From 6d27ec19b216eb5f6cf6db2fc8f7ed30795ede1a Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 12 Oct 2024 17:51:11 +0200 Subject: [PATCH 01/43] orangepi3b: create dtb symlink for mainline migration Linux prior to v6.11 did not contain a native Orange Pi 3B device tree, hence "rk3566-orangepi-3b.dtb" was added via patch. Since there is an incompatibility between board revisions v1.1 and v2.1, mainline Linux however added two device trees for those two revisions. Since mainline U-Boot did already select those new device trees by default, we needed to define the old one via boot environmetn, which does not exist in new kernel. Older U-Boot versions however won't load the new device trees. To not break boot after kernel package upgrade, a symlink is hence added to the package to keep it compatible with old U-Boot and boot environment. A migration to new U-Boot, removing the then obsolete fdtfile declaration from boot env, can be done via distro upgrade scripts or manually, to fully support board revision v2.1. Signed-off-by: MichaIng --- lib/functions/compilation/kernel-debs.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/functions/compilation/kernel-debs.sh b/lib/functions/compilation/kernel-debs.sh index 9d1fe7c13c17..d0b8c21f70b4 100644 --- a/lib/functions/compilation/kernel-debs.sh +++ b/lib/functions/compilation/kernel-debs.sh @@ -334,6 +334,9 @@ function kernel_package_callback_linux_dtb() { mkdir -p "${package_directory}/boot/" run_host_command_logged cp -rp "${tmp_kernel_install_dirs[INSTALL_DTBS_PATH]}" "${package_directory}/boot/dtb-${kernel_version_family}" + # Create symlink for old Orange Pi 3B device tree for transition from custom to mainline dtb: https://dietpi.com/forum/t/20689/22 + [[ -f "${package_directory}/boot/dtb-${kernel_version_family}/rockchip/rk3566-orangepi-3b-v1.1.dtb" && ! -f "${package_directory}/boot/dtb-${kernel_version_family}/rockchip/rk3566-orangepi-3b.dtb" ]] && run_host_command_logged ln -s 'rk3566-orangepi-3b-v1.1.dtb' "${package_directory}/boot/dtb-${kernel_version_family}/rockchip/rk3566-orangepi-3b.dtb" + # Generate a control file cat <<- CONTROL_FILE > "${package_DEBIAN_dir}/control" Version: ${artifact_version} From fc543035c81986053832723a349434e66f3d0d17 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 2 Jun 2024 15:41:46 +0200 Subject: [PATCH 02/43] configs: enable mt7921u USB WiFi drivers for all boards In case of rk35xx-vendor, the mt7921e PCIe WiFi drivers were enabled already, but the one for USB was missing. It was enabled for most other boards already, hence this commit is an alignment. Signed-off-by: MichaIng --- config/kernel/linux-arm64-wdk2023.config | 1 + config/kernel/linux-k3-vendor.config | 1 + config/kernel/linux-odroidxu4-current.config | 1 + config/kernel/linux-phytium-embedded-current.config | 1 + config/kernel/linux-tqma-current.config | 1 + 5 files changed, 5 insertions(+) diff --git a/config/kernel/linux-arm64-wdk2023.config b/config/kernel/linux-arm64-wdk2023.config index f7b25211e1f8..1ba41a2d53c1 100644 --- a/config/kernel/linux-arm64-wdk2023.config +++ b/config/kernel/linux-arm64-wdk2023.config @@ -1183,6 +1183,7 @@ CONFIG_MT76x0U=m CONFIG_MT76x0E=m CONFIG_MT76x2E=m CONFIG_MT76x2U=m +CONFIG_MT7921U=m CONFIG_RT2X00=m CONFIG_RT2400PCI=m CONFIG_RT2500PCI=m diff --git a/config/kernel/linux-k3-vendor.config b/config/kernel/linux-k3-vendor.config index 44fcb84e59a7..7a384daf5496 100644 --- a/config/kernel/linux-k3-vendor.config +++ b/config/kernel/linux-k3-vendor.config @@ -534,6 +534,7 @@ CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m CONFIG_MWIFIEX_PCIE=m CONFIG_MT7921E=m +CONFIG_MT7921U=m CONFIG_RSI_91X=m CONFIG_WL18XX=m CONFIG_CC33XX=m diff --git a/config/kernel/linux-odroidxu4-current.config b/config/kernel/linux-odroidxu4-current.config index cd83306d2406..9f3ce8c95f44 100644 --- a/config/kernel/linux-odroidxu4-current.config +++ b/config/kernel/linux-odroidxu4-current.config @@ -712,6 +712,7 @@ CONFIG_MWIFIEX_USB=m CONFIG_MT7601U=m CONFIG_MT76x0U=m CONFIG_MT76x2U=m +CONFIG_MT7921U=m CONFIG_RT2X00=m CONFIG_RT2500USB=m CONFIG_RT73USB=m diff --git a/config/kernel/linux-phytium-embedded-current.config b/config/kernel/linux-phytium-embedded-current.config index 1ed7337dd0d8..a535b63fc913 100644 --- a/config/kernel/linux-phytium-embedded-current.config +++ b/config/kernel/linux-phytium-embedded-current.config @@ -484,6 +484,7 @@ CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m CONFIG_MWIFIEX_PCIE=m CONFIG_MT7921E=m +CONFIG_MT7921U=m CONFIG_RTW88=m CONFIG_RTW88_8821CS=m CONFIG_RSI_91X=m diff --git a/config/kernel/linux-tqma-current.config b/config/kernel/linux-tqma-current.config index 42bf13e6cde0..c6c1708f0b2d 100644 --- a/config/kernel/linux-tqma-current.config +++ b/config/kernel/linux-tqma-current.config @@ -477,6 +477,7 @@ CONFIG_BRCMFMAC=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m CONFIG_MWIFIEX_PCIE=m +CONFIG_MT7921U=m CONFIG_WL18XX=m CONFIG_WLCORE_SDIO=m CONFIG_INPUT_EVDEV=y From 5e9701466d4dfa1b3c8d018a29c377ccfe51fad6 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 16 Oct 2024 17:50:57 +0200 Subject: [PATCH 03/43] sunxi: revert net: phy: realtek: fix rtl8211e rx/tx delay config to fix onboard Ethernet on NanoPi M1 Plus: https://github.com/MichaIng/DietPi/issues/6974 Signed-off-by: MichaIng --- .../drv-phy-realtek-revert-faulty-patch.patch | 75 +++++++++++++++++++ .../drv-phy-realtek-revert-faulty-patch.patch | 75 +++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 patch/kernel/archive/sunxi-6.12/drv-phy-realtek-revert-faulty-patch.patch create mode 100644 patch/kernel/archive/sunxi-6.6/drv-phy-realtek-revert-faulty-patch.patch diff --git a/patch/kernel/archive/sunxi-6.12/drv-phy-realtek-revert-faulty-patch.patch b/patch/kernel/archive/sunxi-6.12/drv-phy-realtek-revert-faulty-patch.patch new file mode 100644 index 000000000000..414ec51cebfc --- /dev/null +++ b/patch/kernel/archive/sunxi-6.12/drv-phy-realtek-revert-faulty-patch.patch @@ -0,0 +1,75 @@ +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 95dbe5e8e1d8ff..0f09609718007e 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0+ ++/* ++ * drivers/net/phy/realtek.c +-/* drivers/net/phy/realtek.c + * + * Driver for Realtek PHYs + * +@@ -31,9 +32,9 @@ + #define RTL8211F_TX_DELAY BIT(8) + #define RTL8211F_RX_DELAY BIT(3) + ++#define RTL8211E_TX_DELAY BIT(1) ++#define RTL8211E_RX_DELAY BIT(2) ++#define RTL8211E_MODE_MII_GMII BIT(3) +-#define RTL8211E_CTRL_DELAY BIT(13) +-#define RTL8211E_TX_DELAY BIT(12) +-#define RTL8211E_RX_DELAY BIT(11) + + #define RTL8201F_ISR 0x1e + #define RTL8201F_IER 0x13 +@@ -245,16 +246,16 @@ static int rtl8211e_config_init(struct phy_device *phydev) + /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII: ++ val = 0; +- val = RTL8211E_CTRL_DELAY | 0; + break; + case PHY_INTERFACE_MODE_RGMII_ID: ++ val = RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; +- val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; + break; + case PHY_INTERFACE_MODE_RGMII_RXID: ++ val = RTL8211E_RX_DELAY; +- val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: ++ val = RTL8211E_TX_DELAY; +- val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY; + break; + default: /* the rest of the modes imply leaving delays as is. */ + return 0; +@@ -262,12 +263,11 @@ static int rtl8211e_config_init(struct phy_device *phydev) + + /* According to a sample driver there is a 0x1c config register on the + * 0xa4 extension page (0x7) layout. It can be used to disable/enable ++ * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. It can ++ * also be used to customize the whole configuration register: ++ * 8:6 = PHY Address, 5:4 = Auto-Negotiation, 3 = Interface Mode Select, ++ * 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet ++ * for details). +- * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. +- * The configuration register definition: +- * 14 = reserved +- * 13 = Force Tx RX Delay controlled by bit12 bit11, +- * 12 = RX Delay, 11 = TX Delay +- * 10:0 = Test && debug settings reserved by realtek + */ + oldpage = phy_select_page(phydev, 0x7); + if (oldpage < 0) +@@ -277,8 +277,7 @@ static int rtl8211e_config_init(struct phy_device *phydev) + if (ret) + goto err_restore_page; + ++ ret = __phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, +- ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY +- | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, + val); + + err_restore_page: + \ No newline at end of file diff --git a/patch/kernel/archive/sunxi-6.6/drv-phy-realtek-revert-faulty-patch.patch b/patch/kernel/archive/sunxi-6.6/drv-phy-realtek-revert-faulty-patch.patch new file mode 100644 index 000000000000..414ec51cebfc --- /dev/null +++ b/patch/kernel/archive/sunxi-6.6/drv-phy-realtek-revert-faulty-patch.patch @@ -0,0 +1,75 @@ +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 95dbe5e8e1d8ff..0f09609718007e 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0+ ++/* ++ * drivers/net/phy/realtek.c +-/* drivers/net/phy/realtek.c + * + * Driver for Realtek PHYs + * +@@ -31,9 +32,9 @@ + #define RTL8211F_TX_DELAY BIT(8) + #define RTL8211F_RX_DELAY BIT(3) + ++#define RTL8211E_TX_DELAY BIT(1) ++#define RTL8211E_RX_DELAY BIT(2) ++#define RTL8211E_MODE_MII_GMII BIT(3) +-#define RTL8211E_CTRL_DELAY BIT(13) +-#define RTL8211E_TX_DELAY BIT(12) +-#define RTL8211E_RX_DELAY BIT(11) + + #define RTL8201F_ISR 0x1e + #define RTL8201F_IER 0x13 +@@ -245,16 +246,16 @@ static int rtl8211e_config_init(struct phy_device *phydev) + /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII: ++ val = 0; +- val = RTL8211E_CTRL_DELAY | 0; + break; + case PHY_INTERFACE_MODE_RGMII_ID: ++ val = RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; +- val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; + break; + case PHY_INTERFACE_MODE_RGMII_RXID: ++ val = RTL8211E_RX_DELAY; +- val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: ++ val = RTL8211E_TX_DELAY; +- val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY; + break; + default: /* the rest of the modes imply leaving delays as is. */ + return 0; +@@ -262,12 +263,11 @@ static int rtl8211e_config_init(struct phy_device *phydev) + + /* According to a sample driver there is a 0x1c config register on the + * 0xa4 extension page (0x7) layout. It can be used to disable/enable ++ * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. It can ++ * also be used to customize the whole configuration register: ++ * 8:6 = PHY Address, 5:4 = Auto-Negotiation, 3 = Interface Mode Select, ++ * 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet ++ * for details). +- * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. +- * The configuration register definition: +- * 14 = reserved +- * 13 = Force Tx RX Delay controlled by bit12 bit11, +- * 12 = RX Delay, 11 = TX Delay +- * 10:0 = Test && debug settings reserved by realtek + */ + oldpage = phy_select_page(phydev, 0x7); + if (oldpage < 0) +@@ -277,8 +277,7 @@ static int rtl8211e_config_init(struct phy_device *phydev) + if (ret) + goto err_restore_page; + ++ ret = __phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, +- ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY +- | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, + val); + + err_restore_page: + \ No newline at end of file From 1e3ebd3fc6a108f15dd3a0f33e8be587c25ad7ab Mon Sep 17 00:00:00 2001 From: MichaIng Date: Fri, 23 May 2025 18:09:09 +0200 Subject: [PATCH 04/43] uwe5622: replace trace_printk call for all families ********************************************************** ** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE ** ** ** ** trace_printk() being used. Allocating extra memory. ** ** ** ** This means that this is a DEBUG kernel and it is ** ** unsafe for production use. ** ** ** ** If you see this message and you are not debugging ** ** the kernel, report this immediately to your vendor! ** ** ** ** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE ** ********************************************************** Signed-off-by: MichaIng --- ...uwe5622-adjust-for-rockchip-post-6.1.patch | 18 +----------------- .../uwe5622-adjust-for-rockchip-pre-6.1.patch | 19 +------------------ .../wireless-uwe5622/uwe5622-warnings.patch | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 36 deletions(-) diff --git a/patch/misc/wireless-uwe5622/uwe5622-adjust-for-rockchip-post-6.1.patch b/patch/misc/wireless-uwe5622/uwe5622-adjust-for-rockchip-post-6.1.patch index bb0756820349..3a1dd281d349 100644 --- a/patch/misc/wireless-uwe5622/uwe5622-adjust-for-rockchip-post-6.1.patch +++ b/patch/misc/wireless-uwe5622/uwe5622-adjust-for-rockchip-post-6.1.patch @@ -17,7 +17,6 @@ Subject: adjust uwe5622 driver for rockchip drivers/net/wireless/uwe5622/unisocwcn/platform/wcn_misc.c | 13 +- drivers/net/wireless/uwe5622/unisocwcn/platform/wcn_procfs.c | 11 +- drivers/net/wireless/uwe5622/unisocwcn/sdio/sdio_v3.c | 12 +- - drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h | 2 +- drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_main.c | 19 +- drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_rx.c | 2 +- drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_tx.c | 2 +- @@ -44,7 +43,7 @@ Subject: adjust uwe5622 driver for rockchip drivers/net/wireless/uwe5622/unisocwifi/wl_core.c | 108 +- drivers/net/wireless/uwe5622/unisocwifi/wl_intf.c | 112 +- drivers/net/wireless/uwe5622/unisocwifi/wl_intf.h | 2 - - 40 files changed, 3472 insertions(+), 597 deletions(-) + 39 files changed, 3471 insertions(+), 596 deletions(-) diff --git a/drivers/net/wireless/uwe5622/Kconfig b/drivers/net/wireless/uwe5622/Kconfig index a1e123b039bd..fe6c8d115c92 100644 @@ -1805,21 +1804,6 @@ index 98f483353168..eec80dea067b slp_mgr_drv_sleep(subsys, false); slp_mgr_wakeup(subsys); #endif -diff --git a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h b/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h -old mode 100644 -new mode 100755 -index c26bfb3251b4..f87dfafe9c83 ---- a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h -+++ b/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h -@@ -62,7 +62,7 @@ extern long int sdiohal_log_level; - } while (0) - #define sdiohal_pr_perf(fmt, args...) \ - do { if (sdiohal_log_level & SDIOHAL_PERF_LEVEL) \ -- trace_printk(fmt, ## args); \ -+ printk(fmt, ## args); \ - } while (0) - #else - #define sdiohal_normal(fmt, args...) diff --git a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_main.c b/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_main.c old mode 100644 new mode 100755 diff --git a/patch/misc/wireless-uwe5622/uwe5622-adjust-for-rockchip-pre-6.1.patch b/patch/misc/wireless-uwe5622/uwe5622-adjust-for-rockchip-pre-6.1.patch index 751d92d732e6..86b2cf31a74a 100644 --- a/patch/misc/wireless-uwe5622/uwe5622-adjust-for-rockchip-pre-6.1.patch +++ b/patch/misc/wireless-uwe5622/uwe5622-adjust-for-rockchip-pre-6.1.patch @@ -118,7 +118,6 @@ Subject: [PATCH] adjust uwe5622 driver for rockchip .../wireless/uwe5622/unisocwcn/sdio/Kconfig | 0 .../wireless/uwe5622/unisocwcn/sdio/Makefile | 0 .../wireless/uwe5622/unisocwcn/sdio/sdio_v3.c | 16 +- - .../wireless/uwe5622/unisocwcn/sdio/sdiohal.h | 2 +- .../uwe5622/unisocwcn/sdio/sdiohal_common.c | 0 .../uwe5622/unisocwcn/sdio/sdiohal_ctl.c | 0 .../uwe5622/unisocwcn/sdio/sdiohal_main.c | 19 +- @@ -222,7 +221,7 @@ Subject: [PATCH] adjust uwe5622 driver for rockchip .../net/wireless/uwe5622/unisocwifi/wl_intf.h | 2 - .../net/wireless/uwe5622/unisocwifi/work.c | 0 .../net/wireless/uwe5622/unisocwifi/work.h | 0 - 218 files changed, 3730 insertions(+), 849 deletions(-) + 217 files changed, 3729 insertions(+), 848 deletions(-) mode change 100644 => 100755 drivers/net/wireless/uwe5622/tty-sdio/Kconfig mode change 100644 => 100755 drivers/net/wireless/uwe5622/tty-sdio/Makefile create mode 100755 drivers/net/wireless/uwe5622/tty-sdio/Makefile.old @@ -335,7 +334,6 @@ Subject: [PATCH] adjust uwe5622 driver for rockchip mode change 100644 => 100755 drivers/net/wireless/uwe5622/unisocwcn/sdio/Kconfig mode change 100644 => 100755 drivers/net/wireless/uwe5622/unisocwcn/sdio/Makefile mode change 100644 => 100755 drivers/net/wireless/uwe5622/unisocwcn/sdio/sdio_v3.c - mode change 100644 => 100755 drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h mode change 100644 => 100755 drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_common.c mode change 100644 => 100755 drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_ctl.c mode change 100644 => 100755 drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_main.c @@ -2203,21 +2201,6 @@ index 98f48335316..a37fe8c55d6 slp_mgr_drv_sleep(subsys, false); slp_mgr_wakeup(subsys); #endif -diff --git a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h b/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h -old mode 100644 -new mode 100755 -index c26bfb3251b..f87dfafe9c8 ---- a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h -+++ b/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h -@@ -62,7 +62,7 @@ extern long int sdiohal_log_level; - } while (0) - #define sdiohal_pr_perf(fmt, args...) \ - do { if (sdiohal_log_level & SDIOHAL_PERF_LEVEL) \ -- trace_printk(fmt, ## args); \ -+ printk(fmt, ## args); \ - } while (0) - #else - #define sdiohal_normal(fmt, args...) diff --git a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_main.c b/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_main.c old mode 100644 new mode 100755 diff --git a/patch/misc/wireless-uwe5622/uwe5622-warnings.patch b/patch/misc/wireless-uwe5622/uwe5622-warnings.patch index 809b2e743f92..bca75b17135c 100644 --- a/patch/misc/wireless-uwe5622/uwe5622-warnings.patch +++ b/patch/misc/wireless-uwe5622/uwe5622-warnings.patch @@ -8,9 +8,10 @@ Subject: [PATCH] uwe5622: various warning and firmware path fixes .../uwe5622/unisocwcn/platform/rdc_debug.c | 4 +- .../uwe5622/unisocwcn/platform/wcn_boot.c | 2 - .../unisocwcn/platform/wcn_parn_parser.c | 2 +- + .../unisocwcn/sdio/sdiohal.h | 2 +- .../uwe5622/unisocwcn/sdio/sdiohal_ctl.c | 42 ++++++------------- .../wireless/uwe5622/unisocwifi/cfg80211.c | 4 -- - 6 files changed, 17 insertions(+), 39 deletions(-) + 7 files changed, 18 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/uwe5622/Makefile b/drivers/net/wireless/uwe5622/Makefile index 71c863c1017..d2210439f3c 100644 @@ -69,6 +70,19 @@ index 9abcd326972..c1557dcce3f 100755 if (strlen(fstab_name) > 1) fstab_name[strlen(fstab_name)] = '/'; iterate_dir(file1, &ctx); +diff --git a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h b/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h +index c26bfb3251b..f87dfafe9c8 +--- a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h ++++ b/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal.h +@@ -62,7 +62,7 @@ extern long int sdiohal_log_level; + } while (0) + #define sdiohal_pr_perf(fmt, args...) \ + do { if (sdiohal_log_level & SDIOHAL_PERF_LEVEL) \ +- trace_printk(fmt, ## args); \ ++ printk(fmt, ## args); \ + } while (0) + #else + #define sdiohal_normal(fmt, args...) diff --git a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_ctl.c b/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_ctl.c index b426bf89cd9..8000bfea378 100755 --- a/drivers/net/wireless/uwe5622/unisocwcn/sdio/sdiohal_ctl.c From 3efc630f808180eaecb3e51080e58c375aea7997 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 26 May 2025 14:00:40 +0200 Subject: [PATCH 05/43] firmware: add missing package conflicts Signed-off-by: MichaIng --- lib/functions/compilation/packages/firmware-deb.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/functions/compilation/packages/firmware-deb.sh b/lib/functions/compilation/packages/firmware-deb.sh index 9a54fab9cc8e..8dd8886b51bb 100644 --- a/lib/functions/compilation/packages/firmware-deb.sh +++ b/lib/functions/compilation/packages/firmware-deb.sh @@ -65,8 +65,8 @@ function compile_firmware() { Version: ${artifact_version} Architecture: all Maintainer: $MAINTAINER <$MAINTAINERMAIL> - Conflicts: linux-firmware, firmware-brcm80211, firmware-ralink, firmware-samsung, firmware-realtek, armbian-firmware${REPLACE}${extra_conflicts_comma} - Provides: linux-firmware, firmware-brcm80211, firmware-ralink, firmware-samsung, firmware-realtek, armbian-firmware${REPLACE}${extra_conflicts_comma} + Conflicts: linux-firmware, firmware-brcm80211, firmware-ralink, firmware-samsung, firmware-realtek, firmware-atheros, firmware-iwlwifi, firmware-mediatek, armbian-firmware${REPLACE}${extra_conflicts_comma} + Provides: linux-firmware, firmware-brcm80211, firmware-ralink, firmware-samsung, firmware-realtek, firmware-atheros, firmware-iwlwifi, firmware-mediatek, armbian-firmware${REPLACE}${extra_conflicts_comma} Section: kernel Priority: optional Description: Armbian - Linux firmware${FULL} From d80d02e4bb06b20a67cbee8f1eee55fef6296482 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Fri, 6 Jun 2025 15:16:24 +0200 Subject: [PATCH 06/43] packaging: fix linux-update-symlinks call The image path "must be the absolute filename of the kernel image". Else, when using image_dest or link_in_boot in /etc/kernel-img.conf, it links to the non-existing boot/ sub directory. Signed-off-by: MichaIng --- lib/functions/compilation/kernel-debs.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/functions/compilation/kernel-debs.sh b/lib/functions/compilation/kernel-debs.sh index d0b8c21f70b4..74b43ef8dcbd 100644 --- a/lib/functions/compilation/kernel-debs.sh +++ b/lib/functions/compilation/kernel-debs.sh @@ -316,8 +316,8 @@ function kernel_package_callback_linux_image() { # "install" or "upgrade" are decided in a very contrived way by Debian (".fresh-install" file) # do NOT do this if /boot is a vfat, though. if ! is_boot_dev_vfat; then - echo "Armbian: Debian compat: linux-update-symlinks install ${kernel_version_family} ${installed_image_path}" - linux-update-symlinks install "${kernel_version_family}" "${installed_image_path}" || true + echo "Armbian: Debian compat: linux-update-symlinks install ${kernel_version_family} /${installed_image_path}" + linux-update-symlinks install "${kernel_version_family}" "/${installed_image_path}" || true fi HOOK_FOR_DEBIAN_COMPAT_SYMLINK fi From 81a1aa6f6a5278d5c12f45d36690df2c614a3455 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 8 Jun 2025 21:15:33 +0200 Subject: [PATCH 07/43] orangepicm5: add support --- config/boards/orangepicm5.csc | 14 + .../board-orangepicm5-add-overlays.patch | 709 ++++++++++ .../dt/rk3588s-orangepi-cm5-camera1.dtsi | 143 ++ .../dt/rk3588s-orangepi-cm5-camera2.dtsi | 143 ++ .../dt/rk3588s-orangepi-cm5-camera3.dtsi | 152 +++ .../dt/rk3588s-orangepi-cm5-camera4.dtsi | 151 ++ .../rk3588s-orangepi-cm5-tablet-camera1.dtsi | 170 +++ .../rk3588s-orangepi-cm5-tablet-camera2.dtsi | 149 ++ .../rk3588s-orangepi-cm5-tablet-camera3.dtsi | 150 ++ .../dt/rk3588s-orangepi-cm5-tablet-lcd.dtsi | 73 + .../dt/rk3588s-orangepi-cm5-tablet.dts | 1213 +++++++++++++++++ .../dt/rk3588s-orangepi-cm5.dts | 826 +++++++++++ .../defconfig/orangepi-cm5-rk3588s_defconfig | 259 ++++ .../dt/rk3588s-orangepi-cm5.dts | 121 ++ 14 files changed, 4273 insertions(+) create mode 100644 config/boards/orangepicm5.csc create mode 100644 patch/kernel/rk35xx-vendor-6.1/board-orangepicm5-add-overlays.patch create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera1.dtsi create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera2.dtsi create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera3.dtsi create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera4.dtsi create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera1.dtsi create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera2.dtsi create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera3.dtsi create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-lcd.dtsi create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet.dts create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5.dts create mode 100644 patch/u-boot/legacy/u-boot-radxa-rk35xx/defconfig/orangepi-cm5-rk3588s_defconfig create mode 100644 patch/u-boot/legacy/u-boot-radxa-rk35xx/dt/rk3588s-orangepi-cm5.dts diff --git a/config/boards/orangepicm5.csc b/config/boards/orangepicm5.csc new file mode 100644 index 000000000000..9133c58daf53 --- /dev/null +++ b/config/boards/orangepicm5.csc @@ -0,0 +1,14 @@ +# Rockchip RK3588S octa core 2/4/8/16GB RAM SoC 32/64/128/256 onboard eMMC otherwise depending on base board +BOARD_NAME="Orange Pi CM5" +BOARDFAMILY="rockchip-rk3588" +BOARD_MAINTAINER="" +BOOTCONFIG="orangepi-cm5-rk3588s_defconfig" # vendor name, not standard, see hook below, set BOOT_SOC below to compensate +BOOT_SOC="rk3588" +KERNEL_TARGET="vendor" +FULL_DESKTOP="yes" +BOOT_LOGO="desktop" +BOOT_FDT_FILE="rockchip/rk3588s-orangepi-cm5.dtb" +BOOT_SCENARIO="spl-blobs" +BOOT_SUPPORT_SPI="yes" +BOOT_SPI_RKSPI_LOADER="yes" +IMAGE_PARTITION_TABLE="gpt" diff --git a/patch/kernel/rk35xx-vendor-6.1/board-orangepicm5-add-overlays.patch b/patch/kernel/rk35xx-vendor-6.1/board-orangepicm5-add-overlays.patch new file mode 100644 index 000000000000..1c592901481f --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/board-orangepicm5-add-overlays.patch @@ -0,0 +1,709 @@ +From a4a3c28a183bf888de7acc9e14d29d81205c758a Mon Sep 17 00:00:00 2001 +From: MichaIng +Date: Sun, 8 Jun 2025 21:56:04 +0200 +Subject: [PATCH] orangepi-cm5: add overlays + +Signed-off-by: MichaIng +--- + arch/arm64/boot/dts/rockchip/overlay/Makefile | 10 +++ + .../overlay/orangepi-cm5-blink-gpio.dts | 70 ++++++++++++ + .../rockchip/overlay/orangepi-cm5-cam1.dts | 60 ++++++++++ + .../rockchip/overlay/orangepi-cm5-cam2.dts | 60 ++++++++++ + .../rockchip/overlay/orangepi-cm5-cam3.dts | 68 +++++++++++ + .../rockchip/overlay/orangepi-cm5-cam4.dts | 68 +++++++++++ + .../overlay/orangepi-cm5-tablet-cam1.dts | 108 ++++++++++++++++++ + .../overlay/orangepi-cm5-tablet-cam2.dts | 60 ++++++++++ + .../overlay/orangepi-cm5-tablet-cam3.dts | 60 ++++++++++ + .../orangepi-cm5-tablet-disable-leds.dts | 16 +++ + .../overlay/orangepi-cm5-tablet-lcd.dts | 25 ++++ + 11 files changed, 609 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-blink-gpio.dts + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam1.dts + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam2.dts + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam3.dts + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam4.dts + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam1.dts + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam2.dts + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam3.dts + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-disable-leds.dts + create mode 100644 arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-lcd.dts + +diff --git a/arch/arm64/boot/dts/rockchip/overlay/Makefile b/arch/arm64/boot/dts/rockchip/overlay/Makefile +index a7c242cf18355..0b64753d69cb9 100644 +--- a/arch/arm64/boot/dts/rockchip/overlay/Makefile ++++ b/arch/arm64/boot/dts/rockchip/overlay/Makefile +@@ -40,6 +40,16 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ + orangepi-5-ultra-cam1.dtbo \ + orangepi-5-ultra-cam2.dtbo \ + orangepi-5-ultra-disable-leds.dtbo \ ++ orangepi-cm5-blink-gpio.dtbo \ ++ orangepi-cm5-cam1.dtbo \ ++ orangepi-cm5-cam2.dtbo \ ++ orangepi-cm5-cam3.dtbo \ ++ orangepi-cm5-cam4.dtbo \ ++ orangepi-cm5-tablet-cam1.dtbo \ ++ orangepi-cm5-tablet-cam2.dtbo \ ++ orangepi-cm5-tablet-cam3.dtbo \ ++ orangepi-cm5-tablet-lcd.dtbo \ ++ orangepi-cm5-tablet-disable-leds.dtbo \ + rock-3a-sata.dtbo \ + rock-5a-hdmi-8k.dtbo \ + rock-5a-i2c5-rtc-hym8563.dtbo \ +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-blink-gpio.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-blink-gpio.dts +new file mode 100644 +index 0000000000000..551e03bf00505 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-blink-gpio.dts +@@ -0,0 +1,70 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "rockchip,rk3588s-orangepi-cm5", "rockchip,rk3588"; ++ ++ fragment@0 { ++ target = <&leds>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ gpio1_b3@0 { ++ gpios = <&gpio1 11 0>; ++ label = "gpio1_b3"; ++ linux,default-trigger = "heartbeat"; ++ linux,default-trigger-delay-ms = <0>; ++ }; ++ ++ gpio1_b1@1 { ++ gpios = <&gpio1 9 0>; ++ label = "gpio1_b1"; ++ linux,default-trigger = "heartbeat"; ++ linux,default-trigger-delay-ms = <0>; ++ }; ++ ++ gpio1_b4@2 { ++ gpios = <&gpio1 12 0>; ++ label = "gpio1_b4"; ++ linux,default-trigger = "heartbeat"; ++ linux,default-trigger-delay-ms = <0>; ++ }; ++ ++ gpio1_b2@3 { ++ gpios = <&gpio1 10 0>; ++ label = "gpio1_b2"; ++ linux,default-trigger = "heartbeat"; ++ linux,default-trigger-delay-ms = <0>; ++ }; ++ ++ gpio1_b7@4 { ++ gpios = <&gpio1 15 0>; ++ label = "gpio1_b7"; ++ linux,default-trigger = "heartbeat"; ++ linux,default-trigger-delay-ms = <0>; ++ }; ++ ++ gpio1_b6@5 { ++ gpios = <&gpio1 14 0>; ++ label = "gpio1_b6"; ++ linux,default-trigger = "heartbeat"; ++ linux,default-trigger-delay-ms = <0>; ++ }; ++ ++ gpio4_b2@6 { ++ gpios = <&gpio4 10 0>; ++ label = "gpio4_b2"; ++ linux,default-trigger = "heartbeat"; ++ linux,default-trigger-delay-ms = <0>; ++ }; ++ ++ gpio4_b3@7 { ++ gpios = <&gpio4 11 0>; ++ label = "gpio4_b3"; ++ linux,default-trigger = "heartbeat"; ++ linux,default-trigger-delay-ms = <0>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam1.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam1.dts +new file mode 100644 +index 0000000000000..660fd84550558 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam1.dts +@@ -0,0 +1,60 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dphy1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&mipi2_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&rkcif_mipi_lvds2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds2_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkisp0_vir0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&i2c4>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ ov5647-1@36 { ++ status = "okay"; ++ }; ++ ++ imx219-1@10 { ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam2.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam2.dts +new file mode 100644 +index 0000000000000..6e65092cf8209 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam2.dts +@@ -0,0 +1,60 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dphy2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&mipi3_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&rkcif_mipi_lvds3>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds3_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkisp0_vir1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&i2c3>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ ov5647-2@36 { ++ status = "okay"; ++ }; ++ ++ imx219-2@10 { ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam3.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam3.dts +new file mode 100644 +index 0000000000000..04460d9c2eb91 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam3.dts +@@ -0,0 +1,68 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dcphy1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&mipi1_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&rkcif_mipi_lvds1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds1_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkisp1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&rkisp1_vir1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&i2c5>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ ov5647-3@36 { ++ status = "okay"; ++ }; ++ ++ imx219-3@10 { ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam4.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam4.dts +new file mode 100644 +index 0000000000000..d19a6b0ccce87 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-cam4.dts +@@ -0,0 +1,68 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dcphy0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&mipi0_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&rkcif_mipi_lvds>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkisp1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&rkisp1_vir0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&i2c6>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ ov5647-4@36 { ++ status = "okay"; ++ }; ++ ++ imx219-4@10 { ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam1.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam1.dts +new file mode 100644 +index 0000000000000..992669abf772b +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam1.dts +@@ -0,0 +1,108 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dphy0_hw>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&csi2_dphy0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&mipi2_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkcif_mipi_lvds2_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&rkisp0_vir1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&i2c1>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ vm149c-p1@c { ++ status = "okay"; ++ }; ++ ++ ov13850-1@10 { ++ status = "okay"; ++ }; ++ ++ dw9714-p1@c { ++ status = "okay"; ++ }; ++ ++ ov13855-1@36 { ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&rkcif>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&rkcif_mmu>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@9 { ++ target = <&rkisp0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@10 { ++ target = <&isp0_mmu>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam2.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam2.dts +new file mode 100644 +index 0000000000000..34bd3deac9e24 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam2.dts +@@ -0,0 +1,60 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dcphy0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&mipi0_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&rkcif_mipi_lvds>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkisp1_vir0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&i2c6>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ ov5647-cam2@36 { ++ status = "okay"; ++ }; ++ ++ imx219-cam2@10 { ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam3.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam3.dts +new file mode 100644 +index 0000000000000..025c5972dd45d +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-cam3.dts +@@ -0,0 +1,60 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dcphy1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&mipi1_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&rkcif_mipi_lvds1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds1_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkisp1_vir1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&i2c7>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ ov5647-cam3@36 { ++ status = "okay"; ++ }; ++ ++ imx219-cam3@10 { ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-disable-leds.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-disable-leds.dts +new file mode 100644 +index 0000000000000..0b814034f5002 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-disable-leds.dts +@@ -0,0 +1,16 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&leds>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ led@1 { ++ linux,default-trigger = "none"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-lcd.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-lcd.dts +new file mode 100644 +index 0000000000000..d94b827ac9b69 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-cm5-tablet-lcd.dts +@@ -0,0 +1,25 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&dsi1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&dsi1_panel>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&dsi1_in_vp2>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +-- +2.47.2 + diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera1.dtsi b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera1.dtsi new file mode 100644 index 000000000000..b5759d03da0e --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera1.dtsi @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dphy0_hw { + status = "okay"; +}; + +&csi2_dphy1 { + status = "disabled"; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipidphy1_in_ucam0: endpoint@0 { + reg = <0>; + remote-endpoint = <&ov5647_1_out1>; + data-lanes = <1 2>; + }; + + mipidphy1_in_ucam1: endpoint@1 { + reg = <1>; + remote-endpoint = <&imx219_1_out1>; + data-lanes = <1 2>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + csidphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi2_csi2_input>; + }; + }; + }; +}; + +&i2c4 { + status = "okay"; + ddpinctrl-names = "default"; + pinctrl-0 = <&i2c4m3_xfer>; + + ov5647_1: ov5647-1@36 { + status = "disabled"; + compatible = "ovti,ov5647"; + reg = <0x36>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v1"; + rockchip,camera-module-lens-name = "default"; + port { + ov5647_1_out1: endpoint { + remote-endpoint = <&mipidphy1_in_ucam0>; + data-lanes = <1 2>; + }; + }; + }; + + imx219_1: imx219-1@10 { + status = "disabled"; + compatible = "sony,imx219"; + reg = <0x10>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v2"; + rockchip,camera-module-lens-name = "default"; + port { + imx219_1_out1: endpoint { + remote-endpoint = <&mipidphy1_in_ucam1>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&mipi2_csi2 { + status = "disabled"; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + mipi2_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy0_out>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + mipi2_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in2>; + }; + }; + }; +}; + +&rkcif_mipi_lvds2 { + status = "disabled"; + port { + cif_mipi_in2: endpoint { + remote-endpoint = <&mipi2_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds2_sditf { + status = "disabled"; + port { + mipi2_lvds_sditf: endpoint { + remote-endpoint = <&isp0_vir0>; + }; + }; +}; + +&rkisp0_vir0 { + status = "disabled"; + port { + #address-cells = <1>; + #size-cells = <0>; + isp0_vir0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi2_lvds_sditf>; + }; + }; +}; \ No newline at end of file diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera2.dtsi b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera2.dtsi new file mode 100644 index 000000000000..7ea2d9c3e956 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera2.dtsi @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dphy0_hw { + status = "okay"; +}; + +&csi2_dphy2 { + status = "disabled"; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipidphy2_in_ucam0: endpoint@0 { + reg = <0>; + remote-endpoint = <&ov5647_2_out1>; + data-lanes = <1 2>; + }; + + mipidphy2_in_ucam1: endpoint@1 { + reg = <1>; + remote-endpoint = <&imx219_2_out1>; + data-lanes = <1 2>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + csidphy2_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi3_csi2_input>; + }; + }; + }; +}; + +&i2c3 { + status = "okay"; + ddpinctrl-names = "default"; + pinctrl-0 = <&i2c3m2_xfer>; + + ov5647_2: ov5647-2@36 { + status = "disabled"; + compatible = "ovti,ov5647"; + reg = <0x36>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v1"; + rockchip,camera-module-lens-name = "default"; + port { + ov5647_2_out1: endpoint { + remote-endpoint = <&mipidphy2_in_ucam0>; + data-lanes = <1 2>; + }; + }; + }; + + imx219_2: imx219-2@10 { + status = "disabled"; + compatible = "sony,imx219"; + reg = <0x10>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v2"; + rockchip,camera-module-lens-name = "default"; + port { + imx219_2_out1: endpoint { + remote-endpoint = <&mipidphy2_in_ucam1>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&mipi3_csi2 { + status = "disabled"; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + mipi3_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy2_out>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + mipi3_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in3>; + }; + }; + }; +}; + +&rkcif_mipi_lvds3 { + status = "disabled"; + port { + cif_mipi_in3: endpoint { + remote-endpoint = <&mipi3_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds3_sditf { + status = "disabled"; + port { + mipi3_lvds_sditf: endpoint { + remote-endpoint = <&isp0_vir1>; + }; + }; +}; + +&rkisp0_vir1 { + status = "disabled"; + port { + #address-cells = <1>; + #size-cells = <0>; + isp0_vir1: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi3_lvds_sditf>; + }; + }; +}; \ No newline at end of file diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera3.dtsi b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera3.dtsi new file mode 100644 index 000000000000..aaeb94c13868 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera3.dtsi @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dcphy1 { + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipidcphy1_in_ucam0: endpoint@0 { + reg = <0>; + remote-endpoint = <&ov5647_3_out1>; + data-lanes = <1 2>; + }; + + mipidcphy1_in_ucam1: endpoint@1 { + reg = <1>; + remote-endpoint = <&imx219_3_out1>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy1_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi1_csi2_input>; + }; + }; + }; +}; + +&i2c5 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5m2_xfer>; + + ov5647_3: ov5647-3@36 { + status = "disabled"; + compatible = "ovti,ov5647"; + reg = <0x36>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v1"; + rockchip,camera-module-lens-name = "default"; + port { + ov5647_3_out1: endpoint { + remote-endpoint = <&mipidcphy1_in_ucam0>; + data-lanes = <1 2>; + }; + }; + }; + + imx219_3: imx219-3@10 { + status = "disabled"; + compatible = "sony,imx219"; + reg = <0x10>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v2"; + rockchip,camera-module-lens-name = "default"; + port { + imx219_3_out1: endpoint { + remote-endpoint = <&mipidcphy1_in_ucam1>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&mipi1_csi2 { + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy1_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in1>; + }; + }; + }; +}; + +&rkcif_mipi_lvds1 { + status = "disabled"; + + port { + cif_mipi_in1: endpoint { + remote-endpoint = <&mipi1_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds1_sditf { + status = "disabled"; + + port { + mipi1_lvds_sditf: endpoint { + remote-endpoint = <&isp1_in0>; + }; + }; +}; + +&rkisp1_vir1 { + status = "disabled"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp1_in0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi1_lvds_sditf>; + }; + }; +}; \ No newline at end of file diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera4.dtsi b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera4.dtsi new file mode 100644 index 000000000000..4d82148cc2e2 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-camera4.dtsi @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dcphy0 { + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipidcphy0_in_ucam0: endpoint@0 { + reg = <0>; + remote-endpoint = <&ov5647_4_out>; + data-lanes = <1 2>; + }; + + mipidcphy0_in_ucam1: endpoint@1 { + reg = <1>; + remote-endpoint = <&imx219_4_out>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c6 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c6m3_xfer>; + + ov5647_4: ov5647-4@36 { + status = "disabled"; + compatible = "ovti,ov5647"; + reg = <0x36>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PD3 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v1"; + rockchip,camera-module-lens-name = "default"; + port { + ov5647_4_out: endpoint { + remote-endpoint = <&mipidcphy0_in_ucam0>; + data-lanes = <1 2>; + }; + }; + }; + + imx219_4: imx219-4@10 { + status = "disabled"; + compatible = "sony,imx219"; + reg = <0x10>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PD3 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v2"; + rockchip,camera-module-lens-name = "default"; + port { + imx219_4_out: endpoint { + remote-endpoint = <&mipidcphy0_in_ucam1>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&mipi0_csi2 { + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in0>; + }; + }; + }; +}; + +&rkcif_mipi_lvds { + status = "disabled"; + + port { + cif_mipi_in0: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds_sditf { + status = "disabled"; + + port { + mipi_lvds_sditf: endpoint { + remote-endpoint = <&isp1_in1>; + }; + }; +}; + +&rkisp1_vir0 { + status = "disabled"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp1_in1: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds_sditf>; + }; + }; +}; \ No newline at end of file diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera1.dtsi b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera1.dtsi new file mode 100644 index 000000000000..525729bad9dd --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera1.dtsi @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dphy0_hw { + status = "okay"; +}; + +&csi2_dphy0 { + status = "disabled"; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_in_ucam0: endpoint@0 { + reg = <0>; + remote-endpoint = <&ov13850_out2>; + data-lanes = <1 2>; + }; + + mipi_in_ucam1: endpoint@1 { + reg = <1>; + remote-endpoint = <&ov13855_out2>; + data-lanes = <1 2>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + csidphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi2_csi2_input>; + }; + }; + }; +}; + +&i2c1 { + status = "okay"; + ddpinctrl-names = "default"; + pinctrl-0 = <&i2c1m2_xfer>; + + vm149c_p1: vm149c-p1@c { + compatible = "silicon touch,vm149c"; + status = "disabled"; + reg = <0x0c>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + }; + + ov13850_1: ov13850-1@10 { + compatible = "ovti,ov13850"; + status = "disabled"; + reg = <0x10>; + clocks = <&cru CLK_MIPI_CAMARAOUT_M1>; + clock-names = "xvclk"; + pinctrl-names = "default"; + pinctrl-0 = <&mipim1_camera1_clk>; + reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-CT0116"; + rockchip,camera-module-lens-name = "default"; + lens-focus = <&vm149c_p1>; + port { + ov13850_out2: endpoint { + remote-endpoint = <&mipi_in_ucam0>; + data-lanes = <1 2>; + }; + }; + }; + + dw9714_p1: dw9714-p1@c { + compatible = "dongwoon,dw9714"; + status = "disabled"; + reg = <0x0c>; + rockchip,camera-module-index = <0>; + rockchip,vcm-start-current = <10>; + rockchip,vcm-rated-current = <85>; + rockchip,vcm-step-mode = <5>; + rockchip,camera-module-facing = "back"; + }; + + ov13855_1: ov13855-1@36 { + compatible = "ovti,ov13855"; + status = "disabled"; + reg = <0x36>; + clocks = <&cru CLK_MIPI_CAMARAOUT_M1>; + clock-names = "xvclk"; + pinctrl-names = "default"; + pinctrl-0 = <&mipim1_camera1_clk>; + reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-OT2016-FV1"; + rockchip,camera-module-lens-name = "default"; + lens-focus = <&dw9714_p1>; + port { + ov13855_out2: endpoint { + remote-endpoint = <&mipi_in_ucam1>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&mipi2_csi2 { + status = "disabled"; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + mipi2_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy0_out>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + mipi2_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in2>; + }; + }; + }; +}; + +&rkcif_mipi_lvds2 { + status = "disabled"; + port { + cif_mipi_in2: endpoint { + remote-endpoint = <&mipi2_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds2_sditf { + status = "disabled"; + port { + mipi2_lvds_sditf: endpoint { + remote-endpoint = <&isp0_vir1>; + }; + }; +}; + +&rkisp0_vir1 { + status = "disabled"; + port { + #address-cells = <1>; + #size-cells = <0>; + isp0_vir1: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi2_lvds_sditf>; + }; + }; +}; \ No newline at end of file diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera2.dtsi b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera2.dtsi new file mode 100644 index 000000000000..43e3f25be067 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera2.dtsi @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dcphy0 { + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_in_dcphy_0: endpoint@0 { + reg = <0>; + remote-endpoint = <&ov5647_out_1>; + data-lanes = <1 2>; + }; + + mipi_in_dcphy_1: endpoint@1 { + reg = <0>; + remote-endpoint = <&imx219_out_1>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c6 { + status = "okay"; + + ov5647_cam2: ov5647-cam2@36 { + status = "disabled"; + compatible = "ovti,ov5647"; + reg = <0x36>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "front"; + rockchip,camera-module-name = "rpi-camera-v1"; + rockchip,camera-module-lens-name = "default"; + port { + ov5647_out_1: endpoint { + remote-endpoint = <&mipi_in_dcphy_0>; + data-lanes = <1 2>; + }; + }; + }; + + imx219_cam2: imx219-cam2@10 { + status = "disabled"; + compatible = "sony,imx219"; + reg = <0x10>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v2"; + rockchip,camera-module-lens-name = "default"; + port { + imx219_out_1: endpoint { + remote-endpoint = <&mipi_in_dcphy_1>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&mipi0_csi2 { + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in0>; + }; + }; + }; +}; + +&rkcif_mipi_lvds { + status = "disabled"; + + port { + cif_mipi_in0: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds_sditf { + status = "disabled"; + + port { + mipi_lvds_sditf: endpoint { + remote-endpoint = <&isp1_in1>; + }; + }; +}; + +&rkisp1_vir0 { + status = "disabled"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp1_in1: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds_sditf>; + }; + }; +}; \ No newline at end of file diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera3.dtsi b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera3.dtsi new file mode 100644 index 000000000000..9fd0e8555d62 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-camera3.dtsi @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dcphy1 { + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_in_dcphy0_cam3: endpoint@0 { + reg = <0>; + remote-endpoint = <&ov5647_out_cam3>; + data-lanes = <1 2>; + }; + + mipi_in_dcphy1_cam3: endpoint@1 { + reg = <0>; + remote-endpoint = <&imx219_out_cam3>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy1_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi1_csi2_input>; + }; + }; + }; +}; + +&i2c7 { + status = "okay"; + + ov5647_cam3: ov5647-cam3@36 { + status = "disabled"; + compatible = "ovti,ov5647"; + reg = <0x36>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v1"; + rockchip,camera-module-lens-name = "default"; + port { + ov5647_out_cam3: endpoint { + remote-endpoint = <&mipi_in_dcphy0_cam3>; + data-lanes = <1 2>; + }; + }; + }; + + imx219_cam3: imx219-cam3@10 { + status = "disabled"; + compatible = "sony,imx219"; + reg = <0x10>; + clocks = <&ext_cam_ov5647_clk>; + clock-names = "ext_cam_ov5647_clk"; + pwdn-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "rpi-camera-v2"; + rockchip,camera-module-lens-name = "default"; + port { + imx219_out_cam3: endpoint { + remote-endpoint = <&mipi_in_dcphy0_cam3>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&mipi1_csi2 { + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy1_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in1>; + }; + }; + }; +}; + +&rkcif_mipi_lvds1 { + status = "disabled"; + + port { + cif_mipi_in1: endpoint { + remote-endpoint = <&mipi1_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds1_sditf { + status = "disabled"; + + port { + mipi1_lvds_sditf: endpoint { + remote-endpoint = <&isp1_in0>; + }; + }; +}; + +&rkisp1_vir1 { + status = "disabled"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp1_in0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi1_lvds_sditf>; + }; + }; +}; \ No newline at end of file diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-lcd.dtsi b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-lcd.dtsi new file mode 100644 index 000000000000..9b77265a5579 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet-lcd.dtsi @@ -0,0 +1,73 @@ +&pinctrl { + lcd { + lcd_rst_gpio: lcd-rst-gpio { + rockchip,pins = <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + +}; + +&dsi1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&mipi_te1>; + + dsi1_panel: panel@0 { + status = "disabled"; + compatible = "innolux,afj101-ba2131"; + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>; + enable-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_rst_gpio>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + panel_in_dsi1: endpoint { + remote-endpoint = <&dsi1_out_panel>; + }; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + dsi1_out_panel: endpoint { + remote-endpoint = <&panel_in_dsi1>; + }; + }; + }; +}; + +&i2c1 { + status = "okay"; + + gt9xx_0: touchscreen@14 { + compatible = "goodix,gt9271"; + reg = <0x14>; + interrupt-parent = <&gpio0>; + interrupts = ; + irq-gpios = <&gpio0 RK_PC4 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + touchscreen-inverted-x; + //touchscreen-inverted-y; + touchscreen-swapped-x-y; + touchscreen-size-x = <1280>; + touchscreen-size-y = <800>; + status = "okay"; + }; +}; + +&dsi1_in_vp2 { + status = "disabled"; +}; \ No newline at end of file diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet.dts b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet.dts new file mode 100644 index 000000000000..0823b93ea0e7 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5-tablet.dts @@ -0,0 +1,1213 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include +#include +#include +#include +#include +#include +#include +#include "dt-bindings/usb/pd.h" + +#include "rk3588s.dtsi" +#include "rk3588-rk806-single.dtsi" +#include "rk3588-linux.dtsi" + +#include "rk3588s-orangepi-cm5-tablet-lcd.dtsi" +#include "rk3588s-orangepi-cm5-tablet-camera1.dtsi" +#include "rk3588s-orangepi-cm5-tablet-camera2.dtsi" +#include "rk3588s-orangepi-cm5-tablet-camera3.dtsi" + +/ { + model = "RK3588S Orange Pi CM5 Tablet"; + compatible = "rockchip,rk3588s-orangepi-cm5-tablet", "rockchip,rk3588"; + + /delete-node/ chosen; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm14 0 25000 0>; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; + + dp0_sound: dp0-sound { + status = "okay"; + compatible = "rockchip,hdmi"; + rockchip,card-name= "rockchip-dp0"; + rockchip,mclk-fs = <512>; + rockchip,cpu = <&spdif_tx2>; + rockchip,codec = <&dp0 1>; + rockchip,jack-det; + }; + + hdmi0_sound: hdmi0-sound { + status = "okay"; + compatible = "rockchip,hdmi"; + rockchip,mclk-fs = <128>; + rockchip,card-name = "rockchip-hdmi0"; + rockchip,cpu = <&i2s5_8ch>; + rockchip,codec = <&hdmi0>; + rockchip,jack-det; + }; + + test-power { + status = "okay"; + }; + + vcc12v_dcin: vcc12v-dcin { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usbdcin: vcc5v0-usbdcin { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usbdcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb: vcc5v0-usb { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usbdcin>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc_3v3_sd_s0: vcc-3v3-sd-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_sd_s0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + pcie20_avdd0v85: pcie20-avdd0v85 { + compatible = "regulator-fixed"; + regulator-name = "pcie20_avdd0v85"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + vin-supply = <&vdd_0v85_s0>; + }; + + pcie20_avdd1v8: pcie20-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "pcie20_avdd1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&avcc_1v8_s0>; + }; + + vcc5v0_host: vcc5v0-host { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + enable-active-high; + gpio = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + }; + + vbus5v0_typec: vbus5v0-typec { + compatible = "regulator-fixed"; + regulator-name = "vbus5v0_typec"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_usb>; + pinctrl-names = "default"; + pinctrl-0 = <&typec5v_pwren>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&hym8563>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + post-power-on-delay-ms = <200>; + reset-gpios = <&gpio0 RK_PD0 GPIO_ACTIVE_LOW>; + }; + + wireless_bluetooth: wireless-bluetooth { + compatible = "bluetooth-platdata"; + clocks = <&hym8563>; + clock-names = "ext_clock"; + uart_rts_gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart9m2_rtsn>, <&bt_reset_gpio>, <&bt_wake_gpio>, <&bt_irq_gpio>; + pinctrl-1 = <&uart9_gpios>; + BT,reset_gpio = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; + BT,wake_gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; + BT,wake_host_irq = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless_wlan: wireless-wlan { + compatible = "wlan-platdata"; + wifi_chip_type = "ap6256"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_host_wake_irq>; + WIFI,host_wake_irq = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + WIFI,poweren_gpio = <&gpio0 RK_PD0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + es8388_sound: es8388-sound { + status = "okay"; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip,es8388"; + hp-det-gpio = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; + io-channels = <&saradc 3>; + io-channel-names = "adc-detect"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + hp-con-gpio = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>; + rockchip,aux-devs = <&aw87xxx_pa1 &aw87xxx_pa2>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s2_2ch>; + rockchip,codec = <&es8388>; + rockchip,audio-routing = + "Headphone", "LOUT1", + "Headphone", "ROUT1", + "Headphone", "Headphone Power", + "Headphone", "Headphone Power", + "LINPUT1", "Main Mic", + "LINPUT2", "Main Mic", + "RINPUT1", "Headset Mic", + "RINPUT2", "Headset Mic"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + play-pause-key { + label = "playpause"; + linux,code = ; + press-threshold-microvolt = <2000>; + }; + }; + + leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 =<&led_gpio>; + status = "okay"; + + led@1 { + gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; + label = "status_led"; + linux,default-trigger = "heartbeat"; + linux,default-trigger-delay-ms = <0>; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + pwms = <&pwm15 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 40000 2 + 50000 3 + 55000 4 + 60000 5 + 65000 5 + 70000 5 + >; + + status = "okay"; + }; + + ext_cam_ov5647_clk: external-camera-ov5647-clock { + compatible = "fixed-clock"; + clock-frequency = <25000000>; + clock-output-names = "ext_cam_ov5647_clk"; + #clock-cells = <0>; + }; +}; + +&av1d_mmu { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + mem-supply = <&vdd_gpu_mem_s0>; + status = "okay"; +}; + +&iep { + status = "okay"; +}; + +&iep_mmu { + status = "okay"; +}; + +&jpegd { + status = "okay"; +}; + +&jpegd_mmu { + status = "okay"; +}; + +&jpege_ccu { + status = "okay"; +}; +&jpege0 { + status = "okay"; +}; + +&jpege0_mmu { + status = "okay"; +}; + +&jpege1 { + status = "okay"; +}; + +&jpege1_mmu { + status = "okay"; +}; + +&jpege2 { + status = "okay"; +}; + +&jpege2_mmu { + status = "okay"; +}; + +&jpege3 { + status = "okay"; +}; + +&jpege3_mmu { + status = "okay"; +}; + +&mpp_srv { + status = "okay"; +}; + +&rga3_core0 { + status = "okay"; +}; + +&rga3_0_mmu { + status = "okay"; +}; + +&rga3_core1 { + status = "okay"; +}; + +&rga3_1_mmu { + status = "okay"; +}; + +&rga2 { + status = "okay"; +}; + +&rknpu { + rknpu-supply = <&vdd_npu_s0>; + mem-supply = <&vdd_npu_mem_s0>; + status = "okay"; +}; + +&rknpu_mmu { + status = "okay"; +}; + +&rkvdec_ccu { + status = "okay"; +}; + +&rkvdec0 { + status = "okay"; +}; + +&rkvdec0_mmu { + status = "okay"; +}; + +&rkvdec1 { + status = "okay"; +}; + +&rkvdec1_mmu { + status = "okay"; +}; + +&rkvenc_ccu { + status = "okay"; +}; + +&rkvenc0 { + status = "okay"; +}; + +&rkvenc0_mmu { + status = "okay"; +}; + +&rkvenc1 { + status = "okay"; +}; + +&rkvenc1_mmu { + status = "okay"; +}; + +&rockchip_suspend { + status = "okay"; + rockchip,sleep-debug-en = <1>; +}; + +&saradc { + status = "okay"; + vref-supply = <&vcc_1v8_s0>; +}; + +&sdio { + max-frequency = <150000000>; + no-sd; + no-mmc; + bus-width = <4>; + disable-wp; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdiom1_pins>; + sd-uhs-sdr104; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + max-frequency = <200000000>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + status = "okay"; +}; + +&sdmmc { + max-frequency = <150000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s3>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&tsadc { + status = "okay"; +}; + +&vdpu { + status = "okay"; +}; + +&vdpu_mmu { + status = "okay"; +}; + +&vepu { + status = "okay"; +}; + +&vop { + status = "okay"; + disable-win-move; + assigned-clocks = <&cru ACLK_VOP>; + assigned-clock-rates = <800000000>; +}; + +&vop_mmu { + status = "okay"; +}; + +/* vp0 & vp1 splice for 8K output */ +&vp0 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER0 | 1 << ROCKCHIP_VOP2_ESMART0)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&vp1 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER1 | 1 << ROCKCHIP_VOP2_ESMART1)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&vp2 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER2 | 1 << ROCKCHIP_VOP2_ESMART2)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&vp3 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER3 | 1 << ROCKCHIP_VOP2_ESMART3)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&display_subsystem { + clocks = <&hdptxphy_hdmi0>; + clock-names = "hdmi0_phy_pll"; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; + mem-supply = <&vdd_cpu_big0_mem_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; + mem-supply = <&vdd_cpu_big1_mem_s0>; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&spdif_tx2{ + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + + vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: rk8602@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_cpu_big0_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: rk8603@43 { + compatible = "rockchip,rk8603"; + reg = <0x43>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_cpu_big1_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2m0_xfer>; + + vdd_npu_s0: vdd_npu_mem_s0: rk8602@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_npu_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3m1_xfer>; + + es8388: es8388@11 { + status = "okay"; + #sound-dai-cells = <0>; + compatible = "everest,es8388", "everest,es8323"; + reg = <0x11>; + clocks = <&mclkout_i2s2>; + clock-names = "mclk"; + assigned-clocks = <&mclkout_i2s2>; + assigned-clock-rates = <12288000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s2m1_mclk>; + }; +}; + +&i2c6 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c6m3_xfer>; + + sc89890: sc89890@6a { + compatible = "sc,sc89890"; + reg = <0x6a>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&charger_ok>; + + interrupt-parent = <&gpio1>; + interrupts = ; + //otg-mode-en-gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>; + + sc,battery-regulation-voltage = <4350000>; /* 4.4V */ + sc,charge-current = <4000000>; /* 4.0A */ + sc,termination-current = <100000>; /* 100mA */ + sc,precharge-current = <500000>; /* 130mA */ + sc,minimum-sys-voltage = <3400000>; /* 3V */ + sc,thermal-regulation-threshold = <4000000>; + sc,ibatcomp-clamp-microvolt = <100000>; + sc,ibatcomp-micro-ohms = <20>; + }; + + usbc0: fusb302@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio4>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&usbc0_int>; + vbus-supply = <&vbus5v0_typec>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_role_sw: endpoint@0 { + remote-endpoint = <&dwc3_0_role_switch>; + }; + }; + }; + + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + op-sink-microwatt = <1000000>; + sink-pdos = + ; + source-pdos = + ; + + altmodes { + #address-cells = <1>; + #size-cells = <0>; + + altmode@0 { + reg = <0>; + svid = <0xff01>; + vdo = <0xffffffff>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_orien_sw: endpoint { + remote-endpoint = <&usbdp_phy0_orientation_switch>; + }; + }; + + port@1 { + reg = <1>; + dp_altmode_mux: endpoint { + remote-endpoint = <&usbdp_phy0_dp_altmode_mux>; + }; + }; + }; + }; + }; +}; + +&i2c7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7m3_xfer>; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + interrupt-parent = <&gpio0>; + interrupts = ; + status = "okay"; + }; +}; + +&i2s2_2ch { + status = "okay"; + pinctrl-0 = <&i2s2m1_lrck + &i2s2m1_sclk + &i2s2m1_sdi + &i2s2m1_sdo>; +}; + +&i2s5_8ch { + status = "okay"; +}; + +&sata0 { + pinctrl-names = "default"; + pinctrl-0 = <&sata_reset>; + status = "disabled"; +}; + +//phy0 +&pcie2x1l2 { + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pinctrl { + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + typec5v_pwren: typec5v-pwren { + rockchip,pins = <4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + wireless-bluetooth { + uart9_gpios: uart9-gpios { + rockchip,pins = <3 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_reset_gpio: bt-reset-gpio { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_wake_gpio: bt-wake-gpio { + rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_irq_gpio: bt-irq-gpio { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + wireless-wlan { + wifi_host_wake_irq: wifi-host-wake-irq { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + led_gpio: led-gpio { + rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sata { + sata_reset:sata-reset{ + rockchip,pins = <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + charger { + charger_ok: charger_ok { + rockchip,pins = <1 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; + rockchip,typec-vbus-det; +}; + +&u2phy2_host { + status = "okay"; +}; + +&u2phy3_host { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + status = "okay"; + dr_mode = "otg"; + usb-role-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + dwc3_0_role_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_role_sw>; + }; + }; +}; + +&usbhost3_0 { + dr_mode = "host"; + status = "okay"; +}; + +&usbhost_dwc3_0 { + status = "okay"; +}; + +&usbdp_phy0 { + orientation-switch; + svid = <0xff01>; + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + usbdp_phy0_orientation_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_orien_sw>; + }; + + usbdp_phy0_dp_altmode_mux: endpoint@1 { + reg = <1>; + remote-endpoint = <&dp_altmode_mux>; + }; + }; +}; + +&usbdp_phy0_dp { + status = "okay"; +}; + +&usbdp_phy0_u3 { + status = "okay"; +}; + +&dp0 { + status = "okay"; +}; + +&dp0_in_vp1 { + status = "okay"; +}; + +&hdmi0 { + status = "okay"; + enable-gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; + cec-enable = "true"; +}; + +&hdmi0_in_vp0 { + status = "okay"; +}; + +&route_hdmi0{ + status = "okay"; +}; + +&hdptxphy_hdmi0 { + status = "okay"; +}; + +&mipi_dcphy0 { + status = "okay"; +}; + +&mipi_dcphy1 { + status = "okay"; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&rkisp0 { + status = "okay"; +}; + +&isp0_mmu { + status = "okay"; +}; + +&rkisp1 { + status = "okay"; +}; + +&isp1_mmu { + status = "okay"; +}; + +/* watchdog */ +&wdt { + status = "okay"; +}; + +&sfc { + status = "disabled"; +}; + +&pwm0 { + pinctrl-names = "active"; + pinctrl-0 = <&pwm0m1_pins>; + status = "disabled"; +}; + +&pwm1 { + pinctrl-names = "active"; + pinctrl-0 = <&pwm1m2_pins>; + status = "disabled"; +}; + +&pwm13 { + pinctrl-names = "active"; + pinctrl-0 = <&pwm13m2_pins>; + status = "disabled"; +}; + +&pwm14 { + pinctrl-names = "active"; + pinctrl-0 = <&pwm14m0_pins>; + status = "okay"; +}; + +&pwm15 { + pinctrl-names = "active"; + pinctrl-0 = <&pwm15m2_pins>; + status = "okay"; +}; + +&spi0 { + status = "disabled"; + assigned-clocks = <&cru CLK_SPI0>; + assigned-clock-rates = <200000000>; + num-cs = <2>; +}; + +&spi1 { + status = "disabled"; + assigned-clocks = <&cru CLK_SPI1>; + assigned-clock-rates = <200000000>; +}; + +&uart4 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&uart4m2_xfer>; +}; + +&uart9 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart9m2_xfer &uart9m2_ctsn>; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1m2_xfer>; + + aw87xxx_pa1: aw87xxx_pa1@59 { + compatible = "awinic,aw87xxx_pa"; + #sound-dai-cells = <0>; + reg = <0x59>; + dev_index = <0>; + status = "okay"; + }; + + aw87xxx_pa2: aw87xxx_pa2@5a { + compatible = "awinic,aw87xxx_pa"; + #sound-dai-cells = <0>; + reg = <0x5a>; + dev_index = <1>; + status = "okay"; + }; +}; + +&i2c4 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4m3_xfer>; +}; + +&i2c5 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5m3_xfer>; +}; + +&pwm3 { + status = "disabled"; + pinctrl-0 = <&pwm3m3_pins>; +}; + +&uart1 { + status = "disabled"; + pinctrl-0 = <&uart1m1_xfer>; +}; + +&uart6 { + status = "disabled"; + pinctrl-0 = <&uart6m2_xfer>; +}; + +&uart7 { + status = "disabled"; + pinctrl-0 = <&uart7m2_xfer>; +}; + +/* delete gpio0_c2 */ +&pmic_pins { + rockchip,pins = + /* pmic_int_l */ + <0 RK_PA7 0 &pcfg_pull_up>, + /* pmic_sleep1 */ + <0 RK_PA2 1 &pcfg_pull_down>, + /* pmic_sleep2 */ + <0 RK_PA3 1 &pcfg_pull_none>, + /* pmic_sleep3 */ + <0 RK_PC1 1 &pcfg_pull_none>, + /* pmic_sleep5 */ + <0 RK_PC3 1 &pcfg_pull_none>, + /* pmic_sleep6 */ + <0 RK_PD6 1 &pcfg_pull_none>; +}; + +&pwm11 { + compatible = "rockchip,remotectl-pwm"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm11m2_pins>; + remote_pwm_id = <3>; + handle_cpu_id = <1>; + remote_support_psci = <0>; + status = "okay"; + + ir_key1 { + rockchip,usercode = <0xfb04>; + rockchip,key_table = + <0xa3 KEY_ENTER>, + <0xe4 388>, + <0xf5 KEY_BACK>, + <0xbb KEY_UP>, + <0xe2 KEY_DOWN>, + <0xe3 KEY_LEFT>, + <0xb7 KEY_RIGHT>, + <0xe0 KEY_HOME>, + <0xba KEY_VOLUMEUP>, + <0xda KEY_VOLUMEUP>, + <0xe6 KEY_VOLUMEDOWN>, + <0xdb KEY_VOLUMEDOWN>, + <0xbc KEY_SEARCH>, + <0xb2 KEY_POWER>, + <0xe5 KEY_POWER>, + <0xde KEY_POWER>, + <0xdc KEY_MUTE>, + <0xa2 KEY_MENU>, + <0xec KEY_1>, + <0xef KEY_2>, + <0xee KEY_3>, + <0xf0 KEY_4>, + <0xf3 KEY_5>, + <0xf2 KEY_6>, + <0xf4 KEY_7>, + <0xf7 KEY_8>, + <0xf6 KEY_9>, + <0xb8 KEY_0>; + }; +}; \ No newline at end of file diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5.dts b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5.dts new file mode 100644 index 000000000000..6086ab737711 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588s-orangepi-cm5.dts @@ -0,0 +1,826 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include +#include +#include +#include +#include +#include +#include "dt-bindings/usb/pd.h" + +#include "rk3588s.dtsi" +#include "rk3588-rk806-single.dtsi" +#include "rk3588-linux.dtsi" + +#include "rk3588s-orangepi-cm5-camera1.dtsi" +#include "rk3588s-orangepi-cm5-camera2.dtsi" +#include "rk3588s-orangepi-cm5-camera3.dtsi" +#include "rk3588s-orangepi-cm5-camera4.dtsi" + +/ { + model = "RK3588S Orange Pi CM5"; + compatible = "rockchip,rk3588s-orangepi-cm5", "rockchip,rk3588"; + + /delete-node/ chosen; + + hdmi0_sound: hdmi0-sound { + status = "okay"; + compatible = "rockchip,hdmi"; + rockchip,mclk-fs = <128>; + rockchip,card-name = "rockchip-hdmi0"; + rockchip,cpu = <&i2s5_8ch>; + rockchip,codec = <&hdmi0>; + rockchip,jack-det; + }; + + test-power { + status = "disabled"; + }; + + vcc12v_dcin: vcc12v-dcin { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usbdcin: vcc5v0-usbdcin { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usbdcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb: vcc5v0-usb { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usbdcin>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_host: vcc5v0-host { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_usb>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + enable-active-high; + gpios = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>; + startup-delay-us = <50000>; + }; + + leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 =<&leds_gpio>; + status = "okay"; + + lan1@0 { + gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_LOW>; + label = "lan1"; + default-state = "on"; + }; + + lan2@1 { + gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + label = "lan2"; + default-state = "on"; + }; + + wan@3 { + gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_LOW>; + label = "wan"; + default-state = "on"; + }; + + power@4 { + gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; + label = "power"; + default-state = "off"; + }; + }; + + gpio_keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&key1_pin>; + status = "okay"; + + button@1 { + debounce-interval = <50>; + gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_LOW>; + label = "K1"; + linux,code = ; + wakeup-source; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + pwms = <&pwm13 0 20000000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; + + status = "okay"; + }; + + ext_cam_ov5647_clk: external-camera-ov5647-clock { + compatible = "fixed-clock"; + clock-frequency = <25000000>; + clock-output-names = "ext_cam_ov5647_clk"; + #clock-cells = <0>; + }; +}; + +&av1d_mmu { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + mem-supply = <&vdd_gpu_mem_s0>; + status = "okay"; +}; + +&iep { + status = "okay"; +}; + +&iep_mmu { + status = "okay"; +}; + +&jpegd { + status = "okay"; +}; + +&jpegd_mmu { + status = "okay"; +}; + +&jpege_ccu { + status = "okay"; +}; + +&jpege0 { + status = "okay"; +}; + +&jpege0_mmu { + status = "okay"; +}; + +&jpege1 { + status = "okay"; +}; + +&jpege1_mmu { + status = "okay"; +}; + +&jpege2 { + status = "okay"; +}; + +&jpege2_mmu { + status = "okay"; +}; + +&jpege3 { + status = "okay"; +}; + +&jpege3_mmu { + status = "okay"; +}; + +&mpp_srv { + status = "okay"; +}; + +&rga3_core0 { + status = "okay"; +}; + +&rga3_0_mmu { + status = "okay"; +}; + +&rga3_core1 { + status = "okay"; +}; + +&rga3_1_mmu { + status = "okay"; +}; + +&rga2 { + status = "okay"; +}; + +&rknpu { + rknpu-supply = <&vdd_npu_s0>; + mem-supply = <&vdd_npu_mem_s0>; + status = "okay"; +}; + +&rknpu_mmu { + status = "okay"; +}; + +&rkvdec_ccu { + status = "okay"; +}; + +&rkvdec0 { + status = "okay"; +}; + +&rkvdec0_mmu { + status = "okay"; +}; + +&rkvdec1 { + status = "okay"; +}; + +&rkvdec1_mmu { + status = "okay"; +}; + +&rkvenc_ccu { + status = "okay"; +}; + +&rkvenc0 { + status = "okay"; +}; + +&rkvenc0_mmu { + status = "okay"; +}; + +&rkvenc1 { + status = "okay"; +}; + +&rkvenc1_mmu { + status = "okay"; +}; + +&rockchip_suspend { + status = "okay"; + rockchip,sleep-debug-en = <1>; +}; + +&saradc { + status = "okay"; + vref-supply = <&vcc_1v8_s0>; +}; + +&sdhci { + pinctrl-names = "default"; + pinctrl-0 = <&emmc_rstnout &emmc_bus8 &emmc_clk &emmc_cmd &emmc_data_strobe>; + + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + max-frequency = <200000000>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + status = "okay"; +}; + +&sdmmc { + max-frequency = <150000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + sd-uhs-sdr104; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; + + /delete-property/ vmmc-supply; +}; + +&tsadc { + status = "okay"; +}; + +&vdpu { + status = "okay"; +}; + +&vdpu_mmu { + status = "okay"; +}; + +&vepu { + status = "okay"; +}; + +&vop { + status = "okay"; + disable-win-move; + assigned-clocks = <&cru ACLK_VOP>; + assigned-clock-rates = <800000000>; +}; + +&vop_mmu { + status = "okay"; +}; + +/* vp0 & vp1 splice for 8K output */ +&vp0 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER0 | 1 << ROCKCHIP_VOP2_ESMART0)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&vp1 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER1 | 1 << ROCKCHIP_VOP2_ESMART1)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&vp2 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER2 | 1 << ROCKCHIP_VOP2_ESMART2)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&vp3 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER3 | 1 << ROCKCHIP_VOP2_ESMART3)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&display_subsystem { + clocks = <&hdptxphy_hdmi0>; + clock-names = "hdmi0_phy_pll"; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; + mem-supply = <&vdd_cpu_big0_mem_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; + mem-supply = <&vdd_cpu_big1_mem_s0>; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&mipi_dcphy0 { + status = "okay"; +}; + +&mipi_dcphy1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + + vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: rk8602@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_cpu_big0_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: rk8603@43 { + compatible = "rockchip,rk8603"; + reg = <0x43>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_cpu_big1_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2m0_xfer>; + + vdd_npu_s0: vdd_npu_mem_s0: rk8602@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_npu_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1m2_xfer>; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + interrupt-parent = <&gpio0>; + interrupts = ; + status = "okay"; + }; +}; + +&i2s5_8ch { + status = "okay"; +}; + +//phy2 +&pcie2x1l1 { + reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +//phy0 +&pcie2x1l2 { + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pinctrl { + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-key { + key1_pin: key1-pin { + rockchip,pins = <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-func { + leds_gpio: leds-gpio { + rockchip,pins = + <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>, + <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>, + <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy0_otg { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&u2phy2_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usbdp_phy0 { + status = "okay"; + rockchip,dp-lane-mux = <2 3>; +}; + +&usbdp_phy0_dp { + status = "okay"; +}; + +&usbdp_phy0_u3 { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbhost3_0 { + status = "disabled"; +}; + +&usbdrd_dwc3_0 { + status = "okay"; + dr_mode = "otg"; + extcon = <&u2phy0>; +}; + +&hdmi0 { + status = "okay"; + enable-gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; + cec-enable = "true"; +}; + +&hdmi0_in_vp0 { + status = "okay"; +}; + +&hdptxphy_hdmi0 { + status = "okay"; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&rkisp0 { + status = "okay"; +}; + +&isp0_mmu { + status = "okay"; +}; + +&rkisp1 { + status = "okay"; +}; + +&isp1_mmu { + status = "okay"; +}; + +/* watchdog */ +&wdt { + status = "okay"; +}; + +&gmac1 { + /* Use rgmii-rxid mode to disable rx delay inside Soc */ + phy-mode = "rgmii-rxid"; + clock_in_out = "output"; + + snps,reset-gpio = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + + pinctrl-names = "default"; + pinctrl-0 = <&gmac1_miim + &gmac1_tx_bus2 + &gmac1_rx_bus2 + &gmac1_rgmii_clk + &gmac1_rgmii_bus>; + + tx_delay = <0x42>; + /* rx_delay = <0x3f>; */ + + phy-handle = <&rgmii_phy1>; + status = "okay"; +}; + +&mdio1 { + rgmii_phy1: phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + }; +}; + +&pwm7 { + compatible = "rockchip,remotectl-pwm"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm7m0_pins>; + remote_pwm_id = <3>; + handle_cpu_id = <1>; + remote_support_psci = <0>; + status = "okay"; + + ir_key1 { + rockchip,usercode = <0xfb04>; + rockchip,key_table = + <0xa3 KEY_ENTER>, + <0xe4 388>, + <0xf5 KEY_BACK>, + <0xbb KEY_UP>, + <0xe2 KEY_DOWN>, + <0xe3 KEY_LEFT>, + <0xb7 KEY_RIGHT>, + <0xe0 KEY_HOME>, + <0xba KEY_VOLUMEUP>, + <0xda KEY_VOLUMEUP>, + <0xe6 KEY_VOLUMEDOWN>, + <0xdb KEY_VOLUMEDOWN>, + <0xbc KEY_SEARCH>, + <0xb2 KEY_POWER>, + <0xe5 KEY_POWER>, + <0xde KEY_POWER>, + <0xdc KEY_MUTE>, + <0xa2 KEY_MENU>, + <0xec KEY_1>, + <0xef KEY_2>, + <0xee KEY_3>, + <0xf0 KEY_4>, + <0xf3 KEY_5>, + <0xf2 KEY_6>, + <0xf4 KEY_7>, + <0xf7 KEY_8>, + <0xf6 KEY_9>, + <0xb8 KEY_0>; + }; +}; + +&pwm13 { + status = "okay"; + pinctrl-names = "active"; + pinctrl-0 = <&pwm13m1_pins>; +}; + +&pwm14 { + status = "disabled"; + pinctrl-names = "active"; + pinctrl-0 = <&pwm14m1_pins>; +}; + +&pwm15 { + status = "disabled"; + pinctrl-names = "active"; + pinctrl-0 = <&pwm15m1_pins>; +}; + +&i2c7 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7m3_xfer>; +}; + +&uart4 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&uart4m2_xfer>; +}; + + +&uart7 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&uart7m2_xfer>; +}; + +&can1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&can1m1_pins>; + assigned-clocks = <&cru CLK_CAN1>; + assigned-clock-rates = <200000000>; +}; + +&spi0 { + status = "disabled"; + assigned-clocks = <&cru CLK_SPI0>; + assigned-clock-rates = <200000000>; + num-cs = <2>; +}; \ No newline at end of file diff --git a/patch/u-boot/legacy/u-boot-radxa-rk35xx/defconfig/orangepi-cm5-rk3588s_defconfig b/patch/u-boot/legacy/u-boot-radxa-rk35xx/defconfig/orangepi-cm5-rk3588s_defconfig new file mode 100644 index 000000000000..ea69adf0a8ed --- /dev/null +++ b/patch/u-boot/legacy/u-boot-radxa-rk35xx/defconfig/orangepi-cm5-rk3588s_defconfig @@ -0,0 +1,259 @@ +CONFIG_ARM=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x80000 +CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_atf.sh" +CONFIG_ROCKCHIP_RK3588=y +CONFIG_ROCKCHIP_EMMC_IOMUX=y +CONFIG_ROCKCHIP_USB_BOOT=y +CONFIG_ROCKCHIP_FIT_IMAGE=y +CONFIG_ROCKCHIP_HWID_DTB=y +CONFIG_USING_KERNEL_DTB_V2=y +CONFIG_ROCKCHIP_VENDOR_PARTITION=y +CONFIG_ROCKCHIP_FIT_IMAGE_PACK=y +CONFIG_ROCKCHIP_NEW_IDB=y +CONFIG_LOADER_INI="RK3588MINIALL.ini" +CONFIG_TRUST_INI="RK3588TRUST.ini" +CONFIG_PSTORE=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_TARGET_EVB_RK3588=y +CONFIG_SPL_LIBDISK_SUPPORT=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_DEFAULT_DEVICE_TREE="rk3588s-orangepi-cm5" +CONFIG_DEBUG_UART=y +CONFIG_FIT=y +CONFIG_FIT_IMAGE_POST_PROCESS=y +CONFIG_FIT_HW_CRYPTO=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y +CONFIG_SPL_FIT_HW_CRYPTO=y +# CONFIG_SPL_SYS_DCACHE_OFF is not set +CONFIG_BOOTDELAY=0 +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_ANDROID_BOOTLOADER=y +CONFIG_ANDROID_AVB=y +CONFIG_ANDROID_BOOT_IMAGE_HASH=y +CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set +CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=0x1 +CONFIG_SPL_MMC_WRITE=y +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_ATF=y +CONFIG_FASTBOOT_BUF_ADDR=0xc00800 +CONFIG_FASTBOOT_BUF_SIZE=0x07000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_CMD_BOOTZ=y +CONFIG_CMD_DTIMG=y +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_LZMADEC is not set +# CONFIG_CMD_UNZIP is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPT=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_BOOT_ANDROID=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PCI=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_TFTP_BOOTM=y +CONFIG_CMD_TFTP_FLASH=y +# CONFIG_CMD_MISC is not set +CONFIG_CMD_MTD_BLK=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_ISO_PARTITION is not set +CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64 +CONFIG_SPL_OF_CONTROL=y +CONFIG_SPL_DTB_MINIMUM=y +CONFIG_OF_LIVE=y +CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_OF_U_BOOT_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +# CONFIG_NET_TFTP_VARS is not set +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +# CONFIG_SARADC_ROCKCHIP is not set +CONFIG_SARADC_ROCKCHIP_V2=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_CLK_SCMI=y +CONFIG_SPL_CLK_SCMI=y +CONFIG_DM_CRYPTO=y +CONFIG_SPL_DM_CRYPTO=y +CONFIG_ROCKCHIP_CRYPTO_V2=y +CONFIG_SPL_ROCKCHIP_CRYPTO_V2=y +CONFIG_DM_RNG=y +CONFIG_RNG_ROCKCHIP=y +CONFIG_SCMI_FIRMWARE=y +CONFIG_SPL_SCMI_FIRMWARE=y +CONFIG_GPIO_HOG=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_ROCKCHIP_GPIO_V2=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_I2C_MUX=y +CONFIG_DM_KEY=y +CONFIG_RK8XX_PWRKEY=y +CONFIG_ADC_KEY=y +CONFIG_MISC=y +CONFIG_SPL_MISC=y +CONFIG_MISC_DECOMPRESS=y +CONFIG_SPL_MISC_DECOMPRESS=y +CONFIG_ROCKCHIP_OTP=y +CONFIG_ROCKCHIP_HW_DECOMPRESS=y +CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS=y +CONFIG_SPL_ROCKCHIP_SECURE_OTP=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_SDMA=y +CONFIG_MMC_SDHCI_ROCKCHIP=y +CONFIG_MTD=y +CONFIG_MTD_BLK=y +CONFIG_MTD_DEVICE=y +CONFIG_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_SPEED=80000000 +CONFIG_SPI_FLASH_EON=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_XMC=y +CONFIG_SPI_FLASH_XTX=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_DM_ETH=y +CONFIG_DM_ETH_PHY=y +CONFIG_DWC_ETH_QOS=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_NVME=y +CONFIG_PCI=y +CONFIG_DM_PCI=y +CONFIG_DM_PCI_COMPAT=y +CONFIG_PCIE_DW_ROCKCHIP=y +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y +CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX=y +CONFIG_PHY_ROCKCHIP_USBDP=y +CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_DM_FUEL_GAUGE=y +CONFIG_POWER_FG_CW201X=y +CONFIG_POWER_FG_CW221X=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_SPI_RK8XX=y +CONFIG_DM_POWER_DELIVERY=y +CONFIG_TYPEC_TCPM=y +CONFIG_TYPEC_TCPCI=y +CONFIG_TYPEC_HUSB311=y +CONFIG_TYPEC_FUSB302=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_REGULATOR_RK860X=y +CONFIG_REGULATOR_RK806=y +CONFIG_CHARGER_BQ25700=y +CONFIG_CHARGER_BQ25890=y +CONFIG_CHARGER_SC8551=y +CONFIG_CHARGER_SGM41542=y +CONFIG_DM_CHARGE_DISPLAY=y +CONFIG_CHARGE_ANIMATION=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_TPL_RAM=y +CONFIG_ROCKCHIP_SDRAM_COMMON=y +CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE=0 +CONFIG_DM_RESET=y +CONFIG_SPL_DM_RESET=y +CONFIG_SPL_RESET_ROCKCHIP=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_BASE=0xFEB50000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_ROCKCHIP_SPI=y +CONFIG_ROCKCHIP_SFC=y +CONFIG_SYSRESET=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DWC3=y +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_DWC3_GENERIC=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Rockchip" +CONFIG_USB_GADGET_VENDOR_NUM=0x2207 +CONFIG_USB_GADGET_PRODUCT_NUM=0x350a +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_DM_VIDEO=y +CONFIG_DISPLAY=y +CONFIG_DRM_ROCKCHIP=y +CONFIG_DRM_MAXIM_MAX96745=y +CONFIG_DRM_MAXIM_MAX96752F=y +CONFIG_DRM_MAXIM_MAX96755F=y +CONFIG_DRM_PANEL_MAXIM_DESERIALIZER=y +CONFIG_DRM_ROHM_BU18XL82=y +CONFIG_DRM_ROCKCHIP_DW_HDMI_QP=y +CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI2=y +CONFIG_DRM_ROCKCHIP_ANALOGIX_DP=y +CONFIG_DRM_ROCKCHIP_DW_DP=y +CONFIG_DRM_ROCKCHIP_SAMSUNG_MIPI_DCPHY=y +CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX_HDMI=y +CONFIG_USE_TINY_PRINTF=y +CONFIG_LIB_RAND=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_RSA=y +CONFIG_SPL_RSA=y +CONFIG_RSA_N_SIZE=0x200 +CONFIG_RSA_E_SIZE=0x10 +CONFIG_RSA_C_SIZE=0x20 +CONFIG_XBC=y +CONFIG_LZ4=y +CONFIG_LZMA=y +CONFIG_ERRNO_STR=y +# CONFIG_EFI_LOADER is not set +CONFIG_AVB_LIBAVB=y +CONFIG_AVB_LIBAVB_AB=y +CONFIG_AVB_LIBAVB_ATX=y +CONFIG_AVB_LIBAVB_USER=y +CONFIG_RK_AVB_LIBAVB_USER=y +## OPTEE fails with version mismatch +# CONFIG_OPTEE_CLIENT=y +# CONFIG_OPTEE_V2=y +# CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION=y +CONFIG_CMD_SETEXPR=y +CONFIG_AHCI=y +CONFIG_CMD_SCSI=y +CONFIG_DM_SCSI=y +CONFIG_DWC_AHCI=y +CONFIG_LIBATA=y +CONFIG_SCSI_AHCI=y +CONFIG_SCSI=y +CONFIG_MTD_BLK_U_BOOT_OFFS=0x400 diff --git a/patch/u-boot/legacy/u-boot-radxa-rk35xx/dt/rk3588s-orangepi-cm5.dts b/patch/u-boot/legacy/u-boot-radxa-rk35xx/dt/rk3588s-orangepi-cm5.dts new file mode 100644 index 000000000000..e9d02ea8340c --- /dev/null +++ b/patch/u-boot/legacy/u-boot-radxa-rk35xx/dt/rk3588s-orangepi-cm5.dts @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd + * + */ + +/dts-v1/; +#include "rk3588.dtsi" +#include "rk3588-u-boot.dtsi" +#include + +/ { + model = "RK3588S Orange Pi CM5"; + compatible = "rockchip,rk3588s-orangepi-cm5", "rockchip,rk3588"; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 1>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + u-boot,dm-pre-reloc; + status = "okay"; + + volumeup-key { + u-boot,dm-pre-reloc; + linux,code = ; + label = "volume up"; + press-threshold-microvolt = <1750>; + }; + }; + + vcc5v0_sys: vcc5v0-sys { + u-boot,dm-pre-reloc; + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; +}; + +&usb2phy2_grf { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usb2phy3_grf { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&u2phy0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&u2phy0_otg { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&u2phy2 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&u2phy2_host { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&u2phy3 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&u2phy3_host { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usb_host0_ehci { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usb_host0_ohci { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usb_host1_ehci { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usb_host1_ohci { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usbdrd3_0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usbdrd_dwc3_0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usbhost3_0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usbhost_dwc3_0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; From f0ab041fce5b23bad67057715149235d6a6ee368 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 18 Jun 2025 20:54:09 +0200 Subject: [PATCH 08/43] rock64: add SPI bootloader Signed-off-by: MichaIng --- config/boards/rock64.csc | 1 + 1 file changed, 1 insertion(+) diff --git a/config/boards/rock64.csc b/config/boards/rock64.csc index 101618f5ede3..226294bf0be9 100644 --- a/config/boards/rock64.csc +++ b/config/boards/rock64.csc @@ -9,3 +9,4 @@ KERNEL_TARGET="current,edge" KERNEL_TEST_TARGET="current" FULL_DESKTOP="yes" BOOT_SCENARIO="blobless" +BOOT_SUPPORT_SPI=yes From f135327da5652e6182530785e97530878dbbe3ac Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 1 Jun 2025 20:53:26 +0200 Subject: [PATCH 09/43] orangepi-5-ultra: add support for vendor kernel --- .../board-orangepi5-ultra-add-overlays.patch | 407 +++++ .../dt/rk3588-orangepi-5-ultra.dts | 1430 +++++++++++++++++ 2 files changed, 1837 insertions(+) create mode 100644 patch/kernel/rk35xx-vendor-6.1/board-orangepi5-ultra-add-overlays.patch create mode 100644 patch/kernel/rk35xx-vendor-6.1/dt/rk3588-orangepi-5-ultra.dts diff --git a/patch/kernel/rk35xx-vendor-6.1/board-orangepi5-ultra-add-overlays.patch b/patch/kernel/rk35xx-vendor-6.1/board-orangepi5-ultra-add-overlays.patch new file mode 100644 index 000000000000..1b26b0c5c4c1 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/board-orangepi5-ultra-add-overlays.patch @@ -0,0 +1,407 @@ +diff --git a/arch/arm64/boot/dts/rockchip/overlay/Makefile b/arch/arm64/boot/dts/rockchip/overlay/Makefile +index a7c242cf18355..5a74035797e94 100644 +--- a/arch/arm64/boot/dts/rockchip/overlay/Makefile ++++ b/arch/arm64/boot/dts/rockchip/overlay/Makefile +@@ -35,6 +35,11 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ + orangepi-5-pro-cam1.dtbo \ + orangepi-5-pro-cam2.dtbo \ + orangepi-5-pro-disable-leds.dtbo \ ++ orangepi-5-ultra-lcd.dtbo \ ++ orangepi-5-ultra-cam0.dtbo \ ++ orangepi-5-ultra-cam1.dtbo \ ++ orangepi-5-ultra-cam2.dtbo \ ++ orangepi-5-ultra-disable-leds.dtbo \ + rock-3a-sata.dtbo \ + rock-5a-hdmi-8k.dtbo \ + rock-5a-i2c5-rtc-hym8563.dtbo \ +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-lcd.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-lcd.dts +new file mode 100644 +index 0000000000000..074a7355dcb4d +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-lcd.dts +@@ -0,0 +1,25 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&dsi1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&dsi1_panel>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&dsi1_in_vp3>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-cam0.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-cam0.dts +new file mode 100644 +index 0000000000000..3fa67481d5e3b +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-cam0.dts +@@ -0,0 +1,108 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dphy0_hw>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&csi2_dphy0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&mipi2_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkcif_mipi_lvds2_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&rkisp0_vir2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&i2c6>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ vm149c-p0@c { ++ status = "okay"; ++ }; ++ ++ ov13850-0@10 { ++ status = "okay"; ++ }; ++ ++ dw9714-p0@c { ++ status = "okay"; ++ }; ++ ++ ov13855-0@36 { ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&rkcif>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&rkcif_mmu>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@9 { ++ target = <&rkisp0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@10 { ++ target = <&isp0_mmu>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-cam1.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-cam1.dts +new file mode 100644 +index 0000000000000..866eeb3a8f06a +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-cam1.dts +@@ -0,0 +1,108 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dphy1_hw>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&csi2_dphy3>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&mipi4_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds4>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkcif_mipi_lvds4_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&rkisp1_vir1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&i2c3>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ vm149c-p1@c { ++ status = "okay"; ++ }; ++ ++ ov13850-1@10 { ++ status = "okay"; ++ }; ++ ++ dw9714-p1@c { ++ status = "okay"; ++ }; ++ ++ ov13855-1@36 { ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&rkcif>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&rkcif_mmu>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@9 { ++ target = <&rkisp1>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@10 { ++ target = <&isp1_mmu>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-cam2.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-cam2.dts +new file mode 100644 +index 0000000000000..af4debc27621a +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-cam2.dts +@@ -0,0 +1,100 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&csi2_dcphy0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&mipi0_csi2>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&rkcif_mipi_lvds>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&rkcif_mipi_lvds_sditf>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&rkisp0_vir0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&i2c7>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ vm149c-p2@c { ++ status = "okay"; ++ }; ++ ++ ov13850-2@10 { ++ status = "okay"; ++ }; ++ ++ dw9714-p2@c { ++ status = "okay"; ++ }; ++ ++ ov13855-2@36 { ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&rkcif>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&rkcif_mmu>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@9 { ++ target = <&rkisp0>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@10 { ++ target = <&isp0_mmu>; ++ ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-disable-leds.dts b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-disable-leds.dts +new file mode 100644 +index 0000000000000..c8501f3a2c2f8 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/overlay/orangepi-5-ultra-disable-leds.dts +@@ -0,0 +1,20 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ fragment@0 { ++ target = <&leds>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ blue_led@1 { ++ linux,default-trigger = "none"; ++ }; ++ ++ green_led@2 { ++ linux,default-trigger = "none"; ++ }; ++ }; ++ }; ++}; diff --git a/patch/kernel/rk35xx-vendor-6.1/dt/rk3588-orangepi-5-ultra.dts b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588-orangepi-5-ultra.dts new file mode 100644 index 000000000000..d93ab50f3846 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/dt/rk3588-orangepi-5-ultra.dts @@ -0,0 +1,1430 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include +#include +#include +#include +#include +#include +#include +#include "dt-bindings/usb/pd.h" + +#include "rk3588.dtsi" +#include "rk3588-rk806-single.dtsi" +#include "rk3588-linux.dtsi" +#include "rk3588-orangepi-5-max-camera0.dtsi" +#include "rk3588-orangepi-5-max-camera1.dtsi" +#include "rk3588-orangepi-5-max-camera2.dtsi" + +/ { + model = "RK3588 OPi 5 Ultra"; + compatible = "rockchip,rk3588-orangepi-5-ultra", "rockchip,rk3588"; + + /delete-node/ chosen; + + /* If hdmirx node is disabled, delete the reserved-memory node here. */ + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* Reserve 256MB memory for hdmirx-controller@fdee0000 */ + cma { + compatible = "shared-dma-pool"; + reusable; + reg = <0x0 (256 * 0x100000) 0x0 (256 * 0x100000)>; + linux,cma-default; + }; + }; + + adc_keys: adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 1>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + vol-up-key { + label = "volume up"; + linux,code = ; + press-threshold-microvolt = <17000>; + }; + + vol-down-key { + label = "volume down"; + linux,code = ; + press-threshold-microvolt = <417000>; + }; + + menu-key { + label = "menu"; + linux,code = ; + press-threshold-microvolt = <890000>; + }; + + back-key { + label = "back"; + linux,code = ; + press-threshold-microvolt = <1235000>; + }; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm15 0 25000 0>; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; + + hdmi0_sound: hdmi0-sound { + status = "disabled"; + compatible = "rockchip,hdmi"; + rockchip,mclk-fs = <128>; + rockchip,card-name = "rockchip-hdmi0"; + rockchip,cpu = <&i2s5_8ch>; + rockchip,codec = <&hdmi0>; + rockchip,jack-det; + }; + + hdmi1_sound: hdmi1-sound { + status = "okay"; + compatible = "rockchip,hdmi"; + rockchip,mclk-fs = <128>; + rockchip,card-name = "rockchip-hdmi1"; + rockchip,cpu = <&i2s6_8ch>; + rockchip,codec = <&hdmi1>; + rockchip,jack-det; + }; + + spdif_tx1_dc: spdif-tx1-dc { + status = "disabled"; + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + + spdif_tx1_sound: spdif-tx1-sound { + status = "disabled"; + compatible = "simple-audio-card"; + simple-audio-card,name = "rockchip,spdif-tx1"; + simple-audio-card,cpu { + sound-dai = <&spdif_tx1>; + }; + simple-audio-card,codec { + sound-dai = <&spdif_tx1_dc>; + }; + }; + + test-power { + status = "disabled"; + }; + + vcc12v_dcin: vcc12v-dcin { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usbdcin: vcc5v0-usbdcin { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usbdcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb: vcc5v0-usb { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usbdcin>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc_3v3_sd_s0: vcc-3v3-sd-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_sd_s0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + es8388_sound: es8388-sound { + status = "okay"; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip,es8388"; + hp-det-gpio = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; + io-channels = <&saradc 3>; + io-channel-names = "adc-detect"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + hp-con-gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s0_8ch>; + rockchip,codec = <&es8388>; + rockchip,audio-routing = + "Headphone", "LOUT1", + "Headphone", "ROUT1", + "Speaker", "LOUT2", + "Speaker", "ROUT2", + "Headphone", "Headphone Power", + "Headphone", "Headphone Power", + "Speaker", "Speaker Power", + "Speaker", "Speaker Power", + "LINPUT1", "Main Mic", + "LINPUT2", "Main Mic", + "RINPUT1", "Headset Mic", + "RINPUT2", "Headset Mic"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + play-pause-key { + label = "playpause"; + linux,code = ; + press-threshold-microvolt = <2000>; + }; + }; + + pcie20_avdd0v85: pcie20-avdd0v85 { + compatible = "regulator-fixed"; + regulator-name = "pcie20_avdd0v85"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + vin-supply = <&vdd_0v85_s0>; + }; + + pcie20_avdd1v8: pcie20-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "pcie20_avdd1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&avcc_1v8_s0>; + }; + + pcie30_avdd0v75: pcie30-avdd0v75 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd0v75"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + vin-supply = <&avdd_0v75_s0>; + }; + + pcie30_avdd1v8: pcie30-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&avcc_1v8_s0>; + }; + + vcc3v3_pcie30: vcc3v3-pcie30 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie30"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpios = <&gpio2 RK_PB6 GPIO_ACTIVE_HIGH>; + startup-delay-us = <5000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_host: vcc5v0-host { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_usb>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + }; + + vcc5v0_otg: vcc5v0-otg { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_otg"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio4 RK_PB1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_otg_en>; + vin-supply = <&vcc5v0_usb>; + }; + + vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie2x1l0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + //gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; + startup-delay-us = <50000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc3v3_pcie_eth: vcc3v3-pcie-eth { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie_eth"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + enable-active-low; + gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>; + startup-delay-us = <50000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc_mipicsi0: vcc-mipicsi0-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_mipicsi0"; + enable-active-high; + }; + + vcc_mipicsi1: vcc-mipicsi1-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_mipicsi1"; + enable-active-high; + }; + + vcc_mipidcphy0: vcc-mipidcphy0-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_mipicsi1"; + enable-active-high; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&hym8563>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + post-power-on-delay-ms = <200>; + reset-gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_LOW>; + }; + + wireless_bluetooth: wireless-bluetooth { + compatible = "bluetooth-platdata"; + clocks = <&hym8563>; + clock-names = "ext_clock"; + uart_rts_gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart7m0_rtsn>, <&bt_reset_gpio>, <&bt_wake_gpio>, <&bt_irq_gpio>; + pinctrl-1 = <&uart7_gpios>; + BT,reset_gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>; + BT,wake_gpio = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>; + BT,wake_host_irq = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless_wlan: wireless-wlan { + compatible = "wlan-platdata"; + wifi_chip_type = "ap6611"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_host_wake_irq>; + WIFI,host_wake_irq = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; + WIFI,poweren_gpio = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 =<&leds_rgb>; + status = "okay"; + + blue_led@1 { + gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_LOW>; + label = "blue_led"; + linux,default-trigger = "heartbeat"; + linux,default-trigger-delay-ms = <0>; + }; + + green_led@2 { + gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_LOW>; + label = "green_led"; + linux,default-trigger = "heartbeat"; + linux,default-trigger-delay-ms = <0>; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + pwms = <&pwm9 0 20000000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; + + status = "okay"; + }; + + hdmiin-sound { + compatible = "rockchip,hdmi"; + rockchip,mclk-fs = <128>; + rockchip,format = "i2s"; + rockchip,bitclock-master = <&hdmirx_ctrler>; + rockchip,frame-master = <&hdmirx_ctrler>; + rockchip,card-name = "rockchip,hdmiin"; + rockchip,cpu = <&i2s7_8ch>; + rockchip,codec = <&hdmirx_ctrler 0>; + rockchip,jack-det; + + status = "okay"; + }; +}; + +&av1d { + status = "okay"; +}; + +&av1d_mmu { + status = "okay"; +}; + +&avsd { + status = "okay"; +}; + +&dsi0 { + status = "disabled"; + //rockchip,lane-rate = <1000>; + dsi0_panel: panel@0 { + status = "disabled"; + compatible = "innolux,afj101-ba2131"; + reg = <0>; + backlight = <&backlight>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + panel_in_dsi: endpoint { + remote-endpoint = <&dsi_out_panel>; + }; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + dsi_out_panel: endpoint { + remote-endpoint = <&panel_in_dsi>; + }; + }; + }; +}; + +&dsi1 { + status = "disabled"; + //rockchip,lane-rate = <1000>; + dsi1_panel: panel@0 { + status = "disabled"; + compatible = "innolux,afj101-ba2131"; + reg = <0>; + backlight = <&backlight>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + panel_in_dsi1: endpoint { + remote-endpoint = <&dsi1_out_panel>; + }; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + dsi1_out_panel: endpoint { + remote-endpoint = <&panel_in_dsi1>; + }; + }; + }; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + mem-supply = <&vdd_gpu_mem_s0>; + status = "okay"; +}; + +&i2s0_8ch { + status = "okay"; + pinctrl-0 = <&i2s0_lrck + &i2s0_sclk + &i2s0_sdi0 + &i2s0_sdo0>; +}; + +&iep { + status = "okay"; +}; + +&iep_mmu { + status = "okay"; +}; + +&jpegd { + status = "okay"; +}; + +&jpegd_mmu { + status = "okay"; +}; + +&jpege_ccu { + status = "okay"; +}; +&jpege0 { + status = "okay"; +}; + +&jpege0_mmu { + status = "okay"; +}; + +&jpege1 { + status = "okay"; +}; + +&jpege1_mmu { + status = "okay"; +}; + +&jpege2 { + status = "okay"; +}; + +&jpege2_mmu { + status = "okay"; +}; + +&jpege3 { + status = "okay"; +}; + +&jpege3_mmu { + status = "okay"; +}; + +&mpp_srv { + status = "okay"; +}; + +&rga3_core0 { + status = "okay"; +}; + +&rga3_0_mmu { + status = "okay"; +}; + +&rga3_core1 { + status = "okay"; +}; + +&rga3_1_mmu { + status = "okay"; +}; + +&rga2 { + status = "okay"; +}; + +&rknpu { + rknpu-supply = <&vdd_npu_s0>; + mem-supply = <&vdd_npu_mem_s0>; + status = "okay"; +}; + +&rknpu_mmu { + status = "okay"; +}; + +&rkvdec_ccu { + status = "okay"; +}; + +&rkvdec0 { + status = "okay"; +}; + +&rkvdec0_mmu { + status = "okay"; +}; + +&rkvdec1 { + status = "okay"; +}; + +&rkvdec1_mmu { + status = "okay"; +}; + +&rkvenc_ccu { + status = "okay"; +}; + +&rkvenc0 { + status = "okay"; +}; + +&rkvenc0_mmu { + status = "okay"; +}; + +&rkvenc1 { + status = "okay"; +}; + +&rkvenc1_mmu { + status = "okay"; +}; + +&rockchip_suspend { + status = "okay"; + rockchip,sleep-debug-en = <1>; +}; + +&saradc { + status = "okay"; + vref-supply = <&vcc_1v8_s0>; +}; + +&sdio { + max-frequency = <150000000>; + no-sd; + no-mmc; + bus-width = <4>; + disable-wp; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdiom0_pins>; + sd-uhs-sdr104; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + max-frequency = <200000000>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + status = "okay"; +}; + +&sdmmc { + max-frequency = <150000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s3>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy0_otg { + vbus-supply = <&vcc5v0_otg>; + status = "okay"; +}; + +&u2phy1_otg { + status = "okay"; +}; + +&u2phy2_host { + status = "okay"; +}; + +&u2phy3_host { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + dr_mode = "host"; + status = "okay"; +}; + +&usbhost3_0 { + status = "okay"; +}; + +&usbhost_dwc3_0 { + status = "okay"; +}; + +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_1 { + status = "okay"; +}; + +&vdpu { + status = "okay"; +}; + +&vdpu_mmu { + status = "okay"; +}; + +&vepu { + status = "okay"; +}; + +&vop { + status = "okay"; + disable-win-move; + assigned-clocks = <&cru ACLK_VOP>; + assigned-clock-rates = <800000000>; +}; + +&vop_mmu { + status = "okay"; +}; + +/* vp0 & vp1 splice for 8K output */ +&vp0 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER0 | 1 << ROCKCHIP_VOP2_ESMART0)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&vp1 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER1 | 1 << ROCKCHIP_VOP2_ESMART1)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&vp2 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER2 | 1 << ROCKCHIP_VOP2_ESMART2)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&vp3 { + cursor-win-id=; + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER3 | 1 << ROCKCHIP_VOP2_ESMART3)>; + rockchip,primary-plane = ; + rockchip,primary-plane = ; +}; + +&display_subsystem { + clocks = <&hdptxphy_hdmi1>; + clock-names = "hdmi1_phy_pll"; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; + mem-supply = <&vdd_cpu_big0_mem_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; + mem-supply = <&vdd_cpu_big1_mem_s0>; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&spdif_tx2{ + status = "disabled"; +}; + +&dsi0 { + status = "disabled"; +}; + +&dsi0_panel { + status = "disabled"; +}; + +/* + * mipi_dcphy1 needs to be enabled + * when dsi1 is enabled + */ +&dsi1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&mipi_te1>; +}; + +&dsi1_panel { + status = "disabled"; +}; + +&gmac0 { + status = "disabled"; +}; + +&hdmi0 { + status = "disabled"; +}; + +&hdmi0_in_vp0 { + status = "disabled"; +}; + +&hdmi0_in_vp1 { + status = "disabled"; +}; + +&hdmi0_in_vp2 { + status = "disabled"; +}; + +&hdmi0_sound { + status = "disabled"; +}; + +&hdmi1 { + status = "okay"; + enable-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&hdmim0_tx1_cec &hdmim0_tx1_hpd &hdmim1_tx1_scl &hdmim1_tx1_sda>; + cec-enable = "true"; +}; + +&hdmi1_in_vp0 { + status = "okay"; +}; + +&hdmi1_in_vp1 { + status = "disabled"; +}; + +&hdmi1_in_vp2 { + status = "disabled"; +}; + +&hdmi1_sound { + status = "okay"; +}; + +&hdptxphy_hdmi0 { + status = "disabled"; +}; + +&hdptxphy_hdmi1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + + vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: rk8602@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_cpu_big0_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: rk8603@43 { + compatible = "rockchip,rk8603"; + reg = <0x43>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_cpu_big1_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1m2_xfer>; + + vdd_npu_s0: vdd_npu_mem_s0: rk8602@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_npu_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c7 { + status = "okay"; + + es8388: es8388@11 { + status = "okay"; + #sound-dai-cells = <0>; + compatible = "everest,es8388", "everest,es8323"; + reg = <0x11>; + clocks = <&mclkout_i2s0>; + clock-names = "mclk"; + assigned-clocks = <&mclkout_i2s0>; + assigned-clock-rates = <12288000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_mclk>; + }; +}; + +&i2c6 { + status = "okay"; + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c6m0_xfer>; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + interrupt-parent = <&gpio0>; + interrupts = ; + status = "okay"; + }; + +}; + +&i2s5_8ch { + status = "okay"; +}; + +&i2s6_8ch { + status = "okay"; +}; + +&mdio0 { + rgmii_phy: phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + }; +}; + +//phy1 +&pcie2x1l0 { + reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie2x1l0>; + rockchip,skip-scan-in-resume; + status = "okay"; +}; + +//phy2 +&pcie2x1l1 { + reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>; + rockchip,default-link-up; + status = "okay"; +}; + +//phy0 +&pcie2x1l2 { + reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + rockchip,default-link-up; + status = "okay"; +}; + +&pcie30phy { + rockchip,pcie30-phymode = ; + status = "okay"; +}; + +&pcie3x4 { + reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie30>; + status = "okay"; +}; + +&pinctrl { + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <3 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + lcd { + lcd_rst_gpio: lcd-rst-gpio { + rockchip,pins = <1 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + vcc5v0_otg_en: vcc5v0-otg-en { + rockchip,pins = <4 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-bluetooth { + uart7_gpios: uart7-gpios { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_reset_gpio: bt-reset-gpio { + rockchip,pins = <4 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_wake_gpio: bt-wake-gpio { + rockchip,pins = <4 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_irq_gpio: bt-irq-gpio { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + wireless-wlan { + wifi_host_wake_irq: wifi-host-wake-irq { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds_gpio { + leds_rgb: leds-rgb { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>, + <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hdmi-in { + hdmirx_det: hdmirx-det { + rockchip,pins = <3 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&u2phy1_otg { + phy-supply = <&vcc5v0_host>; +}; + +&u2phy2_host { + phy-supply = <&vcc5v0_host>; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_host>; +}; + +&usbdrd_dwc3_0 { + status = "okay"; + dr_mode = "otg"; + extcon = <&u2phy0>; +}; + +&usbhost3_0 { + status = "disabled"; +}; + +&usbhost_dwc3_0 { + status = "disabled"; +}; + +&mipi_dcphy0 { + status = "okay"; +}; + +&mipi_dcphy1 { + status = "okay"; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&rkisp0 { + status = "okay"; +}; + +&isp0_mmu { + status = "okay"; +}; + +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_1 { + dr_mode = "host"; + status = "okay"; +}; + +/* Fan */ +&pwm9 { + status = "okay"; + pinctrl-names = "active"; + pinctrl-0 = <&pwm9m2_pins>; +}; + +/* watchdog */ +&wdt { + status = "okay"; +}; + +&sfc { + status = "okay"; + max-freq = <100000000>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&fspim2_pins>; + + spi_flash: spi-flash@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <100000000>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + loader@0 { + label = "loader"; + reg = <0x0 0x1000000>; + }; + }; + }; +}; + +&pwm15 { + pinctrl-names = "active"; + pinctrl-0 = <&pwm15m2_pins>; + status = "okay"; +}; + +&can1 { + assigned-clocks = <&cru CLK_CAN1>; + assigned-clock-rates = <200000000>; +}; + +&spi0 { + assigned-clocks = <&cru CLK_SPI0>; + assigned-clock-rates = <200000000>; + num-cs = <2>; +}; + +&uart7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart7m0_xfer &uart7m0_ctsn>; +}; + +&spi4 { + assigned-clocks = <&cru CLK_SPI4>; + assigned-clock-rates = <200000000>; + num-cs = <2>; +}; + +&dsi1 { + status = "disabled"; +}; + +&dsi1_panel { + status = "disabled"; + reset-gpios = <&gpio1 RK_PD3 GPIO_ACTIVE_LOW>; + enable-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_rst_gpio>; +}; + +&dsi1_in_vp2 { + status = "disabled"; +}; + +&dsi1_in_vp3 { + status = "disabled"; +}; + +&route_dsi1 { + status = "disabled"; + connect = <&vp3_out_dsi1>; +}; + +&i2c7 { + status = "okay"; + + gt9xx_0: touchscreen@14 { + compatible = "goodix,gt9271"; + reg = <0x14>; + interrupt-parent = <&gpio2>; + interrupts = ; + irq-gpios = <&gpio2 RK_PC1 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; + touchscreen-inverted-x; + //touchscreen-inverted-y; + touchscreen-swapped-x-y; + touchscreen-size-x = <1280>; + touchscreen-size-y = <800>; + status = "okay"; + }; +}; + +&usbdp_phy0 { + status = "okay"; +}; + +&usbdp_phy0_dp { + status = "okay"; +}; + +&usbdp_phy0_u3 { + status = "okay"; +}; + +&usbdp_phy1 { + status = "okay"; +}; + +&usbdp_phy1_dp { + status = "okay"; +}; + +&usbdp_phy1_u3 { + status = "okay"; +}; + +/* Should work with at least 128MB cma reserved above. */ +&hdmirx_ctrler { + #sound-dai-cells = <1>; + /* Effective level used to trigger HPD: 0-low, 1-high */ + hpd-trigger-level = <1>; + hdmirx-det-gpios = <&gpio3 RK_PD3 GPIO_ACTIVE_LOW>; + + /delete-property/ pinctrl-0; + /delete-property/ pinctrl-names; + + pinctrl-names = "default"; + pinctrl-0 = <&hdmim2_rx_cec &hdmim2_rx_hpdin &hdmim2_rx_scl &hdmim2_rx_sda &hdmirx_det>; + + status = "disabled"; +}; + +&i2s7_8ch { + status = "okay"; +}; + +&i2c8 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8m3_xfer>; +}; + +&pwm6 { + status = "disabled"; + pinctrl-names = "active"; + pinctrl-0 = <&pwm6m1_pins>; +}; \ No newline at end of file From 607c1e81e6054ad82b4ee429e76a74fe3a7f51f4 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Thu, 4 Sep 2025 20:39:49 +0200 Subject: [PATCH 10/43] rockchip64: prevent SPI flash from exiting parent shell and replace dialog with whiptail. Signed-off-by: MichaIng --- config/sources/families/include/rockchip64_common.inc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/sources/families/include/rockchip64_common.inc b/config/sources/families/include/rockchip64_common.inc index 6e67f567602a..f1e660ee284f 100644 --- a/config/sources/families/include/rockchip64_common.inc +++ b/config/sources/families/include/rockchip64_common.inc @@ -300,7 +300,7 @@ write_uboot_platform() { ${logging_prelude} dd if=$1/trust.bin of=$2 seek=24576 conv=notrunc status=none else echo "Unsupported u-boot processing configuration!" - exit 1 + return 1 fi } @@ -308,7 +308,7 @@ write_uboot_platform_mtd() { FILES=$(find "$1" -maxdepth 1 -type f \( -name "rkspi_loader*.img" -o -name "u-boot-rockchip-spi*.bin" \)) if [ -z "$FILES" ]; then echo "No SPI image found." - exit 1 + return 1 fi MENU_ITEMS=() @@ -336,7 +336,7 @@ write_uboot_platform_mtd() { [[ -f /etc/armbian-release ]] && source /etc/armbian-release backtitle="Armbian for $BOARD_NAME install script, https://www.armbian.com" - CHOICE=$(dialog --no-collapse \ + CHOICE=$(whiptail \ --title "armbian-install" \ --backtitle "$backtitle" \ --radiolist "Choose SPI image:" 0 56 4 \ @@ -353,7 +353,7 @@ write_uboot_platform_mtd() { fi else echo "No SPI image chosen." - exit 1 + return 1 fi } From 6713ebcd059a911ab03cd18dbd414c511967023f Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 22 Jun 2025 16:03:57 +0200 Subject: [PATCH 11/43] mainline-kernel: align enabled WiFi drivers - Enable all RTW88 mainline drivers - Disable all related 3rd party drivers - Merge and sort all related config keys - Align for all mainline Rockchip/Allwinner/Amlogic configs As an exception, keep using the out-of-tree driver for RTL8723DS, which performs much better on Linux 6.12. On Linux 6.16, the mainline driver runs as smooth, but throws a warning invalid efuse MAC, assigning a random one instead. On ROCK Pi S, the out-of-tree driver does not assign a static MAC etiher, but only the last 3 blocks are random, the first 3 remain static. On the Gateway GZ80X, as heard from someone else, it seems to apply a completely static MAC. In any case, it can obviously better obtain MAC address info hardware, respectively do so in more cases. Signed-off-by: MichaIng --- config/kernel/linux-meson-current.config | 48 +++++++++++---- config/kernel/linux-meson64-current.config | 61 +++++++++++++------ config/kernel/linux-meson64-edge.config | 60 ++++++++++++------ config/kernel/linux-rockchip-current.config | 52 ++++++++++++++-- config/kernel/linux-rockchip-edge.config | 50 +++++++++++++-- config/kernel/linux-rockchip64-current.config | 48 ++++++++++----- config/kernel/linux-rockchip64-edge.config | 47 +++++++++----- config/kernel/linux-sunxi-current.config | 58 +++++++++++++++--- config/kernel/linux-sunxi-edge.config | 57 ++++++++++++++--- config/kernel/linux-sunxi64-current.config | 58 +++++++++++------- config/kernel/linux-sunxi64-edge.config | 58 +++++++++++------- 11 files changed, 447 insertions(+), 150 deletions(-) diff --git a/config/kernel/linux-meson-current.config b/config/kernel/linux-meson-current.config index 3758061cb709..aef479891cdb 100644 --- a/config/kernel/linux-meson-current.config +++ b/config/kernel/linux-meson-current.config @@ -851,19 +851,51 @@ CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m +CONFIG_RTL8192CE=m CONFIG_RTL8192CU=m -# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set +CONFIG_RTL8821AE=m +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTW88=m -CONFIG_RTW88_8822BE=m -CONFIG_RTW88_8822BU=m -CONFIG_RTW88_8822CE=m -CONFIG_RTW88_8822CU=m +CONFIG_RTW88_8723CS=m CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m CONFIG_RTW88_8821CE=m +CONFIG_RTW88_8821CS=m CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822BS=m +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8822CS=m +CONFIG_RTW88_8822CU=m CONFIG_RTW89=m CONFIG_RTW89_8851BE=m CONFIG_RTW89_8852AE=m @@ -882,12 +914,6 @@ CONFIG_WL12XX=m CONFIG_WL18XX=m CONFIG_WLCORE_SPI=m CONFIG_WLCORE_SDIO=m -CONFIG_RTL8723DS=m -CONFIG_RTL8822BU=m -CONFIG_RTL8821CU=m -CONFIG_88XXAU=m -CONFIG_RTL8192EU=m -CONFIG_RTL8189ES=m CONFIG_ZD1211RW=m CONFIG_VIRT_WIFI=m CONFIG_NETDEVSIM=m diff --git a/config/kernel/linux-meson64-current.config b/config/kernel/linux-meson64-current.config index afeb8a40cf6a..d03f30b28180 100644 --- a/config/kernel/linux-meson64-current.config +++ b/config/kernel/linux-meson64-current.config @@ -1091,31 +1091,62 @@ CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RTLWIFI_DEBUG is not set CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m +CONFIG_RTL8192CU=m CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m CONFIG_RTL8723AE=m CONFIG_RTL8723BE=m -CONFIG_RTL8188EE=m -CONFIG_RTL8192EE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set CONFIG_RTL8821AE=m -CONFIG_RTL8192CU=m -CONFIG_RTL8192DU=m -# CONFIG_RTLWIFI_DEBUG is not set +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTW88=m -CONFIG_RTW88_8822BU=m -CONFIG_RTW88_8822CS=m -CONFIG_RTW88_8822CU=m +CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m CONFIG_RTW88_8821CE=m CONFIG_RTW88_8821CS=m CONFIG_RTW88_8821CU=m -CONFIG_RTW88_8821AU=m -CONFIG_RTW88_8812AU=m -CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822BS=m +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8822CS=m +CONFIG_RTW88_8822CU=m +CONFIG_RTW89=m +CONFIG_RTW89_8851BE=m +CONFIG_RTW89_8851BU=m +CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852AU=m +CONFIG_RTW89_8852BE=m +CONFIG_RTW89_8852BTE=m +CONFIG_RTW89_8852BU=m +CONFIG_RTW89_8852CE=m +CONFIG_RTW89_8852CU=m +CONFIG_RTW89_8922AE=m CONFIG_RSI_91X=m # CONFIG_RSI_DEBUGFS is not set CONFIG_CW1200=m @@ -1128,11 +1159,6 @@ CONFIG_WL12XX=m CONFIG_WL18XX=m CONFIG_WLCORE_SPI=m CONFIG_WLCORE_SDIO=m -CONFIG_RTL8723DS=m -CONFIG_RTL8822CS=m -CONFIG_RTL8192EU=m -CONFIG_RTL8189FS=m -CONFIG_RTL8189ES=m CONFIG_ZD1211RW=m CONFIG_QTNFMAC_PCIE=m CONFIG_MAC80211_HWSIM=m @@ -3311,7 +3337,6 @@ CONFIG_XEN_DEV_EVTCHN=m CONFIG_XENFS=m CONFIG_XEN_SCSI_BACKEND=m CONFIG_STAGING=y -CONFIG_RTL8723BS=m CONFIG_AD9832=m CONFIG_AD9834=m CONFIG_FB_SM750=m diff --git a/config/kernel/linux-meson64-edge.config b/config/kernel/linux-meson64-edge.config index 41ec4aaf2fd3..c8b4c0c4f406 100644 --- a/config/kernel/linux-meson64-edge.config +++ b/config/kernel/linux-meson64-edge.config @@ -1091,31 +1091,62 @@ CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RTLWIFI_DEBUG is not set CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m +CONFIG_RTL8192CU=m CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m CONFIG_RTL8723AE=m CONFIG_RTL8723BE=m -CONFIG_RTL8188EE=m -CONFIG_RTL8192EE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set CONFIG_RTL8821AE=m -CONFIG_RTL8192CU=m -CONFIG_RTL8192DU=m -# CONFIG_RTLWIFI_DEBUG is not set +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTW88=m -CONFIG_RTW88_8822BU=m -CONFIG_RTW88_8822CS=m -CONFIG_RTW88_8822CU=m +CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m CONFIG_RTW88_8821CE=m CONFIG_RTW88_8821CS=m CONFIG_RTW88_8821CU=m -CONFIG_RTW88_8821AU=m -CONFIG_RTW88_8812AU=m -CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822BS=m +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8822CS=m +CONFIG_RTW88_8822CU=m +CONFIG_RTW89=m +CONFIG_RTW89_8851BE=m +CONFIG_RTW89_8851BU=m +CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852AU=m +CONFIG_RTW89_8852BE=m +CONFIG_RTW89_8852BTE=m +CONFIG_RTW89_8852BU=m +CONFIG_RTW89_8852CE=m +CONFIG_RTW89_8852CU=m +CONFIG_RTW89_8922AE=m CONFIG_RSI_91X=m # CONFIG_RSI_DEBUGFS is not set CONFIG_CW1200=m @@ -1128,10 +1159,6 @@ CONFIG_WL12XX=m CONFIG_WL18XX=m CONFIG_WLCORE_SPI=m CONFIG_WLCORE_SDIO=m -CONFIG_RTL8723DS=m -CONFIG_RTL8822CS=m -CONFIG_RTL8189FS=m -CONFIG_RTL8189ES=m CONFIG_ZD1211RW=m CONFIG_QTNFMAC_PCIE=m CONFIG_MAC80211_HWSIM=m @@ -3306,7 +3333,6 @@ CONFIG_XEN_DEV_EVTCHN=m CONFIG_XENFS=m CONFIG_XEN_SCSI_BACKEND=m CONFIG_STAGING=y -CONFIG_RTL8723BS=m CONFIG_AD9832=m CONFIG_AD9834=m CONFIG_FB_SM750=m diff --git a/config/kernel/linux-rockchip-current.config b/config/kernel/linux-rockchip-current.config index 4c31e1acf095..0dca951a0861 100644 --- a/config/kernel/linux-rockchip-current.config +++ b/config/kernel/linux-rockchip-current.config @@ -759,22 +759,63 @@ CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m +CONFIG_RTL8192CE=m CONFIG_RTL8192CU=m -# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set +CONFIG_RTL8821AE=m +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTL8XXXU_UNTESTED=y CONFIG_RTW88=m -CONFIG_RTW88_8822BU=m -CONFIG_RTW88_8822CU=m -CONFIG_RTW88_8723DS=m CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8821CE=m +CONFIG_RTW88_8821CS=m CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822BS=m +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8822CS=m +CONFIG_RTW88_8822CU=m CONFIG_RTW89=m +CONFIG_RTW89_8851BE=m CONFIG_RTW89_8851BU=m +CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852AU=m +CONFIG_RTW89_8852BE=m +CONFIG_RTW89_8852BTE=m CONFIG_RTW89_8852BU=m -CONFIG_RTL8189ES=m +CONFIG_RTW89_8852CE=m +CONFIG_RTW89_8852CU=m +CONFIG_RTW89_8922AE=m CONFIG_ZD1211RW=m CONFIG_ESP8089=m CONFIG_VIRT_WIFI=m @@ -1487,7 +1528,6 @@ CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_DMABUF_HEAPS_CMA=y # CONFIG_VIRTIO_MENU is not set CONFIG_STAGING=y -CONFIG_RTL8723BS=m CONFIG_STAGING_MEDIA=y CONFIG_FB_TFT=m CONFIG_FB_TFT_AGM1264K_FL=m diff --git a/config/kernel/linux-rockchip-edge.config b/config/kernel/linux-rockchip-edge.config index 1888a9c8ec13..615e5b493310 100644 --- a/config/kernel/linux-rockchip-edge.config +++ b/config/kernel/linux-rockchip-edge.config @@ -760,24 +760,63 @@ CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m +CONFIG_RTL8192CE=m CONFIG_RTL8192CU=m -# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set +CONFIG_RTL8821AE=m +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTL8XXXU_UNTESTED=y CONFIG_RTW88=m -CONFIG_RTW88_8822BU=m -CONFIG_RTW88_8822CU=m -CONFIG_RTW88_8723DS=m CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8821CE=m +CONFIG_RTW88_8821CS=m CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822BS=m +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8822CS=m +CONFIG_RTW88_8822CU=m CONFIG_RTW89=m +CONFIG_RTW89_8851BE=m CONFIG_RTW89_8851BU=m +CONFIG_RTW89_8852AE=m CONFIG_RTW89_8852AU=m +CONFIG_RTW89_8852BE=m +CONFIG_RTW89_8852BTE=m CONFIG_RTW89_8852BU=m +CONFIG_RTW89_8852CE=m CONFIG_RTW89_8852CU=m -CONFIG_RTL8189ES=m +CONFIG_RTW89_8922AE=m CONFIG_ZD1211RW=m CONFIG_ESP8089=m CONFIG_VIRT_WIFI=m @@ -1489,7 +1528,6 @@ CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_DMABUF_HEAPS_CMA=y # CONFIG_VIRTIO_MENU is not set CONFIG_STAGING=y -CONFIG_RTL8723BS=m CONFIG_STAGING_MEDIA=y CONFIG_FB_TFT=m CONFIG_FB_TFT_AGM1264K_FL=m diff --git a/config/kernel/linux-rockchip64-current.config b/config/kernel/linux-rockchip64-current.config index 1e40d512da85..db8e62a7040a 100644 --- a/config/kernel/linux-rockchip64-current.config +++ b/config/kernel/linux-rockchip64-current.config @@ -1078,39 +1078,61 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y +# CONFIG_RTLWIFI_DEBUG is not set CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m +CONFIG_RTL8192CU=m CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m CONFIG_RTL8723AE=m CONFIG_RTL8723BE=m -CONFIG_RTL8188EE=m -CONFIG_RTL8192EE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set CONFIG_RTL8821AE=m -CONFIG_RTL8192CU=m -# CONFIG_RTLWIFI_DEBUG is not set +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTW88=m +CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set +CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8821CE=m +CONFIG_RTW88_8821CS=m +CONFIG_RTW88_8821CU=m CONFIG_RTW88_8822BE=m CONFIG_RTW88_8822BS=m CONFIG_RTW88_8822BU=m CONFIG_RTW88_8822CE=m CONFIG_RTW88_8822CS=m CONFIG_RTW88_8822CU=m -CONFIG_RTW88_8723DE=m -CONFIG_RTW88_8723DU=m -CONFIG_RTW88_8821CE=m -CONFIG_RTW88_8821CS=m -CONFIG_RTW88_8821CU=m CONFIG_RTW89=m CONFIG_RTW89_8851BE=m CONFIG_RTW89_8851BU=m CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852AU=m CONFIG_RTW89_8852BE=m -CONFIG_RTW89_8852BU=m CONFIG_RTW89_8852BTE=m +CONFIG_RTW89_8852BU=m CONFIG_RTW89_8852CE=m +CONFIG_RTW89_8852CU=m CONFIG_RTW89_8922AE=m CONFIG_RTL8852BS=m CONFIG_RSI_91X=m @@ -1126,9 +1148,6 @@ CONFIG_WL12XX=m CONFIG_WL18XX=m CONFIG_WLCORE_SPI=m CONFIG_WLCORE_SDIO=m -CONFIG_RTL8723DS=m -CONFIG_RTL8192EU=m -CONFIG_RTL8189ES=m CONFIG_ZD1211RW=m CONFIG_QTNFMAC_PCIE=m CONFIG_SPARD_WLAN_SUPPORT=y @@ -2793,7 +2812,6 @@ CONFIG_XEN_GNTDEV=y CONFIG_XEN_GRANT_DEV_ALLOC=y CONFIG_XEN_SCSI_BACKEND=m CONFIG_STAGING=y -CONFIG_RTL8723BS=m CONFIG_AD9832=m CONFIG_AD9834=m CONFIG_FB_SM750=m diff --git a/config/kernel/linux-rockchip64-edge.config b/config/kernel/linux-rockchip64-edge.config index 603a8ac7ed70..5987cfa7ad0d 100644 --- a/config/kernel/linux-rockchip64-edge.config +++ b/config/kernel/linux-rockchip64-edge.config @@ -1076,39 +1076,61 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y +# CONFIG_RTLWIFI_DEBUG is not set CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m +CONFIG_RTL8192CU=m CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m CONFIG_RTL8723AE=m CONFIG_RTL8723BE=m -CONFIG_RTL8188EE=m -CONFIG_RTL8192EE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set CONFIG_RTL8821AE=m -CONFIG_RTL8192CU=m -# CONFIG_RTLWIFI_DEBUG is not set +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTW88=m +CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set +CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8821CE=m +CONFIG_RTW88_8821CS=m +CONFIG_RTW88_8821CU=m CONFIG_RTW88_8822BE=m CONFIG_RTW88_8822BS=m CONFIG_RTW88_8822BU=m CONFIG_RTW88_8822CE=m CONFIG_RTW88_8822CS=m CONFIG_RTW88_8822CU=m -CONFIG_RTW88_8723DE=m -CONFIG_RTW88_8723DU=m -CONFIG_RTW88_8821CE=m -CONFIG_RTW88_8821CS=m -CONFIG_RTW88_8821CU=m CONFIG_RTW89=m CONFIG_RTW89_8851BE=m CONFIG_RTW89_8851BU=m CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852AU=m CONFIG_RTW89_8852BE=m -CONFIG_RTW89_8852BU=m CONFIG_RTW89_8852BTE=m +CONFIG_RTW89_8852BU=m CONFIG_RTW89_8852CE=m +CONFIG_RTW89_8852CU=m CONFIG_RTW89_8922AE=m CONFIG_RTL8852BS=m CONFIG_RSI_91X=m @@ -1124,8 +1146,6 @@ CONFIG_WL12XX=m CONFIG_WL18XX=m CONFIG_WLCORE_SPI=m CONFIG_WLCORE_SDIO=m -CONFIG_RTL8723DS=m -CONFIG_RTL8189ES=m CONFIG_ZD1211RW=m CONFIG_QTNFMAC_PCIE=m CONFIG_SPARD_WLAN_SUPPORT=y @@ -2784,7 +2804,6 @@ CONFIG_XEN_GNTDEV=y CONFIG_XEN_GRANT_DEV_ALLOC=y CONFIG_XEN_SCSI_BACKEND=m CONFIG_STAGING=y -CONFIG_RTL8723BS=m CONFIG_AD9832=m CONFIG_AD9834=m CONFIG_FB_SM750=m diff --git a/config/kernel/linux-sunxi-current.config b/config/kernel/linux-sunxi-current.config index fac131eb1ad4..bc379f20f8c3 100644 --- a/config/kernel/linux-sunxi-current.config +++ b/config/kernel/linux-sunxi-current.config @@ -866,25 +866,64 @@ CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m +CONFIG_RTL8192CE=m CONFIG_RTL8192CU=m -# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set +CONFIG_RTL8821AE=m +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTW88=m +CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set +CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8821CE=m +CONFIG_RTW88_8821CS=m +CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8822BE=m CONFIG_RTW88_8822BS=m CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m CONFIG_RTW88_8822CS=m CONFIG_RTW88_8822CU=m -CONFIG_RTW88_8723DS=m -CONFIG_RTW88_8723DU=m -CONFIG_RTW88_8821CS=m -CONFIG_RTW88_8821CU=m -CONFIG_RTW88_DEBUGFS=y +CONFIG_RTW89=m +CONFIG_RTW89_8851BE=m +CONFIG_RTW89_8851BU=m +CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852AU=m +CONFIG_RTW89_8852BE=m +CONFIG_RTW89_8852BTE=m +CONFIG_RTW89_8852BU=m +CONFIG_RTW89_8852CE=m +CONFIG_RTW89_8852CU=m +CONFIG_RTW89_8922AE=m CONFIG_WFX=m CONFIG_XRADIO=m -CONFIG_RTL8192EU=m -CONFIG_RTL8189FS=m -CONFIG_RTL8189ES=m CONFIG_MAC80211_HWSIM=m CONFIG_WWAN=m # CONFIG_WWAN_DEBUGFS is not set @@ -2386,7 +2425,6 @@ CONFIG_UIO_DMEM_GENIRQ=m CONFIG_VIRTIO_BALLOON=m CONFIG_VIRTIO_INPUT=m CONFIG_STAGING=y -CONFIG_RTL8723BS=m CONFIG_AD9832=m CONFIG_AD9834=m CONFIG_STAGING_MEDIA=y diff --git a/config/kernel/linux-sunxi-edge.config b/config/kernel/linux-sunxi-edge.config index 981e1ad6d83a..1a4bd5b752d6 100644 --- a/config/kernel/linux-sunxi-edge.config +++ b/config/kernel/linux-sunxi-edge.config @@ -878,24 +878,64 @@ CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m +CONFIG_RTL8192CE=m CONFIG_RTL8192CU=m -# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set +CONFIG_RTL8821AE=m +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTW88=m +CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set +CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8821CE=m +CONFIG_RTW88_8821CS=m +CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8822BE=m CONFIG_RTW88_8822BS=m CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m CONFIG_RTW88_8822CS=m CONFIG_RTW88_8822CU=m -CONFIG_RTW88_8723DS=m -CONFIG_RTW88_8723DU=m -CONFIG_RTW88_8821CS=m -CONFIG_RTW88_8821CU=m -CONFIG_RTW88_DEBUGFS=y +CONFIG_RTW89=m +CONFIG_RTW89_8851BE=m +CONFIG_RTW89_8851BU=m +CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852AU=m +CONFIG_RTW89_8852BE=m +CONFIG_RTW89_8852BTE=m +CONFIG_RTW89_8852BU=m +CONFIG_RTW89_8852CE=m +CONFIG_RTW89_8852CU=m +CONFIG_RTW89_8922AE=m CONFIG_WFX=m CONFIG_XRADIO=m -CONFIG_RTL8189FS=m -CONFIG_RTL8189ES=m CONFIG_MAC80211_HWSIM=m CONFIG_WWAN=m # CONFIG_WWAN_DEBUGFS is not set @@ -2394,7 +2434,6 @@ CONFIG_UIO_DMEM_GENIRQ=m CONFIG_VIRTIO_BALLOON=m CONFIG_VIRTIO_INPUT=m CONFIG_STAGING=y -CONFIG_RTL8723BS=m CONFIG_AD9832=m CONFIG_AD9834=m CONFIG_STAGING_MEDIA=y diff --git a/config/kernel/linux-sunxi64-current.config b/config/kernel/linux-sunxi64-current.config index 9b75ebb0f34c..f536d92f5417 100644 --- a/config/kernel/linux-sunxi64-current.config +++ b/config/kernel/linux-sunxi64-current.config @@ -874,54 +874,68 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m +CONFIG_RTL8192CU=m CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m CONFIG_RTL8723AE=m CONFIG_RTL8723BE=m -CONFIG_RTL8188EE=m -CONFIG_RTL8192EE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set CONFIG_RTL8821AE=m -CONFIG_RTL8192CU=m -CONFIG_RTL8192DU=m -# CONFIG_RTLWIFI_DEBUG is not set +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTL8XXXU_UNTESTED=y CONFIG_RTW88=m -CONFIG_RTW88_8822BS=m -CONFIG_RTW88_8822BU=m -CONFIG_RTW88_8822CE=m -CONFIG_RTW88_8822CS=m -CONFIG_RTW88_8822CU=m -CONFIG_RTW88_8723DE=m -CONFIG_RTW88_8723DS=m CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set CONFIG_RTW88_8723DU=m -CONFIG_RTW88_8821CE=m -CONFIG_RTW88_8821CS=m -CONFIG_RTW88_8821CU=m -CONFIG_RTW88_8821AU=m CONFIG_RTW88_8812AU=m CONFIG_RTW88_8814AE=m CONFIG_RTW88_8814AU=m -CONFIG_RTW88_DEBUGFS=y +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8821CE=m +CONFIG_RTW88_8821CS=m +CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822BS=m +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8822CS=m +CONFIG_RTW88_8822CU=m CONFIG_RTW89=m CONFIG_RTW89_8851BE=m +CONFIG_RTW89_8851BU=m CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852AU=m CONFIG_RTW89_8852BE=m CONFIG_RTW89_8852BTE=m +CONFIG_RTW89_8852BU=m CONFIG_RTW89_8852CE=m +CONFIG_RTW89_8852CU=m CONFIG_RTW89_8922AE=m # CONFIG_WLAN_VENDOR_RSI is not set CONFIG_WFX=m # CONFIG_WLAN_VENDOR_ST is not set # CONFIG_WLAN_VENDOR_TI is not set -CONFIG_RTL8723DS=m CONFIG_XRADIO=m -CONFIG_RTL8192EU=m -CONFIG_RTL8189FS=m -CONFIG_RTL8189ES=m # CONFIG_WLAN_VENDOR_ZYDAS is not set CONFIG_SPARD_WLAN_SUPPORT=y CONFIG_SC23XX=y diff --git a/config/kernel/linux-sunxi64-edge.config b/config/kernel/linux-sunxi64-edge.config index a5afb92fa8ca..22e8b0b33b4d 100644 --- a/config/kernel/linux-sunxi64-edge.config +++ b/config/kernel/linux-sunxi64-edge.config @@ -885,53 +885,68 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8180=m CONFIG_RTL8187=m +CONFIG_RTL8188EE=m +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m +CONFIG_RTL8192CU=m CONFIG_RTL8192DE=m +CONFIG_RTL8192DU=m +CONFIG_RTL8192E=m +CONFIG_RTL8192EE=m +CONFIG_RTL8192EU=m +CONFIG_RTL8192SE=m CONFIG_RTL8723AE=m CONFIG_RTL8723BE=m -CONFIG_RTL8188EE=m -CONFIG_RTL8192EE=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723CS is not set +CONFIG_RTL8723DS=m +# CONFIG_RTL8723DU is not set CONFIG_RTL8821AE=m -CONFIG_RTL8192CU=m -CONFIG_RTL8192DU=m -# CONFIG_RTLWIFI_DEBUG is not set +# CONFIG_RTL8821CU is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8822CS is not set +# CONFIG_88XXAU is not set CONFIG_RTL8XXXU=m CONFIG_RTL8XXXU_UNTESTED=y CONFIG_RTW88=m -CONFIG_RTW88_8822BS=m -CONFIG_RTW88_8822BU=m -CONFIG_RTW88_8822CE=m -CONFIG_RTW88_8822CS=m -CONFIG_RTW88_8822CU=m -CONFIG_RTW88_8723DE=m -CONFIG_RTW88_8723DS=m CONFIG_RTW88_8723CS=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set CONFIG_RTW88_8723DU=m -CONFIG_RTW88_8821CE=m -CONFIG_RTW88_8821CS=m -CONFIG_RTW88_8821CU=m -CONFIG_RTW88_8821AU=m CONFIG_RTW88_8812AU=m CONFIG_RTW88_8814AE=m CONFIG_RTW88_8814AU=m -CONFIG_RTW88_DEBUGFS=y +CONFIG_RTW88_8821AE=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8821CE=m +CONFIG_RTW88_8821CS=m +CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822BS=m +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8822CS=m +CONFIG_RTW88_8822CU=m CONFIG_RTW89=m CONFIG_RTW89_8851BE=m +CONFIG_RTW89_8851BU=m CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852AU=m CONFIG_RTW89_8852BE=m CONFIG_RTW89_8852BTE=m +CONFIG_RTW89_8852BU=m CONFIG_RTW89_8852CE=m +CONFIG_RTW89_8852CU=m CONFIG_RTW89_8922AE=m # CONFIG_WLAN_VENDOR_RSI is not set CONFIG_WFX=m # CONFIG_WLAN_VENDOR_ST is not set # CONFIG_WLAN_VENDOR_TI is not set -CONFIG_RTL8723DS=m CONFIG_XRADIO=m -CONFIG_RTL8189FS=m -CONFIG_RTL8189ES=m # CONFIG_WLAN_VENDOR_ZYDAS is not set CONFIG_SPARD_WLAN_SUPPORT=y CONFIG_SC23XX=y @@ -2183,7 +2198,6 @@ CONFIG_UIO_PDRV_GENIRQ=m CONFIG_UIO_DMEM_GENIRQ=m # CONFIG_VIRTIO_MENU is not set CONFIG_STAGING=y -CONFIG_RTL8723BS=m CONFIG_STAGING_MEDIA=y CONFIG_VIDEO_SUNXI=y CONFIG_VIDEO_SUNXI_CEDRUS=y From 618dbf446202b62ed80c7b27ed98960b20ca9dba Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 28 Oct 2025 23:12:30 +0100 Subject: [PATCH 12/43] rock-4cplus: remove faulty UBOOT_TARGET_MAP override This breaks the ATF build that was likely unintentionally enabled with https://github.com/armbian/build/pull/8449. However, when already creating an upstream diff, we go forward and use ATF with latest U-Boot version. This also removes the unnecessary SPI images from U-Boot builds. This SBC does not have an SPI storage. Signed-off-by: MichaIng --- config/boards/rockpi-4cplus.csc | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/config/boards/rockpi-4cplus.csc b/config/boards/rockpi-4cplus.csc index 957d531cf5c4..4b833d296991 100644 --- a/config/boards/rockpi-4cplus.csc +++ b/config/boards/rockpi-4cplus.csc @@ -9,15 +9,7 @@ KERNEL_TEST_TARGET="current" FULL_DESKTOP="yes" BOOT_LOGO="desktop" -BOOTBRANCH_BOARD="tag:v2024.01" -BOOTPATCHDIR="v2024.01" +BOOTBRANCH_BOARD="tag:v2025.10" +BOOTPATCHDIR="v2025.10" BOOTCONFIG="rock-4c-plus-rk3399_defconfig" BOOT_SCENARIO="binman-atf-mainline" -BOOT_SUPPORT_SPI=yes - -DDR_BLOB="rk33/rk3399_ddr_933MHz_v1.30.bin" -BL31_BLOB="rk33/rk3399_bl31_v1.36.elf" - -function post_family_config___mainline_uboot() { - declare -g UBOOT_TARGET_MAP="ROCKCHIP_TPL=${RKBIN_DIR}/${DDR_BLOB} BL31=$RKBIN_DIR/$BL31_BLOB spl/u-boot-spl u-boot.bin flash.bin;;idbloader.img u-boot.itb" -} From 04762035b5edffe655e0023b40dab11de4f49c09 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Fri, 7 Nov 2025 01:34:16 +0100 Subject: [PATCH 13/43] Remove some unneccesary steps and warnings * cpufrequtils is not installed anymore by Armbian, hence removing it from Trixie is not needed anymore. * On Debian, software-properties-common is not needed, but spamming the logs with a warning about that is unnecessary => degraded to debug * Removed duplicate software-properties-common argument * Do not spam logs with a warning if the optional userspace extensions dir does not exist Signed-off-by: MichaIng --- lib/functions/general/extensions.sh | 2 +- lib/functions/main/config-prepare.sh | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/functions/general/extensions.sh b/lib/functions/general/extensions.sh index fc65f37e09a0..1e86ccb38809 100644 --- a/lib/functions/general/extensions.sh +++ b/lib/functions/general/extensions.sh @@ -593,7 +593,7 @@ function enable_extensions_with_hostdeps_builtin_and_user() { mapfile -t ext_list_dir < <(find "${ext_dir}" -maxdepth 2 -type f -name "*.sh" -print0 | xargs -0 -r grep -l "${grep_args[@]}" 2>/dev/null || true) display_alert "Extension search result" "Found ${#ext_list_dir[@]} extensions in \"${ext_dir}\"" "" extension_list+=("${ext_list_dir[@]}") - else + elif [[ "${ext_dir}" != "${USERPATCHES_PATH}/extensions" ]]; then display_alert "Extension search" "Directory does not exist: \"${ext_dir}\"" "wrn" fi done diff --git a/lib/functions/main/config-prepare.sh b/lib/functions/main/config-prepare.sh index dbf39f0e8d91..faaa8e3c616f 100644 --- a/lib/functions/main/config-prepare.sh +++ b/lib/functions/main/config-prepare.sh @@ -390,13 +390,10 @@ function check_config_userspace_release_and_desktop() { function fix_userspace_packages_release_and_distro() { display_alert "fix_userspace_packages_release_and_distro" "For distro '${DISTRIBUTION}' release '${RELEASE}'" "debug" - # Some old hack from the past, not sure if it's still needed. Originally from https://github.com/armbian/build/pull/5881 - if [[ $RELEASE == trixie || $ARCH == riscv64 ]]; then remove_packages "cpufrequtils"; fi # this will remove from rootfs as well - # Debian: no need for this package in the rootfs, as it provides add-apt-repository which is not used on our Debian builds if [[ "${DISTRIBUTION}" == "Debian" ]]; then - display_alert "Not-installing software-properties-common" "For distro '${DISTRIBUTION}' release '${RELEASE}'" "warn" - remove_packages "software-properties-common" "software-properties-gtk" "software-properties-common" + display_alert "Not-installing software-properties-common" "For distro '${DISTRIBUTION}'" "debug" + remove_packages "software-properties-common" "software-properties-gtk" fi } From 09c0fdd2b1fc107a4aa8daebf8da21f147753965 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Thu, 13 Nov 2025 00:06:45 +0100 Subject: [PATCH 14/43] sunxi: disable RTC for all H3/H5 boards but NanoPi R1 All other H3/H5 boards we support, have no RTC battery socket. But the RTC node is enabled by default in mainline Linux, reserving /dev/rtc0. The kernel config uses that via CONFIG_RTC_HCTOSYS_DEVICE="rtc0". This is unnecessary and becomes a problem when aiming to use an external I2C RTC, which currently requires a manual `hwclock --hctosys --rtc /dev/rtc1` call to be used. With the SoC-internal RTC disabled, the kernel restores from the external RTC automatically. Signed-off-by: MichaIng --- ...h5-disable-rtc-for-all-but-nanopi-r1.patch | 27 +++++++++++++++++++ ...h5-disable-rtc-for-all-but-nanopi-r1.patch | 27 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 patch/kernel/archive/sunxi-6.12/arm-dts-sunxi-h3-h5-disable-rtc-for-all-but-nanopi-r1.patch create mode 100644 patch/kernel/archive/sunxi-6.18/arm-dts-sunxi-h3-h5-disable-rtc-for-all-but-nanopi-r1.patch diff --git a/patch/kernel/archive/sunxi-6.12/arm-dts-sunxi-h3-h5-disable-rtc-for-all-but-nanopi-r1.patch b/patch/kernel/archive/sunxi-6.12/arm-dts-sunxi-h3-h5-disable-rtc-for-all-but-nanopi-r1.patch new file mode 100644 index 000000000000..82c9719b1480 --- /dev/null +++ b/patch/kernel/archive/sunxi-6.12/arm-dts-sunxi-h3-h5-disable-rtc-for-all-but-nanopi-r1.patch @@ -0,0 +1,27 @@ +diff --git a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts +index 870649760f707..a7566b1e2ff9f 100644 +--- a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts ++++ b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts +@@ -133,6 +133,10 @@ ®_usb0_vbus { + status = "okay"; + }; + ++&rtc { ++ status = "okay"; ++}; ++ + &uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; +diff --git a/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi +index 7df60515a9032..dfa3d56e0b16e 100644 +--- a/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi ++++ b/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi +@@ -870,6 +870,7 @@ rtc: rtc@1f00000 { + clock-output-names = "osc32k", "osc32k-out", "iosc"; + clocks = <&osc32k>; + #clock-cells = <1>; ++ status = "disabled"; + }; + + r_intc: interrupt-controller@1f00c00 { diff --git a/patch/kernel/archive/sunxi-6.18/arm-dts-sunxi-h3-h5-disable-rtc-for-all-but-nanopi-r1.patch b/patch/kernel/archive/sunxi-6.18/arm-dts-sunxi-h3-h5-disable-rtc-for-all-but-nanopi-r1.patch new file mode 100644 index 000000000000..82c9719b1480 --- /dev/null +++ b/patch/kernel/archive/sunxi-6.18/arm-dts-sunxi-h3-h5-disable-rtc-for-all-but-nanopi-r1.patch @@ -0,0 +1,27 @@ +diff --git a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts +index 870649760f707..a7566b1e2ff9f 100644 +--- a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts ++++ b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts +@@ -133,6 +133,10 @@ ®_usb0_vbus { + status = "okay"; + }; + ++&rtc { ++ status = "okay"; ++}; ++ + &uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; +diff --git a/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi +index 7df60515a9032..dfa3d56e0b16e 100644 +--- a/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi ++++ b/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi +@@ -870,6 +870,7 @@ rtc: rtc@1f00000 { + clock-output-names = "osc32k", "osc32k-out", "iosc"; + clocks = <&osc32k>; + #clock-cells = <1>; ++ status = "disabled"; + }; + + r_intc: interrupt-controller@1f00c00 { From 62606e20c897a0e66394bf97be7b460cbf33fe07 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 22 Jun 2025 02:30:42 +0200 Subject: [PATCH 15/43] nanopi-r2s: apply default Ethernet LED triggers Signed-off-by: MichaIng --- .../archive/rockchip64-6.12/dt/rk3328-nanopi-r2-rev00.dts | 2 ++ .../archive/rockchip64-6.18/dt/rk3328-nanopi-r2-rev00.dts | 2 ++ .../kernel/archive/rockchip64-7.0/dt/rk3328-nanopi-r2-rev00.dts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/patch/kernel/archive/rockchip64-6.12/dt/rk3328-nanopi-r2-rev00.dts b/patch/kernel/archive/rockchip64-6.12/dt/rk3328-nanopi-r2-rev00.dts index 8ba95189c031..59265942fe01 100644 --- a/patch/kernel/archive/rockchip64-6.12/dt/rk3328-nanopi-r2-rev00.dts +++ b/patch/kernel/archive/rockchip64-6.12/dt/rk3328-nanopi-r2-rev00.dts @@ -64,11 +64,13 @@ led@2 { gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; label = "lan_led"; + linux,default-trigger = "netdev"; }; led@3 { gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; label = "wan_led"; + linux,default-trigger = "stmmac-0:00:link"; }; }; diff --git a/patch/kernel/archive/rockchip64-6.18/dt/rk3328-nanopi-r2-rev00.dts b/patch/kernel/archive/rockchip64-6.18/dt/rk3328-nanopi-r2-rev00.dts index 8ba95189c031..59265942fe01 100644 --- a/patch/kernel/archive/rockchip64-6.18/dt/rk3328-nanopi-r2-rev00.dts +++ b/patch/kernel/archive/rockchip64-6.18/dt/rk3328-nanopi-r2-rev00.dts @@ -64,11 +64,13 @@ led@2 { gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; label = "lan_led"; + linux,default-trigger = "netdev"; }; led@3 { gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; label = "wan_led"; + linux,default-trigger = "stmmac-0:00:link"; }; }; diff --git a/patch/kernel/archive/rockchip64-7.0/dt/rk3328-nanopi-r2-rev00.dts b/patch/kernel/archive/rockchip64-7.0/dt/rk3328-nanopi-r2-rev00.dts index 8ba95189c031..59265942fe01 100644 --- a/patch/kernel/archive/rockchip64-7.0/dt/rk3328-nanopi-r2-rev00.dts +++ b/patch/kernel/archive/rockchip64-7.0/dt/rk3328-nanopi-r2-rev00.dts @@ -64,11 +64,13 @@ led@2 { gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; label = "lan_led"; + linux,default-trigger = "netdev"; }; led@3 { gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; label = "wan_led"; + linux,default-trigger = "stmmac-0:00:link"; }; }; From 0e93d56114de9d62f880846cdc9c12f253ee3546 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Thu, 16 Oct 2025 21:58:12 +0200 Subject: [PATCH 16/43] nanopi-r3s: make 2nd Ethernet MAC address static by assigning it to the ethernet1 alias. U-Boot assigns an autogenerated MAC based on hardware parameters automatically. Signed-off-by: MichaIng --- .../archive/rockchip64-6.12/dt/rk3566-nanopi-r3s.dts | 1 + .../board-nanopi-r3s-static-mac.patch | 12 ++++++++++++ .../rockchip64-7.0/board-nanopi-r3s-static-mac.patch | 12 ++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.18/board-nanopi-r3s-static-mac.patch create mode 100644 patch/kernel/archive/rockchip64-7.0/board-nanopi-r3s-static-mac.patch diff --git a/patch/kernel/archive/rockchip64-6.12/dt/rk3566-nanopi-r3s.dts b/patch/kernel/archive/rockchip64-6.12/dt/rk3566-nanopi-r3s.dts index ea7648af0371..eb4a67209ce7 100644 --- a/patch/kernel/archive/rockchip64-6.12/dt/rk3566-nanopi-r3s.dts +++ b/patch/kernel/archive/rockchip64-6.12/dt/rk3566-nanopi-r3s.dts @@ -22,6 +22,7 @@ aliases { ethernet0 = &gmac1; + ethernet1 = &r8169; mmc0 = &sdhci; mmc1 = &sdmmc0; }; diff --git a/patch/kernel/archive/rockchip64-6.18/board-nanopi-r3s-static-mac.patch b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r3s-static-mac.patch new file mode 100644 index 000000000000..1fc0329f689a --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r3s-static-mac.patch @@ -0,0 +1,12 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts b/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts +index fb1f65c868833..a6c9318c6350a 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts +@@ -22,6 +22,7 @@ / { + + aliases { + ethernet0 = &gmac1; ++ ethernet1 = &r8169; + mmc0 = &sdhci; + mmc1 = &sdmmc0; + }; diff --git a/patch/kernel/archive/rockchip64-7.0/board-nanopi-r3s-static-mac.patch b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r3s-static-mac.patch new file mode 100644 index 000000000000..1fc0329f689a --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r3s-static-mac.patch @@ -0,0 +1,12 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts b/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts +index fb1f65c868833..a6c9318c6350a 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts +@@ -22,6 +22,7 @@ / { + + aliases { + ethernet0 = &gmac1; ++ ethernet1 = &r8169; + mmc0 = &sdhci; + mmc1 = &sdmmc0; + }; From 1e9b84522998875fe96f16bb001e5c87beb3ca3a Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 7 Jun 2025 17:24:55 +0200 Subject: [PATCH 17/43] nanopi-r4s: apply static MAC addresses for both Ethernet adapters U-Boot generates and assigns two MAC addresses for Rockchip SBCs with ethernet0 and ethernet1 aliases pointing to repsective device nodes. The PCIe child node for the PCIe Ethernet adapter with the needed "local-mac-address" property is added with this patch, as well as the respective alias. This commit additionally applies default Ethernet LED triggers. Signed-off-by: MichaIng --- .../board-nanopi-r4s-static-eth-mac.patch | 48 +++++++++++++++++++ .../board-nanopi-r4s-static-eth-mac.patch | 48 +++++++++++++++++++ .../board-nanopi-r4s-static-eth-mac.patch | 48 +++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.12/board-nanopi-r4s-static-eth-mac.patch create mode 100644 patch/kernel/archive/rockchip64-6.18/board-nanopi-r4s-static-eth-mac.patch create mode 100644 patch/kernel/archive/rockchip64-7.0/board-nanopi-r4s-static-eth-mac.patch diff --git a/patch/kernel/archive/rockchip64-6.12/board-nanopi-r4s-static-eth-mac.patch b/patch/kernel/archive/rockchip64-6.12/board-nanopi-r4s-static-eth-mac.patch new file mode 100644 index 000000000000..c7a3686b05e6 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/board-nanopi-r4s-static-eth-mac.patch @@ -0,0 +1,48 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +index 6a6b36c36ce21..55ff485dcb23b 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +@@ -21,6 +21,10 @@ / { + + /delete-node/ display-subsystem; + ++ aliases { ++ ethernet1 = &r8111; ++ }; ++ + gpio-leds { + pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; + +@@ -29,6 +33,7 @@ gpio-leds { + lan_led: led-lan { + gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>; + label = "green:lan"; ++ linux,default-trigger = "r8169-0-100:00:link"; + }; + + sys_led: led-sys { +@@ -40,6 +45,7 @@ sys_led: led-sys { + wan_led: led-wan { + gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; + label = "green:wan"; ++ linux,default-trigger = "stmmac-0:01:link"; + }; + }; + +@@ -76,6 +82,16 @@ &pcie0 { + max-link-speed = <1>; + num-lanes = <1>; + vpcie3v3-supply = <&vcc3v3_sys>; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8111: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pinctrl { diff --git a/patch/kernel/archive/rockchip64-6.18/board-nanopi-r4s-static-eth-mac.patch b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r4s-static-eth-mac.patch new file mode 100644 index 000000000000..97da1a108eee --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r4s-static-eth-mac.patch @@ -0,0 +1,48 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi +index 8d94d9f91a5c6..48b4e8eac7311 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi +@@ -19,6 +19,10 @@ + / { + /delete-node/ display-subsystem; + ++ aliases { ++ ethernet1 = &r8111; ++ }; ++ + gpio-leds { + pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; + +@@ -27,6 +31,7 @@ gpio-leds { + lan_led: led-lan { + gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>; + label = "green:lan"; ++ linux,default-trigger = "r8169-0-100:00:link"; + }; + + sys_led: led-sys { +@@ -38,6 +43,7 @@ sys_led: led-sys { + wan_led: led-wan { + gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; + label = "green:wan"; ++ linux,default-trigger = "stmmac-0:01:link"; + }; + }; + +@@ -74,6 +80,16 @@ &pcie0 { + max-link-speed = <1>; + num-lanes = <1>; + vpcie3v3-supply = <&vcc3v3_sys>; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8111: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pinctrl { diff --git a/patch/kernel/archive/rockchip64-7.0/board-nanopi-r4s-static-eth-mac.patch b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r4s-static-eth-mac.patch new file mode 100644 index 000000000000..97da1a108eee --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r4s-static-eth-mac.patch @@ -0,0 +1,48 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi +index 8d94d9f91a5c6..48b4e8eac7311 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi +@@ -19,6 +19,10 @@ + / { + /delete-node/ display-subsystem; + ++ aliases { ++ ethernet1 = &r8111; ++ }; ++ + gpio-leds { + pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; + +@@ -27,6 +31,7 @@ gpio-leds { + lan_led: led-lan { + gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>; + label = "green:lan"; ++ linux,default-trigger = "r8169-0-100:00:link"; + }; + + sys_led: led-sys { +@@ -38,6 +43,7 @@ sys_led: led-sys { + wan_led: led-wan { + gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; + label = "green:wan"; ++ linux,default-trigger = "stmmac-0:01:link"; + }; + }; + +@@ -74,6 +80,16 @@ &pcie0 { + max-link-speed = <1>; + num-lanes = <1>; + vpcie3v3-supply = <&vcc3v3_sys>; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8111: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pinctrl { From b4803ba14c341e09091d7ebb315b04fbc41c4931 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Fri, 30 May 2025 22:29:12 +0200 Subject: [PATCH 18/43] nanopi-r5c: apply static MAC addresses for both Ethernet adapters U-Boot generates and assigns two MAC addresses for Rockchip SBCs with ethernet0 and ethernet1 aliases pointing to repsective device nodes. The PCIe child nodes for both 2.5 Gbit Ethernet adapters with the needed "local-mac-address" properties are added with this patch, as well as the respective aliases. This commit applies as well default Ethernet LED triggers. Signed-off-by: MichaIng --- .../board-nanopi-r5c-static-eth-mac.patch | 66 +++++++++++++++++++ .../board-nanopi-r5c-static-eth-mac.patch | 66 +++++++++++++++++++ .../board-nanopi-r5c-static-eth-mac.patch | 66 +++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.12/board-nanopi-r5c-static-eth-mac.patch create mode 100644 patch/kernel/archive/rockchip64-6.18/board-nanopi-r5c-static-eth-mac.patch create mode 100644 patch/kernel/archive/rockchip64-7.0/board-nanopi-r5c-static-eth-mac.patch diff --git a/patch/kernel/archive/rockchip64-6.12/board-nanopi-r5c-static-eth-mac.patch b/patch/kernel/archive/rockchip64-6.12/board-nanopi-r5c-static-eth-mac.patch new file mode 100644 index 000000000000..f914b32b194d --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/board-nanopi-r5c-static-eth-mac.patch @@ -0,0 +1,66 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts +index c718b8dbb9c6b..58d893b87d121 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts +@@ -13,6 +13,11 @@ / { + model = "FriendlyElec NanoPi R5C"; + compatible = "friendlyarm,nanopi-r5c", "rockchip,rk3568"; + ++ aliases { ++ ethernet0 = &r8125_1; ++ ethernet1 = &r8125_2; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; +@@ -34,6 +34,7 @@ gpio-leds { + led-lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "r8169-1-100:00:link"; + }; + +@@ -47,6 +48,7 @@ power_led: led-power { + led-wan { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "r8169-2-100:00:link"; + }; + +@@ -70,6 +75,16 @@ &pcie3x1 { + reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_1: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie3x2 { +@@ -77,6 +92,16 @@ &pcie3x2 { + reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_2: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pinctrl { diff --git a/patch/kernel/archive/rockchip64-6.18/board-nanopi-r5c-static-eth-mac.patch b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r5c-static-eth-mac.patch new file mode 100644 index 000000000000..f914b32b194d --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r5c-static-eth-mac.patch @@ -0,0 +1,66 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts +index c718b8dbb9c6b..58d893b87d121 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts +@@ -13,6 +13,11 @@ / { + model = "FriendlyElec NanoPi R5C"; + compatible = "friendlyarm,nanopi-r5c", "rockchip,rk3568"; + ++ aliases { ++ ethernet0 = &r8125_1; ++ ethernet1 = &r8125_2; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; +@@ -34,6 +34,7 @@ gpio-leds { + led-lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "r8169-1-100:00:link"; + }; + +@@ -47,6 +48,7 @@ power_led: led-power { + led-wan { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "r8169-2-100:00:link"; + }; + +@@ -70,6 +75,16 @@ &pcie3x1 { + reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_1: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie3x2 { +@@ -77,6 +92,16 @@ &pcie3x2 { + reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_2: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pinctrl { diff --git a/patch/kernel/archive/rockchip64-7.0/board-nanopi-r5c-static-eth-mac.patch b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r5c-static-eth-mac.patch new file mode 100644 index 000000000000..f914b32b194d --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r5c-static-eth-mac.patch @@ -0,0 +1,66 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts +index c718b8dbb9c6b..58d893b87d121 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts +@@ -13,6 +13,11 @@ / { + model = "FriendlyElec NanoPi R5C"; + compatible = "friendlyarm,nanopi-r5c", "rockchip,rk3568"; + ++ aliases { ++ ethernet0 = &r8125_1; ++ ethernet1 = &r8125_2; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; +@@ -34,6 +34,7 @@ gpio-leds { + led-lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "r8169-1-100:00:link"; + }; + +@@ -47,6 +48,7 @@ power_led: led-power { + led-wan { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "r8169-2-100:00:link"; + }; + +@@ -70,6 +75,16 @@ &pcie3x1 { + reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_1: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie3x2 { +@@ -77,6 +92,16 @@ &pcie3x2 { + reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_2: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pinctrl { From 9890bb8b78e76b868a30a9f20d606bad1cb4f1ea Mon Sep 17 00:00:00 2001 From: MichaIng Date: Fri, 30 May 2025 00:53:29 +0200 Subject: [PATCH 19/43] nanopi-r5s: apply static MAC addresses for all 3 Ethernet adapters U-Boot assigns the variables eth(0)addr, eth1addr, eth2addr etc as MAC addresses to device tree aliases ethernet0, ethernet1, ethernet2 etc. For Rockchip SBCs, it generates only ethaddr and eth1addr so far. To support 3 static MAC addresses for the NanoPi R5S, it needs to generate eth2addr. This is archived with a U-Boot patch, to derive eth2addr the same way like eth1addr, but inverting the 2nd last bit instead. With a kernel patch, PCIe child nodes with the needed "local-mac-address" attributes are added to respective PCIe bridge nodes, and added as ethernet1 and ethernet2 aliases respectively. In sum: U-Boot additionally generates a valid eth2addr, and additionally assigns eth1addr and eth2addr to the now existing ethernet1 and ethernet2 aliases, pointing to the 2.5 Gbit Ethernet device nodes. This commit applies as well default Ethernet LED triggers. Signed-off-by: MichaIng --- .../board-nanopi-r5s-static-eth-mac.patch | 71 +++++++++++++++++++ .../board-nanopi-r5s-static-eth-mac.patch | 71 +++++++++++++++++++ .../board-nanopi-r5s-static-eth-mac.patch | 71 +++++++++++++++++++ .../board_nanopi-r5s/0003-mac-ethernet2.patch | 15 ++++ 4 files changed, 228 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.12/board-nanopi-r5s-static-eth-mac.patch create mode 100644 patch/kernel/archive/rockchip64-6.18/board-nanopi-r5s-static-eth-mac.patch create mode 100644 patch/kernel/archive/rockchip64-7.0/board-nanopi-r5s-static-eth-mac.patch create mode 100644 patch/u-boot/v2024.04/board_nanopi-r5s/0003-mac-ethernet2.patch diff --git a/patch/kernel/archive/rockchip64-6.12/board-nanopi-r5s-static-eth-mac.patch b/patch/kernel/archive/rockchip64-6.12/board-nanopi-r5s-static-eth-mac.patch new file mode 100644 index 000000000000..65e9c3ecb24c --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/board-nanopi-r5s-static-eth-mac.patch @@ -0,0 +1,71 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts +index b6ad8328c7ebc..3d68350d87699 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts +@@ -15,6 +15,8 @@ / { + + aliases { + ethernet0 = &gmac0; ++ ethernet1 = &r8125_1; ++ ethernet2 = &r8125_2; + }; + + gpio-leds { +@@ -26,6 +28,7 @@ led-lan1 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "r8169-0-100:00:link"; + }; + +@@ -33,6 +36,7 @@ led-lan2 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + gpios = <&gpio3 RK_PD7 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "r8169-1-100:00:link"; + }; + +@@ -46,6 +50,7 @@ power_led: led-power { + led-wan { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "stmmac-0:01:link"; + }; + }; +@@ -86,6 +91,16 @@ &pcie2x1 { + num-lanes = <1>; + reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_1: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie30phy { +@@ -98,6 +113,16 @@ &pcie3x1 { + reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_2: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie3x2 { diff --git a/patch/kernel/archive/rockchip64-6.18/board-nanopi-r5s-static-eth-mac.patch b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r5s-static-eth-mac.patch new file mode 100644 index 000000000000..f6e328b6779b --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r5s-static-eth-mac.patch @@ -0,0 +1,71 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts +index 718d1a2da8e56..09dedd1d21efa 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts +@@ -15,6 +15,8 @@ / { + + aliases { + ethernet0 = &gmac0; ++ ethernet1 = &r8125_1; ++ ethernet2 = &r8125_2; + }; + + gpio-keys { +@@ -42,6 +44,7 @@ led-lan1 { + function-enumerator = <1>; + gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>; + label = "LAN-1"; ++ linux,default-trigger = "r8169-0-100:00:link"; + }; + + led-lan2 { +@@ -51,6 +54,7 @@ led-lan2 { + function-enumerator = <2>; + gpios = <&gpio3 RK_PD7 GPIO_ACTIVE_HIGH>; + label = "LAN-2"; ++ linux,default-trigger = "r8169-1-100:00:link"; + }; + + power_led: led-sys { +@@ -67,6 +71,7 @@ led-wan { + function = LED_FUNCTION_WAN; + gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; + label = "WAN"; ++ linux,default-trigger = "stmmac-0:01:link"; + }; + }; + }; +@@ -107,6 +112,16 @@ &pcie2x1 { + num-lanes = <1>; + reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_1: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie30phy { +@@ -119,6 +134,16 @@ &pcie3x1 { + reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_2: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie3x2 { diff --git a/patch/kernel/archive/rockchip64-7.0/board-nanopi-r5s-static-eth-mac.patch b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r5s-static-eth-mac.patch new file mode 100644 index 000000000000..f6e328b6779b --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r5s-static-eth-mac.patch @@ -0,0 +1,71 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts +index 718d1a2da8e56..09dedd1d21efa 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts +@@ -15,6 +15,8 @@ / { + + aliases { + ethernet0 = &gmac0; ++ ethernet1 = &r8125_1; ++ ethernet2 = &r8125_2; + }; + + gpio-keys { +@@ -42,6 +44,7 @@ led-lan1 { + function-enumerator = <1>; + gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>; + label = "LAN-1"; ++ linux,default-trigger = "r8169-0-100:00:link"; + }; + + led-lan2 { +@@ -51,6 +54,7 @@ led-lan2 { + function-enumerator = <2>; + gpios = <&gpio3 RK_PD7 GPIO_ACTIVE_HIGH>; + label = "LAN-2"; ++ linux,default-trigger = "r8169-1-100:00:link"; + }; + + power_led: led-sys { +@@ -67,6 +71,7 @@ led-wan { + function = LED_FUNCTION_WAN; + gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; + label = "WAN"; ++ linux,default-trigger = "stmmac-0:01:link"; + }; + }; + }; +@@ -107,6 +112,16 @@ &pcie2x1 { + num-lanes = <1>; + reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_1: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie30phy { +@@ -119,6 +134,16 @@ &pcie3x1 { + reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ r8125_2: pcie@1,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie3x2 { diff --git a/patch/u-boot/v2024.04/board_nanopi-r5s/0003-mac-ethernet2.patch b/patch/u-boot/v2024.04/board_nanopi-r5s/0003-mac-ethernet2.patch new file mode 100644 index 000000000000..441613ec053e --- /dev/null +++ b/patch/u-boot/v2024.04/board_nanopi-r5s/0003-mac-ethernet2.patch @@ -0,0 +1,15 @@ +diff --git a/arch/arm/mach-rockchip/misc.c b/arch/arm/mach-rockchip/misc.c +index 7d03f0c2b67..4bb00d9a73a 100644 +--- a/arch/arm/mach-rockchip/misc.c ++++ b/arch/arm/mach-rockchip/misc.c +@@ -56,6 +56,10 @@ int rockchip_setup_macaddr(void) + /* Make a valid MAC address for ethernet1 */ + mac_addr[5] ^= 0x01; + eth_env_set_enetaddr("eth1addr", mac_addr); ++ ++ /* Make a valid MAC address for ethernet2 */ ++ mac_addr[5] ^= 0x03; ++ eth_env_set_enetaddr("eth2addr", mac_addr); + #endif + return 0; + } From 977822b9cdf1ac19f9bb25e50beab2ec52c37ef3 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 16 Dec 2025 17:55:18 +0100 Subject: [PATCH 20/43] rockchip64: add AIC8800 SDIO driver Signed-off-by: MichaIng --- .../drv-add-aic8800-sdio.patch | 90985 ++++++++++++++++ .../drv-add-aic8800-sdio.patch | 90985 ++++++++++++++++ .../rockchip64-7.0/drv-add-aic8800-sdio.patch | 90985 ++++++++++++++++ 3 files changed, 272955 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.12/drv-add-aic8800-sdio.patch create mode 100644 patch/kernel/archive/rockchip64-6.18/drv-add-aic8800-sdio.patch create mode 100644 patch/kernel/archive/rockchip64-7.0/drv-add-aic8800-sdio.patch diff --git a/patch/kernel/archive/rockchip64-6.12/drv-add-aic8800-sdio.patch b/patch/kernel/archive/rockchip64-6.12/drv-add-aic8800-sdio.patch new file mode 100644 index 000000000000..673ae0921e8f --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/drv-add-aic8800-sdio.patch @@ -0,0 +1,90985 @@ +diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig +index c6599594dc99..81a95a3a4e9a 100644 +--- a/drivers/net/wireless/Kconfig ++++ b/drivers/net/wireless/Kconfig +@@ -19,6 +19,7 @@ menuconfig WLAN + if WLAN + + source "drivers/net/wireless/admtek/Kconfig" ++source "drivers/net/wireless/aic8800_sdio/Kconfig" + source "drivers/net/wireless/ath/Kconfig" + source "drivers/net/wireless/atmel/Kconfig" + source "drivers/net/wireless/broadcom/Kconfig" +diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile +index e1c4141c6004..6837a10805ff 100644 +--- a/drivers/net/wireless/Makefile ++++ b/drivers/net/wireless/Makefile +@@ -4,6 +4,7 @@ + # + + obj-$(CONFIG_WLAN_VENDOR_ADMTEK) += admtek/ ++obj-$(CONFIG_SPARD_WLAN_SUPPORT) += aic8800_sdio/ + obj-$(CONFIG_WLAN_VENDOR_ATH) += ath/ + obj-$(CONFIG_WLAN_VENDOR_ATMEL) += atmel/ + obj-$(CONFIG_WLAN_VENDOR_BROADCOM) += broadcom/ +diff --git a/drivers/net/wireless/aic8800_sdio/Kconfig b/drivers/net/wireless/aic8800_sdio/Kconfig +new file mode 100644 +index 000000000000..e12a89df7899 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/Kconfig +@@ -0,0 +1,17 @@ ++config AIC_WLAN_SUPPORT ++ bool "AIC wireless Support" ++ default y ++ help ++ This is support for aic wireless chip. ++ ++config AIC_FW_PATH ++ depends on AIC_WLAN_SUPPORT ++ string "Firmware & config file path" ++ default "/lib/firmware/aic8800/SDIO/aic8800D80" ++ help ++ Path to the firmware & config file. ++ ++if AIC_WLAN_SUPPORT ++source "drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig" ++source "drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig" ++endif +diff --git a/drivers/net/wireless/aic8800_sdio/Makefile b/drivers/net/wireless/aic8800_sdio/Makefile +new file mode 100644 +index 000000000000..6f02ee9570cd +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/Makefile +@@ -0,0 +1,92 @@ ++CONFIG_AIC8800_BTLPM_SUPPORT := m ++CONFIG_AIC8800_WLAN_SUPPORT := m ++CONFIG_AIC_WLAN_SUPPORT := m ++ ++obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) += aic8800_btlpm/ ++obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/ ++obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800_bsp/ ++ ++MAKEFLAGS +=-j$(shell nproc) ++ ++########## config option ########## ++export CONFIG_USE_FW_REQUEST = n ++export CONFIG_PREALLOC_RX_SKB = y ++export CONFIG_PREALLOC_TXQ = y ++export CONFIG_OOB = n ++export CONFIG_GPIO_WAKEUP = n ++export CONFIG_RESV_MEM_SUPPORT = y ++################################### ++ ++########## Platform support list ########## ++export CONFIG_PLATFORM_ROCKCHIP = n ++export CONFIG_PLATFORM_ROCKCHIP2 = n ++export CONFIG_PLATFORM_ALLWINNER = n ++export CONFIG_PLATFORM_AMLOGIC = n ++export CONFIG_PLATFORM_UBUNTU = y ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ARCH = arm64 ++KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-y += -DANDROID_PLATFORM ++ccflags-y += -DCONFIG_PLATFORM_ROCKCHIP ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++KDIR := /home/yaya/E/Rockchip/3126/Android6/kernel ++ARCH ?= arm ++CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android5/rk3288_JHY/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- ++ccflags-y += -DANDROID_PLATFORM ++ccflags-y += -DCONFIG_PLATFORM_ROCKCHIP2 ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++KDIR = /home/yaya/E/Allwinner/A133/Android10/linux-4.9 ++ARCH = arm64 ++CROSS_COMPILE = /home/yaya/E/Allwinner/r818/Android10/lichee/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++export CONFIG_SUPPORT_LPM = y ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ARCH = arm ++CROSS_COMPILE = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel- ++KDIR = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/out/target/product/u202/obj/KERNEL_OBJ/ ++ccflags-y += -DANDROID_PLATFORM ++export CONFIG_SUPPORT_LPM = y ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++KDIR = /lib/modules/$(shell uname -r)/build ++PWD = $(shell pwd) ++KVER = $(shell uname -r) ++MODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800 ++SUBARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/armv.l/arm/ -e s/aarch64/arm64/) ++ARCH ?= $(SUBARCH) ++CROSS_COMPILE ?= ++endif ++########################################### ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 aic8800_bsp/aic8800_bsp.ko $(MODDESTDIR)/ ++ install -p -m 644 aic8800_fdrv/aic8800_fdrv.ko $(MODDESTDIR)/ ++ install -p -m 644 aic8800_btlpm/aic8800_btlpm.ko $(MODDESTDIR)/ ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/aic8800_bsp.ko ++ rm -rfv $(MODDESTDIR)/aic8800_fdrv.ko ++ rm -rfv $(MODDESTDIR)/aic8800_btlpm.ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ cd aic8800_bsp/;make clean;cd .. ++ cd aic8800_fdrv/;make clean;cd .. ++ cd aic8800_btlpm/;make clean;cd .. ++ rm -rf modules.order Module.symvers .modules.order.cmd .Module.symvers.cmd .tmp_versions/ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore +new file mode 100644 +index 000000000000..c3c2d151e157 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile +new file mode 100644 +index 000000000000..3e3849d0652a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile +@@ -0,0 +1,155 @@ ++CONFIG_SDIO_SUPPORT := y ++CONFIG_SDIO_PWRCTRL := y ++CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800/SDIO/aic8800D80" ++export CONFIG_AIC_FW_PATH ++ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\" ++ ++MODULE_NAME := aic8800_bsp ++ifeq ($(CONFIG_SDIO_SUPPORT), y) ++ccflags-y += -DAICWF_SDIO_SUPPORT ++ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL ++endif ++ ++CONFIG_GPIO_WAKEUP ?= n ++CONFIG_M2D_OTA_AUTO_SUPPORT = n ++CONFIG_M2D_OTA_LZMA_SUPPORT = n ++CONFIG_LINK_DET_5G = y ++CONFIG_MCU_MESSAGE = n ++CONFIG_FIRMWARE_ARRAY = n ++# Need to set fw path in BOARD_KERNEL_CMDLINE ++CONFIG_USE_FW_REQUEST ?= n ++CONFIG_FDRV_NO_REG_SDIO = n ++CONFIG_VRF_DCDC_MODE = y ++CONFIG_OOB ?= n ++CONFIG_PREALLOC_TXQ = y ++CONFIG_DPD = y ++CONFIG_FORCE_DPD_CALIB = y ++CONFIG_LOFT_CALIB = n ++CONFIG_EXT_FEM_8800DCDW = n ++CONFIG_RESV_MEM_SUPPORT ?= y ++CONFIG_AMSDU_RX = y ++CONFIG_IRQ_FALL ?= n ++CONFIG_SDIO_BT = n ++CONFIG_RADAR_OR_IR_DETECT =n ++CONFIG_FOR_IPCAM = n ++ ++ifeq ($(CONFIG_EXT_FEM_8800DCDW), y) ++CONFIG_DPD = n ++CONFIG_FORCE_DPD_CALIB = n ++CONFIG_LOFT_CALIB = y ++endif ++ ++ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP ++ccflags-$(CONFIG_M2D_OTA_AUTO_SUPPORT) += -DCONFIG_M2D_OTA_AUTO_SUPPORT ++ccflags-$(CONFIG_M2D_OTA_LZMA_SUPPORT) += -DCONFIG_M2D_OTA_LZMA_SUPPORT ++ccflags-$(CONFIG_LINK_DET_5G) += -DCONFIG_LINK_DET_5G ++ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE ++ccflags-$(CONFIG_FIRMWARE_ARRAY) += -DCONFIG_FIRMWARE_ARRAY ++ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST ++ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO ++ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE ++ccflags-$(CONFIG_OOB) += -DCONFIG_OOB ++ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ ++ccflags-$(CONFIG_DPD) += -DCONFIG_DPD ++ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD ++ccflags-$(CONFIG_LOFT_CALIB) += -DCONFIG_LOFT_CALIB ++ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW ++ccflags-$(CONFIG_RESV_MEM_SUPPORT) += -DCONFIG_RESV_MEM_SUPPORT ++ccflags-$(CONFIG_AMSDU_RX) += -DCONFIG_AMSDU_RX ++ccflags-$(CONFIG_IRQ_FALL) += -DCONFIG_IRQ_FALL ++ccflags-$(CONFIG_SDIO_BT) += -DCONFIG_SDIO_BT ++ccflags-$(CONFIG_RADAR_OR_IR_DETECT) += -DCONFIG_RADAR_OR_IR_DETECT ++ccflags-$(CONFIG_FOR_IPCAM) += -DCONFIG_FOR_IPCAM ++ ++ ++obj-m := $(MODULE_NAME).o ++$(MODULE_NAME)-y := \ ++ aic8800dc_compat.o \ ++ aic8800d80_compat.o \ ++ aic_bsp_main.o \ ++ aic_bsp_driver.o \ ++ aicsdio.o \ ++ aicsdio_txrxif.o \ ++ md5.o ++ ++$(MODULE_NAME)-$(CONFIG_PREALLOC_TXQ) += aicwf_txq_prealloc.o ++ ++ifeq ($(CONFIG_FIRMWARE_ARRAY),y) ++$(MODULE_NAME)-y += aicwf_firmware_array.o ++endif ++ ++########## Platform support list ########## ++CONFIG_PLATFORM_ROCKCHIP ?= n ++CONFIG_PLATFORM_ROCKCHIP2 ?= n ++CONFIG_PLATFORM_ALLWINNER ?=n ++CONFIG_PLATFORM_INGENIC_T20 ?= n ++CONFIG_PLATFORM_AMLOGIC ?= n ++CONFIG_PLATFORM_UBUNTU ?= y ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 ++ARCH ?= arm64 ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/ ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ++ ++endif ++ ++ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y) ++KDIR ?= /home/yaya/E/T40/kernel ++ARCH ?= mips ++CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC ++KDIR ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/out/target/product/u202/obj/KERNEL_OBJ/ ++ARCH ?= arm ++CROSS_COMPILE ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++ccflags-$(CONFIG_PLATFORM_UBUNTU) += -DCONFIG_PLATFORM_UBUNTU ++KDIR ?= /lib/modules/$(shell uname -r)/build ++PWD ?= $(shell pwd) ++KVER ?= $(shell uname -r) ++MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ++ARCH ?= x86_64 ++CROSS_COMPILE ?= ++ ++ifeq ($(CONFIG_AW_BSP), y) ++ccflags-y += -DCONFIG_PLATFORM_ALLWINNER ++endif ++ ++endif ++########################################### ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk built-in.a ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c +new file mode 100644 +index 000000000000..847da05ad75c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c +@@ -0,0 +1,267 @@ ++#include "aic8800d80_compat.h" ++#include "aic_bsp_driver.h" ++ ++extern struct aicbsp_info_t aicbsp_info; ++extern int adap_test; ++ ++typedef u32 (*array2_tbl_t)[2]; ++ ++#define AIC_PATCH_MAGIG_NUM 0x48435450 // "PTCH" ++#define AIC_PATCH_MAGIG_NUM_2 0x50544348 // "HCTP" ++#define AIC_PATCH_BLOCK_MAX 4 ++ ++typedef struct { ++ uint32_t magic_num; ++ uint32_t pair_start; ++ uint32_t magic_num_2; ++ uint32_t pair_count; ++ uint32_t block_dst[AIC_PATCH_BLOCK_MAX]; ++ uint32_t block_src[AIC_PATCH_BLOCK_MAX]; ++ uint32_t block_size[AIC_PATCH_BLOCK_MAX]; // word count ++} aic_patch_t; ++ ++#define AIC_PATCH_OFST(mem) ((size_t) &((aic_patch_t *)0)->mem) ++#define AIC_PATCH_ADDR(mem) ((u32)(aic_patch_str_base + AIC_PATCH_OFST(mem))) ++ ++u32 aicbsp_syscfg_tbl_8800d80[][2] = { ++}; ++ ++int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev) ++{ ++ int syscfg_num = sizeof(aicbsp_syscfg_tbl_8800d80) / sizeof(u32) / 2; ++ int ret, cnt; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl_8800d80[cnt][0], aicbsp_syscfg_tbl_8800d80[cnt][1]); ++ if (ret) { ++ printk("%x write fail: %d\n", aicbsp_syscfg_tbl_8800d80[cnt][0], ret); ++ return ret; ++ } ++ } ++ return 0; ++} ++ ++ ++u32 adaptivity_patch_tbl_8800d80[][2] = { ++ {0x000C, 0x0000320A}, //linkloss_thd ++ {0x009C, 0x00000000}, //ac_param_conf ++ {0x0168, 0x00010000}, //tx_adaptivity_en ++}; ++ ++#define USER_PWROFST_COVER_CALIB_FLAG 0x01U ++#define USER_CHAN_MAX_TXPWR_EN_FLAG (0x01U << 1) ++#define USER_TX_USE_ANA_F_FLAG (0x01U << 2) ++#define USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG (0x01U << 3) ++ ++#define CFG_PWROFST_COVER_CALIB 1 ++#define CFG_USER_CHAN_MAX_TXPWR_EN 1 ++#define CFG_USER_TX_USE_ANA_F 0 ++#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE 0 ++ ++ ++#define CFG_USER_EXT_FLAGS_EN (CFG_PWROFST_COVER_CALIB || CFG_USER_CHAN_MAX_TXPWR_EN || CFG_USER_TX_USE_ANA_F || CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE) ++ ++u32 patch_tbl_8800d80[][2] = { ++ #ifdef USE_5G ++ {0x00b4, 0xf3010001}, ++ #else ++ {0x00b4, 0xf3010000}, ++ #endif ++#if defined(CONFIG_AMSDU_RX) ++ {0x170, 0x0100000a}, ++#endif ++#ifdef CONFIG_IRQ_FALL ++ {0x00000170, 0x0000010a}, //irqf ++#endif ++ ++ #if CFG_USER_EXT_FLAGS_EN ++ {0x0188, 0x00000000 ++ #if CFG_PWROFST_COVER_CALIB ++ | USER_PWROFST_COVER_CALIB_FLAG ++ #endif ++ #if CFG_USER_CHAN_MAX_TXPWR_EN ++ | USER_CHAN_MAX_TXPWR_EN_FLAG ++ #endif ++ #if CFG_USER_TX_USE_ANA_F ++ | USER_TX_USE_ANA_F_FLAG ++ #endif ++ #if CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE ++ | USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG ++ #endif ++ }, // user_ext_flags ++ #endif ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ {0x019c, 0x00000100}, //enable radar detect ++#endif ++}; ++ ++#ifdef CONFIG_OOB ++// for 8800d40/d80 map data1 isr to gpiob1 ++u32 gpio_cfg_tbl_8800d40d80[][2] = { ++ {0x40504084, 0x00000006}, ++ {0x40500040, 0x00000000}, ++ {0x40100030, 0x00000001}, ++ {0x40241020, 0x00000001}, ++ {0x40240030, 0x00000004}, ++ {0x40240020, 0x03020700}, ++}; ++#endif ++ ++int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev) ++{ ++#ifdef CONFIG_OOB ++ int ret, cnt; ++ int gpiocfg_num = sizeof(gpio_cfg_tbl_8800d40d80) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < gpiocfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, gpio_cfg_tbl_8800d40d80[cnt][0], gpio_cfg_tbl_8800d40d80[cnt][1]); ++ if (ret) { ++ printk("%x write fail: %d\n", gpio_cfg_tbl_8800d40d80[cnt][0], ret); ++ return ret; ++ } ++ } ++#endif ++ ++ return 0; ++} ++ ++#define NEW_PATCH_BUFFER_MAP 1 ++ ++int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev) ++{ ++ const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0198; ++ u32 aic_patch_addr; ++ u32 config_base, aic_patch_str_base; ++ #if (NEW_PATCH_BUFFER_MAP) ++ u32 patch_buff_addr, patch_buff_base, rd_version_addr, rd_version_val; ++ #endif ++ uint32_t start_addr = 0x0016F800; ++ u32 patch_addr = start_addr; ++ u32 patch_cnt = sizeof(patch_tbl_8800d80)/sizeof(u32)/2; ++ struct dbg_mem_read_cfm rd_patch_addr_cfm; ++ int ret = 0; ++ int cnt = 0; ++ //adap test ++ int adap_patch_cnt = 0; ++ ++ if (adap_test) { ++ printk("%s for adaptivity test \r\n", __func__); ++ adap_patch_cnt = sizeof(adaptivity_patch_tbl_8800d80)/sizeof(u32)/2; ++ } ++ ++ aic_patch_addr = rd_patch_addr + 8; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch rd fail\n"); ++ return ret; ++ } ++ ++ config_base = rd_patch_addr_cfm.memdata; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, aic_patch_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch str rd fail\n"); ++ return ret; ++ } ++ aic_patch_str_base = rd_patch_addr_cfm.memdata; ++ ++ #if (NEW_PATCH_BUFFER_MAP) ++ rd_version_addr = RAM_FMAC_FW_ADDR + 0x01C; ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_version_addr, &rd_patch_addr_cfm))) { ++ printk("version val[0x%x] rd fail: %d\n", rd_version_addr, ret); ++ return ret; ++ } ++ rd_version_val = rd_patch_addr_cfm.memdata; ++ printk("rd_version_val=%08X\n", rd_version_val); ++ sdiodev->fw_version_uint = rd_version_val; ++ if (rd_version_val > 0x06090100) { ++ patch_buff_addr = rd_patch_addr + 12; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, patch_buff_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch buf rd fail\n"); ++ return ret; ++ } ++ patch_buff_base = rd_patch_addr_cfm.memdata; ++ patch_addr = start_addr = patch_buff_base; ++ } ++ #endif ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num)); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num_2), AIC_PATCH_MAGIG_NUM_2); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num_2)); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_start), patch_addr); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_start)); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_count), patch_cnt + adap_patch_cnt); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_count)); ++ return ret; ++ } ++ ++ for (cnt = 0; cnt < patch_cnt; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl_8800d80[cnt][0]+config_base); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl_8800d80[cnt][1]); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ return ret; ++ } ++ } ++ ++ if (adap_test){ ++ int tmp_cnt = patch_cnt + adap_patch_cnt; ++ for (cnt = patch_cnt; cnt < tmp_cnt; cnt++) { ++ int tbl_idx = cnt - patch_cnt; ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, adaptivity_patch_tbl_8800d80[tbl_idx][0]+config_base); ++ if(ret) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, adaptivity_patch_tbl_8800d80[tbl_idx][1]); ++ if(ret) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ return ret; ++ } ++ } ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[0]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[0]), ret); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[1]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[1]), ret); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[2]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[2]), ret); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[3]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[3]), ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h +new file mode 100644 +index 000000000000..20956582620f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h +@@ -0,0 +1,24 @@ ++#ifndef _AIC8800D80_COMPAT_H_ ++#define _AIC8800D80_COMPAT_H_ ++ ++#include "aicsdio.h" ++/*typedef u32 (*array2_tbl_t)[2]; ++ ++typedef uint8_t u8_l; ++typedef int8_t s8_l; ++typedef bool bool_l; ++typedef uint16_t u16_l; ++typedef int16_t s16_l; ++typedef uint32_t u32_l; ++typedef int32_t s32_l; ++typedef uint64_t u64_l;*/ ++ ++int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev); ++int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev); ++int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev); ++ ++ ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c +new file mode 100644 +index 000000000000..8efd2b81e194 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c +@@ -0,0 +1,2633 @@ ++#include ++#include "aic8800dc_compat.h" ++#include "aic_bsp_driver.h" ++ ++u8 chip_sub_id = 0; ++u8 chip_mcu_id = 0; ++extern int testmode; ++ ++u32 syscfg_tbl_8800dc[][2] = { ++ {0x40500010, 0x00000004}, ++ {0x40500010, 0x00000006},//160m clk ++}; ++ ++u32 syscfg_tbl_8800dc_sdio_u01[][2] = { ++ {0x40030000, 0x00036724}, // loop forever after assert_err ++ {0x0011E800, 0xE7FE4070}, ++ {0x40030084, 0x0011E800}, ++ {0x40030080, 0x00000001}, ++ {0x4010001C, 0x00000000}, ++}; ++ ++u32 syscfg_tbl_8800dc_sdio_u02[][2] = { ++ {0x40030000, 0x00036DA4}, // loop forever after assert_err ++ {0x0011E800, 0xE7FE4070}, ++ {0x40030084, 0x0011E800}, ++ {0x40030080, 0x00000001}, ++ {0x4010001C, 0x00000000}, ++}; ++#ifdef CONFIG_OOB ++u32 oobcfg_tbl_8800dc_sdio_u02[][2] = { ++ {0x40504044, 0x2},//oob_enable ++ {0x40500060, 0x03020700}, ++ {0x40500040, 0}, ++ {0x40100030, 1}, ++ {0x40241020, 1}, ++ {0x402400f0, 0x340022}, ++}; ++#endif //CONFIG_OOB ++ ++ ++u32 syscfg_tbl_masked_8800dc[][3] = { ++ //#ifdef CONFIG_PMIC_SETTING ++ #if defined(CONFIG_VRF_DCDC_MODE) ++ {0x7000216C, (0x3 << 2), (0x1 << 2)}, // pmic_pmu_init ++ {0x700021BC, (0x3 << 2), (0x1 << 2)}, ++ {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, ++ {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x70002170, (0xF << 0), (0x1 << 0)}, ++ {0x70002190, (0x3F << 0), (24 << 0)}, ++ {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, ++ {0x700010A0, (0x1 << 11), (0x1 << 11)}, ++ {0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))}, ++ {0x70001038, (0x1 << 8), (0x1 << 8)}, ++ {0x70001094, (0x3 << 2), (0x0 << 2)}, ++ {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x1 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ {0x70001028, (0xf << 2), (0x1 << 2)}, ++ #else ++ {0x7000216C, (0x3 << 2), (0x1 << 2)}, // pmic_pmu_init ++ {0x700021BC, (0x3 << 2), (0x1 << 2)}, ++ {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, ++ {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x70002170, (0xF << 0), (0x1 << 0)}, ++ {0x70002190, (0x3F << 0), (24 << 0)}, ++ {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, ++ {0x700010A0, (0x1 << 11), (0x1 << 11)}, ++ {0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))}, ++ {0x70001038, (0x1 << 8), (0x1 << 8)}, ++ {0x70001094, (0x3 << 2), (0x0 << 2)}, ++ {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x0 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ {0x70001028, (0xf << 2), (0x1 << 2)}, ++ #endif ++ //#endif /* CONFIG_PMIC_SETTING */ ++ {0x00000000, 0x00000000, 0x00000000}, // last one ++}; ++ ++u32 syscfg_tbl_masked_8800dc_h[][3] = { ++ {0x7000216C, ((0x3 << 2) | (0x3 << 4)), ((0x2 << 2) | (0x2 << 4))}, // pmic_pmu_init ++ {0x70002138, (0xFF << 0), (0xFF << 0)}, ++ {0x7000213C, (0xFF << 0), (0xFF << 0)}, ++ {0x70002144, (0xFF << 0), (0xFF << 0)}, ++ {0x700021BC, (0x3 << 2), (0x1 << 2)}, ++ {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, ++ {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x70002170, (0xF << 0), (0x1 << 0)}, ++ {0x70002190, (0x3F << 0), (24 << 0)}, ++ {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, ++ {0x700010A0, (0x1 << 11), (0x1 << 11)}, ++ //{0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))}, ++ {0x70001038, (0x1 << 8), (0x1 << 8)}, ++ {0x70001094, (0x3 << 2), (0x0 << 2)}, ++ {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, ++ #if defined(CONFIG_VRF_DCDC_MODE) ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x1 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ #else ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x0 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ #endif ++ {0x70001028, (0xf << 2), (0x1 << 2)}, ++ ++ {0x00000000, 0x00000000, 0x00000000}, // last one ++}; ++ ++u32 syscfg_tbl_masked_8800dc_u01[][3] = { ++ //#ifdef CONFIG_PMIC_SETTING ++ {0x70001000, (0x1 << 16), (0x1 << 16)}, // for low temperature ++ {0x70001028, (0x1 << 6), (0x1 << 6)}, ++ {0x70001000, (0x1 << 16), (0x0 << 16)}, ++ //#endif /* CONFIG_PMIC_SETTING */ ++}; ++ ++u32 patch_tbl_wifisetting_8800dc_u01[][2] = ++{ ++ {0x010c,0x01001E01} ++}; ++ ++u32 patch_tbl_wifisetting_8800dc_u02[][2] = ++{ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ {0x0124,0x01011E01} ++#else ++ {0x0124,0x01001E01} ++#endif ++}; ++ ++ ++ ++uint32_t ldpc_cfg_ram[] = { ++#if 0//def CONFIG_FPGA_VERIFICATION ++ 0x00363638, ++ 0x1DF8F834, ++ 0x1DF8F834, ++ 0x1DF8F834, ++ 0x1DF8F834, ++ 0x002F2F31, ++ 0x1DF8F82C, ++ 0x1DF8F82C, ++ 0x1DF8F82C, ++ 0x1DF8F82C, ++ 0x00363639, ++ 0x1AA5F834, ++ 0x1AA5F834, ++ 0x1ADEF834, ++ 0x1ADEF834, ++ 0x003A3A3E, ++ 0x1578F436, ++ 0x1578F436, ++ 0x1578F436, ++ 0x15B6F436, ++ 0x003B3B40, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x003B3B41, ++ 0x1DC4F838, ++ 0x1DC4F838, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x003B3B40, ++ 0x1781F838, ++ 0x1781F838, ++ 0x1781F838, ++ 0x17C4F838, ++ 0x003B3B40, ++ 0x0E81F838, ++ 0x0E81F838, ++ 0x0E81F838, ++ 0x0E82F838, ++ 0x003F3F43, ++ 0x1A92F83D, ++ 0x1A92F83E, ++ 0x1A92F83D, ++ 0x1ADDF83D, ++ 0x00272729, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F843, ++ 0x1DF8F843, ++ 0x00272729, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F842, ++ 0x1DF8F842, ++ 0x00262628, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00252528, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00262628, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00242427, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x00232326, ++ 0x1DF8F821, ++ 0x1DF8F820, ++ 0x1DF8F820, ++ 0x1DF8F820, ++ 0x00262628, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00242427, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x001F1F21, ++ 0x1DF8F81D, ++ 0x1DF8F81D, ++ 0x1DF8F81D, ++ 0x1DF8F81D, ++ 0x00262643, ++ 0x1DF8F822, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x0018182B, ++ 0x1DF8F816, ++ 0x1DBDF815, ++ 0x1DF8F815, ++ 0x1DF8F815, ++ 0x0018182A, ++ 0x1195F836, ++ 0x1195F815, ++ 0x1195F815, ++ 0x1196F815, ++ 0x0028282C, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0027272C, ++ 0x1DF8F824, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x0082824A, ++ 0x1ADFF841, ++ 0x1ADDF822, ++ 0x1ADEF822, ++ 0x1ADFF822, ++ 0x003E3E40, ++ 0x09D1F81D, ++ 0x095BF81D, ++ 0x095BF81D, ++ 0x095BF81D, ++ 0x0029292D, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x0028282C, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0029292D, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x0028282E, ++ 0x1DF8F825, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0026262C, ++ 0x1DF8F823, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x0028282D, ++ 0x1DF8F825, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x00282852, ++ 0x1DF8F827, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0029294E, ++ 0x1DF8F823, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x00212143, ++ 0x1DF8F821, ++ 0x1DECF81D, ++ 0x1DF4F81D, ++ 0x1DF8F81D, ++ 0x0086864D, ++ 0x1CF0F844, ++ 0x1CEDF823, ++ 0x1CEFF822, ++ 0x1CF0F822, ++ 0x0047474D, ++ 0x1BE8F823, ++ 0x1BE8F823, ++ 0x1BE9F822, ++ 0x1BEAF822, ++ 0x0018182F, ++ 0x14B0F83C, ++ 0x14B0F814, ++ 0x14B0F814, ++ 0x14B0F814, ++ 0x00404040, ++ 0x0AE1F81E, ++ 0x0A61F81D, ++ 0x0A61F81D, ++ 0x0A61F81D, ++ 0x002C2C40, ++ 0x09555526, ++ 0x09555512, ++ 0x09555513, ++ 0x09555512, ++ 0x00181840, ++ 0x06333329, ++ 0x06333314, ++ 0x06333314, ++ 0x06333314, ++ 0x002B2B2F, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x002B2B32, ++ 0x1DF8F829, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x002A2A2F, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x002A2A57, ++ 0x1DF8F82B, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x00919152, ++ 0x1DF8F84B, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x004C4C51, ++ 0x1DF8F826, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x00444440, ++ 0x0CF8F820, ++ 0x0C6EF81F, ++ 0x0C6EF81F, ++ 0x0C6EF81F, ++ 0x00424240, ++ 0x0D75753E, ++ 0x0D75751E, ++ 0x0D75751E, ++ 0x0D75751E, ++ 0x00191940, ++ 0x0539392E, ++ 0x05393914, ++ 0x05393914, ++ 0x05393914, ++ 0x002F2F32, ++ 0x1AA5F82C, ++ 0x1AA5F82C, ++ 0x1ADEF82C, ++ 0x1ADEF82C, ++ 0x002F2F40, ++ 0x0C6EDE2C, ++ 0x0C6EDE2C, ++ 0x0C6EDE2C, ++ 0x0C6EDE2C, ++ 0x00323240, ++ 0x053BB62E, ++ 0x053BB62E, ++ 0x053BB62E, ++ 0x053BB62E, ++ 0x00333339, ++ 0x1DC4F82F, ++ 0x1DC4F82F, ++ 0x1DF8F82F, ++ 0x1DF8F82F, ++ 0x00333340, ++ 0x0E81F82F, ++ 0x0E81F82F, ++ 0x0E81F82F, ++ 0x0E82F82F, ++ 0x00333340, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x00404040, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x00363640, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x00404040, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x00292940, ++ 0x07484825, ++ 0x07484812, ++ 0x07484812, ++ 0x07484812, ++ 0x00404040, ++ 0x07343428, ++ 0x07343414, ++ 0x07343414, ++ 0x07343414, ++ 0x00404040, ++ 0x0538382A, ++ 0x05383814, ++ 0x05383814, ++ 0x05383814, ++ 0x00404040, ++ 0x05292914, ++ 0x05292909, ++ 0x05292909, ++ 0x05292909, ++ 0x000B0B40, ++ 0x02111108, ++ 0x0211110E, ++ 0x02111108, ++ 0x02111108, ++ 0x00404040, ++ 0x063E3E2E, ++ 0x063E3E15, ++ 0x063E3E14, ++ 0x063E3E14, ++ 0x00404040, ++ 0x062E2E14, ++ 0x062E2E09, ++ 0x062E2E09, ++ 0x062E2E09, ++ 0x000B0B40, ++ 0x02131308, ++ 0x0213130F, ++ 0x02131308, ++ 0x02131308 ++#else ++ 0x00767679, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x006E6E72, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x0076767B, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x007E7E85, ++ 0x1DF4F876, ++ 0x1DF4F876, ++ 0x1DF4F876, ++ 0x1DF8F876, ++ 0x0081818A, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x0081818D, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x0081818A, ++ 0x1DF8F87B, ++ 0x1DF8F87C, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x007E7E40, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x008B8B92, ++ 0x1DF8F887, ++ 0x1DF8F889, ++ 0x1DF8F887, ++ 0x1DF8F887, ++ 0x00515155, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F889, ++ 0x1DF8F889, ++ 0x00515154, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F888, ++ 0x1DF8F888, ++ 0x004F4F53, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004F4F53, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004F4F53, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004E4E53, ++ 0x1DF8F849, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x004D4D52, ++ 0x1DF8F847, ++ 0x1DF8F847, ++ 0x1DF8F847, ++ 0x1DF8F847, ++ 0x004F4F55, ++ 0x1DF8F84B, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004E4E53, ++ 0x1DF8F849, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x0049494D, ++ 0x1DF8F844, ++ 0x1DF8F844, ++ 0x1DF8F844, ++ 0x1DF8F844, ++ 0x0051518F, ++ 0x1DF8F849, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x00424277, ++ 0x1DF8F83F, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x00424275, ++ 0x1DF8F89E, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x0055555C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x0053535C, ++ 0x1DF8F84C, ++ 0x1DF8F84B, ++ 0x1DF8F84B, ++ 0x1DF8F84B, ++ 0x00F8F89E, ++ 0x1DF8F88C, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x00898940, ++ 0x18F8F846, ++ 0x18CFF845, ++ 0x18CFF844, ++ 0x18CFF844, ++ 0x0056565F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x0055555E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x0056565F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x00555561, ++ 0x1DF8F850, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x0053535F, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x0055555F, ++ 0x1DF8F84F, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x005555AA, ++ 0x1DF8F854, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x005959A6, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x004F4F9B, ++ 0x1DF8F84E, ++ 0x1DF8F846, ++ 0x1DF8F846, ++ 0x1DF8F846, ++ 0x00F8F8A5, ++ 0x1DF8F894, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x009898A4, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x00464686, ++ 0x1DF8F8B3, ++ 0x1DF8F83D, ++ 0x1DF8F83D, ++ 0x1DF8F83D, ++ 0x008E8E40, ++ 0x1AF8F848, ++ 0x1ADFF848, ++ 0x1ADFF846, ++ 0x1ADFF846, ++ 0x007F7F40, ++ 0x18D2D275, ++ 0x18D2D23A, ++ 0x18D2D23A, ++ 0x18D2D239, ++ 0x00454540, ++ 0x0F868664, ++ 0x0F86863E, ++ 0x0F86863D, ++ 0x0F86863D, ++ 0x005C5C64, ++ 0x1DF8F856, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x005B5B68, ++ 0x1DF8F858, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x005A5A64, ++ 0x1DF8F855, ++ 0x1DF8F854, ++ 0x1DF8F854, ++ 0x1DF8F854, ++ 0x005A5AB5, ++ 0x1DF8F85B, ++ 0x1DF8F855, ++ 0x1DF8F854, ++ 0x1DF8F854, ++ 0x00F8F8B0, ++ 0x1DF8F8A3, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x00A4A4AE, ++ 0x1DF8F854, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x009A9A40, ++ 0x1DF8F84E, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x009C9C40, ++ 0x1DF8F895, ++ 0x1DF8F849, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x00494940, ++ 0x1197976F, ++ 0x11979742, ++ 0x11979741, ++ 0x11979741, ++ 0x006E6E74, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x006E6E40, ++ 0x1ADEF869, ++ 0x1ADEF869, ++ 0x1ADEF869, ++ 0x1ADEF869, ++ 0x00757540, ++ 0x0D78F86E, ++ 0x0D78F86E, ++ 0x0D78F86E, ++ 0x0D79F86E, ++ 0x00787885, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x00787840, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x00787840, ++ 0x0E81F873, ++ 0x0E81F873, ++ 0x0E81F873, ++ 0x0E82F873, ++ 0x00404040, ++ 0x0E82F873, ++ 0x0E82F873, ++ 0x0E82F873, ++ 0x0E82F873, ++ 0x00818140, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x00404040, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x00737340, ++ 0x14B2B26B, ++ 0x14B2B235, ++ 0x14B2B235, ++ 0x14B2B235, ++ 0x00404040, ++ 0x0E828260, ++ 0x0E82823D, ++ 0x0E82823C, ++ 0x0E82823C, ++ 0x00404040, ++ 0x0F8B8B66, ++ 0x0F8B8B3F, ++ 0x0F8B8B3D, ++ 0x0F8B8B3D, ++ 0x00404040, ++ 0x0B68683D, ++ 0x0B68681E, ++ 0x0B68681E, ++ 0x0B68681E, ++ 0x00222240, ++ 0x06434318, ++ 0x06434329, ++ 0x06434318, ++ 0x06434318, ++ 0x00404040, ++ 0x129D9D72, ++ 0x129D9D43, ++ 0x129D9D41, ++ 0x129D9D41, ++ 0x00404040, ++ 0x0D757542, ++ 0x0D757520, ++ 0x0D757520, ++ 0x0D757520, ++ 0x00232340, ++ 0x084C4C19, ++ 0x084C4C2C, ++ 0x084C4C19, ++ 0x084C4C19 ++#endif ++}; ++ ++uint32_t agc_cfg_ram[] = { ++ 0x20000000, ++ 0x0400000E, ++ 0x3000200E, ++ 0x5B000000, ++ 0x0400004B, ++ 0x3000008E, ++ 0x32000000, ++ 0x0400007B, ++ 0x40000000, ++ 0xF8000026, ++ 0x04000011, ++ 0x4819008E, ++ 0x9C000020, ++ 0x08000191, ++ 0x38008000, ++ 0x0A000000, ++ 0x08104411, ++ 0x38018000, ++ 0x0C004641, ++ 0x08D00014, ++ 0x30000000, ++ 0x01000000, ++ 0x04000017, ++ 0x30000000, ++ 0x3C000000, ++ 0x0400001A, ++ 0x38020000, ++ 0x40000001, ++ 0x0800001D, ++ 0x3808008E, ++ 0x14000050, ++ 0x08000020, ++ 0x4000008E, ++ 0xA400007B, ++ 0x00000101, ++ 0x3000339F, ++ 0x41000700, ++ 0x04104420, ++ 0x90000000, ++ 0x49000000, ++ 0xF00E842F, ++ 0xEC0E842C, ++ 0xEC0E842C, ++ 0x04000032, ++ 0x30000000, ++ 0x48000101, ++ 0x04000032, ++ 0x30000000, ++ 0x48000202, ++ 0x04000032, ++ 0x30000000, ++ 0x46000000, ++ 0x04000011, ++ 0x58010006, ++ 0x3D040472, ++ 0xDC204439, ++ 0x081DD4D2, ++ 0x480A0006, ++ 0xDC2044DC, ++ 0x081DD43C, ++ 0x38050004, ++ 0x0EF1F1C3, ++ 0x342044DC, ++ 0x30000000, ++ 0x01000000, ++ 0x04000042, ++ 0x30000000, ++ 0x33000000, ++ 0x04104445, ++ 0x38008000, ++ 0x2200109C, ++ 0x08104448, ++ 0x38008000, ++ 0x23D4509C, ++ 0x08104417, ++ 0x9000A000, ++ 0x32000000, ++ 0x18000063, ++ 0x14000060, ++ 0x1C000051, ++ 0x10000057, ++ 0x38028000, ++ 0x0C000001, ++ 0x08D04466, ++ 0x3000200F, ++ 0x00000000, ++ 0x00000000, ++ 0x38030000, ++ 0x0C002601, ++ 0x08D0445A, ++ 0x30000000, ++ 0x3D020230, ++ 0x0400005D, ++ 0x30000000, ++ 0x3E000100, ++ 0x04000066, ++ 0x38028000, ++ 0x0C001601, ++ 0x34204466, ++ 0x38028000, ++ 0x0C000A01, ++ 0x34204466, ++ 0x38008004, ++ 0xFF000000, ++ 0x0800007B, ++ 0x3800802F, ++ 0x26000000, ++ 0x0800006C, ++ 0x380404AF, ++ 0x1F191010, ++ 0x0800006F, ++ 0x20000CAF, ++ 0x04000071, ++ 0x60000CAF, ++ 0x18700079, ++ 0x14000077, ++ 0x10000075, ++ 0x28140CAF, ++ 0x09B00084, ++ 0x280A0CAF, ++ 0x09B00084, ++ 0x28060CAF, ++ 0x09B00084, ++ 0x28048086, ++ 0x0800007D, ++ 0x38000086, ++ 0x22800000, ++ 0x04000080, ++ 0x30000000, ++ 0x0EF1F101, ++ 0x36004883, ++ 0x28020000, ++ 0x08000085, ++ 0x3802008E, ++ 0x3D040431, ++ 0x08000088, ++ 0x3805008E, ++ 0x1F241821, ++ 0x0800008B, ++ 0x3000008E, ++ 0xA0163021, ++ 0x0400008E, ++ 0x3000008E, ++ 0x0EF10012, ++ 0x34000091, ++ 0x300000CC, ++ 0x50000000, ++ 0x04000094, ++ 0x380095FE, ++ 0x32010000, ++ 0x04000097, ++ 0x50001FFE, ++ 0x5A010000, ++ 0x6DC9989B, ++ 0xFC19D4B9, ++ 0x30000186, ++ 0x3D840373, ++ 0x0400009E, ++ 0x3000008E, ++ 0x0A000000, ++ 0x040000A1, ++ 0x3000008E, ++ 0x22C00000, ++ 0x040000A4, ++ 0x9000028E, ++ 0x32010001, ++ 0x8E4000AA, ++ 0xC80000B0, ++ 0x00000000, ++ 0x00000000, ++ 0x3000008E, ++ 0x32010001, ++ 0x040000CB, ++ 0x3000008E, ++ 0x29000000, ++ 0x94045011, ++ 0x300019B6, ++ 0x32010000, ++ 0x040000B3, ++ 0x300019B6, ++ 0x3D040431, ++ 0x040000B6, ++ 0x300019B6, ++ 0x22800000, ++ 0x04000097, ++ 0x30000186, ++ 0x3D840473, ++ 0x040000BC, ++ 0x3000008E, ++ 0x29030000, ++ 0x040000BF, ++ 0x9AEE028E, ++ 0x32010100, ++ 0x7C0000C5, ++ 0xCC0000B0, ++ 0x080000B0, ++ 0x00000000, ++ 0x3000008E, ++ 0x32010100, ++ 0x040000C8, ++ 0x3000028E, ++ 0x29000000, ++ 0x94045011, ++ 0x5000038E, ++ 0x29000000, ++ 0x94045011, ++ 0xC0000035, ++ 0x38010006, ++ 0x3D040472, ++ 0x080000D2, ++ 0x30000004, ++ 0x0EF1F141, ++ 0x340000D5, ++ 0x28040004, ++ 0x080000D7, ++ 0x2808000E, ++ 0x080000D9, ++ 0x3000018E, ++ 0x0EF10052, ++ 0x340000DC, ++ 0x3000038E, ++ 0x29000000, ++ 0x94045011, ++ 0x38020000, ++ 0x32000000, ++ 0x080000E2, ++ 0x60000000, ++ 0xD80000E6, ++ 0xD40000E9, ++ 0x040000EC, ++ 0x30000000, ++ 0x0EF1F121, ++ 0x360048EF, ++ 0x30000000, ++ 0x0C002421, ++ 0x360048EF, ++ 0x30000000, ++ 0x0C000021, ++ 0x360048EF, ++ 0x28020000, ++ 0x0800007B, ++ 0x50001EFE, ++ 0x5A010000, ++ 0x6DC998F5, ++ 0xFC19D4F8, ++ 0x3000028E, ++ 0x32000040, ++ 0x040000FB, ++ 0x3AEE028E, ++ 0x32000080, ++ 0x040000FB, ++ 0x30000000, ++ 0x0EF1F101, ++ 0x360048FE, ++ 0x28020000, ++ 0x08000100, ++ 0x3802008E, ++ 0x3D040431, ++ 0x08000103, ++ 0x3805008E, ++ 0x1F241821, ++ 0x08000106, ++ 0x3000008E, ++ 0xA0163021, ++ 0x04000109, ++ 0x3000008E, ++ 0x0EF10012, ++ 0x3400010C, ++ 0x300014F6, ++ 0x32010000, ++ 0x04000114, ++ 0x20000000, ++ 0x04000111, ++ 0x300000EC, ++ 0x50000000, ++ 0x040000F1, ++ 0x300014F6, ++ 0x32030000, ++ 0x04000117, ++ 0x30001086, ++ 0x3D840473, ++ 0x0400011A, ++ 0x5000108E, ++ 0x22C00000, ++ 0x8E47C0CB, ++ 0xCB30011E, ++ 0x300019B6, ++ 0x32040000, ++ 0x04000121, ++ 0x300019B6, ++ 0x3D040431, ++ 0x04000124, ++ 0x300019B6, ++ 0x22800000, ++ 0x04000111, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x30000186, ++ 0x3D840473, ++ 0x0400012D, ++ 0x5000038E, ++ 0x29000000, ++ 0x94045011, ++ 0xC0000131, ++ 0x380C800E, ++ 0xFF000000, ++ 0x08000134, ++ 0x30000004, ++ 0x0FF1F103, ++ 0x34000137, ++ 0x28020000, ++ 0x08000139, ++ 0x3000038E, ++ 0x29000000, ++ 0x94045011, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x58010006, ++ 0x3D040472, ++ 0xDC204543, ++ 0x081DD4D2, ++ 0x480A0006, ++ 0xDC2044DC, ++ 0x081DD546, ++ 0x38050004, ++ 0x0EF1F141, ++ 0x342044DC, ++ 0x2802800E, ++ 0x080000DC, ++ 0x48000035, ++ 0x0400014A, ++ 0x7896638F, ++ 0x4100000F, ++ 0x8C00014F, ++ 0x080450C4, ++ 0x90104574, ++ 0x88C8620F, ++ 0xC000015A, ++ 0x90104574, ++ 0x08104554, ++ 0x94104557, ++ 0x3000628F, ++ 0x29000000, ++ 0x9404517A, ++ 0x3000638F, ++ 0x29000000, ++ 0x0410457A, ++ 0x3800E005, ++ 0x3D010131, ++ 0x0810455D, ++ 0xA832600F, ++ 0x90104574, ++ 0x08000154, ++ 0x94104557, ++ 0xC6104567, ++ 0xC4185563, ++ 0x5802E00F, ++ 0x0FEEEA07, ++ 0x80000174, ++ 0x3420456B, ++ 0x5802E00F, ++ 0x0EEEEA07, ++ 0x80000174, ++ 0x3420456B, ++ 0x30004000, ++ 0x33000001, ++ 0x0400016E, ++ 0x38034005, ++ 0x3D030373, ++ 0x08000171, ++ 0x30006007, ++ 0x33000000, ++ 0x04000174, ++ 0x3000608F, ++ 0x29000000, ++ 0x94045177, ++ 0x4000608F, ++ 0xA010457D, ++ 0x0410457A, ++ 0x3000608F, ++ 0x64000101, ++ 0x04104411, ++ 0x3000608F, ++ 0x64000101, ++ 0x04104580, ++ 0x3000618F, ++ 0x42000001, ++ 0x04000183, ++ 0x38028000, ++ 0x32000000, ++ 0x08104586, ++ 0x280A618F, ++ 0x08000188, ++ 0x480A618F, ++ 0xBC00018B, ++ 0x0800018E, ++ 0x3000618F, ++ 0x34000001, ++ 0x04000005, ++ 0x3000618F, ++ 0x34000000, ++ 0x04000008, ++ 0x3000008F, ++ 0x0EEAED0F, ++ 0x36000194, ++ 0x38038000, ++ 0x34000000, ++ 0x08000197, ++ 0x38028005, ++ 0x29010002, ++ 0x0800019A, ++ 0x3000028F, ++ 0x2200209C, ++ 0x0400019D, ++ 0x3000028F, ++ 0x23D4509C, ++ 0x040001A0, ++ 0x2814028F, ++ 0x080001A2, ++ 0x3000028F, ++ 0x43010201, ++ 0x040001A5, ++ 0x3000128F, ++ 0x32000100, ++ 0x040001A8, ++ 0x5AEE138F, ++ 0x4100000F, ++ 0x7C0001AC, ++ 0x080000F9, ++ 0x592C138F, ++ 0x29000000, ++ 0x8C0001B0, ++ 0x080000F9, ++ 0x2000138F, ++ 0x94045011, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++#if !defined(CONFIG_EXT_FEM_8800DCDW) ++uint32_t txgain_map[96] = { ++#ifdef CONFIG_FPGA_VERIFICATION ++ 0x20c0c971, ++ 0x20c0c980, ++ 0x20c0c992, ++ 0x20c0c9a6, ++ 0x20c0c9bf, ++ 0x20c0caa5, ++ 0x20c0cabd, ++ 0x20c0cba0, ++ 0x20c0cbb6, ++ 0x20c0cbea, ++ 0x20c0ccc5, ++ 0x20c0cdac, ++ 0x20c0cdd0, ++ 0x20c0ceb2, ++ 0x20c0ceff, ++ 0x20c0cfff, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c927, ++ 0x20c0c92c, ++ 0x20c0c931, ++ 0x20c0c937, ++ 0x20c0c93f, ++ 0x20c0c946, ++ 0x20c0c94f, ++ 0x20c0c959, ++ 0x20c0c964, ++ 0x20c0cbee, ++ 0x20c0cce0, ++ 0x20c0ccff, ++ 0x20c0cde2, ++ 0x20c0cdfe, ++ 0x20c0cede, ++ 0x20c0cefc, ++ 0x20c0cfd9, ++ 0x20c0cff8, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c98c, ++ 0x20c0ca79, ++ 0x20c0ca89, ++ 0x20c0cb74, ++ 0x20c0cb84, ++ 0x20c0cb94, ++ 0x20c0cba8, ++ 0x20c0cbbb, ++ 0x20c0cbd2, ++ 0x20c0cbee, ++ 0x20c0cce0, ++ 0x20c0ccff, ++ 0x20c0cde2, ++ 0x20c0cdfe, ++ 0x20c0cede, ++ 0x20c0cefc, ++ 0x20c0cfd9, ++ 0x20c0cff8, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c98c, ++ 0x20c0ca79, ++ 0x20c0ca89, ++ 0x20c0cb74, ++ 0x20c0cb84, ++ 0x20c0cb94, ++ 0x20c0cba8, ++ 0x20c0cbbb, ++ 0x20c0cbd2, ++#else ++ //11b ++ 0x00ffd780, ++ 0x00ffd872, ++ 0x00ffd880, ++ 0x00ffd972, ++ 0x00ffd980, ++ 0x00ffda75, ++ 0x00ffda86, ++ 0x00ffdb77, ++ 0x00ffdb86, ++ 0x00ffdc78, ++ 0x00ffdc89, ++ 0x00ffdd79, ++ 0x00ffdd89, ++ 0x00ffde83, ++ 0x00ffdf79, ++ 0x00ffdf8b, ++ 0x00ffd072, ++ 0x00ffd072, ++ 0x00ffd080, ++ 0x00ffd172, ++ 0x00ffd180, ++ 0x00ffd272, ++ 0x00ffd280, ++ 0x00ffd36d, ++ 0x00ffd379, ++ 0x00ffd46d, ++ 0x00ffd479, ++ 0x00ffd572, ++ 0x00ffd580, ++ 0x00ffd672, ++ 0x00ffd680, ++ 0x00ffd772, ++ //high ++ 0x00ffc87d, ++ 0x00ffc88b, ++ 0x00ffc979, ++ 0x00ffc989, ++ 0x00ffcc4b, ++ 0x00ffcc54, ++ 0x00ffcc5e, ++ 0x00ffcc69, ++ 0x00ffcc78, ++ 0x00ffcc85, ++ 0x00ffcd70, ++ 0x00ffcd80, ++ 0x00ffce70, ++ 0x00ffce80, ++ 0x00ffcf7d, ++ 0x00ffcf90, ++ 0x00ffc080, ++ 0x00ffc090, ++ 0x00ffc180, ++ 0x00ffc190, ++ 0x00ffc27b, ++ 0x00ffc28b, ++ 0x00ffc37b, ++ 0x00ffc390, ++ 0x00ffc485, ++ 0x00ffc495, ++ 0x00ffc579, ++ 0x00ffc589, ++ 0x00ffc679, ++ 0x00ffc689, ++ 0x00ffc780, ++ 0x00ffc790, ++ //low ++ 0x00ffc87d, ++ 0x00ffc88b, ++ 0x00ffc979, ++ 0x00ffc989, ++ 0x00ffcc4b, ++ 0x00ffcc54, ++ 0x00ffcc5e, ++ 0x00ffcc69, ++ 0x00ffcc78, ++ 0x00ffcc85, ++ 0x00ffcd70, ++ 0x00ffcd80, ++ 0x00ffcd90, ++ 0x00ffcf68, ++ 0x00ffcf75, ++ 0x00ffcf83, ++ 0x00ffc080, ++ 0x00ffc090, ++ 0x00ffc180, ++ 0x00ffc190, ++ 0x00ffc27b, ++ 0x00ffc28b, ++ 0x00ffc37b, ++ 0x00ffc390, ++ 0x00ffc485, ++ 0x00ffc495, ++ 0x00ffc579, ++ 0x00ffc589, ++ 0x00ffc679, ++ 0x00ffc689, ++ 0x00ffc780, ++ 0x00ffc790, ++#endif ++}; ++ ++const uint32_t txgain_map_h[96] = ++{ ++ //11b ++ 0xffd888, //11 ++ 0xffd979, //12 ++ 0xffd988, //13 ++ 0xffda79, //14 ++ 0xffda88, //15 ++ 0xffdb79, //16 ++ 0xffdb88, //17 ++ 0xffdc72, //18 ++ 0xffdc80, //19 ++ 0xffdd80, //20 ++ 0xffde66, //21 ++ 0xffde72, //22 ++ 0xffde80, //23 ++ 0xffdf79, //24 ++ 0xffdf88, //25 ++ 0xffdf98, //26 ++ 0xffd079, //-5 ++ 0xffd088, //-4 ++ 0xffd179, //-3 ++ 0xffd188, //-2 ++ 0xffd288, //-1 ++ 0xffd36c, //0 ++ 0xffd379, //1 ++ 0xffd388, //2 ++ 0xffd479, //3 ++ 0xffd488, //4 ++ 0xffd579, //5 ++ 0xffd588, //6 ++ 0xffd679, //7 ++ 0xffd688, //8 ++ 0xffd779, //9 ++ 0xffd879, //10 ++ //high ++ 0xffc879, //8 ++ 0xffc96b, //9 ++ 0xffc979, //10 ++ 0xffcc45, //11 ++ 0xffcc4d, //12 ++ 0xffcc56, //13 ++ 0xffcc60, //14 ++ 0xffcc6b, //15 ++ 0xffcc79, //16 ++ 0xffcd72, //17 ++ 0xffce60, //18 ++ 0xffce72, //19 ++ 0xffcf72, //20 ++ 0xffcf80, //21 ++ 0xffcf90, //22 ++ 0xffcf90, //23 ++ 0xffc079, //-8 ++ 0xffc16b, //-7 ++ 0xffc179, //-6 ++ 0xffc26b, //-5 ++ 0xffc279, //-4 ++ 0xffc36b, //-3 ++ 0xffc379, //-2 ++ 0xffc46b, //-1 ++ 0xffc479, //0 ++ 0xffc56b, //1 ++ 0xffc579, //2 ++ 0xffc66b, //3 ++ 0xffc679, //4 ++ 0xffc76b, //5 ++ 0xffc779, //6 ++ 0xffc86b, //7 ++ //low ++ 0xffc879, //8 ++ 0xffc96b, //9 ++ 0xffc979, //10 ++ 0xffcc45, //11 ++ 0xffcc4d, //12 ++ 0xffcc56, //13 ++ 0xffcc60, //14 ++ 0xffcc6b, //15 ++ 0xffcc79, //16 ++ 0xffcd72, //17 ++ 0xffcf5b, //18 ++ 0xffcf66, //19 ++ 0xffcf72, //20 ++ 0xffcf80, //21 ++ 0xffcf90, //22 ++ 0xffcf90, //23 ++ 0xffc079, //-8 ++ 0xffc16b, //-7 ++ 0xffc179, //-6 ++ 0xffc26b, //-5 ++ 0xffc279, //-4 ++ 0xffc36b, //-3 ++ 0xffc379, //-2 ++ 0xffc46b, //-1 ++ 0xffc479, //0 ++ 0xffc56b, //1 ++ 0xffc579, //2 ++ 0xffc66b, //3 ++ 0xffc679, //4 ++ 0xffc76b, //5 ++ 0xffc779, //6 ++ 0xffc86b, //7 ++}; ++ ++#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ ++const uint32_t txgain_map_femkct[96] = ++{ ++ //11b ++ 0x00ffd780,//15 ++ 0x00ffd872,//16 ++ 0x00ffd880,//17 ++ 0x00ffd972,//18 ++ 0x00ffd980,//19 ++ 0x00ffda72,//20 ++ 0x00ffda80,//21 ++ 0x00ffdb72,//22 ++ 0x00ffdb80,//23 ++ 0x00ffdc72,//24 ++ 0x00ffdc80,//25 ++ 0x00ffdd72,//26 ++ 0x00ffdd80,//27 ++ 0x00ffde72,//28 ++ 0x00ffde80,//29 ++ 0x00ffdf72,//30 ++ 0x00ffd072,//-1 ++ 0x00ffd072,//0 ++ 0x00ffd080,//1 ++ 0x00ffd172,//2 ++ 0x00ffd180,//3 ++ 0x00ffd272,//4 ++ 0x00ffd280,//5 ++ 0x00ffd36d,//6 ++ 0x00ffd379,//7 ++ 0x00ffd46d,//8 ++ 0x00ffd479,//9 ++ 0x00ffd572,//10 ++ 0x00ffd580,//11 ++ 0x00ffd672,//12 ++ 0x00ffd680,//13 ++ 0x00ffd772,//14 ++ //high ++ 0x00ffc872,//11 ++ 0x00ffc880,//12 ++ 0x00ffc972,//13 ++ 0x00ffc980,//14 ++ 0x00ffca72,//15 ++ 0x00ffca80,//16 ++ 0x00ffcb72,//17 ++ 0x00ffcb80,//18 ++ 0x00ffcc72,//19 ++ 0x00ffcc80,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//25 ++ 0x00ffcf80,//26 ++ 0x00ffc072,//-5 ++ 0x00ffc080,//-4 ++ 0x00ffc172,//-3 ++ 0x00ffc180,//-2 ++ 0x00ffc272,//-1 ++ 0x00ffc280,//0 ++ 0x00ffc372,//1 ++ 0x00ffc380,//2 ++ 0x00ffc472,//3 ++ 0x00ffc480,//4 ++ 0x00ffc572,//5 ++ 0x00ffc580,//6 ++ 0x00ffc672,//7 ++ 0x00ffc680,//8 ++ 0x00ffc772,//9 ++ 0x00ffc780,//10 ++ //low ++ 0x00ffc872,//11 ++ 0x00ffc880,//12 ++ 0x00ffc972,//13 ++ 0x00ffc980,//14 ++ 0x00ffca72,//15 ++ 0x00ffca80,//16 ++ 0x00ffcb72,//17 ++ 0x00ffcb80,//18 ++ 0x00ffcc72,//19 ++ 0x00ffcc80,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//26 ++ 0x00ffcf80,//27 ++ 0x00ffc072,//-5 ++ 0x00ffc080,//-4 ++ 0x00ffc172,//-3 ++ 0x00ffc180,//-2 ++ 0x00ffc272,//-1 ++ 0x00ffc280,//0 ++ 0x00ffc372,//1 ++ 0x00ffc380,//2 ++ 0x00ffc472,//3 ++ 0x00ffc480,//4 ++ 0x00ffc572,//5 ++ 0x00ffc580,//6 ++ 0x00ffc672,//7 ++ 0x00ffc680,//8 ++ 0x00ffc772,//9 ++ 0x00ffc780,//10 ++}; ++ ++const uint32_t txgain_map_femkct_h[96] = ++{ ++ //11b ++ 0x00ffd872,//15 ++ 0x00ffd880,//16 ++ 0x00ffd972,//17 ++ 0x00ffd980,//18 ++ 0x00ffd990,//19 ++ 0x00ffda72,//20 ++ 0x00ffda80,//21 ++ 0x00ffdb72,//22 ++ 0x00ffdb80,//23 ++ 0x00ffdc72,//24 ++ 0x00ffdc80,//25 ++ 0x00ffdd72,//26 ++ 0x00ffdd80,//27 ++ 0x00ffde72,//28 ++ 0x00ffde80,//29 ++ 0x00ffdf72,//30 ++ 0x00ffd072,//-1 ++ 0x00ffd072,//0 ++ 0x00ffd080,//1 ++ 0x00ffd172,//2 ++ 0x00ffd180,//3 ++ 0x00ffd272,//4 ++ 0x00ffd280,//5 ++ 0x00ffd379,//6 ++ 0x00ffd46d,//7 ++ 0x00ffd479,//8 ++ 0x00ffd572,//9 ++ 0x00ffd580,//10 ++ 0x00ffd672,//11 ++ 0x00ffd680,//12 ++ 0x00ffd772,//13 ++ 0x00ffd780,//14 ++ //high ++ 0x00ffc880,//11 ++ 0x00ffc972,//12 ++ 0x00ffc980,//13 ++ 0x00ffca72,//14 ++ 0x00ffca80,//15 ++ 0x00ffcb72,//16 ++ 0x00ffcb80,//17 ++ 0x00ffcc72,//18 ++ 0x00ffcc80,//19 ++ 0x00ffcc90,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//25 ++ 0x00ffcf80,//26 ++ 0x00ffc080,//-5 ++ 0x00ffc172,//-4 ++ 0x00ffc180,//-3 ++ 0x00ffc272,//-2 ++ 0x00ffc280,//-1 ++ 0x00ffc372,//0 ++ 0x00ffc380,//1 ++ 0x00ffc472,//2 ++ 0x00ffc480,//3 ++ 0x00ffc572,//4 ++ 0x00ffc580,//5 ++ 0x00ffc672,//6 ++ 0x00ffc680,//7 ++ 0x00ffc772,//8 ++ 0x00ffc780,//9 ++ 0x00ffc872,//10 ++ //low ++ 0x00ffc880,//11 ++ 0x00ffc972,//12 ++ 0x00ffc980,//13 ++ 0x00ffca72,//14 ++ 0x00ffca80,//15 ++ 0x00ffcb72,//16 ++ 0x00ffcb80,//17 ++ 0x00ffcc72,//18 ++ 0x00ffcc80,//19 ++ 0x00ffcc90,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//25 ++ 0x00ffcf80,//26 ++ 0x00ffc080,//-5 ++ 0x00ffc172,//-4 ++ 0x00ffc180,//-3 ++ 0x00ffc272,//-2 ++ 0x00ffc280,//-1 ++ 0x00ffc372,//0 ++ 0x00ffc380,//1 ++ 0x00ffc472,//2 ++ 0x00ffc480,//3 ++ 0x00ffc572,//4 ++ 0x00ffc580,//5 ++ 0x00ffc672,//6 ++ 0x00ffc680,//7 ++ 0x00ffc772,//8 ++ 0x00ffc780,//9 ++ 0x00ffc872,//10 ++}; ++#endif ++ ++u32 jump_tbl[][2] = ++{ ++#ifndef CONFIG_FOR_IPCOM ++ {296, 0x180001}, ++ {137, 0x180011}, ++ {303, 0x1810f9}, ++ {168, 0x18186d}, ++ {308, 0x181bbd}, ++ {288, 0x1820c1}, ++#else ++ {308, 0x181001}, ++ {288, 0x181031}, ++ {296, 0x18120d}, ++ {137, 0x18121d}, ++ {303, 0x182305}, ++ {168, 0x182a79}, ++ {258, 0x182ae1}, ++#endif ++}; ++ ++u32 jump_tbl_u02[][2] = ++{ ++ {303, 0x00180d25}, ++ {168, 0x001814a5}, ++ {265, 0x001816b1}, ++ {266, 0x00181849}, ++ {256, 0x001818ad}, ++ {288, 0x00181bf9}, ++ {333, 0x00182d0d}, ++ { 26, 0x00182d45} ++}; ++ ++ ++u32 patch_tbl_func[][2] = ++{ ++#ifndef CONFIG_FOR_IPCOM ++ {0x00110054, 0x0018186D}, // same as jump_tbl idx 168 ++ {0x0011005C, 0x0018186D}, // same as jump_tbl idx 168 ++#else ++ {0x00110054, 0x00182A79}, // same as jump_tbl idx 168 ++ {0x0011005C, 0x00182A79}, // same as jump_tbl idx 168 ++ {0x001118D4, 0x00000011}, ++#endif ++}; ++ ++u32 patch_tbl_func_u02[][2] = ++{ ++ {0x00110054, 0x001814a5}, // same as jump_tbl idx 168 ++ {0x0011005C, 0x001814a5}, // same as jump_tbl idx 168 ++ {0x001109c0, 0x00181e3d}, ++ {0x00110bb4, 0x001824e1}, ++ {0x00110f08, 0x00182d25}, ++}; ++ ++ ++u32 patch_tbl_rf_func[][2] = ++{ ++ {0x00110bf0, 0x00180001}, ++}; ++ ++ ++//adap test ++u32 adaptivity_patch_tbl_8800dc[][2] = { ++ {0x000C, 0x0000320A}, //linkloss_thd ++ {0x009C, 0x00000000}, //ac_param_conf ++ {0x0128, 0xF6140001}, //tx_adaptivity_en ++}; ++//adap test ++ ++ ++static u8 chip_id = 0; ++#define CHIP_ID_H_MASK 0xC0 ++#define IS_CHIP_ID_H() ((chip_id & CHIP_ID_H_MASK) == CHIP_ID_H_MASK) ++ ++//Crystal provided by CPU (start) ++int set_bbpll_config(struct aic_sdio_dev *rwnx_hw){ ++// {0x40505010, 0x7C301010},//bbpll ++ int ret = 0; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ ++ //Read crystal provided by CPU or not. ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40500148, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x rd fail: %d\n", 0x40500148, ret); ++ return -1; ++ } ++ ++ AICWFDBG(LOGDEBUG, "%s rd_mem_addr_cfm.memdata:%x \r\n", __func__, rd_mem_addr_cfm.memdata); ++ ++ if(!(rd_mem_addr_cfm.memdata & 0x01)){ ++ AICWFDBG(LOGINFO, "%s Crystal not provided by CPU \r\n", __func__); ++ return 0; ++ }else{ ++ AICWFDBG(LOGINFO, "%s Crystal provided by CPU \r\n", __func__); ++ //Read 0x40505010 value to check bbpll set or not. ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40505010, &rd_mem_addr_cfm); ++ if(ret < 0){ ++ AICWFDBG(LOGERROR, "%s error ret_val:%d\r\n", __func__, ret); ++ return -1; ++ } ++ ++ if((rd_mem_addr_cfm.memdata >> 29) == 3){ ++ AICWFDBG(LOGERROR, "%s Not need to set \r\n", __func__); ++ return 0; ++ }else{ ++ rd_mem_addr_cfm.memdata |= ((0x1 << 29) | (0x1 << 30)); ++ rd_mem_addr_cfm.memdata &= (~(0x1 << 31)); ++ rwnx_send_dbg_mem_write_req(rwnx_hw, 0x40505010, rd_mem_addr_cfm.memdata); ++ } ++ } ++ return 0; ++} ++//Crystal provided by CPU (end) ++ ++ ++void system_config_8800dc(struct aic_sdio_dev *rwnx_hw) ++{ ++ int syscfg_num; ++ array3_tbl_t p_syscfg_msk_tbl; ++ int ret, cnt; ++ const u32 mem_addr = 0x40500000; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++#ifdef CONFIG_OOB ++ int oobcfg_num; ++#endif ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x rd fail: %d\n", mem_addr, ret); ++ return; ++ } ++ chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16); ++ //printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ if (((rd_mem_addr_cfm.memdata >> 25) & 0x01UL) == 0x00UL) { ++ chip_mcu_id = 1; ++ } ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x00000020, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x00000020] rd fail: %d\n", ret); ++ return; ++ } ++ chip_sub_id = (u8)(rd_mem_addr_cfm.memdata); ++ //printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ AICWFDBG(LOGINFO, "chip_id=%x, chip_sub_id=%x!!\n", chip_id, chip_sub_id); ++ ++ //Crystal provided by CPU (start) ++ ret = set_bbpll_config(rwnx_hw); ++ if (ret) { ++ AICWFDBG(LOGERROR, "set_bbpll_config fail: %d\n", ret); ++ return; ++ } ++ //Crystal provided by CPU (end) ++ ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40500010, &rd_mem_addr_cfm); ++ AICWFDBG(LOGDEBUG, "[0x40500010]=%x\n", rd_mem_addr_cfm.memdata); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x40500010] rd fail: %d\n", ret); ++ return; ++ } ++ ++ syscfg_num = sizeof(syscfg_tbl_8800dc) / sizeof(uint32_t) / 2; ++ ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc[cnt][0], syscfg_tbl_8800dc[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", syscfg_tbl_8800dc[cnt][0], ret); ++ return; ++ } ++ } ++ ++ if (chip_mcu_id == 0) { ++ if (chip_sub_id == 0) { ++ syscfg_num = sizeof(syscfg_tbl_8800dc_sdio_u01) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc_sdio_u01[cnt][0], syscfg_tbl_8800dc_sdio_u01[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", syscfg_tbl_8800dc_sdio_u01[cnt][0], ret); ++ return; ++ } ++ } ++ } else if ((chip_sub_id == 1) || (chip_sub_id == 2)) { ++ syscfg_num = sizeof(syscfg_tbl_8800dc_sdio_u02) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc_sdio_u02[cnt][0], syscfg_tbl_8800dc_sdio_u02[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", syscfg_tbl_8800dc_sdio_u02[cnt][0], ret); ++ return; ++ } ++ } ++ } ++ } ++#ifdef CONFIG_OOB ++ if ((chip_sub_id == 1) || (chip_sub_id == 2)) { ++ oobcfg_num = sizeof(oobcfg_tbl_8800dc_sdio_u02) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < oobcfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, oobcfg_tbl_8800dc_sdio_u02[cnt][0], oobcfg_tbl_8800dc_sdio_u02[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", oobcfg_tbl_8800dc_sdio_u02[cnt][0], ret); ++ return; ++ } ++ } ++ } ++#endif ++ if (IS_CHIP_ID_H()) { ++ syscfg_num = sizeof(syscfg_tbl_masked_8800dc_h) / sizeof(u32) / 3; ++ p_syscfg_msk_tbl = syscfg_tbl_masked_8800dc_h; ++ } else { ++ syscfg_num = sizeof(syscfg_tbl_masked_8800dc) / sizeof(u32) / 3; ++ p_syscfg_msk_tbl = syscfg_tbl_masked_8800dc; ++ } ++ ++ ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ if (p_syscfg_msk_tbl[cnt][0] == 0x00000000) { ++ break; ++ } else if (p_syscfg_msk_tbl[cnt][0] == 0x70001000) { ++ if (chip_mcu_id == 0) { ++ p_syscfg_msk_tbl[cnt][1] |= ((0x1 << 8) | (0x1 << 15)); // mask ++ p_syscfg_msk_tbl[cnt][2] |= ((0x1 << 8) | (0x1 << 15)); ++ } ++ } ++ ++ ret = rwnx_send_dbg_mem_mask_write_req(rwnx_hw, ++ p_syscfg_msk_tbl[cnt][0], p_syscfg_msk_tbl[cnt][1], p_syscfg_msk_tbl[cnt][2]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x mask write fail: %d\n", p_syscfg_msk_tbl[cnt][0], ret); ++ return; ++ } ++ } ++ ++ if (chip_sub_id == 0) { ++ syscfg_num = sizeof(syscfg_tbl_masked_8800dc_u01) / sizeof(u32) / 3; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_mask_write_req(rwnx_hw, ++ syscfg_tbl_masked_8800dc_u01[cnt][0], syscfg_tbl_masked_8800dc_u01[cnt][1], syscfg_tbl_masked_8800dc_u01[cnt][2]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x mask write fail: %d\n", syscfg_tbl_masked_8800dc_u01[cnt][0], ret); ++ return; ++ } ++ } ++ } ++ ++} ++ ++extern int adap_test; ++ ++void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw) ++{ ++ int ret = 0; ++ int cnt = 0; ++ if (testmode == 0) { ++ const u32 cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ int i; ++ u32 wifisetting_cfg_addr; ++ u32 ldpc_cfg_addr; ++ u32 agc_cfg_addr; ++ u32 txgain_cfg_addr; ++ u32 jump_tbl_addr = 0; ++ ++ u32 patch_tbl_wifisetting_num;// = sizeof(patch_tbl_wifisetting_8800dc_u02)/sizeof(u32)/2; ++ u32 ldpc_cfg_size = sizeof(ldpc_cfg_ram); ++ u32 agc_cfg_size = sizeof(agc_cfg_ram); ++ u32 txgain_cfg_size, *txgain_cfg_array; ++ u32 jump_tbl_size = 0; ++ u32 patch_tbl_func_num = 0; ++ ++ //adap test ++ int adap_patch_num = 0; ++ //adap test ++ ++ ++ array2_tbl_t jump_tbl_base = NULL; ++ array2_tbl_t patch_tbl_func_base = NULL; ++ array2_tbl_t patch_tbl_wifisetting_8800dc_base = NULL; ++ ++ if (chip_sub_id == 0) { ++ jump_tbl_base = jump_tbl; ++ jump_tbl_size = sizeof(jump_tbl)/2; ++ patch_tbl_func_base = patch_tbl_func; ++ patch_tbl_func_num = sizeof(patch_tbl_func)/sizeof(u32)/2; ++ patch_tbl_wifisetting_num = sizeof(patch_tbl_wifisetting_8800dc_u01)/sizeof(u32)/2; ++ patch_tbl_wifisetting_8800dc_base = patch_tbl_wifisetting_8800dc_u01; ++ } else if ((chip_sub_id == 1) || (chip_sub_id == 2)) { ++ patch_tbl_wifisetting_num = sizeof(patch_tbl_wifisetting_8800dc_u02)/sizeof(u32)/2; ++ patch_tbl_wifisetting_8800dc_base = patch_tbl_wifisetting_8800dc_u02; ++ } else { ++ printk("unsupported id: %d", chip_sub_id); ++ return; ++ } ++ ++ //struct dbg_mem_read_cfm cfm; ++ //int i; ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base, ret); ++ } ++ wifisetting_cfg_addr = cfm.memdata; ++ ++ if(chip_sub_id == 0){ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 4, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 4, ret); ++ } ++ jump_tbl_addr = cfm.memdata; ++ } ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 8, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 8, ret); ++ } ++ ldpc_cfg_addr = cfm.memdata; ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0xc, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 0xc, ret); ++ } ++ agc_cfg_addr = cfm.memdata; ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x10, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 0x10, ret); ++ } ++ txgain_cfg_addr = cfm.memdata; ++ ++ AICWFDBG(LOGINFO, "wifisetting_cfg_addr=%x, ldpc_cfg_addr=%x, agc_cfg_addr=%x, txgain_cfg_addr=%x\n", wifisetting_cfg_addr, ldpc_cfg_addr, agc_cfg_addr, txgain_cfg_addr); ++ ++ for (cnt = 0; cnt < patch_tbl_wifisetting_num; cnt++) { ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, wifisetting_cfg_addr + patch_tbl_wifisetting_8800dc_base[cnt][0], patch_tbl_wifisetting_8800dc_base[cnt][1]))) { ++ AICWFDBG(LOGERROR, "wifisetting %x write fail\n", patch_tbl_wifisetting_8800dc_base[cnt][0]); ++ } ++ } ++ ++//adap test ++ if(adap_test){ ++ AICWFDBG(LOGINFO, "%s for adaptivity test \r\n", __func__); ++ adap_patch_num = sizeof(adaptivity_patch_tbl_8800dc)/sizeof(u32)/2; ++ for(cnt = 0; cnt < adap_patch_num; cnt++) ++ { ++ if((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, wifisetting_cfg_addr + adaptivity_patch_tbl_8800dc[cnt][0], adaptivity_patch_tbl_8800dc[cnt][1]))) { ++ AICWFDBG(LOGERROR, "%x write fail\n", wifisetting_cfg_addr + adaptivity_patch_tbl_8800dc[cnt][0]); ++ } ++ } ++ } ++//adap test ++ ++ if (ldpc_cfg_size > 512) {// > 0.5KB data ++ for (i = 0; i < (ldpc_cfg_size - 512); i += 512) {//each time write 0.5KB ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ldpc_cfg_addr + i, 512, ldpc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "ldpc upload fail: %x, err:%d\r\n", ldpc_cfg_addr + i, ret); ++ break; ++ } ++ } ++ } ++ ++ if (!ret && (i < ldpc_cfg_size)) {// < 0.5KB data ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ldpc_cfg_addr + i, ldpc_cfg_size - i, ldpc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "ldpc upload fail: %x, err:%d\r\n", ldpc_cfg_addr + i, ret); ++ } ++ } ++ ++ if (agc_cfg_size > 512) {// > 0.5KB data ++ for (i = 0; i < (agc_cfg_size - 512); i += 512) {//each time write 0.5KB ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, agc_cfg_addr + i, 512, agc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "agc upload fail: %x, err:%d\r\n", agc_cfg_addr + i, ret); ++ break; ++ } ++ } ++ } ++ ++ if (!ret && (i < agc_cfg_size)) {// < 0.5KB data ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, agc_cfg_addr + i, agc_cfg_size - i, agc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "agc upload fail: %x, err:%d\r\n", agc_cfg_addr + i, ret); ++ } ++ } ++ ++ #if !defined(CONFIG_FPGA_VERIFICATION) ++ if ((IS_CHIP_ID_H())) { ++ #if defined(CONFIG_EXT_FEM_8800DCDW) ++ txgain_cfg_size = sizeof(txgain_map_femkct_h); ++ txgain_cfg_array = (u32 *)txgain_map_femkct_h; ++ #else ++ txgain_cfg_size = sizeof(txgain_map_h); ++ txgain_cfg_array = (u32 *)txgain_map_h; ++ #endif ++ } else { ++ #if defined(CONFIG_EXT_FEM_8800DCDW) ++ txgain_cfg_size = sizeof(txgain_map_femkct); ++ txgain_cfg_array = (u32 *)txgain_map_femkct; ++ #else ++ txgain_cfg_size = sizeof(txgain_map); ++ txgain_cfg_array = (u32 *)txgain_map; ++ #endif ++ } ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, txgain_cfg_addr, txgain_cfg_size, txgain_cfg_array); ++ if (ret) { ++ AICWFDBG(LOGERROR, "txgain upload fail: %x, err:%d\r\n", txgain_cfg_addr, ret); ++ } ++ ++ if (chip_sub_id == 0) { ++ for (cnt = 0; cnt < jump_tbl_size/4; cnt+=1) { ++ AICWFDBG(LOGDEBUG, "%x = %x\n", jump_tbl_base[cnt][0]*4+jump_tbl_addr, jump_tbl_base[cnt][1]); ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, jump_tbl_base[cnt][0]*4+jump_tbl_addr, jump_tbl_base[cnt][1]))) { ++ AICWFDBG(LOGERROR, "%x write fail\n", jump_tbl_addr+8*cnt); ++ } ++ } ++ for (cnt = 0; cnt < patch_tbl_func_num; cnt++) { ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, patch_tbl_func_base[cnt][0], patch_tbl_func_base[cnt][1]))) { ++ AICWFDBG(LOGERROR, "patch_tbl_func %x write fail\n", patch_tbl_func_base[cnt][0]); ++ } ++ } ++ } else if (chip_sub_id == 1) { ++ ret = aicwf_patch_table_load(rwnx_hw, RWNX_MAC_PATCH_TABLE_8800DC_U02); ++ if(ret){ ++ printk("patch_tbl upload fail: err:%d\r\n", ret); ++ } ++ } else if (chip_sub_id == 2) { ++ ret = aicwf_patch_table_load(rwnx_hw, RWNX_MAC_PATCH_TABLE_8800DC_H_U02); ++ if(ret){ ++ printk("patch_tbl upload fail: err:%d\r\n", ret); ++ } ++ } else { ++ printk("unsupported id: %d\n", chip_sub_id); ++ } ++ ++ #endif ++ } else { ++ if (chip_sub_id == 0) { ++ u32 patch_tbl_rf_func_num = sizeof(patch_tbl_rf_func)/sizeof(u32)/2; ++ for (cnt = 0; cnt < patch_tbl_rf_func_num; cnt++) { ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, patch_tbl_rf_func[cnt][0], patch_tbl_rf_func[cnt][1]))) { ++ AICWFDBG(LOGERROR, "patch_tbl_rf_func %x write fail\n", patch_tbl_rf_func[cnt][0]); ++ } ++ } ++ } ++ } ++} ++ ++int aicwf_misc_ram_init_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t misc_ram_size = 12; ++ int i; ++ ++ if (testmode == FW_RFTEST_MODE) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ // init misc ram ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr); ++ for (i = 0; i < (misc_ram_size / 4); i++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, misc_ram_addr + i * 4, 0); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] wr fail: %d\n", misc_ram_addr + i * 4, ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++ ++#ifdef CONFIG_DPD ++int aicwf_dpd_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ uint32_t fw_addr, boot_type; ++ int valid_flag; ++ ++ printk("%s\n", __func__); ++ ++ ret = aicwf_misc_ram_valid_check_8800dc(sdiodev, &valid_flag); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram check fail: %d\n", ret); ++ return ret; ++ } ++ if (valid_flag) { ++ AICWFDBG(LOGINFO, "misc ram valid, skip calib process\n"); ++ return ret; ++ } ++ ret = aicwf_plat_calib_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ /* fw start */ ++ fw_addr = 0x00130009; ++ boot_type = HOST_START_APP_FNCALL; ++ AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); ++ ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type, NULL); ++ if (ret) { ++ AICWFDBG(LOGINFO, "start app fail: %d\n", ret); ++ return ret; ++ } ++ { // read dpd res ++ const uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_word_cnt; ++ int i; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ // bit_mask ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ dpd_res->bit_mask[i] = cfm.memdata; ++ } ++ // dpd_high ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, dpd_high); ++ ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, dpd_high) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ dpd_res->dpd_high[i] = cfm.memdata; ++ } ++ // loft_res ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ dpd_res->loft_res[i] = cfm.memdata; ++ } ++ } ++ return ret; ++} ++ ++int aicwf_dpd_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", dpd_res->bit_mask[1]); ++ if (dpd_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void dpd_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == FW_RFTEST_MODE) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy dpd_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", dpd_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // dpd_high ++ AICWFDBG(LOGINFO, "dpd_high[0]=%x\n", dpd_res->dpd_high[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, dpd_high); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, dpd_high); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->dpd_high[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "dpd_high wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", dpd_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++ ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_DPDRESULT_NAME_8800DC; ++ struct device *dev = sdiodev->dev; ++ AICWFDBG(LOGINFO, "%s: dpd_res file path:%s \r\n", __func__, filename); ++ /* load file */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of dpd_res file\n"); ++ if (dst) { ++ #ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++ #endif ++ dst = NULL; ++ } ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d, dst[0]=%x\n", filename, size, dst[0]); ++ memcpy((u8 *)dpd_res, (u8 *)dst, sizeof(rf_misc_ram_lite_t)); ++ if (dst) { ++ #ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++ #endif ++ dst = NULL; ++ } ++ return ret; ++} ++ ++int aicwf_dpd_result_write_8800dc(void *buf, int buf_len) ++{ ++ int sum = 0, len = 0; ++ char *path = NULL; ++ struct file *fp = NULL; ++ loff_t pos = 0; ++ mm_segment_t fs; ++ ++ AICWFDBG(LOGINFO, "%s\n", __func__); ++ ++ path = __getname(); ++ if (!path) { ++ AICWFDBG(LOGINFO, "get path fail\n"); ++ return -1; ++ } ++ ++ len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", AICBSP_FW_PATH, FW_DPDRESULT_NAME_8800DC); ++ printk("%s\n", path); ++ ++ fp = filp_open(path, O_RDWR | O_CREAT, 0644); ++ if (IS_ERR(fp)) { ++ AICWFDBG(LOGINFO, "fp open fial\n"); ++ __putname(path); ++ fp = NULL; ++ return -1; ++ } ++ ++ fs = get_fs(); ++ set_fs(KERNEL_DS); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ sum = kernel_write(fp, buf, buf_len, &pos); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) ++ sum = kernel_write(fp, (char *)buf, buf_len, pos); ++#else ++ sum = vfs_write(fp, (char *)buf, buf_len, &pos); ++#endif ++ ++ set_fs(fs); ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ ++ return 0; ++} ++#endif /* !CONFIG_FORCE_DPD_CALIB */ ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++int aicwf_loft_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res) ++{ ++ int ret = 0; ++ uint32_t fw_addr, boot_type; ++ int valid_flag; ++ ++ printk("%s\n", __func__); ++ ++ ret = aicwf_misc_ram_valid_check_8800dc(sdiodev, &valid_flag); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram check fail: %d\n", ret); ++ return ret; ++ } ++ if (valid_flag) { ++ AICWFDBG(LOGINFO, "misc ram valid, skip calib process\n"); ++ return ret; ++ } ++ ret = aicwf_plat_calib_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ /* fw start */ ++ fw_addr = 0x00130009; ++ boot_type = HOST_START_APP_FNCALL; ++ AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); ++ ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type, NULL); ++ if (ret) { ++ AICWFDBG(LOGINFO, "start app fail: %d\n", ret); ++ return ret; ++ } ++ { // read loft res ++ const uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_word_cnt; ++ int i; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ // bit_mask ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ loft_res->bit_mask[i] = cfm.memdata; ++ } ++ // loft_res ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ loft_res->loft_res[i] = cfm.memdata; ++ } ++ } ++ return ret; ++} ++ ++int aicwf_loft_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", loft_res->bit_mask[1]); ++ if (loft_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void loft_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == FW_RFTEST_MODE) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy loft_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", loft_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", loft_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h +new file mode 100644 +index 000000000000..23b8185761eb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h +@@ -0,0 +1,41 @@ ++#ifndef _AIC8800DC_COMPAT_H_ ++#define _AIC8800DC_COMPAT_H_ ++ ++#include "aicsdio.h" ++typedef u32 (*array2_tbl_t)[2]; ++typedef u32 (*array3_tbl_t)[3]; ++ ++typedef uint8_t u8_l; ++typedef int8_t s8_l; ++typedef bool bool_l; ++typedef uint16_t u16_l; ++typedef int16_t s16_l; ++typedef uint32_t u32_l; ++typedef int32_t s32_l; ++typedef uint64_t u64_l; ++ ++extern u8 chip_sub_id; ++extern u8 chip_mcu_id; ++#define FW_PATH_MAX_LEN 200 ++ ++void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw); ++void system_config_8800dc(struct aic_sdio_dev *rwnx_hw); ++int aicwf_misc_ram_init_8800dc(struct aic_sdio_dev *sdiodev); ++ ++#ifdef CONFIG_DPD ++int aicwf_dpd_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res); ++int aicwf_dpd_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res); ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res); ++int aicwf_dpd_result_write_8800dc(void *buf, int buf_len); ++#endif/* !CONFIG_FORCE_DPD_CALIB */ ++#endif ++#ifdef CONFIG_LOFT_CALIB ++int aicwf_loft_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res); ++int aicwf_loft_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res); ++#endif ++ ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c +new file mode 100644 +index 000000000000..658979c535a2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c +@@ -0,0 +1,2214 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.c ++ * ++ * Handles queueing (push to IPC, ack/cfm from IPC) of commands issued to ++ * LMAC FW ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) ++#include ++#endif ++#include ++#include "aicsdio_txrxif.h" ++#include "aicsdio.h" ++#include "aic_bsp_driver.h" ++#include "md5.h" ++#include "aic8800dc_compat.h" ++#include "aic8800d80_compat.h" ++#include "aicwf_firmware_array.h" ++#define FW_PATH_MAX 200 ++ ++extern int adap_test; ++extern char aic_fw_path[FW_PATH_MAX]; ++extern struct aic_sdio_dev *aicbsp_sdiodev; ++ ++static void cmd_dump(const struct rwnx_cmd *cmd) ++{ ++ printk(KERN_CRIT "tkn[%d] flags:%04x result:%3d cmd:%4d - reqcfm(%4d)\n", ++ cmd->tkn, cmd->flags, cmd->result, cmd->id, cmd->reqid); ++} ++ ++static void cmd_complete(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ //printk("cmdcmp\n"); ++ lockdep_assert_held(&cmd_mgr->lock); ++ ++ list_del(&cmd->list); ++ cmd_mgr->queue_sz--; ++ ++ cmd->flags |= RWNX_CMD_FLAG_DONE; ++ if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) { ++ kfree(cmd); ++ } else { ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) { ++ cmd->result = 0; ++ complete(&cmd->complete); ++ } ++ } ++} ++ ++static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ bool defer_push = false; ++ int err = 0; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ ++ if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { ++ printk(KERN_CRIT"cmd queue crashed\n"); ++ cmd->result = -EPIPE; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EPIPE; ++ } ++ ++ if (!list_empty(&cmd_mgr->cmds)) { ++ struct rwnx_cmd *last; ++ ++ if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) { ++ printk(KERN_CRIT"Too many cmds (%d) already queued\n", ++ cmd_mgr->max_queue_sz); ++ cmd->result = -ENOMEM; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -ENOMEM; ++ } ++ last = list_entry(cmd_mgr->cmds.prev, struct rwnx_cmd, list); ++ if (last->flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_PUSH)) { ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ defer_push = true; ++ } ++ } ++ ++ if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM) ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM; ++ ++ cmd->tkn = cmd_mgr->next_tkn++; ++ cmd->result = -EINTR; ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ init_completion(&cmd->complete); ++ ++ list_add_tail(&cmd->list, &cmd_mgr->cmds); ++ cmd_mgr->queue_sz++; ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ if (!defer_push) { ++ //printk("queue:id=%x, param_len=%u\n", cmd->a2e_msg->id, cmd->a2e_msg->param_len); ++ rwnx_set_cmd_tx((void *)(cmd_mgr->sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ //rwnx_ipc_msg_push(rwnx_hw, cmd, RWNX_CMD_A2EMSG_LEN(cmd->a2e_msg)); ++ kfree(cmd->a2e_msg); ++ } else { ++ //WAKE_CMD_WORK(cmd_mgr); ++ printk("ERR: never defer push!!!!"); ++ return 0; ++ } ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) { ++ unsigned long tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz); ++ if (!wait_for_completion_killable_timeout(&cmd->complete, tout)) { ++ printk(KERN_CRIT"cmd timed-out\n"); ++ cmd_dump(cmd); ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED; ++ if (!(cmd->flags & RWNX_CMD_FLAG_DONE)) { ++ cmd->result = -ETIMEDOUT; ++ cmd_complete(cmd_mgr, cmd); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ err = -ETIMEDOUT; ++ } else { ++ kfree(cmd); ++ } ++ } else { ++ cmd->result = 0; ++ } ++ ++ return err; ++} ++ ++static int cmd_mgr_run_callback(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd, ++ struct rwnx_cmd_e2amsg *msg, msg_cb_fct cb) ++{ ++ int res; ++ ++ if (!cb) { ++ return 0; ++ } ++ spin_lock(&cmd_mgr->cb_lock); ++ res = cb(cmd, msg); ++ spin_unlock(&cmd_mgr->cb_lock); ++ ++ return res; ++} ++ ++static int cmd_mgr_msgind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd_e2amsg *msg, ++ msg_cb_fct cb) ++{ ++ struct rwnx_cmd *cmd; ++ bool found = false; ++ ++ //printk("cmd->id=%x\n", msg->id); ++ spin_lock(&cmd_mgr->lock); ++ list_for_each_entry(cmd, &cmd_mgr->cmds, list) { ++ if (cmd->reqid == msg->id && ++ (cmd->flags & RWNX_CMD_FLAG_WAIT_CFM)) { ++ ++ if (!cmd_mgr_run_callback(cmd_mgr, cmd, msg, cb)) { ++ found = true; ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_CFM; ++ ++ if (WARN((msg->param_len > RWNX_CMD_E2AMSG_LEN_MAX), ++ "Unexpect E2A msg len %d > %d\n", msg->param_len, ++ RWNX_CMD_E2AMSG_LEN_MAX)) { ++ msg->param_len = RWNX_CMD_E2AMSG_LEN_MAX; ++ } ++ ++ if (cmd->e2a_msg && msg->param_len) ++ memcpy(cmd->e2a_msg, &msg->param, msg->param_len); ++ ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) ++ cmd_complete(cmd_mgr, cmd); ++ ++ break; ++ } ++ } ++ } ++ spin_unlock(&cmd_mgr->lock); ++ ++ if (!found) ++ cmd_mgr_run_callback(cmd_mgr, NULL, msg, cb); ++ ++ return 0; ++} ++ ++static void cmd_mgr_print(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ cmd_dump(cur); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++static void cmd_mgr_drain(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur, *nxt; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry_safe(cur, nxt, &cmd_mgr->cmds, list) { ++ list_del(&cur->list); ++ cmd_mgr->queue_sz--; ++ if (!(cur->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ complete(&cur->complete); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ cmd_mgr->max_queue_sz = RWNX_CMD_MAX_QUEUED; ++ INIT_LIST_HEAD(&cmd_mgr->cmds); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_INITED; ++ spin_lock_init(&cmd_mgr->lock); ++ spin_lock_init(&cmd_mgr->cb_lock); ++ cmd_mgr->queue = &cmd_mgr_queue; ++ cmd_mgr->print = &cmd_mgr_print; ++ cmd_mgr->drain = &cmd_mgr_drain; ++ cmd_mgr->llind = NULL;//&cmd_mgr_llind; ++ cmd_mgr->msgind = &cmd_mgr_msgind; ++ ++#if 0 ++ INIT_WORK(&cmd_mgr->cmdWork, cmd_mgr_task_process); ++ cmd_mgr->cmd_wq = create_singlethread_workqueue("cmd_wq"); ++ if (!cmd_mgr->cmd_wq) { ++ txrx_err("insufficient memory to create cmd workqueue.\n"); ++ return; ++ } ++#endif ++} ++ ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ if(cmd_mgr->print) ++ cmd_mgr->print(cmd_mgr); ++ if(cmd_mgr->drain) ++ cmd_mgr->drain(cmd_mgr); ++ if(cmd_mgr->print) ++ cmd_mgr->print(cmd_mgr); ++ memset(cmd_mgr, 0, sizeof(*cmd_mgr)); ++} ++ ++void rwnx_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ struct aicwf_bus *bus = sdiodev->bus_if; ++ u8 *buffer = bus->cmd_buf; ++ u16 index = 0; ++ ++ memset(buffer, 0, CMD_BUF_MAX); ++ buffer[0] = (len+4) & 0x00ff; ++ buffer[1] = ((len+4) >> 8) &0x0f; ++ buffer[2] = 0x11; ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ buffer[3] = 0x0; ++ else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ buffer[3] = crc8_ponl_107(&buffer[0], 3); // crc8 ++ index += 4; ++ //there is a dummy word ++ index += 4; ++ ++ //make sure little endian ++ put_u16(&buffer[index], msg->id); ++ index += 2; ++ put_u16(&buffer[index], msg->dest_id); ++ index += 2; ++ put_u16(&buffer[index], msg->src_id); ++ index += 2; ++ put_u16(&buffer[index], msg->param_len); ++ index += 2; ++ memcpy(&buffer[index], (u8 *)msg->param, msg->param_len); ++ ++ aicwf_bus_txmsg(bus, buffer, len + 8); ++} ++ ++static inline void *rwnx_msg_zalloc(lmac_msg_id_t const id, ++ lmac_task_id_t const dest_id, ++ lmac_task_id_t const src_id, ++ uint16_t const param_len) ++{ ++ struct lmac_msg *msg; ++ gfp_t flags; ++ ++ if (in_softirq()) ++ flags = GFP_ATOMIC; ++ else ++ flags = GFP_KERNEL; ++ ++ msg = (struct lmac_msg *)kzalloc(sizeof(struct lmac_msg) + param_len, ++ flags); ++ if (msg == NULL) { ++ printk(KERN_CRIT "%s: msg allocation failed\n", __func__); ++ return NULL; ++ } ++ msg->id = id; ++ msg->dest_id = dest_id; ++ msg->src_id = src_id; ++ msg->param_len = param_len; ++ ++ return msg->param; ++} ++ ++static void rwnx_msg_free(struct lmac_msg *msg, const void *msg_params) ++{ ++ kfree(msg); ++} ++ ++ ++static int rwnx_send_msg(struct aic_sdio_dev *sdiodev, const void *msg_params, ++ int reqcfm, lmac_msg_id_t reqid, void *cfm) ++{ ++ struct lmac_msg *msg; ++ struct rwnx_cmd *cmd; ++ bool nonblock; ++ int ret = 0; ++ ++ msg = container_of((void *)msg_params, struct lmac_msg, param); ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ rwnx_msg_free(msg, msg_params); ++ printk("bus is down\n"); ++ return 0; ++ } ++ ++ nonblock = 0; ++ cmd = kzalloc(sizeof(struct rwnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL); ++ cmd->result = -EINTR; ++ cmd->id = msg->id; ++ cmd->reqid = reqid; ++ cmd->a2e_msg = msg; ++ cmd->e2a_msg = cfm; ++ if (nonblock) ++ cmd->flags = RWNX_CMD_FLAG_NONBLOCK; ++ if (reqcfm) ++ cmd->flags |= RWNX_CMD_FLAG_REQ_CFM; ++ ++ if (reqcfm) { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; // we don't need ack any more ++ ret = sdiodev->cmd_mgr.queue(&sdiodev->cmd_mgr, cmd); ++ } else { ++ rwnx_set_cmd_tx((void *)(sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ } ++ ++ if (!reqcfm) ++ kfree(cmd); ++ ++ return ret; ++} ++ ++ ++int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_size, u32 *mem_data) ++{ ++ struct dbg_mem_block_write_req *mem_blk_write_req; ++ ++ /* Build the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req = rwnx_msg_zalloc(DBG_MEM_BLOCK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_block_write_req)); ++ if (!mem_blk_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req->memaddr = mem_addr; ++ mem_blk_write_req->memsize = mem_size; ++ memcpy(mem_blk_write_req->memdata, mem_data, mem_size); ++ ++ /* Send the DBG_MEM_BLOCK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_blk_write_req, 1, DBG_MEM_BLOCK_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm) ++{ ++ struct dbg_mem_read_req *mem_read_req; ++ ++ /* Build the DBG_MEM_READ_REQ message */ ++ mem_read_req = rwnx_msg_zalloc(DBG_MEM_READ_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_read_req)); ++ if (!mem_read_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_READ_REQ message */ ++ mem_read_req->memaddr = mem_addr; ++ ++ /* Send the DBG_MEM_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_read_req, 1, DBG_MEM_READ_CFM, cfm); ++} ++ ++ ++int rwnx_send_dbg_mem_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_data) ++{ ++ struct dbg_mem_write_req *mem_write_req; ++ ++ /* Build the DBG_MEM_WRITE_REQ message */ ++ mem_write_req = rwnx_msg_zalloc(DBG_MEM_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_write_req)); ++ if (!mem_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_WRITE_REQ message */ ++ mem_write_req->memaddr = mem_addr; ++ mem_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_write_req, 1, DBG_MEM_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_mask_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_mask, u32 mem_data) ++{ ++ struct dbg_mem_mask_write_req *mem_mask_write_req; ++ ++ /* Build the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req = rwnx_msg_zalloc(DBG_MEM_MASK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_mask_write_req)); ++ if (!mem_mask_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req->memaddr = mem_addr; ++ mem_mask_write_req->memmask = mem_mask; ++ mem_mask_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_MASK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_mask_write_req, 1, DBG_MEM_MASK_WRITE_CFM, NULL); ++} ++ ++ ++int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm) ++{ ++ struct dbg_start_app_req *start_app_req; ++ ++ /* Build the DBG_START_APP_REQ message */ ++ start_app_req = rwnx_msg_zalloc(DBG_START_APP_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_start_app_req)); ++ if (!start_app_req) { ++ printk("start app nomen\n"); ++ return -ENOMEM; ++ } ++ ++ /* Set parameters for the DBG_START_APP_REQ message */ ++ start_app_req->bootaddr = boot_addr; ++ start_app_req->boottype = boot_type; ++ ++ /* Send the DBG_START_APP_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, start_app_req, 1, DBG_START_APP_CFM, start_app_cfm); ++} ++ ++static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = { ++}; ++ ++static msg_cb_fct *msg_hdlrs[] = { ++ [TASK_DBG] = dbg_hdlrs, ++}; ++ ++void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg) ++{ ++ sdiodev->cmd_mgr.msgind(&sdiodev->cmd_mgr, msg, ++ msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) ++MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver"); ++#else ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#endif ++#endif ++ ++#define MD5(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] ++#define MD5PINRT "file md5:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\r\n" ++ ++int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device) ++{ ++ ++#ifdef CONFIG_USE_FW_REQUEST ++ const struct firmware *fw = NULL; ++ u32 *dst = NULL; ++ void *buffer=NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ int size = 0; ++ int ret = 0; ++ ++ printk("%s: request firmware = %s \n", __func__ ,name); ++ ++ ++ ret = request_firmware(&fw, name, NULL); ++ ++ if (ret < 0) { ++ printk("Load %s fail\n", name); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ size = fw->size; ++ dst = (u32 *)fw->data; ++ ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ memcpy(buffer, dst, size); ++ ++ *fw_buf = buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ release_firmware(fw); ++ ++ return size; ++#else ++ void *buffer = NULL; ++ char *path = NULL; ++ struct file *fp = NULL; ++ int size = 0, len = 0;// i = 0; ++ ssize_t rdlen = 0; ++ //u32 *src = NULL, *dst = NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ ++ #ifdef CONFIG_FIRMWARE_ARRAY ++ size = aicwf_get_firmware_array((char*)name, fw_buf); ++ printk("%s size:%d \r\n", __func__, size); ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)*fw_buf, size); ++ MD5Final(&md5, decrypt); ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ return size; ++ #endif ++ ++ /* get the firmware path */ ++ path = __getname(); ++ if (!path) { ++ *fw_buf = NULL; ++ return -1; ++ } ++ ++ if(strlen(aic_fw_path) > 0){ ++ len = snprintf(path, AICBSP_FW_PATH_MAX, "%s/%s", aic_fw_path, name); ++ }else{ ++ len = snprintf(path, AICBSP_FW_PATH_MAX, "%s/%s", AICBSP_FW_PATH, name); ++ } ++ if (len >= AICBSP_FW_PATH_MAX) { ++ printk("%s: %s file's path too long\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ return -1; ++ } ++ ++ printk("%s :firmware path = %s \n", __func__, path); ++ ++ /* open the firmware file */ ++ fp = filp_open(path, O_RDONLY, 0); ++ if (IS_ERR_OR_NULL(fp)) { ++ printk("%s: %s file failed to open\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ fp = NULL; ++ return -1; ++ } ++ ++ size = i_size_read(file_inode(fp)); ++ if (size <= 0) { ++ printk("%s: %s file size invalid %d\n", __func__, name, size); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ } ++ ++ /* start to read from firmware file */ ++ buffer = vmalloc(size); ++ ++ if (!buffer) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ }else{ ++ memset(buffer, 0, size); ++ } ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) ++ rdlen = kernel_read(fp, buffer, size, &fp->f_pos); ++#else ++ rdlen = kernel_read(fp, fp->f_pos, buffer, size); ++#endif ++ ++ if (size != rdlen) { ++ printk("%s: %s file rdlen invalid %ld\n", __func__, name, (long int)rdlen); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ vfree(buffer); ++ buffer = NULL; ++ return -1; ++ } ++ if (rdlen > 0) { ++ fp->f_pos += rdlen; ++ } ++ ++#if 0 ++ /*start to transform the data format*/ ++ src = (u32 *)buffer; ++ dst = (u32 *)vmalloc(size); ++ ++ if (!dst) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ vfree(buffer); ++ buffer = NULL; ++ return -1; ++ }else{ ++ memset(dst, 0, size); ++ } ++ ++ for (i = 0; i < (size/4); i++) { ++ dst[i] = src[i]; ++ } ++#endif ++ ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ //vfree(buffer); ++ //buffer = NULL; ++ *fw_buf = (u32*)buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ return size; ++#endif ++} ++ ++extern int testmode; ++ ++#ifdef CONFIG_M2D_OTA_AUTO_SUPPORT ++extern char saved_sdk_ver[64]; ++ ++int rwnx_plat_m2d_flash_ota_android(struct aic_sdio_dev *sdiodev, char *filename) ++{ ++ struct device *dev = sdiodev->dev; ++ unsigned int i=0; ++ int size; ++ u32 *dst=NULL; ++ int err=0; ++ int ret; ++ u8 bond_id; ++ const u32 mem_addr = 0x40500000; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm); ++ if (ret) { ++ printk("m2d %x rd fail: %d\n", mem_addr, ret); ++ return ret; ++ } ++ bond_id = (u8)(rd_mem_addr_cfm.memdata >> 24); ++ printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ if (bond_id & (1<<1)) { ++ //flash is invalid ++ printk("m2d flash is invalid\n"); ++ return -1; ++ } ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if(size<=0){ ++ printk("wrong size of m2d file\n"); ++ vfree(dst); ++ dst = NULL; ++ return -1; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload m2d %s flash, size=%d\n", filename, size); ++ ++ /*send info first*/ ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_INFO_ADDR, 4, (u32 *)&size); ++ ++ /*send data first*/ ++ if (size > 1024) {// > 1KB data ++ for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, 1024, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ break; ++ } ++ } ++ } ++ ++ if (!err && (i < size)) {// <1KB data ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, size - i, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ } ++ } ++ ++ if (dst) { ++ vfree(dst); ++ dst = NULL; ++ } ++ testmode = FW_NORMAL_MODE; ++ aicbsp_info.cpmode = testmode; ++ ++ printk("m2d flash update complete\n\n"); ++ ++ return err; ++} ++ ++int rwnx_plat_m2d_flash_ota_check(struct aic_sdio_dev *sdiodev, char *filename) ++{ ++ struct device *dev = sdiodev->dev; ++ unsigned int i=0,j=0; ++ int size; ++ u32 *dst=NULL; ++ int err=0; ++ int ret=0; ++ u8 bond_id; ++ const u32 mem_addr = 0x40500000; ++ const u32 mem_addr_code_start = AIC_M2D_OTA_CODE_START_ADDR; ++ const u32 mem_addr_sdk_ver = AIC_M2D_OTA_VER_ADDR; ++ const u32 driver_code_start_idx = (AIC_M2D_OTA_CODE_START_ADDR-AIC_M2D_OTA_FLASH_ADDR)/4; ++ const u32 driver_sdk_ver_idx = (AIC_M2D_OTA_VER_ADDR-AIC_M2D_OTA_FLASH_ADDR)/4; ++ u32 driver_sdk_ver_addr_idx = 0; ++ u32 code_start_addr = 0xffffffff; ++ u32 sdk_ver_addr = 0xffffffff; ++ u32 drv_code_start_addr = 0xffffffff; ++ u32 drv_sdk_ver_addr = 0xffffffff; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ char m2d_sdk_ver[64]; ++ char flash_sdk_ver[64]; ++ u32 flash_ver[16]; ++ u32 ota_ver[16]; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm); ++ if (ret) { ++ printk("m2d %x rd fail: %d\n", mem_addr, ret); ++ return ret; ++ } ++ bond_id = (u8)(rd_mem_addr_cfm.memdata >> 24); ++ printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ if (bond_id & (1<<1)) { ++ //flash is invalid ++ printk("m2d flash is invalid\n"); ++ return -1; ++ } ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr_code_start, &rd_mem_addr_cfm); ++ if (ret){ ++ printk("mem_addr_code_start %x rd fail: %d\n", mem_addr_code_start, ret); ++ return ret; ++ } ++ code_start_addr = rd_mem_addr_cfm.memdata; ++ ++ #if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr_sdk_ver, &rd_mem_addr_cfm); ++ if (ret){ ++ printk("mem_addr_sdk_ver %x rd fail: %d\n", mem_addr_code_start, ret); ++ return ret; ++ } ++ sdk_ver_addr = rd_mem_addr_cfm.memdata; ++ #else ++ sdk_ver_addr = mem_addr_sdk_ver; ++ #endif ++ printk("code_start_addr: 0x%x, sdk_ver_addr: 0x%x\n", code_start_addr,sdk_ver_addr); ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if(size<=0){ ++ printk("wrong size of m2d file\n"); ++ vfree(dst); ++ dst = NULL; ++ return -1; ++ } ++ if(code_start_addr == 0xffffffff && sdk_ver_addr == 0xffffffff) { ++ printk("########m2d flash old version , must be upgrade\n"); ++ drv_code_start_addr = dst[driver_code_start_idx]; ++ drv_sdk_ver_addr = dst[driver_sdk_ver_idx]; ++ ++ printk("drv_code_start_addr: 0x%x, drv_sdk_ver_addr: 0x%x\n", drv_code_start_addr,drv_sdk_ver_addr); ++ ++ if(drv_sdk_ver_addr == 0xffffffff){ ++ printk("########driver m2d_ota.bin is old ,not need upgrade\n"); ++ return -1; ++ } ++ ++ } else { ++ for(i=0;i<16;i++){ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, (sdk_ver_addr+i*4), &rd_mem_addr_cfm); ++ if (ret){ ++ printk("mem_addr_sdk_ver %x rd fail: %d\n", mem_addr_code_start, ret); ++ return ret; ++ } ++ flash_ver[i] = rd_mem_addr_cfm.memdata; ++ } ++ memcpy((u8 *)flash_sdk_ver,(u8 *)flash_ver,64); ++ memcpy((u8 *)saved_sdk_ver,(u8 *)flash_sdk_ver,64); ++ printk("flash SDK Version: %s\r\n\r\n", flash_sdk_ver); ++ ++ drv_code_start_addr = dst[driver_code_start_idx]; ++ drv_sdk_ver_addr = dst[driver_sdk_ver_idx]; ++ ++ printk("drv_code_start_addr: 0x%x, drv_sdk_ver_addr: 0x%x\n", drv_code_start_addr,drv_sdk_ver_addr); ++ ++ if(drv_sdk_ver_addr == 0xffffffff){ ++ printk("########driver m2d_ota.bin is old ,not need upgrade\n"); ++ return -1; ++ } ++ ++ #if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++ driver_sdk_ver_addr_idx = (drv_sdk_ver_addr-drv_code_start_addr)/4; ++ #else ++ driver_sdk_ver_addr_idx = driver_sdk_ver_idx; ++ #endif ++ printk("driver_sdk_ver_addr_idx %d\n",driver_sdk_ver_addr_idx); ++ ++ if (driver_sdk_ver_addr_idx){ ++ for(j = 0; j < 16; j++){ ++ ota_ver[j] = dst[driver_sdk_ver_addr_idx+j]; ++ } ++ memcpy((u8 *)m2d_sdk_ver,(u8 *)ota_ver,64); ++ printk("m2d_ota SDK Version: %s\r\n\r\n", m2d_sdk_ver); ++ } else { ++ return -1; ++ } ++ ++ if(!strcmp(m2d_sdk_ver,flash_sdk_ver)){ ++ printk("######## m2d %s flash is not need upgrade\r\n", filename); ++ return -1; ++ } ++ } ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload m2d %s flash, size=%d\n", filename, size); ++ ++ /*send info first*/ ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_INFO_ADDR, 4, (u32 *)&size); ++ ++ /*send data first*/ ++ if (size > 1024) {// > 1KB data ++ for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, 1024, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ break; ++ } ++ } ++ } ++ ++ if (!err && (i < size)) {// <1KB data ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, size - i, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ } ++ } ++ ++ if (dst) { ++ vfree(dst); ++ dst = NULL; ++ } ++ testmode = FW_NORMAL_MODE; ++ ++ printk("m2d flash update complete\n\n"); ++ ++ return err; ++} ++#endif//CONFIG_M2D_OTA_AUTO_SUPPORT ++ ++int aicwf_patch_table_load(struct aic_sdio_dev *rwnx_hw, char *filename) ++{ ++ struct device *dev = rwnx_hw->dev; ++ int err = 0; ++ unsigned int i = 0, size; ++ u32 *dst = NULL; ++ u8 *describle; ++ u32 fmacfw_patch_tbl_8800dc_u02_describe_size = 124; ++ u32 fmacfw_patch_tbl_8800dc_u02_describe_base;//read from patch_tbl ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload %s \n", filename); ++ ++ size = rwnx_load_firmware(&dst, filename,dev); ++ if (!dst) { ++ printk("No such file or directory\n"); ++ return -1; ++ } ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ dst = NULL; ++ err = -1; ++ } ++ ++ printk("tbl size = %d \n",size); ++ ++ fmacfw_patch_tbl_8800dc_u02_describe_base = dst[0]; ++ AICWFDBG(LOGINFO, "FMACFW_PATCH_TBL_8800DC_U02_DESCRIBE_BASE = %x \n",fmacfw_patch_tbl_8800dc_u02_describe_base); ++ ++ if (!err && (i < size)) { ++ err=rwnx_send_dbg_mem_block_write_req(rwnx_hw, fmacfw_patch_tbl_8800dc_u02_describe_base, fmacfw_patch_tbl_8800dc_u02_describe_size + 4, dst); ++ if(err){ ++ printk("write describe information fail \n"); ++ } ++ ++ describle=kzalloc(fmacfw_patch_tbl_8800dc_u02_describe_size,GFP_KERNEL); ++ memcpy(describle,&dst[1],fmacfw_patch_tbl_8800dc_u02_describe_size); ++ printk("%s",describle); ++ kfree(describle); ++ describle=NULL; ++ } ++ ++ if (!err && (i < size)) { ++ for (i =(128/4); i < (size/4); i +=2) { ++ printk("patch_tbl: %x %x\n", dst[i], dst[i+1]); ++ err = rwnx_send_dbg_mem_write_req(rwnx_hw, dst[i], dst[i+1]); ++ } ++ if (err) { ++ printk("bin upload fail: %x, err:%d\r\n", dst[i], err); ++ } ++ } ++ ++ if (dst) { ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++#endif ++ dst = NULL; ++ } ++ ++ ++ return err; ++ ++} ++ ++extern char aic_fw_path[200]; ++int aicwf_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ #if !defined(CONFIG_FPGA_VERIFICATION) ++ if (chip_sub_id == 0) { ++ printk("u01 is loaing ###############\n"); ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_8800DC); ++ } else if (chip_sub_id == 1) { ++ printk("u02 is loaing ###############\n"); ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_8800DC_U02); ++ } else if (chip_sub_id == 2) { ++ printk("h_u02 is loaing ###############\n"); ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_8800DC_H_U02); ++ } else { ++ printk("unsupported id: %d\n", chip_sub_id); ++ } ++ #endif ++ return ret; ++} ++ ++int aicwf_plat_rftest_load_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, RAM_LMAC_FW_ADDR, RWNX_MAC_FW_RF_BASE_NAME_8800DC); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ return ret; ++} ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++int aicwf_misc_ram_valid_check_8800dc(struct aic_sdio_dev *sdiodev, int *valid_out) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_word_cnt; ++ uint32_t bit_mask[4]; ++ int i; ++ if (valid_out) { ++ *valid_out = 0; ++ } ++ if (testmode == FW_RFTEST_MODE) { ++ ++ uint32_t vect1 = 0; ++ uint32_t vect2 = 0; ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0004; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "cfg_base:%x vcet1 rd fail: %d\n", cfg_base, ret); ++ return ret; ++ } ++ vect1 = cfm.memdata; ++ if ((vect1 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) { ++ AICWFDBG(LOGERROR, "vect1 invalid: %x\n", vect1); ++ return ret; ++ } ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0008; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "cfg_base:%x vcet2 rd fail: %d\n", cfg_base, ret); ++ return ret; ++ } ++ vect2 = cfm.memdata; ++ if ((vect2 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) { ++ AICWFDBG(LOGERROR, "vect2 invalid: %x\n", vect2); ++ return ret; ++ } ++ ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ // init misc ram ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr); ++ // bit_mask ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ bit_mask[i] = cfm.memdata; ++ } ++ AICWFDBG(LOGTRACE, "bit_mask:%x,%x,%x,%x\n",bit_mask[0],bit_mask[1],bit_mask[2],bit_mask[3]); ++ if ((bit_mask[0] == 0) && ((bit_mask[1] & 0xFFF00000) == 0x80000000) && ++ (bit_mask[2] == 0) && ((bit_mask[3] & 0xFFFFFF00) == 0x00000000)) { ++ if (valid_out) { ++ *valid_out = 1; ++ } ++ } ++ return ret; ++} ++ ++int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ if (chip_sub_id == 1) { ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_CALIB_ADDR, RWNX_MAC_CALIB_NAME_8800DC_U02); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ } else if (chip_sub_id == 2) { ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_CALIB_ADDR, RWNX_MAC_CALIB_NAME_8800DC_H_U02); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++#endif ++ ++#ifdef CONFIG_DPD ++#ifndef CONFIG_FORCE_DPD_CALIB ++int is_file_exist(char* name) ++{ ++ char *path = NULL; ++ struct file *fp = NULL; ++ int len; ++ ++ path = __getname(); ++ if (!path) { ++ AICWFDBG(LOGINFO, "%s getname fail\n", __func__); ++ return -1; ++ } ++ ++ len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", AICBSP_FW_PATH, name); ++ ++ fp = filp_open(path, O_RDONLY, 0); ++ if (IS_ERR(fp)) { ++ __putname(path); ++ fp = NULL; ++ return 0; ++ } else { ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return 1; ++ } ++} ++ ++EXPORT_SYMBOL(is_file_exist); ++#endif ++#endif ++ ++#ifdef CONFIG_DPD ++rf_misc_ram_lite_t dpd_res = {{0},}; ++EXPORT_SYMBOL(dpd_res); ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++rf_misc_ram_lite_t loft_res_local = {{0},}; ++EXPORT_SYMBOL(loft_res_local); ++#endif ++ ++static int rwnx_plat_patch_load(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ AICWFDBG(LOGINFO, "testmode=%d\n", testmode); ++ if (chip_sub_id == 0) { ++ if (testmode == FW_NORMAL_MODE) { ++ AICWFDBG(LOGINFO, "rwnx_plat_patch_loading\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ } else if (testmode == FW_RFTEST_MODE) { ++ ret = aicwf_plat_rftest_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ } else if (chip_sub_id >= 1) { ++ if (testmode == FW_NORMAL_MODE) { ++ AICWFDBG(LOGINFO, "rwnx_plat_patch_loading\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ #ifdef CONFIG_DPD ++ #ifdef CONFIG_FORCE_DPD_CALIB ++ if (1) { ++ AICWFDBG(LOGINFO, "dpd calib & write\n"); ++ ret = aicwf_dpd_calib_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "dpd calib fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #else ++ if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 1) { ++ AICWFDBG(LOGINFO, "dpd bin load\n"); ++ ret = aicwf_dpd_result_load_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ ret = aicwf_dpd_result_apply_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "apply dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ else ++ #elif defined(CONFIG_LOFT_CALIB) ++ if (1) { ++ AICWFDBG(LOGINFO, "loft calib\n"); ++ ret = aicwf_loft_calib_8800dc(sdiodev, &loft_res_local); ++ if (ret) { ++ AICWFDBG(LOGINFO, "loft calib fail: %d\n", ret); ++ return ret; ++ } ++ } else ++ #endif ++ { ++ ret = aicwf_misc_ram_init_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram init fail: %d\n", ret); ++ return ret; ++ } ++ } ++ } else if (testmode == FW_RFTEST_MODE) { ++ #ifdef CONFIG_DPD ++ #ifdef CONFIG_FORCE_DPD_CALIB ++ if (1) { ++ AICWFDBG(LOGINFO, "patch load\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ AICWFDBG(LOGINFO, "dpd calib & write\n"); ++ ret = aicwf_dpd_calib_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "dpd calib fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif/*CONFIG_FORCE_DPD_CALIB*/ ++ #elif defined(CONFIG_LOFT_CALIB) ++ { ++ AICWFDBG(LOGINFO, "patch load\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ AICWFDBG(LOGINFO, "loft calib\n"); ++ ret = aicwf_loft_calib_8800dc(sdiodev, &loft_res_local); ++ if (ret) { ++ AICWFDBG(LOGINFO, "loft calib fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif/*CONFIG_DPD*/ ++ ret = aicwf_plat_rftest_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ } else if (testmode == FW_DPDCALIB_MODE) { ++ #if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++ if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 0) { ++ AICWFDBG(LOGINFO, "patch load\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ AICWFDBG(LOGINFO, "dpd calib & write\n"); ++ ret = aicwf_dpd_calib_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "dpd calib fail: %d\n", ret); ++ return ret; ++ } ++ ret = aicwf_dpd_result_write_8800dc((void *)&dpd_res, DPD_RESULT_SIZE_8800DC); ++ if (ret) { ++ AICWFDBG(LOGINFO, "file write fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ return 1; // exit calib mode ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, ++ const char *filename) ++{ ++ struct device *dev = sdiodev->dev; ++ unsigned int i = 0; ++ int size; ++ u32 *dst = NULL; ++ int err = 0; ++ ++ printk("%s\n",__func__); ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++#endif ++ dst = NULL; ++ return -1; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ if (size > 1024) {// > 1KB data ++ for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, fw_addr + i, 1024, dst + i / 4); ++ if (err) { ++ printk("bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ break; ++ } ++ } ++ } ++ ++ if (!err && (i < size)) {// <1KB data ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, fw_addr + i, size - i, dst + i / 4); ++ if (err) { ++ printk("bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ } ++ } ++ ++ if (dst) { ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++#endif ++ dst = NULL; ++ } ++ ++ return err; ++} ++ ++int aicbt_patch_table_free(struct aicbt_patch_table **head) ++{ ++ struct aicbt_patch_table *p = *head, *n = NULL; ++ while (p) { ++ n = p->next; ++ vfree(p->name); ++ vfree(p->data); ++ vfree(p); ++ p = n; ++ } ++ *head = NULL; ++ return 0; ++} ++ ++struct aicbt_patch_table *aicbt_patch_table_alloc(const char *filename) ++{ ++ uint8_t *rawdata = NULL, *p; ++ int size; ++ struct aicbt_patch_table *head = NULL, *new = NULL, *cur = NULL; ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware((u32 **)&rawdata, filename, NULL); ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ goto err; ++ } ++ ++ p = rawdata; ++ if (memcmp(p, AICBT_PT_TAG, sizeof(AICBT_PT_TAG) < 16 ? sizeof(AICBT_PT_TAG) : 16)) { ++ printk("TAG err\n"); ++ goto err; ++ } ++ p += 16; ++ ++ while (p - rawdata < size) { ++ new = (struct aicbt_patch_table *)vmalloc(sizeof(struct aicbt_patch_table)); ++ memset(new, 0, sizeof(struct aicbt_patch_table)); ++ if (head == NULL) { ++ head = new; ++ cur = new; ++ } else { ++ cur->next = new; ++ cur = cur->next; ++ } ++ ++ cur->name = (char *)vmalloc(sizeof(char) * 16); ++ memset(cur->name, 0, sizeof(char) * 16); ++ memcpy(cur->name, p, 16); ++ p += 16; ++ ++ cur->type = *(uint32_t *)p; ++ p += 4; ++ ++ cur->len = *(uint32_t *)p; ++ p += 4; ++ ++ if((cur->type ) >= 1000 ) {//Temp Workaround ++ cur->len = 0; ++ }else{ ++ if(cur->len > 0){ ++ cur->data = (uint32_t *)vmalloc(sizeof(uint8_t) * cur->len * 8); ++ memset(cur->data, 0, sizeof(uint8_t) * cur->len * 8); ++ memcpy(cur->data, p, cur->len * 8); ++ p += cur->len * 8; ++ } ++ } ++ } ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(rawdata); ++#endif ++ return head; ++ ++err: ++ aicbt_patch_table_free(&head); ++ if (rawdata) ++ vfree(rawdata); ++ return NULL; ++} ++int aicbt_patch_info_unpack(struct aicbt_patch_info_t *patch_info, struct aicbt_patch_table *head_t) ++{ ++ uint8_t *patch_info_array = (uint8_t*)patch_info; ++ int base_len = 0; ++ int memcpy_len = 0; ++ ++ if (AICBT_PT_INF == head_t->type) { ++ base_len = ((offsetof(struct aicbt_patch_info_t, ext_patch_nb_addr) - offsetof(struct aicbt_patch_info_t, adid_addrinf) )/sizeof(uint32_t))/2; ++ AICWFDBG(LOGDEBUG, "%s head_t->len:%d base_len:%d \r\n", __func__, head_t->len, base_len); ++ ++ if (head_t->len > base_len){ ++ patch_info->info_len = base_len; ++ memcpy_len = patch_info->info_len + 1;//include ext patch nb ++ } else{ ++ patch_info->info_len = head_t->len; ++ memcpy_len = patch_info->info_len; ++ } ++ AICWFDBG(LOGDEBUG, "%s memcpy_len:%d \r\n", __func__, memcpy_len); ++ ++ if (patch_info->info_len == 0) ++ return 0; ++ ++ memcpy(((patch_info_array) + sizeof(patch_info->info_len)), ++ head_t->data, ++ memcpy_len * sizeof(uint32_t) * 2); ++ AICWFDBG(LOGDEBUG, "%s adid_addrinf:%x addr_adid:%x \r\n", __func__, ++ ((struct aicbt_patch_info_t *)patch_info_array)->adid_addrinf, ++ ((struct aicbt_patch_info_t *)patch_info_array)->addr_adid); ++ ++ if (patch_info->ext_patch_nb > 0){ ++ int index = 0; ++ patch_info->ext_patch_param = (uint32_t *)(head_t->data + ((memcpy_len) * 2)); ++ ++ for(index = 0; index < patch_info->ext_patch_nb; index++){ ++ AICWFDBG(LOGDEBUG, "%s id:%x addr:%x \r\n", __func__, ++ *(patch_info->ext_patch_param + (index * 2)), ++ *(patch_info->ext_patch_param + (index * 2) + 1)); ++ } ++ } ++ ++ } ++ return 0; ++} ++ ++int aicbt_ext_patch_data_load(struct aic_sdio_dev *sdiodev, struct aicbt_patch_info_t *patch_info) ++{ ++ int ret = 0; ++ uint32_t ext_patch_nb = patch_info->ext_patch_nb; ++ char ext_patch_file_name[50]; ++ int index = 0; ++ uint32_t id = 0; ++ uint32_t addr = 0; ++ ++ ++ if (ext_patch_nb > 0){ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8800DC) { ++ AICWFDBG(LOGDEBUG, "[0x40506004]: 0x04318000\n"); ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, 0x40506004, 0x04318000); ++ AICWFDBG(LOGDEBUG, "[0x40506004]: 0x04338000\n"); ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, 0x40506004, 0x04338000); ++ } ++ for (index = 0; index < patch_info->ext_patch_nb; index++){ ++ id = *(patch_info->ext_patch_param + (index * 2)); ++ addr = *(patch_info->ext_patch_param + (index * 2) + 1); ++ memset(ext_patch_file_name, 0, sizeof(ext_patch_file_name)); ++ sprintf(ext_patch_file_name,"%s%d.bin", ++ aicbsp_firmware_list[aicbsp_info.cpmode].bt_ext_patch, ++ id); ++ AICWFDBG(LOGDEBUG, "%s ext_patch_file_name:%s ext_patch_id:%x ext_patch_addr:%x \r\n", ++ __func__,ext_patch_file_name, id, addr); ++ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, addr, ext_patch_file_name)) { ++ ret = -1; ++ break; ++ } ++ } ++ } ++ return ret; ++} ++ ++ ++int aicbt_patch_trap_data_load(struct aic_sdio_dev *sdiodev, struct aicbt_patch_table *head) ++{ ++ struct aicbt_patch_info_t patch_info = { ++ .info_len = 0, ++ .adid_addrinf = 0, ++ .addr_adid = 0, ++ .patch_addrinf = 0, ++ .addr_patch = 0, ++ .reset_addr = 0, ++ .reset_val = 0, ++ .adid_flag_addr = 0, ++ .adid_flag = 0, ++ .ext_patch_nb_addr = 0, ++ .ext_patch_nb = 0, ++ }; ++ if(head == NULL){ ++ return -1; ++ } ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR; ++ patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR; ++ } ++ else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC){ ++ if(aicbsp_info.chip_rev == CHIP_REV_U01){ ++ patch_info.addr_adid = RAM_8800DC_U01_ADID_ADDR; ++ }else if(aicbsp_info.chip_rev == CHIP_REV_U02){ ++ patch_info.addr_adid = RAM_8800DC_U02_ADID_ADDR; ++ } ++ patch_info.addr_patch = RAM_8800DC_FW_PATCH_ADDR; ++ aicbt_patch_info_unpack(&patch_info, head); ++ if(patch_info.reset_addr == 0) { ++ patch_info.reset_addr = FW_RESET_START_ADDR; ++ patch_info.reset_val = FW_RESET_START_VAL; ++ patch_info.adid_flag_addr = FW_ADID_FLAG_ADDR; ++ patch_info.adid_flag = FW_ADID_FLAG_VAL; ++ if (rwnx_send_dbg_mem_write_req(sdiodev, patch_info.reset_addr, patch_info.reset_val)) ++ return -1; ++ if (rwnx_send_dbg_mem_write_req(sdiodev, patch_info.adid_flag_addr, patch_info.adid_flag)) ++ return -1; ++ } ++ } else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ if (aicbsp_info.chip_rev == CHIP_REV_U01) { ++ patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80; ++ patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80; ++ } else if (aicbsp_info.chip_rev == CHIP_REV_U02 || aicbsp_info.chip_rev == CHIP_REV_U03) { ++ patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80_U02; ++ patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80_U02; ++ } ++ aicbt_patch_info_unpack(&patch_info, head); ++ if(patch_info.info_len == 0) { ++ printk("%s, aicbt_patch_info_unpack fail\n", __func__); ++ return -1; ++ } ++ } else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ aicbt_patch_info_unpack(&patch_info, head); ++ if(patch_info.info_len == 0) { ++ printk("%s, aicbt_patch_info_unpack fail\n", __func__); ++ return -1; ++ } ++ } ++ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, patch_info.addr_adid, aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid)) ++ return -1; ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, patch_info.addr_patch, aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch)) ++ return -1; ++ if (aicbt_ext_patch_data_load(sdiodev, &patch_info)) ++ return -1; ++ return 0; ++ ++} ++ ++static struct aicbt_info_t aicbt_info[]={ ++ { ++ .btmode = AICBT_BTMODE_DEFAULT, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT, ++ },//PRODUCT_ID_AIC8801 ++ { ++ .btmode = AICBT_BTMODE_BT_WIFI_COMBO, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800dc, ++ },//PRODUCT_ID_AIC8800DC ++ { ++ .btmode = AICBT_BTMODE_BT_WIFI_COMBO, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800dc, ++ },//PRODUCT_ID_AIC8800DW ++ { ++ .btmode = AICBT_BTMODE_DEFAULT_8800d80, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800d80, ++ },//PRODUCT_ID_AIC8800D80 ++ { ++ .btmode = AICBT_BTMODE_DEFAULT_8800d80x2, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800d80x2, ++ }//PRODUCT_ID_AIC8800D80x2 ++ ++}; ++ ++ ++int aicbt_patch_table_load(struct aic_sdio_dev *sdiodev, struct aicbt_patch_table *head) ++{ ++ struct aicbt_patch_table *p; ++ int ret = 0, i; ++ uint32_t *data = NULL; ++ if(head == NULL){ ++ return -1; ++ } ++ ++ for (p = head; p != NULL; p = p->next) { ++ data = p->data; ++ if (AICBT_PT_BTMODE == p->type) { ++ *(data + 1) = aicbsp_info.hwinfo < 0; ++ *(data + 3) = aicbsp_info.hwinfo; ++ *(data + 5) = (sdiodev->chipid == PRODUCT_ID_AIC8800DC?aicbsp_info.cpmode:0);//0;//aicbsp_info.cpmode; ++ ++ *(data + 7) = aicbt_info[sdiodev->chipid].btmode; ++ *(data + 9) = aicbt_info[sdiodev->chipid].btport; ++ *(data + 11) = aicbt_info[sdiodev->chipid].uart_baud; ++ *(data + 13) = aicbt_info[sdiodev->chipid].uart_flowctrl; ++ *(data + 15) = aicbt_info[sdiodev->chipid].lpm_enable; ++ *(data + 17) = aicbt_info[sdiodev->chipid].txpwr_lvl; ++ ++ printk("%s bt btmode[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].btmode); ++ printk("%s bt uart_baud[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].uart_baud); ++ printk("%s bt uart_flowctrl[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].uart_flowctrl); ++ printk("%s bt lpm_enable[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].lpm_enable); ++ printk("%s bt tx_pwr[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].txpwr_lvl); ++ } ++ ++ if (AICBT_PT_VER == p->type) { ++ printk("aicbsp: bt patch version: %s\n", (char *)p->data); ++ continue; ++ } ++ ++ for (i = 0; i < p->len; i++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, *data, *(data + 1)); ++ if (ret != 0) ++ return ret; ++ data += 2; ++ } ++ if (p->type == AICBT_PT_PWRON) ++ udelay(500); ++ } ++ ++ ++ ///aicbt_patch_table_free(&head); ++ return 0; ++} ++ ++ ++int aicbt_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ struct aicbt_patch_table *head = aicbt_patch_table_alloc(aicbsp_firmware_list[aicbsp_info.cpmode].bt_table); ++ if (head == NULL){ ++ printk("aicbt_patch_table_alloc fail\n"); ++ return -1; ++ } ++ ++ if (aicbt_patch_trap_data_load(sdiodev, head)) { ++ printk("aicbt_patch_trap_data_load fail\n"); ++ ret = -1; ++ goto err; ++ } ++ ++ if (aicbt_patch_table_load(sdiodev, head)) { ++ printk("aicbt_patch_table_load fail\n"); ++ ret = -1; ++ goto err; ++ } ++ ++err: ++ aicbt_patch_table_free(&head); ++ return ret; ++} ++ ++static int aicwifi_start_from_bootrom(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ ++ /* memory access */ ++ const u32 fw_addr = RAM_FMAC_FW_ADDR; ++ struct dbg_start_app_cfm start_app_cfm; ++ ++ /* fw start */ ++ ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, HOST_START_APP_AUTO, &start_app_cfm); ++ if (ret) { ++ return -1; ++ } ++ aicbsp_info.hwinfo_r = start_app_cfm.bootstatus & 0xFF; ++ ++ return 0; ++} ++ ++static int start_from_bootrom_8800DC(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ u32 rd_addr; ++ u32 fw_addr; ++ u32 boot_type; ++ struct dbg_mem_read_cfm rd_cfm; ++ ++ /* memory access */ ++ if(testmode == 1){ ++ rd_addr = RAM_LMAC_FW_ADDR; ++ fw_addr = RAM_LMAC_FW_ADDR; ++ } ++ else{ ++ rd_addr = RAM_FMAC_FW_ADDR; ++ fw_addr = RAM_FMAC_FW_ADDR; ++ } ++ ++ AICWFDBG(LOGINFO, "Read FW mem: %08x\n", rd_addr); ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_addr, &rd_cfm))) { ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "cfm: [%08x] = %08x\n", rd_cfm.memaddr, rd_cfm.memdata); ++ ++ if (testmode == 0) { ++ boot_type = HOST_START_APP_DUMMY; ++ } else { ++ boot_type = HOST_START_APP_AUTO; ++ } ++ /* fw start */ ++ AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); ++ if ((ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type ,NULL))) { ++ return -1; ++ } ++ return 0; ++} ++ ++u32 adaptivity_patch_tbl[][2] = { ++ {0x0004, 0x0000320A}, //linkloss_thd ++ {0x0094, 0x00000000}, //ac_param_conf ++ {0x00F8, 0x00010138}, //tx_adaptivity_en ++}; ++ ++u32 patch_tbl[][2] = { ++#if !defined(CONFIG_LINK_DET_5G) ++ {0x0104, 0x00000000}, //link_det_5g ++#endif ++#if defined(CONFIG_MCU_MESSAGE) ++ {0x004c, 0x0000004B}, //pkt_cnt_1724=0x4B ++ {0x0050, 0x0011FC00}, //ipc_base_addr ++#endif ++}; ++ ++u32 syscfg_tbl_masked[][3] = { ++ {0x40506024, 0x000000FF, 0x000000DF}, // for clk gate lp_level ++}; ++ ++u32 rf_tbl_masked[][3] = { ++ {0x40344058, 0x00800000, 0x00000000},// pll trx ++}; ++ ++static int aicwifi_sys_config(struct aic_sdio_dev *sdiodev) ++{ ++ int ret, cnt; ++ int syscfg_num = sizeof(syscfg_tbl_masked) / sizeof(u32) / 3; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, ++ syscfg_tbl_masked[cnt][0], syscfg_tbl_masked[cnt][1], syscfg_tbl_masked[cnt][2]); ++ if (ret) { ++ printk("%x mask write fail: %d\n", syscfg_tbl_masked[cnt][0], ret); ++ return ret; ++ } ++ } ++ ++ ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, ++ rf_tbl_masked[0][0], rf_tbl_masked[0][1], rf_tbl_masked[0][2]); ++ if (ret) { ++ printk("rf config %x write fail: %d\n", rf_tbl_masked[0][0], ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int aicwifi_patch_config(struct aic_sdio_dev *sdiodev) ++{ ++ const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0180; ++ u32 config_base; ++ uint32_t start_addr = 0x1e6000; ++ u32 patch_addr = start_addr; ++ u32 patch_num = sizeof(patch_tbl)/4; ++ struct dbg_mem_read_cfm rd_patch_addr_cfm; ++ u32 patch_addr_reg = 0x1e5318; ++ u32 patch_num_reg = 0x1e531c; ++ int ret = 0; ++ u16 cnt = 0; ++ int tmp_cnt = 0; ++ int adap_patch_num = 0; ++ ++ if (aicbsp_info.cpmode == AICBSP_CPMODE_TEST) { ++ patch_addr_reg = 0x1e5304; ++ patch_num_reg = 0x1e5308; ++ } ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch rd fail\n"); ++ return ret; ++ } ++ ++ config_base = rd_patch_addr_cfm.memdata; ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_addr_reg, patch_addr); ++ if (ret) { ++ printk("0x%x write fail\n", patch_addr_reg); ++ return ret; ++ } ++ ++ if(adap_test){ ++ printk("%s for adaptivity test \r\n", __func__); ++ adap_patch_num = sizeof(adaptivity_patch_tbl)/4; ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_num_reg, patch_num + adap_patch_num); ++ }else{ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_num_reg, patch_num); ++ } ++ if (ret) { ++ printk("0x%x write fail\n", patch_num_reg); ++ return ret; ++ } ++ ++ for (cnt = 0; cnt < patch_num/2; cnt += 1) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl[cnt][0]+config_base); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl[cnt][1]); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ return ret; ++ } ++ } ++ ++ tmp_cnt = cnt; ++ ++ if(adap_test){ ++ for(cnt = 0; cnt < adap_patch_num/2; cnt+=1) ++ { ++ if((ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*(cnt+tmp_cnt), adaptivity_patch_tbl[cnt][0]+config_base))) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ } ++ ++ if((ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*(cnt+tmp_cnt)+4, adaptivity_patch_tbl[cnt][1]))) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int aicwifi_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ #ifdef CONFIG_M2D_OTA_AUTO_SUPPORT ++ if (testmode == FW_M2D_OTA_MODE) { ++ rwnx_plat_m2d_flash_ota_android(sdiodev, FW_M2D_OTA_NAME); ++ } else if (testmode == FW_NORMAL_MODE) { ++ rwnx_plat_m2d_flash_ota_check(sdiodev, FW_M2D_OTA_NAME); ++ } ++ #endif ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { ++ printk("download wifi fw fail\n"); ++ return -1; ++ } ++ if (testmode == FW_NORMAL_MODE) { ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_PATCH_ADDR, RAM_FMAC_FW_PATCH_NAME)) { ++ printk("download wifi fw patch fail\n"); ++ return -1; ++ } ++ } ++ ++ if (aicwifi_patch_config(sdiodev)) { ++ printk("aicwifi_patch_config fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_sys_config(sdiodev)) { ++ printk("aicwifi_sys_config fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_start_from_bootrom(sdiodev)) { ++ printk("wifi start fail\n"); ++ return -1; ++ } ++ }else if (sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ printk("############ aicwifi_init begin \n"); ++ ++ system_config_8800dc(sdiodev); ++ printk("############ system_config_8800dc done\n"); ++ ++ ret = rwnx_plat_patch_load(sdiodev); ++ if (ret) { ++ printk("patch load return %d\n", ret); ++ return ret; ++ } ++ printk("############ rwnx_plat_patch_load done\n"); ++ ++ //rwnx_plat_userconfig_load(sdiodev); ++ ++ aicwf_patch_config_8800dc(sdiodev); ++ printk("############ aicwf_patch_config_8800dc done\n"); ++ ++ start_from_bootrom_8800DC(sdiodev); ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { ++ printk("8800d80 download wifi fw fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_patch_config_8800d80(sdiodev)) { ++ printk("aicwifi_patch_config_8800d80 fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_sys_config_8800d80(sdiodev)) { ++ printk("aicwifi_patch_config_8800d80 fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_start_from_bootrom(sdiodev)) { ++ printk("8800d80 wifi start fail\n"); ++ return -1; ++ } ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { ++ printk("8800d80x2 download wifi fw fail\n"); ++ return -1; ++ } ++ if (aicwifi_start_from_bootrom(sdiodev)) { ++ printk("8800d80x2 wifi start fail\n"); ++ return -1; ++ } ++ } ++ ++#if (defined(CONFIG_GPIO_WAKEUP) || defined(CONFIG_SDIO_PWRCTRL)) ++ if (aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 4)) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ return -1; ++ } ++#endif ++ return 0; ++} ++ ++u32 aicbsp_syscfg_tbl[][2] = { ++ {0x40500014, 0x00000101}, // 1) ++ {0x40500018, 0x00000109}, // 2) ++ {0x40500004, 0x00000010}, // 3) the order should not be changed ++ ++ // def CONFIG_PMIC_SETTING ++ // U02 bootrom only ++ {0x40040000, 0x00001AC8}, // 1) fix panic ++ {0x40040084, 0x00011580}, ++ {0x40040080, 0x00000001}, ++ {0x40100058, 0x00000000}, ++ ++ {0x50000000, 0x03220204}, // 2) pmic interface init ++ {0x50019150, 0x00000002}, // 3) for 26m xtal, set div1 ++ {0x50017008, 0x00000000}, // 4) stop wdg ++}; ++ ++static int aicbsp_system_config(struct aic_sdio_dev *sdiodev) ++{ ++ int syscfg_num = sizeof(aicbsp_syscfg_tbl) / sizeof(u32) / 2; ++ int ret, cnt; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl[cnt][0], aicbsp_syscfg_tbl[cnt][1]); ++ if (ret) { ++ sdio_err("%x write fail: %d\n", aicbsp_syscfg_tbl[cnt][0], ret); ++ return ret; ++ } ++ } ++ return 0; ++} ++ ++ ++ ++int aicbsp_platform_init(struct aic_sdio_dev *sdiodev) ++{ ++ rwnx_cmd_mgr_init(&sdiodev->cmd_mgr); ++ sdiodev->cmd_mgr.sdiodev = (void *)sdiodev; ++ ++ return 0; ++} ++ ++void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev) ++{ ++ (void)sdiodev; ++} ++ ++int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev) ++{ ++ u32 mem_addr; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ u32 btenable = 0; ++ u8 is_chip_id_h = 0; ++ int ret = 0; ++ ++ mem_addr = 0x40500000; ++ ++ testmode = aicbsp_info.cpmode; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)(rd_mem_addr_cfm.memdata >> 16); ++ btenable = 1; ++ ++ if (aicbsp_info.chip_rev != CHIP_REV_U02 && ++ aicbsp_info.chip_rev != CHIP_REV_U03 && ++ aicbsp_info.chip_rev != CHIP_REV_U04) { ++ pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ return -1; ++ } ++ ++ if (aicbsp_info.chip_rev != CHIP_REV_U02) ++ aicbsp_firmware_list = fw_u03; ++ ++ if (aicbsp_system_config(sdiodev)) ++ return -1; ++ } ++ else if (sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); ++ is_chip_id_h = (u8)(((rd_mem_addr_cfm.memdata >> 16) & 0xC0) == 0xC0); ++ ++ btenable = ((rd_mem_addr_cfm.memdata >> 26) & 0x1); ++ AICWFDBG(LOGINFO, "btenable = %d \n",btenable); ++ ++ if(btenable == 0){ ++ sdiodev->chipid = PRODUCT_ID_AIC8800DW; ++ AICWFDBG(LOGINFO, "AIC8800DC change to AIC8800DW \n"); ++ } ++ ++ if (aicbsp_info.chip_rev != CHIP_REV_U01 && ++ aicbsp_info.chip_rev != CHIP_REV_U02 && ++ aicbsp_info.chip_rev != CHIP_REV_U03 && ++ aicbsp_info.chip_rev != CHIP_REV_U04) { ++ pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ return -1; ++ } ++ if (is_chip_id_h) { ++ AICWFDBG(LOGINFO, "IS_CHIP_ID_H \n"); ++ aicbsp_firmware_list = fw_8800dc_h_u02; ++ } else { ++ if(aicbsp_info.chip_rev == CHIP_REV_U01){ ++ aicbsp_firmware_list = fw_8800dc_u01; ++ }else{ ++ aicbsp_firmware_list = fw_8800dc_u02; ++ } ++ } ++ } ++ else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); ++ is_chip_id_h = (u8)(((rd_mem_addr_cfm.memdata >> 16) & 0xC0) == 0xC0); ++ btenable = 1; ++ if (is_chip_id_h) { ++ AICWFDBG(LOGINFO, "IS_CHIP_ID_H \n"); ++ aicbsp_firmware_list = fw_8800d80_h_u02; ++ } else { ++ if (aicbsp_info.chip_rev == CHIP_REV_U01) ++ aicbsp_firmware_list = fw_8800d80_u01; ++ if (aicbsp_info.chip_rev == CHIP_REV_U02 || aicbsp_info.chip_rev == CHIP_REV_U03) ++ aicbsp_firmware_list = fw_8800d80_u02; ++ } ++ if (aicbsp_system_config_8800d80(sdiodev)) ++ return -1; ++ } ++ else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ btenable = 1; ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); ++ if (aicbsp_info.chip_rev >= (CHIP_REV_U04 + 8)) ++ aicbsp_firmware_list = fw_8800d80x2; ++ else{ ++ pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ return -1; ++ } ++ } ++ ++ AICWFDBG(LOGINFO, "aicbsp: %s, chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ ++ #ifndef CONFIG_MCU_MESSAGE ++ if (testmode != 4) { ++ if(btenable == 1){ ++ if (aicbt_init(sdiodev)) ++ return -1; ++ } ++ } ++ #endif ++ ++ ret = aicwifi_init(sdiodev); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path) ++{ ++ if (aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ feature->sdio_clock = FEATURE_SDIO_CLOCK; ++ }else if (aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800D80 || aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ feature->sdio_clock = FEATURE_SDIO_CLOCK_V3; ++ } ++ feature->sdio_phase = FEATURE_SDIO_PHASE; ++ feature->hwinfo = aicbsp_info.hwinfo; ++ feature->fwlog_en = aicbsp_info.fwlog_en; ++ feature->irqf = aicbsp_info.irqf; ++ if(fw_path != NULL){ ++ sprintf(fw_path,"%s", AICBSP_FW_PATH); ++ } ++ ++ sdio_dbg("%s, set FEATURE_SDIO_CLOCK %d MHz\n", __func__, feature->sdio_clock/1000000); ++ return 0; ++} ++ ++EXPORT_SYMBOL_GPL(aicbsp_get_feature); ++ ++#ifdef CONFIG_RESV_MEM_SUPPORT ++static struct skb_buff_pool resv_skb[] = { ++ {AIC_RESV_MEM_TXDATA, 1536*64, "resv_mem_txdata", 0, NULL}, ++}; ++ ++int aicbsp_resv_mem_init(void) ++{ ++ int i = 0; ++ printk("%s \n",__func__); ++ for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) { ++ resv_skb[i].skb = dev_alloc_skb(resv_skb[i].size); ++ } ++ return 0; ++} ++ ++int aicbsp_resv_mem_deinit(void) ++{ ++ int i = 0; ++ printk("%s \n",__func__); ++ for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) { ++ if (resv_skb[i].used == 0 && resv_skb[i].skb) ++ dev_kfree_skb(resv_skb[i].skb); ++ } ++ return 0; ++} ++ ++struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id) ++{ ++ if (resv_skb[id].size < length) { ++ pr_err("aicbsp: %s, no enough mem\n", __func__); ++ goto fail; ++ } ++ ++ if (resv_skb[id].used) { ++ pr_err("aicbsp: %s, mem in use\n", __func__); ++ goto fail; ++ } ++ ++ if (resv_skb[id].skb == NULL) { ++ pr_err("aicbsp: %s, mem not initialazed\n", __func__); ++ resv_skb[id].skb = dev_alloc_skb(resv_skb[id].size); ++ if (resv_skb[id].skb == NULL) { ++ pr_err("aicbsp: %s, mem reinitial still fail\n", __func__); ++ goto fail; ++ } ++ } ++ ++ printk("aicbsp: %s, alloc %s succuss, id: %d, size: %d\n", __func__, ++ resv_skb[id].name, resv_skb[id].id, resv_skb[id].size); ++ ++ resv_skb[id].used = 1; ++ return resv_skb[id].skb; ++ ++fail: ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(aicbsp_resv_mem_alloc_skb); ++ ++void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id) ++{ ++ resv_skb[id].used = 0; ++ printk("aicbsp: %s, free %s succuss, id: %d, size: %d\n", __func__, ++ resv_skb[id].name, resv_skb[id].id, resv_skb[id].size); ++} ++EXPORT_SYMBOL_GPL(aicbsp_resv_mem_kfree_skb); ++ ++#else ++ ++int aicbsp_resv_mem_init(void) ++{ ++ return 0; ++} ++ ++int aicbsp_resv_mem_deinit(void) ++{ ++ return 0; ++} ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h +new file mode 100644 +index 000000000000..f18253d168a3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h +@@ -0,0 +1,598 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.h ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _AIC_BSP_DRIVER_H ++#define _AIC_BSP_DRIVER_H ++ ++#include ++#include ++#include ++#include "aic_bsp_export.h" ++ ++#define RWNX_80211_CMD_TIMEOUT_MS 6000//500//300 ++ ++#define RWNX_CMD_FLAG_NONBLOCK BIT(0) ++#define RWNX_CMD_FLAG_REQ_CFM BIT(1) ++#define RWNX_CMD_FLAG_WAIT_PUSH BIT(2) ++#define RWNX_CMD_FLAG_WAIT_ACK BIT(3) ++#define RWNX_CMD_FLAG_WAIT_CFM BIT(4) ++#define RWNX_CMD_FLAG_DONE BIT(5) ++/* ATM IPC design makes it possible to get the CFM before the ACK, ++ * otherwise this could have simply been a state enum */ ++#define RWNX_CMD_WAIT_COMPLETE(flags) \ ++ (!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM))) ++ ++#define RWNX_CMD_MAX_QUEUED 8 ++ ++#define IPC_E2A_MSG_PARAM_SIZE 256 ++ ++#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ ++ ++/* message levels */ ++#define LOGERROR 0x0001 ++#define LOGINFO 0x0002 ++#define LOGTRACE 0x0004 ++#define LOGDEBUG 0x0008 ++#define LOGDATA 0x0010 ++ ++extern int aicwf_dbg_level_bsp; ++ ++#define AICWF_LOG "AICWFDBG(" ++ ++#define AICWFDBG(level, args, arg...) \ ++do { \ ++ if (aicwf_dbg_level_bsp & level) { \ ++ printk(AICWF_LOG#level")\t" args, ##arg); \ ++ } \ ++} while (0) ++ ++#define RWNX_DBG(fmt, ...) \ ++do { \ ++ if (aicwf_dbg_level_bsp & LOGTRACE) { \ ++ printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \ ++ } \ ++} while (0) ++ ++/// Message structure for MSGs from Emb to App ++struct ipc_e2a_msg { ++ u16 id; ///< Message id. ++ u16 dummy_dest_id; ++ u16 dummy_src_id; ++ u16 param_len; ///< Parameter embedded struct length. ++ u32 pattern; ///< Used to stamp a valid MSG buffer ++ u32 param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++typedef u16 lmac_msg_id_t; ++typedef u16 lmac_task_id_t; ++ ++struct lmac_msg { ++ lmac_msg_id_t id; ///< Message id. ++ lmac_task_id_t dest_id; ///< Destination kernel identifier. ++ lmac_task_id_t src_id; ///< Source kernel identifier. ++ u16 param_len; ///< Parameter embedded struct length. ++ u32 param[]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++#define rwnx_cmd_e2amsg ipc_e2a_msg ++#define rwnx_cmd_a2emsg lmac_msg ++#define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len) ++#define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4) ++ ++static inline void put_u16(u8 *buf, u16 data) ++{ ++ buf[0] = (u8)(data&0x00ff); ++ buf[1] = (u8)((data >> 8)&0x00ff); ++} ++ ++enum rwnx_cmd_mgr_state { ++ RWNX_CMD_MGR_STATE_DEINIT, ++ RWNX_CMD_MGR_STATE_INITED, ++ RWNX_CMD_MGR_STATE_CRASHED, ++}; ++ ++struct rwnx_cmd { ++ struct list_head list; ++ lmac_msg_id_t id; ++ lmac_msg_id_t reqid; ++ struct rwnx_cmd_a2emsg *a2e_msg; ++ char *e2a_msg; ++ u32 tkn; ++ u16 flags; ++ struct completion complete; ++ u32 result; ++}; ++ ++struct aic_sdio_dev; ++struct rwnx_cmd; ++typedef int (*msg_cb_fct)(struct rwnx_cmd *cmd, struct rwnx_cmd_e2amsg *msg); ++ ++struct rwnx_cmd_mgr { ++ enum rwnx_cmd_mgr_state state; ++ spinlock_t lock; ++ u32 next_tkn; ++ u32 queue_sz; ++ u32 max_queue_sz; ++ spinlock_t cb_lock; ++ void *sdiodev; ++ ++ struct list_head cmds; ++ ++ int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct); ++ void (*print)(struct rwnx_cmd_mgr *); ++ void (*drain)(struct rwnx_cmd_mgr *); ++ ++ struct work_struct cmdWork; ++ struct workqueue_struct *cmd_wq; ++}; ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr); ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr); ++int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd); ++void rwnx_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len); ++ ++enum { ++ TASK_NONE = (u8) -1, ++ ++ // MAC Management task. ++ TASK_MM = 0, ++ // DEBUG task ++ TASK_DBG, ++ /// SCAN task ++ TASK_SCAN, ++ /// TDLS task ++ TASK_TDLS, ++ /// SCANU task ++ TASK_SCANU, ++ /// ME task ++ TASK_ME, ++ /// SM task ++ TASK_SM, ++ /// APM task ++ TASK_APM, ++ /// BAM task ++ TASK_BAM, ++ /// MESH task ++ TASK_MESH, ++ /// RXU task ++ TASK_RXU, ++ // This is used to define the last task that is running on the EMB processor ++ TASK_LAST_EMB = TASK_RXU, ++ ++ // nX API task ++ TASK_API, ++ TASK_MAX, ++}; ++ ++#define LMAC_FIRST_MSG(task) ((lmac_msg_id_t)((task) << 10)) ++#define DRV_TASK_ID 100 ++#define MSG_I(msg) ((msg) & ((1<<10)-1)) ++#define MSG_T(msg) ((lmac_task_id_t)((msg) >> 10)) ++ ++enum dbg_msg_tag { ++ /// Memory read request ++ DBG_MEM_READ_REQ = LMAC_FIRST_MSG(TASK_DBG), ++ /// Memory read confirm ++ DBG_MEM_READ_CFM, ++ /// Memory write request ++ DBG_MEM_WRITE_REQ, ++ /// Memory write confirm ++ DBG_MEM_WRITE_CFM, ++ /// Module filter request ++ DBG_SET_MOD_FILTER_REQ, ++ /// Module filter confirm ++ DBG_SET_MOD_FILTER_CFM, ++ /// Severity filter request ++ DBG_SET_SEV_FILTER_REQ, ++ /// Severity filter confirm ++ DBG_SET_SEV_FILTER_CFM, ++ /// LMAC/MAC HW fatal error indication ++ DBG_ERROR_IND, ++ /// Request to get system statistics ++ DBG_GET_SYS_STAT_REQ, ++ /// COnfirmation of system statistics ++ DBG_GET_SYS_STAT_CFM, ++ /// Memory block write request ++ DBG_MEM_BLOCK_WRITE_REQ, ++ /// Memory block write confirm ++ DBG_MEM_BLOCK_WRITE_CFM, ++ /// Start app request ++ DBG_START_APP_REQ, ++ /// Start app confirm ++ DBG_START_APP_CFM, ++ /// Start npc request ++ DBG_START_NPC_REQ, ++ /// Start npc confirm ++ DBG_START_NPC_CFM, ++ /// Memory mask write request ++ DBG_MEM_MASK_WRITE_REQ, ++ /// Memory mask write confirm ++ DBG_MEM_MASK_WRITE_CFM, ++ ++ DBG_RFTEST_CMD_REQ, ++ DBG_RFTEST_CMD_CFM, ++ DBG_BINDING_REQ, ++ DBG_BINDING_CFM, ++ DBG_BINDING_IND, ++ ++ DBG_CUSTOM_MSG_REQ, ++ DBG_CUSTOM_MSG_CFM, ++ DBG_CUSTOM_MSG_IND, ++ ++ DBG_GPIO_WRITE_REQ, ++ DBG_GPIO_WRITE_CFM, ++ ++ ++ /// Max number of Debug messages ++ DBG_MAX, ++}; ++ ++#if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++#define FW_M2D_OTA_NAME "m2d_ota.bin" ++#else ++#define FW_M2D_OTA_NAME "m2d_ota_lzma.bin" ++#endif ++ ++enum { ++ HOST_START_APP_AUTO = 1, ++ HOST_START_APP_CUSTOM, ++ HOST_START_APP_FNCALL = 4, ++ HOST_START_APP_DUMMY = 5, ++}; ++ ++ ++struct dbg_mem_block_write_req { ++ u32 memaddr; ++ u32 memsize; ++ u32 memdata[1024 / sizeof(u32)]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_CFM message. ++struct dbg_mem_block_write_cfm { ++ u32 wstatus; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_REQ message. ++struct dbg_mem_write_req { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_CFM message. ++struct dbg_mem_write_cfm { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_REQ message. ++struct dbg_mem_read_req { ++ u32 memaddr; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_CFM message. ++struct dbg_mem_read_cfm { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_REQ message. ++struct dbg_mem_mask_write_req { ++ u32 memaddr; ++ u32 memmask; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_CFM message. ++struct dbg_mem_mask_write_cfm { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_REQ message. ++struct dbg_start_app_req { ++ u32 bootaddr; ++ u32 boottype; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_CFM message. ++struct dbg_start_app_cfm { ++ u32 bootstatus; ++}; ++ ++int aicwf_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev); ++int aicwf_plat_rftest_load_8800dc(struct aic_sdio_dev *sdiodev); ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++int aicwf_misc_ram_valid_check_8800dc(struct aic_sdio_dev *sdiodev, int *valid_out); ++int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev); ++#endif ++ ++int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device); ++int aicwf_patch_table_load(struct aic_sdio_dev *rwnx_hw, char *filename); ++ ++int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm); ++int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_size, u32 *mem_data); ++int rwnx_send_dbg_mem_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_data); ++int rwnx_send_dbg_mem_mask_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_mask, u32 mem_data); ++int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm); ++ ++int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, const char *filename); ++ ++void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg); ++int aicbsp_platform_init(struct aic_sdio_dev *sdiodev); ++void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev); ++int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev); ++#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++int is_file_exist(char* name); ++#endif ++int aicbsp_resv_mem_init(void); ++int aicbsp_resv_mem_deinit(void); ++ ++#define AICBSP_FW_PATH CONFIG_AIC_FW_PATH ++#define AICBSP_FW_PATH_MAX 200 ++ ++#define RAM_FMAC_FW_ADDR 0x00120000 ++#define RAM_FMAC_FW_PATCH_ADDR 0x00190000 ++#define FW_RAM_ADID_BASE_ADDR 0x00161928 ++#define FW_RAM_ADID_BASE_ADDR_U03 0x00161928 ++#define FW_RAM_PATCH_BASE_ADDR 0x00100000 ++#define RAM_8800DC_U01_ADID_ADDR 0x00101788 ++#define RAM_8800DC_U02_ADID_ADDR 0x001017d8 ++#define RAM_8800DC_FW_PATCH_ADDR 0x00184000 ++#define FW_RESET_START_ADDR 0x40500128 ++#define FW_RESET_START_VAL 0x40 ++#define FW_ADID_FLAG_ADDR 0x40500150 ++#define FW_ADID_FLAG_VAL 0x01 ++#define FW_RAM_ADID_BASE_ADDR_8800D80 0x002017E0 ++#define FW_RAM_PATCH_BASE_ADDR_8800D80 0x0020B2B0 ++#define FW_RAM_ADID_BASE_ADDR_8800D80_U02 0x00201940 ++#define FW_RAM_PATCH_BASE_ADDR_8800D80_U02 0x0020b43c ++ ++#define AICBT_PT_TAG "AICBT_PT_TAG" ++ ++ ++/***************************************************************************** ++ * Addresses within RWNX_ADDR_CPU ++ *****************************************************************************/ ++#define RAM_LMAC_FW_ADDR 0x00150000 ++ ++#define ROM_FMAC_FW_ADDR 0x00010000 ++#define ROM_FMAC_PATCH_ADDR 0x00180000 ++ ++#define RAM_FMAC_FW_PATCH_NAME "fmacfw_patch.bin" ++#define RWNX_MAC_CALIB_BASE_NAME_8800DC "fmacfw_calib_8800dc" ++#define RWNX_MAC_CALIB_NAME_8800DC_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_u02.bin" ++#ifdef CONFIG_SDIO_BT ++#define RWNX_MAC_CALIB_NAME_8800DC_H_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_hbt_u02.bin" ++#else ++#define RWNX_MAC_CALIB_NAME_8800DC_H_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_h_u02.bin" ++#endif ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++#define ROM_FMAC_CALIB_ADDR 0x00130000 ++#endif ++#ifdef CONFIG_DPD ++#ifndef CONFIG_FORCE_DPD_CALIB ++#define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_lite_8800dc.bin" ++#endif ++#endif ++ ++#define RWNX_MAC_FW_RF_BASE_NAME_8800DC "lmacfw_rf_8800dc.bin" ++ ++#ifdef CONFIG_FOR_IPCOM ++#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc_ipc" ++#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin" ++#else ++#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc" ++#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin" ++#define RWNX_MAC_PATCH_NAME2_8800DC_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_u02.bin" ++#ifdef CONFIG_SDIO_BT ++#define RWNX_MAC_PATCH_NAME2_8800DC_H_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_hbt_u02.bin" ++#else ++#define RWNX_MAC_PATCH_NAME2_8800DC_H_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_h_u02.bin" ++#endif ++#endif ++ ++#define RWNX_MAC_PATCH_TABLE_NAME_8800DC "fmacfw_patch_tbl_8800dc" ++#define RWNX_MAC_PATCH_TABLE_8800DC RWNX_MAC_PATCH_TABLE_NAME_8800DC ".bin" ++#define RWNX_MAC_PATCH_TABLE_8800DC_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_u02.bin" ++#ifdef CONFIG_SDIO_BT ++#define RWNX_MAC_PATCH_TABLE_8800DC_H_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_hbt_u02.bin" ++#else ++#define RWNX_MAC_PATCH_TABLE_8800DC_H_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_h_u02.bin" ++#endif ++ ++#define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc" ++#define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin" ++#define FW_USERCONFIG_NAME_8800DC "aic_userconfig_8800dc.txt" ++ ++enum { ++ FW_NORMAL_MODE = 0, ++ FW_RFTEST_MODE = 1, ++ FW_BLE_SCAN_WAKEUP_MODE = 2, ++ FW_M2D_OTA_MODE = 3, ++ FW_DPDCALIB_MODE = 4, ++ FW_BLE_SCAN_AD_FILTER_MODE = 5, ++}; ++ ++enum aicbt_patch_table_type { ++ AICBT_PT_INF = 0x00, ++ AICBT_PT_TRAP = 0x1, ++ AICBT_PT_B4, ++ AICBT_PT_BTMODE, ++ AICBT_PT_PWRON, ++ AICBT_PT_AF, ++ AICBT_PT_VER, ++}; ++ ++enum aicbt_btport_type { ++ AICBT_BTPORT_NULL, ++ AICBT_BTPORT_MB, ++ AICBT_BTPORT_UART, ++}; ++ ++/* btmode ++ * used for force bt mode,if not AICBSP_MODE_NULL ++ * efuse valid and vendor_info will be invalid, even has beed set valid ++*/ ++enum aicbt_btmode_type { ++ AICBT_BTMODE_BT_ONLY_SW = 0x0, // bt only mode with switch ++ AICBT_BTMODE_BT_WIFI_COMBO, // wifi/bt combo mode ++ AICBT_BTMODE_BT_ONLY, // bt only mode without switch ++ AICBT_BTMODE_BT_ONLY_TEST, // bt only test mode ++ AICBT_BTMODE_BT_WIFI_COMBO_TEST, // wifi/bt combo test mode ++ AICBT_BTMODE_BT_ONLY_COANT, // bt only mode with no external switch ++ AICBT_MODE_NULL = 0xFF, // invalid value ++}; ++ ++/* uart_baud ++ * used for config uart baud when btport set to uart, ++ * otherwise meaningless ++*/ ++enum aicbt_uart_baud_type { ++ AICBT_UART_BAUD_115200 = 115200, ++ AICBT_UART_BAUD_921600 = 921600, ++ AICBT_UART_BAUD_1_5M = 1500000, ++ AICBT_UART_BAUD_3_25M = 3250000, ++}; ++ ++enum aicbt_uart_flowctrl_type { ++ AICBT_UART_FLOWCTRL_DISABLE = 0x0, // uart without flow ctrl ++ AICBT_UART_FLOWCTRL_ENABLE, // uart with flow ctrl ++}; ++ ++enum aicbsp_cpmode_type { ++ AICBSP_CPMODE_WORK, ++ AICBSP_CPMODE_TEST, ++ AICBSP_CPMODE_MAX, ++}; ++ ++enum chip_rev { ++ CHIP_REV_U01 = 1, ++ CHIP_REV_U02 = 3, ++ CHIP_REV_U03 = 7, ++ CHIP_REV_U04 = 7, ++}; ++ ++#define AIC_M2D_OTA_INFO_ADDR 0x88000020 ++#define AIC_M2D_OTA_DATA_ADDR 0x88000040 ++#if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++#define AIC_M2D_OTA_FLASH_ADDR 0x08004000 ++#define AIC_M2D_OTA_CODE_START_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x0188) ++#define AIC_M2D_OTA_VER_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x018C) ++#else ++#define AIC_M2D_OTA_FLASH_ADDR 0x08005000 ++#define AIC_M2D_OTA_CODE_START_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x1188) ++#define AIC_M2D_OTA_VER_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x0010) ++#endif ++///aic bt tx pwr lvl :lsb->msb: first byte, min pwr lvl; second byte, max pwr lvl; ++///pwr lvl:20(min), 30 , 40 , 50 , 60(max) ++#define AICBT_TXPWR_LVL 0x00006020 ++#define AICBT_TXPWR_LVL_8800dc 0x00006f2f ++#define AICBT_TXPWR_LVL_8800d80 0x00006f2f ++#define AICBT_TXPWR_LVL_8800d80x2 0x00006f2f ++ ++ ++#define AICBSP_HWINFO_DEFAULT (-1) ++#define AICBSP_CPMODE_DEFAULT AICBSP_CPMODE_WORK ++#define AICBSP_FWLOG_EN_DEFAULT 0 ++ ++#define AICBT_BTMODE_DEFAULT_8800d80x2 AICBT_BTMODE_BT_ONLY_COANT ++#define AICBT_BTMODE_DEFAULT_8800d80 AICBT_BTMODE_BT_ONLY_COANT ++#define AICBT_BTMODE_DEFAULT AICBT_BTMODE_BT_ONLY_SW ++#ifdef CONFIG_SDIO_BT ++#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_MB ++#else ++#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_UART ++#endif ++#define AICBT_UART_BAUD_DEFAULT AICBT_UART_BAUD_1_5M ++#define AICBT_UART_FC_DEFAULT AICBT_UART_FLOWCTRL_ENABLE ++#define AICBT_LPM_ENABLE_DEFAULT 0 ++#define AICBT_TXPWR_LVL_DEFAULT AICBT_TXPWR_LVL ++#define AICBT_TXPWR_LVL_DEFAULT_8800dc AICBT_TXPWR_LVL_8800dc ++#define AICBT_TXPWR_LVL_DEFAULT_8800d80 AICBT_TXPWR_LVL_8800d80 ++#define AICBT_TXPWR_LVL_DEFAULT_8800d80x2 AICBT_TXPWR_LVL_8800d80x2 ++ ++ ++#define FEATURE_SDIO_CLOCK 50000000 // 0: default, other: target clock rate ++#define FEATURE_SDIO_CLOCK_V3 150000000 // 0: default, other: target clock rate ++#define FEATURE_SDIO_PHASE 2 // 0: default, 2: 180° ++ ++struct aicbt_patch_table { ++ char *name; ++ uint32_t type; ++ uint32_t *data; ++ uint32_t len; ++ struct aicbt_patch_table *next; ++}; ++ ++struct aicbt_info_t { ++ uint32_t btmode; ++ uint32_t btport; ++ uint32_t uart_baud; ++ uint32_t uart_flowctrl; ++ uint32_t lpm_enable; ++ uint32_t txpwr_lvl; ++}; ++ ++struct aicbt_patch_info_t { ++ uint32_t info_len; ++//base len start ++ uint32_t adid_addrinf; ++ uint32_t addr_adid; ++ uint32_t patch_addrinf; ++ uint32_t addr_patch; ++ uint32_t reset_addr; ++ uint32_t reset_val; ++ uint32_t adid_flag_addr; ++ uint32_t adid_flag; ++//base len end ++//ext patch nb ++ uint32_t ext_patch_nb_addr; ++ uint32_t ext_patch_nb; ++ uint32_t *ext_patch_param; ++}; ++ ++struct aicbsp_firmware { ++ const char *desc; ++ const char *bt_adid; ++ const char *bt_patch; ++ const char *bt_table; ++ const char *wl_fw; ++ const char *bt_ext_patch; ++}; ++ ++struct aicbsp_info_t { ++ int hwinfo; ++ int hwinfo_r; ++ uint32_t cpmode; ++ uint32_t chip_rev; ++ bool fwlog_en; ++ uint8_t irqf; ++}; ++ ++extern struct aicbsp_info_t aicbsp_info; ++extern struct mutex aicbsp_power_lock; ++extern const struct aicbsp_firmware *aicbsp_firmware_list; ++extern const struct aicbsp_firmware fw_u02[]; ++extern const struct aicbsp_firmware fw_u03[]; ++extern const struct aicbsp_firmware fw_8800dc_u01[]; ++extern const struct aicbsp_firmware fw_8800dc_u02[]; ++extern const struct aicbsp_firmware fw_8800dc_h_u02[]; ++extern const struct aicbsp_firmware fw_8800d80_u01[]; ++extern const struct aicbsp_firmware fw_8800d80_u02[]; ++extern const struct aicbsp_firmware fw_8800d80_h_u02[]; ++extern const struct aicbsp_firmware fw_8800d80x2[]; ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h +new file mode 100644 +index 000000000000..5535df6e0d14 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h +@@ -0,0 +1,71 @@ ++#ifndef __AIC_BSP_EXPORT_H ++#define __AIC_BSP_EXPORT_H ++ ++enum aicbsp_subsys { ++ AIC_BLUETOOTH, ++ AIC_WIFI, ++}; ++ ++enum aicbsp_pwr_state { ++ AIC_PWR_OFF, ++ AIC_PWR_ON, ++}; ++ ++enum skb_buff_id { ++ AIC_RESV_MEM_TXDATA, ++}; ++ ++struct skb_buff_pool { ++ uint32_t id; ++ uint32_t size; ++ const char *name; ++ uint8_t used; ++ struct sk_buff *skb; ++}; ++ ++struct aicbsp_feature_t { ++ int hwinfo; ++ uint32_t sdio_clock; ++ uint8_t sdio_phase; ++ bool fwlog_en; ++ uint8_t irqf; ++}; ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++typedef struct { ++ uint32_t bit_mask[3]; ++ uint32_t reserved; ++ uint32_t dpd_high[96]; ++ uint32_t dpd_11b[96]; ++ uint32_t dpd_low[96]; ++ uint32_t idac_11b[48]; ++ uint32_t idac_high[48]; ++ uint32_t idac_low[48]; ++ uint32_t loft_res[18]; ++ uint32_t rx_iqim_res[16]; ++} rf_misc_ram_t; ++ ++typedef struct { ++ uint32_t bit_mask[4]; ++ uint32_t dpd_high[96]; ++ uint32_t loft_res[18]; ++} rf_misc_ram_lite_t; ++ ++#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) ++#define DPD_RESULT_SIZE_8800DC sizeof(rf_misc_ram_lite_t) ++#endif ++ ++#ifdef CONFIG_DPD ++extern rf_misc_ram_lite_t dpd_res; ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++extern rf_misc_ram_lite_t loft_res_local; ++#endif ++ ++int aicbsp_set_subsys(int, int); ++int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path); ++struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id); ++void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c +new file mode 100644 +index 000000000000..406781997f6f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c +@@ -0,0 +1,456 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aic_bsp_driver.h" ++#include "rwnx_version_gen.h" ++#include "aicwf_txq_prealloc.h" ++ ++ ++#define DRV_DESCRIPTION "AIC BSP" ++#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi" ++#define DRV_AUTHOR "AICSemi" ++#define DRV_VERS_MOD "1.0" ++ ++int aicwf_dbg_level_bsp = LOGERROR; ++ ++struct semaphore aicbsp_probe_semaphore; ++ ++static struct platform_device *aicbsp_pdev; ++ ++const struct aicbsp_firmware *aicbsp_firmware_list = fw_u02; ++ ++const struct aicbsp_firmware fw_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(sdio u02)", ++ .bt_adid = "fw_adid.bin", ++ .bt_patch = "fw_patch.bin", ++ .bt_table = "fw_patch_table.bin", ++ #ifdef CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt.bin" ++ #else ++ .wl_fw = "fmacfw.bin" ++ #endif ++ }, ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(sdio u02)", ++ .bt_adid = "fw_adid.bin", ++ .bt_patch = "fw_patch.bin", ++ .bt_table = "fw_patch_table.bin", ++ .wl_fw = "fmacfw_rf.bin" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_u03[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(sdio u03/u04)", ++ .bt_adid = "fw_adid_u03.bin", ++ .bt_patch = "fw_patch_u03.bin", ++ .bt_table = "fw_patch_table_u03.bin", ++ #ifdef CONFIG_MCU_MESSAGE ++ .wl_fw = "fmacfw_8800m_custmsg.bin" ++ #elif defined(CONFIG_SDIO_BT) ++ .wl_fw = "fmacfwbt.bin" ++ #else ++ .wl_fw = "fmacfw.bin" ++ #endif ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(sdio u03/u04)", ++ .bt_adid = "fw_adid_u03.bin", ++ .bt_patch = "fw_patch_u03.bin", ++ .bt_table = "fw_patch_table_u03.bin", ++ .wl_fw = "fmacfw_rf.bin" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800dc_u01[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(sdio u01)", ++ .bt_adid = "fw_adid_8800dc.bin", ++ .bt_patch = "fw_patch_8800dc.bin", ++ .bt_table = "fw_patch_table_8800dc.bin", ++ .wl_fw = "fmacfw_8800dc.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(sdio u01)", ++ .bt_adid = "fw_adid_8800dc.bin", ++ .bt_patch = "fw_patch_8800dc.bin", ++ .bt_table = "fw_patch_table_8800dc.bin", ++ .wl_fw = "fmacfw_rf_8800dc.bin" ++ }, ++}; ++ ++ ++const struct aicbsp_firmware fw_8800dc_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800dc sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02.bin", ++ .bt_patch = "fw_patch_8800dc_u02.bin", ++ .bt_table = "fw_patch_table_8800dc_u02.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02_ext", ++ .wl_fw = "fmacfw_patch_8800dc_u02.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800dc sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02.bin", ++ .bt_patch = "fw_patch_8800dc_u02.bin", ++ .bt_table = "fw_patch_table_8800dc_u02.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02_ext", ++ .wl_fw = "lmacfw_rf_8800dc.bin" //u01,u02 lmacfw load same bin ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800dc_h_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800dc_h sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02h.bin", ++ .bt_patch = "fw_patch_8800dc_u02h.bin", ++ .bt_table = "fw_patch_table_8800dc_u02h.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02h_ext", ++ .wl_fw = "fmacfw_patch_8800dc_h_u02.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800dc_h sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02h.bin", ++ .bt_patch = "fw_patch_8800dc_u02h.bin", ++ .bt_table = "fw_patch_table_8800dc_u02h.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02h_ext", ++ .wl_fw = "lmacfw_rf_8800dc.bin" //u01,u02 lmacfw load same bin ++ }, ++}; ++ ++ ++const struct aicbsp_firmware fw_8800d80_u01[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80 sdio u01)", ++ .bt_adid = "fw_adid_8800d80.bin", ++ .bt_patch = "fw_patch_8800d80.bin", ++ .bt_table = "fw_patch_table_8800d80.bin", ++ .wl_fw = "fmacfw_8800d80.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80 sdio u01)", ++ .bt_adid = "fw_adid_8800d80.bin", ++ .bt_patch = "fw_patch_8800d80.bin", ++ .bt_table = "fw_patch_table_8800d80.bin", ++ .wl_fw = "lmacfw_rf_8800d80.bin" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800d80_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80 sdio u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ #if defined CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_u02.bin", ++ #elif defined CONFIG_FOR_IPCAM ++ .wl_fw = "fmacfw_8800d80_u02_ipc.bin", ++ #else ++ .wl_fw = "fmacfw_8800d80_u02.bin", ++ #endif ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80 sdio u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ .wl_fw = "lmacfw_rf_8800d80_u02.bin", ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800d80_h_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80 sdio h_u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ #if defined CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_h_u02.bin", ++ #elif defined CONFIG_FOR_IPCAM ++ .wl_fw = "fmacfw_8800d80_h_u02_ipc.bin", ++ #else ++ .wl_fw = "fmacfw_8800d80_h_u02.bin", ++ #endif ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80 sdio u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ .wl_fw = "lmacfw_rf_8800d80_u02.bin", ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800d80x2[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80x2 sdio)", ++ .bt_adid = "fw_adid_8800d80x2_u05.bin", ++ .bt_patch = "fw_patch_8800d80x2_u05.bin", ++ .bt_table = "fw_patch_table_8800d80x2_u05.bin", ++ #ifdef CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_h_u02.bin", ++ #else ++ .wl_fw = "fmacfw_8800d80x2.bin", ++ #endif ++ .bt_ext_patch = "fw_patch_8800d80x2_u05_ext" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80x2 sdio)", ++ .bt_adid = "fw_adid_8800d80x2_u05.bin", ++ .bt_patch = "fw_patch_8800d80x2_u05.bin", ++ .bt_table = "fw_patch_table_8800d80x2_u05.bin", ++ .wl_fw = "lmacfw_rf_8800d80x2.bin", ++ .bt_ext_patch = "fw_patch_8800d80x2_u05_ext" ++ }, ++}; ++ ++struct aicbsp_info_t aicbsp_info = { ++ .hwinfo_r = AICBSP_HWINFO_DEFAULT, ++ .hwinfo = AICBSP_HWINFO_DEFAULT, ++ .cpmode = AICBSP_CPMODE_DEFAULT, ++ .fwlog_en = AICBSP_FWLOG_EN_DEFAULT, ++#ifdef CONFIG_IRQ_FALL ++ .irqf = 1, ++#else ++ .irqf = 0, ++#endif ++}; ++ ++struct mutex aicbsp_power_lock; ++ ++static struct platform_driver aicbsp_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "aic_bsp", ++ }, ++ //.probe = aicbsp_probe, ++ //.remove = aicbsp_remove, ++}; ++ ++static ssize_t cpmode_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t count = 0; ++ uint8_t i = 0; ++ ++ count += sprintf(&buf[count], "Support mode value:\n"); ++ ++ for (i = 0; i < AICBSP_CPMODE_MAX; i++) { ++ if (aicbsp_firmware_list[i].desc) ++ count += sprintf(&buf[count], " %2d: %s\n", i, aicbsp_firmware_list[i].desc); ++ } ++ ++ count += sprintf(&buf[count], "Current: %d, firmware info:\n", aicbsp_info.cpmode); ++ count += sprintf(&buf[count], " BT ADID : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid); ++ count += sprintf(&buf[count], " BT PATCH: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch); ++ count += sprintf(&buf[count], " BT TABLE: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_table); ++ count += sprintf(&buf[count], " WIFI FW : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw); ++ return count; ++} ++ ++static ssize_t cpmode_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ int err = kstrtoul(buf, 0, &val); ++ if (err) ++ return err; ++ ++ if (val >= AICBSP_CPMODE_MAX) { ++ pr_err("mode value must less than %d\n", AICBSP_CPMODE_MAX); ++ return -EINVAL; ++ } ++ ++ aicbsp_info.cpmode = val; ++ printk("%s, set mode to: %lu[%s] done\n", __func__, val, aicbsp_firmware_list[val].desc); ++ ++ return count; ++} ++ ++static ssize_t hwinfo_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t count = 0; ++ ++ count += sprintf(&buf[count], "chip hw rev: "); ++ if (aicbsp_info.hwinfo_r < 0) ++ count += sprintf(&buf[count], "-1(not avalible)\n"); ++ else ++ count += sprintf(&buf[count], "0x%02X\n", aicbsp_info.chip_rev); ++ ++ count += sprintf(&buf[count], "hwinfo read: "); ++ if (aicbsp_info.hwinfo_r < 0) ++ count += sprintf(&buf[count], "%d(not avalible), ", aicbsp_info.hwinfo_r); ++ else ++ count += sprintf(&buf[count], "0x%02X, ", aicbsp_info.hwinfo_r); ++ ++ if (aicbsp_info.hwinfo < 0) ++ count += sprintf(&buf[count], "set: %d(not avalible)\n", aicbsp_info.hwinfo); ++ else ++ count += sprintf(&buf[count], "set: 0x%02X\n", aicbsp_info.hwinfo); ++ ++ return count; ++} ++ ++static ssize_t hwinfo_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ long val; ++ int err = kstrtol(buf, 0, &val); ++ ++ if (err) { ++ pr_err("invalid input\n"); ++ return err; ++ } ++ ++ if ((val == -1) || (val >= 0 && val <= 0xFF)) { ++ aicbsp_info.hwinfo = val; ++ } else { ++ pr_err("invalid values\n"); ++ return -EINVAL; ++ } ++ return count; ++} ++ ++static ssize_t fwdebug_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t count = 0; ++ ++ count += sprintf(&buf[count], "fw log status: %s\n", ++ aicbsp_info.fwlog_en ? "on" : "off"); ++ ++ return count; ++} ++ ++static ssize_t fwdebug_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ long val; ++ int err = kstrtol(buf, 0, &val); ++ ++ if (err) { ++ pr_err("invalid input\n"); ++ return err; ++ } ++ ++ if (val > 1 || val < 0) { ++ pr_err("must be 0 or 1\n"); ++ return -EINVAL; ++ } ++ ++ aicbsp_info.fwlog_en = val; ++ return count; ++} ++ ++static DEVICE_ATTR(cpmode, S_IRUGO | S_IWUSR, ++ cpmode_show, cpmode_store); ++ ++static DEVICE_ATTR(hwinfo, S_IRUGO | S_IWUSR, ++ hwinfo_show, hwinfo_store); ++ ++static DEVICE_ATTR(fwdebug, S_IRUGO | S_IWUSR, ++ fwdebug_show, fwdebug_store); ++ ++static struct attribute *aicbsp_attributes[] = { ++ &dev_attr_cpmode.attr, ++ &dev_attr_hwinfo.attr, ++ &dev_attr_fwdebug.attr, ++ NULL, ++}; ++ ++static struct attribute_group aicbsp_attribute_group = { ++ .name = "aicbsp_info", ++ .attrs = aicbsp_attributes, ++}; ++ ++int testmode = AICBSP_CPMODE_DEFAULT; ++int adap_test = 0; ++module_param(testmode, int, 0660); ++module_param(adap_test, int, 0660); ++ ++ ++static int __init aicbsp_init(void) ++{ ++ int ret; ++ printk("%s\n", __func__); ++ printk("RELEASE_DATE:%s\r\n", RELEASE_DATE); ++ ++ aicbsp_info.cpmode = testmode; ++ ++ aicbsp_resv_mem_init(); ++ ++ sema_init(&aicbsp_probe_semaphore, 0); ++ ++ ret = platform_driver_register(&aicbsp_driver); ++ if (ret) { ++ pr_err("register platform driver failed: %d\n", ret); ++ return ret; ++ } ++ ++ aicbsp_pdev = platform_device_alloc("aic-bsp", -1); ++ ret = platform_device_add(aicbsp_pdev); ++ if (ret) { ++ pr_err("register platform device failed: %d\n", ret); ++ return ret; ++ } ++ ++ ret = sysfs_create_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group); ++ if (ret) { ++ pr_err("register sysfs create group failed!\n"); ++ return ret; ++ } ++ ++ mutex_init(&aicbsp_power_lock); ++#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 ++ aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON); ++#endif ++ return 0; ++} ++ ++void aicbsp_sdio_exit(void); ++extern struct aic_sdio_dev *aicbsp_sdiodev; ++ ++static void __exit aicbsp_exit(void) ++{ ++#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 ++ if(aicbsp_sdiodev){ ++ aicbsp_sdio_exit(); ++ } ++#endif ++ sysfs_remove_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group); ++ platform_device_del(aicbsp_pdev); ++ platform_driver_unregister(&aicbsp_driver); ++ mutex_destroy(&aicbsp_power_lock); ++ aicbsp_resv_mem_deinit(); ++#ifdef CONFIG_PREALLOC_TXQ ++ aicwf_prealloc_txq_free(); ++#endif ++ printk("%s\n", __func__); ++} ++ ++module_init(aicbsp_init); ++module_exit(aicbsp_exit); ++ ++MODULE_DESCRIPTION(DRV_DESCRIPTION); ++MODULE_VERSION(DRV_VERS_MOD); ++MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c +new file mode 100644 +index 000000000000..9ed440f912eb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c +@@ -0,0 +1,2040 @@ ++/** ++ * aicwf_sdmmc.c ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aicsdio_txrxif.h" ++#include "aicsdio.h" ++#include "aic_bsp_driver.h" ++#include ++#include ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#include ++#endif /* CONFIG_PLATFORM_ROCKCHIP */ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#include ++#endif /* CONFIG_PLATFORM_ROCKCHIP */ ++ ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++extern void sunxi_mmc_rescan_card(unsigned ids); ++extern void sunxi_wlan_set_power(int on); ++extern int sunxi_wlan_get_bus_index(void); ++static int aicbsp_bus_index = -1; ++#endif ++ ++#ifdef CONFIG_PLATFORM_AMLOGIC//for AML ++#include ++extern void sdio_reinit(void); ++extern void extern_wifi_set_enable(int is_on); ++extern void set_power_control_lock(int lock); ++#endif//for AML ++ ++ ++static int aicbsp_platform_power_on(void); ++static void aicbsp_platform_power_off(void); ++ ++struct aic_sdio_dev *aicbsp_sdiodev = NULL; ++static struct semaphore *aicbsp_notify_semaphore; ++extern struct semaphore aicbsp_probe_semaphore; ++ ++static const struct sdio_device_id aicbsp_sdmmc_ids[]; ++static bool aicbsp_load_fw_in_fdrv = false; ++ ++#define FW_PATH_MAX 200 ++ ++//#ifdef CONFIG_PLATFORM_UBUNTU ++//static const char* aic_default_fw_path = "/lib/firmware/aic8800_sdio"; ++//#else ++static const char* aic_default_fw_path = CONFIG_AIC_FW_PATH; ++//#endif ++char aic_fw_path[FW_PATH_MAX]; ++module_param_string(aic_fw_path, aic_fw_path, FW_PATH_MAX, 0660); ++#ifdef CONFIG_M2D_OTA_AUTO_SUPPORT ++char saved_sdk_ver[64]; ++module_param_string(saved_sdk_ver, saved_sdk_ver,64, 0660); ++#endif ++ ++extern int testmode; ++ ++ ++#define SDIO_DEVICE_ID_AIC8801_FUNC2 0x0146 ++#define SDIO_DEVICE_ID_AIC8800D80_FUNC2 0x0182 ++ ++/* SDIO Device ID */ ++#define SDIO_VENDOR_ID_AIC8801 0x5449 ++#define SDIO_VENDOR_ID_AIC8800DC 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80X2 0xc8a1 ++ ++#define SDIO_DEVICE_ID_AIC8801 0x0145 ++#define SDIO_DEVICE_ID_AIC8800DC 0xc08d ++#define SDIO_DEVICE_ID_AIC8800D80 0x0082 ++#define SDIO_DEVICE_ID_AIC8800D80X2 0x2082 ++ ++ ++static int aicbsp_dummy_probe(struct sdio_func *func, const struct sdio_device_id *id) ++{ ++ if (func && (func->num != 2)) ++ return 0; ++ ++ if(func->vendor != SDIO_VENDOR_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801_FUNC2 && ++ func->vendor != SDIO_VENDOR_ID_AIC8800DC && ++ func->device != SDIO_DEVICE_ID_AIC8800DC && ++ func->vendor != SDIO_VENDOR_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80_FUNC2){ ++ printk("VID:%x DID:%X \r\n", func->vendor, func->device); ++ aicbsp_load_fw_in_fdrv = true; ++ } ++ ++ if (aicbsp_notify_semaphore) ++ up(aicbsp_notify_semaphore); ++ return 0; ++} ++ ++static void aicbsp_dummy_remove(struct sdio_func *func) ++{ ++} ++ ++static struct sdio_driver aicbsp_dummy_sdmmc_driver = { ++ .probe = aicbsp_dummy_probe, ++ .remove = aicbsp_dummy_remove, ++ .name = "aicbsp_dummy_sdmmc", ++ .id_table = aicbsp_sdmmc_ids, ++}; ++ ++static int aicbsp_reg_sdio_notify(void *semaphore) ++{ ++ aicbsp_notify_semaphore = semaphore; ++ return sdio_register_driver(&aicbsp_dummy_sdmmc_driver); ++} ++ ++static void aicbsp_unreg_sdio_notify(void) ++{ ++ mdelay(15); ++ sdio_unregister_driver(&aicbsp_dummy_sdmmc_driver); ++} ++ ++static const char *aicbsp_subsys_name(int subsys) ++{ ++ switch (subsys) { ++ case AIC_BLUETOOTH: ++ return "AIC_BLUETOOTH"; ++ case AIC_WIFI: ++ return "AIC_WIFI"; ++ default: ++ return "unknown subsys"; ++ } ++} ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#if 1//FOR RK SUSPEND ++void rfkill_rk_sleep_bt(bool sleep); ++#endif ++#endif ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#if 1//FOR RK SUSPEND ++void rfkill_rk_sleep_bt(bool sleep); ++#endif ++#endif ++ ++int aicbsp_set_subsys(int subsys, int state) ++{ ++ static int pre_power_map; ++ int cur_power_map; ++ int pre_power_state; ++ int cur_power_state; ++ ++ mutex_lock(&aicbsp_power_lock); ++ aicbsp_load_fw_in_fdrv = false; ++ cur_power_map = pre_power_map; ++ if (state) ++ cur_power_map |= (1 << subsys); ++ else ++ cur_power_map &= ~(1 << subsys); ++ ++ pre_power_state = pre_power_map > 0; ++ cur_power_state = cur_power_map > 0; ++ ++ sdio_dbg("%s, subsys: %s, state to: %d\n", __func__, aicbsp_subsys_name(subsys), state); ++ ++ if (cur_power_state != pre_power_state) { ++ sdio_dbg("%s, power state change to %d dure to %s\n", __func__, cur_power_state, aicbsp_subsys_name(subsys)); ++ if (cur_power_state) { ++ if (aicbsp_platform_power_on() < 0) ++ goto err0; ++ if (aicbsp_sdio_init()) ++ goto err1; ++ if (aicbsp_driver_fw_init(aicbsp_sdiodev)) ++ goto err2; ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ aicbsp_sdio_release(aicbsp_sdiodev); ++#endif ++ ++#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(true); ++ printk("%s BT wake default to SLEEP\r\n", __func__); ++#endif ++#endif ++ ++//#ifndef CONFIG_PLATFORM_ROCKCHIP ++// aicbsp_sdio_exit(); ++//#endif ++ } else { ++ #ifndef CONFIG_PLATFORM_ROCKCHIP ++ aicbsp_sdio_exit(); ++ #endif ++ aicbsp_platform_power_off(); ++ } ++ } else { ++ sdio_dbg("%s, power state no need to change, current: %d\n", __func__, cur_power_state); ++ } ++ pre_power_map = cur_power_map; ++ mutex_unlock(&aicbsp_power_lock); ++ ++ return cur_power_state; ++ ++err2: ++ aicbsp_sdio_release(aicbsp_sdiodev); ++ aicbsp_sdio_exit(); ++ ++err1: ++ aicbsp_platform_power_off(); ++ ++err0: ++ sdio_dbg("%s, fail to set %s power state to %d\n", __func__, aicbsp_subsys_name(subsys), state); ++ mutex_unlock(&aicbsp_power_lock); ++ return -1; ++} ++EXPORT_SYMBOL_GPL(aicbsp_set_subsys); ++ ++bool aicbsp_get_load_fw_in_fdrv(void){ ++ return aicbsp_load_fw_in_fdrv; ++} ++ ++EXPORT_SYMBOL_GPL(aicbsp_get_load_fw_in_fdrv); ++ ++static int aicwf_sdio_chipmatch(struct aic_sdio_dev *sdio_dev, uint16_t vid, uint16_t did){ ++ ++ if(vid == SDIO_VENDOR_ID_AIC8801 && did == SDIO_DEVICE_ID_AIC8801){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8801; ++ AICWFDBG(LOGINFO, "%s USE AIC8801\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800DC && did == SDIO_DEVICE_ID_AIC8800DC){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800DC; ++ AICWFDBG(LOGINFO, "%s USE AIC8800DC\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80 && did == SDIO_DEVICE_ID_AIC8800D80){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80X2 && did == SDIO_DEVICE_ID_AIC8800D80X2){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80X2; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80X2\r\n", __func__); ++ return 0; ++ }else{ ++ return -1; ++ } ++} ++ ++void *aicbsp_get_drvdata(void *args) ++{ ++ (void)args; ++ if (aicbsp_sdiodev) ++ return aicbsp_sdiodev->bus_if; ++ return dev_get_drvdata((const struct device *)args); ++} ++ ++ ++static int aicbsp_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ struct mmc_host *host; ++ struct aic_sdio_dev *sdiodev; ++ struct aicwf_bus *bus_if; ++ int err = -ENODEV; ++ ++ if (func == NULL) { ++ sdio_err("%s func is null\n", __func__); ++ return err; ++ } ++ ++ sdio_dbg("%s:%d vid:0x%04X did:0x%04X\n", __func__, func->num, ++ func->vendor, func->device); ++ ++ if(func->vendor != SDIO_VENDOR_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801_FUNC2 && ++ func->vendor != SDIO_VENDOR_ID_AIC8800DC && ++ func->device != SDIO_DEVICE_ID_AIC8800DC && ++ func->vendor != SDIO_VENDOR_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80_FUNC2){ ++ aicbsp_load_fw_in_fdrv = true; ++ return err; ++ } ++ ++ if (func->num != 2) { ++ return err; ++ } ++ ++ host = func->card->host; ++ host->caps |= MMC_CAP_NONREMOVABLE; ++ ++ func = func->card->sdio_func[1 - 1]; //replace 2 with 1 ++ ++ sdio_dbg("%s after replace:%d\n", __func__, func->num); ++ ++ bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_KERNEL); ++ if (!bus_if) { ++ sdio_err("alloc bus fail\n"); ++ return -ENOMEM; ++ } ++ ++ ++ sdiodev = kzalloc(sizeof(struct aic_sdio_dev), GFP_KERNEL); ++ if (!sdiodev) { ++ sdio_err("alloc sdiodev fail\n"); ++ kfree(bus_if); ++ return -ENOMEM; ++ } ++ aicbsp_sdiodev = sdiodev; ++ ++ err = aicwf_sdio_chipmatch(sdiodev, func->vendor, func->device); ++ ++ sdiodev->func = func; ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdiodev->func_msg = func->card->sdio_func[1]; ++ } ++ sdiodev->bus_if = bus_if; ++ bus_if->bus_priv.sdio = sdiodev; ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ dev_set_drvdata(&sdiodev->func_msg->dev, bus_if); ++ printk("the device is PRODUCT_ID_AIC8800DC \n"); ++ } ++ dev_set_drvdata(&func->dev, bus_if); ++ sdiodev->dev = &func->dev; ++ ++ if (sdiodev->chipid != PRODUCT_ID_AIC8800D80 && sdiodev->chipid != PRODUCT_ID_AIC8800D80X2) { ++ err = aicwf_sdio_func_init(sdiodev); ++ } else { ++ err = aicwf_sdiov3_func_init(sdiodev); ++ } ++ if (err < 0) { ++ sdio_err("sdio func init fail\n"); ++ goto fail; ++ } ++ ++ if (aicwf_sdio_bus_init(sdiodev) == NULL) { ++ sdio_err("sdio bus init err\r\n"); ++ goto fail; ++ } ++ ++ aicbsp_platform_init(sdiodev); ++ ++ up(&aicbsp_probe_semaphore); ++ ++ return 0; ++fail: ++ aicwf_sdio_func_deinit(sdiodev); ++ dev_set_drvdata(&func->dev, NULL); ++ kfree(sdiodev); ++ kfree(bus_if); ++ return err; ++} ++ ++ ++static void aicbsp_sdio_remove(struct sdio_func *func) ++{ ++ struct mmc_host *host; ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_sdio_dev *sdiodev = NULL; ++ ++ AICWFDBG(LOGINFO, "%s\n", __func__); ++ if (aicbsp_sdiodev == NULL) { ++ AICWFDBG(LOGERROR, "%s: allready unregister\n", __func__); ++ goto done; ++ } ++ if (func == NULL) { ++ AICWFDBG(LOGERROR, "%s, sdio func is null\n", __func__); ++ goto done; ++ } ++ ++ host = func->card->host; ++ host->caps &= ~MMC_CAP_NONREMOVABLE; ++ ++ bus_if = aicbsp_get_drvdata(&func->dev); ++ ++ if (!bus_if) { ++ AICWFDBG(LOGERROR, "%s bus_if is NULL \r\n", __func__); ++ goto done; ++ } ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ if (!sdiodev) { ++ AICWFDBG(LOGERROR, "%s sdiodev is NULL \r\n", __func__); ++ goto done; ++ } ++ ++ aicwf_sdio_release(sdiodev); ++ aicwf_sdio_func_deinit(sdiodev); ++ ++ dev_set_drvdata(&sdiodev->func->dev, NULL); ++ kfree(sdiodev); ++ ++done: ++ if (bus_if) ++ kfree(bus_if); ++ aicbsp_sdiodev = NULL; ++ sdio_dbg("%s done\n", __func__); ++} ++ ++ ++static int aicbsp_sdio_suspend(struct device *dev) ++{ ++ struct sdio_func *func = dev_to_sdio_func(dev); ++ int err; ++ mmc_pm_flag_t sdio_flags; ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(false); ++#endif ++#endif ++ ++ sdio_dbg("%s, func->num = %d\n", __func__, func->num); ++ if (func->num != 2) ++ return 0; ++ ++ sdio_flags = sdio_get_host_pm_caps(func); ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ sdio_dbg("%s: can't keep power while host is suspended\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* keep power while host suspended */ ++ err = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); ++ if (err) { ++ sdio_dbg("%s: error while trying to keep power\n", __func__); ++ return err; ++ } ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(true); ++ printk("%s BT wake to SLEEP\r\n", __func__); ++#endif ++#endif ++ ++ return 0; ++} ++ ++static int aicbsp_sdio_resume(struct device *dev) ++{ ++ sdio_dbg("%s\n", __func__); ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(false); ++#endif ++#endif ++ ++ return 0; ++} ++ ++static const struct sdio_device_id aicbsp_sdmmc_ids[] = { ++ {SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN)}, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(sdio, aicbsp_sdmmc_ids); ++ ++static const struct dev_pm_ops aicbsp_sdio_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(aicbsp_sdio_suspend, aicbsp_sdio_resume) ++}; ++ ++static struct sdio_driver aicbsp_sdio_driver = { ++ .probe = aicbsp_sdio_probe, ++ .remove = aicbsp_sdio_remove, ++ .name = AICBSP_SDIO_NAME, ++ .id_table = aicbsp_sdmmc_ids, ++ .drv = { ++ .pm = &aicbsp_sdio_pm_ops, ++ }, ++}; ++ ++static int aicbsp_platform_power_on(void) ++{ ++ int ret = 0; ++ struct semaphore aic_chipup_sem; ++ sdio_dbg("%s\n", __func__); ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ if (aicbsp_bus_index < 0) ++ aicbsp_bus_index = sunxi_wlan_get_bus_index(); ++ if (aicbsp_bus_index < 0) ++ return aicbsp_bus_index; ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++ mdelay(200); ++ extern_wifi_set_enable(1); ++ mdelay(200); ++ sdio_reinit(); ++ set_power_control_lock(1); ++#endif ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ rockchip_wifi_power(0); ++ mdelay(50); ++ rockchip_wifi_power(1); ++ mdelay(50); ++ rockchip_wifi_set_carddetect(1); ++#endif /*CONFIG_PLATFORM_ROCKCHIP2*/ ++ ++ sema_init(&aic_chipup_sem, 0); ++ ret = aicbsp_reg_sdio_notify(&aic_chipup_sem); ++ if (ret) { ++ sdio_dbg("%s aicbsp_reg_sdio_notify fail(%d)\n", __func__, ret); ++ return ret; ++ } ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ sunxi_wlan_set_power(0); ++ mdelay(50); ++ sunxi_wlan_set_power(1); ++ mdelay(50); ++ sunxi_mmc_rescan_card(aicbsp_bus_index); ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++ if (down_timeout(&aic_chipup_sem, msecs_to_jiffies(2000)) == 0) { ++ aicbsp_unreg_sdio_notify(); ++ if(aicbsp_load_fw_in_fdrv){ ++ printk("%s load fw in fdrv\r\n", __func__); ++ return -1; ++ } ++ return 0; ++ } ++ ++ aicbsp_unreg_sdio_notify(); ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ sunxi_wlan_set_power(0); ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++#endif ++ ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ rockchip_wifi_power(0); ++#endif /*CONFIG_PLATFORM_ROCKCHIP2*/ ++ ++ return -1; ++} ++ ++static void aicbsp_platform_power_off(void) ++{ ++//TODO wifi disable and sdio card detection ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ if (aicbsp_bus_index < 0) ++ aicbsp_bus_index = sunxi_wlan_get_bus_index(); ++ if (aicbsp_bus_index < 0) { ++ sdio_dbg("no aicbsp_bus_index\n"); ++ return; ++ } ++ sunxi_wlan_set_power(0); ++ mdelay(100); ++ sunxi_mmc_rescan_card(aicbsp_bus_index); ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ rockchip_wifi_set_carddetect(0); ++ mdelay(200); ++ rockchip_wifi_power(0); ++ mdelay(200); ++#endif /*CONFIG_PLATFORM_ROCKCHIP*/ ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++#endif ++ ++ ++ sdio_dbg("%s\n", __func__); ++} ++ ++ ++int aicbsp_sdio_init(void) ++{ ++ ++ if (sdio_register_driver(&aicbsp_sdio_driver)) { ++ return -1; ++ } else { ++ //may add mmc_rescan here ++ } ++ if (down_timeout(&aicbsp_probe_semaphore, msecs_to_jiffies(2000)) != 0){ ++ printk("%s aicbsp_sdio_probe fail\r\n", __func__); ++ return -1; ++ } ++ ++ ++ return 0; ++} ++ ++void aicbsp_sdio_exit(void) ++{ ++ sdio_unregister_driver(&aicbsp_sdio_driver); ++} ++ ++void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev) ++{ ++ sdiodev->bus_if->state = BUS_DOWN_ST; ++ sdio_claim_host(sdiodev->func); ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func_msg); ++ sdio_release_irq(sdiodev->func_msg); ++ sdio_release_host(sdiodev->func_msg); ++ } ++} ++ ++int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ *val = sdio_readb(sdiodev->func, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_readb_func2(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func_msg); ++ *val = sdio_readb(sdiodev->func_msg, regaddr, &ret); ++ sdio_release_host(sdiodev->func_msg); ++ return ret; ++} ++ ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ sdio_writeb(sdiodev->func, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_writeb_func2(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func_msg); ++ sdio_writeb(sdiodev->func_msg, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func_msg); ++ return ret; ++} ++ ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = -1; ++ u8 fc_reg = 0; ++ u32 count = 0; ++ ++ while (true) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.flow_ctrl_reg, &fc_reg); ++ if (ret) { ++ return -1; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ fc_reg = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; ++ } ++ ++ if (fc_reg != 0) { ++ ret = fc_reg; ++ return ret; ++ } else { ++ if (count >= FLOW_CTRL_RETRY_COUNT) { ++ ret = -fc_reg; ++ break; ++ } ++ count++; ++ if (count < 30) ++ udelay(200); ++ else if (count < 40) ++ mdelay(1); ++ else ++ mdelay(10); ++ } ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_send_msg(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) ++{ ++ int ret = 0; ++ ++ sdio_claim_host(sdiodev->func_msg); ++ ret = sdio_writesb(sdiodev->func_msg, 7, buf, count); ++ sdio_release_host(sdiodev->func_msg); ++ ++ return ret; ++} ++ ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) ++{ ++ int ret = 0; ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, buf, count); ++ sdio_release_host(sdiodev->func); ++ ++ return ret; ++} ++ ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, ++ u32 size, u8 msg) ++{ ++ int ret; ++ ++ if ((!skbbuf) || (!size)) { ++ return -EINVAL;; ++ } ++ ++ if(!msg) { ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_readsb(sdiodev->func, skbbuf->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func); ++ } else { ++ sdio_claim_host(sdiodev->func_msg); ++ ret = sdio_readsb(sdiodev->func_msg, skbbuf->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func_msg); ++ } ++ ++ ++ if (ret < 0) { ++ return ret; ++ } ++ skbbuf->len = size; ++ ++ return ret; ++} ++ ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++int aicwf_sdio_wakeup(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ int read_retry; ++ int write_retry = 20; ++ int wakeup_reg_val = 0; ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ wakeup_reg_val = 1; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ wakeup_reg_val = 0x11; ++ } ++ ++ if (sdiodev->state == SDIO_SLEEP_ST) { ++ //if (sdiodev->rwnx_hw->vif_started) { ++ down(&sdiodev->pwrctl_wakeup_sema); ++ while (write_retry) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, wakeup_reg_val); ++ if (ret) { ++ txrx_err("sdio wakeup fail\n"); ++ ret = -1; ++ } else { ++ read_retry = 10; ++ while (read_retry) { ++ u8 val; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val); ++ if ((ret == 0) && (val & 0x10)) { ++ break; ++ } ++ read_retry--; ++ udelay(200); ++ } ++ if (read_retry != 0) ++ break; ++ } ++ sdio_dbg("write retry: %d \n", write_retry); ++ write_retry--; ++ udelay(100); ++ } ++ up(&sdiodev->pwrctl_wakeup_sema); ++ // } ++ } ++ ++ sdiodev->state = SDIO_ACTIVE_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ ++ return ret; ++} ++ ++extern u8 dhcped; ++int aicwf_sdio_sleep_allow(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = sdiodev->bus_if; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, 0x10); ++ if (ret) { ++ sdio_err("Write sleep fail!\n"); ++ } ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ return ret; ++ } ++ ++ if (sdiodev->state == SDIO_ACTIVE_ST) { ++ { ++ sdio_dbg("s\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, 0x10); ++ if (ret) ++ sdio_err("Write sleep fail!\n"); ++ } ++ sdiodev->state = SDIO_SLEEP_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ } else { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target) ++{ ++ int ret = 0; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ return -1; ++ } ++ ++ if (sdiodev->state == target) { ++ if (target == SDIO_ACTIVE_ST) { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ return ret; ++ } ++ ++ switch (target) { ++ case SDIO_ACTIVE_ST: ++ aicwf_sdio_wakeup(sdiodev); ++ break; ++ case SDIO_SLEEP_ST: ++ aicwf_sdio_sleep_allow(sdiodev); ++ break; ++ } ++ ++ return ret; ++} ++#endif ++ ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++{ ++ int ret = 0; ++ u8 *frame; ++ u32 len = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("tx bus is down!\n"); ++ return -EINVAL; ++ } ++ ++ frame = (u8 *) (pkt->data); ++ len = pkt->len; ++ len = (len + SDIOWIFI_FUNC_BLOCKSIZE - 1) / SDIOWIFI_FUNC_BLOCKSIZE * SDIOWIFI_FUNC_BLOCKSIZE; ++ ret = aicwf_sdio_send_pkt(sdiodev, pkt->data, len); ++ if (ret) ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", ret); ++ ++ return ret; ++} ++ ++static int aicwf_sdio_intr_get_len_bytemode(struct aic_sdio_dev *sdiodev, u8 *byte_len) ++{ ++ int ret = 0; ++ ++ if (!byte_len) ++ return -EBADE; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ *byte_len = 0; ++ } else { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.bytemode_len_reg, byte_len); ++ sdiodev->rx_priv->data_len = (*byte_len)*4; ++ } ++ ++ return ret; ++} ++ ++static void aicwf_sdio_bus_stop(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = aicbsp_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret; ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ sdio_dbg("%s\n", __func__); ++ if (sdiodev->pwrctl_tsk) { ++ complete_all(&sdiodev->pwrctrl_trgg); ++ kthread_stop(sdiodev->pwrctl_tsk); ++ sdiodev->pwrctl_tsk = NULL; ++ } ++#endif ++ bus_if->state = BUS_DOWN_ST; ++ ret = down_interruptible(&sdiodev->tx_priv->txctl_sema); ++ if (ret) ++ sdio_err("down txctl_sema fail\n"); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++#endif ++ if (!ret) ++ up(&sdiodev->tx_priv->txctl_sema); ++ aicwf_frame_queue_flush(&sdiodev->tx_priv->txq); ++} ++ ++struct sk_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev, u8 msg) ++{ ++ int ret = 0; ++ u32 size = 0; ++ struct sk_buff *skb = NULL; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("bus down\n"); ++ return NULL; ++ } ++ ++ size = sdiodev->rx_priv->data_len; ++ skb = __dev_alloc_skb(size, GFP_KERNEL); ++ if (!skb) { ++ return NULL; ++ } ++ ++ ret = aicwf_sdio_recv_pkt(sdiodev, skb, size, msg); ++ if (ret) { ++ dev_kfree_skb(skb); ++ skb = NULL; ++ } ++ ++ return skb; ++} ++ ++static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++ u16 len; ++ u8 *payload = sdiodev->tx_priv->cmd_buf; ++ u16 payload_len = sdiodev->tx_priv->cmd_len; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ int adjust_len = 0; ++ int buffer_cnt = 0; ++ u8 retry = 0; ++ ++ len = payload_len; ++ if ((len % TX_ALIGNMENT) != 0) { ++ adjust_len = roundup(len, TX_ALIGNMENT); ++ memcpy(payload+payload_len, adjust_str, (adjust_len - len)); ++ payload_len += (adjust_len - len); ++ } ++ len = payload_len; ++ ++ //link tail is necessary ++ if ((len % SDIOWIFI_FUNC_BLOCKSIZE) != 0) { ++ memset(payload+payload_len, 0, TAIL_LEN); ++ payload_len += TAIL_LEN; ++ len = (payload_len/SDIOWIFI_FUNC_BLOCKSIZE + 1) * SDIOWIFI_FUNC_BLOCKSIZE; ++ } else ++ len = payload_len; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); ++ while ((buffer_cnt <= 0 || (buffer_cnt > 0 && len > (buffer_cnt * BUFFER_SIZE))) && retry < 10) { ++ retry++; ++ buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); ++ printk("buffer_cnt = %d\n", buffer_cnt); ++ } ++ } ++ down(&sdiodev->tx_priv->cmd_txsema); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if (buffer_cnt > 0 && len < (buffer_cnt * BUFFER_SIZE)) { ++ err = aicwf_sdio_send_pkt(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ err = aicwf_sdio_send_msg(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ ++ sdiodev->tx_priv->cmd_txstate = false; ++ if (!err) ++ sdiodev->tx_priv->cmd_tx_succ = true; ++ else ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ return err; ++} ++ ++static void aicwf_sdio_tx_process(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("Bus is down\n"); ++ return; ++ } ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++#endif ++ ++ //config ++ sdio_info("send cmd\n"); ++ if (sdiodev->tx_priv->cmd_txstate) { ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txctl down bus->txctl_sema fail\n"); ++ return; ++ } ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ txrx_err("txctl up bus->txctl_sema fail\n"); ++ return; ++ } ++ ++ err = aicwf_sdio_tx_msg(sdiodev); ++ up(&sdiodev->tx_priv->txctl_sema); ++ if (waitqueue_active(&sdiodev->tx_priv->cmd_txdone_wait)) ++ wake_up(&sdiodev->tx_priv->cmd_txdone_wait); ++ } ++ ++ //data ++ sdio_info("send data\n"); ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txdata down bus->txctl_sema\n"); ++ return; ++ } ++ ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("sdio state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ return; ++ } ++ ++ if(!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) ++ sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ while (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) { ++ aicwf_sdio_send(sdiodev->tx_priv); ++ if (sdiodev->tx_priv->cmd_txstate) ++ break; ++ } ++ ++ up(&sdiodev->tx_priv->txctl_sema); ++} ++ ++static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) ++{ ++ uint prio; ++ int ret = -EBADE; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ prio = (pkt->priority & 0x7); ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ if (!aicwf_frame_enq(sdiodev->dev, &sdiodev->tx_priv->txq, pkt, prio)) { ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return -ENOSR; ++ } else { ++ ret = 0; ++ } ++ ++ if (bus_if->state != BUS_UP_ST) { ++ sdio_err("bus_if stopped\n"); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return -1; ++ } ++ ++ atomic_inc(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ complete(&bus_if->bustx_trgg); ++ ++ return ret; ++} ++ ++static int aicwf_sdio_bus_txmsg(struct device *dev, u8 *msg, uint msglen) ++{ ++ int ret = -1; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ down(&sdiodev->tx_priv->cmd_txsema); ++ sdiodev->tx_priv->cmd_txstate = true; ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ sdiodev->tx_priv->cmd_buf = msg; ++ sdiodev->tx_priv->cmd_len = msglen; ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ if (bus_if->state != BUS_UP_ST) { ++ sdio_err("bus has stop\n"); ++ return -1; ++ } ++ ++ complete(&bus_if->bustx_trgg); ++ ++ if (sdiodev->tx_priv->cmd_txstate) { ++ int timeout = msecs_to_jiffies(CMD_TX_TIMEOUT); ++ ret = wait_event_timeout(sdiodev->tx_priv->cmd_txdone_wait, \ ++ !(sdiodev->tx_priv->cmd_txstate), timeout); ++ } ++ ++ if (!sdiodev->tx_priv->cmd_txstate && sdiodev->tx_priv->cmd_tx_succ) { ++ ret = 0; ++ } else { ++ sdio_err("send faild:%d, %d,%x\n", sdiodev->tx_priv->cmd_txstate, sdiodev->tx_priv->cmd_tx_succ, ret); ++ ret = -EIO; ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv) ++{ ++ struct sk_buff *pkt; ++ struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; ++ u16 aggr_len = 0; ++ int retry_times = 0; ++ int max_retry_times = 5; ++ ++ aggr_len = (tx_priv->tail - tx_priv->head); ++ if (((atomic_read(&tx_priv->aggr_count) == 0) && (aggr_len != 0)) ++ || ((atomic_read(&tx_priv->aggr_count) != 0) && (aggr_len == 0))) { ++ if (aggr_len > 0) ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++ goto done; ++ } ++ ++ if (tx_priv->fw_avail_bufcnt <= 0) { //flow control failed ++ tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ while (tx_priv->fw_avail_bufcnt <= 0 && retry_times < max_retry_times) { ++ retry_times++; ++ tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ } ++ if (tx_priv->fw_avail_bufcnt <= 0) { ++ sdio_err("fc retry %d fail\n", tx_priv->fw_avail_bufcnt); ++ goto done; ++ } ++ } ++ ++ if (atomic_read(&tx_priv->aggr_count) == tx_priv->fw_avail_bufcnt) { ++ if (atomic_read(&tx_priv->aggr_count) > 0) { ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); //send and check the next pkt; ++ } ++ } else { ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ pkt = aicwf_frame_dequeue(&sdiodev->tx_priv->txq); ++ if (pkt == NULL) { ++ sdio_err("txq no pkt\n"); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ goto done; ++ } ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ ++ if (tx_priv == NULL || tx_priv->tail == NULL || pkt == NULL) ++ txrx_err("null error\n"); ++ if (aicwf_sdio_aggr(tx_priv, pkt)) { ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++ sdio_err("add aggr pkts failed!\n"); ++ goto done; ++ } ++ ++ //when aggr finish or there is cmd to send, just send this aggr pkt to fw ++ if ((int)atomic_read(&sdiodev->tx_priv->tx_pktcnt) == 0 || sdiodev->tx_priv->cmd_txstate) { //no more pkt send it! ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); ++ } else ++ goto done; ++ } ++ ++done: ++ return 0; ++} ++ ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt) ++{ ++ //struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; ++ u8 *start_ptr = tx_priv->tail; ++ u8 sdio_header[4]; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ u16 curr_len = 0; ++ int allign_len = 0; ++ ++ //sdio_header[0] =((pkt->len - sizeof(struct rwnx_txhdr) + sizeof(struct txdesc_api)) & 0xff); ++ //sdio_header[1] =(((pkt->len - sizeof(struct rwnx_txhdr) + sizeof(struct txdesc_api)) >> 8)&0x0f); ++ sdio_header[2] = 0x01; //data ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ sdio_header[3] = 0; //reserved ++ else if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ sdio_header[3] = crc8_ponl_107(&sdio_header[0], 3); // crc8 ++ ++ memcpy(tx_priv->tail, (u8 *)&sdio_header, sizeof(sdio_header)); ++ tx_priv->tail += sizeof(sdio_header); ++ //payload ++ //memcpy(tx_priv->tail, (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ //tx_priv->tail += sizeof(struct txdesc_api); //hostdesc ++ //memcpy(tx_priv->tail, (u8 *)((u8 *)txhdr + txhdr->sw_hdr->headroom), pkt->len-txhdr->sw_hdr->headroom); ++ //tx_priv->tail += (pkt->len - txhdr->sw_hdr->headroom); ++ ++ //word alignment ++ curr_len = tx_priv->tail - tx_priv->head; ++ if (curr_len & (TX_ALIGNMENT - 1)) { ++ allign_len = roundup(curr_len, TX_ALIGNMENT)-curr_len; ++ memcpy(tx_priv->tail, adjust_str, allign_len); ++ tx_priv->tail += allign_len; ++ } ++ ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ start_ptr[0] = ((tx_priv->tail - start_ptr - 4) & 0xff); ++ start_ptr[1] = (((tx_priv->tail - start_ptr - 4)>>8) & 0x0f); ++ } ++ ++ tx_priv->aggr_buf->dev = pkt->dev; ++ ++ #if 0 ++ if (!txhdr->sw_hdr->need_cfm) { ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, txhdr->sw_hdr->headroom); ++ consume_skb(pkt); ++ } ++ #endif ++ ++ consume_skb(pkt); ++ atomic_inc(&tx_priv->aggr_count); ++ return 0; ++} ++ ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv) ++{ ++ struct sk_buff *tx_buf = tx_priv->aggr_buf; ++ int ret = 0; ++ int curr_len = 0; ++ ++ //link tail is necessary ++ curr_len = tx_priv->tail - tx_priv->head; ++ if ((curr_len % TXPKT_BLOCKSIZE) != 0) { ++ memset(tx_priv->tail, 0, TAIL_LEN); ++ tx_priv->tail += TAIL_LEN; ++ } ++ ++ tx_buf->len = tx_priv->tail - tx_priv->head; ++ ret = aicwf_sdio_txpkt(tx_priv->sdiodev, tx_buf); ++ if (ret < 0) { ++ sdio_err("fail to send aggr pkt!\n"); ++ } ++ ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++} ++ ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv) ++{ ++ struct sk_buff *aggr_buf = tx_priv->aggr_buf; ++ ++ tx_priv->tail = tx_priv->head; ++ aggr_buf->len = 0; ++ atomic_set(&tx_priv->aggr_count, 0); ++} ++ ++static int aicwf_sdio_bus_start(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ sdio_claim_host(sdiodev->func); ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ sdio_release_host(sdiodev->func); ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func); ++ ++ //since we have func2 we don't register irq handler ++ sdio_claim_irq(sdiodev->func, NULL); ++ sdio_claim_irq(sdiodev->func_msg, NULL); ++ ++ sdiodev->func->irq_handler = (sdio_irq_handler_t *)aicwf_sdio_hal_irqhandler; ++ sdiodev->func_msg->irq_handler = (sdio_irq_handler_t *)aicwf_sdio_hal_irqhandler_func2; ++ sdio_release_host(sdiodev->func); ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ ++ if (ret != 0) ++ sdio_err("func2 intr register failed:%d\n", ret); ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdio_claim_host(sdiodev->func); ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++ ++ sdio_f0_writeb(sdiodev->func, 0x07, 0x04, &ret); ++ if (ret) { ++ sdio_err("set func0 int en fail %d\n", ret); ++ } ++ sdio_release_host(sdiodev->func); ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ } ++ ++ bus_if->state = BUS_UP_ST; ++ return ret; ++} ++ ++int aicwf_sdio_bustx_thread(void *data) ++{ ++ struct aicwf_bus *bus = (struct aicwf_bus *) data; ++ struct aic_sdio_dev *sdiodev = bus->bus_priv.sdio; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ sdio_err("sdio bustx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) > 0) || (sdiodev->tx_priv->cmd_txstate == true)) ++ aicwf_sdio_tx_process(sdiodev); ++ } ++ } ++ ++ return 0; ++} ++ ++int aicwf_sdio_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ sdio_err("sdio busrx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ aicwf_process_rxframes(rx_priv); ++ } ++ } ++ ++ return 0; ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static void aicwf_sdio_bus_pwrctl(struct timer_list *t) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ struct aic_sdio_dev *sdiodev = timer_container_of(sdiodev, t, timer); ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, timer); ++#endif ++#else ++static void aicwf_sdio_bus_pwrctl(ulong data) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#endif ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus down\n"); ++ return; ++ } ++ ++ if (sdiodev->pwrctl_tsk) { ++ complete(&sdiodev->pwrctrl_trgg); ++ } ++} ++#endif ++ ++static void aicwf_sdio_enq_rxpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++{ ++ struct aicwf_rx_priv *rx_priv = sdiodev->rx_priv; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (!aicwf_rxframe_enqueue(sdiodev->dev, &rx_priv->rxq, pkt)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ aicwf_dev_skb_free(pkt); ++ return; ++ } ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ ++ atomic_inc(&rx_priv->rx_cnt); ++} ++ ++#define SDIO_OTHER_INTERRUPT (0x1ul << 7) ++ ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(&func->dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ u8 intstatus = 0; ++ u8 byte_len = 0; ++ struct sk_buff *pkt = NULL; ++ int ret; ++ ++ //AICWFDBG(LOGDEBUG,"%s bsp enter \r\n", __func__); ++ ++ if(aicbsp_sdiodev->sdio_hal_irqhandler){ ++ aicbsp_sdiodev->sdio_hal_irqhandler(func); ++ return; ++ } ++ ++ if (!bus_if || bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus err\n"); ++ return; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ ++ while(intstatus){ ++ sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; ++ if (intstatus > 0) { ++ if(intstatus < 64) { ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } else { ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ } ++ }else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ do { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.misc_int_status_reg, &intstatus); ++ if (!ret) { ++ break; ++ } ++ sdio_err("ret=%d, intstatus=%x\r\n",ret, intstatus); ++ } while (1); ++ if (intstatus & SDIO_OTHER_INTERRUPT) { ++ u8 int_pending; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ int_pending &= ~0x01; // dev to host soft irq ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ } ++ ++ if (intstatus > 0) { ++ uint8_t intmaskf2 = intstatus | (0x1UL << 3); ++ if (intmaskf2 > 120U) { // func2 ++ if (intmaskf2 == 127U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 1);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev, 1); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7U) * SDIOWIFI_FUNC_BLOCKSIZE; ++ pkt = aicwf_sdio_readframes(sdiodev, 1); ++ } ++ } else { // func1 ++ if (intstatus == 120U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 0);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7FU) * SDIOWIFI_FUNC_BLOCKSIZE; ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ } ++ ++ complete(&bus_if->busrx_trgg); ++} ++ ++void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(&func->dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ u8 intstatus = 0; ++ u8 byte_len = 0; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_buff *pkt = NULL; ++ #else ++ struct sk_buff *pkt = NULL; ++ #endif ++ int ret; ++ ++ if (!bus_if || bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus err\n"); ++ return; ++ } ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ if (list_empty(&aic_rx_buff_list.rxbuff_list)) { ++ printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); ++ return; ++ } ++ #endif ++ ++ ret = aicwf_sdio_readb_func2(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ ++ while(intstatus) { ++ sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; ++ if (intstatus > 0) { ++ if(intstatus < 64) { ++ pkt = aicwf_sdio_readframes(sdiodev,1); ++ } else { ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ pkt = aicwf_sdio_readframes(sdiodev,1); ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt){ ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ } ++ ret = aicwf_sdio_readb_func2(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ } ++ ++ complete(&bus_if->busrx_trgg); ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration) ++{ ++ uint timeout; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST && duration) ++ return; ++ ++ spin_lock_bh(&sdiodev->pwrctl_lock); ++ if (!duration) { ++ if (timer_pending(&sdiodev->timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&sdiodev->timer); ++#else ++ del_timer_sync(&sdiodev->timer); ++#endif ++ } else { ++ sdiodev->active_duration = duration; ++ timeout = msecs_to_jiffies(sdiodev->active_duration); ++ mod_timer(&sdiodev->timer, jiffies + timeout); ++ } ++ spin_unlock_bh(&sdiodev->pwrctl_lock); ++} ++#endif ++ ++static struct aicwf_bus_ops aicwf_sdio_bus_ops = { ++ .stop = aicwf_sdio_bus_stop, ++ .start = aicwf_sdio_bus_start, ++ .txdata = aicwf_sdio_bus_txdata, ++ .txmsg = aicwf_sdio_bus_txmsg, ++}; ++ ++void aicwf_sdio_release_func2(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ sdio_dbg("%s\n", __func__); ++ sdio_claim_host(sdiodev->func_msg); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); ++ } ++ sdio_release_irq(sdiodev->func_msg); ++ sdio_release_host(sdiodev->func_msg); ++ ++} ++ ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) ++{ ++ struct aicwf_bus *bus_if = NULL; ++ struct aicwf_bus *bus_if_t = NULL; ++ int ret = 0; ++ ++ sdio_dbg("%s\n", __func__); ++ if (sdiodev->func == NULL) { ++ printk("%s, NULL sdio func\n", __func__); ++ return; ++ } ++ ++ bus_if = aicbsp_get_drvdata(sdiodev->dev); ++ if (bus_if) ++ bus_if->state = BUS_DOWN_ST; ++ ++ bus_if_t = dev_get_drvdata(sdiodev->dev); ++ ++ if ((bus_if_t != NULL) && (sdiodev->bus_if == bus_if_t)) { ++ sdio_dbg("%s bsp release\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!, ret=%d\n", sdiodev->sdio_reg.intr_config_reg, ret); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ aicwf_sdio_release_func2(sdiodev); ++ } ++ ++ if (sdiodev->dev) ++ aicwf_bus_deinit(sdiodev->dev); ++ ++ if (sdiodev->tx_priv) ++ aicwf_tx_deinit(sdiodev->tx_priv); ++ ++ if (sdiodev->rx_priv) ++ aicwf_rx_deinit(sdiodev->rx_priv); ++ ++ rwnx_cmd_mgr_deinit(&sdiodev->cmd_mgr); ++} ++ ++ ++ ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev) ++{ ++ sdio_dbg("%s\n", __func__); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_CONFIG_REG; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_SLEEP_REG; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_WAKEUP_REG; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_REG; ++ sdiodev->sdio_reg.register_block = SDIOWIFI_REGISTER_BLOCK; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG; ++ sdiodev->sdio_reg.block_cnt_reg = SDIOWIFI_BLOCK_CNT_REG; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG_V3; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_ENABLE_REG_V3; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_INTR_PENDING_REG_V3; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_INTR_TO_DEVICE_REG_V3; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_Q1_REG_V3; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG_V3; ++ sdiodev->sdio_reg.misc_int_status_reg = SDIOWIFI_MISC_INT_STATUS_REG_V3; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR_V3; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR_V3; ++ } ++} ++ ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 block_bit0 = 0x1; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ struct aicbsp_feature_t feature; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++#if 0//SDIO PHASE SETTING ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ sdio_f0_writeb(sdiodev->func, feature.sdio_phase, 0x13, &ret); ++ if (ret < 0) { ++ sdio_err("write func0 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#endif ++ ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ sdio_err("set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_err("enable func fail %d.\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ udelay(100); ++#if 1//SDIO CLOCK SETTING ++ if (feature.sdio_clock > 0) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++ sdio_release_host(sdiodev->func); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ ++ sdio_claim_host(sdiodev->func_msg); ++ ++ //set sdio blocksize ++ ret = sdio_set_block_size(sdiodev->func_msg, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set func2 blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func_msg); ++ return ret; ++ } ++ ++ //set sdio enable func ++ ret = sdio_enable_func(sdiodev->func_msg); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "enable func2 fail %d.\n", ret); ++ } ++ ++ sdio_release_host(sdiodev->func_msg); ++ ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ } ++ ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ //u8 val; ++ struct aicbsp_feature_t feature; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ sdio_err("set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_err("enable func fail %d.\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ++ sdio_f0_writeb(sdiodev->func, 0x7F, 0xF2, &ret); ++ if (ret) { ++ sdio_err("set fn0 0xF2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#if 0 ++ if (host->ios.timing == MMC_TIMING_UHS_DDR50) { ++ val = 0x21;//0x1D;//0x5; ++ } else { ++ val = 0x01;//0x19;//0x1; ++ } ++ val |= SDIOCLK_FREE_RUNNING_BIT; ++ sdio_f0_writeb(sdiodev->func, val, 0xF0, &ret); ++ if (ret) { ++ sdio_err("set iopad ctrl fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x0, 0xF8, &ret); ++ if (ret) { ++ sdio_err("set iopad delay2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x40, 0xF1, &ret); ++ if (ret) { ++ sdio_err("set iopad delay1 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ msleep(1); ++#if 1//SDIO CLOCK SETTING ++ if ((feature.sdio_clock > 0) && (host->ios.timing != MMC_TIMING_UHS_DDR50)) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++#endif ++ sdio_release_host(sdiodev->func); ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev) ++{ ++ struct aicwf_bus *bus_if = NULL; ++ ++ if (sdiodev->func == NULL) { ++ sdio_err("%s, NULL sdio func\n", __func__); ++ return; ++ } ++ ++ bus_if = dev_get_drvdata(sdiodev->dev); ++ if (bus_if == NULL) { ++ sdio_err("%s, bus_if is null\n", __func__); ++ return; ++ } ++ ++ if (sdiodev->bus_if == bus_if) { ++ sdio_dbg("%s bsp disable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ sdio_disable_func(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func_msg); ++ sdio_disable_func(sdiodev->func_msg); ++ sdio_release_host(sdiodev->func_msg); ++ } ++ ++} ++ ++ ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret; ++ struct aicwf_bus *bus_if; ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ spin_lock_init(&sdiodev->pwrctl_lock); ++ sema_init(&sdiodev->pwrctl_wakeup_sema, 1); ++#endif ++ ++ bus_if = sdiodev->bus_if; ++ bus_if->dev = sdiodev->dev; ++ bus_if->ops = &aicwf_sdio_bus_ops; ++ bus_if->state = BUS_DOWN_ST; ++#if defined(CONFIG_SDIO_PWRCTRL) ++ sdiodev->state = SDIO_SLEEP_ST; ++ sdiodev->active_duration = SDIOWIFI_PWR_CTRL_INTERVAL; ++#else ++ sdiodev->state = SDIO_ACTIVE_ST; ++#endif ++ ++ rx_priv = aicwf_rx_init(sdiodev); ++ if (!rx_priv) { ++ sdio_err("rx init fail\n"); ++ goto fail; ++ } ++ sdiodev->rx_priv = rx_priv; ++ ++ tx_priv = aicwf_tx_init(sdiodev); ++ if (!tx_priv) { ++ sdio_err("tx init fail\n"); ++ goto fail; ++ } ++ sdiodev->tx_priv = tx_priv; ++ aicwf_frame_queue_init(&tx_priv->txq, 8, TXQLEN); ++ spin_lock_init(&tx_priv->txqlock); ++ sema_init(&tx_priv->txctl_sema, 1); ++ sema_init(&tx_priv->cmd_txsema, 1); ++ init_waitqueue_head(&tx_priv->cmd_txdone_wait); ++ atomic_set(&tx_priv->tx_pktcnt, 0); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ timer_setup(&sdiodev->timer, aicwf_sdio_bus_pwrctl, 0); ++#else ++ init_timer(&sdiodev->timer); ++ sdiodev->timer.data = (ulong) sdiodev; ++ sdiodev->timer.function = aicwf_sdio_bus_pwrctl; ++#endif ++ init_completion(&sdiodev->pwrctrl_trgg); ++#endif ++ ret = aicwf_bus_init(0, sdiodev->dev); ++ if (ret < 0) { ++ sdio_err("bus init fail\n"); ++ goto fail; ++ } ++ ++ ret = aicwf_bus_start(bus_if); ++ if (ret != 0) { ++ sdio_err("bus start fail\n"); ++ goto fail; ++ } ++ ++ return sdiodev; ++ ++fail: ++ aicwf_sdio_release(sdiodev); ++ return NULL; ++} ++ ++void get_fw_path(char* fw_path){ ++ if (strlen(aic_fw_path) > 0) { ++ memcpy(fw_path, aic_fw_path, strlen(aic_fw_path)); ++ }else{ ++ memcpy(fw_path, aic_default_fw_path, strlen(aic_default_fw_path)); ++ } ++} ++ ++int get_testmode(void){ ++ return testmode; ++} ++ ++struct sdio_func *get_sdio_func(void){ ++ return aicbsp_sdiodev->func; ++} ++ ++void set_irq_handler(void *fn){ ++ aicbsp_sdiodev->sdio_hal_irqhandler = (sdio_irq_handler_t *)fn; ++} ++ ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size) ++{ ++ uint8_t i; ++ uint8_t crc = 0; ++ if (cal_size==0) { ++ return crc; ++ } ++ while (cal_size--) { ++ for (i = 0x80; i > 0; i /= 2) { ++ if (crc & 0x80) { ++ crc *= 2; ++ crc ^= 0x07; //polynomial X8 + X2 + X + 1,(0x107) ++ } else { ++ crc *= 2; ++ } ++ if ((*p_buffer) & i) { ++ crc ^= 0x07; ++ } ++ } ++ p_buffer++; ++ } ++ return crc; ++} ++ ++EXPORT_SYMBOL(get_fw_path); ++EXPORT_SYMBOL(get_testmode); ++EXPORT_SYMBOL(get_sdio_func); ++EXPORT_SYMBOL(set_irq_handler); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h +new file mode 100644 +index 000000000000..65d73510ad3a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h +@@ -0,0 +1,149 @@ ++/** ++ * aicwf_sdio.h ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_SDMMC_H_ ++#define _AICWF_SDMMC_H_ ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include ++#include ++#include ++#include ++#include "aic_bsp_driver.h" ++ ++#define AICBSP_SDIO_NAME "aicbsp_sdio" ++#define SDIOWIFI_FUNC_BLOCKSIZE 512 ++ ++#define SDIO_VENDOR_ID_AIC 0x8800 ++#define SDIO_DEVICE_ID_AIC 0x0001 ++#define SDIOWIFI_BYTEMODE_LEN_REG 0x02 ++#define SDIOWIFI_INTR_CONFIG_REG 0x04 ++#define SDIOWIFI_SLEEP_REG 0x05 ++#define SDIOWIFI_WAKEUP_REG 0x09 ++#define SDIOWIFI_FLOW_CTRL_REG 0x0A ++#define SDIOWIFI_REGISTER_BLOCK 0x0B ++#define SDIOWIFI_BYTEMODE_ENABLE_REG 0x11 ++#define SDIOWIFI_BLOCK_CNT_REG 0x12 ++#define SDIOWIFI_FLOWCTRL_MASK_REG 0x7F ++#define SDIOWIFI_WR_FIFO_ADDR 0x07 ++#define SDIOWIFI_RD_FIFO_ADDR 0x08 ++ ++#define SDIOWIFI_INTR_ENABLE_REG_V3 0x00 ++#define SDIOWIFI_INTR_PENDING_REG_V3 0x01 ++#define SDIOWIFI_INTR_TO_DEVICE_REG_V3 0x02 ++#define SDIOWIFI_FLOW_CTRL_Q1_REG_V3 0x03 ++#define SDIOWIFI_MISC_INT_STATUS_REG_V3 0x04 ++#define SDIOWIFI_BYTEMODE_LEN_REG_V3 0x05 ++#define SDIOWIFI_BYTEMODE_LEN_MSB_REG_V3 0x06 ++#define SDIOWIFI_BYTEMODE_ENABLE_REG_V3 0x07 ++#define SDIOWIFI_MISC_CTRL_REG_V3 0x08 ++#define SDIOWIFI_FLOW_CTRL_Q2_REG_V3 0x09 ++#define SDIOWIFI_CLK_TEST_RESULT_REG_V3 0x0A ++#define SDIOWIFI_RD_FIFO_ADDR_V3 0x0F ++#define SDIOWIFI_WR_FIFO_ADDR_V3 0x10 ++ ++#define SDIOCLK_FREE_RUNNING_BIT (1 << 6) ++ ++#define SDIOWIFI_PWR_CTRL_INTERVAL 30 ++#define FLOW_CTRL_RETRY_COUNT 50 ++#define BUFFER_SIZE 1536 ++#define TAIL_LEN 4 ++#define TXQLEN (2048*4) ++ ++#define SDIO_SLEEP_ST 0 ++#define SDIO_ACTIVE_ST 1 ++ ++typedef enum { ++ SDIO_TYPE_DATA = 0X00, ++ SDIO_TYPE_CFG = 0X10, ++ SDIO_TYPE_CFG_CMD_RSP = 0X11, ++ SDIO_TYPE_CFG_DATA_CFM = 0X12 ++} sdio_type; ++ ++enum AICWF_IC{ ++ PRODUCT_ID_AIC8801 = 0, ++ PRODUCT_ID_AIC8800DC, ++ PRODUCT_ID_AIC8800DW, ++ PRODUCT_ID_AIC8800D80, ++ PRODUCT_ID_AIC8800D80X2 ++}; ++ ++struct aic_sdio_reg { ++ u8 bytemode_len_reg; ++ u8 intr_config_reg; ++ u8 sleep_reg; ++ u8 wakeup_reg; ++ u8 flow_ctrl_reg; ++ u8 flowctrl_mask_reg; ++ u8 register_block; ++ u8 bytemode_enable_reg; ++ u8 block_cnt_reg; ++ u8 misc_int_status_reg; ++ u8 rd_fifo_addr; ++ u8 wr_fifo_addr; ++}; ++ ++struct aic_sdio_dev { ++ struct rwnx_cmd_mgr cmd_mgr; ++ struct sdio_func *func; ++ struct sdio_func *func_msg; ++ struct device *dev; ++ struct aicwf_bus *bus_if; ++ ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ u32 state; ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ //for sdio pwr ctrl ++ struct timer_list timer; ++ uint active_duration; ++ struct completion pwrctrl_trgg; ++ struct task_struct *pwrctl_tsk; ++ spinlock_t pwrctl_lock; ++ struct semaphore pwrctl_wakeup_sema; ++#endif ++ u16 chipid; ++ u32 fw_version_uint; ++ struct aic_sdio_reg sdio_reg; ++ void (*sdio_hal_irqhandler) (struct sdio_func *func); ++}; ++ ++void *aicbsp_get_drvdata(void *args); ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func); ++void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func); ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration); ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target); ++#endif ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size, u8 msg); ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count); ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev); ++void aicbsp_sdio_exit(void); ++int aicbsp_sdio_init(void); ++void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt); ++int aicwf_sdio_bustx_thread(void *data); ++int aicwf_sdio_busrx_thread(void *data); ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt); ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv); ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv); ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv); ++extern void aicwf_hostif_ready(void); ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv); ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size); ++#endif /* AICWF_SDIO_SUPPORT */ ++ ++#endif /*_AICWF_SDMMC_H_*/ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c +new file mode 100644 +index 000000000000..84e6ca71c7ae +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c +@@ -0,0 +1,464 @@ ++/** ++ * aicwf_bus.c ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aicsdio_txrxif.h" ++#include "aic_bsp_driver.h" ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if; ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return -1; ++ } ++ bus_if = dev_get_drvdata(dev); ++ bus_if->cmd_buf = kzalloc(CMD_BUF_MAX, GFP_KERNEL); ++ if (!bus_if->cmd_buf) { ++ ret = -ENOMEM; ++ txrx_err("proto_attach failed\n"); ++ goto fail; ++ } ++ memset(bus_if->cmd_buf, '\0', CMD_BUF_MAX); ++ ++ init_completion(&bus_if->bustx_trgg); ++ init_completion(&bus_if->busrx_trgg); ++#ifdef AICWF_SDIO_SUPPORT ++ bus_if->bustx_thread = kthread_run(aicwf_sdio_bustx_thread, (void *)bus_if, "aicwf_bustx_thread"); ++ if (IS_ERR(bus_if->bustx_thread)) { ++ bus_if->bustx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ ret = -1; ++ goto fail; ++ } ++ ++ bus_if->busrx_thread = kthread_run(aicwf_sdio_busrx_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busrx_thread"); ++ if (IS_ERR(bus_if->busrx_thread)) { ++ bus_if->busrx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ ret = -1; ++ goto fail; ++ } ++ ++#endif ++ return ret; ++fail: ++ aicwf_bus_deinit(dev); ++ ++ return ret; ++} ++ ++void aicwf_bus_deinit(struct device *dev) ++{ ++ struct aicwf_bus *bus_if; ++ struct aic_sdio_dev *sdiodev; ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return; ++ } ++ sdio_dbg("%s", __func__); ++ bus_if = aicbsp_get_drvdata(dev); ++ aicwf_bus_stop(bus_if); ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ ++ if (bus_if->cmd_buf) { ++ kfree(bus_if->cmd_buf); ++ bus_if->cmd_buf = NULL; ++ } ++ ++ if (bus_if->bustx_thread) { ++ complete_all(&bus_if->bustx_trgg); ++ kthread_stop(bus_if->bustx_thread); ++ bus_if->bustx_thread = NULL; ++ } ++} ++ ++void aicwf_frame_tx(void *dev, struct sk_buff *skb) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ aicwf_bus_txdata(sdiodev->bus_if, skb); ++} ++ ++struct aicwf_tx_priv *aicwf_tx_init(void *arg) ++{ ++ struct aicwf_tx_priv *tx_priv; ++ ++ tx_priv = kzalloc(sizeof(struct aicwf_tx_priv), GFP_KERNEL); ++ if (!tx_priv) ++ return NULL; ++ ++ tx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++ ++ atomic_set(&tx_priv->aggr_count, 0); ++ tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN); ++ if (!tx_priv->aggr_buf) { ++ txrx_err("Alloc bus->txdata_buf failed!\n"); ++ kfree(tx_priv); ++ return NULL; ++ } ++ tx_priv->head = tx_priv->aggr_buf->data; ++ tx_priv->tail = tx_priv->aggr_buf->data; ++ ++ return tx_priv; ++} ++ ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv) ++{ ++ if (tx_priv && tx_priv->aggr_buf) ++ dev_kfree_skb(tx_priv->aggr_buf); ++ ++ kfree(tx_priv); ++ //tx_priv = NULL; ++} ++ ++static bool aicwf_another_ptk(struct sk_buff *skb) ++{ ++ u8 *data; ++ u16 aggr_len = 0; ++ ++ if (skb->data == NULL || skb->len == 0) { ++ return false; ++ } ++ data = skb->data; ++ aggr_len = (*skb->data | (*(skb->data + 1) << 8)); ++ if (aggr_len == 0) { ++ return false; ++ } ++ ++ return true; ++} ++ ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv) ++{ ++ int ret = 0; ++ unsigned long flags = 0; ++ struct sk_buff *skb = NULL; ++ u16 pkt_len = 0; ++ struct sk_buff *skb_inblock = NULL; ++ u16 aggr_len = 0, adjust_len = 0; ++ u8 *data = NULL; ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ skb = aicwf_frame_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (skb == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ while (aicwf_another_ptk(skb)) { ++ data = skb->data; ++ pkt_len = (*skb->data | (*(skb->data + 1) << 8)); ++ ++ if ((skb->data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv ++ if (skb_inblock == NULL) { ++ txrx_err("no more space!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ #if 0 ++ rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ #endif ++ skb_pull(skb, adjust_len); ++ } else { // type : config ++ aggr_len = pkt_len; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len+4, GFP_KERNEL); ++ if (skb_inblock == NULL) { ++ txrx_err("no more space!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ ++ skb_put(skb_inblock, aggr_len+4); ++ memcpy(skb_inblock->data, data, aggr_len+4); ++ if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) ++ rwnx_rx_handle_msg(rx_priv->sdiodev, (struct ipc_e2a_msg *)(skb_inblock->data + 4)); ++ #if 0 ++ if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) ++ aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(skb_inblock->data + 4)); ++ #endif ++ skb_pull(skb, adjust_len+4); ++ } ++ } ++ ++ /* skb_inblock no used currently, just free it! */ ++ dev_kfree_skb(skb_inblock); ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(rx_priv->sdiodev, SDIO_ACTIVE_ST); ++#endif ++ ++ return ret; ++} ++ ++static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize) ++{ ++ int i; ++ struct recv_msdu *req, *reqs; ++ ++ reqs = vmalloc(qsize*sizeof(struct recv_msdu)); ++ if (reqs == NULL) ++ return NULL; ++ ++ req = reqs; ++ for (i = 0; i < qsize; i++) { ++ INIT_LIST_HEAD(&req->rxframe_list); ++ list_add(&req->rxframe_list, q); ++ req->len = 0; ++ req++; ++ } ++ ++ return reqs; ++} ++ ++struct aicwf_rx_priv *aicwf_rx_init(void *arg) ++{ ++ struct aicwf_rx_priv *rx_priv; ++ rx_priv = kzalloc(sizeof(struct aicwf_rx_priv), GFP_KERNEL); ++ if (!rx_priv) ++ return NULL; ++ ++ rx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++ aicwf_frame_queue_init(&rx_priv->rxq, 1, MAX_RXQLEN); ++ spin_lock_init(&rx_priv->rxqlock); ++ atomic_set(&rx_priv->rx_cnt, 0); ++ ++ INIT_LIST_HEAD(&rx_priv->rxframes_freequeue); ++ spin_lock_init(&rx_priv->freeq_lock); ++ rx_priv->recv_frames = aicwf_rxframe_queue_init(&rx_priv->rxframes_freequeue, MAX_REORD_RXFRAME); ++ if (!rx_priv->recv_frames) { ++ txrx_err("no enough buffer for free recv frame queue!\n"); ++ kfree(rx_priv); ++ return NULL; ++ } ++ spin_lock_init(&rx_priv->stas_reord_lock); ++ INIT_LIST_HEAD(&rx_priv->stas_reord_list); ++ ++ return rx_priv; ++} ++ ++ ++static void aicwf_recvframe_queue_deinit(struct list_head *q) ++{ ++ struct recv_msdu *req, *next; ++ ++ list_for_each_entry_safe(req, next, q, rxframe_list) { ++ list_del_init(&req->rxframe_list); ++ } ++} ++ ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv) ++{ ++ if (rx_priv->sdiodev->bus_if->busrx_thread) { ++ complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg); ++ kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread); ++ rx_priv->sdiodev->bus_if->busrx_thread = NULL; ++ } ++ ++ aicwf_frame_queue_flush(&rx_priv->rxq); ++ aicwf_recvframe_queue_deinit(&rx_priv->rxframes_freequeue); ++ if (rx_priv->recv_frames) ++ vfree(rx_priv->recv_frames); ++ ++ kfree(rx_priv); ++ //rx_priv = NULL; ++} ++ ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt) ++{ ++ return aicwf_frame_enq(dev, q, pkt, 0); ++} ++ ++ ++void aicwf_dev_skb_free(struct sk_buff *skb) ++{ ++ if (!skb) ++ return; ++ ++ dev_kfree_skb_any(skb); ++} ++ ++static struct sk_buff *aicwf_frame_queue_penq(struct frame_queue *pq, int prio, struct sk_buff *p) ++{ ++ struct sk_buff_head *q; ++ ++ if (pq->queuelist[prio].qlen >= pq->qmax) ++ return NULL; ++ ++ q = &pq->queuelist[prio]; ++ __skb_queue_tail(q, p); ++ pq->qcnt++; ++ if (pq->hi_prio < prio) ++ pq->hi_prio = (u16)prio; ++ ++ return p; ++} ++ ++void aicwf_frame_queue_flush(struct frame_queue *pq) ++{ ++ int prio; ++ struct sk_buff_head *q; ++ struct sk_buff *p, *next; ++ ++ for (prio = 0; prio < pq->num_prio; prio++) { ++ q = &pq->queuelist[prio]; ++ skb_queue_walk_safe(q, p, next) { ++ skb_unlink(p, q); ++ aicwf_dev_skb_free(p); ++ pq->qcnt--; ++ } ++ } ++} ++ ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len) ++{ ++ int prio; ++ ++ memset(pq, 0, offsetof(struct frame_queue, queuelist) + (sizeof(struct sk_buff_head) * num_prio)); ++ pq->num_prio = (u16)num_prio; ++ pq->qmax = (u16)max_len; ++ ++ for (prio = 0; prio < num_prio; prio++) { ++ skb_queue_head_init(&pq->queuelist[prio]); ++ } ++} ++ ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out) ++{ ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ for (prio = 0; prio < pq->hi_prio; prio++) ++ if (!skb_queue_empty(&pq->queuelist[prio])) ++ break; ++ ++ if (prio_out) ++ *prio_out = prio; ++ ++ return skb_peek_tail(&pq->queuelist[prio]); ++} ++ ++bool aicwf_is_framequeue_empty(struct frame_queue *pq) ++{ ++ int prio, len = 0; ++ ++ for (prio = 0; prio <= pq->hi_prio; prio++) ++ len += pq->queuelist[prio].qlen; ++ ++ if (len > 0) ++ return false; ++ else ++ return true; ++} ++ ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq) ++{ ++ struct sk_buff_head *q; ++ struct sk_buff *p; ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ while ((prio = pq->hi_prio) > 0 && skb_queue_empty(&pq->queuelist[prio])) ++ pq->hi_prio--; ++ ++ q = &pq->queuelist[prio]; ++ p = __skb_dequeue(q); ++ if (p == NULL) ++ return NULL; ++ ++ pq->qcnt--; ++ ++ return p; ++} ++ ++static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio) ++{ ++ struct sk_buff_head *q = &pq->queuelist[prio]; ++ struct sk_buff *p = skb_dequeue_tail(q); ++ ++ if (!p) ++ return NULL; ++ ++ pq->qcnt--; ++ return p; ++} ++ ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio) ++{ ++ struct sk_buff *p = NULL; ++ int prio_modified = -1; ++ ++ if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { ++ aicwf_frame_queue_penq(q, prio, pkt); ++ return true; ++ } ++ if (q->queuelist[prio].qlen >= q->qmax) { ++ prio_modified = prio; ++ } else if (q->qcnt >= q->qmax) { ++ p = aicwf_frame_queue_peek_tail(q, &prio_modified); ++ if (prio_modified > prio) ++ return false; ++ } ++ ++ if (prio_modified >= 0) { ++ if (prio_modified == prio) ++ return false; ++ ++ p = aicwf_skb_dequeue_tail(q, prio_modified); ++ aicwf_dev_skb_free(p); ++ ++ p = aicwf_frame_queue_penq(q, prio_modified, pkt); ++ if (p == NULL) ++ txrx_err("failed\n"); ++ } ++ ++ return p != NULL; ++} ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h +new file mode 100644 +index 000000000000..801e0ea4965c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h +@@ -0,0 +1,214 @@ ++/** ++ * aicwf_txrxif.h ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_TXRXIF_H_ ++#define _AICWF_TXRXIF_H_ ++ ++#include ++#include ++#include "aicsdio.h" ++ ++#define CMD_BUF_MAX 1536 ++#define TXPKT_BLOCKSIZE 512 ++#define MAX_AGGR_TXPKT_LEN (1536*4) ++#define CMD_TX_TIMEOUT 5000 ++#define TX_ALIGNMENT 4 ++ ++#define RX_HWHRD_LEN 60 //58->60 word allined ++#define CCMP_OR_WEP_INFO 8 ++#define MAX_RXQLEN 2000 ++#define RX_ALIGNMENT 4 ++ ++#define DEBUG_ERROR_LEVEL 0 ++#define DEBUG_DEBUG_LEVEL 1 ++#define DEBUG_INFO_LEVEL 2 ++ ++#define DBG_LEVEL DEBUG_DEBUG_LEVEL ++ ++#define txrx_err(fmt, ...) pr_err("aicbsp: txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define sdio_err(fmt, ...) pr_err("aicbsp: sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define usb_err(fmt, ...) pr_err("aicbsp: usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL ++#define sdio_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#define usb_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#else ++#define sdio_dbg(fmt, ...) ++#define usb_dbg(fmt, ...) ++#endif ++#if DBG_LEVEL >= DEBUG_INFO_LEVEL ++#define sdio_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#define usb_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#else ++#define sdio_info(fmt, ...) ++#define usb_info(fmt, ...) ++#endif ++ ++enum aicwf_bus_state { ++ BUS_DOWN_ST, ++ BUS_UP_ST ++}; ++ ++struct aicwf_bus_ops { ++ int (*start) (struct device *dev); ++ void (*stop) (struct device *dev); ++ int (*txdata) (struct device *dev, struct sk_buff *skb); ++ int (*txmsg) (struct device *dev, u8 *msg, uint len); ++}; ++ ++struct frame_queue { ++ u16 num_prio; ++ u16 hi_prio; ++ u16 qmax; /* max number of queued frames */ ++ u16 qcnt; ++ struct sk_buff_head queuelist[8]; ++}; ++ ++struct aicwf_bus { ++ union { ++ struct aic_sdio_dev *sdio; ++ struct aic_usb_dev *usb; ++ } bus_priv; ++ struct device *dev; ++ struct aicwf_bus_ops *ops; ++ enum aicwf_bus_state state; ++ u8 *cmd_buf; ++ struct completion bustx_trgg; ++ struct completion busrx_trgg; ++ struct task_struct *bustx_thread; ++ struct task_struct *busrx_thread; ++}; ++ ++struct aicwf_tx_priv { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++ int fw_avail_bufcnt; ++ //for cmd tx ++ u8 *cmd_buf; ++ uint cmd_len; ++ bool cmd_txstate; ++ bool cmd_tx_succ; ++ struct semaphore cmd_txsema; ++ wait_queue_head_t cmd_txdone_wait; ++ //for data tx ++ atomic_t tx_pktcnt; ++ ++ struct frame_queue txq; ++ spinlock_t txqlock; ++ struct semaphore txctl_sema; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ struct sk_buff *aggr_buf; ++ atomic_t aggr_count; ++ u8 *head; ++ u8 *tail; ++}; ++ ++ ++#define MAX_REORD_RXFRAME 250 ++#define REORDER_UPDATE_TIME 50 ++#define AICWF_REORDER_WINSIZE 64 ++#define SN_LESS(a, b) (((a-b)&0x800) != 0) ++#define SN_EQUAL(a, b) (a == b) ++ ++struct reord_ctrl { ++ struct aicwf_rx_priv *rx_priv; ++ u8 enable; ++ u16 ind_sn; ++ u8 wsize_b; ++ spinlock_t reord_list_lock; ++ struct list_head reord_list; ++ struct timer_list reord_timer; ++ struct work_struct reord_timer_work; ++}; ++ ++struct reord_ctrl_info { ++ u8 mac_addr[6]; ++ struct reord_ctrl preorder_ctrl[8]; ++ struct list_head list; ++}; ++ ++struct recv_msdu { ++ struct sk_buff *pkt; ++ u8 tid; ++ u16 seq_num; ++ uint len; ++ u8 *rx_data; ++ //for pending rx reorder list ++ struct list_head reord_pending_list; ++ //for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue ++ struct list_head rxframe_list; ++ struct reord_ctrl *preorder_ctrl; ++}; ++ ++struct aicwf_rx_priv { ++ struct aic_sdio_dev *sdiodev; ++ void *rwnx_vif; ++ atomic_t rx_cnt; ++ u32 data_len; ++ spinlock_t rxqlock; ++ struct frame_queue rxq; ++ ++ spinlock_t freeq_lock; ++ struct list_head rxframes_freequeue; ++ struct list_head stas_reord_list; ++ spinlock_t stas_reord_lock; ++ struct recv_msdu *recv_frames; ++}; ++ ++static inline int aicwf_bus_start(struct aicwf_bus *bus) ++{ ++ return bus->ops->start(bus->dev); ++} ++ ++static inline void aicwf_bus_stop(struct aicwf_bus *bus) ++{ ++ bus->ops->stop(bus->dev); ++} ++ ++static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb) ++{ ++ return bus->ops->txdata(bus->dev, skb); ++} ++ ++static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len) ++{ ++ return bus->ops->txmsg(bus->dev, msg, len); ++} ++ ++static inline void aicwf_sched_timeout(u32 millisec) ++{ ++ ulong timeout = 0, expires = 0; ++ expires = jiffies + msecs_to_jiffies(millisec); ++ timeout = millisec; ++ ++ while (timeout) { ++ timeout = schedule_timeout(timeout); ++ if (time_after(jiffies, expires)) ++ break; ++ } ++} ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev); ++void aicwf_bus_deinit(struct device *dev); ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv); ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv); ++struct aicwf_tx_priv *aicwf_tx_init(void *arg); ++struct aicwf_rx_priv *aicwf_rx_init(void *arg); ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len); ++void aicwf_frame_queue_flush(struct frame_queue *pq); ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio); ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt); ++bool aicwf_is_framequeue_empty(struct frame_queue *pq); ++void aicwf_frame_tx(void *dev, struct sk_buff *skb); ++void aicwf_dev_skb_free(struct sk_buff *skb); ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq); ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out); ++ ++#endif /* _AICWF_TXRXIF_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c +new file mode 100644 +index 000000000000..77130f76bafa +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c +@@ -0,0 +1,16138 @@ ++#include ++ ++char fmacfw[259592] = { ++0x00, 0x38, 0x18, 0x00, 0x89, 0x01, 0x12, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0xA1, 0xCA, 0x12, 0x00, 0xA9, 0xCA, 0x12, 0x00, ++0xB1, 0xCA, 0x12, 0x00, 0xB9, 0xCA, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x12, 0x00, ++0xA5, 0xC6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0xBB, 0x12, 0x00, 0x19, 0x1E, 0x14, 0x00, 0x35, 0xEE, 0x12, 0x00, ++0x49, 0xED, 0x12, 0x00, 0x79, 0x5C, 0x13, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x79, 0x5C, 0x13, 0x00, 0x49, 0x11, 0x12, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x65, 0x5A, 0x12, 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, 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, 0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, ++0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, 0x7D, 0x4A, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x99, 0x1A, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x8D, 0x52, 0x12, 0x00, 0x79, 0x51, 0x12, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xCD, 0x5B, 0x12, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x05, 0x48, 0x00, 0x68, 0x10, 0xF0, 0x00, 0x4F, ++0x0C, 0xBF, 0x04, 0x48, 0x20, 0xF0, 0x7F, 0x40, 0x80, 0xF3, 0x08, 0x88, 0x02, 0x48, 0x00, 0x47, 0x44, 0x01, 0x50, 0x40, ++0x00, 0x38, 0x18, 0x00, 0x05, 0xC7, 0x12, 0x00, 0xF0, 0xB4, 0x86, 0x07, 0x46, 0xD0, 0x54, 0x1E, 0x00, 0x2A, 0x3C, 0xD0, ++0xCA, 0xB2, 0x03, 0x46, 0x01, 0xE0, 0x01, 0x3C, 0x37, 0xD3, 0x03, 0xF8, 0x01, 0x2B, 0x9D, 0x07, 0xF9, 0xD1, 0x03, 0x2C, ++0x2A, 0xD9, 0xCD, 0xB2, 0x45, 0xEA, 0x05, 0x25, 0x0F, 0x2C, 0x45, 0xEA, 0x05, 0x45, 0x34, 0xD9, 0xA4, 0xF1, 0x10, 0x02, ++0x22, 0xF0, 0x0F, 0x0C, 0x03, 0xF1, 0x20, 0x07, 0x16, 0x09, 0x67, 0x44, 0x03, 0xF1, 0x10, 0x02, 0x42, 0xE9, 0x04, 0x55, ++0x42, 0xE9, 0x02, 0x55, 0x10, 0x32, 0xBA, 0x42, 0xF8, 0xD1, 0x72, 0x1C, 0x14, 0xF0, 0x0C, 0x0F, 0x03, 0xEB, 0x02, 0x12, ++0x04, 0xF0, 0x0F, 0x06, 0x13, 0xD0, 0x33, 0x1F, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x42, 0xF8, 0x04, 0x5B, ++0x93, 0x42, 0xFB, 0xD1, 0x06, 0xF0, 0x03, 0x04, 0x2C, 0xB1, 0xCA, 0xB2, 0x1C, 0x44, 0x03, 0xF8, 0x01, 0x2B, 0x9C, 0x42, ++0xFB, 0xD1, 0xF0, 0xBC, 0x70, 0x47, 0x34, 0x46, 0x13, 0x46, 0x00, 0x2C, 0xF3, 0xD1, 0xF8, 0xE7, 0x14, 0x46, 0x03, 0x46, ++0xC1, 0xE7, 0x1A, 0x46, 0x26, 0x46, 0xE0, 0xE7, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x68, 0x91, 0x4F, 0x4F, 0xD9, 0xF8, ++0x00, 0x60, 0xDF, 0xF8, 0x64, 0xC1, 0x33, 0x89, 0xD6, 0xF8, 0x34, 0xE0, 0xC7, 0xF8, 0x10, 0xE0, 0xD6, 0xE9, 0x09, 0x10, ++0xD6, 0xE9, 0x0B, 0x45, 0x39, 0x60, 0xC9, 0x08, 0x03, 0x29, 0x78, 0x60, 0x4F, 0xEA, 0xD0, 0x00, 0x38, 0xBF, 0x03, 0x21, ++0xBC, 0x60, 0x03, 0x28, 0x4F, 0xEA, 0xD4, 0x04, 0x38, 0xBF, 0x03, 0x20, 0xFD, 0x60, 0x03, 0x2C, 0x4F, 0xEA, 0xD5, 0x05, ++0x4F, 0xF0, 0x54, 0x02, 0x4F, 0xEA, 0xDE, 0x07, 0x2C, 0xF0, 0x03, 0x0C, 0x38, 0xBF, 0x03, 0x24, 0xDF, 0xF8, 0x1C, 0xE1, ++0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0xA1, 0xC8, 0xF8, 0x00, 0x10, 0x03, 0x2D, 0x03, 0xFB, 0x02, 0x22, 0x38, 0xBF, ++0x03, 0x25, 0x62, 0x44, 0x03, 0x2F, 0x38, 0xBF, 0x03, 0x27, 0x72, 0x45, 0xC8, 0xE9, 0x01, 0x04, 0xC8, 0xE9, 0x03, 0x57, ++0xCA, 0xF8, 0x00, 0xC0, 0x4F, 0xD8, 0x01, 0x33, 0xDF, 0xF8, 0xF4, 0xE0, 0x2E, 0x4A, 0xDF, 0xF8, 0xF4, 0x80, 0xDF, 0xF8, ++0xF4, 0x90, 0x4F, 0xF0, 0x58, 0x0C, 0x0C, 0xFB, 0x03, 0xE3, 0xD2, 0xF8, 0x00, 0xC0, 0x2A, 0x4A, 0x13, 0x60, 0x4F, 0xF4, ++0xAC, 0x72, 0x02, 0xFB, 0x01, 0x33, 0x02, 0xFB, 0x00, 0x30, 0x02, 0xFB, 0x04, 0x04, 0x02, 0xFB, 0x05, 0x45, 0xDC, 0xF8, ++0x00, 0x10, 0xC8, 0xF8, 0x00, 0x50, 0x02, 0xFB, 0x07, 0x52, 0xC9, 0xF8, 0x00, 0x40, 0x21, 0x4F, 0x21, 0x4D, 0x22, 0x4C, ++0x38, 0x60, 0x2B, 0x60, 0xC4, 0xF8, 0x00, 0xE0, 0x41, 0xB9, 0xDC, 0xF8, 0x04, 0x30, 0x04, 0x33, 0x11, 0x1D, 0x23, 0xF0, ++0x03, 0x03, 0xCC, 0xF8, 0x00, 0x10, 0x1A, 0x44, 0xDC, 0xF8, 0x08, 0x30, 0x13, 0xB9, 0x04, 0x32, 0xCC, 0xF8, 0x08, 0x20, ++0x18, 0x4B, 0xF2, 0x68, 0x1A, 0x60, 0x33, 0x78, 0x02, 0x2B, 0x0E, 0xD0, 0x01, 0x2B, 0x01, 0xD0, 0xBD, 0xE8, 0xF0, 0x87, ++0x72, 0x69, 0x00, 0x2A, 0xFA, 0xD0, 0x13, 0x49, 0x91, 0x42, 0xF7, 0xD9, 0xBD, 0xE8, 0xF0, 0x47, 0x11, 0x48, 0x05, 0xF0, ++0xC1, 0xBF, 0x32, 0x69, 0xF3, 0xE7, 0x71, 0x46, 0x0F, 0x48, 0x05, 0xF0, 0xBB, 0xFF, 0xD9, 0xF8, 0x00, 0x60, 0xD8, 0xF8, ++0x00, 0x10, 0x33, 0x89, 0xD8, 0xE9, 0x01, 0x04, 0xD8, 0xE9, 0x03, 0x57, 0x01, 0x33, 0xA1, 0xE7, 0x7C, 0x28, 0x17, 0x00, ++0x30, 0x36, 0x17, 0x00, 0xEC, 0x57, 0x18, 0x00, 0xF4, 0x57, 0x18, 0x00, 0xF0, 0x57, 0x18, 0x00, 0x14, 0x63, 0x18, 0x00, ++0x00, 0x38, 0x18, 0x00, 0x00, 0x38, 0x18, 0x00, 0x44, 0x76, 0x15, 0x00, 0x18, 0x76, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, ++0x2B, 0x07, 0x18, 0x00, 0x00, 0x24, 0x18, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x40, 0x61, 0x17, 0x00, 0xE0, 0x9F, 0x18, 0x00, ++0xFC, 0x57, 0x18, 0x00, 0xF8, 0x57, 0x18, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x49, 0x4C, 0x4A, 0x49, 0x4A, 0x4E, 0x4B, 0x4A, ++0x4B, 0x4D, 0x4C, 0x48, 0x0C, 0x60, 0x04, 0xF1, 0x44, 0x07, 0x21, 0x1D, 0xD4, 0xF8, 0xD0, 0x30, 0x37, 0x60, 0x04, 0xF1, ++0x80, 0x07, 0x11, 0x60, 0x2F, 0x60, 0x47, 0x49, 0x47, 0x4A, 0x04, 0xF1, 0x90, 0x05, 0x23, 0xF0, 0x7F, 0x43, 0x05, 0x60, ++0x04, 0xF1, 0xA8, 0x00, 0x08, 0x60, 0x23, 0xF0, 0xFF, 0x03, 0x04, 0xF1, 0xAA, 0x01, 0x11, 0x60, 0x83, 0xB1, 0x94, 0xF8, ++0xD1, 0x30, 0x23, 0xB1, 0x3F, 0x4A, 0x53, 0x6D, 0x23, 0xF0, 0x01, 0x03, 0x53, 0x65, 0x94, 0xF8, 0xD2, 0x30, 0x00, 0x2B, ++0x5B, 0xD1, 0x3B, 0x4B, 0x4F, 0xF0, 0x80, 0x62, 0xC3, 0xF8, 0x10, 0x21, 0x39, 0x4D, 0x3A, 0x4F, 0xD5, 0xF8, 0x30, 0x32, ++0xDF, 0xF8, 0xF8, 0x80, 0x98, 0x47, 0x01, 0x21, 0x00, 0x20, 0x05, 0xF0, 0x5F, 0xFF, 0x00, 0x20, 0x05, 0xF0, 0x9A, 0xFF, ++0x01, 0x21, 0x02, 0x20, 0x05, 0xF0, 0x58, 0xFF, 0x02, 0x20, 0x05, 0xF0, 0x93, 0xFF, 0x01, 0x21, 0x03, 0x20, 0x05, 0xF0, ++0x51, 0xFF, 0x03, 0x20, 0x05, 0xF0, 0x8C, 0xFF, 0x3B, 0x68, 0x03, 0xF0, 0x0F, 0x03, 0xA3, 0xF1, 0x0A, 0x03, 0xB3, 0xFA, ++0x83, 0xF3, 0x5B, 0x09, 0x88, 0xF8, 0x02, 0x30, 0x25, 0xF0, 0x0E, 0xFA, 0x05, 0xF0, 0x90, 0xFA, 0x06, 0xF0, 0x54, 0xF8, ++0xD5, 0xF8, 0x74, 0x32, 0x98, 0x47, 0x94, 0xF8, 0x44, 0x10, 0x23, 0x48, 0x24, 0xF0, 0xEE, 0xF8, 0x07, 0xF0, 0x8C, 0xF8, ++0x06, 0xF0, 0xA8, 0xF9, 0x98, 0xF8, 0x02, 0x30, 0x0B, 0xB3, 0xD5, 0xF8, 0x6C, 0x34, 0x98, 0x47, 0x1D, 0x4A, 0x1E, 0x49, ++0x13, 0x68, 0x23, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0x0F, 0x03, 0x3B, 0x60, 0x02, 0x20, 0x24, 0xF0, ++0x27, 0xF9, 0x33, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x02, 0xD1, 0x17, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD5, 0xF8, 0x80, 0x32, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x0D, 0x4A, 0x53, 0x6D, 0x23, 0xF0, 0x02, 0x03, 0x53, 0x65, 0x9D, 0xE7, 0x11, 0x49, ++0x02, 0x20, 0x24, 0xF0, 0x11, 0xF9, 0xE8, 0xE7, 0x2C, 0x19, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, ++0xC8, 0x35, 0x17, 0x00, 0x30, 0x36, 0x17, 0x00, 0xAC, 0x35, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x00, 0x58, 0x40, 0x70, 0x76, 0x15, 0x00, 0x10, 0x00, 0x58, 0x40, ++0x80, 0x76, 0x15, 0x00, 0x00, 0x41, 0x04, 0x40, 0x8C, 0x76, 0x15, 0x00, 0x3C, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x20, 0x4B, ++0x04, 0x46, 0x1E, 0x68, 0x1D, 0x68, 0x00, 0xF0, 0xAB, 0xFE, 0x07, 0x46, 0x00, 0xF0, 0xAA, 0xFE, 0x01, 0x2C, 0xC6, 0xF3, ++0x03, 0x26, 0xC5, 0xF3, 0xC0, 0x65, 0x14, 0xD0, 0x02, 0x2C, 0x0E, 0xD0, 0x3C, 0xB1, 0x18, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x1C, 0xDB, 0x00, 0x20, 0xF8, 0xBD, 0x90, 0xB9, 0x05, 0xBB, 0x70, 0x1E, 0x18, 0xBF, 0x01, 0x20, ++0xF8, 0xBD, 0x01, 0x2E, 0x0D, 0xD0, 0x68, 0x1D, 0xF8, 0xBD, 0x30, 0xB9, 0x01, 0x2E, 0x17, 0xD0, 0x00, 0x2F, 0x0C, 0xBF, ++0x03, 0x20, 0x09, 0x20, 0xF8, 0xBD, 0x0B, 0x20, 0xF8, 0xBD, 0x0A, 0x20, 0xF8, 0xBD, 0x00, 0x2D, 0x14, 0xBF, 0x07, 0x20, ++0x04, 0x20, 0xF8, 0xBD, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xB5, 0x12, 0x24, 0xF0, 0xDC, 0xFA, 0x00, 0x20, 0xF8, 0xBD, ++0x08, 0x20, 0xF8, 0xBD, 0x02, 0x20, 0xF8, 0xBD, 0x00, 0x00, 0x33, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x10, 0xB4, 0x09, 0x49, 0x0B, 0x69, 0x83, 0xB0, 0x18, 0x44, 0x20, 0x24, 0x01, 0x94, 0x01, 0x9B, ++0x5A, 0x1E, 0x01, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x0B, 0x69, 0x1B, 0x1A, 0x00, 0x2B, 0xF5, 0xDB, 0x03, 0xB0, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x08, 0xB5, 0xFF, 0xF7, 0x9D, 0xFF, 0x03, 0x4B, 0x1A, 0x78, 0x82, 0x42, ++0x18, 0xBF, 0x18, 0x70, 0x08, 0xBD, 0x00, 0xBF, 0x60, 0x25, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4B, 0x10, 0x4C, 0x18, 0x68, ++0xC0, 0xF3, 0x01, 0x60, 0xFF, 0xF7, 0x8C, 0xFF, 0x08, 0x22, 0x05, 0x46, 0x00, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0xB6, 0xFD, ++0x0B, 0x48, 0x0C, 0x4A, 0x00, 0xEB, 0x05, 0x10, 0xFF, 0x21, 0xC3, 0x88, 0x80, 0x88, 0x10, 0x60, 0xC3, 0xF3, 0x85, 0x12, ++0x03, 0xF0, 0x3F, 0x03, 0x1A, 0x44, 0x21, 0x70, 0x4F, 0xF4, 0x96, 0x63, 0xB3, 0xFB, 0xF2, 0xF3, 0x63, 0x70, 0x38, 0xBD, ++0x00, 0x00, 0x33, 0x40, 0x60, 0x25, 0x17, 0x00, 0x98, 0x76, 0x15, 0x00, 0x6C, 0x00, 0x34, 0x40, 0x01, 0x4B, 0x58, 0x78, ++0x70, 0x47, 0x00, 0xBF, 0x60, 0x25, 0x17, 0x00, 0x10, 0xB4, 0x13, 0x4B, 0x13, 0x49, 0x11, 0x22, 0x1A, 0x60, 0x08, 0x69, ++0x83, 0xB0, 0x0A, 0x30, 0x20, 0x24, 0x00, 0x94, 0x00, 0x9B, 0x5A, 0x1E, 0x00, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x0A, 0x69, ++0x12, 0x1A, 0x00, 0x2A, 0xF5, 0xDB, 0x0A, 0x4A, 0x0A, 0x4C, 0x13, 0x60, 0x09, 0x69, 0x20, 0x20, 0x0A, 0x31, 0x01, 0x90, ++0x01, 0x9B, 0x5A, 0x1E, 0x01, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x23, 0x69, 0x5B, 0x1A, 0x00, 0x2B, 0xF5, 0xDB, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x00, 0x34, 0x40, 0x00, 0x10, 0x50, 0x40, 0x16, 0x4A, 0x13, 0x68, ++0x43, 0xF4, 0x80, 0x53, 0x10, 0xB4, 0x13, 0x60, 0x00, 0xBF, 0x02, 0xF5, 0x99, 0x42, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x53, ++0x13, 0x60, 0x00, 0xBF, 0x10, 0x4B, 0x11, 0x48, 0x03, 0xF5, 0x00, 0x64, 0xC0, 0x1A, 0x1A, 0x18, 0x53, 0xF8, 0x04, 0x1B, ++0x11, 0x60, 0xA3, 0x42, 0xF9, 0xD1, 0x00, 0xBF, 0x09, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x00, 0xBF, ++0x1A, 0x68, 0x22, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x00, 0xBF, 0x07, 0x4A, 0x5D, 0xF8, 0x04, 0x4B, 0x13, 0x68, 0x23, 0xF0, ++0x00, 0x53, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x90, 0xB3, 0x33, 0x40, 0xB0, 0x05, 0x17, 0x00, 0x00, 0xA0, 0x33, 0x40, ++0x10, 0x00, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x15, 0x46, 0x1C, 0x46, 0x9D, 0xF8, 0x18, 0x80, 0x0E, 0x46, ++0xFF, 0xF7, 0x94, 0xFF, 0x6C, 0x4A, 0x13, 0x68, 0x01, 0x2F, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x00, 0xF0, 0x98, 0x80, ++0x69, 0x4A, 0x6A, 0x49, 0x13, 0x68, 0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x40, 0x43, 0x13, 0x60, 0x0B, 0x68, 0x02, 0xF5, ++0xD9, 0x32, 0x02, 0xF5, 0xA2, 0x72, 0x43, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, ++0x61, 0x4A, 0x10, 0x68, 0x20, 0xF4, 0xFF, 0x40, 0x20, 0xF0, 0x7F, 0x00, 0x4F, 0xF0, 0x80, 0x63, 0xB3, 0xFB, 0xF5, 0xF3, ++0xC3, 0xF3, 0x0E, 0x03, 0x03, 0x43, 0x01, 0x2C, 0x13, 0x60, 0x60, 0xD0, 0x02, 0x2C, 0x48, 0xD0, 0x00, 0x25, 0x59, 0x4B, ++0x1E, 0x68, 0x26, 0xF0, 0x03, 0x06, 0x35, 0x43, 0x1D, 0x60, 0x00, 0x23, 0x56, 0x4A, 0x57, 0x49, 0x13, 0x60, 0x0B, 0x68, ++0x56, 0x4D, 0x57, 0x48, 0x57, 0x4E, 0x22, 0x06, 0x02, 0xF0, 0x40, 0x72, 0x23, 0xF0, 0x40, 0x73, 0x13, 0x43, 0x0B, 0x60, ++0x29, 0x68, 0x23, 0x04, 0x21, 0xF4, 0x40, 0x31, 0x03, 0xF4, 0x40, 0x33, 0x0B, 0x43, 0x2B, 0x60, 0x03, 0x68, 0x23, 0xF0, ++0x80, 0x43, 0x03, 0x60, 0x31, 0x68, 0x05, 0xF5, 0x82, 0x35, 0x04, 0xF0, 0x0F, 0x03, 0x21, 0xF0, 0x0F, 0x01, 0x05, 0xF5, ++0x88, 0x75, 0x0B, 0x43, 0x33, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0x40, 0x73, 0x1A, 0x43, 0x2A, 0x60, 0xEC, 0xB9, 0x50, 0xF8, ++0x08, 0x3C, 0x45, 0x49, 0x45, 0x4A, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0xC8, 0x53, 0x40, 0xF8, 0x08, 0x3C, 0x0B, 0x68, ++0x23, 0xF0, 0x30, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0x1C, 0x43, 0x13, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0xAD, 0x1B, 0x00, 0x2D, 0x42, 0xDD, 0x0A, 0x2D, 0xCC, 0xBF, 0x00, 0x25, 0x01, 0x25, 0xAF, 0xE7, 0x01, 0x2C, ++0x41, 0xD0, 0x38, 0x4A, 0x38, 0x49, 0x13, 0x68, 0x38, 0x48, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0x60, 0x63, 0x13, 0x60, ++0x08, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0xF5, 0x28, 0x42, 0xB5, 0x42, 0x53, 0x6B, 0x88, 0xBF, 0x01, 0x21, 0x23, 0xF0, ++0x03, 0x03, 0x98, 0xBF, 0x02, 0x21, 0x43, 0xEA, 0x01, 0x03, 0x02, 0xF1, 0x34, 0x02, 0x13, 0x60, 0x94, 0xBF, 0x01, 0x23, ++0x00, 0x23, 0x95, 0xE7, 0x1D, 0x49, 0x1E, 0x48, 0x0B, 0x68, 0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0xC0, 0x33, 0x0B, 0x60, ++0x03, 0x68, 0x01, 0xF5, 0xD9, 0x31, 0x01, 0xF5, 0xA2, 0x71, 0x23, 0xF0, 0x01, 0x03, 0x03, 0x60, 0x0B, 0x68, 0x18, 0xF0, ++0x04, 0x0F, 0x43, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x3F, 0xF4, 0x64, 0xAF, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, ++0x5E, 0xE7, 0x15, 0xF1, 0x0A, 0x0F, 0xB4, 0xBF, 0x03, 0x25, 0x02, 0x25, 0x6B, 0xE7, 0x1A, 0x48, 0x14, 0x49, 0x03, 0x68, ++0x14, 0x4A, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0xC0, 0x53, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x30, 0x03, 0x43, 0xF0, ++0x10, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0xD8, 0x43, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, ++0x24, 0x03, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x20, 0x08, 0x33, 0x40, 0x4C, 0x08, 0x33, 0x40, 0x80, 0xB0, 0x33, 0x40, ++0x50, 0x08, 0x33, 0x40, 0x24, 0x08, 0x33, 0x40, 0x10, 0x03, 0x32, 0x40, 0x0C, 0x08, 0x33, 0x40, 0x00, 0x08, 0x33, 0x40, ++0x08, 0x00, 0x34, 0x40, 0x8C, 0x08, 0x33, 0x40, 0x34, 0x08, 0x33, 0x40, 0x18, 0x08, 0x33, 0x40, 0x06, 0x0C, 0x8E, 0x01, ++0x04, 0x08, 0x33, 0x40, 0x44, 0x49, 0x45, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0xFC, 0x63, 0x70, 0xB4, 0x0B, 0x60, 0x13, 0x68, ++0x42, 0x4C, 0x43, 0x4D, 0x43, 0x4E, 0x23, 0xF4, 0xE0, 0x23, 0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0xE0, 0x03, 0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x23, 0x68, 0xA1, 0xF5, 0x0F, 0x41, 0x23, 0xF4, 0x00, 0x03, 0x23, 0x60, ++0x04, 0x39, 0x0C, 0x23, 0x2B, 0x60, 0x0B, 0x68, 0x32, 0x6A, 0x23, 0xF4, 0xFE, 0x43, 0x23, 0xF0, 0x7F, 0x03, 0x13, 0x43, ++0x40, 0xF6, 0xB4, 0x12, 0x90, 0x42, 0x0B, 0x60, 0x34, 0x4B, 0x26, 0xD0, 0x72, 0x6A, 0x1A, 0x60, 0xA0, 0xF6, 0x6C, 0x13, ++0x3C, 0x2B, 0x22, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, ++0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, ++0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, ++0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x00, 0x21, 0x4A, 0x1A, 0x60, 0x21, 0x4A, 0x21, 0x49, 0x13, 0x68, ++0x91, 0xF8, 0xB4, 0x10, 0x23, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x99, 0xB1, 0x1E, 0x49, 0x1F, 0x4B, 0x0A, 0x68, 0x22, 0xF4, ++0xFE, 0x62, 0x0A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x9A, 0x68, 0x22, 0xF0, ++0x0F, 0x02, 0x9A, 0x60, 0xDA, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0xDA, 0x60, 0x70, 0xBC, 0x70, 0x47, 0x15, 0x49, 0x16, 0x4B, ++0xB0, 0x6A, 0x72, 0x6B, 0x08, 0x60, 0x1A, 0x60, 0xD9, 0xE7, 0x12, 0x4B, 0xF4, 0x6A, 0xB1, 0x6B, 0x11, 0x4A, 0x1C, 0x60, ++0x40, 0xF6, 0xA8, 0x13, 0x98, 0x42, 0x11, 0x60, 0xCF, 0xD1, 0x0F, 0x4B, 0x11, 0x22, 0x1A, 0x60, 0xCB, 0xE7, 0x00, 0xBF, ++0x04, 0x40, 0x34, 0x40, 0x34, 0x21, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x00, 0xB3, 0x33, 0x40, 0xDC, 0x18, 0x17, 0x00, ++0x20, 0x03, 0x33, 0x40, 0x1B, 0x88, 0xB3, 0x01, 0x30, 0x20, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x78, 0x40, 0x34, 0x40, ++0x00, 0x30, 0x50, 0x40, 0x30, 0x40, 0x34, 0x40, 0x2C, 0x40, 0x34, 0x40, 0x24, 0x01, 0x58, 0x40, 0x70, 0x47, 0x00, 0xBF, ++0x3A, 0x49, 0x3B, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0xFC, 0x63, 0x43, 0xF4, 0xA8, 0x63, 0x30, 0xB4, 0x0B, 0x60, 0x13, 0x68, ++0x37, 0x4C, 0x38, 0x4D, 0x23, 0xF4, 0xE0, 0x23, 0x43, 0xF4, 0x00, 0x33, 0x13, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xE0, 0x03, ++0x13, 0x60, 0x23, 0x68, 0x33, 0x4A, 0xA1, 0xF5, 0x0F, 0x41, 0x43, 0xF4, 0x00, 0x03, 0x23, 0x60, 0x04, 0x39, 0x0C, 0x23, ++0x2B, 0x60, 0x0B, 0x68, 0xD4, 0x6C, 0x23, 0xF4, 0xFE, 0x43, 0x23, 0xF0, 0x7F, 0x03, 0x23, 0x43, 0x41, 0xF2, 0xC8, 0x44, ++0xA0, 0x42, 0x0B, 0x60, 0x40, 0xD8, 0x2A, 0x4B, 0x12, 0x6C, 0x1A, 0x60, 0x29, 0x4A, 0x2A, 0x4C, 0x13, 0x68, 0x2A, 0x4D, ++0x2A, 0x48, 0x2B, 0x49, 0x23, 0xF0, 0x80, 0x63, 0x13, 0x60, 0x13, 0x68, 0x94, 0xF8, 0xB4, 0x40, 0x23, 0xF0, 0x0F, 0x03, ++0x43, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x80, 0x63, 0x2B, 0x60, 0x03, 0x68, ++0x43, 0xF4, 0x70, 0x63, 0x03, 0x60, 0x0B, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x0B, 0x60, 0xDC, 0xB1, 0x01, 0xF5, 0x01, 0x51, ++0x1D, 0x4B, 0x8A, 0x68, 0x22, 0xF4, 0xFE, 0x62, 0x42, 0xF4, 0x88, 0x62, 0x8A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x0F, 0x02, ++0x42, 0xF0, 0x03, 0x02, 0x1A, 0x60, 0x9A, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x03, 0x02, 0x9A, 0x60, 0xDA, 0x68, ++0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x03, 0x02, 0x08, 0x31, 0xDA, 0x60, 0x30, 0xBC, 0x70, 0x47, 0x41, 0xF2, 0x44, 0x63, ++0x98, 0x42, 0x08, 0x4B, 0x94, 0xBF, 0x52, 0x6C, 0x92, 0x6C, 0x1A, 0x60, 0xB8, 0xE7, 0x00, 0xBF, 0x04, 0x40, 0x34, 0x40, ++0x34, 0x21, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x00, 0xB3, 0x33, 0x40, 0xDC, 0x18, 0x17, 0x00, 0x30, 0x40, 0x34, 0x40, ++0x38, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x3C, 0x40, 0x34, 0x40, 0x08, 0x01, 0x58, 0x40, 0x30, 0x20, 0x34, 0x40, ++0x00, 0x30, 0x50, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x85, 0xB0, 0x0F, 0x46, 0x9D, 0xF8, 0x3C, 0x10, ++0x02, 0x91, 0xCD, 0xE9, 0x00, 0x23, 0x05, 0x46, 0x14, 0x46, 0x1E, 0x46, 0x02, 0x46, 0x3B, 0x46, 0xAE, 0x49, 0xAF, 0x48, ++0x9D, 0xF8, 0x38, 0xA0, 0xDF, 0xF8, 0x08, 0x83, 0xDF, 0xF8, 0x08, 0x93, 0x23, 0xF0, 0x4C, 0xFD, 0xAB, 0x49, 0x22, 0x46, ++0x04, 0x20, 0x23, 0xF0, 0x97, 0xFD, 0x30, 0x46, 0xFF, 0xF7, 0x06, 0xFD, 0x39, 0x46, 0x33, 0x46, 0xD8, 0xF8, 0x40, 0x71, ++0xCD, 0xF8, 0x00, 0xA0, 0x22, 0x46, 0x28, 0x46, 0xB8, 0x47, 0x99, 0xF8, 0x2A, 0x30, 0xAB, 0x42, 0x0A, 0xD0, 0xD8, 0xF8, ++0x80, 0x34, 0x28, 0x46, 0x98, 0x47, 0x99, 0xF8, 0x2A, 0x20, 0x9F, 0x49, 0x2B, 0x46, 0x04, 0x20, 0x23, 0xF0, 0x7C, 0xFD, ++0x9D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA8, 0x80, 0x00, 0x2D, 0x00, 0xF0, 0xB7, 0x80, ++0x41, 0xF2, 0x43, 0x63, 0x9C, 0x42, 0x00, 0xF2, 0xAE, 0x80, 0x41, 0xF2, 0x7B, 0x53, 0x9C, 0x42, 0x8B, 0xBF, 0x4F, 0xF0, ++0xEC, 0x09, 0x4F, 0xF0, 0xFC, 0x09, 0x3B, 0x27, 0x3F, 0x27, 0x20, 0x46, 0x35, 0xF0, 0x0E, 0xFD, 0x02, 0x46, 0x0B, 0x46, ++0x82, 0x46, 0x8B, 0x46, 0x35, 0xF0, 0xBC, 0xFB, 0x8D, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0x98, 0xFE, 0x8C, 0x4B, 0x00, 0x22, ++0x35, 0xF0, 0x6A, 0xFD, 0x35, 0xF0, 0x62, 0xFB, 0x36, 0xF0, 0x00, 0xF8, 0x52, 0x46, 0x5B, 0x46, 0x88, 0x49, 0x05, 0x46, ++0x00, 0x20, 0x35, 0xF0, 0x89, 0xFE, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x35, 0xF0, 0x5A, 0xFD, 0x35, 0xF0, 0x52, 0xFB, ++0x35, 0xF0, 0xF0, 0xFF, 0x03, 0x46, 0x38, 0x46, 0x1F, 0x46, 0x35, 0xF0, 0xE7, 0xFC, 0x80, 0x4B, 0x00, 0x22, 0x35, 0xF0, ++0x4D, 0xFD, 0x02, 0x46, 0x0B, 0x46, 0x50, 0x46, 0x59, 0x46, 0x35, 0xF0, 0x71, 0xFE, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, ++0x35, 0xF0, 0x42, 0xFD, 0x35, 0xF0, 0x3A, 0xFB, 0x35, 0xF0, 0xD8, 0xFF, 0x77, 0x4B, 0x78, 0x4A, 0xD3, 0xF8, 0x00, 0xE0, ++0x2E, 0xF4, 0x00, 0x0E, 0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x4E, 0xF4, 0x80, 0x0E, 0xC3, 0xF8, 0x00, 0xE0, ++0xD3, 0xF8, 0x00, 0xE0, 0x2E, 0xF4, 0x00, 0x1E, 0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x4E, 0xF0, 0x08, 0x0E, ++0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x01, 0x46, 0x2E, 0xF0, 0x04, 0x0E, 0x6A, 0x48, 0xC3, 0xF8, 0x00, 0xE0, ++0x03, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x03, 0x60, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x53, 0x03, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0xFF, 0x63, 0x23, 0xF0, 0x04, 0x03, 0x43, 0xEA, 0x09, 0x03, 0x13, 0x60, 0x20, 0x46, 0xD8, 0xF8, 0xA8, 0x34, 0x89, 0x46, ++0x98, 0x47, 0x20, 0x46, 0xD8, 0xF8, 0xAC, 0x34, 0x64, 0x08, 0x98, 0x47, 0x5C, 0x4B, 0x5D, 0x4A, 0x1D, 0x60, 0x17, 0x60, ++0xC3, 0xF8, 0x48, 0x90, 0x00, 0x2E, 0x00, 0xF0, 0x8D, 0x80, 0x01, 0x2E, 0x04, 0xD1, 0x59, 0x4A, 0x13, 0x68, 0x23, 0xF4, ++0x00, 0x63, 0x13, 0x60, 0x57, 0x49, 0x58, 0x4B, 0x08, 0x68, 0x58, 0x4A, 0x03, 0x40, 0x43, 0xEA, 0x04, 0x33, 0x01, 0x20, ++0x0B, 0x60, 0x10, 0x60, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x2D, 0x7F, 0xF6, 0x55, 0xAF, 0x52, 0x49, 0x53, 0x48, ++0x40, 0xF6, 0x4A, 0x22, 0x23, 0xF0, 0xEE, 0xFE, 0x41, 0xF2, 0x43, 0x63, 0x9C, 0x42, 0x7F, 0xF6, 0x52, 0xAF, 0x4F, 0xF0, ++0xF0, 0x09, 0x3C, 0x27, 0x57, 0xE7, 0x20, 0x46, 0x35, 0xF0, 0x66, 0xFC, 0x4B, 0x4B, 0x00, 0x22, 0x82, 0x46, 0x8B, 0x46, ++0x35, 0xF0, 0xCA, 0xFC, 0x39, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0xF0, 0xFD, 0x38, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0xC2, 0xFC, ++0x35, 0xF0, 0xBA, 0xFA, 0x35, 0xF0, 0x58, 0xFF, 0x52, 0x46, 0x5B, 0x46, 0x05, 0x46, 0x42, 0x49, 0x00, 0x20, 0x35, 0xF0, ++0xE1, 0xFD, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x35, 0xF0, 0xB2, 0xFC, 0x35, 0xF0, 0xAA, 0xFA, 0x35, 0xF0, 0x48, 0xFF, ++0x24, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x07, 0x46, 0x59, 0x46, 0x50, 0x46, 0x35, 0xF0, 0xD0, 0xFD, 0x00, 0x22, 0x4F, 0xF0, ++0x83, 0x43, 0x35, 0xF0, 0xA1, 0xFC, 0x35, 0xF0, 0x99, 0xFA, 0x35, 0xF0, 0x37, 0xFF, 0x27, 0x4B, 0x28, 0x4A, 0x19, 0x68, ++0x21, 0xF4, 0x00, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x80, 0x01, 0x19, 0x60, 0x19, 0x68, 0x41, 0xF4, 0x00, 0x11, ++0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x08, 0x01, 0x19, 0x60, 0x19, 0x68, 0x41, 0xF0, 0x04, 0x01, 0x19, 0x60, 0x13, 0x68, ++0x23, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x81, 0x46, 0x23, 0xF0, 0x00, 0x53, 0x19, 0x48, 0x13, 0x60, 0x03, 0x68, ++0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, 0x04, 0x03, 0x43, 0xF0, 0xEC, 0x03, 0x03, 0x60, 0xD8, 0xF8, 0xA0, 0x34, 0x20, 0x46, ++0x98, 0x47, 0xD8, 0xF8, 0xA4, 0x34, 0x20, 0x46, 0x98, 0x47, 0x69, 0xE7, 0x13, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x63, ++0x13, 0x60, 0x73, 0xE7, 0xAF, 0xF3, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xA2, 0x40, 0x78, 0x78, 0x15, 0x00, ++0x58, 0x77, 0x15, 0x00, 0x8C, 0x77, 0x15, 0x00, 0x9C, 0x77, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x00, 0x6A, 0x40, ++0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0xB9, 0x40, 0x00, 0x00, 0x54, 0x40, 0x14, 0x40, 0x34, 0x40, 0x3C, 0x40, 0x34, 0x40, ++0x30, 0x40, 0x34, 0x40, 0x10, 0x20, 0x34, 0x40, 0x54, 0x20, 0x34, 0x40, 0x20, 0x40, 0x34, 0x40, 0x1C, 0x20, 0x34, 0x40, ++0xFF, 0x0F, 0x00, 0xE0, 0x84, 0x21, 0x34, 0x40, 0x70, 0x79, 0x15, 0x00, 0xB4, 0x77, 0x15, 0x00, 0x00, 0x00, 0x10, 0x40, ++0x00, 0x00, 0xA4, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0xF8, 0xB5, 0x43, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x6B, 0xDB, 0xFF, 0xF7, 0xBD, 0xFB, 0x40, 0x49, 0x40, 0x4A, 0x0B, 0x68, 0x40, 0x48, 0x43, 0xF0, ++0x00, 0x63, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x03, 0x68, 0xC3, 0xF3, 0x03, 0x23, 0x02, 0x2B, ++0x06, 0xD1, 0xA2, 0xF5, 0x99, 0x42, 0x04, 0x3A, 0x13, 0x68, 0x43, 0xF0, 0x03, 0x03, 0x13, 0x60, 0x36, 0x4B, 0x1B, 0x68, ++0xC3, 0xF3, 0x03, 0x13, 0x02, 0x2B, 0x02, 0xD1, 0x34, 0x4B, 0x35, 0x4A, 0x1A, 0x60, 0x35, 0x4A, 0x35, 0x49, 0x13, 0x68, ++0xDF, 0xF8, 0x04, 0xC1, 0x34, 0x4D, 0x35, 0x4F, 0x35, 0x4C, 0x36, 0x48, 0x36, 0x4E, 0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, ++0x07, 0x03, 0x43, 0xF4, 0xE0, 0x63, 0x13, 0x60, 0x4F, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x04, 0x23, 0xCC, 0xF8, 0x00, 0x30, ++0x01, 0x22, 0xC4, 0x23, 0x3A, 0x60, 0x2B, 0x60, 0x00, 0x23, 0x23, 0x60, 0x6F, 0x24, 0x04, 0x60, 0x2C, 0x4C, 0xB0, 0x27, ++0x37, 0x60, 0x23, 0x60, 0xC3, 0x60, 0xAB, 0x61, 0x6B, 0x25, 0xE5, 0x60, 0x29, 0x4D, 0x83, 0x61, 0x2A, 0x60, 0xA3, 0x61, ++0x07, 0x24, 0x44, 0x62, 0xEC, 0x26, 0x27, 0x4C, 0xEE, 0x60, 0x03, 0x25, 0xC5, 0x62, 0x23, 0x60, 0xD0, 0xF8, 0xEC, 0x31, ++0x93, 0x42, 0x00, 0xF5, 0xF6, 0x70, 0x0F, 0xD9, 0x22, 0x4B, 0xA0, 0xF5, 0x56, 0x70, 0x1A, 0x60, 0x03, 0x68, 0x23, 0xF0, ++0x7F, 0x43, 0x43, 0xF0, 0x20, 0x43, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x40, 0x73, 0x43, 0xF4, 0x80, 0x73, 0x0B, 0x60, ++0xF8, 0xBD, 0x1B, 0x4A, 0x13, 0x68, 0x12, 0x68, 0x1B, 0x0E, 0x02, 0x33, 0x03, 0xEB, 0x83, 0x03, 0xC2, 0xF3, 0x07, 0x42, ++0x02, 0xEB, 0x43, 0x03, 0x1E, 0x2B, 0x86, 0xD0, 0x15, 0x49, 0x16, 0x48, 0x40, 0xF6, 0x2C, 0x32, 0x23, 0xF0, 0xBC, 0xFD, ++0x7F, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x10, 0x00, 0x34, 0x40, 0x14, 0x00, 0x34, 0x40, 0x00, 0x00, 0x33, 0x40, ++0x04, 0xB1, 0x33, 0x40, 0x34, 0x34, 0x34, 0x00, 0xB4, 0xB3, 0x33, 0x40, 0x00, 0x10, 0x34, 0x40, 0x08, 0x12, 0x34, 0x40, ++0x04, 0x12, 0x34, 0x40, 0x0C, 0x12, 0x34, 0x40, 0x10, 0x12, 0x34, 0x40, 0x14, 0x12, 0x34, 0x40, 0x18, 0x12, 0x34, 0x40, ++0x2C, 0x12, 0x34, 0x40, 0x40, 0x12, 0x34, 0x40, 0x0C, 0x10, 0x34, 0x40, 0x3C, 0x00, 0x33, 0x40, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0x77, 0x15, 0x00, 0x00, 0x12, 0x34, 0x40, 0x10, 0xB5, 0x1A, 0x4C, 0x82, 0xB0, 0xD4, 0xF8, 0x3C, 0x31, 0x98, 0x47, ++0x18, 0x4B, 0x19, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, ++0x15, 0x4A, 0x1A, 0x60, 0x19, 0x68, 0x12, 0x4A, 0x41, 0xF0, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xDB, ++0x11, 0x4B, 0x13, 0x60, 0x13, 0x68, 0x0D, 0x49, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x0B, 0x68, 0xDB, 0x0F, 0xFC, 0xD1, ++0xCD, 0xE9, 0x00, 0x33, 0x40, 0xF6, 0x85, 0x12, 0x11, 0x46, 0x18, 0x46, 0xD4, 0xF8, 0x28, 0x42, 0xA0, 0x47, 0x09, 0x49, ++0x09, 0x4B, 0x0A, 0x4A, 0x0C, 0x20, 0x08, 0x60, 0x1A, 0x60, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0x20, 0x00, 0x58, 0x40, 0xBF, 0x3F, 0x42, 0x01, 0xA2, 0x30, 0x43, 0x01, 0xDD, 0x1D, 0x44, 0x01, 0x00, 0xB3, 0x33, 0x40, ++0xC0, 0xB3, 0x33, 0x40, 0xA0, 0xA0, 0x28, 0x28, 0x70, 0xB5, 0x13, 0x4B, 0x13, 0x4D, 0x04, 0x46, 0xED, 0x1A, 0x03, 0xF2, ++0x3C, 0x50, 0x5A, 0x19, 0x53, 0xF8, 0x04, 0x1B, 0x11, 0x60, 0x83, 0x42, 0xF9, 0xD1, 0xFF, 0xF7, 0xEB, 0xFA, 0x0E, 0x4B, ++0x0E, 0x4E, 0xD3, 0xF8, 0x24, 0x32, 0x20, 0x46, 0x98, 0x47, 0x00, 0x23, 0x86, 0xF8, 0x2A, 0x30, 0x0F, 0xCC, 0x35, 0x46, ++0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, 0x23, 0x68, 0x2B, 0x60, 0x05, 0x21, 0x4F, 0xF0, 0xFF, 0x12, 0xFF, 0x23, 0x86, 0xF8, ++0x2B, 0x10, 0x72, 0x62, 0x33, 0x85, 0x70, 0xBD, 0xB0, 0x0D, 0x17, 0x00, 0x00, 0x90, 0x33, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0x08, 0xB5, 0x05, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x00, 0xD4, 0x08, 0xBD, 0x14, 0xF0, 0xF4, 0xFD, ++0x02, 0x4B, 0x08, 0x22, 0x1A, 0x60, 0x08, 0xBD, 0xA8, 0x10, 0x34, 0x40, 0xAC, 0x10, 0x34, 0x40, 0x03, 0x4A, 0x04, 0x4B, ++0x12, 0x68, 0x02, 0x60, 0x1B, 0x68, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x3C, 0x00, 0x33, 0x40, ++0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0x9D, 0xF8, 0x38, 0x40, 0xBD, 0xF8, 0x30, 0xA0, 0x9D, 0xF8, 0x34, 0x90, 0x00, 0x2C, ++0x43, 0xD1, 0x98, 0x46, 0x25, 0x4B, 0x1B, 0x78, 0x05, 0x46, 0x0E, 0x46, 0x17, 0x46, 0xD3, 0xB1, 0x23, 0x4C, 0x24, 0x4A, ++0xCD, 0xF8, 0x00, 0x90, 0x00, 0x23, 0xD2, 0xF8, 0x28, 0xB2, 0x01, 0x93, 0x42, 0x46, 0x33, 0x46, 0x39, 0x46, 0x28, 0x46, ++0xD8, 0x47, 0x84, 0xF8, 0x2A, 0x50, 0x84, 0xF8, 0x2B, 0x60, 0x84, 0xF8, 0x2C, 0x90, 0xA7, 0x84, 0xA4, 0xF8, 0x26, 0x80, ++0xA4, 0xF8, 0x28, 0xA0, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0x4A, 0x15, 0x4C, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, ++0x13, 0x60, 0x94, 0xF8, 0x2A, 0x30, 0x83, 0x42, 0xDB, 0xD1, 0x94, 0xF8, 0x2B, 0x30, 0x8B, 0x42, 0xD7, 0xD1, 0x94, 0xF8, ++0x2C, 0x30, 0x4B, 0x45, 0xD3, 0xD1, 0xA3, 0x8C, 0xBB, 0x42, 0xD0, 0xD1, 0xE3, 0x8C, 0x43, 0x45, 0xCD, 0xD1, 0x23, 0x8D, ++0x53, 0x45, 0xCA, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x23, 0xF0, 0x35, 0xBA, 0x08, 0x49, ++0x09, 0x48, 0x22, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x23, 0xF0, 0x2D, 0xBA, 0x00, 0xBF, 0x3C, 0x36, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x8C, 0x78, 0x15, 0x00, 0x38, 0x78, 0x15, 0x00, ++0x18, 0x78, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x71, 0xB9, 0x0A, 0x4A, 0x93, 0x8C, 0x92, 0xF8, 0x2B, 0x00, 0x92, 0xF8, ++0x2A, 0x10, 0xD2, 0xF8, 0x26, 0x20, 0x62, 0x60, 0x1B, 0x04, 0x43, 0xEA, 0x00, 0x23, 0x0B, 0x43, 0x23, 0x60, 0x10, 0xBD, ++0x0A, 0x46, 0x03, 0x48, 0x03, 0x49, 0x23, 0xF0, 0x07, 0xFA, 0xEA, 0xE7, 0xBC, 0x34, 0x17, 0x00, 0x18, 0x78, 0x15, 0x00, ++0x9C, 0x78, 0x15, 0x00, 0x04, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x00, 0xD1, 0x70, 0x47, 0x03, 0x49, 0x03, 0x48, 0x23, 0xF0, ++0xF7, 0xB9, 0x00, 0xBF, 0x38, 0x00, 0x32, 0x40, 0xAC, 0x78, 0x15, 0x00, 0x60, 0x78, 0x15, 0x00, 0x4F, 0xF4, 0x7A, 0x70, ++0x70, 0x47, 0x00, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0x01, 0x28, 0x94, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x00, 0xBF, ++0xFC, 0x13, 0x34, 0x40, 0x04, 0x4A, 0x13, 0x68, 0xC0, 0x00, 0x00, 0xF0, 0x08, 0x00, 0x23, 0xF0, 0x08, 0x03, 0x18, 0x43, ++0x10, 0x60, 0x70, 0x47, 0xA0, 0x10, 0x34, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x80, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x00, 0x33, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x00, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, ++0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x80, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x06, 0x4B, 0x02, 0x68, ++0x1A, 0x60, 0x42, 0x68, 0x5A, 0x60, 0x0A, 0x68, 0x9A, 0x60, 0x4A, 0x68, 0xDA, 0x60, 0x8A, 0x68, 0x1A, 0x61, 0xCA, 0x68, ++0x5A, 0x61, 0x70, 0x47, 0xA8, 0x08, 0x33, 0x40, 0x30, 0xB4, 0x06, 0x49, 0x06, 0x4D, 0x07, 0x4B, 0x00, 0x24, 0xC0, 0xF3, ++0x0A, 0x00, 0x40, 0xF2, 0xFF, 0x72, 0x28, 0x60, 0x0C, 0x60, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0xC4, 0x08, 0x33, 0x40, ++0xC0, 0x08, 0x33, 0x40, 0xC8, 0x08, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x03, 0x20, 0x01, 0x38, 0xC0, 0xB2, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x03, 0x10, 0x01, 0x38, 0xC0, 0xB2, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0x00, 0xF0, 0x0F, 0x00, 0x01, 0x38, 0xC0, 0xB2, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0xF0, 0xB5, 0xBE, 0x4C, 0x94, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x76, 0xD1, ++0xBC, 0x4B, 0x93, 0xF8, 0xBD, 0x50, 0x00, 0x2D, 0x66, 0xD0, 0xE0, 0x8C, 0x40, 0xF6, 0x7B, 0x14, 0xA0, 0x42, 0x40, 0xF2, ++0xCA, 0x80, 0x40, 0xF6, 0x94, 0x14, 0xA0, 0x42, 0xB6, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x01, 0x60, 0x90, 0xF9, 0x02, 0x60, ++0x93, 0xF8, 0xBE, 0x40, 0xB3, 0x48, 0x06, 0xF1, 0x0F, 0x05, 0x1E, 0x2D, 0x00, 0x5D, 0xA8, 0xBF, 0x1E, 0x25, 0x0A, 0x2C, ++0x4F, 0xEA, 0x20, 0x17, 0x00, 0xF0, 0x0F, 0x0C, 0x25, 0xEA, 0xE5, 0x75, 0x00, 0xF3, 0xCF, 0x80, 0x00, 0xF0, 0xE4, 0x80, ++0xAB, 0x48, 0x04, 0xEB, 0x44, 0x04, 0x10, 0xF9, 0x14, 0xE0, 0x75, 0x45, 0x00, 0xEB, 0x44, 0x04, 0x00, 0xF3, 0x06, 0x81, ++0x64, 0x78, 0xA4, 0xEB, 0x0E, 0x04, 0x2C, 0x44, 0x60, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, 0x07, 0xF1, 0xFF, 0x37, ++0xB8, 0xBF, 0x20, 0x46, 0x60, 0x44, 0x80, 0xF3, 0x04, 0x00, 0x40, 0xEA, 0x07, 0x10, 0x08, 0x70, 0x93, 0xF8, 0xBF, 0x10, ++0x9D, 0x4B, 0x5B, 0x5C, 0x0A, 0x29, 0x4F, 0xEA, 0x23, 0x10, 0x03, 0xF0, 0x0F, 0x03, 0x17, 0xDC, 0x00, 0xF0, 0xD1, 0x80, ++0x01, 0x31, 0x97, 0x4C, 0x01, 0xEB, 0x41, 0x01, 0x14, 0xF9, 0x11, 0x60, 0xAE, 0x42, 0x04, 0xEB, 0x41, 0x01, 0xC0, 0xF2, ++0xD2, 0x80, 0x49, 0x78, 0x89, 0x1B, 0x0D, 0x44, 0x6D, 0xB2, 0x6F, 0xF0, 0x04, 0x01, 0x01, 0x38, 0x8D, 0x42, 0xAC, 0xBF, ++0x5B, 0x19, 0x5B, 0x18, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x00, 0x13, 0x13, 0x70, 0xF0, 0xBD, 0x93, 0xF8, 0xAC, 0x40, ++0xE5, 0x07, 0x68, 0xD5, 0x93, 0xF8, 0xB7, 0x00, 0x08, 0x70, 0x93, 0xF8, 0xAD, 0x30, 0x13, 0x70, 0xF0, 0xBD, 0x81, 0x4B, ++0x93, 0xF8, 0xBD, 0x50, 0x00, 0x2D, 0x3A, 0xD0, 0xE0, 0x8C, 0x41, 0xF2, 0xC8, 0x44, 0xA0, 0x42, 0x4F, 0xD9, 0xB0, 0xF5, ++0xAF, 0x5F, 0x7D, 0xD8, 0x7F, 0x48, 0x90, 0xF9, 0x01, 0x60, 0x93, 0xF8, 0xC3, 0x00, 0x7E, 0x4B, 0x1B, 0x5C, 0x0A, 0x28, ++0x4F, 0xEA, 0x23, 0x15, 0x03, 0xF0, 0x0F, 0x03, 0x1D, 0xDC, 0x06, 0xF1, 0x0F, 0x04, 0x1E, 0x2C, 0xA8, 0xBF, 0x1E, 0x24, ++0x0A, 0x28, 0x24, 0xEA, 0xE4, 0x74, 0x7A, 0xD0, 0x76, 0x4E, 0x00, 0xEB, 0x40, 0x00, 0x16, 0xF9, 0x10, 0x70, 0xBC, 0x42, ++0x06, 0xEB, 0x40, 0x00, 0x00, 0xF3, 0x9E, 0x80, 0x40, 0x78, 0xC0, 0x1B, 0x04, 0x44, 0x64, 0xB2, 0x6F, 0xF0, 0x04, 0x00, ++0x01, 0x3D, 0x84, 0x42, 0xAC, 0xBF, 0x1B, 0x19, 0x1B, 0x18, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x05, 0x13, 0xDB, 0xB2, ++0x13, 0x70, 0x0B, 0x70, 0xF0, 0xBD, 0x93, 0xF8, 0xAC, 0x40, 0xA4, 0x07, 0x04, 0xD5, 0x93, 0xF8, 0xAE, 0x30, 0x0B, 0x70, ++0x13, 0x70, 0xF0, 0xBD, 0x90, 0xF9, 0x00, 0x30, 0x61, 0x48, 0x6F, 0xF0, 0x04, 0x04, 0xA3, 0x42, 0xB8, 0xBF, 0x23, 0x46, ++0x12, 0x2B, 0xA8, 0xBF, 0x12, 0x23, 0x05, 0x33, 0x5B, 0x10, 0xC3, 0x5C, 0x0B, 0x70, 0x13, 0x70, 0xF0, 0xBD, 0x59, 0x48, ++0x90, 0xF9, 0x00, 0x60, 0xB1, 0xE7, 0x53, 0x48, 0x90, 0xF9, 0x00, 0x60, 0x3A, 0xE7, 0x90, 0xF9, 0x00, 0x30, 0x51, 0x4D, ++0x52, 0x4C, 0x01, 0x2B, 0x6F, 0xF0, 0x01, 0x06, 0x18, 0x46, 0xB8, 0xBF, 0x01, 0x20, 0xB3, 0x42, 0xB8, 0xBF, 0x33, 0x46, ++0x17, 0x28, 0xA8, 0xBF, 0x17, 0x20, 0x14, 0x2B, 0xA8, 0xBF, 0x14, 0x23, 0x01, 0x38, 0x02, 0x33, 0x40, 0x10, 0x5B, 0x10, ++0x28, 0x5C, 0xE3, 0x5C, 0x08, 0x70, 0x13, 0x70, 0xF0, 0xBD, 0x74, 0x1C, 0x55, 0xDA, 0xA5, 0xF1, 0x0D, 0x00, 0x40, 0xB2, ++0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, 0xA7, 0xF1, 0x02, 0x07, 0xB8, 0xBF, 0x20, 0x46, 0x3B, 0xE7, 0x41, 0xF2, 0x44, 0x64, ++0xA0, 0x42, 0x3F, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x02, 0x60, 0x90, 0xF9, 0x03, 0x60, 0x7A, 0xE7, 0xB0, 0x1C, 0x53, 0xDB, ++0x01, 0x2E, 0x00, 0xF3, 0x8D, 0x80, 0xA5, 0xF1, 0x0F, 0x00, 0x40, 0xB2, 0x28, 0xE7, 0x03, 0x36, 0x43, 0xDA, 0x09, 0x3C, ++0x64, 0xB2, 0x6F, 0xF0, 0x04, 0x00, 0x01, 0x3D, 0x84, 0x42, 0xAC, 0xBF, 0x1B, 0x19, 0x1B, 0x18, 0x8D, 0xE7, 0x03, 0x36, ++0x30, 0xDA, 0x09, 0x3D, 0x6D, 0xB2, 0x6F, 0xF0, 0x04, 0x01, 0x01, 0x38, 0x8D, 0x42, 0xAC, 0xBF, 0x5B, 0x19, 0x5B, 0x18, ++0x38, 0xE7, 0x91, 0xF9, 0x04, 0x40, 0xAC, 0x42, 0x3B, 0xDD, 0xCC, 0x78, 0x89, 0x78, 0x61, 0x1A, 0x0D, 0x44, 0x43, 0xFA, ++0x85, 0xF3, 0x2D, 0xE7, 0x94, 0xF9, 0x04, 0xE0, 0x75, 0x45, 0x57, 0xDA, 0xE0, 0x78, 0xA4, 0x78, 0x00, 0x1B, 0x28, 0x44, ++0x40, 0xB2, 0xFB, 0xE6, 0x90, 0xF9, 0x04, 0x60, 0xB4, 0x42, 0x43, 0xDA, 0xC6, 0x78, 0x80, 0x78, 0x30, 0x1A, 0x04, 0x44, ++0x43, 0xFA, 0x84, 0xF3, 0x61, 0xE7, 0xA5, 0xF1, 0x0F, 0x04, 0x60, 0xB2, 0x03, 0x28, 0xA8, 0xBF, 0x03, 0x20, 0xE9, 0xE6, ++0x0F, 0x3D, 0x6D, 0xB2, 0x05, 0x2D, 0xD4, 0xBF, 0x5B, 0x19, 0x05, 0x33, 0x0A, 0xE7, 0x0F, 0x3C, 0x64, 0xB2, 0x05, 0x2C, ++0xD4, 0xBF, 0x1B, 0x19, 0x05, 0x33, 0x4C, 0xE7, 0xA5, 0xF1, 0x0A, 0x00, 0x40, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, ++0x07, 0xF1, 0xFF, 0x37, 0xB8, 0xBF, 0x20, 0x46, 0xD0, 0xE6, 0x49, 0x79, 0x09, 0x1B, 0x0D, 0x44, 0x6D, 0xB2, 0x05, 0x2D, ++0xD4, 0xBF, 0x5B, 0x19, 0x05, 0x33, 0x01, 0x30, 0xEE, 0xE6, 0x00, 0xBF, 0xBC, 0x34, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0x68, 0x25, 0x17, 0x00, 0xEC, 0x12, 0x17, 0x00, 0xB8, 0x78, 0x15, 0x00, 0xF8, 0x12, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, ++0x04, 0x13, 0x17, 0x00, 0x0C, 0x79, 0x15, 0x00, 0x40, 0x79, 0x80, 0x1B, 0x04, 0x44, 0x64, 0xB2, 0x05, 0x2C, 0xD4, 0xBF, ++0x1B, 0x19, 0x05, 0x33, 0x01, 0x35, 0x1A, 0xE7, 0x60, 0x79, 0xA0, 0xEB, 0x0E, 0x00, 0x28, 0x44, 0x40, 0xB2, 0x05, 0x28, ++0xA8, 0xBF, 0x05, 0x20, 0x01, 0x37, 0x9F, 0xE6, 0xA5, 0xF1, 0x11, 0x00, 0x40, 0xB2, 0x03, 0x28, 0x07, 0xF1, 0x02, 0x07, ++0xA8, 0xBF, 0x03, 0x20, 0x96, 0xE6, 0x00, 0xBF, 0xF0, 0xB4, 0xB9, 0x4B, 0x93, 0xF8, 0x2A, 0x20, 0xDC, 0x8C, 0x52, 0xBB, ++0xC0, 0xB9, 0x03, 0x29, 0x00, 0xF2, 0x91, 0x80, 0xB5, 0x4A, 0xB6, 0x4B, 0x92, 0xF8, 0xBE, 0x50, 0x5B, 0x5D, 0x02, 0x46, ++0x01, 0x46, 0x07, 0x46, 0x40, 0xF6, 0x7B, 0x10, 0x84, 0x42, 0x00, 0xF2, 0xBA, 0x80, 0xB1, 0x48, 0x90, 0xF9, 0x00, 0x60, ++0x00, 0x29, 0x00, 0xF0, 0xC0, 0x80, 0xD8, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x04, 0x28, 0x40, 0xF2, 0x8F, 0x80, 0x09, 0x29, ++0x40, 0xF2, 0x8E, 0x80, 0xA7, 0x4B, 0x93, 0xF8, 0xC2, 0x50, 0x08, 0x2D, 0x40, 0xF3, 0x17, 0x81, 0x01, 0x21, 0x0F, 0x46, ++0x09, 0x25, 0xD4, 0x23, 0xE0, 0xE7, 0x04, 0x28, 0x44, 0xD9, 0x09, 0x29, 0x44, 0xD9, 0xA0, 0x4B, 0xA2, 0x49, 0x93, 0xF8, ++0xC6, 0x30, 0x09, 0x2B, 0xA8, 0xBF, 0x09, 0x23, 0x41, 0xF2, 0xC8, 0x42, 0x94, 0x42, 0xC8, 0x5C, 0x4F, 0xF0, 0x00, 0x05, ++0x53, 0xD9, 0xB4, 0xF5, 0xAF, 0x5F, 0x00, 0xF2, 0xCC, 0x80, 0x9B, 0x4A, 0x92, 0xF9, 0x01, 0x20, 0x00, 0x2D, 0xD1, 0xD1, ++0x0A, 0x2B, 0x4F, 0xEA, 0x20, 0x14, 0x00, 0xF0, 0x0F, 0x00, 0x1E, 0xDC, 0x02, 0xF1, 0x0F, 0x01, 0x1E, 0x29, 0xA8, 0xBF, ++0x1E, 0x21, 0x0A, 0x2B, 0x21, 0xEA, 0xE1, 0x71, 0x00, 0xF0, 0x3C, 0x81, 0x91, 0x4A, 0x03, 0xEB, 0x43, 0x03, 0x12, 0xF9, ++0x13, 0x50, 0x8D, 0x42, 0x02, 0xEB, 0x43, 0x02, 0x80, 0xF2, 0xF6, 0x80, 0x92, 0xF9, 0x04, 0x50, 0x8D, 0x42, 0x40, 0xF3, ++0x40, 0x81, 0xD3, 0x78, 0x92, 0x78, 0x9B, 0x1A, 0x19, 0x44, 0x40, 0xFA, 0x81, 0xF0, 0x80, 0xF3, 0x04, 0x00, 0x40, 0xEA, ++0x04, 0x10, 0xC0, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x01, 0x28, 0x0C, 0xD9, 0x07, 0x29, 0x2C, 0xD8, 0x04, 0x29, 0x0A, 0xD8, ++0x7B, 0x4B, 0x93, 0xF8, 0xC3, 0x30, 0xA3, 0xF1, 0x0B, 0x05, 0xB5, 0xFA, 0x85, 0xF5, 0x6D, 0x09, 0x09, 0xE0, 0x09, 0x29, ++0xF4, 0xD9, 0x76, 0x4B, 0x93, 0xF8, 0xC4, 0x30, 0x0A, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0xA8, 0xBF, 0x0A, 0x23, 0x75, 0x49, ++0x41, 0xF2, 0xC8, 0x42, 0x94, 0x42, 0xC8, 0x5C, 0xAB, 0xD8, 0x73, 0x4A, 0x92, 0xF9, 0x00, 0x20, 0xAE, 0xE7, 0x09, 0x29, ++0x26, 0xD8, 0x6C, 0x4B, 0x93, 0xF8, 0xBF, 0x50, 0x0B, 0x2D, 0x00, 0xF0, 0xF0, 0x80, 0x6F, 0x4B, 0x00, 0x22, 0x5B, 0x5D, ++0x11, 0x46, 0x01, 0x27, 0x68, 0xE7, 0x66, 0x4B, 0x93, 0xF8, 0xC5, 0x30, 0x09, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0xA8, 0xBF, ++0x09, 0x23, 0xDE, 0xE7, 0x01, 0x28, 0xE6, 0xD0, 0x07, 0x29, 0x0B, 0xD9, 0x5F, 0x4A, 0x65, 0x4B, 0x92, 0xF8, 0xC1, 0x50, ++0x0A, 0x2D, 0xA8, 0xBF, 0x0A, 0x25, 0x00, 0x22, 0x5B, 0x5D, 0x11, 0x46, 0x01, 0x27, 0x4F, 0xE7, 0x04, 0x29, 0xD8, 0xD9, ++0x58, 0x4A, 0x5E, 0x4B, 0x92, 0xF8, 0xC0, 0x50, 0xA5, 0xF1, 0x0B, 0x01, 0xB1, 0xFA, 0x81, 0xF1, 0x5B, 0x5D, 0x00, 0x22, ++0x49, 0x09, 0x01, 0x27, 0x40, 0xE7, 0x40, 0xF6, 0x94, 0x10, 0x84, 0x42, 0x52, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x01, 0x60, ++0x90, 0xF9, 0x02, 0x60, 0x00, 0x29, 0x7F, 0xF4, 0x40, 0xAF, 0x06, 0xF1, 0x0F, 0x01, 0x1E, 0x29, 0xA8, 0xBF, 0x1E, 0x21, ++0x0B, 0x2D, 0x21, 0xEA, 0xE1, 0x74, 0x4F, 0xEA, 0x23, 0x10, 0x29, 0x46, 0x03, 0xF0, 0x0F, 0x03, 0xA8, 0xBF, 0x0B, 0x21, ++0x00, 0x2F, 0x3B, 0xD1, 0x0A, 0x2D, 0x2C, 0xDC, 0x48, 0xD0, 0x49, 0x4D, 0x01, 0xEB, 0x41, 0x01, 0x15, 0xF9, 0x11, 0x60, ++0xB4, 0x42, 0x05, 0xEB, 0x41, 0x01, 0x34, 0xDC, 0x49, 0x78, 0x89, 0x1B, 0x21, 0x44, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, ++0x01, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x00, 0x13, 0xD8, 0xB2, ++0x00, 0x2A, 0x3F, 0xF4, 0x11, 0xAF, 0x82, 0x42, 0xBF, 0xF6, 0x0E, 0xAF, 0xD0, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x41, 0xF2, ++0x44, 0x62, 0x94, 0x42, 0x33, 0x4A, 0x94, 0xBF, 0x92, 0xF9, 0x02, 0x20, 0x92, 0xF9, 0x03, 0x20, 0x2C, 0xE7, 0x01, 0x36, ++0x2A, 0xDA, 0xA4, 0xF1, 0x0D, 0x01, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0x02, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, ++0x1B, 0x19, 0xDA, 0xE7, 0x0A, 0x2D, 0xD8, 0xDC, 0x58, 0xD0, 0x01, 0x31, 0xC1, 0xE7, 0x91, 0xF9, 0x04, 0x50, 0xAC, 0x42, ++0x1E, 0xDA, 0xCD, 0x78, 0x89, 0x78, 0x69, 0x1A, 0x21, 0x44, 0x43, 0xFA, 0x81, 0xF3, 0xCA, 0xE7, 0xB1, 0x1C, 0x2B, 0xDB, ++0x01, 0x2E, 0x76, 0xDC, 0xA4, 0xF1, 0x0F, 0x01, 0x43, 0xFA, 0x81, 0xF3, 0xC1, 0xE7, 0x1F, 0x4B, 0x08, 0xBF, 0xD4, 0x22, ++0x5B, 0x5D, 0x00, 0x21, 0x01, 0x27, 0xC7, 0xE6, 0xA4, 0xF1, 0x0F, 0x01, 0x49, 0xB2, 0x03, 0x29, 0xD4, 0xBF, 0x5B, 0x18, ++0x03, 0x33, 0xB2, 0xE7, 0x49, 0x79, 0x49, 0x1B, 0x21, 0x44, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x05, 0x33, ++0x01, 0x30, 0xA8, 0xE7, 0x53, 0x78, 0x5B, 0x1B, 0x19, 0x44, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x03, 0x01, 0x3C, 0x99, 0x42, ++0xAC, 0xBF, 0x40, 0x18, 0xC0, 0x18, 0x08, 0xE7, 0xA4, 0xF1, 0x0A, 0x01, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0x01, 0x38, ++0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x91, 0xE7, 0x00, 0xBF, 0xBC, 0x34, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xEC, 0x12, 0x17, 0x00, 0x68, 0x25, 0x17, 0x00, 0x04, 0x13, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x0C, 0x79, 0x15, 0x00, ++0xF8, 0x12, 0x17, 0x00, 0xB8, 0x78, 0x15, 0x00, 0x03, 0x36, 0x35, 0xDA, 0xA4, 0xF1, 0x09, 0x01, 0x49, 0xB2, 0x6F, 0xF0, ++0x04, 0x04, 0x01, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x71, 0xE7, 0x01, 0x21, 0x0F, 0x46, 0x00, 0x22, ++0x0F, 0x23, 0x79, 0xE6, 0x03, 0x32, 0x09, 0xDA, 0x09, 0x39, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x03, 0x01, 0x3C, 0x99, 0x42, ++0xAC, 0xBF, 0x40, 0x18, 0xC0, 0x18, 0xCC, 0xE6, 0x0F, 0x39, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x40, 0x18, 0x05, 0x30, ++0xC5, 0xE6, 0x53, 0x79, 0x5B, 0x1B, 0x19, 0x44, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x40, 0x18, 0x05, 0x30, 0x01, 0x34, ++0xBB, 0xE6, 0xA4, 0xF1, 0x11, 0x01, 0x49, 0xB2, 0x03, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x03, 0x33, 0x02, 0x30, 0x46, 0xE7, ++0xA4, 0xF1, 0x0F, 0x01, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x05, 0x33, 0x3E, 0xE7, 0x14, 0x22, 0xF6, 0x23, ++0x02, 0x70, 0x0B, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x08, 0xB5, 0x09, 0x49, 0x09, 0x48, 0x22, 0xF0, 0xF3, 0xFD, 0x09, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x08, 0xBD, 0xBD, 0xE8, 0x08, 0x40, 0x05, 0x49, 0x06, 0x48, ++0x39, 0x22, 0x23, 0xF0, 0x5F, 0xB8, 0x00, 0xBF, 0x50, 0x79, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x1F, 0x49, 0x20, 0x4A, 0x88, 0x68, 0x20, 0x4B, 0x10, 0xB4, 0xD2, 0xF8, ++0x14, 0x44, 0x04, 0x65, 0x10, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0xA0, 0x42, 0x44, 0x65, 0x20, 0x20, 0x18, 0x60, ++0x88, 0x68, 0xD2, 0xF8, 0xA0, 0x42, 0xC4, 0x65, 0x80, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0xD8, 0x40, 0x84, 0x64, ++0x04, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0x0C, 0x44, 0xC4, 0x64, 0xF8, 0x24, 0x08, 0x20, 0x83, 0xF8, 0x03, 0x43, ++0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0x1C, 0x41, 0xC0, 0xF8, 0x0C, 0x41, 0x4F, 0xF4, 0x00, 0x20, 0x58, 0x60, 0x89, 0x68, ++0xD2, 0xF8, 0x2C, 0x21, 0xC1, 0xF8, 0x10, 0x21, 0x4F, 0xF4, 0x80, 0x10, 0x4F, 0xF4, 0x00, 0x41, 0x4F, 0xF4, 0x00, 0x12, ++0x58, 0x60, 0x99, 0x60, 0x1A, 0x60, 0x62, 0xB6, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xED, 0x00, 0xE0, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, 0x33, 0x49, 0x34, 0x4B, 0x0A, 0x68, 0x00, 0x28, 0x22, 0xF4, 0x00, 0x62, ++0xF0, 0xB5, 0x32, 0x4D, 0x0A, 0x60, 0x06, 0xBF, 0x1D, 0x46, 0x30, 0x26, 0x20, 0x26, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x2A, 0x4F, 0x2C, 0x4C, 0x3A, 0x68, 0x22, 0xF4, 0x80, 0x52, 0x3A, 0x60, 0x3A, 0x68, ++0x42, 0xF4, 0x80, 0x62, 0x3A, 0x60, 0x3A, 0x68, 0x42, 0xF4, 0x00, 0x62, 0x3A, 0x60, 0xB6, 0x00, 0x19, 0x46, 0x3A, 0x46, ++0x4F, 0xF0, 0xFF, 0x0E, 0xC8, 0x1C, 0xC0, 0xB2, 0xAC, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x43, 0x13, 0x60, ++0x5C, 0xF8, 0x04, 0x3B, 0x23, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, ++0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, 0xFC, 0xD5, 0x01, 0x38, 0xC0, 0xB2, 0x70, 0x45, 0xE8, 0xD1, 0x04, 0x31, 0x04, 0x30, ++0xB1, 0x42, 0x5F, 0xFA, 0x80, 0xFE, 0x05, 0xF1, 0x10, 0x05, 0xDD, 0xD1, 0x3B, 0x68, 0x23, 0xF4, 0x80, 0x63, 0x3B, 0x60, ++0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, ++0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, ++0x80, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0xF0, 0xBD, 0x00, 0xBF, 0x60, 0x40, 0x34, 0x40, ++0x1C, 0x13, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, 0x64, 0x40, 0x34, 0x40, 0x44, 0x4A, 0x45, 0x49, 0x13, 0x68, 0xF0, 0xB4, ++0x44, 0x4D, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x00, 0x28, 0x0C, 0xBF, 0x28, 0x46, 0x08, 0x46, 0x32, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x3B, 0x4A, 0x3E, 0x4D, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x53, 0x13, 0x60, ++0x13, 0x68, 0x43, 0xF4, 0x80, 0x63, 0x13, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x03, 0x21, 0xA0, 0xF1, ++0x0C, 0x04, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x54, 0xF8, 0x21, 0x30, 0x2B, 0x60, 0x13, 0x68, ++0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9E, 0x04, 0xFC, 0xD5, ++0x04, 0x31, 0x43, 0x29, 0xE9, 0xD1, 0x28, 0x4B, 0x2B, 0x4E, 0x2A, 0x4D, 0x04, 0x1F, 0x02, 0x21, 0x1A, 0x68, 0x22, 0xF0, ++0xFF, 0x02, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, ++0x00, 0xBF, 0x1A, 0x68, 0x90, 0x04, 0xFC, 0xD5, 0x37, 0x68, 0x54, 0xF8, 0x21, 0x20, 0x18, 0x68, 0x27, 0xF0, 0x7F, 0x47, ++0x02, 0xF0, 0x7F, 0x42, 0x20, 0xF0, 0xFF, 0x00, 0x3A, 0x43, 0x08, 0x43, 0x18, 0x60, 0x2A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x80, 0x72, 0x1A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x1A, 0x68, 0x92, 0x04, 0xFC, 0xD5, 0x04, 0x31, ++0x42, 0x29, 0xD3, 0xD1, 0x1A, 0x68, 0x22, 0xF4, 0x80, 0x62, 0x1A, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, ++0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x00, 0x62, 0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x60, 0x40, 0x34, 0x40, 0x1C, 0x16, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, ++0x64, 0x40, 0x34, 0x40, 0x68, 0x40, 0x34, 0x40, 0x2C, 0x49, 0x2D, 0x4B, 0x0A, 0x68, 0x30, 0xB4, 0x2C, 0x4C, 0x00, 0x28, ++0x22, 0xF4, 0x80, 0x72, 0x0C, 0xBF, 0x18, 0x46, 0x20, 0x46, 0x0A, 0x60, 0x0C, 0xBF, 0x20, 0x24, 0x10, 0x24, 0x32, 0x23, ++0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x22, 0x49, 0x24, 0x4D, 0x0A, 0x68, 0x22, 0xF4, 0x00, 0x72, ++0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x72, 0x04, 0x38, 0x0A, 0x60, ++0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x50, 0xF8, 0x04, 0x2F, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF0, ++0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, 0xFC, 0xD5, 0x01, 0x33, ++0x9C, 0x42, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, ++0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x80, 0x72, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x6C, 0x40, 0x34, 0x40, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, ++0x70, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0xA6, 0x49, 0xA7, 0x4C, 0xA7, 0x4B, 0xA8, 0x4A, 0xDF, 0xF8, 0xE8, 0xE2, ++0x00, 0x28, 0x0E, 0xBF, 0xA4, 0x46, 0x8C, 0x46, 0x9E, 0x46, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0xA3, 0x4C, 0xA4, 0x49, ++0x23, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x23, 0x60, 0x01, 0x23, 0x13, 0x60, 0x0B, 0x68, 0xA1, 0x4A, 0x23, 0xF4, 0x00, 0x63, ++0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x24, 0x00, 0xBF, 0x01, 0x3C, 0x14, 0xF0, 0xFF, 0x04, ++0xFA, 0xD1, 0xDF, 0xF8, 0x64, 0x82, 0x99, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x98, 0x4F, 0x23, 0xF4, 0x80, 0x53, 0xC8, 0xF8, ++0x00, 0x30, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x80, 0x63, 0xC8, 0xF8, ++0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x00, 0x63, 0xC8, 0xF8, 0x00, 0x30, 0x42, 0x46, 0xFF, 0x26, 0xE1, 0x1C, ++0xC9, 0xB2, 0x75, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x55, 0xF8, 0x04, 0x3B, 0x3B, 0x60, ++0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, ++0xFC, 0xD5, 0x01, 0x39, 0xC9, 0xB2, 0x8E, 0x42, 0xE8, 0xD1, 0x04, 0x34, 0x04, 0x36, 0x80, 0x2C, 0xF6, 0xB2, 0x0E, 0xF1, ++0x10, 0x0E, 0xDE, 0xD1, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x80, 0x63, 0xC8, 0xF8, 0x00, 0x30, 0xC8, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x74, 0x4C, 0x75, 0x49, 0x22, 0x68, 0x22, 0xF4, 0x00, 0x62, 0x22, 0x60, ++0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x72, 0x10, 0x34, 0xAC, 0xF1, 0x04, 0x0C, ++0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x5C, 0xF8, 0x04, 0x2F, 0x22, 0x60, 0x0A, 0x68, ++0x42, 0xF0, 0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, 0xFC, 0xD5, ++0x01, 0x33, 0x10, 0x2B, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x5D, 0x49, 0x5E, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x13, 0x68, ++0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x54, 0x49, ++0x54, 0x4B, 0x0C, 0x68, 0x56, 0x4A, 0x57, 0x4D, 0x44, 0xF4, 0x80, 0x54, 0x0C, 0x60, 0x1C, 0x68, 0x44, 0xF4, 0x00, 0x74, ++0x1C, 0x60, 0x0C, 0x68, 0x44, 0xF4, 0x00, 0x64, 0x0C, 0x60, 0x19, 0x68, 0x51, 0x4C, 0x41, 0xF4, 0x80, 0x71, 0x19, 0x60, ++0x11, 0x68, 0x50, 0x4B, 0x41, 0xF4, 0x80, 0x51, 0x11, 0x60, 0x29, 0x68, 0x21, 0xF4, 0x80, 0x21, 0x29, 0x60, 0x21, 0x68, ++0x21, 0xF0, 0x00, 0x51, 0x21, 0x60, 0xA5, 0xF5, 0xBC, 0x45, 0x1C, 0x68, 0x2C, 0x60, 0x49, 0x49, 0x5D, 0x68, 0x0D, 0x60, ++0x48, 0x4C, 0x9D, 0x68, 0x25, 0x60, 0xDD, 0x68, 0x8D, 0x60, 0x1D, 0x69, 0xA5, 0x60, 0x5C, 0x69, 0x0C, 0x61, 0xD3, 0xE9, ++0x06, 0x64, 0x44, 0x4D, 0x44, 0x4B, 0x2E, 0x60, 0x8C, 0x61, 0x9B, 0x78, 0x18, 0x31, 0xCB, 0xB1, 0xA5, 0xF6, 0x78, 0x65, ++0x41, 0x4C, 0x2B, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x00, 0x73, 0x2B, 0x60, 0x23, 0x68, 0x01, 0xF5, 0xBB, 0x41, ++0x7C, 0x31, 0x43, 0xF0, 0x80, 0x63, 0x23, 0x60, 0x0B, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0x40, 0x63, 0x43, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x36, 0x4B, 0x93, 0xF8, 0xFA, 0x30, 0x38, 0xB9, 0x43, 0xBB, 0x35, 0x4A, ++0x13, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0xCB, 0xB1, 0x32, 0x49, 0x32, 0x4A, 0x0B, 0x68, ++0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xB5, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xB5, 0x03, ++0x13, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x32, 0x23, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x23, ++0x43, 0xF4, 0x32, 0x23, 0x13, 0x60, 0x24, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, ++0x21, 0x49, 0x22, 0x4A, 0x0B, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, ++0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x0B, 0x60, ++0x13, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x13, 0x60, 0xBB, 0xE7, 0x00, 0xBF, 0x9C, 0x18, 0x17, 0x00, ++0x1C, 0x18, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x60, 0x40, 0x34, 0x40, ++0x6C, 0x40, 0x34, 0x40, 0x64, 0x40, 0x34, 0x40, 0x58, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, ++0x1C, 0x20, 0x34, 0x40, 0xDC, 0x18, 0x17, 0x00, 0x1C, 0xC2, 0x33, 0x40, 0x20, 0xC2, 0x33, 0x40, 0x30, 0xC2, 0x33, 0x40, ++0x3C, 0x36, 0x17, 0x00, 0x38, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0xAC, 0xB3, 0x33, 0x40, ++0xD4, 0xB3, 0x33, 0x40, 0x1C, 0x13, 0x17, 0x00, 0x10, 0xB4, 0x1C, 0x4B, 0x1C, 0x4C, 0x0F, 0xCB, 0x85, 0xB0, 0x0D, 0xF1, ++0x10, 0x0C, 0x0C, 0xE9, 0x0F, 0x00, 0x63, 0x68, 0xDB, 0x06, 0x16, 0xD5, 0x61, 0x68, 0xA3, 0x69, 0x5C, 0xFA, 0x83, 0xF3, ++0xC8, 0x04, 0x13, 0xF8, 0x10, 0x2C, 0x22, 0xD4, 0x60, 0x68, 0x14, 0x49, 0x14, 0x4B, 0x10, 0xF4, 0x80, 0x7F, 0x08, 0xBF, ++0x0B, 0x46, 0x11, 0x06, 0x44, 0xBF, 0x5B, 0x00, 0x02, 0xF0, 0x7F, 0x02, 0xB3, 0xFB, 0xF2, 0xF3, 0x00, 0xE0, 0x0F, 0x4B, ++0x0B, 0x4A, 0x0F, 0x4C, 0x52, 0x69, 0x0F, 0x48, 0x0F, 0x49, 0xD2, 0xB2, 0xB3, 0xFB, 0xF2, 0xF3, 0x23, 0x60, 0xD0, 0xF8, ++0x84, 0x20, 0xD2, 0xB2, 0xB3, 0xFB, 0xF2, 0xF3, 0x0B, 0x60, 0x05, 0xB0, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x09, 0x4B, ++0xE1, 0xE7, 0x00, 0xBF, 0x60, 0x79, 0x15, 0x00, 0x00, 0x00, 0x50, 0x40, 0x00, 0x38, 0x9C, 0x1C, 0x00, 0xD0, 0x12, 0x13, ++0x00, 0x75, 0x19, 0x03, 0x18, 0x13, 0x17, 0x00, 0x00, 0x00, 0x10, 0x40, 0x14, 0x13, 0x17, 0x00, 0x00, 0x70, 0x38, 0x39, ++0x70, 0xB4, 0x5D, 0x4C, 0x5D, 0x48, 0x23, 0x68, 0x5D, 0x4D, 0x5E, 0x49, 0x5E, 0x4A, 0x23, 0xF4, 0xC0, 0x63, 0x43, 0xF4, ++0x00, 0x73, 0x23, 0x60, 0x03, 0x68, 0x95, 0xF8, 0xFA, 0x40, 0x23, 0xF4, 0xBC, 0x03, 0x23, 0xF4, 0x70, 0x53, 0x43, 0xF4, ++0x60, 0x23, 0x43, 0xF4, 0x80, 0x63, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x60, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0xFE, 0x33, 0x43, 0xF4, 0x98, 0x33, 0x13, 0x60, 0x00, 0x2C, 0x00, 0xF0, 0x8F, 0x80, 0xA2, 0xF5, 0x11, 0x12, 0xA2, 0xF6, ++0x4C, 0x52, 0x13, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x13, 0x60, 0x4C, 0x4D, 0x4C, 0x48, 0x2B, 0x68, 0x4C, 0x4C, 0x4D, 0x4A, ++0x4D, 0x49, 0x4E, 0x4E, 0x43, 0xF0, 0x80, 0x63, 0x2B, 0x60, 0x03, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x03, 0x60, 0x23, 0x68, ++0x23, 0xF4, 0x7F, 0x73, 0x43, 0xF0, 0x04, 0x03, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x80, 0x53, 0x43, 0xF4, 0x00, 0x63, ++0x03, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xCC, 0x03, 0x43, 0xF0, 0xC4, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x03, 0xF0, 0x7F, 0x43, ++0xA5, 0xF5, 0xF8, 0x55, 0x43, 0xF4, 0x78, 0x13, 0x0C, 0x3D, 0x43, 0xF4, 0x78, 0x73, 0x0B, 0x60, 0x2B, 0x68, 0x1B, 0x0C, ++0xA4, 0xF5, 0x00, 0x54, 0x1B, 0x04, 0x34, 0x3C, 0x43, 0xF0, 0x84, 0x03, 0x2B, 0x60, 0x23, 0x68, 0x37, 0x4D, 0x23, 0xF4, ++0x40, 0x63, 0x43, 0xF4, 0x00, 0x63, 0x23, 0x60, 0xD0, 0xF8, 0x04, 0x31, 0x02, 0xF5, 0xF8, 0x52, 0x23, 0xF4, 0xE0, 0x23, ++0x18, 0x32, 0x43, 0xF4, 0x80, 0x33, 0xC0, 0xF8, 0x04, 0x31, 0x13, 0x68, 0x23, 0xF0, 0x76, 0x53, 0x23, 0xF0, 0x07, 0x03, ++0x01, 0xF5, 0xF7, 0x51, 0x43, 0xF0, 0x04, 0x53, 0x04, 0x31, 0x43, 0xF0, 0x07, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x04, 0xF5, ++0x00, 0x54, 0x02, 0xF1, 0xEF, 0x52, 0x00, 0xF5, 0x01, 0x50, 0x1C, 0x34, 0x02, 0xF5, 0x3D, 0x22, 0x02, 0xF6, 0x44, 0x02, ++0x1D, 0x40, 0x08, 0x30, 0x22, 0x4B, 0x0D, 0x60, 0x32, 0x60, 0x23, 0x60, 0x03, 0x68, 0x21, 0x4A, 0x21, 0x4C, 0x23, 0xF4, ++0x7F, 0x23, 0x23, 0xF4, 0x00, 0x63, 0x43, 0xF4, 0x32, 0x33, 0x03, 0x60, 0xCB, 0x68, 0x43, 0xF4, 0x00, 0x63, 0xCB, 0x60, ++0x13, 0x68, 0x23, 0xF0, 0x09, 0x03, 0x43, 0xF4, 0x80, 0x53, 0x13, 0x60, 0x23, 0x68, 0x1B, 0x07, 0x08, 0xD5, 0xA2, 0xF5, ++0x0F, 0x12, 0xA2, 0xF5, 0x03, 0x52, 0x24, 0x3A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x53, 0x13, 0x60, 0x70, 0xBC, 0x70, 0x47, ++0x12, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x00, 0x73, 0x13, 0x60, 0x70, 0xE7, 0x20, 0x40, 0x34, 0x40, ++0x24, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x28, 0x40, 0x34, 0x40, 0x04, 0x01, 0x58, 0x40, 0x38, 0x40, 0x34, 0x40, ++0x30, 0x20, 0x34, 0x40, 0x48, 0x40, 0x34, 0x40, 0x28, 0x21, 0x34, 0x40, 0x24, 0x21, 0x34, 0x40, 0x2C, 0x40, 0x34, 0x40, ++0x03, 0x00, 0x00, 0xFF, 0x08, 0x51, 0x2E, 0x1A, 0x08, 0x01, 0x58, 0x40, 0x94, 0x40, 0x04, 0x40, 0xB8, 0xB3, 0x33, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xDE, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xE6, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xE8, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x24, 0x1C, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xEA, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x2D, 0xE9, 0xF0, 0x47, 0x4C, 0x4B, 0x4D, 0x4D, 0x08, 0x22, 0xC3, 0xF8, 0x00, 0x21, 0xAB, 0x78, 0x33, 0xB9, 0x4B, 0x4A, ++0x93, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x43, 0xF4, 0x00, 0x33, 0x93, 0x60, 0x47, 0x4A, 0x13, 0x6B, 0x03, 0xF0, 0x22, 0x03, ++0x02, 0x2B, 0xFA, 0xD1, 0x93, 0x68, 0x45, 0x4C, 0x41, 0x49, 0x45, 0x48, 0x23, 0xF4, 0x00, 0x63, 0x43, 0xF0, 0x01, 0x13, ++0x43, 0xF4, 0x04, 0x43, 0x93, 0x60, 0x06, 0x23, 0x23, 0x60, 0x53, 0x6D, 0x40, 0x4C, 0x23, 0xF4, 0x40, 0x13, 0x53, 0x65, ++0x4F, 0xF4, 0x00, 0x63, 0xC1, 0xF8, 0x34, 0x31, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x03, ++0x01, 0x40, 0x0B, 0x43, 0x13, 0x60, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x08, 0xD1, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, ++0x09, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x08, 0x40, 0x18, 0x43, 0x10, 0x60, 0x2E, 0x49, 0x2C, 0x4E, 0x0B, 0x68, 0x0A, 0x68, ++0x30, 0x48, 0xC3, 0xF3, 0x09, 0x03, 0x22, 0xF4, 0x7F, 0x72, 0x22, 0xF0, 0x03, 0x02, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x43, ++0x0B, 0x60, 0x73, 0x6F, 0x2B, 0x4A, 0x43, 0xF0, 0x02, 0x03, 0x73, 0x67, 0x03, 0x68, 0x2A, 0x4E, 0x23, 0xF4, 0x00, 0x63, ++0x03, 0x60, 0x13, 0x68, 0x96, 0xF8, 0xA9, 0x00, 0x43, 0xF0, 0x80, 0x73, 0x13, 0x60, 0x68, 0xB1, 0x0B, 0x6B, 0x5F, 0x06, ++0x05, 0xD4, 0x0B, 0x6B, 0x58, 0x07, 0x02, 0xD5, 0x22, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x1A, 0x4B, 0x1A, 0x6B, 0x52, 0x06, ++0x40, 0xF1, 0x10, 0x82, 0x1F, 0x4B, 0xD6, 0xF8, 0xA0, 0x20, 0x1A, 0x60, 0xAB, 0x78, 0x00, 0x2B, 0x3E, 0xD0, 0x1D, 0x4B, ++0x1A, 0x68, 0x13, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x6C, 0x82, 0x11, 0x4B, 0x0E, 0x48, 0x02, 0x21, 0x11, 0x70, 0x1A, 0x6D, ++0xA9, 0x78, 0x42, 0xF4, 0x80, 0x22, 0x1A, 0x65, 0x02, 0x69, 0x22, 0xF0, 0x80, 0x02, 0x02, 0x61, 0x5A, 0x6A, 0x22, 0xF0, ++0xFF, 0x02, 0x42, 0xF0, 0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, 0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, ++0x00, 0x29, 0x33, 0xD0, 0x03, 0xF0, 0xB0, 0xFC, 0x0C, 0x4F, 0x33, 0xE0, 0x00, 0x00, 0x50, 0x40, 0x3C, 0x36, 0x17, 0x00, ++0x00, 0x60, 0x50, 0x40, 0x10, 0x00, 0x58, 0x40, 0x00, 0xFC, 0xFF, 0xFF, 0x78, 0x36, 0x17, 0x00, 0x00, 0x01, 0x58, 0x40, ++0x20, 0x01, 0x58, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, 0x74, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xC0, 0x4B, 0xC1, 0x49, 0x1A, 0x6D, 0x42, 0xF4, 0x80, 0x22, 0x1A, 0x65, 0x0A, 0x69, 0x22, 0xF0, ++0x80, 0x02, 0x0A, 0x61, 0x5A, 0x6A, 0x22, 0xF0, 0xFF, 0x02, 0x42, 0xF0, 0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, ++0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, 0xB7, 0x4F, 0xD7, 0xF8, 0xCC, 0x30, 0x98, 0x47, 0x03, 0xF0, 0xF4, 0xF9, ++0xD7, 0xF8, 0x9C, 0x34, 0x98, 0x47, 0xB2, 0x4B, 0xB3, 0x49, 0x1B, 0x68, 0xB3, 0x4A, 0xA8, 0x78, 0x1B, 0x0C, 0x0B, 0x70, ++0x04, 0x23, 0x1B, 0x68, 0x1B, 0x09, 0x13, 0x70, 0x10, 0xB9, 0xD7, 0xF8, 0x80, 0x34, 0x98, 0x47, 0xAE, 0x48, 0xAF, 0x4D, ++0xFF, 0xF7, 0x78, 0xFE, 0xAE, 0x48, 0xFF, 0xF7, 0x9D, 0xFE, 0x03, 0x46, 0x1A, 0x0C, 0xAD, 0x49, 0x2A, 0x70, 0x1B, 0x0F, ++0x02, 0x22, 0x0B, 0x70, 0xAB, 0x48, 0x11, 0x46, 0xFF, 0xF7, 0xE2, 0xFE, 0x4F, 0xF4, 0x80, 0x52, 0x11, 0x46, 0xA9, 0x48, ++0xFF, 0xF7, 0xDC, 0xFE, 0xA8, 0x4A, 0xA9, 0x49, 0xA9, 0x48, 0xFF, 0xF7, 0xD7, 0xFE, 0x2B, 0x78, 0x01, 0x2B, 0x00, 0xF0, ++0x8E, 0x81, 0xA7, 0x48, 0x4F, 0xF4, 0x7F, 0x52, 0x4F, 0xF4, 0x9E, 0x51, 0xFF, 0xF7, 0xCC, 0xFE, 0x04, 0x22, 0xA4, 0x48, ++0x11, 0x46, 0xFF, 0xF7, 0xC7, 0xFE, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x04, 0xD0, 0xA1, 0x48, 0x07, 0x22, 0x00, 0x21, ++0xFF, 0xF7, 0xBE, 0xFE, 0x01, 0x21, 0x02, 0x20, 0x03, 0xF0, 0x5C, 0xFE, 0x04, 0x22, 0x9D, 0x48, 0x00, 0x21, 0xFF, 0xF7, ++0xB5, 0xFE, 0x01, 0x21, 0x03, 0x20, 0x03, 0xF0, 0x53, 0xFE, 0x08, 0x22, 0x98, 0x48, 0x00, 0x21, 0xFF, 0xF7, 0xAC, 0xFE, ++0x00, 0x21, 0x05, 0x20, 0x03, 0xF0, 0x4A, 0xFE, 0x95, 0x48, 0x20, 0x22, 0x00, 0x21, 0xFF, 0xF7, 0xA3, 0xFE, 0x20, 0x22, ++0x11, 0x46, 0x93, 0x48, 0xFF, 0xF7, 0x9E, 0xFE, 0x20, 0x22, 0x11, 0x46, 0x91, 0x48, 0xFF, 0xF7, 0x99, 0xFE, 0x02, 0x22, ++0x90, 0x48, 0x11, 0x46, 0xFF, 0xF7, 0x94, 0xFE, 0x4F, 0xF4, 0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x00, 0xF0, ++0x60, 0x00, 0x20, 0x28, 0x00, 0xF0, 0x74, 0x81, 0x4F, 0xF4, 0xFC, 0x02, 0x11, 0x46, 0x89, 0x48, 0xFF, 0xF7, 0x84, 0xFE, ++0x88, 0x4A, 0x89, 0x48, 0x4F, 0xF0, 0x46, 0x41, 0xFF, 0xF7, 0x7E, 0xFE, 0x87, 0x48, 0x3F, 0x22, 0x1F, 0x21, 0xFF, 0xF7, ++0x79, 0xFE, 0x4F, 0xF4, 0x80, 0x22, 0x85, 0x48, 0x00, 0x21, 0xFF, 0xF7, 0x73, 0xFE, 0x84, 0x48, 0x4F, 0xF4, 0x8E, 0x71, ++0xFF, 0xF7, 0x46, 0xFE, 0x82, 0x48, 0x4F, 0xF4, 0xF8, 0x22, 0x4F, 0xF4, 0xD8, 0x21, 0xFF, 0xF7, 0x67, 0xFE, 0x40, 0x22, ++0x11, 0x46, 0x7F, 0x48, 0xFF, 0xF7, 0x62, 0xFE, 0x4F, 0xF4, 0xC0, 0x32, 0x11, 0x46, 0x7D, 0x48, 0xFF, 0xF7, 0x5C, 0xFE, ++0x7C, 0x48, 0x4F, 0xF4, 0xE0, 0x62, 0x4F, 0xF4, 0x00, 0x71, 0xFF, 0xF7, 0x55, 0xFE, 0x96, 0xF8, 0xC7, 0x70, 0xB7, 0xB3, ++0x78, 0x4A, 0x96, 0xF8, 0xC8, 0x10, 0x78, 0x4B, 0x96, 0xF8, 0xC9, 0x00, 0x11, 0x70, 0x96, 0xF8, 0xCA, 0x10, 0x50, 0x70, ++0x91, 0x70, 0x96, 0xF8, 0xCB, 0x50, 0x96, 0xF8, 0xCC, 0x00, 0x96, 0xF8, 0xCD, 0x10, 0x96, 0xF8, 0xCE, 0x20, 0x1D, 0x70, ++0x58, 0x70, 0x99, 0x70, 0xDA, 0x70, 0x4F, 0xF4, 0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x10, 0xF4, 0x60, 0x2F, ++0xC0, 0xF3, 0x42, 0x41, 0x0E, 0xD0, 0x6A, 0x4A, 0x8D, 0x01, 0x02, 0xF1, 0x40, 0x00, 0x52, 0xF8, 0x04, 0x3F, 0x23, 0xF4, ++0xE0, 0x73, 0x2B, 0x43, 0x90, 0x42, 0x13, 0x60, 0xF7, 0xD1, 0x65, 0x48, 0x03, 0xF0, 0x68, 0xFD, 0x23, 0x68, 0x1C, 0x78, ++0x01, 0x2C, 0x00, 0xF0, 0xEF, 0x80, 0xBD, 0xE8, 0xF0, 0x87, 0x4F, 0xF4, 0xD2, 0x76, 0x0A, 0x20, 0x33, 0x68, 0xDF, 0xF8, ++0x6C, 0xA1, 0x98, 0x47, 0x33, 0x68, 0x05, 0x46, 0x0B, 0x20, 0x98, 0x47, 0x33, 0x68, 0x80, 0x46, 0x0F, 0x20, 0x98, 0x47, ++0x5F, 0xEA, 0x95, 0x7C, 0x3A, 0x46, 0x0C, 0xBF, 0x4F, 0xF0, 0x08, 0x09, 0x4F, 0xF0, 0x10, 0x09, 0x4F, 0xEA, 0x15, 0x6E, ++0xD3, 0x00, 0x25, 0xFA, 0x03, 0xF3, 0xDF, 0xB2, 0xC3, 0xF3, 0x03, 0x13, 0xBC, 0xF1, 0x00, 0x0F, 0x38, 0xD1, 0x00, 0x2B, ++0x54, 0xD1, 0x00, 0x2F, 0x40, 0xF0, 0x1F, 0x81, 0x01, 0x32, 0x03, 0x2A, 0xEE, 0xD1, 0xDF, 0xF8, 0x24, 0xE1, 0x07, 0x0E, ++0x00, 0x21, 0xCB, 0x00, 0x28, 0xFA, 0x03, 0xF3, 0xDE, 0xB2, 0xC3, 0xF3, 0x03, 0x13, 0xBC, 0xF1, 0x00, 0x0F, 0x0B, 0xD1, ++0xEB, 0xB1, 0x08, 0x22, 0x93, 0x42, 0x28, 0xBF, 0xD3, 0x1A, 0x5B, 0xB2, 0x0E, 0xF8, 0x01, 0x30, 0x01, 0x31, 0x04, 0x29, ++0xEB, 0xD1, 0x9C, 0xE7, 0x4D, 0x00, 0x6A, 0x1C, 0x47, 0xFA, 0x02, 0xF2, 0x12, 0x01, 0x02, 0xF0, 0x10, 0x02, 0x13, 0x43, ++0x13, 0xF0, 0xFF, 0x03, 0x1F, 0xD1, 0x47, 0xFA, 0x05, 0xF3, 0x1B, 0x01, 0x03, 0xF0, 0x10, 0x03, 0x06, 0xF0, 0x0F, 0x06, ++0x1E, 0x43, 0x00, 0x2E, 0xE6, 0xD0, 0x33, 0x46, 0x4A, 0x46, 0xDD, 0xE7, 0x56, 0x00, 0x71, 0x1C, 0x4E, 0xFA, 0x01, 0xF1, ++0x09, 0x01, 0x01, 0xF0, 0x10, 0x01, 0x0B, 0x43, 0x13, 0xF0, 0xFF, 0x03, 0x09, 0xD0, 0x10, 0x21, 0x8B, 0x42, 0x28, 0xBF, ++0xCB, 0x1A, 0x5B, 0xB2, 0x0A, 0xF8, 0x02, 0x30, 0xB8, 0xE7, 0x10, 0x22, 0xC8, 0xE7, 0x4E, 0xFA, 0x06, 0xF3, 0x1B, 0x01, ++0x03, 0xF0, 0x10, 0x03, 0x07, 0xF0, 0x0F, 0x07, 0x1F, 0x43, 0xAA, 0xE7, 0x08, 0x21, 0xEB, 0xE7, 0x00, 0x60, 0x50, 0x40, ++0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x11, 0x13, 0x17, 0x00, 0x12, 0x13, 0x17, 0x00, 0x04, 0x02, 0x22, 0x03, ++0x10, 0x13, 0x17, 0x00, 0x00, 0x00, 0x01, 0x50, 0x70, 0x25, 0x17, 0x00, 0x50, 0x91, 0x01, 0x50, 0x20, 0x91, 0x01, 0x50, ++0xC0, 0xFD, 0x01, 0x00, 0xC0, 0xF1, 0x01, 0x00, 0x24, 0x91, 0x01, 0x50, 0x08, 0x88, 0x01, 0x50, 0x18, 0x88, 0x01, 0x50, ++0x2C, 0x91, 0x01, 0x50, 0x00, 0x10, 0x01, 0x50, 0x0C, 0x10, 0x01, 0x50, 0x10, 0x10, 0x01, 0x50, 0x18, 0x10, 0x01, 0x50, ++0x00, 0x30, 0x01, 0x50, 0x00, 0x88, 0x01, 0x50, 0x00, 0x00, 0xC0, 0xFF, 0x04, 0x88, 0x01, 0x50, 0x28, 0x91, 0x01, 0x50, ++0x5C, 0x00, 0x01, 0x50, 0x58, 0x00, 0x01, 0x50, 0x74, 0x91, 0x01, 0x50, 0x18, 0x91, 0x01, 0x50, 0x00, 0x91, 0x01, 0x50, ++0x30, 0x88, 0x01, 0x50, 0x68, 0x25, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x18, 0x18, 0x17, 0x00, 0x74, 0x79, 0x15, 0x00, ++0x1B, 0x6B, 0x59, 0x07, 0x7F, 0xF5, 0xEC, 0xAD, 0xD6, 0xF8, 0xA0, 0x30, 0x3F, 0x48, 0x40, 0x49, 0x40, 0x4A, 0x43, 0xF0, ++0x00, 0x73, 0x01, 0x27, 0x07, 0x70, 0x0B, 0x60, 0x53, 0x6F, 0x43, 0xF0, 0x10, 0x03, 0x53, 0x67, 0xE0, 0xE5, 0x3C, 0x4A, ++0x3C, 0x49, 0x3D, 0x48, 0xFF, 0xF7, 0x40, 0xFD, 0x3C, 0x48, 0x4F, 0xF4, 0x08, 0x42, 0x4F, 0xF4, 0x00, 0x41, 0xFF, 0xF7, ++0x39, 0xFD, 0x3A, 0x4A, 0x3A, 0x49, 0x3B, 0x48, 0xFF, 0xF7, 0x34, 0xFD, 0x3A, 0x48, 0x8F, 0x22, 0x06, 0x21, 0xFF, 0xF7, ++0x2F, 0xFD, 0x66, 0xE6, 0x38, 0x49, 0x39, 0x48, 0x4F, 0xF0, 0xFF, 0x32, 0xFF, 0xF7, 0x28, 0xFD, 0x4F, 0xF0, 0xFF, 0x32, ++0x36, 0x48, 0x4F, 0xF0, 0x02, 0x11, 0xFF, 0xF7, 0x21, 0xFD, 0x35, 0x49, 0x35, 0x48, 0xFF, 0xF7, 0xF5, 0xFC, 0x22, 0x46, ++0x21, 0x46, 0x34, 0x48, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x16, 0xBD, 0x32, 0x48, 0x0F, 0x22, 0x01, 0x21, 0xFF, 0xF7, ++0x11, 0xFD, 0x02, 0x22, 0x11, 0x46, 0x30, 0x48, 0xFF, 0xF7, 0x0C, 0xFD, 0x02, 0x22, 0x11, 0x46, 0x2E, 0x48, 0xFF, 0xF7, ++0x07, 0xFD, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x2A, 0x48, 0xFF, 0xF7, 0x01, 0xFD, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, ++0x28, 0x48, 0xFF, 0xF7, 0xFB, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x27, 0x48, 0xFF, 0xF7, 0xF6, 0xFC, 0x25, 0x48, 0x4F, 0xF4, ++0x00, 0x52, 0x00, 0x21, 0xFF, 0xF7, 0xF0, 0xFC, 0x64, 0xE6, 0x23, 0x4B, 0x0F, 0x49, 0x1A, 0x6D, 0x22, 0x4F, 0x42, 0xF4, ++0x80, 0x22, 0x1A, 0x65, 0x0A, 0x69, 0x22, 0xF0, 0x80, 0x02, 0x0A, 0x61, 0x5A, 0x6A, 0x22, 0xF0, 0xFF, 0x02, 0x42, 0xF0, ++0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, 0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, 0x03, 0xF0, 0x48, 0xFA, ++0xCC, 0xE5, 0x3B, 0x46, 0x49, 0x46, 0x1D, 0xE7, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, 0x00, 0x00, 0x50, 0x40, ++0xC0, 0x3F, 0x00, 0x40, 0x40, 0x12, 0x00, 0x40, 0x08, 0x88, 0x01, 0x50, 0x04, 0x91, 0x01, 0x50, 0xE0, 0x01, 0x00, 0x22, ++0xC0, 0x00, 0x00, 0x02, 0x08, 0x91, 0x01, 0x50, 0x00, 0x91, 0x01, 0x50, 0x00, 0x01, 0x00, 0x03, 0x0C, 0x80, 0x01, 0x50, ++0x18, 0x80, 0x01, 0x50, 0x0A, 0x33, 0x41, 0x01, 0x38, 0x91, 0x01, 0x50, 0x04, 0x00, 0x01, 0x50, 0x04, 0x20, 0x01, 0x50, ++0x04, 0x10, 0x01, 0x50, 0x08, 0x10, 0x01, 0x50, 0x00, 0x10, 0x01, 0x50, 0x00, 0x60, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x10, 0x4B, 0x11, 0x4A, 0x19, 0x68, 0x21, 0xF4, 0x78, 0x11, 0x41, 0xF4, 0x50, 0x11, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, ++0x78, 0x11, 0x41, 0xF4, 0xA0, 0x11, 0x19, 0x60, 0x11, 0x69, 0x18, 0x68, 0x20, 0xF4, 0x78, 0x10, 0x40, 0xF4, 0x50, 0x10, ++0x32, 0x31, 0x18, 0x60, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x78, 0x13, ++0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x70, 0x47, 0x58, 0x40, 0x34, 0x40, 0x00, 0x10, 0x50, 0x40, 0x1E, 0x49, 0x1F, 0x4A, ++0x0B, 0x68, 0x43, 0xF4, 0x00, 0x13, 0x10, 0xB4, 0x0B, 0x60, 0x13, 0x68, 0x59, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x59, 0x07, 0xF6, 0xD5, 0x15, 0x49, 0x15, 0x4A, 0x0B, 0x68, ++0x43, 0xF4, 0xC0, 0x23, 0x0B, 0x60, 0x13, 0x68, 0x9B, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, ++0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x9B, 0x07, 0xF6, 0xD5, 0x0E, 0x4C, 0x0E, 0x48, 0x23, 0x68, 0x0E, 0x4A, 0x0F, 0x49, ++0x43, 0xF4, 0x00, 0x33, 0x23, 0x60, 0x03, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x43, 0xF0, 0x80, 0x73, 0x03, 0x60, 0x13, 0x68, ++0x43, 0xF4, 0xA4, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0xA1, 0xBD, 0x00, 0xBF, ++0x58, 0x40, 0x34, 0x40, 0x80, 0x40, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x10, 0x00, 0x34, 0x40, 0x30, 0x20, 0x34, 0x40, ++0x9C, 0x79, 0x15, 0x00, 0x10, 0xB5, 0x10, 0x4C, 0x10, 0x48, 0x23, 0x68, 0x10, 0x49, 0x11, 0x4A, 0x23, 0xF4, 0x05, 0x43, ++0x23, 0xF0, 0xEC, 0x03, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x00, 0x33, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x73, ++0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xC0, 0x23, 0x0A, 0x20, 0x13, 0x60, 0xFD, 0xF7, 0xD6, 0xFC, 0xBD, 0xE8, 0x10, 0x40, ++0x06, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0x73, 0xBD, 0x00, 0xBF, 0x30, 0x20, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, ++0x10, 0x00, 0x34, 0x40, 0x58, 0x40, 0x34, 0x40, 0xB8, 0x79, 0x15, 0x00, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, ++0x00, 0x2B, 0xFA, 0xD1, 0x19, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, ++0xFA, 0xD1, 0x16, 0x4A, 0x13, 0x68, 0xDB, 0x07, 0x11, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, ++0xFA, 0xD1, 0x13, 0x68, 0xDB, 0x07, 0xF6, 0xD5, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, ++0x13, 0x68, 0xDB, 0x07, 0xED, 0xD5, 0x0B, 0x4B, 0x1A, 0x68, 0x53, 0x0C, 0x00, 0x2A, 0xBC, 0xBF, 0x6F, 0xEA, 0x43, 0x43, ++0x6F, 0xEA, 0x53, 0x43, 0x03, 0x60, 0xC2, 0xF3, 0x4E, 0x03, 0x12, 0x04, 0x44, 0xBF, 0x6F, 0xEA, 0x43, 0x43, 0x6F, 0xEA, ++0x53, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x84, 0x21, 0x34, 0x40, 0x00, 0x22, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x2A, 0x4F, 0x2B, 0x4D, 0x3B, 0x68, 0x2B, 0x4A, 0x23, 0xF4, 0x7F, 0x53, 0x3B, 0x60, 0x2B, 0x68, 0x43, 0xF4, 0x80, 0x63, ++0x2B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x01, 0x20, 0xFD, 0xF7, 0x72, 0xFC, 0x00, 0x24, 0x26, 0x46, ++0x4F, 0xF0, 0x07, 0x08, 0x02, 0x20, 0xFD, 0xF7, 0x6B, 0xFC, 0x2B, 0x68, 0xDA, 0x05, 0x54, 0xBF, 0x01, 0x36, 0x06, 0xF1, ++0xFF, 0x36, 0x76, 0xB2, 0x1B, 0x06, 0x3B, 0x68, 0x54, 0xBF, 0x01, 0x34, 0x04, 0xF1, 0xFF, 0x34, 0x00, 0x2E, 0x23, 0xF4, ++0x7F, 0x53, 0xDC, 0xBF, 0x70, 0x42, 0x43, 0xEA, 0x80, 0x23, 0x64, 0xB2, 0xD4, 0xBF, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xEA, ++0x86, 0x23, 0x00, 0x2C, 0xDC, 0xBF, 0x60, 0x42, 0x43, 0xEA, 0x80, 0x13, 0x08, 0xF1, 0xFF, 0x32, 0xCC, 0xBF, 0x43, 0xEA, ++0x84, 0x13, 0x43, 0xF4, 0x00, 0x73, 0x12, 0xF0, 0xFF, 0x08, 0x3B, 0x60, 0xD2, 0xD1, 0x0A, 0x48, 0x0A, 0x49, 0x02, 0x68, ++0x22, 0xF4, 0x80, 0x62, 0x02, 0x60, 0x0A, 0x68, 0xC3, 0xF3, 0x83, 0x10, 0x22, 0xF0, 0x40, 0x02, 0xC3, 0xF3, 0x83, 0x23, ++0x0A, 0x60, 0x43, 0xEA, 0x00, 0x10, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x50, 0x40, 0x34, 0x40, 0x14, 0x40, 0x34, 0x40, ++0x5C, 0x40, 0x34, 0x40, 0x01, 0x28, 0x15, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x4B, 0x78, 0x10, 0x2B, 0x19, 0xD8, 0x30, 0x23, ++0x8B, 0x70, 0x70, 0x47, 0xD2, 0xE9, 0x00, 0x32, 0x00, 0x2B, 0x24, 0xDD, 0x00, 0x2A, 0x37, 0xDB, 0xB3, 0xEB, 0x42, 0x0F, ++0x0B, 0x78, 0xCC, 0xBF, 0x10, 0x3B, 0x18, 0x3B, 0x4B, 0x70, 0x70, 0x47, 0x13, 0x68, 0xB3, 0xF5, 0x00, 0x5F, 0x10, 0xDA, ++0x00, 0x2B, 0x1A, 0xDD, 0x40, 0x23, 0x0B, 0x70, 0x70, 0x47, 0x30, 0x2B, 0x0C, 0xD9, 0x60, 0x2B, 0x1A, 0xD8, 0x92, 0x68, ++0x00, 0x2A, 0x28, 0xDB, 0x60, 0x2B, 0xDC, 0xD1, 0x20, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x20, 0x23, 0x0B, 0x70, 0x70, 0x47, ++0x18, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x00, 0x2A, 0x1E, 0xDD, 0x0B, 0x78, 0x20, 0x3B, 0x4B, 0x70, 0x70, 0x47, 0x13, 0xF5, ++0x00, 0x5F, 0xD4, 0xBF, 0xE0, 0x23, 0xC0, 0x23, 0x0B, 0x70, 0x70, 0x47, 0xC0, 0x2B, 0x09, 0xD8, 0x92, 0x68, 0x00, 0x2A, ++0x19, 0xDD, 0x60, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x0B, 0x78, 0x20, 0x33, 0x4B, 0x70, 0x70, 0x47, 0xD8, 0x2B, 0x0D, 0xD8, ++0xE8, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xA0, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xB3, 0xEB, 0x42, 0x0F, 0x0B, 0x78, 0xB4, 0xBF, ++0x10, 0x33, 0x18, 0x33, 0x4B, 0x70, 0x70, 0x47, 0xD0, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xA0, 0x2B, 0xFA, 0xD1, 0xE0, 0x23, ++0x8B, 0x70, 0x70, 0x47, 0x01, 0x28, 0x1D, 0xD0, 0x02, 0x28, 0x08, 0xD0, 0x09, 0x78, 0x01, 0x39, 0x05, 0x29, 0x69, 0xD8, ++0xDF, 0xE8, 0x01, 0xF0, 0x3C, 0x42, 0x39, 0x33, 0x2D, 0x2A, 0x10, 0xB4, 0x1C, 0x68, 0xB4, 0xF5, 0x00, 0x5F, 0x19, 0xDA, ++0x00, 0x2C, 0x4A, 0xDD, 0x5B, 0x68, 0x00, 0x2B, 0x13, 0x78, 0xAA, 0xBF, 0x03, 0x20, 0x10, 0x33, 0x10, 0x3B, 0x53, 0x70, ++0x08, 0x70, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x1B, 0x68, 0xB3, 0xF5, 0x00, 0x5F, 0x04, 0xDA, 0x00, 0x2B, 0x2B, 0xDD, ++0x50, 0x23, 0x13, 0x70, 0x70, 0x47, 0x30, 0x23, 0x13, 0x70, 0x70, 0x47, 0x13, 0x78, 0x01, 0x20, 0x10, 0x33, 0x53, 0x70, ++0x08, 0x70, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xC8, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0x21, 0xDD, ++0x70, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0x18, 0xDD, 0x90, 0x23, 0x93, 0x70, 0x70, 0x47, 0x38, 0x23, ++0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0xF0, 0xDD, 0x20, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, ++0xF0, 0xDD, 0x40, 0x23, 0x93, 0x70, 0x70, 0x47, 0x13, 0xF5, 0x00, 0x5F, 0xD4, 0xBF, 0xD0, 0x23, 0xB0, 0x23, 0x13, 0x70, ++0x70, 0x47, 0xE0, 0x23, 0x93, 0x70, 0x70, 0x47, 0xC0, 0x23, 0x93, 0x70, 0x70, 0x47, 0x14, 0xF5, 0x00, 0x5F, 0x05, 0xDC, ++0x13, 0x78, 0x04, 0x20, 0x10, 0x3B, 0x53, 0x70, 0x08, 0x70, 0xB4, 0xE7, 0x5B, 0x68, 0x00, 0x2B, 0x13, 0x78, 0xCC, 0xBF, ++0x05, 0x20, 0x06, 0x20, 0x10, 0x3B, 0x53, 0x70, 0x08, 0x70, 0xAA, 0xE7, 0x88, 0x23, 0x93, 0x70, 0x70, 0x47, 0x00, 0xBF, ++0x30, 0xB4, 0x0F, 0x29, 0x15, 0x46, 0x1C, 0x46, 0x02, 0x9A, 0x03, 0xD0, 0x30, 0xBC, 0x19, 0x46, 0xFF, 0xF7, 0x1C, 0xBF, ++0x13, 0x46, 0x29, 0x46, 0x22, 0x46, 0x30, 0xBC, 0xFF, 0xF7, 0x7A, 0xBF, 0x70, 0xB4, 0x50, 0xEA, 0x01, 0x04, 0x02, 0xD1, ++0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x08, 0x18, 0x18, 0xBF, 0x00, 0x21, 0x03, 0xD1, 0x20, 0xE0, 0xE9, 0xB2, 0x81, 0x42, ++0x1D, 0xDA, 0x53, 0xF8, 0x21, 0x40, 0x94, 0x42, 0x01, 0xF1, 0x01, 0x05, 0x03, 0xEB, 0x81, 0x06, 0xF4, 0xDC, 0xC0, 0xB2, ++0x88, 0x42, 0x0F, 0xD9, 0x44, 0x1E, 0x61, 0x1A, 0x1C, 0x1F, 0xC9, 0xB2, 0x04, 0xEB, 0x80, 0x04, 0xA4, 0xEB, 0x81, 0x04, ++0x03, 0xEB, 0x80, 0x03, 0x53, 0xF8, 0x04, 0x1C, 0x43, 0xF8, 0x04, 0x19, 0xA3, 0x42, 0xF9, 0xD1, 0x32, 0x60, 0x70, 0xBC, ++0x70, 0x47, 0x70, 0xBC, 0x43, 0xF8, 0x20, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0xF1, 0xFF, 0x3C, ++0x85, 0xB0, 0xCC, 0xF3, 0x47, 0x0C, 0x4F, 0xF0, 0x80, 0x34, 0x48, 0xF2, 0x80, 0x03, 0x01, 0x28, 0xCD, 0xE9, 0x01, 0xC4, ++0xAD, 0xF8, 0x0C, 0x30, 0x40, 0xF2, 0x83, 0x80, 0x80, 0x24, 0xA2, 0x46, 0x16, 0x46, 0x00, 0x25, 0x01, 0x23, 0x43, 0xF2, ++0xB0, 0x69, 0x8E, 0x46, 0x00, 0x92, 0x18, 0xE0, 0x80, 0x2C, 0x04, 0xBF, 0x04, 0xAA, 0x02, 0xEB, 0x45, 0x01, 0x4F, 0xEA, ++0x45, 0x07, 0x04, 0xAA, 0x17, 0x44, 0x04, 0xBF, 0x03, 0xF1, 0xFF, 0x34, 0x01, 0xF8, 0x08, 0x4C, 0x07, 0xF8, 0x07, 0x3C, ++0x01, 0x33, 0xDB, 0xB2, 0x98, 0x42, 0x22, 0xD0, 0x04, 0xAA, 0x02, 0xEB, 0x45, 0x01, 0x11, 0xF8, 0x08, 0x4C, 0x37, 0x68, ++0x56, 0xF8, 0x04, 0x1F, 0x7F, 0x1A, 0x77, 0x45, 0xE0, 0xDD, 0x80, 0x2C, 0xEE, 0xD0, 0x00, 0x9A, 0x52, 0xF8, 0x24, 0x10, ++0x49, 0x45, 0x4F, 0xEA, 0x45, 0x07, 0x04, 0xAA, 0x55, 0xDD, 0x02, 0xEB, 0x45, 0x01, 0x11, 0xF8, 0x07, 0x8C, 0x61, 0x46, ++0x0C, 0x44, 0xA0, 0x45, 0x61, 0xDB, 0x01, 0x33, 0xDB, 0xB2, 0x01, 0x35, 0x98, 0x42, 0xED, 0xB2, 0xDC, 0xD1, 0x02, 0x2D, ++0x00, 0x9A, 0x68, 0xD9, 0x9D, 0xF8, 0x08, 0x10, 0x80, 0x29, 0x3A, 0xD0, 0x9D, 0xF8, 0x09, 0x30, 0x52, 0xF8, 0x21, 0x40, ++0x52, 0xF8, 0x23, 0x50, 0x58, 0x1C, 0x40, 0x1A, 0x64, 0x1B, 0xC0, 0xB2, 0x02, 0xAD, 0x94, 0xFB, 0xF0, 0xF4, 0x01, 0x27, ++0xA4, 0xB2, 0x00, 0x26, 0x95, 0xF8, 0x02, 0xE0, 0xBE, 0xF1, 0x80, 0x0F, 0x5F, 0xFA, 0x87, 0xFC, 0x16, 0xD0, 0x95, 0xF8, ++0x03, 0x80, 0x52, 0xF8, 0x2E, 0x30, 0x08, 0xF1, 0x01, 0x01, 0xA1, 0xEB, 0x0E, 0x01, 0xC9, 0xB2, 0x52, 0xF8, 0x28, 0xE0, ++0x81, 0x42, 0xA3, 0xEB, 0x0E, 0x03, 0x93, 0xFB, 0xF1, 0xF3, 0x9B, 0xB2, 0x32, 0xD8, 0x61, 0xD0, 0x02, 0x2F, 0x05, 0xF1, ++0x02, 0x05, 0x34, 0xD1, 0x04, 0xAB, 0x03, 0xEB, 0x46, 0x06, 0x16, 0xF8, 0x08, 0x1C, 0x16, 0xF8, 0x07, 0x3C, 0x5B, 0x1A, ++0x01, 0x33, 0x01, 0xEB, 0x63, 0x03, 0xDB, 0xB2, 0x01, 0x93, 0x01, 0x9B, 0x52, 0xF8, 0x23, 0x00, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x02, 0xEB, 0x45, 0x08, 0x00, 0x9A, 0x18, 0xF8, 0x07, 0x8C, 0x52, 0xF8, 0x28, 0xB0, 0x25, 0x4A, 0x93, 0x45, ++0xA3, 0xDB, 0xB1, 0xF5, 0x7A, 0x7F, 0x02, 0xDA, 0x23, 0x4A, 0x93, 0x45, 0x9D, 0xDA, 0x02, 0x21, 0x0C, 0x44, 0xA0, 0x45, ++0x9D, 0xDA, 0x04, 0xAA, 0x17, 0x44, 0x07, 0xF8, 0x08, 0xAC, 0x07, 0xF8, 0x07, 0xAC, 0x75, 0xE7, 0x02, 0x2F, 0x1C, 0x46, ++0x08, 0x46, 0x66, 0x46, 0x05, 0xF1, 0x02, 0x05, 0xCA, 0xD0, 0x02, 0x27, 0xAA, 0xE7, 0x04, 0xAB, 0x03, 0xEB, 0x45, 0x01, ++0x6D, 0x00, 0x11, 0xF8, 0x08, 0x3C, 0x80, 0x2B, 0x8E, 0xD0, 0x52, 0xF8, 0x23, 0x00, 0x11, 0xF8, 0x07, 0x1C, 0x43, 0xF2, ++0xB0, 0x64, 0xA0, 0x42, 0x0A, 0xDC, 0x0F, 0x4E, 0x52, 0xF8, 0x21, 0x40, 0xB4, 0x42, 0x05, 0xDB, 0xB0, 0xF5, 0x7A, 0x7F, ++0x13, 0xDA, 0x14, 0xF5, 0x7A, 0x7F, 0x10, 0xDD, 0x9C, 0x44, 0x61, 0x45, 0xBF, 0xF6, 0x78, 0xAF, 0x04, 0xAB, 0x1D, 0x44, ++0x80, 0x23, 0x05, 0xF8, 0x08, 0x3C, 0x05, 0xF8, 0x07, 0x3C, 0x6F, 0xE7, 0xA3, 0x42, 0x9B, 0xD2, 0x1C, 0x46, 0x66, 0x46, ++0x98, 0xE7, 0x4F, 0xF0, 0x02, 0x0C, 0xEB, 0xE7, 0x50, 0xC9, 0xFF, 0xFF, 0x19, 0xFC, 0xFF, 0xFF, 0xD0, 0xED, 0x00, 0x7A, ++0x90, 0xED, 0x01, 0x7A, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, ++0x01, 0x6A, 0xB4, 0xEE, 0xE6, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x5E, 0xDA, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x08, 0xDD, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, 0x01, 0x6A, 0xB4, 0xEE, 0xE6, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x50, 0xD9, ++0xD0, 0xED, 0x02, 0x6A, 0xF4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0xD1, 0xED, 0x00, 0x5A, 0x91, 0xED, ++0x02, 0x6A, 0xF4, 0xEE, 0xC6, 0x5A, 0xF1, 0xEE, 0x10, 0xFA, 0x40, 0xDA, 0xF4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x32, 0xDC, 0xB4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0x91, 0xED, 0x01, 0x6A, 0xD1, 0xED, 0x02, 0x7A, ++0xB4, 0xEE, 0xE7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x2D, 0xDA, 0xB4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xDD, ++0x91, 0xED, 0x01, 0x7A, 0xD1, 0xED, 0x02, 0x7A, 0xB4, 0xEE, 0xE7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x1F, 0xD9, 0xD1, 0xED, ++0x00, 0x7A, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x1A, 0xDD, 0x91, 0xED, 0x01, 0x7A, 0xB5, 0xEE, 0xC0, 0x7A, ++0xF1, 0xEE, 0x10, 0xFA, 0x13, 0xDD, 0x91, 0xED, 0x02, 0x7A, 0xB5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x0C, 0xDD, ++0x01, 0x20, 0x70, 0x47, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, 0x02, 0x7A, 0xB4, 0xEE, 0xE7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, ++0xC3, 0xD8, 0x02, 0x20, 0x70, 0x47, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x01, 0xD4, 0x00, 0x20, 0x70, 0x47, ++0xD1, 0xED, 0x01, 0x7A, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0xF6, 0xD5, 0xD1, 0xED, 0x02, 0x7A, 0xF5, 0xEE, ++0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x4C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x28, 0x00, 0xF0, ++0xC7, 0x80, 0x2D, 0xE9, 0xF0, 0x47, 0x00, 0x22, 0xA1, 0xF1, 0x02, 0x08, 0x82, 0xB0, 0x44, 0x46, 0x17, 0x46, 0x94, 0x46, ++0x10, 0x46, 0x4F, 0xF0, 0x01, 0x0E, 0x02, 0xE0, 0x05, 0x2E, 0x11, 0xD0, 0x01, 0x32, 0x34, 0xF9, 0x02, 0x5F, 0x0E, 0xFA, ++0x02, 0xF3, 0x00, 0x2D, 0xD6, 0xB2, 0x43, 0xEA, 0x00, 0x03, 0xF3, 0xDA, 0x01, 0x2A, 0xD8, 0xB2, 0x40, 0xF2, 0x83, 0x80, ++0x01, 0x37, 0x05, 0x2E, 0xFF, 0xB2, 0xED, 0xD1, 0x04, 0x2F, 0x00, 0xF0, 0x81, 0x80, 0x02, 0x2F, 0x00, 0xF2, 0x81, 0x80, ++0xBC, 0xF1, 0x00, 0x0F, 0x0B, 0xD1, 0xB1, 0xF9, 0x02, 0x30, 0xB1, 0xF9, 0x00, 0x20, 0x03, 0xF1, 0x09, 0x04, 0x94, 0x42, ++0x02, 0xDB, 0x09, 0x3B, 0x9A, 0x42, 0x00, 0xDA, 0x4A, 0x80, 0xB1, 0xF9, 0x04, 0x20, 0xB1, 0xF9, 0x06, 0x30, 0x03, 0x24, ++0x40, 0xF2, 0x04, 0x55, 0x9A, 0x42, 0x8D, 0xF8, 0x01, 0x40, 0xAD, 0xF8, 0x02, 0x50, 0xC0, 0xF2, 0x8E, 0x80, 0xB1, 0xF9, ++0x08, 0x20, 0xB1, 0xF9, 0x0A, 0x30, 0x9A, 0x42, 0x25, 0x46, 0x4F, 0xF0, 0x06, 0x09, 0x4F, 0xF0, 0x04, 0x07, 0x4F, 0xF0, ++0x02, 0x04, 0x80, 0xF2, 0x8E, 0x80, 0x40, 0xF2, 0x05, 0x43, 0xAD, 0xF8, 0x02, 0x30, 0x4F, 0xF0, 0x05, 0x0E, 0x4F, 0xF0, ++0x08, 0x08, 0x04, 0x26, 0x0A, 0x22, 0xCB, 0x5F, 0x8F, 0x5E, 0xBB, 0x42, 0x07, 0xDA, 0xBA, 0x46, 0x72, 0x46, 0x8D, 0xF8, ++0x02, 0x40, 0x1F, 0x46, 0xA6, 0x46, 0x53, 0x46, 0x14, 0x46, 0x31, 0xF9, 0x09, 0x20, 0x31, 0xF9, 0x08, 0x80, 0x42, 0x45, ++0x05, 0xDA, 0x8D, 0xF8, 0x03, 0x50, 0x8D, 0xF8, 0x01, 0x60, 0x42, 0x46, 0x35, 0x46, 0x97, 0x42, 0x05, 0xDD, 0x8D, 0xF8, ++0x02, 0x50, 0x8D, 0xF8, 0x01, 0xE0, 0x3A, 0x46, 0x75, 0x46, 0x9D, 0xF8, 0x02, 0xE0, 0x9D, 0xF8, 0x01, 0x60, 0x31, 0xF9, ++0x1E, 0x70, 0x31, 0xF9, 0x16, 0x80, 0x07, 0x32, 0xFE, 0x1D, 0x93, 0x42, 0xD4, 0xBF, 0x04, 0x23, 0x00, 0x23, 0xB0, 0x45, ++0x9D, 0xF8, 0x03, 0x60, 0x31, 0xF9, 0x16, 0x20, 0x02, 0xF1, 0x07, 0x02, 0xD8, 0xBF, 0x43, 0xF0, 0x02, 0x03, 0xBA, 0x42, ++0xA8, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0x06, 0x2B, 0x4E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x4A, 0xA9, 0xA1, 0x9B, 0x93, 0x4A, ++0xB1, 0x00, 0x0C, 0xF1, 0x01, 0x0C, 0x5F, 0xFA, 0x8C, 0xFC, 0x69, 0xE7, 0xBC, 0xF1, 0x02, 0x0F, 0x78, 0xD0, 0x00, 0x23, ++0x1C, 0x46, 0x1A, 0x46, 0x40, 0xFA, 0x03, 0xF5, 0xEF, 0x07, 0x05, 0xD4, 0x31, 0xF8, 0x13, 0x50, 0x01, 0x34, 0x2A, 0x44, ++0xE4, 0xB2, 0x12, 0xB2, 0x01, 0x33, 0x06, 0x2B, 0xF2, 0xD1, 0x92, 0xFB, 0xF4, 0xF2, 0x00, 0x23, 0x40, 0xFA, 0x03, 0xF4, ++0xE6, 0x07, 0x48, 0xBF, 0x21, 0xF8, 0x13, 0x20, 0x01, 0x33, 0x06, 0x2B, 0xF6, 0xD1, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, ++0x8B, 0x1E, 0x80, 0x20, 0x0A, 0x31, 0x33, 0xF9, 0x02, 0x2F, 0x00, 0x2A, 0xB8, 0xBF, 0x18, 0x80, 0x99, 0x42, 0xF8, 0xD1, ++0x70, 0x47, 0xB1, 0xF9, 0x08, 0x20, 0xB1, 0xF9, 0x0A, 0x30, 0x02, 0x25, 0x9A, 0x42, 0x8D, 0xF8, 0x01, 0x50, 0x4F, 0xF0, ++0x04, 0x09, 0x4F, 0xF0, 0x06, 0x07, 0xFF, 0xF6, 0x72, 0xAF, 0x4F, 0xF0, 0x0A, 0x08, 0x08, 0x22, 0x4F, 0xF0, 0x04, 0x0E, ++0x75, 0xE7, 0xBC, 0xF1, 0x00, 0x0F, 0x69, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x02, 0x23, 0x40, 0xFA, 0x03, 0xF5, 0xED, 0x07, ++0x05, 0xD4, 0x31, 0xF8, 0x13, 0x50, 0x01, 0x34, 0x2A, 0x44, 0xE4, 0xB2, 0x12, 0xB2, 0x01, 0x33, 0x06, 0x2B, 0xF2, 0xD1, ++0x64, 0xB9, 0xC3, 0x07, 0x03, 0xD4, 0x0B, 0x88, 0x1A, 0x44, 0x12, 0xB2, 0x01, 0x24, 0x87, 0x07, 0x04, 0xD4, 0x4B, 0x88, ++0x01, 0x34, 0x13, 0x44, 0xE4, 0xB2, 0x1A, 0xB2, 0x00, 0x23, 0x92, 0xFB, 0xF4, 0xF4, 0x00, 0xE0, 0x01, 0x33, 0x40, 0xFA, ++0x03, 0xF2, 0xD6, 0x07, 0xDD, 0xB2, 0x03, 0xD5, 0x01, 0x2B, 0x14, 0xD9, 0x21, 0xF8, 0x13, 0x40, 0x05, 0x2D, 0xF3, 0xD1, ++0xBC, 0xF1, 0x01, 0x0F, 0xA9, 0xD1, 0xC2, 0x07, 0x0F, 0xD4, 0x83, 0x07, 0xA5, 0xD5, 0x0B, 0x88, 0x4B, 0x80, 0xA2, 0xE7, ++0x0A, 0x31, 0x80, 0x23, 0x28, 0xF8, 0x02, 0x3F, 0x88, 0x45, 0xFB, 0xD1, 0x9B, 0xE7, 0xBC, 0xF1, 0x02, 0x0F, 0xDF, 0xD1, ++0xE6, 0xE7, 0x4B, 0x88, 0x0B, 0x80, 0x94, 0xE7, 0x01, 0x22, 0x02, 0xFA, 0x0E, 0xF3, 0xB2, 0x40, 0x13, 0x43, 0x18, 0x43, ++0xC0, 0xB2, 0xB1, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x04, 0xF4, 0x20, 0x43, 0xC0, 0xB2, 0xAB, 0xE7, 0x01, 0x23, 0x03, 0xFA, ++0x06, 0xF6, 0x30, 0x43, 0xA3, 0x40, 0x18, 0x43, 0xC0, 0xB2, 0xA3, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x04, 0xF4, 0x20, 0x43, ++0xAB, 0x40, 0x18, 0x43, 0xC0, 0xB2, 0x9B, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x06, 0xF6, 0x30, 0x43, 0xC0, 0xB2, 0x95, 0xE7, ++0x40, 0xF0, 0x3C, 0x00, 0x92, 0xE7, 0x00, 0xBF, 0xF0, 0xB5, 0xD1, 0xED, 0x01, 0x6A, 0x91, 0xED, 0x00, 0x7A, 0x2D, 0xED, ++0x08, 0x8B, 0xF4, 0xEE, 0xC7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x83, 0xB0, 0x0C, 0x46, 0x07, 0x46, 0x15, 0x46, 0x1E, 0x46, ++0x05, 0xDC, 0xF0, 0xEE, 0x66, 0x7A, 0xF0, 0xEE, 0x47, 0x6A, 0xB0, 0xEE, 0x67, 0x7A, 0xD4, 0xED, 0x02, 0x7A, 0xF4, 0xEE, ++0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xDC, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x48, 0xBF, 0xB0, 0xEE, ++0x67, 0x7A, 0xF0, 0xEE, 0x66, 0x7A, 0x77, 0xEE, 0xC7, 0x7A, 0xB0, 0xEE, 0x08, 0xBA, 0xFC, 0xEE, 0xE7, 0x7A, 0x17, 0xEE, ++0x90, 0x3A, 0xB3, 0x70, 0xD4, 0xED, 0x00, 0x8A, 0x94, 0xED, 0x01, 0xAA, 0xD4, 0xED, 0x02, 0x9A, 0x6A, 0xEE, 0x0A, 0x7A, ++0x28, 0xEE, 0xA8, 0x6A, 0x69, 0xEE, 0xA9, 0xAA, 0x36, 0xEE, 0x27, 0x6A, 0x38, 0xEE, 0x8A, 0x7A, 0x76, 0xEE, 0x2A, 0xAA, ++0x37, 0xEE, 0x29, 0x9A, 0x2A, 0xEE, 0x8B, 0xBA, 0x69, 0xEE, 0x09, 0x7A, 0x3B, 0xEE, 0x67, 0xBA, 0xB5, 0xEE, 0xC0, 0xBA, ++0xF1, 0xEE, 0x10, 0xFA, 0x40, 0xF3, 0xD0, 0x80, 0x1B, 0xEE, 0x10, 0x0A, 0x33, 0xF0, 0x44, 0xF8, 0x6F, 0xA3, 0xD3, 0xE9, ++0x00, 0x23, 0x33, 0xF0, 0x09, 0xFB, 0x80, 0xB1, 0x9F, 0xED, 0x6E, 0xBA, 0x33, 0x78, 0x6E, 0x49, 0x43, 0xF0, 0x04, 0x03, ++0x33, 0x70, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0x73, 0xF8, 0xD4, 0xED, 0x00, 0x8A, 0x94, 0xED, 0x01, 0xAA, 0xD4, 0xED, ++0x02, 0x9A, 0x95, 0xED, 0x00, 0x4A, 0xD5, 0xED, 0x01, 0x4A, 0x95, 0xED, 0x02, 0x5A, 0xF7, 0xEE, 0x00, 0x7A, 0x87, 0xEE, ++0x8B, 0x6A, 0x0D, 0x2F, 0xF0, 0xEE, 0x08, 0x6A, 0x26, 0xEE, 0x49, 0x7A, 0x66, 0xEE, 0x26, 0x6A, 0x2A, 0xEE, 0x86, 0x6A, ++0x66, 0xEE, 0xA8, 0x7A, 0x66, 0xEE, 0x8A, 0x5A, 0x67, 0xEE, 0x28, 0x8A, 0x27, 0xEE, 0x0A, 0xAA, 0x77, 0xEE, 0x87, 0x7A, ++0x26, 0xEE, 0xA9, 0x8A, 0x78, 0xEE, 0x86, 0x8A, 0x67, 0xEE, 0x29, 0x9A, 0x75, 0xEE, 0x87, 0x5A, 0x3A, 0xEE, 0x06, 0xAA, ++0x38, 0xEE, 0x07, 0x8A, 0x67, 0xEE, 0x84, 0x7A, 0x68, 0xEE, 0x84, 0x8A, 0x79, 0xEE, 0x86, 0x9A, 0x25, 0xEE, 0xA4, 0x7A, ++0x2A, 0xEE, 0x24, 0xAA, 0x77, 0xEE, 0x87, 0x7A, 0x78, 0xEE, 0x8A, 0x8A, 0x28, 0xEE, 0x05, 0x8A, 0x69, 0xEE, 0x85, 0x9A, ++0x37, 0xEE, 0x88, 0x8A, 0x78, 0xEE, 0xA9, 0x8A, 0x2E, 0xD9, 0xF3, 0xEE, 0x04, 0x7A, 0xB4, 0xEE, 0xE7, 0x8A, 0xF1, 0xEE, ++0x10, 0xFA, 0x27, 0xD5, 0x33, 0x78, 0x44, 0x49, 0x43, 0xF0, 0x08, 0x03, 0x33, 0x70, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, ++0x1D, 0xF8, 0xB7, 0xEE, 0x00, 0x8A, 0xF0, 0xEE, 0x00, 0x6A, 0xB1, 0xEE, 0x68, 0x7A, 0xC7, 0xEE, 0x08, 0x7A, 0x9F, 0xED, ++0x3D, 0x7A, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x21, 0xDC, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x4E, 0xD4, 0xB6, 0xEE, 0x00, 0x7A, 0x77, 0xEE, 0x87, 0x7A, 0xFC, 0xEE, 0xE7, 0x7A, 0xCD, 0xED, 0x01, 0x7A, 0x9D, 0xF8, ++0x04, 0x30, 0x12, 0xE0, 0x18, 0xEE, 0x10, 0x0A, 0x32, 0xF0, 0xBA, 0xFF, 0x2A, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x33, 0xF0, ++0x7F, 0xFA, 0x00, 0x28, 0xCC, 0xD1, 0x68, 0xEE, 0x08, 0x6A, 0xF7, 0xEE, 0x00, 0x7A, 0x76, 0xEE, 0xA7, 0x6A, 0xD2, 0xE7, ++0xFF, 0x23, 0x73, 0x70, 0xD4, 0xED, 0x00, 0x7A, 0x94, 0xED, 0x01, 0x7A, 0xD4, 0xED, 0x02, 0x4A, 0x95, 0xED, 0x00, 0x5A, ++0xD5, 0xED, 0x01, 0x5A, 0x95, 0xED, 0x02, 0x6A, 0x68, 0xEE, 0x27, 0x7A, 0x28, 0xEE, 0x07, 0x7A, 0x77, 0xEE, 0xA8, 0x7A, ++0x37, 0xEE, 0x28, 0x7A, 0x28, 0xEE, 0x24, 0x8A, 0x77, 0xEE, 0xC5, 0x7A, 0x37, 0xEE, 0x65, 0x7A, 0x38, 0xEE, 0x28, 0x8A, ++0x27, 0xEE, 0x07, 0x7A, 0x38, 0xEE, 0x46, 0x8A, 0x67, 0xEE, 0xA7, 0x7A, 0x28, 0xEE, 0x08, 0x8A, 0x77, 0xEE, 0x87, 0x7A, ++0x37, 0xEE, 0x88, 0x8A, 0xC8, 0xEE, 0x26, 0x7A, 0xC6, 0xED, 0x01, 0x7A, 0x03, 0xB0, 0xBD, 0xEC, 0x08, 0x8B, 0xF0, 0xBD, ++0x00, 0x23, 0xCC, 0xE7, 0xF1, 0xEE, 0x4B, 0x7A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x72, 0xFF, 0x06, 0xA3, 0xD3, 0xE9, ++0x00, 0x23, 0x33, 0xF0, 0x37, 0xFA, 0x00, 0x28, 0x3F, 0xF4, 0x3D, 0xAF, 0x9F, 0xED, 0x08, 0xBA, 0x2A, 0xE7, 0x00, 0xBF, ++0xAF, 0xF3, 0x00, 0x80, 0xF1, 0x68, 0xE3, 0x88, 0xB5, 0xF8, 0xE4, 0x3E, 0x00, 0x50, 0xC3, 0x47, 0xD4, 0x79, 0x15, 0x00, ++0x00, 0x7A, 0x15, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xAC, 0xC5, 0x27, 0xB7, 0x2D, 0xE9, 0xF0, 0x47, 0x09, 0x29, 0x8E, 0xB0, ++0x88, 0x46, 0x1D, 0x46, 0x70, 0xD9, 0x03, 0x28, 0x6E, 0xD0, 0x4F, 0xF0, 0x86, 0x4A, 0x57, 0x1E, 0x00, 0x26, 0x0D, 0xF1, ++0x18, 0x09, 0x00, 0x22, 0x10, 0x46, 0xF1, 0xB2, 0xD3, 0xB2, 0x8B, 0x42, 0x19, 0xD0, 0x00, 0x2B, 0x00, 0xF0, 0xAF, 0x80, ++0xBB, 0x5C, 0x07, 0xEE, 0x90, 0x3A, 0x0E, 0xAB, 0xF8, 0xEE, 0x67, 0x7A, 0x03, 0xEB, 0x80, 0x03, 0x43, 0xED, 0x0E, 0x7A, ++0x84, 0x00, 0x55, 0xF8, 0x22, 0x30, 0x07, 0xEE, 0x90, 0x3A, 0x0E, 0xAB, 0xF8, 0xEE, 0xE7, 0x7A, 0x1C, 0x44, 0x01, 0x30, ++0xC0, 0xB2, 0x44, 0xED, 0x0B, 0x7A, 0x01, 0x32, 0x04, 0x2A, 0xDF, 0xD1, 0x00, 0x23, 0x03, 0xA9, 0x68, 0x46, 0x09, 0xF8, ++0x36, 0x30, 0xFF, 0xF7, 0x9F, 0xFC, 0x10, 0xF0, 0x0E, 0x0F, 0x09, 0xF8, 0x36, 0x00, 0x00, 0xF0, 0x95, 0x80, 0x01, 0x36, ++0x04, 0x2E, 0xCC, 0xD1, 0x07, 0xAD, 0x00, 0x24, 0x2A, 0x46, 0x23, 0x46, 0x80, 0x21, 0x12, 0xF8, 0x04, 0x0C, 0x00, 0x28, ++0x40, 0xF0, 0x82, 0x80, 0x0E, 0xA8, 0x80, 0x29, 0x00, 0xEB, 0xC1, 0x00, 0x00, 0xF0, 0x8A, 0x80, 0x92, 0xED, 0x00, 0x7A, ++0x50, 0xED, 0x07, 0x7A, 0xB4, 0xEE, 0x67, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x98, 0xBF, 0x19, 0x46, 0x01, 0x33, 0xDB, 0xB2, ++0x04, 0x2B, 0x02, 0xF1, 0x08, 0x02, 0xE4, 0xD1, 0x00, 0x2C, 0x00, 0xF0, 0x84, 0x80, 0x80, 0x29, 0x76, 0xD0, 0x0E, 0xAB, ++0x03, 0xEB, 0xC1, 0x00, 0x42, 0x46, 0x10, 0xF8, 0x1F, 0x4C, 0x10, 0xF8, 0x20, 0x3C, 0x55, 0x49, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x22, 0xFF, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x13, 0x78, 0xD5, 0xED, 0x00, 0x6A, 0x95, 0xED, ++0x01, 0x7A, 0xD5, 0xED, 0x02, 0x7A, 0x05, 0xEE, 0x90, 0x3A, 0x53, 0x78, 0x06, 0xEE, 0x10, 0x3A, 0xF8, 0xEE, 0x65, 0x5A, ++0xB8, 0xEE, 0x46, 0x6A, 0xF8, 0xEE, 0xE6, 0x6A, 0xB8, 0xEE, 0xC7, 0x7A, 0xF8, 0xEE, 0xE7, 0x7A, 0x4F, 0xF0, 0x86, 0x42, ++0x00, 0x23, 0xB8, 0xF1, 0x09, 0x0F, 0xCD, 0xED, 0x01, 0x5A, 0x8D, 0xED, 0x02, 0x6A, 0xCD, 0xED, 0x03, 0x6A, 0x8D, 0xED, ++0x04, 0x7A, 0xCD, 0xED, 0x05, 0x7A, 0x00, 0x92, 0x8D, 0xF8, 0x18, 0x30, 0x16, 0xD8, 0x06, 0xAB, 0x03, 0xAA, 0x69, 0x46, ++0x40, 0x46, 0xFF, 0xF7, 0x17, 0xFE, 0x9D, 0xF8, 0x18, 0x30, 0x13, 0xF0, 0x0E, 0x0F, 0x4C, 0xD1, 0x9D, 0xF8, 0x19, 0x40, ++0x35, 0x49, 0x42, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xE2, 0xFE, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, ++0x03, 0xA9, 0x68, 0x46, 0xFF, 0xF7, 0x1C, 0xFC, 0x10, 0xF0, 0x0E, 0x0F, 0x8D, 0xF8, 0x18, 0x00, 0x18, 0xBF, 0x03, 0x46, ++0x49, 0xD0, 0xC8, 0xF1, 0x09, 0x04, 0x64, 0x01, 0xE6, 0xE7, 0x0E, 0xAB, 0x03, 0xEB, 0x80, 0x03, 0x84, 0x00, 0x43, 0xF8, ++0x38, 0xAC, 0x54, 0xE7, 0x06, 0x07, 0x1B, 0xD4, 0x01, 0x28, 0x08, 0xBF, 0x01, 0x24, 0x87, 0xE7, 0x09, 0xEB, 0xC6, 0x03, ++0x03, 0xAA, 0x69, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xE3, 0xFD, 0x62, 0xE7, 0x19, 0x46, 0x7D, 0xE7, 0x00, 0x23, 0x15, 0xF8, ++0x04, 0x2C, 0x01, 0x2A, 0x17, 0xD0, 0x01, 0x33, 0xDB, 0xB2, 0x04, 0x2B, 0x05, 0xF1, 0x08, 0x05, 0xF5, 0xD1, 0x80, 0x29, ++0x7F, 0xF4, 0x7B, 0xAF, 0x17, 0x49, 0x42, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xA4, 0xFE, 0xC8, 0xF1, 0x09, 0x04, ++0x64, 0x01, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x80, 0x24, 0xB2, 0xE7, 0x0E, 0xAA, 0x80, 0x29, 0x02, 0xEB, ++0xC1, 0x02, 0x0A, 0xD0, 0x95, 0xED, 0x00, 0x7A, 0x52, 0xED, 0x07, 0x7A, 0xB4, 0xEE, 0x67, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x98, 0xBF, 0x19, 0x46, 0xD7, 0xE7, 0x19, 0x46, 0xD5, 0xE7, 0x06, 0xAB, 0x03, 0xAA, 0x69, 0x46, 0x40, 0x46, 0xFF, 0xF7, ++0xAB, 0xFD, 0x9D, 0xF8, 0x18, 0x30, 0x13, 0xF0, 0x0E, 0x0F, 0x93, 0xD0, 0xA9, 0xE7, 0x00, 0xBF, 0x14, 0x7A, 0x15, 0x00, ++0x30, 0x7A, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x9A, 0x4A, 0xDF, 0xF8, 0x8C, 0x82, 0x13, 0x68, 0x2D, 0xED, 0x08, 0x8B, ++0x23, 0xF4, 0xFF, 0x43, 0x43, 0xF4, 0xCE, 0x35, 0x8B, 0xB0, 0x43, 0xF4, 0x1D, 0x43, 0x0C, 0x46, 0x45, 0xF4, 0x80, 0x75, ++0x01, 0x46, 0x13, 0x60, 0x01, 0x20, 0x15, 0x60, 0x0D, 0x46, 0x03, 0x91, 0xFC, 0xF7, 0xBA, 0xFD, 0xA2, 0x7B, 0x8F, 0x48, ++0x02, 0xF0, 0x0F, 0x03, 0x01, 0x68, 0x12, 0x09, 0x9B, 0x02, 0x43, 0xEA, 0x82, 0x13, 0x21, 0xF4, 0x7F, 0x52, 0x13, 0x43, ++0x03, 0x60, 0x02, 0x20, 0xFC, 0xF7, 0xAA, 0xFD, 0xAB, 0x6B, 0xC3, 0xF3, 0x07, 0x22, 0x02, 0x92, 0x4F, 0xEA, 0x02, 0x4B, ++0xDA, 0xB2, 0x01, 0x92, 0x4F, 0xEA, 0x03, 0x6A, 0x4F, 0xF0, 0x00, 0x09, 0xDD, 0xE9, 0x01, 0x32, 0xB9, 0xF1, 0x00, 0x0F, ++0x18, 0xBF, 0x13, 0x46, 0xA3, 0xF1, 0x40, 0x02, 0x12, 0xB2, 0x40, 0x33, 0x5F, 0xFA, 0x89, 0xF1, 0x00, 0x2A, 0xAD, 0xF8, ++0x14, 0x20, 0xAD, 0xF8, 0x16, 0x30, 0x00, 0x91, 0xC0, 0xF2, 0xEA, 0x80, 0xFF, 0x2B, 0x01, 0xD9, 0x77, 0x4B, 0x05, 0x93, ++0x00, 0x25, 0x2E, 0x46, 0x05, 0x24, 0x48, 0xF2, 0x80, 0x07, 0xBD, 0xF9, 0x14, 0x30, 0x08, 0xA9, 0x06, 0xA8, 0xB9, 0xF1, ++0x00, 0x0F, 0x00, 0xF0, 0xC3, 0x80, 0x4A, 0xEA, 0x03, 0x43, 0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0xFF, 0xF7, 0xAE, 0xF8, ++0xBD, 0xF9, 0x16, 0x30, 0x4A, 0xEA, 0x03, 0x43, 0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0x09, 0xA9, 0x07, 0xA8, 0xFF, 0xF7, ++0xA3, 0xF8, 0xDD, 0xE9, 0x06, 0x02, 0xDD, 0xE9, 0x08, 0x13, 0x01, 0x3C, 0x12, 0x1A, 0x5B, 0x1A, 0x14, 0xF0, 0xFF, 0x04, ++0x16, 0x44, 0x1D, 0x44, 0xD9, 0xD1, 0x62, 0x4B, 0x83, 0xFB, 0x06, 0x12, 0xF6, 0x17, 0xC6, 0xEB, 0x62, 0x06, 0x07, 0xEE, ++0x90, 0x6A, 0x83, 0xFB, 0x05, 0x13, 0xED, 0x17, 0xC5, 0xEB, 0x63, 0x05, 0xB8, 0xEE, 0xE7, 0x7A, 0x07, 0xEE, 0x90, 0x5A, ++0xF8, 0xEE, 0xE7, 0x7A, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x9D, 0x80, 0x00, 0x9B, 0x01, 0x2B, 0x40, 0xF0, 0x9D, 0x80, ++0xC7, 0xEE, 0x27, 0x9A, 0x03, 0x9B, 0x54, 0x49, 0x54, 0x4F, 0x4F, 0xF4, 0x00, 0x50, 0x1E, 0x1F, 0x03, 0xF1, 0x3C, 0x08, ++0xB6, 0xEE, 0x00, 0xAA, 0x79, 0xEE, 0x88, 0x9A, 0xF7, 0xEE, 0x00, 0xAA, 0x69, 0xEE, 0x8A, 0x9A, 0x8A, 0xEE, 0xA9, 0x8A, ++0xFD, 0xEE, 0xC8, 0x8A, 0x18, 0xEE, 0x90, 0x2A, 0x20, 0xF0, 0xCA, 0xFD, 0xF8, 0xEE, 0xE8, 0x8A, 0xDF, 0xED, 0x49, 0x7A, ++0x49, 0x49, 0x38, 0xEE, 0x68, 0x8A, 0x4F, 0xF4, 0x00, 0x50, 0x28, 0xEE, 0x27, 0x8A, 0xFD, 0xEE, 0xC8, 0x7A, 0x17, 0xEE, ++0x90, 0x2A, 0x20, 0xF0, 0xB9, 0xFD, 0x69, 0xEE, 0xA9, 0x7A, 0x39, 0xEE, 0xAA, 0xBA, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, ++0x71, 0xFD, 0x40, 0x4B, 0x00, 0x22, 0x32, 0xF0, 0x0F, 0xFC, 0x7A, 0xEE, 0xE9, 0xAA, 0x04, 0x46, 0x0D, 0x46, 0x56, 0xF8, ++0x04, 0x3F, 0xC3, 0xF3, 0x07, 0x22, 0x08, 0xEE, 0x90, 0x2A, 0xDB, 0xB2, 0x08, 0xEE, 0x10, 0x3A, 0xF8, 0xEE, 0xE8, 0x8A, ++0xB8, 0xEE, 0xC8, 0x8A, 0x68, 0xEE, 0xAA, 0x8A, 0x28, 0xEE, 0x0B, 0x8A, 0x69, 0xEE, 0xA8, 0x7A, 0x78, 0xEE, 0x67, 0x7A, ++0x29, 0xEE, 0x88, 0x8A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x4E, 0xFD, 0x22, 0x46, 0x2B, 0x46, 0x32, 0xF0, 0xCC, 0xFE, ++0x33, 0xF0, 0x5A, 0xF8, 0x78, 0xEE, 0x28, 0x7A, 0x09, 0xEE, 0x10, 0x0A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x40, 0xFD, ++0x22, 0x46, 0x2B, 0x46, 0x32, 0xF0, 0xBE, 0xFE, 0x33, 0xF0, 0x4C, 0xF8, 0x07, 0xEE, 0x90, 0x0A, 0x77, 0xEE, 0x8A, 0x7A, ++0x39, 0xEE, 0x0A, 0x9A, 0xFD, 0xEE, 0xE7, 0x7A, 0xB0, 0x45, 0x17, 0xEE, 0x90, 0x3A, 0xFD, 0xEE, 0xC9, 0x7A, 0x4F, 0xEA, ++0x03, 0x23, 0xCD, 0xED, 0x00, 0x7A, 0x9D, 0xF8, 0x00, 0x20, 0x03, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x02, 0x03, 0x43, 0xEA, ++0x07, 0x03, 0x33, 0x60, 0xB5, 0xD1, 0x0B, 0xB0, 0xBD, 0xEC, 0x08, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0xEA, 0x03, 0x63, ++0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0x08, 0xA9, 0x06, 0xA8, 0xFE, 0xF7, 0xE9, 0xFF, 0xBD, 0xF9, 0x16, 0x30, 0x4B, 0xEA, ++0x03, 0x63, 0x3B, 0x43, 0x39, 0xE7, 0xF1, 0xEE, 0x67, 0x7A, 0x87, 0xEE, 0x87, 0x8A, 0x09, 0xF1, 0x01, 0x09, 0x01, 0xE7, ++0x4F, 0xF4, 0x00, 0x03, 0x05, 0x93, 0x15, 0xE7, 0x58, 0x40, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, 0x80, 0x00, 0xFF, 0x00, ++0x67, 0x66, 0x66, 0x66, 0x48, 0x7A, 0x15, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x7A, 0x44, 0x58, 0x7A, 0x15, 0x00, ++0x00, 0x00, 0xF0, 0x3F, 0x4C, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0xB5, 0x4C, 0x2D, 0xED, 0x04, 0x8B, 0x27, 0x68, ++0xAD, 0xF2, 0xE4, 0x7D, 0x06, 0x46, 0x0D, 0x46, 0x14, 0x46, 0xB2, 0x49, 0x0A, 0x94, 0x3A, 0x46, 0x4F, 0xF4, 0x00, 0x50, ++0x9A, 0x46, 0xCD, 0xE9, 0x13, 0x56, 0x20, 0xF0, 0x17, 0xFD, 0xAE, 0x4B, 0xAE, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x10, 0xFD, 0xAC, 0x4B, 0xAD, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x09, 0xFD, 0xAB, 0x4B, ++0xAB, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x02, 0xFD, 0xA9, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, ++0xFD, 0xFC, 0x16, 0xF0, 0x01, 0x03, 0x15, 0x93, 0x07, 0xD1, 0xA6, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x61, 0x43, 0xF4, ++0xC0, 0x53, 0x11, 0x60, 0x13, 0x60, 0x14, 0x9A, 0xC2, 0xF3, 0x40, 0x03, 0x03, 0x33, 0x12, 0xF0, 0x0C, 0x0F, 0x09, 0xEE, ++0x10, 0x3A, 0xC2, 0xF3, 0x81, 0x03, 0x00, 0xF0, 0x9C, 0x82, 0x01, 0x2B, 0x14, 0xBF, 0x0A, 0x23, 0x05, 0x23, 0x08, 0xEE, ++0x90, 0x3A, 0x9A, 0x4A, 0x9A, 0x4E, 0x14, 0x68, 0xDF, 0xF8, 0x7C, 0xE2, 0x99, 0x4B, 0x9A, 0x49, 0xDF, 0xF8, 0x78, 0x92, ++0xDF, 0xF8, 0x78, 0xB2, 0x98, 0x48, 0xDF, 0xF8, 0x78, 0xC2, 0x98, 0x4F, 0xDF, 0xF8, 0x74, 0x82, 0x24, 0xF0, 0x04, 0x04, ++0x14, 0x60, 0x35, 0x68, 0x00, 0x24, 0x25, 0xF4, 0x70, 0x45, 0x35, 0x60, 0xCE, 0xF8, 0x00, 0x40, 0x1D, 0x68, 0x45, 0xF0, ++0x80, 0x05, 0x1D, 0x60, 0x0D, 0x68, 0x45, 0xF0, 0x00, 0x45, 0x0D, 0x60, 0x15, 0x68, 0x01, 0x26, 0x45, 0xF0, 0x04, 0x05, ++0x15, 0x60, 0xCB, 0xF8, 0x00, 0x60, 0xC9, 0xF8, 0x00, 0x40, 0x15, 0x68, 0x25, 0xF0, 0x04, 0x05, 0x15, 0x60, 0x0D, 0x68, ++0x25, 0xF0, 0x00, 0x45, 0x0D, 0x60, 0x1D, 0x68, 0x25, 0xF0, 0x80, 0x05, 0x1D, 0x60, 0x15, 0x68, 0x45, 0xF0, 0x04, 0x05, ++0x15, 0x60, 0x82, 0x4D, 0x2A, 0x68, 0x42, 0xF0, 0x02, 0x02, 0x2A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x42, 0x22, 0xF0, ++0x04, 0x02, 0x42, 0xF4, 0x80, 0x42, 0x32, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x07, 0x22, 0x42, 0xF0, 0xC0, 0x62, ++0x42, 0xF4, 0x84, 0x72, 0x1A, 0x60, 0x0B, 0x68, 0x03, 0xF0, 0x00, 0x43, 0x43, 0xEA, 0x0A, 0x03, 0x0B, 0x60, 0x03, 0x68, ++0x43, 0xF0, 0x3F, 0x03, 0x03, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x0B, 0x94, 0x43, 0xF4, 0x00, 0x63, 0x38, 0xAA, 0x78, 0xA9, ++0x10, 0x92, 0x0F, 0x91, 0xCC, 0xF8, 0x00, 0x30, 0x0D, 0xF1, 0x7F, 0x03, 0xCD, 0xE9, 0x11, 0x21, 0x0D, 0x93, 0x08, 0xEE, ++0x10, 0x4A, 0x0D, 0xF1, 0xAF, 0x03, 0x81, 0x46, 0x0E, 0x93, 0x00, 0x23, 0x0C, 0x93, 0x9D, 0xF8, 0x30, 0x50, 0x18, 0xEE, ++0x10, 0x3A, 0x2B, 0x43, 0x09, 0x93, 0x00, 0x24, 0x3D, 0xE0, 0x0C, 0x9B, 0x00, 0x2B, 0x6C, 0xD0, 0x66, 0x00, 0x0D, 0x9B, ++0x26, 0x44, 0x48, 0xF2, 0x80, 0x0B, 0x13, 0xF8, 0x06, 0xA0, 0x0E, 0x9B, 0x9E, 0x5D, 0x4F, 0xEA, 0x0A, 0x63, 0x43, 0xEA, ++0x0A, 0x43, 0x43, 0xEA, 0x0B, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0x19, 0xA9, 0x18, 0xA8, 0xFE, 0xF7, 0xE3, 0xFE, 0xB2, 0x45, ++0x0A, 0xD0, 0x33, 0x06, 0x43, 0xEA, 0x06, 0x46, 0x46, 0xEA, 0x0B, 0x06, 0xC8, 0xF8, 0x00, 0x60, 0x19, 0xA9, 0x17, 0xA8, ++0xFE, 0xF7, 0xD6, 0xFE, 0x04, 0xEB, 0x84, 0x03, 0xB8, 0xAA, 0xDE, 0x00, 0x00, 0x21, 0x02, 0xEB, 0xC3, 0x03, 0x28, 0x46, ++0x18, 0x9A, 0xFF, 0xF7, 0x51, 0xF8, 0x0D, 0xF5, 0xAC, 0x63, 0x33, 0x44, 0x19, 0x9A, 0x01, 0x34, 0x00, 0x21, 0x28, 0x46, ++0xFF, 0xF7, 0x48, 0xF8, 0x10, 0x2C, 0xB8, 0xAE, 0x0D, 0xF5, 0xAC, 0x6B, 0x59, 0xD0, 0x3B, 0x68, 0x23, 0xF4, 0xFF, 0x43, ++0x43, 0xEA, 0x44, 0x23, 0x43, 0xF4, 0x01, 0x42, 0x43, 0xF4, 0xC0, 0x33, 0x43, 0xF4, 0x80, 0x73, 0x3A, 0x60, 0x01, 0x20, ++0x3B, 0x60, 0xFC, 0xF7, 0x71, 0xFB, 0x09, 0x9B, 0xE6, 0xB2, 0x00, 0x2B, 0x3D, 0xD0, 0x0A, 0x9B, 0xD9, 0xF8, 0x00, 0x10, ++0x1A, 0x5D, 0x02, 0xF0, 0x0F, 0x03, 0x9B, 0x02, 0x12, 0x09, 0x43, 0xEA, 0x82, 0x13, 0x21, 0xF4, 0x7F, 0x52, 0x13, 0x43, ++0xC9, 0xF8, 0x00, 0x30, 0x02, 0x20, 0xFC, 0xF7, 0x5B, 0xFB, 0x0B, 0x9B, 0x00, 0x2B, 0x98, 0xD1, 0x4F, 0xF0, 0x80, 0x33, ++0xC8, 0xF8, 0x00, 0x30, 0x19, 0xA9, 0x18, 0xA8, 0xFE, 0xF7, 0x8C, 0xFE, 0xB4, 0xE7, 0x10, 0x9B, 0x04, 0xEB, 0x44, 0x0B, ++0x03, 0xEB, 0x04, 0x12, 0x20, 0xAB, 0x18, 0xEE, 0x10, 0x0A, 0x5B, 0x44, 0x00, 0x92, 0x31, 0x46, 0x0D, 0xF1, 0x5A, 0x02, ++0xFE, 0xF7, 0xF2, 0xFF, 0x0F, 0x9B, 0x4F, 0xEA, 0x04, 0x1A, 0x0A, 0xEB, 0x03, 0x02, 0x2C, 0xAB, 0x31, 0x46, 0x00, 0x92, ++0x18, 0xEE, 0x10, 0x0A, 0x5B, 0x44, 0x0D, 0xF1, 0x5B, 0x02, 0x66, 0x00, 0xFE, 0xF7, 0xE2, 0xFF, 0x73, 0xE7, 0xFE, 0xF7, ++0xA7, 0xFE, 0x0A, 0x9B, 0x18, 0x55, 0x02, 0x20, 0xFC, 0xF7, 0x28, 0xFB, 0xCE, 0xE7, 0x0C, 0x9B, 0x18, 0xEE, 0x90, 0x2A, ++0x01, 0x33, 0x93, 0x42, 0x0C, 0x93, 0x7F, 0xF4, 0x58, 0xAF, 0x18, 0xEE, 0x90, 0xAA, 0x00, 0x25, 0x45, 0xE0, 0x00, 0xBF, ++0x10, 0x20, 0x34, 0x40, 0x60, 0x7A, 0x15, 0x00, 0x1C, 0x20, 0x34, 0x40, 0x74, 0x7A, 0x15, 0x00, 0x04, 0x22, 0x34, 0x40, ++0x88, 0x7A, 0x15, 0x00, 0x18, 0x00, 0x58, 0x40, 0x9C, 0x7A, 0x15, 0x00, 0xB0, 0x7A, 0x15, 0x00, 0x04, 0x40, 0x34, 0x40, ++0x30, 0x20, 0x34, 0x40, 0x60, 0x20, 0x34, 0x40, 0x5C, 0x20, 0x34, 0x40, 0x64, 0x20, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, ++0x58, 0x40, 0x34, 0x40, 0x80, 0x21, 0x34, 0x40, 0x68, 0x20, 0x34, 0x40, 0x0C, 0xB6, 0x33, 0x40, 0x08, 0xB6, 0x33, 0x40, ++0x20, 0x40, 0x34, 0x40, 0x4C, 0x40, 0x34, 0x40, 0x06, 0x2D, 0x34, 0xBF, 0x32, 0x21, 0x64, 0x21, 0x09, 0x91, 0xFE, 0xF7, ++0xDB, 0xFF, 0x11, 0x9B, 0x09, 0x99, 0x84, 0x46, 0x43, 0xF8, 0x04, 0xC0, 0x5A, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xD2, 0xFF, ++0x01, 0x35, 0x12, 0x9B, 0x10, 0x2D, 0x18, 0x51, 0x06, 0xF1, 0x28, 0x06, 0x0B, 0xF1, 0x28, 0x0B, 0x14, 0xD0, 0xBA, 0xF1, ++0x01, 0x0F, 0x32, 0x46, 0x4F, 0xEA, 0x05, 0x14, 0x50, 0x46, 0xDF, 0xD1, 0x11, 0x9B, 0x30, 0x68, 0x18, 0x51, 0x01, 0x35, ++0x12, 0x9B, 0xDB, 0xF8, 0x00, 0x10, 0x19, 0x51, 0x10, 0x2D, 0x06, 0xF1, 0x28, 0x06, 0x0B, 0xF1, 0x28, 0x0B, 0xEA, 0xD1, ++0x11, 0x9A, 0x0B, 0x9B, 0x04, 0x32, 0x11, 0x92, 0x12, 0x9A, 0x04, 0x32, 0x12, 0x92, 0x0D, 0x9A, 0x01, 0x32, 0x0D, 0x92, ++0x0E, 0x9A, 0x01, 0x32, 0x01, 0x33, 0x0E, 0x92, 0x19, 0xEE, 0x10, 0x2A, 0x0B, 0x93, 0xDB, 0xB2, 0x9A, 0x42, 0x08, 0xEE, ++0x10, 0x3A, 0x3F, 0xF6, 0xE0, 0xAE, 0x20, 0xAD, 0x2C, 0xAC, 0xAB, 0x46, 0x0B, 0x95, 0xDD, 0xF8, 0x40, 0x80, 0x0F, 0x9F, ++0x09, 0x94, 0x19, 0xEE, 0x10, 0x5A, 0xA2, 0x46, 0x00, 0x26, 0x09, 0xE0, 0x13, 0x9A, 0x42, 0xF8, 0x26, 0x30, 0x01, 0x36, ++0x0B, 0xF1, 0x03, 0x0B, 0x08, 0xF1, 0x10, 0x08, 0x0A, 0xF1, 0x03, 0x0A, 0x5F, 0xFA, 0x86, 0xF9, 0x49, 0x46, 0x43, 0x46, ++0x5A, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x98, 0xFB, 0x07, 0xEB, 0x06, 0x13, 0x04, 0x46, 0x52, 0x46, 0x49, 0x46, 0x28, 0x46, ++0xFF, 0xF7, 0x90, 0xFB, 0x03, 0x02, 0xE2, 0xB2, 0x03, 0xF4, 0x7F, 0x43, 0x13, 0x43, 0x43, 0xF0, 0x00, 0x43, 0x09, 0x2E, ++0x43, 0xF4, 0x00, 0x03, 0xDA, 0xD9, 0x1A, 0xAB, 0x03, 0xEB, 0x46, 0x02, 0x1D, 0xAB, 0x03, 0xEB, 0x46, 0x03, 0xB9, 0xF1, ++0x0F, 0x0F, 0x22, 0xF8, 0x14, 0x4C, 0x23, 0xF8, 0x14, 0x0C, 0xD0, 0xD1, 0x14, 0x9B, 0x09, 0x9C, 0x0B, 0x9D, 0xC3, 0xF3, ++0x40, 0x10, 0x1A, 0xA9, 0x09, 0x90, 0xFF, 0xF7, 0xD3, 0xF8, 0x09, 0x98, 0x1D, 0xA9, 0xFF, 0xF7, 0xCF, 0xF8, 0x13, 0x9B, ++0xDF, 0xF8, 0x98, 0xC1, 0x1D, 0xA8, 0x1A, 0xA9, 0x03, 0xF1, 0x24, 0x06, 0x03, 0xF1, 0x3C, 0x07, 0x30, 0xF9, 0x02, 0x3B, ++0x31, 0xF9, 0x02, 0x2B, 0x1B, 0x02, 0x03, 0xF4, 0x7F, 0x43, 0xD2, 0xB2, 0x13, 0x43, 0x43, 0xEA, 0x0C, 0x03, 0x46, 0xF8, ++0x04, 0x3F, 0xBE, 0x42, 0xF0, 0xD1, 0x10, 0x9B, 0xDF, 0xF8, 0x6C, 0x81, 0xDD, 0xF8, 0x3C, 0xA0, 0x03, 0xF5, 0x80, 0x77, ++0x00, 0x26, 0x99, 0x46, 0xD9, 0xF8, 0x0C, 0x20, 0xAB, 0x78, 0xD9, 0xF8, 0x08, 0xC0, 0x68, 0x78, 0xD9, 0xF8, 0x04, 0x10, ++0x06, 0x92, 0x15, 0xF8, 0x03, 0x2B, 0x05, 0x93, 0x59, 0xF8, 0x10, 0x3B, 0x00, 0x93, 0xCD, 0xE9, 0x03, 0x0C, 0xCD, 0xE9, ++0x01, 0x21, 0x80, 0x23, 0x32, 0x46, 0x41, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xC6, 0xFA, 0xDA, 0xF8, 0x0C, 0x20, ++0xA3, 0x78, 0x60, 0x78, 0xDA, 0xF8, 0x04, 0x10, 0xDA, 0xF8, 0x08, 0xC0, 0x06, 0x92, 0x14, 0xF8, 0x03, 0x2B, 0x05, 0x93, ++0x5A, 0xF8, 0x10, 0x3B, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x21, 0xCD, 0xE9, 0x03, 0x0C, 0x32, 0x46, 0x36, 0x49, 0x80, 0x23, ++0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xAC, 0xFA, 0x4F, 0x45, 0x06, 0xF1, 0x01, 0x06, 0xC7, 0xD1, 0x13, 0x9B, 0x32, 0x4E, ++0x1D, 0x1F, 0x00, 0x24, 0x55, 0xF8, 0x04, 0x3F, 0xC3, 0xF3, 0x07, 0x22, 0x00, 0x92, 0xDB, 0xB2, 0x22, 0x46, 0x31, 0x46, ++0x01, 0x34, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x97, 0xFA, 0x10, 0x2C, 0xF0, 0xD1, 0x14, 0x9B, 0xDB, 0x06, 0x0D, 0xD5, ++0x15, 0x9B, 0x3B, 0xB1, 0x27, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x61, 0x43, 0xF4, 0xC0, 0x53, 0x11, 0x60, 0x13, 0x60, ++0x0A, 0x99, 0x13, 0x98, 0xFF, 0xF7, 0x0C, 0xFC, 0x22, 0x49, 0x23, 0x4A, 0x0B, 0x68, 0x23, 0x4E, 0x23, 0x4C, 0x24, 0x48, ++0x23, 0xF0, 0x02, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xEE, 0x43, 0x23, 0xF0, 0x09, 0x03, 0x43, 0xF4, 0x58, 0x53, ++0xA1, 0xF5, 0xD6, 0x41, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x74, 0x39, 0x02, 0xF5, 0xFF, 0x52, 0x1C, 0x32, 0x00, 0x23, ++0x4F, 0xF0, 0x80, 0x35, 0x33, 0x60, 0x25, 0x60, 0x03, 0x60, 0x0B, 0x60, 0x13, 0x68, 0x17, 0x49, 0x23, 0xF4, 0x7F, 0x43, ++0x00, 0xF5, 0x09, 0x40, 0x23, 0xF0, 0x80, 0x03, 0xFC, 0x30, 0x43, 0xF4, 0x80, 0x34, 0x13, 0x60, 0x14, 0x60, 0x03, 0x68, ++0x23, 0xF4, 0xC0, 0x53, 0x03, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x4F, 0xFA, 0x0D, 0xF2, 0xE4, 0x7D, 0xBD, 0xEC, ++0x04, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x23, 0x08, 0xEE, 0x90, 0x3A, 0x65, 0xE5, 0x00, 0xBF, 0xF0, 0x7A, 0x15, 0x00, ++0x1C, 0x7B, 0x15, 0x00, 0x04, 0x40, 0x34, 0x40, 0x80, 0x21, 0x34, 0x40, 0x5C, 0x20, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, ++0x4C, 0x40, 0x34, 0x40, 0x08, 0xB6, 0x33, 0x40, 0x3C, 0x7B, 0x15, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC4, 0x7A, 0x15, 0x00, ++0xF0, 0xB5, 0x07, 0x78, 0x43, 0x68, 0x83, 0xB0, 0x0E, 0x46, 0x3A, 0x46, 0x27, 0x49, 0x01, 0x93, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x22, 0xFA, 0x01, 0x9B, 0x30, 0x1F, 0x06, 0xF1, 0x3C, 0x01, 0x4F, 0xF0, 0x80, 0x32, 0x40, 0xF8, 0x04, 0x2F, ++0x88, 0x42, 0xFB, 0xD1, 0x06, 0xF1, 0x3F, 0x00, 0x06, 0xF1, 0x4F, 0x02, 0x00, 0x24, 0x00, 0xF8, 0x01, 0x4F, 0x82, 0x42, ++0xFB, 0xD1, 0x30, 0x46, 0x34, 0x65, 0x06, 0xF1, 0x94, 0x05, 0x40, 0xF8, 0x54, 0x4F, 0x00, 0x24, 0x40, 0xF8, 0x04, 0x4F, ++0xA8, 0x42, 0xFB, 0xD1, 0xBA, 0x09, 0x18, 0xD0, 0x15, 0x4C, 0xDF, 0xF8, 0x74, 0xC0, 0x21, 0x68, 0x14, 0x4D, 0x15, 0x4A, ++0x15, 0x48, 0x21, 0xF4, 0x00, 0x11, 0x21, 0x60, 0xF9, 0x09, 0x00, 0x29, 0x08, 0xBF, 0x62, 0x46, 0x2A, 0x60, 0x05, 0x68, ++0x11, 0x49, 0x12, 0x4C, 0x12, 0x4A, 0x01, 0xEA, 0x05, 0x01, 0x08, 0xBF, 0x22, 0x46, 0x0A, 0x43, 0x02, 0x60, 0x01, 0x93, ++0xFE, 0xF7, 0x08, 0xFC, 0x0E, 0x4A, 0x01, 0x9B, 0xD2, 0xF8, 0xBC, 0x44, 0x38, 0x46, 0x06, 0xF1, 0x40, 0x02, 0x31, 0x46, ++0xA0, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFE, 0xF7, 0x44, 0xBC, 0x50, 0x7B, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, ++0x10, 0x20, 0x34, 0x40, 0x76, 0x62, 0xF7, 0x0B, 0x1C, 0x20, 0x34, 0x40, 0xFF, 0x0F, 0x00, 0xE0, 0x00, 0x50, 0x98, 0x00, ++0x00, 0x90, 0x9B, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x76, 0x62, 0xB7, 0x0B, 0x17, 0x4B, 0x01, 0x22, 0x30, 0xB4, 0x1A, 0x60, ++0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0x08, 0xDB, ++0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x00, 0x2B, 0xF6, 0xDA, 0x0E, 0x4A, ++0x0C, 0x4B, 0x15, 0x68, 0x1C, 0x68, 0xC5, 0xF3, 0x10, 0x02, 0xED, 0x03, 0x44, 0xBF, 0x6F, 0xEA, 0x02, 0x42, 0x6F, 0xEA, ++0x12, 0x42, 0xC4, 0xF3, 0x10, 0x03, 0x02, 0x60, 0xE2, 0x03, 0x44, 0xBF, 0x6F, 0xEA, 0x03, 0x43, 0x6F, 0xEA, 0x13, 0x43, ++0x30, 0xBC, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x6C, 0x08, 0x62, 0x40, 0x90, 0x08, 0x62, 0x40, 0x8C, 0x08, 0x62, 0x40, ++0x30, 0xB4, 0x11, 0x4C, 0x11, 0x4D, 0x12, 0x4B, 0x04, 0xEA, 0x02, 0x42, 0xC1, 0xF3, 0x0E, 0x01, 0x0A, 0x43, 0x2A, 0x60, ++0x1A, 0x68, 0x00, 0xF0, 0x07, 0x00, 0x22, 0xF0, 0xE0, 0x62, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x00, 0x42, ++0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x1A, 0x68, ++0x22, 0xF0, 0x00, 0x42, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0xFF, 0x7F, 0x44, 0x05, 0x62, 0x40, ++0x28, 0x05, 0x62, 0x40, 0x38, 0xB5, 0x28, 0x4C, 0x28, 0x4A, 0x23, 0x68, 0x28, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x43, ++0x43, 0xF0, 0x80, 0x03, 0x23, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x03, 0x02, ++0x42, 0xF0, 0x02, 0x03, 0x0B, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x1D, 0x4B, ++0x42, 0xF0, 0x03, 0x02, 0x1A, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x19, 0x4A, ++0x13, 0x68, 0x98, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, ++0x98, 0x07, 0xF6, 0xD5, 0x13, 0x4C, 0x22, 0x68, 0x51, 0x00, 0x0E, 0xD4, 0x12, 0x4D, 0x29, 0x46, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x28, 0xF9, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x22, 0x68, 0x53, 0x00, ++0xF1, 0xD5, 0x0C, 0x4A, 0x0C, 0x49, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x03, 0x13, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0xBD, 0xE8, ++0x38, 0x40, 0x20, 0xF0, 0x13, 0xB9, 0x00, 0xBF, 0x08, 0x01, 0x60, 0x40, 0x08, 0x05, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, ++0x80, 0x40, 0x34, 0x40, 0x04, 0x22, 0x34, 0x40, 0x68, 0x7B, 0x15, 0x00, 0x04, 0x00, 0x62, 0x40, 0x7C, 0x7B, 0x15, 0x00, ++0x10, 0xB5, 0x0F, 0x4C, 0x0F, 0x4A, 0x23, 0x68, 0x0F, 0x48, 0x10, 0x49, 0x23, 0xF4, 0x80, 0x03, 0x23, 0x60, 0x13, 0x68, ++0x23, 0xF0, 0x03, 0x03, 0x13, 0x60, 0x13, 0x60, 0x03, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, ++0x01, 0x03, 0x0B, 0x60, 0x14, 0x20, 0xFC, 0xF7, 0x45, 0xF8, 0xBD, 0xE8, 0x10, 0x40, 0x06, 0x49, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0xE2, 0xB8, 0x04, 0x00, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, 0x08, 0x01, 0x60, 0x40, 0x08, 0x05, 0x62, 0x40, ++0x88, 0x7B, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0x07, 0x46, 0x10, 0x1A, 0x0E, 0x46, 0x9B, 0x46, 0xDD, 0xE9, ++0x0E, 0x54, 0x9D, 0xF8, 0x30, 0x90, 0x9D, 0xF8, 0x34, 0x80, 0x32, 0xF0, 0x65, 0xFD, 0x82, 0x46, 0xAB, 0xEB, 0x06, 0x00, ++0x32, 0xF0, 0x60, 0xFD, 0xBA, 0xF1, 0x00, 0x0F, 0x11, 0xD0, 0x07, 0xFA, 0x09, 0xF7, 0x07, 0xEE, 0x90, 0x7A, 0xB8, 0xEE, ++0xE7, 0x7A, 0x07, 0xEE, 0x90, 0xAA, 0xF8, 0xEE, 0xE7, 0x7A, 0xC7, 0xEE, 0x27, 0x6A, 0xFD, 0xEE, 0xE6, 0x7A, 0xCD, 0xED, ++0x01, 0x7A, 0x9D, 0xF9, 0x04, 0xA0, 0x85, 0xF8, 0x00, 0xA0, 0xA8, 0xB1, 0x06, 0xFA, 0x08, 0xF6, 0x07, 0xEE, 0x90, 0x6A, ++0xB8, 0xEE, 0xE7, 0x7A, 0x07, 0xEE, 0x90, 0x0A, 0xF8, 0xEE, 0xE7, 0x7A, 0xC7, 0xEE, 0x27, 0x6A, 0xFD, 0xEE, 0xE6, 0x7A, ++0xCD, 0xED, 0x01, 0x7A, 0x9D, 0xF9, 0x04, 0x30, 0x23, 0x70, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x03, 0x46, 0x23, 0x70, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0xA1, 0x4F, 0xA2, 0x4C, 0x3D, 0x68, 0xA2, 0x4E, ++0xAD, 0xB2, 0x25, 0x43, 0x2D, 0xED, 0x02, 0x8B, 0x3D, 0x60, 0x35, 0x68, 0x91, 0xB0, 0x25, 0xF0, 0x01, 0x05, 0x86, 0x46, ++0x35, 0x60, 0x8C, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x9B, 0x49, 0xCD, 0xF8, 0x1C, 0xE0, 0xCD, 0xE9, 0x08, 0x23, 0x08, 0xEE, ++0x10, 0xCA, 0x75, 0x46, 0x20, 0xF0, 0x72, 0xF8, 0x3B, 0x68, 0x9B, 0xB2, 0x23, 0x43, 0x3B, 0x60, 0x00, 0x2D, 0x00, 0xF0, ++0x16, 0x81, 0x00, 0x26, 0x34, 0x46, 0x35, 0x46, 0x0D, 0xF1, 0x34, 0x0B, 0x0D, 0xF1, 0x30, 0x0A, 0x32, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x96, 0xFE, 0xDD, 0xE9, 0x0C, 0x32, ++0x8A, 0x49, 0xCD, 0xE9, 0x00, 0x32, 0x4F, 0xF4, 0x00, 0x50, 0x23, 0x46, 0x2A, 0x46, 0x20, 0xF0, 0x4F, 0xF8, 0x0C, 0x9B, ++0x00, 0x2B, 0xC0, 0xF2, 0xA5, 0x80, 0x00, 0x2E, 0x00, 0xF0, 0xB9, 0x80, 0x01, 0x2E, 0x00, 0xF0, 0xDD, 0x80, 0x0D, 0x9B, ++0x15, 0xF1, 0x7C, 0x0F, 0xAC, 0xBF, 0x2A, 0x1F, 0x2A, 0x1D, 0x00, 0x2B, 0x80, 0xF2, 0xA1, 0x80, 0x01, 0x2E, 0x4F, 0xF0, ++0x02, 0x08, 0x00, 0xF0, 0xDA, 0x80, 0x7B, 0x2C, 0x00, 0xF3, 0xA1, 0x80, 0x23, 0x1D, 0x4F, 0xF0, 0x02, 0x09, 0xA3, 0xF1, ++0x80, 0x01, 0x38, 0x68, 0xC9, 0xB2, 0x09, 0x04, 0xA2, 0xF1, 0x80, 0x0C, 0x41, 0xEA, 0x0C, 0x61, 0x80, 0xB2, 0x01, 0x43, ++0x39, 0x60, 0x32, 0x21, 0x00, 0xBF, 0x01, 0x39, 0x89, 0xB2, 0x00, 0x29, 0xFA, 0xD1, 0x0F, 0xA9, 0x0E, 0xA8, 0xCD, 0xE9, ++0x05, 0x23, 0xFF, 0xF7, 0x55, 0xFE, 0xDD, 0xE9, 0x0E, 0x10, 0xDD, 0xE9, 0x05, 0x23, 0x01, 0x90, 0x00, 0x91, 0x4F, 0xF4, ++0x00, 0x50, 0x68, 0x49, 0x20, 0xF0, 0x0E, 0xF8, 0x0D, 0xF1, 0x2F, 0x03, 0x03, 0x93, 0x0D, 0xF1, 0x2E, 0x03, 0xCD, 0xE9, ++0x01, 0x93, 0xDD, 0xE9, 0x0C, 0x01, 0xDD, 0xE9, 0x0E, 0x23, 0xCD, 0xF8, 0x00, 0x80, 0xFF, 0xF7, 0x27, 0xFF, 0x9D, 0xF9, ++0x2F, 0x30, 0x9D, 0xF9, 0x2E, 0x20, 0x5E, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, 0xF6, 0xFF, 0x9D, 0xF9, 0x2F, 0x30, ++0x9D, 0xF9, 0x2E, 0x20, 0x39, 0x68, 0xE4, 0x1A, 0x6F, 0xF0, 0x7F, 0x03, 0x9C, 0x42, 0xB8, 0xBF, 0x1C, 0x46, 0xAD, 0x1A, ++0x7F, 0x2C, 0xA8, 0xBF, 0x7F, 0x24, 0x9D, 0x42, 0xB8, 0xBF, 0x1D, 0x46, 0x04, 0xEB, 0x03, 0x08, 0x7F, 0x2D, 0xA8, 0xBF, ++0x7F, 0x25, 0x5F, 0xFA, 0x88, 0xF8, 0xA5, 0xF1, 0x80, 0x02, 0x4F, 0xEA, 0x08, 0x43, 0x43, 0xEA, 0x02, 0x63, 0x89, 0xB2, ++0x0B, 0x43, 0x01, 0x36, 0x3B, 0x60, 0x07, 0x9B, 0xF6, 0xB2, 0xB3, 0x42, 0x5F, 0xFA, 0x82, 0xF9, 0x7F, 0xF4, 0x68, 0xAF, ++0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0xFE, 0xFD, ++0xDD, 0xE9, 0x0C, 0x13, 0x2A, 0x46, 0x01, 0x93, 0x00, 0x91, 0x23, 0x46, 0x3F, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, ++0xB7, 0xFF, 0x08, 0x9B, 0x83, 0xF8, 0x00, 0x90, 0x09, 0x9B, 0xDD, 0xE9, 0x0C, 0x12, 0x18, 0xEE, 0x10, 0x0A, 0x83, 0xF8, ++0x00, 0x80, 0xFF, 0xF7, 0x1D, 0xFE, 0x11, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0xB3, 0x01, 0x2E, ++0x29, 0xD0, 0x0D, 0x9B, 0x7B, 0x2D, 0xD4, 0xBF, 0x2A, 0x1D, 0x2A, 0x1F, 0x00, 0x2B, 0xFF, 0xF6, 0x5F, 0xAF, 0x01, 0x2E, ++0x4F, 0xF0, 0x02, 0x08, 0x26, 0xD0, 0x14, 0xF1, 0x7C, 0x0F, 0xFF, 0xF6, 0x5F, 0xAF, 0x23, 0x1F, 0x4F, 0xF0, 0x02, 0x09, ++0x5D, 0xE7, 0x0D, 0x9B, 0x00, 0x2B, 0xA5, 0xF1, 0x20, 0x02, 0x0A, 0xDA, 0x4F, 0xF0, 0x05, 0x08, 0xC1, 0x46, 0x04, 0xF1, ++0x20, 0x03, 0x52, 0xE7, 0x0D, 0x9B, 0x00, 0x2B, 0x05, 0xF1, 0x20, 0x02, 0xF4, 0xDB, 0x4F, 0xF0, 0x05, 0x08, 0xC1, 0x46, ++0xA4, 0xF1, 0x20, 0x03, 0x47, 0xE7, 0x6F, 0x2D, 0xD3, 0xDC, 0x0D, 0x9B, 0x00, 0x2B, 0x05, 0xF1, 0x10, 0x02, 0x4F, 0xF0, ++0x04, 0x08, 0x12, 0xDB, 0x14, 0xF1, 0x70, 0x0F, 0xD5, 0xDB, 0xA4, 0xF1, 0x10, 0x03, 0x4F, 0xF0, 0x04, 0x09, 0x36, 0xE7, ++0x15, 0xF1, 0x70, 0x0F, 0xFF, 0xF6, 0x1F, 0xAF, 0x0D, 0x9B, 0x00, 0x2B, 0xA5, 0xF1, 0x10, 0x02, 0x4F, 0xF0, 0x04, 0x08, ++0xEC, 0xDA, 0x6F, 0x2C, 0x3F, 0xF7, 0x23, 0xAF, 0x04, 0xF1, 0x10, 0x03, 0x4F, 0xF0, 0x04, 0x09, 0x23, 0xE7, 0x07, 0x9C, ++0x4F, 0xF0, 0x80, 0x08, 0x25, 0x46, 0xC1, 0x46, 0x0D, 0xF1, 0x34, 0x0B, 0x0D, 0xF1, 0x30, 0x0A, 0x7E, 0xE7, 0x00, 0xBF, ++0x4C, 0x40, 0x34, 0x40, 0x00, 0x00, 0x80, 0x80, 0x1C, 0x40, 0x34, 0x40, 0x94, 0x7B, 0x15, 0x00, 0xA8, 0x7B, 0x15, 0x00, ++0xCC, 0x7B, 0x15, 0x00, 0xF0, 0x7B, 0x15, 0x00, 0x0C, 0x7C, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x22, 0x4B, 0x23, 0x4E, ++0x1A, 0x68, 0x00, 0x25, 0x22, 0xF4, 0x7F, 0x52, 0x1A, 0x60, 0x98, 0x46, 0x2F, 0x46, 0x4F, 0xF0, 0x07, 0x09, 0x02, 0x20, ++0xFB, 0xF7, 0x86, 0xFE, 0x33, 0x68, 0xD8, 0xF8, 0x00, 0x40, 0xDA, 0x05, 0x54, 0xBF, 0x01, 0x37, 0x07, 0xF1, 0xFF, 0x37, ++0x7F, 0xB2, 0x1B, 0x06, 0x54, 0xBF, 0x01, 0x35, 0x05, 0xF1, 0xFF, 0x35, 0x00, 0x2F, 0x24, 0xF4, 0x7F, 0x54, 0xDC, 0xBF, ++0x7B, 0x42, 0x44, 0xEA, 0x83, 0x24, 0x6D, 0xB2, 0xD4, 0xBF, 0x44, 0xF4, 0x00, 0x54, 0x44, 0xEA, 0x87, 0x24, 0x00, 0x2D, ++0xDC, 0xBF, 0x6B, 0x42, 0x44, 0xEA, 0x83, 0x14, 0x09, 0xF1, 0xFF, 0x33, 0xCC, 0xBF, 0x44, 0xEA, 0x85, 0x14, 0x44, 0xF4, ++0x00, 0x74, 0x13, 0xF0, 0xFF, 0x09, 0xC8, 0xF8, 0x00, 0x40, 0xD0, 0xD1, 0x07, 0x49, 0x2B, 0x46, 0x3A, 0x46, 0x4F, 0xF4, ++0x00, 0x50, 0x1F, 0xF0, 0xF7, 0xFE, 0xC4, 0xF3, 0x87, 0x10, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x50, 0x40, 0x34, 0x40, ++0x14, 0x40, 0x34, 0x40, 0x34, 0x7C, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x4E, 0x4A, 0x4F, 0x4D, 0x13, 0x68, 0x87, 0xB0, ++0xC1, 0xF3, 0x03, 0x24, 0x03, 0x93, 0x23, 0xF0, 0x00, 0x43, 0x23, 0xF4, 0xE0, 0x03, 0x43, 0xEA, 0x04, 0x53, 0x43, 0xF0, ++0x0A, 0x03, 0x13, 0x60, 0x2C, 0x68, 0x48, 0x4B, 0x24, 0xF4, 0xC0, 0x54, 0xC1, 0xF3, 0x01, 0x62, 0x22, 0x43, 0x2A, 0x60, ++0x1A, 0x68, 0x01, 0xF0, 0x0F, 0x04, 0xC1, 0xF3, 0x03, 0x15, 0x42, 0xF0, 0x3F, 0x02, 0xA5, 0x42, 0x02, 0x94, 0xC1, 0xF3, ++0x03, 0x3A, 0x1A, 0x60, 0x5E, 0xD8, 0xDF, 0xF8, 0x04, 0x81, 0x3E, 0x4E, 0xDF, 0xF8, 0x00, 0xB1, 0x44, 0x19, 0x99, 0x46, ++0xEF, 0xB2, 0xD8, 0xF8, 0x00, 0x20, 0x22, 0xF4, 0xFF, 0x42, 0x42, 0xEA, 0x45, 0x22, 0x42, 0xF4, 0x40, 0x40, 0x42, 0xF4, ++0xE0, 0x31, 0xC8, 0xF8, 0x00, 0x00, 0x2A, 0x46, 0xC8, 0xF8, 0x00, 0x10, 0x4F, 0xF4, 0x00, 0x50, 0x33, 0x49, 0x1F, 0xF0, ++0xA9, 0xFE, 0x32, 0x68, 0x42, 0xF4, 0x80, 0x62, 0x32, 0x60, 0xDB, 0xF8, 0x00, 0x20, 0x42, 0xF0, 0x40, 0x02, 0xCB, 0xF8, ++0x00, 0x20, 0x32, 0x22, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0xFF, 0xF7, 0x5D, 0xFF, 0x04, 0xF8, ++0x01, 0x0B, 0x32, 0x68, 0x22, 0xF4, 0x80, 0x62, 0x32, 0x60, 0xD9, 0xF8, 0x00, 0x20, 0x22, 0xF0, 0x40, 0x02, 0xC9, 0xF8, ++0x00, 0x20, 0x32, 0x22, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0x0D, 0xF1, 0x17, 0x03, 0x01, 0x93, ++0x0D, 0xF1, 0x16, 0x03, 0x39, 0x46, 0x00, 0x93, 0x05, 0xAA, 0x0D, 0xF1, 0x15, 0x03, 0x50, 0x46, 0xFF, 0xF7, 0xE8, 0xFD, ++0x01, 0x35, 0x02, 0x9B, 0x9D, 0xF8, 0x16, 0xC0, 0x9D, 0xF8, 0x17, 0x00, 0x9D, 0xF8, 0x14, 0x10, 0x9D, 0xF8, 0x15, 0x20, ++0x84, 0xF8, 0x04, 0xC0, 0xEF, 0xB2, 0xBB, 0x42, 0x60, 0x72, 0xA1, 0x73, 0xE2, 0x74, 0xA8, 0xD2, 0x11, 0x4A, 0x0D, 0x48, ++0x13, 0x68, 0x0D, 0x49, 0x0A, 0x4C, 0x23, 0xF4, 0x7F, 0x43, 0x23, 0xF0, 0x80, 0x03, 0x13, 0x60, 0x43, 0xF4, 0x80, 0x33, ++0x13, 0x60, 0x03, 0x68, 0x23, 0xF4, 0xC0, 0x53, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x3F, 0x03, 0x0B, 0x60, 0x03, 0x9B, ++0x23, 0x60, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1C, 0x05, 0x62, 0x40, 0x04, 0x40, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, ++0x14, 0x40, 0x34, 0x40, 0x54, 0x7C, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, 0x5C, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, ++0x3C, 0x4D, 0x3D, 0x49, 0x81, 0x46, 0x89, 0xB0, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, 0x34, 0xFE, 0x2B, 0x68, 0xD9, 0xF8, ++0x00, 0x40, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE2, 0xB2, 0x04, 0xF0, 0x7F, 0x0A, 0xC4, 0xF3, 0x03, 0x18, 0x04, 0xF0, ++0x0F, 0x04, 0x4A, 0xDB, 0x33, 0x4D, 0x34, 0x4F, 0x2E, 0x68, 0x2B, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x2B, 0x60, 0xD7, 0xF8, ++0x00, 0xB0, 0x3B, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x3B, 0x60, 0x50, 0x46, 0xFF, 0xF7, 0xB2, 0xFC, 0xD9, 0xF8, 0x00, 0x10, ++0x01, 0xA8, 0xFF, 0xF7, 0x25, 0xFF, 0xFF, 0xF7, 0x0D, 0xFD, 0xC7, 0xF8, 0x00, 0xB0, 0x2B, 0x68, 0x2B, 0x68, 0x06, 0xF4, ++0x80, 0x76, 0x1E, 0x43, 0xA0, 0x45, 0x2E, 0x60, 0x26, 0xD8, 0x25, 0x48, 0x0D, 0xF1, 0x05, 0x03, 0xA4, 0xEB, 0x08, 0x04, ++0x43, 0x44, 0x01, 0xAA, 0x42, 0x44, 0x53, 0xFA, 0x84, 0xF4, 0x00, 0xEB, 0x08, 0x10, 0x15, 0x78, 0x53, 0x79, 0x92, 0xF8, ++0x0A, 0xC0, 0xD7, 0x7B, 0x16, 0x7D, 0x29, 0x06, 0x1B, 0x04, 0x01, 0xF0, 0x70, 0x41, 0x43, 0xEA, 0x0C, 0x63, 0x41, 0xEA, ++0x05, 0x51, 0x3B, 0x43, 0x01, 0x32, 0x09, 0x0E, 0x43, 0xEA, 0x06, 0x23, 0xA2, 0x42, 0x80, 0xF8, 0x07, 0x12, 0xC0, 0xF8, ++0x00, 0x32, 0x00, 0xF1, 0x10, 0x00, 0xE4, 0xD1, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0xF0, 0x0C, 0x0F, 0x08, 0xD1, ++0xA0, 0x45, 0xAF, 0xD9, 0x0E, 0x49, 0x0F, 0x48, 0x41, 0xF2, 0x7F, 0x02, 0x1F, 0xF0, 0xFA, 0xFF, 0xA8, 0xE7, 0x0B, 0x49, ++0x0C, 0x48, 0x41, 0xF2, 0x7E, 0x02, 0x1F, 0xF0, 0xF3, 0xFF, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEB, 0xDB, ++0x9C, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x7C, 0x15, 0x00, 0x00, 0x04, 0x60, 0x40, 0x18, 0x00, 0x58, 0x40, ++0x1C, 0x13, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x88, 0x7C, 0x15, 0x00, 0x78, 0x7C, 0x15, 0x00, 0x24, 0x4B, 0x25, 0x4A, ++0x06, 0x21, 0x10, 0xB4, 0xC3, 0xF8, 0x00, 0x11, 0x53, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x53, 0x60, 0x53, 0x68, 0x43, 0xF4, ++0x00, 0x33, 0x53, 0x60, 0x13, 0x6B, 0x03, 0xF0, 0x44, 0x03, 0x04, 0x2B, 0xFA, 0xD1, 0x1D, 0x4B, 0x1D, 0x4C, 0x1B, 0x68, ++0x1D, 0x48, 0x19, 0x49, 0xA4, 0xFB, 0x03, 0x43, 0x9B, 0x0C, 0x43, 0xF0, 0x00, 0x44, 0x44, 0xF4, 0xA0, 0x14, 0x43, 0xF4, ++0xA0, 0x13, 0x03, 0x60, 0x04, 0x60, 0x03, 0x60, 0x53, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x43, 0xF4, 0xC4, 0x33, 0x43, 0xF0, ++0x02, 0x03, 0x4F, 0xF4, 0x80, 0x50, 0x53, 0x60, 0xC1, 0xF8, 0x34, 0x01, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, ++0x4B, 0x6F, 0x43, 0xF0, 0x01, 0x03, 0x4B, 0x67, 0x53, 0x6C, 0x43, 0xF0, 0x08, 0x43, 0x53, 0x64, 0x53, 0x6D, 0x23, 0xF4, ++0x00, 0x13, 0x53, 0x65, 0x53, 0x6D, 0x43, 0xF0, 0x02, 0x03, 0x53, 0x65, 0x53, 0x6D, 0x23, 0xF4, 0x00, 0x63, 0x53, 0x65, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, 0x18, 0x13, 0x17, 0x00, 0x83, 0xDE, 0x1B, 0x43, ++0x08, 0x00, 0x58, 0x40, 0x3B, 0x4A, 0x3C, 0x48, 0x13, 0x68, 0x3C, 0x49, 0xDF, 0xF8, 0x24, 0xC1, 0x43, 0xF0, 0x7C, 0x53, ++0xF0, 0xB4, 0x13, 0x60, 0x39, 0x4C, 0x3A, 0x4B, 0x23, 0x60, 0x03, 0xF1, 0xBE, 0x43, 0xA3, 0xF5, 0x69, 0x03, 0xA3, 0xF6, ++0x77, 0x33, 0x03, 0x60, 0x36, 0x4B, 0x0B, 0x60, 0x36, 0x4F, 0x37, 0x4E, 0x37, 0x4D, 0x40, 0xF6, 0x77, 0x13, 0xCC, 0xF8, ++0x00, 0x30, 0x36, 0x4B, 0x3B, 0x60, 0x04, 0xF5, 0x00, 0x24, 0x01, 0xF5, 0x2F, 0x11, 0x00, 0xF5, 0x2F, 0x10, 0x49, 0xF2, ++0x02, 0x43, 0x02, 0xF5, 0x00, 0x22, 0x33, 0x60, 0x0C, 0x34, 0x30, 0x4B, 0x2B, 0x60, 0x01, 0xF5, 0x05, 0x61, 0x00, 0xF6, ++0x58, 0x00, 0x02, 0xF6, 0x7C, 0x02, 0x07, 0xF5, 0x2F, 0x17, 0x2C, 0x4D, 0x25, 0x60, 0x07, 0xF6, 0x68, 0x07, 0x0B, 0x60, ++0x06, 0xF5, 0x37, 0x16, 0x03, 0x60, 0x13, 0x60, 0x40, 0xF6, 0x34, 0x03, 0x3B, 0x60, 0x06, 0xF2, 0xE4, 0x46, 0x26, 0x4B, ++0x33, 0x60, 0x01, 0xF5, 0xFE, 0x31, 0x03, 0xF1, 0x50, 0x53, 0x88, 0x31, 0x03, 0xF5, 0x54, 0x13, 0x0F, 0x33, 0x0B, 0x60, ++0x00, 0xF5, 0xFE, 0x30, 0x03, 0xF1, 0x48, 0x43, 0x1F, 0x4D, 0x00, 0xF5, 0x90, 0x70, 0x02, 0xF5, 0xFE, 0x32, 0xA3, 0xF5, ++0x78, 0x13, 0x02, 0xF5, 0xB4, 0x72, 0xA3, 0xF2, 0x1F, 0x63, 0x4F, 0xF0, 0x36, 0x36, 0x2B, 0x60, 0x06, 0x60, 0x4F, 0xF4, ++0x7F, 0x40, 0x10, 0x60, 0x04, 0xF5, 0x01, 0x34, 0x02, 0xF1, 0xAC, 0x42, 0x20, 0x34, 0x15, 0x4B, 0x15, 0x4D, 0x25, 0x60, ++0xA2, 0xF5, 0xB5, 0x12, 0x45, 0xF2, 0x55, 0x30, 0xA2, 0xF6, 0x8A, 0x62, 0xC1, 0xF8, 0xA8, 0x00, 0xF0, 0xBC, 0x1A, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x0C, 0x00, 0x58, 0x40, 0x2C, 0x40, 0x34, 0x40, 0x30, 0x40, 0x34, 0x40, 0x04, 0x01, 0x58, 0x40, ++0xFB, 0x23, 0x09, 0x00, 0x08, 0x51, 0x2E, 0x1A, 0x24, 0x40, 0x34, 0x40, 0x28, 0x40, 0x34, 0x40, 0x8C, 0x04, 0x60, 0x40, ++0x94, 0xC5, 0x2E, 0x00, 0x34, 0x08, 0x50, 0x00, 0x58, 0x00, 0x7E, 0x02, 0x13, 0x20, 0x20, 0x20, 0xA0, 0x05, 0x62, 0x40, ++0x1C, 0x05, 0x62, 0x40, 0x0F, 0x12, 0x15, 0x0C, 0x20, 0x40, 0x34, 0x40, 0x63, 0x49, 0x64, 0x4A, 0x0B, 0x68, 0x23, 0xF4, ++0x00, 0x63, 0xF0, 0xB4, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0xDF, 0xF8, 0x6C, 0xC1, 0x5B, 0x4A, 0xDC, 0xF8, 0x00, 0x30, 0x5A, 0x4F, 0x5B, 0x4E, ++0x23, 0xF4, 0x80, 0x53, 0xCC, 0xF8, 0x00, 0x30, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, 0xDC, 0xF8, 0x00, 0x30, ++0x43, 0xF4, 0x80, 0x63, 0xCC, 0xF8, 0x00, 0x30, 0xDC, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x00, 0x63, 0xCC, 0xF8, 0x00, 0x30, ++0x62, 0x46, 0xFF, 0x25, 0x2B, 0x1D, 0x2C, 0x46, 0xDD, 0xB2, 0x29, 0x46, 0x38, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, ++0x0B, 0x43, 0x13, 0x60, 0x50, 0xF8, 0x04, 0x3B, 0x33, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, ++0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, 0xFC, 0xD5, 0x01, 0x39, 0xC9, 0xB2, 0xA1, 0x42, 0xE8, 0xD1, ++0x8F, 0x2D, 0x07, 0xF1, 0x10, 0x07, 0xDF, 0xD1, 0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x80, 0x63, 0xCC, 0xF8, 0x00, 0x30, ++0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x36, 0x4D, 0x37, 0x49, 0x2A, 0x68, 0x39, 0x48, ++0x39, 0x4C, 0x22, 0xF4, 0x00, 0x62, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, ++0x80, 0x72, 0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x50, 0xF8, 0x04, 0x2F, 0x22, 0x60, ++0x0A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, ++0xFC, 0xD5, 0x01, 0x33, 0x20, 0x2B, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x1F, 0x4C, 0x24, 0x48, 0x22, 0x68, 0x24, 0x49, 0x24, 0x4D, 0x22, 0xF4, ++0x80, 0x72, 0x22, 0x60, 0x02, 0x68, 0x22, 0xF0, 0x02, 0x02, 0x02, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x62, 0x0A, 0x60, ++0x32, 0x22, 0x2B, 0x60, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0x13, 0x49, 0x13, 0x4A, 0x08, 0x68, ++0x1A, 0x4D, 0x1B, 0x4C, 0x1B, 0x4B, 0x40, 0xF4, 0x80, 0x50, 0x08, 0x60, 0x08, 0x68, 0x40, 0xF4, 0x00, 0x60, 0x08, 0x60, ++0x11, 0x68, 0x41, 0xF4, 0x00, 0x71, 0x11, 0x60, 0x11, 0x68, 0x41, 0xF4, 0x80, 0x71, 0x11, 0x60, 0x2A, 0x68, 0x42, 0xF4, ++0x80, 0x52, 0x2A, 0x60, 0x22, 0x68, 0x22, 0xF4, 0x80, 0x22, 0x22, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x00, 0x52, 0x1A, 0x60, ++0x1A, 0x68, 0x42, 0xF0, 0x80, 0x42, 0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x60, 0x40, 0x34, 0x40, 0x6C, 0x40, 0x34, 0x40, ++0x1C, 0x13, 0x17, 0x00, 0x64, 0x40, 0x34, 0x40, 0x18, 0x18, 0x17, 0x00, 0x70, 0x40, 0x34, 0x40, 0x18, 0x00, 0x58, 0x40, ++0x58, 0x40, 0x34, 0x40, 0x08, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, 0x1C, 0x20, 0x34, 0x40, ++0x10, 0xB5, 0x09, 0x4C, 0x82, 0xB0, 0xD4, 0xF8, 0xC0, 0x34, 0x01, 0x90, 0x98, 0x47, 0xD4, 0xF8, 0xC4, 0x34, 0x98, 0x47, ++0xD4, 0xF8, 0xC8, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0xCC, 0x34, 0x00, 0x21, 0x01, 0xA8, 0x98, 0x47, 0x02, 0xB0, 0x10, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x2D, 0x4C, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x17, 0xD0, 0x0F, 0x24, 0x4F, 0xF4, ++0x00, 0x62, 0x11, 0x46, 0x29, 0x48, 0xFD, 0xF7, 0x61, 0xFA, 0x4F, 0xF4, 0x40, 0x72, 0x28, 0x48, 0x00, 0x21, 0xFD, 0xF7, ++0x5B, 0xFA, 0x21, 0x46, 0x26, 0x48, 0xFD, 0xF7, 0x2F, 0xFA, 0x02, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x24, 0x48, 0x11, 0x46, ++0xFD, 0xF7, 0x50, 0xBA, 0x04, 0xF0, 0x2E, 0xFD, 0x22, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0xC3, 0xF8, 0x80, 0x20, 0xBF, 0xF3, ++0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0x1F, 0x48, 0x1F, 0xF0, 0x52, 0xFB, 0x1E, 0x4A, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF0, ++0x02, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x13, 0x69, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x61, 0x13, 0x69, 0xDB, 0x07, 0xFC, 0xD4, ++0x18, 0x48, 0x1F, 0xF0, 0x41, 0xFB, 0x18, 0x4A, 0x18, 0x48, 0x4F, 0xF4, 0x00, 0x21, 0xFD, 0xF7, 0x2B, 0xFA, 0x17, 0x4B, ++0x4F, 0xF4, 0x80, 0x61, 0x4F, 0xF4, 0x00, 0x02, 0xC3, 0xF8, 0x28, 0x11, 0xC3, 0xF8, 0x18, 0x21, 0x23, 0x68, 0x1B, 0x78, ++0x02, 0x2B, 0xB5, 0xD1, 0x04, 0xF0, 0xB6, 0xFE, 0x00, 0x28, 0xB1, 0xD0, 0x0F, 0x4B, 0x10, 0x48, 0xD3, 0xF8, 0x00, 0x41, ++0x21, 0x46, 0x1F, 0xF0, 0x23, 0xFB, 0xAA, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x0C, 0x88, 0x01, 0x50, 0x14, 0x88, 0x01, 0x50, ++0x00, 0x70, 0x01, 0x50, 0x08, 0x70, 0x01, 0x50, 0x00, 0xE1, 0x00, 0xE0, 0x9C, 0x7C, 0x15, 0x00, 0x00, 0x00, 0x20, 0x40, ++0xA8, 0x7C, 0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x90, 0x01, 0x50, 0x00, 0x00, 0x10, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0xB8, 0x7C, 0x15, 0x00, 0x38, 0xB5, 0x36, 0x4C, 0x36, 0x48, 0x44, 0x22, 0x00, 0x21, 0xFB, 0xF7, 0x91, 0xF8, 0x23, 0x68, ++0x1A, 0x07, 0xC3, 0xF3, 0xC0, 0x01, 0x51, 0xD5, 0x22, 0x46, 0x00, 0xBF, 0x13, 0x68, 0xDB, 0x06, 0xFB, 0xD5, 0x30, 0x4D, ++0x30, 0x48, 0x29, 0x68, 0x30, 0x4B, 0x00, 0x68, 0x30, 0x4A, 0xC1, 0xF8, 0x44, 0x02, 0x00, 0x21, 0x19, 0x60, 0x11, 0x60, ++0x19, 0x68, 0x2E, 0x48, 0x2E, 0x4C, 0x21, 0xF0, 0x03, 0x01, 0x41, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, ++0x0C, 0x01, 0x41, 0xF0, 0x08, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x40, 0x71, 0x41, 0xF4, 0x00, 0x71, 0x19, 0x60, ++0x19, 0x68, 0x21, 0xF4, 0x40, 0x61, 0x41, 0xF4, 0x00, 0x61, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x40, 0x51, 0x41, 0xF4, ++0x00, 0x51, 0x19, 0x60, 0x11, 0x68, 0x21, 0xF0, 0x40, 0x51, 0x41, 0xF0, 0x00, 0x51, 0x11, 0x60, 0x11, 0x68, 0x21, 0xF0, ++0x40, 0x41, 0x41, 0xF0, 0x00, 0x41, 0x11, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x32, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x40, 0x22, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x12, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x02, 0x1A, 0x60, ++0x1A, 0x68, 0x42, 0xF0, 0x40, 0x72, 0x1A, 0x60, 0x04, 0x60, 0x38, 0xBD, 0x23, 0x68, 0x09, 0x4D, 0x43, 0xF0, 0x08, 0x03, ++0x23, 0x60, 0x28, 0x68, 0x4F, 0xF4, 0x12, 0x72, 0xFB, 0xF7, 0x30, 0xF8, 0x23, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x23, 0x60, ++0xA4, 0xE7, 0x00, 0xBF, 0x80, 0x40, 0x04, 0x40, 0x04, 0x35, 0x17, 0x00, 0x00, 0x38, 0x18, 0x00, 0x84, 0x1A, 0x17, 0x00, ++0x14, 0x41, 0x04, 0x40, 0x18, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x33, 0x1F, 0x00, 0xC0, 0x0C, 0x4B, 0x10, 0xB5, ++0x1C, 0x68, 0x14, 0xF4, 0xF8, 0x54, 0x00, 0xD1, 0x10, 0xBD, 0x60, 0x08, 0x1E, 0xF0, 0x02, 0xF8, 0x08, 0x4A, 0x09, 0x49, ++0x09, 0x4B, 0x0C, 0x60, 0x14, 0x60, 0x1A, 0x78, 0x00, 0x2A, 0xF3, 0xD0, 0x07, 0x4A, 0x01, 0x21, 0x59, 0x70, 0x13, 0x68, ++0x0B, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x1C, 0x41, 0x04, 0x40, 0x08, 0x41, 0x04, 0x40, 0x10, 0x41, 0x04, 0x40, ++0x3C, 0x36, 0x17, 0x00, 0x10, 0x00, 0x58, 0x40, 0x2D, 0xE9, 0xF8, 0x4F, 0x29, 0x4B, 0x06, 0x46, 0x53, 0xF8, 0x20, 0x00, ++0x1E, 0xF0, 0x04, 0xF8, 0x27, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x26, 0x4B, 0xD3, 0xF8, 0x00, 0xA0, 0xDA, 0xF8, ++0x3C, 0x32, 0x0A, 0xF5, 0x0F, 0x7B, 0x8B, 0xB3, 0x23, 0x4D, 0xDF, 0xF8, 0x98, 0x90, 0xDF, 0xF8, 0x98, 0x80, 0x05, 0xF2, ++0x14, 0x57, 0x1D, 0xE0, 0x95, 0xF8, 0x10, 0x35, 0x85, 0xF8, 0x11, 0x45, 0x01, 0x33, 0xA9, 0xFB, 0x03, 0x24, 0xA4, 0x09, ++0x04, 0xEB, 0xC4, 0x04, 0x04, 0xEB, 0xC4, 0x04, 0x1C, 0x1B, 0x85, 0xF8, 0x10, 0x45, 0x1E, 0xF0, 0xA1, 0xF8, 0xD8, 0xF8, ++0x00, 0x20, 0x05, 0xEB, 0x04, 0x11, 0x02, 0x44, 0xC1, 0xE9, 0x01, 0x26, 0x38, 0x46, 0x1E, 0xF0, 0x53, 0xF8, 0xDA, 0xF8, ++0x3C, 0x32, 0x5B, 0xB1, 0x95, 0xF8, 0x11, 0x15, 0x95, 0xF8, 0x12, 0x25, 0x91, 0x42, 0x58, 0x46, 0x01, 0xF1, 0x01, 0x04, ++0xD8, 0xD3, 0x0D, 0x48, 0x01, 0xF0, 0x54, 0xF8, 0x08, 0x4B, 0x01, 0x24, 0x1C, 0x60, 0x20, 0x20, 0x08, 0x36, 0x1D, 0xF0, ++0x9B, 0xFF, 0x04, 0xFA, 0x06, 0xF6, 0x08, 0x4B, 0x06, 0xF4, 0xF8, 0x56, 0x1E, 0x60, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, ++0x80, 0x7E, 0x15, 0x00, 0x4C, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x58, 0x58, 0x17, 0x00, 0xCC, 0x7C, 0x15, 0x00, ++0x0C, 0x41, 0x04, 0x40, 0xE7, 0x87, 0x45, 0xCA, 0x84, 0x1A, 0x17, 0x00, 0x1D, 0x4B, 0x10, 0xB5, 0x1C, 0x68, 0xA0, 0x06, ++0x2C, 0xD4, 0xE1, 0x06, 0x20, 0xD4, 0xA2, 0x07, 0x16, 0xD4, 0x63, 0x00, 0x08, 0xD5, 0x19, 0x4B, 0x01, 0x20, 0xD3, 0xF8, ++0x78, 0x34, 0x98, 0x47, 0x17, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x00, 0x2C, 0x00, 0xDB, 0x10, 0xBD, 0x13, 0x4B, ++0xD3, 0xF8, 0x68, 0x34, 0x98, 0x47, 0x12, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x80, 0x50, ++0x1D, 0xF0, 0x5E, 0xFF, 0x0E, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0xE0, 0xE7, 0x0C, 0x49, 0x0B, 0x4A, 0x10, 0x23, 0x0B, 0x60, ++0x4F, 0xF4, 0x00, 0x10, 0x13, 0x60, 0x1D, 0xF0, 0x51, 0xFF, 0xD4, 0xE7, 0x07, 0x49, 0x06, 0x4A, 0x20, 0x23, 0x0B, 0x60, ++0x4F, 0xF4, 0x80, 0x10, 0x13, 0x60, 0x1D, 0xF0, 0x47, 0xFF, 0xC8, 0xE7, 0x1C, 0x41, 0x04, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x10, 0x41, 0x04, 0x40, 0x06, 0x4A, 0x07, 0x49, 0x12, 0x68, 0xD2, 0xF8, 0x24, 0x02, 0x20, 0x23, ++0x0B, 0x60, 0x08, 0xB1, 0x01, 0x20, 0x70, 0x47, 0x03, 0x4A, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x38, 0x18, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x15, 0x4C, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x14, 0x4B, ++0x18, 0x68, 0xD0, 0xF8, 0x24, 0x32, 0xBB, 0xB1, 0x00, 0xF5, 0x09, 0x70, 0x1E, 0xF0, 0x02, 0xF8, 0x10, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x22, 0x60, 0x01, 0xDB, 0x14, 0x30, 0x10, 0xBD, 0x00, 0x28, 0xFB, 0xD1, ++0x0B, 0x49, 0x0C, 0x48, 0x40, 0xF2, 0x92, 0x32, 0x1F, 0xF0, 0x00, 0xFC, 0x14, 0x20, 0x10, 0xBD, 0x06, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x22, 0x60, 0xF5, 0xDA, 0xEE, 0xE7, 0x00, 0xBF, 0x54, 0x40, 0x04, 0x40, ++0x00, 0x38, 0x18, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xE4, 0x7C, 0x15, 0x00, 0x10, 0xB5, 0x0A, 0x4C, ++0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x09, 0x4B, 0x1B, 0x68, 0xD3, 0xF8, 0x14, 0x02, 0x40, 0xB1, 0x03, 0xF5, 0x05, 0x70, ++0x1D, 0xF0, 0xCC, 0xFF, 0x01, 0x23, 0x23, 0x60, 0x00, 0xB1, 0x04, 0x30, 0x10, 0xBD, 0x01, 0x23, 0x23, 0x60, 0x10, 0xBD, ++0x58, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x01, 0x4B, 0x08, 0x22, 0x1A, 0x60, 0x70, 0x47, ++0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x41, 0x04, 0x40, ++0x01, 0x4B, 0x80, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x00, 0x41, 0x04, 0x40, 0xF8, 0xB5, 0x04, 0x46, 0x40, 0x89, 0x29, 0x4F, ++0x10, 0x30, 0x1D, 0xF0, 0xA3, 0xFB, 0x3E, 0x68, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x22, 0xDB, 0xA3, 0x88, ++0x62, 0x89, 0xE0, 0x88, 0xAB, 0x80, 0x00, 0x21, 0x0C, 0x23, 0x2B, 0x81, 0x6A, 0x81, 0xE8, 0x80, 0x29, 0x60, 0xE3, 0x18, ++0x62, 0xB1, 0x01, 0x3A, 0x22, 0xF0, 0x03, 0x02, 0x10, 0x32, 0x14, 0x44, 0x05, 0xF1, 0x08, 0x02, 0x53, 0xF8, 0x04, 0x1B, ++0x42, 0xF8, 0x04, 0x1F, 0xA3, 0x42, 0xF9, 0xD1, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x05, 0xF1, 0x0C, 0x00, ++0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0xD8, 0xBA, 0x00, 0x28, 0xDA, 0xD1, 0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x6F, 0x42, ++0x1F, 0xF0, 0x82, 0xFB, 0x3E, 0x68, 0xD2, 0xE7, 0x0D, 0x28, 0x0D, 0xD8, 0x0B, 0x28, 0xEB, 0xD9, 0x0C, 0x49, 0x0E, 0x48, ++0x4F, 0xF4, 0x90, 0x62, 0x1F, 0xF0, 0x76, 0xFB, 0x05, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0xBE, 0xBA, ++0x06, 0x49, 0x09, 0x48, 0xBB, 0x22, 0x1F, 0xF0, 0x6B, 0xFB, 0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x90, 0x62, 0x1F, 0xF0, ++0x65, 0xFB, 0xED, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x7C, 0x15, 0x00, 0x20, 0x7D, 0x15, 0x00, ++0x10, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x05, 0x46, 0x40, 0x89, 0x2B, 0x4F, 0x10, 0x30, 0x1D, 0xF0, 0x43, 0xFB, 0x3E, 0x68, ++0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x2A, 0xDB, 0xAB, 0x88, 0x6A, 0x89, 0xEF, 0x88, 0xA3, 0x80, 0x00, 0x21, ++0x0C, 0x23, 0x23, 0x81, 0x62, 0x81, 0xE7, 0x80, 0x21, 0x60, 0xEB, 0x18, 0x62, 0xB1, 0x01, 0x3A, 0x22, 0xF0, 0x03, 0x02, ++0x10, 0x32, 0x2A, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x53, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0F, 0x93, 0x42, 0xF9, 0xD1, ++0x1A, 0x4A, 0x53, 0x7D, 0x59, 0x1C, 0x51, 0x75, 0x2B, 0x81, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x12, 0xDB, 0x17, 0x4B, ++0x04, 0x22, 0x04, 0xF1, 0x0C, 0x00, 0x1A, 0x60, 0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0x70, 0xBA, 0x00, 0x28, 0xD2, 0xD1, ++0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x8E, 0x42, 0x1F, 0xF0, 0x1A, 0xFB, 0x3E, 0x68, 0xCA, 0xE7, 0x0D, 0x2F, 0x08, 0xD8, ++0x0B, 0x2F, 0xE8, 0xD9, 0x0C, 0x49, 0x0E, 0x48, 0x40, 0xF2, 0xA3, 0x42, 0x1F, 0xF0, 0x0E, 0xFB, 0xE1, 0xE7, 0x09, 0x49, ++0x0B, 0x48, 0xBB, 0x22, 0x1F, 0xF0, 0x08, 0xFB, 0x06, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xA3, 0x42, 0x1F, 0xF0, 0x02, 0xFB, ++0xD5, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x04, 0x35, 0x17, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0x79, 0x15, 0x00, ++0xFC, 0x7C, 0x15, 0x00, 0x20, 0x7D, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x0B, 0x4C, 0x23, 0x68, 0x9A, 0x07, ++0x0A, 0xD5, 0x0A, 0x4F, 0x0A, 0x4E, 0x02, 0x25, 0x38, 0x68, 0x35, 0x60, 0x04, 0x30, 0xFF, 0xF7, 0x8B, 0xFF, 0x23, 0x68, ++0x9B, 0x07, 0xF7, 0xD4, 0x4F, 0xF0, 0x80, 0x50, 0x1D, 0xF0, 0x0C, 0xFE, 0x04, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0xF8, 0xBD, ++0x04, 0x41, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x47, ++0xDF, 0xF8, 0x20, 0x93, 0xD9, 0xF8, 0x00, 0x20, 0x13, 0x78, 0x03, 0x2B, 0x82, 0xB0, 0x04, 0x46, 0x00, 0xF0, 0x16, 0x81, ++0x00, 0x27, 0x3E, 0x46, 0x01, 0x2B, 0x00, 0xF0, 0xC2, 0x80, 0x02, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0x00, 0xF0, 0xD3, 0x80, ++0x62, 0x89, 0xA3, 0x88, 0x33, 0x80, 0xF2, 0x80, 0x7A, 0xB9, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x03, 0x2B, 0x1C, 0xD0, ++0x02, 0x2B, 0x2F, 0xD0, 0x01, 0x2B, 0x00, 0xF0, 0x89, 0x80, 0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x1D, 0xF0, ++0x41, 0xBA, 0xA3, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x20, 0x81, 0x06, 0xF1, 0x0C, 0x00, ++0x04, 0xF1, 0x0C, 0x01, 0x31, 0xF0, 0x40, 0xFD, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x03, 0x2B, 0xE2, 0xD1, 0x9B, 0x4E, ++0x33, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x9A, 0x4B, 0x18, 0x68, 0x39, 0x1F, 0x00, 0xF5, 0x03, 0x70, 0x1D, 0xF0, 0x36, 0xFE, ++0x97, 0x4B, 0x01, 0x21, 0x02, 0x22, 0x31, 0x60, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x02, 0x2B, 0xCF, 0xD1, ++0x60, 0x89, 0x10, 0xF0, 0x03, 0x03, 0x40, 0xF0, 0xE9, 0x80, 0x19, 0x46, 0x9C, 0x46, 0x90, 0x4E, 0x42, 0xF2, 0x34, 0x03, ++0xF2, 0x5A, 0xB2, 0xF5, 0xC3, 0x7F, 0x00, 0xF2, 0xFD, 0x80, 0x57, 0x1C, 0xBF, 0xB2, 0x4F, 0xEA, 0xC2, 0x0E, 0x8B, 0x4B, ++0xA8, 0xF8, 0x0C, 0x20, 0xD3, 0xF8, 0x00, 0xA0, 0x00, 0xF1, 0x10, 0x03, 0x0A, 0xEB, 0x0E, 0x00, 0x0C, 0xEB, 0x03, 0x02, ++0x45, 0x60, 0x2A, 0xF8, 0x0E, 0x20, 0xC2, 0x78, 0x02, 0xF0, 0x31, 0x02, 0x42, 0xF0, 0x04, 0x02, 0xC2, 0x70, 0x96, 0xF8, ++0x02, 0x2C, 0x42, 0xF2, 0x34, 0x0C, 0x0B, 0x44, 0x01, 0x32, 0x01, 0x21, 0x4F, 0xF0, 0x00, 0x0E, 0x26, 0xF8, 0x0C, 0x70, ++0x86, 0xF8, 0x02, 0x2C, 0xC8, 0xE9, 0x01, 0x03, 0x88, 0xF8, 0x0E, 0x10, 0xC8, 0xF8, 0x00, 0xE0, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x76, 0x4B, 0x19, 0x60, 0x76, 0x4E, 0x76, 0x48, 0x33, 0x68, 0x41, 0x46, 0x01, 0x33, ++0x33, 0x60, 0x1D, 0xF0, 0xE3, 0xFD, 0x74, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x33, 0x68, 0x33, 0xB1, 0x6E, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x01, 0x2B, ++0x7F, 0xF4, 0x77, 0xAF, 0x01, 0xF0, 0xF2, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x0C, 0x81, 0xA1, 0x7A, 0x68, 0x4A, 0x0C, 0x31, ++0x29, 0x70, 0x61, 0x89, 0x0C, 0x31, 0x00, 0x27, 0x09, 0x12, 0x11, 0x26, 0x69, 0x70, 0xAE, 0x70, 0xEF, 0x70, 0x61, 0x89, ++0x86, 0x68, 0x47, 0x60, 0x10, 0x31, 0xC1, 0xF3, 0x0B, 0x01, 0x32, 0x40, 0x0A, 0x43, 0x42, 0xF0, 0x00, 0x42, 0x05, 0x60, ++0x82, 0x60, 0x03, 0xF0, 0x35, 0xF8, 0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x1D, 0xF0, 0x99, 0xB9, 0x63, 0x89, ++0x6C, 0x2B, 0x40, 0xF2, 0x8C, 0x80, 0x58, 0x4B, 0x1B, 0x68, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x05, 0x46, ++0x00, 0x2D, 0x00, 0xF0, 0x8A, 0x80, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0xF1, 0x04, 0x06, 0x7F, 0xF4, ++0x2D, 0xAF, 0x63, 0x89, 0x6C, 0x2B, 0x7A, 0xD9, 0x4D, 0x4B, 0x1B, 0x68, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, ++0x05, 0x46, 0x00, 0x2D, 0x75, 0xD0, 0x42, 0x4A, 0x42, 0xF2, 0x24, 0x03, 0xD3, 0x58, 0x00, 0x2B, 0x00, 0xF0, 0x9A, 0x80, ++0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x3D, 0x4E, 0x42, 0x48, ++0x33, 0x68, 0x01, 0x33, 0x33, 0x60, 0x1D, 0xF0, 0xB7, 0xFD, 0x33, 0x68, 0x80, 0x46, 0x33, 0xB1, 0x37, 0x4A, 0x01, 0x3B, ++0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xA3, 0x7A, 0x0C, 0x33, 0x2B, 0x70, 0x63, 0x89, 0x0C, 0x33, ++0x1B, 0x12, 0x11, 0x22, 0x6B, 0x70, 0x00, 0x23, 0xAA, 0x70, 0xEB, 0x70, 0x2E, 0x1D, 0xF3, 0xE6, 0x28, 0x4D, 0x2B, 0x68, ++0x00, 0x2B, 0xFC, 0xD0, 0x27, 0x4B, 0x18, 0x68, 0xD0, 0xF8, 0x04, 0x32, 0xD3, 0xB1, 0x00, 0xF5, 0x01, 0x70, 0x1D, 0xF0, ++0x93, 0xFD, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x2A, 0x60, 0xC0, 0xF2, 0x8B, 0x80, ++0x07, 0x1D, 0xD9, 0xF8, 0x00, 0x20, 0x3E, 0x46, 0x27, 0x4B, 0xB3, 0x60, 0x13, 0x78, 0xCD, 0xE6, 0xC3, 0xF1, 0x04, 0x03, ++0x5F, 0xFA, 0x83, 0xFC, 0x61, 0x46, 0x12, 0xE7, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x01, 0x21, 0x00, 0x2B, ++0x29, 0x60, 0xC0, 0xF2, 0x82, 0x80, 0x04, 0x26, 0x37, 0x46, 0xE9, 0xE7, 0xB2, 0xF5, 0x80, 0x6F, 0x7F, 0xF6, 0xDC, 0xAE, ++0x4F, 0xF4, 0xB1, 0x62, 0x1A, 0x49, 0x1B, 0x48, 0x1F, 0xF0, 0x76, 0xF9, 0x62, 0x89, 0xD3, 0xE6, 0x4F, 0xF0, 0x00, 0x0E, ++0x72, 0x46, 0x01, 0x27, 0x01, 0xE7, 0x01, 0xF0, 0xCF, 0xFF, 0x05, 0x46, 0x76, 0xE7, 0x05, 0xF0, 0x2B, 0xF8, 0x05, 0x46, ++0x87, 0xE7, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x11, 0x48, 0x00, 0xF0, 0x1D, 0xFD, 0xB2, 0xE6, 0x38, 0x36, 0x17, 0x00, ++0x50, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x00, 0x41, 0x04, 0x40, 0x7C, 0x36, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xF0, 0xFF, 0x7F, ++0x1C, 0x58, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x2A, 0xDE, 0xDE, 0xAD, 0x70, 0x79, 0x15, 0x00, 0xDC, 0x7D, 0x15, 0x00, ++0x68, 0x7D, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x20, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x1F, 0x4D, 0x20, 0x4A, 0x2B, 0x68, 0xD2, 0xF8, 0x44, 0x24, 0x01, 0x33, 0x2B, 0x60, 0x90, 0x47, ++0x2A, 0x68, 0x03, 0x46, 0x32, 0xB1, 0x19, 0x49, 0x01, 0x3A, 0x09, 0x68, 0x2A, 0x60, 0x0A, 0xB9, 0x01, 0xB1, 0x62, 0xB6, ++0x18, 0x48, 0x01, 0x93, 0x1D, 0xF0, 0x4E, 0xFD, 0x00, 0x90, 0x17, 0x48, 0x1D, 0xF0, 0x4A, 0xFD, 0xDD, 0xE9, 0x00, 0x13, ++0x02, 0x46, 0x15, 0x48, 0x00, 0xF0, 0xD0, 0xFC, 0x65, 0xE6, 0x14, 0x48, 0x00, 0xF0, 0xCC, 0xFC, 0x61, 0xE6, 0x60, 0xB1, ++0x07, 0x1D, 0x7F, 0xF4, 0x72, 0xAF, 0x40, 0xF2, 0x31, 0x52, 0x10, 0x49, 0x10, 0x48, 0x1F, 0xF0, 0x05, 0xF9, 0x3E, 0x46, ++0xD9, 0xF8, 0x00, 0x20, 0x6A, 0xE7, 0x40, 0xF2, 0x26, 0x32, 0x0B, 0x49, 0x0C, 0x48, 0x04, 0x26, 0x1F, 0xF0, 0xFA, 0xF8, ++0x37, 0x46, 0xD9, 0xF8, 0x00, 0x20, 0x5F, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xA0, 0x56, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0xA4, 0x7D, 0x15, 0x00, 0x08, 0x7E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x54, 0x7D, 0x15, 0x00, 0x44, 0x7D, 0x15, 0x00, 0x10, 0xB4, 0x15, 0x49, 0x15, 0x4C, 0x16, 0x4B, 0x4F, 0xF4, 0x4C, 0x02, ++0x22, 0x60, 0x0A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x30, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0xC0, 0x02, 0x1A, 0x60, ++0x1A, 0x68, 0x22, 0xF4, 0x40, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x4F, 0xF0, 0x60, 0x50, 0x22, 0xF4, 0x40, 0x42, 0x1A, 0x60, ++0x20, 0x60, 0x08, 0x60, 0x1A, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x22, 0xF4, 0x40, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, ++0x40, 0x72, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x40, 0x62, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x0C, 0x40, 0x04, 0x40, ++0x08, 0x40, 0x04, 0x40, 0x18, 0x40, 0x04, 0x40, 0x10, 0xB5, 0x01, 0x46, 0x04, 0x46, 0x05, 0x48, 0x1E, 0xF0, 0x30, 0xFE, ++0x04, 0x4A, 0x05, 0x4B, 0x14, 0x60, 0x4F, 0xF0, 0x80, 0x72, 0x1A, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x2C, 0x7E, 0x15, 0x00, ++0x98, 0x40, 0x04, 0x40, 0x00, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF0, 0x00, 0x72, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF0, 0x80, 0x62, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x40, 0x04, 0x40, ++0x08, 0xB5, 0x25, 0x4B, 0x19, 0x68, 0x4A, 0x03, 0x04, 0xD5, 0x4F, 0xF4, 0x80, 0x22, 0x43, 0xF8, 0x14, 0x2C, 0x08, 0xBD, ++0x08, 0x03, 0x04, 0xD5, 0x20, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x08, 0xBD, 0x4A, 0x02, 0x0F, 0xD4, 0x0B, 0x02, ++0x1D, 0xD4, 0x08, 0x01, 0x10, 0xD5, 0x1C, 0x4B, 0x1A, 0x4A, 0xDB, 0x7D, 0x4F, 0xF0, 0x00, 0x61, 0x01, 0x2B, 0x11, 0x60, ++0xE9, 0xD1, 0xBD, 0xE8, 0x08, 0x40, 0x23, 0xF0, 0xED, 0xBE, 0x15, 0x4B, 0x4F, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x08, 0xBD, ++0x11, 0xF0, 0x80, 0x53, 0x16, 0xD0, 0x12, 0x49, 0x10, 0x4B, 0x01, 0x20, 0x4F, 0xF0, 0x80, 0x52, 0x48, 0x75, 0x1A, 0x60, ++0x08, 0xBD, 0x0D, 0x4B, 0x0E, 0x48, 0x4F, 0xF4, 0x00, 0x02, 0x1A, 0x60, 0x00, 0xF0, 0x0E, 0xFC, 0x03, 0x20, 0x00, 0xF0, ++0x93, 0xFC, 0x0B, 0x4B, 0x4F, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x08, 0xBD, 0x8A, 0x00, 0xC4, 0xD5, 0x05, 0x49, 0x04, 0x4A, ++0x4B, 0x75, 0x4F, 0xF0, 0x00, 0x53, 0x13, 0x60, 0x08, 0xBD, 0x00, 0xBF, 0x1C, 0x40, 0x04, 0x40, 0x08, 0x40, 0x04, 0x40, ++0x4C, 0x36, 0x17, 0x00, 0x40, 0x7E, 0x15, 0x00, 0x00, 0x40, 0x04, 0x40, 0x15, 0x4B, 0xD3, 0xF8, 0x24, 0x31, 0x59, 0x06, ++0x09, 0xD5, 0x10, 0xB5, 0x13, 0x4C, 0x23, 0x68, 0x1A, 0x07, 0x88, 0xB0, 0xC3, 0xF3, 0xC0, 0x00, 0x03, 0xD4, 0x08, 0xB0, ++0x10, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x0F, 0x49, 0x20, 0x22, 0x68, 0x46, 0x31, 0xF0, 0xC6, 0xFA, 0x0D, 0x4B, 0x1B, 0x68, ++0x23, 0x68, 0xC3, 0xF3, 0x40, 0x00, 0x9B, 0x07, 0xEF, 0xD5, 0x0B, 0x4B, 0x0B, 0x4A, 0x4F, 0xF4, 0x00, 0x11, 0x19, 0x60, ++0x10, 0x68, 0x10, 0xF4, 0x40, 0x13, 0xFB, 0xD0, 0x08, 0x4A, 0xC0, 0xF3, 0x00, 0x50, 0x13, 0x60, 0xE1, 0xE7, 0x00, 0xBF, ++0x00, 0x00, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x30, 0x95, 0x16, 0x00, 0x30, 0x60, 0x50, 0x40, 0x00, 0x40, 0x04, 0x40, ++0x04, 0x40, 0x04, 0x40, 0x08, 0x40, 0x04, 0x40, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x09, 0xD1, 0x0B, 0x4B, 0x4F, 0xF4, ++0x00, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x09, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x07, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x52, 0x72, 0x1E, 0xF0, ++0xE1, 0xBF, 0x00, 0xBF, 0x00, 0x40, 0x04, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x38, 0xB5, 0x22, 0x48, 0xFC, 0xF7, 0xFA, 0xFB, 0x83, 0x07, 0x23, 0xD5, 0x20, 0x48, 0x00, 0xF0, 0x8B, 0xFB, 0x20, 0x48, ++0xFC, 0xF7, 0xF2, 0xFB, 0x04, 0x46, 0x1F, 0x48, 0xFC, 0xF7, 0xEE, 0xFB, 0x03, 0x46, 0x1D, 0x48, 0x1C, 0x40, 0xFC, 0xF7, ++0xE9, 0xFB, 0x84, 0x42, 0x1F, 0xD0, 0x05, 0x20, 0x00, 0xF0, 0x14, 0xFC, 0x01, 0x28, 0x04, 0x46, 0x17, 0xD0, 0x03, 0x20, ++0x00, 0xF0, 0x06, 0xFC, 0x02, 0x25, 0x21, 0x46, 0x15, 0x48, 0x00, 0xF0, 0x6F, 0xFB, 0x28, 0x46, 0xBD, 0xE8, 0x38, 0x40, ++0xFF, 0xF7, 0xB2, 0xBF, 0x01, 0x46, 0x12, 0x48, 0x00, 0xF0, 0x66, 0xFB, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x08, 0xDB, 0x38, 0xBD, 0x05, 0x46, 0xE9, 0xE7, 0x20, 0x22, 0x0D, 0x48, 0x11, 0x46, 0xFC, 0xF7, 0x12, 0xFC, ++0xD9, 0xE7, 0xBD, 0xE8, 0x38, 0x40, 0x0B, 0x49, 0x0B, 0x48, 0x4F, 0xF4, 0xD3, 0x62, 0x1E, 0xF0, 0x93, 0xBF, 0x00, 0xBF, ++0x08, 0x30, 0x01, 0x50, 0x54, 0x7E, 0x15, 0x00, 0x20, 0x10, 0x01, 0x50, 0x18, 0x10, 0x01, 0x50, 0x60, 0x7E, 0x15, 0x00, ++0x6C, 0x7E, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x24, 0x10, 0x01, 0x50, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x02, 0x48, 0x38, 0x22, 0x00, 0x21, 0xFA, 0xF7, 0x91, 0xBA, 0x00, 0xBF, 0x48, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x5D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x80, 0x46, 0x0F, 0x46, 0x16, 0x46, 0xC0, 0xF2, 0xA8, 0x80, ++0x00, 0x23, 0x3B, 0x62, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x56, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xB5, 0x01, 0x05, 0xF1, 0x80, 0x42, 0x02, 0xF5, 0xE2, 0x24, 0x53, 0x49, 0x23, 0x68, 0x08, 0x68, 0x43, 0xF0, 0x01, 0x03, ++0x00, 0xF1, 0x01, 0x0C, 0x02, 0xF5, 0xE0, 0x22, 0x23, 0x60, 0xC1, 0xF8, 0x00, 0xC0, 0x23, 0x68, 0xDB, 0x03, 0xFC, 0xD5, ++0xDF, 0xF8, 0x38, 0xE1, 0x5E, 0xF8, 0x26, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0x05, 0xF1, 0x80, 0x43, 0x03, 0xF5, ++0xE0, 0x23, 0x41, 0xF2, 0x0C, 0x0A, 0x53, 0xF8, 0x0A, 0xA0, 0x1A, 0xF4, 0x00, 0x6F, 0x61, 0xD0, 0x05, 0xF1, 0x80, 0x43, ++0x03, 0xF5, 0xE0, 0x23, 0x41, 0xF2, 0x08, 0x09, 0xDF, 0xF8, 0x0C, 0xA1, 0x43, 0xF8, 0x09, 0xA0, 0x41, 0xF2, 0x0C, 0x05, ++0x4F, 0xF0, 0x14, 0x0A, 0x43, 0xF8, 0x05, 0xA0, 0x41, 0xF2, 0x10, 0x0B, 0x41, 0xF2, 0x14, 0x0A, 0x00, 0x25, 0x43, 0xF8, ++0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x18, 0x0B, 0x41, 0xF2, 0x1C, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, ++0x0A, 0x50, 0x03, 0xF5, 0x81, 0x5B, 0x41, 0xF2, 0x24, 0x0A, 0xCB, 0xF8, 0x00, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, ++0x28, 0x0B, 0x41, 0xF2, 0x2C, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x34, 0x0B, 0x41, 0xF2, ++0x38, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x3C, 0x0B, 0x41, 0xF2, 0x30, 0x0A, 0x43, 0xF8, ++0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x80, 0xBD, 0x68, 0x45, 0xF4, 0x00, 0x25, 0xBD, 0x60, 0x53, 0xF8, 0x09, 0x50, 0x45, 0xF0, ++0x01, 0x05, 0x43, 0xF8, 0x09, 0x50, 0x41, 0xF2, 0x04, 0x05, 0x53, 0x59, 0x43, 0xF0, 0x01, 0x03, 0x53, 0x51, 0x23, 0x68, ++0x4E, 0xF8, 0x26, 0x70, 0x23, 0xF0, 0x01, 0x03, 0x23, 0x60, 0xBC, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0x14, 0x4B, 0x08, 0x60, ++0x1B, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x41, 0xF2, 0x18, 0x02, 0x9D, 0x58, 0x2D, 0x03, ++0x07, 0xD5, 0x9D, 0x58, 0x41, 0xF2, 0x30, 0x0A, 0x25, 0xF4, 0x00, 0x25, 0x9D, 0x50, 0x43, 0xF8, 0x0A, 0x80, 0xD9, 0xF8, ++0x08, 0x30, 0x23, 0xF4, 0x00, 0x23, 0xC9, 0xF8, 0x08, 0x30, 0xC9, 0xF8, 0x20, 0x80, 0xD8, 0xE7, 0x0D, 0x2A, 0x7F, 0xF7, ++0x55, 0xAF, 0x06, 0x49, 0x06, 0x48, 0x4E, 0x22, 0x1E, 0xF0, 0xBA, 0xFE, 0x4E, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0x7E, 0x15, 0x00, 0x48, 0x35, 0x17, 0x00, ++0x10, 0x00, 0x01, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x01, 0x30, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x63, 0x70, 0x47, 0x00, 0xBF, ++0x3F, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x40, 0x70, 0xB4, 0x18, 0x4D, 0x18, 0x4C, 0x2E, 0x6B, 0xB1, 0xF5, 0x00, 0x6F, ++0x46, 0xF0, 0x80, 0x56, 0x2E, 0x63, 0x60, 0x60, 0xEB, 0x63, 0x20, 0x60, 0x0B, 0x46, 0x28, 0xBF, 0x4F, 0xF4, 0x00, 0x63, ++0x80, 0x07, 0x11, 0xD0, 0xC1, 0xF3, 0x10, 0x05, 0x10, 0x48, 0x43, 0xF0, 0x0C, 0x53, 0x21, 0xF0, 0x70, 0x41, 0xA3, 0x60, ++0xE5, 0x60, 0x21, 0x61, 0x60, 0x61, 0x0B, 0x49, 0x00, 0x23, 0x23, 0x62, 0x08, 0x46, 0x70, 0xBC, 0xFF, 0xF7, 0x04, 0xBF, ++0xC1, 0xF3, 0x10, 0x05, 0x43, 0xF0, 0x23, 0x43, 0x21, 0xF0, 0x70, 0x41, 0x4F, 0xF0, 0x04, 0x10, 0xA3, 0x60, 0xE5, 0x60, ++0x21, 0x61, 0x60, 0x61, 0xEB, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x07, 0x40, 0x74, 0x25, 0x17, 0x00, 0x01, 0x00, 0x04, 0x00, ++0x01, 0x23, 0x06, 0x4A, 0x03, 0xFA, 0x00, 0xF0, 0x93, 0x69, 0x03, 0x42, 0xFC, 0xD1, 0x13, 0x6B, 0x23, 0xF0, 0x80, 0x53, ++0x13, 0x63, 0x10, 0x6C, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x07, 0x40, 0x08, 0x4A, 0xD3, 0x68, 0x19, 0x04, 0x44, 0xBF, ++0x4F, 0xF4, 0x00, 0x01, 0x91, 0x60, 0x5B, 0x05, 0x00, 0xD4, 0x70, 0x47, 0x03, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x9A, 0x60, ++0x4F, 0xF0, 0x80, 0x40, 0x1D, 0xF0, 0x4E, 0xB9, 0x00, 0x10, 0x50, 0x40, 0x11, 0x4A, 0x13, 0x68, 0x13, 0xF0, 0x01, 0x01, ++0x0A, 0xD1, 0x23, 0xF4, 0x40, 0x73, 0x43, 0xF4, 0x90, 0x73, 0x43, 0xF0, 0x01, 0x03, 0x11, 0x20, 0x11, 0x61, 0x51, 0x61, ++0x50, 0x60, 0x13, 0x60, 0x5A, 0x04, 0x03, 0xD4, 0x08, 0x4A, 0x43, 0xF4, 0x80, 0x43, 0x13, 0x60, 0x07, 0x4B, 0x08, 0x49, ++0x9A, 0x68, 0xD1, 0xF8, 0xD0, 0x10, 0xC2, 0xF8, 0xB4, 0x10, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF0, 0x00, 0x52, 0x1A, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x06, 0x4B, 0x07, 0x49, ++0x9A, 0x68, 0xD1, 0xF8, 0xD0, 0x10, 0xC2, 0xF8, 0xB4, 0x10, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF0, 0x00, 0x52, 0x1A, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x3E, 0x4B, 0x1A, 0x68, 0x00, 0x2A, 0x6F, 0xD1, ++0x3D, 0x49, 0xD1, 0xF8, 0xA4, 0x10, 0x00, 0x29, 0xF0, 0xB4, 0x56, 0xDA, 0x3B, 0x48, 0x00, 0x68, 0x00, 0x28, 0x4E, 0xD0, ++0x3A, 0x4D, 0x3B, 0x48, 0x3B, 0x4C, 0x2A, 0x60, 0x01, 0x25, 0x02, 0x60, 0x25, 0x60, 0xC2, 0x68, 0x39, 0x4D, 0x3A, 0x4C, ++0x42, 0xF4, 0x80, 0x72, 0xC2, 0x60, 0x03, 0x22, 0x2A, 0x60, 0x62, 0x68, 0x92, 0x07, 0x21, 0xF0, 0x00, 0x41, 0x57, 0xD5, ++0x35, 0x4A, 0x12, 0x68, 0x10, 0x09, 0x81, 0x42, 0x4D, 0xD2, 0xB2, 0xFB, 0xF1, 0xF1, 0xC1, 0xF3, 0x42, 0x04, 0x01, 0xF0, ++0x0F, 0x02, 0x12, 0x1B, 0xC1, 0xF3, 0x07, 0x1C, 0x04, 0xEB, 0x02, 0x14, 0xC1, 0xF3, 0x07, 0x31, 0x2A, 0x4A, 0x28, 0x4D, ++0x10, 0x68, 0x2C, 0x4E, 0x2C, 0x4F, 0x40, 0xF0, 0x80, 0x00, 0x10, 0x60, 0xC7, 0xF8, 0x00, 0xC0, 0x29, 0x60, 0x34, 0x60, ++0x11, 0x68, 0x21, 0x4C, 0x22, 0x48, 0x28, 0x4E, 0x21, 0xF0, 0x80, 0x01, 0x11, 0x60, 0x07, 0x22, 0x22, 0x60, 0x02, 0x68, ++0x25, 0x4C, 0x26, 0x49, 0xD4, 0xF8, 0xBC, 0x40, 0x22, 0xF4, 0xFF, 0x72, 0x22, 0xF0, 0x01, 0x02, 0x42, 0xF0, 0x01, 0x02, ++0x02, 0x60, 0x01, 0x22, 0x2A, 0x60, 0xB0, 0x68, 0x4F, 0xF4, 0x80, 0x32, 0xC0, 0xF8, 0x80, 0x40, 0x0A, 0x60, 0x01, 0x22, ++0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x10, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0xF7, 0xD0, 0x10, 0x48, 0x17, 0x4C, 0x16, 0x49, ++0xD4, 0xF8, 0xBC, 0x40, 0x16, 0x4A, 0x01, 0x25, 0x05, 0x60, 0x88, 0x68, 0x4F, 0xF4, 0x80, 0x31, 0xC0, 0xF8, 0x80, 0x40, ++0x11, 0x60, 0xE8, 0xE7, 0x70, 0x47, 0x00, 0x24, 0x21, 0x46, 0x4F, 0xF0, 0x01, 0x0C, 0xB9, 0xE7, 0x0F, 0x48, 0x10, 0x4A, ++0xA7, 0xE7, 0x00, 0xBF, 0xA4, 0x25, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x68, 0x28, 0x17, 0x00, 0x08, 0x10, 0x04, 0x40, ++0x04, 0x10, 0x04, 0x40, 0x24, 0x10, 0x04, 0x40, 0x0C, 0x10, 0x04, 0x40, 0x00, 0x00, 0x10, 0x40, 0x14, 0x13, 0x17, 0x00, ++0x28, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, ++0x50, 0x97, 0x31, 0x00, 0x00, 0x75, 0x19, 0x03, 0x03, 0x4A, 0x13, 0x68, 0x1B, 0x03, 0xFC, 0xD4, 0x02, 0x4B, 0x18, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0x03, 0x4A, 0x13, 0x68, 0xDB, 0x07, 0xFC, 0xD5, ++0x02, 0x4B, 0x18, 0x68, 0xC0, 0xB2, 0x70, 0x47, 0x14, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0xF0, 0xB5, 0x03, 0x46, ++0xC3, 0xB0, 0xEF, 0xF3, 0x05, 0x85, 0x73, 0x4C, 0x22, 0x68, 0x12, 0x78, 0x02, 0x2A, 0x04, 0xD1, 0x71, 0x4A, 0xB2, 0xF8, ++0xAA, 0x20, 0x52, 0x04, 0x56, 0xD4, 0x00, 0x91, 0x00, 0x22, 0x4F, 0xF4, 0x80, 0x71, 0x02, 0xA8, 0x1D, 0xF0, 0x46, 0xFE, ++0x06, 0x46, 0x00, 0x2E, 0x31, 0xDD, 0x6B, 0x4B, 0x1B, 0x68, 0x1B, 0xB9, 0x6A, 0x4B, 0xD3, 0xF8, 0x28, 0x33, 0x98, 0x47, ++0x1D, 0xB9, 0x69, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x68, 0x4B, 0x1B, 0x68, 0x33, 0xB9, 0x67, 0x4A, 0x13, 0x68, ++0x1F, 0x03, 0xFC, 0xD4, 0x66, 0x4B, 0x5F, 0x22, 0x1A, 0x60, 0x5F, 0x4B, 0xB3, 0xF8, 0xAA, 0x30, 0x13, 0xF4, 0x80, 0x43, ++0x18, 0xD1, 0x02, 0xA9, 0x60, 0x4A, 0x61, 0x48, 0x77, 0x18, 0x4F, 0xF0, 0x0D, 0x0C, 0x11, 0xF8, 0x01, 0x4B, 0x0A, 0x2C, ++0x1C, 0xD0, 0x13, 0x68, 0x1B, 0x03, 0xFC, 0xD4, 0x04, 0x60, 0xB9, 0x42, 0x11, 0xF8, 0x01, 0x3C, 0xF3, 0xD1, 0x15, 0xB9, ++0x55, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x30, 0x46, 0x43, 0xB0, 0xF0, 0xBD, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x1C, 0xD0, ++0x02, 0x2B, 0xF2, 0xD1, 0x53, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xED, 0xD0, 0x00, 0x2D, 0xEF, 0xD1, 0x26, 0xE0, ++0x0D, 0x2B, 0xE0, 0xD0, 0x13, 0x68, 0x1C, 0x03, 0xFC, 0xD4, 0xC0, 0xF8, 0x00, 0xC0, 0x11, 0xF8, 0x01, 0x4C, 0xD8, 0xE7, ++0x00, 0x91, 0x00, 0x22, 0x4F, 0xF4, 0x80, 0x71, 0x03, 0xA8, 0x1D, 0xF0, 0xEF, 0xFD, 0x06, 0x46, 0xA7, 0xE7, 0x46, 0x4F, ++0x3B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xD2, 0xD0, 0x00, 0x2D, 0xD4, 0xD1, 0x43, 0x48, 0x1D, 0xF0, 0x07, 0xF9, 0x04, 0x28, ++0x62, 0xD8, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0xC8, 0xD1, 0x3B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xC4, 0xD0, 0x3E, 0x48, ++0x1D, 0xF0, 0xFA, 0xF8, 0x04, 0x28, 0xBF, 0xD9, 0x3B, 0x48, 0x3C, 0x4C, 0x1D, 0xF0, 0xB4, 0xF8, 0x42, 0xF2, 0x34, 0x03, ++0x13, 0x25, 0xE2, 0x5A, 0x8D, 0xF8, 0x08, 0x60, 0x00, 0x23, 0xB2, 0xF5, 0xC3, 0x7F, 0x02, 0xAF, 0x01, 0x46, 0x7D, 0x80, ++0x7B, 0x70, 0x4D, 0xD8, 0x55, 0x1C, 0xAD, 0xB2, 0xD3, 0x00, 0x33, 0x48, 0x8A, 0x81, 0xD0, 0xF8, 0x00, 0xC0, 0x0C, 0xEB, ++0x03, 0x00, 0x32, 0x1D, 0x47, 0x60, 0x2C, 0xF8, 0x03, 0x20, 0xC3, 0x78, 0x03, 0xF0, 0x31, 0x03, 0x43, 0xF0, 0x04, 0x03, ++0xC3, 0x70, 0x94, 0xF8, 0x02, 0x3C, 0x42, 0xF2, 0x34, 0x0C, 0x01, 0x33, 0x84, 0xF8, 0x02, 0x3C, 0x01, 0x27, 0x00, 0x23, ++0x24, 0xF8, 0x0C, 0x50, 0xC1, 0xE9, 0x01, 0x02, 0x8F, 0x73, 0x0B, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, ++0x72, 0xB6, 0x22, 0x4B, 0x1F, 0x60, 0x22, 0x4C, 0x22, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1D, 0xF0, 0x32, 0xF8, ++0x13, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x23, 0x68, 0x00, 0x2B, 0x3F, 0xF4, 0x76, 0xAF, 0x19, 0x4A, 0x01, 0x3B, ++0x12, 0x68, 0x23, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0x6F, 0xAF, 0x00, 0x2A, 0x3F, 0xF4, 0x6C, 0xAF, 0x62, 0xB6, 0x69, 0xE7, ++0x7C, 0x2E, 0x32, 0x46, 0xA8, 0xBF, 0x7C, 0x22, 0x92, 0xB2, 0x02, 0xA9, 0x13, 0x20, 0x02, 0xF0, 0xF9, 0xFA, 0x5F, 0xE7, ++0x1A, 0x46, 0x01, 0x25, 0xB1, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xA4, 0x25, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x40, 0x40, 0x04, 0x40, 0x68, 0x28, 0x17, 0x00, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, ++0x74, 0x36, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x0F, 0xB4, 0x00, 0xB5, 0x83, 0xB0, 0x04, 0xA9, ++0x05, 0x4B, 0x51, 0xF8, 0x04, 0x0B, 0xD3, 0xF8, 0x30, 0x34, 0x01, 0x91, 0x98, 0x47, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xEB, ++0x04, 0xB0, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x01, 0x22, 0x90, 0x42, 0x10, 0xB4, 0x02, 0xFA, 0x00, 0xF4, 0x11, 0xDD, ++0xA0, 0xF1, 0x08, 0x03, 0x93, 0x42, 0x0D, 0xD9, 0x0F, 0x28, 0x25, 0xDD, 0x1F, 0x28, 0x12, 0xDC, 0x15, 0x4A, 0x52, 0xF8, ++0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x43, 0xF0, 0x02, 0x03, 0x42, 0xF8, 0x20, 0x30, 0x08, 0xE0, 0x10, 0x4A, 0x52, 0xF8, ++0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x43, 0xF0, 0x01, 0x03, 0x42, 0xF8, 0x20, 0x30, 0x0D, 0x4B, 0x5A, 0x68, 0x22, 0x43, ++0x5A, 0x60, 0x9A, 0x68, 0x29, 0xB9, 0x22, 0xEA, 0x04, 0x02, 0x9A, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x22, 0x43, ++0x9A, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x03, 0x4A, 0x52, 0xF8, 0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x42, 0xF8, ++0x20, 0x30, 0xE6, 0xE7, 0x00, 0x30, 0x50, 0x40, 0x00, 0x40, 0x50, 0x40, 0x04, 0x49, 0x01, 0x22, 0x0B, 0x68, 0x02, 0xFA, ++0x00, 0xF0, 0x23, 0xEA, 0x00, 0x03, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x40, 0x50, 0x40, 0x10, 0xB5, 0x01, 0x29, ++0x82, 0xB0, 0x04, 0x46, 0x10, 0xD0, 0x20, 0xF0, 0x03, 0x03, 0x0F, 0x22, 0x9A, 0x40, 0x11, 0x46, 0x0D, 0x48, 0xFC, 0xF7, ++0x51, 0xF8, 0x01, 0x22, 0xA2, 0x40, 0x0C, 0x48, 0x11, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7, 0x48, 0xB8, ++0x01, 0xFA, 0x00, 0xF2, 0x11, 0x46, 0x07, 0x48, 0x01, 0x92, 0xFC, 0xF7, 0x41, 0xF8, 0x01, 0x9A, 0x05, 0x48, 0x11, 0x46, ++0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7, 0x39, 0xB8, 0x00, 0xBF, 0x2C, 0x10, 0x01, 0x50, 0x04, 0x10, 0x01, 0x50, ++0x08, 0x10, 0x01, 0x50, 0x01, 0x23, 0x03, 0xFA, 0x00, 0xF2, 0x11, 0x46, 0x01, 0x48, 0xFC, 0xF7, 0x2B, 0xB8, 0x00, 0xBF, ++0x00, 0x10, 0x01, 0x50, 0x01, 0x22, 0x82, 0x40, 0x00, 0x21, 0x01, 0x48, 0xFC, 0xF7, 0x22, 0xB8, 0x00, 0x10, 0x01, 0x50, ++0x10, 0xB5, 0x04, 0x46, 0x03, 0x48, 0xFB, 0xF7, 0xCB, 0xFF, 0xE0, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x10, 0xBD, 0x00, 0xBF, ++0x00, 0x10, 0x01, 0x50, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x0E, 0x48, 0x0F, 0x4A, ++0x03, 0x68, 0x0F, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x03, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, ++0x43, 0xF0, 0xC2, 0x03, 0x13, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x03, 0x60, 0x13, 0x68, ++0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0xC2, 0x20, 0x13, 0x60, 0xC8, 0x71, 0x70, 0x47, 0xAC, 0xB3, 0x33, 0x40, ++0xD4, 0xB3, 0x33, 0x40, 0x80, 0x35, 0x17, 0x00, 0x24, 0x4B, 0x25, 0x48, 0x1B, 0x68, 0x2D, 0xE9, 0xF0, 0x41, 0x24, 0x4D, ++0x24, 0x4F, 0x6A, 0x79, 0x95, 0xF9, 0x07, 0x10, 0x3C, 0x68, 0x23, 0x4E, 0x03, 0xF0, 0x0F, 0x03, 0x1A, 0x44, 0x52, 0xB2, ++0x89, 0x1A, 0x6F, 0xF0, 0x3D, 0x03, 0x99, 0x42, 0xB8, 0xBF, 0x19, 0x46, 0x5F, 0xFA, 0x81, 0xFC, 0x24, 0xF0, 0xFF, 0x04, ++0x44, 0xEA, 0x0C, 0x04, 0x3C, 0x60, 0x33, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xEA, 0x0C, 0x03, 0x33, 0x60, 0x3C, 0x68, ++0xCB, 0x1E, 0x5F, 0xFA, 0x83, 0xFC, 0x24, 0xF4, 0x7F, 0x24, 0x44, 0xEA, 0x0C, 0x34, 0x3C, 0x60, 0x33, 0x68, 0x23, 0xF4, ++0x7F, 0x23, 0x4C, 0xB2, 0x43, 0xEA, 0x0C, 0x33, 0x33, 0x60, 0x21, 0x46, 0xEC, 0x71, 0x1E, 0xF0, 0xC3, 0xF8, 0x3D, 0x34, ++0x0E, 0xDB, 0x0D, 0x4B, 0x29, 0x89, 0x1A, 0x69, 0x0C, 0x4B, 0x47, 0xF2, 0x30, 0x54, 0x05, 0xF1, 0x0C, 0x00, 0x04, 0xFB, ++0x01, 0x21, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x81, 0x1C, 0x01, 0x32, 0x40, ++0xB8, 0x7E, 0x15, 0x00, 0x80, 0x35, 0x17, 0x00, 0xAC, 0xB3, 0x33, 0x40, 0xD4, 0xB3, 0x33, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x12, 0x4A, 0x12, 0x68, 0xD2, 0xE9, 0x06, 0x01, 0x38, 0xB5, 0x11, 0x4B, 0x15, 0x6A, 0x18, 0x60, ++0x59, 0x60, 0x50, 0x6A, 0x0F, 0x4C, 0xD2, 0xE9, 0x0A, 0x12, 0xC3, 0xE9, 0x02, 0x50, 0xC3, 0xE9, 0x04, 0x12, 0xD4, 0xF8, ++0x2C, 0x33, 0x98, 0x47, 0xD4, 0xF8, 0xC0, 0x30, 0x98, 0x47, 0xFB, 0xF7, 0xAF, 0xFA, 0x09, 0x4B, 0x1B, 0x68, 0x1B, 0x78, ++0x03, 0x2B, 0x02, 0xD1, 0xD4, 0xF8, 0x20, 0x31, 0x98, 0x47, 0xBD, 0xE8, 0x38, 0x40, 0xFF, 0xF7, 0x79, 0xBB, 0x00, 0xBF, ++0xC8, 0x35, 0x17, 0x00, 0xB0, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x30, 0xB4, 0x08, 0x4B, ++0x08, 0x48, 0x18, 0x60, 0xC2, 0x25, 0x40, 0xF6, 0xEC, 0x20, 0x4F, 0xF4, 0x7A, 0x74, 0x06, 0x49, 0x06, 0x4A, 0xDD, 0x71, ++0x98, 0x80, 0x1C, 0x81, 0x19, 0x61, 0x30, 0xBC, 0x1A, 0x62, 0x70, 0x47, 0x80, 0x35, 0x17, 0x00, 0x01, 0x00, 0x00, 0x14, ++0x95, 0x64, 0x12, 0x00, 0x4D, 0x64, 0x12, 0x00, 0x90, 0xF8, 0x62, 0x30, 0xCB, 0xB9, 0x0D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x03, 0xDB, 0x00, 0x23, 0x84, 0xF8, 0xAC, 0x30, 0x10, 0xBD, 0x90, 0xF8, ++0xAC, 0x30, 0x01, 0x2B, 0xF7, 0xD0, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xE7, 0x12, 0x1E, 0xF0, 0xBB, 0xFA, 0x00, 0x23, ++0x84, 0xF8, 0xAC, 0x30, 0x10, 0xBD, 0x70, 0x47, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xCC, 0x7E, 0x15, 0x00, ++0x13, 0x4A, 0x90, 0xF8, 0x22, 0x30, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, ++0x1B, 0xD1, 0x0F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x08, 0xDB, 0x94, 0xF8, ++0x23, 0x10, 0x0B, 0x48, 0x1E, 0xF0, 0x1E, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x70, 0x32, 0x10, 0xBD, 0x90, 0xF8, 0x70, 0x32, ++0x01, 0x2B, 0xF2, 0xD0, 0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xF3, 0x12, 0x1E, 0xF0, 0x8A, 0xFA, 0xEB, 0xE7, 0x70, 0x47, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x10, 0x7F, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x7E, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x41, 0x90, 0xF8, 0x62, 0x40, 0x1C, 0xB9, 0x90, 0xF8, 0x64, 0x30, 0x06, 0x46, 0x0B, 0xB9, 0xBD, 0xE8, ++0xF0, 0x81, 0xD0, 0xE9, 0x24, 0x23, 0xD0, 0xF8, 0x98, 0x10, 0x42, 0x48, 0xDF, 0xF8, 0x30, 0x81, 0x1D, 0xF0, 0xF0, 0xFF, ++0x45, 0x46, 0x06, 0xF5, 0xB2, 0x77, 0x28, 0x46, 0x06, 0x22, 0x39, 0x46, 0x30, 0xF0, 0xD8, 0xFC, 0x14, 0x35, 0x40, 0xB1, ++0x01, 0x34, 0x05, 0x2C, 0xF5, 0xD1, 0x3A, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5B, 0xDB, 0x04, 0xEB, ++0x84, 0x03, 0x08, 0xEB, 0x83, 0x03, 0xA2, 0x00, 0xD9, 0x79, 0x00, 0x29, 0xD9, 0xD1, 0x1B, 0x7A, 0x03, 0xBB, 0xD6, 0xF8, ++0x90, 0x30, 0x31, 0x2B, 0x29, 0xD9, 0xD6, 0xF8, 0x94, 0x10, 0xB1, 0xEB, 0x53, 0x0F, 0x3B, 0xD8, 0x14, 0x44, 0x08, 0xEB, ++0x84, 0x08, 0x98, 0xF8, 0x06, 0x30, 0x00, 0x2B, 0x48, 0xD1, 0x00, 0x23, 0xC6, 0xE9, 0x24, 0x33, 0x29, 0x4A, 0xC6, 0xF8, ++0x98, 0x30, 0x12, 0x69, 0x28, 0x49, 0x29, 0x4B, 0x06, 0xF1, 0x9C, 0x00, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, ++0x11, 0x44, 0x18, 0x47, 0xD6, 0xF8, 0x98, 0x30, 0x53, 0xB3, 0xD6, 0xF8, 0x90, 0x30, 0x00, 0x2B, 0x37, 0xD0, 0x11, 0x19, ++0x08, 0xEB, 0x81, 0x01, 0x00, 0x20, 0x08, 0x72, 0xD3, 0xE7, 0x0B, 0x2B, 0x12, 0xD8, 0xD6, 0xF8, 0x98, 0x20, 0x14, 0x2A, ++0xDB, 0xD9, 0x00, 0x2B, 0xD9, 0xD1, 0x1B, 0x48, 0x1D, 0xF0, 0x9A, 0xFF, 0x18, 0x4B, 0x01, 0x22, 0x88, 0xF8, 0x06, 0x20, ++0x30, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xD6, 0xF8, 0x94, 0x10, 0x14, 0x4A, 0xA2, 0xFB, ++0x03, 0x02, 0x22, 0xF0, 0x03, 0x00, 0x00, 0xEB, 0x92, 0x02, 0x8A, 0x42, 0xE1, 0xD8, 0xE6, 0xE7, 0xD6, 0xF8, 0x90, 0x30, ++0xD5, 0xE7, 0x0F, 0x49, 0x0F, 0x48, 0x40, 0xF2, 0x13, 0x22, 0x1E, 0xF0, 0xF5, 0xF9, 0x9C, 0xE7, 0x00, 0x23, 0x0D, 0x48, ++0x88, 0xF8, 0x06, 0x30, 0x1D, 0xF0, 0x74, 0xFF, 0xAF, 0xE7, 0x0B, 0x48, 0xD4, 0xE7, 0x00, 0xBF, 0x1C, 0x7F, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x80, 0xC3, 0xC9, 0x01, 0x88, 0x1A, 0x17, 0x00, 0x44, 0x7F, 0x15, 0x00, ++0xAB, 0xAA, 0xAA, 0xAA, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x3C, 0x7F, 0x15, 0x00, 0x30, 0x7F, 0x15, 0x00, ++0xCC, 0x35, 0x17, 0x00, 0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, 0x01, 0xD0, 0x04, 0xF0, ++0xEF, 0xBC, 0x03, 0xF0, 0xD5, 0xBF, 0x00, 0xF0, 0xD7, 0xBF, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x46, ++0x00, 0xF0, 0x6C, 0xFE, 0x01, 0x20, 0x08, 0xBD, 0x70, 0xB5, 0x30, 0x4C, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x1E, 0xD0, ++0x02, 0x2B, 0x14, 0xD1, 0x2D, 0x4B, 0x2E, 0x49, 0x2E, 0x4A, 0xC3, 0xE9, 0x06, 0x12, 0x2E, 0x4D, 0xD5, 0xF8, 0x14, 0x31, ++0x98, 0x47, 0xD5, 0xF8, 0x18, 0x31, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x36, 0xD0, 0x02, 0x2B, 0x1D, 0xD0, ++0x03, 0x2B, 0x0E, 0xD0, 0x70, 0xBD, 0x03, 0x2B, 0xED, 0xD1, 0x22, 0x4B, 0x25, 0x49, 0x26, 0x4A, 0xC3, 0xE9, 0x08, 0x12, ++0xE7, 0xE7, 0x1F, 0x4B, 0x24, 0x49, 0x25, 0x4A, 0xC3, 0xE9, 0x02, 0x12, 0xE1, 0xE7, 0x24, 0x4B, 0x1B, 0x4C, 0x24, 0x4A, ++0x1A, 0x60, 0x04, 0xF0, 0x87, 0xFC, 0x23, 0x6A, 0x22, 0x48, 0x98, 0x47, 0x63, 0x6A, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, ++0x1D, 0x4B, 0x20, 0x49, 0x20, 0x4A, 0x19, 0x60, 0x13, 0x4D, 0x42, 0xF2, 0x34, 0x03, 0x00, 0x21, 0xD1, 0x52, 0x04, 0xF0, ++0x1B, 0xF8, 0x03, 0xF0, 0x35, 0xFF, 0xAB, 0x69, 0x18, 0x48, 0x98, 0x47, 0xEB, 0x69, 0x98, 0x47, 0x04, 0xF0, 0x1A, 0xFC, ++0x23, 0x68, 0x1B, 0x78, 0xCA, 0xE7, 0x12, 0x4B, 0x09, 0x4D, 0x16, 0x4A, 0x1A, 0x60, 0x00, 0xF0, 0xCB, 0xFE, 0x00, 0xF0, ++0xE9, 0xFE, 0x00, 0xF0, 0x13, 0xFF, 0xAB, 0x68, 0x0E, 0x48, 0x98, 0x47, 0xEB, 0x68, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, ++0xB6, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x28, 0x58, 0x17, 0x00, 0xA1, 0xA9, 0x12, 0x00, 0x85, 0xA9, 0x12, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x3D, 0xB2, 0x12, 0x00, 0x29, 0xB2, 0x12, 0x00, 0x0D, 0x7A, 0x12, 0x00, 0xF9, 0x79, 0x12, 0x00, ++0x1C, 0x58, 0x17, 0x00, 0xBC, 0x60, 0x17, 0x00, 0xB8, 0x7F, 0x15, 0x00, 0xA4, 0x60, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x28, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x0B, 0x4C, 0x50, 0x22, 0x51, 0x23, 0x04, 0xF2, 0x14, 0x50, 0xA4, 0xF8, 0x10, 0x25, ++0x84, 0xF8, 0x12, 0x35, 0x1C, 0xF0, 0xD8, 0xFC, 0x27, 0x22, 0x28, 0x23, 0x04, 0xF5, 0xF4, 0x60, 0xA4, 0xF8, 0x9C, 0x27, ++0x84, 0xF8, 0x9E, 0x37, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0xF0, 0xCC, 0xBC, 0x58, 0x58, 0x17, 0x00, 0x70, 0xB5, 0x41, 0xF6, ++0x10, 0x02, 0x25, 0x4D, 0x25, 0x4C, 0x4C, 0xF2, 0xBF, 0x03, 0x41, 0xF6, 0x12, 0x00, 0x00, 0x26, 0xAB, 0x52, 0x41, 0xF6, ++0x14, 0x01, 0x05, 0xF5, 0xC1, 0x52, 0xA5, 0xF8, 0x00, 0x3C, 0x2E, 0x54, 0x05, 0xF6, 0x08, 0x40, 0x6E, 0x50, 0x16, 0x70, ++0x85, 0xF8, 0x02, 0x6C, 0xC5, 0xF8, 0x04, 0x6C, 0x1C, 0xF0, 0xAE, 0xFC, 0xA4, 0xF1, 0x0C, 0x00, 0x1C, 0xF0, 0xAA, 0xFC, ++0x04, 0xF5, 0x00, 0x60, 0x1C, 0xF0, 0xA6, 0xFC, 0x04, 0xF6, 0x08, 0x00, 0x1C, 0xF0, 0xA2, 0xFC, 0x42, 0xF2, 0x34, 0x03, ++0x31, 0x46, 0x4F, 0xF4, 0x00, 0x62, 0x20, 0x46, 0xEE, 0x52, 0x85, 0xF8, 0x02, 0x6C, 0xC5, 0xF8, 0x04, 0x6C, 0xF9, 0xF7, ++0x05, 0xFC, 0x04, 0xF5, 0x00, 0x65, 0x2E, 0x46, 0x21, 0x46, 0x30, 0x46, 0x10, 0x34, 0x1C, 0xF0, 0x91, 0xFC, 0xAC, 0x42, ++0xF8, 0xD1, 0x09, 0x4A, 0x00, 0x21, 0x02, 0xF5, 0xB4, 0x70, 0xA2, 0xF1, 0x24, 0x03, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, ++0xFB, 0xD1, 0x03, 0xF1, 0x24, 0x02, 0x82, 0x42, 0xF5, 0xD1, 0x70, 0xBD, 0x7C, 0x36, 0x17, 0x00, 0xA0, 0x4E, 0x17, 0x00, ++0xD8, 0x56, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x40, 0x20, 0x85, 0xB0, 0x1C, 0xF0, 0xF6, 0xFB, 0xA7, 0x4B, 0x9B, 0x68, ++0x03, 0x93, 0x00, 0x2B, 0x00, 0xF0, 0x80, 0x81, 0xDF, 0xF8, 0xB0, 0x92, 0xDF, 0xF8, 0xB0, 0xB2, 0x09, 0xE0, 0x94, 0xF8, ++0x64, 0x30, 0x63, 0xB1, 0x03, 0x9B, 0x1B, 0x68, 0x03, 0x93, 0x03, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0x71, 0x81, 0x03, 0x9C, ++0x20, 0x46, 0x07, 0xF0, 0x33, 0xFF, 0x00, 0x28, 0xEF, 0xD0, 0x03, 0x9B, 0x9A, 0x4C, 0x03, 0xF5, 0xA3, 0x65, 0x01, 0x26, ++0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0x60, 0x23, 0x68, 0x28, 0x46, 0x01, 0x33, ++0x23, 0x60, 0x1C, 0xF0, 0x8B, 0xFC, 0x23, 0x68, 0x5A, 0x1E, 0x2B, 0xB1, 0xD9, 0xF8, 0x00, 0x30, 0x22, 0x60, 0x0A, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x05, 0x21, 0x38, 0xB1, 0xDB, 0xF8, 0x24, 0x34, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, ++0xE7, 0xD4, 0xE3, 0xE7, 0x89, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0xC8, 0xD1, 0xDD, 0xF8, 0x0C, 0xA0, 0x87, 0x4E, ++0x04, 0x23, 0x01, 0x93, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, 0x00, 0xF0, 0x8C, 0x80, 0x9D, 0xF8, 0x04, 0x70, 0x0A, 0xF5, ++0xA2, 0x68, 0x40, 0x46, 0x1C, 0xF0, 0x62, 0xFC, 0x80, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, ++0x43, 0x7F, 0x7F, 0xDB, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x62, 0x92, 0xF8, 0x25, 0x10, 0x19, 0xB9, 0xE9, 0x8B, ++0x08, 0x07, 0x40, 0xF1, 0x07, 0x81, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x62, 0x92, 0xF8, 0x24, 0x20, 0x01, 0x2A, ++0x00, 0xF0, 0x9E, 0x80, 0xDB, 0xF8, 0x24, 0x34, 0x28, 0x46, 0x39, 0x46, 0x98, 0x47, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, ++0xD7, 0xD1, 0x0A, 0xF5, 0x9D, 0x65, 0xA8, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, ++0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0xDA, 0xF8, 0xE8, 0x14, 0x5A, 0x1C, 0x22, 0x60, 0x2A, 0xB1, 0xD9, 0xF8, 0x00, 0x20, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x00, 0x29, 0x34, 0xD0, 0x4A, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x02, 0x63, 0x93, 0xF8, 0x25, 0x00, 0x00, 0x28, 0x00, 0xF0, 0x87, 0x80, 0x93, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x46, 0xD0, ++0xC9, 0x7E, 0xDB, 0xF8, 0x34, 0x31, 0x10, 0x46, 0x98, 0x47, 0x00, 0x28, 0x00, 0xF0, 0xD7, 0x80, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x40, 0x46, 0x01, 0x33, 0x23, 0x60, ++0x1C, 0xF0, 0x00, 0xFC, 0x23, 0x68, 0x05, 0x46, 0x33, 0xB1, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0xDB, 0xF8, 0x24, 0x34, 0x39, 0x46, 0x28, 0x46, 0x98, 0x47, 0x00, 0x2D, 0xB4, 0xD1, 0x01, 0x9B, ++0x01, 0x3B, 0x1D, 0x46, 0x38, 0x46, 0x01, 0x93, 0x0B, 0xF0, 0x26, 0xFA, 0x2B, 0x46, 0x01, 0x33, 0xAA, 0xF1, 0x08, 0x0A, ++0x3F, 0xF4, 0x38, 0xAF, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, 0x7F, 0xF4, 0x74, 0xAF, 0x9D, 0xF8, 0x04, 0x70, 0x9C, 0xE7, ++0x09, 0x2B, 0x7F, 0xF6, 0x7D, 0xAF, 0x3C, 0x49, 0x3C, 0x48, 0x4F, 0xF4, 0x96, 0x72, 0x1D, 0xF0, 0xE1, 0xFF, 0x6B, 0x7F, ++0x74, 0xE7, 0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x02, 0x92, ++0x01, 0x33, 0x40, 0x46, 0x23, 0x60, 0x1C, 0xF0, 0xC1, 0xFB, 0x23, 0x68, 0x02, 0x9A, 0x05, 0x46, 0x33, 0xB1, 0x01, 0x3B, ++0xD9, 0xF8, 0x00, 0x10, 0x23, 0x60, 0x0B, 0xB9, 0x01, 0xB1, 0x62, 0xB6, 0x01, 0x9B, 0x4F, 0x20, 0x00, 0xFB, 0x02, 0x30, ++0x41, 0x30, 0x06, 0xEB, 0xC0, 0x00, 0x29, 0x46, 0x1C, 0xF0, 0x68, 0xFB, 0x00, 0x2D, 0x7F, 0xF4, 0x6F, 0xAF, 0xB8, 0xE7, ++0x23, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x4D, 0xDB, 0xEA, 0x8B, 0xD2, 0x07, 0x7F, 0xF5, 0x5D, 0xAF, ++0x01, 0x9A, 0x4F, 0x20, 0x46, 0x32, 0x10, 0xFB, 0x03, 0x20, 0x29, 0x46, 0x06, 0xEB, 0xC0, 0x00, 0x1C, 0xF0, 0x50, 0xFB, ++0x51, 0xE7, 0x93, 0xF8, 0x23, 0x10, 0x1B, 0x48, 0x1D, 0xF0, 0x24, 0xFD, 0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x01, 0x23, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x40, 0x46, 0x01, 0x33, 0x23, 0x60, 0x1C, 0xF0, 0x80, 0xFB, ++0x4F, 0xF0, 0x00, 0x42, 0x39, 0x46, 0x05, 0x46, 0x28, 0xF0, 0x2A, 0xFE, 0x23, 0x68, 0x00, 0x2B, 0x85, 0xD0, 0x01, 0x3B, ++0xD9, 0xF8, 0x00, 0x20, 0x23, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0x7F, 0xAF, 0x00, 0x2A, 0x3F, 0xF4, 0x7C, 0xAF, 0x62, 0xB6, ++0x00, 0x2D, 0x7F, 0xF4, 0x2F, 0xAF, 0x78, 0xE7, 0x00, 0x88, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x50, 0x7F, 0x15, 0x00, 0x7C, 0x7F, 0x15, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xEA, 0x8B, 0xD1, 0x07, 0xB2, 0xD4, 0x11, 0x49, 0x11, 0x48, 0x02, 0x93, ++0x40, 0xF2, 0x35, 0x12, 0x1D, 0xF0, 0x5A, 0xFF, 0x02, 0x9B, 0xA5, 0xE7, 0x92, 0xF8, 0x23, 0x10, 0x0D, 0x48, 0x1D, 0xF0, ++0xD9, 0xFC, 0x28, 0x46, 0x4F, 0xF0, 0x00, 0x42, 0x39, 0x46, 0x28, 0xF0, 0xED, 0xFD, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, ++0x7F, 0xF4, 0xD3, 0xAE, 0xF9, 0xE6, 0x07, 0x4A, 0x01, 0x23, 0x82, 0xF8, 0x00, 0x32, 0x42, 0xE7, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0x8C, 0x7F, 0x15, 0x00, 0x7C, 0x7F, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, 0x07, 0xD0, 0x06, 0x4B, 0xD3, 0xF8, 0x30, 0x31, ++0x18, 0x47, 0x04, 0x4B, 0xD3, 0xF8, 0x08, 0x33, 0x18, 0x47, 0x03, 0xF0, 0x8F, 0xBF, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x03, 0xD1, 0x06, 0x4B, ++0xD3, 0xF8, 0x34, 0x34, 0x18, 0x47, 0x04, 0xF0, 0x93, 0xBB, 0x03, 0x4B, 0xD3, 0xF8, 0x00, 0x33, 0x18, 0x47, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x07, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, ++0x01, 0xD0, 0x04, 0xF0, 0x83, 0xBB, 0x04, 0xF0, 0x7B, 0xB8, 0x03, 0x4B, 0xD3, 0xF8, 0x0C, 0x33, 0x18, 0x47, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, ++0x03, 0xD1, 0x06, 0x4B, 0xD3, 0xF8, 0x38, 0x34, 0x18, 0x47, 0x04, 0xF0, 0x6D, 0xBB, 0x03, 0x4B, 0xD3, 0xF8, 0x04, 0x33, ++0x18, 0x47, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, ++0x05, 0xD0, 0x02, 0x2B, 0x01, 0xD0, 0x04, 0xF0, 0x5D, 0xBB, 0x04, 0xF0, 0xAD, 0xB9, 0x01, 0xF0, 0x6B, 0xB9, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x08, 0xB5, 0x0C, 0x22, 0x08, 0x23, 0x01, 0x21, 0x40, 0xF2, 0x0D, 0x40, 0x1B, 0xF0, 0xE6, 0xFD, ++0xBD, 0xE8, 0x08, 0x40, 0x1B, 0xF0, 0x12, 0xBE, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x82, 0x46, 0x00, 0x68, 0x05, 0x91, ++0x03, 0x90, 0x07, 0x92, 0x62, 0xB1, 0xB0, 0xFB, 0xF2, 0xF3, 0x11, 0x46, 0x02, 0xFB, 0x13, 0x02, 0x0B, 0x46, 0x00, 0x2A, ++0x40, 0xF0, 0xDE, 0x80, 0x03, 0x9A, 0x04, 0x3B, 0x1A, 0x44, 0x03, 0x92, 0x9A, 0xF8, 0x08, 0x30, 0x00, 0x2B, 0x00, 0xF0, ++0xD2, 0x80, 0x00, 0x23, 0xDF, 0xF8, 0xC0, 0x81, 0xDF, 0xF8, 0xC0, 0x91, 0x00, 0x93, 0x1F, 0x46, 0xD3, 0x46, 0x08, 0xE0, ++0x00, 0x9B, 0x9B, 0xF8, 0x08, 0x20, 0x01, 0x33, 0xDF, 0xB2, 0xBA, 0x42, 0x00, 0x93, 0x40, 0xF2, 0xC0, 0x80, 0x05, 0x9B, ++0xDB, 0xF8, 0x0C, 0x10, 0x33, 0xF8, 0x27, 0x00, 0x03, 0xEB, 0x87, 0x02, 0x00, 0x24, 0x55, 0x88, 0x07, 0xEB, 0x47, 0x02, ++0x01, 0xEB, 0x82, 0x06, 0x41, 0xF8, 0x22, 0x40, 0xB4, 0x80, 0x00, 0x2D, 0xE4, 0xD0, 0x03, 0x1D, 0x01, 0x93, 0x03, 0x9B, ++0x75, 0x80, 0x03, 0xF1, 0x04, 0x0A, 0x02, 0x95, 0xB0, 0x80, 0x55, 0x46, 0xCD, 0xF8, 0x18, 0xB0, 0xA2, 0x46, 0x04, 0x97, ++0x34, 0xE0, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x37, 0xD3, 0x04, 0x9B, 0x05, 0xF8, 0x04, 0x3C, 0xD8, 0xF8, ++0x00, 0x30, 0xAB, 0x42, 0x41, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x3C, 0xD3, 0x55, 0x23, 0x05, 0xF8, ++0x03, 0x3C, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x46, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x41, 0xD3, ++0x00, 0x23, 0x05, 0xF8, 0x02, 0x3C, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x4B, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, ++0xAB, 0x42, 0x46, 0xD3, 0xCB, 0xF8, 0x04, 0x70, 0x33, 0x88, 0x01, 0x99, 0x01, 0x33, 0x01, 0x34, 0x33, 0x80, 0x02, 0x9B, ++0xA2, 0xB2, 0x93, 0x42, 0x0D, 0x44, 0x48, 0xD9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x57, 0x46, 0xA5, 0xF1, 0x04, 0x0B, ++0xAA, 0x46, 0xC2, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, ++0xBE, 0xD2, 0x31, 0x48, 0x29, 0x46, 0xFF, 0xF7, 0xE9, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0xBD, 0xD9, 0xD9, 0xF8, ++0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0xB9, 0xD2, 0x29, 0x48, 0x29, 0x46, ++0xFF, 0xF7, 0xD8, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0xB8, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, ++0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0xB4, 0xD2, 0x22, 0x48, 0x29, 0x46, 0xFF, 0xF7, 0xC7, 0xF9, 0xD8, 0xF8, ++0x00, 0x30, 0xAB, 0x42, 0xB3, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, ++0xAB, 0x42, 0xAF, 0xD2, 0x29, 0x46, 0x1A, 0x48, 0xFF, 0xF7, 0xB6, 0xF9, 0xAC, 0xE7, 0x0A, 0x46, 0x5D, 0x1E, 0x03, 0x99, ++0xDD, 0xF8, 0x18, 0xB0, 0xAD, 0xB2, 0x05, 0xFB, 0x02, 0x13, 0x05, 0xFB, 0x02, 0x25, 0x48, 0x19, 0x07, 0x99, 0x03, 0x90, ++0x04, 0x33, 0xB3, 0x60, 0x00, 0x29, 0x3F, 0xF4, 0x47, 0xAF, 0xB0, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, 0x13, 0x02, 0x0B, 0x46, ++0x22, 0xB1, 0x8B, 0x1A, 0x03, 0x2B, 0x9C, 0xBF, 0x0A, 0x46, 0x9B, 0x18, 0x03, 0x9A, 0x04, 0x3B, 0x1A, 0x44, 0x03, 0x92, ++0x36, 0xE7, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x8B, 0x1A, 0x03, 0x2B, 0x9C, 0xBF, 0x0A, 0x46, 0x9B, 0x18, 0x1B, 0xE7, ++0xE0, 0x7F, 0x15, 0x00, 0x10, 0x80, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, 0x64, 0x80, 0x15, 0x00, 0xC8, 0x25, 0x17, 0x00, ++0xE4, 0x25, 0x17, 0x00, 0xF8, 0xB5, 0x06, 0x7A, 0x00, 0x2E, 0x00, 0xF0, 0xBC, 0x80, 0xC5, 0x68, 0x00, 0x2D, 0x00, 0xF0, ++0x82, 0x80, 0x2C, 0x46, 0x01, 0x23, 0x09, 0xE0, 0x22, 0x88, 0xA2, 0xB9, 0x9E, 0x42, 0x0F, 0xD9, 0x03, 0xEB, 0x43, 0x04, ++0x05, 0xEB, 0x84, 0x04, 0x01, 0x33, 0xDB, 0xB2, 0xA0, 0x88, 0x88, 0x42, 0x03, 0xEB, 0x43, 0x02, 0xF0, 0xD2, 0x9E, 0x42, ++0x02, 0xD9, 0x05, 0xEB, 0x82, 0x04, 0xF3, 0xE7, 0x9E, 0x42, 0x00, 0xF0, 0x9E, 0x80, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x4E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x4E, 0x4E, 0x23, 0x88, 0x35, 0x68, 0x6A, 0x1C, 0x32, 0x60, ++0x00, 0x2B, 0x5D, 0xD0, 0x4B, 0x4F, 0xA5, 0x68, 0x3A, 0x68, 0xAA, 0x42, 0x28, 0xD8, 0x79, 0x68, 0x11, 0x44, 0x8D, 0x42, ++0x24, 0xD8, 0x29, 0x68, 0xA1, 0x60, 0x01, 0x3B, 0xAA, 0x42, 0x23, 0x80, 0x32, 0xD8, 0x7B, 0x68, 0x13, 0x44, 0xAB, 0x42, ++0x2E, 0xD3, 0x15, 0xF8, 0x03, 0x1C, 0x55, 0x29, 0x53, 0xD1, 0xAA, 0x23, 0x05, 0xF8, 0x03, 0x3C, 0x3B, 0x68, 0x9D, 0x42, ++0x5D, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9D, 0x42, 0x59, 0xD8, 0x01, 0x23, 0x05, 0xF8, 0x02, 0x3C, 0x33, 0x68, 0x00, 0x2B, ++0x34, 0xD0, 0x36, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x7B, 0xBB, 0x72, 0xB3, 0x35, 0xE0, 0x35, 0x48, 0x01, 0x68, ++0x8D, 0x42, 0x03, 0xD3, 0x40, 0x68, 0x01, 0x44, 0x8D, 0x42, 0xD2, 0xD9, 0x29, 0x46, 0x32, 0x48, 0xFF, 0xF7, 0x12, 0xF9, ++0x23, 0x88, 0x3A, 0x68, 0x00, 0x21, 0x01, 0x3B, 0xAA, 0x42, 0xA1, 0x60, 0x23, 0x80, 0xCC, 0xD9, 0x2B, 0x48, 0x03, 0x68, ++0xAB, 0x42, 0x1F, 0xD8, 0x41, 0x68, 0x19, 0x44, 0xA9, 0x42, 0x1B, 0xD3, 0x15, 0xF8, 0x03, 0x1C, 0x55, 0x29, 0x1C, 0xD1, ++0xAA, 0x42, 0x37, 0xD9, 0x42, 0x68, 0x13, 0x44, 0x9D, 0x42, 0xC2, 0xD9, 0x29, 0x46, 0x24, 0x48, 0xFF, 0xF7, 0xF4, 0xF8, ++0xC0, 0xE7, 0x23, 0x48, 0xFF, 0xF7, 0xF0, 0xF8, 0x28, 0x46, 0xF8, 0xBD, 0xC2, 0xB1, 0x1A, 0x4B, 0x35, 0x60, 0x1B, 0x68, ++0xA5, 0xB9, 0x9B, 0xB1, 0x62, 0xB6, 0xF5, 0xE7, 0x29, 0x46, 0x1D, 0x48, 0xFF, 0xF7, 0xE2, 0xF8, 0x00, 0x21, 0x33, 0x68, ++0x33, 0xB1, 0x13, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x17, 0x48, 0x2A, 0x46, ++0xFF, 0xF7, 0xD4, 0xF8, 0x00, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x0F, 0x4A, 0x13, 0x68, 0x9D, 0x42, 0x03, 0xD3, 0x52, 0x68, ++0x13, 0x44, 0x9D, 0x42, 0x9D, 0xD9, 0x29, 0x46, 0x10, 0x48, 0xFF, 0xF7, 0xC5, 0xF8, 0x9B, 0xE7, 0x79, 0x68, 0x0A, 0x44, ++0x95, 0x42, 0x8A, 0xD9, 0x9D, 0x42, 0xC5, 0xD3, 0xC0, 0xE7, 0x0C, 0x48, 0xFF, 0xF7, 0xBA, 0xF8, 0x00, 0x25, 0xC7, 0xE7, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xCC, 0x80, 0x15, 0x00, ++0x10, 0x80, 0x15, 0x00, 0x98, 0x80, 0x15, 0x00, 0x00, 0x81, 0x15, 0x00, 0x28, 0x81, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, ++0xB4, 0x80, 0x15, 0x00, 0x00, 0x29, 0x00, 0xF0, 0x0F, 0x81, 0x2D, 0xE9, 0xF8, 0x43, 0x03, 0x68, 0x8B, 0x42, 0x05, 0x46, ++0x0C, 0x46, 0x59, 0xD8, 0x42, 0x68, 0x13, 0x44, 0x99, 0x42, 0x55, 0xD8, 0x83, 0x4F, 0x3B, 0x68, 0x99, 0x42, 0x55, 0xD3, ++0x7A, 0x68, 0x13, 0x44, 0x99, 0x42, 0x51, 0xD8, 0x14, 0xF8, 0x04, 0x6C, 0x2B, 0x7A, 0xB3, 0x42, 0x48, 0xD9, 0xD5, 0xF8, ++0x0C, 0x80, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x7A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x7A, 0x4D, ++0x38, 0x68, 0x2B, 0x68, 0x84, 0x42, 0x03, 0xF1, 0x01, 0x03, 0x2B, 0x60, 0x25, 0xD3, 0x7B, 0x68, 0x03, 0x44, 0x9C, 0x42, ++0x21, 0xD8, 0x14, 0xF8, 0x03, 0x9C, 0xB9, 0xF1, 0xAA, 0x0F, 0x00, 0xF0, 0xAB, 0x80, 0xB9, 0xF1, 0xFF, 0x0F, 0x20, 0xD1, ++0x7B, 0x68, 0x18, 0x44, 0x84, 0x42, 0x00, 0xF2, 0xA1, 0x80, 0x14, 0xF8, 0x02, 0x0C, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0xF8, ++0x02, 0x0C, 0x00, 0x28, 0x47, 0xD0, 0x2B, 0x68, 0x33, 0xB1, 0x67, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x40, 0xB2, 0xBD, 0xE8, 0xF8, 0x83, 0x64, 0x4B, 0x1A, 0x68, 0x94, 0x42, 0x1E, 0xD2, 0x63, 0x48, ++0x21, 0x46, 0xFF, 0xF7, 0x47, 0xF8, 0x2B, 0x68, 0x33, 0xB1, 0x5D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x4F, 0xF0, 0xFF, 0x30, 0xBD, 0xE8, 0xF8, 0x83, 0x59, 0x4B, 0x1A, 0x68, 0x94, 0x42, 0x03, 0xD3, ++0x5B, 0x68, 0x1A, 0x44, 0x94, 0x42, 0xA5, 0xD9, 0x57, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0x2E, 0xF8, 0x00, 0x26, 0xA1, 0xE7, ++0x59, 0x68, 0x11, 0x44, 0x8C, 0x42, 0xDC, 0xD8, 0x14, 0xF8, 0x03, 0x9C, 0xB9, 0xF1, 0xAA, 0x0F, 0x6C, 0xD0, 0xB9, 0xF1, ++0xFF, 0x0F, 0xD8, 0xD1, 0x84, 0x42, 0xB5, 0xD2, 0x1A, 0x68, 0x94, 0x42, 0x03, 0xD3, 0x5B, 0x68, 0x1A, 0x44, 0x94, 0x42, ++0xB3, 0xD9, 0x4B, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0x13, 0xF8, 0xB9, 0xF1, 0xFF, 0x0F, 0x5D, 0xD0, 0x06, 0xEB, 0x46, 0x06, ++0x08, 0xEB, 0x86, 0x09, 0x38, 0xF8, 0x26, 0x20, 0xB9, 0xF8, 0x02, 0x30, 0x9A, 0x42, 0x4F, 0xEA, 0x86, 0x06, 0xBC, 0xD2, ++0x3B, 0x68, 0x9C, 0x42, 0x31, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x2D, 0xD8, 0x55, 0x23, 0x04, 0xF8, 0x03, 0x3C, ++0x3B, 0x68, 0x9C, 0x42, 0x1A, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x16, 0xD8, 0xD9, 0xF8, 0x08, 0x30, 0x23, 0x60, ++0x38, 0xF8, 0x06, 0x30, 0x28, 0x68, 0xC9, 0xF8, 0x08, 0x40, 0x01, 0x33, 0x28, 0xF8, 0x06, 0x30, 0x38, 0xB1, 0x2E, 0x4B, ++0x01, 0x38, 0x1B, 0x68, 0x28, 0x60, 0x10, 0xB9, 0x0B, 0xB1, 0x62, 0xB6, 0xA2, 0xE7, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, ++0x2A, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, 0xE0, 0xD9, 0x21, 0x46, 0x2A, 0x48, ++0xFE, 0xF7, 0xD0, 0xFF, 0xDE, 0xE7, 0x24, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, ++0xC9, 0xD9, 0x21, 0x46, 0x24, 0x48, 0xFE, 0xF7, 0xC3, 0xFF, 0xC7, 0xE7, 0x1D, 0x4B, 0xA1, 0xE7, 0x14, 0xF8, 0x02, 0x0C, ++0x01, 0x38, 0xC0, 0xB2, 0x04, 0xF8, 0x02, 0x0C, 0x00, 0x28, 0x7F, 0xF4, 0x5C, 0xAF, 0xA5, 0xE7, 0x84, 0x42, 0xBF, 0xF4, ++0x4B, 0xAF, 0x96, 0xE7, 0x3B, 0x68, 0x9C, 0x42, 0x11, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x0D, 0xD8, 0x01, 0x23, ++0x04, 0xF8, 0x02, 0x3C, 0x2B, 0x68, 0x33, 0xB1, 0x0D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x01, 0x20, 0x60, 0xE7, 0x0B, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, ++0xE9, 0xD9, 0x21, 0x46, 0x0C, 0x48, 0xFE, 0xF7, 0x91, 0xFF, 0xE7, 0xE7, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0x47, 0x00, 0xBF, ++0xC8, 0x25, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x00, 0x81, 0x15, 0x00, ++0x50, 0x81, 0x15, 0x00, 0x80, 0x81, 0x15, 0x00, 0x64, 0x80, 0x15, 0x00, 0x10, 0x80, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, ++0x0B, 0x4A, 0x13, 0x68, 0x83, 0x42, 0x05, 0xD8, 0x52, 0x68, 0x13, 0x44, 0x98, 0x42, 0x01, 0xD8, 0x01, 0x20, 0x70, 0x47, ++0x07, 0x4A, 0x13, 0x68, 0x98, 0x42, 0x06, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x98, 0x42, 0x8C, 0xBF, 0x00, 0x20, 0x01, 0x20, ++0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0xC8, 0x25, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x10, 0x4B, 0x70, 0xB5, ++0x10, 0x4C, 0xDC, 0x60, 0x15, 0x46, 0x0E, 0x46, 0x03, 0x24, 0x01, 0x46, 0x20, 0x22, 0x18, 0x46, 0x5D, 0x60, 0x1C, 0x72, ++0x1E, 0x60, 0xFF, 0xF7, 0xCD, 0xFC, 0x0B, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x01, 0x21, 0x4F, 0xF0, 0x02, 0x15, 0x04, 0x24, ++0x4F, 0xF4, 0x80, 0x20, 0x5A, 0x60, 0x00, 0x22, 0xC3, 0xE9, 0x05, 0x40, 0xDD, 0x60, 0x19, 0x60, 0x99, 0x60, 0x1A, 0x61, ++0x9A, 0x83, 0x70, 0xBD, 0xE4, 0x25, 0x17, 0x00, 0xF4, 0x25, 0x17, 0x00, 0xA8, 0x25, 0x17, 0x00, 0x38, 0xB5, 0x0F, 0x4B, ++0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0x46, 0x0D, 0xD0, 0x0D, 0x48, 0x7C, 0x21, 0xFF, 0xF7, 0xAB, 0xFD, 0x04, 0x46, ++0x2C, 0xB1, 0x20, 0x46, 0xFF, 0xF7, 0xAC, 0xFF, 0x38, 0xB1, 0x04, 0xF8, 0x01, 0x5C, 0x20, 0x46, 0x38, 0xBD, 0x00, 0xF0, ++0xC3, 0xF9, 0x04, 0x46, 0xF2, 0xE7, 0x21, 0x46, 0x04, 0x48, 0xFE, 0xF7, 0x17, 0xFF, 0x20, 0x46, 0x38, 0xBD, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xAC, 0x81, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0xFF, 0xF7, 0x92, 0xFF, ++0x98, 0xB1, 0x31, 0x4B, 0x14, 0xF8, 0x04, 0x2C, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x23, 0xD0, 0x02, 0x2B, 0x2A, 0xD0, ++0x03, 0x2B, 0x15, 0xD1, 0x2C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x30, 0xDB, 0x02, 0x2A, 0x30, 0xD0, ++0x10, 0xBD, 0x29, 0x48, 0x21, 0x46, 0xFE, 0xF7, 0xF1, 0xFE, 0x25, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x11, 0xD0, ++0x02, 0x2B, 0x18, 0xD0, 0x03, 0x2B, 0x29, 0xD0, 0x20, 0x46, 0xFF, 0xF7, 0x6D, 0xFF, 0x90, 0xB3, 0x21, 0x46, 0x21, 0x48, ++0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x3C, 0xBE, 0x02, 0x2A, 0x0F, 0xD0, 0x00, 0x2A, 0xE3, 0xD1, 0x20, 0x46, 0xBD, 0xE8, ++0x10, 0x40, 0x00, 0xF0, 0x9B, 0xB9, 0x02, 0x2A, 0x26, 0xD0, 0x00, 0x2A, 0xDA, 0xD1, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, ++0x03, 0xF0, 0xF2, 0xB9, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x45, 0xB9, 0x02, 0x2A, 0x0C, 0xD1, 0x13, 0x4B, ++0x20, 0x46, 0xD3, 0xF8, 0xE8, 0x34, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC1, 0xDA, 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x49, 0x0D, 0x48, 0xBE, 0x22, 0x1D, 0xF0, 0xF5, 0xBA, 0x21, 0x46, ++0x0B, 0x48, 0xFE, 0xF7, 0xAD, 0xFE, 0xC7, 0xE7, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x03, 0xF0, 0x21, 0xB9, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x50, 0x81, 0x15, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xD4, 0x81, 0x15, 0x00, 0xE4, 0x81, 0x15, 0x00, 0x30, 0xB5, 0x1A, 0x4C, 0x1A, 0x4A, 0x23, 0x68, ++0x1A, 0x48, 0x5D, 0x88, 0x99, 0x88, 0xB2, 0xF8, 0xD4, 0x20, 0x85, 0xB0, 0x04, 0x3A, 0xAD, 0xF8, 0x02, 0x50, 0xDD, 0x88, ++0xAD, 0xF8, 0x06, 0x10, 0x19, 0x89, 0xAD, 0xF8, 0x0A, 0x50, 0xD3, 0xE9, 0x05, 0x35, 0xAD, 0xF8, 0x0E, 0x10, 0x01, 0x21, ++0x03, 0x60, 0x01, 0x72, 0x10, 0x4B, 0x45, 0x60, 0x0C, 0x21, 0xC3, 0x60, 0xAD, 0xF8, 0x0C, 0x20, 0x40, 0xF2, 0x3C, 0x63, ++0xAD, 0xF8, 0x00, 0x10, 0x7C, 0x25, 0x69, 0x46, 0x20, 0x22, 0xAD, 0xF8, 0x08, 0x30, 0xAD, 0xF8, 0x04, 0x50, 0xFF, 0xF7, ++0xE9, 0xFB, 0x23, 0x68, 0x01, 0xA8, 0xD3, 0xE9, 0x07, 0x12, 0xFF, 0xF7, 0x07, 0xFF, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, 0xD8, 0x25, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, ++0x0C, 0x48, 0x1B, 0xF0, 0x3F, 0xFE, 0x2B, 0x68, 0x5B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, 0x00, 0x24, 0x0C, 0x21, ++0x38, 0x46, 0xFF, 0xF7, 0xCB, 0xFC, 0x01, 0x46, 0x30, 0x46, 0x1B, 0xF0, 0x35, 0xFE, 0x2B, 0x68, 0x01, 0x34, 0x5A, 0x88, ++0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, 0x78, 0x36, 0x17, 0x00, 0x08, 0x60, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x4C, 0x80, 0x0F, 0x48, 0x1B, 0xF0, 0x1D, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0x1B, 0x89, ++0xB3, 0xB1, 0x0D, 0x4D, 0x0D, 0x4F, 0x0B, 0x4E, 0x00, 0x24, 0x4F, 0xF4, 0xD7, 0x61, 0x38, 0x46, 0xFF, 0xF7, 0xA6, 0xFC, ++0x01, 0x46, 0x30, 0x46, 0x1B, 0xF0, 0x10, 0xFE, 0xD8, 0xF8, 0x00, 0x20, 0x2B, 0x68, 0x11, 0x89, 0x01, 0x34, 0xA2, 0xB2, ++0x01, 0x33, 0x91, 0x42, 0x2B, 0x60, 0xEC, 0xD8, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x60, 0x17, 0x00, 0x18, 0x26, 0x17, 0x00, ++0xE4, 0x25, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, 0x0C, 0x48, 0x1B, 0xF0, 0xF3, 0xFD, 0x2B, 0x68, ++0x9B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, 0x00, 0x24, 0x7C, 0x21, 0x38, 0x46, 0xFF, 0xF7, 0x7F, 0xFC, 0x01, 0x46, ++0x30, 0x46, 0x1B, 0xF0, 0xE9, 0xFD, 0x2B, 0x68, 0x01, 0x34, 0x9A, 0x88, 0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, ++0x78, 0x36, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, ++0x1B, 0xF0, 0x10, 0xFE, 0x23, 0x68, 0x33, 0xB1, 0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x08, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, ++0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0xAB, 0xFD, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x08, 0x60, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x0C, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0xCE, 0xFD, 0x18, 0xB1, 0x0A, 0x4A, ++0x13, 0x68, 0x01, 0x3B, 0x13, 0x60, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x60, 0x17, 0x00, ++0x18, 0x26, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0x61, 0xFD, 0x0A, 0x49, ++0x23, 0x68, 0x0A, 0x68, 0x01, 0x32, 0x0A, 0x60, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x60, 0x17, 0x00, ++0x18, 0x26, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0x7E, 0xFD, 0x23, 0x68, 0x33, 0xB1, ++0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, ++0x19, 0xFD, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x41, 0x4B, 0xDF, 0xF8, 0x20, 0xB1, 0x1B, 0x68, 0x40, 0x4D, 0x1F, 0x8E, 0xDF, 0xF8, 0x18, 0x91, 0xDF, 0xF8, 0x18, 0x81, ++0x8B, 0x89, 0x0C, 0x46, 0x06, 0x46, 0x9F, 0x42, 0x6A, 0xD9, 0xD8, 0xF8, 0x00, 0x30, 0x04, 0x2B, 0x63, 0xD9, 0xD6, 0xE9, ++0x01, 0x03, 0x1B, 0x69, 0x98, 0x47, 0x82, 0x46, 0x00, 0x28, 0x62, 0xD0, 0xFF, 0xF7, 0x0E, 0xFF, 0x00, 0x28, 0x4A, 0xD0, ++0x00, 0x22, 0x34, 0x4B, 0x02, 0x60, 0x1B, 0x68, 0x42, 0x60, 0x53, 0x44, 0x82, 0x60, 0x03, 0x60, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x4A, 0xDB, 0xF8, 0x00, 0x30, 0xD2, 0xF8, ++0x00, 0xC0, 0x43, 0xF0, 0x01, 0x03, 0x0C, 0xF1, 0x01, 0x01, 0x11, 0x60, 0xCB, 0xF8, 0x00, 0x30, 0xDB, 0xF8, 0x00, 0x30, ++0x9B, 0x07, 0xFB, 0xD4, 0x2B, 0x68, 0x1B, 0xBB, 0xD9, 0xF8, 0x00, 0x30, 0xC9, 0xF8, 0x00, 0x00, 0x2B, 0x68, 0xB4, 0xF8, ++0x0C, 0xE0, 0x60, 0x60, 0x0E, 0xF1, 0x01, 0x0E, 0x98, 0xB2, 0x01, 0x30, 0x1F, 0xFA, 0x8E, 0xF3, 0xA3, 0x81, 0x28, 0x60, ++0xDB, 0xF8, 0x00, 0x00, 0x20, 0xF0, 0x01, 0x00, 0xCB, 0xF8, 0x00, 0x00, 0x00, 0x29, 0xB4, 0xD0, 0x18, 0x49, 0xC2, 0xF8, ++0x00, 0xC0, 0x0A, 0x68, 0xBC, 0xF1, 0x00, 0x0F, 0xAD, 0xD1, 0x00, 0x2A, 0xAB, 0xD0, 0x62, 0xB6, 0xA3, 0x89, 0xA8, 0xE7, ++0x63, 0x68, 0x00, 0x2B, 0xDC, 0xD0, 0x58, 0x60, 0xDA, 0xE7, 0x12, 0x48, 0xFE, 0xF7, 0xAA, 0xFC, 0xD6, 0xE9, 0x01, 0x03, ++0x51, 0x46, 0x5B, 0x69, 0x98, 0x47, 0x09, 0x4B, 0xA2, 0x89, 0x1B, 0x68, 0x5B, 0x8E, 0x9A, 0x42, 0x02, 0xD2, 0x04, 0x20, ++0x1B, 0xF0, 0xEA, 0xFB, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0xD8, 0xF8, 0x00, 0x10, 0x08, 0x48, 0xFE, 0xF7, 0x94, 0xFC, ++0xED, 0xE7, 0x00, 0xBF, 0xC8, 0x35, 0x17, 0x00, 0x64, 0x00, 0x24, 0x40, 0x34, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x24, 0x82, 0x15, 0x00, 0x0C, 0x82, 0x15, 0x00, 0x60, 0x00, 0x24, 0x40, 0x68, 0x00, 0x24, 0x40, ++0x18, 0x26, 0x17, 0x00, 0x08, 0xB5, 0x03, 0x4B, 0xD3, 0xF8, 0xF8, 0x32, 0x98, 0x47, 0x01, 0x20, 0x08, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0A, 0x4A, 0x0A, 0x49, 0x0B, 0x4C, 0x00, 0x23, 0xC2, 0xE9, 0x02, 0x03, 0xC2, 0xE9, ++0x04, 0x33, 0xC2, 0xE9, 0x00, 0x33, 0xC1, 0xE9, 0x00, 0x33, 0x8B, 0x81, 0x8B, 0x60, 0x8B, 0x73, 0x10, 0x46, 0xD4, 0xF8, ++0x10, 0x31, 0x98, 0x47, 0x01, 0x20, 0x10, 0xBD, 0x28, 0x60, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0xB9, 0x4B, 0xD3, 0xF8, 0x14, 0x35, 0x00, 0x2B, 0x00, 0xF0, 0x30, 0x81, 0xEF, 0xF3, ++0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0xB4, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xDF, 0xF8, 0x04, 0x93, 0xB1, 0x4B, ++0xD9, 0xF8, 0x00, 0x20, 0xD3, 0xF8, 0x14, 0x35, 0x51, 0x1C, 0xC9, 0xF8, 0x00, 0x10, 0x31, 0xB1, 0xAD, 0x49, 0xC9, 0xF8, ++0x00, 0x20, 0x09, 0x68, 0x0A, 0xB9, 0x01, 0xB1, 0x62, 0xB6, 0x93, 0xF8, 0x0C, 0xB0, 0x5A, 0x7B, 0x5C, 0x68, 0x05, 0x92, ++0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x38, 0x81, 0x00, 0x2C, 0x00, 0xF0, 0x35, 0x81, 0x9B, 0x68, 0x00, 0x2B, 0x00, 0xF0, ++0x31, 0x81, 0xA3, 0x4B, 0x07, 0x93, 0x9B, 0x89, 0x1F, 0xFA, 0x8B, 0xF2, 0x5B, 0x45, 0x06, 0x92, 0xC0, 0xF0, 0x5C, 0x81, ++0xDF, 0xF8, 0xB0, 0xA2, 0x00, 0x26, 0xAA, 0xE0, 0xD4, 0xE9, 0x00, 0x53, 0x03, 0x93, 0x6B, 0x1E, 0xB3, 0xF5, 0xE8, 0x1F, ++0x27, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x95, 0x4A, 0x01, 0x23, 0x13, 0x60, 0x03, 0x9B, ++0xD9, 0xF8, 0x00, 0x70, 0x01, 0x93, 0x23, 0x68, 0x93, 0x48, 0x00, 0x93, 0x5A, 0x46, 0x23, 0x46, 0x31, 0x46, 0x01, 0x37, ++0xC9, 0xF8, 0x00, 0x70, 0x1C, 0xF0, 0xC4, 0xFD, 0x4F, 0xF4, 0x80, 0x71, 0xA4, 0xF1, 0x80, 0x00, 0x1D, 0xF0, 0x9C, 0xF9, ++0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x88, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x20, 0x46, 0xFF, 0xF7, 0x1A, 0xFE, 0x6B, 0x7E, 0x2F, 0x7E, 0x09, 0x2B, 0x09, 0xD8, 0x83, 0x4A, 0x4F, 0xF4, ++0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x25, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xDD, 0x80, 0x6B, 0x8B, 0x13, 0xF0, ++0x08, 0x0F, 0x7E, 0x4B, 0x40, 0xF0, 0xBC, 0x80, 0x1A, 0x46, 0x04, 0x93, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x23, ++0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xCC, 0x80, 0x95, 0xF8, 0x16, 0x80, 0xB8, 0xF1, 0x05, 0x0F, 0x00, 0xF2, ++0x09, 0x81, 0x75, 0x4C, 0x75, 0x48, 0x1B, 0xF0, 0xF1, 0xFB, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, ++0xC0, 0xF2, 0xA5, 0x80, 0xE1, 0x8B, 0x71, 0x4B, 0xE2, 0x6C, 0x13, 0xF8, 0x08, 0xC0, 0x21, 0xF0, 0x01, 0x01, 0x00, 0x23, ++0xE1, 0x83, 0x63, 0x64, 0x13, 0x61, 0xE3, 0x62, 0x6B, 0x4B, 0x29, 0x46, 0x0C, 0xF1, 0x01, 0x0C, 0x1C, 0x22, 0x20, 0x1D, ++0x03, 0xF8, 0x08, 0xC0, 0x2F, 0xF0, 0x8A, 0xFA, 0xE1, 0x8B, 0xDA, 0xF8, 0x00, 0x00, 0x00, 0x23, 0x21, 0xF4, 0x00, 0x42, ++0x84, 0xF8, 0x42, 0x30, 0x22, 0xF0, 0x02, 0x02, 0x2D, 0x1A, 0x63, 0x62, 0x23, 0x65, 0x0B, 0x07, 0xE2, 0x83, 0xA5, 0x64, ++0x00, 0xF1, 0x87, 0x80, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, ++0x13, 0x44, 0x5A, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x02, 0x44, 0x41, 0xF8, 0x23, 0x20, ++0xA4, 0x20, 0x04, 0x9B, 0x00, 0xFB, 0x07, 0x80, 0x99, 0x30, 0x21, 0x46, 0x03, 0xEB, 0xC0, 0x00, 0x03, 0x9C, 0x1B, 0xF0, ++0x61, 0xFB, 0x01, 0x36, 0xF3, 0xB2, 0x9B, 0x45, 0x16, 0xD9, 0x05, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0x51, 0xAF, 0x4D, 0x49, ++0x4F, 0xF4, 0x80, 0x60, 0x1C, 0xF0, 0x7E, 0xFD, 0x20, 0x46, 0xD4, 0xE9, 0x00, 0x54, 0xFF, 0xF7, 0x93, 0xFD, 0xDA, 0xF8, ++0x00, 0x00, 0x01, 0x36, 0x28, 0x1A, 0xFF, 0xF7, 0x4B, 0xFC, 0xF3, 0xB2, 0x9B, 0x45, 0xE8, 0xD8, 0x07, 0x9A, 0x06, 0x99, ++0x93, 0x89, 0x5B, 0x1A, 0x93, 0x81, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4A, 0x01, 0x23, ++0x13, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x3D, 0x48, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x75, 0xFB, 0x2F, 0x49, ++0x91, 0xF8, 0x11, 0x35, 0xD1, 0xF8, 0x14, 0x25, 0x01, 0x3B, 0x81, 0xF8, 0x11, 0x35, 0x00, 0x2A, 0x00, 0xF0, 0x94, 0x80, ++0xD9, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0xDC, 0xAE, 0x28, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, ++0x00, 0x2B, 0x7F, 0xF4, 0xD4, 0xAE, 0x00, 0x2A, 0x3F, 0xF4, 0xD1, 0xAE, 0x62, 0xB6, 0x21, 0x4B, 0xD3, 0xF8, 0x14, 0x35, ++0x00, 0x2B, 0x7F, 0xF4, 0xD0, 0xAE, 0x40, 0x20, 0x1B, 0xF0, 0x6A, 0xFA, 0x04, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, ++0x1B, 0xF0, 0x64, 0xBA, 0x1F, 0x4C, 0x04, 0x93, 0x4F, 0xF0, 0x05, 0x08, 0x50, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0x58, 0xAF, ++0x21, 0x49, 0x22, 0x48, 0x4F, 0xF4, 0xE5, 0x72, 0x1C, 0xF0, 0x4C, 0xFF, 0x50, 0xE7, 0x04, 0x9B, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x07, 0x30, 0x21, 0x46, 0x00, 0xF5, 0xA3, 0x60, 0x03, 0x9C, 0x1B, 0xF0, 0xEC, 0xFA, 0x89, 0xE7, 0xDA, 0xF8, ++0x00, 0x00, 0x03, 0x9C, 0x28, 0x1A, 0xFF, 0xF7, 0xE7, 0xFB, 0x82, 0xE7, 0x0A, 0x4B, 0x16, 0x48, 0x07, 0x93, 0x1D, 0x46, ++0xFE, 0xF7, 0xEE, 0xFA, 0xAB, 0x89, 0x1F, 0xFA, 0x8B, 0xF2, 0x5B, 0x45, 0x06, 0x92, 0x27, 0xD3, 0xBB, 0xF1, 0x00, 0x0F, ++0x7F, 0xF4, 0xC8, 0xAE, 0x8C, 0xE7, 0x00, 0xBF, 0x58, 0x58, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, ++0x50, 0x82, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, ++0x74, 0x28, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0xB4, 0x82, 0x15, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x9C, 0x82, 0x15, 0x00, 0x34, 0x82, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x10, 0x48, 0xFE, 0xF7, ++0xBD, 0xFA, 0xBB, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0x9D, 0xAE, 0x61, 0xE7, 0x0D, 0x48, 0x0E, 0x4C, 0x1C, 0xF0, 0x7E, 0xFC, ++0x80, 0x21, 0xA5, 0xF1, 0x40, 0x00, 0x1D, 0xF0, 0x57, 0xF8, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0xE9, 0xAE, 0x08, 0x49, 0x08, 0x48, 0x4F, 0xF4, 0xE3, 0x72, 0x1C, 0xF0, 0xE7, 0xFE, 0xE1, 0xE6, 0x20, 0x20, 0x1B, 0xF0, ++0x11, 0xFA, 0x67, 0xE7, 0x44, 0x82, 0x15, 0x00, 0x74, 0x82, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x88, 0x82, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x24, 0x91, 0xDF, 0xF8, 0x24, 0x81, 0x42, 0x4F, 0x43, 0x4B, ++0xD3, 0xF8, 0xA0, 0x27, 0x00, 0x2A, 0x5E, 0xD0, 0x15, 0x7B, 0xD2, 0xF8, 0x04, 0xA0, 0x56, 0x7B, 0x65, 0xB3, 0x4F, 0xF0, ++0x00, 0x0B, 0x11, 0xE0, 0xDA, 0xE9, 0x00, 0x4A, 0xFF, 0xF7, 0xB0, 0xFC, 0x20, 0x46, 0xFD, 0xF7, 0x03, 0xFB, 0xD8, 0xF8, ++0x00, 0x00, 0x0B, 0xF1, 0x01, 0x0B, 0x20, 0x1A, 0xFF, 0xF7, 0x64, 0xFB, 0x5F, 0xFA, 0x8B, 0xF1, 0xA9, 0x42, 0x17, 0xD2, ++0x50, 0x46, 0x39, 0x46, 0x00, 0x2E, 0xE9, 0xD0, 0x4F, 0xF4, 0x80, 0x60, 0x1C, 0xF0, 0x80, 0xFC, 0x50, 0x46, 0xDA, 0xE9, ++0x00, 0x4A, 0xFF, 0xF7, 0x95, 0xFC, 0xD8, 0xF8, 0x00, 0x00, 0x0B, 0xF1, 0x01, 0x0B, 0x20, 0x1A, 0xFF, 0xF7, 0x4C, 0xFB, ++0x5F, 0xFA, 0x8B, 0xF1, 0xA9, 0x42, 0xE7, 0xD3, 0x28, 0x4A, 0x93, 0x89, 0x5D, 0x1B, 0x95, 0x81, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x25, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x23, 0x48, 0x01, 0x33, ++0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x76, 0xFA, 0x1D, 0x49, 0xD9, 0xF8, 0x00, 0x20, 0x91, 0xF8, 0x9D, 0x37, 0x01, 0x3B, ++0x81, 0xF8, 0x9D, 0x37, 0x00, 0x2A, 0xAA, 0xD0, 0x1A, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, ++0xA3, 0xD1, 0x00, 0x2B, 0xA1, 0xD0, 0x62, 0xB6, 0x13, 0x4B, 0xD3, 0xF8, 0xA0, 0x27, 0x00, 0x2A, 0xA0, 0xD1, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x4F, 0xF4, ++0x00, 0x00, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x8A, 0xF9, 0x04, 0x20, 0x1B, 0xF0, 0x63, 0xF9, 0xD9, 0xF8, ++0x00, 0x30, 0x3B, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0xBD, 0xE8, 0xF8, 0x8F, 0xB0, 0x82, 0x15, 0x00, 0x58, 0x58, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0xF8, 0x5F, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0xD8, 0x80, ++0xDF, 0xF8, 0xD8, 0x90, 0xDF, 0xF8, 0xD8, 0xA0, 0xD9, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0x41, 0xD0, 0x1F, 0x89, 0x5D, 0x68, ++0xBF, 0xB1, 0x00, 0x24, 0x26, 0x46, 0x23, 0x46, 0xB3, 0x42, 0xAB, 0x46, 0x04, 0xF1, 0x01, 0x04, 0x6D, 0x68, 0x08, 0xD1, ++0xDA, 0xF8, 0x8C, 0x32, 0x98, 0x47, 0x9B, 0xF8, 0x0B, 0x30, 0x03, 0xF0, 0x7F, 0x03, 0x1E, 0x44, 0xB6, 0xB2, 0x58, 0x46, ++0xFF, 0xF7, 0x0A, 0xFC, 0xA3, 0xB2, 0xBB, 0x42, 0xEA, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x1F, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x1E, 0x48, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x1B, 0xF0, ++0xF7, 0xF9, 0x99, 0xF8, 0x02, 0x3C, 0xD8, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0x89, 0xF8, 0x02, 0x3C, 0x00, 0x2A, 0xC7, 0xD0, ++0x15, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xD1, 0x00, 0x2B, 0xBE, 0xD0, 0x62, 0xB6, ++0xD9, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0xBD, 0xD1, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x10, 0x20, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x0E, 0xF9, ++0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x84, 0x42, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x7C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0xB4, 0x80, 0x2A, 0x4E, 0xC1, 0x46, ++0xA8, 0xF1, 0x06, 0x07, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0x33, 0xD0, 0x1D, 0x89, 0x5C, 0x68, 0x7D, 0xB1, 0x4F, 0xF0, ++0x00, 0x0B, 0x20, 0x68, 0xA2, 0x46, 0x0B, 0xF1, 0x01, 0x0B, 0x64, 0x68, 0xFF, 0xF7, 0x5E, 0xFA, 0x50, 0x46, 0xFF, 0xF7, ++0x9D, 0xFB, 0x1F, 0xFA, 0x8B, 0xF2, 0xAA, 0x42, 0xF1, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x1B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x33, 0x68, 0x48, 0x46, 0x01, 0x33, 0x33, 0x60, 0x1B, 0xF0, 0x8B, 0xF9, 0x3B, 0x78, ++0x32, 0x68, 0x01, 0x3B, 0x3B, 0x70, 0x00, 0x2A, 0xD4, 0xD0, 0x14, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0x32, 0x60, 0x00, 0x2A, ++0xCE, 0xD1, 0x00, 0x2B, 0xCC, 0xD0, 0x62, 0xB6, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0xCB, 0xD1, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x33, 0x68, 0x08, 0x20, 0x01, 0x33, 0x33, 0x60, ++0x1B, 0xF0, 0xA8, 0xF8, 0x33, 0x68, 0x33, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x94, 0x4E, 0x17, 0x00, ++0x10, 0xB5, 0x04, 0x20, 0x1B, 0xF0, 0x92, 0xF8, 0x03, 0x4B, 0x04, 0x49, 0xD3, 0xF8, 0x10, 0x31, 0x03, 0x48, 0xBD, 0xE8, ++0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x28, 0x60, 0x17, 0x00, 0xF8, 0xB5, 0xA8, 0x4B, ++0xA8, 0x4A, 0x1B, 0x68, 0x14, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB7, 0x81, 0x65, 0x05, 0x18, 0xD5, ++0xA4, 0x4A, 0x13, 0x68, 0x98, 0x00, 0xFC, 0xD4, 0xA3, 0x4B, 0xA2, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x13, 0xF0, 0x00, 0x53, ++0xFB, 0xD1, 0xA1, 0x49, 0xA1, 0x48, 0x0A, 0x68, 0x42, 0xF0, 0x10, 0x02, 0x0A, 0x60, 0x02, 0x78, 0x02, 0xB1, 0x03, 0x70, ++0x9E, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0xE0, 0x81, 0x21, 0x05, 0x09, 0xD5, 0x97, 0x4A, 0x13, 0x68, 0x9B, 0x00, ++0xFC, 0xD4, 0x9A, 0x4B, 0x94, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0xE2, 0x04, 0x05, 0xD5, 0x94, 0x49, ++0x96, 0x4B, 0x97, 0x4A, 0x01, 0x20, 0x08, 0x70, 0x1A, 0x60, 0x66, 0x06, 0x04, 0xD5, 0x95, 0x4B, 0x95, 0x48, 0x19, 0x68, ++0x1C, 0xF0, 0x9C, 0xFA, 0x14, 0xF4, 0x9B, 0x7F, 0x40, 0xF0, 0x89, 0x81, 0xA5, 0x05, 0x00, 0xF1, 0x8D, 0x81, 0x20, 0x06, ++0x00, 0xF1, 0x94, 0x81, 0x21, 0x04, 0x00, 0xF1, 0x9F, 0x81, 0xE2, 0x02, 0x00, 0xF1, 0xA6, 0x81, 0xA3, 0x02, 0x03, 0xD5, ++0x8B, 0x4B, 0x4F, 0xF4, 0x00, 0x12, 0x1A, 0x60, 0xE7, 0x03, 0x41, 0xD5, 0x89, 0x4B, 0x93, 0xF8, 0x11, 0x15, 0x93, 0xF8, ++0x12, 0x25, 0x91, 0x42, 0x80, 0xF0, 0xB1, 0x81, 0x93, 0xF8, 0x10, 0x05, 0x85, 0x4A, 0x86, 0x4D, 0x86, 0x4E, 0x01, 0x30, ++0xA2, 0xFB, 0x00, 0x72, 0x92, 0x09, 0x02, 0xEB, 0xC2, 0x02, 0x02, 0xEB, 0xC2, 0x02, 0x82, 0x1A, 0x01, 0x31, 0x83, 0xF8, ++0x11, 0x15, 0x83, 0xF8, 0x10, 0x25, 0x03, 0xEB, 0x02, 0x11, 0x30, 0x68, 0x2E, 0x68, 0x4E, 0x60, 0x6E, 0x68, 0x8E, 0x60, ++0x28, 0x3D, 0xC0, 0xF3, 0x00, 0x26, 0x08, 0x73, 0x4E, 0x73, 0x28, 0x68, 0x40, 0xF0, 0x10, 0x00, 0x11, 0x01, 0x28, 0x60, ++0x28, 0x68, 0x86, 0x06, 0xFC, 0xD4, 0x19, 0x44, 0x75, 0x4B, 0x8A, 0x68, 0x75, 0x48, 0x52, 0x68, 0x1A, 0x60, 0x2B, 0x68, ++0x23, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x1B, 0xF0, 0x6F, 0xF8, 0x20, 0x20, 0x1A, 0xF0, 0xCA, 0xFF, 0x69, 0x4B, 0x4F, 0xF4, ++0x80, 0x32, 0x1A, 0x60, 0x65, 0x03, 0x4E, 0xD5, 0x67, 0x4B, 0x93, 0xF8, 0x9D, 0x17, 0x93, 0xF8, 0x9E, 0x27, 0x91, 0x42, ++0x80, 0xF0, 0x7B, 0x81, 0x93, 0xF8, 0x9C, 0x07, 0x68, 0x4A, 0x69, 0x4F, 0x69, 0x4D, 0xDF, 0xF8, 0xE0, 0xC1, 0x01, 0x30, ++0xA2, 0xFB, 0x00, 0x62, 0x56, 0x09, 0x06, 0xEB, 0x86, 0x06, 0xA0, 0xEB, 0xC6, 0x06, 0x4A, 0x1C, 0x83, 0xF8, 0x9D, 0x27, ++0x83, 0xF8, 0x9C, 0x67, 0x03, 0xEB, 0x06, 0x11, 0x3A, 0x68, 0x28, 0x68, 0xC1, 0xF8, 0x20, 0x05, 0x06, 0xF1, 0x52, 0x07, ++0x03, 0xEB, 0x07, 0x15, 0xDC, 0xF8, 0x00, 0x10, 0x5C, 0x48, 0x69, 0x60, 0xC2, 0xF3, 0x00, 0x21, 0x69, 0x72, 0x2A, 0x72, ++0x05, 0x68, 0x45, 0xF0, 0x04, 0x05, 0x05, 0x60, 0x31, 0x01, 0x05, 0x46, 0x2A, 0x68, 0x10, 0x07, 0xFC, 0xD4, 0x03, 0xEB, ++0x07, 0x12, 0x01, 0xF2, 0x1C, 0x51, 0x50, 0x68, 0x53, 0x4A, 0x40, 0x68, 0x10, 0x60, 0x2A, 0x68, 0x52, 0x48, 0x22, 0xF0, ++0x04, 0x02, 0x19, 0x44, 0x2A, 0x60, 0x1B, 0xF0, 0x1F, 0xF8, 0x4F, 0xF4, 0x00, 0x00, 0x1A, 0xF0, 0x79, 0xFF, 0x41, 0x4B, ++0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0xA2, 0x03, 0x1B, 0xD5, 0x4B, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0x35, 0x81, ++0x49, 0x48, 0x90, 0xF8, 0x02, 0x1C, 0x90, 0xF8, 0x01, 0x2C, 0x91, 0x42, 0xC0, 0xF0, 0xA2, 0x80, 0x46, 0x48, 0x1C, 0xF0, ++0xDF, 0xF9, 0x36, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x1A, 0x60, 0x44, 0x4B, 0x1B, 0x68, 0x23, 0xB9, 0x43, 0x4A, 0x13, 0x78, ++0x23, 0xF0, 0x01, 0x03, 0x13, 0x70, 0x23, 0x03, 0x1D, 0xD5, 0x3C, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0x09, 0x81, ++0x3A, 0x48, 0x41, 0xF6, 0x12, 0x04, 0x41, 0xF6, 0x11, 0x03, 0x02, 0x5D, 0xC3, 0x5C, 0x93, 0x42, 0x10, 0xD8, 0x11, 0x46, ++0x39, 0x48, 0x1C, 0xF0, 0xBF, 0xF9, 0x26, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x37, 0x4B, 0x1B, 0x68, 0x23, 0xB9, ++0x33, 0x4A, 0x13, 0x78, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x70, 0xF8, 0xBD, 0x41, 0xF6, 0x10, 0x05, 0x32, 0x4B, 0x41, 0x5D, ++0x01, 0x31, 0xA3, 0xFB, 0x01, 0x63, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, 0xA1, 0xEB, 0x83, 0x13, 0x43, 0x55, 0x03, 0xF1, ++0xC1, 0x01, 0x2D, 0x4E, 0x00, 0xEB, 0x01, 0x11, 0x35, 0x68, 0x4D, 0x60, 0x2B, 0x4D, 0x00, 0xEB, 0x03, 0x13, 0x01, 0x32, ++0x2D, 0x68, 0xA3, 0xF8, 0x18, 0x5C, 0x02, 0x55, 0x28, 0x48, 0x1A, 0xF0, 0xB9, 0xFF, 0x08, 0x20, 0x1A, 0xF0, 0x14, 0xFF, ++0x0E, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0xCF, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x24, 0x00, 0x24, 0x40, ++0x40, 0x00, 0x24, 0x40, 0x01, 0x09, 0x00, 0x32, 0x44, 0x00, 0x24, 0x40, 0x1C, 0x26, 0x17, 0x00, 0x3C, 0x36, 0x17, 0x00, ++0x02, 0x09, 0x00, 0x32, 0x2C, 0x00, 0x24, 0x40, 0x09, 0x70, 0x00, 0xCF, 0x08, 0x00, 0x24, 0x40, 0xDC, 0x82, 0x15, 0x00, ++0x28, 0x00, 0x24, 0x40, 0x58, 0x58, 0x17, 0x00, 0xE7, 0x87, 0x45, 0xCA, 0x88, 0x00, 0x24, 0x40, 0x90, 0x00, 0x24, 0x40, ++0x74, 0x00, 0x24, 0x40, 0x6C, 0x5D, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, 0x84, 0x00, 0x24, 0x40, 0x7C, 0x00, 0x24, 0x40, ++0x60, 0x00, 0x24, 0x40, 0x6C, 0x00, 0x24, 0x40, 0xF8, 0x5F, 0x17, 0x00, 0x1D, 0x26, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x80, 0x83, 0x15, 0x00, 0xA0, 0x00, 0x24, 0x40, 0x9C, 0x4E, 0x17, 0x00, 0x98, 0x83, 0x15, 0x00, 0x98, 0x00, 0x24, 0x40, ++0xAB, 0xAA, 0xAA, 0xAA, 0xA4, 0x00, 0x24, 0x40, 0xA8, 0x00, 0x24, 0x40, 0x94, 0x4E, 0x17, 0x00, 0x80, 0x00, 0x24, 0x40, ++0x90, 0xF8, 0x00, 0x2C, 0x4B, 0x4B, 0x4C, 0x4D, 0x01, 0x32, 0xA3, 0xFB, 0x02, 0x63, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, ++0xA2, 0xEB, 0x83, 0x13, 0x00, 0xEB, 0x03, 0x12, 0x2D, 0x68, 0x55, 0x60, 0x46, 0x4D, 0x80, 0xF8, 0x00, 0x3C, 0x2B, 0x68, ++0x13, 0x81, 0x01, 0x31, 0x80, 0xF8, 0x02, 0x1C, 0x11, 0x46, 0x00, 0xF6, 0x08, 0x40, 0x1A, 0xF0, 0x49, 0xFF, 0x10, 0x20, ++0x1A, 0xF0, 0xA4, 0xFE, 0x3F, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x1A, 0x60, 0x3F, 0xE7, 0x00, 0x2C, 0x7F, 0xF4, 0x46, 0xAE, ++0x3C, 0x49, 0x3D, 0x48, 0x26, 0x22, 0x1C, 0xF0, 0x8D, 0xFB, 0x14, 0xF4, 0x9B, 0x7F, 0x3F, 0xF4, 0x77, 0xAE, 0x3A, 0x48, ++0x21, 0x46, 0x1C, 0xF0, 0x0B, 0xF9, 0xA5, 0x05, 0x7F, 0xF5, 0x73, 0xAE, 0x37, 0x48, 0x1C, 0xF0, 0x05, 0xF9, 0x32, 0x4B, ++0x4F, 0xF4, 0x00, 0x72, 0x20, 0x06, 0x1A, 0x60, 0x7F, 0xF5, 0x6C, 0xAE, 0x33, 0x48, 0x1C, 0xF0, 0xFB, 0xF8, 0x33, 0x4A, ++0x2C, 0x49, 0x13, 0x68, 0x80, 0x20, 0x23, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x08, 0x60, 0x21, 0x04, 0x7F, 0xF5, 0x61, 0xAE, ++0x2E, 0x48, 0x1C, 0xF0, 0xED, 0xF8, 0x26, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0x1A, 0x60, 0xE2, 0x02, 0x7F, 0xF5, 0x5A, 0xAE, ++0x2A, 0x4A, 0x2B, 0x4B, 0x15, 0x68, 0x2B, 0x48, 0x1A, 0x78, 0x29, 0x46, 0xFD, 0xF7, 0x14, 0xFF, 0x29, 0x4A, 0x1E, 0x4B, ++0x15, 0x60, 0x4F, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x4A, 0xE6, 0x27, 0x4A, 0x01, 0x21, 0x59, 0x70, 0x13, 0x68, 0x26, 0x49, ++0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x02, 0x20, 0x1C, 0xF0, 0x1C, 0xF9, 0x13, 0xE6, 0x23, 0x48, 0x1C, 0xF0, 0xC8, 0xF8, ++0x13, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x1A, 0x60, 0x80, 0xE6, 0x00, 0x22, 0x02, 0x20, 0x1A, 0x70, 0xFD, 0xF7, 0x86, 0xFF, ++0xF0, 0xE6, 0x1D, 0x48, 0x1C, 0xF0, 0xBA, 0xF8, 0x0C, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0xC3, 0xE6, 0x00, 0x22, ++0x02, 0x20, 0x1A, 0x70, 0xFD, 0xF7, 0x78, 0xFF, 0x17, 0x48, 0x90, 0xF8, 0x02, 0x1C, 0x90, 0xF8, 0x01, 0x2C, 0x91, 0x42, ++0xBF, 0xF4, 0xC6, 0xAE, 0x66, 0xE7, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, 0xAC, 0x00, 0x24, 0x40, 0xB0, 0x00, 0x24, 0x40, ++0x28, 0x00, 0x24, 0x40, 0x70, 0x79, 0x15, 0x00, 0xC0, 0x82, 0x15, 0x00, 0xEC, 0x82, 0x15, 0x00, 0x08, 0x83, 0x15, 0x00, ++0x1C, 0x83, 0x15, 0x00, 0x4C, 0x00, 0x24, 0x40, 0x30, 0x83, 0x15, 0x00, 0x30, 0x00, 0x24, 0x40, 0x45, 0x00, 0x24, 0x40, ++0x48, 0x83, 0x15, 0x00, 0x34, 0x00, 0x24, 0x40, 0x10, 0x00, 0x58, 0x40, 0xD0, 0x82, 0x15, 0x00, 0xCC, 0x7C, 0x15, 0x00, ++0x64, 0x83, 0x15, 0x00, 0x7C, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x47, 0x4B, 0x1A, 0x68, 0x42, 0xF0, 0x10, 0x02, 0x1A, 0x60, ++0x1B, 0x68, 0x5A, 0x07, 0x7F, 0xD4, 0x44, 0x49, 0x0B, 0x68, 0x9B, 0x00, 0xFC, 0xD4, 0x43, 0x4B, 0x41, 0x4A, 0x0B, 0x60, ++0x13, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0x13, 0x68, 0x9E, 0x07, 0x03, 0xD4, 0x3C, 0x4A, 0x13, 0x68, 0xDD, 0x07, 0xFC, 0xD5, ++0x3A, 0x4A, 0x3D, 0x4D, 0x13, 0x68, 0x3D, 0x48, 0x3D, 0x49, 0x3E, 0x4C, 0x3E, 0x4F, 0x3F, 0x4E, 0x43, 0xF0, 0x02, 0x03, ++0x13, 0x60, 0x2B, 0x68, 0x03, 0x40, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x2B, 0x68, 0x9B, 0xB2, 0x43, 0xF4, 0x80, 0x13, ++0x2B, 0x60, 0x0B, 0x68, 0x03, 0x40, 0x43, 0xF0, 0x10, 0x03, 0x0B, 0x60, 0x0B, 0x68, 0x9B, 0xB2, 0x43, 0xF4, 0x80, 0x13, ++0x0B, 0x60, 0x4F, 0xF6, 0xFF, 0x73, 0x23, 0x60, 0x52, 0xF8, 0x34, 0x3C, 0x03, 0x40, 0x43, 0xF4, 0x88, 0x53, 0x43, 0xF0, ++0x11, 0x03, 0x42, 0xF8, 0x34, 0x3C, 0x03, 0x23, 0xAB, 0x64, 0x4F, 0xF4, 0xFC, 0x53, 0x3B, 0x60, 0x4F, 0xF0, 0xFF, 0x33, ++0x33, 0x60, 0x2A, 0x48, 0x2A, 0x4B, 0x23, 0x62, 0x00, 0x24, 0x20, 0x23, 0x04, 0x60, 0x41, 0xF8, 0xAC, 0x3C, 0x52, 0xF8, ++0x34, 0x3C, 0x27, 0x4C, 0x27, 0x48, 0x23, 0xF4, 0x7F, 0x03, 0x43, 0xF4, 0x80, 0x33, 0x42, 0xF8, 0x34, 0x3C, 0x41, 0xF8, ++0x84, 0x4C, 0x1C, 0xF0, 0x1B, 0xF8, 0x17, 0x4B, 0x17, 0x49, 0x1A, 0x68, 0x94, 0x00, 0xFC, 0xD4, 0x19, 0x60, 0x1A, 0x68, ++0x90, 0x00, 0xFC, 0xD4, 0x1A, 0x68, 0x12, 0xF0, 0x06, 0x0F, 0xF4, 0xD0, 0x10, 0x4A, 0x13, 0x68, 0x99, 0x00, 0xFC, 0xD4, ++0x1A, 0x4B, 0x0E, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x9B, 0x00, 0xFC, 0xD4, 0x18, 0x48, 0x1C, 0xF0, 0x01, 0xF8, 0x18, 0x4B, ++0x18, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0xFC, 0x12, 0x91, 0x67, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF4, 0x80, 0x42, 0x1A, 0x60, ++0xF8, 0xBD, 0x14, 0x4B, 0x0C, 0x4A, 0x1A, 0x60, 0xFE, 0xF7, 0x9A, 0xFB, 0xED, 0xE7, 0x00, 0xBF, 0x44, 0x00, 0x24, 0x40, ++0x40, 0x00, 0x24, 0x40, 0x00, 0x02, 0x00, 0x20, 0x04, 0x00, 0x24, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x24, 0x40, ++0x0C, 0x00, 0x24, 0x40, 0xB4, 0x00, 0x24, 0x40, 0x28, 0x00, 0x24, 0x40, 0x38, 0x00, 0x24, 0x40, 0x09, 0x60, 0x00, 0xCF, ++0x00, 0x00, 0x20, 0x4E, 0xB8, 0x83, 0x15, 0x00, 0x06, 0x03, 0x00, 0x30, 0xCC, 0x83, 0x15, 0x00, 0x00, 0xED, 0x00, 0xE0, ++0x88, 0x1A, 0x17, 0x00, 0x2C, 0x00, 0x24, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x82, 0xB0, 0xEF, 0xF3, 0x10, 0x83, ++0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x24, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x23, 0x4E, 0x24, 0x4B, 0x35, 0x68, 0x1B, 0x68, ++0x01, 0x35, 0x35, 0x60, 0x1C, 0x78, 0x01, 0x2C, 0x2B, 0xD0, 0x21, 0x4C, 0x23, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x23, 0x60, ++0x23, 0x68, 0x9B, 0x05, 0xFC, 0xD4, 0x1E, 0x4B, 0x18, 0x68, 0xC8, 0xB1, 0x1D, 0x4B, 0x1E, 0x4C, 0xD3, 0xF8, 0x04, 0x0C, ++0x47, 0x60, 0x20, 0x68, 0x01, 0x44, 0x21, 0x60, 0x17, 0x49, 0xC3, 0xF8, 0x04, 0x2C, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x73, ++0x0B, 0x60, 0x35, 0xB1, 0x10, 0x4B, 0x01, 0x3D, 0x1B, 0x68, 0x35, 0x60, 0x0D, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x02, 0xB0, ++0xBD, 0xE8, 0xF0, 0x81, 0x11, 0x48, 0x1F, 0x60, 0x04, 0x68, 0x0F, 0x4B, 0x21, 0x44, 0x01, 0x60, 0xE6, 0xE7, 0xDF, 0xF8, ++0x3C, 0x80, 0x98, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0xCD, 0xD1, 0x02, 0x20, 0xCD, 0xE9, 0x00, 0x12, 0xFD, 0xF7, 0x3C, 0xFE, ++0xDD, 0xE9, 0x00, 0x12, 0x35, 0x68, 0x88, 0xF8, 0x00, 0x40, 0xC2, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x74, 0x36, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0xA0, 0x00, 0x24, 0x40, 0x7C, 0x36, 0x17, 0x00, 0x9C, 0x00, 0x24, 0x40, ++0x1D, 0x26, 0x17, 0x00, 0x30, 0xB4, 0x85, 0x68, 0x06, 0x4C, 0xC3, 0xF3, 0x0B, 0x03, 0x2C, 0x40, 0x02, 0x9D, 0x1C, 0x43, ++0x44, 0xEA, 0xC5, 0x74, 0x84, 0x60, 0xC0, 0xE9, 0x00, 0x12, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xF0, 0xFF, 0x7F, ++0xF8, 0xB5, 0x04, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x23, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x22, 0x4D, 0x23, 0x4B, 0x29, 0x68, 0x1B, 0x68, 0x01, 0x31, 0x29, 0x60, 0x1E, 0x78, 0x01, 0x2E, 0x30, 0xD0, 0x20, 0x4A, ++0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x13, 0x68, 0x1B, 0x06, 0xFC, 0xD4, 0x1D, 0x4B, 0x1A, 0x68, 0xF2, 0xB1, ++0x1C, 0x4B, 0x1D, 0x48, 0x41, 0xF6, 0x14, 0x02, 0x9A, 0x58, 0x54, 0x60, 0x02, 0x68, 0x01, 0x32, 0x02, 0x60, 0x41, 0xF6, ++0x14, 0x02, 0x15, 0x4E, 0x9C, 0x50, 0x18, 0x48, 0x32, 0x68, 0x03, 0x78, 0x22, 0xF0, 0x40, 0x02, 0x43, 0xF0, 0x02, 0x03, ++0x32, 0x60, 0x03, 0x70, 0x31, 0xB1, 0x0C, 0x4B, 0x01, 0x39, 0x1B, 0x68, 0x29, 0x60, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, ++0xF8, 0xBD, 0x0E, 0x48, 0x1C, 0x60, 0x02, 0x68, 0x0B, 0x4B, 0x01, 0x32, 0x02, 0x60, 0xE2, 0xE7, 0x0C, 0x4F, 0x3B, 0x78, ++0x00, 0x2B, 0xCA, 0xD1, 0x02, 0x20, 0xFD, 0xF7, 0xC9, 0xFD, 0x29, 0x68, 0x3E, 0x70, 0xC4, 0xE7, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0x98, 0x00, 0x24, 0x40, 0x7C, 0x36, 0x17, 0x00, ++0x94, 0x00, 0x24, 0x40, 0x9C, 0x4E, 0x17, 0x00, 0x1D, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x80, 0x46, 0x04, 0x20, ++0x0F, 0x46, 0x15, 0x46, 0xFE, 0xF7, 0xF0, 0xFD, 0x68, 0xB3, 0x04, 0x46, 0xFE, 0xF7, 0x34, 0xFF, 0x06, 0x46, 0x00, 0xB3, ++0xC5, 0xF3, 0x03, 0x23, 0x4F, 0xF0, 0x00, 0x09, 0x25, 0x70, 0x63, 0x70, 0x2A, 0x46, 0x84, 0xF8, 0x02, 0x80, 0x39, 0x46, ++0x84, 0xF8, 0x03, 0x90, 0x20, 0x1D, 0x2E, 0xF0, 0xF9, 0xFB, 0xB2, 0x68, 0x0E, 0x4B, 0xC6, 0xF8, 0x04, 0x90, 0x04, 0x35, ++0x13, 0x40, 0xC5, 0xF3, 0x0B, 0x05, 0x1D, 0x43, 0x45, 0xF0, 0x00, 0x45, 0x34, 0x60, 0xB5, 0x60, 0x30, 0x46, 0xBD, 0xE8, ++0xF8, 0x43, 0xFF, 0xF7, 0x71, 0xBF, 0x07, 0x48, 0x1C, 0xF0, 0xCC, 0xFF, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0xFE, 0xF7, ++0xE7, 0xBD, 0xBD, 0xE8, 0xF8, 0x43, 0x03, 0x48, 0x1C, 0xF0, 0xC2, 0xBF, 0x00, 0xF0, 0xFF, 0x7F, 0xEC, 0x83, 0x15, 0x00, ++0xD8, 0x83, 0x15, 0x00, 0x05, 0x4B, 0x1B, 0x78, 0x33, 0xB9, 0x05, 0x4B, 0x18, 0x68, 0x6F, 0xEA, 0x10, 0x10, 0x00, 0xF0, ++0x01, 0x00, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x1C, 0x26, 0x17, 0x00, 0x44, 0x00, 0x24, 0x40, 0x44, 0x4A, 0x13, 0x69, ++0x43, 0xF0, 0x01, 0x03, 0x30, 0xB4, 0x13, 0x61, 0x13, 0x69, 0xD9, 0x07, 0xFC, 0xD4, 0x40, 0x4A, 0x13, 0x69, 0x00, 0x2B, ++0xFC, 0xDA, 0xD3, 0x68, 0x3E, 0x48, 0x3D, 0x49, 0x43, 0xF0, 0x80, 0x43, 0x43, 0xF0, 0x07, 0x03, 0xD3, 0x60, 0xD3, 0x68, ++0x18, 0x43, 0xD0, 0x60, 0xD3, 0x68, 0x23, 0xF4, 0x71, 0x53, 0x23, 0xF0, 0x28, 0x03, 0xD3, 0x60, 0x13, 0x69, 0x43, 0xF0, ++0x01, 0x03, 0x13, 0x61, 0x0B, 0x69, 0xDA, 0x07, 0xFC, 0xD4, 0x32, 0x4B, 0x1A, 0x69, 0x00, 0x2A, 0xFC, 0xDA, 0xDA, 0x68, ++0x30, 0x48, 0x2F, 0x49, 0x42, 0xF0, 0x80, 0x42, 0x42, 0xF0, 0x07, 0x02, 0xDA, 0x60, 0xDA, 0x68, 0x10, 0x43, 0xD8, 0x60, ++0xDA, 0x68, 0x22, 0xF4, 0x71, 0x52, 0x22, 0xF0, 0x28, 0x02, 0xDA, 0x60, 0xD3, 0xF8, 0x00, 0x28, 0x22, 0xF4, 0xC0, 0x52, ++0x22, 0xF0, 0x03, 0x02, 0xC3, 0xF8, 0x00, 0x28, 0xD3, 0xF8, 0x00, 0x28, 0x42, 0xF4, 0x00, 0x02, 0x42, 0xF0, 0x04, 0x02, ++0xC3, 0xF8, 0x00, 0x28, 0x00, 0x24, 0x4F, 0xF0, 0xFF, 0x35, 0x01, 0x22, 0x9C, 0x61, 0x01, 0x2A, 0x5D, 0x61, 0xC3, 0xF8, ++0x1C, 0x48, 0xC3, 0xF8, 0x14, 0x48, 0xC3, 0xF8, 0x10, 0x48, 0xA2, 0xF1, 0x02, 0x03, 0x28, 0x46, 0x01, 0xEB, 0x43, 0x13, ++0x0B, 0xD0, 0x05, 0x2A, 0xC3, 0xF8, 0x28, 0x0B, 0xC3, 0xF8, 0x28, 0x09, 0x0A, 0xD0, 0x01, 0x32, 0x93, 0x1E, 0x01, 0x2A, ++0x01, 0xEB, 0x43, 0x13, 0xF3, 0xD1, 0xC1, 0xF8, 0x08, 0x0B, 0xC1, 0xF8, 0x08, 0x09, 0xF4, 0xE7, 0x0F, 0x48, 0x10, 0x4B, ++0x0C, 0x4A, 0x88, 0x61, 0x4B, 0x63, 0x53, 0x6B, 0x1B, 0x01, 0xFC, 0xD5, 0xD2, 0xF8, 0x04, 0x38, 0x23, 0xF0, 0x02, 0x03, ++0xC2, 0xF8, 0x04, 0x38, 0xD2, 0xF8, 0x04, 0x38, 0x2E, 0x21, 0x43, 0xF4, 0x00, 0x43, 0xC2, 0xF8, 0x04, 0x38, 0x91, 0x60, ++0x93, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x30, 0xBC, 0x93, 0x60, 0x70, 0x47, 0x00, 0x00, 0x20, 0x40, 0x10, 0x00, 0x06, 0x40, ++0x00, 0x38, 0x00, 0x80, 0x41, 0x00, 0x44, 0x02, 0x0A, 0x4B, 0x0B, 0x49, 0x1A, 0x68, 0x08, 0x68, 0x0A, 0x49, 0x0B, 0x4B, ++0xC2, 0xE9, 0x00, 0x10, 0xC3, 0xF8, 0x14, 0x2B, 0xD3, 0xF8, 0x08, 0x2B, 0xC3, 0xF8, 0x08, 0x2B, 0xD3, 0xF8, 0x00, 0x2B, ++0x42, 0xF0, 0x04, 0x42, 0xC3, 0xF8, 0x00, 0x2B, 0x70, 0x47, 0x00, 0xBF, 0x5C, 0x60, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, ++0x40, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x20, 0x40, 0x12, 0x4A, 0x13, 0x4B, 0x11, 0x68, 0x18, 0x68, 0x12, 0x4B, 0x30, 0xB4, ++0x12, 0x4C, 0x4F, 0xF0, 0x20, 0x62, 0x00, 0x25, 0x65, 0x81, 0xC1, 0xE9, 0x00, 0x20, 0x1A, 0x69, 0x22, 0xF4, 0xFC, 0x62, ++0x42, 0xF0, 0x20, 0x02, 0x1A, 0x61, 0x18, 0x69, 0x10, 0xF0, 0x20, 0x00, 0xFB, 0xD1, 0xD3, 0xF8, 0x08, 0x29, 0xC3, 0xF8, ++0x08, 0x29, 0xC3, 0xF8, 0x14, 0x19, 0xD3, 0xF8, 0x00, 0x29, 0x42, 0xF0, 0x04, 0x42, 0x30, 0xBC, 0xC3, 0xF8, 0x00, 0x29, ++0x70, 0x47, 0x00, 0xBF, 0x40, 0x60, 0x17, 0x00, 0x58, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xB4, 0x27, 0x17, 0x00, ++0x70, 0xB5, 0x0B, 0x4B, 0x04, 0x46, 0x01, 0x38, 0x03, 0xEB, 0x00, 0x10, 0x10, 0x22, 0x05, 0x7A, 0x00, 0x21, 0xF7, 0xF7, ++0x4D, 0xFB, 0x55, 0xB1, 0x06, 0x48, 0x00, 0xEB, 0x84, 0x04, 0x23, 0x6A, 0x2B, 0xB1, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, ++0x08, 0x46, 0x01, 0x22, 0x18, 0x47, 0x70, 0xBD, 0x08, 0x28, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0x70, 0xB5, 0x0B, 0x4B, ++0x04, 0x46, 0x01, 0x38, 0x03, 0xEB, 0x00, 0x10, 0x10, 0x22, 0xC5, 0x7A, 0x00, 0x21, 0xF7, 0xF7, 0x31, 0xFB, 0x55, 0xB1, ++0x06, 0x48, 0x00, 0xEB, 0x84, 0x04, 0x23, 0x6B, 0x2B, 0xB1, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0x08, 0x46, 0x01, 0x22, ++0x18, 0x47, 0x70, 0xBD, 0xC8, 0x27, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x24, 0x82, 0xB0, 0xE0, 0xB2, ++0x01, 0x90, 0x01, 0x34, 0xFF, 0xF7, 0xC0, 0xFF, 0x01, 0x98, 0xFF, 0xF7, 0xD9, 0xFF, 0x05, 0x2C, 0xF5, 0xD1, 0x02, 0xB0, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0xB5, 0x0C, 0x46, 0x00, 0x28, 0x39, 0xD0, 0x09, 0xBB, 0x1D, 0x4B, 0x1D, 0x4A, 0x1B, 0x68, ++0x51, 0x81, 0x1D, 0x4D, 0x4F, 0xF0, 0x42, 0x42, 0x1A, 0x60, 0xDA, 0x78, 0x42, 0xF0, 0x04, 0x02, 0xDA, 0x70, 0xD9, 0x78, ++0x28, 0x68, 0x19, 0x4A, 0x58, 0x60, 0x01, 0xF0, 0x07, 0x01, 0x41, 0xF0, 0x08, 0x01, 0xD9, 0x70, 0xD2, 0xF8, 0x08, 0x19, ++0xC2, 0xF8, 0x08, 0x19, 0xC2, 0xF8, 0x14, 0x39, 0xD2, 0xF8, 0x00, 0x39, 0x43, 0xF0, 0x04, 0x43, 0xC2, 0xF8, 0x00, 0x39, ++0x38, 0xBD, 0x0E, 0x4D, 0x01, 0x46, 0x22, 0x46, 0x28, 0x68, 0x2E, 0xF0, 0x71, 0xFA, 0x09, 0x4B, 0x09, 0x4A, 0x1B, 0x68, ++0x54, 0x81, 0x4F, 0xF0, 0x40, 0x41, 0xC2, 0x22, 0x40, 0x2C, 0x19, 0x60, 0x1C, 0x80, 0xDA, 0x70, 0xD3, 0xD1, 0xD2, 0xB2, ++0x6F, 0xF3, 0x82, 0x02, 0xDA, 0x70, 0xD2, 0xE7, 0x02, 0x4D, 0xEC, 0xE7, 0x40, 0x60, 0x17, 0x00, 0xB4, 0x27, 0x17, 0x00, ++0x58, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xF0, 0xB4, 0x80, 0xB3, 0x27, 0x4D, 0x43, 0x1E, 0x05, 0xEB, 0x43, 0x16, ++0x08, 0x36, 0x05, 0xEB, 0x43, 0x15, 0x2F, 0x68, 0x17, 0xF0, 0x80, 0x2F, 0x22, 0xD0, 0x23, 0x4B, 0x3B, 0x40, 0xB3, 0xF5, ++0x00, 0x3F, 0x2C, 0xD0, 0x21, 0x4C, 0xD4, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x00, 0x73, 0xC4, 0xF8, 0x04, 0x38, 0x63, 0x69, ++0x1B, 0x06, 0xFC, 0xD5, 0x2B, 0x68, 0x19, 0x43, 0x41, 0xF0, 0x00, 0x61, 0x41, 0xF4, 0x00, 0x41, 0x29, 0x60, 0x1A, 0xB1, ++0x2B, 0x68, 0x23, 0xEA, 0x02, 0x02, 0x2A, 0x60, 0x60, 0xB9, 0x16, 0x4A, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x80, 0x63, ++0xC2, 0xF8, 0x04, 0x38, 0xF0, 0xBC, 0xFF, 0xF7, 0x3D, 0xBF, 0x12, 0x4E, 0x12, 0x4D, 0xD2, 0xE7, 0x00, 0x2F, 0x0C, 0xDB, ++0x3B, 0x04, 0xEE, 0xD4, 0x2B, 0x68, 0x23, 0xF4, 0x00, 0x43, 0x2B, 0x60, 0xE9, 0xE7, 0xB1, 0xF1, 0x00, 0x6F, 0xCF, 0xD1, ++0x00, 0x2A, 0xCD, 0xD1, 0xEA, 0xE7, 0x02, 0x23, 0x33, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x2B, 0x60, 0x33, 0x68, ++0x9A, 0x07, 0xFC, 0xD5, 0x3B, 0x04, 0xD8, 0xD4, 0xE8, 0xE7, 0x00, 0xBF, 0x20, 0x0B, 0x20, 0x40, 0x00, 0x00, 0x02, 0x80, ++0x00, 0x00, 0x20, 0x40, 0x08, 0x0B, 0x20, 0x40, 0x00, 0x0B, 0x20, 0x40, 0x70, 0xB4, 0x70, 0xB3, 0x44, 0x1E, 0x36, 0x4B, ++0x66, 0x01, 0x03, 0xEB, 0x44, 0x14, 0xF5, 0x58, 0x15, 0xF0, 0x80, 0x2F, 0x4D, 0xD0, 0x08, 0x36, 0x33, 0x44, 0x32, 0x4E, ++0x2E, 0x40, 0xB6, 0xF5, 0x00, 0x3F, 0x29, 0xD1, 0xB1, 0xF1, 0x00, 0x6F, 0x46, 0xD0, 0x40, 0x26, 0x1E, 0x60, 0x23, 0x68, ++0x0B, 0x43, 0x43, 0xF0, 0x00, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x23, 0x60, 0x00, 0x2A, 0x45, 0xD1, 0x29, 0x4A, 0x83, 0x01, ++0x43, 0xF0, 0x20, 0x03, 0x13, 0x61, 0x13, 0x69, 0x99, 0x06, 0xFC, 0xD4, 0x2B, 0x04, 0x03, 0xD4, 0x23, 0x68, 0x23, 0xF4, ++0x00, 0x43, 0x23, 0x60, 0x48, 0xBB, 0x70, 0xBC, 0x70, 0x47, 0x22, 0x4C, 0x25, 0x68, 0x15, 0xF0, 0x80, 0x2F, 0xF8, 0xD0, ++0x1D, 0x4E, 0x20, 0x4B, 0x2E, 0x40, 0xB6, 0xF5, 0x00, 0x3F, 0xD5, 0xD0, 0x40, 0x26, 0x1E, 0x60, 0x26, 0x68, 0x31, 0x43, ++0x41, 0xF0, 0x00, 0x61, 0x41, 0xF4, 0x00, 0x41, 0x00, 0x2D, 0x21, 0x60, 0xD6, 0xDA, 0xAE, 0x03, 0x04, 0xD4, 0x19, 0x68, ++0x49, 0x06, 0xFC, 0xD5, 0x40, 0x21, 0x19, 0x60, 0xDA, 0xB9, 0x02, 0x22, 0x1A, 0x60, 0x22, 0x68, 0x42, 0xF0, 0x80, 0x42, ++0x22, 0x60, 0x1A, 0x68, 0x96, 0x07, 0xFC, 0xD5, 0xC6, 0xE7, 0x70, 0xBC, 0xFF, 0xF7, 0xD4, 0xBE, 0x00, 0x2A, 0xCF, 0xD0, ++0x40, 0x21, 0x19, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x23, 0x60, 0x23, 0x68, 0x23, 0xEA, ++0x02, 0x02, 0x22, 0x60, 0xB4, 0xE7, 0x21, 0x68, 0x21, 0xEA, 0x02, 0x02, 0x22, 0x60, 0xDE, 0xE7, 0x20, 0x09, 0x20, 0x40, ++0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x40, 0x00, 0x09, 0x20, 0x40, 0x08, 0x09, 0x20, 0x40, 0x49, 0xB9, 0x0A, 0x4B, ++0x0A, 0x4A, 0x01, 0x28, 0x0C, 0xBF, 0x18, 0x46, 0x10, 0x46, 0x00, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x01, 0x28, ++0x0C, 0xBF, 0x04, 0x48, 0x04, 0x48, 0x49, 0x01, 0x08, 0x44, 0x00, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x09, 0x20, 0x40, 0x00, 0x0B, 0x20, 0x40, 0x38, 0xB9, 0x04, 0x29, 0x0D, 0xD8, 0x02, 0x46, 0x08, 0x46, 0x4F, 0xF0, ++0x00, 0x61, 0xFF, 0xF7, 0x07, 0xBF, 0x04, 0x29, 0x05, 0xD8, 0x08, 0x46, 0x00, 0x22, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, ++0x5B, 0xBF, 0x70, 0x47, 0x38, 0xB9, 0x04, 0x29, 0x0D, 0xD8, 0x02, 0x46, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0xFF, 0xF7, ++0xF5, 0xBE, 0x04, 0x29, 0x05, 0xD8, 0x08, 0x46, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x11, 0xFF, 0xF7, 0x49, 0xBF, 0x70, 0x47, ++0x40, 0xB9, 0x04, 0x29, 0x0F, 0xD8, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x12, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, 0xE2, 0xBE, ++0x04, 0x29, 0x06, 0xD8, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x12, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, 0x35, 0xBF, 0x70, 0x47, ++0xFF, 0xF7, 0xC6, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0x04, 0x46, 0x0D, 0x46, 0x57, 0x48, 0x00, 0x21, 0x1B, 0xF0, 0x04, 0xFC, ++0x00, 0x2C, 0x00, 0xF0, 0x95, 0x80, 0x23, 0x68, 0x00, 0x2B, 0x7B, 0xD0, 0x63, 0x68, 0x00, 0x2B, 0x78, 0xD0, 0xA3, 0x68, ++0x00, 0x2B, 0x75, 0xD0, 0x63, 0x69, 0x00, 0x2B, 0x72, 0xD0, 0x4F, 0x4E, 0x33, 0x78, 0x03, 0xF0, 0xFF, 0x07, 0x00, 0x2B, ++0x6F, 0xD1, 0xDF, 0xF8, 0x68, 0x81, 0x21, 0x46, 0x40, 0x46, 0x01, 0x24, 0x48, 0x22, 0x34, 0x70, 0x2E, 0xF0, 0x06, 0xF9, ++0x48, 0x4B, 0xD3, 0xF8, 0x94, 0x30, 0x00, 0x2B, 0x77, 0xD0, 0x47, 0x48, 0x1B, 0xF0, 0xDE, 0xFB, 0x46, 0x4B, 0xD3, 0xF8, ++0x00, 0x28, 0x12, 0xF4, 0xFE, 0x6F, 0x5B, 0xD0, 0x44, 0x49, 0x45, 0x4A, 0xD1, 0xF8, 0x00, 0xC0, 0x44, 0x49, 0x12, 0x68, ++0xDF, 0xF8, 0x30, 0x91, 0x09, 0x68, 0xC9, 0xF8, 0x04, 0x70, 0x04, 0x20, 0xC9, 0xF8, 0x08, 0x70, 0x89, 0xF8, 0x00, 0x70, ++0xC2, 0xF8, 0x04, 0xC0, 0x30, 0x70, 0xC3, 0xF8, 0x14, 0x2B, 0xC8, 0x78, 0x3C, 0x4A, 0x40, 0xF0, 0xC0, 0x00, 0xD2, 0xF8, ++0x00, 0xC0, 0xC8, 0x70, 0x9C, 0xF8, 0x03, 0x00, 0x39, 0x4A, 0x40, 0xF0, 0xC0, 0x00, 0x17, 0x68, 0x8C, 0xF8, 0x03, 0x00, ++0xF8, 0x78, 0xD2, 0xF8, 0x04, 0xE0, 0x40, 0xF0, 0xC0, 0x00, 0xF8, 0x70, 0x9E, 0xF8, 0x03, 0x00, 0xD2, 0xE9, 0x02, 0xC7, ++0x40, 0xF0, 0xC0, 0x02, 0x8E, 0xF8, 0x03, 0x20, 0x9C, 0xF8, 0x03, 0x20, 0x42, 0xF0, 0xC0, 0x02, 0x8C, 0xF8, 0x03, 0x20, ++0xFA, 0x78, 0x42, 0xF0, 0xC0, 0x02, 0xFA, 0x70, 0xC3, 0xF8, 0x14, 0x19, 0xFF, 0xF7, 0x86, 0xFD, 0xD8, 0xF8, 0x44, 0x30, ++0x89, 0xF8, 0x00, 0x40, 0x03, 0xB1, 0x98, 0x47, 0x26, 0x4B, 0x27, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0x04, 0x11, 0xD1, 0x67, ++0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF4, 0x00, 0x42, 0x01, 0x2D, 0x1A, 0x60, 0x23, 0xD0, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, ++0x02, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x03, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x9A, 0x68, 0xD2, 0x07, 0x14, 0xD5, 0x9A, 0x68, ++0x22, 0xF0, 0x01, 0x02, 0x9A, 0x60, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, 0xFF, 0xF7, ++0xC9, 0xFC, 0xD9, 0xE7, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x14, 0x48, 0xFD, 0xF7, 0x9C, 0xF9, 0x04, 0x20, 0xE2, 0xE7, ++0xFF, 0xF7, 0xBE, 0xFC, 0xCE, 0xE7, 0x11, 0x4B, 0x11, 0x48, 0x1B, 0x69, 0x1B, 0xF0, 0x5C, 0xFB, 0x33, 0x78, 0x04, 0x2B, ++0xFC, 0xD1, 0xD2, 0xE7, 0xFC, 0x83, 0x15, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x00, 0x00, 0x10, 0x40, 0x08, 0x84, 0x15, 0x00, ++0x00, 0x00, 0x20, 0x40, 0x60, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x44, 0x60, 0x17, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x84, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x34, 0x84, 0x15, 0x00, 0x20, 0x26, 0x17, 0x00, 0xB4, 0x27, 0x17, 0x00, 0x14, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0xC3, 0xF8, ++0x80, 0x20, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0x11, 0x4A, 0x11, 0x4B, 0x12, 0x48, 0x00, 0x21, 0x11, 0x70, ++0x9A, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x9A, 0x60, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, ++0x1A, 0x69, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x61, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, ++0x1A, 0x69, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x61, 0x48, 0x22, 0xF7, 0xF7, 0x9F, 0xB8, 0x00, 0xBF, 0x00, 0xE1, 0x00, 0xE0, ++0x6F, 0x26, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x4E, 0x1E, 0xF7, 0xB2, ++0x03, 0x2F, 0x41, 0xD8, 0x14, 0x46, 0x0D, 0x46, 0x9B, 0x46, 0x02, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0x04, 0xF0, 0xFD, 0x01, ++0x01, 0x29, 0x5B, 0xD0, 0xDF, 0x1C, 0xBF, 0x10, 0x7F, 0x00, 0xBF, 0xB2, 0xBA, 0x46, 0x4F, 0xEA, 0x07, 0x49, 0x4F, 0xEA, ++0x45, 0x18, 0x08, 0xF1, 0x80, 0x48, 0x08, 0xF5, 0x00, 0x18, 0xD8, 0xF8, 0x00, 0x19, 0x11, 0xF0, 0x80, 0x2F, 0x68, 0xD1, ++0xA2, 0x04, 0x02, 0xF4, 0x40, 0x22, 0xCB, 0xF3, 0x0A, 0x03, 0x3B, 0x4C, 0x13, 0x43, 0x43, 0xEA, 0x85, 0x53, 0x21, 0x88, ++0x43, 0xF0, 0xC0, 0x53, 0x43, 0xF4, 0x00, 0x43, 0xC8, 0xF8, 0x00, 0x39, 0x01, 0xEB, 0x0A, 0x03, 0xB3, 0xF5, 0xC0, 0x6F, ++0x5E, 0xDC, 0x34, 0x4A, 0x40, 0x36, 0x02, 0xEB, 0x86, 0x06, 0x41, 0xEA, 0x09, 0x03, 0x73, 0x60, 0xD2, 0xF8, 0x1C, 0x38, ++0x0F, 0x44, 0x01, 0x21, 0x01, 0xFA, 0x05, 0xF5, 0x1D, 0x43, 0x27, 0x80, 0xC2, 0xF8, 0x1C, 0x58, 0xBD, 0xE8, 0xF8, 0x8F, ++0x4E, 0x01, 0x06, 0xF1, 0x80, 0x46, 0x06, 0xF5, 0x00, 0x16, 0xD6, 0xF8, 0x00, 0x2B, 0x12, 0xF0, 0x80, 0x2F, 0x33, 0xD1, ++0xA4, 0x04, 0x04, 0xF4, 0x40, 0x24, 0xCB, 0xF3, 0x0A, 0x03, 0x23, 0x43, 0x43, 0xF0, 0xC0, 0x53, 0x21, 0x4A, 0x43, 0xF4, ++0x00, 0x43, 0xC6, 0xF8, 0x00, 0x3B, 0xD2, 0xF8, 0x1C, 0x38, 0x4F, 0xF4, 0x80, 0x31, 0x01, 0xFA, 0x05, 0xF5, 0x1D, 0x43, ++0xC2, 0xF8, 0x1C, 0x58, 0xBD, 0xE8, 0xF8, 0x8F, 0xB3, 0xF5, 0x48, 0x7F, 0x20, 0xD8, 0xDF, 0x1C, 0xBF, 0x10, 0x7F, 0x00, ++0xBF, 0xB2, 0xBA, 0x46, 0x4F, 0xEA, 0x07, 0x49, 0xBB, 0xF5, 0x80, 0x6F, 0x9D, 0xD9, 0x6F, 0xF4, 0x80, 0x63, 0x0B, 0xEB, ++0x03, 0x01, 0xB1, 0xF5, 0x80, 0x6F, 0x25, 0xBF, 0x10, 0x4B, 0xA3, 0xFB, 0x0B, 0x13, 0x4F, 0xEA, 0x5B, 0x0B, 0xC3, 0xF3, ++0x4F, 0x0B, 0x8E, 0xE7, 0xFF, 0xF7, 0x34, 0xFE, 0xC8, 0xE7, 0x10, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0x2F, 0xFE, 0x91, 0xE7, ++0x4F, 0xF4, 0xC8, 0x7A, 0x57, 0x46, 0x4F, 0xF0, 0xC8, 0x79, 0xDF, 0xE7, 0x06, 0x48, 0x52, 0x46, 0x4F, 0xF4, 0xC0, 0x63, ++0xFD, 0xF7, 0x9E, 0xF8, 0x21, 0x88, 0x98, 0xE7, 0x48, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xAB, 0xAA, 0xAA, 0xAA, ++0x40, 0x84, 0x15, 0x00, 0xF8, 0xB5, 0x27, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x3C, 0xD1, 0x44, 0x1E, 0xDF, 0xB2, 0xE3, 0xB2, ++0x04, 0x2B, 0x39, 0xD8, 0x8D, 0x07, 0x3D, 0xD1, 0x22, 0x4E, 0x4F, 0xEA, 0x04, 0x1E, 0x06, 0xEB, 0x04, 0x1C, 0x56, 0xF8, ++0x0E, 0x50, 0x8D, 0xBB, 0x43, 0x01, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x00, 0x13, 0xD3, 0xF8, 0x00, 0x0B, 0x00, 0x04, ++0x2A, 0xD5, 0x1B, 0x48, 0x46, 0xF8, 0x0E, 0x10, 0x50, 0xF8, 0x24, 0x00, 0x19, 0x4F, 0x01, 0x26, 0x8C, 0xF8, 0x08, 0x60, ++0xC6, 0x78, 0x64, 0x01, 0x04, 0xF1, 0x80, 0x44, 0xBA, 0x42, 0x04, 0xF5, 0x00, 0x14, 0x06, 0xF0, 0x31, 0x06, 0x28, 0xBF, ++0x3A, 0x46, 0x46, 0xF0, 0x0E, 0x06, 0xCC, 0xF8, 0x04, 0x20, 0x02, 0x80, 0x41, 0x60, 0xC6, 0x70, 0xC4, 0xF8, 0x34, 0x0B, ++0xD3, 0xF8, 0x00, 0x2B, 0x42, 0xF0, 0x04, 0x42, 0x28, 0x46, 0xC3, 0xF8, 0x00, 0x2B, 0xF8, 0xBD, 0x01, 0x20, 0xF8, 0xBD, ++0x02, 0x20, 0xF8, 0xBD, 0x38, 0x46, 0xF8, 0xBD, 0x05, 0x20, 0xF8, 0xBD, 0x06, 0x48, 0xFD, 0xF7, 0x47, 0xF8, 0x03, 0x20, ++0xF8, 0xBD, 0x00, 0xBF, 0x6F, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, 0xFF, 0xFF, 0x07, 0x00, ++0x80, 0x84, 0x15, 0x00, 0xF8, 0xB5, 0x28, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x3E, 0xD1, 0x44, 0x1E, 0xDF, 0xB2, 0xE3, 0xB2, ++0x04, 0x2B, 0x3B, 0xD8, 0x8D, 0x07, 0x3F, 0xD1, 0x23, 0x4E, 0x4F, 0xEA, 0x04, 0x1E, 0x06, 0xEB, 0x04, 0x1C, 0x56, 0xF8, ++0x0E, 0x50, 0x9D, 0xBB, 0x43, 0x01, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x00, 0x13, 0xD3, 0xF8, 0x00, 0x0B, 0x00, 0x04, ++0x2C, 0xD5, 0x1C, 0x48, 0x46, 0xF8, 0x0E, 0x10, 0x50, 0xF8, 0x24, 0x00, 0x1A, 0x4F, 0x01, 0x26, 0x8C, 0xF8, 0x08, 0x60, ++0xC6, 0x78, 0x64, 0x01, 0x04, 0xF1, 0x80, 0x44, 0xBA, 0x42, 0x04, 0xF5, 0x00, 0x14, 0x06, 0xF0, 0x31, 0x06, 0x28, 0xBF, ++0x3A, 0x46, 0x46, 0xF0, 0x0E, 0x06, 0xCC, 0xF8, 0x04, 0x20, 0x02, 0x80, 0x41, 0x60, 0xC6, 0x70, 0xC4, 0xF8, 0x34, 0x0B, ++0xD3, 0xF8, 0x00, 0x2B, 0x22, 0xF0, 0x04, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x28, 0x46, 0xC3, 0xF8, 0x00, 0x2B, 0xF8, 0xBD, ++0x01, 0x20, 0xF8, 0xBD, 0x02, 0x20, 0xF8, 0xBD, 0x38, 0x46, 0xF8, 0xBD, 0x05, 0x20, 0xF8, 0xBD, 0x06, 0x48, 0xFC, 0xF7, ++0xEB, 0xFF, 0x03, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x6F, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, ++0xFF, 0xFF, 0x07, 0x00, 0x80, 0x84, 0x15, 0x00, 0x10, 0xB5, 0x0C, 0x4C, 0x0C, 0x4B, 0xE0, 0x89, 0x18, 0x80, 0x20, 0xB9, ++0x0B, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x0A, 0x4B, 0x5B, 0x69, 0x4B, 0xB1, 0xC0, 0xB2, 0x98, 0x47, ++0x30, 0xB1, 0x06, 0x4A, 0x04, 0x21, 0x07, 0x23, 0x11, 0x70, 0x23, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, ++0xB4, 0x27, 0x17, 0x00, 0x6C, 0x26, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x46, ++0x00, 0x28, 0x70, 0xD1, 0x01, 0xF0, 0x21, 0x03, 0x21, 0x2B, 0x7F, 0xD0, 0xE1, 0x07, 0x76, 0xD5, 0x14, 0xF0, 0x08, 0x01, ++0x00, 0xF0, 0x8B, 0x80, 0xB5, 0x4D, 0x2B, 0x78, 0x00, 0x2B, 0x40, 0xF0, 0x76, 0x82, 0x63, 0x06, 0x40, 0xF1, 0x15, 0x81, ++0xB2, 0x4B, 0xD3, 0xF8, 0x14, 0x3B, 0x08, 0x3B, 0x00, 0x22, 0xC5, 0xE9, 0x01, 0x22, 0x02, 0x20, 0x28, 0x70, 0x1A, 0x78, ++0x29, 0x7B, 0xD2, 0x09, 0x62, 0xF3, 0xC7, 0x11, 0x29, 0x73, 0x19, 0x78, 0x2A, 0x7B, 0x49, 0x11, 0x61, 0xF3, 0x46, 0x12, ++0x2A, 0x73, 0x19, 0x78, 0x61, 0xF3, 0x04, 0x02, 0x2A, 0x73, 0x5A, 0x78, 0x6A, 0x73, 0xD9, 0x78, 0x9A, 0x78, 0x42, 0xEA, ++0x01, 0x22, 0xEA, 0x81, 0x59, 0x79, 0x1A, 0x79, 0x42, 0xEA, 0x01, 0x22, 0x2A, 0x82, 0xDA, 0x79, 0x9B, 0x79, 0x43, 0xEA, ++0x02, 0x23, 0x6B, 0x82, 0x23, 0xB9, 0x95, 0xF9, 0x0C, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x73, 0x82, 0x9A, 0x4B, 0x9B, 0x4C, ++0xD3, 0xF8, 0x14, 0x28, 0xE1, 0x68, 0x22, 0xF0, 0x10, 0x02, 0xC3, 0xF8, 0x14, 0x28, 0xD3, 0xF8, 0x10, 0x28, 0x22, 0xF0, ++0x10, 0x02, 0xC3, 0xF8, 0x10, 0x28, 0x21, 0xB1, 0x91, 0x48, 0x88, 0x47, 0x00, 0x28, 0x40, 0xF0, 0xB5, 0x80, 0x92, 0x4F, ++0x2B, 0x7B, 0x3A, 0x78, 0x13, 0xF0, 0x60, 0x0F, 0xD6, 0xB2, 0x40, 0xF0, 0xCF, 0x80, 0x68, 0x7B, 0x0B, 0x28, 0x00, 0xF2, ++0xDA, 0x80, 0xDF, 0xE8, 0x10, 0xF0, 0xDE, 0x00, 0x27, 0x01, 0xD8, 0x00, 0xFA, 0x00, 0xD8, 0x00, 0x8C, 0x00, 0x5D, 0x01, ++0xD8, 0x00, 0x4F, 0x01, 0x44, 0x01, 0x98, 0x01, 0x85, 0x01, 0x82, 0x4D, 0x2B, 0x78, 0x02, 0x2B, 0x53, 0xD0, 0xCA, 0x07, ++0x55, 0xD4, 0xA1, 0x06, 0x02, 0xD5, 0x2B, 0x78, 0x06, 0x2B, 0x3D, 0xD0, 0xF8, 0xBD, 0x7C, 0x4D, 0x22, 0x07, 0x2B, 0x78, ++0x35, 0xD5, 0x01, 0x2B, 0x8B, 0xD0, 0xF8, 0xBD, 0x79, 0x4A, 0xD2, 0xF8, 0x10, 0x3B, 0x03, 0xF0, 0x7F, 0x03, 0x40, 0x2B, ++0x7F, 0xF4, 0x78, 0xAF, 0xD2, 0xF8, 0x10, 0x3B, 0x18, 0x03, 0x7F, 0xF5, 0x73, 0xAF, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, ++0xDB, 0xBA, 0x74, 0x4B, 0x6F, 0x4D, 0x1E, 0x68, 0xF3, 0x78, 0x13, 0xF0, 0x01, 0x03, 0x40, 0xF0, 0xE2, 0x81, 0x2A, 0x78, ++0x02, 0x2A, 0x3F, 0xF4, 0x6E, 0xAF, 0x03, 0x2A, 0x00, 0xF0, 0xE6, 0x81, 0x05, 0x2A, 0x0D, 0xD1, 0x68, 0x4A, 0x2B, 0x70, ++0xD2, 0xF8, 0x14, 0x38, 0x23, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xD2, 0xF8, 0x10, 0x38, 0x23, 0xF0, 0x10, 0x03, ++0xC2, 0xF8, 0x10, 0x38, 0xFF, 0xF7, 0xBA, 0xFA, 0xBF, 0xE7, 0x02, 0x2B, 0xBD, 0xD1, 0x54, 0xE7, 0xFF, 0xF7, 0xB4, 0xFA, ++0x5D, 0x4A, 0x07, 0x23, 0x2B, 0x70, 0xD2, 0xF8, 0x14, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xBD, 0xE8, ++0xF8, 0x40, 0xFF, 0xF7, 0xC5, 0xBA, 0x5B, 0x48, 0xFC, 0xF7, 0xEC, 0xFE, 0x41, 0xE7, 0x04, 0x2B, 0x00, 0xF0, 0xDD, 0x81, ++0x07, 0x2B, 0xA4, 0xD1, 0x52, 0x4B, 0x57, 0x49, 0x00, 0x20, 0x28, 0x70, 0xD3, 0xF8, 0x14, 0x28, 0x22, 0xF0, 0x10, 0x02, ++0xC3, 0xF8, 0x14, 0x28, 0xD3, 0xF8, 0x10, 0x28, 0x22, 0xF0, 0x10, 0x02, 0xC3, 0xF8, 0x10, 0x28, 0x0A, 0x78, 0x00, 0x2A, ++0x96, 0xD0, 0xD3, 0xF8, 0x04, 0x48, 0x12, 0x01, 0x02, 0xF0, 0x70, 0x02, 0x24, 0xF0, 0x70, 0x04, 0x22, 0x43, 0xC3, 0xF8, ++0x04, 0x28, 0x08, 0x70, 0xF8, 0xBD, 0x43, 0x48, 0xE9, 0x89, 0xD0, 0xF8, 0x00, 0x28, 0x0B, 0x01, 0x22, 0xF4, 0xFE, 0x62, ++0x03, 0xF4, 0xFE, 0x63, 0x13, 0x43, 0x07, 0x22, 0xC0, 0xF8, 0x00, 0x38, 0x2A, 0x70, 0x00, 0x29, 0x40, 0xF0, 0xF2, 0x81, ++0x02, 0x23, 0x3B, 0x70, 0x04, 0x2E, 0x40, 0xF0, 0x9F, 0x80, 0x3B, 0x78, 0x04, 0x2B, 0x01, 0xD0, 0xFF, 0xF7, 0xE8, 0xFA, ++0x2B, 0x78, 0x03, 0x2B, 0x26, 0xD0, 0x04, 0x2B, 0x00, 0xF0, 0xAB, 0x80, 0x07, 0x2B, 0x00, 0xF0, 0x91, 0x80, 0x00, 0x24, ++0x22, 0x46, 0x20, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x2C, 0x70, 0xFF, 0xF7, 0x2F, 0xFB, 0x22, 0x46, 0x20, 0x46, 0x4F, 0xF4, ++0x00, 0x11, 0xFF, 0xF7, 0x85, 0xFB, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0x49, 0xBA, 0x2B, 0x4B, 0x1B, 0x68, 0x5B, 0x68, ++0xEA, 0xE6, 0x2C, 0x48, 0xFC, 0xF7, 0x8A, 0xFE, 0x04, 0x2E, 0xE4, 0xD1, 0x3B, 0x78, 0x04, 0x2B, 0xE1, 0xD0, 0xFF, 0xF7, ++0xBF, 0xFA, 0xDE, 0xE7, 0x6B, 0x68, 0x00, 0x2B, 0x7F, 0xF4, 0x57, 0xAF, 0x25, 0x4B, 0x6B, 0x60, 0x53, 0xE7, 0x04, 0x2E, ++0xD5, 0xD1, 0x3B, 0x78, 0x04, 0x2B, 0xF0, 0xD1, 0xD1, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0x00, 0xF0, 0xCB, 0x81, 0x2B, 0x8A, ++0x00, 0x2B, 0xE3, 0xD1, 0x2B, 0x7B, 0x03, 0xF0, 0x1F, 0x03, 0x01, 0x2B, 0x00, 0xF0, 0xCF, 0x81, 0x02, 0x2B, 0x00, 0xF0, ++0xC1, 0x80, 0x00, 0x2B, 0xE7, 0xD1, 0x19, 0x4A, 0x19, 0x4B, 0x12, 0x78, 0x1A, 0x80, 0x02, 0x21, 0x04, 0x22, 0x6B, 0x60, ++0x29, 0x81, 0x2A, 0x70, 0x5A, 0xE0, 0x3B, 0x78, 0x04, 0x2B, 0x02, 0xD0, 0x2B, 0x8A, 0x00, 0x2B, 0xC8, 0xD1, 0x2B, 0x7B, ++0x13, 0xF0, 0x1F, 0x03, 0x00, 0xF0, 0xB9, 0x81, 0x02, 0x2B, 0x03, 0xD1, 0xEB, 0x89, 0x00, 0x2B, 0x00, 0xF0, 0xBF, 0x81, ++0x07, 0x23, 0x04, 0x2E, 0x2B, 0x70, 0xA0, 0xD1, 0xC9, 0xE7, 0x00, 0xBF, 0xB4, 0x27, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, ++0x20, 0x26, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x98, 0x84, 0x15, 0x00, 0x70, 0x26, 0x17, 0x00, ++0xD8, 0x84, 0x15, 0x00, 0x74, 0x26, 0x17, 0x00, 0x6E, 0x26, 0x17, 0x00, 0x50, 0x28, 0x17, 0x00, 0x3B, 0x78, 0x04, 0x2B, ++0x02, 0xD0, 0x2B, 0x8A, 0x00, 0x2B, 0x9B, 0xD1, 0x2B, 0x7B, 0x03, 0xF0, 0x1F, 0x03, 0x02, 0x2B, 0xD8, 0xD1, 0xEB, 0x89, ++0x00, 0x2B, 0xD5, 0xD1, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, 0xC0, 0xF3, 0xC0, 0x10, 0xFF, 0xF7, 0xBF, 0xFB, 0x07, 0x23, ++0x04, 0x2E, 0x2B, 0x70, 0x00, 0xF0, 0x95, 0x81, 0xFF, 0xF7, 0xE6, 0xF9, 0xE7, 0xE6, 0xA9, 0x4B, 0xD3, 0xF8, 0xE0, 0x34, ++0x98, 0x47, 0x04, 0x46, 0x04, 0x2E, 0x5A, 0xD0, 0x00, 0x2C, 0x7F, 0xF4, 0x59, 0xAF, 0x60, 0xE7, 0xA4, 0x4B, 0x6B, 0x60, ++0x02, 0x22, 0x04, 0x23, 0x2A, 0x81, 0x2B, 0x70, 0x04, 0x2E, 0x3F, 0xF4, 0x4A, 0xAF, 0x29, 0x89, 0x68, 0x68, 0xFF, 0xF7, ++0x43, 0xFA, 0xCE, 0xE6, 0xE8, 0x89, 0x03, 0x0A, 0x01, 0x3B, 0x01, 0x0A, 0x0E, 0x2B, 0x3F, 0xF6, 0x62, 0xAF, 0x01, 0xA2, ++0x52, 0xF8, 0x23, 0xF0, 0xC1, 0x97, 0x12, 0x00, 0x05, 0x98, 0x12, 0x00, 0xF1, 0x97, 0x12, 0x00, 0xFF, 0x95, 0x12, 0x00, ++0xFF, 0x95, 0x12, 0x00, 0x65, 0x98, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, ++0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, ++0x45, 0x98, 0x12, 0x00, 0xA3, 0x69, 0x00, 0x2B, 0x3F, 0xF4, 0x40, 0xAF, 0xE9, 0x89, 0x28, 0x8A, 0x98, 0x47, 0x00, 0x28, ++0x3F, 0xF4, 0x3A, 0xAF, 0x85, 0x4A, 0x86, 0x4B, 0x29, 0x8A, 0x11, 0x80, 0xEA, 0x89, 0x1A, 0x70, 0x07, 0x23, 0x2B, 0x70, ++0x06, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0xDA, 0xB2, 0x7F, 0xF4, 0x2C, 0xAF, 0x7E, 0x4B, 0x7F, 0x49, 0x18, 0x88, 0x2A, 0x70, ++0x01, 0x23, 0x28, 0x82, 0x69, 0x60, 0x2B, 0x81, 0xAE, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0xA1, 0xD0, 0xFF, 0xF7, 0xE4, 0xF9, ++0x00, 0x2C, 0x7F, 0xF4, 0xF9, 0xAE, 0x00, 0xE7, 0x01, 0x46, 0xFF, 0xF7, 0x0B, 0xFB, 0x00, 0x28, 0x00, 0xF0, 0x05, 0x81, ++0x74, 0x4B, 0x01, 0x22, 0x1A, 0x80, 0x3A, 0xE7, 0x23, 0x68, 0x01, 0x20, 0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0x0A, 0xAF, ++0x03, 0x78, 0x12, 0x2B, 0x7F, 0xF4, 0x06, 0xAF, 0x42, 0x78, 0x01, 0x2A, 0x7F, 0xF4, 0x02, 0xAF, 0x2B, 0x81, 0x68, 0x60, ++0x6B, 0x8A, 0x2A, 0x89, 0x9A, 0x42, 0x88, 0xBF, 0x2B, 0x81, 0x04, 0x23, 0x2B, 0x70, 0x83, 0xE7, 0xA3, 0x68, 0xC0, 0xB2, ++0x98, 0x47, 0x68, 0x60, 0x00, 0x28, 0x3F, 0xF4, 0xF1, 0xAE, 0x03, 0x78, 0x2B, 0x81, 0xED, 0xE7, 0x63, 0x68, 0x00, 0x20, ++0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0xE8, 0xAE, 0x03, 0x78, 0x09, 0x2B, 0x7F, 0xF4, 0xE4, 0xAE, 0x43, 0x78, 0x02, 0x2B, ++0x7F, 0xF4, 0xE0, 0xAE, 0xC2, 0x78, 0x83, 0x78, 0x68, 0x60, 0x43, 0xEA, 0x02, 0x23, 0x2B, 0x81, 0xC3, 0x79, 0x58, 0x4A, ++0x13, 0xF0, 0x40, 0x0F, 0x13, 0x78, 0x14, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x70, 0xCD, 0xE7, ++0x23, 0x68, 0x0F, 0x20, 0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0xC8, 0xAE, 0x03, 0x78, 0x05, 0x2B, 0x7F, 0xF4, 0xC4, 0xAE, ++0x43, 0x78, 0x0F, 0x2B, 0x7F, 0xF4, 0xC0, 0xAE, 0x83, 0x78, 0xBB, 0xE7, 0x23, 0x68, 0x06, 0x20, 0x98, 0x47, 0x00, 0x28, ++0x3F, 0xF4, 0xB8, 0xAE, 0x03, 0x78, 0x0A, 0x2B, 0x7F, 0xF4, 0xB4, 0xAE, 0x42, 0x78, 0x06, 0x2A, 0x7F, 0xF4, 0xB0, 0xAE, ++0xAC, 0xE7, 0x2B, 0x78, 0x00, 0x2B, 0x51, 0xD1, 0x01, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x00, 0x21, 0x01, 0x20, 0xFF, 0xF7, ++0xB3, 0xFA, 0x84, 0xE5, 0x68, 0x89, 0x2B, 0x89, 0x36, 0x88, 0x6A, 0x68, 0x3C, 0x49, 0x1B, 0x1A, 0xC6, 0xF1, 0x40, 0x06, ++0x9B, 0xB2, 0x9E, 0x42, 0xA8, 0xBF, 0x1E, 0x46, 0x10, 0x44, 0x09, 0x68, 0xB2, 0xB2, 0x2D, 0xF0, 0x07, 0xFC, 0x6A, 0x89, ++0x2B, 0x89, 0x16, 0x44, 0xB6, 0xB2, 0xB3, 0x42, 0x6E, 0x81, 0x7F, 0xF4, 0x11, 0xAE, 0x33, 0x4B, 0x1B, 0x69, 0x0B, 0xB1, ++0x28, 0x46, 0x98, 0x47, 0xA0, 0x06, 0x35, 0xD4, 0x06, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x29, 0x89, 0x6A, 0x89, 0x88, 0x1A, ++0x80, 0xB2, 0x30, 0xB9, 0x05, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x2B, 0x48, 0xFC, 0xF7, 0x00, 0xFD, 0x88, 0xE5, 0x40, 0x28, ++0x22, 0xD0, 0x40, 0x28, 0x28, 0xBF, 0x40, 0x20, 0x00, 0x26, 0x02, 0x44, 0x92, 0xB2, 0x91, 0x42, 0x6A, 0x81, 0x29, 0xD3, ++0x89, 0x1A, 0x89, 0xB2, 0x40, 0x29, 0x0F, 0xD8, 0x79, 0xB9, 0x66, 0xBB, 0x21, 0x4A, 0x05, 0x23, 0x2B, 0x70, 0xD2, 0xF8, ++0x10, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x10, 0x38, 0xF8, 0xBD, 0x01, 0x20, 0xFF, 0xF7, 0x65, 0xFA, 0xA9, 0xE7, ++0x40, 0x21, 0x68, 0x68, 0x10, 0x44, 0xFF, 0xF7, 0x27, 0xF9, 0x98, 0xE5, 0x01, 0x26, 0xDE, 0xE7, 0xFF, 0xF7, 0x8E, 0xF8, ++0x15, 0x4A, 0x07, 0x23, 0x2B, 0x70, 0xD2, 0xF8, 0x14, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xFF, 0xF7, ++0xA1, 0xF8, 0x8A, 0xE5, 0x10, 0x48, 0xFC, 0xF7, 0xC7, 0xFC, 0x29, 0x89, 0x6A, 0x89, 0xCF, 0xE7, 0x03, 0x23, 0x3B, 0x70, ++0x0C, 0xE6, 0x08, 0x46, 0xFF, 0xF7, 0x0A, 0xF9, 0x7B, 0xE5, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x6C, 0x26, 0x17, 0x00, ++0x6A, 0x26, 0x17, 0x00, 0x68, 0x26, 0x17, 0x00, 0x50, 0x28, 0x17, 0x00, 0x6E, 0x26, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, ++0x20, 0x26, 0x17, 0x00, 0xB4, 0x84, 0x15, 0x00, 0x00, 0x00, 0x20, 0x40, 0xF0, 0x84, 0x15, 0x00, 0x2B, 0x7B, 0x03, 0xF0, ++0x1F, 0x03, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x7F, 0xF4, 0x39, 0xAE, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, 0x04, 0x29, ++0x2A, 0xD9, 0x17, 0x4B, 0x00, 0x22, 0x1A, 0x80, 0x35, 0xE6, 0xE8, 0x89, 0x02, 0x28, 0x19, 0xD0, 0x00, 0xF1, 0xFF, 0x3C, ++0x07, 0x23, 0xDC, 0xF1, 0x00, 0x04, 0x44, 0xEB, 0x0C, 0x04, 0x2B, 0x70, 0x7E, 0xE6, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, ++0xC0, 0xF3, 0xC0, 0x10, 0xFF, 0xF7, 0x18, 0xFA, 0x07, 0x23, 0x04, 0x2E, 0x2B, 0x70, 0x7F, 0xF4, 0x6B, 0xAE, 0x3B, 0x78, ++0x04, 0x2B, 0x3F, 0xF4, 0x67, 0xAE, 0xC9, 0xE5, 0x2B, 0x8A, 0x07, 0x49, 0x1B, 0x0A, 0x07, 0x22, 0x04, 0x2E, 0x0B, 0x70, ++0x2A, 0x70, 0x7F, 0xF4, 0x5D, 0xAE, 0xF0, 0xE7, 0xC0, 0xF3, 0xC0, 0x10, 0xC7, 0xE6, 0x00, 0xBF, 0x50, 0x28, 0x17, 0x00, ++0x70, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xB4, 0x4B, 0xB5, 0x4D, 0xD3, 0xF8, 0x00, 0x38, 0x13, 0xF4, 0xFE, 0x6F, ++0x03, 0xD0, 0x2B, 0x78, 0x04, 0x2B, 0x00, 0xF0, 0x8F, 0x81, 0xAF, 0x4C, 0xB0, 0x4A, 0xB1, 0x48, 0x00, 0x21, 0x02, 0x23, ++0x2B, 0x70, 0x11, 0x70, 0x1A, 0xF0, 0x1A, 0xFE, 0xD4, 0xF8, 0x00, 0x3E, 0x23, 0xF0, 0x01, 0x03, 0xC4, 0xF8, 0x00, 0x3E, ++0xD4, 0xF8, 0x04, 0x38, 0x23, 0xF0, 0x01, 0x03, 0xC4, 0xF8, 0x04, 0x38, 0xFF, 0xF7, 0x7E, 0xF8, 0xA3, 0x69, 0x1D, 0x06, ++0x03, 0xD5, 0xA3, 0x69, 0x23, 0xF0, 0x80, 0x03, 0xA3, 0x61, 0xA0, 0x4B, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF4, 0x00, 0x72, ++0xC3, 0xF8, 0x04, 0x28, 0x5A, 0x69, 0x14, 0x06, 0xFC, 0xD5, 0x01, 0x23, 0x01, 0x2B, 0x9E, 0x4C, 0x9E, 0x4D, 0x9F, 0x4A, ++0x9F, 0x4F, 0x4F, 0xF0, 0x02, 0x0C, 0x1C, 0xD0, 0x4F, 0xEA, 0x43, 0x1E, 0x5E, 0xF8, 0x02, 0x10, 0x11, 0xF0, 0x80, 0x2F, ++0x10, 0xD0, 0x5E, 0xF8, 0x02, 0x00, 0x00, 0x29, 0x40, 0xEA, 0x05, 0x00, 0x4E, 0xF8, 0x02, 0x00, 0xC0, 0xF2, 0x0F, 0x81, ++0x08, 0x04, 0x05, 0xD4, 0x5E, 0xF8, 0x02, 0x10, 0x21, 0xF4, 0x00, 0x41, 0x4E, 0xF8, 0x02, 0x10, 0x05, 0x2B, 0x0A, 0xD0, ++0x01, 0x33, 0x01, 0x2B, 0xE2, 0xD1, 0x21, 0x68, 0x11, 0xF0, 0x80, 0x2F, 0xF8, 0xD0, 0x21, 0x68, 0x29, 0x43, 0x21, 0x60, ++0xF4, 0xE7, 0x84, 0x4B, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF4, 0x80, 0x62, 0xC3, 0xF8, 0x04, 0x28, 0xD3, 0xF8, 0x04, 0x28, ++0x42, 0xF0, 0x80, 0x02, 0xC3, 0xF8, 0x04, 0x28, 0x5A, 0x69, 0x51, 0x06, 0xFC, 0xD5, 0x01, 0x23, 0x01, 0x2B, 0x83, 0x4F, ++0xDF, 0xF8, 0x40, 0x82, 0xDF, 0xF8, 0xF8, 0xC1, 0x81, 0x4D, 0xDF, 0xF8, 0x3C, 0xE2, 0x4F, 0xF0, 0x40, 0x06, 0x4F, 0xF0, ++0x02, 0x09, 0x19, 0xD0, 0x5A, 0x01, 0x05, 0xEB, 0x43, 0x10, 0x51, 0x59, 0x11, 0xF0, 0x80, 0x2F, 0x0D, 0xD0, 0x72, 0x44, ++0x16, 0x60, 0x04, 0x68, 0x00, 0x29, 0x44, 0xEA, 0x0C, 0x04, 0x04, 0x60, 0x11, 0xDB, 0x0A, 0x04, 0x03, 0xD4, 0x02, 0x68, ++0x22, 0xF4, 0x00, 0x42, 0x02, 0x60, 0x05, 0x2B, 0x1A, 0xD0, 0x01, 0x33, 0x01, 0x2B, 0xE5, 0xD1, 0x39, 0x68, 0x11, 0xF0, ++0x80, 0x2F, 0xF8, 0xD0, 0x42, 0x46, 0x38, 0x46, 0xE6, 0xE7, 0x8C, 0x03, 0x09, 0xD5, 0xC2, 0xF8, 0x00, 0x90, 0x04, 0x68, ++0x44, 0xF0, 0x80, 0x44, 0x04, 0x60, 0x14, 0x68, 0xA4, 0x07, 0xFC, 0xD5, 0xE1, 0xE7, 0x14, 0x68, 0x64, 0x06, 0xFC, 0xD5, ++0x16, 0x60, 0xF0, 0xE7, 0x5B, 0x4B, 0x4F, 0xF4, 0x86, 0x62, 0x1A, 0x61, 0x1A, 0x69, 0x12, 0xF0, 0x30, 0x0F, 0xFB, 0xD1, ++0xD3, 0xF8, 0x04, 0x28, 0x4F, 0xF0, 0x01, 0x14, 0x42, 0xF4, 0x80, 0x72, 0x29, 0x20, 0x09, 0x21, 0xC3, 0xF8, 0x04, 0x28, ++0xC3, 0xF8, 0x1C, 0x48, 0xC3, 0xF8, 0x14, 0x08, 0xC3, 0xF8, 0x10, 0x18, 0x9A, 0x69, 0x42, 0xF4, 0x40, 0x22, 0x9A, 0x61, ++0x9A, 0x6C, 0x14, 0x03, 0x4C, 0xD4, 0x4C, 0x4D, 0x55, 0x4B, 0xD5, 0xF8, 0x00, 0x28, 0x55, 0x48, 0x00, 0x24, 0x22, 0xF4, ++0xFE, 0x62, 0xC5, 0xF8, 0x00, 0x28, 0x21, 0x46, 0xC3, 0xE9, 0x01, 0x44, 0x40, 0x22, 0x1C, 0x70, 0xF6, 0xF7, 0xDE, 0xFA, ++0x21, 0x46, 0x40, 0x22, 0x4E, 0x48, 0xF6, 0xF7, 0xD9, 0xFA, 0x4E, 0x4A, 0x4E, 0x4B, 0x11, 0x68, 0x4E, 0x4A, 0x1B, 0x68, ++0x12, 0x68, 0x59, 0x60, 0xC5, 0xF8, 0x14, 0x3B, 0xD1, 0x78, 0x4C, 0x4B, 0x4C, 0x48, 0x1F, 0x68, 0x4C, 0x4B, 0x06, 0x6A, ++0x18, 0x68, 0xD3, 0xF8, 0x04, 0xC0, 0x41, 0xF0, 0xC0, 0x01, 0xD1, 0x70, 0xF9, 0x78, 0x41, 0xF0, 0xC0, 0x01, 0xF9, 0x70, ++0xC1, 0x78, 0x41, 0xF0, 0xC0, 0x01, 0xC1, 0x70, 0x9C, 0xF8, 0x03, 0x10, 0xD3, 0xE9, 0x02, 0x70, 0x41, 0xF0, 0xC0, 0x03, ++0x8C, 0xF8, 0x03, 0x30, 0xFB, 0x78, 0x43, 0xF0, 0xC0, 0x03, 0xFB, 0x70, 0xC3, 0x78, 0x43, 0xF0, 0xC0, 0x03, 0xC3, 0x70, ++0xC5, 0xF8, 0x14, 0x29, 0x0E, 0xB1, 0x20, 0x46, 0xB0, 0x47, 0xBD, 0xE8, 0xF8, 0x43, 0x3A, 0x48, 0x1A, 0xF0, 0x10, 0xBD, ++0x39, 0x49, 0x3A, 0x4C, 0x24, 0x4A, 0x40, 0xF2, 0x17, 0x15, 0x5D, 0x62, 0x4F, 0xF4, 0x9C, 0x70, 0x9C, 0x62, 0x08, 0x80, ++0xD3, 0xF8, 0x04, 0x18, 0x41, 0xF0, 0x80, 0x01, 0xC3, 0xF8, 0x04, 0x18, 0x53, 0x69, 0x58, 0x06, 0xFC, 0xD5, 0x1C, 0x49, ++0x0B, 0x69, 0x00, 0x2B, 0xFC, 0xDA, 0x4F, 0xF4, 0x84, 0x63, 0x19, 0x4A, 0x0B, 0x61, 0x13, 0x69, 0x99, 0x06, 0xFC, 0xD4, ++0xD2, 0xF8, 0x04, 0x38, 0x15, 0x49, 0x43, 0xF4, 0x80, 0x73, 0xC2, 0xF8, 0x04, 0x38, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, ++0x00, 0x73, 0xC2, 0xF8, 0x04, 0x38, 0x4B, 0x69, 0x1A, 0x06, 0xFC, 0xD5, 0x0B, 0x69, 0x0E, 0x4A, 0x43, 0xF0, 0x10, 0x03, ++0x0B, 0x61, 0x13, 0x69, 0xDB, 0x06, 0xFC, 0xD4, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x80, 0x63, 0xC2, 0xF8, 0x04, 0x38, ++0x75, 0xE7, 0x4E, 0xF8, 0x07, 0xC0, 0x5E, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x80, 0x40, 0x4E, 0xF8, 0x02, 0x00, 0x0E, 0xEB, ++0x07, 0x06, 0x30, 0x68, 0x80, 0x07, 0xFC, 0xD5, 0xE2, 0xE6, 0x00, 0xBF, 0x00, 0x00, 0x20, 0x40, 0x6F, 0x26, 0x17, 0x00, ++0x6E, 0x26, 0x17, 0x00, 0x20, 0x85, 0x15, 0x00, 0x00, 0x0B, 0x20, 0x40, 0x00, 0x80, 0x00, 0x08, 0xE0, 0x0A, 0x20, 0x40, ++0xE8, 0x0A, 0x20, 0x40, 0x00, 0x09, 0x20, 0x40, 0xE0, 0x08, 0x20, 0x40, 0xB4, 0x27, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, ++0xC8, 0x27, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x20, 0x26, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, 0x28, 0x85, 0x15, 0x00, 0x48, 0x28, 0x17, 0x00, 0x17, 0x01, 0x21, 0x00, ++0x08, 0x09, 0x20, 0x40, 0xE8, 0x08, 0x20, 0x40, 0x05, 0x48, 0x1E, 0x21, 0x1A, 0xF0, 0x90, 0xFC, 0x4F, 0xF4, 0xF0, 0x42, ++0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0x7F, 0xFC, 0x64, 0xE6, 0x0C, 0x85, 0x15, 0x00, 0x08, 0xB5, 0x04, 0x49, ++0x04, 0x48, 0x1A, 0xF0, 0x81, 0xFC, 0x04, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x08, 0xBD, 0x00, 0xBF, 0x54, 0x85, 0x15, 0x00, ++0xCC, 0xB5, 0x15, 0x00, 0x52, 0x28, 0x17, 0x00, 0x01, 0x4B, 0x18, 0x78, 0x70, 0x47, 0x00, 0xBF, 0x52, 0x28, 0x17, 0x00, ++0x08, 0xB5, 0x07, 0x48, 0x1A, 0xF0, 0x6C, 0xFC, 0x06, 0x4B, 0x07, 0x4A, 0x00, 0x21, 0x19, 0x70, 0xD2, 0xF8, 0x00, 0x3E, ++0x23, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x00, 0x3E, 0x08, 0xBD, 0x00, 0xBF, 0x30, 0x85, 0x15, 0x00, 0x52, 0x28, 0x17, 0x00, ++0x00, 0x00, 0x20, 0x40, 0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x1A, 0x4C, 0x1A, 0x4D, 0x23, 0x68, 0x2A, 0x78, 0x01, 0x33, 0x23, 0x60, 0x1A, 0xB1, 0x18, 0x4A, 0x12, 0x78, ++0x04, 0x2A, 0x08, 0xD0, 0x33, 0xB1, 0x13, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x38, 0xBD, 0x13, 0x4A, 0x13, 0x49, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x0A, 0x69, ++0x02, 0xF5, 0x0C, 0x52, 0x28, 0x32, 0x0B, 0x69, 0xD3, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x0B, 0x4A, 0x0C, 0x48, 0xD2, 0xF8, ++0x04, 0x38, 0x23, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x1A, 0xF0, 0x23, 0xFC, 0x00, 0x22, 0x23, 0x68, 0x2A, 0x70, ++0xD8, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x52, 0x28, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, ++0x00, 0x00, 0x20, 0x40, 0x00, 0x10, 0x50, 0x40, 0x3C, 0x85, 0x15, 0x00, 0x38, 0xB5, 0x04, 0x46, 0x0D, 0x46, 0xFF, 0xF7, ++0xB1, 0xFF, 0x15, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x20, 0xD1, 0x62, 0x1E, 0xD3, 0xB2, 0x04, 0x2B, 0x1E, 0xD8, 0x60, 0x01, ++0x00, 0xF1, 0x80, 0x40, 0x00, 0xF5, 0x00, 0x10, 0xD0, 0xF8, 0x00, 0x39, 0x1B, 0x04, 0x17, 0xD5, 0x0D, 0x49, 0x53, 0x01, ++0x03, 0xF1, 0x80, 0x43, 0x01, 0xEB, 0x02, 0x12, 0x03, 0xF5, 0x00, 0x13, 0x01, 0x21, 0xD1, 0x72, 0xC3, 0xF8, 0x34, 0x59, ++0xD0, 0xF8, 0x00, 0x39, 0x43, 0xF0, 0x04, 0x43, 0xC0, 0xF8, 0x00, 0x39, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x20, 0x38, 0xBD, ++0x02, 0x20, 0x38, 0xBD, 0x05, 0x20, 0x38, 0xBD, 0x6F, 0x26, 0x17, 0x00, 0xC8, 0x27, 0x17, 0x00, 0x93, 0x4B, 0x5A, 0x69, ++0x2D, 0xE9, 0xF0, 0x4F, 0x5A, 0x61, 0x9C, 0x69, 0x14, 0x40, 0xE1, 0x04, 0x85, 0xB0, 0x0A, 0xD5, 0x8F, 0x4B, 0xD3, 0xF8, ++0xDC, 0x34, 0x98, 0x47, 0x14, 0xF4, 0x00, 0x5A, 0x40, 0xF0, 0xAB, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, ++0x44, 0xA2, 0xA2, 0x04, 0x04, 0xEA, 0x0A, 0x0A, 0x04, 0xF4, 0x80, 0x25, 0x04, 0xF4, 0x00, 0x29, 0x04, 0xF4, 0x00, 0x6B, ++0x00, 0xF1, 0x9F, 0x80, 0x00, 0x2D, 0x42, 0xD0, 0x81, 0x4D, 0x83, 0x4E, 0xD5, 0xF8, 0x18, 0x28, 0xD5, 0xF8, 0x1C, 0x38, ++0x00, 0x24, 0x02, 0xEA, 0x03, 0x08, 0x01, 0x20, 0x00, 0xFA, 0x04, 0xF3, 0x13, 0xEA, 0x08, 0x0F, 0xE7, 0xB2, 0x2D, 0xD0, ++0x00, 0x2C, 0x00, 0xF0, 0xA0, 0x80, 0x63, 0x1E, 0x05, 0xEB, 0x43, 0x13, 0xD3, 0xF8, 0x28, 0x29, 0xC3, 0xF8, 0x28, 0x29, ++0xD5, 0xF8, 0x10, 0x18, 0x11, 0x40, 0x11, 0xF0, 0x09, 0x0F, 0x74, 0xD0, 0x16, 0xF8, 0x05, 0x3C, 0xD3, 0xB1, 0x56, 0xF8, ++0x0C, 0x3C, 0x01, 0x93, 0xD2, 0x43, 0x56, 0xF8, 0x10, 0x3C, 0x02, 0x93, 0x12, 0xF0, 0x01, 0x03, 0x00, 0x93, 0x40, 0xF0, ++0xB6, 0x80, 0x10, 0x22, 0x00, 0x21, 0xA6, 0xF1, 0x10, 0x00, 0xF6, 0xF7, 0x15, 0xF9, 0x6A, 0x4B, 0x03, 0xEB, 0x84, 0x03, ++0x1B, 0x6B, 0x1B, 0xB1, 0xDD, 0xE9, 0x00, 0x21, 0x02, 0x98, 0x98, 0x47, 0x04, 0x2F, 0x02, 0xD0, 0x01, 0x34, 0x10, 0x36, ++0xC5, 0xE7, 0xB9, 0xF1, 0x00, 0x0F, 0x3C, 0xD0, 0x5E, 0x4D, 0x62, 0x4E, 0xD5, 0xF8, 0x18, 0x78, 0xD5, 0xF8, 0x1C, 0x38, ++0xDF, 0xF8, 0x90, 0x81, 0xDF, 0xF8, 0x74, 0x91, 0x1F, 0x40, 0x00, 0x24, 0x4F, 0xF4, 0x80, 0x33, 0xA3, 0x40, 0x3B, 0x42, ++0x0C, 0xD0, 0xC4, 0xB1, 0x63, 0x1E, 0x05, 0xEB, 0x43, 0x13, 0xD3, 0xF8, 0x28, 0x2B, 0xC3, 0xF8, 0x28, 0x2B, 0xD5, 0xF8, ++0x14, 0x38, 0x13, 0x40, 0xDB, 0x07, 0x5F, 0xD4, 0xE3, 0xB2, 0x04, 0x2B, 0x1B, 0xD0, 0x01, 0x34, 0x4F, 0xF4, 0x80, 0x33, ++0xA3, 0x40, 0x3B, 0x42, 0x06, 0xF1, 0x10, 0x06, 0xF4, 0xD0, 0x00, 0x2C, 0xE6, 0xD1, 0xD5, 0xF8, 0x08, 0x1B, 0xC5, 0xF8, ++0x08, 0x1B, 0xD5, 0xF8, 0x14, 0x38, 0x0B, 0x40, 0xDA, 0x06, 0x7B, 0xD4, 0x13, 0xF0, 0x29, 0x0F, 0xE9, 0xD0, 0x44, 0x4B, ++0x20, 0x46, 0xD3, 0xF8, 0x00, 0x31, 0x98, 0x47, 0xE3, 0xE7, 0xBB, 0xF1, 0x00, 0x0F, 0x03, 0xD0, 0x3F, 0x4B, 0xD3, 0xF8, ++0x8C, 0x34, 0x98, 0x47, 0xBA, 0xF1, 0x00, 0x0F, 0xBF, 0xF6, 0x60, 0xAF, 0x3B, 0x4B, 0xD3, 0xF8, 0x90, 0x34, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x3C, 0x48, 0xFC, 0xF7, 0x56, 0xF9, 0xA4, 0xE7, 0x4F, 0xF0, 0x00, 0x0B, 0xD9, 0x46, ++0x5D, 0x46, 0x33, 0x4B, 0xD3, 0xF8, 0x08, 0x38, 0x13, 0xF0, 0x06, 0x0F, 0xC3, 0xF3, 0x47, 0x02, 0x04, 0xD0, 0xD3, 0x07, ++0x02, 0xD5, 0x34, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2C, 0x4B, 0x33, 0x4A, 0xC3, 0xF8, 0x00, 0x29, 0xC3, 0xF8, 0x00, 0x2B, ++0xFE, 0xF7, 0xF4, 0xFC, 0x4A, 0xE7, 0xD5, 0xF8, 0x08, 0x19, 0xC5, 0xF8, 0x08, 0x19, 0xD5, 0xF8, 0x10, 0x38, 0x0B, 0x40, ++0x13, 0xF0, 0x18, 0x0F, 0x2B, 0xD1, 0xDF, 0x07, 0x80, 0xD5, 0x23, 0x4B, 0xD3, 0xF8, 0x00, 0x31, 0x98, 0x47, 0x7B, 0xE7, ++0x16, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0x9B, 0xD0, 0x58, 0xF8, 0x24, 0x30, 0x56, 0xF8, 0x0C, 0x1C, 0x1B, 0x88, 0x02, 0x93, ++0x30, 0x46, 0xA3, 0x00, 0x50, 0xF8, 0x10, 0x2D, 0x03, 0x92, 0x01, 0x91, 0x10, 0x22, 0x00, 0x21, 0x00, 0x93, 0xF6, 0xF7, ++0x71, 0xF8, 0x00, 0x9B, 0x4B, 0x44, 0x1B, 0x6A, 0x00, 0x2B, 0x85, 0xD0, 0xDD, 0xE9, 0x01, 0x01, 0x00, 0x22, 0x41, 0x1A, ++0x03, 0x98, 0x98, 0x47, 0x7E, 0xE7, 0x39, 0x46, 0xFE, 0xF7, 0x8A, 0xFE, 0x45, 0xE7, 0xD5, 0xF8, 0x10, 0x38, 0x23, 0xF0, ++0x10, 0x03, 0xC5, 0xF8, 0x10, 0x38, 0x22, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x20, 0x46, 0xFE, 0xF7, 0xE9, 0xFD, 0x49, 0xE7, ++0xD5, 0xF8, 0x14, 0x38, 0x23, 0xF0, 0x10, 0x03, 0xC5, 0xF8, 0x14, 0x38, 0x22, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x20, 0x46, ++0xFE, 0xF7, 0x80, 0xFD, 0x63, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x20, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x27, 0x17, 0x00, ++0x20, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x48, 0x85, 0x15, 0x00, 0x4C, 0x28, 0x17, 0x00, 0x00, 0x80, 0x00, 0x08, ++0x00, 0x3C, 0x0C, 0x88, 0x40, 0x60, 0x17, 0x00, 0x38, 0xB9, 0x0C, 0x4A, 0x0C, 0x4B, 0x10, 0x70, 0x18, 0x70, 0x0C, 0x4B, ++0x1B, 0x68, 0x5B, 0xB1, 0x18, 0x47, 0x01, 0x28, 0x09, 0xD0, 0x09, 0x4B, 0x02, 0x38, 0x1B, 0x68, 0x01, 0x28, 0x94, 0xBF, ++0x02, 0x20, 0x03, 0x20, 0x00, 0x2B, 0xF3, 0xD1, 0x70, 0x47, 0x05, 0x4A, 0x05, 0x4B, 0x10, 0x70, 0x18, 0x70, 0xEA, 0xE7, ++0x59, 0x28, 0x17, 0x00, 0x5A, 0x28, 0x17, 0x00, 0x60, 0x28, 0x17, 0x00, 0x5B, 0x28, 0x17, 0x00, 0x5C, 0x28, 0x17, 0x00, ++0x00, 0x48, 0x70, 0x47, 0x54, 0x86, 0x15, 0x00, 0x01, 0x28, 0x15, 0xD1, 0x08, 0xB5, 0x0B, 0x4B, 0x1B, 0x68, 0x0B, 0xB1, ++0x04, 0x20, 0x98, 0x47, 0x02, 0x22, 0x11, 0x46, 0x4F, 0xF4, 0x00, 0x73, 0x01, 0x20, 0xFE, 0xF7, 0x65, 0xFF, 0x4F, 0xF4, ++0x00, 0x73, 0x02, 0x22, 0x01, 0x21, 0x00, 0x20, 0xFE, 0xF7, 0x5E, 0xFF, 0x01, 0x20, 0x08, 0xBD, 0x00, 0x20, 0x70, 0x47, ++0x60, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x58, 0x4E, 0xDF, 0xF8, 0x9C, 0xE1, 0x33, 0x88, 0x57, 0x4C, 0x00, 0x2A, ++0x03, 0xF1, 0x01, 0x03, 0x0C, 0xBF, 0x02, 0x25, 0x03, 0x25, 0x9B, 0xB2, 0x00, 0x27, 0x33, 0x80, 0x8E, 0xF8, 0x00, 0x50, ++0x27, 0x70, 0x9E, 0xF8, 0x00, 0xC0, 0xBC, 0xF1, 0x02, 0x0F, 0x4C, 0xD1, 0x03, 0x29, 0x04, 0x46, 0x0D, 0x46, 0x8E, 0xF8, ++0x00, 0x70, 0x55, 0xD9, 0x43, 0x78, 0x4C, 0x4A, 0x07, 0x78, 0x12, 0x78, 0x90, 0xF8, 0x02, 0x80, 0x1B, 0x02, 0x03, 0xF4, ++0x70, 0x63, 0x1F, 0x43, 0x00, 0x2A, 0x78, 0xD1, 0xB8, 0xF1, 0x01, 0x0F, 0x64, 0xD0, 0xB8, 0xF1, 0x11, 0x0F, 0x55, 0xD1, ++0xDF, 0xF8, 0x44, 0x81, 0x98, 0xF8, 0x9D, 0x27, 0x98, 0xF8, 0x9E, 0x37, 0x9A, 0x42, 0x77, 0xD2, 0x3B, 0x1D, 0xAB, 0x42, ++0x02, 0xD0, 0x7B, 0x1D, 0x9D, 0x42, 0x6E, 0xD1, 0x3D, 0x4B, 0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x98, 0xF8, 0x9C, 0x37, ++0x3B, 0x49, 0x98, 0xF8, 0x9D, 0x27, 0x01, 0x33, 0xA1, 0xFB, 0x03, 0x01, 0x49, 0x09, 0x01, 0xEB, 0x81, 0x01, 0xA3, 0xEB, ++0xC1, 0x01, 0x08, 0xEB, 0x01, 0x15, 0x04, 0x34, 0x53, 0x1C, 0x88, 0xF8, 0x9C, 0x17, 0x34, 0x48, 0xC5, 0xF8, 0x20, 0x45, ++0x05, 0xF2, 0x1C, 0x51, 0xC5, 0xF8, 0x24, 0x75, 0x88, 0xF8, 0x9D, 0x37, 0x19, 0xF0, 0x22, 0xF8, 0x4F, 0xF4, 0x00, 0x00, ++0x18, 0xF0, 0x7C, 0xFF, 0x0B, 0xE0, 0x9E, 0xF8, 0x00, 0x10, 0x2C, 0x48, 0xFC, 0xF7, 0x28, 0xF8, 0x47, 0xF2, 0x30, 0x52, ++0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0xE1, 0xF9, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x31, 0x88, 0x26, 0x48, ++0x89, 0xB2, 0x2A, 0x46, 0xFC, 0xF7, 0x18, 0xF8, 0x24, 0x4B, 0x18, 0x68, 0x20, 0x1A, 0xFD, 0xF7, 0x05, 0xF9, 0x1D, 0x4B, ++0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x41, 0x46, 0x1F, 0x48, 0xFC, 0xF7, 0x08, 0xF8, ++0x31, 0x88, 0x1E, 0x48, 0x89, 0xB2, 0x2B, 0x46, 0x3A, 0x46, 0xFC, 0xF7, 0x01, 0xF8, 0xE7, 0xE7, 0xBD, 0x42, 0x02, 0xD0, ++0x7B, 0x1C, 0xAB, 0x42, 0x12, 0xD1, 0x11, 0x4D, 0xD5, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x20, 0x1D, 0xD5, 0xF8, 0x0C, 0x31, ++0x98, 0x47, 0x40, 0x20, 0x18, 0xF0, 0x3E, 0xFF, 0xCD, 0xE7, 0x0A, 0x46, 0x4F, 0xF4, 0x00, 0x70, 0x11, 0x49, 0x1A, 0xF0, ++0x03, 0xFA, 0x7F, 0xE7, 0x31, 0x88, 0x10, 0x48, 0xDE, 0xE7, 0x31, 0x88, 0x0F, 0x48, 0xDB, 0xE7, 0x0F, 0x48, 0xFB, 0xF7, ++0xDF, 0xFF, 0xC5, 0xE7, 0x56, 0x28, 0x17, 0x00, 0x58, 0x28, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xCD, 0xCC, 0xCC, 0xCC, 0xF8, 0x5F, 0x17, 0x00, 0xD0, 0x85, 0x15, 0x00, 0xC0, 0x85, 0x15, 0x00, 0x80, 0x1A, 0x17, 0x00, ++0xB0, 0x85, 0x15, 0x00, 0x78, 0x85, 0x15, 0x00, 0x68, 0x85, 0x15, 0x00, 0x70, 0x85, 0x15, 0x00, 0x84, 0x85, 0x15, 0x00, ++0x98, 0x85, 0x15, 0x00, 0x59, 0x28, 0x17, 0x00, 0x58, 0x58, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x2A, 0x2A, 0x4B, ++0x0C, 0xBF, 0x02, 0x21, 0x03, 0x21, 0x19, 0x70, 0x19, 0x78, 0x02, 0x29, 0x3D, 0xD1, 0x27, 0x4C, 0x22, 0x78, 0x00, 0x21, ++0x19, 0x70, 0x52, 0xB3, 0x25, 0x4D, 0x26, 0x4F, 0xA5, 0xF1, 0x08, 0x06, 0x0A, 0xE0, 0x01, 0x2A, 0x41, 0x46, 0x38, 0x46, ++0x28, 0xD1, 0x13, 0x2B, 0x40, 0x46, 0x01, 0xD0, 0xFD, 0xF7, 0x90, 0xF8, 0x23, 0x78, 0xD3, 0xB1, 0x28, 0x46, 0x18, 0xF0, ++0xCD, 0xFF, 0x42, 0x68, 0x23, 0x78, 0xD2, 0xF8, 0x04, 0x80, 0x01, 0x3B, 0x01, 0x46, 0x30, 0x46, 0x23, 0x70, 0x18, 0xF0, ++0x7F, 0xFF, 0x98, 0xF8, 0x02, 0x30, 0x1A, 0x09, 0xE3, 0xD1, 0x17, 0x4A, 0x13, 0x88, 0x10, 0x20, 0x01, 0x33, 0x13, 0x80, ++0x18, 0xF0, 0xD2, 0xFE, 0x23, 0x78, 0x00, 0x2B, 0xE4, 0xD1, 0x13, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x01, 0x20, ++0xBD, 0xE8, 0xF0, 0x81, 0xFB, 0xF7, 0x78, 0xFF, 0x40, 0x46, 0x20, 0x21, 0x1A, 0xF0, 0x1C, 0xFD, 0xD4, 0xE7, 0x19, 0x78, ++0x0C, 0x48, 0xFB, 0xF7, 0x6F, 0xFF, 0x47, 0xF2, 0x30, 0x52, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0x28, 0xF9, ++0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x5A, 0x28, 0x17, 0x00, 0x64, 0x60, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, ++0xF0, 0x85, 0x15, 0x00, 0x54, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x86, 0x15, 0x00, 0x10, 0x4B, 0x11, 0x49, ++0x11, 0x4A, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x00, 0x68, 0x18, 0x60, 0xDF, 0xF8, 0x44, 0x80, 0x0E, 0x4F, 0x0F, 0x4E, ++0x00, 0x23, 0x0B, 0x70, 0x13, 0x70, 0x29, 0x7A, 0xD8, 0xF8, 0x08, 0x31, 0x00, 0x39, 0x18, 0xBF, 0x01, 0x21, 0x38, 0x46, ++0x98, 0x47, 0x04, 0x46, 0x01, 0x46, 0x30, 0x46, 0x1A, 0xF0, 0x04, 0xF9, 0x00, 0x2C, 0xF0, 0xD1, 0x20, 0x46, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x60, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x5A, 0x28, 0x17, 0x00, 0x38, 0x1A, 0x17, 0x00, ++0x20, 0x86, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x1D, 0x4D, 0x2B, 0x78, 0xFB, 0xB9, 0xD8, 0xB1, 0x0A, 0x46, ++0xC9, 0xB1, 0x1B, 0x4F, 0x3B, 0x78, 0xE3, 0xB9, 0x1A, 0x4C, 0x01, 0x26, 0x3E, 0x70, 0xD4, 0xF8, 0x30, 0x3B, 0x23, 0xF0, ++0xFF, 0x53, 0x23, 0xF4, 0xC0, 0x13, 0x01, 0x46, 0xC4, 0xF8, 0x30, 0x3B, 0x30, 0x46, 0xFE, 0xF7, 0x7B, 0xFE, 0x04, 0x46, ++0xC8, 0xB9, 0x13, 0x4B, 0x1E, 0x70, 0x2B, 0x78, 0x73, 0xB9, 0x20, 0x46, 0xF8, 0xBD, 0x6F, 0xF0, 0x0A, 0x04, 0xFA, 0xE7, ++0x6F, 0xF0, 0x0D, 0x04, 0xF7, 0xE7, 0x39, 0x78, 0x0D, 0x48, 0xFB, 0xF7, 0xFD, 0xFE, 0x6F, 0xF0, 0x02, 0x04, 0xF0, 0xE7, ++0x31, 0x46, 0xFE, 0xF7, 0xB3, 0xFC, 0x3C, 0x70, 0x6F, 0xF0, 0x0D, 0x04, 0xE9, 0xE7, 0x01, 0x46, 0x07, 0x48, 0xFB, 0xF7, ++0xEF, 0xFE, 0x4F, 0xF0, 0xFF, 0x34, 0xE2, 0xE7, 0x5B, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, ++0x58, 0x28, 0x17, 0x00, 0x30, 0x86, 0x15, 0x00, 0x48, 0x86, 0x15, 0x00, 0xF8, 0xB5, 0x20, 0x4D, 0x2B, 0x78, 0x2B, 0xBB, ++0x08, 0xB3, 0x0A, 0x46, 0xF9, 0xB1, 0x1E, 0x4F, 0x3B, 0x78, 0x13, 0xBB, 0x1D, 0x4C, 0x01, 0x26, 0x3E, 0x70, 0xD4, 0xF8, ++0x30, 0x3B, 0x23, 0xF0, 0xFF, 0x53, 0x23, 0xF4, 0xC0, 0x13, 0xC4, 0xF8, 0x30, 0x3B, 0xD4, 0xF8, 0x00, 0x38, 0x43, 0xF4, ++0x00, 0x53, 0x01, 0x46, 0xC4, 0xF8, 0x00, 0x38, 0x30, 0x46, 0xFE, 0xF7, 0x87, 0xFE, 0x04, 0x46, 0xC8, 0xB9, 0x13, 0x4B, ++0x1E, 0x70, 0x2B, 0x78, 0x73, 0xB9, 0x20, 0x46, 0xF8, 0xBD, 0x6F, 0xF0, 0x0A, 0x04, 0xFA, 0xE7, 0x6F, 0xF0, 0x0D, 0x04, ++0xF7, 0xE7, 0x39, 0x78, 0x0D, 0x48, 0xFB, 0xF7, 0xAF, 0xFE, 0x6F, 0xF0, 0x02, 0x04, 0xF0, 0xE7, 0x31, 0x46, 0xFE, 0xF7, ++0x65, 0xFC, 0x3C, 0x70, 0x6F, 0xF0, 0x0D, 0x04, 0xE9, 0xE7, 0x01, 0x46, 0x07, 0x48, 0xFB, 0xF7, 0xA1, 0xFE, 0x4F, 0xF0, ++0xFF, 0x34, 0xE2, 0xE7, 0x5B, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x58, 0x28, 0x17, 0x00, ++0x30, 0x86, 0x15, 0x00, 0x48, 0x86, 0x15, 0x00, 0xF8, 0xB5, 0x26, 0x4C, 0xFF, 0xF7, 0xFE, 0xFB, 0x23, 0x78, 0x00, 0x2B, ++0x42, 0xD1, 0x24, 0x4D, 0x28, 0x46, 0x18, 0xF0, 0xFB, 0xFE, 0xDF, 0xF8, 0x90, 0xC0, 0xC0, 0xB2, 0x8C, 0xF8, 0x00, 0x00, ++0x00, 0x28, 0x31, 0xD0, 0x1F, 0x4A, 0x2F, 0x68, 0x42, 0xF2, 0x30, 0x03, 0x01, 0x28, 0xD6, 0x58, 0x28, 0xD0, 0xBD, 0x89, ++0xB3, 0x89, 0xAB, 0x42, 0x11, 0xD2, 0x39, 0x46, 0x03, 0x46, 0x03, 0xE0, 0x53, 0xB1, 0x95, 0x89, 0x0E, 0x46, 0x11, 0x46, ++0xC2, 0x1A, 0xD2, 0xB2, 0x01, 0x3B, 0xF5, 0xB1, 0x0A, 0x68, 0xDB, 0xB2, 0x00, 0x2A, 0xF3, 0xD1, 0x8C, 0xF8, 0x00, 0x30, ++0x0E, 0x46, 0xB3, 0x7B, 0x72, 0x68, 0x79, 0x68, 0x01, 0x3B, 0x02, 0xEB, 0xC3, 0x02, 0x01, 0x20, 0xD3, 0x78, 0x20, 0x70, ++0x23, 0xF0, 0x0A, 0x03, 0x43, 0xF0, 0x0A, 0x03, 0xD3, 0x70, 0x02, 0x20, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0x0A, 0xBC, ++0x00, 0x2E, 0xEA, 0xD1, 0x6F, 0xF0, 0x61, 0x00, 0xF8, 0xBD, 0x8C, 0xF8, 0x00, 0x20, 0xE4, 0xE7, 0x6F, 0xF0, 0x62, 0x00, ++0xF8, 0xBD, 0x00, 0xBF, 0x5A, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x64, 0x60, 0x17, 0x00, ++0x01, 0x28, 0x07, 0xD0, 0x06, 0x28, 0x07, 0xD0, 0x04, 0x4B, 0x0F, 0x28, 0x0C, 0xBF, 0x18, 0x46, 0x00, 0x20, 0x70, 0x47, ++0x02, 0x48, 0x70, 0x47, 0x02, 0x48, 0x70, 0x47, 0x74, 0x86, 0x15, 0x00, 0x80, 0x86, 0x15, 0x00, 0x94, 0x86, 0x15, 0x00, ++0x06, 0x28, 0x0B, 0xD8, 0x01, 0x38, 0x05, 0x28, 0x16, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x05, 0x03, 0x13, 0x0F, 0x11, 0x03, ++0x09, 0x48, 0x70, 0x47, 0x09, 0x48, 0x70, 0x47, 0x12, 0x30, 0xC0, 0xB2, 0x06, 0x4B, 0x02, 0x28, 0x34, 0xBF, 0x18, 0x46, ++0x00, 0x20, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, ++0xC4, 0x86, 0x15, 0x00, 0xB4, 0x86, 0x15, 0x00, 0xA0, 0x86, 0x15, 0x00, 0xA8, 0x86, 0x15, 0x00, 0xD8, 0x86, 0x15, 0x00, ++0xEC, 0x86, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x1D, 0x4F, 0x1E, 0x48, 0x18, 0xF0, 0xE4, 0xFD, 0x3B, 0x68, 0x1B, 0x89, ++0x93, 0xB3, 0xDF, 0xF8, 0x7C, 0x90, 0x1B, 0x4E, 0xDF, 0xF8, 0x78, 0x80, 0xDF, 0xF8, 0x78, 0xB0, 0xDF, 0xF8, 0x78, 0xA0, ++0x00, 0x25, 0x0C, 0xE0, 0x21, 0x46, 0x15, 0x48, 0x18, 0xF0, 0xD6, 0xFD, 0x3A, 0x68, 0x33, 0x88, 0x11, 0x89, 0x01, 0x35, ++0xAA, 0xB2, 0x01, 0x33, 0x91, 0x42, 0x33, 0x80, 0x1A, 0xD9, 0xB9, 0xF8, 0xD4, 0x10, 0x04, 0x39, 0x89, 0xB2, 0x40, 0x46, ++0xFC, 0xF7, 0x58, 0xFC, 0x04, 0x46, 0x00, 0x28, 0xE8, 0xD1, 0xA9, 0xB2, 0x58, 0x46, 0x19, 0xF0, 0x99, 0xFF, 0xDA, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDE, 0xDA, 0x07, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0xFB, 0x72, 0x1A, 0xF0, ++0x07, 0xFA, 0xD7, 0xE7, 0xBD, 0xE8, 0xF8, 0x8F, 0x78, 0x36, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xF0, 0x86, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x0C, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0xD2, 0xFD, 0x18, 0xB1, 0x0A, 0x4A, ++0x13, 0x88, 0x01, 0x3B, 0x13, 0x80, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, ++0x66, 0x28, 0x17, 0x00, 0x38, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x28, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x27, 0x4C, 0x28, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x65, 0xFD, 0x26, 0x4A, ++0x26, 0x49, 0x13, 0x88, 0x0D, 0x78, 0x01, 0x33, 0x9B, 0xB2, 0x13, 0x80, 0x24, 0x4A, 0x11, 0x78, 0x9D, 0xB9, 0x49, 0xB9, ++0x23, 0x68, 0x33, 0xB1, 0x1C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, ++0x1E, 0x49, 0x09, 0x78, 0x99, 0x42, 0xF1, 0xD8, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0x15, 0x70, 0x1B, 0xE0, 0x00, 0x29, ++0xEA, 0xD0, 0x19, 0x49, 0x09, 0x78, 0x99, 0x42, 0xE6, 0xD8, 0x18, 0x4B, 0x00, 0x21, 0x11, 0x70, 0xD3, 0xF8, 0x00, 0x28, ++0x22, 0xF4, 0x00, 0x52, 0xC3, 0xF8, 0x00, 0x28, 0xD3, 0xF8, 0x20, 0x2B, 0x8A, 0x42, 0x05, 0xDA, 0xD3, 0xF8, 0x20, 0x2B, ++0x42, 0xF0, 0x80, 0x62, 0xC3, 0xF8, 0x20, 0x2B, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0x17, 0xF0, 0xA9, 0xFF, 0x0D, 0x49, ++0x4F, 0xF4, 0x00, 0x70, 0x19, 0xF0, 0x4E, 0xFF, 0x0B, 0x4B, 0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0xC4, 0xE7, 0x00, 0xBF, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, 0x68, 0x60, 0x17, 0x00, ++0x64, 0x28, 0x17, 0x00, 0x88, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x87, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xF8, 0xB5, 0x0C, 0x4D, 0x0C, 0x48, 0x18, 0xF0, 0x01, 0xFD, 0x2B, 0x68, 0x9B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, ++0x00, 0x24, 0x7C, 0x21, 0x38, 0x46, 0xFC, 0xF7, 0x8D, 0xFB, 0x01, 0x46, 0x30, 0x46, 0x18, 0xF0, 0xF7, 0xFC, 0x2B, 0x68, ++0x01, 0x34, 0x9A, 0x88, 0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, 0x78, 0x36, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, ++0xE4, 0x25, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x1E, 0xFD, 0x23, 0x68, 0x33, 0xB1, ++0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, ++0xB9, 0xFC, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x48, ++0xFF, 0xF7, 0x5E, 0xFD, 0x03, 0x48, 0x19, 0xF0, 0x7B, 0xFE, 0x01, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0xFC, 0x87, 0x15, 0x00, ++0x28, 0x87, 0x15, 0x00, 0x70, 0xB5, 0x3C, 0x4D, 0x3C, 0x4C, 0x2A, 0x68, 0x3C, 0x49, 0x12, 0x69, 0x3C, 0x4B, 0x22, 0x60, ++0x02, 0xF1, 0x40, 0x06, 0x00, 0x24, 0x0E, 0x60, 0x3A, 0x4E, 0x98, 0x60, 0xC3, 0xE9, 0x00, 0x44, 0x21, 0x46, 0x10, 0x46, ++0x4F, 0xF4, 0xA0, 0x72, 0xC3, 0xE9, 0x04, 0x44, 0xDC, 0x60, 0xB4, 0x81, 0xF5, 0xF7, 0xEC, 0xFB, 0x2B, 0x68, 0x34, 0x49, ++0x58, 0x69, 0x34, 0x4A, 0x34, 0x4B, 0x08, 0x60, 0x21, 0x46, 0x00, 0xF1, 0x08, 0x04, 0x14, 0x60, 0x00, 0xF1, 0x10, 0x02, ++0x1A, 0x60, 0x00, 0xF1, 0x18, 0x02, 0x5A, 0x60, 0x00, 0xF1, 0x20, 0x02, 0x9A, 0x60, 0x2E, 0x4C, 0x00, 0xF1, 0x28, 0x02, ++0xDA, 0x60, 0x00, 0xF1, 0x30, 0x03, 0x4F, 0xF4, 0x4B, 0x62, 0x23, 0x60, 0xF5, 0xF7, 0xCE, 0xFB, 0x29, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2E, 0xDB, 0x27, 0x4B, 0x28, 0x49, 0xB3, 0xF8, 0xD4, 0x20, 0x0C, 0x68, 0xB3, 0xF8, ++0xD6, 0x00, 0xB3, 0xF8, 0xE6, 0x10, 0x25, 0x4D, 0x25, 0x4E, 0x12, 0x1B, 0x25, 0x4C, 0x04, 0x3A, 0x22, 0x60, 0x04, 0x38, ++0x24, 0x4C, 0x30, 0x60, 0x05, 0xFB, 0x01, 0xF1, 0x93, 0xF8, 0xE0, 0x00, 0x22, 0x4D, 0x20, 0x70, 0x22, 0x4A, 0x93, 0xF8, ++0xE1, 0x00, 0x28, 0x70, 0x93, 0xF8, 0xE2, 0x50, 0x20, 0x48, 0x15, 0x70, 0x20, 0x4C, 0x21, 0x4A, 0x93, 0xF8, 0xE3, 0x50, ++0x93, 0xF8, 0xE4, 0x30, 0x03, 0x70, 0x1F, 0x4B, 0x25, 0x70, 0x91, 0x42, 0xD4, 0xBF, 0x19, 0x60, 0x1A, 0x60, 0x01, 0x20, ++0x70, 0xBD, 0x2B, 0x68, 0x9B, 0x69, 0xB3, 0xF5, 0x4B, 0x6F, 0xCB, 0xD2, 0x19, 0x49, 0x1A, 0x48, 0x40, 0xF2, 0xF2, 0x22, ++0x1A, 0xF0, 0x76, 0xF8, 0xC4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, 0x58, 0x60, 0x17, 0x00, ++0xA4, 0x60, 0x17, 0x00, 0x8C, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, ++0x54, 0x60, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x40, 0x42, 0x0F, 0x00, ++0x9C, 0x60, 0x17, 0x00, 0x78, 0x60, 0x17, 0x00, 0x7C, 0x60, 0x17, 0x00, 0x88, 0x60, 0x17, 0x00, 0xA0, 0x60, 0x17, 0x00, ++0x68, 0x60, 0x17, 0x00, 0xA1, 0x60, 0x17, 0x00, 0xFF, 0xA2, 0xE1, 0x11, 0x6C, 0x60, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x3C, 0x87, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x43, 0x7E, 0x07, 0x7E, 0x09, 0x2B, 0x05, 0x46, 0x09, 0xD8, 0x49, 0x4A, ++0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x25, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x81, 0x80, 0x6B, 0x8B, ++0xDF, 0xF8, 0x30, 0x81, 0x1A, 0x07, 0x5A, 0xD4, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x83, 0x93, 0xF8, 0x64, 0x30, ++0x00, 0x2B, 0x73, 0xD0, 0x3E, 0x4B, 0xAE, 0x7D, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x63, 0xDB, 0x3C, 0x48, ++0x18, 0xF0, 0x0C, 0xFC, 0x04, 0x46, 0x00, 0x28, 0x4C, 0xD0, 0x3A, 0x48, 0xE1, 0x8B, 0x83, 0x5D, 0xE2, 0x6C, 0x4F, 0xF0, ++0x00, 0x09, 0x01, 0x33, 0x21, 0xF0, 0x01, 0x01, 0x83, 0x55, 0xE1, 0x83, 0xC4, 0xF8, 0x44, 0x90, 0x29, 0x46, 0xC2, 0xF8, ++0x10, 0x90, 0x20, 0x1D, 0x1C, 0x22, 0xC4, 0xF8, 0x2C, 0x90, 0x2C, 0xF0, 0xA9, 0xFA, 0x30, 0x4B, 0xE1, 0x8B, 0x1B, 0x68, ++0x84, 0xF8, 0x42, 0x90, 0xEB, 0x1A, 0x04, 0x3B, 0x21, 0xF4, 0x00, 0x42, 0x22, 0xF0, 0x02, 0x02, 0xA3, 0x64, 0x0B, 0x07, ++0xC4, 0xF8, 0x24, 0x90, 0xC4, 0xF8, 0x50, 0x90, 0xE2, 0x83, 0x29, 0xD4, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, ++0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x23, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, ++0x23, 0x20, 0x02, 0x44, 0x41, 0xF8, 0x23, 0x20, 0xA4, 0x20, 0x00, 0xFB, 0x07, 0x60, 0x99, 0x30, 0x21, 0x46, 0x08, 0xEB, ++0xC0, 0x00, 0xBD, 0xE8, 0xF8, 0x43, 0x18, 0xF0, 0x7F, 0xBB, 0x16, 0x48, 0x18, 0xF0, 0xC0, 0xFB, 0x05, 0x26, 0x04, 0x46, ++0x00, 0x28, 0xB2, 0xD1, 0x13, 0x4B, 0x16, 0x48, 0x99, 0x5D, 0xFB, 0xF7, 0x83, 0xFB, 0xFE, 0xE7, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x07, 0x80, 0x21, 0x46, 0x00, 0xF5, 0xA3, 0x60, 0xBD, 0xE8, 0xF8, 0x43, 0x18, 0xF0, 0x67, 0xBB, 0x05, 0x2E, ++0x99, 0xD9, 0x0E, 0x49, 0x0E, 0x48, 0x40, 0xF2, 0x5F, 0x32, 0x19, 0xF0, 0xB3, 0xFF, 0x92, 0xE7, 0x07, 0x4B, 0x18, 0x68, ++0x28, 0x1A, 0x04, 0x38, 0xBD, 0xE8, 0xF8, 0x43, 0xFC, 0xF7, 0x58, 0xBC, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x58, 0x17, 0x00, 0x74, 0x28, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x60, 0x87, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x88, 0x82, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x48, 0x81, ++0xDF, 0xF8, 0x48, 0x91, 0xDF, 0xF8, 0x48, 0xA1, 0x59, 0xE0, 0x47, 0x48, 0x18, 0xF0, 0x7A, 0xFB, 0x04, 0x46, 0xDF, 0xF8, ++0x40, 0xE1, 0x1C, 0x22, 0x29, 0x46, 0x04, 0x30, 0x00, 0x2C, 0x63, 0xD0, 0xB4, 0xF8, 0x1E, 0xB0, 0x1E, 0xF8, 0x07, 0xC0, ++0xE3, 0x6C, 0x66, 0x64, 0x2B, 0xF0, 0x01, 0x0B, 0x0C, 0xF1, 0x01, 0x0C, 0xA4, 0xF8, 0x1E, 0xB0, 0x1E, 0x61, 0xE6, 0x62, ++0x0E, 0xF8, 0x07, 0xC0, 0x2C, 0xF0, 0x16, 0xFA, 0x95, 0xF8, 0x20, 0x20, 0xE3, 0x8B, 0x38, 0x48, 0x12, 0xF0, 0x01, 0x0F, ++0x14, 0xBF, 0x4F, 0xF4, 0x00, 0x52, 0x4F, 0xF4, 0x08, 0x52, 0x2A, 0x61, 0x84, 0xF8, 0x42, 0x60, 0xC5, 0xE9, 0x05, 0x66, ++0x62, 0x7F, 0x10, 0x32, 0x92, 0x02, 0x45, 0xF8, 0x18, 0x2C, 0x21, 0x7F, 0x26, 0x65, 0xA4, 0x22, 0x99, 0x37, 0x23, 0xF4, ++0x00, 0x43, 0x12, 0xFB, 0x01, 0x77, 0x23, 0xF0, 0x02, 0x03, 0x4C, 0x3D, 0xA5, 0x64, 0x00, 0xEB, 0xC7, 0x00, 0xE3, 0x83, ++0x21, 0x46, 0x18, 0xF0, 0xF5, 0xFA, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x24, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x24, 0x4C, 0x24, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x2A, 0xFB, 0x98, 0xF8, 0x11, 0x35, ++0x22, 0x68, 0x01, 0x3B, 0x88, 0xF8, 0x11, 0x35, 0x3A, 0xBB, 0xD8, 0xF8, 0x14, 0x35, 0x00, 0x26, 0xDB, 0xB1, 0xD9, 0xF8, ++0x00, 0x20, 0x5D, 0x68, 0xB2, 0xF9, 0x00, 0x30, 0xAF, 0x7D, 0x00, 0x2B, 0x99, 0xDA, 0x05, 0x2F, 0x97, 0xD9, 0x18, 0x49, ++0x4F, 0xF4, 0x66, 0x72, 0x50, 0x46, 0x19, 0xF0, 0x1F, 0xFF, 0x90, 0xE7, 0x15, 0x48, 0x1E, 0xF8, 0x07, 0x10, 0xFB, 0xF7, ++0xD5, 0xFA, 0x14, 0x4B, 0x18, 0x68, 0x28, 0x1A, 0x04, 0x38, 0xFC, 0xF7, 0xC1, 0xFB, 0x20, 0x20, 0x18, 0xF0, 0x3E, 0xFA, ++0xBD, 0xE8, 0xF8, 0x4F, 0x40, 0x20, 0x18, 0xF0, 0x15, 0xBA, 0x08, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0x22, 0x60, 0x00, 0x2A, ++0x7F, 0xF4, 0x74, 0xAF, 0x00, 0x2B, 0x3F, 0xF4, 0x71, 0xAF, 0x62, 0xB6, 0x6E, 0xE7, 0x00, 0xBF, 0x20, 0x58, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x60, 0x87, 0x15, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x58, 0x58, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x82, 0x15, 0x00, ++0x74, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xB8, 0x90, 0x29, 0x4D, 0x2A, 0x4F, 0xDF, 0xF8, 0xAC, 0x80, ++0x29, 0x4E, 0x20, 0xE0, 0x5C, 0x68, 0x20, 0x46, 0xFA, 0xF7, 0x1E, 0xFB, 0x38, 0x68, 0x20, 0x1A, 0x04, 0x38, 0xFC, 0xF7, ++0x81, 0xFB, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, ++0x00, 0x30, 0x30, 0x46, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0xB3, 0xFA, 0x95, 0xF8, 0x9D, 0x37, 0xD9, 0xF8, ++0x00, 0x20, 0x01, 0x3B, 0x85, 0xF8, 0x9D, 0x37, 0x0A, 0xBB, 0xD5, 0xF8, 0xA0, 0x37, 0x00, 0x2B, 0xDA, 0xD1, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x14, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x4F, 0xF4, ++0x00, 0x00, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0xD4, 0xF9, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x0D, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x01, 0x3A, ++0xD8, 0xF8, 0x00, 0x30, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, 0xB3, 0xD1, 0x00, 0x2B, 0xB1, 0xD0, 0x62, 0xB6, 0xAF, 0xE7, ++0x58, 0x58, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0xF8, 0x5F, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x0E, 0x4B, 0x10, 0xB5, 0xD3, 0xF8, 0x90, 0x32, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0A, 0x4C, 0x23, 0x68, 0x10, 0x20, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x9E, 0xF9, ++0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF8, 0xB5, 0x16, 0x4C, 0x16, 0x4E, 0x17, 0x4F, ++0x14, 0x4D, 0x15, 0xE0, 0x58, 0x68, 0xFC, 0xF7, 0x05, 0xFB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, ++0x01, 0x23, 0x33, 0x60, 0x3B, 0x68, 0x28, 0x46, 0x01, 0x33, 0x3B, 0x60, 0x18, 0xF0, 0x3A, 0xFA, 0x0E, 0x4A, 0x39, 0x68, ++0x13, 0x78, 0x01, 0x3B, 0x13, 0x70, 0x39, 0xB9, 0x23, 0x68, 0x00, 0x2B, 0xE6, 0xD1, 0xBD, 0xE8, 0xF8, 0x40, 0x08, 0x20, ++0x18, 0xF0, 0x6A, 0xB9, 0x01, 0x39, 0x33, 0x68, 0x39, 0x60, 0x00, 0x29, 0xDA, 0xD1, 0x00, 0x2B, 0xD8, 0xD0, 0x62, 0xB6, ++0xD6, 0xE7, 0x00, 0xBF, 0x94, 0x4E, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x8E, 0x4E, 0x17, 0x00, ++0x59, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x67, 0xD1, 0x2D, 0xE9, 0xF0, 0x47, 0x57, 0x4D, 0x2B, 0x78, 0x00, 0x2B, 0x47, 0xD1, ++0x56, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x5B, 0xD1, 0x55, 0x49, 0x56, 0x4A, 0x09, 0x78, 0x12, 0x88, 0x91, 0x42, 0x5E, 0xD2, ++0x54, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x04, 0x46, 0x00, 0x28, 0x78, 0xD0, 0x2B, 0x78, 0x00, 0x2B, ++0x4D, 0xD0, 0x4C, 0x4B, 0xDF, 0xF8, 0x60, 0xA1, 0x1B, 0x78, 0x4E, 0x4F, 0xDA, 0xF8, 0x00, 0x00, 0x00, 0x2B, 0x7B, 0xD1, ++0x4C, 0x4B, 0x39, 0x68, 0xD3, 0xF8, 0x40, 0x34, 0x20, 0x44, 0x98, 0x47, 0x00, 0x28, 0x39, 0xD0, 0x01, 0x46, 0x49, 0x48, ++0xDF, 0xF8, 0x08, 0x91, 0xDF, 0xF8, 0x18, 0x81, 0xFB, 0xF7, 0xAE, 0xF9, 0x05, 0x26, 0x2B, 0x78, 0x00, 0x2B, 0x48, 0xD1, ++0xDA, 0xF8, 0x00, 0x00, 0xD8, 0xF8, 0x40, 0x34, 0x39, 0x68, 0x20, 0x44, 0x98, 0x47, 0x28, 0xB3, 0x01, 0x3E, 0xF2, 0xD1, ++0x05, 0x21, 0x3F, 0x48, 0xFB, 0xF7, 0x9C, 0xF9, 0x20, 0x46, 0xFC, 0xF7, 0x8B, 0xFA, 0xBD, 0xE8, 0xF0, 0x47, 0x04, 0x20, ++0x18, 0xF0, 0xE2, 0xB8, 0x34, 0x4B, 0x1B, 0x88, 0x00, 0x2B, 0x46, 0xD0, 0x31, 0x4A, 0x12, 0x78, 0x9A, 0x42, 0xB9, 0xD3, ++0x36, 0x4A, 0x2E, 0x4B, 0x12, 0x68, 0x01, 0x21, 0x19, 0x70, 0x00, 0x2A, 0x47, 0xD1, 0x34, 0x4B, 0x34, 0x49, 0x1A, 0x88, ++0x4F, 0xF4, 0x00, 0x70, 0x92, 0xB2, 0x19, 0xF0, 0x97, 0xFB, 0xA9, 0xE7, 0xBD, 0xE8, 0xF0, 0x87, 0x70, 0x47, 0xDF, 0xF8, ++0xC8, 0xA0, 0x28, 0x4F, 0xDA, 0xF8, 0x00, 0x00, 0xB4, 0xE7, 0x1A, 0x78, 0x00, 0x2A, 0x9D, 0xD1, 0x28, 0x4A, 0x12, 0x68, ++0x01, 0x21, 0x19, 0x70, 0x92, 0xBB, 0x27, 0x4B, 0x27, 0x49, 0x1A, 0x88, 0xBD, 0xE8, 0xF0, 0x47, 0x4F, 0xF4, 0x00, 0x70, ++0x92, 0xB2, 0x19, 0xF0, 0x7B, 0xBB, 0x99, 0xF8, 0x00, 0x30, 0xDA, 0xF8, 0x00, 0x00, 0x2B, 0xB9, 0xD8, 0xF8, 0x40, 0x34, ++0x39, 0x68, 0x20, 0x44, 0x98, 0x47, 0xB2, 0xE7, 0x39, 0x68, 0x20, 0x44, 0xFF, 0xF7, 0x72, 0xFA, 0xAD, 0xE7, 0x04, 0x20, ++0x18, 0xF0, 0x9C, 0xF8, 0xBD, 0xE8, 0xF0, 0x47, 0x19, 0x48, 0xFB, 0xF7, 0x49, 0xB9, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x49, ++0x4F, 0xF4, 0x00, 0x70, 0x19, 0xF0, 0x5C, 0xBB, 0x39, 0x68, 0x20, 0x44, 0xFF, 0xF7, 0x5E, 0xFA, 0x84, 0xE7, 0x40, 0xF2, ++0x1F, 0x40, 0x17, 0xF0, 0xF9, 0xFA, 0xB2, 0xE7, 0x40, 0xF2, 0x1F, 0x40, 0x17, 0xF0, 0xF4, 0xFA, 0xC7, 0xE7, 0x00, 0xBF, ++0x58, 0x28, 0x17, 0x00, 0x68, 0x60, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0x7C, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, ++0xA4, 0x60, 0x17, 0x00, 0x78, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x8C, 0x87, 0x15, 0x00, 0xAC, 0x87, 0x15, 0x00, ++0x6C, 0x60, 0x17, 0x00, 0x56, 0x28, 0x17, 0x00, 0x7C, 0x87, 0x15, 0x00, 0x98, 0x87, 0x15, 0x00, 0x84, 0x87, 0x15, 0x00, ++0x80, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x0F, 0x48, 0x19, 0xF0, 0xD8, 0xFA, 0x0E, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, ++0x98, 0x47, 0x80, 0xB1, 0x0C, 0x4B, 0x0D, 0x49, 0x1A, 0x68, 0x0D, 0x4B, 0x09, 0x68, 0xD3, 0xF8, 0x40, 0x34, 0x10, 0x44, ++0x98, 0x47, 0x01, 0x1E, 0x00, 0xDB, 0x08, 0xBD, 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x48, 0xFB, 0xF7, 0xF7, 0xB8, 0xBD, 0xE8, ++0x08, 0x40, 0x07, 0x48, 0xFB, 0xF7, 0xF2, 0xB8, 0xC0, 0x87, 0x15, 0x00, 0xA4, 0x60, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, ++0x78, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xCC, 0x87, 0x15, 0x00, 0xE4, 0x87, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x20, ++0x18, 0xF0, 0x52, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x09, 0x4C, 0x0A, 0x4A, 0x23, 0x68, 0xD2, 0xF8, 0x3C, 0x24, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x33, 0xB1, ++0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x11, 0x4D, 0x11, 0x4F, 0x28, 0x68, 0x00, 0xF5, 0x0D, 0x70, ++0x18, 0xF0, 0xA4, 0xF8, 0x28, 0x68, 0x00, 0xF5, 0x0F, 0x70, 0x18, 0xF0, 0x9F, 0xF8, 0x3B, 0x68, 0x1B, 0x89, 0x93, 0xB1, ++0x0B, 0x4E, 0x00, 0x24, 0x4F, 0xF4, 0xD7, 0x61, 0x30, 0x46, 0xFB, 0xF7, 0x2B, 0xFF, 0x01, 0x46, 0x28, 0x68, 0x00, 0xF5, ++0x0D, 0x70, 0x18, 0xF0, 0x93, 0xF8, 0x3B, 0x68, 0x01, 0x34, 0x1A, 0x89, 0xA3, 0xB2, 0x9A, 0x42, 0xEE, 0xD8, 0xF8, 0xBD, ++0x00, 0x38, 0x18, 0x00, 0x78, 0x36, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x12, 0x4A, ++0x01, 0x46, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0E, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4C, 0x0E, 0x4A, 0x23, 0x68, 0x10, 0x68, 0x01, 0x33, 0x00, 0xF5, 0x0D, 0x70, 0x23, 0x60, ++0x18, 0xF0, 0x6C, 0xF8, 0x23, 0x68, 0x33, 0xB1, 0x06, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x02, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x4C, 0x40, 0x04, 0x40, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x00, 0x38, 0x18, 0x00, 0x08, 0xB5, 0x03, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x19, 0xF0, 0x7A, 0xFA, ++0x01, 0x20, 0x08, 0xBD, 0x08, 0x88, 0x15, 0x00, 0x05, 0x4A, 0x06, 0x49, 0x00, 0x23, 0xC2, 0xE9, 0x02, 0x03, 0xC2, 0xE9, ++0x04, 0x33, 0xC2, 0xE9, 0x00, 0x33, 0x8B, 0x81, 0x01, 0x20, 0x70, 0x47, 0xBC, 0x60, 0x17, 0x00, 0xD4, 0x60, 0x17, 0x00, ++0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x0C, 0x92, 0xDF, 0xF8, 0x0C, 0x82, 0xD9, 0xF8, 0x14, 0x35, 0x00, 0x2B, 0x00, 0xF0, ++0x8F, 0x80, 0xDF, 0xF8, 0xE8, 0xA1, 0xDF, 0xF8, 0x00, 0xB2, 0x78, 0xE0, 0x71, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, ++0x06, 0x12, 0x92, 0xF8, 0x64, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xB2, 0x80, 0x6D, 0x4A, 0x1F, 0x7A, 0x13, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA1, 0x80, 0x6A, 0x48, 0x18, 0xF0, 0x5B, 0xF8, 0x04, 0x46, 0x00, 0x28, 0x6C, 0xD0, ++0xC2, 0x8B, 0xC1, 0x6C, 0x1A, 0xF8, 0x07, 0xC0, 0x00, 0x23, 0x22, 0xF0, 0x01, 0x02, 0xC2, 0x83, 0x43, 0x64, 0x0C, 0xF1, ++0x01, 0x0C, 0x0B, 0x61, 0x1C, 0x22, 0xC3, 0x62, 0x29, 0x46, 0x04, 0x30, 0x0A, 0xF8, 0x07, 0xC0, 0x2B, 0xF0, 0xFA, 0xFE, ++0xE2, 0x8B, 0xDB, 0xF8, 0x00, 0x10, 0x6D, 0x1A, 0xC2, 0xF3, 0x0E, 0x01, 0x00, 0x23, 0xE1, 0x83, 0x11, 0x07, 0x84, 0xF8, ++0x42, 0x30, 0x23, 0x65, 0xA5, 0x64, 0x6F, 0xD4, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, ++0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x53, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x02, 0x44, ++0x41, 0xF8, 0x23, 0x20, 0xA4, 0x20, 0x00, 0xFB, 0x06, 0x76, 0x4A, 0x48, 0x99, 0x36, 0x21, 0x46, 0x00, 0xEB, 0xC6, 0x00, ++0x17, 0xF0, 0xD6, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x48, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xD8, 0xF8, 0x00, 0x30, 0x46, 0x48, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0x0A, 0xF8, 0x99, 0xF8, 0x11, 0x35, ++0xD8, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0x89, 0xF8, 0x11, 0x35, 0x3A, 0xB1, 0x3E, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, ++0x00, 0x20, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD9, 0xF8, 0x14, 0x35, 0x83, 0xB1, 0x5D, 0x68, 0x6A, 0x8B, 0x2E, 0x7E, ++0x14, 0x07, 0x81, 0xD5, 0x34, 0x48, 0x17, 0xF0, 0xEF, 0xFF, 0x05, 0x27, 0x04, 0x46, 0x00, 0x28, 0x92, 0xD1, 0x35, 0x4B, ++0x35, 0x48, 0xD9, 0x5D, 0xFA, 0xF7, 0xB2, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2E, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x20, 0x20, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x17, 0xF0, 0x14, 0xFF, ++0x40, 0x20, 0x17, 0xF0, 0xED, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x25, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, ++0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x24, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x21, 0x46, ++0x00, 0xFB, 0x06, 0x30, 0x17, 0xF0, 0x7A, 0xFF, 0xA2, 0xE7, 0x05, 0x2F, 0x7F, 0xF6, 0x5C, 0xAF, 0x1F, 0x49, 0x20, 0x48, ++0xB8, 0x22, 0x19, 0xF0, 0xC5, 0xFB, 0x55, 0xE7, 0xDB, 0xF8, 0x00, 0x00, 0x28, 0x1A, 0xFC, 0xF7, 0x6D, 0xF8, 0xEF, 0xF3, ++0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x12, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x11, 0x48, ++0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x17, 0xF0, 0x9F, 0xFF, 0x99, 0xF8, 0x11, 0x25, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0x3A, ++0x89, 0xF8, 0x11, 0x25, 0x00, 0x2B, 0x9B, 0xD0, 0x08, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x00, 0x2B, ++0x94, 0xD1, 0x00, 0x2A, 0x92, 0xD0, 0x90, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, ++0x7C, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x74, 0x28, 0x17, 0x00, 0x1C, 0x88, 0x15, 0x00, ++0x30, 0x8D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x88, 0x82, 0x15, 0x00, 0x58, 0x58, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x84, 0x1A, 0x17, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x04, 0x20, 0x17, 0xF0, ++0xA5, 0xBE, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0xD0, 0xF8, 0xA8, 0x44, 0xD1, 0xF8, 0xB0, 0x50, 0x07, 0x46, 0x0E, 0x46, ++0x00, 0x2C, 0x00, 0xF0, 0x8F, 0x80, 0xA2, 0x49, 0xA2, 0x4A, 0x4F, 0xF0, 0xFF, 0x33, 0x0B, 0x60, 0x13, 0x60, 0x94, 0xF8, ++0x60, 0x80, 0xB8, 0xF1, 0x04, 0x0F, 0x00, 0xF2, 0xB9, 0x81, 0xDF, 0xE8, 0x18, 0xF0, 0x49, 0x00, 0xF3, 0x00, 0x45, 0x01, ++0x03, 0x01, 0x05, 0x00, 0x9A, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, 0x22, 0x6F, ++0xDA, 0x60, 0x22, 0x6D, 0xDA, 0x61, 0x62, 0x6D, 0x1A, 0x62, 0xA2, 0x6D, 0x5A, 0x62, 0x94, 0x4B, 0x94, 0x4A, 0xE1, 0x6D, ++0x1B, 0x68, 0x11, 0x60, 0x1B, 0x78, 0x13, 0xF0, 0x02, 0x0F, 0xC1, 0x46, 0x4F, 0xF4, 0x80, 0x63, 0x4F, 0xF4, 0x80, 0x51, ++0x4F, 0xF0, 0x01, 0x08, 0x48, 0xD0, 0x97, 0xF8, 0x63, 0xC0, 0x94, 0xF8, 0x62, 0x00, 0x8C, 0x4A, 0x43, 0xEA, 0x0C, 0x13, ++0x43, 0xEA, 0x00, 0x43, 0x0B, 0x43, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0x00, 0x2D, ++0x48, 0xD0, 0x81, 0x4B, 0x7F, 0x49, 0xD6, 0xF8, 0x26, 0x00, 0x72, 0x8D, 0x08, 0x60, 0x1A, 0x60, 0x95, 0xF8, 0x60, 0x30, ++0x04, 0x2B, 0x00, 0xF2, 0x68, 0x81, 0xDF, 0xE8, 0x13, 0xF0, 0x78, 0x00, 0x41, 0x00, 0xD4, 0x00, 0xCF, 0x00, 0xC5, 0x00, ++0x00, 0x21, 0x4F, 0xF0, 0x01, 0x09, 0x77, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, ++0x22, 0x6F, 0xDA, 0x60, 0x73, 0x4B, 0x1B, 0x68, 0xB9, 0xF1, 0x02, 0x0F, 0x1B, 0x78, 0x40, 0xF0, 0xF2, 0x80, 0xD8, 0x07, ++0x40, 0xF1, 0x20, 0x81, 0x71, 0x48, 0x22, 0x6D, 0x02, 0x60, 0x62, 0x6D, 0x42, 0x60, 0xA2, 0x6D, 0x82, 0x60, 0xE2, 0x6D, ++0xC2, 0x60, 0x9B, 0x07, 0x00, 0xF1, 0xFF, 0x80, 0x4F, 0xF4, 0x00, 0x73, 0x97, 0xF8, 0x63, 0xC0, 0x94, 0xF8, 0x62, 0x00, ++0x67, 0x4A, 0x43, 0xEA, 0x0C, 0x13, 0x43, 0xEA, 0x00, 0x43, 0x0B, 0x43, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, ++0x58, 0x00, 0xFC, 0xD4, 0x00, 0x2D, 0xB6, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0xA1, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0xAE, 0xE7, ++0x4F, 0xF0, 0x02, 0x09, 0x59, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, ++0xDA, 0x60, 0xB9, 0xF1, 0x04, 0x0F, 0x40, 0xF0, 0x96, 0x80, 0x57, 0x4B, 0x2A, 0x6D, 0x1A, 0x60, 0x6A, 0x6D, 0x5A, 0x60, ++0xAA, 0x6D, 0x9A, 0x60, 0x50, 0x4B, 0x51, 0x4A, 0xE9, 0x6D, 0x1B, 0x68, 0x11, 0x60, 0x1B, 0x78, 0x99, 0x07, 0x40, 0xF1, ++0xD6, 0x80, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF4, 0x80, 0x69, 0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x4A, 0x4A, ++0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, 0x08, 0x03, 0x43, 0xEA, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, ++0x13, 0x68, 0x58, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x01, 0x09, 0x3D, 0x4B, ++0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, 0xDA, 0x60, 0xB9, 0xF1, 0x02, 0x0F, ++0x62, 0xD1, 0x38, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0xDA, 0x07, 0x40, 0xF1, 0xB3, 0x80, 0x38, 0x4A, 0x29, 0x6D, 0x11, 0x60, ++0x69, 0x6D, 0x51, 0x60, 0xA9, 0x6D, 0x91, 0x60, 0xE9, 0x6D, 0xD1, 0x60, 0x9A, 0x07, 0x7A, 0xD4, 0x4F, 0xF4, 0x00, 0x79, ++0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x2E, 0x4A, 0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, 0x08, 0x03, ++0x43, 0xEA, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x59, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, ++0x4F, 0xF0, 0x02, 0x09, 0x22, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, 0x22, 0x6F, ++0xDA, 0x60, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x01, 0x08, 0x51, 0xE7, 0x4F, 0xF0, 0x01, 0x09, 0xC8, 0x46, 0x4F, 0xF4, ++0x80, 0x51, 0x42, 0xE7, 0x18, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, ++0xDA, 0x60, 0x80, 0xE7, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF0, 0x01, 0x09, 0xA7, 0xE7, 0x95, 0xF8, 0x74, 0x30, 0x10, 0x2B, ++0x00, 0xF0, 0x83, 0x80, 0x20, 0x2B, 0x7B, 0xD0, 0x0D, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, ++0x9A, 0x60, 0x2A, 0x6F, 0xDA, 0x60, 0x4F, 0xF0, 0x03, 0x09, 0xB9, 0xF1, 0x02, 0x0F, 0x4F, 0xEA, 0x08, 0x38, 0x9C, 0xD0, ++0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9E, 0x07, 0x56, 0xD4, 0x4F, 0xEA, 0x09, 0x29, 0xA7, 0xE7, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0xD4, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, ++0xC8, 0x00, 0x32, 0x40, 0x94, 0xF8, 0x74, 0x30, 0x10, 0x2B, 0x5B, 0xD0, 0x20, 0x2B, 0x4A, 0xD0, 0x4F, 0xF0, 0x03, 0x09, ++0xA6, 0xE7, 0x9A, 0x07, 0x42, 0xD5, 0x09, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x01, 0x2B, 0x14, 0xD9, 0x4F, 0xEA, 0x09, 0x23, ++0xCB, 0xE6, 0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x3A, 0x4A, 0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, ++0x08, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, 0x97, 0xF8, ++0x63, 0x30, 0x94, 0xF8, 0x62, 0x00, 0x31, 0x4A, 0x41, 0xEA, 0x03, 0x13, 0x43, 0xEA, 0x00, 0x43, 0x43, 0xF0, 0x80, 0x43, ++0x13, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0xB9, 0xE6, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF4, 0x80, 0x69, 0x5F, 0xE7, ++0x29, 0x48, 0x02, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x02, 0x60, 0xE2, 0xE6, 0x26, 0x49, 0x0A, 0x68, 0x22, 0xF0, 0x01, 0x02, ++0x0A, 0x60, 0x4F, 0xE7, 0x09, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x01, 0x2B, 0xC7, 0xD9, 0x4F, 0xEA, 0x09, 0x29, 0x14, 0xE7, ++0x4F, 0xEA, 0x09, 0x23, 0xD6, 0xE6, 0x4F, 0xF4, 0x00, 0x51, 0x4F, 0xF0, 0x03, 0x09, 0xB0, 0xE6, 0x4F, 0xF4, 0x00, 0x58, ++0x4F, 0xF0, 0x03, 0x09, 0x1F, 0xE7, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x03, 0x09, 0x1A, 0xE7, 0x00, 0x21, 0x88, 0x46, ++0x4F, 0xF0, 0x03, 0x09, 0xA1, 0xE6, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xD6, 0xAE, ++0x12, 0x49, 0x13, 0x48, 0xA6, 0x22, 0x19, 0xF0, 0xA7, 0xF9, 0xCF, 0xE6, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x06, 0xDB, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x01, 0x08, 0x87, 0xE6, 0x09, 0x49, ++0x09, 0x48, 0x4F, 0x22, 0x19, 0xF0, 0x94, 0xF9, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x01, 0x08, ++0x7B, 0xE6, 0x00, 0xBF, 0xC4, 0x00, 0x32, 0x40, 0x64, 0x05, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xA3, 0x4E, 0x0D, 0x46, 0xD6, 0xF8, 0xF0, 0x70, 0x04, 0x46, 0xF4, 0xF7, ++0xF7, 0xFE, 0xB8, 0x47, 0xA0, 0x4A, 0xA1, 0x49, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x0A, 0x68, 0x9F, 0x4B, ++0x42, 0xF4, 0x80, 0x32, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x7F, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x02, ++0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xFE, 0x02, 0x42, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x97, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x4F, 0xF4, 0x40, 0x52, 0x00, 0x2B, 0xC1, 0xF8, 0x04, 0x21, 0xC0, 0xF2, 0xAD, 0x80, 0x92, 0x4B, 0x8E, 0x4A, ++0x92, 0x49, 0x19, 0x60, 0x13, 0x68, 0x92, 0x4F, 0x43, 0xF4, 0x00, 0x53, 0x13, 0x60, 0xF5, 0xF7, 0x49, 0xFD, 0xDF, 0xF8, ++0x9C, 0xC2, 0x8F, 0x49, 0xDC, 0xF8, 0x00, 0x20, 0x43, 0x1C, 0x9B, 0x06, 0x22, 0xF0, 0xE0, 0x52, 0x03, 0xF0, 0xE0, 0x53, ++0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0x0B, 0x68, 0x89, 0x4A, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, ++0x02, 0x03, 0x13, 0x60, 0x3B, 0x68, 0x9A, 0x03, 0x00, 0xF1, 0xAF, 0x80, 0x84, 0x4A, 0x28, 0x8C, 0x13, 0x68, 0x80, 0x49, ++0x9B, 0xB2, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x60, 0x0B, 0x68, 0x1F, 0x04, 0x00, 0xF1, 0x87, 0x80, 0x75, 0x4B, 0xDF, 0xF8, ++0x50, 0xE2, 0x1A, 0x68, 0xDF, 0xF8, 0x4C, 0xC2, 0x7C, 0x48, 0x7D, 0x4F, 0x7D, 0x49, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, ++0x4F, 0xF4, 0x40, 0x72, 0xCE, 0xF8, 0x00, 0x20, 0xE2, 0x6D, 0xCC, 0xF8, 0x00, 0x20, 0xB4, 0xF8, 0x60, 0x20, 0x02, 0x60, ++0xA2, 0x6B, 0xA0, 0x8F, 0x3A, 0x60, 0xD4, 0xF8, 0x90, 0x21, 0x08, 0x60, 0x91, 0x78, 0x74, 0x4A, 0x02, 0xEB, 0x81, 0x01, ++0x50, 0x68, 0x49, 0x69, 0xC7, 0xF8, 0xBC, 0x10, 0x19, 0x68, 0x21, 0xF4, 0xE0, 0x61, 0x19, 0x60, 0x13, 0x68, 0x6F, 0x49, ++0x6F, 0x4A, 0x03, 0x43, 0x3B, 0x64, 0x6F, 0x48, 0x6F, 0x4B, 0x08, 0x60, 0x13, 0x60, 0xD6, 0xF8, 0xB0, 0x31, 0x94, 0xF8, ++0x63, 0x10, 0x95, 0xF8, 0x23, 0x00, 0x98, 0x47, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x70, 0xFD, 0x09, 0xF0, 0xAC, 0xFB, ++0x68, 0x4B, 0x93, 0xF8, 0xB6, 0x30, 0x23, 0xB1, 0x67, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0xD6, 0xF8, ++0x60, 0x32, 0x98, 0x47, 0x64, 0x4A, 0x65, 0x49, 0xD6, 0xF8, 0x9C, 0x34, 0x11, 0x60, 0x98, 0x47, 0x4D, 0x4A, 0x63, 0x48, ++0x13, 0x68, 0x30, 0x24, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x01, 0x21, 0x04, 0x60, 0x00, 0x20, 0x17, 0xF0, 0xDE, 0xF9, ++0x5E, 0x4B, 0x1B, 0x68, 0x5A, 0x78, 0x22, 0xB1, 0x5D, 0x49, 0x0A, 0x68, 0x42, 0xF0, 0x40, 0x02, 0x0A, 0x60, 0x5C, 0x49, ++0x9B, 0x78, 0x0A, 0x68, 0xD8, 0x06, 0x4C, 0xBF, 0x22, 0xF0, 0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x58, 0x4A, ++0x13, 0xF0, 0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, 0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0x3C, 0x4B, 0x1B, 0x68, 0xB3, 0xF1, 0xC8, 0x5F, 0xBF, 0xF4, 0x4D, 0xAF, 0x50, 0x49, 0x50, 0x48, 0xF3, 0x22, ++0x19, 0xF0, 0x9C, 0xF8, 0x46, 0xE7, 0xF5, 0xF7, 0x35, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x74, 0xAF, 0x6B, 0x68, 0x9A, 0x06, ++0x7F, 0xF5, 0x70, 0xAF, 0x28, 0x8C, 0xF5, 0xF7, 0x71, 0xFC, 0x07, 0xF0, 0xB9, 0xFF, 0xD6, 0xF8, 0xE0, 0x33, 0x98, 0x47, ++0x94, 0xF8, 0x62, 0x30, 0x04, 0x2B, 0x3F, 0xF4, 0x63, 0xAF, 0xD6, 0xF8, 0x30, 0x33, 0x94, 0xF8, 0x63, 0x00, 0x98, 0x47, ++0x5C, 0xE7, 0xF5, 0xF7, 0x3F, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x4C, 0xAF, 0xF5, 0xF7, 0x6E, 0xFC, 0xDF, 0xF8, 0xF4, 0x80, ++0xD8, 0xF8, 0x00, 0x30, 0x00, 0x02, 0x23, 0xF4, 0xE0, 0x63, 0x00, 0xF4, 0xE0, 0x60, 0x18, 0x43, 0xC8, 0xF8, 0x00, 0x00, ++0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, ++0x43, 0xF0, 0x04, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF0, 0x01, 0x03, 0xC8, 0xF8, 0x00, 0x30, ++0x3B, 0x68, 0x1B, 0x04, 0x0F, 0xD4, 0x15, 0x4B, 0x1B, 0x68, 0x9B, 0x03, 0x7F, 0xF5, 0x22, 0xAF, 0xF5, 0xF7, 0x18, 0xFC, ++0x00, 0x28, 0x3F, 0xF4, 0x1D, 0xAF, 0x27, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x16, 0xE7, 0xF5, 0xF7, ++0xDF, 0xFB, 0x00, 0x28, 0xEB, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, 0x80, 0x63, 0xC8, 0xF8, ++0x00, 0x30, 0xE2, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x54, 0x00, 0x32, 0x40, 0x64, 0x00, 0x32, 0x40, ++0x38, 0x36, 0x17, 0x00, 0xD8, 0x00, 0x32, 0x40, 0x10, 0x19, 0x04, 0x00, 0x04, 0x00, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x68, 0x00, 0x32, 0x40, 0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0xC0, 0x07, 0xF9, 0x80, ++0x2C, 0x19, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, 0xC0, 0xB3, 0x33, 0x40, 0xA0, 0xA0, 0x28, 0x28, 0x38, 0x00, 0x32, 0x40, ++0x34, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, 0x80, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x40, 0x88, 0x15, 0x00, 0x50, 0x03, 0x32, 0x40, 0x9C, 0x00, 0x32, 0x40, 0x1C, 0x00, 0x32, 0x40, 0x10, 0x00, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x47, 0x5B, 0x4B, 0x5C, 0x4A, 0x1D, 0x68, 0xD2, 0xF8, 0x20, 0x80, 0x15, 0xF0, 0x01, 0x05, 0xD8, 0xF8, ++0xE4, 0x90, 0x84, 0xB0, 0x00, 0xF0, 0x83, 0x80, 0x1A, 0x68, 0x57, 0x4F, 0x22, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x00, 0x23, ++0x7B, 0x70, 0x01, 0x22, 0x54, 0x48, 0x55, 0x49, 0x03, 0x68, 0x55, 0x4C, 0x43, 0xF0, 0x10, 0x03, 0x03, 0x60, 0x0B, 0x68, ++0x00, 0xF5, 0xEC, 0x10, 0x00, 0xF6, 0x6C, 0x70, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x23, 0x68, 0x01, 0x69, 0x00, 0x91, ++0x02, 0x20, 0x4E, 0x49, 0x4E, 0x4C, 0x18, 0xF0, 0x9D, 0xFD, 0x3B, 0x78, 0x00, 0x2B, 0x42, 0xD0, 0xD4, 0xF8, 0x3C, 0x31, ++0xD8, 0xF8, 0x40, 0x60, 0x00, 0x20, 0x98, 0x47, 0x49, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x62, 0xDB, ++0xD4, 0xF8, 0x9C, 0x34, 0xDF, 0xF8, 0x38, 0xA1, 0x98, 0x47, 0xD4, 0xF8, 0x80, 0x34, 0x30, 0x79, 0x98, 0x47, 0x4F, 0xF0, ++0x00, 0x0C, 0x33, 0x89, 0xF2, 0x88, 0x71, 0x79, 0x30, 0x79, 0xCD, 0xF8, 0x08, 0xC0, 0x96, 0xF8, 0x0D, 0xC0, 0xCD, 0xF8, ++0x04, 0xC0, 0xB6, 0xF8, 0x0A, 0xC0, 0xCD, 0xF8, 0x00, 0xC0, 0xF5, 0xF7, 0x9F, 0xFA, 0xD4, 0xF8, 0x3C, 0x33, 0x96, 0xF9, ++0x0C, 0x00, 0x98, 0x47, 0x9A, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x33, 0xD0, 0xD4, 0xF8, 0xA8, 0x34, 0xBA, 0xF8, 0x26, 0x00, ++0x98, 0x47, 0xBA, 0xF8, 0x26, 0x00, 0xD4, 0xF8, 0xAC, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0xD8, 0x34, 0x49, 0x46, 0x40, 0x46, ++0x98, 0x47, 0x00, 0x23, 0xC7, 0xE9, 0x01, 0x33, 0x3B, 0x70, 0x00, 0x2D, 0x33, 0xD0, 0x2B, 0x49, 0x2B, 0x4A, 0x0B, 0x68, ++0x23, 0xF4, 0x00, 0x73, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x28, 0x4A, 0x28, 0x48, 0x13, 0x68, ++0x28, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x83, 0x68, 0xD4, 0xF8, 0xA0, 0x22, 0x5A, 0x65, ++0x20, 0x23, 0x0B, 0x60, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x16, 0x4F, 0x2A, 0x46, 0x81, 0xE7, 0xD4, 0xF8, 0xA0, 0x34, ++0xBA, 0xF8, 0x26, 0x00, 0x98, 0x47, 0xBA, 0xF8, 0x26, 0x00, 0xD4, 0xF8, 0xA4, 0x34, 0x98, 0x47, 0xCA, 0xE7, 0x33, 0x7E, ++0xFF, 0x2B, 0x99, 0xD1, 0x19, 0x49, 0x1A, 0x48, 0x40, 0xF2, 0x89, 0x12, 0x18, 0xF0, 0x4C, 0xFF, 0x92, 0xE7, 0x40, 0x46, ++0x0B, 0xF0, 0xF6, 0xF8, 0xD8, 0xF8, 0x04, 0x30, 0x15, 0x4A, 0x43, 0xF0, 0x01, 0x03, 0xC8, 0xF8, 0x04, 0x30, 0x92, 0xF8, ++0xB6, 0x30, 0x00, 0x2B, 0xC7, 0xD0, 0x03, 0xF0, 0x99, 0xF8, 0xC4, 0xE7, 0x10, 0x00, 0x58, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x3C, 0x36, 0x17, 0x00, 0x94, 0x80, 0x32, 0x40, 0x84, 0x40, 0x04, 0x40, 0x88, 0x00, 0x32, 0x40, 0x88, 0x88, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x8C, 0x00, 0x32, 0x40, 0x78, 0x00, 0x32, 0x40, ++0x00, 0xED, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE0, 0x70, 0x79, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0xF8, 0xB5, 0x3F, 0x4F, 0x3F, 0x4C, 0x3E, 0x6A, 0x3F, 0x49, 0xD6, 0xF8, 0xE4, 0x50, 0x4F, 0xF4, ++0xBE, 0x72, 0x20, 0x46, 0x2B, 0xF0, 0xB0, 0xF9, 0x31, 0x46, 0x4F, 0xF4, 0xA4, 0x62, 0x04, 0xF5, 0xBE, 0x70, 0x2B, 0xF0, ++0xA9, 0xF9, 0x29, 0x46, 0x4F, 0xF4, 0x1E, 0x72, 0x04, 0xF2, 0x9C, 0x60, 0x2B, 0xF0, 0xA2, 0xF9, 0x06, 0xF1, 0xEC, 0x01, ++0xE8, 0x22, 0x04, 0xF6, 0x14, 0x10, 0x2B, 0xF0, 0x9B, 0xF9, 0x31, 0x6C, 0x1C, 0x22, 0x04, 0xF6, 0xFC, 0x10, 0x2B, 0xF0, ++0x95, 0xF9, 0x2F, 0x49, 0x34, 0x22, 0x04, 0xF6, 0x18, 0x20, 0x2B, 0xF0, 0x8F, 0xF9, 0x2D, 0x49, 0x18, 0x22, 0x04, 0xF6, ++0x4C, 0x20, 0x2B, 0xF0, 0x89, 0xF9, 0x2B, 0x49, 0x4F, 0xF4, 0x40, 0x72, 0x04, 0xF6, 0x64, 0x20, 0x2B, 0xF0, 0x82, 0xF9, ++0x28, 0x49, 0x4F, 0xF4, 0x98, 0x62, 0x04, 0xF6, 0x64, 0x50, 0x2B, 0xF0, 0x7B, 0xF9, 0x26, 0x49, 0x26, 0x48, 0x40, 0x22, ++0x2B, 0xF0, 0x76, 0xF9, 0x39, 0x46, 0x28, 0x22, 0x24, 0x48, 0x2B, 0xF0, 0x71, 0xF9, 0x24, 0x49, 0x24, 0x48, 0x60, 0x22, ++0x2B, 0xF0, 0x6C, 0xF9, 0x23, 0x4A, 0x24, 0x4B, 0x12, 0x68, 0xD3, 0xF8, 0x84, 0x60, 0xB2, 0xF8, 0x3C, 0xC0, 0xD3, 0xF8, ++0x80, 0x20, 0xD3, 0xE9, 0x22, 0x07, 0x41, 0xF2, 0x10, 0x33, 0x41, 0xF2, 0x30, 0x31, 0x24, 0xF8, 0x03, 0xC0, 0x41, 0xF2, ++0x2C, 0x33, 0x66, 0x50, 0xE2, 0x50, 0x41, 0xF2, 0x38, 0x36, 0x41, 0xF2, 0x3C, 0x33, 0x41, 0xF2, 0x34, 0x31, 0x18, 0x4A, ++0xE2, 0x50, 0xA7, 0x51, 0x17, 0x4B, 0x60, 0x50, 0x05, 0xF5, 0xBC, 0x70, 0x05, 0xF5, 0xCE, 0x71, 0x50, 0xF8, 0x04, 0x2F, ++0x1A, 0xB1, 0x14, 0x7B, 0x9C, 0x70, 0x12, 0x89, 0x1A, 0x80, 0x88, 0x42, 0x03, 0xF1, 0x04, 0x03, 0xF4, 0xD1, 0xF8, 0xBD, ++0x1C, 0x9E, 0x17, 0x00, 0x00, 0x40, 0x1E, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0x34, 0xE0, 0x17, 0x00, 0xF4, 0xDF, 0x17, 0x00, 0x24, 0x52, 0x1E, 0x00, 0x64, 0x52, 0x1E, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x8C, 0x52, 0x1E, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, ++0xEC, 0x52, 0x1E, 0x00, 0x70, 0xB5, 0x65, 0x4A, 0x53, 0x78, 0x00, 0x2B, 0x7F, 0xD1, 0x64, 0x4B, 0x1B, 0x68, 0x3B, 0xB1, ++0x63, 0x48, 0xD9, 0x68, 0x00, 0x69, 0x09, 0x1A, 0xB1, 0xF5, 0xFA, 0x6F, 0x00, 0xF1, 0xA5, 0x80, 0x13, 0x78, 0x00, 0x2B, ++0x68, 0xD0, 0xD2, 0xE9, 0x01, 0x35, 0x5D, 0x48, 0x5D, 0x4A, 0x5E, 0x49, 0x04, 0x69, 0x0E, 0x68, 0xB2, 0xF8, 0xB0, 0x00, ++0xB2, 0xF8, 0xB2, 0x10, 0xB2, 0x8E, 0x2B, 0x44, 0x1B, 0x1B, 0x1B, 0x1A, 0x5B, 0x1A, 0x9B, 0x1A, 0x00, 0x2B, 0xC0, 0xF2, ++0x98, 0x80, 0xFF, 0xF7, 0x37, 0xFF, 0x56, 0x4B, 0x1B, 0x6A, 0x1C, 0x6C, 0x23, 0x79, 0x20, 0x89, 0x00, 0x2B, 0x56, 0xD0, ++0x2A, 0xF0, 0xC8, 0xFB, 0x02, 0x46, 0x0B, 0x46, 0x2A, 0xF0, 0x78, 0xFA, 0x50, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0x54, 0xFD, ++0x4F, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0x26, 0xFC, 0x2A, 0xF0, 0x1E, 0xFA, 0x2A, 0xF0, 0xBC, 0xFE, 0x05, 0x46, 0x20, 0x89, ++0x2A, 0xF0, 0xB4, 0xFB, 0x02, 0x46, 0x0B, 0x46, 0x00, 0x20, 0x49, 0x49, 0x2A, 0xF0, 0x42, 0xFD, 0x00, 0x22, 0x4F, 0xF0, ++0x83, 0x43, 0x2A, 0xF0, 0x13, 0xFC, 0x2A, 0xF0, 0x0B, 0xFA, 0x2A, 0xF0, 0xA9, 0xFE, 0x03, 0x46, 0x20, 0x89, 0x1C, 0x46, ++0x2A, 0xF0, 0xA0, 0xFB, 0x34, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x2A, 0xF0, 0x2F, 0xFD, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, ++0x2A, 0xF0, 0x00, 0xFC, 0x2A, 0xF0, 0xF8, 0xF9, 0x2A, 0xF0, 0x96, 0xFE, 0x3A, 0x4B, 0x3B, 0x49, 0x03, 0xF5, 0x99, 0x56, ++0x02, 0x46, 0x35, 0x60, 0x41, 0xF2, 0x24, 0x30, 0x41, 0xF2, 0x28, 0x35, 0x1C, 0x50, 0x5A, 0x51, 0x02, 0x20, 0x18, 0xF0, ++0xD5, 0xFB, 0x35, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x33, 0x49, 0x02, 0x20, 0x18, 0xF0, 0xCC, 0xFB, ++0x30, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x30, 0x49, 0xF5, 0xE7, 0x2A, 0xF0, 0x71, 0xFB, 0x2F, 0x4B, ++0x00, 0x22, 0x2A, 0xF0, 0xD7, 0xFB, 0x25, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0xFD, 0xFC, 0x24, 0x4B, 0x00, 0x22, 0x2A, 0xF0, ++0xCF, 0xFB, 0x2A, 0xF0, 0xC7, 0xF9, 0x2A, 0xF0, 0x65, 0xFE, 0x05, 0x46, 0x20, 0x89, 0x2A, 0xF0, 0x5D, 0xFB, 0x02, 0x46, ++0x0B, 0x46, 0x00, 0x20, 0x24, 0x49, 0x2A, 0xF0, 0xEB, 0xFC, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x2A, 0xF0, 0xBC, 0xFB, ++0x2A, 0xF0, 0xB4, 0xF9, 0x2A, 0xF0, 0x52, 0xFE, 0x03, 0x46, 0x20, 0x89, 0x1C, 0x46, 0x2A, 0xF0, 0x49, 0xFB, 0x0B, 0xA3, ++0xD3, 0xE9, 0x00, 0x23, 0xA7, 0xE7, 0x5A, 0x68, 0x1A, 0x49, 0x02, 0x20, 0x18, 0xF0, 0x92, 0xFB, 0x13, 0x4B, 0x4F, 0xF0, ++0x00, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x17, 0x49, 0xBB, 0xE7, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x10, 0xB3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xA2, 0x40, 0x3C, 0x36, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x00, 0x6A, 0x40, ++0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0xB9, 0x40, 0x00, 0x40, 0x1E, 0x00, 0x20, 0x89, 0x15, 0x00, 0x00, 0x41, 0x04, 0x40, ++0x1C, 0x89, 0x15, 0x00, 0xC4, 0x88, 0x15, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0xA4, 0x40, 0xE8, 0x88, 0x15, 0x00, ++0x00, 0x89, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, 0x56, 0x4E, 0xDF, 0xF8, 0x90, 0x81, 0x96, 0xF8, ++0xDF, 0x31, 0x96, 0xF8, 0xBF, 0x56, 0xDF, 0xF8, 0x88, 0xB1, 0x53, 0x4C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xF7, ++0x83, 0xB0, 0x08, 0xEB, 0x07, 0x09, 0x06, 0xF5, 0xBE, 0x71, 0x48, 0x46, 0x01, 0x93, 0x4F, 0xF4, 0x1E, 0x7A, 0x00, 0x97, ++0x2B, 0xF0, 0x0E, 0xF8, 0x07, 0xF1, 0xEC, 0x00, 0x0A, 0xFB, 0x05, 0xF5, 0x06, 0xF6, 0x14, 0x11, 0xE8, 0x22, 0x40, 0x44, ++0x2B, 0xF0, 0x04, 0xF8, 0x05, 0xEB, 0x0B, 0x03, 0x18, 0x46, 0x52, 0x46, 0x06, 0xF2, 0x9C, 0x61, 0x08, 0xEE, 0x10, 0x3A, ++0x2A, 0xF0, 0xFA, 0xFF, 0x06, 0xF6, 0xFC, 0x11, 0x1C, 0x22, 0xD9, 0xF8, 0x40, 0x00, 0x3F, 0x4F, 0xDF, 0xF8, 0x30, 0xA1, ++0x2A, 0xF0, 0xF0, 0xFF, 0x06, 0xF6, 0x18, 0x21, 0x34, 0x22, 0x3C, 0x48, 0x2A, 0xF0, 0xEA, 0xFF, 0x31, 0x46, 0x4F, 0xF4, ++0xBE, 0x72, 0x3A, 0x48, 0x2A, 0xF0, 0xE4, 0xFF, 0x06, 0xF6, 0x4C, 0x21, 0x18, 0x22, 0x38, 0x48, 0x2A, 0xF0, 0xDE, 0xFF, ++0x06, 0xF6, 0x64, 0x21, 0x4F, 0xF4, 0x18, 0x62, 0x35, 0x48, 0x2A, 0xF0, 0xD7, 0xFF, 0x06, 0xF6, 0x64, 0x51, 0x4F, 0xF4, ++0x98, 0x62, 0x33, 0x48, 0x33, 0x4E, 0x2A, 0xF0, 0xCF, 0xFF, 0x40, 0x22, 0xA4, 0xF1, 0xC8, 0x01, 0x31, 0x48, 0x2A, 0xF0, ++0xC9, 0xFF, 0x28, 0x22, 0xA4, 0xF1, 0x88, 0x01, 0x2F, 0x48, 0x2A, 0xF0, 0xC3, 0xFF, 0x2F, 0x48, 0x60, 0x22, 0xA4, 0xF1, ++0x60, 0x01, 0x2A, 0xF0, 0xBD, 0xFF, 0x05, 0xF5, 0xBE, 0x75, 0xAB, 0x44, 0x5B, 0xF8, 0x04, 0x3B, 0x50, 0x46, 0x19, 0x46, ++0x4B, 0xB1, 0xA2, 0x78, 0x1A, 0x73, 0xD7, 0xF8, 0xDC, 0x22, 0x25, 0x88, 0x1D, 0x81, 0xC3, 0xE9, 0x45, 0x23, 0x17, 0xF0, ++0x01, 0xF9, 0x04, 0x34, 0xB4, 0x42, 0xED, 0xD1, 0x1B, 0x48, 0x22, 0x4D, 0x49, 0x46, 0x17, 0xF0, 0xF9, 0xF8, 0x21, 0x48, ++0x49, 0x46, 0x17, 0xF0, 0xA5, 0xF8, 0x00, 0x9E, 0x06, 0xF1, 0xE4, 0x00, 0x18, 0xEE, 0x10, 0x1A, 0x40, 0x44, 0x17, 0xF0, ++0x9D, 0xF8, 0x01, 0x9A, 0xA4, 0x24, 0x99, 0x23, 0x14, 0xFB, 0x02, 0x34, 0x08, 0xEB, 0xC4, 0x04, 0x35, 0x44, 0x20, 0x46, ++0x17, 0xF0, 0x8E, 0xF8, 0x04, 0xF1, 0x28, 0x00, 0x08, 0x34, 0x17, 0xF0, 0x89, 0xF8, 0xAC, 0x42, 0xF5, 0xD1, 0x00, 0x9B, ++0x03, 0xF5, 0xA3, 0x60, 0x40, 0x44, 0x03, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x4F, 0x17, 0xF0, 0x7C, 0xB8, ++0x00, 0x40, 0x1E, 0x00, 0xEC, 0x52, 0x1E, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x34, 0xE0, 0x17, 0x00, 0x10, 0x53, 0x1E, 0x00, 0xF4, 0xDF, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x08, 0x8D, 0x17, 0x00, 0x08, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0xF8, 0xDE, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x6C, 0x4E, 0x6D, 0x4A, 0x33, 0x68, 0xDF, 0xF8, ++0x00, 0x82, 0x0D, 0x46, 0x09, 0x8C, 0x9B, 0xB2, 0x43, 0xEA, 0x01, 0x43, 0xD0, 0xF8, 0x90, 0x11, 0x33, 0x60, 0x8B, 0x78, ++0x67, 0x49, 0x02, 0xEB, 0x83, 0x03, 0x1C, 0x3E, 0x5B, 0x69, 0x0B, 0x60, 0x31, 0x68, 0x21, 0xF4, 0xE0, 0x61, 0x04, 0x46, ++0x50, 0x68, 0x31, 0x60, 0x13, 0x68, 0x62, 0x49, 0x62, 0x4A, 0x03, 0x43, 0x0B, 0x60, 0x62, 0x4B, 0x62, 0x49, 0x11, 0x60, ++0x62, 0x4A, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x9F, 0x03, 0x70, 0xD4, 0x60, 0x4B, 0x1B, 0x68, 0x1A, 0x68, 0xE2, 0xB1, ++0x5F, 0x49, 0x0A, 0x60, 0x5A, 0x68, 0xF2, 0xB1, 0xC2, 0xF3, 0x0B, 0x01, 0x00, 0x29, 0x61, 0xD1, 0xE1, 0x68, 0x5C, 0x48, ++0x22, 0xF4, 0x7F, 0x62, 0x22, 0xF0, 0x0F, 0x02, 0xC1, 0xF3, 0x0B, 0x01, 0x0A, 0x43, 0x02, 0x60, 0x9A, 0x68, 0xA2, 0xB9, ++0x57, 0x4A, 0x21, 0x69, 0x11, 0x60, 0xDB, 0x68, 0xA3, 0xB9, 0x56, 0x4B, 0x62, 0x69, 0x1A, 0x60, 0x12, 0xE0, 0x51, 0x4A, ++0xA1, 0x68, 0x11, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0xE0, 0xD1, 0x4F, 0x4A, 0xE1, 0x68, 0x11, 0x60, 0x9A, 0x68, 0x00, 0x2A, ++0xEA, 0xD0, 0x4D, 0x49, 0x0A, 0x60, 0xDB, 0x68, 0x00, 0x2B, 0xEA, 0xD0, 0x4B, 0x4A, 0x13, 0x60, 0x4B, 0x4B, 0xD3, 0xF8, ++0x60, 0x32, 0x98, 0x47, 0x4A, 0x4B, 0x1B, 0x68, 0x9C, 0x01, 0x06, 0xD4, 0x49, 0x4B, 0x3E, 0x4A, 0x01, 0x21, 0x19, 0x60, ++0x13, 0x68, 0x0B, 0x43, 0x13, 0x60, 0x28, 0x46, 0x1B, 0xF0, 0xE4, 0xFA, 0x43, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x04, 0x03, ++0x13, 0x60, 0x01, 0x21, 0x00, 0x20, 0x16, 0xF0, 0x51, 0xFD, 0x41, 0x4B, 0x1B, 0x68, 0x5A, 0x78, 0x22, 0xB1, 0x40, 0x49, ++0x0A, 0x68, 0x42, 0xF0, 0x40, 0x02, 0x0A, 0x60, 0x3E, 0x49, 0x9B, 0x78, 0x0A, 0x68, 0xD8, 0x06, 0x4C, 0xBF, 0x22, 0xF0, ++0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x3A, 0x4A, 0x13, 0xF0, 0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, ++0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x2B, 0x49, 0x0A, 0x60, 0xB8, 0xE7, 0xF4, 0xF7, ++0xD7, 0xFF, 0x00, 0x28, 0x8A, 0xD0, 0xF5, 0xF7, 0x07, 0xF8, 0x31, 0x4F, 0x3B, 0x68, 0x00, 0x02, 0x23, 0xF4, 0xE0, 0x63, ++0x00, 0xF4, 0xE0, 0x60, 0x18, 0x43, 0x38, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0x3B, 0x60, ++0x3B, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x3B, 0x60, 0x3B, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, ++0x1B, 0x04, 0x0F, 0xD4, 0x24, 0x4B, 0x1B, 0x68, 0x9E, 0x03, 0x7F, 0xF5, 0x69, 0xAF, 0xF4, 0xF7, 0xB9, 0xFF, 0x00, 0x28, ++0x3F, 0xF4, 0x64, 0xAF, 0x1E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x5D, 0xE7, 0xF4, 0xF7, 0x80, 0xFF, ++0x00, 0x28, 0xEB, 0xD0, 0x33, 0x68, 0x43, 0xF4, 0x00, 0x23, 0x33, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, ++0x80, 0x63, 0x3B, 0x60, 0xE0, 0xE7, 0x00, 0xBF, 0x68, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, ++0x60, 0x00, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0xC0, 0x07, 0xF9, 0x80, ++0xAC, 0x35, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, ++0x80, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x50, 0x03, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x33, 0x4D, 0xDF, 0xF8, 0xE4, 0x80, 0xD5, 0xF8, 0xD0, 0x34, 0x32, 0x4E, 0x41, 0xF2, 0x12, 0x32, 0x18, 0xF8, 0x02, 0x70, ++0x98, 0x47, 0xD5, 0xF8, 0x9C, 0x34, 0x98, 0x47, 0xD8, 0xF8, 0xBC, 0x41, 0xF4, 0xF7, 0x46, 0xF9, 0x2C, 0x49, 0xD5, 0xF8, ++0x88, 0x24, 0x0B, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x0B, 0x60, 0x20, 0x79, 0x90, 0x47, 0x23, 0x79, 0x86, 0xF8, 0x2A, 0x30, ++0x62, 0x79, 0x86, 0xF8, 0x2B, 0x20, 0x62, 0x7B, 0x86, 0xF8, 0x2C, 0x20, 0xE1, 0x88, 0x20, 0x89, 0x62, 0x89, 0x32, 0x85, ++0xFF, 0xB2, 0xB1, 0x84, 0xF0, 0x84, 0xD3, 0xB9, 0xD5, 0xF8, 0xA0, 0x34, 0x98, 0x47, 0xF0, 0x8C, 0xD5, 0xF8, 0xA4, 0x34, ++0x98, 0x47, 0x1D, 0x4E, 0x94, 0xF9, 0x0C, 0x00, 0xD5, 0xF8, 0x3C, 0x33, 0x98, 0x47, 0xD5, 0xF8, 0xD4, 0x34, 0x06, 0xF5, ++0xA4, 0x61, 0x30, 0x46, 0x98, 0x47, 0x17, 0xF0, 0x0D, 0x0F, 0x0C, 0xD0, 0xD5, 0xF8, 0x54, 0x32, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0xD5, 0xF8, 0xA8, 0x34, 0x98, 0x47, 0xF0, 0x8C, 0xD5, 0xF8, 0xAC, 0x34, 0x98, 0x47, 0xE3, 0xE7, 0xBB, 0x07, ++0x14, 0xD5, 0x0F, 0x4A, 0xD8, 0xF8, 0x80, 0x31, 0x11, 0x69, 0x0E, 0x48, 0xD5, 0xF8, 0xE0, 0x21, 0x46, 0x61, 0x05, 0x24, ++0x44, 0x77, 0x01, 0xF5, 0x1C, 0x51, 0x43, 0xF0, 0x02, 0x03, 0xC8, 0xF8, 0x80, 0x31, 0x10, 0x31, 0xBD, 0xE8, 0xF0, 0x41, ++0x0C, 0x30, 0x10, 0x47, 0xBD, 0xE8, 0xF0, 0x81, 0x88, 0x1A, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, ++0x7C, 0x41, 0x1E, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x40, 0x1E, 0x00, 0x38, 0xB5, 0x50, 0xBB, ++0x1A, 0x4B, 0x1A, 0x68, 0x52, 0xB1, 0x1A, 0x4B, 0x1A, 0x49, 0x18, 0x69, 0xD3, 0x68, 0xB1, 0xF8, 0xB0, 0x10, 0x1B, 0x1A, ++0x5B, 0x1A, 0xB3, 0xF5, 0xFA, 0x6F, 0x17, 0xD4, 0x16, 0x4A, 0x13, 0x78, 0x7B, 0xB1, 0xD2, 0xE9, 0x01, 0x34, 0x12, 0x48, ++0x14, 0x4D, 0x12, 0x49, 0x00, 0x69, 0x2A, 0x68, 0xB1, 0xF8, 0xB0, 0x10, 0x92, 0x8E, 0x23, 0x44, 0x1B, 0x1A, 0x5B, 0x1A, ++0x9B, 0x1A, 0x00, 0x2B, 0x0E, 0xDB, 0x0F, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x38, 0xBD, 0x52, 0x68, 0x0D, 0x49, ++0x02, 0x20, 0x18, 0xF0, 0xDB, 0xF8, 0x0A, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x38, 0xBD, 0x09, 0x49, 0x02, 0x20, ++0x18, 0xF0, 0xD2, 0xF8, 0xF5, 0xE7, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0x3C, 0x36, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x41, 0x04, 0x40, 0xE8, 0x88, 0x15, 0x00, 0x28, 0x89, 0x15, 0x00, ++0xF0, 0xB5, 0x1B, 0x4B, 0x01, 0x22, 0x85, 0xB0, 0xDA, 0x60, 0xEF, 0xF3, 0x14, 0x81, 0xEF, 0xF3, 0x03, 0x82, 0xEF, 0xF3, ++0x09, 0x85, 0xEF, 0xF3, 0x08, 0x84, 0xEF, 0xF3, 0x10, 0x83, 0x70, 0x46, 0xCD, 0xE9, 0x01, 0x30, 0x00, 0x94, 0x13, 0x48, ++0x2B, 0x46, 0x18, 0xF0, 0x59, 0xF8, 0x15, 0xB9, 0x34, 0xB9, 0x05, 0xB0, 0xF0, 0xBD, 0x10, 0x48, 0x18, 0xF0, 0x52, 0xF8, ++0x00, 0x2C, 0xF8, 0xD0, 0x0E, 0x48, 0x0F, 0x4F, 0x0F, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0x18, 0xF0, 0x49, 0xF8, 0x04, 0xF5, ++0x80, 0x75, 0x06, 0xE0, 0x54, 0xF8, 0x04, 0x1B, 0x30, 0x46, 0x18, 0xF0, 0x41, 0xF8, 0xA5, 0x42, 0xE7, 0xD0, 0x23, 0x07, ++0xF6, 0xD1, 0x21, 0x46, 0x38, 0x46, 0x18, 0xF0, 0x39, 0xF8, 0xF1, 0xE7, 0x00, 0xA0, 0x10, 0x40, 0x40, 0x89, 0x15, 0x00, ++0x94, 0x89, 0x15, 0x00, 0xA0, 0x89, 0x15, 0x00, 0xAC, 0x89, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0x30, 0xB4, 0x0C, 0x4C, ++0x0C, 0x49, 0xD4, 0xF8, 0x3C, 0x31, 0x0C, 0x4A, 0x0C, 0x4D, 0x43, 0xF0, 0x04, 0x03, 0xC4, 0xF8, 0x3C, 0x31, 0xC0, 0x03, ++0x03, 0x24, 0xF4, 0x23, 0x08, 0x60, 0x8C, 0x60, 0x82, 0xF8, 0x44, 0x33, 0xAB, 0x68, 0x07, 0x49, 0xC3, 0xF8, 0x50, 0x11, ++0x10, 0x23, 0x30, 0xBC, 0x93, 0x60, 0x70, 0x47, 0x00, 0x00, 0x50, 0x40, 0x00, 0xA0, 0x10, 0x40, 0x00, 0xE1, 0x00, 0xE0, ++0x00, 0xED, 0x00, 0xE0, 0xA9, 0xC5, 0x12, 0x00, 0x01, 0x4B, 0x1A, 0x68, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, ++0x02, 0x4A, 0x93, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x93, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, 0x02, 0x4A, 0x93, 0x68, ++0x43, 0xF0, 0x02, 0x03, 0x93, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, 0x08, 0xB5, 0x06, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0xFE, 0xE7, 0x03, 0x49, 0x04, 0x48, 0xBA, 0x22, 0x18, 0xF0, 0x5F, 0xFA, 0xF8, 0xE7, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x0B, 0x4B, 0x41, 0xF2, 0x1C, 0x32, 0x41, 0xF2, ++0x18, 0x31, 0x9A, 0x58, 0x5B, 0x58, 0x72, 0xB1, 0x10, 0xB4, 0x08, 0x4C, 0x00, 0x22, 0x19, 0x68, 0x58, 0x68, 0x08, 0x60, ++0x21, 0x68, 0x02, 0x32, 0x91, 0x42, 0x03, 0xF1, 0x08, 0x03, 0xF6, 0xD8, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x70, 0x47, ++0x00, 0x40, 0x1E, 0x00, 0x1C, 0x53, 0x1E, 0x00, 0x32, 0x49, 0x33, 0x4B, 0x99, 0x42, 0x10, 0xB5, 0x0C, 0xD2, 0x01, 0x3B, ++0x5B, 0x1A, 0x31, 0x4A, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x52, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0B, ++0x9A, 0x42, 0xF9, 0xD1, 0x2C, 0x4A, 0x2D, 0x4B, 0x9A, 0x42, 0x0A, 0xD2, 0x01, 0x3B, 0x9B, 0x1A, 0x23, 0xF0, 0x03, 0x03, ++0x04, 0x33, 0x13, 0x44, 0x00, 0x21, 0x42, 0xF8, 0x04, 0x1B, 0x9A, 0x42, 0xFB, 0xD1, 0x27, 0x49, 0x27, 0x4B, 0x99, 0x42, ++0x0D, 0xD2, 0x01, 0x3B, 0x5B, 0x1A, 0x26, 0x4A, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x08, 0x46, 0x52, 0xF8, ++0x04, 0x4B, 0x40, 0xF8, 0x04, 0x4B, 0x9A, 0x42, 0xF9, 0xD1, 0x21, 0x4A, 0x21, 0x48, 0xD2, 0xF8, 0x88, 0x30, 0x43, 0xF4, ++0x70, 0x03, 0xC2, 0xF8, 0x88, 0x30, 0x91, 0x60, 0x00, 0x23, 0xFF, 0x21, 0xC2, 0x18, 0x01, 0x33, 0x50, 0x2B, 0x82, 0xF8, ++0x00, 0x13, 0xF9, 0xD1, 0x1A, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x80, 0x6F, 0x16, 0x4B, 0x1B, 0x68, 0x4F, 0xF6, 0xF0, 0x72, ++0x03, 0xEA, 0x02, 0x03, 0x0D, 0xD0, 0x4C, 0xF2, 0x40, 0x22, 0x93, 0x42, 0x0D, 0xD0, 0x14, 0x4C, 0xF5, 0xF7, 0xBC, 0xFC, ++0xD4, 0xF8, 0x7C, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0x74, 0x34, 0x98, 0x47, 0xFE, 0xE7, 0x4D, 0xF2, 0x10, 0x22, 0x93, 0x42, ++0xF1, 0xD1, 0x0E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xED, 0xE7, 0x00, 0xBF, 0x80, 0x01, 0x17, 0x00, 0x5C, 0x25, 0x17, 0x00, ++0x2C, 0xD2, 0x15, 0x00, 0x60, 0x25, 0x17, 0x00, 0x28, 0x07, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x80, 0x01, 0x17, 0x00, ++0x00, 0x00, 0x12, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x68, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x72, 0x4F, 0x73, 0x4E, 0x86, 0xB0, 0x3D, 0x46, 0x00, 0x24, 0x21, 0x46, ++0x55, 0xF8, 0x04, 0x2B, 0x30, 0x46, 0x01, 0x34, 0xF9, 0xF7, 0x6A, 0xFD, 0x0D, 0x2C, 0xF6, 0xD1, 0xD7, 0xE9, 0x11, 0x21, ++0x3B, 0x6C, 0x6C, 0x4D, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x21, 0x6B, 0x48, 0x79, 0x6B, 0xD7, 0xE9, 0x0E, 0x23, 0xF9, 0xF7, ++0x5B, 0xFD, 0x29, 0x68, 0x6A, 0x68, 0xAB, 0x68, 0xE8, 0x68, 0x00, 0x90, 0x66, 0x48, 0xF9, 0xF7, 0x53, 0xFD, 0x69, 0x6A, ++0xAA, 0x6A, 0xEB, 0x6A, 0x28, 0x6B, 0xEC, 0x6B, 0xCD, 0xE9, 0x00, 0x04, 0x62, 0x48, 0xF9, 0xF7, 0x49, 0xFD, 0xAC, 0x6A, ++0x14, 0xF0, 0xFF, 0x01, 0x68, 0xD1, 0xC4, 0xF3, 0x07, 0x25, 0x14, 0xF4, 0x7F, 0x4F, 0x29, 0x46, 0x44, 0xD1, 0x21, 0x0C, ++0x2E, 0xD1, 0xFB, 0x6C, 0x1C, 0x07, 0x23, 0xD5, 0x5A, 0x48, 0xF9, 0xF7, 0x37, 0xFD, 0x3B, 0x6D, 0xD8, 0x07, 0x21, 0xD4, ++0x58, 0x48, 0xF9, 0xF7, 0x31, 0xFD, 0xFB, 0x6C, 0x59, 0x07, 0x4C, 0xBF, 0x56, 0x48, 0x57, 0x48, 0xF9, 0xF7, 0x2A, 0xFD, ++0x39, 0x6D, 0xEF, 0xF3, 0x10, 0x82, 0xEF, 0xF3, 0x13, 0x83, 0xEF, 0xF3, 0x11, 0x80, 0x00, 0x90, 0x52, 0x48, 0xF9, 0xF7, ++0x1F, 0xFD, 0xBC, 0x6C, 0x00, 0x2C, 0x71, 0xD1, 0x7C, 0x6C, 0x00, 0x2C, 0x56, 0xD1, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, ++0x4D, 0x48, 0xF9, 0xF7, 0x13, 0xFD, 0xDD, 0xE7, 0x4C, 0x48, 0xF9, 0xF7, 0x0F, 0xFD, 0xDC, 0xE7, 0xC4, 0xF3, 0x40, 0x63, ++0xC4, 0xF3, 0x00, 0x60, 0xC4, 0xF3, 0xC0, 0x42, 0x03, 0x93, 0xC4, 0xF3, 0x80, 0x43, 0xCD, 0xE9, 0x01, 0x20, 0x00, 0x93, ++0xC4, 0xF3, 0x00, 0x42, 0xC4, 0xF3, 0x40, 0x43, 0x43, 0x48, 0xF9, 0xF7, 0xFB, 0xFC, 0xBC, 0xE7, 0xC4, 0xF3, 0xC0, 0x33, ++0xC4, 0xF3, 0x00, 0x30, 0xC4, 0xF3, 0xC0, 0x22, 0x04, 0x93, 0xC4, 0xF3, 0x40, 0x36, 0xC4, 0xF3, 0x80, 0x23, 0xCD, 0xE9, ++0x00, 0x32, 0xCD, 0xE9, 0x02, 0x06, 0xC4, 0xF3, 0x40, 0x23, 0x3A, 0x48, 0xC4, 0xF3, 0x00, 0x22, 0xF9, 0xF7, 0xE4, 0xFC, ++0x2D, 0x06, 0xA2, 0xD5, 0x2A, 0x4B, 0x37, 0x48, 0x99, 0x6B, 0xF9, 0xF7, 0xDD, 0xFC, 0x9C, 0xE7, 0xC4, 0xF3, 0xC0, 0x16, ++0xC4, 0xF3, 0x40, 0x10, 0xC4, 0xF3, 0x00, 0x12, 0xC4, 0xF3, 0xC0, 0x03, 0xCD, 0xE9, 0x02, 0x06, 0xCD, 0xE9, 0x00, 0x32, ++0x2F, 0x48, 0xC4, 0xF3, 0x40, 0x03, 0x04, 0xF0, 0x01, 0x02, 0xF9, 0xF7, 0xC9, 0xFC, 0x26, 0x06, 0x81, 0xD5, 0x69, 0x6B, ++0x2B, 0x48, 0xF9, 0xF7, 0xC3, 0xFC, 0x7C, 0xE7, 0x2A, 0x48, 0x2B, 0x4F, 0x2B, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0xF9, 0xF7, ++0xBB, 0xFC, 0x04, 0xF5, 0x80, 0x75, 0x06, 0xE0, 0x54, 0xF8, 0x04, 0x1B, 0x30, 0x46, 0xF9, 0xF7, 0xB3, 0xFC, 0xA5, 0x42, ++0x97, 0xD0, 0x23, 0x07, 0xF6, 0xD1, 0x21, 0x46, 0x38, 0x46, 0xF9, 0xF7, 0xAB, 0xFC, 0xF1, 0xE7, 0x21, 0x48, 0xDF, 0xF8, ++0x7C, 0x80, 0x1F, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0xF9, 0xF7, 0xA2, 0xFC, 0x04, 0xF5, 0x80, 0x75, 0x07, 0xE0, 0x54, 0xF8, ++0x04, 0x1B, 0x30, 0x46, 0xF9, 0xF7, 0x9A, 0xFC, 0xA5, 0x42, 0x3F, 0xF4, 0x7B, 0xAF, 0x22, 0x07, 0xF5, 0xD1, 0x21, 0x46, ++0x40, 0x46, 0xF9, 0xF7, 0x91, 0xFC, 0xF0, 0xE7, 0xE4, 0x60, 0x17, 0x00, 0xC0, 0x89, 0x15, 0x00, 0x00, 0xED, 0x00, 0xE0, ++0xD0, 0x89, 0x15, 0x00, 0x1C, 0x8A, 0x15, 0x00, 0x50, 0x8A, 0x15, 0x00, 0xF0, 0x8B, 0x15, 0x00, 0x10, 0x8C, 0x15, 0x00, ++0x34, 0x8C, 0x15, 0x00, 0x40, 0x8C, 0x15, 0x00, 0x4C, 0x8C, 0x15, 0x00, 0x24, 0x8C, 0x15, 0x00, 0x00, 0x8C, 0x15, 0x00, ++0x8C, 0x8B, 0x15, 0x00, 0x04, 0x8B, 0x15, 0x00, 0x7C, 0x8B, 0x15, 0x00, 0x90, 0x8A, 0x15, 0x00, 0xF4, 0x8A, 0x15, 0x00, ++0x80, 0x8C, 0x15, 0x00, 0xAC, 0x89, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0xA0, 0x89, 0x15, 0x00, 0x08, 0xB5, 0x02, 0x48, ++0xF9, 0xF7, 0x60, 0xFC, 0xFE, 0xE7, 0x00, 0xBF, 0x8C, 0x8C, 0x15, 0x00, 0x04, 0x46, 0x08, 0xB5, 0x10, 0x48, 0xF9, 0xF7, ++0x57, 0xFC, 0x30, 0x2C, 0x10, 0xD0, 0x40, 0x2C, 0x16, 0xD0, 0x20, 0x2C, 0x10, 0xD0, 0x0D, 0x48, 0xF9, 0xF7, 0x4E, 0xFC, ++0x0C, 0x48, 0xF9, 0xF7, 0x4B, 0xFC, 0xFF, 0xF7, 0xD1, 0xFE, 0x0B, 0x48, 0xF9, 0xF7, 0x46, 0xFC, 0xFF, 0xF7, 0xE0, 0xFF, ++0x09, 0x48, 0xF9, 0xF7, 0x41, 0xFC, 0xF1, 0xE7, 0x08, 0x48, 0xF9, 0xF7, 0x3D, 0xFC, 0xED, 0xE7, 0x07, 0x48, 0xF9, 0xF7, ++0x39, 0xFC, 0xE9, 0xE7, 0x98, 0x8C, 0x15, 0x00, 0xE8, 0x8C, 0x15, 0x00, 0xF4, 0x8C, 0x15, 0x00, 0x00, 0x8D, 0x15, 0x00, ++0xD0, 0x8C, 0x15, 0x00, 0xC0, 0x8C, 0x15, 0x00, 0xDC, 0x8C, 0x15, 0x00, 0x4F, 0xF0, 0x10, 0x03, 0x00, 0xF0, 0x0C, 0xB8, ++0x4F, 0xF0, 0x20, 0x03, 0x00, 0xF0, 0x08, 0xB8, 0x4F, 0xF0, 0x30, 0x03, 0x00, 0xF0, 0x04, 0xB8, 0x4F, 0xF0, 0x40, 0x03, ++0x00, 0xF0, 0x00, 0xB8, 0xEF, 0xF3, 0x08, 0x80, 0x4F, 0xF0, 0x04, 0x01, 0x72, 0x46, 0x0A, 0x42, 0x01, 0xD0, 0xEF, 0xF3, ++0x09, 0x80, 0x9C, 0x46, 0x24, 0x49, 0x02, 0x68, 0x0A, 0x60, 0x04, 0x31, 0x42, 0x68, 0x0A, 0x60, 0x04, 0x31, 0x82, 0x68, ++0x0A, 0x60, 0x04, 0x31, 0xC2, 0x68, 0x0A, 0x60, 0x04, 0x31, 0xF0, 0xC1, 0x47, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x4F, 0x46, ++0x0F, 0x60, 0x04, 0x31, 0x57, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x5F, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x02, 0x69, 0x0A, 0x60, ++0x08, 0x31, 0x42, 0x69, 0x0A, 0x60, 0x04, 0x31, 0x82, 0x69, 0x0A, 0x60, 0x04, 0x31, 0xC2, 0x69, 0x0A, 0x60, 0x04, 0x31, ++0x03, 0x46, 0x20, 0x33, 0x4F, 0xF4, 0x00, 0x76, 0x32, 0x42, 0x00, 0xD0, 0x04, 0x33, 0x75, 0x46, 0x4F, 0xF0, 0x10, 0x06, ++0x35, 0x42, 0x00, 0xD1, 0x48, 0x33, 0x0C, 0x46, 0x10, 0x3C, 0x23, 0x60, 0xEF, 0xF3, 0x09, 0x82, 0x0A, 0x60, 0x04, 0x31, ++0xEF, 0xF3, 0x08, 0x82, 0x0A, 0x60, 0x04, 0x31, 0x72, 0x46, 0x0A, 0x60, 0x04, 0x31, 0xEF, 0xF3, 0x14, 0x82, 0x0A, 0x60, ++0x03, 0x4B, 0x60, 0x46, 0x01, 0x49, 0x98, 0x47, 0xFE, 0xE7, 0x00, 0x00, 0xE4, 0x60, 0x17, 0x00, 0x3D, 0xCA, 0x12, 0x00, ++0x08, 0xB5, 0x08, 0x4B, 0x00, 0x22, 0x5A, 0x70, 0x18, 0xF0, 0x3E, 0xF8, 0x1A, 0xF0, 0x14, 0xFC, 0x05, 0x4B, 0xD3, 0xF8, ++0xA8, 0x31, 0x98, 0x47, 0x16, 0xF0, 0x88, 0xFB, 0xBD, 0xE8, 0x08, 0x40, 0x18, 0xF0, 0x42, 0xB8, 0x70, 0x28, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x4B, 0x4E, 0x4C, 0x4A, 0x4C, 0x49, 0x4D, 0x48, 0x17, 0xF0, 0x6E, 0xFD, ++0x33, 0x68, 0xDB, 0x78, 0x00, 0x2B, 0x40, 0xF0, 0x89, 0x80, 0x62, 0xB6, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, ++0xDF, 0xF8, 0x3C, 0x81, 0xDF, 0xF8, 0x3C, 0x91, 0x45, 0x4D, 0x46, 0x4F, 0x46, 0x4C, 0xDF, 0xF8, 0x38, 0xB1, 0x4F, 0xF0, ++0x01, 0x0A, 0x33, 0x68, 0xDB, 0x78, 0xFB, 0xB9, 0x98, 0xF8, 0x00, 0x30, 0x13, 0xB3, 0x18, 0xF0, 0x71, 0xFE, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0xA0, 0x2B, 0x68, 0x3A, 0x68, 0x01, 0x33, 0x2B, 0x60, ++0xBA, 0xB1, 0x00, 0x2B, 0xE9, 0xD0, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x2B, 0x60, 0x00, 0x2B, 0xE3, 0xD1, 0x00, 0x2A, ++0xE1, 0xD0, 0x62, 0xB6, 0x33, 0x68, 0xDB, 0x78, 0x00, 0x2B, 0xDF, 0xD0, 0xFF, 0xF7, 0x2C, 0xFD, 0x98, 0xF8, 0x00, 0x30, ++0x00, 0x2B, 0xDC, 0xD1, 0x16, 0xF0, 0xF8, 0xFA, 0xD9, 0xE7, 0xD4, 0xF8, 0x7C, 0x32, 0x98, 0x47, 0x33, 0x68, 0xDB, 0x78, ++0x00, 0x2B, 0x37, 0xD1, 0xDB, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x01, 0x2B, 0x17, 0xD0, 0xBF, 0xF3, 0x4F, 0x8F, 0x30, 0xBF, ++0xBF, 0xF3, 0x6F, 0x8F, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0xD4, 0xF8, 0x78, 0x32, 0x98, 0x47, 0x00, 0x28, ++0xF1, 0xD0, 0x33, 0x68, 0xDB, 0x78, 0x23, 0xBB, 0xD4, 0xF8, 0x84, 0x32, 0x98, 0x47, 0x2B, 0x68, 0x00, 0x2B, 0xB0, 0xD0, ++0xC5, 0xE7, 0x1D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xE3, 0xD0, 0x1C, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x17, 0xD0, ++0x01, 0x2B, 0x05, 0xD0, 0x00, 0x2B, 0xDA, 0xD1, 0x18, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xD6, 0xD0, 0x17, 0x4B, 0x5B, 0x78, ++0x00, 0x2B, 0xD2, 0xD0, 0x16, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x53, 0x13, 0x60, 0xCC, 0xE7, 0xFF, 0xF7, 0xEA, 0xFC, ++0xC4, 0xE7, 0xFF, 0xF7, 0xEF, 0xFC, 0xD7, 0xE7, 0xFB, 0xF7, 0x32, 0xFE, 0x00, 0x28, 0xEF, 0xD1, 0x0B, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0xDF, 0xE7, 0x10, 0x20, 0xFF, 0xF7, 0xB1, 0xFC, 0x72, 0xE7, 0x34, 0x36, 0x17, 0x00, 0xDC, 0xD1, 0x15, 0x00, ++0x00, 0xD2, 0x15, 0x00, 0x1C, 0x8D, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x3D, 0x61, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x3C, 0x61, 0x17, 0x00, 0x70, 0x28, 0x17, 0x00, 0x00, 0x60, 0x50, 0x40, ++0x3C, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x72, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x71, 0x4C, 0x72, 0x4A, 0x23, 0x68, 0x72, 0x49, ++0x72, 0x4D, 0x01, 0x33, 0x4F, 0xF4, 0x80, 0x60, 0x23, 0x60, 0x17, 0xF0, 0xF9, 0xFC, 0x4F, 0xF0, 0x00, 0x40, 0x16, 0xF0, ++0x4D, 0xFA, 0xD5, 0xF8, 0xEC, 0x30, 0x98, 0x47, 0x6C, 0x4B, 0x6D, 0x4A, 0x19, 0x68, 0x21, 0xF0, 0x7F, 0x41, 0x19, 0x60, ++0x19, 0x68, 0x41, 0xF0, 0x10, 0x01, 0x19, 0x60, 0x11, 0x69, 0x64, 0x31, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, ++0x66, 0x4E, 0xD5, 0xF8, 0x10, 0x24, 0x33, 0x68, 0x40, 0xF2, 0x11, 0x17, 0x3B, 0x43, 0x33, 0x60, 0x90, 0x47, 0x60, 0x49, ++0x62, 0x4A, 0x0B, 0x68, 0xDF, 0xF8, 0xAC, 0xC1, 0x23, 0xF0, 0x10, 0x03, 0x0B, 0x60, 0x33, 0x68, 0x23, 0xF4, 0x88, 0x73, ++0x23, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x0B, 0x23, 0x10, 0x68, 0x13, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0xDB, 0x06, 0x18, 0xD5, ++0x59, 0x4B, 0x40, 0xF2, 0x01, 0x2C, 0x19, 0x68, 0xC3, 0xF8, 0x00, 0xC0, 0x19, 0x60, 0x33, 0x68, 0xA2, 0xF5, 0x7C, 0x72, ++0x1F, 0x43, 0x37, 0x60, 0x11, 0x68, 0x02, 0x31, 0x13, 0x68, 0x5B, 0x1A, 0x00, 0x2B, 0xFB, 0xDB, 0x4E, 0x4A, 0x13, 0x68, ++0x23, 0xF4, 0x88, 0x73, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x4C, 0x4B, 0x18, 0x60, 0x0A, 0xF0, 0xBD, 0xFF, 0x00, 0x20, ++0x16, 0xF0, 0x8E, 0xF8, 0x00, 0x28, 0x6C, 0xD0, 0x49, 0x4E, 0x09, 0xF0, 0xA1, 0xFB, 0xB3, 0x79, 0x00, 0x2B, 0x4F, 0xD0, ++0x47, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x66, 0xD0, 0x33, 0x78, 0x00, 0x2B, 0x47, 0xD0, 0x44, 0x4B, 0x77, 0x79, ++0x1A, 0x68, 0x96, 0xF9, 0x07, 0x30, 0x96, 0xF9, 0x04, 0xE0, 0xDF, 0xF8, 0x20, 0xC1, 0x41, 0x48, 0xDC, 0xF8, 0x00, 0x10, ++0xD5, 0xF8, 0xE0, 0x81, 0x37, 0x4D, 0x02, 0xF0, 0x0F, 0x02, 0x17, 0x44, 0x7F, 0xB2, 0x3B, 0x44, 0x73, 0x45, 0xA8, 0xBF, ++0x73, 0x46, 0x5F, 0xFA, 0x83, 0xFE, 0x21, 0xF0, 0xFF, 0x01, 0x41, 0xEA, 0x0E, 0x01, 0xCC, 0xF8, 0x00, 0x10, 0x02, 0x68, ++0x22, 0xF0, 0xFF, 0x02, 0x42, 0xEA, 0x0E, 0x02, 0x02, 0x60, 0xDC, 0xF8, 0x00, 0x10, 0xDA, 0x1E, 0x5F, 0xFA, 0x82, 0xFE, ++0x21, 0xF4, 0x7F, 0x21, 0x41, 0xEA, 0x0E, 0x31, 0xCC, 0xF8, 0x00, 0x10, 0x02, 0x68, 0xB6, 0xF8, 0x08, 0xC0, 0x22, 0xF4, ++0x7F, 0x22, 0x42, 0xEA, 0x0E, 0x32, 0x02, 0x60, 0x2A, 0x69, 0x2A, 0x48, 0x5D, 0xB2, 0x4E, 0xF6, 0x60, 0x21, 0x01, 0xFB, ++0x0C, 0x21, 0xF5, 0x71, 0xC0, 0x47, 0x00, 0x23, 0x26, 0x48, 0xB3, 0x71, 0x29, 0x46, 0x3A, 0x46, 0x17, 0xF0, 0xFC, 0xFB, ++0x24, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x17, 0xF0, 0x47, 0xFC, 0x08, 0xF0, 0x85, 0xFE, 0x18, 0xB1, 0x4F, 0xF4, 0x80, 0x10, ++0x16, 0xF0, 0x74, 0xF9, 0x23, 0x68, 0x33, 0xB1, 0x0D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF0, 0x80, 0x60, 0x16, 0xF0, 0x89, 0xF9, 0x8D, 0xE7, 0x17, 0x4B, 0x1B, 0x68, ++0x00, 0x22, 0x1A, 0x60, 0xF8, 0xF7, 0x8C, 0xFA, 0x33, 0x78, 0x00, 0x2B, 0xDA, 0xD0, 0xB3, 0x79, 0x00, 0x2B, 0x8F, 0xD1, ++0xD6, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x30, 0x8E, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x04, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x18, 0x00, 0x34, 0x40, 0x10, 0x05, 0x32, 0x40, ++0x00, 0x10, 0x34, 0x40, 0x80, 0x35, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x01, 0x32, 0x40, 0xD4, 0xB3, 0x33, 0x40, ++0x8C, 0x35, 0x17, 0x00, 0x30, 0x8D, 0x15, 0x00, 0x40, 0x8D, 0x15, 0x00, 0x00, 0x38, 0x18, 0x00, 0x0C, 0x05, 0x32, 0x40, ++0xAC, 0xB3, 0x33, 0x40, 0x22, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x20, 0x4B, ++0xD3, 0xF8, 0x04, 0x31, 0x1A, 0x03, 0x10, 0xB5, 0x16, 0xD4, 0x00, 0x22, 0x93, 0x00, 0x03, 0xF1, 0x60, 0x43, 0x03, 0xF5, ++0x61, 0x43, 0x01, 0x2A, 0xD3, 0xF8, 0x00, 0x01, 0x1B, 0x68, 0x00, 0xEA, 0x03, 0x00, 0x04, 0xD0, 0x30, 0xB9, 0x02, 0x2A, ++0x05, 0xD0, 0x01, 0x32, 0xEE, 0xE7, 0x30, 0xF4, 0x00, 0x23, 0xFA, 0xD0, 0x01, 0x20, 0x10, 0xBD, 0x12, 0x4B, 0x1C, 0x68, ++0x41, 0xF6, 0x33, 0x70, 0x20, 0x40, 0xF7, 0xD1, 0x63, 0x00, 0x0F, 0xD4, 0x00, 0x2C, 0x07, 0xDA, 0x0E, 0x4B, 0xD3, 0xF8, ++0x68, 0x34, 0x98, 0x47, 0x0D, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x08, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0xC3, 0xF8, ++0x84, 0x21, 0xD0, 0xE7, 0x07, 0x4B, 0xD3, 0xF8, 0x78, 0x34, 0x98, 0x47, 0x06, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, ++0xE6, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, 0x1C, 0x41, 0x04, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x38, 0xB5, 0x3F, 0x4C, 0x3F, 0x4D, 0x23, 0x68, 0x3F, 0x49, 0x03, 0xF0, 0x0F, 0x03, 0x02, 0x20, ++0x2B, 0x70, 0x17, 0xF0, 0x9F, 0xFB, 0x23, 0x68, 0x18, 0x07, 0x40, 0xD0, 0x3B, 0x49, 0x3C, 0x4A, 0x0B, 0x68, 0x00, 0x20, ++0x23, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x20, 0x60, 0x13, 0x68, 0x59, 0x07, 0xFC, 0xD5, 0x38, 0x4B, 0x35, 0x49, 0x38, 0x4A, ++0x04, 0x20, 0x18, 0x60, 0x0B, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x63, 0x13, 0x60, ++0x33, 0x4B, 0x1B, 0x78, 0x01, 0x22, 0x6A, 0x70, 0x9B, 0xB1, 0x32, 0x49, 0x32, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0x00, 0x13, ++0x0B, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x2F, 0x4B, 0x19, 0x68, 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, ++0x01, 0x20, 0x41, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x10, 0x60, 0x20, 0x4B, 0x2A, 0x4A, 0x2B, 0x49, 0x20, 0x20, 0x18, 0x60, ++0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x26, 0xD0, 0x01, 0x2B, 0x06, 0xD0, ++0x38, 0xBD, 0x1E, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x63, 0x13, 0x60, 0xD0, 0xE7, 0x22, 0x4A, 0x13, 0x68, 0x5B, 0x03, ++0xFC, 0xD5, 0x21, 0x4A, 0x11, 0x69, 0x1C, 0x31, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x1E, 0x49, 0x1F, 0x4A, ++0x0B, 0x68, 0x43, 0xF4, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x6D, 0x43, 0xF4, 0x00, 0x43, 0x13, 0x65, 0xD3, 0x6D, 0x23, 0xF0, ++0x03, 0x03, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xF0, 0x01, 0x03, 0xD3, 0x65, 0x38, 0xBD, 0x17, 0x4B, 0x1A, 0x68, 0x42, 0xF0, ++0x01, 0x02, 0x1A, 0x60, 0x1B, 0x68, 0x5A, 0x07, 0xD2, 0xD5, 0x14, 0x4B, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x38, 0xBD, ++0x38, 0x00, 0x32, 0x40, 0x70, 0x28, 0x17, 0x00, 0x50, 0x8D, 0x15, 0x00, 0x74, 0x80, 0x32, 0x40, 0x6C, 0x80, 0x32, 0x40, ++0x70, 0x80, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, 0x3D, 0x61, 0x17, 0x00, 0x58, 0x40, 0x34, 0x40, 0x40, 0x42, 0x04, 0x40, ++0x18, 0x00, 0x58, 0x40, 0x10, 0x00, 0x58, 0x40, 0x78, 0x36, 0x17, 0x00, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x14, 0x00, 0x24, 0x40, 0x00, 0x60, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x00, 0x41, 0x04, 0x40, 0x00, 0x28, 0x00, 0xF0, ++0xE7, 0x80, 0x2D, 0xE9, 0xF8, 0x4F, 0x90, 0xF8, 0x64, 0x30, 0x04, 0x46, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x8F, 0x83, 0x4B, ++0x83, 0x4A, 0x84, 0x4F, 0xDF, 0xF8, 0x2C, 0x92, 0xDF, 0xF8, 0x64, 0x82, 0x82, 0x4E, 0x83, 0x48, 0x0D, 0x46, 0x83, 0x49, ++0x4F, 0xF0, 0x02, 0x0B, 0xD1, 0xF8, 0x70, 0xC4, 0xC3, 0xF8, 0x80, 0xB1, 0x92, 0x68, 0x80, 0x49, 0xC2, 0xF8, 0x44, 0xC0, ++0x01, 0x22, 0xC3, 0xF8, 0x00, 0xB0, 0x3A, 0x70, 0xD9, 0xF8, 0x10, 0x20, 0x0B, 0x68, 0x7A, 0x60, 0x23, 0xF0, 0x02, 0x03, ++0x0B, 0x60, 0xD8, 0xF8, 0x00, 0x10, 0xB6, 0xF8, 0xB2, 0xC0, 0x8B, 0x8F, 0x01, 0x68, 0x63, 0x44, 0xB3, 0xEB, 0x41, 0x1F, ++0x4F, 0xEA, 0x41, 0x1A, 0xD1, 0xD2, 0x74, 0x49, 0x58, 0x46, 0x17, 0xF0, 0xC9, 0xFA, 0xD9, 0xF8, 0x10, 0x20, 0xFB, 0x68, ++0x9B, 0x1A, 0x00, 0x2B, 0x80, 0xF2, 0xB6, 0x80, 0xB4, 0xF8, 0x68, 0x20, 0x6E, 0x4B, 0xA8, 0x68, 0x41, 0xF2, 0x13, 0x31, ++0x01, 0x2A, 0x5C, 0x5C, 0x40, 0xF2, 0x9F, 0x80, 0x01, 0x3A, 0x00, 0xFB, 0x02, 0xAA, 0x41, 0xF2, 0x13, 0x31, 0x52, 0x46, ++0x5B, 0x5C, 0x68, 0x49, 0x02, 0x20, 0x17, 0xF0, 0xAD, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB6, 0xF8, 0xB2, 0x00, 0x9A, 0x8F, ++0x60, 0x49, 0x64, 0x4B, 0xDF, 0xF8, 0xA8, 0xC1, 0x1C, 0x69, 0x0B, 0x68, 0x02, 0x44, 0xAA, 0xEB, 0x02, 0x02, 0x22, 0xF0, ++0x03, 0x05, 0x03, 0xF0, 0x03, 0x03, 0x2B, 0x43, 0x5E, 0x4D, 0x0B, 0x60, 0x2B, 0x68, 0xBA, 0x60, 0x43, 0xF0, 0x01, 0x03, ++0x2B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0xDC, 0xF8, 0x00, 0x10, 0xC3, 0xF3, 0x09, 0x03, 0x21, 0xF4, 0x7F, 0x71, 0x43, 0xF0, ++0x01, 0x03, 0x21, 0xF0, 0x03, 0x01, 0x0B, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0x2B, 0x68, 0x22, 0x44, 0x5B, 0x07, 0xFA, 0x60, ++0x03, 0xD5, 0x52, 0x4B, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x51, 0x49, 0x51, 0x4A, 0x0B, 0x68, 0x43, 0xF0, 0x08, 0x03, ++0x0B, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4E, 0x4C, 0x45, 0x49, 0x23, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x23, 0x60, ++0x01, 0x23, 0x13, 0x60, 0x0B, 0x68, 0x45, 0x4A, 0x43, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x11, 0x69, 0x01, 0xF5, 0x96, 0x71, ++0x13, 0x69, 0x5B, 0x1A, 0x00, 0x2B, 0xFB, 0xDB, 0x45, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x7F, 0xF4, 0x5D, 0xAF, ++0x43, 0x49, 0x44, 0x4C, 0x4B, 0x6A, 0x24, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xDF, 0x03, 0x4B, 0x62, 0x4B, 0x6A, ++0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0x5F, 0x43, 0x4B, 0x62, 0xB4, 0xB1, 0x3D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x3F, 0xDB, 0xE3, 0x68, 0x62, 0x68, 0x3A, 0x49, 0x02, 0x20, 0x17, 0xF0, 0x3C, 0xFA, 0xB6, 0xF8, 0xB2, 0x10, ++0xE2, 0x68, 0x2D, 0x4B, 0x52, 0x1A, 0x4F, 0xF4, 0x80, 0x20, 0x04, 0x21, 0x98, 0x60, 0x1A, 0x63, 0x99, 0x60, 0x34, 0x49, ++0x2F, 0x4A, 0x0B, 0x68, 0x43, 0xF4, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x6D, 0x43, 0xF4, 0x00, 0x43, 0x13, 0x65, 0xD3, 0x6D, ++0x23, 0xF0, 0x03, 0x03, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xF0, 0x01, 0x03, 0xD3, 0x65, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x53, ++0x13, 0x60, 0x1E, 0xE7, 0x70, 0x47, 0x41, 0xF2, 0x14, 0x32, 0x9C, 0x5C, 0x01, 0x2C, 0x7F, 0xF6, 0x5E, 0xAF, 0x5C, 0x5C, ++0xDC, 0xB1, 0x5A, 0x5C, 0x01, 0x3A, 0x00, 0xFB, 0x02, 0xAA, 0x56, 0xE7, 0x14, 0x4A, 0x22, 0x49, 0x41, 0xF2, 0x13, 0x33, ++0x58, 0x46, 0xD3, 0x5C, 0x52, 0x46, 0x17, 0xF0, 0x03, 0xFA, 0x54, 0xE7, 0x12, 0x69, 0xE3, 0x68, 0x9A, 0x1A, 0x10, 0x1A, ++0x00, 0x28, 0xBA, 0xDA, 0x1B, 0x49, 0x1C, 0x48, 0x40, 0xF2, 0x4F, 0x22, 0x17, 0xF0, 0x20, 0xFC, 0xB2, 0xE7, 0x9A, 0x5C, ++0x3A, 0xE7, 0x00, 0xBF, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0xED, 0x00, 0xE0, 0x3C, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0x40, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x84, 0x00, 0x32, 0x40, 0x54, 0x8D, 0x15, 0x00, 0x00, 0x40, 0x1E, 0x00, ++0x70, 0x8D, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x00, 0x41, 0x04, 0x40, 0x10, 0x00, 0x58, 0x40, ++0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x78, 0x36, 0x17, 0x00, 0x00, 0x60, 0x50, 0x40, 0xD0, 0x9C, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0xC8, 0x8D, 0x15, 0x00, 0x14, 0x00, 0x24, 0x40, 0x5C, 0x8D, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x80, 0x8D, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x70, 0xB5, 0x45, 0x4C, 0x21, 0x68, 0x0B, 0x78, 0x73, 0xB9, 0x44, 0x4B, ++0x44, 0x4D, 0x9B, 0x68, 0x01, 0x22, 0x2A, 0x70, 0x00, 0x2B, 0x3E, 0xD1, 0x0A, 0x78, 0x42, 0x49, 0x01, 0x23, 0x02, 0x20, ++0x17, 0xF0, 0xAC, 0xF9, 0x01, 0x23, 0x2B, 0x70, 0x3F, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x40, 0xD0, 0x02, 0x2B, ++0x28, 0xD0, 0x11, 0xF0, 0x8F, 0xFD, 0x28, 0xB3, 0x3B, 0x4B, 0xD3, 0xF8, 0xF8, 0x31, 0x0B, 0xBB, 0x3A, 0x4B, 0x3B, 0x4D, ++0x1B, 0x68, 0x95, 0xF8, 0x24, 0x20, 0xC3, 0xF3, 0x40, 0x63, 0x13, 0x43, 0x18, 0xD0, 0x6B, 0x7F, 0xB3, 0xB9, 0x37, 0x4E, ++0xD6, 0xF8, 0xF4, 0x30, 0x98, 0x47, 0x88, 0xB1, 0xF8, 0xF7, 0x7E, 0xFB, 0x34, 0x4A, 0xC0, 0xB2, 0x10, 0x70, 0x00, 0x28, ++0x35, 0xD0, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD8, 0xD6, 0xF8, 0xB4, 0x34, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, ++0x02, 0x2B, 0x22, 0xD0, 0x70, 0xBD, 0x93, 0xF8, 0x64, 0x20, 0x42, 0xB9, 0x1B, 0x68, 0x00, 0x2B, 0xC0, 0xD0, 0x93, 0xF8, ++0x62, 0x20, 0x00, 0x2A, 0xF5, 0xD0, 0x02, 0x2A, 0xF6, 0xD1, 0x0A, 0x78, 0x1F, 0x49, 0x00, 0x23, 0x02, 0x20, 0x17, 0xF0, ++0x67, 0xF9, 0x00, 0x23, 0x2B, 0x70, 0x70, 0xBD, 0x23, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x15, 0xD0, 0xFB, 0xF7, 0x5A, 0xFA, ++0x00, 0x28, 0xE1, 0xD0, 0x1E, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xB4, 0xD0, 0x70, 0xBD, 0x28, 0x6A, 0xD6, 0xF8, 0xB8, 0x34, ++0xD0, 0xF8, 0xE4, 0x10, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x19, 0x49, 0x02, 0x20, 0x17, 0xF0, 0x4B, 0xF9, 0xC4, 0xE7, ++0xF8, 0xF7, 0x3C, 0xFB, 0x13, 0x4B, 0x18, 0x70, 0xFB, 0xF7, 0x40, 0xFA, 0x18, 0xB1, 0x10, 0x4B, 0xD3, 0xF8, 0xB4, 0x34, ++0x98, 0x47, 0x12, 0x4A, 0x13, 0x68, 0x5B, 0x03, 0xFC, 0xD5, 0x11, 0x4A, 0x11, 0x69, 0x1C, 0x31, 0x13, 0x69, 0xCB, 0x1A, ++0x00, 0x2B, 0xFB, 0xDA, 0x70, 0xBD, 0x00, 0xBF, 0x74, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x3C, 0x61, 0x17, 0x00, ++0xD8, 0x8D, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x3D, 0x61, 0x17, 0x00, 0x9C, 0x4E, 0x17, 0x00, 0xD4, 0x8D, 0x15, 0x00, 0x20, 0x10, 0x04, 0x40, ++0x00, 0x10, 0x50, 0x40, 0x38, 0xB5, 0x43, 0x4D, 0x6B, 0x78, 0x03, 0xB9, 0x38, 0xBD, 0x42, 0x48, 0x42, 0x49, 0x03, 0x68, ++0x42, 0x4A, 0x23, 0xF0, 0x10, 0x03, 0x03, 0x60, 0x4B, 0x6F, 0x43, 0xF0, 0x10, 0x03, 0x4B, 0x67, 0x13, 0x68, 0x23, 0xF0, ++0x00, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x3C, 0x4C, 0x3C, 0x49, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x43, ++0x23, 0x60, 0x02, 0x20, 0x17, 0xF0, 0xF6, 0xF8, 0x00, 0x23, 0x22, 0x46, 0x6B, 0x70, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD5, ++0x36, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x3C, 0xDB, 0x31, 0x4B, 0x34, 0x4A, 0x19, 0x68, 0x21, 0xF0, ++0x80, 0x41, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x2F, 0x4B, ++0x2F, 0x48, 0x19, 0x68, 0x2F, 0x4C, 0x41, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, 0x01, 0x25, 0x21, 0xF0, 0x02, 0x01, ++0x19, 0x60, 0x15, 0x60, 0x03, 0x68, 0x43, 0xF4, 0x00, 0x13, 0x03, 0x60, 0x23, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x2E, 0xD0, ++0x01, 0x2B, 0x26, 0xD0, 0x26, 0x4B, 0x1B, 0x78, 0x53, 0xB1, 0x1D, 0x4A, 0x25, 0x49, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x73, ++0x13, 0x60, 0x02, 0x20, 0xBD, 0xE8, 0x38, 0x40, 0x17, 0xF0, 0xB8, 0xB8, 0x16, 0x4A, 0x20, 0x49, 0x53, 0x6F, 0x23, 0xF0, ++0x10, 0x03, 0x53, 0x67, 0x02, 0x20, 0xBD, 0xE8, 0x38, 0x40, 0x17, 0xF0, 0xAD, 0xB8, 0x1C, 0x4B, 0x2A, 0x78, 0x1B, 0x68, ++0x03, 0xF0, 0x0F, 0x03, 0x9A, 0x42, 0xBB, 0xD0, 0x19, 0x49, 0x1A, 0x48, 0x4F, 0xF4, 0x3A, 0x72, 0x17, 0xF0, 0xCA, 0xFA, ++0xB4, 0xE7, 0x18, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x43, 0x13, 0x60, 0xD2, 0xE7, 0x16, 0x4A, 0x13, 0x68, 0x23, 0xF0, ++0x01, 0x03, 0x13, 0x60, 0x0D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xCC, 0xD1, 0xD6, 0xE7, 0x00, 0xBF, 0x70, 0x28, 0x17, 0x00, ++0x10, 0x00, 0x58, 0x40, 0x00, 0x00, 0x50, 0x40, 0xE0, 0x50, 0x34, 0x40, 0x48, 0x80, 0x32, 0x40, 0xEC, 0x8D, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x58, 0x40, 0x34, 0x40, 0x78, 0x36, 0x17, 0x00, ++0x4C, 0x36, 0x17, 0x00, 0x28, 0x8E, 0x15, 0x00, 0x38, 0x00, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x8D, 0x15, 0x00, ++0x14, 0x00, 0x24, 0x40, 0x84, 0x40, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x47, 0x1F, 0x48, 0x20, 0x4D, 0x15, 0xF0, 0x36, 0xFE, ++0x1F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0x1D, 0x4E, 0x28, 0x68, 0xDF, 0xF8, 0x7C, 0x90, ++0xDF, 0xF8, 0x60, 0x80, 0xD9, 0xF8, 0x00, 0x30, 0x1A, 0x89, 0x54, 0x24, 0x02, 0xFB, 0x04, 0x42, 0x00, 0x21, 0xF2, 0xF7, ++0x91, 0xFD, 0x4F, 0xF0, 0x00, 0x0A, 0x58, 0x27, 0x29, 0x68, 0x33, 0x68, 0x1F, 0xFA, 0x8A, 0xF2, 0x04, 0xFB, 0x02, 0x11, ++0x07, 0xFB, 0x02, 0x33, 0xCB, 0x64, 0x40, 0x46, 0x15, 0xF0, 0x16, 0xFE, 0xD9, 0xF8, 0x00, 0x30, 0x0A, 0xF1, 0x01, 0x0A, ++0x1A, 0x89, 0x1F, 0xFA, 0x8A, 0xF3, 0x9A, 0x42, 0xEA, 0xD2, 0xBD, 0xE8, 0xF0, 0x87, 0x28, 0x68, 0x08, 0x4E, 0x10, 0xB1, ++0x33, 0x68, 0x00, 0x2B, 0xD2, 0xD1, 0x07, 0x48, 0x07, 0x49, 0x5B, 0x22, 0x17, 0xF0, 0x54, 0xFA, 0x28, 0x68, 0xCB, 0xE7, ++0x20, 0x58, 0x17, 0x00, 0x40, 0x61, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x14, 0x63, 0x18, 0x00, 0x40, 0x8E, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0x0D, 0x49, 0x00, 0xEB, 0xC0, 0x03, 0x10, 0xB4, 0x9C, 0x00, 0x00, 0x22, ++0x01, 0xEB, 0x83, 0x03, 0x16, 0x30, 0x0A, 0x51, 0x01, 0xEB, 0xC0, 0x00, 0x4F, 0xF4, 0x55, 0x64, 0x4F, 0xF0, 0xFF, 0x31, ++0xC3, 0xE9, 0x02, 0x41, 0xC0, 0xE9, 0x01, 0x22, 0x5D, 0xF8, 0x04, 0x4B, 0x5A, 0x60, 0x83, 0xF8, 0x20, 0x20, 0x5A, 0x61, ++0x19, 0x61, 0x70, 0x47, 0x44, 0x61, 0x17, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x80, 0x6C, 0x18, 0xB1, 0xF9, 0xF7, 0xCE, 0xFE, ++0x00, 0x23, 0xA3, 0x64, 0x10, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, 0x38, 0x4C, 0xDF, 0xF8, 0xF0, 0x80, 0x38, 0x4F, ++0x38, 0x4D, 0x04, 0xF5, 0x20, 0x76, 0xC4, 0xF8, 0x00, 0x80, 0xF3, 0xF7, 0x0F, 0xFE, 0x80, 0x03, 0x60, 0x60, 0xF3, 0xF7, ++0x0B, 0xFE, 0x01, 0x23, 0x01, 0x30, 0x03, 0xFA, 0x00, 0xF0, 0x01, 0x38, 0x00, 0x23, 0xC4, 0xE9, 0x02, 0x03, 0xC4, 0xE9, ++0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x27, 0x61, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, ++0x63, 0x62, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0xA3, 0x62, 0x2B, 0x68, 0x2A, 0x68, ++0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0xE3, 0x62, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, ++0x13, 0x43, 0x4F, 0xF4, 0x08, 0x51, 0x4F, 0xF4, 0x7C, 0x12, 0xA2, 0x63, 0xC4, 0xE9, 0x0C, 0x31, 0x40, 0x34, 0xB4, 0x42, ++0xC5, 0xD1, 0x1B, 0x4C, 0x1B, 0x4F, 0x18, 0x4E, 0xDF, 0xF8, 0x60, 0x80, 0x04, 0xF5, 0x80, 0x75, 0x27, 0x60, 0xF3, 0xF7, ++0xCF, 0xFD, 0x80, 0x03, 0x60, 0x60, 0xF3, 0xF7, 0xCB, 0xFD, 0x01, 0x23, 0x01, 0x30, 0x03, 0xFA, 0x00, 0xF0, 0x01, 0x38, ++0x00, 0x23, 0xC4, 0xE9, 0x02, 0x03, 0xC4, 0xE9, 0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x26, 0x61, 0xD8, 0xF8, 0x00, 0x20, ++0xD8, 0xF8, 0x00, 0x10, 0xA3, 0x62, 0x12, 0x02, 0xC9, 0xB2, 0x92, 0xB2, 0x0A, 0x43, 0x4F, 0xF4, 0x7C, 0x11, 0x62, 0x62, ++0xC4, 0xE9, 0x0B, 0x33, 0xC4, 0xE9, 0x0D, 0x31, 0x40, 0x34, 0xAC, 0x42, 0xD8, 0xD1, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, ++0x04, 0x39, 0x18, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0xA0, 0x00, 0x32, 0x40, 0x04, 0x38, 0x18, 0x00, 0x1E, 0xAB, 0xDC, 0xBA, ++0xF0, 0xB5, 0x16, 0x4C, 0x24, 0x68, 0x24, 0x78, 0x1D, 0x46, 0xE3, 0x07, 0x87, 0xB0, 0x16, 0x46, 0x06, 0xD5, 0x50, 0x19, ++0x00, 0x21, 0x08, 0x22, 0xF2, 0xF7, 0xA8, 0xFC, 0x07, 0xB0, 0xF0, 0xBD, 0xC3, 0x7E, 0x00, 0x93, 0x02, 0xAC, 0x07, 0x46, ++0x07, 0xF1, 0x12, 0x03, 0x20, 0x46, 0x07, 0xF1, 0x0C, 0x02, 0x1A, 0xF0, 0xE7, 0xFF, 0x2A, 0x46, 0x31, 0x46, 0x20, 0x46, ++0x1B, 0xF0, 0x08, 0xF8, 0x20, 0x46, 0x1B, 0xF0, 0xA3, 0xF8, 0x35, 0x44, 0x21, 0x46, 0x04, 0xAA, 0x60, 0x1A, 0x14, 0xF8, ++0x01, 0x3B, 0x43, 0x55, 0x94, 0x42, 0xF9, 0xD1, 0x07, 0xB0, 0xF0, 0xBD, 0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x83, 0x6C, 0x90, 0xF8, 0x42, 0xA0, 0x90, 0xF8, 0x33, 0x40, 0x90, 0xF8, 0x35, 0x20, 0x87, 0x88, 0x90, 0xF8, 0x32, 0x80, ++0xD3, 0xF8, 0x24, 0xC0, 0xC6, 0x6C, 0x93, 0xF8, 0x20, 0xE0, 0xA3, 0xEB, 0x0A, 0x05, 0xA8, 0x35, 0x22, 0x44, 0x01, 0x3F, ++0xAA, 0xEB, 0x04, 0x04, 0x3A, 0x44, 0x08, 0xEB, 0x05, 0x09, 0x2C, 0xF0, 0x02, 0x07, 0x04, 0xEB, 0x09, 0x0B, 0x5F, 0x62, ++0x54, 0x19, 0x03, 0xF1, 0x0C, 0x0A, 0xB8, 0xF1, 0x00, 0x0F, 0x03, 0xD0, 0x09, 0xF1, 0xFF, 0x32, 0xC6, 0xE9, 0x09, 0x52, ++0xF2, 0x6C, 0xC3, 0xF8, 0x14, 0xB0, 0x00, 0x25, 0x42, 0xF4, 0x80, 0x72, 0x1C, 0xF0, 0x01, 0x0F, 0x9C, 0x61, 0x1D, 0x61, ++0xC6, 0xF8, 0x20, 0xA0, 0xDD, 0x61, 0xF2, 0x64, 0x16, 0xD1, 0x40, 0x6A, 0x00, 0xF4, 0x60, 0x14, 0xB4, 0xF5, 0x60, 0x1F, ++0x01, 0xD0, 0x80, 0x02, 0x0E, 0xD4, 0x09, 0x48, 0x71, 0x44, 0x01, 0xEB, 0xC1, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x47, 0xF0, ++0x01, 0x07, 0x91, 0xF8, 0x20, 0x00, 0x5F, 0x62, 0x01, 0x30, 0x81, 0xF8, 0x20, 0x00, 0xF2, 0x64, 0x00, 0x22, 0x1A, 0x61, ++0xBD, 0xE8, 0xF0, 0x8F, 0x44, 0x61, 0x17, 0x00, 0x0A, 0x88, 0x03, 0x7F, 0x0A, 0x49, 0x12, 0xF4, 0x00, 0x5F, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x03, 0x12, 0x4F, 0xF4, 0xA4, 0x60, 0x92, 0xF8, 0xDA, 0x20, 0x00, 0xFB, 0x03, 0x13, 0x14, 0xBF, ++0x42, 0xF0, 0x02, 0x02, 0x02, 0xF0, 0xFD, 0x02, 0x83, 0xF8, 0xDA, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x43, 0x6A, 0x2D, 0xE9, 0xF0, 0x47, 0x91, 0x46, 0x9A, 0x02, 0xD0, 0xF8, 0x48, 0x80, 0x06, 0x46, 0x0F, 0x46, 0x29, 0xD5, ++0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x24, 0xD0, 0x50, 0x4C, 0x88, 0xF8, 0x20, 0x90, 0xD4, 0xF8, 0x80, 0x33, ++0x39, 0x46, 0x30, 0x46, 0x98, 0x47, 0x31, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x99, 0x42, 0x68, 0xD0, 0x4A, 0x4B, 0xB1, 0x6C, ++0x93, 0xF8, 0x05, 0x31, 0x00, 0x2B, 0x59, 0xD1, 0xB3, 0x68, 0x00, 0x2B, 0x49, 0xDB, 0x4B, 0x6A, 0x46, 0x4A, 0xCA, 0x60, ++0x23, 0xF0, 0x10, 0x03, 0x4B, 0x62, 0x30, 0x46, 0xD4, 0xF8, 0x04, 0x34, 0x8E, 0x60, 0x3A, 0x46, 0x98, 0x47, 0x00, 0x20, ++0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0x2C, 0xA0, 0x08, 0xF1, 0x24, 0x04, 0x0A, 0xF1, 0x40, 0x00, 0x53, 0x46, 0x53, 0xF8, ++0x04, 0x5B, 0x44, 0xF8, 0x04, 0x5F, 0x83, 0x42, 0xF9, 0xD1, 0xF3, 0x8B, 0x9D, 0x04, 0xCA, 0xD5, 0x38, 0x4B, 0x39, 0x49, ++0x1A, 0x68, 0x73, 0x7F, 0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, ++0x4C, 0x41, 0x38, 0xDB, 0x41, 0x46, 0xDA, 0xF8, 0x14, 0x20, 0xD4, 0xF8, 0x9C, 0x30, 0xC8, 0xF8, 0x40, 0x20, 0xDA, 0xF8, ++0x24, 0x20, 0xC8, 0xF8, 0x50, 0x20, 0xC3, 0xF3, 0xC2, 0x22, 0x05, 0x2A, 0xC8, 0xF8, 0x3C, 0x30, 0x31, 0xD0, 0xDA, 0xF8, ++0x3C, 0x30, 0x5C, 0x07, 0x5E, 0xBF, 0xD8, 0xF8, 0x2C, 0x30, 0x23, 0xF4, 0xC0, 0x73, 0xC8, 0xF8, 0x2C, 0x30, 0x88, 0x46, ++0x9F, 0xE7, 0x32, 0x8B, 0x33, 0x65, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0xAF, 0xD1, 0x8B, 0x6B, 0x23, 0xF4, 0x7F, 0x43, ++0x43, 0xF4, 0x60, 0x63, 0x8B, 0x63, 0xA8, 0xE7, 0xF2, 0x8B, 0x10, 0x07, 0xA5, 0xD4, 0xB2, 0x68, 0x52, 0x00, 0x58, 0xBF, ++0x81, 0xF8, 0x39, 0x30, 0x9F, 0xE7, 0xF3, 0x6C, 0x19, 0x48, 0xDA, 0x6A, 0x16, 0xF0, 0xFA, 0xFD, 0x90, 0xE7, 0x00, 0x2C, ++0xC4, 0xD1, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0x17, 0xF0, 0x6B, 0xF8, 0xB1, 0x6C, 0xBD, 0xE7, 0x03, 0xF4, ++0xC0, 0x63, 0xD8, 0xF8, 0x4C, 0x20, 0x94, 0xF8, 0xA1, 0x00, 0xB3, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x34, ++0x4F, 0xF4, 0x00, 0x34, 0x22, 0xF4, 0x40, 0x33, 0x23, 0x43, 0x20, 0xB1, 0x43, 0xF4, 0x80, 0x23, 0xC8, 0xF8, 0x4C, 0x30, ++0xB7, 0xE7, 0x23, 0xF4, 0x80, 0x23, 0xC8, 0xF8, 0x4C, 0x30, 0xB2, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xDE, 0xFA, 0xFE, 0xCA, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x78, 0x8E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x43, 0x6A, 0x85, 0x6C, 0x13, 0xF4, 0x00, 0x18, 0x83, 0xB0, 0x04, 0x46, ++0x05, 0xF1, 0x28, 0x07, 0x08, 0xD0, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x00, 0xF0, 0x93, 0x80, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0xC3, 0x8B, 0xC6, 0x6C, 0x1A, 0x07, 0x38, 0xD5, 0xDF, 0xF8, 0x58, 0x92, 0xD9, 0xF8, 0x00, 0x20, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xCF, 0x80, 0x71, 0x6A, 0x09, 0xB9, 0x32, 0x6A, 0x91, 0x68, 0x18, 0x06, ++0x09, 0xD5, 0x94, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xDD, 0x80, 0x94, 0xF8, 0x35, 0x30, 0x00, 0x2B, 0x40, 0xF0, ++0xDF, 0x80, 0xF3, 0x6C, 0x23, 0xF4, 0xF0, 0x03, 0xF3, 0x64, 0x0B, 0x79, 0xB7, 0x63, 0x13, 0xF0, 0x01, 0x0F, 0x08, 0xBF, ++0x4F, 0xF4, 0x00, 0x78, 0x00, 0x23, 0xC6, 0xF8, 0x48, 0x80, 0x33, 0x65, 0xEB, 0x6A, 0x2A, 0x6E, 0x72, 0x63, 0x43, 0xF0, ++0x02, 0x03, 0xEB, 0x62, 0x20, 0x46, 0x06, 0xF0, 0xBB, 0xF8, 0xA2, 0x6C, 0x53, 0x6A, 0x43, 0xF0, 0x10, 0x03, 0x53, 0x62, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x74, 0x4B, 0xD3, 0xF8, 0x28, 0x34, 0x98, 0x47, 0xEB, 0x6D, 0xB3, 0x64, 0x22, 0x7F, ++0x71, 0x49, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x12, 0x92, 0xF8, 0x62, 0x20, 0x5A, 0xBB, 0x6E, 0x49, 0x62, 0x7F, ++0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x52, 0x68, 0x91, 0x06, 0x22, 0xD5, 0xE2, 0x8B, 0x12, 0xF4, 0x00, 0x5F, ++0xE2, 0x6A, 0xD2, 0x6B, 0x14, 0xBF, 0xC2, 0xF3, 0x00, 0x12, 0xC2, 0xF3, 0xC0, 0x02, 0xBA, 0xB9, 0x70, 0x6A, 0x02, 0x88, ++0x91, 0xB2, 0x12, 0x04, 0x12, 0xD5, 0xC1, 0xF3, 0x0E, 0x01, 0x01, 0x80, 0x94, 0xF8, 0x33, 0x10, 0x94, 0xF8, 0x32, 0x20, ++0x04, 0x39, 0x04, 0x3A, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x32, 0x20, 0xD6, 0xE9, 0x0A, 0x21, 0x04, 0x39, 0x04, 0x3A, ++0xC6, 0xE9, 0x0A, 0x21, 0xDF, 0xF8, 0x70, 0x81, 0xB7, 0x63, 0xD8, 0xF8, 0x00, 0x20, 0xE7, 0x6C, 0xB2, 0xF9, 0x00, 0x20, ++0x00, 0x2A, 0x4F, 0xDB, 0x7A, 0x6A, 0x0A, 0xB9, 0x3A, 0x6A, 0x92, 0x68, 0x23, 0xF4, 0xC0, 0x63, 0xB3, 0x64, 0x12, 0x79, ++0xD2, 0x07, 0x5C, 0xBF, 0x43, 0xF4, 0x00, 0x73, 0xB3, 0x64, 0x9B, 0xE7, 0x83, 0x6A, 0x46, 0x6C, 0xC3, 0xF3, 0xC2, 0x22, ++0x05, 0x2A, 0x37, 0x63, 0x15, 0xD1, 0x03, 0xF4, 0xC0, 0x63, 0xEA, 0x6C, 0x90, 0xF8, 0x36, 0x10, 0xB3, 0xF5, 0x80, 0x6F, ++0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x33, 0x4F, 0xF4, 0x00, 0x33, 0x22, 0xF4, 0x40, 0x32, 0x1A, 0x43, 0x89, 0x06, 0x4C, 0xBF, ++0x42, 0xF4, 0x80, 0x22, 0x22, 0xF4, 0x80, 0x22, 0xEA, 0x64, 0x04, 0xF1, 0x28, 0x00, 0x04, 0xF0, 0xDD, 0xF9, 0xD4, 0xF8, ++0x48, 0xC0, 0xA2, 0x6A, 0xB0, 0x88, 0xDC, 0xF8, 0x24, 0x30, 0xE9, 0x6D, 0xEA, 0x63, 0xEA, 0x6A, 0x40, 0xF0, 0x08, 0x04, ++0xB4, 0x80, 0x41, 0xF4, 0xC0, 0x60, 0x2C, 0x6E, 0xF4, 0x62, 0x42, 0xF0, 0x02, 0x02, 0x30, 0x64, 0x43, 0xF0, 0x10, 0x03, ++0xEA, 0x62, 0x39, 0x46, 0x06, 0xF5, 0x82, 0x70, 0x34, 0x22, 0xCC, 0xF8, 0x24, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, ++0x29, 0xF0, 0xFE, 0xB9, 0xA2, 0x6C, 0x00, 0x2A, 0x3C, 0xD0, 0x7A, 0x6A, 0x00, 0x2A, 0xAD, 0xD1, 0x3A, 0x6A, 0x92, 0xB1, ++0xB3, 0x6C, 0xA8, 0xE7, 0x2D, 0xB3, 0x71, 0x6A, 0x00, 0x29, 0x7F, 0xF4, 0x30, 0xAF, 0x32, 0x6A, 0x0A, 0xB1, 0xE3, 0x8B, ++0x2A, 0xE7, 0x23, 0x49, 0x23, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x3F, 0xFF, 0x32, 0x6A, 0xF5, 0xE7, 0x1F, 0x49, ++0x1F, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x37, 0xFF, 0x3A, 0x6A, 0xE4, 0xE7, 0x20, 0x22, 0x20, 0x46, 0x01, 0x91, ++0x22, 0xF0, 0xD8, 0xF8, 0x01, 0x99, 0x20, 0xE7, 0xA2, 0x88, 0x01, 0x91, 0x20, 0x46, 0x23, 0xF0, 0x87, 0xFA, 0x01, 0x99, ++0x19, 0xE7, 0x14, 0x49, 0x15, 0x48, 0x4F, 0xF4, 0xD9, 0x72, 0x16, 0xF0, 0x21, 0xFF, 0x71, 0x6A, 0xA9, 0xB9, 0xD9, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCF, 0xDB, 0xD8, 0xE7, 0x4F, 0xF4, 0xD9, 0x72, 0x0B, 0x49, 0x0D, 0x48, ++0x16, 0xF0, 0x12, 0xFF, 0x7A, 0x6A, 0x42, 0xB9, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB7, 0xDB, ++0xD1, 0xE7, 0xE3, 0x8B, 0xED, 0xE6, 0xB3, 0x6C, 0x60, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x8E, 0x15, 0x00, 0x8C, 0x8E, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x05, 0x28, 0x1C, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x07, 0x0B, 0x0F, 0x13, 0x17, 0x03, 0x12, 0x4B, 0x20, 0x22, 0x1A, 0x60, ++0x70, 0x47, 0x10, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0E, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0C, 0x4B, ++0x08, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0A, 0x4B, 0x10, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x70, 0x47, 0x07, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x04, 0x49, 0x05, 0x48, ++0x4F, 0xF4, 0x77, 0x72, 0x16, 0xF0, 0xCA, 0xBE, 0x80, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x05, 0x28, 0x85, 0xB0, 0x06, 0x46, 0x00, 0xF0, 0xE5, 0x81, 0xAE, 0x4C, ++0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, 0xAB, 0x4B, 0xAC, 0x4F, 0xDF, 0xF8, 0xD4, 0x92, ++0x01, 0x22, 0x19, 0x46, 0xB2, 0x40, 0x71, 0x18, 0x00, 0x92, 0xA3, 0x7E, 0x02, 0x91, 0xD2, 0x43, 0x4F, 0xEA, 0x81, 0x08, ++0x01, 0x92, 0x00, 0x2B, 0x3A, 0xD0, 0x3B, 0x68, 0x65, 0x6A, 0x5B, 0x78, 0xD5, 0xF8, 0x8C, 0x20, 0x00, 0x2B, 0x00, 0xF0, ++0x8B, 0x80, 0x69, 0x6D, 0x00, 0x29, 0x00, 0xF0, 0x11, 0x81, 0x00, 0x2A, 0x80, 0xF2, 0x29, 0x81, 0x9D, 0x49, 0xD9, 0xF8, ++0x00, 0x30, 0x51, 0xF8, 0x26, 0x10, 0x0B, 0x44, 0x11, 0x02, 0xC8, 0xF8, 0x00, 0x30, 0x40, 0xF1, 0xA2, 0x80, 0xAB, 0x88, ++0x99, 0x06, 0x40, 0xF1, 0x43, 0x81, 0x97, 0x4A, 0x43, 0xF0, 0x10, 0x03, 0x52, 0xF8, 0x26, 0x00, 0xAB, 0x80, 0x15, 0xF0, ++0x87, 0xF9, 0x94, 0xF8, 0x50, 0x30, 0x3A, 0x68, 0x01, 0x3B, 0x84, 0xF8, 0x50, 0x30, 0x00, 0x23, 0xA3, 0x76, 0x63, 0x62, ++0x53, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0x6B, 0x6D, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0xA5, 0x62, 0xEB, 0x7A, ++0x01, 0x33, 0xEB, 0x72, 0xE5, 0x68, 0x00, 0x2D, 0x00, 0xF0, 0x90, 0x81, 0xD5, 0xF8, 0x4C, 0xB0, 0xDB, 0xF8, 0x50, 0xA0, ++0xBA, 0xF1, 0x00, 0x0F, 0x80, 0xF2, 0xA9, 0x81, 0x30, 0x46, 0xCB, 0xF8, 0x10, 0xA0, 0x04, 0xF0, 0x03, 0xF9, 0x6A, 0x6A, ++0x12, 0xF4, 0x00, 0x10, 0x11, 0xD1, 0xDB, 0xF8, 0x18, 0x10, 0x00, 0x29, 0x00, 0xF0, 0x97, 0x80, 0x8B, 0x6B, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x00, 0x1F, 0x8C, 0x46, 0x00, 0xF0, 0x29, 0x81, 0xDC, 0xF8, 0x3C, 0x30, 0x00, 0x2B, 0x80, 0xF2, ++0x9D, 0x81, 0x1A, 0xF4, 0x00, 0x0F, 0x0B, 0xD0, 0x6B, 0x7F, 0x0D, 0x2B, 0x08, 0xD8, 0x73, 0x48, 0x73, 0x49, 0x4F, 0xF4, ++0x1E, 0x7C, 0x0C, 0xFB, 0x03, 0x03, 0x09, 0x69, 0xC3, 0xF8, 0x58, 0x12, 0x02, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x60, 0x1F, ++0x00, 0xF0, 0x9E, 0x80, 0x04, 0xF1, 0x0C, 0x00, 0x15, 0xF0, 0x18, 0xFA, 0x6B, 0x6A, 0x9B, 0x02, 0x04, 0xD4, 0x94, 0xF8, ++0x50, 0x30, 0x01, 0x3B, 0x84, 0xF8, 0x50, 0x30, 0xAB, 0x88, 0x00, 0x2B, 0x5F, 0xD1, 0x28, 0x46, 0x02, 0xF0, 0x4C, 0xF8, ++0x60, 0x4A, 0xD9, 0xF8, 0x00, 0x30, 0x52, 0xF8, 0x26, 0x20, 0x13, 0x44, 0xC8, 0xF8, 0x00, 0x30, 0xA3, 0x7E, 0x6A, 0xE7, ++0x29, 0x69, 0x00, 0x29, 0x00, 0xF0, 0xA4, 0x80, 0xAB, 0x6C, 0x00, 0x2B, 0x80, 0xF2, 0x9D, 0x80, 0x57, 0x4B, 0xD9, 0xF8, ++0x00, 0x20, 0x53, 0xF8, 0x26, 0x10, 0xAB, 0x88, 0x0A, 0x44, 0xC8, 0xF8, 0x00, 0x20, 0x9A, 0x06, 0x3F, 0xF5, 0x77, 0xAF, ++0xDF, 0xF8, 0x6C, 0xB1, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x4F, 0xF0, 0x04, 0x0A, 0xAB, 0x88, 0x99, 0x06, 0x3F, 0xF5, ++0x6C, 0xAF, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xBA, 0xF1, 0x01, 0x0A, 0xF5, 0xD1, 0xAB, 0x88, 0x9A, 0x06, 0x3F, 0xF5, ++0x62, 0xAF, 0x04, 0xF1, 0x1C, 0x00, 0x15, 0xF0, 0xD3, 0xF9, 0xAB, 0x88, 0x5B, 0xE7, 0x2B, 0x69, 0x00, 0x2B, 0x7F, 0xF4, ++0x71, 0xAF, 0x46, 0x4B, 0x1B, 0x68, 0xEF, 0xF3, 0x10, 0x82, 0xD0, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x43, 0x4A, 0x01, 0x21, ++0x11, 0x60, 0x43, 0x4A, 0x01, 0x99, 0x10, 0x68, 0x3F, 0x4D, 0x0B, 0x40, 0x41, 0x1C, 0x11, 0x60, 0x2B, 0x60, 0x29, 0xB1, ++0x3D, 0x4B, 0x10, 0x60, 0x1B, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x3C, 0x4B, 0x00, 0x9A, 0x1A, 0x60, 0x00, 0x22, ++0xA3, 0x7E, 0x22, 0x60, 0x17, 0xE7, 0x51, 0x46, 0x28, 0x46, 0x32, 0x46, 0x01, 0xF0, 0xC6, 0xF9, 0x9C, 0xE7, 0x33, 0x4B, ++0x1B, 0x68, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x30, 0x4A, 0x01, 0x21, 0x11, 0x60, 0xDF, 0xF8, ++0xC0, 0xC0, 0x01, 0x99, 0xDC, 0xF8, 0x00, 0x00, 0x2B, 0x4A, 0x0B, 0x40, 0x41, 0x1C, 0xCC, 0xF8, 0x00, 0x10, 0x13, 0x60, ++0x39, 0xB1, 0x29, 0x4B, 0xCC, 0xF8, 0x00, 0x00, 0x1B, 0x68, 0x10, 0xB9, 0x00, 0x2B, 0x40, 0xF0, 0xA2, 0x80, 0x27, 0x4B, ++0x00, 0x9A, 0x1A, 0x60, 0x94, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x2B, 0x22, 0x60, 0x7C, 0xD0, 0x6A, 0x6A, 0x4C, 0xE7, ++0x6B, 0x6C, 0x63, 0x62, 0x01, 0x23, 0x40, 0x20, 0xA3, 0x76, 0x15, 0xF0, 0x91, 0xF8, 0x59, 0xE7, 0x94, 0xF8, 0x50, 0x10, ++0x01, 0x29, 0x7F, 0xF4, 0xEA, 0xAE, 0xE1, 0x6A, 0x00, 0x29, 0x3F, 0xF4, 0xE6, 0xAE, 0x21, 0x6B, 0x19, 0x48, 0x09, 0x7F, ++0x4F, 0xF0, 0xA4, 0x0C, 0x0C, 0xFB, 0x01, 0x61, 0x99, 0x31, 0x50, 0xF8, 0x31, 0x10, 0x00, 0x29, 0x7B, 0xD0, 0x00, 0x2B, ++0x3F, 0xF4, 0x62, 0xAF, 0x00, 0x2A, 0xFF, 0xF6, 0xD7, 0xAE, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x94, 0xF8, 0x50, 0x10, ++0x01, 0x29, 0x7F, 0xF4, 0x57, 0xAF, 0xE1, 0x6A, 0x00, 0x29, 0xE2, 0xD1, 0x52, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, ++0x4A, 0x80, 0x0C, 0x10, 0x34, 0x36, 0x17, 0x00, 0xB0, 0x35, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x80, 0x32, 0x40, ++0x18, 0x88, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xDF, 0xF8, 0x68, 0xB1, 0xDB, 0xF8, 0x9C, 0x32, ++0x98, 0x47, 0x4F, 0xF0, 0x04, 0x0A, 0xAB, 0x88, 0x9A, 0x06, 0x3F, 0xF5, 0xB2, 0xAE, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, ++0xBA, 0xF1, 0x01, 0x0A, 0xF5, 0xD1, 0x4D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xAB, 0x88, 0xBF, 0xF6, ++0xA4, 0xAE, 0x98, 0x06, 0x3F, 0xF5, 0xA1, 0xAE, 0x48, 0x49, 0x49, 0x48, 0x4F, 0xF4, 0xAC, 0x62, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x16, 0xF0, 0xEB, 0xBC, 0x43, 0x48, 0x8B, 0x68, 0x01, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x00, 0x29, 0x33, 0xDB, ++0x60, 0x46, 0x9C, 0x46, 0xCC, 0xE6, 0xE3, 0x6A, 0x00, 0x2B, 0x3F, 0xF4, 0x7F, 0xAF, 0x23, 0x6B, 0x3E, 0x4A, 0x1B, 0x7F, ++0xA4, 0x21, 0x01, 0xFB, 0x03, 0x63, 0x99, 0x33, 0x52, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x73, 0xAF, 0x3A, 0x4B, ++0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0x6D, 0xAF, 0x38, 0x4B, 0x30, 0x46, 0xD3, 0xF8, 0x5C, 0x33, 0x98, 0x47, ++0x66, 0xE7, 0x62, 0xB6, 0x5B, 0xE7, 0x33, 0x49, 0x91, 0xF8, 0xFF, 0x11, 0x00, 0x29, 0x7F, 0xF4, 0x7E, 0xAF, 0x31, 0x4B, ++0x03, 0x92, 0xD3, 0xF8, 0x5C, 0x33, 0x30, 0x46, 0x98, 0x47, 0x3B, 0x68, 0x03, 0x9A, 0x5B, 0x78, 0x00, 0x2B, 0x7F, 0xF4, ++0x75, 0xAF, 0xD5, 0xE6, 0x00, 0x2B, 0xC9, 0xD1, 0x25, 0x49, 0x2A, 0x48, 0x00, 0x93, 0x40, 0xF2, 0x56, 0x42, 0x16, 0xF0, ++0xD9, 0xFC, 0x00, 0x9B, 0xDB, 0x6B, 0xFF, 0xDE, 0x26, 0x4C, 0x1F, 0xE6, 0x26, 0x4B, 0x25, 0x60, 0x1B, 0x68, 0xEF, 0xF3, ++0x10, 0x82, 0xD0, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x23, 0x4A, 0x01, 0x21, 0x11, 0x60, 0x23, 0x4A, 0x01, 0x99, 0x10, 0x68, ++0x1F, 0x4C, 0x19, 0x40, 0x0B, 0x46, 0x41, 0x1C, 0x11, 0x60, 0x23, 0x60, 0x29, 0xB1, 0x1D, 0x4B, 0x10, 0x60, 0x1B, 0x68, ++0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x1C, 0x4B, 0x00, 0x9A, 0x1A, 0x60, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x6B, 0x6A, ++0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x7F, 0xF4, 0x41, 0xAF, 0x68, 0x6C, 0x31, 0x46, 0x0C, 0x30, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0x03, 0xF0, 0x28, 0xBF, 0x10, 0xB1, 0x31, 0x46, 0x03, 0xF0, 0x24, 0xFF, 0x10, 0x4B, 0x11, 0x4A, ++0x53, 0xF8, 0x26, 0x10, 0x02, 0x9B, 0x12, 0x68, 0x9B, 0x00, 0x0A, 0x44, 0x1A, 0x60, 0x2A, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xD4, 0x8E, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xC0, 0x8E, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x88, 0x80, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x43, 0x6A, 0x9B, 0x02, 0x03, 0xD5, 0x4B, 0x6A, ++0x5B, 0x07, 0x07, 0xD4, 0x70, 0x47, 0xC1, 0x6C, 0x05, 0x4B, 0x14, 0x31, 0xD3, 0xF8, 0x9C, 0x33, 0x08, 0x46, 0x18, 0x47, ++0x42, 0x6C, 0x93, 0x88, 0x43, 0xF0, 0x02, 0x03, 0x93, 0x80, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x43, 0x7F, ++0x0B, 0x4E, 0x4F, 0xF4, 0x1E, 0x75, 0x04, 0x46, 0x05, 0xFB, 0x03, 0xF5, 0x05, 0xF5, 0xFE, 0x70, 0x01, 0x23, 0xE1, 0x76, ++0x84, 0xF8, 0x5D, 0x30, 0x30, 0x44, 0x21, 0x46, 0x14, 0xF0, 0xFE, 0xFF, 0x04, 0x4B, 0x71, 0x19, 0x20, 0x46, 0x5B, 0x69, ++0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x83, 0x88, 0x2D, 0xE9, ++0xF0, 0x41, 0x04, 0x46, 0x0E, 0x46, 0x15, 0x46, 0xEB, 0xB1, 0x3A, 0x4B, 0xD0, 0xF8, 0x4C, 0x80, 0x1A, 0x68, 0xB2, 0xF9, ++0x00, 0x20, 0x00, 0x2A, 0x23, 0xDB, 0xD8, 0xF8, 0x24, 0x70, 0x17, 0xB9, 0xD8, 0xF8, 0x20, 0x30, 0x9F, 0x68, 0x04, 0x2D, ++0x03, 0xD1, 0x39, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x13, 0xFB, 0xE3, 0x7E, 0xFF, 0x2B, 0x25, 0xD0, 0x2F, 0x4F, 0x29, 0x46, ++0xD7, 0xF8, 0x00, 0x34, 0x20, 0x46, 0x98, 0x47, 0x05, 0xE0, 0x82, 0x6C, 0x2B, 0x4F, 0x53, 0x6A, 0x43, 0xF0, 0x10, 0x03, ++0x53, 0x62, 0xD7, 0xF8, 0xA4, 0x33, 0x2A, 0x46, 0x31, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x82, 0x6C, ++0x5A, 0xB3, 0xD8, 0xF8, 0x24, 0x70, 0x00, 0x2F, 0xDB, 0xD1, 0xD8, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0xD6, 0xD1, 0x21, 0x49, ++0x21, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x03, 0xFC, 0xCD, 0xE7, 0xE3, 0x8B, 0x1A, 0x07, 0x04, 0xD5, 0x3A, 0x88, ++0x02, 0xF0, 0xDC, 0x02, 0x10, 0x2A, 0x25, 0xD0, 0xBB, 0x7D, 0x13, 0xF0, 0x0F, 0x03, 0x07, 0xF1, 0x16, 0x07, 0x06, 0xD0, ++0x18, 0x4A, 0xB2, 0xF8, 0xFC, 0x21, 0x43, 0xEA, 0x02, 0x13, 0x3B, 0x80, 0xC4, 0xE7, 0x15, 0x49, 0xB1, 0xF8, 0xFC, 0x21, ++0x01, 0x32, 0x92, 0xB2, 0xA1, 0xF8, 0xFC, 0x21, 0xF3, 0xE7, 0x0F, 0x49, 0x11, 0x48, 0x4F, 0xF4, 0xD9, 0x72, 0x16, 0xF0, ++0xDF, 0xFB, 0xD8, 0xF8, 0x24, 0x70, 0x00, 0x2F, 0xA9, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC7, 0xDB, 0x9F, 0xE7, 0x7A, 0x8B, 0x00, 0x2A, 0xD6, 0xD1, 0x43, 0xF0, 0x20, 0x03, 0xE3, 0x83, 0x38, 0x1D, 0x20, 0xF0, ++0xF9, 0xFE, 0xCF, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x8E, 0x15, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x8C, 0x8E, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x46, 0x05, 0x29, 0x00, 0xF2, 0x33, 0x81, 0xDF, 0xE8, ++0x01, 0xF0, 0x36, 0x44, 0x51, 0x5E, 0x6B, 0x03, 0x9D, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0x00, 0xF0, ++0x04, 0x81, 0x9B, 0x4A, 0x9B, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x42, 0x1A, 0x60, 0x9A, 0x49, 0x9A, 0x4A, 0x9B, 0x4B, ++0x51, 0xF8, 0x24, 0x50, 0x12, 0x68, 0x9A, 0x48, 0x23, 0x44, 0x9B, 0x00, 0x01, 0x21, 0x2A, 0x44, 0x01, 0xFA, 0x04, 0xF4, ++0x1A, 0x60, 0x04, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x94, 0x4B, 0x19, 0x60, 0x94, 0x4B, ++0x94, 0x49, 0x18, 0x68, 0x0D, 0x68, 0x42, 0x1C, 0x2C, 0x43, 0x1A, 0x60, 0x0C, 0x60, 0x2A, 0xB1, 0x8E, 0x4A, 0x18, 0x60, ++0x13, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x84, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x13, 0x02, 0x2B, ++0x00, 0xF0, 0xAE, 0x80, 0x8A, 0x4A, 0x82, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0xCB, 0xE7, 0x7D, 0x4A, ++0x13, 0x68, 0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0x7D, 0xD0, 0x85, 0x4A, 0x7B, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x62, ++0x1A, 0x60, 0xBE, 0xE7, 0x76, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x33, 0x02, 0x2B, 0x4F, 0xD0, 0x7F, 0x4A, 0x75, 0x4B, ++0x10, 0x60, 0x4F, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0xB1, 0xE7, 0x70, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, ++0x21, 0xD0, 0x7A, 0x4A, 0x6E, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0xA4, 0xE7, 0x77, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0xDB, 0x75, 0x4A, 0x68, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, ++0x97, 0xE7, 0x63, 0x4B, 0x1B, 0x68, 0x03, 0xF0, 0x03, 0x03, 0x02, 0x2B, 0xF2, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x6F, 0x49, ++0x6F, 0x48, 0x4F, 0xF4, 0xEC, 0x62, 0x16, 0xF0, 0xFF, 0xBA, 0x60, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, ++0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, 0xF6, 0xD0, 0x63, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCA, 0xDA, 0x52, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, 0xC4, 0xD1, ++0xBD, 0xE8, 0x38, 0x40, 0x5E, 0x49, 0x60, 0x48, 0x40, 0xF2, 0x6C, 0x72, 0x16, 0xF0, 0xDE, 0xBA, 0x4F, 0x49, 0x0D, 0x68, ++0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x33, 0x02, 0x2B, ++0xF6, 0xD0, 0x53, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x9C, 0xDA, 0x42, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, ++0x01, 0x33, 0x02, 0x2B, 0x96, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x4E, 0x49, 0x50, 0x48, 0x4F, 0xF4, 0xEF, 0x62, 0x16, 0xF0, ++0xBD, 0xBA, 0x3F, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, ++0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0xF6, 0xD0, 0x42, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0x6E, 0xAF, 0x31, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0x7F, 0xF4, 0x67, 0xAF, 0xBD, 0xE8, 0x38, 0x40, ++0x3C, 0x49, 0x40, 0x48, 0x40, 0xF2, 0x84, 0x72, 0x16, 0xF0, 0x9A, 0xBA, 0x2D, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, ++0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x13, 0x02, 0x2B, 0xF6, 0xD0, 0x31, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0x3E, 0xAF, 0x1F, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x13, ++0x02, 0x2B, 0x7F, 0xF4, 0x37, 0xAF, 0xBD, 0xE8, 0x38, 0x40, 0x2B, 0x49, 0x2F, 0x48, 0x4F, 0xF4, 0xF2, 0x62, 0x16, 0xF0, ++0x77, 0xBA, 0x1C, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, ++0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0xF6, 0xD0, 0x1F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0xE8, 0xAE, 0x0E, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0x7F, 0xF4, 0xE1, 0xAE, 0xBD, 0xE8, 0x38, 0x40, ++0x19, 0x49, 0x1F, 0x48, 0x40, 0xF2, 0x9C, 0x72, 0x16, 0xF0, 0x54, 0xBA, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xBF, 0xF6, 0xD8, 0xAE, 0x13, 0x49, 0x19, 0x48, 0x40, 0xF2, 0xA2, 0x72, 0x16, 0xF0, 0x79, 0xFA, 0xD0, 0xE6, ++0x88, 0x81, 0x32, 0x40, 0x34, 0x83, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, ++0x4A, 0x80, 0x0C, 0x10, 0x88, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, ++0x9C, 0x81, 0x32, 0x40, 0xA0, 0x81, 0x32, 0x40, 0xA4, 0x81, 0x32, 0x40, 0xA8, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x98, 0x81, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0xF8, 0x8E, 0x15, 0x00, 0x18, 0x8F, 0x15, 0x00, 0x38, 0x8F, 0x15, 0x00, ++0x58, 0x8F, 0x15, 0x00, 0x78, 0x8F, 0x15, 0x00, 0x98, 0x8F, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x05, 0x2A, 0xF8, 0xB5, ++0x06, 0x46, 0x0D, 0x46, 0x35, 0xD0, 0x54, 0x21, 0x33, 0x4C, 0x01, 0xFB, 0x02, 0xF1, 0x02, 0xEB, 0x42, 0x03, 0x61, 0x58, ++0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, 0x00, 0x29, 0x37, 0xD0, 0x2E, 0x4F, 0x3B, 0x68, 0x5B, 0x78, 0xF3, 0xB1, ++0x4E, 0x60, 0x05, 0x2A, 0x0B, 0xD0, 0x2C, 0x48, 0x02, 0xEB, 0x42, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x91, 0xF8, 0x2E, 0x10, ++0x41, 0xB9, 0x90, 0xF8, 0x8C, 0x10, 0x00, 0x29, 0x3E, 0xD1, 0x10, 0x46, 0xFF, 0xF7, 0x2A, 0xFB, 0x3B, 0x68, 0x5B, 0x78, ++0x3B, 0xB9, 0xAA, 0x6B, 0x92, 0x02, 0x46, 0xBF, 0x01, 0x23, 0xC4, 0xE9, 0x01, 0x63, 0xC4, 0xE9, 0x01, 0x33, 0x25, 0x60, ++0xF8, 0xBD, 0xA0, 0x68, 0x00, 0x28, 0xDD, 0xD0, 0x61, 0x68, 0x4E, 0x60, 0xDB, 0xE7, 0x19, 0x4C, 0xD4, 0xF8, 0xA4, 0x11, ++0x04, 0xF5, 0xD2, 0x74, 0x00, 0x29, 0xCF, 0xD1, 0x11, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x44, 0xFE, 0x14, 0x4B, 0x1B, 0x68, ++0x5B, 0x78, 0xDF, 0xE7, 0x13, 0x4B, 0x02, 0xEB, 0x42, 0x00, 0x03, 0xEB, 0x80, 0x00, 0x51, 0x00, 0x90, 0xF8, 0x2E, 0x00, ++0x38, 0xB9, 0x93, 0xF8, 0x8C, 0x00, 0x93, 0xF8, 0x7E, 0x70, 0x00, 0x28, 0xE8, 0xD0, 0xBA, 0x42, 0xE6, 0xD1, 0x0A, 0x44, ++0x03, 0xEB, 0x82, 0x03, 0x5A, 0x6A, 0x42, 0xB1, 0x07, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0xC5, 0xE7, 0x90, 0xF8, 0x7E, 0x10, ++0x91, 0x42, 0xBC, 0xD1, 0xC0, 0xE7, 0x03, 0x4A, 0x5E, 0x62, 0x13, 0x68, 0x5B, 0x78, 0xBB, 0xE7, 0x20, 0x62, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x38, 0xB5, 0x83, 0x88, 0x33, 0xB1, 0x04, 0x46, 0x80, 0x6C, 0x18, 0xB1, ++0x63, 0x6A, 0x13, 0xF4, 0x00, 0x15, 0x00, 0xD0, 0x38, 0xBD, 0xF8, 0xF7, 0x75, 0xFE, 0xA5, 0x64, 0x38, 0xBD, 0x00, 0xBF, ++0x70, 0xB5, 0x20, 0x4C, 0x20, 0x4D, 0x02, 0xF0, 0xD9, 0xFC, 0xD4, 0xF8, 0x44, 0x33, 0x98, 0x47, 0xFE, 0xF7, 0x9E, 0xFF, ++0x00, 0xF0, 0xA8, 0xFD, 0xD4, 0xF8, 0xA8, 0x33, 0x00, 0x20, 0x98, 0x47, 0x04, 0xF0, 0xBA, 0xFE, 0x4F, 0xF4, 0x01, 0x72, ++0x00, 0x21, 0xA5, 0xF1, 0x0C, 0x00, 0xF1, 0xF7, 0xC3, 0xFC, 0x05, 0xF5, 0xD2, 0x76, 0x00, 0x24, 0x28, 0x46, 0x14, 0xF0, ++0x4D, 0xFD, 0x45, 0xF8, 0x0C, 0x4C, 0xAC, 0x73, 0x85, 0xF8, 0x44, 0x40, 0xC5, 0xE9, 0x06, 0x44, 0x05, 0xF1, 0x10, 0x00, ++0x54, 0x35, 0x14, 0xF0, 0x41, 0xFD, 0xB5, 0x42, 0xEE, 0xD1, 0x0C, 0x4D, 0x05, 0xF5, 0xD8, 0x70, 0x14, 0xF0, 0x3A, 0xFD, ++0x05, 0xF5, 0xE0, 0x70, 0xC5, 0xE9, 0x72, 0x44, 0xC5, 0xF8, 0xA4, 0x41, 0x85, 0xF8, 0xBE, 0x41, 0x85, 0xF8, 0xF4, 0x41, ++0x14, 0xF0, 0x2E, 0xFD, 0xA5, 0xF8, 0xFC, 0x41, 0x70, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x62, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x0C, 0x4B, 0x93, 0xF8, 0xFE, 0x31, 0x0B, 0xB1, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x04, 0x46, ++0x10, 0xF0, 0xBC, 0xF8, 0x20, 0xB1, 0x94, 0xF8, 0xC0, 0x34, 0x1B, 0xB9, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, ++0x94, 0xF8, 0xC1, 0x04, 0x11, 0xF0, 0x16, 0xFD, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x10, 0xBD, 0x20, 0x62, 0x17, 0x00, ++0x45, 0x4B, 0x01, 0x22, 0x70, 0xB4, 0x1B, 0x68, 0x02, 0xFA, 0x00, 0xF6, 0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, ++0x72, 0xB6, 0x41, 0x49, 0x0A, 0x60, 0x41, 0x4A, 0x3E, 0x4D, 0x14, 0x68, 0x23, 0xEA, 0x06, 0x03, 0x61, 0x1C, 0x11, 0x60, ++0x2B, 0x60, 0x29, 0xB1, 0x3B, 0x4B, 0x14, 0x60, 0x1B, 0x68, 0x0C, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x3A, 0x4B, 0x1E, 0x60, ++0x05, 0x28, 0x5D, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x12, 0x21, 0x3F, 0x30, 0x4E, 0x03, 0x37, 0x4B, 0x37, 0x4A, 0x4F, 0xF4, ++0x00, 0x11, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF0, 0x40, 0x7F, 0xFB, 0xD1, 0x34, 0x4B, 0x4F, 0xF4, 0x00, 0x12, 0x70, 0xBC, ++0x1A, 0x60, 0x70, 0x47, 0x2F, 0x4B, 0x30, 0x4A, 0x4F, 0xF4, 0x80, 0x31, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF0, 0x30, 0x0F, ++0xFB, 0xD1, 0x2D, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x28, 0x4B, 0x28, 0x4A, 0x4F, 0xF4, ++0x00, 0x31, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x7F, 0xFB, 0xD1, 0x25, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x70, 0xBC, ++0x1A, 0x60, 0x70, 0x47, 0x20, 0x4B, 0x21, 0x4A, 0x4F, 0xF4, 0x00, 0x21, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x3F, ++0xFB, 0xD1, 0x1E, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x19, 0x4B, 0x19, 0x4A, 0x4F, 0xF4, ++0x80, 0x21, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x5F, 0xFB, 0xD1, 0x16, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x70, 0xBC, ++0x1A, 0x60, 0x70, 0x47, 0x11, 0x4B, 0x12, 0x4A, 0x4F, 0xF4, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x9B, 0x07, 0xFC, 0xD1, ++0x0F, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0x1A, 0x60, 0x70, 0xBC, 0x70, 0x47, 0x0D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xF7, 0xDA, 0x70, 0xBC, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0xE7, 0x02, 0x16, 0xF0, 0xD5, 0xB8, 0x00, 0xBF, ++0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x80, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, ++0x88, 0x81, 0x32, 0x40, 0x84, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x70, 0xB5, 0x05, 0x28, 0x82, 0xB0, 0x04, 0x46, 0x0A, 0x46, 0x3B, 0xD0, 0x1E, 0x4B, 0x00, 0xEB, 0x40, 0x05, 0xC5, 0xEB, ++0xC5, 0x05, 0x03, 0xEB, 0x85, 0x05, 0x1C, 0x4E, 0x1C, 0x49, 0xD6, 0xF8, 0x84, 0x33, 0x01, 0x92, 0x01, 0xEB, 0xC4, 0x01, ++0x20, 0x46, 0x98, 0x47, 0x01, 0x9A, 0xD6, 0xF8, 0x84, 0x33, 0x05, 0xF1, 0x0C, 0x01, 0x20, 0x46, 0x98, 0x47, 0x00, 0x23, ++0x20, 0x46, 0x2B, 0x60, 0x6B, 0x61, 0xFE, 0xF7, 0x59, 0xFE, 0x13, 0x4B, 0x01, 0x22, 0x1B, 0x68, 0x02, 0xFA, 0x04, 0xF4, ++0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x0F, 0x49, 0x0A, 0x60, 0x0F, 0x4A, 0x0C, 0x4D, 0x11, 0x68, ++0x23, 0xEA, 0x04, 0x03, 0x48, 0x1C, 0x10, 0x60, 0x2B, 0x60, 0x28, 0xB1, 0x09, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x08, 0x4B, 0x1C, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x07, 0x4D, 0xC8, 0xE7, 0x20, 0x62, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x24, 0x64, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x88, 0x80, 0x32, 0x40, 0xC4, 0x63, 0x17, 0x00, 0x70, 0xB5, 0x0E, 0x4E, 0x82, 0xB0, 0x00, 0xF5, 0x9E, 0x64, 0x00, 0x25, ++0xE8, 0xB2, 0x21, 0x46, 0xD6, 0xF8, 0x84, 0x33, 0x01, 0x90, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0x01, 0x35, 0xA4, 0xF1, ++0x28, 0x01, 0x01, 0x98, 0xD6, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0x05, 0x2D, 0x04, 0xF1, 0x08, 0x04, ++0xEA, 0xD1, 0x02, 0xB0, 0x70, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x05, 0x29, 0x2D, 0xE9, 0xF0, 0x41, 0x0E, 0x46, ++0x04, 0x46, 0x64, 0xD0, 0x33, 0x4D, 0x01, 0xEB, 0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x05, 0xEB, 0x83, 0x05, 0x94, 0xF8, ++0x35, 0x10, 0x94, 0xF8, 0x33, 0x20, 0xA3, 0x88, 0x2E, 0x48, 0x0A, 0x44, 0x1A, 0x44, 0xE3, 0x6C, 0xE1, 0x8B, 0x58, 0x61, ++0x04, 0x32, 0xDA, 0x62, 0x00, 0x22, 0xC3, 0xE9, 0x0F, 0x22, 0xC3, 0xE9, 0x06, 0x22, 0xC3, 0xE9, 0x08, 0x22, 0x5A, 0x64, ++0x9A, 0x62, 0x9A, 0x63, 0xDA, 0x64, 0x1A, 0x63, 0x1A, 0x65, 0xCA, 0x07, 0x05, 0xD4, 0x22, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, ++0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x21, 0x4B, 0x1B, 0x6A, 0x23, 0xB1, 0x20, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x33, ++0x13, 0x60, 0xDF, 0xF8, 0x88, 0x80, 0x61, 0x7F, 0x20, 0x7F, 0x00, 0x22, 0x12, 0xF0, 0x5A, 0xF9, 0xD8, 0xF8, 0x48, 0x32, ++0xE1, 0x7E, 0x60, 0x7F, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x16, 0x4F, 0xD8, 0xF8, 0x68, 0x33, 0x3A, 0x68, 0x01, 0x32, 0x3A, 0x60, 0x31, 0x46, 0x20, 0x46, 0x98, 0x47, ++0xD8, 0xF8, 0x08, 0x34, 0x31, 0x46, 0x00, 0x22, 0x20, 0x46, 0x98, 0x47, 0x21, 0x46, 0x05, 0xF1, 0x0C, 0x00, 0x14, 0xF0, ++0x99, 0xFB, 0x3B, 0x68, 0x33, 0xB1, 0x0A, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x07, 0x4D, 0x9F, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, ++0x1C, 0x9E, 0x17, 0x00, 0x80, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x03, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, 0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x70, 0x47, 0x00, 0xBF, ++0x20, 0x62, 0x17, 0x00, 0x05, 0x29, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x46, 0x04, 0x46, 0x1C, 0xD0, 0x47, 0x4E, 0x01, 0xEB, ++0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x06, 0xEB, 0x83, 0x06, 0x22, 0x7F, 0x44, 0x4B, 0xE7, 0x6C, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x02, 0x30, 0xFF, 0xF7, 0x32, 0xFE, 0x68, 0xB9, 0x63, 0x7F, 0xFF, 0x2B, 0x67, 0xD0, 0x3F, 0x4B, 0x20, 0x46, ++0xD3, 0xF8, 0x90, 0x33, 0x29, 0x46, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x3C, 0x4E, 0xE7, 0xE7, 0x20, 0x46, ++0x1C, 0xF0, 0xEE, 0xFF, 0x00, 0x28, 0xEC, 0xD0, 0xFB, 0x6C, 0x43, 0xF4, 0x80, 0x73, 0xFB, 0x64, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x34, 0x4F, 0x96, 0xF8, 0x50, 0x30, 0x3A, 0x68, ++0xF1, 0x6A, 0xDF, 0xF8, 0xBC, 0x80, 0x01, 0x32, 0x01, 0x33, 0x3A, 0x60, 0x86, 0xF8, 0x50, 0x30, 0x19, 0xB1, 0xD8, 0xF8, ++0x5C, 0x33, 0x28, 0x46, 0x98, 0x47, 0x73, 0x69, 0x00, 0x2B, 0x42, 0xD0, 0x06, 0xF1, 0x0C, 0x00, 0x21, 0x46, 0x14, 0xF0, ++0x21, 0xFB, 0x3B, 0x68, 0x2B, 0xB1, 0x26, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x00, 0x2B, 0x31, 0xD0, 0x1F, 0x4A, ++0x24, 0x49, 0xD2, 0xF8, 0xF8, 0x31, 0x09, 0x6A, 0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x21, 0xB1, 0x21, 0x4A, 0x13, 0x68, ++0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x19, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x3B, 0x68, 0xD8, 0xF8, 0x04, 0x64, 0xA1, 0x6C, 0x01, 0x33, 0x3B, 0x60, 0x2A, 0x46, 0x20, 0x46, 0xB0, 0x47, ++0x3B, 0x68, 0x33, 0xB1, 0x12, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x01, 0x20, ++0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x46, 0x00, 0x21, 0x01, 0xF0, 0x7E, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x2A, ++0xCB, 0xD0, 0x62, 0xB6, 0xC9, 0xE7, 0xA3, 0x6C, 0x0B, 0x49, 0x5A, 0x6A, 0x9C, 0x60, 0x22, 0xF0, 0x10, 0x02, 0x5A, 0x62, ++0xD9, 0x60, 0xB3, 0xE7, 0x20, 0x62, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x80, 0x00, 0x32, 0x40, 0xDE, 0xFA, 0xFE, 0xCA, ++0x70, 0x47, 0x00, 0xBF, 0x20, 0x4B, 0x70, 0xB5, 0x1C, 0x68, 0xE1, 0x04, 0x2C, 0xD4, 0x1F, 0x4D, 0x2C, 0x42, 0x24, 0xD1, ++0x1E, 0x4B, 0x23, 0x40, 0x20, 0xD0, 0x22, 0x03, 0x0B, 0xD5, 0x1D, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x05, 0x24, ++0x1B, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xA0, 0x33, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x19, 0x4A, 0x12, 0x68, 0xB2, 0xF9, ++0x00, 0x20, 0xB3, 0xFA, 0x83, 0xF3, 0xC3, 0xF1, 0x19, 0x04, 0x00, 0x2A, 0xE4, 0xB2, 0x14, 0xDB, 0x05, 0x2C, 0xE6, 0xD0, ++0x10, 0x4A, 0xA1, 0x1D, 0x01, 0x23, 0x8B, 0x40, 0x13, 0x60, 0xE5, 0xE7, 0x70, 0xBD, 0x04, 0xF0, 0x07, 0xFB, 0x0C, 0x4B, ++0x1D, 0x60, 0xD5, 0xE7, 0x04, 0xF0, 0x56, 0xFA, 0x09, 0x4B, 0x4F, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0xCB, 0xE7, 0x06, 0x2C, ++0xE8, 0xD9, 0x09, 0x49, 0x09, 0x48, 0x40, 0xF6, 0xC2, 0x22, 0x15, 0xF0, 0xD9, 0xFE, 0xE3, 0xE7, 0x78, 0x80, 0x32, 0x40, ++0x00, 0x08, 0x00, 0x20, 0xC0, 0x07, 0x08, 0x00, 0x7C, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xB8, 0x8F, 0x15, 0x00, 0x38, 0xB5, 0x0D, 0x4B, 0x0D, 0x4D, 0x1C, 0x68, 0xE3, 0x06, 0x05, 0xEA, ++0x04, 0x05, 0x03, 0xD5, 0x0B, 0x4B, 0xD3, 0xF8, 0xF0, 0x33, 0x98, 0x47, 0x14, 0xF4, 0x70, 0x04, 0x08, 0xD0, 0x08, 0x4B, ++0xB4, 0xFA, 0x84, 0xF4, 0xC4, 0xF1, 0x0B, 0x00, 0xD3, 0xF8, 0x48, 0x33, 0xC0, 0xB2, 0x98, 0x47, 0x04, 0x4B, 0x1D, 0x60, ++0x38, 0xBD, 0x00, 0xBF, 0x78, 0x80, 0x32, 0x40, 0x1F, 0x00, 0xF0, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x7C, 0x80, 0x32, 0x40, ++0xFF, 0xF7, 0xDA, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1C, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x70, 0x90, 0x1A, 0x4F, 0xD9, 0xF8, 0x00, 0x30, 0xDF, 0xF8, 0x6C, 0x80, 0x01, 0x33, ++0xC9, 0xF8, 0x00, 0x30, 0x3D, 0x46, 0x46, 0x46, 0x04, 0x24, 0x95, 0xF8, 0x5E, 0x30, 0xE2, 0xB2, 0x63, 0xB9, 0x97, 0xF8, ++0x8C, 0x30, 0x97, 0xF8, 0x7E, 0x10, 0x10, 0x46, 0x0B, 0xB1, 0x91, 0x42, 0x04, 0xD0, 0xD6, 0xF8, 0x50, 0x31, 0x0B, 0xB1, ++0xFF, 0xF7, 0x1A, 0xFD, 0x01, 0x3C, 0x63, 0x1C, 0xA5, 0xF1, 0x0C, 0x05, 0xA6, 0xF1, 0x54, 0x06, 0xE7, 0xD1, 0xD9, 0xF8, ++0x00, 0x30, 0x01, 0x22, 0x88, 0xF8, 0xFF, 0x21, 0x3B, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x31, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x31, 0x4E, 0x31, 0x4D, 0x33, 0x68, 0x31, 0x4F, 0xDF, 0xF8, ++0xD0, 0xB0, 0xDF, 0xF8, 0xD0, 0xA0, 0xDF, 0xF8, 0xD0, 0x80, 0x01, 0x33, 0x00, 0x22, 0x33, 0x60, 0x85, 0xF8, 0xFF, 0x21, ++0xB9, 0x46, 0x04, 0x24, 0x99, 0xF8, 0x5E, 0x30, 0xE0, 0xB2, 0x00, 0x2B, 0x34, 0xD1, 0x97, 0xF8, 0x8C, 0x30, 0x97, 0xF8, ++0x7E, 0x20, 0x0B, 0xB1, 0x82, 0x42, 0x2D, 0xD0, 0xD5, 0xF8, 0x50, 0x31, 0x43, 0xB3, 0x01, 0x90, 0xFE, 0xF7, 0x36, 0xFF, ++0x5A, 0xF8, 0x24, 0x30, 0xDB, 0xF8, 0x00, 0x20, 0x20, 0x48, 0x1A, 0x44, 0x40, 0xF8, 0x24, 0x20, 0x01, 0x21, 0x1F, 0x4A, ++0x01, 0xFA, 0x04, 0xF3, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x82, 0x12, 0xF0, 0x01, 0x0F, 0x01, 0x98, 0x02, 0xD1, 0x72, 0xB6, ++0x14, 0x4A, 0x11, 0x60, 0x32, 0x68, 0xD8, 0xF8, 0x00, 0xC0, 0x51, 0x1C, 0x43, 0xEA, 0x0C, 0x03, 0x31, 0x60, 0xC8, 0xF8, ++0x00, 0x30, 0x29, 0xB1, 0x0E, 0x4B, 0x32, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x03, 0xF0, 0x32, 0xF8, ++0x01, 0x3C, 0x63, 0x1C, 0xA9, 0xF1, 0x0C, 0x09, 0xA5, 0xF1, 0x54, 0x05, 0xBE, 0xD1, 0x33, 0x68, 0x33, 0xB1, 0x06, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x40, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, ++0x14, 0xF0, 0xF8, 0xB8, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x28, 0x01, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x20, 0x01, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x4F, 0x5D, 0x4E, 0xDF, 0xF8, 0x90, 0x91, 0xB6, 0xF8, 0xFC, 0x31, 0x83, 0xB0, 0x4F, 0xF4, 0x78, 0x30, ++0x00, 0x93, 0x06, 0xF1, 0x0C, 0x05, 0x14, 0xF0, 0xFB, 0xF8, 0x01, 0x23, 0x86, 0xF8, 0xFE, 0x31, 0xAA, 0x46, 0x4F, 0xF4, ++0x9E, 0x67, 0x4F, 0xF0, 0x00, 0x0B, 0x01, 0x95, 0x53, 0x49, 0xD9, 0xF8, 0x84, 0x33, 0x5F, 0xFA, 0x8B, 0xF8, 0x40, 0x46, ++0x4F, 0xF0, 0x80, 0x42, 0x39, 0x44, 0x98, 0x47, 0x4F, 0x4B, 0x9D, 0x68, 0xA7, 0xF1, 0x28, 0x04, 0xC5, 0xB1, 0xE9, 0x19, ++0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x40, 0x46, 0x98, 0x47, 0x29, 0x19, 0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, ++0x80, 0x42, 0x40, 0x46, 0x98, 0x47, 0x05, 0xF5, 0xA3, 0x61, 0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x40, 0x46, ++0x98, 0x47, 0x2D, 0x68, 0x00, 0x2D, 0xE6, 0xD1, 0x51, 0x46, 0xD9, 0xF8, 0x84, 0x33, 0x40, 0x46, 0x08, 0x37, 0x4F, 0xF0, ++0x80, 0x42, 0x98, 0x47, 0xB7, 0xF5, 0xA3, 0x6F, 0x0B, 0xF1, 0x01, 0x0B, 0x0A, 0xF1, 0x54, 0x0A, 0xC8, 0xD1, 0xD9, 0xF8, ++0x84, 0x33, 0x39, 0x49, 0x01, 0x9D, 0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0x37, 0x49, 0xD9, 0xF8, 0x84, 0x33, ++0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0x02, 0xF0, 0x30, 0xF9, 0x00, 0xF0, 0x6A, 0xF9, 0xD9, 0xF8, 0xCC, 0x33, ++0x98, 0x47, 0x2C, 0x48, 0x4F, 0xF4, 0x01, 0x72, 0x00, 0x21, 0xF1, 0xF7, 0x89, 0xF8, 0x2B, 0x4B, 0xD3, 0xF8, 0x08, 0x80, ++0x00, 0x9B, 0xA6, 0xF8, 0xFC, 0x31, 0xB8, 0xF1, 0x00, 0x0F, 0x17, 0xD0, 0x2B, 0x46, 0x45, 0x46, 0x98, 0x46, 0x05, 0xF5, ++0x9E, 0x64, 0x05, 0xF5, 0xA3, 0x67, 0x20, 0x46, 0x14, 0xF0, 0x06, 0xF9, 0xA4, 0xF1, 0x28, 0x00, 0x08, 0x34, 0x14, 0xF0, ++0x01, 0xF9, 0xBC, 0x42, 0xF5, 0xD1, 0x20, 0x46, 0x14, 0xF0, 0xFC, 0xF8, 0x2D, 0x68, 0x00, 0x2D, 0xEB, 0xD1, 0x45, 0x46, ++0x1B, 0x4F, 0x00, 0x24, 0x28, 0x46, 0x14, 0xF0, 0xF3, 0xF8, 0x45, 0xF8, 0x0C, 0x4C, 0xAC, 0x73, 0x85, 0xF8, 0x44, 0x40, ++0xC5, 0xE9, 0x06, 0x44, 0x05, 0xF1, 0x10, 0x00, 0x54, 0x35, 0x14, 0xF0, 0xE7, 0xF8, 0xAF, 0x42, 0xEE, 0xD1, 0x12, 0x48, ++0x14, 0xF0, 0xE2, 0xF8, 0x12, 0x48, 0xC6, 0xF8, 0xA4, 0x41, 0xC6, 0xE9, 0x72, 0x44, 0x86, 0xF8, 0xBE, 0x41, 0x86, 0xF8, ++0xF4, 0x41, 0x14, 0xF0, 0xD7, 0xF8, 0x0E, 0x4A, 0x00, 0x21, 0x02, 0xF5, 0xB4, 0x70, 0xA2, 0xF1, 0x24, 0x03, 0x43, 0xF8, ++0x04, 0x1B, 0x93, 0x42, 0xFB, 0xD1, 0x03, 0xF1, 0x24, 0x02, 0x90, 0x42, 0xF5, 0xD1, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x20, 0x62, 0x17, 0x00, 0x34, 0x5F, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xD0, 0x63, 0x17, 0x00, 0x4C, 0x64, 0x17, 0x00, ++0xE0, 0x63, 0x17, 0x00, 0xD8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x03, 0x8C, 0x08, 0x8C, 0x83, 0x42, 0x08, 0xD8, ++0x05, 0xD2, 0xC0, 0x1A, 0x3F, 0x28, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x51, 0xB9, 0x81, 0x6C, 0x90, 0xF8, 0x42, 0x30, 0xCB, 0x1A, 0x93, 0xF8, 0xB8, 0x30, 0xDB, 0x07, ++0x02, 0xD4, 0x03, 0x8B, 0x08, 0x2B, 0x00, 0xD0, 0x70, 0x47, 0x91, 0xF8, 0xA8, 0x30, 0x03, 0xF0, 0xF0, 0x03, 0x40, 0x2B, ++0xF8, 0xD1, 0x91, 0xF8, 0xB1, 0x30, 0x06, 0x2B, 0x01, 0xD0, 0x01, 0x2B, 0xF2, 0xD1, 0x13, 0x68, 0x01, 0x33, 0x13, 0x60, ++0xEE, 0xE7, 0x00, 0xBF, 0x03, 0x6D, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x43, 0x56, 0x4A, 0x12, 0x68, ++0x12, 0x78, 0x02, 0x2A, 0x83, 0xB0, 0x04, 0x46, 0x0D, 0x46, 0x07, 0xD0, 0x01, 0x2A, 0x7E, 0xD0, 0x03, 0x2A, 0x00, 0xF0, ++0x8D, 0x80, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0xFB, 0xF7, 0x8A, 0xFB, 0x06, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x94, 0x80, ++0xDF, 0xF8, 0x60, 0x91, 0x42, 0xF2, 0x24, 0x03, 0x59, 0xF8, 0x03, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x87, 0x80, 0x48, 0x48, ++0x14, 0xF0, 0xA8, 0xF8, 0x4F, 0xF0, 0x00, 0x08, 0x08, 0x22, 0x12, 0x23, 0x32, 0x70, 0x86, 0xF8, 0x01, 0x80, 0x86, 0xF8, ++0x03, 0x80, 0xB3, 0x70, 0x23, 0x6D, 0x29, 0x68, 0x00, 0x91, 0x23, 0xF0, 0x40, 0x43, 0x07, 0x46, 0x69, 0x46, 0x30, 0x1D, ++0x01, 0x93, 0x27, 0xF0, 0x49, 0xFF, 0x42, 0xF2, 0x34, 0x03, 0x39, 0xF8, 0x03, 0x30, 0xB3, 0xF5, 0xC3, 0x7F, 0x62, 0xD8, ++0x03, 0xF1, 0x01, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xDA, 0x00, 0x37, 0x49, 0xBB, 0x81, 0x09, 0x68, 0x36, 0x4B, 0x01, 0xEB, ++0x02, 0x0C, 0x42, 0xF2, 0x34, 0x08, 0xCC, 0xF8, 0x04, 0x60, 0x88, 0x58, 0x03, 0x40, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF0, ++0x0C, 0x03, 0x8B, 0x50, 0x99, 0xF8, 0x02, 0x3C, 0x29, 0xF8, 0x08, 0xE0, 0x01, 0x33, 0x01, 0x22, 0x00, 0x20, 0x0C, 0x21, ++0x89, 0xF8, 0x02, 0x3C, 0xC7, 0xF8, 0x04, 0xC0, 0xBA, 0x73, 0x38, 0x60, 0xB9, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x02, 0xD4, 0x72, 0xB6, 0x26, 0x4B, 0x1A, 0x60, 0x26, 0x4E, 0x2B, 0x68, 0x31, 0x68, 0x22, 0x8C, 0x25, 0x48, 0x4D, 0x1C, ++0x21, 0x46, 0x35, 0x60, 0x15, 0xF0, 0xEC, 0xF9, 0x23, 0x48, 0x39, 0x46, 0x14, 0xF0, 0x0E, 0xF8, 0x22, 0x4B, 0xD3, 0xF8, ++0x44, 0x34, 0x98, 0x47, 0x33, 0x68, 0x00, 0x2B, 0x8D, 0xD0, 0x1B, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x00, 0x2B, ++0x87, 0xD1, 0x00, 0x2A, 0x85, 0xD0, 0x62, 0xB6, 0x83, 0xE7, 0x0E, 0x68, 0x00, 0x96, 0x23, 0xF0, 0x40, 0x43, 0x69, 0x46, ++0x08, 0x22, 0x12, 0x20, 0x01, 0x93, 0xF9, 0xF7, 0xD7, 0xFA, 0x2B, 0x68, 0x22, 0x8C, 0x15, 0x48, 0x21, 0x46, 0x15, 0xF0, ++0xC7, 0xF9, 0x72, 0xE7, 0x13, 0x4B, 0x0A, 0x68, 0x1B, 0x68, 0x1A, 0x60, 0xF6, 0xF7, 0x72, 0xF8, 0x6B, 0xE7, 0x42, 0x46, ++0x43, 0x46, 0x4F, 0xF0, 0x01, 0x0E, 0x9C, 0xE7, 0x0E, 0x48, 0xF6, 0xF7, 0xED, 0xFF, 0x62, 0xE7, 0x0D, 0x48, 0xF6, 0xF7, ++0xE9, 0xFF, 0x5E, 0xE7, 0x78, 0x36, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, 0x00, 0x00, 0xFF, 0x31, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x90, 0x15, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x20, 0x90, 0x15, 0x00, 0x00, 0x38, 0x18, 0x00, 0xDC, 0x8F, 0x15, 0x00, 0xD8, 0x83, 0x15, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x10, 0xB5, 0x0D, 0x4C, 0x30, 0x22, 0x00, 0x21, 0x20, 0x46, 0xF0, 0xF7, 0x21, 0xFF, 0x20, 0x46, 0x13, 0xF0, 0xAE, 0xFF, ++0x04, 0xF1, 0x08, 0x00, 0x13, 0xF0, 0xAA, 0xFF, 0x04, 0xF1, 0x10, 0x00, 0x13, 0xF0, 0xA6, 0xFF, 0x04, 0xF1, 0x18, 0x00, ++0x13, 0xF0, 0xA2, 0xFF, 0x04, 0xF1, 0x20, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0xF0, 0x9C, 0xBF, 0x24, 0x64, 0x17, 0x00, ++0x38, 0xB5, 0xC3, 0x6C, 0x04, 0x46, 0x09, 0x48, 0x19, 0x61, 0x00, 0xEB, 0xC2, 0x00, 0x21, 0x46, 0x15, 0x46, 0x13, 0xF0, ++0x93, 0xFF, 0x63, 0x6A, 0x9B, 0x02, 0x00, 0xD5, 0x38, 0xBD, 0x04, 0x4B, 0x53, 0xF8, 0x25, 0x00, 0xBD, 0xE8, 0x38, 0x40, ++0x13, 0xF0, 0xE6, 0xBE, 0x24, 0x64, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x38, 0xB5, 0x38, 0x4B, 0x93, 0xF8, 0x8C, 0x20, ++0x05, 0x46, 0x00, 0x2A, 0x42, 0xD1, 0x43, 0x6D, 0xC3, 0xF3, 0xC1, 0x23, 0x54, 0x22, 0x1C, 0x21, 0x33, 0x48, 0x12, 0xFB, ++0x03, 0x13, 0x18, 0x44, 0x13, 0xF0, 0xB6, 0xFF, 0x04, 0x46, 0x31, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, ++0x01, 0xDB, 0x14, 0xB9, 0x38, 0xBD, 0x00, 0x2C, 0x4C, 0xD0, 0xA2, 0x88, 0x68, 0x6D, 0x42, 0xF0, 0x20, 0x02, 0x81, 0x01, ++0xA2, 0x80, 0xF5, 0xD5, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF3, 0xCF, 0x31, 0xC0, 0xF3, 0xC9, 0x33, 0x26, 0xDB, ++0x62, 0x7A, 0x10, 0x3B, 0x93, 0x42, 0xE9, 0xD1, 0xEB, 0x69, 0x99, 0x68, 0x0B, 0x8A, 0x03, 0xF0, 0x1E, 0x02, 0x16, 0x2A, ++0x25, 0xD0, 0x82, 0x05, 0xE0, 0xD4, 0x2A, 0x8E, 0x1C, 0x2A, 0xDD, 0xD1, 0xA2, 0x7A, 0xB2, 0xEB, 0x13, 0x3F, 0xD9, 0xD1, ++0x04, 0xF1, 0xE0, 0x05, 0x12, 0x31, 0x28, 0x46, 0x0A, 0x22, 0x27, 0xF0, 0x37, 0xFE, 0xC4, 0xF8, 0xDC, 0x50, 0x1A, 0xE0, ++0x93, 0xF8, 0x7E, 0x30, 0x05, 0x2B, 0xBB, 0xD1, 0x14, 0x48, 0x13, 0xF0, 0x77, 0xFF, 0x04, 0x46, 0xBF, 0xE7, 0x11, 0xF4, ++0x7C, 0x7F, 0xD5, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x10, 0x49, 0x11, 0x48, 0xD0, 0x22, 0x15, 0xF0, 0x49, 0xBB, 0x10, 0x4B, ++0x28, 0x46, 0xD3, 0xF8, 0xB4, 0x33, 0x21, 0x46, 0x98, 0x47, 0x00, 0x28, 0xB4, 0xD0, 0xA3, 0x88, 0x43, 0xF0, 0x40, 0x03, ++0xA3, 0x80, 0x38, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x06, 0x49, 0x09, 0x48, 0x40, 0xF2, 0x5F, 0x12, 0x15, 0xF0, 0x34, 0xBB, ++0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xE0, 0x63, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x50, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x3C, 0x90, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xB0, 0x4B, 0xB1, 0x4C, ++0x1B, 0x68, 0xB1, 0x4A, 0xB3, 0xF9, 0x00, 0x30, 0x2D, 0xED, 0x02, 0x8B, 0x87, 0xB0, 0x01, 0x46, 0x01, 0x90, 0x00, 0x2B, ++0x04, 0xEB, 0xC0, 0x00, 0x08, 0xEE, 0x10, 0x0A, 0x52, 0xF8, 0x21, 0x40, 0xC0, 0xF2, 0x38, 0x83, 0x20, 0x46, 0x13, 0xF0, ++0x6B, 0xFE, 0xA6, 0x4B, 0x01, 0x9A, 0x53, 0xF8, 0x32, 0x40, 0x00, 0x2C, 0x00, 0xF0, 0xAD, 0x80, 0x00, 0x23, 0xCD, 0xE9, ++0x04, 0x33, 0x9B, 0x46, 0x98, 0x46, 0xA2, 0x4B, 0x62, 0x7F, 0x93, 0xF8, 0x00, 0x32, 0x03, 0x92, 0x01, 0x2B, 0x22, 0x7F, ++0xE6, 0x6C, 0x67, 0x6C, 0x02, 0x92, 0x00, 0xF0, 0xA1, 0x80, 0x00, 0x2F, 0x00, 0xF0, 0xA8, 0x80, 0x3B, 0x79, 0xD8, 0x06, ++0x40, 0xF1, 0x95, 0x80, 0x35, 0x69, 0x59, 0x06, 0x25, 0xF4, 0x00, 0x05, 0x0B, 0xF1, 0x01, 0x0B, 0x35, 0x61, 0x00, 0xF1, ++0x9B, 0x81, 0xDF, 0xF8, 0x70, 0xA2, 0x00, 0x21, 0xDA, 0xF8, 0x18, 0x34, 0x20, 0x46, 0x98, 0x47, 0x63, 0x6A, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x08, 0xBF, 0xA0, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x8B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x38, 0x92, 0xD9, 0xF8, 0x00, 0x30, 0x18, 0xEE, 0x10, 0x0A, 0x01, 0x33, ++0xC9, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0xE4, 0xFE, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x60, 0x1F, 0x00, 0xF0, ++0x5F, 0x81, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x7F, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x22, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0x00, 0xF0, 0x30, 0x81, 0xE2, 0x6A, 0xD3, 0x6B, ++0x98, 0x06, 0x40, 0xF1, 0xFD, 0x80, 0x15, 0xF4, 0x00, 0x05, 0x00, 0xF0, 0x7E, 0x81, 0xE1, 0x6C, 0x4F, 0x6A, 0x39, 0x88, ++0x88, 0xB2, 0x09, 0x04, 0x00, 0xF1, 0xEB, 0x81, 0x71, 0x4F, 0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0x36, 0xD0, 0x63, 0x7F, ++0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x6B, 0x49, 0xA0, 0x88, ++0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x12, 0x1A, 0x41, 0xF8, 0x23, 0x20, 0x68, 0x4B, 0x93, 0xF8, 0x04, 0x31, ++0x13, 0xB1, 0x00, 0x2D, 0x40, 0xF0, 0x33, 0x82, 0x06, 0xF1, 0x10, 0x01, 0x20, 0x46, 0xFF, 0xF7, 0xC9, 0xFD, 0xE3, 0x8B, ++0xDA, 0x07, 0x00, 0xF1, 0x93, 0x81, 0xA0, 0x6C, 0x30, 0xB1, 0xF7, 0xF7, 0x4F, 0xFF, 0x3B, 0x68, 0x1D, 0x78, 0x01, 0x2D, ++0x00, 0xF0, 0xCB, 0x81, 0x9D, 0xF8, 0x04, 0x00, 0x21, 0x46, 0x15, 0xF0, 0x5B, 0xFB, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, ++0xB3, 0xF5, 0x60, 0x1F, 0x00, 0xF0, 0x74, 0x81, 0x4F, 0x4B, 0x01, 0x9A, 0x53, 0xF8, 0x32, 0x40, 0x00, 0x2C, 0x7F, 0xF4, ++0x58, 0xAF, 0x07, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0x4A, 0x00, 0x23, 0x40, 0x20, 0x82, 0xF8, ++0x00, 0x32, 0x13, 0xF0, 0x87, 0xFD, 0x00, 0x2F, 0x7F, 0xF4, 0x58, 0xAF, 0xEF, 0xF3, 0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x45, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x47, 0x4D, 0x2B, 0x68, 0x18, 0xEE, 0x10, 0x0A, 0x01, 0x33, 0x2B, 0x60, ++0x13, 0xF0, 0x5A, 0xFE, 0x2B, 0x68, 0x3B, 0xB1, 0x3E, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x13, 0xB9, 0x00, 0x2A, ++0x40, 0xF0, 0xF3, 0x81, 0x20, 0x46, 0xD6, 0xF8, 0x10, 0x90, 0x94, 0xF8, 0x1C, 0xA0, 0x23, 0xF0, 0x95, 0xFF, 0xE2, 0x6A, ++0xD3, 0x6B, 0x98, 0x06, 0x40, 0xF1, 0x8C, 0x80, 0x19, 0xF4, 0x00, 0x0F, 0x0C, 0xD0, 0xE1, 0x6C, 0x4D, 0x6A, 0x29, 0x88, ++0x88, 0xB2, 0x09, 0x04, 0x00, 0xF1, 0xFE, 0x81, 0x32, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x00, 0x2B, 0x40, 0xF0, 0x86, 0x80, ++0x31, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x53, 0x93, 0xF8, 0xC0, 0x24, 0x42, 0xB1, 0x93, 0xF8, 0xC1, 0x34, ++0x2D, 0x4F, 0x03, 0xEB, 0x83, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x07, 0xEB, 0x83, 0x07, 0x63, 0x7F, 0x09, 0x2B, 0x08, 0xD8, ++0xE3, 0x8B, 0x18, 0x07, 0x05, 0xD4, 0x09, 0xF4, 0x01, 0x09, 0xB9, 0xF5, 0x80, 0x3F, 0x00, 0xF0, 0x2B, 0x82, 0x25, 0x4F, ++0x9D, 0xF8, 0x04, 0x50, 0xD7, 0xF8, 0x18, 0x34, 0x00, 0x21, 0x20, 0x46, 0x98, 0x47, 0xD7, 0xF8, 0xAC, 0x33, 0x00, 0x22, ++0x29, 0x46, 0x20, 0x46, 0x98, 0x47, 0x22, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0x00, 0xF0, 0x05, 0x81, 0x63, 0x7F, ++0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x11, 0x49, 0xA0, 0x88, ++0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x12, 0x1A, 0x41, 0xF8, 0x23, 0x20, 0x06, 0xF1, 0x10, 0x01, 0x20, 0x46, ++0xFF, 0xF7, 0x1C, 0xFD, 0xE3, 0x8B, 0xDB, 0x07, 0x00, 0xF1, 0x08, 0x81, 0x21, 0x46, 0x28, 0x46, 0x15, 0xF0, 0xB8, 0xFA, ++0x62, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x24, 0x64, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xB7, 0x4F, 0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, ++0x3F, 0xF4, 0x44, 0xAF, 0x15, 0xF4, 0x00, 0x05, 0x7F, 0xF4, 0x09, 0xAF, 0xB4, 0xF9, 0x1E, 0x30, 0xE2, 0x8B, 0x00, 0x2B, ++0xC0, 0xF2, 0x81, 0x80, 0x00, 0x25, 0x00, 0xE7, 0xAF, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x00, 0x2B, 0x3F, 0xF4, 0x7E, 0xAF, ++0x19, 0xF4, 0x00, 0x0F, 0x3F, 0xF4, 0x7A, 0xAF, 0xE3, 0x8B, 0x1D, 0x07, 0x3F, 0xF5, 0x76, 0xAF, 0x23, 0x7F, 0xA9, 0x4D, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x53, 0x03, 0xF1, 0x98, 0x02, 0x93, 0xF8, 0x62, 0x10, 0x20, 0x46, 0xFF, 0xF7, ++0xAF, 0xFC, 0x68, 0xE7, 0x33, 0x69, 0x03, 0xF0, 0x0F, 0x03, 0x09, 0x2B, 0x7F, 0xF4, 0xCA, 0xAE, 0x03, 0x9B, 0xA0, 0x48, ++0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x00, 0x90, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x3F, 0xF6, 0xBF, 0xAE, 0xE2, 0x6C, ++0xB0, 0xF8, 0x5E, 0x12, 0xD2, 0x6A, 0x8A, 0x42, 0x3F, 0xF4, 0xB8, 0xAE, 0x01, 0x33, 0x80, 0xF8, 0x5D, 0x32, 0xA0, 0xF8, ++0x5E, 0x22, 0xB1, 0xE6, 0x95, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9B, 0x80, 0x59, 0x46, ++0x40, 0x46, 0x04, 0x9A, 0x23, 0xF0, 0xCA, 0xFE, 0x38, 0x46, 0x02, 0xF0, 0x9D, 0xF8, 0x00, 0x23, 0x04, 0x93, 0x9B, 0x46, ++0x98, 0x46, 0x8C, 0xE6, 0xD7, 0xF8, 0xDC, 0x20, 0xDA, 0xB1, 0x11, 0x88, 0x23, 0x8C, 0xA3, 0xEB, 0x11, 0x13, 0xC3, 0xF3, ++0x0B, 0x03, 0x40, 0xF2, 0xFE, 0x71, 0x8B, 0x42, 0x0C, 0xD8, 0x3F, 0x2B, 0x4F, 0xEA, 0x13, 0x11, 0x08, 0xD8, 0x02, 0xEB, ++0x41, 0x02, 0x03, 0xF0, 0x0F, 0x03, 0x52, 0x88, 0x42, 0xFA, 0x03, 0xF3, 0xDA, 0x07, 0x04, 0xD4, 0x4F, 0xF4, 0x80, 0x23, ++0x1D, 0x43, 0x35, 0x61, 0x45, 0xE6, 0x04, 0x9B, 0x01, 0x33, 0x04, 0x93, 0x4F, 0xF4, 0x04, 0x03, 0xF6, 0xE7, 0x75, 0x4F, ++0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0x3F, 0xF4, 0xBF, 0xAE, 0xB4, 0xF9, 0x1E, 0x30, 0xE2, 0x8B, 0x00, 0x2B, 0xBF, 0xF6, ++0x7F, 0xAF, 0x71, 0x4D, 0x02, 0x99, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x53, 0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, ++0x3F, 0xF4, 0x74, 0xAF, 0xE6, 0x6C, 0x01, 0x98, 0x00, 0x21, 0xC2, 0xF3, 0x0E, 0x03, 0x31, 0x65, 0x43, 0xF0, 0x01, 0x03, ++0x61, 0x64, 0x31, 0x61, 0x02, 0x9E, 0xE3, 0x83, 0x9E, 0x30, 0xA4, 0x23, 0x13, 0xFB, 0x06, 0x00, 0xE1, 0x62, 0x61, 0x62, ++0x65, 0x4A, 0x05, 0xEB, 0xC0, 0x00, 0x21, 0x46, 0x13, 0xF0, 0x60, 0xFD, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, ++0x60, 0x1F, 0x00, 0xF0, 0xE4, 0x80, 0x01, 0x23, 0x05, 0x93, 0x8B, 0xE6, 0x05, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0xDC, 0x80, ++0x40, 0x20, 0x13, 0xF0, 0x1F, 0xFC, 0x00, 0x23, 0x05, 0x93, 0x81, 0xE6, 0x40, 0x20, 0x13, 0xF0, 0x19, 0xFC, 0x68, 0xE6, ++0x33, 0x69, 0x03, 0xF0, 0x0F, 0x03, 0x09, 0x2B, 0x7F, 0xF4, 0xF5, 0xAE, 0x03, 0x9B, 0x51, 0x48, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x03, 0x00, 0x90, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x3F, 0xF6, 0xEA, 0xAE, 0xE2, 0x6C, 0xB0, 0xF8, 0x5E, 0x12, ++0xD2, 0x6A, 0x8A, 0x42, 0x3F, 0xF4, 0xE3, 0xAE, 0x01, 0x33, 0x80, 0xF8, 0x5D, 0x32, 0xA0, 0xF8, 0x5E, 0x22, 0xDC, 0xE6, ++0x40, 0x20, 0x13, 0xF0, 0xF7, 0xFB, 0xF3, 0xE6, 0xB8, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0x61, 0xAF, 0x44, 0x49, 0x45, 0x48, ++0x40, 0xF2, 0x3D, 0x22, 0x15, 0xF0, 0xE2, 0xF8, 0x59, 0xE7, 0x00, 0xF0, 0x0C, 0x00, 0x08, 0x28, 0x7F, 0xF4, 0x10, 0xAE, ++0xD7, 0xF8, 0x1A, 0x10, 0x01, 0xF0, 0x3F, 0x01, 0x07, 0x29, 0x7F, 0xF4, 0x09, 0xAE, 0x23, 0xF0, 0x20, 0x03, 0xD3, 0x63, ++0x04, 0xE6, 0x3B, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x06, 0x46, 0x00, 0x28, 0x3F, 0xF4, 0x2C, 0xAE, ++0xF7, 0xF7, 0x96, 0xFE, 0x07, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x02, 0x81, 0x00, 0x22, 0x34, 0x4B, 0x02, 0x60, 0x1B, 0x68, ++0x42, 0x60, 0x1E, 0x44, 0x82, 0x60, 0x06, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x2F, 0x4B, ++0x1D, 0x60, 0x2F, 0x49, 0xD9, 0xF8, 0x00, 0x20, 0x0B, 0x68, 0x01, 0x32, 0x43, 0xF0, 0x01, 0x03, 0xC9, 0xF8, 0x00, 0x20, ++0x0B, 0x60, 0x2A, 0x4B, 0x1B, 0x68, 0x9E, 0x07, 0xFB, 0xD4, 0x29, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xE4, 0x80, ++0x27, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xF0, 0x80, 0x25, 0x4B, 0x25, 0x4D, 0x1F, 0x60, 0x22, 0x48, 0xA9, 0x89, ++0x03, 0x68, 0x6F, 0x60, 0x01, 0x31, 0xA9, 0x81, 0x01, 0x33, 0x1E, 0x49, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, ++0x0B, 0x60, 0x00, 0x2A, 0x3F, 0xF4, 0xEC, 0xAD, 0x18, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, ++0x7F, 0xF4, 0xE4, 0xAD, 0x00, 0x2B, 0x3F, 0xF4, 0xE1, 0xAD, 0x62, 0xB6, 0xDE, 0xE5, 0x23, 0x7F, 0x09, 0x4D, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x03, 0x55, 0x05, 0xF1, 0x98, 0x02, 0x95, 0xF8, 0x62, 0x10, 0x20, 0x46, 0xFF, 0xF7, 0x70, 0xFB, ++0xBE, 0xE5, 0x62, 0xB6, 0x0A, 0xE6, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x61, 0xF1, 0x12, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x90, 0x15, 0x00, ++0x28, 0x60, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0x64, 0x00, 0x24, 0x40, ++0x68, 0x00, 0x24, 0x40, 0x10, 0x60, 0x17, 0x00, 0x00, 0xF0, 0x0C, 0x00, 0x08, 0x28, 0x7F, 0xF4, 0xFD, 0xAD, 0xD5, 0xF8, ++0x1A, 0x10, 0x01, 0xF0, 0x3F, 0x01, 0x07, 0x29, 0x7F, 0xF4, 0xF6, 0xAD, 0x23, 0xF0, 0x20, 0x03, 0xD3, 0x63, 0xF1, 0xE5, ++0x4E, 0x4D, 0x02, 0x9B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x03, 0x50, 0xFE, 0xF7, 0xB8, 0xFE, 0x00, 0x28, 0x3F, 0xF4, ++0x19, 0xAF, 0x4A, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0x13, 0xAF, 0x01, 0x9A, 0x02, 0x99, 0xA4, 0x23, ++0x02, 0xF1, 0x9E, 0x06, 0x13, 0xFB, 0x01, 0x66, 0x03, 0xFB, 0x01, 0x23, 0x03, 0xF1, 0x9E, 0x04, 0x05, 0xEB, 0xC6, 0x06, ++0xD7, 0xB2, 0xA1, 0x46, 0x0C, 0xE0, 0x13, 0xF0, 0x09, 0xFC, 0xDA, 0xF8, 0x24, 0x34, 0x20, 0x46, 0x39, 0x46, 0x98, 0x47, ++0x3B, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0xF6, 0xAE, 0x55, 0xF8, 0x39, 0x40, 0x30, 0x46, 0x00, 0x2C, ++0xED, 0xD1, 0xEF, 0xE6, 0x36, 0x4B, 0x1B, 0x68, 0x1C, 0x42, 0x7F, 0xF4, 0xC3, 0xAC, 0x35, 0x49, 0x35, 0x48, 0x4F, 0xF4, ++0xF2, 0x72, 0x14, 0xF0, 0xFD, 0xFF, 0xBB, 0xE4, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x0A, 0x59, 0x99, 0xF8, 0x64, 0x10, ++0x00, 0x29, 0x3F, 0xF4, 0xCC, 0xAD, 0x2F, 0x48, 0x03, 0x99, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, 0x01, 0x01, 0x91, 0xF8, ++0x24, 0x10, 0x01, 0x29, 0x0F, 0xD0, 0x99, 0x07, 0x2F, 0xD4, 0x00, 0x2A, 0x3F, 0xF4, 0xBD, 0xAD, 0x97, 0xF8, 0x70, 0x30, ++0x01, 0x2B, 0x7F, 0xF4, 0xB8, 0xAD, 0x97, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0xB3, 0xAD, 0xE3, 0x8B, 0xE1, 0x6C, ++0x01, 0x98, 0x22, 0x4A, 0xC3, 0xF3, 0x0E, 0x03, 0x00, 0x26, 0x43, 0xF0, 0x01, 0x03, 0x0E, 0x65, 0x0E, 0x61, 0x9E, 0x30, ++0xE3, 0x83, 0xA4, 0x23, 0x13, 0xFB, 0x0A, 0x00, 0x05, 0xEB, 0xC0, 0x00, 0xE6, 0x62, 0x21, 0x46, 0x13, 0xF0, 0xFE, 0xFB, ++0x40, 0x20, 0x13, 0xF0, 0xCB, 0xFA, 0x2F, 0xE5, 0x30, 0x46, 0xF7, 0xF7, 0x6B, 0xFC, 0x1F, 0xE5, 0x15, 0x4D, 0x6B, 0x68, ++0x9B, 0xB1, 0x5F, 0x60, 0x1E, 0xE7, 0xB4, 0xF8, 0x40, 0x00, 0x20, 0xF0, 0x75, 0xFC, 0x00, 0x28, 0xD6, 0xD0, 0x99, 0xF8, ++0xC0, 0x24, 0x00, 0x2A, 0x3F, 0xF4, 0x85, 0xAD, 0xC6, 0xE7, 0x0E, 0x48, 0x14, 0xF0, 0x2E, 0xFD, 0xD9, 0xF8, 0x00, 0x20, ++0x09, 0xE7, 0x0C, 0x48, 0x14, 0xF0, 0x28, 0xFD, 0xD9, 0xF8, 0x00, 0x20, 0x06, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x61, 0xF1, 0x12, 0x00, 0x10, 0x60, 0x17, 0x00, 0xA8, 0x90, 0x15, 0x00, 0xB0, 0x90, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x27, 0x4F, 0xDF, 0xF8, 0xA0, 0xA0, 0x91, 0x46, 0x06, 0x46, 0x0D, 0x46, 0x42, 0xF0, 0x70, 0x58, 0x28, 0x46, 0x13, 0xF0, ++0x6D, 0xFB, 0x04, 0x46, 0x80, 0xB1, 0x42, 0x6C, 0xC1, 0x6C, 0x00, 0x2A, 0x38, 0xD0, 0xC1, 0xF8, 0x10, 0x80, 0xA2, 0x88, ++0x62, 0xB9, 0x20, 0x46, 0x00, 0xF0, 0xA2, 0xF9, 0x28, 0x46, 0x13, 0xF0, 0x5D, 0xFB, 0x04, 0x46, 0x00, 0x28, 0xEE, 0xD1, ++0xBD, 0xE8, 0xF0, 0x47, 0x00, 0xF0, 0xBC, 0xB9, 0x0A, 0x69, 0x42, 0xF4, 0x00, 0x02, 0x41, 0xF8, 0x10, 0x2F, 0x20, 0x46, ++0xFF, 0xF7, 0x7E, 0xFA, 0xD7, 0xF8, 0x18, 0x34, 0x01, 0x21, 0x20, 0x46, 0x98, 0x47, 0x63, 0x7F, 0x09, 0x2B, 0x0D, 0xD8, ++0xE2, 0x7E, 0x08, 0x2A, 0x0A, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x03, 0xF6, 0x0E, 0x03, 0xA1, 0x88, 0x5A, 0xF8, ++0x23, 0x20, 0x52, 0x1A, 0x4A, 0xF8, 0x23, 0x20, 0x31, 0x46, 0x20, 0x46, 0xD7, 0xF8, 0x78, 0x33, 0x98, 0x47, 0x21, 0x46, ++0x30, 0x46, 0x15, 0xF0, 0x03, 0xF8, 0xBD, 0xE7, 0x0A, 0x69, 0x00, 0x2A, 0xA8, 0xBF, 0xC1, 0xF8, 0x10, 0x90, 0xC2, 0xE7, ++0x88, 0x1A, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x6C, 0x80, 0x92, 0x46, 0x06, 0x46, ++0x0F, 0x46, 0x42, 0xF0, 0x70, 0x59, 0x38, 0x46, 0x13, 0xF0, 0x18, 0xFB, 0x04, 0x46, 0xF0, 0xB1, 0x42, 0x6C, 0xC3, 0x6C, ++0x12, 0xB3, 0xC3, 0xF8, 0x10, 0x90, 0xA2, 0x88, 0x00, 0x21, 0x20, 0x46, 0xCA, 0xB1, 0x1D, 0x69, 0x45, 0xF4, 0x00, 0x05, ++0x1D, 0x61, 0xD8, 0xF8, 0x18, 0x34, 0x98, 0x47, 0xD8, 0xF8, 0x78, 0x33, 0x20, 0x46, 0x31, 0x46, 0x98, 0x47, 0x21, 0x46, ++0x30, 0x46, 0x14, 0xF0, 0xD1, 0xFF, 0x38, 0x46, 0x13, 0xF0, 0xFA, 0xFA, 0x04, 0x46, 0x00, 0x28, 0xE0, 0xD1, 0xBD, 0xE8, ++0xF0, 0x47, 0x00, 0xF0, 0x59, 0xB9, 0x00, 0xF0, 0x33, 0xF9, 0xD4, 0xE7, 0x1A, 0x69, 0x00, 0x2A, 0xA8, 0xBF, 0xC3, 0xF8, ++0x10, 0xA0, 0xD8, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x14, 0x46, 0x05, 0x46, 0x0F, 0x46, 0x60, 0x22, 0x00, 0x21, ++0x1E, 0x46, 0xF0, 0xF7, 0x07, 0xFA, 0x4F, 0xF0, 0x01, 0x0C, 0x85, 0xF8, 0x5C, 0xC0, 0x00, 0x23, 0x07, 0x49, 0x08, 0x4A, ++0xAF, 0x64, 0x07, 0xF1, 0x68, 0x00, 0xEE, 0x62, 0xEC, 0x64, 0xC4, 0xE9, 0x0F, 0x33, 0x60, 0x62, 0x61, 0x61, 0x23, 0x63, ++0x63, 0x64, 0x32, 0x60, 0xF8, 0xBD, 0x00, 0xBF, 0xBE, 0xBA, 0xFE, 0xCA, 0x1E, 0xAB, 0xDC, 0xBA, 0x2D, 0xE9, 0xF8, 0x4F, ++0x07, 0x46, 0x3C, 0x48, 0x3C, 0x4C, 0xDF, 0xF8, 0x08, 0xA1, 0x3C, 0x4E, 0x3C, 0x4D, 0xDF, 0xF8, 0x04, 0xB1, 0x81, 0x46, ++0x13, 0xF0, 0x70, 0xFA, 0x09, 0xF1, 0x08, 0x00, 0x13, 0xF0, 0x6C, 0xFA, 0x04, 0xF5, 0xC0, 0x78, 0x00, 0x21, 0x20, 0x46, ++0x60, 0x22, 0x17, 0xB1, 0x94, 0xF8, 0x5D, 0x30, 0xC3, 0xB9, 0xF0, 0xF7, 0xD1, 0xF9, 0x00, 0x22, 0x32, 0x4B, 0xC4, 0xF8, ++0x48, 0xA0, 0x0A, 0xF1, 0x68, 0x0C, 0xC5, 0xE9, 0x0F, 0x22, 0x21, 0x46, 0x48, 0x46, 0xE6, 0x62, 0xE5, 0x64, 0xC5, 0xF8, ++0x14, 0xB0, 0x33, 0x60, 0x84, 0xF8, 0x5C, 0x20, 0x2A, 0x63, 0x6A, 0x64, 0xC5, 0xF8, 0x24, 0xC0, 0x13, 0xF0, 0x4E, 0xFA, ++0x60, 0x34, 0xA0, 0x45, 0x0A, 0xF5, 0xF4, 0x7A, 0x06, 0xF1, 0x40, 0x06, 0x05, 0xF1, 0x58, 0x05, 0xD6, 0xD1, 0x24, 0x4E, ++0xDF, 0xF8, 0x88, 0x90, 0xC6, 0xF8, 0x00, 0x90, 0x00, 0x24, 0xC6, 0xE9, 0x0D, 0x44, 0xF4, 0x63, 0xF1, 0xF7, 0x8E, 0xFA, ++0x80, 0x03, 0x70, 0x60, 0xF1, 0xF7, 0x8A, 0xFA, 0x01, 0x27, 0x43, 0x1C, 0x07, 0xFA, 0x03, 0xF3, 0x1B, 0x4D, 0xDF, 0xF8, ++0x78, 0x80, 0xF4, 0x60, 0x01, 0x3B, 0xB3, 0x60, 0x4F, 0xF4, 0x80, 0x63, 0xC6, 0xE9, 0x04, 0x83, 0xC6, 0xE9, 0x06, 0x44, ++0x34, 0x62, 0xC5, 0xF8, 0x00, 0x90, 0xC6, 0xE9, 0x0A, 0x44, 0xC5, 0xE9, 0x0D, 0x44, 0x34, 0x63, 0xEC, 0x63, 0xF1, 0xF7, ++0x6F, 0xFA, 0x80, 0x03, 0x68, 0x60, 0xF1, 0xF7, 0x6B, 0xFA, 0x38, 0x44, 0x87, 0x40, 0x01, 0x3F, 0x04, 0x23, 0xC5, 0xE9, ++0x02, 0x74, 0xC5, 0xE9, 0x06, 0x44, 0xC5, 0xE9, 0x0A, 0x44, 0xC5, 0xF8, 0x10, 0x80, 0x2C, 0x62, 0x2C, 0x63, 0x6B, 0x61, ++0xBD, 0xE8, 0xF8, 0x8F, 0x54, 0x64, 0x17, 0x00, 0x90, 0x28, 0x17, 0x00, 0x84, 0x3B, 0x18, 0x00, 0x04, 0x3D, 0x18, 0x00, ++0x1E, 0xAB, 0xDC, 0xBA, 0xC4, 0x3C, 0x18, 0x00, 0x84, 0x3C, 0x18, 0x00, 0x4C, 0x50, 0x18, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, ++0x04, 0x07, 0xFF, 0xFF, 0xF8, 0xB5, 0xD0, 0xE9, 0x12, 0x64, 0x63, 0x6A, 0x05, 0x46, 0x50, 0x1E, 0x03, 0x44, 0x04, 0x32, ++0xC4, 0xE9, 0x0A, 0x32, 0xC1, 0xB1, 0x01, 0x29, 0x1A, 0xD0, 0x06, 0xF1, 0x28, 0x01, 0x0F, 0x46, 0x34, 0x22, 0x38, 0x46, ++0x27, 0xF0, 0xD8, 0xF8, 0x0B, 0x4A, 0x13, 0x68, 0x12, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0x00, 0x22, ++0xF3, 0x64, 0xC4, 0xE9, 0x0D, 0x27, 0xE2, 0x64, 0x22, 0x62, 0xC5, 0xE9, 0x15, 0x22, 0xF8, 0xBD, 0x04, 0x49, 0x06, 0xF1, ++0x28, 0x07, 0xE7, 0xE7, 0x03, 0x49, 0x06, 0xF1, 0x28, 0x07, 0xE3, 0xE7, 0xA0, 0x00, 0x32, 0x40, 0xC4, 0x3C, 0x18, 0x00, ++0x84, 0x3C, 0x18, 0x00, 0x70, 0xB5, 0x05, 0x46, 0x05, 0x48, 0x0E, 0x46, 0x13, 0xF0, 0xFE, 0xF9, 0x04, 0x46, 0x18, 0xB1, ++0x32, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0xC2, 0xFF, 0x20, 0x46, 0x70, 0xBD, 0x54, 0x64, 0x17, 0x00, 0x16, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x2D, 0xE9, 0xF0, 0x41, 0xC4, 0x6C, 0x00, 0x2B, 0x62, 0x6A, 0x05, 0x46, 0x0E, 0x46, 0x16, 0xDB, ++0xE3, 0x6C, 0x11, 0x4F, 0x23, 0xF4, 0xF0, 0x03, 0xE3, 0x64, 0x00, 0x23, 0xC4, 0xE9, 0x06, 0x33, 0x12, 0x79, 0x23, 0x65, ++0x12, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x4F, 0xF4, 0x00, 0x73, 0xA3, 0x64, 0xD7, 0xF8, 0x98, 0x33, 0x31, 0x46, 0x28, 0x46, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xD3, 0x07, 0xE6, 0xD5, 0x4F, 0xF4, 0xB1, 0x72, 0x05, 0x49, 0x05, 0x48, 0x14, 0xF0, ++0xD9, 0xFD, 0x62, 0x6A, 0xDE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xDC, 0x90, 0x15, 0x00, 0x08, 0xB5, 0x01, 0x46, 0x04, 0x48, 0x13, 0xF0, 0x75, 0xF9, 0xBD, 0xE8, 0x08, 0x40, 0x4F, 0xF4, ++0x80, 0x20, 0x13, 0xF0, 0xCD, 0xB8, 0x00, 0xBF, 0x5C, 0x64, 0x17, 0x00, 0x70, 0xB5, 0x90, 0xF8, 0x5C, 0x30, 0x04, 0x46, ++0x0D, 0x46, 0x43, 0xB1, 0x35, 0xB1, 0x63, 0x6D, 0x23, 0xB1, 0xA0, 0x6D, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, ++0x70, 0xBD, 0x01, 0x46, 0x01, 0x48, 0x13, 0xF0, 0x59, 0xF9, 0xF1, 0xE7, 0x54, 0x64, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x4F, 0xF4, 0x80, 0x20, 0x13, 0xF0, 0xD2, 0xF8, 0xDF, 0xF8, 0x88, 0x80, 0x1D, 0x4F, 0x1E, 0x4E, 0x1E, 0x4D, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x30, 0x46, 0x01, 0x33, ++0xC8, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0x80, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0x04, 0x46, 0x33, 0xB1, 0x01, 0x3B, 0x3A, 0x68, ++0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD4, 0xB1, 0xD5, 0xF8, 0xF8, 0x31, 0x62, 0x6D, 0x01, 0x3B, ++0xC5, 0xF8, 0xF8, 0x31, 0x32, 0xB1, 0xE3, 0x6C, 0xA0, 0x6D, 0x19, 0x6D, 0x90, 0x47, 0x94, 0xF8, 0x5E, 0x30, 0x43, 0xB9, ++0x94, 0xF8, 0x5C, 0x30, 0x00, 0x2B, 0xD2, 0xD1, 0x08, 0x48, 0x21, 0x46, 0x13, 0xF0, 0x1A, 0xF9, 0xCD, 0xE7, 0x00, 0x23, ++0x84, 0xF8, 0x5E, 0x30, 0xC9, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x5C, 0x64, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x54, 0x64, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x78, 0x91, ++0x58, 0x4D, 0x80, 0x46, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x08, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x90, 0xF8, 0x22, 0xA0, ++0x03, 0xFB, 0x0A, 0x53, 0x0F, 0x46, 0x1B, 0x6C, 0x16, 0x46, 0x00, 0x2B, 0x00, 0xF0, 0x98, 0x80, 0x50, 0x49, 0x1A, 0x79, ++0x0B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5A, 0xDB, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x53, 0x18, 0x21, ++0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xFF, 0xF7, 0x1E, 0xFF, 0x04, 0x46, 0x00, 0x28, ++0x59, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x55, 0x28, 0x46, 0x21, 0x46, 0x12, 0xF0, 0x11, 0xF8, 0x95, 0xF8, ++0x62, 0x20, 0xA3, 0x6C, 0x02, 0x2A, 0x4F, 0xD0, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x08, 0x92, 0xE8, 0x6D, 0x52, 0xF8, ++0x26, 0x1F, 0xB5, 0xF8, 0x60, 0xC0, 0xB2, 0xF8, 0x04, 0xE0, 0x15, 0x68, 0xD9, 0x66, 0x91, 0x88, 0xA3, 0xF8, 0x7C, 0x10, ++0x00, 0x22, 0x9D, 0x67, 0x01, 0x21, 0x48, 0x25, 0xA3, 0xF8, 0x70, 0xE0, 0xC3, 0xF8, 0x72, 0x00, 0xA3, 0xF8, 0x76, 0xC0, ++0x83, 0xF8, 0x6A, 0x20, 0x83, 0xF8, 0x6B, 0x20, 0x83, 0xF8, 0x68, 0x50, 0x83, 0xF8, 0x69, 0x10, 0x2E, 0x49, 0xB1, 0xF8, ++0xFC, 0x51, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x08, 0x99, 0x01, 0x35, 0xAD, 0xB2, 0xA1, 0xF8, 0xFC, 0x51, 0x99, 0xF8, ++0x22, 0x20, 0x2D, 0x01, 0xA3, 0xF8, 0x7E, 0x50, 0x20, 0x46, 0xC4, 0xE9, 0x15, 0x76, 0x22, 0x77, 0x84, 0xF8, 0x1D, 0x80, ++0x05, 0x21, 0xFF, 0xF7, 0xE3, 0xFE, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x02, 0x2A, 0xA2, 0xD1, 0x20, 0x49, 0x21, 0x48, ++0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0xDC, 0xFC, 0x01, 0x20, 0x18, 0x21, 0xFF, 0xF7, 0xC4, 0xFE, 0x04, 0x46, 0x00, 0x28, ++0xA5, 0xD1, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x08, 0x91, 0xE8, 0x6D, 0x51, 0xF8, ++0x26, 0xEF, 0x83, 0xF8, 0x69, 0x20, 0x89, 0x88, 0xA3, 0xF8, 0x70, 0x10, 0x00, 0x22, 0xB5, 0xF8, 0x60, 0x10, 0xC3, 0xF8, ++0x72, 0x00, 0x4F, 0xF0, 0x48, 0x0C, 0xE8, 0x6D, 0x83, 0xF8, 0x6A, 0x20, 0x83, 0xF8, 0x6B, 0x20, 0xB5, 0xF8, 0x60, 0x20, ++0xC3, 0xF8, 0x6C, 0xE0, 0x83, 0xF8, 0x68, 0xC0, 0xA3, 0xF8, 0x76, 0x10, 0x98, 0x67, 0xA3, 0xF8, 0x7C, 0x20, 0xAD, 0xE7, ++0x04, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCB, 0xDA, 0xC4, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x38, 0xB1, 0x49, 0x4C, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0xB5, 0x06, 0x46, ++0x95, 0xF8, 0x22, 0x70, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x07, 0x40, 0x98, 0x46, 0x00, 0x6C, 0x43, 0x4B, 0x8A, 0x46, ++0x91, 0x46, 0x00, 0x28, 0x7A, 0xD0, 0x1B, 0x68, 0x02, 0x79, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x62, 0xDB, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x07, 0x43, 0x1A, 0x21, 0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, ++0xFF, 0xF7, 0x5C, 0xFE, 0x05, 0x46, 0x00, 0x28, 0x61, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x47, 0x38, 0x46, ++0x29, 0x46, 0x11, 0xF0, 0x4F, 0xFF, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0xB3, 0xAC, 0x6C, 0x53, 0xF8, 0x26, 0x1F, ++0x97, 0xF8, 0x62, 0xC0, 0xB3, 0xF8, 0x04, 0xE0, 0xF8, 0x6D, 0xB7, 0xF8, 0x60, 0x20, 0xA4, 0xF8, 0x76, 0x20, 0x00, 0x23, ++0xA4, 0xF8, 0x70, 0xE0, 0xE1, 0x66, 0xC4, 0xF8, 0x72, 0x00, 0x84, 0xF8, 0x6A, 0x30, 0x84, 0xF8, 0x6B, 0x30, 0xBC, 0xF1, ++0x00, 0x0F, 0x22, 0xD0, 0xF8, 0x6D, 0xA0, 0x67, 0x6F, 0xF0, 0x37, 0x01, 0x02, 0x23, 0xA4, 0xF8, 0x7C, 0x20, 0x84, 0xF8, ++0x68, 0x10, 0x84, 0xF8, 0x69, 0x30, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0xBB, 0x00, 0x27, 0x9B, 0xF8, 0x22, 0x30, ++0xA4, 0xF8, 0x80, 0xA0, 0x84, 0xF8, 0x7E, 0x70, 0x84, 0xF8, 0x7F, 0x70, 0x28, 0x46, 0xC5, 0xE9, 0x15, 0x98, 0x2B, 0x77, ++0x6E, 0x77, 0x05, 0x21, 0xFF, 0xF7, 0x24, 0xFE, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x6F, 0xF0, 0x37, 0x02, 0x01, 0x23, ++0xA1, 0x67, 0xA4, 0xF8, 0x7C, 0xE0, 0x84, 0xF8, 0x68, 0x20, 0x84, 0xF8, 0x69, 0x30, 0xDC, 0xE7, 0x02, 0x2A, 0x9A, 0xD1, ++0x0C, 0x49, 0x0D, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0x12, 0xFC, 0x01, 0x20, 0x1A, 0x21, 0xFF, 0xF7, 0xFA, 0xFD, ++0x05, 0x46, 0x00, 0x28, 0x9D, 0xD1, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xF0, 0xDA, 0xE9, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x9C, 0xA1, 0xDF, 0xF8, 0x9C, 0x81, 0x4F, 0xF4, 0x1E, 0x76, ++0x06, 0xFB, 0x00, 0xA6, 0x05, 0x46, 0x96, 0xF8, 0x22, 0x90, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x09, 0x80, 0x83, 0xB0, ++0x00, 0x6C, 0x00, 0x93, 0x0E, 0x1E, 0x17, 0x46, 0x9D, 0xF8, 0x30, 0x40, 0x9D, 0xF8, 0x34, 0xB0, 0x55, 0x4A, 0x0C, 0xBF, ++0x1E, 0x23, 0x1D, 0x23, 0x00, 0x28, 0x00, 0xF0, 0x9D, 0x80, 0x12, 0x68, 0x01, 0x79, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, ++0xC0, 0xF2, 0x85, 0x80, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x82, 0x92, 0xF8, 0xC0, 0x24, 0x0A, 0x43, 0x14, 0xBF, ++0x01, 0x20, 0x00, 0x20, 0x19, 0x46, 0xFF, 0xF7, 0xAF, 0xFD, 0x03, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x81, 0x80, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x09, 0x88, 0xD0, 0xF8, 0x48, 0x90, 0x01, 0x93, 0x40, 0x46, 0x19, 0x46, 0x11, 0xF0, 0x9E, 0xFE, ++0xD9, 0xF8, 0x38, 0x00, 0x01, 0x9B, 0x40, 0x4A, 0x99, 0x6C, 0xB8, 0xF8, 0x60, 0xE0, 0x00, 0x0C, 0x4F, 0xF0, 0x00, 0x0C, ++0x46, 0xEA, 0x07, 0x17, 0x00, 0x04, 0xC9, 0xF8, 0x38, 0x00, 0xD8, 0xF8, 0x5C, 0x00, 0x8F, 0x67, 0x81, 0xF8, 0x7C, 0xC0, ++0x81, 0xF8, 0x7D, 0xC0, 0x81, 0xF8, 0x7E, 0xC0, 0x81, 0xF8, 0x7F, 0xC0, 0x92, 0xF8, 0x43, 0x70, 0xDF, 0xF8, 0xE8, 0x80, ++0xC1, 0xF8, 0x72, 0x00, 0x24, 0x20, 0xB8, 0xF8, 0x04, 0x20, 0xA1, 0xF8, 0x76, 0xE0, 0x81, 0xF8, 0x68, 0x00, 0xD8, 0xF8, ++0x00, 0xE0, 0xA1, 0xF8, 0x70, 0x20, 0xB8, 0x06, 0xC1, 0xF8, 0x6C, 0xE0, 0x81, 0xF8, 0x69, 0xC0, 0x81, 0xF8, 0x6A, 0xC0, ++0x81, 0xF8, 0x6B, 0xC0, 0xC7, 0xF3, 0x40, 0x12, 0x0B, 0xD5, 0x27, 0x48, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x05, 0x02, ++0x52, 0x78, 0x12, 0xF0, 0x20, 0x0F, 0x0C, 0xBF, 0x62, 0x46, 0x4F, 0xF4, 0x80, 0x12, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x05, 0xA5, 0x64, 0x05, 0x28, 0x8C, 0x00, 0x9D, 0x44, 0xEA, 0x45, 0x34, 0x04, 0x43, 0x14, 0x43, 0xD8, 0x22, 0xC1, 0xF8, ++0x80, 0x40, 0x81, 0xF8, 0x84, 0x20, 0x6E, 0xB1, 0x0E, 0x9A, 0x5A, 0x65, 0x0F, 0x9A, 0x9A, 0x65, 0x59, 0x46, 0x18, 0x46, ++0xFF, 0xF7, 0x54, 0xFD, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x4A, 0x12, 0xF8, ++0x0B, 0x20, 0x92, 0x01, 0x81, 0xF8, 0x85, 0x20, 0xEA, 0xE7, 0x02, 0x29, 0x7F, 0xF4, 0x78, 0xAF, 0x0E, 0x48, 0x0F, 0x49, ++0x01, 0x93, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0x41, 0xFB, 0x01, 0x9B, 0x01, 0x20, 0x77, 0xE7, 0x01, 0x20, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xEC, 0xDB, 0x01, 0x20, 0x6C, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x62, 0x66, 0x17, 0x00, 0xA0, 0xB2, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xAC, 0xB2, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0x90, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x77, 0xD1, 0x03, 0x6C, 0x04, 0x46, 0x89, 0x46, 0x00, 0x2B, 0x79, 0xD0, 0x40, 0x4A, ++0x1B, 0x79, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x51, 0xDB, 0x94, 0xF8, 0xC0, 0x24, 0xDF, 0xF8, 0x08, 0x81, ++0x13, 0x43, 0xB8, 0xF8, 0x00, 0x10, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xFF, 0xF7, 0xEE, 0xFC, 0x06, 0x46, 0x00, 0x28, ++0x54, 0xD0, 0x01, 0x46, 0x20, 0x46, 0x11, 0xF0, 0xE5, 0xFD, 0xB5, 0x6C, 0x00, 0x27, 0x50, 0x23, 0x49, 0x46, 0x85, 0xF8, ++0x68, 0x30, 0x85, 0xF8, 0x69, 0x70, 0x85, 0xF8, 0x6A, 0x70, 0x85, 0xF8, 0x6B, 0x70, 0x05, 0xF1, 0x6C, 0x00, 0x06, 0x22, ++0x26, 0xF0, 0x90, 0xFD, 0x2B, 0x49, 0xE0, 0x6D, 0xB1, 0xF8, 0xFC, 0x31, 0xB4, 0xF8, 0x60, 0xC0, 0xB8, 0xF8, 0x00, 0x20, ++0xB4, 0xF8, 0x60, 0xE0, 0xC5, 0xF8, 0x72, 0x00, 0x01, 0x33, 0x9B, 0xB2, 0xE0, 0x6D, 0xA5, 0xF8, 0x76, 0xC0, 0x4F, 0xEA, ++0x03, 0x1C, 0xA8, 0x67, 0xA5, 0xF8, 0x7C, 0xE0, 0x18, 0x3A, 0xA1, 0xF8, 0xFC, 0x31, 0x05, 0xF1, 0x80, 0x00, 0xA5, 0xF8, ++0x7E, 0xC0, 0x1E, 0x49, 0x26, 0xF0, 0x70, 0xFD, 0xC6, 0xE9, 0x15, 0x77, 0x94, 0xF8, 0x63, 0x30, 0x33, 0x77, 0xFF, 0x23, ++0x73, 0x77, 0x30, 0x46, 0x05, 0x21, 0xFF, 0xF7, 0xBB, 0xFC, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x2B, 0xAB, 0xD1, ++0x15, 0x49, 0x16, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0xB4, 0xFA, 0xDF, 0xF8, 0x58, 0x80, 0x01, 0x20, 0xB8, 0xF8, ++0x00, 0x10, 0xFF, 0xF7, 0x99, 0xFC, 0x06, 0x46, 0x00, 0x28, 0xAA, 0xD1, 0xB8, 0xF8, 0x00, 0x10, 0x0E, 0x48, 0x14, 0xF0, ++0x2B, 0xF8, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x48, 0x19, 0x46, 0x14, 0xF0, 0x24, 0xF8, 0x01, 0x20, 0xBD, 0xE8, ++0xF8, 0x83, 0x03, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE0, 0xDA, 0xD9, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x2C, 0x2A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0x28, 0x91, 0x15, 0x00, ++0x14, 0x91, 0x15, 0x00, 0x14, 0x2C, 0x17, 0x00, 0x02, 0x4B, 0x40, 0xEA, 0x41, 0x01, 0x33, 0xF8, 0x11, 0x00, 0x70, 0x47, ++0xA0, 0x92, 0x15, 0x00, 0x02, 0x4B, 0x40, 0xEA, 0x41, 0x01, 0x58, 0x5C, 0x70, 0x47, 0x00, 0xBF, 0x40, 0x93, 0x15, 0x00, ++0xF0, 0xB4, 0x1D, 0x4C, 0x1D, 0x4D, 0x1E, 0x4F, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x02, 0x42, 0x16, 0x46, 0x92, 0xF8, ++0x22, 0x40, 0x4F, 0xF4, 0xA4, 0x6C, 0x0C, 0xFB, 0x04, 0x54, 0x56, 0xF8, 0x26, 0x5F, 0xB4, 0xF8, 0x60, 0xC0, 0x02, 0x46, ++0xE0, 0x6D, 0xB4, 0x88, 0xA2, 0xF8, 0x9C, 0x40, 0x00, 0x24, 0x54, 0x65, 0xC2, 0xF8, 0x8C, 0x40, 0x3C, 0x68, 0x3E, 0x68, ++0x9D, 0xF8, 0x10, 0x70, 0xC2, 0xF8, 0x9E, 0x00, 0x24, 0x02, 0xF6, 0xB2, 0x1B, 0x03, 0xA4, 0xB2, 0x40, 0xF6, 0x08, 0x00, ++0x34, 0x43, 0x40, 0xEA, 0xC7, 0x10, 0x43, 0xF0, 0x04, 0x03, 0x09, 0x01, 0xC2, 0xF8, 0x98, 0x50, 0xC2, 0xF8, 0xCC, 0x40, ++0xA2, 0xF8, 0xA2, 0xC0, 0xF0, 0xBC, 0xA2, 0xF8, 0xA4, 0x30, 0xA2, 0xF8, 0xA6, 0x10, 0xC2, 0xF8, 0xBC, 0x00, 0x70, 0x47, ++0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0xC2, 0x6C, 0x53, 0x6A, 0x13, 0xB3, 0x12, 0x49, ++0x12, 0x4B, 0xC9, 0x6E, 0x10, 0xB5, 0x04, 0x46, 0x18, 0x68, 0x63, 0x6A, 0x92, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, ++0x60, 0x1F, 0x42, 0xF8, 0x03, 0x1C, 0x08, 0xD0, 0xB0, 0xF9, 0x00, 0x30, 0x24, 0x68, 0x00, 0x2B, 0x04, 0xDB, 0xE2, 0x6C, ++0x53, 0x6A, 0x00, 0x2B, 0xED, 0xD1, 0x10, 0xBD, 0x00, 0x2C, 0xF8, 0xD1, 0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xF9, 0x22, ++0x14, 0xF0, 0x0E, 0xFA, 0xE3, 0x6C, 0xFF, 0xDE, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x04, 0x46, 0x9D, 0xF8, 0x48, 0x00, ++0x67, 0x6C, 0x07, 0x90, 0x9B, 0x46, 0x05, 0x28, 0x4F, 0xF0, 0x00, 0x03, 0x06, 0x91, 0x03, 0x92, 0x9A, 0x46, 0x00, 0xF0, ++0x12, 0x81, 0xAA, 0x4A, 0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x04, 0x93, 0xDF, 0xF8, ++0xC8, 0x92, 0xA6, 0x48, 0x12, 0xF0, 0xD4, 0xFD, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, ++0xC0, 0xF2, 0xF3, 0x80, 0xBB, 0x88, 0xAB, 0x80, 0x7B, 0x7A, 0x6B, 0x72, 0xBB, 0x7A, 0xAB, 0x72, 0x01, 0x23, 0xEB, 0x72, ++0xD7, 0xE9, 0x10, 0xC0, 0xFE, 0x6A, 0x79, 0x69, 0x3A, 0x6B, 0xEE, 0x62, 0x00, 0x23, 0x1E, 0x46, 0x69, 0x61, 0x6B, 0x62, ++0x19, 0x46, 0x98, 0x46, 0x02, 0x93, 0x05, 0xF1, 0x0C, 0x03, 0xC5, 0xE9, 0x10, 0xC0, 0x2A, 0x63, 0x05, 0x93, 0x01, 0x96, ++0x53, 0xE0, 0x9B, 0x45, 0x40, 0xF2, 0xB4, 0x80, 0xAB, 0xEB, 0x03, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x0A, 0xF1, 0x03, 0x0A, ++0x4F, 0xEA, 0x9A, 0x0A, 0x03, 0xEB, 0x8A, 0x03, 0x9B, 0xB2, 0x03, 0x9E, 0x19, 0x44, 0xB1, 0x42, 0x5A, 0xD8, 0xB8, 0xF1, ++0x00, 0x0F, 0x57, 0xD1, 0xDE, 0xF8, 0x24, 0x00, 0x28, 0xB1, 0x87, 0x4E, 0xDE, 0xF8, 0x28, 0x00, 0xF6, 0x6E, 0x40, 0xF8, ++0x03, 0x6C, 0xDC, 0x45, 0x65, 0x64, 0x0D, 0xD2, 0xDE, 0xF8, 0x4C, 0x20, 0x22, 0xF4, 0xFF, 0x22, 0x22, 0xF4, 0xC0, 0x62, ++0x42, 0xEA, 0x4A, 0x22, 0x42, 0xF4, 0x80, 0x70, 0x62, 0x62, 0x63, 0x46, 0xCE, 0xF8, 0x4C, 0x00, 0x69, 0x62, 0x79, 0x6A, ++0x02, 0xF4, 0x60, 0x12, 0xCB, 0x1A, 0xB2, 0xF5, 0x60, 0x1F, 0x7B, 0x62, 0x00, 0xF0, 0xAA, 0x80, 0x77, 0x4A, 0xD9, 0xF8, ++0x00, 0x30, 0x11, 0x68, 0x76, 0x4A, 0x91, 0xF8, 0x3E, 0x80, 0x12, 0x68, 0xB3, 0xF9, 0x00, 0x10, 0x23, 0x68, 0x02, 0xF0, ++0x3F, 0x02, 0x90, 0x45, 0x94, 0xBF, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x01, 0x08, 0x00, 0x29, 0x5D, 0xDB, 0x01, 0x9A, ++0x69, 0x6A, 0x02, 0x94, 0x01, 0x32, 0x01, 0x92, 0x1C, 0x46, 0xD4, 0xF8, 0x4C, 0xE0, 0x62, 0x6A, 0xDE, 0xF8, 0x2C, 0x30, ++0x9D, 0xF8, 0x04, 0x00, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0xC2, 0xF3, 0x49, 0x2C, 0x03, 0xEB, ++0x8C, 0x0C, 0x1F, 0xFA, 0x8C, 0xFC, 0xDC, 0x45, 0x97, 0xD3, 0x03, 0x9E, 0x63, 0x46, 0x19, 0x44, 0xB1, 0x42, 0xA4, 0xD9, ++0x02, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0xA2, 0x80, 0x02, 0x9B, 0x5B, 0x6A, 0x03, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x20, 0x1F, ++0x41, 0xD0, 0x02, 0x9E, 0xF2, 0x6C, 0x43, 0xF4, 0x60, 0x11, 0x43, 0xF4, 0x60, 0x13, 0x50, 0x73, 0xC5, 0xF8, 0x38, 0x61, ++0x73, 0x62, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x41, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x00, 0x2B, 0xD1, 0x64, ++0xD0, 0x61, 0x3D, 0xDB, 0x04, 0x9A, 0x92, 0xF8, 0x50, 0x30, 0x01, 0x33, 0x82, 0xF8, 0x50, 0x30, 0x63, 0x6A, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x60, 0x1F, 0x73, 0xD0, 0x1C, 0x32, 0x16, 0x46, 0x48, 0x4B, 0x06, 0x9A, 0x1B, 0x68, 0x14, 0x60, ++0x5B, 0x78, 0x13, 0xB9, 0x63, 0x6C, 0x0C, 0x33, 0x2B, 0x61, 0x29, 0x46, 0x30, 0x46, 0x12, 0xF0, 0xE7, 0xFC, 0x05, 0x98, ++0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2B, 0x9F, 0xD1, 0x40, 0x49, 0x40, 0x48, 0x02, 0x93, 0x40, 0xF2, 0xBD, 0x32, ++0x14, 0xF0, 0x0A, 0xF9, 0x02, 0x9B, 0x96, 0xE7, 0x4F, 0xF0, 0x00, 0x0A, 0x53, 0xE7, 0x02, 0x9E, 0x3B, 0x4B, 0x01, 0x21, ++0xD3, 0xF8, 0x58, 0x33, 0x30, 0x46, 0x98, 0x47, 0xF3, 0x6C, 0x75, 0x64, 0x14, 0x33, 0x05, 0x93, 0xD9, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC1, 0xDA, 0x04, 0x9B, 0xDB, 0x69, 0x9F, 0x42, 0xBD, 0xD0, 0x2F, 0x49, 0x32, 0x48, ++0x40, 0xF2, 0xC3, 0x32, 0x14, 0xF0, 0xEA, 0xF8, 0xB6, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0x0A, 0xAF, 0x2A, 0x49, 0x2E, 0x48, ++0x40, 0xF2, 0x27, 0x32, 0x14, 0xF0, 0xE0, 0xF8, 0x02, 0xE7, 0x2C, 0x4B, 0x04, 0x93, 0xF2, 0xE6, 0xD9, 0xF8, 0x00, 0x30, ++0xC5, 0xF8, 0x38, 0x41, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x16, 0xDB, 0x04, 0x9E, 0x1C, 0x36, 0x30, 0x46, 0x12, 0xF0, ++0xBF, 0xFC, 0x1E, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0x0B, 0xB9, 0x3B, 0x69, 0x2B, 0x61, 0x39, 0x46, 0xD7, 0xF8, 0x48, 0x01, ++0x12, 0xF0, 0x70, 0xFC, 0x06, 0x99, 0x22, 0x68, 0xE3, 0x6C, 0x0A, 0x60, 0x00, 0x22, 0xDA, 0x61, 0xA1, 0xE7, 0x04, 0x9B, ++0xDB, 0x69, 0xBB, 0x42, 0xE4, 0xD0, 0x14, 0x49, 0x16, 0x48, 0x40, 0xF2, 0xC3, 0x32, 0x14, 0xF0, 0xB3, 0xF8, 0xDD, 0xE7, ++0x04, 0x9E, 0x1C, 0x36, 0x30, 0x46, 0x12, 0xF0, 0x9D, 0xFC, 0x87, 0xE7, 0x0F, 0x4B, 0x07, 0x99, 0xD3, 0xF8, 0xBC, 0x33, ++0x07, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0x02, 0x9B, 0xD5, 0xF8, 0x48, 0x01, 0x05, 0x93, 0x29, 0x46, 0x12, 0xF0, 0x4A, 0xFC, ++0x85, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x8C, 0x64, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, ++0x54, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x64, 0x91, 0x15, 0x00, 0x4C, 0x91, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x0C, 0x46, 0x41, 0x7F, 0x63, 0x7F, 0x99, 0x42, 0x85, 0xB0, 0x05, 0xD1, 0xE3, 0x7E, 0x16, 0x46, 0xC2, 0x7E, 0x9A, 0x42, ++0x05, 0x46, 0x03, 0xD0, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD4, 0xE9, 0x11, 0x73, 0x00, 0x2B, 0x00, 0xF0, ++0x8F, 0x80, 0xBB, 0x88, 0x13, 0xF0, 0x08, 0x00, 0xF3, 0xD0, 0x13, 0xF0, 0x02, 0x00, 0xF0, 0xD0, 0x13, 0xF0, 0x01, 0x00, ++0x40, 0xF0, 0x86, 0x80, 0xDF, 0xF8, 0x4C, 0x91, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x93, 0x93, 0xF8, 0x4D, 0x20, 0x01, 0x2A, ++0xE3, 0xD0, 0xD3, 0xF8, 0x34, 0x80, 0xD8, 0xE9, 0x12, 0xBA, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0xDA, 0xF8, 0x20, 0x20, ++0x46, 0x4B, 0x12, 0x68, 0x9A, 0x42, 0xD6, 0xD1, 0x45, 0x4A, 0x46, 0x4B, 0x11, 0x68, 0x1A, 0x68, 0x91, 0xF8, 0x3E, 0x30, ++0x91, 0xF8, 0x3F, 0x10, 0x02, 0xF0, 0x3F, 0x02, 0x0B, 0x44, 0x9A, 0x42, 0xC8, 0xDD, 0xD8, 0xF8, 0x24, 0x20, 0x54, 0x23, ++0x03, 0xFB, 0x06, 0x93, 0x42, 0xF4, 0x60, 0x12, 0x18, 0x6B, 0xC8, 0xF8, 0x24, 0x20, 0xC7, 0xF8, 0x38, 0x81, 0x03, 0x93, ++0x03, 0xF0, 0xE0, 0xF8, 0x39, 0x4A, 0x03, 0x9B, 0x12, 0x68, 0x93, 0xF8, 0x4D, 0x10, 0x8A, 0xF8, 0x0D, 0x10, 0x52, 0x78, ++0x00, 0x2A, 0x4F, 0xD1, 0xEB, 0x6C, 0x3A, 0x61, 0xD9, 0x6C, 0xCA, 0xE9, 0x06, 0x22, 0x8A, 0x02, 0x44, 0xD5, 0x6B, 0x6C, ++0x07, 0xF1, 0x0C, 0x01, 0x19, 0x61, 0x54, 0x23, 0x03, 0xFB, 0x06, 0xF3, 0x0A, 0xF1, 0x14, 0x00, 0x09, 0xEB, 0x03, 0x02, ++0x49, 0xF8, 0x03, 0x00, 0x01, 0x23, 0xC2, 0xE9, 0x01, 0x13, 0xD8, 0xF8, 0x24, 0x30, 0xBA, 0x88, 0x43, 0xF4, 0x80, 0x73, ++0xCA, 0xF8, 0x4C, 0x30, 0x42, 0xF0, 0x01, 0x03, 0xBB, 0x80, 0xBB, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x50, 0x07, 0x06, 0xD4, ++0x11, 0x07, 0x37, 0xD4, 0xA1, 0x6C, 0x4A, 0x6A, 0x42, 0xF0, 0x04, 0x02, 0x4A, 0x62, 0x9B, 0x07, 0x06, 0xD5, 0x54, 0x23, ++0x03, 0xFB, 0x06, 0x93, 0x3A, 0x6B, 0x1B, 0x6B, 0x9B, 0x6A, 0x53, 0x61, 0x54, 0x24, 0x04, 0xFB, 0x06, 0x90, 0x04, 0xFB, ++0x06, 0x96, 0x1C, 0x30, 0x39, 0x46, 0x12, 0xF0, 0x91, 0xFB, 0x96, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x33, 0xF2, 0x62, ++0x86, 0xF8, 0x50, 0x30, 0x01, 0x20, 0x68, 0xE7, 0xBB, 0x88, 0x72, 0xE7, 0x01, 0x20, 0x64, 0xE7, 0x07, 0xF1, 0x0C, 0x01, ++0x99, 0x61, 0xBA, 0xE7, 0xB8, 0x7A, 0x93, 0xF8, 0x4E, 0x30, 0x7A, 0x7A, 0xB8, 0xF8, 0x22, 0x10, 0x00, 0x93, 0x03, 0x46, ++0x38, 0x46, 0xFF, 0xF7, 0x55, 0xFD, 0x07, 0xF1, 0x50, 0x03, 0xCA, 0xF8, 0x1C, 0x30, 0xB6, 0xE7, 0x42, 0xF0, 0x03, 0x03, ++0xBB, 0x80, 0xC8, 0xE7, 0xDE, 0xFA, 0xFE, 0xCA, 0xC8, 0x35, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x45, 0x6C, 0x0C, 0x68, 0x6E, 0x7A, 0x60, 0x7F, 0x9D, 0xF8, 0x20, 0x70, ++0x86, 0x42, 0x03, 0xD1, 0xAE, 0x7A, 0xE0, 0x7E, 0x86, 0x42, 0x02, 0xD0, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xE6, 0x6C, ++0xD5, 0xF8, 0x38, 0xE1, 0xD6, 0xF8, 0x24, 0xC0, 0xDE, 0xF8, 0x4C, 0x80, 0xBC, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x82, 0x80, ++0xBC, 0xF8, 0x00, 0x90, 0x19, 0xF4, 0x00, 0x4F, 0x1F, 0xFA, 0x89, 0xF0, 0x7A, 0xD1, 0x6F, 0xEA, 0x40, 0x40, 0x6F, 0xEA, ++0x50, 0x40, 0xAC, 0xF8, 0x00, 0x00, 0x94, 0xF8, 0x33, 0x90, 0x94, 0xF8, 0x32, 0x00, 0x09, 0xF1, 0x04, 0x09, 0x04, 0x30, ++0x84, 0xF8, 0x33, 0x90, 0x84, 0xF8, 0x32, 0x00, 0xF0, 0x6A, 0x00, 0xF1, 0x04, 0x0A, 0xB0, 0x6A, 0x00, 0xF1, 0x04, 0x09, ++0xC6, 0xE9, 0x0A, 0x9A, 0x0A, 0xF1, 0x03, 0x00, 0x20, 0xF0, 0x03, 0x00, 0x04, 0x30, 0x80, 0xB2, 0x83, 0x42, 0x5C, 0xD9, ++0xA3, 0xEB, 0x00, 0x09, 0x1F, 0xFA, 0x89, 0xF9, 0x09, 0xF1, 0x03, 0x09, 0x4F, 0xEA, 0x99, 0x09, 0x00, 0xEB, 0x89, 0x00, ++0x80, 0xB2, 0x6B, 0x6A, 0x18, 0x44, 0x90, 0x42, 0xBA, 0xD8, 0x28, 0x4A, 0xDE, 0xF8, 0x24, 0x30, 0x4F, 0xF0, 0x54, 0x0A, ++0x0A, 0xFB, 0x07, 0x27, 0x23, 0xF4, 0xC0, 0x13, 0x97, 0xF8, 0x50, 0x20, 0xDF, 0xF8, 0x90, 0xA0, 0x01, 0x3A, 0x87, 0xF8, ++0x50, 0x20, 0x43, 0xF4, 0x40, 0x12, 0xCE, 0xF8, 0x24, 0x20, 0x62, 0x6A, 0xDA, 0xF8, 0x00, 0x70, 0xD4, 0xF8, 0x00, 0xE0, ++0x22, 0xF4, 0xC0, 0x12, 0x42, 0xEA, 0x49, 0x29, 0x43, 0xF4, 0x40, 0x13, 0x49, 0xF4, 0xF0, 0x0A, 0x43, 0xF4, 0x80, 0x73, ++0xC8, 0xF8, 0x4C, 0x30, 0x49, 0xF4, 0xF0, 0x02, 0x00, 0x23, 0x4A, 0xF4, 0x80, 0x7A, 0x06, 0xF1, 0x14, 0x09, 0xC8, 0xF8, ++0x1C, 0x90, 0x62, 0x62, 0xC6, 0xF8, 0x4C, 0xA0, 0xB3, 0x61, 0xB3, 0x63, 0x68, 0x62, 0x65, 0x64, 0xC5, 0xF8, 0x38, 0x41, ++0xC1, 0xF8, 0x00, 0xE0, 0x7B, 0x78, 0x03, 0xB9, 0x2B, 0x61, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0x09, 0x4A, 0xB3, 0x6A, ++0xD2, 0x6E, 0x43, 0xF8, 0x03, 0x2C, 0x98, 0xF8, 0x0D, 0x30, 0x01, 0x33, 0x73, 0x73, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, ++0xD6, 0xF8, 0x2C, 0xA0, 0x9A, 0xE7, 0x4F, 0xF0, 0x00, 0x09, 0xAA, 0xE7, 0x20, 0x62, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x85, 0xB0, 0xD1, 0xF8, 0x00, 0xB0, 0x9D, 0xF8, 0x38, 0x90, 0xDF, 0xF8, ++0x20, 0xA1, 0xDB, 0xF8, 0x44, 0x60, 0xDA, 0xF8, 0x60, 0x43, 0x03, 0x93, 0x0F, 0x46, 0x90, 0x46, 0x59, 0x46, 0x4A, 0x46, ++0x05, 0x46, 0xA0, 0x47, 0x00, 0x28, 0x60, 0xD0, 0xE9, 0x6C, 0x03, 0x9B, 0xCA, 0x6A, 0x02, 0xF1, 0x03, 0x0E, 0x2E, 0xF0, ++0x03, 0x0E, 0x0E, 0xF1, 0x04, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0x73, 0x45, 0x01, 0xF1, 0x14, 0x0C, 0x54, 0xD8, 0x00, 0x20, ++0x72, 0x6A, 0x0E, 0xEB, 0x02, 0x03, 0x43, 0x45, 0x05, 0xD9, 0x34, 0x4A, 0x12, 0x68, 0x02, 0xF0, 0x3F, 0x02, 0x11, 0x2A, ++0x5D, 0xD9, 0x32, 0x4A, 0x6C, 0x6A, 0x4F, 0xF0, 0x54, 0x0E, 0x0E, 0xFB, 0x09, 0x22, 0x24, 0xF4, 0xC0, 0x14, 0x92, 0xF8, ++0x50, 0xE0, 0x44, 0xEA, 0x40, 0x24, 0x0E, 0xF1, 0xFF, 0x30, 0x82, 0xF8, 0x50, 0x00, 0x44, 0xF4, 0xD0, 0x0E, 0x72, 0x69, ++0xCA, 0x61, 0xC6, 0xF8, 0x14, 0xC0, 0x73, 0x62, 0xC5, 0xF8, 0x24, 0xE0, 0xDB, 0xF8, 0x24, 0x20, 0xD6, 0xF8, 0x38, 0xC1, ++0x6E, 0x64, 0x22, 0xF4, 0xC0, 0x12, 0x74, 0x46, 0x42, 0xF4, 0x40, 0x10, 0xDB, 0xF8, 0x4C, 0xE0, 0xDC, 0xF8, 0x4C, 0xC0, ++0x44, 0xF4, 0x80, 0x74, 0xCC, 0x64, 0x42, 0xF4, 0x40, 0x12, 0x40, 0xF4, 0x80, 0x70, 0x00, 0x24, 0x8C, 0x63, 0xCB, 0xF8, ++0x24, 0x20, 0xCE, 0xF8, 0x4C, 0x00, 0x9C, 0xF8, 0x0D, 0x20, 0x43, 0x45, 0x02, 0xF1, 0x01, 0x02, 0x8C, 0xF8, 0x0D, 0x20, ++0x16, 0xD9, 0xDA, 0xF8, 0x70, 0x63, 0x03, 0x9B, 0xCD, 0xF8, 0x00, 0x90, 0x42, 0x46, 0x39, 0x46, 0x28, 0x46, 0xB0, 0x47, ++0x20, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA3, 0xEB, 0x0E, 0x04, 0xA4, 0xB2, 0x03, 0x34, 0xA0, 0x08, 0x0E, 0xEB, ++0x80, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xA1, 0xE7, 0x58, 0x46, 0xFF, 0xF7, 0x53, 0xFC, 0xD6, 0xF8, 0x38, 0x31, 0x1B, 0x68, ++0x3B, 0x60, 0x01, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, ++0x54, 0x83, 0x32, 0x40, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, ++0x05, 0x46, 0x89, 0xB0, 0x6E, 0x6C, 0x9D, 0xF8, 0x50, 0x40, 0x04, 0x91, 0x0F, 0x46, 0x1C, 0x20, 0x54, 0x21, 0x11, 0xFB, ++0x04, 0x01, 0xD6, 0xF8, 0x38, 0x01, 0x06, 0x90, 0xAB, 0x48, 0x05, 0x94, 0x41, 0x18, 0x3C, 0x68, 0x01, 0x92, 0x08, 0x46, ++0x08, 0xEE, 0x10, 0x1A, 0x07, 0x93, 0xD4, 0xF8, 0x44, 0x80, 0xD4, 0xF8, 0x4C, 0x90, 0x12, 0xF0, 0x41, 0xFA, 0xA5, 0x4B, ++0x05, 0x9A, 0xD3, 0xF8, 0x60, 0x33, 0x28, 0x46, 0x21, 0x46, 0x98, 0x47, 0x00, 0x23, 0x02, 0x93, 0x00, 0x28, 0x00, 0xF0, ++0xF8, 0x80, 0xDF, 0xF8, 0x98, 0xA2, 0x9F, 0x48, 0xDA, 0xF8, 0x00, 0x20, 0x03, 0x68, 0x92, 0xF8, 0x3E, 0x20, 0x03, 0xF0, ++0x3F, 0x03, 0x9A, 0x42, 0x00, 0xF2, 0xFD, 0x80, 0x06, 0x9A, 0x04, 0x9D, 0x53, 0x6A, 0x2D, 0x68, 0x03, 0x90, 0x17, 0x46, ++0x23, 0xF4, 0xC0, 0x13, 0xD2, 0x6C, 0x43, 0xF4, 0x40, 0x11, 0x09, 0xF1, 0x14, 0x0C, 0x92, 0xF8, 0x0D, 0xB0, 0xC2, 0xF8, ++0x1C, 0xC0, 0x79, 0x62, 0x61, 0x6A, 0x07, 0x9F, 0x43, 0xF4, 0x40, 0x13, 0x21, 0xF4, 0xC0, 0x11, 0x43, 0xF4, 0x80, 0x73, ++0x41, 0xF4, 0x40, 0x11, 0xD3, 0x64, 0x61, 0x62, 0x6B, 0x6A, 0x43, 0xF4, 0x80, 0x73, 0xC9, 0xF8, 0x4C, 0x30, 0x02, 0x9B, ++0x99, 0x46, 0x4C, 0xE0, 0x9F, 0x42, 0x40, 0xF2, 0x93, 0x80, 0xFA, 0x1A, 0x92, 0xB2, 0x03, 0x32, 0x4F, 0xEA, 0x92, 0x09, ++0x03, 0xEB, 0x89, 0x03, 0x9B, 0xB2, 0x72, 0x6A, 0x01, 0x98, 0x1A, 0x44, 0x82, 0x42, 0x53, 0xD8, 0x03, 0x9D, 0xDA, 0xF8, ++0x00, 0x00, 0x2D, 0x68, 0x90, 0xF8, 0x3E, 0x00, 0x05, 0xF0, 0x3F, 0x05, 0xA8, 0x42, 0x49, 0xD8, 0xDC, 0xF8, 0x24, 0x00, ++0x28, 0xB1, 0x79, 0x4D, 0xDC, 0xF8, 0x28, 0x00, 0xED, 0x6E, 0x40, 0xF8, 0x03, 0x5C, 0xBE, 0x45, 0x66, 0x64, 0x0D, 0xD2, ++0xDC, 0xF8, 0x4C, 0x10, 0x21, 0xF4, 0xFF, 0x21, 0x21, 0xF4, 0xC0, 0x61, 0x41, 0xEA, 0x49, 0x21, 0x41, 0xF4, 0x80, 0x70, ++0x61, 0x62, 0x73, 0x46, 0xCC, 0xF8, 0x4C, 0x00, 0x72, 0x62, 0xD8, 0xF8, 0x24, 0x20, 0x01, 0xF4, 0x60, 0x11, 0xD3, 0x1A, ++0xB1, 0xF5, 0x60, 0x1F, 0xC8, 0xF8, 0x24, 0x30, 0x59, 0xD0, 0x69, 0x4B, 0x25, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x0B, 0xF1, 0x01, 0x0B, 0x00, 0x2B, 0x5F, 0xFA, 0x8B, 0xFB, 0x42, 0xDB, 0x69, 0x6A, 0x02, 0x94, 0x2C, 0x46, 0xD4, 0xF8, ++0x4C, 0xC0, 0xDC, 0xF8, 0x2C, 0x30, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0xC1, 0xF3, 0x49, 0x2E, ++0x03, 0xEB, 0x8E, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xBE, 0x45, 0xA1, 0xD3, 0x72, 0x6A, 0x01, 0x98, 0x73, 0x46, 0x1A, 0x44, ++0x82, 0x42, 0xAB, 0xD9, 0xDD, 0xF8, 0x08, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x7E, 0xD0, 0xD9, 0xF8, 0x4C, 0x10, 0x81, 0xF8, ++0x0D, 0xB0, 0xD9, 0xF8, 0x24, 0x30, 0xC6, 0xF8, 0x38, 0x91, 0x43, 0xF4, 0x60, 0x12, 0xC9, 0xF8, 0x24, 0x20, 0x62, 0x6A, ++0x43, 0xF4, 0x60, 0x13, 0x02, 0xF4, 0x60, 0x12, 0x43, 0xF4, 0x80, 0x73, 0x00, 0x20, 0xB2, 0xF5, 0x60, 0x1F, 0xCB, 0x64, ++0xC8, 0x61, 0x60, 0xD0, 0x48, 0x4B, 0x04, 0x9A, 0x1B, 0x68, 0x14, 0x60, 0x5D, 0x78, 0x00, 0x2D, 0x47, 0xD1, 0x63, 0x6C, ++0x0C, 0x33, 0x33, 0x61, 0x2C, 0xE0, 0x00, 0x2D, 0xBA, 0xD1, 0x43, 0x49, 0x43, 0x48, 0x40, 0xF2, 0xF4, 0x52, 0x13, 0xF0, ++0x7D, 0xFD, 0xB3, 0xE7, 0x4F, 0xF0, 0x00, 0x09, 0x71, 0xE7, 0x05, 0x9A, 0x11, 0x46, 0x37, 0x4A, 0x54, 0x23, 0x03, 0xFB, ++0x01, 0x23, 0x3A, 0x49, 0x93, 0xF8, 0x50, 0x20, 0x09, 0x68, 0xC6, 0xF8, 0x38, 0x41, 0x01, 0x3A, 0x83, 0xF8, 0x50, 0x20, ++0x4B, 0x78, 0x43, 0xB3, 0x18, 0xEE, 0x10, 0x0A, 0x12, 0xF0, 0x54, 0xF9, 0x41, 0x46, 0xD8, 0xF8, 0x48, 0x01, 0x12, 0xF0, ++0x0B, 0xF9, 0x04, 0x99, 0x22, 0x68, 0xE3, 0x6C, 0x0A, 0x60, 0x00, 0x22, 0xDA, 0x61, 0x01, 0x25, 0x18, 0xEE, 0x10, 0x0A, ++0x31, 0x46, 0x12, 0xF0, 0x23, 0xF9, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x05, 0x46, ++0x31, 0x46, 0x18, 0xEE, 0x10, 0x0A, 0x12, 0xF0, 0x17, 0xF9, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0x25, 0xE6, 0xE7, 0xD8, 0xF8, 0x10, 0x30, 0x33, 0x61, 0xD2, 0xE7, 0x18, 0xEE, 0x10, 0x0A, 0x31, 0x46, ++0x12, 0xF0, 0x06, 0xF9, 0x02, 0x9D, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0xEE, ++0x10, 0x0A, 0x12, 0xF0, 0x1B, 0xF9, 0x99, 0xE7, 0x06, 0x99, 0x4A, 0x6A, 0xCD, 0x6C, 0x42, 0xF4, 0x60, 0x13, 0xC5, 0xF8, ++0x1C, 0x90, 0x4B, 0x62, 0x63, 0x6A, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0x20, 0x17, 0x42, 0xF4, 0x60, 0x12, 0x43, 0xF4, ++0x20, 0x13, 0x42, 0xF4, 0x80, 0x72, 0x47, 0xF4, 0x80, 0x77, 0xEA, 0x64, 0x18, 0xEE, 0x10, 0x0A, 0x63, 0x62, 0x31, 0x46, ++0xCC, 0xF8, 0x4C, 0x70, 0x12, 0xF0, 0xDC, 0xF8, 0x04, 0x9B, 0x4D, 0x46, 0x1C, 0x60, 0xB4, 0xE7, 0x20, 0x62, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xA4, 0x91, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x82, 0x69, 0x03, 0x32, 0x22, 0xF0, 0x03, 0x02, ++0x04, 0x32, 0x93, 0xB2, 0x99, 0x42, 0x04, 0xD9, 0xC8, 0x1A, 0x80, 0xB2, 0x03, 0x30, 0x80, 0x08, 0x70, 0x47, 0x00, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, 0x43, 0x4A, 0x44, 0x4B, 0x11, 0x68, 0x18, 0x68, 0x88, 0x42, 0x08, 0xD0, ++0xD2, 0xE9, 0x01, 0x54, 0xD2, 0xE9, 0x03, 0x02, 0xC3, 0xE9, 0x00, 0x15, 0xC3, 0xE9, 0x02, 0x40, 0x1A, 0x61, 0x3E, 0x48, ++0x3C, 0x4D, 0x3E, 0x4F, 0xDF, 0xF8, 0x04, 0x81, 0x30, 0x22, 0x00, 0x21, 0x06, 0x46, 0xEE, 0xF7, 0xE3, 0xFF, 0x05, 0xF1, ++0x18, 0x09, 0x3B, 0x68, 0x55, 0xF8, 0x04, 0x0B, 0x4F, 0xF4, 0xAC, 0x72, 0x02, 0xFB, 0x03, 0xF2, 0x00, 0x21, 0xEE, 0xF7, ++0xD7, 0xFF, 0x57, 0xF8, 0x04, 0x3B, 0x00, 0x2B, 0x58, 0xDD, 0x4F, 0xF0, 0x00, 0x0B, 0xDA, 0x46, 0x55, 0xF8, 0x04, 0x4C, ++0x30, 0x4B, 0x5C, 0x44, 0x05, 0x20, 0x04, 0xF1, 0xA8, 0x01, 0x63, 0x64, 0x2E, 0x4B, 0xC4, 0xF8, 0xA8, 0x30, 0x84, 0xF8, ++0x97, 0x00, 0x04, 0xF1, 0x94, 0x03, 0x04, 0xF1, 0xAB, 0x00, 0x61, 0x67, 0x18, 0x21, 0x6F, 0xF0, 0x7B, 0x0C, 0x23, 0x66, ++0x60, 0x66, 0x4F, 0xF4, 0xC0, 0x63, 0x40, 0xF2, 0x43, 0x10, 0xA1, 0x66, 0x00, 0x21, 0xC4, 0xE9, 0x21, 0x30, 0xC4, 0xE9, ++0x0D, 0x11, 0xC4, 0xE9, 0x16, 0x11, 0xC4, 0xE9, 0x1E, 0x11, 0x84, 0xF8, 0x94, 0xC0, 0x84, 0xF8, 0x95, 0x10, 0x84, 0xF8, ++0x96, 0x10, 0xA1, 0x62, 0xE1, 0x63, 0xE1, 0x66, 0xC4, 0xF8, 0x80, 0x10, 0x21, 0x67, 0xC4, 0xF8, 0x48, 0x61, 0xC4, 0xF8, ++0x0C, 0x80, 0xC4, 0xF8, 0x50, 0x80, 0xF0, 0xF7, 0x7F, 0xF8, 0x80, 0x03, 0xC4, 0xF8, 0xAC, 0x00, 0xF0, 0xF7, 0x7A, 0xF8, ++0x4F, 0xF0, 0x01, 0x0C, 0x01, 0x30, 0x0C, 0xFA, 0x00, 0xF0, 0x12, 0x4B, 0xC4, 0xF8, 0xB8, 0x30, 0x01, 0x38, 0x00, 0x21, ++0xC4, 0xE9, 0x2C, 0x01, 0x21, 0x46, 0x30, 0x46, 0x12, 0xF0, 0x16, 0xF8, 0x57, 0xF8, 0x04, 0x1C, 0x0A, 0xF1, 0x01, 0x0A, ++0x8A, 0x45, 0x0B, 0xF5, 0xAC, 0x7B, 0xA9, 0xDB, 0x4D, 0x45, 0x06, 0xF1, 0x08, 0x06, 0x94, 0xD1, 0xBD, 0xE8, 0xF8, 0x8F, ++0xEC, 0x57, 0x18, 0x00, 0x74, 0x1F, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x00, 0x01, 0x20, 0x00, ++0x1E, 0xAB, 0xDC, 0xBA, 0x04, 0x07, 0xFF, 0xFF, 0xBE, 0xBA, 0xFE, 0xCA, 0x2D, 0xE9, 0xF8, 0x43, 0x18, 0x4A, 0x19, 0x4B, ++0x11, 0x68, 0x18, 0x68, 0x88, 0x42, 0x08, 0xD0, 0xD2, 0xE9, 0x01, 0x54, 0xD2, 0xE9, 0x03, 0x02, 0xC3, 0xE9, 0x00, 0x15, ++0xC3, 0xE9, 0x02, 0x40, 0x1A, 0x61, 0x13, 0x4C, 0x13, 0x4F, 0x11, 0x4E, 0x04, 0xF1, 0x30, 0x09, 0x20, 0x46, 0x11, 0xF0, ++0xDB, 0xFF, 0x57, 0xF8, 0x04, 0x3B, 0x00, 0x2B, 0x0E, 0xDD, 0x00, 0x25, 0xA8, 0x46, 0x31, 0x68, 0x20, 0x46, 0x29, 0x44, ++0x11, 0xF0, 0xD4, 0xFF, 0x57, 0xF8, 0x04, 0x3C, 0x08, 0xF1, 0x01, 0x08, 0x98, 0x45, 0x05, 0xF5, 0xAC, 0x75, 0xF2, 0xDB, ++0x08, 0x34, 0x4C, 0x45, 0x06, 0xF1, 0x04, 0x06, 0xE4, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0xEC, 0x57, 0x18, 0x00, ++0x74, 0x1F, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x28, 0x82, 0xB0, ++0x06, 0x46, 0x00, 0xF0, 0xBD, 0x80, 0x6A, 0x4C, 0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, ++0x94, 0xF8, 0x4D, 0x30, 0xE7, 0x6A, 0x65, 0x6B, 0x01, 0x2B, 0x69, 0xD1, 0xD5, 0xE9, 0x12, 0x38, 0x00, 0x22, 0x4F, 0xF4, ++0x80, 0x71, 0x6A, 0x62, 0xC8, 0xF8, 0x1C, 0x20, 0xC8, 0xF8, 0x4C, 0x10, 0x00, 0x2B, 0x4C, 0xD0, 0xBA, 0x88, 0x11, 0x07, ++0x49, 0xD5, 0xD3, 0xE9, 0x17, 0x21, 0x28, 0x33, 0xC8, 0xF8, 0x34, 0x10, 0xC8, 0xF8, 0x48, 0x20, 0xC8, 0xF8, 0x38, 0x30, ++0x2B, 0x7F, 0x58, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x63, 0xBB, 0x55, 0x4A, ++0x6B, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x5B, 0x68, 0x9A, 0x06, 0x23, 0xD5, 0xEB, 0x8B, 0x13, 0xF4, ++0x00, 0x5F, 0xEB, 0x6A, 0xDB, 0x6B, 0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0xC3, 0xB9, 0xD8, 0xF8, ++0x24, 0x10, 0x0B, 0x88, 0x9A, 0xB2, 0x1B, 0x04, 0x12, 0xD5, 0xC2, 0xF3, 0x0E, 0x02, 0x0A, 0x80, 0x95, 0xF8, 0x33, 0x20, ++0x95, 0xF8, 0x32, 0x30, 0x04, 0x3A, 0x04, 0x3B, 0x85, 0xF8, 0x33, 0x20, 0x85, 0xF8, 0x32, 0x30, 0xD8, 0xE9, 0x0A, 0x32, ++0x04, 0x3A, 0x04, 0x3B, 0xC8, 0xE9, 0x0A, 0x32, 0x28, 0x46, 0x02, 0xF0, 0x71, 0xFC, 0x3E, 0x4B, 0x08, 0xF1, 0x14, 0x01, ++0xD3, 0xF8, 0x9C, 0x33, 0x32, 0x46, 0x08, 0x46, 0x98, 0x47, 0xD7, 0xF8, 0x48, 0x01, 0x39, 0x46, 0x11, 0xF0, 0x4A, 0xFF, ++0x00, 0x23, 0x6B, 0x64, 0x94, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x33, 0x84, 0xF8, 0x50, 0x30, 0xE2, 0x62, 0x02, 0xB0, ++0xBD, 0xE8, 0xF0, 0x87, 0x6B, 0x6A, 0xDF, 0xF8, 0xCC, 0x90, 0x20, 0x6B, 0xD5, 0xE9, 0x12, 0xA8, 0x43, 0xF4, 0x60, 0x13, ++0x6B, 0x62, 0xC7, 0xF8, 0x38, 0x51, 0x02, 0xF0, 0x37, 0xFC, 0x94, 0xF8, 0x4D, 0x20, 0xD9, 0xF8, 0x00, 0x30, 0x88, 0xF8, ++0x0D, 0x20, 0x5B, 0x78, 0x00, 0x2B, 0x34, 0xD1, 0x3B, 0x61, 0x6B, 0x6A, 0xB9, 0x88, 0x43, 0xF4, 0x80, 0x73, 0x41, 0xF0, ++0x01, 0x02, 0xC8, 0xF8, 0x4C, 0x30, 0xBA, 0x80, 0xBA, 0xF1, 0x00, 0x0F, 0x09, 0xD0, 0x4D, 0x07, 0x07, 0xD4, 0x08, 0x07, ++0x31, 0xD4, 0x23, 0x6B, 0x99, 0x6C, 0x4B, 0x6A, 0x43, 0xF0, 0x04, 0x03, 0x4B, 0x62, 0x93, 0x07, 0x10, 0xD5, 0xD9, 0xF8, ++0x00, 0x30, 0x5B, 0x78, 0xA3, 0xB9, 0x08, 0xF1, 0x14, 0x01, 0x23, 0x6B, 0x3A, 0x6B, 0x98, 0x6A, 0x15, 0x4B, 0x50, 0x61, ++0xD3, 0xF8, 0x9C, 0x33, 0x32, 0x46, 0x07, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0x39, 0x46, 0x04, 0xF1, 0x1C, 0x00, 0x11, 0xF0, ++0xF9, 0xFE, 0xAF, 0xE7, 0x0F, 0x4C, 0x47, 0xE7, 0x07, 0xF1, 0x50, 0x01, 0xE9, 0xE7, 0x94, 0xF8, 0x4E, 0x00, 0xBB, 0x7A, ++0x7A, 0x7A, 0x69, 0x8C, 0x00, 0x90, 0x38, 0x46, 0xFF, 0xF7, 0xCA, 0xF8, 0x07, 0xF1, 0x50, 0x03, 0xC8, 0xF8, 0x1C, 0x30, ++0xBD, 0xE7, 0x41, 0xF0, 0x03, 0x02, 0xBA, 0x80, 0xCF, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xD0, 0xF8, 0x4C, 0x90, 0x8B, 0xB0, 0x09, 0xF1, 0x14, 0x03, 0x05, 0x29, 0x04, 0x46, 0x0E, 0x46, 0x00, 0x93, 0x00, 0xF0, ++0xAD, 0x81, 0x57, 0x4D, 0x01, 0xEB, 0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x05, 0xEB, 0x83, 0x05, 0x94, 0xF8, 0x1B, 0xB0, ++0x94, 0xF8, 0x1D, 0xA0, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x50, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xDF, 0xF8, 0x40, 0x81, 0xEA, 0x6A, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x00, 0x2A, 0x79, 0xD0, ++0x4A, 0x4F, 0x06, 0xE0, 0xD7, 0xF8, 0x5C, 0x33, 0x30, 0x46, 0x98, 0x47, 0xEA, 0x6A, 0x00, 0x2A, 0x70, 0xD0, 0x63, 0x6A, ++0x99, 0x02, 0xF5, 0xD5, 0x03, 0xF4, 0x60, 0x11, 0xB1, 0xF5, 0x20, 0x1F, 0xF0, 0xD0, 0x50, 0x7A, 0x61, 0x7F, 0x88, 0x42, ++0xEC, 0xD1, 0x90, 0x7A, 0xE1, 0x7E, 0x88, 0x42, 0xE8, 0xD1, 0xD9, 0xF8, 0x2C, 0x10, 0xB5, 0xF8, 0x48, 0x00, 0x03, 0x31, ++0x21, 0xF0, 0x03, 0x01, 0x04, 0x31, 0x89, 0xB2, 0x88, 0x42, 0x00, 0xF2, 0x5D, 0x81, 0x00, 0x20, 0x03, 0x90, 0x05, 0x90, ++0x86, 0x46, 0x68, 0x6B, 0x01, 0x90, 0x50, 0x6A, 0x02, 0x90, 0x01, 0x98, 0x95, 0xF8, 0x4F, 0xC0, 0xC0, 0x6C, 0x04, 0x90, ++0x03, 0x98, 0xA5, 0xF8, 0x4A, 0xE0, 0x08, 0x44, 0x02, 0x99, 0x05, 0xEB, 0x8C, 0x0E, 0x08, 0x44, 0x4F, 0xEA, 0x8C, 0x01, ++0x03, 0x91, 0xDE, 0xF8, 0x38, 0x10, 0x88, 0x42, 0x40, 0xF2, 0x82, 0x81, 0x95, 0xF8, 0x4E, 0x10, 0x61, 0x45, 0xBB, 0xD9, ++0x95, 0xF8, 0x4D, 0x10, 0x01, 0x29, 0xB7, 0xD0, 0xDE, 0xF8, 0x3C, 0xE0, 0x70, 0x45, 0xB3, 0xD8, 0x03, 0x9F, 0x17, 0x44, ++0xBB, 0x46, 0x01, 0x9F, 0xCB, 0xF8, 0x3C, 0x71, 0x0C, 0xF1, 0x01, 0x0C, 0x02, 0x9F, 0xCB, 0xF8, 0x34, 0x70, 0x85, 0xF8, ++0x4F, 0xC0, 0x05, 0x9F, 0x62, 0x64, 0x43, 0xEA, 0x47, 0x23, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0xE0, 0x03, 0x63, 0x62, ++0xC9, 0xF8, 0x4C, 0x30, 0x04, 0x9B, 0x1F, 0x46, 0x00, 0x9B, 0xFB, 0x61, 0x50, 0x62, 0x95, 0xF8, 0x4C, 0x20, 0x6C, 0x63, ++0x4B, 0x1C, 0xDB, 0xB2, 0x9A, 0x42, 0x85, 0xF8, 0x4D, 0x30, 0x0D, 0xD8, 0x10, 0x4B, 0x30, 0x46, 0xD3, 0xF8, 0x5C, 0x33, ++0x98, 0x47, 0x07, 0xE0, 0x63, 0x6A, 0x98, 0x02, 0x1C, 0xD4, 0x95, 0xF8, 0x50, 0x30, 0x01, 0x33, 0x85, 0xF8, 0x50, 0x30, ++0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x00, 0x20, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA3, 0x6A, 0xDB, 0x0A, 0x13, 0xF0, 0x06, 0x0F, 0xDD, 0xD0, 0xB0, 0x48, ++0x00, 0xEB, 0xC6, 0x00, 0x11, 0xF0, 0x4A, 0xFE, 0xE8, 0x62, 0x00, 0x28, 0x00, 0xF0, 0xEA, 0x80, 0xAC, 0x4F, 0x80, 0xF8, ++0x0A, 0xB0, 0x00, 0x23, 0x01, 0x21, 0x3A, 0x68, 0x80, 0xF8, 0x09, 0xA0, 0x03, 0x72, 0x43, 0x60, 0xC1, 0x72, 0xA3, 0x6A, ++0xB2, 0xF9, 0x00, 0x20, 0x61, 0x7F, 0x03, 0x91, 0xC3, 0xF3, 0xC1, 0x1B, 0xC3, 0xF3, 0xC7, 0x21, 0x00, 0x2A, 0xC3, 0xF3, ++0xC2, 0x23, 0x01, 0x93, 0xC0, 0xF2, 0xD2, 0x80, 0x01, 0x9B, 0x05, 0x2B, 0x00, 0xF0, 0xD9, 0x80, 0xD4, 0xF8, 0x28, 0xA0, ++0x63, 0x7F, 0x05, 0x93, 0x0A, 0xF0, 0x7F, 0x03, 0x04, 0x93, 0xCA, 0xF3, 0x40, 0x23, 0x06, 0x93, 0x01, 0x9B, 0x04, 0x2B, ++0x3B, 0x68, 0x00, 0xF0, 0xF2, 0x80, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x01, 0x81, 0x94, 0x4A, 0x05, 0x99, ++0x02, 0x92, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x23, 0x04, 0x9A, 0x9B, 0x8A, 0x08, 0x93, 0xC2, 0xF3, 0xC1, 0x02, ++0x01, 0x32, 0x09, 0x92, 0x0A, 0xF0, 0x07, 0x0A, 0x8D, 0x4B, 0x05, 0x93, 0x8D, 0x4B, 0x9C, 0x46, 0x06, 0x9B, 0x00, 0x27, ++0x43, 0xEA, 0xCA, 0x0A, 0x5F, 0xFA, 0x8B, 0xF3, 0x19, 0x46, 0x05, 0xF1, 0x38, 0x0B, 0x04, 0x93, 0x85, 0xF8, 0x4E, 0x10, ++0x00, 0x23, 0x31, 0x1D, 0xCD, 0xF8, 0x18, 0x90, 0x07, 0x94, 0xD1, 0x46, 0x85, 0xF8, 0x4F, 0x30, 0xDA, 0x46, 0x1E, 0x46, ++0x64, 0x46, 0x8B, 0x46, 0x01, 0x2A, 0xF1, 0xB2, 0x00, 0xF0, 0xA8, 0x80, 0x48, 0x46, 0xA0, 0x47, 0x7E, 0x4B, 0x09, 0x9A, ++0x33, 0xF8, 0x1B, 0xC0, 0x08, 0x99, 0x02, 0xFB, 0x0C, 0xFC, 0x00, 0xFB, 0x0C, 0xF0, 0xF8, 0x40, 0x81, 0x42, 0x28, 0xBF, ++0x01, 0x46, 0x4A, 0xF8, 0x04, 0x1B, 0x95, 0xF8, 0x4E, 0x10, 0x01, 0x36, 0x8E, 0x42, 0xE5, 0xDD, 0xCA, 0x46, 0x04, 0x99, ++0x05, 0x9B, 0x50, 0x46, 0xDD, 0xE9, 0x06, 0x94, 0x98, 0x47, 0x03, 0x9B, 0xD5, 0xF8, 0x38, 0xC0, 0x1E, 0x46, 0x02, 0x9B, ++0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x06, 0x32, 0x09, 0x9B, 0x16, 0x7F, 0xEA, 0x6A, 0x03, 0xFB, 0x06, 0xF6, 0x00, 0xFB, ++0x06, 0xF6, 0xFE, 0x40, 0xB6, 0xB2, 0xA5, 0xF8, 0x48, 0x60, 0xE1, 0x7E, 0x63, 0x7F, 0xEF, 0x6B, 0x9E, 0x20, 0x00, 0xFB, ++0x03, 0x13, 0x02, 0x99, 0x28, 0x6C, 0x01, 0xEB, 0x83, 0x03, 0x4F, 0xF0, 0x01, 0x0E, 0x93, 0xF8, 0x5A, 0x31, 0x85, 0xF8, ++0x4C, 0x30, 0xD9, 0xF8, 0x2C, 0x10, 0x00, 0x9B, 0x53, 0x61, 0x03, 0x31, 0x21, 0xF0, 0x03, 0x01, 0x04, 0x31, 0x00, 0x23, ++0x89, 0xB2, 0x51, 0x62, 0xC2, 0xF8, 0x54, 0x01, 0xC2, 0xE9, 0x53, 0xC7, 0xC2, 0xE9, 0x0D, 0x33, 0x93, 0x64, 0x93, 0x61, ++0xD3, 0x63, 0x85, 0xF8, 0x4D, 0xE0, 0xD9, 0xF8, 0x2C, 0x00, 0x03, 0x30, 0x20, 0xF0, 0x03, 0x00, 0x04, 0x30, 0x80, 0xB2, ++0xB0, 0x42, 0x57, 0xD2, 0x30, 0x1A, 0x80, 0xB2, 0x03, 0x30, 0x83, 0x10, 0x01, 0xEB, 0x83, 0x01, 0x80, 0x08, 0x5B, 0x02, ++0x66, 0x6A, 0xA5, 0xF8, 0x4A, 0x00, 0x33, 0x43, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0xD0, 0x03, 0x51, 0x62, 0xC5, 0xE9, ++0x0C, 0x44, 0x63, 0x62, 0x62, 0x64, 0xC9, 0xF8, 0x4C, 0x30, 0xFF, 0xE6, 0xA0, 0xEB, 0x01, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, ++0x0E, 0xF1, 0x03, 0x0E, 0x4F, 0xEA, 0xAE, 0x00, 0x05, 0x90, 0x80, 0x00, 0x4F, 0xEA, 0x9E, 0x0E, 0x03, 0x90, 0x98, 0xE6, ++0x3D, 0x4D, 0x57, 0xE6, 0x60, 0x62, 0xE8, 0xE6, 0x11, 0xF0, 0x06, 0x0F, 0x7F, 0xF4, 0x2A, 0xAF, 0x3A, 0x49, 0x3B, 0x48, ++0x4F, 0xF4, 0xEA, 0x72, 0x13, 0xF0, 0x60, 0xF9, 0x22, 0xE7, 0x09, 0xAB, 0x08, 0xAA, 0x01, 0x99, 0x20, 0x46, 0x02, 0xF0, ++0x39, 0xF9, 0x36, 0x4B, 0x05, 0x93, 0x36, 0x4B, 0x94, 0xF8, 0x36, 0x70, 0x09, 0x9A, 0x9C, 0x46, 0x2B, 0x4B, 0x02, 0x93, ++0x82, 0x46, 0xC7, 0xF3, 0x40, 0x17, 0x3F, 0xE7, 0x01, 0x9B, 0x04, 0x2B, 0x7F, 0xF4, 0x54, 0xAF, 0x4F, 0xEA, 0xE9, 0x02, ++0x00, 0x2E, 0x7F, 0xF4, 0x4F, 0xAF, 0x09, 0x2A, 0x04, 0xBF, 0x09, 0xF0, 0x07, 0x03, 0x43, 0xF0, 0x40, 0x09, 0x47, 0xE7, ++0x18, 0x46, 0xAD, 0xE7, 0x95, 0xF8, 0x4D, 0x10, 0x93, 0xE6, 0x04, 0x9A, 0xB3, 0xF9, 0x00, 0x30, 0x11, 0x09, 0x4A, 0x1C, ++0x00, 0x2B, 0x0A, 0xF0, 0x0F, 0x0A, 0x09, 0x92, 0x14, 0xDB, 0x19, 0x49, 0x05, 0x98, 0x02, 0x91, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x00, 0x13, 0x1B, 0x69, 0x08, 0x93, 0x0E, 0xE7, 0x1A, 0xF0, 0x60, 0x0F, 0x3F, 0xF4, 0xFB, 0xAE, 0x17, 0x49, ++0x1A, 0x48, 0x4F, 0xF4, 0xD2, 0x72, 0x13, 0xF0, 0x19, 0xF9, 0xF3, 0xE6, 0x03, 0x29, 0x04, 0xD8, 0xBA, 0xF1, 0x09, 0x0F, ++0x0D, 0xD8, 0x09, 0x9A, 0xE3, 0xE7, 0x10, 0x49, 0x14, 0x48, 0x40, 0xF2, 0x9B, 0x12, 0x13, 0xF0, 0x0B, 0xF9, 0x3B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEF, 0xDB, 0xF1, 0xE7, 0x0A, 0x49, 0x0F, 0x48, 0x4F, 0xF4, 0xCE, 0x72, 0x13, 0xF0, ++0xFF, 0xF8, 0xEA, 0xE7, 0x64, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x85, 0x06, 0x13, 0x00, ++0x75, 0x06, 0x13, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB8, 0x91, 0x15, 0x00, ++0x21, 0x3B, 0x13, 0x00, 0x05, 0x3B, 0x13, 0x00, 0x0C, 0x92, 0x15, 0x00, 0xE0, 0x91, 0x15, 0x00, 0xFC, 0x91, 0x15, 0x00, ++0xC3, 0x7A, 0x01, 0x3B, 0xDB, 0xB2, 0xC3, 0x72, 0x03, 0xB1, 0x70, 0x47, 0x01, 0x46, 0xD0, 0xF8, 0x48, 0x01, 0x11, 0xF0, ++0x83, 0xBC, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0xD0, 0xE9, 0x12, 0x67, 0x00, 0x23, 0x4F, 0xF4, 0x80, 0x72, 0x43, 0x62, ++0x43, 0x64, 0xFB, 0x61, 0xFA, 0x64, 0x00, 0x2E, 0x00, 0xF0, 0x81, 0x80, 0xD0, 0xF8, 0x2C, 0x80, 0x8A, 0x46, 0x05, 0x46, ++0x06, 0xF1, 0x28, 0x09, 0x08, 0xF1, 0x40, 0x01, 0x43, 0x46, 0x06, 0xF1, 0x24, 0x02, 0x53, 0xF8, 0x04, 0x4B, 0x42, 0xF8, ++0x04, 0x4F, 0x8B, 0x42, 0xF9, 0xD1, 0xEB, 0x8B, 0x9C, 0x04, 0x22, 0xD5, 0x48, 0x4B, 0x49, 0x49, 0x1A, 0x68, 0x6B, 0x7F, ++0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x41, 0x61, 0xDB, ++0xD8, 0xF8, 0x14, 0x20, 0xD4, 0xF8, 0x9C, 0x30, 0x32, 0x64, 0xD8, 0xF8, 0x24, 0x20, 0x32, 0x65, 0xC3, 0xF3, 0xC2, 0x22, ++0x05, 0x2A, 0xF3, 0x63, 0x5D, 0xD0, 0xD8, 0xF8, 0x3C, 0x30, 0x58, 0x07, 0x03, 0xD4, 0xF3, 0x6A, 0x23, 0xF4, 0xC0, 0x73, ++0xF3, 0x62, 0x39, 0x4A, 0x2B, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x7B, 0xB1, ++0x73, 0x6A, 0x43, 0xF0, 0x10, 0x03, 0x28, 0x46, 0x73, 0x62, 0x02, 0xF0, 0x47, 0xF9, 0xD6, 0xE9, 0x17, 0x23, 0x07, 0xF1, ++0x14, 0x00, 0xC7, 0xE9, 0x0D, 0x39, 0xBA, 0x64, 0xBD, 0xE8, 0xF0, 0x87, 0x2B, 0x4A, 0x6B, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, ++0x01, 0xFB, 0x03, 0x23, 0x5B, 0x68, 0x99, 0x06, 0xE6, 0xD5, 0xBA, 0xF1, 0x00, 0x0F, 0xE3, 0xD1, 0xEB, 0x8B, 0x13, 0xF4, ++0x00, 0x5F, 0xEB, 0x6A, 0xDB, 0x6B, 0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0x00, 0x2B, 0xD7, 0xD1, ++0x79, 0x6A, 0x0A, 0x88, 0x93, 0xB2, 0x12, 0x04, 0xD2, 0xD5, 0xC3, 0xF3, 0x0E, 0x03, 0x0B, 0x80, 0x95, 0xF8, 0x33, 0x20, ++0x95, 0xF8, 0x32, 0x30, 0x04, 0x3A, 0x04, 0x3B, 0x85, 0xF8, 0x33, 0x20, 0x85, 0xF8, 0x32, 0x30, 0xD7, 0xE9, 0x0A, 0x32, ++0x04, 0x3A, 0x04, 0x3B, 0xC7, 0xE9, 0x0A, 0x32, 0xBE, 0xE7, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x2C, 0x9B, 0xD1, ++0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0x13, 0xF0, 0x3C, 0xF8, 0x94, 0xE7, 0x03, 0xF4, 0xC0, 0x63, 0xF2, 0x6C, ++0x94, 0xF8, 0xA1, 0x10, 0xB3, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x30, 0x4F, 0xF4, 0x00, 0x30, 0x22, 0xF4, ++0x40, 0x33, 0x03, 0x43, 0x19, 0xB1, 0x43, 0xF4, 0x80, 0x23, 0xF3, 0x64, 0x8D, 0xE7, 0x23, 0xF4, 0x80, 0x23, 0xF3, 0x64, ++0x89, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x05, 0x28, 0x89, 0xB0, 0x81, 0x46, 0x00, 0xF0, 0x79, 0x81, 0xBE, 0x4A, ++0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x03, 0x93, 0x03, 0x9B, 0xDC, 0x68, 0xBA, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x09, 0xDA, 0x5D, 0xE1, 0xE3, 0x6C, 0x1B, 0x6D, 0x00, 0x2B, 0x80, 0xF2, ++0xFE, 0x80, 0x24, 0x68, 0x00, 0x2C, 0x00, 0xF0, 0xFA, 0x80, 0x63, 0x6A, 0x9A, 0x02, 0xF3, 0xD5, 0xB0, 0x4D, 0x2A, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x80, 0x81, 0xAE, 0x4B, 0x67, 0x6C, 0x1B, 0x68, 0xDB, 0xB2, 0x07, 0xEB, ++0x83, 0x03, 0xD3, 0xF8, 0x3C, 0x41, 0xE5, 0x6C, 0x63, 0x6A, 0xAA, 0x49, 0x43, 0xF4, 0x60, 0x10, 0x09, 0x68, 0x60, 0x62, ++0x49, 0x78, 0x23, 0xF4, 0xC0, 0x13, 0x00, 0x29, 0x40, 0xF0, 0x58, 0x81, 0x43, 0xF4, 0x60, 0x13, 0x43, 0xF4, 0x80, 0x73, ++0x00, 0x2A, 0x26, 0x68, 0xEB, 0x64, 0xE9, 0x61, 0xC0, 0xF2, 0x57, 0x81, 0x72, 0x6A, 0x02, 0xF4, 0x60, 0x1A, 0xBA, 0xF5, ++0x60, 0x1F, 0x00, 0xF0, 0xEC, 0x80, 0x9D, 0x48, 0x50, 0xF8, 0x39, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xE6, 0x80, 0x00, 0xEB, ++0xC9, 0x00, 0x11, 0xF0, 0xAD, 0xFB, 0xBB, 0x88, 0x83, 0x80, 0x7B, 0x7A, 0x43, 0x72, 0xBB, 0x7A, 0x83, 0x72, 0x01, 0x23, ++0xC3, 0x72, 0x72, 0x6A, 0xD6, 0xF8, 0x4C, 0xA0, 0xF9, 0x6A, 0xD7, 0xF8, 0x4C, 0xB1, 0xB5, 0x6C, 0x05, 0x95, 0x04, 0x46, ++0xD7, 0xE9, 0x10, 0x03, 0x22, 0xF4, 0xC0, 0x12, 0xE1, 0x62, 0x42, 0xF4, 0x20, 0x12, 0x00, 0x21, 0xC4, 0xE9, 0x10, 0x03, ++0xA1, 0x64, 0x3B, 0x6B, 0x72, 0x62, 0xCA, 0xF8, 0x4C, 0x20, 0xC4, 0xF8, 0x4C, 0xB1, 0x06, 0x93, 0xD7, 0xF8, 0x50, 0x31, ++0xC4, 0xF8, 0x50, 0x31, 0xD7, 0xF8, 0x54, 0x31, 0xC4, 0xF8, 0x54, 0x31, 0x04, 0xF1, 0x0C, 0x03, 0x0A, 0xF1, 0x14, 0x0C, ++0x28, 0x35, 0xC4, 0xE9, 0x0D, 0x11, 0xA1, 0x61, 0xE1, 0x63, 0x61, 0x62, 0x04, 0x93, 0x04, 0xF5, 0x82, 0x73, 0xC4, 0xF8, ++0x14, 0xC0, 0x25, 0x63, 0xBC, 0x46, 0x08, 0x46, 0x57, 0x46, 0x07, 0x93, 0xAA, 0x46, 0x8E, 0x46, 0x25, 0x46, 0x0C, 0x46, ++0x06, 0xE0, 0x5A, 0x6A, 0xDF, 0x6C, 0xD8, 0xF8, 0x34, 0x00, 0xD8, 0xF8, 0x4C, 0xB1, 0x1E, 0x46, 0xFB, 0x6A, 0x03, 0x33, ++0xC2, 0xF3, 0x49, 0x28, 0x23, 0xF0, 0x03, 0x03, 0x03, 0xEB, 0x88, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x18, 0x44, 0x01, 0x31, ++0x58, 0x45, 0x02, 0xF4, 0x60, 0x12, 0xC9, 0xB2, 0x06, 0xD9, 0x05, 0xEB, 0x8E, 0x00, 0x0E, 0xF1, 0x01, 0x0E, 0x44, 0x63, ++0x5F, 0xFA, 0x8E, 0xFE, 0x05, 0xEB, 0x8E, 0x08, 0x1C, 0x44, 0xC8, 0xF8, 0x3C, 0x61, 0xB2, 0xF5, 0x60, 0x1F, 0x33, 0x68, ++0x75, 0x64, 0x6C, 0x62, 0x00, 0xF0, 0x18, 0x81, 0x00, 0x2B, 0xD2, 0xD1, 0x2C, 0x46, 0x98, 0x46, 0x55, 0x46, 0xC4, 0xF8, ++0x38, 0x61, 0xBA, 0x46, 0x67, 0x46, 0x03, 0x98, 0x8A, 0xF8, 0x0D, 0x10, 0x90, 0xF8, 0x50, 0x30, 0x03, 0xF1, 0x01, 0x0C, ++0x03, 0x46, 0x22, 0x46, 0x1C, 0x30, 0x83, 0xF8, 0x50, 0xC0, 0x39, 0x46, 0x11, 0xF0, 0xA0, 0xFB, 0x53, 0x4B, 0x1B, 0x68, ++0x58, 0x78, 0x00, 0x28, 0x40, 0xF0, 0x11, 0x81, 0xD7, 0xF8, 0x38, 0x11, 0xF2, 0x6C, 0xDF, 0xF8, 0x30, 0xC1, 0xC9, 0x6C, ++0xD0, 0x61, 0x54, 0x23, 0x03, 0xFB, 0x09, 0xF3, 0x3A, 0x69, 0x5C, 0xF8, 0x03, 0x00, 0x22, 0x61, 0x14, 0x31, 0x04, 0x9A, ++0x3A, 0x61, 0x88, 0x42, 0x63, 0x44, 0x00, 0xF0, 0x2A, 0x81, 0x06, 0x9B, 0x07, 0x9A, 0xA3, 0xF1, 0x28, 0x00, 0x05, 0x9B, ++0xC0, 0x1A, 0x03, 0xF1, 0x5C, 0x01, 0x2B, 0x18, 0x1C, 0x68, 0x45, 0xF8, 0x04, 0x4B, 0x1B, 0x68, 0x42, 0xF8, 0x04, 0x3B, ++0x8D, 0x42, 0xF6, 0xD1, 0x3B, 0x4C, 0x48, 0x46, 0xFC, 0xF7, 0x10, 0xF8, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xD7, 0xF8, 0x38, 0x31, 0x04, 0xDB, 0xB3, 0x42, 0x1C, 0xD1, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0x42, 0xFA, 0xD0, ++0x36, 0x49, 0x37, 0x48, 0x40, 0xF6, 0x2A, 0x42, 0x12, 0xF0, 0xF2, 0xFE, 0xD7, 0xF8, 0x38, 0x31, 0xB3, 0x42, 0xF0, 0xD0, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x08, 0xDA, 0xB8, 0xF1, 0x00, 0x0F, 0x05, 0xD1, 0x2D, 0x49, 0x2F, 0x48, ++0x4F, 0xF4, 0x43, 0x62, 0x12, 0xF0, 0xE0, 0xFE, 0xD8, 0xF8, 0x24, 0x20, 0x46, 0x46, 0x02, 0xF4, 0x60, 0x1A, 0x26, 0x4B, ++0x1B, 0x68, 0x5B, 0x78, 0x00, 0x2B, 0x58, 0xD1, 0xD7, 0xF8, 0x38, 0x31, 0xD7, 0xF8, 0x10, 0x80, 0xDB, 0x6C, 0x07, 0xF1, ++0x0C, 0x05, 0x03, 0xF1, 0x14, 0x07, 0x1C, 0x4B, 0x04, 0x97, 0x54, 0x24, 0x04, 0xFB, 0x09, 0x34, 0x57, 0x46, 0xDF, 0xF8, ++0x88, 0xB0, 0xDF, 0xF8, 0x7C, 0x90, 0xA2, 0x46, 0x03, 0x9C, 0x94, 0xF8, 0x50, 0x10, 0xDB, 0xF8, 0x58, 0x33, 0x01, 0x31, ++0x84, 0xF8, 0x50, 0x10, 0x30, 0x46, 0x00, 0x21, 0x98, 0x47, 0x58, 0xB1, 0x13, 0x4B, 0x68, 0x60, 0x1B, 0x68, 0x59, 0x78, ++0xDA, 0xF8, 0x00, 0x30, 0x00, 0x29, 0x65, 0xD0, 0xAB, 0x42, 0x00, 0xF0, 0xAD, 0x80, 0x05, 0x46, 0xB7, 0xF5, 0x60, 0x1F, ++0x65, 0xD1, 0xC0, 0xF8, 0x04, 0x80, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2C, 0x7F, 0xF4, 0xA8, 0xAE, 0x0A, 0x49, ++0x0B, 0x48, 0x40, 0xF6, 0x8B, 0x32, 0x12, 0xF0, 0x99, 0xFE, 0xA0, 0xE6, 0x09, 0x4B, 0x03, 0x93, 0x8B, 0xE6, 0x00, 0xBF, ++0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x30, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x4C, 0x92, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x07, 0xF1, 0x50, 0x01, 0xA4, 0xE6, 0xD7, 0xF8, 0x54, 0x80, 0x07, 0xF1, 0x50, 0x05, 0x00, 0x27, 0xA9, 0xE7, 0x00, 0x2E, ++0x7F, 0xF4, 0xA6, 0xAE, 0x49, 0x49, 0x4A, 0x48, 0x40, 0xF6, 0xB6, 0x32, 0x12, 0xF0, 0x6E, 0xFE, 0x9E, 0xE6, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x3E, 0xD0, 0x40, 0xF6, 0x9B, 0x32, 0x42, 0x49, 0x44, 0x48, 0x12, 0xF0, 0x62, 0xFE, ++0x43, 0x4B, 0x67, 0x6C, 0x1B, 0x68, 0x2A, 0x68, 0xDB, 0xB2, 0x07, 0xEB, 0x83, 0x03, 0xB2, 0xF9, 0x00, 0x20, 0xD3, 0xF8, ++0x3C, 0x41, 0x00, 0x2A, 0xE5, 0x6C, 0xBF, 0xF6, 0x6F, 0xAE, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x60, 0x1F, ++0x60, 0xD0, 0x3A, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x64, 0xE6, 0x04, 0x9A, 0x93, 0x42, 0x99, 0xD1, 0xCA, 0xE9, ++0x01, 0x11, 0x05, 0x46, 0x96, 0xE7, 0x34, 0x4B, 0x36, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x3F, 0xDB, ++0x77, 0x6A, 0x07, 0xF4, 0x60, 0x17, 0x74, 0xE7, 0x20, 0x46, 0x2C, 0x46, 0x04, 0xEB, 0x8E, 0x0E, 0x55, 0x46, 0xC4, 0xF8, ++0x38, 0x61, 0xBA, 0x46, 0x98, 0x46, 0x67, 0x46, 0xCE, 0xF8, 0x34, 0x00, 0xE3, 0xE6, 0x27, 0x4B, 0x67, 0x6C, 0x1B, 0x68, ++0xDB, 0xB2, 0x07, 0xEB, 0x83, 0x03, 0xD3, 0xF8, 0x3C, 0x41, 0xE5, 0x6C, 0xCB, 0xE7, 0xB0, 0x6A, 0xA3, 0x7A, 0x62, 0x7A, ++0x71, 0x8C, 0xC0, 0xF3, 0xC1, 0x10, 0x00, 0x90, 0x20, 0x46, 0xFE, 0xF7, 0xA1, 0xFB, 0x54, 0x23, 0x1E, 0x49, 0xF2, 0x6C, ++0xD7, 0xF8, 0x54, 0xE0, 0x03, 0xFB, 0x09, 0xF3, 0x04, 0xF1, 0x50, 0x00, 0x51, 0xF8, 0x03, 0xC0, 0xD0, 0x61, 0x07, 0xF1, ++0x50, 0x02, 0xC4, 0xF8, 0x54, 0xE0, 0x94, 0x45, 0x04, 0x9C, 0x7C, 0x65, 0x7F, 0xF4, 0xE5, 0xAE, 0xC8, 0x50, 0xE2, 0xE6, ++0xCA, 0xF8, 0x00, 0x00, 0x05, 0x46, 0x4F, 0xE7, 0x00, 0x2E, 0xBD, 0xD1, 0x0B, 0x49, 0x40, 0xF6, 0x62, 0x42, 0x48, 0x46, ++0x12, 0xF0, 0xF2, 0xFD, 0xB6, 0xE7, 0x04, 0x99, 0x01, 0x22, 0xC3, 0xE9, 0x01, 0x12, 0xD0, 0xE6, 0x40, 0xF6, 0xA5, 0x32, ++0x04, 0x49, 0x0A, 0x48, 0x12, 0xF0, 0xE6, 0xFD, 0x06, 0x4B, 0x1A, 0x68, 0x63, 0x6A, 0xB2, 0xF9, 0x00, 0x20, 0xFC, 0xE5, ++0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x1C, 0x92, 0x15, 0x00, 0x30, 0x83, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x34, 0x92, 0x15, 0x00, 0x05, 0x28, 0x10, 0xB5, 0x25, 0xD0, 0x14, 0x4A, 0x00, 0xEB, 0x40, 0x03, ++0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x02, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0F, 0x4B, ++0x01, 0x21, 0x19, 0x60, 0x0E, 0x4C, 0x92, 0xF8, 0x50, 0x10, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x31, 0xB9, 0xD2, 0x6A, ++0x22, 0xB1, 0x0B, 0x4B, 0xD3, 0xF8, 0x5C, 0x33, 0x98, 0x47, 0x23, 0x68, 0x33, 0xB1, 0x06, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x05, 0x4A, 0xDE, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x03, 0x68, 0x13, 0xF4, ++0xE0, 0x3F, 0x1A, 0xD1, 0x9A, 0x04, 0x4C, 0xBF, 0x03, 0xF0, 0x0F, 0x02, 0x03, 0xF0, 0x07, 0x02, 0x02, 0x2A, 0xC3, 0xF3, ++0xC1, 0x11, 0x88, 0xBF, 0x4F, 0xF4, 0x80, 0x12, 0x23, 0xF0, 0xFF, 0x53, 0x98, 0xBF, 0x4F, 0xF4, 0x00, 0x22, 0x23, 0xF4, ++0xFE, 0x13, 0x42, 0xEA, 0x01, 0x62, 0x13, 0x43, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x03, 0x60, 0x70, 0x47, ++0xC3, 0x6B, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x10, 0xB4, 0x0E, 0x4C, 0x42, 0x6A, 0x24, 0x68, 0xB4, 0xF9, 0x00, 0x40, ++0x00, 0x2C, 0x01, 0xDA, 0xDB, 0x03, 0x0B, 0xD5, 0x53, 0x69, 0x23, 0xF4, 0xE0, 0x33, 0x00, 0x24, 0x43, 0xF4, 0x80, 0x43, ++0xC4, 0x63, 0x5D, 0xF8, 0x04, 0x4B, 0x53, 0x61, 0xFC, 0xF7, 0xA4, 0xB9, 0x04, 0x49, 0x05, 0x48, 0x5D, 0xF8, 0x04, 0x4B, ++0x40, 0xF6, 0xD9, 0x42, 0x12, 0xF0, 0x28, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x92, 0x15, 0x00, ++0x05, 0x28, 0x10, 0xB5, 0x17, 0xD0, 0x0D, 0x4C, 0x00, 0xEB, 0x40, 0x00, 0xC0, 0xEB, 0xC0, 0x00, 0x04, 0xEB, 0x80, 0x04, ++0xA1, 0x6A, 0x31, 0xB1, 0xCB, 0x7A, 0x01, 0x3B, 0xDB, 0xB2, 0xCB, 0x72, 0x13, 0xB1, 0x00, 0x23, 0xA3, 0x62, 0x10, 0xBD, ++0xD1, 0xF8, 0x48, 0x01, 0x11, 0xF0, 0xE8, 0xF8, 0x00, 0x23, 0xA3, 0x62, 0xF7, 0xE7, 0x02, 0x4C, 0xEC, 0xE7, 0x00, 0xBF, ++0x20, 0x62, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0xF0, 0xB4, 0xC5, 0x6C, 0x42, 0x6A, 0xEB, 0x6C, 0xD0, 0xE9, 0x11, 0x67, ++0x22, 0xF4, 0xC0, 0x12, 0x23, 0xF4, 0x60, 0x13, 0x05, 0xF1, 0x14, 0x0C, 0x42, 0xF4, 0x20, 0x14, 0x43, 0xF4, 0x20, 0x12, ++0x06, 0xF5, 0x82, 0x73, 0xC6, 0xF8, 0x14, 0xC0, 0x33, 0x63, 0x44, 0x62, 0xEA, 0x64, 0x06, 0xF1, 0x0C, 0x00, 0x07, 0xF1, ++0x24, 0x02, 0x06, 0xF5, 0x9C, 0x75, 0x53, 0xF8, 0x04, 0x4B, 0x42, 0xF8, 0x04, 0x4F, 0xAB, 0x42, 0xF9, 0xD1, 0x77, 0xB1, ++0x09, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0x33, 0xB9, 0xD6, 0xF8, 0x38, 0x31, 0xDB, 0x6C, 0x14, 0x33, 0x0B, 0x60, 0xF0, 0xBC, ++0x70, 0x47, 0x50, 0x36, 0x0E, 0x60, 0xF0, 0xBC, 0x70, 0x47, 0x01, 0x23, 0x38, 0x46, 0x73, 0x60, 0xF5, 0xE7, 0x00, 0xBF, ++0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x47, 0x6A, 0xD0, 0xF8, 0x4C, 0xE0, 0x85, 0xB0, 0x17, 0xF4, 0x00, 0x1C, ++0x9D, 0xF8, 0x38, 0x90, 0x04, 0x46, 0x0E, 0xF1, 0x14, 0x08, 0x0D, 0x46, 0x16, 0x46, 0x9A, 0x46, 0x2A, 0xD0, 0x07, 0xF4, ++0x60, 0x17, 0xB7, 0xF5, 0x20, 0x1F, 0x40, 0xF0, 0xBB, 0x80, 0xD0, 0xF8, 0x44, 0xB0, 0xBB, 0xF8, 0x04, 0x70, 0x07, 0xF0, ++0x03, 0x07, 0x03, 0x2F, 0x40, 0xF0, 0xB2, 0x80, 0xDF, 0xF8, 0x30, 0xC2, 0x83, 0x4F, 0xDC, 0xF8, 0x00, 0xC0, 0x3F, 0x68, ++0x9C, 0xF8, 0x3E, 0xC0, 0x07, 0xF0, 0x3F, 0x07, 0xBC, 0x45, 0x00, 0xF2, 0xA5, 0x80, 0xDB, 0xF8, 0x24, 0x70, 0x97, 0x42, ++0x40, 0xF2, 0xC1, 0x80, 0x7C, 0x4C, 0xCD, 0xF8, 0x38, 0x90, 0xD4, 0xF8, 0x70, 0x43, 0xA4, 0x46, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x60, 0x47, 0x83, 0x6C, 0x00, 0x2B, 0x00, 0xF0, 0x92, 0x80, 0x5B, 0x6A, 0x13, 0xF0, 0x10, 0x03, 0x00, 0xF0, ++0x8D, 0x80, 0x82, 0x88, 0x00, 0x2A, 0x00, 0xF0, 0x8F, 0x80, 0xC3, 0x8B, 0x1F, 0x07, 0x00, 0xF1, 0x8B, 0x80, 0xDE, 0xF8, ++0x24, 0x10, 0x00, 0x29, 0x00, 0xF0, 0xB9, 0x80, 0x08, 0x88, 0x83, 0xB2, 0x00, 0x04, 0x00, 0xF1, 0xB4, 0x80, 0x6F, 0xEA, ++0x43, 0x43, 0x6F, 0xEA, 0x53, 0x43, 0x0B, 0x80, 0x94, 0xF8, 0x33, 0x20, 0x94, 0xF8, 0x32, 0x30, 0x04, 0x32, 0x04, 0x33, ++0x84, 0xF8, 0x32, 0x30, 0x84, 0xF8, 0x33, 0x20, 0xDE, 0xE9, 0x0A, 0x12, 0xD3, 0x1D, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, ++0x9B, 0xB2, 0x04, 0x32, 0x04, 0x31, 0xB3, 0x42, 0xCE, 0xE9, 0x0A, 0x12, 0x6D, 0xD8, 0xA2, 0x88, 0x32, 0xB1, 0xE3, 0x8B, ++0x1F, 0x07, 0x03, 0xD4, 0x5A, 0x4B, 0xDB, 0x6E, 0x41, 0xF8, 0x03, 0x3C, 0x23, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x36, 0xD0, ++0x11, 0x46, 0xDF, 0xF8, 0x70, 0xB1, 0x54, 0x4F, 0x32, 0x46, 0x00, 0x29, 0x2C, 0xD0, 0xE1, 0x8B, 0x0E, 0x07, 0x29, 0xD4, ++0x99, 0x88, 0x39, 0xB3, 0xD9, 0x8B, 0x08, 0x07, 0x24, 0xD4, 0x4D, 0x49, 0xDB, 0xF8, 0x00, 0x00, 0x09, 0x68, 0x90, 0xF8, ++0x3E, 0x60, 0x01, 0xF0, 0x3F, 0x01, 0x8E, 0x42, 0x1A, 0xD8, 0x5B, 0x6A, 0xBC, 0xF1, 0x00, 0x0F, 0x4C, 0xD1, 0x9B, 0x02, ++0x17, 0xD5, 0xCD, 0xF8, 0x00, 0x90, 0xD7, 0xF8, 0x54, 0x63, 0x03, 0x92, 0x53, 0x46, 0x29, 0x46, 0x20, 0x46, 0xB0, 0x47, ++0x03, 0x9A, 0x00, 0x28, 0x77, 0xD0, 0x2B, 0x68, 0x00, 0x2B, 0x74, 0xD0, 0x60, 0x6A, 0xA1, 0x88, 0x00, 0xF4, 0x00, 0x1C, ++0x00, 0x29, 0xD2, 0xD1, 0xBC, 0xF1, 0x00, 0x0F, 0x47, 0xD1, 0x63, 0x6C, 0xD3, 0xB9, 0x3B, 0x48, 0x11, 0xF0, 0x2C, 0xF8, ++0x3A, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x56, 0xDB, 0x54, 0x23, 0x1C, 0x22, 0x37, 0x48, ++0x13, 0xFB, 0x09, 0x29, 0x00, 0x22, 0x01, 0x23, 0xAA, 0x80, 0xEB, 0x72, 0x48, 0x44, 0x29, 0x46, 0x65, 0x64, 0x10, 0xF0, ++0xF7, 0xFF, 0x01, 0xE0, 0x4F, 0xF0, 0x00, 0x08, 0x40, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDE, 0xF8, 0x2C, 0x30, ++0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x9E, 0x42, 0x9A, 0xD2, 0x25, 0x4B, 0x40, 0x46, 0xD3, 0xF8, ++0xBC, 0x33, 0x49, 0x46, 0x98, 0x47, 0x4F, 0xF0, 0x00, 0x08, 0xE9, 0xE7, 0xCD, 0xF8, 0x00, 0x90, 0x99, 0x02, 0x54, 0xBF, ++0xD7, 0xF8, 0x50, 0x63, 0xD7, 0xF8, 0x4C, 0x63, 0xAF, 0xE7, 0xFE, 0xF7, 0xD1, 0xF9, 0xDB, 0xF8, 0x38, 0x31, 0x67, 0x6A, ++0x1B, 0x68, 0x2B, 0x60, 0x5B, 0xB3, 0xA2, 0x88, 0x07, 0xF4, 0x00, 0x1C, 0x80, 0xE7, 0x63, 0x6C, 0xD3, 0xF8, 0x38, 0x21, ++0x03, 0xF1, 0x0C, 0x08, 0xD2, 0x6C, 0x00, 0x21, 0x40, 0x46, 0xD1, 0x61, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDE, 0xF8, ++0x2C, 0x30, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x9E, 0x42, 0xCC, 0xD3, 0x00, 0x29, 0x3F, 0xF4, ++0x65, 0xAF, 0xDE, 0xF8, 0x28, 0x10, 0x5D, 0xE7, 0x00, 0x28, 0xA6, 0xD1, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF6, 0x92, 0x52, ++0x12, 0xF0, 0xD6, 0xFB, 0x9F, 0xE7, 0x67, 0x6A, 0x07, 0xF4, 0x00, 0x1C, 0x8C, 0xE7, 0x07, 0xF4, 0x00, 0x1C, 0x89, 0xE7, ++0x54, 0x83, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x8C, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x90, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x28, ++0x2C, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x0B, 0x23, 0x13, 0x1B, 0x03, 0x00, 0x1B, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x03, 0x0F, ++0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x17, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x30, 0x0F, 0x0C, 0xBF, 0x01, 0x20, ++0x00, 0x20, 0x08, 0xBD, 0x13, 0x4B, 0x1B, 0x68, 0x13, 0xF4, 0x40, 0x5F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, ++0x0F, 0x4B, 0x1B, 0x68, 0x13, 0xF4, 0x40, 0x3F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x0B, 0x4B, 0x1B, 0x68, ++0x13, 0xF4, 0x40, 0x7F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x01, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xF3, 0x12, 0x12, 0xF0, 0x7E, 0xFB, ++0x00, 0x20, 0x08, 0xBD, 0x88, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x90, 0xF8, 0x25, 0x30, 0xE3, 0xB1, 0x10, 0xB5, 0x0F, 0x4A, 0x10, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x01, 0xF5, ++0x9C, 0x51, 0x84, 0xB0, 0x04, 0x46, 0x08, 0x31, 0x0C, 0x48, 0x98, 0x47, 0x00, 0x21, 0x02, 0x22, 0x05, 0x23, 0x94, 0xF8, ++0x23, 0x00, 0xCD, 0xE9, 0x00, 0x32, 0xCD, 0xE9, 0x02, 0x11, 0x25, 0x23, 0x40, 0xF6, 0xC4, 0x12, 0xFD, 0xF7, 0x5E, 0xFF, ++0x04, 0xB0, 0x10, 0xBD, 0x03, 0x4A, 0xC2, 0xE9, 0x01, 0x33, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x94, 0x64, 0x17, 0x00, 0x03, 0x68, 0x70, 0xB4, 0xC3, 0xF3, 0xC2, 0x24, 0x05, 0x2C, 0x01, 0xD0, 0x70, 0xBC, 0x70, 0x47, ++0xC3, 0xF3, 0x00, 0x26, 0x75, 0x00, 0x03, 0xF0, 0x7F, 0x04, 0x35, 0x44, 0x04, 0xEB, 0x44, 0x04, 0x05, 0xEB, 0x44, 0x04, ++0xC3, 0xF3, 0x41, 0x25, 0x2C, 0x44, 0x16, 0x4D, 0x35, 0xF8, 0x14, 0x50, 0xC3, 0xF3, 0xC0, 0x14, 0x05, 0xFA, 0x04, 0xF4, ++0x01, 0x3A, 0x02, 0xFB, 0x04, 0xF2, 0x8A, 0x42, 0xC3, 0xF3, 0xC1, 0x14, 0xE2, 0xD2, 0x13, 0xF4, 0xE0, 0x3F, 0x06, 0xD0, ++0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x00, 0x43, 0x70, 0xBC, 0x03, 0x60, 0x70, 0x47, 0x03, 0xF0, 0x0F, 0x02, 0x02, 0x2A, ++0x23, 0xF0, 0xFF, 0x53, 0x8C, 0xBF, 0x4F, 0xF4, 0x80, 0x12, 0x4F, 0xF4, 0x00, 0x22, 0x23, 0xF4, 0xFE, 0x13, 0x42, 0xEA, ++0x04, 0x62, 0x13, 0x43, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF4, 0x00, 0x43, 0xE8, 0xE7, 0x00, 0xBF, 0xE0, 0x94, 0x15, 0x00, ++0x70, 0xB5, 0x0C, 0x4D, 0x00, 0xEB, 0x40, 0x03, 0x05, 0xEB, 0x83, 0x03, 0x93, 0xF8, 0x2E, 0x20, 0x72, 0xB1, 0x04, 0x46, ++0x46, 0x00, 0x58, 0x6A, 0x00, 0x22, 0x83, 0xF8, 0x2E, 0x20, 0x10, 0xB1, 0x21, 0x46, 0xFB, 0xF7, 0x35, 0xFF, 0x34, 0x44, ++0x05, 0xEB, 0x84, 0x05, 0x00, 0x23, 0x6B, 0x62, 0x70, 0xBD, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x41, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x41, 0x4F, ++0x41, 0x4E, 0x3B, 0x68, 0xDF, 0xF8, 0x0C, 0x81, 0x01, 0x33, 0x00, 0x24, 0x3B, 0x60, 0x35, 0x46, 0xA2, 0x46, 0x4F, 0xF0, ++0x01, 0x0B, 0x96, 0xF8, 0x60, 0x10, 0x0B, 0xFA, 0x04, 0xF3, 0x0B, 0x42, 0x5F, 0xFA, 0x83, 0xF9, 0x4D, 0xD1, 0x96, 0xF8, ++0x61, 0x10, 0x11, 0xEA, 0x09, 0x0F, 0x30, 0xD0, 0xA8, 0x6A, 0x21, 0xEA, 0x03, 0x03, 0x86, 0xF8, 0x61, 0x30, 0x03, 0x07, ++0x4F, 0xD0, 0x33, 0x4B, 0x43, 0xF8, 0x24, 0x00, 0xE0, 0xB2, 0xD8, 0xF8, 0xD0, 0x33, 0x98, 0x47, 0x95, 0xF8, 0x2C, 0x30, ++0x85, 0xF8, 0x2D, 0x30, 0x49, 0xEA, 0x0A, 0x0A, 0x01, 0x34, 0x04, 0x2C, 0x05, 0xF1, 0x0C, 0x05, 0xD9, 0xD1, 0xBA, 0xF1, ++0x00, 0x0F, 0x47, 0xD0, 0x29, 0x4A, 0x2A, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x29, 0x48, 0x01, 0xF5, 0x00, 0x51, ++0x98, 0x47, 0x3B, 0x68, 0x33, 0xB1, 0x20, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x95, 0xF8, 0x2D, 0x30, 0x00, 0x2B, 0xDE, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x85, 0xF8, ++0x2D, 0x30, 0x5B, 0xB9, 0x32, 0x69, 0xA3, 0x1C, 0xE0, 0xB2, 0x52, 0xF8, 0x23, 0x30, 0x17, 0x4A, 0x42, 0xF8, 0x24, 0x30, ++0xD8, 0xF8, 0xD0, 0x33, 0x98, 0x47, 0xCD, 0xE7, 0x49, 0xEA, 0x0A, 0x0A, 0xCA, 0xE7, 0xE0, 0xB2, 0x01, 0x93, 0xFF, 0xF7, ++0xBD, 0xFE, 0x01, 0x9B, 0x00, 0x28, 0xF5, 0xD0, 0x96, 0xF8, 0x60, 0x10, 0x21, 0xEA, 0x03, 0x01, 0x86, 0xF8, 0x60, 0x10, ++0xA3, 0xE7, 0x95, 0xF8, 0x2E, 0x30, 0x00, 0x2B, 0xB2, 0xD1, 0x85, 0xF8, 0x2E, 0xB0, 0x96, 0xF8, 0x60, 0x30, 0x49, 0xEA, ++0x03, 0x03, 0x86, 0xF8, 0x60, 0x30, 0xA9, 0xE7, 0xC6, 0xF8, 0x18, 0xA0, 0xBD, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0xA8, 0x64, 0x17, 0x00, 0x70, 0xB5, 0x14, 0x4C, 0x94, 0xF8, 0x62, 0x20, 0x4A, 0xB1, 0x94, 0xF8, 0x61, 0x20, 0xA5, 0x69, ++0x01, 0x21, 0x01, 0xFA, 0x00, 0xF3, 0x13, 0x43, 0x84, 0xF8, 0x61, 0x30, 0x05, 0xB1, 0x70, 0xBD, 0x0D, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0xDB, 0x0B, 0x4B, 0x0C, 0x48, 0xD3, 0xF8, 0xC8, 0x33, 0xA3, 0x61, 0xBD, 0xE8, ++0x70, 0x40, 0x18, 0x47, 0xFF, 0xF7, 0x74, 0xFE, 0x00, 0x28, 0xF3, 0xD1, 0xBD, 0xE8, 0x70, 0x40, 0x06, 0x49, 0x07, 0x48, ++0x4F, 0xF4, 0x22, 0x72, 0x12, 0xF0, 0xF4, 0xB9, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xA8, 0x64, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x93, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x1D, 0x4D, 0x1E, 0x4E, ++0x1E, 0x4F, 0xDF, 0xF8, 0x80, 0x80, 0xDF, 0xF8, 0x80, 0x90, 0x2B, 0x68, 0x00, 0x24, 0x01, 0x2C, 0x11, 0xD0, 0x53, 0xF8, ++0x24, 0x30, 0x1B, 0xB9, 0x33, 0x69, 0xA2, 0x1C, 0x53, 0xF8, 0x22, 0x30, 0x47, 0xF8, 0x24, 0x30, 0xE0, 0xB2, 0xFF, 0xF7, ++0xFB, 0xFE, 0x03, 0x2C, 0x0D, 0xD0, 0x01, 0x34, 0x01, 0x2C, 0x2B, 0x68, 0xED, 0xD1, 0x5B, 0x68, 0x73, 0xB9, 0x33, 0x69, ++0xDB, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x01, 0x20, 0xFF, 0xF7, 0xEC, 0xFE, 0xF1, 0xE7, 0x0D, 0x48, 0x08, 0xF0, 0x3C, 0xFC, ++0x00, 0x23, 0xB3, 0x61, 0xBD, 0xE8, 0xF8, 0x83, 0xC3, 0xF3, 0x0B, 0x02, 0x00, 0x2A, 0xEE, 0xD1, 0x32, 0x69, 0xD2, 0x68, ++0x03, 0xEA, 0x09, 0x03, 0xC2, 0xF3, 0x0B, 0x02, 0x13, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0xE6, 0xE7, 0xAC, 0x35, 0x17, 0x00, ++0x94, 0x64, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0xA8, 0x64, 0x17, 0x00, 0x04, 0x02, 0x32, 0x40, 0x00, 0xF0, 0xFF, 0xFF, ++0x1A, 0x4A, 0x1B, 0x4B, 0xF0, 0xB4, 0x02, 0xF1, 0x74, 0x04, 0x94, 0xE8, 0x03, 0x00, 0x16, 0x69, 0xC3, 0xF8, 0xE0, 0x03, ++0xF0, 0x6D, 0xA3, 0xF8, 0xE4, 0x13, 0xB6, 0xF8, 0x60, 0x10, 0xC3, 0xF8, 0xE6, 0x03, 0xA3, 0xF8, 0xEA, 0x13, 0x94, 0xE8, ++0x03, 0x00, 0xD3, 0xF8, 0xD4, 0x53, 0xA3, 0xF8, 0xF0, 0x13, 0xD1, 0x6E, 0xC3, 0xF8, 0xEC, 0x03, 0xC3, 0xF8, 0xF6, 0x13, ++0x0D, 0x4F, 0x0E, 0x48, 0x03, 0xF5, 0x88, 0x64, 0x00, 0x21, 0x82, 0xF8, 0x88, 0x10, 0xC3, 0xF8, 0xBC, 0x43, 0x05, 0xF4, ++0x7F, 0x45, 0x03, 0xF5, 0x66, 0x74, 0x4F, 0xF4, 0x00, 0x52, 0xC3, 0xF8, 0xD4, 0x53, 0xC3, 0xF8, 0x9C, 0x13, 0x3C, 0x60, ++0xF0, 0xBC, 0x02, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x60, 0x5D, 0x18, 0x00, 0xAC, 0x81, 0x32, 0x40, ++0x80, 0x81, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x68, 0xB2, 0x03, 0x68, 0x90, 0x4C, 0xDB, 0xF8, 0x10, 0x20, ++0x80, 0x46, 0x53, 0xF8, 0x26, 0x0F, 0xA0, 0x64, 0xD0, 0x6D, 0x9D, 0x88, 0xC4, 0xF8, 0x4E, 0x00, 0x18, 0x68, 0xB8, 0xF8, ++0x12, 0x10, 0x9B, 0x88, 0xB2, 0xF8, 0x60, 0x20, 0x60, 0x65, 0x00, 0x27, 0x83, 0xB0, 0x04, 0xF1, 0x5C, 0x00, 0xA4, 0xF8, ++0x4C, 0x50, 0xA4, 0xF8, 0x52, 0x20, 0xA4, 0xF8, 0x58, 0x30, 0xA7, 0x61, 0xFE, 0xF7, 0x78, 0xFC, 0x63, 0x6F, 0xD8, 0xF8, ++0x00, 0x10, 0x80, 0x4A, 0x91, 0xF8, 0x23, 0xC0, 0xA5, 0x69, 0xDE, 0x1C, 0x42, 0xF2, 0x38, 0x0E, 0x26, 0xF0, 0x03, 0x06, ++0x24, 0x23, 0x39, 0x46, 0x04, 0x36, 0x13, 0xFB, 0x0C, 0xE7, 0x06, 0xEB, 0x80, 0x06, 0x4F, 0xEA, 0x40, 0x2E, 0x17, 0x44, ++0xB6, 0xB2, 0x89, 0x46, 0x04, 0xF1, 0x5C, 0x02, 0xA4, 0x46, 0x4F, 0xF4, 0x20, 0x10, 0xF2, 0x46, 0x01, 0x97, 0x1C, 0xE0, ++0x0F, 0x33, 0x1B, 0x09, 0x1B, 0x02, 0x43, 0xF0, 0x30, 0x03, 0x9B, 0xB2, 0x4A, 0xEA, 0x00, 0x00, 0x0B, 0x43, 0x90, 0x63, ++0xC2, 0xF8, 0x24, 0x90, 0xC2, 0xF8, 0x3C, 0x90, 0xA2, 0xF8, 0x58, 0x30, 0xCC, 0xF8, 0x08, 0x20, 0xA5, 0x69, 0x35, 0x44, ++0xA5, 0x61, 0x94, 0x46, 0x4F, 0xF4, 0x40, 0x10, 0x01, 0x31, 0x09, 0x29, 0x02, 0xF1, 0x5C, 0x02, 0x22, 0xD0, 0x01, 0x9F, ++0x57, 0xF8, 0x04, 0x3B, 0x01, 0x97, 0x00, 0x2B, 0xF4, 0xD0, 0xD8, 0xF8, 0x08, 0x70, 0x06, 0xEB, 0x05, 0x0E, 0xBE, 0x45, ++0x16, 0xD8, 0xB3, 0xF5, 0x7C, 0x7F, 0xD3, 0xD9, 0xB3, 0xF5, 0x80, 0x6F, 0x0D, 0xD9, 0xB3, 0xF5, 0x86, 0x4F, 0x45, 0xD8, ++0x6F, 0xF4, 0x7C, 0x75, 0x2B, 0x44, 0xC3, 0xF3, 0x07, 0x13, 0x1B, 0x02, 0x43, 0xF4, 0x80, 0x43, 0x43, 0xF0, 0x30, 0x03, ++0xC8, 0xE7, 0x44, 0xF2, 0x30, 0x03, 0xC5, 0xE7, 0x00, 0x2D, 0x3B, 0xD0, 0xDC, 0xF8, 0x38, 0x30, 0x03, 0xF4, 0x60, 0x11, ++0x00, 0x22, 0xB1, 0xF5, 0x20, 0x1F, 0xCC, 0xF8, 0x08, 0x20, 0x63, 0xD0, 0x4C, 0x49, 0x4D, 0x4A, 0x4D, 0x4E, 0x43, 0xF4, ++0x60, 0x13, 0xCC, 0xF8, 0x38, 0x30, 0x0D, 0x68, 0x10, 0x68, 0x04, 0x35, 0xC0, 0xF3, 0x05, 0x20, 0x06, 0xE0, 0x33, 0x68, ++0xDB, 0x04, 0x08, 0xD4, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0x03, 0xF0, 0x3F, 0x03, 0x98, 0x42, ++0xF3, 0xD0, 0xE3, 0x6B, 0x42, 0x48, 0x43, 0x49, 0x43, 0x4A, 0x04, 0x60, 0x03, 0xF4, 0x7F, 0x43, 0xE3, 0x63, 0x4F, 0xF4, ++0x00, 0x50, 0x00, 0x23, 0x08, 0x60, 0x63, 0x60, 0x8B, 0xF8, 0x88, 0x30, 0x62, 0x62, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0xB3, 0xF5, 0x88, 0x4F, 0x1F, 0xD8, 0x48, 0xF2, 0x30, 0x03, 0x87, 0xE7, 0xD4, 0xF8, 0x98, 0x30, 0x37, 0x4A, 0x35, 0x4E, ++0x35, 0x49, 0xC4, 0xF8, 0x94, 0x50, 0x03, 0xF4, 0x7F, 0x43, 0xC4, 0xF8, 0x98, 0x30, 0xA2, 0xF5, 0x79, 0x73, 0xC4, 0xE9, ++0x18, 0x55, 0x8B, 0xF8, 0x88, 0x50, 0x4F, 0xF4, 0x00, 0x50, 0x33, 0x60, 0x30, 0x23, 0x08, 0x60, 0xA4, 0xF8, 0xB4, 0x30, ++0xC4, 0xF8, 0x80, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0xF5, 0x0F, 0x3F, 0x2A, 0xD9, 0xB3, 0xF5, 0x11, 0x3F, ++0x32, 0xD9, 0x28, 0x4D, 0xAB, 0x42, 0x32, 0xD8, 0xA3, 0xF1, 0x01, 0x13, 0xA3, 0xF5, 0x44, 0x43, 0xC3, 0xF3, 0xC7, 0x33, ++0x1B, 0x02, 0x43, 0xF4, 0x40, 0x43, 0x43, 0xF0, 0x30, 0x03, 0x55, 0xE7, 0xDC, 0xF8, 0x3C, 0x30, 0xCC, 0xF8, 0x38, 0x20, ++0xCC, 0xF8, 0x04, 0x20, 0x8B, 0xF8, 0x88, 0x20, 0x19, 0x48, 0x1A, 0x49, 0x1A, 0x4A, 0xCC, 0xF8, 0x24, 0x20, 0x03, 0xF4, ++0x7F, 0x43, 0xCC, 0xF8, 0x3C, 0x30, 0x4F, 0xF4, 0x00, 0x53, 0xC0, 0xF8, 0x00, 0xC0, 0x0B, 0x60, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0xA3, 0xF5, 0x70, 0x53, 0x01, 0x3B, 0xC3, 0xF3, 0xC7, 0x23, 0x1B, 0x02, 0x43, 0xF4, 0x00, 0x43, 0x43, 0xF0, ++0x30, 0x03, 0x31, 0xE7, 0x4C, 0xF2, 0x30, 0x03, 0x2E, 0xE7, 0x4F, 0xF6, 0x30, 0x65, 0x4F, 0xF6, 0x30, 0x77, 0xB3, 0xF1, ++0xFF, 0x3F, 0x08, 0xBF, 0x3D, 0x46, 0x2B, 0x46, 0x24, 0xE7, 0x00, 0xBF, 0x60, 0x5D, 0x18, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x20, 0x01, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x78, 0x80, 0x32, 0x40, 0xAC, 0x81, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, ++0xA0, 0x61, 0x18, 0x00, 0x00, 0xC4, 0x20, 0x00, 0x94, 0x64, 0x17, 0x00, 0x1C, 0x4A, 0x1D, 0x49, 0x13, 0x68, 0xF0, 0xB4, ++0x03, 0xF5, 0xDA, 0x53, 0x1B, 0x4F, 0x1C, 0x4E, 0x1C, 0x4C, 0x1D, 0x4D, 0x18, 0x33, 0x3B, 0x60, 0x40, 0x23, 0x33, 0x60, ++0x23, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x23, 0x60, 0x17, 0x68, 0x0C, 0x68, 0x01, 0x23, 0x10, 0x3E, 0x04, 0x37, 0xC4, 0xF3, ++0x05, 0x24, 0x85, 0xF8, 0x8C, 0x30, 0x06, 0xE0, 0x33, 0x68, 0xDB, 0x04, 0x08, 0xD4, 0x13, 0x68, 0xDB, 0x1B, 0x00, 0x2B, ++0x04, 0xDA, 0x0B, 0x68, 0x03, 0xF0, 0x3F, 0x03, 0x9C, 0x42, 0xF3, 0xD0, 0xC3, 0x6B, 0x0E, 0x4C, 0x0E, 0x4A, 0x0F, 0x49, ++0x42, 0x62, 0x03, 0xF4, 0x7F, 0x43, 0xC3, 0x63, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x53, 0x42, 0x60, 0x85, 0xF8, 0x88, 0x20, ++0x20, 0x60, 0xF0, 0xBC, 0x0B, 0x60, 0x70, 0x47, 0x20, 0x01, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x40, 0x01, 0x32, 0x40, ++0x88, 0x80, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0xAC, 0x81, 0x32, 0x40, 0xA0, 0x61, 0x18, 0x00, ++0x80, 0x81, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x10, 0x4F, 0x0C, 0x23, 0x0E, 0x46, 0x54, 0x25, 0x04, 0x46, 0x15, 0xFB, ++0x01, 0x30, 0x05, 0xFB, 0x06, 0x75, 0x38, 0x44, 0xD4, 0xF8, 0x4C, 0x80, 0x10, 0xF0, 0xEC, 0xFB, 0x95, 0xF8, 0x50, 0x30, ++0xA2, 0x88, 0x01, 0x3B, 0x85, 0xF8, 0x50, 0x30, 0x22, 0xB9, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFD, 0xF7, 0x22, 0xBA, ++0xD8, 0xF8, 0x50, 0x10, 0x32, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFC, 0xF7, 0xF6, 0xBB, 0x20, 0x62, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x00, 0x23, 0x2E, 0x4D, 0x03, 0x60, 0x95, 0xF8, 0x8C, 0x30, 0x82, 0xB0, 0x00, 0x2B, 0x37, 0xD1, ++0x95, 0xF8, 0x85, 0x30, 0x03, 0x2B, 0x33, 0xD8, 0x29, 0x4E, 0xDF, 0xF8, 0xB4, 0xA0, 0x81, 0x46, 0x4F, 0xF0, 0x03, 0x08, ++0x14, 0xE0, 0x95, 0xF8, 0x7E, 0x30, 0xDA, 0xF8, 0x64, 0x73, 0x00, 0x93, 0x2A, 0x6F, 0xB5, 0xF8, 0x7A, 0x30, 0x49, 0x46, ++0x20, 0x46, 0xB8, 0x47, 0x07, 0x46, 0x20, 0xBB, 0x95, 0xF8, 0x85, 0x30, 0x08, 0xF1, 0xFF, 0x38, 0x98, 0x45, 0xA6, 0xF1, ++0x54, 0x06, 0x17, 0xDB, 0x96, 0xF8, 0x16, 0x31, 0x5F, 0xFA, 0x88, 0xF7, 0x01, 0x2B, 0x85, 0xF8, 0x7E, 0x70, 0x0F, 0xD0, ++0xD6, 0xF8, 0x08, 0x41, 0x00, 0x2C, 0xEB, 0xD0, 0x63, 0x6A, 0x9B, 0x02, 0xDB, 0xD4, 0xE3, 0x6C, 0x1B, 0x6D, 0x00, 0x2B, ++0xD7, 0xDA, 0x20, 0x46, 0x39, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xEF, 0xE7, 0x00, 0x27, 0x38, 0x46, 0x02, 0xB0, 0xBD, 0xE8, ++0xF0, 0x87, 0x0E, 0x4B, 0x64, 0x6C, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0xDB, 0xA3, 0x88, 0x38, 0x46, ++0x43, 0xF4, 0x00, 0x73, 0xA3, 0x80, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x2C, 0xF5, 0xD1, 0x06, 0x49, 0x07, 0x48, ++0x40, 0xF2, 0xDF, 0x42, 0x11, 0xF0, 0x88, 0xFF, 0xEE, 0xE7, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xDF, 0xF8, 0x8C, 0x92, 0x99, 0xF8, 0x7E, 0x80, 0x83, 0xB0, 0x04, 0x46, 0x00, 0x27, 0x40, 0x46, 0x01, 0x97, 0xFB, 0xF7, ++0x0D, 0xFE, 0x99, 0xF8, 0x7E, 0x00, 0xFF, 0xF7, 0x15, 0xFA, 0x00, 0x2C, 0x00, 0xF0, 0xA4, 0x80, 0x63, 0x6A, 0x9E, 0x02, ++0x76, 0xD5, 0x03, 0xF4, 0x60, 0x10, 0xB0, 0xF5, 0x60, 0x1F, 0x65, 0x6C, 0x00, 0xF0, 0xE1, 0x80, 0xB0, 0xF5, 0x40, 0x1F, ++0x00, 0xF0, 0xCE, 0x80, 0xAA, 0x88, 0x02, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0x8E, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x01, 0xC0, ++0x00, 0xF0, 0xFF, 0x80, 0x2A, 0x6B, 0x52, 0x69, 0x00, 0x21, 0xC2, 0xF3, 0xC1, 0x1E, 0xC5, 0xE9, 0x0E, 0x11, 0x69, 0x63, ++0x0E, 0x46, 0x0A, 0x46, 0x14, 0xE0, 0xD1, 0xF8, 0x4C, 0x31, 0x9A, 0x45, 0x02, 0xF1, 0x01, 0x03, 0x22, 0xD9, 0xDA, 0xB2, ++0x05, 0xEB, 0x82, 0x03, 0xB0, 0xF5, 0x60, 0x1F, 0x4E, 0x63, 0x56, 0x46, 0xC3, 0xF8, 0x3C, 0x41, 0x20, 0xD0, 0x24, 0x68, ++0x34, 0xB3, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x10, 0xE1, 0x6C, 0xD1, 0xF8, 0x2C, 0xA0, 0xC3, 0xF3, 0x49, 0x2B, 0x0A, 0xF1, ++0x03, 0x03, 0x23, 0xF0, 0x03, 0x03, 0x0B, 0xF1, 0x01, 0x0A, 0x03, 0xEB, 0x8A, 0x03, 0x9B, 0xB2, 0x96, 0x45, 0x05, 0xEB, ++0x82, 0x01, 0x03, 0xEB, 0x06, 0x0A, 0xD6, 0xD8, 0x05, 0xEB, 0x82, 0x03, 0xB0, 0xF5, 0x60, 0x1F, 0x56, 0x46, 0xC3, 0xF8, ++0x3C, 0x41, 0xDE, 0xD1, 0x6B, 0x6A, 0xB3, 0x42, 0x00, 0xF0, 0xCE, 0x80, 0x00, 0x23, 0xC5, 0xE9, 0x0D, 0x33, 0xEB, 0x63, ++0x00, 0x2F, 0x49, 0xD0, 0x08, 0xEB, 0x48, 0x03, 0x09, 0xEB, 0x83, 0x09, 0x01, 0x9A, 0xC9, 0xF8, 0x24, 0x70, 0xBC, 0xF1, ++0x00, 0x0F, 0x30, 0xD1, 0x93, 0x6B, 0x9B, 0x02, 0x00, 0xF1, 0x97, 0x80, 0x53, 0x68, 0x00, 0x2B, 0x4B, 0xD1, 0x61, 0x49, ++0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x01, 0xEB, 0x08, 0x03, 0xC3, 0xE9, 0x01, 0xCC, 0x41, 0xF8, 0x08, 0x20, 0x40, 0xE0, ++0xA3, 0x6C, 0x3B, 0xB3, 0xE3, 0x8B, 0xE2, 0x6C, 0x13, 0xF4, 0x00, 0x5F, 0xE3, 0x6A, 0xDB, 0x6B, 0x02, 0xF1, 0x14, 0x07, ++0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0x01, 0x97, 0x93, 0xB3, 0x52, 0x4B, 0x1B, 0x68, 0x93, 0xF8, ++0x01, 0xC0, 0x3A, 0x46, 0x08, 0xEB, 0x48, 0x03, 0x09, 0xEB, 0x83, 0x09, 0xC9, 0xF8, 0x24, 0x70, 0xBC, 0xF1, 0x00, 0x0F, ++0xCE, 0xD0, 0x53, 0x68, 0xFB, 0xB9, 0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x49, 0x4B, 0x43, 0xF8, 0x08, 0x20, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x45, 0x4B, 0x1B, 0x68, 0x93, 0xF8, 0x01, 0xC0, 0x44, 0x4B, 0x54, 0x22, 0x08, 0xEB, 0x48, 0x01, ++0x09, 0xEB, 0x81, 0x09, 0x02, 0xFB, 0x08, 0xF8, 0x00, 0x22, 0x43, 0xF8, 0x08, 0x20, 0xC9, 0xF8, 0x24, 0x20, 0x43, 0x44, ++0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0xC3, 0xE9, 0x01, 0xCC, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x50, 0x6A, 0x03, 0x88, ++0x1D, 0x04, 0x99, 0xB2, 0xC7, 0xD5, 0xC1, 0xF3, 0x0E, 0x01, 0x01, 0x80, 0x94, 0xF8, 0x33, 0x10, 0x94, 0xF8, 0x32, 0x30, ++0x32, 0x48, 0x04, 0x39, 0x04, 0x3B, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x32, 0x30, 0xD2, 0xE9, 0x0A, 0x31, 0x04, 0x39, ++0x04, 0x3B, 0xC2, 0xE9, 0x0A, 0x31, 0x00, 0x68, 0x3A, 0x46, 0x90, 0xF8, 0x01, 0xC0, 0xB3, 0xE7, 0x2B, 0x4B, 0x01, 0xA9, ++0xD3, 0xF8, 0x6C, 0x33, 0x20, 0x46, 0x98, 0x47, 0x26, 0x4A, 0x63, 0x6A, 0x12, 0x68, 0x07, 0x46, 0x92, 0xF8, 0x01, 0xC0, ++0x03, 0xF4, 0x60, 0x10, 0x2C, 0xE7, 0x24, 0x4B, 0x21, 0x4E, 0xD3, 0xF8, 0x58, 0x33, 0x39, 0x46, 0x20, 0x46, 0x98, 0x47, ++0x33, 0x68, 0x01, 0x90, 0x5B, 0x78, 0x07, 0x46, 0xD3, 0xB1, 0x08, 0xB1, 0x6B, 0x6D, 0x43, 0x60, 0xD5, 0xF8, 0x48, 0x01, ++0x29, 0x46, 0x10, 0xF0, 0x13, 0xFA, 0x33, 0x68, 0x93, 0xF8, 0x01, 0xC0, 0x58, 0xE7, 0x7B, 0x68, 0x00, 0x2B, 0xB4, 0xD1, ++0x15, 0x49, 0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x01, 0xEB, 0x08, 0x03, 0x01, 0x20, 0xC3, 0xE9, 0x01, 0x70, 0x41, 0xF8, ++0x08, 0x20, 0xA8, 0xE7, 0x00, 0x28, 0xE5, 0xD0, 0x2B, 0x69, 0x43, 0x60, 0xE2, 0xE7, 0x05, 0xF1, 0x0C, 0x07, 0xBC, 0xF1, ++0x00, 0x0F, 0x03, 0xD0, 0x05, 0xF1, 0x50, 0x02, 0x01, 0x92, 0xF7, 0xE6, 0xD5, 0xF8, 0x38, 0x21, 0xD2, 0x6C, 0x14, 0x32, ++0x01, 0x92, 0xF1, 0xE6, 0xD5, 0xF8, 0x38, 0x31, 0xA3, 0x42, 0x7F, 0xF4, 0x2D, 0xAF, 0x05, 0xEB, 0x82, 0x02, 0x56, 0x63, ++0x2C, 0xE7, 0x00, 0xBF, 0x34, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x70, 0xB5, 0x1E, 0x48, 0x82, 0xB0, 0x90, 0xF8, 0x88, 0x30, 0x00, 0x22, 0x01, 0x92, 0x93, 0xB1, 0x90, 0xF8, 0x7F, 0x30, ++0x04, 0x2B, 0x2A, 0xD0, 0x19, 0x4C, 0x01, 0xA8, 0xD4, 0xF8, 0xE8, 0x33, 0x98, 0x47, 0x08, 0xB3, 0xD4, 0xF8, 0xF8, 0x33, ++0x98, 0x47, 0xD4, 0xF8, 0xD4, 0x33, 0x01, 0x98, 0x98, 0x47, 0x02, 0xB0, 0x70, 0xBD, 0x13, 0x4A, 0x13, 0x4D, 0xD2, 0xF8, ++0x38, 0x14, 0x13, 0x4C, 0x80, 0xF8, 0x88, 0x30, 0xC2, 0xF8, 0x00, 0x34, 0x01, 0xF4, 0x7F, 0x41, 0x02, 0xF5, 0x88, 0x66, ++0x02, 0xF5, 0x7F, 0x70, 0x4F, 0xF4, 0x00, 0x53, 0xC2, 0xF8, 0x38, 0x14, 0xC2, 0xF8, 0x20, 0x64, 0x28, 0x60, 0x23, 0x60, ++0x02, 0xB0, 0x70, 0xBD, 0xFF, 0xF7, 0x28, 0xFC, 0xE1, 0xE7, 0x04, 0x4B, 0x68, 0x30, 0xD3, 0xF8, 0xF4, 0x33, 0x98, 0x47, ++0x02, 0xB0, 0x70, 0xBD, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x60, 0x5D, 0x18, 0x00, 0xAC, 0x81, 0x32, 0x40, ++0x80, 0x81, 0x32, 0x40, 0xF8, 0xB5, 0x2C, 0x4C, 0x2C, 0x4D, 0x40, 0xF2, 0x74, 0x42, 0x20, 0x46, 0x00, 0x21, 0x26, 0x46, ++0xED, 0xF7, 0xF4, 0xF8, 0x4F, 0xF4, 0xE4, 0x73, 0x28, 0x4A, 0x26, 0xF8, 0x44, 0x3F, 0x4F, 0xF6, 0x30, 0x70, 0x48, 0xF2, ++0xC8, 0x13, 0x04, 0xF5, 0x77, 0x77, 0x4F, 0xF0, 0x22, 0x0C, 0x04, 0xF2, 0xFD, 0x31, 0xC4, 0xF8, 0x40, 0x24, 0xA4, 0xF8, ++0xDC, 0x33, 0xA4, 0xF8, 0xF4, 0x03, 0x04, 0xF5, 0x88, 0x63, 0x00, 0x20, 0x4F, 0xF4, 0x00, 0x12, 0xDF, 0xF8, 0x74, 0xE0, ++0xC4, 0xF8, 0xB0, 0xC3, 0xC4, 0xE9, 0xEA, 0x71, 0xC4, 0xF8, 0xBC, 0x33, 0xC4, 0xF8, 0x20, 0x34, 0x63, 0x62, 0xA2, 0x63, ++0xC4, 0xF8, 0x98, 0x53, 0xC4, 0xF8, 0xFC, 0x53, 0x25, 0x60, 0xC4, 0xF8, 0xA4, 0x03, 0xC4, 0xF8, 0xCC, 0x03, 0xC4, 0xF8, ++0x30, 0x04, 0x04, 0xF1, 0x5B, 0x0C, 0x04, 0xF1, 0xB4, 0x03, 0x1E, 0x27, 0x04, 0xF5, 0x7C, 0x74, 0xA3, 0xF1, 0x14, 0x01, ++0x5A, 0x1C, 0x43, 0xF8, 0x58, 0x5C, 0x43, 0xF8, 0x40, 0x7C, 0x43, 0xF8, 0x24, 0x0C, 0x43, 0xF8, 0x14, 0xEC, 0x43, 0xF8, ++0x4C, 0x1C, 0x43, 0xF8, 0x08, 0x2C, 0x43, 0xE9, 0x12, 0x6C, 0x43, 0xF8, 0x0C, 0x3C, 0x5C, 0x33, 0x9C, 0x42, 0xE9, 0xD1, ++0xF8, 0xBD, 0x00, 0xBF, 0x60, 0x5D, 0x18, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, 0x1E, 0xAB, 0xDC, 0xBA, 0xDE, 0xFA, 0xFE, 0xCA, ++0x2D, 0xE9, 0xF0, 0x41, 0x13, 0x4A, 0x14, 0x4B, 0x92, 0xF8, 0x7E, 0x40, 0xD3, 0xF8, 0xAC, 0x33, 0x12, 0x4F, 0x00, 0x22, ++0x0E, 0x46, 0x21, 0x46, 0x05, 0x46, 0x4F, 0xF0, 0x54, 0x08, 0x98, 0x47, 0x0C, 0x20, 0x18, 0xFB, 0x04, 0x00, 0x38, 0x44, ++0x10, 0xF0, 0x5E, 0xF9, 0x22, 0x46, 0x31, 0x46, 0x28, 0x46, 0xFC, 0xF7, 0x77, 0xF9, 0x6B, 0x6A, 0x03, 0xF4, 0x60, 0x13, ++0xB3, 0xF5, 0x60, 0x1F, 0x05, 0xD1, 0x08, 0xFB, 0x04, 0x74, 0x6B, 0x6C, 0x63, 0x62, 0x02, 0x23, 0xA3, 0x76, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x90, 0xF8, 0x62, 0x40, 0x87, 0xB0, 0x84, 0xB9, 0x90, 0xF8, 0x64, 0x30, 0x6B, 0xB1, 0x90, 0xF8, 0x6C, 0x30, 0x58, 0x4A, ++0x01, 0x93, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x03, 0x25, 0x95, 0xF8, 0x25, 0x30, 0x13, 0xB1, 0x6B, 0x68, 0x9B, 0x06, ++0x02, 0xD4, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x10, 0x22, 0x21, 0x46, 0x02, 0xA8, 0xED, 0xF7, 0x4D, 0xF8, 0x95, 0xF8, ++0x23, 0x30, 0x4E, 0x4A, 0x4E, 0x49, 0x00, 0x94, 0x42, 0xF2, 0x34, 0x06, 0x03, 0xEB, 0xC3, 0x03, 0x06, 0xEB, 0x83, 0x03, ++0x9E, 0x18, 0x01, 0xF1, 0x08, 0x0B, 0xA6, 0x46, 0x22, 0x46, 0xA2, 0x46, 0x20, 0x46, 0x56, 0xF8, 0x04, 0x3F, 0xB3, 0xF5, ++0xFE, 0x0F, 0x1F, 0x46, 0x04, 0xF1, 0x01, 0x08, 0x28, 0xBF, 0x4F, 0xF4, 0xFE, 0x07, 0xF3, 0xB1, 0x42, 0x4C, 0x0B, 0x78, ++0xE3, 0x5C, 0x06, 0xAC, 0x04, 0xEB, 0x83, 0x0C, 0x22, 0xFA, 0x03, 0xF9, 0x5C, 0xF8, 0x10, 0x5C, 0x3D, 0x44, 0x55, 0x45, ++0x84, 0xBF, 0xAA, 0x46, 0x00, 0x93, 0x19, 0xF0, 0x01, 0x0F, 0x5F, 0xFA, 0x88, 0xF4, 0x38, 0x44, 0x4C, 0xF8, 0x10, 0x5C, ++0x07, 0xD1, 0x01, 0x25, 0x05, 0xFA, 0x03, 0xF3, 0x1A, 0x43, 0xAE, 0x44, 0xD2, 0xB2, 0x5F, 0xFA, 0x8E, 0xFE, 0x01, 0x31, ++0x8B, 0x45, 0xD2, 0xD1, 0x08, 0x2C, 0x41, 0xD0, 0xA4, 0xEB, 0x0E, 0x04, 0xE4, 0xB2, 0xA4, 0x02, 0x92, 0x01, 0xB0, 0xF5, ++0x7D, 0x6F, 0x1E, 0xD8, 0x0F, 0x30, 0x0A, 0xF1, 0x0F, 0x0A, 0xC0, 0xF3, 0x07, 0x13, 0xCA, 0xF3, 0x07, 0x1A, 0x00, 0x21, ++0x00, 0x98, 0x1B, 0x06, 0x43, 0xEA, 0x00, 0x33, 0x13, 0x43, 0x23, 0x43, 0x0B, 0x43, 0x01, 0x99, 0x08, 0x46, 0x21, 0x49, ++0x4F, 0xF4, 0x1E, 0x72, 0x43, 0xEA, 0x0A, 0x43, 0x02, 0xFB, 0x00, 0x12, 0x43, 0xF0, 0x0F, 0x03, 0xC2, 0xF8, 0x04, 0x32, ++0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB0, 0xF5, 0x7D, 0x4F, 0x0D, 0xD9, 0xB0, 0xF5, 0xFD, 0x2F, 0x18, 0xD8, 0x00, 0xF2, ++0xFF, 0x70, 0x0A, 0xF2, 0xFF, 0x7A, 0xC0, 0xF3, 0xC7, 0x23, 0xCA, 0xF3, 0xC7, 0x2A, 0x4F, 0xF4, 0x00, 0x41, 0xD7, 0xE7, ++0xFF, 0x30, 0x0A, 0xF1, 0xFF, 0x0A, 0xC0, 0xF3, 0x07, 0x23, 0xCA, 0xF3, 0x07, 0x2A, 0x4F, 0xF4, 0x80, 0x41, 0xCD, 0xE7, ++0x4F, 0xF4, 0x40, 0x64, 0x00, 0x22, 0xBE, 0xE7, 0x47, 0xF6, 0xFF, 0x73, 0xBA, 0xF5, 0xFE, 0x0F, 0x94, 0xBF, 0x9A, 0x44, ++0x03, 0xF5, 0xFE, 0x0A, 0xB0, 0xF5, 0xFE, 0x0F, 0x94, 0xBF, 0x18, 0x18, 0x03, 0xF5, 0xFE, 0x00, 0xC0, 0xF3, 0xC7, 0x33, ++0xCA, 0xF3, 0xC7, 0x3A, 0x4F, 0xF4, 0x40, 0x41, 0xB4, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0xC0, 0xB2, 0x15, 0x00, 0xA0, 0xB2, 0x15, 0x00, 0x49, 0x4B, 0x4A, 0x4A, 0x4F, 0xF4, 0x80, 0x11, 0x2D, 0xE9, 0xF0, 0x47, ++0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x1F, 0xFB, 0xD1, 0xDF, 0xF8, 0x34, 0x81, 0x45, 0x4A, 0x98, 0xF8, 0x8C, 0x30, ++0x4F, 0xF4, 0x80, 0x11, 0x11, 0x60, 0x00, 0x2B, 0x6E, 0xD0, 0x98, 0xF8, 0x7E, 0x60, 0xDF, 0xF8, 0x20, 0x91, 0x54, 0x23, ++0x03, 0xFB, 0x06, 0x93, 0x9A, 0x7E, 0x00, 0x2A, 0x38, 0xD0, 0x54, 0x20, 0x00, 0xFB, 0x06, 0x94, 0x20, 0x46, 0x62, 0x6A, ++0x93, 0x88, 0x43, 0xF0, 0x10, 0x03, 0x93, 0x80, 0x1C, 0x30, 0x10, 0xF0, 0x55, 0xF8, 0x37, 0x4B, 0x53, 0xF8, 0x26, 0x00, ++0x0F, 0xF0, 0x6A, 0xFF, 0x00, 0x23, 0xA3, 0x76, 0x63, 0x62, 0x06, 0xEB, 0x46, 0x04, 0x08, 0xEB, 0x84, 0x04, 0x94, 0xF8, ++0x2E, 0x50, 0x2D, 0xB9, 0x60, 0x6A, 0x18, 0xB1, 0x31, 0x46, 0xFB, 0xF7, 0x93, 0xF8, 0x65, 0x62, 0x2D, 0x4A, 0x2E, 0x49, ++0x13, 0x68, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x99, 0x40, 0x22, 0x0A, 0x60, 0x99, 0xF8, ++0x50, 0x30, 0x00, 0x22, 0x01, 0x3B, 0x30, 0x46, 0x89, 0xF8, 0x50, 0x30, 0x88, 0xF8, 0x8C, 0x20, 0xBD, 0xE8, 0xF0, 0x47, ++0xFE, 0xF7, 0x66, 0xBE, 0xDC, 0x68, 0x62, 0x6A, 0x92, 0x02, 0x2D, 0xD4, 0x54, 0x25, 0xDF, 0xF8, 0x98, 0xA0, 0x20, 0x4F, ++0x05, 0xFB, 0x06, 0x95, 0x11, 0xE0, 0xE3, 0x6C, 0x62, 0x6A, 0x19, 0x6D, 0x41, 0xF0, 0x00, 0x41, 0x41, 0xF4, 0x80, 0x01, ++0x19, 0x65, 0x93, 0x02, 0x20, 0x46, 0x17, 0xD5, 0xD7, 0xF8, 0xD8, 0x33, 0x98, 0x47, 0xAB, 0x7E, 0xEC, 0x68, 0x00, 0x2B, ++0xA9, 0xD1, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE7, 0xDA, 0x00, 0x2C, 0xE5, 0xD1, 0x12, 0x49, ++0x12, 0x48, 0x40, 0xF2, 0xB3, 0x72, 0x11, 0xF0, 0x0D, 0xFC, 0xDE, 0xE7, 0xBD, 0xE8, 0xF0, 0x87, 0xD7, 0xF8, 0xE4, 0x33, ++0x98, 0x47, 0xA8, 0xE7, 0x5A, 0x69, 0x61, 0x6C, 0x52, 0x6C, 0x8A, 0x42, 0xCC, 0xD1, 0xD2, 0xF8, 0x38, 0x21, 0x12, 0x68, ++0x5A, 0x61, 0xC7, 0xE7, 0x80, 0x81, 0x32, 0x40, 0x88, 0x81, 0x32, 0x40, 0x84, 0x81, 0x32, 0x40, 0xC4, 0x90, 0x15, 0x00, ++0x8C, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, ++0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x69, 0x4F, 0xDF, 0xF8, ++0xCC, 0x81, 0x97, 0xF8, 0x7E, 0x60, 0x54, 0x25, 0x05, 0xFB, 0x06, 0x85, 0xAB, 0x7E, 0x53, 0xBB, 0xDF, 0xF8, 0xA0, 0xA1, ++0xDF, 0xF8, 0xAC, 0x91, 0x15, 0xE0, 0xD4, 0xF8, 0x4C, 0xC0, 0xDF, 0xF8, 0xA0, 0xE1, 0xDC, 0xF8, 0x50, 0x30, 0x43, 0xF4, ++0x80, 0x02, 0x00, 0x2B, 0x20, 0x46, 0x11, 0x46, 0x26, 0xDA, 0x63, 0x6A, 0xCC, 0xF8, 0x50, 0x20, 0x9C, 0x02, 0x23, 0xD5, ++0xDE, 0xF8, 0xD8, 0x33, 0x98, 0x47, 0xAB, 0x7E, 0x7B, 0xB9, 0xDA, 0xF8, 0x00, 0x30, 0xEC, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xE2, 0xDA, 0x00, 0x2C, 0xE0, 0xD1, 0x53, 0x48, 0x4F, 0xF4, 0x02, 0x62, 0x49, 0x46, 0x11, 0xF0, 0xAE, 0xFB, ++0xD9, 0xE7, 0x54, 0x22, 0x02, 0xFB, 0x06, 0x82, 0x02, 0x2B, 0x54, 0x6A, 0x0C, 0xBF, 0x04, 0xF1, 0x0C, 0x03, 0x04, 0xF1, ++0x50, 0x03, 0xDB, 0x6B, 0x00, 0x2B, 0x29, 0xDB, 0xBD, 0xE8, 0xF0, 0x87, 0xDE, 0xF8, 0xE4, 0x33, 0x98, 0x47, 0x06, 0xEB, ++0x46, 0x04, 0x07, 0xEB, 0x84, 0x04, 0x94, 0xF8, 0x2E, 0x50, 0x2D, 0xB9, 0x60, 0x6A, 0x18, 0xB1, 0x31, 0x46, 0xFA, 0xF7, ++0xD1, 0xFF, 0x65, 0x62, 0x41, 0x4A, 0x42, 0x49, 0x13, 0x68, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x54, 0x23, 0x03, 0xFB, ++0x06, 0x88, 0x40, 0x22, 0x0A, 0x60, 0x98, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x3B, 0x30, 0x46, 0x88, 0xF8, 0x50, 0x30, ++0x87, 0xF8, 0x8C, 0x20, 0xBD, 0xE8, 0xF0, 0x47, 0xFE, 0xF7, 0xA4, 0xBD, 0x18, 0x02, 0x35, 0xD5, 0xA3, 0x88, 0x99, 0x06, ++0x13, 0xD4, 0xDF, 0xF8, 0xE0, 0x90, 0xD9, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x04, 0x25, 0xA3, 0x88, 0x9A, 0x06, 0x0A, 0xD4, ++0xD9, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x01, 0x3D, 0xF7, 0xD1, 0x2E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x42, 0xDB, 0x97, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x37, 0xD0, 0x2A, 0x49, 0x97, 0xF8, 0x64, 0x30, 0x0A, 0x68, 0x1B, 0x06, ++0x22, 0xF0, 0xE0, 0x62, 0x03, 0xF0, 0xE0, 0x63, 0x13, 0x43, 0x0B, 0x60, 0xA3, 0x88, 0x25, 0x4A, 0x43, 0xF0, 0x10, 0x03, ++0x52, 0xF8, 0x26, 0x00, 0xA3, 0x80, 0x0F, 0xF0, 0x4F, 0xFE, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x83, 0x00, 0x22, 0x9A, 0x76, ++0x5A, 0x62, 0xA2, 0xE7, 0x54, 0x20, 0x00, 0xFB, 0x06, 0x80, 0x1C, 0x30, 0x0F, 0xF0, 0x28, 0xFF, 0x97, 0xF8, 0x87, 0x30, ++0x00, 0x2B, 0xE5, 0xD0, 0x17, 0x4A, 0x97, 0xF8, 0x65, 0x00, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, 0x02, 0x63, 0x01, 0x33, ++0x83, 0x42, 0x28, 0xBF, 0x03, 0x46, 0x1B, 0x06, 0x03, 0xF0, 0xE0, 0x63, 0x21, 0xF0, 0xE0, 0x61, 0x0B, 0x43, 0x13, 0x60, ++0xD2, 0xE7, 0x10, 0x4B, 0x97, 0xF8, 0x7E, 0x00, 0xD3, 0xF8, 0xC0, 0x33, 0x98, 0x47, 0xCB, 0xE7, 0xA3, 0x88, 0x9B, 0x06, ++0xB9, 0xD4, 0xBD, 0xE8, 0xF0, 0x47, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0x6A, 0x02, 0x11, 0xF0, 0xDD, 0xBA, 0x00, 0xBF, ++0x94, 0x64, 0x17, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x54, 0x83, 0x32, 0x40, 0xC4, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD4, 0x8E, 0x15, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x10, 0xB5, 0x0D, 0x4C, 0x90, 0x22, 0x00, 0x21, 0x20, 0x46, 0xEC, 0xF7, 0x09, 0xFE, 0xFF, 0xF7, ++0x09, 0xFD, 0x40, 0xF2, 0xD3, 0x13, 0xE3, 0x66, 0xED, 0xF7, 0xA4, 0xFE, 0x07, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x70, 0x43, ++0x18, 0xB1, 0x43, 0xF0, 0x30, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x43, 0xF0, 0x10, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, ++0x94, 0x64, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x43, 0x2A, 0x4C, 0x65, 0x68, 0x95, 0xB0, 0x00, 0x2D, ++0x44, 0xD0, 0x29, 0x4E, 0xA7, 0x68, 0xD6, 0xF8, 0xD8, 0x31, 0x20, 0x46, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0x80, 0xB8, 0xF1, ++0x00, 0x0F, 0x26, 0xD0, 0x01, 0x25, 0x24, 0x49, 0x68, 0x46, 0x50, 0x22, 0x23, 0xF0, 0x66, 0xFD, 0xA3, 0x69, 0x94, 0xF8, ++0x62, 0x90, 0x23, 0xB1, 0x1E, 0x4E, 0x1F, 0x48, 0xD6, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xFF, 0xF7, 0xBD, 0xFF, 0xC4, 0xF8, ++0x10, 0x80, 0x84, 0xF8, 0x62, 0x90, 0x18, 0x4C, 0x6B, 0x46, 0x22, 0x46, 0x0C, 0xAE, 0x58, 0x69, 0x19, 0x7E, 0x90, 0x62, ++0x0C, 0x33, 0xB3, 0x42, 0x82, 0xF8, 0x2C, 0x10, 0x02, 0xF1, 0x0C, 0x02, 0xF5, 0xD1, 0xFD, 0xB9, 0x15, 0xB0, 0xBD, 0xE8, ++0xF0, 0x83, 0xFF, 0xF7, 0xA5, 0xFF, 0xC4, 0xF8, 0x10, 0x80, 0x10, 0x4B, 0x10, 0x4A, 0x19, 0x69, 0x0B, 0x48, 0xD6, 0xF8, ++0xE0, 0x31, 0xA7, 0x60, 0x01, 0xF5, 0x9C, 0x51, 0x08, 0x31, 0x62, 0x60, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, ++0xD4, 0xF8, 0x10, 0x80, 0xB8, 0xF1, 0x00, 0x0F, 0xC1, 0xD1, 0xFF, 0xF7, 0x8D, 0xFF, 0xC4, 0xF8, 0x10, 0x80, 0xDF, 0xE7, ++0x01, 0x4E, 0xE4, 0xE7, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xA8, 0x64, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x95, 0x24, 0x13, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x42, 0x6D, 0xC3, 0x69, 0x91, 0xF8, 0x09, 0xC0, 0x9D, 0x68, 0x03, 0x8E, ++0x88, 0x46, 0x91, 0x05, 0x02, 0xD5, 0x12, 0xF4, 0x80, 0x60, 0x3B, 0xD0, 0x12, 0x3B, 0x01, 0x2B, 0x05, 0xF1, 0x12, 0x05, ++0x3A, 0xDD, 0x28, 0x4A, 0xDF, 0xF8, 0xA0, 0x90, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x0C, 0x2C, 0x40, 0xF2, 0xFD, 0x7E, ++0x15, 0xE0, 0x03, 0x2B, 0x2A, 0xDD, 0x6A, 0x88, 0x12, 0xF0, 0x08, 0x06, 0xC2, 0xF3, 0x42, 0x01, 0x24, 0xD1, 0x19, 0xF8, ++0x01, 0x20, 0x04, 0x32, 0x9A, 0x42, 0x2B, 0xDC, 0xBC, 0xF8, 0x20, 0x10, 0xB9, 0x42, 0xA3, 0xEB, 0x02, 0x03, 0x11, 0xD0, ++0x01, 0x2B, 0x15, 0x44, 0x1A, 0xDD, 0x2C, 0x88, 0xC4, 0xF3, 0x0A, 0x07, 0x77, 0x45, 0x13, 0xD0, 0x14, 0xF4, 0x00, 0x60, ++0xE1, 0xD0, 0xBC, 0xF8, 0x20, 0x10, 0x02, 0x22, 0xB9, 0x42, 0xA3, 0xEB, 0x02, 0x03, 0xED, 0xD1, 0x14, 0xF4, 0x00, 0x60, ++0x0B, 0xD1, 0x98, 0xF8, 0x0A, 0x30, 0xB3, 0xEB, 0x14, 0x3F, 0x0D, 0xD0, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x22, 0xDB, 0xE7, ++0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0x23, 0xC8, 0xF8, 0xDC, 0x30, 0x01, 0x20, 0xF3, 0xE7, 0x30, 0x46, 0xF1, 0xE7, ++0x08, 0xF1, 0xE0, 0x04, 0x02, 0x3A, 0xA9, 0x1C, 0x20, 0x46, 0x23, 0xF0, 0xBD, 0xFC, 0xC8, 0xF8, 0xDC, 0x40, 0x01, 0x20, ++0xE6, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x00, 0x96, 0x15, 0x00, 0x85, 0x4B, 0x86, 0x4A, 0x19, 0x68, 0x43, 0x6D, ++0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0x24, 0xC5, 0x69, 0x82, 0xF8, 0x88, 0x40, 0xB1, 0xF9, 0x00, 0x10, 0xA1, 0x42, 0x83, 0xB0, ++0xC0, 0xF2, 0xC6, 0x80, 0x9E, 0x01, 0x40, 0xF1, 0xAD, 0x80, 0x00, 0x29, 0xC3, 0xF3, 0xCF, 0x30, 0xC3, 0xF3, 0xC9, 0x33, ++0xC0, 0xF2, 0xB3, 0x80, 0x7A, 0x49, 0x10, 0x3B, 0xDB, 0xB2, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x03, 0x14, 0x94, 0xF8, ++0x25, 0x00, 0x00, 0x28, 0x00, 0xF0, 0x9A, 0x80, 0x94, 0xF8, 0x22, 0x50, 0x54, 0xF8, 0x26, 0x0F, 0x50, 0x67, 0x73, 0x48, ++0x73, 0x4E, 0xA4, 0x88, 0x84, 0x80, 0x4F, 0xF4, 0xA4, 0x67, 0x10, 0x69, 0x07, 0xFB, 0x05, 0x65, 0xA8, 0x42, 0x40, 0xF0, ++0x93, 0x80, 0x6F, 0x48, 0x00, 0x68, 0x00, 0xF0, 0x3F, 0x00, 0x09, 0x28, 0x40, 0xF2, 0x8C, 0x80, 0x6C, 0x4C, 0x6D, 0x48, ++0x24, 0x68, 0x05, 0x68, 0xD2, 0xF8, 0x68, 0x80, 0xC4, 0xF3, 0x0B, 0x10, 0x04, 0xF0, 0x0F, 0x09, 0xC4, 0xF3, 0x01, 0x4E, ++0x24, 0x03, 0x00, 0x90, 0xA2, 0xF8, 0x7C, 0x00, 0x82, 0xF8, 0x7F, 0x90, 0x82, 0xF8, 0x83, 0xE0, 0xC5, 0xF3, 0x03, 0x10, ++0x05, 0xF0, 0x07, 0x06, 0x40, 0xF1, 0x8B, 0x80, 0x4F, 0xF0, 0x02, 0x0B, 0x4F, 0xF4, 0x80, 0x64, 0x5F, 0x46, 0x01, 0x94, ++0xC5, 0xF3, 0x00, 0x34, 0xC5, 0xF3, 0x42, 0x2C, 0x82, 0xF8, 0x80, 0x70, 0xF7, 0xB2, 0x82, 0xF8, 0x81, 0x00, 0x82, 0xF8, ++0x87, 0x40, 0x82, 0xF8, 0x82, 0xC0, 0x82, 0xF8, 0x84, 0x70, 0xB9, 0xF1, 0x00, 0x0F, 0x79, 0xD0, 0x92, 0xF8, 0x86, 0x50, ++0xDF, 0xF8, 0x64, 0x91, 0xD9, 0xF8, 0x00, 0x40, 0x00, 0x2C, 0xFB, 0xDA, 0xD9, 0xF8, 0x00, 0x90, 0x50, 0x4C, 0x02, 0x2E, ++0x09, 0xEA, 0x04, 0x04, 0x76, 0xD8, 0x4F, 0x4F, 0x00, 0xEB, 0x40, 0x09, 0x57, 0xF8, 0x26, 0x70, 0xD9, 0x44, 0x37, 0xF8, ++0x19, 0x90, 0xD8, 0xF8, 0x0C, 0x70, 0xDF, 0xF8, 0x3C, 0xA1, 0xBC, 0x42, 0x28, 0xBF, 0x3C, 0x46, 0x14, 0x67, 0xDA, 0xF8, ++0x00, 0xB0, 0x01, 0x9F, 0x98, 0xF8, 0x1C, 0x80, 0x4F, 0xF4, 0x1E, 0x7A, 0x0A, 0xFB, 0x03, 0x13, 0x07, 0x43, 0x01, 0x21, ++0x47, 0xEA, 0xCE, 0x1E, 0x01, 0xFA, 0x05, 0xF5, 0x4F, 0xEA, 0x1B, 0x67, 0xD3, 0xF8, 0x4C, 0x11, 0x93, 0x66, 0x00, 0x9B, ++0x27, 0x2C, 0x4E, 0xEA, 0x0C, 0x1C, 0x4F, 0xEA, 0x87, 0x17, 0x18, 0xFB, 0x05, 0xF8, 0x4C, 0xF4, 0x40, 0x5C, 0x46, 0xEA, ++0xC3, 0x06, 0x94, 0xBF, 0x00, 0x24, 0x01, 0x24, 0x47, 0xF0, 0x13, 0x07, 0x18, 0xFB, 0x09, 0xF9, 0x82, 0xF8, 0x88, 0x40, ++0xD7, 0x66, 0xA1, 0xF8, 0x82, 0xC0, 0xA1, 0xF8, 0x84, 0x60, 0xA2, 0xF8, 0x7A, 0x90, 0x09, 0xE0, 0xAB, 0x68, 0x59, 0x89, ++0xA2, 0xF8, 0x74, 0x10, 0x99, 0x89, 0xA2, 0xF8, 0x76, 0x10, 0xDB, 0x89, 0xA2, 0xF8, 0x78, 0x30, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x10, 0xF4, 0x7C, 0x7F, 0x7F, 0xF4, 0x49, 0xAF, 0x27, 0x49, 0x27, 0x48, 0x40, 0xF6, 0x53, 0x12, 0x07, 0xE0, ++0x00, 0x8E, 0x1C, 0x28, 0x3F, 0xF6, 0x36, 0xAF, 0x22, 0x49, 0x24, 0x48, 0x40, 0xF6, 0x46, 0x12, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x11, 0xF0, 0xF9, 0xB8, 0x4F, 0xF0, 0x01, 0x0B, 0x4F, 0xF4, 0x00, 0x74, 0x5F, 0x46, 0x01, 0x94, 0x73, 0xE7, ++0xAC, 0x0F, 0xDF, 0xF8, 0x7C, 0x90, 0xC5, 0xF3, 0x01, 0x65, 0x19, 0xF8, 0x04, 0x40, 0x82, 0xF8, 0x85, 0x40, 0x82, 0xF8, ++0x86, 0x50, 0x7B, 0xE7, 0x03, 0x3F, 0x00, 0xEB, 0x40, 0x09, 0xC7, 0xF3, 0x46, 0x0A, 0x0B, 0xEB, 0x49, 0x09, 0x4F, 0xF0, ++0x03, 0x0B, 0x1B, 0xFB, 0x0A, 0x99, 0xDF, 0xF8, 0x54, 0xA0, 0x3A, 0xF8, 0x19, 0x90, 0x07, 0xF0, 0x01, 0x07, 0x09, 0xFA, ++0x07, 0xF9, 0x1F, 0xFA, 0x89, 0xF9, 0x7A, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x08, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x58, 0x83, 0x32, 0x40, 0x5C, 0x83, 0x32, 0x40, ++0xFC, 0xFF, 0x0F, 0x00, 0x04, 0x96, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x50, 0x90, 0x15, 0x00, 0xB0, 0x93, 0x15, 0x00, ++0x60, 0x83, 0x32, 0x40, 0x64, 0x83, 0x32, 0x40, 0xA8, 0xB2, 0x15, 0x00, 0x70, 0x95, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x4C, ++0xD4, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xD4, 0xF8, 0xEC, 0x33, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0x10, 0xB5, 0x03, 0xF0, 0x85, 0xFB, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x04, 0x03, 0xD4, 0x07, 0x4B, 0x00, 0x24, 0x1C, 0x61, ++0x10, 0xBD, 0x04, 0x46, 0xED, 0xF7, 0x62, 0xFC, 0x00, 0x28, 0xF6, 0xD0, 0x02, 0x4B, 0x1C, 0x61, 0x10, 0xBD, 0x00, 0xBF, ++0x04, 0x00, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0x18, 0x4B, 0x1B, 0x69, 0x63, 0xB3, 0x93, 0xF8, 0x64, 0x20, 0x4A, 0xB3, ++0x16, 0x4A, 0x93, 0xF8, 0x6C, 0x30, 0x10, 0x68, 0x15, 0x49, 0x40, 0xF0, 0x10, 0x00, 0x30, 0xB4, 0x10, 0x60, 0x10, 0x68, ++0x13, 0x4D, 0x14, 0x4C, 0x40, 0xF4, 0x00, 0x60, 0x10, 0x60, 0x10, 0x68, 0x40, 0xF4, 0x80, 0x50, 0x10, 0x60, 0x2A, 0x68, ++0x10, 0x48, 0xC4, 0xF8, 0x50, 0x04, 0x42, 0xF4, 0x00, 0x72, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x32, 0x0A, 0x60, ++0x0A, 0x68, 0x10, 0x33, 0xDB, 0xB2, 0x43, 0xEA, 0x83, 0x23, 0x22, 0xF4, 0x00, 0x32, 0xC4, 0xF8, 0x4C, 0x34, 0x30, 0xBC, ++0x0A, 0x60, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x80, 0x80, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, ++0x24, 0x03, 0x32, 0x40, 0x60, 0x5D, 0x18, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0x08, 0xB5, 0x0F, 0x4B, 0x1B, 0x69, 0x1B, 0xB1, ++0x0E, 0x4B, 0xD3, 0xF8, 0xC4, 0x33, 0x98, 0x47, 0x0D, 0x48, 0x0E, 0x4B, 0x02, 0x68, 0x0E, 0x49, 0x22, 0xF4, 0x00, 0x72, ++0x02, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x10, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0x1A, 0x68, ++0x22, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x33, 0x0B, 0x60, 0x08, 0xBD, 0x94, 0x64, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x24, 0x03, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x43, 0x6C, 0x13, 0xB1, ++0x9B, 0x88, 0x9A, 0x05, 0x0C, 0xD4, 0xC3, 0x6A, 0xDB, 0x6B, 0x9B, 0x06, 0x43, 0xBF, 0x91, 0xF8, 0x2D, 0x31, 0x48, 0xF2, ++0x07, 0x00, 0x40, 0xEA, 0x43, 0x20, 0xD1, 0xF8, 0x04, 0x02, 0x70, 0x47, 0x01, 0x4B, 0xD8, 0x6E, 0x70, 0x47, 0x00, 0xBF, ++0x94, 0x64, 0x17, 0x00, 0x4B, 0x08, 0x03, 0x22, 0x02, 0xFB, 0x03, 0x00, 0x03, 0x4B, 0x33, 0xF8, 0x10, 0x00, 0x01, 0xF0, ++0x01, 0x01, 0x88, 0x40, 0x70, 0x47, 0x00, 0xBF, 0xE0, 0x94, 0x15, 0x00, 0x4B, 0x08, 0x03, 0x22, 0x02, 0xFB, 0x03, 0x00, ++0x03, 0x4B, 0x33, 0xF8, 0x10, 0x00, 0x01, 0xF0, 0x01, 0x01, 0x88, 0x40, 0x80, 0xB2, 0x70, 0x47, 0x70, 0x95, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x2B, 0x4F, 0x84, 0x6A, 0x3D, 0x68, 0x90, 0xF8, 0x1D, 0x80, 0xB5, 0xF9, 0x00, 0xC0, 0xBC, 0xF1, ++0x00, 0x0F, 0x16, 0x46, 0x99, 0x46, 0xC4, 0xF3, 0x41, 0x25, 0x12, 0xDB, 0xC4, 0xF3, 0x02, 0x12, 0x01, 0x32, 0x1A, 0x60, ++0x04, 0xF0, 0x0F, 0x04, 0x22, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x08, 0x23, 0x04, 0xEB, 0x44, 0x04, 0xDB, 0x68, ++0x33, 0x60, 0x05, 0xEB, 0x44, 0x00, 0xBD, 0xE8, 0xF8, 0x83, 0x05, 0x29, 0x1E, 0xD0, 0x1C, 0x49, 0x1C, 0x48, 0x40, 0xF6, ++0xF5, 0x12, 0x10, 0xF0, 0xF5, 0xFF, 0x39, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0xC4, 0xF3, 0x02, 0x12, 0x01, 0x32, 0x00, 0x29, ++0x4F, 0xEA, 0x14, 0x13, 0xC9, 0xF8, 0x00, 0x20, 0x04, 0xF0, 0x0F, 0x04, 0xDC, 0xDA, 0x5B, 0x07, 0x11, 0xD4, 0x0B, 0x2C, ++0xD8, 0xD9, 0x10, 0x49, 0x11, 0x48, 0x40, 0xF6, 0xFF, 0x12, 0x10, 0xF0, 0xDD, 0xFF, 0xD1, 0xE7, 0xC4, 0xF3, 0x02, 0x12, ++0x01, 0x32, 0x1A, 0x60, 0x23, 0x09, 0x5B, 0x07, 0x04, 0xF0, 0x0F, 0x04, 0xED, 0xD5, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, ++0xFE, 0x12, 0x10, 0xF0, 0xCD, 0xFF, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE2, 0xDB, 0xBC, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD8, 0x93, 0x15, 0x00, 0xF8, 0x93, 0x15, 0x00, ++0xE0, 0x91, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x14, 0x4E, 0xDF, 0xF8, 0x54, 0xC0, 0x35, 0x69, 0x04, 0x38, 0x31, 0x46, ++0x05, 0xF1, 0x08, 0x04, 0x05, 0xF1, 0x18, 0x0E, 0x00, 0x27, 0x50, 0xF8, 0x04, 0x2F, 0x13, 0x09, 0x02, 0xF0, 0x0F, 0x08, ++0x03, 0xF4, 0x7F, 0x63, 0x43, 0xEA, 0x08, 0x03, 0x12, 0x0C, 0x8B, 0x62, 0x81, 0xF8, 0x2C, 0x20, 0x25, 0xB1, 0x22, 0x68, ++0x02, 0xEA, 0x0C, 0x02, 0x13, 0x43, 0x8B, 0x62, 0x04, 0x34, 0xA6, 0x45, 0x4F, 0x62, 0x01, 0xF1, 0x0C, 0x01, 0xE6, 0xD1, ++0x01, 0x23, 0x86, 0xF8, 0x62, 0x30, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x00, 0xF0, 0xFF, 0xFF, ++0x03, 0x4B, 0x02, 0x78, 0x83, 0xF8, 0x64, 0x20, 0x42, 0x78, 0x83, 0xF8, 0x65, 0x20, 0x70, 0x47, 0x94, 0x64, 0x17, 0x00, ++0x0A, 0x4B, 0x9A, 0x69, 0x8A, 0xB1, 0x30, 0xB4, 0x01, 0xEB, 0x41, 0x02, 0x03, 0xEB, 0x82, 0x02, 0x4C, 0x00, 0x92, 0xF8, ++0x2E, 0x50, 0x05, 0xB1, 0x50, 0x62, 0x21, 0x44, 0x03, 0xEB, 0x81, 0x03, 0x01, 0x22, 0x30, 0xBC, 0x83, 0xF8, 0x2D, 0x20, ++0x70, 0x47, 0x70, 0x47, 0x94, 0x64, 0x17, 0x00, 0x08, 0x4A, 0x09, 0x4B, 0x11, 0x69, 0x09, 0x4A, 0x10, 0xB4, 0x01, 0xF5, ++0x9C, 0x51, 0x08, 0x4C, 0x5C, 0x60, 0x98, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x18, 0x46, 0x08, 0x31, 0xD2, 0xF8, 0xE0, 0x31, ++0x18, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x95, 0x24, 0x13, 0x00, ++0x08, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x40, 0xF2, 0xFF, 0x31, 0xB3, 0xF8, 0xBE, 0x24, ++0x8A, 0x42, 0x00, 0xD1, 0x70, 0x47, 0x43, 0x6C, 0x28, 0x30, 0x59, 0x6A, 0xFE, 0xF7, 0xF2, 0xBB, 0x18, 0x88, 0x17, 0x00, ++0xF8, 0xB5, 0x0E, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x40, 0xF2, 0xFF, 0x31, 0xB3, 0xF8, ++0xBE, 0x24, 0x8A, 0x42, 0x0F, 0xD0, 0xD0, 0xE9, 0x12, 0x67, 0x1D, 0x46, 0x06, 0xF1, 0x3C, 0x04, 0x4C, 0x36, 0x20, 0x46, ++0xF9, 0x6A, 0x04, 0x34, 0xFE, 0xF7, 0xD8, 0xFB, 0xB4, 0x42, 0x02, 0xD0, 0xB5, 0xF8, 0xBE, 0x24, 0xF5, 0xE7, 0xF8, 0xBD, ++0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x9C, 0x4E, 0xD0, 0xF8, 0x44, 0xB0, 0xC7, 0x6C, 0x96, 0xF8, 0x7E, 0x50, ++0x96, 0xF8, 0x87, 0x30, 0x11, 0xF4, 0x00, 0x09, 0x83, 0xB0, 0x04, 0x46, 0x8A, 0x46, 0x3E, 0xD0, 0x7B, 0xBB, 0xDF, 0xF8, ++0x58, 0x82, 0x28, 0x46, 0xD8, 0xF8, 0xC0, 0x33, 0x98, 0x47, 0xD8, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xBB, 0xF8, 0x04, 0x30, ++0x99, 0x06, 0x49, 0xD5, 0x13, 0xF0, 0x40, 0x02, 0x69, 0xD0, 0x58, 0x46, 0xFD, 0xF7, 0x14, 0xFE, 0x00, 0x23, 0xDF, 0xF8, ++0x4C, 0x82, 0x63, 0x64, 0xB9, 0xF1, 0x00, 0x0F, 0x4D, 0xD0, 0x89, 0x4B, 0x00, 0x22, 0xD3, 0xF8, 0xAC, 0x33, 0x29, 0x46, ++0x20, 0x46, 0x98, 0x47, 0x54, 0x20, 0x00, 0xFB, 0x05, 0x80, 0x0C, 0x30, 0x0F, 0xF0, 0xD2, 0xFA, 0xA3, 0x88, 0x00, 0x2B, ++0x47, 0xD1, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xFC, 0xF7, 0x0B, 0xB9, 0x7F, 0x48, 0x96, 0xF8, 0x64, 0x30, ++0x01, 0x68, 0xDF, 0xF8, 0xF0, 0x81, 0x1B, 0x06, 0x21, 0xF0, 0xE0, 0x61, 0x03, 0xF0, 0xE0, 0x63, 0x0B, 0x43, 0x03, 0x60, ++0xC7, 0xE7, 0x00, 0x2B, 0xC8, 0xD0, 0x77, 0x48, 0x96, 0xF8, 0x65, 0xE0, 0x01, 0x68, 0x02, 0x68, 0xC1, 0xF3, 0x02, 0x61, ++0x4B, 0x1C, 0x73, 0x45, 0x28, 0xBF, 0x73, 0x46, 0x1B, 0x06, 0x03, 0xF0, 0xE0, 0x63, 0x22, 0xF0, 0xE0, 0x6C, 0x43, 0xEA, ++0x0C, 0x03, 0x03, 0x60, 0xBB, 0xF8, 0x04, 0x30, 0x99, 0x06, 0xB5, 0xD4, 0x1C, 0x23, 0xDF, 0xF8, 0xC4, 0x81, 0x54, 0x20, ++0x10, 0xFB, 0x05, 0x30, 0x40, 0x44, 0x0F, 0xF0, 0x99, 0xFA, 0x58, 0x46, 0xFD, 0xF7, 0xC4, 0xFD, 0x00, 0x23, 0x63, 0x64, ++0xB9, 0xF1, 0x00, 0x0F, 0xB1, 0xD1, 0xCA, 0xF3, 0x07, 0x29, 0xB9, 0xF1, 0x04, 0x0F, 0x1F, 0xD9, 0x3B, 0x6D, 0x43, 0xF4, ++0x80, 0x33, 0x3B, 0x65, 0xA7, 0xE7, 0x2A, 0x46, 0x51, 0x46, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xFB, 0xF7, ++0x9D, 0xBA, 0x3B, 0x6D, 0x00, 0x92, 0x23, 0xF4, 0x00, 0x03, 0x2A, 0xF4, 0x00, 0x0A, 0x58, 0x46, 0x3B, 0x65, 0xCA, 0xF3, ++0x07, 0x29, 0xFD, 0xF7, 0xA1, 0xFD, 0x00, 0x9A, 0xDF, 0xF8, 0x64, 0x81, 0x62, 0x64, 0xB9, 0xF1, 0x04, 0x0F, 0xDF, 0xD8, ++0xD4, 0xF8, 0x48, 0xA0, 0xB9, 0xF1, 0x00, 0x0F, 0x25, 0xD0, 0x0A, 0xF1, 0x28, 0x0B, 0x05, 0xEB, 0x45, 0x03, 0x06, 0xEB, ++0x83, 0x03, 0x09, 0xF1, 0x01, 0x09, 0x59, 0x6A, 0xDA, 0xE9, 0x17, 0x32, 0xBB, 0x64, 0x4F, 0xEA, 0x09, 0x23, 0xC7, 0xE9, ++0x0D, 0x2B, 0x3B, 0x65, 0x07, 0xF1, 0x14, 0x02, 0x6B, 0x00, 0x00, 0x29, 0x4B, 0xD0, 0xB9, 0x61, 0x54, 0x20, 0x00, 0xFB, ++0x05, 0x88, 0x1D, 0x44, 0x98, 0xF8, 0x50, 0x30, 0x06, 0xEB, 0x85, 0x06, 0x01, 0x33, 0x72, 0x62, 0x88, 0xF8, 0x50, 0x30, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xE3, 0x6A, 0x0A, 0xF1, 0x28, 0x0B, 0x03, 0xF1, 0x40, 0x0C, 0x1A, 0x46, 0x0A, 0xF1, ++0x24, 0x01, 0x52, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0F, 0x62, 0x45, 0xF9, 0xD1, 0xE2, 0x8B, 0x92, 0x04, 0x26, 0xD5, ++0x33, 0x4A, 0x34, 0x48, 0x11, 0x68, 0x62, 0x7F, 0xB1, 0xF9, 0x00, 0x10, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, 0x02, 0x02, ++0x00, 0x29, 0xD2, 0xF8, 0x4C, 0x21, 0x00, 0x92, 0x29, 0xDB, 0x00, 0x9A, 0x59, 0x69, 0xD2, 0xF8, 0x9C, 0x20, 0xCA, 0xF8, ++0x40, 0x10, 0x59, 0x6A, 0xCA, 0xF8, 0x50, 0x10, 0xC2, 0xF3, 0xC2, 0x21, 0x05, 0x29, 0xCA, 0xF8, 0x3C, 0x20, 0x25, 0xD0, ++0xDB, 0x6B, 0x5B, 0x07, 0x05, 0xD4, 0xDA, 0xF8, 0x2C, 0x30, 0x23, 0xF4, 0xC0, 0x73, 0xCA, 0xF8, 0x2C, 0x30, 0x20, 0x46, ++0xFF, 0xF7, 0xDC, 0xFE, 0x9F, 0xE7, 0x54, 0x21, 0x01, 0xFB, 0x05, 0xF1, 0x1E, 0x48, 0x48, 0xF8, 0x01, 0x20, 0x00, 0x68, ++0x40, 0x78, 0x41, 0x44, 0x00, 0x28, 0xA9, 0xD1, 0xC1, 0xE9, 0x01, 0x00, 0xA6, 0xE7, 0x00, 0x2A, 0xD3, 0xD1, 0x19, 0x49, ++0x19, 0x48, 0x01, 0x93, 0x40, 0xF2, 0x4B, 0x12, 0x10, 0xF0, 0xFE, 0xFD, 0x01, 0x9B, 0xCA, 0xE7, 0x00, 0x98, 0xDA, 0xF8, ++0x4C, 0x10, 0x90, 0xF8, 0xA1, 0x00, 0x02, 0xF4, 0xC0, 0x62, 0xB2, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x3C, ++0x4F, 0xF4, 0x00, 0x3C, 0x21, 0xF4, 0x40, 0x32, 0x42, 0xEA, 0x0C, 0x02, 0x20, 0xB1, 0x42, 0xF4, 0x80, 0x22, 0xCA, 0xF8, ++0x4C, 0x20, 0xC1, 0xE7, 0x22, 0xF4, 0x80, 0x22, 0xCA, 0xF8, 0x4C, 0x20, 0xBC, 0xE7, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, 0x10, 0xB5, 0x05, 0x4C, 0x20, 0x46, 0x0F, 0xF0, ++0x6F, 0xF9, 0x10, 0xF0, 0x25, 0xFE, 0x01, 0x38, 0xC0, 0xB2, 0xE0, 0x72, 0xA0, 0x72, 0x10, 0xBD, 0x24, 0x65, 0x17, 0x00, ++0xC2, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x02, 0x38, 0x85, 0xB0, 0x98, 0xF8, 0x62, 0x30, ++0x02, 0x2B, 0x17, 0xD1, 0x4F, 0xF4, 0x1E, 0x79, 0x93, 0x46, 0x0C, 0x46, 0x09, 0xFB, 0x01, 0xF2, 0xBA, 0x49, 0x01, 0x92, ++0x8E, 0x18, 0xB0, 0xF8, 0x00, 0xA0, 0x96, 0xF8, 0x24, 0x90, 0xB9, 0xF1, 0x01, 0x0F, 0x05, 0x46, 0x41, 0xF2, 0x04, 0x42, ++0x07, 0xD0, 0x0A, 0xEA, 0x02, 0x0A, 0xBA, 0xF5, 0x80, 0x5F, 0x5A, 0xD0, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0xEA, ++0x02, 0x02, 0x00, 0xF0, 0x6B, 0x81, 0x0A, 0xF0, 0xFC, 0x03, 0xA4, 0x2B, 0x00, 0xF0, 0x75, 0x82, 0x0A, 0xF0, 0x8C, 0x03, ++0x88, 0x2B, 0xEF, 0xD1, 0x0A, 0xF4, 0x40, 0x7A, 0xBA, 0xF5, 0x40, 0x7F, 0x0C, 0xBF, 0xEF, 0x8B, 0x2F, 0x8B, 0xA7, 0x4B, ++0xA5, 0x49, 0xA7, 0x4A, 0x07, 0xF0, 0x07, 0x07, 0x4F, 0xF4, 0x1E, 0x75, 0xDB, 0x5D, 0x05, 0xFB, 0x04, 0x15, 0xD2, 0x5C, ++0x95, 0xF8, 0x2E, 0x31, 0x1A, 0x42, 0xD9, 0xD0, 0x95, 0xF8, 0x31, 0x30, 0x13, 0xF0, 0x0C, 0x0F, 0x00, 0xF0, 0x7E, 0x82, ++0x95, 0xF8, 0x32, 0x20, 0x12, 0xF0, 0x06, 0x0F, 0xCE, 0xD1, 0x18, 0x07, 0x95, 0xF8, 0x2F, 0x91, 0x40, 0xF1, 0x8A, 0x82, ++0x99, 0x4B, 0x02, 0x22, 0x85, 0xF8, 0x32, 0x20, 0xD3, 0xF8, 0x20, 0x33, 0x31, 0x46, 0x40, 0x46, 0x4A, 0x46, 0x98, 0x47, ++0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x7A, 0x82, 0xA9, 0xEB, 0x00, 0x09, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF3, 0x74, 0x82, ++0x8C, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x24, 0x00, 0x23, 0x1A, 0x46, 0x94, 0xF8, 0x23, 0x00, 0x47, 0xF0, ++0x10, 0x01, 0xFC, 0xF7, 0xA9, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x32, 0x30, 0xA4, 0xE7, 0x00, 0x22, 0x0C, 0x21, 0x49, 0x20, ++0x0E, 0xF0, 0x58, 0xFC, 0x4F, 0xF0, 0x01, 0x09, 0x86, 0xF8, 0x24, 0x90, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, 0x0E, 0xF0, ++0x7F, 0xFC, 0x96, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x58, 0xD1, 0x96, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x54, 0xD8, 0x96, 0xF8, ++0x22, 0x20, 0x77, 0x48, 0x7B, 0x4D, 0xCD, 0xF8, 0x08, 0x90, 0x9E, 0x23, 0xA4, 0x21, 0x11, 0xFB, 0x02, 0x31, 0x07, 0xFB, ++0x02, 0x07, 0x4F, 0x23, 0x46, 0x22, 0x13, 0xFB, 0x04, 0x24, 0x71, 0x4A, 0x02, 0xF5, 0x16, 0x73, 0x02, 0xEB, 0xC4, 0x04, ++0x01, 0x9A, 0x1A, 0x44, 0x00, 0xEB, 0xC1, 0x0A, 0x91, 0x46, 0xD6, 0xF8, 0x08, 0x32, 0x1B, 0xB3, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x6D, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0x2B, 0x68, 0xA4, 0xF1, 0x28, 0x00, 0x01, 0x33, ++0xAA, 0xF1, 0x28, 0x01, 0x01, 0x90, 0x2B, 0x60, 0x0F, 0xF0, 0x98, 0xF9, 0xD6, 0xE9, 0x82, 0x23, 0x01, 0x98, 0xC7, 0xF8, ++0xC8, 0x24, 0xC7, 0xF8, 0xCC, 0x34, 0x0F, 0xF0, 0x99, 0xF8, 0x2B, 0x68, 0x5A, 0x1E, 0x2B, 0xB1, 0x60, 0x4B, 0x2A, 0x60, ++0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD6, 0xF8, 0x30, 0x32, 0x50, 0x46, 0x21, 0x46, 0x08, 0x36, 0x0A, 0xF1, ++0x08, 0x0A, 0x08, 0x37, 0x23, 0xB1, 0x0F, 0xF0, 0x7B, 0xF9, 0x20, 0x46, 0x0F, 0xF0, 0x82, 0xF8, 0x08, 0x34, 0x4C, 0x45, ++0xC7, 0xD1, 0x40, 0x20, 0x0E, 0xF0, 0xDE, 0xFF, 0x4D, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x36, 0x96, 0xF8, ++0xDE, 0x20, 0x00, 0x2A, 0x40, 0xF0, 0x82, 0x80, 0x0B, 0xF1, 0x0A, 0x05, 0x48, 0x4B, 0xED, 0xB2, 0x4F, 0xF4, 0x1E, 0x79, ++0x09, 0xFB, 0x05, 0xF9, 0x03, 0xEB, 0x09, 0x04, 0x94, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x73, 0xD0, 0x02, 0x23, 0x0C, 0x21, ++0x49, 0x20, 0x0E, 0xF0, 0xD5, 0xFB, 0x4F, 0xF0, 0x01, 0x0A, 0x84, 0xF8, 0x24, 0xA0, 0x05, 0x70, 0x80, 0xF8, 0x01, 0xA0, ++0x0E, 0xF0, 0xFC, 0xFB, 0x94, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xA9, 0x81, 0x94, 0xF8, 0x23, 0x30, 0x09, 0x2B, ++0x00, 0xF2, 0xA4, 0x81, 0x94, 0xF8, 0x22, 0x00, 0xCD, 0xF8, 0x08, 0xA0, 0xA4, 0x21, 0x9E, 0x23, 0x11, 0xFB, 0x00, 0x33, ++0x4F, 0xF0, 0x46, 0x0A, 0x4F, 0x21, 0x11, 0xFB, 0x05, 0xAA, 0x36, 0x4A, 0x2E, 0x4E, 0x2E, 0x49, 0x07, 0xFB, 0x00, 0x67, ++0x01, 0xEB, 0xC3, 0x05, 0x30, 0x4E, 0xA2, 0xF5, 0x16, 0x73, 0x03, 0xEB, 0xCA, 0x0A, 0x91, 0x44, 0xD4, 0xF8, 0x08, 0x32, ++0x1B, 0xB3, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2A, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0x33, 0x68, ++0xAA, 0xF1, 0x28, 0x00, 0x01, 0x33, 0xA5, 0xF1, 0x28, 0x01, 0x01, 0x90, 0x33, 0x60, 0x0F, 0xF0, 0x13, 0xF9, 0xD4, 0xE9, ++0x82, 0x23, 0x01, 0x98, 0xC7, 0xF8, 0xC8, 0x24, 0xC7, 0xF8, 0xCC, 0x34, 0x0F, 0xF0, 0x14, 0xF8, 0x33, 0x68, 0x5A, 0x1E, ++0x2B, 0xB1, 0x1E, 0x4B, 0x32, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD4, 0xF8, 0x30, 0x32, 0x28, 0x46, ++0x51, 0x46, 0x08, 0x34, 0x08, 0x35, 0x08, 0x37, 0x23, 0xB1, 0x0F, 0xF0, 0xF7, 0xF8, 0x50, 0x46, 0x0E, 0xF0, 0xFE, 0xFF, ++0x0A, 0xF1, 0x08, 0x0A, 0xCA, 0x45, 0xC7, 0xD1, 0x40, 0x20, 0x0E, 0xF0, 0x59, 0xFF, 0x0B, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x0B, 0x23, 0x93, 0xF8, 0xDE, 0x20, 0x07, 0x48, 0x0B, 0x49, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0B, 0x03, ++0x01, 0x32, 0x83, 0xF8, 0xDE, 0x20, 0xD1, 0xF8, 0x0C, 0x32, 0x40, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, ++0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0xA4, 0xB2, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x0C, 0x21, 0x49, 0x20, 0x02, 0x92, 0x0E, 0xF0, ++0x41, 0xFB, 0x02, 0x9A, 0x86, 0xF8, 0x24, 0x20, 0x04, 0x70, 0x42, 0x70, 0x0E, 0xF0, 0x6A, 0xFB, 0x96, 0xF8, 0x24, 0x30, ++0x00, 0x2B, 0x60, 0xD1, 0x96, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x5C, 0xD8, 0x96, 0xF8, 0x22, 0x20, 0xA8, 0x48, 0xCD, 0xF8, ++0x08, 0x90, 0xA4, 0x21, 0x9E, 0x23, 0x11, 0xFB, 0x02, 0x33, 0xA6, 0x49, 0xDF, 0xF8, 0xA0, 0xA2, 0x03, 0x94, 0x07, 0xFB, ++0x02, 0x19, 0x4F, 0x25, 0x01, 0xEB, 0xC3, 0x07, 0x46, 0x22, 0x01, 0x9B, 0x15, 0xFB, 0x04, 0x25, 0x00, 0xF5, 0x16, 0x72, ++0x13, 0x44, 0x3C, 0x46, 0x00, 0xEB, 0xC5, 0x05, 0x1F, 0x46, 0xD6, 0xF8, 0x08, 0x22, 0x3A, 0xB3, 0xEF, 0xF3, 0x10, 0x82, ++0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x99, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0xA5, 0xF1, 0x28, 0x00, ++0x01, 0x32, 0xA4, 0xF1, 0x28, 0x01, 0x01, 0x90, 0xCA, 0xF8, 0x00, 0x20, 0x0F, 0xF0, 0x7E, 0xF8, 0xD6, 0xE9, 0x82, 0x21, ++0x01, 0x98, 0xC9, 0xF8, 0xC8, 0x24, 0xC9, 0xF8, 0xCC, 0x14, 0x0E, 0xF0, 0x7F, 0xFF, 0xDA, 0xF8, 0x00, 0x20, 0x51, 0x1E, ++0x32, 0xB1, 0x8B, 0x4B, 0xCA, 0xF8, 0x00, 0x10, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD6, 0xF8, 0x30, 0x22, ++0x20, 0x46, 0x29, 0x46, 0x08, 0x36, 0x08, 0x34, 0x09, 0xF1, 0x08, 0x09, 0x22, 0xB1, 0x0F, 0xF0, 0x5F, 0xF8, 0x28, 0x46, ++0x0E, 0xF0, 0x66, 0xFF, 0x08, 0x35, 0xBD, 0x42, 0xC3, 0xD1, 0x40, 0x20, 0x03, 0x9C, 0x0E, 0xF0, 0xC1, 0xFE, 0x7E, 0x4D, ++0x21, 0x46, 0xEB, 0x68, 0x40, 0x46, 0x98, 0x47, 0x79, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x33, 0x93, 0xF8, ++0xDE, 0xA0, 0x0A, 0xF1, 0xFF, 0x3A, 0x5F, 0xFA, 0x8A, 0xFA, 0x83, 0xF8, 0xDE, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, ++0x84, 0x80, 0x0B, 0xF1, 0x0A, 0x06, 0x6F, 0x49, 0xF6, 0xB2, 0x4F, 0xF4, 0x1E, 0x79, 0x09, 0xFB, 0x06, 0xF9, 0x01, 0xEB, ++0x09, 0x04, 0x94, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x71, 0xD0, 0x02, 0x23, 0x52, 0x46, 0x0C, 0x21, 0x49, 0x20, 0x0E, 0xF0, ++0xAB, 0xFA, 0x84, 0xF8, 0x24, 0xA0, 0x06, 0x70, 0x80, 0xF8, 0x01, 0xA0, 0x0E, 0xF0, 0xD4, 0xFA, 0x94, 0xF8, 0x24, 0x30, ++0x00, 0x2B, 0x60, 0xD1, 0x94, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x5C, 0xD8, 0x94, 0xF8, 0x22, 0x10, 0x5E, 0x4A, 0xDF, 0xF8, ++0x88, 0xC1, 0xDF, 0xF8, 0x80, 0xA1, 0x02, 0x96, 0x9E, 0x23, 0xA4, 0x20, 0x10, 0xFB, 0x01, 0x30, 0x07, 0xFB, 0x01, 0x27, ++0x4F, 0x23, 0x46, 0x21, 0x13, 0xFB, 0x06, 0x13, 0xAC, 0xF5, 0x16, 0x71, 0x02, 0xEB, 0xC0, 0x0B, 0xE1, 0x44, 0x01, 0xEB, ++0xC3, 0x03, 0x5E, 0x46, 0xCB, 0x46, 0xB9, 0x46, 0x1F, 0x46, 0xD4, 0xF8, 0x08, 0x22, 0x3A, 0xB3, 0xEF, 0xF3, 0x10, 0x82, ++0xD3, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x4E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0xA7, 0xF1, 0x28, 0x00, ++0x01, 0x32, 0xA6, 0xF1, 0x28, 0x01, 0x01, 0x90, 0xCA, 0xF8, 0x00, 0x20, 0x0E, 0xF0, 0xE8, 0xFF, 0xD4, 0xE9, 0x82, 0x21, ++0x01, 0x98, 0xC9, 0xF8, 0xC8, 0x24, 0xC9, 0xF8, 0xCC, 0x14, 0x0E, 0xF0, 0xE9, 0xFE, 0xDA, 0xF8, 0x00, 0x20, 0x51, 0x1E, ++0x32, 0xB1, 0x40, 0x4B, 0xCA, 0xF8, 0x00, 0x10, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD4, 0xF8, 0x30, 0x22, ++0x30, 0x46, 0x39, 0x46, 0x08, 0x34, 0x08, 0x36, 0x09, 0xF1, 0x08, 0x09, 0x22, 0xB1, 0x0E, 0xF0, 0xC9, 0xFF, 0x38, 0x46, ++0x0E, 0xF0, 0xD0, 0xFE, 0x08, 0x37, 0x5F, 0x45, 0xC3, 0xD1, 0x40, 0x20, 0x02, 0x9E, 0x0E, 0xF0, 0x2B, 0xFE, 0xEB, 0x68, ++0x31, 0x46, 0x40, 0x46, 0x98, 0x47, 0xD5, 0xF8, 0x0C, 0x32, 0x40, 0x46, 0xDC, 0xE6, 0x96, 0xF8, 0x31, 0x20, 0x12, 0xF0, ++0x02, 0x07, 0x16, 0xD0, 0x96, 0xF8, 0x32, 0x30, 0x2B, 0x49, 0x43, 0xF0, 0x01, 0x03, 0x86, 0xF8, 0x32, 0x30, 0x4A, 0x46, ++0xD1, 0xF8, 0x20, 0x33, 0x40, 0x46, 0x31, 0x46, 0x98, 0x47, 0x96, 0xF8, 0x32, 0x30, 0x23, 0xF0, 0x01, 0x03, 0x86, 0xF8, ++0x32, 0x30, 0x71, 0xE5, 0x96, 0xF8, 0xDE, 0x20, 0xB4, 0xE6, 0x04, 0x23, 0x3A, 0x46, 0x0C, 0x21, 0x4A, 0x20, 0x0E, 0xF0, ++0x15, 0xFA, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, 0x87, 0x70, 0x0E, 0xF0, 0x3F, 0xFA, 0x61, 0xE5, 0x95, 0xF8, 0x32, 0x30, ++0x13, 0xF0, 0x06, 0x04, 0x7F, 0xF4, 0x50, 0xAD, 0x02, 0x26, 0x95, 0xF8, 0x23, 0x00, 0x85, 0xF8, 0x32, 0x60, 0x47, 0xF0, ++0x10, 0x01, 0x23, 0x46, 0x22, 0x46, 0xFB, 0xF7, 0x45, 0xFE, 0x85, 0xF8, 0x32, 0x40, 0x41, 0xE5, 0x95, 0xF8, 0x31, 0x30, ++0x59, 0x07, 0x7F, 0xF5, 0x87, 0xAD, 0x0B, 0x4B, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x04, 0x30, 0x04, 0x23, 0x80, 0xF8, ++0x32, 0x30, 0x00, 0x22, 0x0C, 0x21, 0x4A, 0x20, 0x0E, 0xF0, 0xE8, 0xF9, 0x01, 0x22, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, ++0x82, 0x70, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x0E, 0xF0, 0x0E, 0xBA, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x05, 0x8E, 0x87, 0xB0, 0xAD, 0xB1, 0x7A, 0x4B, 0xC6, 0x69, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, ++0x11, 0xDB, 0x77, 0x4A, 0x65, 0x6D, 0x12, 0x68, 0x12, 0x78, 0x92, 0x07, 0x03, 0xD5, 0x05, 0xF0, 0x3C, 0x02, 0x3C, 0x2A, ++0x77, 0xD0, 0x73, 0x4A, 0xAA, 0x43, 0x0E, 0xD0, 0x01, 0x25, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2E, ++0xEB, 0xD1, 0x6F, 0x49, 0x6F, 0x48, 0x4F, 0xF4, 0xD4, 0x72, 0x35, 0x46, 0x10, 0xF0, 0x5A, 0xFA, 0xF1, 0xE7, 0x00, 0x2B, ++0xC5, 0xF3, 0xCF, 0x30, 0xC5, 0xF3, 0xC9, 0x31, 0x68, 0xDB, 0x6A, 0x4A, 0x10, 0x39, 0xC9, 0xB2, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x25, 0x00, 0x00, 0x28, 0x68, 0xD0, 0xD6, 0xF8, 0x08, 0xB0, 0x0D, 0x29, 0xBB, 0xF8, ++0x00, 0x00, 0x00, 0x90, 0x69, 0xD9, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x22, 0x13, 0x8C, 0xFF, 0x2B, 0x67, 0xD0, ++0x01, 0x92, 0x01, 0x9B, 0xDF, 0xF8, 0x88, 0x81, 0x93, 0xF8, 0x22, 0x90, 0xDF, 0xF8, 0x84, 0xA1, 0x02, 0x91, 0x4F, 0xF4, ++0xA4, 0x67, 0x07, 0xFB, 0x09, 0x87, 0xDA, 0xF8, 0xB8, 0x32, 0x97, 0xF8, 0x63, 0x20, 0x58, 0x46, 0x98, 0x47, 0x97, 0xF8, ++0x64, 0x30, 0x00, 0x2B, 0xBA, 0xD0, 0x00, 0x9B, 0x13, 0xF0, 0x04, 0x03, 0x03, 0x93, 0x05, 0xD1, 0x02, 0x99, 0x97, 0xF8, ++0x63, 0x00, 0x01, 0x22, 0x0C, 0xF0, 0x96, 0xFB, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0x88, 0x98, 0xF8, 0x62, 0x30, ++0x00, 0x2B, 0xA7, 0xD1, 0x00, 0x9A, 0x02, 0xF0, 0xFC, 0x07, 0x80, 0x2F, 0x4A, 0xD0, 0x50, 0x2F, 0x67, 0xD0, 0x03, 0x9B, ++0x00, 0x2B, 0x9D, 0xD1, 0xDA, 0xF8, 0x44, 0x32, 0x29, 0x46, 0x58, 0x46, 0x42, 0x46, 0x98, 0x47, 0x98, 0xF8, 0xC0, 0x34, ++0x00, 0x2B, 0x93, 0xD0, 0xD0, 0x2F, 0x91, 0xD1, 0xB1, 0x68, 0x63, 0x6B, 0x22, 0x8E, 0x40, 0x46, 0x0B, 0xF0, 0x5C, 0xFF, ++0x8A, 0xE7, 0x37, 0x4A, 0x25, 0xF0, 0x40, 0x05, 0x45, 0xF4, 0x00, 0x55, 0xAA, 0x43, 0x65, 0x65, 0x82, 0xD1, 0x90, 0xE7, ++0x10, 0xF4, 0x7C, 0x73, 0x93, 0xD1, 0x32, 0x49, 0x34, 0x48, 0x40, 0xF2, 0xE3, 0x12, 0x1D, 0x46, 0x10, 0xF0, 0xE0, 0xF9, ++0x77, 0xE7, 0x25, 0xF0, 0x00, 0x75, 0x65, 0x65, 0x01, 0x25, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2E, 0x48, ++0x00, 0x69, 0xC3, 0xF8, 0x58, 0x02, 0x90, 0xE7, 0x00, 0x9B, 0x03, 0xF0, 0xFC, 0x03, 0x80, 0x2B, 0xED, 0xD1, 0xD3, 0x6A, ++0x01, 0x93, 0x93, 0xF8, 0x23, 0x20, 0x25, 0xF0, 0xFF, 0x73, 0x10, 0x32, 0x23, 0xF4, 0xC0, 0x33, 0x43, 0xEA, 0xC2, 0x33, ++0x63, 0x65, 0x86, 0xE7, 0x04, 0xF1, 0x14, 0x07, 0x01, 0x9A, 0xDA, 0xF8, 0x98, 0x51, 0x05, 0x93, 0x41, 0x46, 0x05, 0xAB, ++0x38, 0x46, 0xA8, 0x47, 0xDA, 0xF8, 0x40, 0x32, 0x21, 0x8E, 0x05, 0x46, 0x42, 0x46, 0x05, 0x98, 0x98, 0x47, 0xDA, 0xF8, ++0x4C, 0x34, 0x40, 0x46, 0x98, 0x47, 0x00, 0x2D, 0x3F, 0xF4, 0x41, 0xAF, 0xDA, 0xF8, 0xE4, 0x31, 0x3A, 0x46, 0x31, 0x46, ++0x40, 0x46, 0x98, 0x47, 0x39, 0xE7, 0x14, 0x4B, 0x5A, 0x7F, 0x07, 0x2A, 0x7F, 0xF4, 0x34, 0xAF, 0x93, 0xF8, 0x24, 0x00, ++0x00, 0x28, 0x7F, 0xF4, 0x2F, 0xAF, 0x10, 0x4C, 0x10, 0x4D, 0x58, 0x77, 0xD4, 0xE9, 0x00, 0x12, 0x22, 0xF4, 0x00, 0x72, ++0x01, 0x20, 0x11, 0x43, 0x62, 0x60, 0x29, 0x60, 0x83, 0xF8, 0x24, 0x00, 0x05, 0x46, 0x20, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x00, 0x20, 0x00, 0x02, 0x70, 0x79, 0x15, 0x00, 0x10, 0x96, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x50, 0x90, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0xA3, 0x7A, 0xE2, 0x7A, 0x01, 0x33, 0xDB, 0xB2, ++0x9A, 0x42, 0xA3, 0x72, 0x00, 0xD3, 0x10, 0xBD, 0x10, 0xF0, 0xF6, 0xF9, 0x00, 0x23, 0xA3, 0x72, 0x10, 0xBD, 0x00, 0xBF, ++0x24, 0x65, 0x17, 0x00, 0x10, 0xB5, 0x10, 0x4C, 0xA3, 0x7A, 0xD3, 0xB9, 0xE3, 0x7A, 0xA3, 0x72, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4A, 0x0C, 0x4C, 0x11, 0x68, 0x23, 0x68, ++0x48, 0x1C, 0x23, 0xF4, 0x80, 0x73, 0x10, 0x60, 0x23, 0x60, 0x28, 0xB1, 0x05, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xF0, 0xCF, 0xF9, 0xE1, 0xE7, 0x24, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x08, 0xB5, 0x00, 0xF0, 0x29, 0xFC, 0xFF, 0xF7, 0x93, 0xFB, 0xBD, 0xE8, ++0x08, 0x40, 0x1A, 0xF0, 0x9F, 0xB8, 0x00, 0xBF, 0x0A, 0x4A, 0x0B, 0x4B, 0x10, 0xB5, 0xD2, 0xE9, 0x20, 0x04, 0xD2, 0xE9, ++0x22, 0x12, 0x04, 0x44, 0x0A, 0x44, 0xC3, 0xE9, 0x01, 0x40, 0xC3, 0xE9, 0x03, 0x12, 0x18, 0x60, 0x59, 0x61, 0xFF, 0xF7, ++0x7D, 0xFB, 0xBD, 0xE8, 0x10, 0x40, 0x1A, 0xF0, 0x89, 0xB8, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x68, 0x81, 0xDF, 0xF8, 0x68, 0x91, 0xDF, 0xF8, 0x68, 0xA1, 0xDF, 0xF8, 0x68, 0xB1, ++0x4D, 0x4F, 0x87, 0xB0, 0x00, 0x25, 0x3C, 0xE0, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF5, 0x80, 0x1F, 0x4E, 0xD8, 0x20, 0x2D, ++0x4C, 0xD0, 0x10, 0xF0, 0x8D, 0xF9, 0x00, 0x28, 0x61, 0xD0, 0x1A, 0xF0, 0x81, 0xFC, 0x00, 0x28, 0x5D, 0xD0, 0x62, 0x69, ++0x5A, 0x45, 0x0E, 0xD0, 0x43, 0x4B, 0xB9, 0x68, 0x1E, 0x68, 0x53, 0xF8, 0x04, 0x0C, 0x7B, 0x68, 0xCD, 0xE9, 0x02, 0x60, ++0xCD, 0xE9, 0x00, 0x31, 0x3F, 0x48, 0x3B, 0x68, 0x21, 0x46, 0x0F, 0xF0, 0x97, 0xFE, 0x20, 0x46, 0x3D, 0x4E, 0x01, 0xF0, ++0x41, 0xF9, 0x00, 0x22, 0xD6, 0xF8, 0x94, 0x32, 0x8D, 0xF8, 0x17, 0x20, 0x0D, 0xF1, 0x17, 0x01, 0x20, 0x46, 0x98, 0x47, ++0x58, 0xBB, 0x9D, 0xF8, 0x17, 0x30, 0x73, 0xB3, 0x36, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x31, 0xD0, 0x03, 0x2B, ++0x02, 0xD1, 0xD6, 0xF8, 0x8C, 0x32, 0x98, 0x47, 0x01, 0x35, 0x01, 0xF0, 0x09, 0xF9, 0x4F, 0xF4, 0x80, 0x33, 0xC9, 0xF8, ++0x00, 0x30, 0x04, 0x46, 0x4F, 0xF4, 0x80, 0x10, 0x0E, 0xF0, 0x18, 0xFC, 0x98, 0xF8, 0xB8, 0x30, 0x94, 0xB3, 0x00, 0x2B, ++0xB2, 0xD1, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF5, 0x80, 0x1F, 0x01, 0xD8, 0x03, 0x2D, 0xB2, 0xDD, 0x4F, 0xF4, 0x80, 0x10, ++0x0E, 0xF0, 0xE4, 0xFB, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD6, 0xF8, 0xC8, 0x32, 0x20, 0x46, 0x98, 0x47, 0x00, 0x28, ++0xD0, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0xC4, 0xF8, 0x1D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0xCD, 0xD1, 0xD6, 0xF8, ++0x90, 0x32, 0x98, 0x47, 0xCE, 0xE7, 0x1A, 0x4B, 0x01, 0x22, 0x83, 0xF8, 0x45, 0x20, 0x1A, 0xF0, 0x1B, 0xFC, 0xB0, 0xFA, ++0x80, 0xF2, 0x17, 0x49, 0x52, 0x09, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x8D, 0xFE, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x1B, 0xB1, 0x13, 0x4D, 0x95, 0xF8, 0x21, 0x30, 0x3B, 0xB9, 0x12, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, ++0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD5, 0xE9, 0x05, 0x12, 0x28, 0x69, 0xF3, 0xF7, 0x5E, 0xFE, 0x6C, 0x61, 0xEC, 0x61, ++0x2C, 0x61, 0xAC, 0x61, 0x85, 0xF8, 0x21, 0x40, 0xEB, 0xE7, 0x00, 0xBF, 0xEC, 0x34, 0x17, 0x00, 0xD4, 0x81, 0x32, 0x40, ++0x3C, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x28, 0x96, 0x15, 0x00, ++0x30, 0x65, 0x17, 0x00, 0x80, 0x80, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x7C, 0x80, 0x32, 0x40, 0x80, 0xB6, 0x17, 0x00, ++0x0D, 0xF0, 0xAD, 0xBA, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0x86, 0xBB, 0x2D, 0xE9, 0xF8, 0x43, 0x30, 0x4D, 0x2C, 0x68, ++0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0xA2, 0xFB, 0x00, 0x2C, 0x31, 0xD0, 0xDF, 0xF8, 0xC4, 0x90, 0x2C, 0x4F, 0x2E, 0x46, ++0x4F, 0xF0, 0x01, 0x08, 0x23, 0x7C, 0xD9, 0x07, 0x02, 0xD4, 0x2B, 0x89, 0x01, 0x33, 0x2B, 0x81, 0x30, 0x46, 0x0E, 0xF0, ++0x53, 0xFC, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC7, 0xF8, 0x00, 0x80, 0xD9, 0xF8, 0x00, 0x30, ++0x62, 0x68, 0x01, 0x33, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x30, 0x21, 0x74, 0x0A, 0xB1, 0xA0, 0x68, 0x90, 0x47, 0xE0, 0x68, ++0x08, 0xB1, 0x00, 0xF0, 0x77, 0xFB, 0xD9, 0xF8, 0x00, 0x30, 0x33, 0xB1, 0x01, 0x3B, 0x3A, 0x68, 0xC9, 0xF8, 0x00, 0x30, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x2C, 0x68, 0x00, 0x2C, 0xD3, 0xD1, 0xAA, 0x7A, 0xEB, 0x7A, 0x9A, 0x42, 0x20, 0xD0, ++0x13, 0x4B, 0x14, 0x48, 0x1B, 0x69, 0x14, 0x4A, 0xC8, 0x33, 0x4F, 0xF4, 0x80, 0x71, 0x03, 0x60, 0x11, 0x60, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0E, 0x4A, 0x0E, 0x4C, 0x11, 0x68, ++0x23, 0x68, 0x48, 0x1C, 0x43, 0xF4, 0x80, 0x73, 0x10, 0x60, 0x23, 0x60, 0x28, 0xB1, 0x05, 0x4B, 0x11, 0x60, 0x1B, 0x68, ++0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x48, 0x01, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, ++0x2D, 0xE9, 0xF8, 0x43, 0x27, 0x4D, 0x2C, 0x68, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0x30, 0xFB, 0x9C, 0xB3, 0xDF, 0xF8, ++0x9C, 0x80, 0xDF, 0xF8, 0x9C, 0x90, 0x00, 0x27, 0x2E, 0x46, 0x27, 0xE0, 0x01, 0x27, 0x30, 0x46, 0x0E, 0xF0, 0xE6, 0xFB, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x00, 0x30, ++0x62, 0x68, 0x01, 0x33, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x30, 0x21, 0x74, 0x0A, 0xB1, 0xA0, 0x68, 0x90, 0x47, 0xE0, 0x68, ++0x08, 0xB1, 0x00, 0xF0, 0x09, 0xFB, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0xC9, 0xF8, ++0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x2C, 0x68, 0x24, 0xB1, 0x23, 0x7C, 0xDA, 0x07, 0xD5, 0xD4, 0x00, 0x2F, ++0xD2, 0xD0, 0x0B, 0x4C, 0x94, 0xF8, 0x45, 0x30, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0x80, 0x10, 0x0E, 0xF0, ++0xCD, 0xFA, 0x07, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x94, 0xFD, 0x00, 0x23, 0x84, 0xF8, 0x45, 0x30, 0xBD, 0xE8, ++0xF8, 0x83, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x96, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x2B, 0x4E, 0x34, 0x68, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0xD4, 0xFA, ++0x00, 0x2C, 0x3F, 0xD0, 0x28, 0x4D, 0x2B, 0x88, 0x00, 0x2B, 0x3B, 0xD0, 0xDF, 0xF8, 0xA4, 0x80, 0xDF, 0xF8, 0xA4, 0x90, ++0x37, 0x46, 0x23, 0x7C, 0xD9, 0x07, 0x01, 0xD4, 0x2B, 0x88, 0x6B, 0xB3, 0x38, 0x46, 0x0E, 0xF0, 0x83, 0xFB, 0xEF, 0xF3, ++0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x00, 0x30, 0x22, 0x7C, ++0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0xD3, 0x07, 0x02, 0xD4, 0x2B, 0x88, 0x01, 0x3B, 0x2B, 0x80, 0x63, 0x68, 0x00, 0x22, ++0x22, 0x74, 0x0B, 0xB1, 0xA0, 0x68, 0x98, 0x47, 0xE0, 0x68, 0x08, 0xB1, 0x00, 0xF0, 0xA0, 0xFA, 0xD9, 0xF8, 0x00, 0x30, ++0x3B, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x34, 0x68, ++0x00, 0x2C, 0xCC, 0xD1, 0x0B, 0x4C, 0x94, 0xF8, 0x45, 0x30, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0x80, 0x10, ++0x0E, 0xF0, 0x68, 0xFA, 0x07, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x2F, 0xFD, 0x00, 0x23, 0x84, 0xF8, 0x45, 0x30, ++0xBD, 0xE8, 0xF8, 0x83, 0x24, 0x65, 0x17, 0x00, 0x54, 0x28, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x96, 0x15, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF8, 0xB5, 0x0D, 0x4E, 0x35, 0x68, 0x95, 0xB1, 0x34, 0x89, 0x01, 0x34, ++0xA4, 0xB2, 0x37, 0x46, 0x38, 0x46, 0x0E, 0xF0, 0x2D, 0xFB, 0x6B, 0x68, 0x0B, 0xB1, 0xA8, 0x68, 0x98, 0x47, 0x0F, 0xF0, ++0x99, 0xFF, 0x35, 0x68, 0x34, 0x81, 0x01, 0x34, 0xA4, 0xB2, 0x00, 0x2D, 0xF0, 0xD1, 0xBD, 0xE8, 0xF8, 0x40, 0x00, 0xF0, ++0xF5, 0xB9, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x44, 0x4F, 0x06, 0x68, 0x15, 0x88, 0xDF, 0xF8, ++0x20, 0x91, 0xDF, 0xF8, 0x20, 0xA1, 0xDF, 0xF8, 0x20, 0xB1, 0x85, 0xB0, 0x4F, 0xF0, 0x00, 0x08, 0xCD, 0xE9, 0x02, 0x02, ++0x87, 0xF8, 0x02, 0x80, 0xCD, 0xF8, 0x04, 0x80, 0x4A, 0xE0, 0xC4, 0x1A, 0x2C, 0x44, 0x0C, 0x44, 0x55, 0x1B, 0xA9, 0xB2, ++0xA4, 0xB2, 0x00, 0x25, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x36, 0x4A, 0x01, 0x23, 0x13, 0x60, ++0xBA, 0xF8, 0x00, 0x30, 0xDB, 0xF8, 0x00, 0x20, 0xD9, 0xF8, 0x00, 0xC0, 0x00, 0x92, 0x02, 0xEB, 0xC3, 0x00, 0xB2, 0x68, ++0x42, 0x60, 0x00, 0x9A, 0x0C, 0xF1, 0x01, 0x0E, 0xC9, 0xF8, 0x00, 0xE0, 0x42, 0xF8, 0x33, 0x10, 0xFA, 0x78, 0x01, 0x33, ++0x01, 0x32, 0x88, 0x44, 0xAA, 0xF8, 0x00, 0x30, 0xFA, 0x70, 0x64, 0xBB, 0xC3, 0x78, 0xA7, 0xF8, 0x00, 0x80, 0x43, 0xF0, ++0x04, 0x03, 0x01, 0x22, 0xC3, 0x70, 0xBA, 0x70, 0xB8, 0x60, 0xBE, 0xF1, 0x00, 0x0F, 0x38, 0xD0, 0x21, 0x4B, 0xC9, 0xF8, ++0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, 0x31, 0xD1, 0x00, 0x2B, 0x2F, 0xD0, 0x62, 0xB6, 0x00, 0x2C, 0x2C, 0xD0, ++0x1C, 0x4B, 0x1A, 0x68, 0x73, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x1A, 0xDB, 0x01, 0x96, 0x21, 0x46, 0x1E, 0x46, ++0xF3, 0x68, 0x30, 0x89, 0x01, 0x33, 0x9B, 0xB2, 0x1A, 0x1A, 0x92, 0xB2, 0x4C, 0x19, 0x94, 0x42, 0xAB, 0xDA, 0x00, 0x24, ++0xB0, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, 0xE7, 0xD0, 0x0F, 0x4B, 0xC9, 0xF8, 0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, ++0xE0, 0xD1, 0x00, 0x2B, 0xDB, 0xD1, 0xDD, 0xE7, 0x00, 0x2B, 0xE2, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x00, 0x93, 0x4F, 0xF4, ++0x17, 0x72, 0x0F, 0xF0, 0xA9, 0xFE, 0x00, 0x9B, 0xD9, 0xE7, 0x02, 0x9B, 0x01, 0x98, 0x1E, 0x60, 0x03, 0x9B, 0x1D, 0x80, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x54, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xB0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x41, 0x4F, 0xB2, 0xF8, 0x00, 0xA0, 0x06, 0x68, 0xDF, 0xF8, 0x0C, 0xB1, 0x87, 0xB0, 0x4F, 0xF0, ++0x00, 0x08, 0xCD, 0xE9, 0x04, 0x02, 0x01, 0x22, 0x0B, 0x46, 0x87, 0xF8, 0x20, 0x20, 0xC1, 0x46, 0xCD, 0xF8, 0x0C, 0x80, ++0x39, 0xE0, 0x05, 0x44, 0xAD, 0x1A, 0xA1, 0xEB, 0x0A, 0x03, 0xAD, 0xB2, 0x9B, 0xB2, 0x00, 0x2D, 0x02, 0x93, 0x08, 0xBF, ++0x4F, 0xF0, 0x01, 0x09, 0xF2, 0xF7, 0x3C, 0xFC, 0x4F, 0xF0, 0x00, 0x0A, 0x02, 0x9B, 0x04, 0x46, 0x00, 0x28, 0x3A, 0xD0, ++0x7A, 0x68, 0x02, 0xB9, 0x38, 0x60, 0xDB, 0xF8, 0x00, 0x00, 0xF9, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x19, 0x44, 0x01, 0x32, ++0x00, 0x28, 0xF9, 0x60, 0x7A, 0x60, 0xB1, 0x68, 0x36, 0xDB, 0xCD, 0xF8, 0x00, 0x90, 0x00, 0x22, 0x20, 0x46, 0xF3, 0xF7, ++0x6F, 0xFC, 0xB8, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0xC8, 0xF8, 0x04, 0x40, 0xBC, 0x60, 0x05, 0xB3, 0xDB, 0xF8, 0x00, 0x20, ++0x73, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x2E, 0xDB, 0x03, 0x96, 0xA0, 0x46, 0x1E, 0x46, 0x2B, 0x46, 0xF2, 0x68, ++0x35, 0x89, 0x01, 0x32, 0x92, 0xB2, 0x51, 0x1B, 0x89, 0xB2, 0x03, 0xEB, 0x0A, 0x00, 0x88, 0x42, 0xBB, 0xDA, 0x02, 0x93, ++0xF2, 0xF7, 0x02, 0xFC, 0x00, 0x25, 0x02, 0x9B, 0x4F, 0xF0, 0x01, 0x09, 0x04, 0x46, 0x00, 0x28, 0xC4, 0xD1, 0x87, 0xF8, ++0x20, 0x00, 0x04, 0x9B, 0x03, 0x98, 0x1E, 0x60, 0x05, 0x9B, 0xA3, 0xF8, 0x00, 0xA0, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x00, 0x29, 0xC6, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x02, 0x93, 0x40, 0xF2, 0x9E, 0x22, 0x0F, 0xF0, 0x17, 0xFE, 0xB1, 0x68, ++0x02, 0x9B, 0xBC, 0xE7, 0x00, 0x2B, 0xCE, 0xD1, 0x05, 0x49, 0x07, 0x48, 0x02, 0x93, 0x40, 0xF2, 0xB3, 0x22, 0x0F, 0xF0, ++0x0B, 0xFE, 0x02, 0x9B, 0xC5, 0xE7, 0x00, 0xBF, 0x30, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x96, 0x15, 0x00, ++0xA0, 0x96, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x08, 0x91, 0x07, 0x68, 0xD9, 0xF8, ++0x00, 0x40, 0x1D, 0x88, 0x94, 0xF8, 0x00, 0xC0, 0xDF, 0xF8, 0xFC, 0xA0, 0x85, 0xB0, 0xB1, 0xF5, 0xC8, 0x6F, 0x0E, 0x9E, ++0x03, 0x93, 0x06, 0xEB, 0x46, 0x06, 0x28, 0xBF, 0x4F, 0xF4, 0xC8, 0x61, 0xBC, 0xF1, 0x03, 0x0F, 0x08, 0xBF, 0x34, 0x4B, ++0x02, 0x90, 0x07, 0xEB, 0x06, 0x16, 0x06, 0xF1, 0x14, 0x06, 0x90, 0x46, 0x08, 0xBF, 0x1E, 0x60, 0x00, 0x20, 0x2C, 0xE0, ++0xAE, 0xEB, 0x03, 0x04, 0x2C, 0x44, 0x0C, 0x44, 0x52, 0x1B, 0xA4, 0xB2, 0x91, 0xB2, 0x00, 0x25, 0xBC, 0xF1, 0x03, 0x0F, ++0x0D, 0xD1, 0xB1, 0xF5, 0x00, 0x6F, 0x0B, 0x46, 0x28, 0xBF, 0x4F, 0xF4, 0x00, 0x63, 0x43, 0xF0, 0x23, 0x43, 0x4F, 0xF0, ++0x04, 0x12, 0xB3, 0x60, 0xF1, 0x60, 0x31, 0x61, 0x72, 0x61, 0x88, 0x44, 0xA4, 0xB3, 0xDA, 0xF8, 0x00, 0x20, 0x7B, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xF1, 0x14, 0x0B, 0x1C, 0xDB, 0xBC, 0xF1, 0x03, 0x0F, 0x01, 0xD1, 0xC6, 0xF8, ++0x20, 0xB0, 0x38, 0x46, 0x5E, 0x46, 0x1F, 0x46, 0x21, 0x46, 0xD7, 0xE9, 0x02, 0x43, 0x01, 0x33, 0x1F, 0xFA, 0x84, 0xFE, ++0x9B, 0xB2, 0xA3, 0xEB, 0x0E, 0x02, 0x05, 0xEB, 0x04, 0x0B, 0x92, 0xB2, 0x4C, 0x19, 0x94, 0x42, 0xC6, 0xF8, 0x04, 0x80, ++0xC6, 0xF8, 0x00, 0xB0, 0xC0, 0xDA, 0x00, 0x24, 0xC6, 0xE7, 0x00, 0x2B, 0xE0, 0xD1, 0x4F, 0xF4, 0x4A, 0x72, 0x0D, 0x49, ++0x0D, 0x48, 0x01, 0x93, 0x0F, 0xF0, 0x90, 0xFD, 0xD9, 0xF8, 0x00, 0x20, 0x01, 0x9B, 0x92, 0xF8, 0x00, 0xC0, 0xD3, 0xE7, ++0xBC, 0xF1, 0x03, 0x0F, 0x02, 0xD1, 0x05, 0x4B, 0x34, 0x62, 0x5E, 0x60, 0x02, 0x9B, 0x1F, 0x60, 0x03, 0x9B, 0x1D, 0x80, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x60, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, ++0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x61, 0xB3, 0x0B, 0x8A, 0xDA, 0x07, 0x12, 0xD4, 0x16, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x20, 0x02, 0xE0, 0x0B, 0x8A, 0xDB, 0x07, 0x0A, 0xD4, 0x00, 0x2A, 0x49, 0x68, 0xF9, 0xDA, 0x00, 0x29, ++0xF7, 0xD1, 0x11, 0x49, 0x11, 0x48, 0x40, 0xF2, 0xE6, 0x32, 0x0F, 0xF0, 0x29, 0xBD, 0xCB, 0x68, 0x23, 0xF0, 0x03, 0x03, ++0x04, 0x33, 0x0E, 0x49, 0x4A, 0x68, 0x9A, 0x42, 0x8A, 0x68, 0x08, 0xBF, 0x0B, 0x68, 0xC0, 0xF8, 0x98, 0x30, 0x22, 0xF0, ++0x00, 0x40, 0x83, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, 0x13, 0x43, 0x8B, 0x60, 0x70, 0x47, ++0x00, 0xF1, 0xA0, 0x03, 0xE9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, ++0xEC, 0x34, 0x17, 0x00, 0x18, 0x4B, 0x19, 0x4A, 0x18, 0x68, 0x19, 0x49, 0xDF, 0xF8, 0x7C, 0xC0, 0xF0, 0xB5, 0xD0, 0xE9, ++0x00, 0x34, 0x17, 0x4D, 0x13, 0x60, 0x1C, 0x44, 0x2B, 0x60, 0x25, 0x1F, 0x0D, 0x60, 0x15, 0x4E, 0x15, 0x4D, 0x11, 0x68, ++0x31, 0x60, 0x29, 0x60, 0xD0, 0xE9, 0x02, 0x10, 0xDF, 0xF8, 0x5C, 0xE0, 0x12, 0x4F, 0x54, 0x60, 0x08, 0x44, 0x69, 0x60, ++0x11, 0x4C, 0x93, 0x60, 0x11, 0x4E, 0x03, 0x1F, 0xCE, 0xF8, 0x00, 0x30, 0xCC, 0xF8, 0x00, 0x10, 0x39, 0x60, 0x6E, 0x61, ++0x23, 0x68, 0x10, 0x61, 0x03, 0xF4, 0x00, 0x23, 0x43, 0xF4, 0xF0, 0x23, 0x43, 0xF0, 0x25, 0x03, 0xD1, 0x60, 0x51, 0x61, ++0x23, 0x60, 0xF0, 0xBD, 0x30, 0x36, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, 0xCC, 0x81, 0x32, 0x40, 0xC8, 0x81, 0x32, 0x40, ++0xD0, 0x81, 0x32, 0x40, 0xD4, 0x81, 0x32, 0x40, 0xE4, 0x81, 0x32, 0x40, 0x0C, 0x01, 0x32, 0x40, 0x05, 0x12, 0x00, 0x0C, ++0xE0, 0x81, 0x32, 0x40, 0xDC, 0x81, 0x32, 0x40, 0x10, 0xB4, 0x0A, 0x4C, 0x0A, 0x49, 0x22, 0x68, 0x83, 0x02, 0x03, 0xF4, ++0x80, 0x63, 0x22, 0xF4, 0x80, 0x62, 0x13, 0x43, 0x23, 0x60, 0x0B, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0xC0, 0x04, 0x00, 0xF4, ++0x00, 0x20, 0x23, 0xF4, 0x00, 0x23, 0x18, 0x43, 0x08, 0x60, 0x70, 0x47, 0x24, 0x03, 0x32, 0x40, 0x0C, 0x01, 0x32, 0x40, ++0x90, 0xF8, 0x9C, 0x20, 0xD0, 0xF8, 0x98, 0x30, 0x6A, 0xB9, 0x0E, 0x4A, 0x12, 0x68, 0x22, 0xF0, 0x00, 0x41, 0x8B, 0x42, ++0x02, 0xF0, 0x00, 0x42, 0x0A, 0x49, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, 0x13, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x08, 0x4A, ++0x12, 0x68, 0x22, 0xF0, 0x00, 0x41, 0x8B, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x04, 0x49, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, ++0x13, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0xD0, 0x81, 0x32, 0x40, 0xE0, 0x81, 0x32, 0x40, 0x10, 0xB5, 0x03, 0x8E, ++0x82, 0xB0, 0xC3, 0xB1, 0x2D, 0x4B, 0xC4, 0x69, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x38, 0xDB, 0xA3, 0x68, ++0x42, 0x6D, 0x1B, 0x88, 0x03, 0xF0, 0xFC, 0x03, 0x24, 0x2B, 0x43, 0xD0, 0x94, 0x2B, 0x03, 0xD1, 0x42, 0xF2, 0x02, 0x03, ++0x93, 0x43, 0x36, 0xD0, 0xE3, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x07, 0xE0, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x18, 0xDB, 0x00, 0xF1, 0xA0, 0x03, 0x1E, 0x49, 0x0A, 0x69, 0x9A, 0x42, 0x4A, 0x69, 0x08, 0xBF, ++0xCB, 0x68, 0xC0, 0xF8, 0x98, 0x30, 0x22, 0xF0, 0x00, 0x44, 0xA3, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x38, 0xBF, 0x02, 0xF1, ++0x00, 0x42, 0x13, 0x43, 0x4B, 0x61, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x9E, 0xBF, 0xC3, 0x69, 0x00, 0x2B, ++0xE3, 0xD0, 0x12, 0x49, 0x12, 0x48, 0x4F, 0xF4, 0xD7, 0x72, 0x05, 0xE0, 0x00, 0x2C, 0xC4, 0xD1, 0x0E, 0x49, 0x10, 0x48, ++0x4F, 0xF4, 0xC2, 0x72, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0x0F, 0xF0, 0x2F, 0xBC, 0x0D, 0x4B, 0x01, 0x90, 0xD3, 0xF8, ++0x74, 0x33, 0x98, 0x47, 0x01, 0x98, 0xC1, 0xE7, 0x93, 0x04, 0xBF, 0xD5, 0x08, 0x4B, 0x01, 0x90, 0xD3, 0xF8, 0xFC, 0x33, ++0x98, 0x47, 0x01, 0x98, 0xB8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0x96, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x29, 0x46, 0xD0, 0x2D, 0xE9, 0xF8, 0x4F, ++0x07, 0x46, 0xDF, 0xF8, 0x8C, 0xA0, 0xDF, 0xF8, 0x8C, 0xB0, 0x08, 0x46, 0x1F, 0x49, 0x99, 0x46, 0x4F, 0xF0, 0x00, 0x08, ++0xD7, 0xE9, 0x02, 0x45, 0x01, 0x35, 0xAB, 0xB2, 0xA6, 0xB2, 0x9D, 0x1B, 0xAD, 0xB2, 0xAD, 0x1A, 0xA8, 0x42, 0x23, 0xDB, ++0xF6, 0x1A, 0x16, 0x44, 0x06, 0x44, 0xB6, 0xB2, 0xA8, 0xB2, 0xC5, 0x1C, 0x4F, 0xEA, 0x98, 0x03, 0xAD, 0x08, 0x14, 0x44, ++0x09, 0xEB, 0x83, 0x03, 0x08, 0xD0, 0x1A, 0x46, 0x03, 0xEB, 0x85, 0x05, 0xE3, 0x1A, 0xD4, 0x58, 0x42, 0xF8, 0x04, 0x4B, ++0xAA, 0x42, 0xFA, 0xD1, 0xBE, 0xB1, 0xDA, 0xF8, 0x00, 0x30, 0x7F, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x80, 0x44, 0x00, 0x2B, ++0x1F, 0xFA, 0x88, 0xF8, 0x04, 0xDB, 0x30, 0x46, 0x00, 0x22, 0xD1, 0xE7, 0x00, 0x26, 0xDE, 0xE7, 0x00, 0x2F, 0xF8, 0xD1, ++0x40, 0xF2, 0x2D, 0x42, 0x58, 0x46, 0x0F, 0xF0, 0xFF, 0xFB, 0x02, 0x49, 0xF1, 0xE7, 0xBD, 0xE8, 0xF8, 0x8F, 0x70, 0x47, ++0x70, 0x79, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xEC, 0x96, 0x15, 0x00, 0x38, 0xB5, 0x13, 0x4C, 0x94, 0xF8, 0x21, 0x30, ++0xA3, 0xB9, 0x20, 0x61, 0x11, 0x48, 0xE3, 0x69, 0xE2, 0x68, 0x61, 0x69, 0x65, 0x68, 0x90, 0xF8, 0xB9, 0x00, 0x13, 0x44, ++0x29, 0x44, 0xA2, 0x68, 0x61, 0x61, 0x01, 0x25, 0xB3, 0xEB, 0x40, 0x2F, 0xE3, 0x61, 0x84, 0xF8, 0x21, 0x50, 0xA2, 0x61, ++0x03, 0xD2, 0x38, 0xBD, 0xA3, 0x69, 0x58, 0x60, 0xE8, 0xE7, 0x20, 0x69, 0xF3, 0xF7, 0x90, 0xF9, 0x00, 0x23, 0xC4, 0xE9, ++0x04, 0x33, 0xC4, 0xE9, 0x06, 0x33, 0x84, 0xF8, 0x21, 0x30, 0x38, 0xBD, 0x30, 0x65, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0xAB, 0x4E, 0xD0, 0xF8, 0x1C, 0xC0, 0x35, 0x68, 0x86, 0xB0, 0x04, 0x46, 0xCD, 0xF8, 0x14, 0xC0, ++0xAD, 0xF8, 0x0E, 0x30, 0x2B, 0x78, 0x02, 0x2B, 0x91, 0x46, 0x00, 0xF0, 0xAD, 0x80, 0x01, 0x2B, 0xDF, 0xF8, 0xC4, 0x82, ++0x22, 0xD0, 0x01, 0x20, 0x00, 0x23, 0xD8, 0xF8, 0xAC, 0x52, 0x4A, 0x46, 0xCD, 0xE9, 0x00, 0x30, 0x0D, 0xF1, 0x0E, 0x03, ++0x05, 0xA8, 0xA8, 0x47, 0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0x46, 0x1F, 0xD0, 0x01, 0x2B, 0x59, 0xD0, 0xD8, 0xF8, ++0x98, 0x32, 0x05, 0x99, 0x20, 0x46, 0x2A, 0x46, 0x98, 0x47, 0x0E, 0x9B, 0x63, 0x60, 0x0F, 0x9B, 0x95, 0x48, 0xA3, 0x60, ++0x21, 0x46, 0x0D, 0xF0, 0x3F, 0xFF, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xD8, 0xF8, 0xB0, 0x52, 0x00, 0x23, 0x00, 0x93, ++0x0D, 0xF1, 0x0E, 0x02, 0x05, 0xA8, 0xA8, 0x47, 0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0x46, 0xDF, 0xD1, 0xDF, 0xF8, ++0x64, 0x92, 0x99, 0xF8, 0x02, 0x30, 0x00, 0x2B, 0xDB, 0xD0, 0xB9, 0xF8, 0x00, 0x30, 0x7A, 0x68, 0x3A, 0x33, 0xBB, 0x60, ++0xD3, 0x78, 0x6F, 0xF3, 0x87, 0x13, 0xD3, 0x70, 0x99, 0xF8, 0x03, 0x30, 0xBB, 0x73, 0x00, 0x23, 0x3B, 0x60, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x7F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x20, 0xA2, 0x7E, 0x48, ++0xDA, 0xF8, 0x00, 0x30, 0x39, 0x46, 0x01, 0x33, 0xCA, 0xF8, 0x00, 0x30, 0x0D, 0xF0, 0x08, 0xFF, 0xD8, 0xF8, 0x44, 0x34, ++0x98, 0x47, 0xDA, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x75, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCA, 0xF8, 0x00, 0x30, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x00, 0x23, 0xC9, 0xE9, 0x00, 0x33, 0x32, 0x68, 0x13, 0x78, 0x01, 0x2B, 0xA5, 0xD1, 0xF2, 0xF7, ++0x15, 0xF9, 0x07, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x92, 0x80, 0x6D, 0x4E, 0x96, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x00, 0xF0, ++0x96, 0x80, 0x73, 0x68, 0x81, 0x68, 0x32, 0x68, 0x03, 0xF1, 0x01, 0x0C, 0x4F, 0xEA, 0x0C, 0x63, 0x21, 0xF0, 0xFE, 0x41, ++0x03, 0xF0, 0xFE, 0x43, 0x0B, 0x43, 0x00, 0x21, 0x83, 0x60, 0x00, 0x91, 0x3A, 0x23, 0x04, 0xF1, 0x30, 0x01, 0xC6, 0xF8, ++0x04, 0xC0, 0xF3, 0xF7, 0x43, 0xF9, 0x60, 0x4A, 0xF3, 0x68, 0x92, 0xF8, 0xB8, 0x20, 0x3A, 0x33, 0xF3, 0x60, 0x38, 0x46, ++0x00, 0x2A, 0x40, 0xF0, 0xA7, 0x80, 0xD6, 0xE9, 0x01, 0x12, 0xF3, 0xF7, 0xD3, 0xF8, 0x5A, 0x49, 0x0A, 0x78, 0x00, 0x23, ++0x42, 0xF0, 0x01, 0x02, 0x0A, 0x70, 0x73, 0x60, 0xF3, 0x60, 0x33, 0x60, 0xB3, 0x60, 0x86, 0xF8, 0x20, 0x30, 0x68, 0xE7, ++0x54, 0x4D, 0x42, 0xF2, 0x24, 0x03, 0xEA, 0x58, 0x00, 0x2A, 0x68, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x4A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x42, 0xF2, 0x34, 0x02, 0xDF, 0xF8, 0x44, 0x81, 0xA8, 0x5A, 0xD8, 0xF8, ++0x00, 0x30, 0x02, 0x91, 0x01, 0x33, 0xB0, 0xF5, 0xC3, 0x7F, 0xC8, 0xF8, 0x00, 0x30, 0x48, 0x48, 0xDF, 0xF8, 0x3C, 0xA1, ++0x84, 0xBF, 0x00, 0x23, 0xAB, 0x52, 0x0D, 0xF0, 0xD7, 0xFE, 0x45, 0x4A, 0x02, 0x99, 0xD2, 0xF8, 0x00, 0xC0, 0x42, 0xF2, ++0x34, 0x0E, 0x07, 0x46, 0x35, 0xF8, 0x0E, 0x30, 0xBB, 0x81, 0x0C, 0xEB, 0xC3, 0x00, 0x04, 0xF1, 0x30, 0x02, 0x42, 0x60, ++0x4C, 0xF8, 0x33, 0xA0, 0xDF, 0xF8, 0x08, 0xC1, 0x78, 0x60, 0x95, 0xF8, 0x02, 0xAC, 0x9C, 0xF8, 0x03, 0x00, 0xD8, 0xF8, ++0x00, 0x20, 0x01, 0x33, 0x0A, 0xF1, 0x01, 0x0A, 0x01, 0x30, 0x25, 0xF8, 0x0E, 0x30, 0x85, 0xF8, 0x02, 0xAC, 0x8C, 0xF8, ++0x03, 0x00, 0x3A, 0xB1, 0x2B, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, 0x00, 0x20, 0x0A, 0xB9, 0x00, 0x2B, 0x48, 0xD1, ++0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x7F, 0xF4, 0xFE, 0xAE, 0xDF, 0xF8, 0xC4, 0x80, 0x00, 0x23, 0xD8, 0xF8, 0xB4, 0x52, ++0x21, 0xE7, 0x23, 0x7C, 0x29, 0x48, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x0F, 0xF0, 0x2E, 0xF8, 0x20, 0x4B, 0x83, 0xF8, ++0x20, 0x70, 0x26, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x76, 0xF8, 0x23, 0x7C, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, ++0xF9, 0xE6, 0x03, 0x7C, 0xDF, 0xF8, 0x8C, 0x80, 0x43, 0xF0, 0x01, 0x03, 0x03, 0x74, 0xD8, 0xF8, 0x98, 0x32, 0x61, 0x46, ++0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x19, 0x4C, ++0xD8, 0xF8, 0x44, 0x24, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x01, 0x46, 0x33, 0xB1, 0x0A, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x11, 0x48, 0xF0, 0xF7, 0x31, 0xFE, 0xE0, 0xE6, ++0xFF, 0xF7, 0x7E, 0xFE, 0x59, 0xE7, 0x62, 0xB6, 0xB4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x24, 0x65, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x30, 0x65, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x9C, 0x4E, 0x17, 0x00, ++0x7C, 0x36, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, 0x0C, 0x97, 0x15, 0x00, 0x20, 0x97, 0x15, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xF8, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x54, 0x65, 0x17, 0x00, 0x3C, 0x00, 0x00, 0xC0, ++0x2D, 0xE9, 0xF0, 0x4F, 0xAE, 0x4B, 0xDF, 0xF8, 0x00, 0xA3, 0xC1, 0x69, 0x9A, 0xF8, 0x32, 0x20, 0x1B, 0x68, 0x87, 0xB0, ++0x04, 0x46, 0x05, 0x91, 0xAD, 0xF8, 0x12, 0x20, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xF0, 0x3F, 0x81, 0x02, 0x2B, 0x77, 0xD0, ++0xA6, 0x4A, 0x27, 0x8E, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xBF, 0x80, 0x01, 0x2B, 0xA3, 0x4E, ++0x4F, 0xF0, 0x00, 0x03, 0x00, 0xF0, 0x3A, 0x81, 0xCD, 0xE9, 0x00, 0x33, 0x39, 0x46, 0xD6, 0xF8, 0xAC, 0x52, 0x0D, 0xF1, ++0x12, 0x03, 0x5A, 0x46, 0x05, 0xA8, 0xA8, 0x47, 0x07, 0xEB, 0x0B, 0x01, 0xCA, 0xF8, 0x1C, 0x10, 0x07, 0x46, 0x00, 0x21, ++0x04, 0xF1, 0x58, 0x00, 0xEB, 0xF7, 0x7E, 0xFD, 0x94, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xF0, 0xB8, 0x80, ++0x01, 0x2B, 0x00, 0xF0, 0x49, 0x81, 0x02, 0x2B, 0x41, 0xD1, 0xDF, 0xF8, 0x88, 0xA2, 0x9A, 0xF8, 0x02, 0x30, 0x00, 0x2B, ++0x3B, 0xD0, 0xBA, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x04, 0x20, 0x3A, 0x33, 0xC8, 0xF8, 0x08, 0x30, 0xD3, 0x78, 0x6F, 0xF3, ++0x87, 0x13, 0xD3, 0x70, 0x9A, 0xF8, 0x03, 0x30, 0x88, 0xF8, 0x0E, 0x30, 0x00, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xEF, 0xF3, ++0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x83, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x14, 0xB2, 0x82, 0x48, ++0xDB, 0xF8, 0x00, 0x30, 0x41, 0x46, 0x01, 0x33, 0xCB, 0xF8, 0x00, 0x30, 0x0D, 0xF0, 0x8C, 0xFD, 0xD6, 0xF8, 0x44, 0x34, ++0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x79, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x72, 0x4B, 0x1A, 0x68, 0x00, 0x23, 0xCA, 0xE9, 0x00, 0x33, 0x13, 0x78, 0x03, 0x2B, 0x00, 0xF0, ++0x9E, 0x81, 0xD6, 0xF8, 0x98, 0x32, 0x05, 0x99, 0x3A, 0x46, 0x20, 0x46, 0x98, 0x47, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x6E, 0x4E, 0x42, 0xF2, 0x24, 0x03, 0xF2, 0x58, 0x00, 0x2A, 0x00, 0xF0, 0x60, 0x81, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x66, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x42, 0xF2, 0x34, 0x02, 0x67, 0x4F, 0xB1, 0x5A, 0x3B, 0x68, ++0x66, 0x48, 0x01, 0x33, 0xB1, 0xF5, 0xC3, 0x7F, 0x3B, 0x60, 0x84, 0xBF, 0x00, 0x23, 0xB3, 0x52, 0x0D, 0xF0, 0x92, 0xFD, ++0x62, 0x4A, 0x42, 0xF2, 0x34, 0x0E, 0xD2, 0xF8, 0x00, 0xC0, 0x36, 0xF8, 0x0E, 0x30, 0x83, 0x81, 0x0C, 0xEB, 0xC3, 0x01, ++0x04, 0xF1, 0x30, 0x02, 0x4A, 0x60, 0x5D, 0x4A, 0x4C, 0xF8, 0x33, 0x20, 0xDF, 0xF8, 0x94, 0xC1, 0x41, 0x60, 0x96, 0xF8, ++0x02, 0x1C, 0x9C, 0xF8, 0x03, 0x20, 0x80, 0x46, 0x38, 0x68, 0x01, 0x33, 0x01, 0x31, 0x01, 0x32, 0x26, 0xF8, 0x0E, 0x30, ++0x86, 0xF8, 0x02, 0x1C, 0x8C, 0xF8, 0x03, 0x20, 0x30, 0xB1, 0x4C, 0x4B, 0x01, 0x38, 0x1B, 0x68, 0x38, 0x60, 0x08, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x46, 0x4B, 0x27, 0x8E, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0xDA, 0x00, 0x2F, ++0x00, 0xF0, 0x07, 0x81, 0xB7, 0xF5, 0x40, 0x5F, 0x00, 0xF2, 0x0A, 0x81, 0x3E, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, ++0x7F, 0xF4, 0x34, 0xAF, 0x3D, 0x4E, 0x39, 0x46, 0xD6, 0xF8, 0xB4, 0x72, 0x00, 0x23, 0x00, 0x93, 0x0D, 0xF1, 0x12, 0x02, ++0x05, 0xA8, 0xB8, 0x47, 0x07, 0x46, 0x3C, 0xE7, 0x3F, 0x4A, 0x40, 0x48, 0x53, 0x68, 0x60, 0x66, 0x04, 0xF1, 0x30, 0x00, ++0xA0, 0x66, 0x04, 0xF1, 0x68, 0x00, 0x3D, 0x49, 0xC4, 0xF8, 0x6C, 0x90, 0x18, 0x62, 0x3A, 0x23, 0x21, 0x67, 0x63, 0x67, ++0x4F, 0xF0, 0x04, 0x11, 0xA3, 0x67, 0x00, 0x23, 0x03, 0x90, 0xE1, 0x67, 0xC4, 0xF8, 0x88, 0x30, 0x10, 0x68, 0x03, 0x99, ++0x05, 0x22, 0xF0, 0xF7, 0xC5, 0xF9, 0x34, 0x4A, 0x13, 0x68, 0x18, 0x05, 0xFC, 0xD5, 0x13, 0x68, 0x59, 0x03, 0x03, 0xD5, ++0x11, 0x68, 0x41, 0xF0, 0x80, 0x61, 0x11, 0x60, 0x1A, 0x05, 0x21, 0xD5, 0xEF, 0xF3, 0x05, 0x80, 0x2D, 0x49, 0x41, 0xF2, ++0x4C, 0x12, 0x8B, 0x58, 0x43, 0xF0, 0x00, 0x63, 0x8B, 0x50, 0x00, 0x28, 0x40, 0xF0, 0xF3, 0x80, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1C, 0x4B, 0x25, 0x48, 0x19, 0x68, 0x00, 0x25, ++0x4A, 0x1C, 0x1A, 0x60, 0x45, 0x61, 0x2A, 0xB1, 0x15, 0x4A, 0x19, 0x60, 0x13, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, ++0x1F, 0x4D, 0x2B, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x1E, 0x4B, 0x18, 0x68, 0xA9, 0xF1, 0x14, 0x01, 0x00, 0xF5, 0x0B, 0x70, ++0x0D, 0xF0, 0xAC, 0xFC, 0x01, 0x23, 0x2B, 0x60, 0xEF, 0xF7, 0x2E, 0xFD, 0x31, 0xE7, 0x0A, 0xF1, 0x40, 0x00, 0x0F, 0xF0, ++0x67, 0xF9, 0x05, 0x4B, 0x1B, 0x68, 0x81, 0x46, 0x1B, 0x78, 0x00, 0xF1, 0x3C, 0x0B, 0xB5, 0xE6, 0x39, 0x46, 0xD6, 0xF8, ++0xB0, 0x72, 0x8C, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0xA8, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x3C, 0x00, 0x00, 0xC0, 0x60, 0x65, 0x17, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x3A, 0x00, 0x00, 0xA3, 0x4C, 0x11, 0x07, 0x40, ++0x00, 0x00, 0x07, 0x40, 0x48, 0x35, 0x17, 0x00, 0x54, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0xB0, 0xDE, 0x17, 0x00, ++0x54, 0x65, 0x17, 0x00, 0xF1, 0xF7, 0x92, 0xFE, 0x83, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0xDF, 0xF8, 0x38, 0xA1, 0x9A, 0xF8, ++0x20, 0x30, 0x00, 0x2B, 0x41, 0xD0, 0xDA, 0xF8, 0x04, 0x30, 0x81, 0x68, 0xDA, 0xF8, 0x00, 0x20, 0x03, 0xF1, 0x01, 0x0C, ++0x4F, 0xEA, 0x0C, 0x63, 0x21, 0xF0, 0xFE, 0x41, 0x03, 0xF0, 0xFE, 0x43, 0x0B, 0x43, 0x00, 0x21, 0x83, 0x60, 0x00, 0x91, ++0x3A, 0x23, 0x04, 0xF1, 0x30, 0x01, 0xCA, 0xF8, 0x04, 0xC0, 0xF2, 0xF7, 0xBF, 0xFE, 0x3C, 0x4A, 0xDA, 0xF8, 0x0C, 0x30, ++0x92, 0xF8, 0xB8, 0x20, 0x3A, 0x33, 0xCA, 0xF8, 0x0C, 0x30, 0x58, 0x46, 0x00, 0x2A, 0x63, 0xD1, 0xDA, 0xE9, 0x01, 0x12, ++0xF2, 0xF7, 0x4E, 0xFE, 0x35, 0x49, 0x0A, 0x78, 0x00, 0x23, 0x42, 0xF0, 0x01, 0x02, 0x0A, 0x70, 0xCA, 0xF8, 0x04, 0x30, ++0xCA, 0xF8, 0x0C, 0x30, 0xCA, 0xF8, 0x00, 0x30, 0xCA, 0xF8, 0x08, 0x30, 0x8A, 0xF8, 0x20, 0x30, 0x12, 0xE0, 0x23, 0x7C, ++0x2D, 0x48, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x0E, 0xF0, 0x00, 0xFE, 0x2B, 0x4B, 0x83, 0xF8, 0x20, 0xB0, 0x2B, 0x49, ++0x4F, 0xF4, 0x80, 0x60, 0x0E, 0xF0, 0x48, 0xFE, 0x23, 0x7C, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x27, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x02, 0x2B, 0x3F, 0xF4, 0x5D, 0xAE, 0x9A, 0xE6, 0x25, 0x49, 0x25, 0x48, 0x40, 0xF2, 0x21, 0x52, 0x0F, 0xF0, ++0x2F, 0xF8, 0x9C, 0xE6, 0x21, 0x49, 0x23, 0x48, 0x40, 0xF2, 0x23, 0x52, 0x0F, 0xF0, 0x28, 0xF8, 0x95, 0xE6, 0x23, 0x7C, ++0x20, 0x4E, 0x05, 0x99, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0xD6, 0xF8, 0x98, 0x32, 0x20, 0x46, 0x98, 0x47, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1A, 0x4C, 0xD6, 0xF8, 0x44, 0x24, ++0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x01, 0x46, 0x33, 0xB1, 0x14, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x12, 0x48, 0xF0, 0xF7, 0xEF, 0xFB, 0x6E, 0xE6, 0xFF, 0xF7, 0x3C, 0xFC, ++0x9C, 0xE7, 0x10, 0x4B, 0x00, 0x22, 0x5A, 0x61, 0x1E, 0xE7, 0x0F, 0x4A, 0xE8, 0xE6, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, ++0x9C, 0x4E, 0x17, 0x00, 0x0C, 0x97, 0x15, 0x00, 0x30, 0x65, 0x17, 0x00, 0x20, 0x97, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x34, 0x97, 0x15, 0x00, 0x44, 0x97, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xFC, 0x96, 0x15, 0x00, 0x48, 0x35, 0x17, 0x00, 0x60, 0x65, 0x17, 0x00, 0x0D, 0x4B, 0xC1, 0x69, ++0xD3, 0xF8, 0x98, 0x32, 0x10, 0xB5, 0x00, 0x22, 0x04, 0x46, 0x98, 0x47, 0x0A, 0x48, 0x03, 0x68, 0x53, 0xB1, 0x23, 0x7C, ++0x43, 0xF0, 0x01, 0x03, 0x00, 0x22, 0x23, 0x74, 0x62, 0x60, 0x21, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x0D, 0xF0, 0xA0, 0xBB, ++0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x19, 0xBB, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x24, 0x65, 0x17, 0x00, ++0x0C, 0x4A, 0x0D, 0x49, 0x93, 0x68, 0x09, 0x68, 0x8B, 0x42, 0x11, 0xD0, 0x51, 0x68, 0x23, 0xF0, 0x00, 0x40, 0x09, 0x1A, ++0x9F, 0x29, 0x0C, 0xD8, 0x11, 0x68, 0x03, 0xF0, 0x00, 0x43, 0x88, 0x42, 0x88, 0xBF, 0x03, 0xF1, 0x00, 0x43, 0x0B, 0x43, ++0x93, 0x60, 0x23, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0xEC, 0x34, 0x17, 0x00, 0xD4, 0x81, 0x32, 0x40, ++0x1E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x21, 0xDB, 0x1B, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x9B, 0x07, 0x04, 0xD5, 0x63, 0x6D, 0x03, 0xF0, 0x3C, 0x03, 0x3C, 0x2B, 0x25, 0xD0, 0x23, 0x8E, 0x53, 0xB1, ++0x62, 0x6D, 0x02, 0xF0, 0x7C, 0x02, 0x08, 0x2A, 0x0D, 0xD0, 0x0C, 0x2A, 0x19, 0xD0, 0x04, 0x2A, 0x09, 0xD0, 0x04, 0x3B, ++0x23, 0x86, 0x00, 0x23, 0x10, 0x4A, 0x23, 0x74, 0x84, 0xF8, 0x9C, 0x30, 0xE4, 0x60, 0x62, 0x60, 0x10, 0xBD, 0x08, 0x3B, ++0x23, 0x86, 0xF4, 0xE7, 0x0C, 0x4B, 0x42, 0x69, 0x9A, 0x42, 0xD9, 0xD0, 0x0B, 0x49, 0x0C, 0x48, 0x40, 0xF2, 0x14, 0x62, ++0x0E, 0xF0, 0x98, 0xFF, 0xD2, 0xE7, 0x0C, 0x3B, 0x23, 0x86, 0xE6, 0xE7, 0x23, 0x8E, 0x04, 0x3B, 0x9B, 0xB2, 0x23, 0x86, ++0xD5, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x3D, 0x48, 0x13, 0x00, 0x0D, 0xF0, 0xAD, 0xBA, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x97, 0x15, 0x00, 0x06, 0x4B, 0x07, 0x4A, 0x4F, 0xF4, 0x80, 0x31, 0x19, 0x60, 0x13, 0x68, ++0x23, 0xF4, 0x80, 0x33, 0x13, 0x60, 0x4F, 0xF4, 0x80, 0x10, 0x0D, 0xF0, 0x7F, 0xBA, 0x00, 0xBF, 0x7C, 0x80, 0x32, 0x40, ++0x80, 0x80, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x47, 0x21, 0x4D, 0x22, 0x4E, 0x6B, 0x69, 0x32, 0x68, 0x93, 0x42, 0x84, 0xB0, ++0x38, 0xD0, 0xDF, 0xF8, 0x88, 0x80, 0x1F, 0x4F, 0xDF, 0xF8, 0x84, 0x90, 0x20, 0xE0, 0x6B, 0x69, 0x1D, 0x48, 0x23, 0xF0, ++0x00, 0x44, 0x21, 0x46, 0x62, 0x69, 0xBA, 0x42, 0x0A, 0xD0, 0xD6, 0xF8, 0x00, 0xE0, 0xD9, 0xF8, 0x00, 0xA0, 0xCD, 0xE9, ++0x00, 0xC3, 0xCD, 0xE9, 0x02, 0xEA, 0xEB, 0x68, 0x0E, 0xF0, 0xD4, 0xFC, 0x20, 0x46, 0xFF, 0xF7, 0x7F, 0xFF, 0x01, 0x23, ++0x84, 0xF8, 0x9C, 0x30, 0xD8, 0xF8, 0xC0, 0x32, 0x20, 0x46, 0x98, 0x47, 0x6B, 0x69, 0x32, 0x68, 0x93, 0x42, 0x11, 0xD0, ++0xD5, 0xF8, 0x10, 0xC0, 0x23, 0xF0, 0x00, 0x41, 0xAC, 0xEB, 0x01, 0x02, 0x9F, 0x2A, 0x03, 0xF0, 0x00, 0x43, 0xD4, 0xD8, ++0xEA, 0x68, 0x91, 0x42, 0x88, 0xBF, 0x03, 0xF1, 0x00, 0x43, 0x13, 0x43, 0x6B, 0x61, 0xCD, 0xE7, 0x04, 0xB0, 0xBD, 0xE8, ++0xF0, 0x87, 0x00, 0xBF, 0xEC, 0x34, 0x17, 0x00, 0xE4, 0x81, 0x32, 0x40, 0x0D, 0xF0, 0xAD, 0xBA, 0x90, 0x97, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xE0, 0x81, 0x32, 0x40, 0x00, 0xB5, 0x10, 0x4A, 0x10, 0x4B, 0x12, 0x68, 0x89, 0xB0, 0x08, 0x33, ++0x03, 0x92, 0x53, 0xF8, 0x08, 0x2C, 0x04, 0x92, 0x53, 0xF8, 0x04, 0x2C, 0x05, 0x92, 0x1B, 0x68, 0x06, 0x93, 0x01, 0xA8, ++0x00, 0x21, 0xEB, 0xF7, 0x73, 0xFA, 0x03, 0x9B, 0x03, 0xF0, 0x0F, 0x03, 0x02, 0x2B, 0x02, 0xD0, 0x09, 0xB0, 0x5D, 0xF8, ++0x04, 0xFB, 0x01, 0xA8, 0x0E, 0xF0, 0x8C, 0xFF, 0x09, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x00, 0xBF, 0xB0, 0x10, 0x34, 0x40, ++0xB4, 0x10, 0x34, 0x40, 0x38, 0xB5, 0xD0, 0xF8, 0xFC, 0x31, 0x04, 0x46, 0x00, 0xF5, 0xFE, 0x75, 0x4B, 0xB1, 0x28, 0x46, ++0x0D, 0xF0, 0xDE, 0xFA, 0x01, 0x21, 0xFA, 0xF7, 0x2B, 0xF9, 0xD4, 0xF8, 0xFC, 0x31, 0x00, 0x2B, 0xF5, 0xD1, 0x4F, 0xF4, ++0x1E, 0x72, 0x00, 0x21, 0x20, 0x46, 0xEA, 0xF7, 0xF9, 0xF9, 0x23, 0x46, 0x04, 0xF1, 0x48, 0x01, 0x21, 0x22, 0x83, 0xF8, ++0xA4, 0x21, 0x83, 0xF8, 0xA5, 0x21, 0x08, 0x33, 0x8B, 0x42, 0xF8, 0xD1, 0xFF, 0x23, 0x84, 0xF8, 0x22, 0x30, 0x38, 0xBD, ++0x2D, 0xE9, 0xF0, 0x43, 0x49, 0x48, 0x4A, 0x4F, 0x83, 0xB0, 0x81, 0x46, 0x0D, 0xF0, 0x72, 0xFA, 0x07, 0xF5, 0x0C, 0x75, ++0x00, 0x26, 0x40, 0xF2, 0x16, 0x38, 0xA5, 0xF5, 0x0C, 0x71, 0x08, 0x46, 0x01, 0x91, 0xFF, 0xF7, 0xC7, 0xFF, 0x01, 0x99, ++0x48, 0x46, 0x0D, 0xF0, 0x67, 0xFA, 0xA5, 0xF1, 0x28, 0x04, 0x20, 0x46, 0x0D, 0xF0, 0x5E, 0xFA, 0x04, 0xF1, 0x28, 0x00, ++0x08, 0x34, 0x0D, 0xF0, 0x59, 0xFA, 0xAC, 0x42, 0xF5, 0xD1, 0x4F, 0x36, 0x46, 0x45, 0x04, 0xF5, 0x1E, 0x75, 0xE4, 0xD1, ++0x38, 0x4D, 0x40, 0xF2, 0x52, 0x48, 0xA5, 0xF1, 0x28, 0x04, 0x20, 0x46, 0x0D, 0xF0, 0x4A, 0xFA, 0x04, 0xF1, 0x28, 0x00, ++0x08, 0x34, 0x0D, 0xF0, 0x45, 0xFA, 0xAC, 0x42, 0xF5, 0xD1, 0x4F, 0x36, 0x46, 0x45, 0x04, 0xF5, 0x1E, 0x75, 0xEE, 0xD1, ++0x2F, 0x48, 0x30, 0x4D, 0x30, 0x4C, 0x00, 0xF1, 0x30, 0x06, 0xFF, 0xF7, 0x97, 0xFF, 0x41, 0xF6, 0xF8, 0x12, 0x4F, 0xF0, ++0x00, 0x08, 0x41, 0xF6, 0x64, 0x11, 0x41, 0xF6, 0xD0, 0x03, 0xBD, 0x50, 0x06, 0xF5, 0x12, 0x70, 0x86, 0xF8, 0x00, 0x80, ++0x4F, 0xF0, 0x20, 0x62, 0x7C, 0x50, 0xFA, 0x50, 0xFF, 0xF7, 0x84, 0xFF, 0x41, 0xF6, 0x58, 0x30, 0x41, 0xF6, 0x70, 0x41, ++0x07, 0xF8, 0x00, 0x80, 0x41, 0xF6, 0xDC, 0x32, 0x05, 0xF1, 0x40, 0x00, 0x78, 0x50, 0x41, 0xF6, 0x48, 0x33, 0x04, 0xF5, ++0xA4, 0x61, 0xB9, 0x50, 0x06, 0xF5, 0x98, 0x60, 0x1C, 0x4A, 0xFA, 0x50, 0xFF, 0xF7, 0x6E, 0xFF, 0x41, 0xF6, 0xD0, 0x52, ++0x41, 0xF6, 0xE8, 0x61, 0x41, 0xF6, 0x54, 0x63, 0x18, 0x48, 0x07, 0xF8, 0x02, 0x80, 0xC6, 0xF8, 0xE0, 0x04, 0x04, 0xF5, ++0x24, 0x62, 0x06, 0xF5, 0xE7, 0x60, 0x05, 0xF1, 0x80, 0x06, 0x7E, 0x50, 0xFA, 0x50, 0xFF, 0xF7, 0x59, 0xFF, 0x42, 0xF2, ++0x60, 0x16, 0x11, 0x4A, 0x42, 0xF2, 0xCC, 0x00, 0x42, 0xF2, 0x48, 0x01, 0x42, 0xF2, 0x38, 0x03, 0xC0, 0x35, 0x04, 0xF5, ++0x76, 0x64, 0xBD, 0x51, 0x3C, 0x50, 0x07, 0xF8, 0x01, 0x80, 0xFA, 0x50, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x00, 0xBF, ++0xF8, 0x87, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x48, 0x80, 0x17, 0x00, 0x18, 0x7E, 0x17, 0x00, 0x04, 0x38, 0x18, 0x00, ++0xC0, 0x8C, 0x17, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x02, 0x0C, 0x00, 0x00, 0x03, 0x0D, 0x2D, 0xE9, 0xF0, 0x41, ++0x05, 0x46, 0x79, 0x48, 0x95, 0xF8, 0x19, 0x80, 0x0E, 0x46, 0x0D, 0xF0, 0x11, 0xFA, 0x00, 0x28, 0x00, 0xF0, 0xE1, 0x80, ++0x6B, 0x7F, 0x04, 0x46, 0x00, 0x2B, 0x40, 0xF0, 0xA5, 0x80, 0x73, 0x4F, 0x05, 0xF1, 0x12, 0x02, 0x11, 0x68, 0x2B, 0x68, ++0x92, 0x88, 0x62, 0x85, 0xC4, 0xF8, 0x26, 0x10, 0x63, 0x60, 0x28, 0x7E, 0x6E, 0x4B, 0x6F, 0x4A, 0x6F, 0x49, 0x10, 0x28, ++0x38, 0xBF, 0x10, 0x20, 0x20, 0x77, 0x28, 0x8A, 0xA0, 0x82, 0xA8, 0x68, 0x20, 0x61, 0x68, 0x68, 0xE0, 0x60, 0xE8, 0x68, ++0xA0, 0x61, 0xE0, 0x1B, 0xC0, 0x10, 0x03, 0xFB, 0x00, 0xF3, 0xDB, 0xB2, 0x68, 0x7E, 0x84, 0xF8, 0x22, 0x00, 0x33, 0x70, ++0x4F, 0xF4, 0x80, 0x70, 0x84, 0xF8, 0x23, 0x30, 0x0E, 0xF0, 0xC6, 0xFB, 0x62, 0x48, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x08, 0x03, 0x4F, 0xF4, 0xC8, 0x31, 0x93, 0xF8, 0xC0, 0x24, 0xA1, 0x60, 0x22, 0xB1, 0x93, 0xF8, 0xC2, 0x24, 0x01, 0x32, ++0x83, 0xF8, 0xC2, 0x24, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xF8, 0xE8, 0x11, 0x04, 0xF5, 0xF4, 0x72, 0x23, 0x46, 0x04, 0xF5, ++0xFD, 0x75, 0x22, 0xF8, 0x02, 0x1F, 0xAA, 0x42, 0xFB, 0xD1, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x08, 0xF8, 0x00, 0xEB, ++0x08, 0x05, 0x00, 0x22, 0x31, 0x78, 0x84, 0xF8, 0x30, 0x20, 0xD5, 0xF8, 0xB0, 0x54, 0x4F, 0x4A, 0x02, 0xEB, 0x81, 0x12, ++0x29, 0x07, 0xC4, 0xF8, 0x48, 0x21, 0x4D, 0x49, 0x56, 0xBF, 0x08, 0xF5, 0x95, 0x62, 0x04, 0xF1, 0xB0, 0x02, 0x12, 0x18, ++0xC4, 0xF8, 0xB4, 0x20, 0x0A, 0x69, 0xA2, 0xF5, 0x74, 0x22, 0xA2, 0xF5, 0x10, 0x72, 0x04, 0xF1, 0x48, 0x01, 0xC3, 0xF8, ++0xA0, 0x21, 0x08, 0x33, 0x8B, 0x42, 0xFA, 0xD1, 0xEA, 0x06, 0x03, 0xD5, 0x63, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x63, 0x60, ++0x08, 0xF1, 0xE4, 0x08, 0x40, 0x44, 0x21, 0x46, 0x0D, 0xF0, 0x4C, 0xF9, 0x3D, 0x4B, 0xC4, 0xF8, 0x04, 0x32, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x3A, 0x4B, 0xE0, 0x6A, 0x1A, 0x68, ++0x01, 0x25, 0x51, 0x19, 0x19, 0x60, 0x84, 0xF8, 0x25, 0x50, 0x08, 0xB1, 0x80, 0xF8, 0x25, 0x50, 0x21, 0xB1, 0x33, 0x49, ++0x1A, 0x60, 0x0B, 0x68, 0x00, 0x2A, 0x42, 0xD0, 0xF6, 0xB2, 0x0D, 0x2E, 0x07, 0xD8, 0x4F, 0xF4, 0x1E, 0x73, 0x2C, 0x4A, ++0x06, 0xFB, 0x03, 0x76, 0x13, 0x69, 0xC6, 0xF8, 0x58, 0x32, 0x00, 0x20, 0x84, 0xF8, 0x5C, 0x02, 0xBD, 0xE8, 0xF0, 0x81, ++0x1F, 0x48, 0x0D, 0xF0, 0x61, 0xF9, 0x00, 0x28, 0x34, 0xD0, 0x2A, 0x46, 0xE0, 0x62, 0xC4, 0x62, 0xA9, 0x7F, 0x52, 0xF8, ++0x12, 0x3F, 0x95, 0xF8, 0x1D, 0xC0, 0xC0, 0xF8, 0x26, 0x30, 0x01, 0x23, 0x8B, 0x40, 0x91, 0x88, 0x41, 0x85, 0x01, 0x3B, ++0x41, 0x8D, 0x16, 0x4F, 0x1B, 0x02, 0x1B, 0xB2, 0x21, 0xEA, 0x03, 0x01, 0x09, 0xB2, 0x41, 0x85, 0xB5, 0xF8, 0x16, 0xE0, ++0xAE, 0xEB, 0x0C, 0x2C, 0x03, 0xEA, 0x0C, 0x03, 0xA0, 0xEB, 0x07, 0x0E, 0xDF, 0xF8, 0x3C, 0xC0, 0x4F, 0xEA, 0xEE, 0x0E, ++0x0B, 0x43, 0x0C, 0xFB, 0x0E, 0xF1, 0x4F, 0xF0, 0xFF, 0x0C, 0x43, 0x85, 0x80, 0xF8, 0x23, 0x10, 0xA0, 0xF8, 0x20, 0xC0, ++0x2A, 0xE7, 0x00, 0x2B, 0xBA, 0xD0, 0x62, 0xB6, 0xB8, 0xE7, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x48, 0x21, 0x46, ++0x0D, 0xF0, 0xE2, 0xF8, 0x01, 0x20, 0xBD, 0xE7, 0xF8, 0x87, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xAF, 0x16, 0x37, 0x61, ++0xEC, 0x97, 0x15, 0x00, 0xDC, 0x97, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x04, 0x39, 0x18, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x0F, 0xCC, 0xFF, 0xFF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x33, 0x4F, 0xDF, 0xF8, ++0xE4, 0x80, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x74, 0x4F, 0xF4, 0xA4, 0x63, 0x94, 0xF8, 0x22, 0x60, 0x03, 0xFB, ++0x06, 0x83, 0x05, 0x46, 0x93, 0xF8, 0xC0, 0x24, 0x22, 0xB1, 0x93, 0xF8, 0xC2, 0x24, 0x01, 0x3A, 0x83, 0xF8, 0xC2, 0x24, ++0x29, 0x4A, 0x2A, 0x49, 0x2B, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0E, 0xF0, 0xD5, 0xFA, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, ++0x06, 0x80, 0xE4, 0x30, 0x21, 0x46, 0x0D, 0xF0, 0xF3, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x21, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x21, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x73, 0x11, 0x68, 0xD8, 0x6A, ++0x4E, 0x1C, 0x4F, 0xF0, 0x00, 0x0C, 0x16, 0x60, 0x83, 0xF8, 0x25, 0xC0, 0xD8, 0xB1, 0x80, 0xF8, 0x25, 0xC0, 0x96, 0xB9, ++0xFF, 0xF7, 0xE4, 0xFD, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x75, 0x16, 0x48, 0xE9, 0x6A, 0x0D, 0xF0, 0x80, 0xF8, ++0x20, 0x46, 0xFF, 0xF7, 0xD9, 0xFD, 0x21, 0x46, 0x12, 0x48, 0xBD, 0xE8, 0xF0, 0x41, 0x0D, 0xF0, 0x77, 0xB8, 0x0E, 0x48, ++0x11, 0x60, 0x02, 0x68, 0x41, 0xB1, 0xD8, 0x6A, 0xE6, 0xE7, 0x00, 0x2E, 0xEE, 0xD0, 0x0A, 0x4B, 0x11, 0x60, 0x1A, 0x68, ++0x00, 0x29, 0xE9, 0xD1, 0x02, 0xB1, 0x62, 0xB6, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x73, 0xD8, 0x6A, 0x00, 0x28, ++0xE0, 0xD0, 0xD5, 0xE7, 0x68, 0x65, 0x17, 0x00, 0x00, 0x98, 0x15, 0x00, 0xDC, 0x97, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xF8, 0x87, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x44, 0x78, 0xDF, 0xF8, ++0x14, 0x81, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0xF6, 0x08, 0xEB, 0x06, 0x07, 0x38, 0x36, 0x87, 0xF8, 0x9A, 0x10, ++0x90, 0xF8, 0x28, 0x30, 0x87, 0xF8, 0x98, 0x30, 0x03, 0x78, 0x87, 0xF8, 0x99, 0x30, 0x46, 0x44, 0x05, 0x46, 0x48, 0x22, ++0x30, 0x46, 0x00, 0x21, 0x97, 0xF8, 0x22, 0x90, 0xE9, 0xF7, 0xA0, 0xFF, 0x97, 0xF8, 0x98, 0x30, 0x04, 0x2B, 0x55, 0xD8, ++0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x3F, 0x54, 0x03, 0x27, 0x00, 0x21, 0xF0, 0x29, 0xF8, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x04, 0x83, 0x03, 0xF1, 0x80, 0x02, 0x20, 0xF0, 0x7F, 0x40, 0xC3, 0xF8, 0x80, 0x00, 0x00, 0x23, 0x53, 0x60, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, 0x01, 0x22, 0xD5, 0xE9, 0x02, 0x40, 0x29, 0x69, 0x83, 0xF8, 0x9B, 0x20, 0x6A, 0x69, ++0xC3, 0xF8, 0xB0, 0x60, 0xC3, 0xE9, 0x27, 0x40, 0xC3, 0xE9, 0x29, 0x12, 0x2A, 0x79, 0x83, 0xF8, 0xAC, 0x20, 0xBD, 0xE8, ++0xF8, 0x83, 0x20, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x39, 0x19, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x99, 0xF8, ++0x62, 0x00, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x04, 0x81, 0x02, 0x28, 0xC1, 0xE9, 0x20, 0x23, 0xD7, 0xD1, 0x15, 0xA3, ++0xD3, 0xE9, 0x00, 0x23, 0xC1, 0xE9, 0x20, 0x23, 0xD1, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, 0xAA, 0x69, ++0xC3, 0xF8, 0x88, 0x20, 0xEA, 0x69, 0xC3, 0xF8, 0x8C, 0x20, 0x2A, 0x6A, 0xC3, 0xF8, 0x90, 0x20, 0x00, 0x20, 0x6A, 0x6A, ++0xC3, 0xF8, 0x94, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x20, 0x01, 0xBC, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, ++0x00, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x20, 0x01, 0xB3, 0xE7, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, 0x36, 0x5C, 0x36, 0x5C, ++0x36, 0x5C, 0x36, 0x5C, 0x37, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x23, 0x01, 0x22, 0x80, 0xF8, 0x30, 0x20, 0x80, 0xF8, 0x9B, 0x30, 0xC0, 0xF8, 0xB0, 0x30, 0x70, 0x47, 0x00, 0xBF, ++0x2D, 0xE9, 0xF0, 0x47, 0xD1, 0xF8, 0xFC, 0xA1, 0x82, 0xB0, 0xBA, 0xF1, 0x00, 0x0F, 0x32, 0xD0, 0x00, 0x24, 0xDF, 0xF8, ++0x6C, 0x80, 0x0D, 0x46, 0x06, 0x46, 0x91, 0x46, 0x27, 0x46, 0x10, 0xE0, 0x80, 0xF8, 0x5D, 0x70, 0xD8, 0xF8, 0x98, 0x33, ++0xC1, 0x7E, 0x01, 0x34, 0x98, 0x47, 0xB9, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x4C, 0x45, 0x1F, 0xD0, 0xD5, 0xF8, 0xFC, 0xA1, ++0xBA, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x30, 0x46, 0x01, 0x97, 0xF8, 0xF7, 0x6B, 0xFA, 0x03, 0x46, 0x50, 0x46, 0x9B, 0xB1, ++0x15, 0xF0, 0x34, 0xFC, 0x03, 0x46, 0x01, 0xAA, 0x29, 0x46, 0x30, 0x46, 0x63, 0xB1, 0xD8, 0xF8, 0x10, 0x30, 0x98, 0x47, ++0x01, 0x9B, 0x3B, 0xB9, 0x00, 0x28, 0xD9, 0xD1, 0x05, 0xF5, 0xFE, 0x70, 0x0C, 0xF0, 0xC2, 0xFF, 0xD4, 0xE7, 0x54, 0x46, ++0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x88, 0x1A, 0x17, 0x00, 0x0A, 0x4B, 0x9B, 0x68, 0x93, 0xF8, 0x62, 0x20, ++0x7A, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x62, 0xB1, 0x93, 0xF8, 0x6D, 0x20, 0x4A, 0xB1, 0x93, 0xF8, 0x6E, 0x20, 0x08, 0x2A, ++0x05, 0xD8, 0x01, 0x23, 0x93, 0x40, 0x01, 0x3B, 0x02, 0x4A, 0x1B, 0x02, 0x13, 0x60, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, ++0x2C, 0x00, 0x32, 0x40, 0x10, 0xB5, 0x90, 0xF8, 0xC0, 0x34, 0x04, 0x46, 0x00, 0x2B, 0x2D, 0xD1, 0x23, 0x6C, 0x1B, 0xB1, ++0x1B, 0x4B, 0x20, 0x46, 0x1B, 0x6B, 0x98, 0x47, 0x63, 0x68, 0xD8, 0x07, 0x1A, 0xD5, 0x19, 0x4A, 0x11, 0x68, 0x89, 0x01, ++0x17, 0xD5, 0x23, 0xF0, 0x01, 0x03, 0x63, 0x60, 0x16, 0x4A, 0x41, 0xF2, 0x14, 0x33, 0xD3, 0x5C, 0x01, 0x2B, 0x41, 0xF2, ++0x13, 0x33, 0x8C, 0xBF, 0x01, 0x21, 0x00, 0x21, 0xD1, 0x54, 0x12, 0x4B, 0x93, 0xF8, 0xB6, 0x30, 0x23, 0xB1, 0x11, 0x4B, ++0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x0C, 0xD0, 0x10, 0xBD, 0x12, 0x68, 0x92, 0x01, 0xFB, 0xD4, 0x0D, 0x4A, 0x92, 0xF8, ++0x24, 0x20, 0x00, 0x2A, 0xF6, 0xD0, 0xDE, 0xE7, 0x0A, 0xF0, 0x34, 0xF8, 0xCE, 0xE7, 0xF8, 0xF7, 0x1D, 0xFD, 0x09, 0x4A, ++0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, ++0x00, 0x40, 0x1E, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, ++0x19, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x18, 0x22, 0x80, 0x46, 0x00, 0x21, 0xE9, 0xF7, 0x72, 0xFE, 0x40, 0x46, 0x0C, 0xF0, ++0xFF, 0xFE, 0x08, 0xF1, 0x08, 0x00, 0x14, 0x4C, 0x14, 0x4F, 0x0C, 0xF0, 0xF9, 0xFE, 0x04, 0xF5, 0xA4, 0x56, 0x45, 0x46, ++0x4F, 0xF4, 0xA4, 0x62, 0x00, 0x21, 0x20, 0x46, 0xE9, 0xF7, 0x60, 0xFE, 0x7F, 0x23, 0xD7, 0xF8, 0x50, 0x24, 0x24, 0x63, ++0x05, 0x21, 0x84, 0xF8, 0x62, 0x10, 0x84, 0xF8, 0x65, 0x30, 0x84, 0xF8, 0x66, 0x30, 0xE2, 0x62, 0x21, 0x46, 0x28, 0x46, ++0x04, 0xF5, 0xA4, 0x64, 0x0C, 0xF0, 0xE2, 0xFE, 0xB4, 0x42, 0xE5, 0xD1, 0xFF, 0x23, 0x88, 0xF8, 0x10, 0x30, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x06, 0x4B, ++0x9C, 0x68, 0x3C, 0xB1, 0x05, 0x4D, 0xD5, 0xF8, 0x5C, 0x34, 0x20, 0x46, 0x98, 0x47, 0x24, 0x68, 0x00, 0x2C, 0xF8, 0xD1, ++0x38, 0xBD, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAC, 0x4D, 0x8D, 0xB0, ++0x2C, 0x68, 0x05, 0x90, 0x88, 0x46, 0x17, 0x46, 0x04, 0x93, 0x00, 0x2C, 0x00, 0xF0, 0xA4, 0x80, 0x00, 0x2A, 0x40, 0xF0, ++0x9E, 0x80, 0xAC, 0x68, 0x00, 0x2C, 0x00, 0xF0, 0x42, 0x81, 0x05, 0x9B, 0xA4, 0x48, 0x1A, 0x68, 0x9B, 0x88, 0x06, 0x92, ++0x4F, 0xF0, 0x00, 0x09, 0x07, 0x93, 0xCB, 0x46, 0xBA, 0x46, 0xE7, 0x6D, 0xB4, 0xF8, 0x60, 0x60, 0x94, 0xF8, 0xC0, 0x34, ++0x39, 0x46, 0x32, 0x46, 0x0E, 0xF0, 0x76, 0xF8, 0x94, 0xF8, 0xC0, 0x34, 0x9A, 0x48, 0x1B, 0xB9, 0x8B, 0xEA, 0x07, 0x0B, ++0x89, 0xEA, 0x06, 0x09, 0x24, 0x68, 0x00, 0x2C, 0xEB, 0xD1, 0x57, 0x46, 0x00, 0x2F, 0x00, 0xF0, 0x99, 0x80, 0x95, 0x4B, ++0x95, 0x48, 0x49, 0xF4, 0x40, 0x74, 0xDD, 0xE9, 0x06, 0x12, 0x1C, 0x60, 0xC0, 0xF8, 0x00, 0xB0, 0x5B, 0x46, 0xCD, 0xE9, ++0x00, 0x97, 0x91, 0x48, 0x0E, 0xF0, 0x58, 0xF8, 0x8B, 0x48, 0x0C, 0xF0, 0xBF, 0xFE, 0x05, 0x99, 0x8E, 0x4A, 0x80, 0xF8, ++0x62, 0x80, 0x04, 0x46, 0x8D, 0x4B, 0x82, 0x1A, 0x08, 0x68, 0xE0, 0x65, 0x52, 0x11, 0x89, 0x88, 0xA4, 0xF8, 0x60, 0x10, ++0x03, 0xFB, 0x02, 0xF2, 0xD3, 0xB2, 0x40, 0xF6, 0x47, 0x21, 0x40, 0xF6, 0x43, 0x22, 0xA1, 0x60, 0xE2, 0x60, 0x86, 0x49, ++0x86, 0x4A, 0x21, 0x61, 0x62, 0x61, 0x40, 0xF2, 0xFF, 0x31, 0x00, 0x22, 0x84, 0xF8, 0xC0, 0x74, 0xA4, 0xF8, 0xBE, 0x14, ++0x84, 0xF8, 0x63, 0x30, 0x84, 0xF8, 0x4C, 0x30, 0x22, 0x64, 0x84, 0xF8, 0x84, 0x20, 0x17, 0xB1, 0xEA, 0x7C, 0x01, 0x32, ++0xEA, 0x74, 0xB8, 0xF1, 0x02, 0x0F, 0x00, 0xF0, 0x89, 0x80, 0xB8, 0xF1, 0x04, 0x0F, 0x00, 0xF0, 0xC3, 0x80, 0xB8, 0xF1, ++0x00, 0x0F, 0x00, 0xF0, 0x9C, 0x80, 0x6B, 0x7C, 0xAA, 0x7C, 0x13, 0x44, 0x01, 0x2B, 0x78, 0xDD, 0x74, 0x48, 0x75, 0x4E, ++0xD0, 0xE9, 0x00, 0x12, 0x42, 0xF4, 0x80, 0x72, 0x11, 0x43, 0x42, 0x60, 0x31, 0x60, 0x01, 0x2B, 0x4D, 0xD0, 0x00, 0x2F, ++0x52, 0xD1, 0x04, 0x9A, 0x94, 0xF8, 0x63, 0x30, 0x6E, 0x48, 0x13, 0x70, 0x21, 0x46, 0x0C, 0xF0, 0x29, 0xFE, 0x04, 0xF5, ++0x99, 0x66, 0x04, 0xF5, 0x9E, 0x69, 0x30, 0x46, 0x0C, 0xF0, 0x1E, 0xFE, 0x06, 0xF1, 0x28, 0x00, 0x08, 0x36, 0x0C, 0xF0, ++0x19, 0xFE, 0x4E, 0x45, 0xF5, 0xD1, 0x04, 0xF5, 0xA3, 0x60, 0x0C, 0xF0, 0x13, 0xFE, 0x00, 0x24, 0x03, 0xE0, 0x63, 0x4B, ++0x1B, 0x78, 0x23, 0xB3, 0x01, 0x24, 0xAA, 0x7C, 0x6B, 0x7C, 0x61, 0x49, 0x13, 0x44, 0x00, 0x20, 0x01, 0x2B, 0x08, 0x60, ++0x04, 0xDC, 0xFF, 0xF7, 0x91, 0xFE, 0xAA, 0x7C, 0x6B, 0x7C, 0x13, 0x44, 0x04, 0x99, 0x09, 0x78, 0x4F, 0xF4, 0x80, 0x70, ++0xCD, 0xE9, 0x02, 0x71, 0xCD, 0xE9, 0x00, 0x28, 0x58, 0x49, 0x59, 0x4A, 0x0E, 0xF0, 0x22, 0xF8, 0x20, 0x46, 0x0D, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x9B, 0x8B, 0xEA, 0x03, 0x0B, 0x07, 0x9B, 0x89, 0xEA, 0x03, 0x09, 0x5F, 0xE7, 0xAC, 0x68, ++0x00, 0x2C, 0x7C, 0xD0, 0xEB, 0x7C, 0x02, 0x2B, 0x7F, 0xF4, 0x37, 0xAF, 0xD2, 0xE7, 0x4F, 0x4A, 0x13, 0x68, 0x43, 0xF0, ++0x01, 0x03, 0x13, 0x60, 0x00, 0x2F, 0xAC, 0xD0, 0xB8, 0xF1, 0x00, 0x01, 0x18, 0xBF, 0x01, 0x21, 0x94, 0xF8, 0x63, 0x00, ++0x09, 0xF0, 0x22, 0xFD, 0x48, 0x4B, 0x84, 0xF8, 0xC1, 0x04, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x9C, 0xDA, ++0xFF, 0x28, 0x9A, 0xD1, 0x44, 0x49, 0x45, 0x48, 0x40, 0xF2, 0x0B, 0x22, 0x0E, 0xF0, 0x1A, 0xFA, 0x93, 0xE7, 0x00, 0x2A, ++0x8D, 0xD0, 0x83, 0xE7, 0xAA, 0x7C, 0x00, 0x2A, 0x00, 0xF0, 0xA8, 0x80, 0x39, 0x46, 0x3F, 0x48, 0x0A, 0x33, 0x4F, 0xF4, ++0x1E, 0x76, 0x06, 0xFB, 0x03, 0x03, 0x01, 0x32, 0x01, 0x20, 0xAA, 0x74, 0x83, 0xF8, 0x25, 0x00, 0x11, 0xB1, 0x3A, 0x4B, ++0xC4, 0xE9, 0x07, 0x34, 0x39, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x80, 0x31, 0x98, 0x47, 0x6B, 0x7C, 0x64, 0xE7, 0x36, 0x4B, ++0x36, 0x49, 0xD3, 0xF8, 0xCC, 0x31, 0xE3, 0x61, 0xFF, 0x23, 0x84, 0xF8, 0x6C, 0x30, 0x34, 0x4A, 0x6B, 0x7C, 0x24, 0x62, ++0xA4, 0xF8, 0x8A, 0x80, 0xC4, 0xF8, 0xB8, 0x40, 0xC4, 0xF8, 0xB4, 0x10, 0x01, 0x33, 0x92, 0xF8, 0x04, 0x21, 0xDB, 0xB2, ++0x6B, 0x74, 0x00, 0x2A, 0x3F, 0xF4, 0x4C, 0xAF, 0x2C, 0x4A, 0xC4, 0xF8, 0xA4, 0x40, 0xC4, 0xE9, 0x24, 0x88, 0xC4, 0xF8, ++0x98, 0x80, 0xC4, 0xF8, 0xA0, 0x20, 0x41, 0xE7, 0x2A, 0x7C, 0xFF, 0x2A, 0x17, 0xD1, 0xAA, 0x68, 0x2B, 0x74, 0x00, 0x2A, ++0x4C, 0xD0, 0x14, 0x49, 0x24, 0x4B, 0x4E, 0x68, 0x12, 0x6C, 0x13, 0x48, 0x0B, 0x60, 0x33, 0x43, 0x03, 0x60, 0x00, 0x2A, ++0x3F, 0xF4, 0x2F, 0xAF, 0x1B, 0x4B, 0x10, 0x7E, 0x1B, 0x6D, 0x98, 0x47, 0x29, 0xE7, 0x05, 0x98, 0x01, 0xF0, 0x4E, 0xFE, ++0xEA, 0xE6, 0x01, 0x24, 0x6E, 0xE7, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x14, 0x98, 0x15, 0x00, 0x1C, 0x00, 0x32, 0x40, ++0x18, 0x00, 0x32, 0x40, 0x2C, 0x98, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x19, 0x9C, 0x8F, 0xC1, 0x32, 0xE4, 0x05, 0x00, ++0x22, 0xF3, 0x02, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0x08, 0x88, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, ++0x2C, 0x00, 0x32, 0x40, 0x74, 0x98, 0x15, 0x00, 0xC8, 0x98, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x50, 0x98, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0xB1, 0x7F, 0x13, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xD5, 0x65, 0x12, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x81, 0x66, 0x12, 0x00, 0xDC, 0xFF, 0xFF, 0x7F, 0x10, 0x4E, 0x11, 0x4A, ++0x09, 0x92, 0x40, 0xF6, 0x85, 0x12, 0xD6, 0xF8, 0xE8, 0x30, 0x0A, 0x92, 0x98, 0x47, 0x73, 0x6C, 0x0D, 0xF1, 0x23, 0x01, ++0x09, 0xA8, 0x98, 0x47, 0x00, 0x28, 0xB6, 0xD1, 0x63, 0x68, 0x32, 0x6D, 0x9D, 0xF8, 0x23, 0x00, 0x43, 0xF0, 0x80, 0x03, ++0x63, 0x60, 0x90, 0x47, 0x6B, 0x7C, 0xD3, 0xE6, 0x01, 0xF0, 0x32, 0xFE, 0xAA, 0x7C, 0x94, 0xF8, 0x63, 0x30, 0x94, 0xF8, ++0xC0, 0x14, 0x50, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x00, 0x85, 0x09, 0x2D, 0xE9, 0xF0, 0x4F, 0x02, 0x46, 0x6A, 0x4D, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xF3, 0x8B, 0xB0, 0xEF, 0x18, 0x04, 0x90, 0x39, 0x46, 0x66, 0x48, 0x06, 0x93, ++0x0C, 0xF0, 0x4A, 0xFD, 0x97, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xDD, 0x80, 0x04, 0x2B, 0x00, 0xF0, 0x98, 0x80, ++0xDF, 0xF8, 0x98, 0xA1, 0x60, 0x4C, 0x00, 0x2B, 0x00, 0xF0, 0x89, 0x80, 0x9A, 0xF8, 0x12, 0x30, 0x9A, 0xF8, 0x11, 0x20, ++0x1A, 0x44, 0x01, 0x2A, 0x5E, 0xD0, 0x0A, 0xB9, 0x5B, 0x4B, 0x1A, 0x60, 0x06, 0x9E, 0xD4, 0xF8, 0xD8, 0x31, 0x06, 0xF1, ++0x18, 0x00, 0x28, 0x44, 0x98, 0x47, 0x06, 0xF1, 0x28, 0x00, 0xD4, 0xF8, 0xD8, 0x31, 0x28, 0x44, 0x98, 0x47, 0x04, 0x9A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0x93, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0x3A, 0xD1, 0x04, 0x9A, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0x05, 0x26, 0x93, 0xF8, 0x63, 0x00, 0x0A, 0xF0, 0x02, 0xFA, 0x4B, 0x4B, 0x1A, 0x69, ++0xBA, 0x42, 0x04, 0xBF, 0x00, 0x22, 0x1A, 0x61, 0x00, 0x21, 0x4F, 0xF4, 0xA4, 0x62, 0x38, 0x46, 0xE9, 0xF7, 0x22, 0xFC, ++0x04, 0x99, 0x9A, 0xF8, 0x11, 0x20, 0x9A, 0xF8, 0x12, 0x30, 0xD4, 0xF8, 0x50, 0xC4, 0x01, 0x91, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x01, 0x55, 0x7F, 0x24, 0x00, 0x93, 0x3F, 0x49, 0xC5, 0xF8, 0x2C, 0xC0, 0x13, 0x44, 0x4F, 0xF4, 0x80, 0x70, ++0x3D, 0x4A, 0x2F, 0x63, 0x85, 0xF8, 0x62, 0x60, 0x85, 0xF8, 0x65, 0x40, 0x85, 0xF8, 0x66, 0x40, 0x0D, 0xF0, 0xC2, 0xFE, ++0x39, 0x48, 0x39, 0x46, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x0C, 0xF0, 0x91, 0xBC, 0x93, 0xF8, 0xC1, 0x04, 0x01, 0x21, ++0x09, 0xF0, 0x2E, 0xFC, 0x9A, 0xF8, 0x13, 0x30, 0x01, 0x3B, 0x8A, 0xF8, 0x13, 0x30, 0xB9, 0xE7, 0x31, 0x4A, 0xDA, 0xF8, ++0x08, 0x60, 0xDF, 0xF8, 0xC8, 0xE0, 0xDF, 0xF8, 0xC8, 0x90, 0xDF, 0xF8, 0xC8, 0x80, 0xD2, 0xE9, 0x00, 0x01, 0x21, 0xF0, ++0x10, 0x0C, 0x4C, 0xEA, 0x00, 0x00, 0xC2, 0xF8, 0x04, 0xC0, 0xCE, 0xF8, 0x00, 0x00, 0xB0, 0x6B, 0xB6, 0x8F, 0xC9, 0xF8, ++0x00, 0x00, 0xC8, 0xF8, 0x00, 0x60, 0x00, 0x2B, 0x88, 0xD1, 0x13, 0x68, 0x21, 0xF4, 0x88, 0x71, 0x0B, 0x43, 0x51, 0x60, ++0xCE, 0xF8, 0x00, 0x30, 0x80, 0xE7, 0x9A, 0xF8, 0x11, 0x20, 0x9A, 0xF8, 0x12, 0x30, 0x01, 0x3A, 0xD2, 0xB2, 0x8A, 0xF8, ++0x11, 0x20, 0x71, 0xE7, 0xEA, 0xF7, 0x50, 0xFC, 0x00, 0x28, 0x40, 0xF0, 0x28, 0x81, 0xDF, 0xF8, 0x60, 0xA0, 0x12, 0x4C, ++0x9A, 0xF8, 0x10, 0x00, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x53, 0x5A, 0x68, 0x19, 0x6C, 0x22, 0xF0, 0x80, 0x02, ++0x5A, 0x60, 0x09, 0xB1, 0x63, 0x6D, 0x98, 0x47, 0x9A, 0xF8, 0x12, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x0D, 0x81, 0x0E, 0x48, ++0x0E, 0x49, 0x42, 0x68, 0x0E, 0x4E, 0x01, 0x60, 0x0A, 0x43, 0x32, 0x60, 0xFF, 0x21, 0x9A, 0xF8, 0x11, 0x20, 0x8A, 0xF8, ++0x10, 0x10, 0x49, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x08, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, ++0x94, 0x64, 0x17, 0x00, 0xB8, 0x98, 0x15, 0x00, 0xDC, 0x98, 0x15, 0x00, 0x00, 0x88, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x8C, 0x84, 0x03, 0x35, 0x60, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x04, 0x9E, 0xDF, 0xF8, ++0x28, 0xA2, 0x7F, 0x49, 0x9A, 0xF8, 0x12, 0x20, 0x7E, 0x4C, 0xDF, 0xF8, 0x20, 0xB2, 0x06, 0xF1, 0x0A, 0x08, 0x08, 0xEB, ++0x88, 0x03, 0x4F, 0xF4, 0x1E, 0x70, 0xC8, 0xEB, 0x03, 0x13, 0x4F, 0xF0, 0xA4, 0x0C, 0x00, 0xFB, 0x08, 0x18, 0x46, 0x33, ++0x9E, 0x20, 0xCD, 0xE9, 0x08, 0x7A, 0x1C, 0xFB, 0x06, 0x06, 0x01, 0x3A, 0x00, 0x20, 0x01, 0xEB, 0xC3, 0x03, 0x03, 0x93, ++0x8A, 0xF8, 0x12, 0x20, 0x88, 0xF8, 0x25, 0x00, 0x05, 0x90, 0x05, 0xEB, 0xC6, 0x06, 0xB9, 0x46, 0xD8, 0xF8, 0x08, 0x32, ++0x9D, 0xF8, 0x14, 0x70, 0x3B, 0xB1, 0x03, 0x99, 0xD4, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x28, 0x39, 0x38, 0x46, ++0x98, 0x47, 0xD8, 0xF8, 0x30, 0x32, 0x33, 0xB1, 0xD4, 0xF8, 0x84, 0x33, 0x03, 0x99, 0x4F, 0xF0, 0x80, 0x42, 0x38, 0x46, ++0x98, 0x47, 0xD9, 0xF8, 0xF0, 0x34, 0x00, 0x2B, 0x00, 0xF0, 0x93, 0x80, 0x30, 0x46, 0x0C, 0xF0, 0x55, 0xFC, 0xA6, 0xF1, ++0x28, 0x0A, 0x07, 0x90, 0x50, 0x46, 0x0C, 0xF0, 0x4F, 0xFC, 0x07, 0x99, 0x02, 0x46, 0x5B, 0x48, 0x0D, 0xF0, 0xA0, 0xFD, ++0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x58, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xDB, 0xF8, 0x00, 0x20, ++0xD4, 0xF8, 0x84, 0x33, 0x01, 0x32, 0xCB, 0xF8, 0x00, 0x20, 0x31, 0x46, 0x4F, 0xF0, 0x80, 0x42, 0x38, 0x46, 0x98, 0x47, ++0xD4, 0xF8, 0x84, 0x33, 0x51, 0x46, 0x38, 0x46, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, ++0x4B, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x00, 0x2A, 0x66, 0xD1, 0x05, 0x9B, 0x03, 0x9A, ++0x01, 0x33, 0x08, 0x32, 0x05, 0x2B, 0x05, 0x93, 0x08, 0xF1, 0x08, 0x08, 0x06, 0xF1, 0x08, 0x06, 0x09, 0xF1, 0x08, 0x09, ++0x03, 0x92, 0xA1, 0xD1, 0x04, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0xDD, 0xE9, 0x08, 0x7A, 0xD3, 0xF8, ++0x18, 0x35, 0x00, 0x2B, 0x4F, 0xD0, 0x06, 0x9B, 0x03, 0xF5, 0xA3, 0x66, 0x2E, 0x44, 0x30, 0x46, 0x0C, 0xF0, 0x04, 0xFC, ++0x01, 0x46, 0x38, 0x48, 0x0D, 0xF0, 0x56, 0xFD, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x33, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xDB, 0xF8, 0x00, 0x20, 0xD4, 0xF8, 0x84, 0x33, 0x01, 0x32, 0xCB, 0xF8, 0x00, 0x20, 0x31, 0x46, ++0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x2A, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x00, 0x2A, 0x43, 0xD1, 0x9A, 0xF8, 0x12, 0x20, 0x00, 0x2A, 0x3C, 0xD0, 0x9A, 0xF8, ++0x11, 0x30, 0x13, 0x44, 0x01, 0x2B, 0x7F, 0xF4, 0x71, 0xAE, 0x23, 0x49, 0xDA, 0xF8, 0x08, 0x00, 0x22, 0x4E, 0xD1, 0xE9, ++0x00, 0x23, 0x23, 0xF0, 0x10, 0x03, 0x4B, 0x60, 0x1A, 0x43, 0x20, 0x49, 0x20, 0x4B, 0x32, 0x60, 0x86, 0x6B, 0x82, 0x8F, ++0x0E, 0x60, 0x1A, 0x60, 0x5E, 0xE6, 0xD9, 0xF8, 0xC8, 0x34, 0x00, 0x2B, 0x7F, 0xF4, 0x68, 0xAF, 0xA6, 0xF1, 0x28, 0x0A, ++0x72, 0xE7, 0x62, 0xB6, 0x96, 0xE7, 0x06, 0x9B, 0x03, 0xF5, 0xA3, 0x66, 0x2E, 0x44, 0xB5, 0xE7, 0x01, 0xF0, 0x4E, 0xFC, ++0x9A, 0xF8, 0x12, 0x30, 0xF4, 0xE6, 0x00, 0x20, 0xEA, 0xF7, 0x2C, 0xFB, 0x12, 0x4B, 0x1A, 0x68, 0xD2, 0x05, 0x7F, 0xF5, ++0xD0, 0xAE, 0x4F, 0xF4, 0x80, 0x72, 0xC3, 0xF8, 0x80, 0x20, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0xC6, 0xE6, ++0x01, 0xF0, 0x5E, 0xFC, 0x2C, 0xE6, 0x62, 0xB6, 0xB9, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x88, 0x98, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0xA0, 0x98, 0x15, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, ++0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0x88, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x2E, 0x78, 0x95, 0xF8, 0x29, 0x80, 0x4F, 0x4C, 0x00, 0xFB, ++0x08, 0xF0, 0xC6, 0xEB, 0x06, 0x17, 0x00, 0xEB, 0xC7, 0x07, 0x27, 0x44, 0x4F, 0xF0, 0x78, 0x0A, 0x1A, 0xFB, 0x06, 0x0A, ++0x87, 0xF8, 0x3A, 0x12, 0x0A, 0xF5, 0xEC, 0x79, 0x95, 0xF8, 0x28, 0x30, 0x87, 0xF8, 0x38, 0x32, 0xA1, 0x44, 0x87, 0xF8, ++0x39, 0x62, 0x48, 0x46, 0x48, 0x22, 0x00, 0x21, 0xE9, 0xF7, 0x46, 0xFA, 0x97, 0xF8, 0x38, 0x32, 0x37, 0x01, 0x05, 0x2B, ++0x0C, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x41, 0x51, 0x0B, 0x41, 0x6A, 0x03, 0x0A, 0xF5, 0x0A, 0x70, 0x20, 0x44, 0x10, 0x22, ++0x05, 0xF1, 0x08, 0x01, 0x20, 0xF0, 0xC2, 0xF9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, 0xBA, 0x1B, 0x03, 0xEB, ++0xC2, 0x03, 0x23, 0x44, 0x00, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x88, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, ++0xBA, 0x1B, 0x03, 0xEB, 0xC2, 0x02, 0x22, 0x44, 0x23, 0x44, 0x92, 0xF8, 0x38, 0x12, 0x05, 0x29, 0x4F, 0xF0, 0x01, 0x00, ++0x0C, 0xBF, 0xC3, 0xF8, 0xAC, 0x94, 0xC3, 0xF8, 0xA8, 0x94, 0x4F, 0xF4, 0xA4, 0x63, 0x82, 0xF8, 0x3B, 0x02, 0x03, 0xFB, ++0x08, 0xF8, 0xD5, 0xE9, 0x02, 0x01, 0xD5, 0xE9, 0x04, 0x23, 0xBF, 0x1B, 0x08, 0xEB, 0xC7, 0x07, 0x3C, 0x44, 0xC4, 0xE9, ++0x8F, 0x01, 0xC4, 0xE9, 0x91, 0x23, 0x2B, 0x79, 0x84, 0xF8, 0x4C, 0x32, 0xBD, 0xE8, 0xF0, 0x87, 0x20, 0xF0, 0x90, 0xFA, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, 0xBA, 0x1B, 0x03, 0xEB, 0xC2, 0x03, 0x23, 0x44, 0x20, 0xF0, 0x7F, 0x40, ++0x00, 0x21, 0xC3, 0xE9, 0x88, 0x01, 0xC5, 0xE7, 0x4F, 0xF4, 0xA4, 0x60, 0xBB, 0x1B, 0x00, 0xFB, 0x08, 0xF0, 0x00, 0xEB, ++0xC3, 0x00, 0x20, 0x44, 0xA9, 0x69, 0xC0, 0xF8, 0x28, 0x12, 0xE9, 0x69, 0xC0, 0xF8, 0x2C, 0x12, 0x29, 0x6A, 0xC0, 0xF8, ++0x30, 0x12, 0x00, 0x22, 0x69, 0x6A, 0xC0, 0xF8, 0x34, 0x12, 0x00, 0x23, 0xC0, 0xE9, 0x88, 0x23, 0xAC, 0xE7, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF2, 0x05, 0xA1, 0xD1, 0xE9, 0x00, 0x01, 0xBB, 0x1B, 0x02, 0xEB, 0xC3, 0x03, 0x23, 0x44, ++0xC3, 0xE9, 0x88, 0x01, 0x9E, 0xE7, 0x00, 0xBF, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x18, 0x88, 0x17, 0x00, ++0x78, 0x22, 0x10, 0xB4, 0xC1, 0xEB, 0x01, 0x13, 0xD0, 0xF8, 0xA8, 0x44, 0x02, 0xFB, 0x01, 0x01, 0x00, 0xEB, 0xC3, 0x03, ++0x01, 0xF5, 0xEC, 0x71, 0x00, 0x22, 0x8C, 0x42, 0x83, 0xF8, 0x3B, 0x22, 0x06, 0xD0, 0xD0, 0xF8, 0xAC, 0x34, 0x8B, 0x42, ++0x1C, 0xD0, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x90, 0xF8, 0x3B, 0x32, 0xC0, 0xF8, 0xA8, 0x24, 0x00, 0xF5, 0xEC, 0x71, ++0x7B, 0xB9, 0x90, 0xF8, 0xB3, 0x32, 0x00, 0xF5, 0x14, 0x71, 0x53, 0xB9, 0x90, 0xF8, 0x2B, 0x33, 0x00, 0xF5, 0x32, 0x71, ++0x2B, 0xB9, 0x90, 0xF8, 0xA3, 0x33, 0x00, 0xF5, 0x50, 0x71, 0x00, 0x2B, 0xE1, 0xD0, 0xC0, 0xF8, 0xA8, 0x14, 0xE2, 0xE7, ++0x90, 0xF8, 0x1B, 0x34, 0x00, 0x22, 0xC0, 0xF8, 0xAC, 0x24, 0x43, 0xB9, 0x90, 0xF8, 0x93, 0x34, 0x00, 0x2B, 0xD8, 0xD0, ++0x00, 0xF5, 0x86, 0x63, 0xC0, 0xF8, 0xAC, 0x34, 0xD3, 0xE7, 0x00, 0xF5, 0x6E, 0x73, 0xF9, 0xE7, 0x70, 0xB5, 0xD0, 0xF8, ++0xE4, 0x40, 0x54, 0xB1, 0x05, 0x4E, 0x05, 0x46, 0x21, 0x46, 0xD6, 0xF8, 0x20, 0x33, 0x00, 0x22, 0x28, 0x46, 0x98, 0x47, ++0x24, 0x68, 0x00, 0x2C, 0xF6, 0xD1, 0x70, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x04, 0x4A, 0x05, 0x4B, 0x11, 0x69, 0xD3, 0xF8, ++0xE0, 0x31, 0x01, 0xF5, 0x1C, 0x51, 0x28, 0x30, 0x10, 0x31, 0x18, 0x47, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x0B, 0x4B, 0x1A, 0x78, 0x02, 0xB9, 0x70, 0x47, 0x5B, 0x68, 0x1B, 0x07, 0xFB, 0xD4, 0x43, 0x68, 0x70, 0xB5, 0x04, 0x46, ++0x03, 0xB1, 0x70, 0xBD, 0x06, 0x4D, 0x28, 0x30, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xD5, 0xF8, 0x50, 0x34, 0x20, 0x46, ++0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF0, 0xB4, 0xA0, 0xF8, ++0xD2, 0x10, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1F, 0x4D, ++0x1F, 0x4B, 0x2E, 0x68, 0x9A, 0x7C, 0x77, 0x1C, 0x01, 0x2A, 0x2F, 0x60, 0x2B, 0xD9, 0x1D, 0x4C, 0x1A, 0x7D, 0x4F, 0xF4, ++0xA4, 0x6C, 0x0C, 0xFB, 0x02, 0x42, 0xB2, 0xF8, 0xD2, 0x40, 0xA1, 0x42, 0x1C, 0xD3, 0x9B, 0x68, 0x5B, 0xB1, 0x01, 0x21, ++0xB3, 0xF8, 0xD2, 0x20, 0x83, 0xF8, 0xD5, 0x10, 0xB2, 0xFB, 0xF4, 0xF2, 0x83, 0xF8, 0xD4, 0x20, 0x1B, 0x68, 0x00, 0x2B, ++0xF4, 0xD1, 0x12, 0x4A, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x23, 0x43, 0x13, 0x60, 0x2F, 0xB1, 0x0A, 0x4B, 0x2E, 0x60, ++0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, 0x70, 0x47, 0x90, 0xF8, 0x63, 0x20, 0x1A, 0x75, 0x0C, 0x46, ++0xDD, 0xE7, 0x90, 0xF8, 0x63, 0x20, 0x1A, 0x75, 0x40, 0xF2, 0x01, 0x13, 0x0C, 0x46, 0xA0, 0xF8, 0xD4, 0x30, 0xE2, 0xE7, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x21, 0x04, 0x46, 0x82, 0xB0, 0x03, 0x23, 0x00, 0x22, 0x58, 0x20, 0x0B, 0xF0, 0xEA, 0xFC, ++0x3B, 0x4F, 0xFF, 0x22, 0x7B, 0x6D, 0x8D, 0xF8, 0x07, 0x20, 0x05, 0x46, 0x94, 0xF8, 0x63, 0x00, 0x98, 0x47, 0xB4, 0xF8, ++0xB6, 0x14, 0x94, 0xF8, 0xB4, 0x04, 0x10, 0xF0, 0xED, 0xF9, 0x94, 0xF8, 0xB5, 0x24, 0xB4, 0xF8, 0xB8, 0x64, 0xB4, 0xF8, ++0xBA, 0x14, 0x84, 0xF8, 0xC5, 0x21, 0x04, 0x2A, 0x08, 0xBF, 0x03, 0x22, 0x03, 0x46, 0xC4, 0xF8, 0x90, 0x01, 0xA4, 0xF8, ++0x94, 0x61, 0xA4, 0xF8, 0x96, 0x11, 0x84, 0xF8, 0xC4, 0x21, 0x00, 0x28, 0x50, 0xD0, 0x1B, 0x79, 0x84, 0xF8, 0xBC, 0x34, ++0x7B, 0x6C, 0x0D, 0xF1, 0x07, 0x01, 0x04, 0xF2, 0xB4, 0x40, 0x98, 0x47, 0x9D, 0xF8, 0x07, 0x10, 0x68, 0x70, 0xA9, 0x70, ++0x06, 0x46, 0x94, 0xF8, 0x63, 0x00, 0x28, 0x70, 0x94, 0xF8, 0x62, 0x30, 0x2B, 0xBB, 0x84, 0xF8, 0x8A, 0x30, 0x7E, 0xBB, ++0xFB, 0x6C, 0x94, 0xF8, 0x6C, 0x80, 0x98, 0x47, 0xD7, 0xF8, 0xD8, 0x31, 0x04, 0xF1, 0x28, 0x00, 0x98, 0x47, 0x1A, 0x4A, ++0x1A, 0x49, 0xD7, 0xF8, 0xE0, 0x31, 0x09, 0x69, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x08, 0x28, 0x04, 0xF1, 0x18, 0x00, ++0xD8, 0xF8, 0x08, 0x20, 0x11, 0x44, 0x98, 0x47, 0x01, 0x23, 0x84, 0xF8, 0x78, 0x60, 0x84, 0xF8, 0x8B, 0x30, 0x28, 0x46, ++0x0B, 0xF0, 0xBE, 0xFC, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x2B, 0xF7, 0xD1, 0x00, 0x23, 0x84, 0xF8, 0xDB, 0x30, ++0x00, 0x2E, 0xF2, 0xD1, 0xFB, 0x6C, 0x98, 0x47, 0x0A, 0x4B, 0x01, 0x22, 0x5A, 0x72, 0xEC, 0xE7, 0xD7, 0xF8, 0xBC, 0x31, ++0x20, 0x46, 0x98, 0x47, 0x28, 0x46, 0x0B, 0xF0, 0xA7, 0xFC, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1B, 0x79, 0xFF, 0xDE, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0xD8, 0x9C, 0x17, 0x00, 0x07, 0x4A, 0x93, 0x7C, ++0x51, 0x7C, 0x0B, 0x44, 0x01, 0x2B, 0x06, 0xD1, 0x90, 0x68, 0x90, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x18, 0xBF, 0x00, 0x20, ++0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x05, 0x4A, 0x06, 0x49, 0x93, 0x7C, 0x50, 0x7C, ++0x03, 0x44, 0x00, 0x22, 0x01, 0x2B, 0x0A, 0x60, 0x01, 0xDC, 0xFF, 0xF7, 0x65, 0xB9, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, ++0x2C, 0x00, 0x32, 0x40, 0x13, 0x4B, 0x00, 0x22, 0x02, 0x70, 0x9B, 0x68, 0x03, 0xB3, 0x10, 0xB4, 0x01, 0x46, 0x01, 0x24, ++0x10, 0x46, 0x08, 0xE0, 0x93, 0xF8, 0x64, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0xC0, 0x24, 0x72, 0xB9, 0x01, 0x30, 0x1B, 0x68, ++0x7B, 0xB1, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xF2, 0xD0, 0x93, 0xF8, 0x64, 0x20, 0x00, 0x2A, 0xF5, 0xD0, 0x93, 0xF8, ++0xC0, 0x24, 0x00, 0x2A, 0xF1, 0xD0, 0x0C, 0x70, 0x1B, 0x68, 0x00, 0x2B, 0xEF, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x18, 0x46, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, 0x10, 0xB5, 0x04, 0x23, 0x04, 0x46, 0xFF, 0x22, 0x00, 0x21, 0x87, 0x20, ++0x0B, 0xF0, 0x16, 0xFC, 0x04, 0x60, 0xBD, 0xE8, 0x10, 0x40, 0x0B, 0xF0, 0x41, 0xBC, 0x00, 0xBF, 0x11, 0xF4, 0x00, 0x01, ++0x70, 0xB5, 0x04, 0x46, 0x16, 0xD0, 0x00, 0x25, 0x2A, 0x4B, 0x80, 0xF8, 0x78, 0x50, 0x19, 0x69, 0x29, 0x48, 0x2A, 0x4B, ++0x80, 0xF8, 0x24, 0x50, 0x40, 0xF2, 0x01, 0x72, 0x01, 0xF5, 0x1C, 0x51, 0x44, 0x61, 0x82, 0x83, 0xD3, 0xF8, 0xE0, 0x31, ++0x10, 0x31, 0x0C, 0x30, 0x98, 0x47, 0x84, 0xF8, 0x6B, 0x50, 0x70, 0xBD, 0x90, 0xF8, 0x6B, 0x30, 0x21, 0x4A, 0x01, 0x33, ++0xDB, 0xB2, 0x12, 0x68, 0x80, 0xF8, 0x6B, 0x30, 0x52, 0x78, 0x9A, 0x42, 0x25, 0xD0, 0x90, 0xF8, 0x64, 0x30, 0xC3, 0xB9, ++0x1C, 0x4B, 0x5B, 0x78, 0x23, 0xB1, 0x1C, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x15, 0x4B, 0x1A, 0x7A, ++0x0A, 0xB1, 0x01, 0x3A, 0x1A, 0x72, 0x14, 0x4A, 0x17, 0x48, 0xD2, 0xF8, 0xD8, 0x21, 0x01, 0x21, 0x99, 0x83, 0x90, 0x47, ++0x63, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x70, 0xBD, 0x0E, 0x4B, 0x90, 0xF8, 0x63, 0x00, 0xD3, 0xF8, 0x94, 0x34, ++0x10, 0x49, 0x22, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x80, 0xF8, 0x6B, 0x10, 0x4F, 0xF4, 0x80, 0x60, 0x0D, 0x49, ++0x0D, 0xF0, 0x74, 0xFA, 0x05, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, ++0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, ++0x34, 0x04, 0x32, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x99, 0x71, 0x13, 0x00, 0xF0, 0x98, 0x15, 0x00, 0x30, 0xB4, 0x01, 0x25, ++0x00, 0x24, 0x1D, 0x70, 0x14, 0x70, 0x04, 0x28, 0x20, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x03, 0x18, 0x09, 0x05, 0x14, 0x00, ++0x00, 0x21, 0x19, 0x70, 0x01, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x09, 0x78, 0x10, 0x29, 0x0F, 0xD0, 0x20, 0x29, ++0x01, 0xD1, 0x02, 0x21, 0x19, 0x70, 0x03, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x04, 0x23, 0x13, 0x70, 0x30, 0xBC, ++0x70, 0x47, 0x02, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x21, 0x19, 0x70, 0xF0, 0xE7, 0x05, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE1, 0xDA, 0x30, 0xBC, 0x03, 0x49, 0x03, 0x48, 0xAD, 0x22, 0x0D, 0xF0, 0x50, 0xBC, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x22, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x0F, 0x33, ++0x23, 0xB1, 0x13, 0x68, 0xC3, 0xF3, 0x0F, 0x33, 0x96, 0x2B, 0x36, 0xD9, 0x96, 0x20, 0x1E, 0x49, 0x1E, 0x4B, 0x0A, 0x68, ++0x18, 0x81, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x96, 0x2A, 0x25, 0xD9, 0x96, 0x22, ++0x19, 0x49, 0x5A, 0x81, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x96, 0x2A, ++0x15, 0xD9, 0x96, 0x22, 0x14, 0x49, 0x9A, 0x81, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, ++0x0F, 0x32, 0x96, 0x2A, 0x03, 0xD9, 0x96, 0x22, 0xDA, 0x81, 0x1A, 0x82, 0x70, 0x47, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, ++0xDA, 0x81, 0x1A, 0x82, 0x70, 0x47, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0xE6, 0xE7, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, ++0xD6, 0xE7, 0x10, 0x68, 0xC0, 0xF3, 0x0F, 0x30, 0xC5, 0xE7, 0x00, 0xBF, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, 0x38, 0xB5, 0x0B, 0x4C, 0x34, 0x22, 0x00, 0x21, ++0x20, 0x46, 0xE8, 0xF7, 0x0B, 0xFF, 0x09, 0x48, 0x09, 0x4A, 0x0A, 0x49, 0x22, 0x60, 0x01, 0x25, 0x00, 0x23, 0xE5, 0x77, ++0x02, 0x60, 0x63, 0x82, 0x63, 0x60, 0xD1, 0xF8, 0xA0, 0x31, 0x98, 0x47, 0x05, 0x4B, 0x63, 0x62, 0x38, 0xBD, 0x00, 0xBF, ++0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x88, 0x1A, 0x17, 0x00, 0x7D, 0x71, 0x13, 0x00, ++0x38, 0xB5, 0x51, 0x4D, 0x51, 0x4C, 0xAB, 0x78, 0x13, 0xB9, 0xD4, 0xF8, 0xE4, 0x30, 0x98, 0x47, 0xFF, 0xF7, 0xD4, 0xFF, ++0xFF, 0xF7, 0x6A, 0xF8, 0xFE, 0xF7, 0xF8, 0xFC, 0x09, 0xF0, 0xDC, 0xFC, 0x07, 0xF0, 0x78, 0xFD, 0x08, 0xF0, 0xAA, 0xFE, ++0xD4, 0xF8, 0x8C, 0x33, 0x98, 0x47, 0xAB, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x82, 0x80, 0xFD, 0xF7, 0x61, 0xFA, 0x45, 0x4D, ++0x2B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x7D, 0xD4, 0x03, 0xF0, 0x70, 0xFD, 0x09, 0xF0, 0x7C, 0xFE, 0x63, 0x6E, 0x98, 0x47, ++0xD4, 0xF8, 0x7C, 0x31, 0x98, 0x47, 0xEF, 0xF7, 0x0D, 0xF8, 0xEF, 0xF7, 0x0D, 0xF8, 0xEF, 0xF7, 0x0D, 0xF8, 0x3C, 0x4B, ++0x93, 0xF8, 0xFA, 0x30, 0x00, 0x2B, 0x62, 0xD1, 0xD4, 0xF8, 0xE4, 0x34, 0x98, 0x47, 0x39, 0x4A, 0x29, 0x68, 0x13, 0x68, ++0x38, 0x48, 0x39, 0x4D, 0xC3, 0xF3, 0x15, 0x03, 0x43, 0xF0, 0x20, 0x73, 0x13, 0x60, 0x8B, 0x78, 0x02, 0x68, 0xDC, 0x06, ++0x4C, 0xBF, 0x22, 0xF0, 0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x02, 0x60, 0x32, 0x4A, 0x33, 0x4C, 0x33, 0x48, 0x13, 0xF0, ++0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, 0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0x22, 0x68, 0x2F, 0x4B, ++0x42, 0xF0, 0x00, 0x62, 0x22, 0x60, 0x02, 0x68, 0x2D, 0x4C, 0x22, 0xF4, 0x70, 0x02, 0x42, 0xF4, 0x00, 0x12, 0x02, 0x60, ++0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x62, 0x42, 0xF4, 0xC0, 0x62, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0x60, 0x52, 0x42, 0xF4, ++0x00, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x32, 0x42, 0xF4, 0x40, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x60, 0x22, 0x1A, 0x60, 0x2B, 0x68, 0x20, 0x4A, 0x23, 0x40, 0x43, 0xF4, 0xBB, 0x63, 0xA0, 0xF5, 0x66, 0x70, 0x43, 0xF0, ++0x04, 0x03, 0x2B, 0x60, 0x03, 0x68, 0xA5, 0xF1, 0xF6, 0x55, 0xA5, 0xF5, 0x32, 0x25, 0x23, 0x40, 0x43, 0xF0, 0x3F, 0x03, ++0xA5, 0xF6, 0xFF, 0x15, 0x03, 0x60, 0x15, 0x60, 0x4B, 0x78, 0x2B, 0xB1, 0xD2, 0xF8, 0x24, 0x31, 0x43, 0xF0, 0x40, 0x03, ++0xC2, 0xF8, 0x24, 0x31, 0x38, 0xBD, 0x12, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x9B, 0xE7, 0xFD, 0xF7, 0xD5, 0xF9, 0x7C, 0xE7, ++0x03, 0x20, 0xEE, 0xF7, 0x8B, 0xFC, 0x7D, 0xE7, 0x3C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x2C, 0x19, 0x17, 0x00, 0xF0, 0x00, 0x32, 0x40, 0x80, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, ++0x40, 0x04, 0x32, 0x40, 0x34, 0x04, 0x32, 0x40, 0x2C, 0x04, 0x32, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x32, 0x40, ++0x80, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x1C, 0x46, 0x05, 0x8C, 0x93, 0xF8, 0x62, 0x30, 0xD2, 0xF8, 0x20, 0x90, ++0x87, 0x69, 0xD0, 0xF8, 0x1C, 0xB0, 0x89, 0xB0, 0x16, 0x46, 0xAD, 0x02, 0xDD, 0xE9, 0x12, 0x20, 0xD3, 0xB9, 0xB4, 0xF8, ++0x68, 0xC0, 0xBC, 0xF1, 0x00, 0x0F, 0x15, 0xD0, 0xD2, 0x8B, 0xB3, 0x6A, 0x0C, 0xFB, 0x02, 0xF2, 0x05, 0x92, 0x18, 0x07, ++0x05, 0xFB, 0x0C, 0xF2, 0x06, 0x92, 0x19, 0xD0, 0x00, 0x23, 0xB7, 0xEB, 0x09, 0x0A, 0x4F, 0xF4, 0xFA, 0x76, 0x07, 0x93, ++0x05, 0x9B, 0x03, 0xF5, 0xC8, 0x73, 0xC4, 0xE9, 0x1F, 0xA3, 0x74, 0xE0, 0x00, 0x28, 0x40, 0xF0, 0xC1, 0x80, 0x06, 0x95, ++0x4F, 0xF0, 0x01, 0x0A, 0xD0, 0x8B, 0xB2, 0x6A, 0x0A, 0xFB, 0x00, 0xF0, 0x12, 0x07, 0x05, 0x90, 0x40, 0xF0, 0x32, 0x81, ++0xF2, 0x6A, 0xDF, 0xF8, 0x94, 0xC2, 0xDF, 0xF8, 0xD4, 0x82, 0xDC, 0xF8, 0x00, 0x30, 0x9F, 0x48, 0xC2, 0xF3, 0x03, 0x12, ++0x23, 0xF0, 0x7F, 0x03, 0x18, 0xF8, 0x02, 0x20, 0x02, 0xF0, 0x7F, 0x02, 0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0xB3, 0x6A, ++0x99, 0x4A, 0xC3, 0xF3, 0xC0, 0x13, 0x41, 0xEA, 0x03, 0x51, 0x4F, 0xF0, 0x00, 0x43, 0x01, 0x60, 0x13, 0x60, 0xBF, 0xF3, ++0x4F, 0x8F, 0x00, 0xBF, 0x13, 0x68, 0x58, 0x00, 0xFC, 0xD5, 0x93, 0x4B, 0x19, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x00, 0x29, ++0xC0, 0xF2, 0xB4, 0x80, 0x8E, 0x4A, 0x12, 0x68, 0x1F, 0xFA, 0x82, 0xFA, 0xB2, 0x6A, 0x12, 0x07, 0x40, 0xF0, 0xA3, 0x80, ++0xF2, 0x6A, 0x8C, 0x49, 0x88, 0x48, 0xD1, 0xF8, 0x00, 0xC0, 0xC2, 0xF3, 0x03, 0x12, 0x2C, 0xF0, 0x7F, 0x0C, 0x18, 0xF8, ++0x02, 0x20, 0x02, 0xF0, 0x7F, 0x02, 0x42, 0xEA, 0x0C, 0x02, 0x0A, 0x60, 0xB2, 0x6A, 0xC2, 0xF3, 0xC0, 0x12, 0x08, 0x31, ++0x12, 0x05, 0x42, 0xF0, 0x18, 0x02, 0x4F, 0xF0, 0x00, 0x46, 0x02, 0x60, 0x0E, 0x60, 0xBF, 0xF3, 0x4F, 0x8F, 0x00, 0xBF, ++0x0A, 0x68, 0x56, 0x00, 0xFC, 0xD5, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x73, 0xDB, 0x77, 0x4A, 0x94, 0xF8, ++0x62, 0x30, 0x16, 0x68, 0x00, 0x22, 0xB6, 0xB2, 0xAA, 0xEB, 0x06, 0x0A, 0x07, 0x92, 0xB7, 0xEB, 0x09, 0x09, 0x19, 0xEB, ++0x0A, 0x0A, 0x00, 0x2B, 0x84, 0xD0, 0x4F, 0xEA, 0xE5, 0x79, 0x2A, 0x46, 0x4B, 0x46, 0x38, 0x46, 0x59, 0x46, 0x1F, 0xF0, ++0x67, 0xFB, 0xBA, 0x1B, 0x02, 0x92, 0x07, 0x9A, 0x00, 0xFB, 0x09, 0xF3, 0x6B, 0xEB, 0x02, 0x02, 0x05, 0xFB, 0x01, 0x33, ++0x03, 0x92, 0xA0, 0xFB, 0x05, 0x01, 0x19, 0x44, 0xDD, 0xE9, 0x02, 0x23, 0x99, 0x42, 0x08, 0xBF, 0x90, 0x42, 0x38, 0xBF, ++0xCD, 0xE9, 0x02, 0x01, 0x64, 0x4B, 0x06, 0x9A, 0x1B, 0x68, 0xDD, 0xE9, 0x02, 0x67, 0xB6, 0x18, 0x99, 0x01, 0x34, 0xD4, ++0x05, 0x9B, 0xF1, 0x1A, 0xA1, 0xF5, 0xC8, 0x71, 0x5F, 0x4F, 0x60, 0x4B, 0x3E, 0x69, 0x1B, 0x68, 0xF6, 0x1A, 0x0E, 0x44, ++0xE9, 0xF7, 0xDC, 0xFD, 0x3B, 0x69, 0xF3, 0x1A, 0xA3, 0xF5, 0x86, 0x53, 0x0C, 0x3B, 0x18, 0x1A, 0x00, 0x28, 0x63, 0x6A, ++0xB8, 0xBF, 0x76, 0x19, 0xB3, 0x42, 0x24, 0xD0, 0x57, 0x4B, 0x1A, 0x6A, 0xA2, 0x42, 0x43, 0xD0, 0x56, 0x4D, 0x31, 0x46, ++0xD5, 0xF8, 0xE0, 0x31, 0x04, 0xF1, 0x18, 0x00, 0x98, 0x47, 0xD5, 0xF8, 0xA8, 0x30, 0x20, 0x46, 0x09, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x18, 0x47, 0x90, 0xF8, 0x02, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0x90, 0xF8, 0x03, 0xA0, 0x05, 0xFB, ++0x0A, 0xF0, 0x06, 0x90, 0x36, 0xE7, 0x4B, 0x49, 0x05, 0x9B, 0xC9, 0x1A, 0xA1, 0xEB, 0x0A, 0x0A, 0x0A, 0xEB, 0x06, 0x01, ++0xC6, 0xE7, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0B, 0x68, 0x58, 0x00, 0x88, 0xD4, 0x45, 0x49, 0x45, 0x48, 0x4F, 0xF4, ++0xBE, 0x72, 0x0D, 0xF0, 0xD7, 0xF9, 0x00, 0x22, 0x94, 0xF8, 0x62, 0x30, 0x07, 0x92, 0xAA, 0xF5, 0xFA, 0x7A, 0x4F, 0xF4, ++0xFA, 0x76, 0x82, 0xE7, 0x12, 0x68, 0x51, 0x00, 0x3F, 0xF5, 0x48, 0xAF, 0x3B, 0x49, 0x3C, 0x48, 0x4F, 0xF4, 0xBE, 0x72, ++0x0D, 0xF0, 0xC4, 0xF9, 0x4F, 0xF4, 0xFA, 0x7A, 0x2F, 0x4B, 0x41, 0xE7, 0x30, 0x4A, 0x66, 0x62, 0x12, 0x68, 0x92, 0x01, ++0xB6, 0xD4, 0x36, 0x4A, 0x36, 0x4D, 0x12, 0x68, 0x93, 0xF8, 0x24, 0x10, 0x41, 0xF2, 0x13, 0x30, 0xC2, 0xF3, 0x07, 0x42, ++0x2A, 0x54, 0x00, 0x29, 0x32, 0xD1, 0x32, 0x4A, 0x32, 0x49, 0x12, 0x68, 0x09, 0x68, 0x41, 0xF2, 0x14, 0x30, 0xD2, 0xB2, ++0x2A, 0x54, 0x01, 0x22, 0x83, 0xF8, 0x24, 0x20, 0x0B, 0x78, 0x93, 0x42, 0x06, 0xD1, 0x2D, 0x49, 0x2D, 0x4A, 0x0B, 0x60, ++0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x41, 0xF2, 0x13, 0x32, 0x41, 0xF2, 0x14, 0x33, 0xA8, 0x5C, 0xE9, 0x5C, ++0x88, 0x42, 0x1D, 0xD2, 0x17, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDA, 0x41, 0xF2, 0x13, 0x32, ++0x41, 0xF2, 0x14, 0x33, 0xAA, 0x5C, 0xEB, 0x5C, 0x9A, 0x42, 0x07, 0xD3, 0x18, 0x49, 0x20, 0x48, 0x15, 0x4D, 0x40, 0xF2, ++0xD7, 0x12, 0x0D, 0xF0, 0xAF, 0xF9, 0x7E, 0xE7, 0x12, 0x4D, 0x7C, 0xE7, 0x00, 0x22, 0x4F, 0xF4, 0xFA, 0x76, 0x07, 0x92, ++0x92, 0x46, 0x28, 0xE7, 0x12, 0x4E, 0x14, 0x48, 0xA9, 0x5C, 0xEA, 0x5C, 0x33, 0x68, 0x06, 0x68, 0x16, 0x48, 0xF6, 0xB2, ++0x1B, 0x0C, 0x00, 0x96, 0x0C, 0xF0, 0x20, 0xFF, 0xD4, 0xE7, 0x00, 0xBF, 0x60, 0x81, 0x32, 0x40, 0x6C, 0x81, 0x32, 0x40, ++0x38, 0x36, 0x17, 0x00, 0x64, 0x81, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0xA4, 0x80, 0x32, 0x40, ++0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xFE, 0xFF, 0xFF, 0x70, 0x79, 0x15, 0x00, 0x04, 0x99, 0x15, 0x00, ++0x44, 0x80, 0x32, 0x40, 0x00, 0x40, 0x1E, 0x00, 0x90, 0x00, 0x32, 0x40, 0x74, 0x36, 0x17, 0x00, 0x70, 0x80, 0x32, 0x40, ++0x74, 0x80, 0x32, 0x40, 0x3C, 0x99, 0x15, 0x00, 0x28, 0x99, 0x15, 0x00, 0x40, 0xA9, 0x15, 0x00, 0x0B, 0x02, 0x10, 0xB5, ++0x04, 0x46, 0x03, 0xD5, 0x00, 0x23, 0x80, 0xF8, 0x78, 0x30, 0x10, 0xBD, 0x4F, 0xF4, 0x80, 0x60, 0x04, 0x49, 0x0C, 0xF0, ++0x37, 0xFF, 0x04, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0xB0, 0x99, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x70, 0x93, 0xD9, 0xF8, 0x20, 0xB0, 0x83, 0xB0, 0x4F, 0xF4, ++0x00, 0x20, 0x0B, 0xF0, 0x79, 0xFC, 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xF5, 0x80, 0xBA, 0x4C, 0xDF, 0xF8, 0x58, 0xA3, ++0xA1, 0x7F, 0xB9, 0x4F, 0xDF, 0xF8, 0x54, 0x83, 0xB8, 0x4E, 0x00, 0x29, 0x00, 0xF0, 0xEA, 0x80, 0x08, 0x07, 0x0E, 0xD5, ++0xB6, 0x4B, 0xDB, 0xF8, 0x70, 0x00, 0x1B, 0x68, 0xDA, 0xF8, 0x10, 0x20, 0x5B, 0x68, 0x03, 0x44, 0x9B, 0x1A, 0x00, 0x2B, ++0xC0, 0xF2, 0xCB, 0x80, 0x01, 0xF0, 0xF7, 0x01, 0xA1, 0x77, 0x4A, 0x07, 0x00, 0xF1, 0x99, 0x80, 0x8B, 0x07, 0x15, 0xD5, ++0xDB, 0xF8, 0x04, 0x30, 0x23, 0xF0, 0x02, 0x03, 0xCB, 0xF8, 0x04, 0x30, 0x99, 0xF8, 0x1D, 0x30, 0x05, 0x2B, 0x08, 0xD1, ++0xA8, 0x4D, 0xA9, 0x48, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x23, 0xA1, 0x7F, 0x89, 0xF8, 0x1D, 0x30, 0x01, 0xF0, ++0xFD, 0x01, 0xA1, 0x77, 0xCD, 0x07, 0x2E, 0xD5, 0x33, 0x68, 0x58, 0x01, 0x40, 0xF1, 0xA3, 0x80, 0x31, 0x68, 0x09, 0x0C, ++0x11, 0xF4, 0x7C, 0x7F, 0x00, 0xF0, 0xAA, 0x80, 0x9E, 0x4A, 0x10, 0x39, 0x01, 0xF0, 0xFF, 0x01, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x25, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xA1, 0x80, 0x99, 0x4A, 0x93, 0xF8, 0x22, 0x10, ++0x13, 0x68, 0x98, 0x4A, 0xB3, 0xF9, 0x00, 0x30, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x22, 0x00, 0x2B, 0x00, 0x92, ++0xC0, 0xF2, 0x9F, 0x80, 0x3B, 0x68, 0x13, 0xF4, 0xE0, 0x2F, 0x00, 0xF0, 0xA8, 0x80, 0xA1, 0x7F, 0x01, 0xF0, 0xFE, 0x01, ++0xA1, 0x77, 0x8A, 0x06, 0x9D, 0xD5, 0x8E, 0x4E, 0x8E, 0x49, 0x35, 0x68, 0xC5, 0xF3, 0x41, 0x17, 0x3A, 0x46, 0x02, 0x20, ++0x0C, 0xF0, 0xAA, 0xFE, 0x00, 0x23, 0xC5, 0xF3, 0x47, 0x15, 0x8B, 0xF8, 0x78, 0x30, 0x00, 0x2F, 0x40, 0xF0, 0xB2, 0x80, ++0x87, 0x4B, 0x80, 0x4E, 0x5A, 0x78, 0x1A, 0x70, 0x86, 0x4A, 0x87, 0x4D, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, ++0xDB, 0xF8, 0x04, 0x30, 0xD6, 0xF8, 0xD8, 0x21, 0x23, 0xF0, 0x01, 0x03, 0xCB, 0xF8, 0x04, 0x30, 0x0B, 0xF1, 0x28, 0x00, ++0x90, 0x47, 0x2A, 0x68, 0x13, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x24, 0x81, 0x78, 0x49, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, ++0x0B, 0x60, 0x13, 0x78, 0x01, 0x2B, 0x12, 0xD1, 0x01, 0xF5, 0xFF, 0x41, 0x34, 0x31, 0x78, 0x4A, 0xDA, 0xF8, 0x10, 0x30, ++0x08, 0x68, 0xB2, 0xF8, 0xB2, 0x10, 0xD6, 0xF8, 0xE0, 0x21, 0x03, 0xEB, 0x40, 0x13, 0x59, 0x1A, 0x0B, 0xF1, 0x18, 0x00, ++0x90, 0x47, 0x2B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x00, 0x81, 0xA1, 0x7F, 0x01, 0xF0, 0xDF, 0x01, 0xA1, 0x77, ++0x4B, 0xE7, 0x6D, 0x49, 0x61, 0x4D, 0x02, 0x20, 0x0C, 0xF0, 0x60, 0xFE, 0x6B, 0x49, 0x63, 0x68, 0x0A, 0x68, 0x22, 0xF0, ++0x04, 0x02, 0x0A, 0x60, 0x22, 0x68, 0x43, 0xF4, 0x00, 0x73, 0x1A, 0x43, 0x4A, 0x61, 0xD5, 0xF8, 0x98, 0x14, 0x63, 0x60, ++0x9B, 0xF8, 0x63, 0x00, 0xD5, 0xF8, 0x94, 0x34, 0x5A, 0x46, 0x98, 0x47, 0x3B, 0x68, 0xA1, 0x7F, 0x23, 0xF0, 0x7C, 0x73, ++0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0xF0, 0xFB, 0x01, 0x43, 0xF4, 0x80, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xA1, 0x77, ++0x3E, 0xE7, 0x5B, 0x48, 0x0C, 0xF0, 0xEA, 0xFD, 0x7F, 0xE7, 0x00, 0x22, 0x9B, 0xF8, 0x6C, 0x00, 0x11, 0x46, 0xF8, 0xF7, ++0x01, 0xFB, 0x60, 0xB1, 0xA1, 0x7F, 0x2B, 0xE7, 0x55, 0x48, 0x0C, 0xF0, 0xDD, 0xFD, 0x72, 0xE7, 0x54, 0x48, 0x0C, 0xF0, ++0xD9, 0xFD, 0x6E, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x10, 0x30, 0xA1, 0x7F, 0xCB, 0xF8, 0x70, 0x30, ++0x1A, 0xE7, 0x93, 0x45, 0x3F, 0xF4, 0x5E, 0xAF, 0x4D, 0x49, 0x4E, 0x48, 0x40, 0xF2, 0x22, 0x32, 0x0D, 0xF0, 0x40, 0xF8, ++0x3B, 0x68, 0x13, 0xF4, 0xE0, 0x2F, 0x7F, 0xF4, 0x58, 0xAF, 0x32, 0x68, 0x33, 0x68, 0x49, 0x49, 0xD0, 0x0F, 0xC3, 0xF3, ++0x80, 0x73, 0x05, 0x46, 0x02, 0x46, 0x02, 0x20, 0x01, 0x93, 0x0C, 0xF0, 0x05, 0xFE, 0x01, 0x9B, 0x53, 0xEA, 0x05, 0x02, ++0x28, 0x46, 0x3F, 0xF4, 0x46, 0xAF, 0x2F, 0x4D, 0x00, 0x9A, 0x19, 0x46, 0xD5, 0xF8, 0x3C, 0x32, 0x98, 0x47, 0x33, 0x68, ++0x23, 0xF0, 0x00, 0x43, 0x33, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x80, 0x43, 0x33, 0x60, 0x36, 0xE7, 0xDA, 0xF8, 0x10, 0x10, ++0x01, 0xF5, 0x9C, 0x51, 0x32, 0x46, 0x08, 0x31, 0x05, 0xE0, 0xDA, 0xF8, 0x10, 0x30, 0xCB, 0x1A, 0x00, 0x2B, 0xC0, 0xF2, ++0xC2, 0x80, 0x13, 0x68, 0x1B, 0x07, 0xF6, 0xD5, 0xDF, 0xF8, 0x90, 0x80, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x08, 0x03, ++0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0xDE, 0x06, 0x19, 0xD5, 0x2C, 0x49, 0x19, 0x4E, 0x02, 0x20, 0x0C, 0xF0, ++0xCF, 0xFD, 0x2B, 0x4B, 0xDF, 0xF8, 0x74, 0xC0, 0x1A, 0x68, 0xD6, 0xF8, 0x3C, 0x32, 0x12, 0x0C, 0x8C, 0xF8, 0x00, 0x20, ++0x05, 0xF0, 0x01, 0x01, 0x78, 0x08, 0x5A, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x10, 0x03, 0xC8, 0xF8, ++0x00, 0x30, 0x1B, 0xE7, 0x21, 0x4B, 0x22, 0x49, 0x0B, 0x4E, 0x01, 0x25, 0x1D, 0x60, 0x02, 0x20, 0x0C, 0xF0, 0xB2, 0xFD, ++0x0F, 0x4A, 0x1F, 0x49, 0x53, 0x78, 0x0D, 0x60, 0xAB, 0x42, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x13, 0x70, 0x09, 0xE7, ++0x98, 0x9C, 0x17, 0x00, 0x74, 0x00, 0x32, 0x40, 0x70, 0x00, 0x32, 0x40, 0xC8, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x28, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, ++0x20, 0x9A, 0x15, 0x00, 0x13, 0x53, 0x1E, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xC0, 0x99, 0x15, 0x00, 0x4C, 0x00, 0x32, 0x40, 0xC4, 0x99, 0x15, 0x00, 0xDC, 0x99, 0x15, 0x00, 0xF0, 0x99, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x04, 0x9A, 0x15, 0x00, 0x14, 0x9A, 0x15, 0x00, 0x40, 0x9A, 0x15, 0x00, 0x44, 0x80, 0x32, 0x40, ++0x64, 0x85, 0x32, 0x40, 0x4C, 0x9A, 0x15, 0x00, 0x68, 0x85, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x36, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0xF7, 0xF7, 0x35, 0xF9, 0xF9, 0xE6, 0xEF, 0xF3, 0x10, 0x83, ++0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x32, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x31, 0x4B, 0x2F, 0x4F, 0x1A, 0x68, 0x01, 0x32, ++0x1A, 0x60, 0x00, 0x21, 0x3A, 0x68, 0x39, 0x60, 0x02, 0xF0, 0x0F, 0x08, 0xDA, 0xF8, 0x10, 0x20, 0x31, 0x46, 0x16, 0x46, ++0x0A, 0x46, 0x47, 0xF2, 0x30, 0x50, 0x04, 0xE0, 0xDA, 0xF8, 0x10, 0x10, 0x89, 0x1B, 0x81, 0x42, 0x1B, 0xD8, 0x39, 0x68, ++0x09, 0x07, 0xF7, 0xD1, 0x25, 0x48, 0x26, 0x49, 0xD0, 0xF8, 0x00, 0xC0, 0x0F, 0x68, 0x16, 0x46, 0xDA, 0xF8, 0x10, 0x20, ++0xB8, 0xF1, 0x00, 0x0F, 0x1A, 0xD1, 0x22, 0x4A, 0x04, 0x21, 0x11, 0x60, 0x1A, 0x68, 0x32, 0xB1, 0x1B, 0x49, 0x01, 0x3A, ++0x1A, 0x60, 0x0B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x2A, 0x68, 0xA0, 0xE6, 0x1C, 0x49, 0x00, 0x92, 0x02, 0x20, ++0x0C, 0xF0, 0x24, 0xFD, 0x15, 0x4B, 0x00, 0x9A, 0xD3, 0xE7, 0x19, 0x49, 0x02, 0x20, 0x0C, 0xF0, 0x1D, 0xFD, 0x3B, 0xE7, ++0x07, 0xEA, 0x0C, 0x07, 0x7F, 0x07, 0xE0, 0xD4, 0xCD, 0xE9, 0x00, 0x16, 0x80, 0x46, 0x16, 0x46, 0x01, 0xE0, 0x7A, 0x07, ++0x12, 0xD4, 0x00, 0x9A, 0xD8, 0xF8, 0x00, 0x70, 0x12, 0x68, 0xDA, 0xF8, 0x10, 0x10, 0x47, 0xF2, 0x30, 0x50, 0x89, 0x1B, ++0x81, 0x42, 0x07, 0xEA, 0x02, 0x07, 0xF0, 0xD9, 0x0B, 0x49, 0x02, 0x20, 0x0C, 0xF0, 0x00, 0xFD, 0x03, 0x4B, 0xEA, 0xE7, ++0x01, 0x9E, 0xC4, 0xE7, 0x38, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, ++0x74, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x5C, 0x9A, 0x15, 0x00, 0x2C, 0x9A, 0x15, 0x00, 0x68, 0x9A, 0x15, 0x00, ++0x10, 0xB5, 0x00, 0x20, 0x0B, 0xF0, 0xD0, 0xF8, 0x01, 0x28, 0x05, 0xD1, 0x05, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, ++0x60, 0x31, 0x18, 0x47, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x0B, 0xF0, 0x1A, 0xB8, 0x88, 0x1A, 0x17, 0x00, ++0x03, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0x01, 0x21, 0x00, 0x20, 0x0B, 0xF0, 0x11, 0xB8, 0x00, 0xBF, 0x38, 0x00, 0x32, 0x40, ++0xF8, 0xB5, 0x90, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x46, 0xD0, 0x90, 0xF8, 0x8A, 0x30, 0x04, 0x46, 0x00, 0x2B, 0x42, 0xD1, ++0x3D, 0x4E, 0x3E, 0x49, 0x94, 0xF8, 0x6C, 0x30, 0x3D, 0x4A, 0x67, 0x6A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, ++0x9D, 0x68, 0x13, 0x6A, 0xA3, 0x42, 0x3D, 0x44, 0x54, 0xD0, 0xD6, 0xF8, 0xE0, 0x31, 0x29, 0x46, 0x04, 0xF1, 0x18, 0x00, ++0x98, 0x47, 0x20, 0x46, 0xFF, 0xF7, 0x82, 0xF8, 0xD4, 0xF8, 0x80, 0x10, 0xD6, 0xF8, 0x14, 0x32, 0x39, 0x44, 0x20, 0x46, ++0x98, 0x47, 0xD6, 0xF8, 0xA4, 0x30, 0x2A, 0x46, 0x39, 0x46, 0x20, 0x46, 0x98, 0x47, 0xD8, 0xB9, 0x94, 0xF8, 0x78, 0x30, ++0x62, 0x68, 0x2C, 0x49, 0x01, 0x33, 0xDB, 0xB2, 0x42, 0xF0, 0x01, 0x02, 0x09, 0x68, 0x84, 0xF8, 0x78, 0x30, 0x62, 0x60, ++0x0A, 0x78, 0x93, 0x42, 0x21, 0xD8, 0x39, 0xD0, 0xB3, 0xEB, 0x52, 0x0F, 0x26, 0xD0, 0xB3, 0xEB, 0x92, 0x0F, 0x4F, 0xEA, ++0x92, 0x01, 0x21, 0xD0, 0x01, 0xEB, 0x41, 0x01, 0x8B, 0x42, 0x1D, 0xD0, 0xF8, 0xBD, 0x90, 0xF8, 0x8C, 0x20, 0x00, 0x2A, ++0xB8, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x01, 0x2B, 0x80, 0xF8, 0x8A, 0x30, 0x29, 0xD9, 0x02, 0x2B, 0x16, 0x4E, 0xB0, 0xD1, ++0x90, 0xF8, 0x63, 0x00, 0xD6, 0xF8, 0xC0, 0x31, 0x00, 0x21, 0x98, 0x47, 0xA9, 0xE7, 0xD6, 0xF8, 0x64, 0x11, 0x94, 0xF8, ++0x6C, 0x00, 0x22, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xF8, 0xF7, 0x30, 0xB9, 0xBD, 0xE8, 0xF8, 0x40, 0xEA, 0xF7, 0x5A, 0xBE, ++0x0F, 0x4B, 0x65, 0x62, 0x93, 0xF8, 0xB5, 0x30, 0x00, 0x2B, 0xAA, 0xD1, 0x0D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, ++0x9F, 0xD1, 0xA4, 0xE7, 0xEA, 0xF7, 0x4C, 0xFE, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0x06, 0xF0, 0x47, 0xBD, 0xBD, 0xE8, ++0xF8, 0x40, 0xFF, 0xF7, 0x9B, 0xB8, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0xC8, 0x35, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x4B, 0x2D, 0xE9, 0xF0, 0x47, 0x9C, 0x68, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x34, 0x4D, 0x2B, 0x68, ++0x04, 0x20, 0x01, 0x33, 0x2B, 0x60, 0xF6, 0xF7, 0xF1, 0xFC, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xF6, 0xF7, 0x8C, 0xFD, ++0x2B, 0x68, 0x2B, 0xB1, 0x2C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x4C, 0xD0, 0xDF, 0xF8, 0xB4, 0x80, ++0x00, 0x2C, 0x43, 0xD0, 0x29, 0x4F, 0x2A, 0x4E, 0x40, 0xF6, 0xE7, 0x35, 0x02, 0xE0, 0x24, 0x68, 0x00, 0x2C, 0x3B, 0xD0, ++0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0xF8, 0xD1, 0x94, 0xF8, 0xD5, 0x30, 0x01, 0x3B, 0xDB, 0xB2, 0x84, 0xF8, 0xD5, 0x30, ++0x00, 0x2B, 0xF0, 0xD1, 0x94, 0xF8, 0xD4, 0x30, 0x84, 0xF8, 0xD5, 0x30, 0x20, 0x46, 0xFE, 0xF7, 0xD3, 0xFF, 0x61, 0x6A, ++0xD8, 0xF8, 0x14, 0x32, 0x01, 0xF6, 0xE8, 0x31, 0x20, 0x46, 0x98, 0x47, 0x3B, 0x68, 0xB4, 0xF8, 0xD2, 0x20, 0x59, 0x01, ++0xB5, 0xEB, 0x43, 0x1F, 0x28, 0xBF, 0x01, 0xEB, 0x82, 0x21, 0x32, 0x69, 0x23, 0x6C, 0xA2, 0xF6, 0xE8, 0x39, 0x89, 0x44, ++0x20, 0x46, 0x4A, 0x46, 0x1B, 0xB1, 0xD8, 0xF8, 0xA4, 0x30, 0x61, 0x6A, 0x98, 0x47, 0x94, 0xF8, 0xC0, 0x34, 0x04, 0xF1, ++0x18, 0x00, 0x49, 0x46, 0x00, 0x2B, 0xC6, 0xD0, 0xD8, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0x24, 0x68, 0x00, 0x2C, 0xC3, 0xD1, ++0xD8, 0xF8, 0x84, 0x31, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x00, 0x2A, 0xB0, 0xD0, 0x62, 0xB6, 0xAE, 0xE7, 0x00, 0xBF, ++0x00, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x40, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0xF0, 0x4A, 0xBE, 0x14, 0x4B, 0x15, 0x4A, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x10, 0xB5, ++0x14, 0x68, 0x00, 0x2B, 0x04, 0xF0, 0x40, 0x74, 0x14, 0xDB, 0x20, 0x46, 0x0B, 0xF0, 0x04, 0xF9, 0x0F, 0x4B, 0x9B, 0x7C, ++0x3B, 0xB9, 0x0F, 0x4A, 0x0F, 0x4B, 0x10, 0x6A, 0xD3, 0xF8, 0xCC, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x0C, 0x4B, ++0x20, 0x46, 0xD3, 0xF8, 0x68, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0xB4, 0xF1, 0x40, 0x7F, 0xE7, 0xD1, 0x08, 0x49, ++0x08, 0x48, 0x4F, 0xF4, 0x9D, 0x62, 0x0C, 0xF0, 0xBB, 0xFD, 0xE0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x9A, 0x15, 0x00, ++0xF0, 0xB5, 0x2D, 0x4E, 0x2D, 0x4B, 0xDF, 0xF8, 0xC8, 0xE0, 0xDF, 0xF8, 0xC8, 0xC0, 0x2C, 0x4F, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x00, 0x62, 0x15, 0x8D, 0xD4, 0x8C, 0x44, 0xEA, 0x05, 0x44, 0x1C, 0x60, 0x52, 0x8D, 0x27, 0x4D, 0x5A, 0x60, ++0x00, 0x24, 0x27, 0x4A, 0xCE, 0xF8, 0x00, 0x40, 0x4F, 0xF0, 0x00, 0x53, 0xCC, 0xF8, 0x00, 0x40, 0x2C, 0x60, 0x00, 0xF1, ++0x10, 0x05, 0x3C, 0x60, 0xEC, 0xB2, 0x13, 0x60, 0x13, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0xDD, 0x00, 0x26, 0xD4, 0x15, 0x68, ++0xC5, 0xF3, 0x07, 0x43, 0xA3, 0x42, 0x4F, 0xEA, 0x15, 0x45, 0x1F, 0xD0, 0xED, 0xB2, 0xDF, 0xF8, 0x5C, 0xE0, 0xDF, 0xF8, ++0x68, 0xC0, 0x18, 0x4F, 0x2D, 0x04, 0x4F, 0xF0, 0xFF, 0x33, 0x45, 0xF0, 0x80, 0x45, 0xCE, 0xF8, 0x00, 0x30, 0xCC, 0xF8, ++0x00, 0x30, 0x15, 0x60, 0x3B, 0x68, 0x5A, 0x00, 0xFC, 0xD4, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x00, 0x63, 0x0C, 0x48, ++0x1D, 0x8D, 0xDA, 0x8C, 0x42, 0xEA, 0x05, 0x42, 0x02, 0x60, 0x0D, 0x4A, 0x5B, 0x8D, 0x13, 0x60, 0x0B, 0x01, 0x43, 0xEA, ++0x04, 0x43, 0x09, 0x4A, 0x43, 0xF0, 0x80, 0x43, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, ++0x20, 0x46, 0xF0, 0xBD, 0x68, 0x65, 0x17, 0x00, 0xBC, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0xB4, 0x00, 0x32, 0x40, ++0xC4, 0x00, 0x32, 0x40, 0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x82, 0xB0, 0x47, 0x78, 0x90, 0xF8, 0x29, 0x60, 0x01, 0x23, 0x8D, 0xF8, 0x06, 0x30, 0xFF, 0x2F, 0x4F, 0xF0, 0x00, 0x03, ++0x04, 0x46, 0x00, 0xF1, 0x04, 0x08, 0x8D, 0xF8, 0x07, 0x30, 0x00, 0xF0, 0x83, 0x80, 0x74, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x73, 0xDB, 0x3A, 0x46, 0x94, 0xF8, 0x28, 0x30, 0x70, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x0C, 0xF0, ++0xF5, 0xFA, 0x07, 0xF1, 0x10, 0x05, 0x6E, 0x4B, 0xED, 0xB2, 0xD3, 0xF8, 0x18, 0x33, 0x29, 0x46, 0x20, 0x46, 0x98, 0x47, ++0x6B, 0x4A, 0x6C, 0x48, 0x6C, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0x22, 0x17, 0x8D, 0xD3, 0x8C, 0x43, 0xEA, ++0x07, 0x43, 0x03, 0x60, 0x53, 0x8D, 0x0B, 0x60, 0x0D, 0xF1, 0x06, 0x03, 0x0D, 0xF1, 0x07, 0x02, 0x94, 0xF8, 0x28, 0x00, ++0x41, 0x46, 0xFF, 0xF7, 0x7B, 0xF8, 0x63, 0x4B, 0xA2, 0x68, 0x1A, 0x60, 0xE2, 0x68, 0x5A, 0x60, 0x22, 0x69, 0x9A, 0x60, ++0x62, 0x69, 0xDA, 0x60, 0x9D, 0xF8, 0x07, 0x30, 0x04, 0x2B, 0x65, 0xD0, 0x5D, 0x4A, 0x12, 0x68, 0x02, 0x2B, 0x12, 0x78, ++0x1F, 0xD1, 0xD1, 0x07, 0x00, 0xF1, 0x85, 0x80, 0x5A, 0x48, 0x01, 0x68, 0x21, 0xF0, 0x01, 0x01, 0x01, 0x60, 0x92, 0x07, ++0x17, 0xD5, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x56, 0x4A, 0x2B, 0x04, 0x43, 0xEA, 0x00, 0x33, 0x43, 0xEA, ++0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0x28, 0x46, ++0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x97, 0x07, 0x6F, 0xD4, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x4A, 0x4A, ++0x1B, 0x02, 0x43, 0xEA, 0x00, 0x33, 0x43, 0xEA, 0x05, 0x43, 0x43, 0xEA, 0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, ++0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x59, 0x00, 0xFC, 0xD4, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x0D, 0x2F, ++0x89, 0xD9, 0x40, 0x49, 0x40, 0x48, 0x40, 0xF2, 0x5C, 0x52, 0x0C, 0xF0, 0xAB, 0xFC, 0x82, 0xE7, 0x90, 0xF8, 0x28, 0x30, ++0x05, 0x2B, 0x4E, 0xD0, 0x34, 0x48, 0x35, 0x4A, 0x25, 0x78, 0x3B, 0x49, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x60, 0x13, 0x60, ++0x94, 0xF8, 0x28, 0x30, 0x94, 0xF8, 0x29, 0x20, 0x4F, 0xF4, 0x80, 0x70, 0x0C, 0xF0, 0x6C, 0xFA, 0x05, 0xEB, 0x86, 0x05, ++0x29, 0x4B, 0xED, 0xB2, 0xD3, 0xF8, 0x48, 0x34, 0x29, 0x46, 0x20, 0x46, 0x98, 0x47, 0x83, 0xE7, 0x30, 0x4A, 0xA1, 0x69, ++0x11, 0x60, 0xE1, 0x69, 0x51, 0x60, 0x21, 0x6A, 0x91, 0x60, 0x27, 0x4A, 0x2D, 0x49, 0x60, 0x6A, 0x12, 0x68, 0x08, 0x60, ++0x12, 0x78, 0x90, 0x07, 0xB1, 0xD5, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x23, 0x4A, 0x1B, 0x02, 0x43, 0xEA, ++0x00, 0x33, 0x43, 0xEA, 0x05, 0x43, 0x43, 0xEA, 0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, ++0x13, 0x68, 0x58, 0x00, 0xFC, 0xD4, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1D, 0x49, 0xA0, 0x69, 0x08, 0x60, ++0xE0, 0x69, 0x48, 0x60, 0x20, 0x6A, 0x88, 0x60, 0x60, 0x6A, 0xC8, 0x60, 0x75, 0xE7, 0x5A, 0x1E, 0x01, 0x2A, 0xDA, 0xD8, ++0x73, 0xE7, 0x18, 0x4B, 0x05, 0x78, 0x1B, 0x68, 0x09, 0x4A, 0x1B, 0x0E, 0x03, 0x3B, 0x2B, 0x44, 0x03, 0xEB, 0x46, 0x03, ++0xDD, 0xB2, 0x29, 0x46, 0xD2, 0xF8, 0x48, 0x34, 0x98, 0x47, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0xB4, 0x9A, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x64, 0x05, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, ++0x70, 0x79, 0x15, 0x00, 0xA0, 0x9A, 0x15, 0x00, 0x90, 0x9A, 0x15, 0x00, 0xC8, 0x00, 0x32, 0x40, 0xD4, 0x00, 0x32, 0x40, ++0xD8, 0x00, 0x32, 0x40, 0x33, 0x4A, 0x13, 0x68, 0xB0, 0xEB, 0x13, 0x6F, 0x70, 0xB5, 0x04, 0x46, 0x46, 0xD8, 0x0F, 0x28, ++0x24, 0xD8, 0x30, 0x4B, 0x30, 0x4D, 0x31, 0x49, 0x31, 0x48, 0x4F, 0xF0, 0xFF, 0x32, 0x1A, 0x60, 0xA3, 0x10, 0x2A, 0x60, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x00, 0xD1, 0xF8, 0x54, 0x34, 0x04, 0xF0, 0x03, 0x01, 0x98, 0x47, 0x2B, 0x4A, ++0x2B, 0x49, 0x2C, 0x4E, 0x2C, 0x4D, 0x2D, 0x48, 0x24, 0x04, 0x00, 0x23, 0x44, 0xF0, 0x80, 0x44, 0x33, 0x60, 0x2B, 0x60, ++0x13, 0x60, 0x03, 0x60, 0x0A, 0x46, 0x0C, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0x70, 0xBD, 0xA0, 0xF1, 0x10, 0x05, ++0x25, 0x48, 0x4F, 0xF4, 0x1E, 0x73, 0xED, 0xB2, 0x03, 0xFB, 0x05, 0x05, 0x28, 0x46, 0x95, 0xF8, 0x22, 0x60, 0xFD, 0xF7, ++0xD3, 0xFF, 0x1A, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x06, 0x36, 0x96, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0xE8, 0xD0, ++0x28, 0x8D, 0xEB, 0x8C, 0x11, 0x49, 0x12, 0x4A, 0x43, 0xEA, 0x00, 0x43, 0x0B, 0x60, 0x6B, 0x8D, 0x13, 0x60, 0xCC, 0xE7, ++0x13, 0x68, 0x15, 0x68, 0x0F, 0x48, 0x0E, 0x4A, 0x1B, 0x0E, 0x01, 0x33, 0xE3, 0x1A, 0x61, 0x1E, 0xA1, 0xEB, 0x15, 0x61, ++0x03, 0xEB, 0xD3, 0x73, 0x5B, 0x10, 0x4F, 0xF4, 0xA4, 0x64, 0x01, 0xF0, 0x01, 0x01, 0x04, 0xFB, 0x03, 0x00, 0x04, 0x31, ++0xBD, 0xE8, 0x70, 0x40, 0xD2, 0xF8, 0x54, 0x34, 0x18, 0x47, 0x00, 0xBF, 0xD8, 0x00, 0x32, 0x40, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xB4, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, ++0xAC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0x68, 0x65, 0x17, 0x00, 0xF0, 0xB4, 0x0E, 0x49, ++0x0E, 0x4F, 0x0F, 0x4E, 0x0F, 0x4D, 0x10, 0x4C, 0x4F, 0xF0, 0xFF, 0x32, 0x00, 0xF1, 0x10, 0x03, 0x0E, 0x48, 0x3A, 0x60, ++0xDB, 0xB2, 0x0A, 0x60, 0x00, 0x21, 0x01, 0x60, 0x1B, 0x04, 0x18, 0x30, 0x43, 0xF0, 0x80, 0x43, 0x31, 0x60, 0x02, 0x46, ++0x29, 0x60, 0x21, 0x60, 0x03, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0xF0, 0xBC, 0x70, 0x47, 0xC0, 0x00, 0x32, 0x40, ++0xBC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0xB4, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, ++0x08, 0xB5, 0x4F, 0xF0, 0x80, 0x60, 0x0A, 0xF0, 0xA5, 0xFE, 0x00, 0x21, 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x46, 0x0A, 0xF0, ++0x89, 0xBC, 0x00, 0xBF, 0x14, 0x4B, 0x15, 0x49, 0x1A, 0x68, 0x22, 0xF0, 0x02, 0x02, 0xF0, 0xB4, 0x1A, 0x60, 0x1A, 0x68, ++0x12, 0x4F, 0x13, 0x4E, 0x13, 0x4D, 0x14, 0x4C, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x4F, 0xF4, 0x40, 0x72, 0x3A, 0x60, ++0x07, 0x68, 0x82, 0x88, 0x00, 0x20, 0x30, 0x60, 0x28, 0x60, 0x27, 0x60, 0x0E, 0x4C, 0x0A, 0x60, 0x19, 0x68, 0x62, 0x68, ++0x0D, 0x4D, 0xA6, 0xF5, 0x00, 0x46, 0x44, 0x3E, 0x2A, 0x43, 0x21, 0xF4, 0xE0, 0x61, 0x19, 0x60, 0x25, 0x60, 0x32, 0x60, ++0xF0, 0xBC, 0xFC, 0xF7, 0x57, 0xBE, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x14, 0x00, 0x32, 0x40, 0x1C, 0x00, 0x32, 0x40, ++0xA4, 0x80, 0x32, 0x40, 0xA8, 0x80, 0x32, 0x40, 0x10, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x8C, 0x84, 0x03, 0x35, ++0x0B, 0x49, 0x0C, 0x48, 0x38, 0xB5, 0x02, 0x68, 0x4B, 0x68, 0x0B, 0x4C, 0x0B, 0x4D, 0x42, 0xF0, 0x02, 0x02, 0x23, 0x43, ++0x02, 0x60, 0x0C, 0x60, 0x00, 0x20, 0x2B, 0x60, 0xFC, 0xF7, 0x36, 0xFE, 0x07, 0x4B, 0x08, 0x49, 0x08, 0x4A, 0x19, 0x60, ++0x13, 0x68, 0x0B, 0x43, 0x13, 0x60, 0x38, 0xBD, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x8C, 0xA4, 0x07, 0x35, ++0x60, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x74, 0x80, 0x32, 0x40, 0x0D, 0x49, 0x0E, 0x48, ++0x38, 0xB5, 0x02, 0x68, 0x4B, 0x68, 0x0D, 0x4C, 0x0D, 0x4D, 0x22, 0xF0, 0x02, 0x02, 0x23, 0x43, 0x02, 0x60, 0x0C, 0x60, ++0x00, 0x20, 0x2B, 0x60, 0xFC, 0xF7, 0x10, 0xFE, 0x09, 0x4B, 0x0A, 0x4A, 0x0A, 0x49, 0x19, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x38, 0xBD, 0x00, 0xBF, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, ++0x8C, 0x84, 0x03, 0x35, 0x60, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, ++0x00, 0xEB, 0x80, 0x03, 0xC0, 0xEB, 0x03, 0x10, 0x04, 0x4B, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0x90, 0xF8, 0xA5, 0x01, ++0x21, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x68, 0x65, 0x17, 0x00, 0x00, 0xEB, 0x80, 0x03, 0xC0, 0xEB, 0x03, 0x10, ++0x04, 0x4B, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0x90, 0xF8, 0xA4, 0x01, 0x21, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, ++0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x37, 0x4A, 0x37, 0x4B, 0x92, 0xF8, 0x30, 0x10, 0x1B, 0x68, 0x00, 0x29, 0x45, 0xD1, ++0x00, 0x28, 0x40, 0xD0, 0x9B, 0xB2, 0x01, 0x21, 0x80, 0xEA, 0xE0, 0x76, 0x00, 0x28, 0x4F, 0xEA, 0x83, 0x23, 0x82, 0xF8, ++0x30, 0x10, 0xA6, 0xEB, 0xE0, 0x76, 0x4E, 0xDD, 0xB6, 0xEB, 0x53, 0x0F, 0x23, 0xFA, 0x01, 0xF4, 0x98, 0xBF, 0x04, 0x46, ++0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x29, 0x49, 0x01, 0x20, 0x08, 0x60, 0x28, 0x4D, 0x29, 0x4F, ++0x29, 0x68, 0x29, 0x48, 0x01, 0x31, 0x00, 0x68, 0x29, 0x60, 0x39, 0x69, 0x00, 0x2C, 0x4F, 0xEA, 0x40, 0x17, 0x01, 0xEB, ++0x40, 0x11, 0x4F, 0xEA, 0x93, 0x00, 0x25, 0xDD, 0xB8, 0x42, 0x1A, 0xD8, 0x64, 0x36, 0xDB, 0x1B, 0x9E, 0x42, 0x31, 0xD9, ++0x20, 0x4B, 0x94, 0x62, 0x09, 0x1A, 0xD3, 0xF8, 0xE0, 0x31, 0x1F, 0x48, 0x98, 0x47, 0x2B, 0x68, 0x43, 0xB1, 0x18, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x1B, 0xB9, 0x12, 0xB1, 0x62, 0xB6, 0x00, 0xE0, 0x04, 0x46, 0x20, 0x46, 0xF8, 0xBD, ++0x00, 0x24, 0x20, 0x46, 0xF8, 0xBD, 0x15, 0x4E, 0x94, 0x62, 0x19, 0x44, 0x09, 0x1A, 0xD6, 0xF8, 0xE0, 0x31, 0x13, 0x48, ++0x98, 0x47, 0xE6, 0xE7, 0x30, 0x44, 0xB8, 0x42, 0x0E, 0xD3, 0x0F, 0x4B, 0x0F, 0x48, 0xD3, 0xF8, 0xE0, 0x31, 0x94, 0x62, ++0x64, 0x31, 0x98, 0x47, 0xDB, 0xE7, 0x5C, 0x08, 0xB6, 0xEB, 0x53, 0x0F, 0x8C, 0xBF, 0x64, 0x42, 0x04, 0x46, 0xAF, 0xE7, ++0x20, 0x46, 0xFE, 0xF7, 0x57, 0xFD, 0xD0, 0xE7, 0x98, 0x9C, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x40, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xB8, 0x9C, 0x17, 0x00, ++0x13, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x0E, 0xDB, 0x11, 0x4B, 0xDB, 0x7F, 0x2B, 0xB1, ++0x10, 0x4A, 0x93, 0x7C, 0x52, 0x7C, 0x13, 0x44, 0x01, 0x2B, 0x11, 0xDD, 0x0E, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, ++0x60, 0x31, 0x18, 0x47, 0x00, 0x20, 0x0A, 0xF0, 0xED, 0xFB, 0x03, 0x28, 0xEB, 0xD0, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF2, ++0x06, 0x72, 0x0C, 0xF0, 0x25, 0xFA, 0xE4, 0xE7, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x0A, 0xF0, 0x36, 0xBB, ++0x38, 0x36, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC4, 0x9A, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x39, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x61, 0xDB, ++0x37, 0x49, 0x04, 0x20, 0x0B, 0xF0, 0xDC, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x34, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0xFC, 0x80, 0x32, 0x4C, 0xD8, 0xF8, 0x00, 0x30, 0x32, 0x4D, 0x01, 0x33, 0x00, 0x22, ++0xC8, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x22, 0x60, 0x2F, 0x69, 0x03, 0xF0, 0x0F, 0x09, 0x47, 0xF2, 0x30, 0x56, 0x05, 0xE0, ++0xF6, 0xF7, 0x22, 0xFB, 0x2B, 0x69, 0xDB, 0x1B, 0xB3, 0x42, 0x2C, 0xD8, 0x23, 0x68, 0x19, 0x07, 0xF6, 0xD1, 0x28, 0x4A, ++0x28, 0x48, 0x53, 0x68, 0x28, 0x49, 0x04, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x53, 0x60, 0x0B, 0x68, 0xB9, 0xF1, 0x00, 0x0F, ++0x22, 0xD1, 0x25, 0x4B, 0x25, 0x49, 0x04, 0x20, 0x18, 0x60, 0x0B, 0xF0, 0xA7, 0xFF, 0x24, 0x4B, 0x93, 0xF8, 0x5A, 0x30, ++0x0B, 0xBB, 0x03, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0xE1, 0xFA, 0x21, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x21, 0x51, 0x82, ++0x3B, 0xB1, 0x15, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, ++0xF8, 0x83, 0x1A, 0x49, 0x04, 0x20, 0x0B, 0xF0, 0x8B, 0xFF, 0xC4, 0xE7, 0x23, 0x40, 0x5A, 0x07, 0xD9, 0xD4, 0x02, 0x68, ++0x0B, 0x68, 0x13, 0x40, 0x5B, 0x07, 0xFA, 0xD5, 0xD3, 0xE7, 0xF6, 0xF7, 0x07, 0xFB, 0xDA, 0xE7, 0x00, 0x20, 0x0A, 0xF0, ++0x65, 0xFB, 0x04, 0x28, 0x98, 0xD1, 0x10, 0x49, 0x10, 0x48, 0x40, 0xF2, 0x14, 0x72, 0x0C, 0xF0, 0x9D, 0xF9, 0x91, 0xE7, ++0x38, 0x36, 0x17, 0x00, 0x14, 0x9B, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x1C, 0x9E, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x28, 0x9B, 0x15, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x5C, 0x9A, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x9A, 0x15, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x24, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x31, 0xDB, 0x00, 0x20, ++0x0A, 0xF0, 0x32, 0xFB, 0x02, 0x28, 0x05, 0xD0, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0x82, 0xBA, ++0x1C, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x19, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x19, 0x4C, 0x23, 0x68, 0x4F, 0xF0, 0x80, 0x60, 0x01, 0x33, 0x23, 0x60, 0x0A, 0xF0, 0x85, 0xFC, 0x16, 0x4B, ++0x1B, 0x68, 0x5B, 0x07, 0x02, 0xD5, 0x15, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xDC, 0xD0, 0x0F, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x00, 0x2B, 0xD6, 0xD1, 0x00, 0x2A, 0xD4, 0xD0, 0x62, 0xB6, 0xD2, 0xE7, 0x00, 0x20, ++0x0A, 0xF0, 0x00, 0xFB, 0x03, 0x28, 0x04, 0xD0, 0x00, 0x20, 0x0A, 0xF0, 0xFB, 0xFA, 0x00, 0x28, 0xC3, 0xD1, 0x09, 0x49, ++0x09, 0x48, 0x40, 0xF2, 0x4F, 0x72, 0x0C, 0xF0, 0x33, 0xF9, 0xBC, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x3C, 0x9B, 0x15, 0x00, 0x08, 0xB5, 0x00, 0x20, 0x0A, 0xF0, 0xDE, 0xFA, 0x04, 0x28, 0x00, 0xD0, 0x08, 0xBD, 0xBD, 0xE8, ++0x08, 0x40, 0x01, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0x2D, 0xBA, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x78, 0xA0, ++0xDA, 0xF8, 0x1C, 0x33, 0x17, 0x46, 0x05, 0x46, 0x0E, 0x46, 0x98, 0x47, 0x04, 0x46, 0x60, 0xBB, 0x96, 0xF8, 0x00, 0x90, ++0x16, 0x4A, 0x95, 0xF8, 0x19, 0x80, 0xDA, 0xF8, 0xB0, 0x31, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x09, 0x29, 0x41, 0x46, ++0x89, 0xF8, 0x5D, 0x02, 0xA9, 0xF8, 0x5E, 0x02, 0x30, 0x78, 0x98, 0x47, 0x38, 0x70, 0xD9, 0xF8, 0x2C, 0x30, 0x2B, 0xB1, ++0xDA, 0xF8, 0xB0, 0x21, 0x93, 0xF8, 0x23, 0x00, 0x69, 0x7E, 0x90, 0x47, 0x0A, 0x49, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x08, 0x11, 0x91, 0xF8, 0x62, 0x30, 0x43, 0xB9, 0x33, 0x78, 0x81, 0xF8, 0x6C, 0x30, 0x6B, 0x7F, 0x81, 0xF8, 0x6D, 0x30, ++0xAB, 0x7F, 0x81, 0xF8, 0x6E, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x7C, 0x4E, 0x7D, 0x4C, 0x4F, 0xF4, 0x1E, 0x77, 0x07, 0xFB, 0x00, 0x67, ++0x4F, 0xF0, 0x4F, 0x08, 0x46, 0x23, 0x18, 0xFB, 0x00, 0x38, 0x97, 0xF8, 0x22, 0xB0, 0x85, 0xB0, 0x05, 0x46, 0x06, 0xEB, ++0xC8, 0x08, 0x4F, 0xF0, 0x00, 0x09, 0xD7, 0xF8, 0x08, 0x32, 0x5F, 0xFA, 0x89, 0xFA, 0xA8, 0xF1, 0x28, 0x01, 0x4F, 0xF0, ++0x80, 0x42, 0x09, 0xF1, 0x01, 0x09, 0x50, 0x46, 0x13, 0xB1, 0xD4, 0xF8, 0x84, 0x33, 0x98, 0x47, 0xD7, 0xF8, 0x30, 0x32, ++0x41, 0x46, 0x08, 0x37, 0x08, 0xF1, 0x08, 0x08, 0x4F, 0xF0, 0x80, 0x42, 0x50, 0x46, 0x13, 0xB1, 0xD4, 0xF8, 0x84, 0x33, ++0x98, 0x47, 0xB9, 0xF1, 0x05, 0x0F, 0xE0, 0xD1, 0x65, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x33, 0x93, 0xF8, ++0x62, 0x10, 0xC1, 0xB9, 0xFF, 0x22, 0x83, 0xF8, 0x6C, 0x20, 0xD4, 0xF8, 0xAC, 0x31, 0x28, 0x46, 0x98, 0x47, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x05, 0x66, 0xF3, 0x6A, 0x23, 0xB1, 0x93, 0xF8, 0x23, 0x00, 0xD4, 0xF8, 0xAC, 0x31, 0x98, 0x47, ++0xD4, 0xF8, 0x24, 0x33, 0x28, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x4F, 0xF4, 0x1E, 0x78, 0x08, 0xFB, ++0x05, 0x62, 0x92, 0xF8, 0x24, 0x90, 0xB9, 0xF1, 0x01, 0x0F, 0x02, 0xD0, 0x02, 0x29, 0xED, 0xD0, 0xDD, 0xE7, 0x93, 0xF8, ++0xDE, 0x20, 0x01, 0x3A, 0xD2, 0xB2, 0x83, 0xF8, 0xDE, 0x20, 0x00, 0x2A, 0xF4, 0xD1, 0x93, 0xF8, 0x63, 0xA0, 0x0A, 0xF1, ++0x0A, 0x0A, 0x5F, 0xFA, 0x8A, 0xFA, 0x08, 0xFB, 0x0A, 0xF3, 0x06, 0xEB, 0x03, 0x08, 0x00, 0x93, 0x98, 0xF8, 0x24, 0x30, ++0x73, 0xB9, 0x44, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x37, 0x38, 0x46, 0x97, 0xF8, 0x63, 0x10, 0xE3, 0x68, ++0x0A, 0x31, 0xC9, 0xB2, 0x98, 0x47, 0x97, 0xF8, 0x62, 0x10, 0xD7, 0xE7, 0x02, 0x23, 0x0C, 0x21, 0x49, 0x20, 0x01, 0x92, ++0x09, 0xF0, 0x64, 0xFF, 0x01, 0x9A, 0x88, 0xF8, 0x24, 0x20, 0x80, 0xF8, 0x00, 0xA0, 0x42, 0x70, 0x09, 0xF0, 0x8C, 0xFF, ++0x98, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0xDE, 0xD1, 0x98, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0xDA, 0xD8, 0x98, 0xF8, 0x22, 0x00, ++0x31, 0x4B, 0xCD, 0xF8, 0x04, 0x90, 0x9E, 0x22, 0xA4, 0x21, 0x11, 0xFB, 0x00, 0x21, 0x2D, 0x4A, 0x03, 0x95, 0x07, 0xFB, ++0x00, 0x27, 0x2B, 0x48, 0x02, 0x97, 0x4F, 0xF0, 0x4F, 0x0C, 0x46, 0x27, 0x1C, 0xFB, 0x0A, 0x77, 0x00, 0xEB, 0xC1, 0x0A, ++0x00, 0x99, 0x28, 0x4A, 0x02, 0x9D, 0xC1, 0x46, 0x88, 0x46, 0x06, 0xEB, 0xC7, 0x07, 0x98, 0x44, 0xD9, 0xF8, 0x08, 0x12, ++0x31, 0xB3, 0xEF, 0xF3, 0x10, 0x81, 0xCB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x21, 0x4B, 0x01, 0x99, 0x19, 0x60, 0x11, 0x68, ++0xA7, 0xF1, 0x28, 0x00, 0x4B, 0x1C, 0xAA, 0xF1, 0x28, 0x01, 0x13, 0x60, 0x00, 0x90, 0x0A, 0xF0, 0xA1, 0xFC, 0xD9, 0xF8, ++0x08, 0x12, 0xD9, 0xF8, 0x0C, 0x32, 0x00, 0x98, 0xC5, 0xF8, 0xC8, 0x14, 0xC5, 0xF8, 0xCC, 0x34, 0x0A, 0xF0, 0xA0, 0xFB, ++0x14, 0x4A, 0x11, 0x68, 0x48, 0x1E, 0x29, 0xB1, 0x13, 0x4B, 0x10, 0x60, 0x19, 0x68, 0x08, 0xB9, 0x01, 0xB1, 0x62, 0xB6, ++0xD9, 0xF8, 0x30, 0x32, 0x50, 0x46, 0x39, 0x46, 0x09, 0xF1, 0x08, 0x09, 0x0A, 0xF1, 0x08, 0x0A, 0x08, 0x35, 0x2B, 0xB1, ++0x0A, 0xF0, 0x80, 0xFC, 0x38, 0x46, 0x0A, 0xF0, 0x87, 0xFB, 0x08, 0x4A, 0x08, 0x37, 0x47, 0x45, 0xC2, 0xD1, 0x40, 0x20, ++0x03, 0x9D, 0x0A, 0xF0, 0xE1, 0xFA, 0x7A, 0xE7, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xC0, 0x67, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x23, 0x04, 0x46, 0x00, 0x22, ++0x06, 0x21, 0x43, 0x20, 0x09, 0xF0, 0xE0, 0xFE, 0x94, 0xF8, 0x63, 0x30, 0x03, 0x70, 0xBD, 0xE8, 0x10, 0x40, 0x09, 0xF0, ++0x09, 0xBF, 0x00, 0xBF, 0x70, 0xB5, 0x90, 0xF9, 0x87, 0x30, 0x04, 0x46, 0x90, 0xF9, 0x86, 0x00, 0x94, 0xF8, 0x88, 0x20, ++0x94, 0xF8, 0x89, 0x60, 0x84, 0xF8, 0x86, 0x10, 0xBB, 0xB1, 0x0D, 0x46, 0x52, 0xB2, 0xAE, 0xB9, 0x88, 0x42, 0x10, 0xDD, ++0x9B, 0x1A, 0x99, 0x42, 0x0D, 0xDA, 0x01, 0x26, 0x00, 0x22, 0x03, 0x23, 0x0C, 0x21, 0x57, 0x20, 0x09, 0xF0, 0xBC, 0xFE, ++0x94, 0xF8, 0x63, 0x20, 0x02, 0x70, 0x46, 0x70, 0x85, 0x70, 0x09, 0xF0, 0xE5, 0xFE, 0x84, 0xF8, 0x89, 0x60, 0x70, 0xBD, ++0x01, 0x2E, 0xFA, 0xD1, 0x88, 0x42, 0xF8, 0xDA, 0x13, 0x44, 0x99, 0x42, 0xF5, 0xDD, 0x00, 0x26, 0xE6, 0xE7, 0x00, 0xBF, ++0x14, 0x4B, 0x93, 0xF9, 0x00, 0x20, 0x22, 0xB3, 0x30, 0xB4, 0x9C, 0x78, 0x90, 0xF9, 0x86, 0x00, 0x93, 0xF9, 0x01, 0x50, ++0x6C, 0xB9, 0x88, 0x42, 0x08, 0xDD, 0x52, 0x1B, 0x91, 0x42, 0x05, 0xDA, 0x0D, 0x49, 0x0A, 0x68, 0x42, 0xF4, 0x00, 0x72, ++0x0A, 0x60, 0x01, 0x24, 0x9C, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x01, 0x2C, 0xFA, 0xD1, 0x88, 0x42, 0xF8, 0xDA, 0x2A, 0x44, ++0x91, 0x42, 0xF5, 0xDD, 0x05, 0x49, 0x0A, 0x68, 0x00, 0x24, 0x22, 0xF4, 0x00, 0x72, 0x0A, 0x60, 0x9C, 0x70, 0x30, 0xBC, ++0x70, 0x47, 0x70, 0x47, 0xA4, 0x1F, 0x17, 0x00, 0xB0, 0xB3, 0x33, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x0C, 0x46, 0x06, 0x46, ++0x80, 0x68, 0x91, 0xF8, 0x8B, 0x10, 0xD0, 0xF8, 0x08, 0x80, 0x60, 0x6F, 0xB6, 0xF8, 0x1C, 0xB0, 0xDF, 0xF8, 0x1C, 0xA1, ++0x87, 0xB0, 0x00, 0x25, 0x05, 0x90, 0x03, 0x92, 0x1F, 0x46, 0x84, 0xF8, 0x78, 0x50, 0x49, 0xB1, 0x94, 0xF8, 0x63, 0x00, ++0xDA, 0xF8, 0xC0, 0x31, 0x01, 0x21, 0x98, 0x47, 0xA4, 0xF8, 0x8A, 0x50, 0x84, 0xF8, 0x8C, 0x50, 0x3A, 0x4B, 0x3B, 0x4D, ++0x1B, 0x68, 0x22, 0x6F, 0x5B, 0x68, 0x01, 0x21, 0x84, 0xF8, 0x85, 0x10, 0x29, 0x69, 0x5B, 0x1A, 0xD3, 0x42, 0x58, 0xD4, ++0x96, 0xF9, 0x2D, 0x10, 0x04, 0x91, 0xE8, 0xF7, 0x35, 0xFB, 0x34, 0x4B, 0x04, 0x99, 0x5B, 0x7C, 0x01, 0x2B, 0x59, 0xD0, ++0xDA, 0xF8, 0x9C, 0x31, 0x20, 0x46, 0xAB, 0xF1, 0x24, 0x05, 0x98, 0x47, 0xAD, 0xB2, 0x00, 0x22, 0x04, 0x21, 0x08, 0xF1, ++0x20, 0x00, 0x0A, 0xF0, 0x19, 0xFC, 0x00, 0x23, 0x01, 0x2D, 0x3B, 0x60, 0x08, 0xF1, 0x24, 0x02, 0x22, 0xD9, 0x04, 0x96, ++0x3E, 0x46, 0x27, 0x46, 0x2C, 0x46, 0x09, 0xE0, 0x32, 0x60, 0xC9, 0xF5, 0x7F, 0x42, 0xFE, 0x32, 0x14, 0x44, 0xA4, 0xB2, ++0x01, 0x2C, 0x05, 0xEB, 0x09, 0x02, 0x10, 0xD9, 0x92, 0xF8, 0x01, 0x90, 0x15, 0x46, 0x09, 0xF1, 0x01, 0x0C, 0xA4, 0x45, ++0x15, 0xF8, 0x02, 0x1B, 0x07, 0xDA, 0x05, 0x29, 0xEA, 0xD0, 0x02, 0x46, 0x49, 0x46, 0x28, 0x46, 0x0A, 0xF0, 0xF4, 0xFB, ++0xE5, 0xE7, 0x3C, 0x46, 0x37, 0x46, 0x04, 0x9E, 0x60, 0x67, 0x3B, 0x68, 0x01, 0x93, 0x03, 0x9B, 0x00, 0x93, 0x32, 0x46, ++0x59, 0x46, 0x40, 0x46, 0x23, 0x46, 0xDA, 0xF8, 0xD0, 0x51, 0xA8, 0x47, 0x04, 0x20, 0x0A, 0xF0, 0xA1, 0xF8, 0x01, 0x28, ++0x04, 0xD0, 0x60, 0x6F, 0x05, 0x9B, 0xC0, 0x1A, 0x18, 0xBF, 0x01, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x22, ++0x94, 0xF8, 0x6C, 0x00, 0x11, 0x46, 0xF7, 0xF7, 0x75, 0xF9, 0x00, 0x28, 0x9E, 0xD1, 0x2B, 0x69, 0x23, 0x67, 0x9B, 0xE7, ++0x20, 0x46, 0xFF, 0xF7, 0x3F, 0xFF, 0x04, 0x99, 0xA0, 0xE7, 0x00, 0xBF, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x00, 0x22, 0x05, 0x46, 0x0C, 0x46, 0x02, 0x23, 0x0C, 0x21, ++0x59, 0x20, 0x09, 0xF0, 0xD3, 0xFD, 0x05, 0x70, 0x44, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x09, 0xF0, 0xFD, 0xBD, 0x00, 0xBF, ++0x08, 0xB5, 0x03, 0x4B, 0x08, 0x46, 0xD3, 0xF8, 0x74, 0x31, 0x98, 0x47, 0x01, 0x20, 0x08, 0xBD, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0xB5, 0x04, 0x4A, 0x08, 0x78, 0xD2, 0xF8, 0x5C, 0x22, 0x19, 0x46, 0x90, 0x47, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x0E, 0x46, 0x2F, 0x20, 0x19, 0x46, 0x02, 0x23, 0x34, 0x78, 0x09, 0xF0, 0xAE, 0xFD, ++0x0D, 0x49, 0x76, 0x78, 0x0D, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x05, 0x46, 0x07, 0xFB, 0x04, 0x10, 0x29, 0x46, 0x90, 0xF8, ++0x65, 0x20, 0x80, 0xF8, 0x66, 0x60, 0x01, 0xF8, 0x01, 0x2F, 0x7F, 0x22, 0xD3, 0xF8, 0x40, 0x33, 0x80, 0xF8, 0x65, 0x20, ++0x2A, 0x46, 0x98, 0x47, 0x28, 0x46, 0x09, 0xF0, 0xC5, 0xFD, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x18, 0x46, 0x38, 0xB5, 0x0D, 0x46, 0x03, 0x23, 0x01, 0x46, 0x0B, 0x20, 0x09, 0xF0, 0x86, 0xFD, ++0x06, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xC4, 0x31, 0xA2, 0x1C, 0x61, 0x1C, 0x28, 0x46, 0x98, 0x47, 0x20, 0x70, 0x20, 0x46, ++0x09, 0xF0, 0xAA, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x0E, 0x4E, 0x0D, 0x46, 0x1C, 0x46, ++0x19, 0x46, 0x28, 0x46, 0xD6, 0xF8, 0x80, 0x30, 0x17, 0x46, 0x98, 0x47, 0x0C, 0xB9, 0x00, 0x20, 0xF8, 0xBD, 0x06, 0x46, ++0x3A, 0x46, 0x21, 0x46, 0x03, 0x23, 0x47, 0x20, 0x09, 0xF0, 0x62, 0xFD, 0x2A, 0x78, 0x02, 0x70, 0x04, 0x22, 0x46, 0x70, ++0x82, 0x70, 0x09, 0xF0, 0x8B, 0xFD, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x0C, 0x46, ++0x76, 0x20, 0x19, 0x46, 0x0C, 0x23, 0x09, 0xF0, 0x4F, 0xFD, 0x23, 0x78, 0x0C, 0x4A, 0x0D, 0x4C, 0x4F, 0xF4, 0x1E, 0x71, ++0x01, 0xFB, 0x03, 0x23, 0x4F, 0xF4, 0xA4, 0x65, 0x93, 0xF8, 0x22, 0x20, 0xD3, 0xF8, 0x48, 0x11, 0x05, 0xFB, 0x02, 0x42, ++0x49, 0x69, 0x92, 0xF8, 0x86, 0x20, 0x02, 0x72, 0x00, 0x24, 0xC0, 0xE9, 0x00, 0x14, 0x09, 0xF0, 0x67, 0xFD, 0x20, 0x46, ++0x38, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xF0, 0xB5, 0x00, 0x22, 0x0D, 0x46, 0x85, 0xB0, ++0x01, 0x23, 0x0C, 0x21, 0x53, 0x20, 0x09, 0xF0, 0x27, 0xFD, 0x01, 0x22, 0x02, 0x70, 0x04, 0x46, 0x28, 0x78, 0x04, 0x28, ++0x28, 0xD8, 0x1D, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x03, 0xB3, 0xAB, 0x78, ++0x23, 0xB3, 0x19, 0x4A, 0x19, 0x49, 0x16, 0x68, 0x09, 0x69, 0x17, 0x68, 0xB0, 0xF8, 0xD2, 0x20, 0xC9, 0x1B, 0x92, 0x02, ++0xEF, 0x68, 0xB6, 0xFB, 0xF2, 0xF6, 0x06, 0xFB, 0x02, 0x22, 0x14, 0x4E, 0x39, 0x44, 0x6F, 0x68, 0xD6, 0xF8, 0x04, 0x62, ++0x01, 0x97, 0x0A, 0x44, 0xA9, 0x68, 0x00, 0x91, 0x02, 0x92, 0xEA, 0x78, 0x00, 0x21, 0xB0, 0x47, 0xFF, 0x28, 0x01, 0xD0, ++0x00, 0x23, 0x23, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x25, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, 0x08, 0x4B, 0x69, 0x78, ++0xD3, 0xF8, 0x08, 0x32, 0x98, 0x47, 0x20, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x19, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, ++0x18, 0x88, 0x17, 0x00, 0xA4, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x19, 0x46, ++0x05, 0x20, 0x1C, 0x23, 0x09, 0xF0, 0xD8, 0xFC, 0x2C, 0x4D, 0x2D, 0x4B, 0x03, 0x60, 0x2A, 0x68, 0x2C, 0x4B, 0x42, 0x60, ++0x1B, 0x68, 0x83, 0x60, 0x0A, 0x22, 0x04, 0x23, 0x83, 0x76, 0x02, 0x83, 0x04, 0x46, 0x00, 0xF1, 0x10, 0x01, 0x0C, 0x30, ++0xE8, 0xF7, 0x9E, 0xF8, 0x26, 0x4B, 0x63, 0x61, 0x2B, 0x68, 0x98, 0x03, 0x24, 0xD4, 0x21, 0x4B, 0x1B, 0x68, 0x99, 0x03, ++0x2C, 0xD4, 0x1F, 0x4B, 0x1B, 0x68, 0x9A, 0x04, 0x03, 0xD5, 0x63, 0x69, 0x43, 0xF4, 0x00, 0x23, 0x63, 0x61, 0xE8, 0xF7, ++0x2F, 0xF9, 0x18, 0xB1, 0x63, 0x69, 0x43, 0xF4, 0x80, 0x33, 0x63, 0x61, 0x17, 0x4B, 0x1B, 0x68, 0x1B, 0x04, 0x22, 0xD4, ++0xE8, 0xF7, 0x2E, 0xF9, 0x63, 0x69, 0x08, 0xB1, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF0, 0x40, 0x53, 0x20, 0x46, 0x63, 0x61, ++0x09, 0xF0, 0xCE, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0xE8, 0xF7, 0x3E, 0xF9, 0x00, 0x28, 0xD6, 0xD0, 0x63, 0x69, 0x43, 0xF4, ++0x00, 0x33, 0x63, 0x61, 0x0A, 0x4B, 0x1B, 0x68, 0x99, 0x03, 0xD2, 0xD5, 0xE8, 0xF7, 0x3A, 0xF9, 0x00, 0x28, 0xCE, 0xD0, ++0x63, 0x69, 0x43, 0xF4, 0x00, 0x13, 0x63, 0x61, 0xC9, 0xE7, 0xE8, 0xF7, 0x03, 0xF9, 0x00, 0x28, 0xD8, 0xD0, 0x63, 0x69, ++0x43, 0xF0, 0x80, 0x43, 0x63, 0x61, 0xD3, 0xE7, 0x04, 0x00, 0x32, 0x40, 0x01, 0x03, 0x04, 0x06, 0x08, 0x00, 0x32, 0x40, ++0x5F, 0xFA, 0x10, 0x00, 0xF0, 0xB5, 0x23, 0x48, 0x4D, 0x79, 0x00, 0x68, 0x8C, 0x79, 0x50, 0xF8, 0x25, 0xC0, 0x21, 0x4F, ++0x0E, 0x68, 0x4F, 0xF4, 0xA4, 0x70, 0x00, 0xFB, 0x04, 0x50, 0x02, 0x30, 0x83, 0xB0, 0x47, 0xF8, 0x20, 0x60, 0x19, 0x46, ++0xBC, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0xCC, 0xF3, 0x0B, 0x03, 0x1B, 0xBB, 0x2C, 0xF4, 0x7F, 0x6C, 0x2C, 0xF0, 0x0F, 0x0C, ++0xC6, 0xF3, 0x0B, 0x06, 0x4C, 0xEA, 0x06, 0x06, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x74, 0x94, 0xF8, 0x64, 0x30, ++0x73, 0xB1, 0x01, 0x2D, 0x1A, 0xD0, 0x02, 0x2D, 0x12, 0xD0, 0xA5, 0xB1, 0x0F, 0x4B, 0x1E, 0x60, 0x0F, 0x4B, 0xD3, 0xF8, ++0xA0, 0x31, 0xCD, 0xE9, 0x00, 0x21, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0x1B, 0x20, 0x09, 0xF0, 0xA5, 0xFC, 0x00, 0x20, ++0x03, 0xB0, 0xF0, 0xBD, 0x66, 0x46, 0xE1, 0xE7, 0x08, 0x4B, 0x1E, 0x60, 0xEC, 0xE7, 0x08, 0x4B, 0x1E, 0x60, 0xE9, 0xE7, ++0x07, 0x4B, 0x1E, 0x60, 0xE6, 0xE7, 0x00, 0xBF, 0xAC, 0x35, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x0C, 0x02, 0x32, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x38, 0xB5, 0x07, 0x48, ++0x8C, 0x78, 0x0D, 0x88, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x04, 0x04, 0x19, 0x46, 0x70, 0x20, 0xA4, 0xF8, 0xBE, 0x54, ++0x09, 0xF0, 0x7A, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0x18, 0x88, 0x17, 0x00, 0x10, 0xB5, 0x08, 0x4C, 0x08, 0x78, 0xD4, 0xF8, ++0xC8, 0x41, 0x82, 0xB0, 0x01, 0x92, 0x00, 0x93, 0xA0, 0x47, 0xDD, 0xE9, 0x00, 0x12, 0x0D, 0x20, 0x09, 0xF0, 0x68, 0xFC, ++0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0x08, 0x78, 0x64, 0x6D, ++0x82, 0xB0, 0x01, 0x92, 0x00, 0x93, 0xA0, 0x47, 0xDD, 0xE9, 0x00, 0x12, 0x3A, 0x20, 0x09, 0xF0, 0x55, 0xFC, 0x00, 0x20, ++0x02, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0C, 0x78, 0x08, 0x46, 0x19, 0x46, 0x24, 0xB1, 0x25, 0x4B, ++0x93, 0xF8, 0xA9, 0x30, 0x00, 0x2B, 0x36, 0xD1, 0x23, 0x4B, 0x24, 0x4E, 0x24, 0x4D, 0x00, 0x24, 0x1C, 0x70, 0x34, 0x68, ++0x24, 0xF0, 0x00, 0x74, 0x34, 0x60, 0x6C, 0x6F, 0x24, 0xF0, 0x10, 0x04, 0x6C, 0x67, 0x1E, 0x4D, 0x2C, 0x68, 0x24, 0xF4, ++0x00, 0x64, 0x2C, 0x60, 0xC4, 0x78, 0x9C, 0x70, 0x84, 0x78, 0x00, 0x25, 0x5D, 0x70, 0xC4, 0xB1, 0x1A, 0x4C, 0x23, 0x68, ++0x43, 0xF0, 0x00, 0x43, 0x23, 0x60, 0x03, 0x79, 0x63, 0xB1, 0x18, 0x4C, 0x85, 0x68, 0x18, 0x4B, 0x25, 0x60, 0x1C, 0x68, ++0xC4, 0xF3, 0x13, 0x04, 0x1C, 0x60, 0xC4, 0x68, 0x18, 0x68, 0x40, 0xEA, 0x04, 0x50, 0x18, 0x60, 0x66, 0x20, 0x09, 0xF0, ++0x17, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x0E, 0x4C, 0x23, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x23, 0x60, 0xE5, 0xE7, 0x08, 0x4B, ++0x08, 0x4E, 0x09, 0x4D, 0x01, 0x24, 0x1C, 0x70, 0x34, 0x68, 0x44, 0xF0, 0x00, 0x74, 0x34, 0x60, 0x6C, 0x6F, 0x44, 0xF0, ++0x10, 0x04, 0x6C, 0x67, 0xC7, 0xE7, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, ++0x00, 0x00, 0x50, 0x40, 0x48, 0x30, 0x34, 0x40, 0xF4, 0x00, 0x60, 0x40, 0xF8, 0x00, 0x60, 0x40, 0x70, 0xB5, 0x08, 0x46, ++0x07, 0x4C, 0x09, 0x68, 0x46, 0x68, 0x05, 0x89, 0xC4, 0xF8, 0xBD, 0x10, 0x78, 0x20, 0x19, 0x46, 0xC4, 0xF8, 0xC1, 0x60, ++0xA4, 0xF8, 0xC5, 0x50, 0x09, 0xF0, 0xE2, 0xFB, 0x00, 0x20, 0x70, 0xBD, 0x2C, 0x19, 0x17, 0x00, 0x38, 0xB5, 0x08, 0x46, ++0x0E, 0x49, 0x44, 0x78, 0x0C, 0x70, 0x84, 0x78, 0x4C, 0x70, 0xC4, 0x78, 0x8C, 0x70, 0x0C, 0x4C, 0x05, 0x79, 0x41, 0x79, ++0x61, 0x70, 0x25, 0x70, 0xC1, 0x79, 0x85, 0x79, 0xA5, 0x70, 0xE1, 0x70, 0x08, 0x4C, 0x41, 0x68, 0x05, 0x68, 0xC4, 0xF8, ++0xCB, 0x10, 0x7A, 0x20, 0x19, 0x46, 0xC4, 0xF8, 0xC7, 0x50, 0x09, 0xF0, 0xC1, 0xFB, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xBF, ++0x68, 0x25, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x48, 0x09, 0x68, 0x01, 0x60, ++0x19, 0x46, 0x72, 0x20, 0x09, 0xF0, 0xB0, 0xFB, 0x00, 0x20, 0x08, 0xBD, 0x34, 0x00, 0x32, 0x40, 0x30, 0xB5, 0x19, 0x46, ++0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x16, 0x4C, ++0x16, 0x4D, 0x23, 0x68, 0x01, 0x33, 0xCD, 0xE9, 0x00, 0x21, 0x23, 0x60, 0x08, 0xF0, 0x12, 0xFA, 0xE7, 0xF7, 0x96, 0xFF, ++0x09, 0xF0, 0x02, 0xFB, 0x0E, 0xF0, 0x22, 0xF8, 0xD5, 0xF8, 0x10, 0x34, 0x98, 0x47, 0xD5, 0xF8, 0xA8, 0x31, 0x98, 0x47, ++0x23, 0x68, 0xDD, 0xE9, 0x00, 0x21, 0x33, 0xB1, 0x08, 0x48, 0x01, 0x3B, 0x00, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x00, 0xB1, ++0x62, 0xB6, 0x01, 0x20, 0x09, 0xF0, 0x7E, 0xFB, 0x00, 0x21, 0x08, 0x46, 0x09, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x03, 0xB0, ++0x30, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x18, 0x46, ++0x21, 0x4E, 0x02, 0x23, 0x0D, 0x46, 0x01, 0x46, 0x25, 0x20, 0x09, 0xF0, 0xFF, 0xFA, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0x46, 0x0C, 0xDB, 0x1C, 0x4B, 0x28, 0x46, 0xD3, 0xF8, 0xB8, 0x31, 0x98, 0x47, 0x00, 0x25, 0x60, 0x70, ++0x25, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x1E, 0xFB, 0x28, 0x46, 0x70, 0xBD, 0x2B, 0x78, 0x05, 0x2B, 0x19, 0xD8, 0x2B, 0x79, ++0x20, 0x2B, 0x0A, 0xD8, 0x95, 0xF8, 0x28, 0x30, 0x05, 0x2B, 0xE8, 0xD9, 0x11, 0x49, 0x12, 0x48, 0x40, 0xF2, 0xFB, 0x62, ++0x0B, 0xF0, 0xBE, 0xFB, 0xE1, 0xE7, 0x0E, 0x49, 0x0F, 0x48, 0x4F, 0xF4, 0xDF, 0x62, 0x0B, 0xF0, 0xB7, 0xFB, 0x33, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE9, 0xDB, 0xD5, 0xE7, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0xF2, 0x62, 0x0B, 0xF0, ++0xAB, 0xFB, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDB, 0xC9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xE4, 0x9B, 0x15, 0x00, 0xBC, 0x9B, 0x15, 0x00, 0x90, 0x9B, 0x15, 0x00, ++0x11, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x70, 0xB5, 0x0C, 0x46, 0x16, 0x46, 0x1D, 0x46, 0x0B, 0xDB, ++0x20, 0x78, 0x0D, 0x4B, 0xD3, 0xF8, 0xB4, 0x31, 0x98, 0x47, 0x32, 0x46, 0x29, 0x46, 0x27, 0x20, 0x09, 0xF0, 0x0A, 0xFB, ++0x00, 0x20, 0x70, 0xBD, 0x08, 0x4B, 0x08, 0x78, 0x1B, 0x68, 0x1B, 0x0E, 0x09, 0x33, 0x98, 0x42, 0xED, 0xDD, 0x06, 0x49, ++0x06, 0x48, 0x40, 0xF2, 0x22, 0x72, 0x0B, 0xF0, 0x75, 0xFB, 0xE5, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xD8, 0x00, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0x14, 0x9C, 0x15, 0x00, 0x16, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x68, ++0x15, 0x4F, 0x0C, 0x46, 0xB0, 0xF9, 0x00, 0x10, 0x25, 0x78, 0x00, 0x29, 0x16, 0x46, 0x98, 0x46, 0x11, 0xDB, 0x4F, 0xF4, ++0xA4, 0x60, 0x00, 0xFB, 0x05, 0x70, 0x62, 0x88, 0xA0, 0xF8, 0x68, 0x20, 0x23, 0x79, 0x80, 0xF8, 0x6A, 0x30, 0x32, 0x46, ++0x41, 0x46, 0x4C, 0x20, 0x09, 0xF0, 0xD4, 0xFA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, ++0x05, 0x72, 0x92, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xE5, 0xD0, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF6, 0x5B, 0x22, 0x0B, 0xF0, ++0x3D, 0xFB, 0xDE, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, ++0x13, 0x4B, 0x70, 0xB5, 0x1B, 0x68, 0x0C, 0x78, 0xB3, 0xF9, 0x00, 0x30, 0x11, 0x4E, 0x00, 0x2B, 0x0D, 0x46, 0x0D, 0xDB, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x63, 0x6A, 0x78, 0x83, 0xF8, 0x87, 0x20, 0xAA, 0x78, 0x83, 0xF8, 0x88, 0x20, ++0x00, 0x20, 0x83, 0xF8, 0x89, 0x00, 0x70, 0xBD, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x63, 0x93, 0xF8, 0x62, 0x30, ++0x00, 0x2B, 0xE9, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF6, 0x78, 0x52, 0x0B, 0xF0, 0x0E, 0xFB, 0xE2, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x20, 0x48, 0x2D, 0xE9, ++0xF0, 0x41, 0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x84, 0xB0, 0x0E, 0x46, 0x15, 0x46, 0x98, 0x46, 0x29, 0xDB, ++0x30, 0x46, 0xE7, 0xF7, 0xAB, 0xFD, 0x00, 0x24, 0x19, 0x4F, 0x00, 0x94, 0x40, 0xF6, 0xB4, 0x13, 0x21, 0x46, 0x1A, 0x46, ++0x20, 0x46, 0xCD, 0xE9, 0x01, 0x44, 0xE7, 0xF7, 0xEB, 0xFD, 0xD7, 0xF8, 0x3C, 0x33, 0x0F, 0x20, 0x98, 0x47, 0x13, 0x4B, ++0xB6, 0xF8, 0x44, 0x20, 0x9A, 0x83, 0x41, 0x46, 0x2A, 0x46, 0x03, 0x20, 0x09, 0xF0, 0x62, 0xFA, 0xD7, 0xF8, 0x60, 0x31, ++0x98, 0x47, 0xD7, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x28, 0x46, 0x02, 0x21, 0x09, 0xF0, 0xEA, 0xFB, 0x20, 0x46, 0x04, 0xB0, ++0xBD, 0xE8, 0xF0, 0x81, 0x10, 0x46, 0x09, 0xF0, 0x8B, 0xFC, 0x00, 0x28, 0xD0, 0xD0, 0x06, 0x49, 0x06, 0x48, 0x4F, 0xF4, ++0xA7, 0x72, 0x0B, 0xF0, 0xC3, 0xFA, 0xC9, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x58, 0x9C, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x46, 0x49, 0x78, 0x16, 0x46, 0x1D, 0x46, 0xE1, 0xB1, ++0x01, 0x29, 0x63, 0x88, 0x3C, 0xD0, 0x02, 0x29, 0x32, 0xD0, 0x03, 0x29, 0x0C, 0xBF, 0x20, 0x48, 0x20, 0x48, 0xA2, 0x88, ++0x18, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x1D, 0xF0, 0x49, 0xFD, 0xE3, 0x88, 0x23, 0xB1, 0x1D, 0x4B, 0x20, 0x78, 0xD3, 0xF8, ++0x80, 0x34, 0x98, 0x47, 0x32, 0x46, 0x29, 0x46, 0x68, 0x20, 0x09, 0xF0, 0x1D, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x04, 0xF1, ++0x08, 0x01, 0x4F, 0xF4, 0x40, 0x72, 0x16, 0x48, 0x1D, 0xF0, 0x34, 0xFD, 0x04, 0xF5, 0x42, 0x71, 0x4F, 0xF4, 0x00, 0x72, ++0x13, 0x48, 0x1D, 0xF0, 0x2D, 0xFD, 0x04, 0xF5, 0xA1, 0x61, 0x80, 0x22, 0x0C, 0x48, 0x1D, 0xF0, 0x27, 0xFD, 0x40, 0x22, ++0x04, 0xF5, 0xB1, 0x61, 0x0A, 0x48, 0x1D, 0xF0, 0x21, 0xFD, 0xD6, 0xE7, 0x0B, 0x48, 0xA2, 0x88, 0x18, 0x44, 0x04, 0xF1, ++0x08, 0x01, 0x1D, 0xF0, 0x19, 0xFD, 0xCE, 0xE7, 0x06, 0x48, 0xA2, 0x88, 0x18, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x1D, 0xF0, ++0x11, 0xFD, 0xC6, 0xE7, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, ++0x1C, 0x16, 0x17, 0x00, 0x38, 0xB5, 0x19, 0x46, 0x81, 0x20, 0x40, 0x23, 0x09, 0xF0, 0x78, 0xF9, 0x00, 0x25, 0x04, 0x46, ++0x08, 0x49, 0x00, 0xF8, 0x01, 0x5B, 0x24, 0x22, 0x1D, 0xF0, 0xF8, 0xFC, 0x23, 0x78, 0x24, 0x33, 0xDB, 0xB2, 0xE2, 0x18, ++0x23, 0x70, 0x20, 0x46, 0x55, 0x70, 0x09, 0xF0, 0x97, 0xF9, 0x28, 0x46, 0x38, 0xBD, 0x00, 0xBF, 0xDC, 0xD1, 0x15, 0x00, ++0x10, 0xB5, 0x82, 0xB0, 0x08, 0x46, 0x1C, 0x46, 0x01, 0x92, 0xFA, 0xF7, 0x83, 0xFA, 0x06, 0x49, 0x4F, 0xF4, 0x80, 0x70, ++0x0B, 0xF0, 0x0E, 0xF8, 0x01, 0x9A, 0x21, 0x46, 0x6C, 0x20, 0x09, 0xF0, 0xB9, 0xF9, 0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, ++0x7C, 0x9C, 0x15, 0x00, 0x25, 0x48, 0x2D, 0xE9, 0xF8, 0x43, 0x00, 0x68, 0xDF, 0xF8, 0xA0, 0x90, 0x0C, 0x46, 0xB0, 0xF9, ++0x00, 0x10, 0x65, 0x79, 0x00, 0x29, 0x17, 0x46, 0x1E, 0x46, 0x2D, 0xDB, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x05, 0xF0, ++0x09, 0xEB, 0x00, 0x08, 0x21, 0x79, 0x98, 0xF8, 0xAC, 0x20, 0x23, 0x68, 0xC8, 0xF8, 0xC4, 0x34, 0x01, 0x2A, 0x88, 0xF8, ++0xC3, 0x14, 0x0A, 0xD1, 0x17, 0x4B, 0xB0, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x48, 0x44, 0x98, 0x47, 0x00, 0x22, 0xD8, 0xF8, ++0xC4, 0x34, 0x88, 0xF8, 0xAC, 0x20, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x05, 0x95, 0x11, 0x49, 0x95, 0xF8, 0xC3, 0x24, ++0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0xD0, 0xFF, 0x3A, 0x46, 0x31, 0x46, 0x62, 0x20, 0x09, 0xF0, 0x7B, 0xF9, 0x00, 0x20, ++0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0x93, 0x93, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xC9, 0xD0, ++0x06, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0x27, 0x62, 0x0B, 0xF0, 0xE4, 0xF9, 0xC2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x8C, 0x9C, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x00, 0xB5, 0x83, 0xB0, 0x08, 0x46, 0x01, 0x92, 0x00, 0x93, 0xFA, 0xF7, 0x45, 0xFA, 0xDD, 0xE9, 0x00, 0x12, 0x6E, 0x20, ++0x09, 0xF0, 0x50, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0xF0, 0xB5, 0x0C, 0x46, 0x0E, 0x78, 0x60, 0x78, ++0x89, 0x78, 0x83, 0xB0, 0x1D, 0x46, 0x01, 0x92, 0x9E, 0xB9, 0xFE, 0xF7, 0xD5, 0xFE, 0x01, 0x9A, 0x00, 0xBB, 0x03, 0x26, ++0x29, 0x46, 0x03, 0x23, 0x2B, 0x20, 0x09, 0xF0, 0xD1, 0xF8, 0x62, 0x78, 0x02, 0x70, 0xA2, 0x78, 0x42, 0x70, 0x86, 0x70, ++0x09, 0xF0, 0xFA, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0xFE, 0xF7, 0xD1, 0xFE, 0x01, 0x9A, 0x00, 0x28, 0xEA, 0xD0, ++0x60, 0x78, 0x14, 0x4B, 0xA1, 0x78, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x00, 0x30, 0x15, 0xF0, 0x9D, 0xFC, 0x02, 0x26, ++0x01, 0x9A, 0xDF, 0xE7, 0x61, 0x78, 0x94, 0xF8, 0x02, 0xC0, 0x0D, 0x48, 0x0D, 0x4F, 0x01, 0xEB, 0x81, 0x03, 0xC1, 0xEB, ++0x03, 0x13, 0x63, 0x44, 0x00, 0xEB, 0xC3, 0x03, 0x4F, 0xF0, 0x9E, 0x0E, 0x93, 0xF8, 0xA5, 0x31, 0x0E, 0xFB, 0x01, 0xC1, ++0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x81, 0x01, 0x07, 0xEB, 0xC3, 0x03, 0x81, 0xF8, 0x5A, 0x61, 0x1E, 0x81, 0x02, 0x26, ++0xC2, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x46, 0x02, 0xF0, 0x0C, 0xFA, ++0x01, 0x20, 0x08, 0xBD, 0x70, 0xB5, 0x48, 0x78, 0xFF, 0x28, 0x0C, 0x46, 0x16, 0x46, 0x1D, 0x46, 0x01, 0xD0, 0x17, 0xF0, ++0xB3, 0xF9, 0x21, 0x78, 0xA0, 0x78, 0x0A, 0x4B, 0x0A, 0x4A, 0x00, 0x39, 0x18, 0xBF, 0x01, 0x21, 0x00, 0x38, 0x18, 0xBF, ++0x01, 0x20, 0x18, 0x70, 0x11, 0x70, 0x02, 0x46, 0x06, 0x48, 0x0A, 0xF0, 0xDD, 0xFE, 0x32, 0x46, 0x29, 0x46, 0x64, 0x20, ++0x09, 0xF0, 0xD8, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0xB9, 0x34, 0x17, 0x00, 0xB8, 0x34, 0x17, 0x00, 0x9C, 0x9C, 0x15, 0x00, ++0xF8, 0xB5, 0x19, 0x46, 0x74, 0x20, 0x06, 0x23, 0x09, 0xF0, 0x62, 0xF8, 0x4F, 0xF4, 0xD2, 0x77, 0x04, 0x46, 0x3B, 0x68, ++0x08, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x06, 0x46, 0x09, 0x20, 0x98, 0x47, 0x36, 0x0C, 0x36, 0x04, 0x56, 0xEA, 0x00, 0x03, ++0x1A, 0xD1, 0x3B, 0x68, 0x07, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x05, 0x46, 0x08, 0x20, 0x98, 0x47, 0x83, 0xB2, 0x19, 0x0A, ++0x28, 0x0A, 0x2A, 0x0C, 0x63, 0x70, 0x2B, 0x0E, 0x21, 0x70, 0x20, 0x71, 0xE2, 0x70, 0xA3, 0x70, 0xEA, 0xB2, 0x07, 0x48, ++0x65, 0x71, 0x0A, 0xF0, 0xA5, 0xFE, 0x20, 0x46, 0x09, 0xF0, 0x6A, 0xF8, 0x00, 0x20, 0xF8, 0xBD, 0x05, 0x04, 0x45, 0xEA, ++0x16, 0x45, 0x03, 0x0C, 0xE7, 0xE7, 0x00, 0xBF, 0xC0, 0x9C, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x46, 0x48, 0x7A, ++0x09, 0x7A, 0x16, 0x46, 0xE2, 0x88, 0x84, 0xB0, 0xCD, 0xE9, 0x00, 0x21, 0x02, 0x90, 0x62, 0x88, 0x5E, 0x48, 0x21, 0x88, ++0x1D, 0x46, 0xA3, 0x88, 0x0A, 0xF0, 0x86, 0xFE, 0xB4, 0xF8, 0x00, 0xC0, 0x67, 0x88, 0xA0, 0x88, 0xE2, 0x88, 0x5A, 0x4B, ++0xBC, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x9E, 0x80, 0x19, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0x0B, 0x68, 0xDF, 0xF8, 0x6C, 0xE1, ++0x03, 0xEA, 0x08, 0x03, 0x43, 0xEA, 0x0C, 0x33, 0x0B, 0x60, 0xDE, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x08, 0x03, 0x43, 0xEA, ++0x0C, 0x33, 0xCE, 0xF8, 0x00, 0x30, 0x00, 0x2F, 0x79, 0xD0, 0x4B, 0x68, 0xDF, 0xF8, 0x44, 0xE1, 0xDF, 0xF8, 0x48, 0xC1, ++0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, 0x07, 0x33, 0x4B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, ++0x07, 0x33, 0xCC, 0xF8, 0x00, 0x30, 0x00, 0x28, 0x3F, 0xD0, 0x8F, 0x68, 0xDF, 0xF8, 0x1C, 0xE1, 0xDF, 0xF8, 0x14, 0xC1, ++0x07, 0xEA, 0x0E, 0x07, 0x47, 0xEA, 0x00, 0x37, 0x8F, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, ++0x00, 0x33, 0xCC, 0xF8, 0x00, 0x30, 0x00, 0x2A, 0x38, 0xD0, 0xC8, 0x68, 0xDF, 0xF8, 0xF4, 0xC0, 0x38, 0x4F, 0x00, 0xEA, ++0x0C, 0x00, 0x40, 0xEA, 0x02, 0x30, 0xC8, 0x60, 0x3B, 0x68, 0x03, 0xEA, 0x0C, 0x03, 0x43, 0xEA, 0x02, 0x33, 0x3B, 0x60, ++0x23, 0x7A, 0x33, 0x4A, 0x00, 0x2B, 0x31, 0xD0, 0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x63, 0x7A, 0x2F, 0x4A, ++0x00, 0x2B, 0x31, 0xD0, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x2C, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, 0x98, 0x47, ++0x32, 0x46, 0x29, 0x46, 0x7F, 0x20, 0x09, 0xF0, 0x17, 0xF8, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x88, 0x68, ++0xDF, 0xF8, 0x9C, 0xC0, 0x25, 0x4F, 0x00, 0xEA, 0x0C, 0x00, 0x88, 0x60, 0x3B, 0x68, 0x03, 0xEA, 0x0C, 0x03, 0x3B, 0x60, ++0x00, 0x2A, 0xC6, 0xD1, 0xCA, 0x68, 0x21, 0x4F, 0x1C, 0x48, 0x3A, 0x40, 0xCA, 0x60, 0x03, 0x68, 0x1B, 0x4A, 0x3B, 0x40, ++0x03, 0x60, 0x23, 0x7A, 0x00, 0x2B, 0xCD, 0xD1, 0x13, 0x68, 0x23, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x63, 0x7A, 0x16, 0x4A, ++0x00, 0x2B, 0xCD, 0xD1, 0x13, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xCC, 0xE7, 0x4F, 0x68, 0xDF, 0xF8, 0x50, 0xE0, ++0xDF, 0xF8, 0x54, 0xC0, 0x07, 0xEA, 0x0E, 0x07, 0x4F, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0xCC, 0xF8, ++0x00, 0x30, 0x88, 0xE7, 0x19, 0x68, 0xDF, 0xF8, 0x34, 0xE0, 0x0B, 0x68, 0xDF, 0xF8, 0x30, 0xC0, 0x03, 0xEA, 0x0E, 0x03, ++0x0B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0xCC, 0xF8, 0x00, 0x30, 0x64, 0xE7, 0xD8, 0x9C, 0x15, 0x00, ++0xAC, 0x35, 0x17, 0x00, 0x0C, 0x02, 0x32, 0x40, 0x24, 0x02, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, ++0xFF, 0x0F, 0x00, 0xF0, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x8A, 0x46, 0x83, 0xB0, ++0x49, 0x7C, 0x28, 0x48, 0xDF, 0xF8, 0xBC, 0x90, 0x27, 0x4F, 0x16, 0x46, 0xDA, 0xF8, 0x0C, 0x20, 0x00, 0x92, 0x01, 0x91, ++0x9A, 0xF8, 0x10, 0xB0, 0xDA, 0xF8, 0x00, 0x10, 0x1D, 0x46, 0xDA, 0xE9, 0x01, 0x23, 0x0A, 0xF0, 0xA5, 0xFD, 0x21, 0x4A, ++0x21, 0x49, 0x9A, 0xF8, 0x11, 0x00, 0x82, 0xF8, 0x05, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0B, 0xF3, 0x03, 0xF1, ++0x08, 0x02, 0x01, 0xEB, 0x02, 0x08, 0x01, 0xEB, 0x03, 0x0B, 0xAA, 0xF1, 0x04, 0x0A, 0x00, 0x24, 0x5A, 0xF8, 0x04, 0x0F, ++0xE3, 0xB2, 0x90, 0xB1, 0x48, 0xF8, 0x24, 0x00, 0x16, 0x4A, 0x9B, 0xF8, 0x64, 0x10, 0x12, 0x68, 0x42, 0xF8, 0x24, 0x00, ++0x49, 0xB1, 0x01, 0x2C, 0x13, 0xD0, 0x02, 0x2B, 0x17, 0xD0, 0x9B, 0xB1, 0x38, 0x60, 0x11, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, ++0x98, 0x47, 0x01, 0x34, 0x04, 0x2C, 0xE5, 0xD1, 0x32, 0x46, 0x29, 0x46, 0x83, 0x20, 0x08, 0xF0, 0x73, 0xFF, 0x00, 0x20, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC9, 0xF8, 0x00, 0x00, 0xEC, 0xE7, 0x08, 0x4B, 0x18, 0x60, 0xE9, 0xE7, 0x08, 0x4B, ++0x18, 0x60, 0xE6, 0xE7, 0x18, 0x9D, 0x15, 0x00, 0x0C, 0x02, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xAC, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, ++0xF8, 0xB5, 0x7C, 0x20, 0x0C, 0x46, 0x19, 0x46, 0x02, 0x23, 0x08, 0xF0, 0xE5, 0xFE, 0x23, 0x78, 0x05, 0x46, 0x00, 0x2B, ++0x5F, 0xD0, 0x35, 0x48, 0x0A, 0xF0, 0x46, 0xFD, 0x34, 0x4B, 0x1B, 0x68, 0x00, 0x22, 0x1A, 0x70, 0x4F, 0xF4, 0xD2, 0x73, ++0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x68, 0x70, 0x62, 0x78, 0x06, 0x46, 0x00, 0x2A, 0x45, 0xD0, 0x2E, 0x4F, 0xC0, 0xF3, ++0x40, 0x11, 0x42, 0x06, 0x87, 0xF8, 0xB4, 0x10, 0x4F, 0xD4, 0x2C, 0x48, 0x0F, 0x22, 0x01, 0x21, 0xE8, 0xF7, 0x1C, 0xFC, ++0x02, 0x22, 0x11, 0x46, 0x29, 0x48, 0xE8, 0xF7, 0x17, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x28, 0x48, 0xE8, 0xF7, 0x12, 0xFC, ++0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x24, 0x48, 0xE8, 0xF7, 0x0C, 0xFC, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x22, 0x48, ++0xE8, 0xF7, 0x06, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x20, 0x48, 0xE8, 0xF7, 0x01, 0xFC, 0x4F, 0xF4, 0x00, 0x52, 0x00, 0x21, ++0x1D, 0x48, 0xE8, 0xF7, 0xFB, 0xFB, 0x97, 0xF8, 0xB4, 0x10, 0x01, 0x22, 0x23, 0x78, 0x6B, 0xB1, 0xE3, 0x78, 0x2B, 0xB1, ++0xB7, 0xF8, 0xAA, 0x30, 0x43, 0xF4, 0x80, 0x43, 0xA7, 0xF8, 0xAA, 0x30, 0x16, 0x48, 0xF3, 0xB2, 0x0A, 0xF0, 0xFA, 0xFC, ++0x97, 0xF8, 0xB4, 0x10, 0x29, 0x70, 0x28, 0x46, 0x08, 0xF0, 0xBC, 0xFE, 0x00, 0x20, 0xF8, 0xBD, 0xA3, 0x78, 0x0B, 0x4F, ++0xC3, 0xF3, 0x40, 0x11, 0x5B, 0x06, 0x87, 0xF8, 0xB4, 0x10, 0xB8, 0xD5, 0xE0, 0xE7, 0x0D, 0x48, 0x0A, 0xF0, 0xE6, 0xFC, ++0x04, 0x4B, 0x1B, 0x68, 0x03, 0x22, 0x1A, 0x70, 0x9E, 0xE7, 0x00, 0x22, 0xD6, 0xE7, 0x00, 0xBF, 0x48, 0x9D, 0x15, 0x00, ++0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x04, 0x20, 0x01, 0x50, 0x04, 0x10, 0x01, 0x50, 0x08, 0x10, 0x01, 0x50, ++0x00, 0x10, 0x01, 0x50, 0x68, 0x9D, 0x15, 0x00, 0x58, 0x9D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x18, 0x46, 0xB1, 0xB0, ++0x0C, 0x46, 0x10, 0x23, 0x01, 0x46, 0x6A, 0x20, 0x04, 0x94, 0x08, 0xF0, 0x59, 0xFE, 0x4F, 0xF4, 0xD2, 0x73, 0x02, 0x46, ++0x1B, 0x68, 0x05, 0x92, 0x06, 0x20, 0x98, 0x47, 0x04, 0x46, 0x01, 0x46, 0x91, 0x48, 0x0A, 0xF0, 0xB5, 0xFC, 0x14, 0xF4, ++0x7F, 0x4F, 0xC4, 0xF3, 0x07, 0x25, 0x6F, 0xD1, 0x26, 0x0E, 0xE5, 0xB2, 0x6E, 0xD0, 0xF4, 0xB2, 0x00, 0x2D, 0x6F, 0xD1, ++0x04, 0x9B, 0x19, 0x7D, 0x00, 0x29, 0x40, 0xF0, 0x83, 0x80, 0x00, 0x2E, 0x40, 0xF0, 0x89, 0x80, 0x59, 0x7D, 0x31, 0xB1, ++0x86, 0x48, 0x0A, 0xF0, 0x9D, 0xFC, 0x04, 0x9B, 0x5C, 0x7D, 0x00, 0x2C, 0x7F, 0xD1, 0x04, 0x9B, 0xDB, 0x68, 0x00, 0x2B, ++0x40, 0xF0, 0x8D, 0x80, 0x04, 0x9B, 0xDF, 0xF8, 0x40, 0xB2, 0x99, 0x68, 0x1A, 0x68, 0x7F, 0x4B, 0xDF, 0xF8, 0x38, 0xA2, ++0xD3, 0xF8, 0x70, 0x32, 0x7D, 0x4C, 0xCD, 0xE9, 0x08, 0x21, 0x08, 0xA8, 0x0A, 0xA9, 0x98, 0x47, 0x1A, 0xAE, 0x6F, 0xF0, ++0x3F, 0x08, 0x09, 0xAF, 0x0A, 0xAB, 0x07, 0x97, 0xA8, 0xEB, 0x03, 0x08, 0x35, 0x46, 0x0D, 0xF1, 0x78, 0x09, 0x06, 0x96, ++0xE3, 0x79, 0x00, 0x93, 0x08, 0xEB, 0x05, 0x02, 0x23, 0x68, 0x03, 0x92, 0x59, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, ++0xBD, 0xFC, 0x15, 0xF8, 0x01, 0x6B, 0x57, 0xF8, 0x04, 0x3F, 0x03, 0x9A, 0x00, 0x96, 0x51, 0x46, 0x23, 0x60, 0xE6, 0x71, ++0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, 0xB0, 0xFC, 0x4D, 0x45, 0x04, 0xF1, 0x10, 0x04, 0xE3, 0xD1, 0xDF, 0xF8, 0xD8, 0xB1, ++0x06, 0x9E, 0x9B, 0xF8, 0xB4, 0x30, 0x00, 0x2B, 0x52, 0xD1, 0xDF, 0xF8, 0xD0, 0xA1, 0x61, 0x4B, 0x00, 0x20, 0xD3, 0xF8, ++0xB0, 0x34, 0x98, 0x47, 0x05, 0x98, 0x5F, 0x4C, 0x5F, 0x4A, 0x60, 0x4B, 0x82, 0x60, 0xC0, 0xE9, 0x00, 0x4A, 0xC3, 0x60, ++0x08, 0xF0, 0x0C, 0xFE, 0x00, 0x20, 0x31, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x23, 0x0E, 0x0B, 0xD1, 0x26, 0x0C, 0xF4, 0xB2, ++0x00, 0x2D, 0x8F, 0xD0, 0x3C, 0xB9, 0x04, 0x9B, 0x59, 0x7D, 0x00, 0x29, 0x40, 0xF0, 0x99, 0x80, 0x00, 0x24, 0x00, 0xE0, ++0xDC, 0xB2, 0x1F, 0x2D, 0x28, 0xBF, 0x1F, 0x25, 0xE9, 0x06, 0x41, 0xEA, 0x85, 0x51, 0x51, 0x4A, 0x51, 0x48, 0xE8, 0xF7, ++0x17, 0xFB, 0x51, 0x48, 0x29, 0x46, 0x0A, 0xF0, 0x23, 0xFC, 0x86, 0xE7, 0x4F, 0x48, 0x0A, 0xF0, 0x1F, 0xFC, 0x04, 0x9B, ++0x1D, 0x7D, 0x00, 0x2E, 0x70, 0xD0, 0x00, 0x2D, 0xE7, 0xD1, 0x3F, 0x2C, 0x21, 0x46, 0x4B, 0x48, 0x28, 0xBF, 0x3F, 0x21, ++0x3F, 0x22, 0x03, 0x91, 0xE8, 0xF7, 0x00, 0xFB, 0x03, 0x99, 0x48, 0x48, 0x0A, 0xF0, 0x0C, 0xFC, 0x04, 0x9B, 0xDB, 0x68, ++0x00, 0x2B, 0x3F, 0xF4, 0x73, 0xAF, 0x04, 0x9B, 0x18, 0x69, 0xEB, 0xF7, 0x6F, 0xF8, 0x6D, 0xE7, 0x42, 0x4A, 0x38, 0x4D, ++0x93, 0x69, 0xD5, 0xF8, 0x28, 0x42, 0xDF, 0xF8, 0x20, 0xA1, 0x40, 0x4F, 0x43, 0xF0, 0x01, 0x03, 0x93, 0x61, 0x04, 0x9B, ++0x5B, 0x68, 0x08, 0x93, 0x41, 0xF2, 0x7C, 0x52, 0x00, 0x23, 0x11, 0x46, 0xCD, 0xE9, 0x00, 0x33, 0x01, 0x20, 0xA0, 0x47, ++0x39, 0x4A, 0x01, 0x23, 0x82, 0xF8, 0x2A, 0x30, 0x0A, 0xA9, 0xD5, 0xF8, 0x70, 0x32, 0x37, 0x4D, 0x08, 0xA8, 0x98, 0x47, ++0x54, 0x46, 0xCD, 0xF8, 0x10, 0xA0, 0xDD, 0xF8, 0x1C, 0xA0, 0xE3, 0x79, 0x00, 0x93, 0x06, 0xEB, 0x08, 0x02, 0x23, 0x68, ++0x03, 0x92, 0x39, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, 0x22, 0xFC, 0x16, 0xF8, 0x01, 0xCB, 0x5A, 0xF8, 0x04, 0x3F, ++0x03, 0x9A, 0xCD, 0xF8, 0x00, 0xC0, 0x29, 0x46, 0x23, 0x60, 0x84, 0xF8, 0x07, 0xC0, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, ++0x13, 0xFC, 0x4E, 0x45, 0x04, 0xF1, 0x10, 0x04, 0xE1, 0xD1, 0x9B, 0xF8, 0xB4, 0x30, 0xDD, 0xF8, 0x10, 0xA0, 0x00, 0x2B, ++0x3F, 0xF4, 0x65, 0xAF, 0x13, 0x4B, 0x00, 0x20, 0xD3, 0xF8, 0x80, 0x34, 0x98, 0x47, 0x1D, 0x4B, 0x1E, 0x49, 0x93, 0xF8, ++0x2A, 0x20, 0x08, 0x20, 0x00, 0x23, 0x0A, 0xF0, 0xFB, 0xFB, 0x5B, 0xE7, 0x59, 0x7D, 0x1C, 0x46, 0x39, 0xB1, 0x0A, 0x48, ++0x0A, 0xF0, 0xA4, 0xFB, 0x64, 0x7D, 0x00, 0x2D, 0x3F, 0xF4, 0x05, 0xAF, 0x6D, 0xE7, 0x00, 0x2D, 0x3F, 0xF4, 0x03, 0xAF, ++0x66, 0xE7, 0x04, 0x48, 0x0A, 0xF0, 0x98, 0xFB, 0x04, 0x9B, 0x5C, 0x7D, 0x63, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x15, 0x00, ++0xBC, 0x9D, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, ++0x00, 0x00, 0xC0, 0xFF, 0x04, 0x88, 0x01, 0x50, 0xD0, 0x9D, 0x15, 0x00, 0xAC, 0x9D, 0x15, 0x00, 0x28, 0x91, 0x01, 0x50, ++0xE4, 0x9D, 0x15, 0x00, 0x00, 0x80, 0x50, 0x40, 0x44, 0x9E, 0x15, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x64, 0x9E, 0x15, 0x00, ++0x9C, 0x77, 0x15, 0x00, 0xFC, 0x9D, 0x15, 0x00, 0x20, 0x9E, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, ++0x38, 0xB5, 0x00, 0x22, 0x0D, 0x46, 0x01, 0x23, 0x0C, 0x21, 0x54, 0x20, 0x08, 0xF0, 0xFA, 0xFC, 0x01, 0x23, 0x03, 0x70, ++0x04, 0x46, 0x28, 0x78, 0x04, 0x28, 0x0D, 0xD8, 0x0C, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, ++0xC0, 0x34, 0x2B, 0xB1, 0x00, 0x23, 0x23, 0x70, 0x69, 0x78, 0x31, 0xB1, 0x06, 0xF0, 0xA2, 0xFB, 0x20, 0x46, 0x08, 0xF0, ++0x13, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x06, 0xF0, 0xBD, 0xFB, 0x20, 0x46, 0x08, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x38, 0xBD, ++0x18, 0x88, 0x17, 0x00, 0x70, 0xB5, 0x10, 0x46, 0x14, 0x46, 0x0D, 0x46, 0x1E, 0x46, 0x08, 0xF0, 0x73, 0xFF, 0x03, 0x28, ++0x25, 0xD0, 0x20, 0x46, 0x08, 0xF0, 0x6E, 0xFF, 0x04, 0x28, 0x20, 0xD0, 0x2A, 0x78, 0x1B, 0x4D, 0x20, 0x46, 0xEA, 0x77, ++0x72, 0xB9, 0x08, 0xF0, 0x65, 0xFF, 0x02, 0x28, 0x17, 0xD0, 0x18, 0x4B, 0xD3, 0xF8, 0x60, 0x31, 0x98, 0x47, 0x23, 0x20, ++0x22, 0x46, 0x31, 0x46, 0x08, 0xF0, 0x20, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x08, 0xF0, 0x56, 0xFF, 0x58, 0xB1, 0x02, 0x28, ++0xF9, 0xD0, 0x10, 0x4B, 0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x20, 0x46, 0x02, 0x21, 0x08, 0xF0, 0xA3, 0xFE, 0x02, 0x20, ++0x70, 0xBD, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x02, 0xDB, 0x00, 0x23, 0x6B, 0x82, 0xE0, 0xE7, ++0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0xF8, 0xD0, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x31, 0x62, 0x0A, 0xF0, 0x76, 0xFD, ++0xF1, 0xE7, 0x00, 0xBF, 0x98, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, ++0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x70, 0xB5, 0x1E, 0x4D, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x0E, 0x46, 0x14, 0x46, 0x1C, 0xDB, 0x20, 0x46, 0x08, 0xF0, 0x1C, 0xFF, 0x58, 0xB1, 0x02, 0x28, 0x08, 0xD0, 0x18, 0x4B, ++0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x20, 0x46, 0x02, 0x21, 0x08, 0xF0, 0x69, 0xFE, 0x02, 0x20, 0x70, 0xBD, 0x2B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x13, 0xDB, 0x20, 0x46, 0x03, 0x21, 0x08, 0xF0, 0x5E, 0xFE, 0x33, 0x68, 0x98, 0x47, ++0x00, 0x20, 0x70, 0xBD, 0x10, 0x46, 0x08, 0xF0, 0xFF, 0xFE, 0x04, 0x28, 0xDD, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, ++0x71, 0x62, 0x0A, 0xF0, 0x37, 0xFD, 0xD6, 0xE7, 0x09, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0xE7, 0xD0, 0x05, 0x49, 0x08, 0x48, ++0x4F, 0xF4, 0xCF, 0x62, 0x0A, 0xF0, 0x2C, 0xFD, 0xE0, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xAC, 0x9E, 0x15, 0x00, 0x38, 0x00, 0x32, 0x40, 0x84, 0x9E, 0x15, 0x00, 0x70, 0xB5, 0x12, 0x4C, ++0x88, 0x78, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x40, 0x82, 0xB0, 0x90, 0xF8, 0x62, 0x40, 0x1E, 0x46, 0x84, 0xB9, ++0x90, 0xF8, 0x6C, 0x00, 0x0C, 0x4D, 0x0C, 0x88, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x00, 0x51, 0xA4, 0x02, 0x8C, 0x60, ++0x31, 0x46, 0x15, 0x20, 0x08, 0xF0, 0x8A, 0xFC, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x06, 0x4C, 0x09, 0x88, 0xD4, 0xF8, ++0x60, 0x44, 0x01, 0x92, 0xA0, 0x47, 0x01, 0x9A, 0xF0, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x88, 0x79, 0x19, 0x4D, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x00, 0xF6, ++0x06, 0xF1, 0x38, 0x00, 0x28, 0x44, 0x35, 0x44, 0x82, 0xB0, 0x90, 0x46, 0x06, 0x22, 0x1F, 0x46, 0x0C, 0x46, 0x1C, 0xF0, ++0x85, 0xFF, 0x95, 0xF8, 0xC0, 0x34, 0x73, 0xB9, 0x10, 0x49, 0x11, 0x4B, 0x20, 0x68, 0xA2, 0x88, 0x08, 0x60, 0x1A, 0x60, ++0x42, 0x46, 0x39, 0x46, 0x19, 0x20, 0x08, 0xF0, 0x57, 0xFC, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x0D, 0xF1, ++0x07, 0x00, 0xFC, 0xF7, 0x9F, 0xFF, 0x00, 0x28, 0xF0, 0xD1, 0x08, 0x49, 0x08, 0x48, 0xD1, 0xE9, 0x00, 0x23, 0x43, 0xF0, ++0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, 0x02, 0x60, 0xE6, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x20, 0x00, 0x32, 0x40, ++0x24, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x0D, 0x46, 0x9E, 0x4F, ++0x95, 0xF8, 0x03, 0xA0, 0x4F, 0xF4, 0xA4, 0x61, 0x89, 0xB0, 0x01, 0xFB, 0x0A, 0xFB, 0x07, 0xEB, 0x0B, 0x06, 0x00, 0x24, ++0x0D, 0xF1, 0x1F, 0x00, 0x90, 0x46, 0x99, 0x46, 0x8D, 0xF8, 0x1F, 0x40, 0xFC, 0xF7, 0x72, 0xFF, 0x96, 0xF8, 0x62, 0x30, ++0xAA, 0x78, 0x86, 0xF8, 0x64, 0x20, 0x04, 0x46, 0x00, 0x2B, 0x40, 0xF0, 0xED, 0x80, 0x96, 0xF8, 0x6C, 0x10, 0x02, 0x91, ++0x00, 0x2A, 0x00, 0xF0, 0x45, 0x81, 0x8E, 0x4A, 0x8E, 0x4B, 0x03, 0x92, 0x8C, 0x46, 0x8E, 0x49, 0x18, 0x69, 0xD2, 0xF8, ++0xE0, 0x31, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x0C, 0x12, 0x0B, 0xF1, 0x18, 0x01, 0x79, 0x18, 0x04, 0x91, 0x91, 0x68, ++0x05, 0x92, 0x41, 0x18, 0x04, 0x98, 0x98, 0x47, 0x05, 0x9A, 0x2B, 0x88, 0x13, 0x84, 0xFC, 0xF7, 0x39, 0xFF, 0x05, 0x9A, ++0x96, 0xF8, 0xC0, 0x14, 0x01, 0x94, 0x13, 0x8C, 0x92, 0xF8, 0x23, 0x20, 0x00, 0x91, 0x4F, 0xF4, 0x80, 0x70, 0x7F, 0x49, ++0x0A, 0xF0, 0x3C, 0xFA, 0x96, 0xF8, 0xC0, 0x34, 0x33, 0xB9, 0x7D, 0x4A, 0x29, 0x88, 0x13, 0x68, 0x9B, 0xB2, 0x43, 0xEA, ++0x01, 0x43, 0x13, 0x60, 0x7A, 0x4B, 0x1B, 0x68, 0x18, 0x04, 0x00, 0xF1, 0xD2, 0x81, 0x79, 0x49, 0x79, 0x4B, 0xB1, 0xF8, ++0x1C, 0xC0, 0x02, 0x99, 0x08, 0x46, 0x72, 0x49, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x00, 0x12, 0x4F, 0xF4, 0xA4, 0x6B, ++0x90, 0x68, 0x02, 0x92, 0x0B, 0xFB, 0x0A, 0x7B, 0x0C, 0xF1, 0x14, 0x0C, 0x00, 0xFB, 0x0C, 0xFC, 0xA3, 0xFB, 0x0C, 0x3C, ++0xDB, 0xF8, 0x04, 0x00, 0x4F, 0xEA, 0x9C, 0x4C, 0x00, 0x23, 0xA2, 0xF8, 0x1E, 0xC0, 0x40, 0xF0, 0x01, 0x00, 0xDF, 0xF8, ++0x90, 0xC1, 0xAB, 0xF8, 0x68, 0x30, 0x8B, 0xF8, 0x6A, 0x30, 0x8B, 0xF8, 0x8C, 0x30, 0x8B, 0xF8, 0x78, 0x30, 0xCB, 0xF8, ++0x74, 0x30, 0xCB, 0xF8, 0x04, 0x00, 0xDC, 0xF8, 0x10, 0x00, 0xCB, 0xF8, 0x70, 0x00, 0x30, 0x46, 0x04, 0xF0, 0xF4, 0xFA, ++0x9B, 0xF8, 0xC0, 0x04, 0x5D, 0x49, 0x00, 0x23, 0x00, 0x28, 0x40, 0xF0, 0x76, 0x81, 0x5D, 0x4B, 0x02, 0x9A, 0x9B, 0x7C, ++0x00, 0x2B, 0x40, 0xF0, 0x8B, 0x81, 0x00, 0x2C, 0x40, 0xF0, 0xD5, 0x81, 0xDF, 0xF8, 0x7C, 0xB1, 0xDB, 0xF8, 0x20, 0x30, ++0x00, 0x2B, 0x40, 0xF0, 0x81, 0x81, 0x9D, 0xF8, 0x1F, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x87, 0x82, 0x53, 0x49, 0x93, 0x68, ++0x0A, 0x68, 0xCB, 0xF8, 0x20, 0x60, 0x12, 0x0C, 0x12, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x13, 0x43, 0x0B, 0x60, 0xDD, 0xE9, ++0x03, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x8B, 0xF8, 0x24, 0x40, 0xD3, 0xF8, 0x60, 0x32, 0x98, 0x47, ++0xAA, 0x78, 0x11, 0x46, 0x30, 0x46, 0x05, 0xF0, 0x5B, 0xFF, 0xAB, 0x78, 0x00, 0x2B, 0x38, 0xD0, 0x45, 0x4B, 0x1B, 0x68, ++0x1A, 0x68, 0x00, 0x2A, 0x00, 0xF0, 0xE0, 0x80, 0x43, 0x49, 0x0A, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0x00, 0xF0, 0xE5, 0x80, ++0xC2, 0xF3, 0x0B, 0x01, 0x00, 0x29, 0x40, 0xF0, 0x4F, 0x81, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x0A, 0x71, 0x22, 0xF4, ++0x7F, 0x62, 0xC9, 0x68, 0x3B, 0x48, 0x22, 0xF0, 0x0F, 0x02, 0xC1, 0xF3, 0x0B, 0x01, 0x0A, 0x43, 0x02, 0x60, 0x9A, 0x68, ++0x00, 0x2A, 0x40, 0xF0, 0xD9, 0x80, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, 0x35, 0x49, 0x12, 0x69, 0x0A, 0x60, ++0xDB, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xD4, 0x80, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x77, 0x30, 0x4B, 0x7A, 0x69, ++0x1A, 0x60, 0x21, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, 0x98, 0x47, 0x42, 0x46, 0x49, 0x46, 0x1F, 0x20, 0x08, 0xF0, 0x30, 0xFB, ++0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x80, 0xB1, 0x22, 0x4B, 0x9C, 0x68, 0x6C, 0xB1, 0x94, 0xF8, 0x62, 0x30, ++0x3B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x23, 0xB1, 0xA6, 0x42, 0x02, 0xD0, 0x94, 0xF8, 0xC0, 0x34, 0x13, 0xB1, 0x24, 0x68, ++0x00, 0x2C, 0xF1, 0xD1, 0x00, 0x2A, 0x00, 0xF0, 0xB2, 0x80, 0x1F, 0x4B, 0x19, 0x6A, 0xA1, 0x42, 0x9D, 0xD1, 0x0E, 0x49, ++0x1D, 0x4C, 0xD1, 0xF8, 0x64, 0x12, 0x00, 0x22, 0x1A, 0x62, 0x83, 0xF8, 0x24, 0x20, 0x88, 0x47, 0x0F, 0x4A, 0x1A, 0x48, ++0xD2, 0xE9, 0x00, 0x13, 0x43, 0xF0, 0x10, 0x03, 0x19, 0x43, 0x01, 0x60, 0x17, 0x48, 0x18, 0x49, 0x20, 0x60, 0x53, 0x60, ++0x0B, 0x68, 0x03, 0x43, 0x0B, 0x60, 0xAA, 0x78, 0x83, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0xD0, 0x9E, 0x15, 0x00, 0x68, 0x00, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x83, 0xDE, 0x1B, 0x43, 0x00, 0x88, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, 0xAC, 0x35, 0x17, 0x00, ++0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x70, 0x80, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x74, 0x80, 0x32, 0x40, 0xAC, 0x4B, 0x03, 0x93, ++0x0B, 0xF1, 0x18, 0x00, 0x38, 0x44, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0xD3, 0xF8, 0xDC, 0x33, 0x98, 0x47, ++0xA7, 0x49, 0x96, 0xF8, 0xC0, 0x24, 0x23, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0x0A, 0xF9, 0xA4, 0x4B, 0x1B, 0x68, ++0x19, 0x04, 0x00, 0xF1, 0xD8, 0x80, 0xA3, 0x4B, 0x9B, 0x7F, 0x3B, 0xB9, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, ++0x82, 0xF8, 0xC3, 0x34, 0xC2, 0xF8, 0xC4, 0x34, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x73, 0x93, 0xF8, 0xC0, 0x34, ++0x00, 0x2B, 0x00, 0xF0, 0x8C, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0x8E, 0x80, 0x98, 0x4B, 0x9C, 0x68, 0x00, 0x2C, 0x00, 0xF0, ++0x89, 0x80, 0x94, 0xF8, 0x62, 0x30, 0x4B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x33, 0xB1, 0xA6, 0x42, 0x04, 0xD0, 0x94, 0xF8, ++0xC0, 0x34, 0x00, 0x2B, 0x00, 0xF0, 0x4A, 0x81, 0x24, 0x68, 0x00, 0x2C, 0xEF, 0xD1, 0x77, 0xE0, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x0A, 0x72, 0x8C, 0x49, 0x92, 0x68, 0x0A, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0x7F, 0xF4, 0x1B, 0xAF, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, 0x88, 0x49, 0xD2, 0x68, 0x0A, 0x60, 0x9A, 0x68, 0x00, 0x2A, 0x3F, 0xF4, 0x27, 0xAF, ++0x85, 0x49, 0x0A, 0x60, 0xDB, 0x68, 0x00, 0x2B, 0x3F, 0xF4, 0x2C, 0xAF, 0x83, 0x4A, 0x13, 0x60, 0x7A, 0x4B, 0xD3, 0xF8, ++0xA0, 0x31, 0x98, 0x47, 0x2F, 0xE7, 0x81, 0x48, 0x81, 0x49, 0x03, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x03, 0x60, 0x0B, 0x6A, ++0x00, 0x2B, 0x7F, 0xF4, 0xE6, 0xAE, 0x00, 0x2C, 0x3F, 0xF4, 0xE3, 0xAE, 0xDF, 0xF8, 0xC4, 0xB1, 0x0C, 0x62, 0x81, 0xF8, ++0x24, 0x20, 0x04, 0xF1, 0x18, 0x00, 0xDB, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xDB, 0xF8, 0x60, 0x32, 0x98, 0x47, 0x76, 0x49, ++0xDF, 0xF8, 0xE4, 0xC1, 0x75, 0x48, 0xD4, 0xF8, 0x38, 0xE0, 0xA4, 0x8F, 0xD1, 0xE9, 0x00, 0x32, 0x22, 0xF0, 0x10, 0x02, ++0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0xC0, 0xF8, 0x00, 0xE0, 0x70, 0x4B, 0x4C, 0xF8, 0x3C, 0x4C, 0x00, 0xF5, 0x00, 0x40, ++0x54, 0x30, 0x6E, 0x4C, 0x1C, 0x60, 0x03, 0x68, 0x4A, 0x60, 0x23, 0xF4, 0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, 0x03, 0x60, ++0x1A, 0xE0, 0xCC, 0xB1, 0x64, 0x4A, 0x10, 0x6A, 0xB0, 0xB1, 0x13, 0x62, 0x82, 0xF8, 0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, ++0x64, 0x32, 0x98, 0x47, 0x60, 0x49, 0x64, 0x48, 0xD1, 0xE9, 0x00, 0x23, 0x43, 0xF0, 0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, ++0x02, 0x60, 0xAA, 0x78, 0x9F, 0xE6, 0x02, 0x2C, 0x65, 0xD0, 0x01, 0x2C, 0x00, 0xF0, 0xC0, 0x80, 0xAA, 0x78, 0x98, 0xE6, ++0x52, 0x49, 0x0A, 0x60, 0x94, 0xE7, 0xE6, 0xF7, 0x1F, 0xFE, 0x00, 0x28, 0x3F, 0xF4, 0x29, 0xAE, 0x02, 0x9A, 0x11, 0x46, ++0x57, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x23, 0x5B, 0x68, 0x9A, 0x06, 0x7F, 0xF5, 0x1E, 0xAE, 0x28, 0x88, ++0xE6, 0xF7, 0x54, 0xFE, 0xF9, 0xF7, 0x9C, 0xF9, 0x51, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0x41, 0xF8, 0x03, 0x9B, ++0xD3, 0xF8, 0xE0, 0x33, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x73, 0x93, 0xF8, 0x62, 0x20, 0x04, 0x2A, ++0x3F, 0xF4, 0x07, 0xAE, 0x93, 0xF8, 0x63, 0x00, 0x03, 0x9B, 0xD3, 0xF8, 0x30, 0x33, 0x98, 0x47, 0xFF, 0xE5, 0xE6, 0xF7, ++0xF1, 0xFD, 0x00, 0x28, 0x3F, 0xF4, 0x23, 0xAF, 0x41, 0x4B, 0x02, 0x99, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0x3B, ++0xDB, 0xF8, 0x04, 0x30, 0x9B, 0x06, 0x7F, 0xF5, 0x18, 0xAF, 0x96, 0xF8, 0x62, 0x30, 0x04, 0x2B, 0x3F, 0xF4, 0x13, 0xAF, ++0x96, 0xF8, 0x63, 0x00, 0x06, 0xF0, 0x2A, 0xFB, 0x0D, 0xE7, 0x01, 0x2C, 0xB0, 0xD1, 0x30, 0x4C, 0x22, 0x6A, 0xB2, 0x42, ++0xAC, 0xD0, 0x23, 0x62, 0x02, 0x93, 0xDD, 0xE9, 0x03, 0x30, 0xD3, 0xF8, 0xD8, 0x21, 0x90, 0x47, 0x02, 0x9B, 0x84, 0xF8, ++0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, 0x64, 0x32, 0x98, 0x47, 0xAA, 0x78, 0x37, 0xE6, 0x26, 0x4C, 0x23, 0x6A, 0x00, 0x2B, ++0x98, 0xD1, 0x1E, 0x4B, 0x98, 0x68, 0x20, 0xB9, 0xA3, 0xE0, 0x00, 0x68, 0x00, 0x28, 0x00, 0xF0, 0xA0, 0x80, 0x90, 0xF8, ++0x62, 0x30, 0x00, 0x2B, 0xF7, 0xD1, 0x90, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF3, 0xD0, 0x86, 0x42, 0xF1, 0xD0, 0x90, 0xF8, ++0xC0, 0x34, 0x00, 0x2B, 0xED, 0xD1, 0x1F, 0x49, 0x17, 0x4A, 0x20, 0x62, 0x9B, 0x46, 0x90, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, ++0x1E, 0x7C, 0x0C, 0xFB, 0x03, 0x13, 0x11, 0x68, 0x9B, 0x68, 0x09, 0x0C, 0x09, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x0B, 0x43, ++0x13, 0x60, 0x03, 0x9B, 0x18, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x84, 0xF8, 0x24, 0xB0, 0xD3, 0xF8, ++0x60, 0x32, 0x98, 0x47, 0xAA, 0x78, 0xFE, 0xE5, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x9F, 0x15, 0x00, 0x04, 0x00, 0x32, 0x40, ++0x64, 0xBA, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, ++0x0C, 0x02, 0x32, 0x40, 0x64, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x20, 0x00, 0x32, 0x40, ++0x70, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x60, 0x00, 0x32, 0x40, 0x68, 0x65, 0x17, 0x00, 0xF0, 0x9E, 0x15, 0x00, ++0x29, 0x4A, 0x11, 0x6A, 0xB1, 0x42, 0x7F, 0xF4, 0x3B, 0xAF, 0x13, 0x62, 0x82, 0xF8, 0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, ++0x64, 0x32, 0x98, 0x47, 0xAA, 0x78, 0xCC, 0xE5, 0xDF, 0xF8, 0x88, 0xB0, 0xDB, 0xF8, 0x20, 0x20, 0x00, 0x2A, 0x7F, 0xF4, ++0x2B, 0xAF, 0x94, 0xF8, 0x6C, 0x30, 0x1F, 0x48, 0x1F, 0x49, 0xCB, 0xF8, 0x20, 0x40, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, ++0x03, 0x03, 0x08, 0x68, 0x9B, 0x68, 0x02, 0x92, 0x00, 0x0C, 0x00, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x03, 0x43, 0x0B, 0x60, ++0x03, 0x9B, 0x04, 0xF1, 0x18, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x02, 0x9A, 0x8B, 0xF8, 0x24, 0x20, ++0xD3, 0xF8, 0x60, 0x32, 0xDF, 0xF8, 0x50, 0xB0, 0x98, 0x47, 0x11, 0x49, 0xDF, 0xF8, 0x4C, 0xC0, 0x10, 0x48, 0xD4, 0xF8, ++0x38, 0xE0, 0xA4, 0x8F, 0xD1, 0xE9, 0x00, 0x23, 0x23, 0xF0, 0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, 0xCB, 0xF8, 0x00, 0x20, ++0xCC, 0xF8, 0x00, 0xE0, 0x04, 0x60, 0xAA, 0x78, 0x8F, 0xE5, 0x01, 0x2B, 0x7F, 0xF4, 0xF2, 0xAE, 0xE1, 0xE6, 0x00, 0x23, ++0x93, 0xF8, 0x6C, 0x30, 0xFF, 0xDE, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x24, 0x00, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x38, 0xB5, 0x07, 0x20, ++0x0C, 0x46, 0x19, 0x46, 0x02, 0x23, 0x08, 0xF0, 0x7F, 0xF8, 0x23, 0x46, 0x07, 0x4D, 0x13, 0xF8, 0x02, 0x1B, 0x22, 0x7A, ++0xD5, 0xF8, 0x58, 0x54, 0x04, 0x46, 0x18, 0x46, 0x63, 0x1C, 0xA8, 0x47, 0x20, 0x70, 0x20, 0x46, 0x08, 0xF0, 0xA0, 0xF8, ++0x00, 0x20, 0x38, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xB5, 0x08, 0x78, 0x03, 0x28, 0x83, 0xB0, 0x19, 0x46, 0x07, 0xD8, ++0xCD, 0xE9, 0x00, 0x23, 0x0C, 0x4B, 0xD3, 0xF8, 0x64, 0x34, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0x0A, 0x4B, 0x9B, 0x68, ++0x33, 0xB1, 0x09, 0x20, 0x08, 0xF0, 0xC0, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x04, 0x4B, 0xD3, 0xF8, ++0xE8, 0x30, 0xCD, 0xE9, 0x00, 0x21, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0xEF, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x78, 0x0C, 0x46, 0x16, 0x46, 0x98, 0x46, 0x00, 0x2D, 0x3B, 0xD1, ++0x91, 0xF8, 0x02, 0xC0, 0x26, 0x49, 0x27, 0x4A, 0x11, 0xF8, 0x0C, 0x00, 0xE1, 0x78, 0x52, 0xF8, 0x20, 0x20, 0x60, 0x78, ++0x24, 0x4F, 0x25, 0x4B, 0x91, 0x42, 0xB8, 0xBF, 0x4A, 0x08, 0x00, 0xEB, 0x80, 0x01, 0xC0, 0xEB, 0x01, 0x11, 0x61, 0x44, ++0x07, 0xEB, 0xC1, 0x01, 0x4F, 0xF0, 0x9E, 0x0E, 0x91, 0xF8, 0xA5, 0x11, 0x0E, 0xFB, 0x00, 0xC0, 0xA8, 0xBF, 0x02, 0xEB, ++0xD2, 0x72, 0x07, 0xEB, 0x80, 0x00, 0xA8, 0xBF, 0xC2, 0xF3, 0x47, 0x02, 0x01, 0xEB, 0x41, 0x01, 0x80, 0xF8, 0x5A, 0x21, ++0x03, 0xEB, 0xC1, 0x01, 0xA2, 0x88, 0x0A, 0x81, 0x32, 0x46, 0x41, 0x46, 0x03, 0x23, 0x29, 0x20, 0x08, 0xF0, 0x0C, 0xF8, ++0x62, 0x78, 0x02, 0x70, 0xA2, 0x78, 0x42, 0x70, 0x85, 0x70, 0x08, 0xF0, 0x35, 0xF8, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, ++0x48, 0x78, 0x0B, 0x49, 0xA2, 0x88, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0x10, 0xA1, 0x78, 0x14, 0xF0, 0xA0, 0xFB, ++0x08, 0xB9, 0x04, 0x25, 0xE2, 0xE7, 0x07, 0x49, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x00, 0x25, 0xDB, 0xE7, ++0xC0, 0xB2, 0x15, 0x00, 0x7C, 0x28, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x54, 0x00, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x43, 0x04, 0x46, 0x87, 0xB0, 0x10, 0x46, 0x15, 0x46, 0x0E, 0x46, 0x1F, 0x46, 0x08, 0xF0, 0x7C, 0xFA, ++0x40, 0xB1, 0x02, 0x38, 0x80, 0xB2, 0x02, 0x28, 0x4D, 0xD8, 0x02, 0x24, 0x20, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, ++0xDF, 0xF8, 0x88, 0x83, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x65, 0xDB, 0x3B, 0x2C, 0x00, 0xF2, ++0xA7, 0x80, 0x05, 0x2C, 0x40, 0xF2, 0xE3, 0x80, 0x06, 0x3C, 0x35, 0x2C, 0x4A, 0xD8, 0xDF, 0xE8, 0x14, 0xF0, 0xBF, 0x01, ++0x49, 0x00, 0xB5, 0x01, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x88, 0x01, 0x49, 0x00, 0x6E, 0x01, ++0x49, 0x00, 0x5A, 0x01, 0x49, 0x00, 0x50, 0x01, 0x49, 0x00, 0x3A, 0x01, 0x49, 0x00, 0x30, 0x01, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0x1D, 0x01, 0x49, 0x00, 0x13, 0x01, 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0xF6, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0xEF, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0x49, 0x00, 0xE2, 0x00, 0xB1, 0x4B, 0xB1, 0x4C, 0x1B, 0x68, 0x28, 0x46, 0x03, 0xF0, 0x0F, 0x03, 0xE3, 0x74, ++0x08, 0xF0, 0x20, 0xFA, 0xAE, 0x4B, 0xA0, 0x74, 0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x28, 0x46, 0x02, 0x21, 0x08, 0xF0, ++0x6F, 0xF9, 0x9E, 0xE7, 0xDF, 0xF8, 0xA0, 0x82, 0x02, 0x24, 0x98, 0xF8, 0x13, 0x30, 0xA5, 0x4A, 0x1B, 0x01, 0xDB, 0xB2, ++0x13, 0x60, 0x28, 0x46, 0x98, 0xF8, 0x12, 0x10, 0x08, 0xF0, 0x60, 0xF9, 0x20, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, ++0x9E, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x40, 0xF0, 0x6F, 0x81, 0x3B, 0x2C, 0x67, 0xD8, 0x05, 0x2C, 0x67, 0xD9, 0x06, 0x3C, ++0x35, 0x2C, 0x64, 0xD8, 0xDF, 0xE8, 0x14, 0xF0, 0x56, 0x01, 0x63, 0x00, 0x4C, 0x01, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, ++0x63, 0x00, 0x63, 0x00, 0x1F, 0x01, 0x63, 0x00, 0x05, 0x01, 0x63, 0x00, 0xF1, 0x00, 0x63, 0x00, 0xE7, 0x00, 0x63, 0x00, ++0xD1, 0x00, 0x63, 0x00, 0xC7, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0xB4, 0x00, 0x63, 0x00, 0xAA, 0x00, 0x63, 0x00, ++0x97, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x8D, 0x00, 0x63, 0x00, ++0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x86, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, ++0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x79, 0x00, 0x87, 0x2C, 0x3C, 0xD1, ++0xDF, 0xF8, 0xF0, 0x81, 0xDF, 0xF8, 0xF0, 0x91, 0x00, 0x27, 0x88, 0xF8, 0x30, 0x70, 0x30, 0x68, 0xD9, 0xF8, 0xF8, 0x30, ++0x98, 0x47, 0x04, 0x46, 0x00, 0x28, 0x40, 0xF0, 0x19, 0x81, 0x98, 0xF8, 0x31, 0x30, 0x00, 0x2B, 0x97, 0xD0, 0x05, 0xA8, ++0x88, 0xF8, 0x31, 0x40, 0x01, 0xF0, 0x74, 0xFD, 0x00, 0x28, 0x90, 0xD0, 0x05, 0x9A, 0x71, 0x49, 0x92, 0xF8, 0x63, 0x30, ++0x92, 0xF8, 0xC1, 0x04, 0x03, 0xEB, 0xC3, 0x02, 0x03, 0xEB, 0x42, 0x03, 0x01, 0xEB, 0x43, 0x01, 0x05, 0xF0, 0x9C, 0xFF, ++0x81, 0xE7, 0x87, 0x2C, 0xD4, 0xD0, 0x6A, 0x49, 0x6A, 0x48, 0xDF, 0xF8, 0x98, 0x81, 0x40, 0xF6, 0x06, 0x22, 0x09, 0xF0, ++0xCB, 0xFF, 0x02, 0x24, 0x75, 0xE7, 0x87, 0x2C, 0xC8, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xED, 0xDB, 0xDF, 0xF8, 0x78, 0x81, 0x02, 0x24, 0x69, 0xE7, 0x5D, 0x4B, 0xDF, 0xF8, 0x6C, 0x81, 0x9B, 0x6D, 0x30, 0x46, ++0x98, 0x47, 0x2A, 0x46, 0x39, 0x46, 0x3C, 0x20, 0x07, 0xF0, 0x38, 0xFF, 0x00, 0x24, 0x5C, 0xE7, 0x30, 0x46, 0x09, 0xF0, ++0xD3, 0xFF, 0xDF, 0xF8, 0x50, 0x81, 0x00, 0x24, 0x55, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x28, 0x20, 0xFF, 0xF7, ++0x7B, 0xFE, 0xDF, 0xF8, 0x3C, 0x81, 0x04, 0x46, 0x4B, 0xE7, 0x52, 0x4B, 0x32, 0x78, 0x1B, 0x68, 0x51, 0x48, 0xDF, 0xF8, ++0x2C, 0x81, 0xDB, 0xB2, 0x03, 0xFB, 0x02, 0xF3, 0x42, 0xEA, 0x03, 0x23, 0x03, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x21, 0x20, ++0x07, 0xF0, 0x14, 0xFF, 0x00, 0x24, 0x38, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x1E, 0x20, 0xFF, 0xF7, 0xD4, 0xFA, ++0xDF, 0xF8, 0x00, 0x81, 0x04, 0x46, 0x2E, 0xE7, 0x45, 0x48, 0x33, 0x78, 0x02, 0x68, 0xDF, 0xF8, 0xF4, 0x80, 0x9B, 0x03, ++0x22, 0xF4, 0xE0, 0x32, 0x03, 0xF4, 0xE0, 0x33, 0x13, 0x43, 0x03, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x1D, 0x20, 0x07, 0xF0, ++0xF7, 0xFE, 0x00, 0x24, 0x1B, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x18, 0x20, 0xFF, 0xF7, 0x77, 0xFA, 0xDF, 0xF8, ++0xC8, 0x80, 0x04, 0x46, 0x11, 0xE7, 0x73, 0x79, 0xDF, 0xF8, 0xBC, 0x80, 0x36, 0x4A, 0x31, 0x68, 0x92, 0x6A, 0x08, 0xEB, ++0x83, 0x00, 0x41, 0x61, 0x22, 0xB1, 0x12, 0x79, 0x9A, 0x42, 0x04, 0xBF, 0x32, 0x4B, 0x19, 0x60, 0x39, 0x46, 0x2A, 0x46, ++0x17, 0x20, 0x07, 0xF0, 0xD7, 0xFE, 0x00, 0x24, 0xFB, 0xE6, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x14, 0x20, 0xFF, 0xF7, ++0x2B, 0xFA, 0xDF, 0xF8, 0x88, 0x80, 0x04, 0x46, 0xF1, 0xE6, 0x2A, 0x4A, 0x31, 0x78, 0x13, 0x68, 0xDF, 0xF8, 0x78, 0x80, ++0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x39, 0x46, 0x2A, 0x46, ++0x13, 0x20, 0x07, 0xF0, 0xB9, 0xFE, 0x00, 0x24, 0xDD, 0xE6, 0x39, 0x46, 0x02, 0x23, 0x2A, 0x46, 0x11, 0x20, 0x07, 0xF0, ++0x49, 0xFE, 0x72, 0x7A, 0xF3, 0x88, 0xB1, 0x7A, 0x02, 0x91, 0xCD, 0xE9, 0x00, 0x32, 0x04, 0x46, 0xB3, 0x88, 0x72, 0x88, ++0x71, 0x78, 0x30, 0x78, 0xDF, 0xF8, 0x34, 0x80, 0xE6, 0xF7, 0x1E, 0xFA, 0x20, 0x46, 0x07, 0xF0, 0x67, 0xFE, 0x00, 0x24, ++0xC3, 0xE6, 0xDF, 0xF8, 0x24, 0x80, 0x33, 0x68, 0xD8, 0xF8, 0x04, 0x10, 0x11, 0x4A, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0x43, ++0x13, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x0F, 0x20, 0x07, 0xF0, 0x8E, 0xFE, 0x00, 0x24, 0xB2, 0xE6, 0x38, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0xE4, 0x00, 0x32, 0x40, 0xE8, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x30, 0x9D, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, ++0x90, 0x00, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x08, 0x20, ++0xFF, 0xF7, 0x96, 0xFD, 0xDF, 0xF8, 0x2C, 0x81, 0x04, 0x46, 0x8C, 0xE6, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x06, 0x20, ++0xFF, 0xF7, 0x72, 0xFD, 0xDF, 0xF8, 0x18, 0x81, 0x04, 0x46, 0x82, 0xE6, 0xD9, 0xF8, 0x6C, 0x31, 0x30, 0x68, 0x98, 0x47, ++0x3C, 0x46, 0x7C, 0xE6, 0x3F, 0x49, 0x40, 0x48, 0x40, 0xF6, 0xC9, 0x12, 0x09, 0xF0, 0xCA, 0xFE, 0x3B, 0x2C, 0x3F, 0xF6, ++0xFE, 0xAE, 0x05, 0x2C, 0x7F, 0xF6, 0xFD, 0xAE, 0x06, 0x3C, 0x35, 0x2C, 0x3F, 0xF6, 0xF9, 0xAE, 0x01, 0xA3, 0x53, 0xF8, ++0x24, 0xF0, 0x00, 0xBF, 0xBD, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xA9, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x4F, 0xAD, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0x1B, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xF3, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xDF, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xB3, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x9F, 0xAC, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x79, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0x65, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x3F, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0x2B, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x1D, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x03, 0xAC, 0x13, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xC0, 0x68, 0xCB, 0x68, 0xC0, 0x1A, 0xC0, 0x0F, ++0x70, 0x47, 0x00, 0xBF, 0x01, 0x48, 0x08, 0xF0, 0xE9, 0xB9, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, 0x06, 0x4B, 0x38, 0xB1, ++0xC1, 0x68, 0x04, 0x22, 0x4F, 0xF4, 0x80, 0x20, 0x98, 0x60, 0x19, 0x63, 0x9A, 0x60, 0x70, 0x47, 0x4F, 0xF4, 0x80, 0x62, ++0x9A, 0x60, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x33, 0x4A, 0xF8, 0xB5, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0x0C, 0x46, ++0x05, 0x46, 0x57, 0xDB, 0x30, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x46, 0xDB, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2B, 0x4F, 0x2C, 0x4E, 0x3B, 0x68, 0x32, 0x68, ++0x01, 0x33, 0x95, 0x42, 0x3B, 0x60, 0x19, 0xD0, 0x29, 0x46, 0x30, 0x46, 0x08, 0xF0, 0x08, 0xFA, 0x30, 0x46, 0x27, 0x4A, ++0xEC, 0x60, 0x29, 0x46, 0x08, 0xF0, 0x40, 0xFA, 0x30, 0x68, 0x85, 0x42, 0x16, 0xD0, 0x3B, 0x68, 0x23, 0xB1, 0x1F, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0xA3, 0xB1, 0x1A, 0x4B, 0x19, 0x69, 0x64, 0x1A, 0x00, 0x2C, 0x17, 0xDB, 0xF8, 0xBD, ++0x30, 0x46, 0x08, 0xF0, 0xE3, 0xF9, 0x30, 0x46, 0x1A, 0x4A, 0xEC, 0x60, 0x29, 0x46, 0x08, 0xF0, 0x27, 0xFA, 0x30, 0x68, ++0x18, 0x4B, 0xD3, 0xF8, 0xDC, 0x31, 0x98, 0x47, 0xE3, 0xE7, 0x00, 0x2A, 0xE8, 0xD0, 0x62, 0xB6, 0x0E, 0x4B, 0x19, 0x69, ++0x64, 0x1A, 0x00, 0x2C, 0xE7, 0xDA, 0xBD, 0xE8, 0xF8, 0x40, 0x4F, 0xF0, 0x80, 0x40, 0x08, 0xF0, 0xE3, 0xB8, 0x09, 0x4B, ++0x1B, 0x69, 0xE3, 0x1A, 0x00, 0x2B, 0xB3, 0xDA, 0x0D, 0x49, 0x0E, 0x48, 0x7D, 0x22, 0x09, 0xF0, 0xCF, 0xFD, 0xAD, 0xE7, ++0x13, 0x69, 0x41, 0x68, 0x0B, 0x48, 0x22, 0x46, 0x09, 0xF0, 0x4E, 0xFB, 0xA0, 0xE7, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, ++0x38, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, 0xE9, 0xAE, 0x13, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x74, 0x9F, 0x15, 0x00, 0x4C, 0x9F, 0x15, 0x00, 0x38, 0xB5, 0x01, 0x46, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0F, 0x4C, 0x10, 0x4D, ++0x23, 0x68, 0x2A, 0x68, 0x01, 0x33, 0x8A, 0x42, 0x23, 0x60, 0x28, 0x46, 0x0B, 0xD0, 0x08, 0xF0, 0x99, 0xF9, 0x23, 0x68, ++0x33, 0xB1, 0x08, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x08, 0xF0, ++0x81, 0xF9, 0x06, 0x4B, 0x28, 0x68, 0xD3, 0xF8, 0xDC, 0x31, 0x98, 0x47, 0xED, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x2C, 0x4F, 0x2D, 0x4D, ++0xDF, 0xF8, 0xC8, 0xA0, 0xDF, 0xF8, 0xC0, 0x80, 0x2B, 0x4E, 0xB9, 0x46, 0x01, 0xE0, 0xA0, 0x68, 0x98, 0x47, 0x4F, 0xF0, ++0x80, 0x40, 0x08, 0xF0, 0x9F, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, ++0x00, 0x30, 0x2B, 0x68, 0x3C, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x4C, 0xB3, 0x32, 0x69, 0xE3, 0x68, 0x9B, 0x1A, 0x32, 0x2B, ++0x08, 0xD4, 0xDA, 0xF8, 0xDC, 0x31, 0x20, 0x46, 0x98, 0x47, 0x32, 0x69, 0xE3, 0x68, 0x9B, 0x1A, 0x00, 0x2B, 0x2A, 0xDA, ++0x48, 0x46, 0x08, 0xF0, 0x43, 0xF9, 0x2B, 0x68, 0x33, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x63, 0x68, 0xCB, 0xDA, 0x00, 0x2B, ++0xC9, 0xD1, 0x11, 0x49, 0x11, 0x48, 0xEB, 0x22, 0x09, 0xF0, 0x3C, 0xFD, 0x63, 0x68, 0xC2, 0xE7, 0xDA, 0xF8, 0xDC, 0x31, ++0x20, 0x46, 0x98, 0x47, 0x2B, 0x68, 0x33, 0xB1, 0x0C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF0, 0x87, 0x2B, 0x68, 0x00, 0x2B, 0xFA, 0xD0, 0xF2, 0xE7, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x9F, 0x15, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x11, 0xF4, 0x00, 0x05, 0x04, 0x46, 0x0E, 0xD1, 0x90, 0xF8, ++0x5C, 0x22, 0x1E, 0x49, 0x1E, 0x48, 0x01, 0x32, 0xD2, 0xB2, 0x84, 0xF8, 0x5C, 0x22, 0x09, 0xF0, 0x8D, 0xFA, 0x94, 0xF8, ++0x5C, 0x32, 0x09, 0x2B, 0x15, 0xD8, 0x70, 0xBD, 0x17, 0x49, 0x19, 0x48, 0x09, 0xF0, 0x84, 0xFA, 0x94, 0xF8, 0x23, 0x30, ++0x00, 0x22, 0x0D, 0x2B, 0x84, 0xF8, 0x5C, 0x22, 0xF3, 0xD8, 0x15, 0x49, 0x15, 0x4A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x03, 0x13, 0x12, 0x69, 0xC3, 0xF8, 0x58, 0x22, 0x70, 0xBD, 0x2A, 0x46, 0x08, 0x23, 0x0C, 0x21, 0x7D, 0x20, 0x07, 0xF0, ++0x05, 0xFC, 0x94, 0xF8, 0x23, 0x30, 0x03, 0x70, 0x94, 0xF8, 0x22, 0x30, 0x43, 0x70, 0x06, 0x46, 0x04, 0xF1, 0x26, 0x01, ++0x84, 0xF8, 0x5C, 0x52, 0x02, 0x30, 0x06, 0x22, 0x1B, 0xF0, 0x7E, 0xFF, 0x30, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x07, 0xF0, ++0x21, 0xBC, 0x00, 0xBF, 0x34, 0xA0, 0x15, 0x00, 0x9C, 0x9F, 0x15, 0x00, 0xB4, 0x9F, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x63, 0x30, 0x63, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x0A, 0x33, ++0x04, 0xFB, 0x03, 0xF3, 0x11, 0x46, 0x02, 0xF1, 0x28, 0x04, 0x1C, 0x44, 0x1A, 0x44, 0x83, 0xB0, 0x0B, 0x46, 0xD2, 0xF8, ++0x08, 0x12, 0x00, 0x29, 0x40, 0xF0, 0xA2, 0x80, 0xD2, 0xF8, 0x30, 0x12, 0x08, 0x32, 0x00, 0x29, 0x40, 0xF0, 0x9C, 0x80, ++0xA2, 0x42, 0xF2, 0xD1, 0x57, 0x4A, 0x58, 0x4C, 0xDF, 0xF8, 0x70, 0xB1, 0x4F, 0xF4, 0xA4, 0x61, 0x93, 0xF8, 0x25, 0x60, ++0x2E, 0xB1, 0x93, 0xF8, 0x22, 0x60, 0x01, 0xFB, 0x06, 0x46, 0xB0, 0x42, 0x06, 0xD0, 0x03, 0xF5, 0x1E, 0x73, 0x9A, 0x42, ++0xF2, 0xD1, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x93, 0xF8, 0x23, 0x60, 0x0D, 0x2E, 0x77, 0xD9, 0x4F, 0xF0, 0x00, 0x08, ++0xDB, 0xF8, 0x10, 0xE0, 0x1E, 0x46, 0x03, 0xF1, 0x28, 0x0C, 0xD6, 0xF8, 0x08, 0x72, 0x77, 0xB9, 0xD6, 0xF8, 0x30, 0x72, ++0x08, 0x36, 0x57, 0xB9, 0xB4, 0x45, 0xF6, 0xD1, 0xCE, 0xF5, 0x64, 0x0E, 0x0E, 0xF5, 0x61, 0x4E, 0x0E, 0xF1, 0xC0, 0x0E, ++0x1E, 0xEB, 0x08, 0x0F, 0xDB, 0xD5, 0x90, 0xF8, 0x63, 0x60, 0x93, 0xF8, 0x20, 0xE0, 0x00, 0x96, 0x35, 0x46, 0xC6, 0xEB, ++0x86, 0x17, 0x3C, 0x4E, 0x4F, 0xEA, 0xDE, 0x08, 0x06, 0xEB, 0x87, 0x07, 0x0E, 0xF0, 0x07, 0x0C, 0x01, 0x26, 0x18, 0xF8, ++0x07, 0x90, 0x06, 0xFA, 0x0C, 0xFC, 0x1C, 0xEA, 0x09, 0x0F, 0x07, 0xEB, 0xDE, 0x06, 0x01, 0x96, 0x5F, 0xFA, 0x8C, 0xFA, ++0x0F, 0xFA, 0x85, 0xFE, 0xBD, 0xD1, 0x4A, 0xEA, 0x09, 0x09, 0x08, 0xF8, 0x07, 0x90, 0xB0, 0xF8, 0xD0, 0x90, 0x90, 0xF8, ++0xD8, 0xC0, 0x09, 0xF1, 0x01, 0x09, 0xC4, 0x45, 0xA0, 0xF8, 0xD0, 0x90, 0x3E, 0xD8, 0xAF, 0x00, 0x90, 0xF8, 0xD9, 0x90, ++0xC1, 0x45, 0x0B, 0xD2, 0x00, 0x9D, 0x28, 0x4E, 0x80, 0xF8, 0xD9, 0x80, 0x07, 0xEB, 0x05, 0x0A, 0x06, 0xEB, 0xCA, 0x0A, ++0x01, 0x9E, 0xCA, 0xF8, 0x20, 0x60, 0xC1, 0x46, 0x23, 0x4E, 0x00, 0x9D, 0xCC, 0xF1, 0x06, 0x0C, 0xCC, 0x44, 0x06, 0xEB, ++0xCE, 0x0E, 0x1F, 0xFA, 0x8C, 0xFC, 0x1E, 0x4E, 0xA0, 0xF8, 0xCE, 0xC0, 0xAC, 0xF1, 0x02, 0x08, 0x8E, 0xF8, 0x01, 0x80, ++0x4F, 0xF0, 0x28, 0x0C, 0x2F, 0x44, 0x06, 0xEB, 0xC7, 0x07, 0x0C, 0xFB, 0x05, 0x66, 0x90, 0xF8, 0xD8, 0xC0, 0x8E, 0xF8, ++0x04, 0xC0, 0x14, 0x36, 0x0E, 0xF1, 0x04, 0x0E, 0xC7, 0xF8, 0x0C, 0xE0, 0x7E, 0x60, 0x7C, 0xE7, 0x0D, 0x4D, 0x4F, 0xF4, ++0x1E, 0x77, 0x07, 0xFB, 0x06, 0x56, 0xD6, 0xF8, 0x58, 0x82, 0x81, 0xE7, 0x0F, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x61, 0xE7, ++0x00, 0x9D, 0x0B, 0x4E, 0x05, 0xEB, 0x85, 0x09, 0x08, 0xF0, 0x1E, 0x0C, 0x06, 0xEB, 0xC9, 0x09, 0x67, 0x44, 0x80, 0xF8, ++0xD8, 0xC0, 0xC9, 0xF8, 0x1C, 0x70, 0xAF, 0x00, 0xB2, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x7E, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x3C, 0x4C, 0x18, 0x00, 0x9C, 0x4B, 0x18, 0x00, 0x2C, 0x50, 0x18, 0x00, 0x16, 0x2C, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF8, 0x43, 0x02, 0x88, 0xC3, 0x78, 0x04, 0x46, 0xB2, 0xB9, 0x82, 0x78, 0x00, 0x2A, ++0x40, 0xF0, 0xAD, 0x80, 0x88, 0x48, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x03, 0x83, 0xF8, 0xDA, 0x20, 0x34, 0xF8, ++0x04, 0x1C, 0x42, 0x20, 0x00, 0x22, 0x07, 0xF0, 0x5B, 0xFB, 0xA4, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0xF8, 0x43, 0x07, 0xF0, ++0x69, 0xBB, 0x80, 0x48, 0x80, 0x4D, 0x94, 0xF8, 0x02, 0xE0, 0xC3, 0xEB, 0x83, 0x11, 0x00, 0xEB, 0x81, 0x00, 0x01, 0x26, ++0xC2, 0xF3, 0xC7, 0x01, 0x02, 0xF0, 0x07, 0x02, 0x06, 0xFA, 0x02, 0xF2, 0x0F, 0x5C, 0x0E, 0x18, 0x5F, 0xFA, 0x82, 0xFC, ++0x05, 0xEB, 0xC3, 0x05, 0xBE, 0xF1, 0x00, 0x0F, 0x4D, 0xD0, 0x1C, 0xEA, 0x07, 0x0F, 0xD8, 0xD1, 0xDF, 0xF8, 0xC4, 0xE1, ++0x4F, 0xF4, 0xA4, 0x62, 0x4C, 0xEA, 0x07, 0x07, 0x02, 0xFB, 0x03, 0xE2, 0x37, 0x70, 0xB2, 0xF8, 0xD0, 0x70, 0x92, 0xF8, ++0xD8, 0xC0, 0x01, 0x37, 0x8C, 0x45, 0xA2, 0xF8, 0xD0, 0x70, 0x6C, 0x4F, 0x0A, 0xD9, 0x03, 0xEB, 0x83, 0x0C, 0x01, 0xF0, ++0xFE, 0x08, 0x07, 0xEB, 0xCC, 0x0C, 0x40, 0x44, 0xCC, 0xF8, 0x1C, 0x00, 0x82, 0xF8, 0xD8, 0x80, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x03, 0xE0, 0x4F, 0xEA, 0x83, 0x0C, 0x90, 0xF8, 0xD9, 0x80, 0x88, 0x45, 0x07, 0xD2, 0x0C, 0xEB, 0x03, 0x02, ++0x07, 0xEB, 0xC2, 0x02, 0x80, 0xF8, 0xD9, 0x10, 0x88, 0x46, 0x16, 0x62, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xEE, ++0x0C, 0xEB, 0x03, 0x01, 0x9E, 0xF8, 0xD8, 0x20, 0x2A, 0x71, 0xC2, 0xF1, 0x06, 0x02, 0x28, 0x20, 0x42, 0x44, 0x07, 0xEB, ++0xC1, 0x01, 0x00, 0xFB, 0x03, 0x73, 0x92, 0xB2, 0x2E, 0x1D, 0x14, 0x33, 0x90, 0x1E, 0xCE, 0x60, 0x4B, 0x60, 0xAE, 0xF8, ++0xCE, 0x20, 0x68, 0x70, 0x8D, 0xE7, 0x1C, 0xEA, 0x07, 0x0F, 0x8A, 0xD0, 0xDF, 0xF8, 0x28, 0xE1, 0x4F, 0xF4, 0xA4, 0x68, ++0x08, 0xFB, 0x03, 0xF8, 0x27, 0xEA, 0x02, 0x02, 0x0E, 0xEB, 0x08, 0x0C, 0x32, 0x70, 0xBC, 0xF8, 0xD0, 0x70, 0x01, 0x3F, ++0xBF, 0xB2, 0xAC, 0xF8, 0xD0, 0x70, 0x00, 0x2F, 0x4D, 0xD0, 0x9C, 0xF8, 0xD8, 0x70, 0x01, 0xF0, 0xFE, 0x02, 0x97, 0x42, ++0x29, 0xD0, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE2, 0x92, 0xF8, 0xD9, 0x70, 0x8F, 0x42, 0x35, 0xD0, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE3, 0x93, 0xF8, 0xD8, 0x10, 0x29, 0x71, 0xC1, 0xF1, 0x06, 0x01, 0x39, 0x44, 0x89, 0xB2, ++0x8A, 0x1E, 0xA3, 0xF8, 0xCE, 0x10, 0x6A, 0x70, 0x59, 0xE7, 0x32, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x13, ++0x01, 0x22, 0x83, 0xF8, 0xDA, 0x20, 0x50, 0xE7, 0x3A, 0x5C, 0x07, 0xF1, 0x01, 0x08, 0x00, 0x2A, 0x51, 0xD1, 0x5F, 0xFA, ++0x88, 0xF7, 0x8C, 0xF8, 0xD8, 0x70, 0xFB, 0x2F, 0xF4, 0xD1, 0xFA, 0x22, 0x17, 0x46, 0xDF, 0xF8, 0xA8, 0x90, 0x03, 0xEB, ++0x83, 0x08, 0x4F, 0xF4, 0xA4, 0x6C, 0x09, 0xEB, 0xC8, 0x08, 0x0C, 0xFB, 0x03, 0xEC, 0x02, 0x44, 0xC8, 0xF8, 0x1C, 0x20, ++0x8C, 0xF8, 0xD8, 0x70, 0xC1, 0xE7, 0x41, 0xB3, 0x37, 0x78, 0x01, 0x39, 0xB4, 0x46, 0xC9, 0xB2, 0x01, 0x3E, 0x57, 0xBB, ++0x82, 0xF8, 0xD9, 0x10, 0xF5, 0xE7, 0x0E, 0xF1, 0xD8, 0x02, 0x06, 0x21, 0xAC, 0xF8, 0xCE, 0x10, 0xFF, 0x21, 0x28, 0xF8, ++0x02, 0x10, 0x19, 0x4A, 0x9C, 0xF8, 0xCE, 0x10, 0x2F, 0x71, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x6E, 0x1D, ++0x8A, 0x1E, 0xDE, 0x60, 0x6A, 0x70, 0xE2, 0x78, 0x9C, 0xF8, 0xD9, 0x50, 0x12, 0x49, 0x02, 0xEB, 0x82, 0x02, 0x28, 0x44, ++0x01, 0xEB, 0x82, 0x02, 0x18, 0x62, 0x5A, 0x60, 0x09, 0xE7, 0x0F, 0x46, 0x0C, 0x4A, 0x03, 0xEB, 0x83, 0x01, 0x02, 0xEB, ++0xC1, 0x02, 0x10, 0x62, 0x97, 0xE7, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE2, 0x60, 0x46, 0x92, 0xF8, 0xD9, 0x70, ++0xF0, 0xE7, 0x07, 0xF0, 0xFE, 0x07, 0x3A, 0x46, 0xB1, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x3C, 0x4C, 0x18, 0x00, ++0x2C, 0x50, 0x18, 0x00, 0x9C, 0x4B, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x89, 0x46, 0xD0, 0xF8, ++0xB8, 0x50, 0x89, 0x88, 0x99, 0xF8, 0x08, 0xA0, 0x90, 0xF8, 0x63, 0xB0, 0xD5, 0xF8, 0x24, 0x80, 0x2A, 0x4B, 0xB9, 0xF8, ++0x06, 0x70, 0xD3, 0xF8, 0x54, 0x31, 0x29, 0x4E, 0xA1, 0xEB, 0x0A, 0x0A, 0x04, 0x46, 0x42, 0x46, 0xA0, 0xF8, 0xCC, 0xA0, ++0x58, 0x46, 0x98, 0x47, 0xB9, 0xF8, 0x06, 0x30, 0x6A, 0x6A, 0x21, 0x6C, 0x23, 0x48, 0x03, 0xF1, 0xFF, 0x3C, 0x62, 0x44, ++0xAA, 0x62, 0x99, 0xF8, 0x08, 0xC0, 0x06, 0xEB, 0xCB, 0x06, 0xDB, 0x43, 0x0B, 0xEB, 0x8B, 0x0B, 0x0C, 0xF1, 0x01, 0x0C, ++0x00, 0xEB, 0x8B, 0x0B, 0x62, 0x44, 0x53, 0x44, 0x13, 0x44, 0x00, 0x20, 0xCB, 0xE9, 0x02, 0x23, 0x03, 0x37, 0xCB, 0xF8, ++0x10, 0x00, 0x31, 0xB3, 0x94, 0xF8, 0xC0, 0x34, 0x0A, 0x79, 0x16, 0x49, 0xE3, 0xB1, 0x16, 0x4A, 0x16, 0x48, 0x13, 0x68, ++0x12, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0x00, 0x22, 0x4B, 0x62, 0xC5, 0xE9, 0x0D, 0x21, 0xE8, 0x64, ++0x94, 0xF8, 0x63, 0x30, 0x10, 0x4A, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x01, 0x22, 0x2B, 0x62, 0x84, 0xF8, ++0xD6, 0x20, 0x18, 0xF8, 0x07, 0x30, 0xF3, 0x70, 0xBD, 0xE8, 0xF8, 0x8F, 0x0A, 0x4B, 0x82, 0x42, 0x08, 0xBF, 0x19, 0x46, ++0xDD, 0xE7, 0x04, 0x49, 0xDB, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x50, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, ++0x84, 0x3C, 0x18, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x41, 0x00, 0x00, 0x01, 0x9C, 0x4B, 0x18, 0x00, 0xC4, 0x3C, 0x18, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x4D, 0x4D, 0x90, 0xF8, 0x63, 0x30, 0xD0, 0xF8, 0xB8, 0x80, 0x05, 0xEB, 0xC3, 0x05, 0x04, 0x46, ++0x2F, 0x79, 0x00, 0xF1, 0x6C, 0x06, 0xFF, 0xF7, 0x7D, 0xFD, 0xB0, 0xF8, 0xCC, 0x30, 0xB0, 0xF8, 0xCE, 0x20, 0x13, 0x44, ++0x04, 0x33, 0xC8, 0xF8, 0x2C, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x54, 0xD1, 0x42, 0x4A, 0xD8, 0xF8, 0x24, 0x10, ++0xB2, 0xF8, 0xFC, 0x31, 0x01, 0x33, 0x9B, 0xB2, 0x18, 0x01, 0xA2, 0xF8, 0xFC, 0x31, 0xC8, 0x82, 0x94, 0xF8, 0xD7, 0x30, ++0xAB, 0x70, 0x94, 0xF8, 0xDA, 0x90, 0xCB, 0xBB, 0xB9, 0xF1, 0x00, 0x0F, 0x31, 0xD1, 0x07, 0xF0, 0xFE, 0x07, 0x38, 0x4B, ++0x1B, 0x78, 0x0B, 0xB1, 0x47, 0xF0, 0x01, 0x07, 0xEB, 0x78, 0x84, 0xF8, 0xD7, 0x30, 0x2F, 0x71, 0x94, 0xF8, 0xD7, 0x30, ++0x94, 0xF8, 0xDB, 0x50, 0x01, 0x3B, 0x84, 0xF8, 0xD7, 0x30, 0xBD, 0xB1, 0x01, 0x3D, 0x94, 0xF8, 0xDC, 0x30, 0xED, 0xB2, ++0x84, 0xF8, 0xDB, 0x50, 0x63, 0xB1, 0xD8, 0xF8, 0x24, 0x20, 0xD5, 0x54, 0x94, 0xF8, 0xDD, 0x30, 0x23, 0xB1, 0xD8, 0xF8, ++0x24, 0x20, 0x94, 0xF8, 0xDB, 0x10, 0xD1, 0x54, 0x94, 0xF8, 0xDB, 0x50, 0x7D, 0xBB, 0x01, 0x23, 0x84, 0xF8, 0xDB, 0x30, ++0x20, 0x46, 0x31, 0x46, 0x06, 0xF0, 0xE0, 0xFC, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x47, 0xF0, 0x01, 0x07, 0x4F, 0xF0, ++0x01, 0x09, 0xCA, 0xE7, 0x19, 0xF0, 0x02, 0x09, 0x1A, 0xBF, 0x47, 0xF0, 0x01, 0x07, 0x4F, 0xF0, 0x01, 0x09, 0x07, 0xF0, ++0xFE, 0x07, 0xC8, 0xE7, 0x90, 0xF8, 0xC1, 0x04, 0x05, 0xF0, 0x7E, 0xF9, 0x00, 0x28, 0xA4, 0xD0, 0x94, 0xF8, 0x63, 0x10, ++0x15, 0x4A, 0xD8, 0xF8, 0x2C, 0x30, 0x01, 0xEB, 0x81, 0x01, 0x02, 0xEB, 0x81, 0x02, 0x19, 0x18, 0x93, 0x68, 0xC8, 0xF8, ++0x2C, 0x10, 0x01, 0x3B, 0x18, 0x44, 0xD0, 0x60, 0x93, 0xE7, 0x02, 0x23, 0x00, 0x22, 0x0C, 0x21, 0x4E, 0x20, 0x94, 0xF8, ++0x63, 0x70, 0x07, 0xF0, 0xE3, 0xF8, 0x07, 0x70, 0x45, 0x70, 0x07, 0xF0, 0x0F, 0xF9, 0x94, 0xF8, 0xDB, 0x30, 0x00, 0x2B, ++0xBF, 0xD0, 0x20, 0x46, 0x31, 0x46, 0x06, 0xF0, 0xA3, 0xFC, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x2C, 0x50, 0x18, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x16, 0x2C, 0x17, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0xF8, 0xB5, 0x18, 0x4D, 0x18, 0x4F, 0x2E, 0x68, ++0x04, 0x46, 0x36, 0xF8, 0x04, 0x1C, 0x00, 0x22, 0x40, 0x20, 0x07, 0xF0, 0x29, 0xF9, 0xD7, 0xF8, 0x78, 0x31, 0x29, 0x68, ++0x20, 0x46, 0x98, 0x47, 0x2A, 0x68, 0x00, 0x23, 0x84, 0xF8, 0xDB, 0x30, 0x93, 0x7A, 0x84, 0xF8, 0xDC, 0x30, 0xD2, 0x7A, ++0x84, 0xF8, 0xDD, 0x20, 0x0C, 0x3E, 0xD4, 0xF8, 0xB8, 0x20, 0x23, 0xB1, 0x52, 0x6A, 0xD3, 0x5C, 0x01, 0x33, 0x84, 0xF8, ++0xDB, 0x30, 0x2B, 0x7A, 0x00, 0x22, 0x6A, 0x72, 0x13, 0xB1, 0xD7, 0xF8, 0x84, 0x31, 0x98, 0x47, 0x00, 0x23, 0x30, 0x46, ++0x2B, 0x60, 0xBD, 0xE8, 0xF8, 0x40, 0x07, 0xF0, 0x17, 0xB9, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0xB5, 0x0E, 0x4D, 0x44, 0x7A, 0x0E, 0x4A, 0x0E, 0x49, 0x03, 0x46, 0x4F, 0xF4, 0x1A, 0x70, 0x00, 0xFB, 0x04, 0x50, ++0x01, 0x25, 0x55, 0x72, 0x00, 0x25, 0x95, 0x72, 0x9A, 0x88, 0x68, 0x30, 0x1B, 0xF0, 0x0C, 0xFC, 0x08, 0x4A, 0x09, 0x4B, ++0x4F, 0xF4, 0xA4, 0x60, 0x29, 0x46, 0x00, 0xFB, 0x04, 0x20, 0xD3, 0xF8, 0x94, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, ++0xFC, 0x41, 0x18, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x14, 0x2A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x7E, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x1B, 0x68, 0x7D, 0x4D, 0xB3, 0xF9, 0x00, 0x30, 0x6E, 0x68, 0x00, 0x2B, 0x83, 0xB0, ++0x04, 0x46, 0x44, 0xDB, 0x01, 0x3E, 0x6E, 0x60, 0x00, 0x2E, 0x4D, 0xD0, 0xDF, 0xF8, 0xE0, 0x91, 0x77, 0x4D, 0x78, 0x4E, ++0x78, 0x4F, 0xDF, 0xF8, 0x00, 0xA2, 0xDF, 0xF8, 0x00, 0x82, 0x03, 0xE0, 0x05, 0xF5, 0x1E, 0x75, 0xB5, 0x42, 0x2F, 0xD0, ++0x95, 0xF8, 0x25, 0x20, 0x4F, 0xF4, 0xA4, 0x61, 0x00, 0x2A, 0xF5, 0xD0, 0x95, 0xF8, 0x22, 0x30, 0x01, 0xFB, 0x03, 0x73, ++0x9C, 0x42, 0xEF, 0xD1, 0x95, 0xF8, 0x23, 0x30, 0x0D, 0x2B, 0x9B, 0xBF, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x93, ++0x00, 0x22, 0xD3, 0xF8, 0x58, 0x22, 0xDA, 0xF8, 0x10, 0x30, 0xA8, 0xEB, 0x03, 0x03, 0xD3, 0x42, 0xDE, 0xD5, 0x20, 0x46, ++0xF2, 0xF7, 0x96, 0xFF, 0x00, 0x28, 0xD9, 0xD0, 0x63, 0x49, 0x95, 0xF8, 0x23, 0x00, 0x2A, 0x46, 0xF4, 0xF7, 0xAE, 0xFB, ++0x00, 0x28, 0xD1, 0xD1, 0x95, 0xF8, 0x23, 0x10, 0x5F, 0x48, 0x08, 0xF0, 0x89, 0xFE, 0xCB, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0x2E, 0xB8, 0xD1, 0x5C, 0x49, 0x5C, 0x48, 0x4F, 0xF4, 0x3F, 0x72, 0x09, 0xF0, 0xF7, 0xF8, 0x6E, 0x68, ++0x01, 0x3E, 0x6E, 0x60, 0x00, 0x2E, 0xB1, 0xD1, 0xDF, 0xF8, 0x74, 0xB1, 0xFC, 0xF7, 0xCC, 0xFF, 0x94, 0xF8, 0x63, 0x30, ++0x9B, 0xF8, 0x00, 0x20, 0x03, 0xF1, 0x0A, 0x08, 0x00, 0x2A, 0x58, 0xD1, 0xDF, 0xF8, 0x2C, 0x91, 0x51, 0x4B, 0x1B, 0x78, ++0x53, 0xB3, 0x08, 0xEB, 0x88, 0x02, 0x4F, 0xF4, 0x1E, 0x73, 0xC8, 0xEB, 0x02, 0x12, 0x4E, 0x4F, 0x01, 0x92, 0x03, 0xFB, ++0x08, 0x9B, 0x4F, 0xF0, 0x00, 0x0A, 0xDB, 0xF8, 0x08, 0x32, 0x5F, 0xFA, 0x8A, 0xF6, 0x0B, 0xF5, 0x02, 0x78, 0x53, 0xB1, ++0x40, 0x46, 0x07, 0xF0, 0xBB, 0xFC, 0xD7, 0xF8, 0x24, 0x34, 0x31, 0x46, 0x98, 0x47, 0xDB, 0xF8, 0x08, 0x32, 0x00, 0x2B, ++0xF4, 0xD1, 0xDB, 0xF8, 0x30, 0x22, 0x00, 0x2A, 0x5B, 0xD1, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x04, 0x0F, 0x0B, 0xF1, ++0x08, 0x0B, 0xE2, 0xD1, 0x3B, 0x4B, 0x1A, 0x70, 0xAB, 0x7A, 0x03, 0xBB, 0xEB, 0x68, 0x63, 0xB1, 0x39, 0x4F, 0xDF, 0xF8, ++0xF8, 0x80, 0xD7, 0xF8, 0xD4, 0x61, 0x40, 0x46, 0x07, 0xF0, 0x9A, 0xFC, 0x0C, 0x30, 0xB0, 0x47, 0xEB, 0x68, 0x00, 0x2B, ++0xF5, 0xD1, 0x94, 0xF8, 0x63, 0x00, 0x05, 0x44, 0x29, 0x7D, 0x19, 0xB1, 0x30, 0x4B, 0xD3, 0xF8, 0x90, 0x31, 0x98, 0x47, ++0x94, 0xF8, 0xDB, 0x30, 0x01, 0x2B, 0x7F, 0xF4, 0x59, 0xAF, 0x20, 0x46, 0xFB, 0xF7, 0xBE, 0xFA, 0x54, 0xE7, 0x2A, 0x4F, ++0x28, 0x68, 0xD7, 0xF8, 0x8C, 0x31, 0x98, 0x47, 0xD8, 0xE7, 0x04, 0x23, 0x32, 0x46, 0x0C, 0x21, 0x4A, 0x20, 0x06, 0xF0, ++0xA5, 0xFF, 0x80, 0xF8, 0x00, 0x80, 0x46, 0x70, 0x86, 0x70, 0x06, 0xF0, 0xCF, 0xFF, 0x9B, 0xF8, 0x00, 0x30, 0xDF, 0xF8, ++0x60, 0x90, 0x00, 0x2B, 0x96, 0xD0, 0x4F, 0xF4, 0x1E, 0x7A, 0x0A, 0xFB, 0x08, 0x9A, 0x9A, 0xF8, 0x31, 0x30, 0x9B, 0x07, ++0x0B, 0xD5, 0x1A, 0x4F, 0x09, 0x22, 0x8A, 0xF8, 0x32, 0x20, 0xD7, 0xF8, 0x20, 0x33, 0x32, 0x46, 0x51, 0x46, 0x20, 0x46, ++0x98, 0x47, 0x8A, 0xF8, 0x32, 0x60, 0x00, 0x23, 0x8B, 0xF8, 0x00, 0x30, 0x7E, 0xE7, 0x01, 0x98, 0x46, 0x30, 0x50, 0x44, ++0x09, 0xEB, 0xC0, 0x00, 0x07, 0xF0, 0x4C, 0xFC, 0x0E, 0x4B, 0x31, 0x46, 0xD3, 0xF8, 0x24, 0x34, 0x98, 0x47, 0x0D, 0x48, ++0x08, 0xF0, 0xDA, 0xFD, 0xFE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x7E, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x51, 0xB1, 0x13, 0x00, 0xF8, 0x9F, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0x9F, 0x15, 0x00, 0x16, 0x2C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xDC, 0x9F, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, ++0xC0, 0xE1, 0xE4, 0x00, 0x10, 0x2A, 0x17, 0x00, 0xE4, 0x9C, 0x17, 0x00, 0x38, 0xB5, 0x0E, 0x4D, 0x0E, 0x4C, 0x18, 0x22, ++0x00, 0x21, 0x28, 0x46, 0xE4, 0xF7, 0x42, 0xFB, 0x05, 0xF1, 0x0C, 0x00, 0x07, 0xF0, 0xCE, 0xFB, 0x20, 0x46, 0x04, 0xF0, ++0xD9, 0xFF, 0x04, 0xF1, 0x26, 0x00, 0x04, 0xF0, 0xD5, 0xFF, 0x04, 0xF1, 0x4C, 0x00, 0x04, 0xF0, 0xD1, 0xFF, 0x04, 0xF1, ++0x72, 0x00, 0xBD, 0xE8, 0x38, 0x40, 0x04, 0xF0, 0xCB, 0xBF, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x64, 0x3E, 0x18, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x90, 0xF8, 0x63, 0x30, 0x3F, 0x4D, 0x40, 0x49, 0x40, 0x4F, 0xDF, 0xF8, 0x1C, 0x91, 0x04, 0x46, ++0x03, 0xEB, 0x83, 0x02, 0x3E, 0x48, 0x4F, 0xF4, 0x1A, 0x76, 0x03, 0xEB, 0x42, 0x02, 0x06, 0xFB, 0x03, 0x11, 0x05, 0xEB, ++0xC2, 0x02, 0x00, 0xEB, 0x83, 0x13, 0x04, 0xF1, 0x6C, 0x00, 0xF4, 0xF7, 0xFD, 0xF8, 0x94, 0xF8, 0x63, 0x30, 0x37, 0x49, ++0xDF, 0xF8, 0xF0, 0xC0, 0x36, 0x48, 0x06, 0x22, 0xA4, 0xF8, 0xCE, 0x20, 0x00, 0x25, 0x01, 0xEB, 0xC3, 0x02, 0x4F, 0xF0, ++0x05, 0x0E, 0xFF, 0x26, 0xA4, 0xF8, 0xD8, 0x60, 0x84, 0xF8, 0xD7, 0x50, 0xA4, 0xF8, 0xD0, 0x50, 0x84, 0xF8, 0xDA, 0x50, ++0x04, 0x26, 0x01, 0xF8, 0x33, 0xE0, 0x56, 0x70, 0x94, 0xF8, 0xD7, 0x10, 0x91, 0x70, 0x01, 0x21, 0x15, 0x71, 0x55, 0x71, ++0xD1, 0x70, 0x94, 0xF8, 0xD9, 0x10, 0x03, 0xEB, 0x83, 0x08, 0xC3, 0xEB, 0x83, 0x16, 0x00, 0xEB, 0x86, 0x00, 0x0C, 0xEB, ++0xC8, 0x06, 0x01, 0x44, 0x07, 0xEB, 0x88, 0x03, 0x31, 0x62, 0x02, 0xEB, 0x0E, 0x01, 0xC6, 0xE9, 0x03, 0x15, 0x4C, 0xF8, ++0x38, 0x90, 0xB2, 0x60, 0x73, 0x60, 0xB3, 0x61, 0x29, 0x46, 0xFC, 0x22, 0xC6, 0xF8, 0x14, 0x90, 0xE4, 0xF7, 0xCE, 0xFA, ++0x07, 0xEB, 0x88, 0x03, 0x47, 0xF8, 0x28, 0x90, 0x5D, 0x60, 0x1D, 0x61, 0x94, 0xF8, 0xC0, 0x34, 0x93, 0xB1, 0x94, 0xF8, ++0x63, 0x30, 0x15, 0x48, 0x15, 0x49, 0x03, 0xEB, 0xC3, 0x02, 0x03, 0xEB, 0x42, 0x02, 0x03, 0xEB, 0x83, 0x03, 0x01, 0xEB, ++0x42, 0x01, 0x00, 0xEB, 0x83, 0x02, 0xC2, 0xE9, 0x01, 0x51, 0x40, 0xF8, 0x23, 0x90, 0x15, 0x61, 0xD4, 0xF8, 0xB8, 0x30, ++0x0D, 0x49, 0x00, 0x22, 0x5A, 0x63, 0xDA, 0x64, 0x1A, 0x62, 0xD1, 0xF8, 0x88, 0x31, 0xC4, 0xE9, 0x30, 0x34, 0xBD, 0xE8, ++0xF8, 0x83, 0x00, 0xBF, 0x9C, 0x40, 0x18, 0x00, 0xFC, 0x41, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, 0x4C, 0x3F, 0x18, 0x00, ++0x2C, 0x50, 0x18, 0x00, 0x3C, 0x4C, 0x18, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xDE, 0xFA, 0xFE, 0xCA, 0x9C, 0x4B, 0x18, 0x00, 0x05, 0x4B, 0x5A, 0x68, 0x18, 0x60, 0x12, 0xB1, 0x01, 0x22, 0x9A, 0x72, ++0x70, 0x47, 0x03, 0x4B, 0xD3, 0xF8, 0x8C, 0x31, 0x18, 0x47, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x06, 0x4B, 0x5A, 0x68, 0x1A, 0xB9, 0x06, 0x4B, 0xD3, 0xF8, 0xD4, 0x31, 0x18, 0x47, 0xA0, 0xF1, 0x0C, 0x01, 0x03, 0xF1, ++0x0C, 0x00, 0x07, 0xF0, 0x05, 0xBB, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x40, 0x4B, 0x41, 0x4A, 0x1B, 0x68, 0x94, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x3F, 0x4E, 0x00, 0x2B, 0x41, 0xDB, 0x75, 0x7A, ++0x00, 0x2D, 0x4A, 0xD1, 0x3D, 0x4A, 0x35, 0x72, 0x17, 0x68, 0x7F, 0x01, 0x6C, 0xB1, 0xDF, 0xF8, 0xF8, 0x90, 0xDF, 0xF8, ++0xF8, 0x80, 0xAA, 0x46, 0x4F, 0xF0, 0x01, 0x0B, 0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x04, 0xD0, 0x24, 0x68, 0x00, 0x2C, ++0xF8, 0xD1, 0xBD, 0xE8, 0xF8, 0x8F, 0x94, 0xF8, 0xD6, 0x30, 0x00, 0x2B, 0xF6, 0xD0, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, ++0xF2, 0xD0, 0x94, 0xF8, 0xD5, 0x20, 0x94, 0xF8, 0xD4, 0x30, 0x9A, 0x42, 0xEC, 0xD1, 0xD9, 0xF8, 0x70, 0x31, 0x20, 0x46, ++0x98, 0x47, 0x20, 0xB1, 0x98, 0xF8, 0x00, 0x30, 0x01, 0x33, 0x88, 0xF8, 0x00, 0x30, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD0, ++0xA7, 0xF1, 0x32, 0x02, 0x40, 0xF6, 0xB6, 0x33, 0x9A, 0x42, 0x18, 0xD8, 0xD5, 0xB9, 0x20, 0x46, 0x02, 0xF0, 0x7A, 0xFE, ++0x83, 0x46, 0xF0, 0xB9, 0x88, 0xF8, 0x00, 0x50, 0xD0, 0xE7, 0x73, 0x68, 0x00, 0x2B, 0xBA, 0xD0, 0x1D, 0x49, 0x1E, 0x48, ++0x40, 0xF2, 0x2F, 0x42, 0x08, 0xF0, 0xFE, 0xFE, 0x75, 0x7A, 0x00, 0x2D, 0xB4, 0xD0, 0x01, 0x23, 0x33, 0x72, 0xBD, 0xE8, ++0xF8, 0x8F, 0x20, 0x46, 0x02, 0xF0, 0x62, 0xFE, 0x88, 0xF8, 0x00, 0xA0, 0x24, 0x68, 0x4F, 0xF0, 0x00, 0x0B, 0x01, 0x25, ++0x00, 0x2C, 0xB1, 0xD1, 0xB7, 0xE7, 0x94, 0xF8, 0x63, 0x30, 0x84, 0xF8, 0x88, 0x30, 0xFF, 0x23, 0x84, 0xF8, 0x89, 0x30, ++0x04, 0x21, 0x04, 0xF1, 0x6C, 0x00, 0xF4, 0xF7, 0xDB, 0xF8, 0x73, 0x68, 0x08, 0xB1, 0x01, 0x33, 0x73, 0x60, 0x01, 0x2B, ++0x02, 0xD0, 0x4F, 0xF0, 0x00, 0x0B, 0x9F, 0xE7, 0xFC, 0xF7, 0x58, 0xFD, 0x4F, 0xF0, 0x00, 0x0B, 0x9A, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x40, 0x80, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x20, 0xA0, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x10, 0x2A, 0x17, 0x00, 0xF8, 0xB5, 0x27, 0x4F, 0x7B, 0x68, 0x04, 0x46, ++0x0E, 0x46, 0x13, 0xB1, 0x3C, 0x44, 0x21, 0x75, 0xF8, 0xBD, 0x02, 0x29, 0x34, 0xD0, 0x03, 0x29, 0x21, 0xD0, 0x01, 0x29, ++0x14, 0xD0, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x32, 0xDB, 0x1F, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x04, 0x53, 0x3C, 0x44, 0x00, 0x22, 0x22, 0x75, 0x93, 0xF8, 0xC1, 0x04, 0x31, 0x46, 0xBD, 0xE8, 0xF8, 0x40, ++0x04, 0xF0, 0xC6, 0xBE, 0x18, 0x4B, 0x19, 0x4A, 0x16, 0x4D, 0x00, 0xEB, 0x80, 0x01, 0x03, 0xEB, 0x81, 0x03, 0x02, 0xEB, ++0x81, 0x02, 0x5A, 0x60, 0xE6, 0xE7, 0x12, 0x4D, 0x14, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x52, 0x00, 0xEB, ++0xC0, 0x03, 0x00, 0xEB, 0x43, 0x03, 0x01, 0xEB, 0x43, 0x01, 0x92, 0xF8, 0xC1, 0x04, 0x04, 0xF0, 0x47, 0xFE, 0xD5, 0xE7, ++0x0A, 0x4A, 0x09, 0x4D, 0x00, 0xEB, 0x80, 0x01, 0x02, 0xEB, 0x81, 0x02, 0x53, 0x60, 0xCD, 0xE7, 0x09, 0x49, 0x0A, 0x48, ++0x04, 0x4D, 0x40, 0xF2, 0xC6, 0x42, 0x08, 0xF0, 0x71, 0xFE, 0xC5, 0xE7, 0xD8, 0x9C, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x4C, 0x40, 0x18, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x04, 0x23, 0x00, 0x22, 0x0C, 0x21, 0x44, 0x20, 0x06, 0xF0, 0x76, 0xFD, ++0x23, 0x7E, 0x03, 0x70, 0x04, 0x2B, 0x09, 0xD0, 0x00, 0x23, 0x00, 0x22, 0x43, 0x70, 0xC2, 0x70, 0xA3, 0x7E, 0x83, 0x70, ++0xBD, 0xE8, 0x10, 0x40, 0x06, 0xF0, 0x98, 0xBD, 0xE3, 0x89, 0x00, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0xF1, 0xE7, 0x00, 0xBF, ++0x38, 0xB5, 0x05, 0xF0, 0xE1, 0xFA, 0x0C, 0x23, 0x05, 0x46, 0x19, 0x46, 0x00, 0x22, 0x4F, 0x20, 0x06, 0xF0, 0x58, 0xFD, ++0x2B, 0x88, 0x03, 0x80, 0x04, 0x46, 0x28, 0x46, 0x05, 0xF0, 0xDE, 0xFA, 0x10, 0x4A, 0x11, 0x4D, 0x11, 0x49, 0xA2, 0xFB, ++0x00, 0x03, 0x9B, 0x09, 0x63, 0x60, 0x2B, 0x68, 0xA2, 0xFB, 0x03, 0x23, 0x9B, 0x09, 0x00, 0x22, 0xA3, 0x60, 0xA2, 0x70, ++0x0A, 0x23, 0x0A, 0x68, 0x52, 0xB2, 0x01, 0x3B, 0x3A, 0xB9, 0x13, 0xF0, 0xFF, 0x03, 0xF8, 0xD1, 0x20, 0x46, 0xBD, 0xE8, ++0x38, 0x40, 0x06, 0xF0, 0x67, 0xBD, 0xA2, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0x38, 0x40, 0x06, 0xF0, 0x61, 0xBD, 0x00, 0xBF, ++0xD3, 0x4D, 0x62, 0x10, 0x20, 0x02, 0x32, 0x40, 0x0C, 0xB2, 0x33, 0x40, 0x10, 0xB5, 0xC1, 0x89, 0x04, 0x46, 0x02, 0x23, ++0x00, 0x22, 0x48, 0x20, 0x06, 0xF0, 0x22, 0xFD, 0x22, 0x7E, 0x42, 0x70, 0xA1, 0x7E, 0x05, 0x4A, 0x01, 0x70, 0x13, 0x68, ++0x23, 0xF0, 0x04, 0x03, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0x60, 0x06, 0xF0, 0x45, 0xBD, 0x00, 0xBF, 0x94, 0x40, 0x04, 0x40, ++0xF0, 0xB5, 0x04, 0x68, 0x0E, 0x68, 0xA5, 0x1B, 0x32, 0xD4, 0x8E, 0x46, 0xAB, 0x42, 0x0C, 0xD2, 0xDE, 0xE9, 0x00, 0x76, ++0xDC, 0x19, 0xF6, 0x1B, 0xED, 0x1A, 0xAB, 0x42, 0x06, 0xEB, 0x04, 0x07, 0xA4, 0x46, 0x1C, 0x44, 0xF8, 0xD3, 0xCE, 0xE9, ++0x00, 0xC7, 0xB5, 0xEB, 0x53, 0x0F, 0x05, 0xD9, 0xDE, 0xE9, 0x00, 0x54, 0x1D, 0x44, 0x23, 0x44, 0xCE, 0xE9, 0x00, 0x53, ++0x43, 0x68, 0x4C, 0x68, 0x1D, 0x1B, 0x00, 0x2D, 0x09, 0xDB, 0xB2, 0xB1, 0x05, 0x68, 0x09, 0x68, 0x53, 0x60, 0x68, 0x1A, ++0x00, 0x28, 0x17, 0xDA, 0x58, 0x1B, 0x15, 0x60, 0xF0, 0xBD, 0xAA, 0xB1, 0x05, 0x68, 0x09, 0x68, 0x54, 0x60, 0x6B, 0x1A, ++0x00, 0x2B, 0xA8, 0xBF, 0x60, 0x1A, 0x18, 0xDB, 0x11, 0x60, 0xF0, 0xBD, 0x35, 0x1B, 0x86, 0x46, 0xCA, 0xE7, 0x00, 0x68, ++0x0A, 0x68, 0x81, 0x1A, 0x00, 0x29, 0x0C, 0xDA, 0x18, 0x1A, 0xF0, 0xBD, 0x58, 0x1A, 0xF1, 0xE7, 0x00, 0x68, 0x0B, 0x68, ++0xC1, 0x1A, 0x00, 0x29, 0xA8, 0xBF, 0xE0, 0x1A, 0xE0, 0xDA, 0x20, 0x1A, 0xF0, 0xBD, 0x98, 0x1A, 0xF0, 0xBD, 0x60, 0x1B, ++0xD9, 0xE7, 0x00, 0xBF, 0x70, 0xB5, 0x19, 0x4E, 0x90, 0xF8, 0xC1, 0x44, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0x05, 0x46, ++0x93, 0xF8, 0x20, 0x20, 0x0A, 0xB9, 0x1B, 0x7C, 0xFB, 0xB9, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x64, 0x94, 0xF8, 0x50, 0x20, ++0x12, 0xB9, 0x94, 0xF8, 0x40, 0x30, 0x7B, 0xB9, 0x0F, 0x4B, 0x9B, 0x68, 0x5B, 0xB1, 0x95, 0xF8, 0x63, 0x10, 0xFF, 0x20, ++0x93, 0xF8, 0x4E, 0x20, 0x8A, 0x42, 0x08, 0xBF, 0x83, 0xF8, 0x4E, 0x00, 0x1B, 0x68, 0x00, 0x2B, 0xF6, 0xD1, 0x70, 0xBD, ++0x08, 0x4B, 0x01, 0x21, 0xD3, 0xF8, 0x08, 0x32, 0x28, 0x46, 0x98, 0x47, 0xE8, 0xE7, 0x05, 0x4B, 0x11, 0x46, 0xD3, 0xF8, ++0x08, 0x32, 0x98, 0x47, 0xD9, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x48, 0x4B, 0x93, 0xF8, 0x5A, 0x30, 0x9B, 0xB0, 0x01, 0x2B, 0x08, 0x90, 0x40, 0xF2, 0x93, 0x81, ++0xDF, 0xF8, 0x20, 0x91, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB7, 0x81, 0x08, 0x9C, ++0x40, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x94, 0x30, 0x98, 0x47, 0x23, 0x6C, 0x94, 0xF8, 0x63, 0x20, 0xDA, 0x76, 0x94, 0xF8, ++0x62, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xB9, 0x81, 0x02, 0x2A, 0x08, 0xBF, 0x08, 0x9A, 0x39, 0x48, 0x0A, 0xBF, 0xB2, 0xF8, ++0xD2, 0x20, 0x4F, 0xF4, 0xC8, 0x32, 0x92, 0x02, 0x0A, 0x92, 0x1A, 0x7E, 0x02, 0x2A, 0x02, 0xF1, 0x01, 0x03, 0x00, 0xF0, ++0xB9, 0x81, 0xC3, 0xEB, 0xC3, 0x04, 0x00, 0xEB, 0x84, 0x04, 0xD9, 0x00, 0x24, 0x7E, 0xFF, 0x2C, 0x0D, 0xD1, 0x01, 0x2A, ++0x02, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, 0xC3, 0xEB, 0xC3, 0x02, 0x00, 0xEB, 0x82, 0x02, 0xD9, 0x00, 0x12, 0x7E, ++0xFF, 0x2A, 0x00, 0xF0, 0x98, 0x82, 0x28, 0x4A, 0xCB, 0x1A, 0x00, 0xEB, 0x83, 0x03, 0x96, 0x68, 0x5B, 0x7E, 0x06, 0x93, ++0x00, 0x2E, 0x00, 0xF0, 0x4A, 0x81, 0x0A, 0x9B, 0x4F, 0xF0, 0x00, 0x0B, 0x5B, 0x00, 0x0B, 0x93, 0x5F, 0x46, 0x03, 0xE0, ++0x36, 0x68, 0x00, 0x2E, 0x00, 0xF0, 0x9A, 0x80, 0x33, 0x6C, 0x00, 0x2B, 0xF8, 0xD0, 0x08, 0x9A, 0x12, 0x6C, 0x93, 0x42, ++0xF4, 0xD0, 0x96, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x93, 0x81, 0x02, 0x2B, 0x0A, 0xBF, 0xB6, 0xF8, 0xD2, 0x30, ++0x4F, 0xF4, 0xC8, 0x3B, 0x4F, 0xEA, 0x83, 0x2B, 0x0B, 0x9B, 0x5B, 0x45, 0x04, 0xD8, 0x0A, 0x9B, 0xBB, 0xFB, 0xF3, 0xF2, ++0xBB, 0xFB, 0xF2, 0xFB, 0x06, 0x9B, 0x4F, 0xEA, 0x5B, 0x00, 0xB0, 0xFB, 0xF3, 0xF5, 0x09, 0x95, 0xE5, 0xF7, 0x7C, 0xF8, ++0x43, 0xF2, 0xB0, 0x64, 0x20, 0x44, 0xA8, 0x42, 0x00, 0xF2, 0x18, 0x81, 0x00, 0x2F, 0x00, 0xF0, 0x1C, 0x81, 0x06, 0x9B, ++0x09, 0x9A, 0x03, 0xFB, 0x02, 0xF3, 0x07, 0x93, 0x10, 0xAC, 0x00, 0x25, 0x10, 0xE0, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x01, 0x35, 0xAF, 0x42, ++0x04, 0xF1, 0x14, 0x04, 0x00, 0xF0, 0x03, 0x81, 0x22, 0x68, 0x5A, 0x45, 0xF6, 0xD1, 0x72, 0x6A, 0x0C, 0x92, 0xD4, 0xE9, ++0x02, 0x01, 0x0D, 0xF1, 0x38, 0x0C, 0x0D, 0xF1, 0x30, 0x0A, 0x02, 0xF5, 0x1C, 0x5E, 0x8C, 0xE8, 0x03, 0x00, 0x0E, 0xF1, ++0x10, 0x0E, 0x52, 0x46, 0x61, 0x46, 0x50, 0x46, 0x5B, 0x46, 0xCD, 0xF8, 0x34, 0xE0, 0xFF, 0xF7, 0xB7, 0xFE, 0xD9, 0xF8, ++0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x80, 0x46, 0xC0, 0xF2, 0x2D, 0x81, 0x06, 0x9B, 0x5A, 0x1E, 0x07, 0x9B, ++0xB3, 0xFB, 0xF2, 0xF2, 0x05, 0x92, 0xE5, 0xF7, 0x31, 0xF8, 0x05, 0x9A, 0x61, 0x68, 0xA2, 0xF5, 0x7A, 0x62, 0x12, 0x1A, ++0x8A, 0x42, 0x38, 0xBF, 0x0A, 0x46, 0x42, 0x45, 0xC6, 0xD9, 0x05, 0x92, 0x05, 0xEB, 0x85, 0x05, 0xE5, 0xF7, 0x22, 0xF8, ++0x1A, 0xAB, 0x03, 0xEB, 0x85, 0x05, 0x96, 0xF8, 0x63, 0x10, 0x05, 0x9A, 0x55, 0xF8, 0x18, 0x3C, 0x36, 0x68, 0x01, 0x24, ++0x8C, 0x40, 0x02, 0x44, 0x9A, 0xE8, 0x03, 0x00, 0x23, 0x43, 0x02, 0xF5, 0x7A, 0x62, 0xA5, 0xF1, 0x20, 0x04, 0x84, 0xE8, ++0x03, 0x00, 0x45, 0xF8, 0x24, 0x2C, 0x45, 0xF8, 0x18, 0x3C, 0x00, 0x2E, 0x7F, 0xF4, 0x66, 0xAF, 0x00, 0x2F, 0x00, 0xF0, ++0xA2, 0x80, 0xDF, 0xF8, 0x88, 0xA3, 0xDD, 0xF8, 0x20, 0xB0, 0x05, 0x96, 0x09, 0x96, 0x0B, 0x96, 0x07, 0x96, 0x12, 0xAC, ++0x06, 0x97, 0x54, 0xF8, 0x08, 0x7C, 0x0A, 0x9B, 0xB7, 0xFB, 0xF3, 0xF2, 0x03, 0xFB, 0x12, 0x72, 0x00, 0x2A, 0x00, 0xF0, ++0x3A, 0x81, 0xE4, 0xF7, 0xED, 0xFF, 0x54, 0xE9, 0x01, 0x63, 0xA3, 0xF5, 0xBB, 0x53, 0x10, 0x3B, 0x1D, 0x1A, 0xE4, 0xF7, ++0xE5, 0xFF, 0xDA, 0xF8, 0x10, 0x30, 0x54, 0xF8, 0x08, 0x1C, 0xEB, 0x1A, 0x06, 0xF5, 0x7A, 0x66, 0x00, 0x2B, 0x06, 0xEB, ++0x00, 0x07, 0xC0, 0xF2, 0xEA, 0x80, 0xDA, 0xF8, 0x10, 0x20, 0x6B, 0x1A, 0x9A, 0x1A, 0x00, 0x2A, 0x80, 0xF2, 0xDB, 0x80, ++0xCD, 0xE9, 0x01, 0x75, 0xBE, 0x4B, 0x00, 0x91, 0xD3, 0xF8, 0x04, 0x32, 0xDF, 0xF8, 0x1C, 0x83, 0x1E, 0x46, 0x00, 0x22, ++0xFF, 0x23, 0x01, 0x21, 0x58, 0x46, 0xB0, 0x47, 0xEB, 0x19, 0xB9, 0x4E, 0x25, 0x60, 0x63, 0x60, 0x07, 0x46, 0x00, 0x25, ++0xA3, 0x68, 0xEB, 0x40, 0xDB, 0x07, 0x22, 0xD5, 0x72, 0x6A, 0x54, 0xF8, 0x08, 0x3C, 0x0E, 0x92, 0x02, 0xF5, 0x1C, 0x5C, ++0x0C, 0xF1, 0x10, 0x0C, 0x00, 0x22, 0x0E, 0xA9, 0x20, 0x46, 0xCD, 0xF8, 0x3C, 0xC0, 0xFF, 0xF7, 0x21, 0xFE, 0xD9, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xC3, 0x80, 0x0E, 0x9A, 0x63, 0x68, 0x9B, 0xF8, 0x63, 0x10, ++0x86, 0xF8, 0x4E, 0x10, 0x9B, 0x1A, 0x00, 0x22, 0x73, 0x65, 0x86, 0xF8, 0x4F, 0x70, 0xA6, 0xF8, 0x58, 0x20, 0x01, 0x35, ++0x04, 0x2D, 0x06, 0xF5, 0xA4, 0x66, 0xD3, 0xD1, 0x05, 0x9B, 0x06, 0x9A, 0x01, 0x33, 0x9A, 0x42, 0x05, 0x93, 0x04, 0xF1, ++0x14, 0x04, 0x90, 0xD1, 0x07, 0x9B, 0x33, 0xB3, 0x0B, 0x9B, 0x0A, 0x99, 0x03, 0xF5, 0x9C, 0x50, 0x09, 0x9B, 0x08, 0x30, ++0x83, 0x42, 0xA8, 0xBF, 0x03, 0x46, 0x18, 0x46, 0x01, 0xEB, 0xD1, 0x73, 0xB0, 0xEB, 0x63, 0x0F, 0x4F, 0xEA, 0x63, 0x02, ++0x00, 0xF3, 0x18, 0x81, 0x52, 0x42, 0x82, 0x42, 0xC4, 0xBF, 0x0A, 0x9B, 0xC0, 0x18, 0x8F, 0x4B, 0xD3, 0xF8, 0x6C, 0x31, ++0x98, 0x47, 0x08, 0x9C, 0x8E, 0x4A, 0x94, 0xF8, 0x4D, 0x30, 0x20, 0x65, 0x43, 0xF0, 0x20, 0x03, 0x01, 0x21, 0x84, 0xF8, ++0x4D, 0x30, 0x82, 0xF8, 0x31, 0x10, 0x1B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xE4, 0xF7, 0x5C, 0xFF, 0x03, 0x19, 0x09, 0x93, ++0x00, 0x2F, 0x7F, 0xF4, 0xE4, 0xAE, 0xD9, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x7B, 0xDB, 0x1A, 0xAB, ++0x07, 0xEB, 0x87, 0x02, 0x70, 0x6A, 0x03, 0xEB, 0x82, 0x02, 0x09, 0x9B, 0x42, 0xF8, 0x28, 0xBC, 0x00, 0xF5, 0x1C, 0x51, ++0x42, 0xE9, 0x09, 0x30, 0x10, 0x31, 0x42, 0xF8, 0x1C, 0x1C, 0xBC, 0x00, 0x96, 0xF8, 0x63, 0x20, 0x3C, 0x44, 0x1A, 0xAB, ++0x03, 0xEB, 0x84, 0x04, 0x01, 0x23, 0x93, 0x40, 0x01, 0x37, 0x44, 0xF8, 0x18, 0x3C, 0x8F, 0xE6, 0x03, 0x6C, 0xDB, 0x7E, ++0xFF, 0x2B, 0x3F, 0xF4, 0x44, 0xAE, 0x90, 0xF8, 0x63, 0x20, 0x9A, 0x42, 0x3F, 0xF4, 0x3F, 0xAE, 0x6E, 0x49, 0x6F, 0x48, ++0x40, 0xF2, 0xA7, 0x22, 0x08, 0xF0, 0x8E, 0xFB, 0x37, 0xE6, 0x08, 0x9A, 0x6C, 0x49, 0x92, 0xF8, 0x6C, 0x20, 0x4F, 0xF4, ++0x1E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x6A, 0x48, 0x92, 0x68, 0x0A, 0x92, 0x1A, 0x7E, 0x02, 0x2A, 0x02, 0xF1, 0x01, 0x03, ++0x7F, 0xF4, 0x47, 0xAE, 0x03, 0x7E, 0xFF, 0x2B, 0x40, 0xF0, 0xEE, 0x80, 0x01, 0x23, 0x4D, 0xE6, 0x06, 0x9B, 0x01, 0x2B, ++0x3F, 0xF6, 0xCF, 0xAE, 0x5D, 0x49, 0x61, 0x48, 0x40, 0xF2, 0xD3, 0x22, 0x08, 0xF0, 0x6C, 0xFB, 0xC7, 0xE6, 0x5C, 0x4A, ++0x96, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0xD3, 0xF8, 0x08, 0xB0, 0x6A, 0xE6, 0xDA, 0xF8, ++0x10, 0x20, 0x1D, 0x46, 0x5B, 0x1A, 0x9A, 0x1A, 0x00, 0x2A, 0xF8, 0xDA, 0x1C, 0xE7, 0xDA, 0xF8, 0x10, 0x30, 0x0D, 0x44, ++0xEB, 0x1A, 0x00, 0x2B, 0xBF, 0xF6, 0x16, 0xAF, 0xDA, 0xF8, 0x10, 0x30, 0x0D, 0x44, 0xEB, 0x1A, 0x00, 0x2B, 0xF2, 0xDB, ++0x0E, 0xE7, 0x96, 0xF8, 0x4E, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0x38, 0xAF, 0x47, 0x49, 0x4F, 0xF4, 0x58, 0x72, 0x40, 0x46, ++0x08, 0xF0, 0x40, 0xFB, 0x30, 0xE7, 0x02, 0x2F, 0x00, 0xF0, 0x98, 0x80, 0x1A, 0xAB, 0x07, 0xEB, 0x87, 0x02, 0x70, 0x6A, ++0x03, 0xEB, 0x82, 0x02, 0x09, 0x9B, 0x42, 0xF8, 0x28, 0xBC, 0x00, 0xF5, 0x1C, 0x51, 0x42, 0xE9, 0x09, 0x30, 0x10, 0x31, ++0x42, 0xF8, 0x1C, 0x1C, 0xBC, 0x00, 0x96, 0xF8, 0x63, 0x20, 0x1F, 0x2A, 0x7F, 0xF6, 0x7E, 0xAF, 0x37, 0x49, 0x3C, 0x48, ++0x40, 0xF2, 0xED, 0x22, 0x08, 0xF0, 0x20, 0xFB, 0x74, 0xE7, 0x3A, 0x4B, 0xDA, 0xF8, 0x10, 0x00, 0x19, 0x68, 0x0A, 0x9B, ++0x00, 0xEB, 0x41, 0x10, 0x9F, 0x42, 0x28, 0xBF, 0x1F, 0x46, 0x00, 0xF5, 0x1C, 0x55, 0x10, 0x35, 0x3B, 0x46, 0x0E, 0xA9, ++0x0E, 0x90, 0x20, 0x46, 0x0F, 0x95, 0xFF, 0xF7, 0x17, 0xFD, 0x0E, 0x9E, 0x23, 0x68, 0x54, 0xF8, 0x04, 0x5C, 0x9A, 0x1B, ++0x00, 0x2A, 0x1D, 0x44, 0x62, 0x68, 0xA5, 0xF5, 0xFA, 0x65, 0xB4, 0xBF, 0xB6, 0x1A, 0x3E, 0x1A, 0xAD, 0x1A, 0xE4, 0xF7, ++0x91, 0xFE, 0x00, 0xF5, 0x7A, 0x60, 0xA8, 0x42, 0x34, 0xDC, 0x54, 0xE9, 0x02, 0x78, 0xE4, 0xF7, 0x89, 0xFE, 0xA7, 0xF5, ++0x5A, 0x53, 0x30, 0x3B, 0xA3, 0xEB, 0x08, 0x03, 0x07, 0x9A, 0xAD, 0x1B, 0x1B, 0x1A, 0x2B, 0x44, 0xDA, 0xB1, 0x09, 0x9A, ++0xAA, 0x42, 0x1F, 0xDB, 0x0B, 0x9A, 0x9A, 0x42, 0x0A, 0xDD, 0x0A, 0x9A, 0x13, 0x44, 0x15, 0x44, 0x09, 0x9A, 0xAA, 0x42, ++0xFF, 0xF6, 0x83, 0xAE, 0x0B, 0x9A, 0x9A, 0x42, 0x3F, 0xF7, 0x7F, 0xAE, 0x0B, 0x9A, 0xAA, 0x42, 0xB8, 0xBF, 0x2A, 0x46, ++0x0B, 0x92, 0x09, 0x9A, 0x9A, 0x42, 0xA8, 0xBF, 0x1A, 0x46, 0x09, 0x92, 0x73, 0xE6, 0x09, 0x93, 0x01, 0x23, 0x0B, 0x95, ++0x07, 0x93, 0x6E, 0xE6, 0x40, 0x1A, 0xEA, 0xE6, 0x0A, 0x9A, 0xAD, 0x1A, 0x9B, 0x1A, 0xE1, 0xE7, 0xE4, 0xF7, 0x56, 0xFE, ++0x00, 0xF5, 0x7A, 0x65, 0xC5, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x48, 0xA0, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0xD0, 0xA0, 0x15, 0x00, ++0x00, 0xA1, 0x15, 0x00, 0x40, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x10, 0xA1, 0x15, 0x00, 0x40, 0xF2, 0xE7, 0x22, ++0x14, 0x49, 0x15, 0x48, 0x08, 0xF0, 0x9E, 0xFA, 0xD9, 0xF8, 0x00, 0x20, 0x09, 0x9B, 0xB2, 0xF9, 0x00, 0x20, 0xCD, 0xF8, ++0x68, 0xB0, 0x1B, 0x93, 0x73, 0x6A, 0x1C, 0x93, 0x03, 0xF5, 0x1C, 0x53, 0x10, 0x33, 0x00, 0x2A, 0x1D, 0x93, 0x4F, 0xF0, ++0x08, 0x04, 0xFF, 0xF6, 0x60, 0xAF, 0xDF, 0xE6, 0x00, 0x23, 0x19, 0x46, 0x67, 0xE5, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0xDA, 0x04, 0x49, 0x05, 0x48, 0x40, 0xF2, 0xAE, 0x22, 0x08, 0xF0, 0x7B, 0xFA, 0x00, 0x23, ++0x5B, 0x7E, 0xFF, 0xDE, 0x70, 0x79, 0x15, 0x00, 0xE4, 0xA0, 0x15, 0x00, 0xC4, 0xA0, 0x15, 0x00, 0x0A, 0x4B, 0x03, 0xF1, ++0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x02, 0xD0, 0xDA, 0x7E, 0xFF, 0x2A, 0x04, 0xD1, 0x1C, 0x33, 0x8B, 0x42, 0xF6, 0xD1, ++0x00, 0x20, 0x70, 0x47, 0x04, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x02, 0x32, 0x02, 0x60, 0x01, 0x20, 0x70, 0x47, ++0x90, 0x9D, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x0E, 0x46, 0x85, 0xB0, 0x14, 0x46, 0x05, 0x46, ++0x00, 0x28, 0x54, 0xD0, 0x07, 0x46, 0x00, 0x2C, 0x3A, 0xD0, 0xA3, 0x7A, 0xFF, 0x2B, 0x37, 0xD0, 0x3D, 0x4A, 0x23, 0x7A, ++0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0x5E, 0xD0, 0x02, 0x2A, 0x52, 0xD0, ++0x4F, 0xF4, 0x48, 0x4A, 0x4F, 0xF4, 0xC8, 0x39, 0x60, 0x68, 0xDF, 0xF8, 0xE0, 0x80, 0x00, 0xF5, 0x1C, 0x5B, 0xE4, 0xF7, ++0xC9, 0xFD, 0x0B, 0xF1, 0x10, 0x0B, 0x03, 0x46, 0xE1, 0x7A, 0xD8, 0xF8, 0xFC, 0x21, 0x28, 0x46, 0x9B, 0x44, 0x90, 0x47, ++0x83, 0x1B, 0x13, 0xEB, 0x0A, 0x0F, 0x05, 0xD5, 0xAA, 0xEB, 0x06, 0x03, 0x48, 0x44, 0xC3, 0x42, 0xFC, 0xD4, 0x83, 0x1B, ++0x00, 0x2B, 0x0B, 0xF5, 0x0C, 0x53, 0xB8, 0xBF, 0x00, 0xF1, 0xFF, 0x36, 0x28, 0x33, 0x9B, 0x1B, 0x00, 0x2B, 0x31, 0xDB, ++0x0B, 0xF5, 0x7A, 0x60, 0x80, 0x1B, 0x06, 0xE0, 0xE4, 0xF7, 0xA6, 0xFD, 0xDF, 0xF8, 0x8C, 0x80, 0x00, 0xF5, 0x5A, 0x50, ++0x30, 0x30, 0x00, 0x22, 0x01, 0x23, 0xCD, 0xE9, 0x01, 0x06, 0xD8, 0xF8, 0x04, 0x42, 0x00, 0x92, 0x38, 0x46, 0x19, 0x46, ++0xA0, 0x47, 0xFF, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x17, 0x4B, 0x03, 0xF1, 0x54, 0x01, ++0x1A, 0x7E, 0xFF, 0x2A, 0x02, 0xD0, 0xDF, 0x7E, 0xFF, 0x2F, 0x1C, 0xD1, 0x1C, 0x33, 0x99, 0x42, 0xF6, 0xD1, 0x00, 0x20, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0xF8, 0xD2, 0x30, 0x4F, 0xEA, 0x83, 0x29, 0x4F, 0xEA, 0x43, 0x2A, 0xA9, 0xE7, ++0x41, 0xF2, 0x88, 0x30, 0xD5, 0xE7, 0x93, 0xF8, 0x6C, 0x30, 0x0A, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, ++0xD3, 0xF8, 0x08, 0x90, 0x4F, 0xEA, 0x59, 0x0A, 0x9A, 0xE7, 0x03, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x37, ++0x7F, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0xB5, 0x0C, 0x46, 0x02, 0x7A, 0x17, 0x49, 0x23, 0x7A, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x02, 0x12, 0x05, 0xFB, ++0x03, 0x13, 0x12, 0x6C, 0x1B, 0x6C, 0x9A, 0x42, 0x0D, 0xD0, 0x45, 0x68, 0xE4, 0xF7, 0x4A, 0xFD, 0x64, 0x68, 0x06, 0x46, ++0xE4, 0xF7, 0x46, 0xFD, 0x2A, 0x1B, 0x06, 0xD4, 0x63, 0x1B, 0x00, 0x2B, 0x0C, 0xDB, 0xA5, 0x42, 0x08, 0xD0, 0x00, 0x20, ++0x70, 0xBD, 0xA4, 0xF5, 0x5A, 0x53, 0x30, 0x3B, 0x5B, 0x1B, 0x9E, 0x1B, 0x00, 0x2E, 0xF1, 0xDA, 0x01, 0x20, 0x70, 0xBD, ++0xA2, 0xF5, 0x5A, 0x53, 0x30, 0x3B, 0x1B, 0x1A, 0x00, 0x2B, 0xF7, 0xDB, 0xA5, 0x42, 0xEC, 0xD1, 0xF4, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x83, 0xB0, 0x0D, 0x46, 0x00, 0xF1, 0x44, 0x08, 0x91, 0x46, ++0x22, 0xB9, 0x90, 0xF8, 0x4D, 0x30, 0xDB, 0x07, 0x00, 0xF1, 0xA3, 0x80, 0xDF, 0xF8, 0x64, 0xA1, 0xD7, 0xF8, 0x40, 0xB0, ++0xDA, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x79, 0xD1, 0xDA, 0xF8, 0x50, 0x30, 0x0B, 0xB1, 0x9B, 0x45, 0x2E, 0xD1, 0xBD, 0x64, ++0xE4, 0xF7, 0x0A, 0xFD, 0x05, 0xF5, 0x5A, 0x53, 0xDA, 0xF8, 0x10, 0x40, 0x2F, 0x33, 0x1E, 0x18, 0x00, 0x2C, 0x00, 0xF0, ++0x88, 0x80, 0xDF, 0xF8, 0x38, 0xA1, 0x0B, 0xE0, 0xDA, 0xF8, 0xA0, 0x30, 0x98, 0x47, 0xD3, 0x46, 0x40, 0xBB, 0x63, 0x68, ++0xEB, 0x1A, 0x00, 0x2B, 0x08, 0xDB, 0x24, 0x68, 0x00, 0x2C, 0x78, 0xD0, 0x63, 0x68, 0xF3, 0x1A, 0x00, 0x2B, 0x21, 0x46, ++0x40, 0x46, 0xED, 0xDA, 0x3F, 0x48, 0x42, 0x46, 0x21, 0x46, 0x06, 0xF0, 0xD9, 0xFD, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, ++0x01, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x54, 0x60, 0xE4, 0xF7, 0xDA, 0xFC, ++0xAE, 0x1B, 0xA6, 0xF5, 0x7A, 0x66, 0x30, 0x1A, 0xC4, 0x0F, 0x00, 0x2C, 0xC5, 0xD0, 0xDF, 0xF8, 0xDC, 0xB0, 0x00, 0x24, ++0x97, 0xF8, 0xC0, 0x34, 0x4B, 0xB1, 0x31, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, ++0x70, 0x30, 0x01, 0x2B, 0x1D, 0xD0, 0x97, 0xF8, 0x62, 0x30, 0xDB, 0xF8, 0x2C, 0x40, 0x7B, 0xB1, 0x02, 0x2B, 0x0A, 0xBF, ++0xB7, 0xF8, 0xD2, 0x10, 0x4F, 0xF4, 0xC8, 0x31, 0x89, 0x02, 0x09, 0xF1, 0x01, 0x02, 0x29, 0x44, 0x38, 0x46, 0x23, 0x46, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x22, 0x4A, 0x97, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, ++0x03, 0x23, 0x99, 0x68, 0xED, 0xE7, 0xDB, 0xF8, 0x90, 0x30, 0x22, 0x46, 0x29, 0x46, 0x38, 0x46, 0x98, 0x47, 0x97, 0xF8, ++0x62, 0x30, 0xDB, 0xF8, 0x2C, 0x40, 0x00, 0x2B, 0xDA, 0xD1, 0xE9, 0xE7, 0xDA, 0xF8, 0x24, 0x20, 0x01, 0x92, 0x56, 0x68, ++0xE4, 0xF7, 0x92, 0xFC, 0x01, 0x9A, 0x93, 0x68, 0x06, 0xF5, 0x7A, 0x66, 0x9B, 0x45, 0x06, 0xEB, 0x00, 0x04, 0x0A, 0xD0, ++0xE4, 0xF7, 0x88, 0xFC, 0x01, 0x9A, 0xD3, 0x68, 0x04, 0xF5, 0x7A, 0x64, 0x04, 0x44, 0x13, 0xB1, 0x04, 0xF5, 0x1C, 0x54, ++0x10, 0x34, 0x2C, 0x1B, 0xE4, 0x0F, 0x00, 0x2C, 0x3F, 0xF4, 0x6D, 0xAF, 0xA5, 0xE7, 0x00, 0x24, 0x8A, 0xE7, 0x05, 0x48, ++0x41, 0x46, 0x06, 0xF0, 0xD9, 0xFC, 0x97, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x01, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x51, 0xE7, ++0x40, 0x9D, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x81, 0x46, 0x1A, 0x48, 0x88, 0x46, 0x17, 0x46, 0x06, 0xF0, 0xB4, 0xFC, 0x18, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x0C, 0xDB, 0x16, 0x4D, 0x28, 0x46, 0x21, 0x46, 0x50, 0xF8, 0x20, 0x6F, ++0xE7, 0x60, 0xC4, 0xE9, 0x01, 0x98, 0x06, 0xF0, 0x5F, 0xFC, 0x4E, 0xB1, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x28, 0xF0, 0xD1, ++0x0F, 0x49, 0x10, 0x48, 0xD6, 0x22, 0x08, 0xF0, 0xA9, 0xF8, 0xEA, 0xE7, 0x0E, 0x4B, 0x61, 0x68, 0x1B, 0x69, 0xAC, 0x64, ++0xCB, 0x1A, 0x14, 0x2B, 0x07, 0xD4, 0x0C, 0x4B, 0x05, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x47, ++0x18, 0x47, 0x6B, 0x6C, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x48, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x48, 0xA1, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0xC1, 0x4B, 0xDF, 0xF8, 0x0C, 0x83, 0x1D, 0x69, 0xD0, 0xF8, 0x40, 0x90, 0x2F, 0x7A, 0x6B, 0x68, ++0x89, 0xB0, 0x4F, 0xF4, 0xA4, 0x6A, 0xA3, 0xF5, 0x7A, 0x63, 0x0A, 0xFB, 0x07, 0x8B, 0x0C, 0x46, 0x03, 0x92, 0x01, 0x93, ++0x06, 0x46, 0xE4, 0xF7, 0x05, 0xFC, 0x01, 0x9B, 0xDB, 0xF8, 0x40, 0x20, 0x1B, 0x1B, 0x1B, 0x1A, 0x4A, 0x45, 0x01, 0x93, ++0x66, 0xD0, 0x6B, 0x68, 0x02, 0x93, 0xE4, 0xF7, 0xF9, 0xFB, 0x02, 0x9B, 0x99, 0xF8, 0x1B, 0x20, 0x04, 0x90, 0xA3, 0xF5, ++0x7A, 0x63, 0x19, 0x1A, 0xFF, 0x2A, 0x02, 0x91, 0x20, 0xD1, 0x96, 0xF8, 0x4E, 0x60, 0x05, 0x93, 0xFF, 0x2E, 0x40, 0xF0, ++0x8F, 0x80, 0x01, 0x9B, 0x03, 0x9A, 0x18, 0x46, 0x10, 0x44, 0xB2, 0xEB, 0x50, 0x0F, 0x4F, 0xEA, 0x50, 0x03, 0x00, 0xF2, ++0xA9, 0x80, 0x03, 0x9A, 0xA4, 0x4E, 0xA4, 0x1A, 0x1C, 0x44, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x87, 0x2A, 0x46, ++0xD6, 0xF8, 0x88, 0x30, 0x39, 0x6C, 0x20, 0x46, 0x98, 0x47, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0A, 0xFB, 0x02, 0x8A, ++0x50, 0x46, 0x07, 0xAA, 0x06, 0xA9, 0xDB, 0xF8, 0x40, 0x90, 0x01, 0x93, 0x03, 0xF0, 0xE8, 0xFB, 0x83, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0x8C, 0x80, 0x07, 0x9C, 0x02, 0x99, 0x01, 0x9B, 0x0A, 0x1B, 0x00, 0x2A, 0xC0, 0xF2, 0x41, 0x81, 0x06, 0x9A, ++0xD1, 0x1A, 0x04, 0x9B, 0xD9, 0x42, 0x7D, 0xD5, 0x14, 0x1B, 0xE4, 0xF7, 0xB1, 0xFB, 0x00, 0xF5, 0x0C, 0x50, 0x28, 0x30, ++0x84, 0x42, 0x40, 0xF2, 0x3B, 0x81, 0x8B, 0x4E, 0x07, 0x98, 0xD6, 0xF8, 0x88, 0x30, 0x49, 0x46, 0x00, 0x22, 0x98, 0x47, ++0x06, 0x9C, 0xD6, 0xF8, 0x88, 0x90, 0xE4, 0xF7, 0x9F, 0xFB, 0xA4, 0xF5, 0x7A, 0x64, 0x20, 0x1A, 0xDA, 0xF8, 0x40, 0x10, ++0x02, 0x9C, 0x00, 0x22, 0xC8, 0x47, 0xBA, 0xE7, 0xE4, 0xF7, 0x94, 0xFB, 0x01, 0x9B, 0xA3, 0xF5, 0x7A, 0x62, 0x12, 0x1A, ++0x41, 0xF2, 0x87, 0x33, 0x9A, 0x42, 0x01, 0x92, 0xB9, 0xDD, 0x6F, 0x68, 0xE4, 0xF7, 0x88, 0xFB, 0x99, 0xF8, 0x1B, 0xB0, ++0x02, 0x97, 0x3B, 0x1A, 0xBB, 0xF1, 0xFF, 0x0F, 0x01, 0x9A, 0x04, 0x90, 0xA3, 0xF5, 0x7A, 0x67, 0x70, 0xD0, 0x0A, 0xFB, ++0x0B, 0x80, 0x07, 0xAA, 0x06, 0xA9, 0x03, 0xF0, 0x9B, 0xFB, 0x00, 0x28, 0x40, 0xF0, 0xE6, 0x80, 0xE4, 0xF7, 0x72, 0xFB, ++0x06, 0x9E, 0xC6, 0xF5, 0x9C, 0x52, 0x08, 0x32, 0x00, 0xF5, 0x7A, 0x60, 0x22, 0x44, 0x12, 0xEB, 0x40, 0x03, 0x00, 0xF1, ++0xF9, 0x80, 0xE4, 0xF7, 0x65, 0xFB, 0x07, 0x9C, 0x04, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0xDB, 0x1B, 0xC3, 0x42, 0x8C, 0xD5, ++0x64, 0x4E, 0xDF, 0xF8, 0x98, 0xA1, 0x5F, 0xE0, 0x07, 0xAA, 0x0A, 0xFB, 0x06, 0x80, 0x06, 0xA9, 0x03, 0xF0, 0x78, 0xFB, ++0x83, 0x46, 0xE4, 0xF7, 0x51, 0xFB, 0x06, 0x9A, 0xA2, 0xF5, 0x7A, 0x62, 0x10, 0x1A, 0xDD, 0xE9, 0x04, 0x23, 0x06, 0x90, ++0xA2, 0xEB, 0x03, 0x0A, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD1, 0x02, 0x9B, 0x10, 0xEB, 0x0A, 0x0F, 0x54, 0xBF, 0x1C, 0x46, ++0x04, 0x46, 0xE4, 0xF7, 0x3D, 0xFB, 0x07, 0x9B, 0x03, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0x53, 0x44, 0xC3, 0x42, 0x65, 0xD4, ++0x50, 0x4E, 0x58, 0xE7, 0x06, 0x9E, 0x02, 0x9B, 0x9A, 0x1B, 0x00, 0x2A, 0xF8, 0xDB, 0xE4, 0xF7, 0x2D, 0xFB, 0x00, 0xF5, ++0x0C, 0x50, 0x36, 0x1B, 0x28, 0x30, 0x86, 0x42, 0x49, 0x4E, 0x11, 0xD9, 0x49, 0x46, 0x20, 0x46, 0x5A, 0x46, 0xD6, 0xF8, ++0x88, 0x30, 0x98, 0x47, 0x06, 0x9C, 0xD6, 0xF8, 0x88, 0x90, 0xE4, 0xF7, 0x1B, 0xFB, 0xA4, 0xF5, 0x7A, 0x64, 0xDA, 0xF8, ++0x40, 0x10, 0x20, 0x1A, 0x5A, 0x46, 0xC8, 0x47, 0x07, 0x9C, 0x02, 0x9B, 0x1B, 0x1B, 0x00, 0x2B, 0xBF, 0xF6, 0x33, 0xAF, ++0x02, 0x9C, 0x30, 0xE7, 0x96, 0xF8, 0x4E, 0x00, 0x01, 0x93, 0xFF, 0x28, 0x51, 0xD1, 0x03, 0x99, 0x0A, 0x44, 0xB1, 0xEB, ++0x52, 0x0F, 0x4F, 0xEA, 0x52, 0x03, 0xA1, 0xD8, 0x03, 0x9A, 0x35, 0x4E, 0xDF, 0xF8, 0xD8, 0xA0, 0xA4, 0x1A, 0x1C, 0x44, ++0x99, 0xF8, 0x18, 0x30, 0xD6, 0xF8, 0x88, 0x80, 0x02, 0x2B, 0x03, 0xF1, 0x01, 0x01, 0x7B, 0xD0, 0xC1, 0xEB, 0xC1, 0x01, ++0x0A, 0xEB, 0x81, 0x01, 0x0A, 0x7E, 0xFF, 0x2A, 0x0E, 0xD1, 0x01, 0x2B, 0x03, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, ++0xC3, 0xEB, 0xC3, 0x03, 0x0A, 0xEB, 0x83, 0x0A, 0x9A, 0xF8, 0x18, 0x30, 0xFF, 0x2B, 0x14, 0xBF, 0x51, 0x46, 0x00, 0x21, ++0x20, 0x46, 0x00, 0x22, 0xC0, 0x47, 0xD6, 0xF8, 0x88, 0x30, 0x2A, 0x46, 0x49, 0x46, 0x38, 0x46, 0x98, 0x47, 0x09, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x06, 0x83, 0x1B, 0x4E, 0x19, 0x6C, 0xD6, 0xF8, 0x88, 0x30, ++0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0xD6, 0xF8, 0x88, 0x30, 0x07, 0x98, 0x49, 0x46, 0x00, 0x22, 0x98, 0x47, 0xBB, 0xF1, ++0x00, 0x0F, 0xAD, 0xD0, 0x06, 0x9C, 0x02, 0x9B, 0x1A, 0xEB, 0x04, 0x0F, 0x58, 0xBF, 0x1C, 0x46, 0xD9, 0xE6, 0x07, 0xAA, ++0x06, 0xA9, 0x0A, 0xFB, 0x00, 0x80, 0x03, 0xF0, 0xD3, 0xFA, 0x06, 0x9C, 0xE4, 0xF7, 0xAC, 0xFA, 0x01, 0x9B, 0x1B, 0x1B, ++0xC3, 0x42, 0x3F, 0xF5, 0xD6, 0xAE, 0x06, 0x9C, 0x08, 0x4E, 0xDF, 0xF8, 0x28, 0xA0, 0xE4, 0xF7, 0xA1, 0xFA, 0x07, 0x9B, ++0xA4, 0xF5, 0x7A, 0x64, 0xFA, 0x1A, 0x24, 0x1A, 0x17, 0xEA, 0x22, 0x07, 0x38, 0xBF, 0x1F, 0x46, 0x9C, 0xE7, 0x00, 0xBF, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0xDD, 0xE9, 0x06, 0x64, ++0xE4, 0xF7, 0x8A, 0xFA, 0x02, 0x9B, 0x04, 0x9A, 0xF6, 0x1A, 0x32, 0x44, 0x13, 0x1A, 0x00, 0x2B, 0x5B, 0xDB, 0xE4, 0xF7, ++0x81, 0xFA, 0x3B, 0x1B, 0xA3, 0xF5, 0x0C, 0x53, 0x28, 0x3B, 0x18, 0x1A, 0x00, 0x28, 0xBF, 0xF6, 0x1B, 0xAF, 0xA6, 0xE6, ++0x37, 0x4E, 0x67, 0xE7, 0x9A, 0xF8, 0x18, 0x30, 0xFF, 0x2B, 0x5F, 0xD1, 0x01, 0x23, 0x89, 0xE7, 0x02, 0x9C, 0x37, 0xE7, ++0xE4, 0xF7, 0x6C, 0xFA, 0x02, 0x9B, 0xF6, 0x1A, 0x04, 0x9B, 0x33, 0x44, 0x1B, 0x1A, 0x00, 0x2B, 0x4A, 0xDB, 0x01, 0x97, ++0xE4, 0xF7, 0x62, 0xFA, 0x07, 0x9B, 0x03, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0xDB, 0x1B, 0xC3, 0x42, 0x4A, 0xD5, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x0B, 0x83, 0x27, 0x4E, 0x1A, 0x6C, 0xDF, 0xF8, 0x9C, 0xA0, 0x11, 0x7E, 0xD6, 0xF8, 0x88, 0x30, ++0x02, 0x29, 0x01, 0xF1, 0x01, 0x02, 0x2B, 0xD0, 0xC2, 0xEB, 0xC2, 0x00, 0x0A, 0xEB, 0x80, 0x00, 0x00, 0x7E, 0xFF, 0x28, ++0x37, 0xD1, 0x01, 0x29, 0x01, 0xF1, 0x02, 0x02, 0x08, 0xBF, 0x00, 0x22, 0xC2, 0xEB, 0xC2, 0x01, 0x0A, 0xEB, 0x81, 0x01, ++0x09, 0x7E, 0xFF, 0x29, 0x08, 0xBF, 0x00, 0x21, 0x29, 0xD1, 0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x0B, 0x88, 0x01, 0x98, 0xD8, 0xF8, 0x40, 0x10, 0xD6, 0xF8, 0x88, 0x30, 0x00, 0x22, 0x98, 0x47, 0x07, 0x9C, ++0x2C, 0xE7, 0x06, 0x9E, 0xE4, 0xF7, 0x24, 0xFA, 0xA6, 0xF5, 0x7A, 0x66, 0x37, 0x1A, 0x9C, 0xE7, 0x9A, 0xF8, 0x18, 0x20, ++0xFF, 0x2A, 0x0D, 0xD1, 0x01, 0x22, 0xD9, 0xE7, 0x06, 0x9E, 0xE4, 0xF7, 0x17, 0xFA, 0xA6, 0xF5, 0x7A, 0x66, 0x33, 0x1A, ++0x01, 0x93, 0xAD, 0xE7, 0x05, 0x49, 0x33, 0xE7, 0x01, 0x9F, 0xAF, 0xE6, 0x00, 0x22, 0x1C, 0x21, 0x01, 0xFB, 0x02, 0xA1, ++0xD1, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x30, 0xB5, 0x0E, 0x48, 0x83, 0xB0, 0x06, 0xF0, ++0x59, 0xFA, 0x01, 0x90, 0xA0, 0xB1, 0x0C, 0x4B, 0x0C, 0x4C, 0xD3, 0xF8, 0xD8, 0x31, 0x0C, 0x48, 0x98, 0x47, 0x00, 0x23, ++0x01, 0x99, 0xA3, 0x64, 0x04, 0xF1, 0x18, 0x05, 0x20, 0x34, 0x28, 0x46, 0x06, 0xF0, 0x04, 0xFA, 0x20, 0x46, 0x06, 0xF0, ++0x45, 0xFA, 0x01, 0x46, 0x00, 0x28, 0xF6, 0xD1, 0x03, 0xB0, 0x30, 0xBD, 0x50, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x4C, 0x4B, 0x42, 0x69, 0x1F, 0x69, 0x4C, 0x4B, ++0x4C, 0x4C, 0x98, 0x42, 0x83, 0xB0, 0x05, 0x46, 0x17, 0x44, 0x6F, 0xD0, 0xA3, 0x6A, 0xAB, 0x42, 0x04, 0xD0, 0xE4, 0xF7, ++0xCD, 0xF9, 0x07, 0xF5, 0x7A, 0x67, 0x07, 0x44, 0x94, 0xF8, 0x5B, 0x80, 0x94, 0xF8, 0x58, 0x30, 0xC4, 0xE9, 0x14, 0x57, ++0xB8, 0xF1, 0x00, 0x0F, 0x57, 0xD1, 0x42, 0x4E, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x73, 0x6B, 0x98, 0x47, ++0xD6, 0xF8, 0x88, 0x30, 0x42, 0x46, 0x41, 0x46, 0x38, 0x46, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, ++0x3A, 0xD0, 0x3A, 0x4B, 0xDF, 0xF8, 0xF8, 0x90, 0xDB, 0x1B, 0x01, 0x93, 0x4F, 0xF4, 0xA4, 0x68, 0x0C, 0xE0, 0x02, 0x2A, ++0x04, 0xBF, 0xB0, 0xF8, 0xD2, 0x20, 0x91, 0x02, 0x61, 0x44, 0x00, 0x22, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, ++0x00, 0x0F, 0x25, 0xD0, 0xDB, 0xF8, 0x04, 0xA0, 0xE4, 0xF7, 0x96, 0xF9, 0x01, 0x9B, 0xAA, 0xEB, 0x00, 0x00, 0xD8, 0x42, ++0x1C, 0xD5, 0x9B, 0xF8, 0x08, 0x00, 0xDB, 0xF8, 0x04, 0xC0, 0xF3, 0x6A, 0x08, 0xFB, 0x00, 0x90, 0x4F, 0xF4, 0xC8, 0x31, ++0x90, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xDC, 0xD1, 0x90, 0xF8, 0x6C, 0x20, 0x24, 0x4F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, ++0x02, 0x72, 0x91, 0x68, 0x00, 0x22, 0x61, 0x44, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, 0xD9, 0xD1, ++0xE3, 0x6A, 0xD3, 0xB1, 0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1B, 0xDB, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x43, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x94, 0xF8, 0x58, 0x30, ++0x5A, 0x07, 0x8B, 0xD4, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD6, 0xF8, ++0x9C, 0x30, 0x28, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x94, 0xF8, 0x58, 0x30, 0x13, 0xF0, 0x0C, 0x0F, ++0xDE, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0x86, 0x62, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x07, 0xF0, 0xAC, 0xBD, ++0x00, 0x10, 0x50, 0x40, 0x00, 0x9E, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x60, 0xF0, 0xFF, 0xFF, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x5C, 0xA1, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x10, 0xB5, 0x22, 0x4C, 0x94, 0xF8, 0x58, 0x30, 0xD8, 0x07, 0x11, 0xD5, 0x20, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, ++0x00, 0x2A, 0x22, 0xDB, 0x23, 0xF0, 0x01, 0x03, 0x43, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x1B, 0x4B, 0x1C, 0x48, ++0xDB, 0x6D, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x03, 0xF0, 0x06, 0x02, 0x02, 0x2A, 0x11, 0xD1, 0x15, 0x4A, 0x12, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x17, 0xDB, 0x23, 0xF0, 0x02, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x58, 0x30, ++0x10, 0x4B, 0x12, 0x48, 0xDB, 0x6D, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x10, 0xBD, 0x59, 0x07, 0xDA, 0xD5, 0x0F, 0x49, ++0x0F, 0x48, 0x40, 0xF2, 0x9B, 0x62, 0x07, 0xF0, 0x61, 0xFD, 0x94, 0xF8, 0x58, 0x30, 0xD1, 0xE7, 0x1A, 0x07, 0xE5, 0xD5, ++0x09, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0xA6, 0x62, 0x07, 0xF0, 0x56, 0xFD, 0x94, 0xF8, 0x58, 0x30, 0xDC, 0xE7, 0x00, 0xBF, ++0x30, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x9E, 0x17, 0x00, 0xE4, 0x9D, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x8C, 0xA1, 0x15, 0x00, 0xC0, 0xA1, 0x15, 0x00, 0x0D, 0x4A, 0x92, 0xF8, 0x58, 0x30, 0xD9, 0x06, ++0x14, 0xD4, 0x92, 0xF8, 0x5A, 0x00, 0x43, 0xF0, 0x10, 0x03, 0x82, 0xF8, 0x58, 0x30, 0x50, 0xB1, 0x08, 0x49, 0x09, 0x4B, ++0x09, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x01, 0xF5, 0xEA, 0x41, 0x02, 0xF1, 0x30, 0x00, 0x30, 0x31, 0x18, 0x47, 0x04, 0x4B, ++0xDB, 0x6B, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0xB5, 0x32, 0x4C, 0x00, 0x23, 0x05, 0x46, 0xA3, 0x62, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x2E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x4A, 0x2E, 0x4E, 0x11, 0x68, 0x73, 0x68, 0x48, 0x1C, 0x23, 0xF0, 0x02, 0x03, ++0x10, 0x60, 0x73, 0x60, 0x18, 0xB1, 0x28, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0xF9, 0xB1, 0x29, 0x49, 0x94, 0xF8, 0x5C, 0x30, ++0x0A, 0x68, 0x9B, 0x00, 0x22, 0xF0, 0x04, 0x02, 0x03, 0xF0, 0x04, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x2B, 0x7E, 0x03, 0x2B, ++0x26, 0xD0, 0x04, 0x2B, 0x94, 0xF8, 0x58, 0x30, 0x19, 0xD0, 0x23, 0xF0, 0x10, 0x02, 0xFF, 0x21, 0x9B, 0x07, 0x29, 0x76, ++0x84, 0xF8, 0x58, 0x20, 0x02, 0xD0, 0x1D, 0x4B, 0x1B, 0x6C, 0x98, 0x47, 0xE3, 0x6A, 0x23, 0xB1, 0x70, 0xBD, 0x00, 0x2B, ++0xDD, 0xD0, 0x62, 0xB6, 0xDB, 0xE7, 0x18, 0x4B, 0xD3, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xBD, 0xE8, 0x70, 0x40, 0xFB, 0xF7, ++0x93, 0xBA, 0x23, 0xF0, 0x04, 0x02, 0x84, 0xF8, 0x58, 0x20, 0xEA, 0x89, 0x92, 0xB9, 0x03, 0xF0, 0xDB, 0x03, 0xDC, 0xE7, ++0x94, 0xF8, 0x58, 0x30, 0x23, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x58, 0x30, 0xFE, 0xF7, 0x84, 0xFE, 0xFF, 0x22, 0x02, 0x21, ++0x86, 0x20, 0x05, 0xF0, 0x49, 0xFC, 0x94, 0xF8, 0x58, 0x30, 0xCC, 0xE7, 0x28, 0x46, 0xFE, 0xF7, 0xB1, 0xFE, 0x94, 0xF8, ++0x58, 0x30, 0xC6, 0xE7, 0x30, 0x9D, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x4C, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x6B, 0x4F, 0x6C, 0x4E, 0x04, 0x46, 0x6C, 0x48, ++0x06, 0xF0, 0x96, 0xF8, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0xC0, 0xF2, 0x85, 0x80, 0x33, 0x78, ++0x00, 0x2B, 0x44, 0xD0, 0x66, 0x4C, 0x01, 0x2B, 0x42, 0xD1, 0x94, 0xF8, 0x58, 0x30, 0x19, 0x07, 0x00, 0xF1, 0x9D, 0x80, ++0x5A, 0x07, 0x40, 0xF1, 0xB0, 0x80, 0x62, 0x4F, 0xE3, 0x6A, 0xBB, 0x42, 0x02, 0xD0, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, ++0xA3, 0x6A, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, 0x00, 0x23, 0xC4, 0xE9, 0x0A, 0x73, 0x39, 0x7E, 0x04, 0x23, 0x03, 0x29, ++0x3B, 0x74, 0x00, 0xF0, 0xA0, 0x80, 0x02, 0x29, 0x24, 0xD9, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x55, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x55, 0x4A, 0x55, 0x48, 0x17, 0x68, 0x43, 0x68, 0x79, 0x1C, 0x43, 0xF0, 0x02, 0x03, ++0x11, 0x60, 0x43, 0x60, 0x29, 0xB1, 0x4F, 0x4B, 0x17, 0x60, 0x1B, 0x68, 0x0F, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x4F, 0x4A, ++0xA3, 0x6A, 0x11, 0x68, 0xC1, 0xF3, 0x80, 0x01, 0x84, 0xF8, 0x5C, 0x10, 0x11, 0x68, 0x21, 0xF0, 0x04, 0x01, 0x11, 0x60, ++0x01, 0xE0, 0x44, 0x4C, 0xA3, 0x6A, 0x01, 0x22, 0x1A, 0x74, 0x22, 0x6D, 0x00, 0x23, 0x33, 0x70, 0x00, 0x2A, 0x31, 0xD0, ++0x94, 0xF8, 0x5A, 0x20, 0x23, 0x65, 0x00, 0x2A, 0x53, 0xD0, 0x01, 0x2A, 0x53, 0xD0, 0x23, 0x69, 0x00, 0x2B, 0x50, 0xD0, ++0x1B, 0x7A, 0x40, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x18, 0x6C, 0xA8, 0x60, 0x18, 0xB1, 0x3D, 0x4B, ++0xD3, 0xF8, 0x9C, 0x30, 0x98, 0x47, 0x3C, 0x48, 0x29, 0x46, 0x05, 0xF0, 0xDF, 0xFF, 0xA0, 0x6A, 0x03, 0x7E, 0x02, 0x2B, ++0x02, 0xD9, 0x37, 0x4B, 0x9B, 0x6B, 0x98, 0x47, 0x20, 0x6A, 0xA0, 0x64, 0x58, 0xB3, 0x36, 0x4B, 0x41, 0x68, 0x1B, 0x69, ++0xCB, 0x1A, 0x14, 0x2B, 0x27, 0xD4, 0x31, 0x4B, 0x33, 0x48, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, ++0xA8, 0x68, 0xDD, 0xE7, 0x84, 0x42, 0x32, 0xD0, 0x2F, 0x49, 0x30, 0x48, 0x40, 0xF2, 0x4F, 0x72, 0x07, 0xF0, 0x12, 0xFC, ++0x33, 0x78, 0x00, 0x2B, 0x7F, 0xF4, 0x72, 0xAF, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB1, 0xDA, 0x1D, 0x4C, ++0xA3, 0x6A, 0x00, 0x2B, 0xAF, 0xD1, 0x26, 0x49, 0x27, 0x48, 0x40, 0xF2, 0x51, 0x72, 0x07, 0xF0, 0xFF, 0xFB, 0x33, 0x78, ++0x61, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x63, 0x6C, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x22, 0x4F, 0x64, 0xE7, 0xAA, 0x60, ++0xBB, 0xE7, 0x21, 0x48, 0x02, 0x7E, 0xFF, 0x2A, 0xB1, 0xD1, 0x90, 0xF8, 0x34, 0x20, 0xFF, 0x2A, 0x12, 0xD1, 0x90, 0xF8, ++0x50, 0x20, 0xFF, 0x2A, 0x10, 0xD1, 0xAB, 0x60, 0xAD, 0xE7, 0x33, 0x78, 0x00, 0x2B, 0xD8, 0xD0, 0x44, 0xE7, 0xE7, 0x6A, ++0x00, 0x2F, 0x87, 0xD0, 0x52, 0xE7, 0x02, 0x20, 0x05, 0xF0, 0xF2, 0xFC, 0x39, 0x7E, 0x5A, 0xE7, 0x1C, 0x30, 0x98, 0xE7, ++0x38, 0x30, 0x96, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x17, 0x2C, 0x17, 0x00, 0x50, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, ++0x00, 0x9E, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x9D, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xF4, 0xA1, 0x15, 0x00, 0x10, 0xA2, 0x15, 0x00, 0xE4, 0x9D, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x0D, 0x4B, 0x93, 0xF8, 0x58, 0x20, 0x11, 0x07, 0x03, 0xD4, 0x52, 0x07, 0x0D, 0xD5, 0x0B, 0x49, 0x00, 0xE0, 0x0B, 0x49, ++0xDA, 0x6A, 0x8A, 0x42, 0x03, 0xD0, 0x0A, 0xB1, 0x01, 0x20, 0x10, 0x74, 0xD9, 0x62, 0x08, 0x4B, 0xD3, 0xF8, 0x98, 0x30, ++0x18, 0x47, 0xDB, 0x6A, 0x00, 0x2B, 0xF8, 0xD1, 0x05, 0x49, 0x08, 0x20, 0x07, 0xF0, 0x68, 0xB9, 0x30, 0x9D, 0x17, 0x00, ++0x00, 0x9E, 0x17, 0x00, 0xE4, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x28, 0xA2, 0x15, 0x00, 0x0B, 0x4A, 0x92, 0xF8, ++0x59, 0x30, 0x43, 0xB1, 0x01, 0x3B, 0xDB, 0xB2, 0x82, 0xF8, 0x59, 0x30, 0x1B, 0xB9, 0x08, 0x4A, 0x11, 0x78, 0x01, 0x29, ++0x00, 0xD0, 0x70, 0x47, 0x10, 0xB5, 0x06, 0x4C, 0x13, 0x70, 0xD4, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xE3, 0x6F, 0xBD, 0xE8, ++0x10, 0x40, 0x18, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x17, 0x2C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x1D, 0x4B, ++0x1D, 0x49, 0x1E, 0x4A, 0xD3, 0xF8, 0xE0, 0x33, 0x8C, 0x68, 0x95, 0x6A, 0x98, 0x47, 0x1C, 0x4B, 0x5B, 0x78, 0x23, 0xB1, ++0x1B, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x1A, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x13, 0x60, ++0x1C, 0xB3, 0x18, 0x4F, 0x8C, 0x26, 0x01, 0xE0, 0x24, 0x68, 0xF4, 0xB1, 0x23, 0x6C, 0xAB, 0x42, 0xFA, 0xD1, 0x94, 0xF8, ++0x62, 0x30, 0x00, 0x2B, 0xF6, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x22, ++0x11, 0x46, 0x3B, 0xB1, 0x94, 0xF8, 0xC1, 0x34, 0x06, 0xFB, 0x03, 0x73, 0x93, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0xE5, 0xD0, ++0x94, 0xF8, 0x6C, 0x00, 0xF2, 0xF7, 0xD6, 0xFD, 0x24, 0x68, 0x00, 0x2C, 0xE0, 0xD1, 0xF8, 0xBD, 0x88, 0x1A, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, ++0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x08, 0x81, 0x3D, 0x4A, 0x3E, 0x4E, 0xD8, 0xF8, 0xDC, 0x33, ++0x94, 0x68, 0x96, 0xF8, 0x59, 0x90, 0x83, 0xB0, 0x98, 0x47, 0xB5, 0x6A, 0x00, 0x2D, 0x5E, 0xD0, 0x39, 0x4A, 0x3A, 0x49, ++0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x4B, 0x78, 0x4F, 0x46, 0x00, 0x2B, 0x4D, 0xD1, 0x00, 0x2C, 0x3A, 0xD0, ++0xDF, 0xF8, 0xD8, 0xB0, 0xDF, 0xF8, 0xD8, 0xA0, 0x4F, 0xF0, 0x06, 0x09, 0x01, 0xE0, 0x24, 0x68, 0x7C, 0xB3, 0x23, 0x6C, ++0x9D, 0x42, 0xFA, 0xD1, 0x94, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xF6, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, ++0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x4F, 0xF0, 0x8C, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0xEA, 0xD0, 0x94, 0xF8, 0xC0, 0x34, ++0x3B, 0xB1, 0x94, 0xF8, 0xC1, 0x34, 0x01, 0xFB, 0x03, 0xA3, 0x93, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0xDF, 0xD0, 0x2B, 0x7C, ++0x85, 0xF8, 0x10, 0x90, 0xD8, 0xF8, 0xB0, 0x10, 0x01, 0x93, 0xF2, 0xF7, 0x79, 0xFD, 0x01, 0x9B, 0x00, 0xB9, 0x01, 0x37, ++0x01, 0x22, 0x2B, 0x74, 0x8B, 0xF8, 0x00, 0x20, 0x24, 0x68, 0x00, 0x2C, 0xCF, 0xD1, 0x5F, 0xFA, 0x87, 0xF9, 0x96, 0xF8, ++0x59, 0x40, 0xF5, 0x6A, 0x86, 0xF8, 0x59, 0x90, 0x3C, 0x1B, 0xAD, 0xB1, 0x27, 0xB1, 0x03, 0x23, 0x2B, 0x74, 0xD8, 0xF8, ++0x60, 0x31, 0x98, 0x47, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD2, 0xF8, 0xE8, 0x33, 0x43, 0xF0, 0x00, 0x43, ++0xC2, 0xF8, 0xE8, 0x33, 0xAA, 0xE7, 0x00, 0x24, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD8, 0xF8, 0x60, 0x31, ++0x98, 0x47, 0x00, 0x2F, 0xF5, 0xD0, 0x96, 0xF8, 0x59, 0x30, 0x01, 0x3B, 0x2C, 0x46, 0x86, 0xF8, 0x59, 0x30, 0xE3, 0xE7, ++0x00, 0x88, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x17, 0x2C, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0xD4, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xA3, 0x6E, ++0x98, 0x47, 0x18, 0xB9, 0xE3, 0x6F, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x43, 0x4D, 0x4E, 0x4E, 0x4F, 0xF4, 0x6A, 0x85, 0xB0, 0x00, 0x25, 0xE2, 0x88, 0x61, 0x79, 0x23, 0x89, ++0x20, 0x79, 0x02, 0x95, 0x65, 0x7B, 0x01, 0x95, 0x65, 0x89, 0x00, 0x95, 0xE3, 0xF7, 0x72, 0xFD, 0xD7, 0xF8, 0x3C, 0x33, ++0x94, 0xF9, 0x0C, 0x00, 0x98, 0x47, 0x21, 0x79, 0x44, 0x4B, 0x45, 0x4A, 0x03, 0xEB, 0x81, 0x03, 0x5B, 0x69, 0x13, 0x60, ++0x23, 0x7E, 0x03, 0x2B, 0x02, 0xD0, 0x20, 0x46, 0xFE, 0xF7, 0xFE, 0xFB, 0xB3, 0x6A, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, ++0x00, 0x23, 0xC6, 0xE9, 0x0A, 0x43, 0x23, 0x7E, 0x04, 0x22, 0x02, 0x2B, 0x22, 0x74, 0x4E, 0xD9, 0x96, 0xF8, 0x5A, 0x20, ++0x00, 0x2A, 0x4A, 0xD0, 0x03, 0x2B, 0x52, 0xD0, 0x04, 0x2B, 0x24, 0xD0, 0xFB, 0x6E, 0x98, 0x47, 0x23, 0x7E, 0x02, 0x2B, ++0x1F, 0xD8, 0x34, 0x4B, 0x9D, 0x68, 0x00, 0x2D, 0x37, 0xD0, 0xDF, 0xF8, 0xE4, 0x90, 0x4F, 0xF0, 0x01, 0x08, 0x01, 0xE0, ++0x2D, 0x68, 0x8D, 0xB1, 0x2B, 0x6C, 0xA3, 0x42, 0xFA, 0xD1, 0x95, 0xF8, 0x63, 0x30, 0xD7, 0xF8, 0x5C, 0x24, 0xC3, 0xEB, ++0xC3, 0x03, 0x09, 0xEB, 0x83, 0x03, 0x28, 0x46, 0x83, 0xF8, 0x1B, 0x80, 0x90, 0x47, 0x2D, 0x68, 0x00, 0x2D, 0xED, 0xD1, ++0x23, 0x7E, 0x02, 0x2B, 0x1B, 0xD9, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x22, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x22, 0x4A, 0x22, 0x4C, 0x11, 0x68, 0x63, 0x68, 0x48, 0x1C, 0x43, 0xF0, 0x02, 0x03, 0x10, 0x60, 0x63, 0x60, ++0x28, 0xBB, 0x1F, 0x4B, 0x19, 0x68, 0x1A, 0x68, 0xC1, 0xF3, 0x80, 0x01, 0x22, 0xF0, 0x04, 0x02, 0x86, 0xF8, 0x5C, 0x10, ++0x1A, 0x60, 0xD7, 0xF8, 0x60, 0x31, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, 0x18, 0x4A, 0x92, 0xF8, 0xFF, 0x21, ++0x00, 0x2A, 0xAF, 0xD0, 0xF1, 0xF7, 0xA2, 0xFB, 0x23, 0x7E, 0x03, 0x2B, 0xAC, 0xD1, 0x14, 0x4B, 0x00, 0x22, 0x1A, 0x60, ++0x02, 0x21, 0xFF, 0x22, 0x85, 0x20, 0x05, 0xF0, 0x77, 0xF9, 0x23, 0x7E, 0x02, 0x2B, 0xE4, 0xD9, 0xC7, 0xE7, 0x09, 0x4B, ++0x11, 0x60, 0x1B, 0x68, 0x00, 0x29, 0xD4, 0xD1, 0x00, 0x2B, 0xD2, 0xD0, 0x62, 0xB6, 0xD0, 0xE7, 0x30, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x20, 0x62, 0x17, 0x00, 0x20, 0x02, 0x32, 0x40, ++0x80, 0x9F, 0x17, 0x00, 0x70, 0xB5, 0x25, 0x4D, 0xEA, 0x6A, 0x04, 0x46, 0x0A, 0xB1, 0xE8, 0x62, 0x70, 0xBD, 0xAE, 0x6A, ++0x86, 0x42, 0x3D, 0xD0, 0x5E, 0xB1, 0x33, 0x7E, 0x03, 0x2B, 0x08, 0xD0, 0x01, 0x23, 0x0C, 0x21, 0x45, 0x20, 0x05, 0xF0, ++0xD7, 0xF8, 0x33, 0x7E, 0x03, 0x70, 0x05, 0xF0, 0x03, 0xF9, 0x1B, 0x4B, 0x5B, 0x68, 0x00, 0x2B, 0x1C, 0xDD, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x17, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x17, 0x4E, 0x33, 0x68, 0x04, 0x20, ++0x01, 0x33, 0x33, 0x60, 0xF1, 0xF7, 0x42, 0xF8, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xF1, 0xF7, 0xDD, 0xF8, 0x33, 0x68, ++0x33, 0xB1, 0x0F, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x02, 0x22, 0xEC, 0x62, ++0x04, 0x23, 0x22, 0x74, 0x00, 0x21, 0xFF, 0x22, 0x84, 0x20, 0x05, 0xF0, 0xA9, 0xF8, 0x09, 0x4B, 0x1B, 0x6E, 0x03, 0x60, ++0xBD, 0xE8, 0x70, 0x40, 0x05, 0xF0, 0xD2, 0xB8, 0x04, 0x23, 0x33, 0x74, 0x70, 0xBD, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, ++0xD8, 0x9C, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x0A, 0x4D, ++0x04, 0x46, 0xD5, 0xF8, 0x6C, 0x31, 0x00, 0x6D, 0x98, 0x47, 0xD5, 0xF8, 0x00, 0x32, 0x20, 0x65, 0x01, 0x46, 0x20, 0x46, ++0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x40, 0x03, 0x43, 0xF0, 0x20, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x38, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x02, 0x6D, 0x41, 0x6A, 0x70, 0xB5, 0x17, 0x4D, 0x04, 0x46, 0xD5, 0xF8, 0xE0, 0x31, 0x11, 0x44, ++0x18, 0x30, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x20, 0x02, 0xDB, 0x07, 0x84, 0xF8, 0x4D, 0x20, 0x0E, 0xD5, ++0x10, 0x4B, 0x5B, 0x6A, 0x23, 0xB1, 0xDA, 0x68, 0x04, 0xF1, 0x44, 0x03, 0x9A, 0x42, 0x07, 0xD0, 0xEB, 0x6A, 0x61, 0x6A, ++0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x70, 0xBD, 0x6B, 0x6B, 0x98, 0x47, 0xEB, 0x6A, 0x61, 0x6A, ++0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0x06, 0x4A, 0xD5, 0xF8, 0x84, 0x30, 0x11, 0x69, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, ++0x70, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF8, 0x43, ++0xDF, 0xF8, 0xB8, 0x80, 0x90, 0xF8, 0x4E, 0x70, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x07, 0x85, 0x95, 0xF8, 0x4D, 0x60, ++0x16, 0xF0, 0x60, 0x06, 0x1F, 0xD1, 0x26, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xFC, 0x31, 0x89, 0x46, 0x90, 0xF8, 0x4F, 0x10, ++0x28, 0x46, 0x98, 0x47, 0x63, 0x6D, 0xA0, 0xEB, 0x09, 0x01, 0x58, 0x1A, 0x00, 0xB2, 0x80, 0xEA, 0xE0, 0x73, 0xA3, 0xEB, ++0xE0, 0x73, 0x9B, 0xB2, 0xB3, 0xF5, 0xFA, 0x6F, 0xA4, 0xF8, 0x58, 0x00, 0x09, 0xD9, 0x95, 0xF8, 0x4D, 0x30, 0x23, 0xF0, ++0x40, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x85, 0xF8, 0x4D, 0x30, 0xBD, 0xE8, 0xF8, 0x83, 0xC8, 0x2B, 0xFB, 0xD9, 0x15, 0x4B, ++0x9B, 0x68, 0x9B, 0xB1, 0x95, 0xF8, 0x63, 0x10, 0x30, 0x46, 0x93, 0xF8, 0x4E, 0x20, 0x8A, 0x42, 0x07, 0xD1, 0xB3, 0xF9, ++0x58, 0x20, 0x90, 0x42, 0xA8, 0xBF, 0x10, 0x46, 0x96, 0x42, 0xB8, 0xBF, 0x16, 0x46, 0x1B, 0x68, 0x00, 0x2B, 0xF0, 0xD1, ++0x60, 0xB9, 0x73, 0x10, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x87, 0x97, 0xF8, 0x4D, 0x20, 0x3B, 0x65, 0x42, 0xF0, ++0x40, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0xD8, 0xE7, 0x00, 0x2E, 0xD6, 0xD1, 0x00, 0xEB, 0xD0, 0x73, 0x5B, 0x10, 0xED, 0xE7, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x23, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x60, 0x22, ++0x00, 0x21, 0x22, 0x4F, 0x06, 0x46, 0xE2, 0xF7, 0xD3, 0xFB, 0x00, 0x25, 0x3C, 0x46, 0xA8, 0x46, 0x00, 0x21, 0x1C, 0x22, ++0x20, 0x46, 0xE2, 0xF7, 0xCB, 0xFB, 0xFF, 0x23, 0x02, 0x2D, 0xE3, 0x81, 0x23, 0x76, 0xE3, 0x76, 0x21, 0x46, 0x30, 0x46, ++0x04, 0xD8, 0x05, 0xF0, 0x55, 0xFC, 0x01, 0x35, 0x1C, 0x34, 0xED, 0xE7, 0x03, 0x2D, 0x22, 0xD0, 0x04, 0x2D, 0xF8, 0xD1, ++0x14, 0x48, 0x05, 0xF0, 0x47, 0xFC, 0x14, 0x48, 0x05, 0xF0, 0x44, 0xFC, 0x13, 0x49, 0x11, 0x48, 0x05, 0xF0, 0x44, 0xFC, ++0x12, 0x49, 0x0F, 0x48, 0x05, 0xF0, 0x40, 0xFC, 0x11, 0x49, 0x0D, 0x48, 0x05, 0xF0, 0x3C, 0xFC, 0x10, 0x49, 0x0B, 0x48, ++0x05, 0xF0, 0x38, 0xFC, 0x0F, 0x4A, 0x07, 0x4B, 0xD2, 0xF8, 0xAC, 0x10, 0xD0, 0x6B, 0x58, 0x63, 0x00, 0x22, 0xC3, 0xE9, ++0x11, 0x12, 0xBD, 0xE8, 0xF0, 0x81, 0xA7, 0xF8, 0x5E, 0x80, 0x87, 0xF8, 0x59, 0x80, 0xD2, 0xE7, 0x30, 0x9D, 0x17, 0x00, ++0x90, 0x9D, 0x17, 0x00, 0x48, 0x9D, 0x17, 0x00, 0x50, 0x9D, 0x17, 0x00, 0xF0, 0x9C, 0x17, 0x00, 0x00, 0x9D, 0x17, 0x00, ++0x10, 0x9D, 0x17, 0x00, 0x20, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x21, 0x4C, 0x24, 0x68, ++0xB4, 0xF9, 0x00, 0x40, 0x83, 0xB0, 0x00, 0x2C, 0x9D, 0xF8, 0x28, 0x90, 0x9D, 0xF8, 0x2C, 0x80, 0x1D, 0x4C, 0x07, 0x46, ++0x0D, 0x46, 0x16, 0x46, 0x27, 0xDB, 0x1C, 0x49, 0x84, 0xF8, 0x58, 0x70, 0x91, 0xF8, 0x58, 0x20, 0xA4, 0xF8, 0x5C, 0x50, ++0xA4, 0xF8, 0x5A, 0x50, 0x42, 0xF0, 0x02, 0x07, 0x84, 0xF8, 0x60, 0x60, 0xFF, 0x25, 0x03, 0x26, 0x01, 0x20, 0xA3, 0x66, ++0xD3, 0x06, 0x84, 0xF8, 0x61, 0x90, 0x84, 0xF8, 0x6E, 0x80, 0x81, 0xF8, 0x58, 0x70, 0x84, 0xF8, 0x6C, 0x60, 0xA4, 0xF8, ++0x62, 0x50, 0x84, 0xF8, 0x64, 0x00, 0x05, 0xD4, 0x0D, 0x4B, 0x1B, 0x6C, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x94, 0xF8, 0x6C, 0x20, 0xFF, 0x2A, 0xD3, 0xD0, 0x08, 0x49, 0x08, 0x48, 0x01, 0x93, ++0x40, 0xF6, 0x8C, 0x22, 0x07, 0xF0, 0x26, 0xF8, 0x01, 0x9B, 0xCA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x48, 0xA2, 0x15, 0x00, 0xF0, 0xB5, 0x65, 0x4F, ++0x04, 0x46, 0x83, 0xB0, 0x97, 0xF8, 0x80, 0x00, 0xE3, 0x68, 0x22, 0x78, 0x00, 0x90, 0x0E, 0x46, 0x08, 0x20, 0x61, 0x49, ++0x06, 0xF0, 0xE0, 0xFD, 0x25, 0x78, 0x25, 0xB3, 0x01, 0x2D, 0x2F, 0xD1, 0x97, 0xF8, 0x88, 0x30, 0xFF, 0x2B, 0x1A, 0xD0, ++0x97, 0xF8, 0x80, 0x30, 0x03, 0x2B, 0x2B, 0xD8, 0x01, 0x2B, 0x5A, 0x4C, 0x44, 0xD8, 0x09, 0xD1, 0x94, 0xF8, 0x58, 0x30, ++0x07, 0xF1, 0x70, 0x00, 0x23, 0xF0, 0x05, 0x03, 0x84, 0xF8, 0x58, 0x30, 0xFE, 0xF7, 0xE4, 0xF9, 0x94, 0xF8, 0x58, 0x30, ++0x03, 0xF0, 0x12, 0x02, 0xFF, 0x21, 0x10, 0x2A, 0x87, 0xF8, 0x88, 0x10, 0x24, 0xD0, 0x00, 0x25, 0x28, 0x46, 0x03, 0xB0, ++0xF0, 0xBD, 0x97, 0xF8, 0x88, 0x30, 0xFF, 0x2B, 0x3A, 0xD0, 0x4B, 0x4A, 0x92, 0xF8, 0x58, 0x30, 0x99, 0x06, 0x03, 0xD5, ++0x23, 0xF0, 0x20, 0x03, 0x82, 0xF8, 0x58, 0x30, 0x01, 0x25, 0x28, 0x46, 0x03, 0xB0, 0xF0, 0xBD, 0x04, 0x2B, 0x17, 0xD1, ++0x44, 0x48, 0x45, 0x4D, 0xA0, 0xF1, 0x40, 0x04, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x22, 0xD5, 0xF8, 0xAC, 0x30, ++0x20, 0x6A, 0xA2, 0x64, 0x98, 0x47, 0xD1, 0xE7, 0x3E, 0x4A, 0x3F, 0x48, 0xD2, 0xF8, 0xD8, 0x21, 0x23, 0xF0, 0x10, 0x03, ++0x84, 0xF8, 0x58, 0x30, 0x90, 0x47, 0xD0, 0xE7, 0x37, 0x4C, 0xC5, 0xE7, 0x94, 0xF8, 0x58, 0x30, 0xE2, 0x6A, 0x23, 0xF0, ++0x04, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x2A, 0xB1, 0x07, 0xF1, 0x70, 0x03, 0x9A, 0x42, 0x50, 0xD0, 0x00, 0x23, 0xE3, 0x62, ++0x33, 0x48, 0xFE, 0xF7, 0x99, 0xF9, 0xB3, 0xE7, 0x97, 0xF8, 0x80, 0x30, 0x04, 0x2B, 0xC0, 0xD0, 0x04, 0x20, 0x05, 0xF0, ++0x5D, 0xF9, 0x01, 0x28, 0xBB, 0xD0, 0x04, 0x23, 0x87, 0xF8, 0x88, 0x30, 0xA3, 0x78, 0x87, 0xF8, 0x74, 0x30, 0xE3, 0x78, ++0x87, 0xF8, 0x75, 0x30, 0xA3, 0x88, 0xE2, 0x88, 0xA7, 0xF8, 0x76, 0x30, 0x01, 0x21, 0x23, 0x89, 0x87, 0xF8, 0x80, 0x10, ++0xA7, 0xF8, 0x78, 0x20, 0xE2, 0x68, 0xA7, 0xF8, 0x7A, 0x30, 0x4F, 0xF4, 0x7A, 0x73, 0x03, 0xFB, 0x02, 0xF3, 0x23, 0x2A, ++0x84, 0xBF, 0xA3, 0xF5, 0x08, 0x43, 0xB8, 0x3B, 0xA7, 0xF8, 0x7E, 0x60, 0xC7, 0xF8, 0x84, 0x30, 0x63, 0x78, 0x17, 0x4A, ++0x87, 0xF8, 0x8A, 0x30, 0x23, 0x7C, 0x87, 0xF8, 0x7C, 0x30, 0x16, 0x49, 0x92, 0xF8, 0x58, 0x30, 0x66, 0xB9, 0x43, 0xF0, ++0x04, 0x03, 0xC9, 0x6D, 0x14, 0x48, 0x82, 0xF8, 0x58, 0x30, 0x88, 0x47, 0x13, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, ++0x13, 0x60, 0x8A, 0xE7, 0x43, 0xF0, 0x01, 0x03, 0x09, 0x6C, 0x82, 0xF8, 0x58, 0x30, 0x88, 0x47, 0xF2, 0xE7, 0x23, 0x6D, ++0x93, 0x42, 0xAB, 0xD1, 0x08, 0x4B, 0x04, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x23, 0xA3, 0x64, ++0xA2, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, 0x68, 0xA2, 0x15, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x60, 0x9D, 0x17, 0x00, 0x00, 0x9E, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x36, 0x4E, 0x84, 0xB0, 0x04, 0x46, 0x0F, 0x46, 0x33, 0x46, 0x00, 0x25, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, 0x1A, 0x79, ++0x20, 0x78, 0x90, 0x42, 0x1B, 0xD0, 0x01, 0x35, 0x03, 0x2D, 0x03, 0xF1, 0x1C, 0x03, 0xF3, 0xD1, 0x2E, 0x48, 0x05, 0xF0, ++0x15, 0xFB, 0x03, 0x46, 0x70, 0xB3, 0x2D, 0x4A, 0x86, 0x1B, 0xB6, 0x10, 0x02, 0xFB, 0x06, 0xF6, 0xF6, 0xB2, 0x06, 0x76, ++0x3E, 0x70, 0x20, 0x68, 0x61, 0x68, 0x04, 0x33, 0x03, 0xC3, 0x22, 0x89, 0x1A, 0x80, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, ++0xF0, 0x81, 0xD9, 0x88, 0x62, 0x88, 0x8A, 0x42, 0xDF, 0xD1, 0x93, 0xF8, 0x05, 0xC0, 0x61, 0x78, 0x8C, 0x45, 0x08, 0xD0, ++0x02, 0xD2, 0xBC, 0xF1, 0x03, 0x0F, 0x13, 0xD1, 0x8C, 0x45, 0xD4, 0xD9, 0x03, 0x29, 0xD2, 0xD0, 0x07, 0xE0, 0x19, 0x89, ++0xA2, 0x88, 0x91, 0x42, 0xCD, 0xD1, 0x59, 0x89, 0xE2, 0x88, 0x91, 0x42, 0xC9, 0xD1, 0x3D, 0x70, 0x00, 0x20, 0xDF, 0xE7, ++0x01, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0xDF, 0xF8, 0x48, 0xE0, 0xB4, 0xF8, 0x04, 0x80, 0xB4, 0xF8, 0x06, 0xC0, ++0xDE, 0xF8, 0x28, 0x30, 0xC5, 0xEB, 0xC5, 0x04, 0x06, 0xEB, 0x84, 0x04, 0xA3, 0x42, 0x61, 0x71, 0xA4, 0xF8, 0x08, 0x80, ++0xA4, 0xF8, 0x0A, 0xC0, 0xE5, 0xD1, 0x9E, 0xF8, 0x5A, 0x40, 0x01, 0x2C, 0xE1, 0xD1, 0x1C, 0x24, 0x04, 0xFB, 0x05, 0x66, ++0x00, 0x24, 0x76, 0x7B, 0xCD, 0xF8, 0x00, 0xC0, 0xCD, 0xE9, 0x01, 0x64, 0x43, 0x46, 0xE3, 0xF7, 0xCF, 0xF9, 0xD4, 0xE7, ++0x90, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0xB7, 0x6D, 0xDB, 0xB6, 0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x98, 0x80, ++0x20, 0x4D, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0xC0, 0xEB, 0xC0, 0x06, 0x00, 0x2B, 0x04, 0x46, 0x05, 0xEB, ++0x86, 0x06, 0x12, 0xDB, 0xC7, 0x00, 0x1B, 0x48, 0x31, 0x46, 0x3C, 0x1B, 0x05, 0xF0, 0x5C, 0xFA, 0x05, 0xEB, 0x84, 0x04, ++0x30, 0x46, 0x1C, 0x22, 0x00, 0x21, 0xE2, 0xF7, 0xC1, 0xF9, 0xFF, 0x23, 0xE3, 0x81, 0x23, 0x76, 0xE3, 0x76, 0xBD, 0xE8, ++0xF0, 0x81, 0xC0, 0xEB, 0xC0, 0x03, 0x05, 0xEB, 0x83, 0x03, 0xC7, 0x00, 0x1B, 0x7E, 0xFF, 0x2B, 0x0C, 0xD0, 0x3B, 0x1B, ++0x05, 0xEB, 0x83, 0x03, 0x5B, 0x7E, 0x00, 0x2B, 0xDF, 0xD0, 0x0C, 0x49, 0x0C, 0x48, 0x40, 0xF6, 0x5C, 0x32, 0x06, 0xF0, ++0x8F, 0xFE, 0xD8, 0xE7, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0x5A, 0x32, 0x06, 0xF0, 0x88, 0xFE, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE6, 0xDB, 0xCB, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0xA2, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xDF, 0xF8, 0x4C, 0x82, 0xDF, 0xF8, 0x24, 0xA2, 0xD8, 0xF8, 0x00, 0x20, 0x84, 0x4F, 0xB2, 0xF9, 0x00, 0x30, 0xC1, 0xEB, ++0xC1, 0x06, 0x00, 0x2B, 0x85, 0xB0, 0x0C, 0x46, 0x05, 0x46, 0x0A, 0xEB, 0x86, 0x06, 0x5F, 0xDB, 0x4F, 0xEA, 0xC4, 0x0B, ++0xAB, 0xEB, 0x04, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x4A, 0x7E, 0xDF, 0xF8, 0x1C, 0x92, 0x01, 0x32, ++0x03, 0xFB, 0x05, 0x73, 0xD2, 0xB2, 0x00, 0x20, 0x01, 0x2A, 0x4A, 0x76, 0x1E, 0x64, 0x83, 0xF8, 0x4D, 0x00, 0x6B, 0xD0, ++0xDF, 0xF8, 0x04, 0x82, 0x99, 0xF8, 0x5B, 0x10, 0x99, 0xF8, 0x5A, 0x30, 0x4F, 0xF4, 0x80, 0x70, 0xCD, 0xE9, 0x00, 0x31, ++0x6F, 0x49, 0x23, 0x46, 0x06, 0xF0, 0x12, 0xFC, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0x73, 0xFF, 0x21, 0x93, 0xF8, ++0xC0, 0x24, 0x83, 0xF8, 0x4E, 0x10, 0x4A, 0xB1, 0x69, 0x49, 0x93, 0xF8, 0xC1, 0x24, 0x8C, 0x20, 0x00, 0xFB, 0x02, 0x12, ++0x92, 0xF8, 0x70, 0x20, 0x01, 0x2A, 0x20, 0xD0, 0x65, 0x4B, 0x03, 0xF1, 0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, ++0xDA, 0x7E, 0xFF, 0x2A, 0x40, 0xF0, 0xAA, 0x80, 0x1C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0xD8, 0xF8, 0xB4, 0x30, 0x30, 0x46, ++0x98, 0x47, 0x5E, 0x4B, 0x1B, 0x7C, 0xAB, 0x42, 0x08, 0xD0, 0xFF, 0x2B, 0x06, 0xD0, 0xD8, 0xF8, 0x50, 0x30, 0x20, 0x46, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x93, 0xF8, 0x4D, 0x20, 0x42, 0xF0, ++0x10, 0x02, 0x83, 0xF8, 0x4D, 0x20, 0xE4, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x73, 0x1B, 0x6C, 0x5B, 0xB1, ++0x50, 0x49, 0x51, 0x48, 0x40, 0xF6, 0x6B, 0x32, 0x06, 0xF0, 0xF4, 0xFD, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x8D, 0xDA, 0xC4, 0xEB, 0xC4, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0xC4, 0x0B, 0x1B, 0x7E, 0xFF, 0x2B, ++0x86, 0xD1, 0x46, 0x49, 0x47, 0x48, 0x40, 0xF6, 0x6C, 0x32, 0x06, 0xF0, 0xDF, 0xFD, 0x7F, 0xE7, 0x99, 0xF8, 0x5A, 0x00, ++0x0A, 0x74, 0x42, 0x1C, 0xD8, 0xF8, 0x00, 0x30, 0xD2, 0xB2, 0x89, 0xF8, 0x5A, 0x20, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x28, 0xDB, 0x02, 0x2A, 0x3C, 0xD0, 0x3E, 0x48, 0x31, 0x46, 0x05, 0xF0, 0x77, 0xF9, 0x99, 0xF8, 0x58, 0x30, 0x13, 0xF0, ++0x0C, 0x0F, 0x0F, 0xD0, 0xD8, 0xF8, 0x00, 0x20, 0xD9, 0xF8, 0x20, 0x30, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x20, 0xDB, ++0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0x9E, 0x60, 0x9A, 0xF8, 0x19, 0x20, 0x6B, 0xE7, 0xD9, 0xF8, 0x2C, 0x30, ++0x8B, 0xB3, 0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0xDF, 0xF8, 0xD0, 0x80, 0x9A, 0xF8, 0x19, 0x20, 0xC9, 0xF8, ++0x2C, 0x60, 0x5F, 0xE7, 0x02, 0x2A, 0xD4, 0xD9, 0x40, 0xF6, 0x81, 0x32, 0x25, 0x49, 0x29, 0x48, 0x06, 0xF0, 0xA0, 0xFD, ++0x99, 0xF8, 0x5A, 0x20, 0xCB, 0xE7, 0x00, 0x2B, 0xDC, 0xD1, 0x21, 0x49, 0x25, 0x48, 0x03, 0x93, 0x4F, 0xF4, 0x39, 0x62, ++0x06, 0xF0, 0x94, 0xFD, 0x03, 0x9B, 0xD3, 0xE7, 0x22, 0x48, 0x05, 0xF0, 0x37, 0xF9, 0x16, 0x4B, 0x03, 0xF5, 0xA4, 0x51, ++0x93, 0xF8, 0x4D, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x4D, 0x20, 0x03, 0xF5, 0xA4, 0x63, 0x99, 0x42, 0xF5, 0xD1, ++0xB1, 0xE7, 0xDF, 0xF8, 0x74, 0x80, 0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0xD8, 0xF8, 0x9C, 0x30, 0x30, 0x46, ++0x98, 0x47, 0x9A, 0xF8, 0x19, 0x20, 0x2B, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x72, 0x12, 0x6C, 0xB2, 0x42, ++0x3F, 0xF4, 0x51, 0xAF, 0x03, 0xFB, 0x05, 0x77, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x10, 0x03, 0x87, 0xF8, 0x4D, 0x30, ++0x47, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0xE0, 0xA2, 0x15, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x38, 0x9D, 0x17, 0x00, ++0xB8, 0xA2, 0x15, 0x00, 0xD4, 0xA2, 0x15, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xBC, 0xA2, 0xDF, 0xF8, 0xB4, 0x82, 0xDA, 0xF8, 0x00, 0x30, ++0x4F, 0xF4, 0xA4, 0x69, 0xB3, 0xF9, 0x00, 0x30, 0x09, 0xFB, 0x00, 0xF9, 0x08, 0xEB, 0x09, 0x02, 0x00, 0x2B, 0x14, 0x6C, ++0x85, 0xB0, 0x05, 0x46, 0xC0, 0xF2, 0x99, 0x80, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x05, 0x86, 0x9A, 0x4F, 0x96, 0xF8, ++0x4D, 0x00, 0x21, 0x7C, 0x97, 0xF8, 0x5A, 0x30, 0x62, 0x7E, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x01, 0x97, 0xF8, 0x5B, 0x30, ++0x95, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x06, 0xF0, 0xEF, 0xFA, 0x09, 0xF1, 0x44, 0x01, 0x07, 0xF1, 0x10, 0x00, 0x41, 0x44, ++0x05, 0xF0, 0x0E, 0xF9, 0x96, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x01, 0x02, 0x86, 0xF8, 0x4D, 0x20, 0x9A, 0x07, 0x09, 0xD5, ++0x97, 0xF8, 0x5B, 0x30, 0x97, 0xF8, 0x5A, 0x20, 0x01, 0x3B, 0xDB, 0xB2, 0x01, 0x2A, 0x87, 0xF8, 0x5B, 0x30, 0x5D, 0xD9, ++0xDF, 0xF8, 0x3C, 0xB2, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x05, 0x85, 0x00, 0x23, 0x85, 0xF8, 0x4D, 0x30, 0x2B, 0x64, ++0x66, 0x7E, 0x23, 0x7C, 0x01, 0x3E, 0xF6, 0xB2, 0x66, 0x76, 0x00, 0x2B, 0x45, 0xD0, 0x95, 0xF8, 0x63, 0x30, 0xE2, 0x7E, ++0x9A, 0x42, 0x00, 0xF0, 0x85, 0x80, 0x7C, 0x4B, 0x03, 0xF1, 0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, 0xD8, 0x7E, ++0xFF, 0x28, 0x40, 0xF0, 0xBD, 0x80, 0x1C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0x00, 0x2E, 0x4E, 0xD0, 0xDB, 0xF8, 0xB4, 0x30, ++0x20, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x97, 0xF8, 0x5A, 0x30, 0x00, 0x20, 0xB8, 0x62, 0x00, 0x2B, ++0x59, 0xD0, 0x21, 0x7E, 0xDB, 0xF8, 0x9C, 0x50, 0x6C, 0x4A, 0x02, 0x29, 0x01, 0xF1, 0x01, 0x03, 0x00, 0xF0, 0xC0, 0x80, ++0xC3, 0xEB, 0xC3, 0x06, 0x02, 0xEB, 0x86, 0x06, 0xD8, 0x00, 0x36, 0x7E, 0xFF, 0x2E, 0x40, 0xF0, 0xC3, 0x80, 0x01, 0x29, ++0x01, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, 0xC3, 0xEB, 0xC3, 0x01, 0x02, 0xEB, 0x81, 0x01, 0xD8, 0x00, 0x09, 0x7E, ++0xFF, 0x29, 0x08, 0xBF, 0x00, 0x20, 0x40, 0xF0, 0xB3, 0x80, 0xA8, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0xCC, 0xD1, 0xDB, 0xF8, ++0x48, 0x30, 0x20, 0x7E, 0x98, 0x47, 0xC7, 0xE7, 0x00, 0x2B, 0x9F, 0xD1, 0x97, 0xF8, 0x58, 0x30, 0xDF, 0xF8, 0x78, 0xB1, ++0x5B, 0x06, 0x9B, 0xD5, 0x38, 0x6D, 0xDB, 0xF8, 0x5C, 0x30, 0x98, 0x47, 0x96, 0xE7, 0x00, 0x2C, 0x7F, 0xF4, 0x64, 0xAF, ++0x51, 0x49, 0x52, 0x48, 0x40, 0xF6, 0xC4, 0x32, 0x06, 0xF0, 0x8C, 0xFC, 0x5C, 0xE7, 0x50, 0x48, 0x21, 0x46, 0x05, 0xF0, ++0x83, 0xF8, 0x26, 0x74, 0x97, 0xF8, 0x5A, 0x30, 0xDA, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0xDB, 0xB2, 0x87, 0xF8, 0x5A, 0x30, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x0A, 0xDB, 0x03, 0xBB, 0xBB, 0x6A, 0xA3, 0x42, 0xA2, 0xD0, 0xFB, 0x6A, 0xA3, 0x42, ++0x31, 0xD0, 0x66, 0x7E, 0x00, 0x2E, 0xC8, 0xD0, 0x94, 0xE7, 0x01, 0x2B, 0xF2, 0xD9, 0x3F, 0x49, 0x41, 0x48, 0x4F, 0xF4, ++0x40, 0x62, 0x06, 0xF0, 0x67, 0xFC, 0x97, 0xF8, 0x5A, 0x30, 0xE9, 0xE7, 0xDB, 0xF8, 0x94, 0x30, 0x08, 0xEB, 0x09, 0x00, ++0x98, 0x47, 0x66, 0x7E, 0xFF, 0x23, 0xE3, 0x76, 0x00, 0x2E, 0x7F, 0xF4, 0x7F, 0xAF, 0xCC, 0xE7, 0x38, 0x48, 0x04, 0xF0, ++0xFD, 0xFF, 0x38, 0x4B, 0x03, 0xF5, 0xA4, 0x51, 0x93, 0xF8, 0x4D, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x4D, 0x20, ++0x03, 0xF5, 0xA4, 0x63, 0x99, 0x42, 0xF5, 0xD1, 0x3B, 0x6D, 0x00, 0x2B, 0xCB, 0xD1, 0xDB, 0xF8, 0x34, 0x30, 0x98, 0x47, ++0xC7, 0xE7, 0x21, 0x7E, 0x27, 0x4A, 0x02, 0x29, 0x01, 0xF1, 0x01, 0x03, 0x29, 0xD0, 0xC3, 0xEB, 0xC3, 0x05, 0x02, 0xEB, ++0x85, 0x05, 0xD8, 0x00, 0x2D, 0x7E, 0xFF, 0x2D, 0x35, 0xD1, 0x01, 0x29, 0x01, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, ++0xC3, 0xEB, 0xC3, 0x01, 0x02, 0xEB, 0x81, 0x01, 0xD8, 0x00, 0x09, 0x7E, 0xFF, 0x29, 0x08, 0xBF, 0x00, 0x22, 0x26, 0xD1, ++0xFA, 0x62, 0xAE, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x80, 0x03, 0x6C, 0xA3, 0x42, 0x3F, 0xF4, 0x3E, 0xAF, ++0x66, 0xB1, 0xDB, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0x7F, 0xF4, 0x38, 0xAF, 0x85, 0xE7, 0x13, 0x7E, ++0xFF, 0x2B, 0x0E, 0xD1, 0x01, 0x23, 0xDD, 0xE7, 0xDB, 0xF8, 0x94, 0x30, 0x98, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0x7F, 0xF4, ++0x2B, 0xAF, 0x78, 0xE7, 0x13, 0x7E, 0xFF, 0x2B, 0x07, 0xD1, 0x01, 0x23, 0x48, 0xE7, 0x00, 0x23, 0x18, 0x46, 0xC3, 0x1A, ++0x02, 0xEB, 0x83, 0x02, 0xD4, 0xE7, 0x03, 0x46, 0xC0, 0x1A, 0x02, 0xEB, 0x80, 0x00, 0x48, 0xE7, 0x30, 0x9D, 0x17, 0x00, ++0x08, 0xA3, 0x15, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF8, 0xA2, 0x15, 0x00, 0x38, 0x9D, 0x17, 0x00, ++0x28, 0xA3, 0x15, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x43, 0x03, 0x46, 0x05, 0x78, 0x29, 0x4E, 0x2A, 0x4A, 0x04, 0x46, 0x53, 0xF8, 0x02, 0x0F, 0x97, 0x6A, ++0x59, 0x68, 0xB3, 0xF8, 0x08, 0xC0, 0xC5, 0xEB, 0xC5, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x04, 0x33, 0x03, 0xC3, 0xC5, 0xEB, ++0xC5, 0x02, 0x06, 0xEB, 0x82, 0x02, 0x97, 0x42, 0x85, 0xB0, 0xA3, 0xF8, 0x00, 0xC0, 0x02, 0xD0, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x83, 0x4F, 0xEA, 0xC5, 0x08, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x1A, 0x4F, 0xDF, 0xF8, 0x68, 0x90, 0x3B, 0x68, 0xD9, 0xF8, 0xA0, 0x22, 0x01, 0x33, 0x3B, 0x60, 0x90, 0x47, ++0xD9, 0xF8, 0x88, 0x32, 0x00, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x33, 0xB1, 0x11, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xE2, 0x7A, 0x23, 0x89, 0x00, 0x93, 0x00, 0x21, 0xCD, 0xE9, 0x01, 0x21, 0xA8, 0xEB, ++0x05, 0x05, 0xE3, 0x88, 0xA0, 0x78, 0xA2, 0x88, 0xE1, 0x78, 0x06, 0xEB, 0x85, 0x06, 0xE2, 0xF7, 0x91, 0xFE, 0xD9, 0xF8, ++0x3C, 0x33, 0x96, 0xF9, 0x0C, 0x00, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x12, 0x4D, ++0x12, 0x4A, 0x2B, 0x7C, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x03, 0x24, 0x06, 0x46, 0x22, 0x6C, 0x4A, 0xB1, 0x0F, 0x4C, ++0x18, 0x46, 0x63, 0x6D, 0x98, 0x47, 0xE3, 0x6C, 0x28, 0x7C, 0x31, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x05, 0x22, ++0x11, 0x46, 0x02, 0x23, 0x41, 0xF2, 0x17, 0x40, 0x04, 0xF0, 0x7E, 0xFA, 0x01, 0x22, 0x02, 0x70, 0x94, 0xF8, 0x63, 0x20, ++0x42, 0x70, 0x04, 0xF0, 0xA7, 0xFA, 0x03, 0x4C, 0xE9, 0xE7, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x6B, 0x4D, 0x2C, 0x69, 0x07, 0x46, 0x8B, 0x46, 0x91, 0x46, 0x8C, 0xB3, ++0x63, 0x68, 0xD0, 0xF8, 0x40, 0xA0, 0xD5, 0xF8, 0x28, 0x80, 0x8B, 0x42, 0x12, 0xD0, 0x05, 0xF1, 0x10, 0x06, 0xA3, 0xEB, ++0x0B, 0x03, 0x00, 0x2B, 0x21, 0x46, 0x30, 0x46, 0x26, 0xDA, 0x04, 0xF0, 0x33, 0xFF, 0x63, 0x7A, 0x23, 0xF0, 0x01, 0x03, ++0x63, 0x72, 0x2C, 0x69, 0xF4, 0xB1, 0x63, 0x68, 0x5B, 0x45, 0xEE, 0xD1, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x4F, 0xF0, ++0x00, 0x04, 0x1B, 0xD8, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x02, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, ++0xB8, 0xEB, 0x0A, 0x00, 0x03, 0xF1, 0x01, 0x03, 0x18, 0xBF, 0x01, 0x20, 0x85, 0xF8, 0x5B, 0x30, 0xBD, 0xE8, 0xF8, 0x8F, ++0xD0, 0xF8, 0x40, 0xA0, 0xD5, 0xF8, 0x28, 0x80, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x4F, 0xF0, 0x01, 0x04, 0xE3, 0xD9, ++0x97, 0xF8, 0x4E, 0x30, 0xFF, 0x2B, 0x26, 0xD0, 0x49, 0x4E, 0x59, 0x46, 0x73, 0x6F, 0x38, 0x46, 0x98, 0x47, 0x00, 0x2C, ++0x41, 0xD0, 0x97, 0xF8, 0x4D, 0x30, 0x97, 0xF8, 0xC0, 0x24, 0x43, 0xF0, 0x04, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x82, 0xB1, ++0x42, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x06, 0xD1, ++0xBB, 0x6C, 0x4B, 0x45, 0x03, 0xD0, 0xA3, 0xEB, 0x09, 0x02, 0x32, 0x2A, 0x5D, 0xD4, 0xB8, 0xEB, 0x0A, 0x00, 0x18, 0xBF, ++0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x97, 0xF8, 0xC0, 0x34, 0xB3, 0xB3, 0x35, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, ++0x01, 0xFB, 0x03, 0x21, 0x91, 0xF8, 0x70, 0x10, 0x01, 0x29, 0x35, 0xD0, 0x00, 0x2C, 0x4F, 0xD1, 0x30, 0x48, 0x07, 0xF1, ++0x44, 0x01, 0x04, 0xF0, 0xC9, 0xFE, 0x97, 0xF8, 0x4D, 0x30, 0x03, 0xF0, 0xFE, 0x03, 0x43, 0xF0, 0x02, 0x03, 0x87, 0xF8, ++0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, 0x01, 0x33, 0x85, 0xF8, 0x5B, 0x30, 0xD7, 0xE7, 0x97, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0xE8, 0xD0, 0x24, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, ++0xDE, 0xD1, 0xF3, 0x6A, 0x49, 0x46, 0x00, 0x22, 0x38, 0x46, 0x98, 0x47, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x08, 0x03, ++0xDD, 0xE7, 0x00, 0x2C, 0xD2, 0xD0, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x04, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0xB6, 0xE7, ++0x97, 0xF8, 0x4D, 0x10, 0xC8, 0x06, 0x0B, 0xD5, 0x12, 0x4E, 0x38, 0x46, 0xD6, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x97, 0xF8, ++0x4D, 0x30, 0x23, 0xF0, 0x10, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x8A, 0xE7, 0x4E, 0x06, 0x10, 0xD4, 0x54, 0xB9, 0x0B, 0x4E, ++0xD7, 0xE7, 0xA9, 0xEB, 0x03, 0x03, 0x32, 0x2B, 0x9D, 0xD5, 0xC7, 0xF8, 0x48, 0x90, 0x9A, 0xE7, 0x97, 0xF8, 0x4D, 0x10, ++0x41, 0xF0, 0x04, 0x01, 0x87, 0xF8, 0x4D, 0x10, 0x85, 0xE7, 0x03, 0x4E, 0x38, 0x46, 0x33, 0x6F, 0x98, 0x47, 0x72, 0xE7, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x4D, 0x4D, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x2B, 0xD9, 0x90, 0xF8, 0x4D, 0x20, 0x04, 0x46, 0xD0, 0x06, 0x0F, 0xD5, ++0x49, 0x4B, 0x03, 0xF1, 0x54, 0x00, 0x19, 0x7E, 0xFF, 0x29, 0x02, 0xD0, 0xD9, 0x7E, 0xFF, 0x29, 0x3B, 0xD1, 0x1C, 0x33, ++0x98, 0x42, 0xF6, 0xD1, 0x02, 0xF0, 0xEF, 0x02, 0x84, 0xF8, 0x4D, 0x20, 0x91, 0x07, 0x14, 0xD4, 0x53, 0x07, 0x6E, 0x6A, ++0x44, 0xBF, 0x22, 0xF0, 0x04, 0x02, 0x84, 0xF8, 0x4D, 0x20, 0x26, 0xB1, 0xF2, 0x68, 0x04, 0xF1, 0x44, 0x03, 0x9A, 0x42, ++0x09, 0xD0, 0x3B, 0x4B, 0x61, 0x6A, 0xDB, 0x6A, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xBD, 0xE8, ++0xF0, 0x81, 0xD4, 0xF8, 0x48, 0x80, 0x67, 0x6A, 0xA8, 0xEB, 0x07, 0x03, 0x00, 0x2B, 0x20, 0xDB, 0xA7, 0xEB, 0x08, 0x03, ++0x00, 0x2B, 0x29, 0xDB, 0x30, 0x4D, 0x6B, 0x6B, 0x98, 0x47, 0xEB, 0x6A, 0x61, 0x6A, 0x20, 0x46, 0x00, 0x22, 0x98, 0x47, ++0x2D, 0x4A, 0xD5, 0xF8, 0x84, 0x30, 0x11, 0x69, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x2A, 0x4A, ++0x27, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x20, 0xD3, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x20, ++0xBA, 0xE7, 0xE2, 0xF7, 0xA5, 0xFD, 0xA7, 0xF5, 0x7A, 0x67, 0xA7, 0xEB, 0x08, 0x07, 0x38, 0x1A, 0x00, 0x28, 0x0C, 0xDB, ++0x67, 0x6A, 0xD4, 0xF8, 0x48, 0x80, 0xD1, 0xE7, 0xE2, 0xF7, 0x98, 0xFD, 0xA8, 0xF5, 0x7A, 0x68, 0xA8, 0xEB, 0x07, 0x07, ++0x3F, 0x1A, 0x00, 0x2F, 0xCC, 0xDA, 0x67, 0x6A, 0xA7, 0x64, 0xE2, 0xF7, 0x8D, 0xFD, 0x73, 0x68, 0xFF, 0x1A, 0x3F, 0x1A, ++0xB7, 0xF5, 0x7A, 0x6F, 0xB5, 0xD5, 0xA4, 0x6C, 0xE2, 0xF7, 0x84, 0xFD, 0xAB, 0x6C, 0xA4, 0xF5, 0x7A, 0x64, 0x24, 0x1A, ++0xB3, 0x42, 0x74, 0x60, 0xAB, 0xD1, 0x0D, 0x4C, 0x0F, 0x48, 0xD4, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x0B, 0x4B, 0x71, 0x68, ++0x1B, 0x69, 0xAE, 0x64, 0xCB, 0x1A, 0x14, 0x2B, 0x05, 0xD4, 0xD4, 0xF8, 0xE0, 0x31, 0x09, 0x48, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x6B, 0x6C, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x18, 0x88, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x45, 0x4D, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x04, 0x46, 0x90, 0xF8, 0x4D, 0x30, 0x51, 0xD9, 0x9E, 0x06, 0x04, 0xD5, ++0x41, 0x4B, 0x9B, 0x6F, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x67, 0x6A, 0x13, 0xF0, 0x04, 0x06, 0x3D, 0xD1, 0x99, 0x07, ++0x42, 0xD5, 0x03, 0xF0, 0xFD, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x20, 0x01, 0x3A, 0xD2, 0xB2, 0x85, 0xF8, ++0x5B, 0x20, 0x4A, 0xB9, 0x95, 0xF8, 0x58, 0x20, 0x52, 0x06, 0x5B, 0xD5, 0x34, 0x4B, 0x28, 0x6D, 0xDB, 0x6D, 0x98, 0x47, ++0x94, 0xF8, 0x4D, 0x30, 0xD4, 0xF8, 0x48, 0x80, 0x13, 0xF0, 0x08, 0x02, 0x42, 0xD0, 0x94, 0xF8, 0x62, 0x20, 0x23, 0xF0, ++0x08, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x00, 0x2A, 0x4A, 0xD0, 0x02, 0x2A, 0x0A, 0xBF, 0xB4, 0xF8, 0xD2, 0x30, 0x4F, 0xF4, ++0xC8, 0x33, 0x9B, 0x02, 0xA8, 0xEB, 0x03, 0x08, 0xB6, 0xB1, 0xEB, 0x6A, 0x26, 0x4A, 0x15, 0x69, 0x93, 0xB9, 0x24, 0x4E, ++0x73, 0x6B, 0x98, 0x47, 0xD6, 0xF8, 0x84, 0x30, 0xA5, 0xEB, 0x08, 0x02, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x13, 0xF0, 0x01, 0x02, 0x23, 0xD0, 0x23, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0xBD, 0xE8, 0xF0, 0x81, ++0x9A, 0x07, 0xFB, 0xD5, 0x23, 0xF0, 0x02, 0x03, 0x80, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, 0x01, 0x3B, 0xDB, 0xB2, ++0x85, 0xF8, 0x5B, 0x30, 0x00, 0x2B, 0xEF, 0xD1, 0x95, 0xF8, 0x58, 0x30, 0x5F, 0x06, 0xEB, 0xD5, 0x10, 0x4B, 0x28, 0x6D, ++0xDB, 0x6D, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x0D, 0x4B, 0x39, 0x46, 0xDB, 0x6A, 0x20, 0x46, 0x98, 0x47, 0xC7, 0xE7, ++0x0A, 0x4B, 0x39, 0x46, 0xDB, 0x6A, 0x20, 0x46, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0xD3, 0xE7, 0x01, 0x26, 0xA7, 0xE7, ++0x07, 0x4A, 0x94, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x9B, 0x68, 0xB2, 0xE7, 0x00, 0xBF, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0x28, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x6C, 0x05, 0x46, 0x3E, 0xDB, 0x24, 0x4E, 0x96, 0xF8, ++0x58, 0x20, 0x12, 0xF0, 0x20, 0x04, 0x03, 0xD1, 0x96, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x01, 0xD8, 0xBD, 0xE8, 0xF0, 0x81, ++0x14, 0x23, 0x22, 0x46, 0x21, 0x46, 0x46, 0x20, 0x95, 0xF8, 0x6C, 0x80, 0x04, 0xF0, 0x2E, 0xF8, 0x04, 0x70, 0x95, 0xF8, ++0x63, 0x10, 0x41, 0x70, 0x39, 0x79, 0x19, 0x4A, 0x81, 0x70, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x08, 0x28, 0x7A, 0x79, ++0xC2, 0x70, 0xD8, 0xF8, 0x08, 0x20, 0x15, 0x4D, 0xB7, 0xF8, 0x06, 0xC0, 0x3C, 0x89, 0x79, 0x89, 0x01, 0x81, 0xA2, 0xF5, ++0x9C, 0x52, 0x08, 0x3A, 0xA5, 0xFB, 0x02, 0x52, 0x92, 0x09, 0xA0, 0xF8, 0x04, 0xC0, 0xC4, 0x80, 0xC2, 0x60, 0x3A, 0x7B, ++0x02, 0x74, 0x04, 0xF0, 0x3B, 0xF8, 0x96, 0xF8, 0x58, 0x30, 0x43, 0xF0, 0x20, 0x03, 0x86, 0xF8, 0x58, 0x30, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0x2F, 0xBE, 0xD1, 0x07, 0x49, 0x07, 0x48, 0x40, 0xF6, 0x71, 0x52, 0x06, 0xF0, 0xDD, 0xF8, 0xB7, 0xE7, ++0x38, 0x36, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xD3, 0x4D, 0x62, 0x10, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0xA0, 0x15, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x0A, 0x4B, 0x9B, 0x6A, 0x83, 0xB1, 0x1A, 0x7E, 0x02, 0x2A, 0x05, 0xD8, ++0x00, 0x6C, 0xC0, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x9B, 0x7E, 0x90, 0xF8, 0x63, 0x00, 0x18, 0x1A, ++0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x18, 0x46, 0x70, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x10, 0x4A, 0x93, 0x6A, ++0xDB, 0xB1, 0x19, 0x7E, 0x02, 0x29, 0x0E, 0xD8, 0x00, 0x6C, 0xC0, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x88, 0xB1, ++0xD2, 0x6A, 0x7A, 0xB1, 0x18, 0x7C, 0xA0, 0xF1, 0x06, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x90, 0xF8, ++0x63, 0x10, 0x98, 0x7E, 0x40, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x00, 0x28, 0xED, 0xD1, 0x70, 0x47, 0x18, 0x46, ++0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x0E, 0x4B, 0x9B, 0x6A, 0x23, 0xB1, 0x02, 0x6C, 0x98, 0x88, 0x91, 0x88, ++0x88, 0x42, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x58, 0x7B, 0x51, 0x7B, 0x88, 0x42, 0xF9, 0xD1, 0xD8, 0x88, 0xD1, 0x88, ++0x88, 0x42, 0xF5, 0xD1, 0x18, 0x89, 0x11, 0x89, 0x88, 0x42, 0xF1, 0xD1, 0x5B, 0x89, 0x50, 0x89, 0x18, 0x1A, 0xB0, 0xFA, ++0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x43, 0x7E, 0xDB, 0xB1, 0x0E, 0x4B, 0x30, 0xB4, ++0x7F, 0x21, 0x03, 0xF5, 0xA4, 0x54, 0x1A, 0x6C, 0x82, 0x42, 0x08, 0xD0, 0x03, 0xF5, 0xA4, 0x63, 0xA3, 0x42, 0xF8, 0xD1, ++0x7F, 0x29, 0x30, 0xBC, 0x18, 0xBF, 0x01, 0x73, 0x70, 0x47, 0x93, 0xF9, 0x66, 0x20, 0x93, 0xF9, 0x65, 0x50, 0xAA, 0x42, ++0xA8, 0xBF, 0x2A, 0x46, 0x91, 0x42, 0xA8, 0xBF, 0x11, 0x46, 0xEB, 0xE7, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x70, 0xB5, 0x11, 0x4E, 0x11, 0x4A, 0xD6, 0xF8, 0x4C, 0x32, 0x04, 0x46, 0x98, 0x47, 0xD0, 0xB1, 0x0F, 0x4B, 0x10, 0x4D, ++0x5B, 0x78, 0x00, 0x22, 0x2A, 0x77, 0x23, 0xB1, 0x0E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x2B, 0x7A, ++0x0B, 0xB1, 0x01, 0x3B, 0x2B, 0x72, 0xD6, 0xF8, 0xD8, 0x31, 0x0A, 0x48, 0x98, 0x47, 0x00, 0x23, 0x6B, 0x77, 0x63, 0x68, ++0x23, 0xF4, 0x01, 0x73, 0x23, 0xF0, 0x02, 0x03, 0x63, 0x60, 0x70, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xDD, 0xEA, 0x13, 0x00, ++0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x70, 0xB5, 0x14, 0x4D, ++0x14, 0x4A, 0xD5, 0xF8, 0x4C, 0x32, 0x04, 0x46, 0x98, 0x47, 0xF8, 0xB1, 0x12, 0x4A, 0x13, 0x4B, 0x52, 0x78, 0x01, 0x21, ++0x19, 0x77, 0x22, 0xB1, 0x11, 0x49, 0x0A, 0x68, 0x22, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x1A, 0x7A, 0x0A, 0xB1, 0x01, 0x3A, ++0x1A, 0x72, 0x0E, 0x4A, 0x0E, 0x49, 0x12, 0x68, 0x09, 0x69, 0xD0, 0x8E, 0x5C, 0x61, 0x04, 0x26, 0x5E, 0x77, 0x01, 0x44, ++0xD5, 0xF8, 0xE0, 0x21, 0x0A, 0x48, 0x90, 0x47, 0x63, 0x68, 0x43, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x70, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x3D, 0xEB, 0x13, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, ++0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4A, 0x0B, 0x46, 0x0C, 0x46, ++0x05, 0x46, 0x0F, 0x49, 0x02, 0x20, 0x05, 0xF0, 0xB3, 0xFD, 0x0E, 0x4B, 0x0E, 0x4A, 0xD3, 0xF8, 0x4C, 0x32, 0x21, 0x46, ++0x28, 0x46, 0x98, 0x47, 0x30, 0xB1, 0x0C, 0x4A, 0x13, 0x7A, 0x23, 0xB1, 0x01, 0x3B, 0xDB, 0xB2, 0x13, 0x72, 0x03, 0xB1, ++0x38, 0xBD, 0x01, 0x23, 0x13, 0x70, 0x51, 0x88, 0xBD, 0xE8, 0x38, 0x40, 0x00, 0x22, 0x32, 0x20, 0x03, 0xF0, 0x4A, 0xBF, ++0x68, 0xA3, 0x15, 0x00, 0x44, 0xA3, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xB1, 0xEB, 0x13, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x38, 0xB5, 0x18, 0x4A, 0x0B, 0x46, 0x0C, 0x46, 0x05, 0x46, 0x17, 0x49, 0x02, 0x20, 0x05, 0xF0, 0x87, 0xFD, 0x16, 0x4B, ++0x16, 0x4A, 0xD3, 0xF8, 0x4C, 0x32, 0x21, 0x46, 0x28, 0x46, 0x98, 0x47, 0xF8, 0xB1, 0x14, 0x48, 0x03, 0x7A, 0xBB, 0xB9, ++0x13, 0x4B, 0x9B, 0x68, 0x63, 0xB1, 0x93, 0xF8, 0x62, 0x20, 0x32, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x1A, 0xB1, 0x5A, 0x68, ++0x22, 0xF0, 0x0E, 0x02, 0x5A, 0x60, 0x1B, 0x68, 0x00, 0x2B, 0xF2, 0xD1, 0x00, 0x22, 0x02, 0x70, 0x41, 0x88, 0xBD, 0xE8, ++0x38, 0x40, 0x32, 0x20, 0x03, 0xF0, 0x14, 0xBF, 0x01, 0x3B, 0xDB, 0xB2, 0x03, 0x72, 0x00, 0x2B, 0xE2, 0xD0, 0x38, 0xBD, ++0x78, 0xA3, 0x15, 0x00, 0x44, 0xA3, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x09, 0xEC, 0x13, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x38, 0xB5, 0x11, 0xF4, 0x00, 0x03, 0x04, 0x46, 0x2A, 0xD1, 0x90, 0xF8, 0x6B, 0x00, 0x25, 0x49, ++0x01, 0x30, 0xC0, 0xB2, 0x09, 0x68, 0x84, 0xF8, 0x6B, 0x00, 0x49, 0x78, 0x81, 0x42, 0x29, 0xD0, 0x94, 0xF8, 0x64, 0x50, ++0x00, 0x2D, 0x34, 0xD1, 0x1F, 0x4A, 0x20, 0x4B, 0x52, 0x78, 0x01, 0x21, 0x19, 0x77, 0x22, 0xB1, 0x1E, 0x49, 0x0A, 0x68, ++0x22, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x1A, 0x7A, 0x0A, 0xB1, 0x01, 0x3A, 0x1A, 0x72, 0x1B, 0x4A, 0x1B, 0x48, 0xD2, 0xF8, ++0xD8, 0x21, 0x00, 0x21, 0x59, 0x77, 0x90, 0x47, 0x63, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x28, 0x46, 0x38, 0xBD, ++0x28, 0xB1, 0x00, 0x23, 0x01, 0x25, 0x80, 0xF8, 0x6B, 0x30, 0x28, 0x46, 0x38, 0xBD, 0x01, 0x25, 0x28, 0x46, 0x38, 0xBD, ++0x11, 0x49, 0x84, 0xF8, 0x6B, 0x30, 0x4F, 0xF4, 0x80, 0x60, 0x05, 0xF0, 0x11, 0xFD, 0x0C, 0x4B, 0x20, 0x46, 0xD3, 0xF8, ++0xBC, 0x31, 0x01, 0x25, 0x98, 0x47, 0x28, 0x46, 0x38, 0xBD, 0x11, 0x46, 0x1D, 0x46, 0x94, 0xF8, 0x6C, 0x00, 0x22, 0x46, ++0xF1, 0xF7, 0xD0, 0xF9, 0x28, 0x46, 0x38, 0xBD, 0xC8, 0x35, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x34, 0x04, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x28, 0x9E, 0x17, 0x00, 0x4C, 0xA3, 0x15, 0x00, 0x70, 0xB5, 0x13, 0x4D, ++0x2B, 0x78, 0x13, 0xB3, 0x2B, 0x7F, 0x03, 0xB3, 0x11, 0x4A, 0x12, 0x49, 0x13, 0x68, 0x8C, 0x68, 0x43, 0xF0, 0x04, 0x03, ++0x00, 0x21, 0x13, 0x60, 0x29, 0x72, 0xB4, 0xB1, 0x0E, 0x4E, 0x94, 0xF8, 0x62, 0x30, 0x7B, 0xB9, 0x94, 0xF8, 0x64, 0x30, ++0x63, 0xB1, 0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x22, 0x46, 0x07, 0xD0, 0xD6, 0xF8, 0x34, 0x12, 0xF1, 0xF7, 0xA0, 0xF9, ++0x10, 0xB9, 0x2B, 0x7A, 0x01, 0x33, 0x2B, 0x72, 0x24, 0x68, 0x00, 0x2C, 0xE9, 0xD1, 0x70, 0xBD, 0x1C, 0x9E, 0x17, 0x00, ++0x4C, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x12, 0x4D, 0x2B, 0x7F, 0xFB, 0xB9, ++0x11, 0x49, 0x12, 0x48, 0x0A, 0x68, 0x84, 0x68, 0x2B, 0x72, 0x22, 0xF0, 0x04, 0x02, 0x0A, 0x60, 0xB4, 0xB1, 0x0F, 0x4E, ++0x94, 0xF8, 0x62, 0x30, 0x7B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x63, 0xB1, 0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x22, 0x46, ++0x07, 0xD0, 0xD6, 0xF8, 0x58, 0x12, 0xF1, 0xF7, 0x73, 0xF9, 0x10, 0xB9, 0x2B, 0x7A, 0x01, 0x33, 0x2B, 0x72, 0x24, 0x68, ++0x00, 0x2C, 0xE9, 0xD1, 0x70, 0xBD, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x2E, 0x4B, 0x2E, 0x4D, 0x1B, 0x68, 0x2E, 0x4A, 0x1B, 0x78, 0xD2, 0xF8, 0xF8, 0x21, ++0x01, 0x2B, 0x6B, 0x68, 0x04, 0x46, 0x03, 0xF0, 0x20, 0x03, 0x44, 0xD0, 0x13, 0x43, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, ++0x94, 0xF8, 0xAC, 0x30, 0x53, 0xB1, 0x27, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x13, 0xB1, 0x94, 0xF8, 0x64, 0x30, 0x33, 0xBB, ++0x00, 0x23, 0x6B, 0x77, 0x63, 0x60, 0x70, 0xBD, 0x21, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0xF6, 0xD0, 0x94, 0xF8, ++0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, 0xC0, 0xB1, 0x1D, 0x4B, 0x1A, 0x68, 0x92, 0x01, 0x05, 0xD4, 0x1B, 0x68, 0x9B, 0x01, ++0x11, 0xD4, 0x95, 0xF8, 0x24, 0x30, 0x73, 0xB1, 0x6B, 0x7F, 0x05, 0x2B, 0x05, 0xD1, 0x63, 0x68, 0x00, 0x22, 0x23, 0xF0, ++0x02, 0x03, 0x63, 0x60, 0x6A, 0x77, 0x15, 0x4B, 0xBD, 0xE8, 0x70, 0x40, 0xD3, 0xF8, 0x50, 0x32, 0x18, 0x47, 0x13, 0x4B, ++0x13, 0x4A, 0x19, 0x68, 0x10, 0x4B, 0xC9, 0x8E, 0x6C, 0x61, 0x01, 0x20, 0x68, 0x77, 0x12, 0x69, 0xD3, 0xF8, 0xE0, 0x31, ++0x0F, 0x48, 0xBD, 0xE8, 0x70, 0x40, 0x11, 0x44, 0x18, 0x47, 0x13, 0x43, 0x01, 0xD0, 0x00, 0x20, 0xBA, 0xE7, 0xE9, 0xF7, ++0x37, 0xFD, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0xB4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0x28, 0x22, 0x20, 0x46, 0x00, 0x21, 0xE1, 0xF7, ++0x5F, 0xF9, 0x04, 0x4A, 0x01, 0x23, 0xD2, 0xF8, 0x38, 0x22, 0x22, 0x61, 0x23, 0x77, 0x10, 0xBD, 0x1C, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x4C, 0x23, 0x78, 0x33, 0xB9, 0x0B, 0x4B, 0xD3, 0xF8, 0xF8, 0x31, 0x98, 0x47, ++0x08, 0xB9, 0x00, 0x20, 0x10, 0xBD, 0x63, 0x68, 0x00, 0x2B, 0xFA, 0xD1, 0x07, 0x4B, 0x9B, 0x68, 0x13, 0xB9, 0x05, 0xE0, ++0x1B, 0x68, 0x1B, 0xB1, 0x5A, 0x68, 0x00, 0x2A, 0xFA, 0xD0, 0xF0, 0xE7, 0x01, 0x20, 0x10, 0xBD, 0x1C, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x08, 0x4B, 0x09, 0x4A, 0x1B, 0x68, 0x51, 0x80, 0x1B, 0x78, 0x02, 0x2B, ++0x07, 0x4B, 0x03, 0xD0, 0x07, 0x49, 0x00, 0x28, 0x18, 0xBF, 0x0B, 0x46, 0x00, 0x20, 0x10, 0x72, 0x4F, 0xF4, 0x00, 0x01, ++0x18, 0x47, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x09, 0xEC, 0x13, 0x00, 0xB1, 0xEB, 0x13, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x92, 0xF8, 0x6C, 0x30, 0x42, 0x4C, 0x43, 0x4E, 0x51, 0x68, 0x4F, 0xF4, 0x1E, 0x75, 0x91, 0x46, ++0x05, 0xFB, 0x03, 0x43, 0x32, 0x78, 0x1D, 0x8C, 0x21, 0xF0, 0x01, 0x07, 0xC9, 0xF8, 0x04, 0x70, 0x00, 0x2A, 0x49, 0xD0, ++0x04, 0x46, 0x00, 0x28, 0x46, 0xD0, 0x99, 0xF8, 0x6A, 0x30, 0x00, 0x2B, 0x44, 0xD0, 0x00, 0xF1, 0x04, 0x08, 0x98, 0xF8, ++0x00, 0x30, 0x03, 0xF0, 0xFE, 0x03, 0xB3, 0xEB, 0xD5, 0x0F, 0x4F, 0xEA, 0xD5, 0x00, 0x31, 0xD8, 0x61, 0x78, 0x04, 0x39, ++0x19, 0x44, 0x88, 0x42, 0x2C, 0xD8, 0x20, 0x44, 0xC3, 0x1A, 0x05, 0xF0, 0x07, 0x05, 0x59, 0x79, 0x01, 0x23, 0x03, 0xFA, ++0x05, 0xF5, 0x29, 0x42, 0x22, 0xD0, 0x2C, 0x4B, 0x19, 0x68, 0x8A, 0x05, 0x03, 0xD5, 0x19, 0x68, 0x21, 0xF4, 0x00, 0x71, ++0x19, 0x60, 0x29, 0x4C, 0xD4, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x28, 0x48, 0xD9, 0xF8, 0x04, 0x30, 0x00, 0x68, 0x27, 0x49, ++0xD4, 0xF8, 0xE0, 0x41, 0x40, 0x8F, 0x43, 0xF0, 0x04, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0x09, 0x69, 0xC6, 0xF8, 0x14, 0x90, ++0x06, 0x23, 0x73, 0x77, 0x01, 0x44, 0x23, 0x46, 0x20, 0x48, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0xD9, 0xF8, 0x04, 0x30, ++0x23, 0xF0, 0x04, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0xBD, 0xE8, 0xF0, 0x87, 0x03, 0x79, 0x00, 0xF1, 0x04, 0x08, 0xD8, 0x07, ++0x1E, 0xD5, 0x14, 0x4B, 0x47, 0xF0, 0x02, 0x07, 0xC9, 0xF8, 0x04, 0x70, 0x19, 0x68, 0x89, 0x05, 0x03, 0xD5, 0x19, 0x68, ++0x21, 0xF4, 0x00, 0x71, 0x19, 0x60, 0x73, 0x7F, 0x00, 0x2B, 0xA8, 0xD1, 0x0E, 0x4B, 0x0F, 0x49, 0x1B, 0x68, 0x09, 0x69, ++0x1F, 0x8F, 0x0B, 0x4B, 0xC6, 0xF8, 0x14, 0x90, 0x05, 0x20, 0x70, 0x77, 0xD3, 0xF8, 0xE0, 0x31, 0x0A, 0x48, 0x39, 0x44, ++0x98, 0x47, 0x98, 0xE7, 0x21, 0xF0, 0x03, 0x01, 0xC9, 0xF8, 0x04, 0x10, 0x93, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x28, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x21, 0x4E, 0x14, 0x46, 0x52, 0x68, 0x35, 0x78, 0x22, 0xF0, 0x01, 0x03, ++0x63, 0x60, 0x00, 0x2D, 0x32, 0xD0, 0x0F, 0x46, 0x94, 0xF8, 0x6A, 0x10, 0xA1, 0xB9, 0x00, 0x28, 0x2E, 0xD0, 0x1B, 0x4A, ++0x1B, 0x49, 0x10, 0x68, 0x1B, 0x4A, 0x00, 0x8F, 0xD2, 0xF8, 0xE0, 0x21, 0x43, 0xF0, 0x02, 0x03, 0x63, 0x60, 0x09, 0x69, ++0x74, 0x61, 0x05, 0x23, 0x01, 0x44, 0x73, 0x77, 0x06, 0xF1, 0x0C, 0x00, 0x90, 0x47, 0x63, 0x68, 0xAF, 0xB1, 0x13, 0x4D, ++0x43, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xD5, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x0D, 0x4B, 0x0E, 0x4A, 0x1B, 0x68, 0x11, 0x69, ++0x58, 0x8F, 0x74, 0x61, 0x06, 0x22, 0xD5, 0xF8, 0xE0, 0x31, 0x72, 0x77, 0x01, 0x44, 0xBD, 0xE8, 0xF0, 0x41, 0x0A, 0x48, ++0x18, 0x47, 0x23, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x22, 0xF0, 0x03, 0x03, 0x00, 0x2F, 0xF6, 0xD0, ++0xDF, 0xE7, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x28, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x21, 0x4D, 0x2B, 0x78, 0xAB, 0xB1, 0x03, 0x79, 0x06, 0x88, 0xDF, 0x07, ++0x14, 0x46, 0x12, 0xD5, 0x6B, 0x7F, 0x05, 0x2B, 0x07, 0xD1, 0x1D, 0x4B, 0x05, 0xF1, 0x0C, 0x00, 0xD3, 0xF8, 0xD8, 0x31, ++0x98, 0x47, 0x00, 0x23, 0x6B, 0x77, 0xB5, 0x04, 0x23, 0xD4, 0x63, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x63, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0x88, 0x05, 0xFB, 0xD4, 0x15, 0x4A, 0x15, 0x4B, 0x12, 0x68, 0x1B, 0x69, 0xD1, 0x8E, 0x11, 0x4F, 0x6C, 0x61, ++0x02, 0x22, 0x19, 0x44, 0x6A, 0x77, 0xD7, 0xF8, 0xE0, 0x31, 0x05, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0xB1, 0x04, 0x63, 0x68, ++0x0E, 0xD5, 0x5A, 0x07, 0x5C, 0xBF, 0x43, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xD7, 0xF8, 0x54, 0x32, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x94, 0xF8, 0x6A, 0x30, 0x00, 0x2B, 0xDB, 0xD0, 0xD6, 0xE7, 0x23, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x38, 0xB5, 0x23, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x3F, 0xD0, 0xFF, 0x28, 0x3D, 0xD0, 0xFF, 0x29, 0x3B, 0xD0, 0x20, 0x4A, ++0x20, 0x49, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x20, 0x4F, 0xF4, 0xA4, 0x64, 0x90, 0xF8, 0x22, 0x20, 0x04, 0xFB, ++0x02, 0x12, 0x92, 0xF8, 0x62, 0x10, 0x00, 0x29, 0x2B, 0xD1, 0x92, 0xF8, 0x64, 0x10, 0x41, 0xB3, 0x18, 0x48, 0x19, 0x49, ++0x00, 0x68, 0x09, 0x69, 0xC5, 0x8E, 0x18, 0x4C, 0x5A, 0x61, 0x03, 0x20, 0x58, 0x77, 0xD4, 0xF8, 0xE0, 0x21, 0x03, 0xF1, ++0x0C, 0x00, 0x29, 0x44, 0x90, 0x47, 0x14, 0x4B, 0x1B, 0x68, 0x5B, 0x07, 0x15, 0xD5, 0x13, 0x4B, 0x93, 0xF8, 0xB6, 0x30, ++0x73, 0xB1, 0x12, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x09, 0xD1, 0x10, 0x49, 0x11, 0x4A, 0x0B, 0x68, 0x23, 0xF4, ++0x00, 0x73, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0xD4, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x00, 0x20, ++0x38, 0xBD, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, ++0x90, 0xB3, 0x33, 0x40, 0x8C, 0x00, 0x32, 0x40, 0x3B, 0x4A, 0xDF, 0xF8, 0x1C, 0xC1, 0x13, 0x68, 0x3A, 0x49, 0xF0, 0xB5, ++0x3A, 0x4F, 0x3B, 0x4C, 0xB7, 0xF8, 0xB2, 0x00, 0x3A, 0x4D, 0x3B, 0x4E, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x23, 0x68, ++0x39, 0x4A, 0x43, 0xF0, 0x80, 0x53, 0x23, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x70, 0x23, 0xCC, 0xF8, 0x00, 0x30, ++0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0x10, 0x03, 0xCC, 0xF8, 0x00, 0x30, 0x2B, 0x68, 0x23, 0xF0, ++0xFC, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x0B, 0x68, 0x40, 0x09, 0x00, 0xF1, 0x20, 0x0C, 0xC3, 0xF3, 0x15, 0x03, ++0x43, 0xEA, 0x8C, 0x53, 0x0B, 0x60, 0x83, 0xB0, 0x33, 0x68, 0x29, 0x49, 0x1B, 0x78, 0xCD, 0xF8, 0x00, 0xC0, 0x02, 0x20, ++0x05, 0xF0, 0x0A, 0xFA, 0x32, 0x68, 0x13, 0x78, 0x01, 0x2B, 0x15, 0xD0, 0x02, 0x2B, 0x11, 0xD1, 0x23, 0x48, 0x24, 0x49, ++0x03, 0x68, 0x24, 0x4C, 0x1D, 0x4A, 0x43, 0xF4, 0x80, 0x33, 0x03, 0x60, 0x0B, 0x68, 0x3F, 0x20, 0x23, 0xF0, 0x00, 0x73, ++0x0B, 0x60, 0x20, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x03, 0xB0, 0xF0, 0xBD, 0x97, 0xF8, 0xB5, 0x10, ++0x69, 0xB1, 0x19, 0x49, 0x19, 0x48, 0x0B, 0x68, 0x23, 0xF0, 0x00, 0x73, 0x0B, 0x60, 0x2B, 0x68, 0x24, 0x21, 0x43, 0xF4, ++0x00, 0x13, 0x2B, 0x60, 0x01, 0x60, 0x13, 0x78, 0xD8, 0xE7, 0x12, 0x48, 0x12, 0x4E, 0x01, 0x68, 0x12, 0x4D, 0x41, 0xF0, ++0x00, 0x71, 0x01, 0x60, 0x04, 0x21, 0x31, 0x60, 0x2B, 0x60, 0x23, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, ++0x23, 0x60, 0x13, 0x78, 0xC6, 0xE7, 0x00, 0xBF, 0x90, 0x00, 0x32, 0x40, 0xF0, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0x74, 0x80, 0x32, 0x40, 0x6C, 0x00, 0x32, 0x40, 0x74, 0x36, 0x17, 0x00, 0x88, 0xA3, 0x15, 0x00, 0x5C, 0xA3, 0x15, 0x00, ++0x44, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x78, 0x00, 0x32, 0x40, ++0x15, 0x48, 0x16, 0x4A, 0x16, 0x49, 0x38, 0xB5, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x02, 0x20, 0x05, 0xF0, ++0xA7, 0xF9, 0x13, 0x4B, 0x9B, 0x7C, 0x23, 0xB9, 0x12, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x11, 0x4C, ++0x11, 0x48, 0x23, 0x68, 0x0E, 0x49, 0x11, 0x4D, 0x11, 0x4A, 0x23, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF0, ++0x80, 0x43, 0x03, 0x60, 0x0B, 0x68, 0x00, 0x20, 0x23, 0xF0, 0x80, 0x53, 0x0B, 0x60, 0x28, 0x60, 0x13, 0x68, 0x23, 0xF0, ++0x01, 0x03, 0x13, 0x60, 0x38, 0xBD, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x98, 0xA3, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x44, 0x00, 0x32, 0x40, 0x90, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x70, 0xB5, 0x90, 0xF8, 0x72, 0x30, 0x01, 0x2B, 0x04, 0x46, 0x11, 0xD0, 0x02, 0x2B, 0x00, 0xD0, ++0x70, 0xBD, 0x0C, 0x4D, 0x41, 0x6F, 0x01, 0x23, 0x80, 0xF8, 0x72, 0x30, 0xD5, 0xF8, 0xE0, 0x31, 0x60, 0x30, 0x98, 0x47, ++0xD5, 0xF8, 0x18, 0x32, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x04, 0x4B, 0x00, 0x22, 0x80, 0xF8, 0x72, 0x20, ++0xBD, 0xE8, 0x70, 0x40, 0xD3, 0xF8, 0x18, 0x32, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x4F, 0xF0, 0x00, 0x0C, 0x4F, 0xF0, 0x01, 0x0E, 0x83, 0xB0, 0x06, 0x46, 0x04, 0x46, 0x00, 0xF1, 0x60, 0x05, 0x03, 0x46, ++0x67, 0x46, 0x71, 0x46, 0x1A, 0x7C, 0x02, 0x2A, 0x13, 0xD1, 0xDA, 0x7C, 0x01, 0x2A, 0x10, 0xD8, 0x96, 0xF8, 0x87, 0x20, ++0x32, 0xB1, 0x93, 0xF8, 0x21, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x20, 0x01, 0x2A, 0x06, 0xD0, 0xDA, 0x68, 0x00, 0x29, ++0x00, 0xF0, 0xC0, 0x80, 0x01, 0x37, 0x94, 0x46, 0x00, 0x21, 0x30, 0x33, 0x9D, 0x42, 0xE5, 0xD1, 0x01, 0x22, 0x8E, 0x46, ++0x33, 0x46, 0x4F, 0xF0, 0x00, 0x09, 0x00, 0x92, 0xA0, 0x46, 0x1A, 0x7C, 0x02, 0x2A, 0x1D, 0xD1, 0xD9, 0x7C, 0x01, 0x29, ++0x1A, 0xD9, 0x96, 0xF8, 0x87, 0x20, 0x32, 0xB1, 0x93, 0xF8, 0x21, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x20, 0x01, 0x2A, ++0x10, 0xD0, 0xD3, 0xE9, 0x06, 0x04, 0xDA, 0x68, 0x04, 0xEB, 0x02, 0x0A, 0xAA, 0xEB, 0x00, 0x00, 0xBE, 0xF1, 0x00, 0x0F, ++0x42, 0xD0, 0x00, 0x21, 0x00, 0x91, 0x01, 0x37, 0x81, 0x46, 0x94, 0x46, 0x4F, 0xF0, 0x00, 0x0E, 0x30, 0x33, 0x9D, 0x42, ++0xDB, 0xD1, 0x01, 0x96, 0x44, 0x46, 0x00, 0x9E, 0x18, 0xE0, 0x00, 0x2F, 0x5F, 0xD1, 0xA1, 0xEB, 0x09, 0x02, 0x00, 0x2A, ++0x58, 0xDB, 0xAC, 0xEB, 0x03, 0x02, 0x00, 0x2A, 0x0B, 0xDB, 0xA3, 0xEB, 0x09, 0x00, 0xAC, 0xEB, 0x01, 0x02, 0x39, 0xEA, ++0x20, 0x09, 0x28, 0xBF, 0x99, 0x46, 0x3C, 0xEA, 0x22, 0x0C, 0x28, 0xBF, 0x8C, 0x46, 0x30, 0x34, 0xA5, 0x42, 0x0F, 0xD0, ++0x23, 0x7C, 0x01, 0x2B, 0xF9, 0xD1, 0xE3, 0x68, 0xA1, 0x69, 0x19, 0x44, 0xBE, 0xF1, 0x00, 0x0F, 0xDD, 0xD0, 0x30, 0x34, ++0x00, 0x26, 0xA5, 0x42, 0x99, 0x46, 0x8C, 0x46, 0xB6, 0x46, 0xEF, 0xD1, 0x33, 0x46, 0x01, 0x9E, 0xC6, 0xF8, 0x80, 0xC0, ++0x0B, 0xB1, 0x0C, 0xF1, 0x0A, 0x09, 0xC6, 0xF8, 0x7C, 0x90, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA0, 0xEB, 0x0C, 0x0A, ++0xBA, 0xF1, 0x00, 0x0F, 0x80, 0xF2, 0x88, 0x80, 0xA4, 0xEB, 0x02, 0x0B, 0x02, 0xEB, 0x0C, 0x0A, 0x01, 0x39, 0x83, 0x44, ++0xA0, 0xEB, 0x0A, 0x0A, 0x01, 0xE0, 0x01, 0x39, 0xB2, 0xD0, 0x0B, 0xEB, 0x02, 0x00, 0x22, 0x44, 0x1A, 0xEB, 0x02, 0x0F, ++0xF7, 0xD4, 0xAC, 0xEB, 0x02, 0x04, 0x3C, 0xEA, 0x24, 0x0C, 0x28, 0xBF, 0x94, 0x46, 0x01, 0x29, 0x3D, 0xD0, 0x62, 0x46, ++0x00, 0x99, 0x00, 0x29, 0x99, 0xD1, 0xA0, 0xEB, 0x09, 0x01, 0x10, 0xEA, 0x21, 0x00, 0x38, 0xBF, 0x48, 0x46, 0x94, 0xE7, ++0x99, 0x46, 0x8C, 0x46, 0xB3, 0xE7, 0xA1, 0xEB, 0x0C, 0x02, 0x00, 0x2A, 0x94, 0xF8, 0x13, 0x80, 0x61, 0xDA, 0x08, 0xF1, ++0xFF, 0x30, 0xB8, 0xF1, 0x00, 0x0F, 0xA8, 0xD0, 0xD4, 0xF8, 0x1C, 0xB0, 0x9A, 0x46, 0x03, 0xE0, 0x42, 0x1E, 0x00, 0x28, ++0xA1, 0xD0, 0x10, 0x46, 0xDA, 0x44, 0x01, 0xEB, 0x0A, 0x08, 0xA8, 0xEB, 0x0C, 0x02, 0xD2, 0x1A, 0x00, 0x2A, 0xA8, 0xEB, ++0x03, 0x08, 0xF1, 0xDB, 0xA6, 0xB1, 0xAC, 0xEB, 0x0A, 0x03, 0x00, 0x2B, 0x29, 0xDB, 0x58, 0xB3, 0xE3, 0x69, 0xC4, 0x46, ++0x0A, 0xEB, 0x03, 0x09, 0x00, 0x26, 0x8A, 0xE7, 0xAC, 0xEB, 0x02, 0x01, 0x12, 0xEA, 0x21, 0x02, 0x38, 0xBF, 0x62, 0x46, ++0x38, 0xE7, 0x48, 0x46, 0x62, 0x46, 0x5E, 0xE7, 0xA9, 0xEB, 0x0A, 0x03, 0x00, 0x2B, 0x11, 0xDB, 0xAC, 0xEB, 0x0A, 0x03, ++0x00, 0x2B, 0x15, 0xDB, 0xA8, 0xEB, 0x09, 0x03, 0x00, 0x2B, 0x14, 0xDB, 0x1B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x29, 0xDB, 0xE3, 0x69, 0xC4, 0x46, 0x0A, 0xEB, 0x03, 0x09, 0x4F, 0xF0, 0x00, 0x0E, 0x67, 0xE7, 0xD1, 0x46, ++0x00, 0x26, 0x64, 0xE7, 0xC4, 0x46, 0x62, 0xE7, 0xD1, 0x46, 0xB6, 0x46, 0x5F, 0xE7, 0x01, 0x28, 0x15, 0xDD, 0xE3, 0x69, ++0x9A, 0x44, 0xAA, 0xEB, 0x09, 0x03, 0xC4, 0x46, 0x39, 0xEA, 0x23, 0x09, 0x28, 0xBF, 0xD1, 0x46, 0xB6, 0x46, 0x52, 0xE7, ++0xAC, 0xEB, 0x02, 0x01, 0x12, 0xEA, 0x21, 0x02, 0x38, 0xBF, 0x62, 0x46, 0x8A, 0xE7, 0x40, 0x46, 0x9A, 0x46, 0x88, 0x46, ++0xB0, 0xE7, 0xC4, 0x46, 0xB6, 0x46, 0x44, 0xE7, 0x04, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x4D, 0x12, 0x05, 0xF0, 0x64, 0xFA, ++0xCE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x03, 0x7C, 0x02, 0x2B, 0x83, 0xB0, 0x04, 0x46, 0x69, 0xD0, 0x90, 0xF8, 0x40, 0x30, 0x02, 0x2B, 0x54, 0xD0, 0x94, 0xF8, ++0x73, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x18, 0xD1, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x40, 0xF0, 0xD2, 0x80, 0x94, 0xF8, ++0x70, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xB8, 0x80, 0xDF, 0xF8, 0x24, 0x93, 0xC3, 0x4B, 0x94, 0xF8, 0x71, 0x20, 0xD3, 0xF8, ++0x5C, 0x34, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x90, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x94, 0xF8, ++0x72, 0x30, 0x01, 0x2B, 0x00, 0xF0, 0x54, 0x81, 0x94, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x00, 0xF0, 0xB9, 0x81, 0xB9, 0x4A, ++0x92, 0xF8, 0x00, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xA8, 0x80, 0x52, 0x68, 0x11, 0x07, 0x00, 0xF1, 0xD4, 0x81, ++0x94, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0xD0, 0x92, 0x02, 0x23, ++0x0C, 0x21, 0x00, 0x22, 0x4D, 0x20, 0x03, 0xF0, 0x15, 0xF9, 0x01, 0x25, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x45, 0x70, ++0x03, 0xF0, 0x3E, 0xF9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x00, 0x22, 0x84, 0xF8, 0x85, 0x20, 0x18, 0x6C, ++0x29, 0x46, 0xFF, 0xF7, 0x15, 0xF9, 0x55, 0xE0, 0x90, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x7B, 0xD0, 0xFF, 0x23, 0x00, 0x21, ++0x94, 0xF8, 0x51, 0x20, 0x00, 0x2A, 0x6F, 0xD0, 0x94, 0xF8, 0x50, 0x20, 0x01, 0x2A, 0x6B, 0xD1, 0x00, 0x29, 0x9A, 0xD0, ++0x11, 0xE0, 0x90, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x5F, 0xD0, 0x90, 0xF8, 0x21, 0x30, 0x23, 0xB1, 0x90, 0xF8, 0x20, 0x30, ++0x01, 0x2B, 0x00, 0xF0, 0xA6, 0x81, 0x94, 0xF8, 0x40, 0x20, 0x23, 0x7D, 0x02, 0x2A, 0x00, 0xF0, 0x9E, 0x81, 0x01, 0x2B, ++0xB8, 0xD0, 0x94, 0xF8, 0x86, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x0D, 0x81, 0x94, 0xF8, 0x72, 0x50, 0x94, 0xF8, ++0x85, 0x30, 0xA5, 0xF1, 0x01, 0x06, 0xB6, 0xFA, 0x86, 0xF6, 0x76, 0x09, 0xB3, 0x42, 0x00, 0xF0, 0x4C, 0x81, 0x02, 0x23, ++0x0C, 0x21, 0x52, 0x46, 0x4D, 0x20, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x20, 0x92, 0x03, 0xF0, 0xC1, 0xF8, 0x6F, 0x1E, ++0x18, 0xBF, 0x01, 0x27, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x47, 0x70, 0x03, 0xF0, 0xE8, 0xF8, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x08, 0x93, 0x84, 0xF8, 0x85, 0x60, 0x18, 0x6C, 0x39, 0x46, 0xFF, 0xF7, 0xC0, 0xF8, 0x01, 0x2D, 0x4C, 0xD0, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x93, 0xF8, 0x62, 0x20, 0x02, 0x2A, 0x00, 0xF0, 0xF1, 0x80, 0x94, 0xF8, ++0x70, 0x30, 0x7B, 0xB9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x98, 0x98, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x07, 0xD0, ++0x6E, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x01, 0x22, 0x83, 0xF8, 0x24, 0x20, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x90, 0xF8, 0x40, 0x20, 0x03, 0x7D, 0x02, 0x2A, 0xA8, 0xD1, 0x94, 0xF8, 0x44, 0x20, 0x93, 0x42, 0x28, 0xBF, ++0x13, 0x46, 0xA2, 0xE7, 0xFF, 0x23, 0xF7, 0xE7, 0x94, 0xF8, 0x85, 0x20, 0x01, 0x2A, 0x3F, 0xF4, 0x30, 0xAF, 0x94, 0xF8, ++0x71, 0x80, 0xDF, 0xF8, 0x88, 0x91, 0x02, 0x23, 0x0C, 0x21, 0x00, 0x22, 0x4D, 0x20, 0x03, 0xF0, 0x71, 0xF8, 0x00, 0x25, ++0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x45, 0x70, 0x03, 0xF0, 0x9A, 0xF8, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, ++0x01, 0x22, 0x84, 0xF8, 0x85, 0x20, 0x18, 0x6C, 0x29, 0x46, 0xFF, 0xF7, 0x71, 0xF8, 0x94, 0xF8, 0x70, 0xE0, 0xBE, 0xF1, ++0x00, 0x0F, 0x40, 0xF0, 0xD4, 0x80, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x08, 0x97, 0x97, 0xF8, 0x6C, 0x10, 0xFF, 0x29, ++0x00, 0xF0, 0xF0, 0x80, 0x4A, 0x4D, 0x01, 0x94, 0x4F, 0xF4, 0x1E, 0x7B, 0xA4, 0x23, 0x0B, 0xFB, 0x01, 0xF0, 0x03, 0xFB, ++0x08, 0xF3, 0x05, 0xF5, 0x16, 0x7B, 0x2E, 0x18, 0x9E, 0x33, 0x58, 0x44, 0x00, 0x90, 0x09, 0xEB, 0xC3, 0x0B, 0x4F, 0xF0, ++0x4F, 0x0C, 0x46, 0x20, 0x1C, 0xFB, 0x01, 0x01, 0x5C, 0x46, 0x40, 0x4A, 0xDD, 0xF8, 0x00, 0xB0, 0x86, 0xF8, 0x24, 0xE0, ++0x05, 0xEB, 0xC1, 0x05, 0xD6, 0xF8, 0x08, 0x12, 0x39, 0xB3, 0xEF, 0xF3, 0x10, 0x81, 0xCB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x39, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x11, 0x68, 0xA5, 0xF1, 0x28, 0x00, 0x4B, 0x1C, 0xA4, 0xF1, 0x28, 0x01, 0x13, 0x60, ++0x00, 0x90, 0x03, 0xF0, 0x9D, 0xFD, 0xD6, 0xF8, 0x08, 0x12, 0xD6, 0xF8, 0x0C, 0x32, 0x00, 0x98, 0xC7, 0xF8, 0xC8, 0x14, ++0xC7, 0xF8, 0xCC, 0x34, 0x03, 0xF0, 0x9C, 0xFC, 0x2C, 0x4A, 0x11, 0x68, 0x48, 0x1E, 0x31, 0xB1, 0x2B, 0x4B, 0x10, 0x60, ++0x19, 0x68, 0x10, 0xB9, 0x00, 0x29, 0x40, 0xF0, 0xB5, 0x80, 0xD6, 0xF8, 0x30, 0x32, 0x20, 0x46, 0x29, 0x46, 0x08, 0x36, ++0x08, 0x34, 0x08, 0x37, 0x2B, 0xB1, 0x03, 0xF0, 0x7D, 0xFD, 0x28, 0x46, 0x03, 0xF0, 0x84, 0xFC, 0x20, 0x4A, 0x08, 0x35, ++0x5D, 0x45, 0xC3, 0xD1, 0x01, 0x9C, 0x40, 0x20, 0x03, 0xF0, 0xDE, 0xFB, 0x94, 0xF8, 0x70, 0x20, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x08, 0x98, 0x98, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x13, 0xD0, 0x00, 0x2A, 0x7F, 0xF4, 0x55, 0xAF, 0xBA, 0xF1, ++0x00, 0x0F, 0x7F, 0xF4, 0x51, 0xAF, 0x99, 0xE6, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0x8E, 0xAE, 0x94, 0xF8, ++0x71, 0x80, 0xDF, 0xF8, 0x48, 0x90, 0x4F, 0xF0, 0x00, 0x0A, 0x5C, 0xE7, 0xD8, 0xF8, 0x04, 0x30, 0x43, 0xF0, 0x20, 0x03, ++0xC8, 0xF8, 0x04, 0x30, 0x00, 0x2A, 0x7F, 0xF4, 0x3B, 0xAF, 0xE4, 0xE7, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, ++0x35, 0xAF, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x1C, 0x90, 0x4F, 0xF0, 0x01, 0x0A, 0x46, 0xE7, 0x88, 0x1A, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x3C, 0x49, 0x5A, 0x68, 0x49, 0x68, 0x22, 0xF0, 0x20, 0x02, 0x00, 0x29, 0x5A, 0x60, 0x7F, 0xF7, 0x06, 0xAF, 0xEF, 0xF3, ++0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x36, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x36, 0x4D, 0x2B, 0x68, 0x04, 0x20, ++0x01, 0x33, 0x2B, 0x60, 0xEE, 0xF7, 0x1C, 0xFF, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xEE, 0xF7, 0xB7, 0xFF, 0x2B, 0x68, ++0x00, 0x2B, 0x3F, 0xF4, 0xEE, 0xAE, 0x2D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0xE7, 0xAE, ++0x00, 0x2A, 0x3F, 0xF4, 0xE4, 0xAE, 0x62, 0xB6, 0xE1, 0xE6, 0x40, 0x20, 0x03, 0xF0, 0x6E, 0xFB, 0x94, 0xF8, 0x70, 0x20, ++0x8E, 0xE7, 0x94, 0xF8, 0x70, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0xEA, 0xAE, 0x01, 0x2D, 0x7F, 0xF4, 0xE7, 0xAE, 0x2D, 0xE6, ++0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x80, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x93, 0xF8, 0xDE, 0x20, ++0x93, 0xF8, 0xC2, 0x34, 0x9A, 0x42, 0x20, 0xD0, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0xD3, 0xAE, 0x4F, 0xF0, ++0x00, 0x0A, 0xE8, 0xE6, 0x97, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x7F, 0xF4, 0x76, 0xAF, 0x7B, 0x68, 0x43, 0xF0, 0x20, 0x03, ++0x7B, 0x60, 0xBA, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0xC3, 0xAE, 0x0B, 0xE6, 0x62, 0xB6, 0x48, 0xE7, 0x94, 0xF8, 0x85, 0x20, ++0x01, 0x2A, 0x7F, 0xF4, 0x70, 0xAF, 0x00, 0x2B, 0x3F, 0xF4, 0x00, 0xAE, 0xB6, 0xE6, 0x94, 0xF8, 0x85, 0x30, 0x00, 0x2B, ++0x7F, 0xF4, 0x27, 0xAE, 0xB0, 0xE6, 0x01, 0x21, 0x42, 0xE6, 0x90, 0xF8, 0x40, 0x30, 0x02, 0x2B, 0x7F, 0xF4, 0xE3, 0xAD, ++0x3A, 0xE6, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xF4, 0x92, 0x47, 0x7C, 0xB6, 0x49, 0x90, 0xF8, 0x10, 0xB0, 0x8C, 0x23, 0x03, 0xFB, ++0x07, 0x93, 0x83, 0xB0, 0x93, 0xF8, 0x71, 0x20, 0x93, 0xF8, 0x70, 0x30, 0x00, 0x92, 0x07, 0xEB, 0x87, 0x06, 0x4F, 0xF4, ++0xA4, 0x6A, 0xC6, 0xEB, 0xC6, 0x06, 0x01, 0x2B, 0x05, 0x46, 0x0A, 0xFB, 0x02, 0x1A, 0x09, 0xEB, 0x86, 0x06, 0x00, 0xF0, ++0x0B, 0x81, 0xAA, 0x4B, 0xC4, 0x6A, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xD3, 0x80, 0xDA, 0xF8, ++0x7C, 0x30, 0xE4, 0x1A, 0xA4, 0x4B, 0xA5, 0x49, 0xDF, 0xF8, 0x94, 0x82, 0xBB, 0xF1, 0x01, 0x0F, 0x17, 0xD0, 0xBB, 0xF1, ++0x02, 0x0F, 0x00, 0xF0, 0x82, 0x80, 0x1A, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x7F, 0xDB, 0xD8, 0xF8, 0x10, 0x20, ++0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0x80, 0xF2, 0xE9, 0x80, 0xBB, 0xF1, 0x00, 0x0F, 0xE7, 0xD1, ++0xDF, 0xF8, 0x70, 0x82, 0x20, 0xE0, 0xA8, 0x69, 0xDF, 0xF8, 0x68, 0x82, 0x95, 0x4B, 0x1B, 0x69, 0x04, 0x44, 0xE3, 0x1A, ++0xA3, 0xF5, 0x9C, 0x53, 0x08, 0x3B, 0x00, 0x2B, 0x80, 0xF2, 0xFA, 0x80, 0xEA, 0x7C, 0xFF, 0x2A, 0x1B, 0xD0, 0x01, 0x3A, ++0xD2, 0xB2, 0xEA, 0x74, 0xBA, 0xB9, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x97, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x5D, 0xD0, ++0xD8, 0xF8, 0xE8, 0x31, 0x28, 0x46, 0x98, 0x47, 0x87, 0x4B, 0x1B, 0x69, 0xD8, 0xF8, 0x1C, 0x32, 0x30, 0x46, 0x98, 0x47, ++0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x4F, 0xF0, 0x8C, 0x0E, 0x0E, 0xFB, ++0x07, 0x9E, 0xD5, 0xE9, 0x06, 0x0B, 0x9E, 0xF8, 0x70, 0x30, 0xAB, 0xEB, 0x00, 0x01, 0x01, 0x2B, 0x0C, 0x44, 0x47, 0xD0, ++0x7A, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xA8, 0xBF, 0x4F, 0xF0, 0x01, 0x0B, ++0xBE, 0xDB, 0x53, 0xB9, 0x72, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB0, 0x80, 0xDA, 0xF8, ++0x7C, 0x30, 0x23, 0x44, 0xEB, 0x62, 0x21, 0x46, 0xD8, 0xF8, 0xE0, 0x31, 0x28, 0x46, 0x98, 0x47, 0x85, 0xF8, 0x10, 0xB0, ++0xD8, 0xF8, 0x1C, 0x32, 0x30, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x98, 0x47, 0x00, 0x9A, 0x11, 0x46, ++0x63, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xA4, 0x80, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, 0x90, 0x81, 0x9B, 0xE7, 0x5F, 0x48, 0x4F, 0xF4, 0x31, 0x72, 0x04, 0xF0, ++0x53, 0xFF, 0x5A, 0x4B, 0x5A, 0x49, 0x77, 0xE7, 0xD8, 0xF8, 0x08, 0x32, 0xA9, 0x7C, 0x50, 0x46, 0x98, 0x47, 0x58, 0x4B, ++0x1B, 0x69, 0x9F, 0xE7, 0x9E, 0xF8, 0x84, 0x10, 0x00, 0x29, 0x36, 0xD0, 0xA9, 0x6A, 0x01, 0x91, 0x69, 0x6A, 0x01, 0xEB, ++0x0B, 0x0C, 0x01, 0x99, 0x01, 0x39, 0xC5, 0xE9, 0x09, 0xC1, 0x00, 0x29, 0x5E, 0xD1, 0x2A, 0x75, 0xBB, 0xF1, 0x00, 0x0F, ++0x05, 0xD0, 0x4F, 0xF0, 0x00, 0x43, 0xB3, 0xFB, 0xFB, 0xF3, 0x01, 0x3B, 0xAB, 0x62, 0x00, 0x9B, 0x19, 0x46, 0x46, 0x4B, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x32, 0xD8, 0xF8, 0x90, 0x31, 0x92, 0xF8, 0x63, 0x00, 0x03, 0x21, 0x98, 0x47, ++0x43, 0x4B, 0x1B, 0x69, 0xE3, 0x1A, 0xA3, 0xF5, 0x9C, 0x53, 0x08, 0x3B, 0x00, 0x2B, 0x71, 0xDA, 0xA8, 0x69, 0x51, 0xE7, ++0x9A, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x28, 0xAF, 0x3B, 0x49, 0x3D, 0x48, 0x58, 0x22, 0x04, 0xF0, 0x0E, 0xFF, ++0x21, 0xE7, 0x39, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xFF, 0xF6, 0x3E, 0xAF, ++0xD8, 0xF8, 0xE0, 0x21, 0x01, 0x93, 0x21, 0x46, 0x28, 0x46, 0x90, 0x47, 0x01, 0x9B, 0x2B, 0x74, 0xD8, 0xF8, 0x1C, 0x32, ++0x30, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x98, 0x47, 0x00, 0x9A, 0x11, 0x46, 0x28, 0x4A, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x8A, 0xD1, 0x31, 0xE0, 0xC4, 0x68, 0xFD, 0xE6, ++0xBB, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x16, 0xAF, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0xDF, 0xF8, 0x98, 0x80, 0x97, 0xF8, ++0x70, 0x30, 0x54, 0xE7, 0x1F, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xFF, 0xF6, ++0x0B, 0xAF, 0x9B, 0x46, 0x9E, 0xF8, 0x70, 0x30, 0x47, 0xE7, 0x9A, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x4B, 0xAF, ++0x15, 0x49, 0x18, 0x48, 0x49, 0x22, 0x04, 0xF0, 0xC3, 0xFE, 0x44, 0xE7, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x4F, 0xF0, ++0x02, 0x0B, 0x97, 0xF8, 0x70, 0x30, 0x34, 0xE7, 0xBB, 0xF1, 0x01, 0x0F, 0x7F, 0xF4, 0x58, 0xAF, 0x00, 0x9A, 0x11, 0x46, ++0x09, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x5A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x5A, 0x60, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x4F, 0xF0, 0x01, 0x0B, 0x97, 0xF8, 0x70, 0x30, 0x1A, 0xE7, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x64, 0x7D, 0x15, 0x00, ++0x40, 0x9C, 0x15, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x00, 0x22, 0x04, 0x46, 0x0D, 0x46, ++0x10, 0x23, 0x0C, 0x21, 0x55, 0x20, 0x02, 0xF0, 0xA5, 0xFD, 0x05, 0xEB, 0x45, 0x03, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, ++0x04, 0xEB, 0x03, 0x13, 0x45, 0x70, 0x1A, 0x7C, 0x22, 0xB9, 0xC2, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0xF0, 0xC6, 0xBD, ++0x1A, 0x7D, 0xC2, 0x70, 0x00, 0x2A, 0xF7, 0xD0, 0x93, 0xF8, 0x20, 0x20, 0x82, 0x70, 0xD3, 0xE9, 0x06, 0x12, 0x5B, 0x6A, ++0xC3, 0x60, 0xC0, 0xE9, 0x01, 0x12, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0xF0, 0xB5, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, ++0x16, 0x46, 0x2D, 0x4D, 0x4F, 0xF4, 0xA4, 0x62, 0xB3, 0x42, 0x04, 0x46, 0x02, 0xFB, 0x01, 0x58, 0x0B, 0xD3, 0xC2, 0x7C, ++0x01, 0x2A, 0x30, 0xD0, 0xC5, 0x69, 0x9B, 0x1B, 0xB3, 0xFB, 0xF5, 0xF3, 0x03, 0xFB, 0x05, 0x55, 0x2E, 0x44, 0x5F, 0x1C, ++0x00, 0xE0, 0x00, 0x27, 0x23, 0x4B, 0xE6, 0x62, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0xE3, 0x7C, ++0xD8, 0xF8, 0x7C, 0x00, 0xFF, 0x2B, 0xA6, 0xEB, 0x00, 0x00, 0x31, 0xD0, 0xBB, 0x42, 0x94, 0xBF, 0xDB, 0x1A, 0xDB, 0x1B, ++0x1B, 0x4A, 0xDB, 0xB2, 0xE3, 0x74, 0x12, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0x0C, 0xDA, 0x18, 0x49, 0x5B, 0xB1, 0xE5, 0x69, ++0xFF, 0x2B, 0x28, 0x44, 0x0A, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0xE3, 0x74, 0x0A, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0xF3, 0xDB, ++0x03, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x0A, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0xED, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, ++0x98, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xD2, 0xD0, 0x0B, 0x48, 0x0C, 0x49, 0x58, 0x22, 0x04, 0xF0, 0x15, 0xFE, 0xE3, 0x7C, ++0xD8, 0xF8, 0x7C, 0x00, 0xFF, 0x2B, 0xA6, 0xEB, 0x00, 0x00, 0xCD, 0xD1, 0x04, 0x4A, 0x12, 0x69, 0x82, 0x1A, 0x00, 0x2A, ++0xD3, 0xDB, 0xE1, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x40, 0x9C, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x70, 0xB5, 0x08, 0x4E, 0xD6, 0xF8, 0xEC, 0x41, 0x05, 0x46, 0xA0, 0x47, 0x04, 0x46, 0x30, 0xB1, ++0xD6, 0xF8, 0xE0, 0x31, 0x01, 0x46, 0x28, 0x46, 0x98, 0x47, 0x01, 0x23, 0x2B, 0x74, 0xE0, 0xB2, 0x70, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x03, 0x7C, 0x43, 0xB1, 0x10, 0xB5, 0x04, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, ++0x00, 0x23, 0x23, 0x74, 0x10, 0xBD, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x5C, 0x4F, 0x00, 0xEB, ++0x80, 0x04, 0xC4, 0xEB, 0xC4, 0x04, 0x4F, 0xEA, 0x84, 0x0A, 0x83, 0xB0, 0x05, 0x46, 0x07, 0xEB, 0x84, 0x04, 0x0E, 0x46, ++0x00, 0x29, 0x74, 0xD0, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x73, 0x91, 0x46, 0xCA, 0x78, 0x93, 0xF8, 0x84, 0x10, 0x00, 0x29, ++0x40, 0xF0, 0x8A, 0x80, 0x4F, 0xF0, 0x8C, 0x08, 0x08, 0xFB, 0x05, 0x78, 0x01, 0x21, 0x98, 0xF8, 0x79, 0x30, 0x88, 0xF8, ++0x78, 0x20, 0x88, 0xF8, 0x84, 0x10, 0xAB, 0xB1, 0xDF, 0xF8, 0x30, 0xB1, 0x20, 0x46, 0xDB, 0xF8, 0xE8, 0x31, 0x98, 0x47, ++0x00, 0x22, 0x0A, 0xF1, 0x30, 0x00, 0xDB, 0xF8, 0xE8, 0x31, 0x88, 0xF8, 0x79, 0x20, 0x38, 0x44, 0x98, 0x47, 0x00, 0x22, ++0xDB, 0xF8, 0x18, 0x32, 0x88, 0xF8, 0x79, 0x20, 0x20, 0x46, 0x98, 0x47, 0xB6, 0xF8, 0x01, 0x20, 0x3F, 0x49, 0x02, 0x3A, ++0x81, 0xFB, 0x02, 0x31, 0xD3, 0x17, 0xC3, 0xEB, 0xA1, 0x03, 0x13, 0xF0, 0xFF, 0x0B, 0x2E, 0xD0, 0x8C, 0x23, 0x03, 0xFB, ++0x05, 0x73, 0x00, 0x93, 0x06, 0xF1, 0x05, 0x08, 0x4F, 0xF0, 0x00, 0x0A, 0x01, 0x95, 0x98, 0xF8, 0x00, 0x20, 0x36, 0x49, ++0x22, 0x75, 0x0A, 0xF1, 0x01, 0x0A, 0x20, 0x46, 0x4B, 0x46, 0x9A, 0xB1, 0x01, 0x2A, 0xD8, 0xF8, 0x05, 0x50, 0x00, 0xD9, ++0x75, 0xB1, 0xD8, 0xF8, 0x01, 0xC0, 0xE2, 0x74, 0xC4, 0xE9, 0x06, 0xC5, 0x00, 0x9A, 0xD1, 0xF8, 0xF4, 0x51, 0x92, 0xF8, ++0x71, 0x10, 0xD8, 0xF8, 0x09, 0x20, 0xA8, 0x47, 0x00, 0x28, 0x45, 0xD1, 0x5F, 0xFA, 0x8A, 0xF3, 0x5B, 0x45, 0x08, 0xF1, ++0x0D, 0x08, 0x04, 0xF1, 0x30, 0x04, 0xDA, 0xD3, 0x01, 0x9D, 0x96, 0xF9, 0x04, 0x20, 0x33, 0x79, 0x00, 0x2A, 0x2D, 0xDB, ++0x8C, 0x20, 0x00, 0xFB, 0x05, 0x75, 0x00, 0x23, 0x85, 0xF8, 0x73, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xF0, ++0x8C, 0x08, 0x08, 0xFB, 0x00, 0x78, 0x98, 0xF8, 0x79, 0x30, 0x88, 0xF8, 0x84, 0x10, 0x00, 0x2B, 0xEC, 0xD0, 0xDF, 0xF8, ++0x60, 0x90, 0x20, 0x46, 0xD9, 0xF8, 0xE8, 0x31, 0x98, 0x47, 0x0A, 0xF1, 0x30, 0x00, 0xD9, 0xF8, 0xE8, 0x31, 0x88, 0xF8, ++0x79, 0x60, 0x38, 0x44, 0x98, 0x47, 0xD9, 0xF8, 0x18, 0x32, 0x88, 0xF8, 0x79, 0x60, 0x20, 0x46, 0x98, 0x47, 0xD7, 0xE7, ++0x93, 0xF8, 0x78, 0x30, 0x93, 0x42, 0x7F, 0xF4, 0x71, 0xAF, 0xD7, 0xE7, 0x8C, 0x20, 0x00, 0xFB, 0x05, 0x75, 0x03, 0xF0, ++0x7F, 0x03, 0x85, 0xF8, 0x73, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x9A, 0x92, 0xF8, 0x79, 0x30, 0x01, 0x33, ++0x82, 0xF8, 0x79, 0x30, 0xB2, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x4F, 0xEC, 0xC4, 0x4E, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0xB5, 0x01, 0x22, 0x05, 0x48, 0x00, 0x21, 0xE0, 0xF7, 0x2C, 0xF8, 0x04, 0x4B, 0xFF, 0x22, 0x83, 0xF8, 0x71, 0x20, ++0x83, 0xF8, 0xFD, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x44, 0x9E, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x25, 0x4C, 0x94, 0xF8, 0x71, 0x30, 0xFF, 0x2B, 0x07, 0x46, 0x0E, 0x46, 0x08, 0xD0, 0x94, 0xF8, 0xFD, 0x30, 0xFF, 0x2B, ++0x18, 0xBF, 0xFF, 0x25, 0x36, 0xD0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x25, 0xA8, 0x46, 0x4F, 0xF0, 0x30, 0x0A, ++0xA1, 0x46, 0x8C, 0x22, 0x00, 0x21, 0x48, 0x46, 0xE0, 0xF7, 0x04, 0xF8, 0x8C, 0x23, 0x03, 0xFB, 0x08, 0x43, 0x01, 0x2E, ++0x83, 0xF8, 0x71, 0x70, 0x83, 0xF8, 0x70, 0x60, 0x03, 0xD1, 0x15, 0x4A, 0x13, 0x78, 0x01, 0x33, 0x13, 0x70, 0x8C, 0x23, ++0x03, 0xFB, 0x08, 0x43, 0x12, 0x4A, 0xC3, 0xF8, 0x08, 0x90, 0x54, 0x44, 0x00, 0x21, 0x01, 0x26, 0x9C, 0x63, 0x99, 0x74, ++0x0F, 0x4C, 0xD2, 0xF8, 0x10, 0x12, 0x5D, 0x74, 0x83, 0xF8, 0x41, 0x50, 0xC3, 0xF8, 0x68, 0x90, 0x83, 0xF8, 0x42, 0x60, ++0x5C, 0x66, 0x59, 0x60, 0x59, 0x63, 0x48, 0x46, 0xD2, 0xF8, 0x18, 0x32, 0x98, 0x47, 0xC8, 0xE7, 0x01, 0x25, 0xA8, 0x46, ++0x4F, 0xF0, 0xBC, 0x0A, 0x04, 0xF1, 0x8C, 0x09, 0xC9, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x41, 0xF4, 0x13, 0x00, 0x0E, 0x4A, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x23, 0x10, 0xB4, 0x93, 0xF8, ++0x71, 0x40, 0xFF, 0x2C, 0x0A, 0xD0, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x09, 0xD0, 0x29, 0xB1, 0x8C, 0x23, 0x03, 0xFB, ++0x00, 0x20, 0xFF, 0x23, 0x80, 0xF8, 0x71, 0x30, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x04, 0x4C, 0x23, 0x78, 0x01, 0x3B, ++0x23, 0x70, 0x00, 0x29, 0xF6, 0xD0, 0xEF, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, 0x90, 0xF8, 0xC0, 0x34, ++0xBB, 0xB3, 0x2D, 0xE9, 0xF0, 0x47, 0x90, 0xF8, 0x62, 0x40, 0x0C, 0x43, 0x2F, 0xD1, 0x90, 0xF8, 0xC1, 0x54, 0xDF, 0xF8, ++0x64, 0x80, 0x17, 0x4F, 0x05, 0xEB, 0x85, 0x00, 0xC0, 0xEB, 0xC0, 0x00, 0x08, 0xEB, 0x80, 0x09, 0xD7, 0xF8, 0xE8, 0x31, ++0x86, 0x00, 0x48, 0x46, 0x98, 0x47, 0x06, 0xF1, 0x30, 0x00, 0xD7, 0xF8, 0xE8, 0x31, 0x40, 0x44, 0x98, 0x47, 0x8C, 0x23, ++0x03, 0xFB, 0x05, 0x85, 0x95, 0xF8, 0x72, 0x30, 0x85, 0xF8, 0x73, 0x40, 0x85, 0xF8, 0x78, 0x40, 0x85, 0xF8, 0x84, 0x40, ++0x3B, 0xB1, 0x06, 0xF1, 0x60, 0x00, 0xD7, 0xF8, 0xD8, 0x31, 0x40, 0x44, 0x98, 0x47, 0x85, 0xF8, 0x72, 0x40, 0xD7, 0xF8, ++0x18, 0x32, 0x48, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x87, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0x48, 0x9E, 0x17, 0x00, 0x03, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0x85, 0x00, 0x70, 0x47, 0x00, 0xBF, ++0x48, 0x9E, 0x17, 0x00, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x70, 0xB5, 0x05, 0x46, 0x0C, 0x46, ++0x16, 0x46, 0x0E, 0xDB, 0x95, 0xF8, 0xC1, 0x34, 0x0C, 0x4A, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0xD3, 0xF8, 0x80, 0x20, ++0x22, 0x60, 0xD8, 0x6F, 0x30, 0x60, 0x23, 0x68, 0xC0, 0x1A, 0xC0, 0x0F, 0x70, 0xBD, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0xEC, 0xD1, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x06, 0x52, 0x04, 0xF0, 0x23, 0xFC, 0xE5, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x48, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA4, 0xA3, 0x15, 0x00, 0x70, 0xB5, 0x35, 0x4E, 0x33, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, 0x12, 0xDB, 0x90, 0xF8, 0xC1, 0x24, 0x31, 0x48, 0x8C, 0x23, 0x01, 0xEB, ++0x41, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, 0x1B, 0x7C, 0x01, 0x2B, 0x28, 0xD0, ++0x02, 0x2B, 0x1D, 0xD0, 0x00, 0x20, 0x70, 0xBD, 0x90, 0xF8, 0xC0, 0x34, 0x0B, 0xB1, 0x01, 0x29, 0x30, 0xD9, 0x27, 0x49, ++0x27, 0x48, 0x40, 0xF2, 0x14, 0x52, 0x04, 0xF0, 0xF3, 0xFB, 0x95, 0xF8, 0xC1, 0x24, 0x22, 0x48, 0x8C, 0x23, 0x04, 0xEB, ++0x44, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, 0x1B, 0x7C, 0x01, 0x2B, 0x0A, 0xD0, ++0x02, 0x2B, 0x13, 0xD1, 0x8C, 0x23, 0x0C, 0x44, 0x03, 0xFB, 0x02, 0xF1, 0x01, 0xEB, 0x04, 0x11, 0x01, 0x44, 0xC8, 0x68, ++0x70, 0xBD, 0x8C, 0x23, 0x0C, 0x44, 0x03, 0xFB, 0x02, 0xF1, 0x01, 0xEB, 0x04, 0x14, 0x01, 0x19, 0xC8, 0x68, 0x8B, 0x69, ++0x18, 0x44, 0x70, 0xBD, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC8, 0xDA, 0x10, 0xE0, 0x90, 0xF8, 0xC1, 0x24, ++0x0C, 0x48, 0x8C, 0x23, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, ++0x1B, 0x7C, 0x01, 0x2B, 0xDF, 0xD0, 0x02, 0x2B, 0xD4, 0xD0, 0x06, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0xA4, 0x62, 0x04, 0xF0, ++0xC9, 0xFB, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xB0, 0xA3, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x43, 0xD0, 0x2D, 0xE9, 0xF0, 0x41, ++0x28, 0x4F, 0x90, 0xF8, 0xC1, 0x24, 0x44, 0x68, 0x8C, 0x26, 0x06, 0xFB, 0x02, 0x76, 0x02, 0xEB, 0x82, 0x03, 0x96, 0xF8, ++0x73, 0xC0, 0x01, 0x25, 0xC3, 0xEB, 0xC3, 0x03, 0x24, 0xF0, 0x40, 0x04, 0x86, 0xF8, 0x86, 0x50, 0x4F, 0xEA, 0x83, 0x0E, ++0x07, 0xEB, 0x83, 0x05, 0x44, 0x60, 0xBC, 0xF1, 0x00, 0x0F, 0x06, 0xD1, 0x1C, 0x4E, 0x28, 0x46, 0xD6, 0xF8, 0x18, 0x32, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x96, 0xF8, 0x70, 0x30, 0x01, 0xEB, 0x8C, 0x24, 0x3B, 0xB9, 0x17, 0x4B, 0x18, 0x69, ++0x01, 0xF5, 0x96, 0x73, 0xC1, 0x1A, 0x11, 0xF1, 0x32, 0x0F, 0x14, 0xD4, 0x8C, 0x23, 0x03, 0xFB, 0x02, 0x72, 0x11, 0x4E, ++0x0E, 0xF1, 0x60, 0x00, 0x01, 0x23, 0x38, 0x44, 0x21, 0x46, 0x82, 0xF8, 0x72, 0x30, 0xD6, 0xF8, 0xE0, 0x31, 0x98, 0x47, ++0xD6, 0xF8, 0x18, 0x32, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x70, 0x47, 0x08, 0x4D, 0x74, 0x67, 0x0E, 0xF1, ++0x60, 0x00, 0x02, 0x22, 0x38, 0x44, 0x19, 0x46, 0x86, 0xF8, 0x72, 0x20, 0xD5, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0xB4, 0x0A, 0x49, ++0x90, 0xF8, 0xC1, 0x34, 0x09, 0x4C, 0x8C, 0x20, 0x03, 0xEB, 0x83, 0x02, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x25, 0xC2, 0xEB, ++0xC2, 0x02, 0x83, 0xF8, 0x86, 0x50, 0x01, 0xEB, 0x82, 0x00, 0xD4, 0xF8, 0x18, 0x32, 0x30, 0xBC, 0x18, 0x47, 0x00, 0xBF, ++0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x90, 0xF8, 0xC0, 0x44, 0x00, 0x2C, 0x3E, 0xD0, ++0x90, 0xF8, 0x62, 0x30, 0x05, 0x46, 0x00, 0x2B, 0x3C, 0xD1, 0x27, 0x4B, 0x90, 0xF8, 0xC1, 0x74, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x88, 0x46, 0x16, 0x46, 0x36, 0xDB, 0xD8, 0xF8, 0x08, 0x00, 0xB2, 0x8B, 0x00, 0xF1, 0x24, 0x03, ++0x10, 0x44, 0x83, 0x42, 0x02, 0xD3, 0x38, 0xE0, 0x98, 0x42, 0x36, 0xD9, 0x5D, 0x78, 0x1A, 0x78, 0xA9, 0x1C, 0xDD, 0x2A, ++0x1C, 0x46, 0x0B, 0x44, 0xF6, 0xD1, 0x62, 0x79, 0x09, 0x2A, 0xF3, 0xD1, 0x06, 0x34, 0x04, 0x3D, 0x14, 0xFA, 0x85, 0xF5, ++0xAC, 0x42, 0x06, 0xD3, 0xEC, 0xE7, 0xB4, 0xF8, 0x01, 0x10, 0x03, 0x31, 0x0C, 0x44, 0xA5, 0x42, 0xE6, 0xD9, 0x22, 0x78, ++0x0C, 0x2A, 0xF6, 0xD1, 0x00, 0x2C, 0xE1, 0xD0, 0xB2, 0x68, 0x0F, 0x4B, 0x92, 0x68, 0xD3, 0xF8, 0xF0, 0x31, 0x92, 0x69, ++0x38, 0x46, 0x21, 0x46, 0x98, 0x47, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x24, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, ++0x01, 0x2F, 0xC6, 0xD9, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x73, 0x52, 0x04, 0xF0, 0xD8, 0xFA, 0x95, 0xF8, 0xC1, 0x74, ++0xBD, 0xE7, 0x00, 0x24, 0xE2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xD8, 0xA3, 0x15, 0x00, 0xF0, 0xB5, 0x0C, 0x7E, 0x7F, 0x2C, 0x83, 0xB0, 0x23, 0xD1, 0x4A, 0x7F, 0x0A, 0xBB, 0xCA, 0x7F, ++0xDD, 0x2A, 0x1E, 0xD1, 0x91, 0xF8, 0x24, 0x20, 0x09, 0x2A, 0x1A, 0xD1, 0x91, 0xF8, 0x25, 0x20, 0x0C, 0x2A, 0x01, 0xF1, ++0x25, 0x04, 0x14, 0xD1, 0x11, 0x4A, 0x12, 0x49, 0x12, 0x68, 0xD1, 0xF8, 0xF0, 0x61, 0xB2, 0xF9, 0x00, 0x20, 0x90, 0xF8, ++0xC1, 0x74, 0x00, 0x2A, 0x05, 0x46, 0x0A, 0xDB, 0xEA, 0x6F, 0x21, 0x46, 0x1A, 0x44, 0x38, 0x46, 0x33, 0x46, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x40, 0x18, 0x47, 0x03, 0xB0, 0xF0, 0xBD, 0x90, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xF0, 0xD0, 0x06, 0x49, ++0x06, 0x48, 0x01, 0x93, 0x49, 0x22, 0x04, 0xF0, 0x95, 0xFA, 0x01, 0x9B, 0xE8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x12, 0x4B, 0x18, 0x78, 0xF8, 0xB1, 0x12, 0x4B, ++0x58, 0x7C, 0xD8, 0xB9, 0x9A, 0x7C, 0x01, 0x2A, 0x19, 0xD8, 0x9B, 0x68, 0x13, 0xB9, 0x16, 0xE0, 0x1B, 0x68, 0xAB, 0xB1, ++0x93, 0xF8, 0x62, 0x20, 0x02, 0x2A, 0xF9, 0xD1, 0x93, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0xF5, 0xD0, 0x93, 0xF8, 0xC1, 0x34, ++0x08, 0x4A, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x85, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x44, 0x9E, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, ++0x18, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x1B, 0xB1, 0x90, 0xF8, 0x62, 0x30, ++0x02, 0x2B, 0x00, 0xD0, 0x70, 0x47, 0x70, 0xB5, 0x90, 0xF8, 0xC1, 0x34, 0x11, 0x4C, 0x8C, 0x22, 0x02, 0xFB, 0x03, 0x42, ++0x00, 0x39, 0x03, 0xEB, 0x83, 0x03, 0x92, 0xF8, 0x84, 0x50, 0x18, 0xBF, 0x01, 0x21, 0xC3, 0xEB, 0xC3, 0x03, 0x82, 0xF8, ++0x87, 0x10, 0x04, 0xEB, 0x83, 0x04, 0x35, 0xB9, 0x09, 0x4D, 0xD5, 0xF8, 0x18, 0x32, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, ++0x18, 0x47, 0x06, 0x4D, 0x92, 0xF8, 0x71, 0x00, 0xD5, 0xF8, 0x90, 0x31, 0x03, 0x21, 0x98, 0x47, 0xF1, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0E, 0x4E, 0x90, 0xF8, 0xC1, 0x44, ++0x0D, 0x4D, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0x01, 0x22, 0x04, 0xEB, 0x84, 0x04, 0x93, 0xF8, 0x71, 0x00, 0x83, 0xF8, ++0x73, 0x10, 0x83, 0xF8, 0x72, 0x20, 0xC4, 0xEB, 0xC4, 0x04, 0xD5, 0xF8, 0x90, 0x31, 0x03, 0x21, 0x98, 0x47, 0xD5, 0xF8, ++0x18, 0x32, 0x06, 0xEB, 0x84, 0x00, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x1D, 0x4F, 0x90, 0xF8, 0xC1, 0x44, 0x8C, 0x26, 0x06, 0xFB, 0x04, 0x76, 0x04, 0xEB, 0x84, 0x00, ++0x96, 0xF8, 0x72, 0x20, 0xC0, 0xEB, 0xC0, 0x00, 0x4F, 0xF0, 0x00, 0x09, 0x07, 0xEB, 0x80, 0x05, 0x86, 0xF8, 0x73, 0x90, ++0x9A, 0xB9, 0xDF, 0xF8, 0x54, 0x80, 0xD8, 0xF8, 0x18, 0x32, 0x28, 0x46, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x74, ++0x94, 0xF8, 0x79, 0x30, 0x9B, 0xB9, 0xD8, 0xF8, 0x90, 0x31, 0x94, 0xF8, 0x71, 0x00, 0x02, 0x21, 0xBD, 0xE8, 0xF0, 0x47, ++0x18, 0x47, 0x83, 0x00, 0xDF, 0xF8, 0x28, 0x80, 0x03, 0xF1, 0x60, 0x00, 0x38, 0x44, 0xD8, 0xF8, 0xD8, 0x31, 0x98, 0x47, ++0x86, 0xF8, 0x72, 0x90, 0xE1, 0xE7, 0xD8, 0xF8, 0x90, 0x31, 0x94, 0xF8, 0x71, 0x00, 0x03, 0x21, 0xBD, 0xE8, 0xF0, 0x47, ++0x18, 0x47, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x90, 0xF8, 0xC0, 0x34, 0x63, 0xB1, 0x90, 0xF8, ++0xC1, 0x34, 0x06, 0x4A, 0x06, 0x48, 0x03, 0xEB, 0x83, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x00, 0xEB, 0x83, 0x00, 0xD2, 0xF8, ++0x18, 0x32, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x42, 0x4E, 0x90, 0xF8, 0xC1, 0x84, 0xDD, 0xF8, 0x30, 0xC0, 0x8C, 0x24, 0x04, 0xFB, 0x08, 0x64, 0x94, 0xF8, 0x70, 0x70, ++0x01, 0x2F, 0x0F, 0xD1, 0x08, 0xEB, 0x88, 0x05, 0x94, 0xF8, 0x10, 0x90, 0xC5, 0xEB, 0xC5, 0x05, 0xA8, 0x00, 0x06, 0xEB, ++0x85, 0x05, 0xB9, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x94, 0xF8, 0x40, 0x40, 0x00, 0x2C, 0x64, 0xD0, 0x4F, 0xF0, 0xFF, 0x09, ++0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x28, 0x46, 0xCA, 0x46, 0x8C, 0x24, 0x4F, 0xEA, 0x4A, 0x07, 0x04, 0xFB, 0x08, 0xF4, ++0x07, 0xEB, 0x0A, 0x0B, 0x06, 0xEB, 0x04, 0x0E, 0x04, 0xEB, 0x0B, 0x14, 0x00, 0x29, 0x06, 0xEB, 0x04, 0x01, 0x9E, 0xF8, ++0x79, 0xB0, 0xCB, 0x74, 0x0B, 0x75, 0x0A, 0x9B, 0xCB, 0x61, 0x0B, 0xF1, 0x01, 0x0B, 0x0B, 0x9B, 0x8B, 0x61, 0x0C, 0xBF, ++0x01, 0x24, 0x00, 0x24, 0xC1, 0xF8, 0x24, 0xC0, 0x81, 0xF8, 0x21, 0x20, 0x81, 0xF8, 0x20, 0x40, 0x8E, 0xF8, 0x79, 0xB0, ++0x04, 0xD0, 0x9E, 0xF8, 0x7A, 0x30, 0x01, 0x33, 0x8E, 0xF8, 0x7A, 0x30, 0x0A, 0x9B, 0x73, 0xB1, 0x8C, 0x23, 0x07, 0xEB, ++0x0A, 0x02, 0x03, 0xFB, 0x08, 0xF3, 0x03, 0xEB, 0x02, 0x13, 0x33, 0x44, 0x0A, 0x99, 0x4F, 0xF0, 0x00, 0x42, 0xB2, 0xFB, ++0xF1, 0xF2, 0x01, 0x3A, 0x9A, 0x62, 0x15, 0x4C, 0x61, 0x46, 0xD4, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, ++0x08, 0xF8, 0x57, 0x44, 0x08, 0xEB, 0x07, 0x17, 0x37, 0x44, 0x46, 0x44, 0x01, 0x23, 0x96, 0xF8, 0x71, 0x00, 0x3B, 0x74, ++0x03, 0x21, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x47, 0x49, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0xA4, 0xFA, 0xD4, 0xF8, 0x1C, 0x32, ++0x28, 0x46, 0x98, 0x47, 0x28, 0x46, 0xD4, 0xF8, 0x18, 0x32, 0x98, 0x47, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x30, 0x30, ++0xB9, 0x46, 0x30, 0x44, 0xBA, 0x46, 0x9C, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x90, 0xF8, 0xC1, 0x64, 0x37, 0x4D, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0xF3, 0xE8, 0x18, 0x90, 0xF8, 0x70, 0x00, 0x01, 0x28, ++0x5C, 0xD1, 0x01, 0x29, 0x0C, 0x46, 0x57, 0xD8, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x01, 0x13, 0x2B, 0x44, 0x4F, 0xEA, ++0x44, 0x08, 0x19, 0x7C, 0x00, 0x29, 0x4D, 0xD0, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x48, 0xD0, 0x06, 0xEB, ++0x86, 0x07, 0x04, 0xEB, 0x44, 0x00, 0xDF, 0xF8, 0xA4, 0x90, 0xC7, 0xEB, 0xC7, 0x07, 0x00, 0x01, 0x00, 0xEB, 0x87, 0x00, ++0xD9, 0xF8, 0xD8, 0x31, 0x28, 0x44, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0xFA, 0xA0, 0x44, 0x0A, 0xEB, 0x08, 0x18, ++0xA8, 0x44, 0x00, 0x23, 0x05, 0xEB, 0x87, 0x07, 0x88, 0xF8, 0x10, 0x30, 0xD9, 0xF8, 0x1C, 0x22, 0x38, 0x46, 0x90, 0x47, ++0xD9, 0xF8, 0x18, 0x22, 0x38, 0x46, 0x90, 0x47, 0x05, 0xEB, 0x0A, 0x03, 0x98, 0xF8, 0x20, 0x10, 0x93, 0xF8, 0x79, 0x20, ++0x01, 0x3A, 0xD2, 0xB2, 0x01, 0x29, 0x83, 0xF8, 0x79, 0x20, 0x04, 0xD1, 0x93, 0xF8, 0x7A, 0x10, 0x01, 0x39, 0x83, 0xF8, ++0x7A, 0x10, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0x53, 0x93, 0xF8, 0x73, 0x10, 0x01, 0xB9, 0x92, 0xB1, 0x8C, 0x23, 0x03, 0xFB, ++0x06, 0x55, 0x03, 0x21, 0xD9, 0xF8, 0x90, 0x31, 0x95, 0xF8, 0x71, 0x00, 0x98, 0x47, 0x38, 0x46, 0x21, 0x46, 0xFF, 0xF7, ++0x29, 0xFA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xD9, 0xF8, 0x90, 0x21, 0x93, 0xF8, ++0x71, 0x00, 0x02, 0x21, 0x90, 0x47, 0xEE, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x1F, 0x4F, 0x90, 0xF8, 0xC1, 0x84, 0x8C, 0x25, 0x05, 0xFB, 0x08, 0x75, 0x08, 0xEB, 0x88, 0x03, 0x95, 0xF8, 0x20, 0x20, ++0xC3, 0xEB, 0xC3, 0x03, 0x0E, 0x46, 0x9C, 0x00, 0xAA, 0xB9, 0x2B, 0x7C, 0x9B, 0xB1, 0xE9, 0x68, 0xDF, 0xF8, 0x5C, 0x90, ++0x31, 0x44, 0xD9, 0xF8, 0xE0, 0x31, 0x38, 0x19, 0x98, 0x47, 0x95, 0xF8, 0x50, 0x30, 0x13, 0xB9, 0x95, 0xF8, 0x40, 0x30, ++0x6B, 0xB9, 0xD9, 0xF8, 0x1C, 0x32, 0x38, 0x19, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x95, 0xF8, 0x50, 0x30, 0xAB, 0xB9, ++0x95, 0xF8, 0x40, 0x30, 0x93, 0xB1, 0xDF, 0xF8, 0x2C, 0x90, 0x8C, 0x23, 0x03, 0xFB, 0x08, 0x73, 0x04, 0xF1, 0x30, 0x00, ++0xD9, 0x6B, 0xD9, 0xF8, 0xE0, 0x31, 0x38, 0x44, 0x31, 0x44, 0x98, 0x47, 0xD9, 0xF8, 0x1C, 0x32, 0x38, 0x19, 0xBD, 0xE8, ++0xF0, 0x47, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x87, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x0A, 0x4B, 0x8C, 0x22, ++0x02, 0xFB, 0x00, 0x33, 0x93, 0xF8, 0x71, 0x20, 0xFF, 0x2A, 0x0B, 0xD0, 0x93, 0xF8, 0x84, 0x00, 0x48, 0xB1, 0x93, 0xF8, ++0x88, 0x00, 0x00, 0xEB, 0x40, 0x03, 0x00, 0xEB, 0x83, 0x00, 0x0B, 0x30, 0xC0, 0xB2, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x48, 0x9E, 0x17, 0x00, 0x30, 0xB4, 0xDD, 0x23, 0x50, 0x25, 0x6F, 0x24, 0x9A, 0x21, 0x09, 0x22, 0x03, 0x70, 0x0C, 0x23, ++0x85, 0x70, 0xC4, 0x70, 0x01, 0x71, 0x42, 0x71, 0x83, 0x71, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x43, ++0x2D, 0x4E, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x63, 0x93, 0xF8, 0x78, 0x20, 0x4A, 0x72, 0x93, 0xF8, 0x73, 0x40, 0x01, 0x32, ++0x83, 0xF8, 0x78, 0x20, 0x00, 0x2C, 0x46, 0xD0, 0x64, 0xF0, 0x7F, 0x04, 0x8C, 0x72, 0x00, 0xEB, 0x80, 0x03, 0xC3, 0xEB, ++0xC3, 0x03, 0x4F, 0xF0, 0x8C, 0x0C, 0xDF, 0xF8, 0x8C, 0x90, 0xDF, 0xF8, 0x8C, 0x80, 0x06, 0xEB, 0x83, 0x03, 0x0C, 0xFB, ++0x00, 0x6C, 0x01, 0xF1, 0x0B, 0x02, 0x01, 0xF1, 0x25, 0x0E, 0x00, 0x24, 0x1D, 0x7C, 0xC5, 0xB1, 0x9C, 0xF8, 0x87, 0x50, ++0x15, 0xB1, 0x93, 0xF8, 0x21, 0x50, 0x55, 0xBB, 0x1D, 0x7D, 0x15, 0x70, 0xD3, 0xE9, 0x06, 0x57, 0xC2, 0xF8, 0x01, 0x50, ++0xC2, 0xF8, 0x05, 0x70, 0xD9, 0xF8, 0x00, 0x50, 0xD8, 0xF8, 0x10, 0x70, 0xED, 0x1B, 0x5F, 0x6A, 0x01, 0x34, 0x3D, 0x44, ++0xE4, 0xB2, 0xC2, 0xF8, 0x09, 0x50, 0x0D, 0x32, 0x72, 0x45, 0x03, 0xF1, 0x30, 0x03, 0xDF, 0xD1, 0x8C, 0x22, 0x04, 0xEB, ++0x44, 0x03, 0x04, 0xEB, 0x83, 0x03, 0x02, 0xFB, 0x00, 0x60, 0x03, 0xF1, 0x09, 0x02, 0x80, 0xF8, 0x88, 0x40, 0x02, 0x33, ++0x4A, 0x70, 0xA1, 0xF8, 0x07, 0x30, 0xBD, 0xE8, 0xF0, 0x83, 0x8C, 0x72, 0xB9, 0xE7, 0x93, 0xF8, 0x20, 0x50, 0x01, 0x2D, ++0xD0, 0xD1, 0xE2, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0xA4, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x02, 0x29, 0x20, 0xD0, ++0x03, 0x29, 0x0F, 0xD0, 0x01, 0x29, 0x06, 0xD0, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1E, 0xDB, ++0x70, 0x47, 0x13, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x80, 0xF8, 0x84, 0x10, 0x70, 0x47, 0x0F, 0x4B, 0x8C, 0x22, ++0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0x84, 0x30, 0x00, 0x2B, 0xEF, 0xD1, 0x0C, 0x4B, 0x90, 0xF8, 0x71, 0x00, 0xD3, 0xF8, ++0x90, 0x31, 0x01, 0x21, 0x18, 0x47, 0x08, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x00, 0x23, 0x80, 0xF8, 0x84, 0x30, ++0x70, 0x47, 0x06, 0x49, 0x06, 0x48, 0x4F, 0xF4, 0xEA, 0x62, 0x03, 0xF0, 0xA5, 0xBF, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x90, 0xF8, 0xC0, 0x34, ++0x33, 0xB1, 0x90, 0xF8, 0x64, 0x30, 0x1B, 0xB1, 0x43, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x43, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0x2D, 0xE9, 0xF0, 0x47, 0x36, 0x4F, 0x02, 0x7E, 0xDF, 0xF8, 0xE0, 0x80, 0x35, 0x49, 0xD8, 0xF8, 0xB0, 0x33, 0x0E, 0x69, ++0x05, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x70, 0x98, 0x47, 0xEB, 0x7E, 0x00, 0x2B, 0x3A, 0xD0, 0xD5, 0xE9, ++0x04, 0x43, 0x02, 0x2C, 0x8C, 0xBF, 0x01, 0x24, 0x00, 0x24, 0x02, 0x2B, 0x6B, 0x7E, 0x95, 0xF8, 0x18, 0xA0, 0x88, 0xBF, ++0x44, 0xF0, 0x02, 0x04, 0x63, 0x40, 0x9B, 0x07, 0x44, 0xD1, 0xD1, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x0A, 0x7A, ++0x6C, 0x76, 0xDA, 0xF8, 0xE4, 0x00, 0x18, 0xB3, 0xDF, 0xF8, 0x94, 0xC0, 0x4F, 0xF0, 0x00, 0x0E, 0x90, 0xF8, 0x23, 0x10, ++0x00, 0x68, 0x01, 0xEB, 0x41, 0x04, 0x64, 0x44, 0x4B, 0x00, 0x62, 0x78, 0xA4, 0x78, 0x02, 0x2A, 0x0B, 0x44, 0x88, 0xBF, ++0x01, 0x22, 0x0C, 0xEB, 0x03, 0x01, 0x98, 0xBF, 0x00, 0x22, 0x02, 0x2C, 0x88, 0xBF, 0x42, 0xF0, 0x02, 0x02, 0x0C, 0xF8, ++0x03, 0x20, 0x81, 0xF8, 0x01, 0xE0, 0x81, 0xF8, 0x02, 0xE0, 0x00, 0x28, 0xE2, 0xD1, 0x01, 0xE0, 0x95, 0xF8, 0x18, 0x90, ++0x11, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x77, 0x9B, 0x6A, 0x39, 0x6C, 0x00, 0x22, 0x5B, 0x1A, 0xC5, 0xE9, ++0x04, 0x22, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0x06, 0xF5, 0xC3, 0x31, 0xEB, 0x76, 0xD8, 0xF8, 0xE0, 0x31, 0x28, 0x46, ++0xA0, 0x31, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x21, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0xC4, 0xFC, 0x95, 0xF8, 0x18, 0x90, ++0xB4, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x60, 0x9F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x10, 0x4D, 0xDF, 0xF8, 0x44, 0x80, 0xC0, 0xEB, 0xC0, 0x03, 0x05, 0xEB, ++0x83, 0x03, 0xC0, 0xEB, 0xC0, 0x06, 0x9B, 0x7E, 0x04, 0x46, 0x05, 0xEB, 0x86, 0x06, 0xC7, 0x00, 0x1B, 0xB1, 0xD8, 0xF8, ++0xD8, 0x31, 0x30, 0x46, 0x98, 0x47, 0x3F, 0x1B, 0x05, 0xEB, 0x87, 0x05, 0x1C, 0x22, 0x00, 0x21, 0x30, 0x46, 0xDF, 0xF7, ++0x0F, 0xFA, 0xD8, 0xF8, 0x34, 0x33, 0xAE, 0x60, 0x2C, 0x76, 0x6B, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x80, 0x9F, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x00, 0x20, 0xFF, 0xF7, 0xD4, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0xD1, 0xFF, 0x02, 0x20, ++0xFF, 0xF7, 0xCE, 0xFF, 0x03, 0x20, 0xFF, 0xF7, 0xCB, 0xFF, 0x05, 0x4B, 0x00, 0x22, 0x03, 0xF1, 0x1E, 0x01, 0x5A, 0x70, ++0x9A, 0x70, 0x03, 0xF8, 0x03, 0x2B, 0x8B, 0x42, 0xF9, 0xD1, 0x08, 0xBD, 0x60, 0x9F, 0x17, 0x00, 0x0B, 0x4A, 0xC0, 0xEB, ++0xC0, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x99, 0x7E, 0x71, 0xB9, 0x30, 0xB4, 0x08, 0x49, 0x09, 0x4C, 0x09, 0x69, 0xD4, 0xF8, ++0xE0, 0x41, 0x01, 0x25, 0x01, 0xF5, 0xC3, 0x31, 0x9D, 0x76, 0x18, 0x46, 0xA0, 0x31, 0x23, 0x46, 0x30, 0xBC, 0x18, 0x47, ++0x70, 0x47, 0x00, 0xBF, 0x80, 0x9F, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x09, 0x29, 0x08, 0xB5, ++0x09, 0xD9, 0x6A, 0xBB, 0x21, 0x4B, 0xC0, 0xEB, 0xC0, 0x00, 0x03, 0xEB, 0x80, 0x00, 0x03, 0x69, 0x01, 0x33, 0x03, 0x61, ++0x08, 0xBD, 0x8A, 0xB1, 0x1C, 0x4B, 0x1D, 0x4A, 0xC0, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x80, 0x00, ++0x11, 0x44, 0x42, 0x69, 0x8B, 0x78, 0x01, 0x32, 0x02, 0x2B, 0x42, 0x61, 0xEE, 0xD8, 0x01, 0x33, 0x8B, 0x70, 0x08, 0xBD, ++0x13, 0x4B, 0x14, 0x4A, 0xC0, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x80, 0x00, 0x11, 0x44, 0x03, 0x69, ++0x4A, 0x78, 0x01, 0x33, 0x02, 0x2A, 0x03, 0x61, 0xDC, 0xD8, 0x01, 0x32, 0x4A, 0x70, 0x08, 0xBD, 0x0A, 0x4A, 0x0C, 0x4B, ++0x1C, 0x21, 0x01, 0xFB, 0x00, 0x20, 0x1A, 0x68, 0x43, 0x69, 0xB2, 0xF9, 0x00, 0x20, 0x01, 0x33, 0x00, 0x2A, 0x43, 0x61, ++0x05, 0xDA, 0x07, 0x49, 0x07, 0x48, 0x40, 0xF2, 0x69, 0x12, 0x03, 0xF0, 0x6F, 0xFE, 0x00, 0x23, 0x9B, 0x78, 0xFF, 0xDE, ++0x80, 0x9F, 0x17, 0x00, 0x60, 0x9F, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF8, 0xA3, 0x15, 0x00, ++0x70, 0xB5, 0x1E, 0x46, 0x0D, 0x46, 0x01, 0x23, 0x31, 0x46, 0x40, 0xF6, 0x01, 0x00, 0x01, 0xF0, 0x77, 0xFD, 0x04, 0x46, ++0x02, 0x20, 0x02, 0xF0, 0x15, 0xF8, 0x18, 0x4A, 0x18, 0x49, 0x03, 0x46, 0x04, 0x20, 0x03, 0xF0, 0x25, 0xFC, 0x02, 0x20, ++0x02, 0xF0, 0x0C, 0xF8, 0xA0, 0xB9, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x16, 0xDB, 0x13, 0x4A, ++0x00, 0x23, 0x23, 0x70, 0x28, 0x46, 0x15, 0x60, 0x93, 0x72, 0x16, 0x81, 0x01, 0x25, 0x00, 0xF0, 0x7D, 0xF9, 0x20, 0x46, ++0x01, 0xF0, 0x86, 0xFD, 0x28, 0x46, 0x70, 0xBD, 0x08, 0x23, 0x20, 0x46, 0x23, 0x70, 0x00, 0x25, 0x01, 0xF0, 0x7E, 0xFD, ++0x28, 0x46, 0x70, 0xBD, 0x95, 0xF8, 0x6F, 0x31, 0x00, 0x2B, 0xE4, 0xD1, 0x06, 0x49, 0x07, 0x48, 0x46, 0x22, 0x03, 0xF0, ++0x25, 0xFE, 0xDE, 0xE7, 0x84, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xF4, 0x9F, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x08, 0xA4, 0x15, 0x00, 0x17, 0x4A, 0x18, 0x4B, 0x12, 0x68, 0x70, 0xB5, 0xB2, 0xF9, 0x00, 0x20, ++0x1D, 0x68, 0x9C, 0x7A, 0x00, 0x2A, 0x19, 0xDB, 0x14, 0x4A, 0x15, 0x48, 0xD2, 0xE9, 0x00, 0x63, 0x04, 0xEB, 0x44, 0x04, ++0x05, 0xEB, 0x44, 0x04, 0x43, 0xF4, 0x08, 0x53, 0xE1, 0x78, 0x53, 0x60, 0x33, 0x43, 0x03, 0x60, 0xCB, 0x07, 0x03, 0xD4, ++0x0E, 0x4B, 0xD3, 0xF8, 0xEC, 0x32, 0x98, 0x47, 0x03, 0x21, 0x02, 0x20, 0x01, 0xF0, 0x0E, 0xFF, 0x00, 0x20, 0x70, 0xBD, ++0x02, 0x20, 0x01, 0xF0, 0xB1, 0xFF, 0x02, 0x28, 0xE0, 0xD0, 0x08, 0x49, 0x08, 0x48, 0x9C, 0x22, 0x03, 0xF0, 0xEA, 0xFD, ++0xDA, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xF4, 0x9F, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x1C, 0xA4, 0x15, 0x00, 0x38, 0xB5, 0x22, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x32, 0xDB, 0x20, 0x49, 0x20, 0x48, 0x21, 0x4C, 0xD1, 0xE9, 0x00, 0x32, 0x22, 0xF4, 0x08, 0x52, ++0x13, 0x43, 0x03, 0x60, 0xA3, 0x7A, 0x20, 0x68, 0x4A, 0x60, 0x90, 0xF8, 0x6F, 0x51, 0x01, 0x33, 0xDB, 0xB2, 0x9D, 0x42, ++0xA3, 0x72, 0x01, 0xD9, 0xE3, 0x7A, 0x93, 0xB1, 0x0C, 0x38, 0x01, 0xF0, 0x55, 0xFD, 0xE3, 0x7A, 0x8B, 0xB1, 0x16, 0x4B, ++0x21, 0x89, 0xD3, 0xF8, 0xF0, 0x32, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0xE3, 0x72, 0x00, 0x21, 0x02, 0x20, 0x01, 0xF0, ++0xC5, 0xFE, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xF0, 0x8D, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x21, 0x89, 0x02, 0x22, 0x40, 0xF6, ++0x02, 0x00, 0x01, 0xF0, 0x27, 0xFD, 0xEE, 0xE7, 0x02, 0x20, 0x01, 0xF0, 0x5D, 0xFF, 0x03, 0x28, 0xC7, 0xD0, 0x08, 0x49, ++0x08, 0x48, 0xC2, 0x22, 0x03, 0xF0, 0x96, 0xFD, 0xC1, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x60, 0x00, 0x32, 0x40, 0xF4, 0x9F, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x4C, 0xA4, 0x15, 0x00, ++0x38, 0xB5, 0x02, 0x20, 0x1D, 0x46, 0x01, 0xF0, 0x41, 0xFF, 0x0A, 0x4A, 0x0A, 0x49, 0x04, 0x46, 0x03, 0x46, 0x04, 0x20, ++0x03, 0xF0, 0x50, 0xFB, 0x24, 0xB1, 0x08, 0x4B, 0x01, 0x22, 0xDA, 0x72, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x4B, 0x29, 0x46, ++0xD3, 0xF8, 0xF0, 0x32, 0x01, 0x20, 0x98, 0x47, 0x00, 0x20, 0x38, 0xBD, 0x9C, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, ++0xF4, 0x9F, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x15, 0x4A, 0x03, 0x88, 0x11, 0x68, 0x40, 0xF6, 0x6C, 0x12, 0x93, 0x42, ++0x08, 0x69, 0x1F, 0xD0, 0x40, 0xF6, 0x85, 0x12, 0x93, 0x42, 0x1B, 0xD0, 0x40, 0xF6, 0x9E, 0x12, 0x93, 0x42, 0x17, 0xD0, ++0x40, 0xF6, 0xA8, 0x12, 0x93, 0x42, 0x13, 0xD0, 0x41, 0xF2, 0x3C, 0x42, 0x93, 0x42, 0x0F, 0xD0, 0x41, 0xF2, 0x64, 0x42, ++0x93, 0x42, 0x0B, 0xD0, 0x41, 0xF2, 0x85, 0x62, 0x93, 0x42, 0x07, 0xD0, 0x41, 0xF2, 0x99, 0x62, 0x93, 0x42, 0x03, 0xD0, ++0x41, 0xF2, 0xAD, 0x62, 0x93, 0x42, 0x02, 0xD1, 0x00, 0xF5, 0x9C, 0x40, 0x20, 0x30, 0x70, 0x47, 0xC8, 0x35, 0x17, 0x00, ++0x08, 0xB5, 0x0C, 0x22, 0x00, 0x21, 0x08, 0x48, 0xDF, 0xF7, 0x48, 0xF8, 0x00, 0x21, 0x02, 0x20, 0x01, 0xF0, 0x44, 0xFE, ++0x05, 0x4B, 0x06, 0x4A, 0x1A, 0x60, 0x03, 0xF1, 0x14, 0x01, 0x00, 0x22, 0x99, 0x60, 0x1A, 0x61, 0x5A, 0x60, 0x08, 0xBD, ++0xF4, 0x9F, 0x17, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xDE, 0xFA, 0xFE, 0xCA, 0x2D, 0xE9, 0xF0, 0x41, 0x2A, 0x4F, 0xBB, 0x7A, ++0x3E, 0x68, 0x03, 0xEB, 0x43, 0x03, 0x06, 0xEB, 0x43, 0x05, 0x82, 0xB0, 0x95, 0xF8, 0x03, 0x80, 0x18, 0xF0, 0x05, 0x0F, ++0x4F, 0xEA, 0x43, 0x04, 0x28, 0xD0, 0x24, 0x4B, 0x1B, 0x68, 0x5B, 0x69, 0x96, 0xF8, 0x6E, 0xC1, 0x95, 0xF9, 0x04, 0x20, ++0x31, 0x5B, 0xA8, 0x78, 0xCD, 0xE9, 0x00, 0x8C, 0xFC, 0xF7, 0x94, 0xFC, 0x7B, 0x68, 0x93, 0xB1, 0xAA, 0x78, 0x31, 0x5B, ++0xDA, 0xB9, 0xA1, 0xF6, 0x6C, 0x10, 0x48, 0x28, 0x0A, 0xD8, 0x40, 0xF6, 0xB4, 0x12, 0x91, 0x42, 0x28, 0xD0, 0x18, 0x48, ++0xA1, 0xF6, 0x67, 0x12, 0xA0, 0xFB, 0x02, 0x12, 0xC2, 0xF3, 0x87, 0x02, 0x9A, 0x70, 0x02, 0x21, 0x08, 0x46, 0x02, 0xB0, ++0xBD, 0xE8, 0xF0, 0x41, 0x01, 0xF0, 0xFA, 0xBD, 0x28, 0x46, 0xFF, 0xF7, 0x7B, 0xFF, 0x03, 0x46, 0xD4, 0xE7, 0x01, 0x2A, ++0x02, 0xD0, 0x00, 0x22, 0x9A, 0x70, 0xEE, 0xE7, 0xA1, 0xF5, 0x9C, 0x51, 0xA1, 0xF1, 0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, ++0x4D, 0x7F, 0xF4, 0xD8, 0x07, 0x4A, 0x08, 0x39, 0xA2, 0xFB, 0x01, 0x12, 0xC2, 0xF3, 0x87, 0x02, 0x9A, 0x70, 0xDE, 0xE7, ++0x0E, 0x22, 0x9A, 0x70, 0xDB, 0xE7, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, ++0x70, 0xB5, 0x0B, 0x4E, 0x0B, 0x4C, 0x33, 0x68, 0x05, 0x46, 0xB3, 0xF8, 0x6C, 0x11, 0x20, 0x46, 0x02, 0xF0, 0x7A, 0xFB, ++0x70, 0x60, 0xFF, 0xF7, 0x95, 0xFF, 0x54, 0xF8, 0x0C, 0x2C, 0xB5, 0xF8, 0x6C, 0x11, 0x01, 0x3A, 0x0A, 0x44, 0x00, 0x21, ++0x44, 0xE9, 0x02, 0x21, 0x70, 0xBD, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0xE8, 0x61, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0xDF, 0xF8, 0xD8, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x93, 0x06, 0x46, 0x93, 0xF8, 0xC0, 0x04, 0x93, 0xF8, ++0x6C, 0x50, 0x88, 0x46, 0x17, 0x46, 0x00, 0x28, 0x52, 0xD1, 0x1B, 0x6C, 0x18, 0x79, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, ++0x1A, 0x21, 0xEE, 0xF7, 0x75, 0xFE, 0x04, 0x46, 0x00, 0x28, 0x4E, 0xD0, 0x28, 0x4A, 0xDF, 0xF8, 0xA8, 0xE0, 0x4F, 0xF4, ++0x1E, 0x71, 0x01, 0xFB, 0x05, 0x21, 0xD0, 0xE9, 0x12, 0x3C, 0x0A, 0x46, 0xBE, 0xF8, 0xFC, 0x51, 0x52, 0xF8, 0x26, 0x0F, ++0xD8, 0x66, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x06, 0x99, 0x40, 0x20, 0x83, 0xF8, 0x68, 0x00, 0x90, 0x88, 0xA3, 0xF8, ++0x70, 0x00, 0xD9, 0xF8, 0x5C, 0x00, 0xB9, 0xF8, 0x60, 0x90, 0xC3, 0xF8, 0x72, 0x00, 0x01, 0x35, 0x90, 0x88, 0xA3, 0xF8, ++0x76, 0x90, 0xAD, 0xB2, 0xD2, 0xF8, 0x00, 0x90, 0xA3, 0xF8, 0x7C, 0x00, 0x00, 0x20, 0x83, 0xF8, 0x69, 0x00, 0x83, 0xF8, ++0x6A, 0x00, 0x83, 0xF8, 0x6B, 0x00, 0xC3, 0xF8, 0x78, 0x90, 0xAE, 0xF8, 0xFC, 0x51, 0x2D, 0x01, 0x83, 0xF8, 0x80, 0x00, ++0x83, 0xF8, 0x81, 0x00, 0xA3, 0xF8, 0x7E, 0x50, 0xCC, 0xF8, 0x20, 0x00, 0x26, 0x77, 0x91, 0xF8, 0x23, 0x30, 0x63, 0x77, ++0xC4, 0xE9, 0x15, 0x87, 0x20, 0x46, 0x05, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xEE, 0xF7, 0x3A, 0xBE, 0x01, 0x20, 0x1A, 0x21, ++0xEE, 0xF7, 0x26, 0xFE, 0x04, 0x46, 0x00, 0x28, 0xB0, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x52, 0x4B, 0x83, 0xB0, 0x1D, 0x68, 0x9B, 0x7A, ++0x01, 0x93, 0x95, 0xF8, 0x70, 0x31, 0x95, 0xF8, 0x6E, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0x8B, 0x80, 0x4D, 0x4B, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x08, 0x38, 0x08, 0xF1, 0x5C, 0x07, 0x05, 0xF1, 0xFD, 0x09, 0x00, 0x26, 0x98, 0xF8, 0xC0, 0x34, ++0x00, 0x2B, 0x7F, 0xD1, 0x01, 0x9B, 0x03, 0xEB, 0x43, 0x03, 0x05, 0xEB, 0x43, 0x03, 0x9B, 0x78, 0x00, 0x2B, 0x77, 0xD1, ++0x95, 0xF8, 0x71, 0x01, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x19, 0xF8, 0x01, 0x3C, 0xB5, 0xF8, 0x6C, 0x11, 0x1A, 0x33, ++0x19, 0x44, 0xEE, 0xF7, 0xE9, 0xFD, 0x4A, 0x46, 0x01, 0x46, 0x00, 0x28, 0x63, 0xD0, 0xD0, 0xE9, 0x12, 0x3C, 0x40, 0x24, ++0x00, 0x20, 0x83, 0xF8, 0x68, 0x40, 0x83, 0xF8, 0x69, 0x00, 0x83, 0xF8, 0x6A, 0x00, 0x83, 0xF8, 0x6B, 0x00, 0x95, 0xF8, ++0x60, 0x01, 0xC0, 0x07, 0x58, 0xD4, 0xD5, 0xF8, 0x60, 0x01, 0xB5, 0xF8, 0x64, 0x41, 0xA3, 0xF8, 0x70, 0x40, 0xD8, 0x66, ++0x05, 0xF5, 0xB0, 0x7A, 0xDF, 0xF8, 0xC0, 0xE0, 0x38, 0x68, 0xBE, 0xF8, 0xFC, 0x41, 0xB7, 0xF8, 0x04, 0xB0, 0xC3, 0xF8, ++0x72, 0x00, 0x01, 0x34, 0xDA, 0xF8, 0x00, 0x00, 0xBA, 0xF8, 0x04, 0xA0, 0xA3, 0xF8, 0x76, 0xB0, 0xA4, 0xB2, 0x4F, 0xF0, ++0x00, 0x0B, 0x98, 0x67, 0xA3, 0xF8, 0x7C, 0xA0, 0xAE, 0xF8, 0xFC, 0x41, 0x83, 0xF8, 0x80, 0xB0, 0x19, 0xF8, 0x01, 0x0C, ++0x83, 0xF8, 0x81, 0x00, 0x19, 0xF8, 0x01, 0x0C, 0x24, 0x01, 0xA3, 0xF8, 0x7E, 0x40, 0x40, 0xB1, 0x81, 0x33, 0x09, 0xEB, ++0x00, 0x04, 0x12, 0xF8, 0x01, 0x0B, 0x03, 0xF8, 0x01, 0x0F, 0xA2, 0x42, 0xF9, 0xD1, 0xB5, 0xF8, 0x6C, 0x21, 0xDC, 0xF8, ++0x28, 0x30, 0x16, 0x48, 0xCC, 0xF8, 0x20, 0x00, 0x9B, 0x1A, 0x00, 0x22, 0xCC, 0xF8, 0x28, 0x30, 0xC1, 0xE9, 0x15, 0x22, ++0x95, 0xF8, 0x6E, 0x31, 0x0B, 0x77, 0xFF, 0x23, 0x4B, 0x77, 0x08, 0x46, 0x05, 0x21, 0xEE, 0xF7, 0x99, 0xFD, 0x95, 0xF8, ++0x70, 0x31, 0x01, 0x36, 0xB3, 0x42, 0x09, 0xF1, 0x21, 0x09, 0x3F, 0xF7, 0x7F, 0xAF, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x01, 0x20, 0x8A, 0xE7, 0x07, 0x48, 0x04, 0x68, 0x80, 0x88, 0xDC, 0x66, 0xA3, 0xF8, 0x70, 0x00, 0x05, 0xF5, 0xB0, 0x7A, ++0xA6, 0xE7, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xAC, 0xB2, 0x15, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x38, 0xB5, 0x02, 0x22, 0x05, 0x46, 0x01, 0x23, 0x40, 0xF6, 0x04, 0x00, 0x01, 0xF0, 0x92, 0xFA, ++0x04, 0x46, 0x02, 0x20, 0x01, 0xF0, 0x30, 0xFD, 0x05, 0x4A, 0x06, 0x49, 0x03, 0x46, 0x04, 0x20, 0x03, 0xF0, 0x40, 0xF9, ++0x25, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0x38, 0x40, 0x01, 0xF0, 0xB2, 0xBA, 0xBC, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, ++0x03, 0x4A, 0x93, 0x7A, 0x10, 0x68, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x43, 0x00, 0x70, 0x47, 0xF4, 0x9F, 0x17, 0x00, ++0xC3, 0x78, 0x13, 0xF0, 0x05, 0x0F, 0x03, 0xD0, 0x02, 0x4B, 0x1B, 0x68, 0x58, 0x69, 0x70, 0x47, 0xFF, 0xF7, 0xE8, 0xBD, ++0xC8, 0x35, 0x17, 0x00, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDA, 0x0C, 0x4B, 0x1B, 0x68, ++0x1B, 0x07, 0x0D, 0xD1, 0x0B, 0x48, 0x0C, 0x49, 0x02, 0x68, 0x4B, 0x68, 0x22, 0xF0, 0x80, 0x02, 0x02, 0x60, 0x23, 0xF0, ++0x04, 0x03, 0x4F, 0xF0, 0x80, 0x60, 0x4B, 0x60, 0x01, 0xF0, 0x3C, 0xBE, 0x06, 0x49, 0x07, 0x48, 0x84, 0x22, 0x03, 0xF0, ++0xFB, 0xBA, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x5A, 0x4A, 0x5B, 0x49, 0x13, 0x68, 0xF0, 0xB4, 0x14, 0x68, 0x5A, 0x4E, ++0x5A, 0x4D, 0x24, 0xF0, 0xFF, 0x04, 0x04, 0x43, 0x14, 0x60, 0x14, 0x68, 0x17, 0x68, 0xC4, 0xF3, 0x09, 0x24, 0x27, 0xF4, ++0x7F, 0x37, 0xDB, 0xB2, 0x00, 0xFB, 0x04, 0xF4, 0x27, 0xF4, 0x40, 0x77, 0xB4, 0xFB, 0xF3, 0xF4, 0x01, 0xEA, 0x04, 0x24, ++0x3C, 0x43, 0x14, 0x60, 0x11, 0x68, 0x14, 0x68, 0xC1, 0xF3, 0x89, 0x41, 0x2C, 0x40, 0x00, 0xFB, 0x01, 0xF1, 0xB1, 0xFB, ++0xF3, 0xF1, 0x06, 0xEA, 0x81, 0x41, 0x21, 0x43, 0x11, 0x60, 0x11, 0x68, 0x49, 0x4E, 0x4A, 0x4C, 0x0D, 0x40, 0x45, 0xF0, ++0x89, 0x65, 0x15, 0x60, 0x32, 0x68, 0x35, 0x68, 0x47, 0x49, 0xC2, 0xF3, 0x0F, 0x22, 0x25, 0xF4, 0x7F, 0x05, 0x25, 0xF4, ++0x7F, 0x45, 0x00, 0xFB, 0x02, 0xF2, 0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x2A, 0x43, 0x32, 0x60, 0x0A, 0x68, ++0x0D, 0x68, 0x40, 0x4C, 0xC2, 0xF3, 0x09, 0x52, 0x25, 0xF0, 0x7F, 0x55, 0x00, 0xFB, 0x02, 0xF2, 0x25, 0xF4, 0x40, 0x15, ++0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x52, 0x2A, 0x43, 0x0A, 0x60, 0x0A, 0x68, 0x0C, 0x68, 0xC2, 0xF3, 0x09, 0x02, ++0x24, 0xF4, 0x7F, 0x74, 0x00, 0xFB, 0x02, 0xF2, 0x24, 0xF0, 0x03, 0x04, 0xB2, 0xFB, 0xF3, 0xF2, 0xC2, 0xF3, 0x09, 0x02, ++0x22, 0x43, 0x1D, 0x28, 0x0A, 0x60, 0x44, 0xD8, 0x4A, 0x68, 0x42, 0xF0, 0x03, 0x02, 0x4A, 0x60, 0x2E, 0x49, 0x2B, 0x4C, ++0x0A, 0x68, 0x2E, 0x4E, 0x0F, 0x68, 0x2E, 0x4D, 0xC2, 0xF3, 0x0F, 0x22, 0x37, 0x40, 0x00, 0xFB, 0x02, 0xF2, 0xB2, 0xFB, ++0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x3A, 0x43, 0x0A, 0x60, 0x2A, 0x68, 0x2F, 0x68, 0xC2, 0xF3, 0x0F, 0x22, 0x00, 0xFB, ++0x02, 0xF2, 0x3E, 0x40, 0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x32, 0x43, 0x2A, 0x60, 0x0A, 0x69, 0x0D, 0x69, ++0x1D, 0x4C, 0xC2, 0xF3, 0x09, 0x52, 0x25, 0xF0, 0x7F, 0x55, 0x00, 0xFB, 0x02, 0xF2, 0x25, 0xF4, 0x40, 0x15, 0xB2, 0xFB, ++0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x52, 0x2A, 0x43, 0x0A, 0x61, 0x0C, 0x69, 0x0A, 0x69, 0xC4, 0xF3, 0x09, 0x04, 0x22, 0xF4, ++0x7F, 0x72, 0x00, 0xFB, 0x04, 0xF0, 0x22, 0xF0, 0x03, 0x02, 0xB0, 0xFB, 0xF3, 0xF0, 0xC0, 0xF3, 0x09, 0x00, 0x10, 0x43, ++0xF0, 0xBC, 0x08, 0x61, 0x70, 0x47, 0x11, 0x49, 0x0A, 0x68, 0x3B, 0x28, 0x22, 0xF0, 0x03, 0x02, 0x94, 0xBF, 0x42, 0xF0, ++0x02, 0x02, 0x42, 0xF0, 0x01, 0x02, 0x0A, 0x60, 0xB2, 0xE7, 0x00, 0xBF, 0xE4, 0x00, 0x32, 0x40, 0x00, 0xFF, 0x03, 0x00, ++0x00, 0x00, 0xFC, 0x0F, 0xFF, 0xFF, 0x03, 0xF0, 0xE8, 0x00, 0x32, 0x40, 0x00, 0xFF, 0xFF, 0x00, 0xEC, 0x00, 0x32, 0x40, ++0x00, 0x00, 0xF0, 0x3F, 0xF4, 0x00, 0x32, 0x40, 0xFF, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x32, 0x40, 0xF0, 0x00, 0x32, 0x40, ++0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2C, 0xDB, 0xF0, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x18, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x18, 0x4B, 0x18, 0x49, 0x1B, 0x68, 0x0E, 0x68, 0x18, 0x4C, ++0x18, 0x4A, 0x19, 0x4D, 0x19, 0x4F, 0x03, 0xF5, 0xC3, 0x43, 0x28, 0x33, 0x70, 0x1C, 0x08, 0x60, 0x23, 0x60, 0x17, 0x4C, ++0x80, 0x23, 0x13, 0x60, 0x2A, 0x68, 0x63, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x43, 0xF0, 0x04, 0x03, 0x2A, 0x60, 0x63, 0x60, ++0x00, 0x23, 0x3B, 0x60, 0x28, 0xB1, 0x09, 0x4B, 0x0E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, ++0x70, 0x47, 0x0B, 0x4B, 0x1B, 0x68, 0x1A, 0x07, 0xCE, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0xD9, 0x22, 0x03, 0xF0, 0xE4, 0xB9, ++0x38, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x44, 0x01, 0x32, 0x40, ++0x88, 0x80, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xD4, 0xA4, 0x15, 0x00, 0x03, 0x4A, 0x01, 0x23, 0x13, 0x60, 0x13, 0x68, 0x13, 0xF0, 0xFF, 0x0F, 0xFB, 0xD1, 0x70, 0x47, ++0x50, 0x80, 0x32, 0x40, 0x70, 0xB5, 0x76, 0x4A, 0x01, 0x23, 0x82, 0xB0, 0x13, 0x60, 0x13, 0x68, 0x13, 0xF0, 0xFF, 0x0F, ++0xFB, 0xD1, 0x73, 0x4B, 0xD3, 0xF8, 0xF0, 0x40, 0xDE, 0xF7, 0x66, 0xFF, 0xA0, 0x47, 0x71, 0x4B, 0x71, 0x49, 0x72, 0x4A, ++0x19, 0x60, 0x13, 0x68, 0x71, 0x49, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x0B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x86, 0x80, 0x6D, 0x48, 0x6E, 0x4B, 0x6A, 0x49, 0x6E, 0x4C, 0x6E, 0x4A, 0x04, 0x60, 0x1A, 0x60, 0x0A, 0x68, ++0x6D, 0x4C, 0x6E, 0x4D, 0x42, 0xF0, 0x80, 0x62, 0x42, 0xF4, 0xF8, 0x62, 0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x62, ++0x0A, 0x60, 0x50, 0xF8, 0x84, 0x2C, 0x69, 0x49, 0xA3, 0xF5, 0x00, 0x43, 0x1C, 0x3B, 0x42, 0xF4, 0x80, 0x32, 0x40, 0xF8, ++0x84, 0x2C, 0x25, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x7F, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x02, 0x1A, 0x60, ++0x1A, 0x68, 0x22, 0xF4, 0xFE, 0x02, 0x42, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x8A, 0x78, 0x2A, 0xB9, 0x1A, 0x68, 0x12, 0x0C, ++0x12, 0x04, 0x42, 0xF0, 0x64, 0x02, 0x1A, 0x60, 0x5A, 0x4B, 0x5B, 0x49, 0x50, 0x4C, 0x5B, 0x4E, 0x5B, 0x4D, 0x00, 0x22, ++0x4F, 0xF4, 0x40, 0x50, 0x08, 0x60, 0x1A, 0x60, 0x0D, 0xF1, 0x06, 0x01, 0x0D, 0xF1, 0x07, 0x00, 0xE0, 0xF7, 0x1C, 0xF9, ++0x9D, 0xF8, 0x07, 0x20, 0x9D, 0xF8, 0x06, 0x00, 0x54, 0x49, 0x13, 0x02, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x43, 0x0B, 0x60, ++0x23, 0x68, 0x52, 0x4A, 0x43, 0xF4, 0x80, 0x53, 0x23, 0x60, 0x23, 0x68, 0x41, 0xF6, 0x25, 0x40, 0x43, 0xF4, 0x00, 0x53, ++0x23, 0x60, 0xC1, 0xF8, 0x70, 0x04, 0x13, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x13, 0x60, 0xDF, 0xF7, 0x77, 0xFD, 0x32, 0x68, ++0x49, 0x49, 0x43, 0x1C, 0x9B, 0x06, 0x22, 0xF0, 0xE0, 0x52, 0x03, 0xF0, 0xE0, 0x53, 0x13, 0x43, 0x33, 0x60, 0x23, 0x68, ++0x45, 0x4A, 0x43, 0xF0, 0x20, 0x03, 0x23, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, ++0x02, 0x03, 0x13, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x23, 0x60, 0x2B, 0x68, 0x99, 0x03, 0x13, 0xD4, 0x3D, 0x4A, ++0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x2A, 0x4B, 0x1B, 0x68, 0xB3, 0xF1, 0xC8, 0x5F, ++0xBF, 0xF4, 0x74, 0xAF, 0x37, 0x49, 0x38, 0x48, 0x40, 0xF2, 0x21, 0x12, 0x03, 0xF0, 0x46, 0xF9, 0x6C, 0xE7, 0xDF, 0xF7, ++0x05, 0xFD, 0x00, 0x28, 0xE7, 0xD0, 0xDF, 0xF7, 0x35, 0xFD, 0x33, 0x4E, 0x32, 0x68, 0x00, 0x02, 0x00, 0xF4, 0xE0, 0x63, ++0x22, 0xF4, 0xE0, 0x62, 0x13, 0x43, 0x33, 0x60, 0x33, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0x33, 0x60, ++0x33, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x33, 0x60, 0x33, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x2B, 0x68, 0x1B, 0x04, ++0x0D, 0xD4, 0x1E, 0x4B, 0x1B, 0x68, 0x9A, 0x03, 0xC7, 0xD5, 0xDF, 0xF7, 0xE9, 0xFC, 0x00, 0x28, 0xC3, 0xD0, 0x22, 0x4A, ++0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE7, 0xDF, 0xF7, 0xB1, 0xFC, 0x00, 0x28, 0xED, 0xD0, 0x23, 0x68, ++0x43, 0xF4, 0x00, 0x23, 0x23, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, 0x80, 0x63, 0x33, 0x60, 0xE2, 0xE7, ++0x50, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0x4C, 0x00, 0x32, 0x40, ++0x38, 0x36, 0x17, 0x00, 0xD8, 0x00, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x10, 0x19, 0x04, 0x00, 0xC0, 0x07, 0xF9, 0x80, ++0x60, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x3C, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, 0x58, 0x01, 0x32, 0x40, ++0x9C, 0x00, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, 0xA0, 0x00, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x00, 0x04, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0x40, 0x88, 0x15, 0x00, 0x50, 0x03, 0x32, 0x40, ++0x05, 0x49, 0x06, 0x4A, 0x0B, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x1D, 0x4A, 0x1E, 0x49, 0x13, 0x68, 0x1E, 0x48, ++0x30, 0xB4, 0x23, 0xF0, 0x80, 0x03, 0x00, 0x25, 0x3C, 0x24, 0x13, 0x60, 0x0D, 0x60, 0x0A, 0x46, 0x04, 0x60, 0x13, 0x68, ++0x1B, 0x07, 0xFC, 0xD1, 0x17, 0x4A, 0x18, 0x49, 0x13, 0x68, 0x18, 0x4D, 0x18, 0x48, 0x19, 0x4C, 0x43, 0xF4, 0x80, 0x33, ++0x13, 0x60, 0x0B, 0x68, 0x02, 0xF5, 0x00, 0x42, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x60, 0x20, 0x32, 0x4F, 0xF0, 0xFF, 0x33, ++0x2B, 0x60, 0x04, 0x60, 0x13, 0x68, 0x12, 0x4C, 0x12, 0x49, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x22, 0x68, 0x4B, 0x68, ++0xA0, 0xF5, 0x00, 0x40, 0x24, 0x38, 0x42, 0xF0, 0x00, 0x42, 0x22, 0x60, 0x02, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x42, 0xF0, ++0x80, 0x02, 0x02, 0x60, 0x30, 0xBC, 0x4B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x38, 0x00, 0x32, 0x40, ++0x54, 0x00, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x7C, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x44, 0xF1, 0x73, 0x0B, ++0x80, 0x80, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x0B, 0x49, 0x0C, 0x4A, 0x0C, 0x4B, 0x10, 0xB4, 0x04, 0x68, 0x80, 0x88, ++0x0C, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x10, 0x60, 0x1A, 0x46, 0x19, 0x60, 0x10, 0x68, 0x81, 0x00, 0xFC, 0xD4, 0xC3, 0x00, ++0x5D, 0xBF, 0x00, 0x0C, 0x10, 0x38, 0xC0, 0xB2, 0xFF, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, 0x38, 0xB5, 0x11, 0x4B, 0x11, 0x48, 0x19, 0x68, 0x42, 0x68, 0x11, 0x4C, ++0x11, 0x4D, 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x23, 0x68, 0x0E, 0x49, ++0x43, 0xF4, 0xE0, 0x63, 0x2A, 0x43, 0x23, 0x60, 0x05, 0x60, 0x01, 0x20, 0x0A, 0x60, 0xF3, 0xF7, 0x51, 0xFB, 0x23, 0x68, ++0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x23, 0x68, 0x43, 0xF4, 0x00, 0x53, 0x23, 0x60, 0x38, 0xBD, ++0x74, 0x80, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x60, 0x00, 0x32, 0x40, ++0x80, 0xEA, 0xE0, 0x72, 0xF0, 0xB4, 0xA2, 0xEB, 0xE0, 0x72, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x16, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x16, 0x4D, 0x16, 0x4B, 0x2E, 0x68, 0x1B, 0x68, 0x16, 0x49, 0x77, 0x1C, 0x00, 0x28, ++0x09, 0x68, 0x2F, 0x60, 0x43, 0xF0, 0x80, 0x73, 0x15, 0xDD, 0x8A, 0x42, 0x18, 0xD8, 0x11, 0x49, 0x0F, 0x4C, 0x0A, 0x68, ++0x10, 0x1A, 0x08, 0x60, 0x23, 0x60, 0x08, 0x60, 0x23, 0x60, 0x08, 0x60, 0x00, 0x20, 0x23, 0x60, 0x2F, 0xB1, 0x08, 0x4B, ++0x2E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, 0x70, 0x47, 0xEA, 0xD0, 0xC9, 0x43, 0x20, 0x32, ++0x91, 0x42, 0xE6, 0xD2, 0x4F, 0xF0, 0xFF, 0x30, 0xEE, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x4C, 0x00, 0x32, 0x40, 0xA4, 0x80, 0x32, 0x40, 0x35, 0x4B, 0x1B, 0x68, 0x70, 0xB5, 0xC3, 0xF3, 0x40, 0x64, 0x9B, 0x01, ++0x12, 0xD4, 0x33, 0x49, 0x33, 0x48, 0x0B, 0x69, 0x33, 0x4A, 0x05, 0x68, 0x08, 0x69, 0xB2, 0xF8, 0xB0, 0x10, 0xB2, 0xF8, ++0xB2, 0x20, 0xA3, 0xF5, 0xFA, 0x63, 0x03, 0xEB, 0x45, 0x13, 0x1B, 0x1A, 0x5B, 0x1A, 0x9B, 0x1A, 0x00, 0x2B, 0x17, 0xDB, ++0x2C, 0x4B, 0x1D, 0x68, 0x9D, 0xB1, 0x28, 0x48, 0x29, 0x4E, 0xEA, 0x68, 0x03, 0x69, 0xB6, 0xF8, 0xB0, 0x40, 0xB6, 0xF8, ++0xB2, 0x10, 0xD3, 0x1A, 0xA3, 0xF5, 0xFA, 0x63, 0x1B, 0x1B, 0x5B, 0x1A, 0x00, 0x2B, 0x07, 0xDB, 0x24, 0x4B, 0x1B, 0x68, ++0x1C, 0x78, 0x01, 0x2C, 0x0B, 0xD0, 0x01, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x12, 0xDB, 0x00, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x18, 0xDB, 0x15, 0x4B, 0x52, 0x1A, 0x4F, 0xF4, 0x80, 0x20, 0x04, 0x21, 0x98, 0x60, 0x1A, 0x63, 0x20, 0x46, 0x99, 0x60, ++0x70, 0xBD, 0x03, 0x69, 0xD2, 0x1A, 0x02, 0xF5, 0x9C, 0x52, 0x08, 0x32, 0x00, 0x2A, 0xE5, 0xDA, 0x12, 0x49, 0x13, 0x48, ++0x40, 0xF2, 0x3E, 0x22, 0x02, 0xF0, 0x92, 0xFF, 0x00, 0x24, 0xD5, 0xE7, 0x03, 0x69, 0xD3, 0x1A, 0x5B, 0x1A, 0x00, 0x2B, ++0xE1, 0xDA, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF2, 0x43, 0x22, 0x02, 0xF0, 0x85, 0xFF, 0xEA, 0x68, 0xB6, 0xF8, 0xB2, 0x10, ++0xD7, 0xE7, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x40, 0x80, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0xD0, 0x9C, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0xA4, 0x15, 0x00, ++0x80, 0x8D, 0x15, 0x00, 0x70, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x0B, 0x4B, 0x0B, 0x49, 0x0C, 0x4D, 0x0E, 0x68, 0x1A, 0x68, 0x28, 0x68, 0x09, 0x68, 0x54, 0x1C, 0xB1, 0x42, ++0x18, 0xBF, 0x28, 0x68, 0x1C, 0x60, 0x2C, 0xB1, 0x03, 0x4C, 0x1A, 0x60, 0x23, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, ++0x70, 0xBC, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x80, 0x32, 0x40, 0xA4, 0x80, 0x32, 0x40, ++0x3B, 0x4A, 0x3C, 0x4B, 0x10, 0xB5, 0x14, 0x68, 0x1C, 0x60, 0x61, 0x05, 0x1D, 0xD4, 0xE2, 0x05, 0x16, 0xD4, 0xA3, 0x05, ++0x10, 0xD4, 0xE0, 0x06, 0x31, 0xD4, 0x37, 0x4B, 0x1A, 0x78, 0x22, 0xB1, 0x14, 0xF0, 0x2F, 0x0F, 0x1C, 0xBF, 0x01, 0x22, ++0x9A, 0x71, 0x34, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0D, 0xDB, 0x10, 0xBD, 0x31, 0x48, 0x02, 0xF0, ++0xAD, 0xFC, 0xFE, 0xE7, 0xF2, 0xF7, 0x96, 0xFD, 0xA3, 0x05, 0xE6, 0xD5, 0xF6, 0xE7, 0x2E, 0x48, 0x02, 0xF0, 0xA4, 0xFC, ++0xFE, 0xE7, 0xE1, 0x07, 0x1C, 0xD4, 0xA2, 0x07, 0x42, 0xD4, 0x63, 0x07, 0x38, 0xD4, 0x20, 0x07, 0x2E, 0xD4, 0x21, 0x06, ++0x24, 0xD4, 0x62, 0x06, 0x1A, 0xD4, 0xA3, 0x06, 0xE3, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x25, 0x49, 0x25, 0x48, 0x40, 0xF2, ++0xB5, 0x22, 0x02, 0xF0, 0xD5, 0xBE, 0x04, 0x20, 0xEC, 0xF7, 0xA4, 0xFD, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xEC, 0xF7, ++0x3F, 0xFE, 0xC4, 0xE7, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0x2B, 0x72, 0x02, 0xF0, 0xC4, 0xBE, ++0xBD, 0xE8, 0x10, 0x40, 0x18, 0x49, 0x1B, 0x48, 0x40, 0xF2, 0xB3, 0x22, 0x02, 0xF0, 0xBC, 0xBE, 0xBD, 0xE8, 0x10, 0x40, ++0x14, 0x49, 0x18, 0x48, 0x40, 0xF2, 0xB1, 0x22, 0x02, 0xF0, 0xB4, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x10, 0x49, 0x15, 0x48, ++0x40, 0xF2, 0xAF, 0x22, 0x02, 0xF0, 0xAC, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x49, 0x12, 0x48, 0x40, 0xF2, 0xAE, 0x22, ++0x02, 0xF0, 0xA4, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x49, 0x0F, 0x48, 0x40, 0xF2, 0xAD, 0x22, 0x02, 0xF0, 0x9C, 0xBE, ++0x84, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x80, 0x35, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x5C, 0xA5, 0x15, 0x00, ++0x28, 0xA5, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x80, 0xA6, 0x15, 0x00, 0x90, 0xA5, 0x15, 0x00, 0x58, 0xA6, 0x15, 0x00, ++0x30, 0xA6, 0x15, 0x00, 0x08, 0xA6, 0x15, 0x00, 0xE0, 0xA5, 0x15, 0x00, 0xB8, 0xA5, 0x15, 0x00, 0x38, 0xB5, 0x62, 0x4A, ++0x62, 0x4B, 0x11, 0x68, 0x1C, 0x68, 0x62, 0x4B, 0x0C, 0x40, 0x23, 0x40, 0x54, 0x60, 0x00, 0x2B, 0x54, 0xD1, 0x60, 0x4B, ++0x23, 0x40, 0x00, 0x2B, 0x4B, 0xD1, 0x62, 0x07, 0x03, 0xD5, 0x5E, 0x4B, 0xD3, 0xF8, 0xDC, 0x30, 0x98, 0x47, 0x23, 0x07, ++0x03, 0xD5, 0x5B, 0x4B, 0xD3, 0xF8, 0xD4, 0x30, 0x98, 0x47, 0xE5, 0x00, 0x2E, 0xD4, 0xE0, 0x05, 0x28, 0xD4, 0x58, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x38, 0xBD, 0x61, 0x02, 0x3C, 0xD4, 0xA2, 0x02, 0x42, 0xD4, ++0x63, 0x06, 0x48, 0xD4, 0xE5, 0x04, 0x4E, 0xD4, 0xA0, 0x04, 0x54, 0xD4, 0x61, 0x04, 0x5A, 0xD4, 0x22, 0x04, 0x60, 0xD4, ++0xE3, 0x03, 0x66, 0xD4, 0xA5, 0x03, 0x6C, 0xD4, 0xE0, 0x01, 0x72, 0xD4, 0xA1, 0x01, 0x78, 0xD4, 0xE2, 0x02, 0x7E, 0xD4, ++0x23, 0x01, 0xE4, 0xD5, 0xBD, 0xE8, 0x38, 0x40, 0x47, 0x49, 0x48, 0x48, 0x40, 0xF2, 0x19, 0x32, 0x02, 0xF0, 0x38, 0xBE, ++0x46, 0x48, 0x02, 0xF0, 0xED, 0xFB, 0xD2, 0xE7, 0x45, 0x4B, 0x46, 0x4A, 0x1D, 0x68, 0x93, 0x7F, 0x05, 0xF0, 0x3F, 0x01, ++0x0B, 0x43, 0x4F, 0xF4, 0x00, 0x20, 0x93, 0x77, 0x01, 0xF0, 0x64, 0xF9, 0x41, 0x4B, 0x1D, 0x60, 0xC1, 0xE7, 0x4F, 0xF0, ++0x80, 0x70, 0x01, 0xF0, 0x5D, 0xF9, 0xAE, 0xE7, 0x4F, 0xF0, 0x00, 0x70, 0x01, 0xF0, 0x58, 0xF9, 0xA5, 0xE7, 0xBD, 0xE8, ++0x38, 0x40, 0x35, 0x49, 0x3A, 0x48, 0x40, 0xF2, 0x0B, 0x32, 0x02, 0xF0, 0x13, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x31, 0x49, ++0x37, 0x48, 0x4F, 0xF4, 0x43, 0x72, 0x02, 0xF0, 0x0B, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x2D, 0x49, 0x34, 0x48, 0x40, 0xF2, ++0x0D, 0x32, 0x02, 0xF0, 0x03, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x29, 0x49, 0x31, 0x48, 0x4F, 0xF4, 0x44, 0x72, 0x02, 0xF0, ++0xFB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x25, 0x49, 0x2E, 0x48, 0x40, 0xF2, 0x11, 0x32, 0x02, 0xF0, 0xF3, 0xBD, 0xBD, 0xE8, ++0x38, 0x40, 0x21, 0x49, 0x2B, 0x48, 0x40, 0xF2, 0x12, 0x32, 0x02, 0xF0, 0xEB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x1D, 0x49, ++0x28, 0x48, 0x40, 0xF2, 0x13, 0x32, 0x02, 0xF0, 0xE3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x19, 0x49, 0x25, 0x48, 0x4F, 0xF4, ++0x45, 0x72, 0x02, 0xF0, 0xDB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x15, 0x49, 0x22, 0x48, 0x40, 0xF2, 0x15, 0x32, 0x02, 0xF0, ++0xD3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x11, 0x49, 0x1F, 0x48, 0x40, 0xF2, 0x16, 0x32, 0x02, 0xF0, 0xCB, 0xBD, 0xBD, 0xE8, ++0x38, 0x40, 0x0D, 0x49, 0x1C, 0x48, 0x40, 0xF2, 0x17, 0x32, 0x02, 0xF0, 0xC3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x09, 0x49, ++0x19, 0x48, 0x4F, 0xF4, 0x46, 0x72, 0x02, 0xF0, 0xBB, 0xBD, 0x00, 0xBF, 0x6C, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, ++0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x08, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x10, 0xA9, 0x15, 0x00, 0xA8, 0xA6, 0x15, 0x00, 0x90, 0x80, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x94, 0x80, 0x32, 0x40, ++0xD8, 0xA6, 0x15, 0x00, 0x00, 0xA7, 0x15, 0x00, 0x34, 0xA7, 0x15, 0x00, 0x68, 0xA7, 0x15, 0x00, 0x90, 0xA7, 0x15, 0x00, ++0xC0, 0xA7, 0x15, 0x00, 0xF0, 0xA7, 0x15, 0x00, 0x20, 0xA8, 0x15, 0x00, 0x50, 0xA8, 0x15, 0x00, 0x80, 0xA8, 0x15, 0x00, ++0xB4, 0xA8, 0x15, 0x00, 0xE8, 0xA8, 0x15, 0x00, 0x10, 0xB5, 0x18, 0x4B, 0x84, 0xB0, 0xD3, 0xF8, 0x20, 0x32, 0x8D, 0xF8, ++0x07, 0x00, 0x0D, 0xF1, 0x0F, 0x02, 0x0D, 0xF1, 0x0E, 0x01, 0x0D, 0xF1, 0x07, 0x00, 0x98, 0x47, 0x12, 0x4A, 0x13, 0x49, ++0x13, 0x68, 0x9D, 0xF8, 0x0E, 0x40, 0x91, 0xF8, 0xBA, 0x00, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x04, 0x23, 0x13, 0x60, ++0x18, 0xB1, 0x0E, 0x4B, 0x93, 0xF8, 0x2A, 0x30, 0x4B, 0xB1, 0x0A, 0x4A, 0x9D, 0xF8, 0x0F, 0x10, 0x13, 0x68, 0x23, 0xF0, ++0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x04, 0xB0, 0x10, 0xBD, 0x13, 0x68, 0x91, 0xF8, 0xBB, 0x10, 0x23, 0xF0, 0xFF, 0x03, ++0x0B, 0x43, 0x13, 0x60, 0x04, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0x30, 0xB5, 0x90, 0xF9, 0x65, 0x50, 0x7F, 0x2D, 0x83, 0xB0, 0x0E, 0xD0, 0x90, 0xF9, 0x66, 0x30, ++0x0B, 0x48, 0x9D, 0x42, 0xA8, 0xBF, 0x1D, 0x46, 0x8D, 0xF8, 0x07, 0x50, 0xD0, 0xF8, 0x20, 0x32, 0x0D, 0xF1, 0x07, 0x00, ++0x98, 0x47, 0x03, 0xB0, 0x30, 0xBD, 0x0C, 0x46, 0x05, 0x49, 0x13, 0x46, 0x0A, 0x68, 0x12, 0x0A, 0x22, 0x70, 0x0A, 0x68, ++0x1A, 0x70, 0x03, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x91, 0xF9, 0x00, 0x30, ++0x7F, 0x2B, 0x40, 0xD0, 0xF0, 0xB5, 0x20, 0x4E, 0x90, 0xF9, 0x65, 0x70, 0xD6, 0xF8, 0x20, 0x32, 0x85, 0xB0, 0x0C, 0x46, ++0x05, 0x46, 0x11, 0x46, 0x20, 0x46, 0x0D, 0xF1, 0x0F, 0x02, 0x01, 0x91, 0x98, 0x47, 0x94, 0xF9, 0x00, 0x30, 0x95, 0xF9, ++0x66, 0x20, 0x85, 0xF8, 0x65, 0x30, 0x93, 0x42, 0x20, 0xDC, 0x94, 0xF9, 0x00, 0x30, 0xBB, 0x42, 0x1A, 0xD0, 0xD5, 0xF8, ++0xE4, 0x30, 0x43, 0xB1, 0x93, 0xF8, 0x56, 0x21, 0x42, 0xF0, 0x10, 0x02, 0x83, 0xF8, 0x56, 0x21, 0x1B, 0x68, 0x00, 0x2B, ++0xF6, 0xD1, 0x28, 0x6C, 0x60, 0xB1, 0xD6, 0xF8, 0xB4, 0x30, 0x98, 0x47, 0x28, 0x46, 0xFC, 0xF7, 0x5D, 0xFC, 0x28, 0xB1, ++0x2A, 0x6C, 0xD6, 0xF8, 0x3C, 0x33, 0x92, 0xF9, 0x0C, 0x00, 0x98, 0x47, 0x05, 0xB0, 0xF0, 0xBD, 0x22, 0x70, 0x01, 0x99, ++0xD6, 0xF8, 0x20, 0x32, 0x0D, 0xF1, 0x0F, 0x02, 0x20, 0x46, 0x98, 0x47, 0xD5, 0xE7, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0x10, 0xB5, 0x15, 0x4B, 0x82, 0xB0, 0x0C, 0x46, 0xD3, 0xF8, 0x38, 0x33, 0x0D, 0xF1, 0x07, 0x02, 0x0D, 0xF1, 0x06, 0x01, ++0x98, 0x47, 0xE2, 0x6C, 0x10, 0x4B, 0x94, 0x6B, 0x93, 0xF8, 0xBD, 0x30, 0x61, 0x69, 0xC1, 0xF3, 0xC2, 0x20, 0xC9, 0xB2, ++0x6B, 0xB9, 0x01, 0xF0, 0x7C, 0x01, 0x50, 0xEA, 0x01, 0x03, 0x0C, 0xBF, 0x9D, 0xF8, 0x06, 0x30, 0x9D, 0xF8, 0x07, 0x30, ++0x43, 0xEA, 0x03, 0x23, 0x63, 0x62, 0x02, 0xB0, 0x10, 0xBD, 0x01, 0xF0, 0x7F, 0x01, 0xDF, 0xF7, 0xB1, 0xFA, 0x40, 0xEA, ++0x00, 0x20, 0x60, 0x62, 0x02, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x00, 0x29, 0x11, 0xDD, ++0x10, 0xB4, 0x01, 0x39, 0x00, 0x23, 0x01, 0x24, 0x10, 0xF0, 0x01, 0x0F, 0x1C, 0xBF, 0x04, 0xFA, 0x01, 0xF2, 0x13, 0x43, ++0x01, 0x39, 0x4F, 0xEA, 0x50, 0x00, 0xF5, 0xD2, 0x18, 0x46, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x23, 0x18, 0x46, ++0x70, 0x47, 0x00, 0xBF, 0x0B, 0x1F, 0x03, 0x44, 0x01, 0x44, 0x03, 0xF8, 0x01, 0x2B, 0x8B, 0x42, 0x4F, 0xEA, 0x12, 0x22, ++0xF9, 0xD1, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x8D, 0x88, 0x0C, 0x7D, 0x00, 0x95, 0x0D, 0x68, 0x01, 0x95, ++0x03, 0x93, 0x1C, 0xB1, 0x0B, 0x69, 0xAB, 0x42, 0x00, 0xF0, 0xAC, 0x81, 0x01, 0x9B, 0xD9, 0x4F, 0x9C, 0xB2, 0x4F, 0xEA, ++0x13, 0x4C, 0xCC, 0x80, 0xA1, 0xF8, 0x08, 0xC0, 0x53, 0x78, 0x16, 0x78, 0x46, 0xEA, 0x03, 0x26, 0x4E, 0x81, 0xD3, 0x78, ++0x95, 0x78, 0x45, 0xEA, 0x03, 0x25, 0x8D, 0x81, 0x92, 0xF8, 0x05, 0xE0, 0x13, 0x79, 0x43, 0xEA, 0x0E, 0x23, 0xCB, 0x81, ++0x4F, 0xF0, 0x00, 0x09, 0x09, 0xF0, 0x01, 0x0A, 0x00, 0xEB, 0x4A, 0x02, 0x10, 0xF8, 0x1A, 0x80, 0x92, 0xF8, 0x01, 0xE0, ++0x02, 0x92, 0x48, 0xEA, 0x0E, 0x22, 0x5A, 0x40, 0x4F, 0xEA, 0x12, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, ++0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x4F, 0xEA, 0x4A, 0x08, 0x14, 0x44, ++0x08, 0xF1, 0x04, 0x02, 0xA4, 0xB2, 0x00, 0xEB, 0x02, 0x0E, 0xCC, 0x80, 0x82, 0x5C, 0x9E, 0xF8, 0x01, 0xE0, 0x42, 0xEA, ++0x0E, 0x2E, 0x84, 0xEA, 0x0E, 0x0E, 0xCE, 0xF3, 0x0F, 0x22, 0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x12, 0x20, 0x37, 0xF8, ++0x1E, 0xB0, 0x4F, 0xEA, 0x12, 0x2E, 0x4E, 0xEA, 0x02, 0x2E, 0x8E, 0xEA, 0x0B, 0x0B, 0xDC, 0x44, 0x08, 0xF1, 0x08, 0x0E, ++0x1F, 0xFA, 0x8C, 0xFC, 0x00, 0xEB, 0x0E, 0x02, 0xA1, 0xF8, 0x08, 0xC0, 0x10, 0xF8, 0x0E, 0xE0, 0x52, 0x78, 0x4E, 0xEA, ++0x02, 0x22, 0x8C, 0xEA, 0x02, 0x02, 0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, 0x12, 0xB0, ++0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x0B, 0x0B, 0x08, 0xF1, 0x0C, 0x08, 0x5E, 0x44, 0x00, 0xEB, ++0x08, 0x02, 0xB6, 0xB2, 0x4E, 0x81, 0x92, 0xF8, 0x01, 0xE0, 0x10, 0xF8, 0x08, 0x20, 0x42, 0xEA, 0x0E, 0x22, 0x72, 0x40, ++0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, 0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, ++0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x15, 0x44, 0xAD, 0xB2, 0x02, 0x9A, 0x8D, 0x81, 0x92, 0xF8, 0x01, 0xE0, 0x10, 0xF8, ++0x1A, 0x20, 0x42, 0xEA, 0x0E, 0x22, 0x6A, 0x40, 0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, ++0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x19, 0xFA, 0x82, 0xF2, 0x13, 0x44, ++0x09, 0xF1, 0x01, 0x09, 0x9B, 0xB2, 0xB9, 0xF1, 0x08, 0x0F, 0xCB, 0x81, 0x7F, 0xF4, 0x6E, 0xAF, 0x01, 0x9A, 0x0A, 0x61, ++0x4F, 0xF0, 0x01, 0x0E, 0x81, 0xF8, 0x14, 0xE0, 0x00, 0x9A, 0x90, 0xF8, 0x01, 0x80, 0x90, 0xF8, 0x00, 0xE0, 0x90, 0xF8, ++0x03, 0x90, 0x1A, 0x44, 0x4E, 0xEA, 0x08, 0x2E, 0x92, 0xB2, 0x82, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x28, 0x5F, 0xFA, ++0x8E, 0xFE, 0x37, 0xF8, 0x18, 0xA0, 0x37, 0xF8, 0x1E, 0x80, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, ++0x08, 0x0A, 0x90, 0xF8, 0x02, 0x80, 0x90, 0xF8, 0x05, 0xE0, 0x54, 0x44, 0xA4, 0xB2, 0x48, 0xEA, 0x09, 0x28, 0x84, 0xEA, ++0x08, 0x08, 0x4F, 0xEA, 0x18, 0x2A, 0x5F, 0xFA, 0x88, 0xF8, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x18, 0x90, 0x4F, 0xEA, ++0x1A, 0x28, 0x48, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x04, 0x90, 0x90, 0xF8, 0x07, 0x80, 0xD4, 0x44, ++0x1F, 0xFA, 0x8C, 0xFC, 0x49, 0xEA, 0x0E, 0x2E, 0x8C, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, 0x5F, 0xFA, 0x8E, 0xFE, ++0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x1E, 0x90, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, ++0x90, 0xF8, 0x06, 0x90, 0x90, 0xF8, 0x09, 0xE0, 0x56, 0x44, 0xB6, 0xB2, 0x49, 0xEA, 0x08, 0x28, 0x86, 0xEA, 0x08, 0x08, ++0x4F, 0xEA, 0x18, 0x2A, 0x5F, 0xFA, 0x88, 0xF8, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x18, 0x90, 0x4F, 0xEA, 0x1A, 0x28, ++0x48, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x08, 0x90, 0x90, 0xF8, 0x0B, 0x80, 0x55, 0x44, 0xAD, 0xB2, ++0x49, 0xEA, 0x0E, 0x2E, 0x85, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, 0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x1A, 0xA0, ++0x37, 0xF8, 0x1E, 0x90, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x0A, 0xE0, ++0x90, 0xF8, 0x0D, 0x90, 0x53, 0x44, 0x9B, 0xB2, 0x4E, 0xEA, 0x08, 0x2E, 0x83, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, ++0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x1E, 0x80, 0x07, 0x7B, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, ++0x0A, 0x2E, 0x8E, 0xEA, 0x08, 0x08, 0x42, 0x44, 0x92, 0xB2, 0x47, 0xEA, 0x09, 0x29, 0x82, 0xEA, 0x09, 0x07, 0xFF, 0x03, ++0x82, 0xEA, 0x09, 0x09, 0x90, 0xF8, 0x0F, 0xE0, 0x47, 0xEA, 0x59, 0x09, 0x87, 0x7B, 0x4C, 0x44, 0xA4, 0xB2, 0x47, 0xEA, ++0x0E, 0x27, 0x84, 0xEA, 0x07, 0x0E, 0x4F, 0xEA, 0xCE, 0x3E, 0x67, 0x40, 0x4E, 0xEA, 0x57, 0x07, 0x67, 0x44, 0xBF, 0xB2, ++0x4F, 0xEA, 0xC7, 0x3C, 0x4C, 0xEA, 0x57, 0x0C, 0x66, 0x44, 0xB6, 0xB2, 0x4F, 0xEA, 0xC6, 0x3C, 0x4C, 0xEA, 0x56, 0x0C, ++0x65, 0x44, 0xAD, 0xB2, 0x4F, 0xEA, 0xC5, 0x3C, 0x4C, 0xEA, 0x55, 0x0C, 0x63, 0x44, 0x1F, 0xFA, 0x83, 0xF9, 0x00, 0x9B, ++0xAD, 0xF8, 0x18, 0x60, 0x4F, 0xEA, 0x13, 0x2E, 0x0E, 0xF0, 0x7F, 0x0C, 0xAD, 0xF8, 0x16, 0x70, 0xAD, 0xF8, 0x1A, 0x50, ++0x03, 0x9E, 0x00, 0x9D, 0xB5, 0x70, 0x4C, 0xF0, 0x20, 0x0C, 0x86, 0xF8, 0x00, 0xE0, 0x86, 0xF8, 0x01, 0xC0, 0x4F, 0xEA, ++0xC9, 0x38, 0x45, 0x78, 0x03, 0x78, 0xAD, 0xF8, 0x1C, 0x90, 0x48, 0xEA, 0x59, 0x08, 0x42, 0x44, 0x92, 0xB2, 0x43, 0xEA, ++0x05, 0x23, 0xAD, 0xF8, 0x1E, 0x20, 0x5A, 0x40, 0x52, 0x08, 0xF2, 0x70, 0x33, 0x46, 0x06, 0xF1, 0x0C, 0x00, 0x05, 0xAA, ++0x01, 0xE0, 0x32, 0xF8, 0x02, 0x4F, 0x1C, 0x71, 0x25, 0x0A, 0x5D, 0x71, 0x02, 0x33, 0x98, 0x42, 0xF7, 0xD1, 0x00, 0x23, ++0x0B, 0x75, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xCC, 0x88, 0xB1, 0xF8, 0x08, 0xC0, 0x4E, 0x89, 0x8D, 0x89, 0xCB, 0x89, ++0x00, 0x4F, 0xFD, 0xE6, 0x50, 0xA9, 0x15, 0x00, 0xF0, 0xB4, 0x13, 0x4F, 0x01, 0x22, 0x3C, 0x1F, 0x00, 0x23, 0xC7, 0xF8, ++0x00, 0x24, 0xC7, 0xF8, 0x04, 0x34, 0x22, 0x46, 0x42, 0xF8, 0x04, 0x3F, 0x01, 0x33, 0xB3, 0xF5, 0x80, 0x7F, 0xF9, 0xD1, ++0x00, 0x23, 0xDF, 0xF8, 0x30, 0xC0, 0x1D, 0x46, 0xC2, 0x5C, 0x54, 0xF8, 0x04, 0x6F, 0x2A, 0x44, 0x32, 0x44, 0xD5, 0xB2, ++0x01, 0x33, 0x57, 0xF8, 0x25, 0x20, 0x22, 0x60, 0x8B, 0x42, 0xA8, 0xBF, 0x00, 0x23, 0xA4, 0x45, 0x47, 0xF8, 0x25, 0x60, ++0xEE, 0xD1, 0x00, 0x20, 0xF0, 0xBC, 0x70, 0x47, 0x18, 0x2C, 0x17, 0x00, 0x14, 0x30, 0x17, 0x00, 0x71, 0xB3, 0x18, 0x4B, ++0xF0, 0xB5, 0xD3, 0xF8, 0x00, 0x54, 0xD3, 0xF8, 0x04, 0x24, 0x53, 0xF8, 0x25, 0x60, 0x32, 0x44, 0x01, 0x39, 0xD2, 0xB2, ++0x89, 0xB2, 0x01, 0x31, 0x53, 0xF8, 0x22, 0x40, 0x01, 0x44, 0x6F, 0x1C, 0x43, 0xF8, 0x22, 0x60, 0x43, 0xF8, 0x25, 0x40, ++0xFD, 0xB2, 0x34, 0x44, 0xE4, 0xB2, 0x53, 0xF8, 0x25, 0x60, 0x53, 0xF8, 0x24, 0x70, 0x10, 0xF8, 0x01, 0x4B, 0x02, 0xEB, ++0x06, 0x0C, 0x96, 0x46, 0x5F, 0xFA, 0x8C, 0xF2, 0x67, 0x40, 0x88, 0x42, 0x53, 0xF8, 0x22, 0x40, 0x00, 0xF8, 0x01, 0x7C, ++0xE5, 0xD1, 0xC3, 0xF8, 0x00, 0x54, 0xC3, 0xF8, 0x04, 0xE4, 0xF0, 0xBD, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x2C, 0x17, 0x00, ++0xFF, 0xF7, 0xCA, 0xBF, 0x83, 0x68, 0x8A, 0x68, 0x03, 0x48, 0x9B, 0x1A, 0x83, 0x42, 0x94, 0xBF, 0x00, 0x20, 0x01, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0xA3, 0xE1, 0x11, 0x83, 0x88, 0xB3, 0xEB, 0x11, 0x4F, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, ++0xC0, 0x88, 0x89, 0xB2, 0x40, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, ++0xDF, 0xF8, 0x4C, 0xB1, 0xDB, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0x46, 0x89, 0x46, 0x15, 0x46, ++0x5E, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, ++0x2C, 0x81, 0xDF, 0xF8, 0x2C, 0xA1, 0xD8, 0xF8, 0x00, 0x30, 0xDA, 0xF8, 0x14, 0x60, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, ++0x1E, 0xB1, 0xB3, 0x88, 0xBB, 0x42, 0x40, 0xD0, 0x00, 0x26, 0x37, 0x49, 0x37, 0x48, 0x49, 0xEA, 0x07, 0x42, 0x00, 0xF0, ++0xF5, 0xF9, 0x04, 0x46, 0x00, 0x28, 0x47, 0xD0, 0x34, 0x4B, 0x35, 0x4A, 0x1B, 0x69, 0x32, 0x48, 0x1D, 0x44, 0xA5, 0x60, ++0x21, 0x46, 0x00, 0xF0, 0x87, 0xFE, 0x9E, 0xB9, 0xDA, 0xF8, 0x14, 0x30, 0xA3, 0x42, 0x13, 0xD0, 0xD8, 0xF8, 0x00, 0x30, ++0x2B, 0xB1, 0x29, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x8B, 0xB1, 0x29, 0x4B, 0x1A, 0x69, 0xAD, 0x1A, ++0x00, 0x2D, 0x14, 0xDB, 0xBD, 0xE8, 0xF8, 0x8F, 0xDA, 0xF8, 0x14, 0x40, 0x00, 0x2C, 0xEB, 0xD0, 0x25, 0x4B, 0xA1, 0x68, ++0xD3, 0xF8, 0xE0, 0x31, 0x24, 0x48, 0x98, 0x47, 0xE4, 0xE7, 0x00, 0x2A, 0xEB, 0xD0, 0x62, 0xB6, 0x1E, 0x4B, 0x1A, 0x69, ++0xAD, 0x1A, 0x00, 0x2D, 0xEA, 0xDA, 0xBD, 0xE8, 0xF8, 0x4F, 0x4F, 0xF0, 0x00, 0x50, 0x00, 0xF0, 0x29, 0xBD, 0xF6, 0x88, ++0xA6, 0xEB, 0x09, 0x06, 0xB6, 0xFA, 0x86, 0xF6, 0x76, 0x09, 0xB8, 0xE7, 0xB2, 0xB1, 0x19, 0x4B, 0x9A, 0x42, 0x9C, 0xD9, ++0x18, 0x49, 0x19, 0x48, 0x94, 0x22, 0x02, 0xF0, 0x0F, 0xFA, 0x96, 0xE7, 0x0C, 0x20, 0x00, 0xF0, 0xFB, 0xF9, 0xDB, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x09, 0xDB, 0xA7, 0x80, 0xA4, 0xF8, 0x06, 0x90, 0xA9, 0xE7, ++0x0E, 0x49, 0x10, 0x48, 0x93, 0x22, 0x02, 0xF0, 0xFB, 0xF9, 0x82, 0xE7, 0x00, 0x28, 0xF3, 0xD1, 0x0A, 0x49, 0x0D, 0x48, ++0xA5, 0x22, 0x02, 0xF0, 0xF3, 0xF9, 0xED, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x59, 0x26, 0x14, 0x00, 0x94, 0xB6, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x41, 0x26, 0x14, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0xB6, 0x17, 0x00, 0xFF, 0xA2, 0xE1, 0x11, ++0x70, 0x79, 0x15, 0x00, 0x5C, 0xAB, 0x15, 0x00, 0x50, 0xAB, 0x15, 0x00, 0x78, 0xAB, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0xF8, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x25, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x25, 0x4D, 0x25, 0x4E, 0x2B, 0x68, 0x74, 0x69, 0x01, 0x33, 0x2B, 0x60, 0x74, 0xB1, ++0xA3, 0x88, 0x83, 0x42, 0x02, 0xD1, 0xE3, 0x88, 0x8B, 0x42, 0x11, 0xD0, 0x41, 0xEA, 0x00, 0x42, 0x1F, 0x49, 0x20, 0x48, ++0x00, 0xF0, 0x54, 0xF9, 0x04, 0x46, 0x38, 0xBB, 0x2B, 0x68, 0x33, 0xB1, 0x18, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xF8, 0xBD, 0x06, 0xF1, 0x14, 0x00, 0x00, 0xF0, 0x98, 0xFD, 0x77, 0x69, 0x17, 0x4B, ++0xDF, 0xB1, 0xD3, 0xF8, 0xE0, 0x31, 0xB9, 0x68, 0x06, 0xF1, 0x20, 0x00, 0x98, 0x47, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x0A, 0xDA, 0x12, 0x4A, 0xBB, 0x68, 0x12, 0x69, 0x9B, 0x1A, 0x00, 0x2B, 0x04, 0xDA, 0x10, 0x49, ++0x10, 0x48, 0xE7, 0x22, 0x02, 0xF0, 0x8E, 0xF9, 0x20, 0x46, 0x00, 0xF0, 0xED, 0xF9, 0x2B, 0x68, 0xD3, 0xE7, 0xD3, 0xF8, ++0xD8, 0x31, 0x06, 0xF1, 0x20, 0x00, 0x98, 0x47, 0xF4, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x80, 0xB6, 0x17, 0x00, 0x59, 0x26, 0x14, 0x00, 0x94, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, 0x80, 0xAB, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x28, 0x4D, 0x29, 0x4F, ++0xDF, 0xF8, 0xB0, 0x80, 0x28, 0x4E, 0xDF, 0xF8, 0xB0, 0x90, 0x21, 0xE0, 0xA1, 0x68, 0x33, 0x69, 0xCB, 0x1A, 0x32, 0x2B, ++0x07, 0xD4, 0xD9, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0xA3, 0x68, 0x32, 0x69, 0x9B, 0x1A, 0x00, 0x2B, 0x30, 0xDA, 0x21, 0x48, ++0x00, 0xF0, 0x44, 0xFD, 0x2B, 0x68, 0x04, 0x46, 0x5A, 0x1E, 0x2B, 0xB1, 0xD8, 0xF8, 0x00, 0x30, 0x2A, 0x60, 0x0A, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0xA0, 0x88, 0xE1, 0x88, 0xFF, 0x22, 0x00, 0xF0, 0xCB, 0xF8, 0x20, 0x46, 0x00, 0xF0, 0xA4, 0xF9, ++0x4F, 0xF0, 0x00, 0x50, 0x00, 0xF0, 0x6C, 0xFC, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, ++0xC8, 0xF8, 0x00, 0x30, 0x2A, 0x68, 0x7C, 0x69, 0x10, 0x48, 0x53, 0x1C, 0x2B, 0x60, 0x00, 0x2C, 0xCA, 0xD1, 0x2B, 0xB1, ++0x0E, 0x4B, 0x2A, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x2B, 0x68, 0x00, 0x2B, ++0xFA, 0xD0, 0x09, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0xF4, 0xD1, 0x00, 0x2A, 0xF2, 0xD0, 0xF0, 0xE7, ++0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x94, 0xB6, 0x17, 0x00, 0xA0, 0xB6, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x0E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0E, 0x4D, 0x0E, 0x4C, 0x2B, 0x68, 0x4F, 0xF0, 0x00, 0x50, 0x01, 0x33, 0x2B, 0x60, ++0x00, 0xF0, 0x28, 0xFC, 0x01, 0xE0, 0x00, 0xF0, 0x59, 0xF9, 0x20, 0x46, 0x00, 0xF0, 0xE4, 0xFC, 0x00, 0x28, 0xF8, 0xD1, ++0x2B, 0x68, 0x33, 0xB1, 0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x94, 0xB6, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x80, 0x46, 0x03, 0xF1, ++0x0C, 0x00, 0x1D, 0x46, 0x0F, 0x46, 0x16, 0x46, 0x00, 0xF0, 0xC8, 0xF8, 0x0F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0x46, 0x0F, 0xDB, 0x00, 0x21, 0xA4, 0xF8, 0x04, 0x80, 0x04, 0xF1, 0x0C, 0x08, 0xE7, 0x80, 0x26, 0x81, ++0x65, 0x81, 0x2A, 0x46, 0x21, 0x60, 0x40, 0x46, 0xDD, 0xF7, 0xDC, 0xFB, 0x40, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x28, ++0xED, 0xD1, 0x04, 0x49, 0x04, 0x48, 0x52, 0x22, 0x02, 0xF0, 0xBA, 0xF8, 0xE7, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, 0x16, 0x4B, 0x1A, 0x68, 0x30, 0xF8, 0x06, 0x3C, 0xB2, 0xF9, 0x00, 0x10, ++0x00, 0x29, 0x10, 0xB5, 0xDA, 0xB2, 0x04, 0x46, 0x0C, 0xDB, 0x0B, 0x2A, 0x13, 0xD8, 0x11, 0x48, 0xA4, 0xF1, 0x0C, 0x01, ++0x00, 0xF0, 0x4C, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0xA4, 0xBB, 0x0D, 0x2A, 0xF0, 0xD9, ++0x0B, 0x49, 0x0C, 0x48, 0xBB, 0x22, 0x02, 0xF0, 0x93, 0xF8, 0x34, 0xF8, 0x06, 0x3C, 0x34, 0xF8, 0x04, 0x2C, 0x34, 0xF8, ++0x08, 0x1C, 0x08, 0x48, 0x01, 0xF0, 0x10, 0xFE, 0xA4, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0xF0, 0xDE, 0xB8, ++0x38, 0x36, 0x17, 0x00, 0x84, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0xB4, 0xAB, 0x15, 0x00, ++0x08, 0xB5, 0x00, 0x23, 0xFF, 0xF7, 0x94, 0xFF, 0xBD, 0xE8, 0x08, 0x40, 0xFF, 0xF7, 0xC0, 0xBF, 0x10, 0xB4, 0x5D, 0xF8, ++0x04, 0x4B, 0x20, 0xF8, 0x08, 0x1C, 0x20, 0xF8, 0x06, 0x2C, 0x20, 0xF8, 0x04, 0x3C, 0xFF, 0xF7, 0xB5, 0xBF, 0x00, 0xBF, ++0x00, 0xF0, 0xC6, 0xB8, 0x2D, 0xE9, 0xF0, 0x41, 0x04, 0x68, 0xD4, 0xB1, 0x07, 0x46, 0x0D, 0x46, 0x16, 0x46, 0x4F, 0xF0, ++0x00, 0x08, 0x02, 0xE0, 0xA0, 0x46, 0x93, 0xB1, 0x1C, 0x46, 0x31, 0x46, 0x20, 0x46, 0xA8, 0x47, 0x23, 0x68, 0x00, 0x28, ++0xF6, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0x0C, 0xD0, 0xC8, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x5B, 0xB1, 0x00, 0x23, 0x23, 0x60, ++0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x24, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x3B, 0x60, 0x00, 0x2B, 0xF3, 0xD1, ++0xC7, 0xF8, 0x04, 0x80, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x0F, 0x48, 0x30, 0xB4, 0x20, 0xF0, 0x03, 0x00, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4A, 0x0C, 0x4B, ++0x11, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x4C, 0x1C, 0x1B, 0x1A, 0x00, 0x25, 0x14, 0x60, 0xC0, 0xE9, 0x00, 0x53, 0x2C, 0xB1, ++0x04, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x03, 0xA0, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0xF8, 0xB5, 0x31, 0x4F, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x03, 0x30, 0x20, 0xF0, 0x03, 0x04, 0x00, 0x2B, 0x04, 0xF1, 0x04, 0x06, 0x48, 0xDB, 0x2C, 0x4B, 0xDB, 0x69, ++0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2A, 0x4A, 0x01, 0x21, 0x11, 0x60, 0x29, 0x4D, 0x2A, 0x68, ++0x02, 0xF1, 0x01, 0x0C, 0xC5, 0xF8, 0x00, 0xC0, 0x00, 0x2B, 0x3E, 0xD0, 0x04, 0xF1, 0x0C, 0x00, 0x00, 0x21, 0x05, 0xE0, ++0x4C, 0x68, 0xA2, 0x42, 0x38, 0xBF, 0x19, 0x46, 0x1B, 0x68, 0x43, 0xB1, 0x5A, 0x68, 0x82, 0x42, 0xFA, 0xD3, 0x00, 0x29, ++0xF4, 0xD1, 0x19, 0x46, 0x1B, 0x68, 0x00, 0x2B, 0xF6, 0xD1, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x12, 0xDB, ++0x0A, 0x46, 0x4B, 0x68, 0x9B, 0x1B, 0x98, 0x18, 0x4B, 0x60, 0x04, 0x30, 0x9E, 0x50, 0xBC, 0xF1, 0x00, 0x0F, 0x07, 0xD0, ++0x13, 0x4A, 0x0C, 0xF1, 0xFF, 0x33, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xF8, 0xBD, 0x00, 0x29, ++0xEA, 0xD1, 0x10, 0x49, 0x10, 0x48, 0x97, 0x22, 0x01, 0xF0, 0xC0, 0xFF, 0x00, 0x22, 0xD5, 0xF8, 0x00, 0xC0, 0x11, 0x46, ++0xE1, 0xE7, 0x07, 0x2E, 0xB4, 0xD8, 0x0A, 0x49, 0x0B, 0x48, 0x7B, 0x22, 0x01, 0xF0, 0xB4, 0xFF, 0xAE, 0xE7, 0x3A, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xE8, 0xDB, 0x5B, 0x68, 0xFF, 0xDE, 0x38, 0x36, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x08, 0xAC, 0x15, 0x00, 0xE0, 0xAB, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xF4, 0x90, 0x36, 0x4A, 0xD9, 0xF8, 0x00, 0x30, 0xD4, 0x69, 0xB3, 0xF9, 0x00, 0x30, ++0x50, 0xF8, 0x04, 0x8C, 0x00, 0x2B, 0x06, 0x46, 0xA0, 0xF1, 0x04, 0x05, 0x2F, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x2E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x48, 0xD0, 0xF8, 0x00, 0xC0, 0x0C, 0xF1, 0x01, 0x07, ++0x07, 0x60, 0x00, 0x2C, 0x47, 0xD0, 0x63, 0x68, 0x1A, 0x19, 0xAA, 0x42, 0x23, 0xD0, 0xAC, 0x42, 0x06, 0xD9, 0x37, 0xE0, ++0x63, 0x68, 0x1A, 0x19, 0xAA, 0x42, 0x1C, 0xD0, 0xAC, 0x42, 0x26, 0xD8, 0x21, 0x46, 0x24, 0x68, 0x00, 0x2C, 0xF5, 0xD1, ++0x0D, 0x60, 0x46, 0xE9, 0x01, 0x48, 0x47, 0xB1, 0x1E, 0x4B, 0xC0, 0xF8, 0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, ++0x01, 0xD1, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0xA0, 0x42, 0xCD, 0xD8, 0x1A, 0x49, 0x1A, 0x48, 0xC7, 0x22, ++0x01, 0xF0, 0x56, 0xFF, 0xC7, 0xE7, 0x43, 0x44, 0x22, 0x68, 0x63, 0x60, 0xE1, 0x18, 0x8A, 0x42, 0xE5, 0xD1, 0xD2, 0xE9, ++0x00, 0x21, 0x0B, 0x44, 0x22, 0x60, 0x63, 0x60, 0xDF, 0xE7, 0x05, 0xEB, 0x08, 0x03, 0x9C, 0x42, 0x0D, 0x60, 0xD8, 0xD1, ++0x23, 0x68, 0x46, 0xF8, 0x04, 0x3C, 0x52, 0x1B, 0x32, 0x60, 0xD4, 0xE7, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0xDB, 0x00, 0x23, 0x1D, 0x60, 0xFF, 0xDE, 0x25, 0x60, 0xFF, 0xDE, 0x06, 0x49, 0x07, 0x48, 0xE2, 0x22, ++0x01, 0xF0, 0x2E, 0xFF, 0xF4, 0xE7, 0x00, 0xBF, 0x80, 0xB6, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x18, 0xAC, 0x15, 0x00, 0x3C, 0xAC, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xC0, 0x88, 0x40, 0x1A, ++0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x2A, 0xB3, 0xF8, 0xB5, 0x53, 0x1E, 0x0F, 0x46, 0x0A, 0x68, 0x01, 0xE0, ++0x59, 0x1C, 0x11, 0xD0, 0x32, 0xF8, 0x33, 0x40, 0x84, 0x42, 0x4F, 0xEA, 0xC3, 0x06, 0x02, 0xEB, 0xC3, 0x05, 0x03, 0xF1, ++0xFF, 0x33, 0xF3, 0xD1, 0x0B, 0x4B, 0x68, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x02, 0xDB, 0xF8, 0xBD, ++0x00, 0x20, 0xF8, 0xBD, 0x00, 0x28, 0xFA, 0xD1, 0x06, 0x49, 0x07, 0x48, 0xF4, 0x22, 0x01, 0xF0, 0xF5, 0xFE, 0x3B, 0x68, ++0x1E, 0x44, 0x70, 0x68, 0xF8, 0xBD, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x50, 0xAC, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x44, 0x4F, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, ++0x0D, 0x46, 0x4F, 0xEA, 0x10, 0x29, 0xC6, 0xB2, 0x3B, 0xDB, 0x40, 0x4B, 0x03, 0xEB, 0x06, 0x16, 0xB3, 0x68, 0x03, 0xEB, ++0x49, 0x09, 0x3E, 0x48, 0x2A, 0x46, 0x21, 0x46, 0x01, 0xF0, 0x56, 0xFC, 0xB9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x01, 0xD1, ++0xBD, 0xE8, 0xF8, 0x83, 0xDF, 0xF8, 0x0C, 0x81, 0x38, 0x4F, 0x39, 0x4E, 0xA9, 0xF8, 0x00, 0x50, 0x19, 0xE0, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0x33, 0x60, 0x34, 0x4D, 0x35, 0x48, 0x2B, 0x68, 0x01, 0x33, ++0x2B, 0x60, 0x00, 0xF0, 0x61, 0xFA, 0x2A, 0x68, 0x53, 0x1E, 0x22, 0xB1, 0x32, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0xB3, 0xF9, 0x41, 0x46, 0x22, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0x40, 0xFE, ++0x01, 0x46, 0x00, 0x28, 0xDD, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x2E, 0x23, 0xD8, 0x33, 0xD0, 0x20, 0x4B, 0x03, 0xEB, ++0x06, 0x16, 0xF3, 0x89, 0x4B, 0x45, 0x0B, 0xD9, 0xB3, 0x68, 0x03, 0xEB, 0x49, 0x09, 0xB9, 0xF1, 0x00, 0x0F, 0xBA, 0xD1, ++0x20, 0x49, 0x21, 0x48, 0xB9, 0x22, 0x01, 0xF0, 0x8B, 0xFE, 0xB4, 0xE7, 0xB4, 0x22, 0x1D, 0x49, 0x1E, 0x48, 0x01, 0xF0, ++0x85, 0xFE, 0x3A, 0x68, 0xB3, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xEB, 0x49, 0x09, 0xA7, 0xDA, 0xB9, 0xF1, ++0x00, 0x0F, 0xA4, 0xD1, 0xE8, 0xE7, 0x15, 0x49, 0x17, 0x48, 0xB2, 0x22, 0x01, 0xF0, 0x74, 0xFE, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x93, 0xDA, 0x0D, 0x2E, 0x04, 0xD0, 0x0F, 0x49, 0x12, 0x48, 0xBB, 0x22, 0x01, 0xF0, 0x68, 0xFE, ++0x0C, 0x49, 0x11, 0x48, 0xB3, 0x22, 0x01, 0xF0, 0x63, 0xFE, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC1, 0xDB, ++0x81, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x14, 0xAD, 0x15, 0x00, 0xC8, 0xAC, 0x15, 0x00, 0x8C, 0xB6, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x84, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB8, 0xAC, 0x15, 0x00, ++0x98, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, 0x41, 0x2D, 0x14, 0x00, ++0x70, 0xB5, 0x20, 0x4D, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x4F, 0xEA, 0x10, 0x26, 0xC4, 0xB2, 0x06, 0xDB, ++0x1C, 0x4D, 0x24, 0x01, 0x25, 0x44, 0xAB, 0x68, 0x33, 0xF8, 0x16, 0x00, 0x70, 0xBD, 0x0C, 0x2C, 0x11, 0xD8, 0x21, 0xD0, ++0x17, 0x4D, 0x05, 0xEB, 0x04, 0x13, 0x24, 0x01, 0xDB, 0x89, 0xB3, 0x42, 0xF0, 0xD8, 0x25, 0x44, 0x14, 0x49, 0x15, 0x48, ++0xD9, 0x22, 0x01, 0xF0, 0x1F, 0xFE, 0xAB, 0x68, 0x33, 0xF8, 0x16, 0x00, 0x70, 0xBD, 0x10, 0x49, 0x11, 0x48, 0xD7, 0x22, ++0x01, 0xF0, 0x16, 0xFE, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDA, 0x0D, 0x2C, 0x04, 0xD0, 0x0A, 0x49, ++0x0C, 0x48, 0xBB, 0x22, 0x01, 0xF0, 0x0A, 0xFE, 0x07, 0x49, 0x0B, 0x48, 0xD8, 0x22, 0x01, 0xF0, 0x05, 0xFE, 0x2B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xD3, 0xDB, 0xC8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x14, 0xAD, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x98, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x68, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x67, 0x4D, 0x68, 0x48, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x00, 0xF0, 0xCF, 0xF9, 0x2B, 0x68, 0x04, 0x46, 0x2B, 0xB1, ++0x61, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x54, 0xD0, 0x00, 0x2C, 0x39, 0xD0, 0x60, 0x4F, 0xB4, 0xF8, ++0x06, 0xA0, 0x3B, 0x68, 0xB4, 0xF8, 0x04, 0x80, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5F, 0xFA, 0x8A, 0xF6, 0x4F, 0xEA, ++0x1A, 0x2A, 0x48, 0xDB, 0xDF, 0xF8, 0x90, 0x91, 0x36, 0x01, 0x59, 0xF8, 0x06, 0x10, 0xB1, 0x44, 0x00, 0x29, 0x52, 0xD0, ++0xD9, 0xF8, 0x08, 0x30, 0x33, 0xF8, 0x1A, 0x30, 0x01, 0xEB, 0xC3, 0x01, 0x40, 0x46, 0x8A, 0x88, 0xFF, 0xF7, 0x9C, 0xFE, ++0x06, 0x46, 0x00, 0x28, 0x45, 0xD0, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x4E, 0x48, 0x01, 0xF0, 0x31, 0xFB, 0x23, 0x89, ++0xE2, 0x88, 0xA0, 0x88, 0x04, 0xF1, 0x0C, 0x01, 0xB0, 0x47, 0x01, 0x28, 0x08, 0xD0, 0x02, 0x28, 0x7B, 0xD0, 0x00, 0x28, ++0x50, 0xD0, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x79, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x3E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x41, 0x4A, 0x2B, 0x68, 0x52, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x00, 0x2A, ++0x40, 0xD0, 0x33, 0xB1, 0x38, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, ++0xF0, 0x87, 0x00, 0x2A, 0xA8, 0xD0, 0x62, 0xB6, 0xA6, 0xE7, 0x0C, 0x2E, 0x36, 0xD8, 0x48, 0xD0, 0xDF, 0xF8, 0xF8, 0x90, ++0x09, 0xEB, 0x06, 0x13, 0x36, 0x01, 0xDB, 0x89, 0x53, 0x45, 0xAE, 0xD8, 0x32, 0x49, 0x33, 0x48, 0x4F, 0xF4, 0x89, 0x72, ++0x01, 0xF0, 0x6C, 0xFD, 0xA7, 0xE7, 0xD9, 0xF8, 0x04, 0x10, 0x69, 0xB1, 0x8A, 0x88, 0x40, 0x46, 0xFF, 0xF7, 0x4C, 0xFE, ++0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x06, 0x46, 0x27, 0x48, 0x01, 0xF0, 0xE3, 0xFA, 0x00, 0x2E, 0xAF, 0xD1, 0x05, 0xE0, ++0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x23, 0x48, 0x01, 0xF0, 0xDA, 0xFA, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x24, 0x48, ++0x01, 0xF0, 0xD4, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0xE5, 0xFC, 0xAF, 0xE7, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0x74, 0xF8, ++0x2B, 0x68, 0xB8, 0xE7, 0x1B, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0x88, 0x72, 0x01, 0xF0, 0x3E, 0xFD, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0x72, 0xAF, 0x0D, 0x2E, 0x04, 0xD0, 0x14, 0x49, 0x18, 0x48, 0xBB, 0x22, 0x01, 0xF0, ++0x31, 0xFD, 0x12, 0x49, 0x16, 0x48, 0x40, 0xF2, 0x11, 0x12, 0x01, 0xF0, 0x2B, 0xFD, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xAB, 0xDB, 0x5E, 0xE7, 0x12, 0x48, 0x21, 0x46, 0x00, 0xF0, 0xCD, 0xF8, 0x85, 0xE7, 0x09, 0x49, 0x10, 0x48, ++0x40, 0xF2, 0x6D, 0x12, 0x01, 0xF0, 0x1A, 0xFD, 0x7E, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x84, 0xB6, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xB4, 0xAB, 0x15, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x98, 0xAC, 0x15, 0x00, 0xDC, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, ++0x8C, 0xB6, 0x17, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x14, 0xAD, 0x15, 0x00, 0x00, 0x20, 0x70, 0x47, 0x02, 0x20, 0x70, 0x47, ++0x30, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4A, ++0x09, 0x4D, 0x11, 0x68, 0x2B, 0x68, 0x4C, 0x1C, 0x18, 0x43, 0x14, 0x60, 0x28, 0x60, 0x2C, 0xB1, 0x03, 0x4B, 0x11, 0x60, ++0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x80, 0xB6, 0x17, 0x00, 0x4F, 0xF0, 0x00, 0x50, 0xFF, 0xF7, 0xDC, 0xBF, 0x30, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0A, 0x4A, 0x0A, 0x4D, 0x11, 0x68, 0x2B, 0x68, 0x4C, 0x1C, ++0x23, 0xEA, 0x00, 0x00, 0x14, 0x60, 0x28, 0x60, 0x2C, 0xB1, 0x04, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, ++0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x18, 0x4E, 0x34, 0x68, 0xDC, 0xB1, 0xDF, 0xF8, 0x68, 0x80, 0x17, 0x4D, 0x17, 0x4F, 0xDF, 0xF8, ++0x64, 0xA0, 0xDF, 0xF8, 0x64, 0x90, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB4, 0xFA, 0x84, 0xF4, ++0x12, 0xDB, 0x55, 0xF8, 0x34, 0x30, 0x05, 0xEB, 0xC4, 0x04, 0x60, 0x68, 0x98, 0x47, 0x3B, 0x68, 0x34, 0x68, 0xDB, 0x78, ++0x1B, 0xB9, 0x00, 0x2C, 0xEB, 0xD1, 0xBD, 0xE8, 0xF0, 0x87, 0xE9, 0xF7, 0x09, 0xFA, 0x00, 0x2C, 0xE5, 0xD1, 0xF8, 0xE7, ++0x1D, 0x2C, 0x03, 0xDC, 0x55, 0xF8, 0x34, 0x30, 0x00, 0x2B, 0xE8, 0xD1, 0xDC, 0x22, 0x51, 0x46, 0x48, 0x46, 0x01, 0xF0, ++0x7D, 0xFC, 0xE0, 0xE7, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x21, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xE4, 0xAD, 0x15, 0x00, 0x08, 0xB5, 0xFF, 0xF7, 0x35, 0xFC, 0x08, 0x4B, 0x08, 0x49, 0xD8, 0x61, ++0x00, 0x22, 0xC3, 0xE9, 0x03, 0x22, 0xC3, 0xE9, 0x01, 0x22, 0xC3, 0xE9, 0x05, 0x22, 0x59, 0x62, 0x4F, 0xF0, 0xFF, 0x30, ++0xBD, 0xE8, 0x08, 0x40, 0xFF, 0xF7, 0x8A, 0xBF, 0x80, 0xB6, 0x17, 0x00, 0xD1, 0x31, 0x14, 0x00, 0x00, 0x23, 0xC0, 0xE9, ++0x00, 0x33, 0x70, 0x47, 0x38, 0xB5, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, ++0x07, 0xDB, 0x2B, 0x68, 0x6B, 0xB1, 0x6B, 0x68, 0x1C, 0x60, 0x00, 0x23, 0x6C, 0x60, 0x23, 0x60, 0x38, 0xBD, 0x00, 0x29, ++0xF5, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x48, 0x22, 0x01, 0xF0, 0x3C, 0xFC, 0xEF, 0xE7, 0x00, 0x23, 0x2C, 0x60, 0x6C, 0x60, ++0x23, 0x60, 0x38, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x14, 0xAE, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, 0x04, 0xDB, 0x2B, 0x68, 0x53, 0xB1, 0x23, 0x60, ++0x2C, 0x60, 0x38, 0xBD, 0x00, 0x29, 0xF8, 0xD1, 0x05, 0x49, 0x06, 0x48, 0x5F, 0x22, 0x01, 0xF0, 0x1B, 0xFC, 0xF2, 0xE7, ++0x6C, 0x60, 0x23, 0x60, 0x2C, 0x60, 0x38, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x14, 0xAE, 0x15, 0x00, ++0x03, 0x68, 0x33, 0xB1, 0x42, 0x68, 0x19, 0x68, 0x01, 0x60, 0x9A, 0x42, 0x04, 0xBF, 0x00, 0x22, 0x42, 0x60, 0x18, 0x46, ++0x70, 0x47, 0x00, 0xBF, 0x38, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, ++0x0B, 0xDB, 0x2B, 0x68, 0x43, 0xB1, 0xA3, 0x42, 0x02, 0xD1, 0x14, 0xE0, 0xA3, 0x42, 0x0C, 0xD0, 0x1A, 0x46, 0x1B, 0x68, ++0x00, 0x2B, 0xF9, 0xD1, 0x38, 0xBD, 0x00, 0x28, 0xF1, 0xD1, 0x0C, 0x49, 0x0C, 0x48, 0x84, 0x22, 0x01, 0xF0, 0xE8, 0xFB, ++0xEB, 0xE7, 0x6B, 0x68, 0xA3, 0x42, 0x0A, 0xD0, 0x23, 0x68, 0x13, 0x60, 0x38, 0xBD, 0x6B, 0x68, 0x22, 0x68, 0x2A, 0x60, ++0xA3, 0x42, 0xEB, 0xD1, 0x00, 0x23, 0x6B, 0x60, 0x38, 0xBD, 0x6A, 0x60, 0xF2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x28, 0xAE, 0x15, 0x00, 0x03, 0x68, 0x2B, 0xB1, 0x00, 0x20, 0x1B, 0x68, 0x01, 0x30, 0x00, 0x2B, ++0xFB, 0xD1, 0x70, 0x47, 0x18, 0x46, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0xD0, 0xE9, 0x00, 0x47, 0x80, 0x46, 0x0D, 0x46, ++0x16, 0x46, 0x1F, 0xB1, 0x39, 0x46, 0x28, 0x46, 0x90, 0x47, 0x88, 0xB1, 0x00, 0x27, 0x24, 0xB9, 0x1A, 0xE0, 0x23, 0x68, ++0x27, 0x46, 0x8B, 0xB1, 0x1C, 0x46, 0x21, 0x46, 0x28, 0x46, 0xB0, 0x47, 0x00, 0x28, 0xF6, 0xD0, 0x2C, 0x60, 0x67, 0xB9, ++0xC8, 0xF8, 0x00, 0x50, 0xBD, 0xE8, 0xF0, 0x81, 0x3D, 0x60, 0xC8, 0xF8, 0x04, 0x50, 0x28, 0x60, 0xBD, 0xE8, 0xF0, 0x81, ++0xC8, 0xF8, 0x04, 0x50, 0x2B, 0x60, 0x3D, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x23, 0xC8, 0xF8, 0x04, 0x50, 0x2B, 0x60, ++0xEA, 0xE7, 0x00, 0xBF, 0x03, 0x68, 0xB9, 0xB1, 0xCB, 0xB1, 0x8B, 0x42, 0x10, 0xB4, 0x04, 0x46, 0x02, 0xD1, 0x07, 0xE0, ++0x99, 0x42, 0x05, 0xD0, 0x1B, 0x68, 0x00, 0x2B, 0xFA, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x63, 0x68, 0x08, 0x68, ++0x10, 0x60, 0x8B, 0x42, 0x0A, 0x60, 0xF6, 0xD1, 0x62, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x11, 0x46, 0xFF, 0xF7, ++0x49, 0xBF, 0x70, 0x47, 0x81, 0xB1, 0x03, 0x68, 0x8B, 0x42, 0x0A, 0xD0, 0x2B, 0xB1, 0x18, 0x68, 0x88, 0x42, 0x03, 0xD0, ++0x03, 0x46, 0x00, 0x2B, 0xF9, 0xD1, 0x70, 0x47, 0x11, 0x60, 0x1A, 0x60, 0x70, 0x47, 0x11, 0x46, 0xFF, 0xF7, 0x36, 0xBF, ++0x11, 0x46, 0xFF, 0xF7, 0x0F, 0xBF, 0x00, 0xBF, 0x0B, 0x46, 0x09, 0x68, 0x99, 0xB1, 0x02, 0x46, 0x00, 0x68, 0x48, 0xB1, ++0x10, 0xB4, 0x54, 0x68, 0x58, 0x68, 0x21, 0x60, 0x50, 0x60, 0x00, 0x22, 0x5D, 0xF8, 0x04, 0x4B, 0x1A, 0x60, 0x70, 0x47, ++0x93, 0xE8, 0x03, 0x00, 0x82, 0xE8, 0x03, 0x00, 0x00, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x70, 0x47, 0xF8, 0xB5, 0x1F, 0x4F, ++0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0x46, 0x0D, 0x46, 0x14, 0x46, 0x0A, 0xDB, 0x25, 0xB3, 0x23, 0x68, ++0x2B, 0x60, 0x73, 0x68, 0xA3, 0x42, 0x4F, 0xF0, 0x00, 0x03, 0x08, 0xBF, 0x75, 0x60, 0x23, 0x60, 0xF8, 0xBD, 0xE0, 0xB1, ++0xB5, 0xB1, 0x2B, 0x68, 0xA3, 0x42, 0x0A, 0xD0, 0x13, 0x49, 0x14, 0x48, 0x40, 0xF2, 0x75, 0x12, 0x01, 0xF0, 0x2A, 0xFB, ++0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE5, 0xDA, 0x00, 0x2C, 0xE3, 0xD1, 0x0D, 0x49, 0x0E, 0x48, 0x4F, 0xF4, ++0xBB, 0x72, 0x01, 0xF0, 0x1D, 0xFB, 0xDB, 0xE7, 0x00, 0x2C, 0xF6, 0xD0, 0x23, 0x68, 0x33, 0x60, 0xD9, 0xE7, 0x07, 0x49, ++0x09, 0x48, 0x4F, 0xF4, 0xBA, 0x72, 0x01, 0xF0, 0x11, 0xFB, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xD7, 0xDB, ++0xCA, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x38, 0xAE, 0x15, 0x00, 0x74, 0xAE, 0x15, 0x00, ++0x28, 0xAE, 0x15, 0x00, 0x81, 0xB1, 0x10, 0xB4, 0x08, 0x4C, 0x01, 0x44, 0x10, 0xF8, 0x01, 0x3B, 0x83, 0xEA, 0x12, 0x63, ++0x81, 0x42, 0x54, 0xF8, 0x23, 0x30, 0x83, 0xEA, 0x02, 0x22, 0xF5, 0xD1, 0x10, 0x46, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x10, 0x46, 0x70, 0x47, 0x84, 0xAE, 0x15, 0x00, 0xF8, 0xB5, 0x0F, 0x18, 0xB8, 0x42, 0xBC, 0x46, 0x06, 0xD3, 0x1D, 0xE0, ++0x44, 0x78, 0x2E, 0x78, 0x02, 0x34, 0xFF, 0x2E, 0x20, 0x44, 0x06, 0xD0, 0x46, 0x1C, 0xB7, 0x42, 0x05, 0x46, 0xF5, 0xD8, ++0x00, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x87, 0x42, 0xFA, 0xD3, 0x1C, 0x80, 0x00, 0x2D, 0xF7, 0xD0, 0xEE, 0x1C, 0x66, 0x45, ++0xF4, 0xD8, 0xAE, 0x78, 0x96, 0x42, 0xF2, 0xD0, 0x0C, 0x1B, 0x84, 0x45, 0xA1, 0xB2, 0x01, 0xD9, 0x0F, 0x18, 0xE7, 0xE7, ++0x06, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE5, 0xDA, 0x84, 0x45, 0xE3, 0xD0, 0x03, 0x49, 0x04, 0x48, ++0x7F, 0x22, 0x01, 0xF0, 0xB9, 0xFA, 0xDD, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x84, 0xB2, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x01, 0xEB, 0x00, 0x08, 0x40, 0x45, 0xC6, 0x46, 0x2D, 0xD2, 0x02, 0xF1, 0x05, 0x0C, 0xC2, 0xF1, ++0x02, 0x07, 0x05, 0xE0, 0x44, 0x78, 0x35, 0x78, 0x02, 0x34, 0xDD, 0x2D, 0x20, 0x44, 0x07, 0xD0, 0x45, 0x1C, 0xA8, 0x45, ++0x06, 0x46, 0xF5, 0xD8, 0x00, 0x26, 0x30, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x80, 0x45, 0xF9, 0xD3, 0x1C, 0x80, 0x00, 0x2E, ++0xF6, 0xD0, 0xF5, 0x1D, 0xAE, 0x45, 0xF3, 0xD3, 0x15, 0x46, 0x01, 0xE0, 0x65, 0x45, 0xF0, 0xD0, 0x05, 0xEB, 0x06, 0x08, ++0x15, 0xF8, 0x01, 0x9B, 0x18, 0xF8, 0x07, 0x80, 0xC1, 0x45, 0xF5, 0xD0, 0x0C, 0x1B, 0x86, 0x45, 0xA1, 0xB2, 0x02, 0xD9, ++0x01, 0xEB, 0x00, 0x08, 0xDC, 0xE7, 0x07, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDA, 0x86, 0x45, ++0xD8, 0xD0, 0x04, 0x49, 0x04, 0x48, 0xB4, 0x22, 0x01, 0xF0, 0x70, 0xFA, 0xD2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0xB2, 0x15, 0x00, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x70, 0xB4, 0x03, 0xE0, ++0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x10, 0xD9, 0x44, 0x78, 0x06, 0x78, 0xA3, 0x1C, 0x01, 0x2E, 0x03, 0xEB, 0x00, 0x05, ++0xF4, 0xD1, 0xA9, 0x42, 0x07, 0xD3, 0x38, 0xB1, 0x0A, 0x2B, 0x04, 0xD8, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x70, 0x70, 0xBC, ++0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x17, 0xD9, ++0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, 0xA3, 0x1C, 0x32, 0x2E, ++0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x70, 0x70, 0xBC, ++0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x70, 0xB4, 0x03, 0xE0, 0x73, 0x1C, 0x99, 0x42, 0x30, 0x46, 0x10, 0xD9, 0x45, 0x78, 0x04, 0x78, 0xAB, 0x1C, 0x1E, 0x18, ++0x00, 0x2C, 0xF5, 0xD1, 0xB1, 0x42, 0x05, 0xD3, 0x10, 0xB1, 0x22, 0x2B, 0x02, 0xD8, 0x15, 0x70, 0x70, 0xBC, 0x70, 0x47, ++0x20, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x17, 0xD9, 0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, ++0xA3, 0x1C, 0x07, 0x2E, 0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x07, 0x2B, 0x02, 0xD9, ++0x14, 0x70, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x17, 0xD9, 0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, ++0xA3, 0x1C, 0x30, 0x2E, 0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x13, 0x2B, 0x02, 0xD9, ++0x14, 0x70, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x25, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x05, 0x2B, 0x18, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, ++0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x3C, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, ++0x06, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x1A, 0xD9, 0x30, 0xB4, 0x03, 0xE0, 0x63, 0x1C, 0x99, 0x42, ++0x20, 0x46, 0x11, 0xD9, 0x43, 0x78, 0x05, 0x78, 0x02, 0x33, 0x3E, 0x2D, 0x03, 0xEB, 0x00, 0x04, 0xF4, 0xD1, 0xA1, 0x42, ++0x08, 0xD3, 0x40, 0xB1, 0xA3, 0xF1, 0x03, 0x03, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0x30, 0xBC, 0x13, 0x70, 0x70, 0x47, ++0x00, 0x20, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x2B, 0xD9, ++0x30, 0xB4, 0x03, 0xE0, 0x18, 0x46, 0x01, 0x33, 0x99, 0x42, 0x16, 0xD9, 0x44, 0x78, 0x05, 0x78, 0xA3, 0x1C, 0xC4, 0x2D, ++0x03, 0x44, 0xF5, 0xD1, 0x99, 0x42, 0x0E, 0xD3, 0x70, 0xB1, 0x02, 0x30, 0x04, 0x44, 0x07, 0xE0, 0x43, 0x78, 0x05, 0x78, ++0x02, 0x33, 0xC2, 0x2D, 0x03, 0xEB, 0x00, 0x01, 0x06, 0xD0, 0x08, 0x46, 0x43, 0x1C, 0x9C, 0x42, 0xF4, 0xD8, 0x00, 0x20, ++0x30, 0xBC, 0x70, 0x47, 0x8C, 0x42, 0xFA, 0xD3, 0x00, 0x28, 0xF9, 0xD0, 0xA3, 0xF1, 0x05, 0x03, 0xB3, 0xFA, 0x83, 0xF3, ++0x5B, 0x09, 0x30, 0xBC, 0x13, 0x70, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x03, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x4C, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x12, 0x2B, 0x18, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, ++0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x2A, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, ++0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, ++0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xC7, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, ++0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, ++0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x20, 0x2C, 0x03, 0xEB, 0x00, 0x02, ++0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x36, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x05, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xB5, 0x83, 0xB0, ++0x06, 0x4A, 0x0D, 0xF1, 0x06, 0x03, 0xFF, 0xF7, 0xC1, 0xFD, 0x20, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0x1A, 0x2B, 0x18, 0xBF, ++0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x98, 0xB2, 0x15, 0x00, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x2D, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x1C, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x47, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x06, 0x2B, 0x38, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x1D, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x63, 0x1C, 0x99, 0x42, 0x20, 0x46, 0x13, 0xD9, ++0x43, 0x78, 0x02, 0x78, 0x02, 0x33, 0x1C, 0x18, 0x00, 0x2A, 0xF5, 0xD1, 0xA1, 0x42, 0x03, 0xD2, 0x10, 0x46, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x28, 0xFA, 0xD0, 0x06, 0x2B, 0x38, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x53, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x04, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x55, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x02, 0x2B, 0x08, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, ++0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xBF, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, ++0x0E, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, 0x06, 0x03, 0x23, 0x22, 0xFF, 0xF7, 0xB2, 0xFC, ++0x40, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0xA3, 0xF1, 0x18, 0x02, 0x21, 0x2A, 0x9A, 0xBF, 0x03, 0x3B, 0x23, 0x70, 0x00, 0x20, ++0x02, 0xB0, 0x10, 0xBD, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, ++0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x3D, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, ++0x06, 0xD3, 0x30, 0xB1, 0x18, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, ++0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xC0, 0x2C, 0x03, 0xEB, 0x00, 0x02, ++0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x07, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, ++0x06, 0x03, 0x24, 0x22, 0xFF, 0xF7, 0x5E, 0xFC, 0x40, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0xA3, 0xF1, 0x09, 0x02, 0x09, 0x2A, ++0x9A, 0xBF, 0x03, 0x3B, 0x23, 0x70, 0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x06, 0x03, ++0x26, 0x22, 0xFF, 0xF7, 0x4B, 0xFC, 0x20, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0x10, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0xFB, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x06, 0x03, 0x25, 0x22, 0xFF, 0xF7, 0x3B, 0xFC, 0x20, 0xB1, ++0xBD, 0xF8, 0x06, 0x30, 0x04, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x43, 0x79, 0x02, 0x79, ++0x58, 0x00, 0x40, 0xEA, 0xD2, 0x10, 0x80, 0x05, 0x70, 0x47, 0x00, 0xBF, 0x43, 0x79, 0x07, 0x48, 0x83, 0xEA, 0x13, 0x13, ++0x5B, 0x01, 0xC1, 0xF3, 0x08, 0x01, 0x03, 0xF4, 0xF0, 0x73, 0x0B, 0x44, 0x00, 0xEA, 0x83, 0x50, 0x40, 0xF4, 0x7C, 0x10, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x28, 0x08, 0xDA, 0x10, 0xF1, 0x6D, 0x0F, 0x01, 0xDA, 0x00, 0x20, ++0x70, 0x47, 0x6E, 0x30, 0x40, 0x00, 0xC0, 0xB2, 0x70, 0x47, 0xDC, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, ++0x1D, 0x46, 0x95, 0xB0, 0x90, 0x46, 0xDD, 0xF8, 0x78, 0xB0, 0x15, 0xF8, 0x01, 0x2B, 0x03, 0x91, 0x07, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0x7F, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x91, 0x83, 0x00, 0x24, 0xCD, 0xE9, 0x00, 0x44, 0x03, 0x9E, 0x02, 0x94, ++0xA1, 0x46, 0xA2, 0x46, 0xA2, 0xF1, 0x20, 0x03, 0x58, 0x2B, 0x5A, 0xD8, 0xDF, 0xE8, 0x13, 0xF0, 0x35, 0x01, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x34, 0x03, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x17, 0x03, 0x35, 0x01, ++0x59, 0x00, 0x35, 0x01, 0x36, 0x03, 0x59, 0x00, 0x12, 0x01, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x10, 0x01, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x01, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0xA2, 0xF1, 0x31, 0x01, 0x08, 0x29, ++0x40, 0xF2, 0xE2, 0x80, 0x00, 0x21, 0x9E, 0x48, 0x00, 0xEB, 0xCA, 0x0A, 0x1A, 0xF8, 0x01, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, ++0x00, 0xF2, 0xD8, 0x83, 0xDF, 0xE8, 0x0A, 0xF0, 0x75, 0x5B, 0x45, 0x9A, 0x70, 0x8E, 0x80, 0x06, 0x07, 0x21, 0xEE, 0xE7, ++0xA2, 0xF1, 0x41, 0x03, 0x37, 0x2B, 0x00, 0xF2, 0x05, 0x82, 0xDF, 0xE8, 0x13, 0xF0, 0x05, 0x02, 0x03, 0x02, 0x03, 0x02, ++0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x54, 0x02, ++0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, ++0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x05, 0x02, ++0x29, 0x01, 0x5E, 0x01, 0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0xA3, 0x01, 0x03, 0x02, 0x03, 0x02, ++0x03, 0x02, 0x54, 0x02, 0x03, 0x02, 0x03, 0x02, 0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0xF8, 0x01, 0x03, 0x02, 0x29, 0x01, ++0x03, 0x02, 0x03, 0x02, 0x29, 0x01, 0x10, 0x2B, 0x00, 0xF2, 0xCA, 0x80, 0xDF, 0xE8, 0x13, 0xF0, 0xD2, 0x00, 0xC8, 0x00, ++0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xD9, 0x00, ++0xC8, 0x00, 0xE0, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC1, 0x00, 0x00, 0x23, 0x00, 0x93, 0x02, 0x93, 0x4F, 0xF0, 0xFF, 0x33, ++0x01, 0x93, 0x4F, 0xF0, 0x01, 0x0A, 0x15, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0x7F, 0xF4, 0x28, 0xAF, 0x00, 0x2E, 0x62, 0xD0, ++0x00, 0x23, 0x3B, 0x70, 0x20, 0x46, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x23, 0x01, 0x93, 0x4F, 0xF0, 0x04, 0x0A, ++0xED, 0xE7, 0x2E, 0xB1, 0xA0, 0x45, 0x9C, 0xBF, 0x07, 0xF8, 0x01, 0x2B, 0x06, 0xF1, 0xFF, 0x36, 0x01, 0x34, 0x4F, 0xF0, ++0x00, 0x0A, 0xE2, 0xE7, 0x68, 0x2A, 0x7B, 0xD0, 0x6C, 0x2A, 0x3F, 0xD0, 0x57, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC0, 0xF2, 0x92, 0x82, 0x4F, 0xF0, 0x06, 0x0A, 0xD4, 0xE7, 0x2A, 0x2A, 0x61, 0xD0, 0x01, 0x9B, 0x30, 0x3A, ++0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x43, 0x03, 0x01, 0x93, 0x4F, 0xF0, 0x05, 0x0A, 0xC8, 0xE7, 0x2A, 0x2A, 0x5B, 0xD0, ++0x02, 0x9B, 0x30, 0x3A, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x43, 0x03, 0x02, 0x93, 0x4F, 0xF0, 0x03, 0x0A, 0xBC, 0xE7, ++0x06, 0x21, 0x4C, 0xE7, 0x44, 0x4B, 0x03, 0xEB, 0xCA, 0x0A, 0x9A, 0xF8, 0x03, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, ++0x25, 0x83, 0x01, 0xA3, 0x53, 0xF8, 0x2A, 0xF0, 0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0xBB, 0x40, 0x14, 0x00, ++0xD9, 0x3F, 0x14, 0x00, 0x85, 0x3F, 0x14, 0x00, 0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, ++0x00, 0x9B, 0x43, 0xF0, 0x02, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x06, 0x0A, 0x97, 0xE7, 0x05, 0x21, 0x27, 0xE7, 0x03, 0x9B, ++0x00, 0x2B, 0x9B, 0xD0, 0x20, 0x46, 0x07, 0xF8, 0x01, 0x6C, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0x49, 0x01, 0xEB, ++0xCA, 0x0A, 0x9A, 0xF8, 0x04, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, 0xF7, 0x82, 0x01, 0xA1, 0x51, 0xF8, 0x2A, 0xF0, ++0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0x2F, 0x3F, 0x14, 0x00, 0xDD, 0x3F, 0x14, 0x00, 0x85, 0x3F, 0x14, 0x00, ++0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, 0x5B, 0xF8, 0x04, 0x3B, 0x01, 0x93, 0x4F, 0xF0, ++0x05, 0x0A, 0x6A, 0xE7, 0x5B, 0xF8, 0x04, 0x3B, 0x02, 0x93, 0x4F, 0xF0, 0x03, 0x0A, 0x64, 0xE7, 0x00, 0x9B, 0x43, 0xF0, ++0x01, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x06, 0x0A, 0x5D, 0xE7, 0x14, 0x46, 0x00, 0x2A, 0x3F, 0xF4, 0x63, 0xAF, 0x03, 0x90, ++0x7D, 0xE6, 0x00, 0x9B, 0x43, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x50, 0xE7, 0x10, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9E, 0x82, 0x4F, 0xF0, 0x02, 0x0A, 0x46, 0xE7, 0x00, 0x9B, 0x43, 0xF0, ++0x10, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x3F, 0xE7, 0x00, 0x9B, 0x43, 0xF0, 0x08, 0x03, 0x00, 0x93, 0x4F, 0xF0, ++0x02, 0x0A, 0x38, 0xE7, 0x00, 0x9B, 0x43, 0xF0, 0x20, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x31, 0xE7, 0x00, 0xBF, ++0x24, 0xB3, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x9B, 0x9B, 0x07, 0x00, 0xF1, 0x94, 0x81, 0x00, 0x9B, 0xD8, 0x07, ++0x40, 0xF1, 0x90, 0x81, 0x64, 0x2A, 0x00, 0xF0, 0x32, 0x82, 0x5B, 0xF8, 0x04, 0x1B, 0x58, 0x3A, 0x89, 0xB2, 0x20, 0x2A, ++0x00, 0xF2, 0x24, 0x82, 0xDF, 0xE8, 0x12, 0xF0, 0x5A, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, ++0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x4E, 0x02, 0x22, 0x02, 0x72, 0x00, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, ++0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x36, 0x02, 0x22, 0x02, ++0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x72, 0x00, 0x22, 0x02, 0x22, 0x02, 0x69, 0x02, 0x02, 0x9B, 0x59, 0x1E, 0x5B, 0xF8, ++0x04, 0x3B, 0x8D, 0xF8, 0x10, 0x30, 0x00, 0x9B, 0x04, 0xAA, 0x03, 0xF0, 0x40, 0x00, 0x01, 0x23, 0x00, 0x28, 0x70, 0xD1, ++0x00, 0x98, 0x80, 0x06, 0x40, 0xF1, 0x15, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0xEA, 0x81, 0x10, 0x46, 0x02, 0xEB, 0x03, 0x09, ++0xA4, 0xEB, 0x02, 0x0E, 0x09, 0xE0, 0xE0, 0x45, 0x04, 0xD8, 0x07, 0x78, 0x02, 0xF8, 0x01, 0x7B, 0x01, 0x3E, 0x17, 0x46, ++0x01, 0x30, 0x48, 0x45, 0x07, 0xD0, 0x00, 0xEB, 0x0E, 0x0C, 0x3A, 0x46, 0x00, 0x2E, 0xF0, 0xD1, 0x01, 0x30, 0x48, 0x45, ++0xF4, 0xD1, 0x23, 0x44, 0x00, 0x29, 0x40, 0xF3, 0xCA, 0x81, 0xCC, 0x18, 0x20, 0x21, 0x08, 0xE0, 0x98, 0x45, 0x03, 0xD8, ++0x02, 0xF8, 0x01, 0x1B, 0x01, 0x3E, 0x17, 0x46, 0x01, 0x33, 0xA3, 0x42, 0x05, 0xD0, 0x3A, 0x46, 0x00, 0x2E, 0xF3, 0xD1, ++0x01, 0x33, 0xA3, 0x42, 0xF6, 0xD1, 0x4F, 0xF0, 0x07, 0x0A, 0xB2, 0xE6, 0x00, 0x9B, 0x99, 0x07, 0x03, 0xD4, 0x00, 0x9B, ++0xDA, 0x07, 0x00, 0xF1, 0xBC, 0x81, 0x5B, 0xF8, 0x04, 0x1B, 0x00, 0x29, 0xC0, 0xF2, 0xBE, 0x81, 0xDF, 0xF8, 0x5C, 0xA4, ++0x00, 0x23, 0x0D, 0xF1, 0x50, 0x0E, 0xAA, 0xFB, 0x01, 0x2C, 0x4F, 0xEA, 0xDC, 0x0C, 0x0C, 0xEB, 0x8C, 0x00, 0xA1, 0xEB, ++0x40, 0x00, 0x89, 0x46, 0x30, 0x30, 0xB9, 0xF1, 0x09, 0x0F, 0x72, 0x46, 0x61, 0x46, 0x0E, 0xF8, 0x01, 0x0D, 0x18, 0x46, ++0x03, 0xF1, 0x01, 0x03, 0xEB, 0xD8, 0x00, 0x99, 0x09, 0x06, 0x00, 0xF1, 0x9E, 0x81, 0x00, 0x99, 0x09, 0x07, 0x40, 0xF1, ++0xE7, 0x81, 0x83, 0x1C, 0x2B, 0x20, 0x0E, 0xF8, 0x01, 0x0C, 0x00, 0x98, 0x02, 0x99, 0x00, 0xF0, 0x40, 0x00, 0x02, 0x3A, ++0xC9, 0x1A, 0x00, 0x28, 0x8E, 0xD0, 0x00, 0x29, 0x14, 0xDD, 0x0C, 0x44, 0x4F, 0xF0, 0x30, 0x0E, 0x08, 0xE0, 0xE0, 0x45, ++0x03, 0xD8, 0x00, 0xF8, 0x01, 0xEB, 0x01, 0x3E, 0x07, 0x46, 0x01, 0x39, 0x00, 0xF0, 0xB0, 0x80, 0xA4, 0xEB, 0x01, 0x0C, ++0x38, 0x46, 0x00, 0x2E, 0xF1, 0xD1, 0x01, 0x39, 0xF5, 0xD1, 0x00, 0x21, 0x00, 0x2B, 0x7F, 0xF4, 0x7C, 0xAF, 0x91, 0x46, ++0xA7, 0xE7, 0x5B, 0xF8, 0x04, 0x2B, 0x00, 0x2A, 0x40, 0xF0, 0x2C, 0x81, 0x00, 0x9B, 0x02, 0x99, 0x03, 0xF0, 0x40, 0x00, ++0x00, 0x23, 0x65, 0xE7, 0x4A, 0x46, 0xF7, 0xE7, 0x5B, 0xF8, 0x04, 0x3B, 0x02, 0x9A, 0xDF, 0xF8, 0xB0, 0xE3, 0x9C, 0x46, ++0x1C, 0xF8, 0x01, 0x3B, 0x00, 0x2A, 0x00, 0xF0, 0x09, 0x81, 0x19, 0x11, 0x15, 0x2A, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, ++0x01, 0x10, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, 0x10, 0x10, 0x28, 0xBF, 0x15, 0x22, 0x02, 0xEB, 0x42, 0x01, 0x01, 0x3A, ++0x8D, 0xF8, 0x11, 0x30, 0x01, 0xF1, 0xFF, 0x33, 0xC1, 0xF1, 0x01, 0x01, 0x1D, 0xD0, 0x0C, 0xEB, 0x02, 0x0A, 0x0D, 0xF1, ++0x13, 0x02, 0x1C, 0xF0, 0x03, 0x0F, 0x1C, 0xF8, 0x01, 0x0B, 0x4F, 0xEA, 0x20, 0x19, 0x00, 0xF0, 0x0F, 0x00, 0x1E, 0xF8, ++0x09, 0x90, 0x82, 0xF8, 0x00, 0x90, 0x1E, 0xF8, 0x00, 0x00, 0x50, 0x70, 0x0C, 0xBF, 0x4F, 0xF0, 0x3A, 0x09, 0x4F, 0xF0, ++0x2E, 0x09, 0xE2, 0x45, 0x02, 0xF8, 0x01, 0x9C, 0x02, 0xF1, 0x03, 0x02, 0xE5, 0xD1, 0x00, 0x9A, 0x02, 0xF0, 0x40, 0x02, ++0x00, 0x2A, 0x40, 0xF0, 0x69, 0x81, 0x00, 0x98, 0x02, 0x92, 0x80, 0x06, 0x04, 0xAA, 0x3F, 0xF5, 0x1F, 0xAF, 0x00, 0x2B, ++0x7F, 0xF4, 0x1F, 0xAF, 0xA1, 0xE7, 0x5B, 0xF8, 0x04, 0x1B, 0xDF, 0xF8, 0x14, 0xE3, 0x8C, 0x46, 0x4F, 0xF0, 0x3A, 0x09, ++0x1C, 0xF8, 0x06, 0x3B, 0x1A, 0x11, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, 0x02, 0x20, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, ++0x11, 0x30, 0x8D, 0xF8, 0x10, 0x20, 0x01, 0x31, 0x04, 0xAB, 0x11, 0xF8, 0x01, 0x2B, 0x83, 0xF8, 0x02, 0x90, 0x10, 0x11, ++0x02, 0xF0, 0x0F, 0x02, 0x1E, 0xF8, 0x00, 0x00, 0x1E, 0xF8, 0x02, 0x20, 0xD8, 0x70, 0x8C, 0x45, 0x1A, 0x71, 0x03, 0xF1, ++0x03, 0x03, 0xEE, 0xD1, 0x02, 0x9B, 0xA3, 0xF1, 0x11, 0x01, 0x00, 0x9B, 0x04, 0xAA, 0x03, 0xF0, 0x40, 0x00, 0x11, 0x23, ++0xE4, 0xE6, 0x00, 0x29, 0x7F, 0xF7, 0x6C, 0xAF, 0x21, 0x44, 0x4F, 0xF0, 0x20, 0x0C, 0x08, 0xE0, 0xA0, 0x45, 0x03, 0xD8, ++0x00, 0xF8, 0x01, 0xCB, 0x01, 0x3E, 0x07, 0x46, 0x01, 0x34, 0xA1, 0x42, 0x05, 0xD0, 0x38, 0x46, 0x00, 0x2E, 0xF3, 0xD1, ++0x01, 0x34, 0xA1, 0x42, 0xF6, 0xD1, 0x0C, 0x46, 0x00, 0x21, 0x00, 0x2B, 0x7F, 0xF4, 0xD3, 0xAE, 0x55, 0xE7, 0x04, 0x23, ++0x9A, 0x49, 0x01, 0xEB, 0xCA, 0x0A, 0x1A, 0xF8, 0x03, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, 0x1F, 0x81, 0x01, 0xA3, ++0x53, 0xF8, 0x2A, 0xF0, 0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0xC9, 0x40, 0x14, 0x00, 0xD9, 0x3F, 0x14, 0x00, ++0x85, 0x3F, 0x14, 0x00, 0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, 0x01, 0x23, 0xE1, 0xE7, ++0x02, 0x21, 0x26, 0xE5, 0x58, 0x3A, 0x5B, 0xF8, 0x04, 0x1B, 0x20, 0x2A, 0x00, 0xF2, 0x98, 0x80, 0x01, 0xA3, 0x53, 0xF8, ++0x22, 0xF0, 0x00, 0xBF, 0xED, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0xD5, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x17, 0x42, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0xA5, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x1D, 0x42, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x0B, 0x46, 0x14, 0x00, 0x03, 0x9E, 0x14, 0x46, ++0x4A, 0xE5, 0x64, 0x49, 0x64, 0x48, 0x4F, 0xF4, 0xA2, 0x72, 0x00, 0xF0, 0x49, 0xFB, 0x4F, 0xF0, 0x06, 0x0A, 0x3C, 0xE5, ++0x1A, 0x11, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, 0x02, 0x20, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, 0x10, 0x20, 0x8D, 0xF8, ++0x11, 0x30, 0x6F, 0xF0, 0x2E, 0x01, 0x2F, 0x23, 0x0F, 0x22, 0xFC, 0xE6, 0x13, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x97, 0x80, ++0x01, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0xCC, 0xAE, 0x01, 0x9B, 0x11, 0x46, 0xC2, 0xF1, 0x01, 0x00, 0x00, 0x2B, 0x00, 0xEB, ++0x01, 0x0C, 0x0F, 0xDD, 0x11, 0xF8, 0x01, 0xEF, 0x01, 0x3B, 0xBE, 0xF1, 0x00, 0x0F, 0x10, 0xD0, 0x00, 0x2B, 0xF3, 0xD1, ++0x02, 0x99, 0x00, 0x98, 0x01, 0x93, 0x63, 0x46, 0xC9, 0x1A, 0x00, 0xF0, 0x40, 0x00, 0x1F, 0xE6, 0x00, 0xEB, 0x01, 0x0C, ++0x11, 0xF8, 0x01, 0xEF, 0xBE, 0xF1, 0x00, 0x0F, 0xE4, 0xD1, 0x01, 0x93, 0x63, 0x46, 0x02, 0x99, 0x00, 0x98, 0xC9, 0x1A, ++0x00, 0xF0, 0x40, 0x00, 0x10, 0xE6, 0x1C, 0x46, 0x4F, 0xF0, 0x07, 0x0A, 0xF9, 0xE4, 0x23, 0x46, 0x91, 0x46, 0x2B, 0xE6, ++0x00, 0x9B, 0x02, 0x99, 0x03, 0xF0, 0x40, 0x00, 0x14, 0xAA, 0x00, 0x23, 0x02, 0xE6, 0x5B, 0xF8, 0x04, 0x1B, 0x09, 0xB2, ++0x41, 0xE6, 0x83, 0x1C, 0x2D, 0x20, 0x64, 0xE6, 0x00, 0x9B, 0x43, 0xF0, 0x80, 0x03, 0x49, 0x42, 0x00, 0x93, 0x3B, 0xE6, ++0x00, 0x9B, 0x43, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x08, 0x23, 0x40, 0x20, 0x02, 0x93, 0xDF, 0xF8, 0xD0, 0xC0, 0x14, 0xAA, ++0x01, 0xF0, 0x0F, 0x03, 0x09, 0x09, 0x1C, 0xF8, 0x03, 0x30, 0x02, 0xF8, 0x01, 0x3D, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, ++0xF4, 0xD1, 0x02, 0x99, 0xC9, 0x1A, 0xDD, 0xE5, 0x14, 0xAA, 0x01, 0xF0, 0x01, 0x03, 0x30, 0x33, 0x02, 0xF8, 0x01, 0x3D, ++0x49, 0x08, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, 0xF5, 0xD1, 0xBA, 0xE7, 0xDF, 0xF8, 0x90, 0xE0, 0x14, 0xAA, 0x01, 0xF0, ++0x0F, 0x03, 0x09, 0x09, 0x1E, 0xF8, 0x03, 0x30, 0x02, 0xF8, 0x01, 0x3D, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, 0xF4, 0xD1, ++0xAB, 0xE7, 0x00, 0x9B, 0x03, 0xF0, 0x40, 0x00, 0xCF, 0xE7, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0x11, 0x12, 0x00, 0xF0, ++0xAF, 0xFA, 0x4F, 0xF0, 0x02, 0x0A, 0xA2, 0xE4, 0x00, 0x22, 0x02, 0x92, 0x04, 0xAA, 0xBA, 0xE5, 0x00, 0x99, 0xC9, 0x06, ++0x06, 0xD4, 0x02, 0x98, 0xC1, 0x1A, 0x00, 0x98, 0x72, 0x46, 0x00, 0xF0, 0x40, 0x00, 0xA7, 0xE5, 0x83, 0x1C, 0x20, 0x20, ++0x0D, 0xE6, 0x00, 0x99, 0x01, 0xF0, 0x40, 0x00, 0x02, 0x99, 0x9F, 0xE5, 0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xBF, 0xF6, 0x86, 0xAC, 0x04, 0x49, 0x04, 0x48, 0x4F, 0xF4, 0x12, 0x72, 0x00, 0xF0, 0x89, 0xFA, 0x7E, 0xE4, ++0x24, 0xB3, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, ++0x10, 0xB3, 0x15, 0x00, 0xFC, 0xB2, 0x15, 0x00, 0x0F, 0xB4, 0x2D, 0xE9, 0xF0, 0x47, 0x21, 0x4E, 0xD6, 0xF8, 0x04, 0x31, ++0x82, 0xB0, 0xFB, 0xB1, 0x0A, 0x9C, 0xDF, 0xF8, 0x80, 0x80, 0xDF, 0xF8, 0x80, 0xA0, 0xDF, 0xF8, 0x80, 0x90, 0xA7, 0x1C, ++0x20, 0x46, 0x14, 0xF8, 0x01, 0x5B, 0x29, 0x06, 0xA5, 0xF1, 0x80, 0x02, 0x0A, 0xD5, 0x88, 0x2D, 0x13, 0xD8, 0xD6, 0xF8, ++0x00, 0x31, 0xDB, 0x43, 0xD3, 0x40, 0xDB, 0x07, 0x08, 0xD4, 0xA7, 0x42, 0x20, 0x46, 0xED, 0xD1, 0x12, 0x4B, 0x0B, 0xA9, ++0xD3, 0xF8, 0x30, 0x34, 0x01, 0x91, 0x98, 0x47, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x04, 0xB0, 0x70, 0x47, 0xD8, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x20, 0x05, 0xF1, 0x66, 0x03, 0x00, 0x2A, 0xDB, 0xB2, 0x05, 0xDB, 0xD6, 0xF8, 0x04, 0x31, ++0x9A, 0x3D, 0xAB, 0x42, 0xE3, 0xD8, 0xEB, 0xE7, 0x05, 0x2B, 0xF7, 0xD9, 0x40, 0xF2, 0xA9, 0x22, 0x51, 0x46, 0x48, 0x46, ++0x00, 0xF0, 0x36, 0xFA, 0xF0, 0xE7, 0x00, 0xBF, 0xB0, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xCC, 0xB2, 0x15, 0x00, 0x0E, 0xB4, 0x09, 0x4B, 0x00, 0xB5, 0x1B, 0x68, 0x1B, 0x88, 0x18, 0x42, ++0x82, 0xB0, 0x06, 0xD0, 0x06, 0x4B, 0x03, 0x98, 0xD3, 0xF8, 0x30, 0x34, 0x04, 0xA9, 0x01, 0x91, 0x98, 0x47, 0x02, 0xB0, ++0x5D, 0xF8, 0x04, 0xEB, 0x03, 0xB0, 0x70, 0x47, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x05, 0x48, ++0xFF, 0xF7, 0x94, 0xFF, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0xFE, 0xF7, 0x35, 0xF8, 0xE0, 0xF7, 0x0F, 0xFC, 0xFE, 0xE7, ++0x64, 0xB3, 0x15, 0x00, 0x08, 0xB5, 0x05, 0x48, 0xFF, 0xF7, 0x86, 0xFF, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0xFE, 0xF7, ++0x27, 0xF8, 0xE0, 0xF7, 0x01, 0xFC, 0xFE, 0xE7, 0x7C, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x17, 0x48, 0x00, 0x68, 0x00, 0x78, ++0x02, 0x28, 0x83, 0xB0, 0x1D, 0x46, 0x06, 0xD1, 0x48, 0x78, 0x83, 0x1E, 0x01, 0x2B, 0x0C, 0x46, 0x0E, 0xD9, 0x05, 0x28, ++0x0C, 0xD0, 0x11, 0x48, 0x01, 0x92, 0xFF, 0xF7, 0x69, 0xFF, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, 0x1C, 0x40, 0xFE, 0xF7, ++0x63, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x23, 0x78, 0x53, 0xB9, 0xA3, 0x78, 0x01, 0x92, 0x1B, 0xB1, 0xE1, 0xF7, ++0x17, 0xFE, 0x01, 0x9A, 0xEE, 0xE7, 0xE1, 0xF7, 0x1D, 0xFE, 0x01, 0x9A, 0xEA, 0xE7, 0x01, 0x21, 0x01, 0x92, 0xE1, 0xF7, ++0xE1, 0xFD, 0x60, 0x78, 0x01, 0x9A, 0xED, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x88, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x83, 0xB0, ++0x0C, 0x46, 0x09, 0x48, 0x09, 0x68, 0x01, 0x92, 0x1D, 0x46, 0xFF, 0xF7, 0x3F, 0xFF, 0x07, 0x4B, 0x21, 0x68, 0xC3, 0xF8, ++0x04, 0x11, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, 0x07, 0x40, 0xFE, 0xF7, 0x35, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, ++0xA0, 0xB3, 0x15, 0x00, 0xB0, 0xB6, 0x17, 0x00, 0x30, 0xB5, 0x83, 0xB0, 0x0C, 0x46, 0x09, 0x48, 0x09, 0x68, 0x01, 0x92, ++0x1D, 0x46, 0xFF, 0xF7, 0x25, 0xFF, 0x07, 0x4B, 0x21, 0x68, 0xC3, 0xF8, 0x00, 0x11, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, ++0x05, 0x40, 0xFE, 0xF7, 0x1B, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0xC8, 0xB3, 0x15, 0x00, 0xB0, 0xB6, 0x17, 0x00, ++0x18, 0x46, 0x38, 0xB5, 0x0D, 0x46, 0x04, 0x23, 0x01, 0x46, 0x4F, 0xF4, 0x82, 0x60, 0xFE, 0xF7, 0xA3, 0xF8, 0x22, 0x4B, ++0xA9, 0x88, 0x93, 0xF8, 0xA9, 0x30, 0x04, 0x46, 0xEB, 0xB1, 0x4B, 0x1E, 0x01, 0x2B, 0x0D, 0xD9, 0x02, 0x29, 0x2A, 0xD0, ++0x03, 0x29, 0x2F, 0xD0, 0x04, 0x29, 0x1C, 0xD1, 0x1B, 0x4B, 0x2A, 0x68, 0xDA, 0x65, 0x4F, 0xF0, 0x80, 0x72, 0xC3, 0xF8, ++0x34, 0x21, 0x14, 0xE0, 0x18, 0x48, 0x17, 0x4A, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x53, 0x6F, 0x16, 0x48, ++0x43, 0xF0, 0x10, 0x03, 0x53, 0x67, 0x01, 0x23, 0x03, 0x70, 0x01, 0x29, 0xE2, 0xD1, 0x10, 0x4B, 0x2A, 0x68, 0xDA, 0x63, ++0x40, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0x00, 0x25, 0x0F, 0x48, 0x25, 0x60, 0xFF, 0xF7, 0xDA, 0xFE, 0x20, 0x46, 0xFE, 0xF7, ++0x9F, 0xF8, 0x28, 0x46, 0x38, 0xBD, 0x08, 0x4B, 0x2A, 0x68, 0x9A, 0x65, 0x20, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0xEE, 0xE7, ++0x04, 0x4B, 0x2A, 0x68, 0x1A, 0x64, 0x80, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0xE7, 0xE7, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, ++0x00, 0x00, 0x50, 0x40, 0xE0, 0x50, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, 0xF0, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x18, 0x46, ++0x0C, 0x46, 0x08, 0x23, 0x01, 0x46, 0x85, 0xB0, 0x40, 0xF2, 0x12, 0x40, 0xFE, 0xF7, 0x4A, 0xF8, 0x18, 0x4B, 0x22, 0x68, ++0x1B, 0x68, 0x1B, 0x78, 0x01, 0x3B, 0x01, 0x2B, 0x05, 0x46, 0x19, 0xD9, 0x11, 0x68, 0xA3, 0x68, 0x60, 0x68, 0x4B, 0x40, ++0x03, 0x40, 0x4B, 0x40, 0x13, 0x60, 0x22, 0x68, 0x2A, 0x60, 0x11, 0x68, 0xA3, 0x68, 0x69, 0x60, 0xCD, 0xE9, 0x01, 0x11, ++0x00, 0x92, 0x61, 0x68, 0x0D, 0x48, 0x1A, 0x46, 0xFF, 0xF7, 0x96, 0xFE, 0x28, 0x46, 0xFE, 0xF7, 0x5B, 0xF8, 0x00, 0x20, ++0x05, 0xB0, 0x30, 0xBD, 0x09, 0x4B, 0x9A, 0x42, 0x07, 0xD1, 0xD4, 0xE9, 0x01, 0x03, 0x11, 0x68, 0x4B, 0x40, 0x03, 0x40, ++0x4B, 0x40, 0x13, 0x60, 0x22, 0x68, 0xA3, 0x68, 0xC5, 0xE9, 0x00, 0x23, 0x19, 0x46, 0xE1, 0xE7, 0x78, 0x36, 0x17, 0x00, ++0x04, 0xB4, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, 0x10, 0xB5, 0x19, 0x46, 0x40, 0xF2, 0x0A, 0x40, 0x0C, 0x23, 0xFE, 0xF7, ++0x0B, 0xF8, 0x00, 0x24, 0xC0, 0xE9, 0x00, 0x44, 0x84, 0x60, 0xFE, 0xF7, 0x35, 0xF8, 0x20, 0x46, 0x10, 0xBD, 0x00, 0xBF, ++0x30, 0xB5, 0x18, 0x46, 0x83, 0xB0, 0x08, 0x23, 0x0C, 0x46, 0x01, 0x46, 0x40, 0xF2, 0x03, 0x40, 0xFD, 0xF7, 0xF8, 0xFF, ++0x10, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x3B, 0x01, 0x2B, 0x05, 0x46, 0x13, 0xD9, 0xD4, 0xE9, 0x00, 0x32, 0x1A, 0x60, ++0x23, 0x68, 0x03, 0x60, 0x19, 0x68, 0x62, 0x68, 0x41, 0x60, 0xCD, 0xE9, 0x00, 0x11, 0x09, 0x48, 0x11, 0x46, 0xFF, 0xF7, ++0x4B, 0xFE, 0x28, 0x46, 0xFE, 0xF7, 0x10, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0xD4, 0xE9, 0x00, 0x32, 0xC0, 0xE9, ++0x00, 0x32, 0x11, 0x46, 0xED, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x58, 0xB4, 0x15, 0x00, 0x38, 0xB5, 0x0D, 0x46, ++0x40, 0xF2, 0x01, 0x40, 0x19, 0x46, 0x08, 0x23, 0xFD, 0xF7, 0xCA, 0xFF, 0x29, 0x68, 0x0B, 0x68, 0x04, 0x46, 0xC4, 0xE9, ++0x00, 0x13, 0x1A, 0x46, 0x03, 0x48, 0xFF, 0xF7, 0x29, 0xFE, 0x20, 0x46, 0xFD, 0xF7, 0xEE, 0xFF, 0x00, 0x20, 0x38, 0xBD, ++0x98, 0xB4, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x46, 0x40, 0xF2, 0x0E, 0x40, 0x19, 0x46, 0x04, 0x23, 0xFD, 0xF7, 0xB2, 0xFF, ++0x61, 0x68, 0x02, 0x29, 0x05, 0x46, 0x20, 0xD9, 0x03, 0x29, 0x11, 0xD0, 0x13, 0x48, 0xFF, 0xF7, 0x11, 0xFE, 0x4F, 0xF4, ++0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0xC0, 0xB2, 0x28, 0x60, 0x0F, 0x48, 0xFF, 0xF7, 0x07, 0xFE, 0x28, 0x46, ++0xFD, 0xF7, 0xCC, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x24, 0x68, 0x0C, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0xFD, 0xFD, 0x5C, 0xB1, ++0xA2, 0x02, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0xFD, 0xF7, 0xEC, 0xFD, 0xE3, 0xE7, 0x22, 0x68, 0x06, 0x48, 0xFF, 0xF7, ++0xF1, 0xFD, 0xDE, 0xE7, 0xE0, 0xF7, 0x70, 0xFA, 0xFE, 0xE7, 0x00, 0xBF, 0xF4, 0xB4, 0x15, 0x00, 0x08, 0xB5, 0x15, 0x00, ++0xE8, 0xB4, 0x15, 0x00, 0xC8, 0xB4, 0x15, 0x00, 0x30, 0xB5, 0x40, 0xF2, 0x0C, 0x40, 0x83, 0xB0, 0x0C, 0x46, 0x19, 0x46, ++0x04, 0x23, 0xFD, 0xF7, 0x73, 0xFF, 0x05, 0x46, 0x20, 0x68, 0x00, 0x23, 0x82, 0x07, 0x62, 0x68, 0x2B, 0x60, 0x1C, 0xBF, ++0xFF, 0x23, 0x2B, 0x60, 0x93, 0x07, 0x1C, 0xBF, 0x01, 0x23, 0x2B, 0x60, 0x04, 0xF1, 0x08, 0x01, 0x12, 0xF0, 0xEA, 0xFA, ++0xD4, 0xE9, 0x00, 0x12, 0x28, 0x68, 0xA3, 0x68, 0x00, 0x90, 0x0A, 0x44, 0x04, 0x48, 0xFF, 0xF7, 0xC1, 0xFD, 0x28, 0x46, ++0xFD, 0xF7, 0x86, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x1C, 0xB5, 0x15, 0x00, 0x70, 0xB5, 0x06, 0x46, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x11, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x10, 0x4C, 0x11, 0x48, ++0x25, 0x68, 0x22, 0xF0, 0x7F, 0x43, 0x01, 0x35, 0x0A, 0x46, 0x31, 0x46, 0x25, 0x60, 0xFF, 0xF7, 0xA3, 0xFD, 0x0D, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x05, 0xDB, 0xFC, 0xF7, 0x41, 0xFF, 0x4F, 0xF0, 0x00, 0x40, 0xFE, 0xF7, 0x1D, 0xFB, 0x23, 0x68, ++0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x70, 0xBD, 0x00, 0xBF, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x78, 0xB5, 0x15, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0xB5, 0x04, 0x46, ++0x72, 0xB6, 0x07, 0x4D, 0x07, 0x48, 0x00, 0x26, 0x22, 0xF0, 0x7F, 0x43, 0x2E, 0x60, 0x0A, 0x46, 0x21, 0x46, 0xFF, 0xF7, ++0x79, 0xFD, 0x04, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xFD, 0xD1, 0x70, 0xBD, 0x38, 0x00, 0x32, 0x40, 0x78, 0xB5, 0x15, 0x00, ++0xD0, 0x22, 0x17, 0x00, 0x10, 0xB4, 0x0C, 0x46, 0x22, 0xF0, 0x7F, 0x43, 0x01, 0x46, 0x22, 0x46, 0x02, 0x48, 0x5D, 0xF8, ++0x04, 0x4B, 0xFF, 0xF7, 0x63, 0xBD, 0x00, 0xBF, 0x90, 0xB5, 0x15, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x07, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x06, 0x4B, 0x1A, 0x68, 0x51, 0x1C, 0x19, 0x60, 0x29, 0xB1, 0x03, 0x49, ++0x1A, 0x60, 0x0B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x10, 0xB5, 0x06, 0x4C, 0x4F, 0xF4, 0x84, 0x72, 0x20, 0x46, 0x00, 0x21, 0xDB, 0xF7, 0xD2, 0xFA, 0x4F, 0xF0, 0xFF, 0x32, ++0x02, 0x23, 0xC4, 0xE9, 0x40, 0x23, 0x10, 0xBD, 0xB0, 0xB6, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x22, 0x00, 0x21, 0x02, 0x48, ++0xDB, 0xF7, 0xC4, 0xFA, 0x00, 0x20, 0x08, 0xBD, 0xB8, 0xB7, 0x17, 0x00, 0xE0, 0xF7, 0xB4, 0xBC, 0x01, 0x4B, 0xD3, 0xF8, ++0x24, 0x31, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x02, 0x20, 0x70, 0x47, 0xE0, 0xF7, 0xCC, 0xBB, 0x04, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x03, 0x2B, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0xE0, 0xF7, 0x5F, 0xBB, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, ++0xE0, 0xF7, 0x6E, 0xBB, 0x70, 0xB5, 0x04, 0x68, 0x9C, 0xB1, 0x0A, 0x4E, 0x05, 0x46, 0x03, 0xE0, 0xFE, 0xF7, 0x32, 0xFB, ++0x2C, 0x68, 0x64, 0xB1, 0x28, 0x46, 0xFE, 0xF7, 0x71, 0xFB, 0xE3, 0x68, 0x21, 0x46, 0x30, 0x46, 0x00, 0x2B, 0xF3, 0xD1, ++0xA2, 0x68, 0x2C, 0x68, 0x13, 0x81, 0x00, 0x2C, 0xF2, 0xD1, 0x70, 0xBD, 0x24, 0x65, 0x17, 0x00, 0x38, 0xB5, 0x14, 0x4B, ++0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xD0, 0x38, 0xBD, 0x04, 0x46, 0xE0, 0xF7, 0x80, 0xFB, 0x05, 0x46, 0xB8, 0xB1, ++0x4C, 0xF2, 0xDE, 0x03, 0xA3, 0x61, 0x21, 0x46, 0x1C, 0x22, 0x12, 0xF0, 0x07, 0xFA, 0x0C, 0x4C, 0x23, 0x68, 0x00, 0x2B, ++0xFC, 0xD0, 0x0B, 0x4B, 0x18, 0x68, 0x29, 0x1F, 0x00, 0xF5, 0x07, 0x70, 0xFE, 0xF7, 0x02, 0xFB, 0x01, 0x23, 0x23, 0x60, ++0xBD, 0xE8, 0x38, 0x40, 0xE0, 0xF7, 0x90, 0xBB, 0xBD, 0xE8, 0x38, 0x40, 0x04, 0x48, 0xFF, 0xF7, 0xD1, 0xBC, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x58, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0xA8, 0xB5, 0x15, 0x00, 0x01, 0x4B, 0xD3, 0xF8, ++0x28, 0x31, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x04, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0F, 0x4D, 0x10, 0x48, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0xFE, 0xF7, ++0xD7, 0xFA, 0x05, 0x2C, 0x03, 0xD8, 0x0D, 0x4A, 0x13, 0x5D, 0x01, 0x3B, 0x13, 0x55, 0x2B, 0x68, 0x33, 0xB1, 0x07, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x07, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, 0x01, 0x3B, ++0xC2, 0xF8, 0xF8, 0x31, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, ++0x74, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x4C, 0xDF, 0xF8, 0x3C, 0x80, 0x0C, 0x4F, ++0x0C, 0x4E, 0x04, 0xF5, 0x7C, 0x75, 0x62, 0x69, 0x30, 0x46, 0x13, 0x46, 0x3A, 0xB1, 0x12, 0x78, 0x21, 0x69, 0x20, 0x2A, ++0x0C, 0xBF, 0x42, 0x46, 0x3A, 0x46, 0xE1, 0xF7, 0xB1, 0xFA, 0x10, 0x34, 0xAC, 0x42, 0xF0, 0xD1, 0x00, 0x20, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x24, 0x30, 0x17, 0x00, 0xC4, 0xB5, 0x15, 0x00, 0xC8, 0xB5, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xF8, 0xB5, 0x10, 0xF8, 0x01, 0x3C, 0x09, 0x2B, 0x00, 0xF1, 0xFF, 0x36, 0x30, 0xD1, 0x1C, 0x4C, 0x23, 0x68, 0x99, 0x42, ++0x0D, 0x46, 0x08, 0xDA, 0x1A, 0x4F, 0x38, 0x46, 0x00, 0xF0, 0x64, 0xFD, 0x23, 0x68, 0x01, 0x3B, 0xAB, 0x42, 0x23, 0x60, ++0xF7, 0xDC, 0x17, 0x4D, 0xAE, 0x42, 0x19, 0xD9, 0x16, 0x4F, 0x06, 0xE0, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x00, 0xF0, ++0x53, 0xFD, 0xAE, 0x42, 0x10, 0xD0, 0x15, 0xF8, 0x01, 0x0B, 0x09, 0x28, 0xF4, 0xD1, 0x20, 0x68, 0x00, 0xF0, 0x07, 0x00, ++0x38, 0x44, 0x00, 0xF0, 0x49, 0xFD, 0x23, 0x68, 0x23, 0xF0, 0x07, 0x03, 0x08, 0x33, 0xAE, 0x42, 0x23, 0x60, 0xEE, 0xD1, ++0x0A, 0x4A, 0x13, 0x68, 0x01, 0x3B, 0x30, 0x46, 0x13, 0x60, 0xF8, 0xBD, 0x04, 0x48, 0x00, 0xF0, 0x39, 0xFD, 0x02, 0x4A, ++0x13, 0x68, 0x01, 0x3B, 0x13, 0x60, 0xF1, 0xE7, 0x24, 0x34, 0x17, 0x00, 0x1C, 0xB8, 0x15, 0x00, 0x28, 0x34, 0x17, 0x00, ++0x20, 0xB8, 0x15, 0x00, 0x68, 0x34, 0x17, 0x00, 0x61, 0xB3, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0x64, 0x90, 0x16, 0x4F, ++0xDF, 0xF8, 0x58, 0x80, 0x0E, 0x46, 0x45, 0x1E, 0x00, 0x24, 0x08, 0xE0, 0x15, 0xF8, 0x01, 0x1F, 0x38, 0x46, 0xFF, 0xF7, ++0x11, 0xFC, 0x23, 0x07, 0x10, 0xD0, 0xB4, 0x42, 0x13, 0xD0, 0x14, 0xF0, 0x07, 0x0F, 0x04, 0xF1, 0x01, 0x04, 0xF1, 0xD1, ++0x48, 0x46, 0xFF, 0xF7, 0x05, 0xFC, 0x15, 0xF8, 0x01, 0x1F, 0x38, 0x46, 0xFF, 0xF7, 0x00, 0xFC, 0x23, 0x07, 0xEE, 0xD1, ++0x40, 0x46, 0xFF, 0xF7, 0xFB, 0xFB, 0xB4, 0x42, 0xEB, 0xD1, 0xBD, 0xE8, 0xF8, 0x43, 0x04, 0x48, 0xFF, 0xF7, 0xF4, 0xBB, ++0x02, 0x48, 0xFF, 0xF7, 0xF1, 0xBB, 0x00, 0xBF, 0xD8, 0xB5, 0x15, 0x00, 0xB4, 0x79, 0x15, 0x00, 0xD4, 0xB5, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x87, 0xB0, 0x04, 0x93, 0x00, 0x29, 0x7E, 0xD0, 0x04, 0x2A, 0x14, 0x46, 0x02, 0xD0, 0x53, 0x1E, ++0x01, 0x2B, 0x78, 0xD8, 0x65, 0x42, 0x04, 0xFB, 0x01, 0xF3, 0xDF, 0xF8, 0x8C, 0x91, 0x03, 0x93, 0x05, 0x40, 0x5C, 0x48, ++0x29, 0x46, 0xE1, 0xF7, 0x09, 0xFA, 0x03, 0x9A, 0x2B, 0x0E, 0x10, 0x2A, 0x17, 0x46, 0x28, 0xBF, 0x10, 0x27, 0x01, 0x2B, ++0x68, 0xD0, 0x2B, 0x0D, 0xB3, 0xF5, 0xA0, 0x6F, 0x64, 0xD0, 0x00, 0x2A, 0x00, 0xF0, 0x9C, 0x80, 0xDF, 0xF8, 0x60, 0x81, ++0xDF, 0xF8, 0x60, 0xA1, 0x2E, 0x46, 0x4F, 0xF0, 0x00, 0x0B, 0x0A, 0xE0, 0x02, 0x2C, 0x0A, 0xBF, 0x31, 0x88, 0x31, 0x78, ++0x50, 0x46, 0xA3, 0x44, 0xE1, 0xF7, 0xEA, 0xF9, 0x5F, 0x45, 0x26, 0x44, 0x0A, 0xD9, 0x04, 0x2C, 0x40, 0x46, 0xF1, 0xD1, ++0x31, 0x68, 0x48, 0x48, 0xA3, 0x44, 0xE1, 0xF7, 0xDF, 0xF9, 0x5F, 0x45, 0x26, 0x44, 0xF4, 0xD8, 0x04, 0x9B, 0xB3, 0xB3, ++0x03, 0x9B, 0x0F, 0x2B, 0x7D, 0xD8, 0x4F, 0xF0, 0x00, 0x08, 0xC7, 0xF1, 0x10, 0x03, 0x04, 0xF1, 0xFF, 0x3A, 0x05, 0x94, ++0xDF, 0xF8, 0x14, 0xB1, 0x44, 0x46, 0x98, 0x46, 0x04, 0xE0, 0x58, 0x46, 0x00, 0xF0, 0x9A, 0xFC, 0xA0, 0x45, 0x0C, 0xD0, ++0x1A, 0xEA, 0x04, 0x0F, 0x04, 0xF1, 0x01, 0x04, 0xF5, 0xD1, 0x20, 0x20, 0x00, 0xF0, 0x8E, 0xFC, 0x58, 0x46, 0x00, 0xF0, ++0x8D, 0xFC, 0xA0, 0x45, 0xF2, 0xD1, 0x34, 0x48, 0x05, 0x9C, 0x00, 0xF0, 0x87, 0xFC, 0x03, 0x9B, 0x00, 0x2B, 0x4D, 0xD0, ++0x4F, 0xF0, 0x00, 0x08, 0x15, 0xF8, 0x08, 0x00, 0xA0, 0xF1, 0x1F, 0x03, 0x5F, 0x2B, 0x88, 0xBF, 0x2E, 0x20, 0x08, 0xF1, ++0x01, 0x08, 0x00, 0xF0, 0x75, 0xFC, 0x47, 0x45, 0xF2, 0xD8, 0x35, 0x46, 0x29, 0x48, 0x00, 0xF0, 0x71, 0xFC, 0x03, 0x9B, ++0xDB, 0x1B, 0x03, 0x93, 0x8D, 0xD1, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x03, 0x9B, 0x8B, 0xB3, 0xDF, 0xF8, 0x84, 0xA0, ++0x4F, 0xF0, 0x00, 0x08, 0x09, 0xE0, 0xCD, 0xF8, 0x00, 0xC0, 0xE1, 0xF7, 0x8D, 0xF9, 0x08, 0xF1, 0x04, 0x08, 0x47, 0x45, ++0x05, 0xF1, 0x04, 0x05, 0x1A, 0xD9, 0x28, 0x46, 0xDD, 0xF7, 0xEE, 0xF9, 0x04, 0x2C, 0x06, 0x46, 0x4F, 0xEA, 0x10, 0x6C, ++0xC0, 0xF3, 0x07, 0x43, 0xC0, 0xF3, 0x07, 0x22, 0xC1, 0xB2, 0x48, 0x46, 0x0F, 0xD0, 0x02, 0x2C, 0xE5, 0xD1, 0x15, 0x48, ++0x32, 0x0C, 0xB1, 0xB2, 0x08, 0xF1, 0x04, 0x08, 0xE1, 0xF7, 0x70, 0xF9, 0x47, 0x45, 0x05, 0xF1, 0x04, 0x05, 0xE4, 0xD8, ++0x00, 0x23, 0x04, 0x93, 0xC6, 0xE7, 0x31, 0x46, 0x50, 0x46, 0xE1, 0xF7, 0x65, 0xF9, 0xD6, 0xE7, 0x0A, 0x48, 0x07, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0x00, 0xF0, 0x30, 0xBC, 0x04, 0x9B, 0x00, 0x2B, 0xB8, 0xD0, 0x2E, 0x46, 0x81, 0xE7, 0x04, 0x48, ++0x00, 0xF0, 0x28, 0xFC, 0xA2, 0xE7, 0x00, 0xBF, 0xE0, 0xB5, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0x1C, 0xB6, 0x15, 0x00, ++0xD0, 0x79, 0x15, 0x00, 0xE8, 0xB5, 0x15, 0x00, 0xF4, 0xB5, 0x15, 0x00, 0x14, 0xB6, 0x15, 0x00, 0x0C, 0xB6, 0x15, 0x00, ++0xD4, 0xB5, 0x15, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x22, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x22, 0x4C, 0x22, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0xFE, 0xF7, 0x1E, 0xF9, 0x20, 0x48, 0xFE, 0xF7, ++0x1B, 0xF9, 0x20, 0x49, 0x1D, 0x48, 0xFE, 0xF7, 0x1B, 0xF9, 0x1F, 0x49, 0x1B, 0x48, 0xFE, 0xF7, 0x17, 0xF9, 0x1E, 0x49, ++0x19, 0x48, 0xFE, 0xF7, 0x13, 0xF9, 0x1D, 0x49, 0x17, 0x48, 0xFE, 0xF7, 0x0F, 0xF9, 0x23, 0x68, 0x33, 0xB1, 0x13, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x01, 0x22, ++0x00, 0xF0, 0xFC, 0xFB, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x04, 0x22, 0x00, 0xF0, 0xF6, 0xFB, 0x17, 0x4B, 0x18, 0x49, ++0x18, 0x48, 0x03, 0x22, 0x00, 0xF0, 0xF0, 0xFB, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x04, 0x22, 0x00, 0xF0, 0xEA, 0xFB, ++0xBD, 0xE8, 0x10, 0x40, 0x16, 0x4B, 0x17, 0x49, 0x17, 0x48, 0x02, 0x22, 0x00, 0xF0, 0xE2, 0xBB, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xD8, 0xB8, 0x17, 0x00, 0xC0, 0xB7, 0x17, 0x00, 0xC8, 0xB7, 0x17, 0x00, 0x0C, 0xB8, 0x17, 0x00, ++0x50, 0xB8, 0x17, 0x00, 0x94, 0xB8, 0x17, 0x00, 0x69, 0x4D, 0x14, 0x00, 0x24, 0xB6, 0x15, 0x00, 0x30, 0xB6, 0x15, 0x00, ++0x61, 0x56, 0x14, 0x00, 0x38, 0xB6, 0x15, 0x00, 0x7C, 0xAB, 0x15, 0x00, 0x2D, 0x57, 0x14, 0x00, 0x4C, 0xB6, 0x15, 0x00, ++0x58, 0xB6, 0x15, 0x00, 0xED, 0x55, 0x14, 0x00, 0x5C, 0xB6, 0x15, 0x00, 0x68, 0xB6, 0x15, 0x00, 0x99, 0x57, 0x14, 0x00, ++0x6C, 0xB6, 0x15, 0x00, 0x7C, 0xB6, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x54, 0x4D, 0x55, 0x4E, 0x29, 0x68, 0x31, 0x60, ++0x17, 0x28, 0x04, 0x46, 0x10, 0xD8, 0x17, 0x28, 0x00, 0xF2, 0x8E, 0x80, 0xDF, 0xE8, 0x00, 0xF0, 0x15, 0x8C, 0x8C, 0x71, ++0x8C, 0x8C, 0x8C, 0x8C, 0x48, 0x8C, 0x1A, 0x8C, 0x8C, 0x1A, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x55, 0x8C, 0x60, ++0x7F, 0x28, 0x39, 0xD0, 0x49, 0x4F, 0x3B, 0x68, 0x3D, 0x2B, 0x65, 0xDD, 0x07, 0x20, 0x00, 0xF0, 0x75, 0xFB, 0x4F, 0xF0, ++0xFF, 0x34, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x44, 0x4E, 0x45, 0x48, 0x33, 0x68, 0xDF, 0xF8, 0x20, 0x81, 0x00, 0x22, ++0x1A, 0x70, 0x00, 0xF0, 0x69, 0xFB, 0x34, 0x68, 0xA4, 0xEB, 0x08, 0x04, 0x00, 0x2C, 0xEE, 0xDB, 0x0F, 0xD1, 0x3F, 0x48, ++0x00, 0xF0, 0x60, 0xFB, 0x00, 0x24, 0x3D, 0x48, 0x12, 0xF0, 0x70, 0xF9, 0x38, 0x4B, 0x28, 0x60, 0x00, 0x22, 0xC6, 0xF8, ++0x00, 0x80, 0x1A, 0x60, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x48, 0xFE, 0xF7, 0xB2, 0xF8, 0x07, 0x46, 0x00, 0x28, ++0x48, 0xD0, 0x41, 0x46, 0x04, 0x30, 0x12, 0xF0, 0xED, 0xF8, 0x34, 0x48, 0x39, 0x46, 0xFE, 0xF7, 0x63, 0xF8, 0xE4, 0xE7, ++0x2C, 0x4B, 0x2D, 0x4E, 0x1B, 0x68, 0x30, 0x68, 0x0B, 0xB1, 0xFF, 0xF7, 0xC9, 0xFD, 0x4F, 0xF0, 0xFF, 0x34, 0x30, 0x60, ++0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x27, 0x4A, 0x25, 0x4B, 0x2B, 0x49, 0x11, 0x60, 0x4F, 0xF0, 0xFF, 0x34, 0x00, 0x22, ++0x1A, 0x60, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x4F, 0x21, 0x4E, 0x3B, 0x68, 0x30, 0x68, 0x0B, 0xB9, 0xAE, 0xE7, ++0x29, 0x68, 0xFF, 0xF7, 0xAF, 0xFD, 0x3B, 0x68, 0x30, 0x60, 0x00, 0x2B, 0xA7, 0xDD, 0x03, 0x78, 0x20, 0x2B, 0xF5, 0xD1, ++0xA3, 0xE7, 0xDF, 0xF8, 0x78, 0x80, 0x18, 0x4E, 0x00, 0x23, 0x88, 0xF8, 0x00, 0x30, 0xB0, 0xE7, 0x01, 0x31, 0x20, 0x46, ++0x31, 0x60, 0x00, 0xF0, 0x0D, 0xFB, 0x13, 0x49, 0x0B, 0x68, 0x1C, 0x70, 0x3A, 0x68, 0x01, 0x33, 0x01, 0x32, 0x0B, 0x60, ++0x3A, 0x60, 0x4F, 0xF0, 0xFF, 0x34, 0x8E, 0xE7, 0x13, 0x48, 0x00, 0xF0, 0x01, 0xFB, 0xA0, 0xE7, 0x0A, 0x4F, 0x3B, 0x68, ++0x3D, 0x2B, 0x81, 0xDC, 0x09, 0x28, 0xE5, 0xD1, 0x0F, 0x48, 0x01, 0xF0, 0x07, 0x01, 0x08, 0x44, 0x00, 0xF0, 0xF4, 0xFA, ++0x33, 0x68, 0x23, 0xF0, 0x07, 0x03, 0x08, 0x33, 0x33, 0x60, 0xDE, 0xE7, 0x6C, 0x34, 0x17, 0x00, 0x24, 0x34, 0x17, 0x00, ++0x68, 0x34, 0x17, 0x00, 0xD4, 0x22, 0x17, 0x00, 0xD0, 0x79, 0x15, 0x00, 0xA0, 0xB6, 0x15, 0x00, 0xD8, 0xB8, 0x17, 0x00, ++0xC0, 0xB7, 0x17, 0x00, 0x28, 0x34, 0x17, 0x00, 0x84, 0xB6, 0x15, 0x00, 0x20, 0xB8, 0x15, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, ++0x2C, 0x68, 0x3F, 0x2C, 0x0D, 0xD8, 0x0B, 0x4F, 0x4F, 0xEA, 0x04, 0x1C, 0x07, 0xEB, 0x04, 0x16, 0x01, 0x34, 0x47, 0xF8, ++0x0C, 0x00, 0xC6, 0xE9, 0x01, 0x12, 0xF3, 0x60, 0x2C, 0x60, 0x00, 0x20, 0xF8, 0xBD, 0x05, 0x48, 0xE0, 0xF7, 0xF0, 0xFF, ++0x4F, 0xF0, 0xFF, 0x30, 0xF8, 0xBD, 0x00, 0xBF, 0x20, 0x30, 0x17, 0x00, 0x24, 0x30, 0x17, 0x00, 0xA8, 0xB6, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x95, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x76, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0xDF, 0xF8, 0xFC, 0xB1, 0x75, 0x48, 0xDB, 0xF8, 0x00, 0x30, 0x01, 0x33, 0xCB, 0xF8, 0x00, 0x30, 0xFE, 0xF7, ++0x05, 0xF8, 0xDB, 0xF8, 0x00, 0x30, 0x06, 0x46, 0x3B, 0xB1, 0x6E, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x00, 0x2E, 0x00, 0xF0, 0x94, 0x80, 0x33, 0x1D, 0x03, 0xAC, 0x01, 0x22, 0x4F, 0xF0, ++0x00, 0x0C, 0x57, 0x1E, 0x3D, 0x46, 0x19, 0x46, 0x13, 0xF8, 0x01, 0x0B, 0x20, 0x28, 0xFA, 0xD0, 0x09, 0x28, 0xF8, 0xD0, ++0x00, 0x28, 0x00, 0xF0, 0xA0, 0x80, 0x22, 0x28, 0x00, 0xF0, 0x83, 0x80, 0x21, 0x60, 0x08, 0x78, 0x15, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0xAC, 0x80, 0x0B, 0x46, 0x06, 0xE0, 0x09, 0x28, 0x06, 0xD0, 0x13, 0xF8, 0x01, 0x0F, 0x00, 0x28, 0x00, 0xF0, ++0xA3, 0x80, 0x20, 0x28, 0xF6, 0xD1, 0x19, 0x78, 0x00, 0x29, 0x00, 0xF0, 0x9D, 0x80, 0x01, 0x32, 0x11, 0x2A, 0x03, 0xF8, ++0x01, 0xCB, 0x04, 0xF1, 0x04, 0x04, 0xD4, 0xD1, 0x52, 0x48, 0x10, 0x21, 0xE0, 0xF7, 0x8E, 0xFF, 0x10, 0x25, 0xDD, 0xF8, ++0x0C, 0x90, 0x2E, 0x21, 0x48, 0x46, 0x11, 0xF0, 0x95, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x83, 0x80, 0xA0, 0xEB, 0x09, 0x04, ++0x4B, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x28, 0xDD, 0x4A, 0x4F, 0x01, 0x95, 0x4F, 0xF0, 0x00, 0x08, 0xC2, 0x46, 0x3D, 0x46, ++0x05, 0xE0, 0x46, 0x4B, 0x1A, 0x68, 0x92, 0x45, 0x07, 0xF1, 0x10, 0x07, 0x16, 0xDA, 0x39, 0x68, 0x22, 0x46, 0x48, 0x46, ++0x0A, 0xF1, 0x01, 0x0A, 0x12, 0xF0, 0xBE, 0xF8, 0x00, 0x28, 0xF0, 0xD1, 0x38, 0x68, 0x12, 0xF0, 0x4B, 0xF8, 0x84, 0x42, ++0x43, 0xD0, 0x3C, 0x4B, 0x1A, 0x68, 0x92, 0x45, 0x3D, 0x46, 0x08, 0xF1, 0x01, 0x08, 0x07, 0xF1, 0x10, 0x07, 0xE8, 0xDB, ++0xB8, 0xF1, 0x01, 0x0F, 0x2B, 0x46, 0x01, 0x9D, 0x37, 0xD0, 0x03, 0x99, 0x36, 0x48, 0xE0, 0xF7, 0x51, 0xFF, 0x36, 0x48, ++0x00, 0xF0, 0x20, 0xFA, 0x35, 0x48, 0x00, 0xF0, 0x1D, 0xFA, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x2A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDB, 0xF8, 0x00, 0x30, 0x30, 0x48, 0x01, 0x33, 0x31, 0x46, 0xCB, 0xF8, 0x00, 0x30, ++0xFD, 0xF7, 0x2A, 0xFF, 0x25, 0x48, 0xFD, 0xF7, 0x6B, 0xFF, 0xDB, 0xF8, 0x00, 0x30, 0x06, 0x46, 0x00, 0x2B, 0x7F, 0xF4, ++0x64, 0xAF, 0x00, 0x2E, 0x7F, 0xF4, 0x6C, 0xAF, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0x1C, 0x23, 0x60, 0x49, 0x78, ++0x15, 0x46, 0x19, 0xB9, 0x28, 0xE0, 0x13, 0xF8, 0x01, 0x1F, 0x29, 0xB3, 0x22, 0x29, 0xFA, 0xD1, 0x81, 0xE7, 0x01, 0x9D, ++0x3B, 0x46, 0x9A, 0x68, 0xAA, 0x42, 0x24, 0xDB, 0xDB, 0x68, 0x00, 0x2B, 0xC8, 0xD0, 0x28, 0x46, 0x03, 0xA9, 0x98, 0x47, ++0x00, 0x28, 0xC3, 0xD0, 0xBF, 0xE7, 0x14, 0xAB, 0x03, 0xEB, 0x87, 0x03, 0x43, 0xF8, 0x44, 0x0C, 0x00, 0x2F, 0xB8, 0xD0, ++0xDD, 0xF8, 0x0C, 0x90, 0x2E, 0x21, 0x48, 0x46, 0x11, 0xF0, 0x12, 0xFF, 0x00, 0x28, 0x7F, 0xF4, 0x7D, 0xAF, 0x48, 0x46, ++0x11, 0xF0, 0xE4, 0xFF, 0x04, 0x46, 0x79, 0xE7, 0x14, 0xAB, 0x03, 0xEB, 0x82, 0x02, 0x00, 0x23, 0x42, 0xF8, 0x44, 0x3C, ++0x67, 0xE7, 0x59, 0x68, 0x0A, 0x48, 0xE0, 0xF7, 0xF1, 0xFE, 0x9E, 0xE7, 0x38, 0x61, 0x17, 0x00, 0xC0, 0xB7, 0x17, 0x00, ++0xC4, 0xB6, 0x15, 0x00, 0x20, 0x30, 0x17, 0x00, 0x24, 0x30, 0x17, 0x00, 0xE4, 0xB6, 0x15, 0x00, 0x08, 0xB7, 0x15, 0x00, ++0xA0, 0xB6, 0x15, 0x00, 0xD8, 0xB8, 0x17, 0x00, 0xFC, 0xB6, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF0, 0xB4, 0x05, 0x78, ++0x30, 0x2D, 0x2B, 0xD0, 0x00, 0x2A, 0x08, 0xBF, 0x0A, 0x22, 0x2D, 0x2D, 0x32, 0xD0, 0x00, 0x27, 0x00, 0x26, 0xA5, 0xF1, ++0x30, 0x03, 0x5F, 0xFA, 0x83, 0xFC, 0x25, 0xF0, 0x20, 0x04, 0xBC, 0xF1, 0x09, 0x0F, 0xA4, 0xF1, 0x41, 0x04, 0x12, 0xD9, ++0x05, 0x2C, 0x06, 0xD9, 0x07, 0xB1, 0x76, 0x42, 0x01, 0xB1, 0x08, 0x60, 0x30, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0xA5, 0xF1, ++0x61, 0x04, 0xA5, 0xF1, 0x20, 0x03, 0x19, 0x2C, 0xDB, 0xB2, 0x94, 0xBF, 0x37, 0x3B, 0xA5, 0xF1, 0x37, 0x03, 0x93, 0x42, ++0xEC, 0xD2, 0x10, 0xF8, 0x01, 0x5F, 0x02, 0xFB, 0x06, 0x36, 0xDA, 0xE7, 0x45, 0x78, 0x78, 0x2D, 0x00, 0xF1, 0x01, 0x03, ++0x0A, 0xD0, 0x18, 0x46, 0x00, 0x2A, 0xCE, 0xD1, 0x2D, 0x2D, 0x4F, 0xF0, 0x08, 0x02, 0xCC, 0xD1, 0x01, 0x27, 0x45, 0x78, ++0x38, 0x44, 0xC9, 0xE7, 0x84, 0x78, 0xA4, 0xF1, 0x30, 0x06, 0x09, 0x2E, 0x09, 0xD9, 0x24, 0xF0, 0x20, 0x06, 0x41, 0x3E, ++0x05, 0x2E, 0x04, 0xD9, 0x3A, 0xB9, 0x17, 0x46, 0x18, 0x46, 0x08, 0x22, 0xBA, 0xE7, 0x02, 0x30, 0x25, 0x46, 0x10, 0x22, ++0xB3, 0xE7, 0x18, 0x46, 0xB3, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x0A, 0x22, 0x0C, 0x46, 0x05, 0x46, 0x48, 0x68, 0x00, 0x21, ++0xFF, 0xF7, 0xA2, 0xFF, 0xC0, 0xB1, 0x01, 0x28, 0x10, 0xD1, 0x02, 0x2D, 0x1C, 0xDD, 0x10, 0x22, 0xA0, 0x68, 0x00, 0x21, ++0xFF, 0xF7, 0x98, 0xFF, 0x0E, 0x4B, 0x1B, 0x68, 0x01, 0x46, 0x19, 0x80, 0x0D, 0x48, 0x89, 0xB2, 0xFF, 0xF7, 0x34, 0xF8, ++0x00, 0x20, 0x38, 0xBD, 0x01, 0x46, 0x0B, 0x48, 0xFF, 0xF7, 0x2E, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x4B, 0x09, 0x48, ++0x1B, 0x68, 0x19, 0x88, 0xFF, 0xF7, 0x26, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x48, 0xFF, 0xF7, 0x21, 0xF8, 0x00, 0x20, ++0x38, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x2C, 0xB7, 0x15, 0x00, 0x50, 0xB7, 0x15, 0x00, 0x18, 0xB7, 0x15, 0x00, ++0x40, 0xB7, 0x15, 0x00, 0x01, 0x28, 0xF8, 0xB5, 0x2A, 0xDD, 0x0D, 0x46, 0x04, 0x46, 0x10, 0x22, 0x68, 0x68, 0x00, 0x21, ++0xFF, 0xF7, 0x66, 0xFF, 0x02, 0x2C, 0x06, 0x46, 0x0D, 0xD1, 0x03, 0x0E, 0x01, 0x2B, 0x22, 0xD0, 0x03, 0x0D, 0xB3, 0xF5, ++0xA0, 0x6F, 0x1E, 0xD0, 0x32, 0x68, 0x24, 0x48, 0x31, 0x46, 0xFE, 0xF7, 0xFB, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0x22, ++0xA8, 0x68, 0x11, 0x46, 0x00, 0xF0, 0x18, 0xF9, 0x03, 0x2C, 0x07, 0x46, 0x19, 0xD1, 0x04, 0x20, 0x01, 0x2F, 0x1C, 0xD0, ++0xC2, 0xB2, 0x39, 0x46, 0x30, 0x46, 0x00, 0x23, 0xFF, 0xF7, 0xFE, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x18, 0x48, 0xFE, 0xF7, ++0xE3, 0xFF, 0x01, 0x20, 0xF8, 0xBD, 0x30, 0x46, 0xDC, 0xF7, 0x7E, 0xFE, 0x31, 0x46, 0x02, 0x46, 0x12, 0x48, 0xFE, 0xF7, ++0xD9, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0x22, 0xE8, 0x68, 0x11, 0x46, 0xFF, 0xF7, 0x2E, 0xFF, 0xE0, 0xE7, 0x33, 0x0E, ++0x01, 0x2B, 0xEC, 0xD0, 0x33, 0x0D, 0xB3, 0xF5, 0xA0, 0x6F, 0xE8, 0xD0, 0x01, 0x28, 0x06, 0xD1, 0x32, 0x78, 0x0A, 0x48, ++0x31, 0x46, 0xFE, 0xF7, 0xC3, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x02, 0x28, 0xBE, 0xD1, 0x32, 0x88, 0x06, 0x48, 0x92, 0xB2, ++0x31, 0x46, 0xFE, 0xF7, 0xB9, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x7C, 0xB7, 0x15, 0x00, 0x64, 0xB7, 0x15, 0x00, ++0x90, 0xB7, 0x15, 0x00, 0xA4, 0xB7, 0x15, 0x00, 0x02, 0x28, 0x38, 0xB5, 0x21, 0xDD, 0x0D, 0x46, 0x10, 0x22, 0x68, 0x68, ++0x00, 0x21, 0xFF, 0xF7, 0x01, 0xFF, 0x10, 0x22, 0x04, 0x46, 0x00, 0x21, 0xA8, 0x68, 0xFF, 0xF7, 0xFB, 0xFE, 0x21, 0x46, ++0x02, 0x46, 0x05, 0x46, 0x0F, 0x48, 0xFE, 0xF7, 0x99, 0xFF, 0x23, 0x0E, 0x01, 0x2B, 0x06, 0xD0, 0x23, 0x0D, 0xB3, 0xF5, ++0xA0, 0x6F, 0x0D, 0xD0, 0x25, 0x60, 0x00, 0x20, 0x38, 0xBD, 0x20, 0x46, 0x29, 0x46, 0xDC, 0xF7, 0x53, 0xFE, 0x00, 0x20, ++0x38, 0xBD, 0x07, 0x48, 0xFE, 0xF7, 0x86, 0xFF, 0x01, 0x20, 0x38, 0xBD, 0xB4, 0xF1, 0xA0, 0x4F, 0xF1, 0xD1, 0x28, 0x46, ++0xDC, 0xF7, 0xF6, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x7C, 0xB7, 0x15, 0x00, 0xB8, 0xB7, 0x15, 0x00, 0x02, 0x28, 0x38, 0xB5, ++0x46, 0xDC, 0x01, 0x28, 0x32, 0xD0, 0x00, 0x22, 0x48, 0x68, 0x11, 0x46, 0xFF, 0xF7, 0xCA, 0xFE, 0x25, 0x4A, 0x26, 0x4B, ++0x02, 0xFB, 0x00, 0xF2, 0x9A, 0x42, 0x04, 0x46, 0x3E, 0xD8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x21, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x21, 0x4D, 0x21, 0x49, 0x2B, 0x68, 0x0A, 0x60, 0x01, 0x33, 0x2B, 0x60, 0x82, 0xB1, ++0x1F, 0x49, 0x09, 0x78, 0xF9, 0xB9, 0x33, 0xB1, 0x1A, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x1B, 0x48, 0x21, 0x46, 0xFE, 0xF7, 0x49, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, ++0xFC, 0xF7, 0xE8, 0xFF, 0x2B, 0x68, 0xEA, 0xE7, 0x12, 0x4A, 0x15, 0x4B, 0x11, 0x68, 0x15, 0x48, 0xA3, 0xFB, 0x01, 0x31, ++0x89, 0x0C, 0xFE, 0xF7, 0x37, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0xFC, 0xF7, 0x26, 0xFF, ++0x2B, 0x68, 0xD8, 0xE7, 0x0E, 0x48, 0xFE, 0xF7, 0x2B, 0xFF, 0x4F, 0xF0, 0xFF, 0x30, 0x38, 0xBD, 0x0C, 0x48, 0xFE, 0xF7, ++0x25, 0xFF, 0x4F, 0xF0, 0xFF, 0x30, 0x38, 0xBD, 0x40, 0x42, 0x0F, 0x00, 0xFF, 0xA2, 0xE1, 0x11, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x6C, 0x60, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0xF8, 0xB7, 0x15, 0x00, 0x83, 0xDE, 0x1B, 0x43, ++0xE8, 0xB7, 0x15, 0x00, 0xD0, 0xB7, 0x15, 0x00, 0x08, 0xB8, 0x15, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0x01, 0xE0, 0x04, 0x2A, ++0x05, 0xD0, 0x23, 0x68, 0x03, 0xF0, 0x0F, 0x02, 0xDB, 0x07, 0xF8, 0xD5, 0x10, 0xBD, 0xE0, 0xF7, 0x1D, 0xFC, 0xFF, 0xF7, ++0x6B, 0xFC, 0xF4, 0xE7, 0x08, 0x10, 0x04, 0x40, 0xE0, 0xF7, 0x0A, 0xBC, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x78, 0x28, 0xB1, ++0xE0, 0xF7, 0x04, 0xFC, 0x14, 0xF8, 0x01, 0x0F, 0x00, 0x28, 0xF9, 0xD1, 0x10, 0xBD, 0x00, 0xBF, 0x10, 0xB5, 0x04, 0x4C, ++0xD4, 0xF8, 0xB8, 0x30, 0x98, 0x47, 0xD4, 0xF8, 0x28, 0x33, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0xFF, 0xF7, 0x2E, 0xBD, 0xFF, 0xF7, 0x0C, 0xBD, 0xFF, 0xF7, 0x36, 0xBE, 0x70, 0xB4, 0x02, 0x68, 0x1C, 0x4C, 0x2D, 0x21, ++0xA3, 0x89, 0x11, 0x70, 0x02, 0x68, 0x1A, 0x21, 0x51, 0x70, 0x23, 0xF0, 0x1C, 0x03, 0x02, 0x68, 0x9B, 0xB2, 0x43, 0xF0, ++0x0C, 0x03, 0x53, 0x80, 0xA3, 0x7B, 0x13, 0x71, 0x06, 0x68, 0x04, 0xF1, 0x0F, 0x03, 0x04, 0xF1, 0x1F, 0x05, 0x13, 0xF8, ++0x01, 0x1B, 0x1A, 0x1B, 0x32, 0x44, 0xAB, 0x42, 0x02, 0xF8, 0x0B, 0x1C, 0xF7, 0xD1, 0x01, 0x68, 0x0E, 0x4A, 0x00, 0x23, ++0xCB, 0x73, 0x01, 0x68, 0x0B, 0x74, 0x05, 0x68, 0x23, 0x8C, 0xA5, 0xF8, 0x15, 0x30, 0x05, 0xF1, 0x17, 0x03, 0x1B, 0x35, ++0x12, 0xF8, 0x01, 0x1B, 0x03, 0xF8, 0x01, 0x1B, 0xAB, 0x42, 0xF9, 0xD1, 0x03, 0x68, 0x94, 0xF8, 0x28, 0x20, 0xDA, 0x76, ++0x03, 0x68, 0x1C, 0x33, 0x03, 0x60, 0x70, 0xBC, 0x1C, 0x20, 0x70, 0x47, 0xE4, 0xB8, 0x17, 0x00, 0x08, 0xB9, 0x17, 0x00, ++0x03, 0x68, 0x28, 0x4A, 0xFF, 0x21, 0x70, 0xB4, 0x19, 0x70, 0x03, 0x68, 0x23, 0x21, 0x99, 0x70, 0x05, 0x68, 0xEB, 0x1C, ++0x05, 0xF1, 0x09, 0x04, 0x12, 0xF8, 0x01, 0x1F, 0x03, 0xF8, 0x01, 0x1B, 0xA3, 0x42, 0xF9, 0xD1, 0x20, 0x4A, 0xA2, 0xF1, ++0x41, 0x01, 0x02, 0xF1, 0x0B, 0x06, 0xA2, 0xF1, 0x38, 0x03, 0x12, 0xF8, 0x01, 0x4F, 0x5B, 0x1A, 0xB2, 0x42, 0x5C, 0x55, ++0xF7, 0xD1, 0x91, 0xF8, 0x42, 0x30, 0xB1, 0xF8, 0x50, 0x40, 0xB1, 0xF8, 0x4E, 0x20, 0xEC, 0x82, 0x1C, 0x07, 0xAA, 0x82, ++0x05, 0xF1, 0x18, 0x06, 0x4F, 0xEA, 0x63, 0x02, 0x07, 0xD5, 0xB1, 0xF8, 0x52, 0x40, 0xB1, 0xF8, 0x54, 0x30, 0x6B, 0x83, ++0x2C, 0x83, 0x05, 0xF1, 0x1C, 0x06, 0x13, 0x07, 0x04, 0xD5, 0xB1, 0xF8, 0x56, 0x30, 0x33, 0x80, 0x73, 0x80, 0x04, 0x36, ++0x0C, 0x4C, 0x32, 0x46, 0x14, 0xF8, 0x01, 0x5F, 0x15, 0x70, 0x91, 0xF8, 0x75, 0x51, 0x93, 0x1B, 0x9D, 0x42, 0x02, 0xF1, ++0x01, 0x02, 0xF5, 0xDA, 0x03, 0x68, 0xD2, 0x1A, 0x91, 0x1E, 0x59, 0x70, 0x03, 0x68, 0x13, 0x44, 0x03, 0x60, 0x70, 0xBC, ++0x10, 0x46, 0x70, 0x47, 0x1F, 0xB9, 0x17, 0x00, 0x25, 0xB9, 0x17, 0x00, 0x3D, 0xB9, 0x17, 0x00, 0x70, 0xB4, 0x0F, 0x4C, ++0x03, 0x46, 0x22, 0x6B, 0x09, 0xB1, 0x22, 0xF4, 0xC0, 0x52, 0x19, 0x68, 0xBF, 0x20, 0x08, 0x70, 0x19, 0x68, 0x0C, 0x20, ++0x48, 0x70, 0x18, 0x68, 0xA1, 0x8E, 0xC0, 0xF8, 0x02, 0x20, 0x1A, 0x68, 0x60, 0x8F, 0xE6, 0x8E, 0x25, 0x8F, 0xD1, 0x80, ++0x02, 0xF1, 0x0E, 0x01, 0x16, 0x81, 0x55, 0x81, 0x90, 0x81, 0x70, 0xBC, 0x0E, 0x20, 0x19, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0xE4, 0xB8, 0x17, 0x00, 0x03, 0x68, 0x10, 0xB4, 0xC7, 0x24, 0x1C, 0x70, 0x03, 0x68, 0x01, 0x24, 0x5C, 0x70, 0x03, 0x68, ++0x42, 0xEA, 0x01, 0x11, 0x99, 0x70, 0x03, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x03, 0x33, 0x03, 0x60, 0x03, 0x20, 0x70, 0x47, ++0x03, 0x68, 0x46, 0x22, 0x1A, 0x70, 0x03, 0x68, 0x05, 0x22, 0x5A, 0x70, 0x03, 0x68, 0x70, 0x22, 0x9A, 0x70, 0x02, 0x68, ++0x00, 0x23, 0xD3, 0x70, 0x02, 0x68, 0x13, 0x71, 0x02, 0x68, 0x53, 0x71, 0x02, 0x68, 0x93, 0x71, 0x03, 0x68, 0x07, 0x33, ++0x03, 0x60, 0x07, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x30, 0xB4, 0x02, 0x9C, 0x01, 0x80, 0x42, 0x80, 0x83, 0x80, 0x84, 0xB1, ++0x10, 0x22, 0x80, 0x23, 0x82, 0x71, 0xC3, 0x71, 0xE5, 0x18, 0x22, 0x46, 0x13, 0x46, 0x08, 0x33, 0x12, 0xF8, 0x01, 0x1B, ++0x1B, 0x1B, 0xAA, 0x42, 0x19, 0x54, 0xF7, 0xD1, 0x88, 0x20, 0x30, 0xBC, 0x70, 0x47, 0x06, 0x20, 0x30, 0xBC, 0x70, 0x47, ++0x01, 0x80, 0x02, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x8F, 0xB0, 0x1F, 0x46, 0x1A, 0x9E, 0x03, 0x93, ++0x34, 0x8F, 0xB6, 0xF8, 0x36, 0x80, 0x0D, 0x46, 0x03, 0x46, 0x01, 0x2C, 0x38, 0x46, 0x38, 0xBF, 0x01, 0x24, 0x07, 0x93, ++0x17, 0x46, 0x01, 0xF0, 0xC1, 0xFE, 0xB5, 0xF8, 0xAE, 0x90, 0x07, 0x9B, 0x09, 0xF0, 0x10, 0x09, 0x40, 0xEA, 0x09, 0x00, ++0x06, 0xF1, 0x40, 0x02, 0x5C, 0x80, 0x02, 0x92, 0x18, 0x80, 0x1F, 0xFA, 0x80, 0xF9, 0x14, 0x46, 0x00, 0x2F, 0x00, 0xF0, ++0xDE, 0x81, 0x3A, 0x88, 0x9A, 0x80, 0x7A, 0x88, 0xDA, 0x80, 0xBA, 0x88, 0x1A, 0x81, 0x0A, 0x22, 0x17, 0x46, 0x18, 0x99, ++0x98, 0x18, 0x08, 0x60, 0x00, 0x21, 0x07, 0x90, 0x95, 0xF8, 0x7E, 0x00, 0x99, 0x54, 0x07, 0x9B, 0x00, 0xF1, 0x02, 0x0E, ++0x58, 0x70, 0x00, 0x28, 0x40, 0xF0, 0xC7, 0x80, 0x07, 0x9B, 0x95, 0xF8, 0xB0, 0x10, 0x0E, 0xEB, 0x03, 0x00, 0x01, 0x22, ++0x07, 0x90, 0x0E, 0xF8, 0x03, 0x20, 0x07, 0x9B, 0x08, 0x29, 0x8C, 0x46, 0x28, 0xBF, 0x4F, 0xF0, 0x08, 0x0C, 0x83, 0xF8, ++0x01, 0xC0, 0x07, 0x9B, 0x1F, 0xFA, 0x8E, 0xFE, 0x0C, 0xF1, 0x02, 0x0A, 0x05, 0xF1, 0xB1, 0x02, 0x51, 0xB1, 0x0C, 0xF1, ++0xB1, 0x0C, 0xAC, 0x44, 0x12, 0xF8, 0x01, 0x0B, 0xD1, 0x18, 0x49, 0x1B, 0x94, 0x45, 0x01, 0xF8, 0xB0, 0x0C, 0xF7, 0xD1, ++0x95, 0xF8, 0xB0, 0x20, 0xD6, 0x44, 0x0A, 0xEB, 0x03, 0x01, 0x08, 0x2A, 0x77, 0x44, 0x07, 0x91, 0x1A, 0xD9, 0x32, 0x21, ++0x0A, 0xF8, 0x03, 0x10, 0x07, 0x9B, 0xA2, 0xF1, 0x08, 0x01, 0x59, 0x70, 0x02, 0xF1, 0xB1, 0x0C, 0x07, 0x9B, 0xA2, 0xF1, ++0x06, 0x0E, 0xAC, 0x44, 0x05, 0xF1, 0xB9, 0x02, 0x12, 0xF8, 0x01, 0x0B, 0xD1, 0x18, 0x49, 0x1B, 0x94, 0x45, 0x01, 0xF8, ++0xB8, 0x0C, 0xF7, 0xD1, 0x73, 0x44, 0x77, 0x44, 0x07, 0x93, 0xBF, 0xB2, 0x19, 0xF4, 0x80, 0x7F, 0x40, 0xF0, 0xB5, 0x80, ++0x07, 0xA8, 0xFF, 0xF7, 0x3F, 0xFF, 0x47, 0x44, 0x07, 0x9B, 0x80, 0xB2, 0xBF, 0xB2, 0xB8, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, ++0x02, 0x9A, 0x42, 0x44, 0x94, 0x46, 0x14, 0xF8, 0x01, 0x1B, 0xE2, 0x18, 0x92, 0x1B, 0x64, 0x45, 0x02, 0xF8, 0x41, 0x1C, ++0xF7, 0xD1, 0xD5, 0xF8, 0xE0, 0x40, 0x07, 0x44, 0x43, 0x44, 0xE2, 0x07, 0xBF, 0xB2, 0x07, 0x93, 0x1A, 0xD5, 0xB4, 0x4A, ++0x07, 0xCA, 0x0A, 0xAE, 0x03, 0xC6, 0x00, 0x20, 0x0A, 0xA9, 0x32, 0x80, 0xAD, 0xF8, 0x36, 0x00, 0xCD, 0xF8, 0x32, 0x00, ++0x8D, 0xF8, 0x30, 0x00, 0x5B, 0x1A, 0x0C, 0xA8, 0xDD, 0x22, 0x01, 0xE0, 0x11, 0xF8, 0x01, 0x2F, 0x5A, 0x54, 0x88, 0x42, ++0xFA, 0xD1, 0x07, 0x9B, 0x09, 0x37, 0x09, 0x33, 0xBF, 0xB2, 0x07, 0x93, 0xA6, 0x07, 0x04, 0xD5, 0xA6, 0x4B, 0x93, 0xF8, ++0x76, 0x31, 0xDC, 0x07, 0x53, 0xD4, 0xA5, 0x4B, 0x9B, 0x7D, 0x01, 0x2B, 0x5A, 0xD0, 0xD5, 0xF8, 0xE0, 0x30, 0x18, 0x07, ++0x04, 0xD5, 0xA0, 0x4A, 0x92, 0xF8, 0x76, 0x21, 0x51, 0x07, 0x3C, 0xD4, 0x5A, 0x07, 0x22, 0xD5, 0x9C, 0x4D, 0x95, 0xF8, ++0x76, 0x31, 0x9B, 0x07, 0x1D, 0xD5, 0x03, 0x99, 0x9B, 0x4B, 0x9C, 0x4C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x33, ++0x07, 0xA8, 0x93, 0xF8, 0xC0, 0x14, 0xD4, 0xF8, 0x50, 0x21, 0x90, 0x47, 0x07, 0x44, 0x28, 0x8F, 0xD4, 0xF8, 0x4C, 0x61, ++0x01, 0xF0, 0x9A, 0xFC, 0x95, 0xF8, 0x75, 0x21, 0x04, 0x2A, 0x01, 0x46, 0x08, 0xBF, 0x03, 0x22, 0x07, 0xA8, 0xB0, 0x47, ++0xBF, 0xB2, 0x38, 0x44, 0x87, 0xB2, 0x18, 0x9B, 0x1A, 0x68, 0x07, 0x9B, 0x9B, 0x1A, 0x19, 0x9A, 0x38, 0x46, 0x13, 0x80, ++0x0F, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x7F, 0x30, 0x07, 0x9B, 0x28, 0x44, 0x05, 0xF1, 0x7F, 0x02, 0x12, 0xF8, 0x01, 0xCB, ++0xD1, 0x18, 0x49, 0x1B, 0x90, 0x42, 0x01, 0xF8, 0x7E, 0xCC, 0xF7, 0xD1, 0x2B, 0xE7, 0x82, 0x4B, 0x07, 0xA8, 0xD3, 0xF8, ++0x44, 0x31, 0x98, 0x47, 0x38, 0x44, 0xD5, 0xF8, 0xE0, 0x30, 0x87, 0xB2, 0xB8, 0xE7, 0x7D, 0x4B, 0x07, 0xA8, 0xD3, 0xF8, ++0x48, 0x31, 0x98, 0x47, 0x78, 0x4B, 0x9B, 0x7D, 0x38, 0x44, 0x01, 0x2B, 0x87, 0xB2, 0xA4, 0xD1, 0xB5, 0xF8, 0xE4, 0x30, ++0x00, 0x2B, 0xA0, 0xD0, 0x07, 0x9B, 0x36, 0x22, 0x1A, 0x70, 0x07, 0x9B, 0x03, 0x22, 0x5A, 0x70, 0x07, 0x9B, 0xB5, 0xF8, ++0xE4, 0x20, 0x5A, 0x80, 0x95, 0xF8, 0xE6, 0x20, 0x1A, 0x71, 0x07, 0x9B, 0x05, 0x37, 0x05, 0x33, 0xBF, 0xB2, 0x07, 0x93, ++0x8D, 0xE7, 0x07, 0x9B, 0x21, 0x22, 0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x02, 0x22, 0x59, 0x1C, 0x07, 0x91, ++0x0A, 0xA8, 0x1A, 0x70, 0x0D, 0xF1, 0x27, 0x01, 0xDB, 0xF7, 0x8E, 0xFE, 0xD5, 0xF8, 0xA4, 0x30, 0x9D, 0xF9, 0x28, 0x20, ++0x93, 0xF9, 0x04, 0x30, 0x9A, 0x42, 0xC8, 0xBF, 0x8D, 0xF8, 0x28, 0x30, 0x07, 0x9B, 0x9D, 0xF8, 0x27, 0x20, 0x59, 0x1C, ++0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x9D, 0xF8, 0x28, 0x20, 0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x24, 0x22, ++0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x04, 0x93, 0x1A, 0x46, 0x02, 0xF1, 0x01, 0x0B, 0xD5, 0xF8, 0xA4, 0x30, ++0xCD, 0xF8, 0x1C, 0xB0, 0x9B, 0x78, 0x4F, 0x4A, 0x00, 0x2B, 0x52, 0xD1, 0x01, 0x23, 0x92, 0xF8, 0x72, 0xA1, 0x05, 0x93, ++0x76, 0x32, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x8C, 0x80, 0x00, 0x21, 0x06, 0x95, 0x01, 0x91, 0x08, 0x46, 0x8E, 0x46, ++0xA1, 0x46, 0x0D, 0x46, 0x1A, 0x96, 0xD3, 0x78, 0x13, 0xF0, 0x02, 0x03, 0x1F, 0xD1, 0x94, 0x78, 0xB2, 0xF8, 0x00, 0xC0, ++0x00, 0x2C, 0x43, 0xD1, 0xAC, 0xF6, 0x6C, 0x14, 0x48, 0x2C, 0x3A, 0xD8, 0x40, 0xF6, 0xB4, 0x13, 0x9C, 0x45, 0x6F, 0xD0, ++0x40, 0x4C, 0xAC, 0xF6, 0x67, 0x13, 0xA4, 0xFB, 0x03, 0x43, 0x9C, 0x08, 0xC3, 0xF3, 0x87, 0x03, 0x00, 0x28, 0x45, 0xD0, ++0xA4, 0xEB, 0x0E, 0x0E, 0x05, 0x9C, 0xA6, 0x45, 0x44, 0xD1, 0x01, 0x30, 0xC0, 0xB2, 0x9E, 0x46, 0x06, 0x32, 0x01, 0x31, ++0xCB, 0xB2, 0x9A, 0x45, 0xD7, 0xD8, 0x01, 0x9B, 0x1A, 0x9E, 0x03, 0xF1, 0x02, 0x0E, 0x29, 0x46, 0x5F, 0xFA, 0x8E, 0xF3, ++0x06, 0x9D, 0x4C, 0x46, 0x9E, 0x46, 0x0B, 0xF1, 0x01, 0x02, 0x07, 0x92, 0x8B, 0xF8, 0x00, 0x10, 0x07, 0x9A, 0x51, 0x1C, ++0x07, 0x91, 0x06, 0x37, 0x10, 0x70, 0x04, 0x9A, 0x1E, 0xFA, 0x87, 0xF7, 0xBF, 0xB2, 0x13, 0x70, 0xC0, 0xE6, 0x04, 0x23, ++0x92, 0xF8, 0x73, 0xA1, 0x05, 0x93, 0xCA, 0x32, 0xAB, 0xE7, 0xD8, 0xB9, 0x86, 0x46, 0x05, 0x46, 0x01, 0x20, 0xD5, 0xE7, ++0x01, 0x2C, 0xF8, 0xD1, 0xAC, 0xF5, 0x9C, 0x5C, 0xAC, 0xF1, 0x0D, 0x04, 0xA4, 0xB2, 0xB4, 0xF5, 0x4D, 0x7F, 0xF0, 0xD8, ++0x1D, 0x4B, 0xAC, 0xF1, 0x08, 0x0C, 0xA3, 0xFB, 0x0C, 0x43, 0x9C, 0x08, 0xC3, 0xF3, 0x87, 0x03, 0x00, 0x28, 0xB9, 0xD1, ++0x9E, 0x46, 0x1D, 0x46, 0x01, 0x20, 0xBD, 0xE7, 0x0B, 0xF1, 0x01, 0x04, 0x07, 0x94, 0x8B, 0xF8, 0x00, 0x50, 0x07, 0x9C, ++0x01, 0x9E, 0x04, 0xF1, 0x01, 0x0C, 0x06, 0xF1, 0x02, 0x0E, 0xCD, 0xF8, 0x1C, 0xC0, 0x00, 0xF1, 0x02, 0x0C, 0x20, 0x70, ++0x5F, 0xFA, 0x8E, 0xF0, 0x01, 0x90, 0xDD, 0xF8, 0x1C, 0xB0, 0x9E, 0x46, 0x5F, 0xFA, 0x8C, 0xF0, 0xA4, 0xE7, 0x04, 0x22, ++0x17, 0x46, 0x26, 0xE6, 0x0E, 0x23, 0x1C, 0x46, 0x94, 0xE7, 0x02, 0x23, 0x50, 0x46, 0x51, 0x46, 0x9E, 0x46, 0xA8, 0xE7, ++0x2C, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xCD, 0xCC, 0xCC, 0xCC, 0x03, 0x22, 0x00, 0x23, 0x30, 0xB4, 0x02, 0x70, 0x43, 0x70, 0x4B, 0x7C, 0x83, 0x70, 0x0B, 0x7C, ++0x8C, 0x7B, 0xCA, 0x7B, 0x4D, 0x89, 0xA0, 0xF8, 0x05, 0x50, 0x9B, 0x00, 0x43, 0xEA, 0x44, 0x03, 0x43, 0xEA, 0x82, 0x13, ++0xA0, 0xF8, 0x03, 0x30, 0x0B, 0x89, 0x1B, 0x01, 0xA0, 0xF8, 0x07, 0x30, 0x30, 0xBC, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, ++0x30, 0xB4, 0x22, 0xF0, 0x01, 0x02, 0xBD, 0xF8, 0x08, 0x40, 0xA0, 0xF8, 0x05, 0x20, 0x03, 0x25, 0x01, 0x22, 0xA0, 0xF8, ++0x03, 0x40, 0x83, 0x70, 0x05, 0x70, 0x42, 0x70, 0x2C, 0xB1, 0x00, 0x23, 0xC3, 0x71, 0x03, 0x72, 0x30, 0xBC, 0x09, 0x20, ++0x70, 0x47, 0x4B, 0x89, 0xA0, 0xF8, 0x07, 0x30, 0x30, 0xBC, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x10, 0xB4, 0x02, 0x23, ++0x03, 0x24, 0x04, 0x70, 0x43, 0x70, 0x0B, 0x7C, 0x49, 0x7B, 0x5D, 0xF8, 0x04, 0x4B, 0x82, 0x80, 0x1B, 0x03, 0x9B, 0xB2, ++0x01, 0x29, 0x08, 0xBF, 0x43, 0xF4, 0x00, 0x63, 0x43, 0x80, 0x06, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, ++0x82, 0xB0, 0x16, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0x07, 0x46, 0x88, 0x46, 0xFD, 0xF7, 0x7A, 0xFB, 0xA8, 0xB3, 0x9D, 0xF8, ++0x07, 0x40, 0x83, 0x1C, 0x7C, 0xB1, 0x02, 0x34, 0x20, 0x44, 0x00, 0x24, 0x1D, 0x78, 0x25, 0xF0, 0x81, 0x02, 0x7E, 0x2A, ++0x03, 0xF1, 0x01, 0x03, 0x03, 0xD0, 0x32, 0x19, 0x01, 0x34, 0x55, 0x70, 0xE4, 0xB2, 0x98, 0x42, 0xF2, 0xD1, 0x0D, 0xF1, ++0x07, 0x02, 0x41, 0x46, 0x38, 0x46, 0xFD, 0xF7, 0x7F, 0xFB, 0xB0, 0xB1, 0x9D, 0xF8, 0x07, 0x30, 0x81, 0x1C, 0x93, 0xB1, ++0x02, 0x33, 0x1F, 0x18, 0x0A, 0x78, 0x22, 0xF0, 0x81, 0x00, 0x63, 0x1C, 0x7E, 0x28, 0x06, 0xEB, 0x04, 0x05, 0x01, 0xF1, ++0x01, 0x01, 0xDB, 0xB2, 0x03, 0xD0, 0x0B, 0x2B, 0x6A, 0x70, 0x1C, 0x46, 0x01, 0xD8, 0x8F, 0x42, 0xEE, 0xD1, 0x34, 0x70, ++0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x04, 0x46, 0x34, 0x70, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x10, 0xB5, 0x14, 0x46, ++0xFD, 0xF7, 0xE8, 0xFC, 0x00, 0xB1, 0x80, 0x78, 0x84, 0xF8, 0xDA, 0x00, 0x10, 0xBD, 0x00, 0xBF, 0xF0, 0xB5, 0x83, 0xB0, ++0x14, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0xFD, 0xF7, 0x8B, 0xFB, 0x60, 0xB3, 0xD4, 0xF8, 0xA4, 0xE0, 0x9E, 0xF8, 0x02, 0x40, ++0x4C, 0xB3, 0x01, 0x2C, 0xBE, 0xF8, 0x00, 0x30, 0x40, 0xD0, 0x00, 0x24, 0x04, 0x25, 0x9D, 0xF8, 0x07, 0x70, 0x02, 0x37, ++0xFF, 0xB2, 0x08, 0x2F, 0x8D, 0xF8, 0x07, 0x70, 0x19, 0xD9, 0x05, 0x26, 0x06, 0xEB, 0x00, 0x0C, 0x33, 0x5C, 0x9C, 0xF8, ++0x01, 0x10, 0x69, 0xB1, 0x9C, 0x42, 0x25, 0xD0, 0x01, 0x39, 0xC9, 0xB2, 0x00, 0x22, 0x01, 0xE0, 0x9C, 0x42, 0x1F, 0xD0, ++0x2B, 0x44, 0x8A, 0x42, 0xDB, 0xB2, 0x02, 0xF1, 0x01, 0x02, 0xF7, 0xD1, 0x03, 0x36, 0xF6, 0xB2, 0xF3, 0x1C, 0x9F, 0x42, ++0xE6, 0xDC, 0x03, 0xB0, 0xF0, 0xBD, 0xBE, 0xF8, 0x00, 0x30, 0xA3, 0xF6, 0x6C, 0x12, 0x48, 0x2A, 0x12, 0xD8, 0x40, 0xF6, ++0xB4, 0x12, 0x93, 0x42, 0x20, 0xD0, 0x12, 0x4A, 0xA3, 0xF6, 0x67, 0x14, 0xA2, 0xFB, 0x04, 0x34, 0xC4, 0xF3, 0x87, 0x04, ++0x01, 0x25, 0xC8, 0xE7, 0x9C, 0xF8, 0x02, 0x30, 0x8E, 0xF8, 0x04, 0x30, 0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x25, 0xC0, 0xE7, ++0xA3, 0xF5, 0x9C, 0x53, 0xA3, 0xF1, 0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, 0x4D, 0x7F, 0xB6, 0xD8, 0x05, 0x4C, 0x08, 0x3B, ++0xA4, 0xFB, 0x03, 0x34, 0xC4, 0xF3, 0x87, 0x04, 0x04, 0x25, 0xB0, 0xE7, 0x0E, 0x24, 0x01, 0x25, 0xAD, 0xE7, 0x00, 0xBF, ++0xCD, 0xCC, 0xCC, 0xCC, 0x10, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0x96, 0xFC, 0x48, 0xB1, 0x83, 0x78, 0xC2, 0x78, 0x43, 0xEA, ++0x02, 0x23, 0xA4, 0xF8, 0xE4, 0x30, 0x03, 0x79, 0x84, 0xF8, 0xE6, 0x30, 0x10, 0xBD, 0x84, 0xF8, 0xE6, 0x00, 0xA4, 0xF8, ++0xE4, 0x00, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x82, 0xB0, 0x1C, 0x46, 0x05, 0x46, 0x0E, 0x46, 0x91, 0x46, 0xFD, 0xF7, ++0x49, 0xFB, 0x31, 0x46, 0x07, 0x46, 0x28, 0x46, 0xFD, 0xF7, 0x64, 0xFB, 0x57, 0xEA, 0x00, 0x03, 0x72, 0xD0, 0x80, 0x46, ++0x0D, 0xF1, 0x07, 0x02, 0x31, 0x46, 0x28, 0x46, 0xFD, 0xF7, 0x7A, 0xFB, 0x82, 0x46, 0x18, 0xB1, 0x9D, 0xF8, 0x07, 0x30, ++0x00, 0x2B, 0x65, 0xD0, 0x31, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0x28, 0x46, 0xFD, 0xF7, 0x90, 0xFB, 0x01, 0x46, 0x00, 0x28, ++0x58, 0xD1, 0x00, 0x2F, 0x7A, 0xD0, 0xBB, 0x78, 0x38, 0x79, 0x89, 0xF8, 0x00, 0x30, 0x97, 0xF8, 0x03, 0xC0, 0x00, 0x28, ++0x08, 0xBF, 0x02, 0x20, 0xBC, 0xF1, 0x0E, 0x0F, 0x0C, 0xF1, 0xFF, 0x33, 0x8C, 0xBF, 0x01, 0x27, 0x00, 0x27, 0x4D, 0xD8, ++0x0D, 0x2B, 0x70, 0xD8, 0xBC, 0xF1, 0x0E, 0x0F, 0x00, 0xF0, 0x97, 0x80, 0x0C, 0xEB, 0x8C, 0x06, 0x06, 0xF6, 0x67, 0x16, ++0x00, 0x29, 0x4A, 0xD0, 0x8D, 0x78, 0xCA, 0x78, 0x91, 0xF8, 0x04, 0xE0, 0x05, 0xF1, 0xFF, 0x38, 0xB8, 0xF1, 0x02, 0x0F, ++0x9A, 0xBF, 0x01, 0x35, 0xED, 0xB2, 0x01, 0x25, 0xBC, 0xF1, 0x0E, 0x0F, 0x93, 0xB2, 0x1F, 0xFA, 0x8E, 0xF1, 0x57, 0xD8, ++0x02, 0xF1, 0xFF, 0x3C, 0xBC, 0xF1, 0x0D, 0x0F, 0x72, 0xD8, 0x0E, 0x2A, 0x00, 0xF0, 0x90, 0x80, 0x03, 0xEB, 0x83, 0x03, ++0x03, 0xF6, 0x67, 0x13, 0x61, 0xB1, 0x0E, 0xF1, 0xFF, 0x32, 0x0D, 0x2A, 0x60, 0xD8, 0xBE, 0xF1, 0x0E, 0x0F, 0x00, 0xF0, ++0x9A, 0x80, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF6, 0x67, 0x11, 0x89, 0xB2, 0x4B, 0x4A, 0x92, 0xF8, 0x75, 0x21, 0xAA, 0x42, ++0x24, 0xD2, 0x01, 0x2A, 0x67, 0xD0, 0x02, 0x2A, 0x5E, 0xD0, 0x00, 0x2A, 0x08, 0xBF, 0x33, 0x46, 0x15, 0x46, 0x1B, 0xE0, ++0x9D, 0xF8, 0x07, 0x30, 0x00, 0x2B, 0xA2, 0xD1, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xA4, 0x2B, 0x22, 0xD8, ++0x0C, 0xEB, 0x8C, 0x06, 0x06, 0xF5, 0x9C, 0x56, 0x08, 0x36, 0x00, 0x29, 0xB4, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x31, 0xD0, ++0x9A, 0xF8, 0x02, 0x50, 0x01, 0x2D, 0x3A, 0xD0, 0x03, 0x2D, 0x50, 0xD0, 0x0D, 0x46, 0x33, 0x46, 0x27, 0x70, 0x65, 0x70, ++0x66, 0x80, 0xA3, 0x80, 0xE1, 0x80, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x98, 0xF8, 0x02, 0x30, 0x98, 0xF8, 0x05, 0x00, ++0x89, 0xF8, 0x00, 0x30, 0x98, 0xF8, 0x04, 0xC0, 0x81, 0xE7, 0x4F, 0xF6, 0xFF, 0x76, 0x93, 0xE7, 0x01, 0x3A, 0xA4, 0x2A, ++0x19, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x53, 0x08, 0x33, 0x00, 0x29, 0xB7, 0xD0, 0x0E, 0xF1, 0xFF, 0x3E, ++0xBE, 0xF1, 0xA4, 0x0F, 0x0A, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, 0x9C, 0x51, 0x08, 0x31, 0x89, 0xB2, 0xAB, 0xE7, ++0x51, 0x46, 0x55, 0x46, 0x33, 0x46, 0xD1, 0xE7, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xE7, 0x4F, 0xF6, 0xFF, 0x73, 0xE7, 0xE7, ++0x4F, 0xF6, 0xFF, 0x73, 0x90, 0xE7, 0x06, 0xF1, 0x0A, 0x03, 0x9B, 0xB2, 0xC4, 0xE7, 0x40, 0xF6, 0xB4, 0x16, 0x69, 0xE7, ++0x9E, 0x42, 0x94, 0xBF, 0x28, 0x3B, 0x28, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0xBA, 0xE7, 0x02, 0x2D, 0x0F, 0xD0, 0x03, 0xF1, ++0x28, 0x05, 0xB5, 0x42, 0x15, 0xDA, 0x3C, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0xB0, 0xE7, 0xA6, 0xF1, 0x0A, 0x03, 0x9B, 0xB2, ++0x01, 0x25, 0xAB, 0xE7, 0x40, 0xF6, 0xB4, 0x13, 0x70, 0xE7, 0x9E, 0x42, 0x03, 0xD8, 0x14, 0x3B, 0x9B, 0xB2, 0x15, 0x46, ++0xA2, 0xE7, 0x14, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0x9E, 0xE7, 0x9E, 0x42, 0xF9, 0xD8, 0xA3, 0xF1, 0x27, 0x05, 0xAE, 0x42, ++0xF1, 0xDA, 0x3C, 0x3B, 0x9B, 0xB2, 0x15, 0x46, 0x94, 0xE7, 0x40, 0xF6, 0xB4, 0x11, 0x67, 0xE7, 0xE4, 0xB8, 0x17, 0x00, ++0x70, 0xB5, 0x1D, 0x46, 0x14, 0x46, 0xFD, 0xF7, 0x95, 0xFB, 0x00, 0x23, 0x2B, 0x70, 0x00, 0x28, 0x48, 0xD0, 0x02, 0x7A, ++0xA1, 0x7C, 0x02, 0xF0, 0x0F, 0x03, 0x99, 0x42, 0x40, 0xD0, 0x01, 0x21, 0x29, 0x70, 0xA3, 0x74, 0x22, 0x74, 0xD0, 0xF8, ++0x0A, 0x20, 0x13, 0x0A, 0xD1, 0x08, 0x02, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x03, 0x12, 0x04, 0xBF, 0x40, 0xF6, 0x43, 0x23, ++0x63, 0x60, 0xD0, 0xF8, 0x0E, 0x30, 0x18, 0xBF, 0x62, 0x60, 0x1D, 0x0A, 0x03, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x05, 0x12, ++0x08, 0xBF, 0x40, 0xF6, 0x47, 0x22, 0x22, 0x60, 0xD0, 0xF8, 0x12, 0x20, 0x95, 0x08, 0x16, 0x0A, 0x02, 0xF0, 0x0F, 0x02, ++0x52, 0xEA, 0x06, 0x12, 0x08, 0xBF, 0x12, 0x4A, 0xA2, 0x60, 0xD0, 0xF8, 0x16, 0x20, 0xC3, 0xF3, 0x00, 0x13, 0x50, 0x08, ++0x05, 0xF0, 0x04, 0x05, 0x01, 0xF0, 0x02, 0x01, 0x2B, 0x43, 0x00, 0xF0, 0x08, 0x00, 0x49, 0xB2, 0x03, 0x43, 0x0B, 0x43, ++0x11, 0x0A, 0x02, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x01, 0x12, 0x63, 0x74, 0x0A, 0xBF, 0x07, 0x4B, 0xE2, 0x60, 0xE3, 0x60, ++0x01, 0x20, 0x70, 0xBD, 0x40, 0xF6, 0x43, 0x23, 0xC4, 0xE9, 0x00, 0x33, 0xC4, 0xE9, 0x02, 0x33, 0x70, 0xBD, 0x00, 0xBF, ++0x32, 0xE4, 0x05, 0x00, 0x22, 0xF3, 0x02, 0x00, 0x38, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0x4A, 0xFB, 0xE8, 0xB1, 0xC2, 0x78, ++0x83, 0x78, 0x43, 0xEA, 0x02, 0x23, 0x23, 0x80, 0x23, 0x46, 0x02, 0x79, 0x03, 0xF8, 0x02, 0x2F, 0x04, 0xF1, 0x12, 0x05, ++0xC4, 0xF1, 0x03, 0x02, 0xC1, 0x18, 0x89, 0x5C, 0x03, 0xF8, 0x01, 0x1F, 0xAB, 0x42, 0xF9, 0xD1, 0x43, 0x7D, 0x82, 0x7D, ++0xB0, 0xF8, 0x17, 0x10, 0xA1, 0x61, 0x43, 0xEA, 0x02, 0x23, 0xA3, 0x82, 0xC3, 0x7E, 0x23, 0x77, 0x01, 0x20, 0x38, 0xBD, ++0xF8, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0xCA, 0xFB, 0xB8, 0xB1, 0xC7, 0x79, 0x43, 0x7A, 0x85, 0x79, 0x02, 0x7A, 0x81, 0x7A, ++0xC6, 0x7A, 0x45, 0xEA, 0x07, 0x25, 0x42, 0xEA, 0x03, 0x22, 0xD0, 0xF8, 0x02, 0x70, 0x03, 0x7B, 0x40, 0x7B, 0x27, 0x60, ++0x43, 0xEA, 0x00, 0x23, 0x41, 0xEA, 0x06, 0x21, 0xA5, 0x80, 0x21, 0x81, 0xE2, 0x80, 0x63, 0x81, 0x01, 0x20, 0xF8, 0xBD, ++0xF0, 0xB5, 0x83, 0xB0, 0x15, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0xFD, 0xF7, 0xC9, 0xFB, 0x00, 0x28, 0x45, 0xD0, 0x9D, 0xF8, ++0x07, 0x30, 0xC6, 0x1C, 0xC5, 0xF1, 0x04, 0x04, 0x1E, 0x44, 0x04, 0x44, 0x6B, 0x1E, 0x69, 0x1D, 0x1A, 0x5D, 0x03, 0xF8, ++0x01, 0x2F, 0x8B, 0x42, 0xFA, 0xD1, 0x05, 0xF1, 0x10, 0x02, 0x19, 0x5D, 0x03, 0xF8, 0x01, 0x1F, 0x93, 0x42, 0xFA, 0xD1, ++0x02, 0x7D, 0x47, 0x7D, 0x83, 0x7D, 0xC4, 0x7D, 0xA9, 0x79, 0x42, 0xEA, 0x07, 0x22, 0x43, 0xEA, 0x04, 0x23, 0x6A, 0x82, ++0x4A, 0x10, 0x09, 0x07, 0xAB, 0x82, 0x00, 0xF1, 0x18, 0x03, 0x0E, 0xD5, 0x00, 0xF1, 0x1C, 0x01, 0xB1, 0x42, 0x1C, 0xD8, ++0x5F, 0x78, 0x04, 0x7E, 0x83, 0x7E, 0xC0, 0x7E, 0x44, 0xEA, 0x07, 0x24, 0x43, 0xEA, 0x00, 0x20, 0xEC, 0x82, 0x0B, 0x46, ++0x28, 0x83, 0x12, 0x07, 0x12, 0xD5, 0x1A, 0x1D, 0xB2, 0x42, 0x0C, 0xD8, 0x58, 0x78, 0x19, 0x78, 0x9A, 0x78, 0xDB, 0x78, ++0x41, 0xEA, 0x00, 0x21, 0x42, 0xEA, 0x03, 0x23, 0x01, 0x20, 0x69, 0x83, 0xAB, 0x83, 0x03, 0xB0, 0xF0, 0xBD, 0x00, 0x20, ++0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, ++0x07, 0x02, 0xFD, 0xF7, 0xC7, 0xFB, 0x40, 0xB1, 0xD0, 0xF8, 0x03, 0x30, 0xC4, 0xF8, 0xDC, 0x30, 0x00, 0x38, 0x18, 0xBF, ++0x01, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x01, 0x4B, 0xF6, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x01, 0x80, 0xF8, 0xB5, 0x1D, 0x46, ++0x14, 0x46, 0xFD, 0xF7, 0xC7, 0xFB, 0x00, 0x23, 0x2B, 0x70, 0x00, 0xB3, 0xC2, 0x78, 0x61, 0x7C, 0x02, 0xF0, 0x0F, 0x03, ++0x99, 0x42, 0x1B, 0xD0, 0x01, 0x26, 0x2E, 0x70, 0x22, 0x74, 0x63, 0x74, 0xB0, 0xF8, 0x05, 0x10, 0x03, 0x79, 0x02, 0x89, ++0xB0, 0xF8, 0x0B, 0x70, 0xC5, 0x89, 0x43, 0xEA, 0x01, 0x23, 0x63, 0x60, 0xC1, 0x79, 0x41, 0xEA, 0x02, 0x21, 0x21, 0x60, ++0x82, 0x7A, 0x42, 0xEA, 0x07, 0x22, 0xA2, 0x60, 0x43, 0x7B, 0x43, 0xEA, 0x05, 0x23, 0x30, 0x46, 0xE3, 0x60, 0xF8, 0xBD, ++0x01, 0x20, 0xF8, 0xBD, 0x10, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0xAC, 0xFB, 0x40, 0xB1, 0xC3, 0x78, 0x03, 0xF0, 0x07, 0x02, ++0xC3, 0xF3, 0xC2, 0x03, 0x22, 0x70, 0x63, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x03, 0x22, 0x05, 0x23, 0x22, 0x70, 0x63, 0x70, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0xB5, 0x07, 0x48, 0x1C, 0x46, 0x15, 0x46, 0xFE, 0x22, 0x10, 0xF0, 0x67, 0xFD, 0x2A, 0x46, ++0x21, 0x46, 0x41, 0xF2, 0x03, 0x40, 0xFC, 0xF7, 0x41, 0xFA, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x5A, 0xB9, 0x17, 0x00, ++0x70, 0xB5, 0x32, 0x4C, 0x08, 0x78, 0x24, 0x68, 0x01, 0x28, 0x19, 0x46, 0x20, 0x70, 0x29, 0xD0, 0x02, 0x28, 0x05, 0xD0, ++0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0x2E, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x2B, 0x4C, 0x2C, 0x48, 0x23, 0x68, 0x2C, 0x4E, ++0x2C, 0x4D, 0x43, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x03, 0x68, 0x2B, 0x4C, 0x23, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x3F, 0x23, ++0x33, 0x60, 0x2B, 0x68, 0x28, 0x48, 0x23, 0xF0, 0x01, 0x03, 0x2B, 0x60, 0x23, 0x6D, 0x23, 0xF4, 0x80, 0x23, 0x23, 0x65, ++0x03, 0x69, 0x43, 0xF0, 0x80, 0x03, 0x03, 0x61, 0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0x0C, 0xFA, 0x00, 0x20, 0x70, 0xBD, ++0x20, 0x4B, 0x1B, 0x4C, 0x93, 0xF8, 0xB5, 0x30, 0x0B, 0xBB, 0x23, 0x68, 0x19, 0x4E, 0x1E, 0x4D, 0x43, 0xF0, 0x00, 0x73, ++0x23, 0x60, 0x04, 0xF5, 0x00, 0x44, 0x04, 0x23, 0x28, 0x34, 0x33, 0x60, 0x28, 0x60, 0x23, 0x68, 0x23, 0xF4, 0x80, 0x23, ++0x23, 0xF0, 0x01, 0x03, 0x23, 0x60, 0x13, 0x4C, 0x13, 0x48, 0x23, 0x6D, 0x43, 0xF4, 0x80, 0x23, 0x23, 0x65, 0x03, 0x69, ++0x23, 0xF0, 0x80, 0x03, 0x03, 0x61, 0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0xE5, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0x23, 0x68, ++0x09, 0x48, 0x08, 0x4D, 0x23, 0xF0, 0x00, 0x73, 0x23, 0x60, 0x03, 0x68, 0x24, 0x24, 0x43, 0xF4, 0x00, 0x13, 0x03, 0x60, ++0x2C, 0x60, 0xE2, 0xE7, 0x74, 0x36, 0x17, 0x00, 0x44, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x00, 0x60, 0x50, 0x40, 0x00, 0x00, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x70, 0x80, 0x32, 0x40, ++0xF8, 0xB5, 0x4C, 0x78, 0x08, 0x78, 0x16, 0x46, 0x1D, 0x46, 0x2C, 0xB3, 0x17, 0x4C, 0x18, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x00, 0x44, 0x4F, 0xF4, 0xA4, 0x61, 0x94, 0xF8, 0x22, 0x20, 0x01, 0xFB, 0x02, 0x32, 0x02, 0x23, 0x92, 0xF8, ++0x62, 0x70, 0x84, 0xF8, 0x30, 0x30, 0x5F, 0xB9, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xFC, 0xF7, 0x3E, 0xF9, ++0x07, 0x70, 0x94, 0xF8, 0x22, 0x20, 0x42, 0x70, 0xFC, 0xF7, 0x68, 0xF9, 0x32, 0x46, 0x29, 0x46, 0x41, 0xF2, 0x05, 0x40, ++0xFC, 0xF7, 0x9A, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x04, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x00, 0x30, 0x01, 0x23, ++0x80, 0xF8, 0x30, 0x30, 0xEE, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0x0C, 0x20, 0x0C, 0x46, 0x17, 0x46, 0x00, 0x21, 0x05, 0x22, 0x1E, 0x46, 0x01, 0x23, 0xFC, 0xF7, 0x17, 0xF9, 0xDF, 0xF8, ++0x6C, 0x90, 0xDF, 0xF8, 0x6C, 0x80, 0xD9, 0xF8, 0x24, 0x30, 0x05, 0x46, 0x20, 0x78, 0x98, 0x47, 0x23, 0x78, 0x2B, 0x70, ++0x28, 0x46, 0xFC, 0xF7, 0x39, 0xF9, 0x20, 0x78, 0xD9, 0xF8, 0xD8, 0x31, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0xF0, ++0x00, 0xF5, 0x18, 0x70, 0x40, 0x44, 0x98, 0x47, 0x63, 0x78, 0x43, 0xB9, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x0A, 0x40, ++0xFC, 0xF7, 0x5E, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x23, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, ++0xFC, 0xF7, 0xEC, 0xF8, 0x00, 0x22, 0x02, 0x70, 0x22, 0x78, 0x05, 0xFB, 0x02, 0x88, 0x98, 0xF8, 0x22, 0x20, 0x42, 0x70, ++0xFC, 0xF7, 0x12, 0xF9, 0xE4, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x0C, 0x46, 0x89, 0x78, 0x25, 0x78, 0xDF, 0xF8, 0xAC, 0x80, 0x1E, 0x46, 0x17, 0x46, 0x63, 0x78, 0xA1, 0xB1, 0x00, 0x2B, ++0x44, 0xD1, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x02, 0xF0, 0xFB, 0x02, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x2E, 0x11, 0x83, 0xF8, 0x31, 0x20, 0x0F, 0x29, 0x1E, 0xD1, 0x0A, 0xE0, ++0x2B, 0xBB, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, ++0x31, 0x20, 0x04, 0x23, 0x05, 0x22, 0x00, 0x21, 0x41, 0x20, 0xFC, 0xF7, 0xAB, 0xF8, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x05, 0x85, 0x95, 0xF8, 0x22, 0x30, 0x2A, 0x8C, 0x02, 0x80, 0xC3, 0x70, 0x63, 0x78, 0x83, 0x70, 0xFC, 0xF7, 0xCE, 0xF8, ++0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x0D, 0x40, 0xFC, 0xF7, 0x00, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x42, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x31, 0x20, 0xD8, 0xE7, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x42, 0xF0, 0x04, 0x02, 0xB9, 0xE7, 0x00, 0xBF, ++0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x31, 0x20, 0x0D, 0x46, 0x4B, 0x4C, 0x91, 0x46, 0x98, 0x46, 0x05, 0x22, ++0x01, 0x23, 0x00, 0x21, 0xFC, 0xF7, 0x72, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x76, 0x31, 0x95, 0xF8, 0x67, 0x30, 0x82, 0x46, ++0x5B, 0xB1, 0x01, 0x23, 0x84, 0xF8, 0x76, 0x31, 0x2F, 0x46, 0x0F, 0xCF, 0x04, 0xF1, 0x0C, 0x06, 0x0F, 0xC6, 0x97, 0xE8, ++0x0F, 0x00, 0x86, 0xE8, 0x0F, 0x00, 0x95, 0xF8, 0x68, 0x30, 0x5B, 0xB1, 0x94, 0xF8, 0x76, 0x21, 0x3C, 0x4B, 0x42, 0xF0, ++0x02, 0x02, 0x84, 0xF8, 0x76, 0x21, 0x05, 0xF1, 0x20, 0x02, 0x07, 0xCA, 0x83, 0xE8, 0x07, 0x00, 0x95, 0xF8, 0x69, 0x30, ++0x93, 0xB1, 0x94, 0xF8, 0x76, 0x31, 0x36, 0x4E, 0x43, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x76, 0x31, 0x05, 0xF1, 0x2C, 0x07, ++0x0F, 0xCF, 0x0F, 0xC6, 0x0F, 0xCF, 0x0F, 0xC6, 0x0F, 0xCF, 0x0F, 0xC6, 0x97, 0xE8, 0x03, 0x00, 0x86, 0xE8, 0x03, 0x00, ++0x95, 0xF8, 0x6A, 0x30, 0x2B, 0xB1, 0x94, 0xF8, 0x76, 0x31, 0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x76, 0x31, 0x95, 0xF8, ++0x66, 0x30, 0x84, 0xF8, 0x75, 0x31, 0x4A, 0x46, 0x41, 0x46, 0x41, 0xF2, 0x01, 0x40, 0xFC, 0xF7, 0x8F, 0xF8, 0x94, 0xF8, ++0x76, 0x31, 0x13, 0xF0, 0x01, 0x03, 0x14, 0xD1, 0x84, 0xF8, 0x74, 0x31, 0x95, 0xF8, 0x6B, 0x30, 0xB5, 0xF8, 0x64, 0x10, ++0x84, 0xF8, 0x77, 0x31, 0x95, 0xF8, 0x6D, 0x20, 0xA1, 0x85, 0x00, 0x2A, 0x14, 0xBF, 0x02, 0x22, 0x01, 0x22, 0x84, 0xF8, ++0x78, 0x21, 0xF3, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xDA, 0xF7, 0xE3, 0xFC, 0x94, 0xF8, 0x76, 0x31, 0x01, 0x30, ++0x40, 0x10, 0x5B, 0x07, 0x84, 0xF8, 0x74, 0x01, 0xE2, 0xD5, 0x94, 0xF8, 0x75, 0x21, 0x94, 0xF8, 0x44, 0x30, 0x02, 0x2A, ++0x88, 0xBF, 0x94, 0xF8, 0x49, 0x20, 0x4F, 0xEA, 0x93, 0x03, 0x88, 0xBF, 0x03, 0xEA, 0x92, 0x13, 0x03, 0xF0, 0x01, 0x03, ++0x84, 0xF8, 0x74, 0x30, 0xD0, 0xE7, 0xFF, 0x23, 0x23, 0x81, 0x50, 0x46, 0x8A, 0xF8, 0x00, 0x20, 0xFC, 0xF7, 0x1A, 0xF8, ++0x01, 0x21, 0x05, 0x20, 0xFC, 0xF7, 0xE0, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, ++0x14, 0xB9, 0x17, 0x00, 0x20, 0xB9, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x41, 0xF2, 0x08, 0x40, 0x97, 0xB0, 0x0C, 0x46, ++0x19, 0x46, 0x03, 0x23, 0xFB, 0xF7, 0xD2, 0xFF, 0x4F, 0xF0, 0x00, 0x0A, 0xCD, 0xE9, 0x0C, 0xAA, 0x05, 0x46, 0xAD, 0xF8, ++0x2E, 0xA0, 0x8D, 0xF8, 0x2C, 0xA0, 0x08, 0xF0, 0xEB, 0xFB, 0x94, 0xF8, 0x81, 0x70, 0xA2, 0x6F, 0x06, 0x90, 0x4F, 0xF4, ++0xA4, 0x61, 0x01, 0xFB, 0x07, 0xF1, 0x12, 0xF0, 0x02, 0x06, 0x07, 0x91, 0x1B, 0xD0, 0x12, 0xF0, 0x04, 0x06, 0x04, 0xF1, ++0x14, 0x08, 0x40, 0xF0, 0xDC, 0x81, 0xB1, 0x46, 0x0B, 0xAB, 0x12, 0xF0, 0x20, 0x02, 0x0D, 0xF1, 0x34, 0x0C, 0x02, 0x93, ++0x0C, 0xAB, 0xCD, 0xE9, 0x00, 0x3C, 0x18, 0xBF, 0x04, 0xF1, 0x40, 0x02, 0x0D, 0xF1, 0x2E, 0x03, 0x49, 0x46, 0x40, 0x46, ++0x00, 0xF0, 0x00, 0xFE, 0x94, 0xF8, 0x81, 0x30, 0x00, 0xE0, 0x3B, 0x46, 0x00, 0x22, 0xDF, 0xF8, 0xC4, 0x93, 0x20, 0x68, ++0x0C, 0x99, 0xB4, 0xF8, 0x04, 0xE0, 0xBD, 0xF8, 0x2E, 0xC0, 0x0E, 0x92, 0x8D, 0xF8, 0x55, 0x20, 0x8D, 0xF8, 0x56, 0x20, ++0x9D, 0xF8, 0x2C, 0x20, 0x8D, 0xF8, 0x51, 0x30, 0xCD, 0xF8, 0x4A, 0x00, 0x10, 0x91, 0x8D, 0xF8, 0x50, 0x20, 0xD9, 0xF8, ++0xC4, 0x31, 0x11, 0x96, 0xAD, 0xF8, 0x4E, 0xE0, 0xAD, 0xF8, 0x48, 0xC0, 0x0D, 0xF1, 0x2D, 0x02, 0x29, 0x46, 0x0E, 0xA8, ++0x98, 0x47, 0x83, 0x46, 0x68, 0x70, 0x00, 0x28, 0x40, 0xF0, 0x1C, 0x81, 0x23, 0x46, 0x2E, 0x78, 0x53, 0xF8, 0x06, 0x0F, ++0xDF, 0xF8, 0x70, 0x83, 0x59, 0x68, 0x9A, 0x68, 0x93, 0xF8, 0x0C, 0xE0, 0xD4, 0xF8, 0x78, 0xC0, 0x04, 0x96, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x06, 0xF3, 0x08, 0xEB, 0x03, 0x0A, 0x08, 0x93, 0x0A, 0xF1, 0xB8, 0x03, 0x07, 0xC3, 0x1C, 0xF0, ++0x01, 0x0F, 0x83, 0xF8, 0x00, 0xE0, 0x40, 0xF0, 0x06, 0x81, 0xC7, 0x4B, 0x05, 0x93, 0x1C, 0xF0, 0x08, 0x0F, 0x08, 0xD0, ++0x04, 0x9A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0x5A, 0x68, 0x42, 0xF0, 0x08, 0x02, 0x5A, 0x60, 0x04, 0x9A, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0x94, 0xF8, 0x7E, 0x20, 0x83, 0xF8, 0x2E, 0x21, 0x94, 0xF8, 0x7F, 0x10, ++0xB4, 0xF8, 0x7C, 0x20, 0x1A, 0x84, 0x83, 0xF8, 0x2F, 0x11, 0x50, 0x46, 0x09, 0x93, 0x00, 0xF0, 0xBB, 0xFE, 0xA2, 0x6F, ++0xD2, 0x06, 0x06, 0xD5, 0x94, 0xF9, 0x80, 0x20, 0x94, 0xF8, 0x80, 0x10, 0x00, 0x2A, 0x80, 0xF2, 0x77, 0x81, 0xBB, 0xF1, ++0x00, 0x0F, 0x40, 0xF0, 0x7F, 0x81, 0x05, 0x9B, 0xAF, 0x48, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x34, 0x04, 0x9B, ++0xB4, 0xF8, 0xE0, 0x20, 0x4F, 0xF4, 0x1E, 0x7B, 0x0B, 0xFB, 0x03, 0x86, 0xD4, 0xF8, 0xB0, 0x34, 0x96, 0xF8, 0x56, 0x11, ++0xC6, 0xF8, 0x68, 0xA2, 0x03, 0xF0, 0x01, 0x03, 0xC3, 0xF1, 0x02, 0x03, 0x86, 0xF8, 0x30, 0x30, 0x41, 0xF0, 0x10, 0x01, ++0xA3, 0x4B, 0x86, 0xF8, 0x56, 0x11, 0x52, 0xBA, 0x4F, 0xF0, 0x01, 0x0A, 0xC6, 0xF8, 0x64, 0x02, 0xB2, 0x86, 0x08, 0x98, ++0x86, 0xF8, 0x70, 0xA2, 0x1A, 0x69, 0x9E, 0x49, 0xD9, 0xF8, 0xE0, 0x31, 0x00, 0xF5, 0x18, 0x70, 0x40, 0x44, 0x11, 0x44, ++0x98, 0x47, 0x06, 0x9B, 0xAB, 0x70, 0x00, 0x2B, 0x00, 0xF0, 0x9A, 0x80, 0x94, 0xF8, 0xDE, 0x20, 0x86, 0xF8, 0x24, 0x30, ++0x00, 0x2A, 0x40, 0xF0, 0x85, 0x80, 0x94, 0xF8, 0x63, 0x60, 0x0A, 0x36, 0xF6, 0xB2, 0x0B, 0xFB, 0x06, 0xF3, 0x08, 0xEB, ++0x03, 0x0B, 0x04, 0x93, 0x9B, 0xF8, 0x24, 0x30, 0x53, 0x45, 0x77, 0xD0, 0x02, 0x23, 0x0C, 0x21, 0x49, 0x20, 0xFB, 0xF7, ++0xDB, 0xFE, 0x8B, 0xF8, 0x24, 0xA0, 0x06, 0x70, 0x80, 0xF8, 0x01, 0xA0, 0xFB, 0xF7, 0x04, 0xFF, 0x9B, 0xF8, 0x24, 0x30, ++0x00, 0x2B, 0x40, 0xF0, 0x48, 0x81, 0x9B, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x00, 0xF2, 0x43, 0x81, 0x9B, 0xF8, 0x22, 0x00, ++0x05, 0x9C, 0xCD, 0xF8, 0x18, 0xA0, 0x9E, 0x23, 0xA4, 0x21, 0x4F, 0xF4, 0xA4, 0x6C, 0x11, 0xFB, 0x00, 0x31, 0x0C, 0xFB, ++0x00, 0x4A, 0x4F, 0x23, 0x46, 0x20, 0x13, 0xFB, 0x06, 0x03, 0x7B, 0x4A, 0x05, 0x98, 0x7B, 0x4C, 0x08, 0x95, 0x08, 0xEB, ++0xC3, 0x08, 0x04, 0x9B, 0x00, 0xEB, 0xC1, 0x06, 0x13, 0x44, 0x35, 0x46, 0x1E, 0x46, 0xDB, 0xF8, 0x08, 0x22, 0x1A, 0xB3, ++0xEF, 0xF3, 0x10, 0x82, 0xD3, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x73, 0x4B, 0x06, 0x9A, 0x1A, 0x60, 0x22, 0x68, 0xA8, 0xF1, ++0x28, 0x00, 0x01, 0x32, 0xA5, 0xF1, 0x28, 0x01, 0x04, 0x90, 0x22, 0x60, 0xFC, 0xF7, 0x18, 0xFC, 0xDB, 0xE9, 0x82, 0x21, ++0x04, 0x98, 0xCA, 0xF8, 0xC8, 0x24, 0xCA, 0xF8, 0xCC, 0x14, 0xFC, 0xF7, 0x19, 0xFB, 0x22, 0x68, 0x51, 0x1E, 0x2A, 0xB1, ++0x66, 0x4B, 0x21, 0x60, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xDB, 0xF8, 0x30, 0x22, 0x28, 0x46, 0x41, 0x46, ++0x0B, 0xF1, 0x08, 0x0B, 0x08, 0x35, 0x0A, 0xF1, 0x08, 0x0A, 0x22, 0xB1, 0xFC, 0xF7, 0xFA, 0xFB, 0x40, 0x46, 0xFC, 0xF7, ++0x01, 0xFB, 0x08, 0xF1, 0x08, 0x08, 0x46, 0x45, 0xC5, 0xD1, 0x40, 0x20, 0x08, 0x9D, 0xFC, 0xF7, 0x5B, 0xFA, 0x05, 0x9A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x23, 0x93, 0xF8, 0xDE, 0x20, 0x05, 0x9C, 0xD9, 0xF8, 0x0C, 0x32, 0x4F, 0xF4, ++0xA4, 0x61, 0x01, 0xFB, 0x07, 0x47, 0x07, 0x99, 0x01, 0x32, 0x21, 0x44, 0x08, 0x46, 0x87, 0xF8, 0xDE, 0x20, 0x98, 0x47, ++0x28, 0x46, 0xFB, 0xF7, 0x87, 0xFE, 0x00, 0x20, 0x17, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x04, 0x30, 0x05, 0x93, ++0x1C, 0xF0, 0x02, 0x0F, 0x43, 0xF0, 0x01, 0x03, 0xCA, 0xF8, 0x04, 0x30, 0x3F, 0xF4, 0xEF, 0xAE, 0x45, 0x4B, 0x93, 0xF8, ++0x76, 0x31, 0x09, 0x93, 0x13, 0xF0, 0x01, 0x0B, 0x3F, 0xF4, 0xE7, 0xAE, 0x04, 0xF1, 0x14, 0x0E, 0xBE, 0xE8, 0x0F, 0x00, ++0x0A, 0xF1, 0xC8, 0x0B, 0xAB, 0xE8, 0x0F, 0x00, 0x9E, 0xE8, 0x0F, 0x00, 0x05, 0x9E, 0x1C, 0xF0, 0x20, 0x0F, 0x46, 0xF0, ++0x03, 0x0E, 0x8B, 0xE8, 0x0F, 0x00, 0xCA, 0xF8, 0x04, 0xE0, 0x22, 0xD0, 0x09, 0x9B, 0x58, 0x07, 0x1F, 0xD5, 0x04, 0xF1, ++0x40, 0x0E, 0xBE, 0xE8, 0x0F, 0x00, 0x0A, 0xF1, 0xF4, 0x0B, 0xAB, 0xE8, 0x0F, 0x00, 0xBE, 0xE8, 0x0F, 0x00, 0xAB, 0xE8, ++0x0F, 0x00, 0xBE, 0xE8, 0x0F, 0x00, 0xAB, 0xE8, 0x0F, 0x00, 0x9E, 0xE8, 0x03, 0x00, 0x46, 0xF0, 0x23, 0x03, 0xCA, 0xF8, ++0x04, 0x30, 0x09, 0x9B, 0x8B, 0xE8, 0x03, 0x00, 0x19, 0x07, 0x04, 0xD5, 0x50, 0x46, 0xEC, 0xF7, 0x85, 0xFF, 0xD4, 0xF8, ++0x78, 0xC0, 0x1C, 0xF0, 0x04, 0x0F, 0x1F, 0xD0, 0x24, 0x4B, 0x04, 0x9A, 0x93, 0xF8, 0x76, 0x31, 0x13, 0xF0, 0x02, 0x0F, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0xD3, 0xF8, 0x04, 0xC0, 0x02, 0xD1, 0x1C, 0xF0, 0x20, 0x0F, 0x0F, 0xD0, ++0x04, 0xF1, 0x34, 0x03, 0x93, 0xE8, 0x07, 0x00, 0x04, 0x9E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0x83, 0x03, 0xF1, ++0xE8, 0x0E, 0x8E, 0xE8, 0x07, 0x00, 0x4C, 0xF0, 0x04, 0x02, 0x5A, 0x60, 0x07, 0x9A, 0x0D, 0x4B, 0x05, 0x93, 0x02, 0xF1, ++0xEC, 0x01, 0x19, 0x44, 0x50, 0x46, 0x00, 0xF0, 0x53, 0xFB, 0xD4, 0xF8, 0x78, 0xC0, 0x83, 0x46, 0x81, 0xE6, 0x07, 0x4B, ++0x05, 0x93, 0x0B, 0x44, 0x04, 0xF1, 0x34, 0x09, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x43, 0xD0, 0x03, 0x2B, 0x2F, 0xD0, ++0xA3, 0xB3, 0x56, 0x46, 0x16, 0xE6, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x1D, 0x66, 0x12, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x40, 0x4B, 0x4C, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x09, 0x9B, 0x0A, 0x09, 0x93, 0xF8, 0x23, 0x00, 0x01, 0xF0, 0x03, 0x01, ++0x01, 0xF0, 0x34, 0xF8, 0xBB, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x81, 0xAE, 0x04, 0x9A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x02, 0x83, 0xFF, 0x21, 0x93, 0xF8, 0x23, 0x00, 0x00, 0x22, 0x01, 0xF0, 0x25, 0xF8, 0x74, 0xE6, 0x20, 0x46, 0xFC, 0xF7, ++0x61, 0xFF, 0xA2, 0x6F, 0x06, 0x46, 0xE3, 0xE5, 0x09, 0x4B, 0x01, 0xF5, 0xB2, 0x70, 0x03, 0x44, 0xB4, 0xF8, 0x7C, 0x10, ++0x18, 0x46, 0xFC, 0xF7, 0x5D, 0xFF, 0xA2, 0x6F, 0x06, 0x46, 0xD7, 0xE5, 0x07, 0x9B, 0x03, 0xF1, 0x5C, 0x00, 0x05, 0x9B, ++0xF1, 0xE7, 0x94, 0xF8, 0xDE, 0x20, 0x1B, 0xE7, 0x18, 0x88, 0x17, 0x00, 0xF0, 0xB5, 0x0C, 0x46, 0x21, 0x4D, 0x09, 0x78, ++0x6F, 0x68, 0x1E, 0x46, 0x63, 0x78, 0x01, 0x20, 0x83, 0xB0, 0x98, 0x40, 0xC1, 0xB1, 0x38, 0x43, 0x95, 0xF8, 0x77, 0x31, ++0x68, 0x60, 0x5B, 0xB1, 0x05, 0x20, 0x01, 0x92, 0xFC, 0xF7, 0x10, 0xF8, 0x01, 0x28, 0x2C, 0xD0, 0x17, 0xF0, 0xFF, 0x0F, ++0x23, 0x78, 0x01, 0x9A, 0x0B, 0xD0, 0x63, 0xB1, 0x41, 0xF2, 0x1A, 0x40, 0x31, 0x46, 0xFB, 0xF7, 0xC9, 0xFD, 0x00, 0x20, ++0x03, 0xB0, 0xF0, 0xBD, 0x27, 0xEA, 0x00, 0x00, 0xE4, 0xE7, 0x00, 0x2B, 0xF2, 0xD0, 0x01, 0x23, 0x00, 0x21, 0x31, 0x20, ++0x01, 0x92, 0xFB, 0xF7, 0x53, 0xFD, 0x6B, 0x68, 0x01, 0x9A, 0x2E, 0x81, 0x63, 0xB1, 0x00, 0x23, 0x03, 0x70, 0x01, 0x92, ++0xFB, 0xF7, 0x7A, 0xFD, 0x01, 0x9A, 0x01, 0x21, 0x10, 0x46, 0xFB, 0xF7, 0x3F, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, ++0x95, 0xF8, 0x78, 0x31, 0xF0, 0xE7, 0x02, 0x20, 0xDC, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0x11, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x14, 0x46, 0x0E, 0xDB, 0x0E, 0x4B, 0x19, 0x89, 0xFF, 0x29, 0x04, 0xD0, ++0x22, 0x46, 0x41, 0xF2, 0x18, 0x40, 0xFB, 0xF7, 0x91, 0xFD, 0x20, 0x46, 0x00, 0x21, 0xFB, 0xF7, 0x1F, 0xFF, 0x00, 0x20, ++0x10, 0xBD, 0x10, 0x46, 0xFB, 0xF7, 0xC2, 0xFF, 0x01, 0x28, 0xEB, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x7F, 0x22, ++0xFD, 0xF7, 0xFA, 0xFD, 0xE4, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x3C, 0xB8, 0x15, 0x00, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x14, 0x46, 0x0E, 0xDB, ++0x0E, 0x4B, 0x19, 0x89, 0xFF, 0x29, 0x04, 0xD0, 0x22, 0x46, 0x41, 0xF2, 0x1A, 0x40, 0xFB, 0xF7, 0x65, 0xFD, 0x20, 0x46, ++0x00, 0x21, 0xFB, 0xF7, 0xF3, 0xFE, 0x00, 0x20, 0x10, 0xBD, 0x10, 0x46, 0xFB, 0xF7, 0x96, 0xFF, 0x01, 0x28, 0xEB, 0xD0, ++0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x15, 0x32, 0xFD, 0xF7, 0xCE, 0xFD, 0xE4, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0xB8, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x46, 0x41, 0xF2, 0x0F, 0x40, ++0x19, 0x46, 0xC8, 0x23, 0xFB, 0xF7, 0xDA, 0xFC, 0x22, 0x78, 0x37, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, ++0x06, 0x46, 0xD3, 0xF8, 0x4C, 0x51, 0x02, 0x70, 0x00, 0x2D, 0x5C, 0xD0, 0xB5, 0xF8, 0xB4, 0x00, 0xB5, 0xF8, 0x90, 0x10, ++0xB5, 0xF8, 0x92, 0x20, 0xD5, 0xF8, 0x94, 0x30, 0xB3, 0x60, 0x70, 0x80, 0xB1, 0x80, 0xF2, 0x80, 0x95, 0xF8, 0xA4, 0x30, ++0x33, 0x73, 0xB5, 0xF8, 0x98, 0x30, 0x73, 0x73, 0x08, 0x22, 0x05, 0xF1, 0x88, 0x01, 0x06, 0xF1, 0x0E, 0x00, 0x10, 0xF0, ++0x3D, 0xF8, 0x78, 0x22, 0x29, 0x1D, 0x06, 0xF1, 0x16, 0x00, 0x10, 0xF0, 0x37, 0xF8, 0xB5, 0xF8, 0xB4, 0x30, 0x83, 0xB1, ++0x00, 0x24, 0x00, 0x22, 0xE1, 0xB2, 0x28, 0x46, 0x0C, 0xF0, 0x2C, 0xFE, 0xA3, 0xB2, 0x06, 0xEB, 0x83, 0x03, 0xB5, 0xF8, ++0xB4, 0x20, 0xC3, 0xF8, 0x9C, 0x00, 0x01, 0x34, 0xA3, 0xB2, 0x9A, 0x42, 0xEF, 0xD8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x05, 0xF1, 0x7C, 0x03, 0x07, 0xCB, 0x14, 0x4C, 0xC6, 0xF8, ++0x8E, 0x00, 0x23, 0x68, 0xC6, 0xF8, 0x92, 0x10, 0x01, 0x33, 0xC6, 0xF8, 0x96, 0x20, 0x28, 0x46, 0x00, 0x22, 0x0A, 0x21, ++0x23, 0x60, 0x0C, 0xF0, 0x07, 0xFE, 0x23, 0x68, 0xC6, 0xF8, 0xC4, 0x00, 0x33, 0xB1, 0x0A, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x30, 0x46, 0xFB, 0xF7, 0xA3, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x45, 0x80, ++0x30, 0x46, 0xFB, 0xF7, 0x9D, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x70, 0xB5, 0x23, 0x4A, 0x0B, 0x78, 0x12, 0x68, 0x0C, 0x46, 0x22, 0x49, 0xB2, 0xF9, 0x00, 0x20, ++0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x22, 0xDB, 0x66, 0x88, 0x4F, 0xF6, ++0xFF, 0x73, 0x9E, 0x42, 0x0B, 0xD1, 0x95, 0xF8, 0xA2, 0x30, 0xA5, 0xF8, 0xBA, 0x60, 0x03, 0xF0, 0xCF, 0x03, 0x85, 0xF8, ++0xA2, 0x30, 0x1B, 0x06, 0x1C, 0xD4, 0x00, 0x20, 0x70, 0xBD, 0x31, 0x46, 0x28, 0x46, 0x0C, 0xF0, 0x65, 0xFD, 0x00, 0x28, ++0xF7, 0xD0, 0x95, 0xF8, 0xA2, 0x30, 0xA5, 0xF8, 0xBA, 0x60, 0x23, 0xF0, 0x30, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x85, 0xF8, ++0xA2, 0x30, 0x00, 0x20, 0x70, 0xBD, 0x00, 0x2D, 0xDA, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0xAF, 0x32, 0xFD, 0xF7, ++0x0B, 0xFD, 0xD3, 0xE7, 0x20, 0x78, 0x0C, 0xF0, 0xC9, 0xFB, 0x95, 0xF8, 0xA2, 0x30, 0x03, 0xF0, 0x7F, 0x03, 0x85, 0xF8, ++0xA2, 0x30, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0xF8, 0xB5, 0x05, 0x20, 0x0E, 0x46, 0x15, 0x46, 0x1C, 0x46, 0xFB, 0xF7, 0xAF, 0xFE, 0x01, 0x28, ++0x4F, 0xD0, 0x2A, 0x46, 0x0C, 0x23, 0x21, 0x46, 0x41, 0xF2, 0x12, 0x40, 0xFB, 0xF7, 0x04, 0xFC, 0x37, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x2A, 0xDB, 0x35, 0x4B, 0x1C, 0x7C, 0xDA, 0xF7, 0x7F, 0xF8, 0x00, 0x28, ++0x30, 0xD1, 0xF3, 0x7A, 0x53, 0xB1, 0x32, 0x4B, 0x32, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0x2C, 0x12, 0x11, 0x66, 0xA3, 0xF5, ++0x40, 0x63, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x2E, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x77, 0x3C, 0x6C, ++0x4C, 0xB3, 0x23, 0x7E, 0x2B, 0x70, 0xB3, 0x7A, 0xE3, 0xB9, 0x23, 0x1D, 0x03, 0xCB, 0x1B, 0x88, 0x6B, 0x81, 0xC5, 0xF8, ++0x02, 0x00, 0xC5, 0xF8, 0x06, 0x10, 0x28, 0x46, 0xFB, 0xF7, 0x04, 0xFC, 0x00, 0x20, 0xF8, 0xBD, 0x1F, 0x4F, 0x3C, 0x7C, ++0xFF, 0x2C, 0xD2, 0xD1, 0x21, 0x49, 0x22, 0x48, 0x40, 0xF2, 0xEB, 0x32, 0xFD, 0xF7, 0xAA, 0xFC, 0x3C, 0x7C, 0xCA, 0xE7, ++0xF0, 0x7A, 0xDA, 0xF7, 0x53, 0xF8, 0xCA, 0xE7, 0x1D, 0x48, 0xFC, 0xF7, 0xD1, 0xF8, 0x01, 0x28, 0x0A, 0xD0, 0x3C, 0x6C, ++0xDB, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xFF, 0x23, 0x28, 0x46, 0x2B, 0x70, 0xFB, 0xF7, 0xE4, 0xFB, 0x20, 0x46, 0xF8, 0xBD, ++0x05, 0x22, 0x0C, 0x23, 0x00, 0x21, 0x3B, 0x20, 0xFB, 0xF7, 0xAC, 0xFB, 0x39, 0x6C, 0x03, 0x46, 0x09, 0x7E, 0x03, 0xF8, ++0x02, 0x1B, 0x31, 0x89, 0x37, 0x68, 0x74, 0x68, 0xC0, 0xF8, 0x02, 0x70, 0x19, 0x81, 0x5C, 0x60, 0xFB, 0xF7, 0xCE, 0xFB, ++0x31, 0x68, 0x72, 0x68, 0x33, 0x89, 0x6B, 0x81, 0xC5, 0xF8, 0x02, 0x10, 0xC5, 0xF8, 0x06, 0x20, 0xBD, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x60, 0xB8, 0x15, 0x00, 0x08, 0x88, 0x17, 0x00, 0xF8, 0xB5, 0x05, 0x20, 0x0C, 0x46, 0x15, 0x46, ++0x1E, 0x46, 0xFB, 0xF7, 0x1F, 0xFE, 0x01, 0x28, 0x3C, 0xD0, 0x1F, 0x4F, 0x3B, 0x68, 0x73, 0xB1, 0x22, 0x78, 0xB2, 0xB1, ++0x61, 0x78, 0x01, 0x22, 0x8A, 0x40, 0x13, 0x43, 0x31, 0x46, 0x2A, 0x46, 0x41, 0xF2, 0x18, 0x40, 0x3B, 0x60, 0xFB, 0xF7, ++0xD3, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x23, 0x78, 0x3B, 0xB9, 0x2A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x18, 0x40, 0xFB, 0xF7, ++0xC9, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x01, 0x23, 0x00, 0x21, 0x2A, 0x46, 0x22, 0x20, 0xFB, 0xF7, 0x59, 0xFB, 0x23, 0x78, ++0x61, 0x78, 0x8B, 0xB1, 0x3A, 0x68, 0x01, 0x23, 0x8B, 0x40, 0x13, 0x43, 0xB3, 0xFA, 0x83, 0xF2, 0x52, 0x09, 0x3B, 0x60, ++0x3E, 0x81, 0x02, 0x70, 0xFB, 0xF7, 0x7A, 0xFB, 0x28, 0x46, 0x01, 0x21, 0xFB, 0xF7, 0x40, 0xFD, 0x00, 0x20, 0xF8, 0xBD, ++0x3B, 0x68, 0x01, 0x22, 0x8A, 0x40, 0x23, 0xEA, 0x02, 0x03, 0xEB, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xE4, 0xB8, 0x17, 0x00, ++0xF8, 0xB5, 0x05, 0x20, 0x0D, 0x46, 0x17, 0x46, 0x1E, 0x46, 0xFB, 0xF7, 0xD5, 0xFD, 0x01, 0x28, 0x24, 0xD0, 0x13, 0x4C, ++0x2B, 0x78, 0x61, 0x68, 0x00, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0x84, 0xF8, 0x77, 0x31, 0x81, 0xB9, 0x01, 0x23, 0x05, 0x22, ++0x31, 0x20, 0xFB, 0xF7, 0x23, 0xFB, 0x94, 0xF8, 0x77, 0x31, 0xFF, 0x22, 0x22, 0x81, 0x73, 0xB9, 0x03, 0x70, 0xFB, 0xF7, ++0x4B, 0xFB, 0x01, 0x21, 0x05, 0x20, 0xFB, 0xF7, 0x11, 0xFD, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x14, 0x40, 0xFB, 0xF7, ++0x79, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x94, 0xF8, 0x78, 0x31, 0xED, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xE4, 0xB8, 0x17, 0x00, ++0x08, 0xB5, 0x4F, 0xF4, 0xBE, 0x72, 0x00, 0x21, 0x09, 0x48, 0xD8, 0xF7, 0xFB, 0xFE, 0x00, 0x21, 0x05, 0x20, 0xFB, 0xF7, ++0xF7, 0xFC, 0x04, 0xF0, 0xFB, 0xFF, 0x04, 0xF0, 0x7D, 0xFA, 0x02, 0xF0, 0x25, 0xF9, 0x09, 0xF0, 0x41, 0xF9, 0xBD, 0xE8, ++0x08, 0x40, 0x0E, 0xF0, 0xD5, 0xB8, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0xA8, 0xB9, 0x10, 0x4B, 0x93, 0xF8, 0x72, 0x01, ++0x76, 0x33, 0xC8, 0xB1, 0x00, 0xEB, 0x40, 0x00, 0x10, 0xB4, 0x03, 0xEB, 0x40, 0x04, 0x01, 0xE0, 0xA3, 0x42, 0x0D, 0xD0, ++0x1A, 0x88, 0x8A, 0x42, 0x18, 0x46, 0x03, 0xF1, 0x06, 0x03, 0xF7, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x05, 0x4B, ++0x93, 0xF8, 0x73, 0x01, 0xCA, 0x33, 0xE8, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, ++0xE4, 0xB8, 0x17, 0x00, 0xF0, 0xB9, 0x4B, 0x1E, 0x0D, 0x2B, 0x31, 0xD8, 0x0E, 0x29, 0x32, 0xD0, 0x01, 0xEB, 0x81, 0x01, ++0x01, 0xF6, 0x67, 0x11, 0x19, 0x4B, 0x93, 0xF8, 0x72, 0x01, 0x76, 0x33, 0x60, 0xB3, 0x00, 0xEB, 0x40, 0x00, 0x10, 0xB4, ++0x03, 0xEB, 0x40, 0x04, 0x01, 0xE0, 0xA3, 0x42, 0x1A, 0xD0, 0x1A, 0x88, 0x8A, 0x42, 0x18, 0x46, 0x03, 0xF1, 0x06, 0x03, ++0xF7, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x01, 0x28, 0x06, 0xD0, 0x4F, 0xF6, 0xFF, 0x71, 0x0C, 0x4B, 0x93, 0xF8, ++0x73, 0x01, 0xCA, 0x33, 0xE4, 0xE7, 0x4B, 0x1E, 0xA4, 0x2B, 0xF5, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, 0x9C, 0x51, ++0x08, 0x31, 0xF1, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x4F, 0xF6, 0xFF, 0x71, 0xD0, 0xE7, 0x40, 0xF6, ++0xB4, 0x11, 0xCD, 0xE7, 0x70, 0x47, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0xF0, 0xB4, 0x03, 0x46, 0x42, 0x48, 0x5C, 0x68, ++0x90, 0xF8, 0x75, 0x21, 0xA5, 0x06, 0x2E, 0xD5, 0x93, 0xF8, 0xFA, 0x70, 0x93, 0xF8, 0xFC, 0x50, 0x93, 0xF8, 0x01, 0x61, ++0x7C, 0x10, 0xFF, 0x06, 0x4F, 0xEA, 0xD5, 0x05, 0x55, 0xD5, 0x04, 0x24, 0x05, 0xEA, 0xD6, 0x16, 0x90, 0xF8, 0x74, 0x50, ++0xB3, 0xF8, 0xC8, 0x00, 0xB5, 0x42, 0x28, 0xBF, 0x35, 0x46, 0x94, 0x42, 0x28, 0xBF, 0x14, 0x46, 0x83, 0xF8, 0x2C, 0x41, ++0x91, 0xF8, 0xD9, 0x20, 0x04, 0x2A, 0x46, 0xD0, 0xA2, 0x42, 0x28, 0xBF, 0x22, 0x46, 0x04, 0x2A, 0x43, 0xD0, 0xD2, 0xB2, ++0x00, 0xF0, 0x0C, 0x00, 0x0C, 0x38, 0x83, 0xF8, 0x2D, 0x21, 0x83, 0xF8, 0x30, 0x51, 0x18, 0xBF, 0x01, 0x20, 0xF0, 0xBC, ++0x70, 0x47, 0x90, 0xF8, 0x74, 0x51, 0x60, 0x07, 0x13, 0xD5, 0xD3, 0xF8, 0xE8, 0x00, 0x00, 0xF0, 0x0C, 0x04, 0x04, 0x2C, ++0x44, 0xD0, 0x08, 0x2C, 0x0C, 0xBF, 0x04, 0x24, 0x02, 0x24, 0xC0, 0xF3, 0x02, 0x20, 0x04, 0x28, 0x27, 0xD8, 0x85, 0x42, ++0x28, 0xBF, 0x05, 0x46, 0xB3, 0xF8, 0xC8, 0x00, 0xCD, 0xE7, 0xB3, 0xF8, 0xC8, 0x00, 0x10, 0xF0, 0x02, 0x04, 0xC0, 0xF3, ++0x01, 0x26, 0x28, 0xD0, 0x01, 0x2A, 0x28, 0xBF, 0x01, 0x22, 0x83, 0xF8, 0x2C, 0x21, 0x14, 0x46, 0x91, 0xF8, 0xD9, 0x20, ++0xB5, 0x42, 0x28, 0xBF, 0x35, 0x46, 0x04, 0x2A, 0xC2, 0xD1, 0x02, 0x2C, 0x22, 0x46, 0x28, 0xBF, 0x02, 0x22, 0xD2, 0xB2, ++0xC2, 0xE7, 0x67, 0x07, 0x09, 0xD5, 0x03, 0x24, 0xA6, 0xE7, 0x04, 0x2C, 0xF3, 0xD1, 0x03, 0x22, 0xBA, 0xE7, 0xB3, 0xF8, ++0xC8, 0x00, 0x00, 0x25, 0xA7, 0xE7, 0xA6, 0x07, 0x47, 0xBF, 0x05, 0xF0, 0x01, 0x06, 0x02, 0x24, 0x04, 0xF0, 0x01, 0x04, ++0x05, 0xF0, 0x01, 0x06, 0x96, 0xE7, 0xB5, 0x42, 0x83, 0xF8, 0x2C, 0x41, 0x28, 0xBF, 0x35, 0x46, 0x22, 0x46, 0xA5, 0xE7, ++0x03, 0x24, 0xBC, 0xE7, 0xE4, 0xB8, 0x17, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x01, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x14, 0xBF, ++0x07, 0x20, 0x09, 0x20, 0x70, 0x47, 0x08, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xF0, 0x03, 0x00, 0x01, 0x28, 0x04, 0xD0, ++0x02, 0x28, 0x14, 0xBF, 0x07, 0x20, 0x0B, 0x20, 0x70, 0x47, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x10, 0xB4, 0x0E, 0x22, ++0x04, 0x46, 0x07, 0x20, 0x44, 0xFA, 0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, ++0x02, 0x02, 0x02, 0xD1, 0x11, 0xF0, 0xFF, 0x00, 0xF2, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xC3, 0x78, 0x33, 0xB9, ++0x83, 0x78, 0x33, 0xB9, 0x40, 0x78, 0x00, 0x28, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x02, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x23, 0x40, 0xFA, 0x03, 0xF2, 0x12, 0xF0, 0x01, 0x0F, 0xD9, 0xB2, 0x03, 0xF1, 0x01, 0x03, ++0x02, 0xD1, 0x0C, 0x2B, 0xF5, 0xD1, 0x19, 0x46, 0x08, 0x46, 0x70, 0x47, 0x68, 0xB1, 0x00, 0x23, 0xC3, 0xF1, 0x0B, 0x02, ++0x40, 0xFA, 0x02, 0xF2, 0xD2, 0x07, 0xD9, 0xB2, 0x03, 0xF1, 0x01, 0x03, 0x05, 0xD4, 0x0C, 0x2B, 0xF4, 0xD1, 0xFF, 0x20, ++0x70, 0x47, 0x0C, 0x20, 0x70, 0x47, 0xC1, 0xF1, 0x0B, 0x01, 0xC8, 0xB2, 0x70, 0x47, 0x00, 0xBF, 0xF0, 0xB5, 0xDD, 0xE9, ++0x05, 0x56, 0x00, 0x24, 0x1C, 0x80, 0x2C, 0x60, 0x34, 0x60, 0x50, 0xB3, 0x84, 0x78, 0xC4, 0xF3, 0x82, 0x0C, 0xBC, 0xF1, ++0x02, 0x0F, 0x04, 0xF0, 0x03, 0x04, 0x23, 0xDC, 0x4F, 0xF0, 0x01, 0x0C, 0x04, 0xF1, 0x0D, 0x00, 0x4F, 0xF0, 0x01, 0x0E, ++0x0E, 0xFA, 0x00, 0xF0, 0x07, 0x9F, 0x01, 0x38, 0x80, 0xB2, 0x87, 0xF8, 0x00, 0xC0, 0x18, 0x80, 0xF9, 0xB1, 0x09, 0x68, ++0xC1, 0xF3, 0xC2, 0x51, 0x01, 0xF1, 0x0D, 0x03, 0x0E, 0xFA, 0x03, 0xF3, 0x01, 0x3B, 0x2B, 0x60, 0x4A, 0xB1, 0x07, 0x29, ++0x11, 0xD1, 0xD3, 0x78, 0xC3, 0xF3, 0xC1, 0x03, 0x14, 0x33, 0x0E, 0xFA, 0x03, 0xF7, 0x01, 0x3F, 0x37, 0x60, 0xF0, 0xBD, ++0xAC, 0xF1, 0x03, 0x00, 0x4F, 0xF0, 0x01, 0x0C, 0x0C, 0xFA, 0x00, 0xFC, 0x5F, 0xFA, 0x8C, 0xFC, 0xD4, 0xE7, 0x33, 0x60, ++0xF0, 0xBD, 0x00, 0x2A, 0xF1, 0xD0, 0x03, 0x2C, 0x01, 0xD0, 0x30, 0x60, 0xF0, 0xBD, 0xD3, 0x78, 0xC3, 0xF3, 0xC1, 0x03, ++0x10, 0x33, 0x0E, 0xFA, 0x03, 0xF7, 0x01, 0x3F, 0x37, 0x60, 0xF0, 0xBD, 0x00, 0xF0, 0x7F, 0x03, 0x48, 0x2B, 0x31, 0xD8, ++0x10, 0xF0, 0x7E, 0x0F, 0x2C, 0xD0, 0x02, 0x3B, 0x46, 0x2B, 0x29, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x26, 0x28, 0x24, 0x28, ++0x28, 0x28, 0x28, 0x28, 0x28, 0x35, 0x37, 0x28, 0x28, 0x28, 0x28, 0x28, 0x39, 0x28, 0x28, 0x28, 0x3B, 0x28, 0x3D, 0x28, ++0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x3F, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, ++0x28, 0x28, 0x41, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, ++0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x33, 0x00, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0xFF, 0x20, 0x70, 0x47, ++0x60, 0x2B, 0x04, 0xD0, 0x6C, 0x2B, 0x14, 0xBF, 0xFF, 0x20, 0x0B, 0x20, 0x70, 0x47, 0x0A, 0x20, 0x70, 0x47, 0x09, 0x20, ++0x70, 0x47, 0x02, 0x20, 0x70, 0x47, 0x04, 0x20, 0x70, 0x47, 0x05, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x06, 0x20, ++0x70, 0x47, 0x07, 0x20, 0x70, 0x47, 0x08, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, 0x90, 0xF8, 0x00, 0xB0, ++0xBB, 0xF1, 0x00, 0x0F, 0x34, 0xD0, 0xDF, 0xF8, 0x70, 0x80, 0xDF, 0xF8, 0x70, 0xA0, 0xDF, 0xF8, 0x70, 0x90, 0x05, 0x46, ++0x0E, 0x46, 0x04, 0x46, 0x00, 0x27, 0x9E, 0xB9, 0x60, 0x78, 0xFF, 0xF7, 0x9B, 0xFF, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x4F, 0xF0, 0x01, 0x03, 0x0E, 0xDB, 0x0B, 0x28, 0x0E, 0xDD, 0x01, 0x34, 0x63, 0x1B, 0x5B, 0x45, ++0xED, 0xDB, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x94, 0xF9, 0x01, 0x30, 0x60, 0x78, 0x00, 0x2B, 0xE7, 0xDB, 0xF2, 0xE7, ++0x0B, 0x28, 0x04, 0xDC, 0x03, 0xFA, 0x00, 0xF0, 0x07, 0x43, 0xBF, 0xB2, 0xEB, 0xE7, 0x4F, 0xF4, 0x15, 0x72, 0x51, 0x46, ++0x48, 0x46, 0xFD, 0xF7, 0xC5, 0xF9, 0x95, 0xF8, 0x00, 0xB0, 0xE2, 0xE7, 0x5F, 0x46, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xB8, 0x15, 0x00, 0xF0, 0xB4, 0x00, 0x24, 0x4F, 0xF6, 0xFF, 0x77, ++0x03, 0x26, 0x40, 0xFA, 0x04, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x06, 0xFA, 0x04, 0xF2, 0x41, 0xFA, 0x04, 0xF5, 0x03, 0x2B, ++0x27, 0xEA, 0x02, 0x02, 0x05, 0xF0, 0x03, 0x05, 0x0A, 0xD0, 0x03, 0x2D, 0x08, 0xD0, 0xAB, 0x42, 0x28, 0xBF, 0x2B, 0x46, ++0xA3, 0x40, 0x02, 0x34, 0x1A, 0x43, 0x10, 0x2C, 0x97, 0xB2, 0xE6, 0xD1, 0x38, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0xBF, ++0x08, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x41, 0xF2, 0x21, 0x42, 0xD0, 0xF8, 0x90, 0x31, 0x98, 0x78, ++0x41, 0xF2, 0x21, 0x53, 0x01, 0x28, 0x14, 0xBF, 0x10, 0x46, 0x18, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0xD0, 0xF8, 0xDC, 0x30, 0xC3, 0xF3, 0x05, 0x60, 0x5B, 0x00, 0x54, 0xBF, 0x40, 0xF4, 0x80, 0x70, 0x40, 0xF4, 0x40, 0x70, ++0x70, 0x47, 0x00, 0xBF, 0x10, 0xB5, 0x04, 0x46, 0x0C, 0xF0, 0x86, 0xFB, 0x03, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x5C, 0x31, ++0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x90, 0xF8, 0xB8, 0x00, 0x18, 0xDB, 0x68, 0xB1, 0x05, 0xF1, 0xB8, 0x03, 0x1C, 0x18, ++0x00, 0x20, 0x13, 0xF8, 0x01, 0x2F, 0x22, 0xF0, 0x80, 0x01, 0x81, 0x42, 0xC8, 0xBF, 0x02, 0xF0, 0x7F, 0x00, 0xA3, 0x42, ++0xF5, 0xD1, 0xFF, 0xF7, 0xFF, 0xFE, 0x01, 0x46, 0x28, 0x46, 0x0C, 0xF0, 0x5F, 0xF9, 0x00, 0x23, 0x85, 0xF8, 0x56, 0x31, ++0x38, 0xBD, 0x00, 0x28, 0xE5, 0xD1, 0x05, 0x48, 0x05, 0x49, 0x40, 0xF2, 0xC1, 0x22, 0xFD, 0xF7, 0x25, 0xF9, 0x95, 0xF8, ++0xB8, 0x00, 0xDB, 0xE7, 0x38, 0x36, 0x17, 0x00, 0xB0, 0xB8, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x90, 0xF8, 0x56, 0x31, 0xD0, 0xF8, 0x48, 0x71, 0x99, 0xB0, 0x00, 0x2B, 0x00, 0xF0, 0xDB, 0x80, 0xFA, 0x6B, 0x09, 0x92, ++0x7A, 0x68, 0x05, 0x92, 0x07, 0xF1, 0x14, 0x04, 0xBA, 0x68, 0x07, 0x92, 0x10, 0xAE, 0x0D, 0xF1, 0x50, 0x08, 0x05, 0x46, ++0x22, 0x46, 0xB4, 0x46, 0x40, 0x46, 0x07, 0xF1, 0x24, 0x0B, 0x52, 0xF8, 0x04, 0x1B, 0x4C, 0xF8, 0x04, 0x1B, 0x5A, 0x45, ++0xD1, 0x68, 0x40, 0xF8, 0x04, 0x1B, 0xF6, 0xD1, 0x13, 0xF0, 0x01, 0x02, 0x06, 0x92, 0x40, 0xF0, 0xC0, 0x80, 0x09, 0x9A, ++0xC2, 0xF3, 0xC0, 0x02, 0x06, 0x92, 0x9A, 0x06, 0x00, 0xF1, 0x16, 0x81, 0x98, 0x07, 0x1A, 0xD5, 0xDF, 0xF8, 0x64, 0x93, ++0x06, 0xF1, 0x10, 0x0E, 0x31, 0x46, 0x51, 0xF8, 0x04, 0x2B, 0xC2, 0xF3, 0xC2, 0x2A, 0x02, 0xF0, 0x7C, 0x00, 0x5A, 0xEA, ++0x00, 0x00, 0xC2, 0xF3, 0xC1, 0x1C, 0x02, 0xEA, 0x09, 0x02, 0x06, 0xD0, 0xD5, 0xF8, 0x50, 0x01, 0x02, 0x43, 0x42, 0xEA, ++0x0C, 0x62, 0x41, 0xF8, 0x04, 0x2C, 0x8E, 0x45, 0xE9, 0xD1, 0xD9, 0x06, 0x5C, 0xD5, 0x95, 0xF8, 0x22, 0x10, 0xC3, 0x4A, ++0xC3, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x20, 0xD3, 0xF8, 0x38, 0x33, 0x0D, 0xF1, 0x3F, 0x02, 0x0D, 0xF1, ++0x3E, 0x01, 0x98, 0x47, 0x06, 0xF1, 0x10, 0x03, 0x06, 0x94, 0x08, 0x95, 0x0D, 0xF1, 0x50, 0x09, 0x1C, 0x46, 0x35, 0x46, ++0xBA, 0x4B, 0x59, 0xF8, 0x04, 0xAB, 0x55, 0xF8, 0x04, 0x1B, 0x93, 0xF8, 0xBD, 0x30, 0x4F, 0xEA, 0x1A, 0x4A, 0xC1, 0xF3, ++0xC7, 0x22, 0xC1, 0xF3, 0xC2, 0x20, 0x5F, 0xFA, 0x81, 0xFC, 0x4F, 0xEA, 0x0A, 0x4A, 0x01, 0xF0, 0x7F, 0x01, 0xD3, 0xB9, ++0x0C, 0xF0, 0x7C, 0x0C, 0x50, 0xEA, 0x0C, 0x03, 0x00, 0xF0, 0x29, 0x81, 0xAD, 0x4B, 0x93, 0xF8, 0xBA, 0x30, 0x00, 0x2B, ++0x00, 0xF0, 0xF3, 0x80, 0xAB, 0x4B, 0x93, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xED, 0x80, 0x00, 0x28, 0x40, 0xF0, ++0x2F, 0x81, 0x09, 0x29, 0x00, 0xF2, 0x2C, 0x81, 0x02, 0xF0, 0x06, 0x02, 0x2D, 0xE1, 0xD9, 0xF7, 0x47, 0xFE, 0xA4, 0x4B, ++0x1A, 0x7D, 0x00, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x5A, 0x7D, 0x00, 0x2A, 0x00, 0xF0, 0x02, 0x81, 0x4A, 0xEA, 0x00, 0x20, ++0x40, 0xF0, 0xA8, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xAC, 0x42, 0xBD, 0xD1, 0x08, 0x9D, 0x06, 0x9C, 0x95, 0xF8, 0x56, 0x31, ++0x5A, 0x06, 0x13, 0xD5, 0x94, 0x4A, 0x95, 0xF8, 0x22, 0x30, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x07, 0x9A, ++0xD3, 0xF8, 0xC8, 0x31, 0x22, 0xF0, 0x7C, 0x72, 0x00, 0x2B, 0x07, 0x92, 0x04, 0xDB, 0xC3, 0xF3, 0x05, 0x63, 0x42, 0xEA, ++0x03, 0x53, 0x07, 0x93, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x8D, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x8C, 0x4A, 0x05, 0x9B, 0x11, 0x68, 0x7B, 0x60, 0x48, 0x1C, 0x07, 0x9B, 0xBB, 0x60, 0x10, 0x60, 0x56, 0xF8, 0x04, 0x3B, ++0x44, 0xF8, 0x04, 0x3B, 0x58, 0xF8, 0x04, 0x3B, 0xE3, 0x60, 0xA3, 0x45, 0xF6, 0xD1, 0x28, 0xB1, 0x82, 0x4B, 0x11, 0x60, ++0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x00, 0x23, 0x85, 0xF8, 0x56, 0x31, 0x38, 0x46, 0x19, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0xD5, 0xF8, 0x4C, 0x01, 0x95, 0xF8, 0x30, 0x21, 0x0D, 0x92, 0xCD, 0xE9, 0x0B, 0x34, 0x00, 0x22, 0x08, 0x92, ++0x00, 0xF1, 0x88, 0x0E, 0x0A, 0x92, 0x31, 0x46, 0x82, 0x46, 0x3E, 0xF8, 0x02, 0x3B, 0x03, 0xEB, 0x43, 0x03, 0x0A, 0xEB, ++0x83, 0x03, 0x58, 0x89, 0xC0, 0xF3, 0x0D, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x4F, 0xEA, 0xD3, 0x29, 0x19, 0xF0, 0x06, 0x0C, ++0x00, 0xF0, 0x8E, 0x80, 0x09, 0xF0, 0x07, 0x09, 0xB9, 0xF1, 0x04, 0x0F, 0x03, 0xF0, 0x7F, 0x0C, 0x00, 0xF0, 0xE5, 0x80, ++0xB9, 0xF1, 0x05, 0x0F, 0x00, 0xF0, 0xE4, 0x80, 0xCC, 0xF3, 0xC1, 0x0C, 0x00, 0x2A, 0x00, 0xF0, 0xD1, 0x80, 0x08, 0x98, ++0x00, 0x28, 0x40, 0xF0, 0x95, 0x80, 0x08, 0x68, 0x20, 0xF0, 0x60, 0x40, 0x20, 0xF4, 0x7F, 0x50, 0x20, 0xF0, 0x3F, 0x00, ++0x18, 0x43, 0x08, 0x60, 0x01, 0x32, 0x04, 0x2A, 0x01, 0xF1, 0x04, 0x01, 0xCB, 0xD1, 0x05, 0x9A, 0x22, 0xF4, 0xC0, 0x71, ++0x08, 0x9A, 0x05, 0x91, 0xDD, 0xE9, 0x0B, 0x34, 0x22, 0xB1, 0x0A, 0x9A, 0x01, 0x32, 0x41, 0xEA, 0xC2, 0x12, 0x05, 0x92, ++0x06, 0x9A, 0x00, 0x2A, 0x7E, 0xD1, 0x09, 0x9A, 0x22, 0xF0, 0x08, 0x02, 0x43, 0xF0, 0x02, 0x03, 0xFA, 0x63, 0x9A, 0x06, ++0x85, 0xF8, 0x56, 0x31, 0x7F, 0xF5, 0xEA, 0xAE, 0xD5, 0xF8, 0x4C, 0x01, 0x7A, 0x69, 0x90, 0xF8, 0xA0, 0x30, 0xDF, 0xF8, ++0x38, 0xE1, 0x05, 0x99, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x0E, 0xEA, 0x02, 0x0E, 0xB3, 0xF8, 0x0A, 0xC0, ++0xCC, 0xF3, 0x0D, 0x02, 0xC1, 0xF3, 0xC1, 0x13, 0x42, 0xF0, 0x80, 0x42, 0x11, 0xF4, 0xC0, 0x7F, 0xCC, 0xF3, 0x80, 0x3C, ++0x4E, 0xEA, 0x02, 0x01, 0x03, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x80, 0xF8, 0xA1, 0xC0, 0xC0, 0xF8, 0x9C, 0x10, 0x4F, 0xF0, ++0x00, 0x02, 0x06, 0x98, 0x00, 0x93, 0x03, 0x90, 0x14, 0xBF, 0x01, 0x23, 0x13, 0x46, 0xCD, 0xE9, 0x01, 0x22, 0x38, 0x46, ++0x0C, 0xF0, 0x56, 0xFF, 0x95, 0xF8, 0x56, 0x31, 0xB6, 0xE6, 0x9D, 0xF8, 0x3F, 0x00, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, ++0x0A, 0x00, 0x02, 0xF0, 0x06, 0x02, 0x49, 0xF8, 0x04, 0x0C, 0x00, 0x2A, 0x3F, 0xF4, 0x20, 0xAF, 0x09, 0x29, 0x7F, 0xF6, ++0x1D, 0xAF, 0x29, 0x4B, 0x59, 0xF8, 0x04, 0x2C, 0x93, 0xF8, 0xAF, 0x10, 0x12, 0x0C, 0x41, 0xEA, 0x01, 0x21, 0x12, 0x04, ++0x0A, 0x43, 0x49, 0xF8, 0x04, 0x2C, 0x0F, 0xE7, 0x08, 0x68, 0xCD, 0xF8, 0x18, 0xC0, 0x20, 0xF0, 0x60, 0x40, 0x20, 0xF4, ++0x7F, 0x50, 0x20, 0xF0, 0x3F, 0x00, 0x18, 0x43, 0x08, 0x60, 0x83, 0xE7, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, 0x0A, 0x00, ++0x49, 0xF8, 0x04, 0x0C, 0xFC, 0xE6, 0x9D, 0xF8, 0x3E, 0x20, 0x42, 0xEA, 0x02, 0x22, 0x42, 0xEA, 0x0A, 0x02, 0x49, 0xF8, ++0x04, 0x2C, 0xF3, 0xE6, 0x0A, 0x98, 0xAC, 0xEB, 0x00, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x08, 0x90, 0x62, 0xE7, ++0x09, 0x9A, 0x42, 0xF0, 0x08, 0x02, 0x7F, 0xE7, 0x12, 0xF0, 0x06, 0x02, 0x0B, 0xD0, 0x04, 0x29, 0x09, 0xD8, 0x0C, 0x4B, ++0x93, 0xF8, 0xBB, 0x00, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, 0x0A, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xB5, 0xE7, 0x07, 0x4B, ++0xB3, 0xF8, 0xBB, 0x00, 0x40, 0xBA, 0x80, 0xB2, 0x40, 0xEA, 0x0A, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xAB, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xFF, 0x3F, 0x00, 0xE0, 0x00, 0xC0, 0xFF, 0x1F, 0x0D, 0x98, 0x84, 0x45, ++0x0A, 0x98, 0x38, 0xBF, 0x60, 0x46, 0x0A, 0x90, 0x08, 0x98, 0x38, 0xBF, 0x01, 0x20, 0x08, 0x90, 0x27, 0xE7, 0x4F, 0xEA, ++0x1C, 0x1C, 0x1D, 0xE7, 0x14, 0xAC, 0x03, 0xF4, 0xC0, 0x69, 0x54, 0xF8, 0x22, 0x40, 0xB9, 0xF5, 0x80, 0x6F, 0x0C, 0xBF, ++0x4F, 0xF4, 0x00, 0x39, 0x4F, 0xF4, 0x80, 0x39, 0x24, 0xF4, 0x40, 0x34, 0x44, 0xEA, 0x09, 0x09, 0x40, 0x04, 0x14, 0xAC, ++0x4C, 0xBF, 0x49, 0xF4, 0x80, 0x20, 0x29, 0xF4, 0x80, 0x20, 0x44, 0xF8, 0x22, 0x00, 0x4F, 0xEA, 0x1C, 0x1C, 0x01, 0xE7, ++0xF0, 0xB4, 0xD2, 0xF8, 0xA4, 0x50, 0x2C, 0x88, 0x30, 0xBB, 0x00, 0x29, 0x44, 0xD0, 0x51, 0x4E, 0x03, 0x46, 0x96, 0xF8, ++0x75, 0x01, 0x26, 0x46, 0x01, 0x28, 0x4F, 0xD9, 0x8F, 0x78, 0x17, 0xF0, 0x03, 0x07, 0x3C, 0xD0, 0xAD, 0x78, 0xCB, 0x78, ++0x09, 0x79, 0x00, 0x2D, 0x41, 0xD1, 0x5E, 0x1E, 0x0D, 0x2E, 0x40, 0xD8, 0x0E, 0x2B, 0x00, 0xF0, 0x86, 0x80, 0x03, 0xEB, ++0x83, 0x03, 0x03, 0xF6, 0x67, 0x13, 0x00, 0x29, 0x47, 0xD0, 0x03, 0x2F, 0x60, 0xD0, 0x02, 0x2F, 0x57, 0xD0, 0x02, 0x20, ++0x1C, 0x46, 0x00, 0x21, 0x03, 0x46, 0x05, 0xE0, 0x3E, 0x4B, 0x93, 0xF8, 0x75, 0x31, 0x5B, 0xB9, 0x18, 0x46, 0x00, 0x21, ++0xA2, 0xF8, 0xA8, 0x40, 0x82, 0xF8, 0xD8, 0x30, 0xF0, 0xBC, 0x82, 0xF8, 0xD9, 0x00, 0xA2, 0xF8, 0xAA, 0x10, 0x70, 0x47, ++0xC0, 0x78, 0x10, 0xF0, 0x03, 0x00, 0x12, 0xD0, 0x01, 0x28, 0x4F, 0xF6, 0xF6, 0x76, 0x08, 0xBF, 0x0A, 0x26, 0x26, 0x44, ++0xB6, 0xB2, 0x51, 0xBB, 0x01, 0x23, 0x34, 0x46, 0x18, 0x46, 0xE5, 0xE7, 0x08, 0x46, 0x0B, 0x46, 0xE2, 0xE7, 0x34, 0x46, ++0x39, 0x46, 0x18, 0x46, 0xDE, 0xE7, 0x99, 0xB1, 0x1F, 0x46, 0x26, 0x46, 0x03, 0x46, 0x38, 0x46, 0xB2, 0xE7, 0x01, 0x2D, ++0x1A, 0xD0, 0x4F, 0xF6, 0xFF, 0x73, 0xC2, 0xE7, 0x34, 0x46, 0xCF, 0xE7, 0x4F, 0xF6, 0xD8, 0x71, 0x9C, 0x42, 0x94, 0xBF, ++0x0C, 0x46, 0x28, 0x24, 0x23, 0x44, 0x9C, 0xB2, 0x03, 0x46, 0x00, 0x21, 0xC6, 0xE7, 0x02, 0x2F, 0x11, 0xD0, 0x03, 0x2F, ++0x20, 0xD0, 0x02, 0x20, 0x1C, 0x46, 0x03, 0x46, 0xBE, 0xE7, 0x18, 0x46, 0x01, 0x23, 0x95, 0xE7, 0x5E, 0x1E, 0xA4, 0x2E, ++0xE1, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x53, 0x08, 0x33, 0xA1, 0xE7, 0x02, 0x28, 0xDE, 0xD0, 0x03, 0x20, ++0x1C, 0x46, 0x00, 0x21, 0x03, 0x46, 0xAB, 0xE7, 0x85, 0xB9, 0x4C, 0x1E, 0x0D, 0x2C, 0x0A, 0xD8, 0x0E, 0x29, 0x19, 0xD0, ++0x01, 0xEB, 0x81, 0x01, 0x01, 0xF6, 0x67, 0x11, 0x04, 0x28, 0x94, 0xD1, 0x1C, 0x46, 0x03, 0x23, 0x9C, 0xE7, 0x4F, 0xF6, ++0xFF, 0x71, 0xF7, 0xE7, 0x01, 0x2D, 0xFA, 0xD1, 0x4C, 0x1E, 0xA4, 0x2C, 0xF7, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, ++0x9C, 0x51, 0x08, 0x31, 0xEC, 0xE7, 0x40, 0xF6, 0xB4, 0x13, 0x7A, 0xE7, 0x40, 0xF6, 0xB4, 0x11, 0xE6, 0xE7, 0x00, 0xBF, ++0xE4, 0xB8, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x7B, 0x4F, 0xDF, 0xF8, 0x08, 0x92, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x00, 0x73, 0x04, 0x46, 0x93, 0xF8, 0x22, 0x60, 0x58, 0x68, 0x77, 0x4B, 0x1B, 0x68, 0x10, 0xF0, 0x20, 0x0A, 0xB3, 0xF9, ++0x00, 0x30, 0x0D, 0x46, 0x90, 0x46, 0x4F, 0xD0, 0x00, 0x2B, 0xC0, 0xF2, 0x9F, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x04, 0x73, 0x0E, 0x21, 0xB3, 0xF8, 0x06, 0xC1, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, ++0x02, 0xF1, 0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, 0xB3, 0x80, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0x90, 0x46, ++0xB9, 0xF8, 0x50, 0xC0, 0x0E, 0x21, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, ++0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, 0x9B, 0x80, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0x5D, 0x4B, 0x4F, 0xF4, ++0x1E, 0x70, 0x00, 0xFB, 0x04, 0x74, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x06, 0x36, 0x94, 0xF8, 0x2C, 0x31, 0x96, 0xF8, ++0xC4, 0x11, 0x94, 0xF8, 0x23, 0x00, 0x04, 0x2B, 0x08, 0xBF, 0x03, 0x23, 0xA9, 0x42, 0x28, 0xBF, 0x29, 0x46, 0x99, 0x42, ++0x28, 0xBF, 0x19, 0x46, 0x84, 0xF8, 0x2D, 0x11, 0x0B, 0xF0, 0x22, 0xFD, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x08, 0x03, ++0x84, 0xF8, 0x56, 0x31, 0xBD, 0xE8, 0xF8, 0x8F, 0x10, 0xF0, 0x04, 0x0B, 0x28, 0xD0, 0x00, 0x2B, 0x58, 0xDB, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x04, 0x73, 0x0E, 0x22, 0xB3, 0xF8, 0xEC, 0xC0, 0x07, 0x20, 0x4C, 0xFA, 0x02, 0xF3, 0x03, 0xF0, ++0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, 0x6A, 0xD1, 0x11, 0xF0, 0xFF, 0x00, 0xF2, 0xD1, ++0xB9, 0xF8, 0x38, 0xC0, 0x0E, 0x21, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, ++0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x54, 0xD1, 0x10, 0xF0, 0xFF, 0x02, 0xF2, 0xD1, 0xAF, 0xE7, 0x00, 0x2B, 0x3A, 0xDB, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x73, 0x03, 0xF1, 0xCB, 0x02, 0x93, 0xF8, 0xCE, 0x30, 0x00, 0x2B, 0x54, 0xD1, ++0x93, 0x78, 0x00, 0x2B, 0x4B, 0xD1, 0x53, 0x78, 0x01, 0x20, 0x00, 0x2B, 0x48, 0xD1, 0x99, 0xF8, 0x12, 0x30, 0x00, 0x2B, ++0x4B, 0xD1, 0x99, 0xF8, 0x11, 0x30, 0x00, 0x2B, 0x49, 0xD1, 0x99, 0xF8, 0x10, 0x20, 0x00, 0x3A, 0x18, 0xBF, 0x01, 0x22, ++0x93, 0x45, 0x58, 0x46, 0x28, 0xBF, 0x10, 0x46, 0xC2, 0xB2, 0x89, 0xE7, 0x99, 0xF8, 0x76, 0x31, 0x59, 0x07, 0x3F, 0xF5, ++0x5C, 0xAF, 0x21, 0x49, 0x21, 0x48, 0x40, 0xF2, 0x55, 0x52, 0xFC, 0xF7, 0x99, 0xFD, 0x54, 0xE7, 0x99, 0xF8, 0x76, 0x31, ++0x9A, 0x07, 0xA2, 0xD4, 0x1B, 0x49, 0x1D, 0x48, 0x40, 0xF2, 0x62, 0x52, 0xFC, 0xF7, 0x8E, 0xFD, 0x9B, 0xE7, 0x99, 0xF8, ++0x76, 0x31, 0xDB, 0x07, 0xC0, 0xD4, 0x16, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x6D, 0x52, 0xFC, 0xF7, 0x83, 0xFD, 0xB9, 0xE7, ++0x42, 0x45, 0x28, 0xBF, 0x42, 0x46, 0xD2, 0xB2, 0x62, 0xE7, 0x90, 0x45, 0x28, 0xBF, 0x90, 0x46, 0x4C, 0xE7, 0x52, 0x45, ++0x28, 0xBF, 0x52, 0x46, 0xD2, 0xB2, 0x59, 0xE7, 0x40, 0x45, 0x28, 0xBF, 0x40, 0x46, 0x82, 0x46, 0x92, 0xE7, 0x02, 0x20, ++0x80, 0x45, 0x28, 0xBF, 0x80, 0x46, 0xC3, 0x46, 0xB1, 0xE7, 0x03, 0x20, 0xF8, 0xE7, 0x03, 0x22, 0xBA, 0xE7, 0x02, 0x22, ++0xB8, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC4, 0xB8, 0x15, 0x00, 0xD4, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x2D, 0xED, 0x02, 0x8B, 0xDF, 0xF8, 0xE4, 0xA3, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0xF3, 0x0A, 0xEB, 0x03, 0x06, ++0x8B, 0xB0, 0xB6, 0xF8, 0xC2, 0x41, 0x02, 0x93, 0x01, 0x90, 0xD6, 0xF8, 0x90, 0x31, 0x96, 0xF8, 0xC6, 0x51, 0x04, 0x95, ++0x00, 0x20, 0xA6, 0xF8, 0xC2, 0x01, 0x98, 0x78, 0x02, 0x9D, 0xD6, 0xF8, 0xC8, 0x31, 0x03, 0x94, 0x03, 0xF0, 0x7F, 0x43, ++0x05, 0xF1, 0xEC, 0x0C, 0x24, 0x32, 0x05, 0x93, 0x0A, 0xEB, 0x0C, 0x03, 0xD6, 0xF8, 0xE4, 0x40, 0x96, 0xF8, 0xC5, 0x71, ++0x08, 0xEE, 0x10, 0x2A, 0x08, 0xEE, 0x90, 0x3A, 0xA1, 0xF1, 0x24, 0x09, 0x00, 0x28, 0x00, 0xF0, 0xDD, 0x81, 0x1F, 0xFA, ++0x89, 0xF8, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x03, 0xA9, 0xD9, 0xF8, 0xCC, 0x31, 0xDD, 0x07, 0x05, 0xD5, ++0x99, 0xF8, 0x62, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x5C, 0x82, 0xD2, 0x4B, 0x93, 0xF8, 0x76, 0xB1, 0x1B, 0xF0, ++0x01, 0x0B, 0x40, 0xF0, 0xE9, 0x81, 0xD9, 0x46, 0x48, 0x46, 0x18, 0xEE, 0x90, 0x2A, 0x59, 0x46, 0xFF, 0xF7, 0xF8, 0xFD, ++0x02, 0x9B, 0x03, 0xF2, 0xB4, 0x43, 0x18, 0xEE, 0x10, 0x0A, 0x53, 0x44, 0x0D, 0xF1, 0x25, 0x02, 0x41, 0x46, 0xFD, 0xF7, ++0xD5, 0xFF, 0x10, 0xF0, 0xFF, 0x09, 0x1F, 0xD0, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x6B, 0x0B, 0xFB, 0x03, 0xAB, 0x9B, 0xF8, ++0x62, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x9D, 0x81, 0x9B, 0xF8, 0x8A, 0x10, 0x00, 0x29, 0x00, 0xF0, 0x6F, 0x82, 0x89, 0x45, ++0x07, 0xD0, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x01, 0x22, 0x83, 0xF8, 0x8C, 0x20, 0x01, 0x9A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x83, 0xF8, 0x8A, 0x90, 0x18, 0xEE, 0x90, 0x2A, 0x41, 0x46, 0x18, 0xEE, ++0x10, 0x0A, 0xFD, 0xF7, 0x25, 0xFF, 0x01, 0x9A, 0x04, 0x99, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x93, 0xF8, ++0xC6, 0x21, 0x8A, 0x42, 0x0E, 0xD0, 0xD3, 0xF8, 0x90, 0x11, 0xAC, 0x4B, 0x09, 0x79, 0xD3, 0xF8, 0x40, 0x33, 0x8A, 0x1A, ++0x8D, 0xF8, 0x26, 0x20, 0x0D, 0xF1, 0x26, 0x01, 0x0D, 0xF1, 0x27, 0x02, 0x30, 0x46, 0x98, 0x47, 0x01, 0x9B, 0x4F, 0xF4, ++0xA4, 0x68, 0x08, 0xFB, 0x03, 0xA8, 0x98, 0xF8, 0xC5, 0x31, 0xBB, 0x42, 0x00, 0xF2, 0x01, 0x81, 0x00, 0x2C, 0x00, 0xF0, ++0x8E, 0x80, 0x01, 0x9B, 0x9F, 0x4E, 0x03, 0x9D, 0xDD, 0xF8, 0x14, 0x90, 0x4F, 0xF4, 0xA4, 0x68, 0x08, 0xFB, 0x03, 0xA8, ++0xB8, 0xF8, 0xC2, 0x21, 0xAA, 0x42, 0x1D, 0xD0, 0x29, 0x46, 0x30, 0x46, 0xFC, 0xF7, 0x1A, 0xFA, 0x94, 0xF8, 0x56, 0x31, ++0xB8, 0xF8, 0xC2, 0x21, 0x94, 0xF8, 0x23, 0x00, 0x43, 0xF0, 0x02, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x53, 0x07, 0x4F, 0xF0, ++0x00, 0x01, 0x58, 0xBF, 0x4F, 0xF4, 0x80, 0x63, 0xC4, 0xF8, 0x50, 0x11, 0x4E, 0xBF, 0xA4, 0xF8, 0x54, 0x11, 0xA4, 0xF8, ++0x54, 0x31, 0x01, 0x21, 0x0B, 0xF0, 0x02, 0xFC, 0x98, 0xF8, 0xC5, 0x31, 0xBB, 0x42, 0x4B, 0xD0, 0x04, 0x2B, 0x94, 0xF8, ++0x2C, 0xA1, 0x5F, 0xD0, 0x53, 0x45, 0x28, 0xBF, 0x53, 0x46, 0x04, 0x2B, 0x00, 0xF0, 0x93, 0x80, 0x5F, 0xFA, 0x83, 0xFA, ++0x94, 0xF8, 0x2D, 0x31, 0x53, 0x45, 0x3B, 0xD0, 0x63, 0x68, 0x13, 0xF0, 0x20, 0x0B, 0x58, 0xD0, 0x7F, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA7, 0x80, 0xB4, 0xF8, 0x06, 0xC1, 0x0E, 0x22, 0x07, 0x20, 0x4C, 0xFA, ++0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, 0x02, 0xD1, 0x11, 0xF0, ++0xFF, 0x00, 0xF2, 0xD1, 0x70, 0x4B, 0x07, 0x22, 0xB3, 0xF8, 0x50, 0xE0, 0x0E, 0x23, 0x4E, 0xFA, 0x03, 0xF1, 0x01, 0xF0, ++0x03, 0x01, 0x03, 0x29, 0x02, 0xF1, 0xFF, 0x3C, 0xA3, 0xF1, 0x02, 0x03, 0x40, 0xF0, 0xF4, 0x80, 0x1C, 0xF0, 0xFF, 0x02, ++0xF1, 0xD1, 0x94, 0xF8, 0x23, 0x00, 0x84, 0xF8, 0x2D, 0xA1, 0x51, 0x46, 0x0B, 0xF0, 0x54, 0xFB, 0x94, 0xF8, 0x56, 0x31, ++0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x56, 0x31, 0xD8, 0xF8, 0xC8, 0x31, 0x03, 0xF0, 0x7F, 0x43, 0x4B, 0x45, 0x08, 0xD0, ++0x63, 0x68, 0x9B, 0x06, 0x05, 0xD5, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x24, 0x68, ++0x00, 0x2C, 0x7F, 0xF4, 0x7B, 0xAF, 0x0B, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0xBA, 0xF1, 0x03, 0x0F, ++0x35, 0xD8, 0xBA, 0xF1, 0x02, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, 0x02, 0x0A, 0x9E, 0xE7, 0x13, 0xF0, 0x04, 0x0F, 0x52, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x2B, 0xD0, 0x00, 0x2B, 0xC0, 0xF2, 0xA7, 0x80, 0xB4, 0xF8, 0xEC, 0xC0, 0x0E, 0x22, ++0x07, 0x20, 0x4C, 0xFA, 0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, ++0x40, 0xF0, 0x97, 0x81, 0x11, 0xF0, 0xFF, 0x00, 0xF1, 0xD1, 0x42, 0x4B, 0xB3, 0xF8, 0x38, 0xC0, 0x0E, 0x21, 0x07, 0x22, ++0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, 0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, ++0x7F, 0x81, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0xA1, 0xE7, 0x4F, 0xF0, 0x03, 0x0A, 0x6B, 0xE7, 0x00, 0x2B, 0x5E, 0xDB, ++0x94, 0xF8, 0xCE, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xDF, 0x81, 0x94, 0xF8, 0xCD, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xE0, 0x81, ++0x94, 0xF8, 0xCC, 0x20, 0x11, 0x1E, 0x18, 0xBF, 0x01, 0x21, 0x2E, 0x4A, 0x93, 0x7C, 0x00, 0x2B, 0x40, 0xF0, 0xD2, 0x81, ++0x53, 0x7C, 0x00, 0x2B, 0x40, 0xF0, 0xD0, 0x81, 0x13, 0x7C, 0x1A, 0x1E, 0x18, 0xBF, 0x01, 0x22, 0x8A, 0x42, 0x28, 0xBF, ++0x0A, 0x46, 0x7C, 0xE7, 0x25, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x58, 0x07, 0x3F, 0xF5, 0x53, 0xAF, 0x26, 0x49, 0x27, 0x48, ++0x40, 0xF2, 0xCD, 0x12, 0xFC, 0xF7, 0xA8, 0xFB, 0x4B, 0xE7, 0x0C, 0x23, 0x05, 0x22, 0x00, 0x21, 0x3B, 0x20, 0xFA, 0xF7, ++0xBF, 0xFA, 0x1F, 0x4B, 0xD8, 0xF8, 0x40, 0x20, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x81, 0x46, 0xC0, 0xF2, ++0x18, 0x81, 0x13, 0x7E, 0x89, 0xF8, 0x00, 0x30, 0xD6, 0xF8, 0x90, 0x31, 0x99, 0x78, 0x89, 0xF8, 0x02, 0x10, 0x96, 0xF8, ++0xC5, 0x11, 0x89, 0xF8, 0x03, 0x10, 0xB3, 0xF8, 0x00, 0xC0, 0xB6, 0xF8, 0x94, 0x01, 0xB6, 0xF8, 0x96, 0x11, 0xA9, 0xF8, ++0x08, 0x10, 0xA9, 0xF8, 0x06, 0x00, 0xA9, 0xF8, 0x04, 0xC0, 0x12, 0x7B, 0x89, 0xF8, 0x0A, 0x20, 0xDB, 0x78, 0x89, 0xF8, ++0x0B, 0x30, 0x48, 0x46, 0xFA, 0xF7, 0xC4, 0xFA, 0xCC, 0xE6, 0x06, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0xDA, 0x07, 0x9B, 0xD4, ++0x07, 0x49, 0x09, 0x48, 0x40, 0xF2, 0xE5, 0x12, 0xFC, 0xF7, 0x6A, 0xFB, 0x94, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x0C, 0xB9, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xC4, 0xB8, 0x15, 0x00, ++0xE4, 0xB8, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0xB9, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x99, 0x07, 0x3F, 0xF5, 0x53, 0xAF, ++0xB7, 0x49, 0xB8, 0x48, 0x4F, 0xF4, 0xED, 0x72, 0xFC, 0xF7, 0x4C, 0xFB, 0x4B, 0xE7, 0x02, 0x2B, 0x08, 0xBF, 0x8B, 0xF8, ++0xDB, 0x90, 0x73, 0xE6, 0x82, 0x42, 0x28, 0xBF, 0x02, 0x46, 0x0A, 0xE7, 0x1F, 0xFA, 0x89, 0xF8, 0x41, 0x46, 0x10, 0x46, ++0xFB, 0xF7, 0x42, 0xFA, 0x00, 0x28, 0x3F, 0xF4, 0x1A, 0xAE, 0xB6, 0xF8, 0xC2, 0x31, 0x82, 0x78, 0x23, 0xF0, 0x07, 0x03, ++0x9B, 0xB2, 0xD1, 0x07, 0x48, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0xA6, 0xF8, 0xC2, 0x31, 0x53, 0x07, 0x7F, 0xF5, 0x0B, 0xAE, ++0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0xB3, 0xF8, 0xC2, 0x21, 0x42, 0xF0, 0x04, 0x02, 0xA3, 0xF8, ++0xC2, 0x21, 0x00, 0xE6, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0xFB, 0xF7, 0x89, 0xFB, 0x9A, 0x4B, 0x93, 0xF8, 0x76, 0xB1, ++0x1B, 0xF0, 0x06, 0x0B, 0x81, 0x46, 0x3F, 0xF4, 0x0B, 0xAE, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0xFB, 0xF7, 0x9C, 0xFB, ++0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x83, 0x46, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0x00, 0xF0, ++0xAA, 0x80, 0x8E, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x59, 0x07, 0x7F, 0xF5, 0xF5, 0xAD, 0x18, 0xEE, 0x90, 0x2A, 0x18, 0xEE, ++0x10, 0x0A, 0x41, 0x46, 0xFD, 0xF7, 0xD6, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x09, 0x81, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x02, 0xA3, 0xD3, 0xF8, 0xC8, 0x31, 0xC3, 0xF3, 0x09, 0x12, 0x15, 0x46, 0xA2, 0xB1, 0x04, 0x23, 0x05, 0x22, ++0x00, 0x21, 0x6F, 0x20, 0xFA, 0xF7, 0xFE, 0xF9, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xA2, 0x06, 0x92, ++0x92, 0xF8, 0x63, 0x10, 0x81, 0x70, 0x05, 0x80, 0xFA, 0xF7, 0x22, 0xFA, 0x06, 0x9A, 0xD2, 0xF8, 0xC8, 0x31, 0x05, 0x9A, ++0x03, 0xF0, 0x7F, 0x43, 0x93, 0x42, 0x3F, 0xF4, 0xC5, 0xAD, 0x04, 0x23, 0x05, 0x22, 0x00, 0x21, 0x71, 0x20, 0xFA, 0xF7, ++0xE3, 0xF9, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0xD3, 0xF8, 0xC8, 0x21, 0xC2, 0xF3, 0x05, 0x63, ++0x52, 0x00, 0x54, 0xBF, 0x43, 0xF4, 0x80, 0x73, 0x43, 0xF4, 0x40, 0x73, 0x03, 0x60, 0xFA, 0xF7, 0x01, 0xFA, 0xAB, 0xE5, ++0x02, 0x9B, 0x03, 0xF5, 0xD6, 0x72, 0x52, 0x44, 0x0D, 0xF1, 0x27, 0x03, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0x06, 0x92, ++0xFD, 0xF7, 0x92, 0xFE, 0x9D, 0xF8, 0x27, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x93, 0xAD, 0x06, 0x9A, 0x06, 0x97, 0x03, 0x9F, ++0x25, 0x46, 0x4C, 0x46, 0x91, 0x46, 0x08, 0x23, 0x05, 0x22, 0x00, 0x21, 0x1A, 0x20, 0xFA, 0xF7, 0xB3, 0xF9, 0x59, 0xF8, ++0x04, 0x1B, 0x80, 0xF8, 0x05, 0xB0, 0x94, 0xF8, 0x63, 0x20, 0x82, 0x71, 0x4F, 0xF0, 0x00, 0x02, 0x01, 0x60, 0x0B, 0xF1, ++0x01, 0x0B, 0x02, 0x71, 0xFA, 0xF7, 0xD4, 0xF9, 0xBB, 0xF1, 0x04, 0x0F, 0xE7, 0xD1, 0x03, 0x97, 0x2C, 0x46, 0x06, 0x9F, ++0x70, 0xE5, 0x00, 0x2A, 0x7F, 0xF4, 0xE5, 0xAE, 0x45, 0x22, 0x4C, 0x49, 0x4D, 0x48, 0xFC, 0xF7, 0x77, 0xFA, 0xD8, 0xF8, ++0x40, 0x20, 0xDC, 0xE6, 0x9B, 0xF8, 0x8C, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x96, 0xAD, 0x9D, 0xF8, 0x25, 0x30, 0x01, 0x2B, ++0x7F, 0xF4, 0x91, 0xAD, 0x46, 0x4B, 0x9B, 0xF8, 0x63, 0x00, 0xD3, 0xF8, 0xC0, 0x31, 0x98, 0x47, 0x9B, 0xF8, 0x8A, 0x10, ++0x00, 0x29, 0x3F, 0xF4, 0x86, 0xAD, 0x7A, 0xE5, 0x5A, 0x45, 0x28, 0xBF, 0x5A, 0x46, 0xD2, 0xB2, 0x21, 0xE6, 0x83, 0x46, ++0x69, 0xE6, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0x06, 0x93, 0xFB, 0xF7, 0x77, 0xF9, 0xB0, 0xB1, 0x06, 0x9B, 0x3A, 0x49, ++0x93, 0xF8, 0x6C, 0x20, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, 0x5B, 0x68, 0x13, 0xF0, 0x24, 0x0F, 0x0A, 0xD0, ++0x90, 0xF9, 0x02, 0x30, 0x81, 0x78, 0x00, 0x2B, 0x05, 0xDB, 0x10, 0x46, 0x0A, 0x09, 0x01, 0xF0, 0x03, 0x01, 0xFF, 0xF7, ++0xDD, 0xFB, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x06, 0x93, 0xD3, 0xF8, 0xCC, 0x31, 0x18, 0x07, ++0x7F, 0xF5, 0x2D, 0xAF, 0x02, 0x23, 0x05, 0x22, 0x00, 0x21, 0x6D, 0x20, 0xFA, 0xF7, 0x46, 0xF9, 0x41, 0x46, 0x02, 0x46, ++0x07, 0x90, 0x18, 0xEE, 0x10, 0x0A, 0xFD, 0xF7, 0x45, 0xFF, 0x07, 0x9A, 0x10, 0x46, 0xFA, 0xF7, 0x6B, 0xF9, 0x22, 0x4B, ++0x1B, 0x69, 0x00, 0x2B, 0x3F, 0xF4, 0x17, 0xAF, 0x02, 0x9B, 0x03, 0xF5, 0xA8, 0x72, 0x18, 0xEE, 0x10, 0x0A, 0x0D, 0xF1, ++0x27, 0x03, 0x52, 0x44, 0x41, 0x46, 0xFD, 0xF7, 0x05, 0xFF, 0x9D, 0xF8, 0x27, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x07, 0xAF, ++0x10, 0x23, 0x05, 0x22, 0x00, 0x21, 0x6B, 0x20, 0xFA, 0xF7, 0x20, 0xF9, 0x06, 0x9A, 0x11, 0x46, 0x15, 0x46, 0xD2, 0xF8, ++0x50, 0xE1, 0xD2, 0xF8, 0x54, 0x21, 0xD1, 0xF8, 0x58, 0x11, 0xD5, 0xF8, 0x5C, 0x51, 0xC5, 0x60, 0xC0, 0xE9, 0x00, 0xE2, ++0x81, 0x60, 0xFA, 0xF7, 0x3F, 0xF9, 0xEE, 0xE6, 0x03, 0x21, 0x28, 0xE6, 0x03, 0x22, 0x33, 0xE6, 0x02, 0x22, 0x31, 0xE6, ++0x02, 0x21, 0x22, 0xE6, 0x40, 0xF2, 0xFF, 0x33, 0x1D, 0x46, 0xFD, 0xE6, 0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xD4, 0xB8, 0x15, 0x00, 0xF4, 0xB8, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x70, 0xB5, 0x0C, 0x46, 0x84, 0xB0, 0x89, 0x78, 0x0C, 0x4D, 0x26, 0x79, 0x8D, 0xF8, 0x04, 0x10, 0xAD, 0xF8, 0x08, 0x20, ++0x01, 0x46, 0x9D, 0xF8, 0x20, 0x20, 0x20, 0x88, 0xE4, 0x78, 0xAD, 0xF8, 0x0A, 0x30, 0xAD, 0xF8, 0x06, 0x00, 0x6B, 0x6C, ++0x8D, 0xF8, 0x0C, 0x60, 0x8D, 0xF8, 0x0D, 0x40, 0x8D, 0xF8, 0x05, 0x20, 0x01, 0xA8, 0x98, 0x47, 0x04, 0xB0, 0x70, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x03, 0x68, 0x30, 0xB4, 0x0C, 0x68, 0x5A, 0x40, 0x84, 0xEA, 0xF2, 0x34, 0x22, 0x44, 0x13, 0x0A, ++0x15, 0x02, 0x05, 0xF0, 0xFF, 0x25, 0x03, 0xF0, 0xFF, 0x13, 0x2B, 0x43, 0x63, 0x40, 0x1A, 0x44, 0x83, 0xEA, 0x72, 0x73, ++0x1A, 0x44, 0x83, 0xEA, 0xB2, 0x03, 0x1A, 0x44, 0x0B, 0x60, 0x30, 0xBC, 0x02, 0x60, 0x70, 0x47, 0xF8, 0xB5, 0x1F, 0x88, ++0xD3, 0xF8, 0x02, 0x50, 0x0B, 0x68, 0x96, 0x88, 0x12, 0x68, 0x03, 0x60, 0x9D, 0xF8, 0x18, 0x40, 0x4B, 0x68, 0x43, 0x60, ++0x00, 0x23, 0xFF, 0x2C, 0x83, 0x60, 0x03, 0x73, 0x00, 0xF1, 0x04, 0x01, 0x46, 0xEA, 0x07, 0x46, 0x14, 0xBF, 0x04, 0xF0, ++0x07, 0x04, 0x00, 0x24, 0xFF, 0xF7, 0xCC, 0xFF, 0x32, 0x46, 0xFF, 0xF7, 0xC9, 0xFF, 0x2A, 0x46, 0xFF, 0xF7, 0xC6, 0xFF, ++0x22, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0xC1, 0xBF, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x21, 0xF0, 0x03, 0x06, ++0x01, 0xF0, 0x03, 0x01, 0xC1, 0xF1, 0x04, 0x03, 0x37, 0x68, 0x90, 0xF8, 0x0C, 0xC0, 0x85, 0x68, 0xDB, 0xB2, 0x04, 0x36, ++0xC9, 0x00, 0x9A, 0x42, 0x83, 0xB0, 0x27, 0xFA, 0x01, 0xF1, 0xB1, 0x46, 0x78, 0xD2, 0xC2, 0xF1, 0x04, 0x04, 0xE3, 0x00, ++0x4F, 0xF0, 0xFF, 0x34, 0x4F, 0xF0, 0x00, 0x0B, 0xDC, 0x40, 0x21, 0x40, 0xD8, 0x46, 0x5F, 0x46, 0x0C, 0xEB, 0x02, 0x04, ++0x03, 0x2C, 0x52, 0xD8, 0x4F, 0xEA, 0xCC, 0x0C, 0x01, 0xFA, 0x0C, 0xF1, 0x0D, 0x43, 0xB8, 0xF1, 0x00, 0x0F, 0x22, 0xD0, ++0xE3, 0x00, 0xC4, 0xF1, 0x04, 0x0A, 0x00, 0x93, 0x4F, 0xEA, 0x88, 0x03, 0x4F, 0xEA, 0xCA, 0x0A, 0x01, 0x1D, 0x01, 0x93, ++0x06, 0xEB, 0x88, 0x08, 0xB1, 0x46, 0xD9, 0xF8, 0x00, 0x30, 0x00, 0x9A, 0x03, 0xFA, 0x02, 0xF2, 0xBA, 0xF1, 0x20, 0x0F, ++0x42, 0xEA, 0x05, 0x02, 0x09, 0xF1, 0x04, 0x09, 0x14, 0xBF, 0x23, 0xFA, 0x0A, 0xF5, 0x00, 0x25, 0xFF, 0xF7, 0x76, 0xFF, ++0xC1, 0x45, 0xEC, 0xD1, 0x01, 0x9B, 0x33, 0x44, 0x99, 0x46, 0x5F, 0x45, 0x20, 0xD9, 0x07, 0xF0, 0x03, 0x07, 0xC7, 0xF1, ++0x04, 0x03, 0xDA, 0x00, 0x20, 0x2A, 0xD9, 0xF8, 0x00, 0x10, 0x40, 0xD0, 0x4F, 0xF0, 0xFF, 0x33, 0xD3, 0x40, 0x0B, 0x40, ++0xE2, 0x00, 0x03, 0xFA, 0x02, 0xF2, 0x15, 0x43, 0x27, 0x44, 0x03, 0x2F, 0x2F, 0xD9, 0xC4, 0xF1, 0x04, 0x04, 0xE4, 0x00, ++0x20, 0x2C, 0x14, 0xBF, 0xE3, 0x40, 0x00, 0x23, 0x2A, 0x46, 0x01, 0x1D, 0x3C, 0x1F, 0x1D, 0x46, 0xFF, 0xF7, 0x4E, 0xFF, ++0x85, 0x60, 0x04, 0x73, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xEA, 0xCC, 0x02, 0xCC, 0xF1, 0x04, 0x0C, 0x4F, 0xEA, ++0xCC, 0x0C, 0xBC, 0xF1, 0x20, 0x0F, 0x01, 0xFA, 0x02, 0xF2, 0x42, 0xEA, 0x05, 0x02, 0x18, 0xBF, 0x21, 0xFA, 0x0C, 0xF5, ++0x00, 0xF1, 0x04, 0x01, 0x08, 0xBF, 0x00, 0x25, 0x04, 0x3C, 0xFF, 0xF7, 0x33, 0xFF, 0x9A, 0xE7, 0xD7, 0x1A, 0x4F, 0xEA, ++0x97, 0x08, 0x1A, 0x46, 0x27, 0xF0, 0x03, 0x0B, 0x8A, 0xE7, 0x3C, 0x46, 0x85, 0x60, 0x04, 0x73, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0x23, 0xC4, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x10, 0x4B, 0x85, 0x68, 0x1B, 0x68, 0x02, 0x7B, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x0D, 0xDB, 0x5A, 0x23, 0xD2, 0x00, 0x03, 0xFA, 0x02, 0xF2, 0x2A, 0x43, 0x21, 0x1D, ++0x20, 0x46, 0xFF, 0xF7, 0x0F, 0xFF, 0xBD, 0xE8, 0x38, 0x40, 0x00, 0x22, 0xFF, 0xF7, 0x0A, 0xBF, 0x03, 0x2A, 0xEF, 0xD9, ++0x40, 0xF2, 0x41, 0x12, 0x03, 0x49, 0x04, 0x48, 0xFC, 0xF7, 0xB8, 0xF8, 0x22, 0x7B, 0xE7, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x20, 0xB9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x06, 0x20, 0x83, 0xB0, 0x00, 0x24, 0xCD, 0xE9, ++0x00, 0x44, 0x91, 0xF8, 0x3D, 0x90, 0x0D, 0x46, 0x17, 0x46, 0x1E, 0x46, 0xFA, 0xF7, 0x62, 0xFA, 0x09, 0x28, 0x79, 0xD0, ++0x01, 0x23, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF6, 0x01, 0x00, 0xF9, 0xF7, 0xB7, 0xFF, 0x80, 0x46, 0x06, 0x20, 0xFA, 0xF7, ++0x55, 0xFA, 0x48, 0xB1, 0x08, 0x26, 0x40, 0x46, 0x88, 0xF8, 0x00, 0x60, 0xF9, 0xF7, 0xDC, 0xFF, 0x20, 0x46, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, 0xAC, 0xA1, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0xA3, 0x93, 0xF8, 0x62, 0x20, ++0x00, 0x2A, 0x4F, 0xD1, 0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x4B, 0xD1, 0xDF, 0xF8, 0x94, 0xB1, 0x5A, 0x4A, 0x5B, 0x49, ++0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x95, 0xF8, 0x3B, 0x30, 0x01, 0x22, 0x02, 0x2B, 0xCA, 0x75, 0x0E, 0xD0, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0xA2, 0x92, 0xF8, 0x64, 0x10, 0x29, 0xB9, 0x53, 0x4C, 0x21, 0x68, 0xB1, 0xF9, ++0x00, 0x10, 0x00, 0x29, 0x7F, 0xDB, 0x03, 0x2B, 0x57, 0xD0, 0x3A, 0x46, 0x4F, 0xF4, 0x55, 0x73, 0x31, 0x46, 0x41, 0xF6, ++0x02, 0x00, 0xCB, 0xF8, 0x00, 0x50, 0xF9, 0xF7, 0x73, 0xFF, 0x95, 0xF8, 0x3B, 0x30, 0xCB, 0xF8, 0x04, 0x00, 0x00, 0x27, ++0x02, 0x2B, 0x8B, 0xF8, 0x16, 0x70, 0x4F, 0xD0, 0x9B, 0xF8, 0x1E, 0x60, 0x3E, 0xB3, 0x95, 0xF8, 0x3D, 0x10, 0x44, 0x48, ++0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x01, 0xA1, 0x06, 0x22, 0x38, 0x31, 0x0E, 0xF0, 0xE4, 0xFA, 0x09, 0x21, 0x06, 0x20, ++0xFA, 0xF7, 0x52, 0xF9, 0x95, 0xF8, 0x3D, 0x00, 0x39, 0x46, 0x04, 0xFB, 0x00, 0xA0, 0x01, 0xF0, 0xCB, 0xF8, 0x3E, 0x46, ++0x01, 0x24, 0x9C, 0xE7, 0x95, 0xF8, 0x3B, 0x30, 0x02, 0x2B, 0xAF, 0xD0, 0x2C, 0x6B, 0x14, 0xF0, 0x20, 0x04, 0x17, 0xD1, ++0x09, 0x26, 0x92, 0xE7, 0x02, 0x24, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0xA9, 0x68, 0x46, 0x00, 0xF0, ++0x75, 0xFD, 0xDD, 0xE9, 0x00, 0x01, 0x28, 0xB1, 0x21, 0xB1, 0x32, 0x46, 0x00, 0xF0, 0x14, 0xFE, 0x01, 0x24, 0x80, 0xE7, ++0x00, 0xF0, 0x90, 0xFD, 0x01, 0x24, 0x7C, 0xE7, 0xDF, 0xF8, 0xBC, 0xB0, 0x28, 0x48, 0x01, 0x23, 0x8B, 0xF8, 0x1E, 0x30, ++0xFB, 0xF7, 0x8E, 0xFD, 0x8C, 0xE7, 0xE9, 0x8E, 0x05, 0xF1, 0x40, 0x00, 0x02, 0xF0, 0x32, 0xF8, 0x00, 0x28, 0xC4, 0xBF, ++0x00, 0x23, 0x85, 0xF8, 0x3B, 0x30, 0x9C, 0xE7, 0x95, 0xF8, 0x3D, 0x10, 0x1F, 0x48, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, ++0x01, 0xA1, 0x06, 0x22, 0x38, 0x31, 0x01, 0x24, 0x8B, 0xF8, 0x16, 0x40, 0x0E, 0xF0, 0x94, 0xFA, 0x09, 0x21, 0x06, 0x20, ++0xFA, 0xF7, 0x02, 0xF9, 0x95, 0xF8, 0x3D, 0x00, 0x39, 0x46, 0x06, 0xFB, 0x00, 0xA0, 0x01, 0xF0, 0x7B, 0xF8, 0x3E, 0x46, ++0x4D, 0xE7, 0x92, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x09, 0xD0, 0x12, 0x49, 0x12, 0x48, 0x64, 0x22, 0xFB, 0xF7, 0xD8, 0xFF, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0B, 0xDA, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0xA9, 0xD9, 0xF8, ++0x40, 0x30, 0x23, 0xB1, 0x09, 0x49, 0x0B, 0x48, 0x65, 0x22, 0xFB, 0xF7, 0xC7, 0xFF, 0x95, 0xF8, 0x3B, 0x30, 0x62, 0xE7, ++0x94, 0x40, 0x04, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x84, 0xBA, 0x17, 0x00, 0x40, 0xB9, 0x15, 0x00, ++0x7C, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x4C, 0xB9, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x64, 0xBA, 0x17, 0x00, 0x38, 0xB5, 0x0B, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0F, 0x49, 0x1C, 0x78, 0xFB, 0xF7, 0x7C, 0xFD, ++0x06, 0x20, 0xFA, 0xF7, 0x63, 0xF9, 0xA8, 0xB9, 0x0C, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, ++0x62, 0x50, 0x15, 0xB9, 0x94, 0xF8, 0x64, 0x00, 0x00, 0xB9, 0x38, 0xBD, 0x09, 0x21, 0x06, 0x20, 0xFA, 0xF7, 0xAA, 0xF8, ++0x20, 0x46, 0x01, 0x21, 0x01, 0xF0, 0x26, 0xF8, 0x28, 0x46, 0x38, 0xBD, 0x02, 0x20, 0x38, 0xBD, 0x70, 0xB9, 0x15, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x08, 0xB5, 0x06, 0x20, 0xFA, 0xF7, 0x42, 0xF9, 0x05, 0x28, 0x04, 0xD0, 0x06, 0x20, 0xFA, 0xF7, ++0x3D, 0xF9, 0x06, 0x28, 0x04, 0xD1, 0x01, 0x20, 0x01, 0xF0, 0x9C, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xFA, 0xF7, ++0x33, 0xF9, 0x07, 0x28, 0xF5, 0xD0, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x16, 0x4B, 0x00, 0xB5, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x20, 0x00, 0x23, 0x83, 0xB0, 0x9A, 0x42, 0xCD, 0xE9, 0x00, 0x33, 0x15, 0xDB, 0x68, 0x46, 0x01, 0xA9, 0x00, 0xF0, ++0xB7, 0xFC, 0x00, 0x98, 0x40, 0xB1, 0x01, 0x99, 0x31, 0xB1, 0x00, 0x22, 0x00, 0xF0, 0x56, 0xFD, 0x00, 0x20, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0xFB, 0x01, 0x20, 0x01, 0xF0, 0x75, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x06, 0x20, ++0xFA, 0xF7, 0x0A, 0xF9, 0x01, 0x28, 0xE4, 0xD0, 0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x8F, 0x72, 0xFB, 0xF7, 0x42, 0xFF, ++0xDD, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x80, 0xB9, 0x15, 0x00, 0x93, 0x4B, 0x2D, 0xE9, ++0xF0, 0x4F, 0x1B, 0x68, 0x92, 0x4D, 0xB3, 0xF9, 0x00, 0x30, 0x2F, 0x68, 0x00, 0x2B, 0x89, 0xB0, 0xC0, 0xF2, 0x91, 0x80, ++0x97, 0xF8, 0x3D, 0x80, 0x8E, 0x4E, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x08, 0x64, 0xD4, 0xF8, 0xCC, 0x31, 0x00, 0x2B, ++0x18, 0xDB, 0x6B, 0x7D, 0x33, 0xB9, 0x01, 0x20, 0x01, 0xF0, 0x42, 0xF9, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x00, 0x23, 0x07, 0xA9, 0x06, 0xA8, 0xCD, 0xE9, 0x06, 0x33, 0x00, 0xF0, 0x6B, 0xFC, 0xDD, 0xE9, 0x06, 0x01, 0x01, 0x22, ++0x00, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x07, 0xA8, 0x00, 0xF0, 0xE1, 0xFD, 0x00, 0x28, ++0x74, 0xD1, 0x01, 0x46, 0x20, 0x23, 0x06, 0x22, 0x0A, 0x20, 0xF9, 0xF7, 0x1D, 0xFE, 0x94, 0xF8, 0xC0, 0x34, 0x05, 0x46, ++0x2B, 0xB1, 0xD4, 0xF8, 0xCC, 0x21, 0x22, 0xF0, 0x08, 0x02, 0xC4, 0xF8, 0xCC, 0x21, 0x74, 0x4A, 0x92, 0xF8, 0x04, 0x21, ++0x4A, 0xB1, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x08, 0xF2, 0xB1, 0x18, 0xD1, 0xF8, 0x90, 0x01, 0x80, 0x78, 0x01, 0x28, ++0x6D, 0xD0, 0x6E, 0x4B, 0x97, 0xF8, 0x3D, 0x00, 0xDB, 0x6C, 0x9D, 0xF8, 0x1C, 0x10, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x6B, ++0x00, 0x23, 0x2B, 0x60, 0x0B, 0xFB, 0x08, 0xFB, 0x97, 0xF8, 0x3D, 0x20, 0x6A, 0x76, 0x06, 0xEB, 0x0B, 0x0A, 0xDA, 0xF8, ++0x64, 0x01, 0xBA, 0xF8, 0x68, 0x21, 0xAB, 0x76, 0x9A, 0xF8, 0x8B, 0x31, 0x6B, 0x77, 0x9A, 0xF8, 0x8C, 0x31, 0xAB, 0x77, ++0xDA, 0xF8, 0xCC, 0x31, 0xC5, 0xF8, 0x12, 0x00, 0x13, 0xF0, 0x02, 0x04, 0xEA, 0x82, 0x1B, 0xD0, 0x0B, 0xF1, 0xEC, 0x09, ++0x13, 0xF0, 0x04, 0x04, 0xB1, 0x44, 0x6E, 0xD1, 0x21, 0x46, 0x13, 0xF0, 0x08, 0x02, 0x05, 0xF1, 0x18, 0x03, 0x18, 0xBF, ++0x0B, 0xF5, 0x8C, 0x72, 0x05, 0xF1, 0x04, 0x0C, 0x02, 0x93, 0x05, 0xF1, 0x08, 0x03, 0xCD, 0xE9, 0x00, 0x3C, 0x18, 0xBF, ++0x92, 0x19, 0x48, 0x46, 0x05, 0xF1, 0x10, 0x03, 0xFE, 0xF7, 0x22, 0xFC, 0x28, 0x46, 0xEC, 0x60, 0xF9, 0xF7, 0xF0, 0xFD, ++0x03, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0xB6, 0xFF, 0x0F, 0xE0, 0x06, 0x20, 0xFA, 0xF7, 0x5A, 0xF8, 0x02, 0x28, 0x3F, 0xF4, ++0x69, 0xAF, 0x47, 0x49, 0x47, 0x48, 0x4F, 0xF4, 0xA3, 0x72, 0xFB, 0xF7, 0x91, 0xFE, 0x61, 0xE7, 0x01, 0x20, 0x01, 0xF0, ++0xB1, 0xF8, 0x3A, 0x6B, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x66, 0x53, 0x07, 0xC6, 0xF8, 0xB0, 0x24, 0x7F, 0xF5, ++0x65, 0xAF, 0xD6, 0xF8, 0xCC, 0x31, 0x00, 0x20, 0x23, 0xF0, 0x0E, 0x03, 0xC6, 0xF8, 0xCC, 0x31, 0x09, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0xD1, 0xF8, 0xCC, 0x11, 0x11, 0xF0, 0x0C, 0x0F, 0x8C, 0xD0, 0x00, 0x2B, 0x8A, 0xD1, 0xDF, 0xF8, 0xD8, 0x90, ++0x02, 0xF5, 0xB2, 0x72, 0xB4, 0x18, 0x9A, 0x46, 0xCB, 0x46, 0x58, 0x46, 0x06, 0x22, 0x21, 0x46, 0x0E, 0xF0, 0xDC, 0xF8, ++0x0B, 0xF1, 0x14, 0x0B, 0x18, 0xB3, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x05, 0x0F, 0xF2, 0xD1, 0x2C, 0x49, 0x50, 0x22, ++0x01, 0xF1, 0x14, 0x00, 0x0E, 0xF0, 0xFE, 0xF8, 0x29, 0x48, 0x21, 0x46, 0x06, 0x22, 0x0E, 0xF0, 0xF9, 0xF8, 0x01, 0x23, ++0xA9, 0xF8, 0x06, 0x30, 0x89, 0xF8, 0x08, 0x30, 0x65, 0xE7, 0x0B, 0xF5, 0xB2, 0x70, 0x0B, 0xF5, 0x86, 0x71, 0x31, 0x44, ++0x30, 0x44, 0x05, 0x91, 0xFA, 0xF7, 0x28, 0xFF, 0xDA, 0xF8, 0xCC, 0x31, 0x05, 0x99, 0x04, 0x46, 0x83, 0xE7, 0x0A, 0xEB, ++0x8A, 0x03, 0x09, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0x8A, 0x0B, 0x9A, 0x79, 0x14, 0x23, 0x03, 0xFB, 0x0A, 0x93, 0x4A, 0xB1, ++0xDB, 0x79, 0x53, 0xB1, 0x0B, 0xEB, 0x0A, 0x03, 0x09, 0xEB, 0x83, 0x09, 0x01, 0x23, 0x89, 0xF8, 0x08, 0x30, 0x42, 0xE7, ++0x01, 0x22, 0x9A, 0x71, 0xF4, 0xE7, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x08, 0x64, 0x00, 0x92, 0xB4, 0xF8, 0x68, 0x31, ++0xB4, 0xF8, 0x66, 0x21, 0xB4, 0xF8, 0x64, 0x11, 0x0C, 0x48, 0xFB, 0xF7, 0x9F, 0xFB, 0xD4, 0xF8, 0xCC, 0x31, 0x23, 0xF0, ++0x0C, 0x03, 0xC4, 0xF8, 0xCC, 0x31, 0xDF, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x2C, 0x19, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xB9, 0x15, 0x00, 0xCC, 0x35, 0x17, 0x00, ++0xCC, 0xB9, 0x15, 0x00, 0x08, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x06, 0x20, ++0xF9, 0xF7, 0xB6, 0xFF, 0x04, 0x28, 0x06, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0xB1, 0xFF, 0x09, 0x28, 0x01, 0xD0, 0x00, 0x20, ++0x08, 0xBD, 0x00, 0xF0, 0xF5, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0xA6, 0xFF, 0x04, 0x28, 0xEA, 0xD0, ++0x06, 0x20, 0xF9, 0xF7, 0xA1, 0xFF, 0x00, 0x28, 0xE5, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0x9C, 0xFF, 0x09, 0x28, 0xE0, 0xD0, ++0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x16, 0x72, 0xFB, 0xF7, 0xD4, 0xFD, 0xD9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xE4, 0xB9, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x03, 0xDB, 0x00, 0xF0, 0xCD, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x7E, 0xFF, 0x04, 0x28, 0xF6, 0xD0, ++0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x79, 0x22, 0xFB, 0xF7, 0xB6, 0xFD, 0x00, 0xF0, 0xBE, 0xFC, 0x00, 0x20, 0x08, 0xBD, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x6C, 0xBA, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0xAD, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x5E, 0xFF, ++0x09, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x29, 0x32, 0xFB, 0xF7, 0x96, 0xFD, 0x00, 0xF0, 0x9E, 0xFC, ++0x00, 0x20, 0x08, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x9C, 0xBA, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0x8D, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, ++0xF9, 0xF7, 0x3E, 0xFF, 0x09, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x43, 0x32, 0xFB, 0xF7, 0x76, 0xFD, ++0x00, 0xF0, 0x7E, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x9C, 0xBA, 0x15, 0x00, ++0x37, 0x4B, 0x30, 0xB5, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x83, 0xB0, 0x37, 0xDB, 0x06, 0x20, 0xF9, 0xF7, ++0x21, 0xFF, 0x09, 0x28, 0x10, 0xD0, 0x32, 0x4B, 0x9A, 0x7D, 0x01, 0x2A, 0x50, 0xD0, 0x1B, 0x68, 0x93, 0xF8, 0x3B, 0x30, ++0x02, 0x2B, 0x3A, 0xD9, 0x03, 0x2B, 0x3F, 0xD1, 0x2D, 0x48, 0x01, 0xF0, 0xF5, 0xFC, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, ++0x29, 0x4C, 0xA2, 0x6A, 0x23, 0x7D, 0x00, 0x25, 0xC2, 0xF8, 0xCC, 0x51, 0x00, 0x2B, 0x40, 0xD1, 0xA0, 0x68, 0x0C, 0x30, ++0xF9, 0xF7, 0x90, 0xFC, 0xA3, 0x7D, 0x00, 0x22, 0x01, 0x2B, 0xA2, 0x60, 0x01, 0xD0, 0xA1, 0x7F, 0x61, 0xB3, 0x00, 0x24, ++0x01, 0xA9, 0x68, 0x46, 0xCD, 0xE9, 0x00, 0x44, 0x00, 0xF0, 0x8C, 0xFA, 0xDD, 0xE9, 0x00, 0x01, 0x22, 0x46, 0x00, 0xF0, ++0x2D, 0xFB, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0xE9, 0xFE, 0x04, 0x28, 0xC2, 0xD0, 0x06, 0x20, ++0xF9, 0xF7, 0xE4, 0xFE, 0x09, 0x28, 0xBD, 0xD0, 0x15, 0x49, 0x16, 0x48, 0x40, 0xF2, 0x93, 0x22, 0xFB, 0xF7, 0x1C, 0xFD, ++0xB6, 0xE7, 0x00, 0x21, 0x01, 0x20, 0x01, 0xF0, 0x2B, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x01, 0x20, 0x00, 0xF0, ++0x35, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x23, 0xFE, 0xDA, 0xE7, 0x01, 0xF0, 0x48, 0xF9, ++0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x04, 0x00, 0xF9, 0xF7, 0x85, 0xFC, 0x25, 0x75, ++0xB6, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x08, 0xAC, 0x0F, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0xBA, 0x15, 0x00, 0x4B, 0x88, 0x03, 0xF0, 0xFC, 0x03, 0xB0, 0x2B, 0x10, 0xB5, 0x0C, 0x46, 0x13, 0xD0, 0x10, 0x2B, ++0x0A, 0xD0, 0x30, 0x2B, 0x08, 0xD0, 0xC0, 0x2B, 0x01, 0xD0, 0xA0, 0x2B, 0x14, 0xD1, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, ++0x01, 0xF0, 0x78, 0xBB, 0x06, 0x20, 0xF9, 0xF7, 0x9B, 0xFE, 0x07, 0x28, 0x13, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x06, 0x20, ++0xF9, 0xF7, 0x94, 0xFE, 0x05, 0x28, 0xF8, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0x37, 0xFA, 0xF4, 0xE7, 0xD0, 0x2B, 0xF2, 0xD1, ++0x23, 0x7B, 0x08, 0x2B, 0xEF, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0xD4, 0xFB, 0xEB, 0xE7, 0x20, 0x46, 0x01, 0xF0, 0x70, 0xFA, ++0xE7, 0xE7, 0x00, 0xBF, 0x10, 0xB5, 0x06, 0x20, 0x0C, 0x46, 0xF9, 0xF7, 0x7B, 0xFE, 0x06, 0x28, 0x01, 0xD0, 0x00, 0x20, ++0x10, 0xBD, 0x60, 0x88, 0x01, 0xF0, 0xC8, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4C, 0x0D, 0x4A, 0x23, 0x68, 0xD2, 0x7D, 0x01, 0x33, ++0x01, 0x2A, 0x23, 0x60, 0x0C, 0xD0, 0x33, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x07, 0x48, 0xFB, 0xF7, 0x1C, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0x00, 0xF0, 0x16, 0xFB, 0x23, 0x68, 0xEE, 0xE7, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x28, 0xBB, 0x15, 0x00, 0x38, 0xB5, 0x06, 0x20, ++0x0D, 0x46, 0xF9, 0xF7, 0x43, 0xFE, 0x30, 0xB9, 0x04, 0x46, 0x29, 0x88, 0xA8, 0x78, 0x00, 0xF0, 0xB7, 0xFD, 0x20, 0x46, ++0x38, 0xBD, 0x02, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x8B, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x89, 0xB0, 0x0C, 0x46, 0xC0, 0xF2, 0xFD, 0x80, 0x25, 0x78, 0x00, 0x2D, 0x40, 0xF0, 0xF2, 0x80, 0x63, 0x78, ++0x00, 0x93, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x03, 0xF4, 0x82, 0x4B, 0xDF, 0xF8, 0x18, 0xA2, 0x1F, 0x19, 0x4F, 0xF4, ++0xA4, 0x6C, 0x97, 0xF8, 0x22, 0xE0, 0x0C, 0xFB, 0x0E, 0xAC, 0x0C, 0xF5, 0xCE, 0x73, 0x0F, 0xCB, 0x07, 0xF1, 0xB8, 0x06, ++0x07, 0xC6, 0xDC, 0xF8, 0xCC, 0x81, 0x33, 0x70, 0x18, 0xF0, 0x01, 0x0F, 0x03, 0xD0, 0x7B, 0x68, 0x43, 0xF0, 0x01, 0x03, ++0x7B, 0x60, 0x18, 0xF0, 0x02, 0x0F, 0x58, 0xD0, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x0E, 0xA3, 0x03, 0xF1, 0xEC, 0x0B, ++0x00, 0x9E, 0x01, 0x93, 0xBB, 0xE8, 0x0F, 0x00, 0xB4, 0x46, 0x6E, 0x4E, 0x4F, 0xF4, 0x1E, 0x79, 0x09, 0xFB, 0x0C, 0x69, ++0x09, 0xF1, 0xC8, 0x0C, 0xAC, 0xE8, 0x0F, 0x00, 0x9B, 0xE8, 0x0F, 0x00, 0xD9, 0xF8, 0x04, 0xB0, 0x18, 0xF0, 0x08, 0x0F, ++0x4B, 0xF0, 0x02, 0x06, 0x8C, 0xE8, 0x0F, 0x00, 0xC9, 0xF8, 0x04, 0x60, 0x15, 0xD0, 0x01, 0x9B, 0x03, 0xF5, 0x8C, 0x76, ++0x0F, 0xCE, 0x09, 0xF1, 0xF4, 0x0C, 0xAC, 0xE8, 0x0F, 0x00, 0x0F, 0xCE, 0xAC, 0xE8, 0x0F, 0x00, 0x0F, 0xCE, 0xAC, 0xE8, ++0x0F, 0x00, 0x96, 0xE8, 0x03, 0x00, 0x8C, 0xE8, 0x03, 0x00, 0x4B, 0xF0, 0x22, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0x18, 0xF0, ++0x04, 0x0F, 0x16, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x00, 0x9E, 0x03, 0xFB, 0x0E, 0xA3, 0x03, 0xF5, 0x86, 0x73, 0x93, 0xE8, ++0x07, 0x00, 0xB4, 0x46, 0x51, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x0C, 0x63, 0x03, 0xF1, 0xE8, 0x06, 0x86, 0xE8, ++0x07, 0x00, 0x5A, 0x68, 0x42, 0xF0, 0x04, 0x02, 0x5A, 0x60, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x0E, 0xA1, 0xEC, 0x31, ++0x38, 0x46, 0xFE, 0xF7, 0x81, 0xF8, 0x48, 0x4B, 0xD3, 0xF8, 0x14, 0x33, 0x98, 0x47, 0x47, 0x4B, 0x1B, 0x78, 0x00, 0x2B, ++0x66, 0xD0, 0x00, 0x9A, 0x42, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, 0x93, 0xF8, 0xB8, 0x20, 0x00, 0x23, ++0xCD, 0xE9, 0x02, 0x33, 0xCD, 0xE9, 0x05, 0x33, 0x04, 0x93, 0x07, 0x93, 0x00, 0x2A, 0x70, 0xD0, 0x01, 0x3A, 0xD2, 0xB2, ++0xB8, 0x34, 0x02, 0xAE, 0x0D, 0xF1, 0x14, 0x0C, 0x9B, 0x46, 0x0D, 0xF1, 0x09, 0x03, 0x01, 0x92, 0x0C, 0x44, 0x03, 0xEB, ++0x02, 0x09, 0x31, 0x46, 0x62, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0x40, 0xF2, 0x05, 0x2A, 0x07, 0xE0, 0x01, 0xF8, 0x01, 0x0B, ++0x49, 0x45, 0x82, 0xF8, 0x00, 0x80, 0x02, 0xF1, 0x01, 0x02, 0x14, 0xD0, 0x14, 0xF8, 0x01, 0x0F, 0x00, 0xF0, 0x7F, 0x03, ++0x02, 0x3B, 0xDB, 0xB2, 0x09, 0x2B, 0x08, 0xFA, 0x03, 0xFE, 0xED, 0xD8, 0x1E, 0xEA, 0x0A, 0x0F, 0xEA, 0xD0, 0x01, 0xF8, ++0x01, 0x0B, 0x49, 0x45, 0x82, 0xF8, 0x00, 0xB0, 0x02, 0xF1, 0x01, 0x02, 0xEA, 0xD1, 0x01, 0x9A, 0x0C, 0xF1, 0x01, 0x03, ++0x1A, 0x44, 0x11, 0x46, 0x00, 0x9A, 0x10, 0x46, 0x1E, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x24, 0x00, 0xE0, ++0x01, 0x33, 0x9C, 0xF8, 0x00, 0x20, 0x9C, 0x46, 0x2A, 0xB1, 0x62, 0x19, 0x30, 0x78, 0x82, 0xF8, 0xB9, 0x00, 0x01, 0x35, ++0xED, 0xB2, 0x8B, 0x42, 0x06, 0xF1, 0x01, 0x06, 0xF0, 0xD1, 0x00, 0x9A, 0x11, 0x46, 0x13, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x01, 0x23, 0x83, 0xF8, 0xB8, 0x50, 0x38, 0x46, 0xFE, 0xF7, 0x1D, 0xFA, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x01, 0x20, 0x00, 0xF0, 0x98, 0xFD, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x20, 0xF9, 0xF7, ++0x2D, 0xFD, 0x03, 0x28, 0x3F, 0xF4, 0xFD, 0xAE, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF2, 0xF1, 0x12, 0xFB, 0xF7, 0x64, 0xFB, ++0xF5, 0xE6, 0x15, 0x46, 0xD9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xB8, 0x34, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0xBB, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0xB5, 0x06, 0x20, ++0xF9, 0xF7, 0x0E, 0xFD, 0x08, 0x28, 0x06, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0x09, 0xFD, 0x09, 0x28, 0x33, 0xD0, 0x00, 0x20, ++0x70, 0xBD, 0x22, 0x4A, 0x22, 0x4B, 0x14, 0x68, 0x94, 0xF8, 0x3D, 0x60, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x06, 0x36, ++0x06, 0x23, 0x1A, 0x46, 0x00, 0x21, 0x4B, 0x20, 0x96, 0xF8, 0x6C, 0x50, 0xF9, 0xF7, 0x52, 0xFA, 0x94, 0xF8, 0x3A, 0x20, ++0x02, 0x71, 0x22, 0x8F, 0x42, 0x80, 0x94, 0xF8, 0x3D, 0x20, 0x02, 0x70, 0xF9, 0xF7, 0x78, 0xFA, 0xD6, 0xF8, 0xB0, 0x34, ++0x15, 0x4A, 0xA1, 0x8E, 0x4F, 0xF4, 0x1E, 0x70, 0x03, 0xF0, 0x01, 0x03, 0x00, 0xFB, 0x05, 0x22, 0xC3, 0xF1, 0x02, 0x03, ++0x49, 0xBA, 0x02, 0x2B, 0x82, 0xF8, 0x30, 0x30, 0x91, 0x86, 0x08, 0xD0, 0x00, 0x20, 0x00, 0xF0, 0x39, 0xFD, 0x00, 0x20, ++0x70, 0xBD, 0x00, 0xF0, 0x1B, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF9, 0xF7, ++0x27, 0xFA, 0x00, 0x22, 0x02, 0x70, 0x94, 0xF8, 0x3D, 0x20, 0x42, 0x70, 0xF9, 0xF7, 0x50, 0xFA, 0xE8, 0xE7, 0x00, 0xBF, ++0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0xB5, 0x06, 0x46, 0x06, 0x20, 0x0D, 0x46, ++0xF9, 0xF7, 0xB4, 0xFC, 0x2B, 0x46, 0x02, 0x46, 0x0A, 0x49, 0x04, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFB, 0xF7, 0xC2, 0xF8, ++0x08, 0x4B, 0x1D, 0x42, 0x04, 0xD0, 0x24, 0xF0, 0x02, 0x01, 0x89, 0xB2, 0x05, 0x29, 0x00, 0xD0, 0x70, 0xBD, 0x30, 0x46, ++0xE6, 0xF7, 0xDC, 0xFC, 0x01, 0x23, 0x86, 0xF8, 0x5E, 0x30, 0x70, 0xBD, 0x70, 0xBB, 0x15, 0x00, 0x00, 0x00, 0x03, 0x40, ++0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x08, 0x40, 0x09, 0x48, ++0xF9, 0xF7, 0x74, 0xBE, 0x08, 0x4B, 0xDB, 0x68, 0x00, 0x2B, 0xF6, 0xD0, 0x07, 0x48, 0x08, 0x49, 0x70, 0x22, 0xFB, 0xF7, ++0xC3, 0xFA, 0xBD, 0xE8, 0x08, 0x40, 0x02, 0x48, 0xF9, 0xF7, 0x66, 0xBE, 0x38, 0x36, 0x17, 0x00, 0x70, 0xBA, 0x17, 0x00, ++0x64, 0xBA, 0x17, 0x00, 0x80, 0xBB, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x03, 0x4A, 0x04, 0x4B, 0x00, 0x21, 0x06, 0x20, ++0xD1, 0x75, 0x19, 0x60, 0xF9, 0xF7, 0xC4, 0xBB, 0x4C, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x70, 0xB5, 0x11, 0x4B, ++0x1E, 0x68, 0x00, 0x23, 0x03, 0x60, 0x0B, 0x60, 0x96, 0xF8, 0x22, 0x30, 0xDB, 0x07, 0x05, 0x46, 0x0C, 0x46, 0x08, 0xD5, ++0x30, 0x46, 0x03, 0xF0, 0x57, 0xFB, 0x58, 0xB1, 0x83, 0x1C, 0x2B, 0x60, 0xC3, 0x6A, 0x23, 0x60, 0x70, 0xBD, 0x06, 0xF1, ++0x22, 0x00, 0x28, 0x60, 0x03, 0xF0, 0x46, 0xFB, 0x00, 0x28, 0xF5, 0xD1, 0x32, 0x8D, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, ++0x1C, 0xBF, 0x28, 0x36, 0x26, 0x60, 0x70, 0xBD, 0x64, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x3B, 0x4C, 0x4F, 0xF4, ++0xBA, 0x73, 0x06, 0x22, 0x84, 0xB0, 0x80, 0x46, 0x0F, 0x46, 0x4F, 0xF4, 0x80, 0x50, 0x04, 0x21, 0x25, 0x68, 0xF9, 0xF7, ++0x91, 0xF9, 0x95, 0xF8, 0x3D, 0x30, 0x80, 0xF8, 0x6E, 0x31, 0x04, 0x46, 0x0F, 0xCD, 0x4F, 0xF0, 0x00, 0x0C, 0x04, 0xF1, ++0xFC, 0x06, 0xC4, 0xF8, 0x68, 0xC1, 0xA4, 0xF8, 0x6C, 0xC1, 0x0F, 0xC6, 0x0F, 0xCD, 0x0F, 0xC6, 0x01, 0x23, 0x2A, 0x68, ++0x32, 0x70, 0x84, 0xF8, 0x70, 0x31, 0xB8, 0xF1, 0x00, 0x0F, 0x19, 0xD0, 0xD8, 0xF8, 0x00, 0x00, 0xC4, 0xF8, 0x60, 0x01, ++0xB8, 0xF8, 0x04, 0x30, 0xA4, 0xF8, 0x64, 0x31, 0xCF, 0xB1, 0x38, 0x68, 0x20, 0x60, 0xBB, 0x88, 0xA3, 0x80, 0x01, 0x23, ++0x84, 0xF8, 0x6F, 0x31, 0x20, 0x46, 0xF9, 0xF7, 0x95, 0xF9, 0x01, 0x21, 0x06, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x41, ++0xF9, 0xF7, 0x58, 0xBB, 0x1C, 0x4B, 0x18, 0x68, 0x9B, 0x88, 0xC4, 0xF8, 0x60, 0x01, 0xA4, 0xF8, 0x64, 0x31, 0x00, 0x2F, ++0xE5, 0xD1, 0x19, 0x4B, 0x02, 0x93, 0x93, 0xF8, 0xFD, 0x50, 0x93, 0xF8, 0xFC, 0x00, 0x8D, 0xF8, 0x05, 0x50, 0x03, 0xF1, ++0x54, 0x02, 0x03, 0x92, 0x84, 0xF8, 0x6F, 0x71, 0x0D, 0xF1, 0x08, 0x0C, 0x06, 0x26, 0xB8, 0xB1, 0x5C, 0xF8, 0x27, 0x30, ++0x16, 0xFB, 0x00, 0x30, 0xDA, 0x78, 0x92, 0x07, 0x0D, 0xD4, 0x94, 0xF8, 0x6F, 0x21, 0x51, 0x1C, 0x84, 0xF8, 0x6F, 0x11, ++0x02, 0xEB, 0x42, 0x02, 0x19, 0x68, 0x44, 0xF8, 0x12, 0x10, 0x04, 0xEB, 0x42, 0x02, 0x99, 0x88, 0x91, 0x80, 0x06, 0x33, ++0x83, 0x42, 0xEB, 0xD1, 0x00, 0x2F, 0xC1, 0xD1, 0x28, 0x46, 0x01, 0x27, 0xE1, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, ++0xAC, 0xB2, 0x15, 0x00, 0x5A, 0xB9, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x8B, 0x78, 0x0D, 0x46, 0x80, 0x46, 0x17, 0x46, ++0x1B, 0xB9, 0x37, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x49, 0xDB, 0x36, 0x4C, 0xDF, 0xF8, 0xEC, 0xA0, 0x4F, 0xF0, 0x00, 0x09, ++0x4F, 0xF4, 0xBA, 0x73, 0x06, 0x22, 0x04, 0x21, 0x41, 0xF2, 0x02, 0x00, 0xDA, 0xF8, 0x00, 0xB0, 0x84, 0xF8, 0x17, 0x90, ++0xF9, 0xF7, 0x04, 0xF9, 0x04, 0x46, 0x28, 0x68, 0x20, 0x60, 0x4F, 0xF0, 0x01, 0x0C, 0xB5, 0xF8, 0x04, 0xE0, 0x84, 0xF8, ++0x6F, 0xC1, 0x5E, 0x46, 0x0F, 0xCE, 0x04, 0xF1, 0xFC, 0x05, 0xA4, 0xF8, 0x04, 0xE0, 0x0F, 0xC5, 0x0F, 0xCE, 0x0F, 0xC5, ++0x33, 0x68, 0x2B, 0x70, 0x84, 0xF8, 0x70, 0xC1, 0xA4, 0xF8, 0x6C, 0x91, 0xC4, 0xF8, 0x68, 0x91, 0x9B, 0xF8, 0x3D, 0x30, ++0x84, 0xF8, 0x6E, 0x31, 0xD8, 0xF8, 0x00, 0x00, 0xC4, 0xF8, 0x60, 0x01, 0xB8, 0xF8, 0x04, 0x30, 0xA4, 0xF8, 0x64, 0x31, ++0x1F, 0xB1, 0xE3, 0x78, 0x43, 0xEA, 0x0C, 0x03, 0xE3, 0x70, 0xB7, 0xFA, 0x87, 0xF2, 0x20, 0x46, 0x52, 0x09, 0x8A, 0xF8, ++0x15, 0x20, 0xF9, 0xF7, 0x01, 0xF9, 0xBD, 0xE8, 0xF8, 0x4F, 0x02, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0xC5, 0xBA, 0x12, 0x4B, ++0x10, 0x4C, 0xD3, 0xF8, 0x24, 0x31, 0x5B, 0x06, 0xB0, 0xD5, 0xE3, 0x7D, 0x01, 0x2B, 0xAD, 0xD1, 0x0E, 0x4A, 0x63, 0x70, ++0x13, 0x68, 0x0E, 0x49, 0x0E, 0x48, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x08, 0x60, 0x0D, 0x4A, 0xC4, 0xF8, 0x0C, 0x80, ++0x06, 0x21, 0x41, 0xF6, 0x09, 0x00, 0x25, 0x61, 0xA7, 0x75, 0xF8, 0xF7, 0x0D, 0xFF, 0xBD, 0xE8, 0xF8, 0x4F, 0xDC, 0xF7, ++0xF9, 0xB8, 0x00, 0xBF, 0x48, 0x30, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x00, 0x00, 0x50, 0x40, 0x34, 0x04, 0x32, 0x40, ++0x20, 0x04, 0x32, 0x40, 0x40, 0x1F, 0xDC, 0x05, 0xA0, 0x86, 0x01, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x27, 0x4D, 0xDF, 0xF8, 0xA0, 0x80, 0xAF, 0x7D, 0xD8, 0xF8, 0x00, 0x90, 0x4F, 0xF4, 0xBA, 0x73, 0x06, 0x22, 0x04, 0x21, ++0x41, 0xF2, 0x02, 0x00, 0xF9, 0xF7, 0x8A, 0xF8, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, 0x09, 0x00, 0xF8, 0xF7, 0x92, 0xFF, ++0xD5, 0xE9, 0x03, 0x23, 0x4F, 0xF0, 0x00, 0x0C, 0x85, 0xF8, 0x17, 0xC0, 0x10, 0x68, 0xC4, 0xF8, 0x60, 0x01, 0x18, 0x68, ++0x95, 0x88, 0x20, 0x60, 0x4F, 0xF0, 0x01, 0x0E, 0xB3, 0xF8, 0x04, 0xA0, 0x84, 0xF8, 0x6F, 0xE1, 0x4E, 0x46, 0x0F, 0xCE, ++0xA4, 0xF8, 0x64, 0x51, 0x04, 0xF1, 0xFC, 0x05, 0xA4, 0xF8, 0x04, 0xA0, 0x0F, 0xC5, 0x0F, 0xCE, 0x0F, 0xC5, 0x33, 0x68, ++0x2B, 0x70, 0x84, 0xF8, 0x70, 0xE1, 0xA4, 0xF8, 0x6C, 0xC1, 0xC4, 0xF8, 0x68, 0xC1, 0x99, 0xF8, 0x3D, 0x30, 0x84, 0xF8, ++0x6E, 0x31, 0x1F, 0xB1, 0xE3, 0x78, 0x43, 0xEA, 0x0E, 0x03, 0xE3, 0x70, 0xB7, 0xFA, 0x87, 0xF3, 0x20, 0x46, 0x5B, 0x09, ++0x88, 0xF8, 0x15, 0x30, 0xF9, 0xF7, 0x7E, 0xF8, 0xBD, 0xE8, 0xF0, 0x47, 0x02, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0x42, 0xBA, ++0x4C, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x30, 0xB5, 0x14, 0x4A, 0x14, 0x4B, 0x11, 0x68, 0x14, 0x4A, 0x91, 0xF8, ++0x3D, 0x10, 0x54, 0x6C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0xF2, 0x99, 0x18, 0x85, 0xB0, 0xD1, 0xF8, 0x90, 0x31, ++0x91, 0xF8, 0xC5, 0x51, 0x8D, 0xF8, 0x05, 0x50, 0x0A, 0x46, 0x99, 0x78, 0xD2, 0xF8, 0x94, 0x21, 0x8D, 0xF8, 0x04, 0x10, ++0x19, 0x88, 0x02, 0x92, 0x1A, 0x79, 0xAD, 0xF8, 0x06, 0x10, 0x8D, 0xF8, 0x0C, 0x20, 0xDB, 0x78, 0x8D, 0xF8, 0x0D, 0x30, ++0x01, 0x46, 0x01, 0xA8, 0xA0, 0x47, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x48, 0xF9, 0xF7, 0xE2, 0xFC, 0x0B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0x46, 0x05, 0xDB, 0x04, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0xF9, 0xF7, 0x33, 0xB8, 0x00, 0x28, ++0xF7, 0xD1, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x0D, 0x22, 0xFB, 0xF7, 0xDD, 0xF8, 0xF0, 0xE7, 0x70, 0xBA, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x02, 0x23, 0x04, 0x46, ++0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF8, 0xF7, 0xE8, 0xFF, 0x06, 0x22, 0x02, 0x23, 0x06, 0x46, 0x05, 0x21, ++0x41, 0xF2, 0x17, 0x40, 0xF8, 0xF7, 0xE0, 0xFF, 0x38, 0x4F, 0x39, 0x49, 0x05, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, ++0x91, 0xFE, 0xFF, 0xF7, 0xE1, 0xFD, 0x20, 0x46, 0xE5, 0xF7, 0x4A, 0xF8, 0x4F, 0xF0, 0x00, 0x08, 0x94, 0xF8, 0x6C, 0x00, ++0x7B, 0x6A, 0x98, 0x47, 0x86, 0xF8, 0x00, 0x80, 0x94, 0xF8, 0x63, 0x30, 0x73, 0x70, 0x2F, 0x48, 0xA6, 0xF1, 0x0C, 0x01, ++0xF9, 0xF7, 0x52, 0xFC, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x3F, 0xD1, 0x94, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x0D, 0xD0, ++0x01, 0x23, 0x00, 0x21, 0x06, 0x22, 0x0C, 0x20, 0xF8, 0xF7, 0xB6, 0xFF, 0x01, 0x46, 0x94, 0xF8, 0x6C, 0x30, 0x01, 0xF8, ++0x0C, 0x39, 0x23, 0x48, 0xF9, 0xF7, 0x3C, 0xFC, 0x23, 0x6C, 0x6B, 0xB1, 0x01, 0x23, 0x00, 0x21, 0x06, 0x22, 0x39, 0x20, ++0xF8, 0xF7, 0xA6, 0xFF, 0x01, 0x46, 0x94, 0xF8, 0x63, 0x30, 0x01, 0xF8, 0x0C, 0x39, 0x1B, 0x48, 0xF9, 0xF7, 0x2C, 0xFC, ++0x00, 0x26, 0x2E, 0x70, 0x94, 0xF8, 0x63, 0x20, 0x18, 0x4B, 0x6A, 0x70, 0x93, 0xF8, 0x04, 0x31, 0x43, 0xB1, 0xD7, 0xF8, ++0xD8, 0x31, 0x04, 0xF1, 0x9C, 0x00, 0x98, 0x47, 0xC4, 0xE9, 0x24, 0x66, 0xC4, 0xF8, 0x98, 0x60, 0x00, 0x23, 0xA5, 0xF1, ++0x0C, 0x01, 0xC4, 0xF8, 0xCC, 0x31, 0x0E, 0x48, 0xF9, 0xF7, 0x12, 0xFC, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7, 0x6C, 0xBF, ++0x41, 0x46, 0x04, 0x23, 0x06, 0x22, 0x1E, 0x20, 0xF8, 0xF7, 0x7A, 0xFF, 0x80, 0xF8, 0x02, 0x80, 0x94, 0xF8, 0x63, 0x30, ++0xC3, 0x70, 0xA0, 0xF1, 0x0C, 0x01, 0x04, 0x48, 0xF9, 0xF7, 0xFE, 0xFB, 0xAE, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0xA8, 0xBB, 0x15, 0x00, 0x70, 0xBA, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x6A, 0x4B, 0xDF, 0xF8, ++0xB4, 0xA1, 0x1D, 0x68, 0x83, 0xB0, 0x95, 0xF8, 0x3D, 0x20, 0x00, 0x92, 0x16, 0x46, 0x02, 0x23, 0x06, 0x22, 0x05, 0x21, ++0x41, 0xF2, 0x19, 0x40, 0xF8, 0xF7, 0x54, 0xFF, 0x08, 0x23, 0x81, 0x46, 0x06, 0x22, 0x00, 0x21, 0x18, 0x20, 0xF8, 0xF7, ++0x4D, 0xFF, 0x08, 0x23, 0x07, 0x46, 0x06, 0x22, 0x00, 0x21, 0x16, 0x20, 0xF8, 0xF7, 0x46, 0xFF, 0x4F, 0xF4, 0xA4, 0x64, ++0x04, 0xFB, 0x06, 0xF4, 0x04, 0x23, 0x06, 0x46, 0x06, 0x22, 0x00, 0x21, 0x14, 0x20, 0xF8, 0xF7, 0x3B, 0xFF, 0x02, 0x23, ++0x06, 0x22, 0x05, 0x21, 0x83, 0x46, 0x41, 0xF2, 0x17, 0x40, 0xF8, 0xF7, 0x33, 0xFF, 0x80, 0x46, 0xFF, 0xF7, 0x3A, 0xFD, ++0x4F, 0xF0, 0x01, 0x02, 0x89, 0xF8, 0x00, 0x20, 0x95, 0xF8, 0x3D, 0x30, 0x89, 0xF8, 0x01, 0x30, 0x0A, 0xEB, 0x04, 0x03, ++0x01, 0x93, 0x4B, 0x4B, 0xA9, 0xF1, 0x0C, 0x01, 0x03, 0xF1, 0x0C, 0x00, 0xF9, 0xF7, 0xAC, 0xFB, 0x01, 0x9B, 0xD3, 0xF8, ++0x64, 0x01, 0xB3, 0xF8, 0x68, 0x21, 0xBA, 0x80, 0x44, 0x4B, 0x38, 0x60, 0x95, 0xF8, 0x3D, 0x20, 0xBA, 0x71, 0x03, 0xF1, ++0x0C, 0x00, 0xA7, 0xF1, 0x0C, 0x01, 0xF9, 0xF7, 0x9B, 0xFB, 0x01, 0x9B, 0xD3, 0xF8, 0x90, 0x31, 0x04, 0xF5, 0xCE, 0x70, ++0x9B, 0x78, 0x73, 0x71, 0x01, 0x21, 0x50, 0x44, 0xFD, 0xF7, 0xFE, 0xFD, 0x73, 0x79, 0x30, 0x60, 0x95, 0xF8, 0x3D, 0x20, ++0x32, 0x71, 0x2B, 0xB9, 0xC1, 0x07, 0x4F, 0xD5, 0x36, 0x4B, 0x4F, 0xF4, 0x80, 0x62, 0x5A, 0x61, 0xA6, 0xF1, 0x0C, 0x01, ++0x34, 0x48, 0xF9, 0xF7, 0x7F, 0xFB, 0x00, 0x9B, 0x32, 0x48, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x03, 0xA6, 0xAB, 0xF1, ++0x0C, 0x01, 0xB6, 0xF8, 0x98, 0x31, 0xAB, 0xF8, 0x00, 0x30, 0x95, 0xF8, 0x3D, 0x30, 0x8B, 0xF8, 0x02, 0x30, 0xF9, 0xF7, ++0x6D, 0xFB, 0xD6, 0xF8, 0xCC, 0x31, 0x1B, 0x07, 0x36, 0xD4, 0x04, 0xF5, 0xD6, 0x74, 0x00, 0x26, 0x26, 0x4F, 0xA2, 0x44, ++0x34, 0x46, 0x08, 0x23, 0x06, 0x22, 0x00, 0x21, 0x1A, 0x20, 0xF8, 0xF7, 0xCF, 0xFE, 0x5A, 0xF8, 0x04, 0x3B, 0x03, 0x60, ++0x46, 0x71, 0x95, 0xF8, 0x3D, 0x30, 0x83, 0x71, 0x04, 0x71, 0xA0, 0xF1, 0x0C, 0x01, 0x01, 0x36, 0x38, 0x46, 0xF9, 0xF7, ++0x4F, 0xFB, 0x04, 0x2E, 0xE9, 0xD1, 0x01, 0x23, 0x88, 0xF8, 0x00, 0x30, 0x95, 0xF8, 0x3D, 0x30, 0x17, 0x48, 0x88, 0xF8, ++0x01, 0x30, 0xA8, 0xF1, 0x0C, 0x01, 0xF9, 0xF7, 0x41, 0xFB, 0xFF, 0xF7, 0x9D, 0xFE, 0x31, 0x46, 0x06, 0x20, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0xF9, 0xF7, 0xA4, 0xB8, 0xC2, 0x06, 0xB1, 0xD5, 0x0D, 0x4B, 0x04, 0x22, 0x5A, 0x61, 0xAD, 0xE7, ++0x06, 0x22, 0x00, 0x21, 0x04, 0x23, 0x71, 0x20, 0xF8, 0xF7, 0x9E, 0xFE, 0x04, 0xF1, 0xEC, 0x03, 0x06, 0x46, 0x0A, 0xEB, ++0x03, 0x00, 0xFD, 0xF7, 0x0F, 0xFE, 0x31, 0x46, 0x03, 0x46, 0x41, 0xF8, 0x0C, 0x39, 0x04, 0x48, 0xF9, 0xF7, 0x1E, 0xFB, ++0xB3, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0xC4, 0x3C, 0x18, 0x00, 0x70, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x06, 0x23, 0x2D, 0xE9, 0xF0, 0x41, 0x1A, 0x46, 0x04, 0x46, 0x0F, 0x46, 0x41, 0xF6, 0x05, 0x00, 0x0C, 0x21, 0xF8, 0xF7, ++0x7B, 0xFE, 0x38, 0x4E, 0x94, 0xF8, 0xC0, 0x34, 0xB4, 0x62, 0x05, 0x46, 0x00, 0x2B, 0x3F, 0xD0, 0x35, 0x4B, 0x9B, 0x68, ++0x00, 0x2B, 0x61, 0xD0, 0x93, 0xF8, 0x62, 0x20, 0x7A, 0xB9, 0x33, 0x49, 0x33, 0x4A, 0xD8, 0x6D, 0x08, 0x60, 0xB3, 0xF8, ++0x60, 0x10, 0x11, 0x60, 0x93, 0xF8, 0x64, 0x20, 0x2A, 0xB1, 0x30, 0x49, 0x98, 0x6B, 0x30, 0x4A, 0x08, 0x60, 0x99, 0x8F, ++0x11, 0x60, 0x2F, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x2C, 0xDB, 0xDF, 0xF8, 0xC4, 0x80, 0x00, 0x20, 0xDB, 0xF7, 0x86, 0xFE, ++0x00, 0x22, 0xD8, 0xF8, 0xD8, 0x31, 0x84, 0xF8, 0xAC, 0x20, 0x04, 0xF1, 0xB0, 0x00, 0x98, 0x47, 0xD8, 0xF8, 0x10, 0x33, ++0x20, 0x46, 0x98, 0x47, 0x2F, 0x80, 0x94, 0xF8, 0x63, 0x30, 0xAB, 0x70, 0xB3, 0x7D, 0x01, 0x2B, 0x08, 0xBF, 0xEB, 0x70, ++0xB3, 0x7F, 0xA3, 0xF1, 0x01, 0x03, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0xA5, 0xF1, 0x0C, 0x02, 0x2B, 0x71, 0xB2, 0x60, ++0xBD, 0xE8, 0xF0, 0x81, 0x1A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xD6, 0xDA, 0x13, 0x4B, 0x9B, 0x68, 0x00, 0x2B, 0xD2, 0xD0, ++0x00, 0x21, 0x93, 0xF8, 0x62, 0x20, 0x1A, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x02, 0xB1, 0x01, 0x31, 0x1B, 0x68, 0x00, 0x2B, ++0xF5, 0xD1, 0x01, 0x29, 0xC5, 0xD1, 0x11, 0x4A, 0x11, 0x49, 0x53, 0x70, 0x0B, 0x68, 0x11, 0x4A, 0x43, 0xF0, 0x00, 0x43, ++0x0B, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x43, 0xF4, 0xBB, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0xB4, 0xE7, ++0x07, 0x4B, 0x1B, 0x68, 0xB1, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x10, 0x00, 0x32, 0x40, ++0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x48, 0x30, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, ++0x34, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0A, 0x46, 0x04, 0x46, 0x05, 0x49, ++0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, 0xA4, 0xFC, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x60, 0xBF, ++0xBC, 0xBB, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xC8, 0x81, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x00, 0x84, ++0x0B, 0x46, 0x02, 0x46, 0x06, 0x46, 0x0F, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x66, 0x49, 0x94, 0xF8, 0x6C, 0x90, 0xFA, 0xF7, ++0x89, 0xFC, 0x94, 0xF8, 0x62, 0x50, 0x15, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x3B, 0xB9, 0xBD, 0xE8, 0xF8, 0x43, 0x06, 0x22, ++0x0C, 0x21, 0x41, 0xF6, 0x04, 0x00, 0xF8, 0xF7, 0x2B, 0xBE, 0x5E, 0x4B, 0x01, 0x25, 0x09, 0x21, 0x06, 0x20, 0x1D, 0x75, ++0xF8, 0xF7, 0xB6, 0xFF, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x79, 0xD1, 0xD4, 0xF8, 0x90, 0x31, 0x9D, 0x78, 0x2C, 0x1E, ++0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x06, 0x85, 0x28, 0x46, 0x18, 0xBF, 0x01, 0x24, 0xE4, 0xF7, 0x11, 0xFD, 0x00, 0x28, ++0x74, 0xD0, 0x20, 0x46, 0x4F, 0xF4, 0xC0, 0x71, 0xE6, 0xF7, 0x72, 0xF8, 0x04, 0x46, 0x01, 0x46, 0x28, 0x46, 0x00, 0x2C, ++0x6C, 0xD0, 0xF8, 0xF7, 0x69, 0xF9, 0x4C, 0x4B, 0xD4, 0xF8, 0x48, 0x80, 0x4B, 0x49, 0xE8, 0x6D, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x09, 0x39, 0xB1, 0xF8, 0xFC, 0x31, 0x59, 0xF8, 0x26, 0x2F, 0xC8, 0xF8, 0x6C, 0x20, 0x6F, 0xF0, 0x3F, 0x02, ++0x88, 0xF8, 0x68, 0x20, 0xB9, 0xF8, 0x04, 0x20, 0xA8, 0xF8, 0x70, 0x20, 0xB5, 0xF8, 0x60, 0x20, 0xA8, 0xF8, 0x76, 0x20, ++0x01, 0x33, 0xD9, 0xF8, 0x00, 0x20, 0xC8, 0xF8, 0x72, 0x00, 0x9B, 0xB2, 0xB9, 0xF8, 0x04, 0x00, 0xC8, 0xF8, 0x78, 0x20, ++0x00, 0x22, 0xA8, 0xF8, 0x7C, 0x00, 0x88, 0xF8, 0x69, 0x20, 0x88, 0xF8, 0x6A, 0x20, 0x88, 0xF8, 0x6B, 0x20, 0x18, 0x01, ++0xA1, 0xF8, 0xFC, 0x31, 0x35, 0x4B, 0xA8, 0xF8, 0x7E, 0x00, 0x26, 0x77, 0xA5, 0x65, 0x63, 0x65, 0x95, 0xF8, 0x6C, 0x30, ++0x63, 0x77, 0x84, 0xF8, 0x33, 0x20, 0x84, 0xF8, 0x35, 0x20, 0xC0, 0x21, 0x20, 0x46, 0x07, 0xF0, 0x5F, 0xF9, 0x01, 0x28, ++0x06, 0x46, 0x08, 0xF1, 0x68, 0x09, 0x34, 0xD0, 0x39, 0x46, 0x08, 0xF1, 0x80, 0x00, 0xFB, 0xF7, 0xDD, 0xFD, 0x02, 0x2E, ++0x00, 0xF1, 0x18, 0x05, 0x3D, 0xD0, 0xE2, 0x6C, 0x53, 0x6A, 0x01, 0x3B, 0x2B, 0x44, 0x04, 0x35, 0xC2, 0xE9, 0x0A, 0x35, ++0x05, 0x21, 0x20, 0x46, 0xE6, 0xF7, 0x20, 0xF8, 0x05, 0x46, 0x88, 0xB1, 0xBD, 0xE8, 0xF8, 0x83, 0x2C, 0x46, 0x4F, 0xF4, ++0xA4, 0x65, 0x05, 0xFB, 0x06, 0x85, 0x28, 0x46, 0xE4, 0xF7, 0x9C, 0xFC, 0x00, 0x28, 0x8A, 0xD1, 0x01, 0x46, 0x28, 0x46, ++0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0xA8, 0xBE, 0xA4, 0x6D, 0x17, 0x49, 0x02, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, ++0xDF, 0xFB, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0x9B, 0xBE, 0x18, 0x22, 0x49, 0x46, 0x20, 0x46, ++0x05, 0xF0, 0x84, 0xFF, 0x94, 0xF8, 0x33, 0x50, 0x18, 0x35, 0x09, 0xEB, 0x05, 0x00, 0x39, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, ++0x94, 0xF8, 0x35, 0x20, 0x15, 0x44, 0x05, 0x44, 0xC1, 0xE7, 0x2A, 0x46, 0x49, 0x46, 0x20, 0x46, 0x07, 0xF0, 0x4A, 0xF9, ++0x05, 0x44, 0xBA, 0xE7, 0xD4, 0xBB, 0x15, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0xD1, 0x9D, 0x14, 0x00, 0xBC, 0xBB, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x66, 0x4D, 0x67, 0x49, ++0xD5, 0xE9, 0x00, 0x34, 0x93, 0xF8, 0x3D, 0x70, 0x67, 0x72, 0x0A, 0x68, 0x20, 0x80, 0x22, 0xF0, 0x10, 0x02, 0x4F, 0xF4, ++0xA4, 0x66, 0x83, 0xB0, 0x80, 0x46, 0x06, 0xFB, 0x07, 0xF6, 0x0A, 0x60, 0x00, 0x28, 0x6C, 0xD1, 0xDF, 0xF8, 0x98, 0x91, ++0x09, 0xEB, 0x06, 0x01, 0x91, 0xF8, 0x6C, 0x20, 0xD1, 0xF8, 0x64, 0x01, 0xB1, 0xF8, 0x68, 0xC1, 0xA2, 0x72, 0x0A, 0x6C, ++0xA4, 0xF8, 0x06, 0xC0, 0xC4, 0xF8, 0x02, 0x00, 0x10, 0x7E, 0xE0, 0x72, 0x10, 0x79, 0x84, 0xF8, 0x36, 0x03, 0xD0, 0x88, ++0xB2, 0xF8, 0x08, 0xC0, 0xA4, 0xF8, 0x38, 0x03, 0x50, 0x89, 0xC4, 0xE9, 0xCF, 0xC0, 0x52, 0x79, 0x84, 0xF8, 0x3A, 0x23, ++0xD1, 0xF8, 0xCC, 0x21, 0x02, 0xF0, 0x01, 0x02, 0x22, 0x73, 0x00, 0x2A, 0x6D, 0xD1, 0x42, 0x46, 0x62, 0x73, 0x1A, 0x6B, ++0x4F, 0xF4, 0xA4, 0x63, 0x02, 0xF0, 0x20, 0x02, 0x03, 0xFB, 0x07, 0x93, 0x22, 0x72, 0x93, 0xF8, 0xC0, 0x24, 0xA2, 0xB1, ++0xB3, 0xF8, 0x5E, 0x00, 0xB3, 0xF8, 0x5C, 0x20, 0x42, 0x49, 0x42, 0xEA, 0x00, 0x42, 0x0A, 0x60, 0x41, 0x4A, 0xB3, 0xF8, ++0x60, 0x10, 0x11, 0x60, 0x58, 0x8F, 0x1A, 0x8F, 0x3F, 0x49, 0x42, 0xEA, 0x00, 0x42, 0x0A, 0x60, 0x3E, 0x4A, 0x9B, 0x8F, ++0x13, 0x60, 0x20, 0x46, 0xF8, 0xF7, 0xC8, 0xFC, 0x94, 0xF8, 0x3A, 0x33, 0xB4, 0xF8, 0x3C, 0x03, 0x40, 0xEA, 0x03, 0x40, ++0x40, 0xF0, 0x00, 0x40, 0xDB, 0xF7, 0xC0, 0xFC, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x97, 0x01, 0x22, 0x35, 0x4B, ++0x87, 0xF8, 0xAC, 0x20, 0x1A, 0x69, 0x34, 0x49, 0x34, 0x4B, 0x06, 0xF1, 0xB0, 0x00, 0x48, 0x44, 0x11, 0x44, 0xD3, 0xF8, ++0xE0, 0x31, 0x98, 0x47, 0x00, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x72, 0xFE, 0x12, 0xE0, 0x2F, 0x4B, 0x1B, 0x68, 0x00, 0x2B, ++0x26, 0xDB, 0x2E, 0x4B, 0x06, 0x20, 0x09, 0x21, 0x1E, 0x44, 0xF8, 0xF7, 0x67, 0xFE, 0x29, 0x4A, 0xAE, 0x62, 0xA4, 0xF1, ++0x0C, 0x03, 0xD2, 0xF8, 0x10, 0x23, 0xAB, 0x60, 0x30, 0x46, 0x90, 0x47, 0xB4, 0xF8, 0x34, 0x33, 0x62, 0x7A, 0x26, 0x49, ++0x00, 0x93, 0x4F, 0xF4, 0x80, 0x70, 0x43, 0x46, 0xFA, 0xF7, 0x12, 0xFB, 0x28, 0x68, 0x0C, 0x38, 0xF8, 0xF7, 0xD2, 0xFC, ++0x00, 0x23, 0x2B, 0x60, 0xAB, 0x75, 0xAB, 0x77, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x91, 0xF8, 0xBD, 0x21, 0x8F, 0xE7, ++0x1C, 0x4B, 0x9A, 0x68, 0x62, 0xB1, 0x00, 0x21, 0x92, 0xF8, 0x62, 0x30, 0x1B, 0xB9, 0x92, 0xF8, 0x64, 0x30, 0x03, 0xB1, ++0x01, 0x31, 0x12, 0x68, 0x00, 0x2A, 0xF5, 0xD1, 0x00, 0x29, 0xC8, 0xD1, 0x15, 0x4B, 0x16, 0x49, 0x00, 0x22, 0x5A, 0x70, ++0x0B, 0x68, 0x15, 0x4A, 0x43, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x43, 0xF4, 0xBB, 0x63, ++0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0xB6, 0xE7, 0x64, 0xBA, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0x10, 0x00, 0x32, 0x40, ++0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x40, 0x4B, 0x4C, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x48, 0x30, 0x34, 0x40, 0x18, 0x88, 0x17, 0x00, 0xE8, 0xBB, 0x15, 0x00, 0x00, 0x88, 0x17, 0x00, ++0x4C, 0x36, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0x4B, 0x8C, 0x4E, ++0xD3, 0xF8, 0x00, 0x90, 0x8B, 0x4A, 0x99, 0xF8, 0x3D, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x05, 0x64, 0x89, 0xB0, ++0x07, 0x46, 0x88, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x86, 0x49, 0x94, 0xF8, 0x6C, 0xA0, 0xFA, 0xF7, 0xAB, 0xFA, 0x94, 0xF8, ++0xC0, 0x34, 0x00, 0x2B, 0x40, 0xF0, 0x82, 0x80, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x78, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, ++0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0xB2, 0xFE, 0x04, 0x46, 0x00, 0x28, 0x7C, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x05, 0x65, 0x28, 0x46, 0x21, 0x46, 0xF7, 0xF7, 0xA5, 0xFF, 0x78, 0x4B, 0xA2, 0x6C, 0x78, 0x49, 0x4F, 0xF4, 0x1E, 0x70, ++0x00, 0xFB, 0x0A, 0x3A, 0x53, 0x46, 0xB1, 0xF8, 0xFC, 0x61, 0x53, 0xF8, 0x26, 0x0F, 0xD0, 0x66, 0x6F, 0xF0, 0x4F, 0x00, ++0x82, 0xF8, 0x68, 0x00, 0x98, 0x88, 0xA2, 0xF8, 0x70, 0x00, 0xE8, 0x6D, 0xC2, 0xF8, 0x72, 0x00, 0x01, 0x36, 0xB5, 0xF8, ++0x60, 0x00, 0xA2, 0xF8, 0x76, 0x00, 0x4F, 0xF0, 0x00, 0x0B, 0x18, 0x68, 0x9B, 0x88, 0xA2, 0xF8, 0x7C, 0x30, 0xB6, 0xB2, ++0x90, 0x67, 0x82, 0xF8, 0x69, 0xB0, 0x82, 0xF8, 0x6A, 0xB0, 0x82, 0xF8, 0x6B, 0xB0, 0x65, 0x4B, 0xA1, 0xF8, 0xFC, 0x61, ++0x30, 0x01, 0x95, 0xF8, 0x63, 0x10, 0xA2, 0xF8, 0x7E, 0x00, 0x21, 0x77, 0x95, 0xF8, 0x6C, 0x10, 0x1B, 0x68, 0x61, 0x77, ++0x84, 0xF8, 0x33, 0xB0, 0x84, 0xF8, 0x35, 0xB0, 0x1B, 0x78, 0x99, 0xF8, 0x3B, 0x10, 0x9B, 0x07, 0x02, 0xF1, 0x68, 0x05, ++0x38, 0xD4, 0x01, 0x29, 0x44, 0xD0, 0x18, 0x26, 0xCD, 0xF8, 0x00, 0x80, 0x3A, 0x46, 0xA8, 0x19, 0x00, 0x23, 0xFB, 0xF7, ++0xFF, 0xFB, 0x30, 0x44, 0xE1, 0x6C, 0x94, 0xF8, 0x35, 0x30, 0x4A, 0x6A, 0xA4, 0x65, 0x18, 0x44, 0x01, 0x3A, 0x02, 0x44, ++0x03, 0x1D, 0x50, 0x48, 0x60, 0x65, 0xC1, 0xE9, 0x0A, 0x23, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, 0x59, 0xFE, 0x4D, 0x4B, ++0x1B, 0x68, 0x06, 0x21, 0xDA, 0x68, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, 0xD1, 0xF9, 0x05, 0x21, 0x06, 0x20, 0xF8, 0xF7, ++0x69, 0xFD, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0x35, 0xFE, 0x04, 0x46, ++0x00, 0x28, 0x82, 0xD1, 0x01, 0x20, 0xFF, 0xF7, 0x67, 0xFE, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x29, 0x01, 0xD1, ++0x03, 0x2F, 0x17, 0xD0, 0xCD, 0xF8, 0x00, 0x80, 0x3A, 0x46, 0x05, 0xF1, 0x18, 0x00, 0x00, 0x23, 0xFB, 0xF7, 0xC4, 0xFB, ++0x18, 0x30, 0xC3, 0xE7, 0x03, 0x2F, 0xB8, 0xD1, 0x29, 0x46, 0x20, 0x46, 0x18, 0x22, 0x05, 0xF0, 0xB1, 0xFD, 0x94, 0xF8, ++0x33, 0x00, 0x99, 0xF8, 0x3B, 0x10, 0x00, 0xF1, 0x18, 0x06, 0xAD, 0xE7, 0xDA, 0xF8, 0xB4, 0x30, 0x29, 0x46, 0x18, 0x22, ++0x20, 0x46, 0x1E, 0x68, 0x05, 0xF0, 0xA2, 0xFD, 0x94, 0xF8, 0x33, 0x00, 0x99, 0xF8, 0x3B, 0x10, 0xCD, 0xF8, 0x00, 0x80, ++0x00, 0xF1, 0x18, 0x08, 0x05, 0xEB, 0x08, 0x09, 0x5B, 0x46, 0x3A, 0x46, 0x48, 0x46, 0xFB, 0xF7, 0x9D, 0xFB, 0x05, 0x46, ++0x3A, 0x46, 0x29, 0x46, 0x4F, 0xF0, 0xFF, 0x33, 0x48, 0x46, 0xDB, 0xF7, 0x67, 0xFD, 0x96, 0xF8, 0x60, 0x30, 0x21, 0x8F, ++0x62, 0x8F, 0xAD, 0xF8, 0x10, 0x10, 0x8D, 0xF8, 0x12, 0x20, 0x06, 0xF1, 0x64, 0x01, 0x93, 0xB1, 0x03, 0x2B, 0x1A, 0xD0, ++0x03, 0x20, 0xDB, 0xF7, 0x8F, 0xFD, 0x29, 0x1D, 0x02, 0x46, 0x89, 0xB2, 0x48, 0x46, 0x03, 0x91, 0xF7, 0xF7, 0x20, 0xFF, ++0x48, 0x46, 0x03, 0x99, 0xF8, 0xF7, 0x16, 0xF9, 0x05, 0xEB, 0x08, 0x00, 0x78, 0xE7, 0x05, 0x22, 0x0D, 0xF1, 0x13, 0x00, ++0x0C, 0xF0, 0x88, 0xFE, 0x04, 0xA8, 0x08, 0x21, 0xF8, 0xF7, 0xDE, 0xF8, 0xE4, 0xE7, 0x0D, 0x22, 0x0D, 0xF1, 0x13, 0x00, ++0x0C, 0xF0, 0x7E, 0xFE, 0x04, 0xA8, 0x10, 0x21, 0xF8, 0xF7, 0xD4, 0xF8, 0xDA, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x9C, 0xBC, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x89, 0x95, 0x14, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x77, 0x4F, 0x78, 0x4E, ++0xD7, 0xF8, 0x00, 0x80, 0x77, 0x4A, 0x98, 0xF8, 0x3D, 0x50, 0x77, 0x49, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x05, 0x64, ++0x87, 0xB0, 0x4F, 0xF4, 0x80, 0x70, 0x94, 0xF8, 0x6C, 0xA0, 0xFA, 0xF7, 0x81, 0xF9, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0x40, 0xF0, 0xAA, 0x80, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x78, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, ++0xE5, 0xF7, 0x88, 0xFD, 0x04, 0x46, 0x00, 0x28, 0x00, 0xF0, 0xA5, 0x80, 0x4F, 0xF4, 0xA4, 0x6B, 0x0B, 0xFB, 0x05, 0xFB, ++0x06, 0xEB, 0x0B, 0x00, 0x21, 0x46, 0xD7, 0xF8, 0x04, 0x90, 0xF7, 0xF7, 0x77, 0xFE, 0xBA, 0x7D, 0xA3, 0x6C, 0x01, 0x2A, ++0x03, 0xF1, 0x68, 0x0C, 0x00, 0xF0, 0x99, 0x80, 0xBA, 0x7F, 0x00, 0x2A, 0x00, 0xF0, 0xA7, 0x80, 0x20, 0x22, 0x00, 0x21, ++0x83, 0xF8, 0x68, 0x20, 0x5B, 0x4A, 0x83, 0xF8, 0x69, 0x10, 0x5B, 0x49, 0x5B, 0x4F, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x0A, 0x10, 0xB7, 0xF8, 0xFC, 0xE1, 0x50, 0xF8, 0x26, 0xAF, 0xC3, 0xF8, 0x6C, 0xA0, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, ++0x05, 0x65, 0xB0, 0xF8, 0x04, 0xA0, 0xA3, 0xF8, 0x70, 0xA0, 0x0B, 0xF1, 0xEC, 0x01, 0x0E, 0xF1, 0x01, 0x0E, 0xD0, 0xF8, ++0x00, 0xA0, 0xB0, 0xF8, 0x04, 0xB0, 0xE8, 0x6D, 0xC3, 0xF8, 0x72, 0x00, 0x1F, 0xFA, 0x8E, 0xFE, 0x31, 0x44, 0x00, 0x26, ++0xB5, 0xF8, 0x60, 0x00, 0xC3, 0xF8, 0x78, 0xA0, 0x83, 0xF8, 0x6A, 0x60, 0x83, 0xF8, 0x6B, 0x60, 0x4F, 0xEA, 0x0E, 0x1A, ++0x46, 0x4E, 0xA3, 0xF8, 0x76, 0x00, 0xA3, 0xF8, 0x7C, 0xB0, 0x0C, 0xF1, 0x18, 0x00, 0xA7, 0xF8, 0xFC, 0xE1, 0x0D, 0xF1, ++0x12, 0x0C, 0xA3, 0xF8, 0x7E, 0xA0, 0x05, 0xAF, 0x95, 0xF8, 0x63, 0x30, 0xCD, 0xF8, 0x08, 0x80, 0xD6, 0xF8, 0x58, 0x61, ++0xCD, 0xE9, 0x00, 0x7C, 0xB0, 0x47, 0x95, 0xF8, 0x63, 0x30, 0x23, 0x77, 0x95, 0xF8, 0x6C, 0x30, 0xE1, 0x6C, 0x63, 0x77, ++0x4B, 0x6A, 0xBD, 0xF8, 0x12, 0x20, 0x37, 0x4D, 0xA4, 0x65, 0x17, 0x33, 0x03, 0x44, 0xB2, 0xF5, 0x48, 0x7F, 0x00, 0xF1, ++0x1C, 0x00, 0x65, 0x65, 0xC1, 0xE9, 0x0A, 0x30, 0x3B, 0xD8, 0x05, 0x98, 0x6A, 0xB1, 0x4A, 0x44, 0x13, 0x38, 0x13, 0x32, ++0xA0, 0xEB, 0x09, 0x00, 0x09, 0xF1, 0x13, 0x03, 0xC1, 0x5C, 0x03, 0xF8, 0x01, 0x1F, 0x93, 0x42, 0xFA, 0xD1, 0xBD, 0xF8, ++0x12, 0x20, 0xA9, 0xF8, 0x0E, 0x20, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, 0x07, 0xFD, 0x27, 0x4B, 0x1B, 0x68, 0x06, 0x21, ++0x9A, 0x68, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, 0x7F, 0xF8, 0x07, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x17, 0xFC, 0x07, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0xE3, 0xFC, 0x04, 0x46, 0x00, 0x28, 0x7F, 0xF4, ++0x5B, 0xAF, 0x01, 0x20, 0xFF, 0xF7, 0x14, 0xFD, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x20, 0x22, 0x00, 0x21, 0x83, 0xF8, ++0x68, 0x20, 0x83, 0xF8, 0x69, 0x10, 0x16, 0x4A, 0x69, 0xE7, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x08, 0xDB, 0x00, 0x23, 0xA9, 0xF8, 0x0E, 0x30, 0xCB, 0xE7, 0x83, 0xF8, 0x68, 0x20, 0x83, 0xF8, 0x69, 0x20, 0x5A, 0xE7, ++0x0F, 0x49, 0x10, 0x48, 0x4F, 0xF4, 0x82, 0x62, 0xFA, 0xF7, 0xE8, 0xFA, 0xEF, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0xAC, 0xBC, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x84, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x89, 0x95, 0x14, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x7C, 0xBA, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0xB5, 0x0B, 0x4D, 0x04, 0x46, 0x04, 0x23, ++0x00, 0x21, 0x06, 0x22, 0x1E, 0x20, 0x2D, 0x68, 0xF8, 0xF7, 0xC6, 0xF9, 0x01, 0x22, 0x04, 0x80, 0x82, 0x70, 0x95, 0xF8, ++0x3D, 0x20, 0xC2, 0x70, 0xF8, 0xF7, 0xEE, 0xF9, 0xBD, 0xE8, 0x38, 0x40, 0x08, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0xB2, 0xBB, ++0x64, 0xBA, 0x17, 0x00, 0x70, 0xB5, 0x00, 0xF1, 0x0C, 0x06, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, ++0xBB, 0xF8, 0xB5, 0x88, 0x19, 0x49, 0x2A, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, 0x5E, 0xF8, 0x45, 0xB9, 0xA3, 0x89, ++0x13, 0xB1, 0x01, 0x2B, 0x09, 0xD0, 0x70, 0xBD, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xBE, 0xBE, 0x28, 0x46, 0xBD, 0xE8, ++0x70, 0x40, 0xFF, 0xF7, 0x9D, 0xBC, 0x73, 0x88, 0x04, 0x2B, 0xF3, 0xD0, 0x02, 0x2B, 0x11, 0xD0, 0x0D, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0xFF, 0xF7, 0x8D, 0xBC, 0x09, 0x49, ++0x09, 0x48, 0x4F, 0xF4, 0x8C, 0x62, 0xFA, 0xF7, 0x7B, 0xFA, 0xF3, 0xE7, 0x04, 0xF1, 0x14, 0x01, 0x03, 0x20, 0xBD, 0xE8, ++0x70, 0x40, 0xFF, 0xF7, 0x6F, 0xBD, 0x00, 0xBF, 0x00, 0xBC, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x69, 0x4B, 0xD3, 0xE9, 0x00, 0x2A, 0x05, 0x46, 0x83, 0xB0, 0x06, 0x21, ++0x00, 0x24, 0x41, 0xF6, 0x08, 0x00, 0x92, 0xF8, 0x3D, 0x80, 0x8D, 0xF8, 0x06, 0x40, 0xF8, 0xF7, 0x6D, 0xF8, 0x29, 0x88, ++0xEE, 0x89, 0x4F, 0xF4, 0xA4, 0x67, 0x05, 0x29, 0x05, 0xF1, 0x0C, 0x09, 0x07, 0xFB, 0x08, 0xF7, 0x34, 0xD9, 0xBA, 0xF8, ++0x0E, 0x30, 0x06, 0x39, 0x89, 0xB2, 0xCA, 0x18, 0x05, 0xF1, 0x12, 0x0B, 0xB2, 0xF5, 0x48, 0x7F, 0x5C, 0x46, 0x09, 0xDD, ++0x58, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x81, 0x80, 0xC3, 0xF5, 0x48, 0x71, 0x89, 0xB2, ++0x0A, 0xF1, 0x14, 0x00, 0x18, 0x44, 0x8B, 0x44, 0x39, 0xB1, 0xA4, 0xF1, 0x12, 0x03, 0x14, 0xF8, 0x01, 0x2B, 0x5B, 0x1B, ++0x5C, 0x45, 0x1A, 0x54, 0xF7, 0xD1, 0xAA, 0xF8, 0x10, 0x10, 0x32, 0x46, 0x4C, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, ++0xE3, 0xFF, 0x9E, 0xB1, 0x4A, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x2B, 0xBB, 0x30, 0x46, 0xFF, 0xF7, 0x29, 0xFC, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x44, 0x49, 0xAA, 0xF8, 0x10, 0x40, 0x32, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0xD0, 0xFF, ++0x00, 0x2E, 0xEB, 0xD1, 0xB9, 0xF8, 0x04, 0x00, 0x40, 0x4C, 0xC0, 0xF3, 0x0D, 0x00, 0xFF, 0xF7, 0x3F, 0xFF, 0x3D, 0x4B, ++0x93, 0xF8, 0x04, 0x31, 0x63, 0xB3, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x08, 0x45, 0xD5, 0xF8, 0x90, 0x31, 0x9A, 0x78, ++0x01, 0x2A, 0x48, 0xD0, 0x38, 0x4E, 0x28, 0xE0, 0x12, 0x2E, 0xD7, 0xD1, 0x35, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, ++0x08, 0x38, 0xD8, 0xF8, 0x90, 0x21, 0x92, 0x78, 0x01, 0x2A, 0xCD, 0xD1, 0x98, 0xF8, 0xC0, 0x44, 0x00, 0x2C, 0xC9, 0xD1, ++0x30, 0x4D, 0x07, 0xF5, 0xB2, 0x77, 0x1F, 0x44, 0xA8, 0x46, 0x40, 0x46, 0x06, 0x22, 0x39, 0x46, 0x0C, 0xF0, 0x3E, 0xFC, ++0x08, 0xF1, 0x14, 0x08, 0x00, 0x28, 0x3F, 0xD0, 0x01, 0x34, 0x05, 0x2C, 0xF3, 0xD1, 0xB7, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x08, 0x43, 0x24, 0x4E, 0xD3, 0xF8, 0x90, 0x31, 0x1B, 0x79, 0xD6, 0xF8, 0x40, 0x53, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x08, 0x48, 0xE0, 0x19, 0x98, 0xF8, 0xC6, 0x21, 0x9B, 0x1A, 0x8D, 0xF8, 0x07, 0x30, 0x0D, 0xF1, 0x06, 0x02, ++0x0D, 0xF1, 0x07, 0x01, 0xA8, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0x49, 0x1B, 0x48, 0x40, 0xF2, 0x8B, 0x42, ++0xFA, 0xF7, 0xB6, 0xF9, 0xBA, 0xF8, 0x0E, 0x30, 0x75, 0xE7, 0xD5, 0xF8, 0xCC, 0x21, 0x12, 0xF0, 0x0C, 0x0F, 0xB1, 0xD0, ++0x95, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0xAD, 0xD1, 0x13, 0x4B, 0x14, 0x49, 0x1B, 0x69, 0x0E, 0x4E, 0x07, 0xF1, 0x9C, 0x00, ++0x19, 0x44, 0x20, 0x44, 0xD6, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0xD5, 0xF8, 0x90, 0x31, 0xCA, 0xE7, 0x04, 0xEB, 0x84, 0x04, ++0x05, 0xEB, 0x84, 0x04, 0x01, 0x23, 0xE3, 0x71, 0x74, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x14, 0xBC, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xCC, 0x35, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x80, 0x96, 0x98, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x04, 0x46, 0x06, 0x20, 0x25, 0x7A, 0xF8, 0xF7, 0x1F, 0xFB, 0x09, 0x28, 0x0A, 0xD0, 0x06, 0x20, 0xF8, 0xF7, 0x1A, 0xFB, ++0x48, 0xB1, 0x2D, 0x4A, 0x23, 0x7A, 0x12, 0x68, 0x92, 0xF8, 0x3D, 0x20, 0x9A, 0x42, 0x0D, 0xD0, 0x02, 0x20, 0xBD, 0xE8, ++0xF0, 0x87, 0x29, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0xF5, 0x7E, 0x19, 0x96, 0xF8, 0x64, 0x00, 0x60, 0xB9, ++0xBD, 0xE8, 0xF0, 0x87, 0x24, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0x15, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0x60, 0xFB, ++0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xA4, 0x89, 0x1F, 0x49, 0x22, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0x08, 0xFF, ++0x1D, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x0B, 0xB1, 0x08, 0x2C, 0x0A, 0xD0, 0x09, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x40, 0xFA, ++0x78, 0x19, 0x21, 0x46, 0xFF, 0xF7, 0xBC, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0x90, 0x31, 0x9B, 0x78, ++0x01, 0x2B, 0xEF, 0xD1, 0x96, 0xF8, 0xC0, 0x64, 0x00, 0x2E, 0xEB, 0xD1, 0xDF, 0xF8, 0x44, 0x90, 0x05, 0xF5, 0xB2, 0x7A, ++0xC8, 0x46, 0xBA, 0x44, 0x40, 0x46, 0x06, 0x22, 0x51, 0x46, 0x0C, 0xF0, 0x83, 0xFB, 0x08, 0xF1, 0x14, 0x08, 0x18, 0xB1, ++0x01, 0x36, 0x05, 0x2E, 0xF4, 0xD1, 0xD9, 0xE7, 0x06, 0xEB, 0x86, 0x06, 0x09, 0xEB, 0x86, 0x06, 0x01, 0x23, 0xB3, 0x71, ++0xD2, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2C, 0xBC, 0x15, 0x00, 0x50, 0xBC, 0x15, 0x00, ++0x2C, 0x19, 0x17, 0x00, 0xCC, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x46, 0x4B, 0x04, 0x7A, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, 0x64, 0x30, 0xC3, 0xB1, 0x94, 0xF8, 0x62, 0x30, 0xAB, 0xB9, 0xC3, 0x79, 0xFF, 0x2B, ++0x05, 0x46, 0x11, 0xD0, 0x94, 0xF8, 0x6C, 0x20, 0x9A, 0x42, 0x0D, 0xD1, 0x3D, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x02, 0x66, 0x96, 0xF8, 0x30, 0x30, 0x02, 0x2B, 0x04, 0xD1, 0x90, 0xF8, 0x0D, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x01, 0xD0, ++0xBD, 0xE8, 0xF8, 0x83, 0x80, 0x79, 0xB5, 0xF8, 0x0E, 0x80, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, ++0xE5, 0xF7, 0xAE, 0xFA, 0x07, 0x46, 0x00, 0x28, 0xF0, 0xD0, 0x01, 0x46, 0x20, 0x46, 0xF7, 0xF7, 0xA5, 0xFB, 0x32, 0x46, ++0xDF, 0xF8, 0xB4, 0xC0, 0xBB, 0x6C, 0x52, 0xF8, 0x26, 0x0F, 0xBC, 0xF8, 0xFC, 0x11, 0xD8, 0x66, 0x6F, 0xF0, 0x2F, 0x00, ++0x83, 0xF8, 0x68, 0x00, 0x01, 0x31, 0x90, 0x88, 0xA3, 0xF8, 0x70, 0x00, 0x89, 0xB2, 0xE0, 0x6D, 0xB4, 0xF8, 0x60, 0x40, ++0xA3, 0xF8, 0x76, 0x40, 0xC3, 0xF8, 0x72, 0x00, 0x14, 0x68, 0x90, 0x88, 0x83, 0xF8, 0x69, 0x90, 0x0A, 0x01, 0x83, 0xF8, ++0x6A, 0x90, 0x83, 0xF8, 0x6B, 0x90, 0x9C, 0x67, 0xA3, 0xF8, 0x7C, 0x00, 0xAC, 0xF8, 0xFC, 0x11, 0xA3, 0xF8, 0x7E, 0x20, ++0x2A, 0x7A, 0x3A, 0x77, 0xEA, 0x79, 0x7A, 0x77, 0x03, 0xF1, 0x68, 0x04, 0x87, 0xF8, 0x33, 0x90, 0x87, 0xF8, 0x35, 0x90, ++0x08, 0x22, 0xD0, 0x21, 0x38, 0x46, 0x06, 0xF0, 0xA5, 0xFB, 0x21, 0x46, 0x38, 0x46, 0x18, 0x22, 0x05, 0xF0, 0x04, 0xFA, ++0x97, 0xF8, 0x33, 0x30, 0x18, 0x33, 0x1A, 0x19, 0x08, 0x21, 0x19, 0x55, 0x01, 0x21, 0x51, 0x70, 0xF9, 0x6C, 0xA2, 0xF8, ++0x02, 0x80, 0x97, 0xF8, 0x35, 0x00, 0x4A, 0x6A, 0x04, 0x30, 0x03, 0x44, 0x01, 0x3A, 0x1A, 0x44, 0x04, 0x33, 0xC1, 0xE9, ++0x0A, 0x23, 0x38, 0x46, 0x05, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xE5, 0xF7, 0x5F, 0xBA, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x31, 0x4B, 0x32, 0x4A, 0x1B, 0x68, 0x2D, 0xE9, 0xF0, 0x41, 0xB3, 0xF9, ++0x00, 0x30, 0xD2, 0xF8, 0x00, 0x80, 0x2F, 0x4F, 0x98, 0xF8, 0x3D, 0x50, 0x00, 0x2B, 0x06, 0x46, 0x45, 0xDB, 0x2C, 0x23, ++0x06, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x06, 0x00, 0xF7, 0xF7, 0x64, 0xFF, 0x4F, 0xF4, 0xA4, 0x61, 0x03, 0x46, 0x98, 0xF8, ++0x3D, 0x20, 0x03, 0xF8, 0x01, 0x2B, 0x01, 0xFB, 0x05, 0x71, 0x01, 0xF5, 0xB5, 0x72, 0x04, 0x46, 0x01, 0xF5, 0xC5, 0x71, ++0xD2, 0xF8, 0x00, 0xE0, 0xD2, 0xF8, 0x04, 0xC0, 0x90, 0x68, 0xD2, 0xF8, 0x0C, 0x80, 0xC3, 0xF8, 0x0C, 0x80, 0x10, 0x32, ++0x8A, 0x42, 0xC3, 0xF8, 0x00, 0xE0, 0xC3, 0xF8, 0x04, 0xC0, 0x98, 0x60, 0x03, 0xF1, 0x10, 0x03, 0xEC, 0xD1, 0x4F, 0xF4, ++0xA4, 0x61, 0x12, 0x78, 0x1A, 0x70, 0x01, 0xFB, 0x05, 0x75, 0x36, 0xBA, 0xD5, 0xF8, 0x64, 0x01, 0xB5, 0xF8, 0x68, 0x31, ++0xE3, 0x84, 0x06, 0x21, 0xC4, 0xF8, 0x22, 0x00, 0xA6, 0x62, 0x08, 0x46, 0xF8, 0xF7, 0x2A, 0xF9, 0x41, 0xF6, 0x08, 0x00, ++0x0E, 0x4A, 0x06, 0x21, 0xF7, 0xF7, 0x88, 0xFD, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xF7, 0xF7, 0x55, 0xBF, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x05, 0x73, 0xD3, 0xF8, 0xCC, 0x31, 0x00, 0x2B, 0xB1, 0xDB, 0x07, 0x49, 0x07, 0x48, 0x4F, 0xF4, ++0xAB, 0x62, 0xF9, 0xF7, 0xF9, 0xFF, 0xAA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xC0, 0x27, 0x09, 0x00, 0x70, 0x79, 0x15, 0x00, 0x74, 0xBC, 0x15, 0x00, 0x10, 0xB5, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, ++0x08, 0x00, 0xF7, 0xF7, 0x11, 0xFE, 0x1C, 0xB9, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x20, 0xBC, 0x20, 0x46, 0xBD, 0xE8, ++0x10, 0x40, 0xFF, 0xF7, 0xFF, 0xB9, 0x00, 0xBF, 0x08, 0xB5, 0x06, 0x20, 0xF8, 0xF7, 0x96, 0xF9, 0xA0, 0xF1, 0x06, 0x00, ++0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x08, 0xBD, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x07, 0x02, 0xF8, 0xF7, 0xDE, 0xFD, ++0xB8, 0xB1, 0x9D, 0xF8, 0x07, 0x30, 0x1D, 0x2B, 0x16, 0xD9, 0x02, 0x89, 0x92, 0x00, 0x0A, 0x3B, 0x92, 0xB2, 0x9B, 0x1A, ++0xDB, 0xB2, 0x15, 0x2B, 0x0E, 0xD9, 0x0A, 0x30, 0x02, 0x3B, 0x81, 0x5A, 0x89, 0x00, 0x89, 0xB2, 0x5B, 0x1A, 0xDB, 0xB2, ++0x13, 0x2B, 0x10, 0x44, 0x04, 0xD9, 0x04, 0x30, 0x40, 0x5A, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x00, 0x20, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0xFB, 0x2D, 0xE9, 0xF0, 0x4F, 0x4F, 0xF4, 0xA4, 0x68, 0x95, 0xB0, 0xDF, 0xF8, 0x50, 0x93, 0xDF, 0xF8, ++0x50, 0xB3, 0x08, 0xFB, 0x00, 0xF3, 0x07, 0x93, 0x4B, 0x44, 0x05, 0x46, 0xD3, 0xF8, 0x90, 0x01, 0x93, 0xF8, 0x6C, 0x40, ++0x80, 0x78, 0x02, 0x93, 0x17, 0x46, 0x4F, 0xF4, 0x1E, 0x78, 0x00, 0x38, 0x08, 0xFB, 0x04, 0xB6, 0x0A, 0x46, 0x3B, 0x78, ++0xD6, 0xF8, 0xB0, 0xA0, 0x04, 0x94, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0x05, 0x92, 0x06, 0x93, 0xE5, 0xF7, ++0x6F, 0xF9, 0x00, 0x28, 0x00, 0xF0, 0xED, 0x80, 0x02, 0x9B, 0x04, 0x46, 0x21, 0x46, 0x18, 0x46, 0xF7, 0xF7, 0x64, 0xFA, ++0xB9, 0x4B, 0x96, 0xF8, 0x23, 0x00, 0xD3, 0xF8, 0x34, 0x21, 0xA3, 0x6C, 0x02, 0x93, 0x00, 0x21, 0x90, 0x47, 0x02, 0x9B, ++0x03, 0x90, 0x03, 0xF1, 0x68, 0x02, 0x08, 0x92, 0x00, 0x28, 0x40, 0xF0, 0xD9, 0x80, 0xB2, 0x49, 0xB1, 0xF8, 0xFC, 0x21, ++0x01, 0x32, 0x92, 0xB2, 0x08, 0x20, 0x83, 0xF8, 0x68, 0x00, 0x10, 0x01, 0x01, 0x26, 0x80, 0xB2, 0x83, 0xF8, 0x69, 0x60, ++0x09, 0x90, 0xA1, 0xF8, 0xFC, 0x21, 0x04, 0x99, 0x02, 0x93, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0xB2, 0x4F, 0xF4, ++0xA4, 0x66, 0x52, 0xF8, 0x26, 0x1F, 0xD9, 0x66, 0x06, 0xFB, 0x05, 0x96, 0x91, 0x88, 0xF0, 0x6D, 0xB6, 0xF8, 0x60, 0x20, ++0xA3, 0xF8, 0x76, 0x20, 0x4F, 0xF0, 0x00, 0x08, 0xA3, 0xF8, 0x70, 0x10, 0xC3, 0xF8, 0x72, 0x00, 0x05, 0x99, 0x83, 0xF8, ++0x6A, 0x80, 0x83, 0xF8, 0x6B, 0x80, 0x06, 0x22, 0x03, 0xF1, 0x78, 0x00, 0x0C, 0xF0, 0xDC, 0xF9, 0x09, 0x9B, 0x96, 0xF8, ++0x63, 0x20, 0x19, 0x01, 0x02, 0x9B, 0xA3, 0xF8, 0x7E, 0x10, 0x22, 0x77, 0x96, 0xF8, 0x6C, 0x20, 0x62, 0x77, 0x03, 0x9A, ++0x00, 0x2A, 0x00, 0xF0, 0xE1, 0x80, 0x1A, 0x22, 0x83, 0xF8, 0x80, 0x80, 0x83, 0xF8, 0x81, 0x80, 0x02, 0x92, 0x7A, 0x78, ++0x00, 0x21, 0x12, 0xF0, 0x40, 0x02, 0xCD, 0xE9, 0x0A, 0x11, 0x40, 0xF0, 0xB5, 0x80, 0x84, 0xF8, 0x33, 0x20, 0x84, 0xF8, ++0x35, 0x20, 0x89, 0x4B, 0x02, 0x9A, 0x93, 0xE8, 0x03, 0x00, 0x08, 0x9B, 0x13, 0x44, 0x1E, 0x46, 0x0D, 0xF1, 0x30, 0x0C, ++0x07, 0x9B, 0x8C, 0xE8, 0x03, 0x00, 0x08, 0x22, 0x61, 0x46, 0x30, 0x46, 0x03, 0xF1, 0x5C, 0x08, 0x0C, 0xF0, 0xA8, 0xF9, ++0x7F, 0x4B, 0xD3, 0xE9, 0x02, 0x01, 0x08, 0x22, 0x0E, 0xAB, 0x83, 0xE8, 0x03, 0x00, 0xC8, 0x44, 0x19, 0x46, 0xB0, 0x18, ++0x0C, 0xF0, 0x9C, 0xF9, 0x06, 0x22, 0x41, 0x46, 0x06, 0xF1, 0x10, 0x00, 0x0C, 0xF0, 0x96, 0xF9, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x05, 0x95, 0x9D, 0xF9, 0x18, 0x20, 0xD5, 0xF8, 0xC4, 0x34, 0xB3, 0x75, 0xD5, 0xF8, 0xC4, 0x34, 0x1B, 0x0A, ++0xF3, 0x75, 0xB5, 0xF8, 0xC6, 0x34, 0x33, 0x76, 0x95, 0xF8, 0xC7, 0x34, 0x73, 0x76, 0x7B, 0x78, 0x58, 0x06, 0x67, 0xD4, ++0x00, 0x2A, 0xB8, 0xBF, 0x07, 0xF1, 0x2A, 0x01, 0x4F, 0xF0, 0x0A, 0x02, 0xA8, 0xBF, 0x07, 0xF1, 0x28, 0x01, 0x06, 0xF1, ++0x1A, 0x00, 0x0C, 0xF0, 0x73, 0xF9, 0xE2, 0x6C, 0x94, 0xF8, 0x35, 0x50, 0x53, 0x6A, 0x02, 0x99, 0xA4, 0x65, 0x24, 0x35, ++0x0D, 0x44, 0x01, 0x3B, 0x2B, 0x44, 0x00, 0x20, 0x29, 0x1D, 0x60, 0x65, 0xC2, 0xE9, 0x0A, 0x31, 0x03, 0x9B, 0x6B, 0xB1, ++0x04, 0x9B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0xB3, 0x93, 0xF8, 0x23, 0x30, 0x02, 0xFB, 0x03, 0xBB, 0x9B, 0xF8, ++0xA5, 0x91, 0xB9, 0xF1, 0x21, 0x0F, 0x6A, 0xD1, 0x7B, 0x78, 0x59, 0x06, 0x2F, 0xD5, 0x9A, 0xF8, 0x60, 0x30, 0x01, 0x2B, ++0x00, 0xF0, 0x53, 0x81, 0x52, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x09, 0xD5, 0x9A, 0xF8, 0x60, 0x30, 0x01, 0x2B, ++0x0A, 0xF1, 0x64, 0x09, 0x40, 0xF2, 0x36, 0x81, 0x03, 0x2B, 0x00, 0xF0, 0x34, 0x81, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, ++0x8F, 0xF8, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x96, 0xF8, 0x23, 0x20, 0x08, 0xFB, 0x02, 0xB8, 0x6F, 0xF0, 0x77, 0x02, ++0xB8, 0xF8, 0x34, 0x11, 0x83, 0xF8, 0x68, 0x20, 0x4A, 0x1C, 0x01, 0x20, 0xC2, 0xF3, 0x0B, 0x02, 0x83, 0xF8, 0x69, 0x00, ++0x09, 0x91, 0x03, 0x90, 0xA8, 0xF8, 0x34, 0x21, 0x21, 0xE7, 0x3D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9A, 0x07, 0xDE, 0xD5, ++0xBA, 0xF1, 0x00, 0x0F, 0xDB, 0xD0, 0xD0, 0xE7, 0x00, 0x2A, 0xB8, 0xBF, 0x07, 0xF1, 0x32, 0x01, 0x4F, 0xF0, 0x0A, 0x02, ++0xA8, 0xBF, 0x07, 0xF1, 0x30, 0x01, 0x06, 0xF1, 0x1A, 0x00, 0x0C, 0xF0, 0x0B, 0xF9, 0x96, 0xE7, 0xE2, 0x6C, 0xB3, 0xF8, ++0x68, 0x10, 0x90, 0x6B, 0x41, 0xF4, 0x80, 0x41, 0xC2, 0x68, 0xA3, 0xF8, 0x68, 0x10, 0x22, 0xF4, 0x7F, 0x73, 0x9A, 0xF8, ++0x62, 0x20, 0x08, 0x99, 0x23, 0xF0, 0x03, 0x03, 0x13, 0x43, 0xC3, 0x60, 0x9A, 0xF8, 0x60, 0x30, 0x02, 0x98, 0x0E, 0x18, ++0x04, 0x2B, 0x00, 0xF2, 0xD3, 0x81, 0xDF, 0xE8, 0x03, 0xF0, 0x1E, 0x51, 0xBA, 0x1E, 0x85, 0x00, 0x18, 0x22, 0x02, 0x92, ++0x21, 0xE7, 0x4F, 0xEA, 0x09, 0x20, 0x40, 0xF0, 0x08, 0x00, 0xF7, 0xF7, 0xFD, 0xFF, 0x01, 0x28, 0x8C, 0xD1, 0x1E, 0x4B, ++0x09, 0x99, 0x09, 0xEB, 0x49, 0x09, 0x03, 0xEB, 0xC9, 0x09, 0x02, 0x22, 0xD9, 0xF8, 0x14, 0x00, 0x02, 0x90, 0x05, 0xF0, ++0x1D, 0xFB, 0x02, 0x98, 0x05, 0xF0, 0xF8, 0xFA, 0x7C, 0xE7, 0x04, 0x23, 0x84, 0xF8, 0x33, 0x30, 0x84, 0xF8, 0x35, 0x30, ++0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, ++0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0xBD, 0xF8, 0x02, 0x99, 0x08, 0x9A, 0xBD, 0xF8, 0x28, 0x30, 0x53, 0x52, ++0xBD, 0xF8, 0x2A, 0x30, 0x9A, 0xF8, 0x61, 0x20, 0x43, 0xEA, 0x82, 0x33, 0x73, 0x80, 0x94, 0xF8, 0x33, 0x30, 0xCB, 0x18, ++0x02, 0x93, 0xF0, 0xE6, 0x88, 0x1A, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x8C, 0xBC, 0x15, 0x00, 0x34, 0x36, 0x17, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x08, 0x22, 0x0C, 0x23, 0x84, 0xF8, 0x33, 0x20, ++0x84, 0xF8, 0x35, 0x30, 0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, ++0xE3, 0xE9, 0x12, 0x01, 0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0x89, 0xF8, 0xBD, 0xF8, 0x28, 0x20, 0x02, 0x99, ++0x42, 0xF4, 0x00, 0x53, 0x03, 0xF4, 0xFE, 0x43, 0x43, 0xEA, 0x12, 0x23, 0x08, 0x9A, 0x53, 0x52, 0x9D, 0xF8, 0x28, 0x30, ++0x9A, 0xF8, 0x61, 0x20, 0x43, 0xEA, 0x82, 0x33, 0x43, 0xF4, 0x00, 0x53, 0x73, 0x80, 0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, ++0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0x94, 0xF8, 0x33, 0x30, 0xCB, 0x18, 0x02, 0x93, 0xAE, 0xE6, 0x10, 0x23, 0x12, 0x21, ++0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x35, 0x30, 0x0F, 0x2A, 0xDA, 0xF8, 0x48, 0x30, 0xDA, 0xF8, 0x4C, 0x20, 0x40, 0xF2, ++0x00, 0x81, 0x02, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, 0x08, 0x22, ++0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0x50, 0xF8, 0x9A, 0xF8, 0x61, 0x30, 0x33, 0x80, 0xBD, 0xF8, 0x28, 0x30, 0x73, 0x80, ++0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, 0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0xBD, 0xF8, 0x2E, 0x30, 0x33, 0x81, 0x45, 0xF6, ++0x36, 0x43, 0x73, 0x81, 0xB3, 0x81, 0xF3, 0x81, 0x33, 0x82, 0x02, 0x9A, 0x94, 0xF8, 0x33, 0x30, 0x1A, 0x44, 0x02, 0x92, ++0x79, 0xE6, 0x08, 0x23, 0x84, 0xF8, 0x33, 0x30, 0x84, 0xF8, 0x35, 0x30, 0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, ++0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, 0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, ++0x21, 0xF8, 0x08, 0x9A, 0xBD, 0xF8, 0x28, 0x30, 0x10, 0x46, 0x02, 0x9A, 0x83, 0x52, 0x9A, 0xF8, 0x61, 0x30, 0x9B, 0x03, ++0x43, 0xF4, 0x00, 0x53, 0x73, 0x80, 0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, 0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0x94, 0xF8, ++0x33, 0x30, 0xD3, 0x18, 0x02, 0x93, 0x4E, 0xE6, 0x31, 0xD0, 0x03, 0x9B, 0x0D, 0xF1, 0x40, 0x0B, 0x00, 0x2B, 0x5D, 0xD1, ++0x94, 0xF8, 0x33, 0x70, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xEC, 0x37, 0x2F, 0x44, 0xBF, 0xB2, ++0x5C, 0xE0, 0x05, 0x99, 0x06, 0x22, 0x04, 0xF1, 0x0C, 0x00, 0x0B, 0xF0, 0xF3, 0xFF, 0x06, 0x22, 0x41, 0x46, 0x04, 0xF1, ++0x12, 0x00, 0x0B, 0xF0, 0xED, 0xFF, 0x03, 0x9B, 0x00, 0x22, 0xE2, 0x76, 0x00, 0x2B, 0x78, 0xD0, 0x94, 0xF8, 0x35, 0x10, ++0x94, 0xF8, 0x33, 0x30, 0x69, 0x48, 0x0B, 0x44, 0xEB, 0x1A, 0xD0, 0xF8, 0x7C, 0x73, 0x00, 0x92, 0x1A, 0x3B, 0x32, 0x46, ++0x0A, 0xF1, 0x50, 0x01, 0x20, 0x46, 0xB8, 0x47, 0x8A, 0xE6, 0x03, 0x9B, 0x94, 0xF8, 0x33, 0x70, 0x00, 0x2B, 0x00, 0xF0, ++0x82, 0x80, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xF2, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, ++0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x30, 0x46, 0xDA, 0xF7, 0x7E, 0xFE, 0xDA, 0xF8, 0x48, 0xC0, 0xDA, 0xF8, 0x4C, 0x00, ++0x57, 0x49, 0x4F, 0xEA, 0x1C, 0x43, 0x43, 0xEA, 0x00, 0x43, 0x0D, 0xF1, 0x40, 0x0B, 0x0B, 0x60, 0x42, 0x46, 0x5B, 0x46, ++0x48, 0x46, 0xA1, 0xF8, 0x04, 0xC0, 0xF7, 0xF7, 0x45, 0xF8, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0x05, 0xFA, 0x9A, 0xF8, ++0x60, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x85, 0x80, 0x94, 0xF8, 0x33, 0x70, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, ++0x7F, 0x47, 0xEA, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x39, 0x1F, 0x30, 0x46, 0xDA, 0xF7, ++0x51, 0xFE, 0x9A, 0xF8, 0x60, 0x30, 0xBA, 0xF8, 0x48, 0x10, 0xBA, 0xF8, 0x4A, 0x20, 0xAD, 0xF8, 0x40, 0x10, 0x8D, 0xF8, ++0x42, 0x20, 0x49, 0x46, 0x7B, 0xBB, 0x05, 0x22, 0x0D, 0xF1, 0x43, 0x00, 0x0B, 0xF0, 0x84, 0xFF, 0x58, 0x46, 0x08, 0x21, ++0xF7, 0xF7, 0xDA, 0xF9, 0x03, 0x20, 0xDA, 0xF7, 0x71, 0xFE, 0x39, 0x46, 0x02, 0x46, 0x30, 0x46, 0xF7, 0xF7, 0x04, 0xF8, ++0x39, 0x46, 0x30, 0x46, 0xF7, 0xF7, 0xFA, 0xF9, 0x20, 0x46, 0x05, 0x21, 0xE4, 0xF7, 0xC6, 0xFE, 0x35, 0xE6, 0x94, 0xF8, ++0x35, 0x20, 0x94, 0xF8, 0x33, 0x30, 0x2D, 0x49, 0x13, 0x44, 0xD1, 0xF8, 0x7C, 0x73, 0x03, 0x99, 0x00, 0x91, 0xEB, 0x1A, ++0x18, 0x3B, 0x32, 0x46, 0x0A, 0xF1, 0x50, 0x01, 0x20, 0x46, 0xB8, 0x47, 0x10, 0xE6, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, ++0xFE, 0xE6, 0x0D, 0x22, 0x0D, 0xF1, 0x43, 0x00, 0x0B, 0xF0, 0x54, 0xFF, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0xAA, 0xF9, ++0xCE, 0xE7, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xF4, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, ++0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x30, 0x46, 0xDA, 0xF7, 0xFC, 0xFD, 0xDA, 0xF8, 0x48, 0xC0, 0xDA, 0xF8, 0x4C, 0x00, ++0x16, 0x49, 0x4F, 0xEA, 0x1C, 0x43, 0x43, 0xEA, 0x00, 0x43, 0x0D, 0xF1, 0x40, 0x0B, 0x0B, 0x60, 0x42, 0x46, 0x5B, 0x46, ++0x48, 0x46, 0xA1, 0xF8, 0x04, 0xC0, 0xF6, 0xF7, 0xC3, 0xFF, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0x83, 0xF9, 0x9A, 0xF8, ++0x60, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x20, 0xAF, 0x03, 0x2B, 0xA1, 0xD1, 0x1C, 0xE7, 0x03, 0x2B, 0x9E, 0xD1, 0x77, 0xE7, ++0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xDC, 0xAE, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, ++0x2C, 0x62, 0xF9, 0xF7, 0x6B, 0xFC, 0xD4, 0xE6, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x34, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x05, 0xDB, 0x0A, 0x4B, 0x00, 0x20, 0x5B, 0x68, 0x98, 0x47, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x10, 0xFE, ++0x02, 0x28, 0xF4, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x31, 0x12, 0xF9, 0xF7, 0x48, 0xFC, 0xED, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xC0, 0xBC, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x0C, 0x46, 0x36, 0x49, 0x60, 0x7C, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x10, 0x86, 0xB0, 0x90, 0xF8, 0x62, 0x10, ++0x00, 0x25, 0x02, 0x29, 0x98, 0x46, 0x8D, 0xF8, 0x0B, 0x50, 0x10, 0xD0, 0x04, 0x25, 0x41, 0x46, 0x02, 0x23, 0x41, 0xF6, ++0x05, 0x40, 0xF7, 0xF7, 0x43, 0xFB, 0x05, 0x70, 0x9D, 0xF8, 0x0B, 0x20, 0x42, 0x70, 0xF7, 0xF7, 0x6D, 0xFB, 0x00, 0x20, ++0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x90, 0xF8, 0x64, 0x10, 0x09, 0xB1, 0x08, 0x25, 0xEA, 0xE7, 0x07, 0x20, 0x01, 0x92, ++0xF7, 0xF7, 0xD2, 0xFD, 0x01, 0x9A, 0x00, 0x28, 0xF6, 0xD1, 0xA7, 0x78, 0x20, 0x7C, 0x21, 0x88, 0x1F, 0x4E, 0x8D, 0xF8, ++0x0C, 0x70, 0x8D, 0xF8, 0x0D, 0x00, 0xA7, 0x68, 0xE0, 0x68, 0xAD, 0xF8, 0x0E, 0x10, 0x21, 0x79, 0x75, 0x6C, 0xAD, 0xF8, ++0x12, 0x00, 0x8D, 0xF8, 0x14, 0x10, 0xAD, 0xF8, 0x10, 0x70, 0x0D, 0xF1, 0x0B, 0x01, 0x03, 0xA8, 0xA8, 0x47, 0x01, 0x9A, ++0x05, 0x46, 0x10, 0xBB, 0xF6, 0x6C, 0x60, 0x7C, 0x9D, 0xF8, 0x0B, 0x10, 0xB0, 0x47, 0xEF, 0xF3, 0x10, 0x81, 0x11, 0xF0, ++0x01, 0x0F, 0x01, 0x9A, 0x03, 0xD1, 0x72, 0xB6, 0x0E, 0x49, 0x01, 0x20, 0x08, 0x60, 0x0E, 0x48, 0x0E, 0x4F, 0x04, 0x68, ++0x79, 0x68, 0x66, 0x1C, 0x41, 0xF0, 0x10, 0x01, 0x06, 0x60, 0x79, 0x60, 0x00, 0x2E, 0xAE, 0xD0, 0x07, 0x49, 0x04, 0x60, ++0x09, 0x68, 0x00, 0x2C, 0xA9, 0xD1, 0x00, 0x29, 0xA7, 0xD0, 0x62, 0xB6, 0xA5, 0xE7, 0x01, 0x25, 0xA3, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x43, 0x0C, 0x46, 0x85, 0xB0, 0x90, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x4A, 0x69, 0x4D, 0x49, 0x4E, 0x4F, ++0x99, 0x46, 0xF9, 0xF7, 0x8D, 0xF9, 0x94, 0xF8, 0x33, 0x60, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x06, 0x75, 0x95, 0xF8, ++0x62, 0x10, 0x02, 0x29, 0x11, 0xD0, 0x04, 0x25, 0x42, 0x46, 0x49, 0x46, 0x04, 0x23, 0x41, 0xF6, 0x01, 0x40, 0xF7, 0xF7, ++0xC3, 0xFA, 0x05, 0x70, 0x94, 0xF8, 0x33, 0x20, 0x42, 0x70, 0xF7, 0xF7, 0xED, 0xFA, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x83, 0x07, 0x20, 0xF7, 0xF7, 0x58, 0xFD, 0xC0, 0xB9, 0x95, 0xF8, 0x64, 0x30, 0xBB, 0xB9, 0x3B, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x13, 0xDB, 0x23, 0x7F, 0x39, 0x49, 0x00, 0x93, 0xD4, 0xE9, 0x05, 0x23, 0x0C, 0x60, ++0x0D, 0xF1, 0x0D, 0x00, 0x04, 0xF1, 0x0E, 0x01, 0xFD, 0xF7, 0xAC, 0xF9, 0x05, 0x46, 0x70, 0xB1, 0x01, 0x25, 0xD1, 0xE7, ++0x08, 0x25, 0xCF, 0xE7, 0x09, 0x25, 0xCD, 0xE7, 0x2B, 0x6C, 0x00, 0x2B, 0xE8, 0xD0, 0x2F, 0x49, 0x2F, 0x48, 0x56, 0x22, ++0xF9, 0xF7, 0x72, 0xFB, 0xE2, 0xE7, 0xE1, 0x89, 0x20, 0x7C, 0xDF, 0xF8, 0xB4, 0x80, 0xFB, 0xF7, 0x9B, 0xFF, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x06, 0xF2, 0x07, 0xEB, 0x02, 0x09, 0xC9, 0xF8, 0x90, 0x01, 0x94, 0xF9, 0x12, 0x30, 0x03, 0x71, ++0xD4, 0xE9, 0x05, 0x31, 0xA9, 0xF8, 0x96, 0x11, 0xA9, 0xF8, 0x94, 0x31, 0x23, 0x7F, 0x89, 0xF8, 0xC5, 0x31, 0x04, 0x2B, ++0x08, 0xBF, 0x03, 0x23, 0x89, 0xF8, 0xC4, 0x31, 0x89, 0xF8, 0xC6, 0x51, 0xD8, 0xF8, 0x4C, 0x30, 0x94, 0xF8, 0x33, 0x00, ++0x9D, 0xF8, 0x0D, 0x10, 0x15, 0x46, 0x98, 0x47, 0x23, 0x7C, 0xA3, 0xB1, 0x00, 0xF0, 0x8C, 0xFA, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x06, 0x73, 0x78, 0x19, 0xD3, 0xF8, 0x90, 0x31, 0xD8, 0xF8, 0x40, 0x43, 0x1B, 0x79, 0x8D, 0xF8, 0x0E, 0x30, ++0x0D, 0xF1, 0x0F, 0x02, 0x0D, 0xF1, 0x0E, 0x01, 0xA0, 0x47, 0x01, 0x20, 0x92, 0xE7, 0x05, 0xF5, 0xCE, 0x70, 0x38, 0x44, ++0x01, 0x21, 0xFC, 0xF7, 0x45, 0xF9, 0x10, 0xF0, 0x0F, 0x00, 0x1A, 0xBF, 0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x1F, 0x03, ++0x01, 0x23, 0x89, 0xF8, 0xC1, 0x31, 0xD9, 0xE7, 0xEC, 0xBC, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x94, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x4F, 0x88, ++0x0D, 0x48, 0x0C, 0x46, 0x16, 0x46, 0x04, 0x31, 0x3A, 0x46, 0x1D, 0x46, 0x0B, 0xF0, 0xAE, 0xFD, 0xDF, 0xF8, 0x28, 0xC0, ++0x32, 0x46, 0x29, 0x46, 0x02, 0x23, 0x41, 0xF6, 0x09, 0x40, 0xAC, 0xF8, 0x00, 0x70, 0xF7, 0xF7, 0x1B, 0xFA, 0x01, 0x22, ++0x02, 0x70, 0x22, 0x78, 0x42, 0x70, 0xF7, 0xF7, 0x45, 0xFA, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x14, 0x2A, 0x17, 0x00, ++0x14, 0x2C, 0x17, 0x00, 0x08, 0xB5, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x07, 0x20, ++0xF7, 0xF7, 0xA6, 0xFC, 0x01, 0x28, 0x06, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0xA1, 0xFC, 0x03, 0x28, 0x01, 0xD0, 0x00, 0x20, ++0x08, 0xBD, 0x00, 0xF0, 0x01, 0xFA, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x96, 0xFC, 0x01, 0x28, 0xEA, 0xD0, ++0x07, 0x20, 0xF7, 0xF7, 0x91, 0xFC, 0x00, 0x28, 0xE5, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x8C, 0xFC, 0x03, 0x28, 0xE0, 0xD0, ++0x03, 0x49, 0x04, 0x48, 0xC2, 0x22, 0xF9, 0xF7, 0xC5, 0xFA, 0xDA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xFC, 0xBC, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, ++0xDB, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x70, 0xFC, 0x01, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, ++0xE6, 0x22, 0xF9, 0xF7, 0xA9, 0xFA, 0x00, 0xF0, 0xCD, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0xBD, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x03, 0xDB, 0x00, 0xF0, 0xBB, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x50, 0xFC, 0x03, 0x28, 0xF6, 0xD0, ++0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0xF9, 0xF7, 0x88, 0xFA, 0x00, 0xF0, 0xAC, 0xF9, 0x00, 0x20, 0x08, 0xBD, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB4, 0xBD, 0x15, 0x00, 0x08, 0xB5, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x06, 0xDB, 0x07, 0x20, 0xF7, 0xF7, 0x34, 0xFC, 0x03, 0x28, 0x12, 0xD0, 0x00, 0x20, 0x08, 0xBD, ++0x07, 0x20, 0xF7, 0xF7, 0x2D, 0xFC, 0x03, 0x28, 0xF3, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x28, 0xFC, 0x00, 0x28, 0xEE, 0xD0, ++0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0x65, 0x12, 0xF9, 0xF7, 0x60, 0xFA, 0xE7, 0xE7, 0x00, 0xF0, 0x83, 0xF9, 0x00, 0x20, ++0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xDC, 0xBD, 0x15, 0x00, 0xF8, 0xB5, 0x0C, 0x46, ++0x4F, 0xF4, 0x80, 0x70, 0x13, 0x49, 0x16, 0x46, 0x1D, 0x46, 0xF9, 0xF7, 0x21, 0xF8, 0x24, 0x78, 0x11, 0x4B, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, 0x62, 0x70, 0x02, 0x2F, 0x02, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x3B, 0xB9, ++0x32, 0x46, 0x29, 0x46, 0x41, 0xF6, 0x03, 0x40, 0xF7, 0xF7, 0xBE, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x07, 0x20, 0xF7, 0xF7, ++0xF3, 0xFB, 0x05, 0x46, 0x28, 0xB9, 0x06, 0x4B, 0x20, 0x46, 0x9B, 0x68, 0x98, 0x47, 0x28, 0x46, 0xF8, 0xBD, 0x38, 0x46, ++0xF8, 0xBD, 0x00, 0xBF, 0x30, 0xBE, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0C, 0x46, ++0x21, 0x49, 0x20, 0x78, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x10, 0x82, 0xB0, 0x90, 0xF8, 0x62, 0x50, 0x02, 0x2D, ++0x19, 0x46, 0x06, 0xD0, 0x41, 0xF6, 0x07, 0x40, 0xF7, 0xF7, 0x96, 0xF9, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x90, 0xF8, ++0x64, 0x30, 0x00, 0x2B, 0xF4, 0xD1, 0x07, 0x20, 0xCD, 0xE9, 0x00, 0x21, 0xF7, 0xF7, 0xC4, 0xFB, 0xDD, 0xE9, 0x00, 0x21, ++0x00, 0x28, 0xEB, 0xD1, 0x12, 0x4B, 0x20, 0x78, 0x5B, 0x6D, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0x13, 0xF0, 0x01, 0x0F, ++0xDD, 0xE9, 0x00, 0x21, 0x03, 0xD1, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x0D, 0x48, 0x0D, 0x4E, 0x04, 0x68, ++0x73, 0x68, 0x65, 0x1C, 0x23, 0xF0, 0x10, 0x03, 0x05, 0x60, 0x73, 0x60, 0x00, 0x2D, 0xD1, 0xD0, 0x06, 0x4B, 0x04, 0x60, ++0x1B, 0x68, 0x00, 0x2C, 0xCC, 0xD1, 0x00, 0x2B, 0xCA, 0xD0, 0x62, 0xB6, 0xC8, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x22, 0x4C, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0x07, 0x20, 0xF7, 0xF7, 0x88, 0xFB, 0x01, 0x28, 0x13, 0xD1, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0x9B, 0xF9, 0x00, 0x20, 0x10, 0xBD, 0x19, 0x4B, ++0x5B, 0x68, 0x00, 0x2B, 0xF7, 0xD0, 0x18, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x0B, 0x12, 0xF9, 0xF7, 0xB3, 0xF9, 0xF0, 0xE7, ++0x07, 0x20, 0xF7, 0xF7, 0x6F, 0xFB, 0x03, 0x28, 0xED, 0xD1, 0x07, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x03, 0x40, 0xF7, 0xF7, ++0x2D, 0xF9, 0x00, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0xBB, 0xFA, 0xE2, 0xE7, 0x07, 0x20, 0xF7, 0xF7, 0x5F, 0xFB, 0x01, 0x28, ++0xD1, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x5A, 0xFB, 0x00, 0x28, 0xCC, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x55, 0xFB, 0x03, 0x28, ++0xC7, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x03, 0x12, 0xF9, 0xF7, 0x8D, 0xF9, 0xC0, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x94, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0xBE, 0x15, 0x00, 0xFC, 0xBC, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x08, 0x40, 0x09, 0x48, 0xF7, 0xF7, 0x1E, 0xBD, ++0x08, 0x4B, 0x5B, 0x68, 0x00, 0x2B, 0xF6, 0xD0, 0x07, 0x48, 0x08, 0x49, 0x2D, 0x22, 0xF9, 0xF7, 0x6D, 0xF9, 0xBD, 0xE8, ++0x08, 0x40, 0x02, 0x48, 0xF7, 0xF7, 0x10, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x98, 0xBA, 0x17, 0x00, 0x94, 0xBA, 0x17, 0x00, ++0x3C, 0xBE, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0x00, 0x21, 0x20, 0x46, 0x10, 0x22, 0xD4, 0xF7, ++0x6F, 0xFC, 0x00, 0x21, 0x21, 0x73, 0x07, 0x20, 0xBD, 0xE8, 0x10, 0x40, 0xF7, 0xF7, 0x68, 0xBA, 0x94, 0xBA, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0xD8, 0x80, 0x05, 0x46, 0x04, 0x23, 0x07, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x01, 0x40, ++0xD8, 0xF8, 0x00, 0x60, 0xF7, 0xF7, 0x5E, 0xF8, 0x04, 0x46, 0x95, 0xB1, 0x96, 0xF8, 0x33, 0x30, 0x63, 0x70, 0x20, 0x46, ++0x25, 0x70, 0xF7, 0xF7, 0x85, 0xF8, 0xA6, 0xF1, 0x0C, 0x00, 0xF7, 0xF7, 0xCD, 0xF8, 0x00, 0x21, 0xC8, 0xF8, 0x00, 0x10, ++0x07, 0x20, 0xBD, 0xE8, 0xF0, 0x47, 0xF7, 0xF7, 0x43, 0xBA, 0x04, 0x23, 0x29, 0x46, 0x07, 0x22, 0x1E, 0x20, 0x96, 0xF8, ++0x33, 0x70, 0xF7, 0xF7, 0x41, 0xF8, 0x21, 0x4A, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x07, 0x29, 0x4F, 0xF0, 0x01, 0x0A, ++0x80, 0xF8, 0x02, 0xA0, 0x99, 0xF8, 0x63, 0x20, 0xC2, 0x70, 0xF7, 0xF7, 0x63, 0xF8, 0xF1, 0x6A, 0x32, 0x8E, 0xD9, 0xF8, ++0x40, 0x30, 0xC9, 0xF8, 0xB0, 0x14, 0xA9, 0xF8, 0xE0, 0x20, 0x89, 0xF8, 0xDE, 0x50, 0x1B, 0x7E, 0xA3, 0x70, 0x96, 0xF8, ++0x33, 0x30, 0xDF, 0xF8, 0x54, 0xC0, 0x0A, 0x33, 0xE3, 0x70, 0x96, 0xE8, 0x0F, 0x00, 0x4F, 0xF4, 0x1E, 0x7E, 0x0A, 0x37, ++0x0E, 0xFB, 0x07, 0xC7, 0x07, 0xF1, 0xB8, 0x0C, 0xAC, 0xE8, 0x07, 0x00, 0x02, 0x22, 0x87, 0xF8, 0x30, 0x20, 0x8C, 0xF8, ++0x00, 0x30, 0x38, 0x46, 0xFB, 0xF7, 0xA0, 0xFF, 0x97, 0xF8, 0x56, 0x31, 0xA7, 0xF8, 0x26, 0xA0, 0x43, 0xF0, 0x10, 0x03, ++0x87, 0xF8, 0x56, 0x31, 0x96, 0xF8, 0x33, 0x30, 0x03, 0xF1, 0x0A, 0x02, 0x87, 0xF8, 0x23, 0x20, 0xA4, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x94, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x48, 0xF7, 0xF7, 0xC6, 0xFC, ++0x0B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x05, 0xDB, 0x04, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, ++0x10, 0x40, 0xF7, 0xF7, 0x17, 0xB8, 0x00, 0x28, 0xF7, 0xD1, 0x05, 0x49, 0x05, 0x48, 0xCB, 0x22, 0xF9, 0xF7, 0xC2, 0xF8, ++0xF1, 0xE7, 0x00, 0xBF, 0x98, 0xBA, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x4F, 0x44, 0x4B, 0xDF, 0xF8, 0x1C, 0xB1, 0x1C, 0x68, 0x07, 0x22, 0x08, 0x23, 0x00, 0x21, 0x18, 0x20, ++0x94, 0xF8, 0x33, 0x90, 0xF6, 0xF7, 0xC8, 0xFF, 0x08, 0x23, 0x07, 0x22, 0x00, 0x21, 0x06, 0x46, 0x16, 0x20, 0xF6, 0xF7, ++0xC1, 0xFF, 0x04, 0x23, 0x07, 0x22, 0x00, 0x21, 0x05, 0x46, 0x14, 0x20, 0xF6, 0xF7, 0xBA, 0xFF, 0x02, 0x23, 0x07, 0x22, ++0x05, 0x21, 0x80, 0x46, 0x41, 0xF2, 0x17, 0x40, 0xF6, 0xF7, 0xB2, 0xFF, 0x4F, 0xF4, 0xA4, 0x6A, 0x0A, 0xFB, 0x09, 0xBA, ++0x07, 0x46, 0xFF, 0xF7, 0x0B, 0xFF, 0x9A, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x49, 0xD0, 0x2F, 0x4A, 0x13, 0x68, 0x23, 0xF0, ++0x04, 0x03, 0x13, 0x60, 0xDA, 0xF8, 0x04, 0x30, 0x43, 0xF0, 0x20, 0x03, 0xCA, 0xF8, 0x04, 0x30, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x09, 0xB9, 0xA6, 0xF1, 0x0C, 0x01, 0xD9, 0xF8, 0x5C, 0x00, 0xB9, 0xF8, 0x60, 0x30, 0xB3, 0x80, 0x30, 0x60, ++0x94, 0xF8, 0x33, 0x30, 0xB3, 0x71, 0x23, 0x48, 0xF7, 0xF7, 0x18, 0xFC, 0x23, 0x7C, 0x6B, 0x71, 0x01, 0x21, 0x20, 0x46, ++0xFB, 0xF7, 0x80, 0xFE, 0x28, 0x60, 0x94, 0xF8, 0x33, 0x30, 0x2B, 0x71, 0xA5, 0xF1, 0x0C, 0x01, 0x1B, 0x48, 0xF7, 0xF7, ++0x09, 0xFC, 0x23, 0x8D, 0xA8, 0xF8, 0x00, 0x30, 0x94, 0xF8, 0x33, 0x30, 0x88, 0xF8, 0x02, 0x30, 0xA8, 0xF1, 0x0C, 0x01, ++0x01, 0x25, 0x15, 0x48, 0xF7, 0xF7, 0xFC, 0xFB, 0x3D, 0x70, 0x94, 0xF8, 0x33, 0x30, 0x12, 0x48, 0x7B, 0x70, 0xA7, 0xF1, ++0x0C, 0x01, 0xF7, 0xF7, 0xF3, 0xFB, 0xFF, 0xF7, 0x6B, 0xFF, 0x29, 0x46, 0x07, 0x20, 0xBD, 0xE8, 0xF8, 0x4F, 0xF7, 0xF7, ++0x57, 0xB9, 0x02, 0x23, 0x07, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF6, 0xF7, 0x56, 0xFF, 0x01, 0x23, 0x03, 0x70, ++0x9A, 0xF8, 0x63, 0x30, 0x43, 0x70, 0x03, 0x4B, 0x01, 0x46, 0x0C, 0x39, 0x18, 0x1D, 0xF7, 0xF7, 0xD9, 0xFB, 0xAD, 0xE7, ++0x94, 0xBA, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x98, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0xB5, 0x0E, 0x4C, ++0x0C, 0x23, 0x07, 0x22, 0x00, 0x21, 0x3F, 0x20, 0x24, 0x68, 0xF6, 0xF7, 0x39, 0xFF, 0xA1, 0x8C, 0xE2, 0x8C, 0x25, 0x6A, ++0x05, 0x60, 0x81, 0x80, 0xC2, 0x80, 0x94, 0xF8, 0x32, 0x20, 0x02, 0x72, 0x94, 0xF8, 0x33, 0x20, 0x42, 0x72, 0xF6, 0xF7, ++0x5B, 0xFF, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0x1F, 0xB9, 0x00, 0xBF, 0x94, 0xBA, 0x17, 0x00, ++0xF8, 0xB5, 0x07, 0x22, 0x04, 0x46, 0x02, 0x23, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF6, 0xF7, 0x19, 0xFF, 0x02, 0x23, ++0x06, 0x46, 0x07, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x17, 0x40, 0xF6, 0xF7, 0x11, 0xFF, 0x00, 0x27, 0x05, 0x46, 0xFF, 0xF7, ++0x6D, 0xFE, 0x37, 0x70, 0x94, 0xF8, 0x63, 0x30, 0x73, 0x70, 0x1D, 0x48, 0xA6, 0xF1, 0x0C, 0x01, 0xF7, 0xF7, 0x92, 0xFB, ++0x94, 0xF8, 0x64, 0x30, 0x0B, 0xBB, 0x23, 0x6C, 0x6B, 0xB1, 0x01, 0x23, 0x00, 0x21, 0x07, 0x22, 0x39, 0x20, 0xF6, 0xF7, ++0xF9, 0xFE, 0x01, 0x46, 0x94, 0xF8, 0x63, 0x30, 0x01, 0xF8, 0x0C, 0x39, 0x12, 0x48, 0xF7, 0xF7, 0x7F, 0xFB, 0x00, 0x23, ++0x2B, 0x70, 0x94, 0xF8, 0x63, 0x30, 0x0F, 0x48, 0x6B, 0x70, 0xA5, 0xF1, 0x0C, 0x01, 0xF7, 0xF7, 0x75, 0xFB, 0xFF, 0xF7, ++0xED, 0xFE, 0xBD, 0xE8, 0xF8, 0x40, 0x03, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0xD9, 0xB8, 0x39, 0x46, 0x04, 0x23, 0x07, 0x22, ++0x1E, 0x20, 0xF6, 0xF7, 0xD9, 0xFE, 0x87, 0x70, 0x94, 0xF8, 0x63, 0x30, 0xC3, 0x70, 0xA0, 0xF1, 0x0C, 0x01, 0x02, 0x48, ++0xF7, 0xF7, 0x5E, 0xFB, 0xCD, 0xE7, 0x00, 0xBF, 0x98, 0xBA, 0x17, 0x00, 0x15, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, ++0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x13, 0xD1, 0x43, 0x7F, 0x0D, 0x2B, 0x10, 0xD8, 0x82, 0x88, ++0x2A, 0xB9, 0x82, 0x6C, 0xB2, 0xF8, 0x68, 0x20, 0xB2, 0xF5, 0x12, 0x7F, 0x08, 0xD0, 0x0C, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, ++0x01, 0xFB, 0x03, 0x22, 0x92, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x02, 0xD0, 0x01, 0x23, 0x18, 0x46, 0x70, 0x47, 0x92, 0xF8, ++0x32, 0x20, 0x12, 0xF0, 0x03, 0x02, 0xF8, 0xD1, 0xC1, 0x8B, 0x41, 0xF4, 0x80, 0x51, 0x13, 0x46, 0xC1, 0x83, 0xF2, 0xE7, ++0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xC3, 0x8B, 0xDB, 0x04, 0x00, 0xD4, 0x70, 0x47, 0x10, 0xB5, 0x0C, 0x46, ++0xC2, 0x7E, 0x15, 0x49, 0x94, 0xF8, 0x2E, 0x31, 0x8A, 0x5C, 0x13, 0x42, 0x1A, 0xD0, 0x94, 0xF8, 0x31, 0x20, 0x11, 0x07, ++0x1A, 0xD4, 0x42, 0xF0, 0x08, 0x02, 0x0F, 0x2B, 0x84, 0xF8, 0x31, 0x20, 0x14, 0xD1, 0x05, 0x22, 0x04, 0x23, 0x00, 0x21, ++0x41, 0x20, 0xF6, 0xF7, 0x7F, 0xFE, 0x22, 0x8C, 0x02, 0x80, 0x94, 0xF8, 0x22, 0x20, 0xC2, 0x70, 0x01, 0x22, 0x82, 0x70, ++0xBD, 0xE8, 0x10, 0x40, 0xF6, 0xF7, 0xA4, 0xBE, 0x94, 0xF8, 0x31, 0x30, 0x9A, 0x07, 0x00, 0xD5, 0x10, 0xBD, 0x43, 0xF0, ++0x02, 0x03, 0x84, 0xF8, 0x31, 0x30, 0xE4, 0xE7, 0xA4, 0xB2, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x90, 0xF8, 0x62, 0x70, ++0x02, 0x2F, 0x91, 0x46, 0x5A, 0xD1, 0x91, 0xF8, 0x32, 0x20, 0x0E, 0x46, 0x00, 0x2A, 0x55, 0xD0, 0x12, 0xF0, 0x01, 0x08, ++0x91, 0xF8, 0x31, 0x30, 0x04, 0xBF, 0x08, 0x27, 0x4F, 0xF0, 0x04, 0x08, 0x1F, 0x42, 0x78, 0xD0, 0xD1, 0xF8, 0xFC, 0x41, ++0x00, 0x2C, 0x68, 0xD0, 0xA2, 0xF1, 0x02, 0x02, 0xB2, 0xFA, 0x82, 0xF2, 0x91, 0xF8, 0x2E, 0x11, 0x3C, 0x4D, 0x52, 0x09, ++0x4F, 0xF0, 0x00, 0x0A, 0x04, 0xE0, 0x23, 0x68, 0xA2, 0x46, 0x00, 0x2B, 0x59, 0xD0, 0x1C, 0x46, 0xE3, 0x7E, 0xEB, 0x5C, ++0x19, 0x42, 0x0C, 0xBF, 0x01, 0x23, 0x00, 0x23, 0x93, 0x42, 0xF2, 0xD0, 0x51, 0x46, 0x22, 0x46, 0x06, 0xF5, 0xFE, 0x70, ++0xF7, 0xF7, 0xC8, 0xFB, 0x96, 0xF8, 0x32, 0x10, 0x11, 0xF0, 0x08, 0x0F, 0x0C, 0xBF, 0x03, 0x23, 0x04, 0x23, 0xE3, 0x76, ++0xBA, 0xF1, 0x00, 0x0F, 0x52, 0xD0, 0xDA, 0xF8, 0x00, 0x30, 0x0B, 0xB3, 0xA1, 0xF1, 0x02, 0x01, 0xB1, 0xFA, 0x81, 0xF1, ++0x96, 0xF8, 0x2E, 0x01, 0x49, 0x09, 0x01, 0xE0, 0x1B, 0x68, 0xBB, 0xB1, 0xDA, 0x7E, 0xAA, 0x5C, 0x10, 0x42, 0x0C, 0xBF, ++0x01, 0x22, 0x00, 0x22, 0x8A, 0x42, 0xF5, 0xD0, 0xA2, 0x6C, 0xB2, 0xF8, 0x68, 0x30, 0x43, 0xF4, 0x00, 0x53, 0xA2, 0xF8, ++0x68, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x24, 0xC9, 0xF8, 0x00, 0x40, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, ++0x96, 0xF8, 0x31, 0x10, 0x21, 0xEA, 0x07, 0x07, 0x17, 0xEA, 0x08, 0x01, 0x86, 0xF8, 0x31, 0x70, 0x07, 0xEA, 0x08, 0x05, ++0xE4, 0xD1, 0x04, 0x23, 0x05, 0x22, 0x41, 0x20, 0xF6, 0xF7, 0xF0, 0xFD, 0x32, 0x8C, 0x02, 0x80, 0x96, 0xF8, 0x22, 0x20, ++0xC2, 0x70, 0x85, 0x70, 0xF6, 0xF7, 0x18, 0xFE, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0xDA, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0x91, 0x12, 0xF8, 0xF7, 0xD3, 0xFE, 0x01, 0x23, ++0x00, 0x24, 0xC9, 0xF8, 0x00, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0xFC, 0x31, 0xAB, 0xE7, 0x00, 0xBF, ++0xA4, 0xB2, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0xB5, 0x90, 0xF8, ++0x62, 0x30, 0x02, 0x2B, 0x14, 0xD1, 0x13, 0x4C, 0x13, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0x44, 0x21, 0x46, ++0xD3, 0xF8, 0x20, 0x33, 0x00, 0x22, 0x98, 0x47, 0x94, 0xF8, 0x31, 0x10, 0x11, 0xF0, 0x0A, 0x0F, 0x04, 0xD0, 0x01, 0xF0, ++0xF5, 0x05, 0x84, 0xF8, 0x31, 0x50, 0x05, 0xB1, 0x38, 0xBD, 0x29, 0x46, 0x04, 0x23, 0x05, 0x22, 0x41, 0x20, 0xF6, 0xF7, ++0xA5, 0xFD, 0x94, 0xF8, 0x22, 0x20, 0x21, 0x8C, 0xC2, 0x70, 0x85, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x01, 0x80, 0xF6, 0xF7, ++0xCB, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x03, 0x6C, 0x2D, 0xE9, 0xF0, 0x41, 0x04, 0x46, ++0x88, 0x46, 0x00, 0x2B, 0x6C, 0xD0, 0x3A, 0x4A, 0x1B, 0x79, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x53, 0xDB, ++0x94, 0xF8, 0xC0, 0x24, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE4, 0xF7, 0x4C, 0xF8, ++0x05, 0x46, 0x00, 0x28, 0x56, 0xD0, 0x01, 0x46, 0x20, 0x46, 0xF6, 0xF7, 0x43, 0xF9, 0xAE, 0x6C, 0x00, 0x27, 0x6F, 0xF0, ++0x3F, 0x03, 0x41, 0x46, 0x86, 0xF8, 0x68, 0x30, 0x86, 0xF8, 0x69, 0x70, 0x86, 0xF8, 0x6A, 0x70, 0x86, 0xF8, 0x6B, 0x70, ++0x06, 0xF1, 0x6C, 0x00, 0x06, 0x22, 0x0B, 0xF0, 0xED, 0xF8, 0x26, 0x4A, 0xE0, 0x6D, 0xB2, 0xF8, 0xFC, 0x31, 0xB4, 0xF8, ++0x60, 0x10, 0xB4, 0xF8, 0x60, 0xC0, 0xC6, 0xF8, 0x72, 0x00, 0x01, 0x33, 0x9B, 0xB2, 0xE0, 0x6D, 0xA6, 0xF8, 0x76, 0x10, ++0x19, 0x01, 0xB0, 0x67, 0xA6, 0xF8, 0x7C, 0xC0, 0xA2, 0xF8, 0xFC, 0x31, 0xA6, 0xF8, 0x7E, 0x10, 0xC5, 0xE9, 0x15, 0x74, ++0x94, 0xF8, 0x63, 0x30, 0x2B, 0x77, 0xFF, 0x23, 0x6B, 0x77, 0x06, 0xF1, 0x80, 0x00, 0x07, 0x21, 0xF9, 0xF7, 0xCE, 0xFD, ++0xE9, 0x6C, 0x4B, 0x6A, 0x17, 0x33, 0x1A, 0x18, 0x00, 0xF1, 0x1C, 0x03, 0xC1, 0xE9, 0x0A, 0x23, 0x28, 0x46, 0x05, 0x21, ++0xBD, 0xE8, 0xF0, 0x41, 0xE4, 0xF7, 0x12, 0xB8, 0x02, 0x2B, 0xA9, 0xD1, 0x0D, 0x49, 0x0E, 0x48, 0x4F, 0xF4, 0x09, 0x72, ++0xF8, 0xF7, 0x0E, 0xFE, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE3, 0xF7, 0xF5, 0xFF, 0x05, 0x46, 0x00, 0x28, 0xA8, 0xD1, ++0xBD, 0xE8, 0xF0, 0x81, 0x03, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEF, 0xDA, 0xE8, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0xF8, 0xB5, 0x14, 0x4A, ++0x14, 0x4D, 0x41, 0xF2, 0x0A, 0x00, 0x41, 0xF2, 0x08, 0x07, 0x00, 0x26, 0x16, 0x52, 0x0C, 0x46, 0xD3, 0x53, 0x41, 0xF2, ++0x0C, 0x06, 0xD1, 0xF8, 0x64, 0x11, 0xD4, 0xF8, 0x60, 0x01, 0x90, 0x51, 0x0B, 0x2B, 0x14, 0x60, 0xA9, 0x80, 0x0D, 0xD0, ++0x19, 0x46, 0x04, 0x22, 0x02, 0x23, 0x41, 0xF2, 0x09, 0x00, 0xF6, 0xF7, 0xF5, 0xFC, 0x01, 0x22, 0x42, 0x70, 0x94, 0xF8, ++0x6E, 0x21, 0x02, 0x70, 0xF6, 0xF7, 0x1E, 0xFD, 0x04, 0x4B, 0xD3, 0xF8, 0xF4, 0x32, 0x98, 0x47, 0x01, 0x20, 0xF8, 0xBD, ++0xA8, 0xBA, 0x17, 0x00, 0xB4, 0xCA, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1A, 0x46, 0x70, 0xB5, 0x40, 0x23, 0x14, 0x4C, ++0x0D, 0x46, 0x41, 0xF2, 0x06, 0x00, 0x11, 0x46, 0x04, 0x22, 0xF6, 0xF7, 0xD7, 0xFC, 0xA3, 0x88, 0x06, 0x46, 0x13, 0xB1, ++0x2A, 0x78, 0x93, 0x42, 0x06, 0xD8, 0x00, 0x23, 0x30, 0x46, 0x33, 0x70, 0xF6, 0xF7, 0xFC, 0xFC, 0x00, 0x20, 0x70, 0xBD, ++0x04, 0xEB, 0x82, 0x14, 0x08, 0x34, 0x0F, 0xCC, 0x35, 0x46, 0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, ++0x94, 0xE8, 0x0F, 0x00, 0x85, 0xE8, 0x0F, 0x00, 0x30, 0x46, 0xF6, 0xF7, 0xE9, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, ++0xA8, 0xBA, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x22, 0x01, 0x23, 0x02, 0x21, 0x40, 0xF6, 0x03, 0x00, 0xF6, 0xF7, 0xAC, 0xFC, ++0xF6, 0xF7, 0xDA, 0xFC, 0x04, 0x20, 0xF6, 0xF7, 0x49, 0xFF, 0x03, 0x49, 0x02, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x5A, 0xFB, ++0x00, 0x20, 0x08, 0xBD, 0x6C, 0xBE, 0x15, 0x00, 0x08, 0xB5, 0x19, 0x46, 0x04, 0x22, 0x01, 0x23, 0x41, 0xF2, 0x0B, 0x00, ++0xF6, 0xF7, 0x96, 0xFC, 0xF6, 0xF7, 0xC4, 0xFC, 0x02, 0x49, 0x08, 0x20, 0xF8, 0xF7, 0x48, 0xFB, 0x00, 0x20, 0x08, 0xBD, ++0x80, 0xBE, 0x15, 0x00, 0x1A, 0x46, 0x38, 0xB5, 0x41, 0xF2, 0x08, 0x00, 0x0D, 0x46, 0x02, 0x23, 0x11, 0x46, 0x04, 0x22, ++0xF6, 0xF7, 0x82, 0xFC, 0x06, 0x49, 0x04, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x35, 0xFB, 0x01, 0x23, 0x23, 0x70, 0xAB, 0x78, ++0x63, 0x70, 0x20, 0x46, 0xF6, 0xF7, 0xA6, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0x98, 0xBE, 0x15, 0x00, 0x10, 0xB5, 0x41, 0xF2, ++0x08, 0x00, 0x04, 0x4C, 0x04, 0x49, 0x1A, 0x46, 0x23, 0x5A, 0x08, 0x20, 0xF8, 0xF7, 0x20, 0xFB, 0x02, 0x20, 0x10, 0xBD, ++0xA8, 0xBA, 0x17, 0x00, 0xB4, 0xBE, 0x15, 0x00, 0xF8, 0xB5, 0x36, 0x4C, 0x91, 0xF8, 0x6E, 0x21, 0x35, 0x4E, 0x21, 0x60, ++0x0D, 0x46, 0x41, 0xF2, 0x08, 0x00, 0x4F, 0xF4, 0xA4, 0x67, 0x41, 0xF2, 0x0A, 0x01, 0x07, 0xFB, 0x02, 0x62, 0x01, 0x26, ++0x23, 0x52, 0x66, 0x52, 0x00, 0x23, 0xC2, 0xF8, 0xCC, 0x31, 0x05, 0xF5, 0xB0, 0x77, 0x97, 0xE8, 0x03, 0x00, 0xDF, 0xF8, ++0xC4, 0xC0, 0x41, 0xF2, 0x0C, 0x02, 0xAC, 0xF8, 0x04, 0x10, 0x41, 0xF2, 0x3B, 0x01, 0xA0, 0x50, 0x63, 0x54, 0x38, 0x46, ++0x1A, 0x46, 0x19, 0x46, 0x00, 0xF0, 0x4A, 0xF9, 0x18, 0xB1, 0x90, 0xF8, 0x3D, 0x10, 0x03, 0x46, 0x91, 0xB9, 0x97, 0xE8, ++0x03, 0x00, 0x21, 0x4B, 0x41, 0xF2, 0x34, 0x02, 0x99, 0x80, 0x20, 0x4B, 0xA0, 0x50, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x28, 0xDB, 0x1D, 0x4B, 0xD3, 0xF8, 0xF4, 0x32, 0x98, 0x47, 0x01, 0x20, 0xF8, 0xBD, 0x02, 0x46, 0x41, 0xF2, ++0x34, 0x0C, 0x52, 0xF8, 0x02, 0x0F, 0x93, 0xF8, 0x3E, 0x70, 0x44, 0xF8, 0x0C, 0x00, 0x14, 0x48, 0x92, 0x88, 0x82, 0x80, ++0xBE, 0x40, 0x41, 0xF2, 0x38, 0x00, 0x01, 0x3E, 0x22, 0x5A, 0x36, 0x02, 0x36, 0xB2, 0x22, 0xEA, 0x06, 0x02, 0x12, 0xB2, ++0x22, 0x52, 0xDB, 0x88, 0xA3, 0xEB, 0x01, 0x21, 0x0E, 0x40, 0x0C, 0x4B, 0x16, 0x43, 0x26, 0x52, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xD6, 0xDA, 0x95, 0xF8, 0x60, 0x31, 0xDB, 0x07, 0xD2, 0xD5, 0x08, 0x49, 0x08, 0x48, 0xA1, 0x22, ++0xF8, 0xF7, 0xD8, 0xFC, 0xCC, 0xE7, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xDC, 0xCA, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD0, 0xBE, 0x15, 0x00, 0xB4, 0xCA, 0x17, 0x00, ++0x1A, 0x46, 0x38, 0xB5, 0x41, 0xF2, 0x08, 0x00, 0x0D, 0x46, 0x02, 0x23, 0x11, 0x46, 0x04, 0x22, 0xF6, 0xF7, 0xDA, 0xFB, ++0x0A, 0x49, 0x04, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x8D, 0xFA, 0x29, 0x46, 0x08, 0x48, 0x31, 0xF8, 0x03, 0x2B, 0x20, 0xF8, ++0x03, 0x2B, 0x0A, 0xF0, 0x55, 0xFF, 0x01, 0x23, 0x23, 0x70, 0xAB, 0x78, 0x63, 0x70, 0x20, 0x46, 0xF6, 0xF7, 0xF6, 0xFB, ++0x00, 0x20, 0x38, 0xBD, 0xF0, 0xBE, 0x15, 0x00, 0x68, 0xCB, 0x17, 0x00, 0x08, 0x78, 0x08, 0xB9, 0x00, 0x20, 0x70, 0x47, ++0x08, 0xB5, 0x00, 0xF0, 0x31, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x70, 0xB5, 0x0B, 0x4E, 0x41, 0xF2, 0x08, 0x05, ++0x01, 0x23, 0x0C, 0x46, 0x04, 0x22, 0x71, 0x5B, 0x41, 0xF2, 0x0B, 0x00, 0xF6, 0xF7, 0xAA, 0xFB, 0xF6, 0xF7, 0xD8, 0xFB, ++0x72, 0x5B, 0x05, 0x49, 0x08, 0x20, 0xF8, 0xF7, 0x5B, 0xFA, 0x20, 0x78, 0x00, 0xF0, 0x18, 0xF8, 0x00, 0x20, 0x70, 0xBD, ++0xA8, 0xBA, 0x17, 0x00, 0x00, 0xBF, 0x15, 0x00, 0x08, 0xB5, 0x05, 0x49, 0x41, 0xF2, 0x0B, 0x02, 0x8B, 0x5C, 0x01, 0x33, ++0x8B, 0x54, 0x00, 0xF0, 0x65, 0xFD, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x08, 0x46, 0x00, 0xF0, ++0x19, 0xB9, 0x00, 0xBF, 0xF0, 0xB5, 0x39, 0x4C, 0x41, 0xF2, 0x0A, 0x05, 0x83, 0xB0, 0x63, 0x5D, 0x06, 0x46, 0x00, 0x2B, ++0x43, 0xD0, 0x41, 0xF2, 0x08, 0x02, 0x03, 0x23, 0xA1, 0x5A, 0x41, 0xF2, 0x03, 0x00, 0x04, 0x22, 0xF6, 0xF7, 0x76, 0xFB, ++0x05, 0x46, 0x23, 0x68, 0x30, 0x49, 0x93, 0xF8, 0x6E, 0x21, 0x00, 0x96, 0x41, 0xF2, 0x0A, 0x07, 0x08, 0x20, 0xE3, 0x5D, ++0xF8, 0xF7, 0x22, 0xFA, 0xE3, 0x5D, 0x63, 0xB9, 0x2B, 0x49, 0x2C, 0x4A, 0x0B, 0x68, 0x2C, 0x48, 0x23, 0xF0, 0x04, 0x03, ++0x0B, 0x60, 0x13, 0x68, 0x01, 0x88, 0x1B, 0x0C, 0x1B, 0x04, 0x0B, 0x43, 0x13, 0x60, 0x20, 0x68, 0x27, 0x4B, 0x90, 0xF8, ++0x6E, 0x21, 0x2A, 0x70, 0x6E, 0x70, 0xA2, 0x88, 0xAA, 0x70, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x20, 0xD0, 0x0C, 0x38, ++0xF6, 0xF7, 0xC8, 0xFB, 0x00, 0x26, 0x28, 0x46, 0x26, 0x60, 0xF6, 0xF7, 0x77, 0xFB, 0x1F, 0x4A, 0x53, 0x68, 0x31, 0x46, ++0x23, 0xF0, 0x20, 0x03, 0x04, 0x20, 0x53, 0x60, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xF6, 0xF7, 0x35, 0xBD, 0xA3, 0x88, ++0xF3, 0xB1, 0x41, 0xF2, 0x08, 0x02, 0x03, 0x23, 0xA1, 0x5A, 0x41, 0xF2, 0x01, 0x00, 0x04, 0x22, 0xF6, 0xF7, 0x30, 0xFB, ++0x05, 0x46, 0xB8, 0xE7, 0x13, 0x4B, 0x93, 0xF8, 0xB5, 0x30, 0x00, 0x2B, 0xD9, 0xD0, 0x12, 0x49, 0x12, 0x4B, 0x0A, 0x68, ++0x22, 0xF0, 0x7C, 0x72, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x12, ++0x1A, 0x60, 0xCA, 0xE7, 0xD6, 0xF7, 0xCC, 0xFB, 0x63, 0x5D, 0x00, 0x2B, 0xDB, 0xD0, 0x94, 0xE7, 0xA8, 0xBA, 0x17, 0x00, ++0x30, 0xBF, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x20, 0x04, 0x32, 0x40, 0x28, 0x25, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x00, 0x32, 0x40, 0x6C, 0x00, 0x32, 0x40, 0x08, 0xB5, 0x00, 0x21, ++0x04, 0x20, 0xF6, 0xF7, 0xF5, 0xFC, 0xBD, 0xE8, 0x08, 0x40, 0x03, 0x48, 0x4F, 0xF4, 0x86, 0x52, 0x00, 0x21, 0xD3, 0xF7, ++0xED, 0xBE, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x3C, 0x4D, 0x83, 0xB0, 0xA8, 0x46, 0x2B, 0x46, ++0x00, 0x22, 0x08, 0xE0, 0x5F, 0x89, 0x04, 0x88, 0xA7, 0x42, 0x14, 0xD0, 0x01, 0x32, 0x40, 0x2A, 0x03, 0xF1, 0x40, 0x03, ++0x1C, 0xD0, 0x1C, 0x7A, 0x03, 0xF1, 0x08, 0x06, 0x00, 0x2C, 0xF1, 0xD1, 0x00, 0x29, 0xF3, 0xD0, 0x08, 0xEB, 0x82, 0x12, ++0x80, 0x23, 0x82, 0xF8, 0x44, 0x30, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x9F, 0x89, 0x44, 0x88, 0xA7, 0x42, ++0xE6, 0xD1, 0xDF, 0x89, 0x84, 0x88, 0xA7, 0x42, 0xF3, 0xD0, 0x01, 0x32, 0x40, 0x2A, 0x03, 0xF1, 0x40, 0x03, 0xE2, 0xD1, ++0x00, 0x29, 0x46, 0xD0, 0x26, 0x4F, 0x4F, 0xF0, 0x00, 0x0B, 0x4F, 0xF0, 0x21, 0x0A, 0x06, 0xE0, 0x0B, 0xF1, 0x01, 0x0B, ++0xBB, 0xF1, 0x40, 0x0F, 0x05, 0xF1, 0x40, 0x05, 0x39, 0xD0, 0x2B, 0x7A, 0x05, 0xF1, 0x08, 0x06, 0x00, 0x2B, 0xF3, 0xD0, ++0x95, 0xF8, 0x45, 0x40, 0x00, 0x2C, 0xEF, 0xD1, 0x38, 0x68, 0x30, 0xB3, 0x90, 0xF8, 0x70, 0x31, 0x1B, 0xB3, 0x05, 0xF1, ++0x11, 0x01, 0x4F, 0xF0, 0xFD, 0x09, 0x06, 0xE0, 0x38, 0x68, 0x01, 0x34, 0x90, 0xF8, 0x70, 0x31, 0xE4, 0xB2, 0xA3, 0x42, ++0x15, 0xD9, 0x04, 0xEB, 0x44, 0x13, 0x03, 0x44, 0x93, 0xF8, 0xFC, 0x30, 0x00, 0x2B, 0xF1, 0xD0, 0x2A, 0x7C, 0x9A, 0x42, ++0xEE, 0xD1, 0x1A, 0xFB, 0x04, 0x93, 0x18, 0x44, 0x01, 0x91, 0x0A, 0xF0, 0xE1, 0xFD, 0x01, 0x99, 0x00, 0x28, 0xE5, 0xD1, ++0x3B, 0x68, 0x93, 0xF8, 0x70, 0x31, 0x9C, 0x42, 0xC6, 0xD1, 0x08, 0xEB, 0x8B, 0x11, 0x80, 0x20, 0x00, 0x23, 0x81, 0xF8, ++0x44, 0x00, 0x0B, 0x72, 0xA5, 0xE7, 0x00, 0x26, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA8, 0xBA, 0x17, 0x00, ++0xF4, 0x9F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, 0x61, 0x4B, 0x99, 0xB0, 0x1C, 0x68, 0x03, 0x46, ++0x04, 0x93, 0x04, 0x20, 0x94, 0xF8, 0x6E, 0x31, 0x07, 0x93, 0xF6, 0xF7, 0x03, 0xFD, 0x01, 0x28, 0x05, 0xD0, 0x00, 0x20, ++0x19, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x58, 0x49, 0x41, 0xF2, 0x0C, 0x03, 0xCA, 0x5C, 0xD2, 0x07, ++0x19, 0xD4, 0xCA, 0x5A, 0x04, 0x9B, 0x9B, 0x8B, 0x9A, 0x42, 0x00, 0xF0, 0x85, 0x80, 0x52, 0x49, 0x41, 0xF2, 0x34, 0x02, ++0x8A, 0x5A, 0x9A, 0x42, 0xE7, 0xD1, 0x04, 0x9A, 0x41, 0xF2, 0x36, 0x03, 0xD2, 0x8B, 0xCB, 0x5A, 0x9A, 0x42, 0xE0, 0xD1, ++0x04, 0x9A, 0x41, 0xF2, 0x38, 0x03, 0x12, 0x8C, 0xCB, 0x5A, 0x9A, 0x42, 0xD9, 0xD1, 0x04, 0x98, 0x30, 0xF8, 0x30, 0x3B, ++0x0B, 0x90, 0x24, 0x3B, 0x9B, 0xB2, 0x0D, 0xF1, 0x37, 0x02, 0x19, 0x46, 0x08, 0xEE, 0x10, 0x3A, 0xF7, 0xF7, 0xE4, 0xF8, ++0x00, 0x28, 0x73, 0xD0, 0x9D, 0xF8, 0x37, 0x60, 0x10, 0xAD, 0x4E, 0xB1, 0xAF, 0x19, 0x2B, 0x46, 0xC5, 0xF1, 0x02, 0x01, ++0xC2, 0x18, 0x52, 0x5C, 0x03, 0xF8, 0x01, 0x2B, 0xBB, 0x42, 0xF9, 0xD1, 0x04, 0x9F, 0x38, 0x46, 0x01, 0x21, 0x2B, 0x46, ++0x32, 0x46, 0x1C, 0x30, 0xFF, 0xF7, 0x24, 0xFF, 0x01, 0x46, 0x0A, 0x90, 0x00, 0x28, 0xB0, 0xD0, 0xBB, 0x8B, 0x43, 0x80, ++0xFB, 0x8B, 0x83, 0x80, 0x3B, 0x8C, 0xC3, 0x80, 0x97, 0xF8, 0x2C, 0x30, 0x97, 0xF8, 0x2D, 0x20, 0x43, 0xEA, 0x02, 0x23, ++0x03, 0x86, 0xFB, 0x8D, 0x43, 0x86, 0x03, 0xF0, 0x01, 0x03, 0xC3, 0xF1, 0x02, 0x03, 0x43, 0x85, 0x00, 0x2E, 0x46, 0xD1, ++0x0A, 0x9B, 0x1E, 0x72, 0x27, 0x4A, 0x41, 0xF2, 0x3A, 0x03, 0xD3, 0x5C, 0x00, 0x2B, 0x40, 0xF0, 0xA5, 0x82, 0x24, 0x4A, ++0x41, 0xF2, 0x0A, 0x03, 0xD5, 0x5C, 0x00, 0x2D, 0x48, 0xD1, 0x94, 0xF8, 0x70, 0x11, 0x00, 0x29, 0x44, 0xD0, 0x0A, 0x9B, ++0x26, 0x46, 0x03, 0xF1, 0x09, 0x07, 0x98, 0x46, 0x08, 0x46, 0x05, 0xE0, 0x01, 0x35, 0xA8, 0x42, 0x06, 0xF1, 0x21, 0x06, ++0x03, 0x46, 0x34, 0xDD, 0x96, 0xF8, 0xFC, 0x30, 0x83, 0xB3, 0x98, 0xF8, 0x08, 0x20, 0x9A, 0x42, 0xF2, 0xD1, 0x39, 0x46, ++0x06, 0xF1, 0xFD, 0x00, 0x0A, 0xF0, 0x26, 0xFD, 0x00, 0x28, 0x00, 0xF0, 0x2C, 0x83, 0x94, 0xF8, 0x70, 0x01, 0xE7, 0xE7, ++0x04, 0x99, 0x0F, 0x48, 0xC9, 0x8B, 0x41, 0xF2, 0x0E, 0x02, 0x82, 0x5A, 0x91, 0x42, 0x7F, 0xF4, 0x72, 0xAF, 0x04, 0x99, ++0x41, 0xF2, 0x10, 0x02, 0x09, 0x8C, 0x82, 0x5A, 0x91, 0x42, 0x7F, 0xF4, 0x6A, 0xAF, 0x7C, 0xE7, 0x06, 0x46, 0x10, 0xAD, ++0x96, 0xE7, 0x0B, 0x46, 0x03, 0xF8, 0x08, 0x6F, 0x2E, 0x44, 0x15, 0xF8, 0x01, 0x2B, 0x03, 0xF8, 0x01, 0x2F, 0xAE, 0x42, ++0xF9, 0xD1, 0xAF, 0xE7, 0xA8, 0xBA, 0x17, 0x00, 0x03, 0x46, 0x9D, 0x42, 0x3F, 0xF4, 0x43, 0xAF, 0x18, 0xEE, 0x10, 0x1A, ++0x0B, 0x98, 0xF7, 0xF7, 0x45, 0xF9, 0x00, 0x28, 0x00, 0xF0, 0x3A, 0x82, 0x04, 0x9B, 0x9A, 0x79, 0x83, 0x78, 0x00, 0x2A, ++0x40, 0xF0, 0x56, 0x82, 0x59, 0x1E, 0x0D, 0x29, 0x00, 0xF2, 0x4F, 0x82, 0x0E, 0x2B, 0x00, 0xF0, 0xEB, 0x82, 0x03, 0xEB, ++0x83, 0x03, 0x03, 0xF6, 0x67, 0x11, 0x10, 0x46, 0xFA, 0xF7, 0x98, 0xFE, 0x0A, 0x99, 0x04, 0x9B, 0xC8, 0x62, 0x91, 0xF9, ++0x3C, 0x20, 0x93, 0xF9, 0x09, 0x30, 0x9A, 0x42, 0xB8, 0xBF, 0x81, 0xF8, 0x3C, 0x30, 0x04, 0x99, 0x03, 0x88, 0x8A, 0x88, ++0x9A, 0x42, 0x00, 0xD0, 0x8B, 0x80, 0x41, 0xF2, 0xBD, 0x03, 0xB4, 0x4A, 0x00, 0x25, 0xD5, 0x54, 0x18, 0xEE, 0x10, 0x3A, ++0x00, 0x2B, 0x6C, 0xD0, 0x0B, 0x9B, 0x8D, 0xED, 0x05, 0x8A, 0x2C, 0x46, 0xA8, 0x46, 0x06, 0x93, 0xDD, 0xE9, 0x05, 0x10, ++0xF7, 0xF7, 0xFC, 0xF9, 0x08, 0x90, 0x00, 0x28, 0x5F, 0xD0, 0x43, 0x78, 0xAA, 0x4A, 0x81, 0x78, 0x11, 0x70, 0x5E, 0x1E, ++0x02, 0x33, 0xB6, 0xB2, 0x09, 0x93, 0x00, 0xF1, 0x03, 0x0A, 0x00, 0x2E, 0x44, 0xD0, 0x31, 0x46, 0x50, 0x46, 0xF7, 0xF7, ++0x09, 0xFA, 0x07, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0x90, 0xF8, 0x01, 0x90, 0x00, 0xF1, 0x02, 0x0B, 0x09, 0xF1, 0x02, 0x03, ++0xF6, 0x1A, 0x58, 0x46, 0x04, 0x21, 0xB6, 0xB2, 0x9A, 0x44, 0xF7, 0xF7, 0x1D, 0xFA, 0x00, 0x28, 0x00, 0xF0, 0x81, 0x81, ++0x49, 0x46, 0x58, 0x46, 0xF7, 0xF7, 0x36, 0xFA, 0x07, 0xF1, 0x04, 0x08, 0x04, 0x46, 0x49, 0x46, 0x58, 0x46, 0x0E, 0xAA, ++0xF6, 0xF7, 0xE8, 0xFF, 0x05, 0x46, 0x00, 0x2C, 0xD7, 0xD0, 0x00, 0x2D, 0xD5, 0xD0, 0x92, 0x4B, 0x98, 0xF8, 0x00, 0xC0, ++0x1A, 0x78, 0xA7, 0x78, 0xA3, 0xF1, 0x81, 0x00, 0x81, 0x1D, 0x98, 0xF8, 0x01, 0x30, 0x01, 0xF8, 0x32, 0x70, 0x4C, 0xEA, ++0x03, 0x21, 0x53, 0x1C, 0xDB, 0xB2, 0x07, 0x1D, 0x10, 0x2B, 0x40, 0xF8, 0x32, 0x50, 0x80, 0xF8, 0x81, 0x30, 0x27, 0xF8, ++0x32, 0x10, 0x12, 0xD0, 0x4F, 0xF0, 0x00, 0x08, 0x00, 0x2E, 0xBA, 0xD1, 0x06, 0x9B, 0x08, 0x9A, 0x05, 0x99, 0x9B, 0x1A, ++0x19, 0x44, 0x09, 0x9B, 0xA1, 0xEB, 0x03, 0x0B, 0x1F, 0xFA, 0x8B, 0xF1, 0xD3, 0x18, 0x05, 0x91, 0x06, 0x93, 0x00, 0x29, ++0x98, 0xD1, 0x0A, 0x99, 0x00, 0x23, 0x4B, 0x63, 0x8B, 0x63, 0x41, 0xF2, 0x0A, 0x02, 0x77, 0x4B, 0x9B, 0x5C, 0x00, 0x2B, ++0x00, 0xF0, 0xB4, 0x80, 0x0A, 0x9A, 0x07, 0x9F, 0x76, 0x4C, 0x56, 0x8D, 0x51, 0x8E, 0x13, 0x46, 0x4F, 0xF4, 0xA4, 0x65, ++0x53, 0xF8, 0x02, 0x0F, 0x12, 0x8E, 0x9B, 0x88, 0x05, 0xFB, 0x07, 0xF5, 0x67, 0x19, 0xA7, 0xF8, 0x68, 0x31, 0xA7, 0xF8, ++0x98, 0x21, 0xFF, 0x23, 0x0A, 0x9A, 0xA7, 0xF8, 0x8E, 0x61, 0xC7, 0xF8, 0x64, 0x01, 0xA7, 0xF8, 0x9A, 0x11, 0x87, 0xF8, ++0x61, 0x31, 0x87, 0xF8, 0xBE, 0x31, 0x13, 0x7A, 0x05, 0xF1, 0xEC, 0x06, 0x26, 0x44, 0x00, 0x2B, 0x40, 0xF0, 0xA2, 0x81, ++0x0A, 0x9A, 0xD2, 0x6A, 0xC7, 0xF8, 0x90, 0x21, 0xA7, 0xF8, 0xC2, 0x31, 0x07, 0x9B, 0x0A, 0x9A, 0x0B, 0x98, 0x4F, 0xF4, ++0xA4, 0x67, 0x07, 0xFB, 0x03, 0x47, 0x92, 0xF8, 0x3D, 0x30, 0x87, 0xF8, 0x8B, 0x31, 0x92, 0xF8, 0x3E, 0x30, 0x87, 0xF8, ++0x8C, 0x31, 0x05, 0xF5, 0xCE, 0x78, 0x00, 0x23, 0xA0, 0x44, 0xC7, 0xF8, 0xCC, 0x31, 0x18, 0xEE, 0x10, 0x1A, 0x42, 0x46, ++0xF9, 0xF7, 0xA4, 0xFB, 0x0A, 0x9B, 0xDB, 0x6A, 0x9B, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0xB3, 0x81, 0x05, 0xF5, 0xD6, 0x72, ++0x18, 0xEE, 0x10, 0x1A, 0x0B, 0x98, 0x22, 0x44, 0x0E, 0xAB, 0xF9, 0xF7, 0x6D, 0xFD, 0x80, 0xB1, 0x07, 0x9A, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, 0xB3, 0xF8, 0x9A, 0x11, 0xD3, 0xF8, 0xCC, 0x21, 0x41, 0xF4, 0x00, 0x71, 0x42, 0xF0, ++0x01, 0x02, 0xA3, 0xF8, 0x9A, 0x11, 0xC3, 0xF8, 0xCC, 0x21, 0x45, 0x4F, 0x97, 0xF8, 0x76, 0x31, 0xDB, 0x07, 0x09, 0xD5, ++0x07, 0x9B, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x03, 0x49, 0xD9, 0xF8, 0xCC, 0x31, 0xD8, 0x07, 0x00, 0xF1, 0x98, 0x81, ++0x00, 0x21, 0x88, 0x46, 0x40, 0x46, 0x32, 0x46, 0xFB, 0xF7, 0x52, 0xFA, 0x0B, 0x9D, 0x18, 0xEE, 0x10, 0x1A, 0x28, 0x46, ++0x32, 0x46, 0xF9, 0xF7, 0xAD, 0xFB, 0x28, 0x46, 0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, 0xF9, 0xF7, 0xB1, 0xFB, 0x28, 0x46, ++0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, 0xF9, 0xF7, 0x13, 0xFC, 0x07, 0x9A, 0x31, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x02, 0x44, 0x29, 0x6D, 0xD4, 0xF8, 0xCC, 0x31, 0x43, 0xF0, 0x00, 0x43, 0x41, 0xF2, 0x3B, 0x02, 0xC4, 0xF8, 0xCC, 0x31, ++0x25, 0x4B, 0x01, 0x20, 0x98, 0x54, 0x2A, 0x6A, 0x00, 0x29, 0x00, 0xF0, 0x1C, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x19, 0x81, ++0x0B, 0x7E, 0x03, 0x2B, 0x08, 0xD1, 0x25, 0x4B, 0x05, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xD5, 0xE9, ++0x11, 0x30, 0x98, 0x47, 0x0A, 0x9A, 0x14, 0x78, 0xDC, 0xB9, 0x19, 0x48, 0x1F, 0x4B, 0x81, 0x88, 0x1B, 0x68, 0x01, 0x31, ++0x89, 0xB2, 0x81, 0x80, 0x1B, 0x88, 0x5B, 0x07, 0x11, 0xD5, 0x13, 0x7A, 0x00, 0x2B, 0x40, 0xF0, 0x7A, 0x81, 0x1A, 0x4D, ++0x0A, 0x9A, 0x04, 0x9C, 0xD2, 0x6A, 0x94, 0xF9, 0x09, 0x00, 0x12, 0x88, 0x00, 0x90, 0xCD, 0xE9, 0x01, 0x35, 0x16, 0x48, ++0x23, 0x7B, 0xF7, 0xF7, 0x89, 0xFE, 0x0A, 0x99, 0x00, 0x25, 0x01, 0x22, 0x0A, 0x70, 0x81, 0xF8, 0x3D, 0x50, 0x81, 0xF8, ++0x3E, 0x50, 0x41, 0xF2, 0xBD, 0x03, 0x08, 0x46, 0x05, 0x49, 0xCB, 0x5C, 0x00, 0x2B, 0x4D, 0xD0, 0x0D, 0x4C, 0x83, 0x46, ++0x04, 0xF1, 0x80, 0x0A, 0x04, 0xF1, 0x81, 0x09, 0x43, 0xE0, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x64, 0xCB, 0x17, 0x00, ++0x65, 0xCB, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x48, 0xBF, 0x15, 0x00, 0x84, 0xBF, 0x15, 0x00, 0xE4, 0xCA, 0x17, 0x00, 0x9A, 0xF8, 0x00, 0x70, ++0x08, 0x2F, 0x2B, 0xD8, 0x5A, 0x46, 0x21, 0x68, 0x52, 0xF8, 0x02, 0x0F, 0x4E, 0x78, 0x0E, 0x90, 0x92, 0x88, 0xAD, 0xF8, ++0x3C, 0x20, 0xBB, 0xF8, 0x06, 0x20, 0xBD, 0xF9, 0x3C, 0x10, 0x4F, 0xF0, 0x01, 0x08, 0x02, 0xEB, 0x03, 0x22, 0x08, 0xFA, ++0x07, 0xF3, 0x4A, 0x40, 0x01, 0x3B, 0x02, 0xEA, 0x03, 0x22, 0x00, 0x23, 0x81, 0xEA, 0x02, 0x0C, 0x0E, 0xA8, 0x1A, 0x46, ++0x19, 0x46, 0xAD, 0xF8, 0x3C, 0xC0, 0xFF, 0xF7, 0xDF, 0xFC, 0x68, 0xB3, 0x99, 0xF8, 0x00, 0x30, 0x01, 0x35, 0x9D, 0x42, ++0x04, 0xF1, 0x08, 0x04, 0x02, 0xDA, 0xA3, 0x79, 0x00, 0x2B, 0xCF, 0xD1, 0x04, 0x98, 0x04, 0x23, 0x0C, 0x22, 0x41, 0xF2, ++0x04, 0x01, 0xF6, 0xF7, 0x2D, 0xF8, 0x01, 0x20, 0x5C, 0xE5, 0xB8, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x62, 0xAE, 0x4C, 0xB1, ++0x00, 0x2D, 0x7F, 0xF4, 0x88, 0xAE, 0x49, 0x46, 0x58, 0x46, 0x0E, 0xAA, 0xF6, 0xF7, 0x66, 0xFE, 0x05, 0x46, 0x7E, 0xE6, ++0x49, 0x46, 0x58, 0x46, 0xF7, 0xF7, 0xA6, 0xF8, 0x04, 0x46, 0x00, 0x2D, 0x3F, 0xF4, 0x6F, 0xAE, 0x00, 0x28, 0x3F, 0xF4, ++0x4C, 0xAE, 0x74, 0xE6, 0x23, 0x68, 0x41, 0x46, 0x02, 0x33, 0x32, 0x46, 0x0E, 0xA8, 0xFF, 0xF7, 0xA9, 0xFC, 0x86, 0x46, ++0x00, 0x28, 0xD1, 0xD0, 0xD8, 0x46, 0xB8, 0xE8, 0x0F, 0x00, 0xF4, 0x46, 0xAC, 0xE8, 0x0F, 0x00, 0xB8, 0xE8, 0x0F, 0x00, ++0xAC, 0xE8, 0x0F, 0x00, 0xB8, 0xE8, 0x0F, 0x00, 0xAC, 0xE8, 0x0F, 0x00, 0x98, 0xE8, 0x0F, 0x00, 0x8C, 0xE8, 0x0F, 0x00, ++0x0E, 0x98, 0xCE, 0xF8, 0x02, 0x00, 0xBD, 0xF8, 0x3C, 0x30, 0x8E, 0xF8, 0x08, 0x60, 0x21, 0x68, 0xAE, 0xF8, 0x06, 0x30, ++0x5E, 0xB1, 0x08, 0x36, 0x06, 0x39, 0x76, 0x44, 0xA1, 0xEB, 0x0E, 0x01, 0x0E, 0xF1, 0x08, 0x03, 0xCA, 0x5C, 0x03, 0xF8, ++0x01, 0x2F, 0x9E, 0x42, 0xFA, 0xD1, 0x7E, 0x49, 0x8E, 0xF8, 0x3E, 0x70, 0x8B, 0x88, 0xA2, 0x79, 0x8E, 0xF8, 0x3D, 0x20, ++0x01, 0x33, 0x01, 0x22, 0x8B, 0x80, 0x8E, 0xF8, 0x00, 0x20, 0x91, 0xE7, 0x04, 0x9B, 0x93, 0xF9, 0x09, 0x20, 0x0A, 0x9B, ++0x93, 0xF9, 0x3C, 0x30, 0x9A, 0x42, 0x7F, 0xF7, 0xE2, 0xAD, 0x04, 0x9C, 0xA1, 0x88, 0xA0, 0x79, 0xFA, 0xF7, 0x64, 0xFC, ++0x0A, 0x9A, 0xD0, 0x62, 0x63, 0x7A, 0x82, 0xF8, 0x3C, 0x30, 0xD6, 0xE5, 0x0A, 0x9B, 0x6E, 0x49, 0x07, 0x22, 0x03, 0xF1, ++0x09, 0x00, 0x0A, 0xF0, 0x9D, 0xFA, 0x00, 0x28, 0x7F, 0xF4, 0xE3, 0xAC, 0x9E, 0xE5, 0x4F, 0xF6, 0xFF, 0x71, 0xB4, 0xE5, ++0x01, 0x2A, 0xFA, 0xD1, 0x59, 0x1E, 0xA4, 0x29, 0xF7, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x51, 0x08, 0x31, ++0xA9, 0xE5, 0xB2, 0xFA, 0x82, 0xF2, 0x62, 0x48, 0x52, 0x09, 0xF7, 0xF7, 0x95, 0xFD, 0xEB, 0xE6, 0x02, 0xF1, 0x09, 0x00, ++0x0A, 0xF0, 0xAC, 0xFC, 0xA8, 0xB1, 0x0A, 0x9B, 0x07, 0xF5, 0xB5, 0x77, 0x03, 0xF1, 0x08, 0x08, 0x03, 0xF1, 0x28, 0x0E, ++0xC4, 0x46, 0xBC, 0xE8, 0x0F, 0x00, 0xF4, 0x45, 0x38, 0x60, 0x79, 0x60, 0xBA, 0x60, 0xFB, 0x60, 0xE0, 0x46, 0x07, 0xF1, ++0x10, 0x07, 0xF3, 0xD1, 0x9C, 0xF8, 0x00, 0x30, 0x3B, 0x70, 0x0A, 0x9B, 0x07, 0x98, 0x19, 0x7A, 0x0A, 0x9B, 0xDA, 0x6A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x43, 0x00, 0x27, 0xC3, 0xF8, 0x90, 0x21, 0xA3, 0xF8, 0xC2, 0x71, 0x00, 0x29, ++0x3F, 0xF4, 0x38, 0xAE, 0x0B, 0x44, 0x05, 0xF2, 0x6B, 0x11, 0x12, 0x88, 0x48, 0x48, 0x83, 0xF8, 0x6B, 0x71, 0x21, 0x44, ++0xF7, 0xF7, 0x5E, 0xFD, 0x2C, 0xE6, 0x40, 0x46, 0x01, 0x21, 0xFA, 0xF7, 0xED, 0xFD, 0x10, 0xF0, 0x0F, 0x00, 0x1A, 0xBF, ++0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x1F, 0x03, 0x01, 0x23, 0x87, 0xF8, 0xC1, 0x31, 0x3D, 0xE6, 0x18, 0xEE, 0x10, 0x1A, ++0x0B, 0x98, 0x32, 0x46, 0xF9, 0xF7, 0x0C, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x5F, 0xAE, 0xD9, 0xF8, 0xCC, 0x31, 0x0B, 0x98, ++0x43, 0xF0, 0x02, 0x03, 0x18, 0xEE, 0x10, 0x1A, 0xC9, 0xF8, 0xCC, 0x31, 0xF7, 0xF7, 0x24, 0xF8, 0x97, 0xF8, 0x76, 0x31, ++0x59, 0x07, 0x80, 0x46, 0x30, 0xD4, 0x9A, 0x07, 0x0A, 0xD4, 0x07, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, ++0xD3, 0xF8, 0xCC, 0x11, 0x11, 0xF0, 0x08, 0x01, 0x3F, 0xF4, 0x44, 0xAE, 0x05, 0xF5, 0x86, 0x72, 0x18, 0xEE, 0x10, 0x1A, ++0x0B, 0x98, 0x22, 0x44, 0xF9, 0xF7, 0x08, 0xFC, 0x30, 0xBB, 0x01, 0x46, 0x38, 0xE6, 0x02, 0xF1, 0x09, 0x05, 0x28, 0x46, ++0x16, 0x46, 0x0A, 0xF0, 0x33, 0xFC, 0x20, 0xB9, 0x1E, 0x4B, 0x22, 0x4D, 0x99, 0x88, 0x33, 0x7A, 0x7A, 0xE6, 0x0A, 0x9A, ++0x1B, 0x49, 0x13, 0x7A, 0x89, 0x88, 0x1A, 0x44, 0x54, 0x72, 0x73, 0xE6, 0x40, 0xF6, 0xB4, 0x11, 0x15, 0xE5, 0x94, 0xF8, ++0x70, 0x31, 0xF6, 0xE4, 0x05, 0xF5, 0x8C, 0x72, 0x18, 0xEE, 0x10, 0x1A, 0x0B, 0x98, 0x22, 0x44, 0xF9, 0xF7, 0x02, 0xFC, ++0xA0, 0xB9, 0x97, 0xF8, 0x76, 0x31, 0xC2, 0xE7, 0x07, 0x9A, 0x0B, 0x98, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, ++0x18, 0xEE, 0x10, 0x1A, 0xD3, 0xF8, 0xCC, 0x21, 0x42, 0xF0, 0x04, 0x02, 0xC3, 0xF8, 0xCC, 0x21, 0xF6, 0xF7, 0xF2, 0xFF, ++0x01, 0x46, 0x01, 0xE6, 0xD9, 0xF8, 0xCC, 0x31, 0x0B, 0x98, 0x43, 0xF0, 0x08, 0x03, 0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, ++0xC9, 0xF8, 0xCC, 0x31, 0xF9, 0xF7, 0x36, 0xFC, 0xDD, 0xE7, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x54, 0xBF, 0x15, 0x00, ++0x68, 0xBF, 0x15, 0x00, 0x5C, 0xBF, 0x15, 0x00, 0x48, 0xBF, 0x15, 0x00, 0x00, 0x23, 0x1A, 0x46, 0x19, 0x46, 0xFF, 0xF7, ++0x71, 0xBB, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0x03, 0x78, 0x43, 0xB3, 0x16, 0x4C, 0x07, 0x46, 0x4F, 0xF0, 0x00, 0x08, ++0x04, 0xF5, 0x80, 0x56, 0x6F, 0xF0, 0x7F, 0x05, 0x00, 0xF1, 0x01, 0x09, 0x02, 0xE0, 0x40, 0x34, 0xB4, 0x42, 0x17, 0xD0, ++0x23, 0x7A, 0xAB, 0xB1, 0x94, 0xF9, 0x44, 0x30, 0xAB, 0x42, 0xF6, 0xDD, 0x23, 0x7C, 0x3A, 0x78, 0x9A, 0x42, 0xF2, 0xD1, ++0x49, 0x46, 0x04, 0xF1, 0x11, 0x00, 0x0A, 0xF0, 0x97, 0xF9, 0x00, 0x28, 0xEB, 0xD1, 0x94, 0xF9, 0x44, 0x50, 0x04, 0xF1, ++0x08, 0x08, 0x40, 0x34, 0xB4, 0x42, 0xE7, 0xD1, 0x40, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x98, 0x46, 0x40, 0x46, 0xBD, 0xE8, ++0xF8, 0x83, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x41, 0xF2, 0x0B, 0x03, 0xC2, 0x4D, 0xE9, 0x5C, ++0x2E, 0x68, 0x01, 0x29, 0x82, 0xB0, 0x00, 0xF2, 0xB8, 0x81, 0x96, 0xF8, 0x6F, 0x01, 0x00, 0x27, 0x00, 0x28, 0x00, 0xF0, ++0x57, 0x81, 0x33, 0x46, 0x00, 0x24, 0x03, 0xE0, 0x01, 0x34, 0x84, 0x42, 0x00, 0xF0, 0x50, 0x81, 0x9A, 0x78, 0x8A, 0x42, ++0x03, 0xF1, 0x06, 0x03, 0xF6, 0xD1, 0x17, 0xB1, 0x41, 0xF2, 0x0B, 0x03, 0xE9, 0x54, 0x4F, 0xF4, 0xBA, 0x73, 0x02, 0x21, ++0x04, 0x22, 0x4F, 0xF4, 0x00, 0x60, 0xF5, 0xF7, 0x03, 0xFE, 0x96, 0xF8, 0x6E, 0x31, 0x80, 0xF8, 0x6E, 0x31, 0x07, 0x46, ++0xD6, 0xE9, 0x58, 0x01, 0xC7, 0xF8, 0x60, 0x01, 0xA7, 0xF8, 0x64, 0x11, 0x96, 0xF8, 0x70, 0x01, 0x87, 0xF8, 0x70, 0x01, ++0x96, 0xF8, 0x71, 0x31, 0x87, 0xF8, 0x71, 0x31, 0x96, 0xF8, 0x6F, 0x31, 0x9C, 0x42, 0x80, 0xF2, 0x79, 0x81, 0x41, 0xF2, ++0x0B, 0x02, 0x04, 0xEB, 0x44, 0x04, 0x06, 0x21, 0x15, 0xF8, 0x02, 0x80, 0x06, 0xEB, 0x44, 0x04, 0x11, 0xFB, 0x03, 0x61, ++0xA3, 0x78, 0x43, 0x45, 0x10, 0xD1, 0x97, 0xF8, 0x6F, 0x31, 0xD4, 0xF8, 0x00, 0xC0, 0x03, 0xEB, 0x43, 0x02, 0x01, 0x33, ++0x47, 0xF8, 0x12, 0xC0, 0x07, 0xEB, 0x42, 0x02, 0xB4, 0xF8, 0x04, 0xC0, 0xA2, 0xF8, 0x04, 0xC0, 0x87, 0xF8, 0x6F, 0x31, ++0x06, 0x34, 0xA1, 0x42, 0xE8, 0xD1, 0xF0, 0xB1, 0x4F, 0xF0, 0x21, 0x0A, 0xFC, 0x21, 0x1A, 0xFB, 0x00, 0x1A, 0x73, 0x18, ++0x03, 0xF1, 0x20, 0x09, 0x7A, 0x18, 0xD3, 0xF8, 0x00, 0xC0, 0x5C, 0x68, 0x98, 0x68, 0xD3, 0xF8, 0x0C, 0xE0, 0xC2, 0xF8, ++0x0C, 0xE0, 0x10, 0x33, 0x4B, 0x45, 0xC2, 0xF8, 0x00, 0xC0, 0x54, 0x60, 0x90, 0x60, 0x02, 0xF1, 0x10, 0x02, 0xEE, 0xD1, ++0x21, 0x31, 0x1B, 0x78, 0x13, 0x70, 0x51, 0x45, 0xE5, 0xD1, 0x2B, 0x68, 0xDF, 0xF8, 0x2C, 0xC2, 0xB3, 0xF8, 0x6C, 0x91, ++0x81, 0x4C, 0xB9, 0xF1, 0xC9, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, 0x00, 0x09, 0xB8, 0xF1, 0x01, 0x0F, 0x66, 0x46, 0x00, 0xF0, ++0xE5, 0x80, 0x93, 0xF8, 0x71, 0x21, 0x7C, 0x4B, 0x00, 0x2A, 0xA3, 0xF1, 0x04, 0x02, 0x0A, 0xBF, 0x13, 0x46, 0x4F, 0xF0, ++0x08, 0x0E, 0x4F, 0xF0, 0x0C, 0x0E, 0x78, 0x4A, 0x01, 0x20, 0x08, 0x21, 0x10, 0x75, 0x15, 0x32, 0x61, 0x70, 0x58, 0x18, ++0x13, 0xF8, 0x01, 0x1B, 0x02, 0xF8, 0x01, 0x1F, 0x98, 0x42, 0xF9, 0xD1, 0x72, 0x4B, 0x01, 0x93, 0xB9, 0xF1, 0x00, 0x0F, ++0x40, 0xF0, 0x99, 0x80, 0xBE, 0xF1, 0x08, 0x0F, 0x19, 0xD0, 0x01, 0x9B, 0x6E, 0x4A, 0x58, 0x1C, 0x32, 0x21, 0x01, 0x90, ++0x19, 0x70, 0x01, 0x9B, 0xAE, 0xF1, 0x08, 0x0E, 0x59, 0x1C, 0x5F, 0xFA, 0x8E, 0xFE, 0x01, 0x91, 0x83, 0xF8, 0x00, 0xE0, ++0x01, 0x9B, 0x18, 0x1D, 0x12, 0xF8, 0x01, 0x1B, 0x03, 0xF8, 0x01, 0x1B, 0x98, 0x42, 0xF9, 0xD1, 0x01, 0x9B, 0x73, 0x44, ++0x01, 0x93, 0x41, 0xF2, 0x0B, 0x03, 0xEB, 0x5C, 0x63, 0xB9, 0x01, 0x9B, 0x03, 0x22, 0x59, 0x1C, 0x01, 0x91, 0x1A, 0x70, ++0x01, 0x9B, 0x01, 0x22, 0x59, 0x1C, 0x01, 0x91, 0x1A, 0x70, 0x01, 0x9B, 0x13, 0x44, 0x01, 0x93, 0xB9, 0xF1, 0x00, 0x0F, ++0x36, 0xD1, 0xDF, 0xF8, 0x7C, 0x81, 0x98, 0xF8, 0x76, 0x31, 0xD8, 0x07, 0x06, 0xD5, 0x56, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, ++0x48, 0x31, 0x98, 0x47, 0x98, 0xF8, 0x76, 0x31, 0x41, 0xF2, 0x0B, 0x02, 0xAA, 0x5C, 0x01, 0x2A, 0x4A, 0xD0, 0x5D, 0x07, ++0x04, 0xD5, 0x4F, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, 0x44, 0x31, 0x98, 0x47, 0x4D, 0x4D, 0x01, 0x98, 0x29, 0x46, 0x31, 0xF8, ++0x03, 0x2B, 0x0A, 0xF0, 0xB1, 0xF8, 0x4B, 0x4A, 0x01, 0x99, 0x12, 0x68, 0x2B, 0x88, 0xB2, 0xF9, 0x00, 0x20, 0x0B, 0x44, ++0x00, 0x2A, 0x01, 0x93, 0xA3, 0xEB, 0x04, 0x03, 0x5D, 0xDB, 0x00, 0x22, 0xA7, 0xF8, 0x6C, 0x31, 0xC7, 0xF8, 0x68, 0x21, ++0x38, 0x46, 0xF5, 0xF7, 0x45, 0xFD, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x32, 0x78, 0x3B, 0x2A, 0x60, 0xD0, 0xDF, 0xF8, ++0x08, 0x81, 0x98, 0xF8, 0x76, 0x31, 0xD9, 0x07, 0x58, 0xD5, 0x39, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, 0x48, 0x31, 0x98, 0x47, ++0xB9, 0xF1, 0x00, 0x0F, 0xC2, 0xD0, 0x01, 0x99, 0x32, 0x78, 0x0B, 0x46, 0x76, 0x1A, 0x49, 0x44, 0x00, 0xE0, 0xF2, 0x5C, ++0x03, 0xF8, 0x01, 0x2B, 0x99, 0x42, 0xFA, 0xD1, 0x01, 0x9A, 0x98, 0xF8, 0x76, 0x31, 0x4A, 0x44, 0x01, 0x92, 0x41, 0xF2, ++0x0B, 0x02, 0xAA, 0x5C, 0x01, 0x2A, 0xB4, 0xD1, 0x9E, 0x07, 0xB2, 0xD5, 0x29, 0x4B, 0x00, 0x21, 0xD3, 0xF8, 0x50, 0x31, ++0x01, 0xA8, 0x98, 0x47, 0x98, 0xF8, 0x76, 0x31, 0xA9, 0xE7, 0x9C, 0xF8, 0x00, 0x20, 0x0A, 0x2A, 0x7F, 0xF4, 0x62, 0xAF, ++0x9C, 0xF8, 0x01, 0x60, 0x02, 0x36, 0x16, 0xF0, 0xFF, 0x06, 0x09, 0xD0, 0x22, 0x49, 0x98, 0x19, 0x01, 0xE0, 0x11, 0xF8, ++0x01, 0x2F, 0x03, 0xF8, 0x01, 0x2B, 0x83, 0x42, 0xF9, 0xD1, 0x01, 0x9B, 0x33, 0x44, 0xA9, 0xEB, 0x06, 0x09, 0x01, 0x93, ++0x1F, 0xFA, 0x89, 0xF9, 0x66, 0x44, 0x49, 0xE7, 0x01, 0x27, 0xB9, 0x42, 0x53, 0xD0, 0x39, 0x46, 0xA0, 0xE6, 0xB3, 0xF5, ++0x96, 0x7F, 0x9E, 0xD9, 0x16, 0x49, 0x17, 0x48, 0xB4, 0x22, 0xF7, 0xF7, 0x99, 0xFD, 0x01, 0x9B, 0x1B, 0x1B, 0x96, 0xE7, ++0x0A, 0x4B, 0x4F, 0xF0, 0x08, 0x0E, 0x22, 0xE7, 0x01, 0x99, 0xAE, 0xE7, 0x70, 0x78, 0x01, 0x99, 0x02, 0x30, 0x10, 0xF0, ++0xFF, 0x00, 0x42, 0xD0, 0x0B, 0x46, 0xA6, 0xEB, 0x03, 0x0C, 0x01, 0x44, 0x1C, 0xE0, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, ++0xE8, 0x61, 0x18, 0x00, 0xB8, 0xB2, 0x15, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xF2, 0x61, 0x18, 0x00, 0xBC, 0xB2, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0xCB, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x63, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x9C, 0xBF, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x1C, 0xF8, 0x03, 0x20, 0x03, 0xF8, 0x01, 0x2B, 0x99, 0x42, 0xF9, 0xD1, ++0xDF, 0xF8, 0x48, 0x80, 0x01, 0x9B, 0x98, 0xF8, 0x76, 0x21, 0x03, 0x44, 0xA9, 0xEB, 0x00, 0x09, 0x01, 0x93, 0xD3, 0x07, ++0x1F, 0xFA, 0x89, 0xF9, 0x06, 0x44, 0x7F, 0xF5, 0x6F, 0xAF, 0x68, 0xE7, 0x41, 0xF2, 0x0B, 0x03, 0x15, 0xF8, 0x03, 0x80, ++0xA3, 0xE6, 0x41, 0xF2, 0x0B, 0x03, 0x02, 0x22, 0xEA, 0x54, 0x00, 0x20, 0xFF, 0xF7, 0xDE, 0xF8, 0x4F, 0xE7, 0xDF, 0xF8, ++0x10, 0x80, 0x98, 0xF8, 0x76, 0x31, 0xDB, 0x07, 0x3F, 0xF5, 0x55, 0xAF, 0x5D, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, ++0xF0, 0xB5, 0x4C, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x83, 0xB0, 0x04, 0xD1, 0x4A, 0x4A, 0x13, 0x68, 0x23, 0xF4, ++0x00, 0x13, 0x13, 0x60, 0x48, 0x4C, 0x49, 0x4D, 0x23, 0x68, 0x5B, 0x07, 0x4E, 0xD4, 0x48, 0x4E, 0x41, 0xF2, 0x0A, 0x03, ++0xEB, 0x5C, 0x5B, 0xB9, 0x44, 0x4A, 0x19, 0x46, 0x02, 0xF5, 0x80, 0x54, 0x80, 0x20, 0x11, 0x72, 0x82, 0xF8, 0x44, 0x00, ++0x40, 0x32, 0x94, 0x42, 0xF9, 0xD1, 0xA9, 0x80, 0x29, 0x68, 0x91, 0xF8, 0x70, 0x21, 0x01, 0x2A, 0x5F, 0xD0, 0x00, 0x24, ++0x20, 0x46, 0x41, 0xF2, 0x3A, 0x02, 0xA8, 0x54, 0x91, 0xF8, 0x6E, 0x21, 0x91, 0xF8, 0x6F, 0x11, 0x08, 0x20, 0xCD, 0xE9, ++0x00, 0x41, 0x38, 0x49, 0xF7, 0xF7, 0xDC, 0xFA, 0x41, 0xF2, 0x0A, 0x03, 0xEB, 0x5C, 0x83, 0xB9, 0x35, 0x49, 0x36, 0x4A, ++0x0B, 0x68, 0x36, 0x48, 0x43, 0xF0, 0x04, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x03, 0x80, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, ++0x43, 0xF4, 0xBB, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x73, 0x68, 0x01, 0x21, 0x43, 0xF0, 0x20, 0x03, 0x04, 0x20, ++0x73, 0x60, 0xF5, 0xF7, 0x01, 0xFE, 0x2B, 0x68, 0xD3, 0xF8, 0x68, 0x11, 0x19, 0xB1, 0xB3, 0xF8, 0x6C, 0x21, 0xC8, 0x2A, ++0x23, 0xD9, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFF, 0xF7, 0xCE, 0xBD, 0x2B, 0x68, 0x25, 0x4A, 0x93, 0xF8, 0x6E, 0x31, ++0x24, 0x49, 0x1E, 0x4E, 0x10, 0x68, 0x24, 0x4A, 0xC0, 0x8E, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x03, 0x13, 0x03, 0x21, ++0x71, 0x77, 0x11, 0x69, 0x20, 0x4A, 0x73, 0x61, 0x01, 0x44, 0xD2, 0xF8, 0xE0, 0x31, 0x06, 0xF1, 0x0C, 0x00, 0x98, 0x47, ++0x01, 0x23, 0x33, 0x77, 0x23, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x23, 0x60, 0x92, 0xE7, 0x1A, 0x48, 0x09, 0xF0, 0x60, 0xFF, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFF, 0xF7, 0xA7, 0xBD, 0x91, 0xF8, 0xFC, 0x20, 0x07, 0x2A, 0x9B, 0xD1, 0x01, 0xF1, ++0xFD, 0x00, 0x14, 0x49, 0x09, 0xF0, 0x22, 0xFF, 0x41, 0xF2, 0x0A, 0x03, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0xEB, 0x5C, ++0x29, 0x68, 0x04, 0x46, 0x8F, 0xE7, 0x00, 0xBF, 0x74, 0x36, 0x17, 0x00, 0x6C, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, ++0xA8, 0xBA, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0xCC, 0xBF, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x20, 0x04, 0x32, 0x40, ++0x28, 0x25, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x18, 0x63, 0x18, 0x00, 0x54, 0xBF, 0x15, 0x00, 0x00, 0x22, 0x02, 0x81, 0xE7, 0xF7, 0xE0, 0xBA, 0x2D, 0xE9, 0xF0, 0x41, ++0x14, 0x46, 0x52, 0x78, 0x00, 0x2B, 0x18, 0xBF, 0x02, 0x23, 0x52, 0x06, 0x44, 0xBF, 0x08, 0x33, 0xDB, 0xB2, 0x23, 0x44, ++0x06, 0x46, 0x9A, 0x7F, 0x08, 0x2A, 0x0D, 0x46, 0x03, 0xD0, 0x00, 0x27, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0xDA, 0x7F, ++0x06, 0x2A, 0xF8, 0xD1, 0x93, 0xF8, 0x26, 0x70, 0x00, 0x2F, 0xF4, 0xD1, 0x93, 0xF8, 0x27, 0x80, 0xB8, 0xF1, 0x01, 0x0F, ++0x07, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0xED, 0xD1, 0x13, 0x49, 0x80, 0x20, 0xF7, 0xF7, 0x2E, 0xFA, 0xE8, 0xE7, 0x93, 0xF8, ++0x3A, 0x70, 0x93, 0xF8, 0x3B, 0xC0, 0x93, 0xF8, 0x38, 0x00, 0x93, 0xF8, 0x39, 0x20, 0x0B, 0x68, 0x0D, 0x49, 0x3F, 0x04, ++0x47, 0xEA, 0x0C, 0x67, 0x07, 0x43, 0x47, 0xEA, 0x02, 0x27, 0x3A, 0x46, 0x80, 0x20, 0xF7, 0xF7, 0x19, 0xFA, 0x2B, 0x68, ++0x9F, 0x42, 0x01, 0xD0, 0x47, 0x46, 0xCF, 0xE7, 0x06, 0x4B, 0x30, 0x78, 0x9B, 0x69, 0x22, 0x46, 0x04, 0xF1, 0x10, 0x01, ++0x47, 0x46, 0x98, 0x47, 0xC6, 0xE7, 0x00, 0xBF, 0x08, 0xC0, 0x15, 0x00, 0xE8, 0xBF, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xF8, 0xB5, 0x21, 0x4B, 0x21, 0x4D, 0x1E, 0x68, 0x95, 0xF8, 0x44, 0x40, 0xB6, 0xF9, 0x00, 0x70, 0x1F, 0x4B, 0x04, 0xEB, ++0x84, 0x06, 0x00, 0x2F, 0x8E, 0x46, 0x03, 0xEB, 0x06, 0x16, 0x23, 0xDB, 0xA7, 0x00, 0x07, 0xEB, 0x04, 0x0C, 0x03, 0xEB, ++0x0C, 0x1C, 0xCC, 0xF8, 0x0C, 0x00, 0x10, 0xB1, 0x01, 0x7C, 0x8C, 0xF8, 0x10, 0x10, 0x3C, 0x44, 0x03, 0xEB, 0x04, 0x13, ++0x31, 0x46, 0x5A, 0x64, 0xA3, 0xF8, 0x4C, 0xE0, 0x13, 0x48, 0xF5, 0xF7, 0xB5, 0xFF, 0x95, 0xF8, 0x44, 0x20, 0x12, 0x4B, ++0x01, 0x32, 0xA3, 0xFB, 0x02, 0x13, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, 0xA2, 0xEB, 0x83, 0x13, 0x85, 0xF8, 0x44, 0x30, ++0x30, 0x46, 0xF8, 0xBD, 0x04, 0xEB, 0x84, 0x01, 0x03, 0xEB, 0x01, 0x11, 0xA7, 0x00, 0xB1, 0xF8, 0x4C, 0x10, 0x00, 0x29, ++0xD3, 0xD0, 0x08, 0x49, 0x08, 0x48, 0xC6, 0x22, 0xF7, 0xF7, 0xBA, 0xFB, 0x00, 0x26, 0xED, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0xB0, 0xDE, 0x17, 0x00, 0xE0, 0x63, 0x18, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0xAB, 0xAA, 0xAA, 0xAA, 0x70, 0x79, 0x15, 0x00, ++0x14, 0xC0, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x4D, 0x42, 0x69, 0x04, 0x46, 0x04, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, ++0x21, 0x46, 0x28, 0x46, 0xF5, 0xF7, 0xCC, 0xFF, 0xA5, 0xF1, 0x08, 0x00, 0x21, 0x46, 0xF5, 0xF7, 0x77, 0xFF, 0x05, 0x4B, ++0xA5, 0xF1, 0x20, 0x00, 0xD3, 0xF8, 0x38, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x08, 0xDF, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xB3, 0x4B, 0x01, 0xF0, 0x7C, 0x04, 0x1A, 0x7A, 0x04, 0x3C, 0x00, 0xEB, ++0x02, 0x0C, 0x01, 0xF4, 0x80, 0x6E, 0x18, 0x2C, 0x0E, 0xD8, 0xDF, 0xE8, 0x04, 0xF0, 0x54, 0x0D, 0x0D, 0x0D, 0x58, 0x0D, ++0x0D, 0x0D, 0x8D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0xB5, 0x00, ++0x00, 0x24, 0xA7, 0x4D, 0x2D, 0x68, 0x2D, 0x78, 0xAD, 0x07, 0x03, 0xD5, 0x01, 0xF0, 0x3C, 0x01, 0x3C, 0x29, 0x02, 0xD0, ++0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xBE, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xD1, 0x80, 0xBC, 0xF8, 0x02, 0x10, 0x9E, 0x7A, ++0x9E, 0x4C, 0x8D, 0x0B, 0x4F, 0xF4, 0xA4, 0x61, 0xC5, 0xEB, 0x05, 0x17, 0x01, 0xFB, 0x06, 0xF1, 0x01, 0xEB, 0xC7, 0x01, ++0x21, 0x44, 0x2F, 0x01, 0x91, 0xF8, 0x3B, 0xE2, 0xBE, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xCC, 0x80, 0x91, 0xF8, 0x38, 0x12, ++0x01, 0x29, 0x00, 0xF0, 0xEB, 0x80, 0x02, 0x29, 0x00, 0xF0, 0xC1, 0x80, 0x0A, 0x1F, 0x01, 0x2A, 0x40, 0xF2, 0xBD, 0x80, ++0x1A, 0x7A, 0x04, 0x32, 0x1A, 0x72, 0xDC, 0xF8, 0x00, 0x00, 0xC1, 0x17, 0xC3, 0xE9, 0x04, 0x01, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x06, 0xF2, 0x79, 0x1B, 0x02, 0xF5, 0xEC, 0x72, 0x02, 0xEB, 0xC1, 0x02, 0x22, 0x44, 0x1A, 0x62, 0x01, 0x24, ++0xC2, 0xE7, 0x14, 0x1D, 0x1C, 0x72, 0x01, 0x24, 0xB5, 0xE7, 0x02, 0xF1, 0x08, 0x04, 0x1C, 0x72, 0x30, 0xF8, 0x02, 0x80, ++0xBC, 0xF8, 0x06, 0x40, 0x9C, 0xF8, 0x02, 0xA0, 0x93, 0xF8, 0x30, 0x90, 0x4F, 0xEA, 0x08, 0x28, 0x1F, 0xFA, 0x88, 0xF8, ++0x46, 0x46, 0xF7, 0x17, 0x44, 0xEA, 0x07, 0x06, 0xBC, 0xF8, 0x04, 0x40, 0x4A, 0xEA, 0x04, 0x44, 0x44, 0xEA, 0x08, 0x04, ++0x49, 0xF0, 0x03, 0x09, 0xC3, 0xE9, 0x04, 0x46, 0x83, 0xF8, 0x30, 0x90, 0xBE, 0xF1, 0x00, 0x0F, 0x5F, 0xD0, 0x9E, 0x7A, ++0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x6E, 0x4E, 0x04, 0xF5, 0xEC, 0x74, ++0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x1C, 0x62, 0x01, 0x24, 0x80, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, ++0x50, 0xD0, 0x9E, 0x7A, 0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x63, 0x4E, ++0x04, 0xF5, 0xEC, 0x74, 0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x02, 0xF1, 0x08, 0x05, 0x1D, 0x72, ++0xBC, 0xF8, 0x04, 0x60, 0x93, 0xF8, 0x30, 0x80, 0x1C, 0x62, 0x84, 0x5A, 0xBC, 0xF8, 0x06, 0x50, 0x5D, 0x61, 0x44, 0xEA, ++0x06, 0x44, 0x48, 0xF0, 0x02, 0x05, 0x1C, 0x61, 0x83, 0xF8, 0x30, 0x50, 0x01, 0x24, 0x58, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, ++0x2F, 0xD0, 0x9E, 0x7A, 0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x4F, 0x4E, ++0x04, 0xF5, 0xEC, 0x74, 0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x02, 0xF1, 0x12, 0x05, 0x66, 0x46, ++0x1D, 0x72, 0x56, 0xF8, 0x02, 0x7F, 0x93, 0xF8, 0x30, 0x50, 0x76, 0x68, 0x1C, 0x62, 0x45, 0xF0, 0x02, 0x04, 0x83, 0xF8, ++0x30, 0x40, 0xC3, 0xE9, 0x04, 0x76, 0x01, 0x24, 0x33, 0xE7, 0x5C, 0x7A, 0x42, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, ++0x04, 0x54, 0xA8, 0xE7, 0x5C, 0x7A, 0x3F, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0x54, 0xB7, 0xE7, 0x5C, 0x7A, ++0x3B, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0x54, 0xD8, 0xE7, 0x59, 0x7A, 0x39, 0x4D, 0x4F, 0xF4, 0x1E, 0x74, ++0x04, 0xFB, 0x01, 0xF4, 0x29, 0x19, 0x91, 0xF8, 0x98, 0x10, 0x01, 0x29, 0x43, 0xD0, 0x02, 0x29, 0x04, 0xD1, 0x34, 0x48, ++0xF7, 0xF7, 0x36, 0xF8, 0x00, 0x24, 0x15, 0xE7, 0x0A, 0x1F, 0x01, 0x2A, 0xF7, 0xD9, 0x18, 0x7A, 0xBC, 0xF8, 0x02, 0x10, ++0x9D, 0x7A, 0x2B, 0x4E, 0x04, 0x30, 0x18, 0x72, 0xDC, 0xF8, 0x00, 0x40, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x05, 0xF2, ++0x89, 0x0B, 0xE5, 0x17, 0xC1, 0xEB, 0x01, 0x11, 0x02, 0xF5, 0xEC, 0x72, 0xC3, 0xE9, 0x04, 0x45, 0x02, 0xEB, 0xC1, 0x02, ++0x32, 0x44, 0x92, 0xF8, 0x63, 0x10, 0x00, 0x29, 0xDE, 0xD0, 0x1A, 0x62, 0x01, 0x24, 0xF3, 0xE6, 0x19, 0x7A, 0x93, 0xF8, ++0x30, 0xE0, 0x08, 0x31, 0x19, 0x72, 0x82, 0x5A, 0x9C, 0xF8, 0x02, 0x80, 0xBC, 0xF8, 0x04, 0x00, 0xBC, 0xF8, 0x06, 0x90, ++0x12, 0x02, 0x92, 0xB2, 0xD1, 0x17, 0x48, 0xEA, 0x00, 0x40, 0x49, 0xEA, 0x01, 0x09, 0x02, 0x43, 0x4E, 0xF0, 0x03, 0x0E, ++0xC3, 0xE9, 0x04, 0x29, 0x83, 0xF8, 0x30, 0xE0, 0x08, 0xE7, 0x19, 0x7A, 0x93, 0xF8, 0x30, 0x70, 0x08, 0x31, 0x19, 0x72, ++0x81, 0x5A, 0xBC, 0xF8, 0x04, 0x80, 0x9C, 0xF8, 0x02, 0x00, 0xBC, 0xF8, 0x06, 0x60, 0x09, 0x02, 0x89, 0xB2, 0x04, 0xF1, ++0x38, 0x02, 0x40, 0xEA, 0x08, 0x44, 0x0C, 0x43, 0xC9, 0x17, 0x47, 0xF0, 0x03, 0x07, 0x0E, 0x43, 0xC3, 0xE9, 0x04, 0x46, ++0x2A, 0x44, 0x83, 0xF8, 0x30, 0x70, 0xC0, 0xE7, 0xB0, 0xDE, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xA0, 0x65, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x34, 0xC0, 0x15, 0x00, 0x70, 0xB5, 0x18, 0x4E, 0x18, 0x4A, 0xB3, 0x7A, ++0x75, 0x7A, 0x12, 0x7C, 0x1B, 0x02, 0x43, 0xEA, 0x05, 0x43, 0xF5, 0x7A, 0x04, 0x46, 0x00, 0x6E, 0x43, 0xEA, 0x05, 0x63, ++0xFF, 0x2A, 0x0D, 0x46, 0x43, 0xEA, 0x00, 0x03, 0x17, 0xD0, 0x41, 0xF0, 0x80, 0x05, 0x43, 0xF0, 0x80, 0x03, 0xEA, 0x07, ++0x48, 0xBF, 0x43, 0xF0, 0x40, 0x03, 0x0D, 0x4A, 0x58, 0xBF, 0x23, 0xF0, 0x40, 0x03, 0x23, 0x66, 0x20, 0x46, 0xD2, 0xF8, ++0xA8, 0x32, 0x98, 0x47, 0x32, 0x6C, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xEF, 0xBD, 0x29, 0x06, ++0x58, 0xBF, 0x23, 0xF0, 0x80, 0x03, 0xE6, 0xD5, 0xE3, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x21, 0x4B, 0x21, 0x4E, 0x1B, 0x7C, 0xFF, 0x2B, 0x04, 0x46, 0x0D, 0x46, 0x21, 0xD0, ++0xB2, 0x7A, 0xFF, 0x2A, 0x32, 0xD0, 0x01, 0xF0, 0x01, 0x01, 0x45, 0xF0, 0x80, 0x05, 0x77, 0x7A, 0x20, 0x6E, 0x13, 0x02, ++0x43, 0xEA, 0x07, 0x43, 0x03, 0x43, 0x43, 0xF0, 0x82, 0x03, 0x11, 0xB3, 0x43, 0xF0, 0x40, 0x03, 0x16, 0x49, 0x23, 0x66, ++0x00, 0x22, 0xD1, 0xF8, 0xA8, 0x32, 0x86, 0xF8, 0x32, 0x20, 0x20, 0x46, 0x98, 0x47, 0x32, 0x6C, 0x29, 0x46, 0x20, 0x46, ++0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0xB8, 0xBD, 0xB3, 0x7A, 0x71, 0x7A, 0x02, 0x6E, 0x1B, 0x02, 0x43, 0xEA, 0x01, 0x43, ++0x13, 0x43, 0x2A, 0x06, 0x0D, 0xD4, 0x23, 0xF0, 0x80, 0x03, 0x05, 0xF0, 0x01, 0x01, 0x43, 0xF0, 0x02, 0x03, 0x00, 0x29, ++0xDC, 0xD1, 0x23, 0xF0, 0x40, 0x03, 0xDB, 0xE7, 0x00, 0x21, 0x80, 0x25, 0xCD, 0xE7, 0x05, 0xF0, 0x01, 0x01, 0xD0, 0xE7, ++0x00, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x32, 0x4B, 0x01, 0x88, 0x70, 0xB4, 0x19, 0x80, ++0xC2, 0x8A, 0x5A, 0x80, 0x01, 0xF0, 0x88, 0x06, 0xC2, 0xF3, 0x0B, 0x14, 0x00, 0x25, 0x02, 0xF0, 0x0F, 0x02, 0x88, 0x2E, ++0x9C, 0x80, 0x9A, 0x71, 0x8C, 0xB2, 0x83, 0xF8, 0x30, 0x50, 0x45, 0xD0, 0xDD, 0x71, 0x04, 0xF4, 0x40, 0x72, 0xB2, 0xF5, ++0x40, 0x7F, 0x04, 0xF0, 0xFC, 0x05, 0x0C, 0xBF, 0x1E, 0x22, 0x18, 0x22, 0x88, 0x2D, 0x08, 0xBF, 0x02, 0x32, 0x0E, 0x04, ++0x44, 0xBF, 0x04, 0x32, 0xD2, 0xB2, 0x1A, 0x72, 0x02, 0x79, 0xD5, 0x07, 0x44, 0xBF, 0x08, 0x22, 0x83, 0xF8, 0x30, 0x20, ++0xE4, 0x05, 0x12, 0xD5, 0x02, 0x8A, 0x9A, 0x84, 0x42, 0x8A, 0xDA, 0x84, 0x82, 0x8A, 0x1A, 0x85, 0x02, 0x88, 0x91, 0x05, ++0x12, 0xD5, 0xD2, 0x05, 0x18, 0xD5, 0x02, 0x8B, 0x5A, 0x85, 0x42, 0x8B, 0x9A, 0x85, 0x82, 0x8B, 0xDA, 0x85, 0x70, 0xBC, ++0x70, 0x47, 0x82, 0x88, 0x9A, 0x84, 0xC2, 0x88, 0xDA, 0x84, 0x02, 0x89, 0x1A, 0x85, 0x02, 0x88, 0x91, 0x05, 0xEC, 0xD4, ++0x42, 0x89, 0x5A, 0x85, 0x82, 0x89, 0x9A, 0x85, 0xC2, 0x89, 0xDA, 0x85, 0x70, 0xBC, 0x70, 0x47, 0x02, 0x8A, 0x5A, 0x85, ++0x42, 0x8A, 0x9A, 0x85, 0x82, 0x8A, 0xDA, 0x85, 0x70, 0xBC, 0x70, 0x47, 0x04, 0xF4, 0x40, 0x72, 0xB2, 0xF5, 0x40, 0x7F, ++0x0C, 0xBF, 0xC5, 0x8B, 0x05, 0x8B, 0x05, 0xF0, 0x07, 0x05, 0xDD, 0x71, 0xB1, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, ++0xF8, 0xB5, 0x05, 0x22, 0x18, 0x23, 0x0C, 0x21, 0x41, 0xF2, 0x06, 0x40, 0xF5, 0xF7, 0x74, 0xF8, 0x0F, 0x4A, 0x03, 0x46, ++0x51, 0x7A, 0x0F, 0x48, 0x94, 0x69, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x01, 0x01, 0xD2, 0xE9, 0x04, 0x67, 0x51, 0xF8, ++0x26, 0x0F, 0x89, 0x88, 0x99, 0x80, 0xC3, 0xE9, 0x02, 0x67, 0x18, 0x60, 0x91, 0x7A, 0x99, 0x74, 0xC4, 0xF3, 0x80, 0x24, ++0x1C, 0x74, 0x12, 0x6A, 0x92, 0xF8, 0x61, 0x20, 0x5A, 0x74, 0x18, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xF5, 0xF7, 0x84, 0xB8, ++0xB0, 0xDE, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x3C, 0x82, 0xD8, 0xF8, 0x00, 0x40, ++0x27, 0x78, 0x87, 0xB0, 0x17, 0xF0, 0x01, 0x07, 0x04, 0x46, 0x03, 0x93, 0x08, 0xD0, 0x43, 0x6D, 0x03, 0xF0, 0x07, 0x03, ++0x02, 0x2B, 0x7F, 0xD0, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x80, 0x4D, 0x89, 0x46, 0x00, 0x2A, 0x40, 0xF0, ++0xA2, 0x80, 0x02, 0x8E, 0x2B, 0x7A, 0xC6, 0x69, 0xD4, 0x1A, 0x03, 0x9A, 0xA4, 0xB2, 0x10, 0x31, 0x12, 0xB1, 0x07, 0x2C, ++0x40, 0xF2, 0xA9, 0x80, 0x08, 0x22, 0x48, 0x46, 0xFA, 0xF7, 0x92, 0xFF, 0x29, 0x7A, 0x8A, 0xB2, 0xD6, 0xE9, 0x02, 0x03, ++0x08, 0x3C, 0x01, 0x33, 0xA5, 0xB2, 0x1C, 0x1A, 0xA4, 0xB2, 0x4B, 0x19, 0x9C, 0x42, 0x01, 0x44, 0x80, 0xF2, 0x82, 0x80, ++0xDF, 0xF8, 0xD4, 0xA1, 0x13, 0x1B, 0x1D, 0x44, 0xA2, 0x1A, 0x92, 0xB2, 0x48, 0x46, 0xAD, 0xB2, 0xFA, 0xF7, 0x7A, 0xFF, ++0x00, 0x22, 0x95, 0xB1, 0xDA, 0xF8, 0x00, 0x30, 0x76, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x93, 0x42, 0x4D, 0xDB, 0xD6, 0xE9, ++0x02, 0x14, 0x01, 0x34, 0x64, 0x1A, 0xA4, 0xB2, 0xAC, 0x42, 0xE7, 0xD3, 0x2C, 0x46, 0x2A, 0x46, 0x48, 0x46, 0xFA, 0xF7, ++0x65, 0xFF, 0xDF, 0xF8, 0x98, 0xE1, 0x0D, 0xF1, 0x10, 0x0C, 0x08, 0x25, 0xD6, 0xE9, 0x02, 0x32, 0x01, 0x32, 0x98, 0xB2, ++0x92, 0xB2, 0xA2, 0xEB, 0x00, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x29, 0x19, 0x51, 0x45, 0x23, 0x44, 0x3B, 0xDD, 0xAA, 0xEB, ++0x04, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x0A, 0xF1, 0xFF, 0x3B, 0xBA, 0xF1, 0x00, 0x0F, 0x37, 0xD0, 0x82, 0x1A, 0x14, 0x44, ++0x25, 0x44, 0xAD, 0xB2, 0x59, 0x1C, 0x59, 0x44, 0xAC, 0xEB, 0x03, 0x00, 0x1A, 0x78, 0xC2, 0x54, 0x01, 0x33, 0x8B, 0x42, ++0xFA, 0xD1, 0xD4, 0x44, 0x65, 0xB3, 0xDE, 0xF8, 0x00, 0x30, 0x76, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x24, 0xA3, 0x42, ++0xD2, 0xDA, 0x00, 0x2E, 0xD0, 0xD1, 0x47, 0x49, 0x47, 0x48, 0x40, 0xF2, 0x66, 0x42, 0xF7, 0xF7, 0x6F, 0xF8, 0x7F, 0xE7, ++0xFF, 0xF7, 0x40, 0xFF, 0x00, 0x27, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2E, 0xAF, 0xD1, 0x3F, 0x49, ++0x3F, 0x48, 0x40, 0xF2, 0x3C, 0x42, 0xF7, 0xF7, 0x5F, 0xF8, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xAA, 0x46, ++0x05, 0xF1, 0xFF, 0x3B, 0x00, 0x25, 0xCB, 0xE7, 0x01, 0x44, 0x8A, 0x1A, 0x95, 0xB2, 0xD2, 0xE7, 0x03, 0x9B, 0x00, 0x2B, ++0x3C, 0xD1, 0xDD, 0xE9, 0x04, 0x23, 0xC9, 0xE9, 0x04, 0x23, 0x01, 0x27, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x2A, 0x44, 0x94, 0xB2, 0x95, 0xE7, 0x29, 0x6A, 0xEB, 0x79, 0x00, 0x93, 0x58, 0x31, 0x05, 0xF1, 0x2A, 0x03, 0x05, 0xF1, ++0x24, 0x02, 0x48, 0x46, 0xFA, 0xF7, 0xCE, 0xFE, 0x29, 0x7A, 0x23, 0x8E, 0xE6, 0x69, 0x5C, 0x1A, 0xA4, 0xB2, 0x8A, 0xB2, ++0x5C, 0xE7, 0xB5, 0x68, 0x03, 0x91, 0x22, 0x46, 0x48, 0x46, 0x1D, 0x44, 0xFA, 0xF7, 0xE6, 0xFE, 0x03, 0x99, 0xC4, 0xF1, ++0x08, 0x06, 0x04, 0xAB, 0xF6, 0xB2, 0x21, 0x44, 0xF2, 0x18, 0xC9, 0x1A, 0xC8, 0x5C, 0x03, 0xF8, 0x01, 0x0B, 0x9A, 0x42, ++0xFA, 0xD1, 0xD6, 0xF1, 0x08, 0x06, 0x07, 0xD0, 0x2B, 0x46, 0xD2, 0x1A, 0x35, 0x44, 0x19, 0x78, 0xD1, 0x54, 0x01, 0x33, ++0x9D, 0x42, 0xFA, 0xD1, 0x48, 0x46, 0xFA, 0xF7, 0x69, 0xFF, 0x04, 0x9A, 0xD9, 0xF8, 0x00, 0x30, 0x9A, 0x42, 0x0D, 0xD0, ++0xD8, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x9B, 0x07, 0x05, 0xD5, 0x03, 0x20, 0xD8, 0xF7, 0xCE, 0xF9, 0x0F, 0x4B, 0x98, 0x42, ++0x12, 0xD1, 0xFF, 0xF7, 0xD1, 0xFE, 0x0D, 0xE7, 0xD9, 0xF8, 0x04, 0x30, 0x05, 0x9A, 0x9A, 0x42, 0xEC, 0xD1, 0xD8, 0xF8, ++0x00, 0x30, 0x1B, 0x78, 0x9A, 0x07, 0xA6, 0xD5, 0x03, 0x20, 0xD8, 0xF7, 0xBB, 0xF9, 0x06, 0x4B, 0x98, 0x42, 0xA0, 0xD0, ++0x05, 0x48, 0xF6, 0xF7, 0xA1, 0xFD, 0xF9, 0xE6, 0xB0, 0xDE, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, ++0x1C, 0xDF, 0x44, 0x21, 0x44, 0xC0, 0x15, 0x00, 0x34, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x10, 0xB5, 0x10, 0x48, ++0xF5, 0xF7, 0xF8, 0xFB, 0x10, 0xB1, 0x04, 0x46, 0x20, 0x46, 0x10, 0xBD, 0x0D, 0x48, 0xF5, 0xF7, 0xF1, 0xFB, 0x0D, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x06, 0xDB, 0x62, 0x69, 0x04, 0x21, 0x00, 0x20, 0xFF, 0xF7, ++0xC7, 0xFB, 0x20, 0x46, 0x10, 0xBD, 0x00, 0x28, 0xF6, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xEA, 0x42, 0xF6, 0xF7, ++0xEB, 0xFF, 0xEF, 0xE7, 0x00, 0xDF, 0x17, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x54, 0xC0, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x63, 0x79, 0x62, 0x69, 0x83, 0x42, 0x14, 0xBF, 0x18, 0x21, ++0x08, 0x21, 0xFF, 0xF7, 0xA7, 0xFB, 0x08, 0xB1, 0xA3, 0x89, 0x83, 0x64, 0x10, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, ++0xA3, 0x4F, 0x8A, 0xB0, 0x05, 0x46, 0x14, 0x46, 0x1A, 0xB3, 0x3E, 0x88, 0x97, 0xF8, 0x07, 0x80, 0x16, 0xF4, 0x80, 0x66, ++0x22, 0xD1, 0x97, 0xF8, 0x06, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x6A, 0xD0, 0xBC, 0x6D, 0xBA, 0x88, 0x14, 0xB9, 0x31, 0xE1, ++0x24, 0x68, 0xEC, 0xB1, 0xA3, 0x79, 0x8B, 0x42, 0xFA, 0xD1, 0xE3, 0x79, 0x43, 0x45, 0xF7, 0xD1, 0x63, 0x89, 0x93, 0x42, ++0xF4, 0xD1, 0x23, 0x7A, 0x53, 0x45, 0x00, 0xF0, 0x90, 0x80, 0x4F, 0xF0, 0x00, 0x0A, 0x50, 0x46, 0x0A, 0xB0, 0xBD, 0xE8, ++0xF0, 0x87, 0x3E, 0x88, 0x16, 0xF4, 0x80, 0x66, 0x90, 0x46, 0xDC, 0xD0, 0xBC, 0x6D, 0xBA, 0x88, 0x97, 0xF8, 0x06, 0xA0, ++0x00, 0x2C, 0xE1, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0xEB, 0xD1, 0x03, 0x91, 0xFF, 0xF7, 0x88, 0xFF, 0x01, 0x26, 0x03, 0x99, ++0x81, 0x71, 0x80, 0xF8, 0x07, 0x80, 0x06, 0x72, 0xBA, 0x88, 0x80, 0xF8, 0x04, 0xA0, 0x39, 0x7A, 0x82, 0x4B, 0xC0, 0xF8, ++0x10, 0xA0, 0x41, 0x72, 0x19, 0x69, 0xDF, 0xF8, 0x0C, 0x92, 0x80, 0x4B, 0x42, 0x81, 0x01, 0xF5, 0xC3, 0x31, 0x83, 0x63, ++0xC0, 0x63, 0xD9, 0xF8, 0xE0, 0x31, 0x04, 0x46, 0xA0, 0x31, 0x34, 0x30, 0x98, 0x47, 0x97, 0xF8, 0x30, 0x30, 0xDA, 0x07, ++0x00, 0xF1, 0xC9, 0x80, 0x2B, 0x6E, 0x23, 0xF0, 0x20, 0x03, 0x2B, 0x66, 0xD9, 0xF8, 0xE8, 0x32, 0x01, 0x21, 0x28, 0x46, ++0x98, 0x47, 0x3B, 0x6C, 0xFA, 0x69, 0x73, 0x48, 0xC4, 0xE9, 0x04, 0x23, 0x97, 0xF8, 0x31, 0x30, 0x63, 0x71, 0x2B, 0x8E, ++0xA3, 0x81, 0x21, 0x46, 0xF5, 0xF7, 0x08, 0xFB, 0x6B, 0x4B, 0x4F, 0xF0, 0x01, 0x0A, 0x1B, 0x69, 0xA3, 0x61, 0x50, 0x46, ++0x0A, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x97, 0xF8, 0x30, 0x30, 0xD8, 0x07, 0x1D, 0xD5, 0x68, 0x4A, 0x01, 0x23, 0xD2, 0xF8, ++0xCC, 0x62, 0x04, 0xA9, 0x1A, 0x46, 0x28, 0x46, 0xB0, 0x47, 0x00, 0x28, 0x9B, 0xD0, 0x2B, 0x8E, 0x63, 0x4A, 0x08, 0x3B, ++0x12, 0x68, 0x2B, 0x86, 0x13, 0x78, 0x99, 0x07, 0x0B, 0xD5, 0x6B, 0x6D, 0x03, 0xF0, 0x3C, 0x02, 0x3C, 0x2A, 0x06, 0xD1, ++0x23, 0xF0, 0x7C, 0x03, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xF0, 0x08, 0x03, 0x6B, 0x65, 0x5B, 0x4B, 0xB8, 0x7A, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC3, 0x34, 0x00, 0x2B, 0x6D, 0xD1, 0x54, 0x4B, 0x28, 0x46, 0xD3, 0xF8, ++0xE8, 0x32, 0x03, 0x21, 0x98, 0x47, 0x4F, 0xF0, 0x01, 0x0A, 0x50, 0x46, 0x0A, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x29, 0x8E, ++0x94, 0xF8, 0x09, 0x80, 0xA3, 0x89, 0xDF, 0xF8, 0x30, 0x91, 0xA1, 0xEB, 0x08, 0x08, 0x1F, 0xFA, 0x88, 0xF8, 0x43, 0x44, ++0x0A, 0xF1, 0x01, 0x0A, 0x84, 0xF8, 0x08, 0xA0, 0xA3, 0x81, 0x97, 0xF8, 0x30, 0x30, 0xDB, 0x07, 0x22, 0xD5, 0xB6, 0xFA, ++0x86, 0xF3, 0xD9, 0xF8, 0xCC, 0x72, 0x5B, 0x09, 0x00, 0x22, 0x04, 0xF1, 0x1C, 0x01, 0x28, 0x46, 0xB8, 0x47, 0x00, 0x28, ++0x4C, 0xD0, 0x2B, 0x6E, 0x00, 0x2E, 0x57, 0xD0, 0x61, 0x7A, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, 0x40, 0x03, ++0x2B, 0x66, 0x41, 0x44, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0xD9, 0xF8, 0xA4, 0x62, 0x89, 0xB2, 0x28, 0x46, 0xB0, 0x47, ++0x23, 0x69, 0x43, 0x44, 0x23, 0x61, 0x87, 0xE7, 0x01, 0x27, 0x2B, 0x6E, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, ++0x40, 0x03, 0x2B, 0x66, 0x00, 0x23, 0xCD, 0xE9, 0x00, 0x33, 0x28, 0x46, 0xD9, 0xF8, 0xA4, 0x52, 0xA8, 0x47, 0x23, 0x69, ++0x43, 0x44, 0x23, 0x61, 0x00, 0x2E, 0x7F, 0xF4, 0x73, 0xAF, 0x20, 0x46, 0xFF, 0xF7, 0xEC, 0xFE, 0x62, 0x69, 0x39, 0x46, ++0x00, 0x20, 0xFF, 0xF7, 0x99, 0xFA, 0xD9, 0xF8, 0xD8, 0x31, 0x04, 0xF1, 0x34, 0x00, 0x98, 0x47, 0x21, 0x46, 0x20, 0x48, ++0xF5, 0xF7, 0xBA, 0xFA, 0x22, 0x48, 0x21, 0x46, 0xF5, 0xF7, 0x66, 0xFA, 0x5C, 0xE7, 0xEA, 0x69, 0x00, 0xF2, 0xC4, 0x41, ++0x92, 0x68, 0x23, 0x46, 0x63, 0x30, 0xFF, 0xF7, 0x31, 0xFA, 0x01, 0x28, 0x87, 0xD1, 0x04, 0xE7, 0x61, 0x7A, 0x41, 0x44, ++0x89, 0xB2, 0x04, 0x27, 0xC5, 0xE7, 0x32, 0x46, 0x53, 0x46, 0xD9, 0xF8, 0xCC, 0x62, 0x04, 0xF1, 0x1C, 0x01, 0x28, 0x46, ++0xB0, 0x47, 0x2D, 0xE7, 0xA0, 0x89, 0x61, 0x7A, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, 0x40, 0x03, 0x08, 0x38, ++0xA0, 0x81, 0x41, 0x44, 0x2B, 0x66, 0x28, 0x46, 0x33, 0x46, 0xCD, 0xE9, 0x00, 0x66, 0xD9, 0xF8, 0xA4, 0x52, 0x89, 0xB2, ++0xA8, 0x47, 0x23, 0x69, 0x43, 0x44, 0x23, 0x61, 0x01, 0x27, 0xB8, 0xE7, 0xA2, 0x46, 0xDC, 0xE6, 0xB0, 0xDE, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0xC5, 0xD3, 0x14, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x00, 0xDF, 0x17, 0x00, 0xF8, 0xB5, 0x03, 0x88, 0x13, 0x4D, 0x13, 0xF4, 0x00, 0x6F, 0x04, 0x46, ++0xC3, 0x8A, 0x0B, 0xD1, 0x05, 0xF1, 0x60, 0x07, 0x00, 0xF1, 0x0A, 0x06, 0x30, 0x68, 0xB2, 0x88, 0xBA, 0x80, 0x28, 0x66, ++0xA5, 0xF8, 0x66, 0x30, 0x01, 0x20, 0xF8, 0xBD, 0xB5, 0xF8, 0x66, 0x20, 0x9A, 0x42, 0x04, 0xD0, 0x00, 0xF1, 0x0A, 0x06, ++0x05, 0xF1, 0x60, 0x07, 0xEE, 0xE7, 0x05, 0xF1, 0x60, 0x07, 0x00, 0xF1, 0x0A, 0x06, 0x39, 0x46, 0x30, 0x46, 0x06, 0x22, ++0x09, 0xF0, 0xC6, 0xF8, 0x00, 0x28, 0xEA, 0xD0, 0xE3, 0x8A, 0xE1, 0xE7, 0xB0, 0xDE, 0x17, 0x00, 0xF0, 0xB4, 0x01, 0xB3, ++0x00, 0x22, 0x87, 0x7A, 0x94, 0x46, 0x07, 0xE0, 0x1E, 0x69, 0x1E, 0xB1, 0x01, 0x3C, 0xC3, 0xF8, 0x10, 0xC0, 0xC4, 0x72, ++0x8D, 0x42, 0x09, 0xD2, 0xBB, 0x18, 0xC4, 0x7A, 0x03, 0xF0, 0x3F, 0x03, 0x01, 0x32, 0x00, 0xEB, 0x83, 0x03, 0x95, 0xB2, ++0x00, 0x2C, 0xED, 0xD1, 0x03, 0x89, 0x0F, 0x44, 0x19, 0x44, 0x07, 0xF0, 0x3F, 0x07, 0xC1, 0xF3, 0x0B, 0x01, 0x87, 0x72, ++0x01, 0x81, 0xF0, 0xBC, 0x70, 0x47, 0x87, 0x7A, 0xF2, 0xE7, 0x00, 0xBF, 0xF8, 0xB5, 0x83, 0x7A, 0x04, 0x33, 0x50, 0xF8, ++0x23, 0x30, 0x53, 0xB3, 0xC1, 0x7A, 0x15, 0x4D, 0x15, 0x4F, 0x16, 0x4E, 0x04, 0x46, 0x15, 0xE0, 0xA3, 0x7A, 0x22, 0x89, ++0x18, 0x1D, 0x01, 0x33, 0x03, 0xF0, 0x3F, 0x03, 0x01, 0x39, 0x4F, 0xF0, 0x00, 0x0C, 0x44, 0xF8, 0x20, 0xC0, 0xC9, 0xB2, ++0x18, 0x1D, 0xA3, 0x72, 0xE1, 0x72, 0x54, 0xF8, 0x20, 0x00, 0x53, 0x1C, 0xC3, 0xF3, 0x0B, 0x03, 0x23, 0x81, 0x70, 0xB1, ++0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE4, 0xDA, 0x00, 0x29, 0xE2, 0xD1, 0x39, 0x46, 0x4F, 0xF4, 0xD6, 0x62, ++0x30, 0x46, 0xF6, 0xF7, 0xF5, 0xFD, 0xE1, 0x7A, 0xDA, 0xE7, 0xF8, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x9E, 0x23, 0x0C, 0x8A, 0x38, 0x4A, 0x03, 0xFB, 0x00, 0xF0, 0x00, 0xEB, ++0x14, 0x30, 0x02, 0xEB, 0x80, 0x00, 0xD0, 0xF8, 0x7C, 0x41, 0x4C, 0xB3, 0x94, 0xF8, 0x21, 0x31, 0x49, 0x8A, 0xC3, 0xB1, ++0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x30, 0xD5, 0x30, 0x48, 0x31, 0x4D, 0x03, 0x68, 0x2E, 0x68, 0x03, 0xF0, 0x60, 0x42, ++0x77, 0x1C, 0xB2, 0xF1, 0xC0, 0x4F, 0x2F, 0x60, 0x31, 0xD0, 0x2D, 0x4B, 0x80, 0x22, 0x1A, 0x60, 0x2F, 0xB1, 0x2C, 0x4B, ++0x2E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x22, 0x89, 0xB2, 0xEB, 0x11, 0x1F, 0x4F, 0xEA, 0x11, 0x13, ++0x06, 0xD0, 0x9B, 0x1A, 0x99, 0xB2, 0x1B, 0x05, 0x04, 0xD5, 0x94, 0xF8, 0x21, 0x31, 0x9B, 0xB1, 0xBD, 0xE8, 0xF0, 0x81, ++0x22, 0x4D, 0x20, 0x46, 0xD5, 0xF8, 0xD8, 0x32, 0xC1, 0xF3, 0x0B, 0x01, 0x98, 0x47, 0xD5, 0xF8, 0x38, 0x31, 0x1F, 0x48, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xC9, 0xE7, 0x1B, 0x48, 0xF6, 0xF7, ++0x23, 0xFB, 0x01, 0x23, 0x84, 0xF8, 0x21, 0x31, 0xE4, 0xE7, 0x19, 0x4A, 0x03, 0xF4, 0xF0, 0x33, 0xD2, 0xF8, 0x00, 0xC0, ++0xB3, 0xF5, 0xF0, 0x3F, 0x0C, 0xF1, 0x10, 0x0C, 0xC3, 0xD0, 0x96, 0x46, 0x03, 0x68, 0x03, 0xF0, 0x60, 0x42, 0xB2, 0xF1, ++0xC0, 0x4F, 0x02, 0xD0, 0x10, 0x4B, 0x1B, 0x68, 0xB9, 0xE7, 0x03, 0xF4, 0xF0, 0x33, 0xB3, 0xF5, 0xF0, 0x3F, 0xF7, 0xD0, ++0xDE, 0xF8, 0x00, 0x30, 0xA3, 0xEB, 0x0C, 0x03, 0x00, 0x2B, 0xEB, 0xDB, 0x00, 0x2F, 0xB6, 0xD0, 0xAF, 0xE7, 0x00, 0xBF, ++0x68, 0x65, 0x17, 0x00, 0x04, 0x05, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x54, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0x7C, 0xC0, 0x15, 0x00, 0x20, 0x01, 0x32, 0x40, 0x2D, 0xE9, 0xF8, 0x43, ++0x8D, 0x4F, 0x8E, 0x4B, 0xBC, 0x7A, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x80, 0x46, 0x94, 0xF8, 0xC3, 0x54, ++0x89, 0x46, 0x00, 0x2D, 0x40, 0xF0, 0x90, 0x80, 0xF8, 0x79, 0x88, 0x49, 0xBA, 0x88, 0x9E, 0x23, 0x03, 0xFB, 0x09, 0x03, ++0x01, 0xEB, 0x83, 0x03, 0xD3, 0xF8, 0x7C, 0x41, 0x23, 0x89, 0x9A, 0x42, 0x00, 0xF0, 0xA5, 0x80, 0xD2, 0x1A, 0x12, 0xF4, ++0x7C, 0x6F, 0xC2, 0xF3, 0x0B, 0x03, 0x38, 0xD1, 0xA6, 0x7A, 0x1E, 0x44, 0x06, 0xF0, 0x3F, 0x06, 0x01, 0x23, 0x04, 0xEB, ++0x86, 0x06, 0x84, 0xF8, 0x20, 0x31, 0x33, 0x69, 0x00, 0x2B, 0x6B, 0xD1, 0x8D, 0xB9, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, ++0x32, 0x30, 0x77, 0x49, 0x42, 0xF0, 0x20, 0x02, 0xC8, 0xF8, 0x60, 0x20, 0x23, 0xF0, 0xFF, 0x03, 0xD1, 0xF8, 0xE8, 0x22, ++0xA8, 0xF8, 0x32, 0x30, 0x40, 0x46, 0x03, 0x21, 0x90, 0x47, 0x71, 0x4B, 0x33, 0x61, 0xE3, 0x7A, 0x70, 0x4A, 0x01, 0x33, ++0x12, 0x68, 0xDB, 0xB2, 0xE3, 0x72, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xB1, 0x80, 0x01, 0x2B, 0x00, 0xF0, ++0xB9, 0x80, 0xC5, 0xF1, 0x01, 0x05, 0xED, 0xB2, 0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xFE, 0xFE, 0x28, 0x46, 0xBD, 0xE8, ++0xF8, 0x83, 0x40, 0xF2, 0xFE, 0x72, 0x93, 0x42, 0x40, 0xF2, 0x91, 0x80, 0x94, 0xF8, 0x20, 0x31, 0x13, 0xB1, 0x94, 0xF8, ++0x21, 0x31, 0x9B, 0xB3, 0x3B, 0x88, 0x1B, 0x05, 0x21, 0xD4, 0x7A, 0x88, 0x4F, 0xF4, 0x9E, 0x73, 0x03, 0xFB, 0x09, 0x03, ++0x01, 0xEB, 0x43, 0x03, 0xA3, 0xF8, 0xEA, 0x21, 0x15, 0xBB, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, 0x32, 0x30, 0x55, 0x49, ++0x42, 0xF0, 0x20, 0x02, 0x23, 0xF0, 0xFF, 0x03, 0xC8, 0xF8, 0x60, 0x20, 0xD1, 0xF8, 0xE8, 0x22, 0xA8, 0xF8, 0x32, 0x30, ++0x40, 0x46, 0x03, 0x21, 0x90, 0x47, 0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xCD, 0xFE, 0x01, 0x25, 0xCC, 0xE7, 0x4F, 0xF4, ++0x9E, 0x73, 0x03, 0xFB, 0x09, 0x03, 0x01, 0xEB, 0x43, 0x03, 0x7A, 0x88, 0xB3, 0xF8, 0xEA, 0x31, 0x93, 0x42, 0xD3, 0xD1, ++0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xBC, 0xFE, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0xC2, 0x69, 0x04, 0xF2, ++0xC4, 0x41, 0x92, 0x68, 0x01, 0x23, 0x04, 0xF1, 0x63, 0x00, 0xFF, 0xF7, 0x3B, 0xF8, 0x05, 0x46, 0xF8, 0x79, 0x3B, 0x49, ++0xBA, 0x88, 0x9E, 0x23, 0x03, 0xFB, 0x09, 0x03, 0x01, 0xEB, 0x83, 0x03, 0x01, 0x2D, 0xD3, 0xF8, 0x7C, 0x41, 0x23, 0x89, ++0x60, 0xD0, 0x9A, 0x42, 0x09, 0xD0, 0xD2, 0x1A, 0x12, 0xF4, 0x7C, 0x6F, 0x4F, 0xF0, 0x00, 0x05, 0xC2, 0xF3, 0x0B, 0x03, ++0x3F, 0xF4, 0x62, 0xAF, 0x99, 0xE7, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, 0x32, 0x30, 0x2E, 0x49, 0x42, 0xF0, 0x20, 0x02, ++0x23, 0xF0, 0xFF, 0x03, 0xC8, 0xF8, 0x60, 0x20, 0xD1, 0xF8, 0xE8, 0x22, 0xA8, 0xF8, 0x32, 0x30, 0x40, 0x46, 0x03, 0x21, ++0x90, 0x47, 0x23, 0x89, 0x01, 0x25, 0x01, 0x20, 0x28, 0x4A, 0xA1, 0x7A, 0x84, 0xF8, 0x20, 0x01, 0x12, 0x69, 0x62, 0x60, ++0x04, 0xEB, 0x81, 0x00, 0x02, 0x69, 0x12, 0xB1, 0xE2, 0x7A, 0x01, 0x3A, 0xE2, 0x72, 0x5A, 0x1C, 0x01, 0x31, 0xC2, 0xF3, ++0x0B, 0x02, 0x01, 0xF0, 0x3F, 0x01, 0x00, 0x23, 0x03, 0x61, 0x20, 0x46, 0x22, 0x81, 0xA1, 0x72, 0xFF, 0xF7, 0x4E, 0xFE, ++0x62, 0xE7, 0x18, 0x4A, 0xA3, 0xF1, 0x3F, 0x01, 0x89, 0xB2, 0xD2, 0xF8, 0xD8, 0x32, 0x20, 0x46, 0x98, 0x47, 0xBB, 0x88, ++0x21, 0x89, 0x5B, 0x1A, 0xC3, 0xF3, 0x0B, 0x03, 0x22, 0xE7, 0x40, 0x2B, 0x7F, 0xF6, 0x4C, 0xAF, 0x13, 0x49, 0x14, 0x48, ++0x40, 0xF2, 0xDB, 0x72, 0xF6, 0xF7, 0x5A, 0xFC, 0xE3, 0x7A, 0x43, 0xE7, 0x0E, 0x4A, 0x0B, 0x4B, 0x11, 0x69, 0xD3, 0xF8, ++0xE0, 0x31, 0x01, 0xF5, 0x43, 0x41, 0x04, 0xF5, 0x88, 0x70, 0x50, 0x31, 0x98, 0x47, 0x3A, 0xE7, 0x9A, 0x42, 0x7F, 0xF4, ++0x03, 0xAF, 0x00, 0x25, 0xB9, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x87, 0xA9, 0xDC, 0xFE, 0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x90, 0xC0, 0x15, 0x00, 0xC3, 0x7A, 0x03, 0xB9, 0x70, 0x47, 0x1A, 0x4B, 0x42, 0x68, 0x1B, 0x69, 0xC3, 0xF5, 0x43, 0x43, ++0x50, 0x33, 0xD3, 0x42, 0x10, 0xB5, 0x04, 0x46, 0x00, 0xD4, 0x10, 0xBD, 0x83, 0x7A, 0x1A, 0x1D, 0x50, 0xF8, 0x22, 0x20, ++0x42, 0xB9, 0x02, 0x89, 0x01, 0x33, 0x01, 0x32, 0x03, 0xF0, 0x3F, 0x03, 0xC2, 0xF3, 0x0B, 0x02, 0x83, 0x72, 0x02, 0x81, ++0x20, 0x46, 0xFF, 0xF7, 0xF1, 0xFD, 0xE3, 0x7A, 0x53, 0xB9, 0x0B, 0x4A, 0x0B, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, ++0x01, 0xF5, 0x43, 0x41, 0x04, 0xF5, 0x88, 0x70, 0x50, 0x31, 0x98, 0x47, 0x07, 0x48, 0x83, 0x6B, 0x00, 0x2B, 0xDC, 0xD0, ++0x04, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, 0x38, 0x31, 0x38, 0x30, 0x18, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x19, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x05, 0x46, ++0x04, 0xD0, 0x03, 0x88, 0x03, 0xF0, 0xEC, 0x03, 0xC4, 0x2B, 0x11, 0xD0, 0x15, 0x4F, 0x05, 0xF1, 0x04, 0x08, 0x07, 0xF5, ++0xA4, 0x56, 0xB9, 0x46, 0x3C, 0x46, 0x94, 0xF8, 0x64, 0x30, 0x1B, 0xB1, 0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x06, 0xD0, ++0x04, 0xF5, 0xA4, 0x64, 0xA6, 0x42, 0xF4, 0xD1, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x06, 0x22, 0x04, 0xF1, 0x5C, 0x01, ++0x40, 0x46, 0x08, 0xF0, 0x45, 0xFE, 0xA4, 0xEB, 0x07, 0x0A, 0x00, 0x28, 0xEE, 0xD1, 0x07, 0x49, 0x07, 0x48, 0xF6, 0xF7, ++0x4D, 0xF9, 0x05, 0xF1, 0x0A, 0x01, 0x09, 0xEB, 0x0A, 0x00, 0xFD, 0xF7, 0x49, 0xFD, 0xE7, 0xE7, 0x00, 0x88, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x20, 0xC1, 0x15, 0x00, 0xA8, 0xC0, 0x15, 0x00, 0x13, 0x4B, 0x93, 0xF8, 0x73, 0x20, 0x12, 0xB1, ++0x11, 0xF4, 0x00, 0x71, 0x00, 0xD0, 0x70, 0x47, 0x10, 0xB4, 0x42, 0x89, 0xB3, 0xF8, 0x6C, 0x40, 0x94, 0x42, 0x02, 0xD0, ++0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xB3, 0xF8, 0x6E, 0x40, 0x82, 0x89, 0x94, 0x42, 0xF7, 0xD1, 0xB3, 0xF8, 0x70, 0x40, ++0xC2, 0x89, 0x94, 0x42, 0xF2, 0xD1, 0x02, 0x88, 0x02, 0xF4, 0xA0, 0x52, 0xB2, 0xF5, 0x80, 0x5F, 0x06, 0xBF, 0x01, 0x22, ++0x83, 0xF8, 0x72, 0x20, 0x83, 0xF8, 0x72, 0x10, 0xE6, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0xF8, 0xB5, 0xBD, 0xF8, ++0x1C, 0x60, 0x06, 0x9D, 0xFF, 0x2A, 0x00, 0xEB, 0x06, 0x07, 0x2E, 0xD0, 0x14, 0x46, 0x82, 0x5D, 0x03, 0x3A, 0x12, 0x2A, ++0x18, 0xD8, 0xDF, 0xE8, 0x02, 0xF0, 0x2B, 0x17, 0x0A, 0x17, 0x30, 0x49, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, ++0x17, 0x17, 0x17, 0x17, 0x5C, 0x00, 0x1B, 0x78, 0x4B, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, ++0x62, 0x30, 0x02, 0x2B, 0x02, 0xD0, 0x7B, 0x78, 0x00, 0x2B, 0x6A, 0xD0, 0x01, 0x26, 0x2B, 0x88, 0xFF, 0x2B, 0x0A, 0xD0, ++0x44, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x57, 0xDB, 0x6F, 0xF0, 0xFF, 0x03, 0x2A, 0x88, 0x13, 0x43, ++0x2B, 0x80, 0x30, 0x46, 0xF8, 0xBD, 0x01, 0x26, 0x30, 0x46, 0xF8, 0xBD, 0x08, 0x23, 0x2B, 0x80, 0x00, 0x26, 0x00, 0x23, ++0xF2, 0xE7, 0x7E, 0x78, 0x00, 0x2E, 0x52, 0xD0, 0x01, 0x2E, 0xE1, 0xD1, 0x38, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x04, 0x23, 0x5E, 0x68, 0x16, 0xF0, 0x02, 0x06, 0xD9, 0xD0, 0xBE, 0x78, 0x16, 0xF0, 0x01, 0x06, 0x5A, 0xD0, 0x20, 0x46, ++0x00, 0x22, 0xFF, 0x21, 0xF9, 0xF7, 0xDC, 0xFC, 0x00, 0x26, 0xCE, 0xE7, 0x89, 0x1B, 0x03, 0x29, 0x2A, 0xDD, 0x1B, 0x78, ++0xFF, 0x2B, 0xC7, 0xD0, 0x29, 0x4A, 0x7E, 0x78, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, ++0x1E, 0x43, 0xBD, 0xD1, 0x06, 0x23, 0x2B, 0x80, 0xD1, 0xE7, 0x7B, 0x78, 0x01, 0x2B, 0x36, 0xD0, 0x02, 0x2B, 0xB5, 0xD1, ++0x22, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x23, 0x5E, 0x68, 0x16, 0xF0, 0x24, 0x06, 0xAD, 0xD0, 0x97, 0xF9, ++0x02, 0x30, 0xB9, 0x78, 0x00, 0x2B, 0x07, 0xDB, 0x0A, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x03, 0x01, 0xF9, 0xF7, 0xAE, 0xFC, ++0x00, 0x26, 0xA0, 0xE7, 0x00, 0x26, 0x9E, 0xE7, 0x17, 0x49, 0x18, 0x48, 0x40, 0xF6, 0x78, 0x12, 0xF6, 0xF7, 0x00, 0xFB, ++0x6F, 0xF0, 0xFF, 0x03, 0xA0, 0xE7, 0x0B, 0x23, 0x2B, 0x80, 0x01, 0x26, 0xA7, 0xE7, 0x10, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x04, 0x23, 0x5B, 0x68, 0x9B, 0x07, 0x89, 0xD5, 0xB9, 0x78, 0x01, 0x29, 0x86, 0xD8, 0x20, 0x46, 0xFF, 0x22, ++0xF9, 0xF7, 0x8E, 0xFC, 0x81, 0xE7, 0x07, 0xF1, 0x0A, 0x01, 0xB8, 0x1C, 0xD2, 0xF7, 0xB6, 0xFE, 0x00, 0x26, 0x7A, 0xE7, ++0xFF, 0x22, 0x20, 0x46, 0x11, 0x46, 0xF9, 0xF7, 0x81, 0xFC, 0x74, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xBC, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x89, 0xB0, 0x1F, 0x46, ++0x10, 0x9E, 0x34, 0x78, 0xFF, 0x2C, 0x47, 0xD0, 0x69, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x55, 0x00, 0xF0, ++0xFC, 0x04, 0x80, 0x2C, 0x95, 0xF8, 0x62, 0x80, 0x46, 0xD0, 0x0F, 0xD8, 0x40, 0x2C, 0x6B, 0xD0, 0x2C, 0xD9, 0x50, 0x2C, ++0x4F, 0xF0, 0x01, 0x04, 0x04, 0xD1, 0x13, 0x9A, 0x14, 0x70, 0x12, 0x9A, 0x04, 0x23, 0x13, 0x80, 0x20, 0x46, 0x09, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0xC0, 0x2C, 0x21, 0xD0, 0x10, 0xD9, 0xD0, 0x2C, 0x15, 0xD1, 0x13, 0x9B, 0x11, 0x98, 0xCD, 0xE9, ++0x01, 0x23, 0x12, 0x9B, 0x00, 0x93, 0x3A, 0x46, 0x33, 0x46, 0xFF, 0xF7, 0x11, 0xFF, 0x04, 0x46, 0x20, 0x46, 0x09, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0xA0, 0x2C, 0x0D, 0xD0, 0xB0, 0x2C, 0x02, 0xD1, 0xFC, 0xF7, 0xBA, 0xFA, 0x40, 0xB1, 0x01, 0x24, ++0x20, 0x46, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x00, 0xF0, 0xDC, 0x00, 0x10, 0x28, 0xF6, 0xD1, 0xB8, 0xF1, 0x00, 0x0F, ++0xF3, 0xD1, 0x12, 0x9A, 0x06, 0x23, 0x13, 0x80, 0x01, 0x24, 0xCF, 0xE7, 0x00, 0xF0, 0xFC, 0x00, 0xB0, 0x28, 0x72, 0xD0, ++0x28, 0xD8, 0x40, 0x28, 0x2A, 0xD0, 0x80, 0x28, 0xE5, 0xD1, 0x00, 0x25, 0x04, 0x20, 0x05, 0x91, 0xF4, 0xF7, 0x34, 0xFC, ++0x01, 0x28, 0x05, 0x99, 0x0E, 0xD1, 0x13, 0x9A, 0x3D, 0x4B, 0x10, 0x70, 0x12, 0x98, 0x1B, 0x68, 0x3A, 0x4D, 0x04, 0x22, ++0x02, 0x80, 0x93, 0xF8, 0x6E, 0x41, 0x34, 0x70, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x55, 0xFF, 0x2F, 0xCC, 0xD0, ++0x95, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xC8, 0xD0, 0x34, 0x4B, 0x30, 0x78, 0xD3, 0xF8, 0x54, 0x31, 0x11, 0x9A, 0x98, 0x47, ++0x01, 0x24, 0xA1, 0xE7, 0xD0, 0x28, 0xA8, 0xD0, 0x01, 0x24, 0xBD, 0xE7, 0x2F, 0x4B, 0x9A, 0x7C, 0x00, 0x2A, 0xB8, 0xD0, ++0x2E, 0x4A, 0x12, 0x68, 0x12, 0x78, 0x01, 0x3A, 0x01, 0x2A, 0xB2, 0xD8, 0x9D, 0x68, 0x00, 0x2D, 0xAF, 0xD0, 0x18, 0x39, ++0x2A, 0x4F, 0x1F, 0xFA, 0x81, 0xF8, 0x01, 0x24, 0x02, 0xE0, 0x2D, 0x68, 0x00, 0x2D, 0x87, 0xD0, 0x95, 0xF8, 0x62, 0x30, ++0x02, 0x2B, 0xF8, 0xD1, 0x95, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF4, 0xD0, 0x95, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0xF0, 0xD1, ++0x11, 0x9B, 0xB7, 0xF8, 0x00, 0x90, 0x03, 0xF1, 0x18, 0x00, 0x0D, 0xF1, 0x1E, 0x02, 0x41, 0x46, 0xF4, 0xF7, 0xFA, 0xFF, ++0xA9, 0xF1, 0x24, 0x01, 0x06, 0x46, 0x89, 0xB2, 0x0D, 0xF1, 0x1F, 0x02, 0x19, 0x48, 0xF4, 0xF7, 0xF1, 0xFF, 0x9D, 0xF8, ++0x1E, 0x30, 0x18, 0x49, 0x02, 0x36, 0x81, 0x46, 0x07, 0x22, 0x30, 0x46, 0x53, 0xB9, 0x11, 0x9B, 0x28, 0x46, 0x03, 0xF1, ++0x0A, 0x01, 0xE1, 0xF7, 0xED, 0xFE, 0x00, 0x24, 0xCD, 0xE7, 0xFC, 0xF7, 0x2F, 0xFA, 0x74, 0xE7, 0x08, 0xF0, 0x7C, 0xFC, ++0x00, 0x28, 0xC6, 0xD0, 0x9D, 0xF8, 0x1F, 0x30, 0x9D, 0xF8, 0x1E, 0x20, 0x9A, 0x42, 0xC0, 0xD1, 0x09, 0xF1, 0x02, 0x01, ++0x30, 0x46, 0x08, 0xF0, 0x6F, 0xFC, 0x00, 0x28, 0xE3, 0xD0, 0xB8, 0xE7, 0x18, 0x88, 0x17, 0x00, 0xA8, 0xBA, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x14, 0x2C, 0x17, 0x00, 0x38, 0x2A, 0x17, 0x00, ++0x54, 0xBF, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xC6, 0x69, 0x8D, 0xB0, 0xD6, 0xF8, 0x08, 0x90, 0x01, 0x23, 0x8D, 0xF8, ++0x24, 0x30, 0x04, 0x46, 0xB9, 0xF8, 0x00, 0x00, 0x10, 0xF4, 0x80, 0x60, 0x40, 0xF0, 0x8B, 0x80, 0xB9, 0xF8, 0x16, 0x70, ++0x17, 0xF0, 0x0F, 0x07, 0x00, 0xF0, 0x89, 0x80, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB9, 0xF8, 0x00, 0x30, 0x98, 0xF8, ++0x08, 0x20, 0x04, 0x92, 0xDF, 0xF8, 0x08, 0xE2, 0xB4, 0xF8, 0x30, 0xA0, 0xBD, 0xF8, 0x10, 0x10, 0xAD, 0xF8, 0x16, 0x30, ++0x4F, 0xF0, 0xFF, 0x0C, 0x18, 0x46, 0xAD, 0xF8, 0x26, 0xC0, 0xB3, 0x68, 0xDE, 0xF8, 0xE0, 0x92, 0x07, 0x93, 0x0D, 0xF1, ++0x25, 0x0C, 0x01, 0x93, 0xCD, 0xF8, 0x0C, 0xC0, 0x72, 0x4B, 0x06, 0x91, 0x0D, 0xF1, 0x26, 0x0C, 0x0A, 0x46, 0x00, 0x93, ++0x51, 0x46, 0x8D, 0xF8, 0x25, 0xB0, 0x80, 0xB2, 0xCD, 0xF8, 0x08, 0xC0, 0x2B, 0x46, 0xC8, 0x47, 0xBD, 0xF8, 0x26, 0x10, ++0xFF, 0x29, 0x00, 0xF0, 0x90, 0x80, 0x0A, 0xF1, 0x0C, 0x03, 0x9B, 0xB2, 0x0A, 0x22, 0x4F, 0xF4, 0x20, 0x50, 0xF4, 0xF7, ++0xB5, 0xF8, 0x59, 0x46, 0x81, 0x46, 0x0A, 0xA8, 0xD2, 0xF7, 0xFA, 0xFC, 0x9D, 0xF8, 0x25, 0x30, 0xD3, 0x46, 0x63, 0xB9, ++0x61, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xAE, 0x80, 0x04, 0x9B, 0x06, 0x9F, 0xAA, 0xEB, ++0x03, 0x0B, 0x1F, 0xFA, 0x8B, 0xFA, 0x4B, 0x46, 0x3A, 0x46, 0x51, 0x46, 0x23, 0xF8, 0x0C, 0xAB, 0x30, 0x46, 0xE6, 0xF7, ++0x35, 0xFD, 0x98, 0xF8, 0x0A, 0x30, 0x89, 0xF8, 0x08, 0x30, 0xBD, 0xF8, 0x16, 0x30, 0x89, 0xF8, 0x07, 0x50, 0xA9, 0xF8, ++0x02, 0x30, 0x94, 0xF9, 0x41, 0x50, 0xD2, 0xF7, 0x75, 0xFD, 0x0A, 0x9B, 0x89, 0xF8, 0x06, 0x30, 0x1A, 0x0C, 0x89, 0xF8, ++0x09, 0x50, 0xA9, 0xF8, 0x04, 0x20, 0x48, 0x46, 0xF4, 0xF7, 0xAE, 0xF8, 0xBD, 0xF8, 0x26, 0x30, 0x04, 0x2B, 0x10, 0xD1, ++0xE1, 0x6B, 0xB9, 0xF8, 0x04, 0x30, 0x62, 0x6B, 0x07, 0x98, 0xC1, 0xF3, 0x03, 0x11, 0x02, 0x91, 0x99, 0xF9, 0x09, 0x10, ++0x01, 0x91, 0x99, 0xF8, 0x06, 0x10, 0x00, 0x91, 0x59, 0x46, 0x07, 0xF0, 0x15, 0xFB, 0x00, 0x20, 0x0D, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x0D, 0x46, 0xD2, 0xF7, 0x4E, 0xFD, 0xFF, 0x2D, 0x38, 0xD0, 0x3C, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x31, 0xD0, ++0x99, 0xF8, 0x04, 0x30, 0xDF, 0xF8, 0xEC, 0x80, 0xDA, 0x07, 0x10, 0xD4, 0x98, 0xF8, 0x0A, 0x00, 0x37, 0x4A, 0xB9, 0xF8, ++0x04, 0x10, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0xF3, 0x5C, 0x33, 0x98, 0x18, 0x9B, 0x5A, 0x8B, 0x42, 0x45, 0xD0, ++0xFF, 0x23, 0x88, 0xF8, 0x0A, 0x30, 0x22, 0x8E, 0x30, 0x48, 0x09, 0xAB, 0x49, 0x46, 0x02, 0xF0, 0x81, 0xFB, 0x83, 0x46, ++0x00, 0x28, 0x3F, 0xF4, 0x50, 0xAF, 0x9D, 0xF8, 0x24, 0x00, 0x00, 0x28, 0x3F, 0xF4, 0x48, 0xAF, 0x2A, 0x4B, 0x20, 0x46, ++0xD3, 0xF8, 0xE4, 0x32, 0x03, 0x21, 0x98, 0x47, 0x9D, 0xF8, 0x24, 0x00, 0x3E, 0xE7, 0x8D, 0xF8, 0x24, 0x00, 0xF0, 0xE7, ++0xDF, 0xF8, 0x8C, 0x80, 0xE1, 0xE7, 0x63, 0x6D, 0x13, 0xF4, 0xC0, 0x6F, 0x1E, 0xD1, 0x1E, 0x4B, 0x9B, 0x68, 0x9B, 0xB3, ++0xB9, 0xF8, 0x04, 0x10, 0x01, 0xE0, 0x1B, 0x68, 0xB3, 0xB1, 0xB3, 0xF8, 0x5C, 0x20, 0x8A, 0x42, 0xF9, 0xD1, 0xB3, 0xF8, ++0x5E, 0x00, 0xB9, 0xF8, 0x06, 0x20, 0x90, 0x42, 0xF3, 0xD1, 0xB3, 0xF8, 0x60, 0x00, 0xB9, 0xF8, 0x08, 0x20, 0x90, 0x42, ++0xED, 0xD1, 0x93, 0xF8, 0x63, 0x30, 0xDF, 0xF8, 0x4C, 0x80, 0x88, 0xF8, 0x0A, 0x30, 0xBE, 0xE7, 0xFF, 0x23, 0xF8, 0xE7, ++0x42, 0x88, 0xB9, 0xF8, 0x06, 0x30, 0x9A, 0x42, 0xB4, 0xD1, 0x82, 0x88, 0xB9, 0xF8, 0x08, 0x30, 0x9A, 0x42, 0xAF, 0xD1, ++0xB1, 0xE7, 0x04, 0x9A, 0x93, 0x07, 0x3F, 0xF4, 0x4E, 0xAF, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0x97, 0x22, 0xF6, 0xF7, ++0xE7, 0xF8, 0x46, 0xE7, 0x2B, 0x46, 0xE0, 0xE7, 0xBA, 0xDE, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD0, 0xC0, 0x15, 0x00, ++0x1D, 0x48, 0x70, 0xB5, 0x00, 0xF1, 0x10, 0x06, 0xF4, 0xF7, 0x5E, 0xFC, 0x30, 0x46, 0x1B, 0x4C, 0xF4, 0xF7, 0x5A, 0xFC, ++0x04, 0xF5, 0x92, 0x55, 0x21, 0x46, 0x30, 0x46, 0x04, 0xF5, 0x92, 0x74, 0xF4, 0xF7, 0x56, 0xFC, 0xAC, 0x42, 0xF7, 0xD1, ++0x15, 0x48, 0xF4, 0xF7, 0x4D, 0xFC, 0x15, 0x48, 0xF4, 0xF7, 0x4A, 0xFC, 0x14, 0x49, 0x12, 0x48, 0xF4, 0xF7, 0x4A, 0xFC, ++0x13, 0x49, 0x10, 0x48, 0xF4, 0xF7, 0x46, 0xFC, 0x12, 0x49, 0x0E, 0x48, 0xF4, 0xF7, 0x42, 0xFC, 0x11, 0x4A, 0x12, 0x4B, ++0x12, 0x48, 0x4F, 0xF6, 0xFF, 0x71, 0xA2, 0xF8, 0x66, 0x10, 0x03, 0xF5, 0x70, 0x51, 0x00, 0x22, 0x03, 0xF8, 0x34, 0x2C, ++0x1A, 0x81, 0x43, 0xE9, 0x10, 0x03, 0x43, 0xF8, 0x30, 0x3C, 0x50, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0x70, 0xBD, 0x00, 0xBF, ++0xE8, 0xDE, 0x17, 0x00, 0x70, 0xCC, 0x17, 0x00, 0x00, 0xDF, 0x17, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x28, 0xDF, 0x17, 0x00, ++0x6C, 0xDF, 0x17, 0x00, 0xB0, 0xDF, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x24, 0x64, 0x18, 0x00, 0x75, 0xD2, 0x14, 0x00, ++0x70, 0xB5, 0x90, 0xF9, 0x00, 0x30, 0x82, 0xB0, 0x00, 0x2B, 0x01, 0xF0, 0x78, 0x02, 0x05, 0x46, 0xB8, 0xBF, 0x1A, 0x23, ++0x4F, 0xF0, 0x00, 0x00, 0xA8, 0xBF, 0x18, 0x23, 0x08, 0x2A, 0xAD, 0xF8, 0x06, 0x00, 0x19, 0xD0, 0x01, 0xF0, 0x7C, 0x01, ++0x04, 0x29, 0x1F, 0xD0, 0x06, 0x33, 0xDC, 0xB2, 0x2E, 0x19, 0x31, 0x46, 0x02, 0x22, 0x0D, 0xF1, 0x06, 0x00, 0x08, 0xF0, ++0xF3, 0xFA, 0x28, 0x79, 0x10, 0xF0, 0x01, 0x00, 0x0B, 0xD0, 0xBD, 0xF8, 0x06, 0x00, 0xA0, 0xF5, 0xC1, 0x60, 0xB0, 0xFA, ++0x80, 0xF0, 0x40, 0x09, 0x02, 0xB0, 0x70, 0xBD, 0x08, 0x33, 0xDB, 0xB2, 0xE6, 0xE7, 0xBD, 0xF8, 0x06, 0x30, 0x08, 0x2B, ++0x04, 0xD0, 0x01, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x04, 0x33, 0xDD, 0xE7, 0xF3, 0x7A, 0x02, 0x2B, 0xEE, 0xD0, 0x11, 0x2B, ++0xF5, 0xD1, 0xB2, 0x78, 0xA3, 0x1C, 0x02, 0xF0, 0x0F, 0x04, 0x03, 0xEB, 0x84, 0x04, 0x2C, 0x44, 0x14, 0xF8, 0x04, 0x3C, ++0xEF, 0x2B, 0xEA, 0xD1, 0x14, 0xF8, 0x03, 0x3C, 0xFF, 0x2B, 0xE6, 0xD1, 0x14, 0xF8, 0x02, 0x3C, 0xFF, 0x2B, 0xE2, 0xD1, ++0x14, 0xF8, 0x01, 0x0C, 0xFA, 0x38, 0x18, 0xBF, 0x01, 0x20, 0xD3, 0xE7, 0x70, 0xB5, 0x90, 0xF9, 0x00, 0x30, 0x82, 0xB0, ++0x00, 0x2B, 0x01, 0xF0, 0x78, 0x05, 0x4F, 0xF0, 0x00, 0x06, 0xB4, 0xBF, 0x1A, 0x23, 0x18, 0x23, 0x08, 0x2D, 0x14, 0x46, ++0xAD, 0xF8, 0x06, 0x60, 0x13, 0xD0, 0x01, 0xF0, 0x7C, 0x01, 0x04, 0x29, 0x12, 0xD0, 0x99, 0x1D, 0x50, 0xFA, 0x81, 0xF1, ++0x02, 0x22, 0x0D, 0xF1, 0x06, 0x00, 0x08, 0xF0, 0x9F, 0xFA, 0xBD, 0xF8, 0x06, 0x10, 0x48, 0xF6, 0x88, 0x63, 0x99, 0x42, ++0x06, 0xD0, 0x02, 0xB0, 0x70, 0xBD, 0x08, 0x33, 0xDB, 0xB2, 0xEC, 0xE7, 0x04, 0x33, 0xEA, 0xE7, 0x02, 0x48, 0x22, 0x46, ++0xF5, 0xF7, 0x6E, 0xFD, 0x02, 0xB0, 0x70, 0xBD, 0xEC, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x45, 0x6D, 0x2D, 0xED, ++0x02, 0x8B, 0xAF, 0x04, 0x87, 0xB0, 0x04, 0x46, 0x1F, 0xD4, 0xC1, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9E, 0x07, 0x03, 0xD5, ++0x05, 0xF0, 0x3C, 0x03, 0x3C, 0x2B, 0x16, 0xD0, 0xBD, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x71, 0xD0, 0xBC, 0x4E, 0xBD, 0x4D, ++0xB3, 0x72, 0x20, 0x46, 0xD5, 0xF8, 0xE4, 0x32, 0x80, 0x21, 0x98, 0x47, 0x01, 0x27, 0xD5, 0xF8, 0x38, 0x31, 0xB9, 0x48, ++0x98, 0x47, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0xD4, 0xF8, 0x1C, 0xA0, 0xB2, 0x4E, ++0xDA, 0xF8, 0x08, 0x80, 0x00, 0x23, 0xB8, 0xF8, 0x00, 0x90, 0x23, 0x66, 0x40, 0x46, 0xFF, 0x23, 0x73, 0x72, 0xB3, 0x72, ++0xFE, 0xF7, 0xE6, 0xFD, 0xA8, 0x01, 0x50, 0xD5, 0xC5, 0xF3, 0xC9, 0x37, 0xDF, 0xF8, 0xBC, 0xB2, 0x10, 0x3F, 0xFF, 0xB2, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x93, 0xF8, 0x25, 0x20, 0x00, 0x2A, 0x39, 0xD0, 0x93, 0xF8, 0x22, 0x10, ++0xA5, 0x48, 0xD3, 0xF8, 0xB0, 0x30, 0x77, 0x72, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x02, 0xB5, 0x61, 0x92, 0xF8, ++0x62, 0x20, 0xB1, 0x72, 0x02, 0x2A, 0x00, 0x93, 0x52, 0xD0, 0x09, 0xF4, 0x40, 0x73, 0xB3, 0xF5, 0x40, 0x7F, 0x03, 0xD1, ++0x23, 0x6E, 0x43, 0xF0, 0x04, 0x03, 0x23, 0x66, 0x33, 0x88, 0x5B, 0x04, 0x00, 0xF1, 0x90, 0x80, 0x98, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x01, 0x2B, 0x09, 0xF0, 0x0C, 0x03, 0x00, 0xF0, 0x90, 0x80, 0x08, 0x2B, 0x00, 0xF0, 0x97, 0x80, 0x4F, 0xF4, ++0x1E, 0x72, 0x02, 0xFB, 0x07, 0xB2, 0x92, 0xF8, 0x5D, 0x22, 0x01, 0x2A, 0x40, 0xF2, 0xE7, 0x80, 0x04, 0x2B, 0x00, 0xF0, ++0xFA, 0x80, 0x08, 0x2B, 0x00, 0xF0, 0x97, 0x80, 0x00, 0x2B, 0x33, 0xD0, 0x85, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x01, 0xD0, ++0x85, 0x4D, 0x8F, 0xE7, 0x84, 0x4D, 0x00, 0x27, 0x93, 0xE7, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x9D, 0xFB, 0x19, 0xF0, ++0x0C, 0x0F, 0x0B, 0xD1, 0xFF, 0xF7, 0xDA, 0xF8, 0x00, 0x28, 0xEB, 0xD0, 0x33, 0x88, 0x59, 0x04, 0x55, 0xD5, 0x05, 0xF0, ++0x7C, 0x03, 0x04, 0x2B, 0x4B, 0xD0, 0x40, 0x46, 0x21, 0x46, 0xFF, 0xF7, 0x4D, 0xFB, 0x78, 0x4D, 0x07, 0x46, 0x75, 0x4B, ++0x1B, 0x7C, 0xFF, 0x2B, 0x3F, 0xF4, 0x77, 0xAF, 0x00, 0x2F, 0x7F, 0xF4, 0x74, 0xAF, 0x6B, 0xE7, 0x96, 0xF8, 0x24, 0x30, ++0xDA, 0x07, 0xA8, 0xD4, 0x06, 0xF1, 0x24, 0x00, 0xF2, 0xF7, 0xB8, 0xFE, 0xF0, 0x72, 0xA2, 0xE7, 0x19, 0xF4, 0x00, 0x6F, ++0x00, 0xF0, 0xCF, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x72, 0x88, 0xB3, 0xF8, 0xE8, 0x31, 0x93, 0x42, ++0xBE, 0xD0, 0x96, 0xF8, 0x30, 0x10, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB7, 0x8D, 0x07, 0xA7, 0xF8, 0xE8, 0x21, ++0x0A, 0xD5, 0x35, 0x6A, 0xD6, 0xE9, 0x04, 0x01, 0xD5, 0xE9, 0x10, 0x23, 0x8B, 0x42, 0x08, 0xBF, 0x82, 0x42, 0xAB, 0xD2, ++0xC5, 0xE9, 0x10, 0x01, 0x5F, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD1, 0x98, 0xF8, 0x00, 0x30, 0x80, 0x2B, ++0x00, 0xF0, 0xCF, 0x80, 0x71, 0x7A, 0x57, 0x4D, 0x20, 0x46, 0xFF, 0xF7, 0x17, 0xFD, 0x07, 0x46, 0xB9, 0xE7, 0x29, 0x46, ++0x40, 0x46, 0xFE, 0xF7, 0x39, 0xFB, 0x00, 0x28, 0xAD, 0xD0, 0xFF, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x0B, 0xFD, 0x4F, 0x4D, ++0x07, 0x46, 0xAC, 0xE7, 0xB1, 0x69, 0x40, 0x46, 0xFE, 0xF7, 0x2C, 0xFB, 0x00, 0x28, 0x7F, 0xF4, 0x69, 0xAF, 0x83, 0xE7, ++0x08, 0x2B, 0x7F, 0xF4, 0x70, 0xAF, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x73, 0xFE, 0x00, 0x28, 0x3F, 0xF4, 0x7A, 0xAF, ++0x3B, 0x46, 0x22, 0x8E, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xC0, 0xFE, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, ++0x93, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x40, 0xF2, 0x87, 0x80, 0x41, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x73, 0xB1, 0xB3, 0x7A, ++0x3C, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x13, 0x93, 0xF8, 0x62, 0x20, 0x2A, 0xB9, 0xD3, 0xF8, 0x90, 0x21, ++0x92, 0x78, 0x01, 0x2A, 0x00, 0xF0, 0x8D, 0x80, 0x19, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x7F, 0xF4, 0x53, 0xAF, 0x09, 0xF0, ++0x80, 0x03, 0x00, 0x2B, 0x14, 0xBF, 0x4F, 0xF0, 0x01, 0x08, 0x4F, 0xF0, 0x00, 0x08, 0x71, 0xD0, 0x96, 0xF8, 0x30, 0x30, ++0x1A, 0x07, 0x40, 0xF1, 0x9A, 0x80, 0xF2, 0x79, 0x4F, 0xF4, 0x9E, 0x73, 0xF5, 0x32, 0x03, 0xFB, 0x07, 0x23, 0x0B, 0xEB, ++0x43, 0x03, 0x19, 0xF4, 0x00, 0x6F, 0x72, 0x88, 0x03, 0xD0, 0x19, 0x88, 0x91, 0x42, 0x3F, 0xF4, 0x35, 0xAF, 0x1F, 0x49, ++0x1A, 0x80, 0x0B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x04, 0xD5, 0x05, 0xF0, 0x3C, 0x05, 0x3C, 0x2D, 0x00, 0xF0, 0x8E, 0x80, ++0x1C, 0x4D, 0x39, 0x46, 0xD5, 0xF8, 0xC4, 0x32, 0x42, 0x46, 0x20, 0x46, 0x98, 0x47, 0x07, 0x46, 0x41, 0xE7, 0x00, 0x9A, ++0x00, 0x2A, 0x3F, 0xF4, 0x15, 0xAF, 0x92, 0xF8, 0x60, 0x20, 0x01, 0x3A, 0x01, 0x2A, 0x3F, 0xF6, 0x0F, 0xAF, 0x19, 0xF4, ++0x80, 0x4F, 0x3F, 0xF4, 0x0B, 0xAF, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x07, 0xB2, 0x02, 0x21, 0x82, 0xF8, 0x5D, 0x12, ++0x02, 0xE7, 0x09, 0xF0, 0xFC, 0x09, 0xB9, 0xF1, 0x84, 0x0F, 0x7F, 0xF4, 0x05, 0xAF, 0x0A, 0x4D, 0x41, 0x46, 0xD5, 0xF8, ++0xD0, 0x32, 0x38, 0x46, 0x98, 0x47, 0x05, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x7F, 0xF4, 0x90, 0xAE, 0xFF, 0xE6, 0x72, 0x88, ++0x37, 0xE7, 0x00, 0xBF, 0x34, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xE8, 0xDE, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0x75, 0xAF, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, 0x01, 0x2B, 0x3F, 0xF6, 0x6F, 0xAF, ++0x08, 0x23, 0xC0, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x03, 0xF5, 0xF4, 0x73, 0x93, 0xE7, 0x98, 0xF8, ++0x01, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x2C, 0xAF, 0xCA, 0xE6, 0xD3, 0xF8, 0xCC, 0x21, 0x12, 0xF0, 0x0C, 0x0F, 0x3F, 0xF4, ++0x6D, 0xAF, 0x98, 0xF8, 0x04, 0x20, 0xD0, 0x07, 0x3F, 0xF5, 0x68, 0xAF, 0xE2, 0x6B, 0x12, 0xF0, 0x0C, 0x0F, 0x3F, 0xF4, ++0x63, 0xAF, 0xD3, 0xF8, 0x90, 0x20, 0x01, 0x32, 0xC3, 0xF8, 0x90, 0x20, 0x98, 0xF8, 0x01, 0x20, 0x11, 0x07, 0x7F, 0xF5, ++0x59, 0xAF, 0xD3, 0xF8, 0x94, 0x20, 0x01, 0x32, 0xC3, 0xF8, 0x94, 0x20, 0x52, 0xE7, 0xF1, 0x79, 0x38, 0x46, 0xE9, 0xF7, ++0x33, 0xFB, 0x00, 0x28, 0x3F, 0xF4, 0x5F, 0xAF, 0x61, 0x4D, 0x39, 0x46, 0xD5, 0xF8, 0xD4, 0x32, 0x20, 0x46, 0x98, 0x47, ++0x07, 0x46, 0xBC, 0xE6, 0x33, 0x6A, 0x01, 0x93, 0x93, 0xF8, 0x60, 0x10, 0x01, 0x29, 0x03, 0xF1, 0x64, 0x09, 0x64, 0xD0, ++0x00, 0x29, 0x40, 0xF0, 0x97, 0x80, 0x08, 0xF1, 0x0E, 0x03, 0x5B, 0x00, 0xDA, 0xE9, 0x01, 0x25, 0x58, 0x19, 0x08, 0xEE, ++0x10, 0x0A, 0x00, 0x2A, 0x52, 0xD0, 0xDA, 0xF8, 0x0C, 0x20, 0x20, 0x8E, 0x01, 0x32, 0x52, 0x1B, 0x04, 0x30, 0xD2, 0x1A, ++0xC0, 0x1A, 0x93, 0xB2, 0x82, 0xB2, 0x9A, 0x42, 0x00, 0x92, 0x28, 0xBF, 0x1A, 0x46, 0x15, 0x46, 0x01, 0x29, 0x2F, 0xD0, ++0x00, 0x29, 0x50, 0xD0, 0x03, 0x29, 0x66, 0xD0, 0x18, 0xEE, 0x10, 0x0A, 0x29, 0x46, 0xF3, 0xF7, 0x2F, 0xFB, 0x4F, 0xF0, ++0xFF, 0x33, 0x18, 0xEE, 0x10, 0x0A, 0x03, 0x22, 0x29, 0x46, 0xD6, 0xF7, 0x29, 0xFF, 0xDA, 0xF8, 0x04, 0x30, 0x23, 0xB1, ++0x00, 0x9A, 0x55, 0x1B, 0xAD, 0xB2, 0x00, 0x2D, 0x67, 0xD1, 0x01, 0x9B, 0x93, 0xF8, 0x60, 0x30, 0x13, 0xB1, 0x03, 0x2B, ++0x7F, 0xF4, 0x2C, 0xAF, 0x03, 0x20, 0xD6, 0xF7, 0x4F, 0xFF, 0x3A, 0x4B, 0x98, 0x42, 0x01, 0x46, 0x3F, 0xD1, 0x63, 0x6D, ++0x23, 0xF0, 0x7C, 0x03, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xF0, 0x04, 0x03, 0x63, 0x65, 0x1B, 0xE7, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x07, 0xB2, 0x02, 0xAB, 0x32, 0x49, 0x26, 0x32, 0x48, 0x46, 0xF3, 0xF7, 0xDA, 0xF8, 0x10, 0x21, 0x02, 0xA8, ++0xF3, 0xF7, 0x9A, 0xFA, 0x01, 0x9B, 0x93, 0xF8, 0x60, 0x10, 0xBD, 0xE7, 0x22, 0x8E, 0x04, 0x32, 0xD3, 0x1A, 0x9D, 0xB2, ++0xB6, 0xE7, 0xD6, 0xE9, 0x04, 0x53, 0x28, 0x48, 0x2A, 0x0C, 0x42, 0xEA, 0x03, 0x42, 0x08, 0xF1, 0x10, 0x03, 0x02, 0x60, ++0x85, 0x80, 0x5B, 0x00, 0x94, 0xE7, 0x32, 0x8A, 0x73, 0x8A, 0xAD, 0xF8, 0x08, 0x20, 0x49, 0x46, 0x05, 0x22, 0x0D, 0xF1, ++0x0B, 0x00, 0x8D, 0xF8, 0x0A, 0x30, 0x08, 0xF0, 0x1F, 0xF8, 0x08, 0x21, 0x02, 0xA8, 0xF3, 0xF7, 0x75, 0xFA, 0x01, 0x9B, ++0x93, 0xF8, 0x60, 0x10, 0x9A, 0xE7, 0x1A, 0x48, 0xF5, 0xF7, 0xF4, 0xFA, 0x0A, 0xE6, 0x32, 0x8A, 0x73, 0x8A, 0xAD, 0xF8, ++0x08, 0x20, 0x49, 0x46, 0x0D, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x8D, 0xF8, 0x0A, 0x30, 0x08, 0xF0, 0x07, 0xF8, 0x02, 0xA8, ++0x10, 0x21, 0xF3, 0xF7, 0x5D, 0xFA, 0x87, 0xE7, 0x03, 0x29, 0x3F, 0xF4, 0x66, 0xAF, 0x00, 0x23, 0x66, 0xE7, 0xD3, 0xF8, ++0x08, 0x90, 0x29, 0x46, 0x48, 0x46, 0xF3, 0xF7, 0xB1, 0xFA, 0x03, 0x20, 0xD6, 0xF7, 0xE8, 0xFE, 0x20, 0x21, 0xC0, 0x43, ++0xF3, 0xF7, 0x64, 0xF8, 0x29, 0x46, 0x03, 0x46, 0x03, 0x22, 0x48, 0x46, 0xD6, 0xF7, 0xA6, 0xFE, 0x83, 0xE7, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x1C, 0xDF, 0x44, 0x21, 0x88, 0x34, 0x17, 0x00, 0x00, 0xC1, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x00, 0xEB, 0x81, 0x04, 0xD4, 0xF8, 0x7C, 0x61, 0x16, 0xB1, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x15, 0x48, 0x0D, 0x46, ++0x17, 0x46, 0xF4, 0xF7, 0x1B, 0xF9, 0x80, 0x46, 0x00, 0x28, 0xF4, 0xD0, 0x31, 0x46, 0x4F, 0xF4, 0x92, 0x72, 0xD1, 0xF7, ++0x3B, 0xF8, 0x07, 0xF0, 0x3F, 0x02, 0x0F, 0x4B, 0x88, 0xF8, 0x0C, 0x50, 0x88, 0xF8, 0x0A, 0x20, 0x19, 0x69, 0x0D, 0x4B, ++0xC8, 0xF8, 0x04, 0x10, 0xD3, 0xF8, 0xDC, 0x22, 0xA8, 0xF8, 0x08, 0x70, 0xC8, 0xE9, 0x45, 0x28, 0x01, 0xF5, 0x43, 0x41, ++0xC4, 0xF8, 0x7C, 0x81, 0x08, 0xF5, 0x88, 0x70, 0xD3, 0xF8, 0xE0, 0x31, 0x50, 0x31, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0xF8, 0xDE, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0xEB, 0x81, 0x04, 0x00, 0x2B, 0xD4, 0xF8, 0x7C, 0x51, 0x0D, 0xDB, 0x0C, 0x4B, ++0x05, 0xF5, 0x88, 0x70, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x0A, 0x48, 0x29, 0x46, 0xF4, 0xF7, 0x95, 0xF8, 0x00, 0x23, ++0xC4, 0xF8, 0x7C, 0x31, 0x38, 0xBD, 0x00, 0x2D, 0xEF, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF6, 0x7F, 0x52, 0xF5, 0xF7, ++0xDD, 0xFC, 0xE8, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xDE, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x10, 0xC1, 0x15, 0x00, 0x08, 0x4B, 0x93, 0xF8, 0x73, 0x20, 0x62, 0xB9, 0x02, 0x88, 0xA3, 0xF8, 0x6C, 0x20, 0x42, 0x88, ++0xA3, 0xF8, 0x6E, 0x20, 0x82, 0x88, 0xA3, 0xF8, 0x70, 0x20, 0x4F, 0xF4, 0x80, 0x72, 0xA3, 0xF8, 0x72, 0x20, 0x70, 0x47, ++0xB0, 0xDE, 0x17, 0x00, 0x03, 0x4B, 0x00, 0x22, 0x93, 0xF8, 0x72, 0x00, 0xA3, 0xF8, 0x72, 0x20, 0x70, 0x47, 0x00, 0xBF, ++0xB0, 0xDE, 0x17, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0xF3, 0xF7, 0xDD, 0xFF, 0x03, 0x4B, 0x03, 0x48, 0xD3, 0xF8, ++0x38, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0x06, 0x4B, 0x07, 0x4A, ++0x93, 0xF8, 0x44, 0x30, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x03, 0x13, 0xB3, 0xF8, 0x4C, 0x00, 0xB0, 0xFA, 0x80, 0xF0, ++0x40, 0x09, 0x70, 0x47, 0xB0, 0xDE, 0x17, 0x00, 0xE0, 0x63, 0x18, 0x00, 0xF8, 0xB5, 0x55, 0x4F, 0x46, 0x7F, 0x05, 0x7F, ++0x54, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x06, 0x74, 0xD4, 0xE9, 0x2C, 0xC3, 0x4F, 0xF4, 0xA4, 0x6E, 0x0E, 0xFB, ++0x05, 0x25, 0x1B, 0x68, 0xD5, 0xF8, 0xA8, 0xE4, 0x00, 0x22, 0x0A, 0x60, 0x4B, 0xB3, 0xBE, 0xF1, 0x00, 0x0F, 0x26, 0xD0, ++0xD5, 0xF8, 0xB0, 0x54, 0xAA, 0x07, 0x06, 0xD5, 0x05, 0x8B, 0xB4, 0xF8, 0x34, 0xE0, 0x6C, 0xBA, 0xA4, 0xB2, 0xA6, 0x45, ++0x1B, 0xD0, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0x9C, 0xF8, 0x60, 0x20, 0x01, 0x3A, 0x01, 0x2A, 0x1C, 0xD9, 0x93, 0xF8, ++0x60, 0x20, 0x04, 0x2A, 0x04, 0xD8, 0xDF, 0xE8, 0x02, 0xF0, 0x10, 0x20, 0x27, 0x10, 0x3C, 0x00, 0x3D, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDA, 0x3B, 0x49, 0x3C, 0x48, 0xC4, 0x22, 0xF5, 0xF7, 0x53, 0xFC, 0x00, 0x20, ++0xF8, 0xBD, 0xC2, 0x8B, 0x04, 0x24, 0xD5, 0x07, 0x0C, 0x60, 0x54, 0xD5, 0x20, 0x46, 0xF8, 0xBD, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x06, 0x76, 0x96, 0xF8, 0x5D, 0x22, 0x01, 0x2A, 0xDA, 0xD8, 0xED, 0xE7, 0xC2, 0x8B, 0x0C, 0x24, 0x0C, 0x60, ++0xD4, 0x07, 0x35, 0xD5, 0x08, 0x20, 0xF8, 0xBD, 0xC2, 0x8B, 0x08, 0x24, 0x0C, 0x60, 0xD1, 0x07, 0xF8, 0xD4, 0xD3, 0xE9, ++0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x16, 0x46, 0x0F, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x67, 0x06, 0x22, ++0x38, 0x30, 0x07, 0xF0, 0xCD, 0xFE, 0x20, 0x46, 0xF8, 0xBD, 0xC2, 0x8B, 0x10, 0x24, 0xD2, 0x07, 0x0C, 0x60, 0x13, 0xD4, ++0x93, 0xF8, 0x62, 0x20, 0x0F, 0x2A, 0xD3, 0xE9, 0x12, 0x21, 0x0F, 0xD9, 0x02, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x14, 0x46, ++0x0D, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x45, 0x08, 0x22, 0x38, 0x30, 0x07, 0xF0, 0xB4, 0xFE, 0x12, 0x20, 0xF8, 0xBD, ++0x12, 0x20, 0xF8, 0xBD, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0xEE, 0xE7, 0xD3, 0xE9, 0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, ++0x00, 0x01, 0x14, 0x46, 0x0D, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x45, 0x06, 0x22, 0x38, 0x30, 0x07, 0xF0, 0x9E, 0xFE, ++0xBA, 0xE7, 0xD3, 0xE9, 0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x16, 0x46, 0x0F, 0x46, 0x19, 0x46, 0xE1, 0xE9, ++0x12, 0x67, 0x22, 0x46, 0x38, 0x30, 0x07, 0xF0, 0x8F, 0xFE, 0x20, 0x46, 0xF8, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xF0, 0xB5, 0xC3, 0x8B, ++0x04, 0x46, 0xD8, 0x07, 0x83, 0xB0, 0x44, 0xD4, 0xE0, 0x7E, 0x66, 0x7F, 0x22, 0x7F, 0xFF, 0x28, 0x44, 0xD0, 0x4F, 0xF4, ++0x9E, 0x71, 0x01, 0xFB, 0x06, 0x01, 0x21, 0x48, 0x98, 0x31, 0x00, 0xEB, 0x41, 0x01, 0x1A, 0x25, 0x8F, 0x88, 0x78, 0x1C, ++0xC0, 0xF3, 0x0B, 0x00, 0x88, 0x80, 0x27, 0x84, 0xD9, 0x05, 0x1C, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x02, 0x33, ++0x48, 0xBF, 0x06, 0x35, 0x93, 0xF8, 0x62, 0x30, 0x43, 0xB9, 0x16, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x06, 0x36, ++0x73, 0x68, 0x9B, 0x06, 0x48, 0xBF, 0x04, 0x35, 0x01, 0xA9, 0x84, 0xF8, 0x32, 0x50, 0x20, 0x46, 0xFF, 0xF7, 0x16, 0xFF, ++0x23, 0x8B, 0xA2, 0x88, 0x22, 0x86, 0x5B, 0xBA, 0x9B, 0xB2, 0xB3, 0xF5, 0xC0, 0x6F, 0x28, 0x44, 0x88, 0xBF, 0x08, 0x30, ++0xC0, 0xB2, 0x01, 0x9B, 0x84, 0xF8, 0x33, 0x00, 0x8C, 0xBF, 0x08, 0x21, 0x00, 0x21, 0x84, 0xF8, 0x42, 0x00, 0x84, 0xF8, ++0x34, 0x10, 0x84, 0xF8, 0x35, 0x30, 0x00, 0x23, 0xC4, 0xE9, 0x09, 0x33, 0x03, 0xB0, 0xF0, 0xBD, 0x18, 0x25, 0xC7, 0xE7, ++0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x1D, 0xA0, 0xDF, 0xF8, 0x58, 0x92, ++0x90, 0xF8, 0x1C, 0x80, 0x92, 0x4F, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x0A, 0xF6, 0x09, 0xEB, 0x06, 0x02, 0x4F, 0xF4, ++0xA4, 0x64, 0x04, 0xFB, 0x08, 0x74, 0xD2, 0xF8, 0xB4, 0x30, 0x94, 0xF8, 0x62, 0xC0, 0xD3, 0xF8, 0x00, 0xB0, 0xD2, 0xF8, ++0xB0, 0x30, 0x83, 0xB0, 0x05, 0x46, 0x01, 0x93, 0xD4, 0xF8, 0xA8, 0x34, 0x00, 0x93, 0x0C, 0x46, 0xBC, 0xF1, 0x00, 0x0F, ++0x40, 0xF0, 0x8D, 0x80, 0x53, 0x68, 0x13, 0xF0, 0x20, 0x03, 0x40, 0xF0, 0x9F, 0x80, 0xE9, 0x7E, 0xB5, 0xF8, 0x1E, 0xC0, ++0xFF, 0x29, 0x0C, 0xBF, 0xA4, 0xF1, 0x18, 0x00, 0xA4, 0xF1, 0x1A, 0x00, 0x1C, 0xF4, 0x80, 0x72, 0x1D, 0xBF, 0x06, 0x38, ++0x00, 0xF1, 0x1E, 0x04, 0x02, 0x46, 0x00, 0xF1, 0x18, 0x04, 0xFF, 0x29, 0x00, 0xF0, 0x94, 0x80, 0x6F, 0xF0, 0x7F, 0x0C, ++0x4F, 0xF0, 0x00, 0x0E, 0x80, 0xF8, 0x00, 0xC0, 0x80, 0xF8, 0x01, 0xE0, 0x21, 0x80, 0x29, 0x8C, 0xB5, 0xF8, 0x1E, 0xC0, ++0x09, 0x01, 0x1C, 0xF4, 0x00, 0x7F, 0xC1, 0x82, 0x63, 0xD1, 0x01, 0x88, 0x0B, 0x43, 0x43, 0xF0, 0x08, 0x01, 0x1C, 0xF4, ++0x00, 0x6F, 0x01, 0x80, 0x69, 0xD0, 0x23, 0xF4, 0x40, 0x71, 0x41, 0xF0, 0x08, 0x01, 0x89, 0xB2, 0x01, 0x80, 0x4F, 0xF4, ++0xA4, 0x64, 0x1C, 0xF0, 0x04, 0x0F, 0x04, 0xFB, 0x08, 0xF4, 0x18, 0xBF, 0x41, 0xF4, 0x00, 0x51, 0x04, 0xF1, 0x5C, 0x03, ++0x18, 0xBF, 0x01, 0x80, 0x07, 0xEB, 0x03, 0x0C, 0xFB, 0x5A, 0x43, 0x81, 0xBC, 0xF8, 0x02, 0x30, 0x83, 0x81, 0x01, 0xF4, ++0x40, 0x71, 0xBC, 0xF8, 0x04, 0x30, 0xC3, 0x81, 0xB1, 0xF5, 0x80, 0x7F, 0x5C, 0xD0, 0xB1, 0xF5, 0x00, 0x7F, 0x76, 0xD0, ++0x00, 0x29, 0x40, 0xF0, 0x81, 0x80, 0xAB, 0x89, 0x83, 0x80, 0xEB, 0x89, 0xC3, 0x80, 0x2B, 0x8A, 0x03, 0x81, 0x04, 0xF5, ++0xB2, 0x74, 0x3B, 0x5B, 0x03, 0x82, 0x3C, 0x44, 0x63, 0x88, 0x43, 0x82, 0xA3, 0x88, 0x83, 0x82, 0xBB, 0xF1, 0x00, 0x0F, ++0x1C, 0xD0, 0x00, 0x9B, 0xD3, 0xB1, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x77, 0xD7, 0xF8, 0xB0, 0x34, 0x9B, 0x07, ++0x0A, 0xD5, 0x6A, 0x7F, 0x2B, 0x8B, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x02, 0x92, 0x5B, 0xBA, 0x92, 0x8E, 0x9B, 0xB2, ++0x9A, 0x42, 0x07, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x7B, 0xD0, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, 0x01, 0x2B, 0x6E, 0xD9, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x23, 0x75, 0xE7, 0x21, 0x88, 0x41, 0xF0, 0x10, 0x01, 0x21, 0x80, 0x01, 0x88, ++0xB5, 0xF8, 0x1E, 0xC0, 0x0B, 0x43, 0x43, 0xF0, 0x08, 0x01, 0x1C, 0xF4, 0x00, 0x6F, 0x01, 0x80, 0x95, 0xD1, 0x1C, 0xF4, ++0x80, 0x7F, 0x22, 0xD0, 0x43, 0xF4, 0x42, 0x71, 0x01, 0x80, 0x94, 0xE7, 0x32, 0x4B, 0x11, 0x46, 0xD3, 0xF8, 0xB8, 0x33, ++0x98, 0x47, 0x4F, 0xF4, 0x00, 0x43, 0x44, 0xF8, 0x04, 0x0D, 0x56, 0xE7, 0x00, 0x21, 0x81, 0x75, 0xC1, 0x75, 0x7A, 0xE7, ++0x26, 0x36, 0x09, 0xEB, 0x06, 0x03, 0x39, 0xF8, 0x06, 0x20, 0x82, 0x80, 0x5A, 0x88, 0xC2, 0x80, 0x9B, 0x88, 0x03, 0x81, ++0xAB, 0x89, 0x03, 0x82, 0xEB, 0x89, 0x43, 0x82, 0x2B, 0x8A, 0x83, 0x82, 0xA6, 0xE7, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, ++0x08, 0x74, 0x94, 0xF8, 0x62, 0x40, 0x00, 0x2C, 0x27, 0xD1, 0x43, 0xF4, 0x84, 0x71, 0x01, 0x80, 0x69, 0xE7, 0xAB, 0x89, ++0x83, 0x80, 0xEB, 0x89, 0xC3, 0x80, 0x2B, 0x8A, 0x03, 0x81, 0x6B, 0x8A, 0x03, 0x82, 0xAB, 0x8A, 0x43, 0x82, 0xEB, 0x8A, ++0x83, 0x82, 0x8D, 0xE7, 0x26, 0x36, 0x09, 0xEB, 0x06, 0x03, 0x39, 0xF8, 0x06, 0x10, 0x91, 0x80, 0x59, 0x88, 0xD1, 0x80, ++0x9B, 0x88, 0x13, 0x81, 0xAB, 0x89, 0x13, 0x82, 0xEB, 0x89, 0x53, 0x82, 0x2B, 0x8A, 0x93, 0x82, 0x6B, 0x8A, 0x13, 0x83, ++0xAB, 0x8A, 0x53, 0x83, 0xEB, 0x8A, 0x93, 0x83, 0x76, 0xE7, 0x02, 0x2C, 0x04, 0xBF, 0x43, 0xF4, 0x02, 0x71, 0x01, 0x80, ++0x3F, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x0A, 0x99, 0x99, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x88, 0xD9, 0x03, 0x88, ++0x43, 0xF4, 0x80, 0x43, 0x03, 0x80, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x06, 0x46, 0x54, 0x48, 0x75, 0x7F, 0x34, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x05, 0x03, 0x89, 0x46, 0xD3, 0xF8, 0xB4, 0x70, 0xD7, 0xF8, 0x00, 0x80, 0xB8, 0xF1, 0x00, 0x0F, 0x4C, 0xD0, ++0x17, 0x46, 0x4D, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x04, 0x24, 0xD4, 0xF8, 0xA8, 0x24, 0x00, 0x2A, 0x42, 0xD0, ++0xD4, 0xF8, 0xB0, 0x24, 0x92, 0x07, 0x05, 0xD5, 0x32, 0x8B, 0x99, 0x8E, 0x53, 0xBA, 0x9B, 0xB2, 0x99, 0x42, 0x38, 0xD0, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x05, 0xD5, 0xF8, 0xB0, 0x30, 0x23, 0xB1, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, ++0x01, 0x2B, 0x40, 0xD9, 0x98, 0xF8, 0x60, 0x30, 0x04, 0x2B, 0x67, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x2A, 0x03, 0x40, 0x2A, ++0x49, 0x00, 0x32, 0x8F, 0x42, 0xF4, 0x00, 0x53, 0x03, 0xF4, 0xFE, 0x43, 0x43, 0xEA, 0x12, 0x23, 0x29, 0xF8, 0x08, 0x3C, ++0x96, 0xF8, 0x38, 0x30, 0x98, 0xF8, 0x61, 0x20, 0xA9, 0xF1, 0x08, 0x09, 0x43, 0xEA, 0x82, 0x33, 0x43, 0xF4, 0x00, 0x53, ++0xA9, 0xF8, 0x02, 0x30, 0x73, 0x8F, 0xA9, 0xF8, 0x04, 0x30, 0xB3, 0x8F, 0xA9, 0xF8, 0x06, 0x30, 0xC7, 0xB1, 0xF2, 0x6A, ++0xD4, 0x68, 0x2B, 0x4B, 0x98, 0xF8, 0x62, 0x00, 0x23, 0x40, 0x03, 0x43, 0xD3, 0x60, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, ++0x33, 0x8F, 0x29, 0xF8, 0x04, 0x3C, 0x98, 0xF8, 0x61, 0x20, 0x73, 0x8F, 0xA9, 0xF1, 0x04, 0x09, 0x43, 0xEA, 0x82, 0x33, ++0xA9, 0xF8, 0x02, 0x30, 0x00, 0x2F, 0xE6, 0xD1, 0xB2, 0x6C, 0x28, 0x32, 0xE4, 0xE7, 0x95, 0xF8, 0x5D, 0x32, 0x01, 0x2B, ++0xBA, 0xD8, 0xE6, 0xE7, 0x33, 0x8F, 0x29, 0xF8, 0x08, 0x3C, 0x98, 0xF8, 0x61, 0x30, 0xA9, 0xF1, 0x08, 0x09, 0x9B, 0x03, ++0xCA, 0xE7, 0x98, 0xF8, 0x61, 0x30, 0x29, 0xF8, 0x12, 0x3C, 0xA9, 0xF1, 0x12, 0x09, 0x33, 0x8F, 0xA9, 0xF8, 0x02, 0x30, ++0x73, 0x8F, 0xA9, 0xF8, 0x04, 0x30, 0xB3, 0x8F, 0xA9, 0xF8, 0x06, 0x30, 0xF3, 0x8F, 0xA9, 0xF8, 0x08, 0x30, 0x45, 0xF6, ++0x36, 0x43, 0xA9, 0xF8, 0x0A, 0x30, 0xA9, 0xF8, 0x0C, 0x30, 0xA9, 0xF8, 0x0E, 0x30, 0xA9, 0xF8, 0x10, 0x30, 0xB7, 0xE7, ++0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB1, 0xDA, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xD9, 0x22, ++0xF5, 0xF7, 0xA8, 0xF9, 0xAA, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x00, 0xFC, 0x0F, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x70, 0xB5, 0x1A, 0x4D, 0x1A, 0x4E, 0xD5, 0xF8, ++0x68, 0x32, 0x04, 0x46, 0x98, 0x47, 0x60, 0x7F, 0xD5, 0xF8, 0x5C, 0x31, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0x60, ++0x98, 0x47, 0xE3, 0x8B, 0xE0, 0x62, 0x99, 0x04, 0x11, 0xD5, 0x63, 0x7F, 0x05, 0xFB, 0x03, 0x66, 0xD6, 0xF8, 0x4C, 0x31, ++0xD3, 0xF8, 0x9C, 0x20, 0xA2, 0x62, 0x93, 0xF8, 0xA1, 0x30, 0x2B, 0xB1, 0x94, 0xF8, 0x36, 0x30, 0x43, 0xF0, 0x20, 0x03, ++0x84, 0xF8, 0x36, 0x30, 0x70, 0xBD, 0x94, 0xF8, 0x36, 0x30, 0x03, 0xF0, 0x03, 0x02, 0x00, 0xEB, 0x82, 0x00, 0x42, 0x6A, ++0x41, 0x69, 0xA1, 0x62, 0x52, 0x03, 0x44, 0xBF, 0x43, 0xF0, 0x20, 0x03, 0x84, 0xF8, 0x36, 0x30, 0x70, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0xC3, 0x7E, 0x00, 0x93, 0x04, 0x46, 0xC3, 0x8B, ++0x0F, 0x46, 0x16, 0x46, 0x16, 0x49, 0x02, 0x8C, 0x20, 0x20, 0xF4, 0xF7, 0x29, 0xFF, 0xE3, 0x8B, 0xD9, 0x07, 0x1E, 0xD5, ++0x13, 0x48, 0xF4, 0xF7, 0xD3, 0xFE, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x10, 0x4D, 0x2B, 0x68, 0x3A, 0x46, 0x01, 0x33, 0x31, 0x46, 0x20, 0x46, 0x2B, 0x60, 0xDF, 0xF7, 0x4A, 0xFD, ++0x2B, 0x68, 0x33, 0xB1, 0x09, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x03, 0xB0, ++0xF0, 0xBD, 0xDF, 0xF7, 0x61, 0xF9, 0xE3, 0x8B, 0xDA, 0x07, 0xDB, 0xD4, 0xDD, 0xE7, 0x00, 0xBF, 0x3C, 0xC1, 0x15, 0x00, ++0x58, 0xC1, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x02, 0x8B, 0x53, 0xBA, 0x9B, 0xB2, 0xB3, 0xF5, ++0xC0, 0x6F, 0x10, 0xB5, 0x04, 0x46, 0x08, 0xD3, 0x4A, 0xF6, 0xAA, 0x23, 0x21, 0xF8, 0x08, 0x3D, 0x03, 0x20, 0x00, 0x23, ++0xCA, 0x80, 0x48, 0x80, 0x8B, 0x80, 0x20, 0x46, 0x01, 0x22, 0xFF, 0xF7, 0xBB, 0xFE, 0x04, 0x4B, 0x01, 0x46, 0xD3, 0xF8, ++0x20, 0x34, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xC5, 0x8B, 0xDF, 0xF8, 0x7C, 0x82, 0x07, 0x7F, 0x4F, 0xF4, 0xA4, 0x6A, 0x0E, 0x46, 0x29, 0x07, 0x83, 0xB0, 0x04, 0x46, ++0x0A, 0xFB, 0x07, 0x8A, 0x6B, 0xD4, 0x41, 0x7F, 0xDF, 0xF8, 0x64, 0xB2, 0x03, 0x8B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, ++0x01, 0xB1, 0x5B, 0xBA, 0x88, 0x8E, 0x91, 0xF8, 0x30, 0x20, 0x9B, 0xB2, 0x98, 0x42, 0x0F, 0xD0, 0x02, 0x2A, 0x16, 0xD0, ++0x8B, 0x49, 0x20, 0x20, 0xF4, 0xF7, 0xB4, 0xFE, 0x20, 0x46, 0x31, 0x46, 0x4F, 0xF0, 0x00, 0x42, 0xFF, 0xF7, 0x78, 0xFF, ++0x00, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x3A, 0x25, 0xF4, 0x80, 0x75, 0x01, 0x2A, 0xE5, 0x83, 0x02, 0xD9, ++0x91, 0xF8, 0x30, 0x20, 0xE8, 0xE7, 0xDF, 0xF8, 0x1C, 0x92, 0x20, 0x46, 0xD9, 0xF8, 0x2C, 0x34, 0x98, 0x47, 0x63, 0x7F, ++0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0xBB, 0x9B, 0xF8, 0x30, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xA2, 0x80, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x07, 0x87, 0x77, 0x4A, 0x3B, 0x6C, 0x77, 0x49, 0x1F, 0x79, 0x77, 0x4B, 0x00, 0x2F, 0x0C, 0xBF, ++0x0F, 0x46, 0x17, 0x46, 0xE7, 0x62, 0x7D, 0x69, 0x93, 0xF8, 0xBD, 0x20, 0xC5, 0xF3, 0xC2, 0x28, 0xED, 0xB2, 0x00, 0x2A, ++0x40, 0xF0, 0xB4, 0x80, 0xD9, 0xF8, 0x38, 0x33, 0x50, 0x46, 0x01, 0xAA, 0x0D, 0xF1, 0x03, 0x01, 0x98, 0x47, 0x05, 0xF0, ++0x7C, 0x03, 0x58, 0xEA, 0x03, 0x03, 0x0C, 0xBF, 0x9D, 0xF8, 0x03, 0x30, 0x9D, 0xF8, 0x04, 0x30, 0x43, 0xEA, 0x03, 0x23, ++0x7B, 0x62, 0xE3, 0x8B, 0xDB, 0x07, 0x4C, 0xD4, 0xA1, 0x6C, 0xD9, 0xF8, 0x1C, 0x34, 0xA8, 0x31, 0x20, 0x46, 0x98, 0x47, ++0x45, 0xE0, 0x00, 0x23, 0xEA, 0x06, 0x01, 0x93, 0x5B, 0xD5, 0x5D, 0x4B, 0xE3, 0x62, 0x15, 0xF0, 0x80, 0x05, 0x7D, 0xD1, ++0xA8, 0x46, 0xDF, 0xF8, 0x80, 0x91, 0x5B, 0x4F, 0xD9, 0xF8, 0x38, 0x33, 0x50, 0x46, 0x0D, 0xF1, 0x03, 0x02, 0x0D, 0xF1, ++0x02, 0x01, 0x98, 0x47, 0xE2, 0x6A, 0x4F, 0xF0, 0x00, 0x0A, 0xA3, 0x68, 0x02, 0xEB, 0x8A, 0x00, 0x23, 0xF0, 0x60, 0x41, ++0x13, 0xF0, 0x80, 0x4F, 0x41, 0xF0, 0x00, 0x51, 0x14, 0xBF, 0x41, 0x61, 0x43, 0x69, 0x97, 0xF8, 0xBD, 0x10, 0xC3, 0xF3, ++0xC2, 0x20, 0x03, 0xF0, 0x7F, 0x03, 0x51, 0xBB, 0x08, 0xBB, 0x03, 0x2B, 0x02, 0xEB, 0x8A, 0x01, 0x1D, 0xD8, 0x9D, 0xF8, ++0x02, 0x30, 0x43, 0xEA, 0x03, 0x23, 0x4B, 0x62, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x04, 0x0F, 0xDD, 0xD1, 0x00, 0x23, ++0xC4, 0xE9, 0x09, 0x33, 0x01, 0x9A, 0x84, 0xF8, 0x32, 0x80, 0x84, 0xF8, 0x33, 0x50, 0x84, 0xF8, 0x42, 0x50, 0x84, 0xF8, ++0x35, 0x20, 0xD9, 0xF8, 0x94, 0x33, 0x31, 0x46, 0x20, 0x46, 0x98, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x9D, 0xF8, ++0x03, 0x30, 0x02, 0xEB, 0x8A, 0x01, 0x43, 0xEA, 0x03, 0x23, 0x4B, 0x62, 0xDE, 0xE7, 0x19, 0x46, 0xD1, 0xF7, 0xF0, 0xFD, ++0xE2, 0x6A, 0x02, 0xEB, 0x8A, 0x03, 0x40, 0xEA, 0x00, 0x20, 0x58, 0x62, 0xD4, 0xE7, 0x9A, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0x9F, 0xD1, 0xDA, 0xF8, 0x40, 0x20, 0x2D, 0x4B, 0x11, 0x79, 0x2B, 0x4A, 0x00, 0x29, 0x18, 0xBF, 0x13, 0x46, 0xC3, 0x62, ++0x97, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x83, 0x93, 0xF8, 0x62, 0x20, 0x52, 0xB3, 0x02, 0x2A, 0x04, 0xD1, ++0x9B, 0xF8, 0x70, 0x32, 0x00, 0x2B, 0x7F, 0xF4, 0x50, 0xAF, 0x24, 0x4B, 0x1B, 0x78, 0x1B, 0xB9, 0xD9, 0xF8, 0x1C, 0x30, ++0x20, 0x46, 0x98, 0x47, 0x20, 0x46, 0xFF, 0xF7, 0x67, 0xFE, 0x6E, 0xE7, 0x00, 0x22, 0xC0, 0x21, 0x20, 0x46, 0x01, 0xF0, ++0x1D, 0xFB, 0x01, 0x28, 0x1C, 0xD0, 0x02, 0x28, 0x15, 0xD0, 0xE3, 0x8B, 0x00, 0x25, 0x23, 0xF0, 0x80, 0x03, 0xE3, 0x83, ++0xA8, 0x46, 0x72, 0xE7, 0x05, 0xF0, 0x7F, 0x01, 0x40, 0x46, 0xD1, 0xF7, 0xAD, 0xFD, 0x40, 0xEA, 0x00, 0x20, 0x78, 0x62, ++0x55, 0xE7, 0x93, 0xF8, 0xAC, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x27, 0xAF, 0xD5, 0xE7, 0x12, 0x23, 0x00, 0x25, 0x01, 0x93, ++0xA8, 0x46, 0x5E, 0xE7, 0x01, 0xA9, 0x20, 0x46, 0xFF, 0xF7, 0x46, 0xFB, 0xA3, 0x6C, 0x05, 0x46, 0x03, 0xF1, 0xA8, 0x01, ++0x03, 0xF1, 0xA0, 0x00, 0x18, 0x22, 0x07, 0xF0, 0x75, 0xFA, 0xED, 0xB2, 0x4F, 0xF0, 0x18, 0x08, 0x4D, 0xE7, 0x00, 0xBF, ++0x70, 0xC1, 0x15, 0x00, 0x84, 0x3C, 0x18, 0x00, 0xC4, 0x3C, 0x18, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xB8, 0x34, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x51, 0x4A, 0x43, 0x7F, ++0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x03, 0x23, 0x86, 0xB0, 0xD3, 0xF8, 0xB4, 0x30, 0x1E, 0x68, 0x8E, 0xB1, 0x90, 0xF8, ++0x35, 0x30, 0x04, 0x46, 0x6B, 0xB1, 0x90, 0xF8, 0x34, 0x30, 0x85, 0x6C, 0x96, 0xF8, 0x60, 0x20, 0xED, 0x1A, 0x01, 0x2A, ++0x05, 0xF1, 0xA8, 0x05, 0x06, 0xD0, 0x03, 0x2A, 0x51, 0xD0, 0x00, 0x2A, 0x4F, 0xD0, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, ++0x07, 0x8E, 0x42, 0x4A, 0x00, 0x91, 0x3B, 0x44, 0x06, 0xF1, 0x50, 0x01, 0xD2, 0xF8, 0x7C, 0x73, 0x2A, 0x46, 0xB8, 0x47, ++0x3E, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9A, 0x07, 0xED, 0xD5, 0x96, 0xF8, 0x60, 0x20, 0x01, 0x2A, 0x06, 0xF1, 0x64, 0x08, ++0x3E, 0xD1, 0x23, 0x8E, 0x94, 0xF8, 0x34, 0x70, 0x0C, 0x33, 0x1F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, 0x4F, 0xF0, 0xFF, 0x33, ++0x03, 0x22, 0x28, 0x46, 0xD6, 0xF7, 0xD8, 0xF8, 0xD6, 0xE9, 0x12, 0x03, 0x32, 0x49, 0x94, 0xF8, 0x1C, 0xC0, 0x88, 0x80, ++0x31, 0x4A, 0x00, 0x0C, 0x4F, 0xF4, 0xA4, 0x6E, 0x40, 0xEA, 0x03, 0x40, 0x0E, 0xFB, 0x0C, 0x22, 0x08, 0x60, 0x02, 0xAB, ++0x40, 0x46, 0xF2, 0xF7, 0x9F, 0xFA, 0x02, 0xA8, 0x10, 0x21, 0xF2, 0xF7, 0x5F, 0xFC, 0x96, 0xF8, 0x60, 0x20, 0xCA, 0xB1, ++0x03, 0x2A, 0x17, 0xD0, 0x03, 0x20, 0xD6, 0xF7, 0xF1, 0xF8, 0x39, 0x46, 0x02, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x84, 0xFA, ++0x39, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x7A, 0xFC, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, ++0x9B, 0x07, 0xAA, 0xD5, 0x06, 0xF1, 0x64, 0x08, 0x00, 0x27, 0xE4, 0xE7, 0x23, 0x8E, 0x94, 0xF8, 0x34, 0x70, 0x04, 0x33, ++0x1F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x28, 0x46, 0xD6, 0xF7, 0x97, 0xF8, 0x96, 0xF8, ++0x60, 0x30, 0xB6, 0xF8, 0x48, 0x10, 0xB6, 0xF8, 0x4A, 0x20, 0xAD, 0xF8, 0x08, 0x10, 0x8D, 0xF8, 0x0A, 0x20, 0x41, 0x46, ++0x4B, 0xB9, 0x05, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x07, 0xF0, 0xCA, 0xF9, 0x02, 0xA8, 0x08, 0x21, 0xF2, 0xF7, 0x20, 0xFC, ++0xC4, 0xE7, 0x0D, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x07, 0xF0, 0xC0, 0xF9, 0x02, 0xA8, 0x10, 0x21, 0xF2, 0xF7, 0x16, 0xFC, ++0xBA, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0xA0, 0x34, 0x17, 0x00, ++0x74, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xC5, 0x6C, 0xC3, 0x8B, 0x2F, 0x69, 0x02, 0x8C, 0x2A, 0x81, 0x00, 0x26, ++0x13, 0xF0, 0x08, 0x02, 0x2E, 0x61, 0x04, 0x46, 0x07, 0xF4, 0x00, 0x06, 0x88, 0x46, 0x07, 0xF0, 0x40, 0x47, 0x1C, 0xD0, ++0x99, 0x06, 0x01, 0xD5, 0x00, 0x2E, 0x6C, 0xD0, 0x9A, 0x05, 0x3E, 0xD4, 0xB7, 0xF1, 0x40, 0x4F, 0x20, 0xD0, 0xE3, 0x7E, ++0xFF, 0x2B, 0x22, 0xD1, 0x2B, 0x69, 0x62, 0x6A, 0x01, 0x20, 0x02, 0xF4, 0x00, 0x12, 0x16, 0xB1, 0x43, 0xF0, 0x08, 0x03, ++0x2B, 0x61, 0x00, 0x2A, 0x47, 0xD0, 0x43, 0xF0, 0x01, 0x03, 0x28, 0x73, 0x2B, 0x61, 0xBD, 0xE8, 0xF0, 0x81, 0x9B, 0x05, ++0xE6, 0xD5, 0x43, 0x7F, 0x2A, 0x49, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0xB7, 0xF1, 0x40, 0x4F, 0x83, 0xF8, ++0x32, 0x20, 0xDE, 0xD1, 0x2B, 0x69, 0x43, 0xF0, 0x04, 0x03, 0x2B, 0x61, 0xDD, 0xE7, 0x31, 0x1E, 0x42, 0x46, 0x18, 0xBF, ++0x01, 0x21, 0x20, 0x46, 0x01, 0xF0, 0x3A, 0xF8, 0x63, 0x6A, 0x13, 0xF4, 0x00, 0x12, 0x20, 0xD0, 0x03, 0xF4, 0x60, 0x13, ++0xB3, 0xF5, 0x60, 0x1F, 0x01, 0xD0, 0x00, 0x23, 0x6B, 0x73, 0x2B, 0x69, 0x00, 0x2E, 0xD2, 0xD0, 0xCC, 0xE7, 0x19, 0x4B, ++0x60, 0x7F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1A, 0xDB, 0x00, 0x23, 0x1A, 0x46, 0x17, 0x21, 0xE0, 0xF7, ++0x0D, 0xFA, 0x12, 0x4A, 0x63, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x00, 0x22, 0x83, 0xF8, 0x32, 0x20, ++0xAA, 0xE7, 0x2B, 0x69, 0x0E, 0xB1, 0x43, 0xF0, 0x08, 0x03, 0x01, 0x22, 0x43, 0xF0, 0x01, 0x03, 0x6A, 0x73, 0x28, 0x73, ++0x2B, 0x61, 0xBD, 0xE8, 0xF0, 0x81, 0xFF, 0x28, 0xE2, 0xD1, 0x08, 0x48, 0x08, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0xF4, 0xF7, ++0x89, 0xFE, 0x60, 0x7F, 0xDA, 0xE7, 0xFF, 0xF7, 0xC7, 0xF9, 0xE3, 0x8B, 0x8E, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x84, 0xC1, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x70, 0xB5, 0x90, 0xF8, 0x33, 0x30, 0x82, 0xB0, ++0x04, 0x46, 0x0D, 0x46, 0x16, 0x46, 0x7B, 0xB1, 0x90, 0xF8, 0x35, 0x20, 0x01, 0x92, 0x18, 0x46, 0x2B, 0x88, 0x2E, 0x44, ++0x43, 0xF4, 0x80, 0x43, 0x31, 0x18, 0x2B, 0x80, 0x20, 0x46, 0x00, 0x22, 0xFF, 0xF7, 0x12, 0xFC, 0x02, 0xB0, 0x70, 0xBD, ++0x01, 0xA9, 0xFF, 0xF7, 0xCD, 0xF9, 0x01, 0x9B, 0x84, 0xF8, 0x33, 0x00, 0x84, 0xF8, 0x35, 0x30, 0xEA, 0xE7, 0x00, 0xBF, ++0x10, 0xB4, 0x0C, 0x88, 0x0B, 0x46, 0x44, 0xF4, 0x80, 0x44, 0x11, 0x44, 0x1C, 0x80, 0x00, 0x22, 0x5D, 0xF8, 0x04, 0x4B, ++0xFF, 0xF7, 0xFA, 0xBB, 0xF0, 0xB5, 0x00, 0x22, 0x18, 0x4C, 0x85, 0xB0, 0x05, 0x46, 0x0F, 0x46, 0x02, 0xE0, 0x01, 0x32, ++0x20, 0x2A, 0x26, 0xD0, 0xA5, 0x42, 0x96, 0xB2, 0x04, 0xF1, 0x18, 0x04, 0xF7, 0xD1, 0x12, 0x02, 0x02, 0xF4, 0x7F, 0x42, ++0x42, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0xF6, 0xFF, 0x04, 0x28, 0x18, 0xD1, 0x17, 0xF4, 0x00, 0x03, 0x02, 0xD1, 0xEA, 0x7C, ++0x02, 0x2A, 0x06, 0xD9, 0x28, 0x7B, 0x31, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0x00, 0xF0, 0x65, 0xBC, 0x08, 0x49, ++0x01, 0x32, 0xEA, 0x74, 0x27, 0x22, 0xCD, 0xE9, 0x01, 0x21, 0x00, 0x93, 0x28, 0x7B, 0x02, 0x22, 0x29, 0x46, 0x00, 0xF0, ++0xBB, 0xFC, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, 0xF4, 0xE4, 0x17, 0x00, 0xE5, 0xFE, 0x14, 0x00, 0x2D, 0xE9, 0xF0, 0x43, ++0x10, 0x46, 0x85, 0xB0, 0x14, 0x46, 0x0F, 0x46, 0xF2, 0xF7, 0xCC, 0xFF, 0x03, 0x28, 0x09, 0xD0, 0x50, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x72, 0xDB, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x4C, 0x4E, 0x4F, 0xEA, ++0x14, 0x28, 0x08, 0xEB, 0x48, 0x03, 0x06, 0xEB, 0xC3, 0x06, 0x96, 0xF8, 0x0D, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x39, 0xD0, ++0xB9, 0xF1, 0x01, 0x0F, 0x29, 0xD1, 0xBB, 0x78, 0x00, 0x2B, 0x7C, 0xD1, 0x05, 0x46, 0x30, 0x46, 0x96, 0xF8, 0x0F, 0x90, ++0x00, 0xF0, 0xA0, 0xFF, 0x41, 0x4B, 0x1B, 0x69, 0x73, 0x60, 0x05, 0x22, 0x2B, 0x46, 0x0C, 0x21, 0x41, 0xF2, 0x0B, 0x40, ++0x3D, 0x78, 0x7F, 0x78, 0xF2, 0xF7, 0xFA, 0xFC, 0xA9, 0xF1, 0x04, 0x09, 0x4F, 0xFA, 0x89, 0xF9, 0x80, 0xF8, 0x02, 0x90, ++0x05, 0x70, 0x47, 0x70, 0xF2, 0xF7, 0x20, 0xFD, 0x73, 0x89, 0x00, 0x2B, 0x39, 0xD1, 0x20, 0x46, 0x01, 0x21, 0xF2, 0xF7, ++0xE3, 0xFE, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x2F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xBC, 0xDA, 0x2F, 0x49, 0x2F, 0x48, 0x40, 0xF2, 0x29, 0x12, 0xF4, 0xF7, 0xD3, 0xFD, 0xB5, 0xE7, 0xBA, 0x78, 0x33, 0x7C, ++0x72, 0xBB, 0xB0, 0x7B, 0xF1, 0x7B, 0x02, 0x92, 0x9B, 0x00, 0x43, 0xEA, 0x40, 0x03, 0x43, 0xEA, 0x81, 0x13, 0xCD, 0xE9, ++0x00, 0x32, 0x31, 0x46, 0x73, 0x7C, 0x30, 0x7B, 0x01, 0x22, 0x00, 0xF0, 0x47, 0xFC, 0x3B, 0x78, 0x7D, 0x78, 0x23, 0x4A, ++0x1F, 0x48, 0x71, 0x89, 0x03, 0xEB, 0x83, 0x07, 0xC3, 0xEB, 0x07, 0x13, 0x2B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x83, 0xF8, ++0xA4, 0x81, 0x03, 0x69, 0x73, 0x60, 0x00, 0x29, 0xC5, 0xD0, 0x40, 0x46, 0x00, 0xF0, 0x9A, 0xFB, 0xC1, 0xE7, 0x17, 0x49, ++0x17, 0x48, 0xC8, 0x22, 0xF4, 0xF7, 0xA4, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0xB1, 0x7B, 0xF2, 0x7B, ++0xCD, 0xF8, 0x08, 0x90, 0x9B, 0x00, 0x43, 0xEA, 0x41, 0x03, 0x43, 0xEA, 0x82, 0x13, 0x25, 0x22, 0xCD, 0xE9, 0x00, 0x32, ++0x31, 0x46, 0x30, 0x7B, 0x73, 0x7C, 0x01, 0x22, 0x00, 0xF0, 0x16, 0xFC, 0x49, 0x46, 0x20, 0x46, 0xF2, 0xF7, 0x8A, 0xFE, ++0x6C, 0xE7, 0x40, 0x46, 0x00, 0xF0, 0xF8, 0xFA, 0x20, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0x82, 0xFE, 0x64, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x8B, 0x78, 0x02, 0x2B, 0x01, 0xD0, 0x00, 0x20, 0xF8, 0xBD, 0x02, 0xF4, 0x7F, 0x40, ++0x40, 0xF0, 0x08, 0x00, 0x0C, 0x46, 0x15, 0x0A, 0xF2, 0xF7, 0x0E, 0xFF, 0x04, 0x28, 0xF3, 0xD1, 0x11, 0x4E, 0x05, 0xEB, ++0x45, 0x03, 0x06, 0xEB, 0xC3, 0x06, 0x73, 0x7B, 0x01, 0x2B, 0x04, 0xD0, 0x0E, 0x4B, 0x28, 0x46, 0x9B, 0x6A, 0x98, 0x47, ++0xE6, 0xE7, 0x70, 0x69, 0x00, 0xF0, 0x1E, 0xFF, 0xF3, 0x7B, 0x67, 0x78, 0x26, 0x78, 0xC3, 0xF1, 0x04, 0x03, 0x1C, 0x18, ++0x05, 0x22, 0x03, 0x23, 0x0C, 0x21, 0x41, 0xF2, 0x0B, 0x40, 0xF2, 0xF7, 0x4D, 0xFC, 0x64, 0xB2, 0x84, 0x70, 0x06, 0x70, ++0x47, 0x70, 0xF2, 0xF7, 0x77, 0xFC, 0xE3, 0xE7, 0xF4, 0xE4, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xB7, 0x4F, 0xCE, 0x79, 0xB7, 0x4A, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x06, 0x75, 0x0C, 0x46, 0x95, 0xF8, 0x22, 0x30, ++0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x85, 0xB0, 0x93, 0xF8, 0x64, 0x30, 0x1B, 0xB9, 0x00, 0x20, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x20, 0x94, 0xF8, 0x0D, 0x80, 0xF2, 0xF7, 0xC7, 0xFE, 0x09, 0x28, 0x04, 0xF1, 0x0C, 0x09, ++0xF2, 0xD0, 0xB8, 0xF1, 0x01, 0x0F, 0x5B, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0x1B, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0xE9, 0xD1, ++0xB9, 0xF8, 0x03, 0x80, 0x99, 0xF8, 0x02, 0xB0, 0xC8, 0xF3, 0x83, 0x0A, 0xBA, 0xF1, 0x08, 0x0F, 0x04, 0xD8, 0xA1, 0x4B, ++0x1B, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x87, 0x80, 0x25, 0x23, 0x00, 0x21, 0xCD, 0xE9, 0x00, 0x83, 0x30, 0x46, 0x5B, 0x46, ++0x02, 0x91, 0x01, 0x22, 0x00, 0xF0, 0x82, 0xFB, 0xD0, 0xE7, 0xB9, 0xF8, 0x02, 0x10, 0xB1, 0xF5, 0x10, 0x4F, 0x4F, 0xEA, ++0x11, 0x35, 0xC9, 0xD2, 0xE3, 0x79, 0xFF, 0x2B, 0xC6, 0xD0, 0x09, 0x05, 0x2A, 0x46, 0x40, 0xF1, 0xBA, 0x80, 0x93, 0x49, ++0x4F, 0xF4, 0x00, 0x60, 0xF4, 0xF7, 0xA4, 0xFA, 0xE3, 0x79, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x2B, 0x44, ++0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA4, 0x51, 0x21, 0x2D, 0xB1, 0xD0, 0x2E, 0x02, 0x46, 0xF0, 0x08, 0x06, 0x30, 0x46, ++0xF2, 0xF7, 0x7C, 0xFE, 0x04, 0x28, 0xA9, 0xD0, 0x31, 0x46, 0x42, 0xF2, 0x01, 0x00, 0xF2, 0xF7, 0xE1, 0xFA, 0x30, 0x46, ++0xF2, 0xF7, 0x72, 0xFE, 0x01, 0x28, 0x00, 0xF0, 0xD2, 0x80, 0x30, 0x46, 0xF2, 0xF7, 0x6C, 0xFE, 0x03, 0x28, 0x00, 0xF0, ++0xCC, 0x80, 0x7F, 0x4B, 0x28, 0x46, 0x9B, 0x6A, 0x98, 0x47, 0x93, 0xE7, 0xB9, 0xF8, 0x05, 0x50, 0xC5, 0xF3, 0x83, 0x06, ++0x08, 0x2E, 0x8D, 0xD8, 0xE3, 0x79, 0x7A, 0x49, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x33, 0x44, 0x07, 0xEB, ++0xC3, 0x07, 0x32, 0x46, 0x97, 0xF8, 0xA5, 0x71, 0x4F, 0xF4, 0x00, 0x60, 0x3B, 0x46, 0xF4, 0xF7, 0x63, 0xFA, 0x21, 0x2F, ++0x3F, 0xF4, 0x7A, 0xAF, 0x4F, 0xEA, 0x07, 0x28, 0x48, 0xF0, 0x08, 0x08, 0x40, 0x46, 0xF2, 0xF7, 0x43, 0xFE, 0x02, 0x28, ++0x7F, 0xF4, 0x70, 0xAF, 0x41, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0xF2, 0xF7, 0xA7, 0xFA, 0x6A, 0x4A, 0x99, 0xF8, 0x02, 0x10, ++0x07, 0xEB, 0x47, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x58, 0x7C, 0x88, 0x42, 0x03, 0xD1, 0x1B, 0x7C, 0xB3, 0x42, 0x00, 0xF0, ++0x9B, 0x80, 0x38, 0x46, 0x00, 0xF0, 0xF4, 0xF9, 0x40, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0x7E, 0xFD, 0x54, 0xE7, 0x60, 0x49, ++0x4F, 0xF4, 0x00, 0x60, 0x52, 0x46, 0xF4, 0xF7, 0x35, 0xFA, 0x51, 0x46, 0x30, 0x46, 0xE8, 0xF7, 0x85, 0xF9, 0x00, 0x28, ++0x4F, 0xD1, 0x95, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0x68, 0xAF, 0x00, 0xF0, 0x04, 0xFA, 0x21, 0x28, 0x04, 0x46, ++0x3F, 0xF4, 0x62, 0xAF, 0x53, 0x4D, 0x55, 0x4A, 0x00, 0xEB, 0x40, 0x01, 0x05, 0xEB, 0xC1, 0x03, 0xC8, 0xF3, 0x40, 0x00, ++0x12, 0x68, 0x83, 0xF8, 0x10, 0xA0, 0x00, 0x27, 0x1E, 0x73, 0x83, 0xF8, 0x11, 0xB0, 0x98, 0x73, 0x5F, 0x73, 0x90, 0x6B, ++0xB9, 0xF8, 0x05, 0x20, 0x5A, 0x81, 0x4F, 0xEA, 0x98, 0x18, 0x80, 0x45, 0x28, 0xBF, 0x80, 0x46, 0x83, 0xF8, 0x0F, 0x80, ++0xB9, 0xF8, 0x07, 0x00, 0xC9, 0x00, 0x00, 0x09, 0x92, 0xB2, 0x6F, 0x50, 0x18, 0x81, 0x1A, 0xB9, 0x44, 0x4A, 0x12, 0x68, ++0x52, 0x88, 0x5A, 0x81, 0x30, 0x46, 0x21, 0x46, 0x00, 0xF0, 0x3C, 0xFA, 0x20, 0x02, 0x00, 0xF4, 0x7F, 0x40, 0x40, 0xF0, ++0x08, 0x00, 0x03, 0x21, 0xF2, 0xF7, 0x32, 0xFD, 0x08, 0xE7, 0x3D, 0x49, 0x4F, 0xF4, 0x00, 0x60, 0xF4, 0xF7, 0xEA, 0xF9, ++0xE3, 0x79, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x2B, 0x44, 0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA5, 0x51, ++0x44, 0xE7, 0x06, 0xEB, 0x86, 0x03, 0xC6, 0xEB, 0x03, 0x13, 0x53, 0x44, 0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA4, 0x71, ++0x3D, 0x02, 0x45, 0xF0, 0x08, 0x05, 0x28, 0x46, 0xF2, 0xF7, 0xBA, 0xFD, 0x01, 0x28, 0x7F, 0xF4, 0x0B, 0xAF, 0x2A, 0x4B, ++0x27, 0x4A, 0x1B, 0x68, 0x07, 0xEB, 0x47, 0x01, 0x02, 0xEB, 0xC1, 0x02, 0x99, 0x6B, 0xD2, 0x7B, 0x4F, 0xEA, 0x98, 0x13, ++0x8B, 0x42, 0x28, 0xBF, 0x0B, 0x46, 0x9A, 0x42, 0x12, 0xD0, 0x28, 0x46, 0x04, 0x21, 0xF2, 0xF7, 0xFB, 0xFC, 0xE0, 0x79, ++0x39, 0x46, 0x00, 0xF0, 0x1D, 0xFA, 0x25, 0x23, 0xF1, 0xE6, 0x30, 0x46, 0x04, 0x21, 0xF2, 0xF7, 0xF1, 0xFC, 0xE0, 0x79, ++0x29, 0x46, 0x00, 0xF0, 0x13, 0xFA, 0xC3, 0xE6, 0x00, 0x23, 0xE6, 0xE6, 0xB9, 0xF8, 0x03, 0x30, 0x00, 0x2B, 0x7F, 0xF4, ++0x60, 0xAF, 0x18, 0x23, 0x03, 0xFB, 0x07, 0x23, 0xA9, 0x09, 0xDB, 0x7B, 0xB3, 0xEB, 0x95, 0x1F, 0x03, 0xD9, 0x18, 0x23, ++0x03, 0xFB, 0x07, 0x23, 0xD9, 0x73, 0x18, 0x23, 0x03, 0xFB, 0x07, 0x22, 0x05, 0xF0, 0x01, 0x05, 0x95, 0x74, 0xE0, 0x79, ++0x39, 0x46, 0x00, 0xF0, 0xD1, 0xF9, 0x40, 0x46, 0x03, 0x21, 0xF2, 0xF7, 0xCB, 0xFC, 0xA1, 0xE6, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0xB9, 0x34, 0x17, 0x00, 0xE4, 0xC1, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC0, 0xC1, 0x15, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0xA4, 0xC1, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x08, 0xC2, 0x15, 0x00, ++0x10, 0xB5, 0x10, 0x46, 0x14, 0x46, 0xF2, 0xF7, 0x57, 0xFD, 0x02, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x20, 0x0A, ++0x00, 0xF0, 0x1A, 0xF9, 0x20, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0xA4, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x10, 0x46, ++0x84, 0xB0, 0x14, 0x46, 0xF2, 0xF7, 0x44, 0xFD, 0x01, 0x28, 0x02, 0xD0, 0x00, 0x20, 0x04, 0xB0, 0x70, 0xBD, 0x20, 0x0A, ++0x13, 0x4A, 0x00, 0xEB, 0x40, 0x05, 0x52, 0xF8, 0x35, 0x60, 0x02, 0xEB, 0xC5, 0x05, 0x3E, 0xB9, 0x10, 0x4B, 0x6A, 0x68, ++0x19, 0x69, 0x6B, 0x89, 0x52, 0x1A, 0x12, 0xEB, 0x83, 0x23, 0x04, 0xD4, 0x00, 0xF0, 0x74, 0xF9, 0x00, 0x20, 0x04, 0xB0, ++0x70, 0xBD, 0x20, 0x46, 0x04, 0x21, 0x2C, 0x7B, 0xF2, 0xF7, 0x7C, 0xFC, 0x08, 0x4B, 0x02, 0x93, 0x27, 0x22, 0x01, 0x92, ++0x00, 0x96, 0x20, 0x46, 0x33, 0x46, 0x29, 0x46, 0x02, 0x22, 0xEE, 0x74, 0x00, 0xF0, 0xF8, 0xF9, 0xD4, 0xE7, 0x00, 0xBF, ++0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0xE5, 0xFE, 0x14, 0x00, 0x90, 0xF8, 0x46, 0x30, 0x90, 0xF8, 0x47, 0x20, ++0x19, 0x44, 0xB1, 0xFB, 0xF2, 0xF0, 0x02, 0xFB, 0x10, 0x10, 0x70, 0x47, 0x90, 0xF8, 0x46, 0x30, 0x90, 0xF8, 0x48, 0x00, ++0x19, 0x44, 0x08, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x03, 0x4B, 0x1B, 0x69, 0xA0, 0xEB, 0x93, 0x20, 0xC0, 0xF3, 0xC0, 0x30, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x70, 0xB5, 0x90, 0xF8, 0x46, 0x30, 0x03, 0x44, 0x9A, 0x79, 0x02, 0x2A, ++0x17, 0xD1, 0x00, 0x26, 0x04, 0x46, 0x35, 0x46, 0x9D, 0x71, 0xA3, 0x88, 0x22, 0x68, 0x01, 0x33, 0xC3, 0xF3, 0x0B, 0x03, ++0xA3, 0x80, 0x01, 0x21, 0x20, 0x46, 0x90, 0x47, 0x54, 0xFA, 0x80, 0xF3, 0x84, 0xF8, 0x46, 0x00, 0x9A, 0x79, 0x01, 0x36, ++0x02, 0x2A, 0x76, 0xB2, 0xEC, 0xD0, 0x30, 0x46, 0x70, 0xBD, 0x00, 0x26, 0x30, 0x46, 0x70, 0xBD, 0x38, 0xB5, 0x85, 0x88, ++0x03, 0x68, 0x49, 0x1B, 0xC1, 0xF3, 0x0B, 0x01, 0x04, 0x46, 0x15, 0x46, 0x98, 0x47, 0x20, 0x44, 0x85, 0x71, 0x38, 0xBD, ++0xF8, 0xB5, 0x05, 0x46, 0x33, 0x48, 0x6F, 0x6A, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0xC1, 0x00, 0xBF, 0x02, 0x44, 0x69, ++0x03, 0xD5, 0x11, 0x46, 0x4B, 0xB3, 0x00, 0x2A, 0x49, 0xD0, 0xA2, 0x88, 0x29, 0x8C, 0x23, 0x68, 0x89, 0x1A, 0xC1, 0xF3, ++0x0B, 0x01, 0x20, 0x46, 0x98, 0x47, 0x20, 0x44, 0x02, 0x23, 0x83, 0x71, 0x94, 0xF8, 0x46, 0x30, 0x23, 0x44, 0x00, 0x26, ++0x9A, 0x79, 0x02, 0x2A, 0x13, 0xD1, 0x35, 0x46, 0x9D, 0x71, 0xA3, 0x88, 0x22, 0x68, 0x01, 0x33, 0xC3, 0xF3, 0x0B, 0x03, ++0xA3, 0x80, 0x01, 0x21, 0x20, 0x46, 0x90, 0x47, 0x54, 0xFA, 0x80, 0xF3, 0x84, 0xF8, 0x46, 0x00, 0x9A, 0x79, 0x01, 0x36, ++0x02, 0x2A, 0x76, 0xB2, 0xEC, 0xD0, 0x30, 0x46, 0xF8, 0xBD, 0x00, 0x2A, 0xD5, 0xD1, 0x19, 0x4B, 0xB5, 0xF8, 0x40, 0x00, ++0x1B, 0x69, 0xA0, 0xEB, 0x93, 0x23, 0x1B, 0x04, 0xCD, 0xD4, 0xEA, 0x8B, 0xEB, 0x6C, 0x6F, 0xEA, 0x42, 0x42, 0x1C, 0x69, ++0x6F, 0xEA, 0x52, 0x42, 0xEA, 0x83, 0x44, 0xF0, 0x02, 0x04, 0x6A, 0x8F, 0x0E, 0x46, 0x29, 0x8F, 0x19, 0x80, 0x1C, 0x61, ++0xE9, 0x8F, 0xAC, 0x8F, 0x5A, 0x80, 0x2A, 0x8C, 0x1A, 0x81, 0x9C, 0x80, 0xD9, 0x80, 0x58, 0x81, 0xDB, 0xE7, 0x09, 0x48, ++0xB5, 0xF8, 0x40, 0x20, 0x03, 0x69, 0xA2, 0xEB, 0x93, 0x23, 0x1E, 0x04, 0xAD, 0xD4, 0x03, 0x69, 0x05, 0x48, 0xA2, 0xEB, ++0x93, 0x22, 0xC2, 0xF3, 0xC0, 0x32, 0xF4, 0xF7, 0x23, 0xF8, 0xA4, 0xE7, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x34, 0xC2, 0x15, 0x00, 0xF8, 0xB5, 0x0D, 0x4D, 0x0D, 0x4E, 0xFF, 0x27, 0x2F, 0x73, 0x00, 0x24, 0x08, 0xE0, 0x0F, 0x2C, ++0x85, 0xF8, 0x24, 0x70, 0x03, 0xDD, 0x4C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0xEB, 0x62, 0x18, 0x35, 0x20, 0x02, 0x00, 0xF4, ++0x7F, 0x40, 0x40, 0xF0, 0x08, 0x00, 0x01, 0x34, 0x00, 0x21, 0xF2, 0xF7, 0x95, 0xFB, 0x20, 0x2C, 0xEB, 0xD1, 0xF8, 0xBD, ++0xF4, 0xE4, 0x17, 0x00, 0x74, 0xDB, 0x17, 0x00, 0x11, 0x4B, 0x00, 0xEB, 0x40, 0x00, 0x03, 0xEB, 0xC0, 0x00, 0x42, 0x7B, ++0x03, 0x7B, 0x01, 0x7C, 0x72, 0xB1, 0x01, 0x2A, 0x0B, 0xD1, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x0B, 0x4A, ++0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA5, 0x21, 0x70, 0x47, 0x70, 0x47, 0x03, 0xEB, 0x83, 0x02, ++0xC3, 0xEB, 0x02, 0x13, 0x04, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA4, 0x21, 0x70, 0x47, ++0xF4, 0xE4, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x00, 0x28, 0x09, 0x4B, 0x14, 0xBF, 0x10, 0x20, 0x00, 0x20, 0x03, 0xEB, ++0x40, 0x03, 0x14, 0xBF, 0x20, 0x21, 0x10, 0x21, 0x33, 0xF8, 0x02, 0x2F, 0x22, 0xB1, 0x01, 0x30, 0x88, 0x42, 0xF9, 0xDB, ++0x21, 0x20, 0x70, 0x47, 0x80, 0xB2, 0x70, 0x47, 0xF2, 0xDF, 0x17, 0x00, 0x38, 0xB5, 0x05, 0x02, 0x45, 0xF0, 0x08, 0x05, ++0x04, 0x46, 0x29, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0xF2, 0xF7, 0x5A, 0xF8, 0x29, 0x46, 0x42, 0xF2, 0x01, 0x00, 0xF2, 0xF7, ++0x55, 0xF8, 0x16, 0x48, 0x04, 0xEB, 0x44, 0x04, 0x00, 0xEB, 0xC4, 0x04, 0x62, 0x7B, 0x23, 0x7B, 0x21, 0x7C, 0x92, 0xB1, ++0x01, 0x2A, 0x0A, 0xD1, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x0F, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, ++0x21, 0x22, 0x83, 0xF8, 0xA5, 0x21, 0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x38, 0x40, 0xF2, 0xF7, 0x25, 0xBB, 0x03, 0xEB, ++0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x07, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA4, 0x21, ++0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x38, 0x40, 0xF2, 0xF7, 0x14, 0xBB, 0xF4, 0xE4, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x07, 0x4B, 0x00, 0xEB, 0x40, 0x02, 0x03, 0xEB, 0xC2, 0x03, 0x00, 0x02, 0x5A, 0x89, 0x00, 0xF4, 0x7F, 0x41, 0x41, 0xF0, ++0x08, 0x01, 0x92, 0x02, 0x42, 0xF2, 0x01, 0x00, 0xF1, 0xF7, 0x64, 0xBF, 0xF4, 0xE4, 0x17, 0x00, 0x0A, 0x02, 0x02, 0xF4, ++0x7F, 0x42, 0x38, 0xB5, 0x42, 0xF0, 0x08, 0x02, 0x05, 0x46, 0x0C, 0x46, 0x06, 0x23, 0x00, 0x21, 0x28, 0x20, 0xF2, 0xF7, ++0xF7, 0xF8, 0x0A, 0x49, 0x04, 0xEB, 0x44, 0x04, 0x01, 0xEB, 0xC4, 0x04, 0x62, 0x7B, 0x45, 0x70, 0x01, 0x3A, 0x18, 0xBF, ++0x01, 0x22, 0x02, 0x70, 0x22, 0x7C, 0x82, 0x70, 0xE2, 0x7B, 0xC2, 0x70, 0x22, 0x89, 0x82, 0x80, 0xBD, 0xE8, 0x38, 0x40, ++0xF2, 0xF7, 0x12, 0xB9, 0xF4, 0xE4, 0x17, 0x00, 0xF8, 0xB5, 0x0D, 0x02, 0x45, 0xF0, 0x08, 0x05, 0xAD, 0xB2, 0x03, 0x23, ++0x0C, 0x46, 0x07, 0x46, 0x2A, 0x46, 0x00, 0x21, 0x2A, 0x20, 0xF2, 0xF7, 0xD3, 0xF8, 0x12, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x06, 0x46, 0x11, 0xDB, 0x0F, 0x49, 0x04, 0xEB, 0x44, 0x04, 0x01, 0xEB, 0xC4, 0x04, 0x30, 0x46, ++0x63, 0x7B, 0x77, 0x70, 0x01, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0x33, 0x70, 0x23, 0x7C, 0xB3, 0x70, 0xBD, 0xE8, 0xF8, 0x40, ++0xF2, 0xF7, 0xEA, 0xB8, 0x28, 0x46, 0xF2, 0xF7, 0x59, 0xFB, 0x04, 0x28, 0xE8, 0xD0, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, ++0x05, 0x22, 0xF4, 0xF7, 0x91, 0xF9, 0xE1, 0xE7, 0x38, 0x36, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x60, 0xC2, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x10, 0x4E, 0x11, 0x4D, 0x80, 0x46, 0x87, 0xB2, 0x00, 0x24, 0x36, 0xF8, ++0x02, 0x3F, 0x8B, 0xB1, 0x2B, 0x7B, 0x43, 0x45, 0x0E, 0xD1, 0x1F, 0xFA, 0x84, 0xF9, 0x4F, 0xEA, 0x09, 0x23, 0x03, 0xF4, ++0x7F, 0x43, 0x43, 0xF0, 0x08, 0x00, 0x04, 0x21, 0xF2, 0xF7, 0x88, 0xFA, 0x49, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xAA, 0xFF, ++0x01, 0x34, 0x20, 0x2C, 0x05, 0xF1, 0x18, 0x05, 0xE5, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0xF2, 0xDF, 0x17, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0xB0, 0xDF, 0xF8, 0x50, 0x92, 0xBD, 0xF8, 0x50, 0x40, 0x09, 0x94, ++0xBD, 0xF8, 0x54, 0x40, 0x07, 0x94, 0x16, 0x9C, 0x04, 0x94, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x94, 0x87, 0x4F, ++0x94, 0xF8, 0x22, 0x80, 0xDF, 0xF8, 0x30, 0xA2, 0x03, 0x91, 0x06, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x08, 0x70, ++0x93, 0x46, 0x00, 0x6C, 0x08, 0x93, 0x00, 0x28, 0x00, 0xF0, 0xC4, 0x80, 0xDA, 0xF8, 0x00, 0x30, 0x02, 0x79, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9B, 0x80, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x73, 0x4F, 0xF4, 0xC0, 0x71, ++0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xDF, 0xF7, 0x14, 0xFB, 0x04, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0x9B, 0x80, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x08, 0xF5, 0x78, 0x19, 0x21, 0x46, 0x05, 0x90, 0xF1, 0xF7, ++0x05, 0xFC, 0x4F, 0xF4, 0x1E, 0x72, 0xA3, 0x6C, 0x02, 0xFB, 0x06, 0xF2, 0x00, 0x21, 0x26, 0x32, 0x6F, 0xF0, 0x2F, 0x0C, ++0x83, 0xF8, 0x68, 0xC0, 0x83, 0xF8, 0x69, 0x10, 0x83, 0xF8, 0x6A, 0x10, 0x83, 0xF8, 0x6B, 0x10, 0x39, 0xF8, 0x02, 0x10, ++0xA3, 0xF8, 0x6C, 0x10, 0x09, 0xEB, 0x02, 0x01, 0x5C, 0x35, 0xB1, 0xF8, 0x02, 0xC0, 0xA3, 0xF8, 0x6E, 0xC0, 0xB1, 0xF8, ++0x04, 0xC0, 0xA3, 0xF8, 0x70, 0xC0, 0x37, 0xF8, 0x05, 0xC0, 0xA3, 0xF8, 0x72, 0xC0, 0x07, 0xEB, 0x05, 0x0C, 0x03, 0xF1, ++0x68, 0x00, 0xBC, 0xF8, 0x02, 0xE0, 0xA3, 0xF8, 0x74, 0xE0, 0xBC, 0xF8, 0x04, 0xE0, 0x06, 0x90, 0x05, 0x98, 0xA3, 0xF8, ++0x76, 0xE0, 0x90, 0xF8, 0x62, 0x00, 0x02, 0x28, 0x5E, 0xD0, 0x39, 0xF8, 0x02, 0x20, 0xA3, 0xF8, 0x78, 0x20, 0x4A, 0x88, ++0xA3, 0xF8, 0x7A, 0x20, 0x8A, 0x88, 0xA3, 0xF8, 0x7C, 0x20, 0x4E, 0x49, 0xB1, 0xF8, 0xFC, 0x21, 0x01, 0x32, 0x92, 0xB2, ++0xA1, 0xF8, 0xFC, 0x21, 0x10, 0x01, 0x00, 0x21, 0xA3, 0xF8, 0x7E, 0x00, 0x03, 0x22, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, ++0x35, 0x10, 0x84, 0xF8, 0x1C, 0x80, 0x66, 0x77, 0xD0, 0x21, 0x20, 0x46, 0x00, 0xF0, 0xE6, 0xFB, 0x01, 0x28, 0x70, 0xD0, ++0x18, 0x25, 0xBB, 0xF1, 0x01, 0x0F, 0x4A, 0xD0, 0xBB, 0xF1, 0x02, 0x0F, 0x54, 0xD0, 0xBB, 0xF1, 0x00, 0x0F, 0x5C, 0xD0, ++0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x69, 0xDB, 0x03, 0x26, 0xE1, 0x6C, 0x94, 0xF8, 0x35, 0x30, ++0x4A, 0x6A, 0x1D, 0x44, 0x01, 0x3A, 0x04, 0x9B, 0x2A, 0x44, 0x04, 0x35, 0xC1, 0xE9, 0x0A, 0x25, 0x13, 0xB1, 0x63, 0x65, ++0x03, 0x9B, 0xA3, 0x65, 0x31, 0x46, 0x20, 0x46, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xDF, 0xF7, 0x97, 0xBA, 0x02, 0x2A, ++0x7F, 0xF4, 0x62, 0xAF, 0x2D, 0x49, 0x2E, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0xF4, 0xF7, 0x92, 0xF8, 0x01, 0x20, 0x4F, 0xF4, ++0xC0, 0x71, 0xDF, 0xF7, 0x79, 0xFA, 0x04, 0x46, 0x00, 0x28, 0x7F, 0xF4, 0x65, 0xAF, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x7A, 0x5B, 0xA3, 0xF8, 0x78, 0x20, 0xBC, 0xF8, 0x02, 0x20, 0xA3, 0xF8, 0x7A, 0x20, 0xBC, 0xF8, 0x04, 0x20, 0xA3, 0xF8, ++0x7C, 0x20, 0x9E, 0xE7, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE1, 0xDA, 0xDA, 0xE7, 0x06, 0x99, ++0x07, 0x9B, 0x00, 0x93, 0x29, 0x44, 0x08, 0x46, 0xDD, 0xE9, 0x08, 0x32, 0x03, 0x99, 0xF5, 0xF7, 0x4D, 0xFA, 0x03, 0x26, ++0x05, 0x44, 0xB4, 0xE7, 0xDD, 0xE9, 0x06, 0x02, 0x03, 0x99, 0x15, 0x4E, 0x0B, 0x7C, 0x28, 0x44, 0xF6, 0x5C, 0xF5, 0xF7, ++0x5D, 0xFA, 0x05, 0x44, 0xA9, 0xE7, 0x03, 0x99, 0x06, 0x98, 0x10, 0x4A, 0x0B, 0x7C, 0x28, 0x44, 0xD6, 0x5C, 0xF5, 0xF7, ++0x1B, 0xFA, 0x05, 0x44, 0x9F, 0xE7, 0x06, 0x99, 0x18, 0x22, 0x20, 0x46, 0xFF, 0xF7, 0xD2, 0xF9, 0x94, 0xF8, 0x33, 0x50, ++0x18, 0x35, 0x86, 0xE7, 0x05, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x6E, 0x22, 0xF4, 0xF7, 0x5A, 0xF8, 0x03, 0x26, 0x8E, 0xE7, ++0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0xC0, 0xB2, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x35, 0x4B, 0x87, 0xB0, ++0x81, 0x46, 0x8A, 0x46, 0x93, 0x46, 0x10, 0x24, 0x33, 0xF8, 0x02, 0x5F, 0x35, 0xB1, 0x01, 0x34, 0x20, 0x2C, 0xF9, 0xD1, ++0x03, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2E, 0x4A, 0xDF, 0xF8, 0xCC, 0x80, 0x04, 0xEB, 0x44, 0x03, 0x02, 0xEB, ++0xC3, 0x06, 0xDB, 0x00, 0x86, 0xF8, 0x0C, 0x90, 0x86, 0xF8, 0x10, 0xA0, 0x05, 0x93, 0x06, 0xF0, 0xBB, 0xFB, 0x28, 0x49, ++0x70, 0x74, 0x09, 0x68, 0x27, 0x48, 0xB1, 0xF8, 0x02, 0xC0, 0x10, 0xF8, 0x0A, 0x00, 0x05, 0x9B, 0x25, 0x49, 0x22, 0x4A, ++0x02, 0x95, 0x09, 0xEB, 0x89, 0x07, 0xC9, 0xEB, 0x07, 0x17, 0x57, 0x44, 0x00, 0x95, 0x34, 0x37, 0x51, 0xF8, 0x20, 0xE0, ++0xD5, 0x50, 0x08, 0xEB, 0xC7, 0x00, 0x27, 0x23, 0x01, 0x93, 0xA6, 0xF8, 0x0A, 0xC0, 0x4F, 0xF0, 0x01, 0x0C, 0x86, 0xF8, ++0x0F, 0xE0, 0x86, 0xF8, 0x0E, 0xC0, 0x86, 0xF8, 0x0D, 0xC0, 0x31, 0x46, 0x2B, 0x46, 0x44, 0x71, 0xA6, 0xF8, 0x08, 0xB0, ++0x48, 0x46, 0x02, 0x22, 0xFF, 0xF7, 0x82, 0xFE, 0x24, 0x02, 0x31, 0x46, 0x48, 0x46, 0x2B, 0x46, 0x2A, 0x46, 0xCD, 0xE9, ++0x01, 0x55, 0x00, 0x95, 0xFF, 0xF7, 0x78, 0xFE, 0x44, 0xF0, 0x08, 0x04, 0x0E, 0x4B, 0xA4, 0xB2, 0x1B, 0x69, 0x48, 0xF8, ++0x37, 0x30, 0x21, 0x46, 0x4F, 0xF4, 0xFA, 0x22, 0x4F, 0xF4, 0x00, 0x50, 0xF1, 0xF7, 0x46, 0xFD, 0x20, 0x46, 0x02, 0x21, ++0xF2, 0xF7, 0xDE, 0xF8, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0xE0, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, ++0xC8, 0x35, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0x7C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x19, 0x4C, 0x1A, 0x4D, 0xDF, 0xF8, 0x68, 0xA0, 0xC4, 0xEB, 0x44, 0x29, 0x4F, 0xEA, 0xC9, 0x19, ++0x84, 0xB0, 0x07, 0x46, 0x1F, 0xFA, 0x89, 0xF9, 0x04, 0xF1, 0x40, 0x06, 0x4F, 0xF0, 0x00, 0x08, 0x34, 0xF8, 0x02, 0x3F, ++0xCB, 0xB1, 0x2B, 0x7B, 0xBB, 0x42, 0x16, 0xD1, 0x09, 0xEB, 0xC4, 0x10, 0xA0, 0xF5, 0x80, 0x70, 0x40, 0xF0, 0x08, 0x00, ++0x80, 0xB2, 0x04, 0x21, 0xF2, 0xF7, 0xAA, 0xF8, 0x27, 0x23, 0xCD, 0xE9, 0x00, 0x83, 0xCD, 0xF8, 0x08, 0xA0, 0x00, 0x23, ++0x02, 0x22, 0x29, 0x46, 0x38, 0x46, 0x85, 0xF8, 0x13, 0x80, 0xFF, 0xF7, 0x25, 0xFE, 0xB4, 0x42, 0x05, 0xF1, 0x18, 0x05, ++0xDE, 0xD1, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xF2, 0xDF, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0xE5, 0xFE, 0x14, 0x00, ++0xFF, 0x29, 0x2F, 0xD0, 0xF8, 0xB5, 0xC3, 0xB2, 0x03, 0xEB, 0x83, 0x02, 0x16, 0x4F, 0xC3, 0xEB, 0x02, 0x13, 0x53, 0xFA, ++0x81, 0xF3, 0x07, 0xEB, 0xC3, 0x03, 0x0C, 0x46, 0x93, 0xF8, 0xA5, 0x61, 0x21, 0x2E, 0x05, 0x46, 0x1C, 0xD0, 0x30, 0x02, ++0x40, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0x20, 0xF9, 0x01, 0x28, 0x15, 0xD1, 0x0D, 0x4B, 0x06, 0xEB, 0x46, 0x06, 0x03, 0xEB, ++0xC6, 0x06, 0x4F, 0xF4, 0x9E, 0x71, 0x01, 0xFB, 0x05, 0x44, 0x73, 0x69, 0x07, 0xEB, 0x44, 0x04, 0x9A, 0x88, 0xB4, 0xF8, ++0x34, 0x31, 0x9B, 0x1A, 0x13, 0xF4, 0x7C, 0x6F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xF8, 0xBD, 0x01, 0x20, 0xF8, 0xBD, ++0x02, 0x20, 0x70, 0x47, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x04, 0x46, 0x50, 0x48, ++0xE1, 0x7E, 0xD0, 0xF8, 0x10, 0x90, 0xFF, 0x29, 0x23, 0xD0, 0x65, 0x7F, 0x4D, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x05, 0x63, 0x5A, 0x68, 0x97, 0x07, 0x1A, 0xD5, 0x05, 0xEB, 0x85, 0x07, 0xC5, 0xEB, 0x07, 0x17, 0x7A, 0x18, 0x34, 0x32, ++0x06, 0xEB, 0xC2, 0x0C, 0x9C, 0xF8, 0x07, 0xE0, 0x9C, 0xF8, 0x05, 0x80, 0x0E, 0xF1, 0x01, 0x0E, 0xB8, 0xF1, 0x21, 0x0F, ++0x8C, 0xF8, 0x07, 0xE0, 0x09, 0xD1, 0x00, 0x69, 0x56, 0xF8, 0x32, 0x20, 0xDF, 0xF8, 0x14, 0xC1, 0x82, 0x1A, 0x62, 0x45, ++0x48, 0xD8, 0xBD, 0xE8, 0xF0, 0x87, 0xDF, 0xF8, 0x0C, 0xA1, 0x08, 0xEB, 0x48, 0x07, 0x0A, 0xEB, 0xC7, 0x07, 0x4F, 0xEA, ++0x08, 0x20, 0xC7, 0xF8, 0x04, 0x90, 0x40, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0xC3, 0xF8, 0x01, 0x28, 0x4F, 0xEA, 0x48, 0x09, ++0xEB, 0xD1, 0x7F, 0x69, 0xE3, 0x8B, 0xB8, 0x88, 0x60, 0x84, 0xD9, 0x07, 0x57, 0xD4, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, ++0x05, 0x65, 0xD5, 0xF8, 0x4C, 0x21, 0x92, 0xF8, 0xA2, 0x20, 0x52, 0x07, 0x03, 0xD5, 0x62, 0x6A, 0x42, 0xF4, 0x00, 0x12, ++0x62, 0x62, 0x21, 0x8C, 0x3A, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x09, 0x1A, 0xE3, 0x83, 0xC1, 0xF3, 0x0B, 0x01, 0x38, 0x46, ++0x90, 0x47, 0x38, 0x44, 0x01, 0x23, 0x83, 0x71, 0xE3, 0x8B, 0xDB, 0x07, 0x07, 0xD4, 0x1F, 0x4A, 0x20, 0x4B, 0x12, 0x69, ++0x9B, 0x8D, 0x03, 0xEB, 0x92, 0x23, 0xA4, 0xF8, 0x40, 0x30, 0xC8, 0x44, 0x4F, 0xEA, 0xC8, 0x08, 0x5A, 0xF8, 0x08, 0x30, ++0x01, 0x33, 0x4A, 0xF8, 0x08, 0x30, 0xB6, 0xE7, 0x93, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0xB2, 0xD0, 0x17, 0x4B, 0x18, 0x48, ++0x5A, 0x5C, 0x54, 0x23, 0x03, 0xFB, 0x02, 0xF3, 0xC3, 0x58, 0x00, 0x2B, 0xA9, 0xD1, 0x15, 0x4B, 0x53, 0xF8, 0x32, 0x30, ++0x00, 0x2B, 0xA4, 0xD1, 0xBB, 0x18, 0x46, 0x33, 0x56, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x9E, 0xD1, 0x23, 0x7F, 0x10, 0x48, ++0xA4, 0x26, 0x06, 0xFB, 0x03, 0x23, 0x9E, 0x33, 0x50, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x94, 0xD1, 0x0C, 0x4B, 0x22, 0x8C, ++0x1B, 0x6A, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x03, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0x89, 0xD1, 0xA2, 0xE7, ++0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x24, 0x64, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x40, 0x42, 0x0F, 0x00, 0xF4, 0xE4, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x1C, 0x48, 0x6C, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x03, 0x5E, 0x68, ++0xB6, 0x07, 0x0E, 0xD5, 0xEB, 0x7E, 0x04, 0xEB, 0x84, 0x06, 0xC4, 0xEB, 0x06, 0x14, 0x1C, 0x44, 0x34, 0x34, 0x00, 0xEB, ++0xC4, 0x04, 0xE3, 0x79, 0x01, 0x3B, 0xE3, 0x71, 0xEB, 0x8B, 0x9B, 0x07, 0x02, 0xD4, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, ++0x66, 0x79, 0x21, 0x2E, 0xF9, 0xD0, 0x30, 0x02, 0x40, 0xF0, 0x08, 0x00, 0x88, 0x46, 0x91, 0x46, 0xF2, 0xF7, 0x20, 0xF8, ++0x01, 0x28, 0xF0, 0xD1, 0x06, 0xEB, 0x46, 0x07, 0xFF, 0x00, 0xDF, 0xF8, 0x20, 0xC0, 0x5C, 0xF8, 0x07, 0x40, 0x01, 0x3C, ++0x4C, 0xF8, 0x07, 0x40, 0x4B, 0x46, 0x42, 0x46, 0x28, 0x46, 0x31, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x46, 0xBB, ++0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x38, 0xB5, 0x45, 0x69, 0x04, 0x46, 0x40, 0x22, 0x00, 0x21, 0xA8, 0x1D, ++0xCF, 0xF7, 0x58, 0xF9, 0x22, 0x7B, 0x21, 0x7C, 0x0C, 0x4B, 0x4F, 0xF4, 0x9E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x03, 0xEB, ++0x42, 0x03, 0x00, 0x22, 0xB3, 0xF8, 0x34, 0x31, 0xAB, 0x80, 0x85, 0xF8, 0x46, 0x20, 0xE3, 0x7B, 0x85, 0xF8, 0x47, 0x30, ++0x5A, 0x1E, 0x1A, 0x42, 0x12, 0xBF, 0x04, 0x4B, 0x04, 0x4B, 0x85, 0xF8, 0x48, 0x20, 0x2B, 0x60, 0x38, 0xBD, 0x00, 0xBF, ++0x68, 0x65, 0x17, 0x00, 0xDD, 0x04, 0x15, 0x00, 0xF1, 0x04, 0x15, 0x00, 0x90, 0xF8, 0x47, 0x10, 0x59, 0xB1, 0x43, 0x1D, ++0x19, 0x44, 0x00, 0x20, 0x13, 0xF8, 0x01, 0x2F, 0x02, 0x2A, 0x04, 0xBF, 0x01, 0x30, 0x40, 0xB2, 0x8B, 0x42, 0xF7, 0xD1, ++0x70, 0x47, 0x08, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x11, 0x4A, 0x12, 0x4B, 0x12, 0x68, 0x10, 0xB5, 0x00, 0xEB, 0x80, 0x04, ++0xC0, 0xEB, 0x04, 0x10, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x90, 0xF8, 0xA4, 0x41, 0x00, 0x2B, ++0x08, 0xDB, 0x0B, 0x4B, 0x0B, 0x4A, 0x04, 0xEB, 0x44, 0x04, 0x03, 0xEB, 0xC4, 0x04, 0x13, 0x69, 0x63, 0x60, 0x10, 0xBD, ++0x20, 0x2C, 0xF4, 0xD9, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x52, 0x32, 0xF3, 0xF7, 0xEA, 0xFD, 0xED, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x9C, 0xC2, 0x15, 0x00, 0x10, 0xF0, 0x0C, 0x0F, 0x11, 0xD1, 0x00, 0xF0, 0xF0, 0x03, 0xC0, 0x2B, 0x0B, 0xD0, 0xD0, 0x2B, ++0x05, 0xD0, 0xA3, 0xF1, 0xA0, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x0F, 0x29, 0x24, 0xD8, 0x03, 0x29, ++0x03, 0xD8, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x04, 0x39, 0x0B, 0x29, 0xF8, 0xD8, 0x01, 0xA3, 0x53, 0xF8, ++0x21, 0xF0, 0x00, 0xBF, 0xEF, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, ++0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, ++0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, 0xB1, 0xF1, 0x7F, 0x00, 0x18, 0xBF, 0x01, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x08, 0xB0, 0xB0, 0xF8, 0x00, 0x90, 0x1B, 0xF8, 0x01, 0xA0, ++0x0C, 0x46, 0x85, 0xB0, 0x80, 0x46, 0x51, 0x46, 0x48, 0x46, 0x1D, 0x46, 0xFF, 0xF7, 0xB4, 0xFF, 0x0B, 0xEB, 0x04, 0x0C, ++0x00, 0x28, 0x00, 0xF0, 0x81, 0x80, 0x98, 0xF8, 0x09, 0x30, 0xFF, 0x2B, 0x24, 0xD0, 0x98, 0xF8, 0x0A, 0x70, 0xFF, 0x2F, ++0x20, 0xD0, 0x50, 0x49, 0x16, 0x46, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x12, 0xD2, 0xF8, 0xA8, 0x24, 0x00, 0x2A, ++0x6E, 0xD0, 0x98, 0xF8, 0x30, 0x20, 0x12, 0x07, 0x6E, 0xD5, 0x09, 0xF0, 0xFC, 0x03, 0xD0, 0x2B, 0x00, 0xF0, 0x84, 0x80, ++0x46, 0x4B, 0x4F, 0xF4, 0xA4, 0x68, 0x08, 0xFB, 0x07, 0xF8, 0x43, 0x44, 0xD3, 0xF8, 0xAC, 0x34, 0x00, 0x2B, 0x5B, 0xD0, ++0x0B, 0xF1, 0x13, 0x03, 0xB3, 0x42, 0x05, 0xDB, 0x00, 0x23, 0x01, 0x20, 0x2B, 0x70, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0xB1, 0x1E, 0xA1, 0xEB, 0x0B, 0x01, 0x0C, 0xF1, 0x02, 0x00, 0x89, 0xB2, 0xF2, 0xF7, 0x3A, 0xFC, 0x1F, 0xFA, 0x8B, 0xF3, ++0x00, 0x28, 0xED, 0xD0, 0xB0, 0xF8, 0x02, 0xC0, 0xAC, 0xF1, 0x04, 0x02, 0x01, 0x2A, 0xE7, 0xD8, 0x33, 0x4A, 0xCC, 0xEB, ++0x0C, 0x11, 0x08, 0xEB, 0xC1, 0x01, 0x11, 0x44, 0x4F, 0xEA, 0x0C, 0x12, 0x03, 0x92, 0x91, 0xF8, 0x3B, 0x22, 0x00, 0x2A, ++0xDA, 0xD0, 0xD1, 0xE9, 0x76, 0xAB, 0x42, 0x68, 0x4F, 0xF0, 0x00, 0x0E, 0x22, 0xF0, 0x7F, 0x48, 0xF3, 0x45, 0x08, 0xBF, ++0xC2, 0x45, 0xF1, 0x46, 0xCE, 0xD2, 0x82, 0x46, 0xDD, 0xF8, 0x0C, 0xB0, 0x5A, 0xF8, 0x0A, 0x2F, 0x00, 0x92, 0xDA, 0xF8, ++0x04, 0x20, 0x01, 0x92, 0xC1, 0xE9, 0x76, 0x89, 0x12, 0x30, 0x52, 0x46, 0x02, 0xF8, 0x01, 0xEB, 0x82, 0x42, 0xFB, 0xD1, ++0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x07, 0xF0, 0xAB, 0xEB, 0x0C, 0x0C, 0x21, 0x46, 0x00, 0xF5, 0xEC, 0x70, 0x1A, 0x4C, ++0x00, 0xEB, 0xCC, 0x00, 0x20, 0x44, 0x32, 0x46, 0x00, 0xF0, 0xD2, 0xFA, 0xDD, 0xE9, 0x00, 0x34, 0x8C, 0x42, 0x08, 0xBF, ++0x83, 0x42, 0xA7, 0xD1, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x4A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x03, 0x23, 0x5B, 0x68, 0x1B, 0x07, 0xF3, 0xD5, 0x19, 0xF4, 0x80, 0x4F, 0xF0, 0xD1, 0x09, 0xF0, 0xFC, 0x09, 0xB9, 0xF1, ++0xC0, 0x0F, 0x02, 0xD0, 0xB9, 0xF1, 0xA0, 0x0F, 0x90, 0xD1, 0xAA, 0xF1, 0x06, 0x01, 0x01, 0x29, 0x8C, 0xD8, 0x01, 0x20, ++0x28, 0x70, 0xE2, 0xE7, 0xAA, 0xF1, 0x0D, 0x01, 0x01, 0x29, 0x3F, 0xF6, 0x77, 0xAF, 0x89, 0xF4, 0x80, 0x40, 0xC0, 0xF3, ++0x80, 0x30, 0xD8, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x45, 0x7F, 0x06, 0x7F, 0xFF, 0x2D, ++0x2B, 0xD0, 0x19, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x06, 0x73, 0xD3, 0xF8, 0xA8, 0x04, 0xE0, 0xB1, 0x0C, 0x46, ++0x20, 0x46, 0x11, 0x46, 0xFF, 0xF7, 0xF0, 0xFE, 0xB0, 0xB1, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0xF5, 0x11, 0x4B, ++0xE8, 0x5C, 0x10, 0xF0, 0x01, 0x00, 0x0E, 0xD0, 0x04, 0xF0, 0xFC, 0x04, 0xD0, 0x2C, 0x12, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x06, 0x76, 0xD6, 0xF8, 0xAC, 0x34, 0x00, 0x2B, 0x0C, 0xBF, 0x00, 0x20, 0x02, 0x20, 0xF8, 0xBD, 0x1D, 0x44, ++0x55, 0xF8, 0x22, 0x0C, 0xC0, 0xF3, 0xC0, 0x00, 0xF8, 0xBD, 0x00, 0x20, 0xF8, 0xBD, 0x0D, 0x3A, 0x01, 0x2A, 0xE9, 0xD8, ++0xF2, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x8E, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x2A, 0x4C, 0x03, 0x7F, 0x4F, 0xF4, ++0xA4, 0x60, 0x00, 0xFB, 0x03, 0x43, 0x02, 0xEB, 0x01, 0x0C, 0xD3, 0xF8, 0xAC, 0x04, 0x00, 0x28, 0x47, 0xD0, 0x4C, 0x23, ++0x53, 0x54, 0x10, 0x23, 0x8C, 0xF8, 0x01, 0x30, 0xD0, 0xE9, 0x12, 0x37, 0x01, 0x33, 0x90, 0xF8, 0x61, 0x40, 0xAC, 0xF8, ++0x02, 0x40, 0x47, 0xF1, 0x00, 0x07, 0xC0, 0xE9, 0x12, 0x37, 0x0C, 0xF1, 0x04, 0x0E, 0x00, 0x24, 0x01, 0xE0, 0xD0, 0xE9, ++0x12, 0x37, 0xC4, 0xF1, 0x20, 0x06, 0xE3, 0x40, 0xA4, 0xF1, 0x20, 0x05, 0x07, 0xFA, 0x06, 0xF6, 0x33, 0x43, 0x27, 0xFA, ++0x05, 0xF5, 0x08, 0x34, 0x2B, 0x43, 0x30, 0x2C, 0x0E, 0xF8, 0x01, 0x3B, 0xED, 0xD1, 0x0C, 0xF1, 0x0A, 0x06, 0x0C, 0xF1, ++0x12, 0x04, 0x33, 0x46, 0x00, 0x25, 0x03, 0xF8, 0x01, 0x5B, 0xA3, 0x42, 0xFB, 0xD1, 0x12, 0x32, 0x18, 0x23, 0x92, 0xB2, ++0x00, 0xF0, 0x22, 0xFA, 0x00, 0x23, 0xC3, 0xF1, 0x20, 0x05, 0x20, 0xFA, 0x03, 0xF2, 0xA3, 0xF1, 0x20, 0x04, 0x01, 0xFA, ++0x05, 0xF5, 0x2A, 0x43, 0x21, 0xFA, 0x04, 0xF4, 0x08, 0x33, 0x22, 0x43, 0x40, 0x2B, 0x06, 0xF8, 0x01, 0x2B, 0xEE, 0xD1, ++0x12, 0x20, 0xF8, 0xBD, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x0A, 0x68, 0x05, 0x68, 0x4B, 0x68, 0xAE, 0x4C, ++0xDF, 0xF8, 0xBC, 0x82, 0x8F, 0xB0, 0x0E, 0x46, 0x6A, 0x40, 0x01, 0x92, 0x32, 0x46, 0x07, 0x46, 0x0D, 0x90, 0xF0, 0x68, ++0x01, 0x9E, 0x04, 0x91, 0x89, 0x68, 0x16, 0x60, 0x7E, 0x68, 0x07, 0x97, 0x83, 0xEA, 0x06, 0x05, 0x55, 0x60, 0x13, 0x46, ++0xBA, 0x68, 0x00, 0x95, 0x81, 0xEA, 0x02, 0x09, 0xC3, 0xF8, 0x08, 0x90, 0xFB, 0x68, 0xCD, 0xF8, 0x0C, 0x90, 0x43, 0x40, ++0x02, 0x93, 0x07, 0xF1, 0x90, 0x03, 0x0C, 0x93, 0x00, 0x9E, 0x01, 0x98, 0x02, 0x99, 0x03, 0x9D, 0xF3, 0xB2, 0x5F, 0xFA, ++0x80, 0xFC, 0xC6, 0xF3, 0x07, 0x2A, 0x4F, 0xEA, 0x10, 0x69, 0xE0, 0x5C, 0x06, 0x90, 0x0A, 0x0E, 0x96, 0x48, 0x08, 0x93, ++0x14, 0xF8, 0x0A, 0x30, 0x87, 0x5C, 0x18, 0xF8, 0x02, 0x10, 0x05, 0x93, 0xC5, 0xF3, 0x07, 0x26, 0xA3, 0x5C, 0x03, 0x9A, ++0x0A, 0x97, 0xC2, 0xF3, 0x07, 0x4E, 0xA7, 0x5D, 0x10, 0xF8, 0x0E, 0x20, 0x18, 0xF8, 0x09, 0xB0, 0x14, 0xF8, 0x0C, 0x50, ++0x38, 0x46, 0x06, 0x9F, 0x09, 0x90, 0x87, 0xEA, 0x0B, 0x0B, 0x05, 0x9F, 0x80, 0xEA, 0x0B, 0x0B, 0x69, 0x40, 0x87, 0x48, ++0x79, 0x40, 0x51, 0x40, 0x10, 0xF8, 0x0A, 0x20, 0x5D, 0x40, 0x6A, 0x40, 0x18, 0xF8, 0x0E, 0x50, 0x14, 0xF8, 0x0E, 0xE0, ++0x6A, 0x40, 0x09, 0x04, 0x41, 0xEA, 0x02, 0x21, 0x7F, 0x4A, 0x02, 0x9D, 0x12, 0xF8, 0x0C, 0x20, 0x5F, 0x46, 0x18, 0xF8, ++0x0A, 0xB0, 0x14, 0xF8, 0x09, 0xA0, 0x10, 0xF8, 0x09, 0x90, 0xCD, 0xF8, 0x2C, 0x90, 0x53, 0x40, 0xC5, 0xF3, 0x07, 0x49, ++0x06, 0x98, 0x18, 0xF8, 0x0C, 0x50, 0x76, 0x4A, 0x83, 0xEA, 0x0B, 0x0B, 0x0A, 0x9B, 0x18, 0xF8, 0x06, 0xC0, 0x5D, 0x40, ++0x12, 0xF8, 0x09, 0x30, 0x92, 0x5D, 0x71, 0x4E, 0x8A, 0xEA, 0x00, 0x00, 0x50, 0x40, 0x08, 0x9A, 0xB6, 0x5C, 0x18, 0xF8, ++0x02, 0x20, 0x8A, 0xEA, 0x06, 0x0A, 0x7B, 0x40, 0x0B, 0x9E, 0x05, 0x9F, 0x8A, 0xEA, 0x0C, 0x0A, 0x18, 0xF8, 0x09, 0xC0, ++0x14, 0xF8, 0x09, 0x90, 0x8E, 0xEA, 0x05, 0x05, 0x56, 0x40, 0x7D, 0x40, 0x1B, 0x04, 0x09, 0x9F, 0x80, 0xEA, 0x0C, 0x00, ++0x8E, 0xEA, 0x0B, 0x0B, 0x43, 0xEA, 0x00, 0x20, 0x89, 0xEA, 0x06, 0x03, 0x41, 0xEA, 0x0B, 0x02, 0x02, 0x99, 0x00, 0x9E, ++0x83, 0xEA, 0x07, 0x0B, 0x03, 0x9B, 0x89, 0xEA, 0x0A, 0x0A, 0x40, 0xEA, 0x0A, 0x0C, 0x5F, 0xFA, 0x83, 0xFE, 0x4F, 0xEA, ++0x13, 0x69, 0xC1, 0xF3, 0x07, 0x20, 0xCB, 0xB2, 0x01, 0x99, 0x02, 0x93, 0x42, 0xEA, 0x05, 0x67, 0x04, 0x9A, 0x03, 0x97, ++0xC1, 0xF3, 0x07, 0x4A, 0x4C, 0xEA, 0x0B, 0x65, 0x17, 0x60, 0x27, 0x5C, 0x55, 0x60, 0x36, 0x0E, 0x05, 0x95, 0x01, 0x97, ++0x4F, 0x4D, 0x14, 0xF8, 0x0A, 0x70, 0x06, 0x97, 0x18, 0xF8, 0x0A, 0x70, 0x15, 0xF8, 0x00, 0xB0, 0xA2, 0x5D, 0x18, 0xF8, ++0x06, 0x30, 0x08, 0x97, 0xC1, 0xF3, 0x07, 0x2C, 0x14, 0xF8, 0x0E, 0x10, 0x15, 0xF8, 0x0A, 0xA0, 0x18, 0xF8, 0x00, 0x00, ++0x01, 0x9F, 0x09, 0x90, 0xA8, 0x5D, 0x0A, 0x90, 0x4B, 0x40, 0x02, 0x98, 0x00, 0x9E, 0x25, 0x5C, 0x18, 0xF8, 0x09, 0x00, ++0x7B, 0x40, 0x83, 0xEA, 0x0A, 0x03, 0x14, 0xF8, 0x0C, 0xA0, 0x51, 0x40, 0x57, 0x46, 0x68, 0x40, 0x8B, 0xEA, 0x01, 0x0B, ++0x00, 0x97, 0x3B, 0x49, 0x14, 0xF8, 0x09, 0xA0, 0x11, 0xF8, 0x09, 0x90, 0xCD, 0xF8, 0x2C, 0x90, 0x78, 0x40, 0x08, 0x9F, ++0x8B, 0xEA, 0x07, 0x01, 0x35, 0x4F, 0x08, 0x91, 0x17, 0xF8, 0x0E, 0x90, 0x09, 0x99, 0x18, 0xF8, 0x0E, 0xE0, 0xC6, 0xF3, ++0x07, 0x46, 0x82, 0xEA, 0x09, 0x02, 0x17, 0xF8, 0x06, 0xB0, 0x17, 0xF8, 0x0C, 0x90, 0x02, 0x9F, 0x18, 0xF8, 0x0C, 0xC0, ++0x4A, 0x40, 0x2C, 0x49, 0x80, 0xEA, 0x0B, 0x00, 0x11, 0xF8, 0x07, 0xB0, 0x0A, 0x99, 0x8A, 0xEA, 0x05, 0x05, 0x89, 0xEA, ++0x05, 0x05, 0x8E, 0xEA, 0x01, 0x0E, 0x18, 0xF8, 0x07, 0x90, 0x0B, 0x99, 0x89, 0xEA, 0x01, 0x09, 0x08, 0x99, 0x1B, 0x04, ++0x43, 0xEA, 0x01, 0x21, 0x06, 0x9B, 0x8A, 0xEA, 0x0B, 0x0A, 0x18, 0xF8, 0x06, 0xB0, 0xA6, 0x5D, 0x01, 0x9F, 0x83, 0xEA, ++0x0E, 0x0E, 0x85, 0xEA, 0x0B, 0x05, 0x87, 0xEA, 0x0E, 0x0E, 0x00, 0x04, 0x00, 0x9F, 0x8A, 0xEA, 0x0C, 0x0A, 0x5A, 0x40, ++0x40, 0xEA, 0x05, 0x20, 0x86, 0xEA, 0x0A, 0x0A, 0x86, 0xEA, 0x09, 0x09, 0x11, 0x43, 0x87, 0xEA, 0x09, 0x09, 0x04, 0x9A, ++0x07, 0x9E, 0x03, 0x9F, 0x05, 0x9B, 0x40, 0xEA, 0x0A, 0x00, 0x41, 0xEA, 0x0E, 0x61, 0x40, 0xEA, 0x09, 0x60, 0xC2, 0xE9, ++0x02, 0x10, 0x35, 0x69, 0x6F, 0x40, 0x17, 0x60, 0x35, 0x46, 0x76, 0x69, 0x01, 0x97, 0x5E, 0x40, 0x56, 0x60, 0x00, 0x96, ++0x2E, 0x46, 0xAD, 0x69, 0x69, 0x40, 0x91, 0x60, 0xF3, 0x69, 0x03, 0x91, 0x43, 0x40, 0x02, 0x93, 0xD3, 0x60, 0x0C, 0x9B, ++0x06, 0xF1, 0x10, 0x01, 0x8B, 0x42, 0x07, 0x91, 0x7F, 0xF4, 0xC8, 0xAE, 0x06, 0xE0, 0x00, 0xBF, 0xE4, 0xC2, 0x15, 0x00, ++0xE4, 0xC3, 0x15, 0x00, 0xE4, 0xC4, 0x15, 0x00, 0xDD, 0xF8, 0x00, 0xE0, 0x3E, 0x0E, 0x5F, 0xFA, 0x8E, 0xF2, 0xDD, 0xE9, ++0x02, 0x39, 0x14, 0xF8, 0x06, 0xC0, 0xA2, 0x5C, 0x70, 0x46, 0x42, 0xEA, 0x0C, 0x62, 0x00, 0x92, 0x1D, 0x0E, 0x02, 0x9A, ++0x65, 0x5D, 0xF9, 0xB2, 0x5F, 0xFA, 0x89, 0xF3, 0x00, 0x0E, 0x61, 0x5C, 0x20, 0x5C, 0xE3, 0x5C, 0xB8, 0x46, 0x5F, 0xFA, ++0x82, 0xFC, 0x4F, 0xEA, 0x19, 0x67, 0x43, 0xEA, 0x00, 0x63, 0xE7, 0x5D, 0x14, 0xF8, 0x0C, 0x00, 0x41, 0xEA, 0x05, 0x61, ++0xCE, 0xF3, 0x07, 0x25, 0x40, 0xEA, 0x07, 0x67, 0x65, 0x5D, 0xC9, 0xF3, 0x07, 0x20, 0x41, 0xEA, 0x05, 0x21, 0x14, 0xF8, ++0x00, 0xB0, 0xC8, 0xF3, 0x07, 0x25, 0xC2, 0xF3, 0x07, 0x20, 0xCE, 0xF3, 0x07, 0x46, 0xC9, 0xF3, 0x07, 0x4A, 0xC2, 0xF3, ++0x07, 0x4C, 0xC8, 0xF3, 0x07, 0x48, 0x65, 0x5D, 0x00, 0x9A, 0x20, 0x5C, 0x14, 0xF8, 0x0A, 0xE0, 0x14, 0xF8, 0x0C, 0xC0, ++0x14, 0xF8, 0x08, 0x80, 0xA6, 0x5D, 0x47, 0xEA, 0x05, 0x27, 0x42, 0xEA, 0x0B, 0x24, 0x43, 0xEA, 0x00, 0x20, 0x04, 0x9A, ++0x0D, 0x9D, 0x41, 0xEA, 0x0E, 0x41, 0x44, 0xEA, 0x0C, 0x44, 0x40, 0xEA, 0x08, 0x40, 0x47, 0xEA, 0x06, 0x46, 0xC2, 0xE9, ++0x00, 0x14, 0xC2, 0xE9, 0x02, 0x06, 0xD5, 0xF8, 0xA0, 0x30, 0x59, 0x40, 0x11, 0x60, 0xD5, 0xF8, 0xA4, 0x30, 0x5C, 0x40, ++0x54, 0x60, 0xD5, 0xF8, 0xA8, 0x30, 0x58, 0x40, 0x90, 0x60, 0xD5, 0xF8, 0xAC, 0x30, 0x5E, 0x40, 0xD6, 0x60, 0x0F, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xD0, 0xE9, 0x01, 0x23, 0xF0, 0xB5, 0x19, 0x49, 0x05, 0x68, 0xC7, 0x68, 0x54, 0x04, 0x04, 0xF0, ++0x80, 0x76, 0x01, 0xEA, 0xD5, 0x34, 0x34, 0x43, 0x6E, 0x00, 0x06, 0xF0, 0xFE, 0x36, 0x34, 0x43, 0x4F, 0xEA, 0x43, 0x4E, ++0x7E, 0x04, 0x0E, 0xF0, 0x80, 0x7E, 0x04, 0x60, 0x01, 0xEA, 0xD2, 0x34, 0x52, 0x00, 0x06, 0xF0, 0x80, 0x7C, 0x44, 0xEA, ++0x0E, 0x04, 0x01, 0xEA, 0xD3, 0x36, 0x02, 0xF0, 0xFE, 0x32, 0x5B, 0x00, 0x22, 0x43, 0x46, 0xEA, 0x0C, 0x06, 0x03, 0xF0, ++0xFE, 0x33, 0x7C, 0x00, 0x33, 0x43, 0x01, 0xEA, 0xD7, 0x31, 0x04, 0xF0, 0xFE, 0x34, 0x21, 0x43, 0xC0, 0xE9, 0x01, 0x23, ++0x2B, 0x06, 0x48, 0xBF, 0x81, 0xF0, 0x07, 0x41, 0xC1, 0x60, 0xF0, 0xBD, 0x01, 0x01, 0x01, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x29, 0x2A, 0xBD, 0xB0, 0x0B, 0xD8, 0x8B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x00, 0x81, ++0x00, 0x20, 0x01, 0x46, 0x3D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x88, 0x46, 0x1D, 0x46, 0x31, 0xF8, 0x04, 0x3B, 0x06, 0x46, ++0x23, 0xF4, 0x60, 0x53, 0x14, 0x46, 0x0D, 0xF1, 0x2E, 0x00, 0x12, 0x22, 0xAD, 0xF8, 0x2C, 0x30, 0x05, 0xF0, 0xC4, 0xFC, ++0xD6, 0xE9, 0x14, 0x13, 0xD6, 0xE9, 0x16, 0x72, 0xC5, 0xF5, 0x7F, 0x40, 0xF4, 0x30, 0x80, 0xB2, 0x01, 0x90, 0xCD, 0xE9, ++0x11, 0x37, 0xDF, 0xF8, 0xEC, 0xE1, 0xDF, 0xF8, 0xEC, 0xC1, 0x10, 0x91, 0x13, 0x92, 0x10, 0xAE, 0x0D, 0xF1, 0xD0, 0x0A, ++0x01, 0x20, 0x02, 0xE0, 0x5E, 0xF8, 0x04, 0x0F, 0x10, 0x36, 0xC2, 0xF3, 0x07, 0x2B, 0x5F, 0xFA, 0x82, 0xF9, 0x1C, 0xF8, ++0x0B, 0xB0, 0x1C, 0xF8, 0x09, 0x90, 0x8B, 0xEA, 0x00, 0x00, 0x4F, 0xEA, 0x12, 0x6B, 0x40, 0xEA, 0x09, 0x60, 0xC2, 0xF3, ++0x07, 0x49, 0x1C, 0xF8, 0x0B, 0xB0, 0x1C, 0xF8, 0x09, 0x90, 0x40, 0xEA, 0x0B, 0x40, 0x40, 0xEA, 0x09, 0x20, 0x41, 0x40, ++0x4B, 0x40, 0x5F, 0x40, 0x7A, 0x40, 0x56, 0x45, 0xC6, 0xE9, 0x06, 0x72, 0xC6, 0xE9, 0x04, 0x13, 0xDA, 0xD1, 0x10, 0x22, ++0x00, 0x21, 0x03, 0xA8, 0xCE, 0xF7, 0xF6, 0xFC, 0x0D, 0xF1, 0x0A, 0x06, 0x00, 0x21, 0x07, 0xA8, 0x10, 0x22, 0xCE, 0xF7, ++0xEF, 0xFC, 0x0D, 0xF1, 0x1A, 0x07, 0x33, 0x46, 0x0D, 0xF1, 0x2A, 0x01, 0x33, 0xF8, 0x02, 0x2F, 0x31, 0xF8, 0x02, 0x0F, ++0x9F, 0x42, 0x82, 0xEA, 0x00, 0x02, 0x1A, 0x80, 0xF6, 0xD1, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x7B, 0xFD, 0x03, 0x9B, ++0x0F, 0x9A, 0x6D, 0x08, 0x08, 0xEB, 0x45, 0x08, 0x53, 0x40, 0xA8, 0xF1, 0x02, 0x01, 0x08, 0xF1, 0x0A, 0x05, 0x03, 0x93, ++0x0D, 0xF1, 0x0E, 0x02, 0x32, 0xF8, 0x02, 0x3F, 0x31, 0xF8, 0x02, 0x0F, 0x43, 0x40, 0x8D, 0x42, 0x13, 0x80, 0xF7, 0xD1, ++0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x62, 0xFD, 0x01, 0x9B, 0x1C, 0x44, 0xA4, 0xB2, 0x10, 0x2C, 0x08, 0xF1, 0x0C, 0x09, ++0x26, 0xD9, 0xA4, 0xF1, 0x11, 0x0A, 0xCA, 0xF3, 0x0B, 0x1A, 0x08, 0xEB, 0x0A, 0x18, 0x08, 0xF1, 0x1C, 0x08, 0x4D, 0x46, ++0xAA, 0x1E, 0x33, 0x46, 0x05, 0xF1, 0x0E, 0x00, 0x33, 0xF8, 0x02, 0x1F, 0x32, 0xF8, 0x02, 0xCF, 0x81, 0xEA, 0x0C, 0x01, ++0x90, 0x42, 0x19, 0x80, 0xF6, 0xD1, 0x10, 0x35, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x40, 0xFD, 0x45, 0x45, 0xEB, 0xD1, ++0xCA, 0xEB, 0x0A, 0x33, 0x10, 0x3C, 0x04, 0xEB, 0x03, 0x14, 0x0A, 0xF1, 0x01, 0x0A, 0xA4, 0xB2, 0x09, 0xEB, 0x0A, 0x19, ++0x07, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x30, 0xFD, 0x07, 0xA8, 0xFF, 0xF7, 0x01, 0xFF, 0x10, 0x2C, 0x34, 0xD0, 0x65, 0x08, ++0x07, 0xA8, 0xFF, 0xF7, 0xFB, 0xFE, 0x65, 0xB1, 0xA9, 0xF1, 0x02, 0x02, 0x02, 0xEB, 0x45, 0x0C, 0x39, 0x46, 0x31, 0xF8, ++0x02, 0x3F, 0x32, 0xF8, 0x02, 0x0F, 0x43, 0x40, 0x94, 0x45, 0x0B, 0x80, 0xF7, 0xD1, 0xE3, 0x07, 0x39, 0xD4, 0x80, 0x23, ++0xA4, 0x08, 0x05, 0xF0, 0x01, 0x05, 0x3C, 0xAA, 0x05, 0xEB, 0x44, 0x04, 0x02, 0xEB, 0x44, 0x04, 0x34, 0xF8, 0xD4, 0x2C, ++0x53, 0x40, 0x24, 0xF8, 0xD4, 0x3C, 0x3A, 0x46, 0x36, 0xF8, 0x02, 0x3F, 0x32, 0xF8, 0x02, 0x1F, 0xB7, 0x42, 0x83, 0xEA, ++0x01, 0x03, 0x33, 0x80, 0xF6, 0xD1, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0xFB, 0xFC, 0xDD, 0xE9, 0x03, 0x01, 0x3D, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xA9, 0xF1, 0x02, 0x02, 0x39, 0x46, 0x09, 0xF1, 0x0E, 0x09, 0x31, 0xF8, 0x02, 0x3F, 0x32, 0xF8, ++0x02, 0x0F, 0x43, 0x40, 0x91, 0x45, 0x0B, 0x80, 0xF7, 0xD1, 0xDE, 0xE7, 0x08, 0x49, 0x09, 0x48, 0x4F, 0xF4, 0xD6, 0x72, ++0xF3, 0xF7, 0x44, 0xF9, 0x00, 0x20, 0x01, 0x46, 0x3D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x19, 0xF8, 0x15, 0x30, 0x43, 0xF4, ++0x00, 0x43, 0xC1, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xBC, 0xC2, 0x15, 0x00, ++0xE4, 0xC2, 0x15, 0x00, 0x81, 0x04, 0x4F, 0xEA, 0xD0, 0x23, 0xC0, 0xF3, 0xC2, 0x22, 0x0C, 0xD4, 0x13, 0xF0, 0x06, 0x0F, ++0x03, 0xF0, 0x06, 0x02, 0x11, 0xD1, 0x00, 0xF0, 0x7F, 0x00, 0x62, 0xB9, 0x03, 0x28, 0x8C, 0xBF, 0x00, 0x20, 0x01, 0x20, ++0x70, 0x47, 0x07, 0x2A, 0x0C, 0xD0, 0x03, 0xF0, 0x06, 0x02, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x2A, 0xF2, 0xD0, 0x00, 0x20, ++0x70, 0x47, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x2A, 0xF9, 0xD1, 0xEB, 0xE7, 0x13, 0xF0, 0x06, 0x0F, 0x0C, 0xBF, 0x01, 0x20, ++0x00, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x40, 0x7F, 0x87, 0xB0, 0x4F, 0xF0, 0xFF, 0x34, 0x09, 0x28, ++0x05, 0x94, 0x02, 0xD9, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x89, 0x46, 0xF9, 0x6C, 0xC9, 0x4E, 0x8C, 0x6C, 0x0D, 0x6D, ++0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x00, 0x60, 0x90, 0x46, 0x90, 0xF8, 0x22, 0x10, 0xFA, 0x8B, 0x14, 0xF4, 0x00, 0x5F, ++0x08, 0xBF, 0x01, 0x23, 0x22, 0xF4, 0x00, 0x54, 0x05, 0xF4, 0x80, 0x05, 0x02, 0xF4, 0x00, 0x52, 0xFF, 0x29, 0x01, 0x95, ++0xFC, 0x83, 0x02, 0x92, 0xE0, 0xD0, 0xBD, 0x4A, 0xD0, 0xF8, 0x4C, 0xA1, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, ++0x50, 0xDB, 0xBA, 0xF8, 0xB4, 0x10, 0xBA, 0x6C, 0x48, 0x1E, 0x05, 0xAC, 0xC0, 0xB2, 0x01, 0xEB, 0x41, 0x0E, 0x00, 0x90, ++0x03, 0x94, 0x0A, 0xEB, 0x8E, 0x0E, 0x02, 0xF1, 0x3C, 0x00, 0x02, 0xF1, 0x4C, 0x0B, 0xA4, 0x46, 0x50, 0xF8, 0x04, 0x6B, ++0xC6, 0xF3, 0x0D, 0x06, 0x79, 0xB1, 0x74, 0x46, 0x00, 0x22, 0x02, 0xE0, 0x01, 0x32, 0x8A, 0x42, 0x09, 0xD0, 0x34, 0xF8, ++0x02, 0x5C, 0xB5, 0x42, 0xA4, 0xF1, 0x0C, 0x04, 0xF6, 0xD1, 0x00, 0x9C, 0xA2, 0x1A, 0x8C, 0xF8, 0x00, 0x20, 0x00, 0x2B, ++0x40, 0xF0, 0xAD, 0x80, 0x83, 0x45, 0x0C, 0xF1, 0x01, 0x0C, 0xE3, 0xD1, 0x97, 0xF8, 0x36, 0x30, 0x9A, 0xF8, 0xA3, 0x20, ++0xC3, 0xF3, 0x82, 0x03, 0x93, 0x42, 0x27, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x64, 0xD0, 0xBA, 0xF8, 0x92, 0x20, 0xBA, 0xF8, ++0x90, 0x30, 0x01, 0x32, 0x01, 0x33, 0xAA, 0xF8, 0x92, 0x20, 0xAA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x7E, 0x10, 0xBA, 0xF8, ++0x7C, 0x20, 0x1F, 0xFA, 0x89, 0xF9, 0xA9, 0xEB, 0x08, 0x03, 0x0B, 0x44, 0x91, 0x44, 0xAA, 0xF8, 0x7E, 0x30, 0xAA, 0xF8, ++0x7C, 0x90, 0x87, 0xE7, 0xBA, 0xF1, 0x00, 0x0F, 0xAB, 0xD1, 0x90, 0x49, 0x90, 0x48, 0x00, 0x93, 0x4F, 0xF4, 0x18, 0x62, ++0xF3, 0xF7, 0x64, 0xF8, 0x00, 0x9B, 0xA2, 0xE7, 0xBA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x92, 0x20, 0x01, 0x33, 0xAA, 0xF8, ++0x90, 0x30, 0x01, 0x9B, 0x01, 0x32, 0xAA, 0xF8, 0x92, 0x20, 0x00, 0x2B, 0xD7, 0xD1, 0x02, 0x9B, 0x00, 0x2B, 0x3A, 0xD0, ++0x83, 0x4E, 0x85, 0x4D, 0x03, 0x9F, 0x00, 0x24, 0xB9, 0xF1, 0x00, 0x0F, 0x24, 0xD0, 0x17, 0xF8, 0x01, 0x3B, 0xFF, 0x2B, ++0x00, 0xF0, 0xEC, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0x41, 0x81, 0x03, 0xEB, 0x43, 0x02, 0xB8, 0xF1, 0x01, 0x0F, 0x0A, 0xEB, ++0x82, 0x02, 0x40, 0xF2, 0x7A, 0x81, 0x92, 0x88, 0x59, 0x00, 0x19, 0x44, 0x0A, 0xEB, 0x81, 0x01, 0x02, 0x32, 0x8A, 0x80, ++0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x71, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, ++0x02, 0x81, 0x01, 0x34, 0x04, 0x2C, 0xD7, 0xD1, 0x00, 0x23, 0x8A, 0xF8, 0x9B, 0x30, 0x3B, 0xE7, 0xBA, 0xF8, 0x92, 0x20, ++0xBA, 0xF8, 0x90, 0x30, 0x01, 0x32, 0x01, 0x33, 0xAA, 0xF8, 0x92, 0x20, 0xAA, 0xF8, 0x90, 0x30, 0xC1, 0xE7, 0x66, 0x4E, ++0x67, 0x4D, 0x03, 0x9F, 0x1C, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x29, 0xAF, 0x17, 0xF8, 0x01, 0x3B, 0xFF, 0x2B, ++0x00, 0xF0, 0xA5, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0xF0, 0x80, 0x03, 0xEB, 0x43, 0x02, 0xB8, 0xF1, 0x01, 0x0F, 0x0A, 0xEB, ++0x82, 0x02, 0x40, 0xF2, 0x43, 0x81, 0x92, 0x88, 0x59, 0x00, 0x19, 0x44, 0x0A, 0xEB, 0x81, 0x01, 0x02, 0x32, 0x8A, 0x80, ++0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x53, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, ++0xB6, 0x80, 0x01, 0x34, 0x04, 0x2C, 0xD6, 0xD1, 0x02, 0xE7, 0x97, 0xF8, 0x36, 0x30, 0x9A, 0xF8, 0xA3, 0x20, 0xC3, 0xF3, ++0x82, 0x03, 0x93, 0x42, 0x38, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x69, 0xD1, 0xBA, 0xF8, 0x92, 0x30, 0xBA, 0xF8, 0x90, 0x20, ++0x01, 0x33, 0x1F, 0xFA, 0x89, 0xF0, 0xAA, 0xF8, 0x92, 0x30, 0x02, 0x9B, 0x02, 0x44, 0xAA, 0xF8, 0x90, 0x20, 0x00, 0x2B, ++0x40, 0xF0, 0x8A, 0x80, 0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0xE3, 0xAE, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, ++0x04, 0x33, 0x3C, 0x4A, 0x5D, 0x88, 0x19, 0x88, 0x14, 0x68, 0xA0, 0xEB, 0x08, 0x02, 0x2A, 0x44, 0x01, 0x44, 0x92, 0xB2, ++0x89, 0xB2, 0x5A, 0x80, 0x19, 0x80, 0xB4, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xCE, 0xAE, 0x91, 0x42, 0xBF, 0xF4, ++0xCB, 0xAE, 0x33, 0x49, 0x34, 0x48, 0x4F, 0xF4, 0x1F, 0x62, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xF2, 0xF7, 0xA8, 0xBF, ++0xBA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x92, 0x20, 0x1F, 0xFA, 0x89, 0xF0, 0x03, 0x44, 0xAA, 0xF8, 0x90, 0x30, 0x01, 0x9B, ++0x01, 0x32, 0xAA, 0xF8, 0x92, 0x20, 0x8B, 0xBB, 0x02, 0x9B, 0x00, 0x2B, 0x52, 0xD1, 0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, ++0x00, 0xF0, 0xFD, 0x80, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, 0x04, 0x33, 0xB9, 0xEB, 0x48, 0x0F, 0x9A, 0xF8, 0xA4, 0x20, ++0x80, 0xF0, 0xE9, 0x80, 0x01, 0x2A, 0x40, 0xF2, 0xF8, 0x80, 0x02, 0x2A, 0x03, 0xD0, 0x00, 0x2B, 0x3F, 0xF4, 0x9A, 0xAE, ++0xB9, 0xE7, 0xDA, 0xF8, 0x00, 0x20, 0xA2, 0xF5, 0x92, 0x32, 0xF8, 0x3A, 0xCA, 0xF8, 0x00, 0x20, 0x00, 0x2B, 0x3F, 0xF4, ++0x8F, 0xAE, 0xAE, 0xE7, 0xBA, 0xF8, 0x90, 0x20, 0xBA, 0xF8, 0x92, 0x30, 0x1F, 0xFA, 0x89, 0xF0, 0x02, 0x44, 0x01, 0x33, ++0xAA, 0xF8, 0x90, 0x20, 0xAA, 0xF8, 0x92, 0x30, 0x0A, 0xF1, 0x7C, 0x03, 0x9F, 0xE7, 0x00, 0x2C, 0x75, 0xD0, 0xB8, 0xF1, ++0x01, 0x0F, 0x7F, 0xF6, 0x79, 0xAE, 0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x6C, 0xE7, 0x00, 0x2C, 0x00, 0xF0, ++0x8C, 0x80, 0xB8, 0xF1, 0x01, 0x0F, 0x7F, 0xF6, 0x2D, 0xAF, 0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x24, 0xE7, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0xE4, 0xC5, 0x15, 0x00, ++0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0x19, 0xAF, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, 0x00, 0x22, 0x04, 0x33, ++0x8A, 0xF8, 0x9B, 0x20, 0x71, 0xE7, 0x03, 0xEB, 0x43, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x9A, 0x88, 0xDB, 0x88, 0x9A, 0x42, ++0xBF, 0xF4, 0x41, 0xAF, 0x40, 0xF6, 0x61, 0x22, 0x31, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x28, 0xFF, 0x39, 0xE7, 0x03, 0xEB, ++0x43, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x9A, 0x88, 0xDB, 0x88, 0x9A, 0x42, 0xBF, 0xF4, 0xF5, 0xAE, 0x40, 0xF6, 0x33, 0x22, ++0x31, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x18, 0xFF, 0xED, 0xE6, 0xB8, 0xF1, 0x00, 0x0F, 0x6C, 0xD0, 0x03, 0xEB, 0x43, 0x01, ++0x0A, 0xEB, 0x81, 0x01, 0x08, 0xF1, 0xFF, 0x38, 0x8A, 0x88, 0x01, 0x32, 0x92, 0xB2, 0xB8, 0xF1, 0x01, 0x0F, 0x8A, 0x80, ++0x09, 0xF1, 0xFF, 0x39, 0x19, 0xB2, 0x73, 0xD9, 0x59, 0x00, 0x04, 0xE7, 0xB8, 0xF1, 0x00, 0x0F, 0x1B, 0xD0, 0x03, 0xEB, ++0x43, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x08, 0xF1, 0xFF, 0x38, 0x8A, 0x88, 0x01, 0x32, 0x92, 0xB2, 0xB8, 0xF1, 0x01, 0x0F, ++0x8A, 0x80, 0x09, 0xF1, 0xFF, 0x39, 0x19, 0xB2, 0x5B, 0xD9, 0x59, 0x00, 0xB3, 0xE6, 0xB8, 0xF1, 0x02, 0x0F, 0x7F, 0xF6, ++0x03, 0xAE, 0xA9, 0xF1, 0x03, 0x09, 0xA8, 0xF1, 0x03, 0x08, 0x01, 0x24, 0xCF, 0xE6, 0x03, 0xEB, 0x43, 0x02, 0x0A, 0xEB, ++0x82, 0x02, 0xA0, 0x46, 0x92, 0x88, 0x19, 0xB2, 0x01, 0xEB, 0x41, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x1F, 0xFA, 0x89, 0xF9, ++0xC8, 0x88, 0xA9, 0xEB, 0x08, 0x08, 0x4A, 0x44, 0x40, 0x44, 0x4F, 0xF0, 0x00, 0x09, 0x8A, 0x80, 0xC8, 0x80, 0xC8, 0x46, ++0x9A, 0xE6, 0xB8, 0xF1, 0x02, 0x0F, 0x7F, 0xF6, 0xA1, 0xAE, 0xA9, 0xF1, 0x03, 0x09, 0xA8, 0xF1, 0x03, 0x08, 0x01, 0x24, ++0x72, 0xE6, 0x92, 0x88, 0x1F, 0xFA, 0x88, 0xF8, 0x19, 0xB2, 0xDF, 0xE7, 0x92, 0x88, 0x1F, 0xFA, 0x88, 0xF8, 0x19, 0xB2, ++0x01, 0xEB, 0x41, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x1F, 0xFA, 0x89, 0xF9, 0xC8, 0x88, 0xA9, 0xEB, 0x08, 0x08, 0x4A, 0x44, ++0x40, 0x44, 0x4F, 0xF0, 0x00, 0x09, 0x8A, 0x80, 0xC8, 0x80, 0xC8, 0x46, 0xB2, 0xE6, 0x03, 0xEB, 0x43, 0x02, 0x0A, 0xEB, ++0x82, 0x02, 0xA0, 0x46, 0x92, 0x88, 0x19, 0xB2, 0xE6, 0xE7, 0x00, 0x2A, 0x3F, 0xF4, 0x19, 0xAF, 0x01, 0x3A, 0x8A, 0xF8, ++0xA4, 0x20, 0x00, 0x2B, 0x3F, 0xF4, 0xB0, 0xAD, 0xCF, 0xE6, 0x02, 0x9B, 0x04, 0xE7, 0x1F, 0xFA, 0x88, 0xF8, 0xB3, 0xE7, ++0x1F, 0xFA, 0x88, 0xF8, 0xD4, 0xE7, 0x01, 0x32, 0x8A, 0xF8, 0xA4, 0x20, 0x00, 0x2B, 0x3F, 0xF4, 0xA1, 0xAD, 0xC0, 0xE6, ++0x03, 0x88, 0xA3, 0xB1, 0x10, 0xB4, 0x42, 0x88, 0x44, 0x7A, 0x00, 0x21, 0x12, 0x04, 0x01, 0x72, 0xB2, 0xFB, 0xF3, 0xF1, ++0x8C, 0xB1, 0x83, 0x88, 0x5D, 0xF8, 0x04, 0x4B, 0x03, 0xEB, 0x43, 0x03, 0x0B, 0x44, 0xC3, 0xF3, 0x98, 0x03, 0x83, 0x80, ++0x01, 0x23, 0x43, 0x72, 0x70, 0x47, 0x03, 0x7A, 0xFF, 0x2B, 0x1C, 0xBF, 0x01, 0x33, 0x03, 0x72, 0x70, 0x47, 0x9A, 0x42, ++0x24, 0xBF, 0x01, 0xF1, 0xFF, 0x33, 0x83, 0x80, 0x4F, 0xF0, 0x01, 0x03, 0x38, 0xBF, 0x84, 0x80, 0x43, 0x72, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0xF8, 0xB5, 0x06, 0x46, 0x88, 0x04, 0x0C, 0x46, 0xC1, 0xF3, 0xC2, 0x25, 0x19, 0xD4, 0xCB, 0x0A, ++0x13, 0xF0, 0x06, 0x0F, 0x40, 0xD1, 0xCF, 0xB2, 0x01, 0xF0, 0x7F, 0x05, 0x05, 0xF0, 0xF8, 0xF9, 0x17, 0xF0, 0x7C, 0x0F, ++0x5B, 0xD1, 0x96, 0xF8, 0xAD, 0x20, 0x04, 0xE0, 0xB6, 0xF8, 0xAA, 0x30, 0xEB, 0x40, 0xD9, 0x07, 0x59, 0xD4, 0x6B, 0x1E, ++0x95, 0x42, 0xDD, 0xB2, 0xF6, 0xD8, 0x20, 0x46, 0xF8, 0xBD, 0x07, 0x2D, 0x47, 0xD0, 0x04, 0x3D, 0x05, 0xF0, 0xE2, 0xF9, ++0x04, 0xF0, 0x0F, 0x02, 0x01, 0x2D, 0xF4, 0xD8, 0xDF, 0xE8, 0x05, 0xF0, 0x01, 0x0E, 0x72, 0xB3, 0x53, 0x1E, 0x24, 0xF0, ++0x0F, 0x04, 0x96, 0xF8, 0xB1, 0x20, 0x23, 0x43, 0x98, 0xB2, 0x00, 0x2A, 0xE8, 0xD0, 0x40, 0xF4, 0x00, 0x70, 0xF8, 0xBD, ++0x0A, 0xB3, 0x24, 0xF0, 0x0F, 0x03, 0x51, 0x1E, 0x0B, 0x43, 0x98, 0xB2, 0x63, 0x04, 0xDD, 0xD5, 0x03, 0x2A, 0x03, 0xD0, ++0x96, 0xF8, 0xBD, 0x30, 0x99, 0x42, 0xD7, 0xDD, 0x20, 0xF4, 0x80, 0x43, 0x98, 0xB2, 0xF8, 0xBD, 0xC4, 0xF3, 0xC1, 0x05, ++0x05, 0xF0, 0xB8, 0xF9, 0x35, 0x44, 0x04, 0xF0, 0x07, 0x03, 0x05, 0xE0, 0x95, 0xF8, 0xA6, 0x20, 0xCB, 0xB2, 0xDA, 0x40, ++0xD2, 0x07, 0x24, 0xD4, 0x59, 0x1E, 0x00, 0x2B, 0xF6, 0xD1, 0x96, 0xF8, 0xAE, 0x30, 0x03, 0x2B, 0xBD, 0xD8, 0x43, 0xB3, ++0x96, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x60, 0x43, 0xEA, 0x82, 0x23, 0x03, 0x43, 0x98, 0xB2, 0xF8, 0xBD, 0x05, 0xF0, ++0x9B, 0xF9, 0x20, 0x46, 0xB0, 0xE7, 0x96, 0xF8, 0xAD, 0x20, 0x04, 0x2A, 0x38, 0xBF, 0x04, 0x22, 0xA5, 0xE7, 0x24, 0xF0, ++0x7F, 0x04, 0x44, 0xEA, 0x05, 0x00, 0x00, 0x2D, 0xA4, 0xD1, 0x40, 0xF4, 0x80, 0x63, 0x98, 0xB2, 0xF8, 0xBD, 0x96, 0xF8, ++0xB1, 0x20, 0x24, 0xF0, 0x07, 0x04, 0x44, 0xEA, 0x03, 0x00, 0x00, 0x2A, 0x98, 0xD0, 0x40, 0xF4, 0x00, 0x73, 0x98, 0xB2, ++0xF8, 0xBD, 0x4F, 0xF4, 0x80, 0x60, 0xF8, 0xBD, 0x8A, 0x04, 0x30, 0xB4, 0xC1, 0xF3, 0xC2, 0x23, 0x20, 0xD4, 0xCA, 0x0A, ++0x12, 0xF0, 0x06, 0x0F, 0x26, 0xD1, 0x11, 0xF0, 0x7C, 0x0F, 0x01, 0xF0, 0x7F, 0x03, 0x71, 0xD1, 0x90, 0xF8, 0xAE, 0x40, ++0x03, 0x2C, 0x28, 0xBF, 0x03, 0x24, 0x04, 0xE0, 0xB0, 0xF8, 0xAA, 0x20, 0xDA, 0x40, 0xD5, 0x07, 0x74, 0xD4, 0x5A, 0x1C, ++0xA3, 0x42, 0xD3, 0xB2, 0xF6, 0xD3, 0x90, 0xF8, 0xA5, 0x30, 0x01, 0x2B, 0x01, 0xD9, 0xD9, 0x02, 0x89, 0xB2, 0x08, 0x46, ++0x30, 0xBC, 0x70, 0x47, 0x07, 0x2B, 0xFA, 0xD0, 0x04, 0x3B, 0x01, 0xF0, 0x0F, 0x02, 0x01, 0x2B, 0xF5, 0xD8, 0xDF, 0xE8, ++0x03, 0xF0, 0x15, 0x30, 0xC1, 0xF3, 0xC1, 0x04, 0x90, 0xF8, 0xAC, 0x50, 0x04, 0x44, 0x01, 0xF0, 0x07, 0x03, 0x04, 0xE0, ++0x94, 0xF8, 0xA6, 0x20, 0xDA, 0x40, 0xD2, 0x07, 0x45, 0xD4, 0x5A, 0x1C, 0x9D, 0x42, 0xD3, 0xB2, 0xF6, 0xD8, 0x08, 0x46, ++0x30, 0xBC, 0x70, 0x47, 0x90, 0xF8, 0xAC, 0x30, 0x93, 0x42, 0xDA, 0xD9, 0xB0, 0xF8, 0xA6, 0x30, 0xC1, 0xF3, 0x02, 0x14, ++0x64, 0x00, 0x23, 0x41, 0x03, 0xF0, 0x03, 0x03, 0x07, 0x33, 0x93, 0x42, 0xCF, 0xD9, 0x21, 0xF0, 0x0F, 0x01, 0x01, 0x32, ++0x90, 0xF8, 0xB1, 0x30, 0x11, 0x43, 0x89, 0xB2, 0x00, 0x2B, 0xC6, 0xD0, 0x41, 0xF4, 0x00, 0x71, 0xC3, 0xE7, 0x90, 0xF8, ++0xAC, 0x30, 0x93, 0x42, 0xBF, 0xD9, 0xB0, 0xF8, 0xA6, 0x30, 0xC1, 0xF3, 0x02, 0x14, 0x64, 0x00, 0x23, 0x41, 0x03, 0xF0, ++0x03, 0x03, 0x5B, 0x00, 0x07, 0x33, 0x93, 0x42, 0xB3, 0xD9, 0x21, 0xF0, 0x0F, 0x01, 0x53, 0x1C, 0x0B, 0x43, 0x99, 0xB2, ++0x5B, 0x04, 0xAC, 0xD5, 0x01, 0x2A, 0x03, 0xD0, 0x90, 0xF8, 0xBD, 0x30, 0x93, 0x42, 0xA6, 0xD8, 0x21, 0xF4, 0x80, 0x41, ++0x89, 0xB2, 0xA2, 0xE7, 0x90, 0xF8, 0xAE, 0x40, 0x95, 0xE7, 0x90, 0xF8, 0xB1, 0x20, 0x21, 0xF0, 0x07, 0x01, 0x19, 0x43, ++0x00, 0x2A, 0x98, 0xD0, 0x41, 0xF4, 0x00, 0x71, 0x89, 0xB2, 0x94, 0xE7, 0x21, 0xF0, 0x7F, 0x01, 0x19, 0x43, 0x90, 0xE7, ++0x2D, 0xE9, 0xF0, 0x4F, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x85, 0xB0, 0x4C, 0x89, 0xE6, 0x0A, 0xC4, 0xF3, ++0x80, 0x22, 0x01, 0x92, 0x71, 0x07, 0x4F, 0xEA, 0x54, 0x22, 0x05, 0x46, 0x06, 0xF0, 0x04, 0x03, 0xC4, 0xF3, 0xC2, 0x27, ++0x02, 0x92, 0xC4, 0xF3, 0x40, 0x2B, 0xC4, 0xF3, 0xC1, 0x1A, 0x23, 0xD5, 0x07, 0x2F, 0x50, 0xD0, 0xC4, 0xF3, 0x02, 0x19, ++0x04, 0xF0, 0x0F, 0x04, 0xDF, 0xF8, 0x70, 0x83, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x22, 0xDA, ++0x05, 0x2F, 0x27, 0xD9, 0x40, 0xF2, 0xB5, 0x22, 0xCA, 0x49, 0xCB, 0x48, 0x03, 0x93, 0xF2, 0xF7, 0x0B, 0xFD, 0x95, 0xF8, ++0xA5, 0x20, 0x03, 0x9B, 0x05, 0x2A, 0x14, 0xD8, 0xDF, 0xE8, 0x12, 0xF0, 0xD6, 0x00, 0xD6, 0x00, 0x31, 0x01, 0x31, 0x01, ++0xF4, 0x00, 0x45, 0x01, 0x16, 0xF0, 0x06, 0x09, 0x26, 0xD1, 0x04, 0xF0, 0x7F, 0x04, 0xDF, 0xF8, 0x2C, 0x83, 0xD8, 0xF8, ++0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x06, 0xDB, 0x05, 0x2F, 0x17, 0xD8, 0xDF, 0xE8, 0x07, 0xF0, 0x22, 0x22, ++0x0F, 0x0F, 0x50, 0x91, 0x95, 0xF8, 0xA5, 0x10, 0x05, 0x29, 0xF4, 0xD8, 0xDF, 0xE8, 0x11, 0xF0, 0xBD, 0x00, 0xBD, 0x00, ++0x15, 0x01, 0x15, 0x01, 0xD8, 0x00, 0x29, 0x01, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, ++0xDF, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC4, 0xF3, 0xC1, 0x09, 0x04, 0xF0, 0x07, 0x04, 0xD5, 0xE7, 0x4F, 0xF0, ++0x00, 0x09, 0x4C, 0x46, 0xAE, 0xE7, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x03, 0x2C, 0x04, 0xD8, 0x95, 0xF8, ++0xB2, 0x10, 0x01, 0x29, 0x00, 0xF0, 0x7B, 0x81, 0x00, 0x2A, 0xE6, 0xDA, 0xBB, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x2E, 0x81, ++0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x1C, 0x81, 0xB9, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0xDC, 0x81, 0x95, 0xF8, 0xAD, 0x30, ++0xA3, 0x42, 0x00, 0xF2, 0xC9, 0x81, 0x95, 0xF8, 0xAE, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0xEE, 0x81, 0xB5, 0xF8, 0xAA, 0x30, ++0x23, 0xFA, 0x04, 0xF4, 0xE2, 0x07, 0xCA, 0xD4, 0x93, 0x49, 0x95, 0x48, 0x40, 0xF2, 0x06, 0x32, 0x3B, 0xE0, 0xD8, 0xF8, ++0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xBF, 0xDA, 0x01, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0xCB, 0x81, 0x95, 0xF8, ++0xB1, 0x30, 0x5B, 0x45, 0xC0, 0xF0, 0x52, 0x82, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, 0xC0, 0xF0, 0x3F, 0x82, 0x95, 0xF8, ++0xB0, 0x30, 0x4B, 0x45, 0xC0, 0xF0, 0x2C, 0x82, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0x19, 0x82, 0xB5, 0xF8, ++0xA6, 0x30, 0x4F, 0xEA, 0x49, 0x02, 0x13, 0x41, 0x03, 0xF0, 0x03, 0x03, 0x07, 0x33, 0x9C, 0x42, 0x00, 0xF3, 0x82, 0x81, ++0x06, 0x2C, 0x00, 0xF0, 0x3E, 0x81, 0x09, 0x2C, 0x97, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x4B, 0x82, 0xB9, 0xF1, ++0x02, 0x0F, 0x90, 0xD0, 0xB9, 0xF1, 0x05, 0x0F, 0x8D, 0xD0, 0x75, 0x49, 0x77, 0x48, 0x4F, 0xF4, 0x48, 0x72, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0xF2, 0xF7, 0x5C, 0xBC, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0x7E, 0xAF, 0x02, 0x9B, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF0, 0x21, 0x82, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, ++0xC0, 0xF0, 0x9E, 0x81, 0x95, 0xF8, 0xB0, 0x30, 0x4B, 0x45, 0xC0, 0xF0, 0xD1, 0x81, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, ++0xC0, 0xF0, 0xBE, 0x81, 0xB5, 0xF8, 0xA6, 0x30, 0x4F, 0xEA, 0x49, 0x09, 0x43, 0xFA, 0x09, 0xF3, 0x03, 0xF0, 0x03, 0x03, ++0x5B, 0x00, 0x07, 0x33, 0x9C, 0x42, 0x7F, 0xF7, 0x5C, 0xAF, 0x5C, 0x49, 0x5F, 0x48, 0x40, 0xF2, 0x2F, 0x32, 0xCC, 0xE7, ++0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xBF, 0xF6, 0x36, 0xAF, 0x16, 0xF0, 0x06, 0x0F, 0x40, 0xF0, ++0x2A, 0x81, 0x05, 0x2F, 0x3F, 0xF6, 0x49, 0xAF, 0x01, 0xA3, 0x53, 0xF8, 0x27, 0xF0, 0x00, 0xBF, 0xE7, 0x21, 0x15, 0x00, ++0xE7, 0x21, 0x15, 0x00, 0x8D, 0x23, 0x15, 0x00, 0x8D, 0x23, 0x15, 0x00, 0x43, 0x22, 0x15, 0x00, 0xC5, 0x22, 0x15, 0x00, ++0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x60, 0xD8, 0x00, 0x2A, 0xBF, 0xF6, ++0x14, 0xAF, 0x04, 0x2F, 0x3F, 0xF4, 0x6B, 0xAF, 0x00, 0x2F, 0x3F, 0xF4, 0x38, 0xAF, 0x42, 0x49, 0x46, 0x48, 0x4F, 0xF4, ++0x36, 0x72, 0xF2, 0xF7, 0xF9, 0xFB, 0x06, 0xE7, 0x01, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0x64, 0x81, 0x95, 0xF8, 0xB1, 0x30, ++0x5B, 0x45, 0xC0, 0xF0, 0x51, 0x81, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, 0xC0, 0xF0, 0xD5, 0x80, 0x95, 0xF8, 0xB0, 0x30, ++0x4B, 0x45, 0xC0, 0xF0, 0xC2, 0x80, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0xD9, 0x80, 0x4D, 0x44, 0x95, 0xF8, ++0xA6, 0x30, 0x23, 0xFA, 0x04, 0xF4, 0xE3, 0x07, 0x3F, 0xF5, 0x01, 0xAF, 0x2E, 0x49, 0x34, 0x48, 0x40, 0xF2, 0x12, 0x32, ++0x71, 0xE7, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x77, 0xD8, 0x00, 0x2A, ++0xBF, 0xF6, 0xD7, 0xAE, 0x00, 0x2B, 0xA2, 0xD0, 0x25, 0x49, 0x2C, 0x48, 0x40, 0xF2, 0xCA, 0x22, 0xF2, 0xF7, 0xC0, 0xFB, ++0xCD, 0xE6, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x56, 0xD8, 0x00, 0x2A, ++0xBF, 0xF6, 0xC3, 0xAE, 0x05, 0x2F, 0x3F, 0xF4, 0x5C, 0xAF, 0x00, 0x2F, 0x3F, 0xF4, 0xE7, 0xAE, 0x19, 0x49, 0x21, 0x48, ++0x40, 0xF2, 0xE7, 0x22, 0xF2, 0xF7, 0xA8, 0xFB, 0xB5, 0xE6, 0x00, 0x2A, 0xBF, 0xF6, 0xB3, 0xAE, 0x04, 0x2F, 0x3F, 0xF4, ++0x0A, 0xAF, 0x13, 0x49, 0x1B, 0x48, 0x4F, 0xF4, 0x37, 0x72, 0xF2, 0xF7, 0x9B, 0xFB, 0xA8, 0xE6, 0x0F, 0x49, 0x19, 0x48, ++0x40, 0xF2, 0x02, 0x32, 0xF2, 0xF7, 0x94, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0xD7, 0xAE, 0xB4, 0xE6, 0x08, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x01, 0x32, 0xF2, 0xF7, 0x86, 0xFB, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xA8, 0xAE, 0xBA, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0xC5, 0xAE, 0xDF, 0xE7, ++0x70, 0x79, 0x15, 0x00, 0x08, 0xC6, 0x15, 0x00, 0xB0, 0xC7, 0x15, 0x00, 0xF0, 0xC8, 0x15, 0x00, 0xA8, 0xC9, 0x15, 0x00, ++0xA8, 0xC6, 0x15, 0x00, 0x3C, 0xC8, 0x15, 0x00, 0x48, 0xC6, 0x15, 0x00, 0x04, 0xC7, 0x15, 0x00, 0xE8, 0xC6, 0x15, 0x00, ++0x64, 0xC7, 0x15, 0x00, 0x58, 0xC7, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x2A, 0xBF, 0xF6, 0x6C, 0xAE, 0x05, 0x2F, ++0x3F, 0xF4, 0x05, 0xAF, 0xA9, 0x49, 0xAA, 0x48, 0x40, 0xF2, 0xEB, 0x22, 0xF2, 0xF7, 0x54, 0xFB, 0x61, 0xE6, 0x00, 0x2A, ++0xBF, 0xF6, 0x5F, 0xAE, 0xBA, 0x1E, 0x01, 0x2A, 0x7F, 0xF6, 0x54, 0xAF, 0xA2, 0x49, 0xA4, 0x48, 0x40, 0xF2, 0xCE, 0x22, ++0xF2, 0xF7, 0x46, 0xFB, 0x53, 0xE6, 0x00, 0x2A, 0xBF, 0xF6, 0x6B, 0xAE, 0x01, 0x9B, 0x00, 0x2B, 0x7F, 0xF4, 0x80, 0xAE, ++0x40, 0xF2, 0xFB, 0x22, 0x9A, 0x49, 0x9D, 0x48, 0xF2, 0xF7, 0x38, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x20, ++0x72, 0xE6, 0xBA, 0xF1, 0x02, 0x0F, 0x7F, 0xF4, 0x58, 0xAE, 0xB9, 0xF1, 0x03, 0x0F, 0x03, 0xD0, 0xB9, 0xF1, 0x06, 0x0F, ++0x7F, 0xF4, 0x51, 0xAE, 0x90, 0x49, 0x94, 0x48, 0x40, 0xF2, 0x1F, 0x32, 0xC1, 0xE6, 0x8E, 0x49, 0x92, 0x48, 0x4F, 0xF4, ++0x44, 0x72, 0xF2, 0xF7, 0x1D, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x31, 0xAF, ++0x3D, 0xE6, 0x87, 0x49, 0x8C, 0x48, 0x40, 0xF2, 0x0F, 0x32, 0xF2, 0xF7, 0x0F, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x1E, 0xAF, 0x2F, 0xE6, 0x80, 0x49, 0x86, 0x48, 0x40, 0xF2, 0x11, 0x32, 0xF2, 0xF7, ++0x01, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x1A, 0xAF, 0x21, 0xE6, 0x79, 0x49, ++0x80, 0x48, 0x40, 0xF2, 0xC2, 0x22, 0xF2, 0xF7, 0xF3, 0xFA, 0x00, 0xE6, 0x75, 0x49, 0x7E, 0x48, 0x40, 0xF2, 0x1E, 0x32, ++0xF2, 0xF7, 0xEC, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x71, 0xAE, 0x0C, 0xE6, ++0x6E, 0x49, 0x78, 0x48, 0x4F, 0xF4, 0x41, 0x72, 0xF2, 0xF7, 0xDE, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xFF, 0xF6, 0x2A, 0xAE, 0xFE, 0xE5, 0x67, 0x49, 0x72, 0x48, 0x40, 0xF2, 0x03, 0x32, 0xF2, 0xF7, 0xD0, 0xFA, ++0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x17, 0xAE, 0xF0, 0xE5, 0x60, 0x49, 0x6C, 0x48, ++0x40, 0xF2, 0x19, 0x32, 0xF2, 0xF7, 0xC2, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0x28, 0xAE, 0xE2, 0xE5, 0x59, 0x49, 0x66, 0x48, 0x40, 0xF2, 0x05, 0x32, 0xF2, 0xF7, 0xB4, 0xFA, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x05, 0xAE, 0xD4, 0xE5, 0x52, 0x49, 0x58, 0x48, 0x4F, 0xF4, 0x4B, 0x72, ++0xF2, 0xF7, 0xA6, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x55, 0xAE, 0xC6, 0xE5, ++0x4B, 0x49, 0x59, 0x48, 0x40, 0xF2, 0x0E, 0x32, 0xF2, 0xF7, 0x98, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xFF, 0xF6, 0xA2, 0xAE, 0xB8, 0xE5, 0x44, 0x49, 0x50, 0x48, 0x40, 0xF2, 0x0D, 0x32, 0xF2, 0xF7, 0x8A, 0xFA, ++0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x8F, 0xAE, 0xAA, 0xE5, 0x3D, 0x49, 0x44, 0x48, ++0x40, 0xF2, 0x2E, 0x32, 0xF2, 0xF7, 0x7C, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0x35, 0xAE, 0x9C, 0xE5, 0x36, 0x49, 0x3B, 0x48, 0x40, 0xF2, 0x2D, 0x32, 0xF2, 0xF7, 0x6E, 0xFA, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x22, 0xAE, 0x8E, 0xE5, 0x2F, 0x49, 0x36, 0x48, 0x40, 0xF2, 0x1D, 0x32, ++0xF2, 0xF7, 0x60, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xDA, 0xAD, 0x80, 0xE5, ++0x28, 0x49, 0x2D, 0x48, 0x4F, 0xF4, 0x47, 0x72, 0xF2, 0xF7, 0x52, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xFF, 0xF6, 0xC7, 0xAD, 0x72, 0xE5, 0x21, 0x49, 0x27, 0x48, 0x40, 0xF2, 0x1B, 0x32, 0xF2, 0xF7, 0x44, 0xFA, ++0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xB4, 0xAD, 0x64, 0xE5, 0x1A, 0x49, 0x28, 0x48, ++0x40, 0xF2, 0x1A, 0x32, 0xF2, 0xF7, 0x36, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0xA1, 0xAD, 0x56, 0xE5, 0x13, 0x49, 0x22, 0x48, 0x40, 0xF2, 0x2B, 0x32, 0xF2, 0xF7, 0x28, 0xFA, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xD2, 0xAD, 0x48, 0xE5, 0xBA, 0xF1, 0x02, 0x0F, 0x08, 0xD1, 0xB9, 0xF1, ++0x05, 0x0F, 0x7F, 0xF4, 0x42, 0xAD, 0x09, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x21, 0x32, 0xB2, 0xE5, 0xBA, 0xF1, 0x03, 0x0F, ++0x7F, 0xF4, 0x39, 0xAD, 0xB9, 0xF1, 0x02, 0x0F, 0x7F, 0xF4, 0x35, 0xAD, 0x02, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x22, 0x32, ++0xA5, 0xE5, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0xD8, 0x93, 0x15, 0x00, 0x64, 0xC6, 0x15, 0x00, 0x48, 0xC7, 0x15, 0x00, ++0xAC, 0xC8, 0x15, 0x00, 0x10, 0xC8, 0x15, 0x00, 0xFC, 0xC7, 0x15, 0x00, 0x24, 0xC8, 0x15, 0x00, 0x28, 0xC6, 0x15, 0x00, ++0x64, 0xC8, 0x15, 0x00, 0x80, 0xC7, 0x15, 0x00, 0x74, 0xC7, 0x15, 0x00, 0xD4, 0xC7, 0x15, 0x00, 0x98, 0xC7, 0x15, 0x00, ++0xE4, 0xC7, 0x15, 0x00, 0xA0, 0xC9, 0x15, 0x00, 0x34, 0xC9, 0x15, 0x00, 0x68, 0xC9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x04, 0x46, 0x04, 0xF0, 0x89, 0xFD, 0x94, 0xF8, 0xA5, 0x10, 0x94, 0xF8, 0xAF, 0x20, 0xCB, 0x02, 0x9B, 0xB2, 0x92, 0xB3, ++0x55, 0x1E, 0xED, 0xB2, 0x05, 0x29, 0x2B, 0xD8, 0xDF, 0xE8, 0x01, 0xF0, 0x6D, 0x6D, 0x2F, 0x2F, 0x94, 0x03, 0x94, 0xF8, ++0xAD, 0x10, 0x03, 0x29, 0x00, 0xF2, 0xD1, 0x80, 0x06, 0x05, 0x40, 0xF1, 0xCE, 0x80, 0x94, 0xF8, 0xAE, 0x60, 0xB4, 0xF8, ++0xAA, 0x20, 0x73, 0x1A, 0x01, 0x33, 0x00, 0xF0, 0x7F, 0x07, 0x97, 0xFB, 0xF3, 0xF5, 0x03, 0xFB, 0x15, 0x73, 0x19, 0x44, ++0xC9, 0xB2, 0x22, 0xFA, 0x01, 0xF3, 0x13, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x31, 0x46, 0x00, 0x29, 0x00, 0xF0, 0x3F, 0x81, ++0x94, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x63, 0x43, 0xEA, 0x82, 0x23, 0x0B, 0x43, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, ++0xF0, 0x81, 0x15, 0x46, 0xCC, 0xE7, 0x94, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x01, 0xD8, 0x06, 0x05, 0xD5, 0xD4, 0x94, 0xF8, ++0xB0, 0x70, 0x94, 0xF8, 0xAC, 0x60, 0x94, 0xF8, 0xB1, 0xC0, 0x01, 0x37, 0xC0, 0xF3, 0xC1, 0x01, 0xB1, 0xFB, 0xF7, 0xFE, ++0x07, 0xFB, 0x1E, 0x11, 0x0C, 0x44, 0x06, 0xF1, 0x01, 0x0E, 0x00, 0xF0, 0x07, 0x08, 0x94, 0xF8, 0xA6, 0x70, 0xB8, 0xFB, ++0xFE, 0xF4, 0x0E, 0xFB, 0x14, 0x84, 0xE7, 0x40, 0xFF, 0x07, 0x48, 0xBF, 0xE6, 0xB2, 0x52, 0x1B, 0x0C, 0xF1, 0x01, 0x04, ++0xC0, 0xF3, 0x40, 0x2C, 0x01, 0x32, 0xC0, 0xF3, 0xC1, 0x10, 0xBC, 0xFB, 0xF4, 0xF7, 0xC9, 0x00, 0x04, 0xFB, 0x17, 0xC4, ++0x41, 0xEA, 0x44, 0x21, 0x90, 0xFB, 0xF2, 0xF4, 0x02, 0xFB, 0x14, 0x00, 0x05, 0x44, 0x0B, 0x43, 0x43, 0xEA, 0xC5, 0x13, ++0x9B, 0xB2, 0x33, 0x43, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x94, 0xF8, 0xAE, 0x70, 0x94, 0xF8, 0xAD, 0x20, 0xB4, 0xF8, ++0xAA, 0x50, 0xB9, 0x1A, 0x01, 0x31, 0x00, 0xF0, 0x7F, 0x0C, 0x9C, 0xFB, 0xF1, 0xF6, 0x01, 0xFB, 0x16, 0xC1, 0x0A, 0x44, ++0xD2, 0xB2, 0x25, 0xFA, 0x02, 0xF1, 0x11, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x3A, 0x46, 0x13, 0x43, 0x00, 0x2A, 0x00, 0xF0, ++0xA2, 0x80, 0x01, 0x3A, 0xD2, 0xB2, 0x02, 0x2A, 0x9E, 0xD8, 0x94, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x60, 0x40, 0xEA, ++0x82, 0x20, 0x03, 0x43, 0x9B, 0xB2, 0x95, 0xE7, 0x94, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x40, 0xF2, 0x8C, 0x80, 0x94, 0xF8, ++0xB0, 0x10, 0xB4, 0xF8, 0xA6, 0x70, 0x94, 0xF8, 0xAC, 0xC0, 0x94, 0xF8, 0xB1, 0x40, 0x4E, 0x1C, 0xC0, 0xF3, 0x02, 0x11, ++0xB1, 0xFB, 0xF6, 0xFE, 0x06, 0xFB, 0x1E, 0x11, 0x4E, 0x00, 0x37, 0x41, 0x07, 0xF0, 0x03, 0x07, 0x0C, 0xF1, 0x01, 0x06, ++0x00, 0xF0, 0x0F, 0x0C, 0x07, 0x37, 0xBC, 0xFB, 0xF6, 0xFE, 0x06, 0xFB, 0x1E, 0xCC, 0xBC, 0x45, 0xCE, 0xB2, 0xA2, 0xEB, ++0x05, 0x02, 0x40, 0xF3, 0x81, 0x80, 0x02, 0xF1, 0x01, 0x0C, 0xC0, 0xF3, 0xC1, 0x1E, 0x9E, 0xFB, 0xFC, 0xF2, 0x0C, 0xFB, ++0x12, 0xE2, 0x15, 0x44, 0xFF, 0xB2, 0xED, 0xB2, 0x09, 0x2F, 0x40, 0xF0, 0xAE, 0x80, 0x00, 0x2D, 0x40, 0xF0, 0x98, 0x80, ++0x02, 0x29, 0x00, 0xF0, 0xC0, 0x80, 0x05, 0x2E, 0x14, 0xBF, 0x4F, 0xF0, 0x08, 0x0C, 0x4F, 0xF0, 0x09, 0x0C, 0x09, 0x01, ++0x09, 0xB2, 0x00, 0x25, 0x76, 0xE0, 0x94, 0xF8, 0xB0, 0x70, 0xB4, 0xF8, 0xA6, 0x60, 0x94, 0xF8, 0xAC, 0xC0, 0x79, 0x1C, ++0xC0, 0xF3, 0x02, 0x17, 0xB7, 0xFB, 0xF1, 0xFE, 0x01, 0xFB, 0x1E, 0x77, 0x79, 0x00, 0x0E, 0x41, 0x06, 0xF0, 0x03, 0x06, ++0x0C, 0xF1, 0x01, 0x0C, 0x00, 0xF0, 0x0F, 0x01, 0x76, 0x00, 0x07, 0x36, 0xB1, 0xFB, 0xFC, 0xFE, 0x0C, 0xFB, 0x1E, 0x11, ++0xB1, 0x42, 0xC0, 0xF3, 0x41, 0x2C, 0xA2, 0xEB, 0x05, 0x02, 0xC8, 0xBF, 0xF1, 0xB2, 0x02, 0xF1, 0x01, 0x02, 0xC0, 0xF3, ++0xC1, 0x1E, 0xD8, 0xBF, 0xC9, 0xB2, 0xBC, 0xF1, 0x03, 0x0F, 0x18, 0xBF, 0x4F, 0xEA, 0x4C, 0x26, 0x9E, 0xFB, 0xF2, 0xFC, ++0x02, 0xFB, 0x1C, 0xEC, 0x94, 0xF8, 0xBC, 0x20, 0x65, 0x44, 0x08, 0xBF, 0x4F, 0xF4, 0x80, 0x66, 0xED, 0xB2, 0xEA, 0xB1, ++0x02, 0x29, 0x1A, 0xD0, 0x94, 0xF8, 0xBD, 0x20, 0x8A, 0x42, 0x16, 0xD3, 0x94, 0xF8, 0xBE, 0xC0, 0xFA, 0xB2, 0x94, 0x45, ++0x11, 0xD3, 0x94, 0xF8, 0xBF, 0x20, 0xAA, 0x42, 0x0D, 0xD3, 0x00, 0xF4, 0x80, 0x42, 0x12, 0xB2, 0x0A, 0xE0, 0x07, 0x05, ++0x7F, 0xF5, 0x71, 0xAF, 0xE1, 0xE6, 0x43, 0xF4, 0x80, 0x63, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x22, ++0x43, 0xEA, 0x07, 0x13, 0x43, 0xEA, 0xC5, 0x15, 0x29, 0x43, 0x31, 0x43, 0x42, 0xEA, 0x01, 0x03, 0x9B, 0xB2, 0x18, 0x46, ++0xBD, 0xE8, 0xF0, 0x81, 0x57, 0x1C, 0xC0, 0xF3, 0xC1, 0x1E, 0x9E, 0xFB, 0xF7, 0xF2, 0x07, 0xFB, 0x12, 0xE2, 0x15, 0x44, ++0xBC, 0xF1, 0x06, 0x0F, 0xED, 0xB2, 0x5F, 0xFA, 0x8C, 0xF7, 0x7F, 0xF4, 0x7B, 0xAF, 0x02, 0x2D, 0x20, 0xD0, 0x09, 0x01, ++0x09, 0xB2, 0xED, 0x01, 0x01, 0x34, 0xC0, 0xF3, 0x40, 0x20, 0xB0, 0xFB, 0xF4, 0xF2, 0x04, 0xFB, 0x12, 0x00, 0x43, 0xEA, ++0x40, 0x23, 0x2B, 0x43, 0x0B, 0x43, 0x4C, 0xEA, 0x03, 0x03, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, ++0x80, 0x63, 0xC5, 0xE6, 0x02, 0x2D, 0x16, 0xD1, 0x05, 0x29, 0x2D, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0xBC, 0x46, 0x4F, 0xF4, ++0x80, 0x75, 0xE1, 0xE7, 0x03, 0x29, 0x16, 0xD0, 0x06, 0x29, 0x14, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0x4F, 0xF4, 0x80, 0x75, ++0xD8, 0xE7, 0x09, 0x01, 0x09, 0xB2, 0xED, 0x01, 0x0F, 0xFA, 0x87, 0xFC, 0xD2, 0xE7, 0x03, 0x2D, 0x1B, 0xD1, 0x02, 0x29, ++0x0F, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0xBC, 0x46, 0x4F, 0xF4, 0xC0, 0x75, 0xC8, 0xE7, 0x71, 0x1E, 0xC9, 0xB2, 0x09, 0x01, ++0x4F, 0xF0, 0x06, 0x0C, 0x4F, 0xF4, 0x80, 0x75, 0xC0, 0xE7, 0xBC, 0x46, 0x43, 0xE7, 0xBC, 0x46, 0x10, 0x21, 0x4F, 0xF4, ++0xC0, 0x75, 0xB9, 0xE7, 0xBC, 0x46, 0x40, 0x21, 0x4F, 0xF4, 0x80, 0x75, 0xB4, 0xE7, 0x09, 0x01, 0x09, 0xB2, 0xED, 0x01, ++0xBC, 0x46, 0xAF, 0xE7, 0xB0, 0xF8, 0xB4, 0x30, 0x00, 0x2B, 0x4A, 0xD0, 0x2D, 0xE9, 0xF0, 0x4F, 0x03, 0xF1, 0xFF, 0x3B, ++0x1F, 0xFA, 0x8B, 0xFB, 0xBB, 0xF1, 0x01, 0x0F, 0x85, 0xB0, 0x8A, 0x46, 0x00, 0xF1, 0x10, 0x09, 0x3A, 0xD9, 0x01, 0x25, ++0x2F, 0x46, 0x0A, 0xF1, 0x04, 0x04, 0x4E, 0x46, 0x00, 0x21, 0x0D, 0xE0, 0x13, 0x43, 0x04, 0xD1, 0x73, 0x7A, 0x13, 0xB9, ++0x73, 0x7D, 0x01, 0x2B, 0x0B, 0xD0, 0x01, 0x35, 0xAF, 0xB2, 0x06, 0xF1, 0x0C, 0x08, 0x5F, 0x45, 0x46, 0x46, 0x20, 0xD2, ++0x22, 0x68, 0x54, 0xF8, 0x04, 0x3F, 0x9A, 0x42, 0xEC, 0xD9, 0x0C, 0x22, 0x06, 0xEB, 0x02, 0x08, 0x31, 0x46, 0x01, 0xA8, ++0x04, 0xF0, 0x3E, 0xFB, 0x30, 0x46, 0x41, 0x46, 0x0C, 0x22, 0x04, 0xF0, 0x39, 0xFB, 0x0C, 0x22, 0x01, 0xA9, 0x40, 0x46, ++0x04, 0xF0, 0x34, 0xFB, 0x01, 0x35, 0x54, 0xE9, 0x01, 0x32, 0x39, 0x46, 0xAF, 0xB2, 0x5F, 0x45, 0x44, 0xF8, 0x04, 0x2C, ++0x23, 0x60, 0x46, 0x46, 0xDE, 0xD3, 0x19, 0xB1, 0x8B, 0x46, 0xBB, 0xF1, 0x01, 0x0F, 0xC4, 0xD8, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0xB0, 0xF8, 0xB4, 0x50, 0x83, 0xB0, 0x06, 0x46, 0x89, 0x46, 0x00, 0x2D, ++0x00, 0xF0, 0xE2, 0x80, 0x6F, 0x1E, 0x1F, 0xFA, 0x87, 0xF8, 0x08, 0xEB, 0x48, 0x08, 0x00, 0xF1, 0x0C, 0x03, 0x03, 0xEB, ++0x88, 0x08, 0x04, 0x46, 0x4F, 0xF0, 0x00, 0x0A, 0x41, 0xF6, 0x98, 0x1B, 0x60, 0x89, 0xFE, 0xF7, 0xAD, 0xFE, 0x30, 0xB9, ++0x63, 0x7B, 0x23, 0xB1, 0x23, 0x89, 0x5B, 0x45, 0x07, 0xD8, 0x4F, 0xF0, 0x01, 0x0A, 0x0C, 0x34, 0x44, 0x45, 0xF1, 0xD1, ++0x4F, 0xEA, 0xCA, 0x00, 0x40, 0xB2, 0x96, 0xF8, 0xA2, 0x40, 0x24, 0xF0, 0x08, 0x04, 0x04, 0x43, 0xE4, 0xB2, 0x86, 0xF8, ++0xA2, 0x40, 0x14, 0xF0, 0x02, 0x04, 0x09, 0xD1, 0x05, 0xF1, 0x80, 0x43, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x59, 0xF8, ++0x23, 0x30, 0x9A, 0x42, 0x00, 0xF2, 0x9C, 0x80, 0x1F, 0xFA, 0x87, 0xFB, 0xCD, 0xF8, 0x00, 0xB0, 0x4F, 0xF0, 0x02, 0x08, ++0x00, 0x9C, 0xA6, 0xF8, 0x88, 0xB0, 0x04, 0xEB, 0x44, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x58, 0x89, 0xFE, 0xF7, 0x7A, 0xFE, ++0x63, 0x00, 0x01, 0x93, 0xE0, 0xB9, 0x00, 0x2F, 0x13, 0xDD, 0x82, 0x46, 0x84, 0x46, 0x0C, 0xEB, 0x4C, 0x0C, 0x06, 0xEB, ++0x8C, 0x04, 0x60, 0x89, 0xFE, 0xF7, 0x6C, 0xFE, 0x0A, 0xF1, 0x01, 0x03, 0x1F, 0xFA, 0x83, 0xFA, 0xD4, 0x46, 0x10, 0xB1, ++0x4F, 0xF0, 0x00, 0x03, 0xA3, 0x73, 0xBA, 0x45, 0xED, 0xDB, 0xDD, 0xE9, 0x00, 0x23, 0x13, 0x44, 0x06, 0xEB, 0x83, 0x04, ++0x01, 0x23, 0xA3, 0x73, 0xA8, 0x45, 0xA6, 0xF8, 0x8A, 0xB0, 0x76, 0xD2, 0xA5, 0xEB, 0x08, 0x03, 0x03, 0xEB, 0x43, 0x03, ++0x06, 0xEB, 0x83, 0x03, 0x03, 0xE0, 0x1F, 0xFA, 0x80, 0xF8, 0xA8, 0x45, 0x6B, 0xD0, 0x99, 0x7B, 0x08, 0xF1, 0x01, 0x00, ++0x0C, 0x3B, 0x00, 0x29, 0xF5, 0xD0, 0xA5, 0xEB, 0x08, 0x00, 0x08, 0xF1, 0x01, 0x08, 0x1F, 0xFA, 0x88, 0xF8, 0x80, 0xB2, ++0x45, 0x45, 0xA6, 0xF8, 0x8A, 0x00, 0x58, 0xD9, 0xA5, 0xEB, 0x08, 0x05, 0xA7, 0xEB, 0x08, 0x08, 0x4F, 0xEA, 0x18, 0x48, ++0x05, 0xEB, 0x45, 0x03, 0x4F, 0xEA, 0x08, 0x48, 0x06, 0xEB, 0x83, 0x03, 0x02, 0xE0, 0x01, 0x3D, 0x45, 0x45, 0x48, 0xD0, ++0x99, 0x7B, 0x0C, 0x3B, 0x00, 0x29, 0xF8, 0xD0, 0x05, 0xEB, 0x45, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x59, 0xF8, 0x25, 0x20, ++0xB3, 0xF8, 0x08, 0xE0, 0x30, 0xB3, 0x31, 0x46, 0x00, 0x23, 0x4F, 0xF2, 0x32, 0x38, 0x0C, 0xE0, 0x59, 0xF8, 0x23, 0x70, ++0x97, 0x42, 0x02, 0xD3, 0xA6, 0x46, 0x3A, 0x46, 0x1D, 0x46, 0x01, 0x33, 0x9C, 0xB2, 0xA0, 0x42, 0x01, 0xF1, 0x0C, 0x01, ++0x14, 0xD9, 0x8C, 0x7B, 0x9F, 0xB2, 0x00, 0x2C, 0xF5, 0xD0, 0x5F, 0x45, 0xF3, 0xD0, 0x0C, 0x89, 0x44, 0x45, 0xE9, 0xD8, ++0x74, 0x45, 0xEE, 0xD3, 0x59, 0xF8, 0x23, 0x20, 0x1D, 0x46, 0x01, 0x33, 0xA6, 0x46, 0x9C, 0xB2, 0xA0, 0x42, 0x01, 0xF1, ++0x0C, 0x01, 0xEA, 0xD8, 0x00, 0x23, 0xA6, 0xF8, 0x8C, 0x50, 0xA6, 0xF8, 0x8E, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x07, 0xEB, 0x47, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x5B, 0x7B, 0x00, 0x2B, 0x3F, 0xF4, 0x5C, 0xAF, 0x00, 0x94, 0xA3, 0x46, ++0x4F, 0xF0, 0x01, 0x08, 0x5C, 0xE7, 0x05, 0x46, 0xB8, 0xE7, 0x5D, 0x46, 0x58, 0x46, 0xB5, 0xE7, 0x28, 0x46, 0x4F, 0xF0, ++0xFF, 0x37, 0x38, 0xE7, 0xC1, 0xF3, 0xC2, 0x23, 0x05, 0x2B, 0x5B, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x03, 0x27, 0x27, ++0x0B, 0x32, 0xB0, 0xF8, 0xAA, 0x00, 0x01, 0xF0, 0x7F, 0x01, 0xC8, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x70, 0x47, 0xC1, 0xF3, ++0x02, 0x12, 0xB0, 0xF8, 0xA6, 0x00, 0x53, 0x00, 0x18, 0x41, 0x00, 0xF0, 0x03, 0x00, 0x07, 0x30, 0x01, 0xF0, 0x0F, 0x03, ++0x83, 0x42, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x06, 0x2B, 0xC1, 0xF3, 0xC1, 0x11, 0x24, 0xD0, 0x09, 0x2B, 0x24, 0xD1, ++0x21, 0xBB, 0x02, 0x2A, 0x21, 0xD0, 0x05, 0x2A, 0x18, 0xBF, 0x00, 0x20, 0x70, 0x47, 0xC1, 0xF3, 0xC1, 0x03, 0x18, 0x44, ++0x01, 0xF0, 0x07, 0x01, 0x90, 0xF8, 0xA6, 0x00, 0xC8, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x70, 0x47, 0xB0, 0xF8, 0xA6, 0x00, ++0xC1, 0xF3, 0x02, 0x13, 0x5B, 0x00, 0x18, 0x41, 0x00, 0xF0, 0x03, 0x00, 0x40, 0x00, 0x07, 0x30, 0x01, 0xF0, 0x0F, 0x01, ++0x81, 0x42, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x02, 0x29, 0x06, 0xD0, 0x70, 0x47, 0x02, 0x29, 0x09, 0xD1, ++0x05, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, 0x03, 0x2A, 0x09, 0xD0, 0x06, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, ++0x03, 0x29, 0xF0, 0xD1, 0x02, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0xEA, 0xE7, 0x01, 0x20, 0x70, 0x47, ++0x2D, 0xE9, 0xF0, 0x4F, 0x82, 0x46, 0xB0, 0xF8, 0x88, 0x70, 0xB0, 0xF8, 0x8A, 0x00, 0x9A, 0xF8, 0xAD, 0x30, 0x9A, 0xF8, ++0xAE, 0x60, 0x00, 0xEB, 0x40, 0x00, 0x07, 0xEB, 0x47, 0x07, 0x83, 0xB0, 0x0A, 0xEB, 0x80, 0x0C, 0x0A, 0xEB, 0x87, 0x07, ++0x14, 0x46, 0x0D, 0x46, 0x08, 0x46, 0x52, 0x00, 0x4F, 0xF0, 0xFF, 0x31, 0x7F, 0x89, 0xBC, 0xF8, 0x0A, 0x80, 0x00, 0x93, ++0xCD, 0xF7, 0x86, 0xF9, 0x00, 0x2C, 0x7E, 0xD0, 0x00, 0x9B, 0xA6, 0xEB, 0x03, 0x09, 0x01, 0x3C, 0x09, 0xF1, 0x01, 0x03, ++0xE4, 0xB2, 0x01, 0x93, 0x4F, 0xF0, 0x00, 0x0B, 0x5F, 0xFA, 0x8B, 0xF3, 0x05, 0x2B, 0x5E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, ++0x59, 0x41, 0x32, 0x23, 0x13, 0x03, 0x41, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xF9, 0xFF, 0x80, 0x45, 0x81, 0x46, 0x52, 0xD0, ++0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x5E, 0xFF, 0x00, 0x28, 0x4C, 0xD0, 0xA5, 0xF8, 0x0A, 0x90, 0x49, 0xE0, 0x41, 0x46, ++0x50, 0x46, 0xFF, 0xF7, 0x77, 0xF8, 0x80, 0x45, 0x81, 0x46, 0x42, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x4E, 0xFF, ++0x00, 0x28, 0x3C, 0xD0, 0xA5, 0xF8, 0x08, 0x90, 0x39, 0xE0, 0x39, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xD9, 0xFF, 0xB8, 0x42, ++0x81, 0x46, 0x32, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x3E, 0xFF, 0x68, 0xB3, 0xA5, 0xF8, 0x06, 0x90, 0x2A, 0xE0, ++0x39, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x58, 0xF8, 0xB8, 0x42, 0x81, 0x46, 0x23, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, ++0x2F, 0xFF, 0xF0, 0xB1, 0xA5, 0xF8, 0x04, 0x90, 0x1B, 0xE0, 0x00, 0x9B, 0x03, 0x2B, 0x03, 0xD8, 0x9A, 0xF8, 0xA2, 0x30, ++0x19, 0x07, 0x3B, 0xD4, 0xC7, 0xF3, 0xC2, 0x23, 0x05, 0x2B, 0x4F, 0xEA, 0xD7, 0x22, 0x23, 0xD0, 0x12, 0xF0, 0x06, 0x0F, ++0x0B, 0xD0, 0x9A, 0xF8, 0xB1, 0x30, 0x01, 0x2B, 0x07, 0xD1, 0x87, 0xF4, 0x00, 0x73, 0x6B, 0x80, 0x03, 0xE0, 0x50, 0x46, ++0xFF, 0xF7, 0x1E, 0xFC, 0x28, 0x80, 0x03, 0x2E, 0x09, 0xD8, 0x35, 0xF8, 0x1B, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, ++0x04, 0xBF, 0x46, 0xF4, 0x80, 0x63, 0x25, 0xF8, 0x1B, 0x30, 0x5C, 0x45, 0x0B, 0xF1, 0x01, 0x03, 0x01, 0xD0, 0x9B, 0x46, ++0x8A, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0x4A, 0xC7, 0xF3, 0x41, 0x23, 0x01, 0x33, 0xA2, 0xFB, 0x03, 0x21, ++0x21, 0xF0, 0x01, 0x02, 0x02, 0xEB, 0x51, 0x02, 0x27, 0xF4, 0xC0, 0x67, 0x9B, 0x1A, 0x47, 0xEA, 0x43, 0x23, 0x6B, 0x80, ++0xBF, 0xB2, 0xD8, 0xE7, 0x04, 0xF0, 0x82, 0xF9, 0x01, 0x99, 0x00, 0xF0, 0x7F, 0x02, 0x92, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, ++0x13, 0x23, 0x00, 0x9A, 0x13, 0x44, 0xBA, 0xF8, 0xAA, 0x20, 0xDB, 0xB2, 0xDA, 0x40, 0xD2, 0x07, 0x0F, 0xD5, 0x00, 0x2B, ++0x08, 0xBF, 0x33, 0x46, 0x5A, 0x1E, 0x02, 0x2A, 0x6B, 0x80, 0xCC, 0xD8, 0x9A, 0xF8, 0xB2, 0x10, 0x00, 0xF4, 0x80, 0x62, ++0x42, 0xEA, 0x81, 0x22, 0x13, 0x43, 0x6B, 0x80, 0xC3, 0xE7, 0x33, 0x46, 0xF0, 0xE7, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, ++0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x84, 0xB0, 0x01, 0xA9, 0x06, 0x22, 0xFF, 0xF7, 0x1C, 0xFF, 0xB5, 0xF8, 0xB4, 0x10, ++0x01, 0x29, 0x30, 0xD9, 0x00, 0x26, 0x01, 0x24, 0xB0, 0x46, 0xA1, 0x46, 0x4F, 0xF6, 0xFF, 0x77, 0x18, 0xE0, 0xB5, 0xF8, ++0x88, 0x20, 0xA2, 0x42, 0x21, 0xD0, 0xB5, 0xF8, 0x8A, 0x20, 0xA2, 0x42, 0x1D, 0xD0, 0xB5, 0xF8, 0x8C, 0x20, 0xA2, 0x42, ++0x19, 0xD0, 0x05, 0x2E, 0x17, 0xD8, 0x04, 0xAA, 0x02, 0xEB, 0x46, 0x02, 0x32, 0xF8, 0x0C, 0xEC, 0xBE, 0x45, 0x17, 0xD1, ++0xA1, 0x42, 0x06, 0xF1, 0x01, 0x06, 0x10, 0xD9, 0x04, 0xEB, 0x44, 0x03, 0x05, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0x44, 0x0C, ++0xB3, 0xF9, 0x08, 0x20, 0x00, 0x2A, 0xDC, 0xDA, 0x1A, 0x7B, 0x0A, 0x2A, 0xD9, 0xD8, 0x01, 0x34, 0xA4, 0xB2, 0xA1, 0x42, ++0xEE, 0xD8, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x59, 0xB1, 0x2A, 0x46, 0x00, 0x20, 0xB2, 0xF8, 0x0A, 0xA0, 0xF2, 0x45, ++0x00, 0xF1, 0x01, 0x00, 0x02, 0xF1, 0x0C, 0x02, 0xDC, 0xD0, 0x88, 0x42, 0xF5, 0xD1, 0x0C, 0xEB, 0x04, 0x02, 0x05, 0xEB, ++0x82, 0x02, 0xA3, 0xF8, 0x0A, 0xE0, 0xA3, 0xF8, 0x08, 0x80, 0x21, 0x46, 0x82, 0xF8, 0x0D, 0x80, 0x28, 0x46, 0xA3, 0xF8, ++0x04, 0x80, 0xA3, 0xF8, 0x06, 0x80, 0x01, 0x34, 0x82, 0xF8, 0x0C, 0x80, 0x82, 0xF8, 0x0E, 0x90, 0xFF, 0xF7, 0x12, 0xF8, ++0xA4, 0xB2, 0xB5, 0xF8, 0xB4, 0x10, 0xBF, 0xE7, 0x30, 0xB4, 0x90, 0xF8, 0xA5, 0x30, 0x05, 0x2B, 0x00, 0xF2, 0x8C, 0x80, ++0xDF, 0xE8, 0x03, 0xF0, 0x36, 0x36, 0x03, 0x03, 0x70, 0x57, 0x90, 0xF8, 0xAF, 0x50, 0x90, 0xF8, 0xB1, 0x20, 0x90, 0xF8, ++0xB0, 0x30, 0x90, 0xF8, 0xA6, 0x40, 0x01, 0x35, 0x95, 0x40, 0x03, 0xFB, 0x05, 0x55, 0xAD, 0xB2, 0x08, 0x21, 0x00, 0x23, ++0x04, 0xF0, 0x01, 0x02, 0x12, 0xFB, 0x05, 0xF2, 0x13, 0x44, 0x01, 0x39, 0x9B, 0xB2, 0x4F, 0xEA, 0x54, 0x04, 0xF5, 0xD1, ++0xB0, 0xF8, 0xAA, 0x20, 0x90, 0xF8, 0xB2, 0x10, 0xC2, 0xF3, 0x80, 0x04, 0xC2, 0xF3, 0x40, 0x00, 0xC1, 0xF1, 0x01, 0x01, ++0x20, 0x44, 0x88, 0x40, 0x02, 0xF0, 0x01, 0x04, 0xC2, 0xF3, 0xC0, 0x02, 0x20, 0x44, 0x8A, 0x40, 0x10, 0x44, 0x18, 0x44, ++0x80, 0xB2, 0x0A, 0x28, 0x28, 0xBF, 0x0A, 0x20, 0x30, 0xBC, 0x70, 0x47, 0xB0, 0xF8, 0xAA, 0x10, 0x90, 0xF8, 0xB2, 0x30, ++0xC1, 0xF3, 0x80, 0x02, 0xC1, 0xF3, 0x40, 0x00, 0xC3, 0xF1, 0x01, 0x03, 0x10, 0x44, 0x98, 0x40, 0x01, 0xF0, 0x01, 0x04, ++0xC1, 0xF3, 0xC0, 0x02, 0x02, 0xFA, 0x03, 0xF3, 0x20, 0x44, 0x13, 0xFA, 0x80, 0xF0, 0x80, 0xB2, 0x04, 0x23, 0x41, 0xFA, ++0x03, 0xF2, 0x02, 0xF0, 0x01, 0x02, 0x01, 0x33, 0x10, 0x44, 0x0C, 0x2B, 0x80, 0xB2, 0xF6, 0xD1, 0xD9, 0xE7, 0x90, 0xF8, ++0xB1, 0x30, 0xB0, 0xF8, 0xA6, 0x20, 0x90, 0xF8, 0xAF, 0x40, 0x90, 0xF8, 0xB0, 0x10, 0x58, 0x1C, 0x02, 0xF0, 0x03, 0x03, ++0x04, 0xFB, 0x00, 0x00, 0x01, 0x2B, 0x01, 0xFB, 0x00, 0x00, 0x1F, 0xD0, 0x02, 0x2B, 0x14, 0xBF, 0x08, 0x23, 0x0A, 0x23, ++0x10, 0xFB, 0x03, 0xF0, 0x80, 0xB2, 0xC0, 0xE7, 0xB0, 0xF8, 0xA6, 0x20, 0x90, 0xF8, 0xAF, 0x30, 0x90, 0xF8, 0xB1, 0x40, ++0x90, 0xF8, 0xB0, 0x10, 0x02, 0xF0, 0x03, 0x02, 0x01, 0x33, 0x01, 0x3A, 0x03, 0xFA, 0x04, 0xF0, 0x01, 0x2A, 0x8C, 0xBF, ++0x08, 0x23, 0x09, 0x23, 0x01, 0xFB, 0x00, 0x00, 0x10, 0xFB, 0x03, 0xF0, 0x80, 0xB2, 0xA8, 0xE7, 0x09, 0x23, 0xE1, 0xE7, ++0x00, 0x20, 0xA7, 0xE7, 0x2D, 0xE9, 0xF8, 0x4F, 0xB0, 0xF8, 0xB4, 0x40, 0x05, 0x46, 0x00, 0x2C, 0x00, 0xF0, 0xF4, 0x80, ++0x04, 0xF1, 0xFF, 0x38, 0x1F, 0xFA, 0x88, 0xF1, 0x01, 0xEB, 0x41, 0x03, 0x00, 0xF1, 0x0C, 0x01, 0x01, 0xEB, 0x83, 0x01, ++0x4F, 0xF6, 0xFF, 0x76, 0x03, 0x46, 0x00, 0x22, 0x01, 0x20, 0x5E, 0x81, 0x9A, 0x80, 0xDA, 0x80, 0x1A, 0x81, 0x1A, 0x73, ++0x5A, 0x73, 0x98, 0x73, 0x0C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0xC1, 0x46, 0x95, 0xF8, 0xA5, 0x30, 0x05, 0x2B, 0x00, 0xF2, ++0xD9, 0x80, 0xDF, 0xE8, 0x03, 0xF0, 0x4E, 0x4E, 0x03, 0x03, 0x8A, 0x5E, 0x95, 0xF8, 0xAD, 0x20, 0xDB, 0x02, 0x00, 0x2A, ++0x00, 0xF0, 0xC7, 0x80, 0x99, 0xB2, 0x95, 0xF8, 0xB0, 0x20, 0x69, 0x81, 0xA9, 0x18, 0x95, 0xF8, 0xB1, 0x60, 0x91, 0xF8, ++0xA6, 0x70, 0x95, 0xF8, 0xAF, 0x00, 0x43, 0xEA, 0x46, 0x23, 0xB7, 0xFA, 0x87, 0xF7, 0xC7, 0xF1, 0x1F, 0x07, 0x43, 0xEA, ++0xC0, 0x13, 0xFF, 0xB2, 0x43, 0xEA, 0xC2, 0x03, 0x3B, 0x43, 0x9F, 0xB2, 0x09, 0xEB, 0x49, 0x09, 0x05, 0xEB, 0x89, 0x03, ++0x01, 0x26, 0x46, 0x45, 0x5F, 0x81, 0x80, 0xF2, 0x9B, 0x80, 0x28, 0x46, 0xFF, 0xF7, 0x7E, 0xFA, 0xB5, 0xF8, 0xB4, 0x40, ++0x00, 0x2C, 0x00, 0xF0, 0x87, 0x80, 0x2B, 0x46, 0x00, 0x22, 0x02, 0xE0, 0xA2, 0x42, 0x00, 0xF0, 0x81, 0x80, 0x59, 0x89, ++0x81, 0x42, 0x02, 0xF1, 0x01, 0x02, 0x03, 0xF1, 0x0C, 0x03, 0xF5, 0xD1, 0x01, 0x3C, 0xA6, 0x42, 0xE7, 0xDB, 0x00, 0x24, ++0xA1, 0xB2, 0x28, 0x46, 0xFE, 0xF7, 0x0A, 0xFF, 0xB5, 0xF8, 0xB4, 0x30, 0x01, 0x34, 0x9C, 0x42, 0xF6, 0xD3, 0xBD, 0xE8, ++0xF8, 0x8F, 0x95, 0xF8, 0xAD, 0x20, 0x00, 0x2A, 0x7A, 0xD0, 0x92, 0xB2, 0x95, 0xF8, 0xB2, 0x10, 0x95, 0xF8, 0xAE, 0x70, ++0x6A, 0x81, 0xDB, 0x02, 0x43, 0xEA, 0x81, 0x23, 0x3B, 0x43, 0x9F, 0xB2, 0xC2, 0xE7, 0x95, 0xF8, 0xAD, 0x30, 0x00, 0x2B, ++0x67, 0xD0, 0x95, 0xF8, 0xBC, 0x30, 0x00, 0x2B, 0x0C, 0xBF, 0x4F, 0xF4, 0x28, 0x52, 0x4F, 0xF4, 0xD4, 0x42, 0x95, 0xF8, ++0xB0, 0x30, 0xB5, 0xF8, 0xA6, 0x60, 0x6A, 0x81, 0x5A, 0x00, 0x16, 0x41, 0x95, 0xF8, 0xAF, 0xA0, 0x06, 0xF0, 0x03, 0x06, ++0x1B, 0x01, 0x76, 0x00, 0x07, 0x36, 0x43, 0xEA, 0xCA, 0x1A, 0x4A, 0xEA, 0x06, 0x07, 0x47, 0xF4, 0x20, 0x57, 0x39, 0x46, ++0x28, 0x46, 0xFF, 0xF7, 0x1B, 0xFD, 0x01, 0x3E, 0xF3, 0xB2, 0xB6, 0xB2, 0x00, 0x28, 0x99, 0xD1, 0x06, 0x2B, 0xF0, 0xD1, ++0x96, 0xE7, 0x95, 0xF8, 0xB0, 0xA0, 0xB5, 0xF8, 0xA6, 0xB0, 0x95, 0xF8, 0xAF, 0x60, 0x95, 0xF8, 0xB1, 0x30, 0x4F, 0xEA, ++0x4A, 0x02, 0x4B, 0xFA, 0x02, 0xFB, 0xF6, 0x01, 0x46, 0xEA, 0x43, 0x26, 0x0B, 0xF0, 0x03, 0x0B, 0x4F, 0xF4, 0x00, 0x53, ++0x4F, 0xEA, 0x0A, 0x1A, 0x0B, 0xF1, 0x07, 0x0B, 0x36, 0xB2, 0x6B, 0x81, 0x4A, 0xEA, 0x0B, 0x07, 0x37, 0x43, 0x47, 0xF4, ++0x00, 0x57, 0xBF, 0xB2, 0x39, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0xF0, 0xFC, 0x0B, 0xF1, 0xFF, 0x3B, 0x5F, 0xFA, 0x8B, 0xF3, ++0x1F, 0xFA, 0x8B, 0xFB, 0x00, 0x28, 0x7F, 0xF4, 0x6B, 0xAF, 0x06, 0x2B, 0xEA, 0xD1, 0x67, 0xE7, 0x06, 0xEB, 0x46, 0x03, ++0x01, 0x36, 0x05, 0xEB, 0x83, 0x03, 0xB6, 0xB2, 0x04, 0xF1, 0xFF, 0x38, 0x46, 0x45, 0x58, 0x81, 0xFF, 0xF6, 0x65, 0xAF, ++0x00, 0x2C, 0x7F, 0xF4, 0x7A, 0xAF, 0xBD, 0xE8, 0xF8, 0x8F, 0x4F, 0xF4, 0x80, 0x62, 0x9C, 0xE7, 0x4F, 0xF4, 0x80, 0x62, ++0x82, 0xE7, 0x4F, 0xF4, 0x80, 0x61, 0x36, 0xE7, 0x4F, 0xF0, 0xFF, 0x39, 0xC8, 0x46, 0x21, 0xE7, 0x00, 0x27, 0x6F, 0x81, ++0x46, 0xE7, 0x00, 0xBF, 0x90, 0xF8, 0xAD, 0x30, 0x0B, 0x2B, 0xF0, 0xB4, 0x0C, 0xD9, 0x90, 0xF8, 0xA2, 0x20, 0x04, 0x23, ++0x01, 0x24, 0x22, 0xF0, 0x04, 0x02, 0x13, 0x43, 0x80, 0xF8, 0xA2, 0x30, 0x01, 0xB1, 0x0C, 0x70, 0xF0, 0xBC, 0x70, 0x47, ++0xB0, 0xF8, 0x88, 0x30, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, ++0x04, 0xD1, 0x00, 0x23, 0x90, 0xF8, 0xA2, 0x20, 0x1C, 0x46, 0xE6, 0xE7, 0xB0, 0xF8, 0x8A, 0x30, 0x03, 0xEB, 0x43, 0x03, ++0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, 0xEF, 0xD0, 0xB0, 0xF8, 0x8C, 0x30, 0x03, 0xEB, ++0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, 0xE4, 0xD0, 0x90, 0xF8, 0xA2, 0x20, ++0x12, 0xF0, 0x20, 0x04, 0x20, 0xD1, 0x90, 0xF8, 0xA4, 0x30, 0x44, 0x33, 0x30, 0xF8, 0x13, 0x30, 0x03, 0xEB, 0x43, 0x03, ++0x00, 0xEB, 0x83, 0x05, 0x6B, 0x89, 0x13, 0xF4, 0x00, 0x5F, 0x4F, 0xEA, 0xD3, 0x27, 0xC3, 0xF3, 0xC2, 0x26, 0x12, 0xD1, ++0x17, 0xF0, 0x06, 0x0F, 0x1D, 0xD1, 0x03, 0xF0, 0x7F, 0x03, 0x02, 0x2B, 0x15, 0xD9, 0x2D, 0x89, 0x40, 0xF2, 0x8E, 0x23, ++0x9D, 0x42, 0x86, 0xBF, 0x01, 0x24, 0x04, 0x23, 0x00, 0x23, 0xAA, 0xE7, 0x04, 0x23, 0x01, 0x24, 0xA7, 0xE7, 0x07, 0x2E, ++0x07, 0xD0, 0x03, 0xF0, 0x0F, 0x06, 0xC3, 0xF3, 0x02, 0x13, 0x02, 0x2E, 0xEB, 0xD8, 0x00, 0x2B, 0xE9, 0xD1, 0x2D, 0x89, ++0x41, 0xF6, 0x98, 0x13, 0xE8, 0xE7, 0x03, 0xF0, 0x07, 0x06, 0xC3, 0xF3, 0xC1, 0x03, 0xF2, 0xE7, 0xF8, 0xB5, 0x90, 0xF8, ++0xA2, 0x60, 0x16, 0xF0, 0x10, 0x05, 0x04, 0x46, 0x35, 0xD0, 0xB0, 0xF8, 0xB4, 0x00, 0x00, 0x28, 0x5F, 0xD0, 0xB4, 0xF8, ++0xBA, 0x70, 0x00, 0x23, 0x02, 0xE0, 0x82, 0x42, 0xCB, 0xB2, 0x46, 0xD2, 0x03, 0xEB, 0x43, 0x02, 0x04, 0xEB, 0x82, 0x02, ++0x59, 0x1C, 0x55, 0x89, 0xBD, 0x42, 0xCA, 0xB2, 0xF3, 0xD1, 0x9A, 0xB2, 0xA4, 0xF8, 0x88, 0x20, 0xA4, 0xF8, 0x8A, 0x20, ++0xA4, 0xF8, 0x8C, 0x20, 0x01, 0x38, 0x80, 0xB2, 0x04, 0xF1, 0x0C, 0x03, 0x00, 0xEB, 0x40, 0x00, 0x03, 0xEB, 0x80, 0x00, ++0x00, 0x22, 0x23, 0x46, 0x9A, 0x80, 0xDA, 0x80, 0x0C, 0x33, 0x98, 0x42, 0xFA, 0xD1, 0x26, 0xF0, 0x30, 0x06, 0x46, 0xF0, ++0x20, 0x06, 0x00, 0x23, 0x84, 0xF8, 0xA2, 0x60, 0x84, 0xF8, 0x9B, 0x30, 0x01, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x90, 0xF8, ++0x88, 0x00, 0x0C, 0x23, 0x03, 0xFB, 0x00, 0x40, 0x04, 0x30, 0xFE, 0xF7, 0x73, 0xFC, 0xB4, 0xF8, 0xB4, 0x30, 0x00, 0x2B, ++0xF1, 0xD0, 0x01, 0x3B, 0x9A, 0xB2, 0x02, 0xEB, 0x42, 0x03, 0x04, 0xF1, 0x0C, 0x02, 0x02, 0xEB, 0x83, 0x02, 0x2B, 0x46, ++0xA3, 0x80, 0xE3, 0x80, 0x0C, 0x34, 0x94, 0x42, 0xFA, 0xD1, 0x28, 0x46, 0xF8, 0xBD, 0xC1, 0xD1, 0x01, 0x38, 0xC3, 0xB2, ++0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0xC2, 0xB2, 0x00, 0x21, 0x5F, 0x81, 0x19, 0x81, 0xA4, 0xF8, 0x88, 0x20, ++0xA4, 0xF8, 0x8A, 0x20, 0xA4, 0xF8, 0x8C, 0x20, 0xB7, 0xE7, 0xB4, 0xF8, 0xBA, 0x20, 0xA4, 0xF8, 0xFE, 0x2B, 0x4F, 0xF0, ++0xFF, 0x11, 0xFF, 0x22, 0xA4, 0xF8, 0xFC, 0x0B, 0xC4, 0xF8, 0x88, 0x10, 0xA4, 0xF8, 0x8C, 0x20, 0xB7, 0xE7, 0x00, 0xBF, ++0xC2, 0x6C, 0x12, 0x69, 0xC2, 0xF3, 0x07, 0x21, 0xC2, 0xF3, 0x00, 0x42, 0x0A, 0x44, 0x00, 0x23, 0x01, 0x31, 0xFE, 0xF7, ++0xC9, 0xB9, 0x00, 0xBF, 0x8A, 0x1A, 0x01, 0x23, 0xFE, 0xF7, 0xC4, 0xB9, 0xC3, 0x88, 0x99, 0x04, 0x30, 0xB4, 0xC3, 0xF3, ++0xC2, 0x22, 0x11, 0xD4, 0xD9, 0x0A, 0x11, 0xF0, 0x06, 0x0F, 0x4A, 0xD1, 0x13, 0xF0, 0x7C, 0x0F, 0x03, 0xF0, 0x7F, 0x02, ++0x5D, 0xD1, 0xC3, 0xF3, 0x80, 0x23, 0x43, 0xEA, 0x42, 0x02, 0x3D, 0x4B, 0x30, 0xBC, 0x53, 0xF8, 0x22, 0x00, 0x70, 0x47, ++0x07, 0x2A, 0x37, 0xD0, 0x51, 0x1F, 0x03, 0xF0, 0x0F, 0x04, 0x01, 0x29, 0x37, 0xD8, 0xDF, 0xE8, 0x01, 0xF0, 0x01, 0x1B, ++0xC3, 0xF3, 0x00, 0x21, 0x4A, 0x00, 0x11, 0x44, 0x06, 0x22, 0x12, 0xFB, 0x04, 0x12, 0xC3, 0xF3, 0x41, 0x21, 0x0A, 0x44, ++0x31, 0x49, 0x51, 0xF8, 0x22, 0x00, 0xC3, 0xF3, 0xC0, 0x11, 0xC3, 0xF3, 0x02, 0x12, 0xC3, 0xF3, 0x80, 0x33, 0xC8, 0x40, ++0x01, 0x32, 0x30, 0xBC, 0xB0, 0xFB, 0xF2, 0xF0, 0x98, 0x40, 0x70, 0x47, 0x00, 0x7A, 0x00, 0xF0, 0x07, 0x00, 0x02, 0x28, ++0x31, 0xD8, 0x28, 0x49, 0xC3, 0xF3, 0x41, 0x25, 0x03, 0x22, 0x51, 0xF8, 0x20, 0x10, 0x12, 0xFB, 0x04, 0x52, 0xC3, 0xF3, ++0x02, 0x10, 0x01, 0x30, 0x51, 0xF8, 0x22, 0x30, 0xB3, 0xFB, 0xF0, 0xF0, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x30, 0xBC, ++0x70, 0x47, 0x03, 0xF0, 0x07, 0x04, 0xC3, 0xF3, 0x40, 0x20, 0xC3, 0xF3, 0xC1, 0x11, 0x40, 0xEA, 0x41, 0x01, 0x41, 0xEA, ++0xC4, 0x04, 0x04, 0x2A, 0x19, 0x49, 0x14, 0xBF, 0xC3, 0xF3, 0xC1, 0x03, 0xC3, 0xF3, 0x02, 0x13, 0x51, 0xF8, 0x24, 0x00, ++0x01, 0x33, 0x30, 0xBC, 0xB0, 0xFB, 0xF3, 0xF0, 0x70, 0x47, 0x14, 0x4B, 0x04, 0x3A, 0x30, 0xBC, 0x53, 0xF8, 0x22, 0x00, ++0x70, 0x47, 0xC2, 0x1E, 0xC2, 0xF3, 0x46, 0x01, 0x02, 0xF0, 0xFE, 0x00, 0x08, 0x44, 0x06, 0x21, 0x11, 0xFB, 0x04, 0x04, ++0xC3, 0xF3, 0x41, 0x21, 0x0C, 0x44, 0x08, 0x49, 0x51, 0xF8, 0x24, 0x00, 0xC3, 0xF3, 0x02, 0x13, 0x02, 0xF0, 0x01, 0x02, ++0x59, 0x1C, 0x30, 0xBC, 0x20, 0xFA, 0x02, 0xF3, 0xB3, 0xFB, 0xF1, 0xF0, 0x70, 0x47, 0x00, 0xBF, 0x54, 0xCC, 0x15, 0x00, ++0x74, 0xCC, 0x15, 0x00, 0xA4, 0xD0, 0x15, 0x00, 0x44, 0xCF, 0x15, 0x00, 0x84, 0xD0, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0xB0, 0xF8, 0x96, 0x30, 0x90, 0xF8, 0xA2, 0x80, 0x90, 0xF8, 0xA5, 0x60, 0x03, 0xEB, 0x83, 0x03, 0x5B, 0x00, 0xA0, 0xF8, ++0x98, 0x30, 0x07, 0x46, 0x03, 0xF0, 0xB8, 0xFD, 0xB7, 0xF8, 0xB4, 0x10, 0x80, 0xB2, 0xB0, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, ++0x13, 0x00, 0x00, 0x29, 0x77, 0xD0, 0xB7, 0xF8, 0x88, 0xC0, 0x83, 0xB2, 0x08, 0xF0, 0x02, 0x08, 0x00, 0x20, 0x4F, 0xF2, ++0x33, 0x3E, 0x03, 0x44, 0xB3, 0xFB, 0xF1, 0xF5, 0x01, 0xFB, 0x15, 0x35, 0x05, 0xEB, 0x45, 0x02, 0x92, 0x00, 0xAB, 0xB2, ++0x07, 0xEB, 0x02, 0x0A, 0x9C, 0x45, 0x02, 0xF1, 0x04, 0x02, 0x00, 0xF1, 0x01, 0x00, 0x07, 0xEB, 0x02, 0x04, 0x4F, 0xEA, ++0x45, 0x09, 0x58, 0xD0, 0xBA, 0xF8, 0x08, 0x20, 0x72, 0x45, 0x54, 0xD8, 0xB8, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0xBA, 0xF8, ++0x0A, 0x20, 0xD2, 0x12, 0x12, 0xF0, 0x06, 0x0F, 0x4B, 0xD0, 0x01, 0x2E, 0x42, 0xD9, 0x0C, 0xEB, 0x4C, 0x0C, 0x07, 0xEB, ++0x8C, 0x0C, 0xBC, 0xF8, 0x0A, 0x30, 0x98, 0x04, 0x4F, 0xEA, 0xD3, 0x26, 0xC3, 0xF3, 0xC2, 0x22, 0x47, 0xD4, 0x16, 0xF0, ++0x06, 0x06, 0x01, 0xD0, 0xC3, 0xF3, 0xC1, 0x06, 0xE3, 0x88, 0x99, 0x04, 0x4F, 0xEA, 0xD3, 0x28, 0xC3, 0xF3, 0xC2, 0x22, ++0x36, 0xD4, 0x18, 0xF0, 0x06, 0x08, 0x01, 0xD0, 0xC3, 0xF3, 0xC1, 0x08, 0xB7, 0xF8, 0x8A, 0x00, 0x00, 0xEB, 0x40, 0x00, ++0x07, 0xEB, 0x80, 0x00, 0xA9, 0x44, 0x04, 0x30, 0x07, 0xEB, 0x89, 0x09, 0xFF, 0xF7, 0xFA, 0xFE, 0x99, 0xF8, 0x0D, 0x30, ++0x82, 0x46, 0x5B, 0xBB, 0xB7, 0xF8, 0x96, 0xB0, 0x20, 0x46, 0xFF, 0xF7, 0xF1, 0xFE, 0x50, 0x45, 0x81, 0x46, 0x0D, 0xD3, ++0x01, 0x3E, 0x46, 0x45, 0x23, 0xD2, 0x23, 0x7A, 0x5B, 0x45, 0x10, 0xD3, 0x97, 0xF8, 0x9A, 0x30, 0x01, 0x33, 0xDB, 0xB2, ++0x02, 0x2B, 0x87, 0xF8, 0x9A, 0x30, 0x29, 0xD8, 0x01, 0x20, 0x87, 0xF8, 0xA0, 0x50, 0x87, 0xF8, 0x9B, 0x00, 0xBD, 0xE8, ++0xF8, 0x8F, 0x88, 0x42, 0x8F, 0xD1, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x07, 0x2A, 0x18, 0xD0, 0xC3, 0xF3, 0x02, 0x18, ++0xC8, 0xE7, 0x07, 0x2A, 0x11, 0xD0, 0xC3, 0xF3, 0x02, 0x16, 0xB7, 0xE7, 0x4F, 0xF0, 0x20, 0x0B, 0xD2, 0xE7, 0xB7, 0xF8, ++0x8C, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x07, 0xEB, 0x80, 0x00, 0x04, 0x30, 0xFF, 0xF7, 0xBE, 0xFE, 0x81, 0x45, 0xDB, 0xD3, ++0xCF, 0xE7, 0x00, 0x26, 0xA6, 0xE7, 0x4F, 0xF0, 0x00, 0x08, 0xAF, 0xE7, 0x0F, 0x2B, 0x84, 0xBF, 0x0F, 0x23, 0x87, 0xF8, ++0x9A, 0x30, 0xD8, 0xE7, 0x90, 0xF8, 0xA2, 0x30, 0x99, 0x06, 0x1F, 0xD4, 0x10, 0xB5, 0x90, 0xF8, 0x9B, 0x20, 0x04, 0x46, ++0xC2, 0xB9, 0xB0, 0xF8, 0x98, 0x20, 0x92, 0xB9, 0x5A, 0x06, 0x0B, 0xD5, 0xB0, 0xF8, 0xB4, 0x20, 0x09, 0x2A, 0x03, 0xD9, ++0xFF, 0xF7, 0x9E, 0xFB, 0x94, 0xF8, 0xA2, 0x30, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0xA2, 0x30, 0x20, 0x46, 0xBD, 0xE8, ++0x10, 0x40, 0xFF, 0xF7, 0x29, 0xBF, 0x01, 0x3A, 0xA0, 0xF8, 0x98, 0x20, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x70, 0x47, ++0x2D, 0xE9, 0xF0, 0x41, 0x29, 0x4F, 0x2A, 0x4E, 0xD7, 0xF8, 0x00, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0xB8, 0xF9, 0x00, 0x20, ++0x03, 0xFB, 0x00, 0x63, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x8A, 0xB0, 0x04, 0x46, 0x20, 0xDB, 0x28, 0x46, 0xFF, 0xF7, ++0xDF, 0xFB, 0xA5, 0xF8, 0xB4, 0x00, 0xB8, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x22, 0xDB, 0x28, 0x46, 0xFF, 0xF7, 0x6A, 0xFC, ++0x69, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x3C, 0xF9, 0x28, 0x46, 0x00, 0x21, 0xFF, 0xF7, 0x66, 0xFD, 0x4F, 0xF4, 0x1E, 0x70, ++0x00, 0xFB, 0x04, 0x64, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x01, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x0A, 0xB0, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0x2D, 0xDC, 0xD1, 0x12, 0x49, 0x12, 0x48, 0x40, 0xF6, 0xAF, 0x42, 0xF1, 0xF7, 0x03, 0xF9, 0xD7, 0xF8, ++0x00, 0x80, 0xD3, 0xE7, 0x40, 0xB1, 0x0A, 0x28, 0xD9, 0xD9, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF6, 0xB4, 0x42, 0xF1, 0xF7, ++0xF7, 0xF8, 0xD2, 0xE7, 0x08, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0xB3, 0x42, 0xF1, 0xF7, 0xF0, 0xF8, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC7, 0xDA, 0xB5, 0xF8, 0xB4, 0x00, 0xE8, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x0C, 0xCA, 0x15, 0x00, 0xF4, 0xC9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0xDF, 0xF8, 0xBC, 0x80, 0x29, 0x4D, 0xD8, 0xF8, 0x00, 0x40, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x00, 0x53, 0x07, 0x46, ++0xB4, 0xF9, 0x00, 0x00, 0xD3, 0xF8, 0x4C, 0x41, 0x00, 0x28, 0x0D, 0x46, 0x16, 0x46, 0x20, 0xDB, 0x94, 0xF8, 0xAF, 0x30, ++0xAB, 0x42, 0x39, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0x84, 0xF8, 0xAF, 0x50, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x26, 0xDB, ++0x84, 0xF8, 0xB0, 0x60, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x17, 0xDB, 0x94, 0xF8, 0xA2, 0x30, 0x9A, 0x06, 0x05, 0xD5, ++0x63, 0xF0, 0x7F, 0x03, 0x84, 0xF8, 0xA2, 0x30, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7, ++0x69, 0xBF, 0x00, 0x2C, 0xDC, 0xD1, 0x11, 0x49, 0x11, 0x48, 0x40, 0xF6, 0xCC, 0x42, 0xF1, 0xF7, 0x9F, 0xF8, 0xD5, 0xE7, ++0x07, 0x2E, 0xE5, 0xD9, 0x0C, 0x49, 0x0E, 0x48, 0x40, 0xF6, 0xD4, 0x42, 0xF1, 0xF7, 0x96, 0xF8, 0xDE, 0xE7, 0x03, 0x2D, ++0xD6, 0xD9, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0xD2, 0x42, 0xF1, 0xF7, 0x8D, 0xF8, 0xD8, 0xF8, 0x00, 0x30, 0xCD, 0xE7, ++0x94, 0xF8, 0xB0, 0x30, 0xB3, 0x42, 0xC1, 0xD1, 0xD6, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0x50, 0xCA, 0x15, 0x00, 0x34, 0xCA, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x4D, 0x4B, 0x8D, 0xB0, 0x1A, 0x68, 0x01, 0x90, 0x04, 0x46, 0x4C, 0x48, 0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x04, 0x03, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0xB1, 0x0C, 0x46, 0x79, 0xDB, 0x9B, 0xF8, 0xB2, 0x20, 0xA2, 0x42, ++0x72, 0xD0, 0x8B, 0xF8, 0xB2, 0x40, 0x00, 0x2C, 0x6E, 0xD0, 0x9B, 0xF8, 0xA2, 0x20, 0x12, 0xF0, 0x20, 0x07, 0x76, 0xD1, ++0xBB, 0xF8, 0xB4, 0x90, 0xB8, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x15, 0xD1, 0x4D, 0xE0, 0x25, 0x44, 0x0C, 0xAB, 0x01, 0x37, ++0x0B, 0xEB, 0x85, 0x05, 0x03, 0xEB, 0x84, 0x04, 0xB8, 0xB2, 0x4F, 0xF0, 0x01, 0x03, 0x81, 0x45, 0xAB, 0x73, 0xA6, 0xF8, ++0x0A, 0xA0, 0xA6, 0xF8, 0x08, 0x80, 0x85, 0xF8, 0x0D, 0x80, 0x44, 0xF8, 0x28, 0x8C, 0x38, 0xD9, 0xBC, 0xB2, 0x04, 0xEB, ++0x44, 0x06, 0x0B, 0xEB, 0x86, 0x06, 0x65, 0x00, 0xB6, 0xF8, 0x0A, 0xA0, 0x50, 0x46, 0xFD, 0xF7, 0x19, 0xFF, 0x00, 0x28, ++0xDD, 0xD0, 0x4A, 0xF4, 0x80, 0x6A, 0xB9, 0xF1, 0x00, 0x0F, 0x16, 0xD0, 0x58, 0x46, 0x4F, 0xF0, 0x00, 0x0C, 0x01, 0xE0, ++0xCC, 0x45, 0xD2, 0xD0, 0xB0, 0xF8, 0x0A, 0xE0, 0xD6, 0x45, 0x0C, 0xF1, 0x01, 0x0C, 0x00, 0xF1, 0x0C, 0x00, 0xF5, 0xD1, ++0x58, 0x46, 0xFE, 0xF7, 0x37, 0xFE, 0xBB, 0xF8, 0xB4, 0x90, 0x82, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0xE8, 0xD1, 0x28, 0x19, ++0x0C, 0xAB, 0x0B, 0xEB, 0x80, 0x00, 0x03, 0xEB, 0x84, 0x04, 0x01, 0x25, 0x85, 0x73, 0xA6, 0xF8, 0x0A, 0xA0, 0xA6, 0xF8, ++0x08, 0x90, 0x80, 0xF8, 0x0D, 0x90, 0x44, 0xF8, 0x28, 0x9C, 0x02, 0xA9, 0x58, 0x46, 0xFE, 0xF7, 0xCF, 0xFF, 0x02, 0xA9, ++0x58, 0x46, 0xFF, 0xF7, 0x1B, 0xF8, 0x01, 0x9A, 0x11, 0x46, 0x10, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x29, ++0x99, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x01, 0x03, 0x89, 0xF8, 0x56, 0x31, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xBB, 0xF1, ++0x00, 0x0F, 0x82, 0xD1, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF6, 0xEA, 0x42, 0xF0, 0xF7, 0xE2, 0xFF, 0x7B, 0xE7, 0x62, 0xF0, ++0x7F, 0x02, 0x8B, 0xF8, 0xA2, 0x20, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0xB0, 0xF8, 0x54, 0x21, 0x03, 0x29, 0x9A, 0xBF, 0x02, 0xF4, 0x80, 0x62, ++0x12, 0xB2, 0x00, 0x22, 0x10, 0xB4, 0x42, 0xEA, 0x01, 0x03, 0xD0, 0xF8, 0x48, 0x41, 0x43, 0xF0, 0x00, 0x53, 0xC4, 0xE9, ++0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x90, 0xF8, 0xA5, 0x30, 0xC1, 0xF3, 0xC2, 0x22, ++0x93, 0x42, 0x13, 0xD3, 0x05, 0x2B, 0x70, 0xB5, 0x4F, 0xEA, 0xD1, 0x24, 0x11, 0xD0, 0x04, 0x2B, 0x29, 0xD0, 0x02, 0x3B, ++0x01, 0x2B, 0x12, 0xD8, 0x14, 0xF0, 0x06, 0x03, 0x04, 0xF0, 0x06, 0x05, 0x26, 0xD1, 0x90, 0xF8, 0xAD, 0x20, 0x03, 0x2A, ++0x1B, 0xD8, 0x0D, 0xE0, 0x00, 0x23, 0x18, 0x46, 0x70, 0x47, 0x05, 0x2A, 0x03, 0xD0, 0x90, 0xF8, 0xAD, 0x30, 0x03, 0x2B, ++0x15, 0xD8, 0x14, 0xF0, 0x06, 0x0F, 0x04, 0xF0, 0x06, 0x05, 0x13, 0xD1, 0x4A, 0x05, 0xC1, 0xF3, 0x80, 0x23, 0x03, 0xD4, ++0x90, 0xF8, 0xB2, 0x20, 0x01, 0x2A, 0x04, 0xD0, 0xFF, 0xF7, 0x9A, 0xF8, 0x03, 0x1E, 0x18, 0xBF, 0x01, 0x23, 0x18, 0x46, ++0x70, 0xBD, 0x04, 0x2A, 0x1A, 0xD0, 0x00, 0x23, 0x18, 0x46, 0x70, 0xBD, 0x04, 0x2A, 0x1A, 0xD9, 0x90, 0xF8, 0xAF, 0x60, ++0xC1, 0xF3, 0xC1, 0x13, 0x9E, 0x42, 0xF4, 0xD3, 0x63, 0x07, 0x08, 0xD5, 0x07, 0x2A, 0xE7, 0xD0, 0xC1, 0xF3, 0x02, 0x13, ++0x90, 0xF8, 0xB0, 0x20, 0x9A, 0x42, 0xEA, 0xD3, 0xE0, 0xE7, 0x00, 0x2D, 0xDE, 0xD0, 0xC1, 0xF3, 0xC1, 0x03, 0xF5, 0xE7, ++0x14, 0xF0, 0x06, 0x0F, 0x04, 0xF0, 0x06, 0x05, 0xCE, 0xD0, 0x8E, 0x05, 0xE2, 0xD5, 0x90, 0xF8, 0xB1, 0x30, 0x00, 0x2B, ++0xD5, 0xD0, 0xDD, 0xE7, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0x81, 0x03, 0x2D, 0xE9, 0xF0, 0x47, 0x1F, 0x89, 0x80, 0x46, ++0x41, 0xF6, 0x98, 0x10, 0x87, 0x42, 0x38, 0xD9, 0xB3, 0xF8, 0x0A, 0x90, 0xD8, 0xF8, 0x94, 0xA0, 0x48, 0x46, 0x15, 0x46, ++0x8C, 0x00, 0xFD, 0xF7, 0x2F, 0xFE, 0x08, 0xB3, 0x00, 0x26, 0x20, 0x1D, 0x40, 0x44, 0xFF, 0xF7, 0x8D, 0xFC, 0x2D, 0x4A, ++0x4F, 0xF4, 0x7A, 0x73, 0x30, 0x44, 0x03, 0xFB, 0x07, 0xF3, 0xB3, 0xFB, 0xF0, 0xF3, 0x02, 0xFB, 0x03, 0xF3, 0x18, 0x0C, ++0x75, 0xB1, 0x43, 0xF2, 0x32, 0x33, 0x9F, 0x42, 0x1C, 0xD9, 0x44, 0xF6, 0xCB, 0x43, 0x9F, 0x42, 0x21, 0xD8, 0x24, 0x4B, ++0x5A, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xBD, 0xE8, 0xF0, 0x87, 0x20, 0x4E, 0x21, 0x4B, ++0xC9, 0xF3, 0xC2, 0x29, 0x4F, 0xEA, 0x1A, 0x4A, 0xB9, 0xF1, 0x06, 0x0F, 0x08, 0xBF, 0x1E, 0x46, 0xB6, 0xFB, 0xFA, 0xF6, ++0xD1, 0xE7, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x17, 0x4B, 0x1A, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, ++0x44, 0x60, 0xBD, 0xE8, 0xF0, 0x87, 0x46, 0xF2, 0x65, 0x63, 0x9F, 0x42, 0x0A, 0xD9, 0xB7, 0xF5, 0x00, 0x4F, 0x0F, 0xD2, ++0x0F, 0x4B, 0xDA, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xD5, 0xE7, 0x0B, 0x4B, 0x9A, 0x78, ++0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xCD, 0xE7, 0x49, 0xF6, 0x98, 0x13, 0x9F, 0x42, 0x06, 0x4B, ++0x94, 0xBF, 0x1A, 0x79, 0x5A, 0x79, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xC0, 0xE7, 0x00, 0xBF, ++0xB0, 0xE2, 0x0D, 0x00, 0x54, 0x25, 0x17, 0x00, 0x90, 0x53, 0x03, 0x00, 0x10, 0x09, 0x05, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x8F, 0xB0, 0x00, 0xF1, 0x88, 0x09, 0x02, 0xAD, 0x01, 0x91, 0x04, 0x46, 0x4A, 0x46, 0x07, 0x46, 0x00, 0xF1, 0x90, 0x06, ++0x29, 0x46, 0x32, 0xF8, 0x02, 0x3B, 0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0xB2, 0x42, 0x5B, 0x89, 0x21, 0xF8, ++0x02, 0x3B, 0xF4, 0xD1, 0xB4, 0xF8, 0x92, 0x10, 0x71, 0xB1, 0xD4, 0xF8, 0x94, 0x20, 0xB4, 0xF8, 0x90, 0x30, 0x02, 0xEB, ++0x42, 0x02, 0x1B, 0x04, 0x93, 0xFB, 0xF1, 0xF3, 0x13, 0x44, 0xC3, 0xF3, 0x98, 0x03, 0x00, 0x22, 0xC4, 0xE9, 0x24, 0x23, ++0x04, 0xF1, 0x7C, 0x00, 0xFE, 0xF7, 0x2A, 0xF8, 0xB4, 0xF8, 0xB4, 0x00, 0x00, 0x21, 0xA4, 0xF8, 0x7C, 0x10, 0xA4, 0xF8, ++0x7E, 0x10, 0x84, 0xF8, 0x9A, 0x10, 0x00, 0x28, 0x74, 0xD0, 0x01, 0x38, 0x05, 0xAB, 0x80, 0xB2, 0x0D, 0xF1, 0x10, 0x0A, ++0x03, 0xEB, 0x80, 0x00, 0x52, 0x46, 0x23, 0x46, 0x4F, 0xF0, 0x01, 0x0C, 0x42, 0xF8, 0x04, 0x1B, 0x82, 0x42, 0x83, 0xF8, ++0x0E, 0xC0, 0x03, 0xF1, 0x0C, 0x03, 0xF7, 0xD1, 0xB4, 0xF8, 0xBA, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, 0x14, 0xD0, ++0x32, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x6C, 0x32, 0x98, 0x47, 0x39, 0xF8, 0x02, 0x3B, 0x35, 0xF8, 0x02, 0x2B, 0x03, 0xEB, ++0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0x93, 0x42, 0x47, 0xD1, 0xB1, 0x45, 0xF2, 0xD1, 0x0F, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x4F, 0xF0, 0x00, 0x08, 0x1F, 0xFA, 0x88, 0xFB, 0x0B, 0xEB, 0x4B, 0x00, 0x04, 0xEB, 0x80, 0x00, 0x04, 0x30, ++0xFD, 0xF7, 0xE6, 0xFF, 0x01, 0x22, 0x5F, 0xFA, 0x88, 0xF1, 0x20, 0x46, 0x90, 0x44, 0xFF, 0xF7, 0x09, 0xFF, 0xB4, 0xF8, ++0xB4, 0x10, 0x0E, 0xAB, 0x03, 0xEB, 0x8B, 0x0B, 0x1F, 0xFA, 0x88, 0xF2, 0x91, 0x42, 0x4B, 0xF8, 0x28, 0x0C, 0xE4, 0xD8, ++0x51, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0x26, 0xFE, 0x51, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0x72, 0xFE, 0x01, 0x9B, 0xCB, 0xB9, ++0x94, 0xF8, 0xA2, 0x20, 0xB4, 0xF8, 0xB4, 0x30, 0x42, 0xF0, 0x40, 0x02, 0x84, 0xF8, 0xA2, 0x20, 0x83, 0xB1, 0x01, 0x3B, ++0x9B, 0xB2, 0x03, 0xEB, 0x43, 0x02, 0xDD, 0xF8, 0x04, 0x80, 0x04, 0xF1, 0x0C, 0x03, 0x03, 0xEB, 0x82, 0x03, 0xA7, 0xF8, ++0x04, 0x80, 0xA7, 0xF8, 0x06, 0x80, 0x0C, 0x37, 0x9F, 0x42, 0xF8, 0xD1, 0x00, 0x20, 0xAC, 0xE7, 0x01, 0x20, 0x0F, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xB4, 0xF8, 0xBA, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, 0x9D, 0xD1, 0x0D, 0xF1, 0x10, 0x0A, ++0xCC, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x23, 0x4B, 0x23, 0x4A, 0x1B, 0x68, 0x4F, 0xF4, 0x1E, 0x71, ++0xB3, 0xF9, 0x00, 0x30, 0x01, 0xFB, 0x00, 0x20, 0x00, 0x2B, 0xD0, 0xF8, 0x4C, 0x41, 0x2F, 0xDB, 0x20, 0x46, 0xFF, 0xF7, ++0x5D, 0xF9, 0xB4, 0xF8, 0xB4, 0x30, 0x59, 0x1E, 0x9A, 0x1E, 0x21, 0xEA, 0xE1, 0x71, 0x03, 0x3B, 0x22, 0xEA, 0xE2, 0x72, ++0x23, 0xEA, 0xE3, 0x73, 0x00, 0x25, 0x4F, 0xF4, 0x80, 0x30, 0xA4, 0xF8, 0x88, 0x10, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xF8, ++0x8A, 0x20, 0xA4, 0xF8, 0x8C, 0x30, 0xC4, 0xF8, 0x94, 0x00, 0xA4, 0xF8, 0xBA, 0x10, 0xA4, 0xF8, 0x8E, 0x50, 0x84, 0xF8, ++0xA2, 0x50, 0x01, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x13, 0xFF, 0x94, 0xF8, 0xB4, 0x30, 0x84, 0xF8, 0x9B, 0x50, 0x04, 0x3B, ++0x05, 0x22, 0x84, 0xF8, 0xA0, 0x30, 0xA4, 0xF8, 0x98, 0x20, 0x38, 0xBD, 0x00, 0x2C, 0xCD, 0xD1, 0x05, 0x49, 0x06, 0x48, ++0x40, 0xF6, 0x76, 0x02, 0xF0, 0xF7, 0xDE, 0xFD, 0xC6, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xC4, 0xA3, 0x90, 0xF8, 0x23, 0x70, ++0xDA, 0xF8, 0x00, 0x30, 0xD0, 0xF8, 0x48, 0x81, 0xB3, 0xF9, 0x00, 0x30, 0x8B, 0xB0, 0x07, 0xF1, 0x10, 0x02, 0xD2, 0xB2, ++0x00, 0x2B, 0x04, 0x46, 0x06, 0x92, 0xC0, 0xF2, 0xA9, 0x81, 0xDA, 0x4D, 0x07, 0xEB, 0x47, 0x03, 0x05, 0xEB, 0x83, 0x1B, ++0xC4, 0xF8, 0x4C, 0xB1, 0x9B, 0x01, 0x04, 0x93, 0xCD, 0xF7, 0xB4, 0xF9, 0x83, 0x03, 0x05, 0x93, 0xCD, 0xF7, 0xB0, 0xF9, ++0x4F, 0xF0, 0x01, 0x09, 0x01, 0x30, 0x09, 0xFA, 0x00, 0xF9, 0x00, 0x21, 0x58, 0x46, 0xC0, 0x22, 0xCC, 0xF7, 0xBE, 0xF8, ++0x61, 0x68, 0x11, 0xF0, 0x02, 0x01, 0x09, 0xF1, 0xFF, 0x39, 0x00, 0xF0, 0x9D, 0x80, 0x00, 0x21, 0x04, 0xF1, 0xB8, 0x00, ++0xF3, 0xF7, 0xB4, 0xFB, 0x63, 0x68, 0xAB, 0xF8, 0xAA, 0x00, 0x98, 0x06, 0x4F, 0xEA, 0x47, 0x06, 0x00, 0xF1, 0x30, 0x82, ++0x58, 0x07, 0x40, 0xF1, 0xA3, 0x81, 0xC3, 0x4B, 0x07, 0x93, 0x04, 0x23, 0xB4, 0xF8, 0xEC, 0x00, 0x8B, 0xF8, 0xA5, 0x30, ++0xCD, 0xF8, 0x24, 0xB0, 0xF3, 0xF7, 0xBA, 0xFA, 0x07, 0x9A, 0x03, 0x46, 0x10, 0x8F, 0x08, 0x93, 0xF3, 0xF7, 0xB4, 0xFA, ++0x08, 0x9B, 0x09, 0x9A, 0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xB0, 0x00, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xC0, 0x83, 0x07, 0x9B, 0xB4, 0xF8, 0xEC, 0x00, 0x19, 0x8F, 0xF3, 0xF7, 0xCA, 0xFB, ++0xF2, 0x19, 0x05, 0xEB, 0x82, 0x12, 0x03, 0x46, 0xB4, 0xF8, 0xEC, 0x00, 0xA2, 0xF8, 0xA6, 0x30, 0x09, 0x92, 0xF3, 0xF7, ++0x7D, 0xFA, 0x07, 0x9A, 0x03, 0x46, 0x10, 0x8F, 0x08, 0x93, 0xF3, 0xF7, 0x77, 0xFA, 0x08, 0x9B, 0x09, 0x9A, 0x98, 0x42, ++0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xAC, 0x00, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, ++0x91, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0x20, 0xF4, 0x7F, 0x60, 0x80, 0xB2, ++0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x96, 0xFA, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x6D, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, ++0xF3, 0xF7, 0x92, 0xFA, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x4E, 0x83, 0xB4, 0xF8, 0x54, 0x21, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, 0x83, 0xF8, ++0xB2, 0x20, 0xCD, 0xF7, 0xD1, 0xF8, 0x00, 0x28, 0x40, 0xF0, 0x04, 0x83, 0xD4, 0xF8, 0xE8, 0x30, 0x03, 0xF0, 0x03, 0x03, ++0x01, 0x2B, 0x00, 0xF0, 0xD4, 0x83, 0x02, 0x2B, 0x00, 0xF0, 0xD9, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x40, 0xF6, ++0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x88, 0xE1, 0x04, 0xF1, 0xB8, 0x00, 0xF3, 0xF7, 0x18, 0xFB, 0x07, 0xEB, 0x47, 0x03, ++0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x4D, 0xFA, 0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, ++0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x4F, 0xEA, 0x47, 0x06, 0xC0, 0xF2, 0xBC, 0x80, 0xF3, 0x19, ++0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x47, 0xFA, 0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, ++0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9E, 0x80, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, ++0xFF, 0x21, 0x83, 0xF8, 0xAC, 0x10, 0x94, 0xF8, 0x2D, 0x11, 0x83, 0xF8, 0xAF, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x83, 0x80, 0xB4, 0xF8, 0x54, 0x11, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC1, 0xF3, 0x80, 0x21, 0x83, 0xF8, ++0xB2, 0x10, 0x58, 0x46, 0x07, 0x92, 0xFE, 0xF7, 0x71, 0xFF, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x07, 0x9A, 0xA3, 0xF8, ++0xB4, 0x00, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x8D, 0x80, 0x3E, 0x44, 0x05, 0xEB, 0x86, 0x1A, 0x94, 0xF8, ++0x23, 0x30, 0x9A, 0xF8, 0xAF, 0x70, 0x9A, 0xF8, 0xB1, 0x00, 0x9A, 0xF8, 0xB2, 0x10, 0x9A, 0xF8, 0xA5, 0x20, 0xCD, 0xE9, ++0x02, 0x07, 0xCD, 0xE9, 0x00, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0x4B, 0x4A, 0x4B, 0x49, 0xF0, 0xF7, 0x6F, 0xFA, 0xBA, 0xF8, ++0xB4, 0x00, 0x9A, 0xF8, 0xAE, 0x10, 0x9A, 0xF8, 0xAD, 0x20, 0x9A, 0xF8, 0xAC, 0x30, 0xCD, 0xE9, 0x02, 0x10, 0xCD, 0xE9, ++0x00, 0x32, 0x45, 0x49, 0x42, 0x4A, 0x9A, 0xF8, 0xB0, 0x30, 0x4F, 0xF4, 0x80, 0x50, 0xF0, 0xF7, 0x5B, 0xFA, 0x94, 0xF8, ++0x23, 0x00, 0xFF, 0xF7, 0x5D, 0xFE, 0x04, 0x99, 0x88, 0x31, 0xB0, 0x01, 0x29, 0x44, 0x08, 0xF1, 0x14, 0x02, 0x08, 0xF1, ++0x24, 0x07, 0x31, 0xF8, 0x02, 0x3B, 0xDB, 0xB2, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x2B, 0x44, 0x5B, 0x89, ++0x43, 0xF0, 0x80, 0x43, 0x42, 0xF8, 0x04, 0x3B, 0x97, 0x42, 0xF0, 0xD1, 0x58, 0x46, 0x00, 0x21, 0xFF, 0xF7, 0xB4, 0xF8, ++0x32, 0x4A, 0x06, 0x99, 0x12, 0x69, 0xD4, 0xF8, 0x48, 0x31, 0x31, 0x4F, 0x31, 0x48, 0xB6, 0x01, 0x89, 0x02, 0xAA, 0x51, ++0xA2, 0x69, 0x05, 0x9D, 0xC8, 0xF8, 0x0C, 0x10, 0x4F, 0xF4, 0x08, 0x51, 0xC8, 0xE9, 0x01, 0x59, 0xC8, 0xF8, 0x00, 0x70, ++0xC8, 0xF8, 0x10, 0x00, 0xC3, 0xE9, 0x0D, 0x12, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x11, 0x03, 0x84, 0xF8, 0x56, 0x31, ++0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x29, 0x3F, 0xF4, 0x7A, 0xAF, 0x40, 0xF6, 0x21, 0x42, 0x22, 0x49, 0x23, 0x48, ++0xF0, 0xF7, 0x3C, 0xFC, 0xDA, 0xF8, 0x00, 0x20, 0x70, 0xE7, 0x0B, 0x28, 0x7F, 0xF6, 0x5F, 0xAF, 0x40, 0xF6, 0x1E, 0x42, ++0x1C, 0x49, 0x1E, 0x48, 0xF0, 0xF7, 0x30, 0xFC, 0xDA, 0xF8, 0x00, 0x20, 0x55, 0xE7, 0x0B, 0x28, 0x7F, 0xF6, 0x41, 0xAF, ++0x17, 0x49, 0x1A, 0x48, 0x40, 0xF6, 0x1C, 0x42, 0xF0, 0xF7, 0x24, 0xFC, 0x39, 0xE7, 0x00, 0x28, 0x00, 0xF0, 0xFE, 0x81, ++0x0A, 0x28, 0x7F, 0xF6, 0x6D, 0xAF, 0x11, 0x49, 0x14, 0x48, 0x40, 0xF6, 0x28, 0x42, 0xF0, 0xF7, 0x17, 0xFC, 0x65, 0xE7, ++0x09, 0x2F, 0x7F, 0xF6, 0x54, 0xAE, 0x0C, 0x49, 0x10, 0x48, 0x40, 0xF6, 0xEB, 0x22, 0xF0, 0xF7, 0x0D, 0xFC, 0x94, 0xF8, ++0x23, 0x70, 0x4A, 0xE6, 0xF4, 0xE7, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x4C, 0xCC, 0x15, 0x00, 0xC4, 0xCB, 0x15, 0x00, ++0x08, 0xCC, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1E, 0xAB, 0xDC, 0xBA, 0x04, 0x07, 0xFF, 0xFF, 0x70, 0x79, 0x15, 0x00, ++0xA8, 0xCB, 0x15, 0x00, 0x84, 0xCB, 0x15, 0x00, 0x60, 0xCB, 0x15, 0x00, 0x0C, 0xCA, 0x15, 0x00, 0x64, 0xCA, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x04, 0xF1, 0xCB, 0x03, 0x02, 0x21, 0x18, 0x46, 0x8B, 0xF8, 0xA5, 0x10, 0x09, 0x93, 0xCD, 0xF8, ++0x20, 0xB0, 0xF3, 0xF7, 0x2B, 0xF9, 0x01, 0x46, 0xD9, 0x48, 0x07, 0x91, 0xF3, 0xF7, 0x26, 0xF9, 0x07, 0x99, 0x08, 0x9A, ++0x09, 0x9B, 0x88, 0x42, 0x28, 0xBF, 0x08, 0x46, 0xDA, 0xF8, 0x00, 0x10, 0x82, 0xF8, 0xB0, 0x00, 0xB1, 0xF9, 0x00, 0x20, ++0x00, 0x2A, 0xC0, 0xF2, 0x41, 0x82, 0x04, 0x9A, 0x02, 0xF1, 0xA6, 0x00, 0x19, 0x46, 0x04, 0x22, 0x28, 0x44, 0x02, 0xF0, ++0x6B, 0xFE, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xFF, 0x22, 0xB3, 0xF8, 0xAA, 0x00, 0x83, 0xF8, 0xA6, 0x20, 0x20, 0xF4, ++0x7F, 0x60, 0x07, 0x22, 0x80, 0xB2, 0x83, 0xF8, 0xAC, 0x20, 0xA3, 0xF8, 0xAA, 0x00, 0x07, 0x93, 0xF3, 0xF7, 0x0A, 0xF9, ++0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x0F, 0x82, ++0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x06, 0xF9, 0x07, 0x9B, 0xDA, 0xF8, ++0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xF0, 0x81, 0xB4, 0xF8, 0x54, 0x21, ++0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, 0x83, 0xF8, 0xB2, 0x20, 0xCC, 0xF7, 0x45, 0xFF, 0x00, 0x28, ++0x40, 0xF0, 0x88, 0x81, 0xB4, 0xF8, 0xC8, 0x30, 0x13, 0xF4, 0x00, 0x6F, 0x06, 0xEB, 0x07, 0x03, 0x05, 0xEB, 0x83, 0x13, ++0x14, 0xBF, 0x40, 0xF6, 0xB5, 0x72, 0x40, 0xF6, 0xFF, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0xF1, 0x19, 0x05, 0xEB, 0x81, 0x11, ++0x94, 0xF8, 0x2D, 0x31, 0xDA, 0xF8, 0x00, 0x20, 0x81, 0xF8, 0xAF, 0x30, 0xB2, 0xF9, 0x00, 0x10, 0x00, 0x29, 0xC0, 0xF2, ++0x31, 0x81, 0x03, 0x2B, 0x3F, 0xF6, 0xA9, 0xAE, 0xDF, 0xE8, 0x13, 0xF0, 0x26, 0x01, 0x20, 0x01, 0x15, 0x01, 0x04, 0x01, ++0x05, 0x23, 0x94, 0xF8, 0x22, 0x10, 0xB4, 0xF8, 0x06, 0x01, 0x8B, 0xF8, 0xA5, 0x30, 0x07, 0x91, 0xCD, 0xF8, 0x24, 0xB0, ++0xF3, 0xF7, 0x8C, 0xF8, 0x95, 0x4A, 0x03, 0x46, 0xB2, 0xF8, 0x50, 0x00, 0x08, 0x93, 0xF3, 0xF7, 0x85, 0xF8, 0x08, 0x9B, ++0x09, 0x9A, 0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xB0, 0x00, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC0, 0xF2, 0xE5, 0x81, 0x8B, 0x4B, 0xB4, 0xF8, 0x06, 0x01, 0xB3, 0xF8, 0x50, 0x10, 0xF3, 0xF7, 0x9A, 0xF9, ++0xF2, 0x19, 0x05, 0xEB, 0x82, 0x12, 0x03, 0x46, 0xB4, 0xF8, 0x06, 0x01, 0xA2, 0xF8, 0xA6, 0x30, 0x09, 0x92, 0xF3, 0xF7, ++0x59, 0xF8, 0x82, 0x4A, 0x03, 0x46, 0xB2, 0xF8, 0x50, 0x00, 0x08, 0x93, 0xF3, 0xF7, 0x52, 0xF8, 0x08, 0x9B, 0x09, 0x9A, ++0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xAC, 0x00, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0xB4, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0x20, 0xF4, 0x7F, 0x60, ++0x80, 0xB2, 0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x65, 0xF8, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, ++0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x90, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, ++0xAA, 0x00, 0xF3, 0xF7, 0x61, 0xF8, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC0, 0xF2, 0x71, 0x81, 0xB4, 0xF8, 0x54, 0x21, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, ++0x83, 0xF8, 0xB2, 0x20, 0xCC, 0xF7, 0xA0, 0xFE, 0x28, 0xB1, 0x5D, 0x4B, 0x93, 0xF8, 0x43, 0x30, 0x99, 0x06, 0x00, 0xF1, ++0x99, 0x81, 0x63, 0x68, 0x5B, 0x07, 0x40, 0xF1, 0xEB, 0x80, 0xD4, 0xF8, 0xE8, 0x30, 0x03, 0xF0, 0x03, 0x03, 0x01, 0x2B, ++0x00, 0xF0, 0xBD, 0x81, 0x02, 0x2B, 0x00, 0xF0, 0xB2, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x40, 0xF6, 0xED, 0x62, ++0xA3, 0xF8, 0xB6, 0x20, 0x50, 0x4B, 0x07, 0x99, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x33, 0x93, 0xF8, 0x62, 0x20, ++0x00, 0x2A, 0x40, 0xF0, 0xDF, 0x80, 0xD3, 0xF8, 0xC8, 0x31, 0xD4, 0xF8, 0x48, 0x01, 0x13, 0xF4, 0x80, 0x3F, 0xC1, 0x6B, ++0x40, 0xF0, 0x69, 0x81, 0x41, 0xF0, 0x20, 0x01, 0x00, 0x2B, 0xC1, 0x63, 0x06, 0xDB, 0xC3, 0xF3, 0x05, 0x63, 0x49, 0xEA, ++0x03, 0x59, 0x02, 0x2A, 0x00, 0xF0, 0x58, 0x81, 0x49, 0xF0, 0x80, 0x59, 0x49, 0xF4, 0xC0, 0x29, 0x3D, 0x4B, 0x93, 0xF8, ++0x45, 0x10, 0x94, 0xF8, 0xFD, 0x30, 0x01, 0xF0, 0x03, 0x00, 0xC3, 0xF3, 0xC1, 0x03, 0x83, 0x42, 0x06, 0xEB, 0x07, 0x02, ++0x28, 0xBF, 0x03, 0x46, 0x05, 0xEB, 0x82, 0x12, 0x01, 0x20, 0x83, 0x42, 0x82, 0xF8, 0xBC, 0x00, 0x00, 0xF0, 0x6A, 0x81, ++0x02, 0x2B, 0x00, 0xF0, 0x64, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0x68, 0x81, 0x04, 0x23, 0x82, 0xF8, 0xBD, 0x30, 0x2E, 0x4B, ++0x94, 0xF8, 0xFD, 0xC0, 0x93, 0xF8, 0x4B, 0x00, 0x93, 0xF8, 0x4A, 0x20, 0x8B, 0x08, 0xF1, 0x19, 0x03, 0xEA, 0x5C, 0x13, ++0x05, 0xEB, 0x81, 0x11, 0x03, 0xF0, 0x01, 0x03, 0x81, 0xF8, 0xBE, 0x30, 0x94, 0xF8, 0x03, 0xC1, 0x94, 0xF8, 0x02, 0x31, ++0x0C, 0xF0, 0x01, 0x0C, 0x9B, 0x11, 0x00, 0xF0, 0x01, 0x00, 0x92, 0x11, 0x43, 0xEA, 0x8C, 0x03, 0x42, 0xEA, 0x80, 0x02, ++0x93, 0x42, 0x28, 0xBF, 0x13, 0x46, 0x81, 0xF8, 0xBF, 0x30, 0xE8, 0xE6, 0xD4, 0xF8, 0xE8, 0x30, 0x59, 0x06, 0x7F, 0xF5, ++0x9E, 0xAD, 0x19, 0x4B, 0x9B, 0x89, 0x5B, 0x06, 0x7F, 0xF5, 0x99, 0xAD, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x01, 0x21, ++0x83, 0xF8, 0xB1, 0x10, 0x91, 0xE5, 0xD4, 0xF8, 0xE8, 0x30, 0x9B, 0x06, 0x7F, 0xF5, 0x8D, 0xAD, 0x10, 0x4B, 0x9B, 0x89, ++0x98, 0x06, 0x7F, 0xF5, 0x88, 0xAD, 0xED, 0xE7, 0xB4, 0xF8, 0xC8, 0x30, 0x59, 0x06, 0x7F, 0xF5, 0x82, 0xAD, 0xE2, 0xE7, ++0xB4, 0xF8, 0xC8, 0x30, 0x98, 0x06, 0x7F, 0xF5, 0x7C, 0xAD, 0xED, 0xE7, 0x03, 0x2B, 0x7F, 0xF6, 0xCC, 0xAE, 0x40, 0xF6, ++0xF9, 0x32, 0x07, 0x49, 0x07, 0x48, 0xF0, 0xF7, 0x31, 0xFA, 0x94, 0xF8, 0x2D, 0x31, 0xDA, 0xF8, 0x00, 0x20, 0xC0, 0xE6, ++0xF3, 0xB8, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x34, 0xCA, 0x15, 0x00, ++0x40, 0xF6, 0x27, 0x42, 0x88, 0x49, 0x89, 0x48, 0x07, 0x93, 0xF0, 0xF7, 0x1B, 0xFA, 0xDA, 0xF8, 0x00, 0x20, 0xB2, 0xF9, ++0x00, 0x20, 0x00, 0x2A, 0xBF, 0xF6, 0x64, 0xAD, 0x07, 0x9B, 0xB3, 0xF8, 0xB4, 0x00, 0xEF, 0xE5, 0x07, 0x9B, 0x1B, 0x6B, ++0x13, 0xF0, 0x10, 0x0F, 0xD4, 0xF8, 0xE8, 0x30, 0x3F, 0xF4, 0xF6, 0xAC, 0xD9, 0x06, 0x7F, 0xF5, 0xF3, 0xAC, 0x05, 0x9A, ++0x42, 0xF0, 0x40, 0x02, 0x05, 0x92, 0xED, 0xE4, 0x7A, 0x4B, 0x9B, 0x89, 0x13, 0xF0, 0x01, 0x0F, 0xB4, 0xF8, 0xC8, 0x30, ++0x3F, 0xF4, 0x72, 0xAE, 0xDA, 0x07, 0x7F, 0xF5, 0x6F, 0xAE, 0x05, 0x9A, 0x42, 0xF0, 0x40, 0x02, 0x05, 0x92, 0x69, 0xE6, ++0xB4, 0xF8, 0xC8, 0x30, 0x13, 0xF4, 0x00, 0x6F, 0x06, 0xEB, 0x07, 0x03, 0x05, 0xEB, 0x83, 0x13, 0x14, 0xBF, 0x41, 0xF6, ++0xFF, 0x62, 0x40, 0xF6, 0xFF, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x15, 0xE7, 0xD4, 0xF8, 0x48, 0x01, 0xD3, 0xF8, 0xC8, 0x31, ++0xC1, 0x6B, 0x00, 0x2B, 0x21, 0xF0, 0x20, 0x01, 0xC1, 0x63, 0xBF, 0xF6, 0x24, 0xAF, 0x26, 0xE7, 0x03, 0x28, 0x7F, 0xF6, ++0xAF, 0xAC, 0x0C, 0x28, 0x3F, 0xF4, 0xAC, 0xAC, 0x5F, 0x49, 0x62, 0x48, 0x40, 0xF6, 0xA2, 0x32, 0xF0, 0xF7, 0xC8, 0xF9, ++0xA4, 0xE4, 0x03, 0x28, 0x7F, 0xF6, 0x90, 0xAC, 0x0C, 0x28, 0x3F, 0xF4, 0x8D, 0xAC, 0x59, 0x49, 0x5C, 0x48, 0x4F, 0xF4, ++0x3A, 0x62, 0xF0, 0xF7, 0xBB, 0xF9, 0x85, 0xE4, 0x09, 0x28, 0x7F, 0xF6, 0x6C, 0xAC, 0x54, 0x49, 0x58, 0x48, 0x40, 0xF6, ++0x94, 0x32, 0xF0, 0xF7, 0xB1, 0xF9, 0x64, 0xE4, 0x07, 0x28, 0x7F, 0xF6, 0x3D, 0xAC, 0x4F, 0x49, 0x54, 0x48, 0x40, 0xF6, ++0x8E, 0x32, 0xF0, 0xF7, 0xA7, 0xF9, 0x35, 0xE4, 0x03, 0x28, 0x7F, 0xF6, 0x0D, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, 0x0A, 0xAE, ++0x48, 0x49, 0x4B, 0x48, 0x40, 0xF6, 0xD9, 0x32, 0xF0, 0xF7, 0x9A, 0xF9, 0x02, 0xE6, 0x03, 0x28, 0x7F, 0xF6, 0xEE, 0xAD, ++0x0C, 0x28, 0x3F, 0xF4, 0xEB, 0xAD, 0x42, 0x49, 0x45, 0x48, 0x40, 0xF6, 0xD7, 0x32, 0xF0, 0xF7, 0x8D, 0xF9, 0xE3, 0xE5, ++0x03, 0x28, 0x7F, 0xF6, 0xBC, 0xAD, 0x3D, 0x49, 0x43, 0x48, 0x07, 0x93, 0x40, 0xF6, 0xCC, 0x32, 0xF0, 0xF7, 0x82, 0xF9, ++0x07, 0x9B, 0xB2, 0xE5, 0x03, 0x28, 0x7F, 0xF6, 0x8C, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, 0x89, 0xAE, 0x35, 0x49, 0x38, 0x48, ++0x40, 0xF6, 0x22, 0x32, 0xF0, 0xF7, 0x74, 0xF9, 0x81, 0xE6, 0x03, 0x28, 0x7F, 0xF6, 0x6D, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, ++0x6A, 0xAE, 0x2F, 0x49, 0x32, 0x48, 0x4F, 0xF4, 0x32, 0x62, 0xF0, 0xF7, 0x67, 0xF9, 0x62, 0xE6, 0x0B, 0x28, 0x7F, 0xF6, ++0x49, 0xAE, 0x2A, 0x49, 0x31, 0x48, 0x40, 0xF6, 0x1C, 0x32, 0xF0, 0xF7, 0x5D, 0xF9, 0x41, 0xE6, 0x07, 0x28, 0x7F, 0xF6, ++0x18, 0xAE, 0x25, 0x49, 0x2A, 0x48, 0x40, 0xF6, 0x16, 0x32, 0xF0, 0xF7, 0x53, 0xF9, 0x10, 0xE6, 0x49, 0xF0, 0x80, 0x59, ++0x49, 0xF4, 0x00, 0x39, 0xA6, 0xE6, 0x21, 0xF0, 0x20, 0x01, 0x00, 0x2B, 0xC1, 0x63, 0xBF, 0xF6, 0x96, 0xAE, 0x9B, 0xE6, ++0x94, 0xF8, 0x2D, 0x31, 0x23, 0xB9, 0x94, 0xF8, 0xFB, 0x30, 0x9A, 0x06, 0x7F, 0xF5, 0x5F, 0xAE, 0x05, 0x9B, 0x43, 0xF0, ++0x40, 0x03, 0x05, 0x93, 0x59, 0xE6, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x41, 0xF6, 0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, ++0xB7, 0xE5, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x42, 0xF6, 0x74, 0x42, 0xA3, 0xF8, 0xB6, 0x20, 0xAF, 0xE5, 0x82, 0xF8, ++0xBD, 0x00, 0x9E, 0xE6, 0x00, 0x23, 0x82, 0xF8, 0xBD, 0x30, 0x9A, 0xE6, 0x82, 0xF8, 0xBC, 0x30, 0xA5, 0xE5, 0xF3, 0x19, ++0x05, 0xEB, 0x83, 0x13, 0x42, 0xF6, 0x74, 0x42, 0xA3, 0xF8, 0xB6, 0x20, 0x4C, 0xE6, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, ++0x41, 0xF6, 0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x44, 0xE6, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0xF4, 0xC9, 0x15, 0x00, ++0xE4, 0xB8, 0x17, 0x00, 0xE8, 0xCA, 0x15, 0x00, 0x98, 0xCA, 0x15, 0x00, 0x38, 0xCB, 0x15, 0x00, 0x50, 0xCA, 0x15, 0x00, ++0x4C, 0xCB, 0x15, 0x00, 0x84, 0xCA, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x46, 0x7F, 0x09, 0x2E, 0x83, 0xB0, 0x04, 0x46, ++0x00, 0xF2, 0x8D, 0x80, 0x4B, 0x4B, 0x4C, 0x4F, 0x1A, 0x68, 0x4F, 0xF4, 0x1E, 0x73, 0xB2, 0xF9, 0x00, 0x20, 0x03, 0xFB, ++0x06, 0x73, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x40, 0xDB, 0x95, 0xF8, 0xA2, 0x30, 0x59, 0x07, 0x34, 0xD4, 0x03, 0xF0, ++0xFD, 0x03, 0x4F, 0xF0, 0x00, 0x08, 0xDF, 0xF8, 0x18, 0x91, 0x85, 0xF8, 0xA2, 0x30, 0xD9, 0xF8, 0x10, 0x30, 0x2A, 0x68, ++0x3F, 0x49, 0x9B, 0x1A, 0x8B, 0x42, 0x36, 0xD8, 0x95, 0xF8, 0xA3, 0x20, 0x95, 0xF8, 0xA4, 0x30, 0x43, 0xEA, 0x82, 0x03, ++0x84, 0xF8, 0x36, 0x30, 0x28, 0x46, 0xFE, 0xF7, 0x65, 0xFF, 0xB0, 0xB1, 0xE2, 0x8B, 0x94, 0xF8, 0x36, 0x30, 0x42, 0xF4, ++0x00, 0x52, 0x23, 0xF0, 0x03, 0x03, 0xE2, 0x83, 0x84, 0xF8, 0x36, 0x30, 0xB8, 0xF1, 0x00, 0x0F, 0x59, 0xD1, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x06, 0x76, 0x96, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x20, 0x03, 0x86, 0xF8, 0x56, 0x31, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0x62, 0x6A, 0x92, 0x02, 0xC7, 0xD5, 0x43, 0xF0, 0x02, 0x03, 0x4F, 0xF0, 0x01, 0x08, 0xC6, 0xE7, ++0x00, 0x2D, 0xBC, 0xD1, 0x26, 0x49, 0x27, 0x48, 0x40, 0xF6, 0x9A, 0x22, 0xF0, 0xF7, 0x9E, 0xF8, 0xB5, 0xE7, 0x00, 0x21, ++0x28, 0x46, 0xFF, 0xF7, 0xBB, 0xF9, 0x95, 0xF8, 0xA3, 0x30, 0x01, 0x33, 0x00, 0x22, 0x03, 0xF0, 0x07, 0x03, 0x85, 0xF8, ++0xA3, 0x30, 0x85, 0xF8, 0x9B, 0x20, 0x85, 0xF8, 0xA4, 0x20, 0xD9, 0xF8, 0x10, 0x20, 0x2A, 0x60, 0x9B, 0x00, 0x84, 0xF8, ++0x36, 0x30, 0x00, 0x28, 0xB8, 0xD0, 0x0D, 0xF1, 0x07, 0x01, 0x28, 0x46, 0xFE, 0xF7, 0xCE, 0xFC, 0x9D, 0xF8, 0x07, 0x30, ++0x53, 0xB9, 0x62, 0x6A, 0x22, 0xF4, 0x00, 0x12, 0x62, 0x62, 0x95, 0xF8, 0xA2, 0x20, 0x22, 0xF0, 0x02, 0x02, 0x98, 0x46, ++0x85, 0xF8, 0xA2, 0x20, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0x73, 0x93, 0xF8, 0x56, 0x21, 0x42, 0xF0, 0x11, 0x02, ++0x83, 0xF8, 0x56, 0x21, 0x9A, 0xE7, 0x00, 0x23, 0x80, 0xF8, 0x36, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x63, 0x6A, ++0x43, 0xF4, 0x20, 0x13, 0x63, 0x62, 0xA0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xA0, 0x86, 0x01, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0xB4, 0xCA, 0x0A, 0x12, 0xF0, 0x06, 0x0F, ++0x9D, 0xF8, 0x08, 0x50, 0x9D, 0xF8, 0x14, 0x40, 0x20, 0xD0, 0x02, 0xF0, 0x07, 0x02, 0x01, 0xF0, 0x7F, 0x01, 0x04, 0x2A, ++0x0C, 0xBF, 0x09, 0x09, 0xC1, 0xF3, 0xC1, 0x01, 0x4B, 0xB9, 0xC3, 0x6B, 0x23, 0xF0, 0x04, 0x03, 0xC3, 0x63, 0x64, 0xB1, ++0x43, 0xF0, 0x10, 0x03, 0x30, 0xBC, 0xC3, 0x63, 0x70, 0x47, 0xA9, 0x42, 0xF3, 0xD1, 0xC3, 0x6B, 0x43, 0xF0, 0x04, 0x03, ++0xC3, 0x63, 0x00, 0x2C, 0xF2, 0xD1, 0x23, 0xF0, 0x10, 0x03, 0x30, 0xBC, 0xC3, 0x63, 0x70, 0x47, 0xC3, 0x6B, 0x23, 0xF0, ++0x10, 0x03, 0xF8, 0xE7, 0x0B, 0x7B, 0x05, 0x2B, 0x0E, 0xD1, 0x2D, 0xE9, 0xF0, 0x41, 0x4B, 0x7B, 0x84, 0xB0, 0x0C, 0x46, ++0x01, 0xF1, 0x0C, 0x07, 0x13, 0xB9, 0x0D, 0x88, 0x09, 0x2D, 0x05, 0xDC, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, ++0x00, 0x20, 0x70, 0x47, 0x0B, 0x20, 0x97, 0xF8, 0x02, 0x80, 0x7E, 0x7A, 0xEE, 0xF7, 0xC8, 0xF9, 0x08, 0xBB, 0xFB, 0x78, ++0x3B, 0xBB, 0x69, 0x1F, 0x04, 0xF1, 0x11, 0x00, 0x1D, 0x46, 0x01, 0x22, 0x07, 0x78, 0x43, 0x78, 0x26, 0x2F, 0x03, 0xF1, ++0x02, 0x03, 0x14, 0xD1, 0x8B, 0x42, 0xA1, 0xEB, 0x03, 0x01, 0x10, 0xDC, 0x05, 0xB9, 0x03, 0x90, 0x02, 0x29, 0x18, 0x44, ++0x4F, 0xF0, 0x01, 0x05, 0xEE, 0xDC, 0x00, 0x92, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x03, 0xAB, 0x00, 0xF0, 0x1A, 0xFD, ++0x01, 0xF0, 0x52, 0xF8, 0xD0, 0xE7, 0x00, 0x96, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x04, 0x23, 0x00, 0xF0, 0xF4, 0xFC, ++0xC8, 0xE7, 0x00, 0x96, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x02, 0x23, 0x00, 0xF0, 0xEC, 0xFC, 0xC0, 0xE7, 0x00, 0xBF, ++0x08, 0xB5, 0x0B, 0x20, 0xEE, 0xF7, 0x90, 0xF9, 0x01, 0x28, 0x07, 0xD0, 0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x05, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x01, 0xF0, 0xEA, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x04, 0x49, 0x05, 0x48, ++0x9D, 0x22, 0xEF, 0xF7, 0xD5, 0xFF, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x08, 0xB5, 0x0B, 0x20, 0xEE, 0xF7, 0x70, 0xF9, 0x04, 0x28, 0x07, 0xD0, 0x09, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x01, 0xF0, 0x3E, 0xF8, 0x00, 0x20, 0x08, 0xBD, ++0x04, 0x49, 0x05, 0x48, 0x81, 0x22, 0xEF, 0xF7, 0xB5, 0xFF, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x3A, 0xB3, 0x93, 0x68, 0x10, 0xB4, 0x93, 0xB9, 0x54, 0x69, 0x64, 0xB1, ++0xFF, 0x28, 0x22, 0xD1, 0x00, 0x2C, 0x1A, 0xDD, 0x18, 0x32, 0x10, 0x19, 0x01, 0xE0, 0x82, 0x42, 0x15, 0xD0, 0x12, 0xF8, ++0x01, 0x3B, 0x99, 0x42, 0xF9, 0xD1, 0x01, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xFF, 0x28, 0x13, 0xD0, 0x00, 0x2B, ++0x09, 0xDD, 0x0C, 0x32, 0x13, 0x44, 0x01, 0xE0, 0x9A, 0x42, 0x04, 0xD0, 0x12, 0xF8, 0x01, 0x1B, 0x81, 0x42, 0xF9, 0xD1, ++0xED, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x18, 0x46, 0xE6, 0xE7, 0x54, 0x69, ++0xD8, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x0A, 0x4D, 0x41, 0xF2, 0x98, 0x74, 0x2B, 0x59, 0x63, 0xB1, 0x0B, 0x20, 0xEE, 0xF7, ++0x1B, 0xF9, 0x03, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x38, 0xBD, 0x2B, 0x59, 0x18, 0x68, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, ++0x38, 0xBD, 0x01, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x78, 0xEF, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0x46, 0x80, 0x6C, ++0x89, 0xB0, 0x14, 0x46, 0x99, 0x46, 0x00, 0xF1, 0x68, 0x05, 0x00, 0x29, 0x3B, 0xD1, 0xB0, 0xF8, 0x68, 0x10, 0xBE, 0x4A, ++0xB2, 0xF8, 0xFC, 0x31, 0x01, 0x33, 0x9B, 0xB2, 0x1E, 0x01, 0xA2, 0xF8, 0xFC, 0x31, 0xA0, 0xF8, 0x7E, 0x60, 0x05, 0x22, ++0x58, 0x46, 0xFC, 0xF7, 0x53, 0xFA, 0x01, 0x28, 0x00, 0xF0, 0xC8, 0x80, 0x1B, 0x23, 0x03, 0x93, 0x18, 0x23, 0xE9, 0x18, ++0x05, 0x22, 0xEA, 0x54, 0x01, 0x22, 0x4A, 0x70, 0x99, 0xF8, 0x00, 0x20, 0x8A, 0x70, 0x01, 0xF1, 0x03, 0x0A, 0x00, 0x2C, ++0x7B, 0xD0, 0x03, 0x22, 0x27, 0x20, 0xC8, 0x70, 0x0A, 0x71, 0x99, 0xF8, 0x01, 0x20, 0x4A, 0x71, 0x8C, 0x71, 0x99, 0xF8, ++0x02, 0x20, 0xCA, 0x71, 0x08, 0x33, 0xDB, 0xF8, 0x4C, 0x00, 0x9B, 0xF8, 0x35, 0x20, 0x41, 0x6A, 0x13, 0x44, 0x01, 0x39, ++0x19, 0x44, 0x04, 0x33, 0xC0, 0xE9, 0x0A, 0x13, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA2, 0x4B, 0xA2, 0x4E, 0x00, 0x22, ++0x41, 0xF2, 0xA8, 0x7C, 0x6F, 0xF0, 0x2F, 0x01, 0x80, 0xF8, 0x69, 0x20, 0x80, 0xF8, 0x6A, 0x20, 0x80, 0xF8, 0x6B, 0x20, ++0x80, 0xF8, 0x68, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x9B, 0x4A, 0x4F, 0xF4, 0x1E, 0x77, 0x07, 0xFB, 0x01, 0xF1, 0x41, 0xF2, ++0xA9, 0x78, 0x89, 0x5B, 0xA0, 0xF8, 0x6C, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x07, 0xFB, 0x01, 0x61, 0x4F, 0xF4, 0xA4, 0x6E, ++0x49, 0x88, 0xA0, 0xF8, 0x6E, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x07, 0xFB, 0x01, 0x61, 0x89, 0x88, 0xA0, 0xF8, 0x70, 0x10, ++0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0xF1, 0x89, 0x5A, 0xA0, 0xF8, 0x72, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, ++0x01, 0x21, 0x49, 0x88, 0xA0, 0xF8, 0x74, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0x21, 0x89, 0x88, 0xA0, 0xF8, ++0x76, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0xF1, 0x02, 0xEB, 0x01, 0x0A, 0x9A, 0xF8, 0x06, 0xA0, 0xBA, 0xF1, ++0x02, 0x0F, 0x5F, 0xD0, 0x13, 0xF8, 0x0C, 0x20, 0x07, 0xFB, 0x02, 0xF2, 0xD0, 0x21, 0x92, 0x5B, 0xA0, 0xF8, 0x78, 0x20, ++0x13, 0xF8, 0x0C, 0x20, 0x07, 0xFB, 0x02, 0x62, 0x52, 0x88, 0xA0, 0xF8, 0x7A, 0x20, 0x13, 0xF8, 0x0C, 0x30, 0x07, 0xFB, ++0x03, 0x66, 0xB3, 0x88, 0xA0, 0xF8, 0x7C, 0x30, 0x63, 0xE7, 0x03, 0x9B, 0x01, 0x94, 0xC3, 0xF5, 0xC0, 0x73, 0x9B, 0xB2, ++0x02, 0x93, 0xCD, 0xF8, 0x14, 0xB0, 0x99, 0xF8, 0x02, 0x30, 0x02, 0x9A, 0x05, 0x2B, 0xA2, 0xF1, 0x05, 0x04, 0xA4, 0xB2, ++0x00, 0xF0, 0xE2, 0x80, 0x27, 0x23, 0x8A, 0xF8, 0x00, 0x30, 0x99, 0xF8, 0x01, 0x30, 0x8A, 0xF8, 0x02, 0x30, 0x00, 0x23, ++0x8A, 0xF8, 0x03, 0x30, 0x99, 0xF8, 0x02, 0x30, 0x8A, 0xF8, 0x04, 0x30, 0x05, 0x2B, 0x3A, 0xD0, 0x03, 0x23, 0x8A, 0xF8, ++0x01, 0x30, 0x02, 0x94, 0x0A, 0xF1, 0x05, 0x0A, 0x05, 0x25, 0xFF, 0xF7, 0x15, 0xFF, 0x01, 0x9B, 0x2B, 0x44, 0x01, 0x93, ++0x08, 0xB9, 0x04, 0x2C, 0xD7, 0xD8, 0x5C, 0x4B, 0xDD, 0xF8, 0x14, 0xB0, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x9D, 0x80, 0x01, 0x9B, 0x03, 0x9A, 0x13, 0x44, 0x52, 0xE7, 0x18, 0x22, 0x29, 0x46, 0x58, 0x46, 0xFA, 0xF7, ++0xE7, 0xFF, 0x9B, 0xF8, 0x33, 0x20, 0x02, 0xF1, 0x18, 0x03, 0x1B, 0x32, 0x03, 0x92, 0x2E, 0xE7, 0x89, 0x5A, 0xA0, 0xF8, ++0x78, 0x10, 0x13, 0xF8, 0x08, 0x60, 0x0E, 0xFB, 0x06, 0x26, 0xD0, 0x21, 0x76, 0x88, 0xA0, 0xF8, 0x7A, 0x60, 0x13, 0xF8, ++0x08, 0x30, 0x0E, 0xFB, 0x03, 0x22, 0x93, 0x88, 0xA0, 0xF8, 0x7C, 0x30, 0x07, 0xE7, 0xD9, 0xF8, 0x5C, 0x20, 0x46, 0x49, ++0x01, 0x32, 0x0D, 0x68, 0xC9, 0xF8, 0x5C, 0x20, 0x0A, 0xF1, 0x05, 0x02, 0x04, 0x92, 0x00, 0x2D, 0x00, 0xF0, 0x45, 0x81, ++0xEB, 0x7C, 0x8A, 0xF8, 0x05, 0x30, 0x2B, 0x7C, 0x8A, 0xF8, 0x06, 0x30, 0xD9, 0xE9, 0x0A, 0x12, 0xB9, 0xF8, 0x30, 0x30, ++0xAA, 0xF8, 0x0F, 0x30, 0xCA, 0xF8, 0x07, 0x10, 0xCA, 0xF8, 0x0B, 0x20, 0xAB, 0x7C, 0x8A, 0xF8, 0x11, 0x30, 0x95, 0xF9, ++0x14, 0x00, 0xEE, 0xF7, 0x21, 0xFF, 0xFF, 0x23, 0x8A, 0xF8, 0x12, 0x00, 0x8A, 0xF8, 0x13, 0x30, 0x05, 0xF1, 0x0C, 0x00, ++0xAB, 0x1D, 0x13, 0xF8, 0x01, 0x1B, 0x03, 0xF1, 0x0D, 0x02, 0x52, 0x1B, 0x83, 0x42, 0x02, 0xF8, 0x0A, 0x10, 0xF6, 0xD1, ++0x6B, 0x7C, 0x8A, 0xF8, 0x1A, 0x30, 0x02, 0x9A, 0xEB, 0x68, 0xCA, 0xF8, 0x1B, 0x30, 0x40, 0xF2, 0x01, 0x14, 0x94, 0x42, ++0x99, 0xF8, 0x20, 0x30, 0x28, 0xBF, 0x14, 0x46, 0x0A, 0xF1, 0x1F, 0x02, 0xA4, 0xB2, 0x04, 0x92, 0x00, 0x2B, 0x40, 0xF0, ++0x05, 0x81, 0x1F, 0x3C, 0xA4, 0xB2, 0x99, 0xF8, 0x04, 0x30, 0x00, 0x2B, 0x6D, 0xD1, 0x6B, 0x8B, 0x2B, 0x83, 0x03, 0x23, ++0x1D, 0x48, 0xAB, 0x80, 0x29, 0x46, 0xEE, 0xF7, 0xEB, 0xF9, 0x99, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x12, 0x81, ++0x04, 0x9B, 0x02, 0x9A, 0xA3, 0xEB, 0x0A, 0x05, 0xAB, 0x1E, 0x8A, 0xF8, 0x01, 0x30, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x54, 0x1B, 0x00, 0x2B, 0xA4, 0xB2, 0x80, 0xF2, 0xF9, 0x80, 0xAA, 0x42, 0x80, 0xF0, 0xF6, 0x80, 0x10, 0x49, ++0x10, 0x48, 0xDD, 0xF8, 0x10, 0xA0, 0x40, 0xF2, 0x07, 0x52, 0xEF, 0xF7, 0xCF, 0xFD, 0x02, 0x94, 0x51, 0xE7, 0x01, 0x9B, ++0x00, 0x2B, 0x7F, 0xF4, 0x5F, 0xAF, 0x09, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0x12, 0x52, 0xEF, 0xF7, 0xDB, 0xFD, 0x57, 0xE7, ++0x20, 0x62, 0x17, 0x00, 0x78, 0xEF, 0x17, 0x00, 0x8E, 0x65, 0x17, 0x00, 0x74, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x10, 0x07, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF4, 0xD0, 0x15, 0x00, 0x0C, 0xD1, 0x15, 0x00, 0x94, 0x4B, 0x1A, 0x68, ++0x00, 0x2A, 0x3F, 0xF4, 0x19, 0xAF, 0x19, 0x2C, 0x7F, 0xF6, 0x35, 0xAF, 0x02, 0x98, 0x99, 0xF8, 0x20, 0x10, 0xA0, 0xF1, ++0x1F, 0x03, 0x9B, 0xB2, 0x29, 0xB1, 0x02, 0x2B, 0x7F, 0xF6, 0x2B, 0xAF, 0xA0, 0xF1, 0x22, 0x03, 0x9B, 0xB2, 0x99, 0xF8, ++0x04, 0x10, 0x00, 0x29, 0x3F, 0xF4, 0x04, 0xAF, 0x03, 0x2B, 0x7F, 0xF6, 0x20, 0xAF, 0x10, 0x8B, 0x04, 0x3B, 0x9D, 0xB2, ++0x00, 0x28, 0x40, 0xF0, 0xCF, 0x80, 0x0D, 0x2D, 0x3F, 0xF6, 0xF8, 0xAE, 0x15, 0xE7, 0x04, 0x9A, 0x01, 0x23, 0x13, 0x70, ++0x2B, 0x8B, 0xA2, 0x1F, 0x92, 0xB2, 0x0A, 0xF1, 0x21, 0x01, 0x0B, 0x2B, 0x06, 0x92, 0x8C, 0x46, 0x1B, 0xD8, 0x7C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xAE, 0x80, 0x05, 0xF1, 0x1C, 0x02, 0x05, 0xF1, 0x28, 0x00, ++0x13, 0x46, 0x05, 0x33, 0x12, 0xF8, 0x01, 0x1B, 0x5B, 0x1B, 0x82, 0x42, 0x03, 0xF8, 0x0A, 0x10, 0xF6, 0xD1, 0x0C, 0x23, ++0x12, 0x3C, 0xA2, 0xB2, 0x2B, 0x83, 0x0A, 0xF1, 0x2D, 0x03, 0x06, 0x92, 0x9C, 0x46, 0x99, 0xF8, 0x04, 0x30, 0x01, 0x2B, ++0x3A, 0xD0, 0x2B, 0x8B, 0x6E, 0x8B, 0xF6, 0x1A, 0x05, 0xF1, 0x1C, 0x07, 0xB6, 0xB2, 0x1F, 0x44, 0x00, 0x2E, 0x3B, 0xD0, ++0xCD, 0xF8, 0x1C, 0xA0, 0xE3, 0x46, 0xAA, 0x46, 0x09, 0xE0, 0xBA, 0xF8, 0x18, 0x10, 0x36, 0x1B, 0xB6, 0xB2, 0x0C, 0x44, ++0x2F, 0x44, 0xAA, 0xF8, 0x18, 0x40, 0x00, 0x2E, 0x5D, 0xD0, 0x97, 0xF8, 0x00, 0x80, 0xB9, 0x78, 0x7C, 0x78, 0x40, 0x46, ++0x4A, 0x46, 0xFF, 0xF7, 0xA9, 0xFD, 0xA5, 0x1C, 0x02, 0x34, 0xED, 0xB2, 0xE4, 0xB2, 0x00, 0x28, 0xE7, 0xD0, 0xD9, 0x2D, ++0xE5, 0xD8, 0x06, 0x9B, 0x9C, 0x42, 0x4A, 0xD8, 0x4D, 0xB1, 0x59, 0x46, 0x78, 0x1A, 0xAB, 0x44, 0x01, 0xE0, 0x10, 0xF8, ++0x01, 0x80, 0x01, 0xF8, 0x01, 0x8B, 0x8B, 0x45, 0xF9, 0xD1, 0x06, 0x9B, 0x1B, 0x1B, 0x9B, 0xB2, 0x06, 0x93, 0xD2, 0xE7, ++0xD9, 0xF8, 0x08, 0x30, 0x00, 0x2B, 0xC0, 0xD1, 0xD9, 0xF8, 0x14, 0x30, 0x00, 0x2B, 0xBC, 0xD1, 0x6B, 0x8B, 0x2B, 0x83, ++0x04, 0x9B, 0xC3, 0xF1, 0xFE, 0x0B, 0xE3, 0x44, 0x02, 0x23, 0x8A, 0xF8, 0x20, 0xB0, 0x8C, 0xF8, 0x00, 0x30, 0x8C, 0xF8, ++0x01, 0x30, 0xEA, 0x7D, 0x28, 0x8B, 0x69, 0x8B, 0x99, 0xF8, 0x01, 0x30, 0x54, 0x1C, 0x88, 0x42, 0x66, 0x46, 0xEC, 0x75, ++0x43, 0xEA, 0x02, 0x23, 0x23, 0xD2, 0x6F, 0xEA, 0x43, 0x43, 0x6F, 0xEA, 0x53, 0x43, 0xAC, 0xF8, 0x02, 0x30, 0x33, 0x1D, ++0x04, 0x93, 0x08, 0xE7, 0x22, 0x3C, 0xA4, 0xB2, 0xF9, 0xE6, 0x03, 0x22, 0x8A, 0xF8, 0x01, 0x20, 0x36, 0x4A, 0x12, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x09, 0xDB, 0xDD, 0xF8, 0x10, 0xA0, 0x02, 0x94, 0x1D, 0x46, 0x6B, 0xE6, 0x55, 0x46, ++0xDC, 0x46, 0xDD, 0xF8, 0x1C, 0xA0, 0xC9, 0xE7, 0x1D, 0x46, 0xDD, 0xF8, 0x10, 0xA0, 0x02, 0x94, 0x61, 0xE6, 0xAC, 0xF8, ++0x02, 0x30, 0x33, 0x1D, 0x04, 0x93, 0xE2, 0xE6, 0x04, 0x9D, 0xA4, 0x23, 0x01, 0x24, 0x2B, 0x70, 0x6C, 0x70, 0xFF, 0xF7, ++0x6D, 0xFD, 0x20, 0xB1, 0xAC, 0x70, 0x04, 0x9B, 0x03, 0x33, 0x04, 0x93, 0xE0, 0xE6, 0x04, 0x9B, 0x98, 0x70, 0xF8, 0xE7, ++0x0B, 0x2A, 0x3F, 0xF6, 0x4F, 0xAF, 0x21, 0x49, 0x21, 0x48, 0x40, 0xF2, 0x7D, 0x42, 0xEF, 0xF7, 0xBF, 0xFC, 0x47, 0xE7, ++0xB2, 0xF8, 0x1A, 0x80, 0x01, 0x29, 0x02, 0xF1, 0x1C, 0x02, 0xA8, 0xEB, 0x00, 0x08, 0x02, 0xEB, 0x00, 0x07, 0x08, 0xD0, ++0xB8, 0xF1, 0x00, 0x0F, 0x1B, 0xD0, 0x7B, 0x78, 0x03, 0x33, 0xAB, 0x42, 0xFF, 0xF6, 0x1A, 0xAE, 0x37, 0xE6, 0x7E, 0x78, ++0x10, 0x5C, 0x97, 0xF8, 0x02, 0xB0, 0x02, 0x36, 0xF6, 0xB2, 0x03, 0xE0, 0x7E, 0x78, 0x38, 0x78, 0x02, 0x36, 0xF6, 0xB2, ++0x4A, 0x46, 0x59, 0x46, 0xFF, 0xF7, 0x08, 0xFD, 0x08, 0xB1, 0xD9, 0x2E, 0xE4, 0xD9, 0xB8, 0xEB, 0x06, 0x08, 0x37, 0x44, ++0xF0, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xFC, 0xAD, 0x05, 0x49, 0x07, 0x48, ++0x40, 0xF2, 0x13, 0x42, 0xEF, 0xF7, 0xA0, 0xFC, 0xF4, 0xE5, 0x00, 0xBF, 0x10, 0x07, 0x18, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xD0, 0xD0, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x2D, 0x4E, 0x41, 0xF2, 0xA9, 0x73, ++0xF2, 0x5C, 0x03, 0x2A, 0x42, 0xD8, 0x41, 0xF2, 0xA8, 0x73, 0xF3, 0x5C, 0x09, 0x2B, 0x3D, 0xD8, 0x0D, 0x46, 0x28, 0x49, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x13, 0x07, 0x46, 0x1B, 0x6C, 0x00, 0x2B, 0x3E, 0xD0, 0x24, 0x48, 0x1B, 0x79, ++0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x2D, 0xDB, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x12, 0x92, 0xF8, ++0xC0, 0x24, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xDA, 0xF7, 0x3D, 0xFE, 0x04, 0x46, ++0xE0, 0xB1, 0x41, 0xF2, 0xA9, 0x72, 0x41, 0xF2, 0xA8, 0x73, 0xB2, 0x5C, 0x02, 0x77, 0xF3, 0x5C, 0x43, 0x77, 0x00, 0x23, ++0x80, 0xF8, 0x33, 0x30, 0x80, 0xF8, 0x35, 0x30, 0x15, 0xB9, 0x13, 0x4B, 0xC0, 0xE9, 0x15, 0x30, 0x20, 0x46, 0x3B, 0x46, ++0x2A, 0x46, 0x01, 0x21, 0xFF, 0xF7, 0xEC, 0xFC, 0x20, 0x46, 0x03, 0x21, 0xBD, 0xE8, 0xF8, 0x40, 0xDA, 0xF7, 0x2E, 0xBE, ++0xF8, 0xBD, 0x02, 0x2B, 0xCF, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0xEF, 0xF7, 0x29, 0xFC, 0x01, 0x20, ++0xD1, 0xE7, 0x05, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xF7, 0xDA, 0xF0, 0xE7, 0x78, 0xEF, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xA1, 0x5E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, ++0x00, 0x2A, 0x35, 0xD0, 0x70, 0xB5, 0x04, 0x46, 0x92, 0xF8, 0x32, 0x00, 0x8A, 0xB0, 0x13, 0x46, 0x58, 0xB9, 0x95, 0x8E, ++0x22, 0x88, 0x95, 0x42, 0x28, 0xD1, 0xDD, 0x8E, 0x62, 0x88, 0x95, 0x42, 0x24, 0xD1, 0xA2, 0x88, 0x1C, 0x8F, 0x94, 0x42, ++0x20, 0xD1, 0x93, 0xF8, 0x3A, 0x20, 0xE2, 0xB1, 0xD9, 0xB1, 0x4D, 0x78, 0x8D, 0xF8, 0x04, 0x50, 0x6D, 0xB1, 0x01, 0xA8, ++0x05, 0x44, 0xC0, 0xF1, 0x02, 0x06, 0x44, 0x18, 0xA4, 0x5D, 0x00, 0xF8, 0x01, 0x4F, 0xA8, 0x42, 0xF9, 0xD1, 0x9D, 0xF8, ++0x04, 0x10, 0x91, 0x42, 0x01, 0xD0, 0x00, 0x20, 0x08, 0xE0, 0x03, 0xF1, 0x3B, 0x00, 0x0D, 0xF1, 0x05, 0x01, 0x01, 0xF0, ++0x57, 0xFE, 0x00, 0x28, 0xF5, 0xD1, 0x01, 0x20, 0x0A, 0xB0, 0x70, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, ++0x04, 0x46, 0xB1, 0xB1, 0x64, 0x48, 0x65, 0x4D, 0xA0, 0xF1, 0x82, 0x07, 0xED, 0xF7, 0x78, 0xFF, 0x00, 0x26, 0x25, 0xF8, ++0x02, 0x6C, 0x28, 0x46, 0x06, 0x22, 0x00, 0x21, 0x05, 0xF5, 0xF6, 0x75, 0xCA, 0xF7, 0xDE, 0xFE, 0xBD, 0x42, 0xF4, 0xD1, ++0xEC, 0xF7, 0x56, 0xFC, 0xC4, 0xE9, 0x0A, 0x01, 0x26, 0x66, 0x5B, 0x4E, 0xDF, 0xF8, 0x6C, 0x81, 0x06, 0xF1, 0x88, 0x07, ++0x0B, 0x20, 0xED, 0xF7, 0x77, 0xFD, 0x01, 0x28, 0x39, 0xD1, 0x57, 0x4D, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x02, 0x0A, ++0x03, 0xE0, 0x05, 0xF5, 0xF6, 0x75, 0xB5, 0x42, 0x1A, 0xD0, 0xAB, 0x88, 0x01, 0x2B, 0xF8, 0xD1, 0x6B, 0x7D, 0x05, 0xF1, ++0x1C, 0x01, 0x19, 0x44, 0x22, 0x46, 0xA8, 0x1D, 0xFF, 0xF7, 0x8C, 0xFF, 0x00, 0x28, 0xEE, 0xD0, 0x29, 0x46, 0xA5, 0xF8, ++0x18, 0x90, 0x85, 0xF8, 0x17, 0x90, 0xA5, 0xF8, 0x04, 0xA0, 0x38, 0x46, 0x05, 0xF5, 0xF6, 0x75, 0xED, 0xF7, 0x3E, 0xFF, ++0xB5, 0x42, 0xE4, 0xD1, 0x23, 0x6E, 0x94, 0xF8, 0x65, 0x20, 0x01, 0x33, 0x93, 0x42, 0x23, 0x66, 0x5D, 0xDA, 0x03, 0x21, ++0x0B, 0x20, 0xED, 0xF7, 0x9D, 0xFC, 0xFF, 0xF7, 0x1F, 0xFC, 0x00, 0x28, 0xC6, 0xD1, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, ++0xF0, 0x47, 0xFF, 0xF7, 0xFF, 0xBE, 0x01, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x8F, 0xFC, 0x23, 0x6E, 0x06, 0xE0, 0x23, 0x6E, ++0x94, 0xF8, 0x65, 0x20, 0x01, 0x33, 0x93, 0x42, 0x23, 0x66, 0xB3, 0xDA, 0x23, 0x44, 0x94, 0xF8, 0x64, 0x00, 0x93, 0xF8, ++0x66, 0x10, 0xF1, 0xF7, 0xBB, 0xFF, 0x05, 0x46, 0x00, 0x28, 0xEE, 0xD0, 0xC3, 0x78, 0x9B, 0x07, 0xEB, 0xD4, 0x4F, 0xF4, ++0xBA, 0x73, 0x0B, 0x22, 0x04, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xED, 0xF7, 0x77, 0xFA, 0x06, 0x46, 0x28, 0x68, 0x30, 0x60, ++0xAB, 0x88, 0xB3, 0x80, 0xE3, 0x78, 0x1B, 0xB9, 0xF3, 0x78, 0x43, 0xF0, 0x01, 0x03, 0xF3, 0x70, 0x01, 0x25, 0x86, 0xF8, ++0x6F, 0x51, 0x94, 0xF8, 0x3A, 0x20, 0x86, 0xF8, 0xFC, 0x20, 0x04, 0xF1, 0x3B, 0x01, 0x06, 0xF1, 0xFD, 0x00, 0x01, 0xF0, ++0xE7, 0xFD, 0x86, 0xF8, 0x70, 0x51, 0xA3, 0x8E, 0xA6, 0xF8, 0x60, 0x31, 0xE3, 0x8E, 0xA6, 0xF8, 0x62, 0x31, 0x23, 0x8F, ++0xA6, 0xF8, 0x64, 0x31, 0x41, 0xF2, 0xA9, 0x73, 0x30, 0x46, 0x18, 0xF8, 0x03, 0x30, 0x86, 0xF8, 0x6E, 0x31, 0xBD, 0xE8, ++0xF0, 0x47, 0xED, 0xF7, 0x79, 0xBA, 0x13, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x09, 0xDB, 0x02, 0x21, ++0x0B, 0x20, 0xED, 0xF7, 0x39, 0xFC, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x9F, 0xBE, 0xFF, 0xF7, ++0xB5, 0xFB, 0x00, 0x28, 0xF1, 0xD0, 0xE3, 0x6D, 0x00, 0x2B, 0xEE, 0xD0, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF2, 0x22, 0x62, ++0xEF, 0xF7, 0x0E, 0xFB, 0xE7, 0xE7, 0x00, 0xBF, 0x10, 0x07, 0x18, 0x00, 0x7E, 0xEF, 0x17, 0x00, 0x88, 0x06, 0x18, 0x00, ++0x78, 0xEF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x1C, 0xD1, 0x15, 0x00, 0x10, 0xB5, 0x08, 0x4C, ++0x00, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x10, 0xFC, 0x20, 0x46, 0x41, 0xF2, 0xB0, 0x72, 0x00, 0x21, 0x04, 0xF5, 0xBD, 0x54, ++0xCA, 0xF7, 0x08, 0xFE, 0x4F, 0xF0, 0xFF, 0x33, 0x23, 0x60, 0x10, 0xBD, 0x78, 0xEF, 0x17, 0x00, 0xF0, 0xB5, 0xA3, 0xB0, ++0x0B, 0x4C, 0x9D, 0xF8, 0xA0, 0x50, 0x8D, 0xF8, 0x02, 0x50, 0x41, 0xF2, 0xA8, 0x75, 0x84, 0x46, 0x41, 0xF2, 0xA9, 0x77, ++0x08, 0x46, 0x66, 0x5B, 0x60, 0x55, 0x19, 0x46, 0x68, 0x46, 0x04, 0xF8, 0x07, 0xC0, 0x8D, 0xF8, 0x00, 0x20, 0xFF, 0xF7, ++0x57, 0xFE, 0x66, 0x53, 0x23, 0xB0, 0xF0, 0xBD, 0x78, 0xEF, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAB, 0xB0, 0x41, 0xF2, ++0xA8, 0x76, 0x00, 0x92, 0xC4, 0x4A, 0x41, 0xF2, 0xA9, 0x75, 0x91, 0x55, 0xCD, 0xE9, 0x01, 0x01, 0x02, 0xF5, 0xBD, 0x51, ++0x50, 0x55, 0x4F, 0xF0, 0xFF, 0x30, 0x08, 0x60, 0x34, 0x99, 0x16, 0x46, 0x41, 0xF2, 0xA4, 0x74, 0x00, 0x22, 0x91, 0x42, ++0x32, 0x51, 0x34, 0xDD, 0xDF, 0xF8, 0xF0, 0x82, 0x1F, 0x46, 0x91, 0x46, 0xBA, 0x46, 0x57, 0xF8, 0x04, 0x4B, 0x65, 0x78, ++0xAB, 0x1C, 0x04, 0x2B, 0x37, 0xD9, 0x88, 0x22, 0x00, 0x21, 0x40, 0x46, 0xCA, 0xF7, 0xBC, 0xFD, 0xA3, 0x78, 0x88, 0xF8, ++0x01, 0x30, 0xE3, 0x78, 0x22, 0x79, 0x88, 0xF8, 0x02, 0x20, 0xD9, 0x07, 0x03, 0xD4, 0x9B, 0x07, 0x1C, 0xD4, 0x05, 0x2A, ++0x73, 0xD0, 0xDA, 0xF8, 0x00, 0x40, 0x02, 0x21, 0x00, 0x9A, 0x23, 0x79, 0x8D, 0xF8, 0x20, 0x20, 0xA8, 0x4A, 0x02, 0x98, ++0x8D, 0xF8, 0x22, 0x30, 0x41, 0xF2, 0xA8, 0x75, 0x41, 0xF2, 0xA9, 0x73, 0x16, 0x46, 0x54, 0x5B, 0x01, 0x9F, 0x50, 0x55, ++0x08, 0xA8, 0xD7, 0x54, 0xFF, 0xF7, 0x04, 0xFE, 0x74, 0x53, 0x2B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x98, 0xF8, 0x00, 0x30, ++0x00, 0x9A, 0x93, 0x42, 0x4C, 0xD0, 0x34, 0x9B, 0x09, 0xF1, 0x01, 0x09, 0x4B, 0x45, 0xC1, 0xD1, 0xF1, 0xE7, 0x04, 0x21, ++0xDA, 0xE7, 0xA3, 0x2C, 0x00, 0xF0, 0x25, 0x81, 0xA4, 0x2C, 0x40, 0xF0, 0x18, 0x81, 0x98, 0x78, 0x88, 0xF8, 0x20, 0x00, ++0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0x0B, 0x44, 0x00, 0xF2, 0x82, 0x80, 0x98, 0xF8, 0x03, 0x30, 0x01, 0x2B, 0x3E, 0x46, ++0x03, 0x9F, 0x2C, 0xD8, 0x04, 0x9C, 0x72, 0x2C, 0x23, 0x46, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x30, ++0x00, 0x2E, 0x00, 0xF0, 0x2B, 0x81, 0xB6, 0xF8, 0x03, 0x20, 0xB1, 0x78, 0xB0, 0x88, 0x88, 0xF8, 0x66, 0x40, 0x41, 0xF2, ++0x88, 0x33, 0x9A, 0x42, 0x94, 0xBF, 0x00, 0x22, 0x01, 0x22, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x20, 0x88, 0xF8, 0x65, 0x30, ++0x00, 0x29, 0x40, 0xF0, 0x03, 0x81, 0x05, 0x9A, 0x88, 0xF8, 0x64, 0x10, 0x94, 0x42, 0x06, 0xD0, 0x80, 0xF0, 0x59, 0x81, ++0x04, 0x9B, 0x04, 0x33, 0x88, 0xF8, 0x67, 0x30, 0x02, 0x23, 0x88, 0xF8, 0x65, 0x30, 0x00, 0x9B, 0x88, 0xF8, 0x00, 0x30, ++0x76, 0x4A, 0x13, 0x68, 0x01, 0x33, 0x08, 0xF1, 0x88, 0x08, 0x13, 0x60, 0xAB, 0xE7, 0xEB, 0x1E, 0x0C, 0x2B, 0x40, 0xF2, ++0xDD, 0x80, 0xE3, 0x7A, 0x88, 0xF8, 0x03, 0x30, 0x02, 0x2B, 0x82, 0xD8, 0x62, 0x79, 0x63, 0x7A, 0x04, 0x92, 0xA2, 0x79, ++0x05, 0x92, 0xA8, 0xF8, 0x30, 0x30, 0x08, 0xF1, 0x3A, 0x0E, 0x08, 0xF1, 0x34, 0x03, 0xA4, 0xEB, 0x08, 0x01, 0x5A, 0x18, ++0x12, 0xF8, 0x28, 0x2C, 0x03, 0xF8, 0x01, 0x2B, 0x73, 0x45, 0xF8, 0xD1, 0xB8, 0xF8, 0x34, 0x20, 0x4F, 0xF6, 0xFF, 0x73, ++0x9A, 0x42, 0xA5, 0xF1, 0x10, 0x02, 0x08, 0xBF, 0x01, 0x23, 0x4F, 0xF0, 0x02, 0x01, 0x92, 0xB2, 0x08, 0xBF, 0x88, 0xF8, ++0x32, 0x30, 0x8A, 0x42, 0x04, 0xF1, 0x12, 0x03, 0x88, 0xF8, 0x04, 0x10, 0x40, 0xF2, 0x47, 0x81, 0x00, 0x21, 0x6F, 0xF0, ++0x13, 0x00, 0x0C, 0x46, 0x6F, 0xF0, 0x08, 0x06, 0x6F, 0xF0, 0x37, 0x0C, 0x0D, 0x46, 0xA0, 0xEB, 0x08, 0x01, 0x03, 0x97, ++0x06, 0x91, 0xA6, 0xEB, 0x08, 0x06, 0xAC, 0xEB, 0x08, 0x0C, 0x27, 0x46, 0x58, 0x78, 0x1C, 0x78, 0x81, 0x1C, 0x91, 0x42, ++0x00, 0xF2, 0x96, 0x80, 0x0B, 0x2C, 0x3F, 0xF6, 0x66, 0xAF, 0x0B, 0x2C, 0x3F, 0xF6, 0x6C, 0xAF, 0x0F, 0xF2, 0x04, 0x0B, ++0x5B, 0xF8, 0x24, 0xF0, 0xA9, 0x58, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0x97, 0x58, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, ++0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, ++0xB1, 0x56, 0x15, 0x00, 0x65, 0x58, 0x15, 0x00, 0x11, 0x58, 0x15, 0x00, 0x02, 0x29, 0x71, 0xD0, 0x9C, 0x78, 0xFF, 0x2C, ++0x7F, 0xF4, 0x4A, 0xAF, 0x00, 0xF1, 0xFF, 0x3B, 0x5F, 0xFA, 0x8B, 0xFB, 0xBB, 0xF1, 0x08, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, ++0x08, 0x0B, 0x01, 0x28, 0xC8, 0xF8, 0x14, 0xB0, 0x3F, 0xF4, 0x3C, 0xAF, 0x08, 0xF1, 0x17, 0x00, 0xCD, 0xF8, 0x1C, 0xA0, ++0xDD, 0xF8, 0x18, 0xA0, 0x83, 0x44, 0x1C, 0x18, 0x14, 0xF8, 0x0A, 0x40, 0x00, 0xF8, 0x01, 0x4F, 0x58, 0x45, 0xF8, 0xD1, ++0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0xDD, 0xF8, 0x1C, 0xA0, 0x0B, 0x44, 0xAE, 0xD8, 0x2B, 0xE7, 0x8C, 0x1E, 0x08, 0x2C, ++0xA8, 0xBF, 0x08, 0x24, 0x02, 0x29, 0xC8, 0xF8, 0x08, 0x40, 0x3F, 0xF4, 0x1D, 0xAF, 0x08, 0xF1, 0x0B, 0x00, 0x00, 0xEB, ++0x04, 0x0B, 0x1C, 0x18, 0xA4, 0x5D, 0x00, 0xF8, 0x01, 0x4F, 0x83, 0x45, 0xF9, 0xD1, 0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, ++0x0B, 0x44, 0x95, 0xD8, 0x12, 0xE7, 0x52, 0x1A, 0x92, 0xB2, 0x98, 0x78, 0x88, 0xF8, 0x04, 0x00, 0x02, 0x2A, 0x0B, 0x44, ++0x8C, 0xD8, 0x09, 0xE7, 0x22, 0x29, 0x25, 0xD8, 0x88, 0xF8, 0x3A, 0x00, 0x00, 0x28, 0x3F, 0xF4, 0xFD, 0xAE, 0x00, 0xEB, ++0x0E, 0x04, 0x70, 0x46, 0x00, 0xEB, 0x03, 0x0B, 0x1B, 0xF8, 0x0C, 0xB0, 0x00, 0xF8, 0x01, 0xBF, 0xA0, 0x42, 0xF7, 0xD1, ++0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0x0B, 0x44, 0x3F, 0xF6, 0x74, 0xAF, 0xF0, 0xE6, 0x52, 0x1A, 0x92, 0xB2, 0x33, 0x2C, ++0x08, 0xBF, 0x1D, 0x46, 0x02, 0x2A, 0x0B, 0x44, 0x3F, 0xF6, 0x6A, 0xAF, 0xE6, 0xE6, 0x1F, 0x46, 0xDE, 0xE6, 0x00, 0x23, ++0x88, 0xF8, 0x65, 0x30, 0xDA, 0xF8, 0x00, 0x40, 0x04, 0x21, 0xA9, 0xE6, 0x78, 0xEF, 0x17, 0x00, 0x1C, 0x07, 0x18, 0x00, ++0x88, 0x06, 0x18, 0x00, 0x01, 0x29, 0x08, 0xF1, 0x66, 0x03, 0x00, 0xF0, 0x47, 0x81, 0x04, 0x9A, 0x41, 0x2A, 0x35, 0xBF, ++0x40, 0x20, 0x80, 0x20, 0x24, 0x22, 0x64, 0x22, 0x11, 0x1D, 0x03, 0xF8, 0x01, 0x2B, 0xCA, 0xB2, 0x90, 0x42, 0xF9, 0xD2, ++0x08, 0x23, 0xF4, 0xE6, 0x05, 0x9B, 0xFF, 0x2B, 0x4E, 0xD0, 0x05, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0x85, 0x80, 0x05, 0x9A, ++0x88, 0xF8, 0x66, 0x20, 0x01, 0x23, 0x88, 0xF8, 0x65, 0x30, 0x04, 0x9B, 0xA3, 0xF1, 0x53, 0x02, 0x08, 0xF1, 0x66, 0x03, ++0x2E, 0x2A, 0x30, 0xD8, 0xDF, 0xE8, 0x12, 0xF0, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, ++0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, ++0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, ++0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, ++0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x71, 0x01, ++0x6E, 0x01, 0x01, 0x23, 0xAD, 0xE6, 0x05, 0x9B, 0x04, 0x93, 0x04, 0x9B, 0x04, 0x3B, 0x88, 0xF8, 0x67, 0x30, 0x02, 0x23, ++0xA5, 0xE6, 0x05, 0x9B, 0x04, 0x93, 0x9D, 0xE6, 0x00, 0x2D, 0x8D, 0xD0, 0xAB, 0x78, 0x04, 0x9A, 0x93, 0x42, 0x89, 0xD1, ++0x68, 0x78, 0x43, 0x1E, 0xDB, 0xB2, 0x1C, 0x2B, 0x28, 0xBF, 0x1C, 0x23, 0x59, 0x1E, 0x01, 0x28, 0x05, 0xF1, 0x03, 0x05, ++0xC9, 0xB2, 0x3F, 0xF4, 0x7D, 0xAF, 0x32, 0x46, 0x08, 0xEB, 0x02, 0x04, 0xAE, 0x5C, 0x84, 0xF8, 0x66, 0x60, 0x91, 0x42, ++0x02, 0xF1, 0x01, 0x02, 0xF6, 0xD1, 0x01, 0x28, 0x3F, 0xF4, 0x70, 0xAF, 0x88, 0xF8, 0x65, 0x30, 0x01, 0x2B, 0x7F, 0xF4, ++0x80, 0xAE, 0x98, 0xF8, 0x66, 0x30, 0x05, 0x93, 0x91, 0xE7, 0x98, 0xF8, 0x03, 0x30, 0x01, 0x2B, 0x3F, 0xF6, 0x77, 0xAE, ++0x04, 0x9B, 0x72, 0x2B, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x30, 0x05, 0x9B, 0xFF, 0x2B, 0x7F, 0xF4, ++0x78, 0xAF, 0x55, 0xE7, 0x04, 0x9A, 0x08, 0xF1, 0x66, 0x03, 0x51, 0x3A, 0x1E, 0x46, 0x30, 0x2A, 0x3F, 0xF6, 0x4B, 0xAF, ++0x01, 0xA1, 0x51, 0xF8, 0x22, 0xF0, 0x00, 0xBF, 0x9B, 0x5B, 0x15, 0x00, 0x27, 0x5C, 0x15, 0x00, 0x9B, 0x5B, 0x15, 0x00, ++0x9B, 0x5B, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x87, 0x5B, 0x15, 0x00, ++0x87, 0x5B, 0x15, 0x00, 0x87, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, ++0x29, 0x5B, 0x15, 0x00, 0x03, 0x5C, 0x15, 0x00, 0x29, 0x5B, 0x15, 0x00, 0x29, 0x5B, 0x15, 0x00, 0xE9, 0x5B, 0x15, 0x00, ++0x0D, 0x5C, 0x15, 0x00, 0x00, 0x25, 0x04, 0x20, 0xA2, 0x24, 0x95, 0x22, 0x71, 0x1E, 0x0B, 0x46, 0x02, 0x33, 0x01, 0xF8, ++0x01, 0x2F, 0x02, 0x44, 0x2B, 0x44, 0x94, 0x42, 0xA3, 0xEB, 0x06, 0x03, 0xF5, 0xDC, 0x40, 0x4A, 0xDB, 0xB2, 0x12, 0x68, ++0x88, 0xF8, 0x65, 0x30, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xDB, 0x00, 0x2B, 0x7F, 0xF4, 0x5F, 0xAF, 0xCB, 0xE6, ++0x1C, 0x2B, 0xF9, 0xD9, 0x39, 0x49, 0x3A, 0x48, 0x40, 0xF2, 0x01, 0x32, 0xEF, 0xF7, 0x06, 0xF8, 0x98, 0xF8, 0x65, 0x30, ++0x00, 0x2B, 0x7F, 0xF4, 0x51, 0xAF, 0xBD, 0xE6, 0x00, 0x25, 0x04, 0x20, 0x91, 0x24, 0x64, 0x22, 0xD4, 0xE7, 0x00, 0x25, ++0x04, 0x20, 0x41, 0x24, 0x34, 0x22, 0xCF, 0xE7, 0x00, 0x25, 0x04, 0x20, 0x31, 0x24, 0x24, 0x22, 0xCA, 0xE7, 0x01, 0x20, ++0x02, 0x46, 0x00, 0x25, 0x0E, 0x24, 0xC5, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0xB6, 0xAE, 0x04, 0x9A, 0x23, 0x2A, 0x7F, 0xF6, ++0x06, 0xAF, 0x30, 0x2A, 0x15, 0xD9, 0x40, 0x2A, 0x10, 0xD9, 0x70, 0x2A, 0x3B, 0xD9, 0x80, 0x2A, 0x36, 0xD9, 0x90, 0x2A, ++0x3F, 0xF6, 0xFB, 0xAE, 0x90, 0x21, 0x84, 0x22, 0x10, 0x1D, 0x03, 0xF8, 0x01, 0x2B, 0xC2, 0xB2, 0x91, 0x42, 0xF9, 0xD2, ++0x04, 0x23, 0xA0, 0xE5, 0x40, 0x21, 0x34, 0x22, 0xF4, 0xE7, 0x30, 0x21, 0x24, 0x22, 0xF1, 0xE7, 0x24, 0x22, 0x03, 0xF8, ++0x01, 0x2B, 0x04, 0x32, 0x44, 0x2A, 0xFA, 0xD1, 0x08, 0xF1, 0x6E, 0x06, 0x08, 0x25, 0x04, 0x20, 0x91, 0x24, 0x64, 0x22, ++0x96, 0xE7, 0x00, 0x25, 0x04, 0x20, 0xAA, 0x24, 0x95, 0x22, 0x91, 0xE7, 0x24, 0x22, 0x03, 0xF8, 0x01, 0x2B, 0x04, 0x32, ++0x44, 0x2A, 0xFA, 0xD1, 0x08, 0xF1, 0x6E, 0x06, 0x08, 0x25, 0x04, 0x20, 0x81, 0x24, 0x64, 0x22, 0x84, 0xE7, 0x0F, 0x24, ++0x01, 0x20, 0x00, 0x25, 0x0E, 0x22, 0x7F, 0xE7, 0x80, 0x21, 0x74, 0x22, 0xCA, 0xE7, 0x70, 0x21, 0x64, 0x22, 0xC7, 0xE7, ++0x05, 0x9A, 0x04, 0x92, 0x69, 0xE6, 0x05, 0x9A, 0x04, 0x92, 0xB0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x5C, 0xD1, 0x15, 0x00, 0x70, 0xB5, 0x15, 0x4D, 0x2C, 0x68, 0xA5, 0xF5, 0xBD, 0x56, 0x01, 0x34, 0xA5, 0xF1, 0x90, 0x01, ++0x2C, 0x60, 0x33, 0x46, 0x01, 0x20, 0x9A, 0x88, 0x01, 0x2A, 0x88, 0xBF, 0x98, 0x80, 0x03, 0xF5, 0xF6, 0x73, 0x8B, 0x42, ++0xF7, 0xD1, 0x41, 0xF2, 0xA4, 0x73, 0xF3, 0x58, 0x9C, 0x42, 0x0B, 0xDA, 0x04, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x90, 0xF8, ++0x0B, 0x22, 0xBD, 0xE8, 0x70, 0x40, 0x11, 0x46, 0x4F, 0xF4, 0x30, 0x50, 0xEC, 0xF7, 0xF6, 0xBE, 0x00, 0x21, 0x0B, 0x20, ++0xED, 0xF7, 0x84, 0xF8, 0x4F, 0xF0, 0xFF, 0x33, 0x2B, 0x60, 0x70, 0xBD, 0x18, 0x07, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0x3E, 0x4C, 0x3F, 0x4E, 0x04, 0xF5, 0xBD, 0x53, 0x31, 0x68, 0x1B, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x03, 0xEB, 0x03, 0x13, ++0x04, 0xEB, 0xC3, 0x05, 0x05, 0xF5, 0xB8, 0x55, 0x00, 0x29, 0x05, 0xF1, 0x10, 0x05, 0x4F, 0xEA, 0xC3, 0x03, 0x3A, 0xDB, ++0x23, 0x44, 0x41, 0xF2, 0x13, 0x72, 0x9B, 0x5C, 0x01, 0x2B, 0x45, 0xD9, 0x02, 0x2B, 0x50, 0xD1, 0x02, 0x21, 0x0B, 0x20, ++0xED, 0xF7, 0x5C, 0xF8, 0x30, 0x48, 0x2E, 0x4C, 0xA0, 0xF1, 0x88, 0x06, 0x06, 0xF1, 0x88, 0x09, 0xED, 0xF7, 0xE4, 0xFA, ++0x00, 0x27, 0x4F, 0xF0, 0x02, 0x08, 0x03, 0xE0, 0x04, 0xF5, 0xF6, 0x74, 0xB4, 0x42, 0x18, 0xD0, 0xA3, 0x88, 0x01, 0x2B, ++0xF8, 0xD1, 0x63, 0x7D, 0x04, 0xF1, 0x1C, 0x01, 0x19, 0x44, 0x2A, 0x46, 0xA0, 0x1D, 0xFF, 0xF7, 0x15, 0xFB, 0x00, 0x28, ++0xEE, 0xD0, 0x21, 0x46, 0x27, 0x83, 0xE7, 0x75, 0xA4, 0xF8, 0x04, 0x80, 0x48, 0x46, 0x04, 0xF5, 0xF6, 0x74, 0xED, 0xF7, ++0xC9, 0xFA, 0xB4, 0x42, 0xE6, 0xD1, 0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0x99, 0xBA, 0x1C, 0x44, ++0x41, 0xF2, 0x12, 0x73, 0xE3, 0x5C, 0x05, 0x2B, 0x19, 0xD0, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0xA3, 0x62, 0xEE, 0xF7, ++0x09, 0xFF, 0x41, 0xF2, 0x13, 0x73, 0xE3, 0x5C, 0x01, 0x2B, 0x05, 0xD8, 0x28, 0x46, 0x01, 0x21, 0xBD, 0xE8, 0xF8, 0x43, ++0xFF, 0xF7, 0x24, 0xBB, 0x02, 0x2B, 0xB3, 0xD0, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x08, 0xDB, 0xBD, 0xE8, ++0xF8, 0x83, 0x41, 0xF2, 0x13, 0x73, 0xE3, 0x5C, 0x01, 0x2B, 0xEB, 0xD9, 0x02, 0x2B, 0xA5, 0xD0, 0xBD, 0xE8, 0xF8, 0x43, ++0x05, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xAF, 0x62, 0xEE, 0xF7, 0xE6, 0xBE, 0x78, 0xEF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x10, 0x07, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xD1, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0xDF, 0xF8, 0xCC, 0x80, 0x2C, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x14, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0C, 0xDB, ++0x29, 0x4F, 0x04, 0xEB, 0x04, 0x13, 0x07, 0xEB, 0xC3, 0x03, 0x41, 0xF2, 0x13, 0x72, 0x25, 0x01, 0x9B, 0x5C, 0x01, 0x2B, ++0x19, 0xD9, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x2C, 0x35, 0xDB, 0x22, 0x4F, 0x04, 0xEB, 0x04, 0x16, 0x07, 0xEB, 0xC6, 0x06, ++0x41, 0xF2, 0x12, 0x73, 0x25, 0x01, 0xF3, 0x5C, 0x05, 0x2B, 0x15, 0xD0, 0x1D, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0xD7, 0x62, ++0xEE, 0xF7, 0xAE, 0xFE, 0x41, 0xF2, 0x13, 0x73, 0xF3, 0x5C, 0x01, 0x2B, 0x17, 0xD8, 0x2C, 0x44, 0x07, 0xEB, 0xC4, 0x00, ++0x00, 0xF5, 0xB8, 0x50, 0xBD, 0xE8, 0xF0, 0x41, 0x10, 0x30, 0x00, 0x21, 0xFF, 0xF7, 0xC4, 0xBA, 0x41, 0xF2, 0x13, 0x73, ++0xF3, 0x5C, 0x01, 0x2B, 0xEF, 0xD9, 0xBD, 0xE8, 0xF0, 0x41, 0x0F, 0x49, 0x10, 0x48, 0x40, 0xF2, 0xC1, 0x62, 0xEE, 0xF7, ++0x91, 0xBE, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xF1, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, 0x08, 0x49, ++0x0A, 0x48, 0x40, 0xF2, 0xB7, 0x62, 0xEE, 0xF7, 0x83, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xBD, 0xDB, 0xAD, 0xE7, 0x18, 0x07, 0x18, 0x00, 0x78, 0xEF, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xD1, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0xC0, 0xD1, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0xB5, 0x29, 0xB3, 0x18, 0x4C, 0x04, 0xF5, ++0xBD, 0x53, 0x05, 0x46, 0x1E, 0x68, 0xFE, 0xF7, 0x01, 0xFF, 0x02, 0x46, 0x40, 0xB1, 0x0B, 0x20, 0xED, 0xF7, 0x20, 0xF8, ++0x03, 0x28, 0x1F, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xC6, 0xBE, 0x06, 0xEB, 0x06, 0x16, 0x04, 0xEB, 0xC6, 0x03, ++0x01, 0x21, 0x03, 0xF5, 0xB8, 0x53, 0x85, 0xF8, 0x5E, 0x10, 0x10, 0x33, 0x01, 0x46, 0x28, 0x46, 0xFE, 0xF7, 0x00, 0xFF, ++0x28, 0x46, 0x03, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0xDA, 0xF7, 0x42, 0xB8, 0x0B, 0x20, 0xEC, 0xF7, 0x5B, 0xFF, 0x05, 0x4B, ++0x4F, 0xF0, 0xFF, 0x32, 0x1A, 0x60, 0x70, 0xBD, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0x60, 0xBF, 0x78, 0xEF, 0x17, 0x00, ++0x18, 0x07, 0x18, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0xB0, 0xB6, 0x4F, 0x9D, 0xF8, 0x50, 0x40, 0x03, 0x94, 0x9D, 0xF9, ++0x54, 0x40, 0x04, 0x94, 0x07, 0xF5, 0xBD, 0x55, 0x04, 0x46, 0x28, 0x68, 0x25, 0x7C, 0x8D, 0xF8, 0x20, 0x50, 0x65, 0x7C, ++0x8D, 0xF8, 0x21, 0x50, 0xA5, 0x7C, 0x8D, 0xF8, 0x22, 0x50, 0xE5, 0x7C, 0x8D, 0xF8, 0x23, 0x50, 0x25, 0x7D, 0x8D, 0xF8, ++0x24, 0x50, 0x00, 0x28, 0x65, 0x7D, 0x9D, 0xF8, 0x58, 0x90, 0x8D, 0xF8, 0x25, 0x50, 0x0E, 0x46, 0x90, 0x46, 0x05, 0x93, ++0xC0, 0xF2, 0x1A, 0x81, 0x00, 0xEB, 0x00, 0x10, 0x07, 0xEB, 0xC0, 0x00, 0x00, 0xF5, 0xB8, 0x57, 0x10, 0x37, 0x3A, 0x46, ++0x00, 0x21, 0x08, 0xA8, 0xFF, 0xF7, 0xEE, 0xF9, 0x10, 0xB9, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xBD, 0xF8, 0x20, 0x00, ++0xBD, 0xF8, 0x24, 0x30, 0x01, 0x93, 0x00, 0x21, 0xBD, 0xF8, 0x22, 0xE0, 0x97, 0x4B, 0x98, 0x4A, 0x02, 0x94, 0x8C, 0x46, ++0x0D, 0x46, 0x83, 0x46, 0x0B, 0xE0, 0x98, 0x88, 0x01, 0x28, 0x00, 0xF0, 0xC1, 0x80, 0x03, 0x28, 0x00, 0xF0, 0xB4, 0x80, ++0x88, 0xB1, 0x03, 0xF5, 0xF6, 0x73, 0x93, 0x42, 0x14, 0xD0, 0xB3, 0xF8, 0x06, 0xA0, 0xDA, 0x45, 0xEF, 0xD1, 0x18, 0x89, ++0x70, 0x45, 0xEC, 0xD1, 0x58, 0x89, 0x01, 0x9C, 0xA0, 0x42, 0xE8, 0xD1, 0x02, 0x9C, 0x1D, 0x46, 0x10, 0xE0, 0x00, 0x2D, ++0x08, 0xBF, 0x1D, 0x46, 0x03, 0xF5, 0xF6, 0x73, 0x93, 0x42, 0xEA, 0xD1, 0x02, 0x9C, 0x00, 0x2D, 0x00, 0xF0, 0x42, 0x81, ++0x4F, 0xF4, 0xF6, 0x72, 0x00, 0x21, 0x28, 0x46, 0xCA, 0xF7, 0xDC, 0xF8, 0xAB, 0x88, 0x03, 0x2B, 0xBF, 0xD0, 0x03, 0x9B, ++0xBD, 0xF8, 0x20, 0x10, 0xBD, 0xF8, 0x22, 0x20, 0xC5, 0xF8, 0x0C, 0x80, 0x00, 0x2B, 0xBD, 0xF8, 0x24, 0x30, 0x6B, 0x81, ++0x08, 0xBF, 0x05, 0x20, 0x05, 0xF1, 0x1C, 0x03, 0x18, 0xBF, 0x04, 0x20, 0x02, 0x93, 0x04, 0xF1, 0x24, 0x08, 0x85, 0xF8, ++0x11, 0x90, 0xA8, 0x74, 0xE9, 0x80, 0x2A, 0x81, 0x18, 0x34, 0x05, 0xF1, 0x1B, 0x03, 0x14, 0xF8, 0x01, 0x2B, 0x03, 0xF8, ++0x01, 0x2F, 0x44, 0x45, 0xF9, 0xD1, 0x02, 0x9B, 0xA6, 0xF1, 0x24, 0x09, 0x03, 0xF1, 0x0C, 0x0B, 0xB9, 0xF1, 0x02, 0x0F, ++0x4F, 0xF0, 0x00, 0x03, 0xCD, 0xE9, 0x06, 0x33, 0x40, 0xF3, 0x56, 0x81, 0x4F, 0xF4, 0xE2, 0x7A, 0x3A, 0x46, 0x98, 0xF8, ++0x01, 0x40, 0x98, 0xF8, 0x00, 0x60, 0x98, 0xF8, 0x02, 0x70, 0x02, 0x34, 0x08, 0xF1, 0x02, 0x00, 0x00, 0x2E, 0x71, 0xD0, ++0x03, 0x2E, 0x7D, 0xD0, 0xA9, 0x7C, 0x05, 0x29, 0x00, 0xF2, 0x81, 0x80, 0x2A, 0x2E, 0x00, 0xF0, 0x8D, 0x80, 0x3D, 0x2E, ++0x00, 0xF0, 0x8D, 0x80, 0xC0, 0x2E, 0x00, 0xF0, 0x9A, 0x80, 0xFF, 0x2E, 0x02, 0xD1, 0x08, 0x2C, 0x00, 0xF2, 0xCD, 0x80, ++0x54, 0x45, 0x07, 0xDC, 0x39, 0x46, 0x30, 0x46, 0x01, 0x92, 0xFE, 0xF7, 0xD5, 0xFD, 0x01, 0x9A, 0x00, 0x28, 0x46, 0xD1, ++0xA0, 0x44, 0xA9, 0xEB, 0x04, 0x09, 0xB9, 0xF1, 0x02, 0x0F, 0xD0, 0xDC, 0xCA, 0xF5, 0xE8, 0x7A, 0x1F, 0xFA, 0x8A, 0xFA, ++0xAB, 0x7D, 0xA5, 0xF8, 0x1A, 0xA0, 0x00, 0x2B, 0x00, 0xF0, 0x94, 0x80, 0x04, 0x9B, 0x2B, 0x75, 0x2B, 0x7C, 0x06, 0x9A, ++0x04, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x03, 0x2A, 0x00, 0xF0, 0x05, 0x81, 0x02, 0x2A, 0x00, 0xF0, 0x04, 0x81, 0x03, 0x99, ++0x00, 0x29, 0x40, 0xF0, 0xC0, 0x80, 0x0E, 0x2B, 0x00, 0xF0, 0x14, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x07, 0x9B, ++0x01, 0x2B, 0x0C, 0xBF, 0x54, 0x23, 0x53, 0x23, 0x01, 0x22, 0xEB, 0x74, 0xAA, 0x80, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x00, 0x29, 0x41, 0xD0, 0x93, 0xF9, 0x14, 0xA0, 0x91, 0xF9, 0x14, 0x00, 0x82, 0x45, 0xB8, 0xBF, 0x19, 0x46, 0x42, 0xE7, ++0xBC, 0xF1, 0x00, 0x0F, 0x34, 0xD0, 0x93, 0xF9, 0x14, 0xA0, 0x9C, 0xF9, 0x14, 0x00, 0x82, 0x45, 0xB8, 0xBF, 0x9C, 0x46, ++0x37, 0xE7, 0x43, 0x46, 0xAB, 0xEB, 0x03, 0x00, 0xA0, 0x44, 0x19, 0x78, 0xC1, 0x54, 0x01, 0x33, 0x98, 0x45, 0xFA, 0xD1, ++0xA3, 0x44, 0xAA, 0xEB, 0x04, 0x0A, 0xAC, 0xE7, 0x02, 0x9B, 0x01, 0x92, 0xAB, 0xEB, 0x03, 0x01, 0x69, 0x75, 0xA8, 0x1D, ++0x41, 0x46, 0xFF, 0xF7, 0xF5, 0xF8, 0x01, 0x9A, 0x00, 0x28, 0x95, 0xD1, 0xA8, 0x80, 0x02, 0xE7, 0x02, 0x9B, 0xAB, 0xEB, ++0x03, 0x01, 0xA9, 0x75, 0x01, 0x78, 0x29, 0x74, 0x8C, 0xE7, 0x06, 0x29, 0x3F, 0xF4, 0x7F, 0xAF, 0x08, 0x29, 0x7F, 0xF6, ++0x7F, 0xAF, 0x0D, 0x29, 0x84, 0xD8, 0x7E, 0xE7, 0x00, 0x27, 0xEA, 0xE6, 0x9C, 0x46, 0x08, 0xE7, 0x19, 0x46, 0x06, 0xE7, ++0x06, 0x21, 0xA9, 0x74, 0x7A, 0xE7, 0x18, 0x2C, 0x7F, 0xF4, 0x78, 0xAF, 0x4F, 0xF0, 0x07, 0x03, 0xAB, 0x74, 0x98, 0xF8, ++0x03, 0x10, 0x11, 0xF0, 0x03, 0x03, 0x07, 0x93, 0x06, 0x9B, 0x18, 0xBF, 0x01, 0x23, 0x06, 0x93, 0x6A, 0xE7, 0x07, 0x2C, ++0x7F, 0xF4, 0x68, 0xAF, 0x4F, 0xF0, 0x09, 0x03, 0xAB, 0x74, 0x01, 0x78, 0x00, 0x29, 0x3F, 0xF4, 0x61, 0xAF, 0x01, 0x29, ++0x76, 0xD0, 0x02, 0x29, 0x00, 0xF0, 0x97, 0x80, 0x03, 0x29, 0x06, 0x9B, 0x08, 0xBF, 0x04, 0x23, 0x06, 0x93, 0x55, 0xE7, ++0x78, 0xEF, 0x17, 0x00, 0x88, 0x06, 0x18, 0x00, 0xAA, 0x88, 0x22, 0xB1, 0x95, 0xF9, 0x14, 0x20, 0x04, 0x99, 0x8A, 0x42, ++0x60, 0xDA, 0x04, 0x9A, 0x2A, 0x75, 0x03, 0x9A, 0x00, 0x2A, 0x42, 0xD1, 0x05, 0x99, 0xA1, 0xF6, 0x6C, 0x13, 0x48, 0x2B, ++0x6D, 0xD8, 0x40, 0xF6, 0xB4, 0x13, 0x99, 0x42, 0x00, 0xF0, 0x82, 0x80, 0x48, 0x4A, 0xA1, 0xF6, 0x67, 0x13, 0xA2, 0xFB, ++0x03, 0x23, 0xC3, 0xF3, 0x87, 0x03, 0x2B, 0x74, 0x4F, 0xE7, 0x24, 0x2F, 0x7F, 0xF4, 0x30, 0xAF, 0x09, 0x29, 0x11, 0xD0, ++0x0B, 0x2C, 0x0F, 0xD9, 0xD8, 0xF8, 0x03, 0x10, 0x4B, 0x04, 0x0B, 0xD5, 0x98, 0xF8, 0x09, 0x10, 0x41, 0xB1, 0x01, 0x29, ++0x71, 0xD0, 0x02, 0x29, 0x72, 0xD0, 0x03, 0x29, 0x06, 0x9B, 0x08, 0xBF, 0x04, 0x23, 0x06, 0x93, 0x4F, 0xF0, 0x0E, 0x03, ++0xAB, 0x74, 0x17, 0xE7, 0x89, 0xB3, 0x0D, 0x46, 0xBA, 0xE6, 0x30, 0x2B, 0x24, 0xD9, 0x40, 0x2B, 0x40, 0xD9, 0x90, 0x2B, ++0x4C, 0xD9, 0xA4, 0x2B, 0x59, 0xD8, 0x06, 0x9B, 0x00, 0x2B, 0x54, 0xD0, 0x0A, 0x23, 0x07, 0x9A, 0x01, 0x2A, 0x0C, 0xBF, ++0x74, 0x33, 0x75, 0x33, 0x38, 0xE7, 0x03, 0x9A, 0x01, 0x2A, 0xCA, 0xD1, 0x05, 0x9A, 0xA2, 0xF5, 0x9C, 0x51, 0xA1, 0xF1, ++0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, 0x4D, 0x7F, 0xC1, 0xD8, 0x26, 0x4A, 0xA1, 0xF1, 0x08, 0x03, 0xA2, 0xFB, 0x03, 0x23, ++0xC3, 0xF3, 0x87, 0x03, 0x2B, 0x74, 0x0A, 0xE7, 0x06, 0x9B, 0x23, 0xB3, 0x00, 0x23, 0xE0, 0xE7, 0x2B, 0x7C, 0x04, 0xE7, ++0x02, 0x23, 0x06, 0x93, 0xE4, 0xE6, 0xBC, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x50, 0xAE, 0x9C, 0xF9, 0x14, 0x30, 0x04, 0x9A, ++0x93, 0x42, 0xBF, 0xF6, 0x4A, 0xAE, 0x65, 0x46, 0x7E, 0xE6, 0x82, 0x23, 0x0C, 0xE7, 0x81, 0x23, 0x0A, 0xE7, 0x80, 0x23, ++0x08, 0xE7, 0x03, 0x9B, 0x2B, 0x74, 0xEC, 0xE6, 0x06, 0x9B, 0x8B, 0xB1, 0x03, 0x23, 0xC2, 0xE7, 0x4F, 0xF0, 0x0C, 0x0A, ++0xDC, 0xE6, 0x51, 0x23, 0xFC, 0xE6, 0x73, 0x23, 0xFA, 0xE6, 0x03, 0x23, 0x06, 0x93, 0xC1, 0xE6, 0x06, 0x9B, 0x43, 0xB1, ++0x06, 0x23, 0xB4, 0xE7, 0x52, 0x23, 0xF1, 0xE6, 0x76, 0x23, 0xEF, 0xE6, 0x0E, 0x23, 0x2B, 0x74, 0xD3, 0xE6, 0x79, 0x23, ++0xEA, 0xE6, 0x7C, 0x23, 0xE8, 0xE6, 0x7D, 0x23, 0xE6, 0xE6, 0x02, 0x23, 0x06, 0x93, 0x91, 0xE7, 0x03, 0x23, 0x06, 0x93, ++0x8E, 0xE7, 0x00, 0xBF, 0xCD, 0xCC, 0xCC, 0xCC, 0x2D, 0xE9, 0xF0, 0x48, 0xC1, 0xF3, 0x0A, 0x57, 0xA7, 0xF2, 0xFF, 0x34, ++0x13, 0x2C, 0x0B, 0x46, 0x0D, 0x46, 0x02, 0x46, 0x0F, 0xDC, 0x00, 0x2C, 0x2A, 0xDB, 0x1D, 0x49, 0x21, 0x41, 0x03, 0xEA, ++0x01, 0x00, 0x10, 0x43, 0x2F, 0xD0, 0x4F, 0xF4, 0x00, 0x23, 0x23, 0x41, 0x1D, 0x44, 0x25, 0xEA, 0x01, 0x05, 0x00, 0x23, ++0x25, 0xE0, 0x33, 0x2C, 0x07, 0xDD, 0xB4, 0xF5, 0x80, 0x6F, 0x22, 0xD1, 0x00, 0xF0, 0x2E, 0xF8, 0x02, 0x46, 0x0B, 0x46, ++0x1D, 0xE0, 0xA7, 0xF2, 0x13, 0x47, 0x4F, 0xF0, 0xFF, 0x31, 0x21, 0xFA, 0x07, 0xF7, 0x38, 0x42, 0x15, 0xD0, 0x01, 0x22, ++0xC4, 0xF1, 0x33, 0x03, 0x02, 0xFA, 0x03, 0xF3, 0xC3, 0x18, 0x28, 0xBF, 0xAD, 0x18, 0x23, 0xEA, 0x07, 0x03, 0x08, 0xE0, ++0x01, 0xF0, 0x00, 0x45, 0x01, 0x34, 0x04, 0xBF, 0x45, 0xF0, 0x7F, 0x55, 0x45, 0xF4, 0x40, 0x15, 0x00, 0x23, 0x1A, 0x46, ++0x2B, 0x46, 0x10, 0x46, 0x19, 0x46, 0xBD, 0xE8, 0xF0, 0x88, 0x00, 0xBF, 0xFF, 0xFF, 0x0F, 0x00, 0x81, 0xF0, 0x00, 0x41, ++0x02, 0xE0, 0x00, 0xBF, 0x83, 0xF0, 0x00, 0x43, 0x30, 0xB5, 0x4F, 0xEA, 0x41, 0x04, 0x4F, 0xEA, 0x43, 0x05, 0x94, 0xEA, ++0x05, 0x0F, 0x08, 0xBF, 0x90, 0xEA, 0x02, 0x0F, 0x1F, 0xBF, 0x54, 0xEA, 0x00, 0x0C, 0x55, 0xEA, 0x02, 0x0C, 0x7F, 0xEA, ++0x64, 0x5C, 0x7F, 0xEA, 0x65, 0x5C, 0x00, 0xF0, 0xE2, 0x80, 0x4F, 0xEA, 0x54, 0x54, 0xD4, 0xEB, 0x55, 0x55, 0xB8, 0xBF, ++0x6D, 0x42, 0x0C, 0xDD, 0x2C, 0x44, 0x80, 0xEA, 0x02, 0x02, 0x81, 0xEA, 0x03, 0x03, 0x82, 0xEA, 0x00, 0x00, 0x83, 0xEA, ++0x01, 0x01, 0x80, 0xEA, 0x02, 0x02, 0x81, 0xEA, 0x03, 0x03, 0x36, 0x2D, 0x88, 0xBF, 0x30, 0xBD, 0x11, 0xF0, 0x00, 0x4F, ++0x4F, 0xEA, 0x01, 0x31, 0x4F, 0xF4, 0x80, 0x1C, 0x4C, 0xEA, 0x11, 0x31, 0x02, 0xD0, 0x40, 0x42, 0x61, 0xEB, 0x41, 0x01, ++0x13, 0xF0, 0x00, 0x4F, 0x4F, 0xEA, 0x03, 0x33, 0x4C, 0xEA, 0x13, 0x33, 0x02, 0xD0, 0x52, 0x42, 0x63, 0xEB, 0x43, 0x03, ++0x94, 0xEA, 0x05, 0x0F, 0x00, 0xF0, 0xA7, 0x80, 0xA4, 0xF1, 0x01, 0x04, 0xD5, 0xF1, 0x20, 0x0E, 0x0D, 0xDB, 0x02, 0xFA, ++0x0E, 0xFC, 0x22, 0xFA, 0x05, 0xF2, 0x80, 0x18, 0x41, 0xF1, 0x00, 0x01, 0x03, 0xFA, 0x0E, 0xF2, 0x80, 0x18, 0x43, 0xFA, ++0x05, 0xF3, 0x59, 0x41, 0x0E, 0xE0, 0xA5, 0xF1, 0x20, 0x05, 0x0E, 0xF1, 0x20, 0x0E, 0x01, 0x2A, 0x03, 0xFA, 0x0E, 0xFC, ++0x28, 0xBF, 0x4C, 0xF0, 0x02, 0x0C, 0x43, 0xFA, 0x05, 0xF3, 0xC0, 0x18, 0x51, 0xEB, 0xE3, 0x71, 0x01, 0xF0, 0x00, 0x45, ++0x07, 0xD5, 0x4F, 0xF0, 0x00, 0x0E, 0xDC, 0xF1, 0x00, 0x0C, 0x7E, 0xEB, 0x00, 0x00, 0x6E, 0xEB, 0x01, 0x01, 0xB1, 0xF5, ++0x80, 0x1F, 0x1B, 0xD3, 0xB1, 0xF5, 0x00, 0x1F, 0x0C, 0xD3, 0x49, 0x08, 0x5F, 0xEA, 0x30, 0x00, 0x4F, 0xEA, 0x3C, 0x0C, ++0x04, 0xF1, 0x01, 0x04, 0x4F, 0xEA, 0x44, 0x52, 0x12, 0xF5, 0x80, 0x0F, 0x80, 0xF0, 0x9A, 0x80, 0xBC, 0xF1, 0x00, 0x4F, ++0x08, 0xBF, 0x5F, 0xEA, 0x50, 0x0C, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, 0x04, 0x51, 0x41, 0xEA, 0x05, 0x01, 0x30, 0xBD, ++0x5F, 0xEA, 0x4C, 0x0C, 0x40, 0x41, 0x41, 0xEB, 0x01, 0x01, 0x01, 0x3C, 0x28, 0xBF, 0xB1, 0xF5, 0x80, 0x1F, 0xE9, 0xD2, ++0x91, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x01, 0x46, 0x00, 0x20, 0xB1, 0xFA, 0x81, 0xF3, 0x08, 0xBF, 0x20, 0x33, 0xA3, 0xF1, ++0x0B, 0x03, 0xB3, 0xF1, 0x20, 0x02, 0x0C, 0xDA, 0x0C, 0x32, 0x08, 0xDD, 0x02, 0xF1, 0x14, 0x0C, 0xC2, 0xF1, 0x0C, 0x02, ++0x01, 0xFA, 0x0C, 0xF0, 0x21, 0xFA, 0x02, 0xF1, 0x0C, 0xE0, 0x02, 0xF1, 0x14, 0x02, 0xD8, 0xBF, 0xC2, 0xF1, 0x20, 0x0C, ++0x01, 0xFA, 0x02, 0xF1, 0x20, 0xFA, 0x0C, 0xFC, 0xDC, 0xBF, 0x41, 0xEA, 0x0C, 0x01, 0x90, 0x40, 0xE4, 0x1A, 0xA2, 0xBF, ++0x01, 0xEB, 0x04, 0x51, 0x29, 0x43, 0x30, 0xBD, 0x6F, 0xEA, 0x04, 0x04, 0x1F, 0x3C, 0x1C, 0xDA, 0x0C, 0x34, 0x0E, 0xDC, ++0x04, 0xF1, 0x14, 0x04, 0xC4, 0xF1, 0x20, 0x02, 0x20, 0xFA, 0x04, 0xF0, 0x01, 0xFA, 0x02, 0xF3, 0x40, 0xEA, 0x03, 0x00, ++0x21, 0xFA, 0x04, 0xF3, 0x45, 0xEA, 0x03, 0x01, 0x30, 0xBD, 0xC4, 0xF1, 0x0C, 0x04, 0xC4, 0xF1, 0x20, 0x02, 0x20, 0xFA, ++0x02, 0xF0, 0x01, 0xFA, 0x04, 0xF3, 0x40, 0xEA, 0x03, 0x00, 0x29, 0x46, 0x30, 0xBD, 0x21, 0xFA, 0x04, 0xF0, 0x29, 0x46, ++0x30, 0xBD, 0x94, 0xF0, 0x00, 0x0F, 0x83, 0xF4, 0x80, 0x13, 0x06, 0xBF, 0x81, 0xF4, 0x80, 0x11, 0x01, 0x34, 0x01, 0x3D, ++0x4E, 0xE7, 0x7F, 0xEA, 0x64, 0x5C, 0x18, 0xBF, 0x7F, 0xEA, 0x65, 0x5C, 0x29, 0xD0, 0x94, 0xEA, 0x05, 0x0F, 0x08, 0xBF, ++0x90, 0xEA, 0x02, 0x0F, 0x05, 0xD0, 0x54, 0xEA, 0x00, 0x0C, 0x04, 0xBF, 0x19, 0x46, 0x10, 0x46, 0x30, 0xBD, 0x91, 0xEA, ++0x03, 0x0F, 0x1E, 0xBF, 0x00, 0x21, 0x00, 0x20, 0x30, 0xBD, 0x5F, 0xEA, 0x54, 0x5C, 0x05, 0xD1, 0x40, 0x00, 0x49, 0x41, ++0x28, 0xBF, 0x41, 0xF0, 0x00, 0x41, 0x30, 0xBD, 0x14, 0xF5, 0x80, 0x04, 0x3C, 0xBF, 0x01, 0xF5, 0x80, 0x11, 0x30, 0xBD, ++0x01, 0xF0, 0x00, 0x45, 0x45, 0xF0, 0xFE, 0x41, 0x41, 0xF4, 0x70, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x30, 0xBD, 0x7F, 0xEA, ++0x64, 0x5C, 0x1A, 0xBF, 0x19, 0x46, 0x10, 0x46, 0x7F, 0xEA, 0x65, 0x5C, 0x1C, 0xBF, 0x0B, 0x46, 0x02, 0x46, 0x50, 0xEA, ++0x01, 0x34, 0x06, 0xBF, 0x52, 0xEA, 0x03, 0x35, 0x91, 0xEA, 0x03, 0x0F, 0x41, 0xF4, 0x00, 0x21, 0x30, 0xBD, 0x00, 0xBF, ++0x90, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x00, 0x21, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, 0x32, 0x04, ++0x4F, 0xF0, 0x00, 0x05, 0x4F, 0xF0, 0x00, 0x01, 0x50, 0xE7, 0x00, 0xBF, 0x90, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x00, 0x21, ++0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, 0x32, 0x04, 0x10, 0xF0, 0x00, 0x45, 0x48, 0xBF, 0x40, 0x42, ++0x4F, 0xF0, 0x00, 0x01, 0x3E, 0xE7, 0x00, 0xBF, 0x42, 0x00, 0x4F, 0xEA, 0xE2, 0x01, 0x4F, 0xEA, 0x31, 0x01, 0x4F, 0xEA, ++0x02, 0x70, 0x1F, 0xBF, 0x12, 0xF0, 0x7F, 0x43, 0x93, 0xF0, 0x7F, 0x4F, 0x81, 0xF0, 0x60, 0x51, 0x70, 0x47, 0x32, 0xF0, ++0x7F, 0x42, 0x08, 0xBF, 0x70, 0x47, 0x93, 0xF0, 0x7F, 0x4F, 0x04, 0xBF, 0x41, 0xF4, 0x00, 0x21, 0x70, 0x47, 0x30, 0xB5, ++0x4F, 0xF4, 0x60, 0x74, 0x01, 0xF0, 0x00, 0x45, 0x21, 0xF0, 0x00, 0x41, 0x1C, 0xE7, 0x00, 0xBF, 0x50, 0xEA, 0x01, 0x02, ++0x08, 0xBF, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF0, 0x00, 0x05, 0x0A, 0xE0, 0x50, 0xEA, 0x01, 0x02, 0x08, 0xBF, 0x70, 0x47, ++0x30, 0xB5, 0x11, 0xF0, 0x00, 0x45, 0x02, 0xD5, 0x40, 0x42, 0x61, 0xEB, 0x41, 0x01, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, ++0x32, 0x04, 0x5F, 0xEA, 0x91, 0x5C, 0x3F, 0xF4, 0xD8, 0xAE, 0x4F, 0xF0, 0x03, 0x02, 0x5F, 0xEA, 0xDC, 0x0C, 0x18, 0xBF, ++0x03, 0x32, 0x5F, 0xEA, 0xDC, 0x0C, 0x18, 0xBF, 0x03, 0x32, 0x02, 0xEB, 0xDC, 0x02, 0xC2, 0xF1, 0x20, 0x03, 0x00, 0xFA, ++0x03, 0xFC, 0x20, 0xFA, 0x02, 0xF0, 0x01, 0xFA, 0x03, 0xFE, 0x40, 0xEA, 0x0E, 0x00, 0x21, 0xFA, 0x02, 0xF1, 0x14, 0x44, ++0xBD, 0xE6, 0x00, 0xBF, 0x70, 0xB5, 0x4F, 0xF0, 0xFF, 0x0C, 0x4C, 0xF4, 0xE0, 0x6C, 0x1C, 0xEA, 0x11, 0x54, 0x1D, 0xBF, ++0x1C, 0xEA, 0x13, 0x55, 0x94, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, 0x0F, 0x00, 0xF0, 0xDE, 0xF8, 0x2C, 0x44, 0x81, 0xEA, ++0x03, 0x06, 0x21, 0xEA, 0x4C, 0x51, 0x23, 0xEA, 0x4C, 0x53, 0x50, 0xEA, 0x01, 0x35, 0x18, 0xBF, 0x52, 0xEA, 0x03, 0x35, ++0x41, 0xF4, 0x80, 0x11, 0x43, 0xF4, 0x80, 0x13, 0x38, 0xD0, 0xA0, 0xFB, 0x02, 0xCE, 0x4F, 0xF0, 0x00, 0x05, 0xE1, 0xFB, ++0x02, 0xE5, 0x06, 0xF0, 0x00, 0x42, 0xE0, 0xFB, 0x03, 0xE5, 0x4F, 0xF0, 0x00, 0x06, 0xE1, 0xFB, 0x03, 0x56, 0x9C, 0xF0, ++0x00, 0x0F, 0x18, 0xBF, 0x4E, 0xF0, 0x01, 0x0E, 0xA4, 0xF1, 0xFF, 0x04, 0xB6, 0xF5, 0x00, 0x7F, 0x64, 0xF5, 0x40, 0x74, ++0x04, 0xD2, 0x5F, 0xEA, 0x4E, 0x0E, 0x6D, 0x41, 0x46, 0xEB, 0x06, 0x06, 0x42, 0xEA, 0xC6, 0x21, 0x41, 0xEA, 0x55, 0x51, ++0x4F, 0xEA, 0xC5, 0x20, 0x40, 0xEA, 0x5E, 0x50, 0x4F, 0xEA, 0xCE, 0x2E, 0xB4, 0xF1, 0xFD, 0x0C, 0x88, 0xBF, 0xBC, 0xF5, ++0xE0, 0x6F, 0x1E, 0xD8, 0xBE, 0xF1, 0x00, 0x4F, 0x08, 0xBF, 0x5F, 0xEA, 0x50, 0x0E, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, ++0x04, 0x51, 0x70, 0xBD, 0x06, 0xF0, 0x00, 0x46, 0x46, 0xEA, 0x01, 0x01, 0x40, 0xEA, 0x02, 0x00, 0x81, 0xEA, 0x03, 0x01, ++0xB4, 0xEB, 0x5C, 0x04, 0xC2, 0xBF, 0xD4, 0xEB, 0x0C, 0x05, 0x41, 0xEA, 0x04, 0x51, 0x70, 0xBD, 0x41, 0xF4, 0x80, 0x11, ++0x4F, 0xF0, 0x00, 0x0E, 0x01, 0x3C, 0x00, 0xF3, 0xAB, 0x80, 0x14, 0xF1, 0x36, 0x0F, 0xDE, 0xBF, 0x00, 0x20, 0x01, 0xF0, ++0x00, 0x41, 0x70, 0xBD, 0xC4, 0xF1, 0x00, 0x04, 0x20, 0x3C, 0x35, 0xDA, 0x0C, 0x34, 0x1B, 0xDC, 0x04, 0xF1, 0x14, 0x04, ++0xC4, 0xF1, 0x20, 0x05, 0x00, 0xFA, 0x05, 0xF3, 0x20, 0xFA, 0x04, 0xF0, 0x01, 0xFA, 0x05, 0xF2, 0x40, 0xEA, 0x02, 0x00, ++0x01, 0xF0, 0x00, 0x42, 0x21, 0xF0, 0x00, 0x41, 0x10, 0xEB, 0xD3, 0x70, 0x21, 0xFA, 0x04, 0xF6, 0x42, 0xEB, 0x06, 0x01, ++0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, 0xC4, 0xF1, 0x0C, 0x04, 0xC4, 0xF1, 0x20, 0x05, ++0x00, 0xFA, 0x04, 0xF3, 0x20, 0xFA, 0x05, 0xF0, 0x01, 0xFA, 0x04, 0xF2, 0x40, 0xEA, 0x02, 0x00, 0x01, 0xF0, 0x00, 0x41, ++0x10, 0xEB, 0xD3, 0x70, 0x41, 0xF1, 0x00, 0x01, 0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, ++0xC4, 0xF1, 0x20, 0x05, 0x00, 0xFA, 0x05, 0xF2, 0x4E, 0xEA, 0x02, 0x0E, 0x20, 0xFA, 0x04, 0xF3, 0x01, 0xFA, 0x05, 0xF2, ++0x43, 0xEA, 0x02, 0x03, 0x21, 0xFA, 0x04, 0xF0, 0x01, 0xF0, 0x00, 0x41, 0x21, 0xFA, 0x04, 0xF2, 0x20, 0xEA, 0x02, 0x00, ++0x00, 0xEB, 0xD3, 0x70, 0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, 0x94, 0xF0, 0x00, 0x0F, ++0x0F, 0xD1, 0x01, 0xF0, 0x00, 0x46, 0x40, 0x00, 0x41, 0xEB, 0x01, 0x01, 0x11, 0xF4, 0x80, 0x1F, 0x08, 0xBF, 0x01, 0x3C, ++0xF7, 0xD0, 0x41, 0xEA, 0x06, 0x01, 0x95, 0xF0, 0x00, 0x0F, 0x18, 0xBF, 0x70, 0x47, 0x03, 0xF0, 0x00, 0x46, 0x52, 0x00, ++0x43, 0xEB, 0x03, 0x03, 0x13, 0xF4, 0x80, 0x1F, 0x08, 0xBF, 0x01, 0x3D, 0xF7, 0xD0, 0x43, 0xEA, 0x06, 0x03, 0x70, 0x47, ++0x94, 0xEA, 0x0C, 0x0F, 0x0C, 0xEA, 0x13, 0x55, 0x18, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, 0x0C, 0xD0, 0x50, 0xEA, 0x41, 0x06, ++0x18, 0xBF, 0x52, 0xEA, 0x43, 0x06, 0xD1, 0xD1, 0x81, 0xEA, 0x03, 0x01, 0x01, 0xF0, 0x00, 0x41, 0x4F, 0xF0, 0x00, 0x00, ++0x70, 0xBD, 0x50, 0xEA, 0x41, 0x06, 0x06, 0xBF, 0x10, 0x46, 0x19, 0x46, 0x52, 0xEA, 0x43, 0x06, 0x19, 0xD0, 0x94, 0xEA, ++0x0C, 0x0F, 0x02, 0xD1, 0x50, 0xEA, 0x01, 0x36, 0x13, 0xD1, 0x95, 0xEA, 0x0C, 0x0F, 0x05, 0xD1, 0x52, 0xEA, 0x03, 0x36, ++0x1C, 0xBF, 0x10, 0x46, 0x19, 0x46, 0x0A, 0xD1, 0x81, 0xEA, 0x03, 0x01, 0x01, 0xF0, 0x00, 0x41, 0x41, 0xF0, 0xFE, 0x41, ++0x41, 0xF4, 0x70, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0xBD, 0x41, 0xF0, 0xFE, 0x41, 0x41, 0xF4, 0x78, 0x01, 0x70, 0xBD, ++0x70, 0xB5, 0x4F, 0xF0, 0xFF, 0x0C, 0x4C, 0xF4, 0xE0, 0x6C, 0x1C, 0xEA, 0x11, 0x54, 0x1D, 0xBF, 0x1C, 0xEA, 0x13, 0x55, ++0x94, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, 0x0F, 0x00, 0xF0, 0xA7, 0xF8, 0xA4, 0xEB, 0x05, 0x04, 0x81, 0xEA, 0x03, 0x0E, ++0x52, 0xEA, 0x03, 0x35, 0x4F, 0xEA, 0x01, 0x31, 0x00, 0xF0, 0x88, 0x80, 0x4F, 0xEA, 0x03, 0x33, 0x4F, 0xF0, 0x80, 0x55, ++0x45, 0xEA, 0x13, 0x13, 0x43, 0xEA, 0x12, 0x63, 0x4F, 0xEA, 0x02, 0x22, 0x45, 0xEA, 0x11, 0x15, 0x45, 0xEA, 0x10, 0x65, ++0x4F, 0xEA, 0x00, 0x26, 0x0E, 0xF0, 0x00, 0x41, 0x9D, 0x42, 0x08, 0xBF, 0x96, 0x42, 0x44, 0xF1, 0xFD, 0x04, 0x04, 0xF5, ++0x40, 0x74, 0x02, 0xD2, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0x1A, 0x65, 0xEB, 0x03, 0x05, 0x5B, 0x08, 0x4F, 0xEA, ++0x32, 0x02, 0x4F, 0xF4, 0x80, 0x10, 0x4F, 0xF4, 0x00, 0x2C, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, ++0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x0C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, ++0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x5C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0xEB, ++0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x9C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, ++0x32, 0x02, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0xDC, 0x00, ++0x55, 0xEA, 0x06, 0x0E, 0x18, 0xD0, 0x4F, 0xEA, 0x05, 0x15, 0x45, 0xEA, 0x16, 0x75, 0x4F, 0xEA, 0x06, 0x16, 0x4F, 0xEA, ++0xC3, 0x03, 0x43, 0xEA, 0x52, 0x73, 0x4F, 0xEA, 0xC2, 0x02, 0x5F, 0xEA, 0x1C, 0x1C, 0xC0, 0xD1, 0x11, 0xF4, 0x80, 0x1F, ++0x0B, 0xD1, 0x41, 0xEA, 0x00, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x4F, 0xF0, 0x00, 0x4C, 0xB6, 0xE7, 0x11, 0xF4, 0x80, 0x1F, ++0x04, 0xBF, 0x01, 0x43, 0x00, 0x20, 0xB4, 0xF1, 0xFD, 0x0C, 0x88, 0xBF, 0xBC, 0xF5, 0xE0, 0x6F, 0x3F, 0xF6, 0xAF, 0xAE, ++0xB5, 0xEB, 0x03, 0x0C, 0x04, 0xBF, 0xB6, 0xEB, 0x02, 0x0C, 0x5F, 0xEA, 0x50, 0x0C, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, ++0x04, 0x51, 0x70, 0xBD, 0x0E, 0xF0, 0x00, 0x4E, 0x4E, 0xEA, 0x11, 0x31, 0x14, 0xEB, 0x5C, 0x04, 0xC2, 0xBF, 0xD4, 0xEB, ++0x0C, 0x05, 0x41, 0xEA, 0x04, 0x51, 0x70, 0xBD, 0x41, 0xF4, 0x80, 0x11, 0x4F, 0xF0, 0x00, 0x0E, 0x01, 0x3C, 0x90, 0xE6, ++0x45, 0xEA, 0x06, 0x0E, 0x8D, 0xE6, 0x0C, 0xEA, 0x13, 0x55, 0x94, 0xEA, 0x0C, 0x0F, 0x08, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, ++0x3F, 0xF4, 0x3B, 0xAF, 0x94, 0xEA, 0x0C, 0x0F, 0x0A, 0xD1, 0x50, 0xEA, 0x01, 0x34, 0x7F, 0xF4, 0x34, 0xAF, 0x95, 0xEA, ++0x0C, 0x0F, 0x7F, 0xF4, 0x25, 0xAF, 0x10, 0x46, 0x19, 0x46, 0x2C, 0xE7, 0x95, 0xEA, 0x0C, 0x0F, 0x06, 0xD1, 0x52, 0xEA, ++0x03, 0x35, 0x3F, 0xF4, 0xFD, 0xAE, 0x10, 0x46, 0x19, 0x46, 0x22, 0xE7, 0x50, 0xEA, 0x41, 0x06, 0x18, 0xBF, 0x52, 0xEA, ++0x43, 0x06, 0x7F, 0xF4, 0xC5, 0xAE, 0x50, 0xEA, 0x41, 0x04, 0x7F, 0xF4, 0x0D, 0xAF, 0x52, 0xEA, 0x43, 0x05, 0x7F, 0xF4, ++0xEB, 0xAE, 0x12, 0xE7, 0x4F, 0xF0, 0xFF, 0x3C, 0x06, 0xE0, 0x00, 0xBF, 0x4F, 0xF0, 0x01, 0x0C, 0x02, 0xE0, 0x00, 0xBF, ++0x4F, 0xF0, 0x01, 0x0C, 0x4D, 0xF8, 0x04, 0xCD, 0x4F, 0xEA, 0x41, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0x4F, 0xEA, 0x43, 0x0C, ++0x18, 0xBF, 0x7F, 0xEA, 0x6C, 0x5C, 0x1B, 0xD0, 0x01, 0xB0, 0x50, 0xEA, 0x41, 0x0C, 0x0C, 0xBF, 0x52, 0xEA, 0x43, 0x0C, ++0x91, 0xEA, 0x03, 0x0F, 0x02, 0xBF, 0x90, 0xEA, 0x02, 0x0F, 0x00, 0x20, 0x70, 0x47, 0x10, 0xF1, 0x00, 0x0F, 0x91, 0xEA, ++0x03, 0x0F, 0x58, 0xBF, 0x99, 0x42, 0x08, 0xBF, 0x90, 0x42, 0x2C, 0xBF, 0xD8, 0x17, 0x6F, 0xEA, 0xE3, 0x70, 0x40, 0xF0, ++0x01, 0x00, 0x70, 0x47, 0x4F, 0xEA, 0x41, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0x02, 0xD1, 0x50, 0xEA, 0x01, 0x3C, 0x07, 0xD1, ++0x4F, 0xEA, 0x43, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0xD6, 0xD1, 0x52, 0xEA, 0x03, 0x3C, 0xD3, 0xD0, 0x5D, 0xF8, 0x04, 0x0B, ++0x70, 0x47, 0x00, 0xBF, 0x84, 0x46, 0x10, 0x46, 0x62, 0x46, 0x8C, 0x46, 0x19, 0x46, 0x63, 0x46, 0x00, 0xE0, 0x00, 0xBF, ++0x01, 0xB5, 0xFF, 0xF7, 0xB7, 0xFF, 0x00, 0x28, 0x48, 0xBF, 0x10, 0xF1, 0x00, 0x0F, 0x01, 0xBD, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xF4, 0xFF, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xEA, 0xFF, 0x34, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xE0, 0xFF, 0x94, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xCE, 0xFF, 0x94, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xC4, 0xFF, 0x34, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4A, 0x00, 0x11, 0xD2, ++0x12, 0xF5, 0x00, 0x12, 0x11, 0xD2, 0x0D, 0xD5, 0x6F, 0xF4, 0x78, 0x73, 0xB3, 0xEB, 0x62, 0x52, 0x0E, 0xD4, 0x4F, 0xEA, ++0xC1, 0x23, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xEA, 0x50, 0x53, 0x23, 0xFA, 0x02, 0xF0, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, ++0x70, 0x47, 0x50, 0xEA, 0x01, 0x30, 0x02, 0xD1, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, ++0x4F, 0xEA, 0x41, 0x02, 0xB2, 0xF1, 0xE0, 0x43, 0x24, 0xBF, 0xB3, 0xF5, 0x00, 0x1C, 0xDC, 0xF1, 0xFE, 0x5C, 0x0D, 0xD9, ++0x01, 0xF0, 0x00, 0x4C, 0x4F, 0xEA, 0xC0, 0x02, 0x4C, 0xEA, 0x50, 0x70, 0xB2, 0xF1, 0x00, 0x4F, 0x40, 0xEB, 0x83, 0x00, ++0x08, 0xBF, 0x20, 0xF0, 0x01, 0x00, 0x70, 0x47, 0x11, 0xF0, 0x80, 0x4F, 0x21, 0xD1, 0x13, 0xF1, 0x38, 0x72, 0xBC, 0xBF, ++0x01, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x41, 0xF4, 0x80, 0x11, 0x4F, 0xEA, 0x52, 0x52, 0xC2, 0xF1, 0x18, 0x02, 0xC2, 0xF1, ++0x20, 0x0C, 0x10, 0xFA, 0x0C, 0xF3, 0x20, 0xFA, 0x02, 0xF0, 0x18, 0xBF, 0x40, 0xF0, 0x01, 0x00, 0x4F, 0xEA, 0xC1, 0x23, ++0x4F, 0xEA, 0xD3, 0x23, 0x03, 0xFA, 0x0C, 0xFC, 0x40, 0xEA, 0x0C, 0x00, 0x23, 0xFA, 0x02, 0xF3, 0x4F, 0xEA, 0x43, 0x03, ++0xCC, 0xE7, 0x7F, 0xEA, 0x62, 0x53, 0x07, 0xD1, 0x50, 0xEA, 0x01, 0x33, 0x1E, 0xBF, 0x4F, 0xF0, 0xFE, 0x40, 0x40, 0xF4, ++0x40, 0x00, 0x70, 0x47, 0x01, 0xF0, 0x00, 0x40, 0x40, 0xF0, 0xFE, 0x40, 0x40, 0xF4, 0x00, 0x00, 0x70, 0x47, 0x00, 0xBF, ++0x53, 0xB9, 0x4A, 0xB9, 0x00, 0x29, 0x08, 0xBF, 0x00, 0x28, 0x1C, 0xBF, 0x4F, 0xF0, 0xFF, 0x31, 0x4F, 0xF0, 0xFF, 0x30, ++0x00, 0xF0, 0x6C, 0xB9, 0xAD, 0xF1, 0x08, 0x0C, 0x6D, 0xE9, 0x04, 0xCE, 0x00, 0xF0, 0x06, 0xF8, 0xDD, 0xF8, 0x04, 0xE0, ++0xDD, 0xE9, 0x02, 0x23, 0x04, 0xB0, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, 0x08, 0x9E, 0x0D, 0x46, 0x04, 0x46, 0x8E, 0x46, ++0x00, 0x2B, 0x40, 0xF0, 0x82, 0x80, 0x8A, 0x42, 0x17, 0x46, 0x46, 0xD9, 0xB2, 0xFA, 0x82, 0xF2, 0x4A, 0xB1, 0xC2, 0xF1, ++0x20, 0x01, 0x05, 0xFA, 0x02, 0xF3, 0x20, 0xFA, 0x01, 0xF1, 0x97, 0x40, 0x41, 0xEA, 0x03, 0x0E, 0x94, 0x40, 0x4F, 0xEA, ++0x17, 0x48, 0x23, 0x0C, 0xBE, 0xFB, 0xF8, 0xFC, 0xB9, 0xB2, 0x08, 0xFB, 0x1C, 0xEE, 0x43, 0xEA, 0x0E, 0x43, 0x0C, 0xFB, ++0x01, 0xF0, 0x98, 0x42, 0x0A, 0xD9, 0xFB, 0x18, 0x0C, 0xF1, 0xFF, 0x35, 0x80, 0xF0, 0x16, 0x81, 0x98, 0x42, 0x40, 0xF2, ++0x13, 0x81, 0xAC, 0xF1, 0x02, 0x0C, 0x3B, 0x44, 0x1B, 0x1A, 0xA4, 0xB2, 0xB3, 0xFB, 0xF8, 0xF0, 0x08, 0xFB, 0x10, 0x33, ++0x44, 0xEA, 0x03, 0x44, 0x00, 0xFB, 0x01, 0xF1, 0xA1, 0x42, 0x09, 0xD9, 0x3C, 0x19, 0x00, 0xF1, 0xFF, 0x33, 0x80, 0xF0, ++0x01, 0x81, 0xA1, 0x42, 0x40, 0xF2, 0xFE, 0x80, 0x02, 0x38, 0x3C, 0x44, 0x64, 0x1A, 0x40, 0xEA, 0x0C, 0x40, 0x00, 0x21, ++0x1E, 0xB1, 0xD4, 0x40, 0x00, 0x23, 0xC6, 0xE9, 0x00, 0x43, 0xBD, 0xE8, 0xF0, 0x87, 0x02, 0xB9, 0xFF, 0xDE, 0xB2, 0xFA, ++0x82, 0xF2, 0x00, 0x2A, 0x4F, 0xD1, 0xCB, 0x1B, 0x4F, 0xEA, 0x17, 0x4E, 0x1F, 0xFA, 0x87, 0xF8, 0x01, 0x21, 0xB3, 0xFB, ++0xFE, 0xFC, 0x25, 0x0C, 0x0E, 0xFB, 0x1C, 0x33, 0x45, 0xEA, 0x03, 0x45, 0x08, 0xFB, 0x0C, 0xF3, 0xAB, 0x42, 0x07, 0xD9, ++0x7D, 0x19, 0x0C, 0xF1, 0xFF, 0x30, 0x02, 0xD2, 0xAB, 0x42, 0x00, 0xF2, 0xE7, 0x80, 0x84, 0x46, 0xED, 0x1A, 0xA3, 0xB2, ++0xB5, 0xFB, 0xFE, 0xF0, 0x0E, 0xFB, 0x10, 0x55, 0x43, 0xEA, 0x05, 0x44, 0x08, 0xFB, 0x00, 0xF8, 0xA0, 0x45, 0x07, 0xD9, ++0x3C, 0x19, 0x00, 0xF1, 0xFF, 0x33, 0x02, 0xD2, 0xA0, 0x45, 0x00, 0xF2, 0xD7, 0x80, 0x18, 0x46, 0xA4, 0xEB, 0x08, 0x04, ++0x40, 0xEA, 0x0C, 0x40, 0xC0, 0xE7, 0x8B, 0x42, 0x08, 0xD9, 0x00, 0x2E, 0x00, 0xF0, 0xAF, 0x80, 0x00, 0x21, 0xC6, 0xE9, ++0x00, 0x05, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xB3, 0xFA, 0x83, 0xF1, 0x00, 0x29, 0x4B, 0xD1, 0xAB, 0x42, 0x02, 0xD3, ++0x82, 0x42, 0x00, 0xF2, 0xB7, 0x80, 0x84, 0x1A, 0x65, 0xEB, 0x03, 0x03, 0x01, 0x20, 0x9E, 0x46, 0x00, 0x2E, 0xAA, 0xD0, ++0xC6, 0xE9, 0x00, 0x4E, 0xA7, 0xE7, 0xC2, 0xF1, 0x20, 0x0C, 0x01, 0xFA, 0x02, 0xF3, 0x97, 0x40, 0x20, 0xFA, 0x0C, 0xF0, ++0x4F, 0xEA, 0x17, 0x4E, 0x21, 0xFA, 0x0C, 0xFC, 0x18, 0x43, 0xBC, 0xFB, 0xFE, 0xF1, 0x05, 0x0C, 0x0E, 0xFB, 0x11, 0xCC, ++0x1F, 0xFA, 0x87, 0xF8, 0x45, 0xEA, 0x0C, 0x45, 0x01, 0xFB, 0x08, 0xF3, 0xAB, 0x42, 0x04, 0xFA, 0x02, 0xF4, 0x09, 0xD9, ++0x7D, 0x19, 0x01, 0xF1, 0xFF, 0x3C, 0x80, 0xF0, 0x8B, 0x80, 0xAB, 0x42, 0x40, 0xF2, 0x88, 0x80, 0x02, 0x39, 0x3D, 0x44, ++0xEB, 0x1A, 0x85, 0xB2, 0xB3, 0xFB, 0xFE, 0xF0, 0x0E, 0xFB, 0x10, 0x33, 0x45, 0xEA, 0x03, 0x45, 0x00, 0xFB, 0x08, 0xF3, ++0xAB, 0x42, 0x07, 0xD9, 0x7D, 0x19, 0x00, 0xF1, 0xFF, 0x3C, 0x71, 0xD2, 0xAB, 0x42, 0x6F, 0xD9, 0x02, 0x38, 0x3D, 0x44, ++0xEB, 0x1A, 0x40, 0xEA, 0x01, 0x41, 0x78, 0xE7, 0xC1, 0xF1, 0x20, 0x0C, 0x8B, 0x40, 0x22, 0xFA, 0x0C, 0xF7, 0x1F, 0x43, ++0x20, 0xFA, 0x0C, 0xF4, 0x05, 0xFA, 0x01, 0xF3, 0x4F, 0xEA, 0x17, 0x4E, 0x25, 0xFA, 0x0C, 0xF5, 0x1C, 0x43, 0x23, 0x0C, ++0xB5, 0xFB, 0xFE, 0xF9, 0x1F, 0xFA, 0x87, 0xF8, 0x0E, 0xFB, 0x19, 0x55, 0x43, 0xEA, 0x05, 0x45, 0x09, 0xFB, 0x08, 0xFA, ++0xAA, 0x45, 0x02, 0xFA, 0x01, 0xF2, 0x00, 0xFA, 0x01, 0xF3, 0x08, 0xD9, 0x7D, 0x19, 0x09, 0xF1, 0xFF, 0x30, 0x47, 0xD2, ++0xAA, 0x45, 0x45, 0xD9, 0xA9, 0xF1, 0x02, 0x09, 0x3D, 0x44, 0xA5, 0xEB, 0x0A, 0x05, 0xA4, 0xB2, 0xB5, 0xFB, 0xFE, 0xF0, ++0x0E, 0xFB, 0x10, 0x55, 0x44, 0xEA, 0x05, 0x44, 0x00, 0xFB, 0x08, 0xF8, 0xA0, 0x45, 0x07, 0xD9, 0x3C, 0x19, 0x00, 0xF1, ++0xFF, 0x35, 0x2D, 0xD2, 0xA0, 0x45, 0x2B, 0xD9, 0x02, 0x38, 0x3C, 0x44, 0x40, 0xEA, 0x09, 0x40, 0xA4, 0xEB, 0x08, 0x04, ++0xA0, 0xFB, 0x02, 0x89, 0x4C, 0x45, 0xC6, 0x46, 0x4D, 0x46, 0x19, 0xD3, 0x16, 0xD0, 0x5E, 0xB1, 0xB3, 0xEB, 0x0E, 0x02, ++0x64, 0xEB, 0x05, 0x04, 0x04, 0xFA, 0x0C, 0xFC, 0xCA, 0x40, 0x4C, 0xEA, 0x02, 0x02, 0xCC, 0x40, 0xC6, 0xE9, 0x00, 0x24, ++0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x87, 0x31, 0x46, 0x30, 0x46, 0x0E, 0xE7, 0xAC, 0x46, 0xED, 0xE6, 0x18, 0x46, 0x01, 0xE7, ++0x43, 0x45, 0xE6, 0xD2, 0xB8, 0xEB, 0x02, 0x0E, 0x69, 0xEB, 0x07, 0x05, 0x01, 0x38, 0xE0, 0xE7, 0x28, 0x46, 0xD3, 0xE7, ++0x60, 0x46, 0x8F, 0xE7, 0x81, 0x46, 0xBA, 0xE7, 0x61, 0x46, 0x77, 0xE7, 0x08, 0x46, 0x4B, 0xE7, 0xAC, 0xF1, 0x02, 0x0C, ++0x3D, 0x44, 0x15, 0xE7, 0x02, 0x38, 0x3C, 0x44, 0x26, 0xE7, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x28, 0xB8, 0xBF, ++0x40, 0x42, 0x70, 0x47, 0x03, 0x2A, 0x70, 0xB4, 0x12, 0xD9, 0x40, 0xEA, 0x01, 0x05, 0xAD, 0x07, 0x04, 0x46, 0x0B, 0x46, ++0x1E, 0xD1, 0x19, 0x46, 0x20, 0x46, 0x53, 0xF8, 0x04, 0x5B, 0x54, 0xF8, 0x04, 0x6B, 0xAE, 0x42, 0x16, 0xD1, 0x04, 0x3A, ++0x03, 0x2A, 0x20, 0x46, 0x19, 0x46, 0xF2, 0xD8, 0x56, 0x1E, 0xA2, 0xB1, 0x01, 0x39, 0x44, 0x1E, 0x01, 0xE0, 0xC3, 0x18, ++0x0C, 0xD0, 0x14, 0xF8, 0x01, 0x5F, 0x11, 0xF8, 0x01, 0x2F, 0x95, 0x42, 0xA6, 0xEB, 0x04, 0x03, 0xF5, 0xD0, 0xA8, 0x1A, ++0x70, 0xBC, 0x70, 0x47, 0x56, 0x1E, 0xED, 0xE7, 0x18, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x10, 0x46, 0xF6, 0xE7, 0x00, 0xBF, ++0x84, 0x46, 0x41, 0xEA, 0x00, 0x03, 0x13, 0xF0, 0x03, 0x03, 0x6D, 0xD1, 0x40, 0x3A, 0x41, 0xD3, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x40, 0x3A, 0xBD, 0xD2, 0x30, 0x32, 0x11, 0xD3, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x10, 0x3A, 0xED, 0xD2, 0x0C, 0x32, 0x05, 0xD3, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x04, 0x3A, 0xF9, 0xD2, 0x04, 0x32, 0x08, 0xD0, 0xD2, 0x07, 0x1C, 0xBF, 0x11, 0xF8, 0x01, 0x3B, 0x00, 0xF8, 0x01, 0x3B, ++0x01, 0xD3, 0x0B, 0x88, 0x03, 0x80, 0x60, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x08, 0x2A, 0x13, 0xD3, 0x8B, 0x07, 0x8D, 0xD0, ++0x10, 0xF0, 0x03, 0x03, 0x8A, 0xD0, 0xC3, 0xF1, 0x04, 0x03, 0xD2, 0x1A, 0xDB, 0x07, 0x1C, 0xBF, 0x11, 0xF8, 0x01, 0x3B, ++0x00, 0xF8, 0x01, 0x3B, 0x80, 0xD3, 0x31, 0xF8, 0x02, 0x3B, 0x20, 0xF8, 0x02, 0x3B, 0x7B, 0xE7, 0x04, 0x3A, 0xD9, 0xD3, ++0x01, 0x3A, 0x11, 0xF8, 0x01, 0x3B, 0x00, 0xF8, 0x01, 0x3B, 0xF9, 0xD2, 0x0B, 0x78, 0x03, 0x70, 0x4B, 0x78, 0x43, 0x70, ++0x8B, 0x78, 0x83, 0x70, 0x60, 0x46, 0x70, 0x47, 0x88, 0x42, 0xF0, 0xB4, 0x0D, 0xD9, 0x8B, 0x18, 0x83, 0x42, 0x0A, 0xD9, ++0x84, 0x18, 0x32, 0xB1, 0x22, 0x46, 0x13, 0xF8, 0x01, 0x4D, 0x02, 0xF8, 0x01, 0x4D, 0x99, 0x42, 0xF9, 0xD1, 0xF0, 0xBC, ++0x70, 0x47, 0x0F, 0x2A, 0x0E, 0xD8, 0x03, 0x46, 0x54, 0x1E, 0x00, 0x2A, 0xF7, 0xD0, 0x01, 0x34, 0x0C, 0x44, 0x01, 0x3B, ++0x11, 0xF8, 0x01, 0x2B, 0x03, 0xF8, 0x01, 0x2F, 0xA1, 0x42, 0xF9, 0xD1, 0xF0, 0xBC, 0x70, 0x47, 0x40, 0xEA, 0x01, 0x03, ++0x9B, 0x07, 0x3F, 0xD1, 0xA2, 0xF1, 0x10, 0x03, 0x23, 0xF0, 0x0F, 0x04, 0x01, 0xF1, 0x20, 0x07, 0x27, 0x44, 0x1B, 0x09, ++0x01, 0xF1, 0x10, 0x04, 0x00, 0xF1, 0x10, 0x05, 0x54, 0xF8, 0x10, 0x6C, 0x45, 0xF8, 0x10, 0x6C, 0x54, 0xF8, 0x0C, 0x6C, ++0x45, 0xF8, 0x0C, 0x6C, 0x54, 0xF8, 0x08, 0x6C, 0x45, 0xF8, 0x08, 0x6C, 0x54, 0xF8, 0x04, 0x6C, 0x45, 0xF8, 0x04, 0x6C, ++0x10, 0x34, 0xBC, 0x42, 0x05, 0xF1, 0x10, 0x05, 0xEA, 0xD1, 0x01, 0x33, 0x12, 0xF0, 0x0C, 0x0F, 0x01, 0xEB, 0x03, 0x11, ++0x02, 0xF0, 0x0F, 0x04, 0x00, 0xEB, 0x03, 0x13, 0x17, 0xD0, 0x04, 0x3C, 0x24, 0xF0, 0x03, 0x0C, 0xA5, 0x08, 0x9C, 0x44, ++0x1C, 0x1F, 0x0E, 0x46, 0x56, 0xF8, 0x04, 0x7B, 0x44, 0xF8, 0x04, 0x7F, 0x64, 0x45, 0xF9, 0xD1, 0x6C, 0x1C, 0x03, 0xEB, ++0x84, 0x03, 0x01, 0xEB, 0x84, 0x01, 0x02, 0xF0, 0x03, 0x02, 0xAD, 0xE7, 0x54, 0x1E, 0x03, 0x46, 0xAD, 0xE7, 0x22, 0x46, ++0xA8, 0xE7, 0x00, 0xBF, 0x0B, 0x4B, 0x0C, 0x48, 0x19, 0x68, 0xD1, 0xE9, 0x2A, 0x23, 0x10, 0xB4, 0x0A, 0x4C, 0x00, 0xFB, ++0x02, 0xF0, 0x04, 0xFB, 0x03, 0x00, 0xA2, 0xFB, 0x04, 0x34, 0x04, 0x44, 0x5A, 0x1C, 0x44, 0xF1, 0x00, 0x00, 0xC1, 0xE9, ++0x2A, 0x20, 0x10, 0xBC, 0x20, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x80, 0x01, 0x17, 0x00, 0x2D, 0xF4, 0x51, 0x58, ++0x2D, 0x7F, 0x95, 0x4C, 0x11, 0xF0, 0xFF, 0x01, 0x03, 0x46, 0x44, 0xD0, 0x82, 0x07, 0x32, 0xD1, 0x70, 0xB4, 0x04, 0x68, ++0x41, 0xEA, 0x01, 0x26, 0x46, 0xEA, 0x06, 0x46, 0x86, 0xEA, 0x04, 0x05, 0xA5, 0xF1, 0x01, 0x33, 0xA4, 0xF1, 0x01, 0x32, ++0x23, 0xEA, 0x05, 0x03, 0x22, 0xEA, 0x04, 0x02, 0x13, 0x43, 0x13, 0xF0, 0x80, 0x3F, 0x0F, 0xD1, 0x50, 0xF8, 0x04, 0x4F, ++0x84, 0xEA, 0x06, 0x05, 0xA5, 0xF1, 0x01, 0x32, 0xA4, 0xF1, 0x01, 0x33, 0x22, 0xEA, 0x05, 0x02, 0x23, 0xEA, 0x04, 0x03, ++0x13, 0x43, 0x13, 0xF0, 0x80, 0x3F, 0xEF, 0xD0, 0x03, 0x78, 0x23, 0xB9, 0x36, 0xE0, 0x10, 0xF8, 0x01, 0x3F, 0x00, 0x2B, ++0x32, 0xD0, 0x99, 0x42, 0xF9, 0xD1, 0x30, 0xE0, 0x8A, 0x42, 0x11, 0xD0, 0x9A, 0x07, 0x18, 0x46, 0xCC, 0xD0, 0x18, 0x46, ++0x13, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0xF5, 0xD1, 0x10, 0x46, 0x70, 0x47, 0x99, 0x07, 0x18, 0x46, 0x07, 0xD0, 0x18, 0x46, ++0x01, 0x33, 0x02, 0x78, 0x00, 0x2A, 0xF7, 0xD1, 0x70, 0x47, 0x82, 0x07, 0xF7, 0xD1, 0x02, 0x68, 0xA2, 0xF1, 0x01, 0x33, ++0x23, 0xEA, 0x02, 0x03, 0x13, 0xF0, 0x80, 0x3F, 0x08, 0xD1, 0x50, 0xF8, 0x04, 0x2F, 0xA2, 0xF1, 0x01, 0x33, 0x23, 0xEA, ++0x02, 0x03, 0x13, 0xF0, 0x80, 0x3F, 0xF6, 0xD0, 0x03, 0x78, 0x00, 0x2B, 0xE8, 0xD0, 0x10, 0xF8, 0x01, 0x3F, 0x00, 0x2B, ++0xFB, 0xD1, 0x70, 0x47, 0x18, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x80, 0xEA, 0x01, 0x02, 0x84, 0x46, 0x12, 0xF0, ++0x03, 0x0F, 0x4F, 0xD1, 0x11, 0xF0, 0x03, 0x0F, 0x32, 0xD1, 0x4D, 0xF8, 0x04, 0x4D, 0x11, 0xF0, 0x04, 0x0F, 0x51, 0xF8, ++0x04, 0x3B, 0x0B, 0xD0, 0xA3, 0xF1, 0x01, 0x32, 0x9A, 0x43, 0x12, 0xF0, 0x80, 0x3F, 0x04, 0xBF, 0x4C, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x16, 0xD1, 0x00, 0xBF, 0x51, 0xF8, 0x04, 0x4B, 0xA3, 0xF1, 0x01, 0x32, 0x9A, 0x43, 0x12, 0xF0, ++0x80, 0x3F, 0xA4, 0xF1, 0x01, 0x32, 0x0B, 0xD1, 0x4C, 0xF8, 0x04, 0x3B, 0xA2, 0x43, 0x12, 0xF0, 0x80, 0x3F, 0x04, 0xBF, ++0x51, 0xF8, 0x04, 0x3B, 0x4C, 0xF8, 0x04, 0x4B, 0xEA, 0xD0, 0x23, 0x46, 0x0C, 0xF8, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x0F, ++0x4F, 0xEA, 0x33, 0x23, 0xF8, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x11, 0xF0, 0x01, 0x0F, 0x06, 0xD0, 0x11, 0xF8, ++0x01, 0x2B, 0x0C, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0x08, 0xBF, 0x70, 0x47, 0x11, 0xF0, 0x02, 0x0F, 0xBF, 0xD0, 0x31, 0xF8, ++0x02, 0x2B, 0x12, 0xF0, 0xFF, 0x0F, 0x16, 0xBF, 0x2C, 0xF8, 0x02, 0x2B, 0x8C, 0xF8, 0x00, 0x20, 0x12, 0xF4, 0x7F, 0x4F, ++0xB3, 0xD1, 0x70, 0x47, 0x11, 0xF8, 0x01, 0x2B, 0x0C, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0xF9, 0xD1, 0x70, 0x47, 0x00, 0xBF, ++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, 0x00, 0x00, 0x00, 0x00, 0x90, 0xF8, 0x00, 0xF0, ++0x6D, 0xE9, 0x02, 0x45, 0x20, 0xF0, 0x07, 0x01, 0x6F, 0xF0, 0x00, 0x0C, 0x10, 0xF0, 0x07, 0x04, 0x91, 0xF8, 0x20, 0xF0, ++0x40, 0xF0, 0x49, 0x80, 0x4F, 0xF0, 0x00, 0x04, 0x6F, 0xF0, 0x07, 0x00, 0xD1, 0xE9, 0x00, 0x23, 0x91, 0xF8, 0x40, 0xF0, ++0x00, 0xF1, 0x08, 0x00, 0x82, 0xFA, 0x4C, 0xF2, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, ++0x4B, 0xBB, 0xD1, 0xE9, 0x02, 0x23, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, ++0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, 0xE3, 0xB9, 0xD1, 0xE9, 0x04, 0x23, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, ++0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, 0x7B, 0xB9, 0xD1, 0xE9, 0x06, 0x23, 0x01, 0xF1, ++0x20, 0x01, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, ++0x8C, 0xF3, 0x00, 0x2B, 0xC6, 0xD0, 0x00, 0x2A, 0x04, 0xBF, 0x04, 0x30, 0x1A, 0x46, 0x12, 0xBA, 0xB2, 0xFA, 0x82, 0xF2, ++0xFD, 0xE8, 0x02, 0x45, 0x00, 0xEB, 0xD2, 0x00, 0x70, 0x47, 0xD1, 0xE9, 0x00, 0x23, 0x04, 0xF0, 0x03, 0x05, 0xC4, 0xF1, ++0x00, 0x00, 0x4F, 0xEA, 0xC5, 0x05, 0x14, 0xF0, 0x04, 0x0F, 0x91, 0xF8, 0x40, 0xF0, 0x0C, 0xFA, 0x05, 0xF5, 0x62, 0xEA, ++0x05, 0x02, 0x1C, 0xBF, 0x63, 0xEA, 0x05, 0x03, 0x62, 0x46, 0x4F, 0xF0, 0x00, 0x04, 0xA9, 0xE7, 0x9A, 0xB3, 0xF0, 0xB4, ++0x40, 0xEA, 0x01, 0x05, 0xAD, 0x07, 0x04, 0x46, 0x03, 0x46, 0x08, 0x46, 0x28, 0xD0, 0x20, 0x78, 0x0E, 0x78, 0x86, 0x42, ++0x29, 0xD1, 0x01, 0x2A, 0x2A, 0xD0, 0x25, 0x46, 0x50, 0xB1, 0x15, 0xF8, 0x01, 0x0F, 0x11, 0xF8, 0x01, 0x6F, 0xEB, 0x43, ++0xB0, 0x42, 0x13, 0x44, 0x1D, 0xD1, 0xE3, 0x18, 0xF4, 0xD1, 0x18, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0x07, 0x68, 0x1C, 0x46, ++0x53, 0xF8, 0x04, 0x5B, 0xA5, 0xF1, 0x01, 0x36, 0xBD, 0x42, 0x01, 0x46, 0x26, 0xEA, 0x05, 0x06, 0x00, 0xF1, 0x04, 0x00, ++0xDD, 0xD1, 0x04, 0x3A, 0x1C, 0x46, 0x01, 0x46, 0x0A, 0xD0, 0x16, 0xF0, 0x80, 0x3F, 0x07, 0xD1, 0x03, 0x2A, 0xE9, 0xD8, ++0xD3, 0xE7, 0x10, 0x46, 0x70, 0x47, 0x80, 0x1B, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0x20, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0xBF, ++0x6D, 0x65, 0x6D, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x6C, 0x61, 0x70, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x6B, 0x5F, 0x73, 0x74, ++0x61, 0x72, 0x74, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x5F, 0x65, 0x6E, 0x64, 0x3D, 0x25, 0x78, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x6D, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x6C, 0x61, 0x70, 0x73, 0x3A, 0x20, 0x73, 0x74, ++0x6B, 0x5F, 0x65, 0x6E, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x3D, ++0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, ++0x6D, 0x61, 0x69, 0x6E, 0x21, 0x0D, 0x0A, 0x00, 0x10, 0x14, 0x08, 0x12, 0x3C, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, ++0x08, 0x12, 0xC7, 0x11, 0x10, 0x14, 0x08, 0x12, 0x3C, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, 0x08, 0x12, 0x45, 0x11, ++0x08, 0x12, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0x03, 0x11, 0x08, 0x12, 0x04, 0x11, ++0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0xC2, 0x10, 0x08, 0x12, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, ++0x07, 0x12, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x86, 0x11, 0xC3, 0x10, ++0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x86, 0x11, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, ++0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, 0x08, 0x12, 0x04, 0x11, ++0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, 0x08, 0x12, 0x03, 0x11, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, ++0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x8A, 0x12, 0x0C, 0x13, ++0x04, 0x11, 0x03, 0x11, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x8A, 0x12, 0x86, 0x11, 0x04, 0x11, 0x03, 0x11, ++0x9D, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x62, 0x61, 0x6E, 0x64, 0x3D, 0x25, 0x64, 0x20, 0x66, 0x72, 0x65, 0x71, 0x3D, 0x25, ++0x64, 0x20, 0x66, 0x72, 0x65, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x74, 0x79, 0x70, 0x65, 0x3D, ++0x25, 0x64, 0x20, 0x73, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x63, 0x68, 0x61, 0x6E, 0x3A, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x62, 0x61, 0x6E, 0x64, 0x20, ++0x25, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x62, 0x61, 0x6E, 0x64, 0x20, 0x3C, 0x20, 0x50, ++0x48, 0x59, 0x5F, 0x42, 0x41, 0x4E, 0x44, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x28, 0x6D, 0x64, 0x6D, 0x5F, 0x6D, 0x61, 0x6A, ++0x6F, 0x72, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x2B, 0x20, ++0x32, 0x29, 0x20, 0x2A, 0x20, 0x31, 0x30, 0x20, 0x2B, 0x20, 0x6D, 0x64, 0x6D, 0x5F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x5F, ++0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x58, ++0x5F, 0x4D, 0x44, 0x4D, 0x5F, 0x56, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x72, 0x61, ++0x64, 0x69, 0x6F, 0x20, 0x25, 0x64, 0x20, 0x64, 0x6F, 0x65, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, ++0x74, 0x0A, 0x00, 0x00, 0x9D, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x61, ++0x6D, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x2C, 0x20, 0x64, 0x6F, 0x20, 0x6E, 0x6F, 0x74, 0x68, 0x69, ++0x6E, 0x67, 0x0A, 0x00, 0x9B, 0x25, 0x73, 0x20, 0x4D, 0x41, 0x43, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x21, 0x3D, ++0x20, 0x49, 0x44, 0x4C, 0x45, 0x0A, 0x00, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x68, 0x77, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x63, ++0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x00, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x63, 0x68, 0x61, 0x6E, ++0x6E, 0x65, 0x6C, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x67, 0x65, 0x74, 0x5F, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x00, ++0x70, 0x68, 0x79, 0x5F, 0x73, 0x74, 0x6F, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x0D, 0xFE, 0x11, 0xFE, 0x0D, 0x02, ++0x0E, 0xFF, 0x13, 0xFE, 0x0B, 0x02, 0x0C, 0xFD, 0x12, 0xFD, 0x0C, 0x03, 0x0D, 0xFE, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, ++0x14, 0xFD, 0x0A, 0x03, 0x0B, 0xFC, 0x11, 0xFF, 0x0D, 0x01, 0x0E, 0xFF, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x12, 0xFE, ++0x0C, 0x02, 0x0D, 0xFE, 0x12, 0xFE, 0x0C, 0x02, 0x0D, 0xFE, 0x12, 0xFE, 0x0C, 0x02, 0x0D, 0xFE, 0x13, 0xFE, 0x0B, 0x02, ++0x0C, 0xFD, 0x1F, 0x00, 0x0C, 0x02, 0x0D, 0xFE, 0x11, 0x00, 0x0D, 0x00, 0x0E, 0xFF, 0x13, 0x03, 0x0B, 0x03, 0x0C, 0xFD, ++0x14, 0xFC, 0x0A, 0x04, 0x0B, 0xFC, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x11, 0xFE, 0x0D, 0x02, 0x0E, 0xFF, 0x13, 0xFE, ++0x0B, 0x02, 0x0C, 0xFD, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x12, 0xFD, 0x0C, 0x03, ++0x0D, 0xFE, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x13, 0xFE, 0x0B, 0x02, 0x0C, 0xFD, ++0x1F, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x74, 0x63, 0x5F, 0x73, 0x70, 0x75, 0x72, 0x69, 0x6F, 0x75, 0x73, 0x00, 0x00, 0x00, ++0x18, 0x10, 0x0C, 0x08, 0x07, 0x06, 0x8B, 0x05, 0x89, 0x04, 0x87, 0x03, 0x85, 0x02, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x65, 0x74, 0x20, 0x74, 0x78, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x32, 0x2E, 0x34, ++0x67, 0x28, 0x70, 0x61, 0x5F, 0x64, 0x72, 0x76, 0x5F, 0x69, 0x62, 0x69, 0x74, 0x29, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x77, 0x66, 0x20, 0x64, 0x66, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x66, 0x69, 0x6E, 0x74, 0x66, 0x20, 0x52, 0x58, ++0x4F, 0x4E, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, 0x66, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, ++0x66, 0x69, 0x6E, 0x74, 0x66, 0x20, 0x52, 0x58, 0x4F, 0x46, 0x46, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x64, 0x65, 0x74, 0x65, ++0x63, 0x74, 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x62, 0x79, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, ++0x69, 0x6E, 0x20, 0x63, 0x61, 0x6C, 0x5F, 0x6C, 0x73, 0x20, 0x64, 0x65, 0x74, 0x20, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x6C, 0x6F, 0x70, 0x65, 0x20, 0x74, 0x6F, 0x6F, 0x20, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x66, 0x69, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, ++0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x66, 0x69, ++0x74, 0x5F, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x21, 0x0D, 0x0A, 0x00, 0x63, 0x6F, 0x65, 0x66, 0x5F, 0x49, 0x51, 0x20, ++0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2E, 0x00, 0x25, 0x30, 0x33, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, ++0x73, 0x64, 0x6D, 0x20, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, ++0x66, 0x72, 0x65, 0x71, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, ++0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x66, 0x65, 0x6E, ++0x20, 0x72, 0x65, 0x67, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, ++0x63, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x21, 0x0D, 0x0A, 0x00, 0x66, 0x69, 0x74, 0x2D, ++0x69, 0x6E, 0x2D, 0x49, 0x20, 0x25, 0x78, 0x3A, 0x20, 0x5B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, ++0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x5D, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x66, 0x69, 0x74, 0x2D, 0x69, 0x6E, 0x2D, 0x51, 0x20, 0x25, 0x78, 0x3A, 0x20, 0x5B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x5D, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x63, 0x61, 0x6C, 0x49, 0x20, 0x25, ++0x78, 0x2C, 0x20, 0x63, 0x61, 0x6C, 0x51, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, ++0x63, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x20, 0x65, 0x6E, 0x64, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x5F, ++0x63, 0x66, 0x67, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, ++0x70, 0x6C, 0x6C, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x63, 0x6B, 0x3A, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x77, 0x66, 0x72, 0x66, 0x20, 0x6F, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x66, 0x72, 0x66, 0x20, 0x6F, 0x66, 0x66, ++0x0D, 0x0A, 0x00, 0x00, 0x20, 0x2A, 0x20, 0x63, 0x61, 0x6C, 0x20, 0x74, 0x69, 0x61, 0x5F, 0x69, 0x71, 0x3A, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x49, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x30, 0x3D, 0x25, 0x64, ++0x2C, 0x20, 0x56, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x30, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, ++0x20, 0x20, 0x49, 0x69, 0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x69, ++0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x20, 0x61, 0x64, 0x6A, ++0x49, 0x69, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x61, 0x64, 0x6A, 0x49, 0x71, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x2D, 0x3E, 0x20, 0x49, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x30, 0x3D, 0x25, ++0x64, 0x2C, 0x20, 0x56, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x30, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x2A, 0x6C, 0x6E, 0x61, 0x5F, 0x76, 0x63, 0x6D, 0x70, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6C, 0x6E, ++0x61, 0x5F, 0x76, 0x63, 0x6D, 0x6E, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, ++0x67, 0x61, 0x69, 0x6E, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x72, 0x66, ++0x20, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, ++0x3C, 0x3D, 0x20, 0x33, 0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x69, ++0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x00, 0x73, 0x66, 0x74, 0x20, 0x64, 0x69, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x66, 0x74, 0x72, 0x73, 0x74, 0x20, 0x64, 0x6F, 0x6E, 0x65, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x6F, 0x61, 0x64, ++0x5F, 0x76, 0x61, 0x6C, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x75, 0x73, ++0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x68, 0x6F, 0x73, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x5F, 0x64, 0x6D, 0x61, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x20, 0x21, 0x3D, ++0x20, 0x30, 0x00, 0x00, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x64, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, ++0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x20, 0x3C, 0x3D, 0x20, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, ++0x6B, 0x65, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x28, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x64, ++0x73, 0x74, 0x2D, 0x3E, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, ++0x6D, 0x73, 0x67, 0x62, 0x75, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x5F, 0x6D, 0x73, 0x67, ++0x5F, 0x62, 0x75, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x69, 0x70, 0x63, 0x5F, 0x65, 0x6D, 0x62, 0x5F, ++0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x66, 0x77, 0x64, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, ++0x6D, 0x73, 0x67, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x73, 0x72, 0x63, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x64, 0x73, ++0x74, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x69, ++0x70, 0x63, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x72, ++0x20, 0x75, 0x73, 0x62, 0x20, 0x69, 0x6E, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x25, 0x64, 0x2C, ++0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x73, 0x72, 0x63, 0x2D, 0x3E, 0x70, 0x61, ++0x72, 0x61, 0x6D, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x73, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x6D, 0x73, ++0x67, 0x2D, 0x3E, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x29, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6D, 0x73, 0x67, ++0x20, 0x63, 0x66, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6E, 0x6F, 0x20, ++0x64, 0x73, 0x63, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x6E, 0x6F, 0x74, 0x69, 0x66, 0x79, 0x3A, ++0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x42, 0x54, 0x20, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x20, 0x68, 0x6F, ++0x73, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x70, 0x6D, 0x69, 0x63, 0x20, 0x67, 0x70, 0x69, 0x6F, 0x0A, 0x00, 0x00, ++0x77, 0x6B, 0x62, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x50, 0x4D, 0x49, 0x43, 0x5F, 0x45, 0x52, 0x52, ++0x49, 0x52, 0x51, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x5F, ++0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x49, 0x50, 0x43, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x43, 0x48, 0x41, 0x4E, 0x4E, 0x45, ++0x4C, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x23, 0x20, 0x3D, 0x25, 0x64, 0x20, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x75, 0x2E, 0x73, 0x74, 0x61, 0x2E, 0x6C, ++0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x3D, 0x3D, ++0x20, 0x31, 0x00, 0x00, 0x73, 0x74, 0x61, 0x2D, 0x3E, 0x6C, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x63, 0x6F, 0x6E, ++0x6E, 0x5F, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x00, 0x00, 0x61, 0x70, 0x6D, 0x20, ++0x73, 0x74, 0x61, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x74, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x72, 0x3A, 0x25, 0x64, 0x2C, 0x20, ++0x72, 0x72, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x31, 0x0A, 0x00, ++0x63, 0x6C, 0x65, 0x61, 0x72, 0x0A, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x0A, 0x00, 0x00, ++0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x74, 0x6D, 0x70, 0x2D, 0x3E, 0x68, 0x6F, 0x73, 0x74, 0x2E, 0x73, 0x74, 0x61, ++0x69, 0x64, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, 0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, ++0x41, 0x58, 0x00, 0x00, 0x73, 0x74, 0x61, 0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x25, 0x64, 0x0A, 0x00, ++0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x74, 0x6D, 0x70, 0x2D, 0x3E, 0x68, 0x6F, 0x73, 0x74, 0x2E, 0x66, 0x6C, 0x61, ++0x67, 0x73, 0x20, 0x26, 0x20, 0x54, 0x58, 0x55, 0x5F, 0x43, 0x4E, 0x54, 0x52, 0x4C, 0x5F, 0x52, 0x45, 0x54, 0x52, 0x59, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xD9, 0x67, 0x12, 0x00, 0xF9, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x70, 0x6F, 0x6F, 0x6C, 0x5F, ++0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, ++0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x74, 0x74, ++0x65, 0x72, 0x6E, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, ++0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x6E, 0x75, 0x6D, 0x5F, ++0x75, 0x73, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, ++0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, ++0x6E, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x20, 0x49, 0x6E, ++0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, ++0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x65, 0x6D, 0x4D, 0x67, 0x72, 0x45, 0x72, 0x72, 0x3A, 0x20, 0x53, ++0x75, 0x62, 0x70, 0x6F, 0x6F, 0x6C, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x53, 0x77, 0x45, 0x72, ++0x3A, 0x4E, 0x6F, 0x53, 0x69, 0x7A, 0x65, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x0D, 0x00, ++0x67, 0x65, 0x74, 0x5F, 0x6E, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x61, 0x64, 0x64, 0x72, ++0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, ++0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x74, 0x74, ++0x65, 0x72, 0x6E, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, ++0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x53, 0x77, 0x45, 0x72, 0x3A, 0x41, 0x6C, 0x6C, ++0x63, 0x45, 0x72, 0x72, 0x50, 0x74, 0x72, 0x6E, 0x20, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, ++0x72, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x74, 0x69, ++0x76, 0x65, 0x5F, 0x70, 0x6F, 0x6F, 0x6C, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, ++0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x64, 0x65, 0x63, 0x72, 0x5F, 0x6E, 0x75, 0x6D, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, ++0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, ++0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, ++0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, ++0x25, 0x78, 0x0A, 0x00, 0x6E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x69, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x32, 0x00, 0x00, ++0x67, 0x65, 0x74, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, ++0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, ++0x72, 0x65, 0x70, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x2C, 0x20, 0x25, 0x64, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x64, 0x65, 0x73, 0x63, 0x0D, 0x0A, 0x00, 0x00, ++0x70, 0x61, 0x72, 0x61, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6E, 0x74, 0x20, ++0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x69, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6E, 0x75, 0x6D, 0x3D, 0x25, 0x64, ++0x2C, 0x20, 0x72, 0x78, 0x64, 0x65, 0x73, 0x63, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x61, 0x63, 0x3E, 0x3D, 0x4E, 0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x20, ++0x2B, 0x20, 0x31, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, 0x65, 0x77, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, ++0x4C, 0x4C, 0x00, 0x00, 0x6D, 0x73, 0x67, 0x20, 0x63, 0x72, 0x63, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x69, 0x6E, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x73, 0x6F, 0x66, 0x74, ++0x77, 0x6B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x61, 0x20, 0x69, 0x6E, 0x74, 0x20, 0x25, 0x78, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x20, 0x73, 0x74, ++0x61, 0x74, 0x75, 0x73, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x68, 0x6F, 0x73, ++0x74, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x61, 0x68, 0x62, 0x32, 0x73, 0x64, 0x69, 0x6F, ++0x20, 0x74, 0x78, 0x20, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x53, 0x44, 0x49, 0x4F, 0x32, 0x41, 0x48, 0x42, ++0x5F, 0x4C, 0x4C, 0x53, 0x54, 0x5F, 0x48, 0x44, 0x52, 0x5F, 0x45, 0x52, 0x52, 0x0D, 0x0A, 0x00, 0x73, 0x64, 0x69, 0x6F, ++0x20, 0x65, 0x72, 0x72, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3D, 0x25, 0x78, 0x2C, 0x30, 0x78, 0x34, 0x35, 0x3D, ++0x25, 0x78, 0x0A, 0x00, 0x6D, 0x73, 0x67, 0x72, 0x78, 0x75, 0x73, 0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, ++0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x63, 0x75, 0x73, 0x65, 0x64, 0x3D, ++0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x74, 0x78, 0x63, 0x6D, ++0x73, 0x67, 0x75, 0x73, 0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6D, 0x73, 0x67, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x61, 0x69, 0x74, 0x20, 0x69, 0x6F, 0x20, 0x65, 0x6E, 0x61, 0x62, ++0x6C, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6F, 0x20, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x0D, 0x0A, 0x00, ++0x65, 0x72, 0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x70, 0x6B, 0x74, 0x21, 0x0D, 0x0A, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x64, 0x73, 0x63, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x6F, 0x70, 0x65, 0x6E, ++0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x55, 0x4C, 0x50, 0x49, 0x20, 0x63, 0x6C, 0x6B, 0x20, 0x64, 0x65, 0x74, ++0x65, 0x63, 0x74, 0x65, 0x64, 0x0D, 0x0A, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x20, 0x6E, 0x6F, 0x20, 0x75, 0x73, 0x62, ++0x20, 0x75, 0x6C, 0x70, 0x69, 0x20, 0x63, 0x6C, 0x6B, 0x0D, 0x0A, 0x00, 0x77, 0x61, 0x69, 0x74, 0x20, 0x63, 0x66, 0x67, ++0x0A, 0x00, 0x00, 0x00, 0x46, 0x49, 0x46, 0x4F, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x3A, 0x20, 0x6F, 0x76, 0x65, 0x72, ++0x66, 0x6C, 0x6F, 0x77, 0x2C, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x69, ++0x7A, 0x65, 0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x20, 0x52, 0x41, 0x4D, 0x20, ++0x69, 0x73, 0x20, 0x25, 0x64, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E, ++0x6D, 0x65, 0x6E, 0x74, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x45, 0x50, 0x30, 0x20, 0x53, 0x45, 0x54, 0x55, ++0x50, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x2C, 0x20, 0x64, 0x69, 0x72, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x00, ++0x45, 0x50, 0x30, 0x20, 0x53, 0x45, 0x54, 0x55, 0x50, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x2C, 0x20, 0x77, 0x4C, 0x65, ++0x6E, 0x67, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6E, 0x6B, 0x6E, ++0x6F, 0x77, 0x6E, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6F, 0x72, 0x3A, 0x20, 0x25, 0x64, 0x00, 0x00, ++0x45, 0x70, 0x30, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x65, 0x72, 0x72, 0x20, ++0x25, 0x75, 0x2D, 0x25, 0x75, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x72, 0x65, 0x62, 0x6F, 0x6F, 0x74, ++0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x65, 0x74, 0x0D, 0x0A, 0x00, 0x65, 0x78, 0x69, 0x74, ++0x0D, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x0A, 0x00, 0x77, 0x61, 0x6B, 0x65, ++0x75, 0x70, 0x20, 0x75, 0x73, 0x62, 0x0A, 0x00, 0x69, 0x72, 0x71, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x77, 0x6C, 0x61, 0x6E, 0x5F, 0x75, 0x73, 0x62, 0x5F, 0x73, 0x75, 0x73, 0x70, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x00, ++0x52, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x64, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, ++0x64, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x6D, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, ++0x64, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x6E, 0x6F, 0x20, 0x72, 0x78, ++0x20, 0x6D, 0x73, 0x67, 0x20, 0x65, 0x6C, 0x65, 0x6D, 0x0D, 0x0A, 0x00, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, ++0x20, 0x25, 0x58, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x65, 0x6E, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, ++0x64, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x72, 0x65, 0x63, 0x76, 0x20, 0x65, 0x72, ++0x72, 0x21, 0x21, 0x21, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x23, 0x65, ++0x72, 0x72, 0x23, 0x23, 0x23, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x6C, 0x61, 0x6E, ++0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6F, 0x70, 0x65, 0x6E, 0x20, 0x72, 0x65, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x21, 0x21, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x64, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x74, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x20, 0x00, ++0x01, 0x01, 0x00, 0xA0, 0xFA, 0x09, 0x04, 0x00, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, ++0x00, 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00, 0x05, 0x0F, 0x0C, 0x00, 0x01, 0x07, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, ++0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x9C, 0xA6, 0x00, 0x88, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00, ++0x0A, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, ++0x0A, 0x03, 0x77, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x10, 0x03, 0x61, 0x00, 0x69, 0x00, 0x63, 0x00, ++0x73, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x12, 0x03, 0x41, 0x00, 0x49, 0x00, 0x43, 0x00, 0x20, 0x00, 0x57, 0x00, ++0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x12, 0x03, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x39, 0x00, 0x30, 0x00, ++0x32, 0x00, 0x32, 0x00, 0x37, 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x75, 0x73, 0x62, 0x5F, 0x77, 0x6C, 0x61, 0x6E, ++0x5F, 0x72, 0x78, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x6E, ++0x69, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, ++0x77, 0x66, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x75, 0x73, 0x62, 0x20, 0x73, 0x74, 0x61, ++0x72, 0x74, 0x20, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x68, 0x6F, 0x73, ++0x74, 0x5F, 0x69, 0x66, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x73, 0x69, 0x7A, ++0x65, 0x00, 0x00, 0x00, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x72, 0x78, 0x3A, 0x20, 0x64, 0x73, 0x63, 0x72, 0x20, 0x75, ++0x73, 0x65, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x23, 0x77, 0x66, 0x3A, 0x25, 0x58, 0x0A, 0x00, ++0x23, 0x77, 0x65, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x64, 0x20, 0x72, 0x78, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x21, 0x20, 0x77, 0x64, 0x20, 0x6E, 0x6F, 0x20, 0x72, 0x78, 0x20, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, ++0x77, 0x64, 0x20, 0x72, 0x78, 0x20, 0x6D, 0x61, 0x78, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, ++0x68, 0x6F, 0x73, 0x74, 0x5F, 0x72, 0x65, 0x61, 0x64, 0x79, 0x0A, 0x00, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x64, 0x61, 0x74, ++0x61, 0x20, 0x72, 0x65, 0x63, 0x76, 0x20, 0x72, 0x65, 0x74, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, ++0x20, 0x6E, 0x6F, 0x20, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x69, 0x70, 0x63, ++0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x69, 0x70, 0x63, 0x20, 0x68, 0x6F, 0x73, ++0x74, 0x20, 0x72, 0x78, 0x3A, 0x20, 0x6E, 0x6F, 0x62, 0x75, 0x66, 0x66, 0x2C, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x3D, ++0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x4D, 0x4D, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x54, 0x4F, 0x5F, 0x4B, 0x45, ++0x59, 0x28, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, 0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x20, ++0x2D, 0x20, 0x31, 0x29, 0x20, 0x3C, 0x3D, 0x20, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x6B, 0x65, ++0x79, 0x5F, 0x6D, 0x61, 0x78, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x00, 0x00, ++0x6C, 0x70, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x61, 0x63, 0x74, 0x73, 0x6C, 0x70, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x69, ++0x6D, 0x65, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x69, 0x64, 0x78, 0x20, 0x21, 0x3D, ++0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x43, 0x54, 0x58, 0x54, 0x5F, 0x55, 0x4E, 0x55, 0x53, 0x45, 0x44, 0x00, 0x00, 0x00, ++0x73, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, ++0x67, 0x3A, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x0D, 0x0A, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, ++0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x6C, 0x61, 0x73, 0x74, 0x20, 0x3C, 0x20, 0x31, 0x30, 0x6D, 0x73, 0x2C, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, ++0x6F, 0x77, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x0D, 0x0A, 0x00, ++0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x0A, 0x43, 0x4F, 0x4E, 0x54, 0x52, 0x4F, 0x4C, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x78, ++0x50, 0x53, 0x52, 0x20, 0x20, 0x20, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x50, 0x53, 0x50, 0x20, 0x20, 0x20, 0x20, 0x3D, ++0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x4D, 0x53, 0x50, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x50, ++0x52, 0x49, 0x4D, 0x41, 0x53, 0x4B, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x4C, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, ++0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x00, 0x0A, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x20, 0x50, 0x53, 0x50, 0x21, 0x00, ++0x0A, 0x44, 0x75, 0x6D, 0x70, 0x4D, 0x53, 0x50, 0x3A, 0x00, 0x00, 0x00, 0x0A, 0x5B, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x3A, ++0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x0A, 0x52, 0x25, 0x2D, 0x34, 0x64, 0x3A, 0x20, ++0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x53, 0x50, 0x20, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x4C, 0x52, 0x20, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x43, 0x20, 0x20, 0x20, 0x3A, 0x20, ++0x25, 0x30, 0x38, 0x58, 0x0A, 0x78, 0x50, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x53, 0x50, ++0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x4D, 0x53, 0x50, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x00, 0x00, 0x00, 0x00, 0x0A, 0x43, 0x50, 0x55, 0x49, 0x44, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x49, 0x43, 0x53, ++0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x56, 0x54, 0x4F, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x41, 0x49, 0x52, 0x43, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x53, 0x48, 0x43, ++0x53, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x43, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x48, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x44, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, ++0x25, 0x30, 0x38, 0x58, 0x0A, 0x41, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, ++0x0A, 0x4D, 0x4D, 0x46, 0x53, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x20, 0x20, 0x49, 0x41, 0x43, 0x43, 0x56, ++0x49, 0x4F, 0x4C, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x44, 0x41, 0x43, 0x43, 0x56, 0x49, 0x4F, 0x4C, 0x20, 0x3A, 0x25, 0x64, ++0x0A, 0x20, 0x20, 0x4D, 0x55, 0x4E, 0x53, 0x54, 0x4B, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x09, 0x4D, 0x53, 0x54, 0x4B, ++0x45, 0x52, 0x52, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x4D, 0x4C, 0x53, 0x50, 0x45, 0x52, 0x52, 0x20, 0x20, ++0x3A, 0x25, 0x64, 0x09, 0x4D, 0x4D, 0x41, 0x52, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x3A, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, ++0x0A, 0x4D, 0x4D, 0x46, 0x41, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x42, 0x46, 0x53, ++0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x20, 0x20, 0x49, 0x42, 0x55, 0x53, 0x45, 0x52, 0x52, 0x20, 0x20, ++0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x0A, 0x20, ++0x20, 0x49, 0x4D, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x09, 0x55, 0x4E, 0x53, 0x54, ++0x4B, 0x45, 0x52, 0x52, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x53, 0x54, 0x4B, 0x45, 0x52, 0x52, 0x20, 0x20, 0x20, ++0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x4C, 0x53, 0x50, 0x45, 0x52, 0x52, 0x20, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, ++0x20, 0x42, 0x46, 0x41, 0x52, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x00, 0x0A, 0x42, 0x46, 0x41, ++0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x55, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, ++0x25, 0x30, 0x34, 0x58, 0x0A, 0x20, 0x20, 0x55, 0x4E, 0x44, 0x45, 0x46, 0x49, 0x4E, 0x53, 0x54, 0x52, 0x3A, 0x25, 0x64, ++0x09, 0x49, 0x4E, 0x56, 0x53, 0x54, 0x41, 0x54, 0x45, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x49, 0x4E, 0x56, 0x50, ++0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x4E, 0x4F, 0x43, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, ++0x25, 0x64, 0x0A, 0x20, 0x20, 0x55, 0x4E, 0x41, 0x4C, 0x49, 0x47, 0x4E, 0x45, 0x44, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x44, ++0x49, 0x56, 0x42, 0x59, 0x5A, 0x45, 0x52, 0x4F, 0x3A, 0x25, 0x64, 0x00, 0x0A, 0x4D, 0x6F, 0x64, 0x65, 0x20, 0x3A, 0x20, ++0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x0A, 0x50, 0x72, 0x69, 0x76, 0x20, 0x3A, 0x20, 0x55, 0x73, 0x65, 0x72, ++0x00, 0x00, 0x00, 0x00, 0x0A, 0x50, 0x72, 0x69, 0x76, 0x20, 0x3A, 0x20, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6C, 0x65, 0x67, ++0x65, 0x64, 0x00, 0x00, 0x0A, 0x4D, 0x6F, 0x64, 0x65, 0x20, 0x3A, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, ++0x0A, 0x53, 0x74, 0x61, 0x63, 0x6B, 0x3A, 0x20, 0x50, 0x53, 0x50, 0x00, 0x0A, 0x53, 0x74, 0x61, 0x63, 0x6B, 0x3A, 0x20, ++0x4D, 0x53, 0x50, 0x00, 0x0A, 0x43, 0x4E, 0x54, 0x52, 0x4C, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x4D, 0x41, ++0x53, 0x4B, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x46, 0x4D, 0x41, 0x53, 0x4B, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x42, 0x41, 0x53, 0x45, 0x50, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x44, 0x75, 0x6D, ++0x70, 0x50, 0x53, 0x50, 0x3A, 0x00, 0x00, 0x00, 0x50, 0x61, 0x6E, 0x69, 0x63, 0x2E, 0x2E, 0x2E, 0x0A, 0x00, 0x00, 0x00, ++0x0A, 0x2B, 0x2B, 0x20, 0x43, 0x4D, 0x34, 0x20, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, ++0x72, 0x20, 0x2B, 0x2B, 0x0A, 0x0A, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x54, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x00, 0x00, 0x00, ++0x4D, 0x65, 0x6D, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x42, 0x75, 0x73, 0x46, ++0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, ++0x48, 0x61, 0x72, 0x64, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, ++0x74, 0x3A, 0x00, 0x00, 0x0A, 0x0A, 0x2D, 0x2D, 0x20, 0x43, 0x4D, 0x34, 0x20, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x48, ++0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x2D, 0x2D, 0x0A, 0x0A, 0x00, 0x9A, 0x25, 0x73, 0x20, 0x2D, 0x20, 0x62, 0x75, ++0x69, 0x6C, 0x64, 0x3A, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x25, ++0x64, 0x2C, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x64, 0x6F, 0x6E, 0x65, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x64, 0x2C, 0x00, 0x00, 0x74, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x6E, 0x6F, 0x74, 0x20, ++0x70, 0x61, 0x73, 0x74, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x70, 0x61, 0x73, 0x73, ++0x3A, 0x20, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, ++0x68, 0x77, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x2D, 0x3E, ++0x74, 0x69, 0x6D, 0x65, 0x20, 0x2D, 0x20, 0x67, 0x5F, 0x77, 0x69, 0x66, 0x69, 0x5F, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6E, ++0x67, 0x73, 0x2E, 0x70, 0x77, 0x72, 0x5F, 0x6F, 0x70, 0x65, 0x6E, 0x5F, 0x73, 0x79, 0x73, 0x64, 0x65, 0x6C, 0x61, 0x79, ++0x29, 0x00, 0x00, 0x00, 0x73, 0x6C, 0x70, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x62, 0x74, 0x0A, 0x00, ++0x6C, 0x70, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x69, 0x67, 0x6E, 0x6F, 0x72, 0x65, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, ++0x77, 0x2C, 0x20, 0x00, 0x72, 0x77, 0x6E, 0x78, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x70, 0x72, 0x65, 0x76, 0x5F, 0x68, 0x77, ++0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, ++0x65, 0x6E, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x00, 0x00, 0x00, 0x00, ++0x77, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x77, 0x6E, 0x78, 0x6C, 0x5F, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5F, ++0x65, 0x76, 0x74, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5B, 0x30, 0x5D, 0x20, ++0x26, 0x26, 0x20, 0x74, 0x78, 0x5F, 0x68, 0x77, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5B, ++0x30, 0x5D, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, ++0x74, 0x78, 0x6C, 0x20, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x6C, 0x65, 0x6E, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x74, 0x78, 0x6C, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, ++0x63, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x74, 0x68, 0x64, 0x2D, 0x3E, 0x66, 0x69, 0x72, ++0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x00, 0x00, 0x6E, 0x65, 0x78, 0x74, 0x64, 0x65, 0x73, 0x63, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, ++0x2D, 0x3E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x41, 0x47, 0x47, 0x5F, 0x42, 0x41, 0x5F, 0x52, 0x45, ++0x43, 0x45, 0x49, 0x56, 0x45, 0x44, 0x00, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x62, 0x63, 0x6E, ++0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x00, ++0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x33, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, ++0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, ++0x5F, 0x61, 0x63, 0x5F, 0x32, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, ++0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x31, 0x5F, 0x73, 0x74, ++0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, ++0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x30, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, ++0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x68, 0x69, 0x5F, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x00, 0x00, ++0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5F, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6F, 0x72, 0x79, 0x20, 0x3C, 0x20, 0x28, 0x4E, ++0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x2B, 0x32, 0x29, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, ++0x21, 0x21, 0x20, 0x74, 0x78, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, ++0x20, 0x66, 0x6F, 0x72, 0x20, 0x75, 0x73, 0x62, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x66, 0x6D, 0x20, 0x66, 0x6C, 0x75, 0x73, ++0x68, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x73, 0x6E, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x63, 0x66, 0x6D, 0x73, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x73, 0x6E, 0x3D, 0x25, 0x64, 0x2C, ++0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x79, 0x5F, 0x69, 0x64, 0x78, 0x5F, ++0x68, 0x77, 0x20, 0x3E, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x53, 0x45, 0x43, 0x5F, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4C, 0x54, ++0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x4F, 0x55, 0x4E, 0x54, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x65, 0x76, 0x74, 0x5F, 0x67, ++0x65, 0x74, 0x28, 0x29, 0x20, 0x26, 0x20, 0x65, 0x76, 0x74, 0x5F, 0x62, 0x69, 0x74, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, ++0x73, 0x63, 0x5F, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, ++0x62, 0x75, 0x67, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x74, 0x61, 0x69, 0x6C, 0x20, 0x65, 0x72, ++0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, ++0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x28, 0x74, 0x68, 0x64, 0x2D, 0x3E, 0x64, 0x61, ++0x74, 0x61, 0x73, 0x74, 0x61, 0x72, 0x74, 0x70, 0x74, 0x72, 0x20, 0x26, 0x20, 0x30, 0x78, 0x30, 0x31, 0x29, 0x20, 0x3D, ++0x3D, 0x20, 0x30, 0x00, 0x62, 0x61, 0x6E, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x50, 0x48, 0x59, 0x5F, 0x42, 0x41, 0x4E, 0x44, ++0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, ++0x6F, 0x72, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x6E, 0x6F, 0x20, 0x70, 0x72, 0x6F, 0x62, 0x65, 0x20, 0x62, 0x75, 0x66, ++0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, ++0x4C, 0x4C, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, 0x65, 0x77, 0x20, 0x21, 0x3D, 0x20, ++0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x70, 0x69, 0x63, 0x6B, ++0x28, 0x26, 0x74, 0x78, 0x6C, 0x69, 0x73, 0x74, 0x2D, 0x3E, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, ++0x29, 0x20, 0x3D, 0x3D, 0x20, 0x26, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6F, 0x6C, 0x64, 0x2D, 0x3E, ++0x6C, 0x69, 0x73, 0x74, 0x5F, 0x68, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, ++0x6F, 0x64, 0x20, 0x3E, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, 0x4F, 0x4E, 0x5F, 0x48, ++0x54, 0x5F, 0x44, 0x55, 0x50, 0x5F, 0x4F, 0x46, 0x44, 0x4D, 0x00, 0x00, 0x28, 0x2A, 0x6E, 0x73, 0x73, 0x20, 0x3E, 0x20, ++0x30, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x2A, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x34, 0x29, 0x00, 0x00, 0x00, ++0x6D, 0x63, 0x73, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x39, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x63, 0x73, 0x5F, ++0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x33, 0x31, 0x00, 0x00, 0x00, 0x69, 0x73, 0x5F, 0x6D, 0x70, 0x64, 0x75, 0x5F, ++0x66, 0x69, 0x72, 0x73, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x29, 0x00, 0x00, 0x00, 0x21, 0x69, 0x73, 0x5F, ++0x6D, 0x70, 0x64, 0x75, 0x5F, 0x6C, 0x61, 0x73, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x29, 0x00, 0x00, 0x00, ++0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x70, 0x72, 0x65, 0x76, 0x20, 0x3D, 0x3D, 0x20, 0x61, 0x67, 0x67, 0x5F, 0x64, ++0x65, 0x73, 0x63, 0x5F, 0x6F, 0x6C, 0x64, 0x2D, 0x3E, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6C, 0x61, 0x73, 0x74, ++0x00, 0x00, 0x00, 0x00, 0x61, 0x5F, 0x74, 0x68, 0x64, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x52, ++0x45, 0x54, 0x52, 0x59, 0x5F, 0x4C, 0x49, 0x4D, 0x49, 0x54, 0x5F, 0x52, 0x45, 0x41, 0x43, 0x48, 0x45, 0x44, 0x5F, 0x42, ++0x49, 0x54, 0x00, 0x00, 0x1A, 0x00, 0x1C, 0x00, 0x36, 0x00, 0x3C, 0x00, 0x75, 0x00, 0x82, 0x00, 0xEA, 0x00, 0x04, 0x01, ++0x34, 0x00, 0x39, 0x00, 0x6C, 0x00, 0x78, 0x00, 0xEA, 0x00, 0x04, 0x01, 0xD4, 0x01, 0x08, 0x02, 0x4E, 0x00, 0x56, 0x00, ++0xA2, 0x00, 0xB4, 0x00, 0x5F, 0x01, 0x86, 0x01, 0xBE, 0x02, 0x0C, 0x03, 0x68, 0x00, 0x73, 0x00, 0xD8, 0x00, 0xF0, 0x00, ++0xD4, 0x01, 0x08, 0x02, 0xA8, 0x03, 0x10, 0x04, 0x9C, 0x00, 0xAD, 0x00, 0x44, 0x01, 0x68, 0x01, 0xBE, 0x02, 0x0C, 0x03, ++0x7C, 0x05, 0x18, 0x06, 0xD0, 0x00, 0xE7, 0x00, 0xB0, 0x01, 0xE0, 0x01, 0xA8, 0x03, 0x10, 0x04, 0x50, 0x07, 0x20, 0x08, ++0xEA, 0x00, 0x04, 0x01, 0xE6, 0x01, 0x1C, 0x02, 0x1D, 0x04, 0x92, 0x04, 0x3A, 0x08, 0x24, 0x09, 0x04, 0x01, 0x20, 0x01, ++0x1C, 0x02, 0x58, 0x02, 0x92, 0x04, 0x14, 0x05, 0x24, 0x09, 0x28, 0x0A, 0x38, 0x01, 0x5A, 0x01, 0x88, 0x02, 0xD0, 0x02, ++0x7C, 0x05, 0x18, 0x06, 0xF8, 0x0A, 0x30, 0x0C, 0x5A, 0x01, 0x81, 0x01, 0xD0, 0x02, 0x20, 0x03, 0x18, 0x06, 0xC5, 0x06, ++0x30, 0x0C, 0x8A, 0x0D, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x08, 0x09, 0x02, 0x02, 0x04, 0x04, 0x08, 0x09, 0x0F, 0x11, ++0x03, 0x03, 0x06, 0x06, 0x0B, 0x0D, 0x16, 0x19, 0x04, 0x04, 0x07, 0x08, 0x0F, 0x11, 0x1E, 0x21, 0x05, 0x06, 0x0B, 0x0C, ++0x16, 0x19, 0x2C, 0x31, 0x07, 0x08, 0x0E, 0x0F, 0x1E, 0x21, 0x3B, 0x41, 0x08, 0x09, 0x10, 0x11, 0x21, 0x25, 0x42, 0x4A, ++0x09, 0x0A, 0x11, 0x13, 0x25, 0x29, 0x4A, 0x52, 0x0A, 0x0B, 0x15, 0x17, 0x2C, 0x31, 0x58, 0x62, 0x0B, 0x0D, 0x17, 0x19, ++0x31, 0x37, 0x62, 0x6D, 0x74, 0x78, 0x6C, 0x5F, 0x68, 0x65, 0x5F, 0x65, 0x64, 0x63, 0x61, 0x5F, 0x71, 0x75, 0x65, 0x75, ++0x65, 0x5F, 0x68, 0x61, 0x6C, 0x74, 0x65, 0x64, 0x28, 0x61, 0x63, 0x29, 0x00, 0x00, 0x00, 0x00, 0x68, 0x64, 0x72, 0x64, ++0x65, 0x73, 0x63, 0x2D, 0x3E, 0x66, 0x72, 0x6D, 0x6C, 0x65, 0x6E, 0x20, 0x3E, 0x3D, 0x20, 0x48, 0x45, 0x5F, 0x54, 0x52, ++0x49, 0x47, 0x5F, 0x46, 0x52, 0x4D, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, ++0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, ++0x48, 0x45, 0x5F, 0x53, 0x55, 0x00, 0x00, 0x00, 0x6D, 0x63, 0x73, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x31, ++0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, ++0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x07, 0x00, ++0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, ++0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, ++0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, ++0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, ++0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, ++0x22, 0x00, 0x20, 0x00, 0x1D, 0x00, 0x90, 0x00, 0x88, 0x00, 0x7A, 0x00, 0x44, 0x00, 0x41, 0x00, 0x3A, 0x00, 0x20, 0x01, ++0x10, 0x01, 0xF5, 0x00, 0x67, 0x00, 0x61, 0x00, 0x57, 0x00, 0xB0, 0x01, 0x98, 0x01, 0x6F, 0x01, 0x89, 0x00, 0x82, 0x00, ++0x75, 0x00, 0x40, 0x02, 0x20, 0x02, 0xEA, 0x01, 0xCE, 0x00, 0xC3, 0x00, 0xAF, 0x00, 0x60, 0x03, 0x30, 0x03, 0xDF, 0x02, ++0x13, 0x01, 0x04, 0x01, 0xEA, 0x00, 0x80, 0x04, 0x40, 0x04, 0xD4, 0x03, 0x35, 0x01, 0x24, 0x01, 0x07, 0x01, 0x11, 0x05, ++0xC9, 0x04, 0x4E, 0x04, 0x58, 0x01, 0x45, 0x01, 0x24, 0x01, 0xA1, 0x05, 0x51, 0x05, 0xC9, 0x04, 0x9C, 0x01, 0x86, 0x01, ++0x5F, 0x01, 0xC1, 0x06, 0x61, 0x06, 0xBE, 0x05, 0xCA, 0x01, 0xB1, 0x01, 0x86, 0x01, 0x81, 0x07, 0x16, 0x07, 0x61, 0x06, ++0x04, 0x02, 0xE7, 0x01, 0xB6, 0x01, 0x71, 0x08, 0xF9, 0x07, 0x2D, 0x07, 0x3D, 0x02, 0x1D, 0x02, 0xE7, 0x01, 0x61, 0x09, ++0xDC, 0x08, 0xF9, 0x07, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, ++0x02, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x0D, 0x00, 0x0C, 0x00, ++0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x13, 0x00, 0x12, 0x00, 0x10, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x1C, 0x00, ++0x1A, 0x00, 0x17, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x25, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x0A, 0x00, 0x0A, 0x00, ++0x09, 0x00, 0x29, 0x00, 0x27, 0x00, 0x23, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x2E, 0x00, 0x2B, 0x00, 0x27, 0x00, ++0x0D, 0x00, 0x0D, 0x00, 0x0B, 0x00, 0x37, 0x00, 0x34, 0x00, 0x2E, 0x00, 0x0F, 0x00, 0x0E, 0x00, 0x0D, 0x00, 0x3D, 0x00, ++0x39, 0x00, 0x34, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x44, 0x00, 0x40, 0x00, 0x3A, 0x00, 0x12, 0x00, 0x11, 0x00, ++0x10, 0x00, 0x4C, 0x00, 0x47, 0x00, 0x40, 0x00, 0x08, 0x10, 0x20, 0x04, 0x50, 0x94, 0x15, 0x00, 0x98, 0x94, 0x15, 0x00, ++0x08, 0x94, 0x15, 0x00, 0x72, 0x68, 0x64, 0x2D, 0x3E, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, ++0x74, 0x72, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x6E, 0x6F, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, ++0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x72, 0x78, 0x62, 0x75, 0x66, 0x31, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, ++0x25, 0x30, 0x38, 0x78, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x65, 0x6E, ++0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x77, ++0x72, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x64, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, ++0x78, 0x0D, 0x0A, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x72, 0x65, 0x63, 0x6F, ++0x76, 0x65, 0x72, 0x79, 0x0D, 0x0A, 0x00, 0x00, 0x70, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, ++0x70, 0x64, 0x2D, 0x3E, 0x70, 0x62, 0x64, 0x2E, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x61, 0x72, 0x74, 0x70, 0x74, 0x72, ++0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x61, 0x5F, 0x68, 0x64, 0x72, 0x64, 0x65, 0x73, 0x63, 0x2D, ++0x3E, 0x68, 0x64, 0x2E, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x20, 0x3D, 0x3D, ++0x20, 0x30, 0x00, 0x00, 0x70, 0x62, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x72, 0x78, 0x6C, 0x20, ++0x65, 0x72, 0x72, 0x2C, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x6E, 0x6F, 0x20, 0x74, ++0x78, 0x5F, 0x64, 0x73, 0x63, 0x72, 0x5F, 0x68, 0x64, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x20, 0x74, ++0x78, 0x5F, 0x64, 0x73, 0x63, 0x72, 0x5F, 0x68, 0x64, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6D, 0x70, 0x64, 0x75, ++0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x6D, 0x70, 0x64, 0x75, 0x5F, 0x6C, 0x65, 0x6E, ++0x20, 0x3C, 0x3D, 0x20, 0x52, 0x57, 0x4E, 0x58, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x41, 0x4D, 0x53, 0x44, 0x55, 0x5F, 0x52, ++0x58, 0x00, 0x00, 0x00, 0x72, 0x68, 0x64, 0x2D, 0x3E, 0x75, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6E, 0x72, 0x78, 0x20, ++0x3D, 0x3D, 0x20, 0x52, 0x58, 0x5F, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5F, 0x44, 0x45, 0x53, 0x43, 0x5F, 0x50, 0x41, ++0x54, 0x54, 0x45, 0x52, 0x4E, 0x00, 0x00, 0x00, 0x72, 0x78, 0x62, 0x75, 0x66, 0x32, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, ++0x25, 0x30, 0x38, 0x78, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x65, 0x6E, ++0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x77, ++0x72, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x64, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, ++0x78, 0x0D, 0x0A, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, ++0x73, 0x74, 0x61, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, ++0x73, 0x74, 0x61, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, ++0x6D, 0x61, 0x63, 0x20, 0x69, 0x73, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x70, 0x32, 0x70, 0x3D, 0x25, ++0x64, 0x0D, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x20, 0x6D, 0x61, 0x63, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x20, 0x6D, ++0x61, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x70, 0x32, 0x70, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x21, 0x3D, 0x20, 0x50, 0x32, ++0x50, 0x5F, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x25, ++0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x76, 0x69, 0x66, 0x20, ++0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x20, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6D, 0x67, 0x6D, 0x74, 0x3A, ++0x25, 0x64, 0x0A, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, ++0x73, 0x6C, 0x65, 0x65, 0x70, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, 0x6C, 0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x6F, 0x6E, 0x5F, 0x61, 0x69, 0x72, 0x5F, 0x76, 0x61, ++0x6C, 0x69, 0x64, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x64, 0x74, 0x69, 0x6D, ++0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x2A, 0x28, 0x76, 0x6F, ++0x6C, 0x61, 0x74, 0x69, 0x6C, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x5F, 0x74, 0x20, 0x2A, 0x29, 0x26, 0x67, 0x5F, ++0x61, 0x6F, 0x6E, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2E, 0x64, 0x74, 0x69, 0x6D, 0x5F, 0x63, 0x6E, 0x74, 0x5F, ++0x61, 0x6F, 0x6E, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x3C, 0x20, 0x2A, 0x28, 0x76, 0x6F, 0x6C, 0x61, 0x74, 0x69, ++0x6C, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x5F, 0x74, 0x20, 0x2A, 0x29, 0x26, 0x67, 0x5F, 0x61, 0x6F, 0x6E, 0x5F, ++0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2E, 0x64, 0x74, 0x69, 0x6D, 0x5F, 0x70, 0x65, 0x72, 0x69, 0x6F, 0x64, 0x5F, 0x61, ++0x6F, 0x6E, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x6E, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, ++0x6C, 0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x4C, 0x2C, 0x00, 0x00, 0x9B, 0x84, 0x4B, 0x65, 0x79, 0x69, 0x64, 0x78, ++0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x2C, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x00, 0x00, 0x9B, 0x84, 0x49, 0x6E, ++0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x6B, 0x65, 0x79, 0x69, 0x64, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x9B, 0x84, 0x49, 0x6E, ++0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x53, 0x54, 0x41, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x5F, ++0x73, 0x74, 0x61, 0x20, 0x3D, 0x3D, 0x20, 0x76, 0x69, 0x66, 0x00, 0x00, 0x54, 0x3D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x42, 0x43, 0x4E, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x6E, 0x20, ++0x64, 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x66, 0x63, 0x73, 0x20, ++0x6F, 0x6B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x66, 0x63, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x6F, 0x6B, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x69, 0x64, 0x6C, 0x65, ++0x20, 0x69, 0x6E, 0x74, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x65, 0x76, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4D, ++0x4D, 0x5F, 0x54, 0x42, 0x54, 0x54, 0x5F, 0x45, 0x56, 0x54, 0x5F, 0x4D, 0x41, 0x53, 0x4B, 0x00, 0x61, 0x64, 0x64, 0x20, ++0x67, 0x74, 0x6B, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x20, ++0x3C, 0x20, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x20, 0x70, 0x74, 0x6B, 0x3A, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x48, 0x4F, 0x53, 0x54, ++0x5F, 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, ++0x4E, 0x4F, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x00, 0x66, 0x6F, 0x72, 0x63, 0x65, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x72, ++0x65, 0x71, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x63, 0x65, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x65, ++0x78, 0x69, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, ++0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x48, 0x4F, 0x53, ++0x54, 0x5F, 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, ++0x20, 0x4D, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x6B, ++0x65, 0x79, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4C, 0x54, ++0x5F, 0x4D, 0x46, 0x50, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x4F, 0x55, 0x4E, 0x54, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, ++0x6D, 0x2D, 0x3E, 0x6B, 0x65, 0x79, 0x2E, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x3C, 0x3D, 0x20, 0x4D, 0x41, 0x43, ++0x5F, 0x53, 0x45, 0x43, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, ++0x6D, 0x2D, 0x3E, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5F, 0x73, 0x75, 0x69, 0x74, 0x65, 0x20, 0x3C, 0x3D, 0x20, 0x4D, ++0x41, 0x43, 0x5F, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x50, 0x5F, 0x43, 0x4D, 0x41, 0x43, 0x5F, 0x31, ++0x32, 0x38, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x68, 0x77, 0x5F, 0x6B, 0x65, 0x79, 0x5F, 0x69, 0x64, ++0x78, 0x20, 0x3C, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x53, 0x45, 0x43, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x4D, 0x46, 0x50, 0x5F, ++0x4B, 0x45, 0x59, 0x5F, 0x4E, 0x42, 0x52, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, ++0x20, 0x56, 0x49, 0x46, 0x5F, 0x53, 0x54, 0x41, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, ++0x49, 0x44, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x6D, 0x75, 0x20, 0x65, 0x64, 0x63, 0x61, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x44, 0x48, 0x43, 0x50, 0x65, 0x64, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x78, 0x2E, 0x0D, 0x0A, 0x00, ++0x73, 0x65, 0x74, 0x20, 0x61, 0x67, 0x67, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x25, 0x64, 0x2C, 0x20, ++0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x72, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x20, ++0x6D, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x73, 0x65, 0x74, 0x20, 0x74, 0x78, 0x6F, 0x70, 0x20, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x62, 0x6B, 0x3A, 0x25, 0x78, 0x2C, ++0x20, 0x62, 0x65, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x76, 0x69, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x76, 0x6F, 0x3A, 0x25, 0x78, ++0x2C, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x6E, 0x61, 0x76, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x63, 0x66, 0x65, 0x3D, 0x25, 0x64, ++0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x20, 0x74, 0x72, 0x78, 0x3A, 0x20, ++0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, ++0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x73, ++0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x73, 0x74, 0x6F, 0x70, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x69, 0x73, 0x20, 0x35, 0x67, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x77, 0x5F, 0x65, 0x6E, 0x3D, ++0x25, 0x64, 0x2C, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x5F, 0x69, 0x6E, 0x66, 0x6F, 0x3D, 0x30, 0x78, 0x25, 0x78, ++0x0D, 0x0A, 0x00, 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, 0x20, 0x65, 0x66, ++0x75, 0x73, 0x65, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x61, 0x70, ++0x3A, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x61, 0x70, 0x5F, 0x66, 0x69, 0x6E, ++0x65, 0x3A, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, ++0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, ++0x5F, 0x66, 0x69, 0x6E, 0x65, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x32, 0x2E, 0x34, 0x67, 0x3A, 0x62, 0x65, 0x66, ++0x6F, 0x72, 0x65, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, ++0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x32, 0x2E, 0x34, 0x67, 0x3A, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x20, ++0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x35, 0x67, 0x3A, 0x62, 0x65, 0x66, 0x6F, 0x72, 0x65, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, ++0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x35, 0x67, 0x3A, 0x61, ++0x66, 0x74, 0x65, 0x72, 0x20, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, ++0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, ++0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x48, 0x57, ++0x5F, 0x49, 0x44, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x4E, 0x4F, 0x5F, 0x49, ++0x44, 0x4C, 0x45, 0x00, 0x76, 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, ++0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x68, 0x65, 0x20, 0x65, ++0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x74, ++0x65, 0x20, 0x69, 0x6E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0xA8, 0x1F, 0x17, 0x00, 0x35, 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, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x74, 0x3A, 0x20, ++0x63, 0x62, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x63, 0x75, 0x72, 0x72, ++0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, 0x68, 0x77, 0x5F, 0x74, ++0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x29, 0x00, 0x74, 0x69, 0x6D, 0x65, ++0x72, 0x2D, 0x3E, 0x63, 0x62, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x20, 0x70, 0x72, 0x6F, 0x62, ++0x65, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x20, ++0x70, 0x72, 0x6F, 0x62, 0x65, 0x20, 0x73, 0x75, 0x63, 0x63, 0x0A, 0x00, 0x6D, 0x6D, 0x5F, 0x62, 0x63, 0x6E, 0x5F, 0x65, ++0x6E, 0x76, 0x2E, 0x74, 0x78, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x6C, ++0x6C, 0x65, 0x20, 0x6E, 0x65, 0x76, 0x65, 0x72, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x61, 0x70, 0x6D, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6E, 0x75, 0x6C, 0x6C, 0x20, 0x74, 0x6F, 0x20, 0x70, 0x72, 0x6F, ++0x62, 0x65, 0x20, 0x73, 0x74, 0x61, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, ++0x21, 0x6D, 0x6D, 0x5F, 0x62, 0x63, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x74, 0x78, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, ++0x61, 0x70, 0x6D, 0x5F, 0x70, 0x72, 0x6F, 0x62, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, ++0x28, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, ++0x74, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3D, ++0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x29, 0x20, 0x7C, ++0x7C, 0x20, 0x28, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, ++0x74, 0x78, 0x74, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, ++0x20, 0x3D, 0x3D, 0x20, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x69, 0x6E, 0x64, 0x65, 0x78, ++0x29, 0x00, 0x00, 0x00, 0x6F, 0x74, 0x68, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x62, 0x5F, 0x76, ++0x69, 0x66, 0x5F, 0x6F, 0x74, 0x68, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3E, 0x20, 0x31, 0x00, 0x6E, 0x6F, 0x61, 0x5F, ++0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x50, 0x32, 0x50, 0x5F, 0x4E, 0x4F, 0x41, 0x5F, 0x4E, 0x42, 0x5F, 0x4D, 0x41, 0x58, ++0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x20, 0x33, 0x32, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x74, 0x62, 0x74, 0x74, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2E, 0x70, 0x32, 0x70, ++0x5F, 0x6E, 0x6F, 0x61, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3D, 0x3D, 0x20, 0x49, 0x4E, ++0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, 0x00, 0x63, 0x68, 0x5F, 0x73, ++0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x52, ++0x4F, 0x43, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x50, 0x45, 0x4E, 0x44, 0x49, 0x4E, 0x47, 0x5F, 0x4D, 0x41, 0x53, 0x4B, ++0x00, 0x00, 0x00, 0x00, 0x28, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, ++0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, 0x54, 0x28, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x45, 0x4E, 0x56, 0x5F, 0x52, ++0x4F, 0x43, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x28, 0x63, 0x68, 0x61, ++0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, ++0x54, 0x28, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x45, 0x4E, 0x56, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x42, 0x49, 0x54, 0x29, ++0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x28, 0x76, 0x6F, 0x69, 0x64, 0x20, 0x2A, 0x29, 0x63, 0x68, 0x5F, 0x73, ++0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6E, 0x76, 0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, ++0x4E, 0x6F, 0x20, 0x63, 0x74, 0x78, 0x74, 0x20, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x64, 0x20, 0x70, 0x72, ++0x65, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x69, 0x64, ++0x78, 0x20, 0x3D, 0x3D, 0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x43, 0x54, 0x58, 0x54, 0x5F, 0x55, 0x4E, 0x55, 0x53, 0x45, ++0x44, 0x00, 0x00, 0x00, 0x72, 0x6F, 0x63, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x64, 0x75, 0x72, 0x3D, 0x25, 0x64, 0x2C, ++0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x6E, 0x62, ++0x5F, 0x6C, 0x69, 0x6E, 0x6B, 0x65, 0x64, 0x5F, 0x76, 0x69, 0x66, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x55, ++0x4C, 0x4C, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x6E, 0x62, 0x5F, 0x73, 0x63, 0x68, 0x65, ++0x64, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3C, 0x3D, 0x20, 0x32, 0x00, 0x63, 0x68, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, ++0x68, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x6C, 0x69, 0x6E, 0x6B, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x63, 0x74, 0x78, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, ++0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x6C, 0x69, 0x6E, 0x6B, 0x3A, 0x20, 0x25, 0x64, 0x2C, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x6E, 0x62, 0x5F, 0x73, 0x63, 0x68, 0x65, 0x64, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3C, ++0x3D, 0x20, 0x31, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x70, 0x73, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, 0x6C, ++0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x70, 0x73, 0x5F, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x64, ++0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x75, 0x70, 0x6D, 0x5F, 0x65, ++0x6E, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x75, 0x70, 0x6D, 0x5F, 0x65, 0x78, 0x69, 0x74, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, ++0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x6F, 0x61, 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x20, 0x3C, 0x20, 0x50, 0x32, 0x50, 0x5F, ++0x4E, 0x4F, 0x41, 0x5F, 0x4E, 0x42, 0x5F, 0x4D, 0x41, 0x58, 0x29, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, ++0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x50, 0x32, 0x50, 0x5F, 0x56, 0x49, 0x46, 0x5F, ++0x4D, 0x41, 0x58, 0x00, 0x74, 0x64, 0x73, 0x5F, 0x65, 0x6E, 0x76, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, ++0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x6E, 0x74, 0x20, 0x3E, 0x20, 0x30, 0x00, ++0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x43, ++0x41, 0x4E, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x57, 0x41, 0x49, 0x54, 0x5F, 0x43, 0x48, 0x41, ++0x4E, 0x4E, 0x45, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, ++0x57, 0x41, 0x49, 0x54, 0x5F, 0x42, 0x45, 0x41, 0x43, 0x4F, 0x4E, 0x5F, 0x50, 0x52, 0x4F, 0x42, 0x45, 0x5F, 0x52, 0x53, ++0x50, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5F, 0x72, 0x65, 0x71, 0x5F, 0x68, ++0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x5F, ++0x72, 0x65, 0x71, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x50, 0x21, 0x17, 0x00, 0x04, 0x00, 0x00, 0x00, ++0x73, 0x63, 0x61, 0x6E, 0x5F, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x5F, 0x63, 0x66, 0x6D, ++0x00, 0x00, 0x00, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x5F, 0x73, 0x74, ++0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x49, 0x44, 0x4C, ++0x45, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x61, 0x6F, 0x6E, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, 0x74, 0x69, ++0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x2D, 0x3E, 0x74, 0x69, 0x6D, 0x65, 0x20, ++0x2B, 0x20, 0x35, 0x30, 0x30, 0x30, 0x29, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, ++0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x6B, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x67, ++0x65, 0x6E, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x79, 0x6D, 0x6F, 0x72, 0x65, 0x0D, 0x0A, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x6D, ++0x6D, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x67, 0x65, 0x6E, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, ++0x20, 0x61, 0x6E, 0x79, 0x6D, 0x6F, 0x72, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x30, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x31, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x32, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x33, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x5F, 0x54, ++0x49, 0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x48, 0x45, 0x5F, 0x54, 0x42, 0x5F, ++0x54, 0x49, 0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x48, 0x49, 0x51, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x5F, 0x46, 0x49, 0x46, 0x4F, 0x5F, ++0x4F, 0x56, 0x45, 0x52, 0x5F, 0x46, 0x4C, 0x4F, 0x57, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x2C, 0x20, 0x68, 0x77, ++0x20, 0x72, 0x65, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6C, 0x66, 0x0D, 0x0A, 0x00, 0x00, ++0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, ++0x58, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x48, 0x59, 0x5F, 0x45, 0x52, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, ++0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, ++0x58, 0x4D, 0x41, 0x43, 0x5F, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x48, 0x59, 0x49, 0x46, 0x5F, 0x55, 0x4E, 0x44, 0x45, 0x52, ++0x5F, 0x52, 0x55, 0x4E, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, ++0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x4D, 0x41, 0x43, ++0x5F, 0x50, 0x48, 0x59, 0x49, 0x46, 0x5F, 0x4F, 0x56, 0x45, 0x52, 0x46, 0x4C, 0x4F, 0x57, 0x5F, 0x42, 0x49, 0x54, 0x29, ++0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, ++0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x54, 0x5F, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x5F, 0x42, 0x49, ++0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, ++0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x30, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, ++0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, ++0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, ++0x31, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, ++0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, ++0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x32, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, ++0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, ++0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x33, 0x5F, 0x54, 0x58, ++0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, ++0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, ++0x5F, 0x42, 0x43, 0x4E, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, ++0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, ++0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x58, 0x5F, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5F, 0x44, ++0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, ++0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, ++0x5F, 0x52, 0x58, 0x5F, 0x50, 0x41, 0x59, 0x4C, 0x4F, 0x41, 0x44, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, ++0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, ++0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x57, 0x5F, 0x45, 0x52, 0x52, 0x5F, ++0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, ++0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x49, 0x5F, 0x54, 0x58, 0x5F, 0x44, ++0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, ++0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x08, 0x06, 0x04, 0x0B, 0x09, 0x07, 0x05, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, 0x8D, 0xF6, ++0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, ++0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, ++0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, ++0xAE, 0x3D, 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, 0x08, 0xF9, ++0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, ++0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, ++0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, ++0x61, 0xB7, 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, 0x2C, 0xC1, ++0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, ++0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, ++0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, ++0xC0, 0x80, 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, 0x63, 0x42, ++0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, ++0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, ++0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, ++0xD3, 0x6B, 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, 0x1E, 0x14, ++0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, ++0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, ++0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, ++0x6F, 0x4A, 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, 0x21, 0x3E, ++0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, ++0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, ++0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, ++0x92, 0x15, 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, 0x17, 0x1A, ++0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, ++0xD6, 0x6D, 0x3A, 0x2C, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x20, 0x3E, 0x20, 0x30, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6C, 0x61, ++0x79, 0x20, 0x3C, 0x20, 0x4B, 0x45, 0x5F, 0x54, 0x49, 0x4D, 0x45, 0x52, 0x5F, 0x44, 0x45, 0x4C, 0x41, 0x59, 0x5F, 0x4D, ++0x41, 0x58, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0x21, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x7C, ++0x7C, 0x20, 0x21, 0x6B, 0x65, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x66, 0x69, 0x72, 0x73, ++0x74, 0x2D, 0x3E, 0x74, 0x69, 0x6D, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x73, 0x67, 0x20, 0x21, 0x3D, 0x20, 0x4E, ++0x55, 0x4C, 0x4C, 0x00, 0x9D, 0x80, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x73, ++0x67, 0x3A, 0x25, 0x78, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x20, 0x74, 0x6F, 0x20, ++0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x73, 0x69, 0x7A, 0x65, 0x20, 0x3E, 0x3D, ++0x20, 0x73, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6D, 0x62, 0x6C, 0x6F, 0x63, ++0x6B, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x29, 0x00, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, ++0x4C, 0x00, 0x00, 0x00, 0x28, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x5F, 0x74, 0x29, 0x6D, 0x65, 0x6D, 0x5F, 0x70, 0x74, ++0x72, 0x20, 0x3E, 0x20, 0x28, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x5F, 0x74, 0x29, 0x6E, 0x6F, 0x64, 0x65, 0x00, 0x00, ++0x70, 0x72, 0x65, 0x76, 0x5F, 0x6E, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x2D, 0x3E, 0x6D, 0x73, 0x67, 0x5F, 0x74, ++0x61, 0x62, 0x6C, 0x65, 0x5B, 0x69, 0x5D, 0x2E, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, ++0x20, 0x3C, 0x20, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x6B, 0x65, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x5F, ++0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x28, 0x74, 0x79, 0x70, 0x65, 0x29, 0x00, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x54, 0x41, ++0x53, 0x4B, 0x5F, 0x44, 0x45, 0x53, 0x43, 0x5B, 0x74, 0x79, 0x70, 0x65, 0x5D, 0x2E, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, ++0x78, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x69, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x00, 0x00, ++0x80, 0x9D, 0x73, 0x65, 0x74, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x9A, 0x80, 0x4E, 0x6F, 0x20, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x66, ++0x6F, 0x72, 0x20, 0x6D, 0x73, 0x67, 0x3A, 0x25, 0x78, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, ++0x78, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x24, 0x9F, 0x15, 0x00, ++0x1C, 0x9F, 0x15, 0x00, 0xCC, 0x9C, 0x17, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xB5, 0x15, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xA4, 0x15, 0x00, 0xF0, 0x9F, 0x17, 0x00, ++0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x20, 0xBF, 0x15, 0x00, 0x18, 0xBF, 0x15, 0x00, 0xA4, 0xBA, 0x17, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x8C, 0xB8, 0x15, 0x00, 0xE0, 0xB8, 0x17, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xBB, 0x15, 0x00, ++0x60, 0xBA, 0x17, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xBE, 0x15, 0x00, 0x90, 0xBA, 0x17, 0x00, ++0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xC2, 0x15, 0x00, 0xF4, 0xDF, 0x17, 0x00, 0x05, 0x00, 0x20, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xD0, 0x15, 0x00, ++0x74, 0xEF, 0x17, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x28, 0x65, 0x76, 0x65, 0x6E, 0x74, 0x20, 0x3C, 0x20, 0x4B, 0x45, 0x5F, 0x45, 0x56, 0x54, 0x5F, ++0x4D, 0x41, 0x58, 0x29, 0x20, 0x26, 0x26, 0x20, 0x6B, 0x65, 0x5F, 0x65, 0x76, 0x74, 0x5F, 0x68, 0x64, 0x6C, 0x72, 0x5B, ++0x65, 0x76, 0x65, 0x6E, 0x74, 0x5D, 0x2E, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x68, 0x64, 0x72, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, ++0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x28, 0x70, 0x72, 0x65, 0x76, 0x5F, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, ++0x74, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x70, 0x72, 0x65, 0x76, 0x5F, ++0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x2D, 0x3E, 0x6E, 0x65, 0x78, 0x74, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6C, 0x65, ++0x6D, 0x65, 0x6E, 0x74, 0x29, 0x00, 0x00, 0x00, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, ++0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x30, 0x07, 0x77, 0x2C, 0x61, 0x0E, 0xEE, 0xBA, 0x51, 0x09, 0x99, ++0x19, 0xC4, 0x6D, 0x07, 0x8F, 0xF4, 0x6A, 0x70, 0x35, 0xA5, 0x63, 0xE9, 0xA3, 0x95, 0x64, 0x9E, 0x32, 0x88, 0xDB, 0x0E, ++0xA4, 0xB8, 0xDC, 0x79, 0x1E, 0xE9, 0xD5, 0xE0, 0x88, 0xD9, 0xD2, 0x97, 0x2B, 0x4C, 0xB6, 0x09, 0xBD, 0x7C, 0xB1, 0x7E, ++0x07, 0x2D, 0xB8, 0xE7, 0x91, 0x1D, 0xBF, 0x90, 0x64, 0x10, 0xB7, 0x1D, 0xF2, 0x20, 0xB0, 0x6A, 0x48, 0x71, 0xB9, 0xF3, ++0xDE, 0x41, 0xBE, 0x84, 0x7D, 0xD4, 0xDA, 0x1A, 0xEB, 0xE4, 0xDD, 0x6D, 0x51, 0xB5, 0xD4, 0xF4, 0xC7, 0x85, 0xD3, 0x83, ++0x56, 0x98, 0x6C, 0x13, 0xC0, 0xA8, 0x6B, 0x64, 0x7A, 0xF9, 0x62, 0xFD, 0xEC, 0xC9, 0x65, 0x8A, 0x4F, 0x5C, 0x01, 0x14, ++0xD9, 0x6C, 0x06, 0x63, 0x63, 0x3D, 0x0F, 0xFA, 0xF5, 0x0D, 0x08, 0x8D, 0xC8, 0x20, 0x6E, 0x3B, 0x5E, 0x10, 0x69, 0x4C, ++0xE4, 0x41, 0x60, 0xD5, 0x72, 0x71, 0x67, 0xA2, 0xD1, 0xE4, 0x03, 0x3C, 0x47, 0xD4, 0x04, 0x4B, 0xFD, 0x85, 0x0D, 0xD2, ++0x6B, 0xB5, 0x0A, 0xA5, 0xFA, 0xA8, 0xB5, 0x35, 0x6C, 0x98, 0xB2, 0x42, 0xD6, 0xC9, 0xBB, 0xDB, 0x40, 0xF9, 0xBC, 0xAC, ++0xE3, 0x6C, 0xD8, 0x32, 0x75, 0x5C, 0xDF, 0x45, 0xCF, 0x0D, 0xD6, 0xDC, 0x59, 0x3D, 0xD1, 0xAB, 0xAC, 0x30, 0xD9, 0x26, ++0x3A, 0x00, 0xDE, 0x51, 0x80, 0x51, 0xD7, 0xC8, 0x16, 0x61, 0xD0, 0xBF, 0xB5, 0xF4, 0xB4, 0x21, 0x23, 0xC4, 0xB3, 0x56, ++0x99, 0x95, 0xBA, 0xCF, 0x0F, 0xA5, 0xBD, 0xB8, 0x9E, 0xB8, 0x02, 0x28, 0x08, 0x88, 0x05, 0x5F, 0xB2, 0xD9, 0x0C, 0xC6, ++0x24, 0xE9, 0x0B, 0xB1, 0x87, 0x7C, 0x6F, 0x2F, 0x11, 0x4C, 0x68, 0x58, 0xAB, 0x1D, 0x61, 0xC1, 0x3D, 0x2D, 0x66, 0xB6, ++0x90, 0x41, 0xDC, 0x76, 0x06, 0x71, 0xDB, 0x01, 0xBC, 0x20, 0xD2, 0x98, 0x2A, 0x10, 0xD5, 0xEF, 0x89, 0x85, 0xB1, 0x71, ++0x1F, 0xB5, 0xB6, 0x06, 0xA5, 0xE4, 0xBF, 0x9F, 0x33, 0xD4, 0xB8, 0xE8, 0xA2, 0xC9, 0x07, 0x78, 0x34, 0xF9, 0x00, 0x0F, ++0x8E, 0xA8, 0x09, 0x96, 0x18, 0x98, 0x0E, 0xE1, 0xBB, 0x0D, 0x6A, 0x7F, 0x2D, 0x3D, 0x6D, 0x08, 0x97, 0x6C, 0x64, 0x91, ++0x01, 0x5C, 0x63, 0xE6, 0xF4, 0x51, 0x6B, 0x6B, 0x62, 0x61, 0x6C, 0x1C, 0xD8, 0x30, 0x65, 0x85, 0x4E, 0x00, 0x62, 0xF2, ++0xED, 0x95, 0x06, 0x6C, 0x7B, 0xA5, 0x01, 0x1B, 0xC1, 0xF4, 0x08, 0x82, 0x57, 0xC4, 0x0F, 0xF5, 0xC6, 0xD9, 0xB0, 0x65, ++0x50, 0xE9, 0xB7, 0x12, 0xEA, 0xB8, 0xBE, 0x8B, 0x7C, 0x88, 0xB9, 0xFC, 0xDF, 0x1D, 0xDD, 0x62, 0x49, 0x2D, 0xDA, 0x15, ++0xF3, 0x7C, 0xD3, 0x8C, 0x65, 0x4C, 0xD4, 0xFB, 0x58, 0x61, 0xB2, 0x4D, 0xCE, 0x51, 0xB5, 0x3A, 0x74, 0x00, 0xBC, 0xA3, ++0xE2, 0x30, 0xBB, 0xD4, 0x41, 0xA5, 0xDF, 0x4A, 0xD7, 0x95, 0xD8, 0x3D, 0x6D, 0xC4, 0xD1, 0xA4, 0xFB, 0xF4, 0xD6, 0xD3, ++0x6A, 0xE9, 0x69, 0x43, 0xFC, 0xD9, 0x6E, 0x34, 0x46, 0x88, 0x67, 0xAD, 0xD0, 0xB8, 0x60, 0xDA, 0x73, 0x2D, 0x04, 0x44, ++0xE5, 0x1D, 0x03, 0x33, 0x5F, 0x4C, 0x0A, 0xAA, 0xC9, 0x7C, 0x0D, 0xDD, 0x3C, 0x71, 0x05, 0x50, 0xAA, 0x41, 0x02, 0x27, ++0x10, 0x10, 0x0B, 0xBE, 0x86, 0x20, 0x0C, 0xC9, 0x25, 0xB5, 0x68, 0x57, 0xB3, 0x85, 0x6F, 0x20, 0x09, 0xD4, 0x66, 0xB9, ++0x9F, 0xE4, 0x61, 0xCE, 0x0E, 0xF9, 0xDE, 0x5E, 0x98, 0xC9, 0xD9, 0x29, 0x22, 0x98, 0xD0, 0xB0, 0xB4, 0xA8, 0xD7, 0xC7, ++0x17, 0x3D, 0xB3, 0x59, 0x81, 0x0D, 0xB4, 0x2E, 0x3B, 0x5C, 0xBD, 0xB7, 0xAD, 0x6C, 0xBA, 0xC0, 0x20, 0x83, 0xB8, 0xED, ++0xB6, 0xB3, 0xBF, 0x9A, 0x0C, 0xE2, 0xB6, 0x03, 0x9A, 0xD2, 0xB1, 0x74, 0x39, 0x47, 0xD5, 0xEA, 0xAF, 0x77, 0xD2, 0x9D, ++0x15, 0x26, 0xDB, 0x04, 0x83, 0x16, 0xDC, 0x73, 0x12, 0x0B, 0x63, 0xE3, 0x84, 0x3B, 0x64, 0x94, 0x3E, 0x6A, 0x6D, 0x0D, ++0xA8, 0x5A, 0x6A, 0x7A, 0x0B, 0xCF, 0x0E, 0xE4, 0x9D, 0xFF, 0x09, 0x93, 0x27, 0xAE, 0x00, 0x0A, 0xB1, 0x9E, 0x07, 0x7D, ++0x44, 0x93, 0x0F, 0xF0, 0xD2, 0xA3, 0x08, 0x87, 0x68, 0xF2, 0x01, 0x1E, 0xFE, 0xC2, 0x06, 0x69, 0x5D, 0x57, 0x62, 0xF7, ++0xCB, 0x67, 0x65, 0x80, 0x71, 0x36, 0x6C, 0x19, 0xE7, 0x06, 0x6B, 0x6E, 0x76, 0x1B, 0xD4, 0xFE, 0xE0, 0x2B, 0xD3, 0x89, ++0x5A, 0x7A, 0xDA, 0x10, 0xCC, 0x4A, 0xDD, 0x67, 0x6F, 0xDF, 0xB9, 0xF9, 0xF9, 0xEF, 0xBE, 0x8E, 0x43, 0xBE, 0xB7, 0x17, ++0xD5, 0x8E, 0xB0, 0x60, 0xE8, 0xA3, 0xD6, 0xD6, 0x7E, 0x93, 0xD1, 0xA1, 0xC4, 0xC2, 0xD8, 0x38, 0x52, 0xF2, 0xDF, 0x4F, ++0xF1, 0x67, 0xBB, 0xD1, 0x67, 0x57, 0xBC, 0xA6, 0xDD, 0x06, 0xB5, 0x3F, 0x4B, 0x36, 0xB2, 0x48, 0xDA, 0x2B, 0x0D, 0xD8, ++0x4C, 0x1B, 0x0A, 0xAF, 0xF6, 0x4A, 0x03, 0x36, 0x60, 0x7A, 0x04, 0x41, 0xC3, 0xEF, 0x60, 0xDF, 0x55, 0xDF, 0x67, 0xA8, ++0xEF, 0x8E, 0x6E, 0x31, 0x79, 0xBE, 0x69, 0x46, 0x8C, 0xB3, 0x61, 0xCB, 0x1A, 0x83, 0x66, 0xBC, 0xA0, 0xD2, 0x6F, 0x25, ++0x36, 0xE2, 0x68, 0x52, 0x95, 0x77, 0x0C, 0xCC, 0x03, 0x47, 0x0B, 0xBB, 0xB9, 0x16, 0x02, 0x22, 0x2F, 0x26, 0x05, 0x55, ++0xBE, 0x3B, 0xBA, 0xC5, 0x28, 0x0B, 0xBD, 0xB2, 0x92, 0x5A, 0xB4, 0x2B, 0x04, 0x6A, 0xB3, 0x5C, 0xA7, 0xFF, 0xD7, 0xC2, ++0x31, 0xCF, 0xD0, 0xB5, 0x8B, 0x9E, 0xD9, 0x2C, 0x1D, 0xAE, 0xDE, 0x5B, 0xB0, 0xC2, 0x64, 0x9B, 0x26, 0xF2, 0x63, 0xEC, ++0x9C, 0xA3, 0x6A, 0x75, 0x0A, 0x93, 0x6D, 0x02, 0xA9, 0x06, 0x09, 0x9C, 0x3F, 0x36, 0x0E, 0xEB, 0x85, 0x67, 0x07, 0x72, ++0x13, 0x57, 0x00, 0x05, 0x82, 0x4A, 0xBF, 0x95, 0x14, 0x7A, 0xB8, 0xE2, 0xAE, 0x2B, 0xB1, 0x7B, 0x38, 0x1B, 0xB6, 0x0C, ++0x9B, 0x8E, 0xD2, 0x92, 0x0D, 0xBE, 0xD5, 0xE5, 0xB7, 0xEF, 0xDC, 0x7C, 0x21, 0xDF, 0xDB, 0x0B, 0xD4, 0xD2, 0xD3, 0x86, ++0x42, 0xE2, 0xD4, 0xF1, 0xF8, 0xB3, 0xDD, 0x68, 0x6E, 0x83, 0xDA, 0x1F, 0xCD, 0x16, 0xBE, 0x81, 0x5B, 0x26, 0xB9, 0xF6, ++0xE1, 0x77, 0xB0, 0x6F, 0x77, 0x47, 0xB7, 0x18, 0xE6, 0x5A, 0x08, 0x88, 0x70, 0x6A, 0x0F, 0xFF, 0xCA, 0x3B, 0x06, 0x66, ++0x5C, 0x0B, 0x01, 0x11, 0xFF, 0x9E, 0x65, 0x8F, 0x69, 0xAE, 0x62, 0xF8, 0xD3, 0xFF, 0x6B, 0x61, 0x45, 0xCF, 0x6C, 0x16, ++0x78, 0xE2, 0x0A, 0xA0, 0xEE, 0xD2, 0x0D, 0xD7, 0x54, 0x83, 0x04, 0x4E, 0xC2, 0xB3, 0x03, 0x39, 0x61, 0x26, 0x67, 0xA7, ++0xF7, 0x16, 0x60, 0xD0, 0x4D, 0x47, 0x69, 0x49, 0xDB, 0x77, 0x6E, 0x3E, 0x4A, 0x6A, 0xD1, 0xAE, 0xDC, 0x5A, 0xD6, 0xD9, ++0x66, 0x0B, 0xDF, 0x40, 0xF0, 0x3B, 0xD8, 0x37, 0x53, 0xAE, 0xBC, 0xA9, 0xC5, 0x9E, 0xBB, 0xDE, 0x7F, 0xCF, 0xB2, 0x47, ++0xE9, 0xFF, 0xB5, 0x30, 0x1C, 0xF2, 0xBD, 0xBD, 0x8A, 0xC2, 0xBA, 0xCA, 0x30, 0x93, 0xB3, 0x53, 0xA6, 0xA3, 0xB4, 0x24, ++0x05, 0x36, 0xD0, 0xBA, 0x93, 0x06, 0xD7, 0xCD, 0x29, 0x57, 0xDE, 0x54, 0xBF, 0x67, 0xD9, 0x23, 0x2E, 0x7A, 0x66, 0xB3, ++0xB8, 0x4A, 0x61, 0xC4, 0x02, 0x1B, 0x68, 0x5D, 0x94, 0x2B, 0x6F, 0x2A, 0x37, 0xBE, 0x0B, 0xB4, 0xA1, 0x8E, 0x0C, 0xC3, ++0x1B, 0xDF, 0x05, 0x5A, 0x8D, 0xEF, 0x02, 0x2D, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6E, 0x64, 0x00, ++0x00, 0x50, 0xF2, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x03, ++0x04, 0x08, 0x02, 0x01, 0x01, 0x00, 0x02, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x02, 0x04, 0x0B, 0x16, ++0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, ++0x44, 0x42, 0x47, 0x5F, 0x53, 0x45, 0x56, 0x5F, 0x4D, 0x49, 0x4E, 0x20, 0x3C, 0x3D, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, ++0x78, 0x20, 0x26, 0x26, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3C, 0x20, 0x44, 0x42, 0x47, 0x5F, 0x53, 0x45, ++0x56, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, ++0x63, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, ++0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, ++0x03, 0x02, 0x06, 0x07, 0x00, 0x00, 0x04, 0x02, 0x03, 0x02, 0x06, 0x07, 0x00, 0x00, 0x04, 0x03, 0x03, 0x00, 0x06, 0x07, ++0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x2C, 0x20, 0x77, 0x6C, 0x61, ++0x6E, 0x20, 0x66, 0x63, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x62, 0x6F, ++0x6F, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x70, 0x69, 0x6F, 0x77, 0x72, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, ++0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x53, ++0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x20, 0x66, 0x69, 0x6C, 0x74, ++0x65, 0x72, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x53, ++0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x20, 0x66, 0x69, 0x6C, 0x74, 0x65, 0x72, ++0x3A, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x42, ++0x6F, 0x6F, 0x74, 0x20, 0x4E, 0x50, 0x43, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x57, ++0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6D, ++0x61, 0x73, 0x6B, 0x3A, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x3A, 0x30, 0x78, 0x25, ++0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, ++0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, ++0x47, 0x3A, 0x20, 0x57, 0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x77, 0x69, ++0x74, 0x68, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, ++0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, ++0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x52, 0x65, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, ++0x79, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, ++0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x42, 0x6F, 0x6F, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, ++0x25, 0x78, 0x2C, 0x20, 0x61, 0x64, 0x64, 0x72, 0x3D, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x64, 0x65, 0x6C, 0x61, 0x79, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, ++0x62, 0x6F, 0x6F, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0D, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x46, ++0x57, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x57, ++0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x7E, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x77, 0x69, ++0x74, 0x68, 0x20, 0x7B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x2E, 0x2E, 0x2E, 0x7D, 0x2C, 0x20, 0x77, 0x73, ++0x74, 0x61, 0x74, 0x75, 0x73, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x70, 0x22, 0x17, 0x00, ++0x0C, 0x00, 0x00, 0x00, 0x9B, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x20, 0x28, 0x25, 0x73, 0x29, 0x20, 0x61, 0x74, 0x20, ++0x25, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x9B, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x20, 0x28, 0x25, 0x73, ++0x29, 0x20, 0x61, 0x74, 0x20, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x45, 0x72, 0x72, 0x3A, 0x20, 0x55, 0x46, 0x20, ++0x68, 0x6F, 0x73, 0x74, 0x20, 0x72, 0x78, 0x20, 0x62, 0x75, 0x66, 0x66, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x0D, 0x0A, 0x00, ++0x09, 0x2D, 0x20, 0x00, 0x25, 0x73, 0x25, 0x73, 0x25, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, ++0x25, 0x30, 0x32, 0x78, 0x20, 0x00, 0x00, 0x00, 0x25, 0x30, 0x38, 0x78, 0x3A, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x34, ++0x58, 0x20, 0x25, 0x30, 0x34, 0x58, 0x00, 0x00, 0x20, 0x25, 0x30, 0x32, 0x58, 0x20, 0x25, 0x30, 0x32, 0x58, 0x20, 0x25, ++0x30, 0x32, 0x58, 0x20, 0x25, 0x30, 0x32, 0x58, 0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x34, 0x58, 0x00, 0x00, 0x00, ++0x20, 0x25, 0x30, 0x32, 0x58, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x68, 0x65, 0x6C, ++0x70, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0x00, 0x68, 0x65, 0x6C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x20, 0x72, 0x20, 0x61, ++0x64, 0x64, 0x72, 0x20, 0x3C, 0x63, 0x6E, 0x74, 0x3E, 0x20, 0x3C, 0x73, 0x7A, 0x3E, 0x00, 0x00, 0x20, 0x77, 0x20, 0x61, ++0x64, 0x64, 0x72, 0x20, 0x76, 0x61, 0x6C, 0x00, 0x77, 0x00, 0x00, 0x00, 0x20, 0x64, 0x62, 0x67, 0x20, 0x6D, 0x73, 0x6B, ++0x00, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x00, 0x00, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x76, 0x61, 0x6C, 0x28, 0x69, 0x6E, ++0x20, 0x73, 0x29, 0x00, 0x77, 0x66, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, 0x20, 0x63, 0x6D, 0x64, ++0x5F, 0x66, 0x72, 0x65, 0x65, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x20, 0x65, 0x6D, 0x70, 0x74, 0x79, 0x0D, 0x0A, 0x00, 0x00, ++0x61, 0x69, 0x63, 0x3E, 0x20, 0x00, 0x00, 0x00, 0x4E, 0x6F, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x63, 0x6D, 0x64, 0x73, ++0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x64, 0x2E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x2A, 0x20, 0x54, ++0x6F, 0x6F, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, 0x28, 0x6D, 0x61, 0x78, 0x2E, 0x20, 0x25, ++0x64, 0x29, 0x20, 0x2A, 0x2A, 0x0A, 0x00, 0x00, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x20, 0x63, 0x6F, 0x6D, 0x6D, ++0x61, 0x6E, 0x64, 0x20, 0x27, 0x25, 0x73, 0x27, 0x0A, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x25, ++0x73, 0x0A, 0x00, 0x00, 0x63, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x0D, 0x0A, 0x00, 0x00, ++0x63, 0x75, 0x72, 0x20, 0x64, 0x62, 0x67, 0x5F, 0x6D, 0x73, 0x6B, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x63, 0x66, 0x67, 0x20, 0x64, 0x62, 0x67, 0x5F, 0x6D, 0x73, 0x6B, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x76, 0x61, ++0x6C, 0x69, 0x64, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, ++0x65, 0x3A, 0x0A, 0x20, 0x20, 0x72, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3C, 0x63, 0x6E, 0x74, 0x3E, 0x0A, 0x00, 0x00, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x0D, 0x0A, 0x00, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x32, 0x58, 0x0D, 0x0A, 0x00, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x34, 0x58, 0x0D, 0x0A, 0x00, ++0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x20, 0x20, 0x77, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x76, 0x61, 0x6C, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x76, 0x61, 0x6C, ++0x28, 0x69, 0x6E, 0x20, 0x73, 0x29, 0x0A, 0x00, 0x63, 0x75, 0x72, 0x20, 0x77, 0x66, 0x63, 0x74, 0x3A, 0x20, 0x25, 0x75, ++0x73, 0x0A, 0x00, 0x00, 0x63, 0x66, 0x67, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x25, 0x75, 0x73, 0x0A, 0x00, 0x00, 0x00, ++0x77, 0x66, 0x63, 0x74, 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x0A, 0x00, 0x00, ++0x08, 0x20, 0x08, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x07, 0x00, 0x50, ++0xF2, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x45, 0x5F, ++0x42, 0x55, 0x53, 0x59, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x65, 0x6E, 0x76, ++0x2E, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x5F, 0x76, 0x69, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, ++0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x00, 0xD8, 0x22, 0x17, 0x00, 0x18, 0x00, 0x00, 0x00, ++0x62, 0x69, 0x74, 0x5F, 0x70, 0x6F, 0x73, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, 0x45, ++0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2D, 0x3E, 0x6C, 0x65, 0x6E, 0x67, 0x74, ++0x68, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x48, ++0x45, 0x29, 0x00, 0x00, 0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x56, 0x48, 0x54, 0x29, 0x00, ++0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x48, 0x54, 0x29, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, ++0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, ++0x63, 0x75, 0x72, 0x72, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x6D, 0x69, 0x63, 0x5F, 0x63, 0x61, 0x6C, 0x63, 0x5F, 0x70, 0x74, 0x72, 0x2D, 0x3E, 0x6C, 0x61, 0x73, 0x74, 0x5F, 0x6D, ++0x5F, 0x69, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x20, 0x34, 0x00, 0x00, 0x72, 0x65, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x75, 0x2E, 0x73, 0x74, 0x61, 0x2E, 0x61, 0x70, 0x5F, 0x69, 0x64, ++0x20, 0x3D, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x49, 0x44, 0x58, 0x00, ++0x63, 0x6F, 0x6E, 0x6E, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x20, 0x69, 0x6E, 0x64, 0x0D, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, ++0x20, 0x53, 0x4D, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x4E, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, ++0x20, 0x53, 0x4D, 0x5F, 0x4A, 0x4F, 0x49, 0x4E, 0x49, 0x4E, 0x47, 0x00, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x3A, 0x20, 0x25, ++0x34, 0x78, 0x3A, 0x25, 0x34, 0x78, 0x3A, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x28, 0x6B, 0x65, 0x5F, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, ++0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, ++0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, ++0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, ++0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, ++0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, ++0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, ++0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, ++0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, ++0x47, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, ++0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, ++0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, ++0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x00, 0x00, ++0x73, 0x6D, 0x20, 0x63, 0x6F, 0x65, 0x78, 0x20, 0x74, 0x73, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, ++0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x41, 0x44, 0x44, 0x49, ++0x4E, 0x47, 0x00, 0x00, 0x98, 0x23, 0x17, 0x00, 0x15, 0x00, 0x00, 0x00, 0x74, 0x78, 0x20, 0x63, 0x66, 0x6D, 0x3A, 0x25, ++0x64, 0x2C, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x73, 0x5F, 0x65, ++0x6D, 0x70, 0x74, 0x79, 0x28, 0x26, 0x73, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x62, 0x73, 0x73, 0x5F, 0x63, 0x6F, 0x6E, ++0x66, 0x69, 0x67, 0x29, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x20, 0x72, 0x65, 0x6F, 0x75, 0x72, ++0x63, 0x65, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x2F, 0x64, 0x69, 0x73, 0x61, 0x73, ++0x73, 0x6F, 0x63, 0x3A, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x63, ++0x74, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x3A, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x61, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x61, 0x75, 0x74, 0x68, ++0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x61, 0x73, 0x73, 0x6F, ++0x63, 0x5F, 0x72, 0x73, 0x70, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x20, ++0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x61, 0x75, ++0x74, 0x68, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x20, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x20, 0x63, ++0x6F, 0x64, 0x65, 0x20, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x42, 0x53, 0x53, 0x5F, 0x43, 0x41, 0x50, 0x41, ++0x28, 0x62, 0x73, 0x73, 0x2C, 0x20, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x29, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x03, 0x00, ++0x00, 0x00, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x73, 0x6D, 0x5F, 0x61, 0x75, 0x74, 0x68, 0x5F, ++0x73, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6D, 0x5F, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x5F, 0x72, 0x65, 0x71, ++0x5F, 0x73, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, 0x43, ++0x4E, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, 0x61, 0x70, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, ++0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, ++0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, ++0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, ++0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, ++0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x20, 0x7C, 0x7C, ++0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, ++0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, ++0x29, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, ++0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, ++0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, ++0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, ++0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, ++0x50, 0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, ++0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x00, 0x00, 0x00, 0x00, 0x61, 0x70, 0x20, 0x73, ++0x74, 0x6F, 0x70, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x73, 0x5F, 0x65, ++0x6D, 0x70, 0x74, 0x79, 0x28, 0x26, 0x61, 0x70, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x62, 0x73, 0x73, 0x5F, 0x63, 0x6F, ++0x6E, 0x66, 0x69, 0x67, 0x29, 0x00, 0x00, 0x00, 0x40, 0x24, 0x17, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, ++0x75, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, ++0x75, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x0D, 0x0A, 0x00, ++0x73, 0x63, 0x61, 0x6E, 0x75, 0x20, 0x73, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x76, 0x6E, 0x64, 0x72, 0x20, ++0x69, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x63, 0x61, ++0x6E, 0x75, 0x20, 0x72, 0x65, 0x71, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x4D, 0x41, 0x43, ++0x5F, 0x41, 0x44, 0x44, 0x52, 0x5F, 0x47, 0x52, 0x4F, 0x55, 0x50, 0x28, 0x26, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, ++0x62, 0x73, 0x73, 0x69, 0x64, 0x29, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x20, 0x76, 0x6E, 0x64, 0x72, 0x20, 0x69, ++0x65, 0x0D, 0x0A, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x20, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x24, 0x17, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC8, 0x24, 0x17, 0x00, ++0x05, 0x00, 0x00, 0x00, 0xF0, 0x24, 0x17, 0x00, 0x07, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x5F, 0x63, 0x6F, ++0x6E, 0x66, 0x69, 0x72, 0x6D, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x5B, 0x48, 0x49, 0x44, ++0x44, 0x45, 0x4E, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x2D, 0x00, 0x6A, 0x6F, 0x69, 0x6E, ++0x3A, 0x25, 0x73, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x66, 0x69, 0x78, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x6E, 0x6F, 0x5F, 0x73, ++0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x64, 0x20, ++0x25, 0x64, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x20, 0x25, 0x78, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00, 0x00, ++0x28, 0x69, 0x65, 0x5F, 0x62, 0x75, 0x66, 0x20, 0x2D, 0x20, 0x43, 0x50, 0x55, 0x32, 0x48, 0x57, 0x28, 0x69, 0x65, 0x2D, ++0x3E, 0x62, 0x75, 0x66, 0x29, 0x29, 0x20, 0x3C, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x49, ++0x45, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3A, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x20, 0x61, ++0x72, 0x70, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x69, 0x70, 0x3D, 0x25, 0x78, 0x2E, 0x20, 0x76, 0x69, 0x66, 0x20, 0x69, 0x70, ++0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x78, 0x20, 0x61, 0x72, 0x70, 0x72, 0x65, 0x73, 0x70, 0x0A, 0x00, ++0x72, 0x78, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x2D, 0x3E, 0x76, 0x61, 0x6C, 0x2E, 0x73, 0x74, ++0x61, 0x74, 0x75, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x75, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x20, 0x73, ++0x74, 0x61, 0x74, 0x3A, 0x25, 0x64, 0x00, 0x00, 0x54, 0x4B, 0x49, 0x50, 0x20, 0x49, 0x43, 0x56, 0x20, 0x45, 0x52, 0x52, ++0x0A, 0x00, 0x00, 0x00, 0x64, 0x65, 0x66, 0x72, 0x61, 0x67, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, ++0x72, 0x78, 0x5F, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x2D, 0x3E, 0x6F, 0x6F, 0x6F, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x63, 0x6E, ++0x74, 0x00, 0x00, 0x00, 0x6F, 0x6C, 0x64, 0x5F, 0x77, 0x69, 0x6E, 0x5F, 0x62, 0x61, 0x72, 0x20, 0x64, 0x65, 0x74, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x2D, 0x3E, 0x6F, 0x6F, 0x6F, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x63, ++0x6E, 0x74, 0x3C, 0x3D, 0x36, 0x34, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x64, 0x65, 0x61, ++0x75, 0x74, 0x68, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x21, 0x3D, 0x20, ++0x30, 0x78, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6D, 0x61, 0x63, 0x68, 0x64, 0x72, 0x5F, 0x6C, 0x65, 0x6E, 0x67, ++0x74, 0x68, 0x20, 0x26, 0x20, 0x30, 0x78, 0x33, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x72, 0x78, 0x20, 0x65, ++0x61, 0x70, 0x6F, 0x6C, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x57, 0x45, 0x50, 0x20, ++0x49, 0x43, 0x56, 0x20, 0x45, 0x52, 0x52, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x20, 0x21, 0x3D, ++0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x72, 0x78, 0x75, 0x5F, 0x63, 0x6E, 0x74, 0x72, 0x6C, 0x5F, 0x73, 0x70, ++0x75, 0x72, 0x69, 0x6F, 0x75, 0x73, 0x5F, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x75, 0x20, ++0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x6D, 0x69, 0x74, 0x20, 0x74, 0x78, 0x75, 0x20, 0x64, ++0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x0A, 0x00, 0x70, 0x6F, 0x72, 0x74, 0x20, 0x66, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3A, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x2D, 0x3E, 0x73, 0x74, 0x61, 0x69, 0x64, 0x20, ++0x21, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, ++0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x61, 0x64, 0x64, 0x62, 0x61, 0x5F, 0x72, 0x65, 0x71, 0x3A, 0x74, 0x69, 0x64, ++0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x61, 0x64, 0x64, 0x62, 0x61, ++0x5F, 0x72, 0x73, 0x70, 0x3A, 0x74, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x72, 0x78, 0x5F, 0x64, 0x65, 0x6C, 0x62, 0x61, 0x3A, ++0x74, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, ++0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x74, 0x78, 0x5F, 0x64, 0x65, 0x6C, 0x62, 0x61, 0x3A, 0x74, 0x69, 0x64, 0x3D, ++0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x2C, 0x25, 0x17, 0x00, ++0x05, 0x00, 0x00, 0x00, 0x6D, 0x6F, 0x76, 0x65, 0x20, 0x77, 0x69, 0x6E, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x66, ++0x6C, 0x75, 0x73, 0x68, 0x3A, 0x20, 0x73, 0x75, 0x63, 0x63, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x70, ++0x61, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x4B, 0x45, 0x5F, 0x42, 0x55, 0x49, 0x4C, 0x44, 0x5F, 0x49, 0x44, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x42, 0x41, ++0x4D, 0x2C, 0x20, 0x62, 0x61, 0x6D, 0x5F, 0x69, 0x64, 0x78, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x41, 0x4D, 0x5F, ++0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x00, 0x00, 0x62, 0x61, 0x6D, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x42, 0x41, ++0x4D, 0x5F, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, ++0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, ++0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, ++0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, ++0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, ++0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, ++0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, ++0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, ++0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, ++0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, ++0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, ++0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, ++0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, ++0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, ++0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, ++0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, 0xC6, 0xF8, 0xEE, 0xF6, ++0xFF, 0xD6, 0xDE, 0x91, 0x60, 0x02, 0xCE, 0x56, 0xE7, 0xB5, 0x4D, 0xEC, 0x8F, 0x1F, 0x89, 0xFA, 0xEF, 0xB2, 0x8E, 0xFB, ++0x41, 0xB3, 0x5F, 0x45, 0x23, 0x53, 0xE4, 0x9B, 0x75, 0xE1, 0x3D, 0x4C, 0x6C, 0x7E, 0xF5, 0x83, 0x68, 0x51, 0xD1, 0xF9, ++0xE2, 0xAB, 0x62, 0x2A, 0x08, 0x95, 0x46, 0x9D, 0x30, 0x37, 0x0A, 0x2F, 0x0E, 0x24, 0x1B, 0xDF, 0xCD, 0x4E, 0x7F, 0xEA, ++0x12, 0x1D, 0x58, 0x34, 0x36, 0xDC, 0xB4, 0x5B, 0xA4, 0x76, 0xB7, 0x7D, 0x52, 0xDD, 0x5E, 0x13, 0xA6, 0xB9, 0x00, 0xC1, ++0x40, 0xE3, 0x79, 0xB6, 0xD4, 0x8D, 0x67, 0x72, 0x94, 0x98, 0xB0, 0x85, 0xBB, 0xC5, 0x4F, 0xED, 0x86, 0x9A, 0x66, 0x11, ++0x8A, 0xE9, 0x04, 0xFE, 0xA0, 0x78, 0x25, 0x4B, 0xA2, 0x5D, 0x80, 0x05, 0x3F, 0x21, 0x70, 0xF1, 0x63, 0x77, 0xAF, 0x42, ++0x20, 0xE5, 0xFD, 0xBF, 0x81, 0x18, 0x26, 0xC3, 0xBE, 0x35, 0x88, 0x2E, 0x93, 0x55, 0xFC, 0x7A, 0xC8, 0xBA, 0x32, 0xE6, ++0xC0, 0x19, 0x9E, 0xA3, 0x44, 0x54, 0x3B, 0x0B, 0x8C, 0xC7, 0x6B, 0x28, 0xA7, 0xBC, 0x16, 0xAD, 0xDB, 0x64, 0x74, 0x14, ++0x92, 0x0C, 0x48, 0xB8, 0x9F, 0xBD, 0x43, 0xC4, 0x39, 0x31, 0xD3, 0xF2, 0xD5, 0x8B, 0x6E, 0xDA, 0x01, 0xB1, 0x9C, 0x49, ++0xD8, 0xAC, 0xF3, 0xCF, 0xCA, 0xF4, 0x47, 0x10, 0x6F, 0xF0, 0x4A, 0x5C, 0x38, 0x57, 0x73, 0x97, 0xCB, 0xA1, 0xE8, 0x3E, ++0x96, 0x61, 0x0D, 0x0F, 0xE0, 0x7C, 0x71, 0xCC, 0x90, 0x06, 0xF7, 0x1C, 0xC2, 0x6A, 0xAE, 0x69, 0x17, 0x99, 0x3A, 0x27, ++0xD9, 0xEB, 0x2B, 0x22, 0xD2, 0xA9, 0x07, 0x33, 0x2D, 0x3C, 0x15, 0xC9, 0x87, 0xAA, 0x50, 0xA5, 0x03, 0x59, 0x09, 0x1A, ++0x65, 0xD7, 0x84, 0xD0, 0x82, 0x29, 0x5A, 0x1E, 0x7B, 0xA8, 0x6D, 0x2C, 0xA5, 0x84, 0x99, 0x8D, 0x0D, 0xBD, 0xB1, 0x54, ++0x50, 0x03, 0xA9, 0x7D, 0x19, 0x62, 0xE6, 0x9A, 0x45, 0x9D, 0x40, 0x87, 0x15, 0xEB, 0xC9, 0x0B, 0xEC, 0x67, 0xFD, 0xEA, ++0xBF, 0xF7, 0x96, 0x5B, 0xC2, 0x1C, 0xAE, 0x6A, 0x5A, 0x41, 0x02, 0x4F, 0x5C, 0xF4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3F, ++0x0C, 0x52, 0x65, 0x5E, 0x28, 0xA1, 0x0F, 0xB5, 0x09, 0x36, 0x9B, 0x3D, 0x26, 0x69, 0xCD, 0x9F, 0x1B, 0x9E, 0x74, 0x2E, ++0x2D, 0xB2, 0xEE, 0xFB, 0xF6, 0x4D, 0x61, 0xCE, 0x7B, 0x3E, 0x71, 0x97, 0xF5, 0x68, 0x00, 0x2C, 0x60, 0x1F, 0xC8, 0xED, ++0xBE, 0x46, 0xD9, 0x4B, 0xDE, 0xD4, 0xE8, 0x4A, 0x6B, 0x2A, 0xE5, 0x16, 0xC5, 0xD7, 0x55, 0x94, 0xCF, 0x10, 0x06, 0x81, ++0xF0, 0x44, 0xBA, 0xE3, 0xF3, 0xFE, 0xC0, 0x8A, 0xAD, 0xBC, 0x48, 0x04, 0xDF, 0xC1, 0x75, 0x63, 0x30, 0x1A, 0x0E, 0x6D, ++0x4C, 0x14, 0x35, 0x2F, 0xE1, 0xA2, 0xCC, 0x39, 0x57, 0xF2, 0x82, 0x47, 0xAC, 0xE7, 0x2B, 0x95, 0xA0, 0x98, 0xD1, 0x7F, ++0x66, 0x7E, 0xAB, 0x83, 0xCA, 0x29, 0xD3, 0x3C, 0x79, 0xE2, 0x1D, 0x76, 0x3B, 0x56, 0x4E, 0x1E, 0xDB, 0x0A, 0x6C, 0xE4, ++0x5D, 0x6E, 0xEF, 0xA6, 0xA8, 0xA4, 0x37, 0x8B, 0x32, 0x43, 0x59, 0xB7, 0x8C, 0x64, 0xD2, 0xE0, 0xB4, 0xFA, 0x07, 0x25, ++0xAF, 0x8E, 0xE9, 0x18, 0xD5, 0x88, 0x6F, 0x72, 0x24, 0xF1, 0xC7, 0x51, 0x23, 0x7C, 0x9C, 0x21, 0xDD, 0xDC, 0x86, 0x85, ++0x90, 0x42, 0xC4, 0xAA, 0xD8, 0x05, 0x01, 0x12, 0xA3, 0x5F, 0xF9, 0xD0, 0x91, 0x58, 0x27, 0xB9, 0x38, 0x13, 0xB3, 0x33, ++0xBB, 0x70, 0x89, 0xA7, 0xB6, 0x22, 0x92, 0x20, 0x49, 0xFF, 0x78, 0x7A, 0x8F, 0xF8, 0x80, 0x17, 0xDA, 0x31, 0xC6, 0xB8, ++0xC3, 0xB0, 0x77, 0x11, 0xCB, 0xFC, 0xD6, 0x3A, 0x72, 0x63, 0x5F, 0x72, 0x73, 0x2D, 0x3E, 0x61, 0x74, 0x74, 0x65, 0x6D, ++0x70, 0x74, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x72, 0x73, 0x2D, 0x3E, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, ++0x73, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, 0x3D, 0x20, 0x46, 0x4F, ++0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, 0x45, 0x5F, 0x53, 0x55, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, ++0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, ++0x54, 0x5F, 0x4D, 0x46, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, ++0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x00, 0x00, 0x28, 0x66, 0x6F, 0x72, ++0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, ++0x5F, 0x48, 0x54, 0x5F, 0x4D, 0x46, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, ++0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, 0x54, 0x5F, 0x47, ++0x46, 0x29, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, ++0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x20, 0x7C, 0x7C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, ++0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, ++0x4F, 0x4E, 0x5F, 0x48, 0x54, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, ++0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x00, 0x28, 0x66, 0x6F, 0x72, ++0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, ++0x5F, 0x48, 0x45, 0x5F, 0x53, 0x55, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, ++0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, 0x4F, 0x4E, 0x5F, ++0x48, 0x54, 0x29, 0x00, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x00, ++0x73, 0x67, 0x69, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, ++0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, ++0x6D, 0x63, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, ++0x6D, 0x69, 0x6E, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, ++0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, ++0x5F, 0x6D, 0x61, 0x70, 0x5F, 0x6C, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, 0x54, 0x28, 0x6D, 0x63, 0x73, 0x29, ++0x29, 0x00, 0x00, 0x00, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, ++0x73, 0x67, 0x69, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x73, 0x68, 0x6F, 0x72, 0x74, 0x5F, ++0x67, 0x69, 0x00, 0x00, 0x62, 0x77, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, 0x77, 0x5F, ++0x6D, 0x61, 0x78, 0x00, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, ++0x5F, 0x73, 0x73, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, 0x63, ++0x73, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x00, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, ++0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x68, 0x74, 0x5B, 0x6E, 0x73, 0x73, 0x5D, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, ++0x54, 0x28, 0x6D, 0x63, 0x73, 0x29, 0x29, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x28, 0x37, 0x20, 0x2B, 0x20, ++0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, 0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x76, 0x68, 0x74, ++0x20, 0x3E, 0x3E, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3C, 0x20, 0x31, 0x29, 0x20, 0x26, 0x20, 0x4D, 0x41, 0x43, ++0x5F, 0x56, 0x48, 0x54, 0x5F, 0x4D, 0x43, 0x53, 0x5F, 0x4D, 0x41, 0x50, 0x5F, 0x4D, 0x53, 0x4B, 0x29, 0x29, 0x00, 0x00, ++0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x36, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, ++0x3D, 0x20, 0x42, 0x57, 0x5F, 0x38, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x28, 0x6E, 0x73, 0x73, ++0x20, 0x3D, 0x3D, 0x20, 0x33, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x36, 0x29, ++0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, ++0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, ++0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, ++0x73, 0x20, 0x21, 0x3D, 0x20, 0x35, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x28, 0x28, 0x6D, 0x63, ++0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, ++0x5F, 0x38, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x35, ++0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, ++0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x31, 0x36, 0x30, 0x4D, 0x48, 0x5A, 0x29, ++0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x32, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, ++0x00, 0x00, 0x00, 0x00, 0x67, 0x69, 0x20, 0x3C, 0x3D, 0x20, 0x32, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x28, ++0x37, 0x20, 0x2B, 0x20, 0x32, 0x20, 0x2A, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, ++0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x68, 0x65, 0x20, 0x3E, 0x3E, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3C, 0x20, 0x31, ++0x29, 0x20, 0x26, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x45, 0x5F, 0x4D, 0x43, 0x53, 0x5F, 0x4D, 0x41, 0x50, 0x5F, 0x4D, ++0x53, 0x4B, 0x29, 0x29, 0x00, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, 0x5F, 0x73, 0x61, ++0x6D, 0x70, 0x6C, 0x65, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, ++0x6F, 0x5F, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x52, 0x43, 0x5F, 0x4D, 0x41, 0x58, 0x5F, ++0x4E, 0x5F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, ++0x77, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x31, 0x36, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, ++0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, 0x5F, 0x73, 0x73, 0x20, 0x3C, 0x20, 0x38, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x74, 0x61, 0x2D, 0x3E, 0x73, 0x74, 0x61, 0x69, 0x64, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, ++0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, ++0x63, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x31, 0x32, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x52, 0x41, 0x54, 0x45, ++0x5F, 0x31, 0x31, 0x4D, 0x42, 0x50, 0x53, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, ++0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x29, 0x00, 0x00, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x52, 0x41, 0x54, 0x45, ++0x5F, 0x31, 0x31, 0x4D, 0x42, 0x50, 0x53, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, ++0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x29, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, ++0x63, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x31, 0x30, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, ++0x6F, 0x5F, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x33, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, ++0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, ++0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, 0x69, 0x64, 0x78, ++0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, ++0x45, 0x4E, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, 0x77, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3D, 0x3D, ++0x20, 0x42, 0x57, 0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x74, ++0x69, 0x6F, 0x6E, 0x5F, 0x69, 0x64, 0x3D, 0x25, 0x69, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, ++0x3D, 0x25, 0x69, 0x20, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x25, 0x69, 0x20, 0x73, 0x68, 0x6F, 0x72, ++0x74, 0x5F, 0x67, 0x69, 0x3D, 0x25, 0x69, 0x20, 0x6D, 0x61, 0x78, 0x5F, 0x62, 0x77, 0x3D, 0x25, 0x69, 0x0A, 0x00, 0x00, ++0x25, 0x73, 0x3A, 0x20, 0x6E, 0x73, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x6D, 0x63, 0x73, 0x5F, 0x6D, ++0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x3D, 0x25, 0x69, 0x20, 0x72, ++0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x6E, 0x6F, 0x5F, 0x73, 0x61, 0x6D, 0x70, 0x6C, ++0x65, 0x73, 0x3D, 0x25, 0x69, 0x0A, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x20, 0x7C, 0x9F, 0x00, ++0x20, 0xF3, 0xA0, 0x00, 0xA0, 0x17, 0x52, 0x00, 0xA0, 0x8E, 0x53, 0x00, 0xF8, 0x52, 0x23, 0x00, 0xF8, 0xC9, 0x24, 0x00, ++0x18, 0xF5, 0x15, 0x00, 0x18, 0x6C, 0x17, 0x00, 0xF9, 0x06, 0x11, 0x00, 0x62, 0x07, 0x12, 0x00, 0x35, 0x08, 0x14, 0x00, ++0xD1, 0x10, 0x04, 0x00, 0x0A, 0x4E, 0x04, 0x00, 0x7D, 0xC8, 0x04, 0x00, 0x7D, 0x83, 0x08, 0x00, 0xB1, 0x03, 0x09, 0x00, ++0x1A, 0x04, 0x0A, 0x00, 0x68, 0x08, 0x02, 0x00, 0x05, 0x27, 0x02, 0x00, 0x3F, 0x64, 0x02, 0x00, 0xFE, 0xAC, 0x05, 0x00, ++0x76, 0x02, 0x06, 0x00, 0x67, 0xAD, 0x06, 0x00, 0xF0, 0x5A, 0x01, 0x00, 0x59, 0x6F, 0x01, 0x00, 0x2A, 0x98, 0x01, 0x00, ++0xBE, 0x41, 0x04, 0x00, 0xD9, 0x81, 0x04, 0x00, 0x0D, 0x02, 0x05, 0x00, 0x34, 0x04, 0x01, 0x00, 0x83, 0x13, 0x01, 0x00, ++0x1F, 0x32, 0x01, 0x00, 0x7F, 0xD6, 0x02, 0x00, 0x3B, 0x01, 0x03, 0x00, 0xB3, 0x56, 0x03, 0x00, 0x78, 0xAD, 0x00, 0x00, ++0xAC, 0xB7, 0x00, 0x00, 0x15, 0xCC, 0x00, 0x00, 0xDF, 0x20, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, 0x07, 0x81, 0x02, 0x00, ++0x1A, 0x82, 0x00, 0x00, 0xC1, 0x89, 0x00, 0x00, 0x10, 0x99, 0x00, 0x00, 0x55, 0xE4, 0x01, 0x00, 0xD2, 0x00, 0x02, 0x00, ++0xCD, 0x39, 0x02, 0x00, 0xA5, 0x73, 0x00, 0x00, 0x73, 0x7A, 0x00, 0x00, 0x0E, 0x88, 0x00, 0x00, 0xE6, 0xB3, 0x01, 0x00, ++0x8A, 0xCD, 0x01, 0x00, 0xD2, 0x00, 0x02, 0x00, 0x15, 0x68, 0x00, 0x00, 0x34, 0x6E, 0x00, 0x00, 0x73, 0x7A, 0x00, 0x00, ++0x3F, 0x6B, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0x5A, 0xAB, 0x01, 0x00, 0xBC, 0x56, 0x00, 0x00, 0xD6, 0x5B, 0x00, 0x00, ++0x0A, 0x66, 0x00, 0x00, 0xEC, 0x46, 0x01, 0x00, 0x27, 0x5A, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0x11, 0x4E, 0x00, 0x00, ++0xA8, 0x52, 0x00, 0x00, 0xD7, 0x5B, 0x00, 0x00, 0x99, 0x22, 0x01, 0x00, 0xB1, 0x33, 0x01, 0x00, 0xE1, 0x55, 0x01, 0x00, ++0x63, 0x45, 0x00, 0x00, 0x78, 0x49, 0x00, 0x00, 0xA2, 0x51, 0x00, 0x00, 0x8A, 0x05, 0x01, 0x00, 0xEC, 0x14, 0x01, 0x00, ++0xB1, 0x33, 0x01, 0x00, 0x74, 0x3E, 0x00, 0x00, 0x21, 0x42, 0x00, 0x00, 0x7A, 0x49, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, ++0x3C, 0x5C, 0x29, 0x00, 0xB4, 0xF4, 0x2D, 0x00, 0x00, 0x88, 0x13, 0x00, 0x1E, 0xAE, 0x14, 0x00, 0x5A, 0xFA, 0x16, 0x00, ++0x55, 0x05, 0x0D, 0x00, 0x69, 0xC9, 0x0D, 0x00, 0x91, 0x51, 0x0F, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x0F, 0x57, 0x0A, 0x00, ++0x2D, 0x7D, 0x0B, 0x00, 0xAA, 0x82, 0x06, 0x00, 0xB4, 0xE4, 0x06, 0x00, 0xC8, 0xA8, 0x07, 0x00, 0x00, 0xE2, 0x04, 0x00, ++0x87, 0x2B, 0x05, 0x00, 0x96, 0xBE, 0x05, 0x00, 0x1C, 0x57, 0x04, 0x00, 0x78, 0x98, 0x04, 0x00, 0x30, 0x1B, 0x05, 0x00, ++0x00, 0xE8, 0x03, 0x00, 0xD2, 0x22, 0x04, 0x00, 0x78, 0x98, 0x04, 0x00, 0x55, 0x41, 0x03, 0x00, 0x5A, 0x72, 0x03, 0x00, ++0x64, 0xD4, 0x03, 0x00, 0x00, 0xEE, 0x02, 0x00, 0x1E, 0x1A, 0x03, 0x00, 0x5A, 0x72, 0x03, 0x00, 0xAA, 0x9A, 0x02, 0x00, ++0xE1, 0xC1, 0x02, 0x00, 0x50, 0x10, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x4B, 0x7B, 0x02, 0x00, 0xE1, 0xC1, 0x02, 0x00, ++0x00, 0x04, 0xA6, 0x00, 0x00, 0xC8, 0xAF, 0x00, 0x00, 0x50, 0xC3, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0xE4, 0x57, 0x00, ++0x00, 0xA8, 0x61, 0x00, 0xAA, 0x56, 0x37, 0x00, 0x00, 0x98, 0x3A, 0x00, 0xAA, 0x1A, 0x41, 0x00, 0x00, 0x81, 0x29, 0x00, ++0x00, 0xF2, 0x2B, 0x00, 0x00, 0xD4, 0x30, 0x00, 0x55, 0xAB, 0x1B, 0x00, 0x00, 0x4C, 0x1D, 0x00, 0x55, 0x8D, 0x20, 0x00, ++0x80, 0xC0, 0x14, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x38, 0x72, 0x12, 0x00, 0x00, 0x88, 0x13, 0x00, ++0x8E, 0xB3, 0x15, 0x00, 0x00, 0x9A, 0x10, 0x00, 0x00, 0x94, 0x11, 0x00, 0x00, 0x88, 0x13, 0x00, 0xAA, 0xD5, 0x0D, 0x00, ++0x00, 0xA6, 0x0E, 0x00, 0xAA, 0x46, 0x10, 0x00, 0x80, 0x73, 0x0C, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, 0xA6, 0x0E, 0x00, ++0x55, 0x11, 0x0B, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x55, 0x05, 0x0D, 0x00, 0x00, 0xF6, 0x09, 0x00, 0x00, 0x8C, 0x0A, 0x00, ++0x00, 0xB8, 0x0B, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, 0xA8, 0x61, 0x00, 0x00, 0x81, 0x29, 0x00, ++0x00, 0xF2, 0x2B, 0x00, 0x00, 0xD4, 0x30, 0x00, 0x55, 0xAB, 0x1B, 0x00, 0x00, 0x4C, 0x1D, 0x00, 0x55, 0x8D, 0x20, 0x00, ++0x80, 0xC0, 0x14, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x6A, 0x18, 0x00, 0xAA, 0xD5, 0x0D, 0x00, 0x00, 0xA6, 0x0E, 0x00, ++0xAA, 0x46, 0x10, 0x00, 0x40, 0x60, 0x0A, 0x00, 0x80, 0xFC, 0x0A, 0x00, 0x00, 0x35, 0x0C, 0x00, 0x1C, 0x39, 0x09, 0x00, ++0x00, 0xC4, 0x09, 0x00, 0xC7, 0xD9, 0x0A, 0x00, 0x00, 0x4D, 0x08, 0x00, 0x00, 0xCA, 0x08, 0x00, 0x00, 0xC4, 0x09, 0x00, ++0xD5, 0xEA, 0x06, 0x00, 0x00, 0x53, 0x07, 0x00, 0x55, 0x23, 0x08, 0x00, 0xC0, 0x39, 0x06, 0x00, 0x80, 0x97, 0x06, 0x00, ++0x00, 0x53, 0x07, 0x00, 0xAA, 0x88, 0x05, 0x00, 0x00, 0xDC, 0x05, 0x00, 0xAA, 0x82, 0x06, 0x00, 0x00, 0xFB, 0x04, 0x00, ++0x00, 0x46, 0x05, 0x00, 0x00, 0xDC, 0x05, 0x00, 0x3B, 0x89, 0x16, 0x00, 0x4F, 0x48, 0x14, 0x00, 0xC7, 0xD9, 0x0A, 0x00, ++0x00, 0xC4, 0x09, 0x00, 0x0D, 0x02, 0x05, 0x00, 0xD9, 0x81, 0x04, 0x00, 0x07, 0x81, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, ++0x9E, 0x44, 0x0B, 0x00, 0x27, 0x24, 0x0A, 0x00, 0xE4, 0x6C, 0x05, 0x00, 0x00, 0xE2, 0x04, 0x00, 0x07, 0x81, 0x02, 0x00, ++0xEC, 0x40, 0x02, 0x00, 0x83, 0x40, 0x01, 0x00, 0x76, 0x20, 0x01, 0x00, 0x14, 0x83, 0x07, 0x00, 0xC5, 0xC2, 0x06, 0x00, ++0xED, 0x9D, 0x03, 0x00, 0x55, 0x41, 0x03, 0x00, 0x5A, 0xAB, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0xAD, 0xD5, 0x00, 0x00, ++0x4F, 0xC0, 0x00, 0x00, 0x4F, 0xA2, 0x05, 0x00, 0x14, 0x12, 0x05, 0x00, 0x72, 0xB6, 0x02, 0x00, 0x00, 0x71, 0x02, 0x00, ++0x83, 0x40, 0x01, 0x00, 0x76, 0x20, 0x01, 0x00, 0x42, 0xA0, 0x00, 0x00, 0x3B, 0x90, 0x00, 0x00, 0x8A, 0xC1, 0x03, 0x00, ++0x62, 0x61, 0x03, 0x00, 0xF7, 0xCE, 0x01, 0x00, 0xAB, 0xA0, 0x01, 0x00, 0xAD, 0xD5, 0x00, 0x00, 0x4F, 0xC0, 0x00, 0x00, ++0xD6, 0x6A, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x27, 0xD1, 0x02, 0x00, 0x0A, 0x89, 0x02, 0x00, 0x39, 0x5B, 0x01, 0x00, ++0x80, 0x38, 0x01, 0x00, 0x42, 0xA0, 0x00, 0x00, 0x3B, 0x90, 0x00, 0x00, 0x21, 0x50, 0x00, 0x00, 0x1E, 0x48, 0x00, 0x00, ++0x07, 0x81, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, 0xA4, 0x34, 0x01, 0x00, 0xC7, 0x15, 0x01, 0x00, 0x73, 0x8E, 0x00, 0x00, ++0x35, 0x80, 0x00, 0x00, 0x3A, 0x47, 0x00, 0x00, 0x1A, 0x40, 0x00, 0x00, 0xEC, 0x40, 0x02, 0x00, 0x3B, 0x07, 0x02, 0x00, ++0xC7, 0x15, 0x01, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x35, 0x80, 0x00, 0x00, 0x62, 0x73, 0x00, 0x00, 0x1A, 0x40, 0x00, 0x00, ++0xB1, 0x39, 0x00, 0x00, 0xC5, 0xE0, 0x01, 0x00, 0xB1, 0xB0, 0x01, 0x00, 0x7B, 0xE7, 0x00, 0x00, 0x55, 0xD0, 0x00, 0x00, ++0xD6, 0x6A, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x6B, 0x35, 0x00, 0x00, 0x14, 0x30, 0x00, 0x00, 0xB1, 0xB0, 0x01, 0x00, ++0x6C, 0x85, 0x01, 0x00, 0x55, 0xD0, 0x00, 0x00, 0x80, 0xBB, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x8A, 0x56, 0x00, 0x00, ++0x14, 0x30, 0x00, 0x00, 0x45, 0x2B, 0x00, 0x00, 0x00, 0x6A, 0x18, 0x00, 0xE0, 0x4B, 0x10, 0x00, 0x00, 0x35, 0x0C, 0x00, ++0xC0, 0x2D, 0x08, 0x00, 0x80, 0x1A, 0x06, 0x00, 0xE0, 0x16, 0x04, 0x00, 0x40, 0x0D, 0x03, 0x00, 0x20, 0xBF, 0x02, 0x00, ++0x24, 0xCE, 0x15, 0x00, 0xB4, 0xCE, 0x15, 0x00, 0x94, 0xCD, 0x15, 0x00, 0xB8, 0xD0, 0x15, 0x00, 0x03, 0x00, 0x00, 0x00, ++0x00, 0x28, 0x00, 0x00, 0x39, 0x4B, 0x15, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x15, 0x4C, 0x15, 0x00, 0x01, 0x10, 0x00, 0x00, ++0xD5, 0x4B, 0x15, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x20, 0x3E, 0x3D, 0x20, 0x42, 0x43, 0x4E, 0x5F, 0x46, 0x49, 0x58, ++0x45, 0x44, 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x5F, 0x46, 0x49, 0x45, 0x4C, 0x44, 0x53, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, ++0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x62, 0x75, 0x66, 0x5F, 0x6C, 0x65, ++0x6E, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x73, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3E, 0x20, 0x30, 0x00, ++0x21, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x5F, 0x6D, 0x6F, 0x72, 0x65, 0x5F, 0x6D, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x5F, ++0x74, 0x6F, 0x5F, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x28, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x65, 0x71, 0x75, ++0x65, 0x73, 0x74, 0x2D, 0x3E, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x73, 0x65, 0x6E, 0x74, 0x20, 0x3D, 0x3D, 0x20, ++0x30, 0x29, 0x00, 0x00, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x6E, ++0x74, 0x20, 0x3C, 0x3D, 0x20, 0x43, 0x4F, 0x5F, 0x41, 0x52, 0x52, 0x41, 0x59, 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x28, 0x72, ++0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x29, 0x00, 0x00, ++0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, ++0x5F, 0x4D, 0x45, 0x41, 0x53, 0x5F, 0x52, 0x45, 0x51, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x45, 0x41, 0x43, 0x4F, ++0x4E, 0x00, 0x00, 0x00, 0x72, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x72, 0x65, ++0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x3E, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x64, 0x69, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, ++0x33, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x34, 0x37, 0x3A, 0x31, 0x34, 0x20, 0x2D, 0x20, 0x67, 0x37, ++0x34, 0x32, 0x30, 0x33, 0x31, 0x37, 0x31, 0x00, 0x76, 0x36, 0x2E, 0x34, 0x2E, 0x33, 0x2E, 0x31, 0x00, 0x00, 0x00, 0x00, ++0xF8, 0xB5, 0x00, 0xBF, 0xF8, 0xBC, 0x08, 0xBC, 0x9E, 0x46, 0x70, 0x47, 0xF8, 0xB5, 0x00, 0xBF, 0xF8, 0xBC, 0x08, 0xBC, ++0x9E, 0x46, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x74, 0x04, 0x17, 0x00, 0xDC, 0x04, 0x17, 0x00, 0x44, 0x05, 0x17, 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, 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, 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, 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, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x33, 0xCD, 0xAB, ++0x34, 0x12, 0x6D, 0xE6, 0xEC, 0xDE, 0x05, 0x00, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0E, 0x00, 0x00, 0x04, 0x0E, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x5B, ++0x4B, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x32, 0x7B, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, ++0x26, 0x00, 0x00, 0xF8, 0x11, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x19, 0x48, 0x20, 0x00, 0x00, 0x9C, 0x91, 0x01, 0x00, 0x08, ++0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x44, 0x10, 0x08, 0x00, 0x80, 0x01, 0x38, 0x41, 0x46, 0x00, 0x0C, ++0x14, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x3C, 0x1A, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x38, 0x01, 0x00, 0x00, 0x40, 0x1D, 0x00, 0x00, 0x08, ++0x8E, 0x00, 0x08, 0x38, 0x50, 0x00, 0x00, 0x14, 0x20, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x00, 0x40, 0x7B, 0x00, 0x00, 0xA4, ++0x01, 0x01, 0x00, 0x00, 0x9F, 0x33, 0x00, 0x30, 0x00, 0x07, 0x00, 0x41, 0x20, 0x44, 0x10, 0x04, 0x00, 0x00, 0x00, 0x90, ++0x00, 0x00, 0x00, 0x49, 0x2F, 0x84, 0x0E, 0xF0, 0x2C, 0x84, 0x0E, 0xEC, 0x2C, 0x84, 0x0E, 0xEC, 0x32, 0x00, 0x00, 0x04, ++0x00, 0x00, 0x00, 0x30, 0x01, 0x01, 0x00, 0x48, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x02, 0x02, 0x00, 0x48, ++0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x46, 0x11, 0x00, 0x00, 0x04, 0x06, 0x00, 0x01, 0x58, ++0x72, 0x04, 0x04, 0x3D, 0x39, 0x44, 0x20, 0xDC, 0xD2, 0xD4, 0x1D, 0x08, 0x06, 0x00, 0x0A, 0x48, 0xDC, 0x44, 0x20, 0xDC, ++0x3C, 0xD4, 0x1D, 0x08, 0x04, 0x00, 0x05, 0x38, 0xC3, 0xF1, 0xF1, 0x0E, 0xDC, 0x44, 0x20, 0x34, 0x00, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, 0x45, 0x44, 0x10, 0x04, ++0x00, 0x80, 0x00, 0x38, 0x9C, 0x10, 0x00, 0x22, 0x48, 0x44, 0x10, 0x08, 0x00, 0x80, 0x00, 0x38, 0x9C, 0x50, 0xD4, 0x23, ++0x17, 0x44, 0x10, 0x08, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x00, 0x00, 0x32, 0x63, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x14, ++0x51, 0x00, 0x00, 0x1C, 0x57, 0x00, 0x00, 0x10, 0x00, 0x80, 0x02, 0x38, 0x01, 0x00, 0x00, 0x0C, 0x66, 0x44, 0xD0, 0x08, ++0x0F, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x38, 0x01, 0x26, 0x00, 0x0C, ++0x5A, 0x44, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x30, 0x30, 0x02, 0x02, 0x3D, 0x5D, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, ++0x00, 0x01, 0x00, 0x3E, 0x66, 0x00, 0x00, 0x04, 0x00, 0x80, 0x02, 0x38, 0x01, 0x16, 0x00, 0x0C, 0x66, 0x44, 0x20, 0x34, ++0x00, 0x80, 0x02, 0x38, 0x01, 0x0A, 0x00, 0x0C, 0x66, 0x44, 0x20, 0x34, 0x04, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, ++0x7B, 0x00, 0x00, 0x08, 0x2F, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0x26, 0x6C, 0x00, 0x00, 0x08, 0xAF, 0x04, 0x04, 0x38, ++0x10, 0x10, 0x19, 0x1F, 0x6F, 0x00, 0x00, 0x08, 0xAF, 0x0C, 0x00, 0x20, 0x71, 0x00, 0x00, 0x04, 0xAF, 0x0C, 0x00, 0x60, ++0x79, 0x00, 0x70, 0x18, 0x77, 0x00, 0x00, 0x14, 0x75, 0x00, 0x00, 0x10, 0xAF, 0x0C, 0x14, 0x28, 0x84, 0x00, 0xB0, 0x09, ++0xAF, 0x0C, 0x0A, 0x28, 0x84, 0x00, 0xB0, 0x09, 0xAF, 0x0C, 0x06, 0x28, 0x84, 0x00, 0xB0, 0x09, 0x86, 0x80, 0x04, 0x28, ++0x7D, 0x00, 0x00, 0x08, 0x86, 0x00, 0x00, 0x38, 0x00, 0x00, 0x80, 0x22, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, ++0x01, 0xF1, 0xF1, 0x0E, 0x83, 0x48, 0x00, 0x36, 0x00, 0x00, 0x02, 0x28, 0x85, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x02, 0x38, ++0x31, 0x04, 0x04, 0x3D, 0x88, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x05, 0x38, 0x21, 0x18, 0x24, 0x1F, 0x8B, 0x00, 0x00, 0x08, ++0x8E, 0x00, 0x00, 0x30, 0x21, 0x30, 0x16, 0xA0, 0x8E, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x12, 0x00, 0xF1, 0x0E, ++0x91, 0x00, 0x00, 0x34, 0xCC, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x50, 0x94, 0x00, 0x00, 0x04, 0xFE, 0x95, 0x00, 0x38, ++0x00, 0x00, 0x01, 0x32, 0x97, 0x00, 0x00, 0x04, 0xFE, 0x1F, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5A, 0x9B, 0x98, 0xC9, 0x6D, ++0xB9, 0xD4, 0x19, 0xFC, 0x86, 0x01, 0x00, 0x30, 0x73, 0x03, 0x84, 0x3D, 0x9E, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x0A, 0xA1, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x00, 0xC0, 0x22, 0xA4, 0x00, 0x00, 0x04, ++0x8E, 0x02, 0x00, 0x90, 0x01, 0x00, 0x01, 0x32, 0xAA, 0x00, 0x40, 0x8E, 0xB0, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x30, 0x01, 0x00, 0x01, 0x32, 0xCB, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x01, 0x32, 0xB3, 0x00, 0x00, 0x04, ++0xB6, 0x19, 0x00, 0x30, 0x31, 0x04, 0x04, 0x3D, 0xB6, 0x00, 0x00, 0x04, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x80, 0x22, ++0x97, 0x00, 0x00, 0x04, 0x86, 0x01, 0x00, 0x30, 0x73, 0x04, 0x84, 0x3D, 0xBC, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x03, 0x29, 0xBF, 0x00, 0x00, 0x04, 0x8E, 0x02, 0xEE, 0x9A, 0x00, 0x01, 0x01, 0x32, 0xC5, 0x00, 0x00, 0x7C, ++0xB0, 0x00, 0x00, 0xCC, 0xB0, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x01, 0x01, 0x32, ++0xC8, 0x00, 0x00, 0x04, 0x8E, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x8E, 0x03, 0x00, 0x50, ++0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x35, 0x00, 0x00, 0xC0, 0x06, 0x00, 0x01, 0x38, 0x72, 0x04, 0x04, 0x3D, ++0xD2, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x30, 0x41, 0xF1, 0xF1, 0x0E, 0xD5, 0x00, 0x00, 0x34, 0x04, 0x00, 0x04, 0x28, ++0xD7, 0x00, 0x00, 0x08, 0x0E, 0x00, 0x08, 0x28, 0xD9, 0x00, 0x00, 0x08, 0x8E, 0x01, 0x00, 0x30, 0x52, 0x00, 0xF1, 0x0E, ++0xDC, 0x00, 0x00, 0x34, 0x8E, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x00, 0x00, 0x02, 0x38, ++0x00, 0x00, 0x00, 0x32, 0xE2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x60, 0xE6, 0x00, 0x00, 0xD8, 0xE9, 0x00, 0x00, 0xD4, ++0xEC, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x21, 0xF1, 0xF1, 0x0E, 0xEF, 0x48, 0x00, 0x36, 0x00, 0x00, 0x00, 0x30, ++0x21, 0x24, 0x00, 0x0C, 0xEF, 0x48, 0x00, 0x36, 0x00, 0x00, 0x00, 0x30, 0x21, 0x00, 0x00, 0x0C, 0xEF, 0x48, 0x00, 0x36, ++0x00, 0x00, 0x02, 0x28, 0x7B, 0x00, 0x00, 0x08, 0xFE, 0x1E, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5A, 0xF5, 0x98, 0xC9, 0x6D, ++0xF8, 0xD4, 0x19, 0xFC, 0x8E, 0x02, 0x00, 0x30, 0x40, 0x00, 0x00, 0x32, 0xFB, 0x00, 0x00, 0x04, 0x8E, 0x02, 0xEE, 0x3A, ++0x80, 0x00, 0x00, 0x32, 0xFB, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x01, 0xF1, 0xF1, 0x0E, 0xFE, 0x48, 0x00, 0x36, ++0x00, 0x00, 0x02, 0x28, 0x00, 0x01, 0x00, 0x08, 0x8E, 0x00, 0x02, 0x38, 0x31, 0x04, 0x04, 0x3D, 0x03, 0x01, 0x00, 0x08, ++0x8E, 0x00, 0x05, 0x38, 0x21, 0x18, 0x24, 0x1F, 0x06, 0x01, 0x00, 0x08, 0x8E, 0x00, 0x00, 0x30, 0x21, 0x30, 0x16, 0xA0, ++0x09, 0x01, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x12, 0x00, 0xF1, 0x0E, 0x0C, 0x01, 0x00, 0x34, 0xF6, 0x14, 0x00, 0x30, ++0x00, 0x00, 0x01, 0x32, 0x14, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x11, 0x01, 0x00, 0x04, 0xEC, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x50, 0xF1, 0x00, 0x00, 0x04, 0xF6, 0x14, 0x00, 0x30, 0x00, 0x00, 0x03, 0x32, 0x17, 0x01, 0x00, 0x04, ++0x86, 0x10, 0x00, 0x30, 0x73, 0x04, 0x84, 0x3D, 0x1A, 0x01, 0x00, 0x04, 0x8E, 0x10, 0x00, 0x50, 0x00, 0x00, 0xC0, 0x22, ++0xCB, 0xC0, 0x47, 0x8E, 0x1E, 0x01, 0x30, 0xCB, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x04, 0x32, 0x21, 0x01, 0x00, 0x04, ++0xB6, 0x19, 0x00, 0x30, 0x31, 0x04, 0x04, 0x3D, 0x24, 0x01, 0x00, 0x04, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x80, 0x22, ++0x11, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, 0x30, ++0x73, 0x04, 0x84, 0x3D, 0x2D, 0x01, 0x00, 0x04, 0x8E, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, ++0x31, 0x01, 0x00, 0xC0, 0x0E, 0x80, 0x0C, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x34, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x30, ++0x03, 0xF1, 0xF1, 0x0F, 0x37, 0x01, 0x00, 0x34, 0x00, 0x00, 0x02, 0x28, 0x39, 0x01, 0x00, 0x08, 0x8E, 0x03, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x06, 0x00, 0x01, 0x58, 0x72, 0x04, 0x04, 0x3D, 0x43, 0x45, 0x20, 0xDC, 0xD2, 0xD4, 0x1D, 0x08, 0x06, 0x00, 0x0A, 0x48, ++0xDC, 0x44, 0x20, 0xDC, 0x46, 0xD5, 0x1D, 0x08, 0x04, 0x00, 0x05, 0x38, 0x41, 0xF1, 0xF1, 0x0E, 0xDC, 0x44, 0x20, 0x34, ++0x0E, 0x80, 0x02, 0x28, 0xDC, 0x00, 0x00, 0x08, 0x35, 0x00, 0x00, 0x48, 0x4A, 0x01, 0x00, 0x04, 0x8F, 0x63, 0x96, 0x78, ++0x0F, 0x00, 0x00, 0x41, 0x4F, 0x01, 0x00, 0x8C, 0xC4, 0x50, 0x04, 0x08, 0x74, 0x45, 0x10, 0x90, 0x0F, 0x62, 0xC8, 0x88, ++0x5A, 0x01, 0x00, 0xC0, 0x74, 0x45, 0x10, 0x90, 0x54, 0x45, 0x10, 0x08, 0x57, 0x45, 0x10, 0x94, 0x8F, 0x62, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x29, 0x7A, 0x51, 0x04, 0x94, 0x8F, 0x63, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x7A, 0x45, 0x10, 0x04, ++0x05, 0xE0, 0x00, 0x38, 0x31, 0x01, 0x01, 0x3D, 0x5D, 0x45, 0x10, 0x08, 0x0F, 0x60, 0x32, 0xA8, 0x74, 0x45, 0x10, 0x90, ++0x54, 0x01, 0x00, 0x08, 0x57, 0x45, 0x10, 0x94, 0x67, 0x45, 0x10, 0xC6, 0x63, 0x55, 0x18, 0xC4, 0x0F, 0xE0, 0x02, 0x58, ++0x07, 0xEA, 0xEE, 0x0F, 0x74, 0x01, 0x00, 0x80, 0x6B, 0x45, 0x20, 0x34, 0x0F, 0xE0, 0x02, 0x58, 0x07, 0xEA, 0xEE, 0x0E, ++0x74, 0x01, 0x00, 0x80, 0x6B, 0x45, 0x20, 0x34, 0x00, 0x40, 0x00, 0x30, 0x01, 0x00, 0x00, 0x33, 0x6E, 0x01, 0x00, 0x04, ++0x05, 0x40, 0x03, 0x38, 0x73, 0x03, 0x03, 0x3D, 0x71, 0x01, 0x00, 0x08, 0x07, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, ++0x74, 0x01, 0x00, 0x04, 0x8F, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x77, 0x51, 0x04, 0x94, 0x8F, 0x60, 0x00, 0x40, ++0x7D, 0x45, 0x10, 0xA0, 0x7A, 0x45, 0x10, 0x04, 0x8F, 0x60, 0x00, 0x30, 0x01, 0x01, 0x00, 0x64, 0x11, 0x44, 0x10, 0x04, ++0x8F, 0x60, 0x00, 0x30, 0x01, 0x01, 0x00, 0x64, 0x80, 0x45, 0x10, 0x04, 0x8F, 0x61, 0x00, 0x30, 0x01, 0x00, 0x00, 0x42, ++0x83, 0x01, 0x00, 0x04, 0x00, 0x80, 0x02, 0x38, 0x00, 0x00, 0x00, 0x32, 0x86, 0x45, 0x10, 0x08, 0x8F, 0x61, 0x0A, 0x28, ++0x88, 0x01, 0x00, 0x08, 0x8F, 0x61, 0x0A, 0x48, 0x8B, 0x01, 0x00, 0xBC, 0x8E, 0x01, 0x00, 0x08, 0x8F, 0x61, 0x00, 0x30, ++0x01, 0x00, 0x00, 0x34, 0x05, 0x00, 0x00, 0x04, 0x8F, 0x61, 0x00, 0x30, 0x00, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00, 0x04, ++0x8F, 0x00, 0x00, 0x30, 0x0F, 0xED, 0xEA, 0x0E, 0x94, 0x01, 0x00, 0x36, 0x00, 0x80, 0x03, 0x38, 0x00, 0x00, 0x00, 0x34, ++0x97, 0x01, 0x00, 0x08, 0x05, 0x80, 0x02, 0x38, 0x02, 0x00, 0x01, 0x29, 0x9A, 0x01, 0x00, 0x08, 0x8F, 0x02, 0x00, 0x30, ++0x9C, 0x20, 0x00, 0x22, 0x9D, 0x01, 0x00, 0x04, 0x8F, 0x02, 0x00, 0x30, 0x9C, 0x50, 0xD4, 0x23, 0xA0, 0x01, 0x00, 0x04, ++0x8F, 0x02, 0x14, 0x28, 0xA2, 0x01, 0x00, 0x08, 0x8F, 0x02, 0x00, 0x30, 0x01, 0x02, 0x01, 0x43, 0xA5, 0x01, 0x00, 0x04, ++0x8F, 0x12, 0x00, 0x30, 0x00, 0x01, 0x00, 0x32, 0xA8, 0x01, 0x00, 0x04, 0x8F, 0x13, 0xEE, 0x5A, 0x0F, 0x00, 0x00, 0x41, ++0xAC, 0x01, 0x00, 0x7C, 0xF9, 0x00, 0x00, 0x08, 0x8F, 0x13, 0x2C, 0x59, 0x00, 0x00, 0x00, 0x29, 0xB0, 0x01, 0x00, 0x8C, ++0xF9, 0x00, 0x00, 0x08, 0x8F, 0x13, 0x00, 0x20, 0x11, 0x50, 0x04, 0x94, 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, 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, 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, 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, ++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, 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, 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, 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, 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, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x76, 0x76, 0x00, 0x70, 0xF8, 0xF8, 0x1D, ++0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x72, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xF8, 0x1D, ++0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x7B, 0x76, 0x76, 0x00, 0x70, 0xF8, 0xF8, 0x1D, ++0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x85, 0x7E, 0x7E, 0x00, 0x76, 0xF8, 0xF4, 0x1D, ++0x76, 0xF8, 0xF4, 0x1D, 0x76, 0xF8, 0xF4, 0x1D, 0x76, 0xF8, 0xF8, 0x1D, 0x8A, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x8D, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x8A, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7C, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x40, 0x7E, 0x7E, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x92, 0x8B, 0x8B, 0x00, 0x87, 0xF8, 0xF8, 0x1D, ++0x89, 0xF8, 0xF8, 0x1D, 0x87, 0xF8, 0xF8, 0x1D, 0x87, 0xF8, 0xF8, 0x1D, 0x55, 0x51, 0x51, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x89, 0xF8, 0xF8, 0x1D, 0x89, 0xF8, 0xF8, 0x1D, 0x54, 0x51, 0x51, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x88, 0xF8, 0xF8, 0x1D, 0x88, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4E, 0x4E, 0x00, 0x49, 0xF8, 0xF8, 0x1D, ++0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x52, 0x4D, 0x4D, 0x00, 0x47, 0xF8, 0xF8, 0x1D, ++0x47, 0xF8, 0xF8, 0x1D, 0x47, 0xF8, 0xF8, 0x1D, 0x47, 0xF8, 0xF8, 0x1D, 0x55, 0x4F, 0x4F, 0x00, 0x4B, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4E, 0x4E, 0x00, 0x49, 0xF8, 0xF8, 0x1D, ++0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x4D, 0x49, 0x49, 0x00, 0x44, 0xF8, 0xF8, 0x1D, ++0x44, 0xF8, 0xF8, 0x1D, 0x44, 0xF8, 0xF8, 0x1D, 0x44, 0xF8, 0xF8, 0x1D, 0x8F, 0x51, 0x51, 0x00, 0x49, 0xF8, 0xF8, 0x1D, ++0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x77, 0x42, 0x42, 0x00, 0x3F, 0xF8, 0xF8, 0x1D, ++0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x75, 0x42, 0x42, 0x00, 0x9E, 0xF8, 0xF8, 0x1D, ++0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x5C, 0x55, 0x55, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x5C, 0x53, 0x53, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4B, 0xF8, 0xF8, 0x1D, 0x4B, 0xF8, 0xF8, 0x1D, 0x4B, 0xF8, 0xF8, 0x1D, 0x9E, 0xF8, 0xF8, 0x00, 0x8C, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x40, 0x89, 0x89, 0x00, 0x46, 0xF8, 0xF8, 0x18, ++0x45, 0xF8, 0xCF, 0x18, 0x44, 0xF8, 0xCF, 0x18, 0x44, 0xF8, 0xCF, 0x18, 0x5F, 0x56, 0x56, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, ++0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x5E, 0x55, 0x55, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x5F, 0x56, 0x56, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, ++0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x61, 0x55, 0x55, 0x00, 0x50, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x5F, 0x53, 0x53, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x5F, 0x55, 0x55, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0xAA, 0x55, 0x55, 0x00, 0x54, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0xA6, 0x59, 0x59, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x9B, 0x4F, 0x4F, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, ++0x46, 0xF8, 0xF8, 0x1D, 0x46, 0xF8, 0xF8, 0x1D, 0x46, 0xF8, 0xF8, 0x1D, 0xA5, 0xF8, 0xF8, 0x00, 0x94, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0xA4, 0x98, 0x98, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x86, 0x46, 0x46, 0x00, 0xB3, 0xF8, 0xF8, 0x1D, ++0x3D, 0xF8, 0xF8, 0x1D, 0x3D, 0xF8, 0xF8, 0x1D, 0x3D, 0xF8, 0xF8, 0x1D, 0x40, 0x8E, 0x8E, 0x00, 0x48, 0xF8, 0xF8, 0x1A, ++0x48, 0xF8, 0xDF, 0x1A, 0x46, 0xF8, 0xDF, 0x1A, 0x46, 0xF8, 0xDF, 0x1A, 0x40, 0x7F, 0x7F, 0x00, 0x75, 0xD2, 0xD2, 0x18, ++0x3A, 0xD2, 0xD2, 0x18, 0x3A, 0xD2, 0xD2, 0x18, 0x39, 0xD2, 0xD2, 0x18, 0x40, 0x45, 0x45, 0x00, 0x64, 0x86, 0x86, 0x0F, ++0x3E, 0x86, 0x86, 0x0F, 0x3D, 0x86, 0x86, 0x0F, 0x3D, 0x86, 0x86, 0x0F, 0x64, 0x5C, 0x5C, 0x00, 0x56, 0xF8, 0xF8, 0x1D, ++0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x68, 0x5B, 0x5B, 0x00, 0x58, 0xF8, 0xF8, 0x1D, ++0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x64, 0x5A, 0x5A, 0x00, 0x55, 0xF8, 0xF8, 0x1D, ++0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0xB5, 0x5A, 0x5A, 0x00, 0x5B, 0xF8, 0xF8, 0x1D, ++0x55, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0xB0, 0xF8, 0xF8, 0x00, 0xA3, 0xF8, 0xF8, 0x1D, ++0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0xAE, 0xA4, 0xA4, 0x00, 0x54, 0xF8, 0xF8, 0x1D, ++0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x40, 0x9A, 0x9A, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, ++0x4D, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x40, 0x9C, 0x9C, 0x00, 0x95, 0xF8, 0xF8, 0x1D, ++0x49, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x40, 0x49, 0x49, 0x00, 0x6F, 0x97, 0x97, 0x11, ++0x42, 0x97, 0x97, 0x11, 0x41, 0x97, 0x97, 0x11, 0x41, 0x97, 0x97, 0x11, 0x74, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xF8, 0x1D, ++0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x40, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xDE, 0x1A, ++0x69, 0xF8, 0xDE, 0x1A, 0x69, 0xF8, 0xDE, 0x1A, 0x69, 0xF8, 0xDE, 0x1A, 0x40, 0x75, 0x75, 0x00, 0x6E, 0xF8, 0x78, 0x0D, ++0x6E, 0xF8, 0x78, 0x0D, 0x6E, 0xF8, 0x78, 0x0D, 0x6E, 0xF8, 0x79, 0x0D, 0x85, 0x78, 0x78, 0x00, 0x73, 0xF8, 0xF8, 0x1D, ++0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x40, 0x78, 0x78, 0x00, 0x73, 0xF8, 0xF8, 0x1D, ++0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x40, 0x78, 0x78, 0x00, 0x73, 0xF8, 0x81, 0x0E, ++0x73, 0xF8, 0x81, 0x0E, 0x73, 0xF8, 0x81, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x40, 0x40, 0x40, 0x00, 0x73, 0xF8, 0x82, 0x0E, ++0x73, 0xF8, 0x82, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x40, 0x81, 0x81, 0x00, 0x7E, 0xF8, 0x92, 0x10, ++0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x40, 0x40, 0x40, 0x00, 0x7E, 0xF8, 0x92, 0x10, ++0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x40, 0x73, 0x73, 0x00, 0x6B, 0xB2, 0xB2, 0x14, ++0x35, 0xB2, 0xB2, 0x14, 0x35, 0xB2, 0xB2, 0x14, 0x35, 0xB2, 0xB2, 0x14, 0x40, 0x40, 0x40, 0x00, 0x60, 0x82, 0x82, 0x0E, ++0x3D, 0x82, 0x82, 0x0E, 0x3C, 0x82, 0x82, 0x0E, 0x3C, 0x82, 0x82, 0x0E, 0x40, 0x40, 0x40, 0x00, 0x66, 0x8B, 0x8B, 0x0F, ++0x3F, 0x8B, 0x8B, 0x0F, 0x3D, 0x8B, 0x8B, 0x0F, 0x3D, 0x8B, 0x8B, 0x0F, 0x40, 0x40, 0x40, 0x00, 0x3D, 0x68, 0x68, 0x0B, ++0x1E, 0x68, 0x68, 0x0B, 0x1E, 0x68, 0x68, 0x0B, 0x1E, 0x68, 0x68, 0x0B, 0x40, 0x22, 0x22, 0x00, 0x18, 0x43, 0x43, 0x06, ++0x29, 0x43, 0x43, 0x06, 0x18, 0x43, 0x43, 0x06, 0x18, 0x43, 0x43, 0x06, 0x40, 0x40, 0x40, 0x00, 0x72, 0x9D, 0x9D, 0x12, ++0x43, 0x9D, 0x9D, 0x12, 0x41, 0x9D, 0x9D, 0x12, 0x41, 0x9D, 0x9D, 0x12, 0x40, 0x40, 0x40, 0x00, 0x42, 0x75, 0x75, 0x0D, ++0x20, 0x75, 0x75, 0x0D, 0x20, 0x75, 0x75, 0x0D, 0x20, 0x75, 0x75, 0x0D, 0x40, 0x23, 0x23, 0x00, 0x19, 0x4C, 0x4C, 0x08, ++0x2C, 0x4C, 0x4C, 0x08, 0x19, 0x4C, 0x4C, 0x08, 0x19, 0x4C, 0x4C, 0x08, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, ++0xB8, 0xC8, 0xD8, 0xF8, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0x08, 0x58, 0x68, 0x78, 0x88, ++0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, 0x09, 0x01, 0x03, 0x1E, 0x00, 0x00, 0x75, 0x19, 0x03, 0x00, 0x75, 0x19, 0x03, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x04, 0x62, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, ++0x61, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x60, 0x23, 0x8D, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x60, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0xB4, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xE3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x84, 0x60, 0xC3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, ++0x60, 0xCB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xB3, 0x0C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0x1B, 0x0F, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xA2, 0x3E, 0x2A, 0x00, ++0xB5, 0x5A, 0x3F, 0x04, 0x60, 0x9B, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, ++0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3F, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0xD8, 0x3F, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, ++0x62, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x61, 0x03, 0x8D, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x60, 0x23, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x58, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x60, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0xB4, 0x2E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x44, 0x60, 0xE3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, ++0x60, 0xC3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x60, 0xCB, 0x0C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xB3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x2A, 0x00, ++0xB5, 0x5A, 0x2F, 0x44, 0x60, 0x1B, 0x0F, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xA2, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x04, ++0x60, 0x9B, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x58, 0x2F, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0xD8, 0x2F, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, ++0x6C, 0x00, 0x0F, 0x03, 0x60, 0xE7, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0x2F, 0x03, ++0x60, 0xD7, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0xEF, 0x03, 0x60, 0x9F, 0x0D, 0xE8, ++0x80, 0x80, 0x80, 0x80, 0x6D, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0xEF, 0x83, 0x60, 0x9F, 0x0D, 0xE8, 0x80, 0x80, 0x80, 0x80, ++0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, ++0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x2F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, ++0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x44, ++0x70, 0xE3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x63, 0x8C, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0x03, 0x11, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x43, 0x8D, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, ++0xB4, 0x00, 0x19, 0x44, 0x70, 0xE3, 0x10, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0xC4, ++0x70, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0xB4, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0xC3, 0x8C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x03, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0xEB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xB9, 0x00, ++0xB4, 0x00, 0x19, 0x84, 0x70, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x84, ++0x70, 0xF3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x84, 0x70, 0x3B, 0x0D, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0xB4, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x44, 0x70, 0xBB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0xEB, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0xAA, 0x00, ++0xB5, 0x5A, 0x39, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3F, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x04, ++0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0xE3, 0xAC, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x70, 0x63, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0x03, 0x11, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x84, 0x70, 0x43, 0x8D, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, ++0x70, 0xE3, 0x10, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x70, 0xE3, 0x0C, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0xB4, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0xC3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x46, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x70, 0x03, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0xB9, 0x00, ++0xB4, 0x00, 0x0F, 0x44, 0x70, 0xEB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x84, ++0x70, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x84, 0x70, 0xF3, 0x0C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x84, 0x70, 0x3B, 0x0D, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0xB4, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x70, 0xBB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x2E, 0xAA, 0x00, ++0xB5, 0x5A, 0x2F, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x2F, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x04, ++0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x2F, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x04, 0x70, 0xFB, 0x11, 0x0E, ++0x7F, 0xC1, 0x9F, 0x00, 0x0A, 0x01, 0x82, 0x00, 0x0C, 0x81, 0x82, 0x00, 0x10, 0x81, 0x82, 0x00, 0x10, 0x01, 0x83, 0x00, ++0x16, 0x01, 0x83, 0x00, 0x16, 0x01, 0x84, 0x00, 0x60, 0x01, 0x84, 0x00, 0x67, 0x01, 0x93, 0x00, 0x67, 0x41, 0x99, 0x00, ++0x7F, 0x41, 0x99, 0x00, 0x7F, 0xC1, 0x99, 0x00, 0x7F, 0x81, 0x9A, 0x00, 0x7F, 0x81, 0x9B, 0x00, 0x3F, 0xC1, 0x9C, 0x00, ++0x3F, 0xC1, 0x8F, 0x00, 0x08, 0x01, 0x82, 0x00, 0x0A, 0x01, 0x82, 0x00, 0x0C, 0x81, 0x82, 0x00, 0x10, 0x81, 0x82, 0x00, ++0x10, 0x01, 0x83, 0x00, 0x16, 0x01, 0x83, 0x00, 0x16, 0x01, 0x84, 0x00, 0x20, 0x01, 0x84, 0x00, 0x20, 0x01, 0x85, 0x00, ++0x20, 0x01, 0x8C, 0x00, 0x27, 0x81, 0x8C, 0x00, 0x27, 0x01, 0x8E, 0x00, 0x27, 0x01, 0x9B, 0x00, 0x3F, 0x01, 0x9B, 0x00, ++0x3F, 0xC1, 0x9C, 0x00, 0x3F, 0xC1, 0x8F, 0x00, 0x00, 0xC6, 0xFF, 0x00, 0x00, 0xC6, 0x40, 0x00, 0x00, 0x06, 0x41, 0x00, ++0x00, 0x46, 0x41, 0x00, 0x00, 0x86, 0x90, 0x00, 0x00, 0xC6, 0x90, 0x00, 0x00, 0x06, 0xB1, 0x00, 0x00, 0x46, 0xB1, 0x00, ++0x00, 0x86, 0xB1, 0x00, 0x00, 0x06, 0xB2, 0x00, 0x00, 0xC6, 0xB2, 0x00, 0x00, 0x46, 0xB9, 0x00, 0x00, 0xC6, 0xB9, 0x00, ++0x00, 0x46, 0xBA, 0x00, 0x00, 0x46, 0xBB, 0x00, 0x00, 0xC6, 0xBC, 0x00, 0x82, 0x01, 0x83, 0x01, 0x40, 0x02, 0x41, 0x02, ++0x80, 0x02, 0x81, 0x02, 0x82, 0x02, 0x83, 0x02, 0x40, 0x03, 0x41, 0x03, 0x80, 0x03, 0x81, 0x03, 0x00, 0x04, 0x01, 0x04, ++0x40, 0x04, 0x41, 0x04, 0x60, 0x60, 0x00, 0x00, 0x3B, 0x18, 0xB3, 0x03, 0x68, 0x51, 0x2E, 0x1A, 0x48, 0x51, 0x2E, 0x1A, ++0x00, 0x00, 0x00, 0x00, 0x84, 0x18, 0x20, 0x56, 0x84, 0x18, 0x20, 0x56, 0x00, 0x00, 0x00, 0x00, 0x08, 0x50, 0x2A, 0x7A, ++0xC8, 0x50, 0x1B, 0x79, 0xC8, 0xD0, 0x2A, 0x7A, 0x40, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x64, 0x32, 0x00, 0x00, ++0x00, 0x87, 0x93, 0x03, 0x00, 0x20, 0x03, 0x00, 0x00, 0x20, 0x03, 0x00, 0x30, 0x75, 0x00, 0x00, 0xB0, 0xAD, 0x01, 0x00, ++0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x10, 0x27, 0x00, 0x00, ++0x40, 0x0D, 0x03, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x27, 0x50, 0xC3, 0xA0, 0x0F, 0x40, 0x1F, 0x84, 0x03, 0x05, 0x08, ++0x01, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x1A, 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x1A, 0x00, 0xE0, 0x57, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, ++0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x19, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x19, 0x00, 0xF4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0xE0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x71, 0x04, 0x00, 0x10, 0x0E, 0x00, ++0x03, 0x01, 0x08, 0x8F, 0x03, 0xE6, 0xE0, 0xD0, 0xD6, 0x06, 0xD6, 0x06, 0x00, 0x00, 0x01, 0xF3, 0x01, 0x0A, 0x00, 0x0F, ++0x08, 0x01, 0x09, 0x08, 0x08, 0x08, 0x08, 0x0A, 0x09, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ++0x03, 0x01, 0x00, 0x00, 0xBC, 0x06, 0x04, 0x04, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, 0x0A, 0x02, 0x04, ++0x01, 0x00, 0xF0, 0x00, 0x08, 0x04, 0x00, 0x04, 0x04, 0x04, 0x09, 0x06, 0x04, 0x01, 0x04, 0x01, 0x05, 0x14, 0x38, 0x01, ++0x38, 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, ++0x7D, 0xA6, 0x12, 0x00, 0x91, 0xA1, 0x12, 0x00, 0xA5, 0xA6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x99, 0xA1, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xA1, 0x12, 0x00, 0xD1, 0xA1, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xA3, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x6D, 0x12, 0x00, 0x88, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, ++0x05, 0xC7, 0x12, 0x00, 0xE1, 0xB8, 0x14, 0x00, 0x75, 0xBB, 0x14, 0x00, 0x2D, 0xBE, 0x14, 0x00, 0xE9, 0xBC, 0x14, 0x00, ++0x81, 0xBC, 0x14, 0x00, 0x29, 0xAC, 0x14, 0x00, 0xFD, 0x0C, 0x15, 0x00, 0x1D, 0x0B, 0x15, 0x00, 0x6D, 0x08, 0x15, 0x00, ++0x0D, 0x07, 0x15, 0x00, 0x59, 0xC8, 0x13, 0x00, 0xF5, 0xE7, 0x13, 0x00, 0xA1, 0xCE, 0x13, 0x00, 0x3D, 0xD1, 0x13, 0x00, ++0x4D, 0xD0, 0x13, 0x00, 0xF9, 0xD0, 0x13, 0x00, 0x05, 0xDD, 0x13, 0x00, 0xF1, 0xDD, 0x13, 0x00, 0x95, 0xDE, 0x13, 0x00, ++0x85, 0xE4, 0x13, 0x00, 0xF5, 0xE0, 0x13, 0x00, 0xC1, 0xE3, 0x13, 0x00, 0xED, 0xCE, 0x13, 0x00, 0x59, 0xD6, 0x13, 0x00, ++0xF5, 0xD9, 0x13, 0x00, 0x3D, 0xD5, 0x13, 0x00, 0xA9, 0xD4, 0x13, 0x00, 0x91, 0xD8, 0x13, 0x00, 0x31, 0xD9, 0x13, 0x00, ++0xC1, 0xD8, 0x13, 0x00, 0x21, 0xD4, 0x13, 0x00, 0x4D, 0xDB, 0x13, 0x00, 0x71, 0xCA, 0x13, 0x00, 0xE5, 0xC9, 0x13, 0x00, ++0xAD, 0xC0, 0x13, 0x00, 0xCD, 0xC6, 0x13, 0x00, 0x39, 0xC0, 0x13, 0x00, 0x79, 0xD6, 0x13, 0x00, 0xE5, 0xD7, 0x13, 0x00, ++0xF1, 0xC7, 0x13, 0x00, 0xDD, 0xE4, 0x13, 0x00, 0xA1, 0xE6, 0x13, 0x00, 0x21, 0xD2, 0x13, 0x00, 0x6D, 0xD4, 0x13, 0x00, ++0x99, 0xEA, 0x13, 0x00, 0x71, 0x50, 0x14, 0x00, 0x71, 0x58, 0x14, 0x00, 0x25, 0x06, 0x12, 0x00, 0x7D, 0x4B, 0x14, 0x00, ++0x19, 0x4B, 0x14, 0x00, 0xF9, 0x5E, 0x12, 0x00, 0xD1, 0x5E, 0x12, 0x00, 0xF1, 0x1C, 0x14, 0x00, 0x19, 0x1E, 0x14, 0x00, ++0xE9, 0x14, 0x14, 0x00, 0xD9, 0x16, 0x14, 0x00, 0x91, 0x17, 0x14, 0x00, 0xC9, 0x1A, 0x14, 0x00, 0xF1, 0x19, 0x14, 0x00, ++0x3D, 0x15, 0x14, 0x00, 0xA5, 0x1B, 0x14, 0x00, 0x25, 0x1B, 0x14, 0x00, 0x1D, 0x90, 0x12, 0x00, 0x7D, 0x93, 0x12, 0x00, ++0xD1, 0x9E, 0x12, 0x00, 0x71, 0x8E, 0x12, 0x00, 0xF5, 0xAA, 0x12, 0x00, 0xC5, 0x78, 0x12, 0x00, 0x05, 0x69, 0x12, 0x00, ++0x39, 0x69, 0x12, 0x00, 0x8D, 0x52, 0x12, 0x00, 0x7D, 0x50, 0x12, 0x00, 0xD9, 0x55, 0x12, 0x00, 0xC1, 0x51, 0x12, 0x00, ++0x79, 0x51, 0x12, 0x00, 0x5D, 0xB2, 0x12, 0x00, 0x8D, 0x0C, 0x15, 0x00, 0x61, 0x4C, 0x14, 0x00, 0xF9, 0x0E, 0x12, 0x00, ++0x49, 0x07, 0x12, 0x00, 0x55, 0x59, 0x14, 0x00, 0xD5, 0x58, 0x14, 0x00, 0x49, 0x5A, 0x14, 0x00, 0x05, 0x5A, 0x14, 0x00, ++0xD9, 0x80, 0x14, 0x00, 0xD9, 0x5A, 0x14, 0x00, 0x45, 0x79, 0x14, 0x00, 0x7D, 0x7D, 0x13, 0x00, 0xA1, 0x78, 0x13, 0x00, ++0xB5, 0x7E, 0x13, 0x00, 0xF1, 0x85, 0x13, 0x00, 0xD5, 0xB6, 0x13, 0x00, 0x91, 0xBC, 0x13, 0x00, 0xF1, 0xB5, 0x13, 0x00, ++0x19, 0xBB, 0x13, 0x00, 0x5D, 0xBB, 0x13, 0x00, 0xD5, 0xBC, 0x13, 0x00, 0xDD, 0xB8, 0x13, 0x00, 0x8D, 0xB8, 0x13, 0x00, ++0xFD, 0xBD, 0x13, 0x00, 0x21, 0xB8, 0x13, 0x00, 0xC5, 0x8C, 0x13, 0x00, 0x09, 0x8C, 0x13, 0x00, 0xE9, 0x72, 0x13, 0x00, ++0x59, 0x87, 0x13, 0x00, 0xCD, 0x73, 0x13, 0x00, 0x31, 0x84, 0x13, 0x00, 0x25, 0x80, 0x13, 0x00, 0x35, 0x83, 0x13, 0x00, ++0xFD, 0x80, 0x13, 0x00, 0xE9, 0x8B, 0x13, 0x00, 0x01, 0x8E, 0x13, 0x00, 0x55, 0x89, 0x13, 0x00, 0xD9, 0x89, 0x13, 0x00, ++0x91, 0x7D, 0x13, 0x00, 0x4D, 0x75, 0x13, 0x00, 0xA5, 0xB3, 0x13, 0x00, 0x19, 0xB0, 0x13, 0x00, 0x01, 0xAF, 0x13, 0x00, ++0x21, 0xAF, 0x13, 0x00, 0x25, 0x05, 0x14, 0x00, 0xA9, 0xFF, 0x13, 0x00, 0xB1, 0xFE, 0x13, 0x00, 0xC5, 0xFF, 0x13, 0x00, ++0x81, 0xFF, 0x13, 0x00, 0x69, 0x06, 0x14, 0x00, 0x49, 0x03, 0x14, 0x00, 0x2D, 0x0A, 0x14, 0x00, 0x25, 0x08, 0x14, 0x00, ++0x3D, 0x09, 0x14, 0x00, 0xF9, 0x07, 0x14, 0x00, 0x59, 0xFB, 0x13, 0x00, 0x35, 0x04, 0x14, 0x00, 0xF5, 0xF6, 0x13, 0x00, ++0x89, 0xF4, 0x13, 0x00, 0xA5, 0x13, 0x12, 0x00, 0x5D, 0x10, 0x12, 0x00, 0xC1, 0x0B, 0x12, 0x00, 0x49, 0x11, 0x12, 0x00, ++0x4D, 0x02, 0x12, 0x00, 0xDD, 0xEA, 0x13, 0x00, 0x01, 0xEE, 0x13, 0x00, 0xA9, 0xF0, 0x13, 0x00, 0x79, 0xEF, 0x13, 0x00, ++0x49, 0xF1, 0x13, 0x00, 0xE5, 0xF1, 0x13, 0x00, 0x85, 0xEC, 0x13, 0x00, 0x45, 0xED, 0x13, 0x00, 0xA5, 0xED, 0x13, 0x00, ++0x3D, 0xEB, 0x13, 0x00, 0x45, 0xEF, 0x13, 0x00, 0xA1, 0xF2, 0x13, 0x00, 0xC5, 0xF3, 0x13, 0x00, 0x85, 0x49, 0x15, 0x00, ++0x01, 0x35, 0x15, 0x00, 0xCD, 0x42, 0x12, 0x00, 0x71, 0xCB, 0x12, 0x00, 0x35, 0xCF, 0x12, 0x00, 0xAD, 0xD3, 0x12, 0x00, ++0x9D, 0xCB, 0x12, 0x00, 0xFD, 0xD4, 0x12, 0x00, 0xFD, 0x48, 0x13, 0x00, 0x69, 0x4B, 0x13, 0x00, 0x21, 0x4C, 0x13, 0x00, ++0x15, 0x46, 0x13, 0x00, 0x99, 0x50, 0x13, 0x00, 0x9D, 0x5C, 0x13, 0x00, 0x79, 0x5C, 0x13, 0x00, 0xED, 0x53, 0x13, 0x00, ++0xE5, 0x56, 0x13, 0x00, 0x81, 0x4F, 0x13, 0x00, 0x61, 0x4E, 0x13, 0x00, 0x29, 0x4D, 0x13, 0x00, 0x01, 0x40, 0x13, 0x00, ++0xED, 0x4C, 0x13, 0x00, 0x1D, 0x52, 0x13, 0x00, 0xDD, 0xDB, 0x14, 0x00, 0xB5, 0xEB, 0x14, 0x00, 0x19, 0xD9, 0x14, 0x00, ++0xA5, 0xDF, 0x14, 0x00, 0xB5, 0xE0, 0x14, 0x00, 0xE9, 0xDE, 0x14, 0x00, 0x15, 0xE3, 0x14, 0x00, 0xD9, 0xE5, 0x14, 0x00, ++0x5D, 0xD7, 0x14, 0x00, 0xED, 0xD6, 0x14, 0x00, 0x21, 0x13, 0x14, 0x00, 0x85, 0x14, 0x14, 0x00, 0x05, 0xD1, 0x14, 0x00, ++0x8D, 0x85, 0x12, 0x00, 0xD1, 0x80, 0x12, 0x00, 0xCD, 0x7D, 0x12, 0x00, 0xED, 0x7F, 0x12, 0x00, 0x45, 0x7A, 0x12, 0x00, ++0x01, 0x7F, 0x12, 0x00, 0xD5, 0x99, 0x14, 0x00, 0xED, 0x9A, 0x14, 0x00, 0x31, 0x62, 0x13, 0x00, 0x29, 0x5F, 0x13, 0x00, ++0x65, 0x63, 0x13, 0x00, 0x41, 0x61, 0x13, 0x00, 0x71, 0x5F, 0x12, 0x00, 0xB9, 0x24, 0x12, 0x00, 0xD9, 0x0D, 0x14, 0x00, ++0x61, 0x0C, 0x14, 0x00, 0x79, 0x20, 0x14, 0x00, 0x05, 0x20, 0x14, 0x00, 0xC1, 0x20, 0x14, 0x00, 0x55, 0xD6, 0x12, 0x00, ++0x4D, 0x1B, 0x13, 0x00, 0x99, 0x0E, 0x13, 0x00, 0x11, 0x0C, 0x13, 0x00, 0x65, 0x0D, 0x13, 0x00, 0xD1, 0x19, 0x13, 0x00, ++0x5D, 0x13, 0x13, 0x00, 0x79, 0x0A, 0x13, 0x00, 0x8D, 0x21, 0x13, 0x00, 0x2D, 0x15, 0x13, 0x00, 0x19, 0x21, 0x13, 0x00, ++0x79, 0x07, 0x13, 0x00, 0xCD, 0xF3, 0x12, 0x00, 0x31, 0xD7, 0x12, 0x00, 0x41, 0xD8, 0x12, 0x00, 0xA1, 0xD8, 0x12, 0x00, ++0x69, 0xFC, 0x12, 0x00, 0x15, 0xFD, 0x12, 0x00, 0xF5, 0xE7, 0x12, 0x00, 0xB5, 0xE2, 0x12, 0x00, 0xE5, 0xEA, 0x12, 0x00, ++0xF5, 0xEB, 0x12, 0x00, 0xED, 0xE6, 0x12, 0x00, 0xF9, 0xDD, 0x12, 0x00, 0x89, 0xE2, 0x12, 0x00, 0xD1, 0xFD, 0x12, 0x00, ++0xD5, 0xE7, 0x12, 0x00, 0xD5, 0x30, 0x13, 0x00, 0x91, 0x36, 0x13, 0x00, 0xD5, 0x3A, 0x13, 0x00, 0x7D, 0x3C, 0x13, 0x00, ++0xDD, 0x26, 0x13, 0x00, 0x49, 0x27, 0x13, 0x00, 0xA9, 0x25, 0x13, 0x00, 0xCD, 0x35, 0x13, 0x00, 0x71, 0x25, 0x13, 0x00, ++0x89, 0x2C, 0x13, 0x00, 0x75, 0x30, 0x13, 0x00, 0x81, 0x3A, 0x13, 0x00, 0x05, 0x3A, 0x13, 0x00, 0x49, 0x3D, 0x13, 0x00, ++0xB1, 0x2B, 0x13, 0x00, 0x21, 0x2F, 0x13, 0x00, 0xBD, 0x39, 0x13, 0x00, 0x59, 0x28, 0x13, 0x00, 0xCD, 0x2A, 0x13, 0x00, ++0x61, 0x37, 0x13, 0x00, 0x01, 0xDB, 0x12, 0x00, 0xF1, 0xE2, 0x12, 0x00, 0x81, 0xD9, 0x12, 0x00, 0x35, 0xEE, 0x12, 0x00, ++0xC5, 0xEF, 0x12, 0x00, 0x49, 0xED, 0x12, 0x00, 0x69, 0xFD, 0x14, 0x00, 0x39, 0xF9, 0x14, 0x00, 0x71, 0xF4, 0x14, 0x00, ++0x79, 0xF9, 0x14, 0x00, 0x09, 0xFC, 0x14, 0x00, 0xC5, 0xF3, 0x14, 0x00, 0xDD, 0x60, 0x12, 0x00, 0xB1, 0xAD, 0x12, 0x00, ++0xBD, 0xAE, 0x12, 0x00, 0x29, 0xAF, 0x12, 0x00, 0xA5, 0xA4, 0x12, 0x00, 0xD1, 0xA5, 0x12, 0x00, 0xD9, 0x6C, 0x13, 0x00, ++0xF5, 0x6E, 0x13, 0x00, 0x1D, 0x64, 0x13, 0x00, 0x2D, 0x6E, 0x13, 0x00, 0x51, 0x65, 0x13, 0x00, 0xB5, 0x6E, 0x13, 0x00, ++0x2D, 0x6F, 0x13, 0x00, 0xC1, 0x68, 0x13, 0x00, 0x91, 0xBE, 0x12, 0x00, 0x29, 0xC4, 0x12, 0x00, 0x95, 0xBB, 0x12, 0x00, ++0xDD, 0x03, 0x12, 0x00, 0x19, 0xC5, 0x12, 0x00, 0xCD, 0xC6, 0x12, 0x00, 0x2D, 0x1E, 0x12, 0x00, 0x61, 0x1B, 0x12, 0x00, ++0x69, 0x1D, 0x12, 0x00, 0x7D, 0x9D, 0x12, 0x00, 0xA9, 0x9D, 0x12, 0x00, 0x39, 0x12, 0x14, 0x00, 0x99, 0x71, 0x13, 0x00, ++0xC1, 0x21, 0x12, 0x00, 0x51, 0x09, 0x12, 0x00, 0x9D, 0x0A, 0x12, 0x00, 0xA1, 0x0A, 0x12, 0x00, 0xBD, 0x0B, 0x12, 0x00, ++0x41, 0x1C, 0x12, 0x00, 0xD5, 0xCF, 0x12, 0x00, 0x21, 0xD1, 0x12, 0x00, 0xD1, 0x3C, 0x12, 0x00, 0xC5, 0x4B, 0x12, 0x00, ++0xA1, 0x4D, 0x12, 0x00, 0x6D, 0x4C, 0x12, 0x00, 0xAD, 0x4A, 0x12, 0x00, 0x71, 0xC0, 0x12, 0x00, 0x19, 0xC2, 0x12, 0x00, ++0x79, 0xB8, 0x12, 0x00, 0x29, 0x9A, 0x12, 0x00, 0x39, 0x93, 0x12, 0x00, 0xA1, 0x65, 0x12, 0x00, 0xCD, 0xB1, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x58, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC2, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x75, 0x95, 0x13, 0x00, ++0x04, 0x00, 0x00, 0x00, 0xFD, 0x8F, 0x13, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x08, 0x00, 0x00, 0x00, ++0xF1, 0xA9, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x93, 0x13, 0x00, 0x10, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, ++0x16, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x12, 0x00, 0x00, 0x00, ++0xF1, 0xA9, 0x13, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, ++0x1A, 0x00, 0x00, 0x00, 0xCD, 0x90, 0x13, 0x00, 0x6B, 0x00, 0x00, 0x00, 0xF5, 0x96, 0x13, 0x00, 0x6D, 0x00, 0x00, 0x00, ++0xD1, 0x97, 0x13, 0x00, 0x71, 0x00, 0x00, 0x00, 0x19, 0x93, 0x13, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x79, 0x91, 0x13, 0x00, ++0x20, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x1E, 0x00, 0x00, 0x00, ++0xF1, 0xA9, 0x13, 0x00, 0x30, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x22, 0x00, 0x00, 0x00, 0x09, 0xA0, 0x13, 0x00, ++0x84, 0x00, 0x00, 0x00, 0xAD, 0xA0, 0x13, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x4D, 0x8E, 0x13, 0x00, 0x24, 0x00, 0x00, 0x00, ++0xA9, 0x93, 0x13, 0x00, 0x26, 0x00, 0x00, 0x00, 0x4D, 0x94, 0x13, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x8E, 0x13, 0x00, ++0x0C, 0x00, 0x00, 0x00, 0x9D, 0x91, 0x13, 0x00, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x2A, 0x00, 0x00, 0x00, ++0xF1, 0x97, 0x13, 0x00, 0x39, 0x00, 0x00, 0x00, 0xC5, 0x91, 0x13, 0x00, 0x3B, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, ++0x46, 0x00, 0x00, 0x00, 0xCD, 0x8E, 0x13, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x21, 0x8E, 0x13, 0x00, 0x41, 0x00, 0x00, 0x00, ++0x91, 0x98, 0x13, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x8E, 0x13, 0x00, 0x4B, 0x00, 0x00, 0x00, 0xA9, 0x94, 0x13, 0x00, ++0x51, 0x00, 0x00, 0x00, 0x59, 0x8F, 0x13, 0x00, 0x52, 0x00, 0x00, 0x00, 0xB5, 0x9F, 0x13, 0x00, 0x56, 0x00, 0x00, 0x00, ++0x15, 0x95, 0x13, 0x00, 0x87, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x61, 0x00, 0x00, 0x00, 0x21, 0x97, 0x13, 0x00, ++0x63, 0x00, 0x00, 0x00, 0x9D, 0x98, 0x13, 0x00, 0x65, 0x00, 0x00, 0x00, 0xE9, 0x91, 0x13, 0x00, 0x67, 0x00, 0x00, 0x00, ++0x0D, 0x96, 0x13, 0x00, 0x69, 0x00, 0x00, 0x00, 0xF1, 0x9C, 0x13, 0x00, 0x73, 0x00, 0x00, 0x00, 0xE9, 0x98, 0x13, 0x00, ++0x75, 0x00, 0x00, 0x00, 0x0D, 0x8F, 0x13, 0x00, 0x77, 0x00, 0x00, 0x00, 0xA5, 0x92, 0x13, 0x00, 0x79, 0x00, 0x00, 0x00, ++0xCD, 0x92, 0x13, 0x00, 0x7B, 0x00, 0x00, 0x00, 0xE1, 0x9B, 0x13, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x59, 0x99, 0x13, 0x00, ++0x80, 0x00, 0x00, 0x00, 0xBD, 0x96, 0x13, 0x00, 0x82, 0x00, 0x00, 0x00, 0x11, 0x9B, 0x13, 0x00, 0x00, 0x08, 0x00, 0x00, ++0xB9, 0x0E, 0x14, 0x00, 0x85, 0x00, 0x00, 0x00, 0x4D, 0x0F, 0x14, 0x00, 0x86, 0x00, 0x00, 0x00, 0xC9, 0x0F, 0x14, 0x00, ++0x03, 0x08, 0x00, 0x00, 0x71, 0x10, 0x14, 0x00, 0x0D, 0xCD, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xB0, 0x13, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xA1, 0x28, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x4C, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x9D, 0x2F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x84, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x7F, 0x13, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xB5, 0x7F, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x85, 0x4A, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xF2, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x48, 0x13, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xD1, 0x78, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xD1, 0xF4, 0x12, 0x00, 0x04, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, ++0x02, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xF9, 0x4C, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x05, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, ++0x03, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, ++0xF9, 0x4C, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x69, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x6D, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x69, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xBD, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x15, 0x4A, 0x14, 0x00, 0x02, 0x04, 0x00, 0x00, 0xB5, 0x49, 0x14, 0x00, ++0x04, 0x04, 0x00, 0x00, 0x2D, 0x48, 0x14, 0x00, 0x06, 0x04, 0x00, 0x00, 0xF9, 0x47, 0x14, 0x00, 0x09, 0x04, 0x00, 0x00, ++0x95, 0x49, 0x14, 0x00, 0x11, 0x04, 0x00, 0x00, 0x11, 0x49, 0x14, 0x00, 0x0B, 0x04, 0x00, 0x00, 0xC1, 0x4A, 0x14, 0x00, ++0x0D, 0x04, 0x00, 0x00, 0x45, 0x4A, 0x14, 0x00, 0x0F, 0x04, 0x00, 0x00, 0x61, 0x48, 0x14, 0x00, 0x1B, 0x04, 0x00, 0x00, ++0x91, 0x47, 0x14, 0x00, 0x1E, 0x04, 0x00, 0x00, 0x75, 0x47, 0x14, 0x00, 0x1F, 0x04, 0x00, 0x00, 0x59, 0x47, 0x14, 0x00, ++0x01, 0x00, 0x00, 0x00, 0x28, 0x34, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0xBD, 0x68, 0x14, 0x00, 0x02, 0x14, 0x00, 0x00, ++0xED, 0x65, 0x14, 0x00, 0x04, 0x14, 0x00, 0x00, 0x01, 0x67, 0x14, 0x00, 0x07, 0x14, 0x00, 0x00, 0x01, 0x6A, 0x14, 0x00, ++0x09, 0x14, 0x00, 0x00, 0x75, 0x67, 0x14, 0x00, 0x17, 0x14, 0x00, 0x00, 0xB1, 0x72, 0x14, 0x00, 0x19, 0x14, 0x00, 0x00, ++0xB5, 0x6E, 0x14, 0x00, 0x0C, 0x14, 0x00, 0x00, 0x01, 0x68, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, ++0x23, 0x00, 0x00, 0x00, 0x45, 0x6F, 0x14, 0x00, 0x13, 0x14, 0x00, 0x00, 0x45, 0x73, 0x14, 0x00, 0x32, 0x00, 0x00, 0x00, ++0x9D, 0x6F, 0x14, 0x00, 0x15, 0x14, 0x00, 0x00, 0x11, 0x66, 0x14, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, ++0x3C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x42, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x1B, 0x00, 0x00, 0x00, ++0x89, 0x31, 0x14, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, ++0x70, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x72, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x0E, 0x14, 0x00, 0x00, ++0xF5, 0x6F, 0x14, 0x00, 0x10, 0x14, 0x00, 0x00, 0xF1, 0x70, 0x14, 0x00, 0x11, 0x14, 0x00, 0x00, 0x91, 0x71, 0x14, 0x00, ++0x00, 0x18, 0x00, 0x00, 0x1D, 0x8A, 0x14, 0x00, 0x03, 0x18, 0x00, 0x00, 0x6D, 0x92, 0x14, 0x00, 0x01, 0x10, 0x00, 0x00, ++0xA1, 0x8C, 0x14, 0x00, 0x03, 0x10, 0x00, 0x00, 0x09, 0x8D, 0x14, 0x00, 0x08, 0x18, 0x00, 0x00, 0x71, 0x8C, 0x14, 0x00, ++0x43, 0x00, 0x00, 0x00, 0x21, 0x8C, 0x14, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x8D, 0x92, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, ++0xA5, 0x90, 0x14, 0x00, 0x19, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x17, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, ++0x15, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x72, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x1B, 0x00, 0x00, 0x00, ++0xE5, 0x8F, 0x14, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xD9, 0x94, 0x14, 0x00, 0x1A, 0x14, 0x00, 0x00, 0x7D, 0x8F, 0x14, 0x00, ++0x4C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x90, 0x14, 0x00, 0x3A, 0x00, 0x00, 0x00, ++0x65, 0x90, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, 0x99, 0x91, 0x14, 0x00, 0x07, 0x18, 0x00, 0x00, 0xFD, 0x91, 0x14, 0x00, ++0x09, 0x18, 0x00, 0x00, 0x19, 0x92, 0x14, 0x00, 0x00, 0x1C, 0x00, 0x00, 0xF5, 0xB3, 0x14, 0x00, 0x02, 0x1C, 0x00, 0x00, ++0xD5, 0xB6, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, 0xD9, 0xB7, 0x14, 0x00, 0x40, 0x00, 0x00, 0x00, 0xBD, 0xB2, 0x14, 0x00, ++0x19, 0x00, 0x00, 0x00, 0x01, 0xB6, 0x14, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0xB6, 0x14, 0x00, 0x15, 0x00, 0x00, 0x00, ++0x01, 0xB6, 0x14, 0x00, 0x1A, 0x14, 0x00, 0x00, 0x9D, 0xB5, 0x14, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x81, 0xB6, 0x14, 0x00, ++0x3A, 0x00, 0x00, 0x00, 0x41, 0xB6, 0x14, 0x00, 0x04, 0x1C, 0x00, 0x00, 0x01, 0xB3, 0x14, 0x00, 0x06, 0x1C, 0x00, 0x00, ++0x39, 0xB7, 0x14, 0x00, 0x08, 0x1C, 0x00, 0x00, 0x59, 0xB5, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, ++0x02, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, 0x05, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, ++0x89, 0x31, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0x95, 0xBF, 0x14, 0x00, 0x02, 0x10, 0x00, 0x00, 0xF5, 0xC0, 0x14, 0x00, ++0x05, 0x10, 0x00, 0x00, 0xF5, 0xBF, 0x14, 0x00, 0x07, 0x10, 0x00, 0x00, 0xF1, 0xC1, 0x14, 0x00, 0x0A, 0x10, 0x00, 0x00, ++0x7D, 0xC0, 0x14, 0x00, 0x01, 0x08, 0x00, 0x00, 0x39, 0xC2, 0x14, 0x00, 0x02, 0x08, 0x00, 0x00, 0x85, 0xC2, 0x14, 0x00, ++0x00, 0x28, 0x00, 0x00, 0xA1, 0xC2, 0x14, 0x00, 0x0A, 0x10, 0x00, 0x00, 0x51, 0xC0, 0x14, 0x00, 0x04, 0x08, 0x00, 0x00, ++0x4D, 0xC2, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0xD5, 0xC0, 0x14, 0x00, 0x07, 0x10, 0x00, 0x00, 0xA1, 0xC0, 0x14, 0x00, ++0xDC, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x45, 0x04, 0x15, 0x00, 0x01, 0x20, 0x00, 0x00, 0x69, 0x04, 0x15, 0x00, ++0x2B, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x15, 0x00, 0x29, 0x00, 0x00, 0x00, 0x55, 0xFF, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, ++0x35, 0x01, 0x15, 0x00, 0x0D, 0x26, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, ++}; ++ ++char fw_adid_u03[1208] = { ++0x61, 0xBD, 0x08, 0x00, 0xFD, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0x03, 0x08, 0x00, ++0x71, 0x02, 0x08, 0x00, 0x21, 0x04, 0x08, 0x00, 0xD9, 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x0F, 0x08, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x15, 0x08, 0x00, ++0x6D, 0x18, 0x08, 0x00, 0xD1, 0x18, 0x08, 0x00, 0x15, 0x19, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x1D, 0x08, 0x00, ++0xA1, 0x24, 0x08, 0x00, 0x05, 0x26, 0x08, 0x00, 0x3D, 0x2A, 0x08, 0x00, 0x9D, 0x55, 0x08, 0x00, 0x39, 0x76, 0x08, 0x00, ++0x91, 0x76, 0x08, 0x00, 0x9D, 0x7C, 0x08, 0x00, 0xE5, 0x7C, 0x08, 0x00, 0x5D, 0x80, 0x08, 0x00, 0x75, 0xA9, 0x08, 0x00, ++0x9D, 0xBE, 0x08, 0x00, 0xD5, 0xBE, 0x08, 0x00, 0x39, 0xC0, 0x08, 0x00, 0x6D, 0xC2, 0x08, 0x00, 0x3D, 0x05, 0x09, 0x00, ++0xF1, 0x3B, 0x09, 0x00, 0x31, 0x3E, 0x09, 0x00, 0xFD, 0x40, 0x09, 0x00, 0x65, 0x9D, 0x09, 0x00, 0x25, 0xC0, 0x09, 0x00, ++0xF9, 0xBB, 0x09, 0x00, 0x05, 0xA2, 0x09, 0x00, 0x91, 0xD7, 0x09, 0x00, 0x4D, 0xB2, 0x0A, 0x00, 0x25, 0xB6, 0x0A, 0x00, ++0x75, 0xB8, 0x0A, 0x00, 0x2D, 0xB9, 0x0A, 0x00, 0x8D, 0xBB, 0x0A, 0x00, 0x99, 0xBC, 0x0A, 0x00, 0xA1, 0xC5, 0x0A, 0x00, ++0x31, 0xCD, 0x0A, 0x00, 0x09, 0xDE, 0x0A, 0x00, 0xB9, 0xEE, 0x0A, 0x00, 0x35, 0x58, 0x09, 0x00, 0xB1, 0x58, 0x09, 0x00, ++0x15, 0x54, 0x09, 0x00, 0xBD, 0x56, 0x09, 0x00, 0x11, 0x5B, 0x09, 0x00, 0xED, 0x5C, 0x09, 0x00, 0x15, 0x6C, 0x09, 0x00, ++0xB9, 0x60, 0x09, 0x00, 0xDD, 0x29, 0x0B, 0x00, 0x05, 0x76, 0x09, 0x00, 0x75, 0x76, 0x09, 0x00, 0x3D, 0x7A, 0x09, 0x00, ++0x5D, 0x7E, 0x09, 0x00, 0x69, 0x78, 0x09, 0x00, 0x61, 0x79, 0x09, 0x00, 0xD9, 0x7E, 0x09, 0x00, 0x35, 0x41, 0x0B, 0x00, ++0xB5, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x0C, 0x0B, 0x00, 0x85, 0x6F, 0x09, 0x00, 0xD5, 0x7B, 0x0B, 0x00, ++0x75, 0x7C, 0x0B, 0x00, 0xDD, 0x6C, 0x09, 0x00, 0xA9, 0x6D, 0x09, 0x00, 0x75, 0x6E, 0x09, 0x00, 0xE9, 0x1F, 0x0B, 0x00, ++0x35, 0x23, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x1B, 0x0B, 0x00, 0x45, 0x27, 0x0B, 0x00, 0x85, 0x1A, 0x0B, 0x00, ++0x69, 0x17, 0x0B, 0x00, 0xDD, 0x27, 0x0B, 0x00, 0x31, 0x2B, 0x0B, 0x00, 0x25, 0x78, 0x0B, 0x00, 0x15, 0x65, 0x0B, 0x00, ++0x3D, 0x6B, 0x0B, 0x00, 0x9D, 0x67, 0x0B, 0x00, 0x99, 0x6B, 0x0B, 0x00, 0xC5, 0x6C, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x2D, 0xAF, 0x0B, 0x00, 0x3D, 0x99, 0x0C, 0x00, 0xC5, 0xD9, 0x0C, 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, 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, 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, 0x00, 0x61, 0x95, 0x0C, 0x00, 0x3D, 0xD5, 0x0C, 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, 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, 0x00, ++0xF5, 0xA4, 0x08, 0x00, 0xB5, 0xA5, 0x08, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0xFD, 0x50, 0x08, 0x00, 0x9D, 0x7D, 0x08, 0x00, 0xBD, 0x7D, 0x08, 0x00, 0xDD, 0x7D, 0x08, 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, 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, 0xA9, 0x91, 0x08, 0x00, ++0xAB, 0x91, 0x08, 0x00, 0xAD, 0x91, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x71, 0xD5, 0x09, 0x00, 0x6D, 0x0E, 0x08, 0x00, ++}; ++ ++char fw_patch_table_u03[1256] = { ++0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x50, 0x54, 0x5F, 0x54, 0x41, 0x47, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, ++0x54, 0x5F, 0x54, 0x52, 0x41, 0x50, 0x5F, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, ++0x00, 0xF0, 0x16, 0x00, 0x04, 0x23, 0xA3, 0x55, 0x00, 0x10, 0x08, 0x40, 0x88, 0x48, 0x0C, 0x00, 0x04, 0xF0, 0x16, 0x00, ++0x00, 0x2B, 0x05, 0xE0, 0x04, 0x10, 0x08, 0x40, 0x58, 0x58, 0x0B, 0x00, 0x08, 0xF0, 0x16, 0x00, 0x00, 0x2B, 0xB1, 0xE7, ++0x08, 0x10, 0x08, 0x40, 0x30, 0x5A, 0x0B, 0x00, 0x14, 0xEA, 0x16, 0x00, 0x02, 0x49, 0x8E, 0x46, 0x18, 0xEA, 0x16, 0x00, ++0x00, 0xB5, 0x02, 0x4B, 0x1C, 0xEA, 0x16, 0x00, 0xDB, 0x6E, 0x00, 0xBD, 0x20, 0xEA, 0x16, 0x00, 0xD7, 0xCB, 0x0A, 0x00, ++0x24, 0xEA, 0x16, 0x00, 0xAC, 0x2B, 0x16, 0x00, 0x0C, 0xF0, 0x16, 0x00, 0xC1, 0xF0, 0x1F, 0xFF, 0x0C, 0x10, 0x08, 0x40, ++0xD2, 0xCB, 0x0A, 0x00, 0x00, 0xEA, 0x16, 0x00, 0x02, 0x49, 0x8E, 0x46, 0x04, 0xEA, 0x16, 0x00, 0x00, 0xB5, 0x02, 0x4B, ++0x08, 0xEA, 0x16, 0x00, 0xDA, 0x6E, 0x00, 0xBD, 0x0C, 0xEA, 0x16, 0x00, 0xC1, 0xE6, 0x0A, 0x00, 0x10, 0xEA, 0x16, 0x00, ++0xAC, 0x2B, 0x16, 0x00, 0x10, 0xF0, 0x16, 0x00, 0xC0, 0xF0, 0xA0, 0xF9, 0x10, 0x10, 0x08, 0x40, 0xBC, 0xE6, 0x0A, 0x00, ++0x14, 0xF0, 0x16, 0x00, 0x43, 0x1C, 0x05, 0xE0, 0x14, 0x10, 0x08, 0x40, 0x1C, 0xFD, 0x0C, 0x00, 0x30, 0xEA, 0x16, 0x00, ++0x01, 0x4B, 0x98, 0x47, 0x34, 0xEA, 0x16, 0x00, 0x01, 0x4B, 0x9F, 0x46, 0x38, 0xEA, 0x16, 0x00, 0xD9, 0x97, 0x10, 0x00, ++0x3C, 0xEA, 0x16, 0x00, 0x59, 0x1E, 0x0D, 0x00, 0x18, 0xF0, 0x16, 0x00, 0x9C, 0xF0, 0x92, 0xFF, 0x18, 0x10, 0x08, 0x40, ++0x08, 0x1B, 0x0D, 0x00, 0x1C, 0xF0, 0x16, 0x00, 0xEC, 0xE1, 0x10, 0x00, 0x1C, 0x10, 0x08, 0x40, 0x30, 0xB8, 0x0B, 0x00, ++0x84, 0x10, 0x08, 0x40, 0x00, 0xF0, 0x16, 0x00, 0x80, 0x10, 0x08, 0x40, 0xFF, 0x00, 0x00, 0x00, 0x58, 0x00, 0x10, 0x40, ++0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x50, 0x41, 0x54, 0x43, 0x48, 0x5F, 0x54, 0x42, 0x34, 0x00, ++0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x38, 0x1B, 0x16, 0x00, 0x99, 0x12, 0x10, 0x00, 0x98, 0x19, 0x16, 0x00, ++0xA9, 0x23, 0x10, 0x00, 0x18, 0x1B, 0x16, 0x00, 0x81, 0x07, 0x10, 0x00, 0x20, 0x1B, 0x16, 0x00, 0xCD, 0x09, 0x10, 0x00, ++0x28, 0x1B, 0x16, 0x00, 0xF1, 0x0B, 0x10, 0x00, 0xB0, 0x19, 0x16, 0x00, 0x21, 0x25, 0x10, 0x00, 0x70, 0x1A, 0x16, 0x00, ++0xB9, 0x30, 0x10, 0x00, 0x6C, 0x1A, 0x16, 0x00, 0x19, 0x64, 0x10, 0x00, 0xE0, 0x1A, 0x16, 0x00, 0xB9, 0x69, 0x10, 0x00, ++0xE0, 0x19, 0x16, 0x00, 0xCB, 0x09, 0x10, 0x00, 0xDC, 0x19, 0x16, 0x00, 0xC9, 0x09, 0x10, 0x00, 0x38, 0x19, 0x16, 0x00, ++0x89, 0x54, 0x10, 0x00, 0x1C, 0x1B, 0x16, 0x00, 0x69, 0x56, 0x10, 0x00, 0x24, 0x1B, 0x16, 0x00, 0x75, 0x58, 0x10, 0x00, ++0x7C, 0x1D, 0x16, 0x00, 0xDD, 0x5B, 0x10, 0x00, 0xB0, 0x1A, 0x16, 0x00, 0xB9, 0x5A, 0x10, 0x00, 0xB0, 0x1D, 0x16, 0x00, ++0x31, 0x6D, 0x10, 0x00, 0x8C, 0x1D, 0x16, 0x00, 0x19, 0x6E, 0x10, 0x00, 0x88, 0x1D, 0x16, 0x00, 0x49, 0x6E, 0x10, 0x00, ++0x40, 0x19, 0x16, 0x00, 0xF5, 0x6E, 0x10, 0x00, 0x2C, 0x1B, 0x16, 0x00, 0x51, 0x6F, 0x10, 0x00, 0x80, 0x1D, 0x16, 0x00, ++0xC1, 0x5F, 0x10, 0x00, 0xF4, 0x19, 0x16, 0x00, 0x89, 0x6F, 0x10, 0x00, 0xEC, 0x19, 0x16, 0x00, 0x0D, 0x70, 0x10, 0x00, ++0x54, 0x19, 0x16, 0x00, 0x31, 0x93, 0x10, 0x00, 0x14, 0x1B, 0x16, 0x00, 0x35, 0x94, 0x10, 0x00, 0x8C, 0x19, 0x16, 0x00, ++0xE9, 0x71, 0x10, 0x00, 0x88, 0x19, 0x16, 0x00, 0xB9, 0x7A, 0x10, 0x00, 0x04, 0x1B, 0x16, 0x00, 0x35, 0x97, 0x10, 0x00, ++0x90, 0x19, 0x16, 0x00, 0xFD, 0x9E, 0x10, 0x00, 0x94, 0x19, 0x16, 0x00, 0x5D, 0x9F, 0x10, 0x00, 0xE8, 0x19, 0x16, 0x00, ++0x3D, 0xA2, 0x10, 0x00, 0xE4, 0x1A, 0x16, 0x00, 0x35, 0x02, 0x10, 0x00, 0xD4, 0x1A, 0x16, 0x00, 0x69, 0xA2, 0x10, 0x00, ++0x64, 0x1A, 0x16, 0x00, 0x29, 0x33, 0x10, 0x00, 0x08, 0x1B, 0x16, 0x00, 0x55, 0x91, 0x10, 0x00, 0xBC, 0x19, 0x16, 0x00, ++0x31, 0x38, 0x10, 0x00, 0x68, 0x1A, 0x16, 0x00, 0x79, 0x61, 0x10, 0x00, 0x40, 0x1A, 0x16, 0x00, 0x8D, 0x40, 0x10, 0x00, ++0x3C, 0x1A, 0x16, 0x00, 0x41, 0x07, 0x10, 0x00, 0x4C, 0x1A, 0x16, 0x00, 0x85, 0x54, 0x10, 0x00, 0xB8, 0x19, 0x16, 0x00, ++0x9D, 0x3B, 0x10, 0x00, 0x7C, 0x1A, 0x16, 0x00, 0x41, 0x2A, 0x10, 0x00, 0x68, 0xAD, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x4D, 0x4F, 0x44, 0x45, 0x5F, 0x54, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ++0x09, 0x00, 0x00, 0x00, 0xA4, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x54, 0xE0, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xA8, 0xE5, 0x10, 0x00, ++0x02, 0x00, 0x00, 0x00, 0xB8, 0xE5, 0x10, 0x00, 0x60, 0xE3, 0x16, 0x00, 0xBC, 0xE5, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, ++0xAC, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xE5, 0x10, 0x00, 0x20, 0x60, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, ++0x54, 0x5F, 0x50, 0x4F, 0x57, 0x45, 0x52, 0x5F, 0x4F, 0x4E, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, ++0x3C, 0x00, 0x50, 0x40, 0x00, 0x00, 0x08, 0x00, 0x24, 0x01, 0x50, 0x40, 0x40, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, ++0x54, 0x5F, 0x50, 0x41, 0x54, 0x43, 0x48, 0x5F, 0x54, 0x41, 0x46, 0x00, 0x05, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, ++0x24, 0x0A, 0x16, 0x00, 0x65, 0x7E, 0x10, 0x00, 0xA4, 0x12, 0x16, 0x00, 0x1D, 0x84, 0x10, 0x00, 0xBC, 0x12, 0x16, 0x00, ++0xFD, 0xA3, 0x10, 0x00, 0xC4, 0x12, 0x16, 0x00, 0xE9, 0xB2, 0x10, 0x00, 0x0C, 0x08, 0x16, 0x00, 0x1D, 0xA3, 0x10, 0x00, ++0x5C, 0x07, 0x16, 0x00, 0x45, 0xA3, 0x10, 0x00, 0x84, 0x15, 0x16, 0x00, 0xB9, 0x89, 0x10, 0x00, 0x4C, 0x18, 0x16, 0x00, ++0x65, 0x8B, 0x10, 0x00, 0x6C, 0x18, 0x16, 0x00, 0xE9, 0x8B, 0x10, 0x00, 0xDC, 0x18, 0x16, 0x00, 0x35, 0x8C, 0x10, 0x00, ++0xF4, 0x1A, 0x16, 0x00, 0x99, 0x05, 0x10, 0x00, 0xAC, 0x12, 0x16, 0x00, 0x35, 0x76, 0x10, 0x00, 0x04, 0x10, 0x16, 0x00, ++0xD1, 0x8E, 0x10, 0x00, 0x0C, 0x10, 0x16, 0x00, 0x25, 0x90, 0x10, 0x00, 0x84, 0x10, 0x16, 0x00, 0x41, 0xAA, 0x10, 0x00, ++0x9C, 0x10, 0x16, 0x00, 0xB1, 0xAA, 0x10, 0x00, 0xA4, 0x10, 0x16, 0x00, 0x71, 0xAB, 0x10, 0x00, 0x4C, 0x10, 0x16, 0x00, ++0x5D, 0xAC, 0x10, 0x00, 0xE4, 0x0F, 0x16, 0x00, 0x65, 0x90, 0x10, 0x00, 0xEC, 0x13, 0x16, 0x00, 0xC5, 0xA7, 0x10, 0x00, ++0x0C, 0x13, 0x16, 0x00, 0x55, 0xB3, 0x10, 0x00, 0xFC, 0x12, 0x16, 0x00, 0x1D, 0x26, 0x10, 0x00, 0x74, 0x0A, 0x16, 0x00, ++0xED, 0x27, 0x10, 0x00, 0x74, 0x13, 0x16, 0x00, 0x35, 0xA8, 0x10, 0x00, 0x04, 0x14, 0x16, 0x00, 0xD9, 0xA8, 0x10, 0x00, ++0x4C, 0x14, 0x16, 0x00, 0xB1, 0xAE, 0x10, 0x00, 0x3C, 0x0A, 0x16, 0x00, 0x05, 0xAF, 0x10, 0x00, 0x44, 0x0A, 0x16, 0x00, ++0xF1, 0xAF, 0x10, 0x00, 0x04, 0x15, 0x16, 0x00, 0x51, 0x91, 0x10, 0x00, 0x2C, 0x13, 0x16, 0x00, 0xA1, 0x42, 0x10, 0x00, ++0xD4, 0x0A, 0x16, 0x00, 0xED, 0xAD, 0x10, 0x00, 0x44, 0x11, 0x16, 0x00, 0x51, 0xAD, 0x10, 0x00, 0xE4, 0x12, 0x16, 0x00, ++0x09, 0xA7, 0x10, 0x00, 0x7C, 0x09, 0x16, 0x00, 0x15, 0xCD, 0x10, 0x00, 0x8C, 0x09, 0x16, 0x00, 0x4D, 0xCD, 0x10, 0x00, ++0x94, 0x09, 0x16, 0x00, 0xC1, 0xCD, 0x10, 0x00, 0x6C, 0x14, 0x16, 0x00, 0x71, 0xCD, 0x10, 0x00, 0x70, 0x30, 0x50, 0x40, ++0x00, 0x00, 0x00, 0x00, 0x74, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x78, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, ++0x7C, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x56, 0x45, 0x52, 0x5F, 0x49, 0x4E, ++0x46, 0x4F, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2D, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, 0x33, ++0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x33, 0x38, 0x3A, 0x33, 0x39, 0x20, 0x2D, 0x20, 0x67, 0x69, 0x74, ++0x20, 0x30, 0x61, 0x61, 0x62, 0x66, 0x62, 0x66, 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, ++}; ++ ++char fw_patch_u03[59704] = { ++0x10, 0xB5, 0x15, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0x13, 0x4B, 0x1B, 0x68, ++0x3F, 0x22, 0x9A, 0x5C, 0x00, 0x2A, 0xF6, 0xD1, 0x3D, 0x32, 0x9C, 0x5C, 0x10, 0x4B, 0x1A, 0x78, 0x01, 0x32, 0xD2, 0xB2, ++0x10, 0x2A, 0x10, 0xD8, 0x1A, 0x70, 0x0D, 0x49, 0x0A, 0x78, 0x12, 0x03, 0x92, 0xB2, 0x62, 0x23, 0x63, 0x43, 0x0B, 0x4C, ++0x1C, 0x19, 0x22, 0x80, 0x0A, 0x78, 0x12, 0x09, 0x09, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x1A, 0x80, 0xDD, 0xE7, 0x05, 0x4B, ++0x00, 0x22, 0x1A, 0x70, 0xEB, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0xC1, 0xE9, 0x0A, 0x00, 0x28, 0x27, 0x16, 0x00, ++0xB0, 0xE6, 0x10, 0x00, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x0B, 0x4B, 0x1B, 0x68, ++0x00, 0x2B, 0x03, 0xD0, 0x3A, 0x22, 0x9B, 0x5C, 0x01, 0x2B, 0x06, 0xD0, 0x20, 0x00, 0x08, 0x4B, 0x98, 0x47, 0x62, 0x68, ++0x07, 0x4B, 0x1A, 0x60, 0x10, 0xBD, 0x07, 0x49, 0x0B, 0x68, 0x07, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, ++0x0B, 0x60, 0xEF, 0xE7, 0x18, 0x27, 0x16, 0x00, 0x25, 0xC3, 0x0C, 0x00, 0x30, 0xE6, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, ++0xFF, 0xFF, 0xDF, 0xFF, 0x10, 0xB5, 0x18, 0x4A, 0x00, 0x23, 0x00, 0x24, 0x14, 0x57, 0x84, 0x42, 0x04, 0xDA, 0x01, 0x33, ++0xDB, 0xB2, 0x01, 0x32, 0x08, 0x2B, 0xF6, 0xD1, 0x12, 0x4A, 0xD2, 0x56, 0x82, 0x42, 0x05, 0xD0, 0x00, 0x29, 0x03, 0xD1, ++0x00, 0x2B, 0x01, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x1A, 0x1C, 0x07, 0x2B, 0x00, 0xD9, 0x07, 0x22, 0xD2, 0xB2, 0x0C, 0x4B, ++0x99, 0x5C, 0x0C, 0x4A, 0x95, 0x23, 0x9B, 0x00, 0xD3, 0x5C, 0x1A, 0x1C, 0xDB, 0xB2, 0x8B, 0x42, 0x00, 0xD9, 0x0A, 0x1C, ++0x07, 0x49, 0x08, 0x4B, 0xCB, 0x5C, 0x18, 0x1C, 0xDB, 0xB2, 0xD1, 0xB2, 0x8B, 0x42, 0x00, 0xD2, 0x10, 0x1C, 0xC0, 0xB2, ++0x10, 0xBD, 0xC0, 0x46, 0x28, 0xE0, 0x10, 0x00, 0xBC, 0xDF, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x55, 0x02, 0x00, 0x00, ++0x10, 0xB5, 0x62, 0x22, 0x42, 0x43, 0x0F, 0x4B, 0x9C, 0x46, 0x62, 0x44, 0x13, 0x88, 0xDB, 0xB2, 0x1E, 0x2B, 0x13, 0xD0, ++0x0C, 0x49, 0x0D, 0x48, 0x0C, 0x5C, 0x0D, 0x48, 0x09, 0x5C, 0x09, 0x19, 0x01, 0x20, 0x8B, 0x42, 0x09, 0xDB, 0x1B, 0x1B, ++0xDB, 0xB2, 0x10, 0x2B, 0x08, 0xD0, 0x11, 0x88, 0xFF, 0x20, 0x81, 0x43, 0x0B, 0x43, 0x13, 0x80, 0x00, 0x20, 0x10, 0xBD, ++0x0E, 0x3B, 0xE9, 0xE7, 0x0E, 0x33, 0xF4, 0xE7, 0x0C, 0x65, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, 0x57, 0x02, 0x00, 0x00, ++0x55, 0x02, 0x00, 0x00, 0x30, 0xB5, 0x62, 0x22, 0x42, 0x43, 0x0F, 0x4B, 0x9C, 0x46, 0x62, 0x44, 0x13, 0x88, 0xDB, 0xB2, ++0x1E, 0x2B, 0x12, 0xD0, 0x0C, 0x49, 0x0D, 0x48, 0x0C, 0x5C, 0x1D, 0x19, 0x03, 0x38, 0x09, 0x5C, 0x01, 0x20, 0x8D, 0x42, ++0x08, 0xDC, 0xEB, 0xB2, 0x10, 0x2B, 0x08, 0xD0, 0x11, 0x88, 0xFF, 0x20, 0x81, 0x43, 0x0B, 0x43, 0x13, 0x80, 0x00, 0x20, ++0x30, 0xBD, 0x0E, 0x3B, 0xEA, 0xE7, 0x0E, 0x33, 0xF4, 0xE7, 0xC0, 0x46, 0x0C, 0x65, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, ++0x57, 0x02, 0x00, 0x00, 0x70, 0x47, 0x70, 0x47, 0x70, 0xB5, 0x00, 0x28, 0x1C, 0xD0, 0x12, 0x4B, 0x1D, 0x68, 0x00, 0x2D, ++0x18, 0xD0, 0xE9, 0x78, 0x09, 0x02, 0x01, 0x23, 0x19, 0x43, 0x03, 0x33, 0xFF, 0x22, 0x0E, 0x48, 0x81, 0xF7, 0xFA, 0xFE, ++0x04, 0x1E, 0x0E, 0xD0, 0x20, 0x00, 0x81, 0xF7, 0x1F, 0xFF, 0xAB, 0xF7, 0x23, 0xFB, 0x03, 0x00, 0x09, 0x48, 0x6A, 0x68, ++0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x43, 0x60, 0xD6, 0xF7, 0x9E, 0xFE, 0x70, 0xBD, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xE9, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x3F, 0x06, 0x00, 0x00, 0xFC, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x05, 0x00, 0x22, 0x4B, 0x23, 0x4A, 0x13, 0x60, 0x02, 0x22, 0xFF, 0x32, 0x9C, 0x5C, ++0x21, 0x4B, 0xE2, 0x18, 0x12, 0x01, 0x13, 0x88, 0x9B, 0x06, 0x5B, 0x0F, 0x01, 0x2B, 0x04, 0xD0, 0x13, 0x88, 0x9B, 0x06, ++0x5B, 0x0F, 0x02, 0x2B, 0x0F, 0xD1, 0x23, 0x01, 0x18, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x1B, 0x7B, 0x00, 0x2B, 0x05, 0xD1, ++0x13, 0x88, 0x38, 0x21, 0x8B, 0x43, 0x20, 0x39, 0x0B, 0x43, 0x13, 0x80, 0x15, 0x48, 0x83, 0xF7, 0xB9, 0xFF, 0x15, 0x4B, ++0x2A, 0x68, 0x9A, 0x42, 0x0F, 0xD0, 0x14, 0x4F, 0xDE, 0x26, 0x76, 0x00, 0x00, 0x23, 0xBB, 0x51, 0x28, 0x00, 0xD7, 0xF7, ++0x4B, 0xF9, 0x11, 0x4B, 0xBB, 0x51, 0xAB, 0xF7, 0xD5, 0xFA, 0xA4, 0x00, 0x0F, 0x4B, 0x18, 0x51, 0xF8, 0xBD, 0x0F, 0x4B, ++0x1B, 0x68, 0x02, 0x2B, 0xEB, 0xD1, 0x2B, 0x7C, 0x9B, 0x00, 0x0D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x68, 0x0C, 0x4A, ++0x12, 0x68, 0x1A, 0x66, 0x1A, 0x61, 0xE0, 0xE7, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0x00, 0x10, 0x06, 0x04, ++0xF8, 0xCD, 0x10, 0x00, 0xD1, 0x1F, 0x0D, 0x00, 0x28, 0x19, 0x16, 0x00, 0x35, 0x02, 0x10, 0x00, 0xE0, 0xE5, 0x10, 0x00, ++0x50, 0xE0, 0x10, 0x00, 0xF4, 0x29, 0x16, 0x00, 0xE8, 0xE1, 0x10, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x04, 0x1E, 0x32, 0xD0, ++0x9E, 0x23, 0xC5, 0x5C, 0x1B, 0x4B, 0x00, 0x93, 0x43, 0x68, 0x01, 0x93, 0x83, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1D, 0x76, ++0x04, 0x95, 0x18, 0x4B, 0x03, 0x93, 0x83, 0x7D, 0x6A, 0x46, 0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, 0x93, 0x75, ++0xB0, 0x22, 0x82, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, 0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, 0xD7, 0xF7, ++0xFB, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x47, 0x3A, 0x6A, 0x43, 0x0C, 0x4B, 0x9C, 0x46, 0x62, 0x44, ++0x13, 0x88, 0xFF, 0x21, 0x8B, 0x43, 0x01, 0x21, 0x0B, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0xA0, 0x23, 0xE1, 0x54, 0x09, 0xB0, ++0x30, 0xBD, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xF6, 0xE7, 0xD1, 0xBD, 0x10, 0x00, ++0xDE, 0x05, 0x00, 0x00, 0x1E, 0x65, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x03, 0x00, 0x0D, 0x00, ++0x89, 0x00, 0x2B, 0x4A, 0x8C, 0x58, 0x00, 0x2C, 0x36, 0xD0, 0xA6, 0x22, 0xA2, 0x5C, 0x12, 0x1A, 0x03, 0x20, 0x10, 0x40, ++0xC0, 0x18, 0x00, 0x01, 0x00, 0x09, 0x63, 0x68, 0xC3, 0x1A, 0x1A, 0x01, 0x12, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8A, 0x42, ++0x26, 0xD8, 0x1B, 0x01, 0x20, 0x2B, 0x23, 0xD9, 0x20, 0x4B, 0x00, 0x93, 0x01, 0x90, 0xA3, 0x68, 0x02, 0x93, 0x6B, 0x46, ++0x1D, 0x76, 0x04, 0x95, 0x1D, 0x4B, 0x03, 0x93, 0xA3, 0x7D, 0x6A, 0x46, 0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, ++0x93, 0x75, 0xB0, 0x22, 0xA2, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, 0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, ++0xD7, 0xF7, 0xA0, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x9F, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x01, 0xD0, ++0x09, 0xB0, 0x30, 0xBD, 0xA3, 0x6F, 0x9B, 0xB2, 0x62, 0x21, 0x4D, 0x43, 0x0D, 0x4A, 0xAA, 0x18, 0x13, 0x80, 0xA3, 0x6F, ++0x1B, 0x0C, 0x0C, 0x4A, 0xAA, 0x18, 0x13, 0x80, 0x0B, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x0B, 0x4B, 0x1B, 0x68, 0xDB, 0x03, ++0xFF, 0x22, 0xD2, 0x03, 0x1A, 0x40, 0x23, 0x6D, 0x13, 0x43, 0x9B, 0xB2, 0x2B, 0x80, 0xE3, 0xE7, 0x38, 0xE6, 0x10, 0x00, ++0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, ++0xC8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x00, 0x28, 0x08, 0xD0, 0x08, 0x4B, 0x98, 0x47, 0x08, 0x4B, 0x1B, 0x68, 0xD9, 0x6A, ++0x05, 0x20, 0xD7, 0xF7, 0x5B, 0xFF, 0x10, 0xBD, 0x05, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0xF7, 0xE7, 0xC0, 0x46, 0x85, 0xC0, 0x0A, 0x00, 0x18, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x04, 0x4B, ++0x98, 0x47, 0x04, 0x4B, 0x1B, 0x68, 0x59, 0x6B, 0x06, 0x20, 0xD7, 0xF7, 0x43, 0xFF, 0x10, 0xBD, 0xA5, 0xD7, 0x0A, 0x00, ++0x24, 0x27, 0x16, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x04, 0x1E, 0x5A, 0xD0, 0x9F, 0x23, 0xC3, 0x5C, 0x01, 0x2B, 0x04, 0xD0, ++0xA0, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x09, 0xB0, 0x30, 0xBD, 0x9D, 0x33, 0xC5, 0x5C, 0x2B, 0x4B, 0x00, 0x93, 0x43, 0x68, ++0x01, 0x93, 0x83, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1D, 0x76, 0x04, 0x95, 0x27, 0x4B, 0x03, 0x93, 0x83, 0x7D, 0x6A, 0x46, ++0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, 0x93, 0x75, 0xB0, 0x22, 0x82, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, ++0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, 0xD7, 0xF7, 0x1A, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, ++0x9F, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0xD3, 0xD1, 0x23, 0x6D, 0x01, 0x33, 0x5B, 0x08, 0xA2, 0x6F, 0x91, 0xB2, 0x62, 0x22, ++0x55, 0x43, 0x17, 0x4A, 0xAA, 0x18, 0x11, 0x80, 0xA2, 0x6F, 0x12, 0x0C, 0x15, 0x49, 0x69, 0x18, 0x0A, 0x80, 0x15, 0x4A, ++0x94, 0x46, 0x65, 0x44, 0x01, 0x33, 0x5B, 0x08, 0x13, 0x4A, 0x13, 0x43, 0x9B, 0xB2, 0x2B, 0x80, 0x9F, 0x23, 0xE3, 0x5C, ++0x01, 0x2B, 0xB7, 0xD1, 0xA5, 0x33, 0xE2, 0x5C, 0x01, 0x32, 0xA3, 0x3B, 0x13, 0x40, 0x9E, 0x22, 0xA1, 0x5C, 0x9C, 0x3A, ++0x0C, 0x48, 0xD7, 0xF7, 0x3D, 0xF9, 0xAA, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xA8, 0xE7, 0x0A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA4, 0xE7, 0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, 0xFA, 0x64, 0x61, 0x40, ++0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0x7D, 0x03, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x00, 0x09, 0x01, 0x4B, 0x18, 0x56, 0x70, 0x47, 0x28, 0xE0, 0x10, 0x00, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, ++0xC0, 0xB5, 0x8A, 0x46, 0x5B, 0x49, 0x09, 0x78, 0x06, 0x29, 0x23, 0xD0, 0x5A, 0x49, 0x0C, 0x78, 0x01, 0x2C, 0x07, 0xD0, ++0x20, 0x21, 0x55, 0x46, 0x69, 0x5C, 0x1E, 0x29, 0x08, 0xD8, 0x56, 0x49, 0x01, 0x25, 0x0D, 0x70, 0x20, 0x21, 0x55, 0x46, ++0x69, 0x5C, 0x1F, 0x29, 0x00, 0xD9, 0x9B, 0xE0, 0x52, 0x4F, 0xE6, 0x25, 0x6D, 0x00, 0x00, 0x21, 0x79, 0x51, 0x51, 0x46, ++0x50, 0x4E, 0xB0, 0x47, 0x50, 0x4B, 0x7B, 0x51, 0x4C, 0x4B, 0x1C, 0x70, 0x00, 0x20, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xF0, 0xBD, 0x00, 0x21, 0xE5, 0x20, 0x81, 0xF7, 0xC8, 0xFD, 0x80, 0x46, 0x00, 0x28, 0x14, 0xD0, 0x20, 0x23, ++0x52, 0x46, 0xD7, 0x5C, 0x04, 0x33, 0xD1, 0x5C, 0x53, 0x8C, 0xC9, 0x18, 0x89, 0xB2, 0x45, 0x4B, 0x9C, 0x46, 0x61, 0x44, ++0x3A, 0x00, 0x40, 0x46, 0xD8, 0xF7, 0xDC, 0xFB, 0x00, 0x2F, 0x64, 0xD0, 0x45, 0x46, 0x41, 0x4B, 0x99, 0x46, 0x14, 0xE0, ++0x3B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xE3, 0xE7, 0x05, 0x2C, 0x27, 0xD0, 0x4B, 0x46, ++0x1A, 0x88, 0x3B, 0x4B, 0x9A, 0x42, 0x36, 0xD0, 0xE2, 0x43, 0xBF, 0x18, 0xFF, 0xB2, 0x01, 0x34, 0x2D, 0x19, 0x00, 0x2F, ++0x4B, 0xD0, 0x2C, 0x78, 0x6E, 0x78, 0x16, 0x2E, 0xED, 0xD0, 0xFF, 0x2E, 0xED, 0xD1, 0x0D, 0x2C, 0xEB, 0xD1, 0xAB, 0x78, ++0x5D, 0x2B, 0xE8, 0xD1, 0xEB, 0x78, 0x00, 0x2B, 0xE5, 0xD1, 0x2B, 0x79, 0x03, 0x2B, 0xE2, 0xD1, 0x6B, 0x79, 0x00, 0x2B, ++0xDF, 0xD1, 0x2D, 0x48, 0x83, 0xF7, 0xB6, 0xFD, 0x2C, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xD7, 0xE7, 0xAB, 0x78, ++0x01, 0x2B, 0xD4, 0xD1, 0xEB, 0x78, 0xFD, 0x2B, 0xD1, 0xD1, 0x2B, 0x79, 0x00, 0x2B, 0xCE, 0xD1, 0x6B, 0x79, 0x01, 0x2B, ++0xCB, 0xD1, 0x25, 0x48, 0x83, 0xF7, 0xA2, 0xFD, 0x22, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xC3, 0xE7, 0x1D, 0x4B, ++0x5B, 0x88, 0xB3, 0x42, 0xC4, 0xD1, 0x1B, 0x4B, 0x9B, 0x68, 0x00, 0x2B, 0x0C, 0xD0, 0x19, 0x4B, 0x9A, 0x79, 0xA9, 0x1C, ++0x98, 0x68, 0xD8, 0xF7, 0x5F, 0xFB, 0x00, 0x28, 0xB8, 0xD1, 0x18, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xB3, 0xE7, ++0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEB, 0xE7, 0x20, 0x23, 0x52, 0x46, 0xD3, 0x5C, ++0x00, 0x2B, 0x03, 0xD1, 0x40, 0x46, 0x81, 0xF7, 0xEB, 0xFD, 0x73, 0xE7, 0x50, 0x8C, 0xBA, 0xF7, 0xAD, 0xFD, 0xF7, 0xE7, ++0x53, 0x46, 0x58, 0x8C, 0xBA, 0xF7, 0xA8, 0xFD, 0x6A, 0xE7, 0xC0, 0x46, 0xD0, 0xE5, 0x10, 0x00, 0x59, 0xA9, 0x16, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x45, 0xF8, 0x0B, 0x00, 0x99, 0x05, 0x10, 0x00, 0x00, 0x00, 0x61, 0x40, 0xC4, 0xE5, 0x10, 0x00, ++0x88, 0xAC, 0x00, 0x00, 0x10, 0xCE, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x00, 0xCE, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, ++0x07, 0x4E, 0x8A, 0x25, 0x6D, 0x00, 0x00, 0x21, 0x71, 0x51, 0x21, 0x00, 0xB3, 0xF7, 0xF0, 0xFC, 0xA4, 0x00, 0x04, 0x4B, ++0xE3, 0x58, 0x04, 0x4A, 0xDA, 0x61, 0x04, 0x4B, 0x73, 0x51, 0x70, 0xBD, 0x28, 0x19, 0x16, 0x00, 0x54, 0x27, 0x16, 0x00, ++0x21, 0x61, 0x10, 0x00, 0x41, 0x07, 0x10, 0x00, 0x10, 0xB5, 0xD2, 0x23, 0x5B, 0x00, 0x1B, 0x68, 0x98, 0x47, 0x10, 0xBD, ++0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0xE3, 0xB0, 0x01, 0xAC, 0xC2, 0x25, 0x6D, 0x00, 0x2A, 0x00, 0x00, 0x21, ++0x20, 0x00, 0x7F, 0xF7, 0xAB, 0xFC, 0x7A, 0x4E, 0x2A, 0x00, 0x00, 0x21, 0x30, 0x68, 0x7F, 0xF7, 0xA5, 0xFC, 0x31, 0x68, ++0x2A, 0x00, 0x01, 0xA8, 0xD8, 0xF7, 0x14, 0xFB, 0x75, 0x48, 0x83, 0xF7, 0x1D, 0xFD, 0x50, 0x22, 0x00, 0x21, 0x4E, 0xA8, ++0x7F, 0xF7, 0x98, 0xFC, 0x00, 0x26, 0x9A, 0x23, 0x5B, 0x00, 0xE6, 0x54, 0x4E, 0xA9, 0x00, 0x20, 0x8B, 0xF7, 0x3A, 0xF8, ++0x86, 0x3D, 0xC0, 0x23, 0x5B, 0x00, 0xE5, 0x54, 0x80, 0x3B, 0xFF, 0x3B, 0x98, 0x46, 0x82, 0x33, 0xFF, 0x33, 0x42, 0x46, ++0xE2, 0x54, 0x03, 0x27, 0x82, 0x23, 0xFF, 0x33, 0xE7, 0x54, 0x0D, 0x3B, 0xE7, 0x54, 0x36, 0x23, 0xFF, 0x33, 0x99, 0x46, ++0xE6, 0x54, 0x4E, 0xA9, 0x00, 0x20, 0x87, 0xF7, 0x6B, 0xFE, 0x4B, 0x46, 0xE0, 0x5C, 0x4E, 0xA9, 0x8B, 0xF7, 0x6A, 0xF8, ++0x50, 0x22, 0x00, 0x21, 0x3A, 0xA8, 0x7F, 0xF7, 0x6D, 0xFC, 0xE4, 0x23, 0xE6, 0x54, 0x3A, 0xA9, 0x00, 0x20, 0x8B, 0xF7, ++0x11, 0xF8, 0x32, 0x23, 0xFF, 0x33, 0xE5, 0x54, 0x30, 0x3B, 0xFF, 0x3B, 0x99, 0x22, 0x52, 0x00, 0xA3, 0x54, 0x02, 0x3A, ++0xA3, 0x54, 0x0C, 0x3A, 0xA3, 0x54, 0x19, 0x3D, 0x43, 0x46, 0x63, 0x55, 0x3A, 0xA9, 0x01, 0x20, 0x87, 0xF7, 0x48, 0xFE, ++0x60, 0x5D, 0x3A, 0xA9, 0x8B, 0xF7, 0x48, 0xF8, 0x4E, 0x4B, 0x1E, 0x60, 0x4E, 0x4D, 0x2E, 0x60, 0x4E, 0x4B, 0x42, 0x46, ++0x1A, 0x60, 0x4E, 0x49, 0x0B, 0x68, 0x4E, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x4C, 0x4C, ++0x27, 0x60, 0x4C, 0x4B, 0x19, 0x68, 0x4C, 0x48, 0xD7, 0xF7, 0x60, 0xFE, 0x0F, 0x23, 0x03, 0x40, 0x22, 0x68, 0x80, 0x21, ++0x8A, 0x43, 0x0A, 0x43, 0x22, 0x60, 0x06, 0x09, 0xFF, 0x22, 0x16, 0x40, 0x46, 0x4F, 0x3E, 0x60, 0x00, 0x0B, 0x10, 0x40, ++0x28, 0x60, 0x5A, 0x08, 0x9B, 0x1A, 0x1B, 0x01, 0x9B, 0x18, 0x43, 0x4A, 0x13, 0x60, 0x23, 0x68, 0x8B, 0x43, 0x23, 0x60, ++0x41, 0x4B, 0x1B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x3F, 0x4A, 0x13, 0x6F, 0x71, 0x39, 0x8B, 0x43, 0x0D, 0x39, 0x0B, 0x43, ++0x13, 0x67, 0x3C, 0x4B, 0x5B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x3A, 0x4A, 0x53, 0x6F, 0x0F, 0x21, 0x8B, 0x43, 0x0D, 0x39, ++0x0B, 0x43, 0x53, 0x67, 0x36, 0x4B, 0x9B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x34, 0x4A, 0x93, 0x6F, 0x0F, 0x21, 0x8B, 0x43, ++0x0D, 0x39, 0x0B, 0x43, 0x93, 0x67, 0x31, 0x4B, 0xDB, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x2F, 0x4A, 0xD3, 0x6F, 0x0F, 0x21, ++0x8B, 0x43, 0x0D, 0x39, 0x0B, 0x43, 0xD3, 0x67, 0x2B, 0x4B, 0x19, 0x69, 0x0F, 0x24, 0xA1, 0x43, 0x03, 0x20, 0x01, 0x43, ++0x19, 0x61, 0x59, 0x69, 0xA1, 0x43, 0x01, 0x43, 0x59, 0x61, 0x99, 0x69, 0xA1, 0x43, 0x01, 0x43, 0x99, 0x61, 0xDA, 0x69, ++0xA2, 0x43, 0x02, 0x43, 0xDA, 0x61, 0x18, 0x4B, 0x07, 0x22, 0x1A, 0x60, 0x01, 0xAA, 0x00, 0x23, 0x20, 0x21, 0x53, 0x54, ++0x06, 0x93, 0x05, 0x93, 0x02, 0x93, 0x01, 0x93, 0x15, 0x4A, 0x13, 0x68, 0x1E, 0x39, 0x0B, 0x43, 0x13, 0x60, 0x1B, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x03, 0xD0, 0x13, 0x68, 0x1E, 0x31, 0x0B, 0x43, 0x13, 0x60, 0x18, 0x4B, 0x9A, 0x68, 0x84, 0x23, ++0x17, 0x49, 0xD1, 0x50, 0x17, 0x4B, 0x80, 0x22, 0x92, 0x01, 0x1A, 0x60, 0xC2, 0x22, 0x05, 0x4B, 0x18, 0x68, 0x52, 0x00, ++0x01, 0xA9, 0xD8, 0xF7, 0x2F, 0xFA, 0x63, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0xFC, 0xE1, 0x10, 0x00, ++0x20, 0xCE, 0x10, 0x00, 0x08, 0x20, 0x04, 0x40, 0x04, 0x20, 0x04, 0x40, 0x24, 0x20, 0x04, 0x40, 0x10, 0x20, 0x04, 0x40, ++0xFF, 0xFE, 0xFF, 0xFF, 0x0C, 0x20, 0x04, 0x40, 0xB8, 0xE5, 0x10, 0x00, 0x00, 0x75, 0x19, 0x03, 0x00, 0x20, 0x04, 0x40, ++0x28, 0x20, 0x04, 0x40, 0x00, 0x30, 0x50, 0x40, 0xBC, 0xE5, 0x10, 0x00, 0x00, 0xED, 0x00, 0xE0, 0xC5, 0x88, 0x08, 0x00, ++0x00, 0xE1, 0x00, 0xE0, 0x70, 0x47, 0x70, 0x47, 0x3D, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, 0x3E, 0x4B, 0x8D, 0x22, 0x12, 0x03, ++0x1A, 0x60, 0x3D, 0x4B, 0x3D, 0x4A, 0x1A, 0x60, 0x3D, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, 0x3E, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, ++0x3E, 0x4B, 0x3F, 0x4A, 0x1A, 0x60, 0x3F, 0x4B, 0x3F, 0x4A, 0x1A, 0x60, 0x3F, 0x4B, 0x40, 0x4A, 0x1A, 0x60, 0x40, 0x4B, ++0x40, 0x4A, 0x1A, 0x60, 0x40, 0x4B, 0x41, 0x4A, 0x1A, 0x60, 0x41, 0x4B, 0x41, 0x4A, 0x1A, 0x60, 0x41, 0x4B, 0x42, 0x4A, ++0x1A, 0x60, 0x42, 0x4B, 0x42, 0x4A, 0x1A, 0x60, 0x42, 0x4B, 0x43, 0x4A, 0x1A, 0x60, 0x43, 0x4B, 0x43, 0x4A, 0x1A, 0x60, ++0x43, 0x4B, 0x44, 0x4A, 0x1A, 0x60, 0x44, 0x4B, 0x44, 0x4A, 0x1A, 0x60, 0x44, 0x4B, 0x45, 0x4A, 0x1A, 0x60, 0x45, 0x4B, ++0x45, 0x4A, 0x1A, 0x60, 0x45, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x88, 0x22, ++0x52, 0x01, 0x1A, 0x60, 0x45, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x46, 0x4A, 0x13, 0x60, 0x46, 0x4A, 0x47, 0x49, ++0x11, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4B, 0x47, 0x4A, 0x1A, 0x60, ++0x47, 0x4B, 0x48, 0x4A, 0x1A, 0x60, 0x48, 0x4B, 0x48, 0x4A, 0x1A, 0x60, 0x48, 0x4B, 0x49, 0x4A, 0x1A, 0x60, 0x49, 0x4B, ++0x49, 0x4A, 0x1A, 0x60, 0x49, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0xFF, 0x22, ++0x12, 0x02, 0x1A, 0x60, 0x49, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x74, 0x22, ++0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4B, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0x04, 0x01, 0x58, 0x40, ++0xFB, 0x33, 0x09, 0x00, 0x1C, 0x20, 0x62, 0x40, 0x28, 0x20, 0x62, 0x40, 0x20, 0x20, 0x91, 0x48, 0x14, 0x20, 0x62, 0x40, ++0x83, 0x89, 0x01, 0x00, 0x54, 0x20, 0x62, 0x40, 0x34, 0x8F, 0x00, 0x00, 0x48, 0x07, 0x62, 0x40, 0xA0, 0x01, 0x1A, 0x02, ++0x28, 0x07, 0x62, 0x40, 0x20, 0x00, 0x01, 0x00, 0x38, 0x07, 0x62, 0x40, 0xD4, 0x0F, 0x80, 0x04, 0x3C, 0x07, 0x62, 0x40, ++0x64, 0x00, 0xC8, 0x00, 0x2C, 0x20, 0x62, 0x40, 0x20, 0xB2, 0x0C, 0x00, 0x0C, 0x20, 0x62, 0x40, 0x45, 0x2B, 0xAD, 0xE9, ++0x30, 0x20, 0x62, 0x40, 0xD2, 0x30, 0x0C, 0x14, 0x34, 0x20, 0x62, 0x40, 0x02, 0x16, 0x00, 0x00, 0x54, 0x07, 0x62, 0x40, ++0xFD, 0x20, 0x42, 0x21, 0x58, 0x07, 0x62, 0x40, 0x1E, 0xF0, 0x07, 0x00, 0x1C, 0x07, 0x62, 0x40, 0x33, 0x0A, 0x00, 0x00, ++0x18, 0x20, 0x62, 0x40, 0x24, 0x41, 0x12, 0x00, 0x0C, 0x00, 0x62, 0x40, 0x00, 0x00, 0x04, 0x04, 0x90, 0x00, 0x62, 0x40, ++0x82, 0x90, 0x06, 0x00, 0x34, 0x10, 0x62, 0x40, 0x80, 0x30, 0x00, 0x02, 0x14, 0x10, 0x62, 0x40, 0x7A, 0x11, 0x45, 0x04, ++0x24, 0x20, 0x62, 0x40, 0x04, 0x20, 0x62, 0x40, 0xC0, 0xA9, 0x01, 0x00, 0x34, 0x08, 0x50, 0x00, 0x8C, 0x04, 0x60, 0x40, ++0x10, 0x01, 0x60, 0x40, 0x58, 0x00, 0x7E, 0x02, 0x80, 0x08, 0x60, 0x40, 0x84, 0x08, 0x60, 0x40, 0x88, 0x08, 0x60, 0x40, ++0x8C, 0x08, 0x60, 0x40, 0x34, 0x08, 0x00, 0x00, 0x18, 0x05, 0x62, 0x40, 0x0A, 0x88, 0x92, 0x36, 0x14, 0x05, 0x62, 0x40, ++0x10, 0x1A, 0x0C, 0xA8, 0x2C, 0x05, 0x62, 0x40, 0x03, 0x14, 0x0C, 0x9C, 0x0C, 0x05, 0x62, 0x40, 0x13, 0x20, 0x20, 0x20, ++0xA0, 0x05, 0x62, 0x40, 0x00, 0x0C, 0x15, 0x14, 0xA4, 0x05, 0x62, 0x40, 0x24, 0x36, 0x2D, 0x36, 0xF0, 0x05, 0x62, 0x40, ++0x08, 0x05, 0x62, 0x40, 0x32, 0x31, 0x55, 0x54, 0x30, 0x05, 0x62, 0x40, 0x00, 0x12, 0x17, 0x13, 0x34, 0x05, 0x62, 0x40, ++0xB0, 0x05, 0x62, 0x40, 0x55, 0x53, 0x00, 0x00, 0x1C, 0x05, 0x62, 0x40, 0x66, 0x57, 0x4B, 0x96, 0x2A, 0x49, 0x0B, 0x68, ++0x2A, 0x4A, 0x1A, 0x40, 0xFC, 0x23, 0x9B, 0x05, 0x13, 0x43, 0x0B, 0x60, 0x28, 0x4B, 0x29, 0x4A, 0x1A, 0x60, 0x29, 0x4B, ++0x29, 0x4A, 0x1A, 0x60, 0x29, 0x4B, 0x2A, 0x4A, 0x1A, 0x60, 0x2A, 0x4B, 0x2A, 0x4A, 0x1A, 0x60, 0x2A, 0x4B, 0x2B, 0x4A, ++0x1A, 0x60, 0x2B, 0x4B, 0x2B, 0x4A, 0x1A, 0x60, 0x2B, 0x4B, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x2C, 0x49, 0x11, 0x60, ++0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4B, 0x2D, 0x4A, 0x1A, 0x60, 0x2D, 0x4B, ++0x2D, 0x4A, 0x1A, 0x60, 0x2D, 0x4B, 0x2E, 0x4A, 0x1A, 0x60, 0x2E, 0x4B, 0x2E, 0x4A, 0x1A, 0x60, 0x2E, 0x4B, 0x2F, 0x4A, ++0x1A, 0x60, 0x2F, 0x4B, 0x2F, 0x4A, 0x1A, 0x60, 0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x30, 0x4A, 0x1A, 0x60, ++0x30, 0x4B, 0xFF, 0x22, 0x12, 0x02, 0x1A, 0x60, 0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x76, 0x22, 0x1A, 0x60, ++0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x31, 0x4A, 0x1A, 0x60, 0x31, 0x4B, ++0x31, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x0C, 0x00, 0x58, 0x40, 0xFF, 0xFF, 0xFF, 0xC0, 0x04, 0x01, 0x58, 0x40, ++0xFB, 0x33, 0x09, 0x00, 0x20, 0x40, 0x34, 0x40, 0x77, 0x0B, 0x00, 0x00, 0x24, 0x40, 0x34, 0x40, 0x94, 0xC5, 0x6E, 0x00, ++0x28, 0x40, 0x34, 0x40, 0x02, 0x94, 0x00, 0x00, 0x2C, 0x40, 0x34, 0x40, 0x84, 0x18, 0x20, 0x56, 0x30, 0x40, 0x34, 0x40, ++0x68, 0x51, 0x2E, 0x1A, 0x34, 0x08, 0x50, 0x00, 0x8C, 0x04, 0x60, 0x40, 0x10, 0x01, 0x60, 0x40, 0x58, 0x00, 0x7E, 0x02, ++0x80, 0x08, 0x60, 0x40, 0x84, 0x08, 0x60, 0x40, 0x88, 0x08, 0x60, 0x40, 0x8C, 0x08, 0x60, 0x40, 0x34, 0x08, 0x00, 0x00, ++0x18, 0x05, 0x62, 0x40, 0x0A, 0x88, 0x92, 0x36, 0x14, 0x05, 0x62, 0x40, 0x10, 0x1A, 0x0C, 0xA8, 0x2C, 0x05, 0x62, 0x40, ++0x03, 0x14, 0x0C, 0x9C, 0x0C, 0x05, 0x62, 0x40, 0x13, 0x20, 0x20, 0x20, 0x08, 0x05, 0x62, 0x40, 0x32, 0x31, 0x55, 0x54, ++0xA0, 0x05, 0x62, 0x40, 0x00, 0x16, 0x17, 0x0F, 0xA4, 0x05, 0x62, 0x40, 0x36, 0x36, 0x28, 0x36, 0xF0, 0x05, 0x62, 0x40, ++0x30, 0x05, 0x62, 0x40, 0x00, 0x1A, 0x17, 0x13, 0x34, 0x05, 0x62, 0x40, 0xB0, 0x05, 0x62, 0x40, 0x55, 0x53, 0x00, 0x00, ++0x1C, 0x05, 0x62, 0x40, 0x66, 0x57, 0x4B, 0x96, 0x90, 0x00, 0x62, 0x40, 0x32, 0x00, 0x05, 0x00, 0x10, 0x10, 0x62, 0x40, ++0x43, 0x01, 0x00, 0x12, 0x10, 0xB5, 0x01, 0x28, 0x03, 0xD0, 0x02, 0x38, 0x01, 0x28, 0x05, 0xD9, 0x10, 0xBD, 0x87, 0xF7, ++0x99, 0xFF, 0xFF, 0xF7, 0x2B, 0xFE, 0xF9, 0xE7, 0x88, 0xF7, 0x96, 0xF8, 0x0A, 0x4A, 0x11, 0x68, 0x80, 0x23, 0xDB, 0x05, ++0x0B, 0x43, 0x13, 0x60, 0xFF, 0xF7, 0x32, 0xFF, 0x07, 0x4B, 0x1B, 0x68, 0x9B, 0x02, 0xEB, 0xD4, 0x05, 0x49, 0x0B, 0x68, ++0x05, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0xE2, 0xE7, 0xC0, 0x46, 0x1C, 0x20, 0x34, 0x40, ++0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0x7F, 0xFF, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, ++0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x00, 0x24, 0x25, 0x4A, 0x26, 0x4B, 0x9B, 0x46, 0xE0, 0x23, 0xDB, 0x04, 0x9A, 0x46, ++0xC0, 0x23, 0x9B, 0x05, 0x99, 0x46, 0x23, 0x4B, 0x98, 0x46, 0x23, 0x4B, 0x00, 0x93, 0x23, 0x4F, 0x23, 0x4E, 0x13, 0x68, ++0x58, 0x46, 0x03, 0x40, 0x50, 0x46, 0x20, 0x40, 0x03, 0x43, 0x13, 0x60, 0x13, 0x68, 0x48, 0x46, 0x03, 0x43, 0x13, 0x60, ++0x43, 0x46, 0x1B, 0x68, 0x00, 0x98, 0x00, 0x68, 0x1B, 0x04, 0x3B, 0x40, 0x40, 0x04, 0x40, 0x0C, 0x03, 0x43, 0x08, 0xC5, ++0x13, 0x68, 0x33, 0x40, 0x13, 0x60, 0x80, 0x23, 0x5B, 0x04, 0x9C, 0x46, 0x64, 0x44, 0x80, 0x23, 0xDB, 0x04, 0x9C, 0x42, ++0xDF, 0xD1, 0x04, 0x20, 0x01, 0x9B, 0x01, 0x2B, 0x06, 0xD0, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, ++0xAB, 0x46, 0xF0, 0xBD, 0x0E, 0x4B, 0x1B, 0x68, 0x0B, 0x61, 0x0E, 0x4B, 0x1B, 0x68, 0x4B, 0x61, 0x0D, 0x4B, 0x1B, 0x68, ++0x8B, 0x61, 0x0D, 0x4B, 0x1B, 0x68, 0xCB, 0x61, 0x0C, 0x4B, 0x1B, 0x68, 0x0B, 0x62, 0x05, 0x30, 0xE7, 0xE7, 0xC0, 0x46, ++0x28, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0xFF, 0xF8, 0x8C, 0x08, 0x62, 0x40, 0x90, 0x08, 0x62, 0x40, 0x00, 0x00, 0xFF, 0x7F, ++0xFF, 0xFF, 0xFF, 0xCF, 0x30, 0x07, 0x62, 0x40, 0x34, 0x07, 0x62, 0x40, 0x5C, 0x07, 0x62, 0x40, 0x60, 0x07, 0x62, 0x40, ++0x20, 0x20, 0x62, 0x40, 0x12, 0x04, 0x12, 0x4B, 0x1A, 0x40, 0x49, 0x04, 0x49, 0x0C, 0x0A, 0x43, 0x10, 0x4B, 0x1A, 0x60, ++0x10, 0x4B, 0x1A, 0x68, 0x00, 0x06, 0xE0, 0x21, 0xC9, 0x04, 0x08, 0x40, 0x0E, 0x49, 0x0A, 0x40, 0x10, 0x43, 0x18, 0x60, ++0x19, 0x68, 0x80, 0x22, 0x12, 0x06, 0x0A, 0x43, 0x1A, 0x60, 0x19, 0x68, 0x80, 0x22, 0xD2, 0x05, 0x0A, 0x43, 0x1A, 0x60, ++0x1A, 0x68, 0x08, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x52, 0x00, 0x52, 0x08, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, ++0x00, 0x00, 0xFF, 0x7F, 0x44, 0x05, 0x62, 0x40, 0x28, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x1C, 0x49, 0x0B, 0x68, 0x99, 0x46, 0x1C, 0x4A, ++0x1A, 0x40, 0x1C, 0x4B, 0x13, 0x43, 0x0B, 0x60, 0x1B, 0x4B, 0x1B, 0x68, 0x98, 0x46, 0x1B, 0x4B, 0x1B, 0x68, 0x9A, 0x46, ++0x00, 0x24, 0xF0, 0x23, 0x47, 0x46, 0x9F, 0x43, 0x16, 0x4E, 0xE5, 0xB2, 0x00, 0x22, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, ++0xB1, 0xFF, 0x23, 0x01, 0x3B, 0x43, 0x33, 0x60, 0x88, 0xF7, 0x3D, 0xF9, 0x69, 0x46, 0x01, 0xA8, 0x88, 0xF7, 0x4A, 0xF9, ++0x00, 0x9A, 0x01, 0x99, 0x28, 0x00, 0xFF, 0xF7, 0xA3, 0xFF, 0x01, 0x34, 0x04, 0x2C, 0xE8, 0xD1, 0x07, 0x4B, 0x4A, 0x46, ++0x1A, 0x60, 0x09, 0x4B, 0x42, 0x46, 0x1A, 0x60, 0x08, 0x4B, 0x52, 0x46, 0x1A, 0x60, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x1C, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0x8F, 0x7F, 0x0A, 0x00, 0x20, 0x00, ++0x08, 0x05, 0x62, 0x40, 0x04, 0x00, 0x62, 0x40, 0x70, 0xB5, 0x0C, 0x4D, 0x2C, 0x68, 0x2A, 0x68, 0x0B, 0x4E, 0x32, 0x40, ++0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x2B, 0x60, 0x26, 0x20, 0x88, 0xF7, 0x3F, 0xFF, 0xFF, 0xF7, 0xA7, 0xFF, 0x88, 0xF7, ++0x81, 0xFF, 0x2B, 0x68, 0xE4, 0x05, 0xE4, 0x0F, 0x24, 0x02, 0x33, 0x40, 0x1C, 0x43, 0x2C, 0x60, 0x70, 0xBD, 0xC0, 0x46, ++0x00, 0x04, 0x60, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0x10, 0xB5, 0x26, 0x20, 0x88, 0xF7, 0x62, 0xF9, 0xFF, 0xF7, 0x92, 0xFF, ++0x88, 0xF7, 0xBA, 0xF9, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, ++0x8B, 0xB0, 0x82, 0x46, 0x0C, 0x00, 0x03, 0x68, 0x7F, 0x22, 0x1A, 0x40, 0x93, 0x46, 0x1E, 0x09, 0x0F, 0x25, 0x2E, 0x40, ++0x1D, 0x40, 0x01, 0x95, 0x0C, 0x22, 0x13, 0x42, 0x05, 0xD0, 0x35, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0x01, 0x9B, 0x9E, 0x42, 0x05, 0xD9, 0x30, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x2E, 0x4B, 0x98, 0x46, 0x1F, 0x68, 0x1A, 0x68, 0x2D, 0x4B, 0x99, 0x46, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, ++0x42, 0x46, 0x13, 0x60, 0x58, 0x46, 0x88, 0xF7, 0xF1, 0xFE, 0x53, 0x46, 0x19, 0x68, 0x03, 0xA8, 0x89, 0xF7, 0x0E, 0xF9, ++0x88, 0xF7, 0x30, 0xFF, 0x43, 0x46, 0x1B, 0x68, 0xFF, 0x05, 0xFF, 0x0F, 0x3F, 0x02, 0x4A, 0x46, 0x13, 0x40, 0x1F, 0x43, ++0x43, 0x46, 0x1F, 0x60, 0x01, 0x9B, 0x9E, 0x42, 0x30, 0xD8, 0x37, 0x00, 0x20, 0x36, 0x36, 0x01, 0x1D, 0x4B, 0xF6, 0x18, ++0x03, 0xA9, 0x1D, 0x4B, 0x98, 0x46, 0xF0, 0x23, 0x1B, 0x05, 0x9C, 0x46, 0x23, 0x1D, 0x99, 0x46, 0x05, 0xE0, 0x01, 0x37, ++0x10, 0x36, 0xFB, 0xB2, 0x01, 0x9A, 0x9A, 0x42, 0x1C, 0xD3, 0x7B, 0x18, 0x1A, 0x7D, 0x12, 0x02, 0xDB, 0x7B, 0x1A, 0x43, ++0x43, 0x46, 0x1A, 0x43, 0x32, 0x60, 0x7B, 0x5C, 0x18, 0x05, 0x65, 0x46, 0x28, 0x40, 0x1B, 0x07, 0x5B, 0x0F, 0x5B, 0x07, ++0x03, 0x43, 0x70, 0x68, 0x00, 0x02, 0x00, 0x0A, 0x03, 0x43, 0x73, 0x60, 0x00, 0x2C, 0xE2, 0xD0, 0xFB, 0x00, 0xE2, 0x50, ++0x4A, 0x46, 0x70, 0x68, 0xD0, 0x50, 0xDC, 0xE7, 0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0x00, 0x04, 0x60, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xD8, 0x99, 0x16, 0x00, ++0x00, 0x00, 0x80, 0x80, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x05, 0x00, ++0x01, 0x91, 0x03, 0x68, 0x5A, 0x02, 0x52, 0x0E, 0x90, 0x46, 0x1C, 0x09, 0x0F, 0x26, 0x34, 0x40, 0x1E, 0x40, 0x0C, 0x22, ++0x13, 0x42, 0x05, 0xD0, 0x38, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xB4, 0x42, 0x2F, 0xD9, ++0x34, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x40, 0x46, 0x88, 0xF7, 0xAD, 0xF8, 0x29, 0x68, ++0x02, 0xA8, 0x88, 0xF7, 0x09, 0xFB, 0x88, 0xF7, 0x03, 0xF9, 0x80, 0x22, 0x52, 0x00, 0x2D, 0x49, 0x2D, 0x48, 0xD7, 0xF7, ++0x49, 0xFE, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x01, 0x35, 0xEB, 0xB2, ++0x9E, 0x42, 0xEE, 0xD3, 0x2B, 0x01, 0xA8, 0x00, 0x63, 0x44, 0x1A, 0x68, 0x22, 0x40, 0x02, 0xA9, 0x41, 0x58, 0x00, 0x91, ++0xC9, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x01, 0x9B, 0x00, 0x2B, 0xED, 0xD0, 0x1A, 0x50, 0xEB, 0xE7, 0x40, 0x46, 0x88, 0xF7, ++0x83, 0xF8, 0x29, 0x68, 0x02, 0xA8, 0x88, 0xF7, 0xDF, 0xFA, 0x25, 0x00, 0xA2, 0x00, 0x02, 0xAB, 0x9C, 0x46, 0x62, 0x44, ++0xFC, 0x23, 0x1B, 0x01, 0x98, 0x46, 0xF8, 0x23, 0x5B, 0x02, 0x9C, 0x46, 0x3F, 0x20, 0xF8, 0x23, 0x9B, 0x03, 0x9B, 0x46, ++0x13, 0x68, 0x1F, 0x0A, 0x41, 0x46, 0x0F, 0x40, 0xB9, 0x46, 0xD9, 0x00, 0x0F, 0x00, 0x61, 0x46, 0x0F, 0x40, 0xBA, 0x46, ++0x4F, 0x46, 0x51, 0x46, 0x0F, 0x43, 0xB9, 0x46, 0x19, 0x0D, 0x0F, 0x00, 0x07, 0x40, 0xBA, 0x46, 0x4F, 0x46, 0x51, 0x46, ++0x0F, 0x43, 0x5B, 0x03, 0x59, 0x46, 0x0B, 0x40, 0x3B, 0x43, 0x08, 0xC2, 0x01, 0x34, 0xE4, 0xB2, 0xA6, 0x42, 0xE1, 0xD2, ++0x88, 0xF7, 0xAC, 0xF8, 0x02, 0x4B, 0x9C, 0x46, 0x03, 0x4C, 0xB5, 0xE7, 0x28, 0x19, 0x16, 0x00, 0xD8, 0x97, 0x16, 0x00, ++0x00, 0x50, 0x1E, 0x00, 0x7F, 0x00, 0x00, 0xE0, 0x70, 0xB5, 0x8E, 0xB0, 0x87, 0xF7, 0x76, 0xFF, 0x04, 0x00, 0x01, 0x28, ++0x05, 0xD0, 0x83, 0x1E, 0xDB, 0xB2, 0x01, 0x2B, 0x24, 0xD9, 0x0E, 0xB0, 0x70, 0xBD, 0x1C, 0x4B, 0x00, 0x93, 0x1C, 0x4C, ++0x25, 0x68, 0xF0, 0x23, 0x2A, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x70, 0x22, 0x13, 0x43, 0x23, 0x60, 0x01, 0xA9, 0x68, 0x46, ++0xFF, 0xF7, 0x56, 0xFF, 0x25, 0x60, 0x16, 0x4B, 0x00, 0x93, 0x00, 0x21, 0x68, 0x46, 0x88, 0xF7, 0xE9, 0xFC, 0x00, 0x20, ++0x88, 0xF7, 0xD0, 0xFB, 0x05, 0xA9, 0x01, 0x20, 0xFF, 0xF7, 0xB0, 0xFD, 0x01, 0x20, 0x89, 0xF7, 0x43, 0xFA, 0xFF, 0xF7, ++0xAF, 0xFE, 0xDA, 0xE7, 0x0A, 0x4B, 0x00, 0x93, 0x0A, 0x4D, 0x2E, 0x68, 0xF0, 0x23, 0x32, 0x00, 0x9A, 0x43, 0x13, 0x00, ++0x70, 0x22, 0x13, 0x43, 0x2B, 0x60, 0x01, 0xA9, 0x68, 0x46, 0xFF, 0xF7, 0xA9, 0xFE, 0x2E, 0x60, 0x20, 0x00, 0x89, 0xF7, ++0x2D, 0xFA, 0xFF, 0xF7, 0x7B, 0xFE, 0xC4, 0xE7, 0x03, 0x42, 0x26, 0x00, 0x08, 0x05, 0x62, 0x40, 0x0F, 0x30, 0x02, 0x00, ++0x30, 0xB5, 0x83, 0xB0, 0x41, 0x4B, 0x18, 0x78, 0x87, 0xF7, 0x12, 0xFF, 0x40, 0x4A, 0x80, 0x23, 0x5B, 0x00, 0x06, 0x21, ++0xD1, 0x50, 0x3F, 0x4B, 0x5A, 0x68, 0x3F, 0x49, 0x0A, 0x40, 0x5A, 0x60, 0x59, 0x68, 0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, ++0x5A, 0x60, 0x19, 0x00, 0x44, 0x22, 0x0B, 0x6B, 0x13, 0x40, 0x04, 0x2B, 0xFB, 0xD1, 0x39, 0x4B, 0x18, 0x68, 0x39, 0x49, ++0xD7, 0xF7, 0x32, 0xF9, 0xA0, 0x23, 0x5B, 0x03, 0x03, 0x43, 0x37, 0x4A, 0x13, 0x60, 0x37, 0x49, 0x08, 0x43, 0x10, 0x60, ++0x13, 0x60, 0x30, 0x4B, 0x59, 0x68, 0x35, 0x4A, 0x0A, 0x43, 0x5A, 0x60, 0x2C, 0x49, 0x9A, 0x22, 0x52, 0x00, 0x80, 0x20, ++0x40, 0x01, 0x88, 0x50, 0x1A, 0x68, 0x40, 0x20, 0x02, 0x43, 0x1A, 0x60, 0x18, 0x68, 0x02, 0x24, 0x20, 0x43, 0x18, 0x60, ++0x48, 0x6F, 0x01, 0x22, 0x10, 0x43, 0x48, 0x67, 0x59, 0x6D, 0x2B, 0x4A, 0x11, 0x40, 0x59, 0x65, 0x5A, 0x6D, 0x22, 0x43, ++0x5A, 0x65, 0x5A, 0x6D, 0x28, 0x49, 0x0A, 0x40, 0x5A, 0x65, 0x87, 0xF7, 0xE1, 0xFE, 0x04, 0x00, 0x80, 0x22, 0x52, 0x00, ++0x25, 0x49, 0x26, 0x48, 0xD7, 0xF7, 0x4C, 0xFD, 0x80, 0x22, 0x25, 0x49, 0x25, 0x48, 0xD7, 0xF7, 0x47, 0xFD, 0x01, 0x2C, ++0x05, 0xD1, 0x17, 0x4B, 0xDB, 0x6D, 0x9B, 0x07, 0x0D, 0xD5, 0x03, 0xB0, 0x30, 0xBD, 0xC0, 0x22, 0x92, 0x00, 0x20, 0x49, ++0x20, 0x48, 0xD7, 0xF7, 0x39, 0xFD, 0x80, 0x22, 0x1F, 0x49, 0x20, 0x48, 0xD7, 0xF7, 0x34, 0xFD, 0xED, 0xE7, 0x20, 0x00, ++0x87, 0xF7, 0xD2, 0xFE, 0x20, 0x00, 0xFF, 0xF7, 0xF1, 0xFC, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0xFF, 0xF7, 0x39, 0xFF, 0x05, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0xDF, 0xD1, 0x16, 0x4A, 0x13, 0x68, 0x01, 0x21, ++0x8B, 0x43, 0x13, 0x60, 0xD9, 0xE7, 0xC0, 0x46, 0xB4, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, ++0xFF, 0xFF, 0xFB, 0xFF, 0xB0, 0x06, 0x16, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x08, 0x00, 0x58, 0x40, 0x00, 0x00, 0x14, 0x80, ++0x02, 0x88, 0x01, 0x00, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x58, 0xE0, 0x10, 0x00, 0xD8, 0x97, 0x16, 0x00, ++0x58, 0xE1, 0x10, 0x00, 0xD8, 0x98, 0x16, 0x00, 0x18, 0xE2, 0x10, 0x00, 0xD8, 0x99, 0x16, 0x00, 0x18, 0xE5, 0x10, 0x00, ++0x58, 0x99, 0x16, 0x00, 0x04, 0x30, 0x34, 0x40, 0x80, 0x00, 0x01, 0x4B, 0xC0, 0x58, 0x70, 0x47, 0x38, 0x27, 0x16, 0x00, ++0x80, 0x00, 0x01, 0x4B, 0xC0, 0x58, 0x70, 0x47, 0x54, 0x27, 0x16, 0x00, 0x80, 0x00, 0x01, 0x4B, 0x19, 0x50, 0x70, 0x47, ++0x54, 0x27, 0x16, 0x00, 0x03, 0x23, 0x03, 0x40, 0x8B, 0x42, 0x05, 0xD8, 0x03, 0x23, 0x98, 0x43, 0x40, 0x18, 0x00, 0x01, ++0x00, 0x09, 0x70, 0x47, 0x03, 0x30, 0x03, 0x23, 0x98, 0x43, 0x40, 0x18, 0xF7, 0xE7, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x05, 0x00, 0x0F, 0x00, 0x14, 0x00, 0x06, 0xAB, 0x04, 0xCB, 0x90, 0x46, 0x1A, 0x78, 0x1B, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x01, 0xD0, 0x00, 0x2A, 0x06, 0xD0, 0x18, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x00, 0x21, 0x99, 0x70, 0xD9, 0x70, ++0x5A, 0x70, 0xAB, 0x68, 0x2A, 0x69, 0x94, 0x46, 0x63, 0x44, 0x18, 0x00, 0x13, 0x49, 0xD7, 0xF7, 0x63, 0xF8, 0x06, 0x00, ++0x10, 0x4B, 0x5D, 0x60, 0x9F, 0x60, 0xDC, 0x60, 0x18, 0x61, 0x00, 0x2C, 0x05, 0xD1, 0x0F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0A, 0x4D, 0x21, 0x00, 0x38, 0x00, 0xD7, 0xF7, 0xD6, 0xF8, 0x29, 0x77, 0x43, 0x46, ++0x6B, 0x61, 0xA4, 0x1B, 0x62, 0x01, 0x12, 0x1B, 0x92, 0x00, 0x12, 0x19, 0x90, 0x00, 0x12, 0x18, 0x78, 0x3A, 0xAA, 0x61, ++0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x74, 0xE6, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x80, 0x46, 0x00, 0x91, 0x01, 0x92, 0x99, 0x46, ++0x40, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA3, 0x46, 0xF0, 0xBD, ++0x3C, 0x4B, 0x1E, 0x68, 0xB4, 0x68, 0x00, 0x2C, 0xF4, 0xD0, 0x00, 0x25, 0x1F, 0x23, 0x9B, 0x46, 0x01, 0x27, 0x03, 0xE0, ++0x3B, 0x00, 0x83, 0x40, 0x9C, 0x43, 0x0D, 0xD0, 0x20, 0x00, 0xD7, 0xF7, 0x8B, 0xF9, 0x5B, 0x46, 0x18, 0x1A, 0x43, 0x1C, ++0xDB, 0x00, 0xF3, 0x18, 0x5B, 0x68, 0x00, 0x2B, 0xF0, 0xD0, 0x01, 0x35, 0xED, 0xB2, 0xED, 0xE7, 0x01, 0x2D, 0xDB, 0xD1, ++0x2C, 0x4B, 0x5C, 0x68, 0xA3, 0x68, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1E, 0x00, 0x2B, 0x49, 0x18, 0x00, 0xD6, 0xF7, ++0xFD, 0xFF, 0x05, 0x00, 0x64, 0x68, 0x04, 0x19, 0x27, 0x49, 0x30, 0x00, 0xD7, 0xF7, 0x7C, 0xF8, 0x4B, 0x46, 0x9B, 0x68, ++0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x64, 0x18, 0x4B, 0x46, 0x99, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, ++0x03, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x54, 0xFF, 0x04, 0x00, 0x43, 0x46, 0x1B, 0x68, 0xE1, 0x1A, 0x0A, 0x01, 0x12, 0x09, ++0x80, 0x20, 0x00, 0x05, 0x82, 0x42, 0x11, 0xD8, 0x09, 0x01, 0x0F, 0xD0, 0x15, 0x4A, 0xD1, 0x68, 0xCB, 0x18, 0xE2, 0x1A, ++0x12, 0x01, 0x12, 0x09, 0x82, 0x42, 0x07, 0xD8, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x1A, 0x1B, 0x01, 0x02, 0xD0, 0x64, 0x1A, ++0x24, 0x01, 0x24, 0x09, 0x43, 0x46, 0x1C, 0x60, 0x0C, 0x4B, 0xDA, 0x68, 0x55, 0x1B, 0x68, 0x01, 0x40, 0x1B, 0x80, 0x00, ++0x40, 0x19, 0x82, 0x00, 0x80, 0x18, 0x0B, 0x4A, 0x94, 0x46, 0x60, 0x44, 0x00, 0x9A, 0x10, 0x60, 0xD8, 0x68, 0x60, 0x28, ++0x02, 0xD8, 0x01, 0x9B, 0x18, 0x60, 0x87, 0xE7, 0x24, 0x21, 0xD6, 0xF7, 0xB1, 0xFF, 0x01, 0x9B, 0x18, 0x60, 0x81, 0xE7, ++0x74, 0xE6, 0x10, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x1E, 0xFB, 0xFF, 0xFF, 0x03, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x02, 0xD0, 0x01, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x70, 0x47, 0x74, 0xE6, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x06, 0x00, 0x01, 0x92, 0x38, 0x4B, 0x38, 0x4A, 0x13, 0x60, ++0x9C, 0x68, 0x00, 0x2C, 0x08, 0xD0, 0x43, 0x68, 0x9B, 0x46, 0x36, 0x4B, 0x99, 0x46, 0x36, 0x4B, 0x98, 0x46, 0x33, 0x4B, ++0x9A, 0x46, 0x0F, 0xE0, 0xD5, 0xF7, 0x8C, 0xF9, 0x04, 0x1E, 0x5B, 0xD0, 0x73, 0x68, 0x9B, 0x46, 0xF1, 0xE7, 0x75, 0x60, ++0x53, 0x46, 0x1B, 0x68, 0x9B, 0x68, 0xA3, 0x42, 0x46, 0xD0, 0x24, 0x68, 0x00, 0x2C, 0x47, 0xD0, 0x21, 0x00, 0x30, 0x00, ++0xC8, 0x47, 0x00, 0x28, 0x43, 0xD0, 0x05, 0x28, 0xF0, 0xD0, 0xA3, 0x68, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x00, ++0x41, 0x46, 0x18, 0x00, 0xD6, 0xF7, 0x64, 0xFF, 0x63, 0x68, 0xC5, 0x18, 0x41, 0x46, 0x38, 0x00, 0xD6, 0xF7, 0xE4, 0xFF, ++0xB3, 0x68, 0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x6D, 0x18, 0xB1, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, ++0x03, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0xBE, 0xFE, 0x05, 0x00, 0x5B, 0x46, 0xEB, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x22, ++0x12, 0x05, 0x93, 0x42, 0x04, 0xD9, 0x5B, 0x46, 0x5B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0x01, 0x9A, 0x93, 0x42, ++0xC1, 0xD9, 0x63, 0x7E, 0x0B, 0x2B, 0x03, 0xD8, 0x10, 0x4A, 0xDA, 0x40, 0xD3, 0x07, 0xBA, 0xD4, 0xA3, 0x7D, 0xB2, 0x7D, ++0x01, 0x20, 0x9A, 0x42, 0x07, 0xD8, 0x01, 0x33, 0xB3, 0x75, 0x04, 0xE0, 0xD5, 0xF7, 0x38, 0xF9, 0x04, 0x00, 0xB5, 0xE7, ++0x00, 0x20, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x00, 0x20, 0xF6, 0xE7, ++0x64, 0x2A, 0x16, 0x00, 0x10, 0xE7, 0x10, 0x00, 0x51, 0x62, 0x0D, 0x00, 0x71, 0x02, 0x00, 0x00, 0x6A, 0x0C, 0x00, 0x00, ++0x01, 0x4B, 0x18, 0x68, 0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x1B, 0x68, 0x01, 0x20, 0x18, 0x40, ++0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0x80, 0x07, 0xC0, 0x0F, 0x70, 0x47, 0xC0, 0x46, ++0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0xC0, 0x07, 0x70, 0x47, 0xC0, 0x46, 0x48, 0x30, 0x34, 0x40, ++0x01, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0x70, 0x47, 0x48, 0x30, 0x34, 0x40, 0x02, 0x4B, 0x18, 0x68, 0x40, 0x07, 0xC0, 0x0F, ++0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x03, 0x4B, 0x1B, 0x68, 0x14, 0x20, 0x18, 0x40, 0x43, 0x1E, 0x98, 0x41, ++0xC0, 0xB2, 0x70, 0x47, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0x06, 0xC0, 0x0F, 0x70, 0x47, 0xC0, 0x46, ++0x94, 0x40, 0x04, 0x40, 0x01, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0x70, 0x47, 0x98, 0x40, 0x04, 0x40, 0x10, 0xB5, 0x10, 0x4B, ++0x1A, 0x68, 0x00, 0x23, 0x01, 0x2A, 0x02, 0xD9, 0x01, 0x20, 0x18, 0x40, 0x10, 0xBD, 0xFF, 0xF7, 0xCF, 0xFF, 0x00, 0x23, ++0x00, 0x28, 0xF7, 0xD0, 0xFF, 0xF7, 0xE2, 0xFF, 0x00, 0x28, 0x03, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x05, 0xDA, ++0xFF, 0xF7, 0xB2, 0xFF, 0x01, 0x23, 0x43, 0x40, 0xDB, 0xB2, 0xE9, 0xE7, 0xFF, 0xF7, 0xC2, 0xFF, 0x00, 0x23, 0x00, 0x28, ++0xE4, 0xD0, 0xF3, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0x98, 0x40, 0x04, 0x40, 0x10, 0xB5, 0xFF, 0xF7, 0xB7, 0xFF, 0x00, 0x23, ++0x00, 0x28, 0x02, 0xD1, 0x01, 0x20, 0x18, 0x40, 0x10, 0xBD, 0xFF, 0xF7, 0x99, 0xFF, 0x01, 0x23, 0x43, 0x40, 0xDB, 0xB2, ++0xF6, 0xE7, 0x00, 0x00, 0x05, 0x4B, 0x1B, 0x68, 0x00, 0x28, 0x04, 0xD0, 0x08, 0x22, 0x13, 0x43, 0x02, 0x4A, 0x13, 0x60, ++0x70, 0x47, 0x08, 0x22, 0x93, 0x43, 0xF9, 0xE7, 0x94, 0x40, 0x04, 0x40, 0x04, 0x4A, 0x13, 0x68, 0x40, 0x01, 0x04, 0x49, ++0x0B, 0x40, 0x04, 0x49, 0x08, 0x40, 0x18, 0x43, 0x10, 0x60, 0x70, 0x47, 0x94, 0x40, 0x04, 0x40, 0x1F, 0x00, 0xFE, 0xFF, ++0xE0, 0xFF, 0x01, 0x00, 0x03, 0x4B, 0x1B, 0x68, 0x00, 0x20, 0x01, 0x22, 0x9A, 0x42, 0x40, 0x41, 0xC0, 0xB2, 0x70, 0x47, ++0x50, 0xE0, 0x10, 0x00, 0x02, 0x4B, 0x18, 0x68, 0x43, 0x42, 0x58, 0x41, 0xC0, 0xB2, 0x70, 0x47, 0x50, 0xE0, 0x10, 0x00, ++0x70, 0xB5, 0x01, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x0F, 0xD0, 0x70, 0xBD, 0x0E, 0x4C, 0xEA, 0x25, 0x6D, 0x00, 0x02, 0x22, ++0x02, 0x21, 0x20, 0x00, 0x2B, 0x68, 0x98, 0x47, 0x80, 0x22, 0x2B, 0x68, 0x92, 0x01, 0x00, 0x21, 0x20, 0x00, 0x98, 0x47, ++0xEF, 0xE7, 0x80, 0x21, 0x89, 0x01, 0x06, 0x4C, 0xEA, 0x25, 0x6D, 0x00, 0x0A, 0x00, 0x20, 0x00, 0x2B, 0x68, 0x98, 0x47, ++0x2B, 0x68, 0x02, 0x22, 0x00, 0x21, 0x20, 0x00, 0x98, 0x47, 0xE0, 0xE7, 0x00, 0x10, 0x01, 0x50, 0x70, 0xB5, 0x05, 0x00, ++0x0C, 0x00, 0x39, 0x4B, 0x1B, 0x68, 0x01, 0x20, 0x00, 0x2B, 0x45, 0xD1, 0x00, 0x29, 0x43, 0xD0, 0x00, 0x2D, 0x1A, 0xD0, ++0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x16, 0x00, 0x1E, 0x40, 0x1A, 0x42, 0x4E, 0xD1, 0x72, 0xB6, 0x31, 0x4B, 0x1B, 0x68, ++0x00, 0x2B, 0x41, 0xD1, 0x00, 0x20, 0x00, 0x2E, 0x4A, 0xD1, 0x62, 0xB6, 0x27, 0xE0, 0x20, 0x00, 0xFF, 0xF7, 0xBA, 0xFF, ++0x2B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x28, 0x00, 0x00, 0x2E, 0x20, 0xD1, 0xF3, 0xE7, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, ++0x16, 0x00, 0x1E, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x24, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x1B, 0xD1, 0x01, 0x20, ++0x87, 0xF7, 0x51, 0xFC, 0x20, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x14, 0xD1, 0x01, 0x20, 0x87, 0xF7, 0x4A, 0xFC, 0x28, 0x00, ++0x00, 0x2E, 0x00, 0xD1, 0x62, 0xB6, 0x1C, 0x4A, 0x13, 0x68, 0x01, 0x33, 0x13, 0x60, 0x00, 0x28, 0x1E, 0xD0, 0x00, 0x23, ++0x19, 0x4A, 0x13, 0x60, 0x19, 0x4A, 0x13, 0x60, 0x16, 0x4A, 0x13, 0x60, 0x70, 0xBD, 0x20, 0x00, 0xFF, 0xF7, 0x88, 0xFF, ++0x12, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x01, 0x20, 0x87, 0xF7, 0x2F, 0xFC, 0x01, 0x20, 0xE3, 0xE7, 0x08, 0x00, 0xFF, 0xF7, ++0x7D, 0xFF, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x28, 0x00, 0xB8, 0xE7, 0x0A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xB6, 0xD1, ++0x09, 0x4B, 0x1B, 0x68, 0x00, 0x20, 0x05, 0x2B, 0xDB, 0xD8, 0x08, 0x4B, 0x1C, 0x60, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x07, 0x48, 0x82, 0xF7, 0x2F, 0xFC, 0x00, 0x20, 0xD8, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x54, 0xE6, 0x10, 0x00, 0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x2C, 0xCE, 0x10, 0x00, 0xF0, 0xB5, 0xCE, 0x46, ++0x00, 0xB5, 0x86, 0xB0, 0x2A, 0x4B, 0x1C, 0x68, 0x21, 0x00, 0x2A, 0x48, 0x82, 0xF7, 0x16, 0xFC, 0x03, 0xAA, 0x29, 0x4B, ++0x03, 0xCB, 0x03, 0xC2, 0x1B, 0x88, 0x13, 0x80, 0x00, 0x2C, 0x0D, 0xDB, 0x0A, 0x22, 0x03, 0xA9, 0x25, 0x48, 0xD7, 0xF7, ++0xFD, 0xF9, 0x0A, 0x22, 0x03, 0xA9, 0x24, 0x48, 0xD7, 0xF7, 0xF8, 0xF9, 0x06, 0xB0, 0x04, 0xBC, 0x91, 0x46, 0xF0, 0xBD, ++0xFF, 0x23, 0x1B, 0x04, 0x23, 0x40, 0x80, 0x22, 0x52, 0x02, 0x93, 0x42, 0x11, 0xD0, 0x24, 0x04, 0x24, 0x0C, 0x1D, 0x4B, ++0xE7, 0x18, 0x1D, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0xFB, 0x43, 0xDB, 0x17, 0x1F, 0x40, 0x4E, 0x2C, 0x00, 0xDD, 0x4E, 0x24, ++0x03, 0xAD, 0x00, 0x26, 0x00, 0x23, 0x01, 0x93, 0x1B, 0xE0, 0x24, 0x04, 0x24, 0x0C, 0x16, 0x4B, 0xE7, 0x18, 0x16, 0x4B, ++0x9C, 0x46, 0x64, 0x44, 0xEC, 0xE7, 0x8B, 0x40, 0x1A, 0x43, 0xD2, 0xB2, 0x01, 0x31, 0x08, 0x29, 0x07, 0xD0, 0x88, 0x19, ++0x01, 0x23, 0xB8, 0x42, 0xF5, 0xDB, 0xA0, 0x42, 0xF3, 0xDC, 0x01, 0x9B, 0xF1, 0xE7, 0x4B, 0x46, 0x1A, 0x70, 0x01, 0x35, ++0x08, 0x36, 0x50, 0x2E, 0xBC, 0xD0, 0xA9, 0x46, 0x00, 0x22, 0x00, 0x21, 0xED, 0xE7, 0xC0, 0x46, 0x98, 0x40, 0x04, 0x40, ++0x34, 0xCE, 0x10, 0x00, 0x48, 0xCE, 0x10, 0x00, 0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x94, 0xF6, 0xFF, 0xFF, ++0xA7, 0xF6, 0xFF, 0xFF, 0x8A, 0xF6, 0xFF, 0xFF, 0xB1, 0xF6, 0xFF, 0xFF, 0x10, 0xB5, 0x84, 0xB0, 0x98, 0x4B, 0x1C, 0x68, ++0x21, 0x00, 0x98, 0x48, 0x82, 0xF7, 0xAC, 0xFB, 0x01, 0xAA, 0x97, 0x4B, 0x03, 0xCB, 0x03, 0xC2, 0x1B, 0x88, 0x13, 0x80, ++0x00, 0x2C, 0x0B, 0xDB, 0x0A, 0x22, 0x01, 0xA9, 0x93, 0x48, 0xD7, 0xF7, 0x93, 0xF9, 0x0A, 0x22, 0x01, 0xA9, 0x92, 0x48, ++0xD7, 0xF7, 0x8E, 0xF9, 0x04, 0xB0, 0x10, 0xBD, 0xFF, 0x23, 0x1B, 0x04, 0x23, 0x40, 0x80, 0x22, 0x52, 0x02, 0x93, 0x42, ++0x00, 0xD1, 0x02, 0xE1, 0x24, 0x04, 0x24, 0x0C, 0x8B, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x3C, 0x2C, 0xE4, 0xD8, 0xA4, 0x00, ++0x89, 0x4B, 0x1B, 0x59, 0x9F, 0x46, 0x01, 0xAB, 0x00, 0x22, 0x1A, 0x70, 0x5A, 0x70, 0x9A, 0x70, 0xFC, 0x32, 0xDA, 0x70, ++0xD8, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, 0x1A, 0x70, 0x00, 0x22, 0x5A, 0x70, 0x9A, 0x70, 0xFC, 0x32, 0xDA, 0x70, ++0x14, 0x29, 0xCD, 0xD1, 0x00, 0x22, 0x1A, 0x70, 0xDA, 0x70, 0x1A, 0x71, 0xC8, 0xE7, 0x14, 0x21, 0xEE, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x03, 0x22, 0x5A, 0x70, 0x00, 0x22, 0x9A, 0x70, 0xC0, 0x32, 0xDA, 0x70, 0x14, 0x29, 0xBC, 0xD1, 0x00, 0x22, ++0x1A, 0x70, 0x5A, 0x70, 0xDA, 0x70, 0x1A, 0x71, 0xF0, 0x32, 0x5A, 0x71, 0xB4, 0xE7, 0x14, 0x21, 0xEC, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x00, 0x22, 0x9A, 0x70, 0xDA, 0x70, 0xF0, 0x32, 0x1A, 0x71, 0x14, 0x29, 0xA9, 0xD1, 0xED, 0x3A, 0x1A, 0x70, ++0x00, 0x22, 0x5A, 0x70, 0x1A, 0x71, 0x5A, 0x71, 0xA2, 0xE7, 0x14, 0x21, 0xEE, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, ++0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x1A, 0x71, 0xFC, 0x32, 0x5A, 0x71, 0x14, 0x29, 0x95, 0xD1, 0x00, 0x22, 0x5A, 0x70, ++0x9A, 0x70, 0x5A, 0x71, 0xF0, 0x32, 0x9A, 0x71, 0x8E, 0xE7, 0x14, 0x21, 0xEC, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x03, 0x22, ++0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0xC0, 0x32, 0x5A, 0x71, 0x14, 0x29, 0x00, 0xD0, 0x81, 0xE7, 0x81, 0x3A, 0x5A, 0x70, ++0x00, 0x22, 0x9A, 0x70, 0xDA, 0x70, 0x5A, 0x71, 0xFC, 0x32, 0x9A, 0x71, 0x78, 0xE7, 0x14, 0x21, 0xEA, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x3F, 0x22, 0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0x5A, 0x71, 0xFC, 0x32, 0x9A, 0x71, 0x14, 0x29, 0x00, 0xD0, ++0x6A, 0xE7, 0xF9, 0x3A, 0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x9A, 0x71, 0xC0, 0x32, 0xDA, 0x71, 0x62, 0xE7, 0x14, 0x21, ++0xEA, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x0F, 0x22, 0x1A, 0x71, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0x14, 0x29, 0x00, 0xD0, ++0x56, 0xE7, 0x3F, 0x32, 0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x1A, 0x71, 0xDA, 0x71, 0x4F, 0xE7, 0x14, 0x21, 0xED, 0xE7, ++0x0A, 0x21, 0x01, 0xAB, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0xF0, 0x32, 0xDA, 0x71, 0x14, 0x29, 0x00, 0xD0, 0x43, 0xE7, ++0xE1, 0x3A, 0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0xDA, 0x71, 0x1A, 0x72, 0x3C, 0xE7, 0x14, 0x21, 0xED, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x3F, 0x22, 0x5A, 0x71, 0x00, 0x22, 0x9A, 0x71, 0xDA, 0x71, 0xFC, 0x32, 0x1A, 0x72, 0x14, 0x29, 0x00, 0xD0, ++0x2E, 0xE7, 0xED, 0x3A, 0x1A, 0x71, 0x00, 0x22, 0x5A, 0x71, 0x1A, 0x72, 0x5A, 0x72, 0x27, 0xE7, 0x14, 0x21, 0xEB, 0xE7, ++0x0A, 0x21, 0x01, 0xAB, 0x03, 0x22, 0x9A, 0x71, 0x00, 0x22, 0xDA, 0x71, 0xC0, 0x32, 0x1A, 0x72, 0x14, 0x29, 0x00, 0xD0, ++0x1A, 0xE7, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0x1A, 0x72, 0x5A, 0x72, 0x14, 0xE7, 0x14, 0x21, 0xED, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x00, 0x22, 0xDA, 0x71, 0x1A, 0x72, 0xF0, 0x32, 0x5A, 0x72, 0x14, 0x29, 0x00, 0xD0, 0x08, 0xE7, 0x00, 0x22, ++0x9A, 0x71, 0x5A, 0x72, 0x04, 0xE7, 0x14, 0x21, 0xF0, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, 0xDA, 0x71, 0x00, 0x22, ++0x1A, 0x72, 0x5A, 0x72, 0x14, 0x29, 0x00, 0xD0, 0xF8, 0xE6, 0x0F, 0x32, 0x9A, 0x71, 0x00, 0x22, 0xDA, 0x71, 0xF3, 0xE6, ++0x14, 0x21, 0xEF, 0xE7, 0x01, 0xAB, 0x00, 0x22, 0x1A, 0x70, 0x5A, 0x70, 0x9A, 0x70, 0xDA, 0x70, 0xFC, 0x32, 0x1A, 0x71, ++0xE8, 0xE6, 0x24, 0x04, 0x24, 0x0C, 0x0A, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x3C, 0x2C, 0x00, 0xD9, 0xE0, 0xE6, 0xA4, 0x00, ++0x08, 0x4B, 0x1B, 0x59, 0x9F, 0x46, 0xC0, 0x46, 0x98, 0x40, 0x04, 0x40, 0x34, 0xCE, 0x10, 0x00, 0x48, 0xCE, 0x10, 0x00, ++0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x94, 0xF6, 0xFF, 0xFF, 0x54, 0xCE, 0x10, 0x00, 0x48, 0xCF, 0x10, 0x00, ++0x10, 0xB5, 0x08, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0x06, 0x4B, 0x1A, 0x6B, 0x06, 0x4B, 0x19, 0x68, ++0x01, 0x20, 0x81, 0x43, 0x19, 0x60, 0x19, 0x68, 0x04, 0x48, 0x82, 0xF7, 0x5F, 0xFA, 0xF2, 0xE7, 0xB4, 0xE5, 0x10, 0x00, ++0x00, 0x60, 0x50, 0x40, 0x04, 0x30, 0x34, 0x40, 0x3C, 0xD0, 0x10, 0x00, 0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x4C, 0x4B, ++0x1B, 0x68, 0x01, 0x2B, 0x02, 0xD0, 0x4B, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x4A, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, ++0x13, 0x60, 0xA9, 0xF7, 0x71, 0xFD, 0x48, 0x4B, 0x18, 0x60, 0x5C, 0x60, 0x0C, 0x2D, 0x38, 0xD8, 0xAD, 0x00, 0x46, 0x4B, ++0x5B, 0x59, 0x9F, 0x46, 0x80, 0x23, 0xDB, 0x01, 0x00, 0x21, 0x9C, 0x42, 0x1B, 0xD3, 0x43, 0x4A, 0x13, 0x68, 0x43, 0x49, ++0x19, 0x40, 0x80, 0x23, 0x9B, 0x02, 0x0B, 0x43, 0x13, 0x60, 0x11, 0x68, 0xE3, 0x08, 0xC0, 0x20, 0x40, 0x01, 0x03, 0x40, ++0x76, 0x20, 0x03, 0x43, 0x09, 0x0C, 0x09, 0x04, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x3B, 0x49, 0x19, 0x40, 0x80, 0x23, ++0x1B, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x80, 0x21, 0xC9, 0x01, 0x35, 0x4B, 0x1A, 0x68, 0x35, 0x48, 0x02, 0x40, 0x1A, 0x60, ++0x1A, 0x68, 0xA4, 0x04, 0xA4, 0x0C, 0x0C, 0x43, 0x12, 0x0C, 0x12, 0x04, 0x14, 0x43, 0x1C, 0x60, 0x1A, 0x68, 0x30, 0x49, ++0x11, 0x40, 0x80, 0x22, 0x12, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x70, 0xBD, 0x2D, 0x4B, 0x1B, 0x68, 0x9A, 0x6A, 0x5B, 0x6B, ++0xD2, 0x1A, 0xD5, 0x00, 0x55, 0x19, 0x6D, 0x00, 0x55, 0x19, 0xAD, 0xB2, 0x2A, 0x00, 0x21, 0x00, 0x28, 0x48, 0x82, 0xF7, ++0xF7, 0xF9, 0x23, 0x4B, 0x19, 0x68, 0x23, 0x4E, 0x31, 0x40, 0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, ++0x12, 0x0C, 0x12, 0x04, 0x6D, 0x05, 0x6D, 0x0D, 0x2A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x1D, 0x48, 0x02, 0x40, 0x80, 0x21, ++0x09, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x16, 0x40, 0x1E, 0x60, 0x1A, 0x68, 0xA4, 0x04, 0xA4, 0x0C, 0x80, 0x25, ++0x2D, 0x02, 0x2C, 0x43, 0x12, 0x0C, 0x12, 0x04, 0x14, 0x43, 0x1C, 0x60, 0x1A, 0x68, 0x10, 0x40, 0x01, 0x43, 0x19, 0x60, ++0xC7, 0xE7, 0x0F, 0x4A, 0x13, 0x68, 0x0F, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x10, 0x49, ++0x0C, 0x43, 0xA4, 0xB2, 0x1C, 0x43, 0x14, 0x60, 0x13, 0x68, 0x0A, 0x49, 0x19, 0x40, 0x80, 0x23, 0x1B, 0x03, 0x0B, 0x43, ++0x13, 0x60, 0xB2, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, 0xFC, 0x00, 0x60, 0x40, 0x6C, 0xE6, 0x10, 0x00, ++0x5C, 0xD0, 0x10, 0x00, 0xF8, 0x00, 0x60, 0x40, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xF8, 0xE6, 0x10, 0x00, ++0x50, 0xD0, 0x10, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, ++0x07, 0x00, 0xD4, 0xF7, 0x4B, 0xFD, 0x04, 0x00, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0x3B, 0x4A, 0x13, 0x70, 0x01, 0x21, ++0x01, 0x20, 0xFF, 0xF7, 0xEF, 0xFC, 0x80, 0x46, 0x38, 0x4B, 0x1E, 0x78, 0x02, 0x3E, 0x73, 0x1E, 0x9E, 0x41, 0x76, 0x42, ++0x19, 0x23, 0x1E, 0x40, 0x02, 0x36, 0x00, 0x2C, 0x21, 0xD0, 0x65, 0x68, 0xFB, 0x7D, 0x9A, 0x46, 0xA3, 0x68, 0x99, 0x46, ++0x69, 0x46, 0x01, 0xA8, 0xA9, 0xF7, 0xB0, 0xFC, 0x01, 0x9B, 0x53, 0x44, 0xEB, 0x1A, 0x1B, 0x01, 0x1A, 0x09, 0x5B, 0x00, ++0x9C, 0x1A, 0xA4, 0x00, 0xA4, 0x18, 0xA3, 0x00, 0xE4, 0x18, 0x4B, 0x46, 0x00, 0x9A, 0x9B, 0x1A, 0xE4, 0x18, 0xA4, 0x09, ++0xA6, 0x42, 0x00, 0xD8, 0xA4, 0x1B, 0x80, 0x23, 0x5B, 0x02, 0x9C, 0x42, 0x02, 0xD9, 0x24, 0x4C, 0x00, 0xE0, 0x23, 0x4C, ++0xFF, 0xF7, 0xFC, 0xFB, 0x05, 0x00, 0x43, 0x46, 0x00, 0x2B, 0x12, 0xD0, 0x20, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, ++0x1F, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x0F, 0xD0, 0x0A, 0x2C, 0x16, 0xD8, 0x4F, 0x23, 0x00, 0x22, 0xFA, 0x54, 0x02, 0xB0, ++0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0x01, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xA3, 0xFC, 0xE7, 0xE7, ++0x16, 0x4B, 0x80, 0x22, 0x12, 0x05, 0x1A, 0x60, 0x13, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0x00, 0x25, 0xE6, 0xE7, 0xFF, 0xF7, ++0x0B, 0xFC, 0x00, 0x28, 0xE4, 0xD0, 0xB2, 0xF7, 0xC9, 0xFD, 0x06, 0x23, 0x00, 0x28, 0x05, 0xD1, 0x4A, 0x33, 0xFB, 0x5C, ++0x01, 0x3B, 0x58, 0x42, 0x43, 0x41, 0x05, 0x33, 0x00, 0x2D, 0xD7, 0xD1, 0xCF, 0x2C, 0x01, 0xD8, 0x06, 0x2B, 0xD3, 0xD1, ++0x21, 0x00, 0x18, 0x00, 0xFF, 0xF7, 0xCC, 0xFE, 0xCE, 0xE7, 0xC0, 0x46, 0xB2, 0xE6, 0x10, 0x00, 0xB4, 0xE5, 0x10, 0x00, ++0xFF, 0xFF, 0x00, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x4E, 0x23, ++0x01, 0x22, 0xC2, 0x54, 0x2A, 0x4B, 0x1D, 0x68, 0x2A, 0x4B, 0x1C, 0x68, 0x2A, 0x4B, 0x19, 0x68, 0x2A, 0x4B, 0x1A, 0x68, ++0x2A, 0x4B, 0x00, 0x26, 0x1E, 0x70, 0x00, 0x23, 0x00, 0x2D, 0x05, 0xD0, 0x42, 0x33, 0xEB, 0x5C, 0x01, 0x3B, 0x5D, 0x42, ++0x6B, 0x41, 0xDB, 0xB2, 0x00, 0x2C, 0x03, 0xD0, 0x3A, 0x25, 0x64, 0x5D, 0x01, 0x2C, 0x23, 0xD0, 0x00, 0x24, 0x00, 0x29, ++0x04, 0xD0, 0x3E, 0x34, 0x0D, 0x5D, 0x00, 0x24, 0x01, 0x2D, 0x1D, 0xD0, 0x00, 0x2A, 0x03, 0xD0, 0x2F, 0x21, 0x51, 0x5C, ++0x01, 0x29, 0x1A, 0xD0, 0x00, 0x2B, 0x1D, 0xD0, 0x1A, 0x49, 0x0B, 0x68, 0x1A, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, ++0x13, 0x43, 0x0B, 0x60, 0x18, 0x4B, 0x19, 0x4A, 0x13, 0x60, 0x81, 0x22, 0x52, 0x00, 0x9B, 0x5C, 0x00, 0x2B, 0x18, 0xD0, ++0x4F, 0x23, 0x01, 0x22, 0xC2, 0x54, 0x70, 0xBD, 0x01, 0x23, 0xD9, 0xE7, 0x8C, 0x62, 0x01, 0x34, 0xDE, 0xE7, 0x00, 0x21, ++0x91, 0x62, 0x00, 0x2B, 0xE2, 0xD1, 0x01, 0xE0, 0x00, 0x2C, 0xE7, 0xD0, 0x0A, 0x49, 0x0B, 0x68, 0x0D, 0x4A, 0x1A, 0x40, ++0x80, 0x23, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0xDE, 0xE7, 0xFF, 0xF7, 0x17, 0xFF, 0xE6, 0xE7, 0x24, 0x27, 0x16, 0x00, ++0x18, 0x27, 0x16, 0x00, 0x28, 0x27, 0x16, 0x00, 0x20, 0x27, 0x16, 0x00, 0xB1, 0xE6, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, ++0xFF, 0xFF, 0xDF, 0xFF, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0xFF, 0xFF, 0x7F, 0xFF, 0x02, 0x4B, 0x1B, 0x68, ++0x04, 0x20, 0x18, 0x40, 0x70, 0x47, 0xC0, 0x46, 0x80, 0x40, 0x34, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x01, 0x00, 0x12, 0x48, ++0x82, 0xF7, 0x98, 0xF8, 0x00, 0x2C, 0x1E, 0xD0, 0x10, 0x4B, 0x1A, 0x68, 0x10, 0x48, 0x02, 0x40, 0xD0, 0x21, 0x89, 0x03, ++0x0A, 0x43, 0x1A, 0x60, 0x1C, 0x68, 0x04, 0x40, 0xA0, 0x22, 0x52, 0x03, 0x22, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x02, 0x40, ++0x11, 0x43, 0x19, 0x60, 0x09, 0x49, 0x04, 0x22, 0x0B, 0x68, 0x1A, 0x42, 0xFC, 0xD0, 0x05, 0x49, 0x0B, 0x68, 0x05, 0x4A, ++0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x10, 0xBD, 0x90, 0xD0, 0x10, 0x00, 0x58, 0x40, 0x34, 0x40, ++0xFF, 0xFF, 0xC1, 0xFF, 0x80, 0x40, 0x34, 0x40, 0xF8, 0xB5, 0x04, 0x00, 0x83, 0x7D, 0x02, 0x33, 0x83, 0x75, 0x03, 0x6C, ++0x03, 0x61, 0xB2, 0xF7, 0xF9, 0xFC, 0x00, 0x28, 0x24, 0xD1, 0x20, 0x4E, 0x4C, 0x25, 0x20, 0x4F, 0x20, 0x00, 0xD4, 0xF7, ++0x19, 0xFA, 0x00, 0x28, 0x33, 0xD0, 0x31, 0x00, 0x20, 0x69, 0xD6, 0xF7, 0xFD, 0xF9, 0x63, 0x68, 0x9C, 0x46, 0x60, 0x44, ++0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x63, 0x5B, 0x5B, 0x00, 0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, ++0xE3, 0x60, 0xA3, 0x7D, 0x14, 0x4A, 0x52, 0x78, 0x9B, 0x18, 0xA3, 0x75, 0x10, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0xBE, 0x42, ++0xDE, 0xD1, 0xF8, 0xBD, 0x63, 0x68, 0x18, 0x33, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x18, 0x26, 0x65, 0x68, 0x00, 0x22, ++0x21, 0x69, 0x20, 0x00, 0xFF, 0xF7, 0x3C, 0xFA, 0x63, 0x68, 0xAB, 0x42, 0xCB, 0xD0, 0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, ++0x65, 0x60, 0x18, 0x36, 0x90, 0x2E, 0xEF, 0xD1, 0xC3, 0xE7, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xE3, 0xE7, 0xC0, 0x46, ++0xE2, 0x04, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x10, 0xB5, 0xFF, 0xF7, 0xAB, 0xFF, 0x10, 0xBD, ++0xF8, 0xB5, 0x04, 0x00, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xF8, 0xBD, 0x00, 0x21, 0xD4, 0xF7, 0x6E, 0xFB, ++0xA9, 0xF7, 0x38, 0xFB, 0x23, 0x6C, 0x23, 0x61, 0x60, 0x60, 0x04, 0x26, 0x4C, 0x27, 0x10, 0x4D, 0x20, 0x00, 0xD4, 0xF7, ++0xBF, 0xF9, 0x00, 0x28, 0x15, 0xD0, 0x63, 0x68, 0x04, 0x33, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0xE3, 0x5B, 0x5B, 0x00, ++0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x60, 0xA3, 0x7D, 0x6A, 0x78, 0x9B, 0x18, 0xA3, 0x75, ++0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xE5, 0xD1, 0xD8, 0xE7, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xD4, 0xE7, 0xC0, 0x46, ++0x7C, 0x91, 0x0D, 0x00, 0x70, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x1C, 0xD1, ++0x72, 0xB6, 0x10, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x07, 0xD0, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x05, 0xD0, 0x01, 0x2B, ++0x0D, 0xD0, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, 0x70, 0xBD, 0x00, 0x21, 0xD4, 0xF7, 0x2A, 0xFB, 0x07, 0x4D, 0x28, 0x68, ++0x80, 0xF7, 0x38, 0xF8, 0x00, 0x23, 0x2B, 0x60, 0xF1, 0xE7, 0x4E, 0x23, 0x02, 0x22, 0xC2, 0x54, 0xED, 0xE7, 0x02, 0x4B, ++0x18, 0x68, 0x00, 0x28, 0xE3, 0xD1, 0xEB, 0xE7, 0xF8, 0xE6, 0x10, 0x00, 0xF8, 0xB5, 0x05, 0x00, 0x36, 0x4B, 0x1B, 0x68, ++0x0C, 0x20, 0x00, 0x2B, 0x00, 0xD0, 0xF8, 0xBD, 0x00, 0x21, 0x48, 0x30, 0x7F, 0xF7, 0x7A, 0xFF, 0x31, 0x4B, 0x18, 0x60, ++0x00, 0x28, 0x56, 0xD0, 0xA9, 0xF7, 0xD2, 0xFA, 0x06, 0x00, 0x00, 0x27, 0x2E, 0x4B, 0x1F, 0x60, 0x2E, 0x4B, 0x1F, 0x60, ++0x2B, 0x4B, 0x1C, 0x68, 0x54, 0x22, 0x00, 0x21, 0x20, 0x00, 0x7D, 0xF7, 0x19, 0xFF, 0x2B, 0x68, 0xA3, 0x62, 0x6A, 0x68, ++0x22, 0x63, 0xEA, 0x68, 0xE2, 0x63, 0x2A, 0x68, 0xE2, 0x62, 0xAA, 0x68, 0xA2, 0x63, 0x62, 0x63, 0x1B, 0x01, 0x4C, 0x22, ++0xA3, 0x52, 0x24, 0x4A, 0x22, 0x64, 0x24, 0x4B, 0x63, 0x62, 0x24, 0x4B, 0xE3, 0x61, 0x24, 0x4B, 0x23, 0x62, 0x03, 0x23, ++0x23, 0x76, 0x23, 0x4B, 0x9B, 0x78, 0x02, 0x33, 0xA3, 0x75, 0x22, 0x61, 0xE7, 0x75, 0x05, 0x23, 0x63, 0x76, 0xEF, 0xF3, ++0x10, 0x83, 0x01, 0x22, 0x15, 0x00, 0x1D, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x66, 0x60, 0x00, 0x23, 0xA3, 0x60, ++0x1A, 0x4B, 0xA3, 0x82, 0x4C, 0x23, 0xE0, 0x5A, 0x40, 0x00, 0x80, 0x19, 0x00, 0x01, 0x00, 0x09, 0xE0, 0x60, 0x20, 0x00, ++0xD4, 0xF7, 0x1E, 0xF9, 0x00, 0x28, 0x06, 0xD1, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x00, 0x2D, 0xA9, 0xD1, 0x62, 0xB6, ++0xA7, 0xE7, 0x11, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0C, 0x20, 0xF3, 0xE7, 0x0D, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0C, 0x20, 0x97, 0xE7, 0xC0, 0x46, 0xF8, 0xE6, 0x10, 0x00, ++0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0xE8, 0xFD, 0x00, 0x00, 0xB9, 0x21, 0x10, 0x00, 0xC9, 0x1F, 0x10, 0x00, ++0x05, 0x4B, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x00, 0xA0, 0xFF, 0xFF, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x06, 0x4B, ++0x18, 0x68, 0x00, 0x28, 0x03, 0xD0, 0x4F, 0x23, 0xC3, 0x5C, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0xFF, 0xF7, 0x84, 0xFD, ++0xFB, 0xE7, 0xC0, 0x46, 0xF8, 0xE6, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x85, 0xF7, 0x55, 0xFE, 0x4C, 0x4B, ++0x1B, 0x68, 0x01, 0x2B, 0x02, 0xD0, 0x4A, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x49, 0x4A, 0x48, 0x4B, 0x19, 0x68, 0x49, 0x4B, ++0xD1, 0x54, 0x00, 0x21, 0x42, 0x3B, 0xD1, 0x54, 0x0B, 0x23, 0x47, 0x48, 0x13, 0x54, 0x01, 0x30, 0x13, 0x54, 0x46, 0x4B, ++0x1B, 0x68, 0x1C, 0x0A, 0x50, 0x38, 0x14, 0x54, 0x44, 0x48, 0x13, 0x54, 0x44, 0x4B, 0x20, 0x20, 0xD0, 0x54, 0x44, 0x4B, ++0x10, 0x38, 0xD0, 0x54, 0x43, 0x4B, 0x19, 0x60, 0x00, 0x24, 0x00, 0x23, 0x98, 0x46, 0x00, 0x27, 0x01, 0x34, 0xE4, 0xB2, ++0x01, 0x2C, 0x0B, 0xD0, 0x02, 0x2C, 0x3E, 0xD0, 0x03, 0x2C, 0x4C, 0xD0, 0x3D, 0x4A, 0x13, 0x78, 0x20, 0x21, 0x8B, 0x43, ++0x13, 0x70, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0C, 0x20, 0xFE, 0xF7, 0xA7, 0xF9, 0x06, 0x00, 0x0D, 0x20, 0xFE, 0xF7, ++0xA3, 0xF9, 0x05, 0x04, 0x2D, 0x0C, 0x2A, 0x00, 0x31, 0x00, 0x35, 0x48, 0x81, 0xF7, 0xDA, 0xFE, 0x2B, 0x00, 0x33, 0x43, ++0xDE, 0xD0, 0x43, 0x46, 0x00, 0x2B, 0x41, 0xD0, 0x27, 0x4B, 0x2A, 0x0A, 0x1A, 0x70, 0x5D, 0x70, 0x32, 0x0E, 0x9A, 0x70, ++0x32, 0x0C, 0xDA, 0x70, 0x32, 0x0A, 0x1A, 0x71, 0x5E, 0x71, 0x00, 0x2F, 0x0A, 0xD0, 0x21, 0x4A, 0x11, 0x1D, 0x13, 0x78, ++0x01, 0x33, 0xDB, 0xB2, 0x13, 0x70, 0x00, 0x2B, 0x02, 0xD1, 0x01, 0x32, 0x8A, 0x42, 0xF6, 0xD1, 0x1B, 0x4C, 0x20, 0x68, ++0x61, 0x68, 0xA9, 0xF7, 0xD1, 0xFC, 0x20, 0x00, 0xB9, 0xF7, 0x0E, 0xFB, 0xC2, 0xE7, 0x07, 0x20, 0xFE, 0xF7, 0x72, 0xF9, ++0x06, 0x00, 0x08, 0x20, 0xFE, 0xF7, 0x6E, 0xF9, 0x05, 0x04, 0x2D, 0x0C, 0x2A, 0x00, 0x31, 0x00, 0x1B, 0x48, 0x81, 0xF7, ++0xA5, 0xFE, 0x01, 0x27, 0xC8, 0xE7, 0x1A, 0x4B, 0x1E, 0x88, 0x58, 0x88, 0x00, 0x04, 0x06, 0x43, 0x18, 0x4B, 0x1D, 0x88, ++0x5B, 0x88, 0x2A, 0x00, 0x31, 0x00, 0x17, 0x48, 0x81, 0xF7, 0x96, 0xFE, 0x01, 0x23, 0x98, 0x46, 0x00, 0x27, 0xB7, 0xE7, ++0x06, 0x4B, 0x2A, 0x0A, 0x5A, 0x71, 0x1D, 0x71, 0x32, 0x0E, 0xDA, 0x70, 0x32, 0x0C, 0x9A, 0x70, 0x32, 0x0A, 0x5A, 0x70, ++0x1E, 0x70, 0xBC, 0xE7, 0xA8, 0xE5, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x9A, 0x02, 0x00, 0x00, 0xA3, 0x02, 0x00, 0x00, ++0xB0, 0xE5, 0x10, 0x00, 0x55, 0x02, 0x00, 0x00, 0x56, 0x02, 0x00, 0x00, 0x57, 0x02, 0x00, 0x00, 0xF8, 0xE6, 0x10, 0x00, ++0xEC, 0xE1, 0x10, 0x00, 0xA0, 0xD0, 0x10, 0x00, 0xB0, 0xD0, 0x10, 0x00, 0x12, 0xC0, 0x1F, 0x08, 0x16, 0xC0, 0x1F, 0x08, ++0xC4, 0xD0, 0x10, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x05, 0x00, 0x14, 0x00, 0x00, 0x28, 0x14, 0xD1, 0x1F, 0x4B, 0x20, 0x48, ++0x1A, 0x5C, 0x04, 0x35, 0xAA, 0x43, 0x1A, 0x54, 0x02, 0x30, 0x1A, 0x5C, 0x3E, 0x35, 0xAA, 0x43, 0x1A, 0x54, 0x22, 0x00, ++0x00, 0x20, 0x8D, 0xF7, 0xF9, 0xFF, 0x1A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x0E, 0xD0, 0x09, 0xB0, 0x30, 0xBD, 0x8D, 0xF7, ++0xF1, 0xFF, 0x02, 0x2D, 0xF5, 0xD1, 0x23, 0x78, 0x0C, 0x22, 0x93, 0x43, 0x23, 0x70, 0x63, 0x78, 0x0B, 0x3A, 0x93, 0x43, ++0x63, 0x70, 0xEC, 0xE7, 0x11, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0xEC, 0xD8, 0x00, 0x23, 0x07, 0x93, 0x0F, 0x4B, 0x1B, 0x68, ++0x03, 0x93, 0x0F, 0x4B, 0x1B, 0x68, 0x01, 0x93, 0x04, 0x93, 0x0E, 0x4B, 0x18, 0x68, 0x0E, 0x49, 0xD5, 0xF7, 0xD4, 0xFF, ++0x05, 0x90, 0x0D, 0x4B, 0x18, 0x68, 0x0B, 0x49, 0xD5, 0xF7, 0xCE, 0xFF, 0x06, 0x90, 0x03, 0xA8, 0xFF, 0xF7, 0x6C, 0xFE, ++0xD3, 0xE7, 0xC0, 0x46, 0x7C, 0x1E, 0x16, 0x00, 0x9E, 0x02, 0x00, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, ++0x0C, 0xE2, 0x10, 0x00, 0x10, 0xE2, 0x10, 0x00, 0x04, 0xE2, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x08, 0xE2, 0x10, 0x00, ++0x80, 0x00, 0x08, 0x4B, 0xC3, 0x58, 0x88, 0x22, 0xFF, 0x32, 0x9A, 0x5C, 0x00, 0x20, 0x01, 0x2A, 0x00, 0xD0, 0x70, 0x47, ++0x8A, 0x22, 0xFF, 0x32, 0x98, 0x5C, 0x01, 0x38, 0x43, 0x42, 0x58, 0x41, 0xF7, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x00, 0x23, 0x00, 0x20, 0x06, 0x49, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, 0x06, 0xD0, 0x9A, 0x00, 0x52, 0x58, 0x00, 0x2A, ++0xF8, 0xD0, 0x01, 0x30, 0xC0, 0xB2, 0xF5, 0xE7, 0x70, 0x47, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x70, 0xB5, 0x82, 0xB0, ++0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x30, 0x4B, 0xD6, 0x58, 0x20, 0x00, 0x80, 0xF7, 0xB2, 0xF8, 0x03, 0x00, 0x02, 0x00, ++0x01, 0x28, 0x12, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x05, 0xD9, 0x19, 0x2B, 0x05, 0xD8, 0x15, 0x23, 0x93, 0x42, 0x40, 0x41, ++0x40, 0x00, 0x02, 0xB0, 0x70, 0xBD, 0x58, 0x3B, 0xDB, 0xB2, 0x01, 0x20, 0x98, 0x42, 0x80, 0x41, 0x40, 0x42, 0x40, 0x00, ++0xF5, 0xE7, 0x4C, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x3A, 0xD1, 0x4B, 0x33, 0xF3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x4B, 0x23, ++0x00, 0x22, 0xF2, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x16, 0xD1, 0x36, 0x33, 0xF2, 0x5C, 0x35, 0x3B, 0x13, 0x40, ++0x3E, 0x22, 0x13, 0x43, 0x6A, 0x46, 0x13, 0x71, 0x00, 0x23, 0x53, 0x71, 0xE8, 0xB2, 0x01, 0xA9, 0xA7, 0xF7, 0x98, 0xF9, ++0x14, 0x48, 0x81, 0xF7, 0xA9, 0xFD, 0x59, 0x21, 0x20, 0x00, 0x80, 0xF7, 0x17, 0xF8, 0x00, 0x20, 0xCF, 0xE7, 0x01, 0xA9, ++0x36, 0x23, 0xF2, 0x5C, 0x38, 0x3B, 0x13, 0x43, 0x0B, 0x70, 0x1F, 0x23, 0x4B, 0x70, 0x1E, 0x3B, 0x8B, 0x70, 0xE8, 0xB2, ++0xA7, 0xF7, 0x82, 0xF9, 0x0A, 0x48, 0x81, 0xF7, 0x93, 0xFD, 0x20, 0x00, 0x97, 0xF7, 0x72, 0xFD, 0x58, 0x21, 0x20, 0x00, ++0x7F, 0xF7, 0xFE, 0xFF, 0x00, 0x20, 0xB6, 0xE7, 0x05, 0x48, 0x81, 0xF7, 0x87, 0xFD, 0x00, 0x20, 0xB1, 0xE7, 0xC0, 0x46, ++0x64, 0xA2, 0x16, 0x00, 0xDC, 0xD0, 0x10, 0x00, 0xEC, 0xD0, 0x10, 0x00, 0xFC, 0xD0, 0x10, 0x00, 0xF0, 0xB5, 0x05, 0xAC, ++0x24, 0x78, 0x4E, 0x28, 0x3C, 0xD8, 0xFF, 0x2C, 0x08, 0xD0, 0x10, 0x2C, 0x0B, 0xD9, 0x18, 0x2C, 0x37, 0xD9, 0x20, 0x2C, ++0x38, 0xD9, 0x03, 0x26, 0x00, 0x25, 0x06, 0xE0, 0x32, 0x4C, 0x24, 0x18, 0xED, 0x34, 0x24, 0x78, 0xF1, 0xE7, 0x00, 0x26, ++0x03, 0x25, 0x00, 0x29, 0x36, 0xD0, 0x2E, 0x4F, 0x39, 0x18, 0x0E, 0x00, 0x4F, 0x36, 0x33, 0x70, 0x3E, 0x56, 0xF3, 0x18, ++0x5B, 0x10, 0x3B, 0x54, 0x0B, 0x00, 0xED, 0x33, 0x1C, 0x70, 0x0E, 0x00, 0x9E, 0x36, 0x33, 0x78, 0x1C, 0x19, 0x64, 0x10, ++0x34, 0x70, 0x8C, 0x31, 0xFF, 0x31, 0x00, 0x23, 0x0B, 0x70, 0x24, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x1B, 0x78, ++0xED, 0x18, 0x6D, 0xB2, 0x06, 0x2D, 0x10, 0xDC, 0x1F, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x1D, 0x70, 0x02, 0x30, ++0x80, 0x00, 0x1C, 0x4B, 0x18, 0x18, 0x42, 0x60, 0xF0, 0xBD, 0x01, 0x26, 0x02, 0x25, 0xD0, 0xE7, 0x02, 0x26, 0x01, 0x25, ++0xCD, 0xE7, 0x17, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x06, 0x21, 0x19, 0x70, 0xEC, 0xE7, 0x12, 0x4B, 0x1B, 0x18, ++0x8C, 0x33, 0xFF, 0x33, 0x1B, 0x78, 0x01, 0x2B, 0x14, 0xD0, 0x0F, 0x49, 0x09, 0x18, 0x8C, 0x31, 0xFF, 0x31, 0x01, 0x23, ++0x0B, 0x70, 0x0D, 0x49, 0x09, 0x18, 0x49, 0x31, 0xFF, 0x31, 0x0B, 0x78, 0x9B, 0x1B, 0x5B, 0xB2, 0x99, 0x1D, 0x08, 0xDB, ++0x08, 0x49, 0x09, 0x18, 0x49, 0x31, 0xFF, 0x31, 0x0B, 0x70, 0xD0, 0xE7, 0x02, 0x36, 0xF6, 0xB2, 0xE7, 0xE7, 0x04, 0x4B, ++0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0xFA, 0x21, 0x19, 0x70, 0xC6, 0xE7, 0x1C, 0xE7, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, ++0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0x4C, 0x00, 0x25, 0x00, 0x22, 0x01, 0x26, ++0xC1, 0x27, 0xFF, 0x00, 0x03, 0xE0, 0x01, 0x35, 0x09, 0x34, 0x07, 0x2D, 0x0E, 0xD0, 0x23, 0x78, 0x03, 0x2B, 0xF8, 0xD1, ++0x63, 0x78, 0x00, 0x2B, 0xF5, 0xD1, 0x29, 0x02, 0x31, 0x43, 0x89, 0xB2, 0x00, 0x22, 0x38, 0x00, 0x7F, 0xF7, 0x20, 0xFC, ++0x01, 0x22, 0xEC, 0xE7, 0x00, 0x2A, 0x0B, 0xD1, 0x7E, 0x4A, 0xD9, 0x23, 0x5B, 0x00, 0x00, 0x21, 0xD1, 0x54, 0x00, 0x20, ++0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, 0xA8, 0xF7, 0xFE, 0xFF, 0x82, 0x46, 0x8E, 0xF7, ++0x09, 0xF8, 0x80, 0x46, 0xA9, 0xF7, 0x18, 0xFB, 0x81, 0x46, 0x00, 0x24, 0x73, 0x4B, 0x9B, 0x46, 0x63, 0xE0, 0x8D, 0xF7, ++0xF3, 0xFF, 0x00, 0x28, 0x19, 0xD0, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, ++0xC8, 0x22, 0x92, 0x01, 0x93, 0x42, 0x3D, 0xD2, 0x4B, 0x46, 0x3D, 0x33, 0xFF, 0x33, 0x1B, 0x57, 0x01, 0x33, 0x2D, 0xDB, ++0xD4, 0x20, 0x40, 0x00, 0x66, 0x4B, 0x5B, 0x19, 0x01, 0x21, 0xB1, 0x40, 0x1A, 0x5C, 0x0A, 0x43, 0x1A, 0x54, 0x2A, 0x00, ++0x63, 0x32, 0xFF, 0x32, 0x5A, 0x44, 0x00, 0x21, 0x06, 0x20, 0x38, 0x40, 0x03, 0x27, 0x13, 0x78, 0x03, 0x41, 0x3B, 0x40, ++0x03, 0x2B, 0x27, 0xD0, 0x01, 0x31, 0x0A, 0x32, 0x07, 0x29, 0xF6, 0xD1, 0xB3, 0x1E, 0x01, 0x2B, 0x00, 0xD8, 0x98, 0xE0, ++0x73, 0x1F, 0x01, 0x2B, 0x00, 0xD8, 0x94, 0xE0, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0xFA, 0x22, 0x12, 0x02, 0x93, 0x42, 0x1E, 0xD9, 0x93, 0xE0, 0xD4, 0x21, 0x49, 0x00, 0x4F, 0x4B, 0x5D, 0x19, ++0x01, 0x22, 0xB2, 0x40, 0x6B, 0x5C, 0x93, 0x43, 0x6B, 0x54, 0x13, 0xE0, 0x4B, 0x46, 0x3D, 0x33, 0xFF, 0x33, 0x00, 0x22, ++0x1A, 0x55, 0xCA, 0xE7, 0xD4, 0x20, 0x40, 0x00, 0x47, 0x4B, 0x9C, 0x46, 0xAC, 0x44, 0x01, 0x22, 0xB2, 0x40, 0x63, 0x46, ++0x1B, 0x5C, 0x93, 0x43, 0x62, 0x46, 0x13, 0x54, 0x07, 0x29, 0xCD, 0xD0, 0x01, 0x34, 0x4F, 0x2C, 0x13, 0xD0, 0xE7, 0xB2, ++0x07, 0x26, 0x26, 0x40, 0x65, 0x05, 0x2D, 0x0E, 0x43, 0x46, 0x5B, 0x5D, 0x33, 0x41, 0xDB, 0x07, 0x91, 0xD4, 0xD4, 0x21, ++0x49, 0x00, 0x3A, 0x4B, 0x5D, 0x19, 0x01, 0x22, 0xB2, 0x40, 0x6B, 0x5C, 0x93, 0x43, 0x6B, 0x54, 0xE8, 0xE7, 0x37, 0x48, ++0x81, 0xF7, 0xB0, 0xFC, 0x13, 0x28, 0x41, 0xD8, 0x14, 0x23, 0x1B, 0x1A, 0xDB, 0xB2, 0x9B, 0x46, 0x14, 0x25, 0x2D, 0x1A, ++0x00, 0x23, 0x99, 0x46, 0x00, 0x24, 0x2F, 0x4E, 0x0E, 0xE0, 0x48, 0x46, 0x13, 0x28, 0x09, 0xD9, 0x2C, 0x48, 0x84, 0x46, ++0x62, 0x44, 0x01, 0x20, 0x98, 0x40, 0x01, 0x43, 0xD4, 0x23, 0x5B, 0x00, 0xD1, 0x54, 0x01, 0x34, 0xAC, 0x42, 0x27, 0xDA, ++0xD6, 0xF7, 0xDA, 0xFA, 0x7F, 0x23, 0x18, 0x40, 0x4E, 0x28, 0x00, 0xD9, 0x4F, 0x38, 0xC2, 0x08, 0xB1, 0x18, 0xD4, 0x23, ++0x5B, 0x00, 0xC9, 0x5C, 0xA2, 0x3B, 0xFF, 0x3B, 0x03, 0x40, 0x0F, 0x00, 0x1F, 0x41, 0xFF, 0x07, 0xEA, 0xD4, 0x47, 0x46, ++0xBF, 0x5C, 0x1F, 0x41, 0xFF, 0x07, 0xE5, 0xD5, 0x4F, 0x46, 0x01, 0x37, 0xFF, 0xB2, 0xB9, 0x46, 0x1A, 0x4F, 0xBC, 0x46, ++0x60, 0x44, 0x9E, 0x30, 0x00, 0x78, 0x18, 0x28, 0xD0, 0xD9, 0xCB, 0x45, 0xCB, 0xD8, 0x20, 0x28, 0xCC, 0xD9, 0xC8, 0xE7, ++0x13, 0x48, 0x81, 0xF7, 0x69, 0xFC, 0x01, 0x00, 0x13, 0x48, 0x81, 0xF7, 0x01, 0xFC, 0xC8, 0x22, 0x00, 0x21, 0x12, 0x48, ++0x7F, 0xF7, 0x38, 0xFA, 0x1F, 0xE7, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, ++0xFA, 0x22, 0xD2, 0x01, 0x93, 0x42, 0x89, 0xD9, 0xD4, 0x21, 0x49, 0x00, 0x05, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x01, 0x22, ++0xB2, 0x40, 0x6B, 0x5C, 0x13, 0x43, 0x6B, 0x54, 0x7E, 0xE7, 0xC0, 0x46, 0xA4, 0x9E, 0x16, 0x00, 0x68, 0x9E, 0x16, 0x00, ++0x10, 0xA0, 0x16, 0x00, 0x1C, 0xE7, 0x10, 0x00, 0x0C, 0xD1, 0x10, 0x00, 0x0A, 0x05, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x07, 0x00, 0x08, 0x00, 0x00, 0x91, 0xBA, 0x00, 0xA4, 0x4B, ++0xD5, 0x58, 0xA6, 0x23, 0xEB, 0x5C, 0x9B, 0x46, 0x2B, 0x6D, 0x98, 0x46, 0x62, 0x23, 0x7B, 0x43, 0xA0, 0x4A, 0x9A, 0x18, ++0x16, 0x88, 0xA0, 0x4A, 0x9A, 0x18, 0x14, 0x88, 0x36, 0x04, 0x26, 0x43, 0x9E, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x92, 0x05, ++0x92, 0x0D, 0x91, 0x46, 0x9C, 0x4A, 0x9A, 0x18, 0x14, 0x88, 0x9C, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x24, 0x04, ++0x1C, 0x19, 0x9A, 0x4B, 0x98, 0x45, 0x1A, 0xD8, 0x73, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x80, 0x22, 0x12, 0x05, 0x91, 0x42, ++0x4A, 0xD9, 0x83, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0x49, 0xD0, 0x00, 0x2B, ++0x09, 0xDB, 0x89, 0x08, 0x00, 0x29, 0x06, 0xDD, 0x89, 0x00, 0x00, 0x9B, 0x9C, 0x46, 0x61, 0x44, 0x09, 0x01, 0x0B, 0x09, ++0x00, 0x93, 0xA4, 0x1B, 0x00, 0x9B, 0x9C, 0x46, 0x64, 0x44, 0x24, 0x01, 0x24, 0x09, 0xF4, 0x26, 0x76, 0x00, 0x4B, 0x46, ++0xF6, 0x1A, 0x3B, 0xD4, 0xAC, 0x67, 0x82, 0x23, 0xEE, 0x52, 0x62, 0x42, 0x7F, 0x3B, 0x13, 0x40, 0xA6, 0x22, 0xAB, 0x54, ++0x72, 0x3A, 0x2A, 0x65, 0x01, 0x96, 0xAE, 0x60, 0x42, 0x46, 0x34, 0x2A, 0x09, 0xD9, 0xEA, 0x7D, 0x00, 0x2A, 0x06, 0xD0, ++0xC8, 0x22, 0x52, 0x00, 0xB2, 0x42, 0x92, 0x41, 0x52, 0x42, 0x05, 0x32, 0xEA, 0x75, 0x5B, 0x45, 0x00, 0xD1, 0x9F, 0xE0, ++0xA1, 0x23, 0xEB, 0x5C, 0x03, 0x2B, 0x21, 0xD0, 0x3B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x02, 0x93, 0x01, 0x23, 0x98, 0x46, ++0xFE, 0x33, 0x9A, 0x46, 0xA9, 0x46, 0x45, 0x46, 0xA0, 0x46, 0x4D, 0xE0, 0x1B, 0x01, 0x1B, 0x09, 0xA1, 0x22, 0xAA, 0x5C, ++0x00, 0x2A, 0xB8, 0xD0, 0xB5, 0xE7, 0x00, 0x2B, 0xB5, 0xDA, 0x6C, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0xB8, 0xE7, 0x69, 0x4E, 0xF6, 0x1A, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0xBD, 0xE7, 0xC1, 0x33, 0x99, 0x46, ++0xEB, 0x58, 0x6A, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x4A, 0x46, 0xAB, 0x50, 0x3B, 0x02, ++0x01, 0x21, 0x19, 0x43, 0x02, 0x23, 0x3B, 0x32, 0x5F, 0x48, 0x7F, 0xF7, 0x2B, 0xFA, 0x80, 0x46, 0x4B, 0x46, 0xEB, 0x58, ++0x5B, 0x08, 0x99, 0x46, 0xCC, 0x23, 0xEB, 0x5A, 0x9A, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x57, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x51, 0x46, 0x48, 0x46, 0xD5, 0xF7, 0x47, 0xFD, 0x43, 0x46, 0x19, 0x80, 0x40, 0x46, ++0x7F, 0xF7, 0x3C, 0xFA, 0xB0, 0xE7, 0x21, 0x00, 0x03, 0x98, 0xD5, 0xF7, 0x3D, 0xFD, 0x04, 0x9B, 0x59, 0x80, 0x18, 0x00, ++0x7F, 0xF7, 0x32, 0xFA, 0x01, 0x3D, 0x3F, 0xD3, 0x53, 0x46, 0x2B, 0x40, 0x9B, 0x00, 0x4B, 0x4A, 0x9C, 0x58, 0x00, 0x2C, ++0xF6, 0xD0, 0x46, 0x23, 0xE3, 0x5C, 0xBB, 0x42, 0xF2, 0xD1, 0x63, 0x6B, 0x42, 0x46, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, ++0x63, 0x63, 0x4A, 0x46, 0x52, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x63, 0x63, 0x68, 0x42, 0x46, ++0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x4A, 0x46, 0x52, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, ++0x63, 0x60, 0x01, 0x9B, 0xA3, 0x60, 0x04, 0x23, 0x52, 0x46, 0x02, 0x99, 0x38, 0x48, 0x7F, 0xF7, 0xD9, 0xF9, 0x04, 0x90, ++0x47, 0x23, 0xE3, 0x5C, 0x03, 0x70, 0x63, 0x6B, 0x5B, 0x08, 0x03, 0x93, 0x42, 0x23, 0xE4, 0x5C, 0x00, 0x2C, 0xBC, 0xD1, ++0x2D, 0x4B, 0x9B, 0x6E, 0x05, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xB4, 0xE7, 0x44, 0x46, 0x4D, 0x46, ++0x6C, 0x67, 0x84, 0x23, 0xEE, 0x52, 0x1D, 0x33, 0xEB, 0x5C, 0x04, 0x2B, 0x0D, 0xD0, 0xA6, 0x23, 0xE8, 0x5C, 0x5B, 0x46, ++0xC0, 0x1A, 0x43, 0x1E, 0x98, 0x41, 0xC0, 0xB2, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, ++0xF0, 0xBD, 0x7C, 0x33, 0xEB, 0x5A, 0x9E, 0x1B, 0xF3, 0x17, 0xF6, 0x18, 0x5E, 0x40, 0x33, 0xB2, 0x9D, 0x22, 0x52, 0x00, ++0x93, 0x42, 0x02, 0xDB, 0x1D, 0x4B, 0x9B, 0x1B, 0x1B, 0xB2, 0x03, 0x2B, 0xE1, 0xDD, 0xE8, 0x23, 0xEB, 0x58, 0x1A, 0x68, ++0x00, 0x9B, 0xA8, 0x6F, 0x84, 0x46, 0x63, 0x44, 0x19, 0x00, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x20, 0x00, 0x05, ++0x83, 0x42, 0xD2, 0xD8, 0x09, 0x01, 0x09, 0x09, 0x51, 0x1A, 0x09, 0x01, 0x09, 0x09, 0x64, 0x29, 0xCB, 0xDD, 0x3F, 0x02, ++0x01, 0x21, 0x39, 0x43, 0xFF, 0x22, 0x0F, 0x48, 0x7F, 0xF7, 0xC2, 0xF9, 0xC3, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, ++0x4C, 0x65, 0x61, 0x40, 0x4A, 0x65, 0x61, 0x40, 0x4E, 0x65, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, ++0xE1, 0x04, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0x59, 0x04, 0x00, 0x00, 0x33, 0x06, 0x00, 0x00, 0x54, 0x27, 0x16, 0x00, ++0x34, 0x06, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x2E, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x89, 0xB0, 0x03, 0x90, 0x89, 0x46, 0x81, 0x00, 0xC9, 0x4B, 0xCF, 0x58, 0x53, 0x1E, 0xDB, 0xB2, ++0x9B, 0x46, 0x00, 0x2A, 0x00, 0xD1, 0x26, 0xE1, 0x03, 0x02, 0x01, 0x22, 0x13, 0x43, 0x07, 0x93, 0xC4, 0x4B, 0x98, 0x46, ++0x9A, 0x46, 0x5C, 0x46, 0x83, 0xE0, 0x6B, 0x46, 0x10, 0x21, 0x5B, 0x5E, 0x00, 0x2B, 0x06, 0xDB, 0xA7, 0x21, 0x79, 0x5C, ++0x77, 0x29, 0x02, 0xD8, 0x01, 0x31, 0xA7, 0x20, 0x39, 0x54, 0xE9, 0x06, 0x00, 0xD5, 0xD7, 0xE0, 0xA4, 0x21, 0x29, 0x42, ++0x5B, 0xD1, 0x29, 0x07, 0x54, 0xD4, 0x00, 0x2B, 0x00, 0xDA, 0xCF, 0xE0, 0xA7, 0x23, 0xFB, 0x5C, 0x77, 0x2B, 0x02, 0xD8, ++0xA7, 0x23, 0x02, 0x21, 0xF9, 0x54, 0x0F, 0x23, 0x1A, 0x40, 0x03, 0x25, 0x05, 0x9B, 0x1D, 0x40, 0x03, 0x2A, 0x01, 0xD0, ++0x08, 0x2A, 0x02, 0xD1, 0x03, 0x2D, 0x00, 0xD1, 0xCE, 0xE0, 0xEC, 0x23, 0xFB, 0x58, 0x00, 0x2B, 0x00, 0xD0, 0xB7, 0xE0, ++0x6B, 0x1E, 0x01, 0x2B, 0x00, 0xD9, 0xB3, 0xE0, 0x05, 0x9B, 0xDE, 0x04, 0xB6, 0x0D, 0x00, 0xD1, 0xAE, 0xE0, 0x04, 0x23, ++0xFF, 0x22, 0x07, 0x99, 0xA5, 0x48, 0x7F, 0xF7, 0x0B, 0xF9, 0xA5, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, ++0x9B, 0x1A, 0x5B, 0x00, 0xA2, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x03, 0x80, 0x43, 0x88, 0x9B, 0x0A, 0x9B, 0x02, ++0x33, 0x43, 0x9F, 0x4E, 0x33, 0x40, 0x2D, 0x03, 0x1D, 0x43, 0xAA, 0x04, 0x92, 0x0C, 0x06, 0x9B, 0x59, 0x42, 0x4B, 0x41, ++0x9B, 0x03, 0x13, 0x43, 0x43, 0x80, 0x7F, 0xF7, 0x17, 0xF9, 0x96, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, ++0x9B, 0x1A, 0x5B, 0x00, 0x93, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x00, 0x22, 0x1A, 0x80, 0x7D, 0xE0, 0xFF, 0x22, 0x07, 0x99, ++0x91, 0x48, 0x7F, 0xF7, 0x1B, 0xF9, 0xA8, 0xF7, 0x3F, 0xFA, 0x90, 0x4B, 0x1D, 0x68, 0x58, 0x46, 0x43, 0x46, 0xDB, 0x69, ++0x98, 0x47, 0x03, 0x00, 0x2D, 0x0A, 0xED, 0xB2, 0x00, 0x95, 0x4A, 0x46, 0x00, 0x21, 0x02, 0x98, 0xFF, 0xF7, 0x52, 0xFC, ++0x01, 0x3C, 0xE4, 0xB2, 0xFF, 0x2C, 0x00, 0xD1, 0x99, 0xE0, 0x03, 0x98, 0xA8, 0xF7, 0x54, 0xFA, 0x00, 0x28, 0x00, 0xD1, ++0x93, 0xE0, 0xD5, 0x23, 0x5B, 0x00, 0x7E, 0x4A, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x80, 0x4A, 0x9A, 0x18, ++0x15, 0x88, 0xAD, 0xB2, 0x7F, 0x4A, 0x9A, 0x18, 0x16, 0x88, 0xB6, 0xB2, 0x7E, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x92, 0xB2, ++0x05, 0x92, 0x7D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9A, 0xB2, 0x04, 0x92, 0xDA, 0xB2, 0x93, 0x46, 0x5B, 0x04, ++0x5B, 0x0E, 0x02, 0x93, 0x4B, 0x46, 0xFA, 0x6E, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xC8, 0x2B, 0x0A, 0xD9, 0xA7, 0x23, ++0xFB, 0x5C, 0x77, 0x2B, 0x06, 0xD8, 0xA1, 0x22, 0xBA, 0x5C, 0x00, 0x2A, 0x02, 0xD1, 0x01, 0x33, 0xA7, 0x32, 0xBB, 0x54, ++0xEB, 0x07, 0xB0, 0xD4, 0x07, 0x23, 0x1A, 0x00, 0x32, 0x40, 0x06, 0x92, 0x4A, 0x46, 0xFA, 0x66, 0x33, 0x42, 0x0B, 0xD0, ++0x5F, 0x4B, 0xDB, 0x69, 0x58, 0x46, 0x98, 0x47, 0x98, 0x22, 0xBB, 0x5A, 0x1B, 0x18, 0xBB, 0x52, 0x02, 0x32, 0xBB, 0x5C, ++0x01, 0x33, 0xBB, 0x54, 0xAB, 0x07, 0x9A, 0xD4, 0x4B, 0x46, 0x3B, 0x67, 0x6B, 0x06, 0x02, 0xD5, 0x06, 0x9B, 0x00, 0x2B, ++0x0C, 0xD1, 0xF6, 0x10, 0xF2, 0xB2, 0x0E, 0x23, 0x1E, 0x42, 0x00, 0xD0, 0x1F, 0xE7, 0x99, 0x33, 0xFB, 0x5C, 0x00, 0x2B, ++0x02, 0xD0, 0x01, 0x3B, 0xA7, 0x22, 0xBB, 0x54, 0xA8, 0xF7, 0xC6, 0xF9, 0x53, 0x4B, 0x1D, 0x68, 0x58, 0x46, 0x53, 0x46, ++0xDB, 0x69, 0x98, 0x47, 0x03, 0x00, 0x2D, 0x0A, 0xED, 0xB2, 0x00, 0x95, 0x4A, 0x46, 0x01, 0x21, 0x02, 0x98, 0xFF, 0xF7, ++0xD9, 0xFB, 0x85, 0xE7, 0x47, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x4D, 0x4A, ++0x94, 0x46, 0x63, 0x44, 0x19, 0x88, 0x8B, 0xB2, 0x04, 0x93, 0x05, 0x9A, 0xD5, 0x04, 0xAD, 0x0D, 0x6B, 0x1C, 0xFF, 0x22, ++0x07, 0x99, 0x48, 0x48, 0x7F, 0xF7, 0x3A, 0xF8, 0x06, 0x00, 0x05, 0x70, 0x04, 0x9B, 0x46, 0x4A, 0x94, 0x46, 0x63, 0x44, ++0x19, 0x00, 0x01, 0x30, 0x2A, 0x00, 0xD5, 0xF7, 0x27, 0xFF, 0x30, 0x00, 0x7F, 0xF7, 0x56, 0xF8, 0xC8, 0xE7, 0x62, 0x24, ++0x03, 0x9B, 0x5C, 0x43, 0x3F, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x80, 0x22, 0x93, 0x43, 0x23, 0x80, 0x89, 0xF7, ++0x59, 0xF9, 0x00, 0x28, 0x18, 0xD0, 0x2F, 0x4B, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x13, 0xD1, 0x38, 0x4B, 0x1B, 0x88, ++0x9B, 0xB2, 0x00, 0x2B, 0x0E, 0xD1, 0x37, 0x4B, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x09, 0xD1, 0x35, 0x4B, 0x1B, 0x88, ++0x9B, 0xB2, 0x00, 0x2B, 0x04, 0xD1, 0x23, 0x88, 0x80, 0x22, 0x93, 0x43, 0x13, 0x43, 0x23, 0x80, 0x9A, 0x23, 0xFB, 0x5C, ++0x96, 0x2B, 0x03, 0xD9, 0xEC, 0x23, 0xFB, 0x58, 0x00, 0x2B, 0x06, 0xD0, 0x09, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xAC, 0x33, 0xFB, 0x5C, 0x00, 0x2B, 0xF4, 0xD0, 0x9B, 0x23, 0x00, 0x22, 0xFA, 0x54, ++0x26, 0x4A, 0x27, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0x03, 0xD5, 0x26, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x05, 0xD1, 0x00, 0x23, ++0x9A, 0x22, 0xBB, 0x54, 0x02, 0x3A, 0xBB, 0x52, 0xE2, 0xE7, 0x03, 0x9B, 0x19, 0x02, 0x01, 0x23, 0x19, 0x43, 0xFF, 0x22, ++0x1F, 0x48, 0x7F, 0xF7, 0x17, 0xF8, 0x98, 0x23, 0xF8, 0x5E, 0x9A, 0x23, 0xF9, 0x5C, 0xD5, 0xF7, 0x05, 0xFB, 0x06, 0x4A, ++0x2F, 0x23, 0xD3, 0x5C, 0xC0, 0x1A, 0x9B, 0x23, 0xF8, 0x54, 0x17, 0x4A, 0x13, 0x78, 0x01, 0x3B, 0x13, 0x70, 0xE0, 0xE7, ++0x38, 0x27, 0x16, 0x00, 0x60, 0x92, 0x16, 0x00, 0x29, 0x06, 0x00, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x9A, 0x69, 0x61, 0x40, ++0xFF, 0xCF, 0xFF, 0xFF, 0x2A, 0x06, 0x00, 0x00, 0x0C, 0x01, 0x60, 0x40, 0x92, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, ++0x96, 0x69, 0x61, 0x40, 0x98, 0x69, 0x61, 0x40, 0x9C, 0x69, 0x61, 0x40, 0x27, 0x06, 0x00, 0x00, 0x00, 0x00, 0x61, 0x40, ++0x0E, 0x65, 0x61, 0x40, 0xA8, 0x69, 0x61, 0x40, 0xB6, 0x69, 0x61, 0x40, 0xC4, 0x69, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, ++0x9D, 0x02, 0x00, 0x00, 0x24, 0xE6, 0x10, 0x00, 0x2F, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x04, 0x00, ++0x88, 0x46, 0x16, 0x00, 0xFF, 0xF7, 0x84, 0xFA, 0x00, 0x28, 0x3F, 0xD1, 0x22, 0x4D, 0x23, 0x4F, 0xEB, 0x5D, 0x04, 0x22, ++0x93, 0x43, 0xEB, 0x55, 0x32, 0x00, 0x41, 0x46, 0x20, 0x00, 0xFF, 0xF7, 0x1F, 0xFE, 0xEB, 0x5D, 0x04, 0x22, 0x13, 0x43, ++0xEB, 0x55, 0xA4, 0x00, 0x1C, 0x4B, 0xE4, 0x58, 0xA7, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x02, 0xD9, 0xA7, 0x23, 0x04, 0x22, ++0xE2, 0x54, 0xFE, 0xF7, 0x49, 0xFB, 0x00, 0x28, 0x02, 0xD1, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xB1, 0xF7, 0x04, 0xFD, ++0x00, 0x28, 0xF8, 0xD1, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x0A, 0xD1, 0xA7, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x06, 0xD1, ++0xAA, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0xA7, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xA8, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x03, 0xD1, 0x62, 0x68, 0x09, 0x4B, 0x1A, 0x60, 0xE1, 0xE7, 0xA8, 0xF7, 0x81, 0xFB, 0x08, 0x4B, 0x18, 0x60, 0xF6, 0xE7, ++0x32, 0x00, 0x41, 0x46, 0x20, 0x00, 0xFF, 0xF7, 0xE5, 0xFD, 0xC8, 0xE7, 0x7C, 0x1E, 0x16, 0x00, 0x9D, 0x02, 0x00, 0x00, ++0x38, 0x27, 0x16, 0x00, 0x28, 0xE6, 0x10, 0x00, 0x2C, 0xE6, 0x10, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x1A, 0x60, 0x04, 0x4B, ++0x04, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x04, 0x30, 0x34, 0x40, 0xC1, 0x00, 0xA0, 0x00, 0x0C, 0x00, 0x58, 0x40, ++0x14, 0x00, 0x7F, 0x30, 0x01, 0x4B, 0x02, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0x04, 0x30, 0x34, 0x40, 0xC0, 0x00, 0xA0, 0x00, ++0x10, 0xB5, 0x30, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x09, 0xD0, 0x01, 0x28, 0x08, 0xD0, 0x02, 0x28, 0x47, 0xD0, 0x2D, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x10, 0xBD, 0xA8, 0xF7, 0x44, 0xFB, 0x27, 0x4B, 0x5B, 0x78, ++0x00, 0x2B, 0x11, 0xD1, 0x25, 0x4B, 0x01, 0x22, 0x5A, 0x70, 0x58, 0x60, 0x9B, 0x78, 0x01, 0x2B, 0xF1, 0xD0, 0xFE, 0xF7, ++0xA7, 0xFA, 0x00, 0x28, 0xED, 0xD1, 0xFE, 0xF7, 0xC1, 0xFA, 0x00, 0x28, 0xE9, 0xD1, 0xFF, 0xF7, 0xC1, 0xFF, 0xE6, 0xE7, ++0x1C, 0x4A, 0x53, 0x68, 0xC3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x92, 0x78, 0x00, 0x2A, 0x0B, 0xD1, 0x23, 0x2B, 0xDC, 0xD9, ++0x17, 0x4B, 0x01, 0x32, 0x9A, 0x70, 0x00, 0x22, 0x5A, 0x70, 0x58, 0x60, 0x16, 0x4B, 0x17, 0x4A, 0x1A, 0x60, 0xD2, 0xE7, ++0x01, 0x2A, 0xD0, 0xD1, 0x3B, 0x2B, 0xCE, 0xD9, 0x10, 0x4B, 0x00, 0x22, 0x9A, 0x70, 0x01, 0x32, 0x5A, 0x70, 0x58, 0x60, ++0xFE, 0xF7, 0x7E, 0xFA, 0x00, 0x28, 0xC4, 0xD1, 0xFE, 0xF7, 0x98, 0xFA, 0x00, 0x28, 0xC0, 0xD1, 0xFF, 0xF7, 0x98, 0xFF, ++0xBD, 0xE7, 0x08, 0x4B, 0x5B, 0x78, 0x01, 0x2B, 0x01, 0xD0, 0x00, 0x29, 0xB7, 0xD0, 0x05, 0x4B, 0x00, 0x22, 0x5A, 0x70, ++0x9A, 0x70, 0x01, 0x3A, 0x5A, 0x60, 0x04, 0x4B, 0x04, 0x4A, 0x1A, 0x60, 0xAD, 0xE7, 0xC0, 0x46, 0xDC, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x04, 0x30, 0x34, 0x40, 0xC0, 0x00, 0xA0, 0x00, 0xF0, 0xB5, 0x80, 0x00, 0x26, 0x4B, 0xC3, 0x58, ++0xAB, 0x20, 0x18, 0x5C, 0x00, 0x28, 0x27, 0xD0, 0x0D, 0x1C, 0xAA, 0x20, 0x80, 0x00, 0x81, 0x42, 0x01, 0xD3, 0x22, 0x49, ++0x0D, 0x1C, 0xAD, 0xB2, 0x9D, 0x21, 0x5F, 0x5C, 0x00, 0x23, 0x00, 0x24, 0x01, 0x26, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, ++0x0C, 0xD0, 0xD8, 0xB2, 0x39, 0x00, 0x19, 0x41, 0x0E, 0x42, 0xF7, 0xD0, 0x59, 0x00, 0x1A, 0x4C, 0x61, 0x5A, 0xA9, 0x42, ++0x01, 0xD2, 0x04, 0x00, 0xF0, 0xE7, 0x04, 0x00, 0x17, 0x4B, 0x18, 0x5D, 0x64, 0x00, 0x15, 0x4B, 0xE3, 0x5A, 0xAB, 0x42, ++0x00, 0xD9, 0x2B, 0x00, 0x13, 0x80, 0xF0, 0xBD, 0x9C, 0x20, 0x1F, 0x5C, 0x00, 0x23, 0x00, 0x25, 0x01, 0x26, 0x02, 0xE0, ++0x01, 0x33, 0x06, 0x2B, 0x0C, 0xD0, 0xDC, 0xB2, 0x38, 0x00, 0x18, 0x41, 0x06, 0x42, 0xF7, 0xD0, 0x58, 0x00, 0x0C, 0x4D, ++0x28, 0x5A, 0x88, 0x42, 0x01, 0xD2, 0x25, 0x00, 0xF0, 0xE7, 0x25, 0x00, 0x09, 0x4B, 0x58, 0x5D, 0x6D, 0x00, 0x07, 0x4B, ++0xEB, 0x5A, 0x8B, 0x42, 0x00, 0xD9, 0x0B, 0x00, 0x13, 0x80, 0xDE, 0xE7, 0x38, 0x27, 0x16, 0x00, 0xA7, 0x02, 0x00, 0x00, ++0x40, 0xC9, 0x0D, 0x00, 0x50, 0xC9, 0x0D, 0x00, 0x2C, 0xC9, 0x0D, 0x00, 0x38, 0xC9, 0x0D, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x85, 0xB0, 0x00, 0x90, 0x88, 0x46, 0x82, 0x00, 0x95, 0x4B, 0xD4, 0x58, ++0xAF, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD9, 0x0D, 0xE1, 0x03, 0x02, 0x01, 0x27, 0x1F, 0x43, 0x88, 0x23, 0x99, 0x46, ++0xBB, 0x46, 0x2A, 0xE0, 0xAB, 0x00, 0x5D, 0x19, 0x6D, 0x00, 0x8E, 0x4B, 0xEA, 0x18, 0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, ++0x60, 0x39, 0x0B, 0x43, 0x13, 0x80, 0x8B, 0x4B, 0xEA, 0x18, 0x83, 0x79, 0xDB, 0x00, 0x11, 0x39, 0x0B, 0x43, 0x13, 0x80, ++0x82, 0x88, 0x88, 0x4B, 0xEB, 0x18, 0x1A, 0x80, 0x87, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, ++0x2B, 0x80, 0xAE, 0x22, 0xA3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, ++0xAF, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD9, 0xDB, 0xE0, 0x9E, 0x23, 0xE5, 0x5C, 0x6D, 0x00, 0x10, 0x33, 0xE3, 0x5C, ++0xED, 0x18, 0xED, 0xB2, 0x20, 0x00, 0x40, 0x30, 0x81, 0xF7, 0x84, 0xFA, 0x00, 0x28, 0xC7, 0xD1, 0xEC, 0x23, 0xE3, 0x58, ++0x00, 0x2B, 0x39, 0xD0, 0x9A, 0x7A, 0x00, 0x2A, 0x36, 0xD1, 0xAC, 0x32, 0xA2, 0x5C, 0x00, 0x2A, 0x00, 0xD1, 0xC2, 0xE0, ++0x9A, 0x78, 0x05, 0x3A, 0x03, 0x2A, 0x00, 0xD8, 0xBD, 0xE0, 0x1A, 0x88, 0xA9, 0x00, 0x4D, 0x19, 0x6D, 0x00, 0x69, 0x49, ++0x68, 0x18, 0x01, 0x88, 0xDE, 0x79, 0x0F, 0x23, 0x33, 0x40, 0xDB, 0x00, 0x78, 0x26, 0xB1, 0x43, 0x0B, 0x43, 0x03, 0x80, ++0x64, 0x4B, 0xE9, 0x18, 0xD3, 0x00, 0x05, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x0B, 0x80, 0xEC, 0x23, 0xE3, 0x58, 0x1A, 0x89, ++0x62, 0x4B, 0xEB, 0x18, 0x1A, 0x80, 0x60, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x2B, 0x80, ++0xAE, 0x22, 0xA3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0xAF, 0xE7, ++0xAC, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x8B, 0xE0, 0x96, 0x23, 0xE1, 0x5A, 0x01, 0x27, 0x00, 0x29, 0x39, 0xD0, ++0x02, 0xAB, 0x9A, 0x1D, 0x00, 0x98, 0xFF, 0xF7, 0x07, 0xFF, 0xAB, 0x00, 0x5D, 0x19, 0x6D, 0x00, 0x4B, 0x4B, 0xEA, 0x18, ++0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, 0xC0, 0x00, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x48, 0x4B, 0xEA, 0x18, 0x02, 0xAB, ++0xDB, 0x88, 0xDB, 0x00, 0x1F, 0x43, 0x04, 0x23, 0x1F, 0x43, 0xBF, 0xB2, 0x17, 0x80, 0x94, 0x22, 0xA1, 0x5A, 0x45, 0x4B, ++0xEB, 0x18, 0x19, 0x80, 0x42, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x2B, 0x80, 0x02, 0xAB, ++0xDB, 0x88, 0x96, 0x20, 0x21, 0x5A, 0xC9, 0x1A, 0x21, 0x52, 0xA1, 0x5A, 0x5B, 0x18, 0xA3, 0x52, 0x1A, 0x32, 0xA3, 0x5C, ++0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x6B, 0xE7, 0x27, 0x00, 0x48, 0x37, ++0x80, 0x23, 0x1B, 0x05, 0x9A, 0x46, 0x0F, 0xE0, 0x52, 0x00, 0x8A, 0x42, 0x1E, 0xDA, 0x01, 0x23, 0xFF, 0x22, 0x59, 0x46, ++0x31, 0x48, 0x7E, 0xF7, 0x7F, 0xFD, 0x01, 0x23, 0x03, 0x70, 0x7E, 0xF7, 0xA5, 0xFD, 0x30, 0x89, 0x88, 0xF7, 0x98, 0xFE, ++0x38, 0x00, 0x81, 0xF7, 0xE7, 0xF9, 0x06, 0x1E, 0x46, 0xD0, 0x4B, 0x46, 0xE2, 0x5A, 0x00, 0x2A, 0x08, 0xD0, 0x43, 0x68, ++0x59, 0x1C, 0x05, 0xD0, 0x41, 0x46, 0xCB, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x51, 0x45, 0xDD, 0xD9, 0x73, 0x89, 0x9F, 0x04, ++0xBF, 0x0F, 0x9B, 0x05, 0x9B, 0x0D, 0x9A, 0x46, 0x90, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0x2C, 0xD0, 0x8C, 0x23, 0xE3, 0x58, ++0x00, 0x2B, 0x06, 0xD0, 0x1D, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x8C, 0x23, ++0xE6, 0x50, 0x96, 0x23, 0x52, 0x46, 0xE2, 0x52, 0x32, 0x89, 0x02, 0x3B, 0xE2, 0x52, 0x01, 0x2F, 0x00, 0xD0, 0x02, 0x27, ++0x96, 0x23, 0xE1, 0x5A, 0x00, 0x29, 0x00, 0xD0, 0x78, 0xE7, 0xAF, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x06, 0xD0, 0xA8, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x02, 0xD1, 0xA8, 0x33, 0x01, 0x22, 0xE2, 0x54, 0x05, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x90, 0x33, 0xE6, 0x50, 0xDC, 0xE7, 0x01, 0x27, 0xE3, 0xE7, 0x38, 0x27, 0x16, 0x00, ++0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xD0, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0xCE, 0x69, 0x61, 0x40, ++0x2B, 0x06, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, ++0x83, 0xB0, 0x82, 0x00, 0x4B, 0x4B, 0xD4, 0x58, 0x90, 0x23, 0xE2, 0x58, 0x00, 0x2A, 0x00, 0xD1, 0x84, 0xE0, 0x49, 0x4B, ++0x59, 0x88, 0x49, 0x4B, 0x1B, 0x78, 0x99, 0x42, 0x73, 0xD9, 0x9E, 0x23, 0xE3, 0x5C, 0x5B, 0x00, 0xAD, 0x21, 0x61, 0x5C, ++0x5B, 0x18, 0xDB, 0xB2, 0x56, 0x89, 0xB6, 0x05, 0xB2, 0x0D, 0x90, 0x46, 0x02, 0x22, 0x90, 0x26, 0x41, 0x49, 0x01, 0x91, ++0xAF, 0x21, 0x8A, 0x46, 0x01, 0x39, 0x89, 0x46, 0x10, 0x39, 0x8C, 0x46, 0x00, 0x90, 0x0C, 0xE0, 0x63, 0x46, 0xE5, 0x5C, ++0x6D, 0x00, 0xAD, 0x23, 0xE1, 0x5C, 0x4B, 0x42, 0x4B, 0x41, 0x5B, 0x19, 0xDB, 0xB2, 0x01, 0x3A, 0xD2, 0xB2, 0x00, 0x2A, ++0x31, 0xD0, 0x99, 0x00, 0xCB, 0x18, 0x5B, 0x00, 0x35, 0x49, 0x5F, 0x18, 0x39, 0x88, 0x89, 0xB2, 0xA5, 0x59, 0x2D, 0x89, ++0x8D, 0x42, 0xE7, 0xD8, 0x45, 0x44, 0xA9, 0x42, 0xE4, 0xDA, 0x31, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x01, 0x98, 0x01, 0x40, ++0x29, 0x80, 0x2F, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x2D, 0x48, 0x01, 0x43, 0x89, 0xB2, 0x29, 0x80, ++0x2C, 0x49, 0x8B, 0x46, 0x5B, 0x44, 0x19, 0x88, 0x78, 0x20, 0x81, 0x43, 0x19, 0x80, 0x00, 0x23, 0x3B, 0x80, 0x53, 0x46, ++0xE3, 0x5C, 0x01, 0x3B, 0x51, 0x46, 0x63, 0x54, 0x4B, 0x46, 0xE3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0x49, 0x46, 0x63, 0x54, ++0xC0, 0xE7, 0x00, 0x98, 0x00, 0x02, 0x01, 0x25, 0x28, 0x43, 0x81, 0xB2, 0x01, 0x23, 0xFF, 0x32, 0x1F, 0x48, 0x7E, 0xF7, ++0xA5, 0xFC, 0x05, 0x70, 0x7E, 0xF7, 0xCC, 0xFC, 0x1D, 0x48, 0x80, 0xF7, 0xA3, 0xFD, 0x90, 0x23, 0xE3, 0x58, 0x18, 0x89, ++0x88, 0xF7, 0xBA, 0xFD, 0x8C, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0x0B, 0xD0, 0x90, 0x22, 0xA3, 0x50, 0x8C, 0x23, 0x00, 0x22, ++0xE2, 0x50, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x96, 0x22, 0x00, 0x21, ++0xA1, 0x52, 0xEF, 0xE7, 0x8C, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0xF0, 0xD0, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0xE9, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x9C, 0xE5, 0x10, 0x00, 0xF8, 0xE1, 0x10, 0x00, ++0x07, 0xE0, 0xFF, 0xFF, 0xCE, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, ++0xCA, 0x69, 0x61, 0x40, 0x2B, 0x06, 0x00, 0x00, 0x18, 0xD1, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x03, 0x00, 0x00, 0x20, ++0x9A, 0x6C, 0x00, 0x2A, 0x00, 0xD0, 0x70, 0x47, 0xA7, 0x32, 0x9A, 0x5C, 0x00, 0x2A, 0xFA, 0xD1, 0xA8, 0x32, 0x98, 0x5C, ++0x43, 0x42, 0x58, 0x41, 0xC0, 0xB2, 0xF4, 0xE7, 0x04, 0x4B, 0x18, 0x68, 0x04, 0x4B, 0x1B, 0x68, 0x18, 0x43, 0x43, 0x1E, ++0x98, 0x41, 0xC0, 0xB2, 0x70, 0x47, 0xC0, 0x46, 0x24, 0x27, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0x70, 0xB5, 0x84, 0xB0, ++0x82, 0x00, 0x12, 0x4B, 0xD5, 0x58, 0x01, 0xA9, 0x11, 0x4C, 0x02, 0x01, 0x13, 0x1A, 0x9B, 0x00, 0xE3, 0x18, 0xDE, 0x88, ++0x4E, 0x80, 0x1E, 0x7B, 0x4E, 0x70, 0x1E, 0x89, 0xCE, 0x80, 0x5E, 0x89, 0x0E, 0x81, 0x9B, 0x88, 0x8B, 0x80, 0x12, 0x1A, ++0x92, 0x00, 0xA2, 0x18, 0x53, 0x7B, 0x01, 0x22, 0x53, 0x40, 0x36, 0x22, 0xAA, 0x5C, 0x5A, 0x40, 0x01, 0x23, 0x13, 0x40, ++0x2E, 0x22, 0x13, 0x43, 0x0B, 0x70, 0xA6, 0xF7, 0x0F, 0xF9, 0x04, 0xB0, 0x70, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0xC0, 0xA0, 0x16, 0x00, 0xF8, 0xB5, 0x06, 0x00, 0x0C, 0x00, 0x05, 0x0A, 0xAA, 0x00, 0x18, 0x4B, 0xD7, 0x58, 0x36, 0x23, ++0xFB, 0x5C, 0x00, 0x2B, 0x0C, 0xD0, 0x2B, 0x01, 0x5B, 0x1B, 0x9B, 0x00, 0x14, 0x4A, 0xD3, 0x18, 0x5B, 0x7B, 0x00, 0x2B, ++0x08, 0xD1, 0x01, 0x21, 0x30, 0x00, 0x7E, 0xF7, 0x77, 0xFF, 0xF8, 0xBD, 0xE8, 0xB2, 0xB2, 0xF7, 0x73, 0xF9, 0xEE, 0xE7, ++0x08, 0x23, 0x14, 0x22, 0x00, 0x21, 0x0D, 0x48, 0x7E, 0xF7, 0xF6, 0xFB, 0x04, 0x70, 0x2B, 0x00, 0x80, 0x33, 0x43, 0x80, ++0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, 0xFB, 0x5C, 0x03, 0x71, 0xD0, 0xF7, 0x4B, 0xFA, 0x2B, 0x01, 0x5D, 0x1B, 0xAD, 0x00, ++0x03, 0x4B, 0x5D, 0x19, 0x00, 0x23, 0x6B, 0x73, 0xDD, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xC0, 0xA0, 0x16, 0x00, ++0x03, 0x11, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x93, 0xB0, 0x05, 0x00, ++0x03, 0x91, 0x93, 0x46, 0x1E, 0x00, 0x1C, 0xAB, 0x1B, 0x88, 0x99, 0x46, 0x1D, 0xAB, 0x1B, 0x88, 0x9A, 0x46, 0x04, 0x0A, ++0xA2, 0x00, 0xCB, 0x4B, 0xD7, 0x58, 0x01, 0x00, 0xCA, 0x48, 0x7E, 0xF7, 0x7B, 0xFB, 0xB3, 0x1F, 0xC9, 0x4A, 0x9B, 0xB2, ++0x93, 0x42, 0x03, 0xD8, 0x5B, 0x46, 0x33, 0x43, 0xDB, 0x07, 0x0D, 0xD5, 0x39, 0x23, 0xFB, 0x5C, 0xE0, 0xB2, 0x12, 0x22, ++0x17, 0x21, 0xA6, 0xF7, 0xF6, 0xF8, 0x13, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, ++0x5E, 0x45, 0xEF, 0xD9, 0x4B, 0x46, 0x00, 0x2B, 0xEC, 0xD0, 0x73, 0x08, 0x4B, 0x45, 0xE9, 0xD3, 0x53, 0x46, 0x28, 0x2B, ++0xE6, 0xD8, 0x4B, 0x44, 0x5B, 0x00, 0xB3, 0x42, 0xE2, 0xD2, 0x28, 0x00, 0x7E, 0xF7, 0x70, 0xFF, 0x01, 0x28, 0x00, 0xD1, ++0x85, 0xE0, 0xB5, 0x4B, 0x22, 0x01, 0x11, 0x1B, 0x89, 0x00, 0xCE, 0x52, 0x5B, 0x18, 0x5E, 0x80, 0x4A, 0x46, 0x1A, 0x81, ++0x9E, 0x80, 0x5A, 0x46, 0xDA, 0x80, 0x52, 0x46, 0x5A, 0x81, 0x03, 0x9A, 0x1A, 0x73, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x22, ++0x04, 0x92, 0x01, 0x2B, 0x77, 0xD0, 0x0A, 0x96, 0x0B, 0x96, 0x36, 0x23, 0xF8, 0x5C, 0x4A, 0x46, 0x02, 0x2A, 0x00, 0xD9, ++0x02, 0x22, 0x90, 0x46, 0x80, 0x44, 0x0A, 0xAB, 0x42, 0x46, 0x0C, 0x92, 0x49, 0x46, 0x49, 0x00, 0x0D, 0x91, 0x00, 0x21, ++0x99, 0x74, 0x80, 0x31, 0x8C, 0x46, 0xA4, 0x44, 0x61, 0x46, 0x19, 0x82, 0x01, 0x21, 0x04, 0x9A, 0x11, 0x40, 0xD9, 0x74, ++0x06, 0xAB, 0x06, 0x96, 0x42, 0x46, 0x07, 0x92, 0x62, 0x46, 0x9A, 0x81, 0x00, 0x28, 0x5A, 0xD1, 0x58, 0x46, 0x08, 0x90, ++0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, 0x5A, 0xD0, 0x08, 0x9B, 0x10, 0x93, 0x11, 0x93, 0x06, 0x9B, 0x0F, 0x93, 0x06, 0xA8, ++0xD4, 0xF7, 0x5A, 0xFA, 0x80, 0x46, 0x00, 0x28, 0x72, 0xD1, 0x0A, 0xAA, 0x10, 0x98, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, ++0x8D, 0x49, 0xCB, 0x18, 0x98, 0x62, 0x0F, 0x99, 0x8C, 0x46, 0x59, 0x62, 0x0C, 0x99, 0xD9, 0x62, 0x0D, 0x99, 0x19, 0x63, ++0x12, 0x8A, 0x9A, 0x86, 0x00, 0x22, 0x9A, 0x63, 0x36, 0x33, 0x1A, 0x70, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x6B, 0xD1, ++0x80, 0xB2, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x81, 0x4A, 0xD3, 0x18, 0xD8, 0x80, 0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, ++0x67, 0xD0, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, 0x7D, 0x4B, 0x9A, 0x42, 0x79, 0xD1, 0x43, 0x46, 0x01, 0x2B, ++0x00, 0xD1, 0xDF, 0xE0, 0x02, 0x2B, 0x00, 0xD1, 0xBC, 0xE0, 0x00, 0x2B, 0x00, 0xD1, 0xAE, 0xE0, 0x77, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x5D, 0xE7, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x70, 0x4A, 0xD3, 0x18, ++0x00, 0x22, 0x5A, 0x73, 0x71, 0xE7, 0xE0, 0xB2, 0xAF, 0xF7, 0xAE, 0xFE, 0x43, 0x08, 0x04, 0x93, 0x81, 0xE7, 0x04, 0x9A, ++0x31, 0x00, 0x58, 0x46, 0xA5, 0xF7, 0x2E, 0xFD, 0x9F, 0xE7, 0x06, 0x9B, 0x9B, 0x46, 0x01, 0x3B, 0x98, 0x46, 0x80, 0x44, ++0x5B, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x66, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x59, 0x46, ++0x40, 0x46, 0xD4, 0xF7, 0x1B, 0xFE, 0x08, 0x91, 0x0A, 0xAB, 0xDA, 0x7C, 0x01, 0x21, 0x4A, 0x40, 0xDA, 0x74, 0x0C, 0x9A, ++0x03, 0x32, 0x0C, 0x92, 0x0D, 0x9A, 0x03, 0x32, 0x0D, 0x92, 0x07, 0x9B, 0x05, 0x93, 0x03, 0x33, 0x07, 0x93, 0x81, 0xE7, ++0x28, 0x00, 0x7E, 0xF7, 0xAD, 0xFE, 0x80, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x01, 0x23, 0x98, 0x46, 0x83, 0xE7, 0x0A, 0xA8, ++0xD4, 0xF7, 0x6A, 0xF9, 0x00, 0x28, 0x00, 0xD0, 0x7D, 0xE7, 0x02, 0x23, 0x98, 0x46, 0x7A, 0xE7, 0x63, 0x46, 0x99, 0xB2, ++0x80, 0xB2, 0x04, 0x9A, 0xA5, 0xF7, 0x0A, 0xFD, 0x8D, 0xE7, 0x43, 0x1C, 0x04, 0x93, 0x0F, 0x9B, 0x9B, 0x46, 0x00, 0x2B, ++0x05, 0xD1, 0x49, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, ++0x42, 0x4A, 0xD3, 0x18, 0x05, 0x93, 0x59, 0x46, 0x04, 0x98, 0xD4, 0xF7, 0xDB, 0xFD, 0x05, 0x9B, 0xD9, 0x80, 0x7E, 0xE7, ++0xE3, 0xB2, 0x9B, 0x46, 0x18, 0x00, 0x95, 0xF7, 0x71, 0xFF, 0x05, 0x90, 0x0F, 0x9B, 0x04, 0x93, 0x00, 0x28, 0x05, 0xD1, ++0x3A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x05, 0x99, 0x04, 0x98, 0xD4, 0xF7, 0xC4, 0xFD, ++0x00, 0x29, 0x00, 0xD0, 0x6E, 0xE7, 0x3C, 0x22, 0x62, 0x43, 0x31, 0x4B, 0x9B, 0x18, 0xD9, 0x88, 0x11, 0x9B, 0x04, 0x93, ++0x10, 0x9B, 0x05, 0x93, 0x04, 0x9B, 0x05, 0x9A, 0x9A, 0x1A, 0x8A, 0x18, 0x92, 0xB2, 0x58, 0x46, 0x95, 0xF7, 0x9C, 0xFF, ++0x04, 0x90, 0x0F, 0x9B, 0x9B, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x29, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, ++0x98, 0x47, 0x3C, 0x23, 0x63, 0x43, 0x23, 0x4A, 0xD3, 0x18, 0x05, 0x93, 0x59, 0x46, 0x04, 0x98, 0xD4, 0xF7, 0x9C, 0xFD, ++0x05, 0x9B, 0xD9, 0x80, 0x46, 0xE7, 0x39, 0x33, 0xFA, 0x5C, 0xE0, 0xB2, 0x17, 0x21, 0xA5, 0xF7, 0x87, 0xFF, 0x2F, 0x21, ++0x28, 0x00, 0x7E, 0xF7, 0xD5, 0xFD, 0xAA, 0xE6, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x0A, 0xD0, 0xE0, 0xB2, 0xFF, 0xF7, ++0x13, 0xFE, 0x28, 0x00, 0x96, 0xF7, 0x3A, 0xFB, 0x2E, 0x21, 0x28, 0x00, 0x7E, 0xF7, 0xC6, 0xFD, 0x9B, 0xE6, 0x3C, 0x22, ++0x62, 0x43, 0x10, 0x4B, 0x9B, 0x18, 0xD9, 0x88, 0xE0, 0xB2, 0x03, 0x9B, 0x9F, 0x07, 0xFF, 0x0F, 0x01, 0x97, 0x53, 0x46, ++0x00, 0x93, 0x4B, 0x46, 0x32, 0x00, 0xAF, 0xF7, 0x5F, 0xFC, 0xE3, 0xE7, 0x39, 0x23, 0xFB, 0x5C, 0xE0, 0xB2, 0x20, 0x22, ++0x17, 0x21, 0xA5, 0xF7, 0x7A, 0xFF, 0x20, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x1B, 0xFE, 0x7E, 0xE6, 0x64, 0xA2, 0x16, 0x00, ++0x05, 0x06, 0x00, 0x00, 0x3A, 0x05, 0x00, 0x00, 0xC0, 0xA0, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x8A, 0xB0, 0x06, 0x00, 0x88, 0x46, 0x91, 0x46, 0x1D, 0x00, ++0x12, 0xAB, 0x1B, 0x88, 0x9C, 0x46, 0x04, 0x0A, 0xA2, 0x00, 0x9C, 0x4B, 0xD7, 0x58, 0x9C, 0x4B, 0x22, 0x01, 0x11, 0x1B, ++0x89, 0x00, 0x40, 0x46, 0xC8, 0x52, 0x5B, 0x18, 0x4A, 0x46, 0x5A, 0x80, 0x1D, 0x81, 0x62, 0x46, 0x5A, 0x81, 0x36, 0x23, ++0xFB, 0x5C, 0x00, 0x22, 0x92, 0x46, 0x01, 0x2B, 0x00, 0xD1, 0x87, 0xE0, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x91, 0x4A, ++0xD3, 0x18, 0x00, 0x22, 0x1A, 0x73, 0xA7, 0xF7, 0x29, 0xFE, 0x50, 0x44, 0x03, 0x01, 0x06, 0xD5, 0x23, 0x01, 0x1B, 0x1B, ++0x9B, 0x00, 0x8B, 0x4A, 0xD3, 0x18, 0x02, 0x22, 0x1A, 0x73, 0x02, 0xAB, 0x4A, 0x46, 0x02, 0x92, 0x42, 0x46, 0x5A, 0x60, ++0x2A, 0x00, 0x02, 0x2D, 0x00, 0xD9, 0x02, 0x22, 0x9A, 0x60, 0x6D, 0x00, 0x05, 0x95, 0x00, 0x23, 0x02, 0xAA, 0x93, 0x74, ++0x25, 0x00, 0x80, 0x35, 0x15, 0x82, 0x53, 0x46, 0x5B, 0x08, 0x9A, 0x46, 0x01, 0x23, 0x52, 0x46, 0x13, 0x40, 0x02, 0xAA, ++0xD3, 0x74, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, 0x7B, 0x4B, 0x9A, 0x42, 0x58, 0xD1, 0x36, 0x23, 0xFB, 0x5C, ++0x01, 0x2B, 0x6A, 0xD0, 0x02, 0xA8, 0xD4, 0xF7, 0x63, 0xF8, 0x00, 0x28, 0x00, 0xD0, 0x72, 0xE0, 0x08, 0x98, 0x22, 0x01, ++0x12, 0x1B, 0x92, 0x00, 0x71, 0x4B, 0x9B, 0x18, 0x98, 0x62, 0x07, 0x99, 0x59, 0x62, 0x04, 0x9A, 0xDA, 0x62, 0x05, 0x9A, ++0x00, 0x92, 0x1A, 0x63, 0x02, 0xAA, 0x12, 0x8A, 0x9A, 0x86, 0x00, 0x22, 0x9A, 0x63, 0x36, 0x33, 0x1A, 0x70, 0x36, 0x23, ++0xFB, 0x5C, 0x00, 0x2B, 0x6A, 0xD1, 0x80, 0xB2, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x65, 0x4A, 0xD3, 0x18, 0xD8, 0x80, ++0x07, 0x9D, 0x9D, 0x80, 0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, 0x63, 0xD0, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, ++0x5F, 0x4B, 0x9A, 0x42, 0x00, 0xD0, 0x72, 0xE0, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x5B, 0x4A, 0xD3, 0x18, 0x01, 0x22, ++0x5A, 0x73, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0xA4, 0xE0, 0xE0, 0xB2, 0xFF, 0xF7, 0x43, 0xFD, 0x30, 0x00, ++0x96, 0xF7, 0x6A, 0xFA, 0x2E, 0x21, 0x30, 0x00, 0x7E, 0xF7, 0xF6, 0xFC, 0x0A, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xF0, 0xBD, 0xE0, 0xB2, 0xAF, 0xF7, 0x1F, 0xFD, 0x82, 0x46, 0x72, 0xE7, 0xE0, 0xB2, 0x95, 0xF7, 0x40, 0xFE, ++0x02, 0x00, 0x03, 0x00, 0x02, 0x98, 0x82, 0x42, 0x07, 0xD2, 0x00, 0x92, 0x11, 0x00, 0xD4, 0xF7, 0x13, 0xFC, 0x43, 0x1C, ++0x00, 0x9A, 0x5A, 0x43, 0x93, 0xB2, 0x03, 0x9A, 0x93, 0x42, 0x93, 0xD8, 0x02, 0x93, 0x03, 0x93, 0x90, 0xE7, 0x02, 0xAB, ++0xDB, 0x7C, 0x01, 0x22, 0x53, 0x40, 0x02, 0xAA, 0xD3, 0x74, 0x04, 0x9B, 0x03, 0x33, 0x04, 0x93, 0x05, 0x9B, 0x00, 0x93, ++0x03, 0x33, 0x05, 0x93, 0x86, 0xE7, 0x08, 0x23, 0x14, 0x22, 0x00, 0x21, 0x3A, 0x48, 0x7E, 0xF7, 0x4B, 0xF9, 0x20, 0x23, ++0x03, 0x70, 0x45, 0x80, 0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, 0xFB, 0x5C, 0x03, 0x71, 0xCF, 0xF7, 0xA1, 0xFF, 0xBF, 0xE7, ++0x89, 0xB2, 0x80, 0xB2, 0x52, 0x46, 0xA5, 0xF7, 0x83, 0xFB, 0x8F, 0xE7, 0x43, 0x1C, 0x98, 0x46, 0x00, 0x2D, 0x05, 0xD1, ++0x2F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x28, 0x4A, ++0x91, 0x46, 0x99, 0x44, 0x29, 0x00, 0x40, 0x46, 0xD4, 0xF7, 0x56, 0xFC, 0x4B, 0x46, 0xD9, 0x80, 0x84, 0xE7, 0xE3, 0xB2, ++0x98, 0x46, 0x18, 0x00, 0x95, 0xF7, 0xEC, 0xFD, 0x05, 0x1E, 0x07, 0x9B, 0x99, 0x46, 0x05, 0xD1, 0x21, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x29, 0x00, 0x48, 0x46, 0xD4, 0xF7, 0x40, 0xFC, 0x00, 0x29, 0x00, 0xD0, ++0x76, 0xE7, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x16, 0x4A, 0xD3, 0x18, 0xD9, 0x88, 0x09, 0x9B, 0x00, 0x93, 0x08, 0x9B, ++0x01, 0x93, 0x00, 0x9B, 0x01, 0x9A, 0x9A, 0x1A, 0x8A, 0x18, 0x92, 0xB2, 0x40, 0x46, 0x95, 0xF7, 0x17, 0xFE, 0x81, 0x46, ++0x07, 0x9B, 0x98, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x0F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x08, 0x4D, 0xED, 0x18, 0x41, 0x46, 0x48, 0x46, 0xD4, 0xF7, 0x17, 0xFC, 0xE9, 0x80, ++0x4E, 0xE7, 0xE0, 0xB2, 0x01, 0x33, 0x00, 0x22, 0x17, 0x21, 0x95, 0xF7, 0x89, 0xFC, 0x53, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0xC0, 0xA0, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x00, 0x24, 0x00, 0x20, 0x0E, 0x4E, 0xA1, 0x27, 0xAF, 0x23, 0x98, 0x46, 0x0C, 0xE0, 0x42, 0x46, 0x9D, 0x5C, ++0x45, 0x19, 0xED, 0xB2, 0x48, 0x33, 0x18, 0x00, 0x80, 0xF7, 0x18, 0xFE, 0x28, 0x18, 0xC0, 0xB2, 0x01, 0x34, 0x07, 0x2C, ++0x07, 0xD0, 0xA3, 0x00, 0x9B, 0x59, 0x00, 0x2B, 0xF8, 0xD0, 0xDA, 0x5D, 0x00, 0x2A, 0xF5, 0xD1, 0xEA, 0xE7, 0x04, 0xBC, ++0x90, 0x46, 0xF0, 0xBD, 0x38, 0x27, 0x16, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x40, 0x4B, 0x1A, 0x78, 0x01, 0x2A, 0x01, 0xD0, ++0x05, 0xB0, 0xF0, 0xBD, 0x3E, 0x4B, 0x1D, 0x78, 0x3E, 0x4B, 0x1B, 0x68, 0x00, 0x24, 0x5B, 0x05, 0x08, 0xD5, 0x3C, 0x48, ++0x03, 0x68, 0x3C, 0x49, 0x19, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x0B, 0x43, 0x03, 0x60, 0x80, 0x34, 0x39, 0x4B, 0x1B, 0x68, ++0x9B, 0x05, 0x09, 0xD4, 0x37, 0x48, 0x03, 0x68, 0x37, 0x49, 0x19, 0x40, 0x80, 0x23, 0x9B, 0x00, 0x0B, 0x43, 0x03, 0x60, ++0x40, 0x23, 0x1C, 0x43, 0x34, 0x4B, 0x18, 0x68, 0x34, 0x4B, 0x19, 0x68, 0x34, 0x4B, 0x1E, 0x68, 0x8B, 0x07, 0x31, 0xD4, ++0xF0, 0x23, 0x03, 0x40, 0x30, 0x2B, 0x0E, 0xD0, 0x20, 0x2B, 0x1F, 0xD0, 0x10, 0x2B, 0x29, 0xD1, 0x2F, 0x4B, 0xDB, 0x69, ++0xB3, 0x42, 0x25, 0xD0, 0xF0, 0x23, 0x07, 0x00, 0x9F, 0x43, 0x3B, 0x00, 0x20, 0x27, 0x3B, 0x43, 0x0A, 0xE0, 0x2A, 0x4B, ++0xDB, 0x6B, 0xB3, 0x42, 0x1A, 0xD0, 0xF0, 0x23, 0x02, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x20, 0x22, 0x13, 0x43, 0x1D, 0x3A, ++0x22, 0x4F, 0x3F, 0x68, 0xBF, 0x07, 0x1F, 0xD4, 0x1F, 0x4F, 0x3B, 0x60, 0x14, 0x43, 0x1D, 0xE0, 0x20, 0x4B, 0xDB, 0x6A, ++0xB3, 0x42, 0x07, 0xD0, 0xF0, 0x23, 0x02, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x10, 0x22, 0x13, 0x43, 0x0E, 0x3A, 0xEB, 0xE7, ++0x01, 0x2D, 0xA3, 0xD1, 0x17, 0x4B, 0x1B, 0x68, 0x02, 0x93, 0x00, 0x23, 0x01, 0x93, 0x00, 0x90, 0x33, 0x00, 0x00, 0x22, ++0x16, 0x48, 0x80, 0xF7, 0x47, 0xF9, 0x00, 0x2C, 0x96, 0xD0, 0x0D, 0xE0, 0x04, 0x27, 0x3C, 0x43, 0x01, 0x2D, 0x00, 0xD0, ++0x90, 0xE7, 0x0E, 0x4D, 0x2D, 0x68, 0x02, 0x95, 0x01, 0x93, 0x00, 0x90, 0x33, 0x00, 0x0E, 0x48, 0x80, 0xF7, 0x36, 0xF9, ++0x32, 0x00, 0x21, 0x00, 0x0C, 0x48, 0x80, 0xF7, 0x31, 0xF9, 0x81, 0xE7, 0xB4, 0xE5, 0x10, 0x00, 0xBC, 0xE6, 0x10, 0x00, ++0x4C, 0x20, 0x62, 0x40, 0xFF, 0xF3, 0xFF, 0xFF, 0x58, 0x20, 0x62, 0x40, 0xFF, 0xFD, 0xFF, 0xFF, 0x08, 0x05, 0x62, 0x40, ++0x74, 0x20, 0x62, 0x40, 0x78, 0x20, 0x62, 0x40, 0xD8, 0x97, 0x16, 0x00, 0x24, 0xD1, 0x10, 0x00, 0x3C, 0xD1, 0x10, 0x00, ++0x70, 0x47, 0x00, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x13, 0x60, 0x81, 0x22, 0x52, 0x00, 0x98, 0x5C, 0x70, 0x47, 0xC0, 0x46, ++0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x17, 0x4B, 0x17, 0x4A, 0x1A, 0x60, ++0x17, 0x48, 0x80, 0xF7, 0x53, 0xFD, 0x45, 0x1E, 0x6D, 0xB2, 0x40, 0xB2, 0x00, 0x28, 0x1F, 0xDD, 0x11, 0x4F, 0x14, 0x4B, ++0x98, 0x46, 0x14, 0x4E, 0x0A, 0xE0, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x43, 0x46, 0x9B, 0x6E, 0x98, 0x47, 0x09, 0xE0, ++0x01, 0x3D, 0x6D, 0xB2, 0x6B, 0x1C, 0x0F, 0xD0, 0x38, 0x68, 0x0C, 0x30, 0x80, 0xF7, 0x56, 0xFC, 0x04, 0x1E, 0xEE, 0xD0, ++0x61, 0x6A, 0x30, 0x00, 0x80, 0xF7, 0xE2, 0xF8, 0x63, 0x6A, 0x00, 0x2B, 0xEE, 0xD0, 0x20, 0x00, 0x98, 0x47, 0xEB, 0xE7, ++0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x10, 0xE7, 0x10, 0x00, 0x64, 0x2A, 0x16, 0x00, 0x70, 0x2A, 0x16, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xC0, 0xD3, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x78, 0x21, 0x88, 0xF7, 0xAB, 0xF9, 0x05, 0x00, ++0x08, 0x4B, 0xC0, 0x18, 0x78, 0x22, 0x55, 0x21, 0x7C, 0xF7, 0x42, 0xF8, 0x29, 0x00, 0x20, 0x00, 0x88, 0xF7, 0xBA, 0xF9, ++0x01, 0x00, 0x20, 0x00, 0xB0, 0xF7, 0x1E, 0xFD, 0x02, 0x48, 0x80, 0xF7, 0xB7, 0xF8, 0x70, 0xBD, 0x00, 0x00, 0x61, 0x40, ++0x4C, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x04, 0x00, ++0x83, 0x00, 0x76, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1D, 0x68, 0x00, 0x2D, 0x00, 0xD1, 0xDE, 0xE0, 0x4B, 0x23, 0xEB, 0x5C, ++0x00, 0x2B, 0x05, 0xD0, 0x71, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x28, 0x00, 0x50, 0x30, ++0x80, 0xF7, 0x02, 0xFC, 0x07, 0x00, 0x00, 0x21, 0x20, 0x00, 0x88, 0xF7, 0xDF, 0xF9, 0x63, 0x01, 0x6A, 0x4A, 0x9A, 0x18, ++0x12, 0x68, 0xD2, 0x0F, 0x49, 0x21, 0x69, 0x5C, 0x01, 0x26, 0x71, 0x40, 0x91, 0x42, 0x4F, 0xD0, 0x66, 0x49, 0x8A, 0x46, ++0x9A, 0x44, 0x51, 0x46, 0x09, 0x68, 0x89, 0xB2, 0x8B, 0x46, 0x64, 0x4E, 0xB1, 0x46, 0x99, 0x44, 0x4E, 0x46, 0x36, 0x68, ++0xB6, 0xB2, 0xB0, 0x46, 0x61, 0x4E, 0x9E, 0x19, 0x36, 0x68, 0xB6, 0x03, 0xB1, 0x0F, 0x01, 0x91, 0x56, 0x46, 0x36, 0x68, ++0x36, 0x0C, 0x36, 0x04, 0xB4, 0x46, 0x56, 0x46, 0x61, 0x46, 0x31, 0x60, 0x49, 0x46, 0x09, 0x68, 0x09, 0x0C, 0x09, 0x04, ++0x8C, 0x46, 0x49, 0x46, 0x66, 0x46, 0x0E, 0x60, 0x00, 0x2F, 0x67, 0xD0, 0x00, 0x2A, 0x4C, 0xD1, 0x52, 0x4A, 0x94, 0x46, ++0x9C, 0x44, 0x62, 0x46, 0x12, 0x68, 0x91, 0x46, 0xBA, 0x88, 0x12, 0x04, 0x49, 0x46, 0x0F, 0x04, 0x3F, 0x0C, 0x3A, 0x43, ++0x61, 0x46, 0x0A, 0x60, 0x00, 0x28, 0x0A, 0xD0, 0x4B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x68, 0x82, 0x88, 0x04, 0x32, ++0x12, 0x04, 0x38, 0x04, 0x00, 0x0C, 0x02, 0x43, 0x1A, 0x60, 0x5B, 0x46, 0x00, 0x2B, 0x4C, 0xD1, 0x43, 0x46, 0x00, 0x2B, ++0x4E, 0xD1, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x3E, 0x49, 0x8A, 0x46, ++0x9A, 0x44, 0x51, 0x46, 0x09, 0x68, 0x09, 0x0C, 0x8B, 0x46, 0x3C, 0x49, 0x89, 0x46, 0x99, 0x44, 0x49, 0x46, 0x0E, 0x68, ++0x31, 0x0C, 0x88, 0x46, 0x39, 0x49, 0x5E, 0x18, 0x36, 0x68, 0x36, 0x03, 0xB1, 0x0F, 0x01, 0x91, 0x51, 0x46, 0x09, 0x68, ++0x09, 0x04, 0x09, 0x0C, 0x8C, 0x46, 0x51, 0x46, 0x66, 0x46, 0x0E, 0x60, 0x49, 0x46, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0C, ++0x8C, 0x46, 0x49, 0x46, 0x66, 0x46, 0x0E, 0x60, 0xAE, 0xE7, 0x2C, 0x4A, 0x94, 0x46, 0x9C, 0x44, 0x62, 0x46, 0x12, 0x68, ++0x12, 0x0C, 0x12, 0x04, 0xBF, 0x88, 0x3A, 0x43, 0x61, 0x46, 0x0A, 0x60, 0x00, 0x28, 0xC0, 0xD0, 0x26, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1F, 0x68, 0x82, 0x88, 0x04, 0x32, 0x92, 0xB2, 0x38, 0x0C, 0x00, 0x04, 0x02, 0x43, 0x1A, 0x60, 0xB4, 0xE7, ++0x00, 0x28, 0xB2, 0xD0, 0x00, 0x2A, 0xEF, 0xD1, 0xA4, 0xE7, 0x59, 0x46, 0x20, 0x00, 0x88, 0xF7, 0x17, 0xF9, 0xAD, 0xE7, ++0x46, 0x23, 0xE9, 0x5C, 0x09, 0x02, 0x45, 0x3B, 0x19, 0x43, 0x05, 0x33, 0xFF, 0x22, 0x1A, 0x48, 0x7D, 0xF7, 0xDE, 0xFE, ++0x07, 0x00, 0x43, 0x46, 0x03, 0x80, 0x58, 0x23, 0xEA, 0x5C, 0x01, 0x32, 0x2B, 0x8F, 0x53, 0x43, 0x83, 0x70, 0x01, 0x99, ++0xC1, 0x70, 0x14, 0x4B, 0x1A, 0x68, 0x01, 0x32, 0x1A, 0x60, 0x00, 0x29, 0x04, 0xD1, 0x3C, 0x71, 0x38, 0x00, 0x7D, 0xF7, ++0xF3, 0xFE, 0x90, 0xE7, 0x0F, 0x49, 0x0B, 0x68, 0x01, 0x33, 0x0B, 0x60, 0x01, 0x99, 0x0E, 0x48, 0x7F, 0xF7, 0xC4, 0xFF, ++0xF1, 0xE7, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x80, 0xE7, 0x54, 0x27, 0x16, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xD0, 0x05, 0x60, 0x40, 0xD8, 0x05, 0x60, 0x40, 0xDC, 0x05, 0x60, 0x40, 0xD4, 0x05, 0x60, 0x40, ++0x35, 0x06, 0x00, 0x00, 0xC4, 0xE6, 0x10, 0x00, 0xC0, 0xE6, 0x10, 0x00, 0x54, 0xD1, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, ++0x15, 0x00, 0x10, 0x00, 0x7E, 0xF7, 0x74, 0xFA, 0x00, 0x28, 0x03, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x07, 0xD8, ++0x21, 0x88, 0x04, 0x39, 0x89, 0xB2, 0x20, 0x79, 0x88, 0xF7, 0xFA, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0x2E, 0x0A, 0x06, 0x23, ++0x2A, 0x00, 0x31, 0x00, 0x1B, 0x48, 0x7D, 0xF7, 0x89, 0xFE, 0x05, 0x00, 0x23, 0x88, 0x83, 0x80, 0xA3, 0x78, 0x83, 0x70, ++0x21, 0x79, 0x01, 0x31, 0x09, 0x02, 0x80, 0x36, 0x89, 0x19, 0x01, 0x80, 0xE1, 0x78, 0x0A, 0x03, 0x14, 0x4B, 0x1A, 0x42, ++0x06, 0xD0, 0xC0, 0x20, 0x13, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x80, 0x01, 0xB0, 0x47, 0x2B, 0x88, 0x0F, 0x4A, ++0x13, 0x40, 0xE2, 0x78, 0x12, 0x03, 0x13, 0x43, 0x2B, 0x80, 0xE3, 0x78, 0x00, 0x2B, 0x03, 0xD1, 0x28, 0x00, 0xCF, 0xF7, ++0xC5, 0xFC, 0xD1, 0xE7, 0xA2, 0x78, 0x20, 0x88, 0x09, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x7B, 0xF7, 0xE0, 0xFE, ++0xE1, 0x78, 0x00, 0x29, 0xF0, 0xD0, 0x06, 0x48, 0x7F, 0xF7, 0x5A, 0xFF, 0xEC, 0xE7, 0xC0, 0x46, 0x07, 0x11, 0x00, 0x00, ++0xFF, 0xCF, 0xFF, 0xFF, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0x6C, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0x89, 0xB0, ++0x04, 0x1E, 0x00, 0xD1, 0xAB, 0xE0, 0x46, 0x23, 0xC6, 0x5C, 0xB2, 0x00, 0x5A, 0x4B, 0xD5, 0x58, 0x00, 0x2D, 0x00, 0xD1, ++0xA9, 0xE0, 0x43, 0x68, 0x02, 0x3B, 0x1B, 0x01, 0x1B, 0x09, 0xC3, 0x62, 0x28, 0x30, 0xD2, 0xF7, 0xE9, 0xFD, 0x62, 0x68, ++0x61, 0x6B, 0x8A, 0x42, 0x13, 0xD0, 0x45, 0x23, 0xE3, 0x5C, 0x5B, 0x00, 0x5B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x9A, 0x42, ++0x0B, 0xD0, 0x4F, 0x4B, 0x9B, 0x7A, 0xA3, 0x75, 0x4A, 0x23, 0xE3, 0x5C, 0x03, 0x2B, 0x00, 0xD0, 0x8D, 0xE0, 0x47, 0x33, ++0x00, 0x22, 0xE2, 0x54, 0x89, 0xE0, 0x4A, 0x4B, 0x00, 0x93, 0x01, 0x92, 0xA3, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1E, 0x76, ++0x47, 0x23, 0xE0, 0x5C, 0x03, 0x01, 0x33, 0x43, 0x04, 0x93, 0x00, 0x23, 0x9C, 0x46, 0x03, 0x93, 0xA7, 0x7D, 0x6B, 0x46, ++0x1F, 0x75, 0x67, 0x46, 0x5F, 0x75, 0x9F, 0x75, 0x8A, 0x42, 0x00, 0xD1, 0x73, 0xE0, 0x10, 0x23, 0x6A, 0x46, 0xD3, 0x75, ++0x0C, 0x3B, 0x6A, 0x46, 0x93, 0x76, 0xD0, 0x76, 0x01, 0x23, 0x53, 0x76, 0x68, 0x46, 0xD3, 0xF7, 0x9B, 0xF8, 0x48, 0x22, ++0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x01, 0x21, 0x63, 0x68, 0x62, 0x6B, 0x93, 0x42, 0x35, 0xD0, 0x47, 0x23, 0xE3, 0x5C, ++0x33, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x5B, 0x01, 0x1A, 0x68, 0x32, 0x48, 0x02, 0x40, 0x09, 0x04, 0x0A, 0x43, 0x1A, 0x60, ++0x9F, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0xB6, 0xD1, 0x2B, 0x6D, 0x5F, 0x1C, 0x7F, 0x08, 0xAB, 0x6F, 0x9B, 0xB2, 0x62, 0x22, ++0x56, 0x43, 0x2B, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0xAB, 0x6F, 0x1B, 0x0C, 0x29, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0x80, 0x23, ++0x9B, 0x01, 0x9F, 0x42, 0x2B, 0xD3, 0x27, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0xF9, 0xF8, 0x00, 0x29, 0x19, 0xD0, 0x25, 0x4B, ++0x9C, 0x46, 0x66, 0x44, 0x22, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0x6A, 0xF8, 0x01, 0x30, 0x22, 0x4B, 0x03, 0x43, 0x9B, 0xB2, ++0x33, 0x80, 0x90, 0xE7, 0x20, 0x4B, 0x2A, 0x6D, 0x9A, 0x42, 0xC5, 0xD8, 0x4A, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0xC1, 0xD1, ++0x44, 0x33, 0xE1, 0x5C, 0x01, 0x31, 0xC9, 0xB2, 0xBC, 0xE7, 0x18, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0x15, 0x49, 0x38, 0x00, ++0xD4, 0xF7, 0x50, 0xF8, 0x15, 0x4B, 0x03, 0x43, 0x9B, 0xB2, 0x33, 0x80, 0x77, 0xE7, 0x01, 0x37, 0x7F, 0x08, 0xBF, 0xB2, ++0x10, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0x37, 0x80, 0x6F, 0xE7, 0x11, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0x09, 0xB0, 0xF0, 0xBD, 0x0F, 0x23, 0x6A, 0x46, 0xD3, 0x75, 0x0D, 0x3B, 0x8A, 0xE7, 0x38, 0x27, 0x16, 0x00, ++0x7C, 0x91, 0x0D, 0x00, 0x5D, 0x74, 0x0B, 0x00, 0x2F, 0x00, 0x03, 0x02, 0xFF, 0xFF, 0x00, 0xFF, 0xFA, 0x64, 0x61, 0x40, ++0xFC, 0x64, 0x61, 0x40, 0x71, 0x02, 0x00, 0x00, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0xE1, 0x04, 0x00, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x06, 0x00, 0x14, 0x4B, 0x1D, 0x68, 0x00, 0x2D, 0x05, 0xD1, 0x5D, 0x68, 0x00, 0x2D, ++0x02, 0xD1, 0x00, 0x24, 0x20, 0x00, 0xF8, 0xBD, 0xAB, 0x68, 0x2A, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x00, 0x0E, 0x49, ++0x18, 0x00, 0xD4, 0xF7, 0x09, 0xF8, 0x6C, 0x6B, 0x04, 0x19, 0x0B, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0x89, 0xF8, 0xB3, 0x68, ++0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x64, 0x18, 0xB1, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, 0xE3, 0xD0, ++0x20, 0x00, 0xFC, 0xF7, 0x63, 0xFF, 0x04, 0x00, 0xDE, 0xE7, 0xC0, 0x46, 0x54, 0x27, 0x16, 0x00, 0x71, 0x02, 0x00, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0xB0, 0xBD, 0x4B, 0x1C, 0x68, 0xA1, 0x46, ++0xBC, 0x4B, 0xA3, 0x82, 0x4C, 0x23, 0xE3, 0x5A, 0x5B, 0x00, 0x62, 0x6C, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, ++0xE3, 0x60, 0xA7, 0xF7, 0x5D, 0xF9, 0x04, 0x90, 0xB6, 0x4B, 0x1B, 0x68, 0x01, 0x93, 0xB6, 0x4B, 0x1B, 0x68, 0x02, 0x93, ++0xB5, 0x4B, 0x1B, 0x68, 0x07, 0x93, 0xB5, 0x4B, 0x1B, 0x68, 0x06, 0x93, 0x00, 0x25, 0x00, 0x20, 0x00, 0x27, 0x00, 0x23, ++0x03, 0x93, 0x00, 0x26, 0xB1, 0x4B, 0x98, 0x46, 0xA1, 0x23, 0x9A, 0x46, 0x02, 0x3B, 0x9B, 0x46, 0x0F, 0xE0, 0x01, 0x37, ++0xFF, 0xB2, 0xAF, 0x22, 0x9E, 0x5C, 0x86, 0x19, 0xF6, 0xB2, 0x48, 0x33, 0x18, 0x00, 0x80, 0xF7, 0x5F, 0xFA, 0x30, 0x18, ++0xC0, 0xB2, 0x01, 0x26, 0x01, 0x35, 0x07, 0x2D, 0x0E, 0xD0, 0xAB, 0x00, 0x42, 0x46, 0x9B, 0x58, 0x00, 0x2B, 0xF7, 0xD0, ++0x52, 0x46, 0x9A, 0x5C, 0x00, 0x2A, 0xF3, 0xD1, 0x5A, 0x46, 0x9A, 0x5C, 0x01, 0x2A, 0xE2, 0xD1, 0x03, 0x92, 0xE0, 0xE7, ++0x9F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x00, 0x23, 0x01, 0x32, 0xBA, 0x42, 0x5B, 0x41, 0x02, 0x33, 0x9C, 0x4A, 0x13, 0x70, ++0x83, 0x42, 0x08, 0xD8, 0x00, 0x22, 0x03, 0x28, 0x01, 0xD9, 0xC2, 0x1E, 0xD2, 0xB2, 0xC0, 0x1A, 0x10, 0x18, 0x96, 0x4B, ++0x18, 0x70, 0x50, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x95, 0x4B, 0x19, 0x00, 0x41, 0x31, 0xFF, 0x31, 0x00, 0x25, 0x04, 0xE0, ++0x01, 0x35, 0xED, 0xB2, 0x40, 0x33, 0x8B, 0x42, 0x07, 0xD0, 0x1A, 0x78, 0x09, 0x2A, 0xF9, 0xD1, 0x00, 0x2F, 0xF5, 0xD0, ++0x01, 0x37, 0xFF, 0xB2, 0xF2, 0xE7, 0xB0, 0xF7, 0x5F, 0xFA, 0x05, 0x90, 0x80, 0x46, 0x02, 0x9B, 0x01, 0x9A, 0x13, 0x43, ++0x5A, 0x1E, 0x93, 0x41, 0xDB, 0xB2, 0x9B, 0x46, 0x87, 0x4B, 0x1B, 0x78, 0x9A, 0x46, 0x00, 0x2B, 0x00, 0xD1, 0x79, 0xE0, ++0x85, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x28, 0xD9, 0x02, 0x2B, 0x64, 0xD0, 0x8C, 0xF7, 0xDC, 0xF8, 0x82, 0x46, 0x00, 0x28, ++0x00, 0xD1, 0x1B, 0xE2, 0x00, 0x23, 0x9A, 0x46, 0x7F, 0x4B, 0x23, 0x64, 0x02, 0x22, 0x62, 0x63, 0xFA, 0x22, 0x92, 0x01, ++0xA2, 0x62, 0x19, 0x00, 0x23, 0x61, 0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x77, 0xE0, 0xA3, 0x6A, 0x62, 0x6B, 0x98, 0x1A, ++0x40, 0x00, 0x04, 0x9B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x01, 0x2D, 0x00, 0xD1, 0x84, 0xE1, ++0x00, 0x22, 0x20, 0x00, 0xFC, 0xF7, 0x9A, 0xFF, 0x11, 0xE0, 0x71, 0x4B, 0x23, 0x64, 0x80, 0x22, 0x62, 0x63, 0xA2, 0x62, ++0x6C, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x16, 0x22, 0xA2, 0x75, 0x23, 0x61, 0x04, 0x98, 0x2C, 0x30, 0x00, 0x01, 0x00, 0x09, ++0x60, 0x60, 0x00, 0x23, 0x9A, 0x46, 0x69, 0x4E, 0x4C, 0x25, 0x69, 0x4F, 0x48, 0x46, 0xD1, 0xF7, 0x33, 0xFF, 0x00, 0x28, ++0x00, 0xD1, 0xB0, 0xE1, 0x31, 0x00, 0x20, 0x69, 0xD3, 0xF7, 0x16, 0xFF, 0x63, 0x68, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x01, ++0x00, 0x09, 0x60, 0x60, 0x63, 0x5B, 0x5B, 0x00, 0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x60, ++0xA3, 0x7D, 0x5D, 0x4A, 0xD2, 0x78, 0x9B, 0x18, 0xA3, 0x75, 0x59, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0xBE, 0x42, 0xDD, 0xD1, ++0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x56, 0x4B, 0x1B, 0x68, 0x5B, 0x00, ++0x23, 0x64, 0x02, 0x23, 0x63, 0x63, 0x4E, 0x33, 0xA3, 0x62, 0x4C, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0x49, 0x4B, 0x00, 0x22, ++0x1A, 0x70, 0x8B, 0xE7, 0xFD, 0xF7, 0x12, 0xF8, 0x00, 0x28, 0x04, 0xD1, 0x4D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x00, 0xD1, ++0x11, 0xE1, 0x43, 0x46, 0x00, 0x2B, 0x2C, 0xD0, 0x4A, 0x4B, 0x23, 0x64, 0x04, 0x23, 0x63, 0x63, 0x08, 0x33, 0xA3, 0x62, ++0x8C, 0xF7, 0x56, 0xF8, 0x00, 0x28, 0x00, 0xD0, 0x7C, 0xE7, 0x23, 0x6C, 0x23, 0x61, 0x20, 0x00, 0xFF, 0xF7, 0xAE, 0xFE, ++0x53, 0x46, 0x00, 0x2B, 0x00, 0xD1, 0x95, 0xE1, 0xC0, 0x30, 0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x18, 0x26, 0x4F, 0x46, ++0x65, 0x68, 0x00, 0x22, 0x21, 0x69, 0x38, 0x00, 0xFC, 0xF7, 0x20, 0xFF, 0x63, 0x68, 0xAB, 0x42, 0x00, 0xD1, 0x4A, 0xE1, ++0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x18, 0x36, 0x90, 0x2E, 0xEE, 0xD1, 0xB9, 0x46, 0x8B, 0xE7, 0x5B, 0x46, ++0x00, 0x2B, 0x21, 0xD0, 0x33, 0x4B, 0x1B, 0x68, 0x5B, 0x00, 0x23, 0x64, 0xE3, 0x6B, 0x63, 0x63, 0x23, 0x6B, 0xA3, 0x62, ++0x03, 0x9B, 0x00, 0x2B, 0x05, 0xD0, 0x2F, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0x46, 0x33, 0xA3, 0x62, 0xB2, 0x46, ++0x00, 0x2E, 0x00, 0xD1, 0xD4, 0xE0, 0x05, 0x9A, 0x92, 0x46, 0x01, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0xCE, 0xE0, 0x28, 0x4B, ++0x1B, 0x68, 0xA1, 0x6A, 0x8C, 0x46, 0x63, 0x44, 0xA3, 0x62, 0xC7, 0xE0, 0x15, 0x4B, 0x1B, 0x78, 0x5A, 0x00, 0x9B, 0x18, ++0x5B, 0x00, 0xDB, 0xB2, 0x01, 0x2F, 0x49, 0xD9, 0x21, 0x4A, 0x22, 0x64, 0x1A, 0x22, 0x62, 0x63, 0x2C, 0x32, 0xA2, 0x62, ++0x00, 0x2B, 0x03, 0xD0, 0x1E, 0x4B, 0x23, 0x64, 0x14, 0x23, 0x63, 0x63, 0x00, 0x2D, 0x03, 0xD0, 0x1C, 0x4B, 0x23, 0x64, ++0x10, 0x23, 0x63, 0x63, 0x63, 0x6B, 0xA3, 0x62, 0xDA, 0x46, 0xA9, 0xE0, 0xF8, 0xE6, 0x10, 0x00, 0x00, 0xA0, 0xFF, 0xFF, ++0x24, 0x27, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0x28, 0x27, 0x16, 0x00, 0x20, 0x27, 0x16, 0x00, 0x38, 0x27, 0x16, 0x00, ++0xB1, 0xE6, 0x10, 0x00, 0xD1, 0xE6, 0x10, 0x00, 0x70, 0xA6, 0x16, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, ++0xC4, 0x09, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, ++0x04, 0xE2, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x08, 0xE2, 0x10, 0x00, 0xDC, 0x82, 0x00, 0x00, ++0x14, 0xE2, 0x10, 0x00, 0xE8, 0x80, 0x00, 0x00, 0xF6, 0x54, 0x00, 0x00, 0xF2, 0x2B, 0x00, 0x00, 0x85, 0x4A, 0x5A, 0x43, ++0x03, 0x99, 0x00, 0x29, 0x33, 0xD0, 0x84, 0x49, 0x09, 0x68, 0x49, 0x00, 0x8A, 0x42, 0x29, 0xD8, 0x8A, 0x1A, 0x22, 0x64, ++0x28, 0x22, 0xD3, 0x1A, 0x63, 0x63, 0xE3, 0x6A, 0xA3, 0x62, 0x7F, 0x4B, 0x22, 0x6C, 0x9A, 0x42, 0x4B, 0xD9, 0xDA, 0x46, ++0x00, 0x2F, 0x5D, 0xD0, 0x07, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0xC4, 0xE0, 0x59, 0x68, 0x06, 0x9A, 0x00, 0x2A, 0x00, 0xD1, ++0xC4, 0xE0, 0x78, 0x4B, 0x99, 0x42, 0x00, 0xD1, 0xBE, 0xE0, 0x52, 0x68, 0x53, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x20, ++0x00, 0x05, 0x83, 0x42, 0x00, 0xD8, 0xBA, 0xE0, 0x8B, 0x1A, 0x1B, 0x01, 0x00, 0xD1, 0xB6, 0xE0, 0x11, 0x00, 0xB1, 0xE0, ++0x6F, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0xD5, 0xE7, 0x00, 0x2D, 0x0D, 0xD0, 0x6D, 0x4B, 0x23, 0x64, 0x10, 0x23, ++0x63, 0x63, 0xA3, 0x62, 0x01, 0x2D, 0x02, 0xD0, 0x01, 0x23, 0x9A, 0x46, 0xD0, 0xE7, 0x40, 0x33, 0x01, 0x22, 0xE2, 0x54, ++0xF8, 0xE7, 0x67, 0x49, 0x09, 0x68, 0x49, 0x00, 0x8A, 0x42, 0x0D, 0xD8, 0x8A, 0x1A, 0x22, 0x64, 0xA2, 0x6B, 0xD3, 0x1A, ++0x63, 0x63, 0xE3, 0x6A, 0xA3, 0x62, 0x5D, 0x4B, 0x22, 0x6C, 0x9A, 0x42, 0x09, 0xD9, 0x03, 0x9B, 0x9A, 0x46, 0xB9, 0xE7, ++0x5B, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0xF1, 0xE7, 0x00, 0x2D, 0x05, 0xD1, 0x58, 0x4B, 0x23, 0x64, 0x1A, 0x23, ++0x63, 0x63, 0xDA, 0x46, 0xAC, 0xE7, 0xDA, 0x46, 0xAA, 0xE7, 0x50, 0x4B, 0x23, 0x64, 0x02, 0x23, 0x63, 0x63, 0x43, 0x46, ++0x00, 0x2B, 0x0B, 0xD1, 0x30, 0x33, 0xA3, 0x62, 0x2F, 0x3B, 0x9A, 0x46, 0x8B, 0xF7, 0x42, 0xFF, 0x00, 0x28, 0x00, 0xD0, ++0x68, 0xE6, 0x21, 0x6C, 0x21, 0x61, 0x72, 0xE6, 0xC0, 0x23, 0xA3, 0x62, 0x05, 0x9B, 0x9A, 0x46, 0xDE, 0xE6, 0x00, 0x23, ++0x08, 0x93, 0x09, 0x93, 0x20, 0x1D, 0x23, 0x00, 0x08, 0xAA, 0x09, 0xA9, 0xFC, 0xF7, 0x72, 0xFD, 0x09, 0x9B, 0x00, 0x2B, ++0x04, 0xD0, 0x22, 0x69, 0x9A, 0x42, 0x00, 0xD9, 0x1A, 0x00, 0x22, 0x61, 0x00, 0x2F, 0x07, 0xD0, 0x08, 0x9B, 0x5B, 0x00, ++0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x63, 0x6B, 0x02, 0x2B, 0x1E, 0xD0, 0x53, 0x46, ++0x00, 0x2B, 0x04, 0xD1, 0x3A, 0x4B, 0x08, 0x9A, 0x53, 0x43, 0x23, 0x61, 0x23, 0x64, 0x03, 0x26, 0x4F, 0x46, 0x65, 0x68, ++0x00, 0x22, 0x21, 0x69, 0x38, 0x00, 0xFC, 0xF7, 0xEB, 0xFD, 0x63, 0x68, 0xAB, 0x42, 0x18, 0xD0, 0x08, 0x9B, 0x9C, 0x46, ++0x65, 0x44, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xEC, 0xD1, 0xB9, 0x46, 0x54, 0xE6, ++0x08, 0x9A, 0x53, 0x00, 0x9B, 0x18, 0x5B, 0x00, 0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, ++0xD5, 0xE7, 0xB9, 0x46, 0x47, 0xE6, 0xB9, 0x46, 0x45, 0xE6, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xA3, 0x7D, 0x10, 0x2B, ++0x00, 0xD9, 0x63, 0xE6, 0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x5F, 0xE6, 0x53, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x5B, 0xE6, ++0x11, 0x33, 0xA3, 0x75, 0x58, 0xE6, 0x06, 0x9B, 0x00, 0x2B, 0x91, 0xD0, 0x06, 0x9B, 0x59, 0x68, 0x15, 0x4B, 0x99, 0x42, ++0x8C, 0xD0, 0x63, 0x6B, 0x1A, 0x00, 0x28, 0x32, 0x52, 0x00, 0xA0, 0x6A, 0xC3, 0x1A, 0x5B, 0x00, 0x04, 0x98, 0x84, 0x46, ++0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x9A, 0x42, 0x00, 0xD2, 0x7A, 0xE7, 0x0C, 0x4B, ++0x23, 0x64, 0x77, 0xE7, 0x21, 0x6C, 0x21, 0x61, 0x43, 0x46, 0x00, 0x2B, 0x04, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x14, 0xFD, ++0x60, 0x60, 0x6B, 0xE6, 0x05, 0x9B, 0x9A, 0x46, 0xE5, 0xE5, 0xC0, 0x46, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xE2, 0x10, 0x00, ++0xE7, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xE8, 0x80, 0x00, 0x00, 0xF2, 0x2B, 0x00, 0x00, 0x04, 0xE2, 0x10, 0x00, ++0xA9, 0x03, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x1A, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x19, 0x4B, ++0x9B, 0x78, 0x83, 0x75, 0xFC, 0xF7, 0x06, 0xFE, 0x05, 0x00, 0x02, 0x21, 0x01, 0x20, 0xFC, 0xF7, 0xC3, 0xFE, 0x06, 0x00, ++0x00, 0x2D, 0x04, 0xD0, 0x11, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x4E, 0x23, 0xE3, 0x5C, 0x02, 0x2B, ++0x0E, 0xD0, 0xA6, 0xF7, 0x83, 0xFE, 0x60, 0x64, 0xFF, 0xF7, 0x0C, 0xFD, 0x00, 0x2E, 0x0E, 0xD0, 0x00, 0x2D, 0x04, 0xD0, ++0x08, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x70, 0xBD, 0x07, 0x4C, 0x20, 0x68, 0x7D, 0xF7, 0xB8, 0xFB, ++0x00, 0x23, 0x23, 0x60, 0xEE, 0xE7, 0x02, 0x21, 0x00, 0x20, 0xFC, 0xF7, 0x9D, 0xFE, 0xEB, 0xE7, 0xFC, 0x00, 0x60, 0x40, ++0x7C, 0x91, 0x0D, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x10, 0xBD, ++0x00, 0x21, 0xD1, 0xF7, 0x8F, 0xFE, 0xFF, 0xF7, 0xE5, 0xFC, 0xF8, 0xE7, 0x10, 0xB5, 0xA6, 0xF7, 0x55, 0xFE, 0x22, 0x4B, ++0x5A, 0x68, 0x92, 0x01, 0x1B, 0x68, 0xC0, 0x1A, 0x00, 0x01, 0x01, 0x09, 0x40, 0x00, 0x43, 0x1A, 0x9B, 0x00, 0x5B, 0x18, ++0x99, 0x00, 0x5B, 0x18, 0x9A, 0x42, 0x20, 0xD3, 0xD3, 0x1A, 0x1B, 0x4C, 0x9C, 0x42, 0xA4, 0x41, 0x64, 0x42, 0x1A, 0x4B, ++0x1A, 0x4A, 0x1A, 0x60, 0xD1, 0xF7, 0xC0, 0xFE, 0x00, 0x28, 0x0A, 0xD0, 0x00, 0x2C, 0x19, 0xD0, 0x17, 0x4B, 0x80, 0x22, ++0x12, 0x05, 0x1A, 0x60, 0x16, 0x48, 0x7F, 0xF7, 0x05, 0xFB, 0x10, 0xBD, 0x00, 0x24, 0x11, 0x4B, 0x1B, 0x68, 0x9B, 0x68, ++0x00, 0x2B, 0xF1, 0xD0, 0x12, 0x4A, 0xDB, 0x69, 0x93, 0x42, 0xEB, 0xD1, 0xEC, 0xE7, 0x0C, 0x4B, 0x0C, 0x4A, 0x1A, 0x60, ++0xD1, 0xF7, 0xA4, 0xFE, 0x00, 0x28, 0xED, 0xD0, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x0D, 0x4B, 0x00, 0x22, 0x1A, 0x70, ++0x0C, 0x4B, 0x18, 0x68, 0x00, 0x28, 0xE2, 0xD0, 0xFF, 0xF7, 0xAE, 0xFF, 0xDF, 0xE7, 0xC0, 0x46, 0x6C, 0xE6, 0x10, 0x00, ++0xFF, 0x70, 0x02, 0x00, 0x10, 0xE7, 0x10, 0x00, 0x64, 0x2A, 0x16, 0x00, 0x00, 0x41, 0x04, 0x40, 0x74, 0xD1, 0x10, 0x00, ++0xC9, 0x1F, 0x10, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0xF8, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x49, 0x4B, 0x1C, 0x68, 0xA4, 0x04, ++0xA4, 0x0E, 0x20, 0x00, 0x50, 0x43, 0x43, 0x01, 0x1B, 0x1A, 0x9B, 0x00, 0x1B, 0x18, 0x98, 0x00, 0x18, 0x18, 0x00, 0x02, ++0xD3, 0xF7, 0x5E, 0xFC, 0x81, 0x46, 0x03, 0x0A, 0x9B, 0x46, 0x29, 0x00, 0x80, 0x20, 0xC0, 0x00, 0xD3, 0xF7, 0x56, 0xFC, ++0x03, 0x00, 0x6B, 0x43, 0x9A, 0x46, 0xFF, 0x21, 0x4B, 0x46, 0x19, 0x40, 0x69, 0x43, 0x09, 0x0A, 0x48, 0x43, 0x53, 0x46, ++0x1B, 0x1A, 0x98, 0x46, 0x23, 0x01, 0x1B, 0x19, 0x9B, 0x00, 0x99, 0x46, 0xA1, 0x44, 0x53, 0x46, 0x00, 0x2B, 0x05, 0xD1, ++0x34, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x78, 0x01, 0xC0, 0x1B, 0x80, 0x00, 0xC7, 0x19, ++0xB8, 0x00, 0x38, 0x18, 0x29, 0x00, 0xD3, 0xF7, 0x33, 0xFC, 0x44, 0x43, 0x27, 0x00, 0x65, 0x09, 0x73, 0x01, 0x2C, 0x4A, ++0x9A, 0x18, 0x11, 0x68, 0x2B, 0x4A, 0x11, 0x60, 0x2B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x68, 0x2A, 0x4B, 0x1A, 0x60, ++0x2A, 0x4B, 0x5A, 0x46, 0x1A, 0x60, 0x51, 0x46, 0x48, 0x46, 0xD3, 0xF7, 0xA3, 0xFC, 0x09, 0x05, 0x43, 0x46, 0x19, 0x43, ++0x26, 0x4B, 0x19, 0x60, 0x26, 0x4B, 0x52, 0x46, 0x1A, 0x60, 0x26, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x25, 0x4B, 0x9E, 0x22, ++0xFF, 0x32, 0x99, 0x5C, 0x09, 0x02, 0x01, 0x3A, 0x9A, 0x5C, 0x0A, 0x43, 0x12, 0x04, 0x9C, 0x21, 0xFF, 0x31, 0x58, 0x5C, ++0x00, 0x02, 0x01, 0x39, 0x59, 0x5C, 0x01, 0x43, 0x0A, 0x43, 0x1E, 0x49, 0x0A, 0x60, 0xA0, 0x22, 0xFF, 0x32, 0x98, 0x5C, ++0x00, 0x02, 0x01, 0x3A, 0x9C, 0x5C, 0x04, 0x43, 0x24, 0x04, 0x20, 0x00, 0x28, 0x43, 0x01, 0x35, 0x6D, 0x01, 0xEC, 0x1B, ++0x24, 0x04, 0x04, 0x43, 0x16, 0x4A, 0x14, 0x60, 0x9A, 0x22, 0xFF, 0x32, 0x98, 0x5C, 0x00, 0x02, 0x01, 0x3A, 0x9B, 0x5C, ++0x03, 0x43, 0x36, 0x02, 0x1E, 0x43, 0x01, 0x20, 0x06, 0x43, 0x11, 0x4B, 0x1E, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, 0xC0, 0x46, 0x08, 0x04, 0x60, 0x40, 0x28, 0x19, 0x16, 0x00, 0xDC, 0x05, 0x60, 0x40, ++0x5C, 0x06, 0x60, 0x40, 0xD8, 0x05, 0x60, 0x40, 0x60, 0x06, 0x60, 0x40, 0x50, 0x06, 0x60, 0x40, 0x54, 0x06, 0x60, 0x40, ++0x58, 0x06, 0x60, 0x40, 0x4C, 0x06, 0x60, 0x40, 0x20, 0xA3, 0x16, 0x00, 0x44, 0x06, 0x60, 0x40, 0x48, 0x06, 0x60, 0x40, ++0x40, 0x06, 0x60, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8F, 0xB0, 0x80, 0x46, ++0x0E, 0x00, 0x15, 0x00, 0x03, 0x93, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x17, 0x00, 0x1F, 0x40, 0x1A, 0x42, 0x00, 0xD0, ++0xF6, 0xE2, 0x72, 0xB6, 0x00, 0x21, 0x5C, 0x20, 0x7D, 0xF7, 0xCE, 0xF9, 0x04, 0x1E, 0x00, 0xD1, 0x25, 0xE3, 0x00, 0x20, ++0x00, 0x2F, 0x00, 0xD0, 0xF1, 0xE2, 0x62, 0xB6, 0x00, 0x28, 0x00, 0xD1, 0xED, 0xE2, 0x0F, 0xB0, 0x3C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xDE, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x0C, 0x20, 0x00, 0x2F, 0xEF, 0xD1, 0xEA, 0xE7, 0x00, 0x23, 0x06, 0x93, 0xEC, 0xE2, 0x01, 0x23, 0x06, 0x93, 0xE9, 0xE2, ++0x00, 0x23, 0x5B, 0x00, 0xD6, 0x4A, 0xD3, 0x18, 0x5F, 0x78, 0xBA, 0x46, 0xBF, 0xE0, 0x2F, 0x7B, 0xD4, 0x4B, 0x19, 0x00, ++0x00, 0x22, 0x08, 0x78, 0xB8, 0x42, 0x00, 0xD1, 0xAD, 0xE0, 0x01, 0x32, 0x02, 0x31, 0x08, 0x2A, 0xF7, 0xD1, 0x02, 0x27, ++0x68, 0x7B, 0x00, 0x22, 0x19, 0x78, 0x81, 0x42, 0x00, 0xD1, 0xA7, 0xE0, 0x01, 0x32, 0x02, 0x33, 0x08, 0x2A, 0xF7, 0xD1, ++0x02, 0x23, 0x9A, 0x46, 0x09, 0x2F, 0x05, 0xD9, 0xC5, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x07, 0x97, 0xD3, 0x46, 0xC4, 0x4A, 0x7B, 0x00, 0xDF, 0x19, 0xD7, 0x19, 0x53, 0x46, 0x5B, 0x00, 0x53, 0x44, 0xD2, 0x18, ++0xBF, 0x78, 0x93, 0x78, 0xFF, 0x18, 0xFB, 0xB2, 0x1F, 0x00, 0x05, 0x93, 0x28, 0x7C, 0x19, 0x00, 0xD3, 0xF7, 0x48, 0xFB, ++0xC0, 0xB2, 0xBC, 0x4B, 0x63, 0x62, 0xBC, 0x4B, 0xE3, 0x61, 0xBC, 0x4B, 0x23, 0x62, 0x03, 0x23, 0x23, 0x76, 0xBB, 0x4B, ++0x9B, 0x7A, 0xA3, 0x75, 0xBA, 0x4A, 0x9F, 0x23, 0x9B, 0x00, 0xD2, 0x5C, 0x00, 0x23, 0x00, 0x2A, 0x02, 0xD1, 0x7B, 0x00, ++0x03, 0x33, 0xDB, 0xB2, 0xE3, 0x75, 0x00, 0x23, 0xA3, 0x82, 0x06, 0x33, 0x63, 0x76, 0x40, 0x33, 0x42, 0x46, 0xE2, 0x54, ++0x01, 0x33, 0xE6, 0x54, 0xEB, 0x88, 0x23, 0x87, 0x2B, 0x89, 0x63, 0x87, 0xAA, 0x7A, 0x3D, 0x23, 0xE2, 0x54, 0xEA, 0x7A, ++0x01, 0x33, 0xE2, 0x54, 0x2A, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0x6A, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0xAA, 0x7B, 0x01, 0x33, ++0xE2, 0x54, 0xEA, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0x6A, 0x7C, 0x01, 0x33, 0xE2, 0x54, 0x01, 0x33, 0xE0, 0x54, 0x9B, 0x4A, ++0xB0, 0x33, 0xD3, 0x58, 0x23, 0x63, 0xAA, 0x78, 0x4B, 0x23, 0xE2, 0x54, 0x2B, 0x7C, 0x05, 0x99, 0x8C, 0x46, 0x63, 0x44, ++0xEA, 0x7B, 0x9B, 0x1A, 0x5A, 0x42, 0x53, 0x41, 0x49, 0x22, 0xA3, 0x54, 0x45, 0x23, 0xE1, 0x54, 0x13, 0x33, 0x08, 0x9A, ++0xE2, 0x54, 0x01, 0x22, 0x31, 0x00, 0x01, 0x20, 0xA6, 0xF7, 0xF8, 0xF9, 0x03, 0x9B, 0x00, 0x2B, 0x00, 0xD0, 0x98, 0xE1, ++0x06, 0x99, 0x01, 0x31, 0x2A, 0x89, 0x4A, 0x43, 0xD3, 0xB2, 0x0C, 0x93, 0xEB, 0x88, 0x4B, 0x43, 0xDB, 0xB2, 0x0D, 0x93, ++0x2B, 0x79, 0x00, 0x22, 0x92, 0x46, 0x00, 0x2B, 0x02, 0xD0, 0xEA, 0x78, 0x04, 0x2A, 0x26, 0xD0, 0x68, 0x78, 0x03, 0x28, ++0x33, 0xD8, 0x2B, 0x78, 0x04, 0x2B, 0x30, 0xD8, 0x9B, 0x00, 0x88, 0x4A, 0xD3, 0x18, 0x1A, 0x5C, 0x0F, 0x23, 0x13, 0x40, ++0x0A, 0x93, 0x53, 0x11, 0x01, 0x21, 0x0B, 0x40, 0x03, 0x93, 0x12, 0x11, 0x11, 0x40, 0x0B, 0x91, 0x2C, 0xE0, 0x52, 0x00, ++0x79, 0x49, 0x8A, 0x18, 0x57, 0x78, 0x51, 0xE7, 0x52, 0x00, 0x77, 0x4B, 0x9A, 0x18, 0x53, 0x78, 0x9A, 0x46, 0x09, 0x2F, ++0x00, 0xD9, 0x57, 0xE7, 0x53, 0x46, 0x09, 0x2B, 0x00, 0xD9, 0x53, 0xE7, 0x58, 0xE7, 0x01, 0x2B, 0x0A, 0xD0, 0x02, 0x3B, ++0x5A, 0x42, 0x53, 0x41, 0x5B, 0x42, 0x76, 0x4A, 0x13, 0x40, 0x9A, 0x46, 0x75, 0x4B, 0x9C, 0x46, 0xE2, 0x44, 0xCB, 0xE7, ++0x74, 0x4B, 0x9A, 0x46, 0xC8, 0xE7, 0x29, 0x78, 0x66, 0x4B, 0xDB, 0x6E, 0x98, 0x46, 0x00, 0x23, 0x00, 0x22, 0xC0, 0x47, ++0x03, 0x9B, 0x0B, 0x93, 0x00, 0x23, 0x0A, 0x93, 0x2B, 0x79, 0x0E, 0x2B, 0x00, 0xD1, 0xBC, 0xE0, 0x00, 0xD9, 0xAC, 0xE0, ++0x00, 0x22, 0x06, 0x92, 0x08, 0x2B, 0x04, 0xD0, 0x01, 0x32, 0x06, 0x92, 0x0D, 0x2B, 0x00, 0xD0, 0xA8, 0xE0, 0xEB, 0x78, ++0x5A, 0x1E, 0x03, 0x2A, 0x00, 0xD9, 0xE3, 0xE0, 0xD3, 0xB2, 0x08, 0x93, 0x63, 0x4A, 0x13, 0x68, 0x63, 0x49, 0x19, 0x40, ++0x80, 0x23, 0x9B, 0x02, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x61, 0x49, 0x0B, 0x40, 0x80, 0x21, 0x49, 0x02, 0x8C, 0x46, ++0x0B, 0x43, 0x13, 0x60, 0x73, 0x01, 0x98, 0x46, 0x5D, 0x4A, 0x42, 0x44, 0x85, 0x23, 0x1B, 0x04, 0x51, 0x46, 0x0B, 0x43, ++0x13, 0x60, 0x5B, 0x4B, 0x43, 0x44, 0x9A, 0x46, 0x4B, 0x4A, 0x5B, 0x46, 0x59, 0x00, 0x59, 0x44, 0x53, 0x18, 0x5B, 0x78, ++0x1B, 0x01, 0xA8, 0x7A, 0x03, 0x43, 0xE8, 0x7A, 0x02, 0x38, 0x07, 0x00, 0x78, 0x42, 0x78, 0x41, 0xC0, 0x00, 0x03, 0x43, ++0x07, 0x9F, 0x78, 0x00, 0xBB, 0x46, 0x58, 0x44, 0x17, 0x18, 0x7F, 0x78, 0x7F, 0x01, 0x3B, 0x43, 0x67, 0x46, 0x3B, 0x43, ++0x57, 0x46, 0x3B, 0x60, 0x4C, 0x4B, 0x43, 0x44, 0x9A, 0x46, 0x2B, 0x89, 0x1B, 0x05, 0x9C, 0x46, 0xEB, 0x88, 0x1B, 0x01, ++0x67, 0x46, 0x3B, 0x43, 0x80, 0x5C, 0x03, 0x43, 0x88, 0x5C, 0x00, 0x04, 0x03, 0x43, 0x52, 0x46, 0x13, 0x60, 0x03, 0x9B, ++0xDB, 0x03, 0x0A, 0x9A, 0x12, 0x02, 0x13, 0x43, 0x0B, 0x9A, 0xD2, 0x01, 0x13, 0x43, 0x06, 0x9A, 0x12, 0x05, 0x13, 0x43, ++0x08, 0x9A, 0x12, 0x04, 0x13, 0x43, 0x3E, 0x4A, 0xB2, 0x18, 0x92, 0x00, 0x13, 0x60, 0xB3, 0x00, 0x3C, 0x4A, 0x9C, 0x50, ++0x4B, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x87, 0xE0, 0x32, 0x01, 0xB2, 0x18, 0xD3, 0x01, 0x9B, 0x1A, 0xF3, 0x18, ++0x37, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x9B, 0xB2, 0x36, 0x49, 0x41, 0x44, 0x0C, 0x98, 0xC2, 0x18, 0x12, 0x04, 0x13, 0x43, ++0x0B, 0x60, 0x87, 0x23, 0xDB, 0x00, 0x73, 0x43, 0x84, 0x46, 0x63, 0x44, 0x31, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x5B, 0x00, ++0x9B, 0xB2, 0x30, 0x49, 0x41, 0x44, 0x0D, 0x9A, 0x9A, 0x18, 0x92, 0xB2, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0x2D, 0x4B, ++0x43, 0x44, 0xE9, 0x7B, 0x80, 0x22, 0xD2, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x29, 0x89, 0x00, 0x29, 0x04, 0xD1, 0xEB, 0x88, ++0x01, 0x31, 0x00, 0x2B, 0x00, 0xD0, 0x19, 0x00, 0x00, 0x2E, 0x00, 0xD0, 0xDA, 0xE0, 0xEA, 0x7B, 0x89, 0xB2, 0x00, 0x20, ++0xFF, 0xF7, 0x72, 0xFD, 0xD4, 0xE0, 0x03, 0x22, 0x06, 0x92, 0x10, 0x2B, 0x00, 0xD1, 0x56, 0xE7, 0x05, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0x06, 0x93, 0x4D, 0xE7, 0x02, 0x23, 0x06, 0x93, 0x4A, 0xE7, ++0x28, 0x19, 0x16, 0x00, 0xE4, 0xDF, 0x10, 0x00, 0xD4, 0xDF, 0x10, 0x00, 0xE8, 0xDF, 0x10, 0x00, 0x69, 0xF5, 0x0A, 0x00, ++0x21, 0x61, 0x10, 0x00, 0x4D, 0xF3, 0x0A, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x08, 0xE0, 0x10, 0x00, ++0x00, 0xA0, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0xD0, 0x04, 0x60, 0x40, 0xFF, 0xFF, 0xFD, 0xFF, ++0xFF, 0xFF, 0xFE, 0xFF, 0xD4, 0x05, 0x60, 0x40, 0xE0, 0x05, 0x60, 0x40, 0xE4, 0x05, 0x60, 0x40, 0x8C, 0x01, 0x18, 0x10, ++0x54, 0x27, 0x16, 0x00, 0x5C, 0xAB, 0xFF, 0xFF, 0xD8, 0x05, 0x60, 0x40, 0xAE, 0x55, 0x00, 0x00, 0xDC, 0x05, 0x60, 0x40, ++0xD0, 0x05, 0x60, 0x40, 0x96, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0x08, 0x93, ++0x14, 0xE7, 0x42, 0x33, 0xE3, 0x5C, 0x5F, 0x1E, 0x20, 0x00, 0x50, 0x30, 0x7F, 0xF7, 0xF0, 0xFA, 0x49, 0x23, 0xE1, 0x5C, ++0xCB, 0x1C, 0xDB, 0xB2, 0x04, 0x31, 0xC9, 0xB2, 0x8B, 0x4A, 0x92, 0x46, 0x0D, 0x9A, 0x04, 0x32, 0xD2, 0xB2, 0x00, 0x92, ++0x84, 0x22, 0x50, 0x46, 0x82, 0x58, 0x93, 0x46, 0x0C, 0x9A, 0x30, 0x00, 0xD8, 0x47, 0x86, 0x4A, 0x42, 0x44, 0x00, 0x23, ++0x13, 0x60, 0x85, 0x4A, 0x42, 0x44, 0x13, 0x60, 0x19, 0x33, 0xFF, 0x33, 0x52, 0x46, 0xD0, 0x58, 0x31, 0x00, 0xD2, 0xF7, ++0x47, 0xFB, 0x81, 0x4A, 0x11, 0x68, 0x80, 0x23, 0x9B, 0x01, 0xB3, 0x40, 0x0B, 0x43, 0x13, 0x60, 0x7E, 0x4A, 0x42, 0x44, ++0xFF, 0x23, 0x3B, 0x40, 0x1F, 0x2B, 0x00, 0xD9, 0x1F, 0x23, 0x1B, 0x02, 0xE9, 0x7B, 0x0B, 0x43, 0x09, 0x99, 0x03, 0x39, ++0x48, 0x42, 0x41, 0x41, 0xC9, 0x03, 0x0B, 0x43, 0xC0, 0x21, 0xC9, 0x01, 0x0B, 0x43, 0x13, 0x60, 0x42, 0xE0, 0x75, 0x4B, ++0xF2, 0x18, 0x52, 0x01, 0x74, 0x49, 0x5B, 0x46, 0x58, 0x00, 0x58, 0x44, 0x0B, 0x18, 0x5B, 0x78, 0x1B, 0x01, 0xAF, 0x7A, ++0x1F, 0x43, 0xBC, 0x46, 0xEB, 0x7A, 0x02, 0x3B, 0x1F, 0x00, 0x7B, 0x42, 0x7B, 0x41, 0xDB, 0x00, 0x67, 0x46, 0x3B, 0x43, ++0x9A, 0x46, 0x07, 0x9F, 0x7B, 0x00, 0x98, 0x46, 0xBC, 0x46, 0xE0, 0x44, 0x8C, 0x46, 0xC4, 0x44, 0x63, 0x46, 0x5B, 0x78, ++0x5B, 0x01, 0x1F, 0x00, 0x53, 0x46, 0x1F, 0x43, 0x80, 0x23, 0x5B, 0x02, 0x3B, 0x43, 0x13, 0x60, 0x2B, 0x89, 0x1B, 0x05, ++0xED, 0x88, 0x2D, 0x01, 0x2B, 0x43, 0x45, 0x46, 0x6D, 0x5C, 0x2B, 0x43, 0x41, 0x5C, 0x09, 0x04, 0x0B, 0x43, 0x53, 0x60, ++0x31, 0x01, 0x71, 0x18, 0xCB, 0x01, 0x5B, 0x1A, 0xF3, 0x18, 0x5B, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x98, 0xB2, 0x11, 0x00, ++0x08, 0x39, 0x1B, 0x04, 0x03, 0x43, 0x0B, 0x60, 0x04, 0x3A, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x11, 0x00, ++0x19, 0x40, 0x88, 0x46, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x52, 0x4B, 0x05, 0x9A, 0x53, 0x43, 0x9B, 0xB2, 0x42, 0x22, ++0xA2, 0x5C, 0x52, 0x00, 0x44, 0x21, 0x61, 0x5C, 0x48, 0x1E, 0x81, 0x41, 0x00, 0x91, 0x31, 0x00, 0x0B, 0x20, 0xD3, 0xF7, ++0x41, 0xF8, 0x4B, 0x46, 0xDB, 0x07, 0x33, 0xD4, 0x4B, 0x46, 0x1F, 0x01, 0x3F, 0x09, 0x41, 0x23, 0xE5, 0x5C, 0x02, 0x33, ++0xE3, 0x5C, 0x9B, 0x06, 0x7F, 0x08, 0x5F, 0x40, 0x42, 0x23, 0xE3, 0x5C, 0x99, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x39, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x49, 0x46, 0x38, 0x00, 0xD3, 0xF7, 0x63, 0xF9, 0x69, 0x1A, ++0x00, 0x29, 0x21, 0xDD, 0x42, 0x23, 0xE3, 0x5C, 0xC9, 0x1A, 0x49, 0x00, 0x58, 0x00, 0x04, 0x9A, 0x94, 0x46, 0x60, 0x44, ++0x09, 0x18, 0x09, 0x01, 0x09, 0x09, 0x61, 0x63, 0x02, 0x2B, 0x02, 0xD9, 0x30, 0x00, 0x34, 0x4B, 0x98, 0x47, 0x00, 0x20, ++0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x28, 0xE5, 0x62, 0xB6, 0x26, 0xE5, 0x30, 0x4F, 0x4B, 0x46, 0x3B, 0x40, 0x1F, 0x00, ++0x04, 0x98, 0x01, 0x38, 0x00, 0x01, 0x03, 0x09, 0x04, 0x93, 0xC4, 0xE7, 0x42, 0x23, 0xE3, 0x5C, 0xC9, 0x18, 0xD9, 0xE7, ++0x00, 0x21, 0x5C, 0x20, 0x7C, 0xF7, 0xD8, 0xFE, 0x04, 0x1E, 0x00, 0xD1, 0x18, 0xE5, 0x43, 0x46, 0x9B, 0x00, 0x26, 0x4A, ++0x9F, 0x58, 0x6B, 0x78, 0x09, 0x93, 0x03, 0x2B, 0x00, 0xD1, 0x19, 0xE5, 0xAB, 0x78, 0x01, 0x2B, 0x00, 0xD1, 0x18, 0xE5, ++0x2A, 0x79, 0x08, 0x23, 0x93, 0x42, 0x9B, 0x41, 0x5B, 0x42, 0x06, 0x93, 0x06, 0x9B, 0x08, 0x93, 0xA6, 0xF7, 0x1C, 0xFA, ++0x04, 0x90, 0xBB, 0x6F, 0x81, 0x46, 0x99, 0x44, 0x5C, 0x22, 0x00, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0x67, 0xFE, 0xEB, 0x7A, ++0x00, 0x2B, 0x00, 0xD0, 0x0B, 0xE5, 0x2B, 0x7B, 0x00, 0x2B, 0x00, 0xD1, 0x00, 0xE5, 0x02, 0x22, 0x92, 0x46, 0x02, 0x27, ++0x02, 0x2B, 0x00, 0xD0, 0x22, 0xE5, 0x01, 0x3B, 0xF9, 0xE4, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0x0C, 0x20, 0xD5, 0xE4, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0xD8, 0x05, 0x60, 0x40, 0xDC, 0x05, 0x60, 0x40, ++0x0C, 0x04, 0x60, 0x40, 0xD0, 0x05, 0x60, 0x40, 0x2F, 0x00, 0x03, 0x02, 0xE8, 0xDF, 0x10, 0x00, 0x5C, 0xAB, 0xFF, 0xFF, ++0xE2, 0x04, 0x00, 0x00, 0x3D, 0xF4, 0x0A, 0x00, 0xFE, 0xFF, 0xFF, 0x0F, 0x38, 0x27, 0x16, 0x00, 0x00, 0x20, 0x70, 0x47, ++0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x5A, 0x4B, ++0x1B, 0x68, 0xDB, 0x05, 0x0B, 0xD5, 0x58, 0x49, 0x0B, 0x68, 0x5B, 0x00, 0x5B, 0x08, 0x80, 0x22, 0x12, 0x06, 0x13, 0x43, ++0x0B, 0x60, 0x0A, 0x00, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xDB, 0x53, 0x4B, 0x1B, 0x68, 0xDB, 0x05, 0x0B, 0xD5, 0x51, 0x49, ++0x0B, 0x68, 0x5B, 0x00, 0x5B, 0x08, 0x80, 0x22, 0x12, 0x06, 0x13, 0x43, 0x0B, 0x60, 0x0A, 0x00, 0x13, 0x68, 0x00, 0x2B, ++0xFC, 0xDB, 0x7A, 0xF7, 0x4F, 0xFF, 0x4B, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x09, 0xD0, 0x7C, 0xF7, 0xF5, 0xFE, 0x48, 0x4B, ++0x00, 0x22, 0x1A, 0x60, 0x47, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x46, 0x4B, 0x11, 0x22, 0x44, 0x21, ++0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x10, 0x3A, ++0x40, 0x49, 0x5A, 0x54, 0x40, 0x49, 0x5A, 0x54, 0x40, 0x4A, 0x00, 0x21, 0x99, 0x54, 0x40, 0x4B, 0x1B, 0x68, 0x01, 0x2B, ++0x47, 0xD9, 0x39, 0x4B, 0x1A, 0x68, 0x08, 0x21, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x01, 0x20, 0x82, 0x43, 0x1A, 0x60, ++0x1A, 0x68, 0x06, 0x39, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x38, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x12, 0x04, ++0x12, 0x0C, 0xB0, 0x21, 0x49, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x34, 0x4A, 0xA0, 0x23, 0x9B, 0x00, 0xD0, 0x54, 0x29, 0x4A, ++0x13, 0x68, 0x0F, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x30, 0x4A, 0x13, 0x68, 0x30, 0x49, 0x19, 0x40, 0xA0, 0x23, 0xDB, 0x03, ++0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0xFF, 0x21, 0x8B, 0x43, 0xAF, 0x39, 0x0B, 0x43, 0x13, 0x60, 0x2B, 0x4B, 0x2C, 0x4A, ++0x9A, 0x60, 0x2C, 0x4A, 0xDA, 0x60, 0x2C, 0x4A, 0x5A, 0x61, 0x2C, 0x4A, 0x9A, 0x61, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, ++0x00, 0x23, 0x2A, 0x4A, 0x13, 0x60, 0x2A, 0x4A, 0x13, 0x60, 0x2A, 0x4A, 0x13, 0x60, 0x0A, 0x22, 0x29, 0x49, 0x2A, 0x48, ++0xD3, 0xF7, 0x10, 0xFC, 0x10, 0xBD, 0x15, 0x4B, 0x1A, 0x68, 0x08, 0x31, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x07, 0x39, ++0x8A, 0x43, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x02, 0x20, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x13, 0x48, 0x10, 0x40, ++0x80, 0x22, 0x92, 0x01, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x12, 0x04, 0x12, 0x0C, 0xB0, 0x20, 0x40, 0x03, 0x02, 0x43, ++0x1A, 0x60, 0x0E, 0x4A, 0xA0, 0x23, 0x9B, 0x00, 0xD1, 0x54, 0x19, 0x4B, 0x19, 0x4A, 0x1A, 0x60, 0xAF, 0xE7, 0xC0, 0x46, ++0x00, 0x04, 0x60, 0x40, 0x00, 0x08, 0x60, 0x40, 0xF8, 0xE6, 0x10, 0x00, 0xFC, 0x00, 0x60, 0x40, 0xEC, 0xA4, 0x16, 0x00, ++0x1E, 0x03, 0x00, 0x00, 0x6F, 0x04, 0x00, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xFF, 0xDF, 0xFF, 0xFF, ++0x7C, 0x1E, 0x16, 0x00, 0x8C, 0x04, 0x60, 0x40, 0xFF, 0xFF, 0x00, 0xFF, 0x60, 0x92, 0x16, 0x00, 0x2D, 0x01, 0x10, 0x00, ++0x81, 0x01, 0x10, 0x00, 0x8D, 0x05, 0x10, 0x00, 0xB9, 0x00, 0x10, 0x00, 0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, ++0x54, 0xE6, 0x10, 0x00, 0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x30, 0x10, 0x62, 0x40, 0x15, 0x1C, 0x20, 0x00, ++0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x70, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x0B, 0xD5, ++0x6F, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x6C, 0x4A, 0x13, 0x68, 0x08, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x6B, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x6A, 0x4C, 0x23, 0x68, 0x6A, 0x4E, 0x33, 0x40, 0x23, 0x60, 0x6A, 0x4D, 0x2B, 0x68, 0x6A, 0x4F, ++0x3B, 0x40, 0x2B, 0x60, 0x83, 0xF7, 0xEE, 0xFA, 0x23, 0x68, 0x68, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x2B, 0x68, 0x33, 0x40, ++0x2B, 0x60, 0x23, 0x68, 0x1F, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x3B, 0x43, 0x23, 0x60, 0x23, 0x68, 0x1E, 0x40, 0x80, 0x23, ++0x9B, 0x00, 0x33, 0x43, 0x23, 0x60, 0x60, 0x4B, 0x99, 0x46, 0xFF, 0x23, 0x9B, 0x46, 0x22, 0x00, 0xC0, 0x3B, 0x98, 0x46, ++0x5D, 0x4B, 0x9C, 0x46, 0x40, 0x25, 0x80, 0x21, 0x09, 0x01, 0x5F, 0x46, 0x5E, 0x46, 0x04, 0x36, 0xF3, 0xB2, 0x9B, 0x46, ++0x4C, 0x46, 0x18, 0x00, 0x13, 0x68, 0x46, 0x46, 0xB3, 0x43, 0x03, 0x43, 0x13, 0x60, 0x63, 0x46, 0x26, 0x68, 0x1E, 0x60, ++0x13, 0x68, 0xAB, 0x43, 0x2B, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, ++0xFC, 0xD0, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0x34, 0xB8, 0x42, 0xE7, 0xD1, 0x10, 0x23, 0x9A, 0x46, 0xD1, 0x44, 0x5B, 0x46, ++0x0F, 0x2B, 0xDA, 0xD1, 0x42, 0x4C, 0x23, 0x68, 0x44, 0x4D, 0x2B, 0x40, 0x23, 0x60, 0x83, 0xF7, 0xAA, 0xFA, 0x23, 0x68, ++0x3F, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x3F, 0x4B, 0x1A, 0x68, 0x80, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x15, 0x40, ++0x80, 0x22, 0x52, 0x00, 0x2A, 0x43, 0x1A, 0x60, 0x3E, 0x4B, 0x9A, 0x46, 0xFF, 0x24, 0x38, 0x4A, 0x1F, 0x23, 0x99, 0x46, ++0x3C, 0x4B, 0x98, 0x46, 0x20, 0x26, 0x80, 0x21, 0xC9, 0x00, 0x04, 0xE0, 0x08, 0x23, 0x9C, 0x46, 0xE2, 0x44, 0x1F, 0x2C, ++0x1D, 0xD0, 0xA4, 0x46, 0x02, 0x34, 0xE4, 0xB2, 0x55, 0x46, 0x20, 0x00, 0x13, 0x68, 0x4F, 0x46, 0xBB, 0x43, 0x03, 0x43, ++0x13, 0x60, 0x43, 0x46, 0x2F, 0x68, 0x1F, 0x60, 0x13, 0x68, 0xB3, 0x43, 0x33, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, ++0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0x35, 0x60, 0x45, 0xE7, 0xD1, ++0xDC, 0xE7, 0x22, 0x4C, 0x23, 0x68, 0x80, 0x22, 0x93, 0x43, 0x23, 0x60, 0x83, 0xF7, 0x65, 0xFA, 0x23, 0x68, 0x1F, 0x4D, ++0x2B, 0x40, 0x23, 0x60, 0x23, 0x49, 0x0B, 0x68, 0x23, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x02, 0x13, 0x43, 0x0B, 0x60, ++0x83, 0xF7, 0x50, 0xFA, 0x15, 0x49, 0x0B, 0x68, 0x18, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x0B, 0x60, ++0x0B, 0x68, 0x12, 0x48, 0x03, 0x40, 0x80, 0x22, 0x92, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x23, 0x68, 0x03, 0x40, 0x1A, 0x43, ++0x22, 0x60, 0x23, 0x68, 0x1D, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x2B, 0x43, 0x23, 0x60, 0x14, 0x49, 0x0B, 0x68, 0x14, 0x4A, ++0x1A, 0x40, 0x80, 0x23, 0x5B, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, ++0xF8, 0xBD, 0xC0, 0x46, 0x18, 0x00, 0x58, 0x40, 0x40, 0x42, 0x04, 0x40, 0x58, 0x20, 0x62, 0x40, 0xFF, 0xFD, 0xFF, 0xFF, ++0x64, 0x20, 0x62, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xD8, 0x97, 0x16, 0x00, 0x5C, 0x20, 0x62, 0x40, ++0xD8, 0x98, 0x16, 0x00, 0x68, 0x20, 0x62, 0x40, 0x4C, 0x20, 0x62, 0x40, 0xFF, 0xFF, 0xFE, 0xFF, 0x30, 0x20, 0x62, 0x40, ++0xFF, 0xFF, 0xEF, 0xFF, 0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x6E, 0x4C, 0x23, 0x68, ++0x6E, 0x4E, 0x33, 0x40, 0x23, 0x60, 0x6E, 0x4D, 0x2B, 0x68, 0x6E, 0x4A, 0x13, 0x40, 0x2B, 0x60, 0x83, 0xF7, 0xF8, 0xF9, ++0x23, 0x68, 0x6C, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x2B, 0x68, 0x6B, 0x4A, 0x13, 0x40, 0x2B, 0x60, 0x23, 0x68, 0x6A, 0x4A, ++0x1A, 0x40, 0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x23, 0x60, 0x23, 0x68, 0x1E, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x33, 0x43, ++0x23, 0x60, 0x65, 0x4B, 0x9A, 0x46, 0x7F, 0x25, 0x22, 0x00, 0xFF, 0x23, 0x99, 0x46, 0x63, 0x4B, 0x98, 0x46, 0x5D, 0x4B, ++0x9C, 0x46, 0x80, 0x21, 0x89, 0x01, 0x2E, 0x00, 0x04, 0x35, 0xED, 0xB2, 0x54, 0x46, 0x28, 0x00, 0x13, 0x68, 0x4F, 0x46, ++0xBB, 0x43, 0x03, 0x43, 0x13, 0x60, 0x43, 0x46, 0x27, 0x68, 0x1F, 0x60, 0x13, 0x68, 0x67, 0x46, 0x3B, 0x40, 0x80, 0x27, ++0x7F, 0x00, 0x3B, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, ++0x01, 0x38, 0xC0, 0xB2, 0x04, 0x34, 0x86, 0x42, 0xE4, 0xD1, 0x10, 0x23, 0x9B, 0x46, 0xDA, 0x44, 0x8F, 0x2D, 0xDA, 0xD1, ++0x45, 0x4C, 0x23, 0x68, 0x4A, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x83, 0xF7, 0xB2, 0xF9, 0x23, 0x68, 0x42, 0x4A, 0x13, 0x40, ++0x23, 0x60, 0x42, 0x4B, 0x1A, 0x68, 0x80, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x40, 0x49, 0x11, 0x40, 0x80, 0x22, ++0x52, 0x00, 0x0A, 0x43, 0x1A, 0x60, 0x10, 0x20, 0x1A, 0x00, 0x1F, 0x27, 0x41, 0x4E, 0x42, 0x4D, 0x20, 0x24, 0x80, 0x21, ++0xC9, 0x00, 0x13, 0x68, 0xBB, 0x43, 0x03, 0x43, 0x13, 0x60, 0x83, 0x00, 0xF3, 0x58, 0x2B, 0x60, 0x13, 0x68, 0xA3, 0x43, ++0x23, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, 0x01, 0x30, ++0x20, 0x28, 0xEA, 0xD1, 0x2D, 0x4C, 0x23, 0x68, 0x80, 0x22, 0x93, 0x43, 0x23, 0x60, 0x83, 0xF7, 0x7E, 0xF9, 0x23, 0x68, ++0x2A, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x31, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x30, 0x4A, 0x13, 0x68, 0x02, 0x21, ++0x8B, 0x43, 0x13, 0x60, 0x2C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2D, 0x4A, 0x13, 0x68, 0x2D, 0x49, 0x0B, 0x40, 0x13, 0x60, ++0x2C, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x83, 0xF7, 0x5D, 0xF9, 0x1B, 0x49, 0x0B, 0x68, 0x1E, 0x4A, 0x13, 0x40, 0x80, 0x22, ++0x52, 0x01, 0x13, 0x43, 0x0B, 0x60, 0x0B, 0x68, 0x17, 0x48, 0x18, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x03, 0x43, 0x0B, 0x60, ++0x15, 0x4B, 0x19, 0x68, 0x17, 0x48, 0x08, 0x40, 0x80, 0x21, 0x89, 0x00, 0x01, 0x43, 0x19, 0x60, 0x19, 0x68, 0x12, 0x48, ++0x08, 0x40, 0x80, 0x21, 0x49, 0x00, 0x01, 0x43, 0x19, 0x60, 0x1C, 0x4B, 0x19, 0x68, 0x0A, 0x43, 0x1A, 0x60, 0x1B, 0x4A, ++0x13, 0x68, 0x1B, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x1A, 0x4B, 0x1A, 0x68, 0x1A, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x19, 0x68, ++0x80, 0x22, 0xD2, 0x05, 0x0A, 0x43, 0x1A, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, ++0x60, 0x40, 0x34, 0x40, 0xFF, 0xF7, 0xFF, 0xFF, 0x6C, 0x40, 0x34, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, ++0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xD8, 0x9B, 0x16, 0x00, 0x64, 0x40, 0x34, 0x40, 0x58, 0x99, 0x16, 0x00, ++0x70, 0x40, 0x34, 0x40, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xFF, 0xFB, ++0x08, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, 0xFF, 0xFF, 0xFB, 0xFF, 0x1C, 0x20, 0x34, 0x40, ++0xFF, 0xFF, 0xFF, 0xDF, 0x10, 0xB5, 0x07, 0x49, 0x0A, 0x69, 0x0F, 0x24, 0xA2, 0x43, 0x03, 0x20, 0x02, 0x43, 0x0A, 0x61, ++0xCB, 0x69, 0xA3, 0x43, 0x03, 0x43, 0xCB, 0x61, 0x02, 0x48, 0x7E, 0xF7, 0xA1, 0xFB, 0x10, 0xBD, 0x00, 0x30, 0x50, 0x40, ++0x94, 0xD1, 0x10, 0x00, 0x70, 0xB5, 0x1B, 0x4B, 0x9B, 0x69, 0xDB, 0x05, 0x1F, 0xD4, 0x0C, 0x38, 0xEF, 0xF3, 0x10, 0x83, ++0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x15, 0x4B, 0x1B, 0x7F, 0x01, 0x2B, 0x1C, 0xD0, ++0xCF, 0xF7, 0x62, 0xF8, 0x12, 0x4B, 0x1B, 0x7F, 0xFF, 0x2B, 0x1A, 0xD0, 0x02, 0x20, 0x7B, 0xF7, 0xCB, 0xF9, 0xFF, 0xF7, ++0xCF, 0xFF, 0x0F, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, 0x70, 0xBD, 0x0C, 0x4D, ++0xC4, 0x24, 0x64, 0x00, 0x00, 0x23, 0x2B, 0x51, 0xCE, 0xF7, 0xCC, 0xF8, 0x09, 0x4B, 0x2B, 0x51, 0xF4, 0xE7, 0x05, 0x4B, ++0xFF, 0x22, 0x1A, 0x77, 0xDE, 0xE7, 0x03, 0x4B, 0x01, 0x22, 0x1A, 0x77, 0xE0, 0xE7, 0xC0, 0x46, 0x3C, 0x95, 0x16, 0x00, ++0x24, 0x2A, 0x16, 0x00, 0x00, 0x41, 0x04, 0x40, 0x28, 0x19, 0x16, 0x00, 0xB9, 0x5A, 0x10, 0x00, 0x01, 0x28, 0x02, 0xD0, ++0x02, 0x28, 0x05, 0xD0, 0x70, 0x47, 0x05, 0x4B, 0x80, 0x22, 0x92, 0x04, 0x1A, 0x60, 0xF9, 0xE7, 0x02, 0x4B, 0x80, 0x22, ++0x52, 0x04, 0x1A, 0x60, 0xF4, 0xE7, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, 0x15, 0x4B, 0x16, 0x4A, 0x13, 0x60, 0x16, 0x4A, ++0x13, 0x60, 0x16, 0x4B, 0x1A, 0x68, 0x30, 0x21, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x90, 0x31, 0x8A, 0x43, 0x1A, 0x60, ++0x1A, 0x68, 0x12, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x11, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x10, 0x49, ++0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x0F, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x0E, 0x4A, 0xC4, 0x20, 0x80, 0x00, 0x13, 0x58, ++0x1B, 0x02, 0x1B, 0x0A, 0xC0, 0x21, 0x09, 0x06, 0x0B, 0x43, 0x13, 0x50, 0x80, 0x23, 0x1B, 0x03, 0x13, 0x60, 0x70, 0x47, ++0x00, 0x00, 0x7C, 0x07, 0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x18, 0x41, 0x04, 0x40, 0xFF, 0xFC, 0xFF, 0xFF, ++0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0x00, 0xE1, 0x00, 0xE0, 0x70, 0xB5, 0x82, 0xB0, ++0x04, 0x00, 0x64, 0x4B, 0x18, 0x68, 0x04, 0x28, 0x04, 0xD8, 0x49, 0xD8, 0x80, 0x00, 0x62, 0x4B, 0x1B, 0x58, 0x9F, 0x46, ++0xFF, 0x28, 0x43, 0xD1, 0x60, 0x4B, 0x80, 0x22, 0xD2, 0x00, 0x1A, 0x60, 0x5F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x5F, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x40, 0xD1, 0x5E, 0x4B, 0x19, 0x68, 0x41, 0x29, 0x57, 0xD0, 0x43, 0xD8, 0x01, 0x29, 0x49, 0xD0, ++0x21, 0x29, 0x00, 0xD0, 0x81, 0xE0, 0x5A, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x52, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x58, 0x4B, ++0x1B, 0x68, 0x01, 0x2B, 0x54, 0xD1, 0x50, 0xE0, 0x54, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x4F, 0x4B, 0x80, 0x22, 0xD2, 0x00, ++0x1A, 0x60, 0x4E, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x50, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x00, 0xD1, 0x7D, 0xE0, 0x47, 0x4B, ++0x1B, 0x68, 0x02, 0x2B, 0x40, 0xD1, 0x00, 0x25, 0x4C, 0x4B, 0x1D, 0x70, 0x01, 0x20, 0xFB, 0xF7, 0xCB, 0xFD, 0x4B, 0x4B, ++0x1D, 0x70, 0x3D, 0xE0, 0x46, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0xE2, 0xE7, 0x44, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xDE, 0xE7, ++0x42, 0x4B, 0x19, 0x78, 0x45, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA8, 0x47, 0xD6, 0xE7, 0x0F, 0x20, 0xFA, 0xF7, ++0x6F, 0xFD, 0xFF, 0x23, 0x03, 0x40, 0x3B, 0x4A, 0x13, 0x60, 0xB6, 0xE7, 0x61, 0x29, 0x10, 0xD0, 0xFF, 0x29, 0x3E, 0xD1, ++0x3D, 0x48, 0x7E, 0xF7, 0xA1, 0xFA, 0xCD, 0xE7, 0x36, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0x2F, 0x4B, 0x01, 0x3A, 0x1A, 0x60, ++0x34, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x0D, 0xD1, 0x4C, 0xE0, 0x31, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x29, 0x4B, 0x01, 0x32, ++0x1A, 0x60, 0x2F, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0xC1, 0xD1, 0x26, 0x4B, 0x03, 0x22, 0x1A, 0x60, 0x2D, 0x4B, 0x01, 0x22, ++0x1A, 0x70, 0x00, 0x20, 0xFB, 0xF7, 0x8A, 0xFD, 0x2D, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0xFF, 0xF7, 0x35, 0xFF, 0x2C, 0x4B, ++0x1B, 0x68, 0x24, 0x4A, 0x12, 0x78, 0x1D, 0x49, 0x09, 0x68, 0x2A, 0x48, 0x00, 0x68, 0x01, 0x90, 0x1E, 0x48, 0x00, 0x68, ++0x00, 0x90, 0x28, 0x48, 0x7E, 0xF7, 0x6E, 0xFA, 0x00, 0x2C, 0x27, 0xD0, 0x26, 0x4A, 0x13, 0x68, 0x20, 0x21, 0x0B, 0x43, ++0x13, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x24, 0x48, 0x7E, 0xF7, 0x62, 0xFA, 0x17, 0x4E, 0x31, 0x78, 0x10, 0x4D, 0x00, 0x23, ++0x00, 0x22, 0x28, 0x68, 0x81, 0xF7, 0xFE, 0xFF, 0x02, 0x23, 0x33, 0x70, 0x01, 0x3B, 0x2B, 0x60, 0x12, 0x4B, 0x1B, 0x68, ++0x01, 0x2B, 0xC9, 0xD1, 0x0F, 0x4B, 0x1B, 0x78, 0x03, 0xE0, 0x0E, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0xBF, 0xD0, 0x02, 0x2B, ++0x00, 0xD0, 0x7A, 0xE7, 0x04, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0xBB, 0xE7, 0x12, 0x4A, 0x13, 0x68, 0x20, 0x21, 0x8B, 0x43, ++0x13, 0x60, 0xD6, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0xE0, 0xD1, 0x10, 0x00, 0xE4, 0xE1, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, ++0xA4, 0xE5, 0x10, 0x00, 0xC0, 0xE5, 0x10, 0x00, 0xB4, 0xE5, 0x10, 0x00, 0x54, 0xE0, 0x10, 0x00, 0x60, 0xE6, 0x10, 0x00, ++0xDC, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x9C, 0xD1, 0x10, 0x00, 0xD1, 0xE6, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, ++0xBC, 0xE5, 0x10, 0x00, 0xC8, 0xD1, 0x10, 0x00, 0x84, 0x40, 0x04, 0x40, 0xB0, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x38, 0x4B, 0x38, 0x4A, 0x1A, 0x60, 0x38, 0x4B, 0x39, 0x4A, 0x1A, 0x60, 0x40, 0x23, 0x38, 0x4A, 0x13, 0x60, ++0x28, 0x22, 0x38, 0x49, 0x0A, 0x80, 0xC8, 0x21, 0x49, 0x00, 0x37, 0x48, 0x01, 0x80, 0x37, 0x48, 0x01, 0x80, 0x03, 0x20, ++0x36, 0x49, 0x08, 0x80, 0x02, 0x21, 0x36, 0x4C, 0x21, 0x80, 0x36, 0x4C, 0x20, 0x80, 0x36, 0x48, 0x01, 0x80, 0x36, 0x49, ++0x0A, 0x80, 0x80, 0x25, 0xAD, 0x00, 0x35, 0x49, 0x0D, 0x80, 0x14, 0x21, 0x34, 0x48, 0x01, 0x80, 0x34, 0x48, 0x15, 0x24, ++0x04, 0x80, 0x34, 0x48, 0x01, 0x80, 0x20, 0x26, 0x33, 0x49, 0x0E, 0x60, 0x0D, 0x3C, 0x33, 0x49, 0x0C, 0x60, 0x33, 0x49, ++0x01, 0x20, 0x40, 0x42, 0x08, 0x60, 0x00, 0x20, 0x31, 0x49, 0x08, 0x60, 0x31, 0x49, 0x88, 0x46, 0x31, 0x4F, 0x39, 0x60, ++0x31, 0x4F, 0x14, 0x21, 0xFF, 0x31, 0x39, 0x60, 0x30, 0x4F, 0x31, 0x49, 0x39, 0x60, 0x31, 0x4F, 0x07, 0x21, 0x39, 0x80, ++0x30, 0x4F, 0x3B, 0x80, 0x30, 0x4F, 0x41, 0x31, 0x39, 0x80, 0x30, 0x4F, 0x01, 0x39, 0x39, 0x80, 0x2F, 0x4F, 0x3E, 0x80, ++0x2F, 0x4E, 0x35, 0x80, 0x2F, 0x4D, 0xD2, 0x26, 0x76, 0x00, 0x2E, 0x80, 0x64, 0x25, 0x2E, 0x4E, 0x35, 0x80, 0x2E, 0x4E, ++0x35, 0x80, 0x2E, 0x4D, 0x2C, 0x80, 0x2E, 0x4C, 0x18, 0x25, 0x25, 0x80, 0x2D, 0x4C, 0x22, 0x80, 0x2D, 0x4A, 0x8C, 0x24, ++0x14, 0x80, 0x2D, 0x4A, 0x10, 0x80, 0x2D, 0x4A, 0x13, 0x60, 0x2D, 0x4B, 0x42, 0x46, 0x1A, 0x60, 0x2C, 0x4B, 0x32, 0x22, ++0x1A, 0x80, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xA0, 0x06, 0x16, 0x00, 0x00, 0xD7, 0x18, 0x00, 0x9C, 0x06, 0x16, 0x00, ++0x00, 0xF7, 0x18, 0x00, 0x78, 0x06, 0x16, 0x00, 0x5C, 0x06, 0x16, 0x00, 0x8E, 0x06, 0x16, 0x00, 0x8C, 0x06, 0x16, 0x00, ++0x5A, 0x06, 0x16, 0x00, 0x4A, 0x06, 0x16, 0x00, 0x56, 0x06, 0x16, 0x00, 0x54, 0x06, 0x16, 0x00, 0x5E, 0x06, 0x16, 0x00, ++0x58, 0x06, 0x16, 0x00, 0x64, 0x06, 0x16, 0x00, 0x66, 0x06, 0x16, 0x00, 0x62, 0x06, 0x16, 0x00, 0x68, 0x06, 0x16, 0x00, ++0x6C, 0x06, 0x16, 0x00, 0x44, 0x1E, 0x16, 0x00, 0x40, 0x1E, 0x16, 0x00, 0x20, 0x4E, 0x00, 0x00, 0x7C, 0x06, 0x16, 0x00, ++0x38, 0x1E, 0x16, 0x00, 0x3C, 0x1E, 0x16, 0x00, 0x02, 0x73, 0x06, 0x20, 0x4C, 0x06, 0x16, 0x00, 0x4E, 0x06, 0x16, 0x00, ++0x50, 0x06, 0x16, 0x00, 0x52, 0x06, 0x16, 0x00, 0x90, 0x06, 0x16, 0x00, 0x94, 0x06, 0x16, 0x00, 0x92, 0x06, 0x16, 0x00, ++0x8A, 0x06, 0x16, 0x00, 0x88, 0x06, 0x16, 0x00, 0x82, 0x06, 0x16, 0x00, 0x80, 0x06, 0x16, 0x00, 0x86, 0x06, 0x16, 0x00, ++0x84, 0x06, 0x16, 0x00, 0x48, 0x1E, 0x16, 0x00, 0x70, 0x06, 0x16, 0x00, 0x74, 0x06, 0x16, 0x00, 0x60, 0x06, 0x16, 0x00, ++0x0F, 0x4B, 0x02, 0x22, 0x9A, 0x77, 0x0F, 0x4A, 0x11, 0x6D, 0x80, 0x23, 0xDB, 0x01, 0x0B, 0x43, 0x13, 0x65, 0x0D, 0x4B, ++0x1B, 0x78, 0x02, 0x2B, 0x0B, 0xD0, 0x0A, 0x4B, 0x19, 0x6D, 0x80, 0x22, 0x12, 0x02, 0x0A, 0x43, 0x1A, 0x65, 0x19, 0x6D, ++0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, 0x1A, 0x65, 0x70, 0x47, 0x11, 0x6D, 0x80, 0x23, 0xDB, 0x02, 0x0B, 0x43, 0x13, 0x65, ++0xED, 0xE7, 0xC0, 0x46, 0x3C, 0x95, 0x16, 0x00, 0x00, 0x60, 0x50, 0x40, 0xB4, 0xE5, 0x10, 0x00, 0x01, 0x4B, 0x01, 0x22, ++0xDA, 0x77, 0x70, 0x47, 0x3C, 0x95, 0x16, 0x00, 0x10, 0xB5, 0x01, 0x20, 0x7F, 0xF7, 0x48, 0xF9, 0x10, 0xBD, 0x10, 0xB5, ++0x80, 0x20, 0x40, 0x00, 0x7B, 0xF7, 0x3A, 0xFC, 0x10, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x20, 0x4B, 0x1B, 0x68, ++0x01, 0x2B, 0x03, 0xD0, 0x1F, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x22, 0xD1, 0x00, 0x2C, 0x2C, 0xD0, 0x1D, 0x4A, 0x13, 0x68, ++0x08, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x00, 0x23, 0x1B, 0x4A, 0x13, 0x60, 0x1B, 0x4A, 0x13, 0x60, 0x1B, 0x4A, 0x13, 0x60, ++0x1B, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x22, 0xD9, 0x1A, 0x4A, 0x0F, 0x21, 0x11, 0x70, 0x03, 0x3B, 0x01, 0x2B, 0x05, 0xD8, ++0x18, 0x4A, 0x80, 0x23, 0x1B, 0x02, 0x91, 0x69, 0x0B, 0x43, 0x93, 0x61, 0x16, 0x49, 0x17, 0x48, 0x7E, 0xF7, 0xEC, 0xF8, ++0x10, 0xBD, 0xFF, 0xF7, 0xCF, 0xFE, 0xFF, 0xF7, 0x97, 0xFF, 0x11, 0x4B, 0x01, 0x22, 0xDA, 0x77, 0xFF, 0xF7, 0xBE, 0xFF, ++0xFF, 0xF7, 0xC1, 0xFF, 0xD0, 0xE7, 0x07, 0x4A, 0x13, 0x68, 0x08, 0x21, 0x8B, 0x43, 0x13, 0x60, 0xD1, 0xE7, 0x09, 0x4B, ++0x0B, 0x22, 0x1A, 0x70, 0xE4, 0xE7, 0xC0, 0x46, 0xA8, 0xE5, 0x10, 0x00, 0xAC, 0xE5, 0x10, 0x00, 0x84, 0x40, 0x04, 0x40, ++0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x54, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xE2, 0xE1, 0x10, 0x00, ++0x3C, 0x95, 0x16, 0x00, 0xF8, 0xE8, 0x10, 0x00, 0xF4, 0xD1, 0x10, 0x00, 0x02, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, ++0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0x12, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, ++0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0xD2, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, ++0x04, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, 0x03, 0x4B, 0x80, 0x22, 0x52, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, ++0xD0, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x13, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x07, 0xD0, ++0x11, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x16, 0xD9, 0x20, 0x00, 0x10, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0xAD, 0x33, 0xC3, 0x5C, ++0x00, 0x2B, 0xF7, 0xD0, 0x0D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, 0xFD, 0xF7, 0x54, 0xF8, ++0xEA, 0xE7, 0xFF, 0xF7, 0xD5, 0xFF, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xAE, 0xF7, 0x09, 0xFD, 0x00, 0x28, ++0xE4, 0xD1, 0xA7, 0x23, 0x04, 0x22, 0xE2, 0x54, 0xE0, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0xD5, 0x0D, 0x0B, 0x00, ++0xD8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x0B, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x03, 0xD0, 0x20, 0x00, 0xFE, 0xF7, ++0x11, 0xF9, 0x10, 0xBD, 0x08, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, 0xFD, 0xF7, 0x2C, 0xF8, ++0xF2, 0xE7, 0xFF, 0xF7, 0xAD, 0xFF, 0x03, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, ++0xD8, 0xE6, 0x10, 0x00, 0x04, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, 0x03, 0x4B, 0x80, 0x22, 0x92, 0x05, 0x1A, 0x60, ++0x70, 0x47, 0xC0, 0x46, 0xD2, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x80, 0x46, 0x00, 0x91, 0x82, 0x00, 0x93, 0x4B, 0xD5, 0x58, 0x9E, 0x23, 0xEC, 0x5C, ++0x64, 0x00, 0x0F, 0x33, 0xEB, 0x5C, 0xE4, 0x18, 0xE4, 0xB2, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0xAF, 0xE0, ++0xA8, 0x23, 0xEB, 0x5C, 0x77, 0x2B, 0x02, 0xD8, 0x01, 0x33, 0xA8, 0x22, 0xAB, 0x54, 0x43, 0x46, 0x1B, 0x02, 0x01, 0x27, ++0x3B, 0x43, 0x9B, 0x46, 0x87, 0x4B, 0x99, 0x46, 0x47, 0xE0, 0xC5, 0x20, 0x02, 0x23, 0xFF, 0x22, 0x59, 0x46, 0xC0, 0x00, ++0x7B, 0xF7, 0x0A, 0xFF, 0x06, 0x00, 0x3B, 0x88, 0x03, 0x80, 0x7B, 0xF7, 0x2F, 0xFF, 0x30, 0x88, 0x43, 0x1C, 0x9B, 0xB2, ++0x7F, 0x49, 0x5A, 0x5C, 0x41, 0x5C, 0x49, 0x10, 0x7E, 0x48, 0x7D, 0xF7, 0xFF, 0xFF, 0x00, 0x23, 0x3B, 0x80, 0x7D, 0x4B, ++0xE2, 0x18, 0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, 0x13, 0x80, 0x7B, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x7A, 0x4A, ++0x13, 0x40, 0x23, 0x80, 0xAF, 0x22, 0xAB, 0x5C, 0x01, 0x3B, 0xDB, 0xB2, 0xAB, 0x54, 0x35, 0x31, 0x6A, 0x5C, 0x50, 0x42, ++0x42, 0x41, 0x6A, 0x54, 0x5A, 0x1E, 0x93, 0x41, 0xA8, 0x22, 0xAB, 0x54, 0x8C, 0x23, 0xEB, 0x58, 0x00, 0x2B, 0x05, 0xD0, ++0x6A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x9E, 0x23, 0xEC, 0x5C, 0x64, 0x00, 0x0F, 0x33, ++0xEB, 0x5C, 0xE4, 0x18, 0xE4, 0xB2, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x58, 0xD0, 0xA3, 0x00, 0x1C, 0x19, 0x64, 0x00, ++0x66, 0x4B, 0xE3, 0x18, 0x1B, 0x88, 0xDB, 0x0B, 0x50, 0xD0, 0x65, 0x4B, 0xE7, 0x18, 0x3B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, ++0xA9, 0xD1, 0x63, 0x4B, 0xE7, 0x18, 0x3B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x38, 0xD0, 0xEC, 0x23, 0xEB, 0x58, 0x00, 0x2B, ++0xB7, 0xD1, 0x5A, 0x4B, 0xE3, 0x18, 0x1B, 0x88, 0xDB, 0x04, 0x9B, 0x0D, 0x0A, 0xD0, 0x3A, 0x88, 0x90, 0x21, 0x69, 0x58, ++0xD3, 0x18, 0x4A, 0x89, 0x92, 0x05, 0x92, 0x0D, 0x09, 0x89, 0x52, 0x18, 0x93, 0x42, 0x0D, 0xDA, 0x8C, 0x23, 0xEB, 0x58, ++0x00, 0x2B, 0x06, 0xD0, 0x4B, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, ++0x3B, 0x80, 0x98, 0xE7, 0x01, 0x23, 0xFF, 0x22, 0x59, 0x46, 0x4E, 0x48, 0x7B, 0xF7, 0x8C, 0xFE, 0x00, 0x23, 0x9A, 0x46, ++0x03, 0x70, 0x7B, 0xF7, 0xB1, 0xFE, 0x90, 0x26, 0xAB, 0x59, 0x18, 0x89, 0x85, 0xF7, 0xA2, 0xFF, 0x8C, 0x23, 0xEA, 0x58, ++0xAA, 0x51, 0x52, 0x46, 0xEA, 0x50, 0xE6, 0xE7, 0xEC, 0x23, 0xEB, 0x58, 0x00, 0x2B, 0x00, 0xD0, 0x7D, 0xE7, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x4B, 0x46, 0x9B, 0x6E, 0x98, 0x47, 0x76, 0xE7, 0x00, 0x99, 0x40, 0x46, 0xFD, 0xF7, 0x0C, 0xF8, ++0x3D, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x0A, 0xD0, 0xFC, 0xF7, 0x6E, 0xF9, 0x01, 0x28, 0x28, 0xD0, 0x03, 0xB0, 0x3C, 0xBC, ++0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xAD, 0x33, 0xEB, 0x5C, 0x00, 0x2B, 0x0E, 0xD1, 0x35, 0x4B, ++0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0x2B, 0xFF, 0xE7, 0xE7, 0xFF, 0xF7, 0x08, 0xFF, ++0x2F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0x2D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, ++0xFC, 0xF7, 0x1C, 0xFF, 0xD8, 0xE7, 0xFF, 0xF7, 0x9D, 0xFE, 0x28, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xFB, 0xF7, ++0x0F, 0xFA, 0x00, 0x28, 0xD2, 0xD0, 0xAE, 0xF7, 0xCD, 0xFB, 0x00, 0x28, 0xCE, 0xD1, 0x8A, 0xF7, 0x5D, 0xFA, 0x00, 0x28, ++0xCA, 0xD1, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0xC6, 0xD1, 0xA7, 0x33, 0xEB, 0x5C, 0x01, 0x2B, 0xC2, 0xD8, 0xD0, 0xF7, ++0xD9, 0xFA, 0x04, 0x1E, 0xBE, 0xD0, 0x1B, 0x4B, 0xC2, 0x69, 0x9A, 0x42, 0xBA, 0xD1, 0xA5, 0xF7, 0x4D, 0xFA, 0x63, 0x68, ++0x05, 0x3B, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xAA, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0xAF, 0xD0, 0x0B, 0x2B, 0xAD, 0xD9, ++0x13, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x9E, 0x23, 0xE8, 0x5C, 0xD1, 0xF7, 0x35, 0xFA, 0xAA, 0x23, 0x00, 0x22, 0xEA, 0x54, ++0xA2, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0xFC, 0xD1, 0x10, 0x00, ++0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0x07, 0xE0, 0xFF, 0xFF, 0xC8, 0x69, 0x61, 0x40, 0xD0, 0x69, 0x61, 0x40, ++0xCE, 0x69, 0x61, 0x40, 0x2B, 0x06, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0xC9, 0x1F, 0x10, 0x00, ++0x98, 0xE5, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x81, 0x46, ++0x82, 0x00, 0xBA, 0x4B, 0xD4, 0x58, 0x01, 0x94, 0xB0, 0x23, 0x15, 0x22, 0xE2, 0x54, 0x2A, 0x3B, 0xFA, 0x22, 0x52, 0x01, ++0xE2, 0x52, 0xB6, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x15, 0xD0, 0xB4, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x26, 0xD9, 0xB3, 0x4B, ++0x00, 0x22, 0x1A, 0x70, 0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x2C, 0xD0, 0x86, 0x23, 0xE3, 0x5A, 0x00, 0x2B, 0x6B, 0xD0, ++0x5B, 0x00, 0x22, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1F, 0x09, 0x29, 0xE0, 0xAB, 0x4B, 0xE3, 0x61, 0xAF, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x03, 0xD1, 0xA9, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD0, 0x01, 0x21, 0x02, 0x20, 0xFC, 0xF7, ++0x87, 0xFE, 0xDA, 0xE7, 0xFF, 0xF7, 0x64, 0xFE, 0xA3, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xA0, 0x4B, 0xE3, 0x61, ++0x9E, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xD2, 0xD0, 0x9F, 0x4B, 0x18, 0x68, 0x00, 0x28, 0xCE, 0xD0, 0xFB, 0xF7, 0x86, 0xFE, ++0xCB, 0xE7, 0xE4, 0x33, 0xE3, 0x58, 0x19, 0x68, 0xA3, 0x6F, 0xC9, 0x1A, 0x14, 0x39, 0x09, 0x01, 0x0F, 0x09, 0xA6, 0x23, ++0xE3, 0x5C, 0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x1A, 0x40, 0x96, 0x4B, 0x59, 0x78, 0x0F, 0x23, 0x0B, 0x40, 0x13, 0x43, ++0x94, 0x4A, 0x13, 0x43, 0xA3, 0x82, 0xE7, 0x60, 0xFB, 0xF7, 0x56, 0xF9, 0x02, 0x90, 0xFD, 0xF7, 0x2B, 0xF9, 0x03, 0x90, ++0xAE, 0xF7, 0x12, 0xFB, 0x06, 0x00, 0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x00, 0xD1, 0x38, 0xE2, 0x00, 0x25, 0x00, 0x28, ++0x2B, 0xD0, 0x8B, 0x4B, 0xA2, 0x6F, 0x1A, 0x60, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x5C, 0xE1, 0x88, 0x4A, ++0xD2, 0x88, 0x22, 0x61, 0x01, 0x2B, 0x00, 0xD0, 0xDA, 0xE1, 0xA7, 0x33, 0xE3, 0x5C, 0xA7, 0x21, 0x61, 0x5C, 0x5B, 0x18, ++0x1B, 0x11, 0x83, 0x49, 0x4B, 0x43, 0x93, 0x42, 0x00, 0xD2, 0x13, 0x00, 0x23, 0x61, 0xCD, 0xE1, 0xA6, 0x23, 0xE3, 0x5C, ++0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x1A, 0x40, 0x78, 0x4B, 0x59, 0x78, 0x0F, 0x23, 0x0B, 0x40, 0x13, 0x43, 0x7B, 0x4A, ++0x13, 0x43, 0xA3, 0x82, 0x01, 0x27, 0x7F, 0x42, 0xC2, 0xE7, 0xA5, 0xF7, 0x73, 0xF9, 0x60, 0x60, 0x03, 0x9B, 0x00, 0x2B, ++0x52, 0xD0, 0x76, 0x4B, 0x23, 0x61, 0x11, 0x23, 0xA3, 0x75, 0x8E, 0x33, 0xE3, 0x5C, 0x01, 0x2B, 0x47, 0xD0, 0x00, 0x25, ++0x48, 0x23, 0x9B, 0x46, 0xAF, 0x23, 0xE3, 0x5C, 0x98, 0x46, 0x20, 0x00, 0x48, 0x30, 0x7E, 0xF7, 0x83, 0xFA, 0x6E, 0x4A, ++0x12, 0x68, 0x92, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0xE0, 0xE0, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x01, 0xD1, 0x6A, 0x4B, ++0x23, 0x61, 0x40, 0x44, 0xC3, 0xB2, 0xA7, 0x22, 0xA2, 0x5C, 0x11, 0x00, 0x19, 0x43, 0x06, 0xD0, 0xD3, 0x18, 0x65, 0x4A, ++0x53, 0x43, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x23, 0x61, 0x23, 0x69, 0x62, 0x4A, 0x93, 0x42, 0x00, 0xD9, 0x13, 0x00, ++0x23, 0x61, 0x5A, 0x46, 0x21, 0x69, 0x20, 0x00, 0xFB, 0xF7, 0x16, 0xF8, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x04, 0xD1, ++0x63, 0x68, 0x03, 0x33, 0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0xA7, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x50, 0x4B, 0xA2, 0x6F, ++0x1A, 0x60, 0x20, 0x00, 0xCF, 0xF7, 0xB6, 0xFF, 0x00, 0x28, 0x00, 0xD0, 0xAE, 0xE1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, ++0x49, 0xE1, 0x37, 0x33, 0x9B, 0x46, 0xB7, 0xE7, 0x02, 0x9B, 0x00, 0x2B, 0x6B, 0xD0, 0x00, 0x23, 0x00, 0x25, 0x3E, 0x4A, ++0x90, 0x46, 0xA1, 0x22, 0x94, 0x46, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, 0x0B, 0xD0, 0x9A, 0x00, 0x41, 0x46, 0x52, 0x58, ++0x00, 0x2A, 0xF7, 0xD0, 0x61, 0x46, 0x52, 0x5C, 0x00, 0x2A, 0xF3, 0xD1, 0x01, 0x35, 0xED, 0xB2, 0xF0, 0xE7, 0x01, 0x2D, ++0x08, 0xD9, 0xA0, 0x33, 0x00, 0x22, 0xE2, 0x54, 0x41, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x28, 0x23, 0x9B, 0x46, 0x93, 0xE7, ++0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x23, 0xD1, 0xA7, 0x33, 0x00, 0x22, 0xE2, 0x54, 0x01, 0x33, 0xE2, 0x5C, 0x53, 0x42, ++0x5A, 0x41, 0x53, 0x42, 0x08, 0x22, 0x1A, 0x40, 0x68, 0x32, 0x38, 0x4B, 0x1B, 0x68, 0x98, 0x46, 0xC3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8B, 0x42, 0x04, 0xD9, 0x43, 0x46, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, ++0x00, 0x21, 0x8B, 0x46, 0x9A, 0x42, 0x01, 0xD3, 0xD3, 0x1A, 0x9B, 0x46, 0x2C, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x6B, 0xE7, ++0x01, 0x2B, 0x00, 0xD0, 0x65, 0xE1, 0xA7, 0x33, 0xE2, 0x5C, 0x53, 0x42, 0x5A, 0x41, 0x53, 0x42, 0x0C, 0x22, 0x1A, 0x40, ++0x44, 0x32, 0xE3, 0x6E, 0x98, 0x46, 0xC3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8B, 0x42, 0x04, 0xD9, ++0x43, 0x46, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0x00, 0x21, 0x8B, 0x46, 0x9A, 0x42, 0x01, 0xD3, 0xD3, 0x1A, ++0x9B, 0x46, 0x1B, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x48, 0xE7, 0x0A, 0x4B, 0x1B, 0x68, 0x00, 0x25, 0x01, 0x2B, 0x00, 0xD9, ++0x05, 0xE7, 0x13, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0x00, 0xD1, 0x37, 0xE1, 0x13, 0x4B, 0x1B, 0x68, 0x23, 0x61, ++0x00, 0x23, 0x9B, 0x46, 0x36, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x98, 0xE5, 0x10, 0x00, ++0xC1, 0x60, 0x10, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x40, 0x80, 0xFF, 0xFF, ++0xCC, 0xE6, 0x10, 0x00, 0x5C, 0xAB, 0x16, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, ++0xF4, 0xE1, 0x10, 0x00, 0x5C, 0x1C, 0x00, 0x00, 0x70, 0x71, 0x00, 0x00, 0x40, 0xE0, 0x10, 0x00, 0x2C, 0xE6, 0x10, 0x00, ++0x00, 0x23, 0x04, 0x93, 0x05, 0x93, 0x20, 0x1D, 0x23, 0x00, 0x05, 0xAA, 0x04, 0xA9, 0xFA, 0xF7, 0xAD, 0xFE, 0x04, 0x9B, ++0x00, 0x2B, 0x28, 0xD0, 0x22, 0x69, 0x9A, 0x42, 0x00, 0xD9, 0x1A, 0x00, 0x22, 0x61, 0x03, 0x26, 0x63, 0x68, 0x9A, 0x46, ++0x5A, 0x46, 0x21, 0x69, 0x01, 0x98, 0xFA, 0xF7, 0x3B, 0xFF, 0x63, 0x68, 0x53, 0x45, 0x08, 0xD0, 0x05, 0x9B, 0x53, 0x44, ++0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xEC, 0xD1, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x00, 0xD0, 0x0E, 0xE7, 0x63, 0x68, 0x03, 0x33, 0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0x23, 0x69, 0x70, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x23, 0x61, 0x03, 0xE7, 0x02, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0x9B, 0xE6, 0xEA, 0xE7, 0xA7, 0x23, 0xE3, 0x5C, ++0x00, 0x2B, 0x00, 0xD0, 0x7B, 0xE0, 0xA8, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x76, 0xE0, 0xB3, 0x33, 0xE3, 0x5C, ++0x00, 0x2B, 0x00, 0xD0, 0x71, 0xE0, 0x65, 0x4B, 0x23, 0x61, 0x73, 0x42, 0x73, 0x41, 0x5B, 0x42, 0x4B, 0x22, 0x93, 0x43, ++0x60, 0x33, 0x5B, 0x00, 0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x60, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xB0, 0x23, 0x09, 0x22, ++0xE2, 0x54, 0x20, 0x00, 0xCF, 0xF7, 0xA8, 0xFE, 0x00, 0x28, 0x00, 0xD0, 0xA0, 0xE0, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, ++0x00, 0x2E, 0x3A, 0xD0, 0xA5, 0xF7, 0x0E, 0xF8, 0x57, 0x4B, 0x18, 0x60, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x66, 0x60, 0x80, 0xE0, 0x00, 0x2E, 0x00, 0xD1, 0x86, 0xE0, 0x51, 0x4B, 0x23, 0x61, ++0x20, 0x00, 0xFD, 0xF7, 0x57, 0xFE, 0x60, 0x60, 0x18, 0x26, 0x65, 0x68, 0x00, 0x22, 0x21, 0x69, 0x01, 0x98, 0xFA, 0xF7, ++0xD1, 0xFE, 0x63, 0x68, 0xAB, 0x42, 0x06, 0xD0, 0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x18, 0x36, 0x60, 0x2E, ++0xEF, 0xD1, 0x20, 0x00, 0xCF, 0xF7, 0x76, 0xFE, 0x00, 0x28, 0x6F, 0xD1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xCF, 0xE7, ++0x39, 0x00, 0x14, 0x31, 0x09, 0x01, 0x09, 0x09, 0x48, 0x46, 0x40, 0x4B, 0x98, 0x47, 0xCB, 0xE7, 0xA0, 0x23, 0x00, 0x22, ++0xE2, 0x54, 0xA3, 0x7D, 0x10, 0x2B, 0x01, 0xD8, 0x11, 0x23, 0xA3, 0x75, 0x02, 0x9B, 0x00, 0x2B, 0xBC, 0xD0, 0x01, 0x2D, ++0xBA, 0xD1, 0x39, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0xB5, 0xD1, 0x37, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x9F, 0x23, ++0xE3, 0x5C, 0x01, 0x2B, 0xAE, 0xD1, 0x35, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0xAA, 0xE7, 0x34, 0x4B, 0xDB, 0x88, 0x23, 0x61, ++0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0xB0, 0xD0, 0x00, 0x2E, 0xB1, 0xD1, 0x30, 0x4B, 0x23, 0x61, 0xA7, 0x23, 0xE3, 0x5C, ++0x00, 0x2B, 0x03, 0xD1, 0xA8, 0x22, 0xA2, 0x5C, 0x00, 0x2A, 0x2E, 0xD0, 0xA8, 0x22, 0xA1, 0x5C, 0xCB, 0x18, 0x2A, 0x49, ++0x59, 0x43, 0x29, 0x4B, 0x9C, 0x46, 0x61, 0x44, 0x21, 0x61, 0x23, 0x4B, 0x1A, 0x68, 0x53, 0x6F, 0x58, 0x42, 0x43, 0x41, ++0x5B, 0x42, 0x1B, 0x48, 0x03, 0x40, 0x24, 0x48, 0x84, 0x46, 0x63, 0x44, 0x92, 0x68, 0x00, 0x2A, 0x02, 0xD0, 0x22, 0x4A, ++0x12, 0x68, 0x9B, 0x1A, 0x99, 0x42, 0x00, 0xD9, 0x19, 0x00, 0x21, 0x61, 0x66, 0x68, 0x28, 0x22, 0x20, 0x00, 0xFA, 0xF7, ++0x63, 0xFE, 0x01, 0x28, 0x00, 0xD1, 0x7C, 0xE7, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x04, 0xD1, 0x63, 0x68, 0x03, 0x33, ++0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0x20, 0x00, 0xCF, 0xF7, 0x06, 0xFE, 0x00, 0x28, 0x9B, 0xD0, 0xA1, 0x23, 0xE3, 0x5C, ++0x04, 0x2B, 0x8F, 0xD0, 0x08, 0x21, 0x48, 0x46, 0x11, 0x4B, 0x98, 0x47, 0x5E, 0xE7, 0x00, 0x25, 0xC7, 0xE5, 0x00, 0x25, ++0xC5, 0xE5, 0x00, 0x23, 0x9B, 0x46, 0xFF, 0xE5, 0xAA, 0xF8, 0xFF, 0xFF, 0x98, 0x12, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, ++0x34, 0xE6, 0x10, 0x00, 0x88, 0x13, 0x00, 0x00, 0xB9, 0x4C, 0x0B, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x40, 0xE0, 0x10, 0x00, ++0x44, 0xE0, 0x10, 0x00, 0x5C, 0xAB, 0x16, 0x00, 0x5C, 0x1C, 0x00, 0x00, 0x7C, 0x42, 0x00, 0x00, 0xE8, 0xE1, 0x10, 0x00, ++0x95, 0x0F, 0x0B, 0x00, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0xB7, 0x4B, 0xB8, 0x4A, ++0x13, 0x60, 0x80, 0x22, 0x52, 0x00, 0x9C, 0x5C, 0xFD, 0xF7, 0x5A, 0xFA, 0xB5, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, ++0x09, 0xD0, 0xB2, 0x4B, 0x1D, 0x68, 0x02, 0x23, 0xFF, 0x33, 0xEB, 0x5C, 0xA3, 0x42, 0x00, 0xD1, 0x42, 0xE1, 0xB0, 0x4F, ++0x84, 0xE0, 0xFA, 0xF7, 0xFD, 0xFD, 0xF2, 0xE7, 0xAE, 0x4A, 0x93, 0x42, 0x46, 0xD1, 0xAE, 0x4B, 0x4B, 0x60, 0x43, 0xE0, ++0xAD, 0x49, 0x8B, 0x42, 0x00, 0xD1, 0xE5, 0xE0, 0xAC, 0x49, 0x8B, 0x42, 0x16, 0xD1, 0xAC, 0x4B, 0x1A, 0x68, 0x00, 0x2A, ++0x38, 0xD0, 0x23, 0x01, 0xED, 0x18, 0xA9, 0x68, 0x8B, 0x00, 0x9B, 0x58, 0x00, 0x9A, 0x48, 0x46, 0x02, 0x43, 0xD2, 0xB2, ++0x00, 0x2A, 0x04, 0xD0, 0x00, 0x29, 0x00, 0xD0, 0xCC, 0xE0, 0xD8, 0x22, 0x1A, 0x86, 0x00, 0x22, 0x9A, 0x62, 0x25, 0xE0, ++0xA1, 0x49, 0x8B, 0x42, 0x22, 0xD1, 0x02, 0x2A, 0x20, 0xD1, 0x00, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0xA5, 0xFB, 0x1B, 0xE0, ++0x9D, 0x4B, 0x1D, 0x68, 0x00, 0x9B, 0x4A, 0x46, 0x13, 0x43, 0xDB, 0xB2, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x23, 0xAB, 0x62, ++0x34, 0x33, 0x01, 0x22, 0xEA, 0x54, 0xAE, 0xF7, 0x53, 0xF8, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0xC0, 0x22, 0x92, 0x01, ++0x13, 0x40, 0x80, 0x22, 0x52, 0x01, 0x94, 0x46, 0x63, 0x44, 0x2B, 0x86, 0x12, 0x23, 0x6B, 0x86, 0x86, 0x4B, 0x1B, 0x68, ++0x52, 0x46, 0x98, 0x18, 0x45, 0x68, 0x00, 0x2D, 0x00, 0xD1, 0xD1, 0xE0, 0x42, 0x46, 0x04, 0x3A, 0x51, 0x42, 0x4A, 0x41, ++0xD2, 0xB2, 0x31, 0x01, 0x5B, 0x18, 0x99, 0x68, 0x00, 0x68, 0xA8, 0x47, 0x7D, 0x4B, 0x1D, 0x68, 0x33, 0x01, 0xEB, 0x18, ++0x85, 0x4A, 0x5B, 0x68, 0x93, 0x42, 0x00, 0xD1, 0xC5, 0xE0, 0x33, 0x01, 0xEB, 0x18, 0x00, 0x22, 0x1A, 0x73, 0x03, 0x32, ++0xFF, 0x32, 0xAB, 0x5C, 0x01, 0x3B, 0xAB, 0x54, 0x02, 0x23, 0xFF, 0x33, 0xEA, 0x5C, 0x0F, 0x21, 0xA2, 0x42, 0x00, 0xD1, ++0xC5, 0xE0, 0x01, 0x34, 0x0C, 0x40, 0x23, 0x01, 0xEB, 0x18, 0x1B, 0x7B, 0x00, 0x2B, 0xF5, 0xD0, 0x80, 0x23, 0x5B, 0x00, ++0xEC, 0x54, 0xA2, 0x42, 0x00, 0xD1, 0xBB, 0xE0, 0x26, 0x00, 0x75, 0x4B, 0xE3, 0x18, 0x1B, 0x01, 0x1B, 0x88, 0x9B, 0x06, ++0x5B, 0x0F, 0x98, 0x46, 0x03, 0x3B, 0x02, 0x2B, 0x00, 0xD9, 0xAF, 0xE0, 0xFB, 0xF7, 0x70, 0xFD, 0x00, 0x90, 0x01, 0x90, ++0x3A, 0x68, 0x00, 0x23, 0x01, 0x21, 0x91, 0x42, 0x5B, 0x41, 0xDB, 0xB2, 0x99, 0x46, 0x23, 0x01, 0x9A, 0x46, 0xE9, 0x18, ++0x4B, 0x68, 0x69, 0x48, 0x83, 0x42, 0x62, 0xD0, 0x00, 0xD9, 0x63, 0xE7, 0x67, 0x4A, 0x93, 0x42, 0x88, 0xD0, 0x63, 0x4A, ++0x93, 0x42, 0x00, 0xD0, 0x56, 0xE7, 0x65, 0x4B, 0x1D, 0x68, 0x00, 0x23, 0xAB, 0x62, 0x51, 0x33, 0x01, 0x22, 0xEA, 0x54, ++0xAD, 0xF7, 0xDE, 0xFF, 0x00, 0x28, 0x05, 0xD0, 0x80, 0x23, 0x9B, 0x01, 0xAB, 0x85, 0x06, 0x23, 0xEB, 0x85, 0x8F, 0xE7, ++0x50, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x0B, 0xD0, 0x00, 0x9B, 0x4A, 0x46, 0x13, 0x43, 0xDB, 0xB2, 0x00, 0x2B, 0x1C, 0xD1, ++0x80, 0x23, 0x1B, 0x01, 0xAB, 0x85, 0x12, 0x23, 0xEB, 0x85, 0x7F, 0xE7, 0x55, 0x4B, 0xEB, 0x61, 0x01, 0x9B, 0x00, 0x2B, ++0x03, 0xD1, 0xFD, 0xF7, 0x13, 0xFA, 0x01, 0x28, 0x07, 0xD9, 0x00, 0x9A, 0xD3, 0x02, 0xAB, 0x85, 0x09, 0x23, 0x9B, 0x1A, ++0x5B, 0x00, 0xEB, 0x85, 0x6E, 0xE7, 0x80, 0x23, 0x5B, 0x00, 0xAB, 0x85, 0xEE, 0x3B, 0xEB, 0x85, 0x68, 0xE7, 0xFD, 0xF7, ++0x41, 0xF9, 0x01, 0x28, 0x00, 0xD8, 0x63, 0xE7, 0x80, 0x23, 0xDB, 0x01, 0xAB, 0x85, 0x08, 0x23, 0xEB, 0x85, 0x5D, 0xE7, ++0xC8, 0x22, 0x92, 0x00, 0x1A, 0x86, 0x30, 0xE7, 0x01, 0x2A, 0x00, 0xD9, 0x56, 0xE7, 0x01, 0x9B, 0x00, 0x2B, 0x00, 0xD1, ++0x52, 0xE7, 0x23, 0x01, 0xED, 0x18, 0xAB, 0x68, 0x9B, 0x00, 0x3E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x68, 0xC0, 0x22, ++0x12, 0x01, 0xDA, 0x66, 0x46, 0xE7, 0x02, 0x2A, 0x00, 0xD0, 0x43, 0xE7, 0x23, 0x01, 0xED, 0x18, 0x2B, 0x7A, 0x9B, 0x00, ++0x37, 0x4A, 0x9D, 0x58, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x03, 0xD1, 0x35, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x09, 0xD0, ++0xA0, 0x23, 0xEB, 0x5C, 0x02, 0x2B, 0x00, 0xD0, 0x30, 0xE7, 0x01, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0xB5, 0xFA, 0x2B, 0xE7, ++0xFF, 0xF7, 0x92, 0xFA, 0x00, 0x23, 0x2D, 0x4A, 0x13, 0x70, 0xEF, 0xE7, 0x2C, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x30, 0xE7, 0x24, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x00, 0xD1, 0x34, 0xE7, 0x11, 0x22, 0x9A, 0x75, ++0x31, 0xE7, 0xFB, 0xF7, 0x93, 0xFB, 0x11, 0xE0, 0x80, 0x20, 0x80, 0x00, 0x7A, 0xF7, 0xE2, 0xFD, 0x13, 0xE0, 0x80, 0x23, ++0x5B, 0x00, 0xEC, 0x54, 0x81, 0x23, 0x5B, 0x00, 0xEB, 0x5C, 0x00, 0x2B, 0x04, 0xD1, 0x05, 0x33, 0xFF, 0x33, 0xEB, 0x58, ++0x00, 0x2B, 0xEA, 0xD0, 0x07, 0x4B, 0x1A, 0x68, 0x81, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0x00, 0x2B, 0xE6, 0xD0, 0x02, 0xB0, ++0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, ++0xF4, 0xE1, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x31, 0xC3, 0x0A, 0x00, 0xE1, 0xA1, 0x10, 0x00, 0xE9, 0x8F, 0x0C, 0x00, ++0xCD, 0x05, 0x0D, 0x00, 0xF0, 0x29, 0x16, 0x00, 0x5D, 0x74, 0x0B, 0x00, 0x20, 0x27, 0x16, 0x00, 0xD9, 0xEA, 0x0A, 0x00, ++0x00, 0x10, 0x06, 0x04, 0x11, 0x6F, 0x0B, 0x00, 0x99, 0xCA, 0x0A, 0x00, 0x28, 0x27, 0x16, 0x00, 0x01, 0x00, 0x10, 0x00, ++0x84, 0x29, 0x16, 0x00, 0x38, 0x27, 0x16, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x04, 0x4B, ++0x1B, 0x7F, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0x02, 0x4B, 0x98, 0x47, 0xFB, 0xE7, 0xC0, 0x46, 0x24, 0x2A, 0x16, 0x00, ++0x69, 0x44, 0x0D, 0x00, 0x10, 0xB5, 0x05, 0x4B, 0x80, 0x22, 0xD2, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, ++0xAF, 0xF8, 0xFF, 0xF7, 0xE7, 0xFF, 0x10, 0xBD, 0x08, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x2D, 0x4B, 0x1B, 0x68, 0xC0, 0x22, ++0x92, 0x02, 0x13, 0x42, 0x16, 0xD1, 0x5A, 0x03, 0x1E, 0xD4, 0x1A, 0x03, 0x2D, 0xD4, 0xDA, 0x02, 0x34, 0xD4, 0x9A, 0x02, ++0x36, 0xD4, 0x5A, 0x02, 0x38, 0xD4, 0xDA, 0x01, 0x39, 0xD4, 0x9A, 0x01, 0x3E, 0xD4, 0x5B, 0x01, 0x0F, 0xD5, 0xFD, 0xF7, ++0x1B, 0xFF, 0x22, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0x08, 0xE0, 0x20, 0x4D, 0x91, 0x24, 0xE4, 0x00, 0x00, 0x23, ++0x2B, 0x51, 0x84, 0xF7, 0x7F, 0xFB, 0x1E, 0x4B, 0x2B, 0x51, 0x70, 0xBD, 0x1D, 0x4B, 0x1C, 0x78, 0xFE, 0xF7, 0x84, 0xFE, ++0x02, 0x2C, 0x04, 0xD0, 0x17, 0x4B, 0x80, 0x22, 0xD2, 0x02, 0x1A, 0x60, 0xF3, 0xE7, 0x19, 0x4B, 0x01, 0x22, 0x1A, 0x70, ++0x84, 0xF7, 0x32, 0xFB, 0xED, 0xE7, 0x12, 0x4B, 0x80, 0x22, 0x12, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, ++0x3F, 0xFD, 0xE4, 0xE7, 0x01, 0x20, 0x84, 0xF7, 0x3D, 0xFB, 0xE0, 0xE7, 0x02, 0x20, 0x84, 0xF7, 0x39, 0xFB, 0xDC, 0xE7, ++0xFF, 0xF7, 0xA6, 0xFF, 0xD9, 0xE7, 0xFA, 0xF7, 0xF1, 0xFD, 0x07, 0x4B, 0x80, 0x22, 0x52, 0x04, 0x1A, 0x60, 0xD2, 0xE7, ++0xFA, 0xF7, 0x9A, 0xFF, 0x03, 0x4B, 0x80, 0x22, 0x92, 0x04, 0x1A, 0x60, 0xCB, 0xE7, 0xC0, 0x46, 0x1C, 0x41, 0x04, 0x40, ++0x08, 0x41, 0x04, 0x40, 0x28, 0x19, 0x16, 0x00, 0x31, 0x6D, 0x10, 0x00, 0xE0, 0x1D, 0x16, 0x00, 0xE1, 0x1D, 0x16, 0x00, ++0x10, 0xB5, 0x04, 0x4B, 0x80, 0x22, 0x12, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, 0x0F, 0xFD, 0x10, 0xBD, ++0x08, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x09, 0x4B, 0xDB, 0x7F, 0x00, 0x2B, 0x08, 0xD0, 0x00, 0x28, 0x01, 0xD1, 0x00, 0x29, ++0x04, 0xD0, 0x01, 0x20, 0x80, 0xF7, 0xD6, 0xFF, 0x84, 0xF7, 0x00, 0xFD, 0x03, 0x49, 0x40, 0x22, 0x0B, 0x6B, 0x1A, 0x42, ++0xFC, 0xD0, 0x10, 0xBD, 0x3C, 0x95, 0x16, 0x00, 0x00, 0x60, 0x50, 0x40, 0x70, 0xB5, 0x82, 0xB0, 0x27, 0x4A, 0xD3, 0x69, ++0x0F, 0x24, 0xA3, 0x43, 0xD3, 0x61, 0x26, 0x4B, 0x99, 0x68, 0x80, 0x20, 0x01, 0x43, 0x99, 0x60, 0x59, 0x68, 0x01, 0x43, ++0x59, 0x60, 0x19, 0x68, 0x01, 0x43, 0x19, 0x60, 0x13, 0x69, 0xA3, 0x43, 0x13, 0x61, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, ++0xEF, 0xFC, 0x01, 0x9C, 0x00, 0x9B, 0x1E, 0x00, 0x7A, 0x36, 0x9C, 0x22, 0x92, 0x00, 0x96, 0x42, 0x19, 0xD9, 0xF8, 0x3B, ++0xFF, 0x3B, 0x1E, 0x00, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0x80, 0x25, 0x2D, 0x05, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, ++0xDB, 0xFC, 0x01, 0x9A, 0xA3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xAB, 0x42, 0xF5, 0xD9, 0x12, 0x1B, 0x12, 0x01, 0xF2, 0xD0, ++0x00, 0x9B, 0xB3, 0x42, 0xEF, 0xD3, 0x02, 0xB0, 0x70, 0xBD, 0xB3, 0x42, 0xE9, 0xD2, 0x80, 0x25, 0x2D, 0x05, 0x02, 0xE0, ++0x00, 0x9B, 0xB3, 0x42, 0xF5, 0xD2, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, 0xC1, 0xFC, 0x01, 0x9A, 0xA3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0xAB, 0x42, 0xF2, 0xD9, 0x12, 0x1B, 0x12, 0x01, 0xEF, 0xD0, 0xE7, 0xE7, 0xC0, 0x46, 0x00, 0x30, 0x50, 0x40, ++0x00, 0x40, 0x50, 0x40, 0x70, 0xB5, 0x10, 0x4B, 0x9A, 0x69, 0x10, 0x4B, 0x1A, 0x42, 0x0A, 0xD1, 0x0F, 0x4D, 0x10, 0x4C, ++0x29, 0x68, 0x00, 0x20, 0xFA, 0xF7, 0xD0, 0xFC, 0x7B, 0xF7, 0x96, 0xFD, 0x23, 0x68, 0x01, 0x2B, 0xF6, 0xD0, 0x0C, 0x4A, ++0x13, 0x68, 0x01, 0x33, 0x13, 0x60, 0x0B, 0x4B, 0x1B, 0x68, 0x03, 0x3B, 0x01, 0x2B, 0x00, 0xD9, 0x70, 0xBD, 0x03, 0x4A, ++0x80, 0x23, 0x1B, 0x02, 0x91, 0x69, 0x0B, 0x43, 0x93, 0x61, 0xF7, 0xE7, 0x3C, 0x95, 0x16, 0x00, 0x01, 0x20, 0x00, 0x00, ++0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x20, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x02, 0x38, 0x01, 0x28, ++0x11, 0xD8, 0x09, 0x4A, 0x80, 0x23, 0x5B, 0x00, 0x08, 0x21, 0xD1, 0x50, 0x07, 0x49, 0x8B, 0x68, 0x07, 0x4A, 0x1A, 0x40, ++0x80, 0x23, 0x9B, 0x02, 0x13, 0x43, 0x8B, 0x60, 0x22, 0x22, 0x0B, 0x6B, 0x13, 0x40, 0x02, 0x2B, 0xFB, 0xD1, 0x70, 0x47, ++0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, 0xFF, 0xFF, 0xFB, 0xFF, 0x70, 0xB5, 0xA6, 0xF7, 0x3D, 0xFF, 0x04, 0x1E, ++0x0D, 0xD1, 0x1A, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x09, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x17, 0xD4, 0x72, 0xB6, ++0x3E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x62, 0xB6, 0x20, 0x00, 0x70, 0xBD, 0x13, 0x4B, 0x1D, 0x68, 0x00, 0x21, ++0xCF, 0xF7, 0x7A, 0xFC, 0x2B, 0x6B, 0x5B, 0x00, 0x6A, 0x68, 0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x0E, 0x4A, 0x13, 0x60, ++0x0E, 0x4B, 0x98, 0x47, 0xEC, 0xE7, 0x3E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0xE9, 0xD1, 0x09, 0x4B, 0x1D, 0x68, 0x00, 0x21, ++0xCF, 0xF7, 0x66, 0xFC, 0x2B, 0x6B, 0x5B, 0x00, 0x6A, 0x68, 0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x04, 0x4A, 0x13, 0x60, ++0x04, 0x4B, 0x98, 0x47, 0xD9, 0xE7, 0xC0, 0x46, 0x28, 0x27, 0x16, 0x00, 0x24, 0x27, 0x16, 0x00, 0x18, 0x2C, 0x16, 0x00, ++0x15, 0xE6, 0x0A, 0x00, 0x10, 0xB5, 0xA5, 0xF7, 0xC7, 0xFA, 0x00, 0x28, 0x0F, 0xD1, 0x0B, 0x4B, 0x19, 0x68, 0x00, 0x29, ++0x0B, 0xD0, 0x0A, 0x4B, 0xCB, 0x61, 0x0A, 0x4B, 0x1C, 0x00, 0x41, 0x34, 0xFF, 0x34, 0x1A, 0x78, 0x09, 0x2A, 0x03, 0xD0, ++0x40, 0x33, 0xA3, 0x42, 0xF9, 0xD1, 0x10, 0xBD, 0x0B, 0x69, 0x05, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x0B, 0x61, 0xF8, 0xE7, ++0x18, 0x27, 0x16, 0x00, 0x51, 0x04, 0x10, 0x00, 0x70, 0xA6, 0x16, 0x00, 0x78, 0xEC, 0xFF, 0xFF, 0x10, 0xB5, 0x02, 0x00, ++0x0C, 0x00, 0x01, 0x23, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0xC2, 0xFF, 0x04, 0x70, 0xCC, 0xF7, 0x1F, 0xFE, 0x10, 0xBD, ++0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x02, 0x00, 0x0C, 0x00, 0x01, 0x23, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0xB4, 0xFF, ++0x04, 0x70, 0xCC, 0xF7, 0x11, 0xFE, 0x10, 0xBD, 0x02, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x06, 0x23, 0x13, 0x4A, 0x00, 0x21, ++0x13, 0x48, 0x7A, 0xF7, 0xA7, 0xFF, 0x13, 0x4A, 0x2D, 0x23, 0xD3, 0x5C, 0x1B, 0x09, 0x12, 0x4A, 0x12, 0x78, 0x02, 0x2A, ++0x0B, 0xD0, 0x01, 0x2A, 0x10, 0xD0, 0x0E, 0x4A, 0x2D, 0x23, 0xD3, 0x5C, 0x03, 0x71, 0x00, 0x23, 0x03, 0x70, 0xCC, 0xF7, ++0xF5, 0xFD, 0x00, 0x20, 0x10, 0xBD, 0x0B, 0x4A, 0xD2, 0x5C, 0x80, 0x23, 0x9B, 0x00, 0x13, 0x43, 0x43, 0x80, 0xEE, 0xE7, ++0x08, 0x4A, 0xD2, 0x5C, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x43, 0x80, 0xE7, 0xE7, 0xC0, 0x46, 0x2D, 0x0C, 0x00, 0x00, ++0x01, 0x11, 0x00, 0x00, 0x60, 0x92, 0x16, 0x00, 0xB4, 0xE5, 0x10, 0x00, 0x30, 0xE0, 0x10, 0x00, 0x28, 0xE0, 0x10, 0x00, ++0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x19, 0x78, 0x03, 0x4A, 0x2D, 0x23, 0xD1, 0x54, 0x00, 0x21, 0xFF, 0xF7, 0xB2, 0xFF, ++0x00, 0x20, 0x10, 0xBD, 0x60, 0x92, 0x16, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0xD1, 0xF7, 0x96, 0xFF, ++0x06, 0x00, 0x2C, 0x4B, 0x99, 0x6F, 0x00, 0x29, 0x15, 0xD0, 0xF8, 0x22, 0x20, 0x00, 0xD1, 0xF7, 0xBB, 0xFF, 0x00, 0x21, ++0x00, 0x28, 0x0A, 0xD1, 0x26, 0x4A, 0x30, 0x23, 0xD3, 0x5C, 0x01, 0x2B, 0x21, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0x86, 0xFF, ++0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x21, 0x4B, 0x98, 0x6F, 0x7B, 0xF7, 0xBF, 0xF8, 0xFF, 0x20, 0x06, 0x40, 0xF8, 0x2E, ++0x00, 0xD9, 0xF8, 0x26, 0x70, 0x1C, 0x00, 0x21, 0x7B, 0xF7, 0x12, 0xF8, 0x1A, 0x4B, 0x98, 0x67, 0x07, 0x21, 0x00, 0x28, ++0xE2, 0xD0, 0x32, 0x00, 0x21, 0x00, 0xD1, 0xF7, 0x2F, 0xFE, 0x16, 0x4B, 0x9B, 0x6F, 0x00, 0x22, 0x9A, 0x55, 0x00, 0x21, ++0xD8, 0xE7, 0x7F, 0x33, 0x5B, 0x00, 0x2F, 0x22, 0x00, 0x21, 0x12, 0x48, 0x7A, 0xF7, 0x2A, 0xFF, 0x06, 0x00, 0x01, 0xA9, ++0x0D, 0x70, 0x2D, 0x0A, 0x4D, 0x70, 0xF8, 0x23, 0x8B, 0x70, 0x03, 0x22, 0xD1, 0xF7, 0x18, 0xFE, 0xF0, 0x1C, 0xF8, 0x22, ++0x21, 0x00, 0xD1, 0xF7, 0x13, 0xFE, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x30, 0x00, 0x0C, 0x38, 0x08, 0x4B, 0x98, 0x47, ++0x08, 0x4B, 0x5B, 0x7F, 0x5B, 0xB2, 0x04, 0x2B, 0xBE, 0xDC, 0x01, 0x33, 0x05, 0x4A, 0x53, 0x77, 0xBA, 0xE7, 0xC0, 0x46, ++0x68, 0x9E, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, 0x68, 0xE6, 0x10, 0x00, 0xA5, 0x4B, 0x0D, 0x00, 0x24, 0x2A, 0x16, 0x00, ++0xF8, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x16, 0x00, 0x1F, 0x00, 0x02, 0x20, 0x79, 0xF7, 0x46, 0xFE, 0x6B, 0x1E, 0x1C, 0x70, ++0x63, 0x1E, 0x03, 0x2B, 0x22, 0xD8, 0x04, 0x2C, 0x10, 0xD0, 0x68, 0x1E, 0x16, 0x4B, 0x18, 0x61, 0x1E, 0x83, 0x5F, 0x61, ++0x1B, 0x7F, 0xFF, 0x2B, 0x25, 0xD1, 0x13, 0x4B, 0x00, 0x22, 0x1A, 0x77, 0x71, 0x1C, 0x1A, 0x68, 0x54, 0x68, 0x11, 0x4A, ++0xA0, 0x47, 0x1C, 0xE0, 0x2B, 0x78, 0x2F, 0x2B, 0xEB, 0xD1, 0x0F, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xE7, 0xD0, 0x19, 0x23, ++0x2B, 0x70, 0xE2, 0x33, 0x6B, 0x70, 0x0B, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xFD, 0x26, 0xDE, 0xE7, 0x09, 0x4D, 0x00, 0x23, ++0x00, 0x22, 0x01, 0x21, 0x20, 0x00, 0xEE, 0x6E, 0xB0, 0x47, 0xED, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x01, 0x21, 0x20, 0x00, ++0xA8, 0x47, 0xF8, 0xBD, 0x58, 0x1E, 0x16, 0x00, 0x19, 0x74, 0x08, 0x00, 0x68, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0xC0, 0xB5, 0x86, 0xB0, 0x04, 0x00, 0x0E, 0x00, 0x03, 0x92, 0xCE, 0xF7, ++0x93, 0xFE, 0x07, 0x00, 0xB8, 0x4B, 0x1D, 0x25, 0x5D, 0x57, 0x2B, 0x00, 0x80, 0x33, 0x00, 0xD1, 0x61, 0xE1, 0x01, 0x3D, ++0x6D, 0xB2, 0xB4, 0x4B, 0x5D, 0x77, 0x00, 0x28, 0x00, 0xD1, 0x18, 0xE1, 0x00, 0x2D, 0x00, 0xDA, 0x59, 0xE1, 0x80, 0x78, ++0x0F, 0x23, 0x18, 0x40, 0x08, 0x28, 0x5F, 0xD8, 0x83, 0x00, 0xAE, 0x4A, 0xD3, 0x58, 0x9F, 0x46, 0x05, 0x23, 0x99, 0x46, ++0x67, 0xE0, 0x06, 0x28, 0x1E, 0xD0, 0x01, 0x2E, 0x00, 0xD8, 0x3B, 0xE1, 0x03, 0x9A, 0x53, 0x78, 0x1B, 0x02, 0x12, 0x78, ++0x13, 0x43, 0x0B, 0x2B, 0x00, 0xD9, 0x22, 0xE1, 0xA5, 0x4A, 0xD2, 0x18, 0x12, 0x7E, 0x00, 0x2A, 0x00, 0xD1, 0x2D, 0xE1, ++0xA2, 0x04, 0x37, 0xD4, 0xA2, 0x4A, 0x94, 0x42, 0x34, 0xD0, 0x27, 0xD8, 0xA1, 0x4A, 0x94, 0x42, 0x30, 0xD0, 0xA1, 0x4A, ++0x94, 0x42, 0x00, 0xD0, 0x20, 0xE1, 0x2B, 0xE0, 0x05, 0x2E, 0x00, 0xD8, 0x1C, 0xE1, 0x9E, 0x4D, 0x00, 0x23, 0x99, 0x46, ++0x07, 0xE0, 0x01, 0x23, 0x9C, 0x46, 0xE1, 0x44, 0x07, 0x35, 0x4B, 0x46, 0x07, 0x2B, 0x00, 0xD1, 0x10, 0xE1, 0x2B, 0x78, ++0x00, 0x2B, 0xF4, 0xD0, 0x69, 0x1C, 0x06, 0x22, 0x03, 0x98, 0xD1, 0xF7, 0x2D, 0xFD, 0x00, 0x28, 0xED, 0xD1, 0x4B, 0x46, ++0x1B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x26, 0xE0, 0x90, 0x4A, 0x94, 0x42, 0x04, 0xD8, 0x90, 0x4A, ++0x94, 0x42, 0x00, 0xD8, 0xF8, 0xE0, 0x03, 0xE0, 0x8E, 0x4A, 0x94, 0x42, 0x00, 0xD0, 0xF3, 0xE0, 0x1B, 0x02, 0x04, 0x22, ++0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x14, 0xE0, 0x1B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x0E, 0xE0, ++0x87, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xA8, 0x47, 0xAF, 0xE0, 0x03, 0x23, 0x99, 0x46, 0x04, 0xE0, ++0x02, 0x23, 0x99, 0x46, 0x01, 0xE0, 0x00, 0x23, 0x99, 0x46, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x00, 0x22, ++0x1A, 0x80, 0x7E, 0x4B, 0x92, 0x46, 0x9C, 0x42, 0x59, 0xD0, 0x00, 0x2E, 0x00, 0xD1, 0xAD, 0xE0, 0x7D, 0x68, 0x00, 0x2D, ++0x00, 0xD1, 0x9C, 0xE0, 0xBB, 0x78, 0x5B, 0x06, 0x65, 0xD5, 0xB3, 0xB2, 0x0E, 0x22, 0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, ++0x03, 0x99, 0x00, 0x20, 0xA8, 0x47, 0xC5, 0xB2, 0x01, 0x2D, 0x66, 0xD0, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, ++0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x6F, 0x48, 0x7A, 0xF7, 0x00, 0xFE, 0x81, 0x46, 0x00, 0x2D, 0x07, 0xD0, 0x6A, 0x4B, ++0xDB, 0x6E, 0x9B, 0x46, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0x28, 0x00, 0xD8, 0x47, 0x4B, 0x46, 0x00, 0x2B, 0x59, 0xD0, ++0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x00, 0x2B, 0x0F, 0xD0, 0x7B, 0x68, 0x9B, 0x46, 0x00, 0x2B, ++0x0B, 0xD0, 0xBB, 0x78, 0x5B, 0x06, 0x51, 0xD5, 0xB3, 0xB2, 0x0E, 0x22, 0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, 0x03, 0x99, ++0x48, 0x46, 0xD8, 0x47, 0xC5, 0xB2, 0x00, 0x2D, 0x06, 0xD0, 0x58, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, ++0x28, 0x00, 0xB0, 0x47, 0x48, 0x46, 0x7A, 0xF7, 0xF9, 0xFD, 0x54, 0x4B, 0x9C, 0x42, 0x4A, 0xD1, 0x53, 0x46, 0x00, 0x2B, ++0x47, 0xD0, 0x50, 0x46, 0x7A, 0xF7, 0x3C, 0xFF, 0x43, 0xE0, 0x75, 0x1C, 0x01, 0x21, 0x28, 0x00, 0x7A, 0xF7, 0x92, 0xFE, ++0x82, 0x46, 0x03, 0x99, 0x0B, 0x78, 0x03, 0x70, 0x72, 0x1E, 0x42, 0x70, 0x01, 0x31, 0x02, 0x30, 0xD1, 0xF7, 0xAE, 0xFC, ++0xEE, 0xB2, 0x49, 0x48, 0x7C, 0xF7, 0xB6, 0xFE, 0x53, 0x46, 0x03, 0x93, 0x8F, 0xE7, 0xB3, 0xB2, 0x00, 0x95, 0x0E, 0x22, ++0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, 0x03, 0x99, 0x00, 0x20, 0x7D, 0xF7, 0x57, 0xF8, 0x05, 0x00, 0x96, 0xE7, 0x21, 0x00, ++0x40, 0x48, 0x7C, 0xF7, 0xA3, 0xFE, 0x00, 0x23, 0x12, 0x22, 0x21, 0x00, 0x38, 0x00, 0x3E, 0x4D, 0xA8, 0x47, 0xC8, 0xE7, ++0x07, 0x22, 0x21, 0x00, 0x38, 0x00, 0x3B, 0x4D, 0xA8, 0x47, 0xC2, 0xE7, 0xB3, 0xB2, 0x5A, 0x46, 0x00, 0x92, 0x0E, 0x22, ++0x62, 0x44, 0x03, 0x99, 0x48, 0x46, 0x7D, 0xF7, 0x3B, 0xF8, 0x05, 0x00, 0xAB, 0xE7, 0x00, 0x23, 0x01, 0x22, 0x21, 0x00, ++0x00, 0x20, 0x32, 0x4C, 0xA0, 0x47, 0x06, 0xB0, 0x1C, 0xBC, 0x91, 0x46, 0x9A, 0x46, 0xA3, 0x46, 0xF0, 0xBD, 0x0E, 0x23, ++0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x27, 0x48, 0x7A, 0xF7, 0x71, 0xFD, 0x81, 0x46, ++0x04, 0x25, 0x70, 0xE7, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x21, 0x48, ++0x7A, 0xF7, 0x64, 0xFD, 0x81, 0x46, 0x35, 0x00, 0x6B, 0xE7, 0x22, 0x4A, 0x13, 0x40, 0x1A, 0x00, 0x80, 0x3A, 0x92, 0xB2, ++0x06, 0x2A, 0x09, 0xD8, 0x80, 0x3B, 0xD9, 0x00, 0xC9, 0x1A, 0x0F, 0x4A, 0x52, 0x18, 0x24, 0x32, 0x12, 0x78, 0x02, 0x2A, ++0x00, 0xD1, 0x11, 0xE7, 0x21, 0x00, 0x1A, 0x48, 0x7C, 0xF7, 0x50, 0xFE, 0x03, 0x9B, 0x02, 0x22, 0x21, 0x00, 0x38, 0x00, ++0x14, 0x4C, 0xA0, 0x47, 0xC3, 0xE7, 0x00, 0x28, 0xBB, 0xD0, 0x00, 0x23, 0x07, 0x22, 0x21, 0x00, 0x38, 0x00, 0x10, 0x4C, ++0xA0, 0x47, 0xBA, 0xE7, 0x24, 0x2A, 0x16, 0x00, 0x2C, 0xD2, 0x10, 0x00, 0xCC, 0xAA, 0x16, 0x00, 0x2D, 0x0C, 0x00, 0x00, ++0x06, 0x04, 0x00, 0x00, 0x1D, 0x04, 0x00, 0x00, 0xF0, 0xAA, 0x16, 0x00, 0x7C, 0x0C, 0x00, 0x00, 0x7A, 0x0C, 0x00, 0x00, ++0x05, 0x14, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0x57, 0xFD, 0x00, 0x00, 0x05, 0x11, 0x00, 0x00, 0x14, 0xD2, 0x10, 0x00, ++0x20, 0xD2, 0x10, 0x00, 0x7D, 0x4A, 0x0D, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0x08, 0xD2, 0x10, 0x00, 0x10, 0xB5, 0x07, 0x20, ++0x7B, 0xF7, 0x10, 0xFA, 0x08, 0x4C, 0xA1, 0x7A, 0x20, 0x89, 0x62, 0x68, 0xFF, 0xF7, 0x54, 0xFE, 0x60, 0x68, 0x00, 0x28, ++0x03, 0xD0, 0x7A, 0xF7, 0x7F, 0xFE, 0x00, 0x22, 0x62, 0x60, 0x02, 0x48, 0x02, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0xC0, 0x46, ++0x58, 0x1E, 0x16, 0x00, 0xA5, 0x73, 0x08, 0x00, 0x30, 0xB5, 0x0C, 0x4C, 0x25, 0x68, 0x29, 0x60, 0x24, 0x68, 0x60, 0x60, ++0xA2, 0x60, 0xE3, 0x60, 0x09, 0x4B, 0x0A, 0x4A, 0x98, 0x50, 0x0A, 0x48, 0x1A, 0x58, 0x0A, 0x43, 0x1A, 0x50, 0x04, 0x30, ++0x1A, 0x58, 0x11, 0x43, 0x19, 0x50, 0x07, 0x49, 0x5A, 0x58, 0x01, 0x20, 0x02, 0x43, 0x5A, 0x50, 0x30, 0xBD, 0xC0, 0x46, ++0xFC, 0xE1, 0x10, 0x00, 0x00, 0x00, 0x07, 0x40, 0x10, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, ++0x70, 0xB5, 0x0D, 0x00, 0x1A, 0x4C, 0x30, 0x21, 0x61, 0x5C, 0x01, 0x29, 0x04, 0xD0, 0x29, 0x00, 0x18, 0x4C, 0xA0, 0x47, ++0x00, 0x20, 0x70, 0xBD, 0x14, 0x0A, 0x84, 0xF7, 0x99, 0xFD, 0x06, 0x1E, 0x1F, 0xD0, 0x6A, 0x88, 0xA9, 0x88, 0x14, 0x4B, ++0x9C, 0x46, 0x61, 0x44, 0x00, 0x89, 0x60, 0x44, 0xD1, 0xF7, 0xB8, 0xFB, 0x08, 0x23, 0x00, 0x22, 0x21, 0x00, 0x10, 0x48, ++0x7A, 0xF7, 0xBA, 0xFC, 0x33, 0x89, 0x43, 0x60, 0x2B, 0x88, 0x03, 0x80, 0x6B, 0x88, 0x43, 0x80, 0xCC, 0xF7, 0x12, 0xFB, ++0x20, 0x00, 0x80, 0x30, 0x01, 0x21, 0x0A, 0x4B, 0x98, 0x47, 0xA8, 0x88, 0x84, 0xF7, 0xCA, 0xFD, 0xD8, 0xE7, 0x08, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEF, 0xE7, 0x68, 0x9E, 0x16, 0x00, 0x49, 0x86, 0x0A, 0x00, ++0x00, 0x00, 0x61, 0x40, 0x06, 0x11, 0x00, 0x00, 0xC1, 0xDC, 0x09, 0x00, 0x28, 0x19, 0x16, 0x00, 0x42, 0x7A, 0x12, 0x02, ++0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x83, 0x7A, 0x8B, 0x70, 0x70, 0x47, 0xC2, 0x7A, 0x12, 0x02, 0x83, 0x7A, 0x13, 0x43, ++0x4B, 0x80, 0x42, 0x7A, 0x12, 0x02, 0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x70, 0x47, 0x83, 0x7A, 0x8B, 0x70, 0x42, 0x7A, ++0x12, 0x02, 0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x70, 0x47, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x00, 0x22, 0x02, 0x73, ++0x0B, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x03, 0x4A, 0x01, 0x21, 0xA0, 0x47, 0x04, 0x20, 0x7A, 0xF7, 0x91, 0xF8, 0x10, 0xBD, ++0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x01, 0x22, 0x02, 0x73, 0x08, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x03, 0x4A, ++0xA0, 0x47, 0x04, 0x20, 0x79, 0xF7, 0xAC, 0xFB, 0x10, 0xBD, 0xC0, 0x46, 0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, ++0x02, 0x22, 0x02, 0x73, 0x40, 0x68, 0x1A, 0x68, 0x14, 0x68, 0x01, 0x4A, 0xA0, 0x47, 0x10, 0xBD, 0x59, 0x78, 0x10, 0x00, ++0x10, 0xB5, 0x03, 0x00, 0x03, 0x22, 0x02, 0x73, 0x0B, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x02, 0x4A, 0x01, 0x21, 0xA0, 0x47, ++0x10, 0xBD, 0xC0, 0x46, 0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x01, 0x23, 0x10, 0x22, 0x00, 0x21, 0x0B, 0x48, ++0x7A, 0xF7, 0x38, 0xFC, 0x00, 0x23, 0x03, 0x70, 0xCC, 0xF7, 0x94, 0xFA, 0x20, 0x00, 0x08, 0x30, 0x02, 0x22, 0x00, 0x21, ++0x78, 0xF7, 0xB2, 0xFC, 0xE3, 0x7A, 0xA3, 0x72, 0x20, 0x00, 0xFF, 0xF7, 0xDB, 0xFF, 0x04, 0x20, 0x7A, 0xF7, 0x4A, 0xF8, ++0x10, 0xBD, 0xC0, 0x46, 0x03, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x06, 0x20, 0x7B, 0xF7, 0x1A, 0xF9, 0x16, 0x4C, 0x17, 0x49, ++0x20, 0x00, 0xFF, 0xF7, 0x83, 0xFF, 0xA4, 0x7A, 0x00, 0x2C, 0x09, 0xD1, 0x12, 0x4C, 0x20, 0x89, 0x00, 0x22, 0x00, 0x21, ++0xFF, 0xF7, 0x56, 0xFD, 0x20, 0x00, 0xFF, 0xF7, 0x93, 0xFF, 0x10, 0xBD, 0x0D, 0x4B, 0x18, 0x89, 0xCD, 0xF7, 0x9C, 0xFA, ++0x84, 0x42, 0x03, 0xD9, 0x0A, 0x48, 0xFF, 0xF7, 0xC3, 0xFF, 0xF4, 0xE7, 0x08, 0x4C, 0xA0, 0x7A, 0x01, 0x21, 0x7A, 0xF7, ++0xCF, 0xFC, 0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0x20, 0x00, 0xA1, 0x7A, 0xFF, 0xF7, 0x9C, 0xFF, 0xE7, 0xE7, 0x02, 0x48, ++0xFF, 0xF7, 0xB2, 0xFF, 0xE3, 0xE7, 0xC0, 0x46, 0x58, 0x1E, 0x16, 0x00, 0x60, 0x1E, 0x16, 0x00, 0x10, 0xB5, 0x82, 0xB0, ++0x04, 0x00, 0x0E, 0x4B, 0x01, 0x93, 0x01, 0x00, 0x08, 0x31, 0x04, 0x22, 0x01, 0xA8, 0xD1, 0xF7, 0xB5, 0xFA, 0x00, 0x28, ++0x0B, 0xD0, 0x04, 0x20, 0x79, 0xF7, 0x2A, 0xFB, 0x63, 0x7A, 0x23, 0x72, 0xA3, 0x7A, 0x63, 0x72, 0xE3, 0x7A, 0xA3, 0x72, ++0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0x22, 0x00, 0x21, 0x03, 0x48, 0xCD, 0xF7, 0x6C, 0xFA, 0x01, 0x20, 0xF6, 0xE7, ++0x01, 0x03, 0x0C, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x00, 0x29, 0x0B, 0xD0, 0x01, 0x29, 0x02, 0xD0, ++0x03, 0x7B, 0x00, 0x2B, 0x03, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x7C, 0xFF, 0x10, 0xBD, 0xFF, 0xF7, 0x3F, 0xFF, 0xFB, 0xE7, ++0x03, 0x7B, 0x02, 0x2B, 0x44, 0xD0, 0x0F, 0xD8, 0x00, 0x2B, 0x17, 0xD0, 0x40, 0x7B, 0x02, 0x28, 0x25, 0xD0, 0x03, 0x28, ++0x27, 0xD0, 0x01, 0x28, 0x1D, 0xD0, 0xA1, 0x7B, 0x34, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA0, 0x47, 0xE7, 0xE7, ++0x03, 0x2B, 0x59, 0xD1, 0xFF, 0xF7, 0xB4, 0xFF, 0x00, 0x28, 0x51, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x21, 0xFF, 0xDD, 0xE7, ++0xC3, 0x7A, 0x43, 0x73, 0x5A, 0x1E, 0x02, 0x2A, 0x04, 0xD8, 0x2B, 0x4A, 0xD1, 0x5C, 0xFF, 0xF7, 0x27, 0xFF, 0xD3, 0xE7, ++0xFF, 0xF7, 0x4E, 0xFF, 0xD0, 0xE7, 0x05, 0x30, 0x7B, 0xF7, 0x5E, 0xF8, 0xCC, 0xE7, 0x08, 0x20, 0x7B, 0xF7, 0x5A, 0xF8, ++0xC8, 0xE7, 0x21, 0x00, 0x08, 0x31, 0x20, 0x00, 0xFF, 0xF7, 0xFD, 0xFE, 0xA1, 0x7A, 0x20, 0x89, 0xCD, 0xF7, 0x2E, 0xFC, ++0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0xA1, 0x7A, 0x20, 0x00, 0xFF, 0xF7, 0x1B, 0xFF, 0xB7, 0xE7, 0x20, 0x00, 0xFF, 0xF7, ++0x31, 0xFF, 0xB3, 0xE7, 0x40, 0x7B, 0x02, 0x28, 0x0E, 0xD0, 0x03, 0x28, 0x15, 0xD0, 0x01, 0x28, 0x06, 0xD0, 0xA1, 0x7B, ++0x13, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA0, 0x47, 0xA5, 0xE7, 0x06, 0x30, 0x7B, 0xF7, 0x33, 0xF8, 0xA1, 0xE7, ++0x61, 0x89, 0x20, 0x89, 0x62, 0x68, 0xCD, 0xF7, 0xB9, 0xFB, 0x20, 0x00, 0xFF, 0xF7, 0xDC, 0xFE, 0x98, 0xE7, 0xA1, 0x7A, ++0x20, 0x89, 0x62, 0x68, 0xCD, 0xF7, 0x2E, 0xFC, 0x20, 0x00, 0xFF, 0xF7, 0xD3, 0xFE, 0x8F, 0xE7, 0x20, 0x00, 0xFF, 0xF7, ++0xFB, 0xFE, 0x8B, 0xE7, 0x03, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x84, 0xE7, 0xC0, 0x46, ++0x28, 0x19, 0x16, 0x00, 0xC8, 0xDF, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, 0x03, 0x05, 0x1B, 0x0D, 0x82, 0x0B, 0x0B, 0x2B, ++0x1C, 0xD8, 0x00, 0x2A, 0x4C, 0xD1, 0x19, 0x02, 0x04, 0x22, 0x0A, 0x43, 0x92, 0xB2, 0xF8, 0x21, 0x09, 0x01, 0x08, 0x42, ++0x1F, 0xD1, 0xFB, 0x21, 0xFF, 0x2A, 0x46, 0xD0, 0x8C, 0x42, 0x44, 0xD8, 0xFF, 0x23, 0x13, 0x40, 0x02, 0x2B, 0x26, 0xD9, ++0x04, 0x2B, 0x26, 0xD1, 0xB3, 0xF7, 0x8A, 0xFC, 0x00, 0x28, 0x3A, 0xD0, 0x25, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x46, 0xE0, ++0x01, 0x2A, 0x31, 0xD0, 0x00, 0x2A, 0x32, 0xD1, 0xF8, 0x22, 0x12, 0x01, 0x10, 0x42, 0x2E, 0xD0, 0x00, 0x21, 0xFF, 0x22, ++0x86, 0x2B, 0xE1, 0xD8, 0x00, 0xE0, 0xFB, 0x21, 0x80, 0x3B, 0xDD, 0x00, 0xED, 0x1A, 0x1C, 0x48, 0x40, 0x19, 0x24, 0x30, ++0x00, 0x78, 0x02, 0x28, 0xD6, 0xD1, 0x1B, 0x02, 0x01, 0x22, 0x1A, 0x43, 0x92, 0xB2, 0x18, 0x49, 0xD2, 0xE7, 0x00, 0x2B, ++0x06, 0xD1, 0x17, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x10, 0xE0, 0x84, 0xF7, 0xE0, 0xFB, ++0x00, 0x28, 0x03, 0xD0, 0x0E, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x18, 0xE0, 0x10, 0x48, 0x7C, 0xF7, 0xEB, 0xFB, 0x04, 0xE0, ++0x01, 0x2A, 0x02, 0xD1, 0x0B, 0x4B, 0x9C, 0x42, 0xEE, 0xD9, 0x01, 0x23, 0x1A, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x7A, 0xF7, ++0xDB, 0xFA, 0x01, 0x25, 0x05, 0x70, 0xCC, 0xF7, 0x37, 0xF9, 0x01, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0xA5, 0xFB, 0x07, 0x4B, ++0x9D, 0x77, 0x70, 0xBD, 0x00, 0x00, 0x61, 0x40, 0xCC, 0xAA, 0x16, 0x00, 0xFD, 0x03, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x50, 0xD2, 0x10, 0x00, 0x03, 0x11, 0x00, 0x00, 0x24, 0x2A, 0x16, 0x00, 0x10, 0xB5, 0x08, 0x20, 0x7A, 0xF7, 0xBA, 0xFF, ++0x10, 0x4C, 0x11, 0x49, 0x20, 0x00, 0xFF, 0xF7, 0x2B, 0xFE, 0x61, 0x89, 0x00, 0x29, 0x0E, 0xD0, 0x20, 0x89, 0xFF, 0xF7, ++0x77, 0xFF, 0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0x09, 0x48, 0x41, 0x89, 0xFF, 0xF7, 0x52, 0xFE, 0x0C, 0xE0, 0x20, 0x00, ++0xFF, 0xF7, 0x68, 0xFE, 0x08, 0xE0, 0x05, 0x4C, 0x20, 0x89, 0x00, 0x22, 0x00, 0x21, 0xCD, 0xF7, 0x01, 0xFB, 0x20, 0x00, ++0xFF, 0xF7, 0x24, 0xFE, 0x10, 0xBD, 0xC0, 0x46, 0x58, 0x1E, 0x16, 0x00, 0x60, 0x1E, 0x16, 0x00, 0x10, 0xB5, 0x7F, 0xF7, ++0xBD, 0xFD, 0x06, 0x49, 0x06, 0x20, 0x7A, 0xF7, 0x47, 0xFF, 0x05, 0x49, 0x07, 0x20, 0x7A, 0xF7, 0x43, 0xFF, 0x04, 0x49, ++0x08, 0x20, 0x7A, 0xF7, 0x3F, 0xFF, 0x10, 0xBD, 0xA5, 0x77, 0x10, 0x00, 0xB9, 0x75, 0x10, 0x00, 0x65, 0x7A, 0x10, 0x00, ++0x10, 0xB5, 0x0A, 0x00, 0x41, 0x23, 0x00, 0x21, 0x0C, 0x48, 0x7A, 0xF7, 0x7B, 0xFA, 0x04, 0x00, 0x01, 0x30, 0x28, 0x22, ++0x0A, 0x49, 0xD1, 0xF7, 0x6D, 0xF9, 0xE2, 0x79, 0x2F, 0x23, 0x13, 0x40, 0xE3, 0x71, 0x20, 0x00, 0x29, 0x30, 0x18, 0x22, ++0x00, 0x21, 0x78, 0xF7, 0xEF, 0xFA, 0x00, 0x23, 0x23, 0x70, 0x20, 0x00, 0xCC, 0xF7, 0xC6, 0xF8, 0x00, 0x20, 0x10, 0xBD, ++0x01, 0x11, 0x00, 0x00, 0xA4, 0xB5, 0x0D, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x0D, 0x00, 0x90, 0x46, 0x06, 0x0A, ++0xB2, 0x00, 0x11, 0x4B, 0xD7, 0x58, 0x0C, 0x23, 0x03, 0x22, 0x00, 0x21, 0x0F, 0x48, 0x7A, 0xF7, 0x51, 0xFA, 0x04, 0x00, ++0x43, 0x46, 0x03, 0x70, 0x2D, 0x02, 0x81, 0x35, 0xFF, 0x35, 0x75, 0x19, 0x45, 0x80, 0x00, 0x23, 0x83, 0x72, 0x88, 0x23, ++0xFF, 0x33, 0xFB, 0x5C, 0xC3, 0x72, 0x39, 0x00, 0x72, 0x31, 0x04, 0x30, 0x06, 0x22, 0xD1, 0xF7, 0x35, 0xF9, 0x20, 0x00, ++0xCC, 0xF7, 0x9A, 0xF8, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, ++0x70, 0xB5, 0x05, 0x00, 0x0E, 0x00, 0x04, 0x78, 0x02, 0x2C, 0x21, 0xD8, 0x00, 0x2C, 0x04, 0xD1, 0x14, 0x4A, 0x30, 0x23, ++0x00, 0x21, 0xD1, 0x54, 0x1B, 0xE0, 0x03, 0x20, 0x88, 0xF7, 0x2E, 0xFC, 0x04, 0x1E, 0x1C, 0xD1, 0x2B, 0x78, 0x0F, 0x49, ++0x30, 0x22, 0x8B, 0x54, 0x01, 0x2B, 0x10, 0xD1, 0xDF, 0x20, 0x00, 0x21, 0x80, 0x00, 0x7A, 0xF7, 0xE7, 0xFA, 0x0B, 0x4B, ++0x18, 0x60, 0x0B, 0x4A, 0x24, 0x23, 0x01, 0x21, 0xD1, 0x54, 0x00, 0x21, 0x00, 0x20, 0x92, 0xF7, 0xA1, 0xF8, 0x00, 0xE0, ++0x12, 0x24, 0x21, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x3B, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x0C, 0x24, 0xF7, 0xE7, 0xC0, 0x46, ++0x68, 0x9E, 0x16, 0x00, 0x64, 0xA2, 0x16, 0x00, 0xCC, 0xAA, 0x16, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0F, 0x4B, ++0x5B, 0x68, 0x02, 0x00, 0x06, 0x21, 0x01, 0x20, 0x98, 0x47, 0x20, 0x78, 0x63, 0x78, 0x1B, 0x02, 0x03, 0x43, 0xA0, 0x78, ++0x00, 0x04, 0x03, 0x43, 0xE0, 0x78, 0x00, 0x06, 0x18, 0x43, 0x23, 0x79, 0x61, 0x79, 0x09, 0x02, 0x19, 0x43, 0xA4, 0xF7, ++0xFF, 0xF8, 0x20, 0x00, 0xB3, 0xF7, 0x3C, 0xFF, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x10, 0xFA, 0x00, 0x20, 0x70, 0xBD, ++0x94, 0x92, 0x16, 0x00, 0x10, 0x4A, 0xFF, 0x21, 0x13, 0x68, 0x8B, 0x43, 0x0F, 0x48, 0x00, 0x78, 0x03, 0x43, 0x80, 0x20, ++0x03, 0x43, 0x0E, 0x48, 0x03, 0x60, 0x0E, 0x4B, 0x1B, 0x78, 0x1B, 0x01, 0x0B, 0x40, 0xD0, 0x68, 0x88, 0x43, 0x03, 0x43, ++0x0B, 0x49, 0x0B, 0x60, 0x0B, 0x4B, 0x00, 0x21, 0x19, 0x60, 0x13, 0x69, 0x0A, 0x4A, 0x13, 0x40, 0x0A, 0x4A, 0x13, 0x60, ++0x0A, 0x4B, 0x0B, 0x4A, 0x1A, 0x60, 0x0B, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xE4, 0xE6, 0x10, 0x00, 0x14, 0xE7, 0x10, 0x00, ++0x08, 0x01, 0x60, 0x40, 0xF7, 0xE8, 0x10, 0x00, 0x28, 0x10, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, 0xFF, 0x0F, 0xF0, 0xFF, ++0x34, 0x08, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, 0x00, 0x01, 0x0A, 0x01, 0x00, 0x01, 0x0F, 0x01, 0x0B, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x11, 0xD1, 0x0A, 0x4B, 0x1B, 0x68, 0x03, 0x60, 0x0A, 0x4B, 0x1B, 0x68, 0x43, 0x60, 0x09, 0x4B, 0x1B, 0x68, ++0x83, 0x60, 0x09, 0x4B, 0x1B, 0x68, 0xC3, 0x60, 0x08, 0x4B, 0x1B, 0x68, 0x03, 0x61, 0x02, 0x4B, 0x01, 0x22, 0x1A, 0x70, ++0x70, 0x47, 0xC0, 0x46, 0xD3, 0xE6, 0x10, 0x00, 0x08, 0x01, 0x60, 0x40, 0x00, 0x00, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, ++0x28, 0x10, 0x62, 0x40, 0x34, 0x08, 0x62, 0x40, 0x09, 0x4B, 0x02, 0x68, 0x1A, 0x60, 0x09, 0x4B, 0x42, 0x68, 0x1A, 0x60, ++0x08, 0x4B, 0x82, 0x68, 0x1A, 0x60, 0x08, 0x4B, 0xC2, 0x68, 0x1A, 0x60, 0x02, 0x69, 0x07, 0x4B, 0x1A, 0x60, 0x07, 0x4B, ++0x00, 0x22, 0x1A, 0x70, 0x70, 0x47, 0xC0, 0x46, 0x08, 0x01, 0x60, 0x40, 0x00, 0x00, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, ++0x28, 0x10, 0x62, 0x40, 0x34, 0x08, 0x62, 0x40, 0xD3, 0xE6, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x03, 0x78, ++0x00, 0x2B, 0x17, 0xD0, 0x02, 0x20, 0xF9, 0xF7, 0x8D, 0xFD, 0x0E, 0x48, 0xFF, 0xF7, 0xB0, 0xFF, 0x62, 0x78, 0x0D, 0x4B, ++0x1A, 0x70, 0xA2, 0x78, 0x0C, 0x4B, 0x1A, 0x70, 0xFF, 0xF7, 0x70, 0xFF, 0x21, 0x78, 0x0B, 0x48, 0x7C, 0xF7, 0x46, 0xFA, ++0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x82, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0x03, 0x48, 0xFF, 0xF7, 0xBF, 0xFF, 0x01, 0x20, ++0xF9, 0xF7, 0x72, 0xFD, 0xEE, 0xE7, 0xC0, 0x46, 0xE4, 0xE6, 0x10, 0x00, 0x14, 0xE7, 0x10, 0x00, 0xF7, 0xE8, 0x10, 0x00, ++0x5C, 0xD2, 0x10, 0x00, 0x00, 0x23, 0x03, 0x73, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x88, ++0x12, 0x21, 0x15, 0x2B, 0x04, 0xD9, 0x04, 0x4B, 0x80, 0x22, 0xD2, 0x01, 0x9A, 0x82, 0x00, 0x21, 0xFF, 0xF7, 0x50, 0xF9, ++0x00, 0x20, 0x10, 0xBD, 0x68, 0x9E, 0x16, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0F, 0x4B, 0x1B, 0x68, 0x02, 0x2B, ++0x0B, 0xD0, 0x29, 0x00, 0x20, 0x00, 0x0D, 0x4B, 0x98, 0x47, 0x0D, 0x4B, 0x80, 0x22, 0x12, 0x01, 0x1A, 0x83, 0x12, 0x22, ++0x5A, 0x83, 0x00, 0x20, 0x70, 0xBD, 0xFA, 0xF7, 0x09, 0xFC, 0x00, 0x28, 0xEF, 0xD1, 0x23, 0x78, 0x9B, 0x07, 0xEC, 0xD5, ++0x05, 0x4B, 0x80, 0x22, 0x92, 0x00, 0x1A, 0x83, 0xEF, 0x3A, 0xFF, 0x3A, 0x5A, 0x83, 0xE4, 0xE7, 0x50, 0xE0, 0x10, 0x00, ++0x15, 0x28, 0x09, 0x00, 0x68, 0x9E, 0x16, 0x00, 0x70, 0xB5, 0x0C, 0x00, 0x0B, 0x4A, 0x8C, 0x23, 0xD3, 0x5C, 0x0C, 0x25, ++0x01, 0x2B, 0x05, 0xD0, 0x29, 0x00, 0x20, 0x00, 0xFF, 0xF7, 0x18, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xA4, 0xF7, 0xB8, 0xFC, ++0x05, 0x1E, 0xF5, 0xD0, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEE, 0xE7, 0xC0, 0x46, ++0x68, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x78, 0x01, 0x21, 0x99, 0x42, ++0x9B, 0x41, 0x11, 0x31, 0x19, 0x40, 0xFF, 0xF7, 0xFB, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0x70, 0xB5, 0x05, 0x00, ++0x08, 0x00, 0x1C, 0x00, 0x47, 0x4B, 0x9C, 0x42, 0x43, 0xD0, 0x23, 0xD8, 0x46, 0x4B, 0x9C, 0x42, 0x51, 0xD0, 0x13, 0xD8, ++0x45, 0x4B, 0x9C, 0x42, 0x45, 0xD0, 0x45, 0x4B, 0x9C, 0x42, 0x04, 0xD1, 0x43, 0x49, 0xFF, 0xF7, 0x43, 0xF9, 0x00, 0x25, ++0x6A, 0xE0, 0x42, 0x4B, 0x9C, 0x42, 0x00, 0xD0, 0x70, 0xE0, 0x40, 0x49, 0xFF, 0xF7, 0xB6, 0xFF, 0x00, 0x25, 0x61, 0xE0, ++0x3E, 0x4B, 0x9C, 0x42, 0x3E, 0xD0, 0x3E, 0x4B, 0x9C, 0x42, 0x65, 0xD1, 0x3C, 0x49, 0x00, 0x20, 0xFF, 0xF7, 0x16, 0xFE, ++0x00, 0x25, 0x55, 0xE0, 0x3A, 0x4B, 0x9C, 0x42, 0x20, 0xD0, 0x0A, 0xD9, 0x39, 0x4B, 0x9C, 0x42, 0x12, 0xD0, 0x39, 0x4B, ++0x9C, 0x42, 0x55, 0xD1, 0x19, 0x00, 0xFF, 0xF7, 0xDB, 0xF8, 0x00, 0x25, 0x46, 0xE0, 0x36, 0x4B, 0x9C, 0x42, 0x28, 0xD0, ++0x35, 0x4B, 0x9C, 0x42, 0x2A, 0xD1, 0x34, 0x49, 0xFF, 0xF7, 0x84, 0xFE, 0x00, 0x25, 0x3B, 0xE0, 0x2E, 0x49, 0xFF, 0xF7, ++0x01, 0xF9, 0x00, 0x25, 0x36, 0xE0, 0x24, 0x49, 0xFF, 0xF7, 0x42, 0xFE, 0x00, 0x25, 0x31, 0xE0, 0x28, 0x49, 0xFF, 0xF7, ++0x15, 0xFF, 0x00, 0x25, 0x2C, 0xE0, 0x00, 0x23, 0x0B, 0x73, 0x20, 0x4B, 0x28, 0x00, 0x29, 0x4D, 0xA8, 0x47, 0x05, 0x00, ++0x24, 0xE0, 0x1C, 0x49, 0xFF, 0xF7, 0x3A, 0xFF, 0x00, 0x25, 0x1F, 0xE0, 0x1D, 0x49, 0xFF, 0xF7, 0x47, 0xFF, 0x00, 0x25, ++0x1A, 0xE0, 0x20, 0x49, 0xFF, 0xF7, 0x88, 0xFF, 0x00, 0x25, 0x15, 0xE0, 0x23, 0x00, 0x28, 0x00, 0x1E, 0x4D, 0xA8, 0x47, ++0x05, 0x00, 0x1E, 0x4B, 0x9C, 0x42, 0x05, 0xD0, 0x1D, 0x4B, 0x08, 0x22, 0x21, 0x00, 0x91, 0x43, 0x99, 0x42, 0x04, 0xD1, ++0x02, 0x20, 0xF9, 0xF7, 0x81, 0xFC, 0xFA, 0xF7, 0x63, 0xF9, 0x19, 0x4B, 0x9C, 0x42, 0x05, 0xD0, 0x21, 0x00, 0x18, 0x48, ++0x7C, 0xF7, 0x40, 0xF9, 0x28, 0x00, 0x70, 0xBD, 0x01, 0x20, 0xF9, 0xF7, 0x73, 0xFC, 0xF5, 0xE7, 0x23, 0x00, 0x01, 0x00, ++0x28, 0x00, 0x0E, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xE0, 0xE7, 0xC0, 0x46, 0x02, 0x18, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, ++0x05, 0x04, 0x00, 0x00, 0x13, 0x0C, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x1A, 0x0C, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, ++0xC6, 0xFC, 0x00, 0x00, 0xC7, 0xFC, 0x00, 0x00, 0xC9, 0xFC, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x70, 0xFC, 0x00, 0x00, ++0x1D, 0x0C, 0x09, 0x00, 0x06, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x0C, 0x18, 0x00, 0x00, 0x6C, 0xD2, 0x10, 0x00, ++0x70, 0xB5, 0x0D, 0x00, 0x14, 0x00, 0x04, 0x23, 0x02, 0x00, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0x03, 0xF8, 0x05, 0x70, ++0x44, 0x80, 0xCB, 0xF7, 0x5F, 0xFE, 0x70, 0xBD, 0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x10, 0x00, 0x1A, 0x88, ++0x0C, 0x21, 0xFF, 0xF7, 0xE9, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x80, 0x46, 0x0C, 0x00, 0x91, 0x46, 0x0F, 0x0A, 0xBA, 0x00, 0x2E, 0x4B, 0xD5, 0x58, ++0x08, 0x00, 0x7A, 0xF7, 0xB7, 0xFB, 0x02, 0x26, 0x00, 0x28, 0x19, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x4F, 0xD0, ++0x3C, 0x23, 0xEE, 0x5C, 0x02, 0x2E, 0x03, 0xD1, 0x43, 0x46, 0x5B, 0x88, 0x00, 0x2B, 0x1B, 0xD1, 0xFA, 0x21, 0x49, 0x01, ++0xA9, 0x83, 0xFF, 0xB2, 0x36, 0x23, 0xEA, 0x5C, 0x38, 0x00, 0xA1, 0xF7, 0x6D, 0xFE, 0xA9, 0x8B, 0x38, 0x00, 0xAB, 0xF7, ++0x31, 0xFC, 0x00, 0x26, 0x43, 0x46, 0x1A, 0x88, 0x31, 0x00, 0x48, 0x46, 0xFF, 0xF7, 0xB2, 0xFF, 0x00, 0x20, 0x03, 0xB0, ++0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xFB, 0xB2, 0x9B, 0x46, 0x06, 0x23, 0x6B, 0x44, ++0x9A, 0x46, 0x6B, 0x46, 0x5A, 0x1D, 0x51, 0x46, 0x58, 0x46, 0x8B, 0xF7, 0x65, 0xFE, 0x43, 0x46, 0x5A, 0x88, 0x53, 0x46, ++0x19, 0x88, 0x8A, 0x42, 0x13, 0xD9, 0x6B, 0x46, 0x05, 0x33, 0x1B, 0x78, 0x00, 0x2B, 0xCD, 0xD0, 0x4B, 0x43, 0x9A, 0x42, ++0xCA, 0xD8, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0x58, 0x46, 0xAB, 0xF7, 0x73, 0xFA, 0x22, 0x00, 0x21, 0x00, 0x07, 0x48, ++0x79, 0xF7, 0xD2, 0xFF, 0xBE, 0xE7, 0x43, 0x46, 0x1A, 0x88, 0x12, 0x21, 0x48, 0x46, 0xFF, 0xF7, 0x7F, 0xFF, 0xC5, 0xE7, ++0x0C, 0x26, 0xC3, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x22, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0x93, 0xB0, 0x01, 0x90, 0x0C, 0x00, ++0x16, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x37, 0x4B, 0xD5, 0x58, 0x08, 0x00, 0x7A, 0xF7, 0x4E, 0xFB, 0x04, 0x28, 0x06, 0xD0, ++0x09, 0x28, 0x18, 0xD0, 0x0C, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x42, 0xFB, 0x10, 0xE0, 0x3C, 0x22, 0x30, 0x49, 0x03, 0xA8, ++0xD0, 0xF7, 0x62, 0xFE, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x38, 0xFB, 0x2D, 0x4A, 0xE8, 0x23, 0xD5, 0x58, 0x03, 0xAB, ++0x01, 0x22, 0x01, 0x21, 0x20, 0x00, 0xA8, 0x47, 0x00, 0x20, 0x13, 0xB0, 0xF0, 0xBD, 0x21, 0x00, 0x28, 0x48, 0x79, 0xF7, ++0x0F, 0xFF, 0x01, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0xC9, 0xFA, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x21, 0xFB, 0xBC, 0x23, ++0x5B, 0x00, 0xEB, 0x5C, 0xDB, 0x43, 0x9B, 0x07, 0x21, 0xD1, 0x00, 0x23, 0x01, 0x9A, 0x93, 0x71, 0xFF, 0xB2, 0x29, 0x00, ++0x38, 0x31, 0x38, 0x00, 0x88, 0xF7, 0x70, 0xF9, 0x00, 0x28, 0x1C, 0xD0, 0x1B, 0x48, 0x7C, 0xF7, 0x3F, 0xF8, 0x01, 0x23, ++0xAF, 0x22, 0x92, 0x00, 0xAB, 0x54, 0x43, 0x22, 0xAB, 0x54, 0x20, 0x00, 0x93, 0xF7, 0xA0, 0xF9, 0x88, 0xF7, 0x64, 0xFA, ++0x00, 0x28, 0x19, 0xD1, 0xC4, 0x20, 0x22, 0x00, 0x21, 0x00, 0xC0, 0x00, 0x79, 0xF7, 0x68, 0xFF, 0xC8, 0xE7, 0x22, 0x00, ++0x21, 0x00, 0x10, 0x48, 0x79, 0xF7, 0x62, 0xFF, 0xD7, 0xE7, 0x0F, 0x48, 0x7C, 0xF7, 0x22, 0xF8, 0x44, 0x23, 0x01, 0x22, ++0xEA, 0x54, 0x0B, 0x3B, 0xEA, 0x5C, 0x33, 0x21, 0x38, 0x00, 0xA1, 0xF7, 0x39, 0xFC, 0xE1, 0xE7, 0x22, 0x00, 0x21, 0x00, ++0x08, 0x48, 0x79, 0xF7, 0x4F, 0xFF, 0xDF, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x80, 0xD6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x06, 0x06, 0x00, 0x00, 0x74, 0xD2, 0x10, 0x00, 0x14, 0x06, 0x00, 0x00, 0x7C, 0xD2, 0x10, 0x00, 0x1D, 0x06, 0x00, 0x00, ++0x70, 0xB5, 0x04, 0x00, 0x0E, 0x00, 0x15, 0x00, 0x41, 0x88, 0x80, 0x23, 0x1B, 0x01, 0x99, 0x42, 0x06, 0xD3, 0x22, 0x88, ++0x0C, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0xE4, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x03, 0x48, 0x7B, 0xF7, 0xEF, 0xFF, 0x30, 0x0A, ++0x00, 0x21, 0xAB, 0xF7, 0xA7, 0xF8, 0xF0, 0xE7, 0x84, 0xD2, 0x10, 0x00, 0x70, 0xB5, 0x0E, 0x00, 0x15, 0x00, 0x07, 0x23, ++0x02, 0x00, 0x00, 0x21, 0x06, 0x48, 0x79, 0xF7, 0xDB, 0xFE, 0x04, 0x00, 0x06, 0x70, 0x01, 0x30, 0x06, 0x22, 0x29, 0x00, ++0xD0, 0xF7, 0xCC, 0xFD, 0x20, 0x00, 0xCB, 0xF7, 0x31, 0xFD, 0x70, 0xBD, 0x01, 0x11, 0x00, 0x00, 0xF0, 0xB5, 0x83, 0xB0, ++0x01, 0x90, 0x0D, 0x00, 0x16, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x22, 0x4B, 0xD4, 0x58, 0x08, 0x00, 0x7A, 0xF7, 0x98, 0xFA, ++0x00, 0x28, 0x1A, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x16, 0xD9, 0x88, 0x23, 0xFF, 0x33, 0xE3, 0x5C, 0x00, 0x2B, ++0x03, 0xD1, 0x36, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x14, 0xD0, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x81, 0xFA, 0x36, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x11, 0xD1, 0x2A, 0x00, 0x29, 0x00, 0x14, 0x48, 0x79, 0xF7, 0xE6, 0xFE, 0x03, 0xE0, 0x02, 0x21, ++0x30, 0x00, 0x91, 0xF7, 0x73, 0xFA, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x0C, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x6C, 0xFA, ++0xF7, 0xE7, 0x06, 0x23, 0x1C, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x79, 0xF7, 0x93, 0xFE, 0x05, 0x00, 0x00, 0x23, 0x03, 0x70, ++0x01, 0x9B, 0x1B, 0x88, 0x43, 0x80, 0xF8, 0xB2, 0xAB, 0xF7, 0x32, 0xFA, 0xC0, 0x03, 0x40, 0x0C, 0xA8, 0x80, 0x28, 0x00, ++0xCB, 0xF7, 0xE4, 0xFC, 0xE1, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x16, 0x06, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, ++0xF0, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x16, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x31, 0x4A, 0x9F, 0x58, 0x08, 0x00, ++0x7A, 0xF7, 0x46, 0xFA, 0x00, 0x28, 0x53, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x02, 0x24, 0x03, 0x28, 0x4F, 0xD9, 0x01, 0x99, ++0x4B, 0x88, 0xA8, 0x22, 0xD2, 0x00, 0x10, 0x34, 0x93, 0x42, 0x48, 0xD8, 0xDA, 0x07, 0x46, 0xD4, 0x8A, 0x88, 0x05, 0x2A, ++0x43, 0xD9, 0xD0, 0x07, 0x41, 0xD4, 0x08, 0x00, 0xC9, 0x88, 0x00, 0x29, 0x3D, 0xD0, 0x00, 0x89, 0x84, 0x46, 0x28, 0x28, ++0x39, 0xD8, 0x58, 0x08, 0x81, 0x42, 0x36, 0xD8, 0x93, 0x42, 0x34, 0xD3, 0x61, 0x44, 0x49, 0x00, 0x99, 0x42, 0x30, 0xD2, ++0x7B, 0x8C, 0x06, 0x3C, 0x5B, 0x07, 0x2C, 0xD5, 0x3C, 0x23, 0xFC, 0x5C, 0x00, 0x2C, 0x01, 0xD0, 0x0C, 0x24, 0x26, 0xE0, ++0x38, 0x00, 0x54, 0x30, 0x07, 0x21, 0xA1, 0xF7, 0x47, 0xFA, 0x00, 0x28, 0x01, 0xD1, 0x1A, 0x24, 0x1D, 0xE0, 0x08, 0x23, ++0x2A, 0x00, 0x29, 0x00, 0x11, 0x48, 0x79, 0xF7, 0x31, 0xFE, 0x01, 0x9B, 0x5A, 0x88, 0x02, 0x80, 0x9B, 0x88, 0x43, 0x80, ++0xC0, 0x21, 0x49, 0x00, 0x8A, 0x42, 0x00, 0xD9, 0x01, 0x80, 0xC0, 0x22, 0x52, 0x00, 0x93, 0x42, 0x00, 0xD9, 0x42, 0x80, ++0x01, 0x9A, 0xD3, 0x88, 0x83, 0x80, 0x13, 0x89, 0xC3, 0x80, 0x79, 0xF7, 0x45, 0xFE, 0x00, 0xE0, 0x02, 0x24, 0x21, 0x00, ++0x30, 0x00, 0x91, 0xF7, 0xE7, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x64, 0xA2, 0x16, 0x00, 0x0D, 0x06, 0x00, 0x00, ++0x70, 0xB5, 0x04, 0x00, 0x08, 0x00, 0x15, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x0F, 0x4A, 0x9E, 0x58, 0x7A, 0xF7, 0xDA, 0xF9, ++0x02, 0x21, 0x00, 0x28, 0x10, 0xD0, 0x63, 0x88, 0xF0, 0x22, 0x10, 0x31, 0x1A, 0x42, 0x0B, 0xD1, 0xE6, 0x3A, 0x01, 0x39, ++0x1A, 0x42, 0x07, 0xD1, 0x73, 0x84, 0x2C, 0x32, 0xB1, 0x5C, 0x00, 0x29, 0x08, 0xD1, 0x35, 0x3A, 0x93, 0x43, 0x73, 0x84, ++0x22, 0x88, 0x28, 0x00, 0xFF, 0xF7, 0xE0, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x00, 0x21, 0xF7, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0E, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x4B, 0x4B, ++0x9C, 0x42, 0x5D, 0xD0, 0x0E, 0xD9, 0x4A, 0x4B, 0x9C, 0x42, 0x67, 0xD0, 0x42, 0xD9, 0x49, 0x4B, 0x9C, 0x42, 0x00, 0xD0, ++0x81, 0xE0, 0x47, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0xDA, 0xFD, 0x00, 0x25, 0x43, 0xE0, 0x44, 0x4B, 0x9C, 0x42, ++0x69, 0xD0, 0x01, 0x33, 0x9C, 0x42, 0x13, 0xD3, 0x42, 0x4B, 0xE3, 0x18, 0x9B, 0xB2, 0x03, 0x2B, 0x00, 0xD9, 0x6E, 0xE0, ++0x10, 0x00, 0x7A, 0xF7, 0x91, 0xF9, 0x43, 0x28, 0x51, 0xD8, 0x41, 0x28, 0x51, 0xD8, 0x32, 0x00, 0x0C, 0x21, 0x20, 0x00, ++0xFF, 0xF7, 0xCE, 0xFE, 0x00, 0x25, 0x29, 0xE0, 0x39, 0x4B, 0x9C, 0x42, 0x37, 0xD0, 0x39, 0x4B, 0x9C, 0x42, 0x5A, 0xD1, ++0x38, 0x48, 0x7B, 0xF7, 0xAB, 0xFE, 0xB5, 0x1D, 0x16, 0x23, 0x9A, 0x46, 0xB2, 0x44, 0x36, 0x4B, 0x99, 0x46, 0x29, 0x78, ++0x48, 0x46, 0x7B, 0xF7, 0xA1, 0xFE, 0x01, 0x35, 0x55, 0x45, 0xF8, 0xD1, 0x2F, 0x4B, 0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, ++0x30, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0x0B, 0xE0, 0x2F, 0x4B, 0x9C, 0x42, 0x38, 0xD0, 0x2F, 0x4B, 0x9C, 0x42, 0x3C, 0xD1, ++0x2D, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x8B, 0xFD, 0x00, 0x25, 0x21, 0x00, 0x2B, 0x48, 0x7B, 0xF7, 0x86, 0xFE, ++0x28, 0x00, 0x03, 0xB0, 0x0C, 0xBC, 0x91, 0x46, 0x9A, 0x46, 0xF0, 0xBD, 0x1A, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, ++0xFB, 0xFE, 0x00, 0x25, 0xEE, 0xE7, 0x1C, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0xEC, 0xFD, 0x05, 0x00, 0xE7, 0xE7, ++0x14, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x6B, 0xFE, 0x05, 0x00, 0xE0, 0xE7, 0x4A, 0x28, 0xAD, 0xD1, 0x23, 0x00, ++0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, 0x16, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xD6, 0xE7, 0x0E, 0x4A, 0x39, 0x00, 0x30, 0x00, ++0xFF, 0xF7, 0x8A, 0xFE, 0x05, 0x00, 0xCF, 0xE7, 0x11, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x43, 0xFF, 0x05, 0x00, ++0xC8, 0xE7, 0x23, 0x00, 0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, 0x0B, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xC0, 0xE7, 0xC0, 0x46, ++0x03, 0x08, 0x00, 0x00, 0x28, 0x0C, 0x00, 0x00, 0x37, 0x0C, 0x00, 0x00, 0x1F, 0x04, 0x00, 0x00, 0xD4, 0xFB, 0xFF, 0xFF, ++0x09, 0x04, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x90, 0xD2, 0x10, 0x00, 0x98, 0xD2, 0x10, 0x00, 0xC1, 0xDB, 0x09, 0x00, ++0x0D, 0x08, 0x00, 0x00, 0x11, 0x08, 0x00, 0x00, 0x9C, 0xD2, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x78, ++0x00, 0x21, 0x01, 0x2B, 0x00, 0xD9, 0x12, 0x31, 0xB2, 0xF7, 0x7C, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x08, 0x00, ++0x00, 0x21, 0xB2, 0xF7, 0x75, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0xAD, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0x02, 0xAB, 0x00, 0x22, 0xDA, 0x71, 0x60, 0x32, 0x00, 0x21, ++0x14, 0xA8, 0x77, 0xF7, 0x8B, 0xFD, 0x9B, 0x4A, 0x9B, 0x4B, 0xD3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0xC8, 0xE1, 0x99, 0x4B, ++0x02, 0x21, 0xD1, 0x54, 0x02, 0xAB, 0x00, 0x21, 0xD9, 0x71, 0x44, 0x32, 0x00, 0x20, 0x00, 0x23, 0x01, 0x26, 0x11, 0x78, ++0x05, 0x29, 0x26, 0xD0, 0x01, 0x33, 0xDB, 0xB2, 0x40, 0x32, 0x30, 0x00, 0x0C, 0x2B, 0xF6, 0xD1, 0x02, 0xAB, 0x0C, 0x22, ++0xDA, 0x71, 0x27, 0x78, 0x00, 0x2F, 0x24, 0xD0, 0x60, 0x7A, 0x07, 0x23, 0x07, 0x00, 0x9F, 0x43, 0x00, 0x97, 0x00, 0xD0, ++0xB5, 0xE1, 0x8A, 0x49, 0x0F, 0x22, 0x02, 0x40, 0x03, 0x09, 0x8E, 0x5C, 0xCB, 0x5C, 0xF6, 0x18, 0xF6, 0xB2, 0x00, 0x2E, ++0x61, 0xDD, 0x23, 0x00, 0x0A, 0x33, 0x3A, 0x00, 0x02, 0x37, 0x07, 0x40, 0x01, 0x21, 0x01, 0x40, 0xA4, 0x46, 0x0C, 0x00, ++0x1E, 0xE0, 0x00, 0x28, 0x01, 0xD0, 0x02, 0xAA, 0xD3, 0x71, 0x0C, 0x21, 0x00, 0x27, 0x0B, 0x2B, 0x00, 0xD8, 0x8D, 0xE1, ++0xD7, 0xE7, 0xA1, 0x78, 0xE0, 0x1C, 0xB2, 0xF7, 0x35, 0xFF, 0x0B, 0x21, 0x00, 0x28, 0x00, 0xD0, 0x84, 0xE1, 0xD1, 0xE7, ++0x59, 0x88, 0x18, 0x88, 0x81, 0x42, 0x46, 0xD8, 0x03, 0x29, 0x44, 0xD9, 0x03, 0x28, 0x42, 0xD9, 0x01, 0x32, 0x10, 0x33, ++0xB2, 0x42, 0x04, 0xDA, 0x00, 0x2F, 0xF1, 0xD0, 0x94, 0x42, 0xEF, 0xD1, 0xF6, 0xE7, 0x64, 0x46, 0x23, 0x00, 0x0E, 0x33, ++0x00, 0x98, 0xC8, 0x22, 0x12, 0x01, 0x91, 0x46, 0x6B, 0x4A, 0x92, 0x46, 0xFA, 0x22, 0x52, 0x00, 0x93, 0x46, 0xA4, 0x46, ++0xA8, 0x46, 0x1F, 0x88, 0x5A, 0x88, 0x97, 0x42, 0x2D, 0xD8, 0x1D, 0x89, 0x59, 0x89, 0x8D, 0x42, 0x29, 0xD8, 0xD9, 0x88, ++0x05, 0x2F, 0x26, 0xD9, 0x4A, 0x45, 0x24, 0xD8, 0x0F, 0x00, 0x0A, 0x3F, 0xBF, 0xB2, 0x57, 0x45, 0x1F, 0xD8, 0x9F, 0x88, ++0x5F, 0x45, 0x1C, 0xD2, 0x8C, 0x00, 0x61, 0x18, 0x49, 0x00, 0x01, 0x37, 0x57, 0x43, 0xBA, 0x00, 0xD2, 0x19, 0x01, 0x32, ++0x52, 0x10, 0x91, 0x42, 0x11, 0xDB, 0x01, 0x30, 0x10, 0x33, 0xB0, 0x42, 0xDB, 0xDB, 0x64, 0x46, 0x45, 0x46, 0xA3, 0x78, ++0x01, 0x2B, 0x0F, 0xD9, 0x12, 0x21, 0x00, 0x27, 0x38, 0xE1, 0x64, 0x46, 0x96, 0x42, 0xC3, 0xDD, 0x12, 0x21, 0x00, 0x27, ++0x32, 0xE1, 0x64, 0x46, 0x45, 0x46, 0x86, 0x42, 0xEF, 0xDD, 0x12, 0x21, 0x00, 0x27, 0x2B, 0xE1, 0x63, 0x78, 0x03, 0x2B, ++0x00, 0xD9, 0x35, 0xE1, 0xDB, 0x07, 0x06, 0xD5, 0x49, 0x49, 0x4A, 0x48, 0x7B, 0xF7, 0x98, 0xFD, 0x00, 0x28, 0x00, 0xD0, ++0x2F, 0xE1, 0x02, 0xAB, 0xD8, 0x1D, 0xB3, 0xF7, 0x71, 0xF9, 0x01, 0x00, 0x01, 0x90, 0x00, 0x27, 0x00, 0x28, 0x00, 0xD0, ++0x14, 0xE1, 0x00, 0x2E, 0x00, 0xDC, 0x25, 0xE1, 0x0E, 0x23, 0x99, 0x46, 0xA1, 0x44, 0x14, 0xAF, 0x00, 0x9B, 0x9A, 0x46, ++0x00, 0x23, 0x9B, 0x46, 0xA0, 0x46, 0x4C, 0x46, 0xA9, 0x46, 0x55, 0x46, 0x13, 0xE0, 0x78, 0x60, 0x39, 0x60, 0xBA, 0x60, ++0xFB, 0x60, 0x5B, 0x46, 0xBB, 0x74, 0xFB, 0x74, 0x02, 0xAB, 0xDB, 0x79, 0x3B, 0x82, 0x38, 0x00, 0xCF, 0xF7, 0xCA, 0xFA, ++0x00, 0x28, 0x18, 0xD1, 0x01, 0x35, 0x10, 0x34, 0x20, 0x37, 0xB5, 0x42, 0x24, 0xDA, 0x23, 0x00, 0x21, 0x88, 0x49, 0x00, ++0x22, 0x89, 0x8A, 0x42, 0x00, 0xD9, 0x0A, 0x00, 0x02, 0x2A, 0x00, 0xD2, 0x02, 0x22, 0x58, 0x88, 0x40, 0x00, 0x5B, 0x89, ++0x83, 0x42, 0x00, 0xD9, 0x03, 0x00, 0x93, 0x42, 0xD9, 0xD2, 0x13, 0x00, 0xD7, 0xE7, 0xAA, 0x46, 0x44, 0x46, 0x4D, 0x46, ++0x51, 0x46, 0x25, 0x48, 0x7B, 0xF7, 0x10, 0xFD, 0x51, 0x46, 0x24, 0x48, 0x7B, 0xF7, 0x0C, 0xFD, 0x01, 0x9F, 0x3B, 0x21, ++0x56, 0x45, 0x00, 0xDD, 0xCC, 0xE0, 0x06, 0xE0, 0xAA, 0x46, 0x44, 0x46, 0x4D, 0x46, 0x51, 0x46, 0x1D, 0x48, 0x7B, 0xF7, ++0xFF, 0xFC, 0x02, 0xAB, 0xDA, 0x79, 0x92, 0x01, 0x13, 0x4B, 0x9B, 0x18, 0x9B, 0x68, 0x00, 0x2B, 0x05, 0xD0, 0x19, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x60, 0x78, 0x02, 0x28, 0x2D, 0xD0, 0x0E, 0xD8, 0x00, 0x28, ++0x2A, 0xD0, 0x0B, 0x49, 0x02, 0xAB, 0xD8, 0x79, 0x80, 0x01, 0x08, 0x18, 0x0C, 0x30, 0x11, 0x4B, 0x9C, 0x46, 0x61, 0x44, ++0x06, 0x22, 0xD0, 0xF7, 0xD3, 0xFA, 0x2B, 0xE0, 0x03, 0x28, 0xF0, 0xD0, 0x0B, 0x4B, 0xDF, 0x6E, 0x00, 0x23, 0x1A, 0x00, ++0x19, 0x00, 0xB8, 0x47, 0x22, 0xE0, 0xC0, 0x46, 0xEC, 0xA4, 0x16, 0x00, 0x6D, 0x04, 0x00, 0x00, 0xE4, 0x98, 0x0D, 0x00, ++0x76, 0x0C, 0x00, 0x00, 0xB4, 0x98, 0x0D, 0x00, 0xFA, 0xA7, 0x16, 0x00, 0xA4, 0xD2, 0x10, 0x00, 0xB0, 0xD2, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x0E, 0x03, 0x00, 0x00, 0x4E, 0x4A, 0x02, 0xAB, 0x07, 0x33, 0x1B, 0x78, 0x9B, 0x01, 0xD3, 0x18, ++0xC2, 0x21, 0x89, 0x00, 0x8C, 0x46, 0x62, 0x44, 0x11, 0x68, 0xD9, 0x60, 0x92, 0x88, 0x1A, 0x82, 0x02, 0xAB, 0x07, 0x33, ++0x1B, 0x78, 0x46, 0x4F, 0x9A, 0x01, 0xBA, 0x18, 0x94, 0x60, 0x01, 0x33, 0x9B, 0x01, 0xFB, 0x18, 0x05, 0x22, 0x1A, 0x71, ++0xE1, 0x1C, 0x01, 0x32, 0x0E, 0x20, 0x02, 0xAB, 0x9C, 0x46, 0x60, 0x44, 0xD0, 0xF7, 0x92, 0xFA, 0x3E, 0x4B, 0xF9, 0x18, ++0x05, 0x22, 0x07, 0xA8, 0xD0, 0xF7, 0x8C, 0xFA, 0x67, 0x7A, 0x04, 0xAB, 0x9F, 0x74, 0x00, 0x2E, 0x17, 0xDD, 0x22, 0x00, ++0x0A, 0x32, 0x14, 0xA9, 0x10, 0x88, 0x18, 0x83, 0x50, 0x88, 0x58, 0x83, 0x48, 0x69, 0x40, 0x08, 0x98, 0x83, 0x88, 0x69, ++0xD8, 0x83, 0x10, 0x89, 0x18, 0x84, 0x50, 0x89, 0x58, 0x84, 0x00, 0x98, 0x01, 0x30, 0x00, 0x90, 0x10, 0x32, 0x0C, 0x33, ++0x20, 0x31, 0xB0, 0x42, 0xEA, 0xDB, 0x05, 0x23, 0x3B, 0x40, 0x05, 0x2B, 0x20, 0xD0, 0x02, 0xAB, 0x07, 0x33, 0x1B, 0x78, ++0x04, 0xA8, 0xC3, 0x74, 0x62, 0x78, 0x02, 0x75, 0xA2, 0x78, 0x42, 0x75, 0x22, 0x78, 0x82, 0x75, 0x24, 0x4A, 0x9B, 0x01, ++0xD3, 0x18, 0xD9, 0x68, 0x04, 0x91, 0x1B, 0x8A, 0x83, 0x80, 0x01, 0x23, 0x43, 0x74, 0x22, 0x4B, 0xD2, 0x5C, 0x3C, 0x23, ++0xC2, 0x54, 0xC7, 0xF7, 0x29, 0xFF, 0x01, 0x00, 0x01, 0x27, 0x00, 0x28, 0x1E, 0xD0, 0x03, 0x21, 0x01, 0x27, 0x1B, 0xE0, ++0x01, 0x3E, 0x04, 0xA8, 0x43, 0x8B, 0x0C, 0x22, 0x72, 0x43, 0x82, 0x18, 0x51, 0x8B, 0x5F, 0x18, 0x02, 0x8B, 0xBA, 0x42, ++0x00, 0xD2, 0x07, 0x83, 0x0C, 0x22, 0x72, 0x43, 0x04, 0xA8, 0x84, 0x46, 0x62, 0x44, 0x12, 0x8B, 0xBA, 0x42, 0xCA, 0xD2, ++0x0C, 0x22, 0x72, 0x43, 0x62, 0x44, 0x5B, 0x18, 0x13, 0x83, 0xC4, 0xE7, 0x0C, 0x21, 0x00, 0x27, 0x28, 0x00, 0xB2, 0xF7, ++0x9B, 0xFD, 0x38, 0x00, 0x2D, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x12, 0x21, ++0x00, 0x27, 0xF1, 0xE7, 0x12, 0x21, 0x00, 0x27, 0xEE, 0xE7, 0x12, 0x21, 0x00, 0x27, 0xEB, 0xE7, 0x00, 0x9B, 0x9A, 0x46, ++0x1F, 0xE7, 0xC0, 0x46, 0xEC, 0xA4, 0x16, 0x00, 0x19, 0x03, 0x00, 0x00, 0xD6, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x80, 0x46, 0x0D, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x58, 0x4B, 0xE3, 0x18, 0x9A, 0xB2, 0x39, 0x2A, 0x00, 0xD9, ++0x90, 0xE0, 0x93, 0x00, 0x55, 0x4A, 0xD3, 0x58, 0x9F, 0x46, 0x02, 0x20, 0xF8, 0xF7, 0x40, 0xFF, 0x53, 0x4B, 0x00, 0x22, ++0x44, 0x21, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, ++0x00, 0x26, 0x7C, 0xE0, 0x01, 0x20, 0xF8, 0xF7, 0x2F, 0xFF, 0x4B, 0x4B, 0x11, 0x22, 0x44, 0x21, 0x5A, 0x54, 0x40, 0x31, ++0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x00, 0x26, 0x6B, 0xE0, 0x45, 0x4B, ++0x1B, 0x78, 0x00, 0x26, 0x00, 0x2B, 0x66, 0xD0, 0x43, 0x49, 0x28, 0x00, 0xFF, 0xF7, 0xB0, 0xFD, 0x05, 0x00, 0x21, 0x00, ++0x41, 0x48, 0x7B, 0xF7, 0xDB, 0xFB, 0x41, 0x4B, 0x9C, 0x42, 0x6E, 0xD1, 0x00, 0x26, 0x3B, 0x4A, 0x3F, 0x4B, 0x00, 0x21, ++0xD1, 0x54, 0x62, 0xE0, 0x39, 0x4B, 0x1B, 0x78, 0x00, 0x26, 0x00, 0x2B, 0x4F, 0xD0, 0x00, 0x21, 0x3B, 0x48, 0xB2, 0xF7, ++0x1F, 0xFD, 0x00, 0x25, 0xE7, 0xE7, 0x4B, 0x78, 0x02, 0x2B, 0x27, 0xD0, 0x38, 0x4E, 0x05, 0x22, 0xFF, 0x21, 0x30, 0x00, ++0x77, 0xF7, 0x3E, 0xFB, 0x36, 0x4B, 0xF3, 0x18, 0x36, 0x49, 0x58, 0x5C, 0x1F, 0x22, 0x02, 0x40, 0x5A, 0x54, 0x35, 0x4B, ++0x1B, 0x78, 0xEB, 0x81, 0x2B, 0x82, 0x12, 0x23, 0xAB, 0x81, 0x6B, 0x7A, 0x9A, 0x07, 0x07, 0xD5, 0x02, 0x22, 0x93, 0x43, ++0x6B, 0x72, 0x12, 0x23, 0xAB, 0x83, 0x6B, 0x8B, 0x9B, 0x00, 0x6B, 0x83, 0x6B, 0x7A, 0x00, 0x26, 0x5B, 0x07, 0x24, 0xD5, ++0x12, 0x23, 0xAB, 0x85, 0x6B, 0x8D, 0x5B, 0x00, 0x6B, 0x85, 0x1E, 0xE0, 0x00, 0x23, 0x4B, 0x70, 0xD4, 0xE7, 0x23, 0x4E, ++0x05, 0x22, 0xFF, 0x21, 0x30, 0x00, 0x77, 0xF7, 0x13, 0xFB, 0x21, 0x4B, 0xF0, 0x18, 0x21, 0x4A, 0x81, 0x5C, 0x1F, 0x23, ++0x0B, 0x40, 0x83, 0x54, 0x20, 0x4B, 0xC6, 0x5C, 0x00, 0x2E, 0x0A, 0xD0, 0x13, 0x4A, 0x00, 0x21, 0xD1, 0x54, 0x06, 0xE0, ++0x11, 0x4A, 0x16, 0x4B, 0x00, 0x21, 0xD1, 0x54, 0x00, 0x26, 0x00, 0xE0, 0x00, 0x26, 0x23, 0x00, 0x3A, 0x00, 0x29, 0x00, ++0x40, 0x46, 0x18, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0x21, 0x00, 0x0D, 0x48, 0x7B, 0xF7, 0x72, 0xFB, 0x0C, 0x4B, 0x9C, 0x42, ++0x97, 0xD0, 0x00, 0x2E, 0x03, 0xD0, 0x06, 0x4A, 0x10, 0x4B, 0x01, 0x21, 0xD1, 0x54, 0x28, 0x00, 0x04, 0xBC, 0x90, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0xF6, 0xDF, 0xFF, 0xFF, 0xC4, 0xD2, 0x10, 0x00, 0xEC, 0xA4, 0x16, 0x00, 0x60, 0xE6, 0x10, 0x00, ++0x0A, 0x20, 0x00, 0x00, 0xB8, 0xD2, 0x10, 0x00, 0x3B, 0x20, 0x00, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x39, 0x20, 0x00, 0x00, ++0x05, 0xA8, 0x16, 0x00, 0xE7, 0xFC, 0xFF, 0xFF, 0x1D, 0x03, 0x00, 0x00, 0xE2, 0xE1, 0x10, 0x00, 0xD6, 0x03, 0x00, 0x00, ++0x15, 0xC9, 0x0B, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x06, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x17, 0x4B, 0x9C, 0x42, ++0x24, 0xD0, 0x17, 0x4B, 0x9C, 0x42, 0x13, 0xD1, 0xCB, 0x88, 0x10, 0x2B, 0x01, 0xD9, 0x10, 0x23, 0xCB, 0x80, 0x14, 0x4B, ++0x1B, 0x78, 0x6A, 0x88, 0x9A, 0x42, 0x01, 0xD8, 0x6B, 0x80, 0xAB, 0x80, 0xEB, 0x88, 0xAA, 0x88, 0x69, 0x88, 0x28, 0x89, ++0x00, 0x90, 0x0F, 0x48, 0x7B, 0xF7, 0x26, 0xFB, 0x23, 0x00, 0x3A, 0x00, 0x29, 0x00, 0x30, 0x00, 0x0C, 0x4D, 0xA8, 0x47, ++0x05, 0x00, 0x21, 0x00, 0x0B, 0x48, 0x7B, 0xF7, 0x1B, 0xFB, 0x28, 0x00, 0x03, 0xB0, 0xF0, 0xBD, 0x0A, 0x88, 0x00, 0x21, ++0x02, 0x48, 0xFF, 0xF7, 0x03, 0xFA, 0x00, 0x25, 0xF1, 0xE7, 0xC0, 0x46, 0x0D, 0x08, 0x00, 0x00, 0x13, 0x20, 0x00, 0x00, ++0xE2, 0xE1, 0x10, 0x00, 0xAC, 0xD3, 0x10, 0x00, 0x09, 0x1C, 0x0C, 0x00, 0xBC, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0xCE, 0x46, ++0x47, 0x46, 0x80, 0xB5, 0x14, 0x0A, 0xA4, 0x00, 0x0E, 0x4D, 0x65, 0x59, 0x44, 0x24, 0x2C, 0x5D, 0x03, 0x27, 0x3E, 0x00, ++0x26, 0x40, 0x27, 0x42, 0x11, 0xD0, 0xB9, 0x46, 0xBC, 0x43, 0xA4, 0x46, 0x44, 0x24, 0x67, 0x46, 0x2F, 0x55, 0xB9, 0xF7, ++0x7F, 0xF8, 0x2B, 0x5D, 0x4A, 0x46, 0x93, 0x43, 0x1E, 0x43, 0x2E, 0x55, 0x00, 0x20, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xF8, 0xBD, 0xB9, 0xF7, 0x73, 0xF8, 0xF7, 0xE7, 0x5C, 0xA9, 0x16, 0x00, 0x70, 0xB5, 0x0D, 0x00, 0x14, 0x0A, 0xA2, 0x00, ++0x29, 0x4B, 0xD6, 0x58, 0x0B, 0x2C, 0x06, 0xD8, 0x00, 0x2E, 0x04, 0xD0, 0x44, 0x23, 0xF3, 0x5C, 0xDB, 0x43, 0x9B, 0x07, ++0x11, 0xD1, 0x2D, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x06, 0xD0, 0x2A, 0x00, 0x16, 0x21, 0x20, 0x00, 0x21, 0x4B, 0x98, 0x47, ++0x00, 0x20, 0x70, 0xBD, 0x45, 0x22, 0xB1, 0x5C, 0x7F, 0x23, 0x0B, 0x40, 0xB3, 0x54, 0x00, 0x20, 0xF7, 0xE7, 0x00, 0x21, ++0x20, 0x00, 0xB8, 0xF7, 0x83, 0xFC, 0x00, 0x28, 0x2C, 0xD1, 0x42, 0x23, 0xF3, 0x5A, 0xDB, 0x06, 0x04, 0xD5, 0x28, 0x00, ++0xB8, 0xF7, 0x92, 0xFC, 0x00, 0x28, 0x25, 0xD0, 0x28, 0x00, 0xB8, 0xF7, 0x8D, 0xFC, 0x00, 0x28, 0x0E, 0xD1, 0x2A, 0x00, ++0x00, 0x21, 0x20, 0x00, 0xB8, 0xF7, 0x20, 0xFC, 0x28, 0x00, 0xB8, 0xF7, 0x83, 0xFC, 0x01, 0x00, 0x00, 0x22, 0x20, 0x00, ++0x0D, 0x4B, 0x98, 0x47, 0x01, 0x20, 0xD4, 0xE7, 0x28, 0x00, 0xB8, 0xF7, 0x79, 0xFC, 0x01, 0x28, 0xEB, 0xD0, 0x0A, 0x4B, ++0xDE, 0x6E, 0x28, 0x00, 0xB8, 0xF7, 0x72, 0xFC, 0x01, 0x00, 0x00, 0x23, 0x00, 0x22, 0x20, 0x00, 0xB0, 0x47, 0xE0, 0xE7, ++0x02, 0x20, 0xC2, 0xE7, 0x02, 0x20, 0xC0, 0xE7, 0x5C, 0xA9, 0x16, 0x00, 0x81, 0x45, 0x0C, 0x00, 0xF5, 0x46, 0x0C, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x82, 0xB0, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0x1F, 0x00, ++0x13, 0x0A, 0x9B, 0x00, 0x0E, 0x4A, 0x9B, 0x58, 0x00, 0x2B, 0x0E, 0xD0, 0x89, 0x88, 0x0D, 0x4B, 0x9C, 0x46, 0x61, 0x44, ++0x01, 0xAB, 0x98, 0x46, 0x01, 0x22, 0x18, 0x00, 0xD0, 0xF7, 0x5A, 0xF8, 0x43, 0x46, 0x19, 0x78, 0x08, 0x48, 0x7B, 0xF7, ++0x61, 0xFA, 0x3B, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0xB9, 0xF7, 0x91, 0xF9, 0x02, 0xB0, 0x04, 0xBC, 0x90, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0x5C, 0xA9, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0xC8, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0x05, 0x00, ++0x0E, 0x00, 0x14, 0x00, 0x1F, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x08, 0x4A, 0x9B, 0x58, 0x9B, 0x6A, 0x00, 0x2B, 0x03, 0xD0, ++0x59, 0x7A, 0x06, 0x48, 0x7B, 0xF7, 0x40, 0xFA, 0x3B, 0x00, 0x22, 0x00, 0x31, 0x00, 0x28, 0x00, 0xB9, 0xF7, 0x50, 0xFA, ++0xF8, 0xBD, 0xC0, 0x46, 0x5C, 0xA9, 0x16, 0x00, 0xD4, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0x04, 0x00, 0x06, 0x0A, 0xB2, 0x00, ++0x28, 0x4B, 0xD5, 0x58, 0x28, 0x00, 0x54, 0x30, 0x2A, 0x21, 0xA0, 0xF7, 0x31, 0xFD, 0x00, 0x28, 0x3C, 0xD0, 0xF6, 0xB2, ++0x30, 0x00, 0xAA, 0xF7, 0xB5, 0xF8, 0x20, 0x00, 0x91, 0xF7, 0x02, 0xFA, 0x43, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x23, 0xD0, ++0x1F, 0x4B, 0xEB, 0x5C, 0x00, 0x2B, 0x14, 0xD0, 0x95, 0x23, 0x9B, 0x00, 0xEF, 0x18, 0x38, 0x00, 0x86, 0xF7, 0x80, 0xFA, ++0x36, 0x23, 0xE9, 0x5C, 0x3A, 0x00, 0x30, 0x00, 0xA1, 0xF7, 0x42, 0xF8, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x0A, 0xD0, ++0x2D, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x76, 0xFC, 0x22, 0xE0, 0x36, 0x23, 0xE9, 0x5C, 0x30, 0x00, 0xA1, 0xF7, 0x4B, 0xF8, ++0xF0, 0xE7, 0x2B, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x6B, 0xFC, 0x17, 0xE0, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x04, 0xD0, ++0x60, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x62, 0xFC, 0x0E, 0xE0, 0x61, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x5D, 0xFC, 0x09, 0xE0, ++0x00, 0x23, 0xAC, 0x22, 0x92, 0x00, 0xAB, 0x54, 0x05, 0x4A, 0xAB, 0x54, 0x00, 0x21, 0x20, 0x00, 0x93, 0xF7, 0xA6, 0xFB, ++0xF8, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xAF, 0x02, 0x00, 0x00, 0xB3, 0x02, 0x00, 0x00, 0xF8, 0xB5, 0x05, 0x00, ++0x0E, 0x00, 0x07, 0x0A, 0xBA, 0x00, 0x1D, 0x4B, 0xD4, 0x58, 0x1D, 0x4B, 0xE3, 0x5C, 0x00, 0x2B, 0x0A, 0xD1, 0x1B, 0x4B, ++0x00, 0x22, 0xE2, 0x54, 0x09, 0x3B, 0xE3, 0x5C, 0x00, 0x2B, 0x27, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0x8F, 0xFF, 0xF8, 0xBD, ++0x93, 0xF7, 0xCC, 0xF8, 0x00, 0x28, 0x03, 0xD0, 0x14, 0x4B, 0xE3, 0x5C, 0x00, 0x2B, 0x0C, 0xD0, 0x11, 0x4B, 0xE3, 0x5C, ++0x00, 0x2B, 0xE8, 0xD0, 0x88, 0x23, 0xFF, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0xE3, 0xD0, 0x43, 0x23, 0x01, 0x22, 0xE2, 0x54, ++0xDF, 0xE7, 0x04, 0x33, 0x06, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x79, 0xF7, 0xA3, 0xF8, 0x06, 0x70, 0x80, 0x37, 0x47, 0x80, ++0xCA, 0xF7, 0xFE, 0xFE, 0x43, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xE3, 0xE7, 0x31, 0x00, 0x28, 0x00, 0x93, 0xF7, 0x60, 0xFB, ++0xD5, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xB9, 0x02, 0x00, 0x00, 0xC5, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, ++0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x8C, 0xB0, 0x05, 0x00, 0x0C, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x4A, 0x4B, 0xD6, 0x58, ++0x08, 0x00, 0x79, 0xF7, 0x55, 0xFC, 0x20, 0x28, 0x07, 0xD0, 0x21, 0x00, 0x28, 0x00, 0x47, 0x4B, 0x98, 0x47, 0x0C, 0xB0, ++0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2A, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x69, 0x1C, 0x29, 0x3A, ++0x30, 0x00, 0xCB, 0x30, 0xFF, 0x30, 0xCF, 0xF7, 0x61, 0xFF, 0xFD, 0x23, 0x5B, 0x00, 0x98, 0x46, 0xB0, 0x44, 0x09, 0xAB, ++0x07, 0x93, 0x43, 0x46, 0x06, 0x93, 0x02, 0xA8, 0x10, 0x22, 0x31, 0x00, 0xCB, 0x31, 0xFF, 0x31, 0xCF, 0xF7, 0x52, 0xFF, ++0x6A, 0x46, 0x33, 0x00, 0x6C, 0x33, 0xF1, 0x6E, 0x00, 0x91, 0x9B, 0x88, 0x93, 0x80, 0xCD, 0x23, 0x5B, 0x00, 0xF3, 0x5A, ++0x35, 0x00, 0x9B, 0x35, 0xFF, 0x35, 0x68, 0x88, 0x00, 0x04, 0x18, 0x43, 0xAB, 0x88, 0xE9, 0x88, 0x09, 0x04, 0x19, 0x43, ++0x2B, 0x89, 0x6A, 0x89, 0x12, 0x04, 0x1A, 0x43, 0xAB, 0x89, 0x9C, 0x46, 0xEB, 0x89, 0x1B, 0x04, 0x65, 0x46, 0x2B, 0x43, ++0x83, 0xF7, 0xDA, 0xFD, 0x27, 0x4B, 0xF3, 0x5C, 0x00, 0x2B, 0x1F, 0xD0, 0x39, 0x23, 0xF2, 0x5C, 0xF8, 0xB2, 0x41, 0x46, ++0xA0, 0xF7, 0x93, 0xFE, 0xBE, 0x23, 0x5B, 0x00, 0xF3, 0x5C, 0x00, 0x2B, 0x1B, 0xD0, 0x88, 0x23, 0xFF, 0x33, 0xF3, 0x5C, ++0x00, 0x2B, 0x05, 0xD0, 0x01, 0x23, 0xAC, 0x22, 0x92, 0x00, 0xB3, 0x54, 0x1C, 0x4A, 0xB3, 0x54, 0x37, 0x23, 0xF3, 0x5C, ++0x05, 0x2B, 0x27, 0xD0, 0x00, 0x21, 0x20, 0x00, 0xFF, 0xF7, 0x44, 0xFF, 0x00, 0x20, 0x9C, 0xE7, 0x0C, 0x22, 0x09, 0xA9, ++0x16, 0x4B, 0xF0, 0x18, 0xCF, 0xF7, 0x08, 0xFF, 0xD8, 0xE7, 0x17, 0x33, 0x18, 0x22, 0x00, 0x21, 0x13, 0x48, 0x79, 0xF7, ++0x09, 0xF8, 0x05, 0x00, 0xC0, 0x23, 0x5B, 0x00, 0xF3, 0x5C, 0x83, 0x75, 0x06, 0x22, 0x31, 0x00, 0x72, 0x31, 0xCF, 0xF7, ++0xF7, 0xFE, 0xA8, 0x1D, 0x10, 0x22, 0x31, 0x00, 0x9B, 0x31, 0xFF, 0x31, 0xCF, 0xF7, 0xF0, 0xFE, 0x28, 0x00, 0xCA, 0xF7, ++0x55, 0xFE, 0xC8, 0xE7, 0x05, 0x21, 0x20, 0x00, 0x93, 0xF7, 0x2E, 0xFB, 0x00, 0x20, 0x74, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0x01, 0x4A, 0x0A, 0x00, 0xC5, 0x02, 0x00, 0x00, 0xB3, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, ++0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x0B, 0x4A, 0x9E, 0x58, 0x08, 0x00, 0x79, 0xF7, 0xAE, 0xFB, ++0x24, 0x28, 0x04, 0xD0, 0x21, 0x00, 0x28, 0x00, 0x07, 0x4B, 0x98, 0x47, 0x70, 0xBD, 0xBE, 0x23, 0x5B, 0x00, 0xF3, 0x5C, ++0x00, 0x2B, 0xF5, 0xD1, 0x7D, 0x33, 0xFF, 0x33, 0x01, 0x22, 0xF2, 0x54, 0xF0, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x55, 0x45, 0x0A, 0x00, 0xF8, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x0F, 0x0A, 0xBA, 0x00, ++0x2F, 0x4B, 0xD6, 0x58, 0x02, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x42, 0x78, 0x37, 0x23, 0xF2, 0x54, ++0x08, 0x00, 0x79, 0xF7, 0x83, 0xFB, 0x18, 0x28, 0x04, 0xD8, 0x01, 0x23, 0x83, 0x40, 0x28, 0x4A, 0x13, 0x42, 0x2B, 0xD1, ++0xFB, 0xB2, 0x99, 0x46, 0x18, 0x00, 0xAA, 0xF7, 0x81, 0xF9, 0x80, 0x46, 0x24, 0x4B, 0x01, 0x22, 0xF2, 0x54, 0x21, 0x00, ++0x23, 0x48, 0x78, 0xF7, 0x51, 0xFF, 0x23, 0x4B, 0xF3, 0x5C, 0x00, 0x2B, 0x1F, 0xD1, 0x3C, 0x23, 0xF3, 0x5C, 0x02, 0x2B, ++0x2D, 0xD0, 0x48, 0x46, 0xA9, 0xF7, 0x24, 0xFF, 0x36, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x2A, 0xD1, 0x43, 0x46, 0x58, 0x00, ++0x40, 0x44, 0x40, 0x00, 0x80, 0xB2, 0x7B, 0xF7, 0xE7, 0xF8, 0x02, 0x00, 0x21, 0x00, 0x16, 0x48, 0x78, 0xF7, 0xBE, 0xFE, ++0x19, 0x21, 0x20, 0x00, 0x79, 0xF7, 0xF0, 0xFA, 0x00, 0x20, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF8, 0xBD, 0x04, 0x23, ++0x06, 0x22, 0x00, 0x21, 0x10, 0x48, 0x78, 0xF7, 0x6F, 0xFF, 0x6B, 0x78, 0x03, 0x70, 0x80, 0x37, 0x47, 0x80, 0xCA, 0xF7, ++0xC9, 0xFD, 0x00, 0x23, 0x0A, 0x4A, 0xB3, 0x54, 0x43, 0x22, 0xB3, 0x54, 0xCD, 0xE7, 0x20, 0x00, 0x09, 0x4B, 0x98, 0x47, ++0xCD, 0xE7, 0x43, 0x46, 0x58, 0x00, 0x40, 0x44, 0x80, 0xB2, 0xD4, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x01, 0x00, 0x40, 0x01, ++0xC2, 0x02, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0xB9, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0xF5, 0x3A, 0x09, 0x00, ++0x00, 0x20, 0x70, 0x47, 0xF0, 0xB5, 0x83, 0xB0, 0x0C, 0x00, 0x04, 0x23, 0x5B, 0x4A, 0x00, 0x21, 0x5B, 0x48, 0x78, 0xF7, ++0x41, 0xFF, 0x05, 0x00, 0x21, 0x78, 0x5A, 0x48, 0x7B, 0xF7, 0x40, 0xF8, 0x23, 0x78, 0x01, 0x2B, 0x65, 0xD0, 0x06, 0x2B, ++0x00, 0xD1, 0x80, 0xE0, 0x00, 0x2B, 0x05, 0xD0, 0x28, 0x00, 0xCA, 0xF7, 0x91, 0xFD, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, ++0xA2, 0x78, 0x52, 0x4B, 0x1A, 0x70, 0x00, 0x23, 0x2B, 0x70, 0x6B, 0x70, 0xA3, 0x78, 0xAB, 0x70, 0x4F, 0x4B, 0x1B, 0x78, ++0xEB, 0x70, 0x63, 0x78, 0x01, 0x2B, 0xEB, 0xD1, 0x4D, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0xE7, 0xD1, 0x49, 0x4B, 0x1B, 0x78, ++0x06, 0x2B, 0xE3, 0xD1, 0xFC, 0xF7, 0x66, 0xF9, 0x49, 0x4C, 0x4A, 0x4B, 0x02, 0x22, 0xE2, 0x54, 0x6B, 0x46, 0xDF, 0x1D, ++0x38, 0x00, 0xB2, 0xF7, 0x2D, 0xFC, 0x3E, 0x78, 0x10, 0x23, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x78, 0xF7, 0x06, 0xFF, ++0xB6, 0x01, 0xA6, 0x19, 0xB0, 0x60, 0x3B, 0x78, 0x9B, 0x01, 0xE3, 0x18, 0x9B, 0x68, 0x01, 0x22, 0x9A, 0x70, 0x00, 0x26, ++0x1E, 0x71, 0x80, 0x22, 0x92, 0x01, 0xDA, 0x80, 0x1A, 0x81, 0x1E, 0x70, 0x5E, 0x70, 0x38, 0x78, 0x43, 0x1C, 0x9B, 0x01, ++0xE3, 0x18, 0x06, 0x22, 0x1A, 0x71, 0x38, 0x4A, 0xA3, 0x5C, 0x03, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x83, 0x01, 0xE3, 0x18, ++0x1E, 0x86, 0x5E, 0x86, 0x34, 0x4B, 0x98, 0x47, 0x3B, 0x78, 0x5A, 0x1C, 0x92, 0x01, 0xA2, 0x18, 0x07, 0x21, 0x11, 0x71, ++0x9B, 0x01, 0xE3, 0x18, 0x98, 0x68, 0x0C, 0x38, 0x78, 0xF7, 0x27, 0xFF, 0x3B, 0x78, 0x9B, 0x01, 0xE4, 0x18, 0xA6, 0x60, ++0x9E, 0xE7, 0xA3, 0x78, 0x00, 0x2B, 0x0C, 0xD1, 0x24, 0x4B, 0x1B, 0x78, 0x01, 0x33, 0xDB, 0xB2, 0x10, 0x2B, 0x02, 0xD8, ++0x21, 0x4A, 0x13, 0x70, 0x07, 0xE0, 0x20, 0x4B, 0x10, 0x22, 0x1A, 0x70, 0x03, 0xE0, 0x1E, 0x4A, 0x13, 0x78, 0x01, 0x3B, ++0x13, 0x70, 0x00, 0x23, 0x2B, 0x70, 0x01, 0x33, 0x6B, 0x70, 0xA3, 0x78, 0xAB, 0x70, 0x19, 0x4B, 0x1B, 0x78, 0xEB, 0x70, ++0x80, 0xE7, 0xE2, 0x78, 0x12, 0x02, 0xA3, 0x78, 0x13, 0x43, 0x1B, 0x4A, 0x1B, 0xB2, 0x93, 0x42, 0x00, 0xD0, 0x77, 0xE7, ++0x19, 0x4B, 0x1A, 0x80, 0x61, 0x79, 0x09, 0x02, 0x22, 0x79, 0x0A, 0x43, 0x5A, 0x80, 0xE1, 0x79, 0x09, 0x02, 0xA2, 0x79, ++0x0A, 0x43, 0x9A, 0x80, 0x98, 0x68, 0x00, 0x28, 0x01, 0xD0, 0x79, 0xF7, 0x11, 0xF8, 0x20, 0x7A, 0x10, 0x4E, 0xB0, 0x71, ++0x01, 0x21, 0x78, 0xF7, 0x67, 0xFF, 0xB0, 0x60, 0xB2, 0x79, 0x21, 0x00, 0x09, 0x31, 0xCF, 0xF7, 0x87, 0xFD, 0x59, 0xE7, ++0x57, 0xFD, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0xE0, 0xD3, 0x10, 0x00, 0xD0, 0xE5, 0x10, 0x00, 0x48, 0x06, 0x16, 0x00, ++0xA8, 0xE5, 0x10, 0x00, 0xEC, 0xA4, 0x16, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x6A, 0x04, 0x00, 0x00, 0xE1, 0xEA, 0x0B, 0x00, ++0x88, 0xAC, 0xFF, 0xFF, 0xC4, 0xE5, 0x10, 0x00, 0x09, 0x4B, 0x1B, 0x68, 0xDA, 0x6E, 0x53, 0x1C, 0x0C, 0xD0, 0x08, 0x4B, ++0x19, 0x68, 0x4B, 0x68, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x06, 0x48, 0x83, 0x42, 0x03, 0xD9, 0x04, 0x32, 0x12, 0x01, ++0x12, 0x09, 0x4A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0xF4, 0xE1, 0x10, 0x00, 0x28, 0x27, 0x16, 0x00, 0xFE, 0xFF, 0xFF, 0x07, ++0x30, 0xB5, 0x83, 0xB0, 0x68, 0x46, 0x77, 0xF7, 0xE5, 0xFC, 0x00, 0x9D, 0x34, 0x4C, 0x23, 0x68, 0x01, 0x22, 0x93, 0x43, ++0x23, 0x60, 0x82, 0xF7, 0x51, 0xFE, 0xB1, 0xF7, 0x69, 0xFE, 0x22, 0x68, 0x8C, 0x23, 0x5B, 0x01, 0x13, 0x43, 0x23, 0x60, ++0x2E, 0x4B, 0x1B, 0x68, 0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x41, 0xD0, 0x2A, 0x49, 0x0B, 0x68, 0x2B, 0x4A, 0x1A, 0x40, ++0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x27, 0x4B, 0x5B, 0x68, 0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x36, 0xD0, ++0x23, 0x49, 0x0B, 0x68, 0x25, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x13, 0x43, 0x0B, 0x60, 0x20, 0x4B, 0x9B, 0x68, ++0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x2B, 0xD0, 0x1C, 0x49, 0x0B, 0x68, 0x1F, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x00, ++0x13, 0x43, 0x0B, 0x60, 0x1D, 0x48, 0x78, 0xF7, 0x3F, 0xFA, 0x18, 0x4B, 0x5B, 0x7F, 0x00, 0x2B, 0x1F, 0xD1, 0x7F, 0xF7, ++0x9B, 0xFE, 0x02, 0x28, 0x21, 0xD1, 0x19, 0x49, 0x0B, 0x68, 0x19, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, ++0x0B, 0x60, 0x17, 0x4B, 0x1A, 0x68, 0x01, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x01, 0x31, 0x8A, 0x43, 0x1A, 0x60, ++0x03, 0xB0, 0x30, 0xBD, 0x77, 0xF7, 0x4E, 0xFB, 0xC2, 0xE7, 0x77, 0xF7, 0x5F, 0xFB, 0xCD, 0xE7, 0x77, 0xF7, 0x70, 0xFB, ++0xD8, 0xE7, 0xFC, 0xF7, 0x49, 0xFB, 0x05, 0x4B, 0x00, 0x22, 0x5A, 0x77, 0xD9, 0xE7, 0x7F, 0xF7, 0x75, 0xFE, 0x03, 0x28, ++0xEA, 0xD1, 0xD8, 0xE7, 0x0C, 0x00, 0x60, 0x40, 0x3C, 0x95, 0x16, 0x00, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, ++0xFF, 0xFD, 0xFF, 0xFF, 0x01, 0x20, 0x00, 0x00, 0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xDF, 0xFF, 0x18, 0x00, 0x58, 0x40, ++0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x91, 0x46, 0x9C, 0x4B, 0x1E, 0x68, 0x80, 0x00, 0x84, 0x59, ++0x3C, 0x23, 0xE3, 0x5C, 0x98, 0x46, 0x9A, 0x4B, 0xE3, 0x61, 0xBD, 0xF7, 0x4D, 0xFA, 0x01, 0x90, 0x00, 0x23, 0xA3, 0x62, ++0x00, 0x20, 0xCE, 0xF7, 0x51, 0xFF, 0x96, 0x4B, 0x1D, 0x68, 0xEB, 0x6E, 0x5A, 0x1C, 0x16, 0xD0, 0x63, 0x60, 0x00, 0x23, ++0xA3, 0x60, 0xE7, 0x8E, 0xA7, 0x62, 0x92, 0x49, 0x9A, 0x00, 0x52, 0x58, 0x00, 0x2A, 0x25, 0xD1, 0x01, 0x33, 0x07, 0x2B, ++0xF8, 0xD1, 0x00, 0x23, 0x9C, 0x46, 0x8E, 0x4B, 0x18, 0x00, 0x41, 0x30, 0xFF, 0x30, 0x00, 0x22, 0x00, 0x21, 0x00, 0x91, ++0x1E, 0xE0, 0x8B, 0x4B, 0x1B, 0x68, 0x01, 0x33, 0x09, 0xD0, 0x8A, 0x4B, 0x1B, 0x68, 0x5B, 0x00, 0x01, 0x9A, 0x94, 0x46, ++0x63, 0x44, 0x88, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xDB, 0xE7, 0xA3, 0x8E, 0xE2, 0x8E, 0x9B, 0x1A, 0x5B, 0x00, 0x01, 0x9A, ++0x94, 0x46, 0x63, 0x44, 0x82, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xD0, 0xE7, 0x01, 0x23, 0x9C, 0x46, 0xDB, 0xE7, 0x40, 0x33, ++0x83, 0x42, 0x07, 0xD0, 0x19, 0x78, 0x09, 0x29, 0xF9, 0xD1, 0x01, 0x32, 0xD2, 0xB2, 0x08, 0x39, 0x00, 0x91, 0xF4, 0xE7, ++0xEB, 0x6E, 0x59, 0x1C, 0x21, 0xD0, 0x63, 0x60, 0x75, 0x4B, 0x9A, 0x88, 0x77, 0x4B, 0x9A, 0x42, 0x02, 0xD9, 0x77, 0x4B, ++0x9C, 0x46, 0x62, 0x44, 0x76, 0x4B, 0x7B, 0x43, 0x93, 0x42, 0x00, 0xD9, 0x13, 0x00, 0x75, 0x4A, 0x93, 0x42, 0x00, 0xD2, ++0x13, 0x00, 0x23, 0x61, 0xB3, 0x68, 0x80, 0x22, 0x52, 0x05, 0x93, 0x42, 0x3B, 0xD2, 0x62, 0x68, 0xD3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0x6F, 0x4A, 0x93, 0x42, 0x34, 0xD8, 0x6E, 0x4B, 0x98, 0x47, 0xAF, 0xE0, 0x65, 0x4B, 0x1B, 0x68, 0x01, 0x33, ++0x07, 0xD0, 0x64, 0x4B, 0x18, 0x68, 0x01, 0x9B, 0x1D, 0x18, 0x63, 0x48, 0x05, 0x40, 0x65, 0x60, 0xD2, 0xE7, 0x63, 0x46, ++0x00, 0x2B, 0x03, 0xD1, 0x66, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x08, 0xD0, 0x5C, 0x4B, 0x18, 0x68, 0x80, 0x00, 0x01, 0x9B, ++0xC5, 0x18, 0x5B, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xC2, 0xE7, 0x00, 0x9B, 0x00, 0x2B, 0xBF, 0xD0, 0x5F, 0x4B, 0x1B, 0x68, ++0x01, 0x2B, 0x06, 0xD9, 0xD3, 0x01, 0x01, 0x9A, 0x9D, 0x18, 0x54, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xB4, 0xE7, 0x51, 0x4B, ++0x1B, 0x68, 0x01, 0x9A, 0xD5, 0x18, 0x50, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xAC, 0xE7, 0x4B, 0x46, 0x00, 0x2B, 0x05, 0xD1, ++0x55, 0x4A, 0x26, 0x33, 0xD3, 0x5C, 0xA3, 0x75, 0x63, 0x68, 0xE3, 0x62, 0x52, 0x4A, 0x27, 0x23, 0xD2, 0x5C, 0x18, 0x3B, ++0x1A, 0x40, 0xC0, 0x23, 0xDB, 0x01, 0x13, 0x43, 0xA3, 0x82, 0x3F, 0x23, 0xE1, 0x5C, 0x1B, 0x33, 0x42, 0x46, 0x53, 0x43, ++0x4C, 0x4A, 0x98, 0x18, 0x8A, 0x00, 0x11, 0x43, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x02, 0x80, 0x21, 0x8D, 0x49, 0x4A, ++0x9A, 0x18, 0x11, 0x80, 0x3E, 0x22, 0xA2, 0x5C, 0x0A, 0x3A, 0x01, 0x2A, 0x5A, 0xD9, 0x46, 0x4A, 0x98, 0x18, 0xA1, 0x6A, ++0x80, 0x22, 0xD2, 0x01, 0x91, 0x42, 0x00, 0xD3, 0x43, 0x49, 0x44, 0x4A, 0x0A, 0x43, 0x92, 0xB2, 0x02, 0x80, 0x00, 0x21, ++0x42, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x32, 0x7D, 0x92, 0x07, 0x14, 0xD5, 0xF1, 0x7B, 0x09, 0x02, 0xB2, 0x7B, 0x0A, 0x43, ++0x3E, 0x49, 0x59, 0x18, 0x0A, 0x80, 0x71, 0x7C, 0x09, 0x02, 0x32, 0x7C, 0x0A, 0x43, 0x3C, 0x49, 0x59, 0x18, 0x0A, 0x80, ++0xF1, 0x7C, 0x09, 0x02, 0xB2, 0x7C, 0x0A, 0x43, 0x39, 0x49, 0x59, 0x18, 0x0A, 0x80, 0x71, 0x7D, 0xB5, 0x7D, 0x38, 0x4A, ++0x97, 0x78, 0x7A, 0x1E, 0x97, 0x41, 0x30, 0x7D, 0x80, 0x07, 0xC0, 0x0F, 0x01, 0x22, 0x94, 0x46, 0x00, 0x2D, 0x00, 0xD1, ++0x84, 0x46, 0x33, 0x4A, 0x9E, 0x18, 0x09, 0x02, 0xAA, 0x01, 0x0A, 0x43, 0xFF, 0x00, 0x3A, 0x43, 0x80, 0x00, 0x02, 0x43, ++0x61, 0x46, 0x0A, 0x43, 0x32, 0x80, 0x2E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x1F, 0x21, 0x8A, 0x43, 0x11, 0x00, ++0x3E, 0x22, 0xA2, 0x5C, 0x0A, 0x43, 0x1A, 0x80, 0x20, 0x00, 0xCC, 0xF7, 0x71, 0xFF, 0x00, 0x28, 0x0D, 0xD1, 0x00, 0x23, ++0x47, 0x22, 0xA3, 0x54, 0x63, 0x87, 0x03, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x22, 0x49, 0x23, 0x4A, ++0x9A, 0x18, 0x11, 0x80, 0x9F, 0xE7, 0x22, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEE, 0xE7, ++0xE4, 0x29, 0x16, 0x00, 0x71, 0x00, 0x10, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x38, 0x27, 0x16, 0x00, 0x70, 0xA6, 0x16, 0x00, ++0x5C, 0xAB, 0x16, 0x00, 0xE4, 0xE1, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x0F, 0xC4, 0x09, 0x00, 0x00, 0x3C, 0xF6, 0xFF, 0xFF, ++0xE2, 0x04, 0x00, 0x00, 0xA6, 0x0E, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x39, 0xC2, 0x0C, 0x00, 0xF0, 0x29, 0x16, 0x00, ++0x50, 0xE0, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x7A, 0x01, 0x61, 0x40, 0x96, 0x01, 0x61, 0x40, 0x90, 0x01, 0x61, 0x40, ++0xFF, 0x3F, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xBC, 0x01, 0x61, 0x40, 0x7C, 0x01, 0x61, 0x40, 0x7E, 0x01, 0x61, 0x40, ++0x80, 0x01, 0x61, 0x40, 0xE8, 0x29, 0x16, 0x00, 0x8A, 0x01, 0x61, 0x40, 0x76, 0x01, 0x61, 0x40, 0x72, 0x3E, 0x00, 0x00, ++0x9E, 0x01, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x10, 0x23, 0x0F, 0x4A, 0x00, 0x21, 0x0F, 0x48, 0x78, 0xF7, ++0x53, 0xFC, 0x00, 0x22, 0x02, 0x70, 0x05, 0x23, 0x43, 0x70, 0x04, 0x3B, 0x83, 0x70, 0x80, 0x21, 0x89, 0x00, 0x81, 0x80, ++0xFE, 0x39, 0xFF, 0x39, 0x81, 0x71, 0xC3, 0x71, 0x0B, 0x31, 0x01, 0x72, 0x43, 0x72, 0x53, 0x31, 0x41, 0x81, 0x57, 0x39, ++0x81, 0x81, 0x83, 0x73, 0xC2, 0x73, 0xCA, 0xF7, 0x9B, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0xC0, 0x46, 0x53, 0xFD, 0x00, 0x00, ++0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x10, 0x4A, 0x11, 0x68, 0xA0, 0x23, 0x5B, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x0E, 0x4C, ++0x01, 0x23, 0x23, 0x60, 0x05, 0x20, 0x7F, 0xF7, 0x10, 0xFD, 0x00, 0x23, 0x23, 0x60, 0x0B, 0x49, 0x04, 0x22, 0x0B, 0x68, ++0x1A, 0x42, 0xFC, 0xD0, 0x06, 0x4A, 0x13, 0x68, 0x08, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x08, 0x4C, 0x01, 0x23, 0x23, 0x60, ++0x05, 0x20, 0x7F, 0xF7, 0xFE, 0xFC, 0x00, 0x23, 0x23, 0x60, 0x10, 0xBD, 0x58, 0x40, 0x34, 0x40, 0x54, 0x40, 0x34, 0x40, ++0x80, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xEB, 0xFF, 0x48, 0x20, 0x62, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x04, 0x90, 0x0F, 0x00, 0x16, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x11, 0x00, ++0x19, 0x40, 0x05, 0x91, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x04, 0x9A, 0x93, 0x00, 0xA3, 0x49, 0x8C, 0x46, 0x63, 0x44, ++0x1C, 0x68, 0xA2, 0x46, 0xA1, 0x4B, 0x63, 0x62, 0xE5, 0x6C, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD5, 0x4F, 0xE2, ++0x93, 0x00, 0x9E, 0x4A, 0x9B, 0x58, 0x1A, 0x8A, 0x00, 0x2A, 0x0E, 0xD0, 0x84, 0x23, 0xE3, 0x5A, 0x5B, 0x07, 0x00, 0xD5, ++0x36, 0xE2, 0x9A, 0x4B, 0x23, 0x61, 0xA2, 0x6E, 0x99, 0x4B, 0x1B, 0x68, 0x9A, 0x42, 0x00, 0xD1, 0x3C, 0xE2, 0x96, 0x4B, ++0x2F, 0xE2, 0x06, 0x32, 0x1A, 0x82, 0x96, 0x48, 0x7A, 0xF7, 0xD0, 0xFC, 0xEA, 0xE7, 0x96, 0x23, 0x00, 0x22, 0xE2, 0x54, ++0x00, 0x2E, 0x00, 0xD1, 0x34, 0xE2, 0x20, 0x3B, 0xE3, 0x5A, 0x00, 0x2B, 0x00, 0xD1, 0x2F, 0xE2, 0x80, 0x21, 0xC9, 0x00, ++0x8E, 0x4A, 0x02, 0x40, 0x8A, 0x42, 0x00, 0xD0, 0x28, 0xE2, 0x02, 0x07, 0x00, 0xD5, 0x25, 0xE2, 0x4A, 0x22, 0xA2, 0x5C, ++0x00, 0x2A, 0x00, 0xD0, 0x20, 0xE2, 0xA2, 0x6E, 0x5A, 0x43, 0x55, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x22, 0xA1, 0x5A, ++0x5B, 0x18, 0xA3, 0x52, 0x96, 0x23, 0x7D, 0x3A, 0xE2, 0x54, 0x7B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x81, 0x4A, 0x93, 0x42, ++0x00, 0xD8, 0x13, 0xE2, 0xE7, 0x6D, 0x2B, 0xE2, 0x46, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x26, 0xE2, 0x7C, 0x33, ++0xE3, 0x5A, 0x7E, 0x22, 0xA2, 0x5A, 0x9B, 0x18, 0x48, 0x22, 0xA2, 0x5A, 0x9B, 0x1A, 0x79, 0x4A, 0x9B, 0xB2, 0x93, 0x42, ++0x00, 0xD9, 0x19, 0xE2, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x21, 0xD1, 0x40, 0x33, 0xE3, 0x5A, 0x5D, 0x19, 0x2D, 0x01, ++0x2D, 0x09, 0xC3, 0x07, 0x00, 0xD4, 0xCA, 0xE1, 0x44, 0x23, 0xE3, 0x5A, 0x5B, 0x08, 0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, ++0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, 0xE3, 0x66, 0x46, 0x23, 0x01, 0x22, ++0xE2, 0x54, 0x48, 0x33, 0xE0, 0x5C, 0x68, 0x4B, 0x98, 0x47, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD4, 0xBB, 0xE1, ++0x7C, 0x23, 0xE2, 0x5A, 0x02, 0x33, 0xE3, 0x5A, 0xD2, 0x18, 0x48, 0x23, 0xE3, 0x5A, 0xD2, 0x1A, 0x92, 0xB2, 0x53, 0x1E, ++0x9B, 0xB2, 0x00, 0x2A, 0x0A, 0xD0, 0xA1, 0x6E, 0x2F, 0x00, 0x5E, 0x4A, 0x7F, 0x1A, 0x3F, 0x01, 0x3F, 0x09, 0x01, 0x3B, ++0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD1, 0xDB, 0xE1, 0x2F, 0x00, 0xD9, 0xE1, 0x00, 0x2B, 0x00, 0xD1, 0x5F, 0xE1, 0x68, 0xE1, ++0x01, 0x3B, 0x1B, 0x01, 0x1B, 0x09, 0x56, 0x4A, 0x94, 0x46, 0xE0, 0x44, 0x78, 0xE1, 0x2B, 0x00, 0x63, 0x60, 0x50, 0x46, ++0xCC, 0xF7, 0xFA, 0xFD, 0x00, 0x28, 0x00, 0xD1, 0x2E, 0xE1, 0xA3, 0x7D, 0x50, 0x49, 0x2F, 0x22, 0x8A, 0x5C, 0x9B, 0x18, ++0xA3, 0x75, 0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0x02, 0xD5, 0x03, 0x9B, 0x00, 0x2B, 0x4C, 0xD0, 0xA3, 0x6E, 0x9C, 0x46, ++0x65, 0x44, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x22, 0xA3, 0x5A, 0x01, 0x33, 0xA3, 0x52, 0xA3, 0x7D, 0x01, 0x33, 0xA3, 0x75, ++0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0x8C, 0xE0, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x99, 0x45, 0x00, 0xD8, ++0xF5, 0xE0, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0xCF, 0xD5, 0x72, 0x23, 0xE3, 0x5E, 0x98, 0x46, 0x63, 0x6D, 0xEE, 0x1A, ++0x36, 0x01, 0x36, 0x09, 0x77, 0xF7, 0x3C, 0xFF, 0x14, 0x23, 0x00, 0x28, 0x02, 0xD1, 0xC4, 0x33, 0x37, 0x4A, 0xD3, 0x5A, ++0x7A, 0x22, 0xA0, 0x5A, 0xC0, 0x18, 0x70, 0x43, 0xC8, 0x21, 0xC9, 0x00, 0xCE, 0xF7, 0xA2, 0xFD, 0x20, 0x30, 0x46, 0x00, ++0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0x00, 0xD5, 0x04, 0xE1, 0x74, 0x23, 0xE2, 0x5A, 0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, ++0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0xF6, 0x18, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD0, 0x05, 0xE1, 0x46, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x8E, 0xE1, 0xFF, 0xE0, 0xF7, 0xF7, 0xB1, 0xFE, 0x00, 0x28, 0xAE, 0xD0, 0x24, 0x4B, ++0x1A, 0x78, 0x01, 0x23, 0x00, 0x2A, 0x08, 0xD0, 0x22, 0x4B, 0x1B, 0x78, 0x01, 0x3B, 0x5A, 0x1E, 0x93, 0x41, 0x5B, 0x42, ++0x06, 0x22, 0x93, 0x43, 0x08, 0x33, 0xA0, 0x6E, 0x02, 0x00, 0x5A, 0x43, 0x80, 0x21, 0x49, 0x00, 0x8A, 0x42, 0x0C, 0xD9, ++0x5A, 0x1E, 0xD2, 0xB2, 0x42, 0x43, 0x8C, 0x46, 0x00, 0xE0, 0x0A, 0x00, 0x01, 0x3B, 0xDB, 0xB2, 0x62, 0x45, 0x02, 0xD9, ++0x11, 0x1A, 0x00, 0x2B, 0xF7, 0xD1, 0x55, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x21, 0x62, 0x5A, 0xD3, 0x18, 0x63, 0x52, ++0x01, 0x23, 0x03, 0x93, 0x8B, 0xE7, 0xC0, 0x46, 0xF4, 0x29, 0x16, 0x00, 0x95, 0x9D, 0x10, 0x00, 0x5C, 0xA9, 0x16, 0x00, ++0xDE, 0x0D, 0x00, 0x00, 0x64, 0xE6, 0x10, 0x00, 0xEC, 0xD3, 0x10, 0x00, 0x04, 0x04, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, ++0xFE, 0x7F, 0x00, 0x00, 0xF1, 0x12, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, ++0x8C, 0xA9, 0x16, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0x46, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, ++0x6D, 0xE7, 0x7C, 0x33, 0xE3, 0x5A, 0x7E, 0x22, 0xA2, 0x5A, 0x9B, 0x18, 0x48, 0x22, 0xA2, 0x5A, 0x9B, 0x1A, 0x9F, 0x4A, ++0x9B, 0xB2, 0x93, 0x42, 0x00, 0xD9, 0x60, 0xE7, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x26, 0xD1, 0x40, 0x33, 0xE3, 0x5A, ++0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD4, 0x76, 0xE0, 0x44, 0x23, 0xE3, 0x5A, ++0x5B, 0x08, 0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, ++0xE3, 0x6B, 0xE3, 0x66, 0x8E, 0x23, 0xE0, 0x5C, 0x8E, 0x4B, 0x98, 0x47, 0x46, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xE3, 0x6E, ++0x99, 0x46, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x01, 0xD4, 0x47, 0x23, 0xE2, 0x54, 0x7C, 0x23, 0xE2, 0x5A, 0x02, 0x33, ++0xE3, 0x5A, 0xD2, 0x18, 0x48, 0x23, 0xE3, 0x5A, 0xD2, 0x1A, 0x92, 0xB2, 0x53, 0x1E, 0x9B, 0xB2, 0x00, 0x2A, 0x0A, 0xD0, ++0xA1, 0x6E, 0x2F, 0x00, 0x81, 0x4A, 0x7F, 0x1A, 0x3F, 0x01, 0x3F, 0x09, 0x01, 0x3B, 0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD1, ++0x1D, 0xE7, 0x2F, 0x00, 0x1B, 0xE7, 0x7D, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x7C, 0x4B, 0x1B, 0x68, 0x00, 0x21, 0x1B, 0x02, ++0x0A, 0xD5, 0x7B, 0x48, 0x7A, 0xF7, 0x2E, 0xFB, 0x84, 0x23, 0xE2, 0x5A, 0x92, 0x07, 0xD2, 0x17, 0x4F, 0x3B, 0x9A, 0x43, ++0x3E, 0x32, 0x0A, 0xE0, 0x01, 0x20, 0xF8, 0xF7, 0x85, 0xFA, 0x01, 0x21, 0xEF, 0xE7, 0x84, 0x23, 0xE3, 0x5A, 0x08, 0x22, ++0x9B, 0x07, 0x00, 0xD4, 0xB6, 0xE0, 0x01, 0x21, 0x04, 0x98, 0x70, 0x4B, 0x98, 0x47, 0x05, 0x9B, 0x00, 0x2B, 0x00, 0xD1, ++0x62, 0xB6, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x8F, 0x23, 0x00, 0x22, ++0xE2, 0x54, 0xE5, 0x64, 0x0B, 0x3B, 0xE3, 0x5A, 0x9A, 0x07, 0x02, 0xD5, 0x62, 0x4A, 0x00, 0x21, 0x11, 0x70, 0xDB, 0x07, ++0xE7, 0xD5, 0x70, 0x23, 0x42, 0x46, 0xE2, 0x52, 0x1C, 0x36, 0x26, 0x65, 0xE1, 0xE7, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, ++0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, 0xE3, 0x66, 0x91, 0xE7, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, ++0x91, 0xE0, 0xA2, 0x6E, 0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, 0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0x5B, 0x08, 0xB3, 0x42, ++0xBF, 0xD9, 0x73, 0x08, 0x9B, 0x46, 0x54, 0x49, 0x18, 0x00, 0xCE, 0xF7, 0x81, 0xFC, 0x01, 0x00, 0x2B, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0x40, 0x01, 0x40, 0x1A, 0x80, 0x00, 0x40, 0x18, 0x82, 0x00, 0x80, 0x18, 0x42, 0x46, 0x59, 0x46, 0x52, 0x1A, ++0x82, 0x18, 0x90, 0x46, 0x00, 0xD5, 0x7F, 0xE6, 0x42, 0x46, 0xA2, 0x60, 0x22, 0x6E, 0x92, 0x19, 0x22, 0x61, 0x81, 0xE6, ++0xE3, 0x6E, 0x99, 0x46, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x08, 0x22, 0x99, 0x45, 0xA0, 0xD9, 0x00, 0x23, 0x03, 0x93, ++0x1C, 0x26, 0x98, 0x46, 0x9F, 0xE6, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, ++0xE3, 0x66, 0x46, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x47, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x3F, 0xE6, 0x39, 0x4B, 0x23, 0x61, ++0xA2, 0x6E, 0xA1, 0x6D, 0x00, 0x20, 0x01, 0x90, 0x00, 0x93, 0x00, 0x23, 0x20, 0x00, 0xF7, 0xF7, 0xC1, 0xFB, 0x35, 0x4B, ++0xA2, 0x6E, 0x1A, 0x60, 0x84, 0x23, 0xE0, 0x5A, 0xC3, 0x43, 0x9B, 0x07, 0x00, 0xD1, 0xC4, 0xE5, 0x7B, 0x1B, 0x1B, 0x01, ++0x1B, 0x09, 0x30, 0x4A, 0x93, 0x42, 0x13, 0xD8, 0xA1, 0x6E, 0x7E, 0x23, 0xE2, 0x5A, 0x01, 0x32, 0x92, 0xB2, 0x2C, 0x4E, ++0x4D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x03, 0x92, 0x01, 0x32, 0x92, 0xB2, 0x7B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0xB3, 0x42, ++0xF4, 0xD9, 0x7E, 0x23, 0x03, 0x9A, 0xE2, 0x52, 0xE7, 0x6D, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0xD3, 0xE5, ++0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0xAB, 0xD4, 0x14, 0x23, 0xA3, 0x75, 0xA2, 0x6E, 0x53, 0x00, 0x9B, 0x18, 0x5B, 0x00, ++0x99, 0x46, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x4B, 0x45, 0xA7, 0xD3, 0x12, 0x4B, 0x1B, 0x78, 0x01, 0x33, 0xDB, 0xB2, ++0x03, 0x2B, 0x00, 0xD9, 0x23, 0xE7, 0x0F, 0x4A, 0x13, 0x70, 0x3E, 0x22, 0x3D, 0xE7, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x00, 0xD1, 0x68, 0xE7, 0x00, 0x23, 0x47, 0x22, 0xA2, 0x5C, 0x00, 0x2A, 0x00, 0xD0, 0xFF, 0xE5, 0x44, 0x23, 0xE2, 0x5A, ++0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, 0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0xF6, 0x18, 0x62, 0xE7, 0xFE, 0x7F, 0x00, 0x00, ++0xF1, 0x12, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xE6, 0x10, 0x00, 0x58, 0x40, 0x34, 0x40, 0xF8, 0xD3, 0x10, 0x00, ++0x65, 0x17, 0x0D, 0x00, 0x71, 0x02, 0x00, 0x00, 0x42, 0x0E, 0x00, 0x00, 0x64, 0xE6, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x07, ++0xF8, 0xB5, 0x04, 0x1E, 0x32, 0xD0, 0xA1, 0xF7, 0x55, 0xFD, 0x05, 0x00, 0x8F, 0x23, 0xE6, 0x5C, 0x00, 0x2E, 0x17, 0xD1, ++0xE3, 0x6C, 0xA2, 0x6E, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x64, 0x7E, 0x22, 0xA3, 0x5A, 0x01, 0x33, ++0xA3, 0x52, 0xA3, 0x7D, 0x13, 0x49, 0x4F, 0x3A, 0x8A, 0x5C, 0x9B, 0x18, 0xA3, 0x75, 0x8E, 0x23, 0xE0, 0x5C, 0x00, 0x22, ++0x29, 0x00, 0xFF, 0xF7, 0x01, 0xFD, 0xF8, 0xBD, 0x67, 0x68, 0xA1, 0xF7, 0x35, 0xFD, 0x03, 0x00, 0x3A, 0x00, 0x31, 0x00, ++0x0B, 0x48, 0x7A, 0xF7, 0x03, 0xFA, 0x8F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0xDA, 0xD0, 0x09, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD3, 0xE7, 0x05, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0xE3, 0xE7, 0xC0, 0x46, 0x7C, 0x91, 0x0D, 0x00, 0x08, 0xD4, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x80, 0x46, 0x0F, 0x00, 0x16, 0x00, 0x1D, 0x00, 0x02, 0x21, 0x10, 0x20, 0x78, 0xF7, 0xAD, 0xF9, 0x04, 0x00, ++0x04, 0x23, 0x03, 0x70, 0xFB, 0x33, 0x43, 0x70, 0xF2, 0x3B, 0x83, 0x70, 0x43, 0x46, 0xC3, 0x70, 0x47, 0x60, 0x86, 0x60, ++0xC5, 0x60, 0x1F, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x1A, 0xD0, 0x01, 0x2B, 0x30, 0xD1, 0x1D, 0x4B, 0x1B, 0x68, 0x00, 0x2B, ++0x0D, 0xD0, 0x0A, 0x25, 0x1B, 0x4F, 0x80, 0x26, 0xB6, 0x02, 0xE8, 0x20, 0x7F, 0xF7, 0xA7, 0xF9, 0x3B, 0x68, 0x33, 0x42, ++0x25, 0xD1, 0x01, 0x3D, 0xED, 0xB2, 0x00, 0x2D, 0xF5, 0xD1, 0x00, 0x23, 0x15, 0x4A, 0x10, 0x21, 0x20, 0x00, 0x81, 0xF7, ++0x6D, 0xFC, 0x17, 0xE0, 0x13, 0x48, 0x14, 0x49, 0x01, 0x22, 0x43, 0x58, 0x1A, 0x42, 0xFC, 0xD1, 0x10, 0x4B, 0x12, 0x4A, ++0x9C, 0x50, 0x12, 0x4A, 0x99, 0x58, 0x10, 0x20, 0x01, 0x43, 0x99, 0x50, 0x81, 0x21, 0x49, 0x01, 0x5A, 0x58, 0x02, 0x43, ++0x5A, 0x50, 0x0B, 0x49, 0x5A, 0x58, 0x0F, 0x38, 0x02, 0x43, 0x5A, 0x50, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0A, 0x4B, ++0x80, 0x22, 0x92, 0x02, 0x1A, 0x60, 0xD8, 0xE7, 0xA8, 0xE5, 0x10, 0x00, 0x28, 0x25, 0x16, 0x00, 0x1C, 0x41, 0x04, 0x40, ++0x19, 0x74, 0x08, 0x00, 0x00, 0x00, 0x07, 0x40, 0x08, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, ++0x10, 0xB5, 0x01, 0x00, 0x13, 0x00, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x00, 0xD4, 0x72, 0xB6, 0x74, 0x46, 0x0E, 0x4A, ++0x94, 0x42, 0x0F, 0xD0, 0x22, 0x00, 0x0D, 0x48, 0x7A, 0xF7, 0x6A, 0xF9, 0x23, 0x00, 0x00, 0x22, 0x00, 0x21, 0x57, 0x20, ++0xFF, 0xF7, 0x7A, 0xFF, 0x09, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x05, 0xD0, 0x72, 0xB6, 0xFE, 0xE7, 0x07, 0x48, 0x7A, 0xF7, ++0x5B, 0xF9, 0x10, 0xBD, 0x06, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0xF4, 0xE7, 0xC0, 0x46, 0xB9, 0x25, 0x0D, 0x00, ++0x40, 0xD4, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, 0x18, 0xD4, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x82, 0xB0, ++0x04, 0x00, 0x0D, 0x00, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x00, 0xD4, 0x72, 0xB6, 0x76, 0x46, 0x00, 0x93, 0x33, 0x00, ++0x2A, 0x00, 0x21, 0x00, 0x09, 0x48, 0x7A, 0xF7, 0x39, 0xF9, 0x33, 0x00, 0x2A, 0x00, 0x21, 0x00, 0x57, 0x20, 0xFF, 0xF7, ++0x49, 0xFF, 0x06, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x01, 0xD0, 0x72, 0xB6, 0xFE, 0xE7, 0x04, 0x4B, 0x80, 0x22, 0xD2, 0x04, ++0x1A, 0x60, 0xF8, 0xE7, 0x64, 0xD4, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x65, 0x4B, 0x1E, 0x68, 0x07, 0x20, 0xA1, 0xF7, 0xA4, 0xF9, ++0x00, 0x28, 0x06, 0xD1, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x5F, 0x4A, ++0xD5, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0xDC, 0x00, 0xE4, 0x1A, 0x64, 0x00, 0x5C, 0x4B, 0xE3, 0x18, 0x1D, 0x88, 0xAD, 0xB2, ++0xA1, 0xF7, 0x62, 0xF9, 0x6B, 0x07, 0xE9, 0xD1, 0x3A, 0x23, 0xF3, 0x5C, 0x02, 0x2B, 0x52, 0xD0, 0x57, 0x4B, 0xE3, 0x18, ++0x1B, 0x88, 0x9B, 0xB2, 0x98, 0x46, 0x56, 0x4B, 0xE2, 0x18, 0x13, 0x88, 0x5B, 0x06, 0x1B, 0x0F, 0x02, 0x2B, 0x08, 0xD0, ++0x10, 0x88, 0x40, 0x06, 0x00, 0x0F, 0x52, 0x4B, 0xDF, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xB8, 0x47, 0x39, 0x23, ++0xF3, 0x5C, 0x00, 0x2B, 0x01, 0xD0, 0xEB, 0x05, 0x53, 0xD4, 0x10, 0x23, 0xFF, 0x22, 0x00, 0x21, 0x4B, 0x48, 0x77, 0xF7, ++0xD5, 0xFF, 0x07, 0x00, 0x00, 0x23, 0x83, 0x73, 0xFB, 0x1D, 0xBA, 0x1D, 0x02, 0x92, 0x05, 0xAA, 0x01, 0x92, 0x00, 0x22, ++0x00, 0x92, 0x3A, 0x00, 0x00, 0x21, 0x40, 0x46, 0xB0, 0xF7, 0x7C, 0xFC, 0x43, 0x4B, 0x19, 0x88, 0x43, 0x4B, 0x1B, 0x88, ++0x05, 0x9A, 0x92, 0x00, 0x09, 0x04, 0x0B, 0x43, 0xD3, 0x1A, 0x6A, 0xD4, 0xDB, 0x03, 0x5B, 0x0C, 0x7B, 0x81, 0x3F, 0x4B, ++0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x3B, 0x73, 0xED, 0x05, 0xED, 0x0F, 0x7D, 0x73, 0x38, 0x00, 0x77, 0xF7, 0xD8, 0xFF, ++0x3C, 0x23, 0xF3, 0x5C, 0x3B, 0x22, 0xB2, 0x5C, 0x9A, 0x42, 0x00, 0xD8, 0x96, 0xE7, 0x01, 0x33, 0x3C, 0x22, 0xB3, 0x54, ++0x92, 0xE7, 0x37, 0x33, 0xF3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x8D, 0xE7, 0xEB, 0x05, 0x00, 0xD4, 0x8A, 0xE7, 0x07, 0x20, ++0xA1, 0xF7, 0x2A, 0xF9, 0x00, 0x28, 0x00, 0xD1, 0x84, 0xE7, 0x25, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, ++0x9B, 0x1A, 0x5B, 0x00, 0x22, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0xA1, 0xF7, 0xEE, 0xF8, 0x76, 0xE7, 0x07, 0x20, ++0xA1, 0xF7, 0x16, 0xF9, 0x00, 0x28, 0xA6, 0xD0, 0x1B, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, ++0x5B, 0x00, 0x19, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x52, 0x07, 0x02, 0xD0, 0xA1, 0xF7, 0xDA, 0xF8, 0x97, 0xE7, 0x1D, 0x4A, ++0x9A, 0x18, 0x11, 0x88, 0x8A, 0xB2, 0x91, 0x46, 0x1B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0xDB, 0x08, 0x9B, 0x46, ++0xFF, 0x23, 0x5A, 0x46, 0x1A, 0x40, 0x92, 0x46, 0x13, 0x00, 0x10, 0x33, 0xFF, 0x22, 0x00, 0x21, 0x0F, 0x48, 0x77, 0xF7, ++0x5D, 0xFF, 0x07, 0x00, 0x5B, 0x46, 0x83, 0x73, 0x12, 0x49, 0x49, 0x44, 0x0F, 0x30, 0x52, 0x46, 0xCE, 0xF7, 0x4C, 0xFE, ++0xA1, 0xF7, 0xB8, 0xF8, 0x7E, 0xE7, 0x80, 0x22, 0x52, 0x05, 0x94, 0x46, 0x63, 0x44, 0x8F, 0xE7, 0x18, 0x27, 0x16, 0x00, ++0x20, 0xA3, 0x16, 0x00, 0x92, 0x69, 0x61, 0x40, 0x9C, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, ++0x01, 0x05, 0x00, 0x00, 0xFA, 0x67, 0x61, 0x40, 0xF8, 0x67, 0x61, 0x40, 0x98, 0x69, 0x61, 0x40, 0x9A, 0x69, 0x61, 0x40, ++0x96, 0x69, 0x61, 0x40, 0x00, 0x00, 0x61, 0x40, 0x70, 0xB5, 0xA1, 0xF7, 0x5F, 0xFB, 0x05, 0x00, 0x0F, 0x4B, 0x1C, 0x68, ++0x00, 0x2C, 0x06, 0xD1, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x70, 0xBD, 0xFF, 0xF7, ++0x03, 0xFF, 0x01, 0x21, 0x20, 0x00, 0xCC, 0xF7, 0x81, 0xFB, 0x3A, 0x23, 0xE3, 0x5C, 0x02, 0x2B, 0x06, 0xD0, 0x07, 0x4B, ++0x1B, 0x7D, 0xA3, 0x75, 0x65, 0x60, 0x06, 0x4B, 0x98, 0x47, 0xED, 0xE7, 0x05, 0x4B, 0x98, 0x47, 0xEA, 0xE7, 0xC0, 0x46, ++0x18, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0xE5, 0xC1, 0x0A, 0x00, 0x99, 0xC1, 0x0A, 0x00, ++0x70, 0xB5, 0x0D, 0x00, 0x14, 0x00, 0x07, 0x29, 0x06, 0xD0, 0x11, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, ++0x28, 0x00, 0xB0, 0x47, 0x01, 0x2C, 0x0E, 0xD9, 0x04, 0x2C, 0x0F, 0xD1, 0x0C, 0x4B, 0x1C, 0x68, 0x01, 0x21, 0x20, 0x00, ++0xCC, 0xF7, 0x52, 0xFB, 0x3A, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x20, 0x00, 0x08, 0x4B, 0x98, 0x47, 0x01, 0xE0, 0xFF, 0xF7, ++0xB3, 0xFF, 0x70, 0xBD, 0x03, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0x28, 0x00, 0xB0, 0x47, 0xF6, 0xE7, ++0x28, 0x19, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0xD1, 0xC2, 0x0A, 0x00, 0x10, 0xB5, 0x01, 0x28, 0x00, 0xD0, 0x10, 0xBD, ++0x00, 0x29, 0xFC, 0xD0, 0x04, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xF8, 0xD0, 0x03, 0x4A, 0xDA, 0x61, 0x03, 0x48, 0x79, 0xF7, ++0xCB, 0xFF, 0xF2, 0xE7, 0x24, 0x27, 0x16, 0x00, 0x85, 0x04, 0x10, 0x00, 0x94, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x1E, 0x4B, ++0x1E, 0x4A, 0x13, 0x60, 0x80, 0x22, 0x52, 0x00, 0x9C, 0x5C, 0x1D, 0x4B, 0xE3, 0x18, 0x1B, 0x01, 0x1A, 0x88, 0xD2, 0x08, ++0x06, 0x21, 0x11, 0x42, 0x08, 0xD1, 0x19, 0x88, 0x89, 0x06, 0x49, 0x0F, 0x18, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x20, 0x00, 0xA8, 0x47, 0x13, 0x4B, 0x1A, 0x68, 0x81, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, 0x12, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0D, 0x4B, 0x1B, 0x68, 0x22, 0x01, 0x9B, 0x18, 0x1B, 0x7B, ++0x00, 0x2B, 0x05, 0xD1, 0x0B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x06, 0x4B, 0x1A, 0x68, ++0x23, 0x01, 0xD3, 0x18, 0x5D, 0x68, 0x00, 0x2D, 0x03, 0xD0, 0x99, 0x68, 0x18, 0x68, 0x02, 0x22, 0xA8, 0x47, 0x70, 0xBD, ++0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0x00, 0x10, 0x06, 0x04, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0xFF, 0x23, ++0x9B, 0x00, 0x98, 0x42, 0x08, 0xD9, 0x05, 0x4B, 0x59, 0x80, 0x00, 0x24, 0x21, 0x00, 0x04, 0x48, 0x79, 0xF7, 0x72, 0xFF, ++0x20, 0x00, 0x10, 0xBD, 0x11, 0x24, 0xF7, 0xE7, 0x54, 0x2A, 0x16, 0x00, 0xA0, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, ++0x0D, 0x00, 0x81, 0x88, 0x00, 0x88, 0xFF, 0xF7, 0xE5, 0xFF, 0x01, 0x1E, 0x04, 0xD0, 0x28, 0x00, 0xFC, 0xF7, 0x90, 0xFE, ++0x00, 0x20, 0x70, 0xBD, 0xE1, 0x88, 0xA0, 0x78, 0xCB, 0xF7, 0xB6, 0xFE, 0x01, 0x00, 0xF4, 0xE7, 0xF0, 0xB5, 0xCE, 0x46, ++0x47, 0x46, 0x80, 0xB5, 0x89, 0xB0, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x23, 0x00, 0x21, 0x26, 0x48, 0x77, 0xF7, 0x46, 0xFE, ++0x80, 0x46, 0x00, 0x23, 0x43, 0x80, 0xB1, 0x79, 0x23, 0x48, 0x79, 0xF7, 0x43, 0xFF, 0xB3, 0x79, 0x00, 0x2B, 0x2A, 0xD1, ++0x60, 0x24, 0x6B, 0x46, 0xDD, 0x1D, 0x16, 0x23, 0x99, 0x46, 0x1F, 0x4F, 0x07, 0xE0, 0x03, 0x23, 0x42, 0x46, 0x13, 0x70, ++0x24, 0xE0, 0x01, 0x34, 0xE4, 0xB2, 0x68, 0x2C, 0x20, 0xD0, 0x4B, 0x46, 0x2B, 0x70, 0x02, 0xAA, 0x29, 0x00, 0x20, 0x00, ++0x3B, 0x68, 0x98, 0x47, 0x00, 0x28, 0xF2, 0xD1, 0x06, 0x22, 0x02, 0xA9, 0x30, 0x00, 0xCE, 0xF7, 0xF3, 0xFC, 0x00, 0x28, ++0xEB, 0xD1, 0x12, 0x4B, 0x9B, 0x68, 0x20, 0x00, 0x98, 0x47, 0x00, 0x28, 0xE1, 0xD1, 0x43, 0x46, 0x5B, 0x88, 0x01, 0x33, ++0x42, 0x46, 0x53, 0x80, 0x04, 0xE0, 0x01, 0x2B, 0x0B, 0xD0, 0x12, 0x23, 0x42, 0x46, 0x13, 0x70, 0x40, 0x46, 0xC9, 0xF7, ++0x69, 0xFC, 0x00, 0x20, 0x09, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x43, 0x46, 0x5B, 0x88, 0x08, 0x33, ++0x42, 0x46, 0x53, 0x80, 0xF0, 0xE7, 0xC0, 0x46, 0x01, 0x11, 0x00, 0x00, 0xAC, 0xD4, 0x10, 0x00, 0x94, 0x92, 0x16, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x85, 0xB0, 0x0C, 0x00, 0x16, 0x00, 0x17, 0x0A, ++0xBA, 0x00, 0x91, 0x4B, 0xD5, 0x58, 0x50, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xD6, 0xE0, 0x4B, 0x78, 0x5B, 0x08, ++0x98, 0x46, 0x7F, 0x2B, 0x11, 0xD0, 0x01, 0x93, 0x00, 0x22, 0x19, 0x00, 0x8A, 0x48, 0x79, 0xF7, 0xDD, 0xFE, 0x43, 0x46, ++0x7E, 0x2B, 0x56, 0xD1, 0x36, 0x3B, 0xEB, 0x5C, 0x00, 0x2B, 0x43, 0xD0, 0x00, 0x23, 0x9B, 0x46, 0x7E, 0x33, 0x01, 0x93, ++0x0C, 0xE0, 0x8B, 0x78, 0x9B, 0x46, 0x1A, 0x00, 0x7F, 0x21, 0x81, 0x48, 0x79, 0xF7, 0xCA, 0xFE, 0x7F, 0x23, 0x01, 0x93, ++0x48, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x43, 0xD0, 0xFB, 0xB2, 0x99, 0x46, 0x61, 0x78, 0x4F, 0x08, 0x59, 0x29, 0x00, 0xD8, ++0xE0, 0xE0, 0x7F, 0x2F, 0x05, 0xD1, 0xA3, 0x78, 0x9A, 0x46, 0x0D, 0x2B, 0x55, 0xD8, 0x0B, 0x2B, 0x55, 0xD8, 0x07, 0x23, ++0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x9A, 0x46, 0x23, 0x78, 0x52, 0x46, 0x13, 0x70, 0x14, 0x23, 0x32, 0x00, 0x31, 0x00, ++0x70, 0x48, 0x77, 0xF7, 0xA3, 0xFD, 0x07, 0x00, 0x61, 0x1C, 0x52, 0x46, 0x82, 0xF7, 0x30, 0xF9, 0x02, 0x28, 0x75, 0xD0, ++0x00, 0x28, 0x00, 0xD1, 0xA9, 0xE0, 0x04, 0x28, 0x00, 0xD0, 0x99, 0xE0, 0xFB, 0x22, 0x43, 0x46, 0x15, 0x3B, 0x13, 0x42, ++0x00, 0xD1, 0xB1, 0xE0, 0x19, 0x24, 0x6F, 0xE0, 0x36, 0x33, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, ++0x0C, 0x22, 0x7E, 0x21, 0x9F, 0xF7, 0xC7, 0xFA, 0x00, 0x23, 0x9B, 0x46, 0x7E, 0x33, 0x01, 0x93, 0xBE, 0xE7, 0x00, 0x23, ++0x9B, 0x46, 0xB7, 0xE7, 0x59, 0x46, 0x40, 0x46, 0x82, 0xF7, 0x96, 0xF8, 0x00, 0x28, 0xB5, 0xD1, 0x43, 0x46, 0x7F, 0x2B, ++0x0A, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, 0x0C, 0x22, 0x41, 0x46, 0x9F, 0xF7, ++0xAC, 0xFA, 0x5A, 0xE0, 0x49, 0x3B, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, 0x0C, 0x22, 0x59, 0x46, ++0x9F, 0xF7, 0xB0, 0xFA, 0x4F, 0xE0, 0x15, 0x2B, 0xA9, 0xD1, 0x4B, 0x46, 0x9B, 0x00, 0x48, 0x4A, 0x9B, 0x58, 0xB2, 0x22, ++0x92, 0x00, 0x9A, 0x5C, 0x00, 0x2A, 0xA0, 0xD0, 0xCA, 0x07, 0x9E, 0xD5, 0x46, 0x4A, 0x9A, 0x5C, 0xBA, 0x42, 0x14, 0xD1, ++0x7F, 0x2F, 0x98, 0xD1, 0x44, 0x4A, 0x9B, 0x5C, 0x53, 0x45, 0x94, 0xD0, 0x4B, 0x46, 0x1B, 0x02, 0x01, 0x20, 0x18, 0x43, ++0x78, 0xF7, 0x16, 0xF9, 0x00, 0x28, 0x30, 0xD0, 0x01, 0x23, 0x2A, 0x22, 0x51, 0x46, 0x48, 0x46, 0x9F, 0xF7, 0x8A, 0xFA, ++0x29, 0xE0, 0x4B, 0x46, 0x1B, 0x02, 0x01, 0x20, 0x18, 0x43, 0x78, 0xF7, 0x07, 0xF9, 0x00, 0x28, 0x21, 0xD0, 0x7F, 0x2F, ++0xEE, 0xD0, 0x01, 0x23, 0x2A, 0x22, 0x39, 0x00, 0x48, 0x46, 0x9F, 0xF7, 0x6A, 0xFA, 0x18, 0xE0, 0x33, 0x4B, 0xDC, 0x6E, ++0x00, 0x23, 0x00, 0x22, 0x01, 0x99, 0x08, 0x00, 0xA0, 0x47, 0x1E, 0x24, 0x38, 0x00, 0x0C, 0x38, 0x77, 0xF7, 0x69, 0xFD, ++0x43, 0x46, 0x7F, 0x2B, 0x1C, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0x22, 0x00, 0x41, 0x46, ++0x48, 0x46, 0x9F, 0xF7, 0x50, 0xFA, 0x8A, 0x23, 0xFF, 0x33, 0xEB, 0x5C, 0x00, 0x2B, 0x03, 0xD0, 0x25, 0x4B, 0xEB, 0x5C, ++0x00, 0x2B, 0x18, 0xD1, 0x00, 0x20, 0x05, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, ++0x1E, 0x24, 0xDB, 0xE7, 0x49, 0x3B, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0x22, 0x00, 0x59, 0x46, 0x48, 0x46, ++0x9F, 0xF7, 0x42, 0xFA, 0xE1, 0xE7, 0x38, 0x00, 0x77, 0xF7, 0x16, 0xFD, 0xDD, 0xE7, 0xAA, 0x8D, 0xEB, 0x8D, 0xD2, 0x1A, ++0x31, 0x00, 0x16, 0x48, 0x77, 0xF7, 0x24, 0xFC, 0xAA, 0x8D, 0x31, 0x00, 0x14, 0x48, 0x77, 0xF7, 0x1F, 0xFC, 0xD9, 0xE7, ++0x38, 0x00, 0x0C, 0x38, 0x77, 0xF7, 0x29, 0xFD, 0x1A, 0x24, 0xC0, 0xE7, 0x12, 0x2F, 0x00, 0xD8, 0x23, 0xE7, 0x3A, 0x00, ++0x13, 0x3A, 0xD2, 0xB2, 0x01, 0x23, 0x93, 0x40, 0x0C, 0x4A, 0x13, 0x42, 0x00, 0xD1, 0x1A, 0xE7, 0x00, 0x23, 0x9A, 0x46, ++0x6D, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xBC, 0xD4, 0x10, 0x00, 0x01, 0x06, 0x00, 0x00, 0xC6, 0x02, 0x00, 0x00, ++0xC7, 0x02, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xAF, 0x02, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x0A, 0x06, 0x00, 0x00, ++0x31, 0x00, 0x00, 0x03, 0x30, 0xB5, 0x87, 0xB0, 0x1E, 0x4C, 0x23, 0x7B, 0x03, 0x22, 0x13, 0x43, 0x23, 0x73, 0x03, 0xAD, ++0x21, 0x00, 0x27, 0x31, 0x03, 0x22, 0x28, 0x00, 0xCE, 0xF7, 0x9E, 0xFB, 0xE3, 0x89, 0xAB, 0x80, 0x23, 0x8A, 0xEB, 0x80, ++0xA3, 0x7C, 0x2B, 0x72, 0x23, 0x7F, 0x6B, 0x72, 0x28, 0x00, 0xA2, 0xF7, 0x3F, 0xFB, 0x23, 0x00, 0x3C, 0x33, 0x00, 0x24, ++0x1A, 0x78, 0x00, 0x2A, 0x06, 0xD0, 0x01, 0x34, 0xE4, 0xB2, 0x09, 0x33, 0x07, 0x2C, 0xF7, 0xD1, 0x07, 0xB0, 0x30, 0xBD, ++0x06, 0x2C, 0xFB, 0xD8, 0x01, 0xA8, 0x0B, 0x4B, 0x1A, 0x8B, 0x02, 0x80, 0x5A, 0x8B, 0x42, 0x80, 0x5B, 0x7F, 0x03, 0x71, ++0x44, 0x71, 0x08, 0x4A, 0xD0, 0x23, 0xD3, 0x58, 0x98, 0x47, 0x00, 0x28, 0xEC, 0xD1, 0xE3, 0x00, 0x1B, 0x19, 0x03, 0x4C, ++0xE4, 0x18, 0x3C, 0x34, 0x02, 0x23, 0x23, 0x70, 0xE4, 0xE7, 0xC0, 0x46, 0x68, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x10, 0xB5, 0x07, 0x4C, 0xA0, 0x47, 0x86, 0xF7, 0x97, 0xF8, 0x00, 0x28, 0x01, 0xD1, 0x00, 0x20, 0x10, 0xBD, 0xFF, 0xF7, ++0xB1, 0xFF, 0x03, 0x48, 0x79, 0xF7, 0x66, 0xFD, 0xF7, 0xE7, 0xC0, 0x46, 0xDD, 0x90, 0x0A, 0x00, 0xCC, 0xD4, 0x10, 0x00, ++0x00, 0xB5, 0x83, 0xB0, 0x01, 0xAA, 0x01, 0x23, 0x0B, 0x40, 0x30, 0x21, 0x0B, 0x43, 0x13, 0x70, 0x11, 0x00, 0x9F, 0xF7, ++0x41, 0xF9, 0x03, 0xB0, 0x00, 0xBD, 0x00, 0x00, 0x30, 0xB5, 0x83, 0xB0, 0x04, 0x00, 0x00, 0x0A, 0x82, 0x00, 0x0E, 0x4B, ++0xD2, 0x58, 0x3C, 0x23, 0xD3, 0x5C, 0x02, 0x2B, 0x07, 0xD0, 0x96, 0x22, 0x52, 0x00, 0x21, 0x00, 0x0A, 0x48, 0x77, 0xF7, ++0x7D, 0xFB, 0x03, 0xB0, 0x30, 0xBD, 0x6B, 0x46, 0x9D, 0x1D, 0xC0, 0xB2, 0x00, 0x22, 0x29, 0x00, 0x89, 0xF7, 0xEE, 0xFA, ++0x28, 0x88, 0x79, 0xF7, 0x95, 0xFD, 0x40, 0x00, 0x02, 0x00, 0x2D, 0x32, 0xFF, 0x32, 0xEA, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0x05, 0x06, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x00, 0x0A, 0x82, 0x00, 0x07, 0x4B, 0xD2, 0x58, 0x36, 0x23, 0xD1, 0x5C, ++0xC0, 0xB2, 0xFF, 0xF7, 0xC1, 0xFF, 0x20, 0x00, 0xFF, 0xF7, 0xCC, 0xFF, 0x32, 0x21, 0x20, 0x00, 0x77, 0xF7, 0x8C, 0xFF, ++0x10, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x70, 0xB5, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x17, 0x4B, 0xD6, 0x58, ++0x20, 0x00, 0x77, 0xF7, 0xDF, 0xFF, 0x03, 0x00, 0x19, 0x28, 0x1D, 0xD8, 0x01, 0x38, 0xC0, 0xB2, 0x14, 0x28, 0x06, 0xD8, ++0x02, 0x20, 0x01, 0x2B, 0x15, 0xD1, 0x3C, 0x23, 0xF3, 0x5C, 0x02, 0x2B, 0x16, 0xD0, 0x08, 0x23, 0x14, 0x22, 0x00, 0x21, ++0x0D, 0x48, 0x77, 0xF7, 0xF5, 0xFB, 0x0C, 0x23, 0x03, 0x70, 0x80, 0x35, 0x45, 0x80, 0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, ++0xF3, 0x5C, 0x03, 0x71, 0xC9, 0xF7, 0x4A, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x02, 0x20, 0x66, 0x2B, 0xFB, 0xD1, 0xE4, 0xE7, ++0x20, 0x00, 0xFF, 0xF7, 0xB9, 0xFF, 0x00, 0x20, 0xF5, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, ++0x70, 0xB5, 0x82, 0xB0, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x24, 0x4B, 0xD6, 0x58, 0x20, 0x00, 0x77, 0xF7, 0xA6, 0xFF, ++0x01, 0x28, 0x16, 0xD0, 0x04, 0xD9, 0x16, 0x38, 0xC3, 0xB2, 0x02, 0x20, 0x03, 0x2B, 0x0E, 0xD8, 0x06, 0x23, 0x1C, 0x22, ++0x00, 0x21, 0x1D, 0x48, 0x77, 0xF7, 0xC2, 0xFB, 0x02, 0x23, 0x03, 0x70, 0x80, 0x35, 0x45, 0x80, 0x00, 0x23, 0x83, 0x80, ++0xC9, 0xF7, 0x1A, 0xFA, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x36, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x0E, 0xD1, 0x01, 0xA9, ++0x0A, 0x33, 0x0B, 0x70, 0xE8, 0xB2, 0x9F, 0xF7, 0x9D, 0xF8, 0x20, 0x00, 0xFF, 0xF7, 0x5C, 0xFF, 0x06, 0x21, 0x20, 0x00, ++0x77, 0xF7, 0x1C, 0xFF, 0x00, 0x20, 0xEA, 0xE7, 0x06, 0x23, 0x1C, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x77, 0xF7, 0x9E, 0xFB, ++0x04, 0x00, 0x00, 0x23, 0x03, 0x70, 0x2B, 0x00, 0x80, 0x33, 0x43, 0x80, 0xE8, 0xB2, 0xA8, 0xF7, 0x3D, 0xFF, 0x00, 0x04, ++0x40, 0x0C, 0xA0, 0x80, 0x20, 0x00, 0xC9, 0xF7, 0xEF, 0xF9, 0x00, 0x20, 0xD3, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x03, 0x11, 0x00, 0x00, 0x70, 0xB5, 0x14, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x14, 0x4A, 0x9D, 0x58, 0x20, 0x00, 0x77, 0xF7, ++0x55, 0xFF, 0x00, 0x28, 0x1E, 0xD0, 0x16, 0x38, 0xC3, 0xB2, 0x00, 0x20, 0x03, 0x2B, 0x13, 0xD9, 0x43, 0x23, 0x01, 0x22, ++0xEA, 0x54, 0x07, 0x3B, 0xEB, 0x5C, 0x02, 0x2B, 0x0D, 0xD0, 0x37, 0x23, 0xE9, 0x5C, 0x20, 0x00, 0x8B, 0xF7, 0x32, 0xF8, ++0x00, 0x28, 0x0D, 0xD0, 0x37, 0x23, 0xE9, 0x5C, 0x20, 0x00, 0x90, 0xF7, 0x57, 0xFF, 0x00, 0x20, 0x70, 0xBD, 0x20, 0x00, ++0x89, 0xF7, 0xFE, 0xFD, 0x02, 0x20, 0xF9, 0xE7, 0x00, 0x20, 0xF7, 0xE7, 0x02, 0x20, 0xF5, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0x10, 0xB5, 0x80, 0x00, 0x0F, 0x4B, 0xC4, 0x58, 0x8E, 0xF7, 0xD4, 0xFC, 0x03, 0x00, 0x01, 0x20, 0x0B, 0x2B, 0x13, 0xD9, ++0x11, 0x2B, 0x06, 0xD8, 0x20, 0x00, 0x54, 0x30, 0x00, 0x21, 0x9E, 0xF7, 0x53, 0xFF, 0x00, 0x28, 0x0B, 0xD1, 0x20, 0x00, ++0x54, 0x30, 0x01, 0x21, 0x9E, 0xF7, 0x4C, 0xFF, 0x43, 0x42, 0x58, 0x41, 0x40, 0x42, 0x03, 0x23, 0x98, 0x43, 0x05, 0x30, ++0x10, 0xBD, 0x03, 0x20, 0xFC, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x02, 0x00, 0x00, 0x29, 0x16, 0xD1, 0x01, 0x23, ++0x03, 0x40, 0x58, 0x42, 0x43, 0x41, 0x58, 0x42, 0x20, 0x4B, 0x18, 0x40, 0x20, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x06, 0x23, ++0x1A, 0x40, 0x04, 0x2A, 0x02, 0xD0, 0x02, 0x2A, 0x03, 0xD0, 0x70, 0x47, 0x80, 0x04, 0x80, 0x0C, 0xFB, 0xE7, 0x1B, 0x4B, ++0x18, 0x40, 0xF8, 0xE7, 0x18, 0x23, 0x19, 0x00, 0x01, 0x40, 0x03, 0x42, 0x21, 0xD0, 0x08, 0x29, 0x0E, 0xD0, 0x60, 0x23, ++0x03, 0x40, 0x40, 0x2B, 0x21, 0xD0, 0x20, 0x3B, 0x18, 0x00, 0x43, 0x1E, 0x98, 0x41, 0x40, 0x42, 0x12, 0x4B, 0x18, 0x40, ++0x12, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xE2, 0xE7, 0x48, 0x33, 0x03, 0x40, 0x60, 0x2B, 0x0E, 0xD0, 0x40, 0x2B, 0x0E, 0xD0, ++0x20, 0x3B, 0x18, 0x00, 0x43, 0x1E, 0x98, 0x41, 0x40, 0x42, 0x0C, 0x4B, 0x18, 0x40, 0x0C, 0x4B, 0x9C, 0x46, 0x60, 0x44, ++0xD1, 0xE7, 0x0B, 0x48, 0xCF, 0xE7, 0x0B, 0x48, 0xCD, 0xE7, 0x0B, 0x48, 0xCB, 0xE7, 0x0B, 0x48, 0xC9, 0xE7, 0xC0, 0x46, ++0xF0, 0x77, 0xFF, 0xFF, 0x1E, 0xFF, 0x00, 0x00, 0xFF, 0x33, 0x00, 0x00, 0x00, 0xCD, 0xFF, 0xFF, 0x08, 0x33, 0x00, 0x00, ++0x00, 0xEF, 0xFF, 0xFF, 0x0C, 0x33, 0x00, 0x00, 0x0E, 0x33, 0x00, 0x00, 0x0C, 0x22, 0x00, 0x00, 0x0C, 0x32, 0x00, 0x00, ++0x08, 0x30, 0x00, 0x00, 0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x77, 0xF7, 0xA4, 0xFE, 0x03, 0x00, 0x01, 0x28, ++0x0A, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x06, 0xD9, 0x16, 0x3B, 0xDB, 0xB2, 0x03, 0x30, 0x98, 0x42, 0x80, 0x41, 0x40, 0x42, ++0x40, 0x00, 0x70, 0xBD, 0x24, 0x0A, 0xA2, 0x00, 0x0F, 0x4B, 0xD6, 0x58, 0x3F, 0x23, 0xF1, 0x5C, 0x68, 0x78, 0xFF, 0xF7, ++0x83, 0xFF, 0x70, 0x85, 0xE4, 0xB2, 0x20, 0x00, 0xFF, 0xF7, 0x5A, 0xFF, 0x9E, 0xF7, 0x5C, 0xFF, 0x71, 0x8D, 0x01, 0x22, ++0x9E, 0xF7, 0x08, 0xFD, 0x31, 0x8C, 0x01, 0x22, 0x9E, 0xF7, 0x04, 0xFD, 0x01, 0x00, 0x33, 0x8C, 0x00, 0x20, 0x8B, 0x42, ++0xE1, 0xD0, 0x20, 0x00, 0xA8, 0xF7, 0xA2, 0xFF, 0x00, 0x20, 0xDC, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x05, 0x00, 0x08, 0x00, 0x0E, 0x0A, 0xB2, 0x00, 0x29, 0x4B, 0xD4, 0x58, 0x77, 0xF7, 0x67, 0xFE, 0x00, 0x28, ++0x03, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x03, 0xD8, 0x00, 0x20, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2B, 0x78, ++0x01, 0x27, 0x3B, 0x40, 0x39, 0x22, 0xA3, 0x54, 0x54, 0x23, 0x98, 0x46, 0xA0, 0x44, 0x69, 0x1C, 0x31, 0x3A, 0x40, 0x46, ++0xCE, 0xF7, 0x72, 0xF9, 0x57, 0x22, 0xA3, 0x5C, 0x04, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x02, 0x32, 0xA3, 0x5C, 0x3E, 0x31, ++0x8B, 0x43, 0xA3, 0x54, 0x29, 0x78, 0x39, 0x40, 0xF0, 0xB2, 0x9F, 0xF7, 0x2D, 0xF9, 0x09, 0x21, 0x40, 0x46, 0x9E, 0xF7, ++0x73, 0xFE, 0x00, 0x28, 0x0D, 0xD1, 0x85, 0xF7, 0x8F, 0xFE, 0x00, 0x28, 0x02, 0xD0, 0x4F, 0x23, 0x01, 0x22, 0xE2, 0x54, ++0xBC, 0x22, 0x52, 0x00, 0xA3, 0x5C, 0x01, 0x21, 0x0B, 0x43, 0xA3, 0x54, 0xCB, 0xE7, 0x3A, 0x21, 0x40, 0x46, 0x9E, 0xF7, ++0x5F, 0xFE, 0x02, 0x00, 0x53, 0x1E, 0x9A, 0x41, 0x4F, 0x23, 0xE2, 0x54, 0x00, 0x23, 0x00, 0x28, 0x04, 0xD0, 0x05, 0x4A, ++0x05, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0xDB, 0x0F, 0x4F, 0x22, 0xA3, 0x54, 0xDD, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x7C, 0x1E, 0x16, 0x00, 0xA2, 0x02, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x0B, 0x0A, ++0x98, 0x46, 0x9A, 0x00, 0x32, 0x4B, 0xD4, 0x58, 0x27, 0x00, 0x54, 0x37, 0x41, 0x1C, 0x08, 0x22, 0x38, 0x00, 0xCE, 0xF7, ++0x23, 0xF9, 0x57, 0x22, 0xA3, 0x5C, 0x04, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x02, 0x32, 0xA3, 0x5C, 0x3E, 0x31, 0x8B, 0x43, ++0xA3, 0x54, 0x28, 0x00, 0x77, 0xF7, 0xF4, 0xFD, 0x14, 0x28, 0x13, 0xD0, 0x07, 0xD9, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, ++0x05, 0xD8, 0x00, 0x20, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x00, 0x28, 0xF9, 0xD0, 0x28, 0x00, 0x77, 0xF7, 0xE4, 0xFD, ++0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0x7D, 0xF7, 0xB1, 0xF8, 0xF0, 0xE7, 0x29, 0x00, 0x1D, 0x48, 0x77, 0xF7, 0xBC, 0xF9, ++0x32, 0x78, 0x01, 0x23, 0x13, 0x40, 0x3A, 0x22, 0xA3, 0x54, 0x09, 0x21, 0x38, 0x00, 0x9E, 0xF7, 0x07, 0xFE, 0x00, 0x28, ++0x11, 0xD1, 0xBC, 0x22, 0x52, 0x00, 0xA3, 0x5C, 0x01, 0x21, 0x0B, 0x43, 0xA3, 0x54, 0x3F, 0x21, 0x38, 0x00, 0x9E, 0xF7, ++0xFB, 0xFD, 0x00, 0x28, 0x19, 0xD0, 0x01, 0x22, 0x41, 0x46, 0x28, 0x00, 0x91, 0xF7, 0xE6, 0xF8, 0xCF, 0xE7, 0x3A, 0x21, ++0x38, 0x00, 0x9E, 0xF7, 0xEF, 0xFD, 0x02, 0x00, 0x53, 0x1E, 0x9A, 0x41, 0x4F, 0x23, 0xE2, 0x54, 0x00, 0x23, 0x00, 0x28, ++0x04, 0xD0, 0x08, 0x4A, 0x08, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0xDB, 0x0F, 0x4F, 0x22, 0xA3, 0x54, 0xD9, 0xE7, 0x01, 0x21, ++0x28, 0x00, 0x77, 0xF7, 0x45, 0xFD, 0xB6, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x05, 0x06, 0x00, 0x00, 0x7C, 0x1E, 0x16, 0x00, ++0xA2, 0x02, 0x00, 0x00, 0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0x0E, 0x0A, ++0xB2, 0x00, 0x35, 0x4B, 0xD7, 0x58, 0x02, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xBB, 0x54, 0x36, 0x23, 0xFB, 0x5C, ++0x98, 0x46, 0x33, 0x01, 0x9B, 0x1B, 0x9B, 0x00, 0x2F, 0x4A, 0xD3, 0x18, 0x5B, 0x7B, 0x99, 0x46, 0x08, 0x00, 0x77, 0xF7, ++0x7F, 0xFD, 0x02, 0x00, 0x19, 0x28, 0x1B, 0xD8, 0x01, 0x38, 0xC0, 0xB2, 0x14, 0x28, 0x47, 0xD8, 0x02, 0x20, 0x01, 0x2A, ++0x47, 0xD1, 0x3C, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x36, 0xD1, 0x7B, 0x8C, 0x5B, 0x07, 0x33, 0xD5, 0xA3, 0x88, 0x62, 0x88, ++0x61, 0x78, 0x20, 0x89, 0x01, 0x90, 0xE0, 0x88, 0x00, 0x90, 0x21, 0x4C, 0x94, 0x20, 0x24, 0x58, 0x28, 0x00, 0xA0, 0x47, ++0x00, 0x20, 0x32, 0xE0, 0x2E, 0x28, 0x2F, 0xD1, 0x01, 0x23, 0x4A, 0x46, 0x5A, 0x40, 0x13, 0x00, 0x42, 0x46, 0x5A, 0x40, ++0x13, 0x00, 0x39, 0x22, 0xBA, 0x5C, 0xDB, 0xB2, 0x9A, 0x42, 0x0D, 0xD1, 0xA3, 0x88, 0x62, 0x88, 0x61, 0x78, 0x20, 0x89, ++0x01, 0x90, 0xE0, 0x88, 0x00, 0x90, 0x13, 0x4C, 0x94, 0x20, 0x24, 0x58, 0x28, 0x00, 0xA0, 0x47, 0x00, 0x20, 0x16, 0xE0, ++0x22, 0x78, 0x01, 0x23, 0x13, 0x40, 0xF0, 0xB2, 0x23, 0x22, 0x17, 0x21, 0x9E, 0xF7, 0xA9, 0xFE, 0x00, 0x20, 0x0C, 0xE0, ++0x22, 0x78, 0x01, 0x23, 0x13, 0x40, 0xF0, 0xB2, 0x24, 0x22, 0x17, 0x21, 0x9E, 0xF7, 0x9F, 0xFE, 0x00, 0x20, 0x02, 0xE0, ++0x00, 0x20, 0x00, 0xE0, 0x02, 0x20, 0x03, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x64, 0xA2, 0x16, 0x00, ++0xC0, 0xA0, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x04, 0x00, 0x08, 0x00, 0x0D, 0x0A, 0xAA, 0x00, 0x22, 0x4B, ++0xD6, 0x58, 0x77, 0xF7, 0x19, 0xFD, 0x00, 0x28, 0x3B, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x37, 0xD9, 0x22, 0x78, ++0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x36, 0x23, 0xF3, 0x5C, 0x01, 0x2B, 0x27, 0xD1, 0x23, 0x7A, 0x1B, 0x3A, ++0x01, 0x2B, 0x24, 0xD8, 0x27, 0x00, 0x09, 0x37, 0x38, 0x00, 0x79, 0xF7, 0x93, 0xFA, 0x01, 0x00, 0x13, 0x28, 0x16, 0xD9, ++0x8B, 0x23, 0x9B, 0x00, 0xF0, 0x18, 0x0A, 0x22, 0x39, 0x00, 0xCE, 0xF7, 0x19, 0xF8, 0x22, 0x7A, 0x53, 0x1E, 0x9A, 0x41, ++0xD2, 0xB2, 0xE8, 0xB2, 0x3B, 0x00, 0x61, 0x68, 0xA9, 0xF7, 0x2E, 0xF8, 0x23, 0x7A, 0x5A, 0x1E, 0x93, 0x41, 0x91, 0x22, ++0x92, 0x00, 0xB3, 0x54, 0x0B, 0xE0, 0x08, 0x48, 0x79, 0xF7, 0x12, 0xFA, 0x1E, 0x22, 0x00, 0xE0, 0x24, 0x22, 0x39, 0x23, ++0xF3, 0x5C, 0xE8, 0xB2, 0x3C, 0x21, 0x9E, 0xF7, 0x48, 0xFE, 0x00, 0x20, 0xF8, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0xD8, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x04, 0x00, 0x08, 0x00, 0x0D, 0x0A, 0xAA, 0x00, 0x2B, 0x4B, 0xD6, 0x58, ++0x77, 0xF7, 0xCA, 0xFC, 0x00, 0x28, 0x20, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x1C, 0xD9, 0x22, 0x78, 0x01, 0x23, ++0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x16, 0xD0, 0xA3, 0x78, 0x01, 0x2B, 0x31, 0xD0, ++0x02, 0x2B, 0x39, 0xD0, 0x00, 0x20, 0x00, 0x2B, 0x22, 0xD0, 0x01, 0xA9, 0x39, 0x23, 0xF2, 0x5C, 0x3B, 0x3B, 0x13, 0x43, ++0x0B, 0x70, 0x20, 0x23, 0x4B, 0x70, 0x88, 0x70, 0xE8, 0xB2, 0x9E, 0xF7, 0xC1, 0xFD, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, ++0x85, 0xF7, 0xF8, 0xFC, 0x00, 0x28, 0x03, 0xD0, 0x4F, 0x23, 0x01, 0x22, 0xF2, 0x54, 0xE0, 0xE7, 0x4F, 0x23, 0xF3, 0x5C, ++0x00, 0x2B, 0xDC, 0xD1, 0x39, 0x23, 0xF3, 0x5C, 0xE8, 0xB2, 0x1A, 0x22, 0x1F, 0x21, 0x9E, 0xF7, 0x0D, 0xFE, 0xE8, 0xE7, ++0xE8, 0xB2, 0xF5, 0xF7, 0x59, 0xF9, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0x2A, 0x20, 0x18, 0x40, 0x15, 0x30, 0xD2, 0xE7, ++0xE8, 0xB2, 0xF5, 0xF7, 0x79, 0xF9, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0x15, 0x20, 0x18, 0x40, 0x15, 0x30, 0xC8, 0xE7, ++0xE8, 0xB2, 0x03, 0x4B, 0x1B, 0x69, 0x98, 0x47, 0x2A, 0x20, 0xC2, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x60, 0x92, 0x16, 0x00, ++0x70, 0xB5, 0x14, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x11, 0x4A, 0x9D, 0x58, 0x20, 0x00, 0x77, 0xF7, 0x69, 0xFC, 0x03, 0x00, ++0x01, 0x28, 0x0A, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x06, 0xD9, 0x16, 0x3B, 0xDB, 0xB2, 0x03, 0x30, 0x98, 0x42, 0x80, 0x41, ++0x40, 0x42, 0x40, 0x00, 0x70, 0xBD, 0x36, 0x23, 0xEB, 0x5C, 0x00, 0x20, 0x00, 0x2B, 0xF9, 0xD1, 0x91, 0x23, 0x9B, 0x00, ++0xEB, 0x5C, 0x00, 0x2B, 0xF4, 0xD0, 0x00, 0x21, 0x20, 0x00, 0x8E, 0xF7, 0xDB, 0xFC, 0x00, 0x20, 0xEE, 0xE7, 0xC0, 0x46, ++0x64, 0xA2, 0x16, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x00, 0x90, 0x0F, 0x00, 0x16, 0x00, 0x01, 0x93, 0x0B, 0x78, 0xDC, 0x00, ++0xE3, 0x18, 0x32, 0x4C, 0xE4, 0x18, 0x3C, 0x34, 0x23, 0x78, 0x01, 0x2B, 0x02, 0xD0, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, ++0x4B, 0x78, 0x00, 0x2B, 0x4B, 0xD1, 0x2C, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x4D, 0xD0, 0x2B, 0x4D, 0x2C, 0x00, 0x3F, 0x34, ++0x02, 0xE0, 0x09, 0x35, 0xA5, 0x42, 0x43, 0xD0, 0xAB, 0x79, 0x02, 0x2B, 0xF9, 0xD9, 0x3B, 0x78, 0xD9, 0x00, 0xC9, 0x18, ++0x36, 0x31, 0x23, 0x4B, 0x9C, 0x46, 0x61, 0x44, 0x06, 0x22, 0x28, 0x00, 0xCD, 0xF7, 0x18, 0xFF, 0x00, 0x28, 0xEC, 0xD1, ++0x0C, 0x23, 0x03, 0x22, 0x00, 0x21, 0x1F, 0x48, 0x77, 0xF7, 0x3C, 0xF8, 0x04, 0x00, 0x0B, 0x23, 0x03, 0x70, 0x3B, 0x78, ++0xD9, 0x00, 0xC9, 0x18, 0x36, 0x31, 0x18, 0x4D, 0x49, 0x19, 0x04, 0x30, 0x06, 0x22, 0xCD, 0xF7, 0x27, 0xFF, 0x01, 0x23, ++0x5B, 0x42, 0x63, 0x80, 0x02, 0x33, 0xA3, 0x72, 0x00, 0x26, 0xE6, 0x72, 0x20, 0x00, 0xC8, 0xF7, 0x85, 0xFE, 0x3A, 0x78, ++0xD3, 0x00, 0x9B, 0x18, 0xEB, 0x18, 0x3E, 0x33, 0x18, 0x78, 0x85, 0xF7, 0x0F, 0xFA, 0x3A, 0x78, 0xD3, 0x00, 0x9B, 0x18, ++0xEB, 0x18, 0x3C, 0x33, 0x1E, 0x70, 0x28, 0x68, 0x0C, 0x38, 0x77, 0xF7, 0x62, 0xF8, 0x2E, 0x60, 0xAD, 0xE7, 0x16, 0x2B, ++0xAB, 0xD0, 0x02, 0xE0, 0x7B, 0x78, 0x16, 0x2B, 0xA7, 0xD0, 0x01, 0x9B, 0x32, 0x00, 0x39, 0x00, 0x00, 0x98, 0x04, 0x4C, ++0xA0, 0x47, 0xA0, 0xE7, 0x68, 0x9E, 0x16, 0x00, 0x9E, 0x9E, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, 0xED, 0x33, 0x09, 0x00, ++0xF0, 0xB5, 0x87, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x02, 0x92, 0x03, 0x93, 0x0A, 0x78, 0xD3, 0x00, 0x9A, 0x18, 0x29, 0x4B, ++0x9B, 0x18, 0x3C, 0x33, 0x1B, 0x78, 0x02, 0x2B, 0x02, 0xD0, 0x00, 0x20, 0x07, 0xB0, 0xF0, 0xBD, 0x25, 0x4C, 0x27, 0x00, ++0x3F, 0x37, 0x4E, 0x1C, 0x02, 0xE0, 0x09, 0x34, 0xBC, 0x42, 0x39, 0xD0, 0xA3, 0x79, 0x02, 0x2B, 0xF9, 0xD9, 0x06, 0x22, ++0x31, 0x00, 0x20, 0x00, 0xCD, 0xF7, 0xAE, 0xFE, 0x00, 0x28, 0xF2, 0xD1, 0x1B, 0x4A, 0x29, 0x78, 0xCB, 0x00, 0x5B, 0x18, ++0xD3, 0x18, 0x3C, 0x33, 0x00, 0x21, 0x19, 0x70, 0x13, 0x7B, 0x9B, 0x07, 0xDF, 0xD5, 0x18, 0x4B, 0x00, 0x24, 0x1A, 0x78, ++0x00, 0x2A, 0x05, 0xD0, 0x01, 0x34, 0xE4, 0xB2, 0x09, 0x33, 0x07, 0x2C, 0xF7, 0xD1, 0xD4, 0xE7, 0x06, 0x2C, 0xD2, 0xD8, ++0x0F, 0x4B, 0x1A, 0x8B, 0x04, 0xA9, 0x0A, 0x80, 0x5A, 0x8B, 0x4A, 0x80, 0x5B, 0x7F, 0x0B, 0x71, 0x4C, 0x71, 0x0E, 0x4A, ++0xD0, 0x23, 0xD3, 0x58, 0x08, 0x00, 0x98, 0x47, 0x00, 0x28, 0xC2, 0xD1, 0xE3, 0x00, 0x1C, 0x19, 0x06, 0x4B, 0x1C, 0x19, ++0x3C, 0x34, 0x02, 0x22, 0x22, 0x70, 0xBA, 0xE7, 0x03, 0x9B, 0x02, 0x9A, 0x29, 0x00, 0x01, 0x98, 0x05, 0x4C, 0xA0, 0x47, ++0xB3, 0xE7, 0xC0, 0x46, 0x68, 0x9E, 0x16, 0x00, 0x9E, 0x9E, 0x16, 0x00, 0xA4, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xDD, 0x32, 0x09, 0x00, 0x00, 0x09, 0x70, 0x47, 0x00, 0x28, 0x14, 0xD0, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x03, 0xD0, ++0x0D, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x06, 0xD1, 0x0C, 0x4B, 0x0A, 0x4A, 0x99, 0x68, 0x11, 0x60, 0xDA, 0x68, 0x09, 0x4B, ++0x1A, 0x60, 0x09, 0x4B, 0x09, 0x4A, 0x9A, 0x60, 0x09, 0x4A, 0xDA, 0x60, 0x70, 0x47, 0x06, 0x4B, 0x03, 0x4A, 0x12, 0x68, ++0x9A, 0x60, 0x03, 0x4A, 0x12, 0x68, 0xDA, 0x60, 0xF6, 0xE7, 0xC0, 0x46, 0xB8, 0xE6, 0x10, 0x00, 0xD4, 0xE6, 0x10, 0x00, ++0x60, 0x92, 0x16, 0x00, 0x2D, 0x01, 0x10, 0x00, 0x81, 0x01, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x01, 0x00, 0x2F, 0x48, ++0x79, 0xF7, 0x68, 0xF8, 0x7D, 0xF7, 0xE8, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x70, 0xBD, 0xFF, 0xF7, 0xC9, 0xFF, 0x2B, 0x4A, ++0x95, 0x23, 0x9B, 0x00, 0xD2, 0x5C, 0x2A, 0x4B, 0x1A, 0x70, 0x2A, 0x4B, 0x1A, 0x68, 0x2A, 0x4B, 0x1A, 0x60, 0xE6, 0x23, ++0x5B, 0x00, 0x1B, 0x68, 0x28, 0x48, 0x98, 0x47, 0x28, 0x4B, 0x18, 0x60, 0x01, 0x2C, 0x27, 0xD0, 0x02, 0x23, 0x22, 0x00, ++0x9A, 0x43, 0x05, 0xD0, 0x25, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x1C, 0x4E, 0x95, 0x25, ++0xAD, 0x00, 0x40, 0x23, 0x73, 0x55, 0x1C, 0x4B, 0x20, 0x4A, 0x1A, 0x60, 0x8C, 0x21, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, ++0x49, 0x00, 0x1A, 0x48, 0x98, 0x47, 0x73, 0x5D, 0x1C, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x01, 0x2C, 0x1B, 0xD9, 0x02, 0x2C, ++0xC8, 0xD1, 0x1A, 0x49, 0x0A, 0x88, 0xFF, 0x20, 0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xC1, 0xE7, 0x0D, 0x4D, 0x95, 0x24, ++0xA4, 0x00, 0x30, 0x23, 0x2B, 0x55, 0x0D, 0x4B, 0x11, 0x4A, 0x1A, 0x60, 0x8C, 0x21, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, ++0x49, 0x00, 0x0B, 0x48, 0x98, 0x47, 0x2B, 0x5D, 0x0D, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x0E, 0x49, 0x0A, 0x88, 0xFF, 0x20, ++0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xA7, 0xE7, 0xE4, 0xD4, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0xF6, 0xE8, 0x10, 0x00, ++0x54, 0x07, 0x62, 0x40, 0x08, 0xE7, 0x10, 0x00, 0x58, 0x00, 0x01, 0x50, 0x18, 0xE7, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xFD, 0x20, 0x22, 0x21, 0x60, 0x92, 0x16, 0x00, 0x8E, 0x01, 0x61, 0x40, 0x0C, 0x65, 0x61, 0x40, 0x70, 0xB5, 0x04, 0x00, ++0x01, 0x00, 0x1A, 0x48, 0x78, 0xF7, 0xEE, 0xFF, 0x7D, 0xF7, 0x6E, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x70, 0xBD, 0x00, 0x20, ++0xFF, 0xF7, 0x4E, 0xFF, 0x15, 0x4E, 0x95, 0x25, 0xAD, 0x00, 0x15, 0x4B, 0x1B, 0x78, 0x73, 0x55, 0x14, 0x4B, 0x1A, 0x68, ++0x14, 0x4B, 0x1A, 0x60, 0x14, 0x4B, 0x1B, 0x68, 0x80, 0x21, 0x49, 0x00, 0x19, 0x43, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, ++0x11, 0x48, 0x98, 0x47, 0x73, 0x5D, 0x11, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x01, 0x2C, 0x08, 0xD9, 0x02, 0x2C, 0xDF, 0xD1, ++0x0E, 0x49, 0x0A, 0x88, 0xFF, 0x20, 0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xD8, 0xE7, 0x0C, 0x49, 0x0A, 0x88, 0xFF, 0x20, ++0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xD1, 0xE7, 0xF8, 0xD4, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0xF6, 0xE8, 0x10, 0x00, ++0x08, 0xE7, 0x10, 0x00, 0x54, 0x07, 0x62, 0x40, 0x18, 0xE7, 0x10, 0x00, 0x58, 0x00, 0x01, 0x50, 0x60, 0x92, 0x16, 0x00, ++0x8E, 0x01, 0x61, 0x40, 0x0C, 0x65, 0x61, 0x40, 0x10, 0xB5, 0x09, 0x28, 0x0B, 0xD9, 0xFF, 0x28, 0x0B, 0xD1, 0x0B, 0x09, ++0x1F, 0x29, 0x0D, 0xD9, 0x02, 0x3B, 0x01, 0x2B, 0x05, 0xD8, 0x01, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, 0x01, 0xE0, 0x00, 0x28, ++0x08, 0xD1, 0x10, 0xBD, 0x00, 0x20, 0xFF, 0xF7, 0x25, 0xFF, 0xFA, 0xE7, 0x00, 0x20, 0xFF, 0xF7, 0x9B, 0xFF, 0xF6, 0xE7, ++0x0B, 0x09, 0x1F, 0x29, 0xF4, 0xD9, 0x02, 0x3B, 0x01, 0x2B, 0xF0, 0xD8, 0x01, 0x20, 0xFF, 0xF7, 0x17, 0xFF, 0xEC, 0xE7, ++0xF8, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0x1F, 0x00, 0x13, 0x0A, 0x9B, 0x00, ++0x11, 0x4A, 0x9B, 0x58, 0x99, 0x46, 0x0A, 0x88, 0x10, 0x4B, 0xD3, 0x5C, 0x98, 0x46, 0x20, 0x00, 0x77, 0xF7, 0x42, 0xFA, ++0x0A, 0x28, 0x0A, 0xD0, 0x3B, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0x0B, 0x4C, 0xA0, 0x47, 0x00, 0x20, 0x0C, 0xBC, ++0x90, 0x46, 0x99, 0x46, 0xF8, 0xBD, 0x43, 0x46, 0x5B, 0x08, 0x03, 0x2B, 0xF0, 0xD1, 0x07, 0x4B, 0x4A, 0x46, 0xD1, 0x5C, ++0x06, 0x3B, 0xD0, 0x5C, 0xFF, 0xF7, 0xB0, 0xFF, 0xE8, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, ++0x05, 0x87, 0x0A, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x20, 0x4B, ++0xD6, 0x58, 0x20, 0x00, 0x77, 0xF7, 0x16, 0xFA, 0x03, 0x00, 0x01, 0x28, 0x10, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x05, 0xD9, ++0x19, 0x2B, 0x05, 0xD8, 0x15, 0x22, 0x9A, 0x42, 0x40, 0x41, 0x40, 0x00, 0x02, 0xB0, 0x70, 0xBD, 0x58, 0x3B, 0x18, 0x00, ++0x43, 0x1E, 0x98, 0x41, 0x40, 0x00, 0xF7, 0xE7, 0x4C, 0x23, 0xF3, 0x5C, 0x00, 0x20, 0x00, 0x2B, 0xF2, 0xD1, 0x4B, 0x33, ++0xF3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x4B, 0x23, 0x00, 0x22, 0xF2, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x20, 0x00, 0x2B, ++0xE6, 0xD0, 0x01, 0xA9, 0x36, 0x23, 0xF2, 0x5C, 0x38, 0x3B, 0x13, 0x43, 0x0B, 0x70, 0x1F, 0x23, 0x4B, 0x70, 0x1D, 0x3B, ++0x8B, 0x70, 0xE8, 0xB2, 0x9E, 0xF7, 0xFE, 0xFA, 0x20, 0x00, 0x8E, 0xF7, 0xF1, 0xFE, 0x58, 0x21, 0x20, 0x00, 0x77, 0xF7, ++0x7D, 0xF9, 0x00, 0x20, 0xD0, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x05, 0x4B, 0x00, 0x20, 0x1A, 0x78, 0x00, 0x2A, ++0x04, 0xD0, 0x01, 0x30, 0xC0, 0xB2, 0x09, 0x33, 0x07, 0x28, 0xF7, 0xD1, 0x70, 0x47, 0xC0, 0x46, 0xA4, 0x9E, 0x16, 0x00, ++0x70, 0xB5, 0x80, 0x00, 0x28, 0x4B, 0xC2, 0x58, 0x28, 0x49, 0xD5, 0x23, 0x5B, 0x00, 0xC9, 0x5C, 0xCB, 0x00, 0x5B, 0x1A, ++0x5B, 0x00, 0x26, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x19, 0x88, 0xC9, 0x0B, 0x0B, 0xD0, 0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, ++0x19, 0x80, 0x20, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x0B, 0x40, 0x23, 0x54, 0x9E, 0x23, ++0xD3, 0x5C, 0x5B, 0x00, 0xAE, 0x21, 0x51, 0x5C, 0x5B, 0x18, 0xDB, 0xB2, 0x99, 0x00, 0xCB, 0x18, 0x5B, 0x00, 0x19, 0x49, ++0x5C, 0x18, 0x21, 0x88, 0x89, 0xB2, 0x00, 0x29, 0x19, 0xD1, 0x9C, 0x31, 0x50, 0x5C, 0x00, 0x28, 0x01, 0xD1, 0x01, 0x31, ++0x50, 0x5C, 0x14, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x78, 0x26, 0xB1, 0x43, 0xC0, 0x00, 0x01, 0x43, 0x29, 0x80, 0x96, 0x21, ++0x51, 0x5A, 0xC9, 0x00, 0x06, 0x20, 0x01, 0x43, 0x89, 0xB2, 0x0E, 0x48, 0x18, 0x18, 0x01, 0x80, 0x94, 0x21, 0x51, 0x5A, ++0x21, 0x80, 0x0C, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x19, 0x80, 0xAE, 0x21, 0x53, 0x5C, ++0x58, 0x42, 0x43, 0x41, 0x53, 0x54, 0x70, 0xBD, 0x38, 0xE6, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, ++0xCE, 0x69, 0x61, 0x40, 0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0x70, 0xB5, 0x35, 0x4B, ++0x1C, 0x68, 0x00, 0x2C, 0x14, 0xD0, 0xE3, 0x78, 0x9B, 0x00, 0x33, 0x4A, 0x9D, 0x58, 0xA0, 0x23, 0xEB, 0x5C, 0x02, 0x2B, ++0x0E, 0xD0, 0x31, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x05, 0xD0, 0x30, 0x4A, 0x11, 0x68, 0x80, 0x23, 0xDB, 0x03, 0x0B, 0x43, ++0x13, 0x60, 0xA0, 0x23, 0x02, 0x22, 0xEA, 0x54, 0x00, 0x20, 0x70, 0xBD, 0x94, 0x23, 0xE8, 0x5A, 0x00, 0x28, 0x07, 0xD0, ++0x63, 0x78, 0x00, 0x2B, 0x42, 0xD0, 0x01, 0x2B, 0x43, 0xD0, 0x94, 0x23, 0x00, 0x22, 0xEA, 0x52, 0xE2, 0x78, 0x62, 0x23, ++0x53, 0x43, 0x24, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x40, 0x05, 0x40, 0x0F, 0x84, 0xF7, 0x51, 0xFF, 0x1D, 0x4D, ++0xE3, 0x78, 0x9B, 0x00, 0x58, 0x59, 0x76, 0xF7, 0xCF, 0xFE, 0xE3, 0x78, 0x9B, 0x00, 0x00, 0x24, 0x5C, 0x51, 0x1C, 0x48, ++0xCB, 0xF7, 0x56, 0xFD, 0x1B, 0x48, 0x78, 0xF7, 0x53, 0xFE, 0x14, 0x4D, 0x2B, 0x68, 0xD8, 0x68, 0x76, 0xF7, 0xC0, 0xFE, ++0x2B, 0x68, 0xDC, 0x60, 0x98, 0x68, 0x00, 0x28, 0x05, 0xD0, 0x76, 0xF7, 0xB9, 0xFE, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x22, ++0x9A, 0x60, 0x0C, 0x4C, 0x20, 0x68, 0x76, 0xF7, 0xB1, 0xFE, 0x00, 0x23, 0x23, 0x60, 0x0B, 0x4B, 0x1B, 0x78, 0x00, 0x2B, ++0xBC, 0xD0, 0x0E, 0x4A, 0x13, 0x68, 0x0E, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x06, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xB3, 0xE7, ++0x80, 0xF7, 0x4A, 0xFE, 0xBB, 0xE7, 0x80, 0xF7, 0xFD, 0xFD, 0xB8, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, ++0xDC, 0xE5, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, 0xFE, 0x64, 0x61, 0x40, 0xFC, 0xE6, 0x10, 0x00, 0x0C, 0xD5, 0x10, 0x00, ++0xD0, 0x04, 0x60, 0x40, 0xFF, 0x7F, 0xFF, 0xFF, 0x70, 0xB5, 0x13, 0x4B, 0x1C, 0x68, 0xA5, 0x78, 0x00, 0x2D, 0x1D, 0xD1, ++0x23, 0x78, 0x03, 0x2B, 0x1C, 0xD0, 0x63, 0x78, 0x00, 0x2B, 0x08, 0xD0, 0x01, 0x2B, 0x0F, 0xD0, 0x0D, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x04, 0xE0, 0x0E, 0x22, 0x01, 0x00, 0xE0, 0x68, 0xCD, 0xF7, 0xF2, 0xFB, ++0x01, 0x23, 0xA3, 0x70, 0x28, 0x00, 0x70, 0xBD, 0x0E, 0x22, 0x01, 0x00, 0xE0, 0x68, 0xCD, 0xF7, 0xE9, 0xFB, 0xF5, 0xE7, ++0x0C, 0x25, 0xF5, 0xE7, 0x0C, 0x25, 0xF3, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0xB0, 0x05, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x01, 0x93, 0x00, 0x23, ++0x08, 0x93, 0x09, 0x93, 0x06, 0x93, 0x06, 0xAA, 0x93, 0x80, 0x82, 0x00, 0xBB, 0x4B, 0xD3, 0x58, 0x00, 0x2B, 0x00, 0xD1, ++0x10, 0xE1, 0xAB, 0x00, 0xB8, 0x4A, 0x9F, 0x58, 0x21, 0x00, 0xB8, 0x48, 0x78, 0xF7, 0xCE, 0xFD, 0x00, 0x2C, 0x00, 0xD1, ++0x0D, 0xE1, 0x01, 0x2C, 0x00, 0xD1, 0x6D, 0xE2, 0xB4, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x00, 0x23, 0x00, 0x93, 0x98, 0x46, 0x99, 0x46, 0x02, 0x93, 0x00, 0x21, 0x00, 0x26, 0x01, 0x9B, 0x00, 0x2B, 0x63, 0xD0, ++0x62, 0x23, 0x6B, 0x43, 0xAC, 0x4A, 0x98, 0x18, 0x02, 0x88, 0x1F, 0x24, 0xA2, 0x43, 0x32, 0x43, 0x02, 0x80, 0xAA, 0x4A, ++0x9A, 0x18, 0x10, 0x88, 0xA9, 0x4E, 0x06, 0x40, 0x80, 0x20, 0x40, 0x00, 0x30, 0x43, 0x10, 0x80, 0x10, 0x88, 0x40, 0x04, ++0x40, 0x0C, 0x10, 0x80, 0x10, 0x88, 0xA5, 0x4E, 0x30, 0x40, 0x10, 0x80, 0xA4, 0x4A, 0x94, 0x46, 0x9C, 0x44, 0x62, 0x46, ++0x16, 0x88, 0xFF, 0x20, 0x86, 0x43, 0xA2, 0x4A, 0x93, 0x46, 0x2D, 0x22, 0x5C, 0x46, 0xA2, 0x5C, 0x32, 0x43, 0x64, 0x46, ++0x22, 0x80, 0x9F, 0x4A, 0x9E, 0x18, 0x00, 0x22, 0x94, 0x46, 0x32, 0x80, 0x9D, 0x4A, 0x93, 0x46, 0x9B, 0x44, 0x5A, 0x46, ++0x12, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x5C, 0x46, 0x22, 0x80, 0x9A, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x99, 0x4A, 0x9A, 0x18, ++0x61, 0x46, 0x11, 0x80, 0x98, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x98, 0x4A, 0x99, 0x18, 0x02, 0x22, 0xFF, 0x32, 0x0A, 0x80, ++0x32, 0x88, 0x40, 0x24, 0xA2, 0x43, 0x22, 0x43, 0x32, 0x80, 0x0A, 0x88, 0x82, 0x43, 0xFE, 0x38, 0x02, 0x43, 0x0A, 0x80, ++0x9E, 0x22, 0xBA, 0x5C, 0x14, 0x21, 0x4A, 0x43, 0x8F, 0x49, 0x8C, 0x46, 0x62, 0x44, 0x92, 0xB2, 0x8E, 0x49, 0x59, 0x18, ++0x0A, 0x80, 0x8E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x3F, 0x21, 0x0A, 0x40, 0x8C, 0x49, 0x0A, 0x43, 0x1A, 0x80, ++0x08, 0xAE, 0x31, 0x00, 0x06, 0xA8, 0xAF, 0xF7, 0x9D, 0xF9, 0x06, 0xAB, 0x5A, 0x78, 0x12, 0x02, 0x1B, 0x78, 0x13, 0x43, ++0x62, 0x27, 0x6F, 0x43, 0x85, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x06, 0xAB, 0xDA, 0x78, 0x12, 0x02, 0x9B, 0x78, 0x13, 0x43, ++0x82, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x06, 0xAB, 0x5A, 0x79, 0x12, 0x02, 0x1B, 0x79, 0x13, 0x43, 0x7F, 0x4A, 0xBA, 0x18, ++0x13, 0x80, 0x72, 0x78, 0x12, 0x02, 0x33, 0x78, 0x13, 0x43, 0x7D, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0xF2, 0x78, 0x12, 0x02, ++0xB3, 0x78, 0x13, 0x43, 0x7A, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x00, 0x22, 0x06, 0x2D, 0x01, 0xD8, 0x6A, 0x1C, 0xD2, 0xB2, ++0x08, 0xAB, 0x19, 0x79, 0x03, 0x23, 0x0B, 0x40, 0x92, 0x00, 0x13, 0x43, 0x6E, 0x4A, 0x13, 0x43, 0x6C, 0x4A, 0xBA, 0x18, ++0x13, 0x80, 0x72, 0x48, 0x03, 0x68, 0x72, 0x49, 0x0B, 0x40, 0x80, 0x22, 0x52, 0x01, 0x1A, 0x43, 0x02, 0x60, 0x5A, 0x4B, ++0xFE, 0x18, 0x33, 0x88, 0x02, 0x9A, 0x14, 0x03, 0x24, 0xB2, 0x0B, 0x40, 0x23, 0x43, 0x9B, 0xB2, 0x33, 0x80, 0x4B, 0x46, ++0x00, 0x2B, 0x00, 0xD1, 0xDE, 0xE1, 0x56, 0x4B, 0xFA, 0x18, 0x13, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x80, 0x21, 0x09, 0x02, ++0x0B, 0x43, 0x13, 0x80, 0x33, 0x88, 0x64, 0x4A, 0x13, 0x40, 0x00, 0x9A, 0xD2, 0x02, 0x13, 0x43, 0x9B, 0xB2, 0x33, 0x80, ++0x61, 0x49, 0x0B, 0x68, 0x61, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, 0x13, 0x43, 0x0B, 0x60, 0x4C, 0x4B, 0xFB, 0x18, ++0x00, 0x22, 0x1A, 0x80, 0x49, 0x4B, 0xFB, 0x18, 0x1A, 0x88, 0x08, 0x21, 0x8A, 0x43, 0x1A, 0x80, 0x30, 0x88, 0x31, 0x88, ++0x33, 0x88, 0x80, 0x0B, 0x01, 0x22, 0x10, 0x40, 0x80, 0x03, 0xC9, 0x0A, 0x0A, 0x40, 0xD2, 0x02, 0x10, 0x43, 0x05, 0x43, ++0x58, 0x05, 0x40, 0x0F, 0x00, 0x02, 0x05, 0x43, 0x25, 0x43, 0xAD, 0xB2, 0x35, 0x80, 0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x32, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0xE7, 0xE6, 0xB3, 0x78, 0x99, 0x46, 0xF3, 0x78, 0x98, 0x46, 0x33, 0x79, 0x00, 0x93, 0x72, 0x79, 0x02, 0x92, 0x00, 0x2B, ++0x10, 0xD1, 0x9D, 0x23, 0x00, 0x22, 0xFA, 0x54, 0x32, 0x78, 0x01, 0x3B, 0xFA, 0x54, 0xF2, 0x88, 0x96, 0x23, 0xFA, 0x52, ++0x73, 0x78, 0x07, 0x2B, 0x00, 0xD9, 0x3D, 0xE1, 0x9B, 0x00, 0x3E, 0x49, 0xCB, 0x58, 0x9F, 0x46, 0x31, 0x78, 0x9D, 0x23, ++0xF9, 0x54, 0x3C, 0x48, 0x78, 0xF7, 0x9C, 0xFC, 0x9C, 0x23, 0x00, 0x22, 0xFA, 0x54, 0xEA, 0xE7, 0x39, 0x4B, 0x1A, 0x68, ++0x39, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x30, 0x49, 0x11, 0x40, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x1A, 0x60, ++0x35, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x76, 0xD0, 0x31, 0x49, 0x0B, 0x68, 0x2D, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, ++0x13, 0x43, 0x0B, 0x60, 0x6D, 0xE0, 0x2D, 0x4B, 0x1A, 0x68, 0x2D, 0x49, 0x11, 0x40, 0x80, 0x22, 0x92, 0x01, 0x0A, 0x43, ++0x1A, 0x60, 0x1A, 0x68, 0x22, 0x49, 0x11, 0x40, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x27, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x5A, 0xD0, 0x23, 0x49, 0x0B, 0x68, 0x1F, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, 0x13, 0x43, 0x0B, 0x60, ++0x51, 0xE0, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0x18, 0xD5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF8, 0x64, 0x61, 0x40, ++0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0x0C, 0x65, 0x61, 0x40, 0x60, 0x92, 0x16, 0x00, ++0x0E, 0x65, 0x61, 0x40, 0x56, 0x65, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, ++0x1E, 0x65, 0x61, 0x40, 0xC8, 0x69, 0x00, 0x00, 0x12, 0x65, 0x61, 0x40, 0x0A, 0x65, 0x61, 0x40, 0x40, 0xFF, 0x00, 0x00, ++0x00, 0x65, 0x61, 0x40, 0x02, 0x65, 0x61, 0x40, 0x04, 0x65, 0x61, 0x40, 0x06, 0x65, 0x61, 0x40, 0x08, 0x65, 0x61, 0x40, ++0x00, 0x04, 0x60, 0x40, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x28, 0x04, 0x60, 0x40, 0xFF, 0x7F, 0xFF, 0xFF, ++0x48, 0xD5, 0x10, 0x00, 0x30, 0xD5, 0x10, 0x00, 0xD0, 0x04, 0x60, 0x40, 0xFF, 0xDF, 0xFF, 0xFF, 0xDC, 0xE5, 0x10, 0x00, ++0x94, 0x23, 0xF8, 0x5A, 0x8E, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xF0, 0x21, 0x74, 0xF7, 0x96, 0xFB, 0x8C, 0x4A, 0x13, 0x68, ++0x8C, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x9E, 0x23, 0xFA, 0x5C, 0x52, 0x00, 0x10, 0x33, 0xFB, 0x5C, 0xD2, 0x18, 0xD2, 0xB2, ++0x62, 0x23, 0x6B, 0x43, 0x87, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x03, 0x93, 0x02, 0x20, 0x07, 0x23, 0x9A, 0x46, 0x04, 0x95, ++0x05, 0x96, 0x91, 0x00, 0x89, 0x18, 0x49, 0x00, 0x82, 0x4B, 0xCC, 0x18, 0x23, 0x88, 0x78, 0x25, 0xAB, 0x43, 0x70, 0x3D, ++0x2B, 0x43, 0x9B, 0xB2, 0x23, 0x80, 0x03, 0x9B, 0x1B, 0x88, 0x25, 0x88, 0xAB, 0x46, 0x1B, 0x0A, 0x55, 0x46, 0x2B, 0x40, ++0x5D, 0x46, 0x56, 0x46, 0xB5, 0x43, 0x2B, 0x43, 0x23, 0x80, 0x79, 0x4B, 0x9C, 0x46, 0x8C, 0x44, 0x63, 0x46, 0x1B, 0x88, ++0x77, 0x4C, 0x23, 0x40, 0x64, 0x46, 0x23, 0x80, 0x76, 0x4B, 0xCB, 0x18, 0x00, 0x24, 0x1C, 0x80, 0x75, 0x4B, 0x9C, 0x46, ++0x61, 0x44, 0x9E, 0x23, 0xFB, 0x5C, 0x5B, 0x00, 0x01, 0x34, 0x54, 0x40, 0xE4, 0xB2, 0xA4, 0x46, 0x63, 0x44, 0x9C, 0x00, ++0xA4, 0x46, 0x63, 0x44, 0x5B, 0x00, 0x6F, 0x4C, 0xA4, 0x46, 0x63, 0x44, 0x6E, 0x4C, 0x23, 0x43, 0x9B, 0xB2, 0x0B, 0x80, ++0x0B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x0B, 0x80, 0x53, 0x42, 0x5A, 0x41, 0xD2, 0xB2, 0x01, 0x38, 0xC0, 0xB2, 0x00, 0x28, ++0xB9, 0xD1, 0x04, 0x9D, 0x05, 0x9E, 0x31, 0x00, 0x08, 0x31, 0x06, 0x22, 0x06, 0xA8, 0xCD, 0xF7, 0xA5, 0xF9, 0x00, 0x21, ++0x02, 0x26, 0xF2, 0xE5, 0x94, 0x23, 0xF8, 0x5A, 0x56, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xAA, 0x21, 0x74, 0xF7, 0x26, 0xFB, ++0x54, 0x4A, 0x13, 0x68, 0x54, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x8E, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x4F, 0x4B, 0x9C, 0x46, ++0x60, 0x44, 0xFF, 0x21, 0x74, 0xF7, 0x18, 0xFB, 0x4D, 0x4A, 0x13, 0x68, 0x4D, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x80, 0xE7, ++0x94, 0x23, 0xF8, 0x5A, 0x48, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x74, 0xF7, 0x0A, 0xFB, 0x46, 0x4A, 0x13, 0x68, ++0x46, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x72, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x41, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x0F, 0x21, ++0x74, 0xF7, 0xFC, 0xFA, 0x3F, 0x4A, 0x13, 0x68, 0x3F, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x64, 0xE7, 0x94, 0x23, 0xF8, 0x5A, ++0x3A, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x55, 0x21, 0x74, 0xF7, 0xEE, 0xFA, 0x38, 0x4A, 0x13, 0x68, 0x38, 0x49, 0x0B, 0x40, ++0x13, 0x60, 0x56, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x33, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x74, 0xF7, 0xE0, 0xFA, ++0x31, 0x4A, 0x13, 0x68, 0x31, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x48, 0xE7, 0xB3, 0x78, 0x98, 0x46, 0xF3, 0x78, 0x00, 0x93, ++0xB4, 0x79, 0xF1, 0x1D, 0x06, 0x22, 0x06, 0xA8, 0xCD, 0xF7, 0x44, 0xF9, 0x00, 0x22, 0x33, 0x4B, 0x99, 0x46, 0xD5, 0x23, ++0x5B, 0x00, 0x9C, 0x46, 0x03, 0x26, 0x17, 0x3B, 0xFF, 0x3B, 0x9B, 0x46, 0x0A, 0xE0, 0x2F, 0x49, 0x8A, 0x46, 0x53, 0x44, ++0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x19, 0x80, 0x01, 0x32, 0xD2, 0xB2, 0x04, 0x2A, 0x11, 0xD0, 0x4B, 0x46, 0x61, 0x46, ++0x5B, 0x5C, 0xD3, 0x18, 0x33, 0x40, 0xD9, 0x00, 0xCB, 0x1A, 0x5B, 0x00, 0x26, 0x49, 0x58, 0x18, 0x01, 0x88, 0x89, 0xB2, ++0x00, 0x29, 0xE6, 0xD1, 0x59, 0x46, 0x79, 0x5A, 0x01, 0x80, 0xE2, 0xE7, 0x02, 0x94, 0x00, 0x23, 0x99, 0x46, 0x21, 0x49, ++0x03, 0x26, 0x66, 0xE5, 0x20, 0x4B, 0xFA, 0x18, 0x13, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x13, 0x80, 0x43, 0x46, 0xDB, 0x07, ++0x0F, 0xD4, 0x11, 0x88, 0x43, 0x46, 0x5B, 0x08, 0x1B, 0x02, 0x1B, 0x48, 0x01, 0x40, 0x0B, 0x43, 0x13, 0x80, 0x43, 0x46, ++0x5B, 0x08, 0x28, 0x33, 0x19, 0x00, 0x18, 0x48, 0x78, 0xF7, 0x0A, 0xFB, 0x10, 0xE6, 0x10, 0x88, 0x43, 0x46, 0x5B, 0x08, ++0x28, 0x33, 0x1B, 0x02, 0x12, 0x49, 0x01, 0x40, 0x0B, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0xEC, 0xE7, 0x00, 0x00, 0x61, 0x40, ++0xD0, 0x04, 0x60, 0x40, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0x64, 0x61, 0x40, 0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, ++0x07, 0xE0, 0xFF, 0xFF, 0xCE, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, ++0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, 0x9A, 0x69, 0x61, 0x40, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x65, 0x61, 0x40, ++0xFF, 0x80, 0xFF, 0xFF, 0x3C, 0xD5, 0x10, 0x00, 0x10, 0xB5, 0x07, 0x4B, 0x1C, 0x68, 0xA3, 0x78, 0x00, 0x2B, 0x00, 0xD1, ++0x10, 0xBD, 0x00, 0x23, 0x0A, 0x00, 0xE1, 0x68, 0xFF, 0xF7, 0xE2, 0xFC, 0x00, 0x23, 0xA3, 0x70, 0xF6, 0xE7, 0xC0, 0x46, ++0xD8, 0xE5, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x05, 0x00, 0x82, 0x00, 0x52, 0x4B, 0xD4, 0x58, 0x00, 0x2C, ++0x00, 0xD1, 0x98, 0xE0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, 0x4E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, 0xDB, 0xB2, 0xA3, 0x54, 0x09, 0x3A, 0xA2, 0x5C, 0x02, 0x3A, ++0x01, 0x2A, 0x01, 0xD8, 0x00, 0x2B, 0x14, 0xD0, 0x9F, 0xF7, 0xD2, 0xFD, 0x06, 0x00, 0x01, 0x00, 0x28, 0x00, 0xFF, 0xF7, ++0xA9, 0xFB, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x68, 0xE0, 0x3F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x01, 0x21, 0x20, 0x00, 0xCA, 0xF7, 0xEF, 0xFD, 0xA0, 0x23, ++0x02, 0x22, 0xE2, 0x54, 0xFF, 0xF7, 0xF4, 0xFB, 0x37, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, ++0x5B, 0x00, 0x35, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0xD2, 0x0B, 0xE7, 0xD0, 0x33, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, ++0xD2, 0x0A, 0xAA, 0x42, 0x07, 0xD0, 0x19, 0x88, 0xC9, 0x0A, 0x2C, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x28, 0x00, ++0xA0, 0x47, 0x2A, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x22, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x27, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x19, 0x40, 0x21, 0x54, ++0x23, 0x4B, 0x1A, 0x68, 0xCB, 0x00, 0x5B, 0x1A, 0x5B, 0x00, 0x22, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x52, 0x04, 0x52, 0x0C, ++0x93, 0x42, 0x05, 0xD0, 0x19, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x18, 0x4E, 0x00, 0x24, ++0xD5, 0x23, 0x5B, 0x00, 0x98, 0x46, 0x14, 0x4F, 0x03, 0xE0, 0x01, 0x34, 0x0E, 0x36, 0x04, 0x2C, 0xA8, 0xD0, 0x33, 0x88, ++0xDB, 0x0B, 0xF8, 0xD0, 0x10, 0x4B, 0x42, 0x46, 0x98, 0x5C, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xFD, 0x6E, 0xA8, 0x47, ++0xEF, 0xE7, 0x01, 0x21, 0x20, 0x00, 0xCA, 0xF7, 0x8F, 0xFD, 0x02, 0x36, 0x66, 0x60, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, ++0x4F, 0xFF, 0x20, 0x00, 0xF4, 0xF7, 0xA6, 0xFA, 0x8E, 0xE7, 0x04, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, ++0xA0, 0x47, 0x87, 0xE7, 0x38, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, ++0x92, 0x69, 0x61, 0x40, 0x2C, 0x04, 0x60, 0x40, 0x90, 0x69, 0x00, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, ++0x14, 0x00, 0xCF, 0xB2, 0x06, 0x2F, 0x07, 0xD9, 0xFF, 0x20, 0x08, 0x40, 0x0B, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x21, 0x00, 0xB0, 0x47, 0x00, 0x2C, 0x09, 0xD0, 0xFF, 0x20, 0x28, 0x40, 0x06, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x21, 0x00, 0xA8, 0x47, 0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x99, 0x38, 0x00, 0xFF, 0xF7, 0x28, 0xFF, 0xF8, 0xE7, 0xC0, 0x46, ++0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x96, 0xB0, 0x2F, 0x4B, 0x1B, 0x68, 0xD9, 0x68, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x51, 0xD4, 0x72, 0xB6, 0x10, 0x31, 0x24, 0x22, 0x0D, 0xA8, 0xCC, 0xF7, 0xCF, 0xFF, 0x62, 0xB6, ++0x0D, 0x9C, 0x00, 0x26, 0x00, 0x2C, 0x07, 0xD0, 0x0E, 0x9B, 0xE3, 0x1A, 0x64, 0x20, 0x58, 0x43, 0x21, 0x00, 0xCC, 0xF7, ++0x75, 0xFB, 0x06, 0x00, 0x13, 0x9D, 0x00, 0x20, 0x00, 0x2D, 0x05, 0xD0, 0x21, 0x48, 0x14, 0x9B, 0x58, 0x43, 0x29, 0x00, ++0xCC, 0xF7, 0x6A, 0xFB, 0x11, 0x9A, 0x12, 0x9F, 0x15, 0x99, 0x13, 0x00, 0x3B, 0x43, 0x0B, 0x43, 0x1B, 0xD0, 0x0F, 0x9B, ++0x98, 0x46, 0x0E, 0x9B, 0x9C, 0x46, 0x00, 0x23, 0x09, 0x93, 0x08, 0x90, 0x07, 0x93, 0x06, 0x96, 0x14, 0x9B, 0x0B, 0x93, ++0x05, 0x93, 0x04, 0x95, 0x03, 0x91, 0x02, 0x97, 0x01, 0x92, 0x10, 0x9B, 0x00, 0x93, 0x43, 0x46, 0x22, 0x00, 0x61, 0x46, ++0x11, 0x48, 0x78, 0xF7, 0xA5, 0xF9, 0x16, 0xB0, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0F, 0x9B, 0x0E, 0x99, 0x00, 0x22, ++0x06, 0x92, 0x05, 0x90, 0x04, 0x92, 0x03, 0x96, 0x14, 0x9A, 0x0B, 0x92, 0x02, 0x92, 0x01, 0x95, 0x10, 0x9A, 0x00, 0x92, ++0x22, 0x00, 0x08, 0x48, 0x78, 0xF7, 0x90, 0xF9, 0xE9, 0xE7, 0x10, 0x31, 0x24, 0x22, 0x0D, 0xA8, 0xCC, 0xF7, 0x7E, 0xFF, ++0xAE, 0xE7, 0xC0, 0x46, 0xD8, 0xE5, 0x10, 0x00, 0x10, 0x27, 0x00, 0x00, 0x68, 0xD5, 0x10, 0x00, 0xC8, 0xD5, 0x10, 0x00, ++0x70, 0x47, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x05, 0x00, 0x0F, 0x00, 0x16, 0x00, 0x1C, 0x00, 0x4B, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x05, 0xD0, 0x4A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x21, ++0x10, 0x20, 0x76, 0xF7, 0x37, 0xF9, 0x44, 0x4B, 0x18, 0x60, 0x00, 0x28, 0x10, 0xD0, 0x42, 0x4B, 0x18, 0x68, 0x10, 0x22, ++0x00, 0x21, 0x74, 0xF7, 0xDF, 0xF8, 0x00, 0x2D, 0x0E, 0xD0, 0x01, 0x2D, 0x2C, 0xD0, 0x3E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x1B, 0xE0, 0x3A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x98, 0x47, 0xE8, 0xE7, ++0x36, 0x4C, 0x25, 0x68, 0x00, 0x21, 0x0E, 0x20, 0x76, 0xF7, 0x16, 0xF9, 0xE8, 0x60, 0x23, 0x68, 0xDB, 0x68, 0x00, 0x2B, ++0x0D, 0xD0, 0x31, 0x4C, 0x23, 0x68, 0xD8, 0x68, 0x0E, 0x22, 0x00, 0x21, 0x74, 0xF7, 0xBC, 0xF8, 0x23, 0x68, 0x00, 0x22, ++0x5A, 0x70, 0xDE, 0x70, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0xEA, 0xE7, 0x26, 0x4D, 0x2B, 0x68, 0x98, 0x46, 0x00, 0x21, 0x38, 0x20, 0x76, 0xF7, 0xF5, 0xF8, 0x43, 0x46, ++0xD8, 0x60, 0x2B, 0x68, 0xDB, 0x68, 0x00, 0x2B, 0x31, 0xD0, 0x20, 0x4D, 0x2B, 0x68, 0xD8, 0x68, 0x38, 0x22, 0x00, 0x21, ++0x74, 0xF7, 0x9A, 0xF8, 0x2B, 0x68, 0x98, 0x46, 0x00, 0x21, 0x28, 0x20, 0x76, 0xF7, 0xE2, 0xF8, 0x43, 0x46, 0x98, 0x60, ++0x2B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0x25, 0xD0, 0x16, 0x4D, 0x2B, 0x68, 0x98, 0x68, 0x28, 0x22, 0x00, 0x21, 0x74, 0xF7, ++0x87, 0xF8, 0x2B, 0x68, 0xD8, 0x68, 0x0E, 0x22, 0x39, 0x00, 0xCC, 0xF7, 0xF5, 0xFE, 0x2B, 0x68, 0x01, 0x22, 0x5A, 0x70, ++0xC8, 0x22, 0x52, 0x01, 0x5A, 0x60, 0xDE, 0x70, 0x0E, 0x48, 0x0F, 0x4A, 0x82, 0x60, 0x5B, 0x68, 0xE4, 0x18, 0x24, 0x01, ++0x24, 0x09, 0x44, 0x60, 0xCA, 0xF7, 0xA0, 0xFF, 0xB6, 0xE7, 0x08, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0xC6, 0xE7, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD2, 0xE7, 0xC0, 0x46, ++0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xFC, 0xE6, 0x10, 0x00, 0xD5, 0x01, 0x10, 0x00, 0xF8, 0xB5, 0x04, 0x00, ++0x4E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0xF7, 0xB8, 0xFA, 0x05, 0x00, 0x28, 0x00, 0xF8, 0xBD, 0x4B, 0x48, ++0x78, 0xF7, 0xCA, 0xF8, 0x4A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x07, 0xD0, 0x49, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0xEE, 0xE7, 0x00, 0x21, 0xF8, 0x20, 0x76, 0xF7, 0x88, 0xF8, 0x42, 0x4B, 0x18, 0x60, ++0x00, 0x28, 0x75, 0xD0, 0x9F, 0xF7, 0xE0, 0xFB, 0x07, 0x00, 0x84, 0xF7, 0x81, 0xF9, 0x40, 0x4A, 0x13, 0x88, 0x40, 0x49, ++0x0B, 0x40, 0x00, 0x02, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x3A, 0x4B, 0x1E, 0x68, 0xF8, 0x22, 0x00, 0x21, 0x30, 0x00, ++0x74, 0xF7, 0x22, 0xF8, 0x00, 0x23, 0x73, 0x62, 0x39, 0x4A, 0xF2, 0x61, 0x39, 0x4A, 0x32, 0x62, 0x03, 0x22, 0x32, 0x76, ++0x38, 0x4A, 0x12, 0x78, 0xB2, 0x75, 0x38, 0x4A, 0x32, 0x61, 0x05, 0x22, 0xF2, 0x75, 0x99, 0x32, 0xB3, 0x54, 0x01, 0x32, ++0xB3, 0x54, 0x02, 0x32, 0xB3, 0x54, 0x03, 0x32, 0x28, 0x21, 0xB1, 0x52, 0x1C, 0x3A, 0xB3, 0x52, 0x80, 0xF7, 0x72, 0xF8, ++0x05, 0x1E, 0x05, 0xD1, 0x28, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x94, 0x23, 0xF5, 0x52, ++0x93, 0x3B, 0x00, 0x22, 0x21, 0x00, 0x00, 0x20, 0xFF, 0xF7, 0x8A, 0xFA, 0x28, 0x4A, 0x13, 0x88, 0x1F, 0x21, 0x0B, 0x40, ++0x13, 0x80, 0x77, 0x60, 0x00, 0x23, 0x82, 0x22, 0xB3, 0x52, 0xB3, 0x60, 0x00, 0x22, 0xA6, 0x33, 0xF2, 0x54, 0x20, 0x3B, ++0xFA, 0x22, 0xD2, 0x01, 0xF2, 0x52, 0x37, 0x67, 0x20, 0x4B, 0xB3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0xFB, 0x18, 0x1B, 0x01, ++0x1B, 0x09, 0xF3, 0x60, 0x30, 0x00, 0xCA, 0xF7, 0x15, 0xFA, 0x05, 0x1E, 0x07, 0xD0, 0x12, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0x7F, 0xE7, 0xA0, 0x23, 0x00, 0x22, 0xF2, 0x54, 0x01, 0x32, 0x00, 0x21, ++0x00, 0x20, 0x9F, 0xF7, 0xF3, 0xF8, 0x3B, 0x00, 0x00, 0x22, 0x21, 0x00, 0x00, 0x20, 0xFF, 0xF7, 0xC3, 0xFE, 0x70, 0xE7, ++0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0x68, 0xE7, 0xD8, 0xE5, 0x10, 0x00, ++0x10, 0xD6, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, ++0xF1, 0x02, 0x10, 0x00, 0xD1, 0x01, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x6A, 0x04, 0x00, 0x00, 0xF8, 0x64, 0x61, 0x40, ++0x00, 0x80, 0xFF, 0xFF, 0x10, 0xB5, 0x00, 0x29, 0x12, 0xD1, 0x03, 0x78, 0xFF, 0x2B, 0x0A, 0xD1, 0x43, 0x78, 0xC1, 0x2B, ++0x2F, 0xD1, 0x83, 0x78, 0xFB, 0x2B, 0x2E, 0xD1, 0xC1, 0x78, 0xE8, 0x39, 0x4B, 0x42, 0x59, 0x41, 0x03, 0x31, 0x04, 0x39, ++0x48, 0x42, 0x48, 0x41, 0xC0, 0xB2, 0x10, 0xBD, 0x03, 0x29, 0x0C, 0xD0, 0x12, 0x4B, 0x5C, 0x5C, 0x00, 0x23, 0xD9, 0xB2, ++0xC2, 0x5C, 0xA2, 0x42, 0xF1, 0xD1, 0x01, 0x31, 0xC9, 0xB2, 0x01, 0x33, 0x04, 0x2B, 0xF6, 0xD1, 0xEB, 0xE7, 0x03, 0x78, ++0xFF, 0x2B, 0x0A, 0xD1, 0x43, 0x78, 0xC1, 0x2B, 0x09, 0xD1, 0x83, 0x78, 0xFB, 0x2B, 0x08, 0xD1, 0xC3, 0x78, 0xE8, 0x2B, ++0xDF, 0xD1, 0x04, 0x21, 0xDD, 0xE7, 0x00, 0x21, 0xDB, 0xE7, 0x01, 0x21, 0xD9, 0xE7, 0x02, 0x21, 0xD7, 0xE7, 0x01, 0x21, ++0xD5, 0xE7, 0x02, 0x21, 0xD3, 0xE7, 0xC0, 0x46, 0x1C, 0xE0, 0x10, 0x00, 0xF8, 0xB5, 0x23, 0x4B, 0x1B, 0x68, 0x00, 0x2B, ++0x3A, 0xD0, 0xDA, 0x68, 0x53, 0x78, 0x00, 0x2B, 0x10, 0xD1, 0x95, 0x88, 0x00, 0x2D, 0x0C, 0xD0, 0x1E, 0x4F, 0x1F, 0x4E, ++0xF1, 0x5C, 0xC4, 0x5C, 0x61, 0x40, 0x79, 0x5C, 0xD4, 0x6A, 0xA4, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xAB, 0x42, ++0xF4, 0xD3, 0xF8, 0xBD, 0x03, 0x2B, 0x11, 0xD0, 0x18, 0x49, 0xCD, 0x5C, 0x94, 0x88, 0x00, 0x2C, 0xF7, 0xD0, 0x00, 0x23, ++0x13, 0x4E, 0xC1, 0x5C, 0x69, 0x40, 0x71, 0x5C, 0xD7, 0x6A, 0xBC, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xA3, 0x42, ++0xF5, 0xD3, 0xEA, 0xE7, 0x95, 0x88, 0x00, 0x2D, 0xE7, 0xD0, 0x00, 0x23, 0x0B, 0x4F, 0x0E, 0x4E, 0xF1, 0x5C, 0xC4, 0x5C, ++0x61, 0x40, 0x79, 0x5C, 0xD4, 0x6A, 0xA4, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xAB, 0x42, 0xF4, 0xD3, 0xD8, 0xE7, ++0x08, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD1, 0xE7, 0xC0, 0x46, 0xD8, 0xE5, 0x10, 0x00, ++0xBC, 0xDE, 0x10, 0x00, 0xBC, 0xDA, 0x10, 0x00, 0x1C, 0xE0, 0x10, 0x00, 0xBC, 0xD6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x06, 0x00, 0x74, 0x4B, 0x1B, 0x68, 0xDD, 0x68, ++0x54, 0x1E, 0xE4, 0xB2, 0x00, 0x2A, 0x00, 0xD1, 0xDA, 0xE0, 0x71, 0x4F, 0xAB, 0xE0, 0x04, 0x21, 0x08, 0x00, 0x10, 0x40, ++0x11, 0x42, 0x2F, 0xD0, 0xE9, 0x69, 0x01, 0x31, 0xE9, 0x61, 0xDB, 0x04, 0x9B, 0x0D, 0x99, 0x46, 0xB8, 0x23, 0x13, 0x42, ++0x5B, 0xD1, 0xAB, 0x88, 0xDB, 0x00, 0xAA, 0x6A, 0x94, 0x46, 0x63, 0x44, 0xAB, 0x62, 0xD5, 0x23, 0x5B, 0x00, 0x65, 0x4A, ++0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x63, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x83, 0xB2, 0x9A, 0x46, ++0x00, 0x2B, 0x06, 0xD1, 0x60, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x4B, 0x46, ++0x00, 0x2B, 0x53, 0xD0, 0x43, 0x46, 0x59, 0x06, 0x09, 0x0F, 0x5B, 0x48, 0x50, 0x44, 0xFF, 0xF7, 0x67, 0xFF, 0x4B, 0xE0, ++0x69, 0x69, 0x01, 0x31, 0x69, 0x61, 0xDB, 0x04, 0x9B, 0x0D, 0x99, 0x46, 0xB8, 0x23, 0x13, 0x42, 0x00, 0xD0, 0x95, 0xE0, ++0x00, 0x28, 0xCC, 0xD1, 0xAB, 0x88, 0x4B, 0x45, 0x2B, 0xD0, 0x6B, 0x6A, 0x01, 0x33, 0x6B, 0x62, 0x4C, 0x4A, 0xD5, 0x23, ++0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x4A, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x83, 0xB2, ++0x98, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x47, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x4B, 0x46, ++0x00, 0x2B, 0x21, 0xD0, 0x69, 0x78, 0x43, 0x48, 0x40, 0x44, 0xFF, 0xF7, 0xF7, 0xFE, 0x00, 0x28, 0x1A, 0xD1, 0x2B, 0x6B, ++0x01, 0x33, 0x2B, 0x63, 0x16, 0xE0, 0x2B, 0x6A, 0x01, 0x33, 0x2B, 0x62, 0x00, 0x28, 0x11, 0xD1, 0xD0, 0xE7, 0xDB, 0x00, ++0xAA, 0x6A, 0x94, 0x46, 0x63, 0x44, 0xAB, 0x62, 0xD0, 0xE7, 0x35, 0x23, 0xEB, 0x5C, 0x01, 0x33, 0xDB, 0xB2, 0x64, 0x2B, ++0x54, 0xD8, 0x35, 0x22, 0xAB, 0x54, 0x34, 0x23, 0x00, 0x22, 0xEA, 0x54, 0x2F, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, ++0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x2D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x05, 0xD1, ++0x2A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x25, 0x48, 0xD5, 0x21, 0x49, 0x00, 0x42, 0x5C, ++0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x26, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, ++0x42, 0x5C, 0x01, 0x32, 0x03, 0x23, 0x13, 0x40, 0x43, 0x54, 0x01, 0x3C, 0xE4, 0xB2, 0xFF, 0x2C, 0x2C, 0xD0, 0x30, 0x00, ++0x9E, 0xF7, 0x5A, 0xFF, 0x00, 0x28, 0x27, 0xD0, 0xD5, 0x23, 0x5B, 0x00, 0xFA, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, ++0x19, 0x4A, 0x9A, 0x18, 0x10, 0x88, 0x82, 0xB2, 0x18, 0x49, 0x59, 0x18, 0x09, 0x88, 0x89, 0xB2, 0x88, 0x46, 0x17, 0x49, ++0x8C, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9B, 0xB2, 0xC1, 0x07, 0xAE, 0xD4, 0x29, 0x69, 0x01, 0x31, 0x29, 0x61, 0x91, 0x07, ++0x00, 0xD4, 0x32, 0xE7, 0xAB, 0x69, 0x01, 0x33, 0xAB, 0x61, 0xAF, 0xE7, 0x35, 0x23, 0x64, 0x22, 0xEA, 0x54, 0xA8, 0xE7, ++0x2B, 0x6A, 0x01, 0x33, 0x2B, 0x62, 0x67, 0xE7, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, ++0xD8, 0xE5, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x9A, 0x69, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, ++0x90, 0x69, 0x61, 0x40, 0x92, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, 0x96, 0x69, 0x61, 0x40, 0xF0, 0xB5, 0xD6, 0x46, ++0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x89, 0x46, 0x82, 0x00, 0x41, 0x4B, 0xD5, 0x58, 0xA6, 0x23, 0xEF, 0x5C, 0x2E, 0x6D, ++0x44, 0x3B, 0x58, 0x43, 0x3E, 0x4B, 0xC3, 0x18, 0x1B, 0x88, 0x3E, 0x4A, 0x82, 0x18, 0x14, 0x88, 0x1B, 0x04, 0x1C, 0x43, ++0xA2, 0x46, 0x3C, 0x4B, 0xC3, 0x18, 0x1B, 0x88, 0x9B, 0x05, 0x9B, 0x0D, 0x98, 0x46, 0x3A, 0x4B, 0xC3, 0x18, 0x1C, 0x88, ++0x39, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x01, 0x88, 0x24, 0x04, 0x0C, 0x19, 0x37, 0x4B, 0x9E, 0x42, 0x1C, 0xD8, 0x53, 0x46, ++0x4A, 0x46, 0x9B, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x80, 0x22, 0x12, 0x05, 0x91, 0x42, 0x40, 0xD9, 0x4B, 0x46, 0x52, 0x46, ++0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0x3D, 0xD0, 0x00, 0x2B, 0x07, 0xDB, ++0x89, 0x08, 0x00, 0x29, 0x04, 0xDD, 0x89, 0x00, 0x49, 0x44, 0x09, 0x01, 0x0B, 0x09, 0x99, 0x46, 0x53, 0x46, 0xE1, 0x1A, ++0x49, 0x44, 0x09, 0x01, 0x09, 0x09, 0xF4, 0x23, 0x5B, 0x00, 0x42, 0x46, 0x9B, 0x1A, 0x32, 0xD4, 0xA9, 0x67, 0x82, 0x22, ++0xAB, 0x52, 0x4A, 0x42, 0x03, 0x20, 0x10, 0x40, 0xA6, 0x22, 0xA8, 0x54, 0x72, 0x3A, 0x2A, 0x65, 0xAB, 0x60, 0x34, 0x2E, ++0x09, 0xD9, 0xEA, 0x7D, 0x00, 0x2A, 0x06, 0xD0, 0xC8, 0x22, 0x52, 0x00, 0x9A, 0x42, 0x92, 0x41, 0x52, 0x42, 0x05, 0x32, ++0xEA, 0x75, 0x69, 0x67, 0x84, 0x22, 0xAB, 0x52, 0xC0, 0x1B, 0x43, 0x1E, 0x98, 0x41, 0xC0, 0xB2, 0x1C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0x1B, 0x01, 0x1B, 0x09, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0xC4, 0xD0, 0xC1, 0xE7, ++0x00, 0x2B, 0xC1, 0xDA, 0x0D, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xC2, 0xE7, 0x0B, 0x4B, ++0x9B, 0x1A, 0x01, 0x31, 0x09, 0x01, 0x09, 0x09, 0xC6, 0xE7, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0x4C, 0x65, 0x61, 0x40, ++0x4A, 0x65, 0x61, 0x40, 0x4E, 0x65, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, 0xE1, 0x04, 0x00, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x59, 0x04, 0x00, 0x00, 0xF8, 0xB5, 0x80, 0x00, 0x25, 0x4B, 0xC5, 0x58, 0xA6, 0x23, 0xEE, 0x5C, ++0x6C, 0x6F, 0xEB, 0x6E, 0xC8, 0x1A, 0x00, 0x01, 0x00, 0x09, 0x22, 0x49, 0x48, 0x43, 0x22, 0x49, 0xCB, 0xF7, 0x84, 0xFF, ++0x1A, 0x30, 0x40, 0x00, 0x02, 0x00, 0x34, 0x3A, 0x52, 0x08, 0x84, 0x23, 0xEB, 0x5A, 0x9B, 0x1A, 0x19, 0xB2, 0x1B, 0x04, ++0x27, 0xD5, 0x00, 0x23, 0x1B, 0x4A, 0x8A, 0x18, 0x11, 0xB2, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0x1F, 0x00, 0x01, 0x33, ++0xDB, 0xB2, 0x12, 0x04, 0xF4, 0xD4, 0xAC, 0x67, 0x82, 0x22, 0xA9, 0x52, 0x64, 0x42, 0x7F, 0x3A, 0x14, 0x40, 0xA3, 0x32, ++0xAC, 0x54, 0x28, 0x65, 0xA9, 0x60, 0x00, 0x2B, 0x0A, 0xD0, 0xEB, 0x7D, 0x00, 0x2B, 0x07, 0xD0, 0xC8, 0x23, 0x5B, 0x00, ++0x8B, 0x42, 0x9B, 0x41, 0x5B, 0x42, 0x06, 0x37, 0xDF, 0x19, 0xEF, 0x75, 0x34, 0x1B, 0x66, 0x1E, 0xB4, 0x41, 0xE0, 0xB2, ++0xF8, 0xBD, 0xAC, 0x67, 0x82, 0x23, 0xE9, 0x52, 0x64, 0x42, 0x7F, 0x3B, 0x1C, 0x40, 0xA3, 0x33, 0xEC, 0x54, 0x28, 0x65, ++0xA9, 0x60, 0xEF, 0xE7, 0x38, 0xE6, 0x10, 0x00, 0xA8, 0x61, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x71, 0x02, 0x00, 0x00, ++0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x8A, 0xB0, 0x0E, 0x00, 0x8A, 0x00, 0x52, 0x4B, 0xD5, 0x58, 0x00, 0x2D, 0x00, 0xD1, ++0x9B, 0xE0, 0xA6, 0x23, 0x98, 0x46, 0xEB, 0x5C, 0x01, 0x33, 0x03, 0x24, 0x23, 0x40, 0x1F, 0x00, 0x9F, 0xF7, 0xB0, 0xF8, ++0x00, 0x90, 0x03, 0x00, 0xA3, 0x43, 0x3B, 0x43, 0x42, 0x46, 0xAA, 0x5C, 0xD2, 0x1A, 0x14, 0x40, 0x04, 0x3B, 0xE4, 0x18, ++0x24, 0x01, 0x24, 0x09, 0x23, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x22, 0x12, 0x05, 0x93, 0x42, 0x02, 0xD9, 0x03, 0x1B, ++0x1B, 0x01, 0x59, 0xD1, 0x00, 0x23, 0x01, 0x93, 0x01, 0xA9, 0x68, 0x46, 0x9F, 0xF7, 0x9C, 0xF8, 0x01, 0x9B, 0x1A, 0x00, ++0x0F, 0x32, 0xFF, 0x32, 0x9C, 0x21, 0x89, 0x00, 0x8A, 0x42, 0x57, 0xD8, 0x01, 0x92, 0x00, 0x9A, 0x13, 0x1B, 0x1B, 0x01, ++0x1B, 0x09, 0x38, 0x49, 0x8B, 0x42, 0x05, 0xD8, 0xA2, 0x42, 0x61, 0xD1, 0xAB, 0x68, 0x01, 0x9A, 0x93, 0x42, 0x5D, 0xD9, ++0x02, 0xA8, 0x34, 0x4B, 0x02, 0x93, 0x44, 0x60, 0xAB, 0x68, 0x83, 0x60, 0x06, 0x76, 0x06, 0x61, 0x31, 0x4B, 0xC3, 0x60, ++0xAB, 0x7D, 0x03, 0x75, 0x01, 0x33, 0x43, 0x75, 0x00, 0x23, 0x83, 0x75, 0xB0, 0x22, 0xAA, 0x5C, 0xC2, 0x75, 0x83, 0x76, ++0xC3, 0x76, 0x01, 0x33, 0x43, 0x76, 0xCA, 0xF7, 0xD7, 0xFE, 0xA9, 0x22, 0xAB, 0x5C, 0x01, 0x33, 0xAB, 0x54, 0xAA, 0x23, ++0xEB, 0x5C, 0x00, 0x2B, 0x31, 0xD1, 0x9F, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x3B, 0xD1, 0xAB, 0x6F, 0x9B, 0xB2, 0x62, 0x21, ++0x4E, 0x43, 0x22, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0xAB, 0x6F, 0x1B, 0x0C, 0x20, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0x20, 0x4B, ++0x9C, 0x46, 0x66, 0x44, 0x2B, 0x6D, 0x01, 0x33, 0x5B, 0x08, 0x01, 0x33, 0x5B, 0x08, 0x1D, 0x4A, 0x13, 0x43, 0x9B, 0xB2, ++0x33, 0x80, 0x22, 0xE0, 0x04, 0x34, 0x24, 0x01, 0x24, 0x09, 0x23, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x93, 0x42, 0x9D, 0xD9, ++0x03, 0x1B, 0x1B, 0x01, 0x9A, 0xD0, 0xF3, 0xE7, 0x64, 0x3B, 0xFF, 0x3B, 0x01, 0x93, 0x00, 0x9B, 0x01, 0x33, 0x1B, 0x01, ++0x1B, 0x09, 0x00, 0x93, 0x9F, 0xE7, 0x9E, 0x23, 0xE8, 0x5C, 0xCB, 0xF7, 0x21, 0xF8, 0x0F, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xAA, 0x23, 0x00, 0x22, 0xEA, 0x54, 0xC2, 0xE7, 0x0C, 0x48, 0x77, 0xF7, 0xF1, 0xFC, 0x0A, 0xB0, 0x04, 0xBC, 0x90, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, ++0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0x18, 0x00, 0x60, 0x40, ++0x28, 0xD6, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x82, 0xB0, 0x05, 0x00, 0x0E, 0x00, 0x82, 0x00, 0x9D, 0x4B, ++0xD4, 0x58, 0x00, 0x2C, 0x00, 0xD1, 0x2B, 0xE1, 0x9B, 0x4B, 0x1B, 0x68, 0xDF, 0x68, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x05, 0xD1, 0x99, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, ++0xDB, 0xB2, 0xA3, 0x54, 0x09, 0x3A, 0xA2, 0x5C, 0x02, 0x2A, 0x01, 0xD1, 0x00, 0x2B, 0x51, 0xD0, 0x9E, 0xF7, 0xDE, 0xFF, ++0x01, 0x90, 0x01, 0x22, 0x31, 0x00, 0x28, 0x00, 0xFF, 0xF7, 0x20, 0xFD, 0x62, 0x23, 0x6B, 0x43, 0x8C, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1B, 0x88, 0xDB, 0x0B, 0x00, 0xD1, 0xAC, 0xE0, 0x31, 0x00, 0x28, 0x00, 0xFF, 0xF7, 0x15, 0xFE, 0xB4, 0x23, ++0xE0, 0x54, 0xA0, 0x23, 0xE3, 0x5C, 0x02, 0x2B, 0x00, 0xD1, 0xEA, 0xE0, 0x01, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0xBA, 0xF9, ++0x82, 0x23, 0xE3, 0x5E, 0xA3, 0x60, 0x81, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x0C, 0xD0, 0x34, 0x23, 0xFB, 0x5C, 0x00, 0x2B, ++0x00, 0xD1, 0x9D, 0xE0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x93, 0xE0, 0x7A, 0x4B, 0x00, 0x22, 0x1A, 0x60, ++0x34, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x90, 0xE0, 0xB4, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xBE, 0xE0, ++0xAA, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xD6, 0xE0, 0xA6, 0x33, 0xE2, 0x5C, 0x01, 0x32, 0xA3, 0x3B, 0x13, 0x40, ++0x9E, 0x22, 0xA1, 0x5C, 0x9C, 0x3A, 0x6E, 0x48, 0xCA, 0xF7, 0x56, 0xFF, 0xAA, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xC7, 0xE0, ++0x01, 0x21, 0x20, 0x00, 0xC9, 0xF7, 0xBE, 0xFF, 0xA0, 0x23, 0x02, 0x22, 0xE2, 0x54, 0x0A, 0x33, 0xE3, 0x5C, 0x00, 0x2B, ++0x49, 0xD1, 0xFE, 0xF7, 0xBF, 0xFD, 0x65, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, ++0x62, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0xD2, 0x0B, 0x00, 0xD1, 0xAD, 0xE0, 0x60, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, ++0xD2, 0x0A, 0xAA, 0x42, 0x07, 0xD0, 0x19, 0x88, 0xC9, 0x0A, 0x56, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x28, 0x00, ++0xA0, 0x47, 0x57, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x22, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x54, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x19, 0x40, 0x21, 0x54, ++0x50, 0x4B, 0x1A, 0x68, 0xCB, 0x00, 0x5B, 0x1A, 0x5B, 0x00, 0x4F, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x52, 0x04, 0x52, 0x0C, ++0x93, 0x42, 0x05, 0xD0, 0x43, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x45, 0x4E, 0x00, 0x24, ++0xD5, 0x23, 0x5B, 0x00, 0x98, 0x46, 0x3E, 0x4F, 0x0A, 0xE0, 0x28, 0x00, 0xCA, 0xF7, 0x30, 0xFF, 0xAA, 0x23, 0x00, 0x22, ++0xE2, 0x54, 0xAE, 0xE7, 0x01, 0x34, 0x0E, 0x36, 0x04, 0x2C, 0x67, 0xD0, 0x33, 0x88, 0xDB, 0x0B, 0xF8, 0xD0, 0x3A, 0x4B, ++0x42, 0x46, 0x98, 0x5C, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xFD, 0x6E, 0xA8, 0x47, 0xEF, 0xE7, 0x31, 0x00, 0x28, 0x00, ++0xFF, 0xF7, 0x04, 0xFE, 0xB4, 0x23, 0xE0, 0x54, 0x51, 0xE7, 0x29, 0x00, 0x01, 0x98, 0xFF, 0xF7, 0x53, 0xFE, 0x66, 0xE7, ++0xB4, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x2E, 0xD1, 0xAA, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x47, 0xD1, 0xA9, 0x33, 0xE3, 0x5C, ++0x00, 0x2B, 0x43, 0xD1, 0x01, 0x21, 0x20, 0x00, 0xC9, 0xF7, 0x3A, 0xFF, 0x01, 0x99, 0x61, 0x60, 0x86, 0x23, 0xFA, 0x22, ++0xD2, 0x01, 0xE2, 0x52, 0x21, 0x67, 0x20, 0x33, 0xE3, 0x5C, 0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x13, 0x40, 0x26, 0x4A, ++0x13, 0x43, 0xA3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0x9C, 0x46, 0x61, 0x44, 0x0F, 0x01, 0x3F, 0x09, 0xE7, 0x60, 0x20, 0x00, ++0xC9, 0xF7, 0x7C, 0xFD, 0x00, 0x28, 0x23, 0xD0, 0x15, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x1C, 0xE0, 0x9E, 0x23, 0xE0, 0x5C, 0xCA, 0xF7, 0xD9, 0xFE, 0x00, 0x23, 0xAA, 0x22, 0xA3, 0x54, 0x75, 0x3A, 0xBB, 0x54, ++0xC6, 0xE7, 0x9E, 0x23, 0xE0, 0x5C, 0xCA, 0xF7, 0xCF, 0xFE, 0xAA, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x01, 0x3B, 0xE1, 0x5C, ++0x12, 0x48, 0x77, 0xF7, 0xA1, 0xFB, 0x05, 0xE0, 0x06, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xA0, 0x47, ++0x02, 0xB0, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x38, 0xE6, 0x10, 0x00, 0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x4E, 0x65, 0x61, 0x40, 0xC8, 0xE6, 0x10, 0x00, 0x7D, 0x03, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, ++0x92, 0x69, 0x61, 0x40, 0x2C, 0x04, 0x60, 0x40, 0x90, 0x69, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x34, 0xD6, 0x10, 0x00, ++0x10, 0xB5, 0x82, 0x00, 0x0C, 0x4B, 0xD4, 0x58, 0x00, 0x2C, 0x0E, 0xD0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, ++0x09, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, 0xA3, 0x54, ++0x10, 0xBD, 0x04, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xA0, 0x47, 0xF7, 0xE7, 0x38, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0xCF, 0xB2, 0x06, 0x2F, ++0x08, 0xD9, 0xFF, 0x20, 0x08, 0x40, 0x10, 0x4B, 0xDB, 0x6E, 0x98, 0x46, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xC0, 0x47, ++0x00, 0x2C, 0x0A, 0xD0, 0x04, 0x2C, 0x0F, 0xD0, 0xFF, 0x20, 0x28, 0x40, 0x09, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x21, 0x00, 0xA8, 0x47, 0x03, 0xE0, 0x31, 0x00, 0x38, 0x00, 0xFF, 0xF7, 0x61, 0xFE, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, ++0x31, 0x00, 0x38, 0x00, 0xFF, 0xF7, 0xB6, 0xFF, 0xF7, 0xE7, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x05, 0x00, ++0x51, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x02, 0xD0, 0xFE, 0xF7, 0x0E, 0xFD, 0xF8, 0xBD, 0x4F, 0x48, 0x77, 0xF7, 0x22, 0xFB, ++0x4E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x07, 0xD0, 0x4D, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x12, 0x20, 0xEF, 0xE7, 0x00, 0x21, 0xF8, 0x20, 0x75, 0xF7, 0xE0, 0xFA, 0x46, 0x4B, 0x18, 0x60, 0x00, 0x28, 0x00, 0xD1, ++0x7C, 0xE0, 0x9E, 0xF7, 0x37, 0xFE, 0x06, 0x00, 0x83, 0xF7, 0xD8, 0xFB, 0x43, 0x4A, 0x13, 0x88, 0x43, 0x49, 0x0B, 0x40, ++0x00, 0x02, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x3D, 0x4B, 0x1C, 0x68, 0xF8, 0x22, 0x00, 0x21, 0x20, 0x00, 0x73, 0xF7, ++0x79, 0xFA, 0x00, 0x23, 0x63, 0x62, 0x3D, 0x4A, 0xE2, 0x61, 0x3D, 0x4A, 0x22, 0x62, 0x03, 0x22, 0x22, 0x76, 0x3C, 0x4A, ++0x12, 0x78, 0xA2, 0x75, 0x3B, 0x4A, 0x22, 0x61, 0x05, 0x22, 0xE2, 0x75, 0x99, 0x32, 0xA3, 0x54, 0x01, 0x32, 0x01, 0x21, ++0xA1, 0x54, 0x6B, 0x3A, 0x22, 0x65, 0x6D, 0x32, 0xA3, 0x54, 0x7F, 0xF7, 0xA9, 0xFA, 0x07, 0x1E, 0x3D, 0xD0, 0x3A, 0x89, ++0x94, 0x23, 0xE2, 0x52, 0x93, 0x3B, 0x01, 0x22, 0x29, 0x00, 0x00, 0x20, 0xFE, 0xF7, 0xE8, 0xFC, 0x33, 0x00, 0x00, 0x22, ++0x29, 0x00, 0x01, 0x20, 0xFF, 0xF7, 0x50, 0xF9, 0x9E, 0xF7, 0xF8, 0xFD, 0x60, 0x60, 0x00, 0x23, 0x82, 0x22, 0xA3, 0x52, ++0xA3, 0x60, 0x04, 0x32, 0xFA, 0x21, 0xC9, 0x01, 0xA1, 0x52, 0xE6, 0x66, 0x26, 0x67, 0x63, 0x67, 0xA3, 0x67, 0x00, 0x22, ++0xA6, 0x33, 0xE2, 0x54, 0x23, 0x4B, 0xA3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0x9C, 0x46, 0x66, 0x44, 0x36, 0x01, 0x36, 0x09, ++0xE6, 0x60, 0x20, 0x00, 0xC9, 0xF7, 0x6C, 0xFC, 0x00, 0x28, 0x15, 0xD1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x1C, 0x49, ++0xA1, 0x32, 0xFF, 0x32, 0x8B, 0x5A, 0x01, 0x24, 0x23, 0x43, 0x8B, 0x52, 0xA0, 0x3A, 0xFF, 0x3A, 0x18, 0x4B, 0x1A, 0x60, ++0x78, 0xE7, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xBA, 0xE7, 0x0A, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x20, 0x69, 0xE7, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x12, 0x20, 0x61, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x4C, 0xD6, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, 0xA1, 0x04, 0x10, 0x00, 0xD3, 0x01, 0x10, 0x00, ++0x7C, 0x91, 0x0D, 0x00, 0x6A, 0x04, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x20, 0xA3, 0x16, 0x00, 0xC8, 0xE6, 0x10, 0x00, ++0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0A, 0x48, 0x77, 0xF7, 0x68, 0xFA, 0xA1, 0x78, 0x4A, 0x10, 0x01, 0x23, 0x1A, 0x40, ++0x07, 0x48, 0x02, 0x70, 0x0B, 0x40, 0xA3, 0x70, 0x20, 0x00, 0xFF, 0xF7, 0x85, 0xF9, 0x01, 0x00, 0x28, 0x00, 0xFA, 0xF7, ++0x8B, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xC0, 0x46, 0x60, 0xD6, 0x10, 0x00, 0xDC, 0xE5, 0x10, 0x00, 0x70, 0xB5, 0x05, 0x00, ++0x0C, 0x00, 0x06, 0x48, 0x77, 0xF7, 0x4C, 0xFA, 0x28, 0x00, 0xFF, 0xF7, 0x1B, 0xFF, 0x01, 0x00, 0x20, 0x00, 0xFA, 0xF7, ++0x77, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xC0, 0x46, 0x68, 0xD6, 0x10, 0x00, 0x10, 0xB5, 0xFF, 0xF7, 0x51, 0xF8, 0x00, 0x20, ++0x10, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x17, 0xD0, 0xDC, 0x68, 0x18, 0x23, 0x0D, 0x22, ++0x00, 0x21, 0x0B, 0x48, 0x75, 0xF7, 0x2A, 0xF9, 0xFF, 0x23, 0x03, 0x70, 0xA3, 0x88, 0x43, 0x80, 0x00, 0x23, 0x03, 0x71, ++0x43, 0x71, 0x23, 0x69, 0x83, 0x60, 0x63, 0x69, 0xC3, 0x60, 0xE3, 0x69, 0x03, 0x61, 0xE3, 0x6A, 0x43, 0x61, 0xC6, 0xF7, ++0x79, 0xFF, 0x10, 0xBD, 0xD8, 0xE5, 0x10, 0x00, 0x03, 0x11, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x01, 0x78, ++0x0A, 0x48, 0x77, 0xF7, 0x11, 0xFA, 0x23, 0x78, 0x00, 0x2B, 0x07, 0xD0, 0x01, 0x2B, 0x08, 0xD0, 0x00, 0x21, 0x28, 0x00, ++0xFA, 0xF7, 0x3A, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xFE, 0xF7, 0x6E, 0xFB, 0xF6, 0xE7, 0xFF, 0xF7, 0xC7, 0xFF, 0xFE, 0xF7, ++0x69, 0xFB, 0xF1, 0xE7, 0x70, 0xD6, 0x10, 0x00, 0x45, 0x54, 0x45, 0x52, 0x52, 0x3A, 0x0A, 0x00, 0x77, 0x61, 0x6B, 0x65, ++0x75, 0x70, 0x5F, 0x68, 0x6F, 0x73, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x5F, 0x75, 0x70, ++0x5F, 0x68, 0x6F, 0x73, 0x74, 0x0A, 0x00, 0x00, 0x75, 0x61, 0x72, 0x74, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x0A, 0x00, 0x00, ++0x70, 0x5F, 0x73, 0x5F, 0x70, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x5F, 0x63, 0x68, 0x5F, 0x75, 0x70, 0x64, 0x61, ++0x74, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, ++0xE6, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xF6, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x1A, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x42, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x66, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x8E, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xBA, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xE6, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x0C, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x32, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x5C, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x82, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA2, 0x1C, 0x10, 0x00, 0xC4, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x16, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x3E, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x62, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x8A, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0xB6, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0xE2, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x08, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x2E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x58, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x7E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x9E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0xC0, 0x1C, 0x10, 0x00, 0x30, 0x78, 0x34, 0x30, 0x33, 0x34, 0x33, 0x30, 0x30, 0x34, 0x3A, 0x25, ++0x78, 0x2C, 0x25, 0x78, 0x00, 0x00, 0x00, 0x00, 0x43, 0x54, 0x53, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x20, 0x0A, 0x00, ++0xE2, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, ++0x78, 0x1D, 0x10, 0x00, 0x52, 0x1E, 0x10, 0x00, 0xE4, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, ++0xE2, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x6D, 0x64, 0x6C, 0x6C, 0x5F, 0x72, 0x65, 0x63, ++0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x62, 0x64, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, 0x2C, 0x25, ++0x78, 0x0A, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x6D, 0x61, 0x63, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, 0x2C, ++0x25, 0x78, 0x0A, 0x00, 0x66, 0x6C, 0x61, 0x73, 0x68, 0x6D, 0x61, 0x63, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, ++0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x43, 0x52, 0x5F, 0x50, 0x57, 0x52, 0x5F, 0x52, 0x45, 0x51, ++0x0A, 0x00, 0x00, 0x00, 0x50, 0x57, 0x52, 0x5F, 0x43, 0x54, 0x52, 0x4C, 0x5F, 0x52, 0x45, 0x51, 0x0A, 0x00, 0x00, 0x00, ++0x72, 0x65, 0x6D, 0x6F, 0x74, 0x65, 0x5F, 0x6D, 0x61, 0x78, 0x5F, 0x70, 0x77, 0x72, 0x0A, 0x00, 0x61, 0x66, 0x68, 0x74, ++0x6F, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x74, 0x78, 0x5F, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x00, ++0x72, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x73, 0x73, 0x69, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, ++0x73, 0x6D, 0x75, 0x74, 0x65, 0x0A, 0x00, 0x00, 0x72, 0x78, 0x5F, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x25, ++0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, ++0x64, 0x75, 0x20, 0x65, 0x6E, 0x6F, 0x75, 0x67, 0x68, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x77, 0x69, 0x66, 0x69, 0x20, 0x63, ++0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x69, 0x6F, 0x6E, 0x0A, 0x00, 0x00, 0x00, 0x75, 0x6D, 0x72, 0x65, 0x0A, 0x00, 0x00, 0x00, ++0x55, 0x4E, 0x44, 0x45, 0x46, 0x20, 0x56, 0x45, 0x4E, 0x44, 0x4F, 0x52, 0x5F, 0x49, 0x4E, 0x46, 0x4F, 0x0A, 0x00, 0x00, ++0x55, 0x4E, 0x4B, 0x4E, 0x4F, 0x57, 0x20, 0x56, 0x45, 0x4E, 0x44, 0x4F, 0x52, 0x5F, 0x49, 0x4E, 0x46, 0x4F, 0x3A, 0x25, ++0x78, 0x0A, 0x00, 0x00, 0x69, 0x6E, 0x69, 0x74, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, ++0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x38, 0x5C, 0x10, 0x00, 0x70, 0x5C, 0x10, 0x00, 0x78, 0x5C, 0x10, 0x00, ++0x38, 0x5C, 0x10, 0x00, 0x70, 0x5C, 0x10, 0x00, 0x76, 0x65, 0x72, 0x3A, 0x25, 0x73, 0x0A, 0x00, 0x6C, 0x6D, 0x74, 0x3A, ++0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x72, 0x65, 0x6A, 0x65, 0x63, 0x74, 0x3A, 0x25, 0x78, 0x00, 0x00, 0x00, ++0x76, 0x73, 0x5F, 0x61, 0x70, 0x63, 0x66, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x6A, 0x65, 0x63, 0x74, 0x32, 0x3A, ++0x25, 0x78, 0x00, 0x00, 0x92, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0x86, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, ++0x92, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0x8C, 0x73, 0x10, 0x00, 0xC0, 0x72, 0x10, 0x00, ++0x6E, 0x6F, 0x61, 0x6C, 0x63, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, 0x00, 0x62, 0x62, 0x5F, 0x74, 0x78, 0x5F, 0x74, 0x6F, ++0x6E, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x6F, 0x70, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x6D, 0x73, 0x73, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6D, 0x73, 0x73, 0x65, 0x72, 0x72, 0x0A, 0x00, 0x46, 0x4C, 0x55, 0x53, 0x48, 0x3A, 0x25, 0x78, ++0x0A, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x4B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x25, 0x78, 0x20, 0x00, 0x6F, 0x70, 0x63, 0x3A, ++0x25, 0x78, 0x0A, 0x00, 0x69, 0x20, 0x3D, 0x20, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x3A, 0x25, 0x78, ++0x0A, 0x00, 0x00, 0x00, 0x6F, 0x70, 0x6C, 0x6C, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x1E, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xBE, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, ++0xFC, 0x89, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xDA, 0x89, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0x4C, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xE8, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0x62, 0x8A, 0x10, 0x00, 0x55, 0x50, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, ++0x25, 0x78, 0x0A, 0x00, 0x6F, 0x70, 0x6C, 0x6C, 0x63, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x63, 0x72, ++0x78, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x63, 0x74, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, ++0x61, 0x70, 0x63, 0x66, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x61, 0x74, 0x65, 0x6E, 0x63, 0x79, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x66, 0x5F, 0x72, 0x65, 0x73, 0x65, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x45, 0x52, 0x52, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x41, 0x53, 0x53, 0x45, ++0x52, 0x54, 0x5F, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x28, 0x25, 0x73, 0x29, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x25, ++0x78, 0x20, 0x61, 0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x41, 0x53, 0x53, 0x45, ++0x52, 0x54, 0x5F, 0x45, 0x52, 0x52, 0x7A, 0x28, 0x25, 0x73, 0x29, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x61, ++0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x5F, 0x50, ++0x41, 0x52, 0x41, 0x4D, 0x7A, 0x28, 0x30, 0x78, 0x25, 0x58, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x58, 0x29, 0x2C, 0x20, 0x69, ++0x6E, 0x20, 0x25, 0x78, 0x20, 0x61, 0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x70, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0A, 0x00, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x25, ++0x78, 0x0D, 0x0A, 0x00, 0x64, 0x65, 0x6C, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x6F, 0x70, 0x3A, 0x30, 0x78, 0x25, 0x78, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x65, 0x72, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, ++0x74, 0x65, 0x73, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x5F, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, ++0x74, 0x65, 0x73, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x5F, 0x65, 0x78, 0x69, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x74, 0x73, 0x74, 0x5F, 0x65, 0x6E, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x74, 0x73, ++0x74, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x64, 0x72, 0x5F, ++0x70, 0x6B, 0x74, 0x3D, 0x25, 0x78, 0x00, 0x00, 0x66, 0x72, 0x65, 0x71, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0xC0, 0xB8, 0x10, 0x00, 0xB4, 0xB9, 0x10, 0x00, 0x94, 0xBA, 0x10, 0x00, 0xF2, 0xB8, 0x10, 0x00, 0xB0, 0xBA, 0x10, 0x00, ++0xCC, 0xBA, 0x10, 0x00, 0xE8, 0xBA, 0x10, 0x00, 0x04, 0xBB, 0x10, 0x00, 0x70, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, ++0x73, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x68, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x65, 0x3A, 0x25, ++0x34, 0x64, 0x2C, 0x20, 0x6F, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x6F, 0x6C, 0x65, 0x3A, 0x25, 0x34, 0x64, ++0x2C, 0x20, 0x70, 0x6E, 0x3A, 0x25, 0x34, 0x64, 0x20, 0x62, 0x63, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x3A, ++0x25, 0x37, 0x64, 0x2C, 0x20, 0x70, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2E, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x72, 0x3A, ++0x25, 0x64, 0x2E, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x70, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x73, 0x6F, 0x3A, 0x25, ++0x34, 0x64, 0x2C, 0x20, 0x68, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, ++0x62, 0x63, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x70, 0x65, 0x72, 0x3A, ++0x25, 0x64, 0x2E, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2E, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x62, 0x75, 0x72, 0x73, 0x74, 0x5F, 0x74, 0x78, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, ++0x0A, 0x00, 0x00, 0x00, 0x72, 0x78, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x63, 0x68, 0x5F, ++0x70, 0x72, 0x6F, 0x67, 0x5F, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x72, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0A, 0x00, ++0x74, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x0A, 0x00, 0x72, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x0A, 0x00, 0x62, 0x62, 0x5F, 0x74, ++0x73, 0x74, 0x5F, 0x73, 0x74, 0x6F, 0x70, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x02, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC7, 0x03, 0x00, 0x00, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, ++0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, ++0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, ++0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, ++0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, ++0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, ++0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, ++0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, ++0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, ++0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, ++0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, ++0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, ++0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, ++0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, ++0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, ++0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, ++0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, ++0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, ++0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, ++0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, ++0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, ++0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, ++0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, ++0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, ++0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, ++0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, ++0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, ++0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, ++0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, ++0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, ++0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, ++0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, ++0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, ++0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, ++0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, ++0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, ++0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, ++0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, ++0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, ++0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, ++0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, ++0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, ++0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, ++0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, ++0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, ++0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, ++0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, ++0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, ++0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, ++0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, ++0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, ++0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFF, 0xC1, 0xFB, 0xE8, ++0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, ++0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, ++0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, ++0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, ++0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, ++0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, ++0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, ++0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, ++0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, ++0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, ++0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, ++0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, ++0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, ++0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, ++0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, ++0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, ++0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, ++0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, ++0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, ++0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, ++0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, ++0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, ++0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, ++0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, ++0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, ++0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, ++0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, ++0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, ++0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, ++0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, ++0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, ++0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, ++0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, ++0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, ++0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, ++0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, ++0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, ++0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, ++0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, ++0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, ++0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, ++0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, ++0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, ++0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, ++0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, ++0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, ++0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, ++0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, ++0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, ++0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, ++0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, ++0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x01, 0x02, 0x02, 0x03, ++0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, ++0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, ++0x04, 0x05, 0x05, 0x06, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, ++0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, ++0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, ++0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, ++0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, ++0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, ++0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, ++0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, ++0x05, 0x06, 0x06, 0x07, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, ++0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08, 0x00, 0x10, 0x20, 0x30, ++0x40, 0x50, 0x60, 0x70, 0x00, 0x00, 0x01, 0x50, 0x00, 0x03, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x50, ++0x00, 0x02, 0x07, 0x03, 0x0C, 0x04, 0x0D, 0x05, 0x26, 0x06, 0x37, 0x07, 0x2C, 0x08, 0x3D, 0x09, 0x00, 0x00, 0x02, 0x01, ++0x05, 0x00, 0x01, 0x07, 0x00, 0x01, 0x00, 0x00, 0x01, 0x07, 0x00, 0x01, 0x0C, 0x00, 0x03, 0x0D, 0x00, 0x03, 0x06, 0x01, ++0x01, 0x07, 0x01, 0x01, 0x0C, 0x01, 0x03, 0x0D, 0x01, 0x03, 0x00, 0x00, 0x00, 0x27, 0x35, 0x00, 0x2B, 0x00, 0x31, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x22, 0x10, 0x00, 0xFF, 0xF0, 0xAA, 0xFF, 0xFF, 0x00, 0x0F, 0x55, ++0x80, 0x01, 0x00, 0x00, 0xF6, 0xFC, 0xFE, 0x00, 0x03, 0x06, 0x09, 0x0A, 0xF9, 0xFC, 0xFF, 0x02, 0x05, 0x07, 0x09, 0x0C, ++0x0F, 0x11, 0x15, 0x17, 0x50, 0x00, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, 0x50, 0xC3, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, ++0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x24, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x25, ++0x00, 0x80, 0xDE, 0xA9, 0x91, 0x06, 0x7B, 0x00, 0x04, 0x10, 0x04, 0x00, 0x04, 0x00, 0x00, 0x26, 0x00, 0x80, 0xDE, 0xA9, ++0x65, 0x06, 0x7C, 0x00, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x48, ++0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0x7F, 0x24, 0x17, 0x42, 0x40, 0x40, 0x8D, 0x08, 0x7B, 0xB0, 0x14, 0x10, 0x04, 0x00, ++0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, 0x04, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x26, ++0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, ++0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, 0x17, 0x42, 0x40, 0x40, 0xFD, 0x08, 0x7A, 0xB0, ++0x14, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, 0x04, 0x10, 0x04, 0x00, ++0x0C, 0x21, 0x04, 0x26, 0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, ++0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, 0x17, 0x42, 0x40, 0x40, ++0xFD, 0x08, 0x7A, 0xB0, 0x14, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, ++0x04, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x26, 0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, ++0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, ++0x17, 0x42, 0x40, 0x40, 0xFD, 0x08, 0x7A, 0xB0, 0xD0, 0x9E, 0x21, 0x00, 0x1C, 0x1C, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, ++0x1C, 0x1C, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x61, ++0xD6, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x65, 0xD7, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x75, 0xD7, 0x9E, 0x21, 0x00, ++0x70, 0x70, 0xFB, 0xFD, 0xD7, 0x9E, 0x21, 0x00, 0xF0, 0xF0, 0xFB, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, ++0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, ++0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, ++0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, ++0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0B, 0x00, 0x00, 0x04, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0xFF, 0xF9, 0x01, 0x08, ++0x00, 0x00, 0x00, 0x00, 0xAC, 0x2B, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x28, 0x21, 0x16, 0x00, 0xA8, 0x61, 0x00, 0x00, ++0xB8, 0x88, 0x00, 0x00, 0x74, 0x40, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0xED, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xCD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, ++0x60, 0x07, 0x8D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x0D, 0x79, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x6B, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0xDB, 0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, ++0x60, 0xD7, 0x0C, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x58, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x55, 0x00, ++0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, ++0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0xEB, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0xED, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xCD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, ++0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x79, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0xDB, ++0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0xD7, 0x0C, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, ++0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0xDB, ++0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, ++0xEB, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, ++0x6C, 0x00, 0x00, 0x03, 0x60, 0x07, 0xAC, 0xE9, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0x00, 0x03, ++0x60, 0x07, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0x20, 0x03, 0x60, 0xD7, 0x0C, 0xE8, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0xE0, 0x03, 0x60, 0x9F, 0x0D, 0xE8, 0x80, 0x80, 0x80, 0x80, ++0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0xE7, 0x8C, 0x69, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, ++0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x2F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, ++0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, 0x03, 0xC7, 0x8E, 0x00, 0x07, 0xC7, 0x8E, 0x00, 0x0B, 0xC7, 0x8E, 0x00, ++0x0F, 0xC7, 0x8E, 0x00, 0x13, 0xC7, 0x8E, 0x00, 0x17, 0xC7, 0x8E, 0x00, 0x1B, 0xC7, 0x8E, 0x00, 0x1F, 0xC7, 0x8E, 0x00, ++0x23, 0xC7, 0x8E, 0x00, 0x27, 0xC7, 0x8E, 0x00, 0x2B, 0xC7, 0x8E, 0x00, 0x2F, 0xC7, 0x8E, 0x00, 0x33, 0xC7, 0x8E, 0x00, ++0x37, 0xC7, 0x8E, 0x00, 0x3B, 0xC7, 0x8E, 0x00, 0x3F, 0xC7, 0x8E, 0x00, 0x06, 0x81, 0x88, 0x00, 0x0A, 0x81, 0x88, 0x00, ++0x0C, 0xC1, 0x88, 0x00, 0x14, 0xC1, 0x90, 0x00, 0x14, 0x41, 0x91, 0x00, 0x15, 0xC1, 0x91, 0x00, 0x23, 0xC1, 0x91, 0x00, ++0x3F, 0xC1, 0x91, 0x00, 0x3F, 0xC1, 0x92, 0x00, 0x3F, 0x01, 0x94, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, ++0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, ++0x2D, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, 0x33, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x33, 0x38, 0x3A, ++0x33, 0x39, 0x20, 0x2D, 0x20, 0x67, 0x69, 0x74, 0x20, 0x30, 0x61, 0x61, 0x62, 0x66, 0x62, 0x66, 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, ++}; ++ ++struct firmware_info{ ++ char fw_name[30]; ++ char* fw_array; ++ int fw_size; ++}; ++ ++struct firmware_info firmware[]={ ++ {"fmacfw.bin", fmacfw, sizeof(fmacfw)}, ++ {"fw_adid_u03.bin", fw_adid_u03, sizeof(fw_adid_u03)}, ++ {"fw_patch_table_u03.bin", fw_patch_table_u03, sizeof(fw_patch_table_u03)}, ++ {"fw_patch_u03.bin", fw_patch_u03, sizeof(fw_patch_u03)} ++}; ++ ++int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf){ ++ int firmware_number = 0; ++ int index = 0; ++ int fw_size = 0; ++ ++ firmware_number = sizeof(firmware)/sizeof(struct firmware_info); ++ printk("%s search:%s \r\n", __func__ , fw_name); ++ ++ for(index = 0; index < firmware_number; index++){ ++ if(!strcmp(firmware[index].fw_name, fw_name)){ ++ fw_size = firmware[index].fw_size; ++ printk("%s find %s len:%d\r\n", __func__, fw_name, fw_size); ++ *fw_buf = (u32*)firmware[index].fw_array; ++ return fw_size; ++ } ++ } ++ ++ printk("%s %s not found \r\n", __func__, fw_name); ++ ++ return 0; ++} +\ No newline at end of file +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h +new file mode 100644 +index 000000000000..dcf38e9ba302 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h +@@ -0,0 +1,3 @@ ++int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf); ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c +new file mode 100644 +index 000000000000..9514c416b5d6 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c +@@ -0,0 +1,62 @@ ++#include ++#include "aicsdio_txrxif.h" ++#include "aic_bsp_driver.h" ++ ++struct prealloc_txq{ ++ int prealloced; ++ void *txq; ++ size_t size; ++}; ++ ++struct prealloc_txq prealloc_txq; ++#define MAX_TXQ_SIZE 100 * 1024 ++ ++void *aicwf_prealloc_txq_alloc(size_t size) ++{ ++ ++ BUG_ON(size > MAX_TXQ_SIZE); ++ ++ //check prealloc_txq.size ++ if((int)prealloc_txq.size != (int)size) ++ { ++ AICWFDBG(LOGINFO, "%s size is diff will to be kzalloc \r\n", __func__); ++ ++ if(prealloc_txq.txq != NULL) ++ { ++ AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__); ++ kfree(prealloc_txq.txq); ++ prealloc_txq.txq = NULL; ++ } ++ ++ prealloc_txq.size = size; ++ prealloc_txq.prealloced = 0; ++ } ++ ++ //check prealloc or not ++ if(!prealloc_txq.prealloced) ++ { ++ prealloc_txq.txq = kzalloc(size, GFP_KERNEL); ++ if(!prealloc_txq.txq){ ++ AICWFDBG(LOGERROR, "%s txq kzalloc fail \r\n", __func__); ++ }else{ ++ AICWFDBG(LOGINFO, "%s txq kzalloc successful \r\n", __func__); ++ prealloc_txq.prealloced = 1; ++ } ++ }else{ ++ AICWFDBG(LOGINFO, "%s txq not need to kzalloc \r\n", __func__); ++ } ++ ++ return prealloc_txq.txq; ++} ++void aicwf_prealloc_txq_free(void) ++{ ++ if(prealloc_txq.txq != NULL) ++ { ++ AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__); ++ kfree(prealloc_txq.txq); ++ prealloc_txq.txq = NULL; ++ } ++} ++ ++EXPORT_SYMBOL(aicwf_prealloc_txq_alloc); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h +new file mode 100644 +index 000000000000..ce4ee07473b3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h +@@ -0,0 +1,4 @@ ++ ++ ++void aicwf_prealloc_txq_free(void); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c +new file mode 100644 +index 000000000000..3d7b65375adb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c +@@ -0,0 +1,161 @@ ++#include ++#include "md5.h" ++ ++unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; ++ ++void MD5Init(MD5_CTX *context) ++{ ++ context->count[0] = 0; ++ context->count[1] = 0; ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xEFCDAB89; ++ context->state[2] = 0x98BADCFE; ++ context->state[3] = 0x10325476; ++} ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) ++{ ++ unsigned int i = 0,index = 0,partlen = 0; ++ index = (context->count[0] >> 3) & 0x3F; ++ partlen = 64 - index; ++ context->count[0] += inputlen << 3; ++ if(context->count[0] < (inputlen << 3)) ++ context->count[1]++; ++ context->count[1] += inputlen >> 29; ++ ++ if(inputlen >= partlen) ++ { ++ memcpy(&context->buffer[index],input,partlen); ++ MD5Transform(context->state,context->buffer); ++ for(i = partlen;i+64 <= inputlen;i+=64) ++ MD5Transform(context->state,&input[i]); ++ index = 0; ++ } ++ else ++ { ++ i = 0; ++ } ++ memcpy(&context->buffer[index],&input[i],inputlen-i); ++} ++void MD5Final(MD5_CTX *context,unsigned char digest[16]) ++{ ++ unsigned int index = 0,padlen = 0; ++ unsigned char bits[8]; ++ index = (context->count[0] >> 3) & 0x3F; ++ padlen = (index < 56)?(56-index):(120-index); ++ MD5Encode(bits,context->count,8); ++ MD5Update(context,PADDING,padlen); ++ MD5Update(context,bits,8); ++ MD5Encode(digest,context->state,16); ++} ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[j] = input[i] & 0xFF; ++ output[j+1] = (input[i] >> 8) & 0xFF; ++ output[j+2] = (input[i] >> 16) & 0xFF; ++ output[j+3] = (input[i] >> 24) & 0xFF; ++ i++; ++ j+=4; ++ } ++} ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[i] = (input[j]) | ++ (input[j+1] << 8) | ++ (input[j+2] << 16) | ++ (input[j+3] << 24); ++ i++; ++ j+=4; ++ } ++} ++void MD5Transform(unsigned int state[4],unsigned char block[64]) ++{ ++ unsigned int a = state[0]; ++ unsigned int b = state[1]; ++ unsigned int c = state[2]; ++ unsigned int d = state[3]; ++ unsigned int x[64]; ++ MD5Decode(x,block,64); ++ FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ ++ FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ ++ FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ ++ FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ ++ FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ ++ FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ ++ FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ ++ FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ ++ FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ ++ FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ ++ FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ ++ FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ ++ FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ ++ FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ ++ FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ ++ FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ ++ ++ /* Round 2 */ ++ GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ ++ GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ ++ GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ ++ GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ ++ GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ ++ GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ ++ GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ ++ GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ ++ GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ ++ GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ ++ GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ ++ GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ ++ GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ ++ GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ ++ GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ ++ GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ ++ ++ /* Round 3 */ ++ HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ ++ HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ ++ HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ ++ HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ ++ HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ ++ HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ ++ HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ ++ HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ ++ HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ ++ HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ ++ HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ ++ HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ ++ HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ ++ HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ ++ HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ ++ HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ ++ ++ /* Round 4 */ ++ II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ ++ II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ ++ II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ ++ II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ ++ II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ ++ II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ ++ II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ ++ II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ ++ II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ ++ II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ ++ II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ ++ II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ ++ II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ ++ II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ ++ II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ ++ II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h +new file mode 100644 +index 000000000000..6ed5c0f8e886 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h +@@ -0,0 +1,48 @@ ++#ifndef MD5_H ++#define MD5_H ++ ++typedef struct ++{ ++ unsigned int count[2]; ++ unsigned int state[4]; ++ unsigned char buffer[64]; ++}MD5_CTX; ++ ++ ++#define F(x,y,z) ((x & y) | (~x & z)) ++#define G(x,y,z) ((x & z) | (y & ~z)) ++#define H(x,y,z) (x^y^z) ++#define I(x,y,z) (y ^ (x | ~z)) ++#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) ++#define FF(a,b,c,d,x,s,ac) \ ++ { \ ++ a += F(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define GG(a,b,c,d,x,s,ac) \ ++ { \ ++ a += G(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define HH(a,b,c,d,x,s,ac) \ ++ { \ ++ a += H(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define II(a,b,c,d,x,s,ac) \ ++ { \ ++ a += I(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++void MD5Init(MD5_CTX *context); ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); ++void MD5Final(MD5_CTX *context,unsigned char digest[16]); ++void MD5Transform(unsigned int state[4],unsigned char block[64]); ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h +new file mode 100644 +index 000000000000..6fcb679c8934 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h +@@ -0,0 +1,4 @@ ++#define RWNX_VERS_REV "241c091M (master)" ++#define RWNX_VERS_MOD "6.4.3.0" ++#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" ++#define RELEASE_DATE "2025_0410_b99ca8b6" +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore +new file mode 100644 +index 000000000000..c3c2d151e157 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig +new file mode 100644 +index 000000000000..ff7aaa649f83 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig +@@ -0,0 +1,5 @@ ++config AIC8800_BTLPM_SUPPORT ++ tristate "AIC8800 bluetooth Support" ++ help ++ This is support for aic bluetooh driver. ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile +new file mode 100644 +index 000000000000..6d59301f9741 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile +@@ -0,0 +1,83 @@ ++CONFIG_AIC8800_BTLPM_SUPPORT = m ++ ++obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) := aic8800_btlpm.o ++ ++ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp ++ ++# Platform support list ++CONFIG_PLATFORM_ROCKCHIP ?= n ++CONFIG_PLATFORM_ROCKCHIP2 ?= n ++CONFIG_PLATFORM_ALLWINNER ?= n ++CONFIG_PLATFORM_AMLOGIC ?= n ++CONFIG_PLATFORM_UBUNTU ?= y ++ ++ ++CONFIG_SUPPORT_LPM ?= n ++CONFIG_AUTO_PM ?= n ++ ++aic8800_btlpm-y := \ ++ aic_bluetooth_main.o \ ++ rfkill.o \ ++ ++aic8800_btlpm-$(CONFIG_SUPPORT_LPM) += lpm.o ++ ++ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) ++ ++ccflags-$(CONFIG_AUTO_PM) += -DCONFIG_AUTO_PM ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ARCH = arm64 ++KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++ARCH = arm64 ++KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++KDIR ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9/ ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ccflags-$(CONFIG_PLATFORM_NANOPI) += -DCONFIG_PLATFORM_NANOPI ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++KDIR ?= /lib/modules/$(shell uname -r)/build ++PWD ?= $(shell pwd) ++KVER ?= $(shell uname -r) ++MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ++ARCH ?= x86_64 ++CROSS_COMPILE ?= ++endif ++ ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c +new file mode 100644 +index 000000000000..52d768d83da8 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c +@@ -0,0 +1,1167 @@ ++/* ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++#include ++#endif ++ ++#include "aic_bsp_export.h" ++ ++/* ++ * #define BT_SLEEP_DBG ++ */ ++#define BT_SLEEP_DBG ++#undef BT_DBG ++#undef BT_ERR ++#ifdef BT_SLEEP_DBG ++#define BT_DBG(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++#else ++#define BT_DBG(fmt, arg...) ++#endif ++#define BT_ERR(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++ ++/* ++ * Defines ++ */ ++ ++#define VERSION "1.3.3" ++#define PROC_DIR "bluetooth/sleep" ++ ++#define DEFAULT_UART_INDEX 1 ++#define BT_BLUEDROID_SUPPORT 1 ++static int bluesleep_start(void); ++static void bluesleep_stop(void); ++ ++struct bluesleep_info { ++ unsigned int wakeup_enable; ++ unsigned host_wake; ++ unsigned ext_wake; ++ unsigned host_wake_irq; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ struct wakeup_source *ws; ++#else ++ struct wake_lock wake_lock; ++#endif ++ struct uart_port *uport; ++ unsigned host_wake_assert:1; ++ unsigned ext_wake_assert:1; ++ struct platform_device *pdev; ++}; ++ ++/* work function */ ++static void bluesleep_sleep_work(struct work_struct *work); ++static void bluesleep_tx_allow_sleep(void); ++ ++/* work queue */ ++DECLARE_DELAYED_WORK(sleep_workqueue, bluesleep_sleep_work); ++ ++/* Macros for handling sleep work */ ++#define bluesleep_rx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_rx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++ ++/* 1 second timeout */ ++#define RX_TIMER_INTERVAL 1 ++ ++/* state variable names and bit positions */ ++#define BT_PROTO 0x01 ++#define BT_TXDATA 0x02 ++#define BT_ASLEEP 0x04 ++#define BT_TXIDLE 0x08 ++#define BT_PAUSE 0x09 ++#define BT_RXTIMER 0x0a ++ ++#if BT_BLUEDROID_SUPPORT ++static bool has_lpm_enabled; ++#else ++/* global pointer to a single hci device. */ ++static struct hci_dev *bluesleep_hdev; ++#endif ++ ++#if BT_BLUEDROID_SUPPORT ++static struct platform_device *bluesleep_uart_dev; ++#endif ++static struct bluesleep_info *bsi; ++ ++/* module usage */ ++static atomic_t open_count = ATOMIC_INIT(1); ++ ++/* ++ * Local function prototypes ++ */ ++ ++#if !BT_BLUEDROID_SUPPORT ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data); ++#endif ++ ++/* ++ * Global variables ++ */ ++ ++/** Global state flags */ ++static unsigned long flags; ++ ++/** Tasklet to respond to change in hostwake line */ ++static struct tasklet_struct hostwake_task; ++ ++/** Reception timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t); ++#else ++static void bluesleep_rx_timer_expire(unsigned long data); ++#endif ++static struct timer_list rx_timer; ++ ++/** Lock for state transitions */ ++static spinlock_t rw_lock; ++ ++#if !BT_BLUEDROID_SUPPORT ++/** Notifier block for HCI events */ ++struct notifier_block hci_event_nblock = { ++ .notifier_call = bluesleep_hci_event, ++}; ++#endif ++ ++struct proc_dir_entry *bluetooth_dir, *sleep_dir; ++ ++/* ++ * Local functions ++ */ ++ ++/* ++ * bt go to sleep will call this function tell uart stop data interactive ++ */ ++static void hsuart_power(int on) ++{ ++ if (bsi->uport != NULL) { ++ if (on) ++ bsi->uport->ops->set_mctrl(bsi->uport, TIOCM_RTS); ++ else ++ bsi->uport->ops->set_mctrl(bsi->uport, 0); ++ } else { ++ BT_ERR("bsi->uport = NULL, has_lpm_enabled = %d", has_lpm_enabled); ++ } ++} ++ ++/** ++ * @return 1 if the Host can go to sleep, 0 otherwise. ++ */ ++static inline int bluesleep_can_sleep(void) ++{ ++ /* check if HOST_WAKE_BT_GPIO and BT_WAKE_HOST_GPIO ++ * are both deasserted ++ */ ++ return (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) && ++ (gpio_get_value(bsi->host_wake) != bsi->host_wake_assert) && ++ (!test_bit(BT_RXTIMER, &flags)) && (bsi->uport != NULL); ++} ++ ++/** ++ * @brief@ main sleep work handling function which update the flags ++ * and activate and deactivate UART ,check FIFO. ++ */ ++static void bluesleep_sleep_work(struct work_struct *work) ++{ ++ if (!has_lpm_enabled) ++ return; ++ ++ if (bluesleep_can_sleep()) { ++ /* already asleep, this is an error case */ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("already asleep"); ++ return; ++ } ++ if (bsi->uport->ops->tx_empty(bsi->uport)) { ++ BT_DBG("going to sleep..."); ++ set_bit(BT_ASLEEP, &flags); ++ /*Deactivating UART */ ++ hsuart_power(0); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++ } else { ++ BT_DBG("This should never happen.\n"); ++ return; ++ } ++ } else if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("hold wake locks for rx_task."); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ clear_bit(BT_ASLEEP, &flags); ++ ++ /* Add a timer to make sure that UART ++ * would not be turned on&off very frequentently ++ */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ ++ set_bit(BT_RXTIMER, &flags); ++ hsuart_power(1); ++ } else { ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ set_bit(BT_RXTIMER, &flags); ++ ++ if(test_bit(BT_PAUSE, &flags)){ ++ BT_DBG("rx wake du BT_PAUSE:%lx", flags); ++ ///enable bt sleep immediately ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } else if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert ++ && !test_bit(BT_TXIDLE, &flags)) { ++ BT_DBG("force retrigger bt wake:%lx", flags); ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ msleep(20); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } ++ } ++} ++ ++/** ++ * A tasklet function that runs in tasklet context and reads the value ++ * of the HOST_WAKE GPIO pin and further defer the work. ++ * @param data Not used. ++ */ ++static void bluesleep_hostwake_task(unsigned long data) ++{ ++ BT_DBG("hostwake line change"); ++ spin_lock(&rw_lock); ++ ++ if (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert) ++ bluesleep_rx_busy(); ++ else ++ bluesleep_rx_idle(); ++ ++ spin_unlock(&rw_lock); ++} ++ ++/** ++ * Handles proper timer action when outgoing data is delivered to the ++ * HCI line discipline. Sets BT_TXDATA. ++ */ ++static void bluesleep_outgoing_data(void) ++{ ++ unsigned long irq_flags; ++ int power_on_uart = 0; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ /* if the tx side is sleeping... */ ++ if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) { ++ BT_DBG("tx was sleeping, wakeup it"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ clear_bit(BT_ASLEEP, &flags); ++ clear_bit(BT_TXIDLE, &flags); ++ power_on_uart = 1; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ if (power_on_uart == 1) ++ hsuart_power(1); ++} ++ ++#if BT_BLUEDROID_SUPPORT ++static struct uart_port *bluesleep_get_uart_port(void) ++{ ++ struct uart_port *uport = NULL; ++ ++ if (bluesleep_uart_dev) { ++ uport = platform_get_drvdata(bluesleep_uart_dev); ++ if (uport) ++ BT_DBG( ++ "%s get uart_port from blusleep_uart_dev: %s, port irq: %d", ++ __func__, bluesleep_uart_dev->name, uport->irq); ++ } ++ return uport; ++} ++ ++static int bluesleep_lpm_proc_show(struct seq_file *m, void *v) ++{ ++ seq_printf(m, "lpm enable: %d\n", has_lpm_enabled); ++ return 0; ++} ++ ++static int bluesleep_lpm_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_lpm_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_lpm(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ if (b == '0') { ++#if 1 ++ set_bit(BT_PAUSE, &flags); ++ set_bit(BT_TXIDLE, &flags); ++ clear_bit(BT_TXDATA, &flags); ++ /* deassert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++#else ++ /* HCI_DEV_UNREG */ ++ bluesleep_stop(); ++ has_lpm_enabled = false; ++ bsi->uport = NULL; ++#endif ++ } else { ++ clear_bit(BT_PAUSE, &flags); ++ /* HCI_DEV_REG */ ++ if (!has_lpm_enabled) { ++ has_lpm_enabled = true; ++ if (bluesleep_uart_dev) ++ bsi->uport = bluesleep_get_uart_port(); ++ ++ /* if bluetooth started, start bluesleep*/ ++ bluesleep_start(); ++ } ++ } ++ ++ return count; ++} ++ ++static int bluesleep_btwrite_proc_show(struct seq_file *m, void *v) ++{ ++ seq_puts(m, "it's not support\n"); ++ return 0; ++} ++ ++static int bluesleep_btwrite_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_btwrite_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_btwrite(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ /* HCI_DEV_WRITE */ ++ if (b != '0') ++ bluesleep_outgoing_data(); ++ else ++ bluesleep_tx_allow_sleep(); ++ ++ return count; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops lpm_fops = { ++ .proc_open = bluesleep_lpm_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_lpm, ++}; ++static const struct proc_ops btwrite_fops = { ++ .proc_open = bluesleep_btwrite_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_btwrite, ++}; ++ ++#else ++ ++static const struct file_operations lpm_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_lpm_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_lpm, ++}; ++static const struct file_operations btwrite_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_btwrite_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_btwrite, ++}; ++#endif ++ ++#else ++/** ++ * Handles HCI device events. ++ * @param this Not used. ++ * @param event The event that occurred. ++ * @param data The HCI device associated with the event. ++ * @return NOTIFY_DONE. ++ */ ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data) ++{ ++ struct hci_dev *hdev = (struct hci_dev *) data; ++ struct hci_uart *hu; ++ struct uart_state *state; ++ ++ if (!hdev) ++ return NOTIFY_DONE; ++ ++ switch (event) { ++ case HCI_DEV_REG: ++ if (!bluesleep_hdev) { ++ bluesleep_hdev = hdev; ++ hu = (struct hci_uart *) hdev->driver_data; ++ state = (struct uart_state *) hu->tty->driver_data; ++ bsi->uport = state->uart_port; ++ } ++ break; ++ case HCI_DEV_UNREG: ++ bluesleep_hdev = NULL; ++ bsi->uport = NULL; ++ break; ++ case HCI_DEV_WRITE: ++ bluesleep_outgoing_data(); ++ break; ++ } ++ ++ return NOTIFY_DONE; ++} ++#endif ++ ++/** ++ * Function to check wheather bluetooth can sleep when btwrite was deasserted ++ * by bluedroid. ++ */ ++static void bluesleep_tx_allow_sleep(void) ++{ ++ unsigned long irq_flags; ++ BT_DBG("Tx has been idle\n"); ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ set_bit(BT_TXIDLE, &flags); ++ clear_bit(BT_TXDATA, &flags); ++ bluesleep_tx_idle(); ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++} ++ ++ ++/* Handles reception timer expiration. ++ * Clear BT_RXTIMER. ++ * @param data Not used. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t) ++#else ++static void bluesleep_rx_timer_expire(unsigned long data) ++#endif ++{ ++ BT_DBG("bluesleep_rx_timer_expire"); ++ clear_bit(BT_RXTIMER, &flags); ++ bluesleep_rx_idle(); ++} ++ ++/** ++ * Schedules a tasklet to run when receiving an interrupt on the ++ * HOST_WAKE GPIO pin. ++ * @param irq Not used. ++ * @param dev_id Not used. ++ */ ++static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id) ++{ ++ /* schedule a tasklet to handle the change in the host wake line */ ++ tasklet_schedule(&hostwake_task); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * Starts the Sleep-Mode Protocol on the Host. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++static int bluesleep_start(void) ++{ ++ int retval; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return 0; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ ++ if (!atomic_dec_and_test(&open_count)) { ++ atomic_inc(&open_count); ++ return -EBUSY; ++ } ++ ++ /* start the timer */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL*HZ)); ++ /*deassert BT_WAKE first*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ msleep(20); ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ retval = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr, ++ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, ++ "bluetooth hostwake", &bsi->pdev->dev); ++ if (retval < 0) { ++ BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ"); ++ goto fail; ++ } ++ ++ set_bit(BT_PROTO, &flags); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ ++ return 0; ++fail: ++ del_timer(&rx_timer); ++ atomic_inc(&open_count); ++ ++ return retval; ++} ++ ++/** ++ * Stops the Sleep-Mode Protocol on the Host. ++ */ ++static void bluesleep_stop(void) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (!test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return; ++ } ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ ++ del_timer(&rx_timer); ++ clear_bit(BT_PROTO, &flags); ++ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ clear_bit(BT_ASLEEP, &flags); ++ hsuart_power(1); ++ } ++ ++ atomic_inc(&open_count); ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++} ++#if 0 ++/** ++ * Read the BT_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the ++ * pin is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_btwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "btwake:%u\n", ++ (gpio_get_value(bsi->ext_wake) == bsi->ext_wake_assert)); ++} ++ ++/** ++ * Write the BT_WAKE GPIO pin value via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluepower_write_proc_btwake(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char *buf; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ buf = kmalloc(count, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ if (copy_from_user(buf, buffer, count)) { ++ kfree(buf); ++ return -EFAULT; ++ } ++ ++ if (buf[0] == '0') { ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } else if (buf[0] == '1') { ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ } else { ++ kfree(buf); ++ return -EINVAL; ++ } ++ ++ kfree(buf); ++ return count; ++} ++ ++/** ++ * Read the BT_HOST_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the pin ++ * is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_hostwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "hostwake: %u\n", ++ (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert)); ++} ++ ++ ++/** ++ * Read the low-power status of the Host via the proc interface. ++ * When this function returns, page contains a 1 if the Host ++ * is asleep, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_asleep(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int asleep; ++ ++ asleep = test_bit(BT_ASLEEP, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "asleep: %u\n", asleep); ++} ++ ++/** ++ * Read the low-power protocol being used by the Host via the proc interface. ++ * When this function returns, page will contain a 1 if the Host ++ * is using the Sleep Mode Protocol, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_proto(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int proto; ++ ++ proto = test_bit(BT_PROTO, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "proto: %u\n", proto); ++} ++ ++/** ++ * Modify the low-power protocol used by the Host via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluesleep_write_proc_proto(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char proto; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&proto, buffer, 1)) ++ return -EFAULT; ++ ++ if (proto == '0') ++ bluesleep_stop(); ++ else ++ bluesleep_start(); ++ ++ /* claim that we wrote everything */ ++ return count; ++} ++#endif ++ ++static int assert_level = -1; ++module_param(assert_level, int, S_IRUGO); ++MODULE_PARM_DESC(assert_level, "BT_LPM hostwake/btwake assert level"); ++ ++static struct platform_device *sw_uart_get_pdev(int id) ++{ ++ struct device_node *np; ++ char match[20]; ++ sprintf(match, "uart%d", id); ++ np = of_find_node_by_type(NULL, match); ++ return of_find_device_by_node(np); ++} ++ ++static int __init bluesleep_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device *dev = &pdev->dev; ++ enum of_gpio_flags config; ++ int ret, uart_index; ++ u32 val; ++ struct aicbsp_feature_t bsp_feature_lpm; ++ ++ bsi = devm_kzalloc(&pdev->dev, sizeof(struct bluesleep_info), ++ GFP_KERNEL); ++ if (!bsi) ++ return -ENOMEM; ++ ++ bsi->host_wake = of_get_named_gpio_flags(np, "bt_hostwake", 0, &config); ++ if (!gpio_is_valid(bsi->host_wake)) { ++ BT_ERR("get gpio bt_hostwake failed\n"); ++ ret = -EINVAL; ++ goto err0; ++ } ++ ++ /* set host_wake_assert */ ++ aicbsp_get_feature(&bsp_feature_lpm); ++ if (bsp_feature_lpm.irqf == 0) ++ bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ else ++ bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 1 : 0; ++ ++ BT_DBG("bt_hostwake gpio=%d assert=%d\n", bsi->host_wake, bsi->host_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->host_wake_assert = (assert_level & 0x02) > 0; ++ BT_DBG("override host_wake assert to %d", bsi->host_wake_assert); ++ } ++ ++ ret = devm_gpio_request(dev, bsi->host_wake, "bt_hostwake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_hostwake gpio %d\n", ++ bsi->host_wake); ++ goto err0; ++ } ++ ret = gpio_direction_input(bsi->host_wake); ++ if (ret < 0) { ++ BT_ERR("can't request input direction bt_wake gpio %d\n", ++ bsi->host_wake); ++ goto err1; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (!of_property_read_bool(np, "wakeup-source")) { ++#else ++ if (!of_property_read_u32(np, "wakeup-source", &bsi->wakeup_enable) && ++ (bsi->wakeup_enable == 0)) { ++#endif ++ BT_DBG("wakeup source is disabled!\n"); ++ } else { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ ret = device_init_wakeup(dev, true); ++ if (ret < 0) { ++ BT_ERR("device init wakeup failed!\n"); ++ goto err1; ++ } ++ ret = dev_pm_set_wake_irq(dev, gpio_to_irq(bsi->host_wake)); ++ if (ret < 0) { ++ BT_ERR("can't enable wakeup src for bt_hostwake %d\n", ++ bsi->host_wake); ++ goto err2; ++ } ++ bsi->wakeup_enable = 1; ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ } ++ ++ bsi->ext_wake = of_get_named_gpio_flags(np, "bt_wake", 0, &config); ++ if (!gpio_is_valid(bsi->ext_wake)) { ++ BT_ERR("get gpio bt_wake failed\n"); ++ ret = -EINVAL; ++ goto err2; ++ } ++ ++ ret = devm_gpio_request(dev, bsi->ext_wake, "bt_wake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err2; ++ } ++ ++ /* set ext_wake_assert */ ++ bsi->ext_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ BT_DBG("bt_wake gpio=%d assert=%d\n", bsi->ext_wake, bsi->ext_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->ext_wake_assert = (assert_level & 0x01) > 0; ++ BT_DBG("override ext_wake assert to %d", bsi->ext_wake_assert); ++ } ++ ++ /* 1.set bt_wake as output and the level is assert, assert bt wake */ ++ ret = gpio_direction_output(bsi->ext_wake, bsi->ext_wake_assert); ++ if (ret < 0) { ++ BT_ERR("can't request output direction bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err3; ++ } ++ /*set ext_wake deassert as default*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ ++ /* 2.get bt_host_wake gpio irq */ ++ bsi->host_wake_irq = gpio_to_irq(bsi->host_wake); ++ if (bsi->host_wake_irq < 0) { ++ BT_ERR("map gpio [%d] to virq failed, errno = %d\n", ++ bsi->host_wake, bsi->host_wake_irq); ++ ret = -ENODEV; ++ goto err3; ++ } ++ ++ uart_index = DEFAULT_UART_INDEX; ++ if (!of_property_read_u32(np, "uart_index", &val)) { ++ switch (val) { ++ case 0: ++ case 1: ++ case 2: ++ uart_index = val; ++ break; ++ default: ++ BT_ERR("unsupported uart_index (%u)\n", val); ++ } ++ } ++ BT_DBG("uart_index (%u)\n", uart_index); ++ bluesleep_uart_dev = sw_uart_get_pdev(uart_index); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ bsi->ws = wakeup_source_register(dev, "bluesleep"); ++#else ++ wake_lock_init(&bsi->wake_lock, WAKE_LOCK_SUSPEND, "bluesleep"); ++#endif ++ bsi->pdev = pdev; ++ ++ return 0; ++ ++err3: ++ devm_gpio_free(dev, bsi->ext_wake); ++err2: ++ device_init_wakeup(dev, false); ++err1: ++ devm_gpio_free(dev, bsi->host_wake); ++err0: ++ devm_kfree(dev, bsi); ++ ++ BT_ERR("probe fail, err: %d", ret); ++ return ret; ++} ++ ++static int bluesleep_remove(struct platform_device *pdev) ++{ ++ /* assert bt wake */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ if (test_bit(BT_PROTO, &flags)) { ++ if (disable_irq_wake(bsi->host_wake_irq)) ++ BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n"); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++ del_timer(&rx_timer); ++ if (test_bit(BT_ASLEEP, &flags)) ++ hsuart_power(1); ++ } ++ gpio_free(bsi->host_wake); ++ gpio_free(bsi->ext_wake); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ wakeup_source_unregister(bsi->ws); ++#else ++ wake_lock_destroy(&bsi->wake_lock); ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ if (bsi->wakeup_enable) { ++ BT_DBG("Deinit wakeup source"); ++ device_init_wakeup(&pdev->dev, false); ++ dev_pm_clear_wake_irq(&pdev->dev); ++ } ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ return 0; ++} ++ ++#ifdef CONFIG_AUTO_PM ++static int bluesleep_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ printk("%s\n", __func__); ++ ++ bluesleep_tx_allow_sleep(); ++ return 0; ++} ++ ++static int bluesleep_resume(struct platform_device *pdev) ++{ ++ printk("%s\n", __func__); ++ ++ bluesleep_outgoing_data(); ++ return 0; ++} ++#endif ++ ++static const struct of_device_id sunxi_btlpm_ids[] = { ++ { .compatible = "allwinner,sunxi-btlpm" }, ++ { /* Sentinel */ } ++}; ++ ++static struct platform_driver bluesleep_driver = { ++ .remove = bluesleep_remove, ++#ifdef CONFIG_AUTO_PM ++ .suspend = bluesleep_suspend, ++ .resume = bluesleep_resume, ++#endif ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "sunxi-btlpm", ++ .of_match_table = sunxi_btlpm_ids, ++ }, ++}; ++ ++/** ++ * Initializes the module. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++static int __init bluesleep_init(void) ++{ ++ int retval; ++ struct proc_dir_entry *ent; ++ ++ BT_DBG("BlueSleep Mode Driver Ver %s", VERSION); ++ ++ retval = platform_driver_probe(&bluesleep_driver, bluesleep_probe); ++ if (retval) ++ return retval; ++ ++#if !BT_BLUEDROID_SUPPORT ++ bluesleep_hdev = NULL; ++#endif ++ ++ bluetooth_dir = proc_mkdir("bluetooth", NULL); ++ if (bluetooth_dir == NULL) { ++ BT_ERR("Unable to create /proc/bluetooth directory"); ++ return -ENOMEM; ++ } ++ ++ sleep_dir = proc_mkdir("sleep", bluetooth_dir); ++ if (sleep_dir == NULL) { ++ BT_ERR("Unable to create /proc/%s directory", PROC_DIR); ++ return -ENOMEM; ++ } ++#if 0 ++ /* Creating read/write "btwake" entry */ ++ ent = create_proc_entry("btwake", 0, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluepower_read_proc_btwake; ++ ent->write_proc = bluepower_write_proc_btwake; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("hostwake", 0, sleep_dir, ++ bluepower_read_proc_hostwake, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* read/write proc entries */ ++ ent = create_proc_entry("proto", 0666, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluesleep_read_proc_proto; ++ ent->write_proc = bluesleep_write_proc_proto; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("asleep", 0, ++ sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++#if BT_BLUEDROID_SUPPORT ++ /* read/write proc entries */ ++ ent = proc_create("lpm", 0660, sleep_dir, &lpm_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/lpm entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ ent = proc_create("btwrite", 0660, sleep_dir, &btwrite_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwrite entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++ ++ flags = 0; /* clear all status bits */ ++ ++ /* Initialize spinlock. */ ++ spin_lock_init(&rw_lock); ++ ++ /* Initialize timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ timer_setup(&rx_timer, bluesleep_rx_timer_expire, 0); ++#else ++ init_timer(&rx_timer); ++ rx_timer.function = bluesleep_rx_timer_expire; ++ rx_timer.data = 0; ++#endif ++ ++ /* initialize host wake tasklet */ ++ tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); ++ ++#if !BT_BLUEDROID_SUPPORT ++ hci_register_notifier(&hci_event_nblock); ++#endif ++ ++ return 0; ++ ++fail: ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++ return retval; ++} ++ ++/** ++ * Cleans up the module. ++ */ ++static void __exit bluesleep_exit(void) ++{ ++#if !BT_BLUEDROID_SUPPORT ++ hci_unregister_notifier(&hci_event_nblock); ++#endif ++ platform_driver_unregister(&bluesleep_driver); ++ ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++} ++ ++module_init(bluesleep_init); ++module_exit(bluesleep_exit); ++ ++MODULE_DESCRIPTION("Bluetooth Sleep Mode Driver ver %s " VERSION); ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c +new file mode 100644 +index 000000000000..122d867f0ed6 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c +@@ -0,0 +1,88 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "lpm.h" ++#include "rfkill.h" ++ ++#define DRV_CONFIG_FW_NAME "fw.bin" ++#define DRV_DESCRIPTION "AIC BLUETOOTH" ++#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi" ++#define DRV_AUTHOR "AICSemi" ++#define DRV_VERS_MOD "1.0" ++ ++static struct platform_device *aicbt_pdev; ++ ++static struct platform_driver aicbt_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "aic_bt", ++ }, ++ //.probe = aicbt_probe, ++ //.remove = aicbt_remove, ++}; ++ ++static int __init aic_bluetooth_mod_init(void) ++{ ++ int ret; ++ printk("%s\n", __func__); ++ ret = platform_driver_register(&aicbt_driver); ++ if (ret) { ++ pr_err("register platform driver failed: %d\n", ret); ++ return ret; ++ } ++ ++ aicbt_pdev = platform_device_alloc("aic-bt", -1); ++ ret = platform_device_add(aicbt_pdev); ++ if (ret) { ++ pr_err("register platform device failed: %d\n", ret); ++ goto err0; ++ } ++ ++ ret = rfkill_bluetooth_init(aicbt_pdev); ++ if (ret) { ++ pr_err("rfkill init fail\n"); ++ goto err1; ++ } ++#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) ++ ret = bluesleep_init(aicbt_pdev); ++ if (ret) { ++ pr_err("bluesleep init fail\n"); ++ goto err2; ++ } ++#endif ++ ++ return 0; ++ ++#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) ++err2: ++#endif ++ rfkill_bluetooth_remove(aicbt_pdev); ++err1: ++ platform_device_del(aicbt_pdev); ++err0: ++ platform_driver_unregister(&aicbt_driver); ++ return ret; ++} ++ ++static void __exit aic_bluetooth_mod_exit(void) ++{ ++ printk("%s\n", __func__); ++#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) ++ bluesleep_exit(aicbt_pdev); ++#endif ++ rfkill_bluetooth_remove(aicbt_pdev); ++ platform_device_del(aicbt_pdev); ++ platform_driver_unregister(&aicbt_driver); ++} ++ ++module_init(aic_bluetooth_mod_init); ++module_exit(aic_bluetooth_mod_exit); ++ ++MODULE_DESCRIPTION(DRV_DESCRIPTION); ++MODULE_VERSION(DRV_VERS_MOD); ++MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h +new file mode 100644 +index 000000000000..88f6b565cd5f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h +@@ -0,0 +1,19 @@ ++#ifndef __AIC_BSP_EXPORT_H ++#define __AIC_BSP_EXPORT_H ++ ++#define AIC_BLUETOOTH 0 ++#define AIC_WIFI 1 ++#define AIC_PWR_OFF 0 ++#define AIC_PWR_ON 1 ++ ++struct aicbsp_feature_t { ++ bool band_5g_support; ++ uint32_t sdio_clock; ++ uint8_t sdio_phase; ++ uint8_t irqf; ++}; ++ ++int aicbsp_set_subsys(int, int); ++int aicbsp_get_feature(struct aicbsp_feature_t *feature); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c +new file mode 100644 +index 000000000000..6e9b71564f19 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c +@@ -0,0 +1,1111 @@ ++/* ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#endif ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++#include ++#endif ++ ++/* ++ * #define BT_SLEEP_DBG ++ */ ++#define BT_SLEEP_DBG ++#undef BT_DBG ++#undef BT_ERR ++#ifdef BT_SLEEP_DBG ++#define BT_DBG(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++#else ++#define BT_DBG(fmt, arg...) ++#endif ++#define BT_ERR(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++ ++/* ++ * Defines ++ */ ++ ++#define VERSION "1.3.3" ++#define PROC_DIR "bluetooth/sleep" ++ ++#define DEFAULT_UART_INDEX 1 ++#define BT_BLUEDROID_SUPPORT 1 ++static int bluesleep_start(void); ++static void bluesleep_stop(void); ++ ++struct bluesleep_info { ++ unsigned int wakeup_enable; ++ unsigned host_wake; ++ unsigned ext_wake; ++ unsigned host_wake_irq; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ struct wakeup_source *ws; ++#else ++ struct wake_lock wake_lock; ++#endif ++ struct uart_port *uport; ++ unsigned host_wake_assert:1; ++ unsigned ext_wake_assert:1; ++ struct platform_device *pdev; ++}; ++ ++/* work function */ ++static void bluesleep_sleep_work(struct work_struct *work); ++static void bluesleep_tx_allow_sleep(void); ++ ++/* work queue */ ++DECLARE_DELAYED_WORK(sleep_workqueue, bluesleep_sleep_work); ++ ++/* Macros for handling sleep work */ ++#define bluesleep_rx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_rx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++ ++/* 1 second timeout */ ++#define RX_TIMER_INTERVAL 1 ++ ++/* state variable names and bit positions */ ++#define BT_PROTO 0x01 ++#define BT_TXDATA 0x02 ++#define BT_ASLEEP 0x04 ++#define BT_RXTIMER 0x20 ++#define BT_TXIDLE 0x08 ++ ++#if BT_BLUEDROID_SUPPORT ++static bool has_lpm_enabled; ++#else ++/* global pointer to a single hci device. */ ++static struct hci_dev *bluesleep_hdev; ++#endif ++ ++#if BT_BLUEDROID_SUPPORT ++static struct platform_device *bluesleep_uart_dev; ++#endif ++static struct bluesleep_info *bsi; ++ ++/* module usage */ ++static atomic_t open_count = ATOMIC_INIT(1); ++ ++/* ++ * Local function prototypes ++ */ ++ ++#if !BT_BLUEDROID_SUPPORT ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data); ++#endif ++ ++/* ++ * Global variables ++ */ ++ ++/** Global state flags */ ++static unsigned long flags; ++ ++/** Tasklet to respond to change in hostwake line */ ++static struct tasklet_struct hostwake_task; ++ ++/** Reception timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t); ++#else ++static void bluesleep_rx_timer_expire(unsigned long data); ++#endif ++static struct timer_list rx_timer; ++ ++/** Lock for state transitions */ ++static spinlock_t rw_lock; ++ ++#if !BT_BLUEDROID_SUPPORT ++/** Notifier block for HCI events */ ++struct notifier_block hci_event_nblock = { ++ .notifier_call = bluesleep_hci_event, ++}; ++#endif ++ ++struct proc_dir_entry *bluetooth_dir, *sleep_dir; ++ ++/* ++ * Local functions ++ */ ++ ++/* ++ * bt go to sleep will call this function tell uart stop data interactive ++ */ ++static void hsuart_power(int on) ++{ ++ if (bsi->uport != NULL) { ++ if (on) ++ bsi->uport->ops->set_mctrl(bsi->uport, TIOCM_RTS); ++ else ++ bsi->uport->ops->set_mctrl(bsi->uport, 0); ++ } else { ++ BT_ERR("bsi->uport = NULL, has_lpm_enabled = %d", has_lpm_enabled); ++ } ++} ++ ++/** ++ * @return 1 if the Host can go to sleep, 0 otherwise. ++ */ ++static inline int bluesleep_can_sleep(void) ++{ ++ /* check if HOST_WAKE_BT_GPIO and BT_WAKE_HOST_GPIO ++ * are both deasserted ++ */ ++ return (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) && ++ (gpio_get_value(bsi->host_wake) != bsi->host_wake_assert) && ++ (!test_bit(BT_RXTIMER, &flags)) && (bsi->uport != NULL); ++} ++ ++/** ++ * @brief@ main sleep work handling function which update the flags ++ * and activate and deactivate UART ,check FIFO. ++ */ ++static void bluesleep_sleep_work(struct work_struct *work) ++{ ++ if (!has_lpm_enabled) ++ return; ++ ++ if (bluesleep_can_sleep()) { ++ /* already asleep, this is an error case */ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("already asleep"); ++ return; ++ } ++ if (bsi->uport->ops->tx_empty(bsi->uport)) { ++ BT_DBG("going to sleep..."); ++ set_bit(BT_ASLEEP, &flags); ++ /*Deactivating UART */ ++ hsuart_power(0); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++ } else { ++ BT_DBG("This should never happen.\n"); ++ return; ++ } ++ } else if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("hold wake locks for rx_task."); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ clear_bit(BT_ASLEEP, &flags); ++ ++ /* Add a timer to make sure that UART ++ * would not be turned on&off very frequentently ++ */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ ++ set_bit(BT_RXTIMER, &flags); ++ hsuart_power(1); ++ } else { ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert ++ && !test_bit(BT_TXIDLE, &flags)) { ++ BT_DBG("force retrigger bt wake:%lx", flags); ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ msleep(20); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } ++ } ++} ++ ++/** ++ * A tasklet function that runs in tasklet context and reads the value ++ * of the HOST_WAKE GPIO pin and further defer the work. ++ * @param data Not used. ++ */ ++static void bluesleep_hostwake_task(unsigned long data) ++{ ++ BT_DBG("hostwake line change"); ++ spin_lock(&rw_lock); ++ ++ if (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert) ++ bluesleep_rx_busy(); ++ else ++ bluesleep_rx_idle(); ++ ++ spin_unlock(&rw_lock); ++} ++ ++/** ++ * Handles proper timer action when outgoing data is delivered to the ++ * HCI line discipline. Sets BT_TXDATA. ++ */ ++static void bluesleep_outgoing_data(void) ++{ ++ unsigned long irq_flags; ++ int power_on_uart = 0; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ /* if the tx side is sleeping... */ ++ if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) { ++ BT_DBG("tx was sleeping, wakeup it"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ clear_bit(BT_ASLEEP, &flags); ++ clear_bit(BT_TXIDLE, &flags); ++ power_on_uart = 1; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ if (power_on_uart == 1) ++ hsuart_power(1); ++} ++ ++#if BT_BLUEDROID_SUPPORT ++static struct uart_port *bluesleep_get_uart_port(void) ++{ ++ struct uart_port *uport = NULL; ++ ++ if (bluesleep_uart_dev) { ++ uport = platform_get_drvdata(bluesleep_uart_dev); ++ if (uport) ++ BT_DBG( ++ "%s get uart_port from blusleep_uart_dev: %s, port irq: %d", ++ __func__, bluesleep_uart_dev->name, uport->irq); ++ } ++ return uport; ++} ++ ++static int bluesleep_lpm_proc_show(struct seq_file *m, void *v) ++{ ++ seq_printf(m, "lpm enable: %d\n", has_lpm_enabled); ++ return 0; ++} ++ ++static int bluesleep_lpm_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_lpm_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_lpm(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ if (b == '0') { ++ /* HCI_DEV_UNREG */ ++ bluesleep_stop(); ++ has_lpm_enabled = false; ++ bsi->uport = NULL; ++ } else { ++ /* HCI_DEV_REG */ ++ if (!has_lpm_enabled) { ++ has_lpm_enabled = true; ++ if (bluesleep_uart_dev) ++ bsi->uport = bluesleep_get_uart_port(); ++ ++ /* if bluetooth started, start bluesleep*/ ++ bluesleep_start(); ++ } ++ } ++ ++ return count; ++} ++ ++static int bluesleep_btwrite_proc_show(struct seq_file *m, void *v) ++{ ++ seq_puts(m, "it's not support\n"); ++ return 0; ++} ++ ++static int bluesleep_btwrite_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_btwrite_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_btwrite(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ /* HCI_DEV_WRITE */ ++ if (b != '0') ++ bluesleep_outgoing_data(); ++ else ++ bluesleep_tx_allow_sleep(); ++ ++ return count; ++} ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0) ++static const struct proc_ops lpm_fops = { ++ .proc_open = bluesleep_lpm_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_lpm, ++}; ++static const struct proc_ops btwrite_fops = { ++ .proc_open = bluesleep_btwrite_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_btwrite, ++}; ++#else ++static const struct file_operations lpm_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_lpm_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_lpm, ++}; ++static const struct file_operations btwrite_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_btwrite_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_btwrite, ++}; ++#endif ++#else ++/** ++ * Handles HCI device events. ++ * @param this Not used. ++ * @param event The event that occurred. ++ * @param data The HCI device associated with the event. ++ * @return NOTIFY_DONE. ++ */ ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data) ++{ ++ struct hci_dev *hdev = (struct hci_dev *) data; ++ struct hci_uart *hu; ++ struct uart_state *state; ++ ++ if (!hdev) ++ return NOTIFY_DONE; ++ ++ switch (event) { ++ case HCI_DEV_REG: ++ if (!bluesleep_hdev) { ++ bluesleep_hdev = hdev; ++ hu = (struct hci_uart *) hdev->driver_data; ++ state = (struct uart_state *) hu->tty->driver_data; ++ bsi->uport = state->uart_port; ++ } ++ break; ++ case HCI_DEV_UNREG: ++ bluesleep_hdev = NULL; ++ bsi->uport = NULL; ++ break; ++ case HCI_DEV_WRITE: ++ bluesleep_outgoing_data(); ++ break; ++ } ++ ++ return NOTIFY_DONE; ++} ++#endif ++ ++/** ++ * Function to check wheather bluetooth can sleep when btwrite was deasserted ++ * by bluedroid. ++ */ ++static void bluesleep_tx_allow_sleep(void) ++{ ++ unsigned long irq_flags; ++ BT_DBG("Tx has been idle\n"); ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ set_bit(BT_TXIDLE, &flags); ++ bluesleep_tx_idle(); ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++} ++ ++ ++/* Handles reception timer expiration. ++ * Clear BT_RXTIMER. ++ * @param data Not used. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t) ++#else ++static void bluesleep_rx_timer_expire(unsigned long data) ++#endif ++{ ++ BT_DBG("bluesleep_rx_timer_expire"); ++ clear_bit(BT_RXTIMER, &flags); ++ bluesleep_rx_idle(); ++} ++ ++/** ++ * Schedules a tasklet to run when receiving an interrupt on the ++ * HOST_WAKE GPIO pin. ++ * @param irq Not used. ++ * @param dev_id Not used. ++ */ ++static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id) ++{ ++ /* schedule a tasklet to handle the change in the host wake line */ ++ tasklet_schedule(&hostwake_task); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * Starts the Sleep-Mode Protocol on the Host. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++static int bluesleep_start(void) ++{ ++ int retval; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return 0; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ ++ if (!atomic_dec_and_test(&open_count)) { ++ atomic_inc(&open_count); ++ return -EBUSY; ++ } ++ ++ /* start the timer */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL*HZ)); ++ /*deassert BT_WAKE first*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ msleep(20); ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ retval = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr, ++ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, ++ "bluetooth hostwake", &bsi->pdev->dev); ++ if (retval < 0) { ++ BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ"); ++ goto fail; ++ } ++ ++ set_bit(BT_PROTO, &flags); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ ++ return 0; ++fail: ++ del_timer(&rx_timer); ++ atomic_inc(&open_count); ++ ++ return retval; ++} ++ ++/** ++ * Stops the Sleep-Mode Protocol on the Host. ++ */ ++static void bluesleep_stop(void) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (!test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return; ++ } ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ ++ del_timer(&rx_timer); ++ clear_bit(BT_PROTO, &flags); ++ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ clear_bit(BT_ASLEEP, &flags); ++ hsuart_power(1); ++ } ++ ++ atomic_inc(&open_count); ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++} ++#if 0 ++/** ++ * Read the BT_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the ++ * pin is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_btwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "btwake:%u\n", ++ (gpio_get_value(bsi->ext_wake) == bsi->ext_wake_assert)); ++} ++ ++/** ++ * Write the BT_WAKE GPIO pin value via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluepower_write_proc_btwake(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char *buf; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ buf = kmalloc(count, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ if (copy_from_user(buf, buffer, count)) { ++ kfree(buf); ++ return -EFAULT; ++ } ++ ++ if (buf[0] == '0') { ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } else if (buf[0] == '1') { ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ } else { ++ kfree(buf); ++ return -EINVAL; ++ } ++ ++ kfree(buf); ++ return count; ++} ++ ++/** ++ * Read the BT_HOST_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the pin ++ * is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_hostwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "hostwake: %u\n", ++ (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert)); ++} ++ ++ ++/** ++ * Read the low-power status of the Host via the proc interface. ++ * When this function returns, page contains a 1 if the Host ++ * is asleep, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_asleep(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int asleep; ++ ++ asleep = test_bit(BT_ASLEEP, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "asleep: %u\n", asleep); ++} ++ ++/** ++ * Read the low-power protocol being used by the Host via the proc interface. ++ * When this function returns, page will contain a 1 if the Host ++ * is using the Sleep Mode Protocol, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_proto(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int proto; ++ ++ proto = test_bit(BT_PROTO, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "proto: %u\n", proto); ++} ++ ++/** ++ * Modify the low-power protocol used by the Host via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluesleep_write_proc_proto(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char proto; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&proto, buffer, 1)) ++ return -EFAULT; ++ ++ if (proto == '0') ++ bluesleep_stop(); ++ else ++ bluesleep_start(); ++ ++ /* claim that we wrote everything */ ++ return count; ++} ++#endif ++ ++static int assert_level = -1; ++module_param(assert_level, int, S_IRUGO); ++MODULE_PARM_DESC(assert_level, "BT_LPM hostwake/btwake assert level"); ++ ++#if 1 ++static struct platform_device *sw_uart_get_pdev(int id) ++{ ++ struct device_node *np; ++ char match[20]; ++ sprintf(match, "uart%d", id); ++ np = of_find_node_by_type(NULL, match); ++ return of_find_device_by_node(np); ++} ++#endif ++ ++static int bluesleep_probe(struct platform_device *pdev) ++{ ++#if 1 ++ struct device_node *np = of_find_compatible_node(NULL, NULL, "allwinner,sunxi-btlpm"); ++ struct device *dev = &pdev->dev; ++ enum of_gpio_flags config; ++ int ret, uart_index; ++ u32 val; ++ ++ bsi = devm_kzalloc(&pdev->dev, sizeof(struct bluesleep_info), ++ GFP_KERNEL); ++ if (!bsi) ++ return -ENOMEM; ++ ++ bsi->host_wake = of_get_named_gpio_flags(np, "bt_hostwake", 0, &config); ++ if (!gpio_is_valid(bsi->host_wake)) { ++ BT_ERR("get gpio bt_hostwake failed\n"); ++ ret = -EINVAL; ++ goto err0; ++ } ++ ++ /* set host_wake_assert */ ++ bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ BT_DBG("bt_hostwake gpio=%d assert=%d\n", bsi->host_wake, bsi->host_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->host_wake_assert = (assert_level & 0x02) > 0; ++ BT_DBG("override host_wake assert to %d", bsi->host_wake_assert); ++ } ++ ++ ret = devm_gpio_request(dev, bsi->host_wake, "bt_hostwake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_hostwake gpio %d\n", ++ bsi->host_wake); ++ goto err0; ++ } ++ ret = gpio_direction_input(bsi->host_wake); ++ if (ret < 0) { ++ BT_ERR("can't request input direction bt_wake gpio %d\n", ++ bsi->host_wake); ++ goto err1; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (!of_property_read_bool(np, "wakeup-source")) { ++#else ++ if (!of_property_read_u32(np, "wakeup-source", &bsi->wakeup_enable) && ++ (bsi->wakeup_enable == 0)) { ++#endif ++ BT_DBG("wakeup source is disabled!\n"); ++ } else { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ ret = device_init_wakeup(dev, true); ++ if (ret < 0) { ++ BT_ERR("device init wakeup failed!\n"); ++ goto err1; ++ } ++ ret = dev_pm_set_wake_irq(dev, gpio_to_irq(bsi->host_wake)); ++ if (ret < 0) { ++ BT_ERR("can't enable wakeup src for bt_hostwake %d\n", ++ bsi->host_wake); ++ goto err2; ++ } ++ bsi->wakeup_enable = 1; ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ } ++ ++ bsi->ext_wake = of_get_named_gpio_flags(np, "bt_wake", 0, &config); ++ if (!gpio_is_valid(bsi->ext_wake)) { ++ BT_ERR("get gpio bt_wake failed\n"); ++ ret = -EINVAL; ++ goto err2; ++ } ++ ++ ret = devm_gpio_request(dev, bsi->ext_wake, "bt_wake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err2; ++ } ++ ++ /* set ext_wake_assert */ ++ bsi->ext_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ BT_DBG("bt_wake gpio=%d assert=%d\n", bsi->ext_wake, bsi->ext_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->ext_wake_assert = (assert_level & 0x01) > 0; ++ BT_DBG("override ext_wake assert to %d", bsi->ext_wake_assert); ++ } ++ ++ /* 1.set bt_wake as output and the level is assert, assert bt wake */ ++ ret = gpio_direction_output(bsi->ext_wake, bsi->ext_wake_assert); ++ if (ret < 0) { ++ BT_ERR("can't request output direction bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err3; ++ } ++ /*set ext_wake deassert as default*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ ++ /* 2.get bt_host_wake gpio irq */ ++ bsi->host_wake_irq = gpio_to_irq(bsi->host_wake); ++ if (bsi->host_wake_irq < 0) { ++ BT_ERR("map gpio [%d] to virq failed, errno = %d\n", ++ bsi->host_wake, bsi->host_wake_irq); ++ ret = -ENODEV; ++ goto err3; ++ } ++ ++ uart_index = DEFAULT_UART_INDEX; ++ if (!of_property_read_u32(np, "uart_index", &val)) { ++ switch (val) { ++ case 0: ++ case 1: ++ case 2: ++ uart_index = val; ++ break; ++ default: ++ BT_ERR("unsupported uart_index (%u)\n", val); ++ } ++ } ++ BT_DBG("uart_index (%u)\n", uart_index); ++ bluesleep_uart_dev = sw_uart_get_pdev(uart_index); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ bsi->ws = wakeup_source_register(dev, "bluesleep"); ++#else ++ bsi->ws = wakeup_source_register("bluesleep"); ++#endif ++ ++#else ++ wake_lock_init(&bsi->wake_lock, WAKE_LOCK_SUSPEND, "bluesleep"); ++#endif ++ bsi->pdev = pdev; ++ ++ return 0; ++ ++err3: ++ devm_gpio_free(dev, bsi->ext_wake); ++err2: ++ device_init_wakeup(dev, false); ++err1: ++ devm_gpio_free(dev, bsi->host_wake); ++err0: ++ devm_kfree(dev, bsi); ++ ++ BT_ERR("probe fail, err: %d", ret); ++ return ret; ++#endif ++ return 0; ++} ++ ++static int bluesleep_remove(struct platform_device *pdev) ++{ ++ /* assert bt wake */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ if (test_bit(BT_PROTO, &flags)) { ++ if (disable_irq_wake(bsi->host_wake_irq)) ++ BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n"); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++ del_timer(&rx_timer); ++ if (test_bit(BT_ASLEEP, &flags)) ++ hsuart_power(1); ++ } ++ gpio_free(bsi->host_wake); ++ gpio_free(bsi->ext_wake); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ wakeup_source_unregister(bsi->ws); ++#else ++ wake_lock_destroy(&bsi->wake_lock); ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ if (bsi->wakeup_enable) { ++ BT_DBG("Deinit wakeup source"); ++ device_init_wakeup(&pdev->dev, false); ++ dev_pm_clear_wake_irq(&pdev->dev); ++ } ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ return 0; ++} ++ ++/** ++ * Initializes the module. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++int bluesleep_init(struct platform_device *pdev) ++{ ++ int retval; ++ struct proc_dir_entry *ent; ++ ++ BT_DBG("BlueSleep Mode Driver Ver %s", VERSION); ++ ++#if 1 ++ retval = bluesleep_probe(pdev); ++ if (retval) ++ return retval; ++#endif ++ ++#if !BT_BLUEDROID_SUPPORT ++ bluesleep_hdev = NULL; ++#endif ++ ++ bluetooth_dir = proc_mkdir("bluetooth", NULL); ++ if (bluetooth_dir == NULL) { ++ BT_ERR("Unable to create /proc/bluetooth directory"); ++ return -ENOMEM; ++ } ++ ++ sleep_dir = proc_mkdir("sleep", bluetooth_dir); ++ if (sleep_dir == NULL) { ++ BT_ERR("Unable to create /proc/%s directory", PROC_DIR); ++ return -ENOMEM; ++ } ++#if 0 ++ /* Creating read/write "btwake" entry */ ++ ent = create_proc_entry("btwake", 0, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluepower_read_proc_btwake; ++ ent->write_proc = bluepower_write_proc_btwake; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("hostwake", 0, sleep_dir, ++ bluepower_read_proc_hostwake, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* read/write proc entries */ ++ ent = create_proc_entry("proto", 0666, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluesleep_read_proc_proto; ++ ent->write_proc = bluesleep_write_proc_proto; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("asleep", 0, ++ sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++#if BT_BLUEDROID_SUPPORT ++ /* read/write proc entries */ ++ ent = proc_create("lpm", 0660, sleep_dir, &lpm_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/lpm entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ ent = proc_create("btwrite", 0660, sleep_dir, &btwrite_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwrite entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++ ++ flags = 0; /* clear all status bits */ ++ ++ /* Initialize spinlock. */ ++ spin_lock_init(&rw_lock); ++ ++ /* Initialize timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ timer_setup(&rx_timer, bluesleep_rx_timer_expire, 0); ++#else ++ init_timer(&rx_timer); ++ rx_timer.function = bluesleep_rx_timer_expire; ++ rx_timer.data = 0; ++#endif ++ ++ /* initialize host wake tasklet */ ++ tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); ++ ++#if !BT_BLUEDROID_SUPPORT ++ hci_register_notifier(&hci_event_nblock); ++#endif ++ ++ return 0; ++ ++fail: ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++ return retval; ++} ++ ++/** ++ * Cleans up the module. ++ */ ++int bluesleep_exit(struct platform_device *dev) ++{ ++#if !BT_BLUEDROID_SUPPORT ++ hci_unregister_notifier(&hci_event_nblock); ++#endif ++ ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++ bluesleep_remove(dev); ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h +new file mode 100644 +index 000000000000..0ff9dca14c0b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2015 Spreadtrum Communications Inc. ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __LPM_H ++#define __LPM_H ++ ++int bluesleep_init(struct platform_device *pdev); ++int bluesleep_exit(struct platform_device *dev); ++ ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c +new file mode 100644 +index 000000000000..5caf3f83a03a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c +@@ -0,0 +1,81 @@ ++/* ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aic_bsp_export.h" ++ ++static struct rfkill *bt_rfk; ++static const char bt_name[] = "bluetooth"; ++ ++static int bluetooth_set_power(void *data, bool blocked) ++{ ++ pr_info("%s: start_block=%d\n", __func__, blocked); ++ if (!blocked) { ++ aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON); ++ } else { ++ aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_OFF); ++ } ++ ++ pr_info("%s: end_block=%d\n", __func__, blocked); ++ return 0; ++} ++ ++static struct rfkill_ops rfkill_bluetooth_ops = { ++ .set_block = bluetooth_set_power, ++}; ++ ++int rfkill_bluetooth_init(struct platform_device *pdev) ++{ ++ ++ int rc = 0; ++ ++ pr_info("-->%s\n", __func__); ++ bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH, ++ &rfkill_bluetooth_ops, NULL); ++ if (!bt_rfk) { ++ rc = -ENOMEM; ++ goto err_rfkill_alloc; ++ } ++ /* userspace cannot take exclusive control */ ++ rfkill_init_sw_state(bt_rfk, true); ++ rc = rfkill_register(bt_rfk); ++ if (rc) ++ goto err_rfkill_reg; ++ ++ pr_info("<--%s\n", __func__); ++ ++ return 0; ++ ++err_rfkill_reg: ++ rfkill_destroy(bt_rfk); ++err_rfkill_alloc: ++ return rc; ++} ++ ++int rfkill_bluetooth_remove(struct platform_device *dev) ++{ ++ pr_info("-->%s\n", __func__); ++ rfkill_unregister(bt_rfk); ++ rfkill_destroy(bt_rfk); ++ pr_info("<--%s\n", __func__); ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h +new file mode 100644 +index 000000000000..ce0d5761a960 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h +@@ -0,0 +1,17 @@ ++/* ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef __RFKILL_H__ ++#define __RFKILL_H__ ++ ++int rfkill_bluetooth_init(struct platform_device *pdev); ++int rfkill_bluetooth_remove(struct platform_device *pdev); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore +new file mode 100644 +index 000000000000..c3c2d151e157 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig +new file mode 100644 +index 000000000000..c26f2b4af23c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig +@@ -0,0 +1,5 @@ ++config AIC8800_WLAN_SUPPORT ++ tristate "AIC8800 wlan Support" ++ help ++ This is support for aic wifi driver. ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile +new file mode 100644 +index 000000000000..558f3818b8e2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile +@@ -0,0 +1,424 @@ ++EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) ++EXTRA_CFLAGS += -Wno-implicit-fallthrough ++#EXTRA_CFLAGS += -Wno-unused-function ++#EXTRA_CFLAGS += -Wno-maybe-uninitialized ++#EXTRA_CFLAGS += -Wno-unused-variable ++ ++RWNX_VERS_NUM := 6.4.3.0 ++ ++CONFIG_COUNTRY_CODE = "00" ++ ++MODULE_NAME = aic8800_fdrv ++CONFIG_AIC8800_WLAN_SUPPORT = m ++ ++# Support of bootrom start ++CONFIG_START_FROM_BOOTROM = y ++ ++# Support of pmic setting, new version bootrom avaliable ++CONFIG_PMIC_SETTING ?=y ++ ++# Select 8800DC/DW DCDC_VRF mode, check your board ++CONFIG_VRF_DCDC_MODE = y ++ ++ ++# ROM patch enabled option ++CONFIG_ROM_PATCH_EN ?=y ++# Support chip with mcu ++CONFIG_MCU_INTEGRATED ?= n ++CONFIG_MCU_MESSAGE ?= n ++ifeq ($(CONFIG_MCU_INTEGRATED), y) ++CONFIG_PMIC_SETTING = n ++else ++CONFIG_MCU_MESSAGE ?= n ++endif ++ ++# ++# WAITING FOR KCONFIG { ++# ++CONFIG_RWNX_FULLMAC ?= y ++CONFIG_RWNX_FHOST ?= n ++ ++# ++# DEBUG OPTIONS ++CONFIG_RWNX_UM_HELPER_DFLT ?= "/dini/dini_bin/rwnx_umh.sh" ++ ++# ++# FW ARCH: ++CONFIG_RWNX_SDM ?= n ++CONFIG_RWNX_TL4 ?= n ++ ++# IPC version ++CONFIG_RWNX_OLD_IPC ?= n ++ ++# Support of P2P DebugFS for enabling/disabling NoA and OppPS ++CONFIG_RWNX_P2P_DEBUGFS := n ++# ++# } // WAITING FOR KCONFIG ++# ++ ++# Enable A-MSDU support (need FW support) ++## Select this if FW is compiled with AMSDU support ++CONFIG_RWNX_SPLIT_TX_BUF ?= n ++## Select this TO send AMSDU ++CONFIG_RWNX_AMSDUS_TX ?= n ++ ++# Enable BFMER support (need FW support) ++CONFIG_RWNX_BFMER ?= n ++ ++CONFIG_SDIO_SUPPORT =y ++CONFIG_USB_SUPPORT =n ++CONFIG_RX_REORDER ?=y ++CONFIG_ARP_OFFLOAD =y ++CONFIG_RADAR_OR_IR_DETECT =n ++CONFIG_DOWNLOAD_FW =n ++CONFIG_RFTEST=y ++CONFIG_USB_BT =y ++CONFIG_SDIO_BT=n ++CONFIG_USE_5G ?= y ++CONFIG_CREATE_TRACE_POINTS = n ++CONFIG_TXRX_THREAD_PRIO = y ++# CONFIG_COEX = n for BT_ONLY, CONFIG_COEX =y for combo and sw ++CONFIG_COEX = y ++CONFIG_RX_NETIF_RECV_SKB = y ++CONFIG_SET_VENDOR_EXTENSION_IE = n ++CONFIG_SUPPORT_REALTIME_CHANGE_MAC = y ++CONFIG_WPA3_FOR_OLD_KERNEL ?= n ++CONFIG_VHT_FOR_OLD_KERNEL ?= n ++CONFIG_HE_FOR_OLD_KERNEL ?= n ++CONFIG_PREALLOC_RX_SKB ?= n ++CONFIG_WIFI_SUSPEND_FOR_LINUX = n ++# Need to set fw path in BOARD_KERNEL_CMDLINE ++CONFIG_USE_FW_REQUEST ?= n ++CONFIG_USE_P2P0=n ++CONFIG_TX_NETIF_FLOWCTRL = n ++CONFIG_ONE_TXQ = n ++CONFIG_BR_SUPPORT =n ++BR_NAME = br0 ++CONFIG_FDRV_NO_REG_SDIO=n ++CONFIG_SCHED_SCAN = n ++CONFIG_OOB ?= n ++CONFIG_USE_CUSTOMER_MAC = n ++CONFIG_PREALLOC_TXQ ?= y ++CONFIG_DPD = y ++CONFIG_FORCE_DPD_CALIB = y ++CONFIG_LOFT_CALIB = n ++CONFIG_FILTER_TCP_ACK =y ++CONFIG_RESV_MEM_SUPPORT ?= y ++CONFIG_GKI = n ++CONFIG_TEMP_COMP = n ++CONFIG_TEMP_CONTROL = n ++CONFIG_EXT_FEM_8800DCDW = n ++CONFIG_SHUTDOWN_CALLBACK = y ++CONFIG_FOR_IPCAM = n ++CONFIG_SDIO_ADMA = n ++# CONFIG_MCC = n for sta and p2p concurrent in same channel. ++CONFIG_MCC = y ++CONFIG_APF = n ++CONFIG_POWER_LIMIT = n ++ ++#CONFIG FOR LOW POWER MODE ++CONFIG_SDIO_PWRCTRL ?= y ++CONFIG_GPIO_WAKEUP ?= n ++CONFIG_AUTO_POWERSAVE = n ++ ++# Enable wifi-hal Latency Mode ++CONFIG_AICWF_LATENCY_MODE = n ++ ++ifneq ($(CONFIG_WIRELESS_EXT), y) ++CONFIG_USE_WIRELESS_EXT = n ++endif ++ ++ifeq ($(CONFIG_EXT_FEM_8800DCDW), y) ++CONFIG_DPD = n ++CONFIG_FORCE_DPD_CALIB = n ++CONFIG_LOFT_CALIB = y ++endif ++ ++# Support of MU-MIMO transmission (need FW support) ++ifeq ($(CONFIG_RWNX_BFMER), y) ++CONFIG_RWNX_MUMIMO_TX ?= n ++else ++CONFIG_RWNX_MUMIMO_TX = n ++endif ++ ++# Enable handling of radar event ++CONFIG_RWNX_RADAR ?= y ++ ++# Enable HW queue for Broadcast/Multicast traffic (need FW support) ++CONFIG_RWNX_BCMC ?= y ++ ++# Enable Monitor+Data interface support (need FW support) ++CONFIG_RWNX_MON_DATA = n ++CONFIG_RWNX_MON_XMIT = n ++CONFIG_RWNX_MON_RXFILTER = n ++ ++ ++# extra DEBUG config ++CONFIG_RWNX_SW_PROFILING ?= n ++CONFIG_RWNX_DBG ?= y ++CONFIG_DEBUG_FS ?= n ++ ++obj-$(CONFIG_AIC8800_WLAN_SUPPORT) := $(MODULE_NAME).o ++$(MODULE_NAME)-y := \ ++ rwnx_msg_tx.o \ ++ rwnx_msg_rx.o \ ++ rwnx_utils.o \ ++ rwnx_cmds.o \ ++ rwnx_irqs.o \ ++ rwnx_cfgfile.o \ ++ rwnx_strs.o \ ++ rwnx_rx.o \ ++ rwnx_tx.o \ ++ rwnx_txq.o \ ++ rwnx_main.o \ ++ rwnx_mod_params.o \ ++ rwnx_mesh.o \ ++ rwnx_platform.o \ ++ rwnx_pci.o \ ++ rwnx_dini.o \ ++ rwnx_v7.o \ ++ ipc_host.o \ ++ rwnx_tdls.o \ ++ aic_vendor.o \ ++ md5.o \ ++ aicwf_compat_8800dc.o \ ++ aicwf_compat_8800d80.o \ ++ rwnx_wakelock.o \ ++ regdb.o \ ++ aic_priv_cmd.o \ ++ aicwf_rx_prealloc.o ++ ++$(MODULE_NAME)-$(CONFIG_BR_SUPPORT) += aic_br_ext.o ++$(MODULE_NAME)-$(CONFIG_RWNX_RADAR) += rwnx_radar.o ++$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_debugfs.o ++$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_fw_trace.o ++$(MODULE_NAME)-$(CONFIG_NL80211_TESTMODE) += rwnx_testmode.o ++$(MODULE_NAME)-$(CONFIG_RWNX_BFMER) += rwnx_bfmer.o ++$(MODULE_NAME)-$(CONFIG_RWNX_MUMIMO_TX) += rwnx_mu_group.o ++$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += sdio_host.o ++$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_txrxif.o ++$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_sdio.o ++$(MODULE_NAME)-$(CONFIG_FILTER_TCP_ACK) += aicwf_tcp_ack.o ++$(MODULE_NAME)-$(CONFIG_SDIO_BT) += aic_btsdio.o ++$(MODULE_NAME)-$(CONFIG_SDIO_BT) += btsdio.o ++ ++$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += usb_host.o ++$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_txrxif.o ++$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_usb.o ++$(MODULE_NAME)-$(CONFIG_GKI) += rwnx_gki.o ++ ++ ++ ++ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_DEBUGFS ++ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_UM_HELPER_DFLT=\"$(CONFIG_RWNX_UM_HELPER_DFLT)\" ++ccflags-$(CONFIG_RWNX_P2P_DEBUGFS) += -DCONFIG_RWNX_P2P_DEBUGFS ++ ++# FW VARS ++ccflags-y += -DNX_VIRT_DEV_MAX=4 ++ ++#for 8800D and DCDW u01 ++#ccflags-y += -DNX_REMOTE_STA_MAX=10 ++ ++#for 8800DCDW u02 ++ccflags-y += -DNX_REMOTE_STA_MAX_FOR_OLD_IC=10 ++ccflags-y += -DNX_REMOTE_STA_MAX=32 ++ ++ccflags-y += -DNX_MU_GROUP_MAX=62 ++ccflags-y += -DNX_TXDESC_CNT=64 ++ccflags-y += -DNX_TX_MAX_RATES=4 ++ccflags-y += -DNX_CHAN_CTXT_CNT=3 ++ ++# FW ARCH: ++ccflags-$(CONFIG_RWNX_SDM) += -DCONFIG_RWNX_SDM ++ccflags-$(CONFIG_RWNX_TL4) += -DCONFIG_RWNX_TL4 ++ccflags-$(CONFIG_RWNX_OLD_IPC) += -DCONFIG_RWNX_OLD_IPC ++ccflags-$(CONFIG_PLATFORM_NANOPI_M4) += -DCONFIG_NANOPI_M4 ++ccflags-$(CONFIG_PLATFORM_INGENIC_T20) += -DCONFIG_INGENIC_T20 ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++ccflags-$(CONFIG_START_FROM_BOOTROM) += -DCONFIG_START_FROM_BOOTROM ++ccflags-$(CONFIG_PMIC_SETTING) += -DCONFIG_PMIC_SETTING ++ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE ++ccflags-$(CONFIG_ROM_PATCH_EN) += -DCONFIG_ROM_PATCH_EN ++ccflags-$(CONFIG_HE_FOR_OLD_KERNEL) += -DCONFIG_HE_FOR_OLD_KERNEL ++ccflags-$(CONFIG_MCU_INTEGRATED) += -DCONFIG_MCU_INTEGRATED ++ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE ++ccflags-$(CONFIG_COEX) += -DCONFIG_COEX ++ ++ccflags-y += -DCONFIG_RWNX_FULLMAC ++ccflags-y += -I$(srctree) ++ccflags-y += -I$(srctree)/$(src) ++ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp ++ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\" ++ccflags-$(CONFIG_RWNX_RADAR) += -DCONFIG_RWNX_RADAR ++ccflags-$(CONFIG_RWNX_MON_DATA) += -DCONFIG_RWNX_MON_DATA ++ccflags-$(CONFIG_RWNX_MON_XMIT) += -DCONFIG_RWNX_MON_XMIT ++ccflags-$(CONFIG_RWNX_MON_RXFILTER) += -DCONFIG_RWNX_MON_RXFILTER ++ ++ccflags-$(CONFIG_RWNX_BFMER) += -DCONFIG_RWNX_BFMER ++ccflags-$(CONFIG_RWNX_SPLIT_TX_BUF) += -DCONFIG_RWNX_SPLIT_TX_BUF ++ifeq ($(CONFIG_RWNX_SPLIT_TX_BUF), y) ++ccflags-$(CONFIG_RWNX_AMSDUS_TX) += -DCONFIG_RWNX_AMSDUS_TX ++endif ++ccflags-$(CONFIG_RWNX_DBG) += -DCONFIG_RWNX_DBG ++ccflags-$(CONFIG_RWNX_SW_PROFILING) += -DCONFIG_RWNX_SW_PROFILING ++ccflags-$(CONFIG_RWNX_MUMIMO_TX) += -DCONFIG_RWNX_MUMIMO_TX ++ccflags-$(CONFIG_RFTEST) += -DCONFIG_RFTEST ++ccflags-y += -DDEFAULT_COUNTRY_CODE=""\$(CONFIG_COUNTRY_CODE)"\" ++ccflags-$(CONFIG_USE_5G) += -DUSE_5G ++ccflags-$(CONFIG_CREATE_TRACE_POINTS) += -DCREATE_TRACE_POINTS ++ccflags-$(CONFIG_TXRX_THREAD_PRIO) += -DCONFIG_TXRX_THREAD_PRIO ++ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP ++ccflags-$(CONFIG_SET_VENDOR_EXTENSION_IE) += -DCONFIG_SET_VENDOR_EXTENSION_IE ++ccflags-$(CONFIG_SUPPORT_REALTIME_CHANGE_MAC) += -DCONFIG_SUPPORT_REALTIME_CHANGE_MAC ++ccflags-$(CONFIG_WPA3_FOR_OLD_KERNEL) += -DCONFIG_WPA3_FOR_OLD_KERNEL ++ccflags-$(CONFIG_VHT_FOR_OLD_KERNEL) += -DCONFIG_VHT_FOR_OLD_KERNEL ++ccflags-$(CONFIG_PREALLOC_RX_SKB) += -DCONFIG_PREALLOC_RX_SKB ++ccflags-$(CONFIG_WIFI_SUSPEND_FOR_LINUX) += -DCONFIG_WIFI_SUSPEND_FOR_LINUX ++ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST ++ccflags-$(CONFIG_USE_P2P0) += -DCONFIG_USE_P2P0 ++ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO ++ccflags-$(CONFIG_SCHED_SCAN) += -DCONFIG_SCHED_SCAN ++ccflags-$(CONFIG_OOB) += -DCONFIG_OOB ++ccflags-$(CONFIG_AICWF_LATENCY_MODE) += -DAICWF_LATENCY_MODE ++ccflags-$(CONFIG_USE_CUSTOMER_MAC) += -DCONFIG_USE_CUSTOMER_MAC ++ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ ++ccflags-$(CONFIG_DPD) += -DCONFIG_DPD ++ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD ++ccflags-$(CONFIG_LOFT_CALIB) += -DCONFIG_LOFT_CALIB ++ccflags-$(CONFIG_FILTER_TCP_ACK) += -DCONFIG_FILTER_TCP_ACK ++ccflags-$(CONFIG_SDIO_BT) += -DCONFIG_SDIO_BT ++ccflags-$(CONFIG_RESV_MEM_SUPPORT) += -DCONFIG_RESV_MEM_SUPPORT ++ccflags-$(CONFIG_GKI) += -DCONFIG_GKI ++ccflags-$(CONFIG_TEMP_COMP) += -DCONFIG_TEMP_COMP ++ccflags-$(CONFIG_TEMP_CONTROL) += -DCONFIG_TEMP_CONTROL ++ccflags-$(CONFIG_POWER_LIMIT) += -DCONFIG_POWER_LIMIT ++ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW ++ccflags-$(CONFIG_MCC) += -DCONFIG_MCC ++ccflags-$(CONFIG_SHUTDOWN_CALLBACK) += -DCONFIG_SHUTDOWN_CALLBACK ++ccflags-$(CONFIG_FOR_IPCAM) += -DCONFIG_FOR_IPCAM ++ccflags-$(CONFIG_SDIO_ADMA) += -DCONFIG_SDIO_ADMA ++ ++ ++ifeq ($(CONFIG_SDIO_SUPPORT), y) ++ccflags-y += -DAICWF_SDIO_SUPPORT ++ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL ++endif ++ ++ifeq ($(CONFIG_USB_SUPPORT), y) ++ccflags-y += -DAICWF_USB_SUPPORT ++endif ++ ++ifeq ($(CONFIG_BR_SUPPORT), y) ++ccflags-y += -DCONFIG_BR_SUPPORT ++ccflags-y += '-DCONFIG_BR_SUPPORT_BRNAME="'$(BR_NAME)'"' ++endif ++ ++ifeq ($(CONFIG_RWNX_MUMIMO_TX), y) ++ccflags-y += -DCONFIG_USER_MAX=2 ++else ++ccflags-y += -DCONFIG_USER_MAX=1 ++endif ++ ++ifeq ($(CONFIG_RWNX_BCMC), y) ++ccflags-y += -DNX_TXQ_CNT=5 ++else ++ccflags-y += -DNX_TXQ_CNT=4 ++endif ++ ++# For old kernel (<=3.19) ++ifeq ($(shell test $(VERSION) -lt 4 -a "$(CONFIG_VENDOR_RWNX)" = y ; echo $$?),0) ++ccflags-y += -DCONFIG_VENDOR_RWNX_VHT_NO80 ++endif ++ ++ccflags-$(CONFIG_RX_REORDER) += -DAICWF_RX_REORDER ++ccflags-$(CONFIG_ARP_OFFLOAD) += -DAICWF_ARP_OFFLOAD ++ccflags-$(CONFIG_RADAR_OR_IR_DETECT) += -DCONFIG_RADAR_OR_IR_DETECT ++ccflags-$(CONFIG_DOWNLOAD_FW) += -DCONFIG_DOWNLOAD_FW ++ccflags-$(CONFIG_RX_NETIF_RECV_SKB) += -DCONFIG_RX_NETIF_RECV_SKB ++ccflags-$(CONFIG_ONE_TXQ) += -DCONFIG_ONE_TXQ ++ccflags-$(CONFIG_TX_NETIF_FLOWCTRL) += -DCONFIG_TX_NETIF_FLOWCTRL ++ccflags-$(CONFIG_APF) += -DCONFIG_APF ++ccflags-$(CONFIG_AUTO_POWERSAVE) += -DCONFIG_AUTO_POWERSAVE ++ ++ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) ++MAKEFLAGS +=-j$(shell nproc) ++ ++########## Platform support list ########## ++CONFIG_PLATFORM_ROCKCHIP ?= n ++CONFIG_PLATFORM_ROCKCHIP2 ?= n ++CONFIG_PLATFORM_ALLWINNER ?= n ++CONFIG_PLATFORM_INGENIC_T20 ?= n ++CONFIG_PLATFORM_AMLOGIC ?= n ++CONFIG_PLATFORM_UBUNTU ?= y ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ARCH := arm64 ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE := /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++ARCH := arm64 ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE := /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++ccflags-y += -DANDROID_PLATFORM ++KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/ ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y) ++KDIR ?= /home/yaya/E/T40/kernel ++ARCH ?= mips ++CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++ccflags-$(CONFIG_PLATFORM_UBUNTU) += -DCONFIG_PLATFORM_UBUNTU ++KDIR ?= /lib/modules/$(shell uname -r)/build ++PWD ?= $(shell pwd) ++KVER ?= $(shell uname -r) ++MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ++ARCH ?= x86_64 ++CROSS_COMPILE ?= ++ ++ifeq ($(CONFIG_AW_BSP), y) ++ccflags-y += -DCONFIG_PLATFORM_ALLWINNER ++endif ++ ++endif ++########################################### ++ ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c +new file mode 100644 +index 000000000000..dd038e39f3fe +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c +@@ -0,0 +1,1569 @@ ++/****************************************************************************** ++ * ++ * Copyright(c) 2007 - 2017 Realtek Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ *****************************************************************************/ ++#define _AIC_BR_EXT_C_ ++ ++#ifdef __KERNEL__ ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include "rwnx_defs.h" ++#endif ++ ++#ifdef CL_IPV6_PASS ++ #ifdef __KERNEL__ ++ #include ++ #include ++ #include ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)) ++ #include ++ #else ++ #include ++ #endif ++ #endif ++#endif ++ ++#ifdef CONFIG_BR_SUPPORT ++ ++/* #define BR_SUPPORT_DEBUG */ ++ ++#define NAT25_IPV4 01 ++#define NAT25_IPV6 02 ++#define NAT25_IPX 03 ++#define NAT25_APPLE 04 ++#define NAT25_PPPOE 05 ++ ++#define RTL_RELAY_TAG_LEN (ETH_ALEN) ++#define TAG_HDR_LEN 4 ++ ++#define MAGIC_CODE 0x8186 ++#define MAGIC_CODE_LEN 2 ++#define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */ ++ ++/*----------------------------------------------------------------- ++ How database records network address: ++ 0 1 2 3 4 5 6 7 8 9 10 ++ |----|----|----|----|----|----|----|----|----|----|----| ++ IPv4 |type| | IP addr | ++ IPX |type| Net addr | Node addr | ++ IPX |type| Net addr |Sckt addr| ++ Apple |type| Network |node| ++ PPPoE |type| SID | AC MAC | ++-----------------------------------------------------------------*/ ++ ++ ++/* Find a tag in pppoe frame and return the pointer */ ++static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type) ++{ ++ unsigned char *cur_ptr, *start_ptr; ++ unsigned short tagLen, tagType; ++ ++ start_ptr = cur_ptr = (unsigned char *)ph->tag; ++ while ((cur_ptr - start_ptr) < ntohs(ph->length)) { ++ /* prevent un-alignment access */ ++ tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]); ++ tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]); ++ if (tagType == type) ++ return cur_ptr; ++ cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen; ++ } ++ return 0; ++} ++ ++ ++static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag) ++{ ++ struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); ++ int data_len; ++ ++ data_len = tag->tag_len + TAG_HDR_LEN; ++ if (skb_tailroom(skb) < data_len) { ++ printk("skb_tailroom() failed in add SID tag!\n"); ++ return -1; ++ } ++ ++ skb_put(skb, data_len); ++ /* have a room for new tag */ ++ memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length)); ++ ph->length = htons(ntohs(ph->length) + data_len); ++ memcpy((unsigned char *)ph->tag, tag, data_len); ++ return data_len; ++} ++ ++static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len) ++{ ++ int tail_len; ++ unsigned long end, tail; ++ ++ if ((src + len) > skb_tail_pointer(skb) || skb->len < len) ++ return -1; ++ ++ tail = (unsigned long)skb_tail_pointer(skb); ++ end = (unsigned long)src + len; ++ if (tail < end) ++ return -1; ++ ++ tail_len = (int)(tail - end); ++ if (tail_len > 0) ++ memmove(src, src + len, tail_len); ++ ++ skb_trim(skb, skb->len - len); ++ return 0; ++} ++ ++static __inline__ unsigned long __nat25_timeout(struct rwnx_vif *vif) ++{ ++ unsigned long timeout; ++ ++ timeout = jiffies - NAT25_AGEING_TIME * HZ; ++ ++ return timeout; ++} ++ ++ ++static __inline__ int __nat25_has_expired(struct rwnx_vif *vif, ++ struct nat25_network_db_entry *fdb) ++{ ++ if (time_before_eq(fdb->ageing_timer, __nat25_timeout(vif))) ++ return 1; ++ ++ return 0; ++} ++ ++ ++static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr, ++ unsigned int *ipAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPV4; ++ memcpy(networkAddr + 7, (unsigned char *)ipAddr, 4); ++} ++ ++ ++static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr, ++ unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPX; ++ memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); ++ memcpy(networkAddr + 5, ipxNodeAddr, 6); ++} ++ ++ ++static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr, ++ unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPX; ++ memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); ++ memcpy(networkAddr + 5, (unsigned char *)ipxSocketAddr, 2); ++} ++ ++ ++static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr, ++ unsigned short *network, unsigned char *node) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_APPLE; ++ memcpy(networkAddr + 1, (unsigned char *)network, 2); ++ networkAddr[3] = *node; ++} ++ ++ ++static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr, ++ unsigned char *ac_mac, unsigned short *sid) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_PPPOE; ++ memcpy(networkAddr + 1, (unsigned char *)sid, 2); ++ memcpy(networkAddr + 3, (unsigned char *)ac_mac, 6); ++} ++ ++ ++#ifdef CL_IPV6_PASS ++static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr, ++ unsigned int *ipAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPV6; ++ memcpy(networkAddr + 1, (unsigned char *)ipAddr, 16); ++} ++ ++ ++static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b) ++{ ++ while (len > 0) { ++ if (*data == tag && *(data + 1) == len8b && len >= len8b * 8) ++ return data + 2; ++ ++ len -= (*(data + 1)) * 8; ++ data += (*(data + 1)) * 8; ++ } ++ return NULL; ++} ++ ++ ++static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac) ++{ ++ struct icmp6hdr *icmphdr = (struct icmp6hdr *)data; ++ unsigned char *mac; ++ ++ if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { ++ if (len >= 8) { ++ mac = scan_tlv(&data[8], len - 8, 1, 1); ++ if (mac) { ++ printk("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) { ++ if (len >= 16) { ++ mac = scan_tlv(&data[16], len - 16, 1, 1); ++ if (mac) { ++ printk("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { ++ if (len >= 24) { ++ mac = scan_tlv(&data[24], len - 24, 1, 1); ++ if (mac) { ++ printk("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { ++ if (len >= 24) { ++ mac = scan_tlv(&data[24], len - 24, 2, 1); ++ if (mac) { ++ printk("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_REDIRECT) { ++ if (len >= 40) { ++ mac = scan_tlv(&data[40], len - 40, 2, 1); ++ if (mac) { ++ printk("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } ++ return 0; ++} ++ ++#ifdef SUPPORT_RX_UNI2MCAST ++static void convert_ipv6_mac_to_mc(struct sk_buff *skb) ++{ ++ struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); ++ unsigned char *dst_mac = skb->data; ++ ++ /* dst_mac[0] = 0xff; */ ++ /* dst_mac[1] = 0xff; */ ++ /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/ ++ dst_mac[0] = 0x33; ++ dst_mac[1] = 0x33; ++ memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4); ++#if defined(__LINUX_2_6__) ++ /*modified by qinjunjie,warning:should not remove next line*/ ++ skb->pkt_type = PACKET_MULTICAST; ++#endif ++} ++#endif /* CL_IPV6_PASS */ ++#endif /* SUPPORT_RX_UNI2MCAST */ ++ ++ ++static __inline__ int __nat25_network_hash(unsigned char *networkAddr) ++{ ++ if (networkAddr[0] == NAT25_IPV4) { ++ unsigned long x; ++ ++ x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } else if (networkAddr[0] == NAT25_IPX) { ++ unsigned long x; ++ ++ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ ++ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } else if (networkAddr[0] == NAT25_APPLE) { ++ unsigned long x; ++ ++ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } else if (networkAddr[0] == NAT25_PPPOE) { ++ unsigned long x; ++ ++ x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } ++#ifdef CL_IPV6_PASS ++ else if (networkAddr[0] == NAT25_IPV6) { ++ unsigned long x; ++ ++ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ ++ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^ ++ networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^ ++ networkAddr[16]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } ++#endif ++ else { ++ unsigned long x = 0; ++ int i; ++ ++ for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++) ++ x ^= networkAddr[i]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } ++} ++ ++ ++static __inline__ void __network_hash_link(struct rwnx_vif *vif, ++ struct nat25_network_db_entry *ent, int hash) ++{ ++ /* Caller must _enter_critical_bh already! */ ++ /* _irqL irqL; */ ++ /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ ++ ++ ent->next_hash = vif->nethash[hash]; ++ if (ent->next_hash != NULL) ++ ent->next_hash->pprev_hash = &ent->next_hash; ++ vif->nethash[hash] = ent; ++ ent->pprev_hash = &vif->nethash[hash]; ++ ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++} ++ ++ ++static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent) ++{ ++ /* Caller must _enter_critical_bh already! */ ++ /* _irqL irqL; */ ++ /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ ++ ++ *(ent->pprev_hash) = ent->next_hash; ++ if (ent->next_hash != NULL) ++ ent->next_hash->pprev_hash = ent->pprev_hash; ++ ent->next_hash = NULL; ++ ent->pprev_hash = NULL; ++ ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++} ++ ++ ++static int __nat25_db_network_lookup_and_replace(struct rwnx_vif *vif, ++ struct sk_buff *skb, unsigned char *networkAddr) ++{ ++ struct nat25_network_db_entry *db; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ db = vif->nethash[__nat25_network_hash(networkAddr)]; ++ while (db != NULL) { ++ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { ++ if (!__nat25_has_expired(vif, db)) { ++ /* replace the destination mac address */ ++ memcpy(skb->data, db->macAddr, ETH_ALEN); ++ atomic_inc(&db->use_count); ++ ++#ifdef CL_IPV6_PASS ++ printk("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ++ "%02x%02x%02x%02x%02x%02x\n", ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10], ++ db->networkAddr[11], ++ db->networkAddr[12], ++ db->networkAddr[13], ++ db->networkAddr[14], ++ db->networkAddr[15], ++ db->networkAddr[16]); ++#else ++ printk("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10]); ++#endif ++ } ++ spin_unlock_bh(&vif->br_ext_lock); ++ return 1; ++ } ++ ++ db = db->next_hash; ++ } ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++ return 0; ++} ++ ++ ++static void __nat25_db_network_insert(struct rwnx_vif *vif, ++ unsigned char *macAddr, unsigned char *networkAddr) ++{ ++ struct nat25_network_db_entry *db; ++ int hash; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ hash = __nat25_network_hash(networkAddr); ++ db = vif->nethash[hash]; ++ ++ while (db != NULL) { ++ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { ++ memcpy(db->macAddr, macAddr, ETH_ALEN); ++ db->ageing_timer = jiffies; ++ spin_unlock_bh(&vif->br_ext_lock); ++ return; ++ } ++ ++ db = db->next_hash; ++ } ++ ++ db = (struct nat25_network_db_entry *)kmalloc(sizeof(*db), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); ++ if (db == NULL) { ++ spin_unlock_bh(&vif->br_ext_lock); ++ return; ++ } ++ ++ memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN); ++ memcpy(db->macAddr, macAddr, ETH_ALEN); ++ atomic_set(&db->use_count, 1); ++ db->ageing_timer = jiffies; ++ ++ __network_hash_link(vif, db, hash); ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++static void __nat25_db_print(struct rwnx_vif *vif) ++{ ++ spin_lock_bh(&vif->br_ext_lock); ++ ++#ifdef BR_SUPPORT_DEBUG ++ static int counter = 0; ++ int i, j; ++ struct nat25_network_db_entry *db; ++ ++ counter++; ++ if ((counter % 16) != 0) ++ return; ++ ++ for (i = 0, j = 0; i < NAT25_HASH_SIZE; i++) { ++ db = vif->nethash[i]; ++ ++ while (db != NULL) { ++#ifdef CL_IPV6_PASS ++ printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ++ "%02x%02x%02x%02x%02x%02x\n", ++ j, ++ i, ++ atomic_read(&db->use_count), ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10], ++ db->networkAddr[11], ++ db->networkAddr[12], ++ db->networkAddr[13], ++ db->networkAddr[14], ++ db->networkAddr[15], ++ db->networkAddr[16]); ++#else ++ printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ j, ++ i, ++ atomic_read(&db->use_count), ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10]); ++#endif ++ j++; ++ ++ db = db->next_hash; ++ } ++ } ++#endif ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++ ++ ++/* ++ * NAT2.5 interface ++ */ ++ ++void nat25_db_cleanup(struct rwnx_vif *vif) ++{ ++ int i; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ for (i = 0; i < NAT25_HASH_SIZE; i++) { ++ struct nat25_network_db_entry *f; ++ f = vif->nethash[i]; ++ while (f != NULL) { ++ struct nat25_network_db_entry *g; ++ ++ g = f->next_hash; ++ if (vif->scdb_entry == f) { ++ memset(vif->scdb_mac, 0, ETH_ALEN); ++ memset(vif->scdb_ip, 0, 4); ++ vif->scdb_entry = NULL; ++ } ++ __network_hash_unlink(f); ++ kfree(f); ++ ++ f = g; ++ } ++ } ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++void nat25_db_expire(struct rwnx_vif *vif) ++{ ++ int i; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ /* if(!priv->ethBrExtInfo.nat25_disable) */ ++ { ++ for (i = 0; i < NAT25_HASH_SIZE; i++) { ++ struct nat25_network_db_entry *f; ++ f = vif->nethash[i]; ++ ++ while (f != NULL) { ++ struct nat25_network_db_entry *g; ++ g = f->next_hash; ++ ++ if (__nat25_has_expired(vif, f)) { ++ if (atomic_dec_and_test(&f->use_count)) { ++#ifdef BR_SUPPORT_DEBUG ++#ifdef CL_IPV6_PASS ++ panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ++ "%02x%02x%02x%02x%02x%02x\n", ++ i, ++ f->macAddr[0], ++ f->macAddr[1], ++ f->macAddr[2], ++ f->macAddr[3], ++ f->macAddr[4], ++ f->macAddr[5], ++ f->networkAddr[0], ++ f->networkAddr[1], ++ f->networkAddr[2], ++ f->networkAddr[3], ++ f->networkAddr[4], ++ f->networkAddr[5], ++ f->networkAddr[6], ++ f->networkAddr[7], ++ f->networkAddr[8], ++ f->networkAddr[9], ++ f->networkAddr[10], ++ f->networkAddr[11], ++ f->networkAddr[12], ++ f->networkAddr[13], ++ f->networkAddr[14], ++ f->networkAddr[15], ++ f->networkAddr[16]); ++#else ++ ++ panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ i, ++ f->macAddr[0], ++ f->macAddr[1], ++ f->macAddr[2], ++ f->macAddr[3], ++ f->macAddr[4], ++ f->macAddr[5], ++ f->networkAddr[0], ++ f->networkAddr[1], ++ f->networkAddr[2], ++ f->networkAddr[3], ++ f->networkAddr[4], ++ f->networkAddr[5], ++ f->networkAddr[6], ++ f->networkAddr[7], ++ f->networkAddr[8], ++ f->networkAddr[9], ++ f->networkAddr[10]); ++#endif ++#endif ++ if (vif->scdb_entry == f) { ++ memset(vif->scdb_mac, 0, ETH_ALEN); ++ memset(vif->scdb_ip, 0, 4); ++ vif->scdb_entry = NULL; ++ } ++ __network_hash_unlink(f); ++ kfree(f); ++ } ++ } ++ ++ f = g; ++ } ++ } ++ } ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++#ifdef SUPPORT_TX_MCAST2UNI ++static int checkIPMcAndReplace(struct rwnx_vif *vif, struct sk_buff *skb, unsigned int *dst_ip) ++{ ++ struct stat_info *pstat; ++ struct list_head *phead, *plist; ++ int i; ++ ++ phead = &vif->asoc_list; ++ plist = phead->next; ++ ++ while (plist != phead) { ++ pstat = list_entry(plist, struct stat_info, asoc_list); ++ plist = plist->next; ++ ++ if (pstat->ipmc_num == 0) ++ continue; ++ ++ for (i = 0; i < MAX_IP_MC_ENTRY; i++) { ++ if (pstat->ipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip) + 1, 3)) { ++ memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN); ++ return 1; ++ } ++ } ++ } ++ return 0; ++} ++#endif ++ ++int nat25_db_handle(struct rwnx_vif *vif, struct sk_buff *skb, int method) ++{ ++ unsigned short protocol; ++ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; ++ ++ if (skb == NULL) ++ return -1; ++ ++ if ((method <= NAT25_MIN) || (method >= NAT25_MAX)) ++ return -1; ++ ++ protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); ++ ++ /*---------------------------------------------------*/ ++ /* Handle IP frame */ ++ /*---------------------------------------------------*/ ++ if (protocol == __constant_htons(ETH_P_IP)) { ++ struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); ++ ++ if (((unsigned char *)(iph) + (iph->ihl << 2)) >= (skb->data + ETH_HLEN + skb->len)) { ++ printk("NAT25: malformed IP packet !\n"); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: { ++ /* some muticast with source IP is all zero, maybe other case is illegal */ ++ /* in class A, B, C, host address is all zero or all one is illegal */ ++ if (iph->saddr == 0) ++ return 0; ++ printk("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); ++ __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr); ++ /* record source IP address and , source mac address into db */ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); ++#ifdef SUPPORT_TX_MCAST2UNI ++ if (vif->pshare->rf_ft_var.mc2u_disable || ++ ((((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) ++ == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) && ++ !checkIPMcAndReplace(vif, skb, &iph->daddr)) || ++ (OPMODE & WIFI_ADHOC_STATE))) ++#endif ++ { ++ __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr); ++ ++ if (!__nat25_db_network_lookup_and_replace(vif, skb, networkAddr)) { ++ if (*((unsigned char *)&iph->daddr + 3) == 0xff) { ++ /* L2 is unicast but L3 is broadcast, make L2 bacome broadcast */ ++ printk("NAT25: Set DA as boardcast\n"); ++ memset(skb->data, 0xff, ETH_ALEN); ++ } else { ++ /* forward unknow IP packet to upper TCP/IP */ ++ printk("NAT25: Replace DA with BR's MAC\n"); ++ if ((*(u32 *)vif->br_mac) == 0 && (*(u16 *)(vif->br_mac + 4)) == 0) { ++ void netdev_br_init(struct net_device *netdev); ++ printk("Re-init netdev_br_init() due to br_mac==0!\n"); ++ netdev_br_init(vif->ndev); ++ } ++ memcpy(skb->data, vif->br_mac, ETH_ALEN); ++ } ++ } ++ } ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle ARP frame */ ++ /*---------------------------------------------------*/ ++ else if (protocol == __constant_htons(ETH_P_ARP)) { ++ struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); ++ unsigned char *arp_ptr = (unsigned char *)(arp + 1); ++ unsigned int *sender, *target; ++ ++ if (arp->ar_pro != __constant_htons(ETH_P_IP)) { ++ printk("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro)); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ return 0; /* skb_copy for all ARP frame */ ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0], ++ arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]); ++ ++ /* change to ARP sender mac address to wlan STA address */ ++ memcpy(arp_ptr, vif->ndev->dev_addr, ETH_ALEN); ++ ++ arp_ptr += arp->ar_hln; ++ sender = (unsigned int *)arp_ptr; ++ ++ __nat25_generate_ipv4_network_addr(networkAddr, sender); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup ARP\n"); ++ ++ arp_ptr += arp->ar_hln; ++ sender = (unsigned int *)arp_ptr; ++ arp_ptr += (arp->ar_hln + arp->ar_pln); ++ target = (unsigned int *)arp_ptr; ++ ++ __nat25_generate_ipv4_network_addr(networkAddr, target); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ /* change to ARP target mac address to Lookup result */ ++ arp_ptr = (unsigned char *)(arp + 1); ++ arp_ptr += (arp->ar_hln + arp->ar_pln); ++ memcpy(arp_ptr, skb->data, ETH_ALEN); ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle IPX and Apple Talk frame */ ++ /*---------------------------------------------------*/ ++ else if ((protocol == __constant_htons(ETH_P_IPX)) || ++ (protocol == __constant_htons(ETH_P_ATALK)) || ++ (protocol == __constant_htons(ETH_P_AARP))) { ++ unsigned char ipx_header[2] = {0xFF, 0xFF}; ++ struct ipxhdr *ipx = NULL; ++ struct elapaarp *ea = NULL; ++ struct ddpehdr *ddp = NULL; ++ unsigned char *framePtr = skb->data + ETH_HLEN; ++ ++ if (protocol == __constant_htons(ETH_P_IPX)) { ++ printk("NAT25: Protocol=IPX (Ethernet II)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else { /* if(protocol <= __constant_htons(ETH_FRAME_LEN)) */ ++ if (!memcmp(ipx_header, framePtr, 2)) { ++ printk("NAT25: Protocol=IPX (Ethernet 802.3)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else { ++ unsigned char ipx_8022_type = 0xE0; ++ unsigned char snap_8022_type = 0xAA; ++ ++ if (*framePtr == snap_8022_type) { ++ unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; /* IPX SNAP ID */ ++ unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; /* Apple Talk AARP SNAP ID */ ++ unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; /* Apple Talk DDP SNAP ID */ ++ ++ framePtr += 3; /* eliminate the 802.2 header */ ++ ++ if (!memcmp(ipx_snap_id, framePtr, 5)) { ++ framePtr += 5; /* eliminate the SNAP header */ ++ ++ printk("NAT25: Protocol=IPX (Ethernet SNAP)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else if (!memcmp(aarp_snap_id, framePtr, 5)) { ++ framePtr += 5; /* eliminate the SNAP header */ ++ ++ ea = (struct elapaarp *)framePtr; ++ } else if (!memcmp(ddp_snap_id, framePtr, 5)) { ++ framePtr += 5; /* eliminate the SNAP header */ ++ ++ ddp = (struct ddpehdr *)framePtr; ++ } else { ++ printk("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0], ++ framePtr[1], framePtr[2], framePtr[3], framePtr[4]); ++ return -1; ++ } ++ } else if (*framePtr == ipx_8022_type) { ++ framePtr += 3; /* eliminate the 802.2 header */ ++ ++ if (!memcmp(ipx_header, framePtr, 2)) { ++ printk("NAT25: Protocol=IPX (Ethernet 802.2)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else ++ return -1; ++ } ++ } ++ } ++ ++ /* IPX */ ++ if (ipx != NULL) { ++ switch (method) { ++ case NAT25_CHECK: ++ if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { ++ printk("NAT25: Check IPX skb_copy\n"); ++ return 0; ++ } ++ return -1; ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n", ++ ipx->ipx_dest.net, ++ ipx->ipx_dest.node[0], ++ ipx->ipx_dest.node[1], ++ ipx->ipx_dest.node[2], ++ ipx->ipx_dest.node[3], ++ ipx->ipx_dest.node[4], ++ ipx->ipx_dest.node[5], ++ ipx->ipx_dest.sock, ++ ipx->ipx_source.net, ++ ipx->ipx_source.node[0], ++ ipx->ipx_source.node[1], ++ ipx->ipx_source.node[2], ++ ipx->ipx_source.node[3], ++ ipx->ipx_source.node[4], ++ ipx->ipx_source.node[5], ++ ipx->ipx_source.sock); ++ ++ if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { ++ printk("NAT25: Use IPX Net, and Socket as network addr\n"); ++ ++ __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock); ++ ++ /* change IPX source node addr to wlan STA address */ ++ memcpy(ipx->ipx_source.node, vif->ndev->dev_addr, ETH_ALEN); ++ } else ++ __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ if (!memcmp(vif->ndev->dev_addr, ipx->ipx_dest.node, ETH_ALEN)) { ++ printk("NAT25: Lookup IPX, Modify Destination IPX Node addr\n"); ++ ++ __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ /* replace IPX destination node addr with Lookup destination MAC addr */ ++ memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN); ++ } else { ++ __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ } ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /* AARP */ ++ else if (ea != NULL) { ++ /* Sanity check fields. */ ++ if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) { ++ printk("NAT25: Appletalk AARP Sanity check fail!\n"); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ return 0; ++ ++ case NAT25_INSERT: { ++ /* change to AARP source mac address to wlan STA address */ ++ memcpy(ea->hw_src, vif->ndev->dev_addr, ETH_ALEN); ++ ++ printk("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n", ++ ea->pa_src_net, ++ ea->pa_src_node, ++ ea->pa_dst_net, ++ ea->pa_dst_node); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n", ++ ea->pa_src_net, ++ ea->pa_src_node, ++ ea->pa_dst_net, ++ ea->pa_dst_node); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ /* change to AARP destination mac address to Lookup result */ ++ memcpy(ea->hw_dst, skb->data, ETH_ALEN); ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /* DDP */ ++ else if (ddp != NULL) { ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n", ++ ddp->deh_snet, ++ ddp->deh_snode, ++ ddp->deh_dnet, ++ ddp->deh_dnode); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n", ++ ddp->deh_snet, ++ ddp->deh_snode, ++ ddp->deh_dnet, ++ ddp->deh_dnode); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ return -1; ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle PPPoE frame */ ++ /*---------------------------------------------------*/ ++ else if ((protocol == __constant_htons(ETH_P_PPP_DISC)) || ++ (protocol == __constant_htons(ETH_P_PPP_SES))) { ++ struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); ++ unsigned short *pMagic; ++ ++ switch (method) { ++ case NAT25_CHECK: ++ if (ph->sid == 0) ++ return 0; ++ return 1; ++ ++ case NAT25_INSERT: ++ if (ph->sid == 0) { /* Discovery phase according to tag */ ++ if (ph->code == PADI_CODE || ph->code == PADR_CODE) { ++ if (vif->ethBrExtInfo.addPPPoETag) { ++ struct pppoe_tag *tag, *pOldTag; ++ unsigned char tag_buf[40]; ++ int old_tag_len = 0; ++ ++ tag = (struct pppoe_tag *)tag_buf; ++ pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); ++ if (pOldTag) { /* if SID existed, copy old value and delete it */ ++ old_tag_len = ntohs(pOldTag->tag_len); ++ if (old_tag_len + TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN > sizeof(tag_buf)) { ++ printk("SID tag length too long!\n"); ++ return -1; ++ } ++ ++ memcpy(tag->tag_data + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN, ++ pOldTag->tag_data, old_tag_len); ++ ++ if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN + old_tag_len) < 0) { ++ printk("call skb_pull_and_merge() failed in PADI/R packet!\n"); ++ return -1; ++ } ++ ph->length = htons(ntohs(ph->length) - TAG_HDR_LEN - old_tag_len); ++ } ++ ++ tag->tag_type = PTT_RELAY_SID; ++ tag->tag_len = htons(MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN + old_tag_len); ++ ++ /* insert the magic_code+client mac in relay tag */ ++ pMagic = (unsigned short *)tag->tag_data; ++ *pMagic = htons(MAGIC_CODE); ++ memcpy(tag->tag_data + MAGIC_CODE_LEN, skb->data + ETH_ALEN, ETH_ALEN); ++ ++ /* Add relay tag */ ++ if (__nat25_add_pppoe_tag(skb, tag) < 0) ++ return -1; ++ ++ printk("NAT25: Insert PPPoE, forward %s packet\n", ++ (ph->code == PADI_CODE ? "PADI" : "PADR")); ++ } else { /* not add relay tag */ ++ if (vif->pppoe_connection_in_progress && ++ memcmp(skb->data + ETH_ALEN, vif->pppoe_addr, ETH_ALEN)) { ++ printk("Discard PPPoE packet due to another PPPoE connection is in progress!\n"); ++ return -2; ++ } ++ ++ if (vif->pppoe_connection_in_progress == 0) ++ memcpy(vif->pppoe_addr, skb->data + ETH_ALEN, ETH_ALEN); ++ ++ vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE; ++ } ++ } else ++ return -1; ++ } else { /* session phase */ ++ printk("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name); ++ ++ __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid)); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ ++ if (!vif->ethBrExtInfo.addPPPoETag && ++ vif->pppoe_connection_in_progress && ++ !memcmp(skb->data + ETH_ALEN, vif->pppoe_addr, ETH_ALEN)) ++ vif->pppoe_connection_in_progress = 0; ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: ++ if (ph->code == PADO_CODE || ph->code == PADS_CODE) { ++ if (vif->ethBrExtInfo.addPPPoETag) { ++ struct pppoe_tag *tag; ++ unsigned char *ptr; ++ unsigned short tagType, tagLen; ++ int offset = 0; ++ ++ ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); ++ if (ptr == 0) { ++ printk("Fail to find PTT_RELAY_SID in FADO!\n"); ++ return -1; ++ } ++ ++ tag = (struct pppoe_tag *)ptr; ++ tagType = (unsigned short)((ptr[0] << 8) + ptr[1]); ++ tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]); ++ ++ if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN))) { ++ printk("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen); ++ return -1; ++ } ++ ++ pMagic = (unsigned short *)tag->tag_data; ++ if (ntohs(*pMagic) != MAGIC_CODE) { ++ printk("Can't find MAGIC_CODE in %s packet!\n", ++ (ph->code == PADO_CODE ? "PADO" : "PADS")); ++ return -1; ++ } ++ ++ memcpy(skb->data, tag->tag_data + MAGIC_CODE_LEN, ETH_ALEN); ++ ++ if (tagLen > MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN) ++ offset = TAG_HDR_LEN; ++ ++ if (skb_pull_and_merge(skb, ptr + offset, TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset) < 0) { ++ printk("call skb_pull_and_merge() failed in PADO packet!\n"); ++ return -1; ++ } ++ ph->length = htons(ntohs(ph->length) - (TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset)); ++ if (offset > 0) ++ tag->tag_len = htons(tagLen - MAGIC_CODE_LEN - RTL_RELAY_TAG_LEN); ++ ++ printk("NAT25: Lookup PPPoE, forward %s Packet from %s\n", ++ (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name); ++ } else { /* not add relay tag */ ++ if (!vif->pppoe_connection_in_progress) { ++ printk("Discard PPPoE packet due to no connection in progresss!\n"); ++ return -1; ++ } ++ memcpy(skb->data, vif->pppoe_addr, ETH_ALEN); ++ vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE; ++ } ++ } else { ++ if (ph->sid != 0) { ++ printk("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name); ++ __nat25_generate_pppoe_network_addr(networkAddr, skb->data + ETH_ALEN, &(ph->sid)); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ __nat25_db_print(vif); ++ } else ++ return -1; ++ ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle EAP frame */ ++ /*---------------------------------------------------*/ ++ else if (protocol == __constant_htons(0x888e)) { ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: ++ return 0; ++ ++ case NAT25_LOOKUP: ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle C-Media proprietary frame */ ++ /*---------------------------------------------------*/ ++ else if ((protocol == __constant_htons(0xe2ae)) || ++ (protocol == __constant_htons(0xe2af))) { ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: ++ return 0; ++ ++ case NAT25_LOOKUP: ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle IPV6 frame */ ++ /*---------------------------------------------------*/ ++#ifdef CL_IPV6_PASS ++ else if (protocol == __constant_htons(ETH_P_IPV6)) { ++ struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); ++ ++ if (sizeof(*iph) >= (skb->len - ETH_HLEN)) { ++ printk("NAT25: malformed IPv6 packet !\n"); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ if (skb->data[0] & 1) ++ return 0; ++ return -1; ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," ++ " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", ++ iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], ++ iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], ++ iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], ++ iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); ++ ++ if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) { ++ __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr); ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ __nat25_db_print(vif); ++ ++ if (iph->nexthdr == IPPROTO_ICMPV6 && ++ skb->len > (ETH_HLEN + sizeof(*iph) + 4)) { ++ if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), ++ skb->len - ETH_HLEN - sizeof(*iph), vif->ndev->dev_addr)) { ++ struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); ++ hdr->icmp6_cksum = 0; ++ hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr, ++ iph->payload_len, ++ IPPROTO_ICMPV6, ++ csum_partial((__u8 *)hdr, iph->payload_len, 0)); ++ } ++ } ++ } ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: ++ printk("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," ++ " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", ++ iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], ++ iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], ++ iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], ++ iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); ++ ++ ++ __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr); ++ if (!__nat25_db_network_lookup_and_replace(vif, skb, networkAddr)) { ++#ifdef SUPPORT_RX_UNI2MCAST ++ if (iph->daddr.s6_addr[0] == 0xff) ++ convert_ipv6_mac_to_mc(skb); ++#endif ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++#endif /* CL_IPV6_PASS */ ++ ++ return -1; ++} ++ ++ ++int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb) ++{ ++ //printk("%s : vif_type=%d \n",__func__,RWNX_VIF_TYPE(vif)); ++#ifdef BR_SUPPORT_DEBUG ++ if ((!vif->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1))) { ++ printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n", ++ skb->data[0], ++ skb->data[1], ++ skb->data[2], ++ skb->data[3], ++ skb->data[4], ++ skb->data[5], ++ skb->data[6], ++ skb->data[7], ++ skb->data[8], ++ skb->data[9], ++ skb->data[10], ++ skb->data[11]); ++ } ++#endif ++ ++ if (!(skb->data[0] & 1)) { ++ int is_vlan_tag = 0, i, retval = 0; ++ unsigned short vlan_hdr = 0; ++ ++ if (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_8021Q)) { ++ is_vlan_tag = 1; ++ vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2)); ++ skb_pull(skb, 4); ++ } ++ ++ if (!vif->ethBrExtInfo.nat25_disable) { ++ unsigned long irqL; ++ spin_lock_bh(&vif->br_ext_lock); ++ /* ++ * This function look up the destination network address from ++ * the NAT2.5 database. Return value = -1 means that the ++ * corresponding network protocol is NOT support. ++ */ ++ if (!vif->ethBrExtInfo.nat25sc_disable && ++ (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && ++ !memcmp(vif->scdb_ip, skb->data + ETH_HLEN + 16, 4)) { ++ memcpy(skb->data, vif->scdb_mac, ETH_ALEN); ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++ } else { ++ spin_unlock_bh(&vif->br_ext_lock); ++ ++ retval = nat25_db_handle(vif, skb, NAT25_LOOKUP); ++ } ++ } else { ++ if (((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && ++ !memcmp(vif->br_ip, skb->data + ETH_HLEN + 16, 4)) || ++ ((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_ARP)) && ++ !memcmp(vif->br_ip, skb->data + ETH_HLEN + 24, 4))) { ++ /* for traffic to upper TCP/IP */ ++ retval = nat25_db_handle(vif, skb, NAT25_LOOKUP); ++ } ++ } ++ ++ if (is_vlan_tag) { ++ skb_push(skb, 4); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); ++ *((unsigned short *)(skb->data + ETH_ALEN * 2)) = __constant_htons(ETH_P_8021Q); ++ *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr; ++ } ++ ++ if (retval == -1) { ++ /* DEBUG_ERR("NAT25: Lookup fail!\n"); */ ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++#if 0 ++void mac_clone(_adapter *priv, unsigned char *addr) ++{ ++ struct sockaddr sa; ++ ++ memcpy(sa.sa_data, addr, ETH_ALEN); ++ RTW_INFO("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); ++ rtl8192cd_set_hwaddr(priv->dev, &sa); ++} ++ ++ ++int mac_clone_handle_frame(_adapter *priv, struct sk_buff *skb) ++{ ++ if (priv->ethBrExtInfo.macclone_enable && !priv->macclone_completed) { ++ if (!(skb->data[ETH_ALEN] & 1)) { /* check any other particular MAC add */ ++ if (memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(priv), ETH_ALEN) && ++ ((priv->dev->br_port) && ++ memcmp(skb->data + ETH_ALEN, priv->br_mac, ETH_ALEN))) { ++ mac_clone(priv, skb->data + ETH_ALEN); ++ priv->macclone_completed = 1; ++ } ++ } ++ } ++ ++ return 0; ++} ++#endif /* 0 */ ++ ++#define SERVER_PORT 67 ++#define CLIENT_PORT 68 ++#define DHCP_MAGIC 0x63825363 ++#define BROADCAST_FLAG 0x8000 ++ ++struct dhcpMessage { ++ u_int8_t op; ++ u_int8_t htype; ++ u_int8_t hlen; ++ u_int8_t hops; ++ u_int32_t xid; ++ u_int16_t secs; ++ u_int16_t flags; ++ u_int32_t ciaddr; ++ u_int32_t yiaddr; ++ u_int32_t siaddr; ++ u_int32_t giaddr; ++ u_int8_t chaddr[16]; ++ u_int8_t sname[64]; ++ u_int8_t file[128]; ++ u_int32_t cookie; ++ u_int8_t options[308]; /* 312 - cookie */ ++}; ++ ++void dhcp_flag_bcast(struct rwnx_vif *vif, struct sk_buff *skb) ++{ ++ if (skb == NULL) ++ return; ++ //print_hex_dump(KERN_ERR, "SKB DUMP: SKB->DATA== ", DUMP_PREFIX_NONE, 32, 1, skb->data, 64,false); ++ if (!vif->ethBrExtInfo.dhcp_bcst_disable) { ++ unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); ++ printk("%s protocol: %04x\n", __func__, protocol); ++ ++ if (protocol == __constant_htons(ETH_P_IP)) { /* IP */ ++ struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); ++ ++ if (iph->protocol == IPPROTO_UDP) { /* UDP */ ++ struct udphdr *udph = (struct udphdr *)((u8 *)iph + (iph->ihl << 2)); ++ ++ if ((udph->source == __constant_htons(CLIENT_PORT)) ++ && (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */ ++ struct dhcpMessage *dhcph = ++ (struct dhcpMessage *)((u8 *)udph + sizeof(struct udphdr)); ++ ++ if (dhcph->cookie == __constant_htonl(DHCP_MAGIC)) { /* match magic word */ ++ if (!(dhcph->flags & htons(BROADCAST_FLAG))) { /* if not broadcast */ ++ register int sum = 0; ++ ++ printk("DHCP: change flag of DHCP request to broadcast.\n"); ++ ++ #if 1 ++ /* or BROADCAST flag */ ++ dhcph->flags |= htons(BROADCAST_FLAG); ++ /* recalculate checksum */ ++ sum = ~(udph->check) & 0xffff; ++ sum += dhcph->flags; ++ while (sum >> 16) ++ sum = (sum & 0xffff) + (sum >> 16); ++ udph->check = ~sum; ++ #endif ++ } ++ } ++ } ++ } ++ } ++ } ++} ++ ++ ++void *scdb_findEntry(struct rwnx_vif *vif, unsigned char *macAddr, ++ unsigned char *ipAddr) ++{ ++ printk("%s()\n",__func__); ++ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; ++ struct nat25_network_db_entry *db; ++ int hash; ++ /* _irqL irqL; */ ++ /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ ++ ++ __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr); ++ hash = __nat25_network_hash(networkAddr); ++ db = vif->nethash[hash]; ++ while (db != NULL) { ++ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++ return (void *)db; ++ } ++ ++ db = db->next_hash; ++ } ++ ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++ return NULL; ++} ++ ++#endif /* CONFIG_BR_SUPPORT */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h +new file mode 100644 +index 000000000000..71ebeb293b8e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h +@@ -0,0 +1,73 @@ ++/****************************************************************************** ++ * ++ * Copyright(c) 2007 - 2017 Realtek Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * 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 _AIC_BR_EXT_H_ ++#define _AIC_BR_EXT_H_ ++ ++#define CL_IPV6_PASS 1 ++#define MACADDRLEN 6 ++#define WLAN_ETHHDR_LEN 14 ++ ++#define NAT25_HASH_BITS 4 ++#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS) ++#define NAT25_AGEING_TIME 300 ++ ++#define NDEV_FMT "%s" ++#define NDEV_ARG(ndev) ndev->name ++#define ADPT_FMT "%s" ++//#define ADPT_ARG(adapter) (adapter->pnetdev ? adapter->pnetdev->name : NULL) ++#define FUNC_NDEV_FMT "%s(%s)" ++#define FUNC_NDEV_ARG(ndev) __func__, ndev->name ++#define FUNC_ADPT_FMT "%s(%s)" ++//#define FUNC_ADPT_ARG(adapter) __func__, (adapter->pnetdev ? adapter->pnetdev->name : NULL) ++#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" ++#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5] ++ ++ ++#ifdef CL_IPV6_PASS ++ #define MAX_NETWORK_ADDR_LEN 17 ++#else ++ #define MAX_NETWORK_ADDR_LEN 11 ++#endif ++ ++struct nat25_network_db_entry { ++ struct nat25_network_db_entry *next_hash; ++ struct nat25_network_db_entry **pprev_hash; ++ atomic_t use_count; ++ unsigned char macAddr[6]; ++ unsigned long ageing_timer; ++ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; ++}; ++ ++enum NAT25_METHOD { ++ NAT25_MIN, ++ NAT25_CHECK, ++ NAT25_INSERT, ++ NAT25_LOOKUP, ++ NAT25_PARSE, ++ NAT25_MAX ++}; ++ ++struct br_ext_info { ++ unsigned int nat25_disable; ++ unsigned int macclone_enable; ++ unsigned int dhcp_bcst_disable; ++ int addPPPoETag; /* 1: Add PPPoE relay-SID, 0: disable */ ++ unsigned char nat25_dmzMac[MACADDRLEN]; ++ unsigned int nat25sc_disable; ++}; ++ ++void nat25_db_cleanup(struct rwnx_vif *vif); ++ ++#endif /* _AIC_BR_EXT_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h +new file mode 100644 +index 000000000000..d3d020533a84 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h +@@ -0,0 +1,64 @@ ++#ifndef __AIC_BSP_EXPORT_H ++#define __AIC_BSP_EXPORT_H ++ ++enum aicbsp_subsys { ++ AIC_BLUETOOTH, ++ AIC_WIFI, ++}; ++ ++enum aicbsp_pwr_state { ++ AIC_PWR_OFF, ++ AIC_PWR_ON, ++}; ++ ++struct aicbsp_feature_t { ++ int hwinfo; ++ uint32_t sdio_clock; ++ uint8_t sdio_phase; ++ int fwlog_en; ++ uint8_t irqf; ++}; ++ ++enum skb_buff_id { ++ AIC_RESV_MEM_TXDATA, ++}; ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++typedef struct { ++ uint32_t bit_mask[3]; ++ uint32_t reserved; ++ uint32_t dpd_high[96]; ++ uint32_t dpd_11b[96]; ++ uint32_t dpd_low[96]; ++ uint32_t idac_11b[48]; ++ uint32_t idac_high[48]; ++ uint32_t idac_low[48]; ++ uint32_t loft_res[18]; ++ uint32_t rx_iqim_res[16]; ++} rf_misc_ram_t; ++ ++typedef struct { ++ uint32_t bit_mask[4]; ++ uint32_t dpd_high[96]; ++ uint32_t loft_res[18]; ++} rf_misc_ram_lite_t; ++ ++#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) ++#define DPD_RESULT_SIZE_8800DC sizeof(rf_misc_ram_lite_t) ++#endif ++ ++#ifdef CONFIG_DPD ++extern rf_misc_ram_lite_t dpd_res; ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++extern rf_misc_ram_lite_t loft_res_local; ++#endif ++ ++int aicbsp_set_subsys(int, int); ++int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path); ++bool aicbsp_get_load_fw_in_fdrv(void); ++struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id); ++void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c +new file mode 100644 +index 000000000000..ba26a37ef6e7 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c +@@ -0,0 +1,1299 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aic_btsdio.h" ++#include "rwnx_msg_tx.h" ++ ++#if CONFIG_BLUEDROID == 1 ++static spinlock_t queue_lock; ++static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how) ++{ ++ struct sk_buff *skb; ++ ++ if ((skb = alloc_skb(len + BT_SKB_RESERVE, how))) { ++ skb_reserve(skb, BT_SKB_RESERVE); ++ bt_cb(skb)->incoming = 0; ++ } ++ return skb; ++} ++ ++static spinlock_t queue_lock; ++static spinlock_t dlfw_lock; ++static volatile uint16_t dlfw_dis_state = 0; ++ ++/* Global parameters for bt usb char driver */ ++#define BT_CHAR_DEVICE_NAME "aicbt_dev" ++struct mutex btchr_mutex; ++static struct sk_buff_head btchr_readq; ++static wait_queue_head_t btchr_read_wait; ++static wait_queue_head_t bt_dlfw_wait; ++static int bt_char_dev_registered; ++static dev_t bt_devid; /* bt char device number */ ++static struct cdev bt_char_dev; /* bt character device structure */ ++static struct class *bt_char_class; /* device class for usb char driver */ ++static int bt_reset = 0; ++//int aic_queue_cnt(void); ++/* HCI device & lock */ ++DEFINE_RWLOCK(hci_dev_lock); ++ ++struct hci_dev *ghdev = NULL; ++ ++static struct sk_buff *aic_skb_queue[QUEUE_SIZE]; ++static int aic_skb_queue_front = 0; ++static int aic_skb_queue_rear = 0; ++ ++static inline int check_set_dlfw_state_value(uint16_t change_value) ++{ ++ spin_lock(&dlfw_lock); ++ if(!dlfw_dis_state) { ++ dlfw_dis_state = change_value; ++ } ++ spin_unlock(&dlfw_lock); ++ return dlfw_dis_state; ++} ++ ++static inline void set_dlfw_state_value(uint16_t change_value) ++{ ++ spin_lock(&dlfw_lock); ++ dlfw_dis_state = change_value; ++ spin_unlock(&dlfw_lock); ++} ++ ++static void print_acl(struct sk_buff *skb, int direction) ++{ ++#if PRINT_ACL_DATA ++ //uint wlength = skb->len; ++ u16 *handle = (u16 *)(skb->data); ++ u16 len = *(handle+1); ++ //u8 *acl_data = (u8 *)(skb->data); ++ ++ AICBT_INFO("aic %s: direction %d, handle %04x, len %d", ++ __func__, direction, *handle, len); ++#endif ++} ++ ++static void print_sco(struct sk_buff *skb, int direction) ++{ ++#if PRINT_SCO_DATA ++ uint wlength = skb->len; ++ u16 *handle = (u16 *)(skb->data); ++ u8 len = *(u8 *)(handle+1); ++ //u8 *sco_data =(u8 *)(skb->data); ++ ++ AICBT_INFO("aic %s: direction %d, handle %04x, len %d,wlength %d", ++ __func__, direction, *handle, len,wlength); ++#endif ++} ++ ++int bt_bypass_event(struct sk_buff *skb) ++{ ++ int ret = 0; ++ u8 *opcode = (u8*)(skb->data); ++ //u8 len = *(opcode+1); ++ //printk("bypass_event %x,%x,%x,%x,%x\r\n",opcode[0],opcode[1],opcode[2],opcode[3],opcode[4]); ++ ++ switch(opcode[1]) { ++ case HCI_EV_LE_Meta: ++ { ++ u8 subevent_code; ++ subevent_code = opcode[3]; ++ switch(subevent_code){ ++ case HCI_BLE_ADV_PKT_RPT_EVT: ++ case HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT: ++ { ++ if(aic_queue_cnt() > (QUEUE_SIZE-490)){ ++ printk("more adv report bypass\r\n"); ++ ret = 1; ++ } ++ } ++ break; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++ ++int bt_sdio_recv(u8 *data,u32 data_len) ++{ ++ struct sk_buff *skb; ++ int type= data[0]; ++ struct hci_dev *hdev; ++ u32 len = data_len; ++ //int ret=0; ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICWFDBG(LOGERROR,"%s: Failed to get hci dev[NULL]", __func__); ++ return -ENODEV; ++ } ++ ++ skb = alloc_skb(len,GFP_ATOMIC); ++ if(!skb){ ++ AICWFDBG(LOGERROR, "alloc skb fail %s \n",__func__); ++ } ++ memcpy(skb_put(skb,len) ,data, len); ++ if(bt_bypass_event(skb)){ ++ kfree_skb(skb); ++ return 0; ++ } ++ //bt_data_dump("bt_skb", skb, skb->len); ++ ++ if(aic_enqueue(skb)<0){ ++ kfree_skb(skb); ++ }else{ ++ //printk("wake up \n"); ++ wake_up_interruptible(&btchr_read_wait); ++ } ++ return 0; ++} ++ ++ ++static int bypass_event(struct sk_buff *skb) ++{ ++ int ret = 0; ++ u8 *opcode = (u8*)(skb->data); ++ //u8 len = *(opcode+1); ++ //printk("bypass_event %x,%x,%x,%x,%x\r\n",opcode[0],opcode[1],opcode[2],opcode[3],opcode[4]); ++ ++ switch(*opcode) { ++#ifdef CONFIG_SUPPORT_VENDOR_APCF ++ case HCI_EV_CMD_COMPLETE: ++ { ++ u16 sub_opcpde; ++ sub_opcpde = ((u16)opcode[3]|(u16)(opcode[4])<<8); ++ if(sub_opcpde == 0xfd57){ ++ if(vendor_apcf_sent_done){ ++ vendor_apcf_sent_done--; ++ printk("apcf bypass\r\n"); ++ ret = 1; ++ } ++ } ++ } ++ break; ++#endif//CONFIG_SUPPORT_VENDOR_APCF ++ case HCI_EV_LE_Meta: ++ { ++ u8 subevent_code; ++ subevent_code = opcode[2]; ++ switch(subevent_code){ ++ case HCI_BLE_ADV_PKT_RPT_EVT: ++ case HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT: ++ { ++ if(aic_queue_cnt() > (QUEUE_SIZE-100)){ ++ printk("more adv report bypass\r\n"); ++ ret = 1; ++ } ++ } ++ break; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++static void print_event(struct sk_buff *skb) ++{ ++#if PRINT_CMD_EVENT ++ //uint wlength = skb->len; ++ //uint icount = 0; ++ u8 *opcode = (u8*)(skb->data); ++ //u8 len = *(opcode+1); ++ ++ printk("aic %s ", __func__); ++ switch (*opcode) { ++ case HCI_EV_INQUIRY_COMPLETE: ++ printk("HCI_EV_INQUIRY_COMPLETE"); ++ break; ++ case HCI_EV_INQUIRY_RESULT: ++ printk("HCI_EV_INQUIRY_RESULT"); ++ break; ++ case HCI_EV_CONN_COMPLETE: ++ printk("HCI_EV_CONN_COMPLETE"); ++ break; ++ case HCI_EV_CONN_REQUEST: ++ printk("HCI_EV_CONN_REQUEST"); ++ break; ++ case HCI_EV_DISCONN_COMPLETE: ++ printk("HCI_EV_DISCONN_COMPLETE"); ++ break; ++ case HCI_EV_AUTH_COMPLETE: ++ printk("HCI_EV_AUTH_COMPLETE"); ++ break; ++ case HCI_EV_REMOTE_NAME: ++ printk("HCI_EV_REMOTE_NAME"); ++ break; ++ case HCI_EV_ENCRYPT_CHANGE: ++ printk("HCI_EV_ENCRYPT_CHANGE"); ++ break; ++ case HCI_EV_CHANGE_LINK_KEY_COMPLETE: ++ printk("HCI_EV_CHANGE_LINK_KEY_COMPLETE"); ++ break; ++ case HCI_EV_REMOTE_FEATURES: ++ printk("HCI_EV_REMOTE_FEATURES"); ++ break; ++ case HCI_EV_REMOTE_VERSION: ++ printk("HCI_EV_REMOTE_VERSION"); ++ break; ++ case HCI_EV_QOS_SETUP_COMPLETE: ++ printk("HCI_EV_QOS_SETUP_COMPLETE"); ++ break; ++ case HCI_EV_CMD_COMPLETE: ++ printk("HCI_EV_CMD_COMPLETE"); ++ break; ++ case HCI_EV_CMD_STATUS: ++ printk("HCI_EV_CMD_STATUS"); ++ break; ++ case HCI_EV_ROLE_CHANGE: ++ printk("HCI_EV_ROLE_CHANGE"); ++ break; ++ case HCI_EV_NUM_COMP_PKTS: ++ printk("HCI_EV_NUM_COMP_PKTS"); ++ break; ++ case HCI_EV_MODE_CHANGE: ++ printk("HCI_EV_MODE_CHANGE"); ++ break; ++ case HCI_EV_PIN_CODE_REQ: ++ printk("HCI_EV_PIN_CODE_REQ"); ++ break; ++ case HCI_EV_LINK_KEY_REQ: ++ printk("HCI_EV_LINK_KEY_REQ"); ++ break; ++ case HCI_EV_LINK_KEY_NOTIFY: ++ printk("HCI_EV_LINK_KEY_NOTIFY"); ++ break; ++ case HCI_EV_CLOCK_OFFSET: ++ printk("HCI_EV_CLOCK_OFFSET"); ++ break; ++ case HCI_EV_PKT_TYPE_CHANGE: ++ printk("HCI_EV_PKT_TYPE_CHANGE"); ++ break; ++ case HCI_EV_PSCAN_REP_MODE: ++ printk("HCI_EV_PSCAN_REP_MODE"); ++ break; ++ case HCI_EV_INQUIRY_RESULT_WITH_RSSI: ++ printk("HCI_EV_INQUIRY_RESULT_WITH_RSSI"); ++ break; ++ case HCI_EV_REMOTE_EXT_FEATURES: ++ printk("HCI_EV_REMOTE_EXT_FEATURES"); ++ break; ++ case HCI_EV_SYNC_CONN_COMPLETE: ++ printk("HCI_EV_SYNC_CONN_COMPLETE"); ++ break; ++ case HCI_EV_SYNC_CONN_CHANGED: ++ printk("HCI_EV_SYNC_CONN_CHANGED"); ++ break; ++ case HCI_EV_SNIFF_SUBRATE: ++ printk("HCI_EV_SNIFF_SUBRATE"); ++ break; ++ case HCI_EV_EXTENDED_INQUIRY_RESULT: ++ printk("HCI_EV_EXTENDED_INQUIRY_RESULT"); ++ break; ++ case HCI_EV_IO_CAPA_REQUEST: ++ printk("HCI_EV_IO_CAPA_REQUEST"); ++ break; ++ case HCI_EV_SIMPLE_PAIR_COMPLETE: ++ printk("HCI_EV_SIMPLE_PAIR_COMPLETE"); ++ break; ++ case HCI_EV_REMOTE_HOST_FEATURES: ++ printk("HCI_EV_REMOTE_HOST_FEATURES"); ++ break; ++ default: ++ printk("unknow event"); ++ break; ++ } ++ printk("\n"); ++#if 0 ++ printk("%02x,len:%d,", *opcode,len); ++ for (icount = 2; (icount < wlength) && (icount < 24); icount++) ++ printk("%02x ", *(opcode+icount)); ++ printk("\n"); ++#endif ++#endif ++} ++ ++ ++static inline ssize_t sdio_put_user(struct sk_buff *skb, ++ char __user *buf, int count) ++{ ++ char __user *ptr = buf; ++ int len = min_t(unsigned int, skb->len, count); ++ ++ if (copy_to_user(ptr, skb->data, len)) ++ return -EFAULT; ++ ++ return len; ++} ++ ++int aic_enqueue(struct sk_buff *skb) ++{ ++ unsigned long flags = 0; ++ int ret = 0; ++ spin_lock_irqsave(&queue_lock, flags); ++ if (aic_skb_queue_front == (aic_skb_queue_rear + 1) % QUEUE_SIZE) { ++ /* ++ * If queue is full, current solution is to drop ++ * the following entries. ++ */ ++ AICBT_WARN("%s: Queue is full, entry will be dropped", __func__); ++ ret = -1; ++ } else { ++ aic_skb_queue[aic_skb_queue_rear] = skb; ++ ++ aic_skb_queue_rear++; ++ aic_skb_queue_rear %= QUEUE_SIZE; ++ ++ } ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return ret; ++} ++ ++static struct sk_buff *aic_dequeue_try(unsigned int deq_len) ++{ ++ struct sk_buff *skb; ++ struct sk_buff *skb_copy; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&queue_lock, flags); ++ if (aic_skb_queue_front == aic_skb_queue_rear) { ++ AICBT_WARN("%s: Queue is empty", __func__); ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return NULL; ++ } ++ ++ skb = aic_skb_queue[aic_skb_queue_front]; ++ if (deq_len >= skb->len) { ++ ++ aic_skb_queue_front++; ++ aic_skb_queue_front %= QUEUE_SIZE; ++ ++ /* ++ * Return skb addr to be dequeued, and the caller ++ * should free the skb eventually. ++ */ ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return skb; ++ } else { ++ skb_copy = pskb_copy(skb, GFP_ATOMIC); ++ skb_pull(skb, deq_len); ++ /* Return its copy to be freed */ ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return skb_copy; ++ } ++} ++ ++static inline int is_queue_empty(void) ++{ ++ return (aic_skb_queue_front == aic_skb_queue_rear) ? 1 : 0; ++} ++ ++void aic_clear_queue(void) ++{ ++ struct sk_buff *skb; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&queue_lock, flags); ++ while(!is_queue_empty()) { ++ skb = aic_skb_queue[aic_skb_queue_front]; ++ aic_skb_queue[aic_skb_queue_front] = NULL; ++ aic_skb_queue_front++; ++ aic_skb_queue_front %= QUEUE_SIZE; ++ if (skb) { ++ kfree_skb(skb); ++ } ++ } ++ spin_unlock_irqrestore(&queue_lock, flags); ++} ++ ++int aic_queue_cnt(void) ++{ ++ int ret_cnt = 0; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&queue_lock, flags); ++ if(is_queue_empty()) { ++ ret_cnt = 0; ++ }else{ ++ if(aic_skb_queue_rear > aic_skb_queue_front){ ++ ret_cnt = aic_skb_queue_rear-aic_skb_queue_front; ++ }else{ ++ ret_cnt = aic_skb_queue_rear+QUEUE_SIZE-aic_skb_queue_front; ++ } ++ } ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return ret_cnt; ++} ++ ++/* ++ * AicSemi - Integrate from hci_core.c ++ */ ++ ++/* Get HCI device by index. ++ * Device is held on return. */ ++struct hci_dev *hci_dev_get(int index) ++{ ++ if (index != 0) ++ return NULL; ++ ++ return ghdev; ++} ++ ++/* ---- HCI ioctl helpers ---- */ ++static int hci_dev_open(__u16 dev) ++{ ++ struct hci_dev *hdev; ++ int ret = 0; ++ ++ AICBT_DBG("%s: dev %d", __func__, dev); ++ ++ hdev = hci_dev_get(dev); ++ if (!hdev) { ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ return -ENODEV; ++ } ++ ++ /*if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) { ++ ret = -ENODEV; ++ goto done; ++ } ++ ++ if (test_bit(HCI_UP, &hdev->flags)) { ++ ret = -EALREADY; ++ goto done; ++ }*/ ++ ++done: ++ return ret; ++} ++ ++static int hci_dev_do_close(struct hci_dev *hdev) ++{ ++ //if (hdev->flush) ++ // hdev->flush(hdev); ++ /* After this point our queues are empty ++ * and no tasks are scheduled. */ ++ //hdev->close(hdev); ++ /* Clear flags */ ++ hdev->flags = 0; ++ return 0; ++} ++ ++static int hci_dev_close(__u16 dev) ++{ ++ struct hci_dev *hdev; ++ int err; ++ hdev = hci_dev_get(dev); ++ if (!hdev) { ++ AICBT_ERR("%s: failed to get hci dev[Null]", __func__); ++ return -ENODEV; ++ } ++ ++ err = hci_dev_do_close(hdev); ++ ++ return err; ++} ++ ++#if CONFIG_BLUEDROID ++static struct hci_dev *hci_alloc_dev(void) ++{ ++ struct hci_dev *hdev; ++ ++ hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL); ++ if (!hdev) ++ return NULL; ++ ++ return hdev; ++} ++ ++/* Free HCI device */ ++static void hci_free_dev(struct hci_dev *hdev) ++{ ++ kfree(hdev); ++} ++ ++/* Register HCI device */ ++static int hci_register_dev(struct hci_dev *hdev) ++{ ++ int i, id; ++ ++ AICBT_DBG("%s: %p name %s bus %d", __func__, hdev, hdev->name, hdev->bus); ++ /* Do not allow HCI_AMP devices to register at index 0, ++ * so the index can be used as the AMP controller ID. ++ */ ++ id = (hdev->dev_type == HCI_BREDR) ? 0 : 1; ++ ++ write_lock(&hci_dev_lock); ++ ++ sprintf(hdev->name, "hci%d", id); ++ hdev->id = id; ++ hdev->flags = 0; ++ hdev->dev_flags = 0; ++ mutex_init(&hdev->lock); ++ ++ AICBT_DBG("%s: id %d, name %s", __func__, hdev->id, hdev->name); ++ ++ ++ for (i = 0; i < NUM_REASSEMBLY; i++) ++ hdev->reassembly[i] = NULL; ++ ++ memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); ++ atomic_set(&hdev->promisc, 0); ++ ++ if (ghdev) { ++ write_unlock(&hci_dev_lock); ++ AICBT_ERR("%s: Hci device has been registered already", __func__); ++ return -1; ++ } else ++ ghdev = hdev; ++ ++ write_unlock(&hci_dev_lock); ++ ++ return id; ++} ++ ++/* Unregister HCI device */ ++static void hci_unregister_dev(struct hci_dev *hdev) ++{ ++ int i; ++ ++ AICBT_DBG("%s: hdev %p name %s bus %d", __func__, hdev, hdev->name, hdev->bus); ++ set_bit(HCI_UNREGISTER, &hdev->dev_flags); ++ ++ write_lock(&hci_dev_lock); ++ ghdev = NULL; ++ write_unlock(&hci_dev_lock); ++ ++ hci_dev_do_close(hdev); ++ for (i = 0; i < NUM_REASSEMBLY; i++) ++ kfree_skb(hdev->reassembly[i]); ++} ++ ++static void hci_send_to_stack(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ struct sk_buff *aic_skb_copy = NULL; ++ ++ //AICBT_DBG("%s", __func__); ++ ++ if (!hdev) { ++ AICBT_ERR("%s: Frame for unknown HCI device", __func__); ++ return; ++ } ++ ++ if (!test_bit(HCI_RUNNING, &hdev->flags)) { ++ AICBT_ERR("%s: HCI not running", __func__); ++ return; ++ } ++ ++ aic_skb_copy = pskb_copy(skb, GFP_ATOMIC); ++ if (!aic_skb_copy) { ++ AICBT_ERR("%s: Copy skb error", __func__); ++ return; ++ } ++ ++ memcpy(skb_push(aic_skb_copy, 1), &bt_cb(skb)->pkt_type, 1); ++ aic_enqueue(aic_skb_copy); ++ ++ /* Make sure bt char device existing before wakeup read queue */ ++ hdev = hci_dev_get(0); ++ if (hdev) { ++ //AICBT_DBG("%s: Try to wakeup read queue", __func__); ++ AICBT_DBG("%s", __func__); ++ wake_up_interruptible(&btchr_read_wait); ++ } ++ ++ ++ return; ++} ++ ++/* Receive frame from HCI drivers */ ++static int hci_recv_frame(struct sk_buff *skb) ++{ ++ struct hci_dev *hdev = (struct hci_dev *) skb->dev; ++ ++ if (!hdev || ++ (!test_bit(HCI_UP, &hdev->flags) && !test_bit(HCI_INIT, &hdev->flags))) { ++ kfree_skb(skb); ++ return -ENXIO; ++ } ++ ++ /* Incomming skb */ ++ bt_cb(skb)->incoming = 1; ++ ++ /* Time stamp */ ++ __net_timestamp(skb); ++ ++ if (atomic_read(&hdev->promisc)) { ++#ifdef CONFIG_SCO_OVER_HCI ++ if(bt_cb(skb)->pkt_type == HCI_SCODATA_PKT){ ++ hci_send_to_alsa_ringbuffer(hdev, skb); ++ }else{ ++ if(bt_cb(skb)->pkt_type == HCI_EVENT_PKT){ ++ if(bypass_event(skb)){ ++ kfree_skb(skb); ++ return 0; ++ } ++ } ++ hci_send_to_stack(hdev, skb); ++ } ++#else ++ if(bt_cb(skb)->pkt_type == HCI_EVENT_PKT){ ++ if(bypass_event(skb)){ ++ kfree_skb(skb); ++ return 0; ++ } ++ } ++ /* Send copy to the sockets */ ++ hci_send_to_stack(hdev, skb); ++#endif ++ ++ } ++ ++ kfree_skb(skb); ++ return 0; ++} ++ ++ ++ ++static int hci_reassembly(struct hci_dev *hdev, int type, void *data, ++ int count, __u8 index) ++{ ++ int len = 0; ++ int hlen = 0; ++ int remain = count; ++ struct sk_buff *skb; ++ struct bt_skb_cb *scb; ++ ++ //AICBT_DBG("%s", __func__); ++ ++ if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) || ++ index >= NUM_REASSEMBLY) ++ return -EILSEQ; ++ ++ skb = hdev->reassembly[index]; ++ ++ if (!skb) { ++ switch (type) { ++ case HCI_ACLDATA_PKT: ++ len = HCI_MAX_FRAME_SIZE; ++ hlen = HCI_ACL_HDR_SIZE; ++ break; ++ case HCI_EVENT_PKT: ++ len = HCI_MAX_EVENT_SIZE; ++ hlen = HCI_EVENT_HDR_SIZE; ++ break; ++ case HCI_SCODATA_PKT: ++ len = HCI_MAX_SCO_SIZE; ++ hlen = HCI_SCO_HDR_SIZE; ++ break; ++ } ++ ++ skb = bt_skb_alloc(len, GFP_ATOMIC); ++ if (!skb) ++ return -ENOMEM; ++ ++ scb = (void *) skb->cb; ++ scb->expect = hlen; ++ scb->pkt_type = type; ++ ++ skb->dev = (void *) hdev; ++ hdev->reassembly[index] = skb; ++ } ++ ++ while (count) { ++ scb = (void *) skb->cb; ++ len = min_t(uint, scb->expect, count); ++ ++ memcpy(skb_put(skb, len), data, len); ++ ++ count -= len; ++ data += len; ++ scb->expect -= len; ++ remain = count; ++ ++ switch (type) { ++ case HCI_EVENT_PKT: ++ if (skb->len == HCI_EVENT_HDR_SIZE) { ++ struct hci_event_hdr *h = hci_event_hdr(skb); ++ scb->expect = h->plen; ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ hdev->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ ++ case HCI_ACLDATA_PKT: ++ if (skb->len == HCI_ACL_HDR_SIZE) { ++ struct hci_acl_hdr *h = hci_acl_hdr(skb); ++ scb->expect = __le16_to_cpu(h->dlen); ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ hdev->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ ++ case HCI_SCODATA_PKT: ++ if (skb->len == HCI_SCO_HDR_SIZE) { ++ struct hci_sco_hdr *h = hci_sco_hdr(skb); ++ scb->expect = h->dlen; ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ hdev->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ } ++ ++ if (scb->expect == 0) { ++ /* Complete frame */ ++ if(HCI_ACLDATA_PKT == type) ++ print_acl(skb,0); ++ if(HCI_SCODATA_PKT == type) ++ print_sco(skb,0); ++ if(HCI_EVENT_PKT == type) ++ print_event(skb); ++ ++ bt_cb(skb)->pkt_type = type; ++ hci_recv_frame(skb); ++ ++ hdev->reassembly[index] = NULL; ++ return remain; ++ } ++ } ++ ++ return remain; ++} ++ ++int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) ++{ ++ int rem = 0; ++ ++ if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ++ return -EILSEQ; ++ ++ while (count) { ++ rem = hci_reassembly(hdev, type, data, count, type - 1); ++ if (rem < 0) ++ return rem; ++ ++ data += (count - rem); ++ count = rem; ++ } ++ ++ return rem; ++} ++#endif //CONFIG_BLUEDROID ++ ++static int btchr_open(struct inode *inode_p, struct file *file_p) ++{ ++ struct btusb_data *data; ++ struct hci_dev *hdev; ++ ++ AICBT_DBG("%s: BT sdio char device is opening", __func__); ++ /* Not open unless wanna tracing log */ ++ /* trace_printk("%s: open....\n", __func__); */ ++ ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_DBG("%s: Failed to get hci dev[NULL]", __func__); ++ return -ENODEV; ++ } ++ data = GET_DRV_DATA(hdev); ++ ++ atomic_inc(&hdev->promisc); ++ /* ++ * As bt device is not re-opened when hotplugged out, we cannot ++ * trust on file's private data(may be null) when other file ops ++ * are invoked. ++ */ ++ file_p->private_data = data; ++ ++ mutex_lock(&btchr_mutex); ++ hci_dev_open(0); ++ mutex_unlock(&btchr_mutex); ++ ++ aic_clear_queue(); ++ return nonseekable_open(inode_p, file_p); ++} ++ ++static int btchr_close(struct inode *inode_p, struct file *file_p) ++{ ++ struct btusb_data *data; ++ struct hci_dev *hdev; ++ ++ AICBT_INFO("%s: BT sdio char device is closing", __func__); ++ /* Not open unless wanna tracing log */ ++ /* trace_printk("%s: close....\n", __func__); */ ++ ++ data = file_p->private_data; ++ file_p->private_data = NULL; ++ ++#if CONFIG_BLUEDROID ++ /* ++ * If the upper layer closes bt char interfaces, no reset ++ * action required even bt device hotplugged out. ++ */ ++ bt_reset = 0; ++#endif ++ ++ hdev = hci_dev_get(0); ++ if (hdev) { ++ atomic_set(&hdev->promisc, 0); ++ mutex_lock(&btchr_mutex); ++ hci_dev_close(0); ++ mutex_unlock(&btchr_mutex); ++ } ++ ++ return 0; ++} ++ ++void bt_data_dump(char* tag, void* data, unsigned long len){ ++ unsigned long i = 0; ++ uint8_t* data_ = (uint8_t* )data; ++ ++ printk("%s %s len:(%lu)\r\n", __func__, tag, len); ++ ++ for (i = 0; i < len; i += 16){ ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", ++ data_[0 + i], ++ data_[1 + i], ++ data_[2 + i], ++ data_[3 + i], ++ data_[4 + i], ++ data_[5 + i], ++ data_[6 + i], ++ data_[7 + i], ++ data_[8 + i], ++ data_[9 + i], ++ data_[10 + i], ++ data_[11 + i], ++ data_[12 + i], ++ data_[13 + i], ++ data_[14 + i], ++ data_[15 + i]); ++ } ++ ++} ++ ++static ssize_t btchr_read(struct file *file_p, ++ char __user *buf_p, ++ size_t count, ++ loff_t *pos_p) ++{ ++ struct hci_dev *hdev; ++ struct sk_buff *skb; ++ ssize_t ret = 0; ++ ++ while (count) { ++#if 1 ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ /* ++ * Note: Only when BT device hotplugged out, we wil get ++ * into such situation. In order to keep the upper layer ++ * stack alive (blocking the read), we should never return ++ * EFAULT or break the loop. ++ */ ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ } ++#endif ++ ret = wait_event_interruptible(btchr_read_wait, !is_queue_empty()); ++ if (ret < 0) { ++ AICBT_ERR("%s: wait event is signaled %d", __func__, (int)ret); ++ break; ++ } ++ ++ skb = aic_dequeue_try(count); ++ //bt_data_dump("btchr_read", skb->data, skb->len); ++ //printk("btchr_read \n"); ++ if (skb) { ++ ret = sdio_put_user(skb, buf_p, count); ++ if (ret < 0) ++ AICBT_ERR("%s: Failed to put data to user space", __func__); ++ kfree_skb(skb); ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++#ifdef CONFIG_SUPPORT_VENDOR_APCF ++void btchr_external_write(char* buff, int len){ ++ struct hci_dev *hdev; ++ struct sk_buff *skb; ++ int i; ++ struct btusb_data *data; ++ ++ AICBT_INFO("%s \r\n", __func__); ++ for(i=0;idev = (void *)hdev; ++ memcpy((__u8 *)skb->data,(__u8 *)buff,len); ++ skb_put(skb, len); ++ bt_cb(skb)->pkt_type = *((__u8 *)skb->data); ++ skb_pull(skb, 1); ++ data->hdev->send(skb); ++} ++ ++EXPORT_SYMBOL(btchr_external_write); ++#endif //CONFIG_SUPPORT_VENDOR_APCF ++ ++//extern struct rwnx_plat *g_rwnx_plat; ++static ssize_t btchr_write(struct file *file_p, ++ const char __user *buf_p, ++ size_t count, ++ loff_t *pos_p) ++{ ++ struct btusb_data *data = file_p->private_data; ++ struct hci_dev *hdev; ++ struct sk_buff *skb; ++ int err=0; ++ ++ AICBT_DBG("%s", __func__); ++ ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_WARN("%s: Failed to get hci dev[Null]", __func__); ++ /* ++ * Note: we bypass the data from the upper layer if bt device ++ * is hotplugged out. Fortunatelly, H4 or H5 HCI stack does ++ * NOT check btchr_write's return value. However, returning ++ * count instead of EFAULT is preferable. ++ */ ++ /* return -EFAULT; */ ++ return count; ++ } ++ ++#if 0 ++ /* Never trust on btusb_data, as bt device may be hotplugged out */ ++ data = GET_DRV_DATA(hdev); ++ if (!data) { ++ AICBT_WARN("%s: Failed to get bt usb driver data[Null]", __func__); ++ return count; ++ } ++#endif ++ ++ if (count > HCI_MAX_FRAME_SIZE) ++ return -EINVAL; ++ ++ skb = bt_skb_alloc(count, GFP_ATOMIC); ++ if (!skb) ++ return -ENOMEM; ++ skb_reserve(skb, -1); // Add this line ++ ++ if (copy_from_user(skb_put(skb, count), buf_p, count)) { ++ AICBT_ERR("%s: Failed to get data from user space", __func__); ++ kfree_skb(skb); ++ return -EFAULT; ++ } ++ ++ skb->dev = (void *)hdev; ++ bt_cb(skb)->pkt_type = *((__u8 *)skb->data); ++ //skb_pull(skb, 1); ++ //data->hdev->send(skb); ++ ++ //bt_data_dump("btwrite", skb->data, skb->len); ++ err = rwnx_sdio_bt_send_req(g_rwnx_plat->sdiodev->rwnx_hw, skb->len, skb); ++ if(err<0){ ++ printk("%s rwnx_sdio_bt_send_req error %d",__func__,err); ++ } ++ ++ kfree_skb(skb); ++ return count; ++} ++ ++static unsigned int btchr_poll(struct file *file_p, poll_table *wait) ++{ ++ struct btusb_data *data = file_p->private_data; ++ struct hci_dev *hdev; ++ ++ //AICBT_DBG("%s: BT sdio char device is polling", __func__); ++ ++ /*if(!bt_char_dev_registered) { ++ AICBT_ERR("%s: char device has not registered!", __func__); ++ return POLLERR | POLLHUP; ++ }*/ ++ //printk("poll wait\n"); ++ poll_wait(file_p, &btchr_read_wait, wait); ++ //printk("poll out\n"); ++ ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ //mdelay(URB_CANCELING_DELAY_MS); ++ return POLLERR | POLLHUP; ++ return POLLOUT | POLLWRNORM; ++ } ++ ++#if 0 ++ /* Never trust on btusb_data, as bt device may be hotplugged out */ ++ data = GET_DRV_DATA(hdev); ++ if (!data) { ++ /* ++ * When bt device is hotplugged out, btusb_data will ++ * be freed in disconnect. ++ */ ++ AICBT_ERR("%s: Failed to get bt sdio driver data[Null]", __func__); ++ mdelay(URB_CANCELING_DELAY_MS); ++ return POLLOUT | POLLWRNORM; ++ } ++#endif ++ ++ if (!is_queue_empty()) ++ return POLLIN | POLLRDNORM; ++ ++ return POLLOUT | POLLWRNORM; ++} ++static long btchr_ioctl(struct file *file_p,unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ struct hci_dev *hdev; ++ struct btusb_data *data; ++ //firmware_info *fw_info; ++ ++ /*if(!bt_char_dev_registered) { ++ return -ENODEV; ++ }*/ ++ ++ printk("%s cmd support %d \n",__func__,cmd); ++ ++#if 1 ++ if(check_set_dlfw_state_value(1) != 1) { ++ AICBT_ERR("%s bt controller is disconnecting!", __func__); ++ return 0; ++ } ++ ++ hdev = hci_dev_get(0); ++ if(!hdev) { ++ AICBT_ERR("%s device is NULL!", __func__); ++ set_dlfw_state_value(0); ++ return 0; ++ } ++ //data = GET_DRV_DATA(hdev); ++ //fw_info = data->fw_info; ++ ++ AICBT_INFO(" btchr_ioctl DOWN_FW_CFG with Cmd:%d",cmd); ++ switch (cmd) { ++ case DOWN_FW_CFG: ++ AICBT_INFO(" btchr_ioctl DOWN_FW_CFG"); ++ /*ret = usb_autopm_get_interface(data->intf); ++ if (ret < 0){ ++ goto failed; ++ }*/ ++ ++ //ret = download_patch(fw_info,1); ++ /*usb_autopm_put_interface(data->intf); ++ if(ret < 0){ ++ AICBT_ERR("%s:Failed in download_patch with ret:%d",__func__,ret); ++ goto failed; ++ } ++ ++ ret = hdev->open(hdev); ++ if(ret < 0){ ++ AICBT_ERR("%s:Failed in hdev->open(hdev):%d",__func__,ret); ++ goto failed; ++ }*/ ++ set_bit(HCI_UP, &hdev->flags); ++ set_dlfw_state_value(0); ++ wake_up_interruptible(&bt_dlfw_wait); ++ return 1; ++ case DWFW_CMPLT: ++ AICBT_INFO(" btchr_ioctl DWFW_CMPLT"); ++#if 1 ++ case SET_ISO_CFG: ++ AICBT_INFO("btchr_ioctl SET_ISO_CFG"); ++ if(copy_from_user(&(hdev->voice_setting), (__u16*)arg, sizeof(__u16))){ ++ AICBT_INFO(" voice settings err"); ++ } ++ //hdev->voice_setting = *(uint16_t*)arg; ++ AICBT_INFO(" voice settings = %d", hdev->voice_setting); ++ //return 1; ++#endif ++ case GET_USB_INFO: ++ //ret = download_patch(fw_info,1); ++ AICBT_INFO(" btchr_ioctl GET_USB_INFO"); ++ /*ret = hdev->open(hdev); ++ if(ret < 0){ ++ AICBT_ERR("%s:Failed in hdev->open(hdev):%d",__func__,ret); ++ //goto done; ++ }*/ ++ set_bit(HCI_UP, &hdev->flags); ++ set_dlfw_state_value(0); ++ wake_up_interruptible(&bt_dlfw_wait); ++ return 1; ++ case RESET_CONTROLLER: ++ AICBT_INFO(" btchr_ioctl RESET_CONTROLLER"); ++ //reset_controller(fw_info); ++ return 1; ++ default: ++ AICBT_ERR("%s:Failed with wrong Cmd:%d",__func__,cmd); ++ goto failed; ++ } ++ failed: ++ set_dlfw_state_value(0); ++ wake_up_interruptible(&bt_dlfw_wait); ++ return ret; ++#endif ++} ++ ++#ifdef CONFIG_PLATFORM_UBUNTU//AIDEN ++typedef u32 compat_uptr_t; ++static inline void __user *compat_ptr(compat_uptr_t uptr) ++{ ++ return (void __user *)(unsigned long)uptr; ++} ++#endif ++ ++#ifdef CONFIG_COMPAT ++static long compat_btchr_ioctl (struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ AICBT_DBG("%s: enter",__func__); ++ return btchr_ioctl(filp, cmd, (unsigned long) compat_ptr(arg)); ++} ++#endif ++static struct file_operations bt_chrdev_ops = { ++ open : btchr_open, ++ release : btchr_close, ++ read : btchr_read, ++ write : btchr_write, ++ poll : btchr_poll, ++ unlocked_ioctl : btchr_ioctl, ++#ifdef CONFIG_COMPAT ++ compat_ioctl : compat_btchr_ioctl, ++#endif ++}; ++ ++int btchr_init() ++{ ++ int res = 0; ++ struct device *dev; ++ ++ AICBT_INFO("Register sdio char device interface for BT driver"); ++ /* ++ * btchr mutex is used to sync between ++ * 1) downloading patch and opening bt char driver ++ * 2) the file operations of bt char driver ++ */ ++ mutex_init(&btchr_mutex); ++ ++ skb_queue_head_init(&btchr_readq); ++ init_waitqueue_head(&btchr_read_wait); ++ init_waitqueue_head(&bt_dlfw_wait); ++ ++ bt_char_class = class_create(THIS_MODULE, BT_CHAR_DEVICE_NAME); ++ if (IS_ERR(bt_char_class)) { ++ AICBT_ERR("Failed to create bt char class"); ++ return PTR_ERR(bt_char_class); ++ } ++ ++ res = alloc_chrdev_region(&bt_devid, 0, 1, BT_CHAR_DEVICE_NAME); ++ if (res < 0) { ++ AICBT_ERR("Failed to allocate bt char device"); ++ goto err_alloc; ++ } ++ ++ dev = device_create(bt_char_class, NULL, bt_devid, NULL, BT_CHAR_DEVICE_NAME); ++ if (IS_ERR(dev)) { ++ AICBT_ERR("Failed to create bt char device"); ++ res = PTR_ERR(dev); ++ goto err_create; ++ } ++ ++ cdev_init(&bt_char_dev, &bt_chrdev_ops); ++ res = cdev_add(&bt_char_dev, bt_devid, 1); ++ if (res < 0) { ++ AICBT_ERR("Failed to add bt char device"); ++ goto err_add; ++ } ++ ++ return 0; ++ ++err_add: ++ device_destroy(bt_char_class, bt_devid); ++err_create: ++ unregister_chrdev_region(bt_devid, 1); ++err_alloc: ++ class_destroy(bt_char_class); ++ return res; ++} ++ ++void btchr_exit(void) ++{ ++ AICBT_INFO("Unregister sdio char device interface for BT driver"); ++ ++ device_destroy(bt_char_class, bt_devid); ++ cdev_del(&bt_char_dev); ++ unregister_chrdev_region(bt_devid, 1); ++ class_destroy(bt_char_class); ++ ++ return; ++} ++ ++int hdev_init(void) ++{ ++ struct hci_dev *hdev; ++ int err=0; ++ hdev = hci_alloc_dev(); ++ ++ err = hci_register_dev(hdev); ++ if (err < 0) { ++ hci_free_dev(hdev); ++ hdev = NULL; ++ return err; ++ } ++ ++ spin_lock_init(&queue_lock); ++ ++ return 0; ++} ++ ++void hdev_exit(void) ++{ ++ struct hci_dev *hdev; ++ hdev = ghdev; ++ hci_unregister_dev(hdev); ++ hci_free_dev(hdev); ++} ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h +new file mode 100644 +index 000000000000..153ba49d7c55 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h +@@ -0,0 +1,554 @@ ++#ifndef _AICWF_SDIO_BT_H_ ++#define _AICWF_SDIO_BT_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++ ++#ifdef CONFIG_PLATFORM_UBUNTU ++#define CONFIG_BLUEDROID 0 /* bleuz 0, bluedroid 1 */ ++#else ++#define CONFIG_BLUEDROID 1 /* bleuz 0, bluedroid 1 */ ++#endif ++/* #define HCI_VERSION_CODE KERNEL_VERSION(3, 14, 41) */ ++#define HCI_VERSION_CODE LINUX_VERSION_CODE ++ ++ ++#define PRINT_CMD_EVENT 1 ++#define PRINT_ACL_DATA 1 ++#define PRINT_SCO_DATA 1 ++ ++#define AICBT_DBG_FLAG 1 ++ ++#if AICBT_DBG_FLAG ++#define AICBT_DBG(fmt, arg...) printk( "aic_btsdio: " fmt "\n" , ## arg) ++#else ++#define AICBT_DBG(fmt, arg...) ++#endif ++ ++#define AICBT_INFO(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) ++#define AICBT_WARN(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) ++#define AICBT_ERR(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 0) ++#define GET_DRV_DATA(x) hci_get_drvdata(x) ++#else ++#define GET_DRV_DATA(x) x->driver_data ++#endif ++ ++#if CONFIG_BLUEDROID ++struct btusb_data { ++ struct hci_dev *hdev; ++ //struct usb_device *udev; ++ //struct usb_interface *intf; ++ //struct usb_interface *isoc; ++ ++ spinlock_t lock; ++ ++ unsigned long flags; ++ ++ struct work_struct work; ++ struct work_struct waker; ++ ++ /*struct usb_anchor tx_anchor; ++ struct usb_anchor intr_anchor; ++ struct usb_anchor bulk_anchor; ++ struct usb_anchor isoc_anchor; ++ struct usb_anchor deferred;*/ ++ int tx_in_flight; ++ spinlock_t txlock; ++ ++#if (CONFIG_BLUEDROID == 0) ++#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) ++ spinlock_t rxlock; ++ struct sk_buff *evt_skb; ++ struct sk_buff *acl_skb; ++ struct sk_buff *sco_skb; ++#endif ++#endif ++ ++ /*struct usb_endpoint_descriptor *intr_ep; ++ struct usb_endpoint_descriptor *bulk_tx_ep; ++ struct usb_endpoint_descriptor *bulk_rx_ep; ++ struct usb_endpoint_descriptor *isoc_tx_ep; ++ struct usb_endpoint_descriptor *isoc_rx_ep;*/ ++ ++ __u8 cmdreq_type; ++ ++ unsigned int sco_num; ++ int isoc_altsetting; ++ int suspend_count; ++ uint16_t sco_handle; ++ ++#if (CONFIG_BLUEDROID == 0) ++#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) ++ int (*recv_bulk) (struct btusb_data * data, void *buffer, int count); ++#endif ++#endif ++ ++//#ifdef CONFIG_HAS_EARLYSUSPEND ++#if 0 ++ struct early_suspend early_suspend; ++#else ++ struct notifier_block pm_notifier; ++ struct notifier_block reboot_notifier; ++#endif ++ //firmware_info *fw_info; ++ ++#ifdef CONFIG_SCO_OVER_HCI ++ AIC_sco_card_t *pSCOSnd; ++#endif ++}; ++ ++ ++ ++#define QUEUE_SIZE 500 ++ ++/*************************************** ++** AicSemi - Integrate from bluetooth.h ** ++*****************************************/ ++/* Reserv for core and drivers use */ ++#define BT_SKB_RESERVE 8 ++ ++/* BD Address */ ++typedef struct { ++ __u8 b[6]; ++} __packed bdaddr_t; ++ ++/* Skb helpers */ ++struct bt_skb_cb { ++ __u8 pkt_type; ++ __u8 incoming; ++ __u16 expect; ++ __u16 tx_seq; ++ __u8 retries; ++ __u8 sar; ++ __u8 force_active; ++}; ++ ++#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) ++ ++ ++/*********************************** ++** AicSemi - Integrate from hci.h ** ++***********************************/ ++#define HCI_MAX_ACL_SIZE 1024 ++#define HCI_MAX_SCO_SIZE 255 ++#define HCI_MAX_EVENT_SIZE 260 ++#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) ++ ++/* 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 ++ ++/* HCI controller types */ ++#define HCI_BREDR 0x00 ++#define HCI_AMP 0x01 ++ ++/* HCI device flags */ ++enum { ++ HCI_UP, ++ HCI_INIT, ++ HCI_RUNNING, ++ ++ HCI_PSCAN, ++ HCI_ISCAN, ++ HCI_AUTH, ++ HCI_ENCRYPT, ++ HCI_INQUIRY, ++ ++ HCI_RAW, ++ ++ HCI_RESET, ++}; ++ ++/* ++ * BR/EDR and/or LE controller flags: the flags defined here should represent ++ * states from the controller. ++ */ ++enum { ++ HCI_SETUP, ++ HCI_AUTO_OFF, ++ HCI_MGMT, ++ HCI_PAIRABLE, ++ HCI_SERVICE_CACHE, ++ HCI_LINK_KEYS, ++ HCI_DEBUG_KEYS, ++ HCI_UNREGISTER, ++ ++ HCI_LE_SCAN, ++ HCI_SSP_ENABLED, ++ HCI_HS_ENABLED, ++ HCI_LE_ENABLED, ++ HCI_CONNECTABLE, ++ HCI_DISCOVERABLE, ++ HCI_LINK_SECURITY, ++ HCI_PENDING_CLASS, ++}; ++ ++/* HCI data types */ ++#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 ++ ++#define HCI_MAX_NAME_LENGTH 248 ++#define HCI_MAX_EIR_LENGTH 240 ++ ++#define HCI_OP_READ_LOCAL_VERSION 0x1001 ++struct hci_rp_read_local_version { ++ __u8 status; ++ __u8 hci_ver; ++ __le16 hci_rev; ++ __u8 lmp_ver; ++ __le16 manufacturer; ++ __le16 lmp_subver; ++} __packed; ++ ++#define HCI_EV_CMD_COMPLETE 0x0e ++struct hci_ev_cmd_complete { ++ __u8 ncmd; ++ __le16 opcode; ++} __packed; ++ ++/* ---- HCI Packet structures ---- */ ++#define HCI_COMMAND_HDR_SIZE 3 ++#define HCI_EVENT_HDR_SIZE 2 ++#define HCI_ACL_HDR_SIZE 4 ++#define HCI_SCO_HDR_SIZE 3 ++ ++struct hci_command_hdr { ++ __le16 opcode; /* OCF & OGF */ ++ __u8 plen; ++} __packed; ++ ++struct hci_event_hdr { ++ __u8 evt; ++ __u8 plen; ++} __packed; ++ ++struct hci_acl_hdr { ++ __le16 handle; /* Handle & Flags(PB, BC) */ ++ __le16 dlen; ++} __packed; ++ ++struct hci_sco_hdr { ++ __le16 handle; ++ __u8 dlen; ++} __packed; ++ ++static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb) ++{ ++ return (struct hci_event_hdr *) skb->data; ++} ++ ++static inline struct hci_acl_hdr *hci_acl_hdr(const struct sk_buff *skb) ++{ ++ return (struct hci_acl_hdr *) skb->data; ++} ++ ++static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) ++{ ++ return (struct hci_sco_hdr *) skb->data; ++} ++ ++/* ---- HCI Ioctl requests structures ---- */ ++struct hci_dev_stats { ++ __u32 err_rx; ++ __u32 err_tx; ++ __u32 cmd_tx; ++ __u32 evt_rx; ++ __u32 acl_tx; ++ __u32 acl_rx; ++ __u32 sco_tx; ++ __u32 sco_rx; ++ __u32 byte_rx; ++ __u32 byte_tx; ++}; ++/* AicSemi - Integrate from hci.h end */ ++ ++/***************************************** ++** AicSemi - Integrate from hci_core.h ** ++*****************************************/ ++struct hci_conn_hash { ++ struct list_head list; ++ unsigned int acl_num; ++ unsigned int sco_num; ++ unsigned int le_num; ++}; ++ ++#define HCI_MAX_SHORT_NAME_LENGTH 10 ++ ++#define NUM_REASSEMBLY 4 ++struct hci_dev { ++ struct mutex lock; ++ ++ char name[8]; ++ unsigned long flags; ++ __u16 id; ++ __u8 bus; ++ __u8 dev_type; ++ ++ struct sk_buff *reassembly[NUM_REASSEMBLY]; ++ ++ struct hci_conn_hash conn_hash; ++ ++ struct hci_dev_stats stat; ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) ++ atomic_t refcnt; ++ struct module *owner; ++ void *driver_data; ++#endif ++ ++ atomic_t promisc; ++ ++ struct device *parent; ++ struct device dev; ++ ++ unsigned long dev_flags; ++ ++ int (*open)(struct hci_dev *hdev); ++ int (*close)(struct hci_dev *hdev); ++ int (*flush)(struct hci_dev *hdev); ++ int (*send)(struct sk_buff *skb); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) ++ void (*destruct)(struct hci_dev *hdev); ++#endif ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 1) ++ __u16 voice_setting; ++#endif ++ void (*notify)(struct hci_dev *hdev, unsigned int evt); ++ int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); ++ u8 *align_data; ++}; ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) ++static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d) ++{ ++ atomic_inc(&d->refcnt); ++ return d; ++} ++ ++static inline void __hci_dev_put(struct hci_dev *d) ++{ ++ if (atomic_dec_and_test(&d->refcnt)) ++ d->destruct(d); ++} ++#endif ++ ++static inline void *hci_get_drvdata(struct hci_dev *hdev) ++{ ++ return dev_get_drvdata(&hdev->dev); ++} ++ ++static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) ++{ ++ dev_set_drvdata(&hdev->dev, data); ++} ++ ++#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev)) ++ ++ ++/* ---- HCI Packet structures ---- */ ++#define HCI_COMMAND_HDR_SIZE 3 ++#define HCI_EVENT_HDR_SIZE 2 ++#define HCI_ACL_HDR_SIZE 4 ++#define HCI_SCO_HDR_SIZE 3 ++ ++/* ----- HCI Commands ---- */ ++#define HCI_OP_INQUIRY 0x0401 ++#define HCI_OP_INQUIRY_CANCEL 0x0402 ++#define HCI_OP_EXIT_PERIODIC_INQ 0x0404 ++#define HCI_OP_CREATE_CONN 0x0405 ++#define HCI_OP_DISCONNECT 0x0406 ++#define HCI_OP_ADD_SCO 0x0407 ++#define HCI_OP_CREATE_CONN_CANCEL 0x0408 ++#define HCI_OP_ACCEPT_CONN_REQ 0x0409 ++#define HCI_OP_REJECT_CONN_REQ 0x040a ++#define HCI_OP_LINK_KEY_REPLY 0x040b ++#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c ++#define HCI_OP_PIN_CODE_REPLY 0x040d ++#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e ++#define HCI_OP_CHANGE_CONN_PTYPE 0x040f ++#define HCI_OP_AUTH_REQUESTED 0x0411 ++#define HCI_OP_SET_CONN_ENCRYPT 0x0413 ++#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415 ++#define HCI_OP_REMOTE_NAME_REQ 0x0419 ++#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a ++#define HCI_OP_READ_REMOTE_FEATURES 0x041b ++#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c ++#define HCI_OP_READ_REMOTE_VERSION 0x041d ++#define HCI_OP_SETUP_SYNC_CONN 0x0428 ++#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429 ++#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a ++#define HCI_OP_SNIFF_MODE 0x0803 ++#define HCI_OP_EXIT_SNIFF_MODE 0x0804 ++#define HCI_OP_ROLE_DISCOVERY 0x0809 ++#define HCI_OP_SWITCH_ROLE 0x080b ++#define HCI_OP_READ_LINK_POLICY 0x080c ++#define HCI_OP_WRITE_LINK_POLICY 0x080d ++#define HCI_OP_READ_DEF_LINK_POLICY 0x080e ++#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f ++#define HCI_OP_SNIFF_SUBRATE 0x0811 ++#define HCI_OP_Write_Link_Policy_Settings 0x080d ++#define HCI_OP_SET_EVENT_MASK 0x0c01 ++#define HCI_OP_RESET 0x0c03 ++#define HCI_OP_SET_EVENT_FLT 0x0c05 ++#define HCI_OP_Write_Extended_Inquiry_Response 0x0c52 ++#define HCI_OP_Write_Simple_Pairing_Mode 0x0c56 ++#define HCI_OP_Read_Buffer_Size 0x1005 ++#define HCI_OP_Host_Buffer_Size 0x0c33 ++#define HCI_OP_Read_Local_Version_Information 0x1001 ++#define HCI_OP_Read_BD_ADDR 0x1009 ++#define HCI_OP_Read_Local_Supported_Commands 0x1002 ++#define HCI_OP_Write_Scan_Enable 0x0c1a ++#define HCI_OP_Write_Current_IAC_LAP 0x0c3a ++#define HCI_OP_Write_Inquiry_Scan_Activity 0x0c1e ++#define HCI_OP_Write_Class_of_Device 0x0c24 ++#define HCI_OP_LE_Rand 0x2018 ++#define HCI_OP_LE_Set_Random_Address 0x2005 ++#define HCI_OP_LE_Set_Extended_Scan_Enable 0x2042 ++#define HCI_OP_LE_Set_Extended_Scan_Parameters 0x2041 ++#define HCI_OP_Set_Event_Filter 0x0c05 ++#define HCI_OP_Write_Voice_Setting 0x0c26 ++#define HCI_OP_Change_Local_Name 0x0c13 ++#define HCI_OP_Read_Local_Name 0x0c14 ++#define HCI_OP_Wirte_Page_Timeout 0x0c18 ++#define HCI_OP_LE_Clear_Resolving_List 0x0c29 ++#define HCI_OP_LE_Set_Addres_Resolution_Enable_Command 0x0c2e ++#define HCI_OP_Write_Inquiry_mode 0x0c45 ++#define HCI_OP_Write_Page_Scan_Type 0x0c47 ++#define HCI_OP_Write_Inquiry_Scan_Type 0x0c43 ++ ++#define HCI_OP_Delete_Stored_Link_Key 0x0c12 ++#define HCI_OP_LE_Read_Local_Resolvable_Address 0x202d ++#define HCI_OP_LE_Extended_Create_Connection 0x2043 ++#define HCI_OP_Read_Remote_Version_Information 0x041d ++#define HCI_OP_LE_Start_Encryption 0x2019 ++#define HCI_OP_LE_Add_Device_to_Resolving_List 0x2027 ++#define HCI_OP_LE_Set_Privacy_Mode 0x204e ++#define HCI_OP_LE_Connection_Update 0x2013 ++ ++/* ----- HCI events---- */ ++#define HCI_OP_DISCONNECT 0x0406 ++#define HCI_EV_INQUIRY_COMPLETE 0x01 ++#define HCI_EV_INQUIRY_RESULT 0x02 ++#define HCI_EV_CONN_COMPLETE 0x03 ++#define HCI_EV_CONN_REQUEST 0x04 ++#define HCI_EV_DISCONN_COMPLETE 0x05 ++#define HCI_EV_AUTH_COMPLETE 0x06 ++#define HCI_EV_REMOTE_NAME 0x07 ++#define HCI_EV_ENCRYPT_CHANGE 0x08 ++#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09 ++ ++#define HCI_EV_REMOTE_FEATURES 0x0b ++#define HCI_EV_REMOTE_VERSION 0x0c ++#define HCI_EV_QOS_SETUP_COMPLETE 0x0d ++#define HCI_EV_CMD_COMPLETE 0x0e ++#define HCI_EV_CMD_STATUS 0x0f ++ ++#define HCI_EV_ROLE_CHANGE 0x12 ++#define HCI_EV_NUM_COMP_PKTS 0x13 ++#define HCI_EV_MODE_CHANGE 0x14 ++#define HCI_EV_PIN_CODE_REQ 0x16 ++#define HCI_EV_LINK_KEY_REQ 0x17 ++#define HCI_EV_LINK_KEY_NOTIFY 0x18 ++#define HCI_EV_CLOCK_OFFSET 0x1c ++#define HCI_EV_PKT_TYPE_CHANGE 0x1d ++#define HCI_EV_PSCAN_REP_MODE 0x20 ++ ++#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22 ++#define HCI_EV_REMOTE_EXT_FEATURES 0x23 ++#define HCI_EV_SYNC_CONN_COMPLETE 0x2c ++#define HCI_EV_SYNC_CONN_CHANGED 0x2d ++#define HCI_EV_SNIFF_SUBRATE 0x2e ++#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f ++#define HCI_EV_IO_CAPA_REQUEST 0x31 ++#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36 ++#define HCI_EV_REMOTE_HOST_FEATURES 0x3d ++#define HCI_EV_LE_Meta 0x3e ++ ++/* ULP Event sub code */ ++#define HCI_BLE_CONN_COMPLETE_EVT 0x01 ++#define HCI_BLE_ADV_PKT_RPT_EVT 0x02 ++#define HCI_BLE_LL_CONN_PARAM_UPD_EVT 0x03 ++#define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT 0x04 ++#define HCI_BLE_LTK_REQ_EVT 0x05 ++#define HCI_BLE_RC_PARAM_REQ_EVT 0x06 ++#define HCI_BLE_DATA_LENGTH_CHANGE_EVT 0x07 ++#define HCI_BLE_ENHANCED_CONN_COMPLETE_EVT 0x0a ++#define HCI_BLE_DIRECT_ADV_EVT 0x0b ++#define HCI_BLE_PHY_UPDATE_COMPLETE_EVT 0x0c ++#define HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT 0x0D ++#define HCI_BLE_PERIODIC_ADV_SYNC_EST_EVT 0x0E ++#define HCI_BLE_PERIODIC_ADV_REPORT_EVT 0x0F ++#define HCI_BLE_PERIODIC_ADV_SYNC_LOST_EVT 0x10 ++#define HCI_BLE_SCAN_TIMEOUT_EVT 0x11 ++#define HCI_LE_ADVERTISING_SET_TERMINATED_EVT 0x12 ++#define HCI_BLE_SCAN_REQ_RX_EVT 0x13 ++#define HCI_BLE_CIS_EST_EVT 0x19 ++#define HCI_BLE_CIS_REQ_EVT 0x1a ++#define HCI_BLE_CREATE_BIG_CPL_EVT 0x1b ++#define HCI_BLE_TERM_BIG_CPL_EVT 0x1c ++#define HCI_BLE_BIG_SYNC_EST_EVT 0x1d ++#define HCI_BLE_BIG_SYNC_LOST_EVT 0x1e ++#define HCI_BLE_REQ_PEER_SCA_CPL_EVT 0x1f ++ ++#define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */ ++ ++#define CONFIG_MAC_OFFSET_GEN_1_2 (0x3C) //MAC's OFFSET in config/efuse for aic generation 1~2 bluetooth chip ++#define CONFIG_MAC_OFFSET_GEN_3PLUS (0x44) //MAC's OFFSET in config/efuse for aic generation 3+ bluetooth chip ++ ++//Define ioctl cmd the same as HCIDEVUP in the kernel ++#define DOWN_FW_CFG _IOW('E', 176, int) ++//#ifdef CONFIG_SCO_OVER_HCI ++//#define SET_ISO_CFG _IOW('H', 202, int) ++//#else ++#define SET_ISO_CFG _IOW('E', 177, int) ++//#endif ++#define RESET_CONTROLLER _IOW('E', 178, int) ++#define DWFW_CMPLT _IOW('E', 179, int) ++ ++#define GET_USB_INFO _IOR('E', 180, int) ++ ++void bt_data_dump(char* tag, void* data, unsigned long len); ++int aic_enqueue(struct sk_buff *skb); ++int aic_queue_cnt(void); ++int bt_sdio_recv(u8 *data,u32 data_len); ++ ++ ++int btchr_init(void); ++void btchr_exit(void); ++int hdev_init(void); ++void hdev_exit(void); ++ ++ ++struct hci_dev *hci_dev_get(int index); ++int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); ++#else ++int btsdio_init(void); ++void btsdio_remove(void); ++int bt_sdio_recv(u8 *data,u32 data_len); ++#endif ++#endif//_AICWF_SDIO_BT_H_ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.c +new file mode 100644 +index 000000000000..4f3d5867dd04 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.c +@@ -0,0 +1,2023 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file aic_priv_cmd.c ++ * ++ * @brief Entry point of the AIC driver ++ * ++ * Copyright (C) Aicsemi 2018-2024 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include "rwnx_defs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_main.h" ++#include "aicwf_sdio.h" ++#include "aic_priv_cmd.h" ++#include "rwnx_mod_params.h" ++ ++ ++extern int testmode; ++static void print_help(const char *cmd); ++struct dbg_rftest_cmd_cfm cfm = {{0,}}; ++ ++#ifdef CONFIG_RFTEST ++enum { ++ SET_TX, ++ SET_TXSTOP, ++ SET_TXTONE, ++ SET_RX, ++ GET_RX_RESULT, ++ SET_RXSTOP, ++ SET_RX_METER, ++ SET_POWER, ++ SET_XTAL_CAP, ++ SET_XTAL_CAP_FINE, ++ GET_EFUSE_BLOCK, ++ SET_FREQ_CAL, ++ SET_FREQ_CAL_FINE, ++ GET_FREQ_CAL, ++ SET_MAC_ADDR, ++ GET_MAC_ADDR, ++ SET_BT_MAC_ADDR, ++ GET_BT_MAC_ADDR, ++ SET_VENDOR_INFO, ++ GET_VENDOR_INFO, ++ RDWR_PWRMM, ++ RDWR_PWRIDX, ++ RDWR_PWRLVL = RDWR_PWRIDX, ++ RDWR_PWROFST, ++ RDWR_DRVIBIT, ++ RDWR_EFUSE_PWROFST, ++ RDWR_EFUSE_DRVIBIT, ++ SET_PAPR, ++ SET_CAL_XTAL, ++ GET_CAL_XTAL_RES, ++ SET_COB_CAL, ++ GET_COB_CAL_RES, ++ RDWR_EFUSE_USRDATA, ++ SET_NOTCH, ++ RDWR_PWROFSTFINE, ++ RDWR_EFUSE_PWROFSTFINE, ++ RDWR_EFUSE_SDIOCFG, ++ RDWR_EFUSE_USBVIDPID, ++ SET_SRRC, ++ SET_FSS, ++ RDWR_EFUSE_HE_OFF, ++ SET_USB_OFF, ++ SET_PLL_TEST, ++ SET_ANT_MODE, ++ RDWR_BT_EFUSE_PWROFST, ++}; ++ ++typedef struct { ++ u8_l chan; ++ u8_l bw; ++ u8_l mode; ++ u8_l rate; ++ u16_l length; ++ u16_l tx_intv_us; ++ s8_l max_pwr; ++} cmd_rf_settx_t; ++ ++typedef struct { ++ u8_l val; ++} cmd_rf_setfreq_t; ++ ++typedef struct { ++ u8_l chan; ++ u8_l bw; ++} cmd_rf_rx_t; ++ ++typedef struct { ++ u8_l block; ++} cmd_rf_getefuse_t; ++ ++typedef struct { ++ u8_l dutid; ++ u8_l chip_num; ++ u8_l dis_xtal; ++} cmd_rf_setcobcal_t; ++ ++typedef struct { ++ u16_l dut_rcv_golden_num; ++ u8_l golden_rcv_dut_num; ++ s8_l rssi_static; ++ s8_l snr_static; ++ s8_l dut_rssi_static; ++ u16_l reserved; ++} cob_result_ptr_t; ++#endif ++ ++typedef struct ++{ ++ u8_l func; ++ u8_l cnt; ++ u8_l reserved[2]; ++ u32_l usrdata[3]; // 3 words totally ++} cmd_ef_usrdata_t; ++ ++#define CMD_MAXARGS 10 ++#define POWER_LEVEL_INVALID_VAL (127) ++ ++extern char country_code[]; ++ ++#if 0//#include ++#define isblank(c) ((c) == ' ' || (c) == '\t') ++#define isascii(c) (((unsigned char)(c)) <= 0x7F) ++ ++static int isdigit(unsigned char c) ++{ ++ return ((c >= '0') && (c <='9')); ++} ++ ++static int isxdigit(unsigned char c) ++{ ++ if ((c >= '0') && (c <='9')) ++ return 1; ++ if ((c >= 'a') && (c <='f')) ++ return 1; ++ if ((c >= 'A') && (c <='F')) ++ return 1; ++ return 0; ++} ++ ++static int islower(unsigned char c) ++{ ++ return ((c >= 'a') && (c <='z')); ++} ++ ++static unsigned char toupper(unsigned char c) ++{ ++ if (islower(c)) ++ c -= 'a'-'A'; ++ return c; ++} ++#endif ++ ++static int parse_line (char *line, char *argv[]) ++{ ++ int nargs = 0; ++ ++ while (nargs < CMD_MAXARGS) { ++ /* skip any white space */ ++ while ((*line == ' ') || (*line == '\t')) { ++ ++line; ++ } ++ ++ if (*line == '\0') { /* end of line, no more args */ ++ argv[nargs] = 0; ++ return nargs; ++ } ++ ++ /* Argument include space should be bracketed by quotation mark */ ++ if (*line == '\"') { ++ /* Skip quotation mark */ ++ line++; ++ ++ /* Begin of argument string */ ++ argv[nargs++] = line; ++ ++ /* Until end of argument */ ++ while (*line && (*line != '\"')) { ++ ++line; ++ } ++ } else { ++ argv[nargs++] = line; /* begin of argument string */ ++ ++ /* find end of string */ ++ while (*line && (*line != ' ') && (*line != '\t')) { ++ ++line; ++ } ++ } ++ ++ if (*line == '\0') { /* end of line, no more args */ ++ argv[nargs] = 0; ++ return nargs; ++ } ++ ++ *line++ = '\0'; /* terminate current arg */ ++ } ++ ++ printk("** Too many args (max. %d) **\n", CMD_MAXARGS); ++ ++ return nargs; ++} ++ ++unsigned int command_strtoul(const char *cp, char **endp, unsigned int base) ++{ ++ unsigned int result = 0, value, is_neg = 0; ++ ++ if (*cp == '0') { ++ cp++; ++ if ((*cp == 'x') && isxdigit(cp[1])) { ++ base = 16; ++ cp++; ++ } ++ if (!base) { ++ base = 8; ++ } ++ } ++ if (!base) { ++ base = 10; ++ } ++ if (*cp == '-') { ++ is_neg = 1; ++ cp++; ++ } ++ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0' : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) { ++ result = result * base + value; ++ cp++; ++ } ++ if (is_neg) ++ result = (unsigned int)((int)result * (-1)); ++ ++ if (endp) ++ *endp = (char *)cp; ++ return result; ++} ++ ++/* ++ * aic_priv_cmd handers. ++ */ ++static int aic_priv_cmd_set_tx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_settx_t settx_param; ++ u8_l set_p = 0; ++ u8_l lvl_band, lvl_mod, lvl_idx, lvl_pwr = 0; ++ u8_l buf[10]; ++#ifdef CONFIG_POWER_LIMIT ++ int8_t max_pwr; ++ uint8_t r_idx; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++ txpwr_loss = &txpwr_loss_tmp; ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (argc < 6) ++ return -EINVAL; ++ ++ settx_param.chan = command_strtoul(argv[1], NULL, 10); ++ settx_param.bw = command_strtoul(argv[2], NULL, 10); ++ settx_param.mode = command_strtoul(argv[3], NULL, 10); ++ settx_param.rate = command_strtoul(argv[4], NULL, 10); ++ settx_param.length = command_strtoul(argv[5], NULL, 10); ++ if (argc > 6) { ++ settx_param.tx_intv_us = command_strtoul(argv[6], NULL, 10); ++ } else { ++ settx_param.tx_intv_us = 10000; // set default val 10ms ++ } ++ if (argc > 7) { ++ if (dev->chipid == PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ return -EINVAL; ++ } ++ lvl_pwr = command_strtoul(argv[7], NULL, 10); ++ AICWFDBG(LOGINFO, "lvl_pwr: %d\n", lvl_pwr); ++ ++ if (settx_param.chan >= 36) ++ lvl_band = 2; ++ else ++ lvl_band = 1; ++ if (settx_param.mode == 0) ++ lvl_mod = 0; ++ else if (settx_param.mode == 2 || settx_param.mode == 4) ++ lvl_mod = 1; ++ else if (settx_param.mode == 5) ++ lvl_mod = 2; ++ if (settx_param.mode >= 4) ++ lvl_idx = settx_param.rate & 0xF; ++ else if (settx_param.mode >= 2) ++ lvl_idx = settx_param.rate & 0x7; ++ else ++ lvl_idx = settx_param.rate; ++ ++ buf[0] = lvl_band; ++ buf[1] = lvl_mod; ++ buf[2] = lvl_idx; ++ buf[3] = lvl_pwr; ++ ++ set_p = 1; ++ } ++ settx_param.max_pwr = POWER_LEVEL_INVALID_VAL; ++ AICWFDBG(LOGINFO, "txparam:%d,%d,%d,%d,%d,%d\n", settx_param.chan, settx_param.bw, ++ settx_param.mode, settx_param.rate, settx_param.length, settx_param.tx_intv_us); ++ ++#ifdef CONFIG_POWER_LIMIT ++ r_idx = get_ccode_region(country_code); ++ txpwr_loss = &txpwr_loss_tmp; ++ get_userconfig_txpwr_loss(txpwr_loss); ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ if (txpwr_loss->loss_enable_5g == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ max_pwr = get_powerlimit_by_chnum(settx_param.chan, r_idx, settx_param.bw); ++ if (settx_param.chan >= 36) { ++ if (txpwr_loss->loss_enable_5g == 1) ++ max_pwr -= txpwr_loss->loss_value_5g; ++ } else { ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ max_pwr -= txpwr_loss->loss_value_2g4; ++ } ++ ++ if (!set_p || (lvl_pwr == 255)) { ++ settx_param.max_pwr = max_pwr; ++ AICWFDBG(LOGINFO, "max_pwr:%d\n", settx_param.max_pwr); ++ } else ++ AICWFDBG(LOGINFO, "the specified power is input without power limit\n"); ++#endif ++ ++ if (set_p && (lvl_pwr != 255)) ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, 4, buf, &cfm); ++ ++ rwnx_send_rftest_req(rwnx_hw, SET_TX, sizeof(cmd_rf_settx_t), (u8_l *)&settx_param, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_txstop (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_TXSTOP, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_rx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_rx_t setrx_param; ++ ++ if (argc < 3) { ++ return -EINVAL; ++ } ++ setrx_param.chan = command_strtoul(argv[1], NULL, 10); ++ setrx_param.bw = command_strtoul(argv[2], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_RX, sizeof(cmd_rf_rx_t), (u8_l *)&setrx_param, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_rx_result (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, GET_RX_RESULT, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ return 8; ++} ++ ++static int aic_priv_cmd_set_rxstop (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_RXSTOP, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_tx_tone (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ u8_l buf[2]; ++ s8_l freq_ = 0; ++ ++ AICWFDBG(LOGINFO, "%s argc:%d\n", argv[0], argc); ++ if ((argc == 2) || (argc == 3)) { ++ AICWFDBG(LOGINFO, "argv 1:%s\n",argv[1]); ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ if (argc == 3) { ++ AICWFDBG(LOGINFO, "argv 2:%s\n",argv[2]); ++ freq_ = (u8_l)command_strtoul(argv[2], NULL, 10); ++ } else { ++ freq_ = 0; ++ }; ++ buf[0] = func; ++ buf[1] = (u8_l)freq_; ++ rwnx_send_rftest_req(rwnx_hw, SET_TXTONE, argc - 1, buf, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_rx_meter (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ s8_l freq = 0; ++ ++ freq = (int)command_strtoul(argv[1], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_RX_METER, sizeof(freq), (u8_l *)&freq, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_set_power (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l ana_pwr; ++ u8_l dig_pwr; ++ u8_l pwr; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (dev->chipid == PRODUCT_ID_AIC8801) { ++ ana_pwr = command_strtoul(argv[1], NULL, 16); ++ dig_pwr = command_strtoul(argv[2], NULL, 16); ++ pwr = (ana_pwr << 4 | dig_pwr); ++ if (ana_pwr > 0xf || dig_pwr > 0xf) ++ return -EINVAL; ++ } else { ++ ana_pwr = command_strtoul(argv[1], NULL, 10); ++ pwr = ana_pwr; ++ if (ana_pwr > 0x1e) ++ return -EINVAL; ++ } ++ AICWFDBG(LOGINFO, "pwr =%x\r\n", pwr); ++ rwnx_send_rftest_req(rwnx_hw, SET_POWER, sizeof(pwr), (u8_l *)&pwr, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_xtal_cap (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l xtal_cap; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ xtal_cap = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "xtal_cap =%x\r\n", xtal_cap); ++ rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap), (u8_l *)&xtal_cap, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_xtal_cap_fine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l xtal_cap_fine; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ xtal_cap_fine = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "xtal_cap_fine =%x\r\n", xtal_cap_fine); ++ rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP_FINE, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_get_efuse_block (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_getefuse_t getefuse_param; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ getefuse_param.block = command_strtoul(argv[1], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, GET_EFUSE_BLOCK, sizeof(cmd_rf_getefuse_t), (u8_l *)&getefuse_param, &cfm); ++ AICWFDBG(LOGINFO, "get val=%x\r\n", cfm.rftest_result[0]); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_setfreq_t cmd_setfreq; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); ++ rwnx_send_rftest_req(rwnx_hw, SET_FREQ_CAL, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_freq_cal_fine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_setfreq_t cmd_setfreq; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); ++ rwnx_send_rftest_req(rwnx_hw, SET_FREQ_CAL_FINE, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_get_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u32_l val; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_FREQ_CAL, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ val = cfm.rftest_result[0]; ++ if (dev->chipid != PRODUCT_ID_AIC8801) { ++ AICWFDBG(LOGINFO, "cap=0x%x (remain:%x), cap_fine=%x (remain:%x)\n", ++ val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff); ++ } else { ++ AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", val & 0xff, (val >> 8) & 0xff); ++ } ++ return 4; ++} ++ ++static int aic_priv_cmd_set_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l mac_addr[6]; ++ ++ if (argc < 7) ++ return -EINVAL; ++ ++ mac_addr[5] = command_strtoul(argv[1], NULL, 16); ++ mac_addr[4] = command_strtoul(argv[2], NULL, 16); ++ mac_addr[3] = command_strtoul(argv[3], NULL, 16); ++ mac_addr[2] = command_strtoul(argv[4], NULL, 16); ++ mac_addr[1] = command_strtoul(argv[5], NULL, 16); ++ mac_addr[0] = command_strtoul(argv[6], NULL, 16); ++ AICWFDBG(LOGINFO, "set macaddr:%x,%x,%x,%x,%x,%x\n", mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); ++ rwnx_send_rftest_req(rwnx_hw, SET_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u32_l addr0, addr1; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_MAC_ADDR, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ addr0 = cfm.rftest_result[0]; ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ int rem_cnt = (cfm.rftest_result[1] >> 16) & 0x00FF; ++ addr1 = cfm.rftest_result[1] & 0x0000FFFF; ++ AICWFDBG(LOGINFO, "0x%x,0x%x (remain:%x)\n", addr0, addr1, rem_cnt); ++ } else { ++ addr1 = cfm.rftest_result[1]; ++ AICWFDBG(LOGINFO, "0x%x,0x%x\n", addr0, addr1); ++ } ++ return 8; ++} ++ ++static int aic_priv_cmd_set_bt_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l mac_addr[6]; ++ ++ if (argc < 7) ++ return -EINVAL; ++ ++ mac_addr[5] = command_strtoul(argv[1], NULL, 16); ++ mac_addr[4] = command_strtoul(argv[2], NULL, 16); ++ mac_addr[3] = command_strtoul(argv[3], NULL, 16); ++ mac_addr[2] = command_strtoul(argv[4], NULL, 16); ++ mac_addr[1] = command_strtoul(argv[5], NULL, 16); ++ mac_addr[0] = command_strtoul(argv[6], NULL, 16); ++ AICWFDBG(LOGINFO, "set bt macaddr:%x,%x,%x,%x,%x,%x\n", mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); ++ rwnx_send_rftest_req(rwnx_hw, SET_BT_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_bt_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u32_l addr0, addr1; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_BT_MAC_ADDR, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ addr0 = cfm.rftest_result[0]; ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ int rem_cnt = (cfm.rftest_result[1] >> 16) & 0x00FF; ++ addr1 = cfm.rftest_result[1] & 0x0000FFFF; ++ AICWFDBG(LOGINFO, "0x%x,0x%x (remain:%x)\n", addr0, addr1, rem_cnt); ++ } else { ++ addr1 = cfm.rftest_result[1]; ++ AICWFDBG(LOGINFO, "0x%x,0x%x\n", addr0, addr1); ++ } ++ return 8; ++} ++ ++static int aic_priv_cmd_set_vendor_info (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l vendor_info; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ vendor_info = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "set vendor info:%x\n", vendor_info); ++ rwnx_send_rftest_req(rwnx_hw, SET_VENDOR_INFO, 1, &vendor_info, &cfm); ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ memcpy(command, &cfm.rftest_result[0], 2); ++ return 2; ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 1); ++ return 1; ++ } ++ AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); ++} ++ ++static int aic_priv_cmd_get_vendor_info (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_VENDOR_INFO, 0, NULL, &cfm); ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ memcpy(command, &cfm.rftest_result[0], 2); ++ return 2; ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 1); ++ return 1; ++ } ++ AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); ++} ++ ++static int aic_priv_cmd_rdwr_pwrmm (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ if (argc <= 1) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRMM, 0, NULL, &cfm); ++ } else { // write ++ u8_l pwrmm = (u8_l)command_strtoul(argv[1], NULL, 16); ++ pwrmm = (pwrmm) ? 1 : 0; ++ AICWFDBG(LOGINFO, "set pwrmm = %x\r\n", pwrmm); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRMM, sizeof(pwrmm), (u8_l *)&pwrmm, &cfm); ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_pwridx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (dev->chipid != PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ return -EINVAL; ++ } ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRIDX, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr idx ++ if (argc > 3) { ++ u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l pwridx = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, type, pwridx}; ++ AICWFDBG(LOGINFO, "set pwridx:[%x][%x]=%x\r\n", func, type, pwridx); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRIDX, sizeof(buf), buf, &cfm); ++ } else { ++ return -EINVAL; ++ } ++ } else { ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 9); ++ return 9; ++} ++ ++static int aic_priv_cmd_rdwr_pwrlvl (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (dev->chipid == PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ return -EINVAL; ++ } ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr lvl ++ if (argc > 4) { ++ u8_l grp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l idx, size; ++ u8_l buf[14] = {func, grp,}; ++ if (argc > 12) { // set all grp ++ AICWFDBG(LOGINFO, "set pwrlvl %s:\n" ++ " [%x] =", (func == 1) ? "2.4g" : "5g", grp); ++ if (grp == 1) { // TXPWR_LVL_GRP_11N_11AC ++ size = 10; ++ } else { ++ size = 12; ++ } ++ for (idx = 0; idx < size; idx++) { ++ s8_l pwrlvl = (s8_l)command_strtoul(argv[3 + idx], NULL, 10); ++ buf[2 + idx] = (u8_l)pwrlvl; ++ if (idx && !(idx & 0x3)) { ++ AICWFDBG(LOGINFO, " "); ++ } ++ AICWFDBG(LOGINFO, " %2d", pwrlvl); ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ size += 2; ++ } else { // set grp[idx] ++ u8_l idx = (u8_l)command_strtoul(argv[3], NULL, 10); ++ s8_l pwrlvl = (s8_l)command_strtoul(argv[4], NULL, 10); ++ buf[2] = idx; ++ buf[3] = (u8_l)pwrlvl; ++ size = 4; ++ AICWFDBG(LOGINFO, "set pwrlvl %s:\n" ++ " [%x][%d] = %d\n", (func == 1) ? "2.4g" : "5g", grp, idx, pwrlvl); ++ } ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, size, buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ if(dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ memcpy(command, &cfm.rftest_result[0], 6 * 12); ++ return (6 * 12); ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 3 * 12); ++ return (3 * 12); ++ } ++} ++ ++static int aic_priv_cmd_rdwr_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ int res_len = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, 0, NULL, &cfm); ++ } else if (func <= 4) { // write 2.4g/5g pwr ofst and ant0/1 ++ if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); ++ u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); ++ } else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D80) && (dev->chipid != PRODUCT_ID_AIC8800D80X2)) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); ++ } else { ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { // 3 = 3 (2.4g) ++ res_len = 3; ++ } else if (dev->chipid == PRODUCT_ID_AIC8800D80) { // 3 * 2 (2.4g) + 3 * 6 (5g) ++ res_len = 3 * 3 + 3 * 6; ++ } else if (dev->chipid == PRODUCT_ID_AIC8800D80X2) { // ant0/1 ++ res_len = ( 3 * 3 + 3 * 6 ) * 2; ++ } else { ++ res_len = 3 + 4; ++ } ++ memcpy(command, &cfm.rftest_result[0], res_len); ++ return res_len; ++} ++ ++static int aic_priv_cmd_rdwr_pwrofstfine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr ofst ++ if (argc > 3) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ ++ } ++ memcpy(command, &cfm.rftest_result[0], 7); ++ return 7; ++} ++ ++static int aic_priv_cmd_rdwr_drvibit (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_DRVIBIT, 0, NULL, &cfm); ++ } else if (func == 1) { // write 2.4g pa drv_ibit ++ if (argc > 2) { ++ u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[2] = {func, ibit}; ++ AICWFDBG(LOGINFO, "set drvibit:[%x]=%x\r\n", func, ibit); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_DRVIBIT, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 16); ++ return 16; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ int res_len = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, 0, NULL, &cfm); ++ } else if (func <= 4) { // write 2.4g/5g pwr ofst and ant0/1 ++ if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); ++ u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set efuse pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); ++ } else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D80) && (dev->chipid != PRODUCT_ID_AIC8800D80X2)) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set efuse pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { // 6 = 3 (2.4g) * 2 ++ res_len = 3 * 2; ++ } else if (dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2) { // 3 * 2 (2.4g) + 3 * 6 (5g) ++ res_len = (3 * 3 + 3 * 6) * 2; ++ } else { // 7 = 3(2.4g) + 4(5g) ++ res_len = 3 + 4; ++ } ++ memcpy(command, &cfm.rftest_result[0], res_len); ++ return res_len; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_pwrofstfine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr ofst ++ if (argc > 3) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 7); ++ return 7; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_drvibit (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_DRVIBIT, 0, NULL, &cfm); ++ } else if (func == 1) { // write 2.4g pa drv_ibit ++ if (argc > 2) { ++ u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[2] = {func, ibit}; ++ AICWFDBG(LOGINFO, "set efuse drvibit:[%x]=%x\r\n", func, ibit); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_DRVIBIT, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_usrdata (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_ef_usrdata_t cmd_ef_usrdata; ++ ++ if (argc <= 1) { // read all ++ cmd_ef_usrdata.func = 0; ++ cmd_ef_usrdata.cnt = 3; ++ } else if (argc >= 2) { // read/write ++ cmd_ef_usrdata.func = (u8_l)command_strtoul(argv[1], NULL, 10); ++ cmd_ef_usrdata.cnt = (u8_l)command_strtoul(argv[2], NULL, 10); ++ if (cmd_ef_usrdata.func == 1) { ++ int idx; ++ for (idx = 0; idx < cmd_ef_usrdata.cnt; idx++) { ++ cmd_ef_usrdata.usrdata[idx] = (u32_l)command_strtoul(argv[3 + idx], NULL, 16); ++ } ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong argc: %x\n", argc); ++ return -EINVAL; ++ } ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USRDATA, sizeof(cmd_ef_usrdata), (u8_l *)&cmd_ef_usrdata, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 12); ++ return 12; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_sdiocfg (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_SDIOCFG, 0, NULL, &cfm); ++ } else if (func == 1) { // write sdiocfg ++ if (argc > 2) { ++ u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[2] = {func, ibit}; ++ AICWFDBG(LOGINFO, "set efuse sdiocfg:[%x]=%x\r\n", func, ibit); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_SDIOCFG, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_usbvidpid (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ AICWFDBG(LOGINFO, "read/write usb vid/pid into efuse\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USBVIDPID, 0, NULL, &cfm); ++ } else if (func == 1) { // write USB vid+pid ++ if (argc > 2) { ++ u32_l usb_id = (u32_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[5] = {func, (u8_l)usb_id, (u8_l)(usb_id >> 8), (u8_l)(usb_id >> 16), (u8_l)(usb_id >> 24)}; ++ AICWFDBG(LOGINFO, "set efuse usb vid/pid:[%x]=%x\r\n", func, usb_id); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USBVIDPID, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_he_off (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set he off: %d\n", func); ++ if(func == 1 || func == 0) { ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_HE_OFF, sizeof(func), (u8_l *)&func, &cfm); ++ AICWFDBG(LOGINFO, "he_off cfm: %d\n", cfm.rftest_result[0]); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_cal_xtal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_CAL_XTAL, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_cal_xtal_res (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, GET_CAL_XTAL_RES, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", cfm.rftest_result[0] & 0x0000ffff, (cfm.rftest_result[0] >> 16) & 0x0000ffff); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_cob_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_setcobcal_t setcob_cal; ++ ++ if (argc < 3) ++ return -EINVAL; ++ setcob_cal.dutid = command_strtoul(argv[1], NULL, 10); ++ setcob_cal.chip_num = command_strtoul(argv[2], NULL, 10); ++ setcob_cal.dis_xtal = command_strtoul(argv[3], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_cob_cal_res (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l state; ++ cob_result_ptr_t *cob_result_ptr; ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); ++ state = (cfm.rftest_result[0] >> 16) & 0x000000ff; ++ if (!state){ ++ AICWFDBG(LOGINFO, "cap= 0x%x, cap_fine= 0x%x, freq_ofst= %d Hz\n", ++ cfm.rftest_result[0] & 0x000000ff, (cfm.rftest_result[0] >> 8) & 0x000000ff, cfm.rftest_result[1]); ++ cob_result_ptr = (cob_result_ptr_t *) & (cfm.rftest_result[2]); ++ AICWFDBG(LOGINFO, "golden_rcv_dut= %d , tx_rssi= %d dBm, snr = %d dB\ndut_rcv_godlden= %d , rx_rssi= %d dBm", ++ cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, ++ cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static); ++ memcpy(command, &cfm.rftest_result, 16); ++ return 16; ++ } else { ++ AICWFDBG(LOGERROR, "cob not idle\n"); ++ return -EINVAL; ++ } ++} ++ ++static int aic_priv_cmd_do_cob_test (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l state; ++ cmd_rf_setcobcal_t setcob_cal; ++ cob_result_ptr_t *cob_result_ptr; ++ ++ setcob_cal.dutid = 1; ++ setcob_cal.chip_num = 1; ++ setcob_cal.dis_xtal = 0; ++ if (argc > 1) ++ setcob_cal.dis_xtal = command_strtoul(argv[1], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); ++ msleep(2000); ++ rwnx_send_rftest_req(rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); ++ state = (cfm.rftest_result[0] >> 16) & 0x000000ff; ++ if (!state){ ++ AICWFDBG(LOGINFO, "cap= 0x%x, cap_fine= 0x%x, freq_ofst= %d Hz\n", ++ cfm.rftest_result[0] & 0x000000ff, (cfm.rftest_result[0] >> 8) & 0x000000ff, cfm.rftest_result[1]); ++ cob_result_ptr = (cob_result_ptr_t *) & (cfm.rftest_result[2]); ++ AICWFDBG(LOGINFO, "golden_rcv_dut= %d , tx_rssi= %d dBm, snr = %d dB\ndut_rcv_godlden= %d , rx_rssi= %d dBm", ++ cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, ++ cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static); ++ memcpy(command, &cfm.rftest_result, 16); ++ return 16; ++ } else { ++ AICWFDBG(LOGERROR, "cob not idle\n"); ++ return -EINVAL; ++ } ++} ++ ++static int aic_priv_cmd_set_papr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "papr %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_PAPR, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_notch (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "notch %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_NOTCH, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_srrc (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "srrc %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_SRRC, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_fss (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "fss %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_FSS, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_usb_off (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_USB_OFF, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_pll_test (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0, tx_pwr = 0xc; ++ s8_l freq = 0; ++ ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 16); ++ } ++ if (argc > 3) { ++ freq = (s8_l)command_strtoul(argv[2], NULL, 10); ++ tx_pwr = command_strtoul(argv[3], NULL, 16); ++ } ++ if (func <= 1) { ++ u8_l buf[3] = {func, (u8_l)freq, tx_pwr}; ++ AICWFDBG(LOGINFO, "set pll_test %d: freq=%d, tx_pwr=0x%x\n", func, freq, tx_pwr); ++ rwnx_send_rftest_req(rwnx_hw, SET_PLL_TEST, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_get_txpwr(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ s8_l power=0; ++ power = get_txpwr_max(power); ++ memcpy(command, &power, 1); ++ return 1; ++} ++ ++static int aic_priv_cmd_set_txpwr_loss(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ s8_l func; ++ if (argc > 1) { ++ func = (s8_l)command_strtoul(argv[1], NULL, 10); ++ printk("set txpwr loss: %d\n", func); ++ if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ set_txpwr_loss_ofst(func); ++ rwnx_send_txpwr_lvl_v3_req(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ set_txpwr_loss_ofst(func); ++ rwnx_send_txpwr_lvl_v4_req(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ set_txpwr_loss_ofst(func); ++ rwnx_send_txpwr_lvl_req(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else{ ++ AICWFDBG(LOGINFO,"error:don't support 8800D"); ++ } ++ } else { ++ printk("wrong args\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_ant_mode (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "ant %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_ANT_MODE, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_rdwr_bt_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc == 1) { ++ func = 0; ++ } else if (argc == 2) { ++ func = 1; ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_BT_EFUSE_PWROFST, 0, NULL, &cfm); ++ } else if (func == 1) { // write bt tx pwrofst ++ int8_t bt_txpwrofst = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set bt efuse pwrofst %d\r\n",bt_txpwrofst); ++ if (bt_txpwrofst < -7 || bt_txpwrofst > 7) { ++ AICWFDBG(LOGERROR, "wrong params %d, pwrofst limit -7 ~ 7\n", bt_txpwrofst); ++ return -EINVAL; ++ } else { ++ rwnx_send_rftest_req(rwnx_hw, RDWR_BT_EFUSE_PWROFST, sizeof(bt_txpwrofst), &bt_txpwrofst, &cfm); ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 2); ++ return 2; ++} ++ ++static int aic_priv_cmd_country_set(struct rwnx_hw *rwnx_hw, int argc, ++ char *argv[], char *command) ++{ ++ int ret = 0; ++ struct ieee80211_regdomain *regdomain; ++ ++ if (argc < 2) { ++ AICWFDBG(LOGINFO, "%s param err\n", __func__); ++ return -1; ++ } ++ ++ AICWFDBG(LOGINFO, "cmd country_set: %s\n", argv[1]); ++ ++ regdomain = getRegdomainFromRwnxDB(rwnx_hw->wiphy, argv[1]); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ ret = regulatory_set_wiphy_regd( ++ rwnx_hw->wiphy, regdomain); ++#else ++ ret = wiphy_apply_custom_regulatory( ++ rwnx_hw->wiphy, regdomain); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */ ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ rwnx_radar_set_domain(&rwnx_hw->radar, regdomain->dfs_region); ++#endif ++ ++#ifdef CONFIG_POWER_LIMIT ++ if (!testmode){ ++ rwnx_send_me_chan_config_req(rwnx_hw, argv[1]); ++ } ++#endif ++ ++ return ret; ++} ++ ++static int aic_priv_cmd_help (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ print_help(argc > 0 ? argv[0] : NULL); ++ return 0; ++} ++ ++struct aic_priv_cmd { ++ const char *cmd; ++ int (*handler)(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command); ++ const char *usage; ++}; ++ ++static const struct aic_priv_cmd aic_priv_commands[] = { ++ { "set_tx", aic_priv_cmd_set_tx, ++ " " }, ++ { "set_txstop", aic_priv_cmd_set_txstop, ++ "= stop tx " }, ++ { "set_rx", aic_priv_cmd_set_rx, ++ " " }, ++ { "get_rx_result", aic_priv_cmd_get_rx_result, ++ "= display rx fcsok/total pkt num" }, ++ { "set_rxstop", aic_priv_cmd_set_rxstop, ++ "= stop rx " }, ++ { "set_txtone", aic_priv_cmd_set_tx_tone, ++ " val = 0/off" }, ++ { "set_rx_meter", aic_priv_cmd_set_rx_meter, ++ "= set rx meter " }, ++ { "set_power", aic_priv_cmd_set_set_power, ++ " " }, ++ { "set_xtal_cap", aic_priv_cmd_set_xtal_cap, ++ " [0 ~ 31]" }, ++ { "set_xtal_cap_fine", aic_priv_cmd_set_xtal_cap_fine, ++ " [0 ~ 63]" }, ++ { "get_efuse_block", aic_priv_cmd_get_efuse_block, ++ "" }, ++ { "set_freq_cal", aic_priv_cmd_set_freq_cal, ++ "" }, ++ { "set_freq_cal_fine", aic_priv_cmd_set_freq_cal_fine, ++ "" }, ++ { "get_freq_cal", aic_priv_cmd_get_freq_cal, ++ "= display cap & cap fine" }, ++ { "set_mac_addr", aic_priv_cmd_set_mac_addr, ++ "= write WiFi MAC into efuse or flash is limited to a maximum of two times" }, ++ { "get_mac_addr", aic_priv_cmd_get_mac_addr, ++ "= display WiFi MAC stored in efuse or flash" }, ++ { "set_bt_mac_addr", aic_priv_cmd_set_bt_mac_addr, ++ "= write BT MAC into efuse or flash is limited to a maximum of two times" }, ++ { "get_bt_mac_addr", aic_priv_cmd_get_bt_mac_addr, ++ "= display BT MAC stored in efuse or flash" }, ++ { "set_vendor_info", aic_priv_cmd_set_vendor_info, ++ "= write vendor info into efuse or flash is allowed only once" }, ++ { "get_vendor_info", aic_priv_cmd_get_vendor_info, ++ "= display vendor info stored in efuse or flash" }, ++ { "rdwr_pwrmm", aic_priv_cmd_rdwr_pwrmm, ++ " = 0/rdwr_pwrlvl, 1/set_power = read/write txpwr manul mode" }, ++ { "rdwr_pwridx", aic_priv_cmd_rdwr_pwridx, ++ " " }, ++ { "rdwr_pwrlvl", aic_priv_cmd_rdwr_pwrlvl, ++ " " }, ++ { "rdwr_pwrofst", aic_priv_cmd_rdwr_pwrofst, ++ " " }, ++ { "rdwr_pwrofstfine", aic_priv_cmd_rdwr_pwrofstfine, ++ " " }, ++ { "rdwr_drvibit", aic_priv_cmd_rdwr_drvibit, ++ " read/write 8800D pa drvibit" }, ++ { "set_cal_xtal", aic_priv_cmd_set_cal_xtal, ++ "= set cal xtal" }, ++ { "get_cal_xtal_res", aic_priv_cmd_get_cal_xtal_res, ++ "= get cal xtal result cap & cap_fine" }, ++ { "set_cob_cal", aic_priv_cmd_set_cob_cal, ++ " = dut cob test" }, ++ { "get_cob_cal_res", aic_priv_cmd_get_cob_cal_res, ++ "= get cob cal result" }, ++ { "do_cob_test", aic_priv_cmd_do_cob_test, ++ " = 0/xtal, 1/dis_xtal, 2/only_xtal" }, ++ { "rdwr_efuse_pwrofst", aic_priv_cmd_rdwr_efuse_pwrofst, ++ " limited to a maximum of two times" }, ++ { "rdwr_efuse_pwrofstfine", aic_priv_cmd_rdwr_efuse_pwrofstfine, ++ " limited to a maximum of two times" }, ++ { "rdwr_efuse_drvibit", aic_priv_cmd_rdwr_efuse_drvibit, ++ " = read/write 8800D efuse pa drvibitis allowed only once" }, ++ { "rdwr_efuse_usrdata", aic_priv_cmd_rdwr_efuse_usrdata, ++ " = read/write efuse usrdata" }, ++ { "rdwr_efuse_sdiocfg", aic_priv_cmd_rdwr_efuse_sdiocfg, ++ " = read/write sdiocfg_bit into efuse" }, ++ { "rdwr_efuse_usbvidpid", aic_priv_cmd_rdwr_efuse_usbvidpid, ++ " = read/write usb vid/pid into efuse" }, ++ { "rdwr_efuse_he_off", aic_priv_cmd_rdwr_efuse_he_off, ++ " = read/write he_off into efuse" }, ++ { "set_papr", aic_priv_cmd_set_papr, ++ " = configure papr filter to optimize sideband suppression" }, ++ { "set_notch", aic_priv_cmd_set_notch, ++ " = configure filter to optimize sideband suppression" }, ++ { "set_srrc", aic_priv_cmd_set_srrc, ++ " = disable/enable sideband suppression for SRRC" }, ++ { "set_fss", aic_priv_cmd_set_fss, ++ " = disable/enable treatment of spurious emissions and burrs" }, ++ { "set_usb_off", aic_priv_cmd_set_usb_off, ++ "= off usb configure before usb disconnect" }, ++ { "set_pll_test", aic_priv_cmd_set_pll_test, ++ " = use pll test to measure saturation power" }, ++ { "get_txpwr", aic_priv_cmd_get_txpwr, ++ "= get userconfig max txpwr" }, ++ { "set_txpwr_loss",aic_priv_cmd_set_txpwr_loss, ++ " = txpwr will change ,val can be negative" }, ++ { "set_ant", aic_priv_cmd_set_ant_mode, ++ " = 0/ant0, 1/ant1, 2/both" }, ++ { "rdwr_bt_efuse_pwrofst", aic_priv_cmd_rdwr_bt_efuse_pwrofst, ++ " = read/write bt tx power offset into efuse" }, ++ {"country_set", aic_priv_cmd_country_set, ""}, ++//Reserve for new aic_priv_cmd. ++ { "help", aic_priv_cmd_help, ++ "= show usage help" }, ++ { NULL, NULL, NULL } ++ ++}; ++ ++ ++/* ++ * Prints command usage, lines are padded with the specified string. ++ */ ++static void print_help(const char *cmd) ++{ ++ int n; ++ printk("commands:\n"); ++ for (n = 0; aic_priv_commands[n].cmd; n++) { ++ if (cmd != NULL) ++ printk("%s %s\n", aic_priv_commands[n].cmd, aic_priv_commands[n].usage); ++ } ++} ++ ++int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len) ++{ ++ const struct aic_priv_cmd *cmd, *match = NULL; ++ int count; ++ int bytes_written = 0; ++ char *argv[CMD_MAXARGS + 1]; ++ int argc; ++ struct rwnx_vif *vif = container_of(net->ieee80211_ptr, struct rwnx_vif, wdev); ++ struct rwnx_hw *p_rwnx_hw = vif->rwnx_hw; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#if 1 ++ if(!testmode) { ++ AICWFDBG(LOGERROR, "not in testmdoe\n"); ++ return -1; ++ } ++#endif ++ argc = parse_line(command, argv); ++ if (argc == 0) { ++ return -1; ++ } ++ ++ count = 0; ++ cmd = aic_priv_commands; ++ while (cmd->cmd) { ++ if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0 && ++ strncasecmp(cmd->cmd, argv[0], strlen(cmd->cmd)) == 0) ++ { ++ match = cmd; ++ if (strcasecmp(cmd->cmd, argv[0]) == 0) { ++ /* we have an exact match */ ++ count = 1; ++ break; ++ } ++ count++; ++ } ++ cmd++; ++ } ++ ++ if (count > 1) { ++ AICWFDBG(LOGINFO, "Ambiguous command '%s'; possible commands:", argv[0]); ++ cmd = aic_priv_commands; ++ while (cmd->cmd) { ++ if (strncasecmp(cmd->cmd, argv[0], ++ strlen(argv[0])) == 0) { ++ AICWFDBG(LOGINFO, " %s", cmd->cmd); ++ } ++ cmd++; ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ } else if (count == 0) { ++ AICWFDBG(LOGERROR, "Unknown command '%s'\n", argv[0]); ++ } else { ++ AICWFDBG(LOGINFO, "match %s", match->cmd); ++ bytes_written = match->handler(p_rwnx_hw, argc, &argv[0], command); ++ } ++ ++ if (bytes_written < 0) ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ ++ return bytes_written; ++} ++ ++#define RWNX_COUNTRY_CODE_LEN 2 ++#define CMD_SET_COUNTRY "COUNTRY" ++#define CMD_SET_VENDOR_EX_IE "SET_VENDOR_EX_IE" ++#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" ++#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" ++#define CMD_SET_MON_FREQ "SET_MON_FREQ" ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2); ++struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, int index); ++extern int reg_regdb_size; ++ ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++extern u8_l vendor_extension_data[256]; ++extern int vendor_extension_len; ++extern int testmode = 0; ++ ++void set_vendor_extension_ie(char *command){ ++ ++ char databyte[3]={0x00, 0x00, 0x00}; ++ int skip = strlen(CMD_SET_VENDOR_EX_IE) + 1; ++ int command_index = skip; ++ int data_index = 0; ++ ++ memset(vendor_extension_data, 0, 256); ++ vendor_extension_len = 0; ++ memcpy(databyte, command + command_index, 2); ++ vendor_extension_len = command_strtoul(databyte, NULL, 16); ++ printk("%s len:%d \r\n", __func__, vendor_extension_len); ++ ++ //parser command and save data in vendor_extension_data ++ for(data_index = 0;data_index < vendor_extension_len; data_index++){ ++ command_index = command_index + 3; ++ memcpy(databyte, command + command_index, 2); ++ vendor_extension_data[data_index] = command_strtoul(databyte, NULL, 16); ++ } ++ ++} ++#endif//CONFIG_SET_VENDOR_EXTENSION_IE ++int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef); ++int rwnx_atoi2(char *value, int c_len); ++void set_mon_chan(struct rwnx_vif *vif, char *parameter){ ++ struct cfg80211_chan_def *chandef = NULL; ++ int freq = 0; ++ ++ ++ chandef = (struct cfg80211_chan_def *)vmalloc(sizeof(struct cfg80211_chan_def)); ++ memset(chandef, 0, sizeof(struct cfg80211_chan_def)); ++ chandef->chan = (struct ieee80211_channel *)vmalloc(sizeof(struct ieee80211_channel)); ++ memset(chandef->chan, 0, sizeof(struct ieee80211_channel)); ++ ++ freq = rwnx_atoi2(parameter, 4); ++ ++ if(freq <= 2484){ ++ chandef->chan->band = NL80211_BAND_2GHZ; ++ }else{ ++ chandef->chan->band = NL80211_BAND_5GHZ; ++ } ++ chandef->chan->center_freq = freq; ++ chandef->width = NL80211_CHAN_WIDTH_20; ++ chandef->center_freq1 = chandef->chan->center_freq; ++ chandef->center_freq2 = 0; ++ ++ rwnx_cfg80211_set_monitor_channel_(vif->rwnx_hw->wiphy, chandef); ++ ++ vfree(chandef->chan); ++ vfree(chandef); ++ ++} ++ ++ ++int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) ++{ ++#define PRIVATE_COMMAND_MAX_LEN 8192 ++#define PRIVATE_COMMAND_DEF_LEN 4096 ++ ++ struct rwnx_vif *vif = netdev_priv(net); ++ int ret = 0; ++ char *command = NULL; ++ int bytes_written = 0; ++ android_wifi_priv_cmd priv_cmd; ++ int buf_size = 0; ++ int skip = 0; ++ char *country = NULL; ++#ifdef CONFIG_GPIO_WAKEUP ++ int setsusp_mode; ++#endif ++ struct ieee80211_regdomain *regdomain; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ///todo: add our lock ++ //net_os_wake_lock(net); ++ ++ ++/* if (!capable(CAP_NET_ADMIN)) { ++ ret = -EPERM; ++ goto exit; ++ }*/ ++ if (!ifr->ifr_data) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++#ifdef CONFIG_COMPAT ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) ++ if (in_compat_syscall()) ++#else ++ if (is_compat_task()) ++#endif ++ { ++ compat_android_wifi_priv_cmd compat_priv_cmd; ++ if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ 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 /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ } ++ if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { ++ printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); ++ command = kmalloc((buf_size + 1), GFP_KERNEL); ++ ++ if (!command) { ++ printk("%s: failed to allocate memory\n", __FUNCTION__); ++ ret = -ENOMEM; ++ goto exit; ++ } ++ if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ command[priv_cmd.total_len] = '\0'; ++ ++ /* outputs */ ++ AICWFDBG(LOGINFO, "%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); ++ AICWFDBG(LOGINFO, "cmd = %d\n", cmd); ++ AICWFDBG(LOGINFO, "buf_size=%d\n", buf_size); ++ ++#if 1//Handle Android command ++ if(!strncasecmp(command, CMD_SET_COUNTRY, strlen(CMD_SET_COUNTRY)) && ++ strncasecmp(command, "country_set", strlen("country_set"))) { ++ skip = strlen(CMD_SET_COUNTRY) + 1; ++ country = command + skip; ++ if (!country || strlen(country) < RWNX_COUNTRY_CODE_LEN) { ++ printk("%s: invalid country code\n", __func__); ++ ret = -EINVAL; ++ goto exit; ++ } ++#if 0 ++ for(index = 0; index < reg_regdb_size; index++){ ++ regdomain = getRegdomainFromRwnxDBIndex(vif->rwnx_hw->wiphy, index); ++ if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ ++ printk("regulatory_set_wiphy_regd fail \r\n"); ++ }else{ ++ printk("regulatory_set_wiphy_regd ok \r\n"); ++ } ++ } ++#endif ++ AICWFDBG(LOGINFO, "%s country code:%c%c\n", __func__, toupper(country[0]), toupper(country[1])); ++ regdomain = getRegdomainFromRwnxDB(vif->rwnx_hw->wiphy, country); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ ++ printk("regulatory_set_wiphy_regd fail \r\n"); ++ } ++#else ++ wiphy_apply_custom_regulatory(vif->rwnx_hw->wiphy, regdomain); ++#endif ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ rwnx_radar_set_domain(&vif->rwnx_hw->radar, regdomain->dfs_region); ++#endif ++ ++#ifdef CONFIG_POWER_LIMIT ++ if (!testmode) ++ rwnx_send_me_chan_config_req(vif->rwnx_hw, country); ++#endif ++ ret = 0; ++ goto exit; ++ } ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++ else if(!strncasecmp(command, CMD_SET_VENDOR_EX_IE, strlen(CMD_SET_VENDOR_EX_IE))){ ++ set_vendor_extension_ie(command); ++ ret = 0; ++ goto exit; ++ } ++#endif//CONFIG_SET_VENDOR_EXTENSION_IE ++ else if(!strncasecmp(command, CMD_SET_AP_WPS_P2P_IE, strlen(CMD_SET_AP_WPS_P2P_IE))){ ++ ret = 0; ++ goto exit; ++ } ++ else if(!strncasecmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) && testmode == 0){ ++#ifdef AICWF_SDIO_SUPPORT ++#if defined(CONFIG_GPIO_WAKEUP) && !defined(CONFIG_AUTO_POWERSAVE) ++ skip = strlen(CMD_SETSUSPENDMODE) + 1; ++ setsusp_mode = command_strtoul((command + skip), NULL, 10); ++#ifdef AICWF_LATENCY_MODE ++ if (setsusp_mode) ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, setsusp_mode, 0); ++ else ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1, 1); ++#else ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, setsusp_mode, !setsusp_mode); ++#endif ++ #if 0 ++ if (setsusp_mode == 1) { ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); ++#endif ++ ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); ++ } ++ } ++ #endif ++ AICWFDBG(LOGINFO, "set suspend mode %d\n", setsusp_mode); ++#endif//CONFIG_GPIO_WAKEUP ++#endif ++ goto exit; ++ } ++#ifdef CONFIG_RWNX_MON_DATA ++ else if(!strncasecmp(command, CMD_SET_MON_FREQ, strlen(CMD_SET_MON_FREQ))){ ++ char *set_parameter; ++ skip = strlen(CMD_SET_MON_FREQ) + 1; ++ set_parameter = command + skip; ++ set_mon_chan(vif, set_parameter); ++ ret = 0; ++ goto exit; ++ } ++#endif ++ ++#endif//Handle Android command ++ ++ bytes_written = handle_private_cmd(net, command, priv_cmd.total_len); ++ if (bytes_written >= 0) { ++ if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { ++ command[0] = '\0'; ++ } ++ if (bytes_written >= priv_cmd.total_len) { ++ printk("%s: err. bytes_written:%d >= buf_size:%d \n", ++ __FUNCTION__, bytes_written, buf_size); ++ goto exit; ++ } ++ bytes_written++; ++ priv_cmd.used_len = bytes_written; ++ if (copy_to_user(priv_cmd.buf, command, bytes_written)) { ++ printk("%s: failed to copy data to user buffer\n", __FUNCTION__); ++ ret = -EFAULT; ++ } ++ } else { ++ /* Propagate the error */ ++ ret = bytes_written; ++ } ++ ++exit: ++ ///todo: add our unlock ++ //net_os_wake_unlock(net); ++ kfree(command); ++ return ret; ++} ++ ++#ifdef CONFIG_MCU_MESSAGE ++#define CMD_GET_VERSION_STR "GET_VERSION" ++#define CMD_GET_SSID_STR "GET_SSID" ++#define CMD_SET_SSID_STR "SET_SSID" ++#define CMD_GET_PASS_STR "GET_PASS" ++#define CMD_SET_PASS_STR "SET_PASS" ++#define CMD_GET_VAR_STR "GET_VAR" ++#define CMD_SET_VAR_STR "SET_VAR" ++ ++enum custmsg_cmd_tag ++{ ++ CUST_CMD_GET_VERSION = 0, ++ CUST_CMD_GET_SSID, ++ CUST_CMD_SET_SSID, ++ CUST_CMD_GET_PASS, ++ CUST_CMD_SET_PASS, ++ CUST_CMD_GET_VAR, ++ CUST_CMD_SET_VAR, ++ CUST_CMD_MAX ++}; ++ ++int handle_custom_msg(char *command, u32 cmd_len) ++{ ++ int bytes_read = 0, max_bytes_to_read = 0; ++ struct rwnx_hw *p_rwnx_hw = NULL; ++ u32 cmd, len = 0, flags = 0; ++ char *buf = NULL; ++ struct dbg_custom_msg_cfm *cust_msg_cfm; ++ printk("cmd,%s,%ld\n",command,strlen(command)); ++ if (strncasecmp(command, CMD_GET_VERSION_STR, strlen(CMD_GET_VERSION_STR)) == 0) { ++ cmd = CUST_CMD_GET_VERSION; ++ max_bytes_to_read = 32; // max str len for version ++ } else if (strncasecmp(command, CMD_GET_SSID_STR, strlen(CMD_GET_SSID_STR)) == 0) { ++ cmd = CUST_CMD_GET_SSID; ++ max_bytes_to_read = 48; // max str len for ssid ++ } else if (strncasecmp(command, CMD_SET_SSID_STR, strlen(CMD_SET_SSID_STR)) == 0) { ++ cmd = CUST_CMD_SET_SSID; ++ len = cmd_len - (strlen(CMD_SET_SSID_STR) + 1); ++ buf = command + (strlen(CMD_SET_SSID_STR) + 1); ++ max_bytes_to_read = 0; ++ } else if (strncasecmp(command, CMD_GET_PASS_STR, strlen(CMD_GET_PASS_STR)) == 0) { ++ cmd = CUST_CMD_GET_PASS; ++ max_bytes_to_read = 64; // max str len for PASS ++ } else if (strncasecmp(command, CMD_SET_PASS_STR, strlen(CMD_SET_PASS_STR)) == 0) { ++ cmd = CUST_CMD_SET_PASS; ++ len = cmd_len - (strlen(CMD_SET_PASS_STR) + 1); ++ buf = command + (strlen(CMD_SET_PASS_STR) + 1); ++ max_bytes_to_read = 0; ++ } else if (strncasecmp(command, CMD_GET_VAR_STR, strlen(CMD_GET_VAR_STR)) == 0) { ++ cmd = CUST_CMD_GET_VAR; ++ max_bytes_to_read = 64; // max str len for VAR ++ } else if (strncasecmp(command, CMD_SET_VAR_STR, strlen(CMD_SET_VAR_STR)) == 0) { ++ cmd = CUST_CMD_SET_VAR; ++ len = cmd_len - (strlen(CMD_SET_VAR_STR) + 1); ++ buf = command + (strlen(CMD_SET_VAR_STR) + 1); ++ max_bytes_to_read = 0; ++ } else { ++ printk("invalid cmd: %s\r\n", command); ++ return -1; ++ } ++ if (len < 0) { ++ printk("invalid len: %d\r\n", len); ++ return -3; ++ } ++ #ifdef AICWF_SDIO_SUPPORT ++ p_rwnx_hw = g_rwnx_plat->sdiodev->rwnx_hw; ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ p_rwnx_hw = g_rwnx_plat->usbdev->rwnx_hw; ++ #endif ++ cust_msg_cfm = (struct dbg_custom_msg_cfm *)kmalloc((offsetof(struct dbg_custom_msg_cfm, buf) + max_bytes_to_read), GFP_KERNEL); ++ if (cust_msg_cfm == NULL) { ++ printk("msg cfm alloc fail\r\n"); ++ return -2; ++ } ++ rwnx_send_dbg_custom_msg_req(p_rwnx_hw, cmd, buf, len, flags, cust_msg_cfm); ++ bytes_read = cust_msg_cfm->len; ++ printk("Custom msg cfm: cmd=%d, len=%d, status=%x\n", cust_msg_cfm->cmd, bytes_read, cust_msg_cfm->status); ++ if (bytes_read) { ++ memcpy(command, cust_msg_cfm->buf, bytes_read); ++ command[bytes_read] = '\0'; ++ } else { ++ command[0] = '\0'; ++ } ++ if (cust_msg_cfm->status) { ++ printk("cfm status: %x", cust_msg_cfm->status); ++ } ++ return bytes_read; ++} ++ ++int devipc_cust_msg(struct net_device *net, struct ifreq *ifr, int cmd) ++{ ++#ifdef PRIVATE_COMMAND_MAX_LEN ++#undef PRIVATE_COMMAND_MAX_LEN ++#undef PRIVATE_COMMAND_DEF_LEN ++#define PRIVATE_COMMAND_MAX_LEN 8192 ++#define PRIVATE_COMMAND_DEF_LEN 4096 ++#endif ++ int ret = 0; ++ char *command = NULL; ++ int bytes_written = 0; ++ android_wifi_priv_cmd priv_cmd; ++ int buf_size = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ///todo: add our lock ++ //net_os_wake_lock(net); ++ ++ ++/* if (!capable(CAP_NET_ADMIN)) { ++ ret = -EPERM; ++ goto exit; ++ }*/ ++ if (!ifr->ifr_data) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++#ifdef CONFIG_COMPAT ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) ++ if (in_compat_syscall()) ++#else ++ if (is_compat_task()) ++#endif ++ { ++ compat_android_wifi_priv_cmd compat_priv_cmd; ++ if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ 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 /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ } ++ if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { ++ printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); ++ command = kmalloc((buf_size + 1), GFP_KERNEL); ++ ++ if (!command) ++ { ++ printk("%s: failed to allocate memory\n", __FUNCTION__); ++ ret = -ENOMEM; ++ goto exit; ++ } ++ if (copy_from_user(command, priv_cmd.buf, priv_cmd.used_len)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ command[priv_cmd.used_len] = '\0'; ++ ++ /* outputs */ ++ printk("%s: Devipc custom msg \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); ++ printk("cmd = %x\n", cmd); ++ printk("buf_size=%d\n", buf_size); ++ ++ ++ bytes_written = handle_custom_msg(command, priv_cmd.used_len); ++ if (bytes_written >= 0) { ++ if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { ++ command[0] = '\0'; ++ } ++ if (bytes_written >= priv_cmd.total_len) { ++ printk("%s: err. bytes_written:%d >= buf_size:%d \n", ++ __FUNCTION__, bytes_written, buf_size); ++ goto exit; ++ } ++ bytes_written++; ++ priv_cmd.used_len = bytes_written; ++ if (copy_to_user(priv_cmd.buf, command, bytes_written)) { ++ printk("%s: failed to copy data to user buffer\n", __FUNCTION__); ++ ret = -EFAULT; ++ } ++ } ++ else { ++ /* Propagate the error */ ++ ret = bytes_written; ++ } ++ ++exit: ++ ///todo: add our unlock ++ //net_os_wake_unlock(net); ++ kfree(command); ++ Sreturn ret; ++} ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.h +new file mode 100644 +index 000000000000..265658ed1053 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.h +@@ -0,0 +1,33 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file private_cmd.h ++ * ++ * Copyright (C) Aicsemi 2018-2024 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _AIC_PRIV_CMD_H_ ++#define _AIC_PRIV_CMD_H_ ++ ++#include "rwnx_defs.h" ++ ++typedef struct _android_wifi_priv_cmd { ++ char *buf; ++ int used_len; ++ int total_len; ++} android_wifi_priv_cmd; ++ ++#ifdef CONFIG_COMPAT ++typedef struct _compat_android_wifi_priv_cmd { ++ compat_caddr_t buf; ++ int used_len; ++ int total_len; ++} compat_android_wifi_priv_cmd; ++#endif /* CONFIG_COMPAT */ ++ ++int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd); ++ ++#endif /* _AIC_PRIV_CMD_H_ */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c +new file mode 100644 +index 000000000000..004a1a3cfdc9 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c +@@ -0,0 +1,1247 @@ ++#include "aic_vendor.h" ++#include "rwnx_defs.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_version_gen.h" ++#include "rwnx_msg_tx.h" ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ ++static struct wifi_ring_buffer_status ring_buffer[] = { ++ { ++ .name = "aicwf_ring_buffer0", ++ .flags = 0, ++ .ring_id = 0, ++ .verbose_level = 0, ++ .written_bytes = 0, ++ .read_bytes = 0, ++ .written_records = 0, ++ }, ++}; ++ ++static struct wlan_driver_wake_reason_cnt_t wake_reason_cnt = { ++ .total_cmd_event_wake = 10, ++}; ++ ++#endif ++ ++#ifdef CONFIG_APF ++#define AIC_APF_MEM_SIZE 2048 ++#define AIC_APF_VERSION 4 ++ ++static char apfProgram[AIC_APF_MEM_SIZE]; ++#endif ++ ++int aic_dev_start_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 mkeep_alive_id, u8 *ip_pkt, u16 ip_pkt_len, u8 *src_mac, u8 *dst_mac, u32 period_msec) ++{ ++ u8 *data, *pos; ++ ++ data = kzalloc(ip_pkt_len + 14, GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ pos = data; ++ memcpy(pos, dst_mac, 6); ++ pos += 6; ++ memcpy(pos, src_mac, 6); ++ pos += 6; ++ /* Mapping Ethernet type (ETHERTYPE_IP: 0x0800) */ ++ *(pos++) = 0x08; ++ *(pos++) = 0x00; ++ ++ /* Mapping IP pkt */ ++ memcpy(pos, ip_pkt, ip_pkt_len); ++ pos += ip_pkt_len; ++ ++ //add send 802.3 pkt(raw data) ++ kfree(data); ++ ++ return 0; ++} ++ ++int aic_dev_stop_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, u8 mkeep_alive_id) ++{ ++ int res = -1; ++ ++ /* ++ * The mkeep_alive packet is for STA interface only; if the bss is configured as AP, ++ * dongle shall reject a mkeep_alive request. ++ */ ++ if (rwnx_vif->wdev.iftype != NL80211_IFTYPE_STATION) ++ return res; ++ ++ printk("%s execution\n", __func__); ++ ++ //add send stop keep alive ++ res = 0; ++ return res; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++static int aicwf_vendor_start_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* max size of IP packet for keep alive */ ++ const int MKEEP_ALIVE_IP_PKT_MAX = 256; ++ ++ int ret = 0, rem, type; ++ u8 mkeep_alive_id = 0; ++ u8 *ip_pkt = NULL; ++ u16 ip_pkt_len = 0; ++ u8 src_mac[6]; ++ u8 dst_mac[6]; ++ u32 period_msec = 0; ++ const struct nlattr *iter; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; ++ printk("%s\n", __func__); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case MKEEP_ALIVE_ATTRIBUTE_ID: ++ mkeep_alive_id = nla_get_u8(iter); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN: ++ ip_pkt_len = nla_get_u16(iter); ++ if (ip_pkt_len > MKEEP_ALIVE_IP_PKT_MAX) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_IP_PKT: ++ if (!ip_pkt_len) { ++ ret = -EINVAL; ++ printk("ip packet length is 0\n"); ++ goto exit; ++ } ++ ip_pkt = (u8 *)kzalloc(ip_pkt_len, kflags); ++ if (ip_pkt == NULL) { ++ ret = -ENOMEM; ++ printk("Failed to allocate mem for ip packet\n"); ++ goto exit; ++ } ++ memcpy(ip_pkt, (u8 *)nla_data(iter), ip_pkt_len); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR: ++ memcpy(src_mac, nla_data(iter), 6); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR: ++ memcpy(dst_mac, nla_data(iter), 6); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC: ++ period_msec = nla_get_u32(iter); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ ret = -EINVAL; ++ goto exit; ++ } ++ } ++ ++ if (ip_pkt == NULL) { ++ ret = -EINVAL; ++ printk("ip packet is NULL\n"); ++ goto exit; ++ } ++ ++ ret = aic_dev_start_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id, ip_pkt, ip_pkt_len, src_mac, ++ dst_mac, period_msec); ++ if (ret < 0) { ++ printk("start_mkeep_alive is failed ret: %d\n", ret); ++ } ++ ++exit: ++ if (ip_pkt) { ++ kfree(ip_pkt); ++ } ++ ++ return ret; ++} ++ ++static int aicwf_vendor_stop_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ u8 mkeep_alive_id = 0; ++ const struct nlattr *iter; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ ++ printk("%s\n", __func__); ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case MKEEP_ALIVE_ATTRIBUTE_ID: ++ mkeep_alive_id = nla_get_u8(iter); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ ++ ret = aic_dev_stop_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id); ++ if (ret < 0) { ++ printk("stop_mkeep_alive is failed ret: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++static int aicwf_vendor_get_ver(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ int payload = 0; ++ char version[128]; ++ int attr = -1; ++ struct sk_buff *reply; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_DRIVER_VER: ++ memcpy(version, RWNX_VERS_BANNER, sizeof(RWNX_VERS_BANNER)); ++ payload = strlen(version); ++ attr = LOGGER_ATTRIBUTE_DRIVER_VER; ++ break; ++ case LOGGER_ATTRIBUTE_FW_VER: ++ memcpy(version, wiphy->fw_version, sizeof(wiphy->fw_version)); ++ payload = strlen(version); ++ attr = LOGGER_ATTRIBUTE_FW_VER; ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ if (attr < 0) ++ return -EINVAL; ++ ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put(reply, attr, ++ payload, version)) { ++ wiphy_err(wiphy, "%s put version error\n", __func__); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "%s reply cmd error\n", __func__); ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_subcmd_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ struct sk_buff *reply; ++ int num_channels = 0; ++ int *channel_list = NULL; ++ int payload; ++ int i = 0; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ]; ++ ++ num_channels += rwnx_band_2GHz->n_channels; ++ num_channels += (rwnx_hw->band_5g_support) ? rwnx_band_5GHz->n_channels : 0; ++ ++ channel_list = (int *)kzalloc(sizeof(int) * num_channels, GFP_KERNEL); ++ if (!channel_list) ++ return -ENOMEM; ++ ++ for (i = 0; i < rwnx_band_2GHz->n_channels; i++) ++ channel_list[i] = rwnx_band_2GHz->channels[i].center_freq; ++ ++ for (; rwnx_hw->band_5g_support && i < num_channels; i++) ++ channel_list[i] = rwnx_band_5GHz->channels[i].center_freq; ++ ++ payload = sizeof(num_channels) + sizeof(int) * num_channels + 4; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case GSCAN_ATTRIBUTE_BAND: ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put_u32(reply, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels)) ++ goto out_put_fail; ++ ++ if (nla_put(reply, GSCAN_ATTRIBUTE_CHANNEL_LIST, sizeof(int) * num_channels, channel_list)) ++ goto out_put_fail; ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "%s reply cmd error\n", __func__); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ kfree(channel_list); ++ return ret; ++ ++out_put_fail: ++ kfree(channel_list); ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2); ++ ++static int aicwf_vendor_subcmd_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ struct ieee80211_regdomain *regdomain; ++ char *country = NULL; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case ANDR_WIFI_ATTRIBUTE_COUNTRY: ++ printk("%s(%d), ANDR_WIFI_ATTRIBUTE_COUNTRY: %s\n", __func__, __LINE__, (char *)nla_data(iter)); ++ country = (char *)nla_data(iter); ++ ++ AICWFDBG(LOGINFO, "%s country code:%c%c\n", __func__, ++ country[0], ++ country[1]); ++ ++ regdomain = getRegdomainFromRwnxDB(rwnx_hw->wiphy, country); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ if((ret = regulatory_set_wiphy_regd(rwnx_hw->wiphy, regdomain))){ ++ printk("regulatory_set_wiphy_regd fail \r\n"); ++ } ++#else ++ wiphy_apply_custom_regulatory(rwnx_hw->wiphy, regdomain); ++#endif ++ ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future! ++ */ ++ ++ return ret; ++} ++ ++static int aicwf_vendor_logger_trigger_memory_dump(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* TODO ++ * Add handle in the future! ++ */ ++ return 0; ++} ++ ++static int aicwf_vendor_subcmd_get_feature_set(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t feature = 0, payload; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ payload = sizeof(feature); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ /* TODO ++ * Add handle in the future! ++ */ ++ /*bit 1:Basic infrastructure mode*/ ++ if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) ++ feature |= WIFI_FEATURE_INFRA; ++ ++ /*bit 2:Support for 5 GHz Band*/ ++ if (rwnx_hw->band_5g_support) ++ feature |= WIFI_FEATURE_INFRA_5G; ++ ++ /*bit3:HOTSPOT is a supplicant feature, enable it by default*/ ++ feature |= WIFI_FEATURE_HOTSPOT; ++ ++ /*bit 4:P2P*/ ++ if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) && ++ (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) ++ feature |= WIFI_FEATURE_P2P; ++ ++ /*bit 5:soft AP feature supported*/ ++ if (wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) ++ feature |= WIFI_FEATURE_SOFT_AP; ++ ++ /*bit 18:WiFi Logger*/ ++ feature |= WIFI_FEATURE_LOGGER; ++ ++ /*bit 21:WiFi mkeep_alive*/ ++ feature |= WIFI_FEATURE_MKEEP_ALIVE; ++ ++#ifdef AICWF_LATENCY_MODE ++ feature |= WIFI_FEATURE_SET_LATENCY_MODE; ++#endif ++ if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) { ++ wiphy_err(wiphy, "%s put u32 error\n", __func__); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "%s reply cmd error\n", __func__); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_get_feature(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t feature = 0, payload; ++ ++ payload = sizeof(feature); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ feature |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED; ++ feature |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED; ++ ++ /*vts will test wake reason state function*/ ++ feature |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED; ++ ++ if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) { ++ wiphy_err(wiphy, "put skb u32 failed\n"); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_get_ring_status(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t payload; ++ uint32_t ring_buffer_nums = sizeof(ring_buffer) / sizeof(ring_buffer[0]); ++ ++ payload = sizeof(ring_buffer_nums) + sizeof(ring_buffer); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put_u32(reply, LOGGER_ATTRIBUTE_RING_NUM, ring_buffer_nums)) { ++ wiphy_err(wiphy, "put skb u32 failed\n"); ++ goto out_put_fail; ++ } ++ ++ if (nla_put(reply, LOGGER_ATTRIBUTE_RING_STATUS, sizeof(ring_buffer), ring_buffer)) { ++ wiphy_err(wiphy, "put skb failed\n"); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_start_logging(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type, intval, size, i; ++ const struct nlattr *iter; ++ struct wifi_ring_buffer_status rb; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_LOG_LEVEL: ++ rb.verbose_level = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_RING_FLAGS: ++ rb.flags = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_LOG_TIME_INTVAL: ++ intval = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE: ++ size = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_RING_NAME: ++ strcpy(rb.name, nla_data(iter)); ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ ret = -EINVAL; ++ for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) { ++ if (strcmp(rb.name, ring_buffer[i].name) == 0) { ++ ret = 0; ++ break; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ ++ return ret; ++} ++ ++static int aicwf_vendor_logger_get_ring_data(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type, i; ++ const struct nlattr *iter; ++ struct wifi_ring_buffer_status rb; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_RING_NAME: ++ strcpy(rb.name, nla_data(iter)); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ ret = -EINVAL; ++ for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) { ++ if (strcmp(rb.name, ring_buffer[i].name) == 0) { ++ ret = 0; ++ break; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ ++ return ret; ++} ++ ++static int aicwf_vendor_logger_get_wake_reason_stats(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t payload; ++ ++ payload = sizeof(wake_reason_cnt.total_cmd_event_wake); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ if (nla_put_u32(reply, WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT, wake_reason_cnt.total_cmd_event_wake)) ++ goto out_put_fail; ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_get_tx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++#if 0 ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ int fate_num; ++ int fate_data; ++ ++ AICWFDBG(LOGDEBUG, "%s Enter\r\n", __func__); ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_PKT_FATE_NUM: ++ fate_num = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_PKT_FATE_DATA: ++ fate_data = nla_get_u64(iter); ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++#endif ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++static int aicwf_vendor_logger_get_rx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++#if 0 ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ int fate_num; ++ int fate_data; ++ ++ AICWFDBG(LOGDEBUG, "%s Enter\r\n", __func__); ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_PKT_FATE_NUM: ++ fate_num = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_PKT_FATE_DATA: ++ fate_data = nla_get_u64(iter); ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++#endif ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++ ++#ifdef AICWF_LATENCY_MODE ++static int aicwf_vendor_subcmd_set_latency_mode(struct wiphy *wiphy, ++ struct wireless_dev *wdev, const void *data, int len) ++{ ++ int err = 0, rem, type; ++ u32 latency_mode; ++ const struct nlattr *iter; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case ANDR_WIFI_ATTRIBUTE_LATENCY_MODE: ++ latency_mode = nla_get_u32(iter); ++ printk("%s,Setting latency mode %d\n", __func__, latency_mode); ++ #ifdef AICWF_SDIO_SUPPORT ++ if (latency_mode) { ++ rwnx_send_me_set_lp_level(rwnx_hw, 0, 1); ++ } else { ++ rwnx_send_me_set_lp_level(rwnx_hw, 1, 0); ++ } ++ #endif ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return err; ++ } ++ } ++ ++ return err; ++} ++#endif ++ ++static int aicwf_vendor_logger_start_pkt_fate_monitoring(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++#ifdef CONFIG_APF ++static int aicwf_vendor_apf_subcmd_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t payload; ++ printk("%s\n", __func__); ++ ++ /* APF_ATTRIBUTE_VERSION + APF_ATTRIBUTE_MAX_LEN */ ++ payload = sizeof(u32) * 2; ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put_u32(reply, APF_ATTRIBUTE_VERSION, AIC_APF_VERSION)) ++ goto out_put_fail; ++ ++ if (nla_put_u32(reply, APF_ATTRIBUTE_MAX_LEN, AIC_APF_MEM_SIZE)) ++ goto out_put_fail; ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_apf_set_filter(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ unsigned int mProgramLen = 0; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ printk("%s\n", __func__); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case APF_ATTRIBUTE_PROGRAM_LEN: ++ memcpy(&mProgramLen, nla_data(iter), sizeof(unsigned int)); ++ ret = (mProgramLen > 0 && mProgramLen <= AIC_APF_MEM_SIZE) ? 0 : -EINVAL; ++ break; ++ case APF_ATTRIBUTE_PROGRAM: ++ if (mProgramLen > AIC_APF_MEM_SIZE || mProgramLen == 0) { ++ printk("%s: apf program size invalid: %d (should > 0 and <= %d)\n", ++ __func__, mProgramLen, AIC_APF_MEM_SIZE); ++ return -EINVAL; ++ } ++ ++ memcpy(apfProgram, nla_data(iter), mProgramLen); ++ ret = rwnx_send_set_apf_prog_req(rwnx_hw, apfProgram, mProgramLen); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ return ret; ++} ++ ++static int aicwf_vendor_apf_read_filter_data(struct wiphy *wiphy, ++ struct wireless_dev *wdev, const void *data, int len) ++{ ++ struct sk_buff *reply; ++ int ret, payload, apf_mem_size; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ printk("%s\n", __func__); ++ ++ apf_mem_size = AIC_APF_MEM_SIZE; ++ payload = sizeof(u32) + apf_mem_size; ++ ++ ret = rwnx_send_get_apf_prog_req(rwnx_hw, apfProgram, apf_mem_size); ++ if (ret != 0) { ++ pr_err("%s, Failed to read apf mem from firmware, ret = %d\n", __func__, ret); ++ return ret; ++ } ++ ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ if (!reply) ++ return -ENOMEM; ++ ++ ret = nla_put_u32(reply, APF_ATTRIBUTE_PROGRAM_LEN, apf_mem_size); ++ if (ret < 0) { ++ pr_err("%s, Failed to put APF_ATTRIBUTE_MAX_LEN, ret = %d\n", __func__, ret); ++ goto out_put_fail; ++ } ++ ++ /* copy the full apf mem */ ++ ret = nla_put(reply, APF_ATTRIBUTE_PROGRAM, apf_mem_size, &apfProgram[0]); ++ if (ret < 0) { ++ pr_err("%s, Failed to put APF_ATTRIBUTE_PROGRAM, ret = %d\n", __func__, ret); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++#endif ++ ++static int aicwf_vendor_sub_cmd_set_mac(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ u8 mac[ETH_ALEN]; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR: ++ memcpy(mac, nla_data(iter), ETH_ALEN); ++ printk("%s, %02X:%02X:%02X:%02X:%02X:%02X\n", __func__, ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ ++ return ret; ++} ++#endif ++ ++static const struct nla_policy ++aicwf_cfg80211_mkeep_alive_policy[MKEEP_ALIVE_ATTRIBUTE_MAX+1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [MKEEP_ALIVE_ATTRIBUTE_ID] = { .type = NLA_U8 }, ++ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = { .type = NLA_MSECS }, ++ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = { .type = NLA_U16 }, ++ [MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = { .type = NLA_MSECS, ++ .len = ETH_ALEN }, ++ [MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = { .type = NLA_MSECS, ++ .len = ETH_ALEN }, ++ [MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = { .type = NLA_U32 }, ++}; ++ ++static const struct nla_policy ++aicwf_cfg80211_logger_policy[LOGGER_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [LOGGER_ATTRIBUTE_DRIVER_VER] = { .type = NLA_BINARY }, ++ [LOGGER_ATTRIBUTE_FW_VER] = { .type = NLA_BINARY }, ++ [LOGGER_ATTRIBUTE_LOG_LEVEL] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_RING_FLAGS] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_LOG_TIME_INTVAL] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_RING_NAME] = { .type = NLA_STRING }, ++}; ++ ++#ifdef CONFIG_APF ++static const struct nla_policy ++aicwf_cfg80211_apf_policy[APF_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [APF_ATTRIBUTE_VERSION] = {.type = NLA_U32 }, ++ [APF_ATTRIBUTE_MAX_LEN] = {.type = NLA_U32 }, ++ [APF_ATTRIBUTE_PROGRAM] = { .type = NLA_BINARY }, ++ [APF_ATTRIBUTE_PROGRAM_LEN] = { .type = NLA_U32 }, ++}; ++#endif ++ ++static const struct nla_policy ++aicwf_cfg80211_subcmd_policy[GSCAN_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [GSCAN_ATTRIBUTE_BAND] = { .type = NLA_U32 }, ++}; ++ ++static const struct nla_policy ++aicwf_cfg80211_andr_wifi_policy[ANDR_WIFI_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [ANDR_WIFI_ATTRIBUTE_COUNTRY] = { .type = NLA_STRING }, ++}; ++ ++static const struct nla_policy ++aicwf_cfg80211_subcmd_set_mac_policy[WIFI_VENDOR_ATTR_DRIVER_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR] = { .type = NLA_MSECS, .len = ETH_ALEN }, ++}; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++static int aicwf_dump_interface(struct wiphy *wiphy, ++ struct wireless_dev *wdev, struct sk_buff *skb, ++ const void *data, int data_len, ++ unsigned long *storage) ++{ ++ return 0; ++} ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++const struct wiphy_vendor_command aicwf_vendor_cmd[] = { ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_start_mkeep_alive, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_mkeep_alive_policy, ++ .maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_stop_mkeep_alive, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_mkeep_alive_policy, ++ .maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_VER ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_get_ver, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_logger_policy, ++ .maxattr = LOGGER_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_get_channel_list, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_subcmd_policy, ++ .maxattr = GSCAN_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_set_country_code, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_andr_wifi_policy, ++ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_TRIGGER_MEM_DUMP ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_trigger_memory_dump, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_GET_FEATURE_SET ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_get_feature_set, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_FEATURE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_feature, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_RING_STATUS ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_ring_status, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_START_LOGGING ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_start_logging, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_logger_policy, ++ .maxattr = LOGGER_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_RING_DATA ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_ring_data, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_logger_policy, ++ .maxattr = LOGGER_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_WAKE_REASON_STATS ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_wake_reason_stats, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++#ifdef CONFIG_APF ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = APF_SUBCMD_GET_CAPABILITIES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_apf_subcmd_get_capabilities, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_apf_policy, ++ .maxattr = APF_ATTRIBUTE_MAX, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = APF_SUBCMD_SET_FILTER ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_apf_set_filter, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_apf_policy, ++ .maxattr = APF_ATTRIBUTE_MAX, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = APF_SUBCMD_READ_FILTER_DATA ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_apf_read_filter_data, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) ++ .policy = aicwf_cfg80211_apf_policy, ++ .maxattr = APF_ATTRIBUTE_MAX ++#endif /* LINUX_VERSION >= 5.3 */ ++ }, ++#endif ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_START_PKT_FATE_MONITORING ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_start_pkt_fate_monitoring, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_TX_PKT_FATES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_tx_pkt_fates, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_RX_PKT_FATES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_rx_pkt_fates, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = VENDOR_NL80211_SUBCMD_SET_MAC ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = aicwf_vendor_sub_cmd_set_mac, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_subcmd_set_mac_policy, ++ .maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX, ++#endif ++ }, ++ { ++ { ++ .vendor_id = BRCM_OUI, ++ .subcmd = VENDOR_NL80211_SUBCMD_SET_MAC ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = aicwf_vendor_sub_cmd_set_mac, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_subcmd_set_mac_policy, ++ .maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX, ++#endif ++ }, ++#ifdef AICWF_LATENCY_MODE ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_SET_LATENCY_MODE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_set_latency_mode, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) ++ .policy = aicwf_cfg80211_andr_wifi_policy, ++ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX ++#endif /* LINUX_VERSION >= 5.3 */ ++ }, ++#endif ++}; ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++static const struct nl80211_vendor_cmd_info aicwf_vendor_events[] = { ++}; ++#endif ++ ++int aicwf_vendor_init(struct wiphy *wiphy) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ wiphy->vendor_commands = aicwf_vendor_cmd; ++ wiphy->n_vendor_commands = ARRAY_SIZE(aicwf_vendor_cmd); ++ wiphy->vendor_events = aicwf_vendor_events; ++ wiphy->n_vendor_events = ARRAY_SIZE(aicwf_vendor_events); ++#endif ++ return 0; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h +new file mode 100644 +index 000000000000..996edefa812e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h +@@ -0,0 +1,363 @@ ++#ifndef _AIC_VENDOR_H ++#define _AIC_VENDOR_H ++ ++#include ++ ++#define GOOGLE_OUI 0x001A11 ++#define BRCM_OUI 0x001018 ++ ++typedef enum { ++ START_MKEEP_ALIVE, ++ STOP_MKEEP_ALIVE, ++} GetCmdType; ++ ++typedef enum { ++ /* don't use 0 as a valid subcommand */ ++ VENDOR_NL80211_SUBCMD_UNSPECIFIED, ++ ++ /* define all vendor startup commands between 0x0 and 0x0FFF */ ++ VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001, ++ VENDOR_NL80211_SUBCMD_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 NearbyDiscovery related commands between 0x1100 and 0x11FF */ ++ ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100, ++ ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x11FF, ++ ++ /* 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, ++ ++ /* define all NAN related commands between 0x1700 and 0x17FF */ ++ ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700, ++ ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF, ++ ++ /* define all Android Packet Filter related commands between 0x1800 and 0x18FF */ ++ ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800, ++ ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF, ++ ++ /* This is reserved for future usage */ ++ ++} ANDROID_VENDOR_SUB_COMMAND; ++ ++typedef enum { ++ WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, ++ WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE, ++} WIFI_OFFLOAD_SUB_COMMAND; ++ ++ ++enum mkeep_alive_attributes { ++ MKEEP_ALIVE_ATTRIBUTE_ID = 0x1, ++ MKEEP_ALIVE_ATTRIBUTE_IP_PKT, ++ MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, ++ MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, ++ MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, ++ MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, ++ MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST, ++ MKEEP_ALIVE_ATTRIBUTE_MAX = MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST - 1 ++}; ++ ++enum debug_sub_command { ++ LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, ++ LOGGER_TRIGGER_MEM_DUMP, ++ LOGGER_GET_MEM_DUMP, ++ LOGGER_GET_VER, ++ LOGGER_GET_RING_STATUS, ++ LOGGER_GET_RING_DATA, ++ LOGGER_GET_FEATURE, ++ LOGGER_RESET_LOGGING, ++ LOGGER_TRIGGER_DRIVER_MEM_DUMP, ++ LOGGER_GET_DRIVER_MEM_DUMP, ++ LOGGER_START_PKT_FATE_MONITORING, ++ LOGGER_GET_TX_PKT_FATES, ++ LOGGER_GET_RX_PKT_FATES, ++ LOGGER_GET_WAKE_REASON_STATS, ++ LOGGER_DEBUG_GET_DUMP, ++ LOGGER_FILE_DUMP_DONE_IND, ++ LOGGER_SET_HAL_START, ++ LOGGER_HAL_STOP, ++ LOGGER_SET_HAL_PID, ++}; ++ ++enum logger_attributes { ++ LOGGER_ATTRIBUTE_INVALID = 0, ++ LOGGER_ATTRIBUTE_DRIVER_VER, ++ LOGGER_ATTRIBUTE_FW_VER, ++ LOGGER_ATTRIBUTE_RING_ID, ++ LOGGER_ATTRIBUTE_RING_NAME, ++ LOGGER_ATTRIBUTE_RING_FLAGS, ++ LOGGER_ATTRIBUTE_LOG_LEVEL, ++ LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, ++ LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, ++ LOGGER_ATTRIBUTE_FW_DUMP_LEN, ++ LOGGER_ATTRIBUTE_FW_DUMP_DATA, ++ // LOGGER_ATTRIBUTE_FW_ERR_CODE, ++ LOGGER_ATTRIBUTE_RING_DATA, ++ LOGGER_ATTRIBUTE_RING_STATUS, ++ LOGGER_ATTRIBUTE_RING_NUM, ++ LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN, ++ LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA, ++ LOGGER_ATTRIBUTE_PKT_FATE_NUM, ++ LOGGER_ATTRIBUTE_PKT_FATE_DATA, ++ LOGGER_ATTRIBUTE_AFTER_LAST, ++ LOGGER_ATTRIBUTE_MAX = LOGGER_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++#ifdef CONFIG_APF ++enum wifi_apf_attr { ++ APF_ATTRIBUTE_VERSION, ++ APF_ATTRIBUTE_MAX_LEN, ++ APF_ATTRIBUTE_PROGRAM, ++ APF_ATTRIBUTE_PROGRAM_LEN, ++ APF_ATTRIBUTE_LAST, ++ APF_ATTRIBUTE_MAX = APF_ATTRIBUTE_LAST - 1, ++}; ++#endif ++ ++enum wifi_sub_command { ++ 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 */ ++ GSCAN_SUBCMD_GET_CHANNEL_LIST, /* 0x1009 */ ++ WIFI_SUBCMD_GET_FEATURE_SET, /* 0x100A */ ++ WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x100B */ ++ WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x100C */ ++ WIFI_SUBCMD_NODFS_SET, /* 0x100D */ ++ WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x100E */ ++ /* Add more sub commands here */ ++ GSCAN_SUBCMD_SET_EPNO_SSID, /* 0x100F */ ++ WIFI_SUBCMD_SET_SSID_WHITE_LIST, /* 0x1010 */ ++ WIFI_SUBCMD_SET_ROAM_PARAMS, /* 0x1011 */ ++ WIFI_SUBCMD_ENABLE_LAZY_ROAM, /* 0x1012 */ ++ WIFI_SUBCMD_SET_BSSID_PREF, /* 0x1013 */ ++ WIFI_SUBCMD_SET_BSSID_BLACKLIST, /* 0x1014 */ ++ GSCAN_SUBCMD_ANQPO_CONFIG, /* 0x1015 */ ++ WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x1016 */ ++ WIFI_SUBCMD_CONFIG_ND_OFFLOAD, /* 0x1017 */ ++ WIFI_SUBCMD_SET_LATENCY_MODE, /* 0x1018 */ ++ /* Add more sub commands here */ ++ GSCAN_SUBCMD_MAX, ++ APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START, ++ APF_SUBCMD_SET_FILTER, ++#ifdef CONFIG_APF ++ APF_SUBCMD_READ_FILTER_DATA, ++#endif ++}; ++ ++enum gscan_attributes { ++ 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_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, ++ ++ 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, ++ ++ /* remaining reserved for additional attributes */ ++ 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_NUM_CHANNELS, ++ GSCAN_ATTRIBUTE_CHANNEL_LIST, ++ GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, ++ ++ GSCAN_ATTRIBUTE_AFTER_LAST, ++ GSCAN_ATTRIBUTE_MAX = GSCAN_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++enum andr_wifi_attributes { ++ ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, ++ ANDR_WIFI_ATTRIBUTE_FEATURE_SET, ++ ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, ++ ANDR_WIFI_ATTRIBUTE_NODFS_SET, ++ ANDR_WIFI_ATTRIBUTE_COUNTRY, ++ ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE, ++ ANDR_WIFI_ATTRIBUTE_LATENCY_MODE, ++ // Add more attribute here ++ ANDR_WIFI_ATTRIBUTE_AFTER_LAST, ++ ANDR_WIFI_ATTRIBUTE_MAX = ANDR_WIFI_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++enum wifi_support_feature { ++ /* Feature enums */ ++ WIFI_FEATURE_INFRA = 0x0001, /* Basic infrastructure mode */ ++ WIFI_FEATURE_INFRA_5G = 0x0002, /* Support for 5, GHz Band */ ++ WIFI_FEATURE_HOTSPOT = 0x0004, /* Support for GAS/ANQP */ ++ WIFI_FEATURE_P2P = 0x0008, /* Wifi-Direct */ ++ WIFI_FEATURE_SOFT_AP = 0x0010, /* Soft AP */ ++ WIFI_FEATURE_GSCAN = 0x0020, /* Google-Scan APIs */ ++ WIFI_FEATURE_NAN = 0x0040, /* Neighbor Awareness Networking */ ++ WIFI_FEATURE_D2D_RTT = 0x0080, /* Device-to-device RTT */ ++ WIFI_FEATURE_D2AP_RTT = 0x0100, /* Device-to-AP RTT */ ++ WIFI_FEATURE_BATCH_SCAN = 0x0200, /* Batched Scan (legacy) */ ++ WIFI_FEATURE_PNO = 0x0400, /* Preferred network offload */ ++ WIFI_FEATURE_ADDITIONAL_STA = 0x0800, /* Support for two STAs */ ++ WIFI_FEATURE_TDLS = 0x1000, /* Tunnel directed link setup */ ++ WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000, /* Support for TDLS off channel */ ++ WIFI_FEATURE_EPR = 0x4000, /* Enhanced power reporting */ ++ WIFI_FEATURE_AP_STA = 0x8000, /* Support for AP STA Concurrency */ ++ WIFI_FEATURE_LINK_LAYER_STATS = 0x10000, /* Support for Linkstats */ ++ WIFI_FEATURE_LOGGER = 0x20000, /* WiFi Logger */ ++ WIFI_FEATURE_HAL_EPNO = 0x40000, /* WiFi PNO enhanced */ ++ WIFI_FEATURE_RSSI_MONITOR = 0x80000, /* RSSI Monitor */ ++ WIFI_FEATURE_MKEEP_ALIVE = 0x100000, /* WiFi mkeep_alive */ ++ WIFI_FEATURE_CONFIG_NDO = 0x200000, /* ND offload configure */ ++ WIFI_FEATURE_TX_TRANSMIT_POWER = 0x400000, /* Capture Tx transmit power levels */ ++ WIFI_FEATURE_CONTROL_ROAMING = 0x800000, /* Enable/Disable firmware roaming */ ++ WIFI_FEATURE_IE_WHITELIST = 0x1000000, /* Support Probe IE white listing */ ++ WIFI_FEATURE_SCAN_RAND = 0x2000000, /* Support MAC & Probe Sequence Number randomization */ ++ WIFI_FEATURE_SET_LATENCY_MODE = 0x40000000, /* Support Latency mode setting */ ++ WIFI_FEATURE_INVALID = 0xFFFFFFFF, /* Invalid Feature */ ++}; ++ ++enum wifi_logger_feature { ++ WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), // Memory dump of FW ++ WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), // PKT status ++ WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), // Connectivity event ++ WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), // POWER of Driver ++ WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), // WAKE LOCK of Driver ++ WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), // verbose log of FW ++ WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), // monitor the health of FW ++ WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), // dumps driver state ++ WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)), // tracks connection packets' fate ++}; ++ ++enum wake_stats_attributes { ++ WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT, ++ WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE, ++ WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT, ++ WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED, ++ WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW, ++ WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE, ++ WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT, ++ WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED, ++ WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE, ++ WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT, ++ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT, ++ WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS, ++ WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT, ++ WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT, ++ WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT, ++ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO, ++ WAKE_STAT_ATTRIBUTE_AFTER_LAST, ++ WAKE_STAT_ATTRIBUTE_MAX = WAKE_STAT_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++enum vendor_nl80211_subcmd { ++ /* copied from wpa_supplicant brcm definations */ ++ VENDOR_NL80211_SUBCMD_UNSPEC = 0, ++ VENDOR_NL80211_SUBCMD_SET_PMK = 4, ++ VENDOR_NL80211_SUBCMD_SET_MAC = 6, ++ VENDOR_NL80211_SCMD_ACS = 9, ++ VENDOR_NL80211_SCMD_MAX = 10, ++}; ++ ++enum nl80211_vendor_subcmd_attributes { ++ WIFI_VENDOR_ATTR_DRIVER_CMD = 0, ++ WIFI_VENDOR_ATTR_DRIVER_KEY_PMK = 1, ++ WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR = 3, ++ WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST = 5, ++ WIFI_VENDOR_ATTR_DRIVER_MAX = ++ WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST - 1, ++}; ++ ++typedef int wifi_ring_buffer_id; ++ ++struct wifi_ring_buffer_status { ++ u8 name[32]; ++ u32 flags; ++ wifi_ring_buffer_id ring_id; ++ u32 ring_buffer_byte_size; ++ u32 verbose_level; ++ u32 written_bytes; ++ u32 read_bytes; ++ u32 written_records; ++}; ++ ++struct rx_data_cnt_details_t { ++ int rx_unicast_cnt; /*Total rx unicast packet which woke up host */ ++ int rx_multicast_cnt; /*Total rx multicast packet which woke up host */ ++ int rx_broadcast_cnt; /*Total rx broadcast packet which woke up host */ ++}; ++ ++struct rx_wake_pkt_type_classification_t { ++ int icmp_pkt; /*wake icmp packet count */ ++ int icmp6_pkt; /*wake icmp6 packet count */ ++ int icmp6_ra; /*wake icmp6 RA packet count */ ++ int icmp6_na; /*wake icmp6 NA packet count */ ++ int icmp6_ns; /*wake icmp6 NS packet count */ ++ //ToDo: Any more interesting classification to add? ++}; ++ ++struct rx_multicast_cnt_t{ ++ int ipv4_rx_multicast_addr_cnt; /*Rx wake packet was ipv4 multicast */ ++ int ipv6_rx_multicast_addr_cnt; /*Rx wake packet was ipv6 multicast */ ++ int other_rx_multicast_addr_cnt;/*Rx wake packet was non-ipv4 and non-ipv6*/ ++}; ++ ++struct wlan_driver_wake_reason_cnt_t { ++ int total_cmd_event_wake; /* Total count of cmd event wakes */ ++ int *cmd_event_wake_cnt; /* Individual wake count array, each index a reason */ ++ int cmd_event_wake_cnt_sz; /* Max number of cmd event wake reasons */ ++ int cmd_event_wake_cnt_used; /* Number of cmd event wake reasons specific to the driver */ ++ ++ int total_driver_fw_local_wake; /* Total count of drive/fw wakes, for local reasons */ ++ int *driver_fw_local_wake_cnt; /* Individual wake count array, each index a reason */ ++ int driver_fw_local_wake_cnt_sz; /* Max number of local driver/fw wake reasons */ ++ int driver_fw_local_wake_cnt_used; /* Number of local driver/fw wake reasons specific to the driver */ ++ ++ int total_rx_data_wake; /* total data rx packets, that woke up host */ ++ struct rx_data_cnt_details_t rx_wake_details; ++ struct rx_wake_pkt_type_classification_t rx_wake_pkt_classification_info; ++ struct rx_multicast_cnt_t rx_multicast_wake_pkt_info; ++}; ++ ++typedef struct wl_mkeep_alive_pkt { ++ u16 version; /* Version for mkeep_alive */ ++ u16 length; /* length of fixed parameters in the structure */ ++ u32 period_msec; /* high bit on means immediate send */ ++ u16 len_bytes; ++ u8 keep_alive_id; /* 0 - 3 for N = 4 */ ++ u8 data[1]; ++} wl_mkeep_alive_pkt_t; ++ ++#endif /* _AIC_VENDOR_H */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c +new file mode 100644 +index 000000000000..8dee7597efad +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c +@@ -0,0 +1,166 @@ ++#include "rwnx_main.h" ++#include "rwnx_msg_tx.h" ++#include "reg_access.h" ++#include "aicwf_compat_8800d80.h" ++ ++#define FW_USERCONFIG_NAME_8800D80 "aic_userconfig_8800d80.txt" ++#define FW_USERCONFIG_NAME_8800D80X2 "aic_userconfig_8800d80x2.txt" ++#define FW_POWERLIMIT_NAME_8800D80 "aic_powerlimit_8800d80.txt" ++ ++ ++int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, ++ u32** buffer, const char *filename); ++void rwnx_plat_userconfig_parsing2(char *buffer, int size); ++void rwnx_plat_userconfig_parsing3(char *buffer, int size); ++void rwnx_plat_userconfig_parsing_8800d80x2(char *buffer, int size); ++ ++void rwnx_release_firmware_common(u32** buffer); ++ ++int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm) ++{ ++ int ret = 0; ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ if ((ret = rwnx_send_txpwr_lvl_v3_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst2x_req(rwnx_hw))) { ++ return -1; ++ } ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if ((ret = rwnx_send_txpwr_lvl_v4_req(rwnx_hw))) { ++ return -1; ++ } ++ if ((ret = rwnx_send_txpwr_ofst2x_v2_req(rwnx_hw))) { ++ return -1; ++ } ++ } ++ ++ if ((ret = rwnx_send_txpwr_lvl_adj_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) { ++ return -1; ++ } ++ ++ return 0 ; ++} ++ ++int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800D80; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing3((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ ++int rwnx_plat_userconfig_load_8800d80x2(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800D80X2; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing_8800d80x2((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ ++#ifdef CONFIG_POWER_LIMIT ++extern char country_code[4]; ++int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst = NULL; ++ char *filename = FW_POWERLIMIT_NAME_8800D80; ++ ++ AICWFDBG(LOGDEBUG, "powerlimit file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of cfg file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ AICWFDBG(LOGDEBUG, "### Load file done: %s, size=%d\n", filename, size); ++ ++ /* parsing the file */ ++ rwnx_plat_powerlimit_parsing((char *)dst, size, country_code); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGDEBUG, "powerlimit download complete\n\n"); ++ return 0; ++} ++ ++int rwnx_plat_powerlimit_load_8800d80x2(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst = NULL; ++ char *filename = FW_POWERLIMIT_NAME_8800D80; ++ ++ AICWFDBG(LOGDEBUG, "powerlimit file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of cfg file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ AICWFDBG(LOGDEBUG, "### Load file done: %s, size=%d\n", filename, size); ++ ++ /* parsing the file */ ++ rwnx_plat_powerlimit_parsing((char *)dst, size, country_code); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGDEBUG, "powerlimit download complete\n\n"); ++ return 0; ++} ++ ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h +new file mode 100644 +index 000000000000..e76577414834 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h +@@ -0,0 +1,15 @@ ++#ifndef _AICWF_COMPAT_8800D80_H_ ++#define _AICWF_COMPAT_8800D80_H_ ++#include ++ ++int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); ++int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw); ++int rwnx_plat_userconfig_load_8800d80x2(struct rwnx_hw *rwnx_hw); ++ ++#ifdef CONFIG_POWER_LIMIT ++int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw); ++int rwnx_plat_powerlimit_load_8800d80x2(struct rwnx_hw *rwnx_hw); ++#endif ++ ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c +new file mode 100644 +index 000000000000..3e68283f6dc7 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c +@@ -0,0 +1,685 @@ ++#include "rwnx_main.h" ++#include "rwnx_msg_tx.h" ++#include "reg_access.h" ++#include "aic_bsp_export.h" ++ ++#define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc" ++#define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin" ++#define FW_USERCONFIG_NAME_8800DC "aic_userconfig_8800dc.txt" ++#define FW_USERCONFIG_NAME_8800DW "aic_userconfig_8800dw.txt" ++ ++int rwnx_plat_bin_fw_upload_2(struct rwnx_hw *rwnx_hw, u32 fw_addr, ++ char *filename); ++int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, ++ u32** buffer, const char *filename); ++void rwnx_plat_userconfig_parsing2(char *buffer, int size); ++ ++void rwnx_release_firmware_common(u32** buffer); ++ ++#if !defined(CONFIG_EXT_FEM_8800DCDW) ++u32 wifi_txgain_table_24g_8800dcdw[32] = ++{ ++ 0xA4B22189, //index 0 ++ 0x00007825, ++ 0xA4B2214B, //index 1 ++ 0x00007825, ++ 0xA4B2214F, //index 2 ++ 0x00007825, ++ 0xA4B221D5, //index 3 ++ 0x00007825, ++ 0xA4B221DC, //index 4 ++ 0x00007825, ++ 0xA4B221E5, //index 5 ++ 0x00007825, ++ 0xAC9221E5, //index 6 ++ 0x00006825, ++ 0xAC9221EF, //index 7 ++ 0x00006825, ++ 0xBC9221EE, //index 8 ++ 0x00006825, ++ 0xBC9221FF, //index 9 ++ 0x00006825, ++ 0xBC9221FF, //index 10 ++ 0x00004025, ++ 0xB792203F, //index 11 ++ 0x00004026, ++ 0xDC92203F, //index 12 ++ 0x00004025, ++ 0xE692203F, //index 13 ++ 0x00004025, ++ 0xFF92203F, //index 14 ++ 0x00004035, ++ 0xFFFE203F, //index 15 ++ 0x00004832 ++}; ++ ++u32 wifi_txgain_table_24g_1_8800dcdw[32] = ++{ ++ 0x096E2011, //index 0 ++ 0x00004001, ++ 0x096E2015, //index 1 ++ 0x00004001, ++ 0x096E201B, //index 2 ++ 0x00004001, ++ 0x116E2018, //index 3 ++ 0x00004001, ++ 0x116E201E, //index 4 ++ 0x00004001, ++ 0x116E2023, //index 5 ++ 0x00004001, ++ 0x196E2021, //index 6 ++ 0x00004001, ++ 0x196E202B, //index 7 ++ 0x00004001, ++ 0x216E202B, //index 8 ++ 0x00004001, ++ 0x236E2027, //index 9 ++ 0x00004001, ++ 0x236E2031, //index 10 ++ 0x00004001, ++ 0x246E2039, //index 11 ++ 0x00004001, ++ 0x26922039, //index 12 ++ 0x00004001, ++ 0x2E92203F, //index 13 ++ 0x00004001, ++ 0x3692203F, //index 14 ++ 0x00004001, ++ 0x3FF2203F, //index 15 ++ 0x00004001, ++}; ++ ++u32 wifi_txgain_table_24g_8800dcdw_h[32] = ++{ ++ 0xA55629C9, //index 0 ++ 0x00005825, ++ 0xAE5629C9, //index 1 ++ 0x00005825, ++ 0xAD5629CD, //index 2 ++ 0x00005825, ++ 0xAD5629D1, //index 3 ++ 0x00005825, ++ 0xAD5629D7, //index 4 ++ 0x00005825, ++ 0xAD5629DE, //index 5 ++ 0x00005825, ++ 0xAD5629E6, //index 6 ++ 0x00005825, ++ 0xBD5629E6, //index 7 ++ 0x00005825, ++ 0xBD5629F0, //index 8 ++ 0x00005825, ++ 0xCD5629F0, //index 9 ++ 0x00005825, ++ 0xE55629F0, //index 10 ++ 0x00005825, ++ 0xE55629FF, //index 11 ++ 0x00005825, ++ 0xE55629FF, //index 12 ++ 0x00002825, ++ 0xE75629FF, //index 13 ++ 0x00002825, ++ 0xFF5629FF, //index 14 ++ 0x00001825, ++ 0xFF5628FF, //index 15 ++ 0x00001025, ++}; ++ ++u32 wifi_txgain_table_24g_1_8800dcdw_h[32] = ++{ ++ 0x941A2048, //index 0 ++ 0x00001825, ++ 0x961A2048, //index 1 ++ 0x00001825, ++ 0x9D1A2048, //index 2 ++ 0x00001825, ++ 0x9A1A204F, //index 3 ++ 0x00001825, ++ 0x961A204F, //index 4 ++ 0x00001825, ++ 0x9A1A2057, //index 5 ++ 0x00001825, ++ 0x9C1A2057, //index 6 ++ 0x00001825, ++ 0xA31A205B, //index 7 ++ 0x00001825, ++ 0xAB1A205B, //index 8 ++ 0x00001825, ++ 0xAD1A205B, //index 9 ++ 0x00001825, ++ 0xA71A2064, //index 10 ++ 0x00001825, ++ 0xAD1A2070, //index 11 ++ 0x00001825, ++ 0xAD72207F, //index 12 ++ 0x00001825, ++ 0xBCAE207F, //index 13 ++ 0x00001825, ++ 0xBFB2207F, //index 14 ++ 0x00001825, ++ 0xD73A207F, //index 15 ++ 0x00001825, ++}; ++ ++#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ ++// ofdm ++uint32_t wifi_txgain_table_24g_8800dcdw_femkct[32] = { ++ 0x919221C2, //index 0 ++ 0x00007825, ++ 0x899221C3, //index 1 ++ 0x00007825, ++ 0x8B9221C3, //index 2 ++ 0x00007825, ++ 0x929221C3, //index 3 ++ 0x00007825, ++ 0x949221C4, //index 4 ++ 0x00007825, ++ 0x969221C4, //index 5 ++ 0x00007825, ++ 0x949221C6, //index 6 ++ 0x00007825, ++ 0x949221C8, //index 7 ++ 0x00007825, ++ 0x9C9221C8, //index 8 ++ 0x00007825, ++ 0x9C9221CA, //index 9 ++ 0x00007825, ++ 0x9C9221CB, //index 10 ++ 0x00007825, ++ 0x939221D5, //index 11 ++ 0x00007825, ++ 0x9B9221D7, //index 12 ++ 0x00007825, ++ 0xA49221D7, //index 13 ++ 0x00007825, ++ 0xA79221D7, //index 14 ++ 0x00007825, ++ 0xBD9221D7, //index 15 ++ 0x00007825, ++}; ++ ++// 11b ++uint32_t wifi_txgain_table_24g_1_8800dcdw_femkct[32] = { ++ 0x836E20C2, //index 0 ++ 0x00003024, ++ 0x856E20C2, //index 1 ++ 0x00003024, ++ 0x826E20C3, //index 2 ++ 0x00003024, ++ 0x836E20C3, //index 3 ++ 0x00003024, ++ 0x856E20C3, //index 4 ++ 0x00003024, ++ 0x876E20C3, //index 5 ++ 0x00003024, ++ 0x8B6E20C3, //index 6 ++ 0x00003024, ++ 0x926E20C4, //index 7 ++ 0x00003024, ++ 0x9A6E20C4, //index 8 ++ 0x00003024, ++ 0x936E20C5, //index 9 ++ 0x00003024, ++ 0x936E20C7, //index 10 ++ 0x00003024, ++ 0xA16E20C8, //index 11 ++ 0x00003024, ++ 0xA16E20CA, //index 12 ++ 0x00003024, ++ 0xA26E20CB, //index 13 ++ 0x00003024, ++ 0xAA6E20CD, //index 14 ++ 0x00003024, ++ 0xAC7220CF, //index 15 ++ 0x00003024, ++}; ++#endif ++ ++u32 wifi_rxgain_table_24g_20m_8800dcdw[64] = { ++ 0x82f282d1,//index 0 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x42f282d1,//index 1 ++ 0x95923524, ++ 0x80808419, ++ 0x000000f0, ++ 0x22f282d1,//index 2 ++ 0x9592c724, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282d1,//index 3 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x06f282d1,//index 4 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ad1,//index 5 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ad3,//index 6 ++ 0x95923524, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ad7,//index 7 ++ 0x9595a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282d2,//index 8 ++ 0x95951124, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282f4,//index 9 ++ 0x95951124, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 10 ++ 0x9595a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 11 ++ 0x9599a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 12 ++ 0x959da324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 13 ++ 0x959f5924, ++ 0x80808419, ++ 0x000000f0, ++ 0x06f282e6,//index 14 ++ 0x959f5924, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ae6,//index 15 ++ 0x959f5924, //loft [35:34]=3 ++ 0x80808419, ++ 0x000000f0 ++}; ++ ++u32 wifi_rxgain_table_24g_40m_8800dcdw[64] = { ++ 0x83428151,//index 0 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x43428151,//index 1 ++ 0x96323528, ++ 0x80808419, ++ 0x000000f0, ++ 0x23428151,//index 2 ++ 0x9632c728, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428151,//index 3 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x07429951,//index 4 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d151,//index 5 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d153,//index 6 ++ 0x96323528, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d157,//index 7 ++ 0x9635a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428152,//index 8 ++ 0x96351128, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428174,//index 9 ++ 0x96351128, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 10 ++ 0x9635a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 11 ++ 0x9639a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 12 ++ 0x963da328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 13 ++ 0x963f5928, ++ 0x80808419, ++ 0x000000f0, ++ 0x07429966,//index 14 ++ 0x963f5928, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d166,//index 15 ++ 0x963f5928, ++ 0x80808419, ++ 0x000000f0 ++}; ++ ++#define RAM_LMAC_FW_ADDR 0x00150000 ++#ifdef CONFIG_DPD ++#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++extern int is_file_exist(char* name); ++#endif ++extern rf_misc_ram_lite_t dpd_res; ++ ++int aicwf_fdrv_dpd_result_apply_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", dpd_res->bit_mask[1]); ++ if (dpd_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void dpd_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == 1) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy dpd_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", dpd_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // dpd_high ++ AICWFDBG(LOGINFO, "dpd_high[0]=%x\n", dpd_res->dpd_high[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, dpd_high); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, dpd_high); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->dpd_high[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "dpd_high wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", dpd_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++ ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_fdrv_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_DPDRESULT_NAME_8800DC; ++ AICWFDBG(LOGINFO, "dpd_res file path:%s \r\n", filename); ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of dpd_res file\n"); ++ dst = NULL; ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d, dst[0]=%x\n", filename, size, dst[0]); ++ memcpy((u8 *)dpd_res, (u8 *)dst, sizeof(rf_misc_ram_lite_t)); ++ if (dst) { ++ rwnx_release_firmware_common(&dst); ++ } ++ return ret; ++} ++#endif ++#endif ++ ++#if defined(CONFIG_LOFT_CALIB) ++extern rf_misc_ram_lite_t loft_res_local; ++ ++int aicwf_fdrv_loft_result_apply_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *loft_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", loft_res->bit_mask[1]); ++ if (loft_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void loft_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == 1) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy loft_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", loft_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", loft_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++#endif ++ ++int aicwf_fdrv_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t misc_ram_size = 12; ++ int i; ++ ++ if (testmode == 1) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ // init misc ram ++ printk("%s\n", __func__); ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr); ++ for (i = 0; i < (misc_ram_size / 4); i++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, misc_ram_addr + i * 4, 0); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] wr fail: %d\n", misc_ram_addr + i * 4, ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++ ++ ++int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm){ ++ int ret = 0; ++ ++ if ((ret = rwnx_send_txpwr_lvl_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ ++ if (testmode == 0) { ++ #if !defined(CONFIG_EXT_FEM_8800DCDW) ++ if (IS_CHIP_ID_H()) { ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_h, 128))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw_h, 128))) ++ return -1; ++ } else { ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw, 128))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw, 128))) ++ return -1; ++ } ++ #else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ ++ { ++ ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_femkct, 128); ++ if (ret) { ++ return -1; ++ } ++ ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw_femkct, 128); ++ if (ret) { ++ return -1; ++ } ++ } ++ #endif ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 0, (u8_l *)wifi_rxgain_table_24g_20m_8800dcdw, 256))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 32, 0, (u8_l *)wifi_rxgain_table_24g_40m_8800dcdw, 256))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) { ++ return -1; ++ } ++ } else if (testmode == 1) { ++ if (chip_sub_id >= 1) { ++ #ifdef CONFIG_DPD ++ #ifndef CONFIG_FORCE_DPD_CALIB ++ if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 1) { ++ AICWFDBG(LOGINFO, "%s load dpd bin\n", __func__); ++ ret = aicwf_fdrv_dpd_result_load_8800dc(rwnx_hw, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ if (dpd_res.bit_mask[1]) { ++ ret = aicwf_fdrv_dpd_result_apply_8800dc(rwnx_hw, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "apply dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #elif defined(CONFIG_LOFT_CALIB) ++ if (loft_res_local.bit_mask[1]) { ++ ret = aicwf_fdrv_loft_result_apply_8800dc(rwnx_hw, &loft_res_local); ++ if (ret) { ++ AICWFDBG(LOGINFO, "apply loft res fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #else ++ { ++ ret = aicwf_fdrv_misc_ram_init_8800dc(rwnx_hw); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram init fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ ret = rwnx_send_rf_calib_req(rwnx_hw, cfm); ++ if (ret) { ++ AICWFDBG(LOGINFO, "rf calib req fail: %d\n", ret); ++ return ret; ++ } ++ } ++ } ++ ++ return 0 ; ++} ++ ++int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw){ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800DC; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing2((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ ++int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw){ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800DC; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing2((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h +new file mode 100644 +index 000000000000..249703b68389 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h +@@ -0,0 +1,15 @@ ++#include ++#include "aic_bsp_export.h" ++ ++#ifdef CONFIG_DPD ++int aicwf_fdrv_dpd_result_apply_8800dc(struct rwnx_hw * rwnx_hw, rf_misc_ram_lite_t * dpd_res); ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_fdrv_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res); ++#endif ++#endif ++int aicwf_fdrv_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw); ++int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); ++int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw); ++int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw); ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h +new file mode 100644 +index 000000000000..25a5766567eb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h +@@ -0,0 +1,56 @@ ++ ++ ++#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ ++ ++ ++ ++/* message levels */ ++#define LOGERROR 0x0001 ++#define LOGINFO 0x0002 ++#define LOGTRACE 0x0004 ++#define LOGDEBUG 0x0008 ++#define LOGDATA 0x0010 ++#define LOGIRQ 0x0020 ++#define LOGSDPWRC 0x0040 ++#define LOGWAKELOCK 0x0080 ++#define LOGRXPOLL 0x0100 ++ ++extern int aicwf_dbg_level; ++void rwnx_data_dump(char* tag, void* data, unsigned long len); ++ ++#define AICWF_LOG "AICWFDBG(" ++ ++#define AICWFDBG(level, args, arg...) \ ++do { \ ++ if (aicwf_dbg_level & level) { \ ++ printk(AICWF_LOG#level")\t" args, ##arg); \ ++ } \ ++} while (0) ++ ++#define RWNX_DBG(fmt, ...) \ ++do { \ ++ if (aicwf_dbg_level & LOGTRACE) { \ ++ printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \ ++ } \ ++} while (0) ++ ++ ++ ++#if 0 ++#define RWNX_DBG(fmt, ...) \ ++ do { \ ++ if (aicwf_dbg_level & LOGTRACE) { \ ++ printk(AICWF_LOG"LOGTRACE"")\t" fmt, ##__VA_ARGS__); \ ++ } \ ++ } while (0) ++#define AICWFDBG(args, level) \ ++do { \ ++ if (aicwf_dbg_level & level) { \ ++ printk(AICWF_LOG"(%s)\t" ,#level); \ ++ printf args; \ ++ } \ ++} while (0) ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c +new file mode 100644 +index 000000000000..59502b89a318 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c +@@ -0,0 +1,97 @@ ++#include ++#include ++#include ++#include ++#include ++#include "aicwf_rx_prealloc.h" ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct aicwf_rx_buff_list aic_rx_buff_list; ++ ++int aic_rxbuff_num_max = 30; ++ ++int aic_rxbuff_size = (64 * 512); ++ ++struct rx_buff *aicwf_prealloc_rxbuff_alloc(spinlock_t *lock) ++{ ++ unsigned long flags; ++ struct rx_buff *rxbuff = NULL; ++ ++ spin_lock_irqsave(lock, flags); ++ if (list_empty(&aic_rx_buff_list.rxbuff_list)) { ++ spin_unlock_irqrestore(lock, flags); ++ printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); ++ return NULL; ++ } else { ++ rxbuff = list_first_entry(&aic_rx_buff_list.rxbuff_list, ++ struct rx_buff, queue); ++ list_del_init(&rxbuff->queue); ++ atomic_dec(&aic_rx_buff_list.rxbuff_list_len); ++ } ++ spin_unlock_irqrestore(lock, flags); ++ //printk("len:%d\n", aic_rx_buff_list.rxbuff_list_len); ++ memset(rxbuff->data, 0, aic_rxbuff_size); ++ rxbuff->len = 0; ++ rxbuff->start = NULL; ++ rxbuff->read = NULL; ++ rxbuff->end = NULL; ++ ++ return rxbuff; ++} ++ ++void aicwf_prealloc_rxbuff_free(struct rx_buff *rxbuff, spinlock_t *lock) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(lock, flags); ++ list_add_tail(&rxbuff->queue, &aic_rx_buff_list.rxbuff_list); ++ atomic_inc(&aic_rx_buff_list.rxbuff_list_len); ++ spin_unlock_irqrestore(lock, flags); ++} ++ ++int aicwf_prealloc_init() ++{ ++ struct rx_buff *rxbuff; ++ int i = 0; ++ ++ printk("%s enter\n", __func__); ++ INIT_LIST_HEAD(&aic_rx_buff_list.rxbuff_list); ++ ++ for (i = 0 ; i < aic_rxbuff_num_max ; i++) { ++ rxbuff = kzalloc(sizeof(struct rx_buff), GFP_KERNEL); ++ if (rxbuff) { ++ rxbuff->data = kzalloc(aic_rxbuff_size, GFP_KERNEL); ++ if (rxbuff->data == NULL) { ++ printk("failed to alloc rxbuff data\n"); ++ kfree(rxbuff); ++ continue; ++ } ++ rxbuff->len = 0; ++ rxbuff->start = NULL; ++ rxbuff->read = NULL; ++ rxbuff->end = NULL; ++ list_add_tail(&rxbuff->queue, &aic_rx_buff_list.rxbuff_list); ++ atomic_inc(&aic_rx_buff_list.rxbuff_list_len); ++ } ++ } ++ ++ printk("pre alloc rxbuff list len: %d\n", (int)atomic_read(&aic_rx_buff_list.rxbuff_list_len)); ++ return 0; ++} ++ ++void aicwf_prealloc_exit() ++{ ++ struct rx_buff *rxbuff; ++ struct rx_buff *pos; ++ ++ printk("%s enter\n", __func__); ++ ++ printk("free pre alloc rxbuff list %d\n", (int)atomic_read(&aic_rx_buff_list.rxbuff_list_len)); ++ list_for_each_entry_safe(rxbuff, pos, &aic_rx_buff_list.rxbuff_list, queue) { ++ list_del_init(&rxbuff->queue); ++ kfree(rxbuff->data); ++ kfree(rxbuff); ++ } ++} ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h +new file mode 100644 +index 000000000000..64a494aeef16 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h +@@ -0,0 +1,24 @@ ++#ifndef _AICWF_RX_PREALLOC_H_ ++#define _AICWF_RX_PREALLOC_H_ ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct rx_buff { ++ struct list_head queue; ++ unsigned char *data; ++ u32 len; ++ uint8_t *start; ++ uint8_t *end; ++ uint8_t *read; ++}; ++ ++struct aicwf_rx_buff_list { ++ struct list_head rxbuff_list; ++ atomic_t rxbuff_list_len; ++}; ++ ++struct rx_buff *aicwf_prealloc_rxbuff_alloc(spinlock_t *lock); ++void aicwf_prealloc_rxbuff_free(struct rx_buff *rxbuff, spinlock_t *lock); ++int aicwf_prealloc_init(void); ++void aicwf_prealloc_exit(void); ++#endif ++#endif /* _AICWF_RX_PREALLOC_H_ */ +\ No newline at end of file +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c +new file mode 100644 +index 000000000000..0c0fa323b3de +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c +@@ -0,0 +1,3462 @@ ++/** ++ * aicwf_sdmmc.c ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aicwf_txrxif.h" ++#include "aicwf_sdio.h" ++#include "sdio_host.h" ++#include "rwnx_defs.h" ++#include "rwnx_platform.h" ++#include "aicwf_rx_prealloc.h" ++#include "rwnx_msg_tx.h" ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#else ++#include ++#endif ++#include "rwnx_wakelock.h" ++ ++#ifdef CONFIG_INGENIC_T20 ++#include "mach/jzmmc.h" ++#endif /* CONFIG_INGENIC_T20 */ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#include ++#endif ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#include ++#endif ++ ++#include "aic_bsp_export.h" ++extern uint8_t scanning; ++ ++#ifdef CONFIG_SDIO_ADMA ++unsigned char sdio_tx_buf_fill[512]; ++unsigned char sdio_tx_buf_dummy[SDIO_TX_SLIST_MAX][8]; ++#endif ++ ++#ifdef CONFIG_GPIO_WAKEUP ++extern int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter); ++ ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++#include ++void rwnx_init_wifi_suspend_node(void); ++void rwnx_deinit_wifi_suspend_node(void); ++void rwnx_set_wifi_suspend(char onoff); ++struct proc_dir_entry *wifi_suspend_node; ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ ++#endif//CONFIG_GPIO_WAKEUP ++ ++int tx_aggr_counter = 32; ++module_param_named(tx_aggr_counter, tx_aggr_counter, int, 0644); ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++int tx_fc_low_water = AICWF_SDIO_TX_LOW_WATER; ++module_param_named(tx_fc_low_water, tx_fc_low_water, int, 0644); ++ ++int tx_fc_high_water = AICWF_SDIO_TX_HIGH_WATER; ++module_param_named(tx_fc_high_water, tx_fc_high_water, int, 0644); ++#endif ++ ++#if 0 ++void rwnx_data_dump(char* tag, void* data, unsigned long len){ ++ if(dump){ ++ unsigned long i = 0; ++ uint8_t* data_ = (uint8_t* )data; ++ ++ printk("%s %s len:(%lu)\r\n", __func__, tag, len); ++ ++ for (i = 0; i < len; i += 16){ ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", ++ data_[0 + i], ++ data_[1 + i], ++ data_[2 + i], ++ data_[3 + i], ++ data_[4 + i], ++ data_[5 + i], ++ data_[6 + i], ++ data_[7 + i], ++ data_[8 + i], ++ data_[9 + i], ++ data_[10 + i], ++ data_[11 + i], ++ data_[12 + i], ++ data_[13 + i], ++ data_[14 + i], ++ data_[15 + i]); ++ } ++ } ++} ++#endif ++ ++int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ *val = sdio_readb(sdiodev->func, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ sdio_writeb(sdiodev->func, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_func2_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func2); ++ *val = sdio_readb(sdiodev->func2, regaddr, &ret); ++ sdio_release_host(sdiodev->func2); ++ return ret; ++} ++ ++int aicwf_sdio_func2_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func2); ++ sdio_writeb(sdiodev->func2, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func2); ++ return ret; ++} ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++void aicwf_sdio_tx_netif_flowctrl(struct rwnx_hw *rwnx_hw, bool state) ++{ ++ struct rwnx_vif *rwnx_vif; ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (! rwnx_vif->up) ++ continue; ++ if (state) ++ netif_tx_stop_all_queues(rwnx_vif->ndev);//netif_stop_queue(rwnx_vif->ndev); ++ else ++ netif_tx_wake_all_queues(rwnx_vif->ndev);//netif_wake_queue(rwnx_vif->ndev); ++ } ++} ++#endif ++ ++#ifdef CONFIG_TEMP_CONTROL ++//int interval = 30; ++//module_param(interval, int, 0660); ++static int update_state(s8_l value, u8_l current_state) ++{ ++ if (value > TEMP_THD_2) ++ return 2; ++ else if (value > (TEMP_THD_2 - BUFFERING_V2) && (current_state == 2)) ++ return 2; ++ else if (value > TEMP_THD_1 && current_state != 2) ++ return 1; ++ else if (value > (TEMP_THD_1 - BUFFERING_V1) && current_state == 1) ++ return 1; ++ else if (current_state == 0) ++ return 0; ++ else ++ return 1; ++} ++ ++void aicwf_netif_ctrl(struct aic_sdio_dev *sdiodev, int val) ++{ ++ unsigned long flags; ++ struct rwnx_vif *rwnx_vif; ++ ++ if (sdiodev->net_stop) ++ return; ++ ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ list_for_each_entry(rwnx_vif, &sdiodev->rwnx_hw->vifs, list) { ++ if (!rwnx_vif || !rwnx_vif->ndev || !rwnx_vif->up) ++ continue; ++ netif_tx_stop_all_queues(rwnx_vif->ndev);//netif_stop_queue(rwnx_vif->ndev); ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++ sdiodev->net_stop = true; ++ mod_timer(&sdiodev->netif_timer, jiffies + msecs_to_jiffies(val)); ++ ++ return; ++} ++ ++void aicwf_temp_ctrl(struct aic_sdio_dev *sdiodev) ++{ ++ if (sdiodev->set_level) { ++ if (sdiodev->set_level == 1) { ++ sdiodev->get_level = 1; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t1/*TMR_INTERVAL_1*/); ++ //mdelay(1); ++ } else if (sdiodev->set_level == 2) { ++ sdiodev->get_level = 2; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t2/*TMR_INTERVAL_2*/); ++ //mdelay(2); ++ } ++ return; ++ } else { ++ if (sdiodev->cur_temp > (TEMP_THD_1 - 8)) { ++ //if ((sdiodev->cur_temp > TEMP_THD_1 && sdiodev->cur_temp <= TEMP_THD_2) || (sdiodev->cur_stat == 1)) { ++ if (update_state(sdiodev->cur_temp, sdiodev->cur_stat) == 1) { ++ sdiodev->get_level = 1; ++ sdiodev->cur_stat = 1; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t1/*TMR_INTERVAL_1*/); ++ //mdelay(1); ++ //break; ++ //} else if ((sdiodev->cur_temp > TEMP_THD_2) || (sdiodev->cur_stat == 2)) { ++ } else if (update_state(sdiodev->cur_temp, sdiodev->cur_stat) == 2) { ++ sdiodev->get_level = 2; ++ sdiodev->cur_stat = 2; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t2/*TMR_INTERVAL_2*/); ++ //mdelay(2); ++ //break; ++ } ++ return; ++ } ++ ++ if (sdiodev->cur_stat) { ++ AICWFDBG(LOGINFO, "reset cur_stat"); ++ sdiodev->cur_stat = 0; ++ } ++ ++ return; ++ } ++} ++ ++void aicwf_netif_worker(struct work_struct *work) ++{ ++ struct aic_sdio_dev *sdiodev = container_of(work, struct aic_sdio_dev, netif_work); ++ unsigned long flags; ++ struct rwnx_vif *rwnx_vif; ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ list_for_each_entry(rwnx_vif, &sdiodev->rwnx_hw->vifs, list) { ++ if (!rwnx_vif || !rwnx_vif->ndev || !rwnx_vif->up) ++ continue; ++ netif_tx_wake_all_queues(rwnx_vif->ndev);//netif_wake_queue(rwnx_vif->ndev); ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++ sdiodev->net_stop = false; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++static void aicwf_netif_timer(ulong data) ++#else ++static void aicwf_netif_timer(struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, netif_timer); ++#endif ++ ++ if (!work_pending(&sdiodev->netif_work)) ++ schedule_work(&sdiodev->netif_work); ++ ++ return; ++} ++ ++void aicwf_temp_ctrl_worker(struct work_struct *work) ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct mm_set_vendor_swconfig_cfm cfm; ++ struct aic_sdio_dev *sdiodev = container_of(work, struct aic_sdio_dev, tp_ctrl_work); ++ rwnx_hw = sdiodev->rwnx_hw; ++ //AICWFDBG(LOGINFO, "%s\n", __func__); ++ ++ rwnx_hw->started_jiffies = jiffies; ++ ++ rwnx_send_get_temp_req(rwnx_hw, &cfm); ++ sdiodev->cur_temp = cfm.temp_comp_get_cfm.degree; ++ ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++ ++ return; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++static void aicwf_temp_ctrl_timer(ulong data) ++#else ++static void aicwf_temp_ctrl_timer(struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, tp_ctrl_timer); ++#endif ++ ++ if (!work_pending(&sdiodev->tp_ctrl_work)) ++ schedule_work(&sdiodev->tp_ctrl_work); ++ ++ return; ++} ++#endif ++ ++int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = -1; ++ u8 fc_reg = 0; ++ u32 count = 0; ++ ++ while (true) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.flow_ctrl_reg, &fc_reg); ++ if (ret) { ++ return -1; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ fc_reg = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; ++ } ++ ++ if (fc_reg != 0) { ++ ret = fc_reg; ++ if(ret > tx_aggr_counter){ ++ ret = tx_aggr_counter; ++ } ++ return ret; ++ } else { ++ if (count >= FLOW_CTRL_RETRY_COUNT) { ++ ret = -fc_reg; ++ break; ++ } ++ count++; ++ if (count < 30) ++ udelay(200); ++ else if(count < 40) ++ msleep(2); ++ else ++ msleep(10); ++ } ++ } ++ ++ return ret; ++} ++ ++ ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = -1; ++ u8 fc_reg = 0; ++ u32 count = 0; ++ ++ while (true) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.flow_ctrl_reg, &fc_reg); ++ if (ret) { ++ return -1; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ fc_reg = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; ++ } ++ ++ if (fc_reg > DATA_FLOW_CTRL_THRESH) { ++ ret = fc_reg; ++ if(ret > tx_aggr_counter){ ++ ret = tx_aggr_counter; ++ } ++ return ret; ++ } else { ++ if (count >= FLOW_CTRL_RETRY_COUNT) { ++ ret = -fc_reg; ++ break; ++ } ++ count++; ++ if (count < 30) ++ udelay(200); ++ else if(count < 40) ++ msleep(2); ++ else ++ msleep(10); ++ } ++ } ++ ++ return ret; ++} ++ ++ ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) ++{ ++ int ret = 0; ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, buf, count); ++ sdio_release_host(sdiodev->func); ++ ++ return ret; ++} ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct rx_buff *rxbuff, ++ u32 size) ++{ ++ int ret; ++ ++ if ((!rxbuff->data) || (!size)) { ++ return -EINVAL;; ++ } ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_readsb(sdiodev->func, rxbuff->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ rxbuff->len = size; ++ ++ return ret; ++} ++#else ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, ++ u32 size) ++{ ++ int ret; ++ ++ if ((!skbbuf) || (!size)) { ++ return -EINVAL;; ++ } ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_readsb(sdiodev->func, skbbuf->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ skbbuf->len = size; ++ ++ return ret; ++} ++#endif ++ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++static int wakeup_enable; ++static u32 hostwake_irq_num; ++#endif//CONFIG_GPIO_WAKEUP ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)//LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++//static struct wakeup_source *ws_rx_sdio; ++//static struct wakeup_source *ws_sdio_pwrctrl; ++//static struct wakeup_source *ws_tx_sdio; ++#ifdef CONFIG_GPIO_WAKEUP ++//static struct wakeup_source *ws; ++#endif ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++#include ++static struct wake_lock irq_wakelock; ++//struct wake_lock irq_wakelock; ++#endif//CONFIG_GPIO_WAKEUP ++#endif//ANDROID_PLATFORM ++#endif ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++extern int sunxi_wlan_get_oob_irq(int *, int *); ++#else ++extern int sunxi_wlan_get_oob_irq(void); ++extern int sunxi_wlan_get_oob_irq_flags(void); ++#endif ++#endif// CONFIG_PLATFORM_ALLWINNER ++ ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static struct wakeup_source *ws; ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++#include ++static struct wake_lock irq_wakelock; ++#endif//CONFIG_GPIO_WAKEUP ++#endif//ANDROID_PLATFORM ++#endif ++#endif ++ ++#if 0 ++void rwnx_pm_stay_awake(struct aic_sdio_dev *sdiodev){ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ spin_lock_bh(&sdiodev->wslock); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if(ws != NULL){ ++ __pm_stay_awake(ws); ++ AICWFDBG(LOGWAKELOCK, "%s active_count:%d relax_count:%d\r\n", __func__, (int)ws->active_count, (int)ws->relax_count); ++ } ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++ wake_lock(&irq_wakelock); ++#endif //CONFIG_GPIO_WAKEUP ++#endif //ANDROID_PLATFORM ++#endif ++ ++ spin_unlock_bh(&sdiodev->wslock); ++#endif ++} ++ ++void rwnx_pm_relax(struct aic_sdio_dev *sdiodev){ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ spin_lock_bh(&sdiodev->wslock); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if(ws != NULL){ ++ __pm_relax(ws); ++ AICWFDBG(LOGWAKELOCK, "%s active_count:%d relax_count:%d\r\n", __func__, (int)ws->active_count, (int)ws->relax_count); ++ } ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++ wake_unlock(&irq_wakelock); ++#endif //CONFIG_GPIO_WAKEUP ++#endif //ANDROID_PLATFORM ++#endif ++ spin_unlock_bh(&sdiodev->wslock); ++#endif ++ ++} ++#endif ++ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ ++void rwnx_set_wifi_suspend(char onoff); ++ ++ ++static irqreturn_t rwnx_hostwake_irq_handler(int irq, void *para) ++{ ++ static int wake_cnt; ++ wake_cnt++; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ rwnx_wakeup_lock_timeout(g_rwnx_plat->sdiodev->rwnx_hw->ws_rx, 1000); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_timeout(&irq_wakelock, HZ); ++#endif //ANDROID_PLATFORM ++#endif ++ ++ AICWFDBG(LOGIRQ, "%s(%d): wake_irq_cnt = %d\n", __func__, __LINE__, wake_cnt); ++ ++#ifdef CONFIG_OOB ++#if 0//old oob feature ++ complete(&g_rwnx_plat->sdiodev->bus_if->busrx_trgg); ++#else//new oob feature ++ if(g_rwnx_plat->sdiodev->oob_enable){ ++ complete(&g_rwnx_plat->sdiodev->bus_if->busirq_trgg); ++ } ++#endif//old oob feature ++#endif ++ ++ return IRQ_HANDLED; ++} ++#endif//CONFIG_GPIO_WAKEUP ++ ++#ifdef CONFIG_GPIO_WAKEUP ++static int rwnx_disable_hostwake_irq(void); ++static int rwnx_enable_hostwake_irq(void); ++#endif ++ ++static int rwnx_register_hostwake_irq(struct device *dev) ++{ ++ int ret = 0;//-1; ++#ifdef CONFIG_GPIO_WAKEUP ++ unsigned long flag_edge; ++ struct aicbsp_feature_t aicwf_feature; ++ int irq_flags; ++//TODO hostwake_irq_num hostwake_irq_num and wakeup_enable ++ ++ aicbsp_get_feature(&aicwf_feature, NULL); ++ if (aicwf_feature.irqf == 0) ++ flag_edge = IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND; ++ else ++ flag_edge = IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND; ++ ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ hostwake_irq_num = sunxi_wlan_get_oob_irq(&irq_flags, &wakeup_enable); ++#else ++ hostwake_irq_num = sunxi_wlan_get_oob_irq(); ++ irq_flags = sunxi_wlan_get_oob_irq_flags(); ++ wakeup_enable = 1; ++#endif ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++//For Rockchip ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ hostwake_irq_num = rockchip_wifi_get_oob_irq(); ++ printk("%s hostwake_irq_num:%d \r\n", __func__, hostwake_irq_num); ++ irq_flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE) & IRQF_TRIGGER_MASK; ++ printk("%s irq_flags:%d \r\n", __func__, irq_flags); ++ wakeup_enable = 1; ++#endif //CONFIG_PLATFORM_ROCKCHIP ++ //For Rockchip ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ hostwake_irq_num = rockchip_wifi_get_oob_irq(); ++ printk("%s hostwake_irq_num:%d \r\n", __func__, hostwake_irq_num); ++ irq_flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE) & IRQF_TRIGGER_MASK; ++ printk("%s irq_flags:%d \r\n", __func__, irq_flags); ++ wakeup_enable = 1; ++#endif //CONFIG_PLATFORM_ROCKCHIP ++ ++ ++ ++ if (wakeup_enable) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ //ws = wakeup_source_register(dev, "wifisleep"); ++ //ws_tx_sdio = wakeup_source_register(dev, "wifi_tx_sleep"); ++ //ws_rx_sdio = wakeup_source_register(dev, "wifi_rx_sleep"); ++ //ws_sdio_pwrctrl = wakeup_source_register(dev, "sdio_pwrctrl_sleep"); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_init(&irq_wakelock, WAKE_LOCK_SUSPEND, "wifisleep"); ++#endif ++#endif ++ ret = device_init_wakeup(dev, true); ++ if (ret < 0) { ++ pr_err("%s(%d): device init wakeup failed!\n", __func__, __LINE__); ++ return ret; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ ret = dev_pm_set_wake_irq(dev, hostwake_irq_num); ++#endif ++ if (ret < 0) { ++ pr_err("%s(%d): can't enable wakeup src!\n", __func__, __LINE__); ++ goto fail1; ++ } ++ ++ ret = request_irq(hostwake_irq_num, rwnx_hostwake_irq_handler, flag_edge, "rwnx_hostwake_irq", NULL); ++ ++ if (ret < 0) { ++ pr_err("%s(%d): request_irq fail! ret = %d\n", __func__, __LINE__, ret); ++ goto fail2; ++ } ++ } ++ //disable_irq(hostwake_irq_num); ++ rwnx_disable_hostwake_irq(); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ dev_pm_clear_wake_irq(dev); ++#endif ++ rwnx_enable_hostwake_irq(); ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++ return ret; ++ ++fail2: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ dev_pm_clear_wake_irq(dev); ++#endif ++fail1: ++ device_init_wakeup(dev, false); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ //wakeup_source_unregister(ws); ++ //wakeup_source_unregister(ws_tx_sdio); ++ //wakeup_source_unregister(ws_rx_sdio); ++ //wakeup_source_unregister(ws_sdio_pwrctrl); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_destroy(&irq_wakelock); ++#endif ++#endif ++#endif//CONFIG_GPIO_WAKEUP ++ return ret; ++} ++ ++static int rwnx_unregister_hostwake_irq(struct device *dev) ++{ ++#ifdef CONFIG_GPIO_WAKEUP ++ rwnx_disable_hostwake_irq(); ++ if (wakeup_enable) { ++ device_init_wakeup(dev, false); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ dev_pm_clear_wake_irq(dev); ++#else ++ AICWFDBG(LOGERROR, "%s kernel unsupport this feature!\r\n", __func__); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ //wakeup_source_unregister(ws); ++ //wakeup_source_unregister(ws_tx_sdio); ++ //wakeup_source_unregister(ws_rx_sdio); ++ //wakeup_source_unregister(ws_sdio_pwrctrl); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_destroy(&irq_wakelock); ++#endif //ANDROID_PLATFORM ++#endif ++ } ++ free_irq(hostwake_irq_num, NULL); ++#endif//CONFIG_GPIO_WAKEUP ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++ return 0; ++} ++ ++#ifdef CONFIG_GPIO_WAKEUP ++static int rwnx_enable_hostwake_irq(void) ++{ ++#ifdef CONFIG_GPIO_WAKEUP ++ enable_irq(hostwake_irq_num); ++ enable_irq_wake(hostwake_irq_num); ++#endif//CONFIG_GPIO_WAKEUP ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++ return 0; ++} ++ ++static int rwnx_disable_hostwake_irq(void) ++{ ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++#ifdef CONFIG_GPIO_WAKEUP ++ disable_irq_nosync(hostwake_irq_num); ++ //disable_irq_wake(hostwake_irq_num); ++ //disable_irq(hostwake_irq_num); ++#endif//CONFIG_GPIO_WAKEUP ++ return 0; ++} ++#endif ++ ++static int aicwf_sdio_chipmatch(struct aic_sdio_dev *sdio_dev, u16_l vid, u16_l did){ ++ ++ if(vid == SDIO_VENDOR_ID_AIC8801 && did == SDIO_DEVICE_ID_AIC8801){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8801; ++ AICWFDBG(LOGINFO, "%s USE AIC8801\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800DC && did == SDIO_DEVICE_ID_AIC8800DC){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800DC; ++ AICWFDBG(LOGINFO, "%s USE AIC8800DC\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80 && did == SDIO_DEVICE_ID_AIC8800D80){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80X2 && did == SDIO_DEVICE_ID_AIC8800D80X2){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80X2; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80X2\r\n", __func__); ++ return 0; ++ }else{ ++ return -1; ++ } ++} ++ ++ ++extern int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter); ++ ++static int aicwf_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ struct mmc_host *host; ++ struct aic_sdio_dev *sdiodev; ++ struct aicwf_bus *bus_if; ++ int err = -ENODEV; ++ ++ AICWFDBG(LOGDEBUG, "%s:%d\n", __func__, func->num); ++ AICWFDBG(LOGDEBUG, "Class=%x\n", func->class); ++ AICWFDBG(LOGDEBUG, "sdio vendor ID: 0x%04x\n", func->vendor); ++ AICWFDBG(LOGDEBUG, "sdio device ID: 0x%04x\n", func->device); ++ AICWFDBG(LOGDEBUG, "Function#: %d\n", func->num); ++ ++ host = func->card->host; ++ if (func->num != 1) { ++ return err; ++ } ++ ++ bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_KERNEL); ++ if (!bus_if) { ++ sdio_err("alloc bus fail\n"); ++ return -ENOMEM; ++ } ++ ++ sdiodev = kzalloc(sizeof(struct aic_sdio_dev), GFP_KERNEL); ++ if (!sdiodev) { ++ sdio_err("alloc sdiodev fail\n"); ++ kfree(bus_if); ++ return -ENOMEM; ++ } ++ ++ ++ err = aicwf_sdio_chipmatch(sdiodev, func->vendor, func->device); ++ ++ sdiodev->func = func; ++ sdiodev->bus_if = bus_if; ++ ++#ifdef CONFIG_OOB ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "%s ERROR!!! 8801 not support OOB \r\n", __func__); ++ sdiodev->oob_enable = false; ++ }else{ ++ sdiodev->oob_enable = true; ++ } ++#else ++ sdiodev->oob_enable = false; ++#endif ++ ++ atomic_set(&sdiodev->is_bus_suspend, 0); ++ bus_if->bus_priv.sdio = sdiodev; ++ ++ dev_set_drvdata(&func->dev, bus_if); ++ sdiodev->dev = &func->dev; ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ sdiodev->func2 = func->card->sdio_func[1]; ++ } ++ ++ //sdio func init start ++ if (sdiodev->chipid != PRODUCT_ID_AIC8800D80 && sdiodev->chipid != PRODUCT_ID_AIC8800D80X2) { ++ err = aicwf_sdio_func_init(sdiodev); ++ } else { ++ err = aicwf_sdiov3_func_init(sdiodev); ++ } ++ if (err < 0) { ++ sdio_err("sdio func init fail\n"); ++ goto fail; ++ } ++ //sdio func init end ++ ++ if (aicwf_sdio_bus_init(sdiodev) == NULL) { ++ sdio_err("sdio bus init fail\n"); ++ err = -1; ++ goto fail; ++ } ++ ++ host->caps |= MMC_CAP_NONREMOVABLE; ++ aicwf_rwnx_sdio_platform_init(sdiodev); ++ aicwf_hostif_ready(); ++ err = rwnx_register_hostwake_irq(sdiodev->dev); ++ if (err != 0) ++ return err; ++ ++#ifdef CONFIG_GPIO_WAKEUP ++#ifdef CONFIG_OOB ++ if(sdiodev->oob_enable){ ++ AICWFDBG(LOGINFO, "%s SDIOWIFI_INTR_CONFIG_REG Disable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ err = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x0); ++ if (err < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_INTR_CONFIG_REG); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++#if 0 ++#if 0//old oob feature ++ sdiodev->oob_enable = true; ++#else//new oob feature ++ sdiodev->oob_enable = true; ++#endif//old oob feature ++#endif ++ } ++#endif ++ ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++ rwnx_init_wifi_suspend_node(); ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++#endif//CONFIG_GPIO_WAKEUP ++ device_disable_async_suspend(sdiodev->dev); ++ ++ return 0; ++fail: ++ aicwf_sdio_func_deinit(sdiodev); ++ dev_set_drvdata(&func->dev, NULL); ++ kfree(sdiodev); ++ kfree(bus_if); ++ aicwf_hostif_fail(); ++ return err; ++} ++ ++void aicwf_sdio_probe_(struct sdio_func *func, ++ const struct sdio_device_id *id){ ++ aicwf_sdio_probe(func, NULL); ++} ++ ++ ++static void aicwf_sdio_remove(struct sdio_func *func) ++{ ++ struct mmc_host *host; ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_sdio_dev *sdiodev = NULL; ++ ++ AICWFDBG(LOGINFO, "%s Enter\n", __func__); ++ host = func->card->host; ++ host->caps &= ~MMC_CAP_NONREMOVABLE; ++ bus_if = dev_get_drvdata(&func->dev); ++ if (!bus_if) { ++ return; ++ } ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ if (!sdiodev) { ++ return; ++ } ++ ++ sdiodev->bus_if->state = BUS_DOWN_ST; ++ aicwf_sdio_release(sdiodev); ++ aicwf_sdio_func_deinit(sdiodev); ++ rwnx_unregister_hostwake_irq(sdiodev->dev); ++ dev_set_drvdata(&sdiodev->func->dev, NULL); ++ kfree(sdiodev); ++ kfree(bus_if); ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++ rwnx_deinit_wifi_suspend_node(); ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ AICWFDBG(LOGINFO, "%s done\n", __func__); ++} ++ ++void aicwf_sdio_remove_(struct sdio_func *func){ ++ aicwf_sdio_remove(func); ++} ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_SHUTDOWN_CALLBACK ++int rwnx_close_(struct net_device *dev); ++ ++void aicwf_sdio_shutdown(struct device *dev) ++{ ++ struct rwnx_vif *rwnx_vif, *tmp; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ AICWFDBG(LOGINFO, "%s Enter", __func__); ++ list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { ++ if (rwnx_vif->ndev && test_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags)){ ++ AICWFDBG(LOGINFO, "%s rwnx_close by shutdown", __func__); ++ rwnx_close_(rwnx_vif->ndev); ++ ++ }else{ ++ if(!rwnx_vif->ndev){ ++ AICWFDBG(LOGERROR, "%s rwnx_vif->ndev is NULL \r\n", __func__); ++ } ++ if(!test_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags)){ ++ AICWFDBG(LOGERROR, "%s rwnx_vif->drv_flags close\r\n", __func__); ++ } ++ } ++ ++ } ++ AICWFDBG(LOGINFO, "%s Exit", __func__); ++ ++} ++#endif ++#endif ++ ++#if defined(CONFIG_AUTO_POWERSAVE) ++static int aicwf_wakeup_lock_status(struct rwnx_hw *rwnx_hw) ++{ ++ if(rwnx_hw->ws_tx && rwnx_hw->ws_tx->active) ++ return -1; ++ ++ if(rwnx_hw->ws_rx && rwnx_hw->ws_rx->active) ++ return -1; ++ ++ if(rwnx_hw->ws_pwrctrl && rwnx_hw->ws_pwrctrl->active) ++ return -1; ++ ++ if(rwnx_hw->ws_irqrx && rwnx_hw->ws_irqrx->active) ++ return -1; ++ ++ return 0; ++} ++#endif ++ ++static int aicwf_sdio_suspend(struct device *dev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ mmc_pm_flag_t sdio_flags; ++ struct rwnx_vif *rwnx_vif, *tmp; ++ ++ sdio_dbg("%s enter\n", __func__); ++ ++ list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { ++ if (rwnx_vif->ndev) ++ netif_device_detach(rwnx_vif->ndev); ++ } ++ ++ sdio_flags = sdio_get_host_pm_caps(sdiodev->func); ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ return -EINVAL; ++ } ++ ret = sdio_set_host_pm_flags(sdiodev->func, MMC_PM_KEEP_POWER); ++ if (ret) { ++ return ret; ++ } ++ ++#ifdef CONFIG_TEMP_CONTROL ++ del_timer_sync(&sdiodev->tp_ctrl_timer); ++ cancel_work_sync(&sdiodev->tp_ctrl_work); ++ ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++ ++ del_timer_sync(&sdiodev->netif_timer); ++ cancel_work_sync(&sdiodev->netif_work); ++#endif ++ ++#if (defined(CONFIG_AUTO_POWERSAVE) && defined(CONFIG_SDIO_PWRCTRL)) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ ++ if((sdiodev->chipid == PRODUCT_ID_AIC8800D80) || (sdiodev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ sdio_dbg("autops set\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x8); ++ if(ret) { ++ sdio_err("sdio set autops fail\n"); ++ } ++ } ++#endif ++ ++ #if (!defined(CONFIG_AUTO_POWERSAVE)) ++ while (sdiodev->state == SDIO_ACTIVE_ST) { ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) ++ continue; ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ #endif ++ up(&sdiodev->tx_priv->txctl_sema); ++ break; ++ } ++ #else ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ #endif ++ #endif ++#ifdef CONFIG_GPIO_WAKEUP ++// rwnx_enable_hostwake_irq(); ++#endif ++ ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ sdio_dbg("%s SDIOWIFI_INTR_CONFIG_REG Disable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_INTR_CONFIG_REG); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++#endif ++ atomic_set(&sdiodev->is_bus_suspend, 1); ++// smp_mb(); ++ ++#if defined(CONFIG_AUTO_POWERSAVE) ++ if(aicwf_wakeup_lock_status(sdiodev->rwnx_hw)) { ++ printk("%s ws active dont suspend", __func__); ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ ++ if((sdiodev->chipid == PRODUCT_ID_AIC8800D80) || (sdiodev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ sdio_dbg("autops clear\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x8); ++ if(ret) { ++ sdio_err("sdio clear autops fail\n"); ++ } ++ } ++ ++ return -EBUSY; ++ } ++#endif ++ ++ sdio_dbg("%s exit\n", __func__); ++ ++ return 0; ++} ++ ++static int aicwf_sdio_resume(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ struct rwnx_vif *rwnx_vif, *tmp; ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_AUTO_POWERSAVE) ++ int ret; ++#endif ++ ++ sdio_dbg("%s enter \n", __func__); ++ ++#ifdef CONFIG_TEMP_CONTROL ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++#endif ++ ++//#ifdef CONFIG_GPIO_WAKEUP ++// rwnx_disable_hostwake_irq(); ++//#endif ++ //dev_pm_clear_wake_irq(dev); ++ list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { ++ if (rwnx_vif->ndev) ++ netif_device_attach(rwnx_vif->ndev); ++ } ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ #endif ++ ++#if defined(CONFIG_AUTO_POWERSAVE) && defined(CONFIG_SDIO_PWRCTRL) ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ sdio_dbg("autops clear\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x8); ++ if(ret) { ++ sdio_err("sdio clear autops fail\n"); ++ } ++ } ++#endif ++ ++// aicwf_sdio_hal_irqhandler(sdiodev->func); ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ sdio_dbg("%s SDIOWIFI_INTR_CONFIG_REG Enable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ sdio_release_host(sdiodev->func); ++ } ++#endif ++ atomic_set(&sdiodev->is_bus_suspend, 0); ++// smp_mb(); ++ #ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++ rwnx_set_wifi_suspend('0'); ++ #endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ ++ ++ sdio_dbg("%s exit\n", __func__); ++ return 0; ++} ++ ++static const struct sdio_device_id aicwf_sdmmc_ids[] = { ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8801, SDIO_DEVICE_ID_AIC8801)}, ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8800DC, SDIO_DEVICE_ID_AIC8800DC)}, ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8800D80, SDIO_DEVICE_ID_AIC8800D80)}, ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8800D80X2, SDIO_DEVICE_ID_AIC8800D80X2)}, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(sdio, aicwf_sdmmc_ids); ++ ++static const struct dev_pm_ops aicwf_sdio_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(aicwf_sdio_suspend, aicwf_sdio_resume) ++}; ++ ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++static struct sdio_driver aicwf_sdio_driver = { ++ .probe = aicwf_sdio_probe, ++ .remove = aicwf_sdio_remove, ++ .name = AICWF_SDIO_NAME, ++ .id_table = aicwf_sdmmc_ids, ++ .drv = { ++ .pm = &aicwf_sdio_pm_ops, ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_SHUTDOWN_CALLBACK ++ .shutdown = aicwf_sdio_shutdown, ++#endif ++#endif ++ }, ++}; ++#endif ++ ++#if 0 ++#ifdef CONFIG_NANOPI_M4 ++extern int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq); ++extern unsigned aic_max_freqs; ++extern struct mmc_host *aic_host_drv; ++extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); ++extern void mmc_release_host(struct mmc_host *host); ++#endif ++#endif ++ ++#ifdef CONFIG_FDRV_NO_REG_SDIO ++extern struct sdio_func *get_sdio_func(void); ++void aicwf_sdio_probe_(struct sdio_func *func, const struct sdio_device_id *id); ++void aicwf_sdio_remove_(struct sdio_func *func); ++#endif ++ ++void aicwf_sdio_register(void) ++{ ++#if 0 ++#ifdef CONFIG_PLATFORM_NANOPI ++ extern_wifi_set_enable(0); ++ mdelay(200); ++ extern_wifi_set_enable(1); ++ mdelay(200); ++ sdio_reinit(); ++#endif /*CONFIG_PLATFORM_NANOPI*/ ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ rockchip_wifi_power(0); ++ mdelay(200); ++ rockchip_wifi_power(1); ++ mdelay(200); ++ rockchip_wifi_set_carddetect(1); ++#endif /*CONFIG_PLATFORM_ROCKCHIP*/ ++ ++#ifdef CONFIG_INGENIC_T20 ++ jzmmc_manual_detect(1, 1); ++#endif /* CONFIG_INGENIC_T20 */ ++ ++ ++#ifdef CONFIG_NANOPI_M4 ++ if (aic_host_drv->card == NULL) { ++ __mmc_claim_host(aic_host_drv, NULL); ++ printk("aic: >>>mmc_rescan_try_freq\n"); ++ mmc_rescan_try_freq(aic_host_drv, aic_max_freqs); ++ mmc_release_host(aic_host_drv); ++ } ++#endif ++#endif ++ ++ ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ if (sdio_register_driver(&aicwf_sdio_driver)) { ++ ++ } else { ++ //may add mmc_rescan here ++ } ++#else ++ aicwf_sdio_probe_(get_sdio_func(), NULL); ++#endif ++} ++ ++void aicwf_sdio_exit(void) ++{ ++ if (g_rwnx_plat && g_rwnx_plat->enabled){ ++#ifdef CONFIG_TEMP_CONTROL ++ if (timer_pending(&g_rwnx_plat->sdiodev->tp_ctrl_timer)) { ++ AICWFDBG(LOGINFO, "%s del tp_ctrl_timer\n", __func__); ++ del_timer_sync(&g_rwnx_plat->sdiodev->tp_ctrl_timer); ++ } ++ cancel_work_sync(&g_rwnx_plat->sdiodev->tp_ctrl_work); ++ ++ if (timer_pending(&g_rwnx_plat->sdiodev->netif_timer)) { ++ AICWFDBG(LOGINFO, "%s del netif_timer\n", __func__); ++ del_timer_sync(&g_rwnx_plat->sdiodev->netif_timer); ++ } ++ cancel_work_sync(&g_rwnx_plat->sdiodev->netif_work); ++#endif ++ rwnx_platform_deinit(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else{ ++ AICWFDBG(LOGERROR, "%s g_rwnx_plat is not ready \r\n", __func__); ++ } ++ ++ udelay(500); ++ ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ sdio_unregister_driver(&aicwf_sdio_driver); ++#else ++ aicwf_sdio_remove_(get_sdio_func()); ++#endif ++ ++#if 0 ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++#endif /*CONFIG_PLATFORM_AMLOGIC*/ ++#endif ++ ++#if 0 ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ rockchip_wifi_set_carddetect(0); ++ mdelay(200); ++ rockchip_wifi_power(0); ++ mdelay(200); ++#endif /*CONFIG_PLATFORM_ROCKCHIP*/ ++#endif ++ ++ if(g_rwnx_plat){ ++ kfree(g_rwnx_plat); ++ } ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++int aicwf_sdio_wakeup(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ int read_retry; ++ int write_retry = 1; ++ int wakeup_reg_val = 0; ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ wakeup_reg_val = 1; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ wakeup_reg_val = 0x11; ++ } ++ ++ if (sdiodev->state == SDIO_SLEEP_ST) { ++ AICWFDBG(LOGSDPWRC, "%s w\n", __func__); ++ ++ //rwnx_pm_stay_awake(sdiodev); ++ ++ while (write_retry) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, wakeup_reg_val); ++ if (ret) { ++ txrx_err("sdio wakeup fail\n"); ++ ret = -1; ++ } else { ++ read_retry = 50; ++ while (read_retry) { ++ u8 val; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.wakeup_reg, &val); ++ if (ret < 0) ++ txrx_err("sdio wakeup read fail\n"); ++ else if ((val & 0x1) == 0) { ++ break; ++ } ++ read_retry--; ++ udelay(200); ++ } ++ if (read_retry != 0) ++ break; ++ } ++ sdio_dbg("write retry: %d \n", write_retry); ++ write_retry--; ++ udelay(100); ++ } ++ ++ sdiodev->state = SDIO_ACTIVE_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ return ret; ++} ++ ++int aicwf_sdio_sleep_allow(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = sdiodev->bus_if; ++ struct rwnx_hw *rwnx_hw = sdiodev->rwnx_hw; ++ u8 read_retry; ++ u8 val; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, 0x10); ++ if (ret) { ++ sdio_err("Write sleep fail!\n"); ++ } ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ return ret; ++ } ++ ++ sdio_info("sleep: %d, %d\n", sdiodev->state, scanning); ++ if (sdiodev->state == SDIO_ACTIVE_ST && !scanning && !rwnx_hw->is_p2p_alive \ ++ && !rwnx_hw->is_p2p_connected && (int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) <= 0) \ ++ && (sdiodev->tx_priv->cmd_txstate == false) && (int)(atomic_read(&sdiodev->rx_priv->rx_cnt) == 0)) { ++ AICWFDBG(LOGSDPWRC, "%s s\n", __func__); ++ if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ if (aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x02) < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ if (aicwf_sdio_func2_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x2) < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++ read_retry = 100; ++ while (read_retry) { ++ val = 0; ++ if (aicwf_sdio_func2_readb(sdiodev, sdiodev->sdio_reg.wakeup_reg, &val) < 0){ ++ sdio_err("reg %d read fail\n", sdiodev->sdio_reg.wakeup_reg); ++ }else if ((val & 0x2) == 0) { ++ break; ++ } else { ++ sdio_err("val:%d\n", val); ++ } ++ read_retry--; ++ if(read_retry < 90) ++ printk("warning: read cnt %d\n", read_retry); ++ udelay(500); ++ } ++ } ++ sdiodev->state = SDIO_SLEEP_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ //rwnx_pm_relax(sdiodev); ++ } else { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target) ++{ ++ int ret = 0; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ return -1; ++ } ++ ++ down(&sdiodev->pwrctl_wakeup_sema); ++ ++ if (sdiodev->state == target) { ++ if (target == SDIO_ACTIVE_ST) { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ up(&sdiodev->pwrctl_wakeup_sema); ++ return ret; ++ } ++ ++ switch (target) { ++ case SDIO_ACTIVE_ST: ++ aicwf_sdio_wakeup(sdiodev); ++ break; ++ case SDIO_SLEEP_ST: ++ aicwf_sdio_sleep_allow(sdiodev); ++ break; ++ } ++ ++ up(&sdiodev->pwrctl_wakeup_sema); ++ return ret; ++} ++#endif ++ ++#if 0 ++int align_param = 16; ++module_param(align_param, int, 0660); ++#endif ++ ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++{ ++ int ret = 0; ++ u8 *frame; ++ u32 len = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++#if 0 ++ int align = 0; ++#endif ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("tx bus is down!\n"); ++ return -EINVAL; ++ } ++ ++#if 0 ++ len = pkt->len; ++ len = (len + SDIOWIFI_FUNC_BLOCKSIZE - 1) / SDIOWIFI_FUNC_BLOCKSIZE * SDIOWIFI_FUNC_BLOCKSIZE; ++ ++ frame = (u8*)kmalloc(sizeof(u8) * len + align_param, GFP_ATOMIC); ++ align = ((unsigned long)(frame)) & (align_param - 1); ++ memcpy(frame + (align_param - align), (u8 *) (pkt->data), len); ++ ++ ret = aicwf_sdio_send_pkt(sdiodev, frame + (align_param - align), len); ++ if (ret) ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", ret); ++ ++ kfree(frame); ++#endif ++#if 1 ++ frame = (u8 *) (pkt->data); ++ len = pkt->len; ++ len = (len + SDIOWIFI_FUNC_BLOCKSIZE - 1) / SDIOWIFI_FUNC_BLOCKSIZE * SDIOWIFI_FUNC_BLOCKSIZE; ++ ++ ret = aicwf_sdio_send_pkt(sdiodev, pkt->data, len); ++ if (ret) ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", ret); ++#endif ++ return ret; ++} ++ ++#ifdef CONFIG_SDIO_ADMA ++int aicwf_sdio_txscatterpkt(struct aicwf_tx_priv *tx_priv) ++{ ++ int ret = 0; ++ u8 *frame; ++ u32 len = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(tx_priv->sdiodev->dev); ++ struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; ++ int nents = tx_priv->aggr_segcnt; ++ int i=0; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("tx bus is down!\n"); ++ return -EINVAL; ++ } ++ ++ //AICWFDBG(LOGTRACE,"%s aggr_segcnt %d len %d \n",__func__,tx_priv->aggr_segcnt, tx_priv->len); ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_write_sg(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, &(tx_priv->sg_list[0]), tx_priv->aggr_segcnt, tx_priv->len);//&(tx_priv->sg_list[0]) ++ //sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, tx_priv->sg_list[0].buf, tx_priv->sg_list[0].len); ++ /*for(i=0;i<1;i++){ ++ sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, tx_priv->sg_list[i].buf, tx_priv->sg_list[i].len); ++ }*/ ++ sdio_release_host(sdiodev->func); ++ ++ return ret; ++ ++} ++ ++void aicwf_adma_add(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt) ++{ ++ u8 adj_len = 0; ++ u8 *sdio_header = NULL; ++ u32 sdio_len = 0; ++ u32 curr_len = 0; ++ unsigned int align_len = 0; ++ u8 *start_ptr = NULL; ++ ++ adj_len = ALIGN4_ADJ_LEN((uint32_t)pkt->data); ++ start_ptr = skb_push(pkt,adj_len); //skb_push(pkt,adj_len) ++ //ASSERT((adj_len==0)||(adj_len==2)); // mgmt-pkt or data-pkt ++ //ASSERT((((uint32_t)start_ptr)&3) == 0); // start_ptr addr word align ++ if(!((adj_len==0)||(adj_len==2))) ++ AICWFDBG(LOGTRACE,"adj_len false %u \n",adj_len); ++ ++ if((((uint32_t)start_ptr)&3) != 0) ++ AICWFDBG(LOGTRACE,"start_ptr %x \n",(((uint32_t)start_ptr)&3)); ++ ++ //AICWFDBG(LOGTRACE,"start adj_len %d aggrcnt %d segcnt %d len %d \n",adj_len,atomic_read(&tx_priv->aggr_count),tx_priv->aggr_segcnt,tx_priv->len); ++ ++ if (adj_len==0) { ++ sdio_len = pkt->len + SDIO_MGMT_FAKE_LEN; ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ //AICWFDBG(LOGTRACE,"pkt_len %d \n",pkt->len); ++ start_ptr = skb_push(pkt, (SDIO_HEADER_LEN+SDIO_MGMT_FAKE_LEN)); ++ //AICWFDBG(LOGTRACE,"push_pkt_len %d \n",pkt->len); ++ sdio_header = start_ptr; ++ ++ sdio_header[0] =((sdio_len) & 0xff); ++ sdio_header[1] =(((sdio_len) >> 8)&0x0f); ++ sdio_header[2] = 0x01; //data ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80) ++ sdio_header[3] = crc8_ponl_107(&sdio_header[0], 3); // crc8 ++ else ++ sdio_header[3] = 0; //reserved ++ ++ // fill 4 byte 0x00, need to fasync with data-pkt. ++ sdio_header[4] = 0; ++ sdio_header[5] = 0; ++ sdio_header[6] = 0; ++ sdio_header[7] = 0; ++ ++ curr_len = sdio_len + SDIO_HEADER_LEN; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj0",pkt->data,((pkt->len>32) ? 32 : pkt->len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ tx_priv->len += curr_len; ++ }else if (adj_len==1) { ++ sdio_len = pkt->len + 3; ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][0] = ((sdio_len) & 0xff); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][1] = (((sdio_len) >> 8)&0x0f); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][2] = 0x01; // data ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][3] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][4] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][5] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][6] = 0; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_dummy[tx_priv->aggr_segcnt]; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = SDIO_HEADER_LEN + 3; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] =NULL; ++ ++ tx_priv->aggr_segcnt++; ++ ++ sdio_header = start_ptr; ++ sdio_header[0] = 0; ++ ++ curr_len = sdio_len - 3; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj1",start_ptr,((curr_len>32) ? 32 : curr_len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ ++ tx_priv->len += curr_len + SDIO_HEADER_LEN + 3; ++ ++ }else if (adj_len==2) { // adj_len==2 ++ sdio_len = pkt->len + SDIO_DATA_FAKE_LEN;//adj_len + ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][0] = ((sdio_len) & 0xff); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][1] = (((sdio_len) >> 8)&0x0f); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][2] = 0x01; // data ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][3] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][4] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][5] = 0; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_dummy[tx_priv->aggr_segcnt]; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = SDIO_HEADER_LEN + SDIO_DATA_FAKE_LEN; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] =NULL; ++ ++ tx_priv->aggr_segcnt++; ++ ++ sdio_header = start_ptr; ++ sdio_header[0] = 0; ++ sdio_header[1] = 0; ++ ++ curr_len = sdio_len - SDIO_DATA_FAKE_LEN; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj2",start_ptr,((curr_len>32) ? 32 : curr_len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ ++ tx_priv->len += curr_len + SDIO_HEADER_LEN + SDIO_DATA_FAKE_LEN; ++ }else if (adj_len==3) { ++ sdio_len = pkt->len + 1; ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][0] = ((sdio_len) & 0xff); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][1] = (((sdio_len) >> 8)&0x0f); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][2] = 0x01; // data ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][3] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][4] = 0; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_dummy[tx_priv->aggr_segcnt]; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = SDIO_HEADER_LEN + 1; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] =NULL; ++ ++ tx_priv->aggr_segcnt++; ++ ++ sdio_header = start_ptr; ++ sdio_header[0] = 0; ++ sdio_header[1] = 0; ++ sdio_header[2] = 0; ++ ++ curr_len = sdio_len - 1; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj3",start_ptr,((curr_len>32) ? 32 : curr_len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ ++ tx_priv->len += curr_len + SDIO_HEADER_LEN + 1; ++ } ++ ++ //AICWFDBG(LOGTRACE,"end aggrcnt %d segcnt %d len %d \n",atomic_read(&tx_priv->aggr_count),tx_priv->aggr_segcnt,tx_priv->len); ++ ++} ++ ++#endif ++ ++static int aicwf_sdio_intr_get_len_bytemode(struct aic_sdio_dev *sdiodev, u8 *byte_len) ++{ ++ int ret = 0; ++ ++ if (!byte_len) ++ return -EBADE; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ *byte_len = 0; ++ } else { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.bytemode_len_reg, byte_len); ++ sdiodev->rx_priv->data_len = (*byte_len)*4; ++ } ++ ++ return ret; ++} ++ ++static void aicwf_sdio_bus_stop(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ #endif ++ AICWFDBG(LOGINFO, "%s Enter\n", __func__); ++ ++ bus_if->state = BUS_DOWN_ST; ++ if (sdiodev->tx_priv) { ++ ret = down_interruptible(&sdiodev->tx_priv->txctl_sema); ++ if (ret) ++ AICWFDBG(LOGERROR, "down txctl_sema fail\n"); ++ } ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ #endif ++ ++ if (sdiodev->tx_priv) { ++ if (!ret) ++ up(&sdiodev->tx_priv->txctl_sema); ++ aicwf_frame_queue_flush(&sdiodev->tx_priv->txq); ++ } ++ AICWFDBG(LOGINFO, "%s Exit \n", __func__); ++} ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct rx_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ u32 size = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ struct rx_buff* rxbuff; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("bus down\n"); ++ return NULL; ++ } ++ ++ size = sdiodev->rx_priv->data_len; ++ rxbuff = aicwf_prealloc_rxbuff_alloc(&sdiodev->rx_priv->rxbuff_lock); ++ if (rxbuff == NULL) { ++ printk("failed to alloc rxbuff\n"); ++ return NULL; ++ } ++ rxbuff->len = 0; ++ rxbuff->start = rxbuff->data; ++ rxbuff->read = rxbuff->start; ++ rxbuff->end = rxbuff->data + size; ++ ++ ret = aicwf_sdio_recv_pkt(sdiodev, rxbuff, size); ++ if (ret) { ++ printk("%s %d, sdio recv pkt fail\n", __func__, __LINE__); ++ aicwf_prealloc_rxbuff_free(rxbuff, &sdiodev->rx_priv->rxbuff_lock); ++ return NULL; ++ } ++ ++ return rxbuff; ++} ++#else ++struct sk_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ u32 size = 0; ++ struct sk_buff *skb = NULL; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("bus down\n"); ++ return NULL; ++ } ++ ++ size = sdiodev->rx_priv->data_len; ++ skb = __dev_alloc_skb(size, GFP_KERNEL); ++ if (!skb) { ++ return NULL; ++ } ++ ++ ret = aicwf_sdio_recv_pkt(sdiodev, skb, size); ++ if (ret) { ++ dev_kfree_skb(skb); ++ skb = NULL; ++ } ++ ++ return skb; ++} ++#endif ++ ++static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++ u16 len; ++ u8 *payload = sdiodev->tx_priv->cmd_buf; ++ u16 payload_len = sdiodev->tx_priv->cmd_len; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ int adjust_len = 0; ++ int buffer_cnt = 0; ++ u8 retry = 0; ++ ++ len = payload_len; ++ if ((len % TX_ALIGNMENT) != 0) { ++ adjust_len = roundup(len, TX_ALIGNMENT); ++ memcpy(payload+payload_len, adjust_str, (adjust_len - len)); ++ payload_len += (adjust_len - len); ++ } ++ len = payload_len; ++ ++ //link tail is necessary ++ if ((len % SDIOWIFI_FUNC_BLOCKSIZE) != 0) { ++ memset(payload+payload_len, 0, TAIL_LEN); ++ payload_len += TAIL_LEN; ++ len = (payload_len/SDIOWIFI_FUNC_BLOCKSIZE + 1) * SDIOWIFI_FUNC_BLOCKSIZE; ++ } else ++ len = payload_len; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ buffer_cnt = aicwf_sdio_flow_ctrl_msg(sdiodev); ++ while ((buffer_cnt <= 0 || (buffer_cnt > 0 && len > (buffer_cnt * BUFFER_SIZE))) && retry < 10) { ++ retry++; ++ buffer_cnt = aicwf_sdio_flow_ctrl_msg(sdiodev); ++ printk("buffer_cnt = %d\n", buffer_cnt); ++ } ++ } ++ down(&sdiodev->tx_priv->cmd_txsema); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if (buffer_cnt > 0 && len < (buffer_cnt * BUFFER_SIZE)) { ++ err = aicwf_sdio_send_pkt(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC){ ++ err = aicwf_sdio_send_pkt(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ ++ sdiodev->tx_priv->cmd_txstate = false; ++ if (!err) ++ sdiodev->tx_priv->cmd_tx_succ = true; ++ else ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ return err; ++ ++} ++ ++static void aicwf_sdio_tx_process(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ unsigned long flags; ++#endif ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("Bus is down\n"); ++ return; ++ } ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ #endif ++ ++ //config ++ sdio_info("send cmd\n"); ++ if (sdiodev->tx_priv->cmd_txstate) { ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txctl down bus->txctl_sema fail\n"); ++ return; ++ } ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ txrx_err("txctl up bus->txctl_sema fail\n"); ++ return; ++ } ++ err = aicwf_sdio_tx_msg(sdiodev); ++ up(&sdiodev->tx_priv->txctl_sema); ++ if (waitqueue_active(&sdiodev->tx_priv->cmd_txdone_wait)) ++ wake_up(&sdiodev->tx_priv->cmd_txdone_wait); ++ } ++ ++ //data ++ sdio_info("send data\n"); ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txdata down bus->txctl_sema\n"); ++ return; ++ } ++ ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("sdio state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ return; ++ } ++ ++ if (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)){ ++ sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ } ++ while (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) { ++ if(sdiodev->bus_if->state == BUS_DOWN_ST) { ++ break; ++ } ++#ifdef CONFIG_TEMP_CONTROL ++ if (sdiodev->on_off) ++ aicwf_temp_ctrl(sdiodev); ++#endif ++ ++ if (sdiodev->tx_priv->fw_avail_bufcnt <= DATA_FLOW_CTRL_THRESH) { ++ if (sdiodev->tx_priv->cmd_txstate) ++ break; ++ sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ } else { ++ if (sdiodev->tx_priv->cmd_txstate) { ++ aicwf_sdio_send(sdiodev->tx_priv, 1); ++ break; ++ } else { ++ aicwf_sdio_send(sdiodev->tx_priv, 0); ++ } ++ } ++ } ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) < tx_fc_low_water) { ++ //printk("sdiodev->tx_priv->tx_pktcnt < tx_fc_low_water:%d %d\r\n", ++ // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_low_water); ++ if (sdiodev->flowctrl) { ++ sdiodev->flowctrl = 0; ++ aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, false); ++ } ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++#endif ++ ++ up(&sdiodev->tx_priv->txctl_sema); ++} ++ ++static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) ++{ ++ uint prio; ++ int ret = -EBADE; ++ struct rwnx_txhdr *txhdr = NULL; ++ int headroom = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ unsigned long flags; ++#endif ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus_if stopped\n"); ++ txhdr = (struct rwnx_txhdr *)pkt->data; ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ consume_skb(pkt); ++ return -1; ++ } ++ ++ prio = (pkt->priority & 0x7); ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ if (!aicwf_frame_enq(sdiodev->dev, &sdiodev->tx_priv->txq, pkt, prio)) { ++ txhdr = (struct rwnx_txhdr *)pkt->data; ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ consume_skb(pkt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return -ENOSR; ++ goto flowctrl; ++ } else { ++ ret = 0; ++ } ++ ++ atomic_inc(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ complete(&bus_if->bustx_trgg); ++ ++ flowctrl: ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) >= tx_fc_high_water) { ++ //printk("sdiodev->tx_priv->tx_pktcnt >= tx_fc_high_water:%d %d\r\n", ++ // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_high_water); ++ if (!sdiodev->flowctrl) { ++ sdiodev->flowctrl = 1; ++ aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, true); ++ } ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++#endif ++ ++ return ret; ++} ++ ++static int aicwf_sdio_bus_txmsg(struct device *dev, u8 *msg, uint msglen) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ down(&sdiodev->tx_priv->cmd_txsema); ++ sdiodev->tx_priv->cmd_txstate = true; ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ sdiodev->tx_priv->cmd_buf = msg; ++ sdiodev->tx_priv->cmd_len = msglen; ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ if (bus_if->state != BUS_UP_ST) { ++ sdio_err("bus has stop\n"); ++ return -1; ++ } ++ ++ complete(&bus_if->bustx_trgg); ++#if 0 ++ if (sdiodev->tx_priv->cmd_txstate) { ++ int timeout = msecs_to_jiffies(CMD_TX_TIMEOUT); ++ ret = wait_event_interruptible_timeout(sdiodev->tx_priv->cmd_txdone_wait, \ ++ !(sdiodev->tx_priv->cmd_txstate), timeout); ++ } ++ ++ if (!sdiodev->tx_priv->cmd_txstate && sdiodev->tx_priv->cmd_tx_succ) { ++ ret = 0; ++ } else { ++ sdio_err("send faild:%d, %d,%x\n", sdiodev->tx_priv->cmd_txstate, sdiodev->tx_priv->cmd_tx_succ, ret); ++ ret = -EIO; ++ } ++#endif ++ return 0; ++} ++ ++ ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv, u8 txnow) ++{ ++ struct sk_buff *pkt; ++ struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; ++ u32 aggr_len = 0; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ unsigned long flags; ++#endif ++ ++#ifdef CONFIG_SDIO_ADMA ++ aggr_len = tx_priv->len; ++#else ++ aggr_len = (tx_priv->tail - tx_priv->head); ++#endif ++ ++ if (((atomic_read(&tx_priv->aggr_count) == 0) && (aggr_len != 0)) ++ || ((atomic_read(&tx_priv->aggr_count) != 0) && (aggr_len == 0))) { ++ if (aggr_len > 0){ ++#ifdef CONFIG_SDIO_ADMA ++ printk("len %d seg_cnt %d aggr_cnt %d avail_cnt %d \n",aggr_len,tx_priv->aggr_segcnt,atomic_read(&tx_priv->aggr_count),tx_priv->fw_avail_bufcnt ); ++#endif ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++#ifdef CONFIG_SDIO_ADMA ++ printk("set len %d seg_cnt %d aggr_cnt %d avail_cnt %d \n",aggr_len,tx_priv->aggr_segcnt,atomic_read(&tx_priv->aggr_count),tx_priv->fw_avail_bufcnt ); ++#endif ++ } ++ ++ return 0; ++ } ++ ++ if (atomic_read(&tx_priv->aggr_count) == (tx_priv->fw_avail_bufcnt - DATA_FLOW_CTRL_THRESH)) { ++ if (atomic_read(&tx_priv->aggr_count) > 0) { ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); //send and check the next pkt; ++ } ++ return 0; ++ } else { ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ pkt = aicwf_frame_dequeue(&sdiodev->tx_priv->txq); ++ if (pkt == NULL) { ++ sdio_err("txq no pkt\n"); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return 0; ++ } ++ //atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) < tx_fc_low_water) { ++ //printk("sdiodev->tx_priv->tx_pktcnt < tx_fc_low_water:%d %d\r\n", ++ // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_low_water); ++ if (sdiodev->flowctrl) { ++ sdiodev->flowctrl = 0; ++ aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, false); ++ } ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++#endif ++ ++#ifndef CONFIG_SDIO_ADMA ++ if (tx_priv == NULL || tx_priv->tail == NULL || pkt == NULL) ++ txrx_err("null error\n"); ++#endif ++ if (aicwf_sdio_aggr(tx_priv, pkt)) { ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++ sdio_err("add aggr pkts failed!\n"); ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ return 0; ++ } ++ ++ //when aggr finish or there is cmd to send, just send this aggr pkt to fw ++ if ((int)atomic_read(&sdiodev->tx_priv->tx_pktcnt) == 1 || txnow || (atomic_read(&tx_priv->aggr_count) == (tx_priv->fw_avail_bufcnt - DATA_FLOW_CTRL_THRESH))) { ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ return 0; ++ } else { ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ return 0; ++ } ++ } ++} ++ ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt) ++{ ++#ifdef CONFIG_SDIO_ADMA ++ u8 adj_len = 0; ++ struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; ++ u8 *sdio_header = NULL; ++ u32 sdio_len = 0; ++ u32 curr_len = 0; ++ int align_len = 0; ++ int headroom; ++ u32 pkt_len = 0; ++ struct txdesc_api tmp_txdesc; ++ struct sk_buff *tmp_skb; ++ ++ //AICWFDBG(LOGTRACE,"%s \n",__func__); ++ //pkt (txhdr + data),aggr only need txhdr->sw_hdr->desc and data ++ memcpy(&tmp_txdesc, (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ ++ if(txhdr->sw_hdr->need_cfm){ ++ tmp_skb = skb_copy(pkt,GFP_ATOMIC);//save pkt when cfm get,then release,send skb is copy ++ if(!tmp_skb){ ++ AICWFDBG(LOGERROR,"skb copy fail"); ++ return -ENOMEM; ++ } ++ //AICWFDBG(LOGTRACE,"tmp_len %d pkt_len %d \n",tmp_skb->len,pkt->len); ++ ++ skb_pull(tmp_skb, txhdr->sw_hdr->headroom); ++ ++ //AICWFDBG(LOGTRACE,"pull_tmp_len %d \n",tmp_skb->len); ++ ++ skb_push(tmp_skb,sizeof(struct txdesc_api));//skb header is enough ++ ++ //AICWFDBG(LOGTRACE,"push_tmp_len %d \n",tmp_skb->len); ++ ++ memcpy(tmp_skb->data, (u8 *)(long)&tmp_txdesc,sizeof(struct txdesc_api)); ++ AICWFDBG(LOGTRACE,"need cfm len %d \n",tmp_skb->len); ++ ++ //printk("cfm alloc %p \n",tmp_skb); ++ //printk("delay free %p \n",pkt); ++ aicwf_adma_add(tx_priv, tmp_skb); ++ tx_priv->copyd[tx_priv->aggr_segcnt -1] = true; ++ }else{ ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ ++ //AICWFDBG(LOGTRACE,"pull_pkt_len %d \n",pkt->len); ++ ++ skb_push(pkt,sizeof(struct txdesc_api));//skb header is enough ++ ++ //AICWFDBG(LOGTRACE,"push_pkt_len %d \n",pkt->len); ++ ++ memcpy(pkt->data, (u8 *)(long)&tmp_txdesc,sizeof(struct txdesc_api)); ++ ++ //rwnx_data_dump("data",pkt->data,((pkt->len>64) ? 64 : pkt->len)); ++ ++ //printk("alloc %p \n",pkt); ++ ++ aicwf_adma_add(tx_priv, pkt); ++ tx_priv->copyd[tx_priv->aggr_segcnt -1] = false; ++ } ++ ++#else ++ ++ struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; ++ u8 *start_ptr = tx_priv->tail; ++ u8 sdio_header[4]; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ u32 curr_len = 0; ++ int allign_len = 0; ++ int headroom; ++ ++ sdio_header[0] = ((pkt->len - txhdr->sw_hdr->headroom + sizeof(struct txdesc_api)) & 0xff); ++ sdio_header[1] = (((pkt->len - txhdr->sw_hdr->headroom + sizeof(struct txdesc_api)) >> 8)&0x0f); ++ sdio_header[2] = 0x01; //data ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ sdio_header[3] = 0; //reserved ++ else if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ sdio_header[3] = crc8_ponl_107(&sdio_header[0], 3); // crc8 ++ ++ memcpy(tx_priv->tail, (u8 *)&sdio_header, sizeof(sdio_header)); ++ tx_priv->tail += sizeof(sdio_header); ++ //payload ++ memcpy(tx_priv->tail, (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ tx_priv->tail += sizeof(struct txdesc_api); //hostdesc ++ memcpy(tx_priv->tail, (u8 *)((u8 *)txhdr + txhdr->sw_hdr->headroom), pkt->len-txhdr->sw_hdr->headroom); ++ tx_priv->tail += (pkt->len - txhdr->sw_hdr->headroom); ++ ++ //word alignment ++ curr_len = tx_priv->tail - tx_priv->head; ++ if (curr_len & (TX_ALIGNMENT - 1)) { ++ allign_len = roundup(curr_len, TX_ALIGNMENT)-curr_len; ++ memcpy(tx_priv->tail, adjust_str, allign_len); ++ tx_priv->tail += allign_len; ++ } ++ ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ start_ptr[0] = ((tx_priv->tail - start_ptr - 4) & 0xff); ++ start_ptr[1] = (((tx_priv->tail - start_ptr - 4)>>8) & 0x0f); ++ } ++ tx_priv->aggr_buf->dev = pkt->dev; ++ ++ if (!txhdr->sw_hdr->need_cfm) { ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ consume_skb(pkt); ++ } ++ ++ atomic_inc(&tx_priv->aggr_count); ++#endif /* CONFIG_SDIO_ADMA */ ++ ++ return 0; ++} ++ ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv) ++{ ++#ifdef CONFIG_SDIO_ADMA ++ int ret = 0; ++ int i=0; ++ int nents = tx_priv->aggr_segcnt; ++ //struct sk_buff *scatter_buf; ++ ++ if(tx_priv->len & (TXPKT_BLOCKSIZE-1)) ++ { ++ uint16_t alen = TXPKT_BLOCKSIZE-(tx_priv->len & (TXPKT_BLOCKSIZE-1)); ++ ++ memset(sdio_tx_buf_fill, 0,32); ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_fill; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = alen; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = NULL; ++ tx_priv->aggr_segcnt += 1; ++ tx_priv->len += alen; ++ } ++ ++ //AICWFDBG(LOGTRACE,"nents %d \n",tx_priv->aggr_segcnt); ++ /*for(i=0;iaggr_segcnt;i++){ ++ if(tx_priv->sg_list[i].buf != NULL){ ++ rwnx_data_dump("send",tx_priv->sg_list[i].buf,((tx_priv->sg_list[i].len>64) ? 64 : tx_priv->sg_list[i].len)); ++ } ++ }*/ ++ ++ ret = aicwf_sdio_txscatterpkt(tx_priv); ++ if (ret < 0) { ++ sdio_err("fail to send scatter pkt %d !\n",ret); ++ } ++ ++#else ++ ++ struct sk_buff *tx_buf = tx_priv->aggr_buf; ++ int ret = 0; ++ int curr_len = 0; ++ ++ //link tail is necessary ++ curr_len = tx_priv->tail - tx_priv->head; ++ if ((curr_len % TXPKT_BLOCKSIZE) != 0) { ++ memset(tx_priv->tail, 0, TAIL_LEN); ++ tx_priv->tail += TAIL_LEN; ++ } ++ ++ tx_buf->len = tx_priv->tail - tx_priv->head; ++ ret = aicwf_sdio_txpkt(tx_priv->sdiodev, tx_buf); ++ if (ret < 0) { ++ sdio_err("fail to send aggr pkt!\n"); ++ } ++#endif/* CONFIG_SDIO_ADMA */ ++ ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++} ++ ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv) ++{ ++#ifdef CONFIG_SDIO_ADMA ++ struct sk_buff *scatter_buf; ++ int i = 0; ++ int nents = tx_priv->aggr_segcnt; ++ ++ for(i=0;ifree_buf[i]; ++ if(scatter_buf != NULL){ ++ //printk("free %p \n",scatter_buf); ++ if(tx_priv->copyd[i]){ ++ kfree_skb(scatter_buf); ++ tx_priv->copyd[i] = false; ++ } ++ else ++ consume_skb(scatter_buf); ++ } ++ } ++ ++ tx_priv->len = 0; ++ tx_priv->aggr_segcnt = 0; ++ atomic_set(&tx_priv->aggr_count, 0); ++ AICWFDBG(LOGTRACE,"reset len %d seg_cnt %d aggr_cnt %d \n",tx_priv->len,tx_priv->aggr_segcnt,atomic_read(&tx_priv->aggr_count)); ++#else ++ ++ struct sk_buff *aggr_buf = tx_priv->aggr_buf; ++ ++ tx_priv->tail = tx_priv->head; ++ aggr_buf->len = 0; ++ atomic_set(&tx_priv->aggr_count, 0); ++#endif/* CONFIG_SDIO_ADMA */ ++} ++ ++extern void set_irq_handler(void *fn); ++ ++static int aicwf_sdio_bus_start(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ ++ sdio_claim_host(sdiodev->func); ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++#else ++ set_irq_handler(aicwf_sdio_hal_irqhandler); ++#endif ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdio_f0_writeb(sdiodev->func, 0x07, 0x04, &ret); ++ if (ret) { ++ sdio_err("set func0 int en fail %d\n", ret); ++ } ++ } ++ sdio_release_host(sdiodev->func); ++ ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ ++ bus_if->state = BUS_UP_ST; ++ ++ return ret; ++} ++ ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) ++#include "uapi/linux/sched/types.h" ++#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) ++#include "linux/sched/types.h" ++#else ++#include "linux/sched/rt.h" ++#endif ++ ++int bustx_thread_prio = 1; ++module_param_named(bustx_thread_prio, bustx_thread_prio, int, 0644); ++//module_param(bustx_thread_prio, int, 0); ++int busrx_thread_prio = 1; ++module_param_named(busrx_thread_prio, busrx_thread_prio, int, 0644); ++//module_param(busrx_thread_prio, int, 0); ++#endif ++ ++ ++static inline void aic_thread_wait_stop(void) ++{ ++#if 1// PLATFORM_LINUX ++ #if 0 ++ while (!kthread_should_stop()){ ++ AICWFDBG(LOGINFO, "%s waiting for thread_stop notify \r\n", __func__); ++ msleep(100); ++ } ++ #else ++ set_current_state(TASK_INTERRUPTIBLE); ++ while (!kthread_should_stop()) { ++ AICWFDBG(LOGINFO, "%s waiting for thread_stop notify \r\n", __func__); ++ schedule(); ++ set_current_state(TASK_INTERRUPTIBLE); ++ } ++ __set_current_state(TASK_RUNNING); ++ #endif ++#endif ++} ++ ++#ifdef CONFIG_OOB ++int rx_thread_wait_to = 1000; ++module_param_named(rx_thread_wait_to, rx_thread_wait_to, int, 0644); ++ ++//new oob feature ++int sdio_busirq_thread(void *data){ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++#if 0 ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ int set_cpu_ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s the cpu is:%d\n", __func__, current->cpu); ++ set_cpu_ret = set_cpus_allowed_ptr(current, cpumask_of(0)); ++ AICWFDBG(LOGINFO, "%s set_cpu_ret is:%d\n", __func__, set_cpu_ret); ++ AICWFDBG(LOGINFO, "%s change cpu to:%d\n", __func__, current->cpu); ++#endif ++#endif ++ ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (busrx_thread_prio > 0) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) ++ sched_set_fifo_low(current); ++#else ++ struct sched_param param; ++ param.sched_priority = (busrx_thread_prio - 1 < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++#endif ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++ ++ while (1) { ++#if 0 ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busirq thread stop\n"); ++ break; ++ } ++#endif ++ if(!wait_for_completion_timeout(&bus_if->busirq_trgg, msecs_to_jiffies(rx_thread_wait_to))){ ++ AICWFDBG(LOGRXPOLL, "%s wait for completion timout \r\n", __func__); ++ } ++ ++ if (bus_if->state == BUS_DOWN_ST){ ++ AICWFDBG(LOGERROR, "%s bus down thread exit \r\n", __func__); ++ break; ++ } ++ //continue; ++#if 1 ++#ifdef CONFIG_SDIO_PWRCTRL ++ while(atomic_read(&bus_if->bus_priv.sdio->is_bus_suspend) == 1){ ++ AICWFDBG(LOGDEBUG, "%s waiting for sdio bus resume \r\n", __func__); ++ msleep(100); ++ } ++ aicwf_sdio_pwr_stctl(bus_if->bus_priv.sdio, SDIO_ACTIVE_ST); ++#endif//CONFIG_SDIO_PWRCTRL ++#endif ++ aicwf_sdio_hal_irqhandler(bus_if->bus_priv.sdio->func); ++ } ++ ++ aic_thread_wait_stop(); ++ ++ return 0; ++} ++ ++#endif//CONFIG_OOB ++ ++#if 0 ++#include ++#endif ++int sdio_bustx_thread(void *data) ++{ ++ struct aicwf_bus *bus = (struct aicwf_bus *) data; ++ struct aic_sdio_dev *sdiodev = bus->bus_priv.sdio; ++#if 0 ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ int set_cpu_ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s the cpu is:%d\n", __func__, current->cpu); ++ set_cpu_ret = set_cpus_allowed_ptr(current, cpumask_of(1)); ++ AICWFDBG(LOGINFO, "%s set_cpu_ret is:%d\n", __func__, set_cpu_ret); ++ AICWFDBG(LOGINFO, "%s change cpu to:%d\n", __func__, current->cpu); ++#endif ++#endif ++ ++#if 0 ++ struct cpumask cpumask; ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(1, &cpumask); ++ cpumask_set_cpu(2, &cpumask); ++ cpumask_set_cpu(3, &cpumask); ++ sched_setaffinity(0, &cpumask);//need to add EXPORT_SYMBOL_GPL(sched_setaffinity) in kernel/sched/core.c ++#endif ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (bustx_thread_prio > 0) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) ++ sched_set_fifo_low(current); ++#else ++ struct sched_param param; ++ param.sched_priority = (bustx_thread_prio < MAX_RT_PRIO)?bustx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++#endif ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++ while (1) { ++ #if 0 ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio bustx thread stop\n"); ++ break; ++ } ++ #endif ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) ++ break; ++ //continue; ++ ++ rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_tx); ++ if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) > 0) || (sdiodev->tx_priv->cmd_txstate == true)){ ++ aicwf_sdio_tx_process(sdiodev); ++ } ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_tx); ++ } ++ } ++ ++ aic_thread_wait_stop(); ++ AICWFDBG(LOGINFO, "%s Exit\r\n", __func__); ++ return 0; ++} ++ ++#if 0//old oob feature ++int sdio_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++#if 0 ++ struct cpumask cpumask; ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(1, &cpumask); ++ cpumask_set_cpu(2, &cpumask); ++ cpumask_set_cpu(3, &cpumask); ++ sched_setaffinity(0, &cpumask); ++#endif ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (busrx_thread_prio > 0) { ++ struct sched_param param; ++ param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++while (1) { ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busrx thread stop\n"); ++ break; ++ } ++#ifndef CONFIG_OOB ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++#else ++ if(!wait_for_completion_timeout(&bus_if->busrx_trgg, msecs_to_jiffies(rx_thread_wait_to))){ ++ AICWFDBG(LOGDEBUG, "%s wait for completion timout \r\n", __func__); ++ } ++#endif ++ if (bus_if->state == BUS_DOWN_ST) ++ continue; ++#ifdef CONFIG_OOB ++#ifdef CONFIG_SDIO_PWRCTRL ++ while(atomic_read(&bus_if->bus_priv.sdio->is_bus_suspend) == 1){ ++ AICWFDBG(LOGDEBUG, "%s waiting for sdio bus resume \r\n", __func__); ++ msleep(100); ++ } ++ aicwf_sdio_pwr_stctl(bus_if->bus_priv.sdio, SDIO_ACTIVE_ST); ++#endif//CONFIG_SDIO_PWRCTRL ++ aicwf_sdio_hal_irqhandler(bus_if->bus_priv.sdio->func); ++#endif//CONFIG_OOB ++ rwnx_wakeup_lock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++ aicwf_process_rxframes(rx_priv); ++ rwnx_wakeup_unlock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++#ifndef CONFIG_OOB ++ } ++#endif ++ } ++ ++ return 0; ++ ++} ++#else//new oob feature ++int sdio_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++ ++ ++#if 0 ++ struct cpumask cpumask; ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(1, &cpumask); ++ cpumask_set_cpu(2, &cpumask); ++ cpumask_set_cpu(3, &cpumask); ++ sched_setaffinity(0, &cpumask); ++#endif ++#if 0 ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ int set_cpu_ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s the cpu is:%d\n", __func__, current->cpu); ++ set_cpu_ret = set_cpus_allowed_ptr(current, cpumask_of(2)); ++ AICWFDBG(LOGINFO, "%s set_cpu_ret is:%d\n", __func__, set_cpu_ret); ++ AICWFDBG(LOGINFO, "%s change cpu to:%d\n", __func__, current->cpu); ++#endif ++#endif ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (busrx_thread_prio > 0) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) ++ sched_set_fifo_low(current); ++#else ++ struct sched_param param; ++ param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++#endif ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++ while (1) { ++ #if 0 ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busrx thread stop\n"); ++ break; ++ } ++ #endif ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ ++ if (bus_if->state == BUS_DOWN_ST) ++ break; ++ //continue; ++ rwnx_wakeup_lock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++ aicwf_process_rxframes(rx_priv); ++ rwnx_wakeup_unlock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++ } ++ } ++ aic_thread_wait_stop(); ++ AICWFDBG(LOGINFO, "%s Exit\r\n", __func__); ++ return 0; ++ ++} ++ ++#endif//old oob feature ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++static int aicwf_sdio_pwrctl_thread(void *data) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ sdio_err("sdio pwrctl thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&sdiodev->pwrctrl_trgg)) { ++ //printk("%s working\r\n", __func__); ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) ++ continue; ++ ++ rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_pwrctrl); ++ ++ if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) <= 0) && (sdiodev->tx_priv->cmd_txstate == false) && \ ++ atomic_read(&sdiodev->rx_priv->rx_cnt) == 0) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ else ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_pwrctrl); ++ } ++ } ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++static void aicwf_sdio_bus_pwrctl(ulong data) ++#else ++static void aicwf_sdio_bus_pwrctl(struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ struct aic_sdio_dev *sdiodev = timer_container_of(sdiodev, t, timer); ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, timer); ++#endif ++#endif ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus down\n"); ++ return; ++ } ++ ++ if (sdiodev->pwrctl_tsk) { ++ complete(&sdiodev->pwrctrl_trgg); ++ } ++} ++#endif ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++static void aicwf_sdio_enq_rxpkt(struct aic_sdio_dev *sdiodev, struct rx_buff *pkt) ++#else ++static void aicwf_sdio_enq_rxpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++#endif ++{ ++ struct aicwf_rx_priv *rx_priv = sdiodev->rx_priv; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ if (!aicwf_rxbuff_enqueue(sdiodev->dev, &rx_priv->rxq, pkt)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ printk("%s %d, enqueue rxq fail\n", __func__, __LINE__); ++ aicwf_prealloc_rxbuff_free(pkt, &rx_priv->rxbuff_lock); ++ return; ++ } ++ #else ++ if (!aicwf_rxframe_enqueue(sdiodev->dev, &rx_priv->rxq, pkt)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ aicwf_dev_skb_free(pkt); ++ return; ++ } ++ #endif ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ ++ atomic_inc(&rx_priv->rx_cnt); ++} ++ ++ ++#define SDIO_OTHER_INTERRUPT (0x1ul << 7) ++ ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(&func->dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ u8 intstatus = 0; ++ u8 byte_len = 0; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_buff *pkt = NULL; ++ #else ++ struct sk_buff *pkt = NULL; ++ #endif ++ int ret; ++ ++ ++ if ((sdiodev->rwnx_hw) == NULL) { ++ sdio_err("waiting for rwnx_hw->irq_enable is true\r\n"); ++ return; ++ } ++ ++ //AICWFDBG(LOGDEBUG, "fdrv %s enter \r\n", __func__); ++ rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_irqrx); ++ ++ ++ if (!bus_if || bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus err\n"); ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); ++ return; ++ } ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++ if (list_empty(&aic_rx_buff_list.rxbuff_list)) { ++ printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); ++ return; ++ } ++#endif ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ while (ret || (intstatus & SDIO_OTHER_INTERRUPT)) { ++ sdio_err("ret=%d, intstatus=%x\r\n", ret, intstatus); ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ if (!ret) { ++ return; ++ } ++ } ++ sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; ++ ++ if (intstatus > 0) { ++ if (intstatus < 64) { ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } else { ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ // sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ ++ if(atomic_read(&sdiodev->rx_priv->rx_cnt) == 1){ ++ complete(&bus_if->busrx_trgg); ++ } ++ ++ }else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ do { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.misc_int_status_reg, &intstatus); ++ if (!ret) { ++ break; ++ } ++ sdio_err("ret=%d, intstatus=%x\r\n",ret, intstatus); ++ return; ++ } while (1); ++ if (intstatus & SDIO_OTHER_INTERRUPT) { ++ u8 int_pending; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ int_pending &= ~0x01; // dev to host soft irq ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ } ++ ++ if (intstatus > 0) { ++ uint8_t intmaskf2 = intstatus | (0x1UL << 3); ++ if (intmaskf2 > 120U) { // func2 ++ if (intmaskf2 == 127U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 1);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ //pkt = aicwf_sdio_readframes(sdiodev, 1); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7U) * SDIOWIFI_FUNC_BLOCKSIZE; ++ //pkt = aicwf_sdio_readframes(sdiodev, 1); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } ++ } else { // func1 ++ if (intstatus == 120U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 0);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ //pkt = aicwf_sdio_readframes(sdiodev, 0); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7FU) * SDIOWIFI_FUNC_BLOCKSIZE; ++ //pkt = aicwf_sdio_readframes(sdiodev, 0); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ //sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ ++ if(atomic_read(&sdiodev->rx_priv->rx_cnt) == 1){ ++ complete(&bus_if->busrx_trgg); ++ } ++ } ++ ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration) ++{ ++ uint timeout; ++ ++ //printk("%s duration:%d\r\n", __func__, duration); ++ if (sdiodev->bus_if->state == BUS_DOWN_ST && duration) ++ return; ++ ++ spin_lock_bh(&sdiodev->pwrctl_lock); ++ if (!duration) { ++ if (timer_pending(&sdiodev->timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&sdiodev->timer); ++#else ++ del_timer_sync(&sdiodev->timer); ++#endif ++ } else { ++ sdiodev->active_duration = duration; ++ timeout = msecs_to_jiffies(sdiodev->active_duration); ++ mod_timer(&sdiodev->timer, jiffies + timeout); ++ } ++ spin_unlock_bh(&sdiodev->pwrctl_lock); ++} ++#endif ++ ++static struct aicwf_bus_ops aicwf_sdio_bus_ops = { ++ .stop = aicwf_sdio_bus_stop, ++ .start = aicwf_sdio_bus_start, ++ .txdata = aicwf_sdio_bus_txdata, ++ .txmsg = aicwf_sdio_bus_txmsg, ++}; ++ ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) ++{ ++ struct aicwf_bus *bus_if; ++ int ret = 0; ++ AICWFDBG(LOGINFO, "%s Enter\n", __func__); ++ ++ bus_if = dev_get_drvdata(sdiodev->dev); ++ bus_if->state = BUS_DOWN_ST; ++#ifdef CONFIG_OOB ++ if(sdiodev->oob_enable){ ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++#else ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++#endif ++ if (sdiodev->dev) ++ aicwf_bus_deinit(sdiodev->dev); ++ ++ if (sdiodev->tx_priv) ++ aicwf_tx_deinit(sdiodev->tx_priv); ++ ++ if (sdiodev->rx_priv) ++ aicwf_rx_deinit(sdiodev->rx_priv); ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ if (sdiodev->pwrctl_tsk) { ++ complete_all(&sdiodev->pwrctrl_trgg); ++ kthread_stop(sdiodev->pwrctl_tsk); ++ sdiodev->pwrctl_tsk = NULL; ++ } ++ ++ AICWFDBG(LOGINFO, "%s:pwrctl stopped\n", __func__); ++ #endif ++ ++ if (sdiodev->cmd_mgr.state == RWNX_CMD_MGR_STATE_INITED) ++ rwnx_cmd_mgr_deinit(&sdiodev->cmd_mgr); ++ AICWFDBG(LOGINFO, "%s Exit\n", __func__); ++} ++ ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev) ++{ ++ sdio_dbg("%s\n", __func__); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_CONFIG_REG; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_SLEEP_REG; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_WAKEUP_REG; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_REG; ++ sdiodev->sdio_reg.register_block = SDIOWIFI_REGISTER_BLOCK; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG; ++ sdiodev->sdio_reg.block_cnt_reg = SDIOWIFI_BLOCK_CNT_REG; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG_V3; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_ENABLE_REG_V3; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_INTR_PENDING_REG_V3; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_INTR_TO_DEVICE_REG_V3; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_Q1_REG_V3; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG_V3; ++ sdiodev->sdio_reg.misc_int_status_reg = SDIOWIFI_MISC_INT_STATUS_REG_V3; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR_V3; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR_V3; ++ } ++} ++ ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 block_bit0 = 0x1; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ struct aicbsp_feature_t feature; ++ //u8 val = 0; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++#if 0//SDIO PHASE SETTING ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ sdio_f0_writeb(sdiodev->func, feature.sdio_phase, 0x13, &ret); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "write func0 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#endif ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_release_host(sdiodev->func); ++ AICWFDBG(LOGERROR, "enable func fail %d.\n", ret); ++ return ret; ++ } ++ ++#if 1//SDIO CLOCK SETTING ++ if (feature.sdio_clock > 0) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ AICWFDBG(LOGINFO, "Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++ ++ sdio_release_host(sdiodev->func); ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ sdio_claim_host(sdiodev->func2); ++ //set sdio blocksize ++ ret = sdio_set_block_size(sdiodev->func2, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set func2 blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func2); ++ return ret; ++ } ++ ++ //set sdio enable func ++ ret = sdio_enable_func(sdiodev->func2); ++ if (ret < 0) { ++ sdio_release_host(sdiodev->func2); ++ AICWFDBG(LOGERROR, "enable func2 fail %d.\n", ret); ++ return ret; ++ } ++ ++ sdio_release_host(sdiodev->func2); ++ ++ ret = aicwf_sdio_func2_writeb(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_func2_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ } ++ ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++#if 0 ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 1); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ return ret; ++ } ++ ++ mdelay(5); ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ return ret; ++ } ++ ++ if(!(val & 0x10)){ ++ AICWFDBG(LOGERROR, "wakeup fail\n"); ++ }else{ ++ AICWFDBG(LOGINFO, "sdio ready\n"); ++ } ++#else ++ mdelay(10); ++#endif ++ return ret; ++} ++ ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ struct aicbsp_feature_t feature; ++ //u8 val = 0; ++ u8 val1 = 0; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_release_host(sdiodev->func); ++ AICWFDBG(LOGERROR, "enable func fail %d.\n", ret); ++ return ret; ++ } ++ ++ sdio_f0_writeb(sdiodev->func, 0x7F, 0xF2, &ret); ++ if (ret) { ++ sdio_err("set fn0 0xF2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#if 0 ++ if (host->ios.timing == MMC_TIMING_UHS_DDR50) { ++ val = 0x21;//0x1D;//0x5; ++ } else { ++ val = 0x01;//0x19;//0x1; ++ } ++ val |= SDIOCLK_FREE_RUNNING_BIT; ++ sdio_f0_writeb(sdiodev->func, val, 0xF0, &ret); ++ if (ret) { ++ sdio_err("set iopad ctrl fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x0, 0xF8, &ret); ++ if (ret) { ++ sdio_err("set iopad delay2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x20, 0xF1, &ret); ++ if (ret) { ++ sdio_err("set iopad delay1 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ msleep(1); ++#if 1//SDIO CLOCK SETTING ++ if ((feature.sdio_clock > 0) && (host->ios.timing != MMC_TIMING_UHS_DDR50)) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ AICWFDBG(LOGINFO, "Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++#endif ++ sdio_release_host(sdiodev->func); ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x11); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ return ret; ++ } ++ ++#if 1 ++ mdelay(5); ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val1); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ return ret; ++ } ++ ++ if(!(val1 & 0x10)){ ++ AICWFDBG(LOGERROR, "wakeup fail\n"); ++ }else{ ++ AICWFDBG(LOGINFO, "sdio ready\n"); ++ } ++#endif ++ return ret; ++} ++ ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev) ++{ ++ sdio_claim_host(sdiodev->func); ++ sdio_disable_func(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func2); ++ sdio_disable_func(sdiodev->func2); ++ sdio_release_host(sdiodev->func2); ++ } ++} ++ ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret; ++ struct aicwf_bus *bus_if; ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ spin_lock_init(&sdiodev->pwrctl_lock); ++ sema_init(&sdiodev->pwrctl_wakeup_sema, 1); ++ #endif ++ ++ bus_if = sdiodev->bus_if; ++ bus_if->dev = sdiodev->dev; ++ bus_if->ops = &aicwf_sdio_bus_ops; ++ bus_if->state = BUS_DOWN_ST; ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ sdiodev->state = SDIO_SLEEP_ST; ++ sdiodev->active_duration = SDIOWIFI_PWR_CTRL_INTERVAL; ++ #else ++ sdiodev->state = SDIO_ACTIVE_ST; ++ #endif ++ ++ rx_priv = aicwf_rx_init(sdiodev); ++ if (!rx_priv) { ++ sdio_err("rx init fail\n"); ++ goto fail; ++ } ++ sdiodev->rx_priv = rx_priv; ++ ++ tx_priv = aicwf_tx_init(sdiodev); ++ if (!tx_priv) { ++ sdio_err("tx init fail\n"); ++ goto fail; ++ } ++ sdiodev->tx_priv = tx_priv; ++ aicwf_frame_queue_init(&tx_priv->txq, 8, TXQLEN); ++ spin_lock_init(&tx_priv->txqlock); ++ sema_init(&tx_priv->txctl_sema, 1); ++ sema_init(&tx_priv->cmd_txsema, 1); ++ init_waitqueue_head(&tx_priv->cmd_txdone_wait); ++ atomic_set(&tx_priv->tx_pktcnt, 0); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ init_timer(&sdiodev->timer); ++ sdiodev->timer.data = (ulong) sdiodev; ++ sdiodev->timer.function = aicwf_sdio_bus_pwrctl; ++#else ++ timer_setup(&sdiodev->timer, aicwf_sdio_bus_pwrctl, 0); ++#endif ++ init_completion(&sdiodev->pwrctrl_trgg); ++#ifdef AICWF_SDIO_SUPPORT ++ sdiodev->pwrctl_tsk = kthread_run(aicwf_sdio_pwrctl_thread, sdiodev, "aicwf_pwrctl"); ++#endif ++ if (IS_ERR(sdiodev->pwrctl_tsk)) { ++ sdiodev->pwrctl_tsk = NULL; ++ } ++#endif ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ sdiodev->flowctrl = 0; ++ spin_lock_init(&sdiodev->tx_flow_lock); ++#endif ++ ++#ifdef CONFIG_TEMP_CONTROL ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ init_timer(&sdiodev->tp_ctrl_timer); ++ sdiodev->tp_ctrl_timer.data = (ulong) sdiodev; ++ sdiodev->tp_ctrl_timer.function = aicwf_temp_ctrl_timer; ++ init_timer(&sdiodev->netif_timer); ++ sdiodev->netif_timer.data = (ulong) sdiodev; ++ sdiodev->netif_timer.function = aicwf_netif_timer; ++#else ++ timer_setup(&sdiodev->tp_ctrl_timer, aicwf_temp_ctrl_timer, 0); ++ timer_setup(&sdiodev->netif_timer, aicwf_netif_timer, 0); ++#endif ++ INIT_WORK(&sdiodev->tp_ctrl_work, aicwf_temp_ctrl_worker); ++ INIT_WORK(&sdiodev->netif_work, aicwf_netif_worker); ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++ sdiodev->net_stop = false;; ++ sdiodev->on_off = true; ++ sdiodev->cur_temp = 0; ++ sdiodev->get_level = 0; ++ sdiodev->set_level = 0; ++ sdiodev->interval_t1 = TMR_INTERVAL_1; ++ sdiodev->interval_t2 = TMR_INTERVAL_2; ++ sdiodev->cur_stat = 0; ++#endif ++ ++ ret = aicwf_bus_init(0, sdiodev->dev); ++ if (ret < 0) { ++ sdio_err("bus init fail\n"); ++ goto fail; ++ } ++ ++ ret = aicwf_bus_start(bus_if); ++ if (ret != 0) { ++ sdio_err("bus start fail\n"); ++ goto fail; ++ } ++ ++ return sdiodev; ++ ++fail: ++ aicwf_sdio_release(sdiodev); ++ return NULL; ++} ++ ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size) ++{ ++ uint8_t i; ++ uint8_t crc = 0; ++ if (cal_size==0) { ++ return crc; ++ } ++ while (cal_size--) { ++ for (i = 0x80; i > 0; i /= 2) { ++ if (crc & 0x80) { ++ crc *= 2; ++ crc ^= 0x07; //polynomial X8 + X2 + X + 1,(0x107) ++ } else { ++ crc *= 2; ++ } ++ if ((*p_buffer) & i) { ++ crc ^= 0x07; ++ } ++ } ++ p_buffer++; ++ } ++ ++ return crc; ++} ++ ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++void rwnx_set_wifi_suspend(char onoff){ ++ int ret = 0; ++ if (onoff == '0') { ++ printk("%s resume \r\n", __func__); ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 0, 1); ++ }else{ ++ printk("%s suspend \r\n", __func__); ++ ret = rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1, 0); ++ if (!ret) { ++ aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); ++ ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); ++ } ++ } ++ } ++} ++ ++static ssize_t rwnx_wifi_suspend_write_proc(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos){ ++ char onoff; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&onoff, buffer, 1)) ++ return -EFAULT; ++ ++ rwnx_set_wifi_suspend(onoff); ++ ++ return count; ++} ++ ++static const struct file_operations wifi_suspend_fops = { ++ .owner = THIS_MODULE, ++ .write = rwnx_wifi_suspend_write_proc, ++}; ++ ++void rwnx_init_wifi_suspend_node(void){ ++ struct proc_dir_entry *ent; ++ ++ wifi_suspend_node = proc_mkdir("wifi_suspend", NULL); ++ if (wifi_suspend_node == NULL) { ++ printk("Unable to create /proc/wifi_suspend directory"); ++ } ++ ++ ent = proc_create("suspend", 0660, wifi_suspend_node, &wifi_suspend_fops); ++ if (ent == NULL) { ++ printk("Unable to create /proc/wifi_suspend/suspend"); ++ } ++} ++ ++void rwnx_deinit_wifi_suspend_node(void){ ++ remove_proc_entry("suspend", wifi_suspend_node); ++ remove_proc_entry("wifi_suspend", 0); ++} ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h +new file mode 100644 +index 000000000000..7e3e16fd405c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h +@@ -0,0 +1,226 @@ ++/** ++ * aicwf_sdio.h ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_SDMMC_H_ ++#define _AICWF_SDMMC_H_ ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include ++#include ++#include ++#include ++#include "rwnx_cmds.h" ++#include "aicwf_rx_prealloc.h" ++#define AICWF_SDIO_NAME "aicwf_sdio" ++#define SDIOWIFI_FUNC_BLOCKSIZE 512 ++ ++#define SDIOWIFI_BYTEMODE_LEN_REG 0x02 ++#define SDIOWIFI_INTR_CONFIG_REG 0x04 ++#define SDIOWIFI_SLEEP_REG 0x05 ++#define SDIOWIFI_WAKEUP_REG 0x09 ++#define SDIOWIFI_FLOW_CTRL_REG 0x0A ++#define SDIOWIFI_REGISTER_BLOCK 0x0B ++#define SDIOWIFI_BYTEMODE_ENABLE_REG 0x11 ++#define SDIOWIFI_BLOCK_CNT_REG 0x12 ++#define SDIOWIFI_FLOWCTRL_MASK_REG 0x7F ++#define SDIOWIFI_WR_FIFO_ADDR 0x07 ++#define SDIOWIFI_RD_FIFO_ADDR 0x08 ++ ++#define SDIOWIFI_INTR_ENABLE_REG_V3 0x00 ++#define SDIOWIFI_INTR_PENDING_REG_V3 0x01 ++#define SDIOWIFI_INTR_TO_DEVICE_REG_V3 0x02 ++#define SDIOWIFI_FLOW_CTRL_Q1_REG_V3 0x03 ++#define SDIOWIFI_MISC_INT_STATUS_REG_V3 0x04 ++#define SDIOWIFI_BYTEMODE_LEN_REG_V3 0x05 ++#define SDIOWIFI_BYTEMODE_LEN_MSB_REG_V3 0x06 ++#define SDIOWIFI_BYTEMODE_ENABLE_REG_V3 0x07 ++#define SDIOWIFI_MISC_CTRL_REG_V3 0x08 ++#define SDIOWIFI_FLOW_CTRL_Q2_REG_V3 0x09 ++#define SDIOWIFI_CLK_TEST_RESULT_REG_V3 0x0A ++#define SDIOWIFI_RD_FIFO_ADDR_V3 0x0F ++#define SDIOWIFI_WR_FIFO_ADDR_V3 0x10 ++ ++#define SDIOCLK_FREE_RUNNING_BIT (1 << 6) ++ ++#define SDIOWIFI_PWR_CTRL_INTERVAL 30 ++#define FLOW_CTRL_RETRY_COUNT 50 ++#define BUFFER_SIZE 1536 ++#define TAIL_LEN 4 ++#define TXQLEN (2048*4) ++ ++#define SDIO_SLEEP_ST 0 ++#define SDIO_ACTIVE_ST 1 ++ ++#define DATA_FLOW_CTRL_THRESH 2 ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++#define AICWF_SDIO_TX_LOW_WATER 100 ++#define AICWF_SDIO_TX_HIGH_WATER 500 ++#endif ++ ++#ifdef CONFIG_TEMP_CONTROL ++#define TEMP_GET_INTERVAL (60 * 1000) ++#define TEMP_THD_1 80 //temperature 1 (℃) ++#define TEMP_THD_2 95 //temperature 2 (℃) ++#define BUFFERING_V1 8 ++#define BUFFERING_V2 13 ++#define TMR_INTERVAL_1 60 //timer_1 60ms ++#define TMR_INTERVAL_2 180 //timer_2 130ms ++#endif ++ ++typedef enum { ++ SDIO_TYPE_DATA = 0X00, ++ SDIO_TYPE_CFG = 0X10, ++ SDIO_TYPE_CFG_CMD_RSP = 0X11, ++ SDIO_TYPE_CFG_DATA_CFM = 0X12, ++ SDIO_TYPE_CFG_PRINT = 0X13 ++} sdio_type; ++ ++/* SDIO Device ID */ ++#define SDIO_VENDOR_ID_AIC8801 0x5449 ++#define SDIO_VENDOR_ID_AIC8800DC 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80X2 0xc8a1 ++ ++#define SDIO_DEVICE_ID_AIC8801 0x0145 ++#define SDIO_DEVICE_ID_AIC8800DC 0xc08d ++#define SDIO_DEVICE_ID_AIC8800D80 0x0082 ++#define SDIO_DEVICE_ID_AIC8800D80X2 0x2082 ++ ++enum AICWF_IC{ ++ PRODUCT_ID_AIC8801 = 0, ++ PRODUCT_ID_AIC8800DC, ++ PRODUCT_ID_AIC8800DW, ++ PRODUCT_ID_AIC8800D80, ++ PRODUCT_ID_AIC8800D80X2 ++}; ++ ++ ++struct rwnx_hw; ++ ++struct aic_sdio_reg { ++ u8 bytemode_len_reg; ++ u8 intr_config_reg; ++ u8 sleep_reg; ++ u8 wakeup_reg; ++ u8 flow_ctrl_reg; ++ u8 flowctrl_mask_reg; ++ u8 register_block; ++ u8 bytemode_enable_reg; ++ u8 block_cnt_reg; ++ u8 misc_int_status_reg; ++ u8 rd_fifo_addr; ++ u8 wr_fifo_addr; ++}; ++ ++struct aic_sdio_dev { ++ struct rwnx_hw *rwnx_hw; ++ struct sdio_func *func; ++ struct sdio_func *func2; ++ struct device *dev; ++ struct aicwf_bus *bus_if; ++ struct rwnx_cmd_mgr cmd_mgr; ++ ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ u32 state; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ u8 flowctrl; ++ spinlock_t tx_flow_lock; ++#endif ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ //for sdio pwr ctrl ++ struct timer_list timer; ++ uint active_duration; ++ struct completion pwrctrl_trgg; ++ struct task_struct *pwrctl_tsk; ++ spinlock_t pwrctl_lock; ++ struct semaphore pwrctl_wakeup_sema; ++ #endif ++ u16 chipid; ++ struct aic_sdio_reg sdio_reg; ++ ++ spinlock_t wslock;//AIDEN test ++ bool oob_enable; ++ atomic_t is_bus_suspend; ++ ++#ifdef CONFIG_TEMP_CONTROL ++ spinlock_t tx_flow_lock; ++ struct timer_list netif_timer; ++ struct timer_list tp_ctrl_timer; ++ struct work_struct tp_ctrl_work; ++ struct work_struct netif_work; ++ s8_l cur_temp; ++ bool net_stop; ++ bool on_off; //for command, 0 - off, 1 - on ++ int8_t get_level; //for command, 0 - 100%, 1 - 12%, 2 - 3% ++ int8_t set_level; //for command, 0 - driver auto, 1 - 12%, 2 - 3% ++ int interval_t1; ++ int interval_t2; ++ u8_l cur_stat; //0--normal temp, 1/2--buffering temp ++#endif ++ ++}; ++ ++#ifdef CONFIG_TEMP_CONTROL ++void aicwf_netif_worker(struct work_struct *work); ++void aicwf_temp_ctrl_worker(struct work_struct *work); ++void aicwf_temp_ctrl(struct aic_sdio_dev *sdiodev); ++void aicwf_netif_ctrl(struct aic_sdio_dev *sdiodev, int val); ++#endif ++extern struct aicwf_rx_buff_list aic_rx_buff_list; ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++int aicwf_sdio_func2_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val); ++int aicwf_sdio_func2_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration); ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target); ++#endif ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev); ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++void aicwf_sdio_tx_netif_flowctrl(struct rwnx_hw *rwnx_hw, bool state); ++#endif ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev); ++#ifdef CONFIG_PREALLOC_RX_SKB ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct rx_buff *rxbbuf, u32 size); ++#else ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size); ++#endif ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count); ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_exit(void); ++void aicwf_sdio_register(void); ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt); ++int sdio_bustx_thread(void *data); ++int sdio_busrx_thread(void *data); ++#ifdef CONFIG_OOB ++//new oob feature ++int sdio_busirq_thread(void *data); ++#endif //CONFIG_OOB ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt); ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv, u8 txnow); ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv); ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv); ++extern void aicwf_hostif_ready(void); ++extern void aicwf_hostif_fail(void); ++#ifdef CONFIG_PLATFORM_AMLOGIC ++extern void extern_wifi_set_enable(int is_on); ++extern void sdio_reinit(void); ++#endif /*CONFIG_PLATFORM_AMLOGIC*/ ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size); ++ ++#endif /* AICWF_SDIO_SUPPORT */ ++ ++#endif /*_AICWF_SDMMC_H_*/ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c +new file mode 100644 +index 000000000000..d74bd8d1f420 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c +@@ -0,0 +1,646 @@ ++#include"aicwf_tcp_ack.h" ++//#include"rwnx_tx.h" ++//#include "aicwf_tcp_ack.h" ++#include"rwnx_defs.h" ++extern int intf_tx(struct rwnx_hw *priv,struct msg_buf *msg); ++struct msg_buf *intf_tcp_alloc_msg(struct msg_buf *msg) ++{ ++ //printk("%s \n",__func__); ++ int len=sizeof(struct msg_buf) ; ++ msg = kzalloc(len , /*GFP_KERNEL*/GFP_ATOMIC); ++ if(!msg) ++ printk("%s: alloc failed \n", __func__); ++ memset(msg,0,len); ++ return msg; ++} ++ ++void intf_tcp_drop_msg(struct rwnx_hw *priv, ++ struct msg_buf *msg) ++{ ++ //printk("%s \n",__func__); ++ if (msg->skb) ++ dev_kfree_skb_any(msg->skb); ++ ++ kfree(msg); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void tcp_ack_timeout(unsigned long data) ++#else ++void tcp_ack_timeout(struct timer_list *t) ++#endif ++{ ++ //printk("%s \n",__func__); ++ struct tcp_ack_info *ack_info; ++ struct msg_buf *msg; ++ struct tcp_ack_manage *ack_m = NULL; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ ack_info = (struct tcp_ack_info *)data; ++#else ++ ack_info = container_of(t,struct tcp_ack_info,timer); ++#endif ++ ++ ack_m = container_of(ack_info, struct tcp_ack_manage, ++ ack_info[ack_info->ack_info_num]); ++ ++ write_seqlock_bh(&ack_info->seqlock); ++ msg = ack_info->msgbuf; ++ if (ack_info->busy && msg && !ack_info->in_send_msg) { ++ ack_info->msgbuf = NULL; ++ ack_info->drop_cnt = 0; ++ ack_info->in_send_msg = msg; ++ write_sequnlock_bh(&ack_info->seqlock); ++ intf_tx(ack_m->priv, msg);//send skb ++ //ack_info->in_send_msg = NULL;//add by dwx ++ //write_sequnlock_bh(&ack_info->seqlock); ++ //intf_tx(ack_m->priv, msg); ++ return; ++ } ++ write_sequnlock_bh(&ack_info->seqlock); ++} ++ ++void tcp_ack_init(struct rwnx_hw *priv) ++{ ++ int i; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ ++ printk("%s \n",__func__); ++ memset(ack_m, 0, sizeof(struct tcp_ack_manage)); ++ ack_m->priv = priv; ++ spin_lock_init(&ack_m->lock); ++ atomic_set(&ack_m->max_drop_cnt, TCP_ACK_DROP_CNT); ++ ack_m->last_time = jiffies; ++ ack_m->timeout = msecs_to_jiffies(ACK_OLD_TIME); ++ ++ for (i = 0; i < TCP_ACK_NUM; i++) { ++ ack_info = &ack_m->ack_info[i]; ++ ack_info->ack_info_num = i; ++ seqlock_init(&ack_info->seqlock); ++ ack_info->last_time = jiffies; ++ ack_info->timeout = msecs_to_jiffies(ACK_OLD_TIME); ++ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ setup_timer(&ack_info->timer, tcp_ack_timeout, ++ (unsigned long)ack_info); ++ #else ++ timer_setup(&ack_info->timer,tcp_ack_timeout,0); ++ #endif ++ } ++ ++ atomic_set(&ack_m->enable, 1); ++ ack_m->ack_winsize = MIN_WIN; ++} ++ ++void tcp_ack_deinit(struct rwnx_hw *priv) ++{ ++ int i; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ struct msg_buf *drop_msg = NULL; ++ ++ printk("%s \n",__func__); ++ atomic_set(&ack_m->enable, 0); ++ ++ for (i = 0; i < TCP_ACK_NUM; i++) { ++ drop_msg = NULL; ++ ++ write_seqlock_bh(&ack_m->ack_info[i].seqlock); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_m->ack_info[i].timer); ++#else ++ del_timer(&ack_m->ack_info[i].timer); ++#endif ++ drop_msg = ack_m->ack_info[i].msgbuf; ++ ack_m->ack_info[i].msgbuf = NULL; ++ write_sequnlock_bh(&ack_m->ack_info[i].seqlock); ++ ++ if (drop_msg) ++ intf_tcp_drop_msg(priv, drop_msg);//drop skb ++ } ++} ++ ++int tcp_check_quick_ack(unsigned char *buf, ++ struct tcp_ack_msg *msg) ++{ ++ int ip_hdr_len; ++ unsigned char *temp; ++ struct ethhdr *ethhdr; ++ struct iphdr *iphdr; ++ struct tcphdr *tcphdr; ++ ++ ethhdr = (struct ethhdr *)buf; ++ if (ethhdr->h_proto != htons(ETH_P_IP)) ++ return 0; ++ iphdr = (struct iphdr *)(ethhdr + 1); ++ if (iphdr->version != 4 || iphdr->protocol != IPPROTO_TCP) ++ return 0; ++ ip_hdr_len = iphdr->ihl * 4; ++ temp = (unsigned char *)(iphdr) + ip_hdr_len; ++ tcphdr = (struct tcphdr *)temp; ++ /* TCP_FLAG_ACK */ ++ if (!(temp[13] & 0x10)) ++ return 0; ++ ++ if (temp[13] & 0x8) { ++ msg->saddr = iphdr->daddr; ++ msg->daddr = iphdr->saddr; ++ msg->source = tcphdr->dest; ++ msg->dest = tcphdr->source; ++ msg->seq = ntohl(tcphdr->seq); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int is_drop_tcp_ack(struct tcphdr *tcphdr, int tcp_tot_len, ++ unsigned short *win_scale) ++{ ++ //printk("%s \n",__func__); ++ int drop = 1; ++ int len = tcphdr->doff * 4; ++ unsigned char *ptr; ++ ++ if(tcp_tot_len > len) { ++ drop = 0; ++ } else { ++ len -= sizeof(struct tcphdr); ++ ptr = (unsigned char *)(tcphdr + 1); ++ ++ while ((len > 0) && drop) { ++ int opcode = *ptr++; ++ int opsize; ++ ++ switch (opcode) { ++ case TCPOPT_EOL: ++ break; ++ case TCPOPT_NOP: ++ len--; ++ continue; ++ default: ++ opsize = *ptr++; ++ if (opsize < 2) ++ break; ++ if (opsize > len) ++ break; ++ ++ switch (opcode) { ++ /* TODO: Add other ignore opt */ ++ case TCPOPT_TIMESTAMP: ++ break; ++ case TCPOPT_WINDOW: ++ if (*ptr < 15) ++ *win_scale = (1 << (*ptr)); ++ //printk("%d\n",*win_scale); ++ break; ++ default: ++ drop = 2; ++ } ++ ++ ptr += opsize - 2; ++ len -= opsize; ++ } ++ } ++ } ++ ++ return drop; ++} ++ ++ ++/* flag:0 for not tcp ack ++ * 1 for ack which can be drop ++ * 2 for other ack whith more info ++ */ ++ ++int tcp_check_ack(unsigned char *buf, ++ struct tcp_ack_msg *msg, ++ unsigned short *win_scale) ++{ ++ int ret; ++ int ip_hdr_len; ++ int tcp_tot_len; ++ unsigned char *temp; ++ struct ethhdr *ethhdr; ++ struct iphdr *iphdr; ++ struct tcphdr *tcphdr; ++ ++ ethhdr =(struct ethhdr *)buf; ++ if (ethhdr->h_proto != htons(ETH_P_IP)) ++ return 0; ++ ++ iphdr = (struct iphdr *)(ethhdr + 1); ++ if (iphdr->version != 4 || iphdr->protocol != IPPROTO_TCP) ++ return 0; ++ ++ ip_hdr_len = iphdr->ihl * 4; ++ temp = (unsigned char *)(iphdr) + ip_hdr_len; ++ tcphdr = (struct tcphdr *)temp; ++ /* TCP_FLAG_ACK */ ++ if (!(temp[13] & 0x10)) ++ return 0; ++ ++ tcp_tot_len = ntohs(iphdr->tot_len) - ip_hdr_len;// tcp total len ++ ret = is_drop_tcp_ack(tcphdr, tcp_tot_len, win_scale); ++ //printk("is drop:%d \n",ret); ++ ++ if (ret > 0) { ++ msg->saddr = iphdr->saddr; ++ msg->daddr = iphdr->daddr; ++ msg->source = tcphdr->source; ++ msg->dest = tcphdr->dest; ++ msg->seq = ntohl(tcphdr->ack_seq); ++ msg->win = ntohs(tcphdr->window); ++ } ++ ++ return ret; ++} ++ ++/* return val: -1 for not match, others for match */ ++int tcp_ack_match(struct tcp_ack_manage *ack_m, ++ struct tcp_ack_msg *ack_msg) ++{ ++ int i, ret = -1; ++ unsigned start; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_msg *ack; ++ ++ for (i = 0; ((ret < 0) && (i < TCP_ACK_NUM)); i++) { ++ ack_info = &ack_m->ack_info[i]; ++ do { ++ start = read_seqbegin(&ack_info->seqlock); ++ ret = -1; ++ ++ ack = &ack_info->ack_msg; ++ if (ack_info->busy && ++ ack->dest == ack_msg->dest && ++ ack->source == ack_msg->source && ++ ack->saddr == ack_msg->saddr && ++ ack->daddr == ack_msg->daddr) ++ ret = i; ++ } while(read_seqretry(&ack_info->seqlock, start)); ++ } ++ ++ return ret; ++} ++ ++ ++void tcp_ack_update(struct tcp_ack_manage *ack_m) ++{ ++ int i; ++ struct tcp_ack_info *ack_info; ++ ++ if (time_after(jiffies, ack_m->last_time + ack_m->timeout)) { ++ spin_lock_bh(&ack_m->lock); ++ ack_m->last_time = jiffies; ++ for (i = TCP_ACK_NUM - 1; i >= 0; i--) { ++ ack_info = &ack_m->ack_info[i]; ++ write_seqlock_bh(&ack_info->seqlock); ++ if (ack_info->busy && ++ time_after(jiffies, ack_info->last_time + ++ ack_info->timeout)) { ++ ack_m->free_index = i; ++ ack_m->max_num--; ++ ack_info->busy = 0; ++ } ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++ spin_unlock_bh(&ack_m->lock); ++ } ++} ++ ++/* return val: -1 for no index, others for index */ ++int tcp_ack_alloc_index(struct tcp_ack_manage *ack_m) ++{ ++ int i, ret = -1; ++ struct tcp_ack_info *ack_info; ++ unsigned start; ++ ++ spin_lock_bh(&ack_m->lock); ++ if (ack_m->max_num == TCP_ACK_NUM) { ++ spin_unlock_bh(&ack_m->lock); ++ return -1; ++ } ++ ++ if (ack_m->free_index >= 0) { ++ i = ack_m->free_index; ++ ack_m->free_index = -1; ++ ack_m->max_num++; ++ spin_unlock_bh(&ack_m->lock); ++ return i; ++ } ++ ++ for (i = 0; ((ret < 0) && (i < TCP_ACK_NUM)); i++) { ++ ack_info = &ack_m->ack_info[i]; ++ do { ++ start = read_seqbegin(&ack_info->seqlock); ++ ret = -1; ++ if (!ack_info->busy) { ++ ack_m->free_index = -1; ++ ack_m->max_num++; ++ ret = i; ++ } ++ } while(read_seqretry(&ack_info->seqlock, start)); ++ } ++ spin_unlock_bh(&ack_m->lock); ++ ++ return ret; ++} ++ ++ ++/* return val: 0 for not handle tx, 1 for handle tx */ ++int tcp_ack_handle(struct msg_buf *new_msgbuf, ++ struct tcp_ack_manage *ack_m, ++ struct tcp_ack_info *ack_info, ++ struct tcp_ack_msg *ack_msg, ++ int type) ++{ ++ int quick_ack = 0; ++ struct tcp_ack_msg *ack; ++ int ret = 0; ++ struct msg_buf *drop_msg = NULL; ++ ++ //printk("%s %d",__func__,type); ++ write_seqlock_bh(&ack_info->seqlock); ++ ++ ack_info->last_time = jiffies; ++ ack = &ack_info->ack_msg; ++ ++ if (type == 2) { ++ if (U32_BEFORE(ack->seq, ack_msg->seq)) { ++ ack->seq = ack_msg->seq; ++ if (ack_info->psh_flag && ++ !U32_BEFORE(ack_msg->seq, ++ ack_info->psh_seq)) { ++ ack_info->psh_flag = 0; ++ } ++ ++ if (ack_info->msgbuf) { ++ //printk("%lx \n",ack_info->msgbuf); ++ drop_msg = ack_info->msgbuf; ++ ack_info->msgbuf = NULL; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_info->timer); ++#else ++ del_timer(&ack_info->timer); ++#endif ++ }else{ ++ //printk("msgbuf is NULL \n"); ++ } ++ ++ ack_info->in_send_msg = NULL; ++ ack_info->drop_cnt = atomic_read(&ack_m->max_drop_cnt); ++ } else { ++ printk("%s before abnormal ack: %d, %d\n", ++ __func__, ack->seq, ack_msg->seq); ++ drop_msg = new_msgbuf; ++ ret = 1; ++ } ++ } else if (U32_BEFORE(ack->seq, ack_msg->seq)) { ++ if (ack_info->msgbuf) { ++ drop_msg = ack_info->msgbuf; ++ ack_info->msgbuf = NULL; ++ } ++ ++ if (ack_info->psh_flag && ++ !U32_BEFORE(ack_msg->seq, ack_info->psh_seq)) { ++ ack_info->psh_flag = 0; ++ quick_ack = 1; ++ } else { ++ ack_info->drop_cnt++; ++ } ++ ++ ack->seq = ack_msg->seq; ++ ++ if (quick_ack || (!ack_info->in_send_msg && ++ (ack_info->drop_cnt >= ++ atomic_read(&ack_m->max_drop_cnt)))) { ++ ack_info->drop_cnt = 0; ++ ack_info->in_send_msg = new_msgbuf; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_info->timer); ++#else ++ del_timer(&ack_info->timer); ++#endif ++ } else { ++ ret = 1; ++ ack_info->msgbuf = new_msgbuf; ++ if (!timer_pending(&ack_info->timer)) ++ mod_timer(&ack_info->timer, ++ (jiffies + msecs_to_jiffies(5))); ++ } ++ } else { ++ printk("%s before ack: %d, %d\n", ++ __func__, ack->seq, ack_msg->seq); ++ drop_msg = new_msgbuf; ++ ret = 1; ++ } ++ ++ write_sequnlock_bh(&ack_info->seqlock); ++ ++ if (drop_msg) ++ intf_tcp_drop_msg(ack_m->priv, drop_msg);// drop skb ++ ++ return ret; ++} ++ ++int tcp_ack_handle_new(struct msg_buf *new_msgbuf, ++ struct tcp_ack_manage *ack_m, ++ struct tcp_ack_info *ack_info, ++ struct tcp_ack_msg *ack_msg, ++ int type) ++{ ++ int quick_ack = 0; ++ struct tcp_ack_msg *ack; ++ int ret = 0; ++ struct msg_buf *drop_msg = NULL; ++ //struct msg_buf * send_msg = NULL; ++ //printk("",); ++ write_seqlock_bh(&ack_info->seqlock); ++ ++ ack_info->last_time = jiffies; ++ ack = &ack_info->ack_msg; ++ ++ if(U32_BEFORE(ack->seq, ack_msg->seq)){ ++ if (ack_info->msgbuf) { ++ drop_msg = ack_info->msgbuf; ++ ack_info->msgbuf = NULL; ++ //ack_info->drop_cnt++; ++ } ++ ++ if (ack_info->psh_flag && ++ !U32_BEFORE(ack_msg->seq, ack_info->psh_seq)) { ++ ack_info->psh_flag = 0; ++ quick_ack = 1; ++ } else { ++ ack_info->drop_cnt++; ++ } ++ ++ ack->seq = ack_msg->seq; ++ ++ if(quick_ack || (!ack_info->in_send_msg && ++ (ack_info->drop_cnt >= ++ atomic_read(&ack_m->max_drop_cnt)))){ ++ ack_info->drop_cnt = 0; ++ //send_msg = new_msgbuf; ++ ack_info->in_send_msg = new_msgbuf; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_info->timer); ++#else ++ del_timer(&ack_info->timer); ++#endif ++ }else{ ++ ret = 1; ++ ack_info->msgbuf = new_msgbuf; ++ if (!timer_pending(&ack_info->timer)) ++ mod_timer(&ack_info->timer, ++ (jiffies + msecs_to_jiffies(5))); ++ } ++ ++ //ret = 1; ++ }else { ++ printk("%s before ack: %d, %d\n", ++ __func__, ack->seq, ack_msg->seq); ++ drop_msg = new_msgbuf; ++ ret = 1; ++ } ++ ++ /*if(send_msg){ ++ intf_tx(ack_m->priv,send_msg); ++ ack_info->in_send_msg=NULL; ++ }*/ ++ ++ //ack_info->in_send_msg=NULL; ++ ++ write_sequnlock_bh(&ack_info->seqlock); ++ ++ /*if(send_msg){ ++ intf_tx(ack_m->priv,send_msg); ++ //ack_info->in_send_msg=NULL; ++ }*/ ++ ++ if (drop_msg) ++ intf_tcp_drop_msg(ack_m->priv, drop_msg);// drop skb ++ ++ return ret; ++ ++} ++ ++void filter_rx_tcp_ack(struct rwnx_hw *priv, ++ unsigned char *buf, unsigned plen) ++{ ++ int index; ++ struct tcp_ack_msg ack_msg; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ ++ if (!atomic_read(&ack_m->enable)) ++ return; ++ ++ if ((plen > MAX_TCP_ACK) || ++ !tcp_check_quick_ack(buf, &ack_msg)) ++ return; ++ ++ index = tcp_ack_match(ack_m, &ack_msg); ++ if (index >= 0) { ++ ack_info = ack_m->ack_info + index; ++ write_seqlock_bh(&ack_info->seqlock); ++ ack_info->psh_flag = 1; ++ ack_info->psh_seq = ack_msg.seq; ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++} ++ ++/* return val: 0 for not filter, 1 for filter */ ++int filter_send_tcp_ack(struct rwnx_hw *priv, ++ struct msg_buf *msgbuf, ++ unsigned char *buf, unsigned int plen) ++{ ++ //printk("%s \n",__func__); ++ int ret = 0; ++ int index, drop; ++ unsigned short win_scale = 0; ++ unsigned int win = 0; ++ struct tcp_ack_msg ack_msg; ++ struct tcp_ack_msg *ack; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ ++ tcp_ack_update(ack_m); ++ drop = tcp_check_ack(buf, &ack_msg, &win_scale); ++ //printk("drop:%d win_scale:%d",drop,win_scale); ++ if (!drop && (0 == win_scale)) ++ return 0; ++ ++ index = tcp_ack_match(ack_m, &ack_msg); ++ if (index >= 0) { ++ ack_info = ack_m->ack_info + index; ++ if ((0 != win_scale) && ++ (ack_info->win_scale != win_scale)) { ++ write_seqlock_bh(&ack_info->seqlock); ++ ack_info->win_scale = win_scale; ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++ ++ if (drop > 0 && atomic_read(&ack_m->enable)) { ++ win = ack_info->win_scale * ack_msg.win; ++ if ((win_scale!=0) && (win < (ack_m->ack_winsize * SIZE_KB))) ++ { ++ drop = 2; ++ printk("%d %d %d",win_scale,win,(ack_m->ack_winsize * SIZE_KB)); ++ } ++ ret = tcp_ack_handle_new(msgbuf, ack_m, ack_info, ++ &ack_msg, drop); ++ } ++ ++ goto out; ++ } ++ ++ index = tcp_ack_alloc_index(ack_m); ++ if (index >= 0) { ++ write_seqlock_bh(&ack_m->ack_info[index].seqlock); ++ ack_m->ack_info[index].busy = 1; ++ ack_m->ack_info[index].psh_flag = 0; ++ ack_m->ack_info[index].last_time = jiffies; ++ ack_m->ack_info[index].drop_cnt = ++ atomic_read(&ack_m->max_drop_cnt); ++ ack_m->ack_info[index].win_scale = ++ (win_scale != 0) ? win_scale : 1; ++ ++ //ack_m->ack_info[index].msgbuf = NULL; ++ //ack_m->ack_info[index].in_send_msg = NULL; ++ ack = &ack_m->ack_info[index].ack_msg; ++ ack->dest = ack_msg.dest; ++ ack->source = ack_msg.source; ++ ack->saddr = ack_msg.saddr; ++ ack->daddr = ack_msg.daddr; ++ ack->seq = ack_msg.seq; ++ write_sequnlock_bh(&ack_m->ack_info[index].seqlock); ++ } ++ ++out: ++ return ret; ++} ++ ++void move_tcpack_msg(struct rwnx_hw *priv, ++ struct msg_buf *msg) ++{ ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ int i = 0; ++ ++ if (!atomic_read(&ack_m->enable)) ++ return; ++ ++ //if (msg->len > MAX_TCP_ACK) ++ // return; ++ ++ for (i = 0; i < TCP_ACK_NUM; i++) { ++ ack_info = &ack_m->ack_info[i]; ++ write_seqlock_bh(&ack_info->seqlock); ++ if (ack_info->busy && (ack_info->in_send_msg == msg)) ++ ack_info->in_send_msg = NULL; ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h +new file mode 100644 +index 000000000000..542023fc577c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h +@@ -0,0 +1,92 @@ ++#ifndef _AICWF_TCP_ACK_H_ ++#define _AICWF_TCP_ACK_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define TCP_ACK_NUM 32 ++#define TCP_ACK_EXIT_VAL 0x800 ++#define TCP_ACK_DROP_CNT 10 ++ ++#define ACK_OLD_TIME 4000 ++#define U32_BEFORE(a, b) ((__s32)((__u32)a - (__u32)b) <= 0) ++ ++#define MAX_TCP_ACK 200 ++/*min window size in KB, it's 256KB*/ ++#define MIN_WIN 256 ++#define SIZE_KB 1024 ++ ++ ++struct msg_buf { ++ //struct list_head list; ++ struct sk_buff *skb; ++ struct rwnx_vif *rwnx_vif; ++ /* data just tx cmd use,not include the head */ ++}; ++ ++struct tcp_ack_msg { ++ u16 source; ++ u16 dest; ++ s32 saddr; ++ s32 daddr; ++ u32 seq; ++ u16 win; ++}; ++ ++ ++struct tcp_ack_info { ++ int ack_info_num; ++ int busy; ++ int drop_cnt; ++ int psh_flag; ++ u32 psh_seq; ++ u16 win_scale; ++ /* seqlock for ack info */ ++ seqlock_t seqlock; ++ unsigned long last_time; ++ unsigned long timeout; ++ struct timer_list timer; ++ struct msg_buf *msgbuf; ++ struct msg_buf *in_send_msg; ++ struct tcp_ack_msg ack_msg; ++}; ++ ++struct tcp_ack_manage { ++ /* 1 filter */ ++ atomic_t enable; ++ int max_num; ++ int free_index; ++ unsigned long last_time; ++ unsigned long timeout; ++ atomic_t max_drop_cnt; ++ /* lock for tcp ack alloc and free */ ++ spinlock_t lock; ++ struct rwnx_hw *priv; ++ struct tcp_ack_info ack_info[TCP_ACK_NUM]; ++ /*size in KB*/ ++ unsigned int ack_winsize; ++}; ++ ++struct msg_buf *intf_tcp_alloc_msg(struct msg_buf *msg); ++ ++void tcp_ack_init(struct rwnx_hw *priv); ++ ++void tcp_ack_deinit(struct rwnx_hw *priv); ++ ++ ++int is_drop_tcp_ack(struct tcphdr *tcphdr, int tcp_tot_len, unsigned short *win_scale); ++ ++int is_tcp_ack(struct sk_buff *skb, unsigned short *win_scale); ++ ++int filter_send_tcp_ack(struct rwnx_hw *priv, struct msg_buf *msgbuf,unsigned char *buf, unsigned int plen); ++ ++void filter_rx_tcp_ack(struct rwnx_hw *priv,unsigned char *buf, unsigned plen); ++ ++void move_tcpack_msg(struct rwnx_hw *priv, struct msg_buf * msg); ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c +new file mode 100644 +index 000000000000..555a8deadf54 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c +@@ -0,0 +1,891 @@ ++/** ++ * aicwf_bus.c ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "lmac_msg.h" ++#include "aicwf_txrxif.h" ++#include "rwnx_platform.h" ++#include "rwnx_defs.h" ++#include "rwnx_msg_rx.h" ++#include "rwnx_rx.h" ++#include "aicwf_rx_prealloc.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "sdio_host.h" ++#endif ++#include "aic_bsp_export.h" ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++void aicwf_rxframe_queue_init_2(struct rx_frame_queue *pq, int max_len) ++{ ++ //int prio; ++ ++ memset(pq, 0, offsetof(struct rx_frame_queue, queuelist) + (sizeof(struct list_head))); ++ pq->qmax = (u16)max_len; ++ INIT_LIST_HEAD(&pq->queuelist); ++#if 0 ++ memset(pq, 0, offsetof(struct rx_frame_queue, queuelist) + (sizeof(struct list_head) * num_prio)); ++ pq->num_prio = (u16)num_prio; ++ pq->qmax = (u16)max_len; ++ ++ for (prio = 0; prio < num_prio; prio++) { ++ INIT_LIST_HEAD(&pq->queuelist[prio]); ++ } ++#endif ++} ++ ++//extern struct aic_sdio_dev *g_sdiodev; ++void rxbuff_queue_flush(struct aicwf_rx_priv* rx_priv) ++{ ++ ++ //int prio; ++ struct rx_frame_queue *pq = &rx_priv->rxq; ++ struct list_head *pos; ++ struct list_head *n; ++ struct list_head *head; ++ struct rx_buff *tempbuf = NULL; ++ ++ head = &pq->queuelist; ++ list_for_each_safe(pos, n, head) { ++ tempbuf = list_entry(pos, struct rx_buff, queue); ++ list_del_init(&tempbuf->queue); ++#if 0 ++ rxbuff_free(tempbuf); ++#else ++ aicwf_prealloc_rxbuff_free(tempbuf, &rx_priv->rxbuff_lock); ++#endif ++ pq->qcnt--; ++ } ++} ++#endif ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if; ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return -1; ++ } ++ bus_if = dev_get_drvdata(dev); ++ bus_if->cmd_buf = kzalloc(CMD_BUF_MAX, GFP_KERNEL); ++ if (!bus_if->cmd_buf) { ++ ret = -ENOMEM; ++ txrx_err("proto_attach failed\n"); ++ goto fail; ++ } ++ memset(bus_if->cmd_buf, '\0', CMD_BUF_MAX); ++ ++ init_completion(&bus_if->bustx_trgg); ++ init_completion(&bus_if->busrx_trgg); ++ //new oob feature ++ init_completion(&bus_if->busirq_trgg); ++#ifdef AICWF_SDIO_SUPPORT ++ spin_lock_init(&bus_if->bus_priv.sdio->wslock);//AIDEN test ++ bus_if->bustx_thread = kthread_run(sdio_bustx_thread, (void *)bus_if, "aicwf_bustx_thread"); ++ bus_if->busrx_thread = kthread_run(sdio_busrx_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busrx_thread"); ++ //new oob feature ++#ifdef CONFIG_OOB ++ if(bus_if->bus_priv.sdio->oob_enable){ ++ bus_if->busirq_thread = kthread_run(sdio_busirq_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busirq_thread"); ++ } ++#endif //CONFIG_OOB ++#endif ++#ifdef AICWF_USB_SUPPORT ++ bus_if->bustx_thread = kthread_run(usb_bustx_thread, (void *)bus_if, "aicwf_bustx_thread"); ++ bus_if->busrx_thread = kthread_run(usb_busrx_thread, (void *)bus_if->bus_priv.usb->rx_priv, "aicwf_busrx_thread"); ++#endif ++ ++ if (IS_ERR(bus_if->bustx_thread)) { ++ bus_if->bustx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ goto fail; ++ } ++ ++ if (IS_ERR(bus_if->busrx_thread)) { ++ bus_if->busrx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ goto fail; ++ } ++ ++ return ret; ++fail: ++ aicwf_bus_deinit(dev); ++ ++ return ret; ++} ++ ++void aicwf_bus_deinit(struct device *dev) ++{ ++ struct aicwf_bus *bus_if; ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usb; ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return; ++ } ++ AICWFDBG(LOGINFO, "%s Enter\r\n", __func__); ++ bus_if = dev_get_drvdata(dev); ++ aicwf_bus_stop(bus_if); ++ ++#ifdef AICWF_USB_SUPPORT ++ usb = bus_if->bus_priv.usb; ++ if (g_rwnx_plat->enabled) ++ rwnx_platform_deinit(usb->rwnx_hw); ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ sdiodev = bus_if->bus_priv.sdio; ++ if (g_rwnx_plat && g_rwnx_plat->enabled) { ++ rwnx_platform_deinit(sdiodev->rwnx_hw); ++ } ++#endif ++ ++ if (bus_if->cmd_buf) { ++ kfree(bus_if->cmd_buf); ++ bus_if->cmd_buf = NULL; ++ } ++ ++ if (bus_if->bustx_thread) { ++ complete_all(&bus_if->bustx_trgg); ++ kthread_stop(bus_if->bustx_thread); ++ bus_if->bustx_thread = NULL; ++ } ++ AICWFDBG(LOGINFO, "%s Exit\r\n", __func__); ++} ++ ++void aicwf_frame_tx(void *dev, struct sk_buff *skb) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ aicwf_bus_txdata(sdiodev->bus_if, skb); ++#else ++ struct aic_usb_dev *usbdev = (struct aic_usb_dev *)dev; ++ ++ if (!usbdev->state) { ++ txrx_err("down\n"); ++ aicwf_usb_tx_flowctrl(usbdev->rwnx_hw, true); ++ dev_kfree_skb(skb); ++ return; ++ } ++ aicwf_bus_txdata(usbdev->bus_if, skb); ++#endif ++} ++ ++struct aicwf_tx_priv *aicwf_tx_init(void *arg) ++{ ++ struct aicwf_tx_priv *tx_priv; ++ ++ tx_priv = kzalloc(sizeof(struct aicwf_tx_priv), GFP_KERNEL); ++ if (!tx_priv) ++ return NULL; ++ ++#ifdef AICWF_SDIO_SUPPORT ++ tx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++#else ++ tx_priv->usbdev = (struct aic_usb_dev *)arg; ++#endif ++ ++ atomic_set(&tx_priv->aggr_count, 0); ++#ifdef CONFIG_RESV_MEM_SUPPORT ++ tx_priv->aggr_buf = aicbsp_resv_mem_alloc_skb(MAX_AGGR_TXPKT_LEN, AIC_RESV_MEM_TXDATA); ++#else ++ tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN); ++#endif ++ if (!tx_priv->aggr_buf) { ++ txrx_err("Alloc bus->txdata_buf failed!\n"); ++ kfree(tx_priv); ++ return NULL; ++ } ++ tx_priv->head = tx_priv->aggr_buf->data; ++ tx_priv->tail = tx_priv->aggr_buf->data; ++ ++#ifdef CONFIG_SDIO_ADMA ++ tx_priv->aggr_segcnt = 0; ++ tx_priv->len = 0; ++#endif ++ ++ return tx_priv; ++} ++ ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv) ++{ ++ if (tx_priv && tx_priv->aggr_buf) { ++#ifdef CONFIG_RESV_MEM_SUPPORT ++ aicbsp_resv_mem_kfree_skb(tx_priv->aggr_buf, AIC_RESV_MEM_TXDATA); ++#else ++ dev_kfree_skb(tx_priv->aggr_buf); ++#endif ++ kfree(tx_priv); ++ } ++#ifdef CONFIG_SDIO_ADMA ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++#endif ++} ++ ++#ifdef AICWF_SDIO_SUPPORT ++#ifdef CONFIG_PREALLOC_RX_SKB ++static bool aicwf_another_ptk_1(struct rx_buff *buffer) ++{ ++ u8 *read = buffer->read; ++ u16 aggr_len = 0; ++ ++ BUG_ON((read - buffer->start)%4 != 0); ++ ++ if(read == NULL || read >= buffer->end) { ++ return false; ++ } ++ ++ aggr_len = (*read | (*(read + 1) << 8)); ++ if(aggr_len == 0) { ++ return false; ++ } ++ ++ return true; ++} ++#else ++static bool aicwf_another_ptk(struct sk_buff *skb) ++{ ++ u8 *data; ++ u16 aggr_len = 0; ++ ++ if (skb->data == NULL || skb->len == 0) { ++ return false; ++ } ++ data = skb->data; ++ aggr_len = (*skb->data | (*(skb->data + 1) << 8)); ++ if (aggr_len == 0) { ++ return false; ++ } ++ ++ return true; ++} ++#endif ++#endif ++ ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ int ret = 0; ++ unsigned long flags = 0; ++#ifndef CONFIG_PREALLOC_RX_SKB ++ struct sk_buff *skb = NULL; ++#endif ++ u16 pkt_len = 0; ++ struct sk_buff *skb_inblock = NULL; ++ u16 aggr_len = 0, adjust_len = 0; ++ u8 *data = NULL; ++ u8_l *msg = NULL; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_buff *buffer = NULL; ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (!rx_priv->rxq.qcnt) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ buffer = rxbuff_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (buffer == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ while (aicwf_another_ptk_1(buffer)) { ++ data = buffer->read; ++ pkt_len = (*data | (*(data + 1) << 8)); ++ ++ if ((data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL); ++ if (skb_inblock == NULL) { ++ txrx_err("no more space! skip\n"); ++ buffer->read = buffer->read + adjust_len; ++ continue; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ buffer->read = buffer->read + adjust_len; ++ } else { ++ // type : config ++ aggr_len = pkt_len; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ msg = kmalloc(aggr_len+4, GFP_KERNEL); ++ if (msg == NULL) { ++ txrx_err("no more space for msg!\n"); ++ aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock); ++ return -EBADE; ++ } ++ ++ memcpy(msg, data, aggr_len + 4); ++ if (((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) && (rx_priv->sdiodev->bus_if->state != BUS_DOWN_ST)) ++ rwnx_rx_handle_msg(rx_priv->sdiodev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) ++ aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_PRINT) ++ rwnx_rx_handle_print(rx_priv->sdiodev->rwnx_hw, msg + 4, aggr_len); ++ ++ buffer->read = buffer->read + (adjust_len + 4); ++ kfree(msg); ++ } ++ } ++ ++ aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock); ++ ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ ++ #else ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ skb = aicwf_frame_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (skb == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ while (aicwf_another_ptk(skb)) { ++ data = skb->data; ++ pkt_len = (*skb->data | (*(skb->data + 1) << 8)); ++ ++ if ((skb->data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL); ++ if (skb_inblock == NULL) { ++ txrx_err("no more space! skip\n"); ++ skb_pull(skb, adjust_len); ++ continue; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ skb_pull(skb, adjust_len); ++ } else { ++ // type : config ++ aggr_len = pkt_len; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ msg = kmalloc(aggr_len+4, GFP_KERNEL); ++ if (msg == NULL) { ++ txrx_err("no more space for msg!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ ++ memcpy(msg, data, aggr_len + 4); ++ if (((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) && (rx_priv->sdiodev->bus_if->state != BUS_DOWN_ST)) ++ rwnx_rx_handle_msg(rx_priv->sdiodev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) ++ aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_PRINT) ++ rwnx_rx_handle_print(rx_priv->sdiodev->rwnx_hw, msg + 4, aggr_len); ++ ++ skb_pull(skb, adjust_len+4); ++ kfree(msg); ++ } ++ } ++ ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ #endif ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(rx_priv->sdiodev, SDIO_ACTIVE_ST); ++ #endif ++ ++ return ret; ++#else //AICWF_USB_SUPPORT ++ int ret = 0; ++ unsigned long flags = 0; ++ struct sk_buff *skb = NULL; /* Packet for event or data frames */ ++ u16 pkt_len = 0; ++ struct sk_buff *skb_inblock = NULL; ++ u16 aggr_len = 0, adjust_len = 0; ++ u8 *data = NULL; ++ u8_l *msg = NULL; ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { ++ usb_info("no more rxdata\n"); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ skb = aicwf_frame_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (skb == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ data = skb->data; ++ pkt_len = (*skb->data | (*(skb->data + 1) << 8)); ++ //printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]); ++ if (pkt_len > 1600) { ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ continue; ++ } ++ ++ if ((skb->data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv ++ if (skb_inblock == NULL) { ++ txrx_err("no more space! skip!\n"); ++ skb_pull(skb, adjust_len); ++ continue; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ ///TODO: here need to add rx data process ++ ++ skb_pull(skb, adjust_len); ++ } else { // type : config ++ aggr_len = pkt_len; ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ msg = kmalloc(aggr_len+4, GFP_KERNEL); ++ if (msg == NULL) { ++ txrx_err("no more space for msg!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ memcpy(msg, data, aggr_len + 4); ++ if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP) ++ rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM) ++ aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4)); ++ skb_pull(skb, adjust_len + 4); ++ kfree(msg); ++ } ++ ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ ++ return ret; ++#endif //AICWF_SDIO_SUPPORT ++} ++ ++static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize) ++{ ++ int i; ++ struct recv_msdu *req, *reqs; ++ ++ reqs = vmalloc(qsize*sizeof(struct recv_msdu)); ++ if (reqs == NULL) ++ return NULL; ++ ++ req = reqs; ++ for (i = 0; i < qsize; i++) { ++ INIT_LIST_HEAD(&req->rxframe_list); ++ list_add(&req->rxframe_list, q); ++ req++; ++ } ++ ++ return reqs; ++} ++ ++struct aicwf_rx_priv *aicwf_rx_init(void *arg) ++{ ++ struct aicwf_rx_priv *rx_priv; ++ rx_priv = kzalloc(sizeof(struct aicwf_rx_priv), GFP_KERNEL); ++ if (!rx_priv) ++ return NULL; ++ ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++#else ++ rx_priv->usbdev = (struct aic_usb_dev *)arg; ++#endif ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ aicwf_rxframe_queue_init_2(&rx_priv->rxq, MAX_RXQLEN); ++ #else ++ aicwf_frame_queue_init(&rx_priv->rxq, 1, MAX_RXQLEN); ++ #endif ++ spin_lock_init(&rx_priv->rxqlock); ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ spin_lock_init(&rx_priv->rxbuff_lock); ++ aicwf_prealloc_init(); ++ #endif ++ atomic_set(&rx_priv->rx_cnt, 0); ++ ++#ifdef AICWF_RX_REORDER ++ INIT_LIST_HEAD(&rx_priv->rxframes_freequeue); ++ spin_lock_init(&rx_priv->freeq_lock); ++ rx_priv->recv_frames = aicwf_rxframe_queue_init(&rx_priv->rxframes_freequeue, MAX_REORD_RXFRAME); ++ if (!rx_priv->recv_frames) { ++ txrx_err("no enough buffer for free recv frame queue!\n"); ++ kfree(rx_priv); ++ return NULL; ++ } ++ spin_lock_init(&rx_priv->stas_reord_lock); ++ INIT_LIST_HEAD(&rx_priv->stas_reord_list); ++#endif ++ ++ return rx_priv; ++} ++ ++ ++static void aicwf_recvframe_queue_deinit(struct list_head *q) ++{ ++ struct recv_msdu *req, *next; ++ ++ list_for_each_entry_safe(req, next, q, rxframe_list) { ++ list_del_init(&req->rxframe_list); ++ } ++} ++ ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv) ++{ ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *tmp; ++ ++ AICWFDBG(LOGINFO, "%s\n", __func__); ++ ++ list_for_each_entry_safe(reord_info, tmp, ++ &rx_priv->stas_reord_list, list) { ++ reord_deinit_sta(rx_priv, reord_info); ++ } ++#endif ++ ++#ifdef AICWF_SDIO_SUPPORT ++ AICWFDBG(LOGINFO, "sdio rx thread\n"); ++ if (rx_priv->sdiodev->bus_if->busrx_thread) { ++ complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg); ++ kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread); ++ rx_priv->sdiodev->bus_if->busrx_thread = NULL; ++ } ++#ifdef CONFIG_OOB ++ if(rx_priv->sdiodev->oob_enable){ ++ //new oob feature ++ if (rx_priv->sdiodev->bus_if->busirq_thread) { ++ complete_all(&rx_priv->sdiodev->bus_if->busirq_trgg); ++ kthread_stop(rx_priv->sdiodev->bus_if->busirq_thread); ++ rx_priv->sdiodev->bus_if->busirq_thread = NULL; ++ } ++ } ++#endif //CONFIG_OOB ++#endif ++#ifdef AICWF_USB_SUPPORT ++ if (rx_priv->usbdev->bus_if->busrx_thread) { ++ complete_all(&rx_priv->usbdev->bus_if->busrx_trgg); ++ kthread_stop(rx_priv->usbdev->bus_if->busrx_thread); ++ rx_priv->usbdev->bus_if->busrx_thread = NULL; ++ } ++#endif ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ rxbuff_queue_flush(rx_priv); ++ #else ++ aicwf_frame_queue_flush(&rx_priv->rxq); ++ #endif ++ ++#ifdef AICWF_RX_REORDER ++ aicwf_recvframe_queue_deinit(&rx_priv->rxframes_freequeue); ++ if (rx_priv->recv_frames) ++ vfree(rx_priv->recv_frames); ++#endif ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ aicwf_prealloc_exit(); ++ #endif ++ kfree(rx_priv); ++ ++ AICWFDBG(LOGINFO, "%s exit \n", __func__); ++} ++ ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt) ++{ ++ return aicwf_frame_enq(dev, q, pkt, 0); ++} ++ ++ ++void aicwf_dev_skb_free(struct sk_buff *skb) ++{ ++ if (!skb) ++ return; ++ ++ dev_kfree_skb_any(skb); ++} ++ ++static struct sk_buff *aicwf_frame_queue_penq(struct frame_queue *pq, int prio, struct sk_buff *p) ++{ ++ struct sk_buff_head *q; ++ ++ if (pq->queuelist[prio].qlen >= pq->qmax) ++ return NULL; ++ ++ q = &pq->queuelist[prio]; ++ __skb_queue_tail(q, p); ++ pq->qcnt++; ++ if (pq->hi_prio < prio) ++ pq->hi_prio = (u16)prio; ++ ++ return p; ++} ++ ++void aicwf_frame_queue_flush(struct frame_queue *pq) ++{ ++ int prio; ++ struct sk_buff_head *q; ++ struct sk_buff *p, *next; ++ ++ for (prio = 0; prio < pq->num_prio; prio++) { ++ q = &pq->queuelist[prio]; ++ skb_queue_walk_safe(q, p, next) { ++ skb_unlink(p, q); ++ aicwf_dev_skb_free(p); ++ pq->qcnt--; ++ } ++ } ++} ++ ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len) ++{ ++ int prio; ++ ++ memset(pq, 0, offsetof(struct frame_queue, queuelist) + (sizeof(struct sk_buff_head) * num_prio)); ++ pq->num_prio = (u16)num_prio; ++ pq->qmax = (u16)max_len; ++ ++ for (prio = 0; prio < num_prio; prio++) { ++ skb_queue_head_init(&pq->queuelist[prio]); ++ } ++} ++ ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out) ++{ ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ for (prio = 0; prio < pq->hi_prio; prio++) ++ if (!skb_queue_empty(&pq->queuelist[prio])) ++ break; ++ ++ if (prio_out) ++ *prio_out = prio; ++ ++ return skb_peek_tail(&pq->queuelist[prio]); ++} ++ ++bool aicwf_is_framequeue_empty(struct frame_queue *pq) ++{ ++ int prio, len = 0; ++ ++ for (prio = 0; prio <= pq->hi_prio; prio++) ++ len += pq->queuelist[prio].qlen; ++ ++ if (len > 0) ++ return false; ++ else ++ return true; ++} ++ ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq) ++{ ++ struct sk_buff_head *q; ++ struct sk_buff *p; ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ while ((prio = pq->hi_prio) > 0 && skb_queue_empty(&pq->queuelist[prio])) ++ pq->hi_prio--; ++ ++ q = &pq->queuelist[prio]; ++ p = __skb_dequeue(q); ++ if (p == NULL) ++ return NULL; ++ ++ pq->qcnt--; ++ ++ return p; ++} ++#if 0 ++static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio) ++{ ++ struct sk_buff_head *q = &pq->queuelist[prio]; ++ struct sk_buff *p = skb_dequeue_tail(q); ++ ++ if (!p) ++ return NULL; ++ ++ pq->qcnt--; ++ return p; ++} ++#endif ++ ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio) ++{ ++ #if 0 ++ struct sk_buff *p = NULL; ++ int prio_modified = -1; ++ ++ if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { ++ aicwf_frame_queue_penq(q, prio, pkt); ++ return true; ++ } ++ if (q->queuelist[prio].qlen >= q->qmax) { ++ prio_modified = prio; ++ } else if (q->qcnt >= q->qmax) { ++ p = aicwf_frame_queue_peek_tail(q, &prio_modified); ++ if (prio_modified > prio) ++ return false; ++ } ++ ++ if (prio_modified >= 0) { ++ if (prio_modified == prio) ++ return false; ++ ++ p = aicwf_skb_dequeue_tail(q, prio_modified); ++ aicwf_dev_skb_free(p); ++ ++ p = aicwf_frame_queue_penq(q, prio_modified, pkt); ++ if (p == NULL) ++ txrx_err("failed\n"); ++ } ++ ++ return p != NULL; ++ #else ++ if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { ++ aicwf_frame_queue_penq(q, prio, pkt); ++ return true; ++ } else ++ return false; ++ #endif ++} ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++void rxbuff_free(struct rx_buff *rxbuff) ++{ ++ kfree(rxbuff->data); ++ kfree(rxbuff); ++} ++ ++struct rx_buff *rxbuff_queue_penq(struct rx_frame_queue *pq, struct rx_buff *p) ++{ ++ ++ struct list_head *q; ++ if (pq->qcnt >= pq->qmax) ++ return NULL; ++ ++ q = &pq->queuelist; ++ list_add_tail(&p->queue,q); ++ ++ pq->qcnt++; ++ ++ return p; ++} ++ ++struct rx_buff *rxbuff_dequeue(struct rx_frame_queue *pq) ++{ ++ struct rx_buff *p = NULL; ++ ++ if (pq->qcnt == 0) { ++ printk("%s %d, rxq is empty\n", __func__, __LINE__); ++ return NULL; ++ } ++ ++ if(list_empty(&pq->queuelist)) { ++ printk("%s %d, rxq is empty\n", __func__, __LINE__); ++ return NULL; ++ } else { ++ p = list_first_entry(&pq->queuelist, struct rx_buff, queue); ++ list_del_init(&p->queue); ++ pq->qcnt--; ++ } ++ ++ return p; ++} ++ ++bool aicwf_rxbuff_enqueue(struct device *dev, struct rx_frame_queue *rxq, struct rx_buff *pkt) ++{ ++// struct rx_buff *p = NULL; ++ ++ if ((rxq == NULL) || (pkt == NULL)) { ++ printk("%s %d, rxq or pkt is NULL\n", __func__, __LINE__); ++ return false; ++ } ++ ++ if (rxq->qcnt < rxq->qmax) { ++ if (rxbuff_queue_penq(rxq, pkt)) { ++ return true; ++ } else { ++ printk("%s %d, rxbuff enqueue fail\n", __func__, __LINE__); ++ return false; ++ } ++ } else { ++ printk("%s %d, rxq or pkt is full\n", __func__, __LINE__); ++ return false; ++ } ++} ++#endif ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h +new file mode 100644 +index 000000000000..0774c1676235 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h +@@ -0,0 +1,284 @@ ++/** ++ * aicwf_txrxif.h ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_TXRXIF_H_ ++#define _AICWF_TXRXIF_H_ ++ ++#include ++#include ++#include "ipc_shared.h" ++#include "aicwf_rx_prealloc.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#else ++#include "aicwf_usb.h" ++#endif ++ ++#define CMD_BUF_MAX 1536 ++#define TXPKT_BLOCKSIZE 512 ++#define MAX_AGGR_TXPKT_LEN (1536*64) ++#define CMD_TX_TIMEOUT 5000 ++#define TX_ALIGNMENT 4 ++ ++#define RX_HWHRD_LEN 60 //58->60 word allined ++#define CCMP_OR_WEP_INFO 8 ++#define MAX_RXQLEN 2000 ++#define RX_ALIGNMENT 4 ++ ++#define DEBUG_ERROR_LEVEL 0 ++#define DEBUG_DEBUG_LEVEL 1 ++#define DEBUG_INFO_LEVEL 2 ++ ++#define DBG_LEVEL DEBUG_DEBUG_LEVEL ++ ++#define txrx_err(fmt, ...) pr_err("txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define sdio_err(fmt, ...) pr_err("sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define usb_err(fmt, ...) pr_err("usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL ++#define txrx_dbg(fmt, ...) printk("txrx: " fmt, ##__VA_ARGS__) ++#define sdio_dbg(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__) ++#define usb_dbg(fmt, ...) printk("aicusb: " fmt, ##__VA_ARGS__) ++#else ++#define txrx_dbg(fmt, ...) ++#define sdio_dbg(fmt, ...) ++#define usb_dbg(fmt, ...) ++#endif ++#if DBG_LEVEL >= DEBUG_INFO_LEVEL ++#define txrx_info(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__) ++#define sdio_info(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__) ++#define usb_info(fmt, ...) printk("aicusb: " fmt, ##__VA_ARGS__) ++#else ++#define txrx_info(fmt, ...) ++#define sdio_info(fmt, ...) ++#define usb_info(fmt, ...) ++#endif ++ ++enum aicwf_bus_state { ++ BUS_DOWN_ST, ++ BUS_UP_ST ++}; ++ ++struct aicwf_bus_ops { ++ int (*start) (struct device *dev); ++ void (*stop) (struct device *dev); ++ int (*txdata) (struct device *dev, struct sk_buff *skb); ++ int (*txmsg) (struct device *dev, u8 *msg, uint len); ++}; ++ ++struct frame_queue { ++ u16 num_prio; ++ u16 hi_prio; ++ u16 qmax; /* max number of queued frames */ ++ u16 qcnt; ++ struct sk_buff_head queuelist[8]; ++}; ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct rx_frame_queue { ++ u16 qmax; /* max number of queued frames */ ++ u16 qcnt; ++ struct list_head queuelist; ++}; ++#endif ++ ++struct aicwf_bus { ++ union { ++ struct aic_sdio_dev *sdio; ++ struct aic_usb_dev *usb; ++ } bus_priv; ++ struct device *dev; ++ struct aicwf_bus_ops *ops; ++ enum aicwf_bus_state state; ++ u8 *cmd_buf; ++ struct completion bustx_trgg; ++ struct completion busrx_trgg; ++ struct completion busirq_trgg;//new oob feature ++ struct task_struct *bustx_thread; ++ struct task_struct *busrx_thread; ++ struct task_struct *busirq_thread;//new oob feature ++}; ++ ++#ifdef CONFIG_SDIO_ADMA ++#define SDIO_HEADER_LEN 4 ++#define SDIO_DATA_FAKE_LEN 2 ++#define SDIO_MGMT_FAKE_LEN 4 ++#define ALIGN4_ADJ_LEN(x) ((4-(x&3))&3) ++ ++#define SDIO_TX_SLIST_MAX 136 ++ ++/*struct tx_scatterlist { ++ const void *buf; ++ unsigned int len; ++};*/ ++#endif ++ ++struct aicwf_tx_priv { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++ int fw_avail_bufcnt; ++ //for cmd tx ++ u8 *cmd_buf; ++ uint cmd_len; ++ bool cmd_txstate; ++ bool cmd_tx_succ; ++ struct semaphore cmd_txsema; ++ wait_queue_head_t cmd_txdone_wait; ++ //for data tx ++ atomic_t tx_pktcnt; ++ ++ struct frame_queue txq; ++ spinlock_t txqlock; ++ struct semaphore txctl_sema; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ struct sk_buff *aggr_buf; ++ atomic_t aggr_count; ++ u8 *head; ++ u8 *tail; ++ ++#ifdef CONFIG_SDIO_ADMA ++ struct tx_scatterlist sg_list[SDIO_TX_SLIST_MAX]; ++ void *free_buf[SDIO_TX_SLIST_MAX]; ++ bool copyd[SDIO_TX_SLIST_MAX]; ++ u32 aggr_segcnt; ++ u32 len; ++#endif ++}; ++ ++ ++#define DEFRAG_MAX_WAIT 40 //100 ++#ifdef AICWF_RX_REORDER ++#define MAX_REORD_RXFRAME 250 ++#define REORDER_UPDATE_TIME 50 ++#define AICWF_REORDER_WINSIZE 64 ++#define SN_LESS(a, b) (((a-b)&0x800) != 0) ++#define SN_EQUAL(a, b) (a == b) ++ ++struct reord_ctrl { ++ struct aicwf_rx_priv *rx_priv; ++ u8 enable; ++ u16 ind_sn; ++ u8 wsize_b; ++ spinlock_t reord_list_lock; ++ struct list_head reord_list; ++ struct timer_list reord_timer; ++ struct work_struct reord_timer_work; ++}; ++ ++struct reord_ctrl_info { ++ u8 mac_addr[6]; ++ struct reord_ctrl preorder_ctrl[8]; ++ struct list_head list; ++}; ++ ++struct recv_msdu { ++ struct sk_buff *pkt; ++ u8 tid; ++ u16 seq_num; ++ u8 forward; ++ //uint len; ++ u32 is_amsdu; ++ u8 *rx_data; ++ //for pending rx reorder list ++ struct list_head reord_pending_list; ++ //for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue ++ struct list_head rxframe_list; ++ struct reord_ctrl *preorder_ctrl; ++}; ++#endif ++ ++struct aicwf_rx_priv { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ ++ void *rwnx_vif; ++ atomic_t rx_cnt; ++ u32 data_len; ++ spinlock_t rxqlock; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_frame_queue rxq; ++ #else ++ struct frame_queue rxq; ++ #endif ++ ++#ifdef AICWF_RX_REORDER ++ spinlock_t freeq_lock; ++ struct list_head rxframes_freequeue; ++ struct list_head stas_reord_list; ++ spinlock_t stas_reord_lock; ++ struct recv_msdu *recv_frames; ++#endif ++#ifdef CONFIG_PREALLOC_RX_SKB ++ spinlock_t rxbuff_lock; ++#endif ++}; ++ ++static inline int aicwf_bus_start(struct aicwf_bus *bus) ++{ ++ return bus->ops->start(bus->dev); ++} ++ ++static inline void aicwf_bus_stop(struct aicwf_bus *bus) ++{ ++ bus->ops->stop(bus->dev); ++} ++ ++static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb) ++{ ++ return bus->ops->txdata(bus->dev, skb); ++} ++ ++static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len) ++{ ++ return bus->ops->txmsg(bus->dev, msg, len); ++} ++ ++static inline void aicwf_sched_timeout(u32 millisec) ++{ ++ ulong timeout = 0, expires = 0; ++ expires = jiffies + msecs_to_jiffies(millisec); ++ timeout = millisec; ++ ++ while (timeout) { ++ timeout = schedule_timeout(timeout); ++ if (time_after(jiffies, expires)) ++ break; ++ } ++} ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev); ++void aicwf_bus_deinit(struct device *dev); ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv); ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv); ++struct aicwf_tx_priv *aicwf_tx_init(void *arg); ++struct aicwf_rx_priv *aicwf_rx_init(void *arg); ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len); ++void aicwf_frame_queue_flush(struct frame_queue *pq); ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio); ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt); ++bool aicwf_is_framequeue_empty(struct frame_queue *pq); ++void aicwf_frame_tx(void *dev, struct sk_buff *skb); ++void aicwf_dev_skb_free(struct sk_buff *skb); ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq); ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out); ++#ifdef CONFIG_PREALLOC_RX_SKB ++void rxbuff_queue_flush(struct aicwf_rx_priv* rx_priv); ++void aicwf_rxframe_queue_init_2(struct rx_frame_queue *pq, int max_len); ++void rxbuff_free(struct rx_buff *rxbuff); ++struct rx_buff *rxbuff_dequeue(struct rx_frame_queue *pq); ++bool aicwf_rxbuff_enqueue(struct device *dev, struct rx_frame_queue *rxq, struct rx_buff *pkt); ++extern struct aicwf_rx_buff_list aic_rx_buff_list; ++#endif ++ ++#endif /* _AICWF_TXRXIF_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c +new file mode 100644 +index 000000000000..9344217c2256 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c +@@ -0,0 +1,957 @@ ++/** ++ * aicwf_usb.c ++ * ++ * USB function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#include ++#include ++#include "aicwf_txrxif.h" ++#include "aicwf_usb.h" ++#include "rwnx_tx.h" ++#include "rwnx_defs.h" ++#include "usb_host.h" ++#include "rwnx_platform.h" ++ ++void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state) ++{ ++ struct rwnx_vif *rwnx_vif; ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (!rwnx_vif->up) ++ continue; ++ if (!rwnx_vif->ndev) ++ continue; ++ if (state) ++ netif_stop_queue(rwnx_vif->ndev); ++ else ++ netif_wake_queue(rwnx_vif->ndev); ++ } ++} ++ ++static struct aicwf_usb_buf *aicwf_usb_tx_dequeue(struct aic_usb_dev *usb_dev, ++ struct list_head *q, int *counter, spinlock_t *qlock) ++{ ++ unsigned long flags; ++ struct aicwf_usb_buf *usb_buf; ++ ++ spin_lock_irqsave(qlock, flags); ++ if (list_empty(q)) { ++ usb_buf = NULL; ++ } else { ++ usb_buf = list_first_entry(q, struct aicwf_usb_buf, list); ++ list_del_init(&usb_buf->list); ++ if (counter) ++ (*counter)--; ++ } ++ spin_unlock_irqrestore(qlock, flags); ++ return usb_buf; ++} ++ ++static void aicwf_usb_tx_queue(struct aic_usb_dev *usb_dev, ++ struct list_head *q, struct aicwf_usb_buf *usb_buf, int *counter, ++ spinlock_t *qlock) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(qlock, flags); ++ list_add_tail(&usb_buf->list, q); ++ (*counter)++; ++ spin_unlock_irqrestore(qlock, flags); ++} ++ ++static struct aicwf_usb_buf *aicwf_usb_rx_buf_get(struct aic_usb_dev *usb_dev) ++{ ++ unsigned long flags; ++ struct aicwf_usb_buf *usb_buf; ++ ++ spin_lock_irqsave(&usb_dev->rx_free_lock, flags); ++ if (list_empty(&usb_dev->rx_free_list)) { ++ usb_buf = NULL; ++ } else { ++ usb_buf = list_first_entry(&usb_dev->rx_free_list, struct aicwf_usb_buf, list); ++ list_del_init(&usb_buf->list); ++ } ++ spin_unlock_irqrestore(&usb_dev->rx_free_lock, flags); ++ return usb_buf; ++} ++ ++static void aicwf_usb_rx_buf_put(struct aic_usb_dev *usb_dev, struct aicwf_usb_buf *usb_buf) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&usb_dev->rx_free_lock, flags); ++ list_add_tail(&usb_buf->list, &usb_dev->rx_free_list); ++ spin_unlock_irqrestore(&usb_dev->rx_free_lock, flags); ++} ++ ++static void aicwf_usb_tx_complete(struct urb *urb) ++{ ++ unsigned long flags; ++ struct aicwf_usb_buf *usb_buf = (struct aicwf_usb_buf *) urb->context; ++ struct aic_usb_dev *usb_dev = usb_buf->usbdev; ++ struct sk_buff *skb; ++ u8 *buf; ++ ++ if (usb_buf->cfm == false) { ++ skb = usb_buf->skb; ++ } else { ++ buf = (u8 *)usb_buf->skb; ++ } ++ ++ if (usb_buf->cfm == false) { ++ dev_kfree_skb_any(skb); ++ } else { ++ kfree(buf); ++ } ++ usb_buf->skb = NULL; ++ ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ ++ spin_lock_irqsave(&usb_dev->tx_flow_lock, flags); ++ if (usb_dev->tx_free_count > AICWF_USB_TX_HIGH_WATER) { ++ if (usb_dev->tbusy) { ++ usb_dev->tbusy = false; ++ aicwf_usb_tx_flowctrl(usb_dev->rwnx_hw, false); ++ } ++ } ++ spin_unlock_irqrestore(&usb_dev->tx_flow_lock, flags); ++ } ++ ++static void aicwf_usb_rx_complete(struct urb *urb) ++{ ++ struct aicwf_usb_buf *usb_buf = (struct aicwf_usb_buf *) urb->context; ++ struct aic_usb_dev *usb_dev = usb_buf->usbdev; ++ struct aicwf_rx_priv *rx_priv = usb_dev->rx_priv; ++ struct sk_buff *skb = NULL; ++ unsigned long flags = 0; ++ ++ skb = usb_buf->skb; ++ usb_buf->skb = NULL; ++ ++ if (urb->actual_length > urb->transfer_buffer_length) { ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ schedule_work(&usb_dev->rx_urb_work); ++ return; ++ } ++ ++ if (urb->status != 0 || !urb->actual_length) { ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ schedule_work(&usb_dev->rx_urb_work); ++ return; ++ } ++ ++ if (usb_dev->state == USB_UP_ST) { ++ skb_put(skb, urb->actual_length); ++ ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (!aicwf_rxframe_enqueue(usb_dev->dev, &rx_priv->rxq, skb)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ usb_err("rx_priv->rxq is over flow!!!\n"); ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ return; ++ } ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ atomic_inc(&rx_priv->rx_cnt); ++ complete(&rx_priv->usbdev->bus_if->busrx_trgg); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ ++ schedule_work(&usb_dev->rx_urb_work); ++ } else { ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ } ++} ++ ++static int aicwf_usb_submit_rx_urb(struct aic_usb_dev *usb_dev, ++ struct aicwf_usb_buf *usb_buf) ++{ ++ struct sk_buff *skb; ++ int ret; ++ ++ if (!usb_buf || !usb_dev) ++ return -1; ++ ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("usb state is not up!\n"); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ return -1; ++ } ++ ++ skb = __dev_alloc_skb(AICWF_USB_MAX_PKT_SIZE, GFP_KERNEL); ++ if (!skb) { ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ return -1; ++ } ++ ++ usb_buf->skb = skb; ++ ++ usb_fill_bulk_urb(usb_buf->urb, ++ usb_dev->udev, ++ usb_dev->bulk_in_pipe, ++ skb->data, skb_tailroom(skb), aicwf_usb_rx_complete, usb_buf); ++ ++ usb_buf->usbdev = usb_dev; ++ ++ usb_anchor_urb(usb_buf->urb, &usb_dev->rx_submitted); ++ ret = usb_submit_urb(usb_buf->urb, GFP_ATOMIC); ++ if (ret) { ++ usb_err("usb submit rx urb fail:%d\n", ret); ++ usb_unanchor_urb(usb_buf->urb); ++ aicwf_dev_skb_free(usb_buf->skb); ++ usb_buf->skb = NULL; ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ ++ msleep(100); ++ } ++ return 0; ++} ++ ++static void aicwf_usb_rx_submit_all_urb(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf; ++ ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("bus is not up=%d\n", usb_dev->state); ++ return; ++ } ++ ++ while ((usb_buf = aicwf_usb_rx_buf_get(usb_dev)) != NULL) { ++ if (aicwf_usb_submit_rx_urb(usb_dev, usb_buf)) { ++ usb_err("usb rx refill fail\n"); ++ if (usb_dev->state != USB_UP_ST) ++ return; ++ } ++ } ++} ++ ++static void aicwf_usb_rx_prepare(struct aic_usb_dev *usb_dev) ++{ ++ aicwf_usb_rx_submit_all_urb(usb_dev); ++} ++ ++static void aicwf_usb_tx_prepare(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf; ++ ++ while (!list_empty(&usb_dev->tx_post_list)) { ++ usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_post_list, ++ &usb_dev->tx_post_count, &usb_dev->tx_post_lock); ++ if (usb_buf->skb) { ++ dev_kfree_skb(usb_buf->skb); ++ usb_buf->skb = NULL; ++ } ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ } ++} ++static void aicwf_usb_tx_process(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf; ++ int ret = 0; ++ u8 *data = NULL; ++ ++ while (!list_empty(&usb_dev->tx_post_list)) { ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("usb state is not up!\n"); ++ return; ++ } ++ ++ usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_post_list, ++ &usb_dev->tx_post_count, &usb_dev->tx_post_lock); ++ if (!usb_buf) { ++ usb_err("can not get usb_buf from tx_post_list!\n"); ++ return; ++ } ++ data = usb_buf->skb->data; ++ ++ ret = usb_submit_urb(usb_buf->urb, GFP_ATOMIC); ++ if (ret) { ++ usb_err("aicwf_usb_bus_tx usb_submit_urb FAILED\n"); ++ goto fail; ++ } ++ ++ continue; ++fail: ++ dev_kfree_skb(usb_buf->skb); ++ usb_buf->skb = NULL; ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ } ++} ++ ++int usb_bustx_thread(void *data) ++{ ++ struct aicwf_bus *bus = (struct aicwf_bus *)data; ++ struct aic_usb_dev *usbdev = bus->bus_priv.usb; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ usb_err("usb bustx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if (usbdev->bus_if->state == BUS_DOWN_ST) ++ continue; ++ if (usbdev->tx_post_count > 0) ++ aicwf_usb_tx_process(usbdev); ++ } ++ } ++ ++ return 0; ++} ++ ++int usb_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->usbdev->bus_if; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ usb_err("usb busrx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ if (bus_if->state == BUS_DOWN_ST) ++ continue; ++ aicwf_process_rxframes(rx_priv); ++ } ++ } ++ ++ return 0; ++} ++ ++static void aicwf_usb_send_msg_complete(struct urb *urb) ++{ ++ struct aic_usb_dev *usb_dev = (struct aic_usb_dev *) urb->context; ++ ++ usb_dev->msg_finished = true; ++ if (waitqueue_active(&usb_dev->msg_wait)) ++ wake_up(&usb_dev->msg_wait); ++} ++ ++static int aicwf_usb_bus_txmsg(struct device *dev, u8 *buf, u32 len) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ ++ if (usb_dev->state != USB_UP_ST) ++ return -EIO; ++ ++ if (buf == NULL || len == 0 || usb_dev->msg_out_urb == NULL) ++ return -EINVAL; ++ ++ if (test_and_set_bit(0, &usb_dev->msg_busy)) { ++ usb_err("In a control frame option, can't tx!\n"); ++ return -EIO; ++ } ++ ++ usb_dev->msg_finished = false; ++ ++ usb_fill_bulk_urb(usb_dev->msg_out_urb, ++ usb_dev->udev, ++ usb_dev->bulk_out_pipe, ++ buf, len, (usb_complete_t) aicwf_usb_send_msg_complete, usb_dev); ++ usb_dev->msg_out_urb->transfer_flags |= URB_ZERO_PACKET; ++ ++ ret = usb_submit_urb(usb_dev->msg_out_urb, GFP_ATOMIC); ++ if (ret) { ++ usb_err("usb_submit_urb failed %d\n", ret); ++ goto exit; ++ } ++ ++ ret = wait_event_timeout(usb_dev->msg_wait, ++ usb_dev->msg_finished, msecs_to_jiffies(CMD_TX_TIMEOUT)); ++ if (!ret) { ++ if (usb_dev->msg_out_urb) ++ usb_kill_urb(usb_dev->msg_out_urb); ++ usb_err("Txmsg wait timed out\n"); ++ ret = -EIO; ++ goto exit; ++ } ++ ++ if (usb_dev->msg_finished == false) { ++ usb_err("Txmsg timed out\n"); ++ ret = -ETIMEDOUT; ++ goto exit; ++ } ++exit: ++ clear_bit(0, &usb_dev->msg_busy); ++ return ret; ++} ++ ++ ++static void aicwf_usb_free_urb(struct list_head *q, spinlock_t *qlock) ++{ ++ struct aicwf_usb_buf *usb_buf, *tmp; ++ unsigned long flags; ++ ++ spin_lock_irqsave(qlock, flags); ++ list_for_each_entry_safe(usb_buf, tmp, q, list) { ++ spin_unlock_irqrestore(qlock, flags); ++ if (!usb_buf->urb) { ++ usb_err("bad usb_buf\n"); ++ spin_lock_irqsave(qlock, flags); ++ break; ++ } ++ usb_free_urb(usb_buf->urb); ++ list_del_init(&usb_buf->list); ++ spin_lock_irqsave(qlock, flags); ++ } ++ spin_unlock_irqrestore(qlock, flags); ++} ++ ++static int aicwf_usb_alloc_rx_urb(struct aic_usb_dev *usb_dev) ++{ ++ int i; ++ ++ for (i = 0; i < AICWF_USB_RX_URBS; i++) { ++ struct aicwf_usb_buf *usb_buf = &usb_dev->usb_rx_buf[i]; ++ ++ usb_buf->usbdev = usb_dev; ++ usb_buf->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!usb_buf->urb) { ++ usb_err("could not allocate rx data urb\n"); ++ goto err; ++ } ++ list_add_tail(&usb_buf->list, &usb_dev->rx_free_list); ++ } ++ return 0; ++ ++err: ++ aicwf_usb_free_urb(&usb_dev->rx_free_list, &usb_dev->rx_free_lock); ++ return -ENOMEM; ++} ++ ++static int aicwf_usb_alloc_tx_urb(struct aic_usb_dev *usb_dev) ++{ ++ int i; ++ ++ for (i = 0; i < AICWF_USB_TX_URBS; i++) { ++ struct aicwf_usb_buf *usb_buf = &usb_dev->usb_tx_buf[i]; ++ ++ usb_buf->usbdev = usb_dev; ++ usb_buf->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!usb_buf->urb) { ++ usb_err("could not allocate tx data urb\n"); ++ goto err; ++ } ++ list_add_tail(&usb_buf->list, &usb_dev->tx_free_list); ++ (usb_dev->tx_free_count)++; ++ } ++ return 0; ++ ++err: ++ aicwf_usb_free_urb(&usb_dev->tx_free_list, &usb_dev->tx_free_lock); ++ return -ENOMEM; ++} ++ ++ ++static void aicwf_usb_state_change(struct aic_usb_dev *usb_dev, int state) ++{ ++ int old_state; ++ ++ if (usb_dev->state == state) ++ return; ++ ++ old_state = usb_dev->state; ++ usb_dev->state = state; ++ ++ if (state == USB_DOWN_ST) { ++ usb_dev->bus_if->state = BUS_DOWN_ST; ++ } ++ if (state == USB_UP_ST) { ++ usb_dev->bus_if->state = BUS_UP_ST; ++ } ++} ++ ++static int aicwf_usb_bus_txdata(struct device *dev, struct sk_buff *skb) ++{ ++ u8 *buf; ++ u16 buf_len = 0; ++ u16 adjust_len = 0; ++ struct aicwf_usb_buf *usb_buf; ++ int ret = 0; ++ unsigned long flags; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)skb->data; ++ struct rwnx_hw *rwnx_hw = usb_dev->rwnx_hw; ++ u8 usb_header[4]; ++ u8 adj_buf[4] = {0}; ++ u16 index = 0; ++ bool need_cfm = false; ++ ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("usb state is not up!\n"); ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ dev_kfree_skb_any(skb); ++ return -EIO; ++ } ++ ++ usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_free_list, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ if (!usb_buf) { ++ usb_err("free:%d, post:%d\n", usb_dev->tx_free_count, usb_dev->tx_post_count); ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ dev_kfree_skb_any(skb); ++ ret = -ENOMEM; ++ goto flow_ctrl; ++ } ++ ++ if (txhdr->sw_hdr->need_cfm) { ++ need_cfm = true; ++ buf = kmalloc(skb->len, GFP_KERNEL); ++ index += sizeof(usb_header); ++ memcpy(&buf[index], (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ index += sizeof(struct txdesc_api); ++ memcpy(&buf[index], &skb->data[txhdr->sw_hdr->headroom], skb->len - txhdr->sw_hdr->headroom); ++ index += skb->len - txhdr->sw_hdr->headroom; ++ buf_len = index; ++ if (buf_len & (TX_ALIGNMENT - 1)) { ++ adjust_len = roundup(buf_len, TX_ALIGNMENT)-buf_len; ++ memcpy(&buf[buf_len], adj_buf, adjust_len); ++ buf_len += adjust_len; ++ } ++ usb_header[0] = ((buf_len) & 0xff); ++ usb_header[1] = (((buf_len) >> 8)&0x0f); ++ usb_header[2] = 0x01; //data ++ usb_header[3] = 0; //reserved ++ memcpy(&buf[0], usb_header, sizeof(usb_header)); ++ usb_buf->skb = (struct sk_buff *)buf; ++ } else { ++ skb_pull(skb, txhdr->sw_hdr->headroom); ++ skb_push(skb, sizeof(struct txdesc_api)); ++ memcpy(&skb->data[0], (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ ++ skb_push(skb, sizeof(usb_header)); ++ usb_header[0] = ((skb->len) & 0xff); ++ usb_header[1] = (((skb->len) >> 8)&0x0f); ++ usb_header[2] = 0x01; //data ++ usb_header[3] = 0; //reserved ++ memcpy(&skb->data[0], usb_header, sizeof(usb_header)); ++ ++ buf = skb->data; ++ buf_len = skb->len; ++ ++ usb_buf->skb = skb; ++ } ++ usb_buf->usbdev = usb_dev; ++ if (need_cfm) ++ usb_buf->cfm = true; ++ else ++ usb_buf->cfm = false; ++ usb_fill_bulk_urb(usb_buf->urb, usb_dev->udev, usb_dev->bulk_out_pipe, ++ buf, buf_len, aicwf_usb_tx_complete, usb_buf); ++ usb_buf->urb->transfer_flags |= URB_ZERO_PACKET; ++ ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_post_list, usb_buf, ++ &usb_dev->tx_post_count, &usb_dev->tx_post_lock); ++ complete(&bus_if->bustx_trgg); ++ ret = 0; ++ ++ flow_ctrl: ++ spin_lock_irqsave(&usb_dev->tx_flow_lock, flags); ++ if (usb_dev->tx_free_count < AICWF_USB_TX_LOW_WATER) { ++ usb_dev->tbusy = true; ++ aicwf_usb_tx_flowctrl(usb_dev->rwnx_hw, true); ++ } ++ spin_unlock_irqrestore(&usb_dev->tx_flow_lock, flags); ++ ++ return ret; ++} ++ ++static int aicwf_usb_bus_start(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ ++ if (usb_dev->state == USB_UP_ST) ++ return 0; ++ ++ aicwf_usb_state_change(usb_dev, USB_UP_ST); ++ aicwf_usb_rx_prepare(usb_dev); ++ aicwf_usb_tx_prepare(usb_dev); ++ return 0; ++} ++ ++static void aicwf_usb_cancel_all_urbs(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf, *tmp; ++ unsigned long flags; ++ ++ if (usb_dev->msg_out_urb) ++ usb_kill_urb(usb_dev->msg_out_urb); ++ ++ spin_lock_irqsave(&usb_dev->tx_post_lock, flags); ++ list_for_each_entry_safe(usb_buf, tmp, &usb_dev->tx_post_list, list) { ++ spin_unlock_irqrestore(&usb_dev->tx_post_lock, flags); ++ if (!usb_buf->urb) { ++ usb_err("bad usb_buf\n"); ++ spin_lock_irqsave(&usb_dev->tx_post_lock, flags); ++ break; ++ } ++ usb_kill_urb(usb_buf->urb); ++ spin_lock_irqsave(&usb_dev->tx_post_lock, flags); ++ } ++ spin_unlock_irqrestore(&usb_dev->tx_post_lock, flags); ++ ++ usb_kill_anchored_urbs(&usb_dev->rx_submitted); ++} ++ ++static void aicwf_usb_bus_stop(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ ++ usb_dbg("%s\r\n", __func__); ++ if (usb_dev == NULL) ++ return; ++ ++ if (usb_dev->state == USB_DOWN_ST) ++ return; ++ ++ aicwf_usb_state_change(usb_dev, USB_DOWN_ST); ++ aicwf_usb_cancel_all_urbs(usb_dev); ++} ++ ++static void aicwf_usb_deinit(struct aic_usb_dev *usbdev) ++{ ++ cancel_work_sync(&usbdev->rx_urb_work); ++ aicwf_usb_free_urb(&usbdev->rx_free_list, &usbdev->rx_free_lock); ++ aicwf_usb_free_urb(&usbdev->tx_free_list, &usbdev->tx_free_lock); ++ usb_free_urb(usbdev->msg_out_urb); ++} ++ ++static void aicwf_usb_rx_urb_work(struct work_struct *work) ++{ ++ struct aic_usb_dev *usb_dev = container_of(work, struct aic_usb_dev, rx_urb_work); ++ ++ aicwf_usb_rx_submit_all_urb(usb_dev); ++} ++ ++static int aicwf_usb_init(struct aic_usb_dev *usb_dev) ++{ ++ int ret = 0; ++ ++ usb_dev->tbusy = false; ++ usb_dev->state = USB_DOWN_ST; ++ ++ init_waitqueue_head(&usb_dev->msg_wait); ++ init_usb_anchor(&usb_dev->rx_submitted); ++ ++ spin_lock_init(&usb_dev->tx_free_lock); ++ spin_lock_init(&usb_dev->tx_post_lock); ++ spin_lock_init(&usb_dev->rx_free_lock); ++ spin_lock_init(&usb_dev->tx_flow_lock); ++ ++ INIT_LIST_HEAD(&usb_dev->rx_free_list); ++ INIT_LIST_HEAD(&usb_dev->tx_free_list); ++ INIT_LIST_HEAD(&usb_dev->tx_post_list); ++ ++ usb_dev->tx_free_count = 0; ++ usb_dev->tx_post_count = 0; ++ ++ ret = aicwf_usb_alloc_rx_urb(usb_dev); ++ if (ret) { ++ goto error; ++ } ++ ret = aicwf_usb_alloc_tx_urb(usb_dev); ++ if (ret) { ++ goto error; ++ } ++ ++ ++ usb_dev->msg_out_urb = usb_alloc_urb(0, GFP_ATOMIC); ++ if (!usb_dev->msg_out_urb) { ++ usb_err("usb_alloc_urb (msg out) failed\n"); ++ ret = ENOMEM; ++ goto error; ++ } ++ ++ INIT_WORK(&usb_dev->rx_urb_work, aicwf_usb_rx_urb_work); ++ ++ return ret; ++ error: ++ usb_err("failed!\n"); ++ aicwf_usb_deinit(usb_dev); ++ return ret; ++} ++ ++ ++static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *interface) ++{ ++ struct usb_interface_descriptor *interface_desc; ++ struct usb_host_interface *host_interface; ++ struct usb_endpoint_descriptor *endpoint; ++ struct usb_device *usb = usb_dev->udev; ++ int i, endpoints; ++ u8 endpoint_num; ++ int ret = 0; ++ ++ usb_dev->bulk_in_pipe = 0; ++ usb_dev->bulk_out_pipe = 0; ++ ++ host_interface = &interface->altsetting[0]; ++ interface_desc = &host_interface->desc; ++ endpoints = interface_desc->bNumEndpoints; ++ ++ /* Check device configuration */ ++ if (usb->descriptor.bNumConfigurations != 1) { ++ usb_err("Number of configurations: %d not supported\n", ++ usb->descriptor.bNumConfigurations); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ /* Check deviceclass */ ++#ifndef CONFIG_USB_BT ++ if (usb->descriptor.bDeviceClass != 0x00) { ++ usb_err("DeviceClass %d not supported\n", ++ usb->descriptor.bDeviceClass); ++ ret = -ENODEV; ++ goto exit; ++ } ++#endif ++ ++ /* Check interface number */ ++#ifdef CONFIG_USB_BT ++ if (usb->actconfig->desc.bNumInterfaces != 3) { ++#else ++ if (usb->actconfig->desc.bNumInterfaces != 1) { ++#endif ++ usb_err("Number of interfaces: %d not supported\n", ++ usb->actconfig->desc.bNumInterfaces); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ if ((interface_desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || ++ (interface_desc->bInterfaceSubClass != 0xff) || ++ (interface_desc->bInterfaceProtocol != 0xff)) { ++ usb_err("non WLAN interface %d: 0x%x:0x%x:0x%x\n", ++ interface_desc->bInterfaceNumber, interface_desc->bInterfaceClass, ++ interface_desc->bInterfaceSubClass, interface_desc->bInterfaceProtocol); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ for (i = 0; i < endpoints; i++) { ++ endpoint = &host_interface->endpoint[i].desc; ++ endpoint_num = usb_endpoint_num(endpoint); ++ ++ if (usb_endpoint_dir_in(endpoint) && ++ usb_endpoint_xfer_bulk(endpoint)) { ++ if (!usb_dev->bulk_in_pipe) { ++ usb_dev->bulk_in_pipe = usb_rcvbulkpipe(usb, endpoint_num); ++ } ++ } ++ ++ if (usb_endpoint_dir_out(endpoint) && ++ usb_endpoint_xfer_bulk(endpoint)) { ++ if (!usb_dev->bulk_out_pipe) { ++ usb_dev->bulk_out_pipe = usb_sndbulkpipe(usb, endpoint_num); ++ } ++ } ++ } ++ ++ if (usb_dev->bulk_in_pipe == 0) { ++ usb_err("No RX (in) Bulk EP found\n"); ++ ret = -ENODEV; ++ goto exit; ++ } ++ if (usb_dev->bulk_out_pipe == 0) { ++ usb_err("No TX (out) Bulk EP found\n"); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ if (usb->speed == USB_SPEED_HIGH) ++ printk("Aic high speed USB device detected\n"); ++ else ++ printk("Aic full speed USB device detected\n"); ++ ++ exit: ++ return ret; ++} ++ ++ ++ ++static struct aicwf_bus_ops aicwf_usb_bus_ops = { ++ .start = aicwf_usb_bus_start, ++ .stop = aicwf_usb_bus_stop, ++ .txdata = aicwf_usb_bus_txdata, ++ .txmsg = aicwf_usb_bus_txmsg, ++}; ++ ++static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ++{ ++ int ret = 0; ++ struct usb_device *usb = interface_to_usbdev(intf); ++ struct aicwf_bus *bus_if ; ++ struct device *dev = NULL; ++ struct aicwf_rx_priv *rx_priv = NULL; ++ struct aic_usb_dev *usb_dev = NULL; ++ ++ usb_dev = kzalloc(sizeof(struct aic_usb_dev), GFP_ATOMIC); ++ if (!usb_dev) { ++ return -ENOMEM; ++ } ++ ++ usb_dev->udev = usb; ++ usb_dev->dev = &usb->dev; ++ usb_set_intfdata(intf, usb_dev); ++ ++ ret = aicwf_parse_usb(usb_dev, intf); ++ if (ret) { ++ usb_err("aicwf_parse_usb err %d\n", ret); ++ goto out_free; ++ } ++ ++ ret = aicwf_usb_init(usb_dev); ++ if (ret) { ++ usb_err("aicwf_usb_init err %d\n", ret); ++ goto out_free; ++ } ++ ++ bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_ATOMIC); ++ if (!bus_if) { ++ ret = -ENOMEM; ++ goto out_free_usb; ++ } ++ ++ dev = usb_dev->dev; ++ bus_if->dev = dev; ++ usb_dev->bus_if = bus_if; ++ bus_if->bus_priv.usb = usb_dev; ++ dev_set_drvdata(dev, bus_if); ++ ++ bus_if->ops = &aicwf_usb_bus_ops; ++ ++ rx_priv = aicwf_rx_init(usb_dev); ++ if (!rx_priv) { ++ txrx_err("rx init failed\n"); ++ ret = -1; ++ goto out_free_bus; ++ } ++ usb_dev->rx_priv = rx_priv; ++ ++ ret = aicwf_bus_init(0, dev); ++ if (ret < 0) { ++ usb_err("aicwf_bus_init err %d\n", ret); ++ goto out_free_bus; ++ } ++ ++ ret = aicwf_bus_start(bus_if); ++ if (ret < 0) { ++ usb_err("aicwf_bus_start err %d\n", ret); ++ goto out_free_bus; ++ } ++ ++ aicwf_rwnx_usb_platform_init(usb_dev); ++ aicwf_hostif_ready(); ++ return 0; ++ ++out_free_bus: ++ aicwf_bus_deinit(dev); ++ kfree(bus_if); ++out_free_usb: ++ aicwf_usb_deinit(usb_dev); ++out_free: ++ usb_err("failed with errno %d\n", ret); ++ kfree(usb_dev); ++ usb_set_intfdata(intf, NULL); ++ return ret; ++} ++ ++static void aicwf_usb_disconnect(struct usb_interface *intf) ++{ ++ struct aic_usb_dev *usb_dev = ++ (struct aic_usb_dev *) usb_get_intfdata(intf); ++ ++ if (!usb_dev) ++ return; ++ ++ aicwf_bus_deinit(usb_dev->dev); ++ aicwf_usb_deinit(usb_dev); ++ rwnx_cmd_mgr_deinit(&usb_dev->cmd_mgr); ++ ++ if (usb_dev->rx_priv) ++ aicwf_rx_deinit(usb_dev->rx_priv); ++ kfree(usb_dev->bus_if); ++ kfree(usb_dev); ++} ++ ++static int aicwf_usb_suspend(struct usb_interface *intf, pm_message_t state) ++{ ++ struct aic_usb_dev *usb_dev = ++ (struct aic_usb_dev *) usb_get_intfdata(intf); ++ ++ aicwf_usb_state_change(usb_dev, USB_SLEEP_ST); ++ aicwf_bus_stop(usb_dev->bus_if); ++ return 0; ++} ++ ++static int aicwf_usb_resume(struct usb_interface *intf) ++{ ++ struct aic_usb_dev *usb_dev = ++ (struct aic_usb_dev *) usb_get_intfdata(intf); ++ ++ if (usb_dev->state == USB_UP_ST) ++ return 0; ++ ++ aicwf_bus_start(usb_dev->bus_if); ++ return 0; ++} ++ ++static int aicwf_usb_reset_resume(struct usb_interface *intf) ++{ ++ return aicwf_usb_resume(intf); ++} ++ ++static struct usb_device_id aicwf_usb_id_table[] = { ++#ifndef CONFIG_USB_BT ++ {USB_DEVICE(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC)}, ++#else ++ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC, 0xff, 0xff, 0xff)}, ++#endif ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(usb, aicwf_usb_id_table); ++ ++static struct usb_driver aicwf_usbdrvr = { ++ .name = KBUILD_MODNAME, ++ .probe = aicwf_usb_probe, ++ .disconnect = aicwf_usb_disconnect, ++ .id_table = aicwf_usb_id_table, ++ .suspend = aicwf_usb_suspend, ++ .resume = aicwf_usb_resume, ++ .reset_resume = aicwf_usb_reset_resume, ++ .supports_autosuspend = 1, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) ++ .disable_hub_initiated_lpm = 1, ++#endif ++}; ++ ++void aicwf_usb_register(void) ++{ ++ if (usb_register(&aicwf_usbdrvr) < 0) { ++ usb_err("usb_register failed\n"); ++ } ++} ++ ++void aicwf_usb_exit(void) ++{ ++ if (g_rwnx_plat && g_rwnx_plat->enabled) ++ rwnx_platform_deinit(g_rwnx_plat->usbdev->rwnx_hw); ++ usb_deregister(&aicwf_usbdrvr); ++ kfree(g_rwnx_plat); ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h +new file mode 100644 +index 000000000000..cc3619b2dfe0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h +@@ -0,0 +1,99 @@ ++/** ++ * aicwf_usb.h ++ * ++ * USB function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_USB_H_ ++#define _AICWF_USB_H_ ++ ++#include ++#include "rwnx_cmds.h" ++ ++#ifdef AICWF_USB_SUPPORT ++ ++/* USB Device ID */ ++#define USB_VENDOR_ID_AIC 0xA69C ++ ++#ifndef CONFIG_USB_BT ++#define USB_PRODUCT_ID_AIC 0x8800 ++#else ++#define USB_PRODUCT_ID_AIC 0x8801 ++#endif ++ ++#define AICWF_USB_RX_URBS (200) ++#define AICWF_USB_TX_URBS (100) ++#define AICWF_USB_TX_LOW_WATER (AICWF_USB_TX_URBS/4) ++#define AICWF_USB_TX_HIGH_WATER (AICWF_USB_TX_LOW_WATER*3) ++#define AICWF_USB_MAX_PKT_SIZE (2048) ++ ++typedef enum { ++ USB_TYPE_DATA = 0X00, ++ USB_TYPE_CFG = 0X10, ++ USB_TYPE_CFG_CMD_RSP = 0X11, ++ USB_TYPE_CFG_DATA_CFM = 0X12 ++} usb_type; ++ ++enum aicwf_usb_state { ++ USB_DOWN_ST, ++ USB_UP_ST, ++ USB_SLEEP_ST ++}; ++ ++struct aicwf_usb_buf { ++ struct list_head list; ++ struct aic_usb_dev *usbdev; ++ struct urb *urb; ++ struct sk_buff *skb; ++ bool cfm; ++}; ++ ++struct aic_usb_dev { ++ struct rwnx_hw *rwnx_hw; ++ struct aicwf_bus *bus_if; ++ struct usb_device *udev; ++ struct device *dev; ++ struct aicwf_rx_priv *rx_priv; ++ enum aicwf_usb_state state; ++ struct rwnx_cmd_mgr cmd_mgr; ++ ++ struct usb_anchor rx_submitted; ++ struct work_struct rx_urb_work; ++ ++ spinlock_t rx_free_lock; ++ spinlock_t tx_free_lock; ++ spinlock_t tx_post_lock; ++ spinlock_t tx_flow_lock; ++ ++ struct list_head rx_free_list; ++ struct list_head tx_free_list; ++ struct list_head tx_post_list; ++ ++ uint bulk_in_pipe; ++ uint bulk_out_pipe; ++ ++ int tx_free_count; ++ int tx_post_count; ++ ++ struct aicwf_usb_buf usb_tx_buf[AICWF_USB_TX_URBS]; ++ struct aicwf_usb_buf usb_rx_buf[AICWF_USB_RX_URBS]; ++ ++ int msg_finished; ++ wait_queue_head_t msg_wait; ++ ulong msg_busy; ++ struct urb *msg_out_urb; ++ ++ bool tbusy; ++}; ++ ++extern void aicwf_usb_exit(void); ++extern void aicwf_usb_register(void); ++extern void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state); ++int usb_bustx_thread(void *data); ++int usb_busrx_thread(void *data); ++extern void aicwf_hostif_ready(void); ++ ++#endif /* AICWF_USB_SUPPORT */ ++#endif /* _AICWF_USB_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/btsdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/btsdio.c +new file mode 100644 +index 000000000000..81c5c1ae1e98 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/btsdio.c +@@ -0,0 +1,298 @@ ++/* ++ * ++ * Generic Bluetooth SDIO driver ++ * ++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd. ++ * Copyright (C) 2007 Marcel Holtmann ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++ ++#include "aic_btsdio.h" ++#include "rwnx_msg_tx.h" ++ ++#include ++ ++#define VERSION "0.1" ++#if CONFIG_BLUEDROID == 0 ++struct btsdio_data { ++ struct hci_dev *hdev; ++ ++ struct work_struct work; ++ ++ struct sk_buff_head txq; ++}; ++struct hci_dev *ghdev = NULL; ++ ++void bt_data_dump(char* tag, void* data, unsigned long len){ ++ unsigned long i = 0; ++ uint8_t* data_ = (uint8_t* )data; ++ ++ printk("%s %s len:(%lu)\r\n", __func__, tag, len); ++ ++ for (i = 0; i < len; i += 16){ ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", ++ data_[0 + i], ++ data_[1 + i], ++ data_[2 + i], ++ data_[3 + i], ++ data_[4 + i], ++ data_[5 + i], ++ data_[6 + i], ++ data_[7 + i], ++ data_[8 + i], ++ data_[9 + i], ++ data_[10 + i], ++ data_[11 + i], ++ data_[12 + i], ++ data_[13 + i], ++ data_[14 + i], ++ data_[15 + i]); ++ } ++ ++} ++ ++static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) ++{ ++ int err; ++ ++ AICBT_INFO("%s", data->hdev->name); ++ ++ /* Prepend Type-A header */ ++ skb_push(skb, 1); ++ skb->data[0] = hci_skb_pkt_type(skb); ++ ++ //bt_data_dump("btwrite", skb->data, skb->len); ++ err = rwnx_sdio_bt_send_req(g_rwnx_plat->sdiodev->rwnx_hw, skb->len, skb); ++ if(err<0){ ++ printk("%s rwnx_sdio_bt_send_req error %d",__func__,err); ++ return err; ++ } ++ ++ data->hdev->stat.byte_tx += skb->len; ++ ++ kfree_skb(skb); ++ ++ return 0; ++} ++ ++static void btsdio_work(struct work_struct *work) ++{ ++ struct btsdio_data *data = container_of(work, struct btsdio_data, work); ++ struct sk_buff *skb; ++ int err; ++ ++ AICBT_INFO("%s,%s", data->hdev->name,__func__); ++ ++ ++ while ((skb = skb_dequeue(&data->txq))) { ++ err = btsdio_tx_packet(data, skb); ++ if (err < 0) { ++ data->hdev->stat.err_tx++; ++ skb_queue_head(&data->txq, skb); ++ break; ++ } ++ } ++} ++ ++/* Get HCI device by index. ++ * Device is held on return. */ ++struct hci_dev *hci_dev_get(int index) ++{ ++ if (index != 0) ++ return NULL; ++ ++ return ghdev; ++} ++ ++int bt_sdio_recv(u8 *data,u32 data_len) ++{ ++ struct sk_buff *skb; ++ int type= data[0]; ++ struct hci_dev *hdev; ++ u32 len = data_len; ++ int ret=0; ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICWFDBG(LOGERROR,"%s: Failed to get hci dev[NULL]", __func__); ++ return -ENODEV; ++ } ++ ++ skb = alloc_skb(len-1,GFP_ATOMIC); ++ if(!skb){ ++ AICWFDBG(LOGERROR, "alloc skb fail %s \n",__func__); ++ } ++ memcpy(skb_put(skb,len-1) ,(data+1), len-1); ++ hdev->stat.byte_rx += len; ++ hci_skb_pkt_type(skb) = type; ++ //if(bt_bypass_event(skb)){ ++ //kfree_skb(skb); ++ ///return 0; ++ //} ++ AICBT_INFO("skb type %d",type); ++ //bt_data_dump("bt_skb", skb, skb->len); ++ ret = hci_recv_frame(hdev, skb); ++ if(ret < 0){ ++ AICWFDBG(LOGERROR, "hci_recv_frame fail %d\n",ret); ++ hdev->stat.err_rx++; ++ kfree_skb(skb); ++ } ++ return 0; ++} ++ ++static int btsdio_open(struct hci_dev *hdev) ++{ ++ //struct btsdio_data *data = hci_get_drvdata(hdev); ++ int err = 0; ++ ++ AICBT_INFO("%s", hdev->name); ++ ++ return err; ++} ++ ++static int btsdio_close(struct hci_dev *hdev) ++{ ++ //struct btsdio_data *data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("%s,%s", hdev->name,__func__); ++ ++ return 0; ++} ++ ++static int btsdio_flush(struct hci_dev *hdev) ++{ ++ struct btsdio_data *data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("%s,%s", hdev->name,__func__); ++ ++ skb_queue_purge(&data->txq); ++ ++ return 0; ++} ++ ++static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ struct btsdio_data *data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("%s,%s", hdev->name,__func__); ++ ++ switch (hci_skb_pkt_type(skb)) { ++ case HCI_COMMAND_PKT: ++ hdev->stat.cmd_tx++; ++ break; ++ ++ case HCI_ACLDATA_PKT: ++ hdev->stat.acl_tx++; ++ break; ++ ++ case HCI_SCODATA_PKT: ++ hdev->stat.sco_tx++; ++ break; ++ ++ default: ++ return -EILSEQ; ++ } ++ ++ skb_queue_tail(&data->txq, skb); ++ ++ schedule_work(&data->work); ++ ++ return 0; ++} ++ ++int btsdio_init(void) ++{ ++ struct btsdio_data *data; ++ struct hci_dev *hdev; ++ int err; ++ ++ AICBT_INFO("%s", __func__); ++ ++ ++ data = kzalloc(sizeof(struct btsdio_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ INIT_WORK(&data->work, btsdio_work); ++ ++ skb_queue_head_init(&data->txq); ++ ++ hdev = hci_alloc_dev(); ++ if (!hdev) ++ return -ENOMEM; ++ ++ hdev->bus = HCI_SDIO; ++ hci_set_drvdata(hdev, data); ++ ++ hdev->dev_type = HCI_PRIMARY; ++ ++ data->hdev = hdev; ++ ++ hdev->open = btsdio_open; ++ hdev->close = btsdio_close; ++ hdev->flush = btsdio_flush; ++ hdev->send = btsdio_send_frame; ++ ++ err = hci_register_dev(hdev); ++ if (err < 0) { ++ hci_free_dev(hdev); ++ return err; ++ } ++ ghdev = hdev; ++ ++ return 0; ++} ++ ++void btsdio_remove(void) ++{ ++ struct btsdio_data *data; ++ struct hci_dev *hdev; ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ return; ++ } ++ data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("btsdio_remove"); ++ ++ if (!data) ++ return; ++ ++ kfree(data); ++ ++ hci_unregister_dev(hdev); ++ ++ hci_free_dev(hdev); ++} ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h +new file mode 100644 +index 000000000000..e2429283314b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h +@@ -0,0 +1,383 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file hal_desc.h ++ * ++ * @brief File containing the definition of HW descriptors. ++ * ++ * Contains the definition and structures used by HW ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _HAL_DESC_H_ ++#define _HAL_DESC_H_ ++ ++#include "lmac_types.h" ++ ++/* Rate and policy table */ ++ ++#define N_CCK 8 ++#define N_OFDM 8 ++#define N_HT (8 * 2 * 2 * 4) ++#define N_VHT (10 * 4 * 2 * 8) ++#define N_HE_SU (12 * 4 * 3 * 8) ++#define N_HE_MU (12 * 6 * 3 * 8) ++#define N_HE_ER (3 * 3 + 3) //RU242 + RU106 ++ ++/* conversion table from NL80211 to MACHW enum */ ++extern const int chnl2bw[]; ++ ++/* conversion table from MACHW to NL80211 enum */ ++extern const int bw2chnl[]; ++ ++/* Rate cntrl info */ ++#define MCS_INDEX_TX_RCX_OFT 0 ++#define MCS_INDEX_TX_RCX_MASK (0x7F << MCS_INDEX_TX_RCX_OFT) ++#define BW_TX_RCX_OFT 7 ++#define BW_TX_RCX_MASK (0x3 << BW_TX_RCX_OFT) ++#define SHORT_GI_TX_RCX_OFT 9 ++#define SHORT_GI_TX_RCX_MASK (0x1 << SHORT_GI_TX_RCX_OFT) ++#define PRE_TYPE_TX_RCX_OFT 10 ++#define PRE_TYPE_TX_RCX_MASK (0x1 << PRE_TYPE_TX_RCX_OFT) ++#define FORMAT_MOD_TX_RCX_OFT 11 ++#define FORMAT_MOD_TX_RCX_MASK (0x7 << FORMAT_MOD_TX_RCX_OFT) ++ ++ ++/* Values for formatModTx */ ++#define FORMATMOD_NON_HT 0 ++#define FORMATMOD_NON_HT_DUP_OFDM 1 ++#define FORMATMOD_HT_MF 2 ++#define FORMATMOD_HT_GF 3 ++#define FORMATMOD_VHT 4 ++#define FORMATMOD_HE_SU 5 ++#define FORMATMOD_HE_MU 6 ++#define FORMATMOD_HE_ER 7 ++#define FORMATMOD_HE_TB 8 ++ ++/* Values for navProtFrmEx */ ++#define NAV_PROT_NO_PROT_BIT 0 ++#define NAV_PROT_SELF_CTS_BIT 1 ++#define NAV_PROT_RTS_CTS_BIT 2 ++#define NAV_PROT_RTS_CTS_WITH_QAP_BIT 3 ++#define NAV_PROT_STBC_BIT 4 ++ ++/* THD MACCTRLINFO2 fields, used in struct umacdesc umac.flags */ ++/// WhichDescriptor definition - contains aMPDU bit and position value ++/// Offset of WhichDescriptor field in the MAC CONTROL INFO 2 word ++#define WHICHDESC_OFT 19 ++/// Mask of the WhichDescriptor field ++#define WHICHDESC_MSK (0x07 << WHICHDESC_OFT) ++/// Only 1 THD possible, describing an unfragmented MSDU ++#define WHICHDESC_UNFRAGMENTED_MSDU (0x00 << WHICHDESC_OFT) ++/// THD describing the first MPDU of a fragmented MSDU ++#define WHICHDESC_FRAGMENTED_MSDU_FIRST (0x01 << WHICHDESC_OFT) ++/// THD describing intermediate MPDUs of a fragmented MSDU ++#define WHICHDESC_FRAGMENTED_MSDU_INT (0x02 << WHICHDESC_OFT) ++/// THD describing the last MPDU of a fragmented MSDU ++#define WHICHDESC_FRAGMENTED_MSDU_LAST (0x03 << WHICHDESC_OFT) ++/// THD for extra descriptor starting an AMPDU ++#define WHICHDESC_AMPDU_EXTRA (0x04 << WHICHDESC_OFT) ++/// THD describing the first MPDU of an A-MPDU ++#define WHICHDESC_AMPDU_FIRST (0x05 << WHICHDESC_OFT) ++/// THD describing intermediate MPDUs of an A-MPDU ++#define WHICHDESC_AMPDU_INT (0x06 << WHICHDESC_OFT) ++/// THD describing the last MPDU of an A-MPDU ++#define WHICHDESC_AMPDU_LAST (0x07 << WHICHDESC_OFT) ++ ++/// aMPDU bit offset ++#define AMPDU_OFT 21 ++/// aMPDU bit ++#define AMPDU_BIT CO_BIT(AMPDU_OFT) ++ ++union rwnx_mcs_index { ++ struct { ++ u32 mcs : 3; ++ u32 nss : 2; ++ } ht; ++ struct { ++ u32 mcs : 4; ++ u32 nss : 3; ++ } vht; ++ struct { ++ u32 mcs : 4; ++ u32 nss : 3; ++ } he; ++ u32 legacy : 7; ++}; ++ ++enum { ++ HW_RATE_1MBPS = 0, ++ HW_RATE_2MBPS = 1, ++ HW_RATE_5_5MBPS = 2, ++ HW_RATE_11MBPS = 3, ++ HW_RATE_6MBPS = 4, ++ HW_RATE_9MBPS = 5, ++ HW_RATE_12MBPS = 6, ++ HW_RATE_18MBPS = 7, ++ HW_RATE_24MBPS = 8, ++ HW_RATE_36MBPS = 9, ++ HW_RATE_48MBPS = 10, ++ HW_RATE_54MBPS = 11, ++ HW_RATE_MAX ++}; ++ ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_rate_ctrl_info { ++ struct { ++ u32 mcsIndexTx : 7; ++ u32 bwTx : 2; ++ u32 giAndPreTypeTx : 2; ++ u32 formatModTx : 3; ++ u32 navProtFrmEx : 3; ++ u32 mcsIndexProtTx : 7; ++ u32 bwProtTx : 2; ++ u32 formatModProtTx : 3; ++ u32 nRetry : 3; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++struct rwnx_power_ctrl_info { ++ u32 txPwrLevelPT : 8; ++ u32 txPwrLevelProtPT : 8; ++ u32 reserved :16; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_phy_ctrl_info_1 { ++ struct { ++ u32 rsvd1 : 3; ++ u32 bfFrmEx : 1; ++ u32 numExtnSS : 2; ++ u32 fecCoding : 1; ++ u32 stbc : 2; ++ u32 rsvd2 : 5; ++ u32 nTx : 3; ++ u32 nTxProt : 3; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_phy_ctrl_info_2 { ++ struct { ++ u32 antennaSet : 8; ++ u32 smmIndex : 8; ++ u32 beamFormed : 1; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_mac_ctrl_info_1 { ++ struct { ++ u32 keySRamIndex : 10; ++ u32 keySRamIndexRA : 10; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_mac_ctrl_info_2 { ++ struct { ++ u32 longRetryLimit : 8; ++ u32 shortRetryLimit : 8; ++ u32 rtsThreshold : 12; ++ }; ++ u32 value; ++}; ++ ++#define POLICY_TABLE_PATTERN 0xBADCAB1E ++ ++struct tx_policy_tbl { ++ /* Unique Pattern at the start of Policy Table */ ++ u32 upatterntx; ++ /* PHY Control 1 Information used by MAC HW */ ++ union rwnx_pol_phy_ctrl_info_1 phyctrlinfo_1; ++ /* PHY Control 2 Information used by MAC HW */ ++ union rwnx_pol_phy_ctrl_info_2 phyctrlinfo_2; ++ /* MAC Control 1 Information used by MAC HW */ ++ union rwnx_pol_mac_ctrl_info_1 macctrlinfo_1; ++ /* MAC Control 2 Information used by MAC HW */ ++ union rwnx_pol_mac_ctrl_info_2 macctrlinfo_2; ++ ++ union rwnx_rate_ctrl_info ratectrlinfos[NX_TX_MAX_RATES]; ++ struct rwnx_power_ctrl_info powerctrlinfos[NX_TX_MAX_RATES]; ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++/** ++ * struct rwnx_hw_txstatus - Bitfield of confirmation status ++ * ++ * @tx_done: packet has been processed by the firmware. ++ * @retry_required: packet has been transmitted but not acknoledged. ++ * Driver must repush it. ++ * @sw_retry_required: packet has not been transmitted (FW wasn't able to push ++ * it when it received it: not active channel ...). Driver must repush it. ++ * @acknowledged: packet has been acknowledged by peer ++ */ ++union rwnx_hw_txstatus { ++ struct { ++ u32 tx_done : 1; ++ u32 retry_required : 1; ++ u32 sw_retry_required : 1; ++ u32 acknowledged : 1; ++ u32 reserved :28; ++ }; ++ u32 value; ++}; ++ ++/** ++ * struct tx_cfm_tag - Structure indicating the status and other ++ * information about the transmission ++ * ++ * @pn: PN that was used for the transmission ++ * @sn: Sequence number of the packet ++ * @timestamp: Timestamp of first transmission of this MPDU ++ * @credits: Number of credits to be reallocated for the txq that push this ++ * buffer (can be 0 or 1) ++ * @ampdu_size: Size of the ampdu in which the frame has been transmitted if ++ * this was the last frame of the a-mpdu, and 0 if the frame is not the last ++ * frame on a a-mdpu. ++ * 1 means that the frame has been transmitted as a singleton. ++ * @amsdu_size: Size, in bytes, allowed to create a-msdu. ++ * @status: transmission status ++ */ ++struct tx_cfm_tag { ++/* ++ u16_l pn[4]; ++ u16_l sn; ++ u16_l timestamp; ++*/ ++ s8_l credits; ++ u8_l ampdu_size; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ u16_l amsdu_size; ++#endif ++ union rwnx_hw_txstatus status; ++ u32_l hostid; ++}; ++ ++/** ++ * struct rwnx_hw_txhdr - Hardware part of tx header ++ * ++ * @cfm: Information updated by fw/hardware after sending a frame ++ */ ++struct rwnx_hw_txhdr { ++ struct tx_cfm_tag cfm; ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/* Modem */ ++ ++#define MDM_PHY_CONFIG_TRIDENT 0 ++#define MDM_PHY_CONFIG_ELMA 1 ++#define MDM_PHY_CONFIG_KARST 2 ++ ++// MODEM features (from reg_mdm_stat.h) ++/// MUMIMOTX field bit ++#define MDM_MUMIMOTX_BIT ((u32)0x80000000) ++/// MUMIMOTX field position ++#define MDM_MUMIMOTX_POS 31 ++/// MUMIMORX field bit ++#define MDM_MUMIMORX_BIT ((u32)0x40000000) ++/// MUMIMORX field position ++#define MDM_MUMIMORX_POS 30 ++/// BFMER field bit ++#define MDM_BFMER_BIT ((u32)0x20000000) ++/// BFMER field position ++#define MDM_BFMER_POS 29 ++/// BFMEE field bit ++#define MDM_BFMEE_BIT ((u32)0x10000000) ++/// BFMEE field position ++#define MDM_BFMEE_POS 28 ++/// LDPCDEC field bit ++#define MDM_LDPCDEC_BIT ((u32)0x08000000) ++/// LDPCDEC field position ++#define MDM_LDPCDEC_POS 27 ++/// LDPCENC field bit ++#define MDM_LDPCENC_BIT ((u32)0x04000000) ++/// LDPCENC field position ++#define MDM_LDPCENC_POS 26 ++/// CHBW field mask ++#define MDM_CHBW_MASK ((u32)0x03000000) ++/// CHBW field LSB position ++#define MDM_CHBW_LSB 24 ++/// CHBW field width ++#define MDM_CHBW_WIDTH ((u32)0x00000002) ++/// DSSSCCK field bit ++#define MDM_DSSSCCK_BIT ((u32)0x00800000) ++/// DSSSCCK field position ++#define MDM_DSSSCCK_POS 23 ++/// VHT field bit ++#define MDM_VHT_BIT ((u32)0x00400000) ++/// VHT field position ++#define MDM_VHT_POS 22 ++/// HE field bit ++#define MDM_HE_BIT ((u32)0x00200000) ++/// HE field position ++#define MDM_HE_POS 21 ++/// ESS field bit ++#define MDM_ESS_BIT ((u32)0x00100000) ++/// ESS field position ++#define MDM_ESS_POS 20 ++/// RFMODE field mask ++#define MDM_RFMODE_MASK ((u32)0x000F0000) ++/// RFMODE field LSB position ++#define MDM_RFMODE_LSB 16 ++/// RFMODE field width ++#define MDM_RFMODE_WIDTH ((u32)0x00000004) ++/// NSTS field mask ++#define MDM_NSTS_MASK ((u32)0x0000F000) ++/// NSTS field LSB position ++#define MDM_NSTS_LSB 12 ++/// NSTS field width ++#define MDM_NSTS_WIDTH ((u32)0x00000004) ++/// NSS field mask ++#define MDM_NSS_MASK ((u32)0x00000F00) ++/// NSS field LSB position ++#define MDM_NSS_LSB 8 ++/// NSS field width ++#define MDM_NSS_WIDTH ((u32)0x00000004) ++/// NTX field mask ++#define MDM_NTX_MASK ((u32)0x000000F0) ++/// NTX field LSB position ++#define MDM_NTX_LSB 4 ++/// NTX field width ++#define MDM_NTX_WIDTH ((u32)0x00000004) ++/// NRX field mask ++#define MDM_NRX_MASK ((u32)0x0000000F) ++/// NRX field LSB position ++#define MDM_NRX_LSB 0 ++/// NRX field width ++#define MDM_NRX_WIDTH ((u32)0x00000004) ++ ++#define __MDM_PHYCFG_FROM_VERS(v) (((v) & MDM_RFMODE_MASK) >> MDM_RFMODE_LSB) ++ ++#define RIU_FCU_PRESENT_MASK ((u32)0xFF000000) ++#define RIU_FCU_PRESENT_LSB 24 ++ ++#define __RIU_FCU_PRESENT(v) (((v) & RIU_FCU_PRESENT_MASK) >> RIU_FCU_PRESENT_LSB == 5) ++ ++/// AGC load version field mask ++#define RIU_AGC_LOAD_MASK ((u32)0x00C00000) ++/// AGC load version field LSB position ++#define RIU_AGC_LOAD_LSB 22 ++ ++#define __RIU_AGCLOAD_FROM_VERS(v) (((v) & RIU_AGC_LOAD_MASK) >> RIU_AGC_LOAD_LSB) ++ ++#define __FPGA_TYPE(v) (((v) & 0xFFFF0000) >> 16) ++ ++#define __MDM_MAJOR_VERSION(v) (((v) & 0xFF000000) >> 24) ++#define __MDM_MINOR_VERSION(v) (((v) & 0x00FF0000) >> 16) ++#define __MDM_VERSION(v) ((__MDM_MAJOR_VERSION(v) + 2) * 10 + __MDM_MINOR_VERSION(v)) ++ ++ ++#endif // _HAL_DESC_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h +new file mode 100644 +index 000000000000..069f69ee5ee0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h +@@ -0,0 +1,25 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file ipc_compat.h ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _IPC_H_ ++#define _IPC_H_ ++ ++#define __INLINE inline ++ ++#define __ALIGN4 __aligned(4) ++ ++#define ASSERT_ERR(condition) \ ++ do { \ ++ if (unlikely(!(condition))) { \ ++ printk(KERN_ERR "%s:%d:ASSERT_ERR(" #condition ")\n", __FILE__, __LINE__); \ ++ } \ ++ } while (0) ++ ++#endif /* _IPC_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c +new file mode 100644 +index 000000000000..7746f4097976 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c +@@ -0,0 +1,52 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file ipc_host.c ++ * ++ * @brief IPC module. ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++/* ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++#ifndef __KERNEL__ ++#include ++#else ++#include ++#include "rwnx_defs.h" ++#include "rwnx_prof.h" ++#endif ++ ++#include "ipc_host.h" ++ ++/* ++ * TYPES DEFINITION ++ ****************************************************************************** ++ */ ++ ++const int nx_txdesc_cnt[] = { ++ NX_TXDESC_CNT0, ++ NX_TXDESC_CNT1, ++ NX_TXDESC_CNT2, ++ NX_TXDESC_CNT3, ++ #if NX_TXQ_CNT == 5 ++ NX_TXDESC_CNT4, ++ #endif ++}; ++ ++const int nx_txuser_cnt[] = { ++ CONFIG_USER_MAX, ++ CONFIG_USER_MAX, ++ CONFIG_USER_MAX, ++ CONFIG_USER_MAX, ++ #if NX_TXQ_CNT == 5 ++ 1, ++ #endif ++}; ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h +new file mode 100644 +index 000000000000..583b66889aa4 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h +@@ -0,0 +1,168 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file ipc_host.h ++ * ++ * @brief IPC module. ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _IPC_HOST_H_ ++#define _IPC_HOST_H_ ++ ++/* ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++#include "ipc_shared.h" ++#ifndef __KERNEL__ ++#include "arch.h" ++#else ++#include "ipc_compat.h" ++#endif ++ ++/** ++ ****************************************************************************** ++ * @brief This structure is used to initialize the MAC SW ++ * ++ * The WLAN device driver provides functions call-back with this structure ++ ****************************************************************************** ++ */ ++struct ipc_host_cb_tag { ++ /// WLAN driver call-back function: send_data_cfm ++ int (*send_data_cfm)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_data_ind ++ uint8_t (*recv_data_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_radar_ind ++ uint8_t (*recv_radar_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_unsup_rx_vec_ind ++ uint8_t (*recv_unsup_rx_vec_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_msg_ind ++ uint8_t (*recv_msg_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_msgack_ind ++ uint8_t (*recv_msgack_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_dbg_ind ++ uint8_t (*recv_dbg_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: prim_tbtt_ind ++ void (*prim_tbtt_ind)(void *pthis); ++ ++ /// WLAN driver call-back function: sec_tbtt_ind ++ void (*sec_tbtt_ind)(void *pthis); ++ ++}; ++ ++/* ++ * Struct used to store information about host buffers (DMA Address and local pointer) ++ */ ++struct ipc_hostbuf { ++ void *hostid; ///< ptr to hostbuf client (ipc_host client) structure ++ uint32_t dma_addr; ///< ptr to real hostbuf dma address ++}; ++ ++/// Definition of the IPC Host environment structure. ++struct ipc_host_env_tag { ++ /// Structure containing the callback pointers ++ struct ipc_host_cb_tag cb; ++ ++ /// Pointer to the shared environment ++ struct ipc_shared_env_tag *shared; ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ // Array used to store the descriptor addresses ++ struct ipc_hostbuf ipc_host_rxdesc_array[IPC_RXDESC_CNT]; ++ // Index of the host RX descriptor array (ipc_shared environment) ++ uint8_t ipc_host_rxdesc_idx; ++ /// Store the number of RX Descriptors ++ uint8_t rxdesc_nb; ++ #endif //(CONFIG_RWNX_FULLMAC) ++ ++ /// Fields for Data Rx handling ++ // Index used for ipc_host_rxbuf_array to point to current buffer ++ uint8_t ipc_host_rxbuf_idx; ++ // Store the number of Rx Data buffers ++ uint32_t rx_bufnb; ++ // Store the size of the Rx Data buffers ++ uint32_t rx_bufsz; ++ ++ /// Fields for Radar events handling ++ // Global array used to store the hostid and hostbuf addresses ++ struct ipc_hostbuf ipc_host_radarbuf_array[IPC_RADARBUF_CNT]; ++ // Index used for ipc_host_rxbuf_array to point to current buffer ++ uint8_t ipc_host_radarbuf_idx; ++ // Store the number of radar event buffers ++ uint32_t radar_bufnb; ++ // Store the size of the radar event buffers ++ uint32_t radar_bufsz; ++ ++ ///Fields for Unsupported frame handling ++ // Global array used to store the hostid and hostbuf addresses ++ struct ipc_hostbuf ipc_host_unsuprxvecbuf_array[IPC_UNSUPRXVECBUF_CNT]; ++ // Index used for ipc_host_unsuprxvecbuf_array to point to current buffer ++ uint8_t ipc_host_unsuprxvecbuf_idx; ++ // Store the number of unsupported rx vector buffers ++ uint32_t unsuprxvec_bufnb; ++ // Store the size of unsupported rx vector buffers ++ uint32_t unsuprxvec_bufsz; ++ ++ // Index used that points to the first free TX desc ++ uint32_t txdesc_free_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ // Index used that points to the first used TX desc ++ uint32_t txdesc_used_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ // Array storing the currently pushed host ids for the BK queue ++ void *tx_host_id0[CONFIG_USER_MAX][NX_TXDESC_CNT0]; ++ // Array storing the currently pushed host ids for the BE queue ++ void *tx_host_id1[CONFIG_USER_MAX][NX_TXDESC_CNT1]; ++ // Array storing the currently pushed host ids for the VI queue ++ void *tx_host_id2[CONFIG_USER_MAX][NX_TXDESC_CNT2]; ++ // Array storing the currently pushed host ids for the VO queue ++ void *tx_host_id3[CONFIG_USER_MAX][NX_TXDESC_CNT3]; ++ #if NX_TXQ_CNT == 5 ++ // Array storing the currently pushed host ids for the BCN queue ++ void *tx_host_id4[1][NX_TXDESC_CNT4]; ++ #endif ++ // Pointer to the different host ids arrays, per IPC queue ++ void **tx_host_id[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ // Pointer to the different TX descriptor arrays, per IPC queue ++ volatile struct txdesc_host *txdesc[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ ++ /// Fields for Emb->App MSGs handling ++ // Global array used to store the hostid and hostbuf addresses for msg/ind ++ struct ipc_hostbuf ipc_host_msgbuf_array[IPC_MSGE2A_BUF_CNT]; ++ // Index of the MSG E2A buffers array to point to current buffer ++ uint8_t ipc_host_msge2a_idx; ++ // Store the number of E2A MSG buffers ++ uint32_t ipc_e2amsg_bufnb; ++ // Store the size of the E2A MSG buffers ++ uint32_t ipc_e2amsg_bufsz; ++ ++ /// E2A ACKs of A2E MSGs ++ uint8_t msga2e_cnt; ++ void *msga2e_hostid; ++ ++ /// Fields for Debug MSGs handling ++ // Global array used to store the hostid and hostbuf addresses for Debug messages ++ struct ipc_hostbuf ipc_host_dbgbuf_array[IPC_DBGBUF_CNT]; ++ // Index of the Debug messages buffers array to point to current buffer ++ uint8_t ipc_host_dbg_idx; ++ // Store the number of Debug messages buffers ++ uint32_t ipc_dbg_bufnb; ++ // Store the size of the Debug messages buffers ++ uint32_t ipc_dbg_bufsz; ++ ++ /// Pointer to the attached object (used in callbacks and register accesses) ++ void *pthis; ++}; ++ ++extern const int nx_txdesc_cnt[]; ++extern const int nx_txuser_cnt[]; ++ ++#endif // _IPC_HOST_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h +new file mode 100644 +index 000000000000..7e2fedcb1b53 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h +@@ -0,0 +1,785 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file ipc_shared.h ++ * ++ * @brief Shared data between both IPC modules. ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _IPC_SHARED_H_ ++#define _IPC_SHARED_H_ ++ ++/* ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++#include "ipc_compat.h" ++#include "lmac_mac.h" ++ ++/* ++ * DEFINES AND MACROS ++ **************************************************************************************** ++ */ ++#define CO_BIT(pos) (1U<<(pos)) ++ ++#define IPC_TXQUEUE_CNT NX_TXQ_CNT ++#define NX_TXDESC_CNT0 8 ++#define NX_TXDESC_CNT1 64 ++#define NX_TXDESC_CNT2 64 ++#define NX_TXDESC_CNT3 32 ++#if NX_TXQ_CNT == 5 ++#define NX_TXDESC_CNT4 8 ++#endif ++ ++/* ++ * Number of Host buffers available for Data Rx handling (through DMA) ++ */ ++#define IPC_RXBUF_CNT 128 ++ ++/* ++ * Number of shared descriptors available for Data RX handling ++ */ ++#define IPC_RXDESC_CNT 128 ++ ++/* ++ * Number of Host buffers available for Radar events handling (through DMA) ++ */ ++#define IPC_RADARBUF_CNT 16 ++ ++/* ++ * Number of Host buffers available for unsupported Rx vectors handling (through DMA) ++ */ ++#define IPC_UNSUPRXVECBUF_CNT 8 ++ ++/* ++ * Size of RxVector ++ */ ++#define IPC_RXVEC_SIZE 16 ++ ++/* ++ * Number of Host buffers available for Emb->App MSGs sending (through DMA) ++ */ ++#ifdef CONFIG_RWNX_FULLMAC ++#define IPC_MSGE2A_BUF_CNT 64 ++#endif ++/* ++ * Number of Host buffers available for Debug Messages sending (through DMA) ++ */ ++#define IPC_DBGBUF_CNT 32 ++ ++/* ++ * Length used in MSGs structures ++ */ ++#define IPC_A2E_MSG_BUF_SIZE 127 // size in 4-byte words ++#ifdef CONFIG_RWNX_FULLMAC ++#define IPC_E2A_MSG_SIZE_BASE 256 // size in 4-byte words ++#endif ++ ++#ifdef CONFIG_RWNX_TL4 ++#define IPC_E2A_MSG_PARAM_SIZE (IPC_E2A_MSG_SIZE_BASE + (IPC_E2A_MSG_SIZE_BASE / 2)) ++#else ++#define IPC_E2A_MSG_PARAM_SIZE IPC_E2A_MSG_SIZE_BASE ++#endif ++ ++/* ++ * Debug messages buffers size (in bytes) ++ */ ++#define IPC_DBG_PARAM_SIZE 256 ++ ++/* ++ * Define used for Rx hostbuf validity. ++ * This value should appear only when hostbuf was used for a Reception. ++ */ ++#define RX_DMA_OVER_PATTERN 0xAAAAAA00 ++ ++/* ++ * Define used for MSG buffers validity. ++ * This value will be written only when a MSG buffer is used for sending from Emb to App. ++ */ ++#define IPC_MSGE2A_VALID_PATTERN 0xADDEDE2A ++ ++/* ++ * Define used for Debug messages buffers validity. ++ * This value will be written only when a DBG buffer is used for sending from Emb to App. ++ */ ++#define IPC_DBG_VALID_PATTERN 0x000CACA0 ++ ++/* ++ * Length of the receive vectors, in bytes ++ */ ++#define DMA_HDR_PHYVECT_LEN 36 ++ ++/* ++ * Maximum number of payload addresses and lengths present in the descriptor ++ */ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++#define NX_TX_PAYLOAD_MAX 6 ++#else ++#define NX_TX_PAYLOAD_MAX 1 ++#endif ++ ++/* ++ * Message struct/ID API version ++ */ ++#define MSG_API_VER 33 ++ ++/* ++ **************************************************************************************** ++ */ ++// c.f LMAC/src/tx/tx_swdesc.h ++/// Descriptor filled by the Host ++struct hostdesc { ++ /// Pointer to packet payload ++ //u32_l packet_addr; ++ /// Size of the payload ++ u16_l packet_len; ++ u16_l flags_ext; ++ ++ u32_l hostid; ++#ifdef CONFIG_RWNX_FULLMAC ++ /// Address of the status descriptor in host memory (used for confirmation upload) ++ //u32_l status_desc_addr; ++ /// Destination Address ++ struct mac_addr eth_dest_addr; ++ /// Source Address ++ struct mac_addr eth_src_addr; ++ /// Ethernet Type ++ u16_l ethertype; ++#else /* ! CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_AGG_TX ++ ///Sequence Number for AMPDU MPDUs - for quick check if it's allowed within window ++ u16_l sn; ++#endif /* CONFIG_RWNX_AGG_TX */ ++ /// Padding between the buffer control structure and the MPDU in host memory ++ u8_l padding; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ u8_l ac; ++ /// Packet TID (0xFF if not a QoS frame) ++ u8_l tid; ++ /// Interface Id ++ u8_l vif_idx; ++ /// Station Id (0xFF if station is unknown) ++ u8_l staid; ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ /// MU-MIMO information (GroupId and User Position in the group) - The GroupId ++ /// is located on bits 0-5 and the User Position on bits 6-7. The GroupId value is set ++ /// to 63 if MU-MIMO shall not be used ++ u8_l mumimo_info; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#ifdef CONFIG_RWNX_FULLMAC ++ /// TX flags ++ u16_l flags; ++#endif /* CONFIG_RWNX_FULLMAC */ ++}; ++ ++/// Descriptor filled by the UMAC ++struct umacdesc { ++#ifdef CONFIG_RWNX_AGG_TX ++ ///First Sequence Number of the BlockAck window ++ u16_l sn_win; ++ /// Flags from UMAC (match tx_hd.macctrlinfo2 format) ++ u32_l flags; ++ /// PHY related flags field - rate, GI type, BW type - filled by driver ++ u32_l phy_flags; ++#endif //(CONFIG_RWNX_AGG_TX) ++}; ++ ++struct txdesc_api { ++ /// Information provided by Host ++ struct hostdesc host; ++}; ++ ++ ++struct txdesc_host { ++ u32_l ready; ++ ++ /// API of the embedded part ++ struct txdesc_api api; ++}; ++ ++/// Comes from ipc_dma.h ++/// Element in the pool of TX DMA bridge descriptors. ++struct dma_desc { ++ /** Application subsystem address which is used as source address for DMA payload ++ * transfer*/ ++ u32_l src; ++ /** Points to the start of the embedded data buffer associated with this descriptor. ++ * This address acts as the destination address for the DMA payload transfer*/ ++ u32_l dest; ++ /// Complete length of the buffer in memory ++ u16_l length; ++ /// Control word for the DMA engine (e.g. for interrupt generation) ++ u16_l ctrl; ++ /// Pointer to the next element of the chained list ++ u32_l next; ++}; ++ ++// Comes from la.h ++/// Length of the configuration data of a logic analyzer ++#define LA_CONF_LEN 10 ++ ++/// Structure containing the configuration data of a logic analyzer ++struct la_conf_tag { ++ u32_l conf[LA_CONF_LEN]; ++ u32_l trace_len; ++ u32_l diag_conf; ++}; ++ ++/// Size of a logic analyzer memory ++#define LA_MEM_LEN (1024 * 1024) ++ ++/// Type of errors ++enum { ++ /// Recoverable error, not requiring any action from Upper MAC ++ DBG_ERROR_RECOVERABLE = 0, ++ /// Fatal error, requiring Upper MAC to reset Lower MAC and HW and restart operation ++ DBG_ERROR_FATAL ++}; ++ ++/// Maximum length of the SW diag trace ++#define DBG_SW_DIAG_MAX_LEN 1024 ++ ++/// Maximum length of the error trace ++#define DBG_ERROR_TRACE_SIZE 256 ++ ++/// Number of MAC diagnostic port banks ++#define DBG_DIAGS_MAC_MAX 48 ++ ++/// Number of PHY diagnostic port banks ++#define DBG_DIAGS_PHY_MAX 32 ++ ++/// Maximum size of the RX header descriptor information in the debug dump ++#define DBG_RHD_MEM_LEN (5 * 1024) ++ ++/// Maximum size of the RX buffer descriptor information in the debug dump ++#define DBG_RBD_MEM_LEN (5 * 1024) ++ ++/// Maximum size of the TX header descriptor information in the debug dump ++#define DBG_THD_MEM_LEN (10 * 1024) ++ ++/// Structure containing the information about the PHY channel that is used ++struct phy_channel_info { ++ /// PHY channel information 1 ++ u32_l info1; ++ /// PHY channel information 2 ++ u32_l info2; ++}; ++ ++/// Debug information forwarded to host when an error occurs ++struct dbg_debug_info_tag { ++ /// Type of error (0: recoverable, 1: fatal) ++ u32_l error_type; ++ /// Pointer to the first RX Header Descriptor chained to the MAC HW ++ u32_l rhd; ++ /// Size of the RX header descriptor buffer ++ u32_l rhd_len; ++ /// Pointer to the first RX Buffer Descriptor chained to the MAC HW ++ u32_l rbd; ++ /// Size of the RX buffer descriptor buffer ++ u32_l rbd_len; ++ /// Pointer to the first TX Header Descriptors chained to the MAC HW ++ u32_l thd[NX_TXQ_CNT]; ++ /// Size of the TX header descriptor buffer ++ u32_l thd_len[NX_TXQ_CNT]; ++ /// MAC HW diag configuration ++ u32_l hw_diag; ++ /// Error message ++ u32_l error[DBG_ERROR_TRACE_SIZE/4]; ++ /// SW diag configuration length ++ u32_l sw_diag_len; ++ /// SW diag configuration ++ u32_l sw_diag[DBG_SW_DIAG_MAX_LEN/4]; ++ /// PHY channel information ++ struct phy_channel_info chan_info; ++ /// Embedded LA configuration ++ struct la_conf_tag la_conf; ++ /// MAC diagnostic port state ++ u16_l diags_mac[DBG_DIAGS_MAC_MAX]; ++ /// PHY diagnostic port state ++ u16_l diags_phy[DBG_DIAGS_PHY_MAX]; ++ /// MAC HW RX Header descriptor pointer ++ u32_l rhd_hw_ptr; ++ /// MAC HW RX Buffer descriptor pointer ++ u32_l rbd_hw_ptr; ++}; ++ ++/// Full debug dump that is forwarded to host in case of error ++struct dbg_debug_dump_tag { ++ /// Debug information ++ struct dbg_debug_info_tag dbg_info; ++ ++ /// RX header descriptor memory ++ u32_l rhd_mem[DBG_RHD_MEM_LEN/4]; ++ ++ /// RX buffer descriptor memory ++ u32_l rbd_mem[DBG_RBD_MEM_LEN/4]; ++ ++ /// TX header descriptor memory ++ u32_l thd_mem[NX_TXQ_CNT][DBG_THD_MEM_LEN/4]; ++ ++ /// Logic analyzer memory ++ u32_l la_mem[LA_MEM_LEN/4]; ++}; ++ ++ ++/// Number of pulses in a radar event structure ++#define RADAR_PULSE_MAX 4 ++ ++/// Definition of an array of radar pulses ++struct radar_pulse_array_desc { ++ /// Buffer containing the radar pulses ++ u32_l pulse[RADAR_PULSE_MAX]; ++ /// Index of the radar detection chain that detected those pulses ++ u32_l idx; ++ /// Number of valid pulses in the buffer ++ u32_l cnt; ++}; ++ ++/// Bit mapping inside a radar pulse element ++struct radar_pulse { ++ s32_l freq:6; /** Freq (resolution is 2Mhz range is [-Fadc/4 .. Fadc/4]) */ ++ u32_l fom:4; /** Figure of Merit */ ++ u32_l len:6; /** Length of the current radar pulse (resolution is 2us) */ ++ u32_l rep:16; /** Time interval between the previous radar event ++ and the current one (in us) */ ++}; ++ ++/// Definition of a RX vector descriptor ++struct rx_vector_desc { ++ /// PHY channel information ++ struct phy_channel_info phy_info; ++ ++ /// RX vector 1 ++ u32_l rx_vect1[IPC_RXVEC_SIZE/4]; ++ ++ /// Used to print a valid rx vector ++ u32_l pattern; ++}; ++ ++/// ++struct rxdesc_tag { ++ /// Host Buffer Address ++ u32_l host_id; ++ /// Length ++ u32_l frame_len; ++ /// Status ++ u16_l status; ++}; ++ ++/** ++ **************************************************************************************** ++ * @defgroup IPC IPC ++ * @ingroup NXMAC ++ * @brief Inter Processor Communication module. ++ * ++ * The IPC module implements the protocol to communicate between the Host CPU ++ * and the Embedded CPU. ++ * ++ * @see http://en.wikipedia.org/wiki/Circular_buffer ++ * For more information about the ring buffer typical use and difficulties. ++ **************************************************************************************** ++ */ ++ ++ ++/** ++ **************************************************************************************** ++ * @addtogroup IPC_TX IPC Tx path ++ * @ingroup IPC ++ * @brief IPC Tx path structures and functions ++ * ++ * A typical use case of the IPC Tx path API: ++ * @msc ++ * hscale = "2"; ++ * ++ * a [label=Driver], ++ * b [label="IPC host"], ++ * c [label="IPC emb"], ++ * d [label=Firmware]; ++ * ++ * --- [label="Tx descriptor queue example"]; ++ * a=>a [label="Driver receives a Tx packet from OS"]; ++ * a=>b [label="ipc_host_txdesc_get()"]; ++ * a<a [label="Driver fill the descriptor"]; ++ * a=>b [label="ipc_host_txdesc_push()"]; ++ * ... [label="(several Tx desc can be pushed)"]; ++ * b:>c [label="Tx desc queue filled IRQ"]; ++ * c=>>d [label="EDCA sub-scheduler callback"]; ++ * c<>d [label="UMAC Tx desc callback"]; ++ * ... [label="(several Tx desc can be popped)"]; ++ * d=>d [label="Packets are sent or discarded"]; ++ * --- [label="Tx confirm queue example"]; ++ * c<=d [label="ipc_emb_txcfm_push()"]; ++ * c>>d [label="Request accepted"]; ++ * ... [label="(several Tx cfm can be pushed)"]; ++ * b<:c [label="Tx cfm queue filled IRQ"]; ++ * a<<=b [label="Driver's Tx Confirm callback"]; ++ * a=>b [label="ipc_host_txcfm_pop()"]; ++ * a<c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * ... [label="(several Rx buffer are pushed)"]; ++ * a=>a [label=" Frame is received\n from the medium"]; ++ * a<a [label=" Firmware fill the buffer\n with received frame"]; ++ * a<c [label="Rx desc queue filled IRQ"]; ++ * c=>>d [label="Driver Rx packet callback"]; ++ * c<=d [label="ipc_host_rxdesc_pop()"]; ++ * d=>d [label="Rx packet is handed \nover to the OS "]; ++ * ... [label="(several Rx desc can be poped)"]; ++ * --- [label="Rx buffer request exemple"]; ++ * b:>c [label="Low Rx buffer count IRQ"]; ++ * a<>d [label="Driver Rx buffer callback"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * ... [label="(several Rx buffer are pushed)"]; ++ * @endmsc ++ * ++ * @addtogroup IPC_RX ++ * @{ ++ **************************************************************************************** ++ */ ++ ++/// @} IPC_RX ++ ++ ++ ++/** ++ **************************************************************************************** ++ * @defgroup IPC_MISC IPC Misc ++ * @ingroup IPC ++ * @brief IPC miscellaneous functions ++ **************************************************************************************** ++ */ ++/** IPC header structure. This structure is stored at the beginning of every IPC message. ++ * @warning This structure's size must NOT exceed 4 bytes in length. ++ */ ++struct ipc_header { ++ /// IPC message type. ++ u16_l type; ++ /// IPC message size in number of bytes. ++ u16_l size; ++}; ++ ++struct ipc_msg_elt { ++ /// Message header (alignment forced on word size, see allocation in shared env). ++ struct ipc_header header __ALIGN4; ++}; ++ ++/// Message structure for MSGs from Emb to App ++struct ipc_e2a_msg { ++ u16_l id; ///< Message id. ++ u16_l dummy_dest_id; ++ u16_l dummy_src_id; ++ u16_l param_len; ///< Parameter embedded struct length. ++ u32_l pattern; ///< Used to stamp a valid MSG buffer ++ u32_l param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++/// Message structure for Debug messages from Emb to App ++struct ipc_dbg_msg { ++ u32_l string[IPC_DBG_PARAM_SIZE/4]; ///< Debug string ++ u32_l pattern; ///< Used to stamp a valid buffer ++}; ++ ++/// Message structure for MSGs from App to Emb. ++/// Actually a sub-structure will be used when filling the messages. ++struct ipc_a2e_msg { ++ u32_l dummy_word; // used to cope with kernel message structure ++ u32_l msg[IPC_A2E_MSG_BUF_SIZE]; // body of the msg ++}; ++ ++struct ipc_shared_rx_buf { ++ /// < ptr to hostbuf client (ipc_host client) structure ++ u32_l hostid; ++ /// < ptr to real hostbuf dma address ++ u32_l dma_addr; ++}; ++ ++struct ipc_shared_rx_desc { ++ /// DMA Address ++ u32_l dma_addr; ++}; ++ ++/// Structure containing FW characteristics for compatibility checking ++struct compatibility_tag { ++ /// Size of IPC shared memory ++ u16_l ipc_shared_size; ++ /// Message struct/ID API version ++ u16_l msg_api; ++ /// Version of IPC shared ++ u8_l ipc_shared_version; ++ /// Number of host buffers available for Emb->App MSGs sending ++ u8_l msge2a_buf_cnt; ++ /// Number of host buffers available for Debug Messages sending ++ u8_l dbgbuf_cnt; ++ /// Number of host buffers available for Radar events handling ++ u8_l radarbuf_cnt; ++ /// Number of host buffers available for unsupported Rx vectors handling ++ u8_l unsuprxvecbuf_cnt; ++ /// Number of shared descriptors available for Data RX handling ++ u8_l rxdesc_cnt; ++ /// Number of host buffers available for Data Rx handling ++ u8_l rxbuf_cnt; ++ /// Number of descriptors in BK TX queue (power of 2, min 4, max 64) ++ u8_l bk_txq; ++ /// Number of descriptors in BE TX queue (power of 2, min 4, max 64) ++ u8_l be_txq; ++ /// Number of descriptors in VI TX queue (power of 2, min 4, max 64) ++ u8_l vi_txq; ++ /// Number of descriptors in VO TX queue (power of 2, min 4, max 64) ++ u8_l vo_txq; ++ /// Number of descriptors in BCN TX queue (power of 2, min 4, max 64) ++ u8_l bcn_txq; ++}; ++ ++/* ++ * TYPE and STRUCT DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++ ++// Indexes are defined in the MIB shared structure ++struct ipc_shared_env_tag { ++ volatile struct compatibility_tag comp_info; //FW characteristics ++ ++ volatile struct ipc_a2e_msg msg_a2e_buf; // room for MSG to be sent from App to Emb ++ ++ // Fields for MSGs sending from Emb to App ++ volatile struct ipc_e2a_msg msg_e2a_buf; // room to build the MSG to be DMA Xferred ++ volatile struct dma_desc msg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers ++ volatile u32_l msg_e2a_hostbuf_addr[IPC_MSGE2A_BUF_CNT]; // buffers @ for DMA Xfers ++ ++ // Fields for Debug MSGs sending from Emb to App ++ volatile struct ipc_dbg_msg dbg_buf; // room to build the MSG to be DMA Xferred ++ volatile struct dma_desc dbg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers ++ volatile u32_l dbg_hostbuf_addr[IPC_DBGBUF_CNT]; // buffers @ for MSGs DMA Xfers ++ volatile u32_l la_dbginfo_addr; // Host buffer address for the debug information ++ volatile u32_l pattern_addr; ++ volatile u32_l radarbuf_hostbuf[IPC_RADARBUF_CNT]; // buffers @ for Radar Events ++ volatile u32_l unsuprxvecbuf_hostbuf[IPC_UNSUPRXVECBUF_CNT]; // buffers @ for unsupported Rx vectors ++ volatile struct txdesc_host txdesc0[CONFIG_USER_MAX][NX_TXDESC_CNT0]; ++ volatile struct txdesc_host txdesc1[CONFIG_USER_MAX][NX_TXDESC_CNT1]; ++ volatile struct txdesc_host txdesc2[CONFIG_USER_MAX][NX_TXDESC_CNT2]; ++ volatile struct txdesc_host txdesc3[CONFIG_USER_MAX][NX_TXDESC_CNT3]; ++ #if NX_TXQ_CNT == 5 ++ volatile struct txdesc_host txdesc4[1][NX_TXDESC_CNT4]; ++ #endif ++ #ifdef CONFIG_RWNX_FULLMAC ++ // RX Descriptors Array ++ volatile struct ipc_shared_rx_desc host_rxdesc[IPC_RXDESC_CNT]; ++ // RX Buffers Array ++ volatile struct ipc_shared_rx_buf host_rxbuf[IPC_RXBUF_CNT]; ++ #else ++ // buffers @ for Data Rx ++ volatile u32_l host_rxbuf[IPC_RXBUF_CNT]; ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ ++ u32_l buffered[NX_REMOTE_STA_MAX][TID_MAX]; ++ ++ volatile uint16_t trace_pattern; ++ volatile uint32_t trace_start; ++ volatile uint32_t trace_end; ++ volatile uint32_t trace_size; ++ volatile uint32_t trace_offset; ++ volatile uint32_t trace_nb_compo; ++ volatile uint32_t trace_offset_compo; ++}; ++ ++extern struct ipc_shared_env_tag ipc_shared_env; ++ ++ ++/* ++ * TYPE and STRUCT DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++// IRQs from app to emb ++/// Interrupts bits used for the TX descriptors of the AC queues ++#ifdef CONFIG_RWNX_MUMIMO_TX ++#ifdef CONFIG_RWNX_OLD_IPC ++#error "MU-MIMO cannot be compiled for old IPC" ++#endif ++/// Interrupts bits used ++#if CONFIG_USER_MAX > 3 ++#define IPC_IRQ_A2E_USER_MSK 0xF ++#elif CONFIG_USER_MAX > 2 ++#define IPC_IRQ_A2E_USER_MSK 0x7 ++#else ++#define IPC_IRQ_A2E_USER_MSK 0x3 ++#endif ++ ++/// Offset of the interrupts for AC0 ++#define IPC_IRQ_A2E_AC0_OFT 8 ++/// Mask of the interrupts for AC0 ++#define IPC_IRQ_A2E_AC0_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC0_OFT) ++/// Offset of the interrupts for AC1 ++#define IPC_IRQ_A2E_AC1_OFT (IPC_IRQ_A2E_AC0_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC1 ++#define IPC_IRQ_A2E_AC1_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC1_OFT) ++/// Offset of the interrupts for AC2 ++#define IPC_IRQ_A2E_AC2_OFT (IPC_IRQ_A2E_AC1_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC2 ++#define IPC_IRQ_A2E_AC2_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC2_OFT) ++/// Offset of the interrupts for AC3 ++#define IPC_IRQ_A2E_AC3_OFT (IPC_IRQ_A2E_AC2_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC3 ++#define IPC_IRQ_A2E_AC3_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC3_OFT) ++/// Offset of the interrupts for BCN ++#define IPC_IRQ_A2E_BCN_OFT (IPC_IRQ_A2E_AC3_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for BCN ++#define IPC_IRQ_A2E_BCN_MSK CO_BIT(IPC_IRQ_A2E_BCN_OFT) ++ ++#define IPC_IRQ_A2E_AC_TXDESC (IPC_IRQ_A2E_AC0_MSK | IPC_IRQ_A2E_AC1_MSK | \ ++ IPC_IRQ_A2E_AC2_MSK | IPC_IRQ_A2E_AC3_MSK) ++ ++/// Interrupts bits used for the TX descriptors of the BCN queue ++#if NX_TXQ_CNT < 5 ++#define IPC_IRQ_A2E_BCN_TXDESC 0 ++#else ++#define IPC_IRQ_A2E_BCN_TXDESC (0x01 << IPC_IRQ_A2E_BCN_OFT) ++#endif ++ ++/// IPC TX descriptor interrupt mask ++#define IPC_IRQ_A2E_TXDESC (IPC_IRQ_A2E_AC_TXDESC | IPC_IRQ_A2E_BCN_TXDESC) ++#else ++/// IPC TX descriptor interrupt mask ++#define IPC_IRQ_A2E_TXDESC 0xFF00 ++#endif ++ ++#define IPC_IRQ_A2E_TXDESC_FIRSTBIT (8) ++#define IPC_IRQ_A2E_RXBUF_BACK CO_BIT(5) ++#define IPC_IRQ_A2E_RXDESC_BACK CO_BIT(4) ++ ++#define IPC_IRQ_A2E_MSG CO_BIT(1) ++#define IPC_IRQ_A2E_DBG CO_BIT(0) ++ ++#define IPC_IRQ_A2E_ALL (IPC_IRQ_A2E_TXDESC|IPC_IRQ_A2E_MSG|IPC_IRQ_A2E_DBG) ++ ++// IRQs from emb to app ++#define IPC_IRQ_E2A_TXCFM_POS 7 ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++#ifdef CONFIG_RWNX_OLD_IPC ++#error "MU-MIMO cannot be compiled for old IPC" ++#endif ++/// Interrupts bits used ++#if CONFIG_USER_MAX > 3 ++#define IPC_IRQ_E2A_USER_MSK 0xF ++#elif CONFIG_USER_MAX > 2 ++#define IPC_IRQ_E2A_USER_MSK 0x7 ++#else ++#define IPC_IRQ_E2A_USER_MSK 0x3 ++#endif ++ ++/// Offset of the interrupts for AC0 ++#define IPC_IRQ_E2A_AC0_OFT IPC_IRQ_E2A_TXCFM_POS ++/// Mask of the interrupts for AC0 ++#define IPC_IRQ_E2A_AC0_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC0_OFT) ++/// Offset of the interrupts for AC1 ++#define IPC_IRQ_E2A_AC1_OFT (IPC_IRQ_E2A_AC0_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC1 ++#define IPC_IRQ_E2A_AC1_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC1_OFT) ++/// Offset of the interrupts for AC2 ++#define IPC_IRQ_E2A_AC2_OFT (IPC_IRQ_E2A_AC1_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC2 ++#define IPC_IRQ_E2A_AC2_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC2_OFT) ++/// Offset of the interrupts for AC3 ++#define IPC_IRQ_E2A_AC3_OFT (IPC_IRQ_E2A_AC2_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC3 ++#define IPC_IRQ_E2A_AC3_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC3_OFT) ++/// Offset of the interrupts for BCN ++#define IPC_IRQ_E2A_BCN_OFT (IPC_IRQ_E2A_AC3_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for BCN ++#define IPC_IRQ_E2A_BCN_MSK CO_BIT(IPC_IRQ_E2A_BCN_OFT) ++ ++#define IPC_IRQ_E2A_AC_TXCFM (IPC_IRQ_E2A_AC0_MSK | IPC_IRQ_E2A_AC1_MSK | \ ++ IPC_IRQ_E2A_AC2_MSK | IPC_IRQ_E2A_AC3_MSK) ++ ++/// Interrupts bits used for the TX descriptors of the BCN queue ++#if NX_TXQ_CNT < 5 ++#define IPC_IRQ_E2A_BCN_TXCFM 0 ++#else ++#define IPC_IRQ_E2A_BCN_TXCFM (0x01 << IPC_IRQ_E2A_BCN_OFT) ++#endif ++ ++/// IPC TX descriptor interrupt mask ++#define IPC_IRQ_E2A_TXCFM (IPC_IRQ_E2A_AC_TXCFM | IPC_IRQ_E2A_BCN_TXCFM) ++ ++#else ++ ++#define IPC_IRQ_E2A_TXCFM (((1 << NX_TXQ_CNT) - 1) << IPC_IRQ_E2A_TXCFM_POS) ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++#define IPC_IRQ_E2A_UNSUP_RX_VEC CO_BIT(7) ++#define IPC_IRQ_E2A_RADAR CO_BIT(6) ++#define IPC_IRQ_E2A_TBTT_SEC CO_BIT(5) ++#define IPC_IRQ_E2A_TBTT_PRIM CO_BIT(4) ++#define IPC_IRQ_E2A_RXDESC CO_BIT(3) ++#define IPC_IRQ_E2A_MSG_ACK CO_BIT(2) ++#define IPC_IRQ_E2A_MSG CO_BIT(1) ++#define IPC_IRQ_E2A_DBG CO_BIT(0) ++ ++#define IPC_IRQ_E2A_ALL (IPC_IRQ_E2A_TXCFM \ ++ | IPC_IRQ_E2A_RXDESC \ ++ | IPC_IRQ_E2A_MSG_ACK \ ++ | IPC_IRQ_E2A_MSG \ ++ | IPC_IRQ_E2A_DBG \ ++ | IPC_IRQ_E2A_TBTT_PRIM \ ++ | IPC_IRQ_E2A_TBTT_SEC \ ++ | IPC_IRQ_E2A_RADAR \ ++ | IPC_IRQ_E2A_UNSUP_RX_VEC) ++ ++// FLAGS for RX desc ++#define IPC_RX_FORWARD CO_BIT(1) ++#define IPC_RX_INTRABSS CO_BIT(0) ++ ++ ++// IPC message TYPE ++enum { ++ IPC_MSG_NONE = 0, ++ IPC_MSG_WRAP, ++ IPC_MSG_KMSG, ++ ++ IPC_DBG_STRING, ++ ++}; ++ ++#endif // _IPC_SHARED_H_ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h +new file mode 100644 +index 000000000000..2753d4d23253 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h +@@ -0,0 +1,564 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file lmac_mac_types.h ++ * ++ * @brief MAC related definitions. ++ * ++ * Adapted from mac_types.h to used lmac_types.h instead of standard types ++ * eg: perl -pi -e '$_ =~ s/uint(\d{1,2})_t/u$1_l/g; \ ++ * $_ =~ s/int(\d{1,2})_t/s$1_l/g; \ ++ * $_ =~ s/CO_BIT/BIT/g;' lmac_mac.h ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef LMAC_MAC_H_ ++#define LMAC_MAC_H_ ++ ++#include "lmac_types.h" ++ ++/// Interface types ++enum mac_vif_type { ++ /// ESS STA interface ++ VIF_STA, ++ /// IBSS STA interface ++ VIF_IBSS, ++ /// AP interface ++ VIF_AP, ++ /// Mesh Point interface ++ VIF_MESH_POINT, ++ /// Monitor interface ++ VIF_MONITOR, ++ /// Unknown type ++ VIF_UNKNOWN ++}; ++ ++/// MAC address length in bytes. ++#define MAC_ADDR_LEN 6 ++ ++/// MAC address structure. ++struct mac_addr { ++ /// Array of 16-bit words that make up the MAC address. ++ u16_l array[MAC_ADDR_LEN/2]; ++}; ++ ++/// SSID maximum length. ++#define MAC_SSID_LEN 32 ++ ++/// SSID. ++struct mac_ssid { ++ /// Actual length of the SSID. ++ u8_l length; ++ /// Array containing the SSID name. ++ u8_l array[MAC_SSID_LEN]; ++}; ++ ++/// BSS type ++enum mac_bss_type { ++ INFRASTRUCTURE_MODE = 1, ++ INDEPENDENT_BSS_MODE, ++ ANY_BSS_MODE ++}; ++ ++/// Channel Band ++enum mac_chan_band { ++ /// 2.4GHz Band ++ PHY_BAND_2G4, ++ /// 5GHz band ++ PHY_BAND_5G, ++ /// Number of bands ++ PHY_BAND_MAX, ++}; ++ ++/// Operating Channel Bandwidth ++enum mac_chan_bandwidth { ++ /// 20MHz BW ++ PHY_CHNL_BW_20, ++ /// 40MHz BW ++ PHY_CHNL_BW_40, ++ /// 80MHz BW ++ PHY_CHNL_BW_80, ++ /// 160MHz BW ++ PHY_CHNL_BW_160, ++ /// 80+80MHz BW ++ PHY_CHNL_BW_80P80, ++ /// Reserved BW ++ PHY_CHNL_BW_OTHER, ++}; ++ ++/// max number of channels in the 2.4 GHZ band ++#define MAC_DOMAINCHANNEL_24G_MAX 14 ++ ++/// max number of channels in the 5 GHZ band ++#define MAC_DOMAINCHANNEL_5G_MAX 28 ++ ++/// Channel Flag ++enum mac_chan_flags { ++ /// Cannot initiate radiation on this channel ++ CHAN_NO_IR = BIT(0), ++ /// Channel is not allowed ++ CHAN_DISABLED = BIT(1), ++ /// Radar detection required on this channel ++ CHAN_RADAR = BIT(2), ++}; ++ ++/// Primary Channel definition ++struct mac_chan_def { ++ /// Frequency of the channel (in MHz) ++ u16_l freq; ++ /// RF band (@ref mac_chan_band) ++ u8_l band; ++ /// Additional information (@ref mac_chan_flags) ++ u8_l flags; ++ /// Max transmit power allowed on this channel (dBm) ++ s8_l tx_power; ++}; ++ ++/// Operating Channel ++struct mac_chan_op { ++ /// Band (@ref mac_chan_band) ++ u8_l band; ++ /// Channel type (@ref mac_chan_bandwidth) ++ u8_l type; ++ /// Frequency for Primary 20MHz channel (in MHz) ++ u16_l prim20_freq; ++ /// Frequency center of the contiguous channel or center of Primary 80+80 (in MHz) ++ u16_l center1_freq; ++ /// Frequency center of the non-contiguous secondary 80+80 (in MHz) ++ u16_l center2_freq; ++ /// Max transmit power allowed on this channel (dBm) ++ s8_l tx_power; ++ /// Additional information (@ref mac_chan_flags) ++ u8_l flags; ++}; ++ ++/// Cipher suites (order is important as it is used by MACHW) ++enum mac_cipher_suite { ++ /// 00-0F-AC 1 ++ MAC_CIPHER_WEP40 = 0, ++ /// 00-0F-AC 2 ++ MAC_CIPHER_TKIP = 1, ++ /// 00-0F-AC 4 ++ MAC_CIPHER_CCMP = 2, ++ /// 00-0F-AC 5 ++ MAC_CIPHER_WEP104 = 3, ++ /// 00-14-72 1 ++ MAC_CIPHER_WPI_SMS4 = 4, ++ /// 00-0F-AC 6 (aka AES_CMAC) ++ MAC_CIPHER_BIP_CMAC_128 = 5, ++ ++ // following cipher are not supported by MACHW ++ /// 00-0F-AC 08 ++ MAC_CIPHER_GCMP_128, ++ /// 00-0F-AC 09 ++ MAC_CIPHER_GCMP_256, ++ /// 00-0F-AC 10 ++ MAC_CIPHER_CCMP_256, ++ /// 00-0F-AC 11 ++ MAC_CIPHER_BIP_GMAC_128, ++ /// 00-0F-AC 12 ++ MAC_CIPHER_BIP_GMAC_256, ++ /// 00-0F-AC 13 ++ MAC_CIPHER_BIP_CMAC_256, ++ ++ MAC_CIPHER_INVALID = 0xFF ++}; ++ ++/// Authentication and Key Management suite ++enum mac_akm_suite { ++ /// No security ++ MAC_AKM_NONE, ++ /// Pre RSN (WEP or WPA) ++ MAC_AKM_PRE_RSN, ++ /// 00-0F-AC 1 ++ MAC_AKM_8021X, ++ /// 00-0F-AC 2 ++ MAC_AKM_PSK, ++ /// 00-0F-AC 3 ++ MAC_AKM_FT_8021X, ++ /// 00-0F-AC 4 ++ MAC_AKM_FT_PSK, ++ /// 00-0F-AC 5 ++ MAC_AKM_8021X_SHA256, ++ /// 00-0F-AC 6 ++ MAC_AKM_PSK_SHA256, ++ /// 00-0F-AC 7 ++ MAC_AKM_TDLS, ++ /// 00-0F-AC 8 ++ MAC_AKM_SAE, ++ /// 00-0F-AC 9 ++ MAC_AKM_FT_OVER_SAE, ++ /// 00-0F-AC 11 ++ MAC_AKM_8021X_SUITE_B, ++ /// 00-0F-AC 12 ++ MAC_AKM_8021X_SUITE_B_192, ++ /// 00-0F-AC 14 ++ MAC_AKM_FILS_SHA256, ++ /// 00-0F-AC 15 ++ MAC_AKM_FILS_SHA384, ++ /// 00-0F-AC 16 ++ MAC_AKM_FT_FILS_SHA256, ++ /// 00-0F-AC 17 ++ MAC_AKM_FT_FILS_SHA384, ++ /// 00-0F-AC 18 ++ MAC_AKM_OWE, ++ ++ /// 00-14-72 1 ++ MAC_AKM_WAPI_CERT, ++ /// 00-14-72 2 ++ MAC_AKM_WAPI_PSK, ++}; ++ ++/// Scan result element, parsed from beacon or probe response frames. ++struct mac_scan_result { ++ /// Scan result is valid ++ bool valid_flag; ++ /// Network BSSID. ++ struct mac_addr bssid; ++ /// Network name. ++ struct mac_ssid ssid; ++ /// Network type (@ref mac_bss_type). ++ u16_l bsstype; ++ /// Network channel. ++ struct mac_chan_def *chan; ++ /// Network beacon period (in TU). ++ u16_l beacon_period; ++ /// Capability information ++ u16_l cap_info; ++ /// Supported AKM (bit-field of @ref mac_akm_suite) ++ u32_l akm; ++ /// Group cipher (bit-field of @ref mac_cipher_suite) ++ u16_l group_cipher; ++ /// Group cipher (bit-field of @ref mac_cipher_suite) ++ u16_l pairwise_cipher; ++ /// RSSI of the scanned BSS (in dBm) ++ s8_l rssi; ++}; ++ ++/// Legacy rate 802.11 definitions ++enum mac_legacy_rates { ++ /// DSSS/CCK 1Mbps ++ MAC_RATE_1MBPS = 2, ++ /// DSSS/CCK 2Mbps ++ MAC_RATE_2MBPS = 4, ++ /// DSSS/CCK 5.5Mbps ++ MAC_RATE_5_5MBPS = 11, ++ /// OFDM 6Mbps ++ MAC_RATE_6MBPS = 12, ++ /// OFDM 9Mbps ++ MAC_RATE_9MBPS = 18, ++ /// DSSS/CCK 11Mbps ++ MAC_RATE_11MBPS = 22, ++ /// OFDM 12Mbps ++ MAC_RATE_12MBPS = 24, ++ /// OFDM 18Mbps ++ MAC_RATE_18MBPS = 36, ++ /// OFDM 24Mbps ++ MAC_RATE_24MBPS = 48, ++ /// OFDM 36Mbps ++ MAC_RATE_36MBPS = 72, ++ /// OFDM 48Mbps ++ MAC_RATE_48MBPS = 96, ++ /// OFDM 54Mbps ++ MAC_RATE_54MBPS = 108 ++}; ++ ++/// BSS Membership Selector definitions ++enum mac_bss_membership { ++ /// HT PHY ++ MAC_BSS_MEMBERSHIP_HT_PHY = 127, ++ /// VHT PHY ++ MAC_BSS_MEMBERSHIP_VHT_PHY = 126, ++}; ++ ++/// MAC rateset maximum length ++#define MAC_RATESET_LEN 12 ++ ++/// Structure containing the legacy rateset of a station ++struct mac_rateset { ++ /// Number of legacy rates supported ++ u8_l length; ++ /// Array of legacy rates ++ u8_l array[MAC_RATESET_LEN]; ++}; ++ ++/// MAC Security Key maximum length ++#define MAC_SEC_KEY_LEN 32 // TKIP keys 256 bits (max length) with MIC keys ++ ++/// Structure defining a security key ++struct mac_sec_key { ++ /// Key material length ++ u8_l length; ++ /// Key material ++ u32_l array[MAC_SEC_KEY_LEN/4]; ++}; ++ ++/// Access Category enumeration ++enum mac_ac { ++ /// Background ++ AC_BK = 0, ++ /// Best-effort ++ AC_BE, ++ /// Video ++ AC_VI, ++ /// Voice ++ AC_VO, ++ /// Number of access categories ++ AC_MAX ++}; ++ ++/// Traffic ID enumeration ++enum mac_tid { ++ /// TID_0. Mapped to @ref AC_BE as per 802.11 standard. ++ TID_0, ++ /// TID_1. Mapped to @ref AC_BK as per 802.11 standard. ++ TID_1, ++ /// TID_2. Mapped to @ref AC_BK as per 802.11 standard. ++ TID_2, ++ /// TID_3. Mapped to @ref AC_BE as per 802.11 standard. ++ TID_3, ++ /// TID_4. Mapped to @ref AC_VI as per 802.11 standard. ++ TID_4, ++ /// TID_5. Mapped to @ref AC_VI as per 802.11 standard. ++ TID_5, ++ /// TID_6. Mapped to @ref AC_VO as per 802.11 standard. ++ TID_6, ++ /// TID_7. Mapped to @ref AC_VO as per 802.11 standard. ++ TID_7, ++ /// Non standard Management TID used internally ++ TID_MGT, ++ /// Number of TID supported ++ TID_MAX ++}; ++ ++/// MCS bitfield maximum size (in bytes) ++#define MAX_MCS_LEN 16 // 16 * 8 = 128 ++ ++/// MAC HT capability information element ++struct mac_htcapability { ++ /// HT capability information ++ u16_l ht_capa_info; ++ /// A-MPDU parameters ++ u8_l a_mpdu_param; ++ /// Supported MCS ++ u8_l mcs_rate[MAX_MCS_LEN]; ++ /// HT extended capability information ++ u16_l ht_extended_capa; ++ /// Beamforming capability information ++ u32_l tx_beamforming_capa; ++ /// Antenna selection capability information ++ u8_l asel_capa; ++}; ++ ++/// MAC VHT capability information element ++struct mac_vhtcapability { ++ /// VHT capability information ++ u32_l vht_capa_info; ++ /// RX MCS map ++ u16_l rx_mcs_map; ++ /// RX highest data rate ++ u16_l rx_highest; ++ /// TX MCS map ++ u16_l tx_mcs_map; ++ /// TX highest data rate ++ u16_l tx_highest; ++}; ++ ++/// Length (in bytes) of the MAC HE capability field ++#define MAC_HE_MAC_CAPA_LEN 6 ++/// Length (in bytes) of the PHY HE capability field ++#define MAC_HE_PHY_CAPA_LEN 11 ++/// Maximum length (in bytes) of the PPE threshold data ++#define MAC_HE_PPE_THRES_MAX_LEN 25 ++ ++/// Structure listing the per-NSS, per-BW supported MCS combinations ++struct mac_he_mcs_nss_supp { ++ /// per-NSS supported MCS in RX, for BW <= 80MHz ++ u16_l rx_mcs_80; ++ /// per-NSS supported MCS in TX, for BW <= 80MHz ++ u16_l tx_mcs_80; ++ /// per-NSS supported MCS in RX, for BW = 160MHz ++ u16_l rx_mcs_160; ++ /// per-NSS supported MCS in TX, for BW = 160MHz ++ u16_l tx_mcs_160; ++ /// per-NSS supported MCS in RX, for BW = 80+80MHz ++ u16_l rx_mcs_80p80; ++ /// per-NSS supported MCS in TX, for BW = 80+80MHz ++ u16_l tx_mcs_80p80; ++}; ++ ++/// MAC HE capability information element ++struct mac_hecapability { ++ /// MAC HE capabilities ++ u8_l mac_cap_info[MAC_HE_MAC_CAPA_LEN]; ++ /// PHY HE capabilities ++ u8_l phy_cap_info[MAC_HE_PHY_CAPA_LEN]; ++ /// Supported MCS combinations ++ struct mac_he_mcs_nss_supp mcs_supp; ++ /// PPE Thresholds data ++ u8_l ppe_thres[MAC_HE_PPE_THRES_MAX_LEN]; ++}; ++ ++/// Station flags ++enum mac_sta_flags { ++ /// Bit indicating that a STA has QoS (WMM) capability ++ STA_QOS_CAPA = BIT(0), ++ /// Bit indicating that a STA has HT capability ++ STA_HT_CAPA = BIT(1), ++ /// Bit indicating that a STA has VHT capability ++ STA_VHT_CAPA = BIT(2), ++ /// Bit indicating that a STA has MFP capability ++ STA_MFP_CAPA = BIT(3), ++ /// Bit indicating that the STA included the Operation Notification IE ++ STA_OPMOD_NOTIF = BIT(4), ++ /// Bit indicating that a STA has HE capability ++ STA_HE_CAPA = BIT(5), ++}; ++ ++/// Connection flags ++enum mac_connection_flags { ++ /// Flag indicating whether the control port is controlled by host or not ++ CONTROL_PORT_HOST = BIT(0), ++ /// Flag indicating whether the control port frame shall be sent unencrypted ++ CONTROL_PORT_NO_ENC = BIT(1), ++ /// Flag indicating whether HT and VHT shall be disabled or not ++ DISABLE_HT = BIT(2), ++ /// Flag indicating whether WPA or WPA2 authentication is in use ++ WPA_WPA2_IN_USE = BIT(3), ++ /// Flag indicating whether MFP is in use ++ MFP_IN_USE = BIT(4), ++ // Flag indicating Roam ++ REASSOCIATION = BIT(5), ++}; ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++#define IEEE80211_HE_MAC_CAP2_ALL_ACK 0x02 ++#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02 ++#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04 ++#define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD 0x20 ++#define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US 0x40 ++#define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS 0x80 ++#define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS 0x01 ++#define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US 0x02 ++#define IEEE80211_HE_PHY_CAP2_DOPPLER_RX 0x20 ++#define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ 0x08 ++#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM 0x18 ++#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 0x00 ++#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA 0x40 ++#define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE 0x01 ++#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 0x0c ++#define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK 0x40 ++#define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK 0x80 ++#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU 0x01 ++#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU 0x02 ++#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB 0x04 ++#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB 0x08 ++#define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT 0x80 ++#define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO 0x40 ++#define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI 0x04 ++#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G 0x02 ++#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB 0x10 ++#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB 0x20 ++ ++#define IEEE80211_HE_PPE_THRES_MAX_LEN 25 ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) ++#define WLAN_EID_EXTENSION 255 ++/* Element ID Extensions for Element ID 255 */ ++ ++enum ieee80211_eid_ext { ++ WLAN_EID_EXT_ASSOC_DELAY_INFO = 1, ++ WLAN_EID_EXT_FILS_REQ_PARAMS = 2, ++ WLAN_EID_EXT_FILS_KEY_CONFIRM = 3, ++ WLAN_EID_EXT_FILS_SESSION = 4, ++ WLAN_EID_EXT_FILS_HLP_CONTAINER = 5, ++ WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN = 6, ++ WLAN_EID_EXT_KEY_DELIVERY = 7, ++ WLAN_EID_EXT_FILS_WRAPPED_DATA = 8, ++ WLAN_EID_EXT_FILS_PUBLIC_KEY = 12, ++ WLAN_EID_EXT_FILS_NONCE = 13, ++ WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE = 14, ++ ++}; ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define WLAN_EID_EXT_HE_CAPABILITY 35 ++#define WLAN_EID_EXT_HE_OPERATION 36 ++#define WLAN_EID_EXT_UORA 37 ++#define WLAN_EID_EXT_HE_MU_EDCA 38 ++#define WLAN_EID_EXT_HE_SPR 39 ++#define WLAN_EID_EXT_NDP_FEEDBACK_REPORT_PARAMSET 41 ++#define WLAN_EID_EXT_BSS_COLOR_CHG_ANN 42 ++#define WLAN_EID_EXT_QUIET_TIME_PERIOD_SETUP 43 ++#define WLAN_EID_EXT_ESS_REPORT 45 ++#define WLAN_EID_EXT_OPS 46 ++#define WLAN_EID_EXT_HE_BSS_LOAD 47 ++#define WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME 52 ++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55 ++#define WLAN_EID_EXT_NON_INHERITANCE 56 ++#define WLAN_EID_EXT_KNOWN_BSSID 57 ++#define WLAN_EID_EXT_SHORT_SSID_LIST 58 ++#define WLAN_EID_EXT_HE_6GHZ_CAPA 59 ++#define WLAN_EID_EXT_UL_MU_POWER_CAPA 60 ++#define WLAN_EID_EXT_EHT_OPERATION 106 ++#define WLAN_EID_EXT_EHT_MULTI_LINK 107 ++#define WLAN_EID_EXT_EHT_CAPABILITY 108 ++#endif ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++#include ++#else ++struct ieee80211_he_cap_elem { ++ u8 mac_cap_info[6]; ++ u8 phy_cap_info[11]; ++} __packed; ++ ++struct ieee80211_he_mcs_nss_supp { ++ __le16 rx_mcs_80; ++ __le16 tx_mcs_80; ++ __le16 rx_mcs_160; ++ __le16 tx_mcs_160; ++ __le16 rx_mcs_80p80; ++ __le16 tx_mcs_80p80; ++} __packed; ++ ++struct ieee80211_sta_he_cap { ++ bool has_he; ++ struct ieee80211_he_cap_elem he_cap_elem; ++ struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; ++ u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; ++}; ++ ++struct ieee80211_sband_iftype_data { ++ u16 types_mask; ++ struct ieee80211_sta_he_cap he_cap; ++}; ++#endif ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++struct ieee80211_vht_mcs_info { ++ __le16 rx_mcs_map; ++ __le16 rx_highest; ++ __le16 tx_mcs_map; ++ __le16 tx_highest; ++} __packed; ++ ++struct ieee80211_vht_cap { ++ __le32 vht_cap_info; ++ struct ieee80211_vht_mcs_info supp_mcs; ++}; ++#define WLAN_EID_VHT_CAPABILITY 191 ++ ++struct ieee80211_sta_vht_cap { ++ bool vht_supported; ++ u32 cap; /* use IEEE80211_VHT_CAP_ */ ++ struct ieee80211_vht_mcs_info vht_mcs; ++}; ++#endif ++#endif // LMAC_MAC_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h +new file mode 100644 +index 000000000000..96f492bba754 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h +@@ -0,0 +1,3224 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file lmac_msg.h ++ * ++ * @brief Main definitions for message exchanges with LMAC ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef LMAC_MSG_H_ ++#define LMAC_MSG_H_ ++ ++/* ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++// for MAC related elements (mac_addr, mac_ssid...) ++#include "lmac_mac.h" ++ ++#define LMAC_MSG_MAX_LEN 1024 ++ ++/* ++ **************************************************************************************** ++ */ ++///////////////////////////////////////////////////////////////////////////////// ++// COMMUNICATION WITH LMAC LAYER ++///////////////////////////////////////////////////////////////////////////////// ++/* Task identifiers for communication between LMAC and DRIVER */ ++enum { ++ TASK_NONE = (u8_l) -1, ++ ++ // MAC Management task. ++ TASK_MM = 0, ++ // DEBUG task ++ TASK_DBG, ++ /// SCAN task ++ TASK_SCAN, ++ /// TDLS task ++ TASK_TDLS, ++ /// SCANU task ++ TASK_SCANU, ++ /// ME task ++ TASK_ME, ++ /// SM task ++ TASK_SM, ++ /// APM task ++ TASK_APM, ++ /// BAM task ++ TASK_BAM, ++ /// MESH task ++ TASK_MESH, ++ /// RXU task ++ TASK_RXU, ++ /// RM_task ++ TASK_RM, ++ /// TWT task ++ TASK_TWT, ++#if defined CONFIG_RWNX_FULLMAC || defined CONFIG_RWNX_FHOST ++ // This is used to define the last task that is running on the EMB processor ++ TASK_LAST_EMB = TASK_TWT, ++#else ++#error "Need to define SOFTMAC or FULLMAC" ++#endif ++ // nX API task ++ TASK_API, ++ TASK_MAX, ++}; ++ ++ ++/// For MAC HW States copied from "hal_machw.h" ++enum { ++ /// MAC HW IDLE State. ++ HW_IDLE = 0, ++ /// MAC HW RESERVED State. ++ HW_RESERVED, ++ /// MAC HW DOZE State. ++ HW_DOZE, ++ /// MAC HW ACTIVE State. ++ HW_ACTIVE ++}; ++ ++/// Power Save mode setting ++enum mm_ps_mode_state { ++ MM_PS_MODE_OFF, ++ MM_PS_MODE_ON, ++ MM_PS_MODE_ON_DYN, ++}; ++ ++/// Status/error codes used in the MAC software. ++enum { ++ CO_OK, ++ CO_FAIL, ++ CO_EMPTY, ++ CO_FULL, ++ CO_BAD_PARAM, ++ CO_NOT_FOUND, ++ CO_NO_MORE_ELT_AVAILABLE, ++ CO_NO_ELT_IN_USE, ++ CO_BUSY, ++ CO_OP_IN_PROGRESS, ++}; ++ ++/// Remain on channel operation codes ++enum mm_remain_on_channel_op { ++ MM_ROC_OP_START = 0, ++ MM_ROC_OP_CANCEL, ++}; ++ ++#define DRV_TASK_ID 100 ++ ++/// Message Identifier. The number of messages is limited to 0xFFFF. ++/// The message ID is divided in two parts: ++/// - bits[15..10] : task index (no more than 64 tasks supported). ++/// - bits[9..0] : message index (no more that 1024 messages per task). ++typedef u16 lmac_msg_id_t; ++ ++typedef u16 lmac_task_id_t; ++ ++/// Build the first message ID of a task. ++#define LMAC_FIRST_MSG(task) ((lmac_msg_id_t)((task) << 10)) ++ ++#define MSG_T(msg) ((lmac_task_id_t)((msg) >> 10)) ++#define MSG_I(msg) ((msg) & ((1<<10)-1)) ++ ++/// Message structure. ++struct lmac_msg { ++ lmac_msg_id_t id; ///< Message id. ++ lmac_task_id_t dest_id; ///< Destination kernel identifier. ++ lmac_task_id_t src_id; ///< Source kernel identifier. ++ u16 param_len; ///< Parameter embedded struct length. ++ u32 param[]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++/// List of messages related to the task. ++enum mm_msg_tag { ++ /// RESET Request. ++ MM_RESET_REQ = LMAC_FIRST_MSG(TASK_MM), ++ /// RESET Confirmation. ++ MM_RESET_CFM, ++ /// START Request. ++ MM_START_REQ, ++ /// START Confirmation. ++ MM_START_CFM, ++ /// Read Version Request. ++ MM_VERSION_REQ, ++ /// Read Version Confirmation. ++ MM_VERSION_CFM, ++ /// ADD INTERFACE Request. ++ MM_ADD_IF_REQ, ++ /// ADD INTERFACE Confirmation. ++ MM_ADD_IF_CFM, ++ /// REMOVE INTERFACE Request. ++ MM_REMOVE_IF_REQ, ++ /// REMOVE INTERFACE Confirmation. ++ MM_REMOVE_IF_CFM, ++ /// STA ADD Request. ++ MM_STA_ADD_REQ, ++ /// STA ADD Confirm. ++ MM_STA_ADD_CFM, ++ /// STA DEL Request. ++ MM_STA_DEL_REQ, ++ /// STA DEL Confirm. ++ MM_STA_DEL_CFM, ++ /// RX FILTER CONFIGURATION Request. ++ MM_SET_FILTER_REQ, ++ /// RX FILTER CONFIGURATION Confirmation. ++ MM_SET_FILTER_CFM, ++ /// CHANNEL CONFIGURATION Request. ++ MM_SET_CHANNEL_REQ, ++ /// CHANNEL CONFIGURATION Confirmation. ++ MM_SET_CHANNEL_CFM, ++ /// DTIM PERIOD CONFIGURATION Request. ++ MM_SET_DTIM_REQ, ++ /// DTIM PERIOD CONFIGURATION Confirmation. ++ MM_SET_DTIM_CFM, ++ /// BEACON INTERVAL CONFIGURATION Request. ++ MM_SET_BEACON_INT_REQ, ++ /// BEACON INTERVAL CONFIGURATION Confirmation. ++ MM_SET_BEACON_INT_CFM, ++ /// BASIC RATES CONFIGURATION Request. ++ MM_SET_BASIC_RATES_REQ, ++ /// BASIC RATES CONFIGURATION Confirmation. ++ MM_SET_BASIC_RATES_CFM, ++ /// BSSID CONFIGURATION Request. ++ MM_SET_BSSID_REQ, ++ /// BSSID CONFIGURATION Confirmation. ++ MM_SET_BSSID_CFM, ++ /// EDCA PARAMETERS CONFIGURATION Request. ++ MM_SET_EDCA_REQ, ++ /// EDCA PARAMETERS CONFIGURATION Confirmation. ++ MM_SET_EDCA_CFM, ++ /// ABGN MODE CONFIGURATION Request. ++ MM_SET_MODE_REQ, ++ /// ABGN MODE CONFIGURATION Confirmation. ++ MM_SET_MODE_CFM, ++ /// Request setting the VIF active state (i.e associated or AP started) ++ MM_SET_VIF_STATE_REQ, ++ /// Confirmation of the @ref MM_SET_VIF_STATE_REQ message. ++ MM_SET_VIF_STATE_CFM, ++ /// SLOT TIME PARAMETERS CONFIGURATION Request. ++ MM_SET_SLOTTIME_REQ, ++ /// SLOT TIME PARAMETERS CONFIGURATION Confirmation. ++ MM_SET_SLOTTIME_CFM, ++ /// Power Mode Change Request. ++ MM_SET_IDLE_REQ, ++ /// Power Mode Change Confirm. ++ MM_SET_IDLE_CFM, ++ /// KEY ADD Request. ++ MM_KEY_ADD_REQ, ++ /// KEY ADD Confirm. ++ MM_KEY_ADD_CFM, ++ /// KEY DEL Request. ++ MM_KEY_DEL_REQ, ++ /// KEY DEL Confirm. ++ MM_KEY_DEL_CFM, ++ /// Block Ack agreement info addition ++ MM_BA_ADD_REQ, ++ /// Block Ack agreement info addition confirmation ++ MM_BA_ADD_CFM, ++ /// Block Ack agreement info deletion ++ MM_BA_DEL_REQ, ++ /// Block Ack agreement info deletion confirmation ++ MM_BA_DEL_CFM, ++ /// Indication of the primary TBTT to the upper MAC. Upon the reception of this ++ // message the upper MAC has to push the beacon(s) to the beacon transmission queue. ++ MM_PRIMARY_TBTT_IND, ++ /// Indication of the secondary TBTT to the upper MAC. Upon the reception of this ++ // message the upper MAC has to push the beacon(s) to the beacon transmission queue. ++ MM_SECONDARY_TBTT_IND, ++ /// Request for changing the TX power ++ MM_SET_POWER_REQ, ++ /// Confirmation of the TX power change ++ MM_SET_POWER_CFM, ++ /// Request to the LMAC to trigger the embedded logic analyzer and forward the debug ++ /// dump. ++ MM_DBG_TRIGGER_REQ, ++ /// Set Power Save mode ++ MM_SET_PS_MODE_REQ, ++ /// Set Power Save mode confirmation ++ MM_SET_PS_MODE_CFM, ++ /// Request to add a channel context ++ MM_CHAN_CTXT_ADD_REQ, ++ /// Confirmation of the channel context addition ++ MM_CHAN_CTXT_ADD_CFM, ++ /// Request to delete a channel context ++ MM_CHAN_CTXT_DEL_REQ, ++ /// Confirmation of the channel context deletion ++ MM_CHAN_CTXT_DEL_CFM, ++ /// Request to link a channel context to a VIF ++ MM_CHAN_CTXT_LINK_REQ, ++ /// Confirmation of the channel context link ++ MM_CHAN_CTXT_LINK_CFM, ++ /// Request to unlink a channel context from a VIF ++ MM_CHAN_CTXT_UNLINK_REQ, ++ /// Confirmation of the channel context unlink ++ MM_CHAN_CTXT_UNLINK_CFM, ++ /// Request to update a channel context ++ MM_CHAN_CTXT_UPDATE_REQ, ++ /// Confirmation of the channel context update ++ MM_CHAN_CTXT_UPDATE_CFM, ++ /// Request to schedule a channel context ++ MM_CHAN_CTXT_SCHED_REQ, ++ /// Confirmation of the channel context scheduling ++ MM_CHAN_CTXT_SCHED_CFM, ++ /// Request to change the beacon template in LMAC ++ MM_BCN_CHANGE_REQ, ++ /// Confirmation of the beacon change ++ MM_BCN_CHANGE_CFM, ++ /// Request to update the TIM in the beacon (i.e to indicate traffic bufferized at AP) ++ MM_TIM_UPDATE_REQ, ++ /// Confirmation of the TIM update ++ MM_TIM_UPDATE_CFM, ++ /// Connection loss indication ++ MM_CONNECTION_LOSS_IND, ++ /// Channel context switch indication to the upper layers ++ MM_CHANNEL_SWITCH_IND, ++ /// Channel context pre-switch indication to the upper layers ++ MM_CHANNEL_PRE_SWITCH_IND, ++ /// Request to remain on channel or cancel remain on channel ++ MM_REMAIN_ON_CHANNEL_REQ, ++ /// Confirmation of the (cancel) remain on channel request ++ MM_REMAIN_ON_CHANNEL_CFM, ++ /// Remain on channel expired indication ++ MM_REMAIN_ON_CHANNEL_EXP_IND, ++ /// Indication of a PS state change of a peer device ++ MM_PS_CHANGE_IND, ++ /// Indication that some buffered traffic should be sent to the peer device ++ MM_TRAFFIC_REQ_IND, ++ /// Request to modify the STA Power-save mode options ++ MM_SET_PS_OPTIONS_REQ, ++ /// Confirmation of the PS options setting ++ MM_SET_PS_OPTIONS_CFM, ++ /// Indication of PS state change for a P2P VIF ++ MM_P2P_VIF_PS_CHANGE_IND, ++ /// Indication that CSA counter has been updated ++ MM_CSA_COUNTER_IND, ++ /// Channel occupation report indication ++ MM_CHANNEL_SURVEY_IND, ++ /// Message containing Beamformer Information ++ MM_BFMER_ENABLE_REQ, ++ /// Request to Start/Stop/Update NOA - GO Only ++ MM_SET_P2P_NOA_REQ, ++ /// Request to Start/Stop/Update Opportunistic PS - GO Only ++ MM_SET_P2P_OPPPS_REQ, ++ /// Start/Stop/Update NOA Confirmation ++ MM_SET_P2P_NOA_CFM, ++ /// Start/Stop/Update Opportunistic PS Confirmation ++ MM_SET_P2P_OPPPS_CFM, ++ /// P2P NoA Update Indication - GO Only ++ MM_P2P_NOA_UPD_IND, ++ /// Request to set RSSI threshold and RSSI hysteresis ++ MM_CFG_RSSI_REQ, ++ /// Indication that RSSI level is below or above the threshold ++ MM_RSSI_STATUS_IND, ++ /// Indication that CSA is done ++ MM_CSA_FINISH_IND, ++ /// Indication that CSA is in prorgess (resp. done) and traffic must be stopped (resp. restarted) ++ MM_CSA_TRAFFIC_IND, ++ /// Request to update the group information of a station ++ MM_MU_GROUP_UPDATE_REQ, ++ /// Confirmation of the @ref MM_MU_GROUP_UPDATE_REQ message ++ MM_MU_GROUP_UPDATE_CFM, ++ /// Request to initialize the antenna diversity algorithm ++ MM_ANT_DIV_INIT_REQ, ++ /// Request to stop the antenna diversity algorithm ++ MM_ANT_DIV_STOP_REQ, ++ /// Request to update the antenna switch status ++ MM_ANT_DIV_UPDATE_REQ, ++ /// Request to switch the antenna connected to path_0 ++ MM_SWITCH_ANTENNA_REQ, ++ /// Indication that a packet loss has occurred ++ MM_PKTLOSS_IND, ++ ++ MM_SET_ARPOFFLOAD_REQ, ++ MM_SET_ARPOFFLOAD_CFM, ++ MM_SET_AGG_DISABLE_REQ, ++ MM_SET_AGG_DISABLE_CFM, ++ MM_SET_COEX_REQ, ++ MM_SET_COEX_CFM, ++ MM_SET_RF_CONFIG_REQ, ++ MM_SET_RF_CONFIG_CFM, ++ MM_SET_RF_CALIB_REQ, ++ MM_SET_RF_CALIB_CFM, ++ ++ /// MU EDCA PARAMETERS Configuration Request. ++ MM_SET_MU_EDCA_REQ, ++ /// MU EDCA PARAMETERS Configuration Confirmation. ++ MM_SET_MU_EDCA_CFM, ++ /// UORA PARAMETERS Configuration Request. ++ MM_SET_UORA_REQ, ++ /// UORA PARAMETERS Configuration Confirmation. ++ MM_SET_UORA_CFM, ++ /// TXOP RTS THRESHOLD Configuration Request. ++ MM_SET_TXOP_RTS_THRES_REQ, ++ /// TXOP RTS THRESHOLD Configuration Confirmation. ++ MM_SET_TXOP_RTS_THRES_CFM, ++ /// HE BSS Color Configuration Request. ++ MM_SET_BSS_COLOR_REQ, ++ /// HE BSS Color Configuration Confirmation. ++ MM_SET_BSS_COLOR_CFM, ++ ++ MM_GET_MAC_ADDR_REQ, ++ MM_GET_MAC_ADDR_CFM, ++ ++ MM_GET_STA_INFO_REQ, ++ MM_GET_STA_INFO_CFM, ++ ++ MM_SET_TXPWR_IDX_LVL_REQ, ++ MM_SET_TXPWR_IDX_LVL_CFM, ++ ++ MM_SET_TXPWR_OFST_REQ, ++ MM_SET_TXPWR_OFST_CFM, ++ ++ MM_SET_STACK_START_REQ, ++ MM_SET_STACK_START_CFM, ++ ++ MM_APM_STALOSS_IND, ++ ++ MM_SET_VENDOR_HWCONFIG_REQ, ++ MM_SET_VENDOR_HWCONFIG_CFM, ++ ++ MM_GET_FW_VERSION_REQ, ++ MM_GET_FW_VERSION_CFM, ++ ++ MM_SET_RESUME_RESTORE_REQ, ++ MM_SET_RESUME_RESTORE_CFM, ++ ++ MM_GET_WIFI_DISABLE_REQ, ++ MM_GET_WIFI_DISABLE_CFM, ++ ++ MM_CFG_RSSI_CFM, ++ ++ MM_SET_VENDOR_SWCONFIG_REQ, ++ MM_SET_VENDOR_SWCONFIG_CFM, ++ ++ MM_SET_TXPWR_LVL_ADJ_REQ, ++ MM_SET_TXPWR_LVL_ADJ_CFM, ++ ++ MM_RADAR_DETECT_IND, ++ ++ MM_SET_APF_PROG_REQ, ++ MM_SET_APF_PROG_CFM, ++ ++ MM_GET_APF_PROG_REQ, ++ MM_GET_APF_PROG_CFM, ++ ++ /// MAX number of messages ++ MM_MAX, ++}; ++ ++/// Interface types ++enum { ++ /// ESS STA interface ++ MM_STA, ++ /// IBSS STA interface ++ MM_IBSS, ++ /// AP interface ++ MM_AP, ++ // Mesh Point interface ++ MM_MESH_POINT, ++ // Monitor interface ++ MM_MONITOR, ++}; ++ ++///BA agreement types ++enum { ++ ///BlockAck agreement for TX ++ BA_AGMT_TX, ++ ///BlockAck agreement for RX ++ BA_AGMT_RX, ++}; ++ ++///BA agreement related status ++enum { ++ ///Correct BA agreement establishment ++ BA_AGMT_ESTABLISHED, ++ ///BA agreement already exists for STA+TID requested, cannot override it (should have been deleted first) ++ BA_AGMT_ALREADY_EXISTS, ++ ///Correct BA agreement deletion ++ BA_AGMT_DELETED, ++ ///BA agreement for the (STA, TID) doesn't exist so nothing to delete ++ BA_AGMT_DOESNT_EXIST, ++}; ++ ++/// Features supported by LMAC - Positions ++enum mm_features { ++ /// Beaconing ++ MM_FEAT_BCN_BIT = 0, ++/* ++ /// Autonomous Beacon Transmission ++ MM_FEAT_AUTOBCN_BIT, ++ /// Scan in LMAC ++ MM_FEAT_HWSCAN_BIT, ++ /// Connection Monitoring ++ MM_FEAT_CMON_BIT, ++ /// Multi Role ++ MM_FEAT_MROLE_BIT, ++*/ ++ /// Radar Detection ++ MM_FEAT_RADAR_BIT, ++ /// Power Save ++ MM_FEAT_PS_BIT, ++ /// UAPSD ++ MM_FEAT_UAPSD_BIT, ++ /// DPSM ++// MM_FEAT_DPSM_BIT, ++ /// A-MPDU ++ MM_FEAT_AMPDU_BIT, ++ /// A-MSDU ++ MM_FEAT_AMSDU_BIT, ++ /// Channel Context ++// MM_FEAT_CHNL_CTXT_BIT, ++ /// Packet reordering ++// MM_FEAT_REORD_BIT, ++ /// P2P ++ MM_FEAT_P2P_BIT, ++ /// P2P Go ++ MM_FEAT_P2P_GO_BIT, ++ /// UMAC Present ++ MM_FEAT_UMAC_BIT, ++ /// VHT support ++ MM_FEAT_VHT_BIT, ++ /// Beamformee ++ MM_FEAT_BFMEE_BIT, ++ /// Beamformer ++ MM_FEAT_BFMER_BIT, ++ /// WAPI ++ MM_FEAT_WAPI_BIT, ++ /// MFP ++ MM_FEAT_MFP_BIT, ++ /// Mu-MIMO RX support ++ MM_FEAT_MU_MIMO_RX_BIT, ++ /// Mu-MIMO TX support ++ MM_FEAT_MU_MIMO_TX_BIT, ++ /// Wireless Mesh Networking ++ MM_FEAT_MESH_BIT, ++ /// TDLS support ++ MM_FEAT_TDLS_BIT, ++ /// Antenna Diversity support ++ MM_FEAT_ANT_DIV_BIT, ++ /// UF support ++ MM_FEAT_UF_BIT, ++ /// A-MSDU maximum size (bit0) ++ MM_AMSDU_MAX_SIZE_BIT0, ++ /// A-MSDU maximum size (bit1) ++ MM_AMSDU_MAX_SIZE_BIT1, ++ /// MON_DATA support ++ MM_FEAT_MON_DATA_BIT, ++ /// HE (802.11ax) support ++ MM_FEAT_HE_BIT, ++ /// TWT support ++ MM_FEAT_TWT_BIT, ++}; ++ ++/// Maximum number of words in the configuration buffer ++#define PHY_CFG_BUF_SIZE 16 ++ ++/// Structure containing the parameters of the PHY configuration ++struct phy_cfg_tag { ++ /// Buffer containing the parameters specific for the PHY used ++ u32_l parameters[PHY_CFG_BUF_SIZE]; ++}; ++ ++/// Structure containing the parameters of the Trident PHY configuration ++struct phy_trd_cfg_tag { ++ /// MDM type(nxm)(upper nibble) and MDM2RF path mapping(lower nibble) ++ u8_l path_mapping; ++ /// TX DC offset compensation ++ u32_l tx_dc_off_comp; ++}; ++ ++/// Structure containing the parameters of the Karst PHY configuration ++struct phy_karst_cfg_tag { ++ /// TX IQ mismatch compensation in 2.4GHz ++ u32_l tx_iq_comp_2_4G[2]; ++ /// RX IQ mismatch compensation in 2.4GHz ++ u32_l rx_iq_comp_2_4G[2]; ++ /// TX IQ mismatch compensation in 5GHz ++ u32_l tx_iq_comp_5G[2]; ++ /// RX IQ mismatch compensation in 5GHz ++ u32_l rx_iq_comp_5G[2]; ++ /// RF path used by default (0 or 1) ++ u8_l path_used; ++}; ++ ++/// Structure containing the parameters of the @ref MM_START_REQ message ++struct mm_start_req { ++ /// PHY configuration ++ struct phy_cfg_tag phy_cfg; ++ /// UAPSD timeout ++ u32_l uapsd_timeout; ++ /// Local LP clock accuracy (in ppm) ++ u16_l lp_clk_accuracy; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_CHANNEL_REQ message ++struct mm_set_channel_req { ++ /// Channel information ++ struct mac_chan_op chan; ++ /// Index of the RF for which the channel has to be set (0: operating (primary), 1: secondary ++ /// RF (used for additional radar detection). This parameter is reserved if no secondary RF ++ /// is available in the system ++ u8_l index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_CHANNEL_CFM message ++struct mm_set_channel_cfm { ++ /// Radio index to be used in policy table ++ u8_l radio_idx; ++ /// TX power configured (in dBm) ++ s8_l power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_DTIM_REQ message ++struct mm_set_dtim_req { ++ /// DTIM period ++ u8_l dtim_period; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_POWER_REQ message ++struct mm_set_power_req { ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++ /// TX power (in dBm) ++ s8_l power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_POWER_CFM message ++struct mm_set_power_cfm { ++ /// Radio index to be used in policy table ++ u8_l radio_idx; ++ /// TX power configured (in dBm) ++ s8_l power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BEACON_INT_REQ message ++struct mm_set_beacon_int_req { ++ /// Beacon interval ++ u16_l beacon_int; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BASIC_RATES_REQ message ++struct mm_set_basic_rates_req { ++ /// Basic rate set (as expected by bssBasicRateSet field of Rates MAC HW register) ++ u32_l rates; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++ /// Band on which the interface will operate ++ u8_l band; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BSSID_REQ message ++struct mm_set_bssid_req { ++ /// BSSID to be configured in HW ++ struct mac_addr bssid; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_FILTER_REQ message ++struct mm_set_filter_req { ++ /// RX filter to be put into rxCntrlReg HW register ++ u32_l filter; ++}; ++ ++/// Structure containing the parameters of the @ref MM_ADD_IF_REQ message. ++struct mm_add_if_req { ++ /// Type of the interface (AP, STA, ADHOC, ...) ++ u8_l type; ++ /// MAC ADDR of the interface to start ++ struct mac_addr addr; ++ /// P2P Interface ++ bool_l p2p; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_EDCA_REQ message ++struct mm_set_edca_req { ++ /// EDCA parameters of the queue (as expected by edcaACxReg HW register) ++ u32_l ac_param; ++ /// Flag indicating if UAPSD can be used on this queue ++ bool_l uapsd; ++ /// HW queue for which the parameters are configured ++ u8_l hw_queue; ++ /// Index of the interface for which the parameters are configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_MU_EDCA_REQ message ++struct mm_set_mu_edca_req { ++ /// MU EDCA parameters of the different HE queues ++ u32_l param[AC_MAX]; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_UORA_REQ message ++struct mm_set_uora_req { ++ /// Minimum exponent of OFDMA Contention Window. ++ u8_l eocw_min; ++ /// Maximum exponent of OFDMA Contention Window. ++ u8_l eocw_max; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_TXOP_RTS_THRES_REQ message ++struct mm_set_txop_rts_thres_req { ++ /// TXOP RTS threshold ++ u16_l txop_dur_rts_thres; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BSS_COLOR_REQ message ++struct mm_set_bss_color_req { ++ /// HE BSS color, formatted as per BSS_COLOR MAC HW register ++ u32_l bss_color; ++}; ++ ++struct mm_set_idle_req { ++ u8_l hw_idle; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_SLOTTIME_REQ message ++struct mm_set_slottime_req { ++ /// Slot time expressed in us ++ u8_l slottime; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_MODE_REQ message ++struct mm_set_mode_req { ++ /// abgnMode field of macCntrl1Reg register ++ u8_l abgnmode; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_VIF_STATE_REQ message ++struct mm_set_vif_state_req { ++ /// Association Id received from the AP (valid only if the VIF is of STA type) ++ u16_l aid; ++ /// Flag indicating if the VIF is active or not ++ bool_l active; ++ /// Interface index ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_ADD_IF_CFM message. ++struct mm_add_if_cfm { ++ /// Status of operation (different from 0 if unsuccessful) ++ u8_l status; ++ /// Interface index assigned by the LMAC ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMOVE_IF_REQ message. ++struct mm_remove_if_req { ++ /// Interface index assigned by the LMAC ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_VERSION_CFM message. ++struct mm_version_cfm { ++ /// Version of the LMAC FW ++ u32_l version_lmac; ++ /// Version1 of the MAC HW (as encoded in version1Reg MAC HW register) ++ u32_l version_machw_1; ++ /// Version2 of the MAC HW (as encoded in version2Reg MAC HW register) ++ u32_l version_machw_2; ++ /// Version1 of the PHY (depends on actual PHY) ++ u32_l version_phy_1; ++ /// Version2 of the PHY (depends on actual PHY) ++ u32_l version_phy_2; ++ /// Supported Features ++ u32_l features; ++ /// Maximum number of supported stations ++ u16_l max_sta_nb; ++ /// Maximum number of supported virtual interfaces ++ u8_l max_vif_nb; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_ADD_REQ message. ++struct mm_sta_add_req { ++ /// Bitfield showing some capabilities of the STA (@ref enum mac_sta_flags) ++ u32_l capa_flags; ++ /// Maximum A-MPDU size, in bytes, for HE frames ++ u32_l ampdu_size_max_he; ++ /// Maximum A-MPDU size, in bytes, for VHT frames ++ u32_l ampdu_size_max_vht; ++ /// PAID/GID ++ u32_l paid_gid; ++ /// Maximum A-MPDU size, in bytes, for HT frames ++ u16_l ampdu_size_max_ht; ++ /// MAC address of the station to be added ++ struct mac_addr mac_addr; ++ /// A-MPDU spacing, in us ++ u8_l ampdu_spacing_min; ++ /// Interface index ++ u8_l inst_nbr; ++ /// TDLS station ++ bool_l tdls_sta; ++ /// Indicate if the station is TDLS link initiator station ++ bool_l tdls_sta_initiator; ++ /// Indicate if the TDLS Channel Switch is allowed ++ bool_l tdls_chsw_allowed; ++ /// nonTransmitted BSSID index, set to the BSSID index in case the STA added is an AP ++ /// that is a nonTransmitted BSSID. Should be set to 0 otherwise ++ u8_l bssid_index; ++ /// Maximum BSSID indicator, valid if the STA added is an AP that is a nonTransmitted ++ /// BSSID ++ u8_l max_bssid_ind; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_ADD_CFM message. ++struct mm_sta_add_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++ /// Index assigned by the LMAC to the newly added station ++ u8_l sta_idx; ++ /// MAC HW index of the newly added station ++ u8_l hw_sta_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_DEL_REQ message. ++struct mm_sta_del_req { ++ /// Index of the station to be deleted ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_DEL_CFM message. ++struct mm_sta_del_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the SET_POWER_MODE REQ message. ++struct mm_setpowermode_req { ++ u8_l mode; ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the parameters of the SET_POWER_MODE CFM message. ++struct mm_setpowermode_cfm { ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_KEY_ADD REQ message. ++struct mm_key_add_req { ++ /// Key index (valid only for default keys) ++ u8_l key_idx; ++ /// STA index (valid only for pairwise or mesh group keys) ++ u8_l sta_idx; ++ /// Key material ++ struct mac_sec_key key; ++ /// Cipher suite (WEP64, WEP128, TKIP, CCMP) ++ u8_l cipher_suite; ++ /// Index of the interface for which the key is set (valid only for default keys or mesh group keys) ++ u8_l inst_nbr; ++ /// A-MSDU SPP parameter ++ u8_l spp; ++ /// Indicate if provided key is a pairwise key or not ++ bool_l pairwise; ++}; ++ ++/// Structure containing the parameters of the @ref MM_KEY_ADD_CFM message. ++struct mm_key_add_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++ /// HW index of the key just added ++ u8_l hw_key_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_KEY_DEL_REQ message. ++struct mm_key_del_req { ++ /// HW index of the key to be deleted ++ u8_l hw_key_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_ADD_REQ message. ++struct mm_ba_add_req { ++ ///Type of agreement (0: TX, 1: RX) ++ u8_l type; ++ ///Index of peer station with which the agreement is made ++ u8_l sta_idx; ++ ///TID for which the agreement is made with peer station ++ u8_l tid; ++ ///Buffer size - number of MPDUs that can be held in its buffer per TID ++ u8_l bufsz; ++ /// Start sequence number negotiated during BA setup - the one in first aggregated MPDU counts more ++ u16_l ssn; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_ADD_CFM message. ++struct mm_ba_add_cfm { ++ ///Index of peer station for which the agreement is being confirmed ++ u8_l sta_idx; ++ ///TID for which the agreement is being confirmed ++ u8_l tid; ++ /// Status of ba establishment ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_DEL_REQ message. ++struct mm_ba_del_req { ++ ///Type of agreement (0: TX, 1: RX) ++ u8_l type; ++ ///Index of peer station for which the agreement is being deleted ++ u8_l sta_idx; ++ ///TID for which the agreement is being deleted ++ u8_l tid; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_DEL_CFM message. ++struct mm_ba_del_cfm { ++ ///Index of peer station for which the agreement deletion is being confirmed ++ u8_l sta_idx; ++ ///TID for which the agreement deletion is being confirmed ++ u8_l tid; ++ /// Status of ba deletion ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_ADD_REQ message ++struct mm_chan_ctxt_add_req { ++ /// Operating channel ++ struct mac_chan_op chan; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_ADD_REQ message ++struct mm_chan_ctxt_add_cfm { ++ /// Status of the addition ++ u8_l status; ++ /// Index of the new channel context ++ u8_l index; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_DEL_REQ message ++struct mm_chan_ctxt_del_req { ++ /// Index of the new channel context to be deleted ++ u8_l index; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_LINK_REQ message ++struct mm_chan_ctxt_link_req { ++ /// VIF index ++ u8_l vif_index; ++ /// Channel context index ++ u8_l chan_index; ++ /// Indicate if this is a channel switch (unlink current ctx first if true) ++ u8_l chan_switch; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_UNLINK_REQ message ++struct mm_chan_ctxt_unlink_req { ++ /// VIF index ++ u8_l vif_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_UPDATE_REQ message ++struct mm_chan_ctxt_update_req { ++ /// Channel context index ++ u8_l chan_index; ++ /// New channel information ++ struct mac_chan_op chan; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_SCHED_REQ message ++struct mm_chan_ctxt_sched_req { ++ /// VIF index ++ u8_l vif_index; ++ /// Channel context index ++ u8_l chan_index; ++ /// Type of the scheduling request (0: normal scheduling, 1: derogatory ++ /// scheduling) ++ u8_l type; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHANNEL_SWITCH_IND message ++struct mm_channel_switch_ind { ++ /// Index of the channel context we will switch to ++ u8_l chan_index; ++ /// Indicate if the switch has been triggered by a Remain on channel request ++ bool_l roc; ++ /// VIF on which remain on channel operation has been started (if roc == 1) ++ u8_l vif_index; ++ /// Indicate if the switch has been triggered by a TDLS Remain on channel request ++ bool_l roc_tdls; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHANNEL_PRE_SWITCH_IND message ++struct mm_channel_pre_switch_ind { ++ /// Index of the channel context we will switch to ++ u8_l chan_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CONNECTION_LOSS_IND message. ++struct mm_connection_loss_ind { ++ /// VIF instance number ++ u8_l inst_nbr; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_DBG_TRIGGER_REQ message. ++struct mm_dbg_trigger_req { ++ /// Error trace to be reported by the LMAC ++ char error[64]; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_PS_MODE_REQ message. ++struct mm_set_ps_mode_req { ++ /// Power Save is activated or deactivated ++ u8_l new_state; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BCN_CHANGE_REQ message. ++#define BCN_MAX_CSA_CPT 2 ++struct mm_bcn_change_req { ++ /// Pointer, in host memory, to the new beacon template ++ u32_l bcn_ptr; ++ /// Length of the beacon template ++ u16_l bcn_len; ++ /// Offset of the TIM IE in the beacon ++ u16_l tim_oft; ++ /// Length of the TIM IE ++ u8_l tim_len; ++ /// Index of the VIF for which the beacon is updated ++ u8_l inst_nbr; ++ /// Offset of CSA (channel switch announcement) counters (0 means no counter) ++ u8_l csa_oft[BCN_MAX_CSA_CPT]; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_TIM_UPDATE_REQ message. ++struct mm_tim_update_req { ++ /// Association ID of the STA the bit of which has to be updated (0 for BC/MC traffic) ++ u16_l aid; ++ /// Flag indicating the availability of data packets for the given STA ++ u8_l tx_avail; ++ /// Index of the VIF for which the TIM is updated ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMAIN_ON_CHANNEL_REQ message. ++struct mm_remain_on_channel_req { ++ /// Operation Code ++ u8_l op_code; ++ /// VIF Index ++ u8_l vif_index; ++ /// Band (2.4GHz or 5GHz) ++ u8_l band; ++ /// Channel type: 20,40,80,160 or 80+80 MHz ++ u8_l type; ++ /// Frequency for Primary 20MHz channel (in MHz) ++ u16_l prim20_freq; ++ /// Frequency for Center of the contiguous channel or center of Primary 80+80 ++ u16_l center1_freq; ++ /// Frequency for Center of the non-contiguous secondary 80+80 ++ u16_l center2_freq; ++ /// Duration (in ms) ++ u32_l duration_ms; ++ /// TX power (in dBm) ++ s8_l tx_power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMAIN_ON_CHANNEL_CFM message ++struct mm_remain_on_channel_cfm { ++ /// Operation Code ++ u8_l op_code; ++ /// Status of the operation ++ u8_l status; ++ /// Channel Context index ++ u8_l chan_ctxt_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMAIN_ON_CHANNEL_EXP_IND message ++struct mm_remain_on_channel_exp_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// Channel Context index ++ u8_l chan_ctxt_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_UAPSD_TMR_REQ message. ++struct mm_set_uapsd_tmr_req { ++ /// action: Start or Stop the timer ++ u8_l action; ++ /// timeout value, in milliseconds ++ u32_l timeout; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_UAPSD_TMR_CFM message. ++struct mm_set_uapsd_tmr_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_PS_CHANGE_IND message ++struct mm_ps_change_ind { ++ /// Index of the peer device that is switching its PS state ++ u8_l sta_idx; ++ /// New PS state of the peer device (0: active, 1: sleeping) ++ u8_l ps_state; ++}; ++ ++/// Structure containing the parameters of the @ref MM_P2P_VIF_PS_CHANGE_IND message ++struct mm_p2p_vif_ps_change_ind { ++ /// Index of the P2P VIF that is switching its PS state ++ u8_l vif_index; ++ /// New PS state of the P2P VIF interface (0: active, 1: sleeping) ++ u8_l ps_state; ++}; ++ ++/// Structure containing the parameters of the @ref MM_TRAFFIC_REQ_IND message ++struct mm_traffic_req_ind { ++ /// Index of the peer device that needs traffic ++ u8_l sta_idx; ++ /// Number of packets that need to be sent (if 0, all buffered traffic shall be sent and ++ /// if set to @ref PS_SP_INTERRUPTED, it means that current service period has been interrupted) ++ u8_l pkt_cnt; ++ /// Flag indicating if the traffic request concerns U-APSD queues or not ++ bool_l uapsd; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_PS_OPTIONS_REQ message. ++struct mm_set_ps_options_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// Listen interval (0 if wake up shall be based on DTIM period) ++ u16_l listen_interval; ++ /// Flag indicating if we shall listen the BC/MC traffic or not ++ bool_l dont_listen_bc_mc; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CSA_COUNTER_IND message ++struct mm_csa_counter_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Updated CSA counter value ++ u8_l csa_count; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHANNEL_SURVEY_IND message ++struct mm_channel_survey_ind { ++ /// Frequency of the channel ++ u16_l freq; ++ /// Noise in dbm ++ s8_l noise_dbm; ++ /// Amount of time spent of the channel (in ms) ++ u32_l chan_time_ms; ++ /// Amount of time the primary channel was sensed busy ++ u32_l chan_time_busy_ms; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BFMER_ENABLE_REQ message. ++struct mm_bfmer_enable_req { ++ /** ++ * Address of the beamforming report space allocated in host memory ++ * (Valid only if vht_su_bfmee is true) ++ */ ++ u32_l host_bfr_addr; ++ /** ++ * Size of the beamforming report space allocated in host memory. This space should ++ * be twice the maximum size of the expected beamforming reports as the FW will ++ * divide it in two in order to be able to upload a new report while another one is ++ * used in transmission ++ */ ++ u16_l host_bfr_size; ++ /// AID ++ u16_l aid; ++ /// Station Index ++ u8_l sta_idx; ++ /// Maximum number of spatial streams the station can receive ++ u8_l rx_nss; ++ /** ++ * Indicate if peer STA is MU Beamformee (VHT) capable ++ * (Valid only if vht_su_bfmee is true) ++ */ ++ bool_l vht_mu_bfmee; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_NOA_REQ message. ++struct mm_set_p2p_noa_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// Allocated NOA Instance Number - Valid only if count = 0 ++ u8_l noa_inst_nb; ++ /// Count ++ u8_l count; ++ /// Indicate if NoA can be paused for traffic reason ++ bool_l dyn_noa; ++ /// Duration (in us) ++ u32_l duration_us; ++ /// Interval (in us) ++ u32_l interval_us; ++ /// Start Time offset from next TBTT (in us) ++ u32_l start_offset; ++}; ++ ++#ifdef AICWF_ARP_OFFLOAD ++struct mm_set_arpoffload_en_req { ++ u32_l ipaddr; ++ u8_l enable; ++ u8_l vif_idx; ++}; ++ ++struct mm_set_arpoffload_en_cfm { ++ u8_l status; ++}; ++#endif ++ ++struct mm_set_agg_disable_req { ++ u8_l disable; ++ u8_l staidx; ++ u8_l disable_rx; ++}; ++ ++struct mm_set_coex_req { ++ u8_l bt_on; ++ u8_l disable_coexnull; ++ u8_l enable_nullcts; ++ u8_l enable_periodic_timer; ++ u8_l coex_timeslot_set; ++ u32_l coex_timeslot[2]; ++}; ++#if 0 ++struct mm_set_rf_config_req { ++ u8_l def_band; ++ u8_l config_type; ++ u16_l offset; ++ u16_l len; ++ u16_l set; ++ u32_l rx_gain_24g[48][4]; ++ u32_l rx_gain_5g[32][4]; ++ u32_l tx_gain[32]; ++}; ++#endif ++struct mm_set_rf_config_req ++{ ++ u8_l table_sel; ++ u8_l table_ofst; ++ u8_l table_num; ++ u8_l deft_page; ++ u32_l data[64]; ++}; ++ ++struct mm_set_rf_calib_req { ++ u32_l cal_cfg_24g; ++ u32_l cal_cfg_5g; ++ u32_l param_alpha; ++ u32_l bt_calib_en; ++ u32_l bt_calib_param; ++ u8_l xtal_cap; ++ u8_l xtal_cap_fine; ++}; ++ ++struct mm_set_rf_calib_cfm { ++ u32_l rxgain_24g_addr; ++ u32_l rxgain_5g_addr; ++ u32_l txgain_24g_addr; ++ u32_l txgain_5g_addr; ++}; ++ ++struct mm_get_mac_addr_req { ++ u32_l get; ++}; ++ ++struct mm_get_mac_addr_cfm { ++ u8_l mac_addr[6]; ++}; ++ ++struct mm_get_sta_info_req { ++ u8_l sta_idx; ++}; ++ ++struct mm_get_sta_info_cfm { ++ u32_l rate_info; ++ u32_l txfailed; ++ u8 rssi; ++ u8 reserved[3]; ++ u32_l chan_busy_time; ++ u32_l ack_fail_stat; ++ u32_l ack_succ_stat; ++ u32_l chan_tx_busy_time; ++}; ++ ++typedef struct ++{ ++ u8_l enable; ++ u8_l dsss; ++ u8_l ofdmlowrate_2g4; ++ u8_l ofdm64qam_2g4; ++ u8_l ofdm256qam_2g4; ++ u8_l ofdm1024qam_2g4; ++ u8_l ofdmlowrate_5g; ++ u8_l ofdm64qam_5g; ++ u8_l ofdm256qam_5g; ++ u8_l ofdm1024qam_5g; ++} txpwr_lvl_conf_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_11b_11ag_2g4[12]; ++ s8_l pwrlvl_11n_11ac_2g4[10]; ++ s8_l pwrlvl_11ax_2g4[12]; ++} txpwr_lvl_conf_v2_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_11b_11ag_2g4[12]; ++ s8_l pwrlvl_11n_11ac_2g4[10]; ++ s8_l pwrlvl_11ax_2g4[12]; ++ s8_l pwrlvl_11a_5g[12]; ++ s8_l pwrlvl_11n_11ac_5g[10]; ++ s8_l pwrlvl_11ax_5g[12]; ++} txpwr_lvl_conf_v3_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_11b_11ag_2g4[12]; ++ s8_l pwrlvl_11n_11ac_2g4[10]; ++ s8_l pwrlvl_11ax_2g4[12]; ++ s8_l pwrlvl_11a_5g[8]; ++ s8_l pwrlvl_11n_11ac_5g[10]; ++ s8_l pwrlvl_11ax_5g[12]; ++ s8_l pwrlvl_11a_6g[8]; ++ s8_l pwrlvl_11n_11ac_6g[10]; ++ s8_l pwrlvl_11ax_6g[12]; ++} txpwr_lvl_conf_v4_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_adj_tbl_2g4[3]; ++ s8_l pwrlvl_adj_tbl_5g[6]; ++} txpwr_lvl_adj_conf_t; ++ ++typedef struct ++{ ++ u8_l loss_enable_2g4; ++ s8_l loss_value_2g4; ++ u8_l loss_enable_5g; ++ s8_l loss_value_5g; ++} txpwr_loss_conf_t; ++ ++struct mm_set_txpwr_lvl_req ++{ ++ union { ++ txpwr_lvl_conf_t txpwr_lvl; ++ txpwr_lvl_conf_v2_t txpwr_lvl_v2; ++ txpwr_lvl_conf_v3_t txpwr_lvl_v3; ++ txpwr_lvl_conf_v4_t txpwr_lvl_v4; ++ }; ++}; ++ ++struct mm_set_txpwr_lvl_adj_req ++{ ++ txpwr_lvl_adj_conf_t txpwr_lvl_adj; ++}; ++ ++typedef struct { ++ u8_l enable; ++ u8_l dsss; ++ u8_l ofdmlowrate_2g4; ++ u8_l ofdm64qam_2g4; ++ u8_l ofdm256qam_2g4; ++ u8_l ofdm1024qam_2g4; ++ u8_l ofdmlowrate_5g; ++ u8_l ofdm64qam_5g; ++ u8_l ofdm256qam_5g; ++ u8_l ofdm1024qam_5g; ++} txpwr_idx_conf_t; ++ ++struct mm_set_txpwr_idx_req { ++ txpwr_idx_conf_t txpwr_idx; ++}; ++ ++typedef struct { ++ u8_l enable; ++ s8_l chan_1_4; ++ s8_l chan_5_9; ++ s8_l chan_10_13; ++ s8_l chan_36_64; ++ s8_l chan_100_120; ++ s8_l chan_122_140; ++ s8_l chan_142_165; ++} txpwr_ofst_conf_t; ++ ++/* ++ * pwrofst2x_tbl_2g4[3][3]: ++ * +---------------+----------+----------+----------+ ++ * | RateTyp\ChGrp | CH_1_4 | CH_5_9 | CH_10_13 | ++ * +---------------+----------+----------+----------+ ++ * | DSSS | [0][0] | [0][1] | [0][2] | ++ * +---------------+----------+----------+----------+ ++ * | OFDM_HIGHRATE | [1][0] | [1][1] | [1][2] | ++ * +---------------+----------+----------+----------+ ++ * | OFDM_LOWRATE | [2][0] | [2][1] | [2][2] | ++ * +---------------+----------+----------+----------+ ++ * pwrofst2x_tbl_5g[3][6]: ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | RateTyp\ChGrp | CH_42(36~50) | CH_58(51~64) | CH_106(98~114) | CH_122(115~130)| CH_138(131~146)| CH_155(147~166)| ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | OFDM_LOWRATE | [0][0] | [0][1] | [0][2] | [0][3] | [0][4] | [0][5] | ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | OFDM_HIGHRATE | [1][0] | [1][1] | [1][2] | [1][3] | [1][4] | [1][5] | ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | OFDM_MIDRATE | [2][0] | [2][1] | [2][2] | [2][3] | [2][4] | [2][5] | ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ */ ++ ++typedef struct ++{ ++ int8_t enable; ++ int8_t pwrofst2x_tbl_2g4[3][3]; ++ int8_t pwrofst2x_tbl_5g[3][6]; ++} txpwr_ofst2x_conf_t; ++ ++/* ++ * pwrofst2x_v2_tbl_2g4_ant0/1[3][3]: ++ * +---------------+----------+---------------+--------------+ ++ * | ChGrp\RateTyp | DSSS | OFDM_HIGHRATE | OFDM_LOWRATE | ++ * +---------------+----------+---------------+--------------+ ++ * | CH_1_4 | [0][0] | [0][1] | Reserved | ++ * +---------------+----------+---------------+--------------+ ++ * | CH_5_9 | [1][0] | [1][1] | Reserved | ++ * +---------------+----------+---------------+--------------+ ++ * | CH_10_13 | [2][0] | [2][1] | Reserved | ++ * +---------------+----------+---------------+--------------+ ++ * pwrofst2x_v2_tbl_5g_ant0/1[6][3]: ++ * +-----------------+---------------+--------------+--------------+ ++ * | ChGrp\RateTyp | OFDM_HIGHRATE | OFDM_LOWRATE | OFDM_MIDRATE | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_42(36~50) | [0][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_58(51~64) | [1][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_106(98~114) | [2][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_122(115~130) | [3][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_138(131~146) | [4][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_155(147~166) | [5][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ */ ++ ++typedef struct ++{ ++ u8_l enable; ++ u8_l pwrofst_flags; ++ s8_l pwrofst2x_tbl_2g4_ant0[3][3]; ++ s8_l pwrofst2x_tbl_2g4_ant1[3][3]; ++ s8_l pwrofst2x_tbl_5g_ant0[6][3]; ++ s8_l pwrofst2x_tbl_5g_ant1[6][3]; ++ s8_l pwrofst2x_tbl_6g_ant0[15]; ++ s8_l pwrofst2x_tbl_6g_ant1[15]; ++} txpwr_ofst2x_conf_v2_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ u8_l xtal_cap; ++ u8_l xtal_cap_fine; ++} xtal_cap_conf_t; ++ ++ ++struct mm_set_txpwr_ofst_req { ++ union { ++ txpwr_ofst_conf_t txpwr_ofst; ++ txpwr_ofst2x_conf_t txpwr_ofst2x; ++ txpwr_ofst2x_conf_v2_t txpwr_ofst2x_v2; ++ }; ++}; ++ ++struct mm_set_stack_start_req { ++ u8_l is_stack_start; ++ u8_l efuse_valid; ++ u8_l set_vendor_info; ++ u8_l fwtrace_redir; ++}; ++ ++struct mm_set_stack_start_cfm { ++ u8_l is_5g_support; ++ u8_l vendor_info; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_OPPPS_REQ message. ++struct mm_set_p2p_oppps_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// CTWindow ++ u8_l ctwindow; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_NOA_CFM message. ++struct mm_set_p2p_noa_cfm { ++ /// Request status ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_OPPPS_CFM message. ++struct mm_set_p2p_oppps_cfm { ++ /// Request status ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_P2P_NOA_UPD_IND message. ++struct mm_p2p_noa_upd_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// NOA Instance Number ++ u8_l noa_inst_nb; ++ /// NoA Type ++ u8_l noa_type; ++ /// Count ++ u8_l count; ++ /// Duration (in us) ++ u32_l duration_us; ++ /// Interval (in us) ++ u32_l interval_us; ++ /// Start Time ++ u32_l start_time; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CFG_RSSI_REQ message ++struct mm_cfg_rssi_req { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// RSSI threshold ++ s8_l rssi_thold; ++ /// RSSI hysteresis ++ u8_l rssi_hyst; ++}; ++ ++/// Structure containing the parameters of the @ref MM_RSSI_STATUS_IND message ++struct mm_rssi_status_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Status of the RSSI ++ bool_l rssi_status; ++ /// Current RSSI ++ s8_l rssi; ++}; ++ ++/// Structure containing the parameters of the @ref MM_PKTLOSS_IND message ++struct mm_pktloss_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Address of the STA for which there is a packet loss ++ struct mac_addr mac_addr; ++ /// Number of packets lost ++ u32 num_packets; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CSA_FINISH_IND message ++struct mm_csa_finish_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Status of the operation ++ u8_l status; ++ /// New channel ctx index ++ u8_l chan_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CSA_TRAFFIC_IND message ++struct mm_csa_traffic_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Is tx traffic enable or disable ++ bool_l enable; ++}; ++ ++/// Structure containing the parameters of the @ref MM_MU_GROUP_UPDATE_REQ message. ++/// Size allocated for the structure depends of the number of group ++struct mm_mu_group_update_req { ++ /// Station index ++ u8_l sta_idx; ++ /// Number of groups the STA belongs to ++ u8_l group_cnt; ++ /// Group information ++ struct { ++ /// Group Id ++ u8_l group_id; ++ /// User position ++ u8_l user_pos; ++ } groups[0]; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For Scan messages ++/////////////////////////////////////////////////////////////////////////////// ++enum scan_msg_tag { ++ /// Scanning start Request. ++ SCAN_START_REQ = LMAC_FIRST_MSG(TASK_SCAN), ++ /// Scanning start Confirmation. ++ SCAN_START_CFM, ++ /// End of scanning indication. ++ SCAN_DONE_IND, ++ /// Cancel scan request ++ SCAN_CANCEL_REQ, ++ /// Cancel scan confirmation ++ SCAN_CANCEL_CFM, ++ ++ /// MAX number of messages ++ SCAN_MAX, ++}; ++ ++/// Maximum number of SSIDs in a scan request ++#define SCAN_SSID_MAX 3 ++ ++/// Maximum number of channels in a scan request ++#define SCAN_CHANNEL_MAX (MAC_DOMAINCHANNEL_24G_MAX + MAC_DOMAINCHANNEL_5G_MAX) ++ ++/// Maximum length of the ProbeReq IEs (SoftMAC mode) ++#define SCAN_MAX_IE_LEN 300 ++ ++/// Maximum number of PHY bands supported ++#define SCAN_BAND_MAX 2 ++ ++/// Structure containing the parameters of the @ref SCAN_START_REQ message ++struct scan_start_req { ++ /// List of channel to be scanned ++ struct mac_chan_def chan[SCAN_CHANNEL_MAX]; ++ /// List of SSIDs to be scanned ++ struct mac_ssid ssid[SCAN_SSID_MAX]; ++ /// BSSID to be scanned ++ struct mac_addr bssid; ++ /// Pointer (in host memory) to the additional IEs that need to be added to the ProbeReq ++ /// (following the SSID element) ++ u32_l add_ies; ++ /// Length of the additional IEs ++ u16_l add_ie_len; ++ /// Index of the VIF that is scanning ++ u8_l vif_idx; ++ /// Number of channels to scan ++ u8_l chan_cnt; ++ /// Number of SSIDs to scan for ++ u8_l ssid_cnt; ++ /// no CCK - For P2P frames not being sent at CCK rate in 2GHz band. ++ bool no_cck; ++ /// Scan duration, in us ++ u32_l duration; ++}; ++ ++/// Structure containing the parameters of the @ref SCAN_START_CFM message ++struct scan_start_cfm { ++ /// Status of the request ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref SCAN_CANCEL_REQ message ++struct scan_cancel_req { ++}; ++ ++/// Structure containing the parameters of the @ref SCAN_START_CFM message ++struct scan_cancel_cfm { ++ /// Status of the request ++ u8_l status; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For Scanu messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Messages that are logically related to the task. ++enum { ++ /// Scan request from host. ++ SCANU_START_REQ = LMAC_FIRST_MSG(TASK_SCANU), ++ /// Scanning start Confirmation. ++ SCANU_START_CFM, ++ /// Join request ++ SCANU_JOIN_REQ, ++ /// Join confirmation. ++ SCANU_JOIN_CFM, ++ /// Scan result indication. ++ SCANU_RESULT_IND, ++ /// Fast scan request from any other module. ++ SCANU_FAST_REQ, ++ /// Confirmation of fast scan request. ++ SCANU_FAST_CFM, ++ ++ SCANU_VENDOR_IE_REQ, ++ SCANU_VENDOR_IE_CFM, ++ SCANU_START_CFM_ADDTIONAL, ++ SCANU_CANCEL_REQ, ++ SCANU_CANCEL_CFM, ++ ++ /// MAX number of messages ++ SCANU_MAX, ++}; ++ ++/// Maximum length of the additional ProbeReq IEs (FullMAC mode) ++#define SCANU_MAX_IE_LEN 200 ++ ++/// Structure containing the parameters of the @ref SCANU_START_REQ message ++struct scanu_start_req { ++ /// List of channel to be scanned ++ struct mac_chan_def chan[SCAN_CHANNEL_MAX]; ++ /// List of SSIDs to be scanned ++ struct mac_ssid ssid[SCAN_SSID_MAX]; ++ /// BSSID to be scanned (or WILDCARD BSSID if no BSSID is searched in particular) ++ struct mac_addr bssid; ++ /// Address (in host memory) of the additional IEs that need to be added to the ProbeReq ++ /// (following the SSID element) ++ u32_l add_ies; ++ /// Length of the additional IEs ++ u16_l add_ie_len; ++ /// Index of the VIF that is scanning ++ u8_l vif_idx; ++ /// Number of channels to scan ++ u8_l chan_cnt; ++ /// Number of SSIDs to scan for ++ u8_l ssid_cnt; ++ /// no CCK - For P2P frames not being sent at CCK rate in 2GHz band. ++ bool no_cck; ++ /// Scan duration, in us ++ u32_l duration; ++}; ++ ++struct scanu_vendor_ie_req { ++ u16_l add_ie_len; ++ u8_l vif_idx; ++ u8_l ie[256]; ++}; ++ ++/// Structure containing the parameters of the @ref SCANU_START_CFM message ++struct scanu_start_cfm { ++ /// Index of the VIF that was scanning ++ u8_l vif_idx; ++ /// Status of the request ++ u8_l status; ++ /// Number of scan results available ++ u8_l result_cnt; ++}; ++ ++/// Parameters of the @SCANU_RESULT_IND message ++struct scanu_result_ind { ++ /// Length of the frame ++ u16_l length; ++ /// Frame control field of the frame. ++ u16_l framectrl; ++ /// Center frequency on which we received the packet ++ u16_l center_freq; ++ /// PHY band ++ u8_l band; ++ /// Index of the station that sent the frame. 0xFF if unknown. ++ u8_l sta_idx; ++ /// Index of the VIF that received the frame. 0xFF if unknown. ++ u8_l inst_nbr; ++ /// RSSI of the received frame. ++ s8_l rssi; ++ /// Frame payload. ++ u32_l payload[]; ++}; ++ ++/// Structure containing the parameters of the message. ++struct scanu_fast_req { ++ /// The SSID to scan in the channel. ++ struct mac_ssid ssid; ++ /// BSSID. ++ struct mac_addr bssid; ++ /// Probe delay. ++ u16_l probe_delay; ++ /// Minimum channel time. ++ u16_l minch_time; ++ /// Maximum channel time. ++ u16_l maxch_time; ++ /// The channel number to scan. ++ u16_l ch_nbr; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For ME messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Messages that are logically related to the task. ++enum { ++ /// Configuration request from host. ++ ME_CONFIG_REQ = LMAC_FIRST_MSG(TASK_ME), ++ /// Configuration confirmation. ++ ME_CONFIG_CFM, ++ /// Configuration request from host. ++ ME_CHAN_CONFIG_REQ, ++ /// Configuration confirmation. ++ ME_CHAN_CONFIG_CFM, ++ /// Set control port state for a station. ++ ME_SET_CONTROL_PORT_REQ, ++ /// Control port setting confirmation. ++ ME_SET_CONTROL_PORT_CFM, ++ /// TKIP MIC failure indication. ++ ME_TKIP_MIC_FAILURE_IND, ++ /// Add a station to the FW (AP mode) ++ ME_STA_ADD_REQ, ++ /// Confirmation of the STA addition ++ ME_STA_ADD_CFM, ++ /// Delete a station from the FW (AP mode) ++ ME_STA_DEL_REQ, ++ /// Confirmation of the STA deletion ++ ME_STA_DEL_CFM, ++ /// Indication of a TX RA/TID queue credit update ++ ME_TX_CREDITS_UPDATE_IND, ++ /// Request indicating to the FW that there is traffic buffered on host ++ ME_TRAFFIC_IND_REQ, ++ /// Confirmation that the @ref ME_TRAFFIC_IND_REQ has been executed ++ ME_TRAFFIC_IND_CFM, ++ /// Request of RC statistics to a station ++ ME_RC_STATS_REQ, ++ /// RC statistics confirmation ++ ME_RC_STATS_CFM, ++ /// RC fixed rate request ++ ME_RC_SET_RATE_REQ, ++ /// Configure monitor interface ++ ME_CONFIG_MONITOR_REQ, ++ /// Configure monitor interface response ++ ME_CONFIG_MONITOR_CFM, ++ /// Setting power Save mode request from host ++ ME_SET_PS_MODE_REQ, ++ /// Set power Save mode confirmation ++ ME_SET_PS_MODE_CFM, ++ /// Setting Low Power level request from host ++ ME_SET_LP_LEVEL_REQ, ++ /// Set Low Power level confirmation ++ ME_SET_LP_LEVEL_CFM, ++ /// MAX number of messages ++ ME_MAX, ++}; ++ ++/// Structure containing the parameters of the @ref ME_START_REQ message ++struct me_config_req { ++ /// HT Capabilities ++ struct mac_htcapability ht_cap; ++ /// VHT Capabilities ++ struct mac_vhtcapability vht_cap; ++ /// HE capabilities ++ struct mac_hecapability he_cap; ++ /// Lifetime of packets sent under a BlockAck agreement (expressed in TUs) ++ u16_l tx_lft; ++ /// Maximum supported BW ++ u8_l phy_bw_max; ++ /// Boolean indicating if HT is supported or not ++ bool_l ht_supp; ++ /// Boolean indicating if VHT is supported or not ++ bool_l vht_supp; ++ /// Boolean indicating if HE is supported or not ++ bool_l he_supp; ++ /// Boolean indicating if HE OFDMA UL is enabled or not ++ bool_l he_ul_on; ++ /// Boolean indicating if PS mode shall be enabled or not ++ bool_l ps_on; ++ /// Boolean indicating if Antenna Diversity shall be enabled or not ++ bool_l ant_div_on; ++ /// Boolean indicating if Dynamic PS mode shall be used or not ++ bool_l dpsm; ++}; ++ ++/// Structure containing the parameters of the @ref ME_CHAN_CONFIG_REQ message ++struct me_chan_config_req { ++ /// List of 2.4GHz supported channels ++ struct mac_chan_def chan2G4[MAC_DOMAINCHANNEL_24G_MAX]; ++ /// List of 5GHz supported channels ++ struct mac_chan_def chan5G[MAC_DOMAINCHANNEL_5G_MAX]; ++ /// Number of 2.4GHz channels in the list ++ u8_l chan2G4_cnt; ++ /// Number of 5GHz channels in the list ++ u8_l chan5G_cnt; ++}; ++ ++/// Structure containing the parameters of the @ref ME_SET_CONTROL_PORT_REQ message ++struct me_set_control_port_req { ++ /// Index of the station for which the control port is opened ++ u8_l sta_idx; ++ /// Control port state ++ bool_l control_port_open; ++}; ++ ++/// Structure containing the parameters of the @ref ME_TKIP_MIC_FAILURE_IND message ++struct me_tkip_mic_failure_ind { ++ /// Address of the sending STA ++ struct mac_addr addr; ++ /// TSC value ++ u64_l tsc; ++ /// Boolean indicating if the packet was a group or unicast one (true if group) ++ bool_l ga; ++ /// Key Id ++ u8_l keyid; ++ /// VIF index ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref ME_STA_ADD_REQ message ++struct me_sta_add_req { ++ /// MAC address of the station to be added ++ struct mac_addr mac_addr; ++ /// Supported legacy rates ++ struct mac_rateset rate_set; ++ /// HT Capabilities ++ struct mac_htcapability ht_cap; ++ /// VHT Capabilities ++ struct mac_vhtcapability vht_cap; ++ /// HE capabilities ++ struct mac_hecapability he_cap; ++ /// Flags giving additional information about the station (@ref mac_sta_flags) ++ u32_l flags; ++ /// Association ID of the station ++ u16_l aid; ++ /// Bit field indicating which queues have U-APSD enabled ++ u8_l uapsd_queues; ++ /// Maximum size, in frames, of a APSD service period ++ u8_l max_sp_len; ++ /// Operation mode information (valid if bit @ref STA_OPMOD_NOTIF is ++ /// set in the flags) ++ u8_l opmode; ++ /// Index of the VIF the station is attached to ++ u8_l vif_idx; ++ /// Whether the the station is TDLS station ++ bool_l tdls_sta; ++ /// Indicate if the station is TDLS link initiator station ++ bool_l tdls_sta_initiator; ++ /// Indicate if the TDLS Channel Switch is allowed ++ bool_l tdls_chsw_allowed; ++}; ++ ++/// Structure containing the parameters of the @ref ME_STA_ADD_CFM message ++struct me_sta_add_cfm { ++ /// Station index ++ u8_l sta_idx; ++ /// Status of the station addition ++ u8_l status; ++ /// PM state of the station ++ u8_l pm_state; ++}; ++ ++/// Structure containing the parameters of the @ref ME_STA_DEL_REQ message. ++struct me_sta_del_req { ++ /// Index of the station to be deleted ++ u8_l sta_idx; ++ /// Whether the the station is TDLS station ++ bool_l tdls_sta; ++}; ++ ++/// Structure containing the parameters of the @ref ME_TX_CREDITS_UPDATE_IND message. ++struct me_tx_credits_update_ind { ++ /// Index of the station for which the credits are updated ++ u8_l sta_idx; ++ /// TID for which the credits are updated ++ u8_l tid; ++ /// Offset to be applied on the credit count ++ s8_l credits; ++}; ++ ++/// Structure containing the parameters of the @ref ME_TRAFFIC_IND_REQ message. ++struct me_traffic_ind_req { ++ /// Index of the station for which UAPSD traffic is available on host ++ u8_l sta_idx; ++ /// Flag indicating the availability of UAPSD packets for the given STA ++ u8_l tx_avail; ++ /// Indicate if traffic is on uapsd-enabled queues ++ bool_l uapsd; ++}; ++ ++struct mm_apm_staloss_ind ++{ ++ u8_l sta_idx; ++ u8_l vif_idx; ++ u8_l mac_addr[6]; ++}; ++ ++#ifdef CONFIG_SDIO_BT ++struct mm_bt_recv_ind ++{ ++ u32_l data_len; ++ u8_l bt_data[1024]; ++}; ++#endif ++ ++enum vendor_hwconfig_tag{ ++ ACS_TXOP_REQ = 0, ++ CHANNEL_ACCESS_REQ, ++ MAC_TIMESCALE_REQ, ++ CCA_THRESHOLD_REQ, ++ BWMODE_REQ, ++ CHIP_TEMP_GET_REQ, ++ AP_PS_LEVEL_SET_REQ, ++ CUSTOMIZED_FREQ_REQ, ++ WAKEUP_INFO_REQ, ++ KEEPALIVE_PKT_REQ, ++}; ++ ++enum { ++ BWMODE20M = 0, ++ BWMODE10M, ++ BWMODE5M, ++}; ++ ++struct mm_set_acs_txop_req ++{ ++ u32_l hwconfig_id; ++ u16_l txop_bk; ++ u16_l txop_be; ++ u16_l txop_vi; ++ u16_l txop_vo; ++}; ++ ++struct mm_set_channel_access_req ++{ ++ u32_l hwconfig_id; ++ u32_l edca[4]; ++ u8_l vif_idx; ++ u8_l retry_cnt; ++ u8_l rts_en; ++ u8_l long_nav_en; ++ u8_l cfe_en; ++ u8_l rc_retry_cnt[3]; ++ s8_l ccademod_th; ++ u8_l remove_1m2m; ++}; ++ ++struct mm_set_mac_timescale_req ++{ ++ u32_l hwconfig_id; ++ u8_l sifsA_time; ++ u8_l sifsB_time; ++ u8_l slot_time; ++ u8_l rx_startdelay_ofdm; ++ u8_l rx_startdelay_long; ++ u8_l rx_startdelay_short; ++}; ++ ++struct mm_set_cca_threshold_req ++{ ++ u32_l hwconfig_id; ++ u8_l auto_cca_en; ++ s8_l cca20p_rise_th; ++ s8_l cca20s_rise_th; ++ s8_l cca20p_fall_th; ++ s8_l cca20s_fall_th; ++ ++}; ++ ++struct mm_set_bwmode_req ++{ ++ u32_l hwconfig_id; ++ u8_l bwmode; ++}; ++ ++struct mm_get_chip_temp_req ++{ ++ u32_l hwconfig_id; ++}; ++ ++struct mm_get_chip_temp_cfm ++{ ++ /// Temp degree val ++ s8_l degree; ++}; ++ ++struct mm_set_ap_ps_level_req ++{ ++ u32_l hwconfig_id; ++ u8 ap_ps_level; ++}; ++ ++struct mm_set_vendor_hwconfig_cfm ++{ ++ u32_l hwconfig_id; ++ union { ++ struct mm_get_chip_temp_cfm chip_temp_cfm; ++ }; ++}; ++ ++struct mm_set_customized_freq_req ++{ ++ u32_l hwconfig_id; ++ u16_l raw_freq[4]; ++ u16_l map_freq[4]; ++}; ++ ++struct mm_set_wakeup_info_req ++{ ++ u32_l hwconfig_id; ++ u16_l offset; ++ u8_l length; ++ u8_l mask_and_patten[]; ++ ++}; ++ ++struct mm_set_keepalive_req ++{ ++ u32_l hwconfig_id; ++ u16_l code; ++ u16_l length; ++ u32_l intv; ++ u8_l payload[]; ++}; ++ ++struct mm_set_txop_req ++{ ++ u16_l txop_bk; ++ u16_l txop_be; ++ u16_l txop_vi; ++ u16_l txop_vo; ++ u8_l long_nav_en; ++ u8_l cfe_en; ++}; ++ ++#ifdef CONFIG_APF ++struct mm_set_apf_prog_req { ++ u32_l program_len; ++ u32_l offset; ++ u8_l program[LMAC_MSG_MAX_LEN]; ++}; ++ ++struct mm_get_apf_prog_req { ++ u16_l offset; ++}; ++ ++struct mm_get_apf_prog_cfm { ++ u8_l program[LMAC_MSG_MAX_LEN]; ++}; ++#endif ++ ++struct mm_get_fw_version_cfm ++{ ++ u8_l fw_version_len; ++ u8_l fw_version[63]; ++}; ++ ++struct mm_get_wifi_disable_cfm ++{ ++ u8_l wifi_disable; ++}; ++ ++enum vendor_swconfig_tag ++{ ++ BCN_CFG_REQ = 0, ++ TEMP_COMP_SET_REQ, ++ TEMP_COMP_GET_REQ, ++ EXT_FLAGS_SET_REQ, ++ EXT_FLAGS_GET_REQ, ++ EXT_FLAGS_MASK_SET_REQ, ++}; ++ ++struct mm_set_bcn_cfg_req ++{ ++ /// Ignore or not bcn tim bcmc bit ++ bool_l tim_bcmc_ignored_enable; ++}; ++ ++struct mm_set_bcn_cfg_cfm ++{ ++ /// Request status ++ bool_l tim_bcmc_ignored_status; ++}; ++ ++struct mm_set_temp_comp_req ++{ ++ /// Enable or not temp comp ++ u8_l enable; ++ u8_l reserved[3]; ++ u32_l tmr_period_ms; ++}; ++ ++struct mm_set_temp_comp_cfm ++{ ++ /// Request status ++ u8_l status; ++}; ++ ++struct mm_get_temp_comp_cfm ++{ ++ /// Request status ++ u8_l status; ++ /// Temp degree val ++ s8_l degree; ++}; ++ ++struct mm_set_ext_flags_req ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_set_ext_flags_cfm ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_get_ext_flags_cfm ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_mask_set_ext_flags_req ++{ ++ u32_l user_flags_mask; ++ u32_l user_flags_val; ++}; ++ ++struct mm_mask_set_ext_flags_cfm ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_set_vendor_swconfig_req ++{ ++ u32_l swconfig_id; ++ union { ++ struct mm_set_bcn_cfg_req bcn_cfg_req; ++ struct mm_set_temp_comp_req temp_comp_set_req; ++ struct mm_set_ext_flags_req ext_flags_set_req; ++ struct mm_mask_set_ext_flags_req ext_flags_mask_set_req; ++ }; ++}; ++ ++struct mm_set_vendor_swconfig_cfm ++{ ++ u32_l swconfig_id; ++ union { ++ struct mm_set_bcn_cfg_cfm bcn_cfg_cfm; ++ struct mm_set_temp_comp_cfm temp_comp_set_cfm; ++ struct mm_get_temp_comp_cfm temp_comp_get_cfm; ++ struct mm_set_ext_flags_cfm ext_flags_set_cfm; ++ struct mm_get_ext_flags_cfm ext_flags_get_cfm; ++ struct mm_mask_set_ext_flags_cfm ext_flags_mask_set_cfm; ++ }; ++}; ++ ++#ifdef CONFIG_SDIO_BT ++struct mm_bt_send_req ++{ ++ u32_l data_len; ++ u8_l bt_data[1024]; ++}; ++ ++struct mm_bt_send_cfm ++{ ++ u8_l status; ++}; ++#endif ++ ++/// Structure containing the parameters of the @ref ME_RC_STATS_REQ message. ++struct me_rc_stats_req { ++ /// Index of the station for which the RC statistics are requested ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the rate control statistics ++struct rc_rate_stats { ++ /// Number of attempts (per sampling interval) ++ u16_l attempts; ++ /// Number of success (per sampling interval) ++ u16_l success; ++ /// Estimated probability of success (EWMA) ++ u16_l probability; ++ /// Rate configuration of the sample ++ u16_l rate_config; ++ union { ++ struct { ++ /// Number of times the sample has been skipped (per sampling interval) ++ u8_l sample_skipped; ++ /// Whether the old probability is available ++ bool_l old_prob_available; ++ /// Whether the rate can be used in the retry chain ++ bool_l rate_allowed; ++ }; ++ struct { ++ /// RU size and UL length received in the latest HE trigger frame ++ u16_l ru_and_length; ++ }; ++ }; ++}; ++ ++/// Number of RC samples ++#define RC_MAX_N_SAMPLE 10 ++/// Index of the HE statistics element in the table ++#define RC_HE_STATS_IDX RC_MAX_N_SAMPLE ++ ++/// Structure containing the parameters of the @ref ME_RC_STATS_CFM message. ++struct me_rc_stats_cfm { ++ /// Index of the station for which the RC statistics are provided ++ u8_l sta_idx; ++ /// Number of samples used in the RC algorithm ++ u16_l no_samples; ++ /// Number of MPDUs transmitted (per sampling interval) ++ u16_l ampdu_len; ++ /// Number of AMPDUs transmitted (per sampling interval) ++ u16_l ampdu_packets; ++ /// Average number of MPDUs in each AMPDU frame (EWMA) ++ u32_l avg_ampdu_len; ++ // Current step 0 of the retry chain ++ u8_l sw_retry_step; ++ /// Trial transmission period ++ u8_l sample_wait; ++ /// Retry chain steps ++ u16_l retry_step_idx[4]; ++ /// RC statistics - Max number of RC samples, plus one for the HE TB statistics ++ struct rc_rate_stats rate_stats[RC_MAX_N_SAMPLE + 1]; ++ /// Throughput - Max number of RC samples, plus one for the HE TB statistics ++ u32_l tp[RC_MAX_N_SAMPLE + 1]; ++}; ++ ++/// Structure containing the parameters of the @ref ME_RC_SET_RATE_REQ message. ++struct me_rc_set_rate_req { ++ /// Index of the station for which the fixed rate is set ++ u8_l sta_idx; ++ /// Rate configuration to be set ++ u16_l fixed_rate_cfg; ++}; ++ ++/// Structure containing the parameters of the @ref ME_CONFIG_MONITOR_REQ message. ++struct me_config_monitor_req { ++ /// Channel to configure ++ struct mac_chan_op chan; ++ /// Is channel data valid ++ bool_l chan_set; ++ /// Enable report of unsupported HT frames ++ bool_l uf; ++ /// Enable auto-reply as the mac_addr matches ++ bool_l auto_reply; ++}; ++ ++/// Structure containing the parameters of the @ref ME_CONFIG_MONITOR_CFM message. ++struct me_config_monitor_cfm { ++ /// Channel context index ++ u8_l chan_index; ++ /// Channel parameters ++ struct mac_chan_op chan; ++}; ++ ++/// Structure containing the parameters of the @ref ME_SET_PS_MODE_REQ message. ++struct me_set_ps_mode_req { ++ /// Power Save is activated or deactivated ++ u8_l ps_state; ++}; ++ ++/// Structure containing the parameters of the @ref ME_SET_LP_LEVEL_REQ message. ++struct me_set_lp_level_req { ++ /// Low Power level ++ u8_l lp_level; ++ u8_l disable_filter; ++}; ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For SM messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Message API of the SM task ++enum sm_msg_tag { ++ /// Request to connect to an AP ++ SM_CONNECT_REQ = LMAC_FIRST_MSG(TASK_SM), ++ /// Confirmation of connection ++ SM_CONNECT_CFM, ++ /// Indicates that the SM associated to the AP ++ SM_CONNECT_IND, ++ /// Request to disconnect ++ SM_DISCONNECT_REQ, ++ /// Confirmation of disconnection ++ SM_DISCONNECT_CFM, ++ /// Indicates that the SM disassociated the AP ++ SM_DISCONNECT_IND, ++ /// Request to start external authentication ++ SM_EXTERNAL_AUTH_REQUIRED_IND, ++ /// Response to external authentication request ++ SM_EXTERNAL_AUTH_REQUIRED_RSP, ++ /// Request to update assoc elements after FT over the air authentication ++ SM_FT_AUTH_IND, ++ /// Response to FT authentication with updated assoc elements ++ SM_FT_AUTH_RSP, ++ ++ SM_RSP_TIMEOUT_IND, ++ ++ SM_COEX_TS_TIMEOUT_IND, ++ ++ SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM, ++ /// MAX number of messages ++ SM_MAX, ++}; ++ ++/// Structure containing the parameters of @ref SM_CONNECT_REQ message. ++struct sm_connect_req { ++ /// SSID to connect to ++ struct mac_ssid ssid; ++ /// BSSID to connect to (if not specified, set this field to WILDCARD BSSID) ++ struct mac_addr bssid; ++ /// Channel on which we have to connect (if not specified, set -1 in the chan.freq field) ++ struct mac_chan_def chan; ++ /// Connection flags (see @ref mac_connection_flags) ++ u32_l flags; ++ /// Control port Ethertype (in network endianness) ++ u16_l ctrl_port_ethertype; ++ /// Length of the association request IEs ++ u16_l ie_len; ++ /// Listen interval to be used for this connection ++ u16_l listen_interval; ++ /// Flag indicating if the we have to wait for the BC/MC traffic after beacon or not ++ bool_l dont_wait_bcmc; ++ /// Authentication type ++ u8_l auth_type; ++ /// UAPSD queues (bit0: VO, bit1: VI, bit2: BE, bit3: BK) ++ u8_l uapsd_queues; ++ /// VIF index ++ u8_l vif_idx; ++ /// Buffer containing the additional information elements to be put in the ++ /// association request ++ u32_l ie_buf[64]; ++}; ++ ++/// Structure containing the parameters of the @ref SM_CONNECT_CFM message. ++struct sm_connect_cfm { ++ /// Status. If 0, it means that the connection procedure will be performed and that ++ /// a subsequent @ref SM_CONNECT_IND message will be forwarded once the procedure is ++ /// completed ++ u8_l status; ++}; ++ ++#define SM_ASSOC_IE_LEN 800 ++/// Structure containing the parameters of the @ref SM_CONNECT_IND message. ++struct sm_connect_ind { ++ /// Status code of the connection procedure ++ u16_l status_code; ++ /// BSSID ++ struct mac_addr bssid; ++ /// Flag indicating if the indication refers to an internal roaming or from a host request ++ bool_l roamed; ++ /// Index of the VIF for which the association process is complete ++ u8_l vif_idx; ++ /// Index of the STA entry allocated for the AP ++ u8_l ap_idx; ++ /// Index of the LMAC channel context the connection is attached to ++ u8_l ch_idx; ++ /// Flag indicating if the AP is supporting QoS ++ bool_l qos; ++ /// ACM bits set in the AP WMM parameter element ++ u8_l acm; ++ /// Length of the AssocReq IEs ++ u16_l assoc_req_ie_len; ++ /// Length of the AssocRsp IEs ++ u16_l assoc_rsp_ie_len; ++ /// IE buffer ++ u32_l assoc_ie_buf[SM_ASSOC_IE_LEN/4]; ++ ++ u16_l aid; ++ u8_l band; ++ u16_l center_freq; ++ u8_l width; ++ u32_l center_freq1; ++ u32_l center_freq2; ++ ++ /// EDCA parameters ++ u32_l ac_param[AC_MAX]; ++}; ++ ++/// Structure containing the parameters of the @ref SM_DISCONNECT_REQ message. ++struct sm_disconnect_req { ++ /// Reason of the deauthentication. ++ u16_l reason_code; ++ /// Index of the VIF. ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of SM_ASSOCIATION_IND the message ++struct sm_association_ind { ++ // MAC ADDR of the STA ++ struct mac_addr me_mac_addr; ++}; ++ ++ ++/// Structure containing the parameters of the @ref SM_DISCONNECT_IND message. ++struct sm_disconnect_ind { ++ /// Reason of the disconnection. ++ u16_l reason_code; ++ /// Index of the VIF. ++ u8_l vif_idx; ++ /// FT over DS is ongoing ++ bool_l ft_over_ds; ++ u8_l reassoc; ++}; ++ ++/// Structure containing the parameters of the @ref SM_EXTERNAL_AUTH_REQUIRED_IND ++struct sm_external_auth_required_ind { ++ /// Index of the VIF. ++ u8_l vif_idx; ++ /// SSID to authenticate to ++ struct mac_ssid ssid; ++ /// BSSID to authenticate to ++ struct mac_addr bssid; ++ /// AKM suite of the respective authentication ++ u32_l akm; ++}; ++ ++/// Structure containing the parameters of the @ref SM_EXTERNAL_AUTH_REQUIRED_RSP ++struct sm_external_auth_required_rsp { ++ /// Index of the VIF. ++ u8_l vif_idx; ++ /// Authentication status ++ u16_l status; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For APM messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Message API of the APM task ++enum apm_msg_tag { ++ /// Request to start the AP. ++ APM_START_REQ = LMAC_FIRST_MSG(TASK_APM), ++ /// Confirmation of the AP start. ++ APM_START_CFM, ++ /// Request to stop the AP. ++ APM_STOP_REQ, ++ /// Confirmation of the AP stop. ++ APM_STOP_CFM, ++ /// Request to start CAC ++ APM_START_CAC_REQ, ++ /// Confirmation of the CAC start ++ APM_START_CAC_CFM, ++ /// Request to stop CAC ++ APM_STOP_CAC_REQ, ++ /// Confirmation of the CAC stop ++ APM_STOP_CAC_CFM, ++ ++ APM_SET_BEACON_IE_REQ, ++ APM_SET_BEACON_IE_CFM, ++ ++ /// MAX number of messages ++ APM_MAX, ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_REQ message. ++struct apm_start_req { ++ /// Basic rate set ++ struct mac_rateset basic_rates; ++ /// Control channel on which we have to enable the AP ++ struct mac_chan_def chan; ++ /// Center frequency of the first segment ++ u32_l center_freq1; ++ /// Center frequency of the second segment (only in 80+80 configuration) ++ u32_l center_freq2; ++ /// Width of channel ++ u8_l ch_width; ++ /// Address, in host memory, to the beacon template ++ u32_l bcn_addr; ++ /// Length of the beacon template ++ u16_l bcn_len; ++ /// Offset of the TIM IE in the beacon ++ u16_l tim_oft; ++ /// Beacon interval ++ u16_l bcn_int; ++ /// Flags (@ref mac_connection_flags) ++ u32_l flags; ++ /// Control port Ethertype ++ u16_l ctrl_port_ethertype; ++ /// Length of the TIM IE ++ u8_l tim_len; ++ /// Index of the VIF for which the AP is started ++ u8_l vif_idx; ++}; ++ ++struct apm_set_bcn_ie_req { ++ u8_l vif_idx; ++ u16_l bcn_ie_len; ++ u8_l bcn_ie[512]; ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_CFM message. ++struct apm_start_cfm { ++ /// Status of the AP starting procedure ++ u8_l status; ++ /// Index of the VIF for which the AP is started ++ u8_l vif_idx; ++ /// Index of the channel context attached to the VIF ++ u8_l ch_idx; ++ /// Index of the STA used for BC/MC traffic ++ u8_l bcmc_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_STOP_REQ message. ++struct apm_stop_req { ++ /// Index of the VIF for which the AP has to be stopped ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_CAC_REQ message. ++struct apm_start_cac_req { ++ /// Control channel on which we have to start the CAC ++ struct mac_chan_op chan; ++ /// Center frequency of the first segment ++ //u32_l center_freq1; ++ /// Center frequency of the second segment (only in 80+80 configuration) ++ //u32_l center_freq2; ++ /// Width of channel ++ //u8_l ch_width; ++ /// Index of the VIF for which the CAC is started ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_CAC_CFM message. ++struct apm_start_cac_cfm { ++ /// Status of the CAC starting procedure ++ u8_l status; ++ /// Index of the channel context attached to the VIF for CAC ++ u8_l ch_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_STOP_CAC_REQ message. ++struct apm_stop_cac_req { ++ /// Index of the VIF for which the CAC has to be stopped ++ u8_l vif_idx; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For MESH messages ++/////////////////////////////////////////////////////////////////////////////// ++ ++/// Maximum length of the Mesh ID ++#define MESH_MESHID_MAX_LEN (32) ++ ++/// Message API of the MESH task ++enum mesh_msg_tag ++{ ++ /// Request to start the MP ++ MESH_START_REQ = LMAC_FIRST_MSG(TASK_MESH), ++ /// Confirmation of the MP start. ++ MESH_START_CFM, ++ ++ /// Request to stop the MP. ++ MESH_STOP_REQ, ++ /// Confirmation of the MP stop. ++ MESH_STOP_CFM, ++ ++ // Request to update the MP ++ MESH_UPDATE_REQ, ++ /// Confirmation of the MP update ++ MESH_UPDATE_CFM, ++ ++ /// Request information about a given link ++ MESH_PEER_INFO_REQ, ++ /// Response to the MESH_PEER_INFO_REQ message ++ MESH_PEER_INFO_CFM, ++ ++ /// Request automatic establishment of a path with a given mesh STA ++ MESH_PATH_CREATE_REQ, ++ /// Confirmation to the MESH_PATH_CREATE_REQ message ++ MESH_PATH_CREATE_CFM, ++ ++ /// Request a path update (delete path, modify next hop mesh STA) ++ MESH_PATH_UPDATE_REQ, ++ /// Confirmation to the MESH_PATH_UPDATE_REQ message ++ MESH_PATH_UPDATE_CFM, ++ ++ /// Indication from Host that the indicated Mesh Interface is a proxy for an external STA ++ MESH_PROXY_ADD_REQ, ++ ++ /// Indicate that a connection has been established or lost ++ MESH_PEER_UPDATE_IND, ++ /// Notification that a connection has been established or lost (when MPM handled by userspace) ++ MESH_PEER_UPDATE_NTF = MESH_PEER_UPDATE_IND, ++ ++ /// Indicate that a path is now active or inactive ++ MESH_PATH_UPDATE_IND, ++ /// Indicate that proxy information have been updated ++ MESH_PROXY_UPDATE_IND, ++ ++ /// MAX number of messages ++ MESH_MAX, ++}; ++ ++ ++/// Structure containing the parameters of the @ref MESH_START_REQ message. ++struct mesh_start_req { ++ /// Basic rate set ++ struct mac_rateset basic_rates; ++ /// Control channel on which we have to enable the AP ++ struct mac_chan_def chan; ++ /// Center frequency of the first segment ++ u32_l center_freq1; ++ /// Center frequency of the second segment (only in 80+80 configuration) ++ u32_l center_freq2; ++ /// Width of channel ++ u8_l ch_width; ++ /// DTIM Period ++ u8_l dtim_period; ++ /// Beacon Interval ++ u16_l bcn_int; ++ /// Index of the VIF for which the MP is started ++ u8_l vif_index; ++ /// Length of the Mesh ID ++ u8_l mesh_id_len; ++ /// Mesh ID ++ u8_l mesh_id[MESH_MESHID_MAX_LEN]; ++ /// Address of the IEs to download ++ u32_l ie_addr; ++ /// Length of the provided IEs ++ u8_l ie_len; ++ /// Indicate if Mesh Peering Management (MPM) protocol is handled in userspace ++ bool_l user_mpm; ++ /// Indicate if Mesh Point is using authentication ++ bool_l is_auth; ++ /// Indicate which authentication method is used ++ u8_l auth_id; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_START_CFM message. ++struct mesh_start_cfm { ++ /// Status of the MP starting procedure ++ u8_l status; ++ /// Index of the VIF for which the MP is started ++ u8_l vif_idx; ++ /// Index of the channel context attached to the VIF ++ u8_l ch_idx; ++ /// Index of the STA used for BC/MC traffic ++ u8_l bcmc_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_STOP_REQ message. ++struct mesh_stop_req { ++ /// Index of the VIF for which the MP has to be stopped ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_STOP_CFM message. ++struct mesh_stop_cfm { ++ /// Index of the VIF for which the MP has to be stopped ++ u8_l vif_idx; ++ /// Status ++ u8_l status; ++}; ++ ++/// Bit fields for mesh_update_req message's flags value ++enum mesh_update_flags_bit { ++ /// Root Mode ++ MESH_UPDATE_FLAGS_ROOT_MODE_BIT = 0, ++ /// Gate Mode ++ MESH_UPDATE_FLAGS_GATE_MODE_BIT, ++ /// Mesh Forwarding ++ MESH_UPDATE_FLAGS_MESH_FWD_BIT, ++ /// Local Power Save Mode ++ MESH_UPDATE_FLAGS_LOCAL_PSM_BIT, ++}; ++ ++/// Structure containing the parameters of the @ref MESH_UPDATE_REQ message. ++struct mesh_update_req { ++ /// Flags, indicate fields which have been updated ++ u8_l flags; ++ /// VIF Index ++ u8_l vif_idx; ++ /// Root Mode ++ u8_l root_mode; ++ /// Gate Announcement ++ bool_l gate_announ; ++ /// Mesh Forwarding ++ bool_l mesh_forward; ++ /// Local PS Mode ++ u8_l local_ps_mode; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_UPDATE_CFM message. ++struct mesh_update_cfm { ++ /// Status ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_INFO_REQ message. ++struct mesh_peer_info_req { ++ ///Index of the station allocated for the peer ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_INFO_CFM message. ++struct mesh_peer_info_cfm { ++ /// Response status ++ u8_l status; ++ /// Index of the station allocated for the peer ++ u8_l sta_idx; ++ /// Local Link ID ++ u16_l local_link_id; ++ /// Peer Link ID ++ u16_l peer_link_id; ++ /// Local PS Mode ++ u8_l local_ps_mode; ++ /// Peer PS Mode ++ u8_l peer_ps_mode; ++ /// Non-peer PS Mode ++ u8_l non_peer_ps_mode; ++ /// Link State ++ u8_l link_state; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_CREATE_REQ message. ++struct mesh_path_create_req { ++ /// Index of the interface on which path has to be created ++ u8_l vif_idx; ++ /// Indicate if originator MAC Address is provided ++ bool_l has_orig_addr; ++ /// Path Target MAC Address ++ struct mac_addr tgt_mac_addr; ++ /// Originator MAC Address ++ struct mac_addr orig_mac_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_CREATE_CFM message. ++struct mesh_path_create_cfm { ++ /// Confirmation status ++ u8_l status; ++ /// VIF Index ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_UPDATE_REQ message. ++struct mesh_path_update_req { ++ /// Indicate if path must be deleted ++ bool_l delete; ++ /// Index of the interface on which path has to be created ++ u8_l vif_idx; ++ /// Path Target MAC Address ++ struct mac_addr tgt_mac_addr; ++ /// Next Hop MAC Address ++ struct mac_addr nhop_mac_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_UPDATE_CFM message. ++struct mesh_path_update_cfm { ++ /// Confirmation status ++ u8_l status; ++ /// VIF Index ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PROXY_ADD_REQ message. ++struct mesh_proxy_add_req { ++ /// VIF Index ++ u8_l vif_idx; ++ /// MAC Address of the External STA ++ struct mac_addr ext_sta_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PROXY_UPDATE_IND ++struct mesh_proxy_update_ind { ++ /// Indicate if proxy information has been added or deleted ++ bool_l delete; ++ /// Indicate if we are a proxy for the external STA ++ bool_l local; ++ /// VIF Index ++ u8_l vif_idx; ++ /// MAC Address of the External STA ++ struct mac_addr ext_sta_addr; ++ /// MAC Address of the proxy (only valid if local is false) ++ struct mac_addr proxy_mac_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_UPDATE_IND message. ++struct mesh_peer_update_ind { ++ /// Indicate if connection has been established or lost ++ bool_l estab; ++ /// VIF Index ++ u8_l vif_idx; ++ /// STA Index ++ u8_l sta_idx; ++ /// Peer MAC Address ++ struct mac_addr peer_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_UPDATE_NTF message. ++struct mesh_peer_update_ntf { ++ /// VIF Index ++ u8_l vif_idx; ++ /// STA Index ++ u8_l sta_idx; ++ /// Mesh Link State ++ u8_l state; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_UPDATE_IND message. ++struct mesh_path_update_ind { ++ /// Indicate if path is deleted or not ++ bool_l delete; ++ /// Indicate if path is towards an external STA (not part of MBSS) ++ bool_l ext_sta; ++ /// VIF Index ++ u8_l vif_idx; ++ /// Path Index ++ u8_l path_idx; ++ /// Target MAC Address ++ struct mac_addr tgt_mac_addr; ++ /// External STA MAC Address (only if ext_sta is true) ++ struct mac_addr ext_sta_mac_addr; ++ /// Next Hop STA Index ++ u8_l nhop_sta_idx; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For Debug messages ++/////////////////////////////////////////////////////////////////////////////// ++ ++/// Messages related to Debug Task ++enum dbg_msg_tag { ++ /// Memory read request ++ DBG_MEM_READ_REQ = LMAC_FIRST_MSG(TASK_DBG), ++ /// Memory read confirm ++ DBG_MEM_READ_CFM, ++ /// Memory write request ++ DBG_MEM_WRITE_REQ, ++ /// Memory write confirm ++ DBG_MEM_WRITE_CFM, ++ /// Module filter request ++ DBG_SET_MOD_FILTER_REQ, ++ /// Module filter confirm ++ DBG_SET_MOD_FILTER_CFM, ++ /// Severity filter request ++ DBG_SET_SEV_FILTER_REQ, ++ /// Severity filter confirm ++ DBG_SET_SEV_FILTER_CFM, ++ /// LMAC/MAC HW fatal error indication ++ DBG_ERROR_IND, ++ /// Request to get system statistics ++ DBG_GET_SYS_STAT_REQ, ++ /// COnfirmation of system statistics ++ DBG_GET_SYS_STAT_CFM, ++ /// Memory block write request ++ DBG_MEM_BLOCK_WRITE_REQ, ++ /// Memory block write confirm ++ DBG_MEM_BLOCK_WRITE_CFM, ++ /// Start app request ++ DBG_START_APP_REQ, ++ /// Start app confirm ++ DBG_START_APP_CFM, ++ /// Start npc request ++ DBG_START_NPC_REQ, ++ /// Start npc confirm ++ DBG_START_NPC_CFM, ++ /// Memory mask write request ++ DBG_MEM_MASK_WRITE_REQ, ++ /// Memory mask write confirm ++ DBG_MEM_MASK_WRITE_CFM, ++ ++ DBG_RFTEST_CMD_REQ, ++ DBG_RFTEST_CMD_CFM, ++ DBG_BINDING_REQ, ++ DBG_BINDING_CFM, ++ DBG_BINDING_IND, ++ ++ DBG_CUSTOM_MSG_REQ, ++ DBG_CUSTOM_MSG_CFM, ++ DBG_CUSTOM_MSG_IND, ++ ++ DBG_GPIO_WRITE_REQ, ++ DBG_GPIO_WRITE_CFM, ++ DBG_GPIO_READ_REQ, ++ DBG_GPIO_READ_CFM, ++ DBG_GPIO_INIT_REQ, ++ DBG_GPIO_INIT_CFM, ++ ++ /// EF usrdata read request ++ DBG_EF_USRDATA_READ_REQ, ++ /// EF usrdata read confirm ++ DBG_EF_USRDATA_READ_CFM, ++ /// Memory block read request ++ DBG_MEM_BLOCK_READ_REQ, ++ /// Memory block read confirm ++ DBG_MEM_BLOCK_READ_CFM, ++ ++ DBG_PWM_INIT_REQ, ++ DBG_PWM_INIT_CFM, ++ DBG_PWM_DEINIT_REQ, ++ DBG_PWM_DEINIT_CFM, ++ ++ /// Max number of Debug messages ++ DBG_MAX, ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_REQ message. ++struct dbg_mem_read_req { ++ u32_l memaddr; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_CFM message. ++struct dbg_mem_read_cfm { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_REQ message. ++struct dbg_mem_write_req { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_CFM message. ++struct dbg_mem_write_cfm { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_REQ message. ++struct dbg_mem_mask_write_req { ++ u32_l memaddr; ++ u32_l memmask; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_CFM message. ++struct dbg_mem_mask_write_cfm { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++struct dbg_rftest_cmd_req { ++ u32_l cmd; ++ u32_l argc; ++ u8_l argv[10]; ++}; ++ ++struct dbg_rftest_cmd_cfm { ++ u32_l rftest_result[32]; ++}; ++ ++struct dbg_gpio_write_req { ++ uint8_t gpio_idx; ++ uint8_t gpio_val; ++}; ++ ++struct dbg_gpio_read_req { ++ uint8_t gpio_idx; ++}; ++ ++struct dbg_gpio_read_cfm { ++ uint8_t gpio_idx; ++ uint8_t gpio_val; ++}; ++ ++struct dbg_gpio_init_req { ++ uint8_t gpio_idx; ++ uint8_t gpio_dir; //1 output, 0 input; ++ uint8_t gpio_val; //for output, 1 high, 0 low; ++}; ++ ++#ifdef CONFIG_MCU_MESSAGE ++/// Structure containing the parameters of the @ref DBG_CUSTOM_MSG_REQ message. ++struct dbg_custom_msg_req ++{ ++ u32_l cmd; ++ u32_l len; ++ u32_l flags; ++ u32_l buf[1]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_CUSTOM_MSG_CFM message. ++struct dbg_custom_msg_cfm ++{ ++ u32_l cmd; ++ u32_l len; ++ u32_l status; ++ u32_l buf[1]; ++}; ++ ++typedef struct dbg_custom_msg_cfm dbg_custom_msg_ind_t; ++#endif ++ ++/// Structure containing the parameters of the @ref DBG_SET_MOD_FILTER_REQ message. ++struct dbg_set_mod_filter_req { ++ /// Bit field indicating for each module if the traces are enabled or not ++ u32_l mod_filter; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_SEV_MOD_FILTER_REQ message. ++struct dbg_set_sev_filter_req { ++ /// Bit field indicating the severity threshold for the traces ++ u32_l sev_filter; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_GET_SYS_STAT_CFM message. ++struct dbg_get_sys_stat_cfm { ++ /// Time spent in CPU sleep since last reset of the system statistics ++ u32_l cpu_sleep_time; ++ /// Time spent in DOZE since last reset of the system statistics ++ u32_l doze_time; ++ /// Total time spent since last reset of the system statistics ++ u32_l stats_time; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_REQ message. ++struct dbg_mem_block_write_req { ++ u32_l memaddr; ++ u32_l memsize; ++ u32_l memdata[1024 / sizeof(u32_l)]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_CFM message. ++struct dbg_mem_block_write_cfm { ++ u32_l wstatus; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_READ_REQ message. ++struct dbg_mem_block_read_req ++{ ++ u32_l memaddr; ++ u32_l memsize; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_READ_CFM message. ++struct dbg_mem_block_read_cfm ++{ ++ u32_l memaddr; ++ u32_l memsize; ++ u32_l memdata[1024 / sizeof(u32_l)]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_REQ message. ++struct dbg_start_app_req { ++ u32_l bootaddr; ++ u32_l boottype; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_CFM message. ++struct dbg_start_app_cfm { ++ u32_l bootstatus; ++}; ++ ++enum { ++ HOST_START_APP_AUTO = 1, ++ HOST_START_APP_CUSTOM, ++ HOST_START_APP_FNCALL = 4, ++ HOST_START_APP_DUMMY = 5, ++}; ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For TDLS messages ++/////////////////////////////////////////////////////////////////////////////// ++ ++/// List of messages related to the task. ++enum tdls_msg_tag { ++ /// TDLS channel Switch Request. ++ TDLS_CHAN_SWITCH_REQ = LMAC_FIRST_MSG(TASK_TDLS), ++ /// TDLS channel switch confirmation. ++ TDLS_CHAN_SWITCH_CFM, ++ /// TDLS channel switch indication. ++ TDLS_CHAN_SWITCH_IND, ++ /// TDLS channel switch to base channel indication. ++ TDLS_CHAN_SWITCH_BASE_IND, ++ /// TDLS cancel channel switch request. ++ TDLS_CANCEL_CHAN_SWITCH_REQ, ++ /// TDLS cancel channel switch confirmation. ++ TDLS_CANCEL_CHAN_SWITCH_CFM, ++ /// TDLS peer power save indication. ++ TDLS_PEER_PS_IND, ++ /// TDLS peer traffic indication request. ++ TDLS_PEER_TRAFFIC_IND_REQ, ++ /// TDLS peer traffic indication confirmation. ++ TDLS_PEER_TRAFFIC_IND_CFM, ++ ++#ifdef CONFIG_SDIO_BT ++ TDLS_SDIO_BT_SEND_REQ = LMAC_FIRST_MSG(TASK_TDLS)+16, ++ TDLS_SDIO_BT_SEND_CFM, ++ TDLS_SDIO_BT_RECV_IND, ++#endif ++ /// MAX number of messages ++ TDLS_MAX ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_REQ message ++struct tdls_chan_switch_req { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ /// MAC address of the TDLS station ++ struct mac_addr peer_mac_addr; ++ bool_l initiator; ++ /// Band (2.4GHz or 5GHz) ++ u8_l band; ++ /// Channel type: 20,40,80,160 or 80+80 MHz ++ u8_l type; ++ /// Frequency for Primary 20MHz channel (in MHz) ++ u16_l prim20_freq; ++ /// Frequency for Center of the contiguous channel or center of Primary 80+80 ++ u16_l center1_freq; ++ /// Frequency for Center of the non-contiguous secondary 80+80 ++ u16_l center2_freq; ++ /// TX power (in dBm) ++ s8_l tx_power; ++ /// Operating class ++ u8_l op_class; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CANCEL_CHAN_SWITCH_REQ message ++struct tdls_cancel_chan_switch_req { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ /// MAC address of the TDLS station ++ struct mac_addr peer_mac_addr; ++}; ++ ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_CFM message ++struct tdls_chan_switch_cfm { ++ /// Status of the operation ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CANCEL_CHAN_SWITCH_CFM message ++struct tdls_cancel_chan_switch_cfm { ++ /// Status of the operation ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_IND message ++struct tdls_chan_switch_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// Channel Context Index ++ u8_l chan_ctxt_index; ++ /// Status of the operation ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_BASE_IND message ++struct tdls_chan_switch_base_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// Channel Context index ++ u8_l chan_ctxt_index; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_PEER_PS_IND message ++struct tdls_peer_ps_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ /// MAC ADDR of the TDLS STA ++ struct mac_addr peer_mac_addr; ++ /// Flag to indicate if the TDLS peer is going to sleep ++ bool ps_on; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_PEER_TRAFFIC_IND_REQ message ++struct tdls_peer_traffic_ind_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ // MAC ADDR of the TDLS STA ++ struct mac_addr peer_mac_addr; ++ /// Dialog token ++ u8_l dialog_token; ++ /// TID of the latest MPDU transmitted over the TDLS direct link to the TDLS STA ++ u8_l last_tid; ++ /// Sequence number of the latest MPDU transmitted over the TDLS direct link ++ /// to the TDLS STA ++ u16_l last_sn; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_PEER_TRAFFIC_IND_CFM message ++struct tdls_peer_traffic_ind_cfm { ++ /// Status of the operation ++ u8_l status; ++}; ++ ++ ++#endif // LMAC_MSG_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h +new file mode 100644 +index 000000000000..83b112290409 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h +@@ -0,0 +1,62 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file co_types.h ++ * ++ * @brief This file replaces the need to include stdint or stdbool typical headers, ++ * which may not be available in all toolchains, and adds new types ++ * ++ * Copyright (C) RivieraWaves 2009-2019 ++ * ++ * $Rev: $ ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _LMAC_INT_H_ ++#define _LMAC_INT_H_ ++ ++ ++/** ++ **************************************************************************************** ++ * @addtogroup CO_INT ++ * @ingroup COMMON ++ * @brief Common integer standard types (removes use of stdint) ++ * ++ * @{ ++ **************************************************************************************** ++ */ ++ ++ ++/* ++ * DEFINES ++ **************************************************************************************** ++ */ ++ ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++#include ++#else ++#include ++#endif ++ ++#ifdef CONFIG_RWNX_TL4 ++typedef uint16_t u8_l; ++typedef int16_t s8_l; ++typedef uint16_t bool_l; ++#else ++typedef uint8_t u8_l; ++typedef int8_t s8_l; ++typedef bool bool_l; ++#endif ++typedef uint16_t u16_l; ++typedef int16_t s16_l; ++typedef uint32_t u32_l; ++typedef int32_t s32_l; ++typedef uint64_t u64_l; ++ ++ ++ ++/// @} CO_INT ++#endif // _LMAC_INT_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c +new file mode 100644 +index 000000000000..3d7b65375adb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c +@@ -0,0 +1,161 @@ ++#include ++#include "md5.h" ++ ++unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; ++ ++void MD5Init(MD5_CTX *context) ++{ ++ context->count[0] = 0; ++ context->count[1] = 0; ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xEFCDAB89; ++ context->state[2] = 0x98BADCFE; ++ context->state[3] = 0x10325476; ++} ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) ++{ ++ unsigned int i = 0,index = 0,partlen = 0; ++ index = (context->count[0] >> 3) & 0x3F; ++ partlen = 64 - index; ++ context->count[0] += inputlen << 3; ++ if(context->count[0] < (inputlen << 3)) ++ context->count[1]++; ++ context->count[1] += inputlen >> 29; ++ ++ if(inputlen >= partlen) ++ { ++ memcpy(&context->buffer[index],input,partlen); ++ MD5Transform(context->state,context->buffer); ++ for(i = partlen;i+64 <= inputlen;i+=64) ++ MD5Transform(context->state,&input[i]); ++ index = 0; ++ } ++ else ++ { ++ i = 0; ++ } ++ memcpy(&context->buffer[index],&input[i],inputlen-i); ++} ++void MD5Final(MD5_CTX *context,unsigned char digest[16]) ++{ ++ unsigned int index = 0,padlen = 0; ++ unsigned char bits[8]; ++ index = (context->count[0] >> 3) & 0x3F; ++ padlen = (index < 56)?(56-index):(120-index); ++ MD5Encode(bits,context->count,8); ++ MD5Update(context,PADDING,padlen); ++ MD5Update(context,bits,8); ++ MD5Encode(digest,context->state,16); ++} ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[j] = input[i] & 0xFF; ++ output[j+1] = (input[i] >> 8) & 0xFF; ++ output[j+2] = (input[i] >> 16) & 0xFF; ++ output[j+3] = (input[i] >> 24) & 0xFF; ++ i++; ++ j+=4; ++ } ++} ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[i] = (input[j]) | ++ (input[j+1] << 8) | ++ (input[j+2] << 16) | ++ (input[j+3] << 24); ++ i++; ++ j+=4; ++ } ++} ++void MD5Transform(unsigned int state[4],unsigned char block[64]) ++{ ++ unsigned int a = state[0]; ++ unsigned int b = state[1]; ++ unsigned int c = state[2]; ++ unsigned int d = state[3]; ++ unsigned int x[64]; ++ MD5Decode(x,block,64); ++ FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ ++ FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ ++ FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ ++ FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ ++ FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ ++ FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ ++ FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ ++ FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ ++ FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ ++ FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ ++ FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ ++ FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ ++ FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ ++ FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ ++ FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ ++ FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ ++ ++ /* Round 2 */ ++ GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ ++ GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ ++ GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ ++ GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ ++ GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ ++ GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ ++ GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ ++ GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ ++ GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ ++ GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ ++ GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ ++ GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ ++ GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ ++ GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ ++ GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ ++ GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ ++ ++ /* Round 3 */ ++ HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ ++ HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ ++ HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ ++ HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ ++ HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ ++ HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ ++ HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ ++ HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ ++ HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ ++ HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ ++ HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ ++ HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ ++ HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ ++ HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ ++ HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ ++ HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ ++ ++ /* Round 4 */ ++ II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ ++ II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ ++ II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ ++ II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ ++ II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ ++ II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ ++ II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ ++ II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ ++ II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ ++ II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ ++ II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ ++ II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ ++ II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ ++ II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ ++ II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ ++ II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h +new file mode 100644 +index 000000000000..6ed5c0f8e886 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h +@@ -0,0 +1,48 @@ ++#ifndef MD5_H ++#define MD5_H ++ ++typedef struct ++{ ++ unsigned int count[2]; ++ unsigned int state[4]; ++ unsigned char buffer[64]; ++}MD5_CTX; ++ ++ ++#define F(x,y,z) ((x & y) | (~x & z)) ++#define G(x,y,z) ((x & z) | (y & ~z)) ++#define H(x,y,z) (x^y^z) ++#define I(x,y,z) (y ^ (x | ~z)) ++#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) ++#define FF(a,b,c,d,x,s,ac) \ ++ { \ ++ a += F(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define GG(a,b,c,d,x,s,ac) \ ++ { \ ++ a += G(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define HH(a,b,c,d,x,s,ac) \ ++ { \ ++ a += H(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define II(a,b,c,d,x,s,ac) \ ++ { \ ++ a += I(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++void MD5Init(MD5_CTX *context); ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); ++void MD5Final(MD5_CTX *context,unsigned char digest[16]); ++void MD5Transform(unsigned int state[4],unsigned char block[64]); ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h +new file mode 100644 +index 000000000000..568146624cee +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h +@@ -0,0 +1,148 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file reg_access.h ++ * ++ * @brief Definitions and macros for MAC HW and platform register accesses ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef REG_ACCESS_H_ ++#define REG_ACCESS_H_ ++ ++/***************************************************************************** ++ * Addresses within RWNX_ADDR_SYSTEM ++ *****************************************************************************/ ++/* Shard RAM */ ++#define SHARED_RAM_START_ADDR 0x00000000 ++ ++/* IPC registers */ ++#define IPC_REG_BASE_ADDR 0x00800000 ++ ++/* System Controller Registers */ ++#define SYSCTRL_SIGNATURE_ADDR 0x00900000 ++// old diag register name ++#define SYSCTRL_DIAG_CONF_ADDR 0x00900068 ++#define SYSCTRL_PHYDIAG_CONF_ADDR 0x00900074 ++#define SYSCTRL_RIUDIAG_CONF_ADDR 0x00900078 ++// new diag register name ++#define SYSCTRL_DIAG_CONF0 0x00900064 ++#define SYSCTRL_DIAG_CONF1 0x00900068 ++#define SYSCTRL_DIAG_CONF2 0x00900074 ++#define SYSCTRL_DIAG_CONF3 0x00900078 ++#define SYSCTRL_MISC_CNTL_ADDR 0x009000E0 ++#define BOOTROM_ENABLE BIT(4) ++#define FPGA_B_RESET BIT(1) ++#define SOFT_RESET BIT(0) ++ ++/* MAC platform */ ++#define NXMAC_VERSION_1_ADDR 0x00B00004 ++#define NXMAC_MU_MIMO_TX_BIT BIT(19) ++#define NXMAC_BFMER_BIT BIT(18) ++#define NXMAC_BFMEE_BIT BIT(17) ++#define NXMAC_MAC_80211MH_FORMAT_BIT BIT(16) ++#define NXMAC_COEX_BIT BIT(14) ++#define NXMAC_WAPI_BIT BIT(13) ++#define NXMAC_TPC_BIT BIT(12) ++#define NXMAC_VHT_BIT BIT(11) ++#define NXMAC_HT_BIT BIT(10) ++#define NXMAC_RCE_BIT BIT(8) ++#define NXMAC_CCMP_BIT BIT(7) ++#define NXMAC_TKIP_BIT BIT(6) ++#define NXMAC_WEP_BIT BIT(5) ++#define NXMAC_SECURITY_BIT BIT(4) ++#define NXMAC_SME_BIT BIT(3) ++#define NXMAC_HCCA_BIT BIT(2) ++#define NXMAC_EDCA_BIT BIT(1) ++#define NXMAC_QOS_BIT BIT(0) ++ ++#define NXMAC_RX_CNTRL_ADDR 0x00B00060 ++#define NXMAC_EN_DUPLICATE_DETECTION_BIT BIT(31) ++#define NXMAC_ACCEPT_UNKNOWN_BIT BIT(30) ++#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT BIT(29) ++#define NXMAC_ACCEPT_QO_S_NULL_BIT BIT(28) ++#define NXMAC_ACCEPT_QCFWO_DATA_BIT BIT(27) ++#define NXMAC_ACCEPT_Q_DATA_BIT BIT(26) ++#define NXMAC_ACCEPT_CFWO_DATA_BIT BIT(25) ++#define NXMAC_ACCEPT_DATA_BIT BIT(24) ++#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT BIT(23) ++#define NXMAC_ACCEPT_CF_END_BIT BIT(22) ++#define NXMAC_ACCEPT_ACK_BIT BIT(21) ++#define NXMAC_ACCEPT_CTS_BIT BIT(20) ++#define NXMAC_ACCEPT_RTS_BIT BIT(19) ++#define NXMAC_ACCEPT_PS_POLL_BIT BIT(18) ++#define NXMAC_ACCEPT_BA_BIT BIT(17) ++#define NXMAC_ACCEPT_BAR_BIT BIT(16) ++#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT BIT(15) ++#define NXMAC_ACCEPT_BFMEE_FRAMES_BIT BIT(14) ++#define NXMAC_ACCEPT_ALL_BEACON_BIT BIT(13) ++#define NXMAC_ACCEPT_NOT_EXPECTED_BA_BIT BIT(12) ++#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_BIT BIT(11) ++#define NXMAC_ACCEPT_BEACON_BIT BIT(10) ++#define NXMAC_ACCEPT_PROBE_RESP_BIT BIT(9) ++#define NXMAC_ACCEPT_PROBE_REQ_BIT BIT(8) ++#define NXMAC_ACCEPT_MY_UNICAST_BIT BIT(7) ++#define NXMAC_ACCEPT_UNICAST_BIT BIT(6) ++#define NXMAC_ACCEPT_ERROR_FRAMES_BIT BIT(5) ++#define NXMAC_ACCEPT_OTHER_BSSID_BIT BIT(4) ++#define NXMAC_ACCEPT_BROADCAST_BIT BIT(3) ++#define NXMAC_ACCEPT_MULTICAST_BIT BIT(2) ++#define NXMAC_DONT_DECRYPT_BIT BIT(1) ++#define NXMAC_EXC_UNENCRYPTED_BIT BIT(0) ++ ++#define NXMAC_DEBUG_PORT_SEL_ADDR 0x00B00510 ++#define NXMAC_SW_SET_PROFILING_ADDR 0x00B08564 ++#define NXMAC_SW_CLEAR_PROFILING_ADDR 0x00B08568 ++ ++/* Modem Status */ ++#define MDM_HDMCONFIG_ADDR 0x00C00000 ++ ++/* Clock gating configuration */ ++#define MDM_MEMCLKCTRL0_ADDR 0x00C00848 ++#define MDM_CLKGATEFCTRL0_ADDR 0x00C00874 ++#define CRM_CLKGATEFCTRL0_ADDR 0x00940010 ++ ++/* AGC (trident) */ ++#define AGC_RWNXAGCCNTL_ADDR 0x00C02060 ++ ++/* LDPC RAM*/ ++#define PHY_LDPC_RAM_ADDR 0x00C09000 ++ ++/* FCU (elma )*/ ++#define FCU_RWNXFCAGCCNTL_ADDR 0x00C09034 ++ ++/* AGC RAM */ ++#define PHY_AGC_UCODE_ADDR 0x00C0A000 ++ ++/* RIU */ ++#define RIU_RWNXVERSION_ADDR 0x00C0B000 ++#define RIU_RWNXDYNAMICCONFIG_ADDR 0x00C0B008 ++#define RIU_AGCMEMBISTSTAT_ADDR 0x00C0B238 ++#define RIU_AGCMEMSIGNATURESTAT_ADDR 0x00C0B23C ++#define RIU_RWNXAGCCNTL_ADDR 0x00C0B390 ++ ++/* FCU RAM */ ++#define PHY_FCU_UCODE_ADDR 0x00C0E000 ++ ++/* RF ITF */ ++#define FPGAB_MPIF_SEL_ADDR 0x00C10030 ++#define RF_V6_DIAGPORT_CONF1_ADDR 0x00C10010 ++#define RF_v6_PHYDIAG_CONF1_ADDR 0x00C10018 ++ ++#define RF_V7_DIAGPORT_CONF1_ADDR 0x00F10010 ++#define RF_v7_PHYDIAG_CONF1_ADDR 0x00F10018 ++ ++/***************************************************************************** ++ * Macros for generated register files ++ *****************************************************************************/ ++/* Macros for IPC registers access (used in reg_ipc_app.h) */ ++#define REG_IPC_APP_RD(env, INDEX) \ ++ (*(volatile u32 *)((u8 *)env + IPC_REG_BASE_ADDR + 4 * (INDEX))) ++ ++#define REG_IPC_APP_WR(env, INDEX, value) \ ++ (*(volatile u32 *)((u8 *)env + IPC_REG_BASE_ADDR + 4 * (INDEX)) = value) ++ ++#endif /* REG_ACCESS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c +new file mode 100644 +index 000000000000..260a9d27468e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c +@@ -0,0 +1,2914 @@ ++#include ++#include ++#include ++ ++//#include "regdb.h" ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++#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_antenna_gain = DBI_TO_MBI(gain),\ ++ .power_rule.max_eirp = DBM_TO_MBM(eirp), \ ++ .flags = reg_flags, \ ++} ++#define NL80211_RRF_AUTO_BW 0 ++#endif ++ ++static const struct ieee80211_regdomain regdom_00 = { ++ .n_reg_rules = 2, ++ .alpha2 = "00", ++ .reg_rules = { ++ // 1...14 ++ REG_RULE(2390 - 10, 2510 + 10, 40, 0, 20, 0), ++ // 36...165 ++ REG_RULE(5150 - 10, 5970 + 10, 80, 0, 20, 0), ++ } ++ ++#if 0 ++ .alpha2 = "00", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 20, 0, 0), ++ //REG_RULE_EXT(2457, 2482, 40, 0, 20, 0, ++ // NL80211_RRF_NO_IR | 0), ++ REG_RULE_EXT(2474, 2494, 20, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_NO_OFDM | 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, ++ NL80211_RRF_NO_IR | 0), ++ }, ++ .n_reg_rules = 6 ++#endif ++}; ++ ++static const struct ieee80211_regdomain regdom_AD = { ++ .alpha2 = "AD", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5710, 80, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AE = { ++ .alpha2 = "AE", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ //REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AF = { ++ .alpha2 = "AF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AI = { ++ .alpha2 = "AI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AL = { ++ .alpha2 = "AL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AM = { ++ .alpha2 = "AM", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 18, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 18, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_AN = { ++ .alpha2 = "AN", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AR = { ++ .alpha2 = "AR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ //REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ // NL80211_RRF_AUTO_BW | 0), ++ //REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ // NL80211_RRF_DFS | ++ // NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5270, 5330, 40, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ //REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ // NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_AS = { ++ .alpha2 = "AS", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AT = { ++ .alpha2 = "AT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AU = { ++ .alpha2 = "AU", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AW = { ++ .alpha2 = "AW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AZ = { ++ .alpha2 = "AZ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 18, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 18, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_BA = { ++ .alpha2 = "BA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BB = { ++ .alpha2 = "BB", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BD = { ++ .alpha2 = "BD", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_BE = { ++ .alpha2 = "BE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BF = { ++ .alpha2 = "BF", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BG = { ++ .alpha2 = "BG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BH = { ++ .alpha2 = "BH", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BL = { ++ .alpha2 = "BL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BM = { ++ .alpha2 = "BM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BN = { ++ .alpha2 = "BN", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BO = { ++ .alpha2 = "BO", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_BR = { ++ .alpha2 = "BR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BS = { ++ .alpha2 = "BS", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BT = { ++ .alpha2 = "BT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BY = { ++ .alpha2 = "BY", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BZ = { ++ .alpha2 = "BZ", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_CA = { ++ .alpha2 = "CA", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CF = { ++ .alpha2 = "CF", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 40, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 40, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 40, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 40, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CH = { ++ .alpha2 = "CH", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CI = { ++ .alpha2 = "CI", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CL = { ++ .alpha2 = "CL", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_CN = { ++ .alpha2 = "CN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ REG_RULE_EXT(57240, 59400, 2160, 0, 28, 0, 0), ++ REG_RULE_EXT(59400, 63720, 2160, 0, 44, 0, 0), ++ REG_RULE_EXT(63720, 65880, 2160, 0, 28, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_CO = { ++ .alpha2 = "CO", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CR = { ++ .alpha2 = "CR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CX = { ++ .alpha2 = "CX", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CY = { ++ .alpha2 = "CY", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CZ = { ++ .alpha2 = "CZ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5470, 5725, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_DE = { ++ .alpha2 = "DE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 20, 0, NL80211_RRF_AUTO_BW| ++ NL80211_RRF_NO_OUTDOOR| ++ 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, NL80211_RRF_AUTO_BW| ++ NL80211_RRF_DFS| ++ NL80211_RRF_NO_OUTDOOR| ++ 0), ++ REG_RULE_EXT(5470, 5725, 160, 0, 20, 0, NL80211_RRF_DFS| ++ 0), ++ REG_RULE_EXT(5725, 5875, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5945, 6425, 160, 0, 20, 0, NL80211_RRF_NO_OUTDOOR| ++ 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++ ++static const struct ieee80211_regdomain regdom_DK = { ++ .alpha2 = "DK", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_DM = { ++ .alpha2 = "DM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_DO = { ++ .alpha2 = "DO", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_DZ = { ++ .alpha2 = "DZ", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5670, 160, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_EC = { ++ .alpha2 = "EC", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_EE = { ++ .alpha2 = "EE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_EG = { ++ .alpha2 = "EG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_ES = { ++ .alpha2 = "ES", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5470, 5725, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_ET = { ++ .alpha2 = "ET", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_FI = { ++ .alpha2 = "FI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_FM = { ++ .alpha2 = "FM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_FR = { ++ .alpha2 = "FR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5695, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GB = { ++ .alpha2 = "GB", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GD = { ++ .alpha2 = "GD", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GE = { ++ .alpha2 = "GE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 18, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 18, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GF = { ++ .alpha2 = "GF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GH = { ++ .alpha2 = "GH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GL = { ++ .alpha2 = "GL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5710, 80, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GP = { ++ .alpha2 = "GP", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GR = { ++ .alpha2 = "GR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GT = { ++ .alpha2 = "GT", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GU = { ++ .alpha2 = "GU", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GY = { ++ .alpha2 = "GY", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_HK = { ++ .alpha2 = "HK", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HN = { ++ .alpha2 = "HN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HR = { ++ .alpha2 = "HR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HT = { ++ .alpha2 = "HT", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HU = { ++ .alpha2 = "HU", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_ID = { ++ .alpha2 = "ID", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 23, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_IE = { ++ .alpha2 = "IE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_IL = { ++ .alpha2 = "IL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_IN = { ++ .alpha2 = "IN", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_IR = { ++ .alpha2 = "IR", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_IS = { ++ .alpha2 = "IS", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_IT = { ++ .alpha2 = "IT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_JM = { ++ .alpha2 = "JM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_JO = { ++ .alpha2 = "JO", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 23, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_JP = { ++ .alpha2 = "JP", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(2474, 2494, 20, 0, 20, 0, ++ NL80211_RRF_NO_OFDM | 0), ++ REG_RULE_EXT(4910, 4990, 40, 0, 23, 0, 0), ++ REG_RULE_EXT(5030, 5090, 40, 0, 23, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_KE = { ++ .alpha2 = "KE", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, 0), ++ REG_RULE_EXT(5490, 5570, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5775, 40, 0, 23, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_KH = { ++ .alpha2 = "KH", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_KN = { ++ .alpha2 = "KN", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KP = { ++ .alpha2 = "KP", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5630, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KR = { ++ .alpha2 = "KR", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KW = { ++ .alpha2 = "KW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_KY = { ++ .alpha2 = "KY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KZ = { ++ .alpha2 = "KZ", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 1 ++}; ++ ++static const struct ieee80211_regdomain regdom_LB = { ++ .alpha2 = "LB", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LC = { ++ .alpha2 = "LC", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LI = { ++ .alpha2 = "LI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_LK = { ++ .alpha2 = "LK", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LS = { ++ .alpha2 = "LS", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_LT = { ++ .alpha2 = "LT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LU = { ++ .alpha2 = "LU", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LV = { ++ .alpha2 = "LV", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MA = { ++ .alpha2 = "MA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_MC = { ++ .alpha2 = "MC", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MD = { ++ .alpha2 = "MD", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_ME = { ++ .alpha2 = "ME", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MF = { ++ .alpha2 = "MF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MH = { ++ .alpha2 = "MH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MK = { ++ .alpha2 = "MK", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MN = { ++ .alpha2 = "MN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MO = { ++ .alpha2 = "MO", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 40, 0, 23, 0, 0), ++ REG_RULE_EXT(5250, 5330, 40, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 40, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MP = { ++ .alpha2 = "MP", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MQ = { ++ .alpha2 = "MQ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MR = { ++ .alpha2 = "MR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MT = { ++ .alpha2 = "MT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MU = { ++ .alpha2 = "MU", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MW = { ++ .alpha2 = "MW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MX = { ++ .alpha2 = "MX", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MY = { ++ .alpha2 = "MY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_NG = { ++ .alpha2 = "NG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, NL80211_RRF_DFS| ++ 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_NI = { ++ .alpha2 = "NI", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_NL = { ++ .alpha2 = "NL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_NO = { ++ .alpha2 = "NO", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5470, 5795, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5815, 5850, 35, 0, 33, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(17100, 17300, 200, 0, 20, 0, 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_NP = { ++ .alpha2 = "NP", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_NZ = { ++ .alpha2 = "NZ", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_OM = { ++ .alpha2 = "OM", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PA = { ++ .alpha2 = "PA", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PE = { ++ .alpha2 = "PE", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PF = { ++ .alpha2 = "PF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PG = { ++ .alpha2 = "PG", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PH = { ++ .alpha2 = "PH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PK = { ++ .alpha2 = "PK", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_PL = { ++ .alpha2 = "PL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PM = { ++ .alpha2 = "PM", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PR = { ++ .alpha2 = "PR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PT = { ++ .alpha2 = "PT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PW = { ++ .alpha2 = "PW", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PY = { ++ .alpha2 = "PY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_QA = { ++ .alpha2 = "QA", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_RE = { ++ .alpha2 = "RE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_RO = { ++ .alpha2 = "RO", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_RS = { ++ .alpha2 = "RS", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5350, 40, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | 0), ++ REG_RULE_EXT(5470, 5725, 20, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_RU = { ++ .alpha2 = "RU", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5650, 5730, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_RW = { ++ .alpha2 = "RW", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SA = { ++ .alpha2 = "SA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_SE = { ++ .alpha2 = "SE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SG = { ++ .alpha2 = "SG", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SI = { ++ .alpha2 = "SI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SK = { ++ .alpha2 = "SK", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SN = { ++ .alpha2 = "SN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SR = { ++ .alpha2 = "SR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_SV = { ++ .alpha2 = "SV", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_SY = { ++ .alpha2 = "SY", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 1 ++}; ++ ++static const struct ieee80211_regdomain regdom_TC = { ++ .alpha2 = "TC", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TD = { ++ .alpha2 = "TD", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_TG = { ++ .alpha2 = "TG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 40, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5710, 40, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_TH = { ++ .alpha2 = "TH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TN = { ++ .alpha2 = "TN", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_TR = { ++ .alpha2 = "TR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TT = { ++ .alpha2 = "TT", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TW = { ++ .alpha2 = "TW", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5270, 5330, 40, 0, 17, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5590, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5650, 5710, 40, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_UA = { ++ .alpha2 = "UA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | 0), ++ REG_RULE_EXT(5150, 5350, 40, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | 0), ++ REG_RULE_EXT(5490, 5670, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_UG = { ++ .alpha2 = "UG", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_US = { ++ .alpha2 = "US", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ // 1...13 ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ // 36 40 44 48 ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ // 52 56 60 64 ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ // 100 104 108 112 116 120 124 ++ REG_RULE_EXT(5490, 5650, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ // 128 132 136 140 ++ REG_RULE_EXT(5650, 5710, 40, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ // 149 153 157 161 165 ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ REG_RULE_EXT(57240, 63720, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_UY = { ++ .alpha2 = "UY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_UZ = { ++ .alpha2 = "UZ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_VC = { ++ .alpha2 = "VC", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_VE = { ++ .alpha2 = "VE", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_VI = { ++ .alpha2 = "VI", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_VN = { ++ .alpha2 = "VN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_VU = { ++ .alpha2 = "VU", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_WF = { ++ .alpha2 = "WF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_YE = { ++ .alpha2 = "YE", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 1 ++}; ++ ++static const struct ieee80211_regdomain regdom_YT = { ++ .alpha2 = "YT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_ZA = { ++ .alpha2 = "ZA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5695, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ /*REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0),*/ ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_ZW = { ++ .alpha2 = "ZW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++const struct ieee80211_regdomain *reg_regdb[] = { ++ ®dom_00, ++ ®dom_AD, ++ ®dom_AE, ++ ®dom_AF, ++ ®dom_AI, ++ ®dom_AL, ++ ®dom_AM, ++ ®dom_AN, ++ ®dom_AR, ++ ®dom_AS, ++ ®dom_AT, ++ ®dom_AU, ++ ®dom_AW, ++ ®dom_AZ, ++ ®dom_BA, ++ ®dom_BB, ++ ®dom_BD, ++ ®dom_BE, ++ ®dom_BF, ++ ®dom_BG, ++ ®dom_BH, ++ ®dom_BL, ++ ®dom_BM, ++ ®dom_BN, ++ ®dom_BO, ++ ®dom_BR, ++ ®dom_BS, ++ ®dom_BT, ++ ®dom_BY, ++ ®dom_BZ, ++ ®dom_CA, ++ ®dom_CF, ++ ®dom_CH, ++ ®dom_CI, ++ ®dom_CL, ++ ®dom_CN, ++ ®dom_CO, ++ ®dom_CR, ++ ®dom_CX, ++ ®dom_CY, ++ ®dom_CZ, ++ ®dom_DE, ++ ®dom_DK, ++ ®dom_DM, ++ ®dom_DO, ++ ®dom_DZ, ++ ®dom_EC, ++ ®dom_EE, ++ ®dom_EG, ++ ®dom_ES, ++ ®dom_ET, ++ ®dom_FI, ++ ®dom_FM, ++ ®dom_FR, ++ ®dom_GB, ++ ®dom_GD, ++ ®dom_GE, ++ ®dom_GF, ++ ®dom_GH, ++ ®dom_GL, ++ ®dom_GP, ++ ®dom_GR, ++ ®dom_GT, ++ ®dom_GU, ++ ®dom_GY, ++ ®dom_HK, ++ ®dom_HN, ++ ®dom_HR, ++ ®dom_HT, ++ ®dom_HU, ++ ®dom_ID, ++ ®dom_IE, ++ ®dom_IL, ++ ®dom_IN, ++ ®dom_IR, ++ ®dom_IS, ++ ®dom_IT, ++ ®dom_JM, ++ ®dom_JO, ++ ®dom_JP, ++ ®dom_KE, ++ ®dom_KH, ++ ®dom_KN, ++ ®dom_KP, ++ ®dom_KR, ++ ®dom_KW, ++ ®dom_KY, ++ ®dom_KZ, ++ ®dom_LB, ++ ®dom_LC, ++ ®dom_LI, ++ ®dom_LK, ++ ®dom_LS, ++ ®dom_LT, ++ ®dom_LU, ++ ®dom_LV, ++ ®dom_MA, ++ ®dom_MC, ++ ®dom_MD, ++ ®dom_ME, ++ ®dom_MF, ++ ®dom_MH, ++ ®dom_MK, ++ ®dom_MN, ++ ®dom_MO, ++ ®dom_MP, ++ ®dom_MQ, ++ ®dom_MR, ++ ®dom_MT, ++ ®dom_MU, ++ ®dom_MW, ++ ®dom_MX, ++ ®dom_MY, ++ ®dom_NG, ++ ®dom_NI, ++ ®dom_NL, ++ ®dom_NO, ++ ®dom_NP, ++ ®dom_NZ, ++ ®dom_OM, ++ ®dom_PA, ++ ®dom_PE, ++ ®dom_PF, ++ ®dom_PG, ++ ®dom_PH, ++ ®dom_PK, ++ ®dom_PL, ++ ®dom_PM, ++ ®dom_PR, ++ ®dom_PT, ++ ®dom_PW, ++ ®dom_PY, ++ ®dom_QA, ++ ®dom_RE, ++ ®dom_RO, ++ ®dom_RS, ++ ®dom_RU, ++ ®dom_RW, ++ ®dom_SA, ++ ®dom_SE, ++ ®dom_SG, ++ ®dom_SI, ++ ®dom_SK, ++ ®dom_SN, ++ ®dom_SR, ++ ®dom_SV, ++ ®dom_SY, ++ ®dom_TC, ++ ®dom_TD, ++ ®dom_TG, ++ ®dom_TH, ++ ®dom_TN, ++ ®dom_TR, ++ ®dom_TT, ++ ®dom_TW, ++ ®dom_UA, ++ ®dom_UG, ++ ®dom_US, ++ ®dom_UY, ++ ®dom_UZ, ++ ®dom_VC, ++ ®dom_VE, ++ ®dom_VI, ++ ®dom_VN, ++ ®dom_VU, ++ ®dom_WF, ++ ®dom_YE, ++ ®dom_YT, ++ ®dom_ZA, ++ ®dom_ZW, ++ NULL, ++}; ++ ++int reg_regdb_size = ARRAY_SIZE(reg_regdb); ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c +new file mode 100644 +index 000000000000..b39cf0f205a3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c +@@ -0,0 +1,105 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_bfmer.c ++ * ++ * @brief VHT Beamformer function definitions ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++/** ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++ ++#include ++#include "rwnx_bfmer.h" ++ ++/** ++ * FUNCTION DEFINITIONS ++ ****************************************************************************** ++ */ ++ ++int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ unsigned int length) ++{ ++ gfp_t flags; ++ struct rwnx_bfmer_report *bfm_report ; ++ ++ if (in_softirq()) ++ flags = GFP_ATOMIC; ++ else ++ flags = GFP_KERNEL; ++ ++ /* Allocate a structure that will contain the beamforming report */ ++ bfm_report = kmalloc(sizeof(*bfm_report) + length, flags); ++ ++ ++ /* Check report allocation */ ++ if (!bfm_report) { ++ /* Do not use beamforming */ ++ return -1; ++ } ++ ++ /* Store report length */ ++ bfm_report->length = length; ++ ++ /* ++ * Need to provide a Virtual Address to the MAC so that it can ++ * upload the received Beamforming Report in driver memory ++ */ ++ bfm_report->dma_addr = dma_map_single(rwnx_hw->dev, &bfm_report->report[0], ++ length, DMA_FROM_DEVICE); ++ ++ /* Check DMA mapping result */ ++ if (dma_mapping_error(rwnx_hw->dev, bfm_report->dma_addr)) { ++ /* Free allocated report */ ++ kfree(bfm_report); ++ /* And leave */ ++ return -1; ++ } ++ ++ /* Store report structure */ ++ rwnx_sta->bfm_report = bfm_report; ++ ++ return 0; ++} ++ ++void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) ++{ ++ /* Verify if a report has been allocated */ ++ if (rwnx_sta->bfm_report) { ++ struct rwnx_bfmer_report *bfm_report = rwnx_sta->bfm_report; ++ ++ /* Unmap DMA region */ ++ dma_unmap_single(rwnx_hw->dev, bfm_report->dma_addr, ++ bfm_report->length, DMA_BIDIRECTIONAL); ++ ++ /* Free allocated report structure and clean the pointer */ ++ kfree(bfm_report); ++ rwnx_sta->bfm_report = NULL; ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa) ++{ ++ int i; ++ u8 rx_nss = 0; ++ u16 rx_mcs_map = le16_to_cpu(vht_capa->supp_mcs.rx_mcs_map); ++ ++ for (i = 7; i >= 0; i--) { ++ u8 mcs = (rx_mcs_map >> (2 * i)) & 3; ++ ++ if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) { ++ rx_nss = i + 1; ++ break; ++ } ++ } ++ ++ return rx_nss; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h +new file mode 100644 +index 000000000000..4ce16496ef2e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h +@@ -0,0 +1,100 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_bfmer.h ++ * ++ * @brief VHT Beamformer function declarations ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_BFMER_H_ ++#define _RWNX_BFMER_H_ ++ ++/** ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++ ++/** ++ * DEFINES ++ ****************************************************************************** ++ */ ++ ++/// Maximal supported report length (in bytes) ++#define RWNX_BFMER_REPORT_MAX_LEN 2048 ++ ++/// Size of the allocated report space (twice the maximum report length) ++#define RWNX_BFMER_REPORT_SPACE_SIZE (RWNX_BFMER_REPORT_MAX_LEN * 2) ++ ++/** ++ * TYPE DEFINITIONS ++ ****************************************************************************** ++ */ ++ ++/* ++ * Structure used to store a beamforming report. ++ */ ++struct rwnx_bfmer_report { ++ dma_addr_t dma_addr; /* Virtual address provided to MAC for ++ DMA transfer of the Beamforming Report */ ++ unsigned int length; /* Report Length */ ++ u8 report[1]; /* Report to be used for VHT TX Beamforming */ ++}; ++ ++/** ++ * FUNCTION DECLARATIONS ++ ****************************************************************************** ++ */ ++ ++/** ++ ****************************************************************************** ++ * @brief Allocate memory aiming to contains the Beamforming Report received ++ * from a Beamformee capable capable. ++ * The providing length shall be large enough to contain the VHT Compressed ++ * Beaforming Report and the MU Exclusive part. ++ * It also perform a DMA Mapping providing an address to be provided to the HW ++ * responsible for the DMA transfer of the report. ++ * If successful a struct rwnx_bfmer_report object is allocated, it's address ++ * is stored in rwnx_sta->bfm_report. ++ * ++ * @param[in] rwnx_hw PHY Information ++ * @param[in] rwnx_sta Peer STA Information ++ * @param[in] length Memory size to be allocated ++ * ++ * @return 0 if operation is successful, else -1. ++ ****************************************************************************** ++ */ ++int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ unsigned int length); ++ ++/** ++ ****************************************************************************** ++ * @brief Free a previously allocated memory intended to be used for ++ * Beamforming Reports. ++ * ++ * @param[in] rwnx_hw PHY Information ++ * @param[in] rwnx_sta Peer STA Information ++ * ++ ****************************************************************************** ++ */ ++void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/** ++ ****************************************************************************** ++ * @brief Parse a Rx VHT-MCS map in order to deduce the maximum number of ++ * Spatial Streams supported by a beamformee. ++ * ++ * @param[in] vht_capa Received VHT Capability field. ++ * ++ ****************************************************************************** ++ */ ++u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#endif /* _RWNX_BFMER_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c +new file mode 100644 +index 000000000000..39a5a251482a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c +@@ -0,0 +1,239 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_configparse.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_cfgfile.h" ++ ++/** ++ * ++ */ ++static const char *rwnx_find_tag(const u8 *file_data, unsigned int file_size, ++ const char *tag_name, unsigned int tag_len) ++{ ++ unsigned int curr, line_start = 0, line_size; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Walk through all the lines of the configuration file */ ++ while (line_start < file_size) { ++ /* Search the end of the current line (or the end of the file) */ ++ for (curr = line_start; curr < file_size; curr++) ++ if (file_data[curr] == '\n') ++ break; ++ ++ /* Compute the line size */ ++ line_size = curr - line_start; ++ ++ /* Check if this line contains the expected tag */ ++ if ((line_size == (strlen(tag_name) + tag_len)) && ++ (!strncmp(&file_data[line_start], tag_name, strlen(tag_name)))) ++ return &file_data[line_start + strlen(tag_name)]; ++ ++ /* Move to next line */ ++ line_start = curr + 1; ++ } ++ ++ /* Tag not found */ ++ return NULL; ++} ++ ++/** ++ * Parse the Config file used at init time ++ */ ++int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_conf_file *config) ++{ ++ const struct firmware *config_fw; ++ u8 dflt_mac[ETH_ALEN] = { 0, 111, 111, 111, 111, 0 }; ++ int ret; ++ const u8 *tag_ptr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ret = request_firmware(&config_fw, filename, rwnx_hw->dev); ++ if (ret) { ++ printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); ++ return ret; ++ } ++ ++ /* Get MAC Address */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "MAC_ADDR=", strlen("00:00:00:00:00:00")); ++ if (tag_ptr != NULL) { ++ u8 *addr = config->mac_addr; ++ if (sscanf(tag_ptr, ++ "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ addr + 0, addr + 1, addr + 2, ++ addr + 3, addr + 4, addr + 5) != ETH_ALEN) ++ memcpy(config->mac_addr, dflt_mac, ETH_ALEN); ++ } else ++ memcpy(config->mac_addr, dflt_mac, ETH_ALEN); ++ ++ RWNX_DBG("MAC Address is:\n%pM\n", config->mac_addr); ++ ++ /* Release the configuration file */ ++ release_firmware(config_fw); ++ ++ return 0; ++} ++ ++/** ++ * Parse the Config file used at init time ++ */ ++int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_phy_conf_file *config, int path) ++{ ++ const struct firmware *config_fw; ++ int ret; ++ const u8 *tag_ptr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ret = request_firmware(&config_fw, filename, rwnx_hw->dev); ++ if (ret) { ++ printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); ++ return ret; ++ } ++ ++ /* Get Trident path mapping */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "TRD_PATH_MAPPING=", strlen("00")); ++ if (tag_ptr != NULL) { ++ u8 val; ++ if (sscanf(tag_ptr, "%hhx", &val) == 1) ++ config->trd.path_mapping = val; ++ else ++ config->trd.path_mapping = path; ++ } else ++ config->trd.path_mapping = path; ++ ++ RWNX_DBG("Trident path mapping is: %d\n", config->trd.path_mapping); ++ ++ /* Get DC offset compensation */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "TX_DC_OFF_COMP=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->trd.tx_dc_off_comp) != 1) ++ config->trd.tx_dc_off_comp = 0; ++ } else ++ config->trd.tx_dc_off_comp = 0; ++ ++ RWNX_DBG("TX DC offset compensation is: %08X\n", config->trd.tx_dc_off_comp); ++ ++ /* Get Karst TX IQ compensation value for path0 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[0]) != 1) ++ config->karst.tx_iq_comp_2_4G[0] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_2_4G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[0]); ++ ++ /* Get Karst TX IQ compensation value for path1 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[1]) != 1) ++ config->karst.tx_iq_comp_2_4G[1] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_2_4G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[1]); ++ ++ /* Get Karst RX IQ compensation value for path0 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[0]) != 1) ++ config->karst.rx_iq_comp_2_4G[0] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_2_4G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[0]); ++ ++ /* Get Karst RX IQ compensation value for path1 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[1]) != 1) ++ config->karst.rx_iq_comp_2_4G[1] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_2_4G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[1]); ++ ++ /* Get Karst TX IQ compensation value for path0 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_5G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[0]) != 1) ++ config->karst.tx_iq_comp_5G[0] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_5G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[0]); ++ ++ /* Get Karst TX IQ compensation value for path1 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_5G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[1]) != 1) ++ config->karst.tx_iq_comp_5G[1] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_5G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[1]); ++ ++ /* Get Karst RX IQ compensation value for path0 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_5G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[0]) != 1) ++ config->karst.rx_iq_comp_5G[0] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_5G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[0]); ++ ++ /* Get Karst RX IQ compensation value for path1 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_5G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[1]) != 1) ++ config->karst.rx_iq_comp_5G[1] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_5G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[1]); ++ ++ /* Get Karst default path */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_DEFAULT_PATH=", strlen("00")); ++ if (tag_ptr != NULL) { ++ u8 val; ++ if (sscanf(tag_ptr, "%hhx", &val) == 1) ++ config->karst.path_used = val; ++ else ++ config->karst.path_used = path; ++ } else ++ config->karst.path_used = path; ++ ++ RWNX_DBG("Karst default path is: %d\n", config->karst.path_used); ++ ++ /* Release the configuration file */ ++ release_firmware(config_fw); ++ ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h +new file mode 100644 +index 000000000000..7dc96fe5862b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h +@@ -0,0 +1,35 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_cfgfile.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_CFGFILE_H_ ++#define _RWNX_CFGFILE_H_ ++ ++/* ++ * Structure used to retrieve information from the Config file used at Initialization time ++ */ ++struct rwnx_conf_file { ++ u8 mac_addr[ETH_ALEN]; ++}; ++ ++/* ++ * Structure used to retrieve information from the PHY Config file used at Initialization time ++ */ ++struct rwnx_phy_conf_file { ++ struct phy_trd_cfg_tag trd; ++ struct phy_karst_cfg_tag karst; ++}; ++ ++int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_conf_file *config); ++ ++int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_phy_conf_file *config, int path); ++ ++#endif /* _RWNX_CFGFILE_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c +new file mode 100644 +index 000000000000..cdbe42c3f14c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c +@@ -0,0 +1,586 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.c ++ * ++ * Handles queueing (push to IPC, ack/cfm from IPC) of commands issued to ++ * LMAC FW ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++ ++#include "rwnx_cmds.h" ++#include "rwnx_defs.h" ++#include "rwnx_strs.h" ++//#define CREATE_TRACE_POINTS ++#include "rwnx_events.h" ++#include "aicwf_txrxif.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#else ++#include "aicwf_usb.h" ++#endif ++/** ++ * ++ */ ++extern int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++ ++void rwnx_cmd_free(struct rwnx_cmd *cmd); ++ ++static void cmd_dump(const struct rwnx_cmd *cmd) ++{ ++ printk(KERN_CRIT "tkn[%d] flags:%04x result:%3d cmd:%4d-%-24s - reqcfm(%4d-%-s)\n", ++ cmd->tkn, cmd->flags, cmd->result, cmd->id, RWNX_ID2STR(cmd->id), ++ cmd->reqid, cmd->reqid != (lmac_msg_id_t)-1 ? RWNX_ID2STR(cmd->reqid) : "none"); ++} ++ ++/** ++ * ++ */ ++static void cmd_complete(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ lockdep_assert_held(&cmd_mgr->lock); ++ ++ //list_del(&cmd->list); ++ //cmd_mgr->queue_sz--; ++ ++ cmd->flags |= RWNX_CMD_FLAG_DONE; ++ if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) { ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ } else { ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) { ++ cmd->result = 0; ++ complete(&cmd->complete); ++ } ++ } ++} ++ ++int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ bool defer_push = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef CREATE_TRACE_POINTS ++ trace_msg_send(cmd->id); ++#endif ++ spin_lock_bh(&cmd_mgr->lock); ++ ++ if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { ++ printk(KERN_CRIT"cmd queue crashed\n"); ++ cmd->result = -EPIPE; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EPIPE; ++ } ++ ++ #ifndef CONFIG_RWNX_FHOST ++ if (!list_empty(&cmd_mgr->cmds)) { ++ if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) { ++ printk(KERN_CRIT"Too many cmds (%d) already queued\n", ++ cmd_mgr->max_queue_sz); ++ cmd->result = -ENOMEM; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -ENOMEM; ++ } ++ } ++ #endif ++ ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ defer_push = true; ++ ++ if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM) ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM; ++ ++ cmd->tkn = cmd_mgr->next_tkn++; ++ cmd->result = -EINTR; ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ init_completion(&cmd->complete); ++ ++ list_add_tail(&cmd->list, &cmd_mgr->cmds); ++ cmd_mgr->queue_sz++; ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ WAKE_CMD_WORK(cmd_mgr); ++ return 0; ++} ++ ++#if 1 ++static void aic8800_start_system_reset_flow(struct aic_sdio_dev *aic) ++{ ++ int ret = 0; ++ char *event_string = "DHDISDOWN=1"; ++ char *envp[] = { event_string, NULL }; ++ printk(KERN_ERR "wlan error reset flow.\n"); ++ printk(KERN_ERR "send event.\n"); ++ ret=kobject_uevent_env(&aic->dev->kobj, KOBJ_CHANGE,envp); ++ if(!ret) ++ printk(KERN_ERR "wlan error event send.\n"); ++} ++#endif ++ ++static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ int ret; ++ struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); ++#endif ++ bool defer_push = false; ++ u8_l empty = 0; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef CREATE_TRACE_POINTS ++ trace_msg_send(cmd->id); ++#endif ++ if(cmd->e2a_msg != NULL) { ++ do { ++ if(cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) ++ break; ++ spin_lock_bh(&cmd_mgr->lock); ++ empty = list_empty(&cmd_mgr->cmds); ++ if(!empty) { ++ spin_unlock_bh(&cmd_mgr->lock); ++ if(in_softirq()) { ++ printk("in_softirq:check cmdqueue empty\n"); ++ mdelay(10); ++ } else { ++ printk("check cmdqueue empty\n"); ++ msleep(50); ++ } ++ } ++ } while(!empty);//wait for cmd queue empty ++ } else { ++ spin_lock_bh(&cmd_mgr->lock); ++ } ++ ++ if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { ++ printk(KERN_CRIT"cmd queue crashed\n"); ++ cmd->result = -EPIPE; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EPIPE; ++ } ++ ++ #ifndef CONFIG_RWNX_FHOST ++ if (!list_empty(&cmd_mgr->cmds)) { ++ struct rwnx_cmd *last; ++ ++ if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) { ++ printk(KERN_CRIT"Too many cmds (%d) already queued\n", ++ cmd_mgr->max_queue_sz); ++ cmd->result = -ENOMEM; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -ENOMEM; ++ } ++ last = list_entry(cmd_mgr->cmds.prev, struct rwnx_cmd, list); ++ if (last->flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_PUSH | RWNX_CMD_FLAG_WAIT_CFM)) { ++#if 0 // queue even NONBLOCK command. ++ if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) { ++ printk(KERN_CRIT"cmd queue busy\n"); ++ cmd->result = -EBUSY; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EBUSY; ++ } ++#endif ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ defer_push = true; ++ } ++ } ++ #endif ++ ++#if 0 ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_ACK; ++#endif ++ if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM) ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM; ++ ++ cmd->tkn = cmd_mgr->next_tkn++; ++ cmd->result = -EINTR; ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ init_completion(&cmd->complete); ++ ++ list_add_tail(&cmd->list, &cmd_mgr->cmds); ++ cmd_mgr->queue_sz++; ++ ++ if (cmd->a2e_msg->id == ME_TRAFFIC_IND_REQ ++ #ifdef AICWF_ARP_OFFLOAD ++ || cmd->a2e_msg->id == MM_SET_ARPOFFLOAD_REQ ++ #endif ++ ) { ++ defer_push = true; ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ //printk("defer push: tkn=%d\r\n", cmd->tkn); ++ } ++ ++ spin_unlock_bh(&cmd_mgr->lock); ++ if (!defer_push) { ++ //printk("queue:id=%x, param_len=%u\n",cmd->a2e_msg->id, cmd->a2e_msg->param_len); ++ #ifdef AICWF_SDIO_SUPPORT ++ aicwf_set_cmd_tx((void *)(sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ #else ++ aicwf_set_cmd_tx((void *)(usbdev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ #endif ++ //rwnx_ipc_msg_push(rwnx_hw, cmd, RWNX_CMD_A2EMSG_LEN(cmd->a2e_msg)); ++ ++ kfree(cmd->a2e_msg); ++ } else { ++ if(cmd_mgr->queue_sz <= 1){ ++ WAKE_CMD_WORK(cmd_mgr); ++ } ++ return 0; ++ } ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) { ++ #ifdef CONFIG_RWNX_FHOST ++ if (wait_for_completion_killable(&cmd->complete)) { ++ cmd->result = -EINTR; ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_complete(cmd_mgr, cmd); ++ spin_unlock_bh(&cmd_mgr->lock); ++ /* TODO: kill the cmd at fw level */ ++ } ++ #else ++ unsigned long tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz); ++ if (!wait_for_completion_timeout(&cmd->complete, tout)) { ++ printk(KERN_CRIT"cmd timed-out\n"); ++ #ifdef AICWF_SDIO_SUPPORT ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++ #endif ++ ++ aic8800_start_system_reset_flow(sdiodev); ++ ++ cmd_dump(cmd); ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED; ++ if (!(cmd->flags & RWNX_CMD_FLAG_DONE)) { ++ cmd->result = -ETIMEDOUT; ++ cmd_complete(cmd_mgr, cmd); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ } else { ++ spin_lock_bh(&cmd_mgr->lock); ++ list_del(&cmd->list); ++ cmd_mgr->queue_sz--; ++ spin_unlock_bh(&cmd_mgr->lock); ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ if (!list_empty(&cmd_mgr->cmds)) ++ WAKE_CMD_WORK(cmd_mgr); ++ } ++ #endif ++ } else { ++ cmd->result = 0; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ++ */ ++static int cmd_mgr_llind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ struct rwnx_cmd *cur, *acked = NULL, *next = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ if (!acked) { ++ if (cur->tkn == cmd->tkn) { ++ if (WARN_ON_ONCE(cur != cmd)) { ++ cmd_dump(cmd); ++ } ++ acked = cur; ++ continue; ++ } ++ } ++ if (cur->flags & RWNX_CMD_FLAG_WAIT_PUSH) { ++ next = cur; ++ break; ++ } ++ } ++ if (!acked) { ++ printk(KERN_CRIT "Error: acked cmd not found\n"); ++ } else { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) ++ cmd_complete(cmd_mgr, cmd); ++ } ++ ++ if (next) { ++ #if 0 //there is no ack ++ struct rwnx_hw *rwnx_hw = container_of(cmd_mgr, struct rwnx_hw, cmd_mgr); ++ next->flags &= ~RWNX_CMD_FLAG_WAIT_PUSH; ++ rwnx_ipc_msg_push(rwnx_hw, next, RWNX_CMD_A2EMSG_LEN(next->a2e_msg)); ++ kfree(next->a2e_msg); ++ #endif ++ } ++ spin_unlock(&cmd_mgr->lock); ++ ++ return 0; ++} ++ ++void cmd_mgr_task_process(struct work_struct *work) ++{ ++ struct rwnx_cmd_mgr *cmd_mgr = container_of(work, struct rwnx_cmd_mgr, cmdWork); ++ struct rwnx_cmd *cur, *next = NULL; ++ unsigned long tout; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ while (1) { ++ next = NULL; ++ spin_lock_bh(&cmd_mgr->lock); ++ ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ if (cur->flags & RWNX_CMD_FLAG_WAIT_PUSH) { //just judge the first ++ next = cur; ++ } ++ break; ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ if (next == NULL) ++ break; ++ ++ if (next) { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); ++#endif ++ next->flags &= ~RWNX_CMD_FLAG_WAIT_PUSH; ++ ++ //printk("cmd_process, cmd->id=%d, tkn=%d\r\n",next->reqid, next->tkn); ++ //rwnx_ipc_msg_push(rwnx_hw, next, RWNX_CMD_A2EMSG_LEN(next->a2e_msg)); ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_set_cmd_tx((void *)(sdiodev), next->a2e_msg, sizeof(struct lmac_msg) + next->a2e_msg->param_len); ++#else ++ aicwf_set_cmd_tx((void *)(usbdev), next->a2e_msg, sizeof(struct lmac_msg) + next->a2e_msg->param_len); ++#endif ++ kfree(next->a2e_msg); ++ ++ tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz); ++ if (!wait_for_completion_timeout(&next->complete, tout)) { ++ printk(KERN_CRIT"cmd timed-out\n"); ++#ifdef AICWF_SDIO_SUPPORT ++ if (aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 2) < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++#endif ++ aic8800_start_system_reset_flow(sdiodev); ++ ++ cmd_dump(next); ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED; ++ if (!(next->flags & RWNX_CMD_FLAG_DONE)) { ++ next->result = -ETIMEDOUT; ++ cmd_complete(cmd_mgr, next); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ } else { ++ spin_lock_bh(&cmd_mgr->lock); ++ list_del(&next->list); ++ cmd_mgr->queue_sz--; ++ spin_unlock_bh(&cmd_mgr->lock); ++ rwnx_cmd_free(next);//kfree(next); ++ } ++ } ++ } ++ ++} ++ ++ ++static int cmd_mgr_run_callback(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd, ++ struct rwnx_cmd_e2amsg *msg, msg_cb_fct cb) ++{ ++ int res; ++ ++ if (!cb) { ++ return 0; ++ } ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ //spin_lock_bh(&rwnx_hw->cb_lock); ++ res = cb(rwnx_hw, cmd, msg); ++ //spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ return res; ++} ++ ++/** ++ * ++ ++ */ ++static int cmd_mgr_msgind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd_e2amsg *msg, ++ msg_cb_fct cb) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); ++ struct rwnx_hw *rwnx_hw = sdiodev->rwnx_hw; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); ++ struct rwnx_hw *rwnx_hw = usbdev->rwnx_hw; ++#endif ++ struct rwnx_cmd *cmd, *pos; ++ bool found = false; ++ ++ // RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef CREATE_TRACE_POINTS ++ trace_msg_recv(msg->id); ++#endif ++ //printk("cmd->id=%x\n", msg->id); ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry_safe(cmd, pos, &cmd_mgr->cmds, list) { ++ if (cmd->reqid == msg->id && ++ (cmd->flags & RWNX_CMD_FLAG_WAIT_CFM)) { ++ ++ if (!cmd_mgr_run_callback(rwnx_hw, cmd, msg, cb)) { ++ found = true; ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_CFM; ++ ++ if (WARN((msg->param_len > RWNX_CMD_E2AMSG_LEN_MAX), ++ "Unexpect E2A msg len %d > %d\n", msg->param_len, ++ RWNX_CMD_E2AMSG_LEN_MAX)) { ++ msg->param_len = RWNX_CMD_E2AMSG_LEN_MAX; ++ } ++ ++ if (cmd->e2a_msg && msg->param_len) ++ memcpy(cmd->e2a_msg, &msg->param, msg->param_len); ++ ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) ++ cmd_complete(cmd_mgr, cmd); ++ ++ break; ++ } ++ } ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ if (!found) ++ cmd_mgr_run_callback(rwnx_hw, NULL, msg, cb); ++ ++ return 0; ++} ++ ++/** ++ * ++ */ ++static void cmd_mgr_print(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ RWNX_DBG("q_sz/max: %2d / %2d - next tkn: %d\n", ++ cmd_mgr->queue_sz, cmd_mgr->max_queue_sz, ++ cmd_mgr->next_tkn); ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ cmd_dump(cur); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++static void cmd_mgr_drain(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur, *nxt; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry_safe(cur, nxt, &cmd_mgr->cmds, list) { ++ list_del(&cur->list); ++ cmd_mgr->queue_sz--; ++ if (!(cur->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ complete(&cur->complete); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ INIT_LIST_HEAD(&cmd_mgr->cmds); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_INITED; ++ spin_lock_init(&cmd_mgr->lock); ++ cmd_mgr->max_queue_sz = RWNX_CMD_MAX_QUEUED; ++ cmd_mgr->queue = &cmd_mgr_queue; ++ cmd_mgr->print = &cmd_mgr_print; ++ cmd_mgr->drain = &cmd_mgr_drain; ++ cmd_mgr->llind = &cmd_mgr_llind; ++ cmd_mgr->msgind = &cmd_mgr_msgind; ++ ++ INIT_WORK(&cmd_mgr->cmdWork, cmd_mgr_task_process); ++ cmd_mgr->cmd_wq = create_singlethread_workqueue("cmd_wq"); ++ if (!cmd_mgr->cmd_wq) { ++ txrx_err("insufficient memory to create cmd workqueue.\n"); ++ return; ++ } ++} ++ ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ cmd_mgr->print(cmd_mgr); ++ cmd_mgr->drain(cmd_mgr); ++ cmd_mgr->print(cmd_mgr); ++ flush_workqueue(cmd_mgr->cmd_wq); ++ destroy_workqueue(cmd_mgr->cmd_wq); ++ memset(cmd_mgr, 0, sizeof(*cmd_mgr)); ++} ++ ++void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len) ++{ ++ u8 *buffer = NULL; ++ u16 index = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ struct aicwf_bus *bus = sdiodev->bus_if; ++#else ++ struct aic_usb_dev *usbdev = (struct aic_usb_dev *)dev; ++ struct aicwf_bus *bus = NULL; ++ if (!usbdev->state) { ++ printk("down msg \n"); ++ return; ++ } ++ bus = usbdev->bus_if; ++#endif ++ buffer = bus->cmd_buf; ++ ++ memset(buffer, 0, CMD_BUF_MAX); ++ buffer[0] = (len+4) & 0x00ff; ++ buffer[1] = ((len+4) >> 8) &0x0f; ++ buffer[2] = 0x11; ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ buffer[3] = 0x0; ++ else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ buffer[3] = crc8_ponl_107(&buffer[0], 3); // crc8 ++ index += 4; ++ //there is a dummy word ++ index += 4; ++ ++ //make sure little endian ++ put_u16(&buffer[index], msg->id); ++ index += 2; ++ put_u16(&buffer[index], msg->dest_id); ++ index += 2; ++ put_u16(&buffer[index], msg->src_id); ++ index += 2; ++ put_u16(&buffer[index], msg->param_len); ++ index += 2; ++ memcpy(&buffer[index], (u8 *)msg->param, msg->param_len); ++ ++ aicwf_bus_txmsg(bus, buffer, len + 8); ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h +new file mode 100644 +index 000000000000..d1ba11994193 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h +@@ -0,0 +1,124 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.h ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_CMDS_H_ ++#define _RWNX_CMDS_H_ ++ ++#include ++#include ++#include ++#include "lmac_msg.h" ++ ++#ifdef CONFIG_RWNX_SDM ++#define RWNX_80211_CMD_TIMEOUT_MS (20 * 300) ++#elif defined(CONFIG_RWNX_FHOST) ++#define RWNX_80211_CMD_TIMEOUT_MS (10000) ++#else ++#ifdef AICWF_USB_SUPPORT ++#define RWNX_80211_CMD_TIMEOUT_MS 2000//300 ++#else ++#define RWNX_80211_CMD_TIMEOUT_MS 6000//500//300 ++#endif ++#endif ++ ++#define RWNX_CMD_FLAG_NONBLOCK BIT(0) ++#define RWNX_CMD_FLAG_REQ_CFM BIT(1) ++#define RWNX_CMD_FLAG_WAIT_PUSH BIT(2) ++#define RWNX_CMD_FLAG_WAIT_ACK BIT(3) ++#define RWNX_CMD_FLAG_WAIT_CFM BIT(4) ++#define RWNX_CMD_FLAG_DONE BIT(5) ++/* ATM IPC design makes it possible to get the CFM before the ACK, ++ * otherwise this could have simply been a state enum */ ++#define RWNX_CMD_WAIT_COMPLETE(flags) \ ++ (!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM))) ++ ++#define RWNX_CMD_MAX_QUEUED 16 ++ ++#ifdef CONFIG_RWNX_FHOST ++#include "ipc_fhost.h" ++#define rwnx_cmd_e2amsg ipc_fhost_msg ++#define rwnx_cmd_a2emsg ipc_fhost_msg ++#define RWNX_CMD_A2EMSG_LEN(m) (m->param_len) ++#define RWNX_CMD_E2AMSG_LEN_MAX IPC_FHOST_MSG_BUF_SIZE ++struct rwnx_term_stream; ++ ++#else /* !CONFIG_RWNX_FHOST*/ ++#include "ipc_shared.h" ++#define rwnx_cmd_e2amsg ipc_e2a_msg ++#define rwnx_cmd_a2emsg lmac_msg ++#define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len) ++#define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4) ++ ++#endif /* CONFIG_RWNX_FHOST*/ ++ ++struct rwnx_hw; ++struct rwnx_cmd; ++typedef int (*msg_cb_fct)(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd, ++ struct rwnx_cmd_e2amsg *msg); ++static inline void put_u16(u8 *buf, u16 data) ++{ ++ buf[0] = (u8)(data&0x00ff); ++ buf[1] = (u8)((data >> 8)&0x00ff); ++} ++ ++enum rwnx_cmd_mgr_state { ++ RWNX_CMD_MGR_STATE_DEINIT, ++ RWNX_CMD_MGR_STATE_INITED, ++ RWNX_CMD_MGR_STATE_CRASHED, ++}; ++ ++struct rwnx_cmd { ++ struct list_head list; ++ lmac_msg_id_t id; ++ lmac_msg_id_t reqid; ++ struct rwnx_cmd_a2emsg *a2e_msg; ++ char *e2a_msg; ++ u32 tkn; ++ u16 flags; ++ ++ struct completion complete; ++ u32 result; ++ u8 used; ++ int array_id; ++ #ifdef CONFIG_RWNX_FHOST ++ struct rwnx_term_stream *stream; ++ #endif ++}; ++ ++struct rwnx_cmd_mgr { ++ enum rwnx_cmd_mgr_state state; ++ spinlock_t lock; ++ u32 next_tkn; ++ u32 queue_sz; ++ u32 max_queue_sz; ++ ++ struct list_head cmds; ++ ++ int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct); ++ void (*print)(struct rwnx_cmd_mgr *); ++ void (*drain)(struct rwnx_cmd_mgr *); ++ ++ struct work_struct cmdWork; ++ struct workqueue_struct *cmd_wq; ++}; ++ ++#define WAKE_CMD_WORK(cmd_mgr) \ ++ do { \ ++ queue_work((cmd_mgr)->cmd_wq, &cmd_mgr->cmdWork); \ ++ } while (0) ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr); ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr); ++int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd); ++void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len); ++ ++#endif /* _RWNX_CMDS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h +new file mode 100644 +index 000000000000..49f5cdd032a2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h +@@ -0,0 +1,448 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_compat.h ++ * ++ * Ensure driver compilation for linux 3.16 to 3.19 ++ * ++ * To avoid too many #if LINUX_VERSION_CODE if the code, when prototype change ++ * between different kernel version: ++ * - For external function, define a macro whose name is the function name with ++ * _compat suffix and prototype (actually the number of parameter) of the ++ * latest version. Then latest version this macro simply call the function ++ * and for older kernel version it call the function adapting the api. ++ * - For internal function (e.g. cfg80211_ops) do the same but the macro name ++ * doesn't need to have the _compat suffix when the function is not used ++ * directly by the driver ++ * ++ * Copyright (C) RivieraWaves 2018 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_COMPAT_H_ ++#define _RWNX_COMPAT_H_ ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) ++#error "Minimum kernel version supported is 3.10" ++#endif ++ ++/* Generic */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) ++#define __bf_shf(x) (__builtin_ffsll(x) - 1) ++#define FIELD_PREP(_mask, _val) \ ++ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) ++#else ++#include ++#endif ++ ++/* CFG80211 */ ++ ++//because android kernel 5.15 uses kernel 6.0 or 6.1 kernel api ++#ifdef ANDROID_PLATFORM ++#define HIGH_KERNEL_VERSION KERNEL_VERSION(5, 15, 41) ++#define HIGH_KERNEL_VERSION2 KERNEL_VERSION(5, 15, 41) ++#define HIGH_KERNEL_VERSION3 KERNEL_VERSION(5, 15, 104) ++#define HIGH_KERNEL_VERSION4 KERNEL_VERSION(6, 1, 0) ++#else ++#define HIGH_KERNEL_VERSION KERNEL_VERSION(6, 0, 0) ++#define HIGH_KERNEL_VERSION2 KERNEL_VERSION(6, 1, 0) ++#define HIGH_KERNEL_VERSION3 KERNEL_VERSION(6, 3, 0) ++#define HIGH_KERNEL_VERSION4 KERNEL_VERSION(6, 3, 0) ++#endif ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 60) ++#define IEEE80211_MAX_AMPDU_BUF IEEE80211_MAX_AMPDU_BUF_HE ++#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB ++#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB ++#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU ++#endif ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) ++#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_MASK ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define IEEE80211_RADIOTAP_HE 23 ++#define IEEE80211_RADIOTAP_HE_MU 24 ++ ++struct ieee80211_radiotap_he { ++ __le16 data1, data2, data3, data4, data5, data6; ++}; ++ ++enum ieee80211_radiotap_he_bits { ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3, ++ ++ IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004, ++ IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008, ++ IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010, ++ IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020, ++ IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040, ++ IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080, ++ IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100, ++ IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000, ++ IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001, ++ IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002, ++ IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004, ++ IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008, ++ IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010, ++ IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020, ++ IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040, ++ IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080, ++ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00, ++ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f, ++ IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040, ++ IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080, ++ IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00, ++ IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000, ++ IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000, ++ IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000, ++ ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10, ++ ++ IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030, ++ IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0, ++ IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1, ++ IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2, ++ ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3, ++ IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700, ++ IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000, ++ IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010, ++ IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00, ++ IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000, ++}; ++ ++struct ieee80211_radiotap_he_mu { ++ __le16 flags1, flags2; ++ u8 ru_ch1[4]; ++ u8 ru_ch2[4]; ++}; ++ ++enum ieee80211_radiotap_he_mu_bits { ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS = 0x000f, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN = 0x0010, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM = 0x0020, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN = 0x0040, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN = 0x0080, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN = 0x0100, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN = 0x0200, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN = 0x1000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU = 0x2000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN = 0x4000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW = 0x0003, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_20MHZ = 0x0000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_40MHZ = 0x0001, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_80MHZ = 0x0002, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_160MHZ = 0x0003, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN = 0x0004, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP = 0x0008, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS = 0x00f0, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW = 0x0300, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN = 0x0400, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800, ++}; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) ++#define rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, params) \ ++ rwnx_cfg80211_add_iface(wiphy, name, type, u32 *flags, params) ++#else ++#define rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, params) \ ++ rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, u32 *flags, params) ++#endif ++ ++#define rwnx_cfg80211_change_iface(wiphy, dev, type, params) \ ++ rwnx_cfg80211_change_iface(wiphy, dev, type, u32 *flags, params) ++ ++#define CCFS0(vht) vht->center_freq_seg1_idx ++#define CCFS1(vht) vht->center_freq_seg2_idx ++ ++#else ++#define CCFS0(vht) vht->center_freq_seg0_idx ++#define CCFS1(vht) vht->center_freq_seg1_idx ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) ++#define cfg80211_cqm_rssi_notify(dev, event, level, gfp) \ ++ cfg80211_cqm_rssi_notify(dev, event, gfp) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) ++#define ieee80211_amsdu_to_8023s(skb, list, addr, iftype, extra_headroom, check_da, check_sa) \ ++ ieee80211_amsdu_to_8023s(skb, list, addr, iftype, extra_headroom, false) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) ++#define NUM_NL80211_BANDS IEEE80211_NUM_BANDS ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++#define cfg80211_disconnected(dev, reason, ie, len, local, gfp) \ ++ cfg80211_disconnected(dev, reason, ie, len, gfp) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !(defined CONFIG_VENDOR_RWNX) ++#define ieee80211_chandef_to_operating_class(chan_def, op_class) 0 ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++#define SURVEY_INFO_TIME SURVEY_INFO_CHANNEL_TIME ++#define SURVEY_INFO_TIME_BUSY SURVEY_INFO_CHANNEL_TIME_BUSY ++#define SURVEY_INFO_TIME_EXT_BUSY SURVEY_INFO_CHANNEL_TIME_EXT_BUSY ++#define SURVEY_INFO_TIME_RX SURVEY_INFO_CHANNEL_TIME_RX ++#define SURVEY_INFO_TIME_TX SURVEY_INFO_CHANNEL_TIME_TX ++ ++#define SURVEY_TIME(s) s->channel_time ++#define SURVEY_TIME_BUSY(s) s->channel_time_busy ++#else ++#define SURVEY_TIME(s) s->time ++#define SURVEY_TIME_BUSY(s) s->time_busy ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) ++#define cfg80211_ch_switch_started_notify(dev, chandef, count) ++ ++#define WLAN_BSS_COEX_INFORMATION_REQUEST BIT(0) ++#define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2) ++#define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4) ++#define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5) ++#define WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH BIT(6) ++#define WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED BIT(7) ++#define NL80211_FEATURE_TDLS_CHANNEL_SWITCH 0 ++ ++#define STA_TDLS_INITIATOR(sta) 0 ++ ++#else ++#define STA_TDLS_INITIATOR(sta) sta->tdls_initiator ++#endif ++ ++#ifndef REGULATORY_IGNORE_STALE_KICKOFF ++#define REGULATORY_IGNORE_STALE_KICKOFF 0 ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) ++#define cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags) \ ++ cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags, GFP_ATOMIC) ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) ++#define cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags) \ ++ cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, GFP_ATOMIC) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) ++#define rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, initiator, buf, len) \ ++ rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, buf, len) ++#else ++#define rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, initiator, buf, len) \ ++ rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, buf, len) ++#endif ++#endif ++ ++#include ++ ++struct ieee80211_wmm_ac_param { ++ u8 aci_aifsn; /* AIFSN, ACM, ACI */ ++ u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ ++ __le16 txop_limit; ++} __packed; ++ ++struct ieee80211_wmm_param_ie { ++ u8 element_id; /* Element ID: 221 (0xdd); */ ++ u8 len; /* Length: 24 */ ++ /* required fields for WMM version 1 */ ++ u8 oui[3]; /* 00:50:f2 */ ++ u8 oui_type; /* 2 */ ++ u8 oui_subtype; /* 1 */ ++ u8 version; /* 1 for WMM version 1.0 */ ++ u8 qos_info; /* AP/STA specific QoS info */ ++ u8 reserved; /* 0 */ ++ /* AC_BE, AC_BK, AC_VI, AC_VO */ ++ struct ieee80211_wmm_ac_param ac[4]; ++} __packed; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++enum { ++ IEEE80211_HE_MCS_SUPPORT_0_7 = 0, ++ IEEE80211_HE_MCS_SUPPORT_0_9 = 1, ++ IEEE80211_HE_MCS_SUPPORT_0_11 = 2, ++ IEEE80211_HE_MCS_NOT_SUPPORTED = 3, ++}; ++#endif ++ ++/* MAC80211 */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) ++#define rwnx_ops_mgd_prepare_tx(hw, vif, duration) \ ++ rwnx_ops_mgd_prepare_tx(hw, vif) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) ++ ++#define RX_ENC_HT(s) (s->flag |= RX_FLAG_HT) ++#define RX_ENC_HT_GF(s) (s->flag |= (RX_FLAG_HT | RX_FLAG_HT_GF)) ++#define RX_ENC_VHT(s) (s->flag |= RX_FLAG_HT) ++#define RX_ENC_HE(s) (s->flag |= RX_FLAG_HT) ++#define RX_ENC_FLAG_SHORT_GI(s) (s->flag |= RX_FLAG_SHORT_GI) ++#define RX_ENC_FLAG_SHORT_PRE(s) (s->flag |= RX_FLAG_SHORTPRE) ++#define RX_ENC_FLAG_LDPC(s) (s->flag |= RX_FLAG_LDPC) ++#define RX_BW_40MHZ(s) (s->flag |= RX_FLAG_40MHZ) ++#define RX_BW_80MHZ(s) (s->vht_flag |= RX_VHT_FLAG_80MHZ) ++#define RX_BW_160MHZ(s) (s->vht_flag |= RX_VHT_FLAG_160MHZ) ++#define RX_NSS(s) s->vht_nss ++ ++#else ++#define RX_ENC_HT(s) (s->encoding = RX_ENC_HT) ++#define RX_ENC_HT_GF(s) { s->encoding = RX_ENC_HT; \ ++ s->enc_flags |= RX_ENC_FLAG_HT_GF; } ++#define RX_ENC_VHT(s) (s->encoding = RX_ENC_VHT) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define RX_ENC_HE(s) (s->encoding = RX_ENC_VHT) ++#else ++#define RX_ENC_HE(s) (s->encoding = RX_ENC_HE) ++#endif ++#define RX_ENC_FLAG_SHORT_GI(s) (s->enc_flags |= RX_ENC_FLAG_SHORT_GI) ++#define RX_ENC_FLAG_SHORT_PRE(s) (s->enc_flags |= RX_ENC_FLAG_SHORTPRE) ++#define RX_ENC_FLAG_LDPC(s) (s->enc_flags |= RX_ENC_FLAG_LDPC) ++#define RX_BW_40MHZ(s) (s->bw = RATE_INFO_BW_40) ++#define RX_BW_80MHZ(s) (s->bw = RATE_INFO_BW_80) ++#define RX_BW_160MHZ(s) (s->bw = RATE_INFO_BW_160) ++#define RX_NSS(s) s->nss ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) ++#define ieee80211_cqm_rssi_notify(vif, event, level, gfp) \ ++ ieee80211_cqm_rssi_notify(vif, event, gfp) ++#endif ++ ++#ifndef CONFIG_VENDOR_RWNX_AMSDUS_TX ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) ++#define rwnx_ops_ampdu_action(hw, vif, params) \ ++ rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \ ++ struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) ++#define rwnx_ops_ampdu_action(hw, vif, params) \ ++ rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \ ++ struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, \ ++ bool amsdu) ++#endif ++#endif /* CONFIG_VENDOR_RWNX_AMSDUS_TX */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++#define IEEE80211_HW_SUPPORT_FAST_XMIT 0 ++#define ieee80211_hw_check(hw, feat) (hw->flags & IEEE80211_HW_##feat) ++#define ieee80211_hw_set(hw, feat) {hw->flags |= IEEE80211_HW_##feat; } ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) ++#define rwnx_ops_sw_scan_start(hw, vif, mac_addr) \ ++ rwnx_ops_sw_scan_start(hw) ++#define rwnx_ops_sw_scan_complete(hw, vif) \ ++ rwnx_ops_sw_scan_complete(hw) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define rwnx_ops_hw_scan(hw, vif, hw_req) \ ++ rwnx_ops_hw_scan(hw, vif, struct cfg80211_scan_request *req) ++#endif ++ ++/* NET */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb) ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb, void *accel_priv, select_queue_fallback_t fallback) ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb, sb_dev, select_queue_fallback_t fallback) ++#else ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb, sb_dev) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)) && !(defined CONFIG_VENDOR_RWNX) ++#define sk_pacing_shift_update(sk, shift) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define alloc_netdev_mqs(size, name, assign, setup, txqs, rxqs) \ ++ alloc_netdev_mqs(size, name, setup, txqs, rxqs) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define NET_NAME_UNKNOWN 0 ++#endif ++ ++/* TRACE */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++#define trace_print_symbols_seq ftrace_print_symbols_seq ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define trace_seq_buffer_ptr(p) (p->buffer + p->len) ++#endif ++ ++/* TIME */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) ++#define time64_to_tm(t, o, tm) time_to_tm((time_t)t, o, tm) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) ++#define ktime_get_real_seconds get_seconds ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++typedef __s64 time64_t; ++#endif ++ ++#endif /* _RWNX_COMPAT_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c +new file mode 100644 +index 000000000000..fdca110169b0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c +@@ -0,0 +1,2469 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_debugfs.c ++ * ++ * @brief Definition of debugfs entries ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rwnx_debugfs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_radar.h" ++#include "rwnx_tx.h" ++ ++#ifdef CONFIG_DEBUG_FS ++#ifdef CONFIG_RWNX_FULLMAC ++static ssize_t rwnx_dbgfs_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int ret; ++ int i, skipped; ++ ssize_t read; ++ int bufsz = (NX_TXQ_CNT) * 20 + (ARRAY_SIZE(priv->stats.amsdus_rx) + 1) * 40 ++ + (ARRAY_SIZE(priv->stats.ampdus_tx) * 30); ++ ++ if (*ppos) ++ return 0; ++ ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ ret = scnprintf(buf, bufsz, "TXQs CFM balances "); ++ for (i = 0; i < NX_TXQ_CNT; i++) ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%1d]:%3d", i, ++ priv->stats.cfm_balance[i]); ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, "\n"); ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "\nAMSDU[len] done failed received\n"); ++ for (i = skipped = 0; i < NX_TX_PAYLOAD_MAX; i++) { ++ if (priv->stats.amsdus[i].done) { ++ per = DIV_ROUND_UP((priv->stats.amsdus[i].failed) * ++ 100, priv->stats.amsdus[i].done); ++ } else if (priv->stats.amsdus_rx[i]) { ++ per = 0; ++ } else { ++ per = 0; ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %10d %8d(%3d%%) %10d\n", i ? i + 1 : i, ++ priv->stats.amsdus[i].done, ++ priv->stats.amsdus[i].failed, per, ++ priv->stats.amsdus_rx[i]); ++ } ++ ++ for (; i < ARRAY_SIZE(priv->stats.amsdus_rx); i++) { ++ if (!priv->stats.amsdus_rx[i]) { ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %10d\n", ++ i + 1, priv->stats.amsdus_rx[i]); ++ } ++#else ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "\nAMSDU[len] received\n"); ++ for (i = skipped = 0; i < ARRAY_SIZE(priv->stats.amsdus_rx); i++) { ++ if (!priv->stats.amsdus_rx[i]) { ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %10d\n", ++ i + 1, priv->stats.amsdus_rx[i]); ++ } ++ ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "\nAMPDU[len] done received\n"); ++ for (i = skipped = 0; i < ARRAY_SIZE(priv->stats.ampdus_tx); i++) { ++ if (!priv->stats.ampdus_tx[i] && !priv->stats.ampdus_rx[i]) { ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %9d %9d\n", i ? i + 1 : i, ++ priv->stats.ampdus_tx[i], priv->stats.ampdus_rx[i]); ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "#mpdu missed %9d\n", ++ priv->stats.ampdus_rx_miss); ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ kfree(buf); ++ ++ return read; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++static ssize_t rwnx_dbgfs_stats_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ ++ /* Prevent from interrupt preemption as these statistics are updated under ++ * interrupt */ ++ spin_lock_bh(&priv->tx_lock); ++ ++ memset(&priv->stats, 0, sizeof(priv->stats)); ++ ++ spin_unlock_bh(&priv->tx_lock); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(stats); ++ ++#define TXQ_STA_PREF "tid|" ++#define TXQ_STA_PREF_FMT "%3d|" ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define TXQ_VIF_PREF "type|" ++#define TXQ_VIF_PREF_FMT "%4s|" ++#else ++#define TXQ_VIF_PREF "AC|" ++#define TXQ_VIF_PREF_FMT "%2s|" ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#define TXQ_HDR "idx| status|credit|ready|retry" ++#define TXQ_HDR_FMT "%3d|%s%s%s%s%s%s%s|%6d|%5d|%5d" ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++#ifdef CONFIG_RWNX_FULLMAC ++#define TXQ_HDR_SUFF "|amsdu" ++#define TXQ_HDR_SUFF_FMT "|%5d" ++#else ++#define TXQ_HDR_SUFF "|amsdu-ht|amdsu-vht" ++#define TXQ_HDR_SUFF_FMT "|%8d|%9d" ++#endif /* CONFIG_RWNX_FULLMAC */ ++#else ++#define TXQ_HDR_SUFF "" ++#define TXQ_HDR_SUF_FMT "" ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++#define TXQ_HDR_MAX_LEN (sizeof(TXQ_STA_PREF) + sizeof(TXQ_HDR) + sizeof(TXQ_HDR_SUFF) + 1) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define PS_HDR "Legacy PS: ready=%d, sp=%d / UAPSD: ready=%d, sp=%d" ++#define PS_HDR_LEGACY "Legacy PS: ready=%d, sp=%d" ++#define PS_HDR_UAPSD "UAPSD: ready=%d, sp=%d" ++#define PS_HDR_MAX_LEN sizeof("Legacy PS: ready=xxx, sp=xxx / UAPSD: ready=xxx, sp=xxx\n") ++#else ++#define PS_HDR "" ++#define PS_HDR_MAX_LEN 0 ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#define STA_HDR "** STA %d (%pM)\n" ++#define STA_HDR_MAX_LEN (sizeof("- STA xx (xx:xx:xx:xx:xx:xx)\n") + PS_HDR_MAX_LEN) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define VIF_HDR "* VIF [%d] %s\n" ++#define VIF_HDR_MAX_LEN (sizeof(VIF_HDR) + IFNAMSIZ) ++#else ++#define VIF_HDR "* VIF [%d]\n" ++#define VIF_HDR_MAX_LEN sizeof(VIF_HDR) ++#endif ++ ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define VIF_SEP "---------------------------------------\n" ++#else ++#define VIF_SEP "----------------------------------------------------\n" ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#else /* ! CONFIG_RWNX_AMSDUS_TX */ ++#define VIF_SEP "---------------------------------\n" ++#endif /* CONFIG_RWNX_AMSDUS_TX*/ ++ ++#define VIF_SEP_LEN sizeof(VIF_SEP) ++ ++#define CAPTION "status: L=in hwq list, F=stop full, P=stop sta PS, V=stop vif PS, C=stop channel, S=stop CSA, M=stop MU" ++#define CAPTION_LEN sizeof(CAPTION) ++ ++#define STA_TXQ 0 ++#define VIF_TXQ 1 ++ ++static int rwnx_dbgfs_txq(char *buf, size_t size, struct rwnx_txq *txq, int type, int tid, char *name) ++{ ++ int res, idx = 0; ++ ++ if (type == STA_TXQ) { ++ res = scnprintf(&buf[idx], size, TXQ_STA_PREF_FMT, tid); ++ idx += res; ++ size -= res; ++ } else { ++ res = scnprintf(&buf[idx], size, TXQ_VIF_PREF_FMT, name); ++ idx += res; ++ size -= res; ++ } ++ ++ res = scnprintf(&buf[idx], size, TXQ_HDR_FMT, txq->idx, ++ (txq->status & RWNX_TXQ_IN_HWQ_LIST) ? "L" : " ", ++ (txq->status & RWNX_TXQ_STOP_FULL) ? "F" : " ", ++ (txq->status & RWNX_TXQ_STOP_STA_PS) ? "P" : " ", ++ (txq->status & RWNX_TXQ_STOP_VIF_PS) ? "V" : " ", ++ (txq->status & RWNX_TXQ_STOP_CHAN) ? "C" : " ", ++ (txq->status & RWNX_TXQ_STOP_CSA) ? "S" : " ", ++ (txq->status & RWNX_TXQ_STOP_MU_POS) ? "M" : " ", ++ txq->credits, skb_queue_len(&txq->sk_list), ++ txq->nb_retry); ++ idx += res; ++ size -= res; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (type == STA_TXQ) { ++ res = scnprintf(&buf[idx], size, TXQ_HDR_SUFF_FMT, ++#ifdef CONFIG_RWNX_FULLMAC ++ txq->amsdu_len ++#else ++ txq->amsdu_ht_len_cap, txq->amsdu_vht_len_cap ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ); ++ idx += res; ++ size -= res; ++ } ++#endif ++ ++ res = scnprintf(&buf[idx], size, "\n"); ++ idx += res; ++ size -= res; ++ ++ return idx; ++} ++ ++static int rwnx_dbgfs_txq_sta(char *buf, size_t size, struct rwnx_sta *rwnx_sta, ++ struct rwnx_hw *rwnx_hw) ++{ ++ int tid, res, idx = 0; ++ struct rwnx_txq *txq; ++ ++ res = scnprintf(&buf[idx], size, "\n" STA_HDR, ++ rwnx_sta->sta_idx, ++#ifdef CONFIG_RWNX_FULLMAC ++ rwnx_sta->mac_addr ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ); ++ idx += res; ++ size -= res; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (rwnx_sta->ps.active) { ++ if (rwnx_sta->uapsd_tids && ++ (rwnx_sta->uapsd_tids == ((1 << NX_NB_TXQ_PER_STA) - 1))) ++ res = scnprintf(&buf[idx], size, PS_HDR_UAPSD "\n", ++ rwnx_sta->ps.pkt_ready[UAPSD_ID], ++ rwnx_sta->ps.sp_cnt[UAPSD_ID]); ++ else if (rwnx_sta->uapsd_tids) ++ res = scnprintf(&buf[idx], size, PS_HDR "\n", ++ rwnx_sta->ps.pkt_ready[LEGACY_PS_ID], ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID], ++ rwnx_sta->ps.pkt_ready[UAPSD_ID], ++ rwnx_sta->ps.sp_cnt[UAPSD_ID]); ++ else ++ res = scnprintf(&buf[idx], size, PS_HDR_LEGACY "\n", ++ rwnx_sta->ps.pkt_ready[LEGACY_PS_ID], ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID]); ++ idx += res; ++ size -= res; ++ } else { ++ res = scnprintf(&buf[idx], size, "\n"); ++ idx += res; ++ size -= res; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ ++ res = scnprintf(&buf[idx], size, TXQ_STA_PREF TXQ_HDR TXQ_HDR_SUFF "\n"); ++ idx += res; ++ size -= res; ++ ++ ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, STA_TXQ, tid, NULL); ++ idx += res; ++ size -= res; ++ } ++ ++ return idx; ++} ++ ++static int rwnx_dbgfs_txq_vif(char *buf, size_t size, struct rwnx_vif *rwnx_vif, ++ struct rwnx_hw *rwnx_hw) ++{ ++ int res, idx = 0; ++ struct rwnx_txq *txq; ++ struct rwnx_sta *rwnx_sta; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ res = scnprintf(&buf[idx], size, VIF_HDR, rwnx_vif->vif_index, rwnx_vif->ndev->name); ++ idx += res; ++ size -= res; ++ if (!rwnx_vif->up || rwnx_vif->ndev == NULL) ++ return idx; ++ ++#else ++ int ac; ++ char ac_name[2] = {'0', '\0'}; ++ ++ res = scnprintf(&buf[idx], size, VIF_HDR, rwnx_vif->vif_index); ++ idx += res; ++ size -= res; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT) { ++ res = scnprintf(&buf[idx], size, TXQ_VIF_PREF TXQ_HDR "\n"); ++ idx += res; ++ size -= res; ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, VIF_TXQ, 0, "UNK"); ++ idx += res; ++ size -= res; ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, VIF_TXQ, 0, "BCMC"); ++ idx += res; ++ size -= res; ++ rwnx_sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ if (rwnx_sta->ps.active) { ++ res = scnprintf(&buf[idx], size, PS_HDR_LEGACY "\n", ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID], ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID]); ++ idx += res; ++ size -= res; ++ } else { ++ res = scnprintf(&buf[idx], size, "\n"); ++ idx += res; ++ size -= res; ++ } ++ ++ list_for_each_entry(rwnx_sta, &rwnx_vif->ap.sta_list, list) { ++ res = rwnx_dbgfs_txq_sta(&buf[idx], size, rwnx_sta, rwnx_hw); ++ idx += res; ++ size -= res; ++ } ++ } else if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ if (rwnx_vif->sta.ap) { ++ res = rwnx_dbgfs_txq_sta(&buf[idx], size, rwnx_vif->sta.ap, rwnx_hw); ++ idx += res; ++ size -= res; ++ } ++ } ++ ++#else ++ res = scnprintf(&buf[idx], size, TXQ_VIF_PREF TXQ_HDR "\n"); ++ idx += res; ++ size -= res; ++ ++ foreach_vif_txq(rwnx_vif, txq, ac) { ++ ac_name[0]++; ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, VIF_TXQ, 0, ac_name); ++ idx += res; ++ size -= res; ++ } ++ ++ list_for_each_entry(rwnx_sta, &rwnx_vif->stations, list) { ++ res = rwnx_dbgfs_txq_sta(&buf[idx], size, rwnx_sta, rwnx_hw); ++ idx += res; ++ size -= res; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ return idx; ++} ++ ++static ssize_t rwnx_dbgfs_txq_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rwnx_hw = file->private_data; ++ struct rwnx_vif *vif; ++ char *buf; ++ int idx, res; ++ ssize_t read; ++ size_t bufsz = ((NX_VIRT_DEV_MAX * (VIF_HDR_MAX_LEN + 2 * VIF_SEP_LEN)) + ++ (NX_REMOTE_STA_MAX * STA_HDR_MAX_LEN) + ++ ((NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX + NX_NB_TXQ) * ++ TXQ_HDR_MAX_LEN) + CAPTION_LEN); ++ ++ /* everything is read in one go */ ++ if (*ppos) ++ return 0; ++ ++ bufsz = min_t(size_t, bufsz, count); ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ bufsz--; ++ idx = 0; ++ ++ res = scnprintf(&buf[idx], bufsz, CAPTION); ++ idx += res; ++ bufsz -= res; ++ ++ //spin_lock_bh(&rwnx_hw->tx_lock); ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ res = scnprintf(&buf[idx], bufsz, "\n"VIF_SEP); ++ idx += res; ++ bufsz -= res; ++ res = rwnx_dbgfs_txq_vif(&buf[idx], bufsz, vif, rwnx_hw); ++ idx += res; ++ bufsz -= res; ++ res = scnprintf(&buf[idx], bufsz, VIF_SEP); ++ idx += res; ++ bufsz -= res; ++ } ++ //spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, idx); ++ kfree(buf); ++ ++ return read; ++} ++DEBUGFS_READ_FILE_OPS(txq); ++ ++static ssize_t rwnx_dbgfs_acsinfo_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++#ifdef CONFIG_RWNX_FULLMAC ++ struct wiphy *wiphy = priv->wiphy; ++#endif //CONFIG_RWNX_FULLMAC ++ int survey_cnt = 0; ++ int len = 0; ++ int band, chan_cnt; ++ int band_max = NL80211_BAND_5GHZ; ++ char *buf = (char *)vmalloc((SCAN_CHANNEL_MAX + 1) * 43); ++ ssize_t size; ++ ++ if (!buf) ++ return 0; ++ ++ if (priv->band_5g_support) ++ band_max = NL80211_BAND_5GHZ + 1; ++ ++ mutex_lock(&priv->dbgdump_elem.mutex); ++ ++ len += scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "FREQ TIME(ms) BUSY(ms) NOISE(dBm)\n"); ++ ++ for (band = NL80211_BAND_2GHZ; band < band_max; band++) { ++ for (chan_cnt = 0; chan_cnt < wiphy->bands[band]->n_channels; chan_cnt++) { ++ struct rwnx_survey_info *p_survey_info = &priv->survey[survey_cnt]; ++ struct ieee80211_channel *p_chan = &wiphy->bands[band]->channels[chan_cnt]; ++ ++ if (p_survey_info->filled) { ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - len - 1, count), ++ "%d %03d %03d %d\n", ++ p_chan->center_freq, ++ p_survey_info->chan_time_ms, ++ p_survey_info->chan_time_busy_ms, ++ p_survey_info->noise_dbm); ++ } else { ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) -len -1, count), ++ "%d NOT AVAILABLE\n", ++ p_chan->center_freq); ++ } ++ ++ survey_cnt++; ++ } ++ } ++ ++ mutex_unlock(&priv->dbgdump_elem.mutex); ++ ++ size = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ vfree(buf); ++ ++ return size; ++} ++ ++DEBUGFS_READ_FILE_OPS(acsinfo); ++ ++static ssize_t rwnx_dbgfs_fw_dbg_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ char help[] = "usage: [MOD:]* " ++ "[DBG:]\n"; ++ ++ return simple_read_from_buffer(user_buf, count, ppos, help, sizeof(help)); ++} ++ ++ ++static ssize_t rwnx_dbgfs_fw_dbg_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int idx = 0; ++ u32 mod = 0; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ ++#define RWNX_MOD_TOKEN(str, val) \ ++ do { \ ++ if (strncmp(&buf[idx], str, sizeof(str) - 1) == 0) { \ ++ idx += sizeof(str) - 1; \ ++ mod |= val; \ ++ continue; \ ++ } \ ++ } while (0) ++ ++#define RWNX_DBG_TOKEN(str, val) \ ++ do { \ ++ if (strncmp(&buf[idx], str, sizeof(str) - 1) == 0) { \ ++ idx += sizeof(str) - 1; \ ++ dbg = val; \ ++ goto dbg_done; \ ++ } \ ++ } while (0) ++ ++ while ((idx + 4) < len) { ++ if (strncmp(&buf[idx], "MOD:", 4) == 0) { ++ idx += 4; ++ RWNX_MOD_TOKEN("ALL", 0xffffffff); ++ RWNX_MOD_TOKEN("KE", BIT(0)); ++ RWNX_MOD_TOKEN("DBG", BIT(1)); ++ RWNX_MOD_TOKEN("IPC", BIT(2)); ++ RWNX_MOD_TOKEN("DMA", BIT(3)); ++ RWNX_MOD_TOKEN("MM", BIT(4)); ++ RWNX_MOD_TOKEN("TX", BIT(5)); ++ RWNX_MOD_TOKEN("RX", BIT(6)); ++ RWNX_MOD_TOKEN("PHY", BIT(7)); ++ idx++; ++ } else if (strncmp(&buf[idx], "DBG:", 4) == 0) { ++ u32 dbg = 0; ++ idx += 4; ++ RWNX_DBG_TOKEN("NONE", 0); ++ RWNX_DBG_TOKEN("CRT", 1); ++ RWNX_DBG_TOKEN("ERR", 2); ++ RWNX_DBG_TOKEN("WRN", 3); ++ RWNX_DBG_TOKEN("INF", 4); ++ RWNX_DBG_TOKEN("VRB", 5); ++ idx++; ++ continue; ++ dbg_done: ++ rwnx_send_dbg_set_sev_filter_req(priv, dbg); ++ } else { ++ idx++; ++ } ++ } ++ ++ if (mod) { ++ rwnx_send_dbg_set_mod_filter_req(priv, mod); ++ } ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg); ++ ++static ssize_t rwnx_dbgfs_sys_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[3*64]; ++ int len = 0; ++ ssize_t read; ++ int error = 0; ++ struct dbg_get_sys_stat_cfm cfm; ++ u32 sleep_int, sleep_frac, doze_int, doze_frac; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Get the information from the FW */ ++ error = rwnx_send_dbg_get_sys_stat_req(priv, &cfm); ++ if (error) ++ return error; ++ ++ if (cfm.stats_time == 0) ++ return 0; ++ ++ sleep_int = ((cfm.cpu_sleep_time * 100) / cfm.stats_time); ++ sleep_frac = (((cfm.cpu_sleep_time * 100) % cfm.stats_time) * 10) / cfm.stats_time; ++ doze_int = ((cfm.doze_time * 100) / cfm.stats_time); ++ doze_frac = (((cfm.doze_time * 100) % cfm.stats_time) * 10) / cfm.stats_time; ++ ++ len += scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "\nSystem statistics:\n"); ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - 1, count), ++ " CPU sleep [%%]: %d.%d\n", sleep_int, sleep_frac); ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - 1, count), ++ " Doze [%%]: %d.%d\n", doze_int, doze_frac); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ return read; ++} ++ ++DEBUGFS_READ_FILE_OPS(sys_stats); ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++static ssize_t rwnx_dbgfs_mu_group_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rwnx_hw = file->private_data; ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ struct rwnx_mu_group *group; ++ size_t bufsz = NX_MU_GROUP_MAX * sizeof("xx = (xx - xx - xx - xx)\n") + 50; ++ char *buf; ++ int j, res, idx = 0; ++ ++ if (*ppos) ++ return 0; ++ ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ res = scnprintf(&buf[idx], bufsz, "MU Group list (%d groups, %d users max)\n", ++ NX_MU_GROUP_MAX, CONFIG_USER_MAX); ++ idx += res; ++ bufsz -= res; ++ ++ list_for_each_entry(group, &mu->active_groups, list) { ++ if (group->user_cnt) { ++ res = scnprintf(&buf[idx], bufsz, "%2d = (", group->group_id); ++ idx += res; ++ bufsz -= res; ++ for (j = 0; j < (CONFIG_USER_MAX - 1) ; j++) { ++ if (group->users[j]) ++ res = scnprintf(&buf[idx], bufsz, "%2d - ", ++ group->users[j]->sta_idx); ++ else ++ res = scnprintf(&buf[idx], bufsz, ".. - "); ++ ++ idx += res; ++ bufsz -= res; ++ } ++ ++ if (group->users[j]) ++ res = scnprintf(&buf[idx], bufsz, "%2d)\n", ++ group->users[j]->sta_idx); ++ else ++ res = scnprintf(&buf[idx], bufsz, "..)\n"); ++ ++ idx += res; ++ bufsz -= res; ++ } ++ } ++ ++ res = simple_read_from_buffer(user_buf, count, ppos, buf, idx); ++ kfree(buf); ++ ++ return res; ++} ++ ++DEBUGFS_READ_FILE_OPS(mu_group); ++#endif ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++static ssize_t rwnx_dbgfs_oppps_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rw_hw = file->private_data; ++ struct rwnx_vif *rw_vif; ++ char buf[32]; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ctw; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ ++ /* Read the written CT Window (provided in ms) value */ ++ if (sscanf(buf, "ctw=%d", &ctw) > 0) { ++ /* Check if at least one VIF is configured as P2P GO */ ++ list_for_each_entry(rw_vif, &rw_hw->vifs, list) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (RWNX_VIF_TYPE(rw_vif) == NL80211_IFTYPE_P2P_GO) { ++#endif /* CONFIG_RWNX_FULLMAC */ ++ struct mm_set_p2p_oppps_cfm cfm; ++ ++ /* Forward request to the embedded and wait for confirmation */ ++ rwnx_send_p2p_oppps_req(rw_hw, rw_vif, (u8)ctw, &cfm); ++ ++ break; ++ } ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(oppps); ++ ++static ssize_t rwnx_dbgfs_noa_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rw_hw = file->private_data; ++ struct rwnx_vif *rw_vif; ++ char buf[64]; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int noa_count, interval, duration, dyn_noa; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ ++ /* Read the written NOA information */ ++ if (sscanf(buf, "count=%d interval=%d duration=%d dyn=%d", ++ &noa_count, &interval, &duration, &dyn_noa) > 0) { ++ /* Check if at least one VIF is configured as P2P GO */ ++ list_for_each_entry(rw_vif, &rw_hw->vifs, list) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (RWNX_VIF_TYPE(rw_vif) == NL80211_IFTYPE_P2P_GO) { ++#endif /* CONFIG_RWNX_FULLMAC */ ++ struct mm_set_p2p_noa_cfm cfm; ++ ++ /* Forward request to the embedded and wait for confirmation */ ++ rwnx_send_p2p_noa_req(rw_hw, rw_vif, noa_count, interval, ++ duration, (dyn_noa > 0), &cfm); ++ ++ break; ++ } ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(noa); ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++static char fw_log_buffer[FW_LOG_SIZE]; ++ ++static ssize_t rwnx_dbgfs_fw_log_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ size_t not_cpy; ++ size_t nb_cpy; ++ char *log = fw_log_buffer; ++ ++ printk("%s, %d, %p, %p\n", __func__, priv->debugfs.fw_log.buf.size, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.dataend); ++ //spin_lock_bh(&priv->debugfs.fw_log.lock); ++ ++ if ((priv->debugfs.fw_log.buf.start + priv->debugfs.fw_log.buf.size) >= priv->debugfs.fw_log.buf.dataend) { ++ memcpy(log, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.dataend - priv->debugfs.fw_log.buf.start); ++ not_cpy = copy_to_user(user_buf, log, priv->debugfs.fw_log.buf.dataend - priv->debugfs.fw_log.buf.start); ++ nb_cpy = priv->debugfs.fw_log.buf.dataend - priv->debugfs.fw_log.buf.start - not_cpy; ++ priv->debugfs.fw_log.buf.start = priv->debugfs.fw_log.buf.data; ++ } else { ++ memcpy(log, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.size); ++ not_cpy = copy_to_user(user_buf, log, priv->debugfs.fw_log.buf.size); ++ nb_cpy = priv->debugfs.fw_log.buf.size - not_cpy; ++ priv->debugfs.fw_log.buf.start = priv->debugfs.fw_log.buf.start + priv->debugfs.fw_log.buf.size - not_cpy; ++ } ++ ++ priv->debugfs.fw_log.buf.size -= nb_cpy; ++ //spin_unlock_bh(&priv->debugfs.fw_log.lock); ++ ++ printk("nb_cpy=%lu, not_cpy=%lu, start=%p, end=%p\n", (long unsigned int)nb_cpy, (long unsigned int)not_cpy, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.end); ++ return nb_cpy; ++} ++ ++static ssize_t rwnx_dbgfs_fw_log_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ //struct rwnx_hw *priv = file->private_data; ++ ++ printk("%s\n", __func__); ++ return count; ++} ++DEBUGFS_READ_WRITE_FILE_OPS(fw_log); ++ ++#ifdef CONFIG_RWNX_RADAR ++static ssize_t rwnx_dbgfs_pulses_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos, ++ int rd_idx) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int len = 0; ++ int bufsz; ++ int i; ++ int index; ++ struct rwnx_radar_pulses *p = &priv->radar.pulses[rd_idx]; ++ ssize_t read; ++ ++ if (*ppos != 0) ++ return 0; ++ ++ /* Prevent from interrupt preemption */ ++ spin_lock_bh(&priv->radar.lock); ++ bufsz = p->count * 34 + 51; ++ bufsz += rwnx_radar_dump_pattern_detector(NULL, 0, &priv->radar, rd_idx); ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) { ++ spin_unlock_bh(&priv->radar.lock); ++ return 0; ++ } ++ ++ if (p->count) { ++ len += scnprintf(&buf[len], bufsz - len, ++ " PRI WIDTH FOM FREQ\n"); ++ index = p->index; ++ for (i = 0; i < p->count; i++) { ++ struct radar_pulse *pulse; ++ ++ if (index > 0) ++ index--; ++ else ++ index = RWNX_RADAR_PULSE_MAX - 1; ++ ++ pulse = (struct radar_pulse *) &p->buffer[index]; ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ "%05dus %03dus %2d%% %+3dMHz\n", pulse->rep, ++ 2 * pulse->len, 6 * pulse->fom, 2*pulse->freq); ++ } ++ } ++ ++ len += rwnx_radar_dump_pattern_detector(&buf[len], bufsz - len, ++ &priv->radar, rd_idx); ++ ++ spin_unlock_bh(&priv->radar.lock); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_pulses_prim_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ return rwnx_dbgfs_pulses_read(file, user_buf, count, ppos, 0); ++} ++ ++DEBUGFS_READ_FILE_OPS(pulses_prim); ++ ++static ssize_t rwnx_dbgfs_pulses_sec_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ return rwnx_dbgfs_pulses_read(file, user_buf, count, ppos, 1); ++} ++ ++DEBUGFS_READ_FILE_OPS(pulses_sec); ++ ++static ssize_t rwnx_dbgfs_detected_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int bufsz, len = 0; ++ ssize_t read; ++ ++ if (*ppos != 0) ++ return 0; ++ ++ bufsz = 5; // RIU:\n ++ bufsz += rwnx_radar_dump_radar_detected(NULL, 0, &priv->radar, ++ RWNX_RADAR_RIU); ++ ++ if (priv->phy.cnt > 1) { ++ bufsz += 5; // FCU:\n ++ bufsz += rwnx_radar_dump_radar_detected(NULL, 0, &priv->radar, ++ RWNX_RADAR_FCU); ++ } ++ ++ buf = kmalloc(bufsz, GFP_KERNEL); ++ if (buf == NULL) { ++ return 0; ++ } ++ ++ len = scnprintf(&buf[len], bufsz, "RIU:\n"); ++ len += rwnx_radar_dump_radar_detected(&buf[len], bufsz - len, &priv->radar, ++ RWNX_RADAR_RIU); ++ ++ if (priv->phy.cnt > 1) { ++ len += scnprintf(&buf[len], bufsz - len, "FCU:\n"); ++ len += rwnx_radar_dump_radar_detected(&buf[len], bufsz - len, ++ &priv->radar, RWNX_RADAR_FCU); ++ } ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ ++ return read; ++} ++ ++DEBUGFS_READ_FILE_OPS(detected); ++ ++static ssize_t rwnx_dbgfs_enable_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "RIU=%d FCU=%d\n", priv->radar.dpd[RWNX_RADAR_RIU]->enabled, ++ priv->radar.dpd[RWNX_RADAR_FCU]->enabled); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_enable_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "RIU=%d", &val) > 0) ++ rwnx_radar_detection_enable(&priv->radar, val, RWNX_RADAR_RIU); ++ ++ if (sscanf(buf, "FCU=%d", &val) > 0) ++ rwnx_radar_detection_enable(&priv->radar, val, RWNX_RADAR_FCU); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(enable); ++ ++static ssize_t rwnx_dbgfs_band_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "BAND=%d\n", priv->phy.sec_chan.band); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_band_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int band_max = NL80211_BAND_5GHZ; ++ ++ if (priv->band_5g_support) ++ band_max = NL80211_BAND_5GHZ + 1; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if ((sscanf(buf, "%d", &val) > 0) && (val >= 0) && (val < band_max)) ++ priv->phy.sec_chan.band = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(band); ++ ++static ssize_t rwnx_dbgfs_type_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "TYPE=%d\n", priv->phy.sec_chan.type); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_type_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if ((sscanf(buf, "%d", &val) > 0) && (val >= PHY_CHNL_BW_20) && ++ (val <= PHY_CHNL_BW_80P80)) ++ priv->phy.sec_chan.type = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(type); ++ ++static ssize_t rwnx_dbgfs_prim20_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "PRIM20=%dMHz\n", priv->phy.sec_chan.prim20_freq); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_prim20_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%d", &val) > 0) ++ priv->phy.sec_chan.prim20_freq = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(prim20); ++ ++static ssize_t rwnx_dbgfs_center1_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "CENTER1=%dMHz\n", priv->phy.sec_chan.center_freq1); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_center1_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%d", &val) > 0) ++ priv->phy.sec_chan.center_freq1 = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(center1); ++ ++static ssize_t rwnx_dbgfs_center2_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "CENTER2=%dMHz\n", priv->phy.sec_chan.center_freq2); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_center2_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%d", &val) > 0) ++ priv->phy.sec_chan.center_freq2 = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(center2); ++ ++ ++static ssize_t rwnx_dbgfs_set_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ return 0; ++} ++ ++static ssize_t rwnx_dbgfs_set_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ ++ rwnx_send_set_channel(priv, 1, NULL); ++ rwnx_radar_detection_enable(&priv->radar, RWNX_RADAR_DETECT_ENABLE, ++ RWNX_RADAR_FCU); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(set); ++#endif /* CONFIG_RWNX_RADAR */ ++ ++static ssize_t rwnx_dbgfs_regdbg_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ u32 addr,val, oper; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ struct dbg_mem_read_cfm mem_read_cfm; ++ int ret; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%x %x %x" , &oper, &addr, &val ) > 0) ++ printk("addr=%x, val=%x,oper=%d\n", addr, val, oper); ++ ++ if(oper== 0) { ++ ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); ++ printk("[0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); ++ } else if (oper == 1) { ++ ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); ++ printk("before write : [0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); ++ ret = rwnx_send_dbg_mem_block_write_req(priv, addr, 4, &val); ++ ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); ++ printk("after write : [0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(regdbg); ++ ++static ssize_t rwnx_dbgfs_vendor_hwconfig_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[64]; ++ int32_t addr[14]; ++ int32_t addr_out[12]; ++ u32_l hwconfig_id; ++ size_t len = min_t(size_t,count,sizeof(buf)-1); ++ int ret; ++ printk("%s\n",__func__); ++ //choose the type of write info by struct ++ //struct mm_set_vendor_trx_param_req trx_param; ++ ++ if(copy_from_user(buf,user_buf,len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", ++ &hwconfig_id, &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5], &addr[6], &addr[7], &addr[8], &addr[9], &addr[10], &addr[11], &addr[12], &addr[13]); ++ if(ret > 15) { ++ printk("param error > 15\n"); ++ } else { ++ switch(hwconfig_id) ++ { ++ case 0: ++ if(ret != 5) { ++ printk("param error != 5\n"); ++ break;} ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("ACS_TXOP_REQ bk:0x%x be:0x%x vi:0x%x vo:0x%x\n",addr[0], addr[1], addr[2], addr[3]); ++ break; ++ case 1: ++ if(ret != 15) { ++ printk("param error != 15\n"); ++ break;} ++ addr[12] = ~addr[12] + 1; ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("CHANNEL_ACCESS_REQ edca:%x,%x,%x,%x, vif:%x, retry_cnt:%x, rts:%x, long_nav:%x, cfe:%x, rc_retry_cnt:%x:%x:%x ccademod_th %x, remove_1m2m %x\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13]); ++ break; ++ case 2: ++ if(ret != 7) { ++ printk("param error != 7\n"); ++ break;} ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("MAC_TIMESCALE_REQ sifsA:%x,sifsB:%x,slot:%x,ofdm_delay:%x,long_delay:%x,short_delay:%x\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); ++ break; ++ case 3: ++ if(ret != 6) { ++ printk("param error != 6\n"); ++ break;} ++ addr[1] = ~addr[1] + 1; ++ addr[2] = ~addr[2] + 1; ++ addr[3] = ~addr[3] + 1; ++ addr[4] = ~addr[4] + 1; ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("CCA_THRESHOLD_REQ auto_cca:%d, cca20p_rise:%d cca20s_rise:%d cca20p_fail:%d cca20s_fail:%d\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4]); ++ break; ++ case 4: // BWMODE_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("BWMODE_REQ md=%d\n", addr[0]); ++ } ++ break; ++ case 5: // CHIP_TEMP_GET_REQ ++ if (ret != 1) { ++ printk("param error != 1\n"); ++ } else { ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, addr_out); ++ printk("CHIP_TEMP_GET_REQ degree=%d\n", addr_out[0]); ++ } ++ break; ++ case 6://AP_PS_LEVEL_SET_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("AP_PS_LEVEL_SET_REQ lvl=%d\n", addr[0]); ++ } ++ break; ++ default: ++ printk("param error\n"); ++ break; ++ } ++ if(ret) { ++ printk("rwnx_send_vendor_hwconfig_req fail: %x\n", ret); ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(vendor_hwconfig); ++ ++static ssize_t rwnx_dbgfs_vendor_swconfig_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[64]; ++ int32_t addr[12]; ++ int32_t addr_out[12]; ++ u32_l swconfig_id; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ret; ++ printk("%s\n", __func__); ++ ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%x %x %x", &swconfig_id, &addr[0], &addr[1]); ++ if (ret > 3) { ++ printk("param error > 3\n"); ++ } else { ++ switch (swconfig_id) ++ { ++ case 0: // BCN_CFG_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("BCN_CFG_REQ set_en=%d, get_en=%d\n", addr[0], addr_out[0]); ++ } ++ break; ++ ++ case 1: // TEMP_COMP_SET_REQ ++ if (ret != 3) { ++ printk("param error != 3\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("TEMP_COMP_SET_REQ set_en=%d, tmr=%dms, get_st=%d\n", ++ addr[0], addr[1], addr_out[0]); ++ } ++ break; ++ ++ case 2: // TEMP_COMP_GET_REQ ++ if (ret != 1) { ++ printk("param error != 1\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("TEMP_COMP_GET_REQ get_st=%d, degree=%d\n", addr_out[0], addr_out[1]); ++ } ++ break; ++ ++ case 3: // EXT_FLAGS_SET_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("EXT_FLAGS_SET_REQ set ext_flags=0x%x, get ext_flags=0x%x\n", ++ addr[0], addr_out[0]); ++ } ++ break; ++ ++ case 4: // EXT_FLAGS_GET_REQ ++ if (ret != 1) { ++ printk("param error != 1\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("EXT_FLAGS_GET_REQ get ext_flags=0x%x\n", addr_out[0]); ++ } ++ break; ++ ++ case 5: // EXT_FLAGS_MASK_SET_REQ ++ if (ret != 3) { ++ printk("param error != 3\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("EXT_FLAGS_MASK_SET_REQ set ext_flags mask=0x%x, val=0x%x, get ext_flags=0x%x\n", ++ addr[0], addr[1], addr_out[0]); ++ } ++ break; ++ ++ default: ++ printk("param error\n"); ++ break; ++ } ++ ++ if (ret) { ++ printk("rwnx_send_vendor_swconfig_req fail: %x\n", ret); ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(vendor_swconfig); ++ ++static ssize_t rwnx_dbgfs_agg_disable_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[64]; ++ int agg_disable, agg_disable_rx, sta_idx; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ret; ++ printk("%s\n", __func__); ++ ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%d %d %d", &agg_disable, &agg_disable_rx, &sta_idx); ++ if ((ret > 3) || (ret < 2)) { ++ printk("param error: cnt=%d\n", ret); ++ } else { ++ if (ret < 3) { ++ sta_idx = RWNX_INVALID_STA; ++ } ++ printk("disable_agg: T=%d, R=%d, staidx=%d\n", agg_disable, agg_disable_rx, sta_idx); ++ ret = rwnx_send_disable_agg_req(priv, (u8_l)agg_disable, (u8_l)agg_disable_rx, (u8_l)sta_idx); ++ if (ret) { ++ printk("rwnx_send_disable_agg_req fail: %d\n", ret); ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(agg_disable); ++ ++static ssize_t rwnx_dbgfs_set_roc_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ struct rwnx_vif *vif = NULL; ++ char buf[64]; ++ int roc_start, chan_freq, duration; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ret; ++ int if_type = NL80211_IFTYPE_STATION; ++ printk("%s\n", __func__); ++ ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%d %d %d", &roc_start, &chan_freq, &duration); ++ ++ list_for_each_entry(vif, &priv->vifs, list) { ++ if (RWNX_VIF_TYPE(vif) == if_type) { ++ break; ++ } ++ } ++ if ((ret > 3) || (ret < 1)) { ++ printk("param error: cnt=%d\n", ret); ++ } else if (vif) { ++ struct ieee80211_channel chan_entry = {0,}; ++ struct ieee80211_channel *chan = &chan_entry; ++ struct mm_remain_on_channel_cfm roc_cfm; ++ if (ret < 3) { ++ duration = 2000; ++ if (ret < 2) { ++ chan_freq = 2412; ++ } ++ } ++ printk("set_roc: start=%d, freq=%d\n", roc_start, chan_freq); ++ if (roc_start) { ++ if (chan_freq <= 2484) { ++ chan->band = NL80211_BAND_2GHZ; ++ } else { ++ chan->band = NL80211_BAND_5GHZ; ++ } ++ chan->center_freq = chan_freq; ++ chan->max_power = 18; ++ ret = rwnx_send_roc(priv, vif, chan, duration, &roc_cfm); ++ if (ret) { ++ printk("rwnx_send_roc fail: %d\n", ret); ++ } else { ++ printk("roc_cfm: opcode=%x, st=%d, idx=%d\n", roc_cfm.op_code, roc_cfm.status, roc_cfm.chan_ctxt_index); ++ } ++ } else { ++ ret = rwnx_send_cancel_roc(priv); ++ if (ret) { ++ printk("rwnx_send_cancel_roc fail: %d\n", ret); ++ } ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(set_roc); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++#define LINE_MAX_SZ 150 ++ ++struct st { ++ char line[LINE_MAX_SZ + 1]; ++ unsigned int r_idx; ++}; ++ ++static int compare_idx(const void *st1, const void *st2) ++{ ++ int index1 = ((struct st *)st1)->r_idx; ++ int index2 = ((struct st *)st2)->r_idx; ++ ++ if (index1 > index2) ++ return 1; ++ if (index1 < index2) ++ return -1; ++ ++ return 0; ++} ++ ++static const int ru_size[] = { ++ 26, ++ 52, ++ 106, ++ 242, ++ 484, ++ 996 ++}; ++ ++static int print_rate(char *buf, int size, int format, int nss, int mcs, int bw, ++ int sgi, int pre, int *r_idx) ++{ ++ int res = 0; ++ int bitrates_cck[4] = { 10, 20, 55, 110 }; ++ int bitrates_ofdm[8] = { 6, 9, 12, 18, 24, 36, 48, 54}; ++ char he_gi[3][4] = {"0.8", "1.6", "3.2"}; ++ ++ if (format < FORMATMOD_HT_MF) { ++ if (mcs < 4) { ++ if (r_idx) { ++ *r_idx = (mcs * 2) + pre; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "L-CCK/%cP %2u.%1uM ", ++ pre > 0 ? 'L' : 'S', ++ bitrates_cck[mcs] / 10, ++ bitrates_cck[mcs] % 10); ++ } else { ++ mcs -= 4; ++ if (r_idx) { ++ *r_idx = N_CCK + mcs; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "L-OFDM %2u.0M ", ++ bitrates_ofdm[mcs]); ++ } ++ } else if (format < FORMATMOD_VHT) { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + nss * 32 + mcs * 4 + bw * 2 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ mcs += nss * 8; ++ res += scnprintf(&buf[res], size - res, "HT%d/%cGI MCS%-2d ", ++ 20 * (1 << bw), sgi ? 'S' : 'L', mcs); ++ } else if (format == FORMATMOD_VHT) { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + N_HT + nss * 80 + mcs * 8 + bw * 2 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "VHT%d/%cGI%*cMCS%d/%1d ", ++ 20 * (1 << bw), sgi ? 'S' : 'L', bw > 2 ? 5 : 6, ' ', ++ mcs, nss + 1); ++ } else if (format == FORMATMOD_HE_SU) { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + N_HT + N_VHT + nss * 144 + mcs * 12 + bw * 3 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "HE%d/GI%s%*cMCS%d/%1d%*c", ++ 20 * (1 << bw), he_gi[sgi], bw > 2 ? 4 : 5, ' ', ++ mcs, nss + 1, mcs > 9 ? 1 : 2, ' '); ++ } else { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU + nss * 216 + mcs * 18 + bw * 3 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "HEMU-%d/GI%s%*cMCS%d/%1d%*c", ++ ru_size[bw], he_gi[sgi], bw > 1 ? 1 : 2, ' ', ++ mcs, nss + 1, mcs > 9 ? 1 : 2, ' '); ++ ++ } ++ ++ return res; ++} ++ ++static int print_rate_from_cfg(char *buf, int size, u32 rate_config, int *r_idx, int ru_size) ++{ ++ union rwnx_rate_ctrl_info *r_cfg = (union rwnx_rate_ctrl_info *)&rate_config; ++ union rwnx_mcs_index *mcs_index = (union rwnx_mcs_index *)&rate_config; ++ unsigned int ft, pre, gi, bw, nss, mcs, len; ++ ++ ft = r_cfg->formatModTx; ++ pre = r_cfg->giAndPreTypeTx >> 1; ++ gi = r_cfg->giAndPreTypeTx; ++ bw = r_cfg->bwTx; ++ if (ft == FORMATMOD_HE_MU) { ++ mcs = mcs_index->he.mcs; ++ nss = mcs_index->he.nss; ++ bw = ru_size; ++ } else if (ft == FORMATMOD_HE_SU) { ++ mcs = mcs_index->he.mcs; ++ nss = mcs_index->he.nss; ++ } else if (ft == FORMATMOD_VHT) { ++ mcs = mcs_index->vht.mcs; ++ nss = mcs_index->vht.nss; ++ } else if (ft >= FORMATMOD_HT_MF) { ++ mcs = mcs_index->ht.mcs; ++ nss = mcs_index->ht.nss; ++ } else { ++ mcs = mcs_index->legacy; ++ nss = 0; ++ } ++ ++ len = print_rate(buf, size, ft, nss, mcs, bw, gi, pre, r_idx); ++ return len; ++} ++ ++static void idx_to_rate_cfg(int idx, union rwnx_rate_ctrl_info *r_cfg, int *ru_size) ++{ ++ r_cfg->value = 0; ++ if (idx < N_CCK) { ++ r_cfg->formatModTx = FORMATMOD_NON_HT; ++ r_cfg->giAndPreTypeTx = (idx & 1) << 1; ++ r_cfg->mcsIndexTx = idx / 2; ++ } else if (idx < (N_CCK + N_OFDM)) { ++ r_cfg->formatModTx = FORMATMOD_NON_HT; ++ r_cfg->mcsIndexTx = idx - N_CCK + 4; ++ } else if (idx < (N_CCK + N_OFDM + N_HT)) { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ idx -= (N_CCK + N_OFDM); ++ r_cfg->formatModTx = FORMATMOD_HT_MF; ++ r->ht.nss = idx / (8*2*2); ++ r->ht.mcs = (idx % (8*2*2)) / (2*2); ++ r_cfg->bwTx = ((idx % (8*2*2)) % (2*2)) / 2; ++ r_cfg->giAndPreTypeTx = idx & 1; ++ } else if (idx < (N_CCK + N_OFDM + N_HT + N_VHT)) { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ idx -= (N_CCK + N_OFDM + N_HT); ++ r_cfg->formatModTx = FORMATMOD_VHT; ++ r->vht.nss = idx / (10*4*2); ++ r->vht.mcs = (idx % (10*4*2)) / (4*2); ++ r_cfg->bwTx = ((idx % (10*4*2)) % (4*2)) / 2; ++ r_cfg->giAndPreTypeTx = idx & 1; ++ } else if (idx < (N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU)) { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ idx -= (N_CCK + N_OFDM + N_HT + N_VHT); ++ r_cfg->formatModTx = FORMATMOD_HE_SU; ++ r->vht.nss = idx / (12*4*3); ++ r->vht.mcs = (idx % (12*4*3)) / (4*3); ++ r_cfg->bwTx = ((idx % (12*4*3)) % (4*3)) / 3; ++ r_cfg->giAndPreTypeTx = idx % 3; ++ } else { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ BUG_ON(ru_size == NULL); ++ ++ idx -= (N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU); ++ r_cfg->formatModTx = FORMATMOD_HE_MU; ++ r->vht.nss = idx / (12*6*3); ++ r->vht.mcs = (idx % (12*6*3)) / (6*3); ++ *ru_size = ((idx % (12*6*3)) % (6*3)) / 3; ++ r_cfg->giAndPreTypeTx = idx % 3; ++ r_cfg->bwTx = 0; ++ } ++} ++ ++static void idx_to_rate_cfg1(unsigned int formatmod, ++ unsigned int mcs,unsigned int nss, ++ unsigned int bwTx,unsigned int gi, ++ union rwnx_rate_ctrl_info *r_cfg, int *ru_size) ++{ ++ r_cfg->value = 0; ++ ++ switch(formatmod){ ++ case FORMATMOD_NON_HT: ++ { ++ r_cfg->formatModTx = formatmod; ++ r_cfg->giAndPreTypeTx = 1; ++ r_cfg->mcsIndexTx = mcs; ++ break; ++ } ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ { ++ r_cfg->formatModTx = formatmod; ++ r_cfg->giAndPreTypeTx = gi; ++ r_cfg->mcsIndexTx = mcs; ++ break; ++ } ++ case FORMATMOD_HT_MF: ++ { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ r_cfg->formatModTx = formatmod; ++ r->ht.nss = nss; ++ r->ht.mcs = mcs; ++ r_cfg->bwTx = bwTx; ++ r_cfg->giAndPreTypeTx = gi; ++ break; ++ } ++ case FORMATMOD_VHT: ++ case FORMATMOD_HE_SU: ++ { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ r_cfg->formatModTx = formatmod; ++ r->vht.nss = nss; ++ r->vht.mcs = mcs; ++ r_cfg->bwTx = bwTx; ++ r_cfg->giAndPreTypeTx = gi; ++ break; ++ } ++ case FORMATMOD_HE_MU: ++ { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ r_cfg->formatModTx = formatmod; ++ r->he.nss = nss; ++ r->he.mcs = mcs; ++ r_cfg->bwTx = 0; ++ r_cfg->giAndPreTypeTx = gi; ++ break; ++ } ++ default: ++ printk("Don't have the formatmod"); ++ } ++} ++ ++static ssize_t rwnx_dbgfs_rc_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int bufsz, len = 0; ++ ssize_t read; ++ int i = 0; ++ int error = 0; ++ struct me_rc_stats_cfm me_rc_stats_cfm; ++ unsigned int no_samples; ++ struct st *st; ++ u8 mac[6]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* everything should fit in one call */ ++ if (*ppos) ++ return 0; ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ //if (mac == NULL) ++ // return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_me_rc_stats(priv, sta->sta_idx, &me_rc_stats_cfm); ++ if (error) ++ return error; ++ ++ no_samples = me_rc_stats_cfm.no_samples; ++ if (no_samples == 0) ++ return 0; ++ ++ bufsz = no_samples * LINE_MAX_SZ + 500; ++ ++ buf = kmalloc(bufsz + 1, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ st = kmalloc(sizeof(struct st) * no_samples, GFP_ATOMIC); ++ if (st == NULL) { ++ kfree(buf); ++ return 0; ++ } ++ ++ for (i = 0; i < no_samples; i++) { ++ unsigned int tp, eprob; ++ len = print_rate_from_cfg(st[i].line, LINE_MAX_SZ, ++ me_rc_stats_cfm.rate_stats[i].rate_config, ++ &st[i].r_idx, 0); ++ ++ if (me_rc_stats_cfm.sw_retry_step != 0) { ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c", ++ me_rc_stats_cfm.retry_step_idx[me_rc_stats_cfm.sw_retry_step] == i ? '*' : ' '); ++ } else { ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, " "); ++ } ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c", ++ me_rc_stats_cfm.retry_step_idx[0] == i ? 'T' : ' '); ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c", ++ me_rc_stats_cfm.retry_step_idx[1] == i ? 't' : ' '); ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c ", ++ me_rc_stats_cfm.retry_step_idx[2] == i ? 'P' : ' '); ++ ++ tp = me_rc_stats_cfm.tp[i] / 10; ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, " %4u.%1u", ++ tp / 10, tp % 10); ++ ++ eprob = ((me_rc_stats_cfm.rate_stats[i].probability * 1000) >> 16) + 1; ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, ++ " %4u.%1u %5u(%6u) %6u", ++ eprob / 10, eprob % 10, ++ me_rc_stats_cfm.rate_stats[i].success, ++ me_rc_stats_cfm.rate_stats[i].attempts, ++ me_rc_stats_cfm.rate_stats[i].sample_skipped); ++ } ++ len = scnprintf(buf, bufsz, ++ "\nTX rate info for %02X:%02X:%02X:%02X:%02X:%02X:\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ " # type rate tpt eprob ok( tot) skipped\n"); ++ ++ // add sorted statistics to the buffer ++ sort(st, no_samples, sizeof(st[0]), compare_idx, NULL); ++ for (i = 0; i < no_samples; i++) { ++ len += scnprintf(&buf[len], bufsz - len, "%s\n", st[i].line); ++ } ++ ++ // display HE TB statistics if any ++ if (me_rc_stats_cfm.rate_stats[RC_HE_STATS_IDX].rate_config != 0) { ++ unsigned int tp, eprob; ++ struct rc_rate_stats *rate_stats = &me_rc_stats_cfm.rate_stats[RC_HE_STATS_IDX]; ++ int ru_index = rate_stats->ru_and_length & 0x07; ++ int ul_length = rate_stats->ru_and_length >> 3; ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ "\nHE TB rate info:\n"); ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ " type rate tpt eprob ok( tot) ul_length\n "); ++ len += print_rate_from_cfg(&buf[len], bufsz - len, rate_stats->rate_config, ++ NULL, ru_index); ++ ++ tp = me_rc_stats_cfm.tp[RC_HE_STATS_IDX] / 10; ++ len += scnprintf(&buf[len], bufsz - len, " %4u.%1u", ++ tp / 10, tp % 10); ++ ++ eprob = ((rate_stats->probability * 1000) >> 16) + 1; ++ len += scnprintf(&buf[len], bufsz - len, ++ " %4u.%1u %5u(%6u) %6u\n", ++ eprob / 10, eprob % 10, ++ rate_stats->success, ++ rate_stats->attempts, ++ ul_length); ++ } ++ ++ len += scnprintf(&buf[len], bufsz - len, "\n MPDUs AMPDUs AvLen trialP"); ++ len += scnprintf(&buf[len], bufsz - len, "\n%6u %6u %3d.%1d %6u\n", ++ me_rc_stats_cfm.ampdu_len, ++ me_rc_stats_cfm.ampdu_packets, ++ me_rc_stats_cfm.avg_ampdu_len >> 16, ++ ((me_rc_stats_cfm.avg_ampdu_len * 10) >> 16) % 10, ++ me_rc_stats_cfm.sample_wait); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ kfree(st); ++ ++ return read; ++} ++ ++DEBUGFS_READ_FILE_OPS(rc_stats); ++ ++static ssize_t rwnx_dbgfs_rc_fixed_rate_idx_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ u8 mac[6]; ++ char buf[20]; ++ int fixed_rate_idx = 1; ++ unsigned int formatmod, mcs, nss, bwTx, gi; ++ union rwnx_rate_ctrl_info rate_config; ++ union rwnx_rate_ctrl_info *r_cfg=&rate_config; ++ int error = 0; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ //if (mac == NULL) ++ // return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ /* Get the content of the file */ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ //sscanf(buf, "%i\n", &fixed_rate_idx); ++ sscanf(buf, "%u %u %u %u %u",&formatmod, &mcs, &nss, &bwTx, &gi); ++ printk("%u %u %u %u %u\n",formatmod, mcs, nss, bwTx, gi); ++ ++ if((formatmod > 6) || (mcs > 11) || (nss > 8) || (bwTx > 6) || (gi > 3)){ ++ printk("error parameter"); ++ return len; ++ } ++ ++ /* Convert rate index into rate configuration */ ++ if ((fixed_rate_idx < 0) || (fixed_rate_idx >= (N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU))) ++ { ++ // disable fixed rate ++ rate_config.value = (u32)-1; ++ } ++ else ++ { ++ //idx_to_rate_cfg(fixed_rate_idx, &rate_config, NULL); ++ idx_to_rate_cfg1(formatmod, mcs, nss, bwTx, gi, &rate_config, NULL); ++ } ++ ++ printk("formatModTx=%u mcsIndexTx=%u bwTx=%u giAndPreTypeTx=%u\n",r_cfg->formatModTx,r_cfg->mcsIndexTx,r_cfg->bwTx,r_cfg->giAndPreTypeTx); ++ // Forward the request to the LMAC ++ if ((error = rwnx_send_me_rc_set_rate(priv, sta->sta_idx, ++ (u16)rate_config.value)) != 0) ++ { ++ return error; ++ } ++ ++ printk("send success \n"); ++ priv->debugfs.rc_config[sta->sta_idx] = (int)rate_config.value; ++ return len; ++ ++} ++ ++DEBUGFS_WRITE_FILE_OPS(rc_fixed_rate_idx); ++ ++static ssize_t rwnx_dbgfs_last_rx_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ struct rwnx_rx_rate_stats *rate_stats; ++ char *buf; ++ int bufsz, i, len = 0; ++ ssize_t read; ++ unsigned int fmt, pre, bw, nss, mcs, gi; ++ u8 mac[6]; ++ struct rx_vector_1 *last_rx; ++ char hist[] = "##################################################"; ++ int hist_len = sizeof(hist) - 1; ++ u8 nrx; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* everything should fit in one call */ ++ if (*ppos) ++ return 0; ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++// if (mac == NULL) ++// return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ rate_stats = &sta->stats.rx_rate; ++ bufsz = (rate_stats->rate_cnt * (50 + hist_len) + 200); ++ buf = kmalloc(bufsz + 1, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ // Get number of RX paths ++ nrx = (priv->version_cfm.version_phy_1 & MDM_NRX_MASK) >> MDM_NRX_LSB; ++ ++ len += scnprintf(buf, bufsz, ++ "\nRX rate info for %02X:%02X:%02X:%02X:%02X:%02X:\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ ++ // Display Statistics ++ for (i = 0; i < rate_stats->size; i++) { ++ if (rate_stats->table[i]) { ++ union rwnx_rate_ctrl_info rate_config; ++ int percent = (rate_stats->table[i] * 1000) / rate_stats->cpt; ++ int p = 0; ++ int ru_size = 0; ++ ++ idx_to_rate_cfg(i, &rate_config, &ru_size); ++ len += print_rate_from_cfg(&buf[len], bufsz - len, ++ rate_config.value, NULL, ru_size); ++ p = (percent * hist_len) / 1000; ++ len += scnprintf(&buf[len], bufsz - len, ": %6d(%3d.%1d%%)%.*s\n", ++ rate_stats->table[i], ++ percent / 10, percent % 10, p, hist); ++ } ++ } ++ ++ // Display detailed info of the last received rate ++ last_rx = &sta->stats.last_rx.rx_vect1; ++ ++ len += scnprintf(&buf[len], bufsz - len, "\nLast received rate\n" ++ " type rate LDPC STBC BEAMFM DCM DOPPLER %s\n", ++ (nrx > 1) ? "rssi1(dBm) rssi2(dBm)" : "rssi(dBm)"); ++ ++ fmt = last_rx->format_mod; ++ bw = last_rx->ch_bw; ++ pre = last_rx->pre_type; ++ if (fmt >= FORMATMOD_HE_SU) { ++ mcs = last_rx->he.mcs; ++ nss = last_rx->he.nss; ++ gi = last_rx->he.gi_type; ++ if (fmt == FORMATMOD_HE_MU) ++ bw = last_rx->he.ru_size; ++ } else if (fmt == FORMATMOD_VHT) { ++ mcs = last_rx->vht.mcs; ++ nss = last_rx->vht.nss; ++ gi = last_rx->vht.short_gi; ++ } else if (fmt >= FORMATMOD_HT_MF) { ++ mcs = last_rx->ht.mcs % 8; ++ nss = last_rx->ht.mcs / 8;; ++ gi = last_rx->ht.short_gi; ++ } else { ++ BUG_ON((mcs = legrates_lut[last_rx->leg_rate].idx) == -1); ++ nss = 0; ++ gi = 0; ++ } ++ ++ len += print_rate(&buf[len], bufsz - len, fmt, nss, mcs, bw, gi, pre, NULL); ++ ++ /* flags for HT/VHT/HE */ ++ if (fmt >= FORMATMOD_HE_SU) { ++ len += scnprintf(&buf[len], bufsz - len, " %c %c %c %c %c", ++ last_rx->he.fec ? 'L' : ' ', ++ last_rx->he.stbc ? 'S' : ' ', ++ last_rx->he.beamformed ? 'B' : ' ', ++ last_rx->he.dcm ? 'D' : ' ', ++ last_rx->he.doppler ? 'D' : ' '); ++ } else if (fmt == FORMATMOD_VHT) { ++ len += scnprintf(&buf[len], bufsz - len, " %c %c %c ", ++ last_rx->vht.fec ? 'L' : ' ', ++ last_rx->vht.stbc ? 'S' : ' ', ++ last_rx->vht.beamformed ? 'B' : ' '); ++ } else if (fmt >= FORMATMOD_HT_MF) { ++ len += scnprintf(&buf[len], bufsz - len, " %c %c ", ++ last_rx->ht.fec ? 'L' : ' ', ++ last_rx->ht.stbc ? 'S' : ' '); ++ } else { ++ len += scnprintf(&buf[len], bufsz - len, " "); ++ } ++ if (nrx > 1) { ++ len += scnprintf(&buf[len], bufsz - len, " %-4d %d\n", ++ last_rx->rssi1, last_rx->rssi1); ++ } else { ++ len += scnprintf(&buf[len], bufsz - len, " %d\n", last_rx->rssi1); ++ } ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_last_rx_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ u8 mac[6]; ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++// if (mac == NULL) ++// return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ /* Prevent from interrupt preemption as these statistics are updated under ++ * interrupt */ ++ spin_lock_bh(&priv->tx_lock); ++ memset(sta->stats.rx_rate.table, 0, ++ sta->stats.rx_rate.size * sizeof(sta->stats.rx_rate.table[0])); ++ sta->stats.rx_rate.cpt = 0; ++ sta->stats.rx_rate.rate_cnt = 0; ++ spin_unlock_bh(&priv->tx_lock); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(last_rx); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static void rwnx_rc_stat_work(struct work_struct *ws) ++{ ++ struct rwnx_debugfs *rwnx_debugfs = container_of(ws, struct rwnx_debugfs, ++ rc_stat_work); ++ struct rwnx_hw *rwnx_hw = container_of(rwnx_debugfs, struct rwnx_hw, ++ debugfs); ++ struct rwnx_sta *sta; ++ uint8_t ridx, sta_idx; ++ ++ ridx = rwnx_debugfs->rc_read; ++ sta_idx = rwnx_debugfs->rc_sta[ridx]; ++ if (sta_idx > (NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX)) { ++ WARN(1, "Invalid sta index %d", sta_idx); ++ return; ++ } ++ ++ rwnx_debugfs->rc_sta[ridx] = 0xFF; ++ ridx = (ridx + 1) % ARRAY_SIZE(rwnx_debugfs->rc_sta); ++ rwnx_debugfs->rc_read = ridx; ++ sta = &rwnx_hw->sta_table[sta_idx]; ++ if (!sta) { ++ WARN(1, "Invalid sta %d", sta_idx); ++ return; ++ } ++ ++ if (rwnx_debugfs->dir_sta[sta_idx] == NULL) { ++ /* register the sta */ ++ struct dentry *dir_rc = rwnx_debugfs->dir_rc; ++ struct dentry *dir_sta; ++ struct dentry *file; ++ char sta_name[18]; ++ struct rwnx_rx_rate_stats *rate_stats = &sta->stats.rx_rate; ++ int nb_rx_rate = N_CCK + N_OFDM; ++ struct rwnx_rc_config_save *rc_cfg, *next; ++ ++ if (sta->sta_idx >= NX_REMOTE_STA_MAX) { ++ scnprintf(sta_name, sizeof(sta_name), "bc_mc"); ++ } else { ++ scnprintf(sta_name, sizeof(sta_name), "%pM", sta->mac_addr); ++ } ++ ++ dir_sta = debugfs_create_dir(sta_name, dir_rc); ++ if (!dir_sta) ++ goto error; ++ ++ rwnx_debugfs->dir_sta[sta->sta_idx] = dir_sta; ++ ++ file = debugfs_create_file("stats", S_IRUSR, dir_sta, rwnx_hw, ++ &rwnx_dbgfs_rc_stats_ops); ++ if (IS_ERR_OR_NULL(file)) ++ goto error_after_dir; ++ ++ file = debugfs_create_file("fixed_rate_idx", S_IWUSR, dir_sta, rwnx_hw, ++ &rwnx_dbgfs_rc_fixed_rate_idx_ops); ++ if (IS_ERR_OR_NULL(file)) ++ goto error_after_dir; ++ ++ file = debugfs_create_file("rx_rate", S_IRUSR | S_IWUSR, dir_sta, rwnx_hw, ++ &rwnx_dbgfs_last_rx_ops); ++ if (IS_ERR_OR_NULL(file)) ++ goto error_after_dir; ++ ++ if (rwnx_hw->mod_params->ht_on) ++ nb_rx_rate += N_HT; ++ ++ if (rwnx_hw->mod_params->vht_on) ++ nb_rx_rate += N_VHT; ++ ++ if (rwnx_hw->mod_params->he_on) ++ nb_rx_rate += N_HE_SU + N_HE_MU; ++ ++ rate_stats->table = kzalloc(nb_rx_rate * sizeof(rate_stats->table[0]), ++ GFP_KERNEL); ++ if (!rate_stats->table) ++ goto error_after_dir; ++ ++ rate_stats->size = nb_rx_rate; ++ rate_stats->cpt = 0; ++ rate_stats->rate_cnt = 0; ++ ++ /* By default enable rate contoller */ ++ rwnx_debugfs->rc_config[sta_idx] = -1; ++ ++ /* Unless we already fix the rate for this station */ ++ list_for_each_entry_safe(rc_cfg, next, &rwnx_debugfs->rc_config_save, list) { ++ if (jiffies_to_msecs(jiffies - rc_cfg->timestamp) > RC_CONFIG_DUR) { ++ list_del(&rc_cfg->list); ++ kfree(rc_cfg); ++ } else if (!memcmp(rc_cfg->mac_addr, sta->mac_addr, ETH_ALEN)) { ++ rwnx_debugfs->rc_config[sta_idx] = rc_cfg->rate; ++ list_del(&rc_cfg->list); ++ kfree(rc_cfg); ++ break; ++ } ++ } ++ ++ if ((rwnx_debugfs->rc_config[sta_idx] >= 0) && ++ rwnx_send_me_rc_set_rate(rwnx_hw, sta_idx, ++ (u16)rwnx_debugfs->rc_config[sta_idx])) ++ rwnx_debugfs->rc_config[sta_idx] = -1; ++ ++ } else { ++ /* unregister the sta */ ++ if (sta->stats.rx_rate.table) { ++ kfree(sta->stats.rx_rate.table); ++ sta->stats.rx_rate.table = NULL; ++ } ++ sta->stats.rx_rate.size = 0; ++ sta->stats.rx_rate.cpt = 0; ++ sta->stats.rx_rate.rate_cnt = 0; ++ ++ /* If fix rate was set for this station, save the configuration in case ++ we reconnect to this station within RC_CONFIG_DUR msec */ ++ if (rwnx_debugfs->rc_config[sta_idx] >= 0) { ++ struct rwnx_rc_config_save *rc_cfg; ++ rc_cfg = kmalloc(sizeof(*rc_cfg), GFP_KERNEL); ++ if (rc_cfg) { ++ rc_cfg->rate = rwnx_debugfs->rc_config[sta_idx]; ++ rc_cfg->timestamp = jiffies; ++ memcpy(rc_cfg->mac_addr, sta->mac_addr, ETH_ALEN); ++ list_add_tail(&rc_cfg->list, &rwnx_debugfs->rc_config_save); ++ } ++ } ++ ++ debugfs_remove_recursive(rwnx_debugfs->dir_sta[sta_idx]); ++ rwnx_debugfs->dir_sta[sta->sta_idx] = NULL; ++ } ++ ++ return; ++ ++error_after_dir: ++ debugfs_remove_recursive(rwnx_debugfs->dir_sta[sta_idx]); ++ rwnx_debugfs->dir_sta[sta->sta_idx] = NULL; ++error: ++ dev_err(rwnx_hw->dev, ++ "Error while (un)registering debug entry for sta %d\n", sta_idx); ++} ++ ++void _rwnx_dbgfs_rc_stat_write(struct rwnx_debugfs *rwnx_debugfs, uint8_t sta_idx) ++{ ++ uint8_t widx = rwnx_debugfs->rc_write; ++ if (rwnx_debugfs->rc_sta[widx] != 0XFF) { ++ WARN(1, "Overlap in debugfs rc_sta table\n"); ++ } ++ ++ if (rwnx_debugfs->unregistering) ++ return; ++ ++ rwnx_debugfs->rc_sta[widx] = sta_idx; ++ widx = (widx + 1) % ARRAY_SIZE(rwnx_debugfs->rc_sta); ++ rwnx_debugfs->rc_write = widx; ++ ++ schedule_work(&rwnx_debugfs->rc_stat_work); ++} ++ ++void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{ ++ _rwnx_dbgfs_rc_stat_write(&rwnx_hw->debugfs, sta->sta_idx); ++} ++ ++void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{ ++ _rwnx_dbgfs_rc_stat_write(&rwnx_hw->debugfs, sta->sta_idx); ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct dentry *phyd = rwnx_hw->wiphy->debugfsdir; ++ struct dentry *dir_rc; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ struct rwnx_debugfs *rwnx_debugfs = &rwnx_hw->debugfs; ++ struct dentry *dir_drv, *dir_diags; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ dir_drv = debugfs_create_dir(name, phyd); ++ if (!dir_drv) ++ return -ENOMEM; ++ ++ rwnx_debugfs->dir = dir_drv; ++ rwnx_debugfs->unregistering = false; ++ ++ dir_diags = debugfs_create_dir("diags", dir_drv); ++ if (!dir_diags) ++ goto err; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ dir_rc = debugfs_create_dir("rc", dir_drv); ++ if (!dir_rc) ++ goto err; ++ rwnx_debugfs->dir_rc = dir_rc; ++ INIT_WORK(&rwnx_debugfs->rc_stat_work, rwnx_rc_stat_work); ++ INIT_LIST_HEAD(&rwnx_debugfs->rc_config_save); ++ rwnx_debugfs->rc_write = rwnx_debugfs->rc_read = 0; ++ memset(rwnx_debugfs->rc_sta, 0xFF, sizeof(rwnx_debugfs->rc_sta)); ++#endif ++ ++ DEBUGFS_ADD_U32(tcp_pacing_shift, dir_drv, &rwnx_hw->tcp_pacing_shift, ++ S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(stats, dir_drv, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(sys_stats, dir_drv, S_IRUSR); ++ DEBUGFS_ADD_FILE(txq, dir_drv, S_IRUSR); ++ DEBUGFS_ADD_FILE(acsinfo, dir_drv, S_IRUSR); ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ DEBUGFS_ADD_FILE(mu_group, dir_drv, S_IRUSR); ++#endif ++ DEBUGFS_ADD_FILE(regdbg, dir_drv, S_IWUSR); ++ DEBUGFS_ADD_FILE(vendor_hwconfig, dir_drv,S_IWUSR); ++ DEBUGFS_ADD_FILE(vendor_swconfig, dir_drv,S_IWUSR); ++ DEBUGFS_ADD_FILE(agg_disable, dir_drv,S_IWUSR); ++ DEBUGFS_ADD_FILE(set_roc, dir_drv,S_IWUSR); ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++ { ++ /* Create a p2p directory */ ++ struct dentry *dir_p2p; ++ dir_p2p = debugfs_create_dir("p2p", dir_drv); ++ if (!dir_p2p) ++ goto err; ++ ++ /* Add file allowing to control Opportunistic PS */ ++ DEBUGFS_ADD_FILE(oppps, dir_p2p, S_IRUSR); ++ /* Add file allowing to control Notice of Absence */ ++ DEBUGFS_ADD_FILE(noa, dir_p2p, S_IRUSR); ++ } ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++ if (rwnx_hw->fwlog_en) { ++ rwnx_fw_log_init(&rwnx_hw->debugfs.fw_log); ++ DEBUGFS_ADD_FILE(fw_log, dir_drv, S_IWUSR | S_IRUSR); ++ } ++#ifdef CONFIG_RWNX_RADAR ++ { ++ struct dentry *dir_radar, *dir_sec; ++ dir_radar = debugfs_create_dir("radar", dir_drv); ++ if (!dir_radar) ++ goto err; ++ ++ DEBUGFS_ADD_FILE(pulses_prim, dir_radar, S_IRUSR); ++ DEBUGFS_ADD_FILE(detected, dir_radar, S_IRUSR); ++ DEBUGFS_ADD_FILE(enable, dir_radar, S_IRUSR); ++ ++ if (rwnx_hw->phy.cnt == 2) { ++ DEBUGFS_ADD_FILE(pulses_sec, dir_radar, S_IRUSR); ++ ++ dir_sec = debugfs_create_dir("sec", dir_radar); ++ if (!dir_sec) ++ goto err; ++ ++ DEBUGFS_ADD_FILE(band, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(type, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(prim20, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(center1, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(center2, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(set, dir_sec, S_IWUSR | S_IRUSR); ++ } ++ } ++#endif /* CONFIG_RWNX_RADAR */ ++ return 0; ++ ++err: ++ rwnx_dbgfs_unregister(rwnx_hw); ++ return -ENOMEM; ++} ++ ++void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_debugfs *rwnx_debugfs = &rwnx_hw->debugfs; ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_rc_config_save *cfg, *next; ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ list_for_each_entry_safe(cfg, next, &rwnx_debugfs->rc_config_save, list) { ++ list_del(&cfg->list); ++ kfree(cfg); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (rwnx_hw->fwlog_en) ++ rwnx_fw_log_deinit(&rwnx_hw->debugfs.fw_log); ++ ++ if (!rwnx_hw->debugfs.dir) ++ return; ++ ++ rwnx_debugfs->unregistering = true; ++#ifdef CONFIG_RWNX_FULLMAC ++ flush_work(&rwnx_debugfs->rc_stat_work); ++#endif ++ debugfs_remove_recursive(rwnx_hw->debugfs.dir); ++ rwnx_hw->debugfs.dir = NULL; ++} ++ ++#endif /* CONFIG_DEBUG_FS */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h +new file mode 100644 +index 000000000000..7f5c7c9c575d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h +@@ -0,0 +1,202 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_debugfs.h ++ * ++ * @brief Miscellaneous utility function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++ ++#ifndef _RWNX_DEBUGFS_H_ ++#define _RWNX_DEBUGFS_H_ ++#include ++ ++#include ++#include ++#include "rwnx_fw_trace.h" ++ ++struct rwnx_hw; ++struct rwnx_sta; ++ ++/* some macros taken from iwlwifi */ ++/* TODO: replace with generic read and fill read buffer in open to avoid double ++ * reads */ ++#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ ++ if (!debugfs_create_file(#name, mode, parent, rwnx_hw, \ ++ &rwnx_dbgfs_##name##_ops)) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_X64(name, parent, ptr) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_x64(#name, S_IWUSR | S_IRUSR, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_U64(name, parent, ptr, mode) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_u64(#name, mode, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) ++#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ ++ debugfs_create_u32(#name, mode, \ ++ parent, ptr); \ ++} while (0) ++#else ++#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_u32(#name, mode, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++ } while (0) ++#endif ++ ++ ++ ++/* file operation */ ++#define DEBUGFS_READ_FUNC(name) \ ++ static ssize_t rwnx_dbgfs_##name##_read(struct file *file, \ ++ char __user *user_buf, \ ++ size_t count, loff_t *ppos); ++ ++#define DEBUGFS_WRITE_FUNC(name) \ ++ static ssize_t rwnx_dbgfs_##name##_write(struct file *file, \ ++ const char __user *user_buf,\ ++ size_t count, loff_t *ppos); ++ ++#define DEBUGFS_OPEN_FUNC(name) \ ++ static int rwnx_dbgfs_##name##_open(struct inode *inode, \ ++ struct file *file); ++ ++#define DEBUGFS_RELEASE_FUNC(name) \ ++ static int rwnx_dbgfs_##name##_release(struct inode *inode, \ ++ struct file *file); ++ ++#define DEBUGFS_READ_FILE_OPS(name) \ ++ DEBUGFS_READ_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .read = rwnx_dbgfs_##name##_read, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++#define DEBUGFS_WRITE_FILE_OPS(name) \ ++ DEBUGFS_WRITE_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .write = rwnx_dbgfs_##name##_write, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ ++ DEBUGFS_READ_FUNC(name); \ ++ DEBUGFS_WRITE_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .write = rwnx_dbgfs_##name##_write, \ ++ .read = rwnx_dbgfs_##name##_read, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++#define DEBUGFS_READ_WRITE_OPEN_RELEASE_FILE_OPS(name) \ ++ DEBUGFS_READ_FUNC(name); \ ++ DEBUGFS_WRITE_FUNC(name); \ ++ DEBUGFS_OPEN_FUNC(name); \ ++ DEBUGFS_RELEASE_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .write = rwnx_dbgfs_##name##_write, \ ++ .read = rwnx_dbgfs_##name##_read, \ ++ .open = rwnx_dbgfs_##name##_open, \ ++ .release = rwnx_dbgfs_##name##_release, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++ ++#ifdef CONFIG_RWNX_DEBUGFS ++ ++struct rwnx_debugfs { ++ unsigned long long rateidx; ++ struct dentry *dir; ++ bool trace_prst; ++ ++ char helper_cmd[64]; ++ //struct work_struct helper_work; ++ bool helper_scheduled; ++ spinlock_t umh_lock; ++ bool unregistering; ++ ++#ifndef CONFIG_RWNX_FHOST ++ struct rwnx_fw_log fw_log; ++#endif /* CONFIG_RWNX_FHOST */ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct work_struct rc_stat_work; ++ uint8_t rc_sta[NX_REMOTE_STA_MAX]; ++ uint8_t rc_write; ++ uint8_t rc_read; ++ struct dentry *dir_rc; ++ struct dentry *dir_sta[NX_REMOTE_STA_MAX]; ++ int rc_config[NX_REMOTE_STA_MAX]; ++ struct list_head rc_config_save; ++#endif ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++// Max duration in msecs to save rate config for a sta after disconnection ++#define RC_CONFIG_DUR 600000 ++ ++struct rwnx_rc_config_save { ++ struct list_head list; ++ unsigned long timestamp; ++ int rate; ++ u8 mac_addr[ETH_ALEN]; ++}; ++#endif ++ ++int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name); ++void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw); ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); ++void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); ++#endif ++#else ++struct rwnx_debugfs { ++}; ++static inline int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name) { return 0; } ++static inline void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw) {} ++#ifdef CONFIG_RWNX_FULLMAC ++static inline void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {} ++static inline void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {} ++#endif ++#endif /* CONFIG_RWNX_DEBUGFS */ ++ ++ ++#endif /* _RWNX_DEBUGFS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h +new file mode 100644 +index 000000000000..55e532bcbf8c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h +@@ -0,0 +1,769 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_defs.h ++ * ++ * @brief Main driver structure declarations for fullmac driver ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_DEFS_H_ ++#define _RWNX_DEFS_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rwnx_mod_params.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_tx.h" ++#include "rwnx_rx.h" ++#include "rwnx_radar.h" ++#include "rwnx_utils.h" ++#include "rwnx_mu_group.h" ++#include "rwnx_platform.h" ++#include "rwnx_cmds.h" ++#ifdef CONFIG_GKI ++#include "rwnx_gki.h" ++#endif ++#include "rwnx_compat.h" ++#ifdef CONFIG_FILTER_TCP_ACK ++#include "aicwf_tcp_ack.h" ++#endif ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#include "sdio_host.h" ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++#include "usb_host.h" ++#endif ++ ++#ifdef CONFIG_BR_SUPPORT ++#include "aic_br_ext.h" ++#endif /* CONFIG_BR_SUPPORT */ ++ ++#define WPI_HDR_LEN 18 ++#define WPI_PN_LEN 16 ++#define WPI_PN_OFST 2 ++#define WPI_MIC_LEN 16 ++#define WPI_KEY_LEN 32 ++#define WPI_SUBKEY_LEN 16 // WPI key is actually two 16bytes key ++ ++#define LEGACY_PS_ID 0 ++#define UAPSD_ID 1 ++ ++#define PS_SP_INTERRUPTED 255 ++#define MAC_ADDR_LEN 6 ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++enum nl80211_ac { ++ NL80211_AC_VO, ++ NL80211_AC_VI, ++ NL80211_AC_BE, ++ NL80211_AC_BK, ++ NL80211_NUM_ACS ++}; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++struct ieee80211_vht_operation { ++ u8 vht_op_info_chwidth; ++ u8 vht_op_info_chan_center_freq_seg1_idx; ++ u8 vht_op_info_chan_center_freq_seg2_idx; ++ __le16 vht_basic_mcs_set; ++} __packed; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++#define IEEE80211_RADIOTAP_VHT 21 ++#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004 ++#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040 ++ ++#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01 ++#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04 ++ ++#define NL80211_FEATURE_CELL_BASE_REG_HINTS 1 << 3 ++#define NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL 1 << 4 ++#define NL80211_FEATURE_SAE 1 << 5 ++#define NL80211_FEATURE_LOW_PRIORITY_SCAN 1 << 6 ++#define NL80211_FEATURE_SCAN_FLUSH 1 << 7 ++#define NL80211_FEATURE_AP_SCAN 1 << 8 ++#define NL80211_FEATURE_VIF_TXPOWER 1 << 9 ++#define NL80211_FEATURE_NEED_OBSS_SCAN 1 << 10 ++#define NL80211_FEATURE_P2P_GO_CTWIN 1 << 11 ++#define NL80211_FEATURE_P2P_GO_OPPPS 1 << 12 ++ ++/* 802.11ac VHT Capabilities */ ++#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 ++#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 ++#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 ++#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 ++#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 ++#define IEEE80211_VHT_CAP_RXLDPC 0x00000010 ++#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 ++#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 ++#define IEEE80211_VHT_CAP_TXSTBC 0x00000080 ++#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 ++#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 ++#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 ++#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 ++#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 ++#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 ++#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 ++#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000 ++#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 ++#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 ++#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 ++#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 ++#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23 ++#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \ ++ (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT) ++#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 ++#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 ++#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 ++#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 ++ ++enum ieee80211_vht_mcs_support { ++ IEEE80211_VHT_MCS_SUPPORT_0_7 = 0, ++ IEEE80211_VHT_MCS_SUPPORT_0_8 = 1, ++ IEEE80211_VHT_MCS_SUPPORT_0_9 = 2, ++ IEEE80211_VHT_MCS_NOT_SUPPORTED = 3, ++}; ++ ++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, ++}; ++ ++struct cfg80211_chan_def { ++ struct ieee80211_channel *chan; ++ enum nl80211_chan_width width; ++ u32 center_freq1; ++ u32 center_freq2; ++}; ++ ++enum nl80211_mesh_power_mode { ++ NL80211_MESH_POWER_UNKNOWN, ++ NL80211_MESH_POWER_ACTIVE, ++ NL80211_MESH_POWER_LIGHT_SLEEP, ++ NL80211_MESH_POWER_DEEP_SLEEP, ++ __NL80211_MESH_POWER_AFTER_LAST, ++ NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1 ++}; ++#endif ++ ++/** ++ * struct rwnx_bcn - Information of the beacon in used (AP mode) ++ * ++ * @head: head portion of beacon (before TIM IE) ++ * @tail: tail portion of beacon (after TIM IE) ++ * @ies: extra IEs (not used ?) ++ * @head_len: length of head data ++ * @tail_len: length of tail data ++ * @ies_len: length of extra IEs data ++ * @tim_len: length of TIM IE ++ * @len: Total beacon len (head + tim + tail + extra) ++ * @dtim: dtim period ++ */ ++struct rwnx_bcn { ++ u8 *head; ++ u8 *tail; ++ u8 *ies; ++ size_t head_len; ++ size_t tail_len; ++ size_t ies_len; ++ size_t tim_len; ++ size_t len; ++ u8 dtim; ++}; ++ ++/** ++ * struct rwnx_key - Key information ++ * ++ * @hw_idx: Idx of the key from hardware point of view ++ */ ++struct rwnx_key { ++ u8 hw_idx; ++}; ++ ++/** ++ * Structure containing information about a Mesh Path ++ */ ++struct rwnx_mesh_path { ++ struct list_head list; /* For rwnx_vif.mesh_paths */ ++ u8 path_idx; /* Path Index */ ++ struct mac_addr tgt_mac_addr; /* Target MAC Address */ ++ struct rwnx_sta *p_nhop_sta; /* Pointer to the Next Hop STA */ ++}; ++ ++struct rwnx_mesh_proxy { ++ struct list_head list; /* For rwnx_vif.mesh_proxy */ ++ struct mac_addr ext_sta_addr; /* Address of the External STA */ ++ struct mac_addr proxy_addr; /* Proxy MAC Address */ ++ bool local; /* Indicate if interface is a proxy for the device */ ++}; ++ ++/** ++ * struct rwnx_csa - Information for CSA (Channel Switch Announcement) ++ * ++ * @vif: Pointer to the vif doing the CSA ++ * @bcn: Beacon to use after CSA ++ * @elem: IPC buffer to send the new beacon to the fw ++ * @chandef: defines the channel to use after the switch ++ * @count: Current csa counter ++ * @status: Status of the CSA at fw level ++ * @ch_idx: Index of the new channel context ++ * @work: work scheduled at the end of CSA ++ */ ++struct rwnx_csa { ++ struct rwnx_vif *vif; ++ struct rwnx_bcn bcn; ++ struct rwnx_ipc_elem_var elem; ++ struct cfg80211_chan_def chandef; ++ int count; ++ int status; ++ int ch_idx; ++ struct work_struct work; ++}; ++ ++struct apm_probe_sta { ++ u8 sta_mac_addr[6]; ++ u8 vif_idx; ++ u64 probe_id; ++ struct work_struct apmprobestaWork; ++ struct workqueue_struct *apmprobesta_wq; ++}; ++/// Possible States of the TDLS link. ++enum tdls_status_tag { ++ /// TDLS link is not active (no TDLS peer connected) ++ TDLS_LINK_IDLE, ++ /// TDLS Setup Request transmitted ++ TDLS_SETUP_REQ_TX, ++ /// TDLS Setup Response transmitted ++ TDLS_SETUP_RSP_TX, ++ /// TDLS link is active (TDLS peer connected) ++ TDLS_LINK_ACTIVE, ++ /// TDLS Max Number of states. ++ TDLS_STATE_MAX ++}; ++ ++/* ++ * Structure used to save information relative to the TDLS peer. ++ * This is also linked within the rwnx_hw vifs list. ++ * ++ */ ++struct rwnx_tdls { ++ bool active; /* Indicate if TDLS link is active */ ++ bool initiator; /* Indicate if TDLS peer is the TDLS initiator */ ++ bool chsw_en; /* Indicate if channel switch is enabled */ ++ u8 last_tid; /* TID of the latest MPDU transmitted over the ++ TDLS direct link to the TDLS STA */ ++ u16 last_sn; /* Sequence number of the latest MPDU transmitted ++ over the TDLS direct link to the TDLS STA */ ++ bool ps_on; /* Indicate if the power save is enabled on the ++ TDLS STA */ ++ bool chsw_allowed; /* Indicate if TDLS channel switch is allowed */ ++}; ++ ++ ++/** ++ * enum rwnx_ap_flags - AP flags ++ * ++ * @RWNX_AP_ISOLATE Isolate clients (i.e. Don't brige packets transmitted by ++ * one client for another one) ++ */ ++enum rwnx_ap_flags { ++ RWNX_AP_ISOLATE = BIT(0), ++}; ++ ++/* ++ * Structure used to save information relative to the managed interfaces. ++ * This is also linked within the rwnx_hw vifs list. ++ * ++ */ ++struct rwnx_vif { ++ struct list_head list; ++ struct rwnx_hw *rwnx_hw; ++ struct wireless_dev wdev; ++ struct net_device *ndev; ++ struct net_device_stats net_stats; ++ struct rwnx_key key[6]; ++ unsigned long drv_flags; ++ atomic_t drv_conn_state; ++ u8 drv_vif_index; /* Identifier of the VIF in driver */ ++ u8 vif_index; /* Identifier of the station in FW */ ++ u8 ch_index; /* Channel context identifier */ ++ bool up; /* Indicate if associated netdev is up ++ (i.e. Interface is created at fw level) */ ++ bool use_4addr; /* Should we use 4addresses mode */ ++ bool is_resending; /* Indicate if a frame is being resent on this interface */ ++ bool user_mpm; /* In case of Mesh Point VIF, indicate if MPM is handled by userspace */ ++ bool roc_tdls; /* Indicate if the ROC has been called by a ++ TDLS station */ ++ u8 tdls_status; /* Status of the TDLS link */ ++ bool tdls_chsw_prohibited; /* Indicate if TDLS Channel Switch is prohibited */ ++ bool wep_enabled; /* 1 if WEP is enabled */ ++ bool wep_auth_err; /* 1 if auth status code is not supported auth alg when WEP enabled */ ++ enum nl80211_auth_type last_auth_type; /* Authentication type (algorithm) sent in the last connection ++ when WEP enabled */ ++ union { ++ struct { ++ struct rwnx_sta *ap; /* Pointer to the peer STA entry allocated for ++ the AP */ ++ struct rwnx_sta *tdls_sta; /* Pointer to the TDLS station */ ++ bool external_auth; /* Indicate if external authentication is in progress */ ++ u32 group_cipher_type; ++ u32 paired_cipher_type; ++ //connected network info start ++ char ssid[33];//ssid max is 32, but this has one spare for '\0' ++ int ssid_len; ++ u8 bssid[ETH_ALEN]; ++ u32 conn_owner_nlportid; ++ bool is_roam; ++ //connected network info end ++ } sta; ++ struct { ++ u16 flags; /* see rwnx_ap_flags */ ++ struct list_head sta_list; /* List of STA connected to the AP */ ++ struct rwnx_bcn bcn; /* beacon */ ++ u8 bcmc_index; /* Index of the BCMC sta to use */ ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ u8 aic_index; ++#endif ++ struct rwnx_csa *csa; ++ ++ struct list_head mpath_list; /* List of Mesh Paths used on this interface */ ++ struct list_head proxy_list; /* List of Proxies Information used on this interface */ ++ bool create_path; /* Indicate if we are waiting for a MESH_CREATE_PATH_CFM ++ message */ ++ int generation; /* Increased each time the list of Mesh Paths is updated */ ++ enum nl80211_mesh_power_mode mesh_pm; /* mesh power save mode currently set in firmware */ ++ enum nl80211_mesh_power_mode next_mesh_pm; /* mesh power save mode for next peer */ ++ } ap; ++ struct { ++ struct rwnx_vif *master; /* pointer on master interface */ ++ struct rwnx_sta *sta_4a; ++ } ap_vlan; ++ }; ++ ++ u8_l key_has_add; ++ u8_l is_p2p_vif; ++ struct apm_probe_sta sta_probe; ++ ++ #ifdef CONFIG_BR_SUPPORT ++ spinlock_t br_ext_lock; ++ /* unsigned int macclone_completed; */ ++ struct nat25_network_db_entry *nethash[NAT25_HASH_SIZE]; ++ int pppoe_connection_in_progress; ++ unsigned char pppoe_addr[MACADDRLEN]; ++ unsigned char scdb_mac[MACADDRLEN]; ++ unsigned char scdb_ip[4]; ++ struct nat25_network_db_entry *scdb_entry; ++ unsigned char br_mac[MACADDRLEN]; ++ unsigned char br_ip[4]; ++ ++ struct br_ext_info ethBrExtInfo; ++ #endif /* CONFIG_BR_SUPPORT */ ++}; ++ ++#define RWNX_VIF_TYPE(rwnx_vif) (rwnx_vif->wdev.iftype) ++ ++/** ++ * Structure used to store information relative to PS mode. ++ * ++ * @active: True when the sta is in PS mode. ++ * If false, other values should be ignored ++ * @pkt_ready: Number of packets buffered for the sta in drv's txq ++ * (1 counter for Legacy PS and 1 for U-APSD) ++ * @sp_cnt: Number of packets that remain to be pushed in the service period. ++ * 0 means that no service period is in progress ++ * (1 counter for Legacy PS and 1 for U-APSD) ++ */ ++struct rwnx_sta_ps { ++ bool active; ++ u16 pkt_ready[2]; ++ u16 sp_cnt[2]; ++}; ++ ++/** ++ * struct rwnx_rx_rate_stats - Store statistics for RX rates ++ * ++ * @table: Table indicating how many frame has been receive which each ++ * rate index. Rate index is the same as the one used by RC algo for TX ++ * @size: Size of the table array ++ * @cpt: number of frames received ++ */ ++struct rwnx_rx_rate_stats { ++ int *table; ++ int size; ++ int cpt; ++ int rate_cnt; ++}; ++ ++/** ++ * struct rwnx_sta_stats - Structure Used to store statistics specific to a STA ++ * ++ * @last_rx: Hardware vector of the last received frame ++ * @rx_rate: Statistics of the received rates ++ */ ++struct rwnx_sta_stats { ++ struct hw_vect last_rx; ++ struct rwnx_rx_rate_stats rx_rate; ++}; ++ ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++struct aic_sta { ++ u8 sta_idx; /* Identifier of the station */ ++ bool he; /* Flag indicating if the station supports HE */ ++ bool vht; /* Flag indicating if the station supports VHT */ ++ ++ struct ieee80211_he_cap_elem he_cap_elem; ++ struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ __le32 vht_cap_info; ++ struct ieee80211_vht_mcs_info supp_mcs; ++#endif ++}; ++#endif ++ ++/* ++ * Structure used to save information relative to the managed stations. ++ */ ++struct rwnx_sta { ++ struct list_head list; ++ u16 aid; /* association ID */ ++ u8 sta_idx; /* Identifier of the station */ ++ u8 vif_idx; /* Identifier of the VIF (fw id) the station ++ belongs to */ ++ u8 vlan_idx; /* Identifier of the VLAN VIF (fw id) the station ++ belongs to (= vif_idx if no vlan in used) */ ++ enum nl80211_band band; /* Band */ ++ enum nl80211_chan_width width; /* Channel width */ ++ u16 center_freq; /* Center frequency */ ++ u32 center_freq1; /* Center frequency 1 */ ++ u32 center_freq2; /* Center frequency 2 */ ++ u8 ch_idx; /* Identifier of the channel ++ context the station belongs to */ ++ bool qos; /* Flag indicating if the station ++ supports QoS */ ++ u8 acm; /* Bitfield indicating which queues ++ have AC mandatory */ ++ u16 uapsd_tids; /* Bitfield indicating which tids are subject to ++ UAPSD */ ++ u8 mac_addr[ETH_ALEN]; /* MAC address of the station */ ++ struct rwnx_key key; ++ bool valid; /* Flag indicating if the entry is valid */ ++ struct rwnx_sta_ps ps; /* Information when STA is in PS (AP only) */ ++#ifdef CONFIG_RWNX_BFMER ++ struct rwnx_bfmer_report *bfm_report; /* Beamforming report to be used for ++ VHT TX Beamforming */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ struct rwnx_sta_group_info group_info; /* MU grouping information for the STA */ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ bool ht; /* Flag indicating if the station ++ supports HT */ ++ bool vht; /* Flag indicating if the station ++ supports VHT */ ++ u32 ac_param[AC_MAX]; /* EDCA parameters */ ++ struct rwnx_tdls tdls; /* TDLS station information */ ++ struct rwnx_sta_stats stats; ++ enum nl80211_mesh_power_mode mesh_pm; /* link-specific mesh power save mode */ ++}; ++ ++static inline const u8 *rwnx_sta_addr(struct rwnx_sta *rwnx_sta) ++{ ++ return rwnx_sta->mac_addr; ++} ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++struct rwnx_amsdu_stats { ++ int done; ++ int failed; ++}; ++#endif ++ ++struct rwnx_stats { ++ int cfm_balance[NX_TXQ_CNT]; ++ unsigned long last_rx, last_tx; /* jiffies */ ++ int ampdus_tx[IEEE80211_MAX_AMPDU_BUF]; ++ int ampdus_rx[IEEE80211_MAX_AMPDU_BUF]; ++ int ampdus_rx_map[4]; ++ int ampdus_rx_miss; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ struct rwnx_amsdu_stats amsdus[NX_TX_PAYLOAD_MAX]; ++#endif ++ int amsdus_rx[64]; ++}; ++ ++struct rwnx_sec_phy_chan { ++ u16 prim20_freq; ++ u16 center_freq1; ++ u16 center_freq2; ++ enum nl80211_band band; ++ u8 type; ++}; ++ ++/* Structure that will contains all RoC information received from cfg80211 */ ++struct rwnx_roc_elem { ++ struct wireless_dev *wdev; ++ struct ieee80211_channel *chan; ++ unsigned int duration; ++ /* Used to avoid call of CFG80211 callback upon expiration of RoC */ ++ bool mgmt_roc; ++ /* Indicate if we have switch on the RoC channel */ ++ bool on_chan; ++}; ++ ++/* Structure containing channel survey information received from MAC */ ++struct rwnx_survey_info { ++ // Filled ++ u32 filled; ++ // Amount of time in ms the radio spent on the channel ++ u32 chan_time_ms; ++ // Amount of time the primary channel was sensed busy ++ u32 chan_time_busy_ms; ++ // Noise in dbm ++ s8 noise_dbm; ++}; ++ ++#define RWNX_CH_NOT_SET 0xFF ++#define RWNX_INVALID_VIF 0xFF ++#define RWNX_INVALID_STA 0xFF ++ ++/* Structure containing channel context information */ ++struct rwnx_chanctx { ++ struct cfg80211_chan_def chan_def; /* channel description */ ++ u8 count; /* number of vif using this ctxt */ ++}; ++ ++/** ++ * rwnx_phy_info - Phy information ++ * ++ * @phy_cnt: Number of phy interface ++ * @cfg: Configuration send to firmware ++ * @sec_chan: Channel configuration of the second phy interface (if phy_cnt > 1) ++ * @limit_bw: Set to true to limit BW on requested channel. Only set to use ++ * VHT with old radio that don't support 80MHz (deprecated) ++ */ ++struct rwnx_phy_info { ++ u8 cnt; ++ struct phy_cfg_tag cfg; ++ struct rwnx_sec_phy_chan sec_chan; ++ bool limit_bw; ++}; ++ ++ ++struct defrag_ctrl_info { ++ struct list_head list; ++ u8 sta_idx; ++ u8 tid; ++ u16 sn; ++ u8 next_fn; ++ u16 frm_len; ++ struct sk_buff *skb; ++ struct timer_list defrag_timer; ++ struct rwnx_hw *rwnx_hw; ++}; ++ ++struct amsdu_subframe_hdr { ++ u8 da[6]; ++ u8 sa[6]; ++ u16 sublen; ++}; ++ ++ ++/* rwnx driver status */ ++void rwnx_set_conn_state(atomic_t *drv_conn_state, int state); ++ ++enum rwnx_drv_connect_status { ++ RWNX_DRV_STATUS_DISCONNECTED = 0, ++ RWNX_DRV_STATUS_DISCONNECTING, ++ RWNX_DRV_STATUS_CONNECTING, ++ RWNX_DRV_STATUS_CONNECTED, ++ RWNX_DRV_STATUS_ROAMING, ++}; ++ ++static const char *const s_conn_state[] = { ++ "RWNX_DRV_STATUS_DISCONNECTED", ++ "RWNX_DRV_STATUS_DISCONNECTING", ++ "RWNX_DRV_STATUS_CONNECTING", ++ "RWNX_DRV_STATUS_CONNECTED", ++ "RWNX_DRV_STATUS_ROAMING", ++}; ++ ++ ++struct rwnx_hw { ++ struct rwnx_mod_params *mod_params; ++ struct device *dev; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ struct wiphy *wiphy; ++ struct list_head vifs; ++ struct rwnx_vif *vif_table[NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX]; /* indexed with fw id */ ++ struct rwnx_sta sta_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX]; ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ struct aic_sta aic_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX]; ++#endif ++ struct rwnx_survey_info survey[SCAN_CHANNEL_MAX]; ++ struct cfg80211_scan_request *scan_request; ++#ifdef CONFIG_SCHED_SCAN ++ struct cfg80211_sched_scan_request *sched_scan_req; ++#endif ++ struct rwnx_chanctx chanctx_table[NX_CHAN_CTXT_CNT]; ++ u8 cur_chanctx; ++ ++ u8 monitor_vif; /* FW id of the monitor interface, RWNX_INVALID_VIF if no monitor vif at fw level */ ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ /* tcp ack management */ ++ struct tcp_ack_manage ack_m; ++#endif ++ ++ /* RoC Management */ ++ struct rwnx_roc_elem *roc_elem; /* Information provided by cfg80211 in its remain on channel request */ ++ u32 roc_cookie_cnt; /* Counter used to identify RoC request sent by cfg80211 */ ++ ++ struct rwnx_cmd_mgr *cmd_mgr; ++ ++ struct rwnx_plat *plat; ++ ++ spinlock_t tx_lock; ++ spinlock_t cb_lock; ++ struct mutex mutex; /* per-device perimeter lock */ ++ ++ struct tasklet_struct task; ++ struct mm_version_cfm version_cfm; /* Lower layers versions - obtained via MM_VERSION_REQ */ ++ ++ u32 tcp_pacing_shift; ++ ++ /* IPC */ ++ struct ipc_host_env_tag *ipc_env; ++#ifdef AICWF_SDIO_SUPPORT ++ struct sdio_host_env_tag sdio_env; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct usb_host_env_tag usb_env; ++#endif ++ ++ struct rwnx_ipc_elem_pool e2amsgs_pool; ++ struct rwnx_ipc_elem_pool dbgmsgs_pool; ++ struct rwnx_ipc_elem_pool e2aradars_pool; ++ struct rwnx_ipc_elem_var pattern_elem; ++ struct rwnx_ipc_dbgdump_elem dbgdump_elem; ++ struct rwnx_ipc_elem_pool e2arxdesc_pool; ++ struct rwnx_ipc_skb_elem *e2aunsuprxvec_elems; ++ //struct rwnx_ipc_rxbuf_elems rxbuf_elems; ++ struct rwnx_ipc_elem_var scan_ie; ++ ++ struct kmem_cache *sw_txhdr_cache; ++ ++ struct rwnx_debugfs debugfs; ++ struct rwnx_stats stats; ++ ++#ifdef CONFIG_PREALLOC_TXQ ++ struct rwnx_txq *txq; ++#else ++ struct rwnx_txq txq[NX_NB_TXQ]; ++#endif ++ ++ struct rwnx_hwq hwq[NX_TXQ_CNT]; ++ ++ u64 avail_idx_map; ++ u8 vif_started; ++ bool adding_sta; ++ struct rwnx_phy_info phy; ++ ++ struct rwnx_radar radar; ++ ++ /* extended capabilities supported */ ++ u8 ext_capa[8]; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ struct rwnx_mu_info mu; ++#endif ++ u8 is_p2p_alive; ++ u8 is_p2p_connected; ++ struct timer_list p2p_alive_timer; ++ struct rwnx_vif *p2p_dev_vif; ++ atomic_t p2p_alive_timer_count; ++ bool band_5g_support; ++ u8_l vendor_info; ++ bool fwlog_en; ++ ++ struct list_head defrag_list; ++ spinlock_t defrag_lock; ++ ++ struct work_struct apmStalossWork; ++ struct workqueue_struct *apmStaloss_wq; ++ u8 apm_vif_idx; ++ u8 sta_mac_addr[6]; ++ ++ struct wakeup_source *ws_rx; ++ struct wakeup_source *ws_irqrx; ++ struct wakeup_source *ws_tx; ++ struct wakeup_source *ws_pwrctrl; ++ ++#ifdef CONFIG_SCHED_SCAN ++ bool is_sched_scan; ++#endif//CONFIG_SCHED_SCAN ++#ifdef CONFIG_TEMP_CONTROL ++ unsigned long started_jiffies; ++ s8_l temp; ++#endif ++ ++}; ++ ++u8 *rwnx_build_bcn(struct rwnx_bcn *bcn, struct cfg80211_beacon_data *new); ++ ++void rwnx_chanctx_link(struct rwnx_vif *vif, u8 idx, ++ struct cfg80211_chan_def *chandef); ++void rwnx_chanctx_unlink(struct rwnx_vif *vif); ++int rwnx_chanctx_valid(struct rwnx_hw *rwnx_hw, u8 idx); ++ ++extern u8 chip_id; ++ ++static inline bool is_multicast_sta(int sta_idx) ++{ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)) ++ { ++ return (sta_idx >= NX_REMOTE_STA_MAX_FOR_OLD_IC); ++ }else{ ++ return (sta_idx >= NX_REMOTE_STA_MAX); ++ } ++ ++} ++struct rwnx_sta *rwnx_get_sta(struct rwnx_hw *rwnx_hw, const u8 *mac_addr); ++ ++static inline uint8_t master_vif_idx(struct rwnx_vif *vif) ++{ ++ if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) { ++ return vif->ap_vlan.master->vif_index; ++ } else { ++ return vif->vif_index; ++ } ++} ++ ++void rwnx_external_auth_enable(struct rwnx_vif *vif); ++void rwnx_external_auth_disable(struct rwnx_vif *vif); ++ ++#endif /* _RWNX_DEFS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c +new file mode 100644 +index 000000000000..17d55da1156f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c +@@ -0,0 +1,297 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_dini.c - Add support for dini platform ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_dini.h" ++#include "rwnx_defs.h" ++#include "rwnx_irqs.h" ++#include "reg_access.h" ++ ++/* Config FPGA is accessed via bar0 */ ++#define CFPGA_DMA0_CTRL_REG 0x02C ++#define CFPGA_DMA1_CTRL_REG 0x04C ++#define CFPGA_DMA2_CTRL_REG 0x06C ++#define CFPGA_UINTR_SRC_REG 0x0E8 ++#define CFPGA_UINTR_MASK_REG 0x0EC ++#define CFPGA_BAR4_HIADDR_REG 0x100 ++#define CFPGA_BAR4_LOADDR_REG 0x104 ++#define CFPGA_BAR4_LOADDR_MASK_REG 0x110 ++#define CFPGA_BAR_TOUT 0x120 ++ ++#define CFPGA_DMA_CTRL_ENABLE 0x00001400 ++#define CFPGA_DMA_CTRL_DISABLE 0x00001000 ++#define CFPGA_DMA_CTRL_CLEAR 0x00001800 ++#define CFPGA_DMA_CTRL_REREAD_TIME_MASK (BIT(10) - 1) ++ ++#define CFPGA_BAR4_LOADDR_MASK_MAX 0xFF000000 ++ ++#define CFPGA_PCIEX_IT 0x00000001 ++#define CFPGA_ALL_ITS 0x0000000F ++ ++/* Programmable BAR4 Window start address */ ++#define CPU_RAM_WINDOW_HIGH 0x00000000 ++#define CPU_RAM_WINDOW_LOW 0x00000000 ++#define AHB_BRIDGE_WINDOW_HIGH 0x00000000 ++#define AHB_BRIDGE_WINDOW_LOW 0x60000000 ++ ++struct rwnx_dini { ++ u8 *pci_bar0_vaddr; ++ u8 *pci_bar4_vaddr; ++}; ++ ++static const u32 mv_cfg_fpga_dma_ctrl_regs[] = { ++ CFPGA_DMA0_CTRL_REG, ++ CFPGA_DMA1_CTRL_REG, ++ CFPGA_DMA2_CTRL_REG ++}; ++ ++/* This also clears running transactions */ ++static void dini_dma_on(struct rwnx_dini *rwnx_dini) ++{ ++ int i; ++ u32 reread_time; ++ volatile void *reg; ++ ++ for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) { ++ reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i]; ++ reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK; ++ ++ writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg); ++ writel(CFPGA_DMA_CTRL_ENABLE | reread_time, reg); ++ } ++} ++ ++/* This also clears running transactions */ ++static void dini_dma_off(struct rwnx_dini *rwnx_dini) ++{ ++ int i; ++ u32 reread_time; ++ volatile void *reg; ++ ++ for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) { ++ reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i]; ++ reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK; ++ ++ writel(CFPGA_DMA_CTRL_DISABLE | reread_time, reg); ++ writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg); ++ } ++} ++ ++ ++/* Configure address range for BAR4. ++ * By default BAR4_LOADDR_MASK value is 0xFF000000, then there is no need to ++ * change it because the addresses we need to access are covered by this mask ++ */ ++static void dini_set_bar4_win(u32 low, u32 high, struct rwnx_dini *rwnx_dini) ++{ ++ writel(low, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_REG); ++ writel(high, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_HIADDR_REG); ++ writel(CFPGA_BAR4_LOADDR_MASK_MAX, ++ rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_MASK_REG); ++} ++ ++ ++/** ++ * Enable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10 ++ * and request the corresponding IRQ line ++ */ ++int rwnx_cfpga_irq_enable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ unsigned int cfpga_uintr_mask; ++ volatile void *reg; ++ int ret; ++ ++ /* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */ ++ ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0, "rwnx", rwnx_hw); ++ if (ret) ++ return ret; ++ ++ reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG; ++ cfpga_uintr_mask = readl(reg); ++ writel(cfpga_uintr_mask | CFPGA_PCIEX_IT, reg); ++ ++ return ret; ++} ++ ++/** ++ * Disable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10 ++ * and free the corresponding IRQ line ++ */ ++int rwnx_cfpga_irq_disable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ unsigned int cfpga_uintr_mask; ++ volatile void *reg; ++ ++ reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG; ++ cfpga_uintr_mask = readl(reg); ++ writel(cfpga_uintr_mask & ~CFPGA_PCIEX_IT, reg); ++ ++ free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw); ++ ++ return 0; ++} ++ ++static int rwnx_dini_platform_enable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++#ifdef CONFIG_RWNX_SDM ++ writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT); ++#endif ++ ++ dini_dma_on(rwnx_dini); ++ return rwnx_cfpga_irq_enable(rwnx_hw); ++} ++ ++static int rwnx_dini_platform_disable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ int ret; ++ ++ ret = rwnx_cfpga_irq_disable(rwnx_hw); ++ dini_dma_off(rwnx_dini); ++ return ret; ++} ++ ++static void rwnx_dini_platform_deinit(struct rwnx_plat *rwnx_plat) ++{ ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++ pci_disable_device(rwnx_plat->pci_dev); ++ iounmap(rwnx_dini->pci_bar0_vaddr); ++ iounmap(rwnx_dini->pci_bar4_vaddr); ++ pci_release_regions(rwnx_plat->pci_dev); ++ ++ kfree(rwnx_plat); ++} ++ ++static u8 *rwnx_dini_get_address(struct rwnx_plat *rwnx_plat, int addr_name, ++ unsigned int offset) ++{ ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++ if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name)) ++ return NULL; ++ ++ if (addr_name == RWNX_ADDR_CPU) ++ dini_set_bar4_win(CPU_RAM_WINDOW_LOW, CPU_RAM_WINDOW_HIGH, rwnx_dini); ++ else ++ dini_set_bar4_win(AHB_BRIDGE_WINDOW_LOW, AHB_BRIDGE_WINDOW_HIGH, rwnx_dini); ++ ++ return rwnx_dini->pci_bar4_vaddr + offset; ++} ++ ++static void rwnx_dini_ack_irq(struct rwnx_plat *rwnx_plat) ++{ ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++ writel(CFPGA_ALL_ITS, rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_SRC_REG); ++} ++ ++static const u32 rwnx_dini_config_reg[] = { ++ NXMAC_DEBUG_PORT_SEL_ADDR, ++ SYSCTRL_DIAG_CONF_ADDR, ++ RF_V6_DIAGPORT_CONF1_ADDR, ++ RF_v6_PHYDIAG_CONF1_ADDR, ++}; ++ ++static int rwnx_dini_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list) ++{ ++ if (!list) ++ return 0; ++ ++ *list = rwnx_dini_config_reg; ++ return ARRAY_SIZE(rwnx_dini_config_reg); ++} ++ ++/** ++ * rwnx_dini_platform_init - Initialize the DINI platform ++ * ++ * @pci_dev PCI device ++ * @rwnx_plat Pointer on struct rwnx_stat * to be populated ++ * ++ * @return 0 on success, < 0 otherwise ++ * ++ * Allocate and initialize a rwnx_plat structure for the dini platform. ++ */ ++int rwnx_dini_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat) ++{ ++ struct rwnx_dini *rwnx_dini; ++ u16 pci_cmd; ++ int ret = 0; ++ ++ *rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_dini), ++ GFP_KERNEL); ++ if (!*rwnx_plat) ++ return -ENOMEM; ++ ++ rwnx_dini = (struct rwnx_dini *)(*rwnx_plat)->priv; ++ ++ /* Hotplug fixups */ ++ pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd); ++ pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; ++ pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd); ++ //pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2); ++ ++ ret = pci_enable_device(pci_dev); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_enable_device failed\n"); ++ goto out_enable; ++ } ++ ++ pci_set_master(pci_dev); ++#if 0 ++ ret = pci_request_regions(pci_dev, KBUILD_MODNAME); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_request_regions failed\n"); ++ goto out_request; ++ } ++#endif ++ rwnx_dini->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0); ++ if (!rwnx_dini->pci_bar0_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0); ++ ret = -ENOMEM; ++ goto out_bar0; ++ } ++ rwnx_dini->pci_bar4_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 4); ++ if (!rwnx_dini->pci_bar4_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 4); ++ ret = -ENOMEM; ++ goto out_bar4; ++ } ++ ++ (*rwnx_plat)->enable = rwnx_dini_platform_enable; ++ (*rwnx_plat)->disable = rwnx_dini_platform_disable; ++ (*rwnx_plat)->deinit = rwnx_dini_platform_deinit; ++ (*rwnx_plat)->get_address = rwnx_dini_get_address; ++ (*rwnx_plat)->ack_irq = rwnx_dini_ack_irq; ++ (*rwnx_plat)->get_config_reg = rwnx_dini_get_config_reg; ++ ++#ifdef CONFIG_RWNX_SDM ++ writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT); ++#endif ++ ++ return 0; ++ ++out_bar4: ++ iounmap(rwnx_dini->pci_bar0_vaddr); ++out_bar0: ++ pci_release_regions(pci_dev); ++//out_request: ++ pci_disable_device(pci_dev); ++out_enable: ++ kfree(*rwnx_plat); ++ return ret; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h +new file mode 100644 +index 000000000000..d9f57c10ed4f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h +@@ -0,0 +1,20 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_dini.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_DINI_H_ ++#define _RWNX_DINI_H_ ++ ++#include ++#include "rwnx_platform.h" ++ ++int rwnx_dini_platform_init(struct pci_dev *pci_dev, ++ struct rwnx_plat **rwnx_plat); ++ ++#endif /* _RWNX_DINI_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h +new file mode 100644 +index 000000000000..3bd59807f663 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h +@@ -0,0 +1,1326 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_events.h ++ * ++ * @brief Trace events definition ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM rwnx ++ ++#if !defined(_RWNX_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _RWNX_EVENTS_H ++ ++#include ++#ifndef CONFIG_RWNX_FHOST ++#include "rwnx_tx.h" ++#endif ++#include "rwnx_compat.h" ++ ++/***************************************************************************** ++ * TRACE function for MGMT TX (FULLMAC) ++ ****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++#include "linux/ieee80211.h" ++#if defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) ++#include ++ ++/* P2P Public Action Frames Definitions (see WiFi P2P Technical Specification, section 4.2.8) */ ++/* IEEE 802.11 Public Action Usage Category - Define P2P public action frames */ ++#define MGMT_ACTION_PUBLIC_CAT (0x04) ++/* Offset of OUI Subtype field in P2P Action Frame format */ ++#define MGMT_ACTION_OUI_SUBTYPE_OFFSET (6) ++/* P2P Public Action Frame Types */ ++enum p2p_action_type { ++ P2P_ACTION_GO_NEG_REQ = 0, /* GO Negociation Request */ ++ P2P_ACTION_GO_NEG_RSP, /* GO Negociation Response */ ++ P2P_ACTION_GO_NEG_CFM, /* GO Negociation Confirmation */ ++ P2P_ACTION_INVIT_REQ, /* P2P Invitation Request */ ++ P2P_ACTION_INVIT_RSP, /* P2P Invitation Response */ ++ P2P_ACTION_DEV_DISC_REQ, /* Device Discoverability Request */ ++ P2P_ACTION_DEV_DISC_RSP, /* Device Discoverability Response */ ++ P2P_ACTION_PROV_DISC_REQ, /* Provision Discovery Request */ ++ P2P_ACTION_PROV_DISC_RSP, /* Provision Discovery Response */ ++}; ++ ++const char *ftrace_print_mgmt_info(struct trace_seq *p, u16 frame_control, u8 cat, u8 type, u8 p2p) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ switch (frame_control & IEEE80211_FCTL_STYPE) { ++ case (IEEE80211_STYPE_ASSOC_REQ): ++ trace_seq_printf(p, "Association Request"); ++ break; ++ case (IEEE80211_STYPE_ASSOC_RESP): ++ trace_seq_printf(p, "Association Response"); ++ break; ++ case (IEEE80211_STYPE_REASSOC_REQ): ++ trace_seq_printf(p, "Reassociation Request"); ++ break; ++ case (IEEE80211_STYPE_REASSOC_RESP): ++ trace_seq_printf(p, "Reassociation Response"); ++ break; ++ case (IEEE80211_STYPE_PROBE_REQ): ++ trace_seq_printf(p, "Probe Request"); ++ break; ++ case (IEEE80211_STYPE_PROBE_RESP): ++ trace_seq_printf(p, "Probe Response"); ++ break; ++ case (IEEE80211_STYPE_BEACON): ++ trace_seq_printf(p, "Beacon"); ++ break; ++ case (IEEE80211_STYPE_ATIM): ++ trace_seq_printf(p, "ATIM"); ++ break; ++ case (IEEE80211_STYPE_DISASSOC): ++ trace_seq_printf(p, "Disassociation"); ++ break; ++ case (IEEE80211_STYPE_AUTH): ++ trace_seq_printf(p, "Authentication"); ++ break; ++ case (IEEE80211_STYPE_DEAUTH): ++ trace_seq_printf(p, "Deauthentication"); ++ break; ++ case (IEEE80211_STYPE_ACTION): ++ trace_seq_printf(p, "Action"); ++ if (cat == MGMT_ACTION_PUBLIC_CAT && type == 0x9) { ++ switch (p2p) { ++ case (P2P_ACTION_GO_NEG_REQ): ++ trace_seq_printf(p, ": GO Negociation Request"); ++ break; ++ case (P2P_ACTION_GO_NEG_RSP): ++ trace_seq_printf(p, ": GO Negociation Response"); ++ break; ++ case (P2P_ACTION_GO_NEG_CFM): ++ trace_seq_printf(p, ": GO Negociation Confirmation"); ++ break; ++ case (P2P_ACTION_INVIT_REQ): ++ trace_seq_printf(p, ": P2P Invitation Request"); ++ break; ++ case (P2P_ACTION_INVIT_RSP): ++ trace_seq_printf(p, ": P2P Invitation Response"); ++ break; ++ case (P2P_ACTION_DEV_DISC_REQ): ++ trace_seq_printf(p, ": Device Discoverability Request"); ++ break; ++ case (P2P_ACTION_DEV_DISC_RSP): ++ trace_seq_printf(p, ": Device Discoverability Response"); ++ break; ++ case (P2P_ACTION_PROV_DISC_REQ): ++ trace_seq_printf(p, ": Provision Discovery Request"); ++ break; ++ case (P2P_ACTION_PROV_DISC_RSP): ++ trace_seq_printf(p, ": Provision Discovery Response"); ++ break; ++ default: ++ trace_seq_printf(p, "Unknown p2p %d", p2p); ++ break; ++ } ++ } else { ++ switch (cat) { ++ case 0: ++ trace_seq_printf(p, ":Spectrum %d", type); ++ break; ++ case 1: ++ trace_seq_printf(p, ":QOS %d", type); break; ++ case 2: ++ trace_seq_printf(p, ":DLS %d", type); ++ break; ++ case 3: ++ trace_seq_printf(p, ":BA %d", type); ++ break; ++ case 4: ++ trace_seq_printf(p, ":Public %d", type); ++ break; ++ case 5: ++ trace_seq_printf(p, ":Radio Measure %d", type); ++ break; ++ case 6: ++ trace_seq_printf(p, ":Fast BSS %d", type); ++ break; ++ case 7: ++ trace_seq_printf(p, ":HT Action %d", type); ++ break; ++ case 8: ++ trace_seq_printf(p, ":SA Query %d", type); ++ break; ++ case 9: ++ trace_seq_printf(p, ":Protected Public %d", type); ++ break; ++ case 10: ++ trace_seq_printf(p, ":WNM %d", type); ++ break; ++ case 11: ++ trace_seq_printf(p, ":Unprotected WNM %d", type); ++ break; ++ case 12: ++ trace_seq_printf(p, ":TDLS %d", type); ++ break; ++ case 13: ++ trace_seq_printf(p, ":Mesh %d", type); ++ break; ++ case 14: ++ trace_seq_printf(p, ":MultiHop %d", type); ++ break; ++ case 15: ++ trace_seq_printf(p, ":Self Protected %d", type); ++ break; ++ case 126: ++ trace_seq_printf(p, ":Vendor protected"); ++ break; ++ case 127: ++ trace_seq_printf(p, ":Vendor"); ++ break; ++ default: ++ trace_seq_printf(p, ":Unknown category %d", cat); ++ break; ++ } ++ } ++ break; ++ default: ++ trace_seq_printf(p, "Unknown subtype %d", frame_control & IEEE80211_FCTL_STYPE); ++ break; ++ } ++ ++ trace_seq_putc(p, 0); ++ ++ return ret; ++} ++#endif /* defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) */ ++ ++#undef __print_mgmt_info ++#define __print_mgmt_info(frame_control, cat, type, p2p) ftrace_print_mgmt_info(p, frame_control, cat, type, p2p) ++ ++TRACE_EVENT( ++ roc, ++ TP_PROTO(u8 vif_idx, u16 freq, unsigned int duration), ++ TP_ARGS(vif_idx, freq, duration), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ __field(u16, freq) ++ __field(unsigned int, duration) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ __entry->freq = freq; ++ __entry->duration = duration; ++ ), ++ TP_printk("f=%d vif=%d dur=%d", ++ __entry->freq, __entry->vif_idx, __entry->duration) ++); ++ ++TRACE_EVENT( ++ cancel_roc, ++ TP_PROTO(u8 vif_idx), ++ TP_ARGS(vif_idx), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ ), ++ TP_printk("vif=%d", __entry->vif_idx) ++); ++ ++TRACE_EVENT( ++ roc_exp, ++ TP_PROTO(u8 vif_idx), ++ TP_ARGS(vif_idx), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ ), ++ TP_printk("vif=%d", __entry->vif_idx) ++); ++ ++TRACE_EVENT( ++ switch_roc, ++ TP_PROTO(u8 vif_idx), ++ TP_ARGS(vif_idx), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ ), ++ TP_printk("vif=%d", __entry->vif_idx) ++); ++ ++DECLARE_EVENT_CLASS( ++ mgmt_template, ++ TP_PROTO(u16 freq, u8 vif_idx, u8 sta_idx, struct ieee80211_mgmt *mgmt), ++ TP_ARGS(freq, vif_idx, sta_idx, mgmt), ++ TP_STRUCT__entry( ++ __field(u16, freq) ++ __field(u8, vif_idx) ++ __field(u8, sta_idx) ++ __field(u16, frame_control) ++ __field(u8, action_cat) ++ __field(u8, action_type) ++ __field(u8, action_p2p) ++ ), ++ TP_fast_assign( ++ __entry->freq = freq; ++ __entry->vif_idx = vif_idx; ++ __entry->sta_idx = sta_idx; ++ __entry->frame_control = mgmt->frame_control; ++ __entry->action_cat = mgmt->u.action.category; ++ __entry->action_type = mgmt->u.action.u.wme_action.action_code; ++ __entry->action_p2p = *((u8 *)&mgmt->u.action.category ++ + MGMT_ACTION_OUI_SUBTYPE_OFFSET); ++ ), ++ TP_printk("f=%d vif=%d sta=%d -> %s", ++ __entry->freq, __entry->vif_idx, __entry->sta_idx, ++ __print_mgmt_info(__entry->frame_control, __entry->action_cat, ++ __entry->action_type, __entry->action_p2p)) ++); ++ ++DEFINE_EVENT(mgmt_template, mgmt_tx, ++ TP_PROTO(u16 freq, u8 vif_idx, u8 sta_idx, struct ieee80211_mgmt *mgmt), ++ TP_ARGS(freq, vif_idx, sta_idx, mgmt)); ++ ++DEFINE_EVENT(mgmt_template, mgmt_rx, ++ TP_PROTO(u16 freq, u8 vif_idx, u8 sta_idx, struct ieee80211_mgmt *mgmt), ++ TP_ARGS(freq, vif_idx, sta_idx, mgmt)); ++ ++TRACE_EVENT( ++ mgmt_cfm, ++ TP_PROTO(u8 vif_idx, u8 sta_idx, bool acked), ++ TP_ARGS(vif_idx, sta_idx, acked), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ __field(u8, sta_idx) ++ __field(bool, acked) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ __entry->sta_idx = sta_idx; ++ __entry->acked = acked; ++ ), ++ TP_printk("vif=%d sta=%d ack=%d", ++ __entry->vif_idx, __entry->sta_idx, __entry->acked) ++); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/***************************************************************************** ++ * TRACE function for TXQ ++ ****************************************************************************/ ++#ifndef CONFIG_RWNX_FHOST ++#if defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) ++ ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#else ++#include ++#endif ++ ++const char * ++ftrace_print_txq(struct trace_seq *p, int txq_idx) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (txq_idx == TXQ_INACTIVE) { ++ trace_seq_printf(p, "[INACTIVE]"); ++ } else if (txq_idx < NX_FIRST_VIF_TXQ_IDX) { ++ trace_seq_printf(p, "[STA %d/%d]", ++ txq_idx / NX_NB_TXQ_PER_STA, ++ txq_idx % NX_NB_TXQ_PER_STA); ++#ifdef CONFIG_RWNX_FULLMAC ++ } else if (txq_idx < NX_FIRST_UNK_TXQ_IDX) { ++ trace_seq_printf(p, "[BC/MC %d]", ++ txq_idx - NX_FIRST_BCMC_TXQ_IDX); ++ } else if (txq_idx < NX_OFF_CHAN_TXQ_IDX) { ++ trace_seq_printf(p, "[UNKNOWN %d]", ++ txq_idx - NX_FIRST_UNK_TXQ_IDX); ++ } else if (txq_idx == NX_OFF_CHAN_TXQ_IDX) { ++ trace_seq_printf(p, "[OFFCHAN]"); ++#else ++ } else if (txq_idx < NX_NB_TXQ) { ++ txq_idx -= NX_FIRST_VIF_TXQ_IDX; ++ trace_seq_printf(p, "[VIF %d/%d]", ++ txq_idx / NX_NB_TXQ_PER_VIF, ++ txq_idx % NX_NB_TXQ_PER_VIF); ++#endif ++ } else { ++ trace_seq_printf(p, "[ERROR %d]", txq_idx); ++ } ++ ++ trace_seq_putc(p, 0); ++ ++ return ret; ++} ++ ++const char * ++ftrace_print_sta(struct trace_seq *p, int sta_idx) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (sta_idx < NX_REMOTE_STA_MAX) { ++ trace_seq_printf(p, "[STA %d]", sta_idx); ++ } else { ++ trace_seq_printf(p, "[BC/MC %d]", sta_idx - NX_REMOTE_STA_MAX); ++ } ++ ++ trace_seq_putc(p, 0); ++ ++ return ret; ++} ++ ++const char * ++ftrace_print_hwq(struct trace_seq *p, int hwq_idx) ++{ ++ ++ static const struct trace_print_flags symbols[] = { ++ {RWNX_HWQ_BK, "BK"}, ++ {RWNX_HWQ_BE, "BE"}, ++ {RWNX_HWQ_VI, "VI"}, ++ {RWNX_HWQ_VO, "VO"}, ++#ifdef CONFIG_RWNX_FULLMAC ++ {RWNX_HWQ_BCMC, "BCMC"}, ++#else ++ {RWNX_HWQ_BCN, "BCN"}, ++#endif ++ { -1, NULL } }; ++ return trace_print_symbols_seq(p, hwq_idx, symbols); ++} ++ ++const char * ++ftrace_print_hwq_cred(struct trace_seq *p, u8 *cred) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++#if CONFIG_USER_MAX == 1 ++ trace_seq_printf(p, "%d", cred[0]); ++#else ++ int i; ++ ++ for (i = 0; i < CONFIG_USER_MAX - 1; i++) ++ trace_seq_printf(p, "%d-", cred[i]); ++ trace_seq_printf(p, "%d", cred[i]); ++#endif ++ ++ trace_seq_putc(p, 0); ++ return ret; ++} ++ ++const char * ++ftrace_print_mu_info(struct trace_seq *p, u8 mu_info) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (mu_info) ++ trace_seq_printf(p, "MU: %d-%d", (mu_info & 0x3f), (mu_info >> 6)); ++ ++ trace_seq_putc(p, 0); ++ return ret; ++} ++ ++const char * ++ftrace_print_mu_group(struct trace_seq *p, int nb_user, u8 *users) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ int i; ++ ++ if (users[0] != 0xff) ++ trace_seq_printf(p, "(%d", users[0]); ++ else ++ trace_seq_printf(p, "(-"); ++ for (i = 1; i < CONFIG_USER_MAX ; i++) { ++ if (users[i] != 0xff) ++ trace_seq_printf(p, ",%d", users[i]); ++ else ++ trace_seq_printf(p, ",-"); ++ } ++ ++ trace_seq_printf(p, ")"); ++ trace_seq_putc(p, 0); ++ return ret; ++} ++ ++const char * ++ftrace_print_amsdu(struct trace_seq *p, u16 nb_pkt) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (nb_pkt > 1) ++ trace_seq_printf(p, "(AMSDU %d)", nb_pkt); ++ ++ trace_seq_putc(p, 0); ++ return ret; ++} ++#endif /* defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) */ ++ ++#undef __print_txq ++#define __print_txq(txq_idx) ftrace_print_txq(p, txq_idx) ++ ++#undef __print_sta ++#define __print_sta(sta_idx) ftrace_print_sta(p, sta_idx) ++ ++#undef __print_hwq ++#define __print_hwq(hwq) ftrace_print_hwq(p, hwq) ++ ++#undef __print_hwq_cred ++#define __print_hwq_cred(cred) ftrace_print_hwq_cred(p, cred) ++ ++#undef __print_mu_info ++#define __print_mu_info(mu_info) ftrace_print_mu_info(p, mu_info) ++ ++#undef __print_mu_group ++#define __print_mu_group(nb, users) ftrace_print_mu_group(p, nb, users) ++ ++#undef __print_amsdu ++#define __print_amsdu(nb_pkt) ftrace_print_amsdu(p, nb_pkt) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++TRACE_EVENT( ++ txq_select, ++ TP_PROTO(int txq_idx, u16 pkt_ready_up, struct sk_buff *skb), ++ TP_ARGS(txq_idx, pkt_ready_up, skb), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, pkt_ready) ++ __field(struct sk_buff *, skb) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq_idx; ++ __entry->pkt_ready = pkt_ready_up; ++ __entry->skb = skb; ++ ), ++ TP_printk("%s pkt_ready_up=%d skb=%p", __print_txq(__entry->txq_idx), ++ __entry->pkt_ready, __entry->skb) ++); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++DECLARE_EVENT_CLASS( ++ hwq_template, ++ TP_PROTO(u8 hwq_idx), ++ TP_ARGS(hwq_idx), ++ TP_STRUCT__entry( ++ __field(u8, hwq_idx) ++ ), ++ TP_fast_assign( ++ __entry->hwq_idx = hwq_idx; ++ ), ++ TP_printk("%s", __print_hwq(__entry->hwq_idx)) ++); ++ ++DEFINE_EVENT(hwq_template, hwq_flowctrl_stop, ++ TP_PROTO(u8 hwq_idx), ++ TP_ARGS(hwq_idx)); ++ ++DEFINE_EVENT(hwq_template, hwq_flowctrl_start, ++ TP_PROTO(u8 hwq_idx), ++ TP_ARGS(hwq_idx)); ++ ++ ++DECLARE_EVENT_CLASS( ++ txq_template, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ ), ++ TP_printk("%s", __print_txq(__entry->txq_idx)) ++); ++ ++DEFINE_EVENT(txq_template, txq_add_to_hw, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++DEFINE_EVENT(txq_template, txq_del_from_hw, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++DEFINE_EVENT(txq_template, txq_flowctrl_stop, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++DEFINE_EVENT(txq_template, txq_flowctrl_restart, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++TRACE_EVENT( ++ process_txq, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, len) ++ __field(u16, len_retry) ++ __field(s8, credit) ++ #ifdef CONFIG_RWNX_FULLMAC ++ __field(u16, limit) ++ #endif /* CONFIG_RWNX_FULLMAC*/ ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->len = skb_queue_len(&txq->sk_list); ++ #ifdef CONFIG_MAC80211_TXQ ++ __entry->len += txq->nb_ready_mac80211; ++ #endif ++ __entry->len_retry = txq->nb_retry; ++ __entry->credit = txq->credits; ++ #ifdef CONFIG_RWNX_FULLMAC ++ __entry->limit = txq->push_limit; ++ #endif /* CONFIG_RWNX_FULLMAC*/ ++ ), ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ TP_printk("%s txq_credits=%d, len=%d, retry_len=%d, push_limit=%d", ++ __print_txq(__entry->txq_idx), __entry->credit, ++ __entry->len, __entry->len_retry, __entry->limit) ++ #else ++ TP_printk("%s txq_credits=%d, len=%d, retry_len=%d", ++ __print_txq(__entry->txq_idx), __entry->credit, ++ __entry->len, __entry->len_retry) ++ #endif /* CONFIG_RWNX_FULLMAC*/ ++); ++ ++DECLARE_EVENT_CLASS( ++ txq_reason_template, ++ TP_PROTO(struct rwnx_txq *txq, u16 reason), ++ TP_ARGS(txq, reason), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, reason) ++ __field(u16, status) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->reason = reason; ++ __entry->status = txq->status; ++ ), ++ TP_printk("%s reason=%s status=%s", ++ __print_txq(__entry->txq_idx), ++ __print_symbolic(__entry->reason, ++ {RWNX_TXQ_STOP_FULL, "FULL"}, ++ {RWNX_TXQ_STOP_CSA, "CSA"}, ++ {RWNX_TXQ_STOP_STA_PS, "PS"}, ++ {RWNX_TXQ_STOP_VIF_PS, "VPS"}, ++ {RWNX_TXQ_STOP_CHAN, "CHAN"}, ++ {RWNX_TXQ_STOP_MU_POS, "MU"}), ++ __print_flags(__entry->status, "|", ++ {RWNX_TXQ_IN_HWQ_LIST, "IN LIST"}, ++ {RWNX_TXQ_STOP_FULL, "FULL"}, ++ {RWNX_TXQ_STOP_CSA, "CSA"}, ++ {RWNX_TXQ_STOP_STA_PS, "PS"}, ++ {RWNX_TXQ_STOP_VIF_PS, "VPS"}, ++ {RWNX_TXQ_STOP_CHAN, "CHAN"}, ++ {RWNX_TXQ_STOP_MU_POS, "MU"}, ++ {RWNX_TXQ_NDEV_FLOW_CTRL, "FLW_CTRL"})) ++); ++ ++DEFINE_EVENT(txq_reason_template, txq_start, ++ TP_PROTO(struct rwnx_txq *txq, u16 reason), ++ TP_ARGS(txq, reason)); ++ ++DEFINE_EVENT(txq_reason_template, txq_stop, ++ TP_PROTO(struct rwnx_txq *txq, u16 reason), ++ TP_ARGS(txq, reason)); ++ ++ ++TRACE_EVENT( ++ push_desc, ++ TP_PROTO(struct sk_buff *skb, struct rwnx_sw_txhdr *sw_txhdr, int push_flags), ++ ++ TP_ARGS(skb, sw_txhdr, push_flags), ++ ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(unsigned int, len) ++ __field(u16, tx_queue) ++ __field(u8, hw_queue) ++ __field(u8, push_flag) ++ __field(u32, flag) ++ __field(s8, txq_cred) ++ __field(u8, hwq_cred) ++ __field(u16, pkt_cnt) ++ __field(u8, mu_info) ++ ), ++ TP_fast_assign( ++ __entry->skb = skb; ++ __entry->tx_queue = sw_txhdr->txq->idx; ++ __entry->push_flag = push_flags; ++ __entry->hw_queue = sw_txhdr->txq->hwq->id; ++ __entry->txq_cred = sw_txhdr->txq->credits; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ __entry->pkt_cnt = sw_txhdr->desc.host.packet_cnt; ++#endif ++#ifdef CONFIG_RWNX_FULLMAC ++ __entry->flag = sw_txhdr->desc.host.flags; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->amsdu.len) ++ __entry->len = sw_txhdr->amsdu.len; ++ else ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ __entry->len = sw_txhdr->desc.host.packet_len[0]; ++#else ++ __entry->len = sw_txhdr->desc.host.packet_len; ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ ++#else /* !CONFIG_RWNX_FULLMAC */ ++ __entry->flag = sw_txhdr->desc.umac.flags; ++ __entry->len = sw_txhdr->frame_len; ++ __entry->sn = sw_txhdr->sn; ++#endif /* CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ __entry->mu_info = sw_txhdr->desc.host.mumimo_info; ++#else ++ __entry->mu_info = 0; ++#endif ++ ), ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ TP_printk("%s skb=%p (len=%d) hw_queue=%s cred_txq=%d cred_hwq=%d %s flag=%s %s%s%s", ++ __print_txq(__entry->tx_queue), __entry->skb, __entry->len, ++ __print_hwq(__entry->hw_queue), ++ __entry->txq_cred, __entry->hwq_cred, ++ __print_mu_info(__entry->mu_info), ++ __print_flags(__entry->flag, "|", ++ {TXU_CNTRL_RETRY, "RETRY"}, ++ {TXU_CNTRL_MORE_DATA, "MOREDATA"}, ++ {TXU_CNTRL_MGMT, "MGMT"}, ++ {TXU_CNTRL_MGMT_NO_CCK, "NO_CCK"}, ++ {TXU_CNTRL_MGMT_ROBUST, "ROBUST"}, ++ {TXU_CNTRL_AMSDU, "AMSDU"}, ++ {TXU_CNTRL_USE_4ADDR, "4ADDR"}, ++ {TXU_CNTRL_EOSP, "EOSP"}, ++ {TXU_CNTRL_MESH_FWD, "MESH_FWD"}, ++ {TXU_CNTRL_TDLS, "TDLS"}), ++ (__entry->push_flag & RWNX_PUSH_IMMEDIATE) ? "(IMMEDIATE)" : "", ++ (!(__entry->flag & TXU_CNTRL_RETRY) && ++ (__entry->push_flag & RWNX_PUSH_RETRY)) ? "(SW_RETRY)" : "", ++ __print_amsdu(__entry->pkt_cnt)) ++#else ++ TP_printk("%s skb=%p (len=%d) hw_queue=%s cred_txq=%d cred_hwq=%d %s flag=%x (%s) sn=%d %s", ++ __print_txq(__entry->tx_queue), __entry->skb, __entry->len, ++ __print_hwq(__entry->hw_queue), __entry->txq_cred, __entry->hwq_cred, ++ __print_mu_info(__entry->mu_info), ++ __entry->flag, ++ __print_flags(__entry->push_flag, "|", ++ {RWNX_PUSH_RETRY, "RETRY"}, ++ {RWNX_PUSH_IMMEDIATE, "IMMEDIATE"}), ++ __entry->sn, __print_amsdu(__entry->pkt_cnt)) ++#endif /* CONFIG_RWNX_FULLMAC */ ++); ++ ++ ++TRACE_EVENT( ++ txq_queue_skb, ++ TP_PROTO(struct sk_buff *skb, struct rwnx_txq *txq, bool retry), ++ TP_ARGS(skb, txq, retry), ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(s8, credit) ++ __field(u16, q_len) ++ __field(u16, q_len_retry) ++ __field(bool, retry) ++ ), ++ TP_fast_assign( ++ __entry->skb = skb; ++ __entry->txq_idx = txq->idx; ++ __entry->credit = txq->credits; ++ __entry->q_len = skb_queue_len(&txq->sk_list); ++ __entry->q_len_retry = txq->nb_retry; ++ __entry->retry = retry; ++ ), ++ ++ TP_printk("%s skb=%p retry=%d txq_credits=%d queue_len=%d (retry = %d)", ++ __print_txq(__entry->txq_idx), __entry->skb, __entry->retry, ++ __entry->credit, __entry->q_len, __entry->q_len_retry) ++); ++ ++#ifdef CONFIG_MAC80211_TXQ ++TRACE_EVENT( ++ txq_wake, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, q_len) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->q_len = txq->nb_ready_mac80211; ++ ), ++ ++ TP_printk("%s mac80211_queue_len=%d", __print_txq(__entry->txq_idx), __entry->q_len) ++); ++ ++TRACE_EVENT( ++ txq_drop, ++ TP_PROTO(struct rwnx_txq *txq, unsigned long nb_drop), ++ TP_ARGS(txq, nb_drop), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, nb_drop) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->nb_drop = nb_drop; ++ ), ++ ++ TP_printk("%s %u pkt have been dropped by codel in mac80211 txq", ++ __print_txq(__entry->txq_idx), __entry->nb_drop) ++); ++ ++#endif ++ ++ ++DECLARE_EVENT_CLASS( ++ idx_template, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ ), ++ TP_fast_assign( ++ __entry->idx = idx; ++ ), ++ TP_printk("idx=%d", __entry->idx) ++); ++ ++ ++DEFINE_EVENT(idx_template, txq_vif_start, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++DEFINE_EVENT(idx_template, txq_vif_stop, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++TRACE_EVENT( ++ process_hw_queue, ++ TP_PROTO(struct rwnx_hwq *hwq), ++ TP_ARGS(hwq), ++ TP_STRUCT__entry( ++ __field(u16, hwq) ++ __array(u8, credits, CONFIG_USER_MAX) ++ ), ++ TP_fast_assign( ++ __entry->hwq = hwq->id; ++ ), ++ TP_printk("hw_queue=%s hw_credits=%s", ++ __print_hwq(__entry->hwq), __print_hwq_cred(__entry->credits)) ++); ++ ++DECLARE_EVENT_CLASS( ++ sta_idx_template, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ ), ++ TP_fast_assign( ++ __entry->idx = idx; ++ ), ++ TP_printk("%s", __print_sta(__entry->idx)) ++); ++ ++DEFINE_EVENT(sta_idx_template, txq_sta_start, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++DEFINE_EVENT(sta_idx_template, txq_sta_stop, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++DEFINE_EVENT(sta_idx_template, ps_disable, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++TRACE_EVENT( ++ skb_confirm, ++ TP_PROTO(struct sk_buff *skb, struct rwnx_txq *txq, struct rwnx_hwq *hwq, ++#ifdef CONFIG_RWNX_FULLMAC ++ struct tx_cfm_tag *cfm ++#else ++ u8 cfm ++#endif ++ ), ++ ++ TP_ARGS(skb, txq, hwq, cfm), ++ ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(u8, hw_queue) ++ __array(u8, hw_credit, CONFIG_USER_MAX) ++ __field(s8, sw_credit) ++ __field(s8, sw_credit_up) ++#ifdef CONFIG_RWNX_FULLMAC ++ __field(u8, ampdu_size) ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ __field(u16, amsdu) ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ __field(u16, sn) ++#endif /* CONFIG_RWNX_FULLMAC*/ ++ ), ++ ++ TP_fast_assign( ++ __entry->skb = skb; ++ __entry->txq_idx = txq->idx; ++ __entry->hw_queue = hwq->id; ++ __entry->sw_credit = txq->credits; ++#if defined CONFIG_RWNX_FULLMAC ++ __entry->sw_credit_up = cfm->credits; ++ __entry->ampdu_size = cfm->ampdu_size; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ __entry->amsdu = cfm->amsdu_size; ++ __entry->sn = cfm->sn; ++#endif ++#else ++ __entry->sw_credit_up = cfm ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ), ++ ++ TP_printk("%s skb=%p hw_queue=%s, hw_credits=%s, txq_credits=%d (+%d)" ++#ifdef CONFIG_RWNX_FULLMAC ++ " sn=%u ampdu=%d" ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ " amsdu=%u" ++#endif ++#endif ++ , __print_txq(__entry->txq_idx), __entry->skb, ++ __print_hwq(__entry->hw_queue), ++ __print_hwq_cred(__entry->hw_credit), ++ __entry->sw_credit, __entry->sw_credit_up ++#ifdef CONFIG_RWNX_FULLMAC ++ , __entry->sn, __entry->ampdu_size ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ , __entry->amsdu ++#endif ++#endif ++ ) ++); ++ ++TRACE_EVENT( ++ credit_update, ++ TP_PROTO(struct rwnx_txq *txq, s8_l cred_up), ++ ++ TP_ARGS(txq, cred_up), ++ ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(s8, sw_credit) ++ __field(s8, sw_credit_up) ++ ), ++ ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->sw_credit = txq->credits; ++ __entry->sw_credit_up = cred_up; ++ ), ++ ++ TP_printk("%s txq_credits=%d (%+d)", __print_txq(__entry->txq_idx), ++ __entry->sw_credit, __entry->sw_credit_up) ++) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++DECLARE_EVENT_CLASS( ++ ps_template, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ __field(u16, ready_ps) ++ __field(u16, sp_ps) ++ __field(u16, ready_uapsd) ++ __field(u16, sp_uapsd) ++ ), ++ TP_fast_assign( ++ __entry->idx = sta->sta_idx; ++ __entry->ready_ps = sta->ps.pkt_ready[LEGACY_PS_ID]; ++ __entry->sp_ps = sta->ps.sp_cnt[LEGACY_PS_ID]; ++ __entry->ready_uapsd = sta->ps.pkt_ready[UAPSD_ID]; ++ __entry->sp_uapsd = sta->ps.sp_cnt[UAPSD_ID]; ++ ), ++ ++ TP_printk("%s [PS] ready=%d sp=%d [UAPSD] ready=%d sp=%d", ++ __print_sta(__entry->idx), __entry->ready_ps, __entry->sp_ps, ++ __entry->ready_uapsd, __entry->sp_uapsd) ++); ++ ++DEFINE_EVENT(ps_template, ps_queue, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta)); ++ ++DEFINE_EVENT(ps_template, ps_push, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta)); ++ ++DEFINE_EVENT(ps_template, ps_enable, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta)); ++ ++TRACE_EVENT( ++ ps_traffic_update, ++ TP_PROTO(u16 sta_idx, u8 traffic, bool uapsd), ++ ++ TP_ARGS(sta_idx, traffic, uapsd), ++ ++ TP_STRUCT__entry( ++ __field(u16, sta_idx) ++ __field(u8, traffic) ++ __field(bool, uapsd) ++ ), ++ ++ TP_fast_assign( ++ __entry->sta_idx = sta_idx; ++ __entry->traffic = traffic; ++ __entry->uapsd = uapsd; ++ ), ++ ++ TP_printk("%s %s%s traffic available ", __print_sta(__entry->sta_idx), ++ __entry->traffic ? "" : "no more ", ++ __entry->uapsd ? "U-APSD" : "legacy PS") ++); ++ ++TRACE_EVENT( ++ ps_traffic_req, ++ TP_PROTO(struct rwnx_sta *sta, u16 pkt_req, u8 ps_id), ++ TP_ARGS(sta, pkt_req, ps_id), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ __field(u16, pkt_req) ++ __field(u8, ps_id) ++ __field(u16, ready) ++ __field(u16, sp) ++ ), ++ TP_fast_assign( ++ __entry->idx = sta->sta_idx; ++ __entry->pkt_req = pkt_req; ++ __entry->ps_id = ps_id; ++ __entry->ready = sta->ps.pkt_ready[ps_id]; ++ __entry->sp = sta->ps.sp_cnt[ps_id]; ++ ), ++ ++ TP_printk("%s %s traffic request %d pkt (ready=%d, sp=%d)", ++ __print_sta(__entry->idx), ++ __entry->ps_id == UAPSD_ID ? "U-APSD" : "legacy PS", ++ __entry->pkt_req, __entry->ready, __entry->sp) ++); ++ ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++TRACE_EVENT( ++ amsdu_subframe, ++ TP_PROTO(struct rwnx_sw_txhdr *sw_txhdr), ++ TP_ARGS(sw_txhdr), ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(u8, nb) ++ __field(u32, len) ++ ), ++ TP_fast_assign( ++ __entry->skb = sw_txhdr->skb; ++ __entry->nb = sw_txhdr->amsdu.nb; ++ __entry->len = sw_txhdr->amsdu.len; ++ __entry->txq_idx = sw_txhdr->txq->idx; ++ ), ++ ++ TP_printk("%s skb=%p %s nb_subframe=%d, len=%u", ++ __print_txq(__entry->txq_idx), __entry->skb, ++ (__entry->nb == 2) ? "Start new AMSDU" : "Add subframe", ++ __entry->nb, __entry->len) ++); ++#endif ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++TRACE_EVENT( ++ mu_group_update, ++ TP_PROTO(struct rwnx_mu_group *group), ++ TP_ARGS(group), ++ TP_STRUCT__entry( ++ __field(u8, nb_user) ++ __field(u8, group_id) ++ __array(u8, users, CONFIG_USER_MAX) ++ ), ++ TP_fast_assign( ++ int i; ++ __entry->nb_user = group->user_cnt; ++ for (i = 0; i < CONFIG_USER_MAX ; i++) { ++ if (group->users[i]) { ++ __entry->users[i] = group->users[i]->sta_idx; ++ } else { ++ __entry->users[i] = 0xff; ++ } ++ } ++ ++ __entry->group_id = group->group_id; ++ ), ++ ++ TP_printk("Group-id = %d, Users = %s", ++ __entry->group_id, ++ __print_mu_group(__entry->nb_user, __entry->users)) ++); ++ ++TRACE_EVENT( ++ mu_group_delete, ++ TP_PROTO(int group_id), ++ TP_ARGS(group_id), ++ TP_STRUCT__entry( ++ __field(u8, group_id) ++ ), ++ TP_fast_assign( ++ __entry->group_id = group_id; ++ ), ++ ++ TP_printk("Group-id = %d", __entry->group_id) ++); ++ ++TRACE_EVENT( ++ mu_group_selection, ++ TP_PROTO(struct rwnx_sta *sta, int group_id), ++ TP_ARGS(sta, group_id), ++ TP_STRUCT__entry( ++ __field(u8, sta_idx) ++ __field(u8, group_id) ++ ), ++ TP_fast_assign( ++ __entry->sta_idx = sta->sta_idx; ++ __entry->group_id = group_id; ++ ), ++ ++ TP_printk("[Sta %d] Group-id = %d", __entry->sta_idx, __entry->group_id) ++); ++ ++TRACE_EVENT( ++ txq_select_mu_group, ++ TP_PROTO(struct rwnx_txq *txq, int group_id, int pos), ++ ++ TP_ARGS(txq, group_id, pos), ++ ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u8, group_id) ++ __field(u8, pos) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->group_id = group_id; ++ __entry->pos = pos; ++ ), ++ ++ TP_printk("%s: group=%d pos=%d", __print_txq(__entry->txq_idx), ++ __entry->group_id, __entry->pos) ++); ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* ! CONFIG_RWNX_FHOST */ ++ ++/***************************************************************************** ++ * TRACE functions for MESH ++ ****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++DECLARE_EVENT_CLASS( ++ mesh_path_template, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path), ++ TP_STRUCT__entry( ++ __field(u8, idx) ++ __field(u8, next_hop_sta) ++ __array(u8, tgt_mac, ETH_ALEN) ++ ), ++ ++ TP_fast_assign( ++ __entry->idx = mesh_path->path_idx; ++ memcpy(__entry->tgt_mac, &mesh_path->tgt_mac_addr, ETH_ALEN); ++ if (mesh_path->p_nhop_sta) ++ __entry->next_hop_sta = mesh_path->p_nhop_sta->sta_idx; ++ else ++ __entry->next_hop_sta = 0xff; ++ ), ++ ++ TP_printk("Mpath(%d): target=%pM next_hop=STA-%d", ++ __entry->idx, __entry->tgt_mac, __entry->next_hop_sta) ++); ++ ++DEFINE_EVENT(mesh_path_template, mesh_create_path, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path)); ++ ++DEFINE_EVENT(mesh_path_template, mesh_delete_path, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path)); ++ ++DEFINE_EVENT(mesh_path_template, mesh_update_path, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path)); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/***************************************************************************** ++ * TRACE functions for RADAR ++ ****************************************************************************/ ++#ifdef CONFIG_RWNX_RADAR ++TRACE_EVENT( ++ radar_pulse, ++ TP_PROTO(u8 chain, struct radar_pulse *pulse), ++ TP_ARGS(chain, pulse), ++ TP_STRUCT__entry( ++ __field(u8, chain) ++ __field(s16, freq) ++ __field(u16, pri) ++ __field(u8, len) ++ __field(u8, fom) ++ ), ++ TP_fast_assign( ++ __entry->freq = pulse->freq * 2; ++ __entry->len = pulse->len * 2; ++ __entry->fom = pulse->fom * 6; ++ __entry->pri = pulse->rep; ++ __entry->chain = chain; ++ ), ++ ++ TP_printk("%s: PRI=%.5d LEN=%.3d FOM=%.2d%% freq=%dMHz ", ++ __print_symbolic(__entry->chain, ++ {RWNX_RADAR_RIU, "RIU"}, ++ {RWNX_RADAR_FCU, "FCU"}), ++ __entry->pri, __entry->len, __entry->fom, __entry->freq) ++ ); ++ ++TRACE_EVENT( ++ radar_detected, ++ TP_PROTO(u8 chain, u8 region, s16 freq, u8 type, u16 pri), ++ TP_ARGS(chain, region, freq, type, pri), ++ TP_STRUCT__entry( ++ __field(u8, chain) ++ __field(u8, region) ++ __field(s16, freq) ++ __field(u8, type) ++ __field(u16, pri) ++ ), ++ TP_fast_assign( ++ __entry->chain = chain; ++ __entry->region = region; ++ __entry->freq = freq; ++ __entry->type = type; ++ __entry->pri = pri; ++ ), ++ TP_printk("%s: region=%s type=%d freq=%dMHz (pri=%dus)", ++ __print_symbolic(__entry->chain, ++ {RWNX_RADAR_RIU, "RIU"}, ++ {RWNX_RADAR_FCU, "FCU"}), ++ __print_symbolic(__entry->region, ++ {NL80211_DFS_UNSET, "UNSET"}, ++ {NL80211_DFS_FCC, "FCC"}, ++ {NL80211_DFS_ETSI, "ETSI"}, ++ {NL80211_DFS_JP, "JP"}), ++ __entry->type, __entry->freq, __entry->pri) ++); ++ ++TRACE_EVENT( ++ radar_set_region, ++ TP_PROTO(u8 region), ++ TP_ARGS(region), ++ TP_STRUCT__entry( ++ __field(u8, region) ++ ), ++ TP_fast_assign( ++ __entry->region = region; ++ ), ++ TP_printk("region=%s", ++ __print_symbolic(__entry->region, ++ {NL80211_DFS_UNSET, "UNSET"}, ++ {NL80211_DFS_FCC, "FCC"}, ++ {NL80211_DFS_ETSI, "ETSI"}, ++ {NL80211_DFS_JP, "JP"})) ++); ++ ++TRACE_EVENT( ++ radar_enable_detection, ++ TP_PROTO(u8 region, u8 enable, u8 chain), ++ TP_ARGS(region, enable, chain), ++ TP_STRUCT__entry( ++ __field(u8, region) ++ __field(u8, chain) ++ __field(u8, enable) ++ ), ++ TP_fast_assign( ++ __entry->chain = chain; ++ __entry->enable = enable; ++ __entry->region = region; ++ ), ++ TP_printk("%s: %s radar detection %s", ++ __print_symbolic(__entry->chain, ++ {RWNX_RADAR_RIU, "RIU"}, ++ {RWNX_RADAR_FCU, "FCU"}), ++ __print_symbolic(__entry->enable, ++ {RWNX_RADAR_DETECT_DISABLE, "Disable"}, ++ {RWNX_RADAR_DETECT_ENABLE, "Enable (no report)"}, ++ {RWNX_RADAR_DETECT_REPORT, "Enable"}), ++ __entry->enable == RWNX_RADAR_DETECT_DISABLE ? "" : ++ __print_symbolic(__entry->region, ++ {NL80211_DFS_UNSET, "UNSET"}, ++ {NL80211_DFS_FCC, "FCC"}, ++ {NL80211_DFS_ETSI, "ETSI"}, ++ {NL80211_DFS_JP, "JP"})) ++); ++#endif /* CONFIG_RWNX_RADAR */ ++ ++/***************************************************************************** ++ * TRACE functions for IPC message ++ ****************************************************************************/ ++#include "rwnx_strs.h" ++ ++DECLARE_EVENT_CLASS( ++ ipc_msg_template, ++ TP_PROTO(u16 id), ++ TP_ARGS(id), ++ TP_STRUCT__entry( ++ __field(u16, id) ++ ), ++ TP_fast_assign( ++ __entry->id = id; ++ ), ++ ++ TP_printk("%s (%d - %d)", RWNX_ID2STR(__entry->id), ++ MSG_T(__entry->id), MSG_I(__entry->id)) ++); ++ ++DEFINE_EVENT(ipc_msg_template, msg_send, ++ TP_PROTO(u16 id), ++ TP_ARGS(id)); ++ ++DEFINE_EVENT(ipc_msg_template, msg_recv, ++ TP_PROTO(u16 id), ++ TP_ARGS(id)); ++ ++ ++ ++#endif /* !defined(_RWNX_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ) */ ++ ++#undef TRACE_INCLUDE_PATH ++#undef TRACE_INCLUDE_FILE ++//#define TRACE_INCLUDE_PATH . ++#define TRACE_INCLUDE_PATH AIC_TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_FILE rwnx_events ++#include +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c +new file mode 100644 +index 000000000000..9151c8b81f59 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c +@@ -0,0 +1,48 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_fw_trace.c ++ * ++ * Copyright (C) RivieraWaves 2017-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_fw_trace.h" ++#include "aicwf_debug.h" ++ ++int rwnx_fw_log_init(struct rwnx_fw_log *fw_log) ++{ ++ u8 *buf = kmalloc(FW_LOG_SIZE, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ fw_log->buf.data = buf; ++ fw_log->buf.start = fw_log->buf.data; ++ fw_log->buf.size = 0; ++ fw_log->buf.end = fw_log->buf.data; ++ fw_log->buf.dataend = fw_log->buf.data + FW_LOG_SIZE; ++ spin_lock_init(&fw_log->lock); ++ ++ AICWFDBG(LOGINFO, "fw_log_init: %lx, %lx\n", (unsigned long)fw_log->buf.start, (unsigned long)(fw_log->buf.dataend)); ++ return 0; ++} ++ ++void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log) ++{ ++ if (!fw_log) ++ return; ++ ++ if (fw_log->buf.data) ++ kfree(fw_log->buf.data); ++ fw_log->buf.start = NULL; ++ fw_log->buf.end = NULL; ++ fw_log->buf.size = 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h +new file mode 100644 +index 000000000000..7956790957c3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h +@@ -0,0 +1,35 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_fw_trace.h ++ * ++ * Copyright (C) RivieraWaves 2017-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_FW_TRACE_H_ ++#define _RWNX_FW_TRACE_H_ ++ ++#include ++#include ++#include ++ ++#define FW_LOG_SIZE (10240) ++ ++struct rwnx_fw_log_buf { ++ uint8_t *data; ++ uint8_t *start; ++ uint8_t *end; ++ uint8_t *dataend; ++ uint32_t size; ++}; ++ ++struct rwnx_fw_log { ++ struct rwnx_fw_log_buf buf; ++ spinlock_t lock; ++}; ++ ++int rwnx_fw_log_init(struct rwnx_fw_log *fw_log); ++void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log); ++#endif /* _RWNX_FW_TRACE_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c +new file mode 100644 +index 000000000000..7f6333d91e59 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c +@@ -0,0 +1,408 @@ ++#include ++#ifdef ANDROID_PLATFORM ++#include "net/wireless/core.h" ++#endif ++#include ++ ++#undef NL80211_MCGRP_MLME ++#define NL80211_MCGRP_MLME 3 ++//#if IS_ENABLED(CONFIG_GKI_OPT_FEATURES) && IS_ENABLED(CONFIG_ANDROID) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++ ++static struct genl_family rwnx_nl80211_fam; ++ ++static bool __rwnx_cfg80211_unexpected_frame(struct net_device *dev, u8 cmd, ++ const u8 *addr, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid); ++ ++ if (!nlportid) ++ return false; ++ ++ msg = nlmsg_new(100, gfp); ++ if (!msg) ++ return true; ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, cmd); ++ if (!hdr) { ++ nlmsg_free(msg); ++ return true; ++ } ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || ++ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || ++ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); ++ return true; ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++ return true; ++} ++ ++bool rwnx_cfg80211_rx_spurious_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ bool ret; ++ ++ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && ++ wdev->iftype != NL80211_IFTYPE_P2P_GO)) { ++ return false; ++ } ++ ret = __rwnx_cfg80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, ++ addr, gfp); ++ return ret; ++} ++ ++bool rwnx_cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ bool ret; ++ ++ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && ++ wdev->iftype != NL80211_IFTYPE_P2P_GO && ++ wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { ++ return false; ++ } ++ ret = __rwnx_cfg80211_unexpected_frame(dev, ++ NL80211_CMD_UNEXPECTED_4ADDR_FRAME, ++ addr, gfp); ++ return ret; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) ++void rwnx_cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, ++ const u8 *ie, u8 ie_len, ++ int sig_dbm, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ ++ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) ++ return; ++ ++ msg = nlmsg_new(100 + ie_len, gfp); ++ if (!msg) ++ return; ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, NL80211_CMD_NEW_PEER_CANDIDATE); ++ if (!hdr) { ++ nlmsg_free(msg); ++ return; ++ } ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || ++ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || ++ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || ++ (ie_len && ie && ++ nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) || ++ (sig_dbm && ++ nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm))) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++#define NL80211_MCGRP_MLME 3 ++ genlmsg_multicast_netns(&rwnx_nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, ++ NL80211_MCGRP_MLME, gfp); ++ return; ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++} ++#endif ++ ++void rwnx_cfg80211_report_obss_beacon(struct wiphy *wiphy, ++ const u8 *frame, size_t len, ++ int freq, int sig_dbm) ++{ ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ struct cfg80211_beacon_registration *reg; ++ ++ spin_lock_bh(&rdev->beacon_registrations_lock); ++ list_for_each_entry(reg, &rdev->beacon_registrations, list) { ++ msg = nlmsg_new(len + 100, GFP_ATOMIC); ++ if (!msg) { ++ spin_unlock_bh(&rdev->beacon_registrations_lock); ++ return; ++ } ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, NL80211_CMD_FRAME); ++ if (!hdr) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || ++ (freq && ++ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || ++ (sig_dbm && ++ nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || ++ nla_put(msg, NL80211_ATTR_FRAME, len, frame)) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid); ++ } ++ spin_unlock_bh(&rdev->beacon_registrations_lock); ++ return; ++ ++ nla_put_failure: ++ spin_unlock_bh(&rdev->beacon_registrations_lock); ++ nlmsg_free(msg); ++} ++ ++static int rwnx_nl80211_send_chandef(struct sk_buff *msg, ++ const struct cfg80211_chan_def *chandef) ++{ ++ if (WARN_ON(!cfg80211_chandef_valid(chandef))) ++ return -EINVAL; ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, ++ chandef->chan->center_freq)) ++ return -ENOBUFS; ++ switch (chandef->width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ case NL80211_CHAN_WIDTH_40: ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ++ cfg80211_get_chandef_type(chandef))) ++ return -ENOBUFS; ++ break; ++ default: ++ break; ++ } ++ if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width)) ++ return -ENOBUFS; ++ if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1)) ++ return -ENOBUFS; ++ if (chandef->center_freq2 && ++ nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2)) ++ return -ENOBUFS; ++ return 0; ++} ++ ++void rwnx_cfg80211_ch_switch_notify(struct cfg80211_registered_device *rdev, ++ struct net_device *netdev, ++ struct cfg80211_chan_def *chandef, ++ gfp_t gfp, ++ enum nl80211_commands notif, ++ u8 count) ++{ ++ struct sk_buff *msg; ++ void *hdr; ++ ++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); ++ if (!msg) ++ return; ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, notif); ++ if (!hdr) { ++ nlmsg_free(msg); ++ return; ++ } ++ ++ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) ++ goto nla_put_failure; ++ ++ if (rwnx_nl80211_send_chandef(msg, chandef)) ++ goto nla_put_failure; ++ ++ if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) && ++ (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++ genlmsg_multicast_netns(&rwnx_nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, ++ NL80211_MCGRP_MLME, gfp); ++ return; ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++} ++ ++void rwnx_cfg80211_ch_switch_started_notify(struct net_device *dev, ++ struct cfg80211_chan_def *chandef, ++ u8 count ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ , bool quiet ++ #endif ++ ) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct wiphy *wiphy = wdev->wiphy; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ ++ rwnx_cfg80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL, ++ NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count); ++} ++ ++int rwnx_regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, ++ struct ieee80211_regdomain *rd) ++{ ++ wiphy_apply_custom_regulatory(wiphy, rd); ++ return 0; ++} ++ ++void rwnx_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list) ++{ ++ unsigned long flags; ++ struct sk_buff *prev = old; ++ struct sk_buff *next = prev->next; ++ spin_lock_irqsave(&list->lock, flags); ++ WRITE_ONCE(newsk->next, next); ++ WRITE_ONCE(newsk->prev, prev); ++ WRITE_ONCE(next->prev, newsk); ++ WRITE_ONCE(prev->next, newsk); ++ list->qlen++; ++ spin_unlock_irqrestore(&list->lock, flags); ++} ++ ++bool rwnx_ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, ++ u8 *op_class) ++{ ++ u8 vht_opclass; ++ u32 freq = chandef->center_freq1; ++ ++ if (freq >= 2412 && freq <= 2472) { ++ if (chandef->width > NL80211_CHAN_WIDTH_40) ++ return false; ++ ++ /* 2.407 GHz, channels 1..13 */ ++ if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 83; /* HT40+ */ ++ else ++ *op_class = 84; /* HT40- */ ++ } else { ++ *op_class = 81; ++ } ++ ++ return true; ++ } ++ ++ if (freq == 2484) { ++ /* channel 14 is only for IEEE 802.11b */ ++ if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT) ++ return false; ++ ++ *op_class = 82; /* channel 14 */ ++ return true; ++ } ++ ++ switch (chandef->width) { ++ case NL80211_CHAN_WIDTH_80: ++ vht_opclass = 128; ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ vht_opclass = 129; ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ vht_opclass = 130; ++ break; ++ case NL80211_CHAN_WIDTH_10: ++ case NL80211_CHAN_WIDTH_5: ++ return false; /* unsupported for now */ ++ default: ++ vht_opclass = 0; ++ break; ++ } ++ ++ /* 5 GHz, channels 36..48 */ ++ if (freq >= 5180 && freq <= 5240) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 116; ++ else ++ *op_class = 117; ++ } else { ++ *op_class = 115; ++ } ++ ++ return true; ++ } ++ ++ /* 5 GHz, channels 52..64 */ ++ if (freq >= 5260 && freq <= 5320) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 119; ++ else ++ *op_class = 120; ++ } else { ++ *op_class = 118; ++ } ++ ++ return true; ++ } ++ ++ /* 5 GHz, channels 100..144 */ ++ if (freq >= 5500 && freq <= 5720) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 122; ++ else ++ *op_class = 123; ++ } else { ++ *op_class = 121; ++ } ++ ++ return true; ++ } ++ ++ /* 5 GHz, channels 149..169 */ ++ if (freq >= 5745 && freq <= 5845) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 126; ++ else ++ *op_class = 127; ++ } else if (freq <= 5805) { ++ *op_class = 124; ++ } else { ++ *op_class = 125; ++ } ++ ++ return true; ++ } ++ ++ /* 56.16 GHz, channel 1..4 */ ++ if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) { ++ if (chandef->width >= NL80211_CHAN_WIDTH_40) ++ return false; ++ ++ *op_class = 180; ++ return true; ++ } ++ ++ /* not supported yet */ ++ return false; ++} ++ ++int rwnx_call_usermodehelper(const char *path, char **argv, char **envp, int wait) ++{ ++ return -1; ++} ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h +new file mode 100644 +index 000000000000..a41f57832279 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h +@@ -0,0 +1,72 @@ ++#ifndef __RWNX_GKI_H ++#define __RWNX_GKI_H ++ ++#ifdef ANDROID_PLATFORM ++#include "net/wireless/core.h" ++#endif ++ ++//#if IS_ENABLED(CONFIG_GKI_OPT_FEATURES) && IS_ENABLED(CONFIG_ANDROID) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++ ++ ++bool rwnx_cfg80211_rx_spurious_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp); ++ ++bool rwnx_cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) ++void rwnx_cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, ++ const u8 *ie, u8 ie_len, ++ int sig_dbm, gfp_t gfp); ++#endif ++ ++void rwnx_cfg80211_report_obss_beacon(struct wiphy *wiphy, ++ const u8 *frame, size_t len, ++ int freq, int sig_dbm); ++ ++void rwnx_cfg80211_ch_switch_notify(struct cfg80211_registered_device *rdev, ++ struct net_device *netdev, ++ struct cfg80211_chan_def *chandef, ++ gfp_t gfp, ++ enum nl80211_commands notif, ++ u8 count); ++ ++void rwnx_cfg80211_ch_switch_started_notify(struct net_device *dev, ++ struct cfg80211_chan_def *chandef, ++ u8 count ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ , bool quiet ++ #endif ++ ); ++ ++int rwnx_regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, ++ struct ieee80211_regdomain *rd); ++ ++void rwnx_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list); ++ ++bool rwnx_ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, ++ u8 *op_class); ++ ++int rwnx_call_usermodehelper(const char *path, char **argv, char **envp, int wait); ++ ++#else ++ ++#define rwnx_cfg80211_rx_spurious_frame cfg80211_rx_spurious_frame ++#define rwnx_cfg80211_rx_unexpected_4addr_frame cfg80211_rx_unexpected_4addr_frame ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) ++#define rwnx_cfg80211_notify_new_peer_candidate cfg80211_notify_new_peer_candidate ++#endif ++ ++#define rwnx_cfg80211_report_obss_beacon cfg80211_report_obss_beacon ++#define rwnx_cfg80211_ch_switch_notify cfg80211_ch_switch_notify ++#define rwnx_cfg80211_ch_switch_started_notify cfg80211_ch_switch_started_notify ++#define rwnx_regulatory_set_wiphy_regd_sync_rtnl regulatory_set_wiphy_regd_sync_rtnl ++#define rwnx_skb_append skb_append ++#define rwnx_ieee80211_chandef_to_operating_class ieee80211_chandef_to_operating_class ++#define rwnx_call_usermodehelper call_usermodehelper ++ ++#endif ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c +new file mode 100644 +index 000000000000..8ba95b703f17 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c +@@ -0,0 +1,65 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_irqs.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++ ++#include "rwnx_defs.h" ++#include "ipc_host.h" ++#include "rwnx_prof.h" ++ ++/** ++ * rwnx_irq_hdlr - IRQ handler ++ * ++ * Handler registerd by the platform driver ++ */ ++irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id) ++{ ++ struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)dev_id; ++ disable_irq_nosync(irq); ++ tasklet_schedule(&rwnx_hw->task); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * rwnx_task - Bottom half for IRQ handler ++ * ++ * Read irq status and process accordingly ++ */ ++void rwnx_task(unsigned long data) ++{ ++ struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)data; ++ ++#if 0 ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ u32 status, statuses = 0; ++ ++ /* Ack unconditionnally in case ipc_host_get_status does not see the irq */ ++ rwnx_plat->ack_irq(rwnx_plat); ++ ++ while ((status = ipc_host_get_status(rwnx_hw->ipc_env))) { ++ statuses |= status; ++ /* All kinds of IRQs will be handled in one shot (RX, MSG, DBG, ...) ++ * this will ack IPC irqs not the cfpga irqs */ ++ ipc_host_irq(rwnx_hw->ipc_env, status); ++ ++ rwnx_plat->ack_irq(rwnx_plat); ++ } ++#endif ++ //if (statuses & IPC_IRQ_E2A_RXDESC) ++ // rwnx_hw->stats.last_rx = now; ++ //if (statuses & IPC_IRQ_E2A_TXCFM) ++ // rwnx_hw->stats.last_tx = now; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ rwnx_hwq_process_all(rwnx_hw); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++#if 0 ++ enable_irq(rwnx_platform_get_irq(rwnx_plat)); ++#endif ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h +new file mode 100644 +index 000000000000..d3fb4519c615 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h +@@ -0,0 +1,20 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_irqs.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_IRQS_H_ ++#define _RWNX_IRQS_H_ ++ ++#include ++ ++/* IRQ handler to be registered by platform driver */ ++irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id); ++ ++void rwnx_task(unsigned long data); ++ ++#endif /* _RWNX_IRQS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c +new file mode 100644 +index 000000000000..4773735ffe64 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c +@@ -0,0 +1,6124 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_main.c ++ * ++ * @brief Entry point of the RWNX driver ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_defs.h" ++#include "rwnx_dini.h" ++#include "rwnx_msg_tx.h" ++#include "reg_access.h" ++#include "hal_desc.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_cfgfile.h" ++#include "rwnx_irqs.h" ++#include "rwnx_radar.h" ++#include "rwnx_version.h" ++#ifdef CONFIG_RWNX_BFMER ++#include "rwnx_bfmer.h" ++#endif //(CONFIG_RWNX_BFMER) ++#include "rwnx_tdls.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "rwnx_version.h" ++#include "rwnx_main.h" ++#include "aicwf_txrxif.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#endif ++#ifdef AICWF_USB_SUPPORT ++#include "aicwf_usb.h" ++#endif ++#include "aic_bsp_export.h" ++#include "aicwf_compat_8800dc.h" ++#include "aicwf_compat_8800d80.h" ++#include "rwnx_wakelock.h" ++#ifdef CONFIG_SDIO_BT ++#include "aic_btsdio.h" ++#endif ++#include "aic_priv_cmd.h" ++ ++#define RW_DRV_DESCRIPTION "RivieraWaves 11nac driver for Linux cfg80211" ++#define RW_DRV_COPYRIGHT "Copyright(c) 2015-2017 RivieraWaves" ++#define RW_DRV_AUTHOR "RivieraWaves S.A.S" ++ ++#define RWNX_PRINT_CFM_ERR(req) \ ++ printk(KERN_CRIT "%s: Status Error(%d)\n", #req, (&req##_cfm)->status) ++ ++extern char country_code[]; ++ ++#define RWNX_HT_CAPABILITIES \ ++{ \ ++ .ht_supported = true, \ ++ .cap = 0, \ ++ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, \ ++ .mcs = { \ ++ .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \ ++ .rx_highest = cpu_to_le16(65), \ ++ .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ ++ }, \ ++} ++ ++#define RWNX_VHT_CAPABILITIES \ ++{ \ ++ .vht_supported = false, \ ++ .cap = \ ++ (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT),\ ++ .vht_mcs = { \ ++ .rx_mcs_map = cpu_to_le16( \ ++ IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 14), \ ++ .tx_mcs_map = cpu_to_le16( \ ++ IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 14), \ ++ } \ ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) || defined(CONFIG_HE_FOR_OLD_KERNEL) ++#define RWNX_HE_CAPABILITIES \ ++{ \ ++ .has_he = false, \ ++ .he_cap_elem = { \ ++ .mac_cap_info[0] = 0, \ ++ .mac_cap_info[1] = 0, \ ++ .mac_cap_info[2] = 0, \ ++ .mac_cap_info[3] = 0, \ ++ .mac_cap_info[4] = 0, \ ++ .mac_cap_info[5] = 0, \ ++ .phy_cap_info[0] = 0, \ ++ .phy_cap_info[1] = 0, \ ++ .phy_cap_info[2] = 0, \ ++ .phy_cap_info[3] = 0, \ ++ .phy_cap_info[4] = 0, \ ++ .phy_cap_info[5] = 0, \ ++ .phy_cap_info[6] = 0, \ ++ .phy_cap_info[7] = 0, \ ++ .phy_cap_info[8] = 0, \ ++ .phy_cap_info[9] = 0, \ ++ .phy_cap_info[10] = 0, \ ++ }, \ ++ .he_mcs_nss_supp = { \ ++ .rx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .tx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .rx_mcs_160 = cpu_to_le16(0xffff), \ ++ .tx_mcs_160 = cpu_to_le16(0xffff), \ ++ .rx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ .tx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ }, \ ++ .ppe_thres = {0x08, 0x1c, 0x07}, \ ++} ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++#define RWNX_HE_CAPABILITIES \ ++{ \ ++ .has_he = false, \ ++ .he_cap_elem = { \ ++ .mac_cap_info[0] = 0, \ ++ .mac_cap_info[1] = 0, \ ++ .mac_cap_info[2] = 0, \ ++ .mac_cap_info[3] = 0, \ ++ .mac_cap_info[4] = 0, \ ++ .phy_cap_info[0] = 0, \ ++ .phy_cap_info[1] = 0, \ ++ .phy_cap_info[2] = 0, \ ++ .phy_cap_info[3] = 0, \ ++ .phy_cap_info[4] = 0, \ ++ .phy_cap_info[5] = 0, \ ++ .phy_cap_info[6] = 0, \ ++ .phy_cap_info[7] = 0, \ ++ .phy_cap_info[8] = 0, \ ++ }, \ ++ .he_mcs_nss_supp = { \ ++ .rx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .tx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .rx_mcs_160 = cpu_to_le16(0xffff), \ ++ .tx_mcs_160 = cpu_to_le16(0xffff), \ ++ .rx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ .tx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ }, \ ++ .ppe_thres = {0x08, 0x1c, 0x07}, \ ++} ++#endif ++#endif ++ ++#define RATE(_bitrate, _hw_rate, _flags) { \ ++ .bitrate = (_bitrate), \ ++ .flags = (_flags), \ ++ .hw_value = (_hw_rate), \ ++} ++ ++#define CHAN(_freq) { \ ++ .center_freq = (_freq), \ ++ .max_power = 30, /* FIXME */ \ ++} ++ ++static struct ieee80211_rate rwnx_ratetable[] = { ++ RATE(10, 0x00, 0), ++ RATE(20, 0x01, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(55, 0x02, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(110, 0x03, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(60, 0x04, 0), ++ RATE(90, 0x05, 0), ++ RATE(120, 0x06, 0), ++ RATE(180, 0x07, 0), ++ RATE(240, 0x08, 0), ++ RATE(360, 0x09, 0), ++ RATE(480, 0x0A, 0), ++ RATE(540, 0x0B, 0), ++}; ++ ++/* The channels indexes here are not used anymore */ ++static struct ieee80211_channel rwnx_2ghz_channels[] = { ++ CHAN(2412), ++ CHAN(2417), ++ CHAN(2422), ++ CHAN(2427), ++ CHAN(2432), ++ CHAN(2437), ++ CHAN(2442), ++ CHAN(2447), ++ CHAN(2452), ++ CHAN(2457), ++ CHAN(2462), ++ CHAN(2467), ++ CHAN(2472), ++ CHAN(2484), ++ // Extra channels defined only to be used for PHY measures. ++ // Enabled only if custregd and custchan parameters are set ++ CHAN(2390), ++ CHAN(2400), ++ CHAN(2410), ++ CHAN(2420), ++ CHAN(2430), ++ CHAN(2440), ++ CHAN(2450), ++ CHAN(2460), ++ CHAN(2470), ++ CHAN(2480), ++ CHAN(2490), ++ CHAN(2500), ++ CHAN(2510), ++}; ++ ++static struct ieee80211_channel rwnx_5ghz_channels[] = { ++ CHAN(5180), // 36 - 20MHz ++ CHAN(5200), // 40 - 20MHz ++ CHAN(5220), // 44 - 20MHz ++ CHAN(5240), // 48 - 20MHz ++ CHAN(5260), // 52 - 20MHz ++ CHAN(5280), // 56 - 20MHz ++ CHAN(5300), // 60 - 20MHz ++ CHAN(5320), // 64 - 20MHz ++ CHAN(5500), // 100 - 20MHz ++ CHAN(5520), // 104 - 20MHz ++ CHAN(5540), // 108 - 20MHz ++ CHAN(5560), // 112 - 20MHz ++ CHAN(5580), // 116 - 20MHz ++ CHAN(5600), // 120 - 20MHz ++ CHAN(5620), // 124 - 20MHz ++ CHAN(5640), // 128 - 20MHz ++ CHAN(5660), // 132 - 20MHz ++ CHAN(5680), // 136 - 20MHz ++ CHAN(5700), // 140 - 20MHz ++ CHAN(5720), // 144 - 20MHz ++ CHAN(5745), // 149 - 20MHz ++ CHAN(5765), // 153 - 20MHz ++ CHAN(5785), // 157 - 20MHz ++ CHAN(5805), // 161 - 20MHz ++ CHAN(5825), // 165 - 20MHz ++ // Extra channels defined only to be used for PHY measures. ++ // Enabled only if custregd and custchan parameters are set ++ CHAN(5190), ++ CHAN(5210), ++ CHAN(5230), ++ CHAN(5250), ++ CHAN(5270), ++ CHAN(5290), ++ CHAN(5310), ++ CHAN(5330), ++ CHAN(5340), ++ CHAN(5350), ++ CHAN(5360), ++ CHAN(5370), ++ CHAN(5380), ++ CHAN(5390), ++ CHAN(5400), ++ CHAN(5410), ++ CHAN(5420), ++ CHAN(5430), ++ CHAN(5440), ++ CHAN(5450), ++ CHAN(5460), ++ CHAN(5470), ++ CHAN(5480), ++ CHAN(5490), ++ CHAN(5510), ++ CHAN(5530), ++ CHAN(5550), ++ CHAN(5570), ++ CHAN(5590), ++ CHAN(5610), ++ CHAN(5630), ++ CHAN(5650), ++ CHAN(5670), ++ CHAN(5690), ++ CHAN(5710), ++ CHAN(5730), ++ CHAN(5750), ++ CHAN(5760), ++ CHAN(5770), ++ CHAN(5780), ++ CHAN(5790), ++ CHAN(5800), ++ CHAN(5810), ++ CHAN(5820), ++ CHAN(5830), ++ CHAN(5840), ++ CHAN(5850), ++ CHAN(5860), ++ CHAN(5870), ++ CHAN(5880), ++ CHAN(5890), ++ CHAN(5900), ++ CHAN(5910), ++ CHAN(5920), ++ CHAN(5930), ++ CHAN(5940), ++ CHAN(5950), ++ CHAN(5960), ++ CHAN(5970), ++}; ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) || defined(CONFIG_HE_FOR_OLD_KERNEL) ++struct ieee80211_sband_iftype_data rwnx_he_capa = { ++ .types_mask = BIT(NL80211_IFTYPE_STATION)|BIT(NL80211_IFTYPE_AP), ++ .he_cap = RWNX_HE_CAPABILITIES, ++}; ++#endif ++ ++static struct ieee80211_supported_band rwnx_band_2GHz = { ++ .channels = rwnx_2ghz_channels, ++ .n_channels = ARRAY_SIZE(rwnx_2ghz_channels) - 13, // -13 to exclude extra channels ++ .bitrates = rwnx_ratetable, ++ .n_bitrates = ARRAY_SIZE(rwnx_ratetable), ++ .ht_cap = RWNX_HT_CAPABILITIES, ++ .vht_cap = RWNX_VHT_CAPABILITIES, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ .iftype_data = &rwnx_he_capa, ++ .n_iftype_data = 1, ++#endif ++}; ++ ++static struct ieee80211_supported_band rwnx_band_5GHz = { ++ .channels = rwnx_5ghz_channels, ++ .n_channels = ARRAY_SIZE(rwnx_5ghz_channels) - 59, // -59 to exclude extra channels ++ .bitrates = &rwnx_ratetable[4], ++ .n_bitrates = ARRAY_SIZE(rwnx_ratetable) - 4, ++ .ht_cap = RWNX_HT_CAPABILITIES, ++ .vht_cap = RWNX_VHT_CAPABILITIES, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ .iftype_data = &rwnx_he_capa, ++ .n_iftype_data = 1, ++#endif ++}; ++ ++static struct ieee80211_iface_limit rwnx_limits[] = { ++ { .max = 1, ++ .types = BIT(NL80211_IFTYPE_STATION)}, ++ { .max = 1, ++ .types = BIT(NL80211_IFTYPE_AP)}, ++#ifdef CONFIG_USE_P2P0 ++ { .max = 2, ++#else ++ { .max = 1, ++#endif ++ .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)}, ++#ifndef CONFIG_USE_P2P0 ++ { .max = 1, ++ .types = BIT(NL80211_IFTYPE_P2P_DEVICE), ++ } ++#endif ++}; ++ ++static struct ieee80211_iface_limit rwnx_limits_dfs[] = { ++ { .max = NX_VIRT_DEV_MAX, .types = BIT(NL80211_IFTYPE_AP)} ++}; ++ ++static const struct ieee80211_iface_combination rwnx_combinations[] = { ++ { ++ .limits = rwnx_limits, ++ .n_limits = ARRAY_SIZE(rwnx_limits), ++#ifdef CONFIG_MCC ++ .num_different_channels = NX_CHAN_CTXT_CNT, ++#else ++ .num_different_channels = 1, ++#endif ++ .max_interfaces = NX_VIRT_DEV_MAX, ++ }, ++ /* Keep this combination as the last one */ ++ { ++ .limits = rwnx_limits_dfs, ++ .n_limits = ARRAY_SIZE(rwnx_limits_dfs), ++ .num_different_channels = 1, ++ .max_interfaces = NX_VIRT_DEV_MAX, ++ .radar_detect_widths = (BIT(NL80211_CHAN_WIDTH_20_NOHT) | ++ BIT(NL80211_CHAN_WIDTH_20) | ++ BIT(NL80211_CHAN_WIDTH_40) | ++ BIT(NL80211_CHAN_WIDTH_80)), ++ } ++}; ++ ++/* There isn't a lot of sense in it, but you can transmit anything you like */ ++static struct ieee80211_txrx_stypes ++rwnx_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { ++ [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_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_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_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_DEVICE] = { ++ .tx = 0xffff, ++ .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)), ++ }, ++ [NL80211_IFTYPE_MESH_POINT] = { ++ .tx = 0xffff, ++ .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) | ++ BIT(IEEE80211_STYPE_AUTH >> 4) | ++ BIT(IEEE80211_STYPE_DEAUTH >> 4)), ++ }, ++}; ++ ++ ++static u32 cipher_suites[] = { ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++ WLAN_CIPHER_SUITE_AES_CMAC, // reserved entries to enable AES-CMAC and/or SMS4 ++ WLAN_CIPHER_SUITE_SMS4, ++ 0, ++}; ++#define NB_RESERVED_CIPHER 1; ++ ++static const int rwnx_ac2hwq[1][NL80211_NUM_ACS] = { ++ { ++ [NL80211_TXQ_Q_VO] = RWNX_HWQ_VO, ++ [NL80211_TXQ_Q_VI] = RWNX_HWQ_VI, ++ [NL80211_TXQ_Q_BE] = RWNX_HWQ_BE, ++ [NL80211_TXQ_Q_BK] = RWNX_HWQ_BK ++ } ++}; ++ ++const int rwnx_tid2hwq[IEEE80211_NUM_TIDS] = { ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BK, ++ RWNX_HWQ_BK, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_VI, ++ RWNX_HWQ_VI, ++ RWNX_HWQ_VO, ++ RWNX_HWQ_VO, ++ /* TID_8 is used for management frames */ ++ RWNX_HWQ_VO, ++ /* At the moment, all others TID are mapped to BE */ ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++}; ++ ++static const int rwnx_hwq2uapsd[NL80211_NUM_ACS] = { ++ [RWNX_HWQ_VO] = IEEE80211_WMM_IE_STA_QOSINFO_AC_VO, ++ [RWNX_HWQ_VI] = IEEE80211_WMM_IE_STA_QOSINFO_AC_VI, ++ [RWNX_HWQ_BE] = IEEE80211_WMM_IE_STA_QOSINFO_AC_BE, ++ [RWNX_HWQ_BK] = IEEE80211_WMM_IE_STA_QOSINFO_AC_BK, ++}; ++ ++#define P2P_ALIVE_TIME_MS (1*1000) ++#define P2P_ALIVE_TIME_COUNT 200 ++ ++ ++extern uint8_t scanning; ++int aicwf_dbg_level = LOGERROR; ++module_param(aicwf_dbg_level, int, 0660); ++int testmode = 0; ++char aic_fw_path[200]; ++u8 chip_sub_id = 0; ++u8 chip_mcu_id = 0; ++u8 chip_id = 0; ++ ++int rwnx_init_cmd_array(void); ++void rwnx_free_cmd_array(void); ++ ++ ++/********************************************************************* ++ * helper ++ *********************************************************************/ ++struct rwnx_sta *rwnx_get_sta(struct rwnx_hw *rwnx_hw, const u8 *mac_addr) ++{ ++ int i; ++ ++ for (i = 0; i < NX_REMOTE_STA_MAX; i++) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[i]; ++ if (sta->valid && (memcmp(mac_addr, &sta->mac_addr, 6) == 0)) ++ return sta; ++ } ++ ++ return NULL; ++} ++ ++void rwnx_enable_wapi(struct rwnx_hw *rwnx_hw) ++{ ++ //cipher_suites[rwnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_SMS4; ++ rwnx_hw->wiphy->n_cipher_suites++; ++ rwnx_hw->wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; ++} ++ ++void rwnx_enable_mfp(struct rwnx_hw *rwnx_hw) ++{ ++ cipher_suites[rwnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC; ++ rwnx_hw->wiphy->n_cipher_suites++; ++} ++ ++u8 *rwnx_build_bcn(struct rwnx_bcn *bcn, struct cfg80211_beacon_data *new) ++{ ++ u8 *buf, *pos; ++ ++ if (new->head) { ++ u8 *head = kmalloc(new->head_len, GFP_KERNEL); ++ ++ if (!head) ++ return NULL; ++ ++ if (bcn->head) ++ kfree(bcn->head); ++ ++ bcn->head = head; ++ bcn->head_len = new->head_len; ++ memcpy(bcn->head, new->head, new->head_len); ++ } ++ if (new->tail) { ++ u8 *tail = kmalloc(new->tail_len, GFP_KERNEL); ++ ++ if (!tail) ++ return NULL; ++ ++ if (bcn->tail) ++ kfree(bcn->tail); ++ ++ bcn->tail = tail; ++ bcn->tail_len = new->tail_len; ++ memcpy(bcn->tail, new->tail, new->tail_len); ++ } ++ ++ if (!bcn->head) ++ return NULL; ++ ++ bcn->tim_len = 6; ++ bcn->len = bcn->head_len + bcn->tail_len + bcn->ies_len + bcn->tim_len; ++ ++ buf = kmalloc(bcn->len, GFP_KERNEL); ++ if (!buf) ++ return NULL; ++ ++ // Build the beacon buffer ++ pos = buf; ++ memcpy(pos, bcn->head, bcn->head_len); ++ pos += bcn->head_len; ++ *pos++ = WLAN_EID_TIM; ++ *pos++ = 4; ++ *pos++ = 0; ++ *pos++ = bcn->dtim; ++ *pos++ = 0; ++ *pos++ = 0; ++ if (bcn->tail) { ++ memcpy(pos, bcn->tail, bcn->tail_len); ++ pos += bcn->tail_len; ++ } ++ if (bcn->ies) { ++ memcpy(pos, bcn->ies, bcn->ies_len); ++ } ++ ++ return buf; ++} ++ ++ ++static void rwnx_del_bcn(struct rwnx_bcn *bcn) ++{ ++ if (bcn->head) { ++ kfree(bcn->head); ++ bcn->head = NULL; ++ } ++ bcn->head_len = 0; ++ ++ if (bcn->tail) { ++ kfree(bcn->tail); ++ bcn->tail = NULL; ++ } ++ bcn->tail_len = 0; ++ ++ if (bcn->ies) { ++ kfree(bcn->ies); ++ bcn->ies = NULL; ++ } ++ bcn->ies_len = 0; ++ bcn->tim_len = 0; ++ bcn->dtim = 0; ++ bcn->len = 0; ++} ++ ++/** ++ * Link channel ctxt to a vif and thus increments count for this context. ++ */ ++void rwnx_chanctx_link(struct rwnx_vif *vif, u8 ch_idx, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_chanctx *ctxt; ++ ++ if (ch_idx >= NX_CHAN_CTXT_CNT) { ++ WARN(1, "Invalid channel ctxt id %d", ch_idx); ++ return; ++ } ++ ++ vif->ch_index = ch_idx; ++ ctxt = &vif->rwnx_hw->chanctx_table[ch_idx]; ++ ctxt->count++; ++ ++ // For now chandef is NULL for STATION interface ++ if (chandef) { ++ if (!ctxt->chan_def.chan) ++ ctxt->chan_def = *chandef; ++ else { ++ // TODO. check that chandef is the same as the one already ++ // set for this ctxt ++ } ++ } ++} ++ ++/** ++ * Unlink channel ctxt from a vif and thus decrements count for this context ++ */ ++void rwnx_chanctx_unlink(struct rwnx_vif *vif) ++{ ++ struct rwnx_chanctx *ctxt; ++ ++ if (vif->ch_index == RWNX_CH_NOT_SET) ++ return; ++ ++ ctxt = &vif->rwnx_hw->chanctx_table[vif->ch_index]; ++ ++ if (ctxt->count == 0) { ++ WARN(1, "Chan ctxt ref count is already 0"); ++ } else { ++ ctxt->count--; ++ } ++ ++ if (ctxt->count == 0) { ++ if (vif->ch_index == vif->rwnx_hw->cur_chanctx) { ++ /* If current chan ctxt is no longer linked to a vif ++ disable radar detection (no need to check if it was activated) */ ++ rwnx_radar_detection_enable(&vif->rwnx_hw->radar, ++ RWNX_RADAR_DETECT_DISABLE, ++ RWNX_RADAR_RIU); ++ } ++ /* set chan to null, so that if this ctxt is relinked to a vif that ++ don't have channel information, don't use wrong information */ ++ ctxt->chan_def.chan = NULL; ++ } ++ vif->ch_index = RWNX_CH_NOT_SET; ++} ++ ++int rwnx_chanctx_valid(struct rwnx_hw *rwnx_hw, u8 ch_idx) ++{ ++ if (ch_idx >= NX_CHAN_CTXT_CNT || ++ rwnx_hw->chanctx_table[ch_idx].chan_def.chan == NULL) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static void rwnx_del_csa(struct rwnx_vif *vif) ++{ ++ struct rwnx_csa *csa = vif->ap.csa; ++ ++ if (!csa) ++ return; ++ ++ rwnx_del_bcn(&csa->bcn); ++ kfree(csa); ++ vif->ap.csa = NULL; ++} ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++static void rwnx_csa_finish(struct work_struct *ws) ++{ ++ struct rwnx_csa *csa = container_of(ws, struct rwnx_csa, work); ++ struct rwnx_vif *vif = csa->vif; ++ struct rwnx_hw *rwnx_hw = vif->rwnx_hw; ++ int error = csa->status; ++ u8 *buf, *pos; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ buf = kmalloc(csa->bcn.len, GFP_KERNEL); ++ if (!buf) { ++ printk ("%s buf fail\n", __func__); ++ return; ++ } ++ pos = buf; ++ ++ memcpy(pos, csa->bcn.head, csa->bcn.head_len); ++ pos += csa->bcn.head_len; ++ *pos++ = WLAN_EID_TIM; ++ *pos++ = 4; ++ *pos++ = 0; ++ *pos++ = csa->bcn.dtim; ++ *pos++ = 0; ++ *pos++ = 0; ++ if (csa->bcn.tail) { ++ memcpy(pos, csa->bcn.tail, csa->bcn.tail_len); ++ pos += csa->bcn.tail_len; ++ } ++ if (csa->bcn.ies) { ++ memcpy(pos, csa->bcn.ies, csa->bcn.ies_len); ++ } ++ ++ if (!error) { ++ error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, csa->bcn.len); ++ if (error) ++ return; ++ error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, ++ csa->bcn.len, csa->bcn.head_len, ++ csa->bcn.tim_len, NULL); ++ } ++ ++ if (error) { ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) ++ cfg80211_stop_iface(rwnx_hw->wiphy, &vif->wdev, GFP_KERNEL); ++ #else ++ cfg80211_disconnected(vif->ndev, 0, NULL, 0, 0, GFP_KERNEL); ++ #endif ++ } else { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) ++ wiphy_lock(rwnx_hw->wiphy); ++#else ++ mutex_lock(&vif->wdev.mtx); ++ __acquire(&vif->wdev.mtx); ++#endif ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_unlink(vif); ++ rwnx_chanctx_link(vif, csa->ch_idx, &csa->chandef); ++ if (rwnx_hw->cur_chanctx == csa->ch_idx) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ rwnx_txq_vif_start(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } else ++ rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 9, 0)) ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0); ++#elif (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION3) ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0, 0); ++#elif (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION) ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0); ++#else ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef); ++#endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) ++ wiphy_unlock(rwnx_hw->wiphy); ++#else ++ mutex_unlock(&vif->wdev.mtx); ++ __release(&vif->wdev.mtx); ++#endif ++ } ++ rwnx_del_csa(vif); ++} ++#endif ++ ++/** ++ * rwnx_external_auth_enable - Enable external authentication on a vif ++ * ++ * @vif: VIF on which external authentication must be enabled ++ * ++ * External authentication requires to start TXQ for unknown STA in ++ * order to send auth frame pusehd by user space. ++ * Note: It is assumed that fw is on the correct channel. ++ */ ++void rwnx_external_auth_enable(struct rwnx_vif *vif) ++{ ++ vif->sta.external_auth = true; ++ rwnx_txq_unk_vif_init(vif); ++ rwnx_txq_start(rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE), 0); ++} ++ ++/** ++ * rwnx_external_auth_disable - Disable external authentication on a vif ++ * ++ * @vif: VIF on which external authentication must be disabled ++ */ ++void rwnx_external_auth_disable(struct rwnx_vif *vif) ++{ ++ if (!vif->sta.external_auth) ++ return; ++ ++ vif->sta.external_auth = false; ++ rwnx_txq_unk_vif_deinit(vif); ++} ++ ++/** ++ * rwnx_update_mesh_power_mode - ++ * ++ * @vif: mesh VIF for which power mode is updated ++ * ++ * Does nothing if vif is not a mesh point interface. ++ * Since firmware doesn't support one power save mode per link select the ++ * most "active" power mode among all mesh links. ++ * Indeed as soon as we have to be active on one link we might as well be ++ * active on all links. ++ * ++ * If there is no link then the power mode for next peer is used; ++ */ ++void rwnx_update_mesh_power_mode(struct rwnx_vif *vif) ++{ ++ enum nl80211_mesh_power_mode mesh_pm; ++ struct rwnx_sta *sta; ++ struct mesh_config mesh_conf; ++ struct mesh_update_cfm cfm; ++ u32 mask; ++ ++ if (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_MESH_POINT) ++ return; ++ ++ if (list_empty(&vif->ap.sta_list)) { ++ mesh_pm = vif->ap.next_mesh_pm; ++ } else { ++ mesh_pm = NL80211_MESH_POWER_DEEP_SLEEP; ++ list_for_each_entry(sta, &vif->ap.sta_list, list) { ++ if (sta->valid && (sta->mesh_pm < mesh_pm)) { ++ mesh_pm = sta->mesh_pm; ++ } ++ } ++ } ++ ++ if (mesh_pm == vif->ap.mesh_pm) ++ return; ++ ++ mask = BIT(NL80211_MESHCONF_POWER_MODE - 1); ++ mesh_conf.power_mode = mesh_pm; ++ if (rwnx_send_mesh_update_req(vif->rwnx_hw, vif, mask, &mesh_conf, &cfm) || ++ cfm.status) ++ return; ++ ++ vif->ap.mesh_pm = mesh_pm; ++} ++ ++#ifdef CONFIG_BR_SUPPORT ++void netdev_br_init(struct net_device *netdev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(netdev); ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++ rcu_read_lock(); ++#endif ++ ++ /* if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) */ ++ { ++ /* struct net_bridge *br = netdev->br_port->br; */ /* ->dev->dev_addr; */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ if (netdev->br_port) ++ #else ++ if (rcu_dereference(rwnx_vif->ndev->rx_handler_data)) ++ #endif ++ { ++ struct net_device *br_netdev; ++ ++ br_netdev = dev_get_by_name(&init_net, CONFIG_BR_SUPPORT_BRNAME); ++ if (br_netdev) { ++ memcpy(rwnx_vif->br_mac, br_netdev->dev_addr, ETH_ALEN); ++ dev_put(br_netdev); ++ printk(FUNC_NDEV_FMT" bind bridge dev "NDEV_FMT"("MAC_FMT")\n" ++ , FUNC_NDEV_ARG(netdev), NDEV_ARG(br_netdev), MAC_ARG(br_netdev->dev_addr)); ++ } else { ++ printk(FUNC_NDEV_FMT" can't get bridge dev by name \"%s\"\n" ++ , FUNC_NDEV_ARG(netdev), CONFIG_BR_SUPPORT_BRNAME); ++ } ++ } ++ ++ rwnx_vif->ethBrExtInfo.addPPPoETag = 1; ++ } ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++ rcu_read_unlock(); ++#endif ++} ++#endif /* CONFIG_BR_SUPPORT */ ++ ++void rwnx_set_conn_state(atomic_t *drv_conn_state, int state){ ++ ++ if((int)atomic_read(drv_conn_state) != state){ ++ AICWFDBG(LOGDEBUG, "%s drv_conn_state:%p %s --> %s \r\n", __func__, ++ drv_conn_state, ++ s_conn_state[(int)atomic_read(drv_conn_state)], ++ s_conn_state[state]); ++ ++ atomic_set(drv_conn_state, state); ++ } ++} ++ ++/********************************************************************* ++ * netdev callbacks ++ ********************************************************************/ ++/** ++ * int (*ndo_open)(struct net_device *dev); ++ * This function is called when network device transistions to the up ++ * state. ++ * ++ * - Start FW if this is the first interface opened ++ * - Add interface at fw level ++ */ ++static int rwnx_open(struct net_device *dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct mm_add_if_cfm add_if_cfm; ++ int error = 0; ++ u8 rwnx_rx_gain = 0x0E; ++ int err = 0; ++ int waiting_counter = 10; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ while(test_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags)){ ++ msleep(100); ++ AICWFDBG(LOGDEBUG, "%s waiting for rwnx_close \r\n", __func__); ++ waiting_counter--; ++ if(waiting_counter == 0){ ++ AICWFDBG(LOGERROR, "%s error waiting for close time out \r\n", __func__); ++ break; ++ } ++ } ++ ++#ifdef AICWF_LATENCY_MODE ++ if ((testmode == 0) && (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT)) { ++ rwnx_send_me_set_lp_level(rwnx_hw, 1, 1); ++ } ++#endif ++ ++#ifdef CONFIG_GPIO_WAKEUP ++//close lp mode ++// rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 0); ++#endif//CONFIG_GPIO_WAKEUP ++ ++ // Check if it is the first opened VIF ++ if (rwnx_hw->vif_started == 0) { ++ // Start the FW ++ error = rwnx_send_start(rwnx_hw); ++ if (error) ++ return error; ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ error = rwnx_send_dbg_mem_mask_write_req(rwnx_hw, 0x4033b300, 0xFF, rwnx_rx_gain); ++ if(error){ ++ return error; ++ } ++ } ++ ++#ifdef CONFIG_COEX ++ if (testmode == 0) { ++ rwnx_send_coex_req(rwnx_hw, 0, 1); ++ } ++#endif ++ ++ /* Device is now started */ ++ } ++ ++ set_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif->drv_flags:%d\r\n", __func__, (int)rwnx_vif->drv_flags); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO) { ++ if (!rwnx_hw->is_p2p_alive) { ++ if (rwnx_hw->p2p_dev_vif && !rwnx_hw->p2p_dev_vif->up) { ++ err = rwnx_send_add_if (rwnx_hw, rwnx_hw->p2p_dev_vif->wdev.address, ++ RWNX_VIF_TYPE(rwnx_hw->p2p_dev_vif), false, &add_if_cfm); ++ if (err) { ++ return -EIO; ++ } ++ ++ if (add_if_cfm.status != 0) { ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->p2p_dev_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_hw->p2p_dev_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_hw->p2p_dev_vif; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++ rwnx_hw->is_p2p_alive = 1; ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ } ++ } ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN) { ++ /* For AP_vlan use same fw and drv indexes. We ensure that this index ++ will not be used by fw for another vif by taking index >= NX_VIRT_DEV_MAX */ ++ add_if_cfm.inst_nbr = rwnx_vif->drv_vif_index; ++ netif_tx_stop_all_queues(dev); ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ AICWFDBG(LOGDEBUG, "%s ap create vif in rwnx_hw->vif_table[%d] \r\n", ++ __func__, rwnx_vif->vif_index); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } else { ++ /* Forward the information to the LMAC, ++ * p2p value not used in FMAC configuration, iftype is sufficient */ ++ error = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); ++ if (error) { ++ printk("add if fail\n"); ++ return error; ++ } ++ ++ if (add_if_cfm.status != 0) { ++ RWNX_PRINT_CFM_ERR(add_if); ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ AICWFDBG(LOGDEBUG, "%s sta create vif in rwnx_hw->vif_table[%d] \r\n", ++ __func__, rwnx_vif->vif_index); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++#ifdef CONFIG_USE_P2P0 ++ if(rwnx_vif->is_p2p_vif){ ++ rwnx_hw->p2p_dev_vif = rwnx_vif; ++ rwnx_hw->is_p2p_alive = 1; ++ } ++#endif ++ } ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MONITOR) { ++ rwnx_hw->monitor_vif = rwnx_vif->vif_index; ++ if (rwnx_vif->ch_index != RWNX_CH_NOT_SET) { ++ //Configure the monitor channel ++ error = rwnx_send_config_monitor_req(rwnx_hw, &rwnx_hw->chanctx_table[rwnx_vif->ch_index].chan_def, NULL); ++ } ++#if defined(CONFIG_RWNX_MON_XMIT) ++ rwnx_txq_unk_vif_init(rwnx_vif); ++#endif ++#if defined(CONFIG_RWNX_MON_RXFILTER) ++ rwnx_send_set_filter(rwnx_hw, (FIF_BCN_PRBRESP_PROMISC | FIF_OTHER_BSS | FIF_PSPOLL | FIF_PROBE_REQ)); ++#endif ++ } ++ ++#if defined(CONFIG_RWNX_MON_XMIT) ++ netif_carrier_on(dev); ++ AICWFDBG(LOGINFO, "monitor xmit: netif_carrier_on\n"); ++#endif ++ ++ ++ #ifdef CONFIG_BR_SUPPORT ++ netdev_br_init(dev); ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ //netif_carrier_off(dev); ++ netif_start_queue(dev); ++ ++ return error; ++} ++ ++/** ++ * int (*ndo_stop)(struct net_device *dev); ++ * This function is called when network device transistions to the down ++ * state. ++ * ++ * - Remove interface at fw level ++ * - Reset FW if this is the last interface opened ++ */ ++static int rwnx_close(struct net_device *dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ int ret; ++#if defined(AICWF_USB_SUPPORT) ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_usb_dev *usbdev = NULL; ++ bus_if = dev_get_drvdata(rwnx_hw->dev); ++ usbdev = bus_if->bus_priv.usb; ++#elif defined(AICWF_SDIO_SUPPORT) ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_sdio_dev *sdiodev = NULL; ++#else ++#endif ++ int waiting_counter = 20; ++ int test_counter = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ test_counter = waiting_counter; ++ while(atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING|| ++ atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING){ ++ AICWFDBG(LOGDEBUG, "%s wifi is connecting or disconnecting, waiting 200ms for state to stable\r\n", __func__); ++ msleep(200); ++ test_counter--; ++ if(test_counter == 0){ ++ AICWFDBG(LOGERROR, "%s connecting or disconnecting, not finish\r\n", __func__); ++ WARN_ON(1); ++ break; ++ } ++ } ++ ++#if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) ++ if (scanning) { ++ scanning = false; ++ } ++#endif ++ ++ netdev_info(dev, "CLOSE"); ++ ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ ++ /* Abort scan request on the vif */ ++ if (rwnx_hw->scan_request && ++ rwnx_hw->scan_request->wdev == &rwnx_vif->wdev) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ cfg80211_scan_done(rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(rwnx_hw->scan_request, true); ++#endif ++ rwnx_hw->scan_request = NULL; ++ ++ ret = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ mdelay(35);//make sure firmware take affect ++ if (ret) { ++ printk("scanu_cancel fail\n"); ++ return ret; ++ } ++ } ++ ++ if (rwnx_hw->roc_elem && (rwnx_hw->roc_elem->wdev == &rwnx_vif->wdev)) { ++ printk(KERN_CRIT "%s clear roc\n", __func__); ++ /* Initialize RoC element pointer to NULL, indicate that RoC can be started */ ++ kfree(rwnx_hw->roc_elem); ++ rwnx_hw->roc_elem = NULL; ++ } ++ ++ rwnx_vif->up = false; ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif[%d] down \r\n", __func__, rwnx_vif->vif_index); ++ ++ if (netif_carrier_ok(dev)) { ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ cfg80211_disconnected(dev, WLAN_REASON_DEAUTH_LEAVING, ++ NULL, 0, true, GFP_ATOMIC); ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ udelay(1000); ++ } else if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN) { ++ netif_carrier_off(dev); ++ } else { ++ netdev_warn(dev, "AP not stopped when disabling interface"); ++ } ++ ++ #ifdef CONFIG_BR_SUPPORT ++ /* if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) */ ++ { ++ /* void nat25_db_cleanup(_adapter *priv); */ ++ nat25_db_cleanup(rwnx_vif); ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ } ++ ++#if defined(AICWF_USB_SUPPORT) ++ if (usbdev != NULL) { ++ if (usbdev->state != USB_DOWN_ST) ++ rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, false); ++ } ++#endif ++#if defined(AICWF_SDIO_SUPPORT) ++ bus_if = dev_get_drvdata(rwnx_hw->dev); ++ if (bus_if) { ++ sdiodev = bus_if->bus_priv.sdio; ++ } ++ if (sdiodev != NULL) { ++ if (sdiodev->bus_if->state != BUS_DOWN_ST){ ++ if(RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT){ ++ test_counter = waiting_counter; ++ if(atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTED){ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTING); ++ rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, 3); ++ while (atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING) { ++ AICWFDBG(LOGDEBUG, "%s wifi is disconnecting, waiting 100ms for state to stable\r\n", __func__); ++ msleep(100); ++ test_counter--; ++ if (test_counter ==0) ++ break; ++ } ++ } ++ } ++#ifdef CONFIG_USE_P2P0 ++ if(!rwnx_vif->is_p2p_vif || ( rwnx_vif->is_p2p_vif && rwnx_hw->is_p2p_alive)){ ++ if (rwnx_vif->is_p2p_vif) ++ rwnx_hw->is_p2p_alive = 0; ++#endif ++ rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, false); ++#ifdef CONFIG_USE_P2P0 ++ } ++#endif ++ } ++ } ++#endif ++ /* Ensure that we won't process disconnect ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ ++ rwnx_hw->vif_table[rwnx_vif->vif_index] = NULL; ++ ++ rwnx_chanctx_unlink(rwnx_vif); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MONITOR) ++ rwnx_hw->monitor_vif = RWNX_INVALID_VIF; ++ ++ rwnx_hw->vif_started--; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if (rwnx_hw->vif_started == 0) { ++ /* This also lets both ipc sides remain in sync before resetting */ ++#if 0 ++ rwnx_ipc_tx_drain(rwnx_hw); ++#else ++#ifdef AICWF_USB_SUPPORT ++ if (usbdev->bus_if->state != BUS_DOWN_ST) { ++#else ++ if (sdiodev->bus_if->state != BUS_DOWN_ST) { ++#endif ++ rwnx_send_reset(rwnx_hw); ++ // Set parameters to firmware ++ if (testmode == 0) { ++ rwnx_send_me_config_req(rwnx_hw); ++ // Set channel parameters to firmware ++ rwnx_send_me_chan_config_req(rwnx_hw, country_code); ++ } ++ } ++#endif ++ } ++ clear_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif->drv_flags:%d\r\n", __func__, (int)rwnx_vif->drv_flags); ++ ++ return 0; ++} ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_SHUTDOWN_CALLBACK ++int rwnx_close_(struct net_device *dev){ ++ return rwnx_close(dev); ++} ++#endif ++#endif ++ ++#define IOCTL_HOSTAPD (SIOCIWFIRSTPRIV+28) ++#define IOCTL_WPAS (SIOCIWFIRSTPRIV+30) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) ++static int rwnx_do_ioctl(struct net_device *net, struct ifreq *req, int cmd) ++#else ++static int rwnx_do_ioctl(struct net_device *net, struct ifreq *req, void __user *data, int cmd) ++#endif ++{ ++ int ret = 0; ++ ///TODO: add ioctl command handler later ++ switch (cmd) { ++ case IOCTL_HOSTAPD: ++ printk("IOCTL_HOSTAPD\n"); ++ break; ++ case IOCTL_WPAS: ++ AICWFDBG(LOGINFO, "IOCTL_WPAS\n"); ++ break; ++ case SIOCDEVPRIVATE: ++ AICWFDBG(LOGINFO, "IOCTL SIOCDEVPRIVATE\n"); ++ break; ++ case (SIOCDEVPRIVATE+1): ++ AICWFDBG(LOGINFO, "IOCTL PRIVATE\n"); ++ ret = android_priv_cmd(net, req, cmd); ++ break; ++ case (SIOCDEVPRIVATE+2): ++ AICWFDBG(LOGINFO, "IOCTL PRIVATE+2\n"); ++ #ifdef CONFIG_MCU_MESSAGE ++ devipc_cust_msg(net, req, cmd); ++ #endif ++ break; ++ default: ++ ret = -EOPNOTSUPP; ++ } ++ return ret; ++} ++ ++/** ++ * struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); ++ * Called when a user wants to get the network device usage ++ * statistics. Drivers must do one of the following: ++ * 1. Define @ndo_get_stats64 to fill in a zero-initialised ++ * rtnl_link_stats64 structure passed by the caller. ++ * 2. Define @ndo_get_stats to update a net_device_stats structure ++ * (which should normally be dev->stats) and return a pointer to ++ * it. The structure may be changed asynchronously only if each ++ * field is written atomically. ++ * 3. Update dev->stats asynchronously and atomically, and define ++ * neither operation. ++ */ ++static struct net_device_stats *rwnx_get_stats(struct net_device *dev) ++{ ++ struct rwnx_vif *vif = netdev_priv(dev); ++ ++ return &vif->net_stats; ++} ++ ++/** ++ * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, ++ * struct net_device *sb_dev); ++ * Called to decide which queue to when device supports multiple ++ * transmit queues. ++ */ ++u16 rwnx_select_queue(struct net_device *dev, struct sk_buff *skb, ++ struct net_device *sb_dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ return rwnx_select_txq(rwnx_vif, skb); ++} ++ ++/** ++ * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); ++ * This function is called when the Media Access Control address ++ * needs to be changed. If this interface is not defined, the ++ * mac address can not be changed. ++ */ ++static int rwnx_set_mac_address(struct net_device *dev, void *addr) ++{ ++ struct sockaddr *sa = addr; ++ int ret = 0; ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ AICWFDBG(LOGTRACE, "%s enter \r\n", __func__); ++ ++ ret = eth_mac_addr(dev, sa); ++ AICWFDBG(LOGINFO, "%s set %02X:%02X:%02X:%02X:%02X:%02X\r\n", __func__, ++ dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2], ++ dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]); ++ memcpy(rwnx_vif->wdev.address, dev->dev_addr, 6); ++ ++ return ret; ++} ++ ++static const struct net_device_ops rwnx_netdev_ops = { ++ .ndo_open = rwnx_open, ++ .ndo_stop = rwnx_close, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) ++ .ndo_do_ioctl = rwnx_do_ioctl, ++#else ++ .ndo_siocdevprivate = rwnx_do_ioctl, ++#endif ++ .ndo_start_xmit = rwnx_start_xmit, ++ .ndo_get_stats = rwnx_get_stats, ++#ifndef CONFIG_ONE_TXQ ++ .ndo_select_queue = rwnx_select_queue, ++#endif ++#ifdef CONFIG_SUPPORT_REALTIME_CHANGE_MAC ++ .ndo_set_mac_address = rwnx_set_mac_address ++#endif ++// .ndo_set_features = rwnx_set_features, ++// .ndo_set_rx_mode = rwnx_set_multicast_list, ++}; ++ ++static const struct net_device_ops rwnx_netdev_monitor_ops = { ++ .ndo_open = rwnx_open, ++ .ndo_stop = rwnx_close, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) ++ .ndo_siocdevprivate = rwnx_do_ioctl, ++#else ++ .ndo_do_ioctl = rwnx_do_ioctl, ++#endif ++#ifdef CONFIG_RWNX_MON_XMIT ++ .ndo_start_xmit = rwnx_start_monitor_if_xmit, ++ .ndo_select_queue = rwnx_select_queue, ++#endif ++ .ndo_get_stats = rwnx_get_stats, ++ .ndo_set_mac_address = rwnx_set_mac_address, ++}; ++ ++static void rwnx_netdev_setup(struct net_device *dev) ++{ ++ ether_setup(dev); ++ dev->priv_flags &= ~IFF_TX_SKB_SHARING; ++ dev->netdev_ops = &rwnx_netdev_ops; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) ++ dev->destructor = free_netdev; ++#else ++ dev->needs_free_netdev = true; ++#endif ++ dev->watchdog_timeo = RWNX_TX_LIFETIME_MS; ++ ++ dev->needed_headroom = sizeof(struct rwnx_txhdr) + RWNX_SWTXHDR_ALIGN_SZ; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ dev->needed_headroom = max(dev->needed_headroom, ++ (unsigned short)(sizeof(struct rwnx_amsdu_txhdr) ++ + sizeof(struct ethhdr) + 4 ++ + sizeof(rfc1042_header) + 2)); ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++ dev->hw_features = 0; ++} ++ ++/********************************************************************* ++ * Cfg80211 callbacks (and helper) ++ *********************************************************************/ ++static struct rwnx_vif *rwnx_interface_add(struct rwnx_hw *rwnx_hw, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ struct net_device *ndev; ++ struct rwnx_vif *vif; ++ int min_idx, max_idx; ++ int vif_idx = -1; ++ int i; ++ int nx_nb_ndev_txq = NX_NB_NDEV_TXQ; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_nb_ndev_txq = NX_NB_NDEV_TXQ_FOR_OLD_IC; ++ } ++ ++ AICWFDBG(LOGINFO, "rwnx_interface_add: %s, %d, %d\r\n", name, type, NL80211_IFTYPE_P2P_DEVICE); ++ // Look for an available VIF ++ if (type == NL80211_IFTYPE_AP_VLAN) { ++ min_idx = NX_VIRT_DEV_MAX; ++ max_idx = NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; ++ } else { ++ min_idx = 0; ++ max_idx = NX_VIRT_DEV_MAX; ++ } ++ ++ for (i = min_idx; i < max_idx; i++) { ++ if ((rwnx_hw->avail_idx_map) & BIT(i)) { ++ vif_idx = i; ++ break; ++ } ++ } ++ if (vif_idx < 0) ++ return NULL; ++ ++ #ifndef CONFIG_RWNX_MON_DATA ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ // Check if monitor interface already exists or type is monitor ++ if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR) || ++ (type == NL80211_IFTYPE_MONITOR)) { ++ wiphy_err(rwnx_hw->wiphy, ++ "Monitor+Data interface support (MON_DATA) disabled\n"); ++ return NULL; ++ } ++ } ++ #endif ++ ++#ifndef CONFIG_ONE_TXQ ++ ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type, ++ rwnx_netdev_setup, nx_nb_ndev_txq, 1); ++#else ++ ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type, ++ rwnx_netdev_setup, 1, 1); ++#endif ++ ++ if (!ndev) ++ return NULL; ++ ++ vif = netdev_priv(ndev); ++ vif->key_has_add = 0; ++ ndev->ieee80211_ptr = &vif->wdev; ++ vif->wdev.wiphy = rwnx_hw->wiphy; ++ vif->rwnx_hw = rwnx_hw; ++ vif->ndev = ndev; ++ vif->drv_vif_index = vif_idx; ++ SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy)); ++ vif->wdev.netdev = ndev; ++ vif->wdev.iftype = type; ++ vif->up = false; ++ vif->ch_index = RWNX_CH_NOT_SET; ++ memset(&vif->net_stats, 0, sizeof(vif->net_stats)); ++ vif->is_p2p_vif = 0; ++ ++ #ifdef CONFIG_BR_SUPPORT ++ spin_lock_init(&vif->br_ext_lock); ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ ++ switch (type) { ++ case NL80211_IFTYPE_STATION: ++ vif->sta.ap = NULL; ++ vif->sta.tdls_sta = NULL; ++ vif->sta.external_auth = false; ++ break; ++ case NL80211_IFTYPE_P2P_CLIENT: ++ vif->sta.ap = NULL; ++ vif->sta.tdls_sta = NULL; ++ vif->sta.external_auth = false; ++ vif->is_p2p_vif = 1; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ INIT_LIST_HEAD(&vif->ap.mpath_list); ++ INIT_LIST_HEAD(&vif->ap.proxy_list); ++ vif->ap.create_path = false; ++ vif->ap.generation = 0; ++ vif->ap.mesh_pm = NL80211_MESH_POWER_ACTIVE; ++ vif->ap.next_mesh_pm = NL80211_MESH_POWER_ACTIVE; ++ // no break ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ INIT_LIST_HEAD(&vif->ap.sta_list); ++ memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn)); ++ break; ++ case NL80211_IFTYPE_P2P_GO: ++ INIT_LIST_HEAD(&vif->ap.sta_list); ++ memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn)); ++ vif->is_p2p_vif = 1; ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ { ++ struct rwnx_vif *master_vif; ++ bool found = false; ++ list_for_each_entry(master_vif, &rwnx_hw->vifs, list) { ++ if ((RWNX_VIF_TYPE(master_vif) == NL80211_IFTYPE_AP) && ++ !(!memcmp(master_vif->ndev->dev_addr, params->macaddr, ++ ETH_ALEN))) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ goto err; ++ ++ vif->ap_vlan.master = master_vif; ++ vif->ap_vlan.sta_4a = NULL; ++ break; ++ } ++ case NL80211_IFTYPE_MONITOR: ++ ndev->type = ARPHRD_IEEE80211_RADIOTAP; ++ ndev->netdev_ops = &rwnx_netdev_monitor_ops; ++ break; ++ default: ++ break; ++ } ++ ++ if (type == NL80211_IFTYPE_AP_VLAN) { ++ memcpy((void *)ndev->dev_addr, (const void *)params->macaddr, ETH_ALEN); ++ memcpy((void *)vif->wdev.address, (const void *)params->macaddr, ETH_ALEN); ++ } else { ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 17, 0) ++ unsigned char mac_addr[6]; ++ memcpy(mac_addr, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ mac_addr[5] ^= vif_idx; ++ //memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); ++ eth_hw_addr_set(ndev, mac_addr); ++ memcpy(vif->wdev.address, mac_addr, ETH_ALEN); ++#else ++ memcpy(ndev->dev_addr, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ ndev->dev_addr[5] ^= vif_idx; ++ memcpy(vif->wdev.address, ndev->dev_addr, ETH_ALEN); ++#endif ++ ++ } ++ ++ AICWFDBG(LOGINFO, "interface add:%x %x %x %x %x %x\n", vif->wdev.address[0], vif->wdev.address[1], \ ++ vif->wdev.address[2], vif->wdev.address[3], vif->wdev.address[4], vif->wdev.address[5]); ++ ++ if (params) { ++ vif->use_4addr = params->use_4addr; ++ ndev->ieee80211_ptr->use_4addr = params->use_4addr; ++ } else ++ vif->use_4addr = false; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) ++ if (cfg80211_register_netdevice(ndev)) ++#else ++ if (register_netdevice(ndev)) ++#endif ++ goto err; ++ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_add_tail(&vif->list, &rwnx_hw->vifs); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->avail_idx_map &= ~BIT(vif_idx); ++ ++ return vif; ++ ++err: ++ free_netdev(ndev); ++ return NULL; ++} ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++void aicwf_p2p_alive_timeout(ulong data) ++#else ++void aicwf_p2p_alive_timeout(struct timer_list *t) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct rwnx_vif *rwnx_vif; ++ struct rwnx_vif *rwnx_vif1, *tmp; ++ u8_l p2p = 0; ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ rwnx_vif = (struct rwnx_vif *)data; ++ rwnx_hw = rwnx_vif->rwnx_hw; ++ #else ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ rwnx_hw = timer_container_of(rwnx_hw, t, p2p_alive_timer); ++ #else ++ rwnx_hw = from_timer(rwnx_hw, t, p2p_alive_timer); ++ #endif ++ rwnx_vif = rwnx_hw->p2p_dev_vif; ++ #endif ++ ++ list_for_each_entry_safe(rwnx_vif1, tmp, &rwnx_hw->vifs, list) { ++ if ((rwnx_hw->avail_idx_map & BIT(rwnx_vif1->drv_vif_index)) == 0) { ++ switch (RWNX_VIF_TYPE(rwnx_vif1)) { ++ case NL80211_IFTYPE_P2P_CLIENT: ++ case NL80211_IFTYPE_P2P_GO: ++ rwnx_hw->is_p2p_alive = 1; ++ p2p = 1; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ ++ if (p2p) ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++ else ++ atomic_inc(&rwnx_hw->p2p_alive_timer_count); ++ ++ if (atomic_read(&rwnx_hw->p2p_alive_timer_count) < P2P_ALIVE_TIME_COUNT) { ++ mod_timer(&rwnx_hw->p2p_alive_timer, ++ jiffies + msecs_to_jiffies(P2P_ALIVE_TIME_MS)); ++ return; ++ } else ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++ ++ rwnx_hw->is_p2p_alive = 0; ++ if (rwnx_vif->up) { ++ rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, true); ++ ++ /* Ensure that we won't process disconnect ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ ++ rwnx_vif->up = false; ++ rwnx_hw->vif_table[rwnx_vif->vif_index] = NULL; ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif[%d] down \r\n", __func__, rwnx_vif->vif_index); ++ rwnx_hw->vif_started--; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++} ++ ++ ++/********************************************************************* ++ * Cfg80211 callbacks (and helper) ++ *********************************************************************/ ++static struct wireless_dev *rwnx_virtual_interface_add(struct rwnx_hw *rwnx_hw, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ struct wireless_dev *wdev = NULL; ++ struct rwnx_vif *vif; ++ int min_idx, max_idx; ++ int vif_idx = -1; ++ int i; ++ ++ printk("rwnx_virtual_interface_add: %d, %s\n", type, name); ++ ++ if (type == NL80211_IFTYPE_AP_VLAN) { ++ min_idx = NX_VIRT_DEV_MAX; ++ max_idx = NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; ++ } else { ++ min_idx = 0; ++ max_idx = NX_VIRT_DEV_MAX; ++ } ++ ++ for (i = min_idx; i < max_idx; i++) { ++ if ((rwnx_hw->avail_idx_map) & BIT(i)) { ++ vif_idx = i; ++ break; ++ } ++ } ++ ++ if (vif_idx < 0) { ++ printk("virtual_interface_add %s fail\n", name); ++ return NULL; ++ } ++ ++ vif = kzalloc(sizeof(struct rwnx_vif), GFP_KERNEL); ++ if (unlikely(!vif)) { ++ printk("Could not allocate wireless device\n"); ++ return NULL; ++ } ++ wdev = &vif->wdev; ++ wdev->wiphy = rwnx_hw->wiphy; ++ wdev->iftype = type; ++ ++ printk("rwnx_virtual_interface_add, ifname=%s, wdev=%p, vif_idx=%d\n", name, wdev, vif_idx); ++ ++ #ifndef CONFIG_USE_P2P0 ++ vif->is_p2p_vif = 1; ++ vif->rwnx_hw = rwnx_hw; ++ vif->vif_index = vif_idx; ++ vif->wdev.wiphy = rwnx_hw->wiphy; ++ vif->drv_vif_index = vif_idx; ++ vif->up = false; ++ vif->ch_index = RWNX_CH_NOT_SET; ++ memset(&vif->net_stats, 0, sizeof(vif->net_stats)); ++ vif->use_4addr = false; ++ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_add_tail(&vif->list, &rwnx_hw->vifs); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if (rwnx_hw->is_p2p_alive == 0) { ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ init_timer(&rwnx_hw->p2p_alive_timer); ++ rwnx_hw->p2p_alive_timer.data = (unsigned long)vif; ++ rwnx_hw->p2p_alive_timer.function = aicwf_p2p_alive_timeout; ++ #else ++ timer_setup(&rwnx_hw->p2p_alive_timer, aicwf_p2p_alive_timeout, 0); ++ #endif ++ rwnx_hw->is_p2p_alive = 0; ++ rwnx_hw->is_p2p_connected = 0; ++ rwnx_hw->p2p_dev_vif = vif; ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++ } ++ #endif ++ rwnx_hw->avail_idx_map &= ~BIT(vif_idx); ++ ++ memcpy(vif->wdev.address, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ vif->wdev.address[5] ^= vif_idx; ++ printk("p2p dev addr=%x %x %x %x %x %x\n", vif->wdev.address[0], vif->wdev.address[1], \ ++ vif->wdev.address[2], vif->wdev.address[3], vif->wdev.address[4], vif->wdev.address[5]); ++ ++ return wdev; ++} ++ ++/* ++ * @brief Retrieve the rwnx_sta object allocated for a given MAC address ++ * and a given role. ++ */ ++static struct rwnx_sta *rwnx_retrieve_sta(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, u8 *addr, ++ __le16 fc, bool ap) ++{ ++ if (ap) { ++ /* only deauth, disassoc and action are bufferable MMPDUs */ ++ bool bufferable = ieee80211_is_deauth(fc) || ++ ieee80211_is_disassoc(fc) || ++ ieee80211_is_action(fc); ++ ++ /* Check if the packet is bufferable or not */ ++ if (bufferable) { ++ /* Check if address is a broadcast or a multicast address */ ++ if (is_broadcast_ether_addr(addr) || is_multicast_ether_addr(addr)) { ++ /* Returned STA pointer */ ++ struct rwnx_sta *rwnx_sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ ++ if (rwnx_sta->valid) ++ return rwnx_sta; ++ } else { ++ /* Returned STA pointer */ ++ struct rwnx_sta *rwnx_sta; ++ ++ /* Go through list of STAs linked with the provided VIF */ ++ spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ list_for_each_entry(rwnx_sta, &rwnx_vif->ap.sta_list, list) { ++ if (rwnx_sta->valid && ++ ether_addr_equal(rwnx_sta->mac_addr, addr)) { ++ /* Return the found STA */ ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ return rwnx_sta; ++ } ++ } ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ } ++ } ++ } else { ++ return rwnx_vif->sta.ap; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * @add_virtual_intf: create a new virtual interface with the given name, ++ * must set the struct wireless_dev's iftype. Beware: You must create ++ * the new netdev in the wiphy's network namespace! Returns the struct ++ * wireless_dev, or an ERR_PTR. For P2P device wdevs, the driver must ++ * also set the address member in the wdev. ++ */ ++static struct wireless_dev *rwnx_cfg80211_add_iface(struct wiphy *wiphy, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct wireless_dev *wdev; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) ++ unsigned char name_assign_type = NET_NAME_UNKNOWN; ++#endif ++ ++ if (type != NL80211_IFTYPE_P2P_DEVICE) { ++ struct rwnx_vif *vif = rwnx_interface_add(rwnx_hw, name, name_assign_type, type, params); ++ if (!vif) ++ return ERR_PTR(-EINVAL); ++ return &vif->wdev; ++ ++ } else { ++ wdev = rwnx_virtual_interface_add(rwnx_hw, name, name_assign_type, type, params); ++ if (!wdev) ++ return ERR_PTR(-EINVAL); ++ return wdev; ++ } ++} ++ ++/** ++ * @del_virtual_intf: remove the virtual interface ++ */ ++static int rwnx_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ struct net_device *dev = wdev->netdev; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ ++ AICWFDBG(LOGINFO, "del_iface: %p, %x\n", wdev, wdev->address[5]); ++ ++ if (!dev || !rwnx_vif->ndev) { ++ cfg80211_unregister_wdev(wdev); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_del(&rwnx_vif->list); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->avail_idx_map |= BIT(rwnx_vif->drv_vif_index); ++ rwnx_vif->ndev = NULL; ++ kfree(rwnx_vif); ++ return 0; ++ } ++ ++ netdev_info(dev, "Remove Interface"); ++ ++ if (dev->reg_state == NETREG_REGISTERED) { ++ /* Will call rwnx_close if interface is UP */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) ++ cfg80211_unregister_netdevice(dev); ++#else ++ unregister_netdevice(dev); ++#endif ++ ++ } ++ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_del(&rwnx_vif->list); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->avail_idx_map |= BIT(rwnx_vif->drv_vif_index); ++ rwnx_vif->ndev = NULL; ++ ++ /* Clear the priv in adapter */ ++ dev->ieee80211_ptr = NULL; ++ ++ return 0; ++} ++ ++/** ++ * @change_virtual_intf: change type/configuration of virtual interface, ++ * keep the struct wireless_dev's iftype updated. ++ */ ++static int rwnx_cfg80211_change_iface(struct wiphy *wiphy, ++ struct net_device *dev, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++#ifndef CONFIG_RWNX_MON_DATA ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++#endif ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct mm_add_if_cfm add_if_cfm; ++ bool_l p2p = false; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("change_if: %d to %d, %d, %d", vif->wdev.iftype, type, NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_STATION); ++ ++#ifndef CONFIG_RWNX_MON_DATA ++ if ((type == NL80211_IFTYPE_MONITOR) && ++ (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_MONITOR)) { ++ struct rwnx_vif *vif_el; ++ list_for_each_entry(vif_el, &rwnx_hw->vifs, list) { ++ // Check if data interface already exists ++ if ((vif_el != vif) && ++ (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_MONITOR)) { ++ wiphy_err(rwnx_hw->wiphy, ++ "Monitor+Data interface support (MON_DATA) disabled\n"); ++ return -EIO; ++ } ++ } ++ } ++#endif ++ ++ // Reset to default case (i.e. not monitor) ++ dev->type = ARPHRD_ETHER; ++ dev->netdev_ops = &rwnx_netdev_ops; ++ ++ switch (type) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ vif->sta.ap = NULL; ++ vif->sta.tdls_sta = NULL; ++ vif->sta.external_auth = false; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ INIT_LIST_HEAD(&vif->ap.mpath_list); ++ INIT_LIST_HEAD(&vif->ap.proxy_list); ++ vif->ap.create_path = false; ++ vif->ap.generation = 0; ++ // no break ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ INIT_LIST_HEAD(&vif->ap.sta_list); ++ memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn)); ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ return -EPERM; ++ case NL80211_IFTYPE_MONITOR: ++ dev->type = ARPHRD_IEEE80211_RADIOTAP; ++ dev->netdev_ops = &rwnx_netdev_monitor_ops; ++ break; ++ default: ++ break; ++ } ++ ++ vif->wdev.iftype = type; ++ if (params->use_4addr != -1) ++ vif->use_4addr = params->use_4addr; ++ if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO) ++ p2p = true; ++ ++ if (vif->up) { ++ /* Abort scan request on the vif */ ++ if (vif->rwnx_hw->scan_request && ++ vif->rwnx_hw->scan_request->wdev == &vif->wdev) { ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ cfg80211_scan_done(vif->rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(vif->rwnx_hw->scan_request, true); ++#endif ++ ret = rwnx_send_scanu_cancel_req(vif->rwnx_hw, NULL); ++ if (ret) { ++ printk("scanu_cancel fail\n"); ++ return ret; ++ } ++ vif->rwnx_hw->scan_request = NULL; ++#else ++ if ((ret = rwnx_send_scanu_cancel_req(vif->rwnx_hw, NULL))) { ++ AICWFDBG(LOGERROR, "scanu_cancel fail\n"); ++ return ret; ++ } ++#endif ++ } ++ ret = rwnx_send_remove_if(vif->rwnx_hw, vif->vif_index, false); ++ if (ret) { ++ printk("remove_if fail\n"); ++ return ret; ++ } ++ vif->rwnx_hw->vif_table[vif->vif_index] = NULL; ++ printk("change_if from %d \n", vif->vif_index); ++ ret = rwnx_send_add_if(vif->rwnx_hw, vif->wdev.address, RWNX_VIF_TYPE(vif), p2p, &add_if_cfm); ++ if (ret) { ++ printk("add if fail\n"); ++ return ret; ++ } ++ if (add_if_cfm.status != 0) { ++ printk("add if status fail\n"); ++ return -EIO; ++ } ++ ++ printk("change_if to %d \n", add_if_cfm.inst_nbr); ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&vif->rwnx_hw->cb_lock); ++ vif->vif_index = add_if_cfm.inst_nbr; ++ vif->rwnx_hw->vif_table[add_if_cfm.inst_nbr] = vif; ++ spin_unlock_bh(&vif->rwnx_hw->cb_lock); ++ } ++ ++ if (type == NL80211_IFTYPE_MONITOR) { ++ vif->rwnx_hw->monitor_vif = vif->vif_index; ++ #if defined(CONFIG_RWNX_MON_XMIT) ++ rwnx_txq_unk_vif_init(vif); ++ #endif ++ #if defined(CONFIG_RWNX_MON_RXFILTER) ++ rwnx_send_set_filter(vif->rwnx_hw, (FIF_BCN_PRBRESP_PROMISC | FIF_OTHER_BSS | FIF_PSPOLL | FIF_PROBE_REQ)); ++ #endif ++ } else { ++ vif->rwnx_hw->monitor_vif = RWNX_INVALID_VIF; ++ } ++ ++ return 0; ++} ++ ++static int rwnx_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ int ret = 0; ++ ++ //do nothing ++ printk("P2P interface started\n"); ++ ++ return ret; ++} ++ ++static void rwnx_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ int ret = 0; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ /* Abort scan request on the vif */ ++ if (rwnx_hw->scan_request && ++ rwnx_hw->scan_request->wdev == &rwnx_vif->wdev) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ cfg80211_scan_done(rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(rwnx_hw->scan_request, true); ++#endif ++ rwnx_hw->scan_request = NULL; ++ ret = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ if (ret) ++ printk("scanu_cancel fail\n"); ++ } ++ ++ if (rwnx_vif == rwnx_hw->p2p_dev_vif) { ++ rwnx_hw->is_p2p_alive = 0; ++ if (timer_pending(&rwnx_hw->p2p_alive_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&rwnx_hw->p2p_alive_timer); ++#else ++ del_timer_sync(&rwnx_hw->p2p_alive_timer); ++#endif ++ } ++ ++ if (rwnx_vif->up) { ++ rwnx_send_remove_if(rwnx_hw, rwnx_vif->vif_index, true); ++ /* Ensure that we won't process disconnect ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->up = false; ++ rwnx_hw->vif_table[rwnx_vif->vif_index] = NULL; ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif[%d] down \r\n", __func__, rwnx_vif->vif_index); ++ rwnx_hw->vif_started--; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++ ++ } ++ ++ printk("Exit. P2P interface stopped\n"); ++ ++ return; ++} ++ ++ ++/** ++ * @scan: Request to do a scan. If returning zero, the scan request is given ++ * the driver, and will be valid until passed to cfg80211_scan_done(). ++ * For scan results, call cfg80211_inform_bss(); you can call this outside ++ * the scan/scan_done bracket too. ++ */ ++static int rwnx_cfg80211_scan(struct wiphy *wiphy, ++ struct cfg80211_scan_request *request) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(request->wdev, struct rwnx_vif, wdev); ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if(testmode){ ++ return -EBUSY; ++ } ++ ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING){ ++ AICWFDBG(LOGERROR, "%s wifi is connecting, return it\r\n", __func__); ++ return -EBUSY; ++ } ++ ++ if (scanning) { ++ AICWFDBG(LOGERROR, "%s is scanning, abort\n", __func__); ++ #if 0 ++ error = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ if (error) ++ return error; ++ msleep(150); ++ #endif ++ return -EBUSY; ++ } ++ ++ if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) && ++ rwnx_vif->sta.external_auth) { ++ AICWFDBG(LOGERROR, "scan about: external auth\r\n"); ++ return -EBUSY; ++ } ++ ++ rwnx_hw->scan_request = request; ++ error = rwnx_send_scanu_req(rwnx_hw, rwnx_vif, request); ++ if (error) ++ return error; ++ ++ return 0; ++} ++ ++bool key_flag = false; ++/** ++ * @add_key: add a key with the given parameters. @mac_addr will be %NULL ++ * when adding a group key. ++ */ ++ static int rwnx_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool pairwise, const u8 *mac_addr, ++ struct key_params *params) ++ ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(netdev); ++ int i, error = 0; ++ struct mm_key_add_cfm key_add_cfm; ++ u8_l cipher = 0; ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_key *rwnx_key; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (mac_addr) { ++ sta = rwnx_get_sta(rwnx_hw, mac_addr); ++ if (!sta) ++ return -EINVAL; ++ rwnx_key = &sta->key; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.paired_cipher_type = params->cipher; ++ } else { ++ rwnx_key = &vif->key[key_index]; ++ vif->key_has_add = 1; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.group_cipher_type = params->cipher; ++ } ++ ++ /* Retrieve the cipher suite selector */ ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ cipher = MAC_CIPHER_WEP40; ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ cipher = MAC_CIPHER_WEP104; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ cipher = MAC_CIPHER_TKIP; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ cipher = MAC_CIPHER_CCMP; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ cipher = MAC_CIPHER_BIP_CMAC_128; ++ break; ++ case WLAN_CIPHER_SUITE_SMS4: ++ { ++ // Need to reverse key order ++ u8 tmp, *key = (u8 *)params->key; ++ cipher = MAC_CIPHER_WPI_SMS4; ++ for (i = 0; i < WPI_SUBKEY_LEN/2; i++) { ++ tmp = key[i]; ++ key[i] = key[WPI_SUBKEY_LEN - 1 - i]; ++ key[WPI_SUBKEY_LEN - 1 - i] = tmp; ++ } ++ for (i = 0; i < WPI_SUBKEY_LEN/2; i++) { ++ tmp = key[i + WPI_SUBKEY_LEN]; ++ key[i + WPI_SUBKEY_LEN] = key[WPI_KEY_LEN - 1 - i]; ++ key[WPI_KEY_LEN - 1 - i] = tmp; ++ } ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ key_flag = false; ++ error = rwnx_send_key_add(rwnx_hw, vif->vif_index, ++ (sta ? sta->sta_idx : 0xFF), pairwise, ++ (u8 *)params->key, params->key_len, ++ key_index, cipher, &key_add_cfm); ++ if (error) ++ return error; ++ ++ if (key_add_cfm.status != 0) { ++ RWNX_PRINT_CFM_ERR(key_add); ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ rwnx_key->hw_idx = key_add_cfm.hw_key_idx; ++ ++ return 0; ++} ++ ++/** ++ * @get_key: get information about the key with the given parameters. ++ * @mac_addr will be %NULL when requesting information for a group ++ * key. All pointers given to the @callback function need not be valid ++ * after it returns. This function should return an error if it is ++ * not possible to retrieve the key, -ENOENT if it doesn't exist. ++ * ++ */ ++static int rwnx_cfg80211_get_key(struct wiphy *wiphy, struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool pairwise, const u8 *mac_addr, ++ void *cookie, ++ void (*callback)(void *cookie, struct key_params*)) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ return -1; ++} ++ ++ ++/** ++ * @del_key: remove a key given the @mac_addr (%NULL for a group key) ++ * and @key_index, return -ENOENT if the key doesn't exist. ++ */ ++static int rwnx_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool pairwise, const u8 *mac_addr) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(netdev); ++ int error; ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_key *rwnx_key; ++ if (!key_flag && vif->wdev.iftype == NL80211_IFTYPE_STATION) ++ return 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ if (mac_addr) { ++ sta = rwnx_get_sta(rwnx_hw, mac_addr); ++ if (!sta) ++ return -EINVAL; ++ rwnx_key = &sta->key; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.paired_cipher_type = 0xff; ++ } else { ++ rwnx_key = &vif->key[key_index]; ++ vif->key_has_add = 0; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.group_cipher_type = 0xff; ++ } ++ ++ error = rwnx_send_key_del(rwnx_hw, rwnx_key->hw_idx); ++ ++ rwnx_key->hw_idx = 0; ++ return error; ++} ++ ++/** ++ * @set_default_key: set the default key on an interface ++ */ ++static int rwnx_cfg80211_set_default_key(struct wiphy *wiphy, ++ struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool unicast, bool multicast) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ return 0; ++} ++ ++/** ++ * @set_default_mgmt_key: set the default management frame key on an interface ++ */ ++static int rwnx_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, ++ struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index) ++{ ++ return 0; ++} ++ ++/** ++ * @connect: Connect to the ESS with the specified parameters. When connected, ++ * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. ++ * If the connection fails for some reason, call cfg80211_connect_result() ++ * with the status from the AP. ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_connect_params *sme) ++{ ++ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct sm_connect_cfm sm_connect_cfm; ++ int error = 0; ++ int is_wep = ((sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104)); ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#if 1 ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTED) { ++ AICWFDBG(LOGDEBUG, "%s this connection is roam \r\n", __func__); ++ rwnx_vif->sta.is_roam = true; ++ }else{ ++ rwnx_vif->sta.is_roam = false; ++ } ++ ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING|| ++ (int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING) { ++ AICWFDBG(LOGERROR, "%s driver is disconnecting or connecting ,return it \r\n", __func__); ++ return 0; ++ } ++#endif ++ ++ if(rwnx_vif->sta.is_roam){ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_ROAMING); ++ }else{ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTING); ++ } ++ ++ if (is_wep) { ++ if(sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { ++ if(rwnx_vif->wep_enabled && rwnx_vif->wep_auth_err) { ++ if(rwnx_vif->last_auth_type == NL80211_AUTHTYPE_SHARED_KEY) ++ sme->auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; ++ else ++ sme->auth_type = NL80211_AUTHTYPE_SHARED_KEY; ++ } else { ++ if((rwnx_vif->wep_enabled && !rwnx_vif->wep_auth_err)) ++ sme->auth_type = rwnx_vif->last_auth_type; ++ else ++ sme->auth_type = NL80211_AUTHTYPE_SHARED_KEY; ++ } ++ printk("auto: use sme->auth_type = %d\r\n", sme->auth_type); ++ } else { ++ if (rwnx_vif->wep_enabled && rwnx_vif->wep_auth_err && (sme->auth_type == rwnx_vif->last_auth_type)) { ++ if(sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { ++ sme->auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; ++ printk("start connect, auth_type changed, shared --> open\n"); ++ } else if(sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { ++ sme->auth_type = NL80211_AUTHTYPE_SHARED_KEY; ++ printk("start connect, auth_type changed, open --> shared\n"); ++ } ++ } ++ } ++ } ++ ++ /* For SHARED-KEY authentication, must install key first */ ++ if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY && sme->key) { ++ struct key_params key_params; ++ key_params.key = (u8*)sme->key; ++ key_params.seq = NULL; ++ key_params.key_len = sme->key_len; ++ key_params.seq_len = 0; ++ key_params.cipher = sme->crypto.cipher_group; ++ rwnx_cfg80211_add_key(wiphy, dev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ 0, ++#endif ++ sme->key_idx, false, NULL, &key_params); ++ } ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ else if ((sme->auth_type == NL80211_AUTHTYPE_SAE) && ++ !(sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) { ++ netdev_err(dev, "Doesn't support SAE without external authentication\n"); ++ return -EINVAL; ++ } ++#endif ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) { ++ rwnx_hw->is_p2p_connected = 1; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) { ++ rwnx_vif->sta.paired_cipher_type = 0xff; ++ rwnx_vif->sta.group_cipher_type = 0xff; ++ } ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_sm_connect_req(rwnx_hw, rwnx_vif, sme, &sm_connect_cfm); ++ if (error) ++ return error; ++ ++ // Check the status ++ switch (sm_connect_cfm.status) { ++ case CO_OK: ++ error = 0; ++ break; ++ case CO_BUSY: ++ error = -EINPROGRESS; ++ break; ++ case CO_OP_IN_PROGRESS: ++ error = -EALREADY; ++ break; ++ default: ++ error = -EIO; ++ break; ++ } ++ ++ return error; ++ ++} ++ ++/** ++ * @disconnect: Disconnect from the BSS/ESS. ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, ++ u16 reason_code) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int ret = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ AICWFDBG(LOGINFO, "%s drv_vif_index:%d disconnect reason:%d \r\n", ++ __func__, rwnx_vif->drv_vif_index, reason_code); ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTED) { ++ AICWFDBG(LOGERROR, "%s this\r\n",__func__); ++ WARN_ON(1); ++ return -EBUSY; ++ } ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTING) { ++ AICWFDBG(LOGERROR, "%s wifi is disconnecting, return it:%d \r\n", ++ __func__, reason_code); ++ return -EBUSY; ++ } ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTED|| ++ atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTING|| ++ atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_ROAMING) { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTING); ++ key_flag = true; ++ ret = rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, reason_code); ++#ifdef AICWF_SDIO_SUPPORT ++ if (rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { ++ AICWFDBG(LOGINFO, "%s bus is down %d\n", __func__, ret); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ } ++#endif ++ return ret; ++ } ++#if 0 ++ else { ++ cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, ++ reason_code?reason_code:WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ return 0; ++ } ++#endif ++ return 0; ++} ++ ++#ifdef CONFIG_SCHED_SCAN ++ ++static int rwnx_cfg80211_sched_scan_stop(struct wiphy *wiphy, ++ struct net_device *ndev ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ ,u64 reqid) ++#else ++ ) ++#endif ++{ ++ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ //struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ AICWFDBG(LOGINFO, "%s enter wiphy:%p\r\n", __func__, wiphy); ++ ++ if(rwnx_hw->scan_request){ ++ AICWFDBG(LOGINFO, "%s rwnx_send_scanu_cancel_req\r\n", __func__); ++ return rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ }else{ ++ return 0; ++ } ++} ++ ++ ++static int rwnx_cfg80211_sched_scan_start(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_sched_scan_request *request) ++ ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct cfg80211_scan_request *scan_request = NULL; ++ ++ int ret = 0; ++ int index = 0; ++ ++ AICWFDBG(LOGINFO, "%s enter wiphy:%p\r\n", __func__, wiphy); ++ ++ if(rwnx_hw->is_sched_scan || scanning){ ++ AICWFDBG(LOGERROR, "%s is_sched_scanning and scanning, busy", __func__); ++ return -EBUSY; ++ } ++ ++ scan_request = (struct cfg80211_scan_request *)kmalloc(sizeof(struct cfg80211_scan_request), GFP_KERNEL); ++ ++ scan_request->ssids = request->ssids; ++ scan_request->n_channels = request->n_channels; ++ scan_request->n_ssids = request->n_match_sets; ++ scan_request->no_cck = false; ++ scan_request->ie = request->ie; ++ scan_request->ie_len = request->ie_len; ++ scan_request->flags = request->flags; ++ ++ scan_request->wiphy = wiphy; ++ scan_request->scan_start = request->scan_start; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) ++ memcpy(scan_request->mac_addr, request->mac_addr, ETH_ALEN); ++ memcpy(scan_request->mac_addr_mask, request->mac_addr_mask, ETH_ALEN); ++#endif ++ rwnx_hw->sched_scan_req = request; ++ scan_request->wdev = &rwnx_vif->wdev; ++ AICWFDBG(LOGDEBUG, "%s scan_request->n_channels:%d \r\n", __func__, scan_request->n_channels); ++ AICWFDBG(LOGDEBUG, "%s scan_request->n_ssids:%d \r\n", __func__, scan_request->n_ssids); ++ ++ for(index = 0; index < scan_request->n_ssids; index++){ ++ memset(scan_request->ssids[index].ssid, 0, IEEE80211_MAX_SSID_LEN); ++ ++ memcpy(scan_request->ssids[index].ssid, ++ request->match_sets[index].ssid.ssid, ++ IEEE80211_MAX_SSID_LEN); ++ ++ scan_request->ssids[index].ssid_len = request->match_sets[index].ssid.ssid_len; ++ ++ AICWFDBG(LOGDEBUG, "%s request ssid:%s len:%d \r\n", __func__, ++ scan_request->ssids[index].ssid, scan_request->ssids[index].ssid_len); ++ } ++ ++ for(index = 0;index < scan_request->n_channels; index++){ ++ scan_request->channels[index] = request->channels[index]; ++ ++ AICWFDBG(LOGDEBUG, "%s scan_request->channels[%d]:%d \r\n", __func__, index, ++ scan_request->channels[index]->center_freq); ++ ++ if(scan_request->channels[index] == NULL){ ++ AICWFDBG(LOGERROR, "%s ERROR!!! channels is NULL", __func__); ++ continue; ++ } ++ } ++ ++ rwnx_hw->is_sched_scan = true; ++ ++ if(scanning){ ++ AICWFDBG(LOGERROR, "%s scanning, about it", __func__); ++ kfree(scan_request); ++ return -EBUSY; ++ }else{ ++ ret = rwnx_cfg80211_scan(wiphy, scan_request); ++ } ++ ++ return ret; ++} ++#endif //CONFIG_SCHED_SCAN ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++/** ++ * @external_auth: indicates result of offloaded authentication processing from ++ * user space ++ */ ++static int rwnx_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_external_auth_params *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ ++ if (!rwnx_vif->sta.external_auth) ++ return -EINVAL; ++ ++ rwnx_external_auth_disable(rwnx_vif); ++ return rwnx_send_sm_external_auth_required_rsp(rwnx_hw, rwnx_vif, ++ params->status); ++} ++#endif ++ ++/** ++ * @add_station: Add a new station. ++ */ ++static int rwnx_cfg80211_add_station(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac, ++#else ++ const u8 *mac, ++#endif ++ struct station_parameters *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct me_sta_add_cfm me_sta_add_cfm; ++ int error = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ WARN_ON(RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN); ++ ++ /* Do not add TDLS station */ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ++ return 0; ++ ++ /* Indicate we are in a STA addition process - This will allow handling ++ * potential PS mode change indications correctly ++ */ ++ rwnx_hw->adding_sta = true; ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_me_sta_add(rwnx_hw, params, mac, rwnx_vif->vif_index, &me_sta_add_cfm); ++ if (error) ++ return error; ++ ++ // Check the status ++ switch (me_sta_add_cfm.status) { ++ case CO_OK: ++ { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[me_sta_add_cfm.sta_idx]; ++ int tid; ++ sta->aid = params->aid; ++ ++ sta->sta_idx = me_sta_add_cfm.sta_idx; ++ sta->ch_idx = rwnx_vif->ch_index; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->vlan_idx = sta->vif_idx; ++ sta->qos = (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) != 0; ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ sta->ht = params->link_sta_params.ht_capa ? 1 : 0; ++ sta->vht = params->link_sta_params.vht_capa ? 1 : 0; ++#else ++ sta->ht = params->ht_capa ? 1 : 0; ++ sta->vht = params->vht_capa ? 1 : 0; ++#endif ++ sta->acm = 0; ++ sta->key.hw_idx = 0; ++ ++ if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) ++ sta->mesh_pm = params->local_pm; ++ else ++ sta->mesh_pm = rwnx_vif->ap.next_mesh_pm; ++ rwnx_update_mesh_power_mode(rwnx_vif); ++ ++ for (tid = 0; tid < NX_NB_TXQ_PER_STA; tid++) { ++ int uapsd_bit = rwnx_hwq2uapsd[rwnx_tid2hwq[tid]]; ++ if (params->uapsd_queues & uapsd_bit) ++ sta->uapsd_tids |= 1 << tid; ++ else ++ sta->uapsd_tids &= ~(1 << tid); ++ } ++ memcpy(sta->mac_addr, mac, ETH_ALEN); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, sta); ++#endif ++ ++ /* Ensure that we won't process PS change or channel switch ind*/ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_txq_sta_init(rwnx_hw, sta, rwnx_txq_vif_get_status(rwnx_vif)); ++ list_add_tail(&sta->list, &rwnx_vif->ap.sta_list); ++ sta->valid = true; ++ rwnx_ps_bh_enable(rwnx_hw, sta, sta->ps.active || me_sta_add_cfm.pm_state); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ error = 0; ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { ++ struct station_info sinfo; ++ memset(&sinfo, 0, sizeof(struct station_info)); ++ sinfo.assoc_req_ies = NULL; ++ sinfo.assoc_req_ies_len = 0; ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; ++ #endif ++ cfg80211_new_sta(rwnx_vif->ndev, sta->mac_addr, &sinfo, GFP_KERNEL); ++ } ++#ifdef CONFIG_RWNX_BFMER ++ if (rwnx_hw->mod_params->bfmer) ++ rwnx_send_bfmer_enable(rwnx_hw, sta, params->vht_capa); ++ ++ rwnx_mu_group_sta_init(sta, params->vht_capa); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ #define PRINT_STA_FLAG(f) \ ++ (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "") ++ ++ netdev_info(dev, "Add sta %d (%pM) flags=%s%s%s%s%s%s%s", ++ sta->sta_idx, mac, ++ PRINT_STA_FLAG(AUTHORIZED), ++ PRINT_STA_FLAG(SHORT_PREAMBLE), ++ PRINT_STA_FLAG(WME), ++ PRINT_STA_FLAG(MFP), ++ PRINT_STA_FLAG(AUTHENTICATED), ++ PRINT_STA_FLAG(TDLS_PEER), ++ PRINT_STA_FLAG(ASSOCIATED)); ++ #undef PRINT_STA_FLAG ++ break; ++ } ++ default: ++ error = -EBUSY; ++ break; ++ } ++ ++ rwnx_hw->adding_sta = false; ++ ++ return error; ++} ++ ++/** ++ * @del_station: Remove a station ++ */ ++static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)) ++ const u8 *mac ++#else ++ struct station_del_parameters *params ++#endif ++ ++) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_sta *cur, *tmp; ++ int error = 0, found = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ const u8 *mac = NULL; ++#endif ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *reord_tmp; ++ u8 *macaddr; ++ struct aicwf_rx_priv *rx_priv; ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ if (params) ++ mac = params->mac; ++#endif ++ printk("%s: %pM\n", __func__, mac); ++ ++ do { ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ if(list_empty(&rwnx_vif->ap.sta_list)) { ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ break; ++ } ++ ++ list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { ++ if ((!mac) || (!memcmp(cur->mac_addr, mac, ETH_ALEN))) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if(found) { ++ cur->ps.active = false; ++ cur->valid = false; ++ list_del(&cur->list); ++ } ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if(found) { ++ netdev_info(dev, "Del sta %d (%pM)", cur->sta_idx, cur->mac_addr); ++ if (cur->vif_idx != cur->vlan_idx) { ++ struct rwnx_vif *vlan_vif; ++ vlan_vif = rwnx_hw->vif_table[cur->vlan_idx]; ++ if (vlan_vif->up) { ++ if ((RWNX_VIF_TYPE(vlan_vif) == NL80211_IFTYPE_AP_VLAN) && ++ (vlan_vif->use_4addr)) { ++ vlan_vif->ap_vlan.sta_4a = NULL; ++ } else { ++ WARN(1, "Deleting sta belonging to VLAN other than AP_VLAN 4A"); ++ } ++ } ++ } ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { ++ cfg80211_del_sta(rwnx_vif->ndev, cur->mac_addr, GFP_KERNEL); ++ } ++ ++#ifdef AICWF_RX_REORDER ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv = rwnx_hw->sdiodev->rx_priv; ++#else ++ rx_priv = rwnx_hw->usbdev->rx_priv; ++#endif ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ BUG();//should be other function ++ } ++ else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)){ ++ macaddr = cur->mac_addr; ++ printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0],macaddr[1],macaddr[2], \ ++ macaddr[3],macaddr[4],macaddr[5]); ++ list_for_each_entry_safe(reord_info, reord_tmp, ++ &rx_priv->stas_reord_list, list) { ++ printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0],reord_info->mac_addr[1],reord_info->mac_addr[2], \ ++ reord_info->mac_addr[3],reord_info->mac_addr[4],reord_info->mac_addr[5]); ++ if (!memcmp(reord_info->mac_addr, macaddr, 6)) { ++ reord_deinit_sta(rx_priv, reord_info); ++ break; ++ } ++ } ++ } ++#endif ++ ++ rwnx_txq_sta_deinit(rwnx_hw, cur); ++ error = rwnx_send_me_sta_del(rwnx_hw, cur->sta_idx, false); ++ if ((error != 0) && (error != -EPIPE)) ++ return error; ++ ++#ifdef CONFIG_RWNX_BFMER ++ // Disable Beamformer if supported ++ rwnx_bfmer_report_del(rwnx_hw, cur); ++ rwnx_mu_group_sta_del(rwnx_hw, cur); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++#ifdef CONFIG_DEBUG_FS_AIC ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, cur); ++#endif ++ } ++ ++ if(mac) ++ break; ++ } while (1); ++ ++ rwnx_update_mesh_power_mode(rwnx_vif); ++ ++ if(!found && mac != NULL) ++ return -ENOENT; ++ else ++ return 0; ++} ++ ++ ++void apm_staloss_work_process(struct work_struct *work) ++{ ++ struct rwnx_hw *rwnx_hw = container_of(work, struct rwnx_hw, apmStalossWork); ++ struct rwnx_sta *cur, *tmp; ++ int error = 0; ++ ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *reord_tmp; ++ u8 *macaddr; ++ struct aicwf_rx_priv *rx_priv; ++#endif ++ struct rwnx_vif *rwnx_vif; ++ bool_l found = false; ++ const u8 *mac = rwnx_hw->sta_mac_addr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == rwnx_hw->apm_vif_idx) { ++ found = true; ++ break; ++ } ++ } ++ ++ printk("apm vif idx=%d, found=%d, mac addr=%pM\n", rwnx_hw->apm_vif_idx, found, mac); ++ if (!found || !rwnx_vif || (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_AP && RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_P2P_GO)) ++ { ++ return; ++ } ++ ++ found = false; ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { ++ if ((mac) && (!memcmp(cur->mac_addr, mac, ETH_ALEN))) { ++ found = true; ++ break; ++ } ++ } ++ if(found) { ++ cur->ps.active = false; ++ cur->valid = false; ++ list_del(&cur->list); ++ } ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if(found) { ++ netdev_info(rwnx_vif->ndev, "Del sta %d (%pM)", cur->sta_idx, cur->mac_addr); ++ if (cur->vif_idx != cur->vlan_idx) { ++ struct rwnx_vif *vlan_vif; ++ vlan_vif = rwnx_hw->vif_table[cur->vlan_idx]; ++ if (vlan_vif->up) { ++ if ((RWNX_VIF_TYPE(vlan_vif) == NL80211_IFTYPE_AP_VLAN) && ++ (vlan_vif->use_4addr)) { ++ vlan_vif->ap_vlan.sta_4a = NULL; ++ } else { ++ WARN(1, "Deleting sta belonging to VLAN other than AP_VLAN 4A"); ++ } ++ } ++ } ++ ++#ifdef AICWF_RX_REORDER ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv = rwnx_hw->sdiodev->rx_priv; ++#else ++ rx_priv = rwnx_hw->usbdev->rx_priv; ++#endif ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ BUG();//should be other function ++ } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { ++ macaddr = cur->mac_addr; ++ printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0], macaddr[1], macaddr[2], \ ++ macaddr[3], macaddr[4], macaddr[5]); ++ list_for_each_entry_safe(reord_info, reord_tmp, ++ &rx_priv->stas_reord_list, list) { ++ printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0], reord_info->mac_addr[1], reord_info->mac_addr[2], \ ++ reord_info->mac_addr[3], reord_info->mac_addr[4], reord_info->mac_addr[5]); ++ if (!memcmp(reord_info->mac_addr, macaddr, 6)) { ++ reord_deinit_sta(rx_priv, reord_info); ++ break; ++ } ++ } ++ } ++#endif ++ ++ rwnx_txq_sta_deinit(rwnx_hw, cur); ++ error = rwnx_send_me_sta_del(rwnx_hw, cur->sta_idx, false); ++ if ((error != 0) && (error != -EPIPE)) ++ return; ++ ++#ifdef CONFIG_RWNX_BFMER ++ // Disable Beamformer if supported ++ rwnx_bfmer_report_del(rwnx_hw, cur); ++ rwnx_mu_group_sta_del(rwnx_hw, cur); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++#ifdef CONFIG_DEBUG_FS_AIC ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, cur); ++#endif ++ }else { ++ printk("sta not found: %pM\n", mac); ++ return; ++ } ++ ++ rwnx_update_mesh_power_mode(rwnx_vif); ++} ++ ++ ++void apm_probe_sta_work_process(struct work_struct *work) ++{ ++ struct apm_probe_sta *probe_sta = container_of(work, struct apm_probe_sta, apmprobestaWork); ++ struct rwnx_vif *rwnx_vif = container_of(probe_sta, struct rwnx_vif, sta_probe); ++ bool found = false; ++ struct rwnx_sta *cur, *tmp; ++ ++ u8 *mac = rwnx_vif->sta_probe.sta_mac_addr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { ++ if (!memcmp(cur->mac_addr, mac, ETH_ALEN)) { ++ found = true; ++ break; ++ } ++ } ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ ++ printk("sta %pM found = %d\n", mac, found); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) ++ if(found) ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, 0, false, GFP_ATOMIC); ++ else ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 0, 0, false, GFP_ATOMIC); ++#else ++ if(found) ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, GFP_ATOMIC); ++ else ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 0, GFP_ATOMIC); ++ ++#endif ++ rwnx_vif->sta_probe.probe_id ++; ++} ++/** ++ * @change_station: Modify a given station. Note that flags changes are not much ++ * validated in cfg80211, in particular the auth/assoc/authorized flags ++ * might come to the driver in invalid combinations -- make sure to check ++ * them, also against the existing state! Drivers must call ++ * cfg80211_check_station_change() to validate the information. ++ */ ++static int rwnx_cfg80211_change_station(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac, ++#else ++ const u8 *mac, ++#endif ++ struct station_parameters *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_sta *sta; ++ ++ sta = rwnx_get_sta(rwnx_hw, mac); ++ if (!sta) { ++ /* Add the TDLS station */ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct me_sta_add_cfm me_sta_add_cfm; ++ int error = 0; ++ ++ /* Indicate we are in a STA addition process - This will allow handling ++ * potential PS mode change indications correctly ++ */ ++ rwnx_hw->adding_sta = true; ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_me_sta_add(rwnx_hw, params, mac, rwnx_vif->vif_index, &me_sta_add_cfm); ++ if (error) ++ return error; ++ ++ // Check the status ++ switch (me_sta_add_cfm.status) { ++ case CO_OK: ++ { ++ int tid; ++ sta = &rwnx_hw->sta_table[me_sta_add_cfm.sta_idx]; ++ sta->aid = params->aid; ++ sta->sta_idx = me_sta_add_cfm.sta_idx; ++ sta->ch_idx = rwnx_vif->ch_index; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->vlan_idx = sta->vif_idx; ++ sta->qos = (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) != 0; ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ sta->ht = params->link_sta_params.ht_capa ? 1 : 0; ++ sta->vht = params->link_sta_params.vht_capa ? 1 : 0; ++#else ++ sta->ht = params->ht_capa ? 1 : 0; ++ sta->vht = params->vht_capa ? 1 : 0; ++#endif ++ sta->acm = 0; ++ for (tid = 0; tid < NX_NB_TXQ_PER_STA; tid++) { ++ int uapsd_bit = rwnx_hwq2uapsd[rwnx_tid2hwq[tid]]; ++ if (params->uapsd_queues & uapsd_bit) ++ sta->uapsd_tids |= 1 << tid; ++ else ++ sta->uapsd_tids &= ~(1 << tid); ++ } ++ memcpy(sta->mac_addr, mac, ETH_ALEN); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, sta); ++#endif ++ /* Ensure that we won't process PS change or channel switch ind*/ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_txq_sta_init(rwnx_hw, sta, rwnx_txq_vif_get_status(rwnx_vif)); ++ if (rwnx_vif->tdls_status == TDLS_SETUP_RSP_TX) { ++ rwnx_vif->tdls_status = TDLS_LINK_ACTIVE; ++ sta->tdls.initiator = true; ++ sta->tdls.active = true; ++ } ++ /* Set TDLS channel switch capability */ ++ if ((params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) && ++ !rwnx_vif->tdls_chsw_prohibited) ++ sta->tdls.chsw_allowed = true; ++ rwnx_vif->sta.tdls_sta = sta; ++ sta->valid = true; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++#ifdef CONFIG_RWNX_BFMER ++ if (rwnx_hw->mod_params->bfmer) ++ rwnx_send_bfmer_enable(rwnx_hw, sta, params->vht_capa); ++ ++ rwnx_mu_group_sta_init(sta, NULL); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ #define PRINT_STA_FLAG(f) \ ++ (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "") ++ ++ netdev_info(dev, "Add %s TDLS sta %d (%pM) flags=%s%s%s%s%s%s%s", ++ sta->tdls.initiator ? "initiator" : "responder", ++ sta->sta_idx, mac, ++ PRINT_STA_FLAG(AUTHORIZED), ++ PRINT_STA_FLAG(SHORT_PREAMBLE), ++ PRINT_STA_FLAG(WME), ++ PRINT_STA_FLAG(MFP), ++ PRINT_STA_FLAG(AUTHENTICATED), ++ PRINT_STA_FLAG(TDLS_PEER), ++ PRINT_STA_FLAG(ASSOCIATED)); ++ #undef PRINT_STA_FLAG ++ ++ break; ++ } ++ default: ++ error = -EBUSY; ++ break; ++ } ++ ++ rwnx_hw->adding_sta = false; ++ } else { ++ return -EINVAL; ++ } ++ } ++ ++ if (params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) ++ rwnx_send_me_set_control_port_req(rwnx_hw, ++ (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) != 0, ++ sta->sta_idx); ++ ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MESH_POINT) { ++ if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) { ++ if (params->plink_state < NUM_NL80211_PLINK_STATES) { ++ rwnx_send_mesh_peer_update_ntf(rwnx_hw, vif, sta->sta_idx, params->plink_state); ++ } ++ } ++ ++ if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) { ++ sta->mesh_pm = params->local_pm; ++ rwnx_update_mesh_power_mode(vif); ++ } ++ } ++ ++ if (params->vlan) { ++ uint8_t vlan_idx; ++ ++ vif = netdev_priv(params->vlan); ++ vlan_idx = vif->vif_index; ++ ++ if (sta->vlan_idx != vlan_idx) { ++ struct rwnx_vif *old_vif; ++ old_vif = rwnx_hw->vif_table[sta->vlan_idx]; ++ rwnx_txq_sta_switch_vif(sta, old_vif, vif); ++ sta->vlan_idx = vlan_idx; ++ ++ if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP_VLAN) && ++ (vif->use_4addr)) { ++ WARN((vif->ap_vlan.sta_4a), ++ "4A AP_VLAN interface with more than one sta"); ++ vif->ap_vlan.sta_4a = sta; ++ } ++ ++ if ((RWNX_VIF_TYPE(old_vif) == NL80211_IFTYPE_AP_VLAN) && ++ (old_vif->use_4addr)) { ++ old_vif->ap_vlan.sta_4a = NULL; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * @start_ap: Start acting in AP mode defined by the parameters. ++ */ ++static int rwnx_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_ap_settings *settings) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct apm_start_cfm apm_start_cfm; ++ struct rwnx_ipc_elem_var elem; ++ struct rwnx_sta *sta; ++ int error = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ INIT_WORK(&rwnx_vif->sta_probe.apmprobestaWork, apm_probe_sta_work_process); ++ rwnx_vif->sta_probe.apmprobesta_wq = create_singlethread_workqueue("apmprobe_wq"); ++ if (!rwnx_vif->sta_probe.apmprobesta_wq) { ++ txrx_err("insufficient memory to create apmprobe_wq.\n"); ++ return -ENOBUFS; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ++ rwnx_hw->is_p2p_connected = 1; ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_apm_start_req(rwnx_hw, rwnx_vif, settings, &apm_start_cfm, &elem); ++ if (error) ++ goto end; ++ ++ // Check the status ++ switch (apm_start_cfm.status) { ++ case CO_OK: ++ { ++ u8 txq_status = 0; ++ rwnx_vif->ap.bcmc_index = apm_start_cfm.bcmc_idx; ++ rwnx_vif->ap.flags = 0; ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ rwnx_vif->ap.aic_index = 0; ++#endif ++ rwnx_vif->ap.csa = NULL; ++ sta = &rwnx_hw->sta_table[apm_start_cfm.bcmc_idx]; ++ sta->valid = true; ++ sta->aid = 0; ++ sta->sta_idx = apm_start_cfm.bcmc_idx; ++ sta->ch_idx = apm_start_cfm.ch_idx; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->qos = false; ++ sta->acm = 0; ++ sta->ps.active = false; ++ rwnx_mu_group_sta_init(sta, NULL); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_link(rwnx_vif, apm_start_cfm.ch_idx, ++ &settings->chandef); ++ if (rwnx_hw->cur_chanctx != apm_start_cfm.ch_idx) { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ rwnx_txq_vif_init(rwnx_hw, rwnx_vif, txq_status); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ error = 0; ++ /* If the AP channel is already the active, we probably skip radar ++ activation on MM_CHANNEL_SWITCH_IND (unless another vif use this ++ ctxt). In anycase retest if radar detection must be activated ++ */ ++ if (txq_status == 0) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ } ++ break; ++ } ++ case CO_BUSY: ++ error = -EINPROGRESS; ++ break; ++ case CO_OP_IN_PROGRESS: ++ error = -EALREADY; ++ break; ++ default: ++ error = -EIO; ++ break; ++ } ++ ++ if (error) { ++ netdev_info(dev, "Failed to start AP (%d)", error); ++ } else { ++ netdev_info(dev, "AP started: ch=%d, bcmc_idx=%d channel=%d bw=%d", ++ rwnx_vif->ch_index, rwnx_vif->ap.bcmc_index, ++ ((settings->chandef).chan)->center_freq, ++ ((settings->chandef).width)); ++ } ++ ++end: ++ //rwnx_ipc_elem_var_deallocs(rwnx_hw, &elem); ++ ++ return error; ++} ++ ++ ++/** ++ * @change_beacon: Change the beacon parameters for an access point mode ++ * interface. This should reject the call when AP mode wasn't started. ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)) ++static int rwnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_ap_update *params) ++#else ++static int rwnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_beacon_data *info) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_bcn *bcn = &vif->ap.bcn; ++ struct rwnx_ipc_elem_var elem; ++ u8 *buf; ++ int error = 0; ++ elem.dma_addr = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Build the beacon ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)) ++ buf = rwnx_build_bcn(bcn, ¶ms->beacon); ++#else ++ buf = rwnx_build_bcn(bcn, info); ++#endif ++ if (!buf) ++ return -ENOMEM; ++ ++ rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn->len); ++ ++ // Forward the information to the LMAC ++ error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, ++ bcn->len, bcn->head_len, bcn->tim_len, NULL); ++ ++ return error; ++} ++ ++/** ++ * * @stop_ap: Stop being an AP, including stopping beaconing. ++ */ ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION) ++static int rwnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, unsigned int link_id) ++#else ++static int rwnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_sta *sta; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ ++ /* delete any remaining STA*/ ++ while (!list_empty(&rwnx_vif->ap.sta_list)) { ++ rwnx_cfg80211_del_station_compat(wiphy, dev, NULL); ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ++ rwnx_hw->is_p2p_connected = 0; ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ rwnx_send_apm_stop_req(rwnx_hw, rwnx_vif); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_unlink(rwnx_vif); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ /* delete BC/MC STA */ ++ sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ rwnx_txq_vif_deinit(rwnx_hw, rwnx_vif); ++ rwnx_del_bcn(&rwnx_vif->ap.bcn); ++ rwnx_del_csa(rwnx_vif); ++ ++ flush_workqueue(rwnx_vif->sta_probe.apmprobesta_wq); ++ destroy_workqueue(rwnx_vif->sta_probe.apmprobesta_wq); ++ ++ netdev_info(dev, "AP Stopped"); ++ ++ return 0; ++} ++ ++/** ++ * @set_monitor_channel: Set the monitor mode channel for the device. If other ++ * interfaces are active this callback should reject the configuration. ++ * If no interfaces are active or the device is down, the channel should ++ * be stored for when a monitor interface becomes active. ++ * ++ * Also called internaly with chandef set to NULL simply to retrieve the channel ++ * configured at firmware level. ++ */ ++static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 13, 0) ++ struct net_device *, ++#endif ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif; ++ struct me_config_monitor_cfm cfm; ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (rwnx_hw->monitor_vif == RWNX_INVALID_VIF) ++ return -EINVAL; ++ ++ rwnx_vif = rwnx_hw->vif_table[rwnx_hw->monitor_vif]; ++ ++ // Do nothing if monitor interface is already configured with the requested channel ++ if (rwnx_chanctx_valid(rwnx_hw, rwnx_vif->ch_index)) { ++ struct rwnx_chanctx *ctxt; ++ ctxt = &rwnx_vif->rwnx_hw->chanctx_table[rwnx_vif->ch_index]; ++ if (chandef && cfg80211_chandef_identical(&ctxt->chan_def, chandef)) ++ return 0; ++ } ++ ++ // Always send command to firmware. It allows to retrieve channel context index ++ // and its configuration. ++ if (rwnx_send_config_monitor_req(rwnx_hw, chandef, &cfm)) ++ return -EIO; ++ ++ // Always re-set channel context info ++ rwnx_chanctx_unlink(rwnx_vif); ++ ++ ++ ++ // If there is also a STA interface not yet connected then monitor interface ++ // will only have a channel context after the connection of the STA interface. ++ if (cfm.chan_index != RWNX_CH_NOT_SET) { ++ struct cfg80211_chan_def mon_chandef; ++ ++ if (rwnx_hw->vif_started > 1) { ++ // In this case we just want to update the channel context index not ++ // the channel configuration ++ rwnx_chanctx_link(rwnx_vif, cfm.chan_index, NULL); ++ return -EBUSY; ++ } ++ ++ mon_chandef.chan = ieee80211_get_channel(wiphy, cfm.chan.prim20_freq); ++ mon_chandef.center_freq1 = cfm.chan.center1_freq; ++ mon_chandef.center_freq2 = cfm.chan.center2_freq; ++ mon_chandef.width = chnl2bw[cfm.chan.type]; ++ rwnx_chanctx_link(rwnx_vif, cfm.chan_index, &mon_chandef); ++ } ++ ++ return 0; ++} ++ ++int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef){ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 13, 0) ++ return rwnx_cfg80211_set_monitor_channel(wiphy, NULL, chandef); ++#else ++ return rwnx_cfg80211_set_monitor_channel(wiphy, chandef); ++#endif ++} ++ ++ ++/** ++ * @probe_client: probe an associated client, must return a cookie that it ++ * later passes to cfg80211_probe_status(). ++ */ ++int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, u64 *cookie) ++{ ++// struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_sta *sta = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if((RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP) && (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_P2P_GO) && ++ (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP_VLAN)) ++ return -EINVAL; ++ spin_lock_bh(&vif->rwnx_hw->cb_lock); ++ list_for_each_entry(sta, &vif->ap.sta_list, list){ ++ if (sta->valid && ether_addr_equal(sta->mac_addr, peer)) ++ break; ++ } ++ spin_unlock_bh(&vif->rwnx_hw->cb_lock); ++ ++ if (!sta) ++ return -ENOENT; ++ ++ ++ memcpy(vif->sta_probe.sta_mac_addr, peer, 6); ++ queue_work(vif->sta_probe.apmprobesta_wq, &vif->sta_probe.apmprobestaWork); ++ ++ *cookie = vif->sta_probe.probe_id; ++ ++ return 0; ++ ++} ++ ++/** ++ * @mgmt_frame_register: Notify driver that a management frame type was ++ * registered. Note that this callback may not sleep, and cannot run ++ * concurrently with itself. ++ */ ++void rwnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ u16 frame_type, bool reg) ++{ ++} ++ ++/** ++ * @set_wiphy_params: Notify that wiphy parameters have changed; ++ * @changed bitfield (see &enum wiphy_params_flags) describes which values ++ * have changed. The actual parameter values are available in ++ * struct wiphy. If returning an error, no value should be changed. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ++#else ++static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, int radio_idx, u32 changed) ++#endif ++{ ++ return 0; ++} ++ ++ ++/** ++ * @set_tx_power: set the transmit power according to the parameters, ++ * the power passed is in mBm, to get dBm use MBM_TO_DBM(). The ++ * wdev may be %NULL if power was set for the wiphy, and will ++ * always be %NULL unless the driver supports per-vif TX power ++ * (as advertised by the nl80211 feature flag.) ++ */ ++static int rwnx_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ enum nl80211_tx_power_setting type, int mbm) ++#else ++ int radio_idx, enum nl80211_tx_power_setting type, int mbm) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif; ++ s8 pwr; ++ int res = 0; ++ ++ if (type == NL80211_TX_POWER_AUTOMATIC) { ++ pwr = 0x7f; ++ } else { ++ pwr = MBM_TO_DBM(mbm); ++ } ++ ++ if (wdev) { ++ vif = container_of(wdev, struct rwnx_vif, wdev); ++ res = rwnx_send_set_power(rwnx_hw, vif->vif_index, pwr, NULL); ++ } else { ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ res = rwnx_send_set_power(rwnx_hw, vif->vif_index, pwr, NULL); ++ if (res) ++ break; ++ } ++ } ++ ++ return res; ++} ++ ++static int rwnx_cfg80211_get_tx_power(struct wiphy *wiphy, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) ++ struct wireless_dev *wdev, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 14, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ unsigned int link_id, ++#else ++ int radio_idx, unsigned int link_id, ++#endif ++#endif ++#endif ++ int *mbm) ++{ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) ++ struct wireless_dev *wdev = NULL; ++ #endif ++ //struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ //struct rwnx_vif *vif; ++ s8 pwr = 0; ++ int res = 0; ++ ++ *mbm = get_txpwr_max(pwr); ++ ++ return res; ++} ++ ++/** ++ * @set_power_mgmt: set the power save to one of those two modes: ++ * Power-save off ++ * Power-save on - Dynamic mode ++ */ ++static int rwnx_cfg80211_set_power_mgmt(struct wiphy *wiphy, ++ struct net_device *dev, ++ bool enabled, int timeout) ++{ ++#if 0 ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ u8 ps_mode; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ if (timeout >= 0) ++ netdev_info(dev, "Ignore timeout value %d", timeout); ++ ++ if (!(rwnx_hw->version_cfm.features & BIT(MM_FEAT_PS_BIT))) ++ enabled = false; ++ ++ if (enabled) { ++ /* Switch to Dynamic Power Save */ ++ ps_mode = MM_PS_MODE_ON_DYN; ++ } else { ++ /* Exit Power Save */ ++ ps_mode = MM_PS_MODE_OFF; ++ } ++ ++ return rwnx_send_me_set_ps_mode(rwnx_hw, ps_mode); ++#else ++ /* TODO ++ * Add handle in the feature! ++ */ ++ return 0; ++#endif ++} ++ ++static int rwnx_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev, ++ struct ieee80211_txq_params *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ u8 hw_queue, aifs, cwmin, cwmax; ++ u32 param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ hw_queue = rwnx_ac2hwq[0][params->ac]; ++ ++ aifs = params->aifs; ++ cwmin = fls(params->cwmin); ++ cwmax = fls(params->cwmax); ++ ++ /* Store queue information in general structure */ ++ param = (u32) (aifs << 0); ++ param |= (u32) (cwmin << 4); ++ param |= (u32) (cwmax << 8); ++ param |= (u32) (params->txop) << 12; ++ ++ /* Send the MM_SET_EDCA_REQ message to the FW */ ++ return rwnx_send_set_edca(rwnx_hw, hw_queue, param, false, rwnx_vif->vif_index); ++} ++ ++ ++/** ++ * @remain_on_channel: Request the driver to remain awake on the specified ++ * channel for the specified duration to complete an off-channel ++ * operation (e.g., public action frame exchange). When the driver is ++ * ready on the requested channel, it must indicate this with an event ++ * notification by calling cfg80211_ready_on_channel(). ++ */ ++static int ++rwnx_cfg80211_remain_on_channel_(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, ++ unsigned int duration, u64 *cookie, bool mgmt_roc_flag) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ //struct rwnx_vif *rwnx_vif = netdev_priv(wdev->netdev); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ struct rwnx_roc_elem *roc_elem; ++ struct mm_add_if_cfm add_if_cfm; ++ struct mm_remain_on_channel_cfm roc_cfm; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* For debug purpose (use ftrace kernel option) */ ++#ifdef CREATE_TRACE_POINTS ++ trace_roc(rwnx_vif->vif_index, chan->center_freq, duration); ++#endif ++ /* Check that no other RoC procedure has been launched */ ++ if (rwnx_hw->roc_elem) { ++ msleep(2); ++ if (rwnx_hw->roc_elem) { ++ printk("remain_on_channel fail\n"); ++ return -EBUSY; ++ } ++ } ++ ++ printk("remain:%d,%d,%d\n", rwnx_vif->vif_index, rwnx_vif->is_p2p_vif, rwnx_hw->is_p2p_alive); ++#ifdef CONFIG_USE_P2P0 ++ if (rwnx_vif->is_p2p_vif) { ++#else ++ if (rwnx_vif == rwnx_hw->p2p_dev_vif && !rwnx_vif->up) { ++#endif ++ if (!rwnx_hw->is_p2p_alive) { ++ error = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, //wdev->netdev->dev_addr, ++ RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); ++ if (error) ++ return -EIO; ++ ++ if (add_if_cfm.status != 0) { ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->is_p2p_alive = 1; ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ } else { ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ } ++ } ++ ++ /* Allocate a temporary RoC element */ ++ roc_elem = kmalloc(sizeof(struct rwnx_roc_elem), GFP_KERNEL); ++ ++ /* Verify that element has well been allocated */ ++ if (!roc_elem) { ++ return -ENOMEM; ++ } ++ ++ /* Initialize the RoC information element */ ++ roc_elem->wdev = wdev; ++ roc_elem->chan = chan; ++ roc_elem->duration = duration; ++ roc_elem->mgmt_roc = mgmt_roc_flag; ++ roc_elem->on_chan = false; ++ ++ /* Initialize the OFFCHAN TX queue to allow off-channel transmissions */ ++ rwnx_txq_offchan_init(rwnx_vif); ++ ++ /* Forward the information to the FMAC */ ++ rwnx_hw->roc_elem = roc_elem; ++ error = rwnx_send_roc(rwnx_hw, rwnx_vif, chan, duration, &roc_cfm); ++ ++ /* If no error, keep all the information for handling of end of procedure */ ++ if (error == 0) { ++ /* Set the cookie value */ ++ *cookie = (u64)(rwnx_hw->roc_cookie_cnt); ++ if (roc_cfm.status) { ++ // failed to roc ++ rwnx_hw->roc_elem = NULL; ++ kfree(roc_elem); ++ rwnx_txq_offchan_deinit(rwnx_vif); ++ return -EBUSY; ++ } ++ } else { ++ /* Free the allocated element */ ++ rwnx_hw->roc_elem = NULL; ++ kfree(roc_elem); ++ rwnx_txq_offchan_deinit(rwnx_vif); ++ } ++ ++ return error; ++} ++ ++ ++static int ++rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, ++ unsigned int duration, u64 *cookie) ++{ ++ return rwnx_cfg80211_remain_on_channel_(wiphy, wdev, chan, duration, cookie, false); ++} ++ ++/** ++ * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. ++ * This allows the operation to be terminated prior to timeout based on ++ * the duration value. ++ */ ++static int rwnx_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ u64 cookie) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++#ifdef CREATE_TRACE_POINTS ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);//netdev_priv(wdev->netdev); ++#endif ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* For debug purpose (use ftrace kernel option) */ ++#ifdef CREATE_TRACE_POINTS ++ trace_cancel_roc(rwnx_vif->vif_index); ++#endif ++ /* Check if a RoC procedure is pending */ ++ if (!rwnx_hw->roc_elem) { ++ return 0; ++ } ++ ++ /* Forward the information to the FMAC */ ++ return rwnx_send_cancel_roc(rwnx_hw); ++} ++ ++#define IS_2P4GHZ(n) (n >= 2412 && n <= 2484) ++#define IS_5GHZ(n) (n >= 4000 && n <= 5895) ++#define DEFAULT_NOISE_FLOOR_2GHZ (-89) ++#define DEFAULT_NOISE_FLOOR_5GHZ (-92) ++ ++/** ++ * @dump_survey: get site survey information. ++ */ ++static int rwnx_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *netdev, ++ int idx, struct survey_info *info) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct ieee80211_supported_band *sband; ++ struct rwnx_survey_info *rwnx_survey; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (idx >= ARRAY_SIZE(rwnx_hw->survey)) ++ return -ENOENT; ++ ++ rwnx_survey = &rwnx_hw->survey[idx]; ++ ++ // Check if provided index matches with a supported 2.4GHz channel ++ sband = wiphy->bands[NL80211_BAND_2GHZ]; ++ if (sband && idx >= sband->n_channels) { ++ idx -= sband->n_channels; ++ sband = NULL; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ if (!sband) { ++ // Check if provided index matches with a supported 5GHz channel ++ sband = wiphy->bands[NL80211_BAND_5GHZ]; ++ ++ if (!sband || idx >= sband->n_channels) ++ return -ENOENT; ++ } ++ } else { ++ if (!sband || idx >= sband->n_channels) ++ return -ENOENT; ++ } ++ ++ // Fill the survey ++ info->channel = &sband->channels[idx]; ++ info->filled = rwnx_survey->filled; ++ ++ if (rwnx_survey->filled != 0) { ++ SURVEY_TIME(info) = (u64)rwnx_survey->chan_time_ms; ++ SURVEY_TIME_BUSY(info) = (u64)rwnx_survey->chan_time_busy_ms; ++ //info->noise = rwnx_survey->noise_dbm; ++ info->noise = ((IS_2P4GHZ(info->channel->center_freq)) ? DEFAULT_NOISE_FLOOR_2GHZ : ++ (IS_5GHZ(info->channel->center_freq)) ? DEFAULT_NOISE_FLOOR_5GHZ : DEFAULT_NOISE_FLOOR_5GHZ); ++ ++ // Set the survey report as not used ++ if(info->noise == 0){ ++ rwnx_survey->filled = 0; ++ }else{ ++ rwnx_survey->filled |= SURVEY_INFO_NOISE_DBM; ++ } ++ ++ } ++ ++ return 0; ++} ++ ++/** ++ * @get_channel: Get the current operating channel for the virtual interface. ++ * For monitor interfaces, it should return %NULL unless there's a single ++ * current monitoring channel. ++ */ ++static int rwnx_cfg80211_get_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ unsigned int link_id, ++#endif ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ struct rwnx_chanctx *ctxt; ++ ++ if (!rwnx_vif->up) { ++ return -ENODATA; ++ } ++ ++ if (rwnx_vif->vif_index == rwnx_hw->monitor_vif) { ++ //retrieve channel from firmware ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 13, 0) ++ rwnx_cfg80211_set_monitor_channel(wiphy, NULL, NULL); ++#else ++ rwnx_cfg80211_set_monitor_channel(wiphy, NULL); ++#endif ++ } ++ ++ //Check if channel context is valid ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_vif->ch_index)) { ++ return -ENODATA; ++ } ++ ++ ctxt = &rwnx_hw->chanctx_table[rwnx_vif->ch_index]; ++ *chandef = ctxt->chan_def; ++ ++ return 0; ++} ++ ++/** ++ * @mgmt_tx: Transmit a management frame. ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct cfg80211_mgmt_tx_params *params, ++ u64 *cookie) ++#else ++static int rwnx_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, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ bool no_cck, ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) ++ bool dont_wait_for_ack, ++ #endif ++ u64 *cookie) ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);//netdev_priv(wdev->netdev); ++ struct rwnx_sta *rwnx_sta; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ struct ieee80211_channel *channel = params->chan; ++ const u8 *buf = params->buf; ++ //size_t len = params->len; ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ struct ieee80211_mgmt *mgmt = (void *)buf; ++ bool ap = false; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ bool offchan = false; ++ #endif ++ ++ /* Check if provided VIF is an AP or a STA one */ ++ switch (RWNX_VIF_TYPE(rwnx_vif)) { ++ case NL80211_IFTYPE_AP_VLAN: ++ rwnx_vif = rwnx_vif->ap_vlan.master; ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ case NL80211_IFTYPE_MESH_POINT: ++ ap = true; ++ break; ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ default: ++ break; ++ } ++ ++ /* Get STA on which management frame has to be sent */ ++ rwnx_sta = rwnx_retrieve_sta(rwnx_hw, rwnx_vif, mgmt->da, ++ mgmt->frame_control, ap); ++#ifdef CREATE_TRACE_POINTS ++ trace_mgmt_tx((channel) ? channel->center_freq : 0, ++ rwnx_vif->vif_index, (rwnx_sta) ? rwnx_sta->sta_idx : 0xFF, ++ mgmt); ++#endif ++ if (ap || rwnx_sta) ++ goto send_frame; ++ ++ /* Not an AP interface sending frame to unknown STA: ++ * This is allowed for external authetication */ ++ if (rwnx_vif->sta.external_auth && ieee80211_is_auth(mgmt->frame_control)) ++ goto send_frame; ++ ++ /* Otherwise ROC is needed */ ++ if (!channel) { ++ printk("mgmt_tx fail since channel\n"); ++ return -EINVAL; ++ } ++ ++ /* Check that a RoC is already pending */ ++ if (rwnx_hw->roc_elem) { ++ /* Get VIF used for current ROC */ ++ struct rwnx_vif *rwnx_roc_vif = container_of(rwnx_hw->roc_elem->wdev, struct rwnx_vif, wdev);//netdev_priv(rwnx_hw->roc_elem->wdev->netdev); ++ ++ /* Check if RoC channel is the same than the required one */ ++ if ((rwnx_hw->roc_elem->chan->center_freq != channel->center_freq) ++ || (rwnx_vif->vif_index != rwnx_roc_vif->vif_index)) { ++ printk("mgmt rx chan invalid: %d, %d", rwnx_hw->roc_elem->chan->center_freq, channel->center_freq); ++ return -EINVAL; ++ } ++ } else { ++ u64 cookie; ++ int error; ++ ++ printk("mgmt rx remain on chan\n"); ++ ++ /* Start a ROC procedure for 30ms */ ++ error = rwnx_cfg80211_remain_on_channel_(wiphy, wdev, channel, ++ 30, &cookie, true); ++ if (error) { ++ printk("mgmt rx chan err\n"); ++ return error; ++ } ++ /* Need to keep in mind that RoC has been launched internally in order to ++ * avoid to call the cfg80211 callback once expired */ ++ //rwnx_hw->roc_elem->mgmt_roc = true; ++ } ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ offchan = true; ++ #endif ++ ++send_frame: ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, params, offchan, cookie); ++ #else ++ return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, channel, offchan, wait, buf, len, no_cck, dont_wait_for_ack, cookie); ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++} ++ ++/** ++ * @start_radar_detection: Start radar detection in the driver. ++ */ ++static ++int rwnx_cfg80211_start_radar_detection(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_chan_def *chandef ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) ++ , u32 cac_time_ms ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)) ++ , int link_id ++ #endif ++ ) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct apm_start_cac_cfm cfm; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) ++ rwnx_radar_start_cac(&rwnx_hw->radar, cac_time_ms, rwnx_vif); ++ #endif ++ rwnx_send_apm_start_cac_req(rwnx_hw, rwnx_vif, chandef, &cfm); ++ ++ if (cfm.status == CO_OK) { ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_link(rwnx_vif, cfm.ch_idx, chandef); ++ if (rwnx_hw->cur_chanctx == rwnx_vif->ch_index) ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_REPORT, ++ RWNX_RADAR_RIU); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } else { ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++/** ++ * @update_ft_ies: Provide updated Fast BSS Transition information to the ++ * driver. If the SME is in the driver/firmware, this information can be ++ * used in building Authentication and Reassociation Request frames. ++ */ ++static ++int rwnx_cfg80211_update_ft_ies(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_update_ft_ies_params *ftie) ++{ ++ printk("%s\n", __func__); ++ return 0; ++} ++ ++/** ++ * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. ++ */ ++static ++int rwnx_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, ++ struct net_device *dev, ++ int32_t rssi_thold, uint32_t rssi_hyst) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ ++ return rwnx_send_cfg_rssi_req(rwnx_hw, rwnx_vif->vif_index, rssi_thold, rssi_hyst); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++/** ++ * ++ * @channel_switch: initiate channel-switch procedure (with CSA). Driver is ++ * responsible for veryfing if the switch is possible. Since this is ++ * inherently tricky driver may decide to disconnect an interface later ++ * with cfg80211_stop_iface(). This doesn't mean driver can accept ++ * everything. It should do it's best to verify requests and reject them ++ * as soon as possible. ++ */ ++int rwnx_cfg80211_channel_switch (struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_csa_settings *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_bcn *bcn, *bcn_after; ++ struct rwnx_csa *csa; ++ u16 csa_oft[BCN_MAX_CSA_CPT]; ++ u8 *buf; ++ int i, error = 0; ++ ++ ++ if (vif->ap.csa) ++ return -EBUSY; ++ ++ if (params->n_counter_offsets_beacon > BCN_MAX_CSA_CPT) ++ return -EINVAL; ++ ++ /* Build the new beacon with CSA IE */ ++ bcn = &vif->ap.bcn; ++ buf = rwnx_build_bcn(bcn, ¶ms->beacon_csa); ++ if (!buf) ++ return -ENOMEM; ++ ++ memset(csa_oft, 0, sizeof(csa_oft)); ++ for (i = 0; i < params->n_counter_offsets_beacon; i++) { ++ csa_oft[i] = params->counter_offsets_beacon[i] + bcn->head_len + ++ bcn->tim_len; ++ } ++ ++ /* If count is set to 0 (i.e anytime after this beacon) force it to 2 */ ++ if (params->count == 0) { ++ params->count = 2; ++ for (i = 0; i < params->n_counter_offsets_beacon; i++) { ++ buf[csa_oft[i]] = 2; ++ } ++ } ++ ++ error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn->len); ++ if (error) { ++ goto end; ++ } ++ ++ /* Build the beacon to use after CSA. It will only be sent to fw once ++ CSA is over, but do it before sending the beacon as it must be ready ++ when CSA is finished. */ ++ csa = kzalloc(sizeof(struct rwnx_csa), GFP_KERNEL); ++ if (!csa) { ++ error = -ENOMEM; ++ goto end; ++ } ++ ++ bcn_after = &csa->bcn; ++ buf = rwnx_build_bcn(bcn_after, ¶ms->beacon_after); ++ if (!buf) { ++ error = -ENOMEM; ++ rwnx_del_csa(vif); ++ goto end; ++ } ++ ++ vif->ap.csa = csa; ++ csa->vif = vif; ++ csa->chandef = params->chandef; ++ ++ /* Send new Beacon. FW will extract channel and count from the beacon */ ++ error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, ++ bcn->len, bcn->head_len, bcn->tim_len, csa_oft); ++ ++ if (error) { ++ rwnx_del_csa(vif); ++ goto end; ++ } else { ++ INIT_WORK(&csa->work, rwnx_csa_finish); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 9, 0)) ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false); ++#elif LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION4 ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false, 0); ++#elif LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2 ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count, params->block_tx); ++#else ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count); ++#endif ++ ++ } ++ ++end: ++ return error; ++} ++#endif ++ ++ ++/* ++ * @tdls_mgmt: prepare TDLS action frame packets and forward them to FW ++ */ ++static int ++rwnx_cfg80211_tdls_mgmt(struct wiphy *wiphy, ++ struct net_device *dev, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ const u8 *peer, ++#else ++ u8 *peer, ++#endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0)) ++ int link_id, ++#endif ++ u8 action_code, ++ u8 dialog_token, ++ u16 status_code, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) ++ u32 peer_capability, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) ++ bool initiator, ++#endif ++ const u8 *buf, ++ size_t len) ++ ++{ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++ u32 peer_capability = 0; ++ #endif ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ bool initiator = false; ++ #endif ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int ret = 0; ++ ++ /* make sure we support TDLS */ ++ if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return -ENOTSUPP; ++ ++ /* make sure we are in station mode (and connected) */ ++ if ((RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_STATION) || ++ (!rwnx_vif->up) || (!rwnx_vif->sta.ap)) ++ return -ENOTSUPP; ++ ++ /* only one TDLS link is supported */ ++ if ((action_code == WLAN_TDLS_SETUP_REQUEST) && ++ (rwnx_vif->sta.tdls_sta) && ++ (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE)) { ++ printk("%s: only one TDLS link is supported!\n", __func__); ++ return -ENOTSUPP; ++ } ++ ++ if ((action_code == WLAN_TDLS_DISCOVERY_REQUEST) && ++ (rwnx_hw->mod_params->ps_on)) { ++ printk("%s: discovery request is not supported when " ++ "power-save is enabled!\n", __func__); ++ return -ENOTSUPP; ++ } ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_RESPONSE: ++ /* only one TDLS link is supported */ ++ if ((status_code == 0) && ++ (rwnx_vif->sta.tdls_sta) && ++ (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE)) { ++ printk("%s: only one TDLS link is supported!\n", __func__); ++ status_code = WLAN_STATUS_REQUEST_DECLINED; ++ } ++ /* fall-through */ ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ ret = rwnx_tdls_send_mgmt_packet_data(rwnx_hw, rwnx_vif, peer, action_code, ++ dialog_token, status_code, peer_capability, initiator, buf, len, 0, NULL); ++ break; ++ ++ default: ++ printk("%s: Unknown TDLS mgmt/action frame %pM\n", ++ __func__, peer); ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ if (action_code == WLAN_TDLS_SETUP_REQUEST) { ++ rwnx_vif->tdls_status = TDLS_SETUP_REQ_TX; ++ } else if (action_code == WLAN_TDLS_SETUP_RESPONSE) { ++ rwnx_vif->tdls_status = TDLS_SETUP_RSP_TX; ++ } else if ((action_code == WLAN_TDLS_SETUP_CONFIRM) && (ret == CO_OK)) { ++ rwnx_vif->tdls_status = TDLS_LINK_ACTIVE; ++ /* Set TDLS active */ ++ rwnx_vif->sta.tdls_sta->tdls.active = true; ++ } ++ ++ return ret; ++} ++ ++/* ++ * @tdls_oper: execute TDLS operation ++ */ ++static int ++rwnx_cfg80211_tdls_oper(struct wiphy *wiphy, ++ struct net_device *dev, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ const u8 *peer, ++#else ++ u8 *peer, ++#endif ++ enum nl80211_tdls_operation oper) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int error; ++ ++ if (oper != NL80211_TDLS_DISABLE_LINK) ++ return 0; ++ ++ if (!rwnx_vif->sta.tdls_sta) { ++ printk("%s: TDLS station %pM does not exist\n", __func__, peer); ++ return -ENOLINK; ++ } ++ ++ if (memcmp(rwnx_vif->sta.tdls_sta->mac_addr, peer, ETH_ALEN) == 0) { ++ /* Disable Channel Switch */ ++ if (!rwnx_send_tdls_cancel_chan_switch_req(rwnx_hw, rwnx_vif, ++ rwnx_vif->sta.tdls_sta, ++ NULL)) ++ rwnx_vif->sta.tdls_sta->tdls.chsw_en = false; ++ ++ netdev_info(dev, "Del TDLS sta %d (%pM)", ++ rwnx_vif->sta.tdls_sta->sta_idx, ++ rwnx_vif->sta.tdls_sta->mac_addr); ++ /* Ensure that we won't process PS change ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->sta.tdls_sta->ps.active = false; ++ rwnx_vif->sta.tdls_sta->valid = false; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_vif->sta.tdls_sta); ++ error = rwnx_send_me_sta_del(rwnx_hw, rwnx_vif->sta.tdls_sta->sta_idx, true); ++ if ((error != 0) && (error != -EPIPE)) ++ return error; ++ ++#ifdef CONFIG_RWNX_BFMER ++ // Disable Beamformer if supported ++ rwnx_bfmer_report_del(rwnx_hw, rwnx_vif->sta.tdls_sta); ++ rwnx_mu_group_sta_del(rwnx_hw, rwnx_vif->sta.tdls_sta); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ /* Set TDLS not active */ ++ rwnx_vif->sta.tdls_sta->tdls.active = false; ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.tdls_sta); ++#endif ++ // Remove TDLS station ++ rwnx_vif->tdls_status = TDLS_LINK_IDLE; ++ rwnx_vif->sta.tdls_sta = NULL; ++ } ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++/* ++ * @tdls_channel_switch: enable TDLS channel switch ++ */ ++static int ++rwnx_cfg80211_tdls_channel_switch (struct wiphy *wiphy, ++ struct net_device *dev, ++ const u8 *addr, u8 oper_class, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_sta *rwnx_sta = rwnx_vif->sta.tdls_sta; ++ struct tdls_chan_switch_cfm cfm; ++ int error; ++ ++ if ((!rwnx_sta) || (memcmp(addr, rwnx_sta->mac_addr, ETH_ALEN))) { ++ printk("%s: TDLS station %pM doesn't exist\n", __func__, addr); ++ return -ENOLINK; ++ } ++ ++ if (!rwnx_sta->tdls.chsw_allowed) { ++ printk("%s: TDLS station %pM does not support TDLS channel switch\n", __func__, addr); ++ return -ENOTSUPP; ++ } ++ ++ error = rwnx_send_tdls_chan_switch_req(rwnx_hw, rwnx_vif, rwnx_sta, ++ rwnx_sta->tdls.initiator, ++ oper_class, chandef, &cfm); ++ if (error) ++ return error; ++ ++ if (!cfm.status) { ++ rwnx_sta->tdls.chsw_en = true; ++ return 0; ++ } else { ++ printk("%s: TDLS channel switch already enabled and only one is supported\n", __func__); ++ return -EALREADY; ++ } ++} ++ ++/* ++ * @tdls_cancel_channel_switch: disable TDLS channel switch ++ */ ++static void ++rwnx_cfg80211_tdls_cancel_channel_switch (struct wiphy *wiphy, ++ struct net_device *dev, ++ const u8 *addr) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_sta *rwnx_sta = rwnx_vif->sta.tdls_sta; ++ struct tdls_cancel_chan_switch_cfm cfm; ++ ++ if (!rwnx_sta) ++ return; ++ ++ if (!rwnx_send_tdls_cancel_chan_switch_req(rwnx_hw, rwnx_vif, ++ rwnx_sta, &cfm)) ++ rwnx_sta->tdls.chsw_en = false; ++} ++#endif /* version >= 3.19 */ ++ ++/** ++ * @change_bss: Modify parameters for a given BSS (mainly for AP mode). ++ */ ++int rwnx_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, ++ struct bss_parameters *params) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int res = -EOPNOTSUPP; ++ ++ if (((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP) || ++ (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO)) && ++ (params->ap_isolate > -1)) { ++ ++ if (params->ap_isolate) ++ rwnx_vif->ap.flags |= RWNX_AP_ISOLATE; ++ else ++ rwnx_vif->ap.flags &= ~RWNX_AP_ISOLATE; ++ ++ res = 0; ++ } ++ ++ return res; ++} ++ ++static int rwnx_fill_station_info(struct rwnx_sta *sta, struct rwnx_vif *vif, ++ struct station_info *sinfo) ++{ ++ struct rwnx_sta_stats *stats = &sta->stats; ++ struct rx_vector_1 *rx_vect1 = &stats->last_rx.rx_vect1; ++ union rwnx_rate_ctrl_info *rate_info; ++ struct mm_get_sta_info_cfm cfm; ++ ++ rwnx_send_get_sta_info_req(vif->rwnx_hw, sta->sta_idx, &cfm); ++ sinfo->tx_failed = cfm.txfailed; ++ rate_info = (union rwnx_rate_ctrl_info *)&cfm.rate_info; ++ ++ AICWFDBG(LOGDEBUG, "%s ModTx(%d):%d TxIndex:%d ModRx(%d):%d RxHTIndex:%d RxVHTIndex:%d RxHEIndex:%d RSSI:%d \r\n", __func__, ++ rate_info->bwTx, ++ rate_info->formatModTx, ++ rate_info->mcsIndexTx, ++ rx_vect1->ch_bw, ++ rx_vect1->format_mod, ++ rx_vect1->ht.mcs, ++ rx_vect1->vht.mcs, ++ rx_vect1->he.mcs, ++ (s8)cfm.rssi); ++ ++ ++ ++ switch (rate_info->formatModTx) { ++ case FORMATMOD_NON_HT: ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ sinfo->txrate.flags = 0; ++ sinfo->txrate.legacy = tx_legrates_lut_rate[rate_info->mcsIndexTx]; ++ sinfo->txrate.nss = 1; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx & 0x7; ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 3) & 0x7) + 1; ++ if (rate_info->giAndPreTypeTx) ++ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ break; ++ case FORMATMOD_VHT: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx & 0xF; ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 4) & 0x7) + 1; ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_HE_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx & 0xF; ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 4) & 0x7) + 1; ++ break; ++#else ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ sinfo->txrate.mcs = ((rate_info->mcsIndexTx & 0xF) > 9 ? 9 : (rate_info->mcsIndexTx & 0xF)); ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 4) & 0x7) + 1; ++ break; ++#endif ++ default: ++ return -EINVAL; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ switch (rate_info->bwTx) { ++ case PHY_CHNL_BW_20: ++ sinfo->txrate.bw = RATE_INFO_BW_20; ++ break; ++ case PHY_CHNL_BW_40: ++ sinfo->txrate.bw = RATE_INFO_BW_40; ++ break; ++ case PHY_CHNL_BW_80: ++ sinfo->txrate.bw = RATE_INFO_BW_80; ++ break; ++ case PHY_CHNL_BW_160: ++ sinfo->txrate.bw = RATE_INFO_BW_160; ++ break; ++ default: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ sinfo->txrate.bw = RATE_INFO_BW_HE_RU; ++#else ++ sinfo->txrate.bw = RATE_INFO_BW_20; ++#endif ++ break; ++ } ++#endif ++ ++ sinfo->filled |= (BIT(NL80211_STA_INFO_TX_BITRATE) | BIT(NL80211_STA_INFO_TX_FAILED)); ++ ++ sinfo->inactive_time = jiffies_to_msecs(jiffies - vif->rwnx_hw->stats.last_tx); ++ sinfo->rx_bytes = vif->net_stats.rx_bytes; ++ sinfo->tx_bytes = vif->net_stats.tx_bytes; ++ sinfo->tx_packets = vif->net_stats.tx_packets; ++ sinfo->rx_packets = vif->net_stats.rx_packets; ++ sinfo->signal = (s8)cfm.rssi; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ switch (rx_vect1->ch_bw) { ++ case PHY_CHNL_BW_20: ++ sinfo->rxrate.bw = RATE_INFO_BW_20; ++ break; ++ case PHY_CHNL_BW_40: ++ sinfo->rxrate.bw = RATE_INFO_BW_40; ++ break; ++ case PHY_CHNL_BW_80: ++ sinfo->rxrate.bw = RATE_INFO_BW_80; ++ break; ++ case PHY_CHNL_BW_160: ++ sinfo->rxrate.bw = RATE_INFO_BW_160; ++ break; ++ default: ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ sinfo->rxrate.bw = RATE_INFO_BW_HE_RU; ++ #else ++ sinfo->rxrate.bw = RATE_INFO_BW_20; ++ #endif ++ break; ++ } ++ #endif ++ ++ switch (rx_vect1->format_mod) { ++ case FORMATMOD_NON_HT: ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ sinfo->rxrate.flags = 0; ++ sinfo->rxrate.legacy = legrates_lut[rx_vect1->leg_rate].rate; ++ sinfo->rxrate.nss = 1; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS; ++ if (rx_vect1->ht.short_gi) ++ sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ sinfo->rxrate.mcs = rx_vect1->ht.mcs; ++ sinfo->rxrate.nss = rx_vect1->ht.num_extn_ss + 1; ++ break; ++ case FORMATMOD_VHT: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ if (rx_vect1->vht.short_gi) ++ sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ sinfo->rxrate.mcs = rx_vect1->vht.mcs; ++ sinfo->rxrate.nss = rx_vect1->vht.nss + 1; ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ case FORMATMOD_HE_MU: ++ sinfo->rxrate.he_ru_alloc = rx_vect1->he.ru_size; ++ __attribute__((__fallthrough__)); ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_HE_MCS; ++ sinfo->rxrate.mcs = rx_vect1->he.mcs; ++ sinfo->rxrate.he_gi = rx_vect1->he.gi_type; ++ sinfo->rxrate.he_dcm = rx_vect1->he.dcm; ++ sinfo->rxrate.nss = rx_vect1->he.nss + 1; ++ break; ++#else ++ //kernel not support he ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ if(rx_vect1->he.mcs > 9){ ++ sinfo->rxrate.mcs = 9; ++ }else{ ++ sinfo->rxrate.mcs = rx_vect1->he.mcs; ++ } ++ sinfo->rxrate.mcs = (rx_vect1->he.mcs > 9 ? 9 : rx_vect1->he.mcs); ++ sinfo->rxrate.nss = rx_vect1->he.nss + 1; ++ break; ++#endif ++ default: ++ return -EINVAL; ++ } ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ sinfo->filled |= (STATION_INFO_INACTIVE_TIME | ++ STATION_INFO_RX_BYTES64 | ++ STATION_INFO_TX_BYTES64 | ++ STATION_INFO_RX_PACKETS | ++ STATION_INFO_TX_PACKETS | ++ STATION_INFO_SIGNAL | ++ STATION_INFO_RX_BITRATE); ++#else ++ sinfo->filled |= (BIT(NL80211_STA_INFO_INACTIVE_TIME) | ++ BIT(NL80211_STA_INFO_RX_BYTES64) | ++ BIT(NL80211_STA_INFO_TX_BYTES64) | ++ BIT(NL80211_STA_INFO_RX_PACKETS) | ++ BIT(NL80211_STA_INFO_TX_PACKETS) | ++ BIT(NL80211_STA_INFO_SIGNAL) | ++ BIT(NL80211_STA_INFO_RX_BITRATE)); ++#endif ++ ++ return 0; ++} ++ ++ ++/** ++ * @get_station: get station information for the station identified by @mac ++ */ ++static int rwnx_cfg80211_get_station(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac, ++#else ++ const u8 *mac, ++#endif ++ struct station_info *sinfo) ++{ ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_sta *sta = NULL; ++ ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR) ++ return -EINVAL; ++ else if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_STATION) || ++ (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_CLIENT)) { ++ if (vif->sta.ap && ether_addr_equal(vif->sta.ap->mac_addr, mac)) ++ sta = vif->sta.ap; ++ } else { ++ struct rwnx_sta *sta_iter; ++ spin_lock_bh(&vif->rwnx_hw->cb_lock); ++ list_for_each_entry(sta_iter, &vif->ap.sta_list, list) { ++ if (sta_iter->valid && ether_addr_equal(sta_iter->mac_addr, mac)) { ++ sta = sta_iter; ++ break; ++ } ++ } ++ spin_unlock_bh(&vif->rwnx_hw->cb_lock); ++ } ++ ++ if (sta) ++ return rwnx_fill_station_info(sta, vif, sinfo); ++ ++ return -ENOENT; ++} ++ ++ ++/** ++ * @dump_station: dump station callback -- resume dump at index @idx ++ */ ++static int rwnx_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, ++ int idx, u8 *mac, struct station_info *sinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ //struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_sta *sta_iter, *sta = NULL; ++ //struct mesh_peer_info_cfm peer_info_cfm; ++ int i = 0; ++ ++#if 0 ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++#endif ++ ++ list_for_each_entry(sta_iter, &rwnx_vif->ap.sta_list, list) { ++ if (i < idx) { ++ i++; ++ continue; ++ } ++ ++ sta = sta_iter; ++ break; ++ } ++ ++ if (sta == NULL) ++ return -ENOENT; ++ ++ /* Copy peer MAC address */ ++ memcpy(mac, &sta->mac_addr, ETH_ALEN); ++ ++ ++#if 0 ++ /* Forward the information to the UMAC */ ++ if (rwnx_send_mesh_peer_info_req(rwnx_hw, rwnx_vif, sta->sta_idx, ++ &peer_info_cfm)) ++ return -ENOMEM; ++ ++ /* Copy peer MAC address */ ++ memcpy(mac, &sta->mac_addr, ETH_ALEN); ++ ++ /* Fill station information */ ++ sinfo->llid = peer_info_cfm.local_link_id; ++ sinfo->plid = peer_info_cfm.peer_link_id; ++ sinfo->plink_state = peer_info_cfm.link_state; ++ sinfo->local_pm = peer_info_cfm.local_ps_mode; ++ sinfo->peer_pm = peer_info_cfm.peer_ps_mode; ++ sinfo->nonpeer_pm = peer_info_cfm.non_peer_ps_mode; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ sinfo->filled = (STATION_INFO_LLID | ++ STATION_INFO_PLID | ++ STATION_INFO_PLINK_STATE | ++ STATION_INFO_LOCAL_PM | ++ STATION_INFO_PEER_PM | ++ STATION_INFO_NONPEER_PM); ++#else ++ sinfo->filled = (BIT(NL80211_STA_INFO_LLID) | ++ BIT(NL80211_STA_INFO_PLID) | ++ BIT(NL80211_STA_INFO_PLINK_STATE) | ++ BIT(NL80211_STA_INFO_LOCAL_PM) | ++ BIT(NL80211_STA_INFO_PEER_PM) | ++ BIT(NL80211_STA_INFO_NONPEER_PM)); ++#endif ++#endif ++ ++ if (sta){ ++ rwnx_fill_station_info(sta, rwnx_vif, sinfo); ++ } ++ ++ return 0; ++} ++ ++/** ++ * @add_mpath: add a fixed mesh path ++ */ ++static int rwnx_cfg80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *dst, ++ u8 *next_hop ++#else ++ const u8 *dst, ++ const u8 *next_hop ++#endif ++) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_path_update_cfm cfm; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return rwnx_send_mesh_path_update_req(rwnx_hw, rwnx_vif, dst, next_hop, &cfm); ++} ++ ++/** ++ * @del_mpath: delete a given mesh path ++ */ ++static int rwnx_cfg80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *dst ++#else ++ const u8 *dst ++#endif ++) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_path_update_cfm cfm; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return rwnx_send_mesh_path_update_req(rwnx_hw, rwnx_vif, dst, NULL, &cfm); ++} ++ ++/** ++ * @change_mpath: change a given mesh path ++ */ ++static int rwnx_cfg80211_change_mpath(struct wiphy *wiphy, struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *dst, ++ u8 *next_hop ++#else ++ const u8 *dst, ++ const u8 *next_hop ++#endif ++) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_path_update_cfm cfm; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return rwnx_send_mesh_path_update_req(rwnx_hw, rwnx_vif, dst, next_hop, &cfm); ++} ++ ++/** ++ * @get_mpath: get a mesh path for the given parameters ++ */ ++static int rwnx_cfg80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, ++ u8 *dst, u8 *next_hop, struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_path *mesh_path = NULL; ++ struct rwnx_mesh_path *cur; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.mpath_list, list) { ++ /* Compare the path target address and the provided destination address */ ++ if (memcmp(dst, &cur->tgt_mac_addr, ETH_ALEN)) { ++ continue; ++ } ++ ++ mesh_path = cur; ++ break; ++ } ++ ++ if (mesh_path == NULL) ++ return -ENOENT; ++ ++ /* Copy next HOP MAC address */ ++ if (mesh_path->p_nhop_sta) ++ memcpy(next_hop, &mesh_path->p_nhop_sta->mac_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++ ++/** ++ * @dump_mpath: dump mesh path callback -- resume dump at index @idx ++ */ ++static int rwnx_cfg80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, ++ int idx, u8 *dst, u8 *next_hop, ++ struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_path *mesh_path = NULL; ++ struct rwnx_mesh_path *cur; ++ int i = 0; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.mpath_list, list) { ++ if (i < idx) { ++ i++; ++ continue; ++ } ++ ++ mesh_path = cur; ++ break; ++ } ++ ++ if (mesh_path == NULL) ++ return -ENOENT; ++ ++ /* Copy target and next hop MAC address */ ++ memcpy(dst, &mesh_path->tgt_mac_addr, ETH_ALEN); ++ if (mesh_path->p_nhop_sta) ++ memcpy(next_hop, &mesh_path->p_nhop_sta->mac_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++/** ++ * @get_mpp: get a mesh proxy path for the given parameters ++ */ ++static int rwnx_cfg80211_get_mpp(struct wiphy *wiphy, struct net_device *dev, ++ u8 *dst, u8 *mpp, struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_proxy *mesh_proxy = NULL; ++ struct rwnx_mesh_proxy *cur; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.proxy_list, list) { ++ if (cur->local) { ++ continue; ++ } ++ ++ /* Compare the path target address and the provided destination address */ ++ if (memcmp(dst, &cur->ext_sta_addr, ETH_ALEN)) { ++ continue; ++ } ++ ++ mesh_proxy = cur; ++ break; ++ } ++ ++ if (mesh_proxy == NULL) ++ return -ENOENT; ++ ++ memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++ ++/** ++ * @dump_mpp: dump mesh proxy path callback -- resume dump at index @idx ++ */ ++static int rwnx_cfg80211_dump_mpp(struct wiphy *wiphy, struct net_device *dev, ++ int idx, u8 *dst, u8 *mpp, struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_proxy *mesh_proxy = NULL; ++ struct rwnx_mesh_proxy *cur; ++ int i = 0; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.proxy_list, list) { ++ if (cur->local) { ++ continue; ++ } ++ ++ if (i < idx) { ++ i++; ++ continue; ++ } ++ ++ mesh_proxy = cur; ++ break; ++ } ++ ++ if (mesh_proxy == NULL) ++ return -ENOENT; ++ ++ /* Copy target MAC address */ ++ memcpy(dst, &mesh_proxy->ext_sta_addr, ETH_ALEN); ++ memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++#endif /* version >= 3.19 */ ++ ++/** ++ * @get_mesh_config: Get the current mesh configuration ++ */ ++static int rwnx_cfg80211_get_mesh_config(struct wiphy *wiphy, struct net_device *dev, ++ struct mesh_config *conf) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return 0; ++} ++ ++/** ++ * @update_mesh_config: Update mesh parameters on a running mesh. ++ */ ++static int rwnx_cfg80211_update_mesh_config(struct wiphy *wiphy, struct net_device *dev, ++ u32 mask, const struct mesh_config *nconf) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_update_cfm cfm; ++ int status; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ if (mask & CO_BIT(NL80211_MESHCONF_POWER_MODE - 1)) { ++ rwnx_vif->ap.next_mesh_pm = nconf->power_mode; ++ ++ if (!list_empty(&rwnx_vif->ap.sta_list)) { ++ // If there are mesh links we don't want to update the power mode ++ // It will be updated with rwnx_update_mesh_power_mode() when the ++ // ps mode of a link is updated or when a new link is added/removed ++ mask &= ~BIT(NL80211_MESHCONF_POWER_MODE - 1); ++ ++ if (!mask) ++ return 0; ++ } ++ } ++ ++ status = rwnx_send_mesh_update_req(rwnx_hw, rwnx_vif, mask, nconf, &cfm); ++ ++ if (!status && (cfm.status != 0)) ++ status = -EINVAL; ++ ++ return status; ++} ++ ++/** ++ * @join_mesh: join the mesh network with the specified parameters ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, ++ const struct mesh_config *conf, const struct mesh_setup *setup) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct mesh_start_cfm mesh_start_cfm; ++ int error = 0; ++ u8 txq_status = 0; ++ /* STA for BC/MC traffic */ ++ struct rwnx_sta *sta; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ /* Forward the information to the UMAC */ ++ error = rwnx_send_mesh_start_req(rwnx_hw, rwnx_vif, conf, setup, &mesh_start_cfm); ++ if (error) { ++ return error; ++ } ++ ++ /* Check the status */ ++ switch (mesh_start_cfm.status) { ++ case CO_OK: ++ rwnx_vif->ap.bcmc_index = mesh_start_cfm.bcmc_idx; ++ rwnx_vif->ap.flags = 0; ++ rwnx_vif->use_4addr = true; ++ rwnx_vif->user_mpm = setup->user_mpm; ++ ++ sta = &rwnx_hw->sta_table[mesh_start_cfm.bcmc_idx]; ++ sta->valid = true; ++ sta->aid = 0; ++ sta->sta_idx = mesh_start_cfm.bcmc_idx; ++ sta->ch_idx = mesh_start_cfm.ch_idx; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->qos = true; ++ sta->acm = 0; ++ sta->ps.active = false; ++ rwnx_mu_group_sta_init(sta, NULL); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_link(rwnx_vif, mesh_start_cfm.ch_idx, ++ (struct cfg80211_chan_def *)(&setup->chandef)); ++ if (rwnx_hw->cur_chanctx != mesh_start_cfm.ch_idx) { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ rwnx_txq_vif_init(rwnx_hw, rwnx_vif, txq_status); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ ++ /* If the AP channel is already the active, we probably skip radar ++ activation on MM_CHANNEL_SWITCH_IND (unless another vif use this ++ ctxt). In anycase retest if radar detection must be activated ++ */ ++ if (rwnx_hw->cur_chanctx == mesh_start_cfm.ch_idx) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ } ++ break; ++ ++ case CO_BUSY: ++ error = -EINPROGRESS; ++ break; ++ ++ default: ++ error = -EIO; ++ break; ++ } ++ ++ /* Print information about the operation */ ++ if (error) { ++ netdev_info(dev, "Failed to start MP (%d)", error); ++ } else { ++ netdev_info(dev, "MP started: ch=%d, bcmc_idx=%d", ++ rwnx_vif->ch_index, rwnx_vif->ap.bcmc_index); ++ } ++ ++ return error; ++} ++ ++/** ++ * @leave_mesh: leave the current mesh network ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct mesh_stop_cfm mesh_stop_cfm; ++ int error = 0; ++ ++ error = rwnx_send_mesh_stop_req(rwnx_hw, rwnx_vif, &mesh_stop_cfm); ++ ++ if (error == 0) { ++ /* Check the status */ ++ switch (mesh_stop_cfm.status) { ++ case CO_OK: ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_unlink(rwnx_vif); ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ /* delete BC/MC STA */ ++ rwnx_txq_vif_deinit(rwnx_hw, rwnx_vif); ++ rwnx_del_bcn(&rwnx_vif->ap.bcn); ++ ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ ++ break; ++ ++ default: ++ error = -EIO; ++ break; ++ } ++ } ++ ++ if (error) { ++ netdev_info(dev, "Failed to stop MP"); ++ } else { ++ netdev_info(dev, "MP Stopped"); ++ } ++ ++ return 0; ++} ++ ++static struct cfg80211_ops rwnx_cfg80211_ops = { ++ .add_virtual_intf = rwnx_cfg80211_add_iface, ++ .del_virtual_intf = rwnx_cfg80211_del_iface, ++ .change_virtual_intf = rwnx_cfg80211_change_iface, ++ .start_p2p_device = rwnx_cfgp2p_start_p2p_device, ++ .stop_p2p_device = rwnx_cfgp2p_stop_p2p_device, ++ .scan = rwnx_cfg80211_scan, ++ .connect = rwnx_cfg80211_connect, ++ .disconnect = rwnx_cfg80211_disconnect, ++ .add_key = rwnx_cfg80211_add_key, ++ .get_key = rwnx_cfg80211_get_key, ++ .del_key = rwnx_cfg80211_del_key, ++ .set_default_key = rwnx_cfg80211_set_default_key, ++ .set_default_mgmt_key = rwnx_cfg80211_set_default_mgmt_key, ++ .add_station = rwnx_cfg80211_add_station, ++ .del_station = rwnx_cfg80211_del_station_compat, ++ .change_station = rwnx_cfg80211_change_station, ++ .mgmt_tx = rwnx_cfg80211_mgmt_tx, ++ .start_ap = rwnx_cfg80211_start_ap, ++ .change_beacon = rwnx_cfg80211_change_beacon, ++ .stop_ap = rwnx_cfg80211_stop_ap, ++ .set_monitor_channel = rwnx_cfg80211_set_monitor_channel, ++ .probe_client = rwnx_cfg80211_probe_client, ++// .mgmt_frame_register = rwnx_cfg80211_mgmt_frame_register, ++ .set_wiphy_params = rwnx_cfg80211_set_wiphy_params, ++ .set_txq_params = rwnx_cfg80211_set_txq_params, ++ .set_tx_power = rwnx_cfg80211_set_tx_power, ++ .get_tx_power = rwnx_cfg80211_get_tx_power, ++ .set_power_mgmt = rwnx_cfg80211_set_power_mgmt, ++ .get_station = rwnx_cfg80211_get_station, ++ .remain_on_channel = rwnx_cfg80211_remain_on_channel, ++ .cancel_remain_on_channel = rwnx_cfg80211_cancel_remain_on_channel, ++ .dump_survey = rwnx_cfg80211_dump_survey, ++ .get_channel = rwnx_cfg80211_get_channel, ++ .start_radar_detection = rwnx_cfg80211_start_radar_detection, ++ .update_ft_ies = rwnx_cfg80211_update_ft_ies, ++ .set_cqm_rssi_config = rwnx_cfg80211_set_cqm_rssi_config, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ .channel_switch = rwnx_cfg80211_channel_switch, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ .tdls_channel_switch = rwnx_cfg80211_tdls_channel_switch, ++ .tdls_cancel_channel_switch = rwnx_cfg80211_tdls_cancel_channel_switch, ++#endif ++ .tdls_mgmt = rwnx_cfg80211_tdls_mgmt, ++ .tdls_oper = rwnx_cfg80211_tdls_oper, ++ .change_bss = rwnx_cfg80211_change_bss, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ .external_auth = rwnx_cfg80211_external_auth, ++#endif ++#ifdef CONFIG_SCHED_SCAN ++ .sched_scan_start = rwnx_cfg80211_sched_scan_start, ++ .sched_scan_stop = rwnx_cfg80211_sched_scan_stop, ++#endif ++}; ++ ++ ++/********************************************************************* ++ * Init/Exit functions ++ *********************************************************************/ ++static void rwnx_wdev_unregister(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_vif *rwnx_vif, *tmp; ++ ++ rtnl_lock(); ++ list_for_each_entry_safe(rwnx_vif, tmp, &rwnx_hw->vifs, list) { ++ rwnx_cfg80211_del_iface(rwnx_hw->wiphy, &rwnx_vif->wdev); ++ } ++ rtnl_unlock(); ++} ++ ++static void rwnx_set_vers(struct rwnx_hw *rwnx_hw) ++{ ++ u32 vers = rwnx_hw->version_cfm.version_lmac; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ snprintf(rwnx_hw->wiphy->fw_version, ++ sizeof(rwnx_hw->wiphy->fw_version), "%d.%d.%d.%d", ++ (vers & (0xff << 24)) >> 24, (vers & (0xff << 16)) >> 16, ++ (vers & (0xff << 8)) >> 8, (vers & (0xff << 0)) >> 0); ++} ++ ++static void rwnx_reg_notifier(struct wiphy *wiphy, ++ struct regulatory_request *request) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ // For now trust all initiator ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ if(request->dfs_region != 0) ++ rwnx_radar_set_domain(&rwnx_hw->radar, request->dfs_region); ++#else ++ rwnx_radar_set_domain(&rwnx_hw->radar, request->dfs_region); ++#endif ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC|| ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) && testmode == 0)){ ++ rwnx_send_me_chan_config_req(rwnx_hw, &request->alpha2[0]); ++ } ++} ++ ++static void rwnx_enable_mesh(struct rwnx_hw *rwnx_hw) ++{ ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ ++ if (!rwnx_mod_params.mesh) ++ return; ++ ++ rwnx_cfg80211_ops.get_station = rwnx_cfg80211_get_station; ++ rwnx_cfg80211_ops.dump_station = rwnx_cfg80211_dump_station; ++ rwnx_cfg80211_ops.add_mpath = rwnx_cfg80211_add_mpath; ++ rwnx_cfg80211_ops.del_mpath = rwnx_cfg80211_del_mpath; ++ rwnx_cfg80211_ops.change_mpath = rwnx_cfg80211_change_mpath; ++ rwnx_cfg80211_ops.get_mpath = rwnx_cfg80211_get_mpath; ++ rwnx_cfg80211_ops.dump_mpath = rwnx_cfg80211_dump_mpath; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ rwnx_cfg80211_ops.get_mpp = rwnx_cfg80211_get_mpp; ++ rwnx_cfg80211_ops.dump_mpp = rwnx_cfg80211_dump_mpp; ++#endif ++ rwnx_cfg80211_ops.get_mesh_config = rwnx_cfg80211_get_mesh_config; ++ rwnx_cfg80211_ops.update_mesh_config = rwnx_cfg80211_update_mesh_config; ++ rwnx_cfg80211_ops.join_mesh = rwnx_cfg80211_join_mesh; ++ rwnx_cfg80211_ops.leave_mesh = rwnx_cfg80211_leave_mesh; ++ ++ wiphy->flags |= (WIPHY_FLAG_MESH_AUTH | WIPHY_FLAG_IBSS_RSN); ++ wiphy->features |= NL80211_FEATURE_USERSPACE_MPM; ++ wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT); ++ ++ rwnx_limits[0].types |= BIT(NL80211_IFTYPE_MESH_POINT); ++ rwnx_limits_dfs[0].types |= BIT(NL80211_IFTYPE_MESH_POINT); ++} ++ ++extern int rwnx_init_aic(struct rwnx_hw *rwnx_hw); ++ ++#if IS_ENABLED(CONFIG_SUNXI_ADDR_MGT) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++extern int get_custom_mac_address(int fmt, char *name, char *addr); ++#else ++extern int get_wifi_custom_mac_address(char *addr_str); ++#endif ++#endif ++#if IS_ENABLED(CONFIG_PM) ++static const struct wiphy_wowlan_support aic_wowlan_support = { ++ .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT, ++}; ++#endif ++/** ++ * ++ */ ++extern int aicwf_vendor_init(struct wiphy *wiphy); ++extern txpwr_idx_conf_t nvram_txpwr_idx; ++ ++ ++int rwnx_ic_system_init(struct rwnx_hw *rwnx_hw){ ++ u32 mem_addr; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ ++ mem_addr = 0x40500000; ++ ++// if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++// rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ if (rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &rd_mem_addr_cfm)){ ++ return -1; ++ } ++ ++ chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16); ++ ++ if (rwnx_send_dbg_mem_read_req(rwnx_hw, 0x00000020, &rd_mem_addr_cfm)) { ++ AICWFDBG(LOGERROR, "[0x00000020] rd fail\n"); ++ return -1; ++ } ++ chip_sub_id = (u8)(rd_mem_addr_cfm.memdata); ++ ++ AICWFDBG(LOGINFO, "FDRV chip_id=%x, chip_sub_id=%x!!\n", chip_id, chip_sub_id); ++ ++#ifdef CONFIG_OOB ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ u32 memdata_temp = 0x00000006; ++ int ret; ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, 0x40504084, 4, &memdata_temp); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x40504084] write fail: %d\n", ret); ++ return -1; ++ } ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40504084, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x40504084] rd fail\n"); ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "rd [0x40504084] = %x\n", rd_mem_addr_cfm.memdata); ++ } ++#endif ++ ++ if (rwnx_platform_on(rwnx_hw, NULL)) ++ return -1; ++#if defined(CONFIG_START_FROM_BOOTROM) ++ //if (start_from_bootrom(rwnx_hw)) ++ // return -1; ++#endif ++// } ++ return 0; ++} ++ ++int rwnx_ic_rf_init(struct rwnx_hw *rwnx_hw){ ++ struct mm_set_rf_calib_cfm cfm; ++ int ret = 0; ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ if ((ret = rwnx_send_txpwr_idx_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if (testmode == 0) { ++ if ((ret = rwnx_send_rf_calib_req(rwnx_hw, &cfm))) ++ return -1; ++ } ++ ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ ++ if ((ret = aicwf_set_rf_config_8800dc(rwnx_hw, &cfm))) ++ return -1; ++ ++ ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if ((ret = aicwf_set_rf_config_8800d80(rwnx_hw, &cfm))) ++ return -1; ++ } ++ return 0; ++} ++ ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#ifdef CONFIG_USE_CUSTOMER_MAC ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++extern int get_custom_mac_address(int fmt, char *name, char *addr); ++#else ++extern int get_wifi_custom_mac_address(char *addr_str); ++#endif ++#endif//CONFIG_USE_CUSTOMER_MAC ++#endif//CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#include ++#endif ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#include ++#endif ++ ++#ifdef CONFIG_USE_CUSTOMER_MAC ++int rwnx_get_custom_mac_addr(u8_l *mac_addr_efuse){ ++ int ret = 0; ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ ret = get_custom_mac_address(1, "wifi", mac_addr_efuse); ++#else ++ ret = get_wifi_custom_mac_address(addr_str); ++ if (ret >= 0) { ++ sscanf(addr_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &mac_addr_efuse[0], &mac_addr_efuse[1], &mac_addr_efuse[2], ++ &mac_addr_efuse[3], &mac_addr_efuse[4], &mac_addr_efuse[5]); ++ } ++#endif ++ ++#endif//CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ ret = rockchip_wifi_mac_addr(mac_addr_efuse); ++#endif//CONFIG_PLATFORM_ROCKCHIP ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ ret = rockchip_wifi_mac_addr(mac_addr_efuse); ++#endif//CONFIG_PLATFORM_ROCKCHIP ++ ++ if(ret == 0){ ++ AICWFDBG(LOGINFO, "%s %02x:%02x:%02x:%02x:%02x:%02x", __func__, ++ mac_addr_efuse[0], mac_addr_efuse[1], mac_addr_efuse[2], ++ mac_addr_efuse[3], mac_addr_efuse[4], mac_addr_efuse[5]); ++ } ++ ++ return ret; ++} ++#endif ++ ++#ifdef CONFIG_FOR_IPCAM ++void aic_ipc_setting(struct rwnx_vif *rwnx_vif){ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ uint32_t hw_edca = 1; ++ uint32_t hw_cca = 3; ++ int32_t param[14]; ++ int32_t cca[5]= {0x10, 0, 0, 0, 0}; ++ ++ param[0] = 0xFA522; param[1] = 0xFA522; param[2] = 0xFA522; param[3] = 0xFA522; ++ param[4] = rwnx_vif->vif_index; ++ param[5] = 0x1e; param[6] = 0; param[7] = 0; param[8] =0;param[9] = 0x2;param[10] = 0x2;param[11] = 0x7;param[12] = 0;param[13] = 1; ++ rwnx_send_vendor_hwconfig_req(rwnx_hw, hw_edca, param, NULL); ++ rwnx_send_vendor_hwconfig_req(rwnx_hw, hw_cca, cca, NULL); ++} ++#endif ++ ++extern void *aicwf_prealloc_txq_alloc(size_t size); ++#ifdef CONFIG_POWER_LIMIT ++extern char default_ccode[]; ++#endif ++int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data) ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct rwnx_conf_file init_conf; ++ int ret = 0; ++ struct wiphy *wiphy; ++ struct rwnx_vif *vif; ++ int i; ++ u8 dflt_mac[ETH_ALEN] = { 0x88, 0x00, 0x33, 0x77, 0x10, 0x99}; ++ u8 addr_str[20]; ++ //struct mm_set_rf_calib_cfm cfm; ++ struct mm_get_fw_version_cfm fw_version; ++ u8_l mac_addr_efuse[ETH_ALEN]; ++ struct aicbsp_feature_t feature; ++ struct mm_set_stack_start_cfm set_start_cfm; ++#ifdef CONFIG_TEMP_COMP ++ struct mm_set_vendor_swconfig_cfm swconfig_cfm; ++#endif ++ char fw_path[200]; ++ (void)addr_str; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ memset(fw_path, 0, 200); ++ aicbsp_get_feature(&feature, fw_path); ++ ++ get_random_bytes(&dflt_mac[4], 2); ++#ifdef CONFIG_POWER_LIMIT ++ memcpy(country_code, default_ccode, 4); ++#endif ++ ++ /* create a new wiphy for use with cfg80211 */ ++ AICWFDBG(LOGINFO, "%s sizeof(struct rwnx_hw):%d \r\n", __func__, (int)sizeof(struct rwnx_hw)); ++ wiphy = wiphy_new(&rwnx_cfg80211_ops, sizeof(struct rwnx_hw)); ++ ++ if (!wiphy) { ++ dev_err(rwnx_platform_get_dev(rwnx_plat), "Failed to create new wiphy\n"); ++ ret = -ENOMEM; ++ goto err_out; ++ } ++ ++ rwnx_hw = wiphy_priv(wiphy); ++ rwnx_hw->wiphy = wiphy; ++ rwnx_hw->plat = rwnx_plat; ++ rwnx_hw->dev = rwnx_platform_get_dev(rwnx_plat); ++#ifdef AICWF_SDIO_SUPPORT ++ rwnx_hw->sdiodev = rwnx_plat->sdiodev; ++ rwnx_plat->sdiodev->rwnx_hw = rwnx_hw; ++ rwnx_hw->cmd_mgr = &rwnx_plat->sdiodev->cmd_mgr; ++#else ++ rwnx_hw->usbdev = rwnx_plat->usbdev; ++ rwnx_plat->usbdev->rwnx_hw = rwnx_hw; ++ rwnx_hw->cmd_mgr = &rwnx_plat->usbdev->cmd_mgr; ++#endif ++ rwnx_hw->mod_params = &rwnx_mod_params; ++ rwnx_hw->tcp_pacing_shift = 7; ++ ++#ifdef CONFIG_SCHED_SCAN ++ rwnx_hw->is_sched_scan = false; ++#endif//CONFIG_SCHED_SCAN ++ ++ aicwf_wakeup_lock_init(rwnx_hw); ++ rwnx_init_aic(rwnx_hw); ++ /* set device pointer for wiphy */ ++ set_wiphy_dev(wiphy, rwnx_hw->dev); ++ ++ /* Create cache to allocate sw_txhdr */ ++ rwnx_hw->sw_txhdr_cache = KMEM_CACHE(rwnx_sw_txhdr, 0); ++ if (!rwnx_hw->sw_txhdr_cache) { ++ wiphy_err(wiphy, "Cannot allocate cache for sw TX header\n"); ++ ret = -ENOMEM; ++ goto err_cache; ++ } ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ tcp_ack_init(rwnx_hw); ++#endif ++ ++#if 0 ++ ret = rwnx_parse_configfile(rwnx_hw, RWNX_CONFIG_FW_NAME, &init_conf); ++ if (ret) { ++ wiphy_err(wiphy, "rwnx_parse_configfile failed\n"); ++ goto err_config; ++ } ++#else ++ memcpy(init_conf.mac_addr, dflt_mac, ETH_ALEN); ++#endif ++ ++ rwnx_hw->vif_started = 0; ++ rwnx_hw->monitor_vif = RWNX_INVALID_VIF; ++ rwnx_hw->adding_sta = false; ++ ++ rwnx_hw->scan_ie.addr = NULL; ++ ++ for (i = 0; i < NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; i++) ++ rwnx_hw->avail_idx_map |= BIT(i); ++ ++ rwnx_hwq_init(rwnx_hw); ++ ++#ifdef CONFIG_PREALLOC_TXQ ++ rwnx_hw->txq = (struct rwnx_txq*)aicwf_prealloc_txq_alloc(sizeof(struct rwnx_txq)*NX_NB_TXQ); ++#endif ++ ++ for (i = 0; i < NX_NB_TXQ; i++) { ++ rwnx_hw->txq[i].idx = TXQ_INACTIVE; ++ } ++ ++ rwnx_mu_group_init(rwnx_hw); ++ ++ /* Initialize RoC element pointer to NULL, indicate that RoC can be started */ ++ rwnx_hw->roc_elem = NULL; ++ /* Cookie can not be 0 */ ++ rwnx_hw->roc_cookie_cnt = 1; ++ ++ INIT_LIST_HEAD(&rwnx_hw->vifs); ++ INIT_LIST_HEAD(&rwnx_hw->defrag_list); ++ spin_lock_init(&rwnx_hw->defrag_lock); ++ mutex_init(&rwnx_hw->mutex); ++ mutex_init(&rwnx_hw->dbgdump_elem.mutex); ++ spin_lock_init(&rwnx_hw->tx_lock); ++ spin_lock_init(&rwnx_hw->cb_lock); ++ ++ INIT_WORK(&rwnx_hw->apmStalossWork, apm_staloss_work_process); ++ rwnx_hw->apmStaloss_wq = create_singlethread_workqueue("apmStaloss_wq"); ++ if (!rwnx_hw->apmStaloss_wq) { ++ txrx_err("insufficient memory to create apmStaloss workqueue.\n"); ++ goto err_cache; ++ } ++ ++ wiphy->mgmt_stypes = rwnx_default_mgmt_stypes; ++ rwnx_hw->fwlog_en = feature.fwlog_en; ++ ++ ++ //init ic system ++ if((ret = rwnx_ic_system_init(rwnx_hw))){ ++ goto err_lmac_reqs; ++ } ++ ++ //ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, feature.hwinfo < 0, feature.hwinfo, 0, &set_start_cfm); ++#ifdef USE_5G ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801) { ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, CO_BIT(5), 0, &set_start_cfm); ++ } ++#else ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801) { ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, 0, 0, &set_start_cfm); ++ } ++#endif ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, 0, 0, &set_start_cfm); ++ set_start_cfm.is_5g_support = false; ++ } else { ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, CO_BIT(5), 0, &set_start_cfm); ++ } ++ ++ if (ret) ++ goto err_lmac_reqs; ++ ++ AICWFDBG(LOGINFO, "is 5g support = %d, vendor_info = 0x%02X\n", set_start_cfm.is_5g_support, set_start_cfm.vendor_info); ++ rwnx_hw->band_5g_support = set_start_cfm.is_5g_support; ++ rwnx_hw->vendor_info = (feature.hwinfo < 0) ? set_start_cfm.vendor_info : feature.hwinfo; ++ ++ ret = rwnx_send_get_fw_version_req(rwnx_hw, &fw_version); ++ memcpy(wiphy->fw_version, fw_version.fw_version, fw_version.fw_version_len>32? 32 : fw_version.fw_version_len); ++ AICWFDBG(LOGINFO, "Firmware Version: %s\r\n", fw_version.fw_version); ++ ++ wiphy->bands[NL80211_BAND_2GHZ] = &rwnx_band_2GHz; ++ if (rwnx_hw->band_5g_support) ++ wiphy->bands[NL80211_BAND_5GHZ] = &rwnx_band_5GHz; ++ ++ wiphy->interface_modes = ++ BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_AP_VLAN) | ++ BIT(NL80211_IFTYPE_P2P_CLIENT) | ++ BIT(NL80211_IFTYPE_P2P_GO) | ++#ifndef CONFIG_USE_P2P0 ++ BIT(NL80211_IFTYPE_P2P_DEVICE) | ++#endif ++ BIT(NL80211_IFTYPE_MONITOR); ++ ++#if IS_ENABLED(CONFIG_PM) ++ /* Set WoWLAN flags */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) ++ wiphy->wowlan = &aic_wowlan_support; ++#else ++ wiphy->wowlan.flags = aic_wowlan_support.flags; ++#endif ++#endif ++ wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) ++ WIPHY_FLAG_HAS_CHANNEL_SWITCH | ++ #endif ++ WIPHY_FLAG_4ADDR_STATION | ++ WIPHY_FLAG_4ADDR_AP; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ wiphy->max_num_csa_counters = BCN_MAX_CSA_CPT; ++ #endif ++ ++ wiphy->max_remain_on_channel_duration = rwnx_hw->mod_params->roc_dur_max; ++ ++ wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN | ++ NL80211_FEATURE_SK_TX_STATUS | ++ NL80211_FEATURE_VIF_TXPOWER | ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) ++ NL80211_FEATURE_ACTIVE_MONITOR | ++ #endif ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | ++ #endif ++ 0; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ wiphy->features |= NL80211_FEATURE_SAE; ++#endif ++ ++ if (rwnx_mod_params.tdls) ++ /* TDLS support */ ++ wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH; ++ ++ wiphy->iface_combinations = rwnx_combinations; ++ /* -1 not to include combination with radar detection, will be re-added in ++ rwnx_handle_dynparams if supported */ ++ wiphy->n_iface_combinations = ARRAY_SIZE(rwnx_combinations) - 1; ++ wiphy->reg_notifier = rwnx_reg_notifier; ++ ++ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; ++ ++ rwnx_enable_wapi(rwnx_hw); ++ ++ wiphy->cipher_suites = cipher_suites; ++ wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites) - NB_RESERVED_CIPHER; ++ ++ rwnx_hw->ext_capa[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING; ++ rwnx_hw->ext_capa[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF; ++ ++ wiphy->extended_capabilities = rwnx_hw->ext_capa; ++ wiphy->extended_capabilities_mask = rwnx_hw->ext_capa; ++ wiphy->extended_capabilities_len = ARRAY_SIZE(rwnx_hw->ext_capa); ++ ++#ifdef CONFIG_SCHED_SCAN ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ wiphy->max_sched_scan_reqs = 1; ++#endif ++ wiphy->max_sched_scan_ssids = SCAN_SSID_MAX;//16; ++ wiphy->max_match_sets = SCAN_SSID_MAX;//16; ++ wiphy->max_sched_scan_ie_len = 2048; ++#endif//CONFIG_SCHED_SCAN ++ ++ tasklet_init(&rwnx_hw->task, rwnx_task, (unsigned long)rwnx_hw); ++ ++ //init ic rf ++ if((ret = rwnx_ic_rf_init(rwnx_hw))){ ++ goto err_lmac_reqs; ++ } ++ ++ ++#ifdef CONFIG_USE_CUSTOMER_MAC ++ ret = rwnx_get_custom_mac_addr(mac_addr_efuse); ++ if (ret){ ++ AICWFDBG(LOGERROR, "%s read mac fail use default mac\r\n", __func__); ++ memcpy(init_conf.mac_addr, dflt_mac, ETH_ALEN); ++ } ++#else ++ ret = rwnx_send_get_macaddr_req(rwnx_hw, (struct mm_get_mac_addr_cfm *)mac_addr_efuse); ++ if (ret) ++ goto err_lmac_reqs; ++#endif ++ ++ if (mac_addr_efuse[0] | mac_addr_efuse[1] | mac_addr_efuse[2] | mac_addr_efuse[3]) { ++ memcpy(init_conf.mac_addr, mac_addr_efuse, ETH_ALEN); ++ }else{ ++ memcpy(init_conf.mac_addr, dflt_mac, ETH_ALEN); ++ } ++ ++ ++ AICWFDBG(LOGINFO, "get macaddr: %02x:%02x:%02x:%02x:%02x:%02x\r\n", ++ mac_addr_efuse[0], mac_addr_efuse[1], mac_addr_efuse[2], ++ mac_addr_efuse[3], mac_addr_efuse[4], mac_addr_efuse[5]); ++ memcpy(wiphy->perm_addr, init_conf.mac_addr, ETH_ALEN); ++ ++ /* Reset FW */ ++ ret = rwnx_send_reset(rwnx_hw); ++ if (ret) ++ goto err_lmac_reqs; ++ ++#ifdef CONFIG_TEMP_COMP ++ rwnx_send_set_temp_comp_req(rwnx_hw, &swconfig_cfm); ++#endif ++ ++ ret = rwnx_send_version_req(rwnx_hw, &rwnx_hw->version_cfm); ++ if (ret) ++ goto err_lmac_reqs; ++ rwnx_set_vers(rwnx_hw); ++ ++ ret = rwnx_handle_dynparams(rwnx_hw, rwnx_hw->wiphy); ++ if (ret) ++ goto err_lmac_reqs; ++ ++ rwnx_enable_mesh(rwnx_hw); ++ rwnx_radar_detection_init(&rwnx_hw->radar); ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ rwnx_radar_set_domain(&rwnx_hw->radar, NL80211_DFS_FCC); ++#endif ++ ++ /* Set parameters to firmware */ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC|| ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) && testmode == 0)){ ++ rwnx_send_me_config_req(rwnx_hw); ++ } ++ ++ /* Only monitor mode supported when custom channels are enabled */ ++ if (rwnx_mod_params.custchan) { ++ rwnx_limits[0].types = BIT(NL80211_IFTYPE_MONITOR); ++ rwnx_limits_dfs[0].types = BIT(NL80211_IFTYPE_MONITOR); ++ } ++ ++ aicwf_vendor_init(wiphy); ++ ++ ret = wiphy_register(wiphy); ++ if (ret) { ++ wiphy_err(wiphy, "Could not register wiphy device\n"); ++ goto err_register_wiphy; ++ } ++ ++ /* Update regulatory (if needed) and set channel parameters to firmware ++ (must be done after WiPHY registration) */ ++ rwnx_custregd(rwnx_hw, wiphy); ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) && testmode == 0)) { ++ rwnx_send_me_chan_config_req(rwnx_hw, "00"); ++ } ++ ++ *platform_data = rwnx_hw; ++ ++#ifdef CONFIG_DEBUG_FS ++ ret = rwnx_dbgfs_register(rwnx_hw, "rwnx"); ++ if (ret) { ++ wiphy_err(wiphy, "Failed to register debugfs entries"); ++ goto err_debugfs; ++ } ++#endif ++ rtnl_lock(); ++ ++ /* Add an initial station interface */ ++ vif = rwnx_interface_add(rwnx_hw, "wlan%d", NET_NAME_UNKNOWN, ++ NL80211_IFTYPE_STATION, NULL); ++ ++#ifdef CONFIG_RWNX_MON_DATA ++ /* Add an initial station interface */ ++ vif = rwnx_interface_add(rwnx_hw, "wlan%d", 1, ++ NL80211_IFTYPE_MONITOR, NULL); ++#endif ++ ++ rtnl_unlock(); ++ ++ if (!vif) { ++ wiphy_err(wiphy, "Failed to instantiate a network device\n"); ++ ret = -ENOMEM; ++ goto err_add_interface; ++ } ++ ++ //wiphy_info(wiphy, "New interface create %s", vif->ndev->name); ++ AICWFDBG(LOGINFO, "New interface create %s \r\n", vif->ndev->name); ++ ++#ifdef CONFIG_SDIO_BT ++#if CONFIG_BLUEDROID ++ btchr_init(); ++ hdev_init(); ++#else ++ btsdio_init(); ++#endif ++#endif ++ ++#ifdef CONFIG_USE_P2P0 ++ ++ rtnl_lock(); ++ /* Add an initial p2p0 interface */ ++ vif = rwnx_interface_add(rwnx_hw, "p2p%d", NET_NAME_UNKNOWN, ++ NL80211_IFTYPE_STATION, NULL); ++ vif->is_p2p_vif = 1; ++ rtnl_unlock(); ++ ++ if (!vif) { ++ wiphy_err(wiphy, "Failed to instantiate a network device\n"); ++ ret = -ENOMEM; ++ goto err_add_interface; ++ } ++ ++ //wiphy_info(wiphy, "New interface create %s", vif->ndev->name); ++ AICWFDBG(LOGINFO, "New interface create %s \r\n", vif->ndev->name); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ init_timer(&rwnx_hw->p2p_alive_timer); ++ rwnx_hw->p2p_alive_timer.data = (unsigned long)vif; ++ rwnx_hw->p2p_alive_timer.function = aicwf_p2p_alive_timeout; ++#else ++ timer_setup(&rwnx_hw->p2p_alive_timer, aicwf_p2p_alive_timeout, 0); ++#endif ++ rwnx_hw->is_p2p_alive = 0; ++ rwnx_hw->is_p2p_connected = 0; ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ ++#ifdef CONFIG_FOR_IPCAM ++ if(!testmode && !adap_test) { ++ aic_ipc_setting(vif); ++ } ++#endif ++ ++ return 0; ++ ++err_add_interface: ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister(rwnx_hw); ++err_debugfs: ++#endif ++ wiphy_unregister(rwnx_hw->wiphy); ++err_register_wiphy: ++err_lmac_reqs: ++ printk("err_lmac_reqs\n"); ++ rwnx_platform_off(rwnx_hw, NULL); ++//err_platon: ++//err_config: ++ kmem_cache_destroy(rwnx_hw->sw_txhdr_cache); ++err_cache: ++ aicwf_wakeup_lock_deinit(rwnx_hw); ++ wiphy_free(wiphy); ++err_out: ++ return ret; ++} ++ ++/** ++ * ++ */ ++void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_stack_start_cfm set_start_cfm; ++ struct defrag_ctrl_info *defrag_ctrl = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef AICWF_USB_SUPPORT ++ if (rwnx_hw->usbdev->bus_if->state != BUS_DOWN_ST) ++#else ++ if (rwnx_hw->sdiodev->bus_if->state != BUS_DOWN_ST) ++#endif ++ rwnx_send_set_stack_start_req(rwnx_hw, 0, 0, 0, 0, &set_start_cfm); ++ ++ rwnx_hw->fwlog_en = 0; ++ spin_lock_bh(&rwnx_hw->defrag_lock); ++ if (!list_empty(&rwnx_hw->defrag_list)) { ++ list_for_each_entry(defrag_ctrl, &rwnx_hw->defrag_list, list) { ++ list_del_init(&defrag_ctrl->list); ++ if (timer_pending(&defrag_ctrl->defrag_timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&defrag_ctrl->defrag_timer); ++#else ++ del_timer_sync(&defrag_ctrl->defrag_timer); ++#endif ++ dev_kfree_skb(defrag_ctrl->skb); ++ kfree(defrag_ctrl); ++ } ++ } ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister(rwnx_hw); ++#endif ++ ++#ifdef CONFIG_SDIO_BT ++#if CONFIG_BLUEDROID ++ btchr_exit(); ++ hdev_exit(); ++#else ++ btsdio_remove(); ++#endif ++#endif ++ ++ flush_workqueue(rwnx_hw->apmStaloss_wq); ++ destroy_workqueue(rwnx_hw->apmStaloss_wq); ++ ++ rwnx_wdev_unregister(rwnx_hw); ++ wiphy_unregister(rwnx_hw->wiphy); ++ rwnx_radar_detection_deinit(&rwnx_hw->radar); ++ rwnx_platform_off(rwnx_hw, NULL); ++ kmem_cache_destroy(rwnx_hw->sw_txhdr_cache); ++#ifdef CONFIG_FILTER_TCP_ACK ++ tcp_ack_deinit(rwnx_hw); ++#endif ++ aicwf_wakeup_lock_deinit(rwnx_hw); ++ wiphy_free(rwnx_hw->wiphy); ++} ++ ++static void aicsmac_driver_register(void) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_register(); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ aicwf_usb_register(); ++#endif ++#ifdef AICWF_PCIE_SUPPORT ++ aicwf_pcie_register(); ++#endif ++} ++ ++//static DECLARE_WORK(aicsmac_driver_work, aicsmac_driver_register); ++ ++struct completion hostif_register_done; ++static int rwnx_driver_err = -1; ++ ++#define REGISTRATION_TIMEOUT 9000 ++ ++void aicwf_hostif_ready(void) ++{ ++ rwnx_driver_err = 0; ++ g_rwnx_plat->enabled = true; ++ complete(&hostif_register_done); ++} ++ ++void aicwf_hostif_fail(void) ++{ ++ rwnx_driver_err = 1; ++ complete(&hostif_register_done); ++} ++ ++static int __init rwnx_mod_init(void) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ rwnx_print_version(); ++ rwnx_init_cmd_array(); ++ ++//#ifndef CONFIG_PLATFORM_ROCKCHIP ++ if (aicbsp_set_subsys(AIC_WIFI, AIC_PWR_ON) < 0) { ++ AICWFDBG(LOGERROR, "%s, set power on fail!\n", __func__); ++ if(!aicbsp_get_load_fw_in_fdrv()){ ++ return -ENODEV; ++ } ++ } ++//#endif ++ ++ init_completion(&hostif_register_done); ++ aicsmac_driver_register(); ++ ++ if ((wait_for_completion_timeout(&hostif_register_done, msecs_to_jiffies(REGISTRATION_TIMEOUT)) == 0) || rwnx_driver_err) { ++ AICWFDBG(LOGERROR, "register_driver timeout or error\n"); ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_exit(); ++#endif /* AICWF_SDIO_SUPPORT */ ++#ifdef AICWF_USB_SUPPORT ++ aicwf_usb_exit(); ++#endif /*AICWF_USB_SUPPORT */ ++ aicbsp_set_subsys(AIC_WIFI, AIC_PWR_OFF); ++ return -ENODEV; ++ } ++ ++#ifdef AICWF_PCIE_SUPPORT ++ return rwnx_platform_register_drv(); ++#else ++ return 0; ++#endif ++} ++ ++/** ++ * ++ */ ++static void __exit rwnx_mod_exit(void) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef AICWF_PCIE_SUPPORT ++ rwnx_platform_unregister_drv(); ++#endif ++ ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_exit(); ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++ aicwf_usb_exit(); ++#endif ++//#ifndef CONFIG_PLATFORM_ROCKCHIP ++ aicbsp_set_subsys(AIC_WIFI, AIC_PWR_OFF); ++//#endif ++ rwnx_free_cmd_array(); ++ ++} ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) ++MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver"); ++#else ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#endif ++#endif ++ ++module_init(rwnx_mod_init); ++module_exit(rwnx_mod_exit); ++ ++MODULE_FIRMWARE(RWNX_CONFIG_FW_NAME); ++ ++MODULE_DESCRIPTION(RW_DRV_DESCRIPTION); ++MODULE_VERSION(RWNX_VERS_MOD); ++MODULE_AUTHOR(RW_DRV_COPYRIGHT " " RW_DRV_AUTHOR); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h +new file mode 100644 +index 000000000000..dfa89034706a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h +@@ -0,0 +1,26 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_main.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_MAIN_H_ ++#define _RWNX_MAIN_H_ ++ ++#include "rwnx_defs.h" ++ ++int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data); ++void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw); ++extern int testmode; ++extern u8 chip_sub_id; ++extern u8 chip_mcu_id; ++extern u8 chip_id; ++ ++#define CHIP_ID_H_MASK 0xC0 ++#define IS_CHIP_ID_H() ((chip_id & CHIP_ID_H_MASK) == CHIP_ID_H_MASK) ++ ++#endif /* _RWNX_MAIN_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c +new file mode 100644 +index 000000000000..8773db61a664 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c +@@ -0,0 +1,42 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_mesh.c ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++/** ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++ ++#include "rwnx_mesh.h" ++ ++/** ++ * FUNCTION DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local) ++{ ++ struct rwnx_mesh_proxy *p_mesh_proxy = NULL; ++ struct rwnx_mesh_proxy *p_cur_proxy; ++ ++ /* Look for proxied devices with provided address */ ++ list_for_each_entry(p_cur_proxy, &p_rwnx_vif->ap.proxy_list, list) { ++ if (p_cur_proxy->local != local) { ++ continue; ++ } ++ ++ if (!memcmp(&p_cur_proxy->ext_sta_addr, p_sta_addr, ETH_ALEN)) { ++ p_mesh_proxy = p_cur_proxy; ++ break; ++ } ++ } ++ ++ /* Return the found information */ ++ return p_mesh_proxy; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h +new file mode 100644 +index 000000000000..db8950f160de +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h +@@ -0,0 +1,45 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_mesh.h ++ * ++ * @brief VHT Beamformer function declarations ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_MESH_H_ ++#define _RWNX_MESH_H_ ++ ++/** ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++ ++/** ++ * DEFINES ++ **************************************************************************************** ++ */ ++ ++/** ++ * TYPE DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++/** ++ * FUNCTION DECLARATIONS ++ **************************************************************************************** ++ */ ++ ++/** ++ **************************************************************************************** ++ * @brief TODO [LT] ++ **************************************************************************************** ++ */ ++struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local); ++ ++#endif /* _RWNX_MESH_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c +new file mode 100644 +index 000000000000..965454201a8a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c +@@ -0,0 +1,1798 @@ ++/** ++****************************************************************************** ++* ++* @file rwnx_mod_params.c ++* ++* @brief Set configuration according to modules parameters ++* ++* Copyright (C) RivieraWaves 2012-2019 ++* ++****************************************************************************** ++*/ ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_tx.h" ++#include "hal_desc.h" ++#include "rwnx_cfgfile.h" ++#include "rwnx_dini.h" ++#include "reg_access.h" ++#include "rwnx_compat.h" ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define COMMON_PARAM(name, default_softmac, default_fullmac) \ ++ .name = default_fullmac, ++#define SOFTMAC_PARAM(name, default) ++#define FULLMAC_PARAM(name, default) .name = default, ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++struct rwnx_mod_params rwnx_mod_params = { ++ /* common parameters */ ++ COMMON_PARAM(ht_on, true, true) ++ COMMON_PARAM(vht_on, true, true) ++ COMMON_PARAM(he_on, true, true) ++ COMMON_PARAM(mcs_map, IEEE80211_VHT_MCS_SUPPORT_0_9, IEEE80211_VHT_MCS_SUPPORT_0_9) ++ COMMON_PARAM(he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_11, IEEE80211_HE_MCS_SUPPORT_0_11) ++ COMMON_PARAM(he_ul_on, false, false) ++ COMMON_PARAM(ldpc_on, true, true) ++ COMMON_PARAM(stbc_on, true, true) ++ COMMON_PARAM(gf_rx_on, false, false) ++ COMMON_PARAM(phy_cfg, 2, 2) ++ COMMON_PARAM(uapsd_timeout, 300, 300) ++ COMMON_PARAM(ap_uapsd_on, true, true) ++ COMMON_PARAM(sgi, true, true) ++ COMMON_PARAM(sgi80, false, false) ++ COMMON_PARAM(use_2040, 1, 1) ++ COMMON_PARAM(nss, 2, 2) ++ COMMON_PARAM(amsdu_rx_max, 1, 1) ++ COMMON_PARAM(bfmee, true, true) ++ COMMON_PARAM(bfmer, false, false) ++ COMMON_PARAM(mesh, true, true) ++ COMMON_PARAM(murx, true, true) ++ COMMON_PARAM(mutx, true, true) ++ COMMON_PARAM(mutx_on, true, true) ++ COMMON_PARAM(use_80, false, false) ++ COMMON_PARAM(custregd, true, true) ++ COMMON_PARAM(custchan, false, false) ++ COMMON_PARAM(roc_dur_max, 500, 500) ++ COMMON_PARAM(listen_itv, 0, 0) ++ COMMON_PARAM(listen_bcmc, true, true) ++ COMMON_PARAM(lp_clk_ppm, 20, 20) ++ COMMON_PARAM(ps_on, true, true) ++ COMMON_PARAM(tx_lft, RWNX_TX_LIFETIME_MS, RWNX_TX_LIFETIME_MS) ++ COMMON_PARAM(amsdu_maxnb, NX_TX_PAYLOAD_MAX, NX_TX_PAYLOAD_MAX) ++ // By default, only enable UAPSD for Voice queue (see IEEE80211_DEFAULT_UAPSD_QUEUE comment) ++ COMMON_PARAM(uapsd_queues, IEEE80211_WMM_IE_STA_QOSINFO_AC_VO, IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) ++ COMMON_PARAM(tdls, false, false) ++ COMMON_PARAM(uf, false, false) ++ COMMON_PARAM(auto_reply, false, false) ++ COMMON_PARAM(ftl, "", "") ++ COMMON_PARAM(dpsm, false, false) ++ ++ /* SOFTMAC only parameters */ ++ SOFTMAC_PARAM(mfp_on, false) ++ SOFTMAC_PARAM(gf_on, false) ++ SOFTMAC_PARAM(bwsig_on, true) ++ SOFTMAC_PARAM(dynbw_on, true) ++ SOFTMAC_PARAM(agg_tx, true) ++ SOFTMAC_PARAM(amsdu_force, 2) ++ SOFTMAC_PARAM(rc_probes_on, false) ++ SOFTMAC_PARAM(cmon, true) ++ SOFTMAC_PARAM(hwscan, true) ++ SOFTMAC_PARAM(autobcn, true) ++ SOFTMAC_PARAM(dpsm, true) ++ ++ /* FULLMAC only parameters */ ++ FULLMAC_PARAM(ant_div, true) ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/* FULLMAC specific parameters*/ ++module_param_named(ant_div, rwnx_mod_params.ant_div, bool, S_IRUGO); ++MODULE_PARM_DESC(ant_div, "Enable Antenna Diversity (Default: 1)"); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++module_param_named(ht_on, rwnx_mod_params.ht_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ht_on, "Enable HT (Default: 1)"); ++ ++module_param_named(vht_on, rwnx_mod_params.vht_on, bool, S_IRUGO); ++MODULE_PARM_DESC(vht_on, "Enable VHT (Default: 1)"); ++ ++module_param_named(he_on, rwnx_mod_params.he_on, bool, S_IRUGO); ++MODULE_PARM_DESC(he_on, "Enable HE (Default: 1)"); ++ ++module_param_named(mcs_map, rwnx_mod_params.mcs_map, int, S_IRUGO); ++MODULE_PARM_DESC(mcs_map, "VHT MCS map value 0: MCS0_7, 1: MCS0_8, 2: MCS0_9" ++ " (Default: 2)"); ++ ++module_param_named(he_mcs_map, rwnx_mod_params.he_mcs_map, int, S_IRUGO); ++MODULE_PARM_DESC(he_mcs_map, "HE MCS map value 0: MCS0_7, 1: MCS0_9, 2: MCS0_11" ++ " (Default: 2)"); ++ ++module_param_named(he_ul_on, rwnx_mod_params.he_ul_on, bool, S_IRUGO); ++MODULE_PARM_DESC(he_ul_on, "Enable HE OFDMA UL (Default: 0)"); ++ ++module_param_named(amsdu_maxnb, rwnx_mod_params.amsdu_maxnb, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(amsdu_maxnb, "Maximum number of MSDUs inside an A-MSDU in TX: (Default: NX_TX_PAYLOAD_MAX)"); ++ ++module_param_named(ps_on, rwnx_mod_params.ps_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ps_on, "Enable PowerSaving (Default: 1-Enabled)"); ++ ++module_param_named(tx_lft, rwnx_mod_params.tx_lft, int, 0644); ++MODULE_PARM_DESC(tx_lft, "Tx lifetime (ms) - setting it to 0 disables retries " ++ "(Default: "__stringify(RWNX_TX_LIFETIME_MS)")"); ++ ++module_param_named(ldpc_on, rwnx_mod_params.ldpc_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ldpc_on, "Enable LDPC (Default: 1)"); ++ ++module_param_named(stbc_on, rwnx_mod_params.stbc_on, bool, S_IRUGO); ++MODULE_PARM_DESC(stbc_on, "Enable STBC in RX (Default: 1)"); ++ ++module_param_named(gf_rx_on, rwnx_mod_params.gf_rx_on, bool, S_IRUGO); ++MODULE_PARM_DESC(gf_rx_on, "Enable HT greenfield in reception (Default: 1)"); ++ ++module_param_named(phycfg, rwnx_mod_params.phy_cfg, int, S_IRUGO); ++MODULE_PARM_DESC(phycfg, ++ "0 <= phycfg <= 5 : RF Channel Conf (Default: 2(C0-A1-B2))"); ++ ++module_param_named(uapsd_timeout, rwnx_mod_params.uapsd_timeout, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(uapsd_timeout, ++ "UAPSD Timer timeout, in ms (Default: 300). If 0, UAPSD is disabled"); ++ ++module_param_named(uapsd_queues, rwnx_mod_params.uapsd_queues, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(uapsd_queues, "UAPSD Queues, integer value, must be seen as a bitfield\n" ++ " Bit 0 = VO\n" ++ " Bit 1 = VI\n" ++ " Bit 2 = BK\n" ++ " Bit 3 = BE\n" ++ " -> uapsd_queues=7 will enable uapsd for VO, VI and BK queues"); ++ ++module_param_named(ap_uapsd_on, rwnx_mod_params.ap_uapsd_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ap_uapsd_on, "Enable UAPSD in AP mode (Default: 1)"); ++ ++module_param_named(sgi, rwnx_mod_params.sgi, bool, S_IRUGO); ++MODULE_PARM_DESC(sgi, "Advertise Short Guard Interval support (Default: 1)"); ++ ++module_param_named(sgi80, rwnx_mod_params.sgi80, bool, S_IRUGO); ++MODULE_PARM_DESC(sgi80, "Advertise Short Guard Interval support for 80MHz (Default: 1)"); ++ ++module_param_named(use_2040, rwnx_mod_params.use_2040, bool, S_IRUGO); ++MODULE_PARM_DESC(use_2040, "Use tweaked 20-40MHz mode (Default: 1)"); ++ ++module_param_named(use_80, rwnx_mod_params.use_80, bool, S_IRUGO); ++MODULE_PARM_DESC(use_80, "Enable 80MHz (Default: 1)"); ++ ++module_param_named(custregd, rwnx_mod_params.custregd, bool, S_IRUGO); ++MODULE_PARM_DESC(custregd, ++ "Use permissive custom regulatory rules (for testing ONLY) (Default: 0)"); ++ ++module_param_named(custchan, rwnx_mod_params.custchan, bool, S_IRUGO); ++MODULE_PARM_DESC(custchan, ++ "Extend channel set to non-standard channels (for testing ONLY) (Default: 0)"); ++ ++module_param_named(nss, rwnx_mod_params.nss, int, S_IRUGO); ++MODULE_PARM_DESC(nss, "1 <= nss <= 2 : Supported number of Spatial Streams (Default: 1)"); ++ ++module_param_named(amsdu_rx_max, rwnx_mod_params.amsdu_rx_max, int, S_IRUGO); ++MODULE_PARM_DESC(amsdu_rx_max, "0 <= amsdu_rx_max <= 2 : Maximum A-MSDU size supported in RX\n" ++ " 0: 3895 bytes\n" ++ " 1: 7991 bytes\n" ++ " 2: 11454 bytes\n" ++ " This value might be reduced according to the FW capabilities.\n" ++ " Default: 2"); ++ ++module_param_named(bfmee, rwnx_mod_params.bfmee, bool, S_IRUGO); ++MODULE_PARM_DESC(bfmee, "Enable Beamformee Capability (Default: 1-Enabled)"); ++ ++module_param_named(bfmer, rwnx_mod_params.bfmer, bool, S_IRUGO); ++MODULE_PARM_DESC(bfmer, "Enable Beamformer Capability (Default: 0-Disabled)"); ++ ++module_param_named(mesh, rwnx_mod_params.mesh, bool, S_IRUGO); ++MODULE_PARM_DESC(mesh, "Enable Meshing Capability (Default: 1-Enabled)"); ++ ++module_param_named(murx, rwnx_mod_params.murx, bool, S_IRUGO); ++MODULE_PARM_DESC(murx, "Enable MU-MIMO RX Capability (Default: 1-Enabled)"); ++ ++module_param_named(mutx, rwnx_mod_params.mutx, bool, S_IRUGO); ++MODULE_PARM_DESC(mutx, "Enable MU-MIMO TX Capability (Default: 1-Enabled)"); ++ ++module_param_named(mutx_on, rwnx_mod_params.mutx_on, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(mutx_on, "Enable MU-MIMO transmissions (Default: 1-Enabled)"); ++ ++module_param_named(roc_dur_max, rwnx_mod_params.roc_dur_max, int, S_IRUGO); ++MODULE_PARM_DESC(roc_dur_max, "Maximum Remain on Channel duration"); ++ ++module_param_named(listen_itv, rwnx_mod_params.listen_itv, int, S_IRUGO); ++MODULE_PARM_DESC(listen_itv, "Maximum listen interval"); ++ ++module_param_named(listen_bcmc, rwnx_mod_params.listen_bcmc, bool, S_IRUGO); ++MODULE_PARM_DESC(listen_bcmc, "Wait for BC/MC traffic following DTIM beacon"); ++ ++module_param_named(lp_clk_ppm, rwnx_mod_params.lp_clk_ppm, int, S_IRUGO); ++MODULE_PARM_DESC(lp_clk_ppm, "Low Power Clock accuracy of the local device"); ++ ++module_param_named(tdls, rwnx_mod_params.tdls, bool, S_IRUGO); ++MODULE_PARM_DESC(tdls, "Enable TDLS (Default: 1-Enabled)"); ++ ++module_param_named(uf, rwnx_mod_params.uf, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(uf, "Enable Unsupported HT Frame Logging (Default: 0-Disabled)"); ++ ++module_param_named(auto_reply, rwnx_mod_params.auto_reply, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(auto_reply, "Enable Monitor MacAddr Auto-Reply (Default: 0-Disabled)"); ++ ++module_param_named(ftl, rwnx_mod_params.ftl, charp, S_IRUGO); ++MODULE_PARM_DESC(ftl, "Firmware trace level (Default: \"\")"); ++ ++module_param_named(dpsm, rwnx_mod_params.dpsm, bool, S_IRUGO); ++MODULE_PARM_DESC(dpsm, "Enable Dynamic PowerSaving (Default: 1-Enabled)"); ++ ++ ++#ifdef DEFAULT_COUNTRY_CODE ++char default_ccode[4] = DEFAULT_COUNTRY_CODE; ++#else ++char default_ccode[4] = "00"; ++#endif ++ ++char country_code[4]; ++module_param_string(country_code, country_code, 4, 0600); ++ ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++/* Regulatory rules */ ++static struct ieee80211_regdomain rwnx_regdom = { ++ .n_reg_rules = 2, ++ .alpha2 = "99", ++ .reg_rules = { ++ REG_RULE(2390 - 10, 2510 + 10, 40, 0, 1000, 0), ++ REG_RULE(5150 - 10, 5970 + 10, 80, 0, 1000, 0), ++ } ++}; ++#endif ++#endif ++ ++static const int mcs_map_to_rate[4][3] = { ++ [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_7] = 65, ++ [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_8] = 78, ++ [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_9] = 78, ++ [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_7] = 135, ++ [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_8] = 162, ++ [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_9] = 180, ++ [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_7] = 292, ++ [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_8] = 351, ++ [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_9] = 390, ++ [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_7] = 585, ++ [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_8] = 702, ++ [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_9] = 780, ++}; ++ ++#define MAX_VHT_RATE(map, nss, bw) (mcs_map_to_rate[bw][map] * (nss)) ++ ++extern struct ieee80211_regdomain *reg_regdb[]; ++extern int reg_regdb_size; ++ ++char ccode_channels[200]; ++int index_for_channel_list = 0; ++module_param_string(ccode_channels, ccode_channels, 200, 0600); ++ ++void rwnx_get_countrycode_channels(struct wiphy *wiphy, ++ struct ieee80211_regdomain *regdomain){ ++ enum nl80211_band band; ++ struct ieee80211_supported_band *sband; ++ int channel_index; ++ int rule_index; ++ int band_num = 0; ++ int rule_num = regdomain->n_reg_rules; ++ int start_freq = 0; ++ int end_freq = 0; ++ int center_freq = 0; ++ char channel[4]; ++ ++ band_num = NUM_NL80211_BANDS; ++ ++ memset(ccode_channels, 0, 200); ++ index_for_channel_list = 0; ++ ++ for (band = 0; band < band_num; band++) { ++ sband = wiphy->bands[band];// bands: 0:2.4G 1:5G 2:60G ++ if (!sband) ++ continue; ++ ++ for (channel_index = 0; channel_index < sband->n_channels; channel_index++) { ++ for(rule_index = 0; rule_index < rule_num; rule_index++){ ++ start_freq = regdomain->reg_rules[rule_index].freq_range.start_freq_khz/1000; ++ end_freq = regdomain->reg_rules[rule_index].freq_range.end_freq_khz/1000; ++ center_freq = sband->channels[channel_index].center_freq; ++ if((center_freq - 10) >= start_freq && (center_freq + 10) <= end_freq){ ++ sprintf(channel, "%d",ieee80211_frequency_to_channel(center_freq)); ++ memcpy(ccode_channels + index_for_channel_list, channel, strlen(channel)); ++ index_for_channel_list += strlen(channel); ++ memcpy(ccode_channels + index_for_channel_list, " ", 1); ++ index_for_channel_list += 1; ++ break; ++ } ++ } ++ } ++ } ++ AICWFDBG(LOGINFO, "%s support channel:%s\r\n", __func__, ccode_channels); ++} ++ ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, ++ int index) ++{ ++ u8 idx; ++ ++ idx = index; ++ ++ memset(country_code, 0, 4); ++ country_code[0] = reg_regdb[idx]->alpha2[0]; ++ country_code[1] = reg_regdb[idx]->alpha2[1]; ++ ++ printk("%s set ccode:%s \r\n", __func__, country_code); ++ ++ rwnx_get_countrycode_channels(wiphy, reg_regdb[idx]); ++ ++ return reg_regdb[idx]; ++} ++ ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, ++ char *alpha2) ++{ ++ u8 idx; ++ ++ memset(country_code, 0, 4); ++ ++ AICWFDBG(LOGINFO, "%s set ccode:%s \r\n", __func__, alpha2); ++ idx = 0; ++ ++ while (reg_regdb[idx]){ ++ if((reg_regdb[idx]->alpha2[0] == alpha2[0]) && ++ (reg_regdb[idx]->alpha2[1] == alpha2[1])){ ++ memcpy(country_code, alpha2, 2); ++ rwnx_get_countrycode_channels(wiphy, reg_regdb[idx]); ++ return reg_regdb[idx]; ++ } ++ idx++; ++ } ++ ++ AICWFDBG(LOGERROR, "%s(): Error, wrong country = %s\n", ++ __func__, alpha2); ++ AICWFDBG(LOGINFO, "Set as default 00\n"); ++ memcpy(country_code, default_ccode, sizeof(default_ccode)); ++ rwnx_get_countrycode_channels(wiphy, reg_regdb[0]); ++ ++ return reg_regdb[0]; ++} ++ ++ ++ ++/** ++ * Do some sanity check ++ * ++ */ ++#if 0 ++static int rwnx_check_fw_hw_feature(struct rwnx_hw *rwnx_hw, ++ struct wiphy *wiphy) ++{ ++ u32_l sys_feat = rwnx_hw->version_cfm.features; ++ u32_l mac_feat = rwnx_hw->version_cfm.version_machw_1; ++ u32_l phy_feat = rwnx_hw->version_cfm.version_phy_1; ++ u32_l phy_vers = rwnx_hw->version_cfm.version_phy_2; ++ u16_l max_sta_nb = rwnx_hw->version_cfm.max_sta_nb; ++ u8_l max_vif_nb = rwnx_hw->version_cfm.max_vif_nb; ++ int bw, res = 0; ++ int amsdu_rx; ++ ++ if (!rwnx_hw->mod_params->custregd) ++ rwnx_hw->mod_params->custchan = false; ++ ++ if (rwnx_hw->mod_params->custchan) { ++ rwnx_hw->mod_params->mesh = false; ++ rwnx_hw->mod_params->tdls = false; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++ if (!(sys_feat & BIT(MM_FEAT_UMAC_BIT))) { ++ wiphy_err(wiphy, ++ "Loading softmac firmware with fullmac driver\n"); ++ res = -1; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_ANT_DIV_BIT))) { ++ rwnx_hw->mod_params->ant_div = false; ++ } ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (!(sys_feat & BIT(MM_FEAT_VHT_BIT))) { ++ rwnx_hw->mod_params->vht_on = false; ++ } ++ ++ // Check if HE is supported ++ if (!(sys_feat & BIT(MM_FEAT_HE_BIT))) { ++ rwnx_hw->mod_params->he_on = false; ++ rwnx_hw->mod_params->he_ul_on = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_PS_BIT))) { ++ rwnx_hw->mod_params->ps_on = false; ++ } ++ ++ /* AMSDU (non)support implies different shared structure definition ++ so insure that fw and drv have consistent compilation option */ ++ if (sys_feat & BIT(MM_FEAT_AMSDU_BIT)) { ++#ifndef CONFIG_RWNX_SPLIT_TX_BUF ++ wiphy_err(wiphy, ++ "AMSDU enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#else ++ if (rwnx_hw->mod_params->amsdu_maxnb > NX_TX_PAYLOAD_MAX) ++ rwnx_hw->mod_params->amsdu_maxnb = NX_TX_PAYLOAD_MAX; ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ } else { ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ wiphy_err(wiphy, ++ "AMSDU disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_UAPSD_BIT))) { ++ rwnx_hw->mod_params->uapsd_timeout = 0; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_BFMEE_BIT))) { ++ rwnx_hw->mod_params->bfmee = false; ++ } ++ ++ if ((sys_feat & BIT(MM_FEAT_BFMER_BIT))) { ++#ifndef CONFIG_RWNX_BFMER ++ wiphy_err(wiphy, ++ "BFMER enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_BFMER */ ++ // Check PHY and MAC HW BFMER support and update parameter accordingly ++ if (!(phy_feat & MDM_BFMER_BIT) || !(mac_feat & NXMAC_BFMER_BIT)) { ++ rwnx_hw->mod_params->bfmer = false; ++ // Disable the feature in the bitfield so that it won't be displayed ++ sys_feat &= ~BIT(MM_FEAT_BFMER_BIT); ++ } ++ } else { ++#ifdef CONFIG_RWNX_BFMER ++ wiphy_err(wiphy, ++ "BFMER disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#else ++ rwnx_hw->mod_params->bfmer = false; ++#endif /* CONFIG_RWNX_BFMER */ ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_MESH_BIT))) { ++ rwnx_hw->mod_params->mesh = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_TDLS_BIT))) { ++ rwnx_hw->mod_params->tdls = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_UF_BIT))) { ++ rwnx_hw->mod_params->uf = false; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if ((sys_feat & BIT(MM_FEAT_MON_DATA_BIT))) { ++#ifndef CONFIG_RWNX_MON_DATA ++ wiphy_err(wiphy, ++ "Monitor+Data interface support (MON_DATA) is enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_MON_DATA */ ++ } else { ++#ifdef CONFIG_RWNX_MON_DATA ++ wiphy_err(wiphy, ++ "Monitor+Data interface support (MON_DATA) disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_MON_DATA */ ++ } ++#endif ++ ++ // Check supported AMSDU RX size ++ amsdu_rx = (sys_feat >> MM_AMSDU_MAX_SIZE_BIT0) & 0x03; ++ if (amsdu_rx < rwnx_hw->mod_params->amsdu_rx_max) { ++ rwnx_hw->mod_params->amsdu_rx_max = amsdu_rx; ++ } ++ ++ // Check supported BW ++ bw = (phy_feat & MDM_CHBW_MASK) >> MDM_CHBW_LSB; ++ // Check if 80MHz BW is supported ++ if (bw < 2) { ++ rwnx_hw->mod_params->use_80 = false; ++ } ++ // Check if 40MHz BW is supported ++ if (bw < 1) ++ rwnx_hw->mod_params->use_2040 = false; ++ ++ // 80MHz BW shall be disabled if 40MHz is not enabled ++ if (!rwnx_hw->mod_params->use_2040) ++ rwnx_hw->mod_params->use_80 = false; ++ ++ // Check if HT is supposed to be supported. If not, disable VHT/HE too ++ if (!rwnx_hw->mod_params->ht_on) { ++ rwnx_hw->mod_params->vht_on = false; ++ rwnx_hw->mod_params->he_on = false; ++ rwnx_hw->mod_params->he_ul_on = false; ++ rwnx_hw->mod_params->use_80 = false; ++ rwnx_hw->mod_params->use_2040 = false; ++ } ++ ++ // LDPC is mandatory for HE40 and above, so if LDPC is not supported, then disable ++ // HE to use HT/VHT only ++ if (rwnx_hw->mod_params->use_2040 && !rwnx_hw->mod_params->ldpc_on) { ++ rwnx_hw->mod_params->he_on = false; ++ rwnx_hw->mod_params->he_ul_on = false; ++ } ++ ++ // HT greenfield is not supported in modem >= 3.0 ++ if (__MDM_MAJOR_VERSION(phy_vers) > 0) { ++ rwnx_hw->mod_params->gf_rx_on = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_MU_MIMO_RX_BIT)) || ++ !rwnx_hw->mod_params->bfmee) { ++ rwnx_hw->mod_params->murx = false; ++ } ++ ++ if ((sys_feat & BIT(MM_FEAT_MU_MIMO_TX_BIT))) { ++#ifndef CONFIG_RWNX_MUMIMO_TX ++ wiphy_err(wiphy, ++ "MU-MIMO TX enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ if (!rwnx_hw->mod_params->bfmer) ++ rwnx_hw->mod_params->mutx = false; ++ // Check PHY and MAC HW MU-MIMO TX support and update parameter accordingly ++ else if (!(phy_feat & MDM_MUMIMOTX_BIT) || !(mac_feat & NXMAC_MU_MIMO_TX_BIT)) { ++ rwnx_hw->mod_params->mutx = false; ++ // Disable the feature in the bitfield so that it won't be displayed ++ sys_feat &= ~BIT(MM_FEAT_MU_MIMO_TX_BIT); ++ } ++ } else { ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ wiphy_err(wiphy, ++ "MU-MIMO TX disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#else ++ rwnx_hw->mod_params->mutx = false; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ } ++ ++ if (sys_feat & BIT(MM_FEAT_WAPI_BIT)) { ++ rwnx_enable_wapi(rwnx_hw); ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (sys_feat & BIT(MM_FEAT_MFP_BIT)) { ++ rwnx_enable_mfp(rwnx_hw); ++ } ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define QUEUE_NAME "Broadcast/Multicast queue " ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (sys_feat & BIT(MM_FEAT_BCN_BIT)) { ++#if NX_TXQ_CNT == 4 ++ wiphy_err(wiphy, QUEUE_NAME ++ "enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* NX_TXQ_CNT == 4 */ ++ } else { ++#if NX_TXQ_CNT == 5 ++ wiphy_err(wiphy, QUEUE_NAME ++ "disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#endif /* NX_TXQ_CNT == 5 */ ++ } ++#undef QUEUE_NAME ++ ++#ifdef CONFIG_RWNX_RADAR ++ if (sys_feat & BIT(MM_FEAT_RADAR_BIT)) { ++ /* Enable combination with radar detection */ ++ wiphy->n_iface_combinations++; ++ } ++#endif /* CONFIG_RWNX_RADAR */ ++ ++#ifndef CONFIG_RWNX_SDM ++ switch (__MDM_PHYCFG_FROM_VERS(phy_feat)) { ++ case MDM_PHY_CONFIG_TRIDENT: ++ case MDM_PHY_CONFIG_ELMA: ++ rwnx_hw->mod_params->nss = 1; ++ break; ++ case MDM_PHY_CONFIG_KARST: ++ { ++ int nss_supp = (phy_feat & MDM_NSS_MASK) >> MDM_NSS_LSB; ++ if (rwnx_hw->mod_params->nss > nss_supp) ++ rwnx_hw->mod_params->nss = nss_supp; ++ } ++ break; ++ default: ++ WARN_ON(1); ++ break; ++ } ++#endif /* CONFIG_RWNX_SDM */ ++ ++ if (rwnx_hw->mod_params->nss < 1 || rwnx_hw->mod_params->nss > 2) ++ rwnx_hw->mod_params->nss = 1; ++ ++ if (rwnx_hw->mod_params->phy_cfg < 0 || rwnx_hw->mod_params->phy_cfg > 5) ++ rwnx_hw->mod_params->phy_cfg = 2; ++ ++ if (rwnx_hw->mod_params->mcs_map < 0 || rwnx_hw->mod_params->mcs_map > 2) ++ rwnx_hw->mod_params->mcs_map = 0; ++ ++ wiphy_info(wiphy, "PHY features: [NSS=%d][CHBW=%d]%s%s\n", ++ rwnx_hw->mod_params->nss, ++ 20 * (1 << ((phy_feat & MDM_CHBW_MASK) >> MDM_CHBW_LSB)), ++ rwnx_hw->mod_params->ldpc_on ? "[LDPC]" : "", ++ rwnx_hw->mod_params->he_on ? "[HE]" : ""); ++ ++#define PRINT_RWNX_FEAT(feat) \ ++ (sys_feat & BIT(MM_FEAT_##feat##_BIT) ? "["#feat"]" : "") ++ ++ wiphy_info(wiphy, "FW features: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", ++ PRINT_RWNX_FEAT(BCN), ++ PRINT_RWNX_FEAT(AUTOBCN), ++ PRINT_RWNX_FEAT(HWSCAN), ++ PRINT_RWNX_FEAT(CMON), ++ PRINT_RWNX_FEAT(MROLE), ++ PRINT_RWNX_FEAT(RADAR), ++ PRINT_RWNX_FEAT(PS), ++ PRINT_RWNX_FEAT(UAPSD), ++ PRINT_RWNX_FEAT(DPSM), ++ PRINT_RWNX_FEAT(AMPDU), ++ PRINT_RWNX_FEAT(AMSDU), ++ PRINT_RWNX_FEAT(CHNL_CTXT), ++ PRINT_RWNX_FEAT(REORD), ++ PRINT_RWNX_FEAT(P2P), ++ PRINT_RWNX_FEAT(P2P_GO), ++ PRINT_RWNX_FEAT(UMAC), ++ PRINT_RWNX_FEAT(VHT), ++ PRINT_RWNX_FEAT(HE), ++ PRINT_RWNX_FEAT(BFMEE), ++ PRINT_RWNX_FEAT(BFMER), ++ PRINT_RWNX_FEAT(WAPI), ++ PRINT_RWNX_FEAT(MFP), ++ PRINT_RWNX_FEAT(MU_MIMO_RX), ++ PRINT_RWNX_FEAT(MU_MIMO_TX), ++ PRINT_RWNX_FEAT(MESH), ++ PRINT_RWNX_FEAT(TDLS), ++ PRINT_RWNX_FEAT(ANT_DIV)); ++#undef PRINT_RWNX_FEAT ++ ++ if (max_sta_nb != NX_REMOTE_STA_MAX) { ++ wiphy_err(wiphy, "Different number of supported stations between driver and FW (%d != %d)\n", ++ NX_REMOTE_STA_MAX, max_sta_nb); ++ res = -1; ++ } ++ ++ if (max_vif_nb != NX_VIRT_DEV_MAX) { ++ wiphy_err(wiphy, "Different number of supported virtual interfaces between driver and FW (%d != %d)\n", ++ NX_VIRT_DEV_MAX, max_vif_nb); ++ res = -1; ++ } ++ ++ return res; ++} ++#endif ++ ++ ++static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#ifdef CONFIG_VHT_FOR_OLD_KERNEL ++ #ifdef USE_5G ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ #endif ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ int mcs_map; ++ int mcs_map_max; ++ int bw_max; ++ ++ if (!rwnx_hw->mod_params->vht_on) { ++ return; ++ } ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ rwnx_hw->vht_cap_2G.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_2G.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_2G.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ rwnx_hw->vht_cap_2G.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_2G.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_2G.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif//CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_2G.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; ++ printk("%s, vht_capa_info=0x%x\n", __func__, rwnx_hw->vht_cap_2G.cap); ++#ifdef USE_5G ++ if (rwnx_hw->band_5g_support) { ++ rwnx_hw->vht_cap_5G.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_5G.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_5G.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ rwnx_hw->vht_cap_5G.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_5G.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_5G.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif//CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_5G.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; ++ } ++#endif//USE_5G ++ return; ++#else ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ int mcs_map; ++ int mcs_map_max; ++ int bw_max; ++#endif//CONFIG_VHT_FOR_OLD_KERNEL ++ ++ if (!rwnx_hw->mod_params->vht_on) { ++ return; ++ } ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ band_2GHz->vht_cap.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_2GHz->vht_cap.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ band_2GHz->vht_cap.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ band_2GHz->vht_cap.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_2GHz->vht_cap.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ band_2GHz->vht_cap.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_2GHz->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_2GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_2GHz->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_2GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif ++ band_2GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ band_5GHz->vht_cap.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_5GHz->vht_cap.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ band_5GHz->vht_cap.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ band_5GHz->vht_cap.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_5GHz->vht_cap.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ band_5GHz->vht_cap.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_5GHz->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_5GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_5GHz->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_5GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif ++ band_5GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ } ++} ++ ++static void rwnx_set_ht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ ++ if (!rwnx_hw->mod_params->ht_on) { ++ band_2GHz->ht_cap.ht_supported = false; ++ if (rwnx_hw->band_5g_support) ++ band_5GHz->ht_cap.ht_supported = false; ++ return; ++ } ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ if (rwnx_hw->mod_params->stbc_on) ++ band_2GHz->ht_cap.cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; ++ if (rwnx_hw->mod_params->ldpc_on) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; ++ if (rwnx_hw->mod_params->use_2040) { ++ band_2GHz->ht_cap.mcs.rx_mask[4] = 0x1; /* MCS32 */ ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(135 * nss); ++ } else { ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(65 * nss); ++ } ++ if (nss > 1) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; ++ ++ // Update the AMSDU max RX size ++ if (rwnx_hw->mod_params->amsdu_rx_max) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; ++ ++ if (rwnx_hw->mod_params->sgi) { ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; ++ if (rwnx_hw->mod_params->use_2040) { ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(150 * nss); ++ } else ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(72 * nss); ++ } ++ if (rwnx_hw->mod_params->gf_rx_on) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; ++ ++ for (i = 0; i < nss; i++) { ++ band_2GHz->ht_cap.mcs.rx_mask[i] = 0xFF; ++ } ++ ++ if (rwnx_hw->band_5g_support) ++ band_5GHz->ht_cap = band_2GHz->ht_cap; ++} ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++extern struct ieee80211_sband_iftype_data rwnx_he_capa; ++#endif ++static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++ struct ieee80211_sta_he_cap *he_cap; ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ int mcs_map; ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ he_cap = (struct ieee80211_sta_he_cap *) &rwnx_he_capa.he_cap; ++ he_cap->has_he = true; ++ he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK; ++ if (rwnx_hw->mod_params->use_2040) { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; ++ he_cap->ppe_thres[0] |= 0x10; ++ } ++ if (rwnx_hw->mod_params->use_80) { ++ he_cap->ppe_thres[0] |= 0x20; ++ he_cap->ppe_thres[2] |= 0xc0; ++ he_cap->ppe_thres[3] |= 0x01; ++ } ++ if (nss == 2) { ++ he_cap->ppe_thres[0] |= 0x01; ++ he_cap->ppe_thres[3] |= 0x70; ++ he_cap->ppe_thres[4] |= 0x1c; ++ he_cap->ppe_thres[5] |= 0x07; ++ } ++ //if (rwnx_hw->mod_params->use_80) ++ { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; ++ } ++ if (rwnx_hw->mod_params->ldpc_on) { ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; ++ } else { ++ // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory ++ // for MCS 10 and 11 ++ rwnx_hw->mod_params->he_mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US ++ | IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS; ++ ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS | ++ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #endif ++ if (rwnx_hw->mod_params->stbc_on) ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; ++ if (rwnx_hw->mod_params->bfmee) { ++ he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ he_cap->he_cap_elem.phy_cap_info[4] |= ++ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; ++ } ++ he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | ++ IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ //he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; ++ he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; ++ he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | ++ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9); ++ memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp)); ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ } ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, ++ // IEEE80211_HE_MCS_SUPPORT_0_7); ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ } ++ ++ return ; ++ #endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ struct ieee80211_sta_he_cap *he_cap; ++ int mcs_map; ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ if (!rwnx_hw->mod_params->he_on) { ++ band_2GHz->iftype_data = NULL; ++ band_2GHz->n_iftype_data = 0; ++ if (rwnx_hw->band_5g_support) { ++ band_5GHz->iftype_data = NULL; ++ band_5GHz->n_iftype_data = 0; ++ } ++ return; ++ } ++ he_cap = (struct ieee80211_sta_he_cap *) &band_2GHz->iftype_data->he_cap; ++ he_cap->has_he = true; ++ he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK; ++ if (rwnx_hw->mod_params->use_2040) { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; ++ he_cap->ppe_thres[0] |= 0x10; ++ } ++ if (rwnx_hw->mod_params->use_80) { ++ he_cap->ppe_thres[0] |= 0x20; ++ he_cap->ppe_thres[2] |= 0xc0; ++ he_cap->ppe_thres[3] |= 0x01; ++ } ++ if (nss == 2) { ++ he_cap->ppe_thres[0] |= 0x01; ++ he_cap->ppe_thres[3] |= 0x70; ++ he_cap->ppe_thres[4] |= 0x1c; ++ he_cap->ppe_thres[5] |= 0x07; ++ } ++ //if (rwnx_hw->mod_params->use_80) ++ { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; ++ } ++ if (rwnx_hw->mod_params->ldpc_on) { ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; ++ } else { ++ // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory ++ // for MCS 10 and 11 ++ rwnx_hw->mod_params->he_mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US ++ | IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS; ++ ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS | ++ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #endif ++ if (rwnx_hw->mod_params->stbc_on) ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; ++ #endif ++ ++ ++ if (rwnx_hw->mod_params->bfmee) { ++ he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ he_cap->he_cap_elem.phy_cap_info[4] |= ++ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; ++ } ++ he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | ++ IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #endif ++ ++ //he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; ++ he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | ++ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; ++ #endif ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ } ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp)); ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ } ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, ++ // IEEE80211_HE_MCS_SUPPORT_0_7); ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ he_cap = (struct ieee80211_sta_he_cap *) &band_5GHz->iftype_data->he_cap; ++ he_cap->has_he = true; ++ he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK; ++ if (rwnx_hw->mod_params->use_2040) { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; ++ he_cap->ppe_thres[0] |= 0x10; ++ } ++ if (rwnx_hw->mod_params->use_80) { ++ he_cap->ppe_thres[0] |= 0x20; ++ he_cap->ppe_thres[2] |= 0xc0; ++ he_cap->ppe_thres[3] |= 0x01; ++ } ++ if (nss == 2) { ++ he_cap->ppe_thres[0] |= 0x01; ++ he_cap->ppe_thres[3] |= 0x70; ++ he_cap->ppe_thres[4] |= 0x1c; ++ he_cap->ppe_thres[5] |= 0x07; ++ } ++ //if (rwnx_hw->mod_params->use_80) ++ { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; ++ } ++ if (rwnx_hw->mod_params->ldpc_on) { ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; ++ } else { ++ // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory ++ // for MCS 10 and 11 ++ rwnx_hw->mod_params->he_mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US | ++ IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS | ++ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #endif ++ if (rwnx_hw->mod_params->stbc_on) ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; ++ #endif ++ ++ if (rwnx_hw->mod_params->bfmee) { ++ he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ he_cap->he_cap_elem.phy_cap_info[4] |= ++ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; ++ } ++ he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | ++ IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #endif ++ ++ //he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; ++ he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | ++ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; ++ #endif ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9); ++ memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp)); ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ } ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, ++ // IEEE80211_HE_MCS_SUPPORT_0_7); ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ } ++ } ++#endif ++} ++ ++static void rwnx_set_wiphy_params(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) ++ struct ieee80211_regdomain *regdomain; ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ /* FULLMAC specific parameters */ ++ wiphy->flags |= WIPHY_FLAG_REPORTS_OBSS; ++ wiphy->max_scan_ssids = SCAN_SSID_MAX; ++ wiphy->max_scan_ie_len = SCANU_MAX_IE_LEN; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (rwnx_hw->mod_params->tdls) { ++ /* TDLS support */ ++ wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; ++#ifdef CONFIG_RWNX_FULLMAC ++ /* TDLS external setup support */ ++ wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; ++#endif ++ } ++ ++ if (rwnx_hw->mod_params->ap_uapsd_on) ++ wiphy->flags |= WIPHY_FLAG_AP_UAPSD; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (rwnx_hw->mod_params->ps_on) ++ wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; ++ else ++ wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; ++#endif ++ ++if (rwnx_hw->mod_params->custregd) { ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ // Apply custom regulatory. Note that for recent kernel versions we use instead the ++ // REGULATORY_WIPHY_SELF_MANAGED flag, along with the regulatory_set_wiphy_regd() ++ // function, that needs to be called after wiphy registration ++ memcpy(country_code, default_ccode, sizeof(default_ccode)); ++ regdomain = getRegdomainFromRwnxDB(wiphy, default_ccode); ++ printk(KERN_CRIT ++ "\n\n%s: CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES\n\n", ++ __func__); ++ wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; ++ /* From kernel 6.5.0, this bit is removed and will be reused later */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 39) || LINUX_VERSION_CODE > KERNEL_VERSION(6, 2, 0)) ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) */ ++ wiphy_apply_custom_regulatory(wiphy, regdomain); ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) ++ memcpy(country_code, default_ccode, sizeof(default_ccode)); ++ regdomain = getRegdomainFromRwnxDB(wiphy, default_ccode); ++ printk(KERN_CRIT"%s: Registering custom regulatory\n", __func__); ++ wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; ++ wiphy_apply_custom_regulatory(wiphy, regdomain); ++#endif ++ // Check if custom channel set shall be enabled. In such case only monitor mode is ++ // supported ++ if (rwnx_hw->mod_params->custchan) { ++ wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR); ++ ++ // Enable "extra" channels ++ wiphy->bands[NL80211_BAND_2GHZ]->n_channels += 13; ++ //#ifdef USE_5G ++ if(rwnx_hw->band_5g_support){ ++ wiphy->bands[NL80211_BAND_5GHZ]->n_channels += 59; ++ } ++ //#endif ++ } ++ } ++ ++#if 0 ++ if (rwnx_hw->mod_params->custregd) { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ // Apply custom regulatory. Note that for recent kernel versions we use instead the ++ // REGULATORY_WIPHY_SELF_MANAGED flag, along with the regulatory_set_wiphy_regd() ++ // function, that needs to be called after wiphy registration ++ printk(KERN_CRIT ++ "\n\n%s: CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES\n\n", ++ __func__); ++ wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; ++ /* From kernel 6.5.0, this bit is removed and will be reused later */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 39) || LINUX_VERSION_CODE > KERNEL_VERSION(6, 2, 0)) ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) */ ++ wiphy_apply_custom_regulatory(wiphy, &rwnx_regdom); ++#endif ++ // Check if custom channel set shall be enabled. In such case only monitor mode is ++ // supported ++ if (rwnx_hw->mod_params->custchan) { ++ wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR); ++ ++ // Enable "extra" channels ++ wiphy->bands[NL80211_BAND_2GHZ]->n_channels += 13; ++ if (rwnx_hw->band_5g_support) ++ wiphy->bands[NL80211_BAND_5GHZ]->n_channels += 59; ++ } ++ } ++#endif ++} ++ ++#if 0 ++static void rwnx_set_rf_params(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#ifndef CONFIG_RWNX_SDM ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ u32 mdm_phy_cfg = __MDM_PHYCFG_FROM_VERS(rwnx_hw->version_cfm.version_phy_1); ++ ++ /* ++ * Get configuration file depending on the RF ++ */ ++ if (mdm_phy_cfg == MDM_PHY_CONFIG_TRIDENT) { ++ struct rwnx_phy_conf_file phy_conf; ++ // Retrieve the Trident configuration ++ rwnx_parse_phy_configfile(rwnx_hw, RWNX_PHY_CONFIG_TRD_NAME, ++ &phy_conf, rwnx_hw->mod_params->phy_cfg); ++ memcpy(&rwnx_hw->phy.cfg, &phy_conf.trd, sizeof(phy_conf.trd)); ++ } else if (mdm_phy_cfg == MDM_PHY_CONFIG_ELMA) { ++ } else if (mdm_phy_cfg == MDM_PHY_CONFIG_KARST) { ++ struct rwnx_phy_conf_file phy_conf; ++ // We use the NSS parameter as is ++ // Retrieve the Karst configuration ++ rwnx_parse_phy_configfile(rwnx_hw, RWNX_PHY_CONFIG_KARST_NAME, ++ &phy_conf, rwnx_hw->mod_params->phy_cfg); ++ ++ memcpy(&rwnx_hw->phy.cfg, &phy_conf.karst, sizeof(phy_conf.karst)); ++ } else { ++ WARN_ON(1); ++ } ++ ++ /* ++ * adjust caps depending on the RF ++ */ ++ switch (mdm_phy_cfg) { ++ case MDM_PHY_CONFIG_TRIDENT: ++ { ++ wiphy_dbg(wiphy, "found Trident phy .. limit BW to 40MHz\n"); ++ rwnx_hw->phy.limit_bw = true; ++ if (rwnx_hw->band_5g_support) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif ++ band_5GHz->vht_cap.cap &= ~(IEEE80211_VHT_CAP_SHORT_GI_80 | ++ IEEE80211_VHT_CAP_RXSTBC_MASK); ++ } ++ break; ++ } ++ case MDM_PHY_CONFIG_ELMA: ++ wiphy_dbg(wiphy, "found ELMA phy .. disabling 2.4GHz and greenfield rx\n"); ++ wiphy->bands[NL80211_BAND_2GHZ] = NULL; ++ band_2GHz->ht_cap.cap &= ~IEEE80211_HT_CAP_GRN_FLD; ++ if (rwnx_hw->band_5g_support) { ++ band_5GHz->ht_cap.cap &= ~IEEE80211_HT_CAP_GRN_FLD; ++ band_5GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_RXSTBC_MASK; ++ } ++ break; ++ case MDM_PHY_CONFIG_KARST: ++ { ++ wiphy_dbg(wiphy, "found KARST phy\n"); ++ break; ++ } ++ default: ++ WARN_ON(1); ++ break; ++ } ++#endif /* CONFIG_RWNX_SDM */ ++} ++#endif ++ ++int rwnx_handle_dynparams(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#if 0 ++ /* Check compatibility between requested parameters and HW/SW features */ ++ int ret; ++ ++ ret = rwnx_check_fw_hw_feature(rwnx_hw, wiphy); ++ if (ret) ++ return ret; ++ ++ /* Allocate the RX buffers according to the maximum AMSDU RX size */ ++ ret = rwnx_ipc_rxbuf_init(rwnx_hw, ++ (4 * (rwnx_hw->mod_params->amsdu_rx_max + 1) + 1) * 1024); ++ if (ret) { ++ wiphy_err(wiphy, "Cannot allocate the RX buffers\n"); ++ return ret; ++ } ++#endif ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rwnx_hw->mod_params->sgi80 = true; ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80 && rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80X2 && ++ rwnx_hw->mod_params->he_mcs_map == IEEE80211_HE_MCS_SUPPORT_0_11) { ++ AICWFDBG(LOGINFO,"%s unsupport mcs11 change to mcs9", __func__); ++ rwnx_hw->mod_params->he_mcs_map = IEEE80211_HE_MCS_SUPPORT_0_9; ++ } ++ ++ /* Set wiphy parameters */ ++ rwnx_set_wiphy_params(rwnx_hw, wiphy); ++ /* Set VHT capabilities */ ++ rwnx_set_vht_capa(rwnx_hw, wiphy); ++ /* Set HE capabilities */ ++ rwnx_set_he_capa(rwnx_hw, wiphy); ++ /* Set HT capabilities */ ++ rwnx_set_ht_capa(rwnx_hw, wiphy); ++ /* Set RF specific parameters (shall be done last as it might change some ++ capabilities previously set) */ ++#if 0 ++ rwnx_set_rf_params(rwnx_hw, wiphy); ++#endif ++ return 0; ++} ++ ++void rwnx_custregd(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++// For older kernel version, the custom regulatory is applied before the wiphy ++// registration (in rwnx_set_wiphy_params()), so nothing has to be done here ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ if (!rwnx_hw->mod_params->custregd) ++ return; ++ ++ /* From kernel 6.5.0, this bit is removed and will be reused later */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 39) || LINUX_VERSION_CODE > KERNEL_VERSION(6, 2, 0)) ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) */ ++ wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; ++ ++ rtnl_lock(); ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) ++ if (regulatory_set_wiphy_regd_sync(wiphy, getRegdomainFromRwnxDB(wiphy, default_ccode))){ ++ wiphy_err(wiphy, "Failed to set custom regdomain\n"); ++ } ++ #else ++ if (regulatory_set_wiphy_regd_sync_rtnl(wiphy, getRegdomainFromRwnxDB(wiphy, default_ccode))){ ++ wiphy_err(wiphy, "Failed to set custom regdomain\n"); ++ } ++ #endif ++ ++ else{ ++ wiphy_err(wiphy,"\n" ++ "*******************************************************\n" ++ "** CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES **\n" ++ "*******************************************************\n"); ++ } ++ rtnl_unlock(); ++#endif ++ ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h +new file mode 100644 +index 000000000000..ef31093fcadb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h +@@ -0,0 +1,76 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_mod_params.h ++ * ++ * @brief Declaration of module parameters ++ * ++ * Copyright (C) RivieraWaves 2012-2021 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_MOD_PARAM_H_ ++#define _RWNX_MOD_PARAM_H_ ++ ++struct rwnx_mod_params { ++ bool ht_on; ++ bool vht_on; ++ bool he_on; ++ int mcs_map; ++ int he_mcs_map; ++ bool he_ul_on; ++ bool ldpc_on; ++ bool stbc_on; ++ bool gf_rx_on; ++ int phy_cfg; ++ int uapsd_timeout; ++ bool ap_uapsd_on; ++ bool sgi; ++ bool sgi80; ++ bool use_2040; ++ bool use_80; ++ bool custregd; ++ bool custchan; ++ int nss; ++ int amsdu_rx_max; ++ bool bfmee; ++ bool bfmer; ++ bool mesh; ++ bool murx; ++ bool mutx; ++ bool mutx_on; ++ unsigned int roc_dur_max; ++ int listen_itv; ++ bool listen_bcmc; ++ int lp_clk_ppm; ++ bool ps_on; ++ int tx_lft; ++ int amsdu_maxnb; ++ int uapsd_queues; ++ bool tdls; ++ bool uf; ++ bool auto_reply; ++ char *ftl; ++ bool dpsm; ++#ifdef CONFIG_RWNX_FULLMAC ++ bool ant_div; ++#endif /* CONFIG_RWNX_FULLMAC */ ++}; ++ ++extern struct rwnx_mod_params rwnx_mod_params; ++ ++struct rwnx_hw; ++struct wiphy; ++int rwnx_handle_dynparams(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy); ++void rwnx_custregd(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy); ++void rwnx_enable_wapi(struct rwnx_hw *rwnx_hw); ++void rwnx_enable_mfp(struct rwnx_hw *rwnx_hw); ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, ++ char *alpha2); ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, ++ int index); ++ ++ ++#endif /* _RWNX_MOD_PARAM_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c +new file mode 100644 +index 000000000000..1799d7dde4cd +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c +@@ -0,0 +1,1557 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_msg_rx.c ++ * ++ * @brief RX function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2021 ++ * ++ **************************************************************************************** ++ */ ++#include ++#include "rwnx_defs.h" ++#include "rwnx_prof.h" ++#include "rwnx_tx.h" ++#ifdef CONFIG_RWNX_BFMER ++#include "rwnx_bfmer.h" ++#endif //(CONFIG_RWNX_BFMER) ++#ifdef CONFIG_RWNX_FULLMAC ++#include "rwnx_debugfs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_tdls.h" ++#endif /* CONFIG_RWNX_FULLMAC */ ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "aicwf_txrxif.h" ++#include "rwnx_msg_rx.h" ++#ifdef CONFIG_SDIO_BT ++#include "aic_btsdio.h" ++#endif ++void rwnx_cfg80211_unlink_bss(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif); ++ ++static int rwnx_freq_to_idx(struct rwnx_hw *rwnx_hw, int freq) ++{ ++ struct ieee80211_supported_band *sband = NULL; ++ int band, ch, idx = 0; ++ ++ for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { ++#ifdef CONFIG_RWNX_FULLMAC ++ sband = rwnx_hw->wiphy->bands[band]; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ if (!sband) { ++ continue; ++ } ++ ++ for (ch = 0; ch < sband->n_channels; ch++, idx++) { ++ if (sband->channels[ch].center_freq == freq) { ++ goto exit; ++ } ++ } ++ } ++ ++ BUG_ON(1); ++ ++exit: ++ // Channel has been found, return the index ++ return idx; ++} ++ ++/*************************************************************************** ++ * Messages from MM task ++ **************************************************************************/ ++static inline int rwnx_rx_chan_pre_switch_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ int chan_idx = ((struct mm_channel_pre_switch_ind *)msg->param)->chan_index; ++ ++ REG_SW_SET_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->up && rwnx_vif->ch_index == chan_idx) { ++ rwnx_txq_vif_stop(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ REG_SW_CLEAR_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT); ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_chan_switch_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ int chan_idx = ((struct mm_channel_switch_ind *)msg->param)->chan_index; ++ bool roc = ((struct mm_channel_switch_ind *)msg->param)->roc; ++ bool roc_tdls = ((struct mm_channel_switch_ind *)msg->param)->roc_tdls; ++ ++ REG_SW_SET_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (roc_tdls) { ++ u8 vif_index = ((struct mm_channel_switch_ind *)msg->param)->vif_index; ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == vif_index) { ++ rwnx_vif->roc_tdls = true; ++ rwnx_txq_tdls_sta_start(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ } else if (!roc) { ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->up && rwnx_vif->ch_index == chan_idx) { ++ rwnx_txq_vif_start(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ } else { ++ /* Retrieve the allocated RoC element */ ++ struct rwnx_roc_elem *roc_elem = rwnx_hw->roc_elem; ++ /* Get VIF on which RoC has been started */ ++ //rwnx_vif = netdev_priv(roc_elem->wdev->netdev); ++ ++ /* For debug purpose (use ftrace kernel option) */ ++ //trace_switch_roc(rwnx_vif->vif_index); ++ ++ if(roc_elem) { ++ /* If mgmt_roc is true, remain on channel has been started by ourself */ ++ if (!roc_elem->mgmt_roc) { ++ /* Inform the host that we have switch on the indicated off-channel */ ++ cfg80211_ready_on_channel(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), ++ roc_elem->chan, roc_elem->duration, GFP_ATOMIC); ++ } ++ ++ /* Keep in mind that we have switched on the channel */ ++ roc_elem->on_chan = true; ++ } else { ++ printk("roc_elem == null\n"); ++ } ++ // Enable traffic on OFF channel queue ++ rwnx_txq_offchan_start(rwnx_hw); ++ } ++ ++ tasklet_schedule(&rwnx_hw->task); ++ ++ rwnx_hw->cur_chanctx = chan_idx; ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ REG_SW_CLEAR_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT); ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_tdls_chan_switch_cfm(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ return 0; ++} ++ ++static inline int rwnx_rx_tdls_chan_switch_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ // Enable traffic on OFF channel queue ++ rwnx_txq_offchan_start(rwnx_hw); ++ ++ return 0; ++#endif ++} ++ ++static inline int rwnx_rx_tdls_chan_switch_base_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ u8 vif_index = ((struct tdls_chan_switch_base_ind *)msg->param)->vif_index; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == vif_index) { ++ rwnx_vif->roc_tdls = false; ++ rwnx_txq_tdls_sta_stop(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ return 0; ++#endif ++} ++ ++static inline int rwnx_rx_tdls_peer_ps_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ u8 vif_index = ((struct tdls_peer_ps_ind *)msg->param)->vif_index; ++ bool ps_on = ((struct tdls_peer_ps_ind *)msg->param)->ps_on; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == vif_index) { ++ rwnx_vif->sta.tdls_sta->tdls.ps_on = ps_on; ++ // Update PS status for the TDLS station ++ rwnx_ps_bh_enable(rwnx_hw, rwnx_vif->sta.tdls_sta, ps_on); ++ } ++ } ++ ++ return 0; ++#endif ++} ++ ++static inline int rwnx_rx_remain_on_channel_exp_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ /* Retrieve the allocated RoC element */ ++ struct rwnx_roc_elem *roc_elem = rwnx_hw->roc_elem; ++ /* Get VIF on which RoC has been started */ ++ struct rwnx_vif *rwnx_vif; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (!roc_elem) ++ return 0; ++ ++ rwnx_vif = container_of(roc_elem->wdev, struct rwnx_vif, wdev); ++ /* For debug purpose (use ftrace kernel option) */ ++#ifdef CREATE_TRACE_POINTS ++ trace_roc_exp(rwnx_vif->vif_index); ++#endif ++ /* If mgmt_roc is true, remain on channel has been started by ourself */ ++ /* If RoC has been cancelled before we switched on channel, do not call cfg80211 */ ++ if (!roc_elem->mgmt_roc && roc_elem->on_chan) { ++ /* Inform the host that off-channel period has expired */ ++ cfg80211_remain_on_channel_expired(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), ++ roc_elem->chan, GFP_ATOMIC); ++ } ++ ++ /* De-init offchannel TX queue */ ++ rwnx_txq_offchan_deinit(rwnx_vif); ++ ++ /* Increase the cookie counter cannot be zero */ ++ rwnx_hw->roc_cookie_cnt++; ++ ++ if (rwnx_hw->roc_cookie_cnt == 0) { ++ rwnx_hw->roc_cookie_cnt = 1; ++ } ++ ++ /* Free the allocated RoC element */ ++ kfree(roc_elem); ++ rwnx_hw->roc_elem = NULL; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ return 0; ++} ++ ++static inline int rwnx_rx_p2p_vif_ps_change_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ int vif_idx = ((struct mm_p2p_vif_ps_change_ind *)msg->param)->vif_index; ++ int ps_state = ((struct mm_p2p_vif_ps_change_ind *)msg->param)->ps_state; ++ struct rwnx_vif *vif_entry; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ vif_entry = rwnx_hw->vif_table[vif_idx]; ++ ++ if (vif_entry) { ++ goto found_vif; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ goto exit; ++ ++found_vif: ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (ps_state == MM_PS_MODE_OFF) { ++ // Start TX queues for provided VIF ++ rwnx_txq_vif_start(vif_entry, RWNX_TXQ_STOP_VIF_PS, rwnx_hw); ++ tasklet_schedule(&rwnx_hw->task); ++ } else { ++ // Stop TX queues for provided VIF ++ rwnx_txq_vif_stop(vif_entry, RWNX_TXQ_STOP_VIF_PS, rwnx_hw); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++exit: ++ return 0; ++} ++ ++static inline int rwnx_rx_channel_survey_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_channel_survey_ind *ind = (struct mm_channel_survey_ind *)msg->param; ++ // Get the channel index ++ int idx = rwnx_freq_to_idx(rwnx_hw, ind->freq); ++ // Get the survey ++ struct rwnx_survey_info *rwnx_survey; ++ ++ if (idx > ARRAY_SIZE(rwnx_hw->survey)) ++ return 0; ++ ++ rwnx_survey = &rwnx_hw->survey[idx]; ++ ++ // Store the received parameters ++ rwnx_survey->chan_time_ms = ind->chan_time_ms; ++ rwnx_survey->chan_time_busy_ms = ind->chan_time_busy_ms; ++ rwnx_survey->noise_dbm = ind->noise_dbm; ++ rwnx_survey->filled = (SURVEY_INFO_TIME | ++ SURVEY_INFO_TIME_BUSY); ++ ++ if (ind->noise_dbm != 0) { ++ rwnx_survey->filled |= SURVEY_INFO_NOISE_DBM; ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_p2p_noa_upd_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ return 0; ++} ++ ++static inline int rwnx_rx_rssi_status_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_rssi_status_ind *ind = (struct mm_rssi_status_ind *)msg->param; ++ int vif_idx = ind->vif_index; ++ bool rssi_status = ind->rssi_status; ++ ++ struct rwnx_vif *vif_entry; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++vif_entry = rwnx_hw->vif_table[vif_idx]; ++ if (vif_entry) { ++ cfg80211_cqm_rssi_notify(vif_entry->ndev, ++ rssi_status ? NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW : ++ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, ++ ind->rssi, GFP_ATOMIC); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_pktloss_notify_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct mm_pktloss_ind *ind = (struct mm_pktloss_ind *)msg->param; ++ struct rwnx_vif *vif_entry; ++ int vif_idx = ind->vif_index; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ vif_entry = rwnx_hw->vif_table[vif_idx]; ++ if (vif_entry) { ++ cfg80211_cqm_pktloss_notify(vif_entry->ndev, (const u8 *)ind->mac_addr.array, ++ ind->num_packets, GFP_ATOMIC); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ return 0; ++} ++ ++static inline int rwnx_radar_detect_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct radar_pulse_array_desc *pulses = (struct radar_pulse_array_desc *)msg->param; ++ int i; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ //printk("%s\n", __func__); ++ ++ if(pulses->cnt == 0) { ++ printk("cnt error\n"); ++ return -1; ++ } ++ ++ if(rwnx_radar_detection_is_enable(&rwnx_hw->radar, pulses->idx)) { ++ for(i=0; icnt; i++) { ++ struct rwnx_radar_pulses *p = &rwnx_hw->radar.pulses[pulses->idx]; ++ ++ p->buffer[p->index] = pulses->pulse[i]; ++ p->index = (p->index + 1)%RWNX_RADAR_PULSE_MAX; ++ if(p->count < RWNX_RADAR_PULSE_MAX) ++ p->count++; ++ //printk("pulse=%x\n", pulses->pulse[i]); ++ } ++ ++ if(!work_pending(&rwnx_hw->radar.detection_work)) ++ schedule_work(&rwnx_hw->radar.detection_work); ++ } else ++ printk("not enable\n"); ++ ++ return 0; ++} ++ ++static inline int rwnx_apm_staloss_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_apm_staloss_ind *ind = (struct mm_apm_staloss_ind *)msg->param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ memcpy(rwnx_hw->sta_mac_addr, ind->mac_addr, 6); ++ rwnx_hw->apm_vif_idx = ind->vif_idx; ++ ++ queue_work(rwnx_hw->apmStaloss_wq, &rwnx_hw->apmStalossWork); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SDIO_BT ++static inline int rwnx_bt_recv_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_bt_recv_ind *ind = (struct mm_bt_recv_ind *)msg->param; ++ ++ bt_sdio_recv(ind->bt_data,ind->data_len); ++ return 0; ++} ++#endif ++ ++static inline int rwnx_rx_csa_counter_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_csa_counter_ind *ind = (struct mm_csa_counter_ind *)msg->param; ++ struct rwnx_vif *vif; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ if (vif->vif_index == ind->vif_index) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (vif->ap.csa) ++ vif->ap.csa->count = ind->csa_count; ++ else ++ netdev_err(vif->ndev, "CSA counter update but no active CSA"); ++ ++#endif ++ } ++ ++ return 0; ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline int rwnx_rx_csa_finish_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_csa_finish_ind *ind = (struct mm_csa_finish_ind *)msg->param; ++ struct rwnx_vif *vif; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ if (vif->vif_index == ind->vif_index) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) { ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP || ++ RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_GO) { ++ if (vif->ap.csa) { ++ vif->ap.csa->status = ind->status; ++ vif->ap.csa->ch_idx = ind->chan_idx; ++ schedule_work(&vif->ap.csa->work); ++ } else ++ netdev_err(vif->ndev, "CSA finish indication but no active CSA"); ++ } else { ++ if (ind->status == 0) { ++ rwnx_chanctx_unlink(vif); ++ rwnx_chanctx_link(vif, ind->chan_idx, NULL); ++ if (rwnx_hw->cur_chanctx == ind->chan_idx) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ rwnx_txq_vif_start(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } else ++ rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_csa_traffic_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_csa_traffic_ind *ind = (struct mm_csa_traffic_ind *)msg->param; ++ struct rwnx_vif *vif; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ if (vif->vif_index == ind->vif_index) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) { ++ if (ind->enable) ++ rwnx_txq_vif_start(vif, RWNX_TXQ_STOP_CSA, rwnx_hw); ++ else ++ rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CSA, rwnx_hw); ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_ps_change_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_ps_change_ind *ind = (struct mm_ps_change_ind *)msg->param; ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[ind->sta_idx]; ++ ++ if (ind->sta_idx >= (NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX)) { ++ wiphy_err(rwnx_hw->wiphy, "Invalid sta index reported by fw %d\n", ++ ind->sta_idx); ++ return 1; ++ } ++ ++ netdev_dbg(rwnx_hw->vif_table[sta->vif_idx]->ndev, ++ "Sta %d, change PS mode to %s", sta->sta_idx, ++ ind->ps_state ? "ON" : "OFF"); ++ ++ if (sta->valid) { ++ rwnx_ps_bh_enable(rwnx_hw, sta, ind->ps_state); ++ } else if (rwnx_hw->adding_sta) { ++ sta->ps.active = ind->ps_state ? true : false; ++ } else { ++ if (rwnx_hw->vif_table[sta->vif_idx] && rwnx_hw->vif_table[sta->vif_idx]->ndev) ++ netdev_err(rwnx_hw->vif_table[sta->vif_idx]->ndev, ++ "Ignore PS mode change on invalid sta\n"); ++ } ++ ++ return 0; ++} ++ ++ ++static inline int rwnx_rx_traffic_req_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_traffic_req_ind *ind = (struct mm_traffic_req_ind *)msg->param; ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[ind->sta_idx]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ netdev_dbg(rwnx_hw->vif_table[sta->vif_idx]->ndev, ++ "Sta %d, asked for %d pkt", sta->sta_idx, ind->pkt_cnt); ++ ++ rwnx_ps_bh_traffic_req(rwnx_hw, sta, ind->pkt_cnt, ++ ind->uapsd ? UAPSD_ID : LEGACY_PS_ID); ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from SCAN task ++ **************************************************************************/ ++#if 0 ++static inline int rwnx_rx_scan_done_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = false, ++ }; ++#endif ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_ipc_elem_var_deallocs(rwnx_hw, &rwnx_hw->scan_ie); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ ieee80211_scan_completed(rwnx_hw->hw, &info); ++#else ++ ieee80211_scan_completed(rwnx_hw->hw, false); ++#endif ++ ++ return 0; ++} ++#endif ++ ++/*************************************************************************** ++ * Messages from SCANU task ++ **************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++extern uint8_t scanning; ++static inline int rwnx_rx_scanu_start_cfm(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (rwnx_hw->scan_request ++#ifdef CONFIG_SCHED_SCAN ++ && !rwnx_hw->is_sched_scan ++#endif//CONFIG_SCHED_SCAN ++ ) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = false, ++ }; ++ ++ cfg80211_scan_done(rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(rwnx_hw->scan_request, false); ++#endif ++ } ++ ++#ifdef CONFIG_SCHED_SCAN ++ if(rwnx_hw->is_sched_scan){ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ AICWFDBG(LOGINFO, "%s cfg80211_sched_scan_results \r\n", __func__); ++ cfg80211_sched_scan_results(rwnx_hw->scan_request->wiphy, ++ rwnx_hw->sched_scan_req->reqid); ++#else ++ cfg80211_sched_scan_results(rwnx_hw->sched_scan_req->wiphy); ++#endif ++ kfree(rwnx_hw->scan_request); ++ rwnx_hw->is_sched_scan = false; ++ } ++#endif//CONFIG_SCHED_SCAN ++ ++ rwnx_hw->scan_request = NULL; ++ scanning = 0; ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_scanu_result_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct cfg80211_bss *bss = NULL; ++ struct ieee80211_channel *chan; ++ struct scanu_result_ind *ind = (struct scanu_result_ind *)msg->param; ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)ind->payload; ++ u64 tsf; ++ u8 *ie; ++ size_t ielen; ++ u16 capability, beacon_interval; ++ u16 len = ind->length; ++ ++ chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq); ++ ++ if (chan != NULL) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ struct timespec ts; ++ get_monotonic_boottime(&ts); ++ tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000); ++ mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000) + ts.tv_nsec/1000; ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0) ++ struct timespec ts; ++ ts = ktime_to_timespec(ktime_get_boottime()); ++ tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000); ++ mgmt->u.probe_resp.timestamp = tsf; ++#else ++ struct timespec64 ts; ++ ts = ktime_to_timespec64(ktime_get_boottime()); ++ tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000); ++ mgmt->u.probe_resp.timestamp = tsf; ++#endif ++ ie = mgmt->u.probe_resp.variable; ++ ielen = len - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); ++ beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); ++ capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); ++ /* framework use system bootup time */ ++ bss = cfg80211_inform_bss(rwnx_hw->wiphy, chan, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) ++ CFG80211_BSS_FTYPE_UNKNOWN, ++#endif ++ mgmt->bssid, tsf, capability, beacon_interval, ++ ie, ielen, ind->rssi * 100, GFP_ATOMIC); ++ } ++ ++ if (bss != NULL) ++ cfg80211_put_bss(rwnx_hw->wiphy, bss); ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from ME task ++ **************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline int rwnx_rx_me_tkip_mic_failure_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct me_tkip_mic_failure_ind *ind = (struct me_tkip_mic_failure_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct net_device *dev = rwnx_vif->ndev; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ cfg80211_michael_mic_failure(dev, (u8 *)&ind->addr, (ind->ga ? NL80211_KEYTYPE_GROUP : ++ NL80211_KEYTYPE_PAIRWISE), ind->keyid, ++ (u8 *)&ind->tsc, GFP_ATOMIC); ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_me_tx_credits_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct me_tx_credits_update_ind *ind = (struct me_tx_credits_update_ind *)msg->param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_txq_credit_update(rwnx_hw, ind->sta_idx, ind->tid, ind->credits); ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from SM task ++ **************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct sm_connect_ind *ind = (struct sm_connect_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct net_device *dev = rwnx_vif->ndev; ++ const u8 *req_ie, *rsp_ie; ++ const u8 *extcap_ie; ++ const struct ieee_types_extcap *extcap; ++ struct ieee80211_channel *chan; ++ //struct cfg80211_bss *bss = NULL; ++ struct wireless_dev *wdev = NULL; ++ //int retry_counter = 10; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ wdev = dev->ieee80211_ptr; ++ ++ /* Retrieve IE addresses and lengths */ ++ req_ie = (const u8 *)ind->assoc_ie_buf; ++ rsp_ie = req_ie + ind->assoc_req_ie_len; ++ ++ // Fill-in the AP information ++ AICWFDBG(LOGINFO, "%s ind->status_code:%d \r\n", __func__, ind->status_code); ++ ++ if (ind->status_code == 0) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[ind->ap_idx]; ++ u8 txq_status; ++ struct cfg80211_chan_def chandef; ++ ++ sta->valid = true; ++ sta->sta_idx = ind->ap_idx; ++ sta->ch_idx = ind->ch_idx; ++ sta->vif_idx = ind->vif_idx; ++ sta->vlan_idx = sta->vif_idx; ++ sta->qos = ind->qos; ++ sta->acm = ind->acm; ++ sta->ps.active = false; ++ sta->aid = ind->aid; ++ sta->band = ind->band;//ind->chan.band; ++ sta->width = ind->width;//ind->chan.type; ++ sta->center_freq = ind->center_freq;//ind->chan.prim20_freq; ++ sta->center_freq1 = ind->center_freq1;//ind->chan.center1_freq; ++ sta->center_freq2 = ind->center_freq2;//ind->chan.center2_freq; ++ rwnx_vif->sta.ap = sta; ++ chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq);//ind->chan.prim20_freq); ++ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); ++ if (!rwnx_hw->mod_params->ht_on) ++ chandef.width = NL80211_CHAN_WIDTH_20_NOHT; ++ else ++ chandef.width = chnl2bw[ind->width];//[ind->chan.type]; ++ chandef.center_freq1 = ind->center_freq1;//ind->chan.center1_freq; ++ chandef.center_freq2 = ind->center_freq2;//ind->chan.center2_freq; ++ rwnx_chanctx_link(rwnx_vif, ind->ch_idx, &chandef); ++ memcpy(sta->mac_addr, ind->bssid.array, ETH_ALEN); ++ if (ind->ch_idx == rwnx_hw->cur_chanctx) { ++ txq_status = 0; ++ } else { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ memcpy(sta->ac_param, ind->ac_param, sizeof(sta->ac_param)); ++ rwnx_txq_sta_init(rwnx_hw, sta, txq_status); ++ rwnx_txq_tdls_vif_init(rwnx_vif); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, sta); ++#endif ++ rwnx_mu_group_sta_init(sta, NULL); ++ /* Look for TDLS Channel Switch Prohibited flag in the Extended Capability ++ * Information Element*/ ++ extcap_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, rsp_ie, ind->assoc_rsp_ie_len); ++ if (extcap_ie && extcap_ie[1] >= 5) { ++ extcap = (void *)(extcap_ie); ++ rwnx_vif->tdls_chsw_prohibited = extcap->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED; ++ } ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ if (chan->flags & IEEE80211_CHAN_RADAR) ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_REPORT, ++ RWNX_RADAR_RIU); ++#endif ++ ++ if (rwnx_vif->wep_enabled) ++ rwnx_vif->wep_auth_err = false; ++ ++#ifdef CONFIG_RWNX_BFMER ++ /* If Beamformer feature is activated, check if features can be used ++ * with the new peer device ++ */ ++ if (rwnx_hw->mod_params->bfmer) { ++ const u8 *vht_capa_ie; ++ const struct ieee80211_vht_cap *vht_cap; ++ ++ do { ++ /* Look for VHT Capability Information Element */ ++ vht_capa_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, rsp_ie, ++ ind->assoc_rsp_ie_len); ++ ++ /* Stop here if peer device does not support VHT */ ++ if (!vht_capa_ie) { ++ break; ++ } ++ ++ vht_cap = (const struct ieee80211_vht_cap *)(vht_capa_ie + 2); ++ ++ /* Send MM_BFMER_ENABLE_REQ message if needed */ ++ rwnx_send_bfmer_enable(rwnx_hw, sta, vht_cap); ++ } while (0); ++ } ++#endif //(CONFIG_RWNX_BFMER) ++ ++#ifdef CONFIG_RWNX_MON_DATA ++ // If there are 1 sta and 1 monitor interface active at the same time then ++ // monitor interface channel context is always the same as the STA interface. ++ // This doesn't work with 2 STA interfaces but we don't want to support it. ++ if (rwnx_hw->monitor_vif != RWNX_INVALID_VIF) { ++ struct rwnx_vif *rwnx_mon_vif = rwnx_hw->vif_table[rwnx_hw->monitor_vif]; ++ rwnx_chanctx_unlink(rwnx_mon_vif); ++ rwnx_chanctx_link(rwnx_mon_vif, ind->ch_idx, NULL); ++ } ++#endif ++ //atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ } else if (ind->status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { ++ if (rwnx_vif->wep_enabled) { ++ rwnx_vif->wep_auth_err = true; ++ AICWFDBG(LOGINFO, "con ind wep_auth_err %d\n", rwnx_vif->wep_auth_err); ++ } ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ }else{ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ } ++ ++ AICWFDBG(LOGINFO, "%s ind->roamed:%d ind->status_code:%d rwnx_vif->drv_conn_state:%d\r\n", ++ __func__, ++ ind->roamed, ++ ind->status_code, ++ (int)atomic_read(&rwnx_vif->drv_conn_state)); ++ ++ if(ind->status_code == 0 && (int)atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTING){ ++ AICWFDBG(LOGINFO, "%s the disconnection has been requested, return it\r\n", __func__); ++ goto exit; ++ } ++ ++ if (!ind->roamed){//not roaming ++ cfg80211_connect_result(dev, (const u8 *)ind->bssid.array, req_ie, ++ ind->assoc_req_ie_len, rsp_ie, ++ ind->assoc_rsp_ie_len, ind->status_code, ++ GFP_ATOMIC); ++ if (ind->status_code == 0) { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ AICWFDBG(LOGINFO, "%s cfg80211_connect_result pass, rwnx_vif->drv_conn_state:%d\r\n", ++ __func__, ++ (int)atomic_read(&rwnx_vif->drv_conn_state)); ++ } else { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ } ++ ++ }else {//roaming ++ if(ind->status_code != 0){ ++ AICWFDBG(LOGINFO, "%s roaming fail to notify disconnect \r\n", __func__); ++ cfg80211_disconnected(dev, 0, NULL, 0,1, GFP_ATOMIC); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ }else{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ struct cfg80211_roam_info info; ++ memset(&info, 0, sizeof(info)); ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ if (rwnx_vif->ch_index < NX_CHAN_CTXT_CNT) ++ info.links[0].channel = rwnx_hw->chanctx_table[rwnx_vif->ch_index].chan_def.chan; ++ info.links[0].bssid = (const u8 *)ind->bssid.array; ++#else ++ if (rwnx_vif->ch_index < NX_CHAN_CTXT_CNT) ++ info.channel = rwnx_hw->chanctx_table[rwnx_vif->ch_index].chan_def.chan; ++ info.bssid = (const u8 *)ind->bssid.array; ++#endif ++ info.req_ie = req_ie; ++ info.req_ie_len = ind->assoc_req_ie_len; ++ info.resp_ie = rsp_ie; ++ info.resp_ie_len = ind->assoc_rsp_ie_len; ++ cfg80211_roamed(dev, &info, GFP_ATOMIC); ++#else ++ chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq); ++ cfg80211_roamed(dev ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE) ++ , chan ++#endif ++ , (const u8 *)ind->bssid.array ++ , req_ie ++ , ind->assoc_req_ie_len ++ , rsp_ie ++ , ind->assoc_rsp_ie_len ++ , GFP_ATOMIC); ++ ++#endif /*LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)*/ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ } ++ rwnx_vif->sta.is_roam = false; ++ } ++ ++ if (ind->status_code == 0) { ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ } ++ ++exit: ++ rwnx_vif->sta.is_roam = false; ++ return 0; ++} ++ ++void rwnx_cfg80211_unlink_bss(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif){ ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ struct cfg80211_bss *bss = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/, ++ rwnx_vif->sta.bssid, rwnx_vif->sta.ssid, ++ rwnx_vif->sta.ssid_len, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) ++ IEEE80211_BSS_TYPE_ESS, ++ IEEE80211_PRIVACY(true));//temp set true ++#else ++ WLAN_CAPABILITY_ESS, ++ WLAN_CAPABILITY_ESS); ++#endif ++ ++ if (bss) { ++ cfg80211_unlink_bss(wiphy, bss); ++ AICWFDBG(LOGINFO, "%s(): cfg80211_unlink %s!!\n", __func__, rwnx_vif->sta.ssid); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) ++ cfg80211_put_bss(wiphy, bss); ++#else ++ cfg80211_put_bss(bss); ++#endif ++ }else{ ++ AICWFDBG(LOGINFO, "%s(): cfg80211_unlink error %s!!\n", __func__, rwnx_vif->sta.ssid); ++ } ++} ++ ++extern u8 dhcped; ++static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct sm_disconnect_ind *ind = (struct sm_disconnect_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct net_device *dev; ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *tmp; ++ u8 *macaddr; ++ struct aicwf_rx_priv *rx_priv; ++#endif ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ AICWFDBG(LOGINFO, "%s reason code:%d \r\n", __func__, ind->reason_code); ++ ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTED){ ++ AICWFDBG(LOGINFO, "%s, is already disconnected, drop disconnect ind", __func__); ++ return 0; ++ } ++ ++ dhcped = 0; ++ ++ if(!rwnx_vif) ++ return 0; ++ dev = rwnx_vif->ndev; ++ ++ if (rwnx_vif->sta.is_roam == false) { ++ rwnx_cfg80211_unlink_bss(rwnx_hw, rwnx_vif); ++ } else { ++ AICWFDBG(LOGINFO, "%s roaming no rwnx_cfg80211_unlink_bss \r\n", __func__); ++ } ++ ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.ap); ++#endif ++ ++ #ifdef CONFIG_BR_SUPPORT ++ struct rwnx_vif *vif = netdev_priv(dev); ++ /* clear bridge database */ ++ nat25_db_cleanup(rwnx_vif); ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ rwnx_hw->is_p2p_connected = 0; ++ /* if vif is not up, rwnx_close has already been called */ ++ if (rwnx_vif->up) { ++ if (!ind->ft_over_ds && !ind->reassoc) { ++ cfg80211_disconnected(dev, ind->reason_code, NULL, 0, ++ (ind->reason_code < 1), GFP_ATOMIC); ++ } ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ } ++ ++#ifdef CONFIG_RWNX_BFMER ++ /* Disable Beamformer if supported */ ++ rwnx_bfmer_report_del(rwnx_hw, rwnx_vif->sta.ap); ++#endif //(CONFIG_RWNX_BFMER) ++ ++#ifdef AICWF_RX_REORDER ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv = rwnx_hw->sdiodev->rx_priv; ++#else ++ rx_priv = rwnx_hw->usbdev->rx_priv; ++#endif ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ macaddr = (u8*)rwnx_vif->ndev->dev_addr; ++ printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0], macaddr[1], macaddr[2], \ ++ macaddr[3], macaddr[4], macaddr[5]); ++ ++ //spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry_safe(reord_info, tmp, &rx_priv->stas_reord_list, list) { ++ macaddr = (u8*)rwnx_vif->ndev->dev_addr; ++ printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0], reord_info->mac_addr[1], reord_info->mac_addr[2], \ ++ reord_info->mac_addr[3], reord_info->mac_addr[4], reord_info->mac_addr[5]); ++ if (!memcmp(reord_info->mac_addr, macaddr, 6)) { ++ reord_deinit_sta(rx_priv, reord_info); ++ break; ++ } ++ } ++ //spin_unlock_bh(&rx_priv->stas_reord_lock); ++ } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { ++ BUG();//should be not here: del_sta function ++ } ++#endif ++ ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_vif->sta.ap); ++ rwnx_txq_tdls_vif_deinit(rwnx_vif); ++ #if 0 ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.ap); ++ #endif ++ rwnx_vif->sta.ap->valid = false; ++ rwnx_vif->sta.ap = NULL; ++ rwnx_external_auth_disable(rwnx_vif); ++ rwnx_chanctx_unlink(rwnx_vif); ++ ++ //msleep(200); ++ if (rwnx_vif->sta.is_roam == false) { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_sm_external_auth_required_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct sm_external_auth_required_ind *ind = ++ (struct sm_external_auth_required_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ struct net_device *dev = rwnx_vif->ndev; ++ struct cfg80211_external_auth_params params; ++ int ret = 0; ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ int retry_counter = 10; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ memset((void*)¶ms, 0, sizeof(struct cfg80211_external_auth_params)); ++ ++ params.action = NL80211_EXTERNAL_AUTH_START; ++ memcpy(params.bssid, ind->bssid.array, ETH_ALEN); ++ params.ssid.ssid_len = ind->ssid.length; ++ memcpy(params.ssid.ssid, ind->ssid.array, ++ min_t(size_t, ind->ssid.length, sizeof(params.ssid.ssid))); ++ params.key_mgmt_suite = ind->akm; ++ ++ while (wdev->conn_owner_nlportid == 0) { ++ AICWFDBG(LOGINFO, "%s WARNING conn_owner_nlportid = 0, msleep 100ms.\r\n", __func__); ++ msleep(100); ++ retry_counter--; ++ if (retry_counter == 0) { ++ break; ++ } ++ } ++ AICWFDBG(LOGINFO, "%s wdev->conn_owner_nlportid:%d \r\n", __func__, (int)wdev->conn_owner_nlportid); ++ ++ if ((ind->vif_idx > NX_VIRT_DEV_MAX) || !rwnx_vif->up || ++ (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_STATION) || ++ (ret = cfg80211_external_auth_request(dev, ¶ms, GFP_ATOMIC))) { ++ wiphy_err(rwnx_hw->wiphy, "Failed to start external auth on vif %d, rwnx_vif->up %d, iftype:%d, ret %d", ++ ind->vif_idx, rwnx_vif->up, RWNX_VIF_TYPE(rwnx_vif), ret); ++ rwnx_send_sm_external_auth_required_rsp(rwnx_hw, rwnx_vif, ++ WLAN_STATUS_UNSPECIFIED_FAILURE); ++ return 0; ++ } ++ ++ rwnx_external_auth_enable(rwnx_vif); ++#else ++ rwnx_send_sm_external_auth_required_rsp(rwnx_hw, rwnx_vif, ++ WLAN_STATUS_UNSPECIFIED_FAILURE); ++#endif ++ return 0; ++} ++ ++ ++static inline int rwnx_rx_mesh_path_create_cfm(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_path_create_cfm *cfm = (struct mesh_path_create_cfm *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[cfm->vif_idx]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Check we well have a Mesh Point Interface */ ++ if (rwnx_vif && (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT)) { ++ rwnx_vif->ap.create_path = false; ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_mesh_peer_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_peer_update_ind *ind = (struct mesh_peer_update_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct rwnx_sta *rwnx_sta = &rwnx_hw->sta_table[ind->sta_idx]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if ((ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) || ++ (rwnx_vif && (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT)) || ++ (ind->sta_idx >= NX_REMOTE_STA_MAX)) ++ return 1; ++ ++ /* Check we well have a Mesh Point Interface */ ++ if (!rwnx_vif->user_mpm) { ++ /* Check if peer link has been established or lost */ ++ if (ind->estab) { ++ if (!rwnx_sta->valid) { ++ u8 txq_status; ++ ++ rwnx_sta->valid = true; ++ rwnx_sta->sta_idx = ind->sta_idx; ++ rwnx_sta->ch_idx = rwnx_vif->ch_index; ++ rwnx_sta->vif_idx = ind->vif_idx; ++ rwnx_sta->vlan_idx = rwnx_sta->vif_idx; ++ rwnx_sta->ps.active = false; ++ rwnx_sta->qos = true; ++ rwnx_sta->aid = ind->sta_idx + 1; ++ //rwnx_sta->acm = ind->acm; ++ memcpy(rwnx_sta->mac_addr, ind->peer_addr.array, ETH_ALEN); ++ ++ rwnx_chanctx_link(rwnx_vif, rwnx_sta->ch_idx, NULL); ++ ++ /* Add the station in the list of VIF's stations */ ++ INIT_LIST_HEAD(&rwnx_sta->list); ++ list_add_tail(&rwnx_sta->list, &rwnx_vif->ap.sta_list); ++ ++ /* Initialize the TX queues */ ++ if (rwnx_sta->ch_idx == rwnx_hw->cur_chanctx) { ++ txq_status = 0; ++ } else { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ ++ rwnx_txq_sta_init(rwnx_hw, rwnx_sta, txq_status); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, rwnx_sta); ++#endif ++#ifdef CONFIG_RWNX_BFMER ++ // TODO: update indication to contains vht capabilties ++ if (rwnx_hw->mod_params->bfmer) ++ rwnx_send_bfmer_enable(rwnx_hw, rwnx_sta, NULL); ++ ++ rwnx_mu_group_sta_init(rwnx_sta, NULL); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ } else { ++ WARN_ON(0); ++ } ++ } else { ++ if (rwnx_sta->valid) { ++ rwnx_sta->ps.active = false; ++ rwnx_sta->valid = false; ++ ++ /* Remove the station from the list of VIF's station */ ++ list_del_init(&rwnx_sta->list); ++ ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_sta); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_sta); ++#endif ++ } else { ++ WARN_ON(0); ++ } ++ } ++ } else { ++ if (!ind->estab && rwnx_sta->valid) { ++ /* There is no way to inform upper layer for lost of peer, still ++ clean everything in the driver */ ++ rwnx_sta->ps.active = false; ++ rwnx_sta->valid = false; ++ ++ /* Remove the station from the list of VIF's station */ ++ list_del_init(&rwnx_sta->list); ++ ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_sta); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_sta); ++#endif ++ } else { ++ WARN_ON(0); ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_mesh_path_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_path_update_ind *ind = (struct mesh_path_update_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct rwnx_mesh_path *mesh_path; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) ++ return 1; ++ ++ if (!rwnx_vif || (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT)) ++ return 0; ++ ++ /* Look for path with provided target address */ ++ list_for_each_entry(mesh_path, &rwnx_vif->ap.mpath_list, list) { ++ if (mesh_path->path_idx == ind->path_idx) { ++ found = true; ++ break; ++ } ++ } ++ ++ /* Check if element has been deleted */ ++ if (ind->delete) { ++ if (found) { ++#ifdef CREATE_TRACE_POINTS ++ trace_mesh_delete_path(mesh_path); ++#endif ++ /* Remove element from list */ ++ list_del_init(&mesh_path->list); ++ /* Free the element */ ++ kfree(mesh_path); ++ } ++ } else { ++ if (found) { ++ // Update the Next Hop STA ++ mesh_path->p_nhop_sta = &rwnx_hw->sta_table[ind->nhop_sta_idx]; ++#ifdef CREATE_TRACE_POINTS ++ trace_mesh_update_path(mesh_path); ++#endif ++ } else { ++ // Allocate a Mesh Path structure ++ mesh_path = (struct rwnx_mesh_path *)kmalloc(sizeof(struct rwnx_mesh_path), GFP_ATOMIC); ++ ++ if (mesh_path) { ++ INIT_LIST_HEAD(&mesh_path->list); ++ ++ mesh_path->path_idx = ind->path_idx; ++ mesh_path->p_nhop_sta = &rwnx_hw->sta_table[ind->nhop_sta_idx]; ++ memcpy(&mesh_path->tgt_mac_addr, &ind->tgt_mac_addr, MAC_ADDR_LEN); ++ ++ // Insert the path in the list of path ++ list_add_tail(&mesh_path->list, &rwnx_vif->ap.mpath_list); ++#ifdef CREATE_TRACE_POINTS ++ trace_mesh_create_path(mesh_path); ++#endif ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_mesh_proxy_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_proxy_update_ind *ind = (struct mesh_proxy_update_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct rwnx_mesh_proxy *mesh_proxy; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) ++ return 1; ++ ++ if (!rwnx_vif || (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT)) ++ return 0; ++ ++ /* Look for path with provided external STA address */ ++ list_for_each_entry(mesh_proxy, &rwnx_vif->ap.proxy_list, list) { ++ if (!memcmp(&ind->ext_sta_addr, &mesh_proxy->ext_sta_addr, ETH_ALEN)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (ind->delete && found) { ++ /* Delete mesh path */ ++ list_del_init(&mesh_proxy->list); ++ kfree(mesh_proxy); ++ } else if (!ind->delete && !found) { ++ /* Allocate a Mesh Path structure */ ++ mesh_proxy = (struct rwnx_mesh_proxy *)kmalloc(sizeof(*mesh_proxy), ++ GFP_ATOMIC); ++ ++ if (mesh_proxy) { ++ INIT_LIST_HEAD(&mesh_proxy->list); ++ ++ memcpy(&mesh_proxy->ext_sta_addr, &ind->ext_sta_addr, MAC_ADDR_LEN); ++ mesh_proxy->local = ind->local; ++ ++ if (!ind->local) { ++ memcpy(&mesh_proxy->proxy_addr, &ind->proxy_mac_addr, MAC_ADDR_LEN); ++ } ++ ++ /* Insert the path in the list of path */ ++ list_add_tail(&mesh_proxy->list, &rwnx_vif->ap.proxy_list); ++ } ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from APM task ++ **************************************************************************/ ++ ++ ++/*************************************************************************** ++ * Messages from DEBUG task ++ **************************************************************************/ ++static inline int rwnx_rx_dbg_error_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_MCU_MESSAGE ++static inline int rwnx_rx_dbg_custmsg_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ dbg_custom_msg_ind_t * ind; ++ char str_msg[32 + 1]; ++ int str_len; ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ind = (dbg_custom_msg_ind_t *)msg->param; ++ str_len = (ind->len < 32) ? ind->len : 32; ++ memcpy(str_msg, (char *)ind->buf, str_len); ++ str_msg[str_len] = '\0'; ++ printk("CustMsgInd: cmd=0x%x, len=%d, str=%s\r\n", ind->cmd, ind->len, str_msg); ++ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++static msg_cb_fct mm_hdlrs[MSG_I(MM_MAX)] = { ++ [MSG_I(MM_CHANNEL_SWITCH_IND)] = rwnx_rx_chan_switch_ind, ++ [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = rwnx_rx_chan_pre_switch_ind, ++ [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = rwnx_rx_remain_on_channel_exp_ind, ++ [MSG_I(MM_PS_CHANGE_IND)] = rwnx_rx_ps_change_ind, ++ [MSG_I(MM_TRAFFIC_REQ_IND)] = rwnx_rx_traffic_req_ind, ++ [MSG_I(MM_P2P_VIF_PS_CHANGE_IND)] = rwnx_rx_p2p_vif_ps_change_ind, ++ [MSG_I(MM_CSA_COUNTER_IND)] = rwnx_rx_csa_counter_ind, ++ [MSG_I(MM_CSA_FINISH_IND)] = rwnx_rx_csa_finish_ind, ++ [MSG_I(MM_CSA_TRAFFIC_IND)] = rwnx_rx_csa_traffic_ind, ++ [MSG_I(MM_CHANNEL_SURVEY_IND)] = rwnx_rx_channel_survey_ind, ++ [MSG_I(MM_P2P_NOA_UPD_IND)] = rwnx_rx_p2p_noa_upd_ind, ++ [MSG_I(MM_RSSI_STATUS_IND)] = rwnx_rx_rssi_status_ind, ++ [MSG_I(MM_PKTLOSS_IND)] = rwnx_rx_pktloss_notify_ind, ++ [MSG_I(MM_APM_STALOSS_IND)] = rwnx_apm_staloss_ind, ++ [MSG_I(MM_RADAR_DETECT_IND)] = rwnx_radar_detect_ind, ++}; ++ ++static msg_cb_fct scan_hdlrs[MSG_I(SCANU_MAX)] = { ++ [MSG_I(SCANU_START_CFM)] = rwnx_rx_scanu_start_cfm, ++ [MSG_I(SCANU_RESULT_IND)] = rwnx_rx_scanu_result_ind, ++}; ++ ++static msg_cb_fct me_hdlrs[MSG_I(ME_MAX)] = { ++ [MSG_I(ME_TKIP_MIC_FAILURE_IND)] = rwnx_rx_me_tkip_mic_failure_ind, ++ [MSG_I(ME_TX_CREDITS_UPDATE_IND)] = rwnx_rx_me_tx_credits_update_ind, ++}; ++ ++static msg_cb_fct sm_hdlrs[MSG_I(SM_MAX)] = { ++ [MSG_I(SM_CONNECT_IND)] = rwnx_rx_sm_connect_ind, ++ [MSG_I(SM_DISCONNECT_IND)] = rwnx_rx_sm_disconnect_ind, ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_IND)] = rwnx_rx_sm_external_auth_required_ind, ++}; ++ ++static msg_cb_fct apm_hdlrs[MSG_I(APM_MAX)] = { ++}; ++ ++static msg_cb_fct mesh_hdlrs[MSG_I(MESH_MAX)] = { ++ [MSG_I(MESH_PATH_CREATE_CFM)] = rwnx_rx_mesh_path_create_cfm, ++ [MSG_I(MESH_PEER_UPDATE_IND)] = rwnx_rx_mesh_peer_update_ind, ++ [MSG_I(MESH_PATH_UPDATE_IND)] = rwnx_rx_mesh_path_update_ind, ++ [MSG_I(MESH_PROXY_UPDATE_IND)] = rwnx_rx_mesh_proxy_update_ind, ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = { ++ [MSG_I(DBG_ERROR_IND)] = rwnx_rx_dbg_error_ind, ++#ifdef CONFIG_MCU_MESSAGE ++ [MSG_I(DBG_CUSTOM_MSG_IND)] = rwnx_rx_dbg_custmsg_ind, ++#endif ++}; ++ ++static msg_cb_fct tdls_hdlrs[MSG_I(TDLS_MAX)] = { ++ [MSG_I(TDLS_CHAN_SWITCH_CFM)] = rwnx_rx_tdls_chan_switch_cfm, ++ [MSG_I(TDLS_CHAN_SWITCH_IND)] = rwnx_rx_tdls_chan_switch_ind, ++ [MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = rwnx_rx_tdls_chan_switch_base_ind, ++ [MSG_I(TDLS_PEER_PS_IND)] = rwnx_rx_tdls_peer_ps_ind, ++#ifdef CONFIG_SDIO_BT ++ [MSG_I(TDLS_SDIO_BT_RECV_IND)] = rwnx_bt_recv_ind, ++#endif ++}; ++ ++static msg_cb_fct *msg_hdlrs[] = { ++ [TASK_MM] = mm_hdlrs, ++ [TASK_DBG] = dbg_hdlrs, ++#ifdef CONFIG_RWNX_FULLMAC ++ [TASK_TDLS] = tdls_hdlrs, ++ [TASK_SCANU] = scan_hdlrs, ++ [TASK_ME] = me_hdlrs, ++ [TASK_SM] = sm_hdlrs, ++ [TASK_APM] = apm_hdlrs, ++ [TASK_MESH] = mesh_hdlrs, ++#endif /* CONFIG_RWNX_FULLMAC */ ++}; ++ ++/** ++ * ++ */ ++void rwnx_rx_handle_msg(struct rwnx_hw *rwnx_hw, struct ipc_e2a_msg *msg) ++{ ++ AICWFDBG(LOGDEBUG, "%s msg->id:0x%x \r\n", __func__, msg->id); ++ ++ rwnx_hw->cmd_mgr->msgind(rwnx_hw->cmd_mgr, msg, ++ msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]); ++} ++ ++void rwnx_rx_handle_print(struct rwnx_hw *rwnx_hw, u8 *msg, u32 len) ++{ ++ u8 *data_end = NULL; ++ (void)data_end; ++ ++ if (!rwnx_hw || !rwnx_hw->fwlog_en) { ++ pr_err("FWLOG-OVFL: %s", msg); ++ return; ++ } ++ ++ printk("FWLOG: %s", msg); ++ ++#ifdef CONFIG_RWNX_DEBUGFS ++ data_end = rwnx_hw->debugfs.fw_log.buf.dataend; ++ ++ if (!rwnx_hw->debugfs.fw_log.buf.data) ++ return ; ++ ++ //printk("end=%lx, len=%d\n", (unsigned long)rwnx_hw->debugfs.fw_log.buf.end, len); ++ ++ spin_lock_bh(&rwnx_hw->debugfs.fw_log.lock); ++ ++ if (rwnx_hw->debugfs.fw_log.buf.end + len > data_end) { ++ int rem = data_end - rwnx_hw->debugfs.fw_log.buf.end; ++ memcpy(rwnx_hw->debugfs.fw_log.buf.end, msg, rem); ++ memcpy(rwnx_hw->debugfs.fw_log.buf.data, &msg[rem], len - rem); ++ rwnx_hw->debugfs.fw_log.buf.end = rwnx_hw->debugfs.fw_log.buf.data + (len - rem); ++ } else { ++ memcpy(rwnx_hw->debugfs.fw_log.buf.end, msg, len); ++ rwnx_hw->debugfs.fw_log.buf.end += len; ++ } ++ ++ rwnx_hw->debugfs.fw_log.buf.size += len; ++ if (rwnx_hw->debugfs.fw_log.buf.size > FW_LOG_SIZE) ++ rwnx_hw->debugfs.fw_log.buf.size = FW_LOG_SIZE; ++ ++ spin_unlock_bh(&rwnx_hw->debugfs.fw_log.lock); ++#endif ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h +new file mode 100644 +index 000000000000..b5556d160ff0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h +@@ -0,0 +1,19 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_msg_rx.h ++ * ++ * @brief RX function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_MSG_RX_H_ ++#define _RWNX_MSG_RX_H_ ++ ++void rwnx_rx_handle_msg(struct rwnx_hw *rwnx_hw, struct ipc_e2a_msg *msg); ++void rwnx_rx_handle_print(struct rwnx_hw *rwnx_hw, u8 *msg, u32 len); ++ ++#endif /* _RWNX_MSG_RX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c +new file mode 100644 +index 000000000000..849a8ea709e3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c +@@ -0,0 +1,4185 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_msg_tx.c ++ * ++ * @brief TX function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_msg_tx.h" ++#include "rwnx_mod_params.h" ++#include "reg_access.h" ++#ifdef CONFIG_RWNX_BFMER ++#include "rwnx_bfmer.h" ++#endif //(CONFIG_RWNX_BFMER) ++#include "rwnx_compat.h" ++#include "rwnx_cmds.h" ++#include "aicwf_txrxif.h" ++#include "rwnx_strs.h" ++#include "rwnx_main.h" ++#include "rwnx_wakelock.h" ++ ++const struct mac_addr mac_addr_bcst = {{0xFFFF, 0xFFFF, 0xFFFF}}; ++ ++/* Default MAC Rx filters that can be changed by mac80211 ++ * (via the configure_filter() callback) */ ++#define RWNX_MAC80211_CHANGEABLE ( \ ++ NXMAC_ACCEPT_BA_BIT | \ ++ NXMAC_ACCEPT_BAR_BIT | \ ++ NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT | \ ++ NXMAC_ACCEPT_PROBE_REQ_BIT | \ ++ NXMAC_ACCEPT_PS_POLL_BIT \ ++ ) ++ ++/* Default MAC Rx filters that cannot be changed by mac80211 */ ++#define RWNX_MAC80211_NOT_CHANGEABLE ( \ ++ NXMAC_ACCEPT_QO_S_NULL_BIT | \ ++ NXMAC_ACCEPT_Q_DATA_BIT | \ ++ NXMAC_ACCEPT_DATA_BIT | \ ++ NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT | \ ++ NXMAC_ACCEPT_MY_UNICAST_BIT | \ ++ NXMAC_ACCEPT_BROADCAST_BIT | \ ++ NXMAC_ACCEPT_BEACON_BIT | \ ++ NXMAC_ACCEPT_PROBE_RESP_BIT \ ++ ) ++ ++/* Default MAC Rx filter */ ++#define RWNX_DEFAULT_RX_FILTER (RWNX_MAC80211_CHANGEABLE | RWNX_MAC80211_NOT_CHANGEABLE) ++ ++const int bw2chnl[] = { ++ [NL80211_CHAN_WIDTH_20_NOHT] = PHY_CHNL_BW_20, ++ [NL80211_CHAN_WIDTH_20] = PHY_CHNL_BW_20, ++ [NL80211_CHAN_WIDTH_40] = PHY_CHNL_BW_40, ++ [NL80211_CHAN_WIDTH_80] = PHY_CHNL_BW_80, ++ [NL80211_CHAN_WIDTH_160] = PHY_CHNL_BW_160, ++ [NL80211_CHAN_WIDTH_80P80] = PHY_CHNL_BW_80P80, ++}; ++ ++const int chnl2bw[] = { ++ [PHY_CHNL_BW_20] = NL80211_CHAN_WIDTH_20, ++ [PHY_CHNL_BW_40] = NL80211_CHAN_WIDTH_40, ++ [PHY_CHNL_BW_80] = NL80211_CHAN_WIDTH_80, ++ [PHY_CHNL_BW_160] = NL80211_CHAN_WIDTH_160, ++ [PHY_CHNL_BW_80P80] = NL80211_CHAN_WIDTH_80P80, ++}; ++ ++#define RWNX_CMD_ARRAY_SIZE 40 ++#define RWNX_CMD_HIGH_WATER_SIZE RWNX_CMD_ARRAY_SIZE/2 ++ ++struct rwnx_cmd cmd_array[RWNX_CMD_ARRAY_SIZE]; ++static spinlock_t cmd_array_lock; ++int cmd_array_index = 0; ++ ++ ++ ++/*****************************************************************************/ ++/* ++ * Parse the ampdu density to retrieve the value in usec, according to the ++ * values defined in ieee80211.h ++ */ ++static inline u8 rwnx_ampdudensity2usec(u8 ampdudensity) ++{ ++ switch (ampdudensity) { ++ case IEEE80211_HT_MPDU_DENSITY_NONE: ++ return 0; ++ /* 1 microsecond is our granularity */ ++ case IEEE80211_HT_MPDU_DENSITY_0_25: ++ case IEEE80211_HT_MPDU_DENSITY_0_5: ++ case IEEE80211_HT_MPDU_DENSITY_1: ++ return 1; ++ case IEEE80211_HT_MPDU_DENSITY_2: ++ return 2; ++ case IEEE80211_HT_MPDU_DENSITY_4: ++ return 4; ++ case IEEE80211_HT_MPDU_DENSITY_8: ++ return 8; ++ case IEEE80211_HT_MPDU_DENSITY_16: ++ return 16; ++ default: ++ return 0; ++ } ++} ++ ++static inline bool use_pairwise_key(struct cfg80211_crypto_settings *crypto) ++{ ++ if ((crypto->cipher_group == WLAN_CIPHER_SUITE_WEP40) || ++ (crypto->cipher_group == WLAN_CIPHER_SUITE_WEP104)) ++ return false; ++ ++ return true; ++} ++ ++static inline bool is_non_blocking_msg(int id) ++{ ++ return ((id == MM_TIM_UPDATE_REQ) || (id == ME_RC_SET_RATE_REQ) || ++ (id == MM_BFMER_ENABLE_REQ) || (id == ME_TRAFFIC_IND_REQ) || ++ (id == TDLS_PEER_TRAFFIC_IND_REQ) || ++ (id == MESH_PATH_CREATE_REQ) || (id == MESH_PROXY_ADD_REQ) || ++ (id == SM_EXTERNAL_AUTH_REQUIRED_RSP)); ++} ++ ++static inline u8_l get_chan_flags(uint32_t flags) ++{ ++ u8_l chan_flags = 0; ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) ++ if (flags & IEEE80211_CHAN_PASSIVE_SCAN) ++ #else ++ if (flags & IEEE80211_CHAN_NO_IR) ++ #endif ++ chan_flags |= CHAN_NO_IR; ++ if (flags & IEEE80211_CHAN_RADAR) ++ chan_flags |= CHAN_RADAR; ++#endif ++ return chan_flags; ++} ++ ++static inline s8_l chan_to_fw_pwr(int power) ++{ ++ return power > 127 ? 127 : (s8_l)power; ++} ++ ++static inline void limit_chan_bw(u8_l *bw, u16_l primary, u16_l *center1) ++{ ++ int oft, new_oft = 10; ++ ++ if (*bw <= PHY_CHNL_BW_40) ++ return; ++ ++ oft = *center1 - primary; ++ *bw = PHY_CHNL_BW_40; ++ ++ if (oft < 0) ++ new_oft = new_oft * -1; ++ if (abs(oft) == 10 || abs(oft) == 50) ++ new_oft = new_oft * -1; ++ ++ *center1 = primary + new_oft; ++} ++ ++struct rwnx_cmd *rwnx_cmd_malloc(void){ ++ struct rwnx_cmd *cmd = NULL; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&cmd_array_lock, flags); ++ ++ for(cmd_array_index = 0; cmd_array_index < RWNX_CMD_ARRAY_SIZE; cmd_array_index++){ ++ if(cmd_array[cmd_array_index].used == 0){ ++ AICWFDBG(LOGTRACE, "%s get cmd_array[%d]:%p \r\n", __func__, cmd_array_index,&cmd_array[cmd_array_index]); ++ cmd = &cmd_array[cmd_array_index]; ++ cmd_array[cmd_array_index].used = 1; ++ break; ++ } ++ } ++ ++ if(cmd_array_index >= RWNX_CMD_HIGH_WATER_SIZE){ ++ AICWFDBG(LOGERROR, "%s cmd(%d) was pending...\r\n", __func__, cmd_array_index); ++ mdelay(100); ++ } ++ ++ if(!cmd){ ++ AICWFDBG(LOGERROR, "%s array is empty...\r\n", __func__); ++ } ++ ++ spin_unlock_irqrestore(&cmd_array_lock, flags); ++ ++ return cmd; ++} ++ ++void rwnx_cmd_free(struct rwnx_cmd *cmd){ ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&cmd_array_lock, flags); ++ cmd->used = 0; ++ AICWFDBG(LOGTRACE, "%s cmd_array[%d]:%p \r\n", __func__, cmd->array_id, cmd); ++ spin_unlock_irqrestore(&cmd_array_lock, flags); ++} ++ ++ ++int rwnx_init_cmd_array(void){ ++ ++ AICWFDBG(LOGTRACE, "%s Enter \r\n", __func__); ++ spin_lock_init(&cmd_array_lock); ++ ++ for(cmd_array_index = 0; cmd_array_index < RWNX_CMD_ARRAY_SIZE; cmd_array_index++){ ++ AICWFDBG(LOGTRACE, "%s cmd_queue[%d]:%p \r\n", __func__, cmd_array_index, &cmd_array[cmd_array_index]); ++ cmd_array[cmd_array_index].used = 0; ++ cmd_array[cmd_array_index].array_id = cmd_array_index; ++ } ++ AICWFDBG(LOGTRACE, "%s Exit \r\n", __func__); ++ ++ return 0; ++} ++ ++void rwnx_free_cmd_array(void){ ++ ++ AICWFDBG(LOGTRACE, "%s Enter \r\n", __func__); ++ ++ for(cmd_array_index = 0; cmd_array_index < RWNX_CMD_ARRAY_SIZE; cmd_array_index++){ ++ cmd_array[cmd_array_index].used = 0; ++ } ++ ++ AICWFDBG(LOGTRACE, "%s Exit \r\n", __func__); ++} ++ ++ ++/** ++ ****************************************************************************** ++ * @brief Allocate memory for a message ++ * ++ * This primitive allocates memory for a message that has to be sent. The memory ++ * is allocated dynamically on the heap and the length of the variable parameter ++ * structure has to be provided in order to allocate the correct size. ++ * ++ * Several additional parameters are provided which will be preset in the message ++ * and which may be used internally to choose the kind of memory to allocate. ++ * ++ * The memory allocated will be automatically freed by the kernel, after the ++ * pointer has been sent to ke_msg_send(). If the message is not sent, it must ++ * be freed explicitly with ke_msg_free(). ++ * ++ * Allocation failure is considered critical and should not happen. ++ * ++ * @param[in] id Message identifier ++ * @param[in] dest_id Destination Task Identifier ++ * @param[in] src_id Source Task Identifier ++ * @param[in] param_len Size of the message parameters to be allocated ++ * ++ * @return Pointer to the parameter member of the ke_msg. If the parameter ++ * structure is empty, the pointer will point to the end of the message ++ * and should not be used (except to retrieve the message pointer or to ++ * send the message) ++ ****************************************************************************** ++ */ ++static inline void *rwnx_msg_zalloc(lmac_msg_id_t const id, ++ lmac_task_id_t const dest_id, ++ lmac_task_id_t const src_id, ++ uint16_t const param_len) ++{ ++ struct lmac_msg *msg; ++ gfp_t flags; ++ ++// if (is_non_blocking_msg(id) && (in_softirq()||in_atomic())) ++ flags = GFP_ATOMIC; ++// else ++// flags = GFP_KERNEL; ++ ++ msg = (struct lmac_msg *)kzalloc(sizeof(struct lmac_msg) + param_len, ++ flags); ++ if (msg == NULL) { ++ AICWFDBG(LOGERROR, "%s: msg allocation failed\n", __func__); ++ return NULL; ++ } ++ msg->id = id; ++ msg->dest_id = dest_id; ++ msg->src_id = src_id; ++ msg->param_len = param_len; ++ //printk("rwnx_msg_zalloc size=%d id=%d\n",msg->param_len,msg->id); ++ ++ return msg->param; ++} ++ ++static void rwnx_msg_free(struct rwnx_hw *rwnx_hw, const void *msg_params) ++{ ++ struct lmac_msg *msg = container_of((void *)msg_params, ++ struct lmac_msg, param); ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Free the message */ ++ kfree(msg); ++} ++ ++//void rwnx_pm_relax(struct aic_sdio_dev *sdiodev); ++//void rwnx_pm_stay_awake(struct aic_sdio_dev *sdiodev); ++ ++static int rwnx_send_msg(struct rwnx_hw *rwnx_hw, const void *msg_params, ++ int reqcfm, lmac_msg_id_t reqid, void *cfm) ++{ ++ struct lmac_msg *msg; ++ struct rwnx_cmd *cmd; ++ bool nonblock; ++ int ret = 0; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ AICWFDBG(LOGTRACE, "%s (%d)%s reqcfm:%d in_irq:%d in_softirq:%d in_atomic:%d\r\n", ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(6, 18, 0)) ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_irq(), (int)in_softirq(), (int)in_atomic()); ++#else ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_hardirq(), (int)in_softirq(), (int)in_atomic()); ++#endif ++ ++ ++#ifdef AICWF_USB_SUPPORT ++ if (rwnx_hw->usbdev->state == USB_DOWN_ST) { ++ rwnx_msg_free(rwnx_hw, msg_params); ++ usb_err("bus is down\n"); ++ return 0; ++ } ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ rwnx_wakeup_lock(rwnx_hw->ws_tx); ++ if (rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { ++ rwnx_msg_free(rwnx_hw, msg_params); ++ sdio_err("bus is down\n"); ++ rwnx_wakeup_unlock(rwnx_hw->ws_tx); ++ return 0; ++ } ++#endif ++ ++ msg = container_of((void *)msg_params, struct lmac_msg, param); ++ ++ #if 0 ++ if (!test_bit(RWNX_DEV_STARTED, &rwnx_hw->drv_flags) && ++ reqid != DBG_MEM_READ_CFM && reqid != DBG_MEM_WRITE_CFM && ++ reqid != DBG_MEM_BLOCK_WRITE_CFM && reqid != DBG_START_APP_CFM && ++ reqid != MM_SET_RF_CALIB_CFM && reqid != MM_SET_RF_CONFIG_CFM && ++ reqid != MM_RESET_CFM && reqid != MM_VERSION_CFM && ++ reqid != MM_START_CFM && reqid != MM_SET_IDLE_CFM && ++ reqid != ME_CONFIG_CFM && reqid != MM_SET_PS_MODE_CFM && ++ reqid != ME_CHAN_CONFIG_CFM) { ++ printk(KERN_CRIT "%s: bypassing (RWNX_DEV_RESTARTING set) 0x%02x\n", ++ __func__, reqid); ++ kfree(msg); ++ return -EBUSY; ++ } ++ #endif ++#if 0 ++ else if (!rwnx_hw->ipc_env) { ++ printk(KERN_CRIT "%s: bypassing (restart must have failed)\n", __func__); ++ kfree(msg); ++ return -EBUSY; ++ } ++#endif ++ ++ //nonblock = is_non_blocking_msg(msg->id); ++ nonblock = 0; ++ cmd = rwnx_cmd_malloc();//kzalloc(sizeof(struct rwnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL); ++ cmd->result = -EINTR; ++ cmd->id = msg->id; ++ cmd->reqid = reqid; ++ cmd->a2e_msg = msg; ++ cmd->e2a_msg = cfm; ++ if (nonblock) ++ cmd->flags = RWNX_CMD_FLAG_NONBLOCK; ++ if (reqcfm) ++ cmd->flags |= RWNX_CMD_FLAG_REQ_CFM; ++ ++#if 0 ++ if (cfm != NULL) { ++ do { ++ if(rwnx_hw->cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) ++ break; ++ spin_lock_bh(&rwnx_hw->cmd_mgr->lock); ++ empty = list_empty(&rwnx_hw->cmd_mgr->cmds); ++ spin_unlock_bh(&rwnx_hw->cmd_mgr->lock); ++ if(!empty) { ++ if(in_softirq()) { ++ printk("in_softirq:check cmdqueue empty\n"); ++ mdelay(10); ++ } ++ else { ++ printk("check cmdqueue empty\n"); ++ msleep(50); ++ } ++ } ++ } while (!empty);//wait for cmd queue empty ++ } ++#endif ++ if (reqcfm) { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; // we don't need ack any more ++ ret = rwnx_hw->cmd_mgr->queue(rwnx_hw->cmd_mgr, cmd); ++ } else { ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_set_cmd_tx((void *)(rwnx_hw->sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++#else ++ aicwf_set_cmd_tx((void *)(rwnx_hw->usbdev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++#endif ++ } ++ ++ if (!reqcfm || ret) ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ ++ rwnx_wakeup_unlock(rwnx_hw->ws_tx); ++ return 0; ++} ++ ++ ++static int rwnx_send_msg1(struct rwnx_hw *rwnx_hw, const void *msg_params, ++ int reqcfm, lmac_msg_id_t reqid, void *cfm, bool defer) ++{ ++ struct lmac_msg *msg; ++ struct rwnx_cmd *cmd; ++ bool nonblock; ++ int ret = 0; ++ ++// RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("%s (%d)%s reqcfm:%d in_irq:%d in_softirq:%d in_atomic:%d\r\n", ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(6, 18, 0)) ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_irq(), (int)in_softirq(), (int)in_atomic()); ++#else ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_hardirq(), (int)in_softirq(), (int)in_atomic()); ++#endif ++ ++ rwnx_wakeup_lock(rwnx_hw->ws_tx); ++ msg = container_of((void *)msg_params, struct lmac_msg, param); ++ ++ //nonblock = is_non_blocking_msg(msg->id); ++ nonblock = 0; ++ cmd = rwnx_cmd_malloc();//kzalloc(sizeof(struct rwnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL); ++ cmd->result = -EINTR; ++ cmd->id = msg->id; ++ cmd->reqid = reqid; ++ cmd->a2e_msg = msg; ++ cmd->e2a_msg = cfm; ++ if (nonblock) ++ cmd->flags = RWNX_CMD_FLAG_NONBLOCK; ++ if (reqcfm) ++ cmd->flags |= RWNX_CMD_FLAG_REQ_CFM; ++ ++ if (reqcfm) { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; // we don't need ack any more ++ if (!defer) ++ ret = rwnx_hw->cmd_mgr->queue(rwnx_hw->cmd_mgr, cmd); ++ else ++ ret = cmd_mgr_queue_force_defer(rwnx_hw->cmd_mgr, cmd); ++ } ++ ++ if (!reqcfm || ret) ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ ++ if (!ret) ++ ret = cmd->result; ++ ++ rwnx_wakeup_unlock(rwnx_hw->ws_tx); ++ //return ret; ++ return 0; ++} ++ ++/****************************************************************************** ++ * Control messages handling functions (FULLMAC) ++ *****************************************************************************/ ++int rwnx_send_reset(struct rwnx_hw *rwnx_hw) ++{ ++ void *void_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* RESET REQ has no parameter */ ++ void_param = rwnx_msg_zalloc(MM_RESET_REQ, TASK_MM, DRV_TASK_ID, 0); ++ if (!void_param) ++ return -ENOMEM; ++ ++ return rwnx_send_msg(rwnx_hw, void_param, 1, MM_RESET_CFM, NULL); ++} ++ ++int rwnx_send_start(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_start_req *start_req_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the START REQ message */ ++ start_req_param = rwnx_msg_zalloc(MM_START_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_start_req)); ++ if (!start_req_param) ++ return -ENOMEM; ++ ++ /* Set parameters for the START message */ ++ memcpy(&start_req_param->phy_cfg, &rwnx_hw->phy.cfg, sizeof(rwnx_hw->phy.cfg)); ++ start_req_param->uapsd_timeout = (u32_l)rwnx_hw->mod_params->uapsd_timeout; ++ start_req_param->lp_clk_accuracy = (u16_l)rwnx_hw->mod_params->lp_clk_ppm; ++ ++ /* Send the START REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, start_req_param, 1, MM_START_CFM, NULL); ++} ++ ++int rwnx_send_version_req(struct rwnx_hw *rwnx_hw, struct mm_version_cfm *cfm) ++{ ++ void *void_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* VERSION REQ has no parameter */ ++ void_param = rwnx_msg_zalloc(MM_VERSION_REQ, TASK_MM, DRV_TASK_ID, 0); ++ if (!void_param) ++ return -ENOMEM; ++ ++ return rwnx_send_msg(rwnx_hw, void_param, 1, MM_VERSION_CFM, cfm); ++} ++ ++int rwnx_send_add_if (struct rwnx_hw *rwnx_hw, const unsigned char *mac, ++ enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm) ++{ ++ struct mm_add_if_req *add_if_req_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ADD_IF_REQ message */ ++ add_if_req_param = rwnx_msg_zalloc(MM_ADD_IF_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_add_if_req)); ++ if (!add_if_req_param) ++ return -ENOMEM; ++ ++ /* Set parameters for the ADD_IF_REQ message */ ++ memcpy(&(add_if_req_param->addr.array[0]), mac, ETH_ALEN); ++ switch (iftype) { ++ #ifdef CONFIG_RWNX_FULLMAC ++ //case NL80211_IFTYPE_P2P_DEVICE: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ add_if_req_param->p2p = true; ++ // no break ++ __attribute__((__fallthrough__)); ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ case NL80211_IFTYPE_STATION: ++ add_if_req_param->type = MM_STA; ++ break; ++ ++ case NL80211_IFTYPE_ADHOC: ++ add_if_req_param->type = MM_IBSS; ++ break; ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ case NL80211_IFTYPE_P2P_GO: ++ add_if_req_param->p2p = true; ++ // no break ++ __attribute__((__fallthrough__)); ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ case NL80211_IFTYPE_AP: ++ add_if_req_param->type = MM_AP; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ add_if_req_param->type = MM_MESH_POINT; ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ return -1; ++ case NL80211_IFTYPE_MONITOR: ++ add_if_req_param->type = MM_MONITOR; ++ break; ++ default: ++ add_if_req_param->type = MM_STA; ++ break; ++ } ++ ++ ++ /* Send the ADD_IF_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, add_if_req_param, 1, MM_ADD_IF_CFM, cfm); ++} ++ ++int rwnx_send_remove_if (struct rwnx_hw *rwnx_hw, u8 vif_index, bool defer) ++{ ++ struct mm_remove_if_req *remove_if_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_REMOVE_IF_REQ message */ ++ remove_if_req = rwnx_msg_zalloc(MM_REMOVE_IF_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_remove_if_req)); ++ if (!remove_if_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_REMOVE_IF_REQ message */ ++ remove_if_req->inst_nbr = vif_index; ++ ++ /* Send the MM_REMOVE_IF_REQ message to LMAC FW */ ++ return rwnx_send_msg1(rwnx_hw, remove_if_req, 1, MM_REMOVE_IF_CFM, NULL, defer); ++} ++ ++int rwnx_send_set_channel(struct rwnx_hw *rwnx_hw, int phy_idx, ++ struct mm_set_channel_cfm *cfm) ++{ ++ struct mm_set_channel_req *req; ++ enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT; ++ u16 center_freq = 2412, center_freq1 = 2412, center_freq2 = 2412; ++ s8 tx_power = 0; ++ u8 flags = 0; ++ enum nl80211_band band = NL80211_BAND_2GHZ; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (phy_idx >= rwnx_hw->phy.cnt) ++ return -ENOTSUPP; ++ ++ req = rwnx_msg_zalloc(MM_SET_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_channel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if (phy_idx == 0) { ++#ifdef CONFIG_RWNX_FULLMAC ++ /* On FULLMAC only setting channel of secondary chain */ ++ wiphy_err(rwnx_hw->wiphy, "Trying to set channel of primary chain"); ++ return 0; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } else { ++ struct rwnx_sec_phy_chan *chan = &rwnx_hw->phy.sec_chan; ++ width = chnl2bw[chan->type]; ++ band = chan->band; ++ center_freq = chan->prim20_freq; ++ center_freq1 = chan->center_freq1; ++ center_freq2 = chan->center_freq2; ++ flags = 0; ++ } ++ ++ req->chan.band = band; ++ req->chan.type = bw2chnl[width]; ++ req->chan.prim20_freq = center_freq; ++ req->chan.center1_freq = center_freq1; ++ req->chan.center2_freq = center_freq2; ++ req->chan.tx_power = tx_power; ++ req->chan.flags = flags; ++ req->index = phy_idx; ++ ++ if (rwnx_hw->phy.limit_bw) ++ limit_chan_bw(&req->chan.type, req->chan.prim20_freq, &req->chan.center1_freq); ++ ++ RWNX_DBG("mac80211: freq=%d(c1:%d - c2:%d)/width=%d - band=%d\n" ++ " hw(%d): prim20=%d(c1:%d - c2:%d)/ type=%d - band=%d\n", ++ center_freq, center_freq1, center_freq2, width, band, ++ phy_idx, req->chan.prim20_freq, req->chan.center1_freq, ++ req->chan.center2_freq, req->chan.type, req->chan.band); ++ ++ /* Send the MM_SET_CHANNEL_REQ REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_SET_CHANNEL_CFM, cfm); ++} ++ ++int rwnx_send_key_add(struct rwnx_hw *rwnx_hw, u8 vif_idx, u8 sta_idx, bool pairwise, ++ u8 *key, u8 key_len, u8 key_idx, u8 cipher_suite, ++ struct mm_key_add_cfm *cfm) ++{ ++ struct mm_key_add_req *key_add_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_KEY_ADD_REQ message */ ++ key_add_req = rwnx_msg_zalloc(MM_KEY_ADD_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_key_add_req)); ++ if (!key_add_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_KEY_ADD_REQ message */ ++ if (sta_idx != 0xFF) { ++ /* Pairwise key */ ++ key_add_req->sta_idx = sta_idx; ++ } else { ++ /* Default key */ ++ key_add_req->sta_idx = sta_idx; ++ key_add_req->key_idx = (u8_l)key_idx; /* only useful for default keys */ ++ } ++ key_add_req->pairwise = pairwise; ++ key_add_req->inst_nbr = vif_idx; ++ key_add_req->key.length = key_len; ++ memcpy(&(key_add_req->key.array[0]), key, key_len); ++ ++ key_add_req->cipher_suite = cipher_suite; ++ ++ RWNX_DBG("%s: sta_idx:%d key_idx:%d inst_nbr:%d cipher:%d key_len:%d\n", __func__, ++ key_add_req->sta_idx, key_add_req->key_idx, key_add_req->inst_nbr, ++ key_add_req->cipher_suite, key_add_req->key.length); ++#if defined(CONFIG_RWNX_DBG) || defined(CONFIG_DYNAMIC_DEBUG) ++ print_hex_dump_bytes("key: ", DUMP_PREFIX_OFFSET, key_add_req->key.array, key_add_req->key.length); ++#endif ++ ++ /* Send the MM_KEY_ADD_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, key_add_req, 1, MM_KEY_ADD_CFM, cfm); ++} ++ ++int rwnx_send_key_del(struct rwnx_hw *rwnx_hw, uint8_t hw_key_idx) ++{ ++ struct mm_key_del_req *key_del_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_KEY_DEL_REQ message */ ++ key_del_req = rwnx_msg_zalloc(MM_KEY_DEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_key_del_req)); ++ if (!key_del_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_KEY_DEL_REQ message */ ++ key_del_req->hw_key_idx = hw_key_idx; ++ ++ /* Send the MM_KEY_DEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, key_del_req, 1, MM_KEY_DEL_CFM, NULL); ++} ++ ++int rwnx_send_bcn(struct rwnx_hw *rwnx_hw, u8 *buf, u8 vif_idx, u16 bcn_len) ++{ ++ struct apm_set_bcn_ie_req *bcn_ie_req; ++ bcn_ie_req = rwnx_msg_zalloc(APM_SET_BEACON_IE_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_set_bcn_ie_req)); ++ if (!bcn_ie_req) ++ return -ENOMEM; ++ ++ bcn_ie_req->vif_idx = vif_idx; ++ bcn_ie_req->bcn_ie_len = bcn_len; ++ memcpy(bcn_ie_req->bcn_ie, (u8 *)buf, bcn_len); ++ kfree(buf); ++ ++ return rwnx_send_msg(rwnx_hw, bcn_ie_req, 1, APM_SET_BEACON_IE_CFM, NULL); ++} ++ ++int rwnx_send_bcn_change(struct rwnx_hw *rwnx_hw, u8 vif_idx, u32 bcn_addr, ++ u16 bcn_len, u16 tim_oft, u16 tim_len, u16 *csa_oft) ++{ ++ struct mm_bcn_change_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_BCN_CHANGE_REQ message */ ++ req = rwnx_msg_zalloc(MM_BCN_CHANGE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_bcn_change_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_BCN_CHANGE_REQ message */ ++ req->bcn_ptr = bcn_addr; ++ req->bcn_len = bcn_len; ++ req->tim_oft = tim_oft; ++ req->tim_len = tim_len; ++ req->inst_nbr = vif_idx; ++ ++ if (csa_oft) { ++ int i; ++ for (i = 0; i < BCN_MAX_CSA_CPT; i++) { ++ req->csa_oft[i] = csa_oft[i]; ++ } ++ } ++ ++ /* Send the MM_BCN_CHANGE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_BCN_CHANGE_CFM, NULL); ++} ++ ++int rwnx_send_roc(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct ieee80211_channel *chan, unsigned int duration, ++ struct mm_remain_on_channel_cfm *roc_cfm) ++{ ++ struct mm_remain_on_channel_req *req; ++ struct cfg80211_chan_def chandef; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Create channel definition structure */ ++ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); ++ ++ /* Build the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req = rwnx_msg_zalloc(MM_REMAIN_ON_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_remain_on_channel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req->op_code = MM_ROC_OP_START; ++ req->vif_index = vif->vif_index; ++ req->duration_ms = duration; ++ req->band = chan->band; ++ req->type = bw2chnl[chandef.width]; ++ req->prim20_freq = chan->center_freq; ++ req->center1_freq = chandef.center_freq1; ++ req->center2_freq = chandef.center_freq2; ++ req->tx_power = chan_to_fw_pwr(chan->max_power); ++ ++ /* Send the MM_REMAIN_ON_CHANNEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_REMAIN_ON_CHANNEL_CFM, roc_cfm); ++} ++ ++int rwnx_send_cancel_roc(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_remain_on_channel_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req = rwnx_msg_zalloc(MM_REMAIN_ON_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_remain_on_channel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req->op_code = MM_ROC_OP_CANCEL; ++ ++ /* Send the MM_REMAIN_ON_CHANNEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_REMAIN_ON_CHANNEL_CFM, NULL); ++} ++ ++int rwnx_send_set_power(struct rwnx_hw *rwnx_hw, u8 vif_idx, s8 pwr, ++ struct mm_set_power_cfm *cfm) ++{ ++ struct mm_set_power_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_POWER_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_POWER_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_power_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_SET_POWER_REQ message */ ++ req->inst_nbr = vif_idx; ++ req->power = pwr; ++ ++ /* Send the MM_SET_POWER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_SET_POWER_CFM, cfm); ++} ++ ++int rwnx_send_set_edca(struct rwnx_hw *rwnx_hw, u8 hw_queue, u32 param, ++ bool uapsd, u8 inst_nbr) ++{ ++ struct mm_set_edca_req *set_edca_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_EDCA_REQ message */ ++ set_edca_req = rwnx_msg_zalloc(MM_SET_EDCA_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_edca_req)); ++ if (!set_edca_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_SET_EDCA_REQ message */ ++ set_edca_req->ac_param = param; ++ set_edca_req->uapsd = uapsd; ++ set_edca_req->hw_queue = hw_queue; ++ set_edca_req->inst_nbr = inst_nbr; ++ ++ /* Send the MM_SET_EDCA_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_edca_req, 1, MM_SET_EDCA_CFM, NULL); ++} ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++int rwnx_send_p2p_oppps_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 ctw, struct mm_set_p2p_oppps_cfm *cfm) ++{ ++ struct mm_set_p2p_oppps_req *p2p_oppps_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_P2P_OPPPS_REQ message */ ++ p2p_oppps_req = rwnx_msg_zalloc(MM_SET_P2P_OPPPS_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_p2p_oppps_req)); ++ ++ if (!p2p_oppps_req) { ++ return -ENOMEM; ++ } ++ ++ /* Fill the message parameters */ ++ p2p_oppps_req->vif_index = rwnx_vif->vif_index; ++ p2p_oppps_req->ctwindow = ctw; ++ ++ /* Send the MM_P2P_OPPPS_REQ message to LMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, p2p_oppps_req, 1, MM_SET_P2P_OPPPS_CFM, cfm); ++ ++ return error; ++} ++ ++int rwnx_send_p2p_noa_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ int count, int interval, int duration, bool dyn_noa, ++ struct mm_set_p2p_noa_cfm *cfm) ++{ ++ struct mm_set_p2p_noa_req *p2p_noa_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Param check */ ++ if (count > 255) ++ count = 255; ++ ++ if (duration >= interval) { ++ dev_err(rwnx_hw->dev, "Invalid p2p NOA config: interval=%d <= duration=%d\n", ++ interval, duration); ++ return -EINVAL; ++ } ++ ++ /* Build the MM_SET_P2P_NOA_REQ message */ ++ p2p_noa_req = rwnx_msg_zalloc(MM_SET_P2P_NOA_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_p2p_noa_req)); ++ ++ if (!p2p_noa_req) { ++ return -ENOMEM; ++ } ++ ++ /* Fill the message parameters */ ++ p2p_noa_req->vif_index = rwnx_vif->vif_index; ++ p2p_noa_req->noa_inst_nb = 0; ++ p2p_noa_req->count = count; ++ ++ if (count) { ++ p2p_noa_req->duration_us = duration * 1024; ++ p2p_noa_req->interval_us = interval * 1024; ++ p2p_noa_req->start_offset = (interval - duration - 10) * 1024; ++ p2p_noa_req->dyn_noa = dyn_noa; ++ } ++ ++ /* Send the MM_SET_2P_NOA_REQ message to LMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, p2p_noa_req, 1, MM_SET_P2P_NOA_CFM, cfm); ++ ++ return error; ++} ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++#ifdef AICWF_ARP_OFFLOAD ++int rwnx_send_arpoffload_en_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u32_l ipaddr, u8_l enable) ++{ ++ struct mm_set_arpoffload_en_req *arp_offload_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_P2P_NOA_REQ message */ ++ arp_offload_req = rwnx_msg_zalloc(MM_SET_ARPOFFLOAD_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_arpoffload_en_req)); ++ ++ if (!arp_offload_req) { ++ return -ENOMEM; ++ } ++ ++ /* Fill the message parameters */ ++ arp_offload_req->enable = enable; ++ arp_offload_req->vif_idx = rwnx_vif->vif_index; ++ arp_offload_req->ipaddr = ipaddr; ++ ++ /* Send the MM_ARPOFFLOAD_EN_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, arp_offload_req, 1, MM_SET_ARPOFFLOAD_CFM, NULL); ++ ++ return error; ++} ++#endif ++ ++int rwnx_send_disable_agg_req(struct rwnx_hw *rwnx_hw, u8_l agg_disable, u8_l agg_disable_rx, u8_l sta_idx) ++{ ++ struct mm_set_agg_disable_req *req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_AGG_DISABLE_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_AGG_DISABLE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_agg_disable_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->disable = agg_disable; ++ req->staidx = sta_idx; ++ req->disable_rx = agg_disable_rx; ++ ++ /* Send the MM_SET_AGG_DISABLE_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_AGG_DISABLE_CFM, NULL); ++ ++ return (error); ++}; ++ ++int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enable_nullcts) ++{ ++ struct mm_set_coex_req *coex_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_COEX_REQ message */ ++ coex_req = rwnx_msg_zalloc(MM_SET_COEX_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_coex_req)); ++ ++ if (!coex_req) { ++ return -ENOMEM; ++ } ++ ++ coex_req->bt_on = 1; ++ coex_req->disable_coexnull = disable_coexnull; ++ coex_req->enable_nullcts = enable_nullcts; ++ coex_req->enable_periodic_timer = 0; ++ coex_req->coex_timeslot_set = 0; ++ ++ /* Send the MM_SET_COEX_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, coex_req, 1, MM_SET_COEX_CFM, NULL); ++ ++ return error; ++}; ++ ++ ++int rwnx_send_rf_config_req(struct rwnx_hw *rwnx_hw, u8_l ofst, u8_l sel, u8_l *tbl, u16_l len) ++{ ++ struct mm_set_rf_config_req *rf_config_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_RF_CONFIG_REQ message */ ++ rf_config_req = rwnx_msg_zalloc(MM_SET_RF_CONFIG_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_rf_config_req)); ++ ++ if (!rf_config_req) { ++ return -ENOMEM; ++ } ++ ++ rf_config_req->table_sel = sel; ++ rf_config_req->table_ofst = ofst; ++ rf_config_req->table_num = 16; ++ rf_config_req->deft_page = 0; ++ ++ memcpy(rf_config_req->data, tbl, len); ++ ++ /* Send the MM_SET_RF_CONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, rf_config_req, 1, MM_SET_RF_CONFIG_CFM, NULL); ++ ++ return (error); ++ ++} ++ ++int rwnx_send_rf_calib_req(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm) ++{ ++ struct mm_set_rf_calib_req *rf_calib_req; ++ xtal_cap_conf_t xtal_cap = {0,}; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_P2P_NOA_REQ message */ ++ rf_calib_req = rwnx_msg_zalloc(MM_SET_RF_CALIB_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_rf_calib_req)); ++ ++ if (!rf_calib_req) { ++ return -ENOMEM; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ rf_calib_req->cal_cfg_24g = 0xbf; ++ rf_calib_req->cal_cfg_5g = 0x3f; ++ } else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ rf_calib_req->cal_cfg_24g = 0x0f8f; ++ rf_calib_req->cal_cfg_5g = 0; ++ } else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rf_calib_req->cal_cfg_24g = 0x0f8f; ++ rf_calib_req->cal_cfg_5g = 0x0f0f; ++ } ++ ++ rf_calib_req->param_alpha = 0x0c34c008; ++ rf_calib_req->bt_calib_en = 0; ++ rf_calib_req->bt_calib_param = 0x264203; ++ ++ get_userconfig_xtal_cap(&xtal_cap); ++ ++ if (xtal_cap.enable) { ++ printk("user xtal cap: %d, cap_fine: %d\n", xtal_cap.xtal_cap, xtal_cap.xtal_cap_fine); ++ rf_calib_req->xtal_cap = xtal_cap.xtal_cap; ++ rf_calib_req->xtal_cap_fine = xtal_cap.xtal_cap_fine; ++ } else { ++ rf_calib_req->xtal_cap = 0; ++ rf_calib_req->xtal_cap_fine = 0; ++ } ++ ++ ++ /* Send the MM_SET_RF_CALIB_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, rf_calib_req, 1, MM_SET_RF_CALIB_CFM, cfm); ++ ++ return error; ++}; ++ ++int rwnx_send_get_macaddr_req(struct rwnx_hw *rwnx_hw, struct mm_get_mac_addr_cfm *cfm) ++{ ++ struct mm_get_mac_addr_req *get_macaddr_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_GET_MAC_ADDR_REQ message */ ++ get_macaddr_req = rwnx_msg_zalloc(MM_GET_MAC_ADDR_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_get_mac_addr_req)); ++ ++ if (!get_macaddr_req) { ++ return -ENOMEM; ++ } ++ ++ get_macaddr_req->get = 1; ++ ++ /* Send the MM_GET_MAC_ADDR_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, get_macaddr_req, 1, MM_GET_MAC_ADDR_CFM, cfm); ++ ++ return error; ++}; ++ ++int rwnx_send_get_sta_info_req(struct rwnx_hw *rwnx_hw, u8_l sta_idx, struct mm_get_sta_info_cfm *cfm) ++{ ++ struct mm_get_sta_info_req *get_info_req; ++ int error; ++ ++ ++ /* Build the MM_GET_STA_INFO_REQ message */ ++ get_info_req = rwnx_msg_zalloc(MM_GET_STA_INFO_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_get_sta_info_req)); ++ ++ if (!get_info_req) { ++ return -ENOMEM; ++ } ++ ++ get_info_req->sta_idx = sta_idx; ++ ++ /* Send the MM_GET_STA_INFO_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, get_info_req, 1, MM_GET_STA_INFO_CFM, cfm); ++ ++ return error; ++}; ++ ++int rwnx_send_set_stack_start_req(struct rwnx_hw *rwnx_hw, u8_l on, u8_l efuse_valid, u8_l set_vendor_info, ++ u8_l fwtrace_redir_en, struct mm_set_stack_start_cfm *cfm) ++{ ++ struct mm_set_stack_start_req *req; ++ int error; ++ ++ /* Build the MM_SET_STACK_START_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_STACK_START_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_stack_start_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->is_stack_start = on; ++ req->efuse_valid = efuse_valid; ++ req->set_vendor_info = set_vendor_info; ++ req->fwtrace_redir = fwtrace_redir_en; ++ /* Send the MM_SET_STACK_START_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_STACK_START_CFM, cfm); ++ ++ return error; ++} ++ ++#ifdef CONFIG_TEMP_COMP ++ ++int rwnx_send_get_temp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the TEMP_COMP_GET_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ AICWFDBG(LOGINFO, "%s msg_alloc fail\n", __func__); ++ return -ENOMEM; ++ } ++ req->swconfig_id = TEMP_COMP_GET_REQ; ++ ++ ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); ++ if (!ret) ++ AICWFDBG(LOGINFO, "status=%d, temp=%d\n", cfm->temp_comp_get_cfm.status, cfm->temp_comp_get_cfm.degree); ++ else { ++ AICWFDBG(LOGINFO, "%s msg_fail\n", __func__); ++ return ret; ++ } ++ //rwnx_hw->started_jiffies = jiffies; ++ rwnx_hw->temp = cfm->temp_comp_get_cfm.degree; ++ ++ return ret; ++} ++ ++ ++int rwnx_send_set_temp_comp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ /* Build the TEMP_COMP_SET_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ printk("%s msg_alloc fail\n", __func__); ++ return -ENOMEM; ++ } ++ req->swconfig_id = TEMP_COMP_SET_REQ; ++ req->temp_comp_set_req.enable = 1; ++ req->temp_comp_set_req.tmr_period_ms = 15 * 1000; ++ ++ ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); ++ if (!ret) ++ printk("temp_comp status: %d\n", cfm->temp_comp_set_cfm.status); ++ else { ++ printk("%s msg_fail\n", __func__); ++ return ret; ++ } ++ return ret; ++} ++#endif ++ ++int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, int32_t *param, int32_t *param_out) ++{ ++ struct mm_set_acs_txop_req *req0; ++ struct mm_set_channel_access_req *req1; ++ struct mm_set_mac_timescale_req *req2; ++ struct mm_set_cca_threshold_req *req3; ++ struct mm_set_bwmode_req *req4; ++ struct mm_set_ap_ps_level_req *req5 = NULL; ++ struct mm_set_customized_freq_req *req6; ++ ++ int error = 0; ++ int i; ++ ++ switch (hwconfig_id) ++ { ++ case ACS_TXOP_REQ: ++ /* Build the ACS_TXOP_REQ message */ ++ req0= rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_acs_txop_req) ); ++ if (!req0) ++ return -ENOMEM; ++ req0->hwconfig_id = hwconfig_id; ++ req0->txop_be = param[0]; ++ req0->txop_bk = param[1]; ++ req0->txop_vi = param[2]; ++ req0->txop_vo = param[3]; ++ printk("set_acs_txop_req: be: %x,bk: %x,vi: %x,vo: %x\n", ++ req0->txop_be, req0->txop_bk, req0->txop_vi, req0->txop_vo); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req0, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ ++ case CHANNEL_ACCESS_REQ: ++ /* Build the CHANNEL_ACCESS_REQ message */ ++ req1 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_channel_access_req)); ++ if (!req1) ++ return -ENOMEM; ++ req1->hwconfig_id = hwconfig_id; ++ req1->edca[0] = param[0]; ++ req1->edca[1] = param[1]; ++ req1->edca[2] = param[2]; ++ req1->edca[3] = param[3]; ++ req1->vif_idx = param[4]; ++ req1->retry_cnt = param[5]; ++ req1->rts_en = param[6]; ++ req1->long_nav_en = param[7]; ++ req1->cfe_en = param[8]; ++ req1->rc_retry_cnt[0] = param[9]; ++ req1->rc_retry_cnt[1] = param[10]; ++ req1->rc_retry_cnt[2] = param[11]; ++ req1->ccademod_th = param[12]; ++ req1->remove_1m2m = param[13]; ++ printk("set_channel_access_req:edca[]= %x %x %x %x\nvif_idx: %x, retry_cnt: %x, rts_en: %x, long_nav_en: %x, cfe_en: %x, rc_retry_cnt: %x:%x:%x, ccademod_th = %d remove_1m2m = %x\n", ++ req1->edca[0], req1->edca[1], req1->edca[2], req1->edca[3], req1->vif_idx, req1->retry_cnt, req1->rts_en, req1->long_nav_en, req1->cfe_en, req1->rc_retry_cnt[0],req1->rc_retry_cnt[1], req1->rc_retry_cnt[2], req1->ccademod_th, req1->remove_1m2m); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req1, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ ++ case MAC_TIMESCALE_REQ: ++ /* Build the MAC_TIMESCALE_REQ message */ ++ req2 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_mac_timescale_req)); ++ if (!req2) ++ return -ENOMEM; ++ req2->hwconfig_id = hwconfig_id; ++ req2->sifsA_time = param[0]; ++ req2->sifsB_time = param[1]; ++ req2->slot_time = param[2]; ++ req2->rx_startdelay_ofdm = param[3]; ++ req2->rx_startdelay_long = param[4]; ++ req2->rx_startdelay_short = param[5]; ++ printk("set_mac_timescale_req:sifsA_time: %x, sifsB_time: %x, slot_time: %x, rx_startdelay ofdm:%x long %x short %x\n", ++ req2->sifsA_time, req2->sifsB_time, req2->slot_time, req2->rx_startdelay_ofdm, req2->rx_startdelay_long, req2->rx_startdelay_short); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req2, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ ++ case CCA_THRESHOLD_REQ: ++ /* Build the CCA_THRESHOLD_REQ message */ ++ req3 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_cca_threshold_req)); ++ if (!req3) ++ return -ENOMEM; ++ req3->hwconfig_id = hwconfig_id; ++ req3->auto_cca_en = param[0]; ++ req3->cca20p_rise_th = param[1]; ++ req3->cca20s_rise_th = param[2]; ++ req3->cca20p_fall_th = param[3]; ++ req3->cca20s_fall_th = param[4]; ++ printk("cca_threshold_req: auto_cca_en:%d\ncca20p_rise_th = %d\ncca20s_rise_th = %d\ncca20p_fall_th = %d\ncca20s_fall_th = %d\n", ++ req3->auto_cca_en, req3->cca20p_rise_th, req3->cca20s_rise_th, req3->cca20p_fall_th, req3->cca20s_fall_th); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req3, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ case BWMODE_REQ: ++ /* Build the SET_BWMODE_REQ message */ ++ req4 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_bwmode_req)); ++ if (!req4) ++ return -ENOMEM; ++ req4->hwconfig_id = hwconfig_id; ++ req4->bwmode = param[0]; ++ printk("bwmode :%d\n", req4->bwmode); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req4, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ case CHIP_TEMP_GET_REQ: ++ if ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) ++ { ++ struct mm_get_chip_temp_req *req; ++ struct mm_set_vendor_hwconfig_cfm cfm = {0,}; ++ /* Build the CHIP_TEMP_GET_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_get_chip_temp_req)); ++ if (!req) ++ return -ENOMEM; ++ req->hwconfig_id = hwconfig_id; ++ /* Send the MM_SET_VENDOR_HWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_HWCONFIG_CFM, &cfm); ++ if (!error) { ++ if (param_out) { ++ param_out[0] = (int32_t)cfm.chip_temp_cfm.degree; ++ } ++ printk("get_chip_temp degree=%d\n", cfm.chip_temp_cfm.degree); ++ } else { ++ printk("get_chip_temp err=%d\n", error); ++ } ++ } ++ break; ++ case AP_PS_LEVEL_SET_REQ: ++ /* ++ AP_PS_CLK_1 = 1, // 3:7 -> active 3, doze 7 ++ AP_PS_CLK_2, // 5:5 -> active 5, doze 5 ++ AP_PS_CLK_3, // 7:3 -> active 7, doze 3 ++ AP_PS_CLK_4, // 8:2 -> active 8, doze 2 ++ AP_PS_CLK_5, // 9:1 -> active 9, doze 1 ++ */ ++ /* Build the MM_SET_VENDOR_HWCONFIG_REQ message */ ++ req5 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_ap_ps_level_req)); ++ if (!req5) { ++ return -ENOMEM; ++ } ++ req5->hwconfig_id = hwconfig_id; ++ req5->ap_ps_level = param[0]; ++ ++ /* Send the MM_GET_MAC_ADDR_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req5, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ if(!error) ++ printk("set ap_ps_level=%d \n",param[0]); ++ break; ++ ++ case CUSTOMIZED_FREQ_REQ: ++ /* Build the CUSTOMIZED_FREQ_REQ message */ ++ req6 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_customized_freq_req)); ++ if (!req6) ++ return -ENOMEM; ++ req5->hwconfig_id = hwconfig_id; ++ for (i = 0; i < 4; i++) { ++ req6->raw_freq[i] = param [i]; ++ req6->map_freq[i] = param [i + 4]; ++ } ++ printk("customized_freq_req: raw_freq[ %d %d %d %d ], map_freq[ %d %d %d %d]\n", ++ param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7]); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req5, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ ++ break; ++ default: ++ return -ENOMEM; ++ } ++ return error; ++} ++ ++int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, int32_t *param_in, int32_t *param_out) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ struct mm_set_vendor_swconfig_cfm cfm = {0,}; ++ int error; ++ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ req->swconfig_id = swconfig_id; ++ ++ switch (swconfig_id) ++ { ++ case BCN_CFG_REQ: ++ /* Build the BCN_CFG_REQ message */ ++ req->bcn_cfg_req.tim_bcmc_ignored_enable = (bool_l)param_in[0]; ++ printk("bcn_cfg_req: tim_bcmc_ignd=%d\n", req->bcn_cfg_req.tim_bcmc_ignored_enable); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (int32_t)cfm.bcn_cfg_cfm.tim_bcmc_ignored_status; ++ printk("status=%d\n", cfm.bcn_cfg_cfm.tim_bcmc_ignored_status); ++ } ++ break; ++ ++ case TEMP_COMP_SET_REQ: ++ /* Build the TEMP_COMP_SET_REQ message */ ++ req->temp_comp_set_req.enable = (u8_l)param_in[0]; ++ req->temp_comp_set_req.tmr_period_ms = (u32_l)param_in[1]; ++ printk("temp_comp_set_req: en=%d, tmr=%x\n", ++ req->temp_comp_set_req.enable, req->temp_comp_set_req.tmr_period_ms); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (int32_t)cfm.temp_comp_set_cfm.status; ++ printk("status=%d\n", cfm.temp_comp_set_cfm.status); ++ } ++ break; ++ ++ case TEMP_COMP_GET_REQ: ++ printk("temp_comp_get_req\n"); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (int32_t)cfm.temp_comp_get_cfm.status; ++ param_out[1] = (int32_t)cfm.temp_comp_get_cfm.degree; ++ printk("status=%d, degree=%d\n", ++ cfm.temp_comp_get_cfm.status, cfm.temp_comp_get_cfm.degree); ++ } ++ break; ++ ++ case EXT_FLAGS_SET_REQ: ++ /* Build the EXT_FLAGS_SET_REQ message */ ++ req->ext_flags_set_req.user_flags = (u32_l)param_in[0]; ++ printk("ext_flags_set_req: flags=%x\n", ++ req->ext_flags_set_req.user_flags); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (uint32_t)cfm.ext_flags_set_cfm.user_flags; ++ printk("cfm flags=%x\n", cfm.ext_flags_set_cfm.user_flags); ++ } ++ break; ++ ++ case EXT_FLAGS_GET_REQ: ++ /* Build the EXT_FLAGS_GET_REQ message */ ++ printk("ext_flags_get_req\n"); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (uint32_t)cfm.ext_flags_get_cfm.user_flags; ++ printk("cfm flags=%x\n", cfm.ext_flags_get_cfm.user_flags); ++ } ++ break; ++ ++ case EXT_FLAGS_MASK_SET_REQ: ++ /* Build the EXT_FLAGS_MASK_SET_REQ message */ ++ req->ext_flags_mask_set_req.user_flags_mask = (u32_l)param_in[0]; ++ req->ext_flags_mask_set_req.user_flags_val = (u32_l)param_in[1]; ++ printk("ext_flags_mask_set_req: flags mask=0x%x, val=0x%x\n", ++ req->ext_flags_mask_set_req.user_flags_mask, req->ext_flags_mask_set_req.user_flags_val); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (uint32_t)cfm.ext_flags_mask_set_cfm.user_flags; ++ printk("cfm flags=%x\n", cfm.ext_flags_mask_set_cfm.user_flags); ++ } ++ break; ++ ++ default: ++ error = -ENOMEM; ++ break; ++ } ++ ++ return error; ++} ++ ++int rwnx_send_mask_set_ext_flags_req(struct rwnx_hw *rwnx_hw, uint32_t flags_mask, uint32_t flags_val, struct mm_set_vendor_swconfig_cfm *cfm) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ /* Build the REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ AICWFDBG(LOGERROR, "%s msg_alloc fail\n", __func__); ++ return -ENOMEM; ++ } ++ req->swconfig_id = EXT_FLAGS_MASK_SET_REQ; ++ req->ext_flags_mask_set_req.user_flags_mask = (u32_l)flags_mask; ++ req->ext_flags_mask_set_req.user_flags_val = (u32_l)flags_val; ++ ++ ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); ++ if (!ret) { ++ AICWFDBG(LOGINFO, "curr ext_flags=%x\n", cfm->ext_flags_mask_set_cfm.user_flags); ++ } else { ++ AICWFDBG(LOGERROR, "%s send_msg_fail\n", __func__); ++ return ret; ++ } ++ return ret; ++} ++ ++#ifdef CONFIG_SDIO_BT ++int rwnx_sdio_bt_send_req(struct rwnx_hw *rwnx_hw,uint32_t len, struct sk_buff *skb) ++{ ++ struct mm_bt_send_req *req; ++ struct mm_bt_send_cfm cfm; ++ int error; ++ ++ if(testmode) { ++ AICWFDBG(LOGERROR, "%s testmode can not send\n", __func__); ++ return 0; ++ } ++ cfm.status = 0; ++ req = rwnx_msg_zalloc(TDLS_SDIO_BT_SEND_REQ, TASK_TDLS, DRV_TASK_ID, sizeof(struct mm_bt_send_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->data_len = len; ++ memcpy(req->bt_data,skb->data,len); ++ ++ error = rwnx_send_msg(rwnx_hw, req, 1, TDLS_SDIO_BT_SEND_CFM, &cfm); ++ if(!cfm.status){ ++ printk("bt send no cfm"); ++ } ++ ++ return error; ++} ++#endif ++ ++int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_version_cfm *cfm) ++{ ++ void *req; ++ int error; ++ ++ /* Build the MM_GET_FW_VERSION_REQ message */ ++ req = rwnx_msg_zalloc(MM_GET_FW_VERSION_REQ, TASK_MM, DRV_TASK_ID, sizeof(u8)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ /* Send the MM_GET_FW_VERSION_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_GET_FW_VERSION_CFM, cfm); ++ ++ return error; ++} ++ ++int rwnx_send_txpwr_lvl_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_req *txpwr_lvl_req; ++ txpwr_lvl_conf_v2_t txpwr_lvl_v2_tmp; ++ txpwr_lvl_conf_v2_t *txpwr_lvl_v2; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_req)); ++ ++ if (!txpwr_lvl_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_v2 = &txpwr_lvl_v2_tmp; ++ ++ get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_v2); ++ ++ if (txpwr_lvl_v2->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v2->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[11]); ++ ++ if ((testmode == 0) && (chip_sub_id == 0)) { ++ txpwr_lvl_req->txpwr_lvl.enable = txpwr_lvl_v2->enable; ++ txpwr_lvl_req->txpwr_lvl.dsss = txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]; // 11M ++ txpwr_lvl_req->txpwr_lvl.ofdmlowrate_2g4= txpwr_lvl_v2->pwrlvl_11ax_2g4[4]; // MCS4 ++ txpwr_lvl_req->txpwr_lvl.ofdm64qam_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[7]; // MCS7 ++ txpwr_lvl_req->txpwr_lvl.ofdm256qam_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[9]; // MCS9 ++ txpwr_lvl_req->txpwr_lvl.ofdm1024qam_2g4= txpwr_lvl_v2->pwrlvl_11ax_2g4[11]; // MCS11 ++ txpwr_lvl_req->txpwr_lvl.ofdmlowrate_5g = 13; // unused ++ txpwr_lvl_req->txpwr_lvl.ofdm64qam_5g = 13; // unused ++ txpwr_lvl_req->txpwr_lvl.ofdm256qam_5g = 13; // unused ++ txpwr_lvl_req->txpwr_lvl.ofdm1024qam_5g = 13; // unused ++ } else { ++ txpwr_lvl_req->txpwr_lvl_v2 = *txpwr_lvl_v2; ++ } ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_req *txpwr_lvl_req; ++ txpwr_lvl_conf_v3_t txpwr_lvl_v3_tmp; ++ txpwr_lvl_conf_v3_t *txpwr_lvl_v3; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++ int error; ++ int i; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_req)); ++ ++ if (!txpwr_lvl_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_v3 = &txpwr_lvl_v3_tmp; ++ txpwr_loss = &txpwr_loss_tmp; ++ txpwr_loss->loss_enable_2g4 = 0; ++ txpwr_loss->loss_enable_5g = 0; ++ ++ get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_v3); ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable_2g4 == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11ax_2g4[i] -= txpwr_loss->loss_value_2g4; ++ } ++ ++ if (txpwr_loss->loss_enable_5g == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11a_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v3->pwrlvl_11n_11ac_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11ax_5g[i] -= txpwr_loss->loss_value_5g; ++ } ++ ++ if (txpwr_lvl_v3->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v3->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_1m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_2m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_5m5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_11m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[11]); ++ ++ txpwr_lvl_req->txpwr_lvl_v3 = *txpwr_lvl_v3; ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_lvl_v4_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_req *txpwr_lvl_req; ++ txpwr_lvl_conf_v4_t txpwr_lvl_v4_tmp; ++ txpwr_lvl_conf_v4_t *txpwr_lvl_v4; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++ int error; ++ int i; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_req)); ++ ++ if (!txpwr_lvl_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_v4 = &txpwr_lvl_v4_tmp; ++ txpwr_loss = &txpwr_loss_tmp; ++ txpwr_loss->loss_enable_2g4 = 0; ++ txpwr_loss->loss_enable_5g = 0; ++ ++ get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_v4); ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable_2g4 == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v4->pwrlvl_11ax_2g4[i] -= txpwr_loss->loss_value_2g4; ++ } ++ ++ if (txpwr_loss->loss_enable_5g == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ ++ for (i = 0; i <= 7; i++) ++ txpwr_lvl_v4->pwrlvl_11a_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v4->pwrlvl_11n_11ac_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v4->pwrlvl_11ax_5g[i] -= txpwr_loss->loss_value_5g; ++ } ++ ++ ++ if (txpwr_lvl_v4->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v4->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[11]); ++ ++ txpwr_lvl_req->txpwr_lvl_v4 = *txpwr_lvl_v4; ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_adj_req *txpwr_lvl_adj_req; ++ txpwr_lvl_adj_conf_t txpwr_lvl_adj_tmp; ++ txpwr_lvl_adj_conf_t *txpwr_lvl_adj; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_adj_req = rwnx_msg_zalloc(MM_SET_TXPWR_LVL_ADJ_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_adj_req)); ++ ++ if (!txpwr_lvl_adj_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_adj = &txpwr_lvl_adj_tmp; ++ ++ get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj); ++ ++ if (txpwr_lvl_adj->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_adj_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_adj->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_1_4:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_5_9:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_10_13:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[2]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_42:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_58:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_106:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_122:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_138:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_155:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[5]); ++ ++ txpwr_lvl_adj_req->txpwr_lvl_adj = *txpwr_lvl_adj; ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_adj_req, 1, MM_SET_TXPWR_LVL_ADJ_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_idx_req *txpwr_idx_req; ++ txpwr_idx_conf_t *txpwr_idx; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_IDX_LVL_REQ message */ ++ txpwr_idx_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_idx_req)); ++ ++ if (!txpwr_idx_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_idx = &txpwr_idx_req->txpwr_idx; ++ txpwr_idx->enable = 1; ++ txpwr_idx->dsss = 9; ++ txpwr_idx->ofdmlowrate_2g4 = 8; ++ txpwr_idx->ofdm64qam_2g4 = 8; ++ txpwr_idx->ofdm256qam_2g4 = 8; ++ txpwr_idx->ofdm1024qam_2g4 = 8; ++ txpwr_idx->ofdmlowrate_5g = 11; ++ txpwr_idx->ofdm64qam_5g = 10; ++ txpwr_idx->ofdm256qam_5g = 9; ++ txpwr_idx->ofdm1024qam_5g = 9; ++ ++ get_userconfig_txpwr_idx(txpwr_idx); ++ ++ if (txpwr_idx->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_idx_req); ++ return 0; ++ } else { ++ /* Send the MM_SET_TXPWR_IDX_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_idx_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return error; ++ } ++}; ++ ++int rwnx_send_txpwr_ofst_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_ofst_req *txpwr_ofst_req; ++ txpwr_ofst_conf_t *txpwr_ofst; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_OFST_REQ message */ ++ txpwr_ofst_req = rwnx_msg_zalloc(MM_SET_TXPWR_OFST_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_ofst_req)); ++ ++ if (!txpwr_ofst_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_ofst = &txpwr_ofst_req->txpwr_ofst; ++ txpwr_ofst->enable = 1; ++ txpwr_ofst->chan_1_4 = 0; ++ txpwr_ofst->chan_5_9 = 0; ++ txpwr_ofst->chan_10_13 = 0; ++ txpwr_ofst->chan_36_64 = 0; ++ txpwr_ofst->chan_100_120 = 0; ++ txpwr_ofst->chan_122_140 = 0; ++ txpwr_ofst->chan_142_165 = 0; ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ get_userconfig_txpwr_ofst(txpwr_ofst); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst); ++ } ++ ++ if (txpwr_ofst->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_ofst_req); ++ return 0; ++ } else { ++ /* Send the MM_SET_TXPWR_OFST_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_ofst_req, 1, MM_SET_TXPWR_OFST_CFM, NULL); ++ ++ return error; ++ } ++}; ++ ++int rwnx_send_txpwr_ofst2x_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_ofst_req *txpwr_ofst_req; ++ txpwr_ofst2x_conf_t *txpwr_ofst2x; ++ int error = 0; ++ int type, ch_grp; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_OFST_REQ message */ ++ txpwr_ofst_req = rwnx_msg_zalloc(MM_SET_TXPWR_OFST_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_ofst_req)); ++ ++ if (!txpwr_ofst_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_ofst2x = &txpwr_ofst_req->txpwr_ofst2x; ++ txpwr_ofst2x->enable = 0; ++ for (type = 0; type < 3; type++) { ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ if (ch_grp < 3) { ++ txpwr_ofst2x->pwrofst2x_tbl_2g4[type][ch_grp] = 0; ++ } ++ txpwr_ofst2x->pwrofst2x_tbl_5g[type][ch_grp] = 0; ++ } ++ } ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x); ++ } ++ if (txpwr_ofst2x->enable){ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_ofst2x->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g: [0]:11b, [1]:ofdm_highrate, [2]:ofdm_lowrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_2g4[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g: [0]:ofdm_lowrate, [1]:ofdm_highrate, [2]:ofdm_midrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_5g[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ ++ /* Send the MM_SET_TXPWR_OFST_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_ofst_req, 1, MM_SET_TXPWR_OFST_CFM, NULL); ++ }else{ ++ AICWFDBG(LOGINFO, "%s:Do not use txpwr_ofst2x\r\n", __func__); ++ rwnx_msg_free(rwnx_hw, txpwr_ofst_req); ++ } ++ ++ return (error); ++} ++ ++int rwnx_send_txpwr_ofst2x_v2_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_ofst_req *txpwr_ofst_req; ++ txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2; ++ int error = 0; ++ int type, ch_grp; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_OFST_REQ message */ ++ txpwr_ofst_req = rwnx_msg_zalloc(MM_SET_TXPWR_OFST_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_ofst_req)); ++ ++ if (!txpwr_ofst_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_ofst2x_v2 = &txpwr_ofst_req->txpwr_ofst2x_v2; ++ txpwr_ofst2x_v2->enable = 0; ++ ++ get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_v2); ++ ++ if (txpwr_ofst2x_v2->enable){ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_ofst2x_v2->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g(ant0/ant1): [0]:11b, [1]:ofdm_highrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 2; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g(ant0/ant1): [0]:ofdm_highrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 1; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ ++ /* Send the MM_SET_TXPWR_OFST_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_ofst_req, 1, MM_SET_TXPWR_OFST_CFM, NULL); ++ }else{ ++ AICWFDBG(LOGINFO, "%s:Do not use txpwr_ofst2x_v2\r\n", __func__); ++ rwnx_msg_free(rwnx_hw, txpwr_ofst_req); ++ } ++ ++ return (error); ++} ++ ++#ifdef CONFIG_APF ++int rwnx_send_set_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len) ++{ ++ struct mm_set_apf_prog_req *req; ++ int error = 0; ++ int buffer_len, buffer_start = 0, buffer_end, page; ++ ++ /* current only 8800d80 support apf */ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80) { ++ return 0; ++ } ++ ++ if (!program) ++ return -ENOMEM; ++ ++ for (page = 0; buffer_start < program_len; page++) { ++ buffer_end = buffer_start + LMAC_MSG_MAX_LEN; ++ if (buffer_end > program_len) ++ buffer_end = program_len; ++ buffer_len = buffer_end - buffer_start; ++ ++ /* Build the MM_SET_TXOP_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_APF_PROG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_apf_prog_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ req->program_len = buffer_len; ++ req->offset = page; ++ memcpy(req->program, program + buffer_start, buffer_len); ++ buffer_start = buffer_end; ++ ++ /* Send the MM_SET_TXOP_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_APF_PROG_CFM, NULL); ++ if (error) ++ break; ++ } ++ return error; ++} ++ ++int rwnx_send_get_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len) ++{ ++ struct mm_get_apf_prog_req *req; ++ int error = 0; ++ struct mm_get_apf_prog_cfm cfm; ++ int buffer_len, buffer_start = 0, buffer_end, page; ++ ++ /* current only 8800d80 support apf */ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80) { ++ return 0; ++ } ++ ++ if (!program) ++ return -ENOMEM; ++ ++ for (page = 0; buffer_start < program_len; page++) { ++ buffer_end = buffer_start + LMAC_MSG_MAX_LEN; ++ if (buffer_end > program_len) ++ buffer_end = program_len; ++ buffer_len = buffer_end - buffer_start; ++ ++ /* Build the MM_SET_TXOP_REQ message */ ++ req = rwnx_msg_zalloc(MM_GET_APF_PROG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_get_apf_prog_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ req->offset = page; ++ /* Send the MM_GET_APF_PROG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_GET_APF_PROG_CFM, &cfm); ++ if (error) ++ break; ++ ++ memcpy(program + buffer_start, cfm.program, buffer_len); ++ buffer_start = buffer_end; ++ } ++ ++ return error; ++} ++#endif ++ ++int rwnx_send_set_filter(struct rwnx_hw *rwnx_hw, uint32_t filter) ++{ ++ struct mm_set_filter_req *set_filter_req_param; ++ uint32_t rx_filter = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_FILTER_REQ message */ ++ set_filter_req_param = ++ rwnx_msg_zalloc(MM_SET_FILTER_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_filter_req)); ++ if (!set_filter_req_param) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_SET_FILTER_REQ message */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++ if (filter & FIF_PROMISC_IN_BSS) ++ rx_filter |= NXMAC_ACCEPT_UNICAST_BIT; ++#endif ++ if (filter & FIF_ALLMULTI) ++ rx_filter |= NXMAC_ACCEPT_MULTICAST_BIT; ++ ++ if (filter & (FIF_FCSFAIL | FIF_PLCPFAIL)) ++ rx_filter |= NXMAC_ACCEPT_ERROR_FRAMES_BIT; ++ ++ if (filter & FIF_BCN_PRBRESP_PROMISC) ++ rx_filter |= NXMAC_ACCEPT_OTHER_BSSID_BIT; ++ ++ if (filter & FIF_CONTROL) ++ rx_filter |= NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT | ++ NXMAC_ACCEPT_CF_END_BIT | ++ NXMAC_ACCEPT_ACK_BIT | ++ NXMAC_ACCEPT_CTS_BIT | ++ NXMAC_ACCEPT_RTS_BIT | ++ NXMAC_ACCEPT_BA_BIT | NXMAC_ACCEPT_BAR_BIT; ++ ++ if (filter & FIF_OTHER_BSS) ++ rx_filter |= NXMAC_ACCEPT_OTHER_BSSID_BIT; ++ ++ if (filter & FIF_PSPOLL) { ++ /* TODO: check if the MAC filters apply to our BSSID or is general */ ++ rx_filter |= NXMAC_ACCEPT_PS_POLL_BIT; ++ } ++ ++ if (filter & FIF_PROBE_REQ) { ++ rx_filter |= NXMAC_ACCEPT_PROBE_REQ_BIT; ++ rx_filter |= NXMAC_ACCEPT_ALL_BEACON_BIT; ++ } ++ ++ /* Add the filter flags that are set by default and cannot be changed here */ ++ rx_filter |= RWNX_MAC80211_NOT_CHANGEABLE; ++ ++ /* XXX */ ++ //if (ieee80211_hw_check(rwnx_hw->hw, AMPDU_AGGREGATION)) ++ rx_filter |= NXMAC_ACCEPT_BA_BIT; ++ ++ /* Now copy all the flags into the message parameter */ ++ set_filter_req_param->filter = rx_filter; ++ ++ RWNX_DBG("new total_flags = 0x%08x rx filter set to 0x%08x\r\n", ++ filter, rx_filter); ++ ++ /* Send the MM_SET_FILTER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_filter_req_param, 1, MM_SET_FILTER_CFM, NULL); ++} ++ ++ ++/****************************************************************************** ++ * Control messages handling functions (FULLMAC only) ++ *****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++extern struct ieee80211_sband_iftype_data rwnx_he_capa; ++#endif ++#ifdef CONFIG_VHT_FOR_OLD_KERNEL ++static struct ieee80211_sta_vht_cap* rwnx_vht_capa; ++#endif ++int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct me_config_req *req; ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ ++ struct ieee80211_sta_ht_cap *ht_cap; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ struct ieee80211_sta_vht_cap *vht_cap; ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ struct ieee80211_sta_he_cap const *he_cap = NULL; ++#else ++ #ifdef CONFIG_HE_FOR_OLD_KERNEL ++ struct ieee80211_sta_he_cap const *he_cap; ++ #endif ++#endif ++ uint8_t *ht_mcs; ++ int i; ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ ht_cap = &wiphy->bands[NL80211_BAND_5GHZ]->ht_cap; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ vht_cap = &wiphy->bands[NL80211_BAND_5GHZ]->vht_cap; ++ #endif ++ } else { ++ ht_cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ vht_cap = &wiphy->bands[NL80211_BAND_2GHZ]->vht_cap; ++ #endif ++ } ++ #ifdef CONFIG_VHT_FOR_OLD_KERNEL ++ rwnx_vht_capa = vht_cap; ++ #endif ++ ++ ht_mcs = (uint8_t *)&ht_cap->mcs; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_CONFIG_REQ message */ ++ req = rwnx_msg_zalloc(ME_CONFIG_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_config_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_CONFIG_REQ message */ ++ req->ht_supp = ht_cap->ht_supported; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ req->vht_supp = vht_cap->vht_supported; ++ #endif ++ req->ht_cap.ht_capa_info = cpu_to_le16(ht_cap->cap | IEEE80211_HT_CAP_LDPC_CODING); ++ req->ht_cap.a_mpdu_param = ht_cap->ampdu_factor | ++ (ht_cap->ampdu_density << ++ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); ++ for (i = 0; i < sizeof(ht_cap->mcs); i++) ++ req->ht_cap.mcs_rate[i] = ht_mcs[i]; ++ req->ht_cap.ht_extended_capa = 0; ++ req->ht_cap.tx_beamforming_capa = 0; ++ req->ht_cap.asel_capa = 0; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ if (req->vht_supp) { ++ req->vht_cap.vht_capa_info = cpu_to_le32(vht_cap->cap); ++ req->vht_cap.rx_highest = cpu_to_le16(vht_cap->vht_mcs.rx_highest); ++ req->vht_cap.rx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.rx_mcs_map); ++ req->vht_cap.tx_highest = cpu_to_le16(vht_cap->vht_mcs.tx_highest); ++ req->vht_cap.tx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.tx_mcs_map); ++ } ++ #endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) || defined(CONFIG_HE_FOR_OLD_KERNEL) ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (wiphy->bands[NL80211_BAND_2GHZ]->iftype_data != NULL) { ++ he_cap = &wiphy->bands[NL80211_BAND_2GHZ]->iftype_data->he_cap; ++ //} ++ #endif ++ #if defined(CONFIG_HE_FOR_OLD_KERNEL) ++ if (1) { ++ he_cap = &rwnx_he_capa.he_cap; ++ #endif ++ req->he_supp = he_cap->has_he; ++ for (i = 0; i < ARRAY_SIZE(he_cap->he_cap_elem.mac_cap_info); i++) { ++ req->he_cap.mac_cap_info[i] = he_cap->he_cap_elem.mac_cap_info[i]; ++ } ++ for (i = 0; i < ARRAY_SIZE(he_cap->he_cap_elem.phy_cap_info); i++) { ++ req->he_cap.phy_cap_info[i] = he_cap->he_cap_elem.phy_cap_info[i]; ++ } ++ req->he_cap.mcs_supp.rx_mcs_80 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_80); ++ req->he_cap.mcs_supp.tx_mcs_80 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_80); ++ req->he_cap.mcs_supp.rx_mcs_160 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_160); ++ req->he_cap.mcs_supp.tx_mcs_160 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_160); ++ req->he_cap.mcs_supp.rx_mcs_80p80 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_80p80); ++ req->he_cap.mcs_supp.tx_mcs_80p80 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_80p80); ++ for (i = 0; i < MAC_HE_PPE_THRES_MAX_LEN; i++) { ++ req->he_cap.ppe_thres[i] = he_cap->ppe_thres[i]; ++ } ++ req->he_ul_on = rwnx_hw->mod_params->he_ul_on; ++ } ++#else ++ req->he_supp = false; ++ req->he_ul_on = false; ++#endif ++ req->ps_on = rwnx_hw->mod_params->ps_on; ++ req->dpsm = rwnx_hw->mod_params->dpsm; ++ req->tx_lft = rwnx_hw->mod_params->tx_lft; ++ req->ant_div_on = rwnx_hw->mod_params->ant_div; ++ if (rwnx_hw->mod_params->use_80) ++ req->phy_bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ req->phy_bw_max = PHY_CHNL_BW_40; ++ else ++ req->phy_bw_max = PHY_CHNL_BW_20; ++ ++ wiphy_info(wiphy, "HT supp %d, VHT supp %d, HE supp %d\n", req->ht_supp, ++ req->vht_supp, ++ req->he_supp); ++ /* Send the ME_CONFIG_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_CONFIG_CFM, NULL); ++} ++ ++int rwnx_send_me_chan_config_req(struct rwnx_hw *rwnx_hw, char *ccode) ++{ ++ struct me_chan_config_req *req; ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ int i; ++#ifdef CONFIG_POWER_LIMIT ++ int8_t max_pwr; ++ uint8_t r_idx; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++#endif ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_CHAN_CONFIG_REQ message */ ++ req = rwnx_msg_zalloc(ME_CHAN_CONFIG_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_chan_config_req)); ++ if (!req) ++ return -ENOMEM; ++ ++#ifdef CONFIG_POWER_LIMIT ++ txpwr_loss = &txpwr_loss_tmp; ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ if (txpwr_loss->loss_enable_5g == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ r_idx = get_ccode_region(ccode); ++#endif ++ ++ req->chan2G4_cnt = 0; ++ if (wiphy->bands[NL80211_BAND_2GHZ] != NULL) { ++ struct ieee80211_supported_band *b = wiphy->bands[NL80211_BAND_2GHZ]; ++ for (i = 0; i < b->n_channels; i++) { ++ req->chan2G4[req->chan2G4_cnt].flags = 0; ++ if (b->channels[i].flags & IEEE80211_CHAN_DISABLED) ++ req->chan2G4[req->chan2G4_cnt].flags |= CHAN_DISABLED; ++ req->chan2G4[req->chan2G4_cnt].flags |= get_chan_flags(b->channels[i].flags); ++ req->chan2G4[req->chan2G4_cnt].band = NL80211_BAND_2GHZ; ++ req->chan2G4[req->chan2G4_cnt].freq = b->channels[i].center_freq; ++ req->chan2G4[req->chan2G4_cnt].tx_power = chan_to_fw_pwr(b->channels[i].max_power); ++#ifdef CONFIG_POWER_LIMIT ++ { ++ max_pwr = get_powerlimit_by_freq(PHY_BAND_2G4, req->chan2G4[req->chan2G4_cnt].freq, r_idx); ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ max_pwr -= txpwr_loss->loss_value_2g4; ++ if (req->chan2G4[req->chan2G4_cnt].tx_power > max_pwr) ++ req->chan2G4[req->chan2G4_cnt].tx_power = max_pwr; ++ } ++#endif ++ req->chan2G4_cnt++; ++ if (req->chan2G4_cnt == MAC_DOMAINCHANNEL_24G_MAX) ++ break; ++ } ++ } ++ ++ req->chan5G_cnt = 0; ++ if (wiphy->bands[NL80211_BAND_5GHZ] != NULL) { ++ struct ieee80211_supported_band *b = wiphy->bands[NL80211_BAND_5GHZ]; ++ for (i = 0; i < b->n_channels; i++) { ++ req->chan5G[req->chan5G_cnt].flags = 0; ++ if (b->channels[i].flags & IEEE80211_CHAN_DISABLED) ++ req->chan5G[req->chan5G_cnt].flags |= CHAN_DISABLED; ++ req->chan5G[req->chan5G_cnt].flags |= get_chan_flags(b->channels[i].flags); ++ req->chan5G[req->chan5G_cnt].band = NL80211_BAND_5GHZ; ++ req->chan5G[req->chan5G_cnt].freq = b->channels[i].center_freq; ++ req->chan5G[req->chan5G_cnt].tx_power = chan_to_fw_pwr(b->channels[i].max_power); ++#ifdef CONFIG_POWER_LIMIT ++ { ++ max_pwr = get_powerlimit_by_freq( PHY_BAND_5G, req->chan5G[req->chan5G_cnt].freq, r_idx); ++ if (txpwr_loss->loss_enable_5g == 1) ++ max_pwr -= txpwr_loss->loss_value_5g; ++ if (req->chan5G[req->chan5G_cnt].tx_power > max_pwr) ++ req->chan5G[req->chan5G_cnt].tx_power = max_pwr; ++ } ++#endif ++ req->chan5G_cnt++; ++ if (req->chan5G_cnt == MAC_DOMAINCHANNEL_5G_MAX) ++ break; ++ } ++ } ++ ++ /* Send the ME_CHAN_CONFIG_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_CHAN_CONFIG_CFM, NULL); ++} ++ ++int rwnx_send_me_set_control_port_req(struct rwnx_hw *rwnx_hw, bool opened, u8 sta_idx) ++{ ++ struct me_set_control_port_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_SET_CONTROL_PORT_REQ message */ ++ req = rwnx_msg_zalloc(ME_SET_CONTROL_PORT_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_set_control_port_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_SET_CONTROL_PORT_REQ message */ ++ req->sta_idx = sta_idx; ++ req->control_port_open = opened; ++ ++ /* Send the ME_SET_CONTROL_PORT_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_CONTROL_PORT_CFM, NULL); ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)) ++struct ieee80211_he_cap_elem_4_19 { ++ u8 mac_cap_info[6]; ++ u8 phy_cap_info[11]; ++} __packed; ++#endif ++ ++int rwnx_send_me_sta_add(struct rwnx_hw *rwnx_hw, struct station_parameters *params, ++ const u8 *mac, u8 inst_nbr, struct me_sta_add_cfm *cfm) ++{ ++ struct me_sta_add_req *req; ++ ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ struct link_station_parameters *link_sta_params = ¶ms->link_sta_params; ++#else ++ struct station_parameters *link_sta_params = params; ++#endif ++ u8 *ht_mcs = (u8 *)&link_sta_params->ht_capa->mcs; ++ ++ int i; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[inst_nbr]; ++ #if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ struct aic_sta *sta = &rwnx_hw->aic_table[rwnx_vif->ap.aic_index]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("assoc_req idx %d, he: %d, vht: %d\n ", rwnx_vif->ap.aic_index, sta->he, sta->vht); ++ if (rwnx_vif->ap.aic_index < NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX) ++ rwnx_vif->ap.aic_index++; ++ else ++ rwnx_vif->ap.aic_index = 0; ++ #endif ++ ++ /* Build the MM_STA_ADD_REQ message */ ++ req = rwnx_msg_zalloc(ME_STA_ADD_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_sta_add_req)); ++ if (!req){ ++ return -ENOMEM; ++ } ++ ++ /* Set parameters for the MM_STA_ADD_REQ message */ ++ memcpy(&(req->mac_addr.array[0]), mac, ETH_ALEN); ++ ++ req->rate_set.length = link_sta_params->supported_rates_len; ++ for (i = 0; i < link_sta_params->supported_rates_len; i++) ++ req->rate_set.array[i] = link_sta_params->supported_rates[i]; ++ ++ req->flags = 0; ++ if (link_sta_params->ht_capa) { ++ const struct ieee80211_ht_cap *ht_capa = link_sta_params->ht_capa; ++ ++ req->flags |= STA_HT_CAPA; ++ req->ht_cap.ht_capa_info = cpu_to_le16(ht_capa->cap_info); ++ req->ht_cap.a_mpdu_param = ht_capa->ampdu_params_info; ++ for (i = 0; i < sizeof(ht_capa->mcs); i++) ++ req->ht_cap.mcs_rate[i] = ht_mcs[i]; ++ req->ht_cap.ht_extended_capa = cpu_to_le16(ht_capa->extended_ht_cap_info); ++ req->ht_cap.tx_beamforming_capa = cpu_to_le32(ht_capa->tx_BF_cap_info); ++ req->ht_cap.asel_capa = ht_capa->antenna_selection_info; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) ++ if (link_sta_params->vht_capa) { ++ const struct ieee80211_vht_cap *vht_capa = link_sta_params->vht_capa; ++ ++ req->flags |= STA_VHT_CAPA; ++ req->vht_cap.vht_capa_info = cpu_to_le32(vht_capa->vht_cap_info); ++ req->vht_cap.rx_highest = cpu_to_le16(vht_capa->supp_mcs.rx_highest); ++ req->vht_cap.rx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.rx_mcs_map); ++ req->vht_cap.tx_highest = cpu_to_le16(vht_capa->supp_mcs.tx_highest); ++ req->vht_cap.tx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.tx_mcs_map); ++ } ++#elif defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ if (sta->vht) { ++ //const struct ieee80211_vht_cap *vht_capa = rwnx_vht_capa; ++ ++ req->flags |= STA_VHT_CAPA; ++ req->vht_cap.vht_capa_info = cpu_to_le32(rwnx_vht_capa->cap); ++ req->vht_cap.rx_highest = sta->supp_mcs.rx_highest;//cpu_to_le16(rwnx_vht_capa->vht_mcs.rx_highest); ++ req->vht_cap.rx_mcs_map = sta->supp_mcs.rx_mcs_map;//cpu_to_le16(rwnx_vht_capa->vht_mcs.rx_mcs_map); ++ req->vht_cap.tx_highest = sta->supp_mcs.tx_highest;//cpu_to_le16(rwnx_vht_capa->vht_mcs.tx_highest); ++ req->vht_cap.tx_mcs_map = sta->supp_mcs.tx_mcs_map;//cpu_to_le16(rwnx_vht_capa->vht_mcs.tx_mcs_map); ++ } ++#endif ++ ++ AICWFDBG(LOGDEBUG,"rx map %x rx high %x tx map %x tx high %x \n",req->vht_cap.rx_mcs_map,req->vht_cap.rx_highest,req->vht_cap.tx_mcs_map,req->vht_cap.tx_highest); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (link_sta_params->he_capa) { ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) ++ const struct ieee80211_he_cap_elem_4_19 *he_capa = (const struct ieee80211_he_cap_elem_4_19 *) link_sta_params->he_capa; ++ #else ++ const struct ieee80211_he_cap_elem *he_capa = link_sta_params->he_capa; ++ #endif ++ struct ieee80211_he_mcs_nss_supp *mcs_nss_supp = ++ (struct ieee80211_he_mcs_nss_supp *)(he_capa + 1); ++ ++ req->flags |= STA_HE_CAPA; ++ for (i = 0; i < ARRAY_SIZE(he_capa->mac_cap_info); i++) { ++ req->he_cap.mac_cap_info[i] = he_capa->mac_cap_info[i]; ++ } ++ for (i = 0; i < ARRAY_SIZE(he_capa->phy_cap_info); i++) { ++ req->he_cap.phy_cap_info[i] = he_capa->phy_cap_info[i]; ++ } ++ req->he_cap.mcs_supp.rx_mcs_80 = mcs_nss_supp->rx_mcs_80; ++ req->he_cap.mcs_supp.tx_mcs_80 = mcs_nss_supp->tx_mcs_80; ++ req->he_cap.mcs_supp.rx_mcs_160 = mcs_nss_supp->rx_mcs_160; ++ req->he_cap.mcs_supp.tx_mcs_160 = mcs_nss_supp->tx_mcs_160; ++ req->he_cap.mcs_supp.rx_mcs_80p80 = mcs_nss_supp->rx_mcs_80p80; ++ req->he_cap.mcs_supp.tx_mcs_80p80 = mcs_nss_supp->tx_mcs_80p80; ++ } ++#else ++ #ifdef CONFIG_HE_FOR_OLD_KERNEL ++ if (sta->he) { ++ const struct ieee80211_he_cap_elem *he_capa = &rwnx_he_capa.he_cap.he_cap_elem; ++ struct ieee80211_he_mcs_nss_supp *mcs_nss_supp = ++ (struct ieee80211_he_mcs_nss_supp *)(he_capa + 1); ++ req->flags |= STA_HE_CAPA; ++ for (i = 0; i < ARRAY_SIZE(he_capa->mac_cap_info); i++) { ++ req->he_cap.mac_cap_info[i] = sta->he_cap_elem.mac_cap_info[i];//he_capa->mac_cap_info[i]; ++ } ++ for (i = 0; i < ARRAY_SIZE(he_capa->phy_cap_info); i++) { ++ req->he_cap.phy_cap_info[i] = sta->he_cap_elem.phy_cap_info[i];//he_capa->phy_cap_info[i]; ++ } ++ req->he_cap.mcs_supp.rx_mcs_80 = sta->he_mcs_nss_supp.rx_mcs_80;//mcs_nss_supp->rx_mcs_80; ++ req->he_cap.mcs_supp.tx_mcs_80 = sta->he_mcs_nss_supp.tx_mcs_80;//mcs_nss_supp->tx_mcs_80; ++ req->he_cap.mcs_supp.rx_mcs_160 = mcs_nss_supp->rx_mcs_160; ++ req->he_cap.mcs_supp.tx_mcs_160 = mcs_nss_supp->tx_mcs_160; ++ req->he_cap.mcs_supp.rx_mcs_80p80 = mcs_nss_supp->rx_mcs_80p80; ++ req->he_cap.mcs_supp.tx_mcs_80p80 = mcs_nss_supp->tx_mcs_80p80; ++ } ++ #endif ++#endif ++ ++ AICWFDBG(LOGDEBUG,"rwnx sta add he mcs/nss rx mcs 80 0x%04x \n",le16_to_cpu(req->he_cap.mcs_supp.rx_mcs_80)); ++ AICWFDBG(LOGDEBUG,"rwnx sta add he mcs/nss tx mcs 80 0x%04x \n",le16_to_cpu(req->he_cap.mcs_supp.tx_mcs_80)); ++ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) ++ req->flags |= STA_QOS_CAPA; ++ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_MFP)) ++ req->flags |= STA_MFP_CAPA; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ if (link_sta_params->opmode_notif_used) { ++ req->flags |= STA_OPMOD_NOTIF; ++ req->opmode = link_sta_params->opmode_notif_used; ++ } ++ #endif ++ ++ req->aid = cpu_to_le16(params->aid); ++ req->uapsd_queues = params->uapsd_queues; ++ req->max_sp_len = params->max_sp * 2; ++ req->vif_idx = inst_nbr; ++ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { ++ //struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[inst_nbr]; ++ req->tdls_sta = true; ++ if ((params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) && ++ !rwnx_vif->tdls_chsw_prohibited) ++ req->tdls_chsw_allowed = true; ++ if (rwnx_vif->tdls_status == TDLS_SETUP_RSP_TX) ++ req->tdls_sta_initiator = true; ++ } ++ ++ /* Send the ME_STA_ADD_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_STA_ADD_CFM, cfm); ++} ++ ++int rwnx_send_me_sta_del(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool tdls_sta) ++{ ++ struct me_sta_del_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_STA_DEL_REQ message */ ++ req = rwnx_msg_zalloc(ME_STA_DEL_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_sta_del_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_STA_DEL_REQ message */ ++ req->sta_idx = sta_idx; ++ req->tdls_sta = tdls_sta; ++ ++ /* Send the ME_STA_DEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_STA_DEL_CFM, NULL); ++} ++ ++int rwnx_send_me_traffic_ind(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool uapsd, u8 tx_status) ++{ ++ struct me_traffic_ind_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_UTRAFFIC_IND_REQ message */ ++ req = rwnx_msg_zalloc(ME_TRAFFIC_IND_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_traffic_ind_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_TRAFFIC_IND_REQ message */ ++ req->sta_idx = sta_idx; ++ req->tx_avail = tx_status; ++ req->uapsd = uapsd; ++ ++ /* Send the ME_TRAFFIC_IND_REQ to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_TRAFFIC_IND_CFM, NULL); ++} ++ ++int rwnx_send_me_rc_stats(struct rwnx_hw *rwnx_hw, ++ u8 sta_idx, ++ struct me_rc_stats_cfm *cfm) ++{ ++ struct me_rc_stats_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_RC_STATS_REQ message */ ++ req = rwnx_msg_zalloc(ME_RC_STATS_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_rc_stats_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_RC_STATS_REQ message */ ++ req->sta_idx = sta_idx; ++ ++ /* Send the ME_RC_STATS_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_RC_STATS_CFM, cfm); ++} ++ ++int rwnx_send_me_rc_set_rate(struct rwnx_hw *rwnx_hw, ++ u8 sta_idx, ++ u16 rate_cfg) ++{ ++ struct me_rc_set_rate_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_RC_SET_RATE_REQ message */ ++ req = rwnx_msg_zalloc(ME_RC_SET_RATE_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_rc_set_rate_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_RC_SET_RATE_REQ message */ ++ req->sta_idx = sta_idx; ++ req->fixed_rate_cfg = rate_cfg; ++ ++ /* Send the ME_RC_SET_RATE_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 0, 0, NULL); ++} ++ ++int rwnx_send_me_set_ps_mode(struct rwnx_hw *rwnx_hw, u8 ps_mode) ++{ ++ struct me_set_ps_mode_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_SET_PS_MODE_REQ message */ ++ req = rwnx_msg_zalloc(ME_SET_PS_MODE_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_set_ps_mode_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_SET_PS_MODE_REQ message */ ++ req->ps_state = ps_mode; ++ ++ /* Send the ME_SET_PS_MODE_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_PS_MODE_CFM, NULL); ++} ++ ++int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter) ++{ ++ struct me_set_lp_level_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ printk("%s %d %d \n", __func__, lp_level, disable_filter); ++ /* Build the ME_SET_LP_LEVEL_REQ message */ ++ req = rwnx_msg_zalloc(ME_SET_LP_LEVEL_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_set_lp_level_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_SET_LP_LEVEL_REQ message */ ++ req->lp_level = lp_level; ++ req->disable_filter = disable_filter; ++ /* Send the ME_SET_LP_LEVEL_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_LP_LEVEL_CFM, NULL); ++} ++ ++int rwnx_send_sm_connect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct cfg80211_connect_params *sme, ++ struct sm_connect_cfm *cfm) ++{ ++ struct sm_connect_req *req; ++ int i; ++ u32_l flags = 0; ++ bool gval = false; ++ bool pval = false; ++ rwnx_vif->wep_enabled = false; ++ rwnx_vif->wep_auth_err = false; ++ rwnx_vif->last_auth_type = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SM_CONNECT_REQ message */ ++ req = rwnx_msg_zalloc(SM_CONNECT_REQ, TASK_SM, DRV_TASK_ID, ++ sizeof(struct sm_connect_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if ((sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)) { ++ gval = true; ++ } ++ ++ if (sme->crypto.n_ciphers_pairwise && ++ ((sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104))) { ++ pval = true; ++ } ++ ++ /* Set parameters for the SM_CONNECT_REQ message */ ++ if (sme->crypto.n_ciphers_pairwise && ++ ((sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_TKIP) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104))) ++ flags |= DISABLE_HT; ++ ++ if (sme->crypto.control_port) ++ flags |= CONTROL_PORT_HOST; ++ ++ if (sme->crypto.control_port_no_encrypt) ++ flags |= CONTROL_PORT_NO_ENC; ++ ++ if (use_pairwise_key(&sme->crypto)) ++ flags |= WPA_WPA2_IN_USE; ++ ++ if (sme->mfp == NL80211_MFP_REQUIRED) ++ flags |= MFP_IN_USE; ++ ++ if (rwnx_vif->sta.ap) ++ flags |= REASSOCIATION; ++ ++ req->ctrl_port_ethertype = sme->crypto.control_port_ethertype; ++ ++ if (sme->bssid) ++ memcpy(&req->bssid, sme->bssid, ETH_ALEN); ++ else ++ req->bssid = mac_addr_bcst; ++ req->vif_idx = rwnx_vif->vif_index; ++ if (sme->channel) { ++ req->chan.band = sme->channel->band; ++ req->chan.freq = sme->channel->center_freq; ++ req->chan.flags = get_chan_flags(sme->channel->flags); ++ } else { ++ req->chan.freq = (u16_l)-1; ++ } ++ for (i = 0; i < sme->ssid_len; i++) ++ req->ssid.array[i] = sme->ssid[i]; ++ req->ssid.length = sme->ssid_len; ++ req->flags = flags; ++ if (WARN_ON(sme->ie_len > sizeof(req->ie_buf))) ++ goto invalid_param; ++ if (sme->ie_len) ++ memcpy(req->ie_buf, sme->ie, sme->ie_len); ++ req->ie_len = sme->ie_len; ++ req->listen_interval = rwnx_mod_params.listen_itv; ++ req->dont_wait_bcmc = !rwnx_mod_params.listen_bcmc; ++ ++ /* Set auth_type */ ++ if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) ++ req->auth_type = WLAN_AUTH_OPEN; ++ else if (sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ++ req->auth_type = WLAN_AUTH_OPEN; ++ else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ++ req->auth_type = WLAN_AUTH_SHARED_KEY; ++ else if (sme->auth_type == NL80211_AUTHTYPE_FT) { ++ req->auth_type = WLAN_AUTH_FT; ++ } else if (sme->auth_type == NL80211_AUTHTYPE_SAE) ++ req->auth_type = WLAN_AUTH_SAE; ++ else ++ goto invalid_param; ++ ++ /* Set UAPSD queues */ ++ req->uapsd_queues = rwnx_mod_params.uapsd_queues; ++ ++ rwnx_vif->wep_enabled = pval & gval; ++ ++ if (rwnx_vif->wep_enabled) { ++ rwnx_vif->last_auth_type = sme->auth_type; ++ } ++ ++ rwnx_vif->sta.ssid_len = (int)sme->ssid_len; ++ memset(rwnx_vif->sta.ssid, 0, rwnx_vif->sta.ssid_len + 1); ++ memcpy(rwnx_vif->sta.ssid, sme->ssid, rwnx_vif->sta.ssid_len); ++ if (sme->bssid) ++ memcpy(rwnx_vif->sta.bssid, sme->bssid, ETH_ALEN); ++ ++ printk("%s drv_vif_index:%d connect to %s(%d) channel:%d auth_type:%d\r\n", ++ __func__, ++ rwnx_vif->drv_vif_index, ++ rwnx_vif->sta.ssid, ++ rwnx_vif->sta.ssid_len, ++ req->chan.freq, ++ req->auth_type); ++ ++ /* Send the SM_CONNECT_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SM_CONNECT_CFM, cfm); ++ ++invalid_param: ++ rwnx_msg_free(rwnx_hw, req); ++ return -EINVAL; ++} ++ ++int rwnx_send_sm_disconnect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 reason) ++{ ++ struct sm_disconnect_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SM_DISCONNECT_REQ message */ ++ req = rwnx_msg_zalloc(SM_DISCONNECT_REQ, TASK_SM, DRV_TASK_ID, ++ sizeof(struct sm_disconnect_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the SM_DISCONNECT_REQ message */ ++ req->reason_code = reason; ++ req->vif_idx = rwnx_vif->vif_index; ++ ++ /* Send the SM_DISCONNECT_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SM_DISCONNECT_CFM, NULL); ++} ++ ++int rwnx_send_sm_external_auth_required_rsp(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 status) ++{ ++ struct sm_external_auth_required_rsp *rsp; ++ ++ /* Build the SM_EXTERNAL_AUTH_CFM message */ ++ rsp = rwnx_msg_zalloc(SM_EXTERNAL_AUTH_REQUIRED_RSP, TASK_SM, DRV_TASK_ID, ++ sizeof(struct sm_external_auth_required_rsp)); ++ if (!rsp) ++ return -ENOMEM; ++ ++ rsp->status = status; ++ rsp->vif_idx = rwnx_vif->vif_index; ++ ++ /* send the SM_EXTERNAL_AUTH_REQUIRED_RSP message UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, rsp, 1, SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM, NULL); ++} ++ ++int rwnx_send_apm_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_ap_settings *settings, ++ struct apm_start_cfm *cfm, ++ struct rwnx_ipc_elem_var *elem) ++{ ++ struct apm_start_req *req; ++ struct rwnx_bcn *bcn = &vif->ap.bcn; ++ u8 *buf; ++ u32 flags = 0; ++ const u8 *rate_ie; ++ u8 rate_len = 0; ++ int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); ++ const u8 *var_pos; ++ int len, i; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_START_REQ message */ ++ req = rwnx_msg_zalloc(APM_START_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_start_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ // Build the beacon ++ bcn->dtim = (u8)settings->dtim_period; ++ buf = rwnx_build_bcn(bcn, &settings->beacon); ++ if (!buf) { ++ rwnx_msg_free(rwnx_hw, req); ++ return -ENOMEM; ++ } ++ ++ // Retrieve the basic rate set from the beacon buffer ++ len = bcn->len - var_offset; ++ var_pos = buf + var_offset; ++ ++// Assume that rate higher that 54 Mbps are BSS membership ++#define IS_BASIC_RATE(r) ((r & 0x80) && ((r & ~0x80) <= (54 * 2))) ++ ++ rate_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); ++ if (rate_ie) { ++ const u8 *rates = rate_ie + 2; ++ for (i = 0; (i < rate_ie[1]) && (rate_len < MAC_RATESET_LEN); i++) { ++ if (IS_BASIC_RATE(rates[i])) ++ req->basic_rates.array[rate_len++] = rates[i]; ++ } ++ } ++ rate_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, var_pos, len); ++ if (rate_ie) { ++ const u8 *rates = rate_ie + 2; ++ for (i = 0; (i < rate_ie[1]) && (rate_len < MAC_RATESET_LEN); i++) { ++ if (IS_BASIC_RATE(rates[i])) ++ req->basic_rates.array[rate_len++] = rates[i]; ++ } ++ } ++ req->basic_rates.length = rate_len; ++#undef IS_BASIC_RATE ++ ++#if 0 ++ // Sync buffer for FW ++ error = rwnx_ipc_elem_var_allocs(rwnx_hw, elem, bcn->len, DMA_TO_DEVICE, buf, NULL, NULL); ++ if (error) { ++ return error; ++ } ++#else ++ rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn->len); ++#endif ++ ++ /* Set parameters for the APM_START_REQ message */ ++ req->vif_idx = vif->vif_index; ++ req->bcn_addr = elem->dma_addr; ++ req->bcn_len = bcn->len; ++ req->tim_oft = bcn->head_len; ++ req->tim_len = bcn->tim_len; ++ req->chan.band = settings->chandef.chan->band; ++ req->chan.freq = settings->chandef.chan->center_freq; ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ req->chan.flags = get_chan_flags(settings->chandef.chan->flags); ++#else ++ req->chan.flags = 0; ++#endif ++ printk("chan.flags %u \n",req->chan.flags); ++ req->chan.tx_power = chan_to_fw_pwr(settings->chandef.chan->max_power); ++ req->center_freq1 = settings->chandef.center_freq1; ++ req->center_freq2 = settings->chandef.center_freq2; ++ req->ch_width = bw2chnl[settings->chandef.width]; ++ req->bcn_int = settings->beacon_interval; ++ if (settings->crypto.control_port) ++ flags |= CONTROL_PORT_HOST; ++ ++ if (settings->crypto.control_port_no_encrypt) ++ flags |= CONTROL_PORT_NO_ENC; ++ ++ if (use_pairwise_key(&settings->crypto)) ++ flags |= WPA_WPA2_IN_USE; ++ ++ if (settings->crypto.control_port_ethertype) ++ req->ctrl_port_ethertype = settings->crypto.control_port_ethertype; ++ else ++ req->ctrl_port_ethertype = ETH_P_PAE; ++ req->flags = flags; ++ ++ /* Send the APM_START_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_START_CFM, cfm); ++} ++ ++int rwnx_send_apm_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif) ++{ ++ struct apm_stop_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_STOP_REQ message */ ++ req = rwnx_msg_zalloc(APM_STOP_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_stop_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the APM_STOP_REQ message */ ++ req->vif_idx = vif->vif_index; ++ ++ /* Send the APM_STOP_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_STOP_CFM, NULL); ++} ++ ++uint8_t scanning;// = 0; ++ ++#define P2P_WILDCARD_SSID "DIRECT-" ++#define P2P_WILDCARD_SSID_LEN (sizeof(P2P_WILDCARD_SSID) - 1) ++ ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++u8_l vendor_extension_data[256]; ++u8_l vendor_extension_len = 0; ++#if 0 ++u8_l vendor_extension_data[]={ ++ 0x10,0x49,0x00,0x17,0x00,0x01,0x37,0x10, ++ 0x06,0x00,0x10,0xc5,0xc9,0x91,0xeb,0x1f, ++ 0xce,0x4d,0x00,0xa1,0x2a,0xdf,0xa1,0xe9, ++ 0xc3,0x44,0xe6,0x10,0x49,0x00,0x21,0x00, ++ 0x01,0x37,0x20,0x01,0x00,0x01,0x05,0x20, ++ 0x02,0x00,0x04,0x43,0x56,0x54,0x45,0x20, ++ 0x05,0x00,0x0d,0x31,0x39,0x32,0x2e,0x31, ++ 0x36,0x38,0x2e,0x31,0x35,0x34,0x2e,0x31}; ++#endif ++ ++void rwnx_insert_vendor_extension_data(struct scanu_vendor_ie_req *ie_req){ ++ u8_l temp_ie[256]; ++ u8_l vendor_extension_subelement[3] = {0x00,0x37,0x2A}; ++ u8_l vendor_extension_id[2] = {0x10,0x49}; ++ int index = 0; ++ int vendor_extension_subelement_len = 0; ++ ++ memset(temp_ie, 0, 256); ++ ++ //find vendor_extension_subelement ++ for(index = 0; index < ie_req->add_ie_len; index++){ ++ if(ie_req->ie[index] == vendor_extension_id[0]){ ++ index++; ++ if(index == ie_req->add_ie_len){ ++ return; ++ } ++ if(ie_req->ie[index] == vendor_extension_id[1] && ++ ie_req->ie[index + 3] == vendor_extension_subelement[0]&& ++ ie_req->ie[index + 4] == vendor_extension_subelement[1]&& ++ ie_req->ie[index + 5] == vendor_extension_subelement[2]){ ++ index = index + 2; ++ vendor_extension_subelement_len = ie_req->ie[index]; ++ printk("%s find vendor_extension_subelement,index:%d len:%d\r\n", __func__, index, ie_req->ie[index]); ++ break; ++ } ++ } ++ } ++ index = index + vendor_extension_subelement_len; ++ ++ //insert vendor extension ++ memcpy(&temp_ie[0], ie_req->ie, index + 1); ++ memcpy(&temp_ie[index + 1], vendor_extension_data, vendor_extension_len/*sizeof(vendor_extension_data)*/);//insert vendor extension data ++ memcpy(&temp_ie[index + 1 + vendor_extension_len/*sizeof(vendor_extension_data)*/], &ie_req->ie[index + 1], ie_req->add_ie_len - index); ++ ++ memcpy(ie_req->ie, temp_ie, ie_req->add_ie_len + vendor_extension_len/*sizeof(vendor_extension_data)*/); ++ ie_req->add_ie_len = ie_req->add_ie_len + vendor_extension_len/*sizeof(vendor_extension_data)*/; ++ ie_req->ie[1] = ie_req->ie[1] + vendor_extension_len/*sizeof(vendor_extension_data)*/; ++ ++ //rwnx_data_dump((char*)__func__, (void*)ie_req->ie, ie_req->add_ie_len); ++} ++#endif//CONFIG_SET_VENDOR_EXTENSION_IE ++ ++ ++int rwnx_send_scanu_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct cfg80211_scan_request *param) ++{ ++ struct scanu_start_req *req = NULL; ++ struct scanu_vendor_ie_req *ie_req = NULL; ++ struct mm_add_if_cfm add_if_cfm; ++ int i; ++ uint8_t chan_flags = 0; ++ int err; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SCANU_START_REQ message */ ++ req = rwnx_msg_zalloc(SCANU_START_REQ, TASK_SCANU, DRV_TASK_ID, ++ sizeof(struct scanu_start_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ scanning = 1; ++ /* Set parameters */ ++ req->vif_idx = rwnx_vif->vif_index; ++ req->chan_cnt = (u8)min_t(int, SCAN_CHANNEL_MAX, param->n_channels); ++ req->ssid_cnt = (u8)min_t(int, SCAN_SSID_MAX, param->n_ssids); ++ req->bssid = mac_addr_bcst; ++ req->no_cck = param->no_cck; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ if (param->duration_mandatory) ++ //req->duration = ieee80211_tu_to_usec(param->duration); ++ req->duration = 0; ++#endif ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ if (req->ssid_cnt == 0) ++ chan_flags |= CHAN_NO_IR; ++#endif ++ for (i = 0; i < req->ssid_cnt; i++) { ++ int j; ++ for (j = 0; j < param->ssids[i].ssid_len; j++) ++ req->ssid[i].array[j] = param->ssids[i].ssid[j]; ++ req->ssid[i].length = param->ssids[i].ssid_len; ++ ++ if (!memcmp(P2P_WILDCARD_SSID, param->ssids[i].ssid, ++ P2P_WILDCARD_SSID_LEN)) { ++ AICWFDBG(LOGINFO, "p2p scanu:%d,%d,%d\n", rwnx_vif->vif_index, rwnx_vif->is_p2p_vif, rwnx_hw->is_p2p_alive); ++#ifdef CONFIG_USE_P2P0 ++ if (rwnx_vif->is_p2p_vif && !rwnx_hw->is_p2p_alive) { ++#else ++ if (rwnx_vif == rwnx_hw->p2p_dev_vif && !rwnx_vif->up) { ++#endif ++ err = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, ++ RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); ++ if (err) ++ goto error; ++ ++ if (add_if_cfm.status != 0) { ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++ rwnx_hw->is_p2p_alive = 1; ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ AICWFDBG(LOGINFO, "p2p scan start\n"); ++ } ++ } ++ ++#if 1 ++ if (param->ie) { ++ #if 0 ++ if (rwnx_ipc_elem_var_allocs(rwnx_hw, &rwnx_hw->scan_ie, ++ param->ie_len, DMA_TO_DEVICE, ++ NULL, param->ie, NULL)) ++ goto error; ++ ++ req->add_ie_len = param->ie_len; ++ req->add_ies = rwnx_hw->scan_ie.dma_addr; ++ #else ++ ie_req = rwnx_msg_zalloc(SCANU_VENDOR_IE_REQ, TASK_SCANU, DRV_TASK_ID, ++ sizeof(struct scanu_vendor_ie_req)); ++ if (!ie_req) ++ return -ENOMEM; ++ ++ ie_req->add_ie_len = param->ie_len; ++ ie_req->vif_idx = rwnx_vif->vif_index; ++ memcpy(ie_req->ie, param->ie, param->ie_len); ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++ rwnx_insert_vendor_extension_data(ie_req); ++#endif //CONFIG_SET_VENDOR_EXTENSION_IE ++ req->add_ie_len = 0; ++ req->add_ies = 0; ++ ++ err = rwnx_send_msg(rwnx_hw, ie_req, 1, SCANU_VENDOR_IE_CFM, NULL); ++ if (err) ++ goto error; ++ #endif ++ } ++ else { ++ req->add_ie_len = 0; ++ req->add_ies = 0; ++ } ++#else ++ req->add_ie_len = 0; ++ req->add_ies = 0; ++#endif ++ ++ for (i = 0; i < req->chan_cnt; i++) { ++ struct ieee80211_channel *chan = param->channels[i]; ++ AICWFDBG(LOGDEBUG, "scan channel:%d(%d) \r\n", ieee80211_frequency_to_channel(chan->center_freq), chan->center_freq); ++ req->chan[i].band = chan->band; ++ req->chan[i].freq = chan->center_freq; ++ req->chan[i].flags = chan_flags | get_chan_flags(chan->flags); ++ req->chan[i].tx_power = chan_to_fw_pwr(chan->max_reg_power); ++ } ++ ++ /* Send the SCANU_START_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SCANU_START_CFM_ADDTIONAL, NULL); ++error: ++ if (req != NULL) ++ rwnx_msg_free(rwnx_hw, req); ++ if (ie_req != NULL) ++ rwnx_msg_free(rwnx_hw, ie_req); ++ return -ENOMEM; ++} ++ ++int rwnx_send_scanu_cancel_req(struct rwnx_hw *rwnx_hw, struct scan_cancel_cfm *cfm) ++{ ++ struct scan_cancel_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SCAN_CANCEL_REQ message */ ++ req = rwnx_msg_zalloc(SCANU_CANCEL_REQ, TASK_SCANU, DRV_TASK_ID, ++ sizeof(struct scan_cancel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Send the SCAN_CANCEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SCANU_CANCEL_CFM, cfm); ++} ++ ++int rwnx_send_apm_start_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_chan_def *chandef, ++ struct apm_start_cac_cfm *cfm) ++{ ++ struct apm_start_cac_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_START_CAC_REQ message */ ++ req = rwnx_msg_zalloc(APM_START_CAC_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_start_cac_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the APM_START_CAC_REQ message */ ++ req->vif_idx = vif->vif_index; ++ req->chan.band = chandef->chan->band; ++ req->chan.type = bw2chnl[chandef->width]; ++ req->chan.prim20_freq = chandef->chan->center_freq; ++ req->chan.center1_freq = chandef->center_freq1; ++ req->chan.center2_freq = chandef->center_freq2; ++ req->chan.tx_power = 20; ++ req->chan.flags = get_chan_flags(chandef->chan->flags); ++ ++ /* Send the APM_START_CAC_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_START_CAC_CFM, cfm); ++} ++ ++int rwnx_send_apm_stop_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif) ++{ ++ struct apm_stop_cac_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_STOP_CAC_REQ message */ ++ req = rwnx_msg_zalloc(APM_STOP_CAC_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_stop_cac_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the APM_STOP_CAC_REQ message */ ++ req->vif_idx = vif->vif_index; ++ ++ /* Send the APM_STOP_CAC_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_STOP_CAC_CFM, NULL); ++} ++ ++int rwnx_send_mesh_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ const struct mesh_config *conf, const struct mesh_setup *setup, ++ struct mesh_start_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_start_req *req; ++ // Supported basic rates ++ struct ieee80211_supported_band *band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ /* Counter */ ++ int i; ++ /* Return status */ ++ int status; ++ /* DMA Address to be unmapped after confirmation reception */ ++ u32 dma_addr = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_START_REQ message */ ++ req = rwnx_msg_zalloc(MESH_START_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_start_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->vif_index = vif->vif_index; ++ req->bcn_int = setup->beacon_interval; ++ req->dtim_period = setup->dtim_period; ++ req->mesh_id_len = setup->mesh_id_len; ++ ++ for (i = 0; i < setup->mesh_id_len; i++) { ++ req->mesh_id[i] = *(setup->mesh_id + i); ++ } ++ ++ req->user_mpm = setup->user_mpm; ++ req->is_auth = setup->is_authenticated; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) ++ req->auth_id = setup->auth_id; ++ #endif ++ req->ie_len = setup->ie_len; ++ ++ if (setup->ie_len) { ++ /* ++ * Need to provide a Virtual Address to the MAC so that it can download the ++ * additional information elements. ++ */ ++ req->ie_addr = dma_map_single(rwnx_hw->dev, (void *)setup->ie, ++ setup->ie_len, DMA_FROM_DEVICE); ++ ++ /* Check DMA mapping result */ ++ if (dma_mapping_error(rwnx_hw->dev, req->ie_addr)) { ++ printk(KERN_CRIT "%s - DMA Mapping error on additional IEs\n", __func__); ++ ++ /* Consider there is no Additional IEs */ ++ req->ie_len = 0; ++ } else { ++ /* Store DMA Address so that we can unmap the memory section once MESH_START_CFM is received */ ++ dma_addr = req->ie_addr; ++ } ++ } ++ ++ /* Provide rate information */ ++ req->basic_rates.length = 0; ++ for (i = 0; i < band_2GHz->n_bitrates; i++) { ++ u16 rate = band_2GHz->bitrates[i].bitrate; ++ ++ /* Read value is in in units of 100 Kbps, provided value is in units ++ * of 1Mbps, and multiplied by 2 so that 5.5 becomes 11 */ ++ rate = (rate << 1) / 10; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) // TODO: check basic rates ++ if (setup->basic_rates & CO_BIT(i)) { ++ rate |= 0x80; ++ } ++ #endif ++ ++ req->basic_rates.array[i] = (u8)rate; ++ req->basic_rates.length++; ++ } ++ ++ /* Provide channel information */ ++ req->chan.band = setup->chandef.chan->band; ++ req->chan.freq = setup->chandef.chan->center_freq; ++ req->chan.flags = 0; ++ req->chan.tx_power = chan_to_fw_pwr(setup->chandef.chan->max_power); ++ req->center_freq1 = setup->chandef.center_freq1; ++ req->center_freq2 = setup->chandef.center_freq2; ++ req->ch_width = bw2chnl[setup->chandef.width]; ++ ++ /* Send the MESH_START_REQ message to UMAC FW */ ++ status = rwnx_send_msg(rwnx_hw, req, 1, MESH_START_CFM, cfm); ++ ++ /* Unmap DMA area */ ++ if (setup->ie_len) { ++ dma_unmap_single(rwnx_hw->dev, dma_addr, setup->ie_len, DMA_TO_DEVICE); ++ } ++ ++ /* Return the status */ ++ return status; ++} ++ ++int rwnx_send_mesh_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct mesh_stop_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_stop_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_STOP_REQ message */ ++ req = rwnx_msg_zalloc(MESH_STOP_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_stop_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->vif_idx = vif->vif_index; ++ ++ /* Send the MESH_STOP_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_STOP_CFM, cfm); ++} ++ ++int rwnx_send_mesh_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u32 mask, const struct mesh_config *p_mconf, struct mesh_update_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_update_req *req; ++ // Keep only bit for fields which can be updated ++ u32 supp_mask = (mask << 1) & (CO_BIT(NL80211_MESHCONF_GATE_ANNOUNCEMENTS) ++ | CO_BIT(NL80211_MESHCONF_HWMP_ROOTMODE) ++ | CO_BIT(NL80211_MESHCONF_FORWARDING) ++ | CO_BIT(NL80211_MESHCONF_POWER_MODE)); ++ ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (!supp_mask) { ++ return -ENOENT; ++ } ++ ++ /* Build the MESH_UPDATE_REQ message */ ++ req = rwnx_msg_zalloc(MESH_UPDATE_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_update_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->vif_idx = vif->vif_index; ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_GATE_ANNOUNCEMENTS)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_GATE_MODE_BIT); ++ req->gate_announ = p_mconf->dot11MeshGateAnnouncementProtocol; ++ } ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_HWMP_ROOTMODE)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_ROOT_MODE_BIT); ++ req->root_mode = p_mconf->dot11MeshHWMPRootMode; ++ } ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_FORWARDING)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_MESH_FWD_BIT); ++ req->mesh_forward = p_mconf->dot11MeshForwarding; ++ } ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_POWER_MODE)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_LOCAL_PSM_BIT); ++ req->local_ps_mode = p_mconf->power_mode; ++ } ++ ++ /* Send the MESH_UPDATE_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_UPDATE_CFM, cfm); ++} ++ ++int rwnx_send_mesh_peer_info_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, struct mesh_peer_info_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_peer_info_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PEER_INFO_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PEER_INFO_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_peer_info_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->sta_idx = sta_idx; ++ ++ /* Send the MESH_PEER_INFO_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_PEER_INFO_CFM, cfm); ++} ++ ++void rwnx_send_mesh_peer_update_ntf(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, u8 mlink_state) ++{ ++ // Message to send ++ struct mesh_peer_update_ntf *ntf; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PEER_UPDATE_NTF message */ ++ ntf = rwnx_msg_zalloc(MESH_PEER_UPDATE_NTF, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_peer_update_ntf)); ++ ++ if (ntf) { ++ ntf->vif_idx = vif->vif_index; ++ ntf->sta_idx = sta_idx; ++ ntf->state = mlink_state; ++ ++ /* Send the MESH_PEER_INFO_REQ message to UMAC FW */ ++ rwnx_send_msg(rwnx_hw, ntf, 0, 0, NULL); ++ } ++} ++ ++void rwnx_send_mesh_path_create_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *tgt_addr) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Check if we are already waiting for a confirmation */ ++ if (!vif->ap.create_path) { ++ // Message to send ++ struct mesh_path_create_req *req; ++ ++ /* Build the MESH_PATH_CREATE_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PATH_CREATE_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_path_create_req)); ++ ++ if (req) { ++ req->vif_idx = vif->vif_index; ++ memcpy(&req->tgt_mac_addr, tgt_addr, ETH_ALEN); ++ ++ vif->ap.create_path = true; ++ ++ /* Send the MESH_PATH_CREATE_REQ message to UMAC FW */ ++ rwnx_send_msg(rwnx_hw, req, 0, 0, NULL); ++ } ++ } ++} ++ ++int rwnx_send_mesh_path_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, const u8 *tgt_addr, ++ const u8 *p_nhop_addr, struct mesh_path_update_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_path_update_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PATH_UPDATE_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PATH_UPDATE_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_path_update_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->delete = (p_nhop_addr == NULL); ++ req->vif_idx = vif->vif_index; ++ memcpy(&req->tgt_mac_addr, tgt_addr, ETH_ALEN); ++ ++ if (p_nhop_addr) { ++ memcpy(&req->nhop_mac_addr, p_nhop_addr, ETH_ALEN); ++ } ++ ++ /* Send the MESH_PATH_UPDATE_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_PATH_UPDATE_CFM, cfm); ++} ++ ++void rwnx_send_mesh_proxy_add_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *ext_addr) ++{ ++ // Message to send ++ struct mesh_proxy_add_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PROXY_ADD_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PROXY_ADD_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_proxy_add_req)); ++ ++ if (req) { ++ req->vif_idx = vif->vif_index; ++ memcpy(&req->ext_sta_addr, ext_addr, ETH_ALEN); ++ ++ /* Send the MESH_PROXY_ADD_REQ message to UMAC FW */ ++ rwnx_send_msg(rwnx_hw, req, 0, 0, NULL); ++ } ++} ++ ++int rwnx_send_tdls_peer_traffic_ind_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif) ++{ ++ struct tdls_peer_traffic_ind_req *tdls_peer_traffic_ind_req; ++ ++ if (!rwnx_vif->sta.tdls_sta) ++ return -ENOLINK; ++ ++ /* Build the TDLS_PEER_TRAFFIC_IND_REQ message */ ++ tdls_peer_traffic_ind_req = rwnx_msg_zalloc(TDLS_PEER_TRAFFIC_IND_REQ, TASK_TDLS, DRV_TASK_ID, ++ sizeof(struct tdls_peer_traffic_ind_req)); ++ ++ if (!tdls_peer_traffic_ind_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the TDLS_PEER_TRAFFIC_IND_REQ message */ ++ tdls_peer_traffic_ind_req->vif_index = rwnx_vif->vif_index; ++ tdls_peer_traffic_ind_req->sta_idx = rwnx_vif->sta.tdls_sta->sta_idx; ++ memcpy(&(tdls_peer_traffic_ind_req->peer_mac_addr.array[0]), ++ rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN); ++ tdls_peer_traffic_ind_req->dialog_token = 0; // check dialog token value ++ tdls_peer_traffic_ind_req->last_tid = rwnx_vif->sta.tdls_sta->tdls.last_tid; ++ tdls_peer_traffic_ind_req->last_sn = rwnx_vif->sta.tdls_sta->tdls.last_sn; ++ ++ /* Send the TDLS_PEER_TRAFFIC_IND_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, tdls_peer_traffic_ind_req, 0, 0, NULL); ++} ++ ++int rwnx_send_config_monitor_req(struct rwnx_hw *rwnx_hw, ++ struct cfg80211_chan_def *chandef, ++ struct me_config_monitor_cfm *cfm) ++{ ++ struct me_config_monitor_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_CONFIG_MONITOR_REQ message */ ++ req = rwnx_msg_zalloc(ME_CONFIG_MONITOR_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_config_monitor_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if (chandef) { ++ req->chan_set = true; ++ ++ req->chan.band = chandef->chan->band; ++ req->chan.type = bw2chnl[chandef->width]; ++ req->chan.prim20_freq = chandef->chan->center_freq; ++ req->chan.center1_freq = chandef->center_freq1; ++ req->chan.center2_freq = chandef->center_freq2; ++ req->chan.tx_power = chan_to_fw_pwr(chandef->chan->max_power); ++ ++ if (rwnx_hw->phy.limit_bw) ++ limit_chan_bw(&req->chan.type, req->chan.prim20_freq, &req->chan.center1_freq); ++ } else { ++ req->chan_set = false; ++ } ++ ++ req->uf = rwnx_hw->mod_params->uf; ++ req->auto_reply = rwnx_hw->mod_params->auto_reply; ++ ++ /* Send the ME_CONFIG_MONITOR_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_CONFIG_MONITOR_CFM, cfm); ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++int rwnx_send_tdls_chan_switch_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, bool sta_initiator, ++ u8 oper_class, struct cfg80211_chan_def *chandef, ++ struct tdls_chan_switch_cfm *cfm) ++{ ++ struct tdls_chan_switch_req *tdls_chan_switch_req; ++ ++ ++ /* Build the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_chan_switch_req = rwnx_msg_zalloc(TDLS_CHAN_SWITCH_REQ, TASK_TDLS, DRV_TASK_ID, ++ sizeof(struct tdls_chan_switch_req)); ++ ++ if (!tdls_chan_switch_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_chan_switch_req->vif_index = rwnx_vif->vif_index; ++ tdls_chan_switch_req->sta_idx = rwnx_sta->sta_idx; ++ memcpy(&(tdls_chan_switch_req->peer_mac_addr.array[0]), ++ rwnx_sta_addr(rwnx_sta), ETH_ALEN); ++ tdls_chan_switch_req->initiator = sta_initiator; ++ tdls_chan_switch_req->band = chandef->chan->band; ++ tdls_chan_switch_req->type = bw2chnl[chandef->width]; ++ tdls_chan_switch_req->prim20_freq = chandef->chan->center_freq; ++ tdls_chan_switch_req->center1_freq = chandef->center_freq1; ++ tdls_chan_switch_req->center2_freq = chandef->center_freq2; ++ tdls_chan_switch_req->tx_power = chan_to_fw_pwr(chandef->chan->max_power); ++ tdls_chan_switch_req->op_class = oper_class; ++ ++ /* Send the TDLS_CHAN_SWITCH_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, tdls_chan_switch_req, 1, TDLS_CHAN_SWITCH_CFM, cfm); ++} ++ ++int rwnx_send_tdls_cancel_chan_switch_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, ++ struct tdls_cancel_chan_switch_cfm *cfm) ++{ ++ struct tdls_cancel_chan_switch_req *tdls_cancel_chan_switch_req; ++ ++ /* Build the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_cancel_chan_switch_req = rwnx_msg_zalloc(TDLS_CANCEL_CHAN_SWITCH_REQ, TASK_TDLS, DRV_TASK_ID, ++ sizeof(struct tdls_cancel_chan_switch_req)); ++ if (!tdls_cancel_chan_switch_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_cancel_chan_switch_req->vif_index = rwnx_vif->vif_index; ++ tdls_cancel_chan_switch_req->sta_idx = rwnx_sta->sta_idx; ++ memcpy(&(tdls_cancel_chan_switch_req->peer_mac_addr.array[0]), ++ rwnx_sta_addr(rwnx_sta), ETH_ALEN); ++ ++ /* Send the TDLS_CHAN_SWITCH_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, tdls_cancel_chan_switch_req, 1, TDLS_CANCEL_CHAN_SWITCH_CFM, cfm); ++} ++ ++#ifdef CONFIG_RWNX_BFMER ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_send_bfmer_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ const struct ieee80211_vht_cap *vht_cap) ++#endif /* CONFIG_RWNX_FULLMAC*/ ++{ ++ struct mm_bfmer_enable_req *bfmer_en_req; ++#ifdef CONFIG_RWNX_FULLMAC ++ __le32 vht_capability; ++ u8 rx_nss = 0; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (!vht_cap) { ++#endif /* CONFIG_RWNX_FULLMAC */ ++ goto end; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ vht_capability = vht_cap->vht_cap_info; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (!(vht_capability & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) { ++ goto end; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ rx_nss = rwnx_bfmer_get_rx_nss(vht_cap); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ /* Allocate a structure that will contain the beamforming report */ ++ if (rwnx_bfmer_report_add(rwnx_hw, rwnx_sta, RWNX_BFMER_REPORT_SPACE_SIZE)) { ++ goto end; ++ } ++ ++ /* Build the MM_BFMER_ENABLE_REQ message */ ++ bfmer_en_req = rwnx_msg_zalloc(MM_BFMER_ENABLE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_bfmer_enable_req)); ++ ++ /* Check message allocation */ ++ if (!bfmer_en_req) { ++ /* Free memory allocated for the report */ ++ rwnx_bfmer_report_del(rwnx_hw, rwnx_sta); ++ ++ /* Do not use beamforming */ ++ goto end; ++ } ++ ++ /* Provide DMA address to the MAC */ ++ bfmer_en_req->host_bfr_addr = rwnx_sta->bfm_report->dma_addr; ++ bfmer_en_req->host_bfr_size = RWNX_BFMER_REPORT_SPACE_SIZE; ++ bfmer_en_req->sta_idx = rwnx_sta->sta_idx; ++#ifdef CONFIG_RWNX_FULLMAC ++ bfmer_en_req->aid = rwnx_sta->aid; ++ bfmer_en_req->rx_nss = rx_nss; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (vht_capability & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) { ++ bfmer_en_req->vht_mu_bfmee = true; ++ } else { ++ bfmer_en_req->vht_mu_bfmee = false; ++ } ++ ++ /* Send the MM_BFMER_EN_REQ message to LMAC FW */ ++ rwnx_send_msg(rwnx_hw, bfmer_en_req, 0, 0, NULL); ++ ++end: ++ return; ++} ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++int rwnx_send_mu_group_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) ++{ ++ struct mm_mu_group_update_req *req; ++ int group_id, i = 0; ++ u64 map; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_MU_GROUP_UPDATE_REQ message */ ++ req = rwnx_msg_zalloc(MM_MU_GROUP_UPDATE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_mu_group_update_req) + ++ rwnx_sta->group_info.cnt * sizeof(req->groups[0])); ++ ++ /* Check message allocation */ ++ if (!req) ++ return -ENOMEM; ++ ++ /* Go through the groups the STA belongs to */ ++ group_sta_for_each(rwnx_sta, group_id, map) { ++ int user_pos = rwnx_mu_group_sta_get_pos(rwnx_hw, rwnx_sta, group_id); ++ ++ if (WARN((i >= rwnx_sta->group_info.cnt), ++ "STA%d: Too much group (%d)\n", ++ rwnx_sta->sta_idx, i + 1)) ++ break; ++ ++ req->groups[i].group_id = group_id; ++ req->groups[i].user_pos = user_pos; ++ ++ i++; ++ } ++ ++ req->group_cnt = rwnx_sta->group_info.cnt; ++ req->sta_idx = rwnx_sta->sta_idx; ++ ++ /* Send the MM_MU_GROUP_UPDATE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_MU_GROUP_UPDATE_CFM, NULL); ++} ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* CONFIG_RWNX_BFMER */ ++ ++/********************************************************************** ++ * Debug Messages ++ *********************************************************************/ ++int rwnx_send_dbg_trigger_req(struct rwnx_hw *rwnx_hw, char *msg) ++{ ++ struct mm_dbg_trigger_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_DBG_TRIGGER_REQ message */ ++ req = rwnx_msg_zalloc(MM_DBG_TRIGGER_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_dbg_trigger_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_DBG_TRIGGER_REQ message */ ++ strncpy(req->error, msg, sizeof(req->error)); ++ ++ /* Send the MM_DBG_TRIGGER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 0, -1, NULL); ++} ++ ++int rwnx_send_dbg_mem_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm) ++{ ++ struct dbg_mem_read_req *mem_read_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_READ_REQ message */ ++ mem_read_req = rwnx_msg_zalloc(DBG_MEM_READ_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_read_req)); ++ if (!mem_read_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_READ_REQ message */ ++ mem_read_req->memaddr = mem_addr; ++ ++ /* Send the DBG_MEM_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_read_req, 1, DBG_MEM_READ_CFM, cfm); ++} ++ ++int rwnx_send_dbg_mem_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_data) ++{ ++ struct dbg_mem_write_req *mem_write_req; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_WRITE_REQ message */ ++ mem_write_req = rwnx_msg_zalloc(DBG_MEM_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_write_req)); ++ if (!mem_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_WRITE_REQ message */ ++ mem_write_req->memaddr = mem_addr; ++ mem_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_write_req, 1, DBG_MEM_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_mask_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_mask, u32 mem_data) ++{ ++ struct dbg_mem_mask_write_req *mem_mask_write_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req = rwnx_msg_zalloc(DBG_MEM_MASK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_mask_write_req)); ++ if (!mem_mask_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req->memaddr = mem_addr; ++ mem_mask_write_req->memmask = mem_mask; ++ mem_mask_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_MASK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_mask_write_req, 1, DBG_MEM_MASK_WRITE_CFM, NULL); ++} ++ ++#ifdef CONFIG_RFTEST ++int rwnx_send_rftest_req(struct rwnx_hw *rwnx_hw, u32_l cmd, u32_l argc, u8_l *argv, struct dbg_rftest_cmd_cfm *cfm) ++{ ++ struct dbg_rftest_cmd_req *mem_rftest_cmd_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_RFTEST_CMD_REQ message */ ++ mem_rftest_cmd_req = rwnx_msg_zalloc(DBG_RFTEST_CMD_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_rftest_cmd_req)); ++ if (!mem_rftest_cmd_req) ++ return -ENOMEM; ++ ++ if (argc > 10) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_rftest_cmd_req->cmd = cmd; ++ mem_rftest_cmd_req->argc = argc; ++ if (argc != 0) ++ memcpy(mem_rftest_cmd_req->argv, argv, argc); ++ ++ /* Send the DBG_RFTEST_CMD_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_rftest_cmd_req, 1, DBG_RFTEST_CMD_CFM, cfm); ++} ++#endif ++ ++#ifdef CONFIG_MCU_MESSAGE ++int rwnx_send_dbg_custom_msg_req(struct rwnx_hw *rwnx_hw, ++ u32 cmd, void *buf, u32 len, u32 action, ++ struct dbg_custom_msg_cfm *cfm) ++{ ++ struct dbg_custom_msg_req *cust_msg_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_CUSTOM_MSG_REQ message */ ++ cust_msg_req = ++ rwnx_msg_zalloc(DBG_CUSTOM_MSG_REQ, TASK_DBG, DRV_TASK_ID, ++ offsetof(struct dbg_custom_msg_req, buf) + len); ++ if (!cust_msg_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_CUSTOM_MSG_REQ message */ ++ cust_msg_req->cmd = cmd; ++ cust_msg_req->len = len; ++ cust_msg_req->flags = action; ++ if (buf) { ++ memcpy(cust_msg_req->buf, buf, len); ++ } ++ ++ /* Send the DBG_CUSTOM_MSG_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, cust_msg_req, 1, DBG_CUSTOM_MSG_CFM, cfm); ++} ++#endif ++ ++int rwnx_send_dbg_set_mod_filter_req(struct rwnx_hw *rwnx_hw, u32 filter) ++{ ++ struct dbg_set_mod_filter_req *set_mod_filter_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_SET_MOD_FILTER_REQ message */ ++ set_mod_filter_req = ++ rwnx_msg_zalloc(DBG_SET_MOD_FILTER_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_set_mod_filter_req)); ++ if (!set_mod_filter_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_SET_MOD_FILTER_REQ message */ ++ set_mod_filter_req->mod_filter = filter; ++ ++ /* Send the DBG_SET_MOD_FILTER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_mod_filter_req, 1, DBG_SET_MOD_FILTER_CFM, NULL); ++} ++ ++int rwnx_send_dbg_set_sev_filter_req(struct rwnx_hw *rwnx_hw, u32 filter) ++{ ++ struct dbg_set_sev_filter_req *set_sev_filter_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_SET_SEV_FILTER_REQ message */ ++ set_sev_filter_req = ++ rwnx_msg_zalloc(DBG_SET_SEV_FILTER_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_set_sev_filter_req)); ++ if (!set_sev_filter_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_SET_SEV_FILTER_REQ message */ ++ set_sev_filter_req->sev_filter = filter; ++ ++ /* Send the DBG_SET_SEV_FILTER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_sev_filter_req, 1, DBG_SET_SEV_FILTER_CFM, NULL); ++} ++ ++int rwnx_send_dbg_get_sys_stat_req(struct rwnx_hw *rwnx_hw, ++ struct dbg_get_sys_stat_cfm *cfm) ++{ ++ void *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Allocate the message */ ++ req = rwnx_msg_zalloc(DBG_GET_SYS_STAT_REQ, TASK_DBG, DRV_TASK_ID, 0); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Send the DBG_MEM_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, DBG_GET_SYS_STAT_CFM, cfm); ++} ++ ++int rwnx_send_dbg_mem_block_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, u32 *mem_data) ++{ ++ struct dbg_mem_block_write_req *mem_blk_write_req; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req = rwnx_msg_zalloc(DBG_MEM_BLOCK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_block_write_req)); ++ if (!mem_blk_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req->memaddr = mem_addr; ++ mem_blk_write_req->memsize = mem_size; ++ memcpy(mem_blk_write_req->memdata, mem_data, mem_size); ++ ++ /* Send the DBG_MEM_BLOCK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_blk_write_req, 1, DBG_MEM_BLOCK_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_block_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, struct dbg_mem_block_read_cfm *cfm) ++{ ++ struct dbg_mem_block_read_req *mem_blk_read_req; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_BLOCK_READ_REQ message */ ++ mem_blk_read_req = rwnx_msg_zalloc(DBG_MEM_BLOCK_READ_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_block_read_req)); ++ if (!mem_blk_read_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_BLOCK_READ_REQ message */ ++ mem_blk_read_req->memaddr = mem_addr; ++ mem_blk_read_req->memsize = mem_size; ++ ++ /* Send the DBG_MEM_BLOCK_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_blk_read_req, 1, DBG_MEM_BLOCK_READ_CFM, cfm); ++} ++ ++int rwnx_send_dbg_start_app_req(struct rwnx_hw *rwnx_hw, u32 boot_addr, ++ u32 boot_type) ++{ ++ struct dbg_start_app_req *start_app_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_START_APP_REQ message */ ++ start_app_req = rwnx_msg_zalloc(DBG_START_APP_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_start_app_req)); ++ if (!start_app_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_START_APP_REQ message */ ++ start_app_req->bootaddr = boot_addr; ++ start_app_req->boottype = boot_type; ++ ++ /* Send the DBG_START_APP_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, start_app_req, 1, DBG_START_APP_CFM, NULL); ++} ++ ++int rwnx_send_cfg_rssi_req(struct rwnx_hw *rwnx_hw, u8 vif_index, int rssi_thold, u32 rssi_hyst) ++{ ++ struct mm_cfg_rssi_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_CFG_RSSI_REQ message */ ++ req = rwnx_msg_zalloc(MM_CFG_RSSI_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_cfg_rssi_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if (rwnx_hw->vif_table[vif_index] == NULL) ++ return 0; ++ ++ /* Set parameters for the MM_CFG_RSSI_REQ message */ ++ req->vif_index = vif_index; ++ req->rssi_thold = (s8)rssi_thold; ++ req->rssi_hyst = (u8)rssi_hyst; ++ ++ /* Send the MM_CFG_RSSI_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_CFG_RSSI_CFM, NULL); ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h +new file mode 100644 +index 000000000000..d44c66c4645a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h +@@ -0,0 +1,196 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_msg_tx.h ++ * ++ * @brief TX function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_MSG_TX_H_ ++#define _RWNX_MSG_TX_H_ ++ ++#include "rwnx_defs.h" ++ ++int rwnx_send_reset(struct rwnx_hw *rwnx_hw); ++int rwnx_send_start(struct rwnx_hw *rwnx_hw); ++int rwnx_send_version_req(struct rwnx_hw *rwnx_hw, struct mm_version_cfm *cfm); ++int rwnx_send_add_if (struct rwnx_hw *rwnx_hw, const unsigned char *mac, ++ enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm); ++int rwnx_send_remove_if (struct rwnx_hw *rwnx_hw, u8 vif_index, bool defer); ++int rwnx_send_set_channel(struct rwnx_hw *rwnx_hw, int phy_idx, ++ struct mm_set_channel_cfm *cfm); ++int rwnx_send_key_add(struct rwnx_hw *rwnx_hw, u8 vif_idx, u8 sta_idx, bool pairwise, ++ u8 *key, u8 key_len, u8 key_idx, u8 cipher_suite, ++ struct mm_key_add_cfm *cfm); ++int rwnx_send_key_del(struct rwnx_hw *rwnx_hw, uint8_t hw_key_idx); ++int rwnx_send_bcn(struct rwnx_hw *rwnx_hw, u8 *buf, u8 vif_idx, u16 bcn_len); ++ ++int rwnx_send_bcn_change(struct rwnx_hw *rwnx_hw, u8 vif_idx, u32 bcn_addr, ++ u16 bcn_len, u16 tim_oft, u16 tim_len, u16 *csa_oft); ++int rwnx_send_tim_update(struct rwnx_hw *rwnx_hw, u8 vif_idx, u16 aid, ++ u8 tx_status); ++int rwnx_send_roc(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct ieee80211_channel *chan, unsigned int duration, struct mm_remain_on_channel_cfm *roc_cfm); ++int rwnx_send_cancel_roc(struct rwnx_hw *rwnx_hw); ++int rwnx_send_set_power(struct rwnx_hw *rwnx_hw, u8 vif_idx, s8 pwr, ++ struct mm_set_power_cfm *cfm); ++int rwnx_send_set_edca(struct rwnx_hw *rwnx_hw, u8 hw_queue, u32 param, ++ bool uapsd, u8 inst_nbr); ++int rwnx_send_tdls_chan_switch_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, bool sta_initiator, ++ u8 oper_class, struct cfg80211_chan_def *chandef, ++ struct tdls_chan_switch_cfm *cfm); ++int rwnx_send_tdls_cancel_chan_switch_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, ++ struct tdls_cancel_chan_switch_cfm *cfm); ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++int rwnx_send_p2p_oppps_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 ctw, struct mm_set_p2p_oppps_cfm *cfm); ++int rwnx_send_p2p_noa_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ int count, int interval, int duration, ++ bool dyn_noa, struct mm_set_p2p_noa_cfm *cfm); ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++#ifdef AICWF_ARP_OFFLOAD ++int rwnx_send_arpoffload_en_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u32_l ipaddr, u8_l enable); ++#endif ++int rwnx_send_rf_config_req(struct rwnx_hw *rwnx_hw, u8_l ofst, u8_l sel, u8_l *tbl, u16_l len); ++int rwnx_send_rf_calib_req(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); ++int rwnx_send_get_macaddr_req(struct rwnx_hw *rwnx_hw, struct mm_get_mac_addr_cfm *cfm); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_me_chan_config_req(struct rwnx_hw *rwnx_hw, char *ccode); ++int rwnx_send_me_set_control_port_req(struct rwnx_hw *rwnx_hw, bool opened, ++ u8 sta_idx); ++int rwnx_send_me_sta_add(struct rwnx_hw *rwnx_hw, struct station_parameters *params, ++ const u8 *mac, u8 inst_nbr, struct me_sta_add_cfm *cfm); ++int rwnx_send_me_sta_del(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool tdls_sta); ++int rwnx_send_me_traffic_ind(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool uapsd, u8 tx_status); ++int rwnx_send_me_rc_stats(struct rwnx_hw *rwnx_hw, u8 sta_idx, ++ struct me_rc_stats_cfm *cfm); ++int rwnx_send_me_rc_set_rate(struct rwnx_hw *rwnx_hw, ++ u8 sta_idx, ++ u16 rate_idx); ++int rwnx_send_me_set_ps_mode(struct rwnx_hw *rwnx_hw, u8 ps_mode); ++int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter); ++int rwnx_send_sm_connect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct cfg80211_connect_params *sme, ++ struct sm_connect_cfm *cfm); ++int rwnx_send_sm_disconnect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 reason); ++int rwnx_send_sm_external_auth_required_rsp(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 status); ++int rwnx_send_apm_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_ap_settings *settings, ++ struct apm_start_cfm *cfm, ++ struct rwnx_ipc_elem_var *elem); ++int rwnx_send_apm_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); ++int rwnx_send_scanu_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct cfg80211_scan_request *param); ++int rwnx_send_scanu_cancel_req(struct rwnx_hw *rwnx_hw, ++ struct scan_cancel_cfm *cfm); ++ ++int rwnx_send_apm_start_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_chan_def *chandef, ++ struct apm_start_cac_cfm *cfm); ++int rwnx_send_apm_stop_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); ++int rwnx_send_tdls_peer_traffic_ind_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif); ++int rwnx_send_config_monitor_req(struct rwnx_hw *rwnx_hw, ++ struct cfg80211_chan_def *chandef, ++ struct me_config_monitor_cfm *cfm); ++int rwnx_send_mesh_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ const struct mesh_config *conf, const struct mesh_setup *setup, ++ struct mesh_start_cfm *cfm); ++int rwnx_send_mesh_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct mesh_stop_cfm *cfm); ++int rwnx_send_mesh_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u32 mask, const struct mesh_config *p_mconf, struct mesh_update_cfm *cfm); ++int rwnx_send_mesh_peer_info_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, struct mesh_peer_info_cfm *cfm); ++void rwnx_send_mesh_peer_update_ntf(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, u8 mlink_state); ++void rwnx_send_mesh_path_create_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *tgt_addr); ++int rwnx_send_mesh_path_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, const u8 *tgt_addr, ++ const u8 *p_nhop_addr, struct mesh_path_update_cfm *cfm); ++void rwnx_send_mesh_proxy_add_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *ext_addr); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_BFMER ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_send_bfmer_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ const struct ieee80211_vht_cap *vht_cap); ++#endif /* CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++int rwnx_send_mu_group_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* CONFIG_RWNX_BFMER */ ++ ++/* Debug messages */ ++int rwnx_send_dbg_trigger_req(struct rwnx_hw *rwnx_hw, char *msg); ++int rwnx_send_dbg_mem_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm); ++int rwnx_send_dbg_mem_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_data); ++int rwnx_send_dbg_mem_mask_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_mask, u32 mem_data); ++int rwnx_send_dbg_set_mod_filter_req(struct rwnx_hw *rwnx_hw, u32 filter); ++#ifdef CONFIG_RFTEST ++int rwnx_send_rftest_req(struct rwnx_hw *rwnx_hw, u32_l cmd, u32_l argc, u8_l *argv, struct dbg_rftest_cmd_cfm *cfm); ++#endif ++#ifdef CONFIG_MCU_MESSAGE ++int rwnx_send_dbg_custom_msg_req(struct rwnx_hw *rwnx_hw, ++ u32 cmd, void *buf, u32 len, u32 action, ++ struct dbg_custom_msg_cfm *cfm); ++#endif ++int rwnx_send_dbg_set_sev_filter_req(struct rwnx_hw *rwnx_hw, u32 filter); ++int rwnx_send_dbg_get_sys_stat_req(struct rwnx_hw *rwnx_hw, ++ struct dbg_get_sys_stat_cfm *cfm); ++int rwnx_send_dbg_mem_block_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, u32 *mem_data); ++int rwnx_send_dbg_mem_block_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, struct dbg_mem_block_read_cfm *cfm); ++int rwnx_send_dbg_start_app_req(struct rwnx_hw *rwnx_hw, u32 boot_addr, ++ u32 boot_type); ++int rwnx_send_cfg_rssi_req(struct rwnx_hw *rwnx_hw, u8 vif_index, int rssi_thold, u32 rssi_hyst); ++int rwnx_send_disable_agg_req(struct rwnx_hw *rwnx_hw, u8_l agg_disable, u8_l agg_disable_rx, u8_l sta_idx); ++int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enable_nullcts); ++int rwnx_send_get_sta_info_req(struct rwnx_hw *rwnx_hw, u8_l sta_idx, struct mm_get_sta_info_cfm *cfm); ++int rwnx_send_set_stack_start_req(struct rwnx_hw *rwnx_hw, u8_l on, u8_l efuse_valid, u8_l set_vendor_info, ++ u8_l fwtrace_redir_en, struct mm_set_stack_start_cfm *cfm); ++int rwnx_send_txop_req(struct rwnx_hw *rwnx_hw, uint16_t *txop, u8_l long_nav_en, u8_l cfe_en); ++int rwnx_send_get_temp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm); ++int rwnx_send_set_temp_comp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm); ++int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, int32_t *param, int32_t *param_out); ++int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, int32_t *param_in, int32_t *param_out); ++int rwnx_send_mask_set_ext_flags_req(struct rwnx_hw *rwnx_hw, uint32_t flags_mask, uint32_t flags_val, struct mm_set_vendor_swconfig_cfm *cfm); ++int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_version_cfm *cfm); ++int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_ofst_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_ofst2x_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_ofst2x_v2_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_set_filter(struct rwnx_hw *rwnx_hw, uint32_t filter); ++int rwnx_send_txpwr_lvl_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_v4_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw); ++#ifdef CONFIG_APF ++int rwnx_send_set_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len); ++int rwnx_send_get_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len); ++#endif ++ ++#ifdef CONFIG_SDIO_BT ++int rwnx_sdio_bt_send_req(struct rwnx_hw *rwnx_hw,uint32_t len, struct sk_buff *skb); ++#endif ++ ++#endif /* _RWNX_MSG_TX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c +new file mode 100644 +index 000000000000..538f14306afb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c +@@ -0,0 +1,659 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_mu_group.c ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_events.h" ++ ++ ++/** ++ * rwnx_mu_group_sta_init - Initialize group information for a STA ++ * ++ * @sta: Sta to initialize ++ */ ++void rwnx_mu_group_sta_init(struct rwnx_sta *sta, ++ const struct ieee80211_vht_cap *vht_cap) ++{ ++ sta->group_info.map = 0; ++ sta->group_info.cnt = 0; ++ sta->group_info.active.next = LIST_POISON1; ++ sta->group_info.update.next = LIST_POISON1; ++ sta->group_info.last_update = 0; ++ sta->group_info.traffic = 0; ++ sta->group_info.group = 0; ++ ++ if (!vht_cap || ++ !(vht_cap->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { ++ sta->group_info.map = RWNX_SU_GROUP; ++ } ++} ++ ++/** ++ * rwnx_mu_group_sta_del - Remove a sta from all MU group ++ * ++ * @rwnx_hw: main driver data ++ * @sta: STA to remove ++ * ++ * Remove one sta from all the MU groups it belongs to. ++ */ ++void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ int i, j, group_id; ++ bool lock_taken; ++ u64 map; ++ ++ lock_taken = (down_interruptible(&mu->lock) == 0); ++ ++ group_sta_for_each(sta, group_id, map) { ++ struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id); ++ ++ for (i = 0; i < CONFIG_USER_MAX; i++) { ++ if (group->users[i] == sta) { ++ group->users[i] = NULL; ++ group->user_cnt--; ++ /* Don't keep group with only one user */ ++ if (group->user_cnt == 1) { ++ for (j = 0; j < CONFIG_USER_MAX; j++) { ++ if (group->users[j]) { ++ group->users[j]->group_info.cnt--; ++ group->users[j]->group_info.map &= ~BIT_ULL(group->group_id); ++ if (group->users[j]->group_info.group == group_id) ++ group->users[j]->group_info.group = 0; ++ group->user_cnt--; ++ break; ++ } ++ } ++ mu->group_cnt--; ++ trace_mu_group_delete(group->group_id); ++ } else { ++ trace_mu_group_update(group); ++ } ++ break; ++ } ++ } ++ ++ WARN((i == CONFIG_USER_MAX), "sta %d doesn't belongs to group %d", ++ sta->sta_idx, group_id); ++ } ++ ++ sta->group_info.map = 0; ++ sta->group_info.cnt = 0; ++ sta->group_info.traffic = 0; ++ ++ if (sta->group_info.active.next != LIST_POISON1) ++ list_del(&sta->group_info.active); ++ ++ if (sta->group_info.update.next != LIST_POISON1) ++ list_del(&sta->group_info.update); ++ ++ if (lock_taken) ++ up(&mu->lock); ++} ++ ++/** ++ * rwnx_mu_group_sta_get_map - Get the list of group a STA belongs to ++ * ++ * @sta: pointer to the sta ++ * ++ * @return the list of group a STA belongs to as a bitfield ++ */ ++u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta) ++{ ++ if (sta) ++ return sta->group_info.map; ++ return 0; ++} ++ ++/** ++ * rwnx_mu_group_sta_get_pos - Get sta position in a group ++ * ++ * @rwnx_hw: main driver data ++ * @sta: pointer to the sta ++ * @group_id: Group id ++ * ++ * @return the positon of @sta in group @group_id or -1 if the sta ++ * doesn't belongs to the group (or group id is invalid) ++ */ ++int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int group_id) ++{ ++ struct rwnx_mu_group *group; ++ int i; ++ ++ group = rwnx_mu_group_from_id(&rwnx_hw->mu, group_id); ++ if (!group) ++ return -1; ++ ++ for (i = 0; i < CONFIG_USER_MAX; i++) { ++ if (group->users[i] == sta) ++ return i; ++ } ++ ++ WARN(1, "sta %d doesn't belongs to group %d", ++ sta->sta_idx, group_id); ++ return -1; ++} ++ ++/** ++ * rwnx_mu_group_move_head - Move (or add) one element at the top of a list ++ * ++ * @list: list pointer ++ * @elem: element to move (or add) at the top of @list ++ * ++ */ ++static inline ++void rwnx_mu_group_move_head(struct list_head *list, struct list_head *elem) ++{ ++ if (elem->next != LIST_POISON1) { ++ __list_del_entry(elem); ++ } ++ list_add(elem, list); ++} ++ ++/** ++ * rwnx_mu_group_remove_users - Remove all the users of a group ++ * ++ * @mu: pointer on MU info ++ * @group: pointer on group to remove users from ++ * ++ * Loop over all users one one group and remove this group from their ++ * map (and count). ++ * Each users is also added to the update_sta list, so that group info ++ * will be resent to fw for this user. ++ */ ++static inline ++void rwnx_mu_group_remove_users(struct rwnx_mu_info *mu, ++ struct rwnx_mu_group *group) ++{ ++ struct rwnx_sta *sta; ++ int i, group_id = group->group_id; ++ ++ for (i = 0; i < CONFIG_USER_MAX; i++) { ++ if (group->users[i]) { ++ sta = group->users[i]; ++ group->users[i] = NULL; ++ sta->group_info.cnt--; ++ sta->group_info.map &= ~BIT_ULL(group_id); ++ rwnx_mu_group_move_head(&mu->update_sta, ++ &sta->group_info.update); ++ } ++ } ++ ++ if (group->user_cnt) ++ mu->group_cnt--; ++ group->user_cnt = 0; ++ trace_mu_group_delete(group_id); ++} ++ ++/** ++ * rwnx_mu_group_add_users - Add users to a group ++ * ++ * @mu: pointer on MU info ++ * @group: pointer on group to add users in ++ * @nb_user: number of users to ad ++ * @users: table of user to add ++ * ++ * Add @nb_users to @group (which may already have users) ++ * Each new users is added to the first free position. ++ * It is assume that @group has at least @nb_user free position. If it is not ++ * case it only add the number of users needed to complete the group. ++ * Each users (effectively added to @group) is also added to the update_sta ++ * list, so that group info will be resent to fw for this user. ++ */ ++static inline ++void rwnx_mu_group_add_users(struct rwnx_mu_info *mu, ++ struct rwnx_mu_group *group, ++ int nb_user, struct rwnx_sta **users) ++{ ++ int i, j, group_id = group->group_id; ++ ++ if (!group->user_cnt) ++ mu->group_cnt++; ++ ++ j = 0; ++ for (i = 0; i < nb_user ; i++) { ++ for (; j < CONFIG_USER_MAX ; j++) { ++ if (group->users[j] == NULL) { ++ group->users[j] = users[i]; ++ users[i]->group_info.cnt++; ++ users[i]->group_info.map |= BIT_ULL(group_id); ++ ++ rwnx_mu_group_move_head(&(mu->update_sta), ++ &(users[i]->group_info.update)); ++ group->user_cnt++; ++ j++; ++ break; ++ } ++ ++ WARN(j == (CONFIG_USER_MAX - 1), ++ "Too many user for group %d (nb_user=%d)", ++ group_id, group->user_cnt + nb_user - i); ++ } ++ } ++ ++ trace_mu_group_update(group); ++} ++ ++ ++/** ++ * rwnx_mu_group_create_one - create on group with a specific group of user ++ * ++ * @mu: pointer on MU info ++ * @nb_user: number of user to include in the group (<= CONFIG_USER_MAX) ++ * @users: table of users ++ * ++ * Try to create a new group with a specific group of users. ++ * 1- First it checks if a group containing all this users already exists. ++ * ++ * 2- Then it checks if it is possible to complete a group which already ++ * contains at least one user. ++ * ++ * 3- Finally it create a new group. To do so, it take take the last group of ++ * the active_groups list, remove all its current users and add the new ones ++ * ++ * In all cases, the group selected is moved at the top of the active_groups ++ * list ++ * ++ * @return 1 if a new group has been created and 0 otherwise ++ */ ++static ++int rwnx_mu_group_create_one(struct rwnx_mu_info *mu, int nb_user, ++ struct rwnx_sta **users, int *nb_group_left) ++{ ++ int i, group_id; ++ struct rwnx_mu_group *group; ++ u64 group_match; ++ u64 group_avail; ++ ++ group_match = users[0]->group_info.map; ++ group_avail = users[0]->group_info.map; ++ for (i = 1; i < nb_user ; i++) { ++ group_match &= users[i]->group_info.map; ++ group_avail |= users[i]->group_info.map; ++ ++ } ++ ++ if (group_match) { ++ /* a group (or more) with all the users already exist */ ++ group_id = RWNX_GET_FIRST_GROUP_ID(group_match); ++ group = rwnx_mu_group_from_id(mu, group_id); ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++ return 0; ++ } ++ ++#if CONFIG_USER_MAX > 2 ++ if (group_avail) { ++ /* check if we can complete a group */ ++ struct rwnx_sta *users2[CONFIG_USER_MAX]; ++ int nb_user2; ++ ++ group_for_each(group_id, group_avail) { ++ group = rwnx_mu_group_from_id(mu, group_id); ++ if (group->user_cnt == CONFIG_USER_MAX) ++ continue; ++ ++ nb_user2 = 0; ++ for (i = 0; i < nb_user ; i++) { ++ if (!(users[i]->group_info.map & BIT_ULL(group_id))) { ++ users2[nb_user2] = users[i]; ++ nb_user2++; ++ } ++ } ++ ++ if ((group->user_cnt + nb_user2) <= CONFIG_USER_MAX) { ++ rwnx_mu_group_add_users(mu, group, nb_user2, users2); ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++ return 0; ++ } ++ } ++ } ++#endif /* CONFIG_USER_MAX > 2*/ ++ ++ /* create a new group */ ++ group = list_last_entry(&mu->active_groups, struct rwnx_mu_group, list); ++ rwnx_mu_group_remove_users(mu, group); ++ rwnx_mu_group_add_users(mu, group, nb_user, users); ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++ (*nb_group_left)--; ++ ++ return 1; ++} ++ ++/** ++ * rwnx_mu_group_create - Create new groups containing one specific sta ++ * ++ * @mu: pointer on MU info ++ * @sta: sta to add in each group ++ * @nb_group_left: maximum number to new group allowed. (updated on exit) ++ * ++ * This will try to create "all the possible" group with a specific sta being ++ * a member of all these group. ++ * The function simply loops over the @active_sta list (starting from @sta). ++ * When it has (CONFIG_USER_MAX - 1) users it try to create a new group with ++ * these users (plus @sta). ++ * Loops end when there is no more users, or no more new group is allowed ++ * ++ */ ++static ++void rwnx_mu_group_create(struct rwnx_mu_info *mu, struct rwnx_sta *sta, ++ int *nb_group_left) ++{ ++ struct rwnx_sta *user_sta = sta; ++ struct rwnx_sta *users[CONFIG_USER_MAX]; ++ int nb_user = 1; ++ ++ users[0] = sta; ++ while (*nb_group_left) { ++ ++ list_for_each_entry_continue(user_sta, &mu->active_sta, group_info.active) { ++ users[nb_user] = user_sta; ++ if (++nb_user == CONFIG_USER_MAX) { ++ break; ++ } ++ } ++ ++ if (nb_user > 1) { ++ if (rwnx_mu_group_create_one(mu, nb_user, users, nb_group_left)) ++ (*nb_group_left)--; ++ ++ if (nb_user < CONFIG_USER_MAX) ++ break; ++ else ++ nb_user = 1; ++ } else ++ break; ++ } ++} ++ ++/** ++ * rwnx_mu_group_work - process function of the "group_work" ++ * ++ * The work is scheduled when several sta (MU beamformee capable) are active. ++ * When called, the @active_sta contains the list of the active sta (starting ++ * from the most recent one), and @active_groups is the list of all possible ++ * groups ordered so that the first one is the most recently used. ++ * ++ * This function will create new groups, starting from group containing the ++ * most "active" sta. ++ * For example if the list of sta is : ++ * sta8 -> sta3 -> sta4 -> sta7 -> sta1 ++ * and the number of user per group is 3, it will create grooups : ++ * - sta8 / sta3 / sta4 ++ * - sta8 / sta7 / sta1 ++ * - sta3 / sta4 / sta7 ++ * - sta3 / sta1 ++ * - sta4 / sta7 / sta1 ++ * - sta7 / sta1 ++ * ++ * To create new group, the least used group are first selected. ++ * It is only allowed to create NX_MU_GROUP_MAX per iteration. ++ * ++ * Once groups have been updated, mu group information is update to the fw. ++ * To do so it use the @update_sta list to know which sta has been affected. ++ * As it is necessary to wait for fw confirmation before using this new group ++ * MU is temporarily disabled during group update ++ * ++ * Work is then rescheduled. ++ * ++ * At the end of the function, both @active_sta and @update_sta list are empty. ++ * ++ * Note: ++ * - This is still a WIP, and will require more tuning ++ * - not all combinations are created, to avoid to much processing. ++ * - reschedule delay should be adaptative ++ */ ++void rwnx_mu_group_work(struct work_struct *ws) ++{ ++ struct delayed_work *dw = container_of(ws, struct delayed_work, work); ++ struct rwnx_mu_info *mu = container_of(dw, struct rwnx_mu_info, group_work); ++ struct rwnx_hw *rwnx_hw = container_of(mu, struct rwnx_hw, mu); ++ struct rwnx_sta *sta, *next; ++ int nb_group_left = NX_MU_GROUP_MAX; ++ ++ if (WARN(!rwnx_hw->mod_params->mutx, ++ "In group formation work, but mutx disabled")) ++ return; ++ ++ if (down_interruptible(&mu->lock) != 0) ++ return; ++ ++ mu->update_count++; ++ if (!mu->update_count) ++ mu->update_count++; ++ ++ list_for_each_entry_safe(sta, next, &mu->active_sta, group_info.active) { ++ if (nb_group_left) ++ rwnx_mu_group_create(mu, sta, &nb_group_left); ++ ++ sta->group_info.last_update = mu->update_count; ++ list_del(&sta->group_info.active); ++ } ++ ++ if (!list_empty(&mu->update_sta)) { ++ list_for_each_entry_safe(sta, next, &mu->update_sta, group_info.update) { ++ rwnx_send_mu_group_update_req(rwnx_hw, sta); ++ list_del(&sta->group_info.update); ++ } ++ } ++ ++ mu->next_group_select = jiffies; ++ rwnx_mu_group_sta_select(rwnx_hw); ++ up(&mu->lock); ++ ++ return; ++} ++ ++/** ++ * rwnx_mu_group_init - Initialize MU groups ++ * ++ * @rwnx_hw: main driver data ++ * ++ * Initialize all MU group ++ */ ++void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ int i; ++ ++ INIT_LIST_HEAD(&mu->active_groups); ++ INIT_LIST_HEAD(&mu->active_sta); ++ INIT_LIST_HEAD(&mu->update_sta); ++ ++ for (i = 0; i < NX_MU_GROUP_MAX; i++) { ++ int j; ++ mu->groups[i].user_cnt = 0; ++ mu->groups[i].group_id = i + 1; ++ for (j = 0; j < CONFIG_USER_MAX; j++) { ++ mu->groups[i].users[j] = NULL; ++ } ++ list_add(&mu->groups[i].list, &mu->active_groups); ++ } ++ ++ mu->update_count = 1; ++ mu->group_cnt = 0; ++ mu->next_group_select = jiffies; ++ INIT_DELAYED_WORK(&mu->group_work, rwnx_mu_group_work); ++ sema_init(&mu->lock, 1); ++} ++ ++/** ++ * rwnx_mu_set_active_sta - mark a STA as active ++ * ++ * @rwnx_hw: main driver data ++ * @sta: pointer to the sta ++ * @traffic: Number of buffers to add in the sta's traffic counter ++ * ++ * If @sta is MU beamformee capable (and MU-MIMO tx is enabled) move the ++ * sta at the top of the @active_sta list. ++ * It also schedule the group_work if not already scheduled and the list ++ * contains more than one sta. ++ * ++ * If a STA was already in the list during the last group update ++ * (i.e. sta->group_info.last_update == mu->update_count) it is not added ++ * back to the list until a sta that wasn't active during the last update is ++ * added. This is to avoid scheduling group update with a list of sta that ++ * were all already in the list during previous update. ++ * ++ * It is called with mu->lock taken. ++ */ ++void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int traffic) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ ++ if (!sta || (sta->group_info.map & RWNX_SU_GROUP)) ++ return; ++ ++ sta->group_info.traffic += traffic; ++ ++ if ((sta->group_info.last_update != mu->update_count) || ++ !list_empty(&mu->active_sta)) { ++ ++ rwnx_mu_group_move_head(&mu->active_sta, &sta->group_info.active); ++ ++ if (!delayed_work_pending(&mu->group_work) && ++ !list_is_singular(&mu->active_sta)) { ++ schedule_delayed_work(&mu->group_work, ++ msecs_to_jiffies(RWNX_MU_GROUP_INTERVAL)); ++ } ++ } ++} ++ ++/** ++ * rwnx_mu_set_active_group - mark a MU group as active ++ * ++ * @rwnx_hw: main driver data ++ * @group_id: Group id ++ * ++ * move a group at the top of the @active_groups list ++ */ ++void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id); ++ ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++} ++ ++ ++/** ++ * rwnx_mu_group_sta_select - Select the best group for MU stas ++ * ++ * @rwnx_hw: main driver data ++ * ++ * For each MU capable client of AP interfaces this function tries to select ++ * the best group to use. ++ * ++ * In first pass, gather information from all stations to form statistics ++ * for each group for the previous @RWNX_MU_GROUP_SELECT_INTERVAL interval: ++ * - number of buffers transmitted ++ * - number of user ++ * ++ * Then groups with more than 2 active users, are assigned after being ordered ++ * by traffic : ++ * - group with highest traffic is selected: set this group for all its users ++ * - update nb_users for all others group (as one sta may be in several groups) ++ * - select the next group that have still mor than 2 users and assign it. ++ * - continue until all group are processed ++ * ++ */ ++void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ int nb_users[NX_MU_GROUP_MAX + 1]; ++ int traffic[NX_MU_GROUP_MAX + 1]; ++ int order[NX_MU_GROUP_MAX + 1]; ++ struct rwnx_sta *sta; ++ struct rwnx_vif *vif; ++ struct list_head *head; ++ u64 map; ++ int i, j, update, group_id, tmp, cnt = 0; ++ ++ if (!mu->group_cnt || time_before(jiffies, mu->next_group_select)) ++ return; ++ ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ ++ if (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP) ++ continue; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ head = &vif->ap.sta_list; ++#else ++ head = &vif->stations; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ memset(nb_users, 0, sizeof(nb_users)); ++ memset(traffic, 0, sizeof(traffic)); ++ list_for_each_entry(sta, head, list) { ++ int sta_traffic = sta->group_info.traffic; ++ ++ /* reset statistics for next selection */ ++ sta->group_info.traffic = 0; ++ if (sta->group_info.group) ++ trace_mu_group_selection(sta, 0); ++ sta->group_info.group = 0; ++ ++ if (sta->group_info.cnt == 0 || ++ sta_traffic < RWNX_MU_GROUP_MIN_TRAFFIC) ++ continue; ++ ++ group_sta_for_each(sta, group_id, map) { ++ nb_users[group_id]++; ++ traffic[group_id] += sta_traffic; ++ ++ /* list group with 2 users or more */ ++ if (nb_users[group_id] == 2) ++ order[cnt++] = group_id; ++ } ++ } ++ ++ /* reorder list of group with more that 2 users */ ++ update = 1; ++ while (update) { ++ update = 0; ++ for (i = 0; i < cnt - 1; i++) { ++ if (traffic[order[i]] < traffic[order[i + 1]]) { ++ tmp = order[i]; ++ order[i] = order[i + 1]; ++ order[i + 1] = tmp; ++ update = 1; ++ } ++ } ++ } ++ ++ /* now assign group in traffic order */ ++ for (i = 0; i < cnt; i++) { ++ struct rwnx_mu_group *group; ++ group_id = order[i]; ++ ++ if (nb_users[group_id] < 2) ++ continue; ++ ++ group = rwnx_mu_group_from_id(mu, group_id); ++ for (j = 0; j < CONFIG_USER_MAX; j++) { ++ if (group->users[j]) { ++ trace_mu_group_selection(group->users[j], group_id); ++ group->users[j]->group_info.group = group_id; ++ ++ group_sta_for_each(group->users[j], tmp, map) { ++ if (group_id != tmp) ++ nb_users[tmp]--; ++ } ++ } ++ } ++ } ++ } ++ ++ mu->next_group_select = jiffies + ++ msecs_to_jiffies(RWNX_MU_GROUP_SELECT_INTERVAL); ++ mu->next_group_select |= 1; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h +new file mode 100644 +index 000000000000..c24bb0396e9f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h +@@ -0,0 +1,181 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_mu_group.h ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_MU_GROUP_H_ ++#define _RWNX_MU_GROUP_H_ ++ ++#include ++#include ++ ++struct rwnx_hw; ++struct rwnx_sta; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ ++/** ++ * struct rwnx_sta_group_info - Group Information for a STA ++ * ++ * @active: node for @mu->active_sta list ++ * @update: node for @mu->update_sta list ++ * @cnt: Number of groups the STA belongs to ++ * @map: Bitfield of groups the sta belongs to ++ * @traffic: Number of buffers sent since previous group selection ++ * @group: Id of the group selected by previous group selection ++ * (cf @rwnx_mu_group_sta_select) ++ */ ++struct rwnx_sta_group_info { ++ struct list_head active; ++ struct list_head update; ++ u16 last_update; ++ int cnt; ++ u64 map; ++ int traffic; ++ u8 group; ++}; ++ ++/** ++ * struct mu_group_info - Information about the users of a group ++ * ++ * @list: node for mu->active_groups ++ * @group_id: Group identifier ++ * @user_cnt: Number of the users in the group ++ * @users: Pointer to the sta, ordered by user position ++ */ ++struct rwnx_mu_group { ++ struct list_head list; ++ int group_id; ++ int user_cnt; ++ struct rwnx_sta *users[CONFIG_USER_MAX]; ++}; ++ ++/** ++ * struct rwnx_mu_info - Information about all MU group ++ * ++ * @active_groups: List of all possible groups. Ordered from the most recently ++ * used one to the least one (and possibly never used) ++ * @active_sta: List of MU beamformee sta that have been active (since previous ++ * group update). Ordered from the most recently active. ++ * @update_sta: List of sta whose group information has changed and need to be ++ * updated at fw level ++ * @groups: Table of all groups ++ * @group_work: Work item used to schedule group update ++ * @update_count: Counter used to identify the last group formation update. ++ * (cf rwnx_sta_group_info.last_update) ++ * @lock: Lock taken during group update. If tx happens lock is taken, then tx ++ * will not used MU. ++ * @next_group_assign: Next time the group selection should be run ++ * (ref @rwnx_mu_group_sta_select) ++ * @group_cnt: Number of group created ++ */ ++struct rwnx_mu_info { ++ struct list_head active_groups; ++ struct list_head active_sta; ++ struct list_head update_sta; ++ struct rwnx_mu_group groups[NX_MU_GROUP_MAX]; ++ struct delayed_work group_work; ++ u16 update_count; ++ struct semaphore lock; ++ unsigned long next_group_select; ++ u8 group_cnt; ++}; ++ ++#define RWNX_SU_GROUP BIT_ULL(0) ++#define RWNX_MU_GROUP_MASK 0x7ffffffffffffffeULL ++#define RWNX_MU_GROUP_INTERVAL 200 /* in ms */ ++#define RWNX_MU_GROUP_SELECT_INTERVAL 100 /* in ms */ ++// minimum traffic in a RWNX_MU_GROUP_SELECT_INTERVAL to consider the sta ++#define RWNX_MU_GROUP_MIN_TRAFFIC 50 /* in number of packet */ ++ ++ ++#define RWNX_GET_FIRST_GROUP_ID(map) (fls64(map) - 1) ++ ++#define group_sta_for_each(sta, id, map) \ ++ do { \ ++ map = sta->group_info.map & RWNX_MU_GROUP_MASK; \ ++ for (id = (fls64(map) - 1) ; id > 0 ; \ ++ map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1)) \ ++ } while (0) ++ ++#define group_for_each(id, map) \ ++ for (id = (fls64(map) - 1) ; id > 0 ; \ ++ map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1)) ++ ++#define RWNX_MUMIMO_INFO_POS_ID(info) (((info) >> 6) & 0x3) ++#define RWNX_MUMIMO_INFO_GROUP_ID(info) ((info) & 0x3f) ++ ++static inline ++struct rwnx_mu_group *rwnx_mu_group_from_id(struct rwnx_mu_info *mu, int id) ++{ ++ if (id > NX_MU_GROUP_MAX) ++ return NULL; ++ ++ return &mu->groups[id - 1]; ++} ++ ++ ++void rwnx_mu_group_sta_init(struct rwnx_sta *sta, ++ const struct ieee80211_vht_cap *vht_cap); ++void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); ++u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta); ++int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int group_id); ++ ++void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw); ++ ++void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int traffic); ++void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id); ++void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw); ++ ++ ++#else /* ! CONFIG_RWNX_MUMIMO_TX */ ++ ++static inline ++void rwnx_mu_group_sta_init(struct rwnx_sta *sta, ++ const struct ieee80211_vht_cap *vht_cap) ++{} ++ ++static inline ++void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{} ++ ++static inline ++u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta) ++{ ++ return 0; ++} ++ ++static inline ++int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int group_id) ++{ ++ return 0; ++} ++ ++static inline ++void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw) ++{} ++ ++static inline ++void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int traffic) ++{} ++ ++static inline ++void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id) ++{} ++ ++static inline ++void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw) ++{} ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++#endif /* _RWNX_MU_GROUP_H_ */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c +new file mode 100644 +index 000000000000..40dac946536d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c +@@ -0,0 +1,94 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_pci.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_dini.h" ++#include "rwnx_v7.h" ++ ++#define PCI_VENDOR_ID_DINIGROUP 0x17DF ++#define PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE 0x1907 ++ ++#define PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7 0x7011 ++ ++static const struct pci_device_id rwnx_pci_ids[] = { ++ {PCI_DEVICE(PCI_VENDOR_ID_DINIGROUP, PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7)}, ++ {0,} ++}; ++ ++ ++/* Uncomment this for depmod to create module alias */ ++/* We don't want this on development platform */ ++//MODULE_DEVICE_TABLE(pci, rwnx_pci_ids); ++ ++static int rwnx_pci_probe(struct pci_dev *pci_dev, ++ const struct pci_device_id *pci_id) ++{ ++ struct rwnx_plat *rwnx_plat = NULL; ++ void *drvdata; ++ int ret = -ENODEV; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (pci_id->vendor == PCI_VENDOR_ID_DINIGROUP) { ++ ret = rwnx_dini_platform_init(pci_dev, &rwnx_plat); ++ } else if (pci_id->vendor == PCI_VENDOR_ID_XILINX) { ++ ret = rwnx_v7_platform_init(pci_dev, &rwnx_plat); ++ } ++ ++ if (ret) ++ return ret; ++ ++ rwnx_plat->pci_dev = pci_dev; ++ ++ ret = rwnx_platform_init(rwnx_plat, &drvdata); ++ pci_set_drvdata(pci_dev, drvdata); ++ ++ if (ret) ++ rwnx_plat->deinit(rwnx_plat); ++ ++ return ret; ++} ++ ++static void rwnx_pci_remove(struct pci_dev *pci_dev) ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct rwnx_plat *rwnx_plat; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_hw = pci_get_drvdata(pci_dev); ++ rwnx_plat = rwnx_hw->plat; ++ ++ rwnx_platform_deinit(rwnx_hw); ++ rwnx_plat->deinit(rwnx_plat); ++ ++ pci_set_drvdata(pci_dev, NULL); ++} ++ ++static struct pci_driver rwnx_pci_drv = { ++ .name = KBUILD_MODNAME, ++ .id_table = rwnx_pci_ids, ++ .probe = rwnx_pci_probe, ++ .remove = rwnx_pci_remove ++}; ++ ++int rwnx_pci_register_drv(void) ++{ ++ return pci_register_driver(&rwnx_pci_drv); ++} ++ ++void rwnx_pci_unregister_drv(void) ++{ ++ pci_unregister_driver(&rwnx_pci_drv); ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h +new file mode 100644 +index 000000000000..d81578cbef48 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h +@@ -0,0 +1,17 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_pci.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_PCI_H_ ++#define _RWNX_PCI_H_ ++ ++int rwnx_pci_register_drv(void); ++void rwnx_pci_unregister_drv(void); ++ ++#endif /* _RWNX_PCI_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c +new file mode 100644 +index 000000000000..33bc63bd4057 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c +@@ -0,0 +1,3417 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_platform.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "rwnx_platform.h" ++#include "reg_access.h" ++#include "hal_desc.h" ++#include "rwnx_main.h" ++#include "rwnx_pci.h" ++#ifndef CONFIG_RWNX_FHOST ++#include "ipc_host.h" ++#endif /* !CONFIG_RWNX_FHOST */ ++#include "rwnx_msg_tx.h" ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++#include "aicwf_usb.h" ++#endif ++#include "md5.h" ++#include "aicwf_compat_8800dc.h" ++#include "aicwf_compat_8800d80.h" ++ ++#ifdef CONFIG_USE_FW_REQUEST ++#include ++#endif ++ ++#define FW_PATH_MAX_LEN 200 ++extern char aic_fw_path[FW_PATH_MAX_LEN]; ++ ++//Parser state ++#define INIT 0 ++#define CMD 1 ++#define PRINT 2 ++#define GET_VALUE 3 ++ ++ ++struct rwnx_plat *g_rwnx_plat; ++ ++typedef struct ++{ ++ txpwr_lvl_conf_t txpwr_lvl; ++ txpwr_lvl_conf_v2_t txpwr_lvl_v2; ++ txpwr_lvl_conf_v3_t txpwr_lvl_v3; ++ txpwr_lvl_conf_v4_t txpwr_lvl_v4; ++ txpwr_lvl_adj_conf_t txpwr_lvl_adj; ++ txpwr_loss_conf_t txpwr_loss; ++ txpwr_ofst_conf_t txpwr_ofst; ++ txpwr_ofst2x_conf_t txpwr_ofst2x; ++ txpwr_ofst2x_conf_v2_t txpwr_ofst2x_v2; ++ xtal_cap_conf_t xtal_cap; ++} userconfig_info_t; ++ ++userconfig_info_t userconfig_info = { ++ .txpwr_lvl = { ++ .enable = 1, ++ .dsss = 9, ++ .ofdmlowrate_2g4 = 8, ++ .ofdm64qam_2g4 = 8, ++ .ofdm256qam_2g4 = 8, ++ .ofdm1024qam_2g4 = 8, ++ .ofdmlowrate_5g = 11, ++ .ofdm64qam_5g = 10, ++ .ofdm256qam_5g = 9, ++ .ofdm1024qam_5g = 9 ++ }, ++ .txpwr_lvl_v2 = { ++ .enable = 1, ++ .pwrlvl_11b_11ag_2g4 = ++ //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, ++ .pwrlvl_11ax_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, ++ }, ++ .txpwr_lvl_v3 = { ++ .enable = 1, ++ .pwrlvl_11b_11ag_2g4 = ++ //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, ++ .pwrlvl_11ax_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, ++ .pwrlvl_11a_5g = ++ //NA, NA, NA, NA, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 0x80, 0x80, 0x80, 0x80, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15}, ++ .pwrlvl_11ax_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15, 14, 14}, ++ }, ++ .txpwr_lvl_v4 = { ++ .enable = 1, ++ .pwrlvl_11b_11ag_2g4 = ++ //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, ++ .pwrlvl_11ax_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, ++ .pwrlvl_11a_5g = ++ //6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15}, ++ .pwrlvl_11ax_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15, 14, 14}, ++ }, ++ .txpwr_loss = { ++ .loss_enable_2g4 = 0, ++ .loss_value_2g4 = 0, ++ .loss_enable_5g = 0, ++ .loss_value_5g = 0, ++ }, ++ .txpwr_ofst = { ++ .enable = 1, ++ .chan_1_4 = 0, ++ .chan_5_9 = 0, ++ .chan_10_13 = 0, ++ .chan_36_64 = 0, ++ .chan_100_120 = 0, ++ .chan_122_140 = 0, ++ .chan_142_165 = 0, ++ }, ++ .txpwr_ofst2x = { ++ .enable = 0, ++ .pwrofst2x_tbl_2g4 = ++ { // ch1-4, ch5-9, ch10-13 ++ { 0, 0, 0 }, // 11b ++ { 0, 0, 0 }, // ofdm_highrate ++ { 0, 0, 0 }, // ofdm_lowrate ++ }, ++ .pwrofst2x_tbl_5g = ++ { // ch42, ch58, ch106,ch122,ch138,ch155 ++ { 0, 0, 0, 0, 0, 0 }, // ofdm_lowrate ++ { 0, 0, 0, 0, 0, 0 }, // ofdm_highrate ++ { 0, 0, 0, 0, 0, 0 }, // ofdm_midrate ++ }, ++ }, ++ .txpwr_ofst2x_v2 = { ++ .enable = 0, ++ .pwrofst_flags = 0, ++ .pwrofst2x_tbl_2g4_ant0 = ++ { // 11b, ofdm_highrate, ofdm_lowrate ++ { 0, 0, 0 }, // ch1-4 ++ { 0, 0, 0 }, // ch5-9 ++ { 0, 0, 0 }, // ch10-13 ++ }, ++ .pwrofst2x_tbl_2g4_ant1 = ++ { // 11b, ofdm_highrate, ofdm_lowrate ++ { 0, 0, 0 }, // ch1-4 ++ { 0, 0, 0 }, // ch5-9 ++ { 0, 0, 0 }, // ch10-13 ++ }, ++ .pwrofst2x_tbl_5g_ant0 = ++ { // ofdm_highrate, ofdm_lowrate, ofdm_midrate ++ { 0, 0, 0 }, // ch42 ++ { 0, 0, 0 }, // ch58 ++ { 0, 0, 0 }, // ch106 ++ { 0, 0, 0 }, // ch122 ++ { 0, 0, 0 }, // ch138 ++ { 0, 0, 0 }, // ch155 ++ }, ++ .pwrofst2x_tbl_5g_ant1 = ++ { // ofdm_highrate, ofdm_lowrate, ofdm_midrate ++ { 0, 0, 0 }, // ch42 ++ { 0, 0, 0 }, // ch58 ++ { 0, 0, 0 }, // ch106 ++ { 0, 0, 0 }, // ch122 ++ { 0, 0, 0 }, // ch138 ++ { 0, 0, 0 }, // ch155 ++ }, ++ .pwrofst2x_tbl_6g_ant0 = { 0, }, // ofdm_highrate: 6e_ch7 ~ 6e_ch229 ++ .pwrofst2x_tbl_6g_ant1 = { 0, }, // ofdm_highrate: 6e_ch7 ~ 6e_ch229 ++ }, ++ .xtal_cap = { ++ .enable = 0, ++ .xtal_cap = 24, ++ .xtal_cap_fine = 31, ++ }, ++}; ++ ++typedef struct { ++ char ccode[3]; ++ Regions_code region; ++} reg_table; ++ ++/* If the region conflicts with the kernel, the actual authentication standard prevails */ ++reg_table reg_tables[] = { ++ {.ccode = "CN", .region = REGIONS_SRRC}, ++ {.ccode = "US", .region = REGIONS_FCC}, ++ {.ccode = "DE", .region = REGIONS_ETSI}, ++ {.ccode = "00", .region = REGIONS_DEFAULT}, ++ {.ccode = "WW", .region = REGIONS_DEFAULT}, ++ {.ccode = "XX", .region = REGIONS_DEFAULT}, ++ {.ccode = "JP", .region = REGIONS_JP}, ++ {.ccode = "AD", .region = REGIONS_ETSI}, ++ {.ccode = "AE", .region = REGIONS_ETSI}, ++ {.ccode = "AF", .region = REGIONS_ETSI}, ++ {.ccode = "AI", .region = REGIONS_ETSI}, ++ {.ccode = "AL", .region = REGIONS_ETSI}, ++ {.ccode = "AM", .region = REGIONS_ETSI}, ++ {.ccode = "AN", .region = REGIONS_ETSI}, ++ {.ccode = "AR", .region = REGIONS_FCC}, ++ {.ccode = "AS", .region = REGIONS_FCC}, ++ {.ccode = "AT", .region = REGIONS_ETSI}, ++ {.ccode = "AU", .region = REGIONS_ETSI}, ++ {.ccode = "AW", .region = REGIONS_ETSI}, ++ {.ccode = "AZ", .region = REGIONS_ETSI}, ++ {.ccode = "BA", .region = REGIONS_ETSI}, ++ {.ccode = "BB", .region = REGIONS_FCC}, ++ {.ccode = "BD", .region = REGIONS_JP}, ++ {.ccode = "BE", .region = REGIONS_ETSI}, ++ {.ccode = "BF", .region = REGIONS_FCC}, ++ {.ccode = "BG", .region = REGIONS_ETSI}, ++ {.ccode = "BH", .region = REGIONS_ETSI}, ++ {.ccode = "BL", .region = REGIONS_ETSI}, ++ {.ccode = "BM", .region = REGIONS_FCC}, ++ {.ccode = "BN", .region = REGIONS_JP}, ++ {.ccode = "BO", .region = REGIONS_JP}, ++ {.ccode = "BR", .region = REGIONS_FCC}, ++ {.ccode = "BS", .region = REGIONS_FCC}, ++ {.ccode = "BT", .region = REGIONS_ETSI}, ++ {.ccode = "BW", .region = REGIONS_ETSI}, ++ {.ccode = "BY", .region = REGIONS_ETSI}, ++ {.ccode = "BZ", .region = REGIONS_JP}, ++ {.ccode = "CA", .region = REGIONS_FCC}, ++ {.ccode = "CF", .region = REGIONS_FCC}, ++ {.ccode = "CH", .region = REGIONS_ETSI}, ++ {.ccode = "CI", .region = REGIONS_FCC}, ++ {.ccode = "CL", .region = REGIONS_ETSI}, ++ {.ccode = "CO", .region = REGIONS_FCC}, ++ {.ccode = "CR", .region = REGIONS_FCC}, ++ {.ccode = "CX", .region = REGIONS_FCC}, ++ {.ccode = "CY", .region = REGIONS_ETSI}, ++ {.ccode = "CZ", .region = REGIONS_ETSI}, ++ {.ccode = "DK", .region = REGIONS_ETSI}, ++ {.ccode = "DM", .region = REGIONS_FCC}, ++ {.ccode = "DO", .region = REGIONS_FCC}, ++ {.ccode = "DZ", .region = REGIONS_JP}, ++ {.ccode = "EC", .region = REGIONS_FCC}, ++ {.ccode = "EE", .region = REGIONS_ETSI}, ++ {.ccode = "EG", .region = REGIONS_ETSI}, ++ {.ccode = "ES", .region = REGIONS_ETSI}, ++ {.ccode = "ET", .region = REGIONS_ETSI}, ++ {.ccode = "FI", .region = REGIONS_ETSI}, ++ {.ccode = "FM", .region = REGIONS_FCC}, ++ {.ccode = "FR", .region = REGIONS_ETSI}, ++ {.ccode = "GB", .region = REGIONS_ETSI}, ++ {.ccode = "GD", .region = REGIONS_FCC}, ++ {.ccode = "GE", .region = REGIONS_ETSI}, ++ {.ccode = "GF", .region = REGIONS_ETSI}, ++ {.ccode = "GH", .region = REGIONS_FCC}, ++ {.ccode = "GI", .region = REGIONS_ETSI}, ++ {.ccode = "GL", .region = REGIONS_ETSI}, ++ {.ccode = "GP", .region = REGIONS_ETSI}, ++ {.ccode = "GR", .region = REGIONS_ETSI}, ++ {.ccode = "GT", .region = REGIONS_FCC}, ++ {.ccode = "GU", .region = REGIONS_FCC}, ++ {.ccode = "GY", .region = REGIONS_DEFAULT}, ++ {.ccode = "HK", .region = REGIONS_ETSI}, ++ {.ccode = "HN", .region = REGIONS_FCC}, ++ {.ccode = "HR", .region = REGIONS_ETSI}, ++ {.ccode = "HT", .region = REGIONS_FCC}, ++ {.ccode = "HU", .region = REGIONS_ETSI}, ++ {.ccode = "ID", .region = REGIONS_ETSI}, ++ {.ccode = "IE", .region = REGIONS_ETSI}, ++ {.ccode = "IL", .region = REGIONS_ETSI}, ++ {.ccode = "IN", .region = REGIONS_ETSI}, ++ {.ccode = "IQ", .region = REGIONS_ETSI}, ++ {.ccode = "IR", .region = REGIONS_JP}, ++ {.ccode = "IS", .region = REGIONS_ETSI}, ++ {.ccode = "IT", .region = REGIONS_ETSI}, ++ {.ccode = "JM", .region = REGIONS_FCC}, ++ {.ccode = "JO", .region = REGIONS_ETSI}, ++ {.ccode = "KE", .region = REGIONS_ETSI}, ++ {.ccode = "KG", .region = REGIONS_ETSI}, ++ {.ccode = "KH", .region = REGIONS_ETSI}, ++ {.ccode = "KN", .region = REGIONS_ETSI}, ++ {.ccode = "KP", .region = REGIONS_JP}, ++ {.ccode = "KR", .region = REGIONS_ETSI}, ++ {.ccode = "KW", .region = REGIONS_ETSI}, ++ {.ccode = "KY", .region = REGIONS_FCC}, ++ {.ccode = "KZ", .region = REGIONS_DEFAULT}, ++ {.ccode = "LB", .region = REGIONS_ETSI}, ++ {.ccode = "LC", .region = REGIONS_ETSI}, ++ {.ccode = "LI", .region = REGIONS_ETSI}, ++ {.ccode = "LK", .region = REGIONS_FCC}, ++ {.ccode = "LS", .region = REGIONS_ETSI}, ++ {.ccode = "LT", .region = REGIONS_ETSI}, ++ {.ccode = "LU", .region = REGIONS_ETSI}, ++ {.ccode = "LV", .region = REGIONS_ETSI}, ++ {.ccode = "LY", .region = REGIONS_ETSI}, ++ {.ccode = "MA", .region = REGIONS_ETSI}, ++ {.ccode = "MC", .region = REGIONS_ETSI}, ++ {.ccode = "MD", .region = REGIONS_ETSI}, ++ {.ccode = "ME", .region = REGIONS_ETSI}, ++ {.ccode = "MF", .region = REGIONS_ETSI}, ++ {.ccode = "MH", .region = REGIONS_FCC}, ++ {.ccode = "MK", .region = REGIONS_ETSI}, ++ {.ccode = "MN", .region = REGIONS_ETSI}, ++ {.ccode = "MO", .region = REGIONS_ETSI}, ++ {.ccode = "MP", .region = REGIONS_FCC}, ++ {.ccode = "MQ", .region = REGIONS_ETSI}, ++ {.ccode = "MR", .region = REGIONS_ETSI}, ++ {.ccode = "MT", .region = REGIONS_ETSI}, ++ {.ccode = "MU", .region = REGIONS_FCC}, ++ {.ccode = "MV", .region = REGIONS_ETSI}, ++ {.ccode = "MW", .region = REGIONS_ETSI}, ++ {.ccode = "MX", .region = REGIONS_FCC}, ++ {.ccode = "MY", .region = REGIONS_FCC}, ++ {.ccode = "NA", .region = REGIONS_ETSI}, ++ {.ccode = "NG", .region = REGIONS_ETSI}, ++ {.ccode = "NI", .region = REGIONS_FCC}, ++ {.ccode = "NL", .region = REGIONS_ETSI}, ++ {.ccode = "NO", .region = REGIONS_ETSI}, ++ {.ccode = "NP", .region = REGIONS_JP}, ++ {.ccode = "NZ", .region = REGIONS_ETSI}, ++ {.ccode = "OM", .region = REGIONS_ETSI}, ++ {.ccode = "PA", .region = REGIONS_FCC}, ++ {.ccode = "PE", .region = REGIONS_FCC}, ++ {.ccode = "PF", .region = REGIONS_ETSI}, ++ {.ccode = "PG", .region = REGIONS_FCC}, ++ {.ccode = "PH", .region = REGIONS_FCC}, ++ {.ccode = "PK", .region = REGIONS_ETSI}, ++ {.ccode = "PL", .region = REGIONS_ETSI}, ++ {.ccode = "PM", .region = REGIONS_ETSI}, ++ {.ccode = "PR", .region = REGIONS_FCC}, ++ {.ccode = "PT", .region = REGIONS_ETSI}, ++ {.ccode = "PW", .region = REGIONS_FCC}, ++ {.ccode = "PY", .region = REGIONS_FCC}, ++ {.ccode = "QA", .region = REGIONS_ETSI}, ++ {.ccode = "RE", .region = REGIONS_ETSI}, ++ {.ccode = "RO", .region = REGIONS_ETSI}, ++ {.ccode = "RS", .region = REGIONS_ETSI}, ++ {.ccode = "RU", .region = REGIONS_ETSI}, ++ {.ccode = "RW", .region = REGIONS_FCC}, ++ {.ccode = "SA", .region = REGIONS_ETSI}, ++ {.ccode = "SE", .region = REGIONS_ETSI}, ++ {.ccode = "SG", .region = REGIONS_ETSI}, ++ {.ccode = "SI", .region = REGIONS_ETSI}, ++ {.ccode = "SK", .region = REGIONS_ETSI}, ++ {.ccode = "SM", .region = REGIONS_ETSI}, ++ {.ccode = "SN", .region = REGIONS_FCC}, ++ {.ccode = "SR", .region = REGIONS_ETSI}, ++ {.ccode = "SV", .region = REGIONS_FCC}, ++ {.ccode = "SY", .region = REGIONS_DEFAULT}, ++ {.ccode = "TC", .region = REGIONS_FCC}, ++ {.ccode = "TD", .region = REGIONS_ETSI}, ++ {.ccode = "TG", .region = REGIONS_ETSI}, ++ {.ccode = "TH", .region = REGIONS_FCC}, ++ {.ccode = "TJ", .region = REGIONS_ETSI}, ++ {.ccode = "TM", .region = REGIONS_ETSI}, ++ {.ccode = "TN", .region = REGIONS_ETSI}, ++ {.ccode = "TR", .region = REGIONS_ETSI}, ++ {.ccode = "TT", .region = REGIONS_FCC}, ++ {.ccode = "TW", .region = REGIONS_FCC}, ++ {.ccode = "UA", .region = REGIONS_ETSI}, ++ {.ccode = "UG", .region = REGIONS_FCC}, ++ {.ccode = "UY", .region = REGIONS_FCC}, ++ {.ccode = "UZ", .region = REGIONS_ETSI}, ++ {.ccode = "VC", .region = REGIONS_ETSI}, ++ {.ccode = "VE", .region = REGIONS_FCC}, ++ {.ccode = "VI", .region = REGIONS_FCC}, ++ {.ccode = "VN", .region = REGIONS_JP}, ++ {.ccode = "VU", .region = REGIONS_FCC}, ++ {.ccode = "WF", .region = REGIONS_ETSI}, ++ {.ccode = "YE", .region = REGIONS_DEFAULT}, ++ {.ccode = "YT", .region = REGIONS_ETSI}, ++ {.ccode = "ZA", .region = REGIONS_ETSI}, ++ {.ccode = "ZM", .region = REGIONS_ETSI}, ++ {.ccode = "ZW", .region = REGIONS_ETSI}, ++}; ++ ++uint8_t get_ccode_region(char * ccode) ++{ ++ int i, cnt; ++ AICWFDBG(LOGDEBUG, "%s ccode:%s\r\n", __func__, ccode); ++ ++ cnt = sizeof(reg_tables) / sizeof(reg_tables[0]); ++ ++ for (i = 0; i < cnt; i++) { ++ if (reg_tables[i].ccode[0] == ccode[0] && ++ reg_tables[i].ccode[1] == ccode[1]) { ++ AICWFDBG(LOGDEBUG, "region: %d\r\n", reg_tables[i].region); ++ return reg_tables[i].region; ++ } ++ } ++ AICWFDBG(LOGDEBUG, "use default region\r\n"); ++ return REGIONS_DEFAULT; ++} ++ ++u8 get_region_index(char * name) ++{ ++ if (strncmp(name, "SRRC", 4) == 0) ++ return REGIONS_SRRC; ++ else if (strncmp(name, "FCC", 3) == 0) ++ return REGIONS_FCC; ++ else if (strncmp(name, "ETSI", 4) == 0) ++ return REGIONS_ETSI; ++ else if (strncmp(name, "JP", 2) == 0) ++ return REGIONS_JP; ++ else if (strncmp(name, "UNSET", 5) == 0) ++ return REGIONS_DEFAULT; ++ ++ return REGIONS_DEFAULT; ++} ++ ++ ++#ifdef CONFIG_POWER_LIMIT ++#define POWER_LIMIT_INVALID_VAL POWER_LEVEL_INVALID_VAL ++ ++#define POWER_LIMIT_CC_MATCHED_BIT (0x1U << 0) ++ ++#define MAX_2_4G_BW_NUM 2 ++#define MAX_5G_BW_NUM 3 ++#define MAX_REGION_NUM 5 ++ ++typedef struct ++{ ++ u8_l ch_cnt_2g4[MAX_2_4G_BW_NUM]; ++ u8_l ch_cnt_5g[MAX_5G_BW_NUM]; ++ u8_l ch_num_2g4[MAX_2_4G_BW_NUM][MAC_DOMAINCHANNEL_24G_MAX]; ++ u8_l ch_num_5g[MAX_5G_BW_NUM][MAC_DOMAINCHANNEL_5G_MAX]; ++ s8_l max_pwr_2g4[MAX_2_4G_BW_NUM][MAC_DOMAINCHANNEL_24G_MAX]; ++ s8_l max_pwr_5g[MAX_5G_BW_NUM][MAC_DOMAINCHANNEL_5G_MAX]; ++} txpwr_lmt_info_t; ++ ++typedef struct ++{ ++ u32_l flags; ++ txpwr_lmt_info_t txpwr_lmt[MAX_REGION_NUM]; ++} powerlimit_info_t; ++ ++powerlimit_info_t powerlimit_info = {0,}; ++#endif ++ ++#ifdef CONFIG_RWNX_TL4 ++/** ++ * rwnx_plat_tl4_fw_upload() - Load the requested FW into embedded side. ++ * ++ * @rwnx_plat: pointer to platform structure ++ * @fw_addr: Virtual address where the fw must be loaded ++ * @filename: Name of the fw. ++ * ++ * Load a fw, stored as a hex file, into the specified address ++ */ ++static int rwnx_plat_tl4_fw_upload(struct rwnx_plat *rwnx_plat, u8 *fw_addr, ++ char *filename) ++{ ++ struct device *dev = rwnx_platform_get_dev(rwnx_plat); ++ const struct firmware *fw; ++ int err = 0; ++ u32 *dst; ++ u8 const *file_data; ++ char typ0, typ1; ++ u32 addr0, addr1; ++ u32 dat0, dat1; ++ int remain; ++ ++ err = request_firmware(&fw, filename, dev); ++ if (err) { ++ return err; ++ } ++ file_data = fw->data; ++ remain = fw->size; ++ ++ /* Copy the file on the Embedded side */ ++ dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr); ++ ++ /* Walk through all the lines of the configuration file */ ++ while (remain >= 16) { ++ u32 data, offset; ++ ++ if (sscanf(file_data, "%c:%08X %04X", &typ0, &addr0, &dat0) != 3) ++ break; ++ if ((addr0 & 0x01) != 0) { ++ addr0 = addr0 - 1; ++ dat0 = 0; ++ } else { ++ file_data += 16; ++ remain -= 16; ++ } ++ if ((remain < 16) || ++ (sscanf(file_data, "%c:%08X %04X", &typ1, &addr1, &dat1) != 3) || ++ (typ1 != typ0) || (addr1 != (addr0 + 1))) { ++ typ1 = typ0; ++ addr1 = addr0 + 1; ++ dat1 = 0; ++ } else { ++ file_data += 16; ++ remain -= 16; ++ } ++ ++ if (typ0 == 'C') { ++ offset = 0x00200000; ++ if ((addr1 % 4) == 3) ++ offset += 2*(addr1 - 3); ++ else ++ offset += 2*(addr1 + 1); ++ ++ data = dat1 | (dat0 << 16); ++ } else { ++ offset = 2*(addr1 - 1); ++ data = dat0 | (dat1 << 16); ++ } ++ dst = (u32 *)(fw_addr + offset); ++ *dst = data; ++ } ++ ++ release_firmware(fw); ++ ++ return err; ++} ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) ++MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver"); ++#else ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#endif ++#endif ++ ++#if 0 ++/** ++ * rwnx_plat_bin_fw_upload() - Load the requested binary FW into embedded side. ++ * ++ * @rwnx_plat: pointer to platform structure ++ * @fw_addr: Virtual address where the fw must be loaded ++ * @filename: Name of the fw. ++ * ++ * Load a fw, stored as a binary file, into the specified address ++ */ ++static int rwnx_plat_bin_fw_upload(struct rwnx_plat *rwnx_plat, u8 *fw_addr, ++ char *filename) ++{ ++ const struct firmware *fw; ++ struct device *dev = rwnx_platform_get_dev(rwnx_plat); ++ int err = 0; ++ unsigned int i, size; ++ u32 *src, *dst; ++ ++ err = request_firmware(&fw, filename, dev); ++ if (err) { ++ return err; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr); ++ ++ src = (u32 *)fw->data; ++ dst = (u32 *)fw_addr; ++ size = (unsigned int)fw->size; ++ ++ /* check potential platform bug on multiple stores vs memcpy */ ++ for (i = 0; i < size; i += 4) { ++ *dst++ = *src++; ++ } ++ ++ release_firmware(fw); ++ ++ return err; ++} ++#endif ++ ++#define MD5(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] ++#define MD5PINRT "file md5:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\r\n" ++ ++static int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device) ++{ ++#ifdef CONFIG_USE_FW_REQUEST ++ const struct firmware *fw = NULL; ++ u32 *dst = NULL; ++ void *buffer=NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ int size = 0; ++ int ret = 0; ++ ++ printk("%s: request firmware = %s \n", __func__ ,name); ++ ++ ret = request_firmware(&fw, name, NULL); ++ ++ if (ret < 0) { ++ printk("Load %s fail\n", name); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ size = fw->size; ++ dst = (u32 *)fw->data; ++ ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ memcpy(buffer, dst, size); ++ ++ *fw_buf = buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ release_firmware(fw); ++ ++ return size; ++#else ++ void *buffer = NULL; ++ char *path = NULL; ++ struct file *fp = NULL; ++ int size = 0, len = 0;// i = 0; ++ ssize_t rdlen = 0; ++ //u32 *src = NULL, *dst = NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ ++ /* get the firmware path */ ++ path = __getname(); ++ if (!path) { ++ *fw_buf = NULL; ++ return -1; ++ } ++ ++ len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", aic_fw_path, name); ++ ++ //len = snprintf(path, FW_PATH_MAX_LEN, "%s", name); ++ if (len >= FW_PATH_MAX_LEN) { ++ AICWFDBG(LOGERROR, "%s: %s file's path too long\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ return -1; ++ } ++ ++ AICWFDBG(LOGINFO, "%s :firmware path = %s \n", __func__, path); ++ ++ /* open the firmware file */ ++ fp = filp_open(path, O_RDONLY, 0); ++ if (IS_ERR_OR_NULL(fp)) { ++ AICWFDBG(LOGERROR, "%s: %s file failed to open\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ fp = NULL; ++ return -1; ++ } ++ ++ size = i_size_read(file_inode(fp)); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "%s: %s file size invalid %d\n", __func__, name, size); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ } ++ ++ /* start to read from firmware file */ ++ buffer = kzalloc(size, GFP_KERNEL); ++ if (!buffer) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ } ++ ++ #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) ++ rdlen = kernel_read(fp, buffer, size, &fp->f_pos); ++ #else ++ rdlen = kernel_read(fp, fp->f_pos, buffer, size); ++ #endif ++ ++ if (size != rdlen) { ++ AICWFDBG(LOGERROR, "%s: %s file rdlen invalid %d\n", __func__, name, (int)rdlen); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ kfree(buffer); ++ buffer = NULL; ++ return -1; ++ } ++ if (rdlen > 0) { ++ fp->f_pos += rdlen; ++ } ++ ++#if 0 ++ /*start to transform the data format*/ ++ src = (u32 *)buffer; ++ dst = (u32 *)kzalloc(size, GFP_KERNEL); ++ ++ if (!dst) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ kfree(buffer); ++ buffer = NULL; ++ return -1; ++ } ++ ++ for (i = 0; i < (size/4); i++) { ++ dst[i] = src[i]; ++ } ++#endif ++ ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ //kfree(buffer); ++ //buffer = NULL; ++ *fw_buf = (u32*)buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ ++ AICWFDBG(LOGINFO, MD5PINRT, MD5(decrypt)); ++ ++ return size; ++#endif ++} ++ ++ ++ ++/* buffer is allocated by kzalloc */ ++int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, u32** buffer, const char *filename) ++{ ++ int size; ++ ++ AICWFDBG(LOGINFO, "### Load file %s\n", filename); ++ ++ size = rwnx_load_firmware(buffer, filename, NULL); ++ ++ return size; ++} ++ ++static void rwnx_restore_firmware(u32 **fw_buf) ++{ ++#ifdef CONFIG_USE_FW_REQUEST ++ vfree(*fw_buf); ++#else ++ kfree(*fw_buf); ++#endif ++ *fw_buf = NULL; ++} ++ ++ ++void rwnx_release_firmware_common(u32** buffer) ++{ ++ rwnx_restore_firmware(buffer); ++} ++ ++ ++/** ++ * rwnx_plat_bin_fw_upload_2() - Load the requested binary FW into embedded side. ++ * ++ * @rwnx_hw: Main driver data ++ * @fw_addr: Address where the fw must be loaded ++ * @filename: Name of the fw. ++ * ++ * Load a fw, stored as a binary file, into the specified address ++ */ ++int rwnx_plat_bin_fw_upload_2(struct rwnx_hw *rwnx_hw, u32 fw_addr, ++ char *filename) ++{ ++ int err = 0; ++ unsigned int i = 0, size; ++// u32 *src; ++ u32 *dst=NULL; ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Upload %s firmware, @ = %x\n", filename, fw_addr); ++ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (!dst) { ++ AICWFDBG(LOGERROR, "No such file or directory\n"); ++ return -1; ++ } ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ err = -1; ++ } ++ ++ AICWFDBG(LOGINFO, "size=%d, dst[0]=%x\n", size, dst[0]); ++ if (size > 512) { ++ for (; i < (size - 512); i += 512) { ++ //printk("wr blk 0: %p -> %x\r\n", dst + i / 4, fw_addr + i); ++ err = rwnx_send_dbg_mem_block_write_req(rwnx_hw, fw_addr + i, 512, dst + i / 4); ++ if (err) { ++ AICWFDBG(LOGERROR, "bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ break; ++ } ++ } ++ } ++ if (!err && (i < size)) { ++ //printk("wr blk 1: %p -> %x\r\n", dst + i / 4, fw_addr + i); ++ err = rwnx_send_dbg_mem_block_write_req(rwnx_hw, fw_addr + i, size - i, dst + i / 4); ++ if (err) { ++ AICWFDBG(LOGERROR, "bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ } ++ } ++ ++ if (dst) { ++ rwnx_release_firmware_common(&dst); ++ } ++ ++ return err; ++} ++ ++ ++ ++typedef struct { ++ txpwr_idx_conf_t txpwr_idx; ++ txpwr_ofst_conf_t txpwr_ofst; ++ xtal_cap_conf_t xtal_cap; ++} nvram_info_t; ++ ++nvram_info_t nvram_info = { ++ .txpwr_idx = { ++ .enable = 1, ++ .dsss = 9, ++ .ofdmlowrate_2g4 = 8, ++ .ofdm64qam_2g4 = 8, ++ .ofdm256qam_2g4 = 8, ++ .ofdm1024qam_2g4 = 8, ++ .ofdmlowrate_5g = 11, ++ .ofdm64qam_5g = 10, ++ .ofdm256qam_5g = 9, ++ .ofdm1024qam_5g = 9 ++ }, ++ .txpwr_ofst = { ++ .enable = 1, ++ .chan_1_4 = 0, ++ .chan_5_9 = 0, ++ .chan_10_13 = 0, ++ .chan_36_64 = 0, ++ .chan_100_120 = 0, ++ .chan_122_140 = 0, ++ .chan_142_165 = 0, ++ }, ++ .xtal_cap = { ++ .enable = 0, ++ .xtal_cap = 24, ++ .xtal_cap_fine = 31, ++ }, ++}; ++ ++void get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst_conf_t *txpwr_ofst) ++{ ++ txpwr_ofst->enable = userconfig_info.txpwr_ofst.enable; ++ txpwr_ofst->chan_1_4 = userconfig_info.txpwr_ofst.chan_1_4; ++ txpwr_ofst->chan_5_9 = userconfig_info.txpwr_ofst.chan_5_9; ++ txpwr_ofst->chan_10_13 = userconfig_info.txpwr_ofst.chan_10_13; ++ txpwr_ofst->chan_36_64 = userconfig_info.txpwr_ofst.chan_36_64; ++ txpwr_ofst->chan_100_120 = userconfig_info.txpwr_ofst.chan_100_120; ++ txpwr_ofst->chan_122_140 = userconfig_info.txpwr_ofst.chan_122_140; ++ txpwr_ofst->chan_142_165 = userconfig_info.txpwr_ofst.chan_142_165; ++ ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst->enable); ++ AICWFDBG(LOGINFO, "%s:chan_1_4 :%d\r\n", __func__, txpwr_ofst->chan_1_4); ++ AICWFDBG(LOGINFO, "%s:chan_5_9 :%d\r\n", __func__, txpwr_ofst->chan_5_9); ++ AICWFDBG(LOGINFO, "%s:chan_10_13 :%d\r\n", __func__, txpwr_ofst->chan_10_13); ++ AICWFDBG(LOGINFO, "%s:chan_36_64 :%d\r\n", __func__, txpwr_ofst->chan_36_64); ++ AICWFDBG(LOGINFO, "%s:chan_100_120:%d\r\n", __func__, txpwr_ofst->chan_100_120); ++ AICWFDBG(LOGINFO, "%s:chan_122_140:%d\r\n", __func__, txpwr_ofst->chan_122_140); ++ AICWFDBG(LOGINFO, "%s:chan_142_165:%d\r\n", __func__, txpwr_ofst->chan_142_165); ++} ++ ++void get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x_conf_t *txpwr_ofst2x) ++{ ++ int type, ch_grp; ++ *txpwr_ofst2x = userconfig_info.txpwr_ofst2x; ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst2x->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g: [0]:11b, [1]:ofdm_highrate, [2]:ofdm_lowrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_2g4[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g: [0]:ofdm_lowrate, [1]:ofdm_highrate, [2]:ofdm_midrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_5g[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++} ++ ++void get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2) ++{ ++ int type, ch_grp; ++ *txpwr_ofst2x_v2 = userconfig_info.txpwr_ofst2x_v2; ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst2x_v2->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g(ant0/ant1): [0]:11b, [1]:ofdm_highrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 2; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g: [0]:ofdm_highrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 1; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++} ++ ++void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx) ++{ ++ memcpy(txpwr_idx, &(nvram_info.txpwr_idx), sizeof(txpwr_idx_conf_t)); ++} ++ ++void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst) ++{ ++ memcpy(txpwr_ofst, &(nvram_info.txpwr_ofst), sizeof(txpwr_ofst_conf_t)); ++} ++ ++void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap) ++{ ++ if(nvram_info.xtal_cap.enable){ ++ *xtal_cap = nvram_info.xtal_cap; ++ } ++ ++ if(userconfig_info.xtal_cap.enable){ ++ *xtal_cap = userconfig_info.xtal_cap; ++ } ++ ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, xtal_cap->enable); ++ AICWFDBG(LOGINFO, "%s:xtal_cap :%d\r\n", __func__, xtal_cap->xtal_cap); ++ AICWFDBG(LOGINFO, "%s:xtal_cap_fine:%d\r\n", __func__, xtal_cap->xtal_cap_fine); ++} ++ ++s8_l get_txpwr_max(s8_l power) ++{ ++ int i=0; ++ ++ if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i]; ++ } ++ for (i = 0; i <= 9; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i]; ++ } ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i]; ++ } ++ for (i = 4; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i]; ++ } ++ for (i = 0; i <= 9; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i]; ++ } ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i]; ++ } ++ ++ if ((userconfig_info.txpwr_loss.loss_enable_2g4 == 1) || ++ (userconfig_info.txpwr_loss.loss_enable_5g == 1)) { ++ if (userconfig_info.txpwr_loss.loss_value_2g4 < ++ userconfig_info.txpwr_loss.loss_value_5g) ++ power += userconfig_info.txpwr_loss.loss_value_5g; ++ else ++ power += userconfig_info.txpwr_loss.loss_value_2g4; ++ } ++ ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[i]; ++ } ++ for (i = 0; i <= 9; i++){ ++ if(power < userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[i]; ++ } ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[i]; ++ } ++ } ++ ++ printk("%s:txpwr_max:%d \r\n",__func__,power); ++ return power; ++} ++ ++ ++void set_txpwr_loss_ofst(s8_l value) ++{ ++ int i=0; ++ if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i] += value; ++ } ++ for (i = 4; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i] += value; ++ } ++ }else if( g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[i] += value; ++ } ++ for (i = 0; i <= 7; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[i] += value; ++ } ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[i] += value; ++ } ++ } ++ printk("%s:value:%d\r\n", __func__, value); ++} ++ ++ ++#define MATCH_NODE(type, node, cfg_key) {cfg_key, offsetof(type, node)} ++ ++struct parse_match_t { ++ char keyname[64]; ++ int offset; ++}; ++ ++static const char *parse_key_prefix[] = { ++ [0x01] = "module0_", ++ [0x21] = "module1_", ++}; ++ ++static const struct parse_match_t parse_match_tab[] = { ++ MATCH_NODE(nvram_info_t, txpwr_idx.enable, "enable"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.dsss, "dsss"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdmlowrate_2g4, "ofdmlowrate_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm64qam_2g4, "ofdm64qam_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm256qam_2g4, "ofdm256qam_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm1024qam_2g4, "ofdm1024qam_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdmlowrate_5g, "ofdmlowrate_5g"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm64qam_5g, "ofdm64qam_5g"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm256qam_5g, "ofdm256qam_5g"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm1024qam_5g, "ofdm1024qam_5g"), ++ ++ MATCH_NODE(nvram_info_t, txpwr_ofst.enable, "ofst_enable"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_1_4, "ofst_chan_1_4"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_5_9, "ofst_chan_5_9"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_10_13, "ofst_chan_10_13"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_36_64, "ofst_chan_36_64"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_100_120, "ofst_chan_100_120"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_122_140, "ofst_chan_122_140"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_142_165, "ofst_chan_142_165"), ++ ++ MATCH_NODE(nvram_info_t, xtal_cap.enable, "xtal_enable"), ++ MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap, "xtal_cap"), ++ MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap_fine, "xtal_cap_fine"), ++}; ++ ++static int parse_key_val(const char *str, const char *key, char *val) ++{ ++ const char *p = NULL; ++ const char *dst = NULL; ++ int keysize = 0; ++ int bufsize = 0; ++ ++ if (str == NULL || key == NULL || val == NULL) ++ return -1; ++ ++ keysize = strlen(key); ++ bufsize = strlen(str); ++ if (bufsize <= keysize) ++ return -1; ++ ++ p = str; ++ while (*p != 0 && *p == ' ') ++ p++; ++ ++ if (*p == '#') ++ return -1; ++ ++ if (str + bufsize - p <= keysize) ++ return -1; ++ ++ if (strncmp(p, key, keysize) != 0) ++ return -1; ++ ++ p += keysize; ++ ++ while (*p != 0 && *p == ' ') ++ p++; ++ ++ if (*p != '=') ++ return -1; ++ ++ p++; ++ while (*p != 0 && *p == ' ') ++ p++; ++ ++ if (*p == '"') ++ p++; ++ ++ dst = p; ++ while (*p != 0) ++ p++; ++ ++ p--; ++ while (*p == ' ') ++ p--; ++ ++ if (*p == '"') ++ p--; ++ ++ while (*p == '\r' || *p == '\n') ++ p--; ++ ++ p++; ++ strncpy(val, dst, p -dst); ++ val[p - dst] = 0; ++ return 0; ++} ++ ++int rwnx_atoi2(char *value, int c_len) ++{ ++ int len = 0; ++ int i = 0; ++ int result = 0; ++ int flag = 1; ++ ++ if (value[0] == '-') { ++ flag = -1; ++ value++; ++ } ++ len = c_len; ++ ++ for (i = 0;i < len ;i++) { ++ result = result * 10; ++ if (value[i] >= 48 && value[i] <= 57) { ++ result += value[i] - 48; ++ } else { ++ result = 0; ++ break; ++ } ++ } ++ ++ return result * flag; ++} ++ ++ ++int rwnx_atoi(char *value) ++{ ++ int len = 0; ++ int i = 0; ++ int result = 0; ++ int flag = 1; ++ ++ if (value[0] == '-') { ++ flag = -1; ++ value++; ++ } ++ len = strlen(value); ++ ++ for (i = 0;i < len ;i++) { ++ result = result * 10; ++ if (value[i] >= 48 && value[i] <= 57) { ++ result += value[i] - 48; ++ } else { ++ result = 0; ++ break; ++ } ++ } ++ ++ return result * flag; ++} ++ ++ ++void rwnx_plat_nvram_set_value(char *command, char *value) ++{ ++ //TODO send command ++ AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); ++ if (!strcmp(command, "enable")) { ++ userconfig_info.txpwr_lvl.enable = rwnx_atoi(value); ++ userconfig_info.txpwr_lvl_v2.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "dsss")) { ++ userconfig_info.txpwr_lvl.dsss = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_2g4")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_5g")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_enable")) { ++ userconfig_info.txpwr_ofst.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_1_4")) { ++ userconfig_info.txpwr_ofst.chan_1_4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_5_9")) { ++ userconfig_info.txpwr_ofst.chan_5_9 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_10_13")) { ++ userconfig_info.txpwr_ofst.chan_10_13 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_36_64")) { ++ userconfig_info.txpwr_ofst.chan_36_64 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_100_120")) { ++ userconfig_info.txpwr_ofst.chan_100_120 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_122_140")) { ++ userconfig_info.txpwr_ofst.chan_122_140 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_142_165")) { ++ userconfig_info.txpwr_ofst.chan_142_165 = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_enable")) { ++ userconfig_info.xtal_cap.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap")) { ++ userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap_fine")) { ++ userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); ++ } else { ++ AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); ++ } ++} ++ ++void rwnx_plat_nvram_set_value_v3(char *command, char *value) ++{ ++ //TODO send command ++ AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); ++ if (!strcmp(command, "enable")) { ++ userconfig_info.txpwr_lvl.enable = rwnx_atoi(value); ++ userconfig_info.txpwr_lvl_v3.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "dsss")) { ++ userconfig_info.txpwr_lvl.dsss = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_2g4")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_5g")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_1m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_2m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_5m5_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_11m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_6m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_9m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_12m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_18m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_24m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_36m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_48m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_54m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_enable")) { ++ userconfig_info.txpwr_lvl_adj.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_1_4")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_5_9")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_10_13")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_42")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_58")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_106")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_122")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_138")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_155")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_2g4")) { ++ userconfig_info.txpwr_loss.loss_enable_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_2g4")) { ++ userconfig_info.txpwr_loss.loss_value_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_5g")) { ++ userconfig_info.txpwr_loss.loss_enable_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_5g")) { ++ userconfig_info.txpwr_loss.loss_value_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_enable")) { ++ userconfig_info.txpwr_ofst.enable = rwnx_atoi(value); ++ userconfig_info.txpwr_ofst2x.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_1_4")) { ++ userconfig_info.txpwr_ofst.chan_1_4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_5_9")) { ++ userconfig_info.txpwr_ofst.chan_5_9 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_10_13")) { ++ userconfig_info.txpwr_ofst.chan_10_13 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_36_64")) { ++ userconfig_info.txpwr_ofst.chan_36_64 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_100_120")) { ++ userconfig_info.txpwr_ofst.chan_100_120 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_122_140")) { ++ userconfig_info.txpwr_ofst.chan_122_140 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_142_165")) { ++ userconfig_info.txpwr_ofst.chan_142_165 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_11b_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_11b_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_11b_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[0][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_highrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_highrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_highrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[1][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_lowrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_lowrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_lowrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[2][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_enable")) { ++ userconfig_info.xtal_cap.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap")) { ++ userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap_fine")) { ++ userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); ++ } else { ++ AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); ++ } ++} ++ ++void rwnx_plat_userconfig_parsing2(char *buffer, int size) ++{ ++ int i = 0; ++ int parse_state = 0; ++ char command[30]; ++ char value[100]; ++ int char_counter = 0; ++ ++ memset(command, 0, 30); ++ memset(value, 0, 100); ++ ++ for (i = 0; i < size; i++) { ++ //Send command or print nvram log when char is \r or \n ++ if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ if (command[0] != 0 && value[0] != 0) { ++ if (parse_state == PRINT) { ++ AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); ++ } else if (parse_state == GET_VALUE) { ++ rwnx_plat_nvram_set_value(command, value); ++ } ++ } ++ //Reset command value and char_counter ++ memset(command, 0, 30); ++ memset(value, 0, 100); ++ char_counter = 0; ++ parse_state = INIT; ++ continue; ++ } ++ ++ //Switch parser state ++ if (parse_state == INIT) { ++ if (buffer[i] == '#') { ++ parse_state = PRINT; ++ continue; ++ } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ parse_state = INIT; ++ continue; ++ } else { ++ parse_state = CMD; ++ } ++ } ++ ++ //Fill data to command and value ++ if (parse_state == PRINT) { ++ command[0] = 0x01; ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == CMD) { ++ if (command[0] != 0 && buffer[i] == '=') { ++ parse_state = GET_VALUE; ++ char_counter = 0; ++ continue; ++ } ++ command[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == GET_VALUE) { ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } ++ } ++} ++ ++void rwnx_plat_userconfig_parsing3(char *buffer, int size) ++{ ++ int i = 0; ++ int parse_state = 0; ++ char command[64]; ++ char value[100]; ++ int char_counter = 0; ++ ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ ++ for (i = 0; i < size; i++) { ++ //Send command or print nvram log when char is \r or \n ++ if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ if (command[0] != 0 && value[0] != 0) { ++ if (parse_state == PRINT) { ++ AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); ++ } else if (parse_state == GET_VALUE) { ++ rwnx_plat_nvram_set_value_v3(command, value); ++ } ++ } ++ //Reset command value and char_counter ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ char_counter = 0; ++ parse_state = INIT; ++ continue; ++ } ++ ++ //Switch parser state ++ if (parse_state == INIT) { ++ if (buffer[i] == '#') { ++ parse_state = PRINT; ++ continue; ++ } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ parse_state = INIT; ++ continue; ++ } else { ++ parse_state = CMD; ++ } ++ } ++ ++ //Fill data to command and value ++ if (parse_state == PRINT) { ++ command[0] = 0x01; ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == CMD) { ++ if (command[0] != 0 && buffer[i] == '=') { ++ parse_state = GET_VALUE; ++ char_counter = 0; ++ continue; ++ } ++ command[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == GET_VALUE) { ++ if(buffer[i] != 0x2D && (buffer[i] < 0x30 || buffer[i] > 0x39)) { ++ continue; ++ } ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } ++ } ++} ++ ++void rwnx_plat_userconfig_parsing(struct rwnx_hw *rwnx_hw, char *buffer, int size) ++{ ++ char conf[100], keyname[64]; ++ char *line; ++ char *data; ++ int i = 0, err, len = 0; ++ long val; ++ ++ if (size <= 0) { ++ pr_err("Config buffer size %d error\n", size); ++ return; ++ } ++ ++ printk("%s rwnx_hw->vendor_info:0x%02X \r\n", __func__, rwnx_hw->vendor_info); ++ if (rwnx_hw->vendor_info == 0x00 || ++ (rwnx_hw->vendor_info > (sizeof(parse_key_prefix) / sizeof(parse_key_prefix[0]) - 1))) { ++ printk("Unsuppor vendor info config\n"); ++ printk("Using module0 config\n"); ++ rwnx_hw->vendor_info = 0x01; ++ //return; ++ } ++ ++ data = vmalloc(size + 1); ++ if (!data) { ++ pr_err("vmalloc fail\n"); ++ return; ++ } ++ ++ memcpy(data, buffer, size); ++ buffer = data; ++ ++ while (1) { ++ line = buffer; ++ if (*line == 0) ++ break; ++ ++ while (*buffer != '\r' && *buffer != '\n' && *buffer != 0 && len++ < size) ++ buffer++; ++ ++ while ((*buffer == '\r' || *buffer == '\n') && len++ < size) ++ *buffer++ = 0; ++ ++ if (len >= size) ++ *buffer = 0; ++ ++ // store value to data struct ++ for (i = 0; i < sizeof(parse_match_tab) / sizeof(parse_match_tab[0]); i++) { ++ sprintf(&keyname[0], "%s%s", parse_key_prefix[rwnx_hw->vendor_info], parse_match_tab[i].keyname); ++ if (parse_key_val(line, keyname, conf) == 0) { ++ err = kstrtol(conf, 0, &val); ++ *(unsigned long *)((unsigned long)&nvram_info + parse_match_tab[i].offset) = val; ++ printk("%s, %s = %ld\n", __func__, parse_match_tab[i].keyname, val); ++ break; ++ } ++ } ++ ++ } ++ vfree(data); ++} ++ ++void rwnx_plat_nvram_set_value_8800d80x2(char *command, char *value) ++{ ++ //TODO send command ++ AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); ++ if (!strcmp(command, "enable")) { ++ userconfig_info.txpwr_lvl_v4.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_6m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_9m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_12m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_18m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_24m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_36m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_48m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_54m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_enable")) { ++ userconfig_info.txpwr_lvl_adj.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_1_4")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_5_9")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_10_13")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_42")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_58")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_106")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_122")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_138")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_155")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_2g4")) { ++ userconfig_info.txpwr_loss.loss_enable_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_2g4")) { ++ userconfig_info.txpwr_loss.loss_value_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_5g")) { ++ userconfig_info.txpwr_loss.loss_enable_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_5g")) { ++ userconfig_info.txpwr_loss.loss_value_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_enable")) { ++ userconfig_info.txpwr_ofst2x_v2.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_11b_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_11b_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_11b_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_ofdm_highrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_ofdm_highrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_ofdm_highrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_11b_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_11b_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_11b_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_ofdm_highrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_ofdm_highrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_ofdm_highrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[3][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[4][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[5][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[3][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[4][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[5][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_enable")) { ++ userconfig_info.xtal_cap.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap")) { ++ userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap_fine")) { ++ userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); ++ } else { ++ AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); ++ } ++} ++ ++void rwnx_plat_userconfig_parsing_8800d80x2(char *buffer, int size) ++{ ++ int i = 0; ++ int parse_state = 0; ++ char command[100]; ++ char value[100]; ++ int char_counter = 0; ++ ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ ++ for (i = 0; i < size; i++) { ++ //Send command or print nvram log when char is \r or \n ++ if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ if (command[0] != 0 && value[0] != 0) { ++ if (parse_state == PRINT) { ++ AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); ++ } else if (parse_state == GET_VALUE) { ++ rwnx_plat_nvram_set_value_8800d80x2(command, value); ++ } ++ } ++ //Reset command value and char_counter ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ char_counter = 0; ++ parse_state = INIT; ++ continue; ++ } ++ ++ //Switch parser state ++ if (parse_state == INIT) { ++ if (buffer[i] == '#') { ++ parse_state = PRINT; ++ continue; ++ } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ parse_state = INIT; ++ continue; ++ } else { ++ parse_state = CMD; ++ } ++ } ++ ++ //Fill data to command and value ++ if (parse_state == PRINT) { ++ command[0] = 0x01; ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == CMD) { ++ if (command[0] != 0 && buffer[i] == '=') { ++ parse_state = GET_VALUE; ++ char_counter = 0; ++ continue; ++ } ++ command[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == GET_VALUE) { ++ if(buffer[i] != 0x2D && (buffer[i] < 0x30 || buffer[i] > 0x39)) { ++ continue; ++ } ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } ++ } ++} ++ ++static int aic_load_firmware(u32 ** fw_buf, char *fw_path,const char *name, struct device *device) ++{ ++#ifdef CONFIG_USE_FW_REQUEST ++ const struct firmware *fw = NULL; ++ u32 *dst = NULL; ++ void *buffer=NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ int size = 0; ++ int ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s: request firmware = %s \n", __func__ ,name); ++ ++ ret = request_firmware(&fw, name, NULL); ++ ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "Load %s fail\n", name); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ size = fw->size; ++ dst = (u32 *)fw->data; ++ ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ memcpy(buffer, dst, size); ++ ++ *fw_buf = buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ AICWFDBG(LOGINFO, MD5PINRT, MD5(decrypt)); ++ ++ release_firmware(fw); ++ ++ return size; ++#else ++ void *buffer=NULL; ++ char *path=NULL; ++ struct file *fp=NULL; ++ int size = 0, len=0;//, i=0; ++ ssize_t rdlen=0; ++ //u32 *src=NULL, *dst = NULL; ++ ++ /* get the firmware path */ ++ path = __getname(); ++ if (!path){ ++ *fw_buf=NULL; ++ return -1; ++ } ++ ++ len = sprintf(path, "%s/%s",fw_path, name); ++ ++ AICWFDBG(LOGINFO, "%s :firmware path = %s \n", __func__ ,path); ++ ++ ++ /* open the firmware file */ ++ fp=filp_open(path, O_RDONLY, 0); ++ if(IS_ERR(fp) || (!fp)){ ++ printk("%s: %s file failed to open\n", __func__, name); ++ if(IS_ERR(fp)){ ++ printk("is_Err\n"); ++ } ++ if((!fp)){ ++ printk("null\n"); ++ } ++ *fw_buf=NULL; ++ __putname(path); ++ fp=NULL; ++ return -1; ++ } ++ ++ size = i_size_read(file_inode(fp)); ++ if(size<=0){ ++ printk("%s: %s file size invalid %d\n", __func__, name, size); ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ return -1; ++ } ++ ++ /* start to read from firmware file */ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ if(!buffer){ ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ return -1; ++ } ++ ++ ++ #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) ++ rdlen = kernel_read(fp, buffer, size, &fp->f_pos); ++ #else ++ rdlen = kernel_read(fp, fp->f_pos, buffer, size); ++ #endif ++ ++ if(size != rdlen){ ++ printk("%s: %s file rdlen invalid %d %d\n", __func__, name, (int)rdlen, size); ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ vfree(buffer); ++ buffer=NULL; ++ return -1; ++ } ++ if(rdlen > 0){ ++ fp->f_pos += rdlen; ++ //printk("f_pos=%d\n", (int)fp->f_pos); ++ } ++ ++#if 0 ++ /*start to transform the data format*/ ++ src = (u32*)buffer; ++ //printk("malloc dst\n"); ++ dst = (u32*)vmalloc(size); ++ memset(dst, 0, size); ++ ++ if(!dst){ ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ vfree(buffer); ++ buffer=NULL; ++ return -1; ++ } ++ ++ for(i=0;i<(size/4);i++){ ++ dst[i] = src[i]; ++ } ++#endif ++ ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ //vfree(buffer); ++ //buffer=NULL; ++ *fw_buf = (u32 *)buffer; ++ ++ return size; ++#endif ++} ++ ++ ++ ++#define FW_USERCONFIG_NAME "aic_userconfig.txt" ++ ++int rwnx_plat_userconfig_upload_android(struct rwnx_hw *rwnx_hw, char *fw_path, char *filename) ++{ ++ int size; ++ u32 *dst=NULL; ++ ++ printk("userconfig file path:%s \r\n", filename); ++ ++ /* load aic firmware */ ++ size = aic_load_firmware(&dst, fw_path ,filename, NULL); ++ if(size <= 0){ ++ printk("wrong size of firmware file\n"); ++ vfree(dst); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload %s userconfig, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing(rwnx_hw, (char *)dst, size); ++ ++ if (dst) { ++ vfree(dst); ++ dst = NULL; ++ } ++ ++ printk("userconfig download complete\n\n"); ++ ++ return 0; ++ ++} ++ ++/** ++ * rwnx_plat_fmac_load() - Load FW code ++ * ++ * @rwnx_hw: Main driver data ++ */ ++ #if 0 ++static int rwnx_plat_fmac_load(struct rwnx_hw *rwnx_hw, char *fw_path) ++{ ++ int ret = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ret = rwnx_plat_userconfig_upload_android(rwnx_hw, fw_path, FW_USERCONFIG_NAME); ++ return ret; ++} ++ #endif ++ ++/** ++ * rwnx_platform_reset() - Reset the platform ++ * ++ * @rwnx_plat: platform data ++ */ ++static int rwnx_platform_reset(struct rwnx_plat *rwnx_plat) ++{ ++ u32 regval; ++ ++#if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) ++ return 0; ++#endif ++ ++ /* the doc states that SOFT implies FPGA_B_RESET ++ * adding FPGA_B_RESET is clearer */ ++ RWNX_REG_WRITE(SOFT_RESET | FPGA_B_RESET, rwnx_plat, ++ RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); ++ msleep(100); ++ ++ regval = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); ++ ++ if (regval & SOFT_RESET) { ++ dev_err(rwnx_platform_get_dev(rwnx_plat), "reset: failed\n"); ++ return -EIO; ++ } ++ ++ RWNX_REG_WRITE(regval & ~FPGA_B_RESET, rwnx_plat, ++ RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); ++ msleep(100); ++ return 0; ++} ++ ++/** ++ * rwmx_platform_save_config() - Save hardware config before reload ++ * ++ * @rwnx_plat: Pointer to platform data ++ * ++ * Return configuration registers values. ++ */ ++static void *rwnx_term_save_config(struct rwnx_plat *rwnx_plat) ++{ ++ const u32 *reg_list; ++ u32 *reg_value, *res; ++ int i, size = 0; ++ ++ if (rwnx_plat->get_config_reg) { ++ size = rwnx_plat->get_config_reg(rwnx_plat, ®_list); ++ } ++ ++ if (size <= 0) ++ return NULL; ++ ++ res = kmalloc(sizeof(u32) * size, GFP_KERNEL); ++ if (!res) ++ return NULL; ++ ++ reg_value = res; ++ for (i = 0; i < size; i++) { ++ *reg_value++ = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, ++ *reg_list++); ++ } ++ ++ return res; ++} ++ ++#if 0 ++/** ++ * rwmx_platform_restore_config() - Restore hardware config after reload ++ * ++ * @rwnx_plat: Pointer to platform data ++ * @reg_value: Pointer of value to restore ++ * (obtained with rwmx_platform_save_config()) ++ * ++ * Restore configuration registers value. ++ */ ++static void rwnx_term_restore_config(struct rwnx_plat *rwnx_plat, ++ u32 *reg_value) ++{ ++ const u32 *reg_list; ++ int i, size = 0; ++ ++ if (!reg_value || !rwnx_plat->get_config_reg) ++ return; ++ ++ size = rwnx_plat->get_config_reg(rwnx_plat, ®_list); ++ ++ for (i = 0; i < size; i++) { ++ RWNX_REG_WRITE(*reg_value++, rwnx_plat, RWNX_ADDR_SYSTEM, ++ *reg_list++); ++ } ++} ++#endif ++ ++#ifndef CONFIG_RWNX_FHOST ++#if 0 ++static int rwnx_check_fw_compatibility(struct rwnx_hw *rwnx_hw) ++{ ++ struct ipc_shared_env_tag *shared = rwnx_hw->ipc_env->shared; ++ #ifdef CONFIG_RWNX_FULLMAC ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ #endif //CONFIG_RWNX_FULLMAC ++ #ifdef CONFIG_RWNX_OLD_IPC ++ int ipc_shared_version = 10; ++ #else //CONFIG_RWNX_OLD_IPC ++ int ipc_shared_version = 11; ++ #endif //CONFIG_RWNX_OLD_IPC ++ int res = 0; ++ ++ if (shared->comp_info.ipc_shared_version != ipc_shared_version) { ++ wiphy_err(wiphy, "Different versions of IPC shared version between driver and FW (%d != %d)\n ", ++ ipc_shared_version, shared->comp_info.ipc_shared_version); ++ res = -1; ++ } ++ ++ if (shared->comp_info.radarbuf_cnt != IPC_RADARBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for Radar events handling "\ ++ "between driver and FW (%d != %d)\n", IPC_RADARBUF_CNT, ++ shared->comp_info.radarbuf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.unsuprxvecbuf_cnt != IPC_UNSUPRXVECBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for unsupported Rx vectors "\ ++ "handling between driver and FW (%d != %d)\n", IPC_UNSUPRXVECBUF_CNT, ++ shared->comp_info.unsuprxvecbuf_cnt); ++ res = -1; ++ } ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ if (shared->comp_info.rxdesc_cnt != IPC_RXDESC_CNT) { ++ wiphy_err(wiphy, "Different number of shared descriptors available for Data RX handling "\ ++ "between driver and FW (%d != %d)\n", IPC_RXDESC_CNT, ++ shared->comp_info.rxdesc_cnt); ++ res = -1; ++ } ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (shared->comp_info.rxbuf_cnt != IPC_RXBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for Data Rx handling "\ ++ "between driver and FW (%d != %d)\n", IPC_RXBUF_CNT, ++ shared->comp_info.rxbuf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.msge2a_buf_cnt != IPC_MSGE2A_BUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for Emb->App MSGs "\ ++ "sending between driver and FW (%d != %d)\n", IPC_MSGE2A_BUF_CNT, ++ shared->comp_info.msge2a_buf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.dbgbuf_cnt != IPC_DBGBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for debug messages "\ ++ "sending between driver and FW (%d != %d)\n", IPC_DBGBUF_CNT, ++ shared->comp_info.dbgbuf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.bk_txq != NX_TXDESC_CNT0) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of BK TX queue (%d != %d)\n", ++ NX_TXDESC_CNT0, shared->comp_info.bk_txq); ++ res = -1; ++ } ++ ++ if (shared->comp_info.be_txq != NX_TXDESC_CNT1) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of BE TX queue (%d != %d)\n", ++ NX_TXDESC_CNT1, shared->comp_info.be_txq); ++ res = -1; ++ } ++ ++ if (shared->comp_info.vi_txq != NX_TXDESC_CNT2) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of VI TX queue (%d != %d)\n", ++ NX_TXDESC_CNT2, shared->comp_info.vi_txq); ++ res = -1; ++ } ++ ++ if (shared->comp_info.vo_txq != NX_TXDESC_CNT3) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of VO TX queue (%d != %d)\n", ++ NX_TXDESC_CNT3, shared->comp_info.vo_txq); ++ res = -1; ++ } ++ ++ #if NX_TXQ_CNT == 5 ++ if (shared->comp_info.bcn_txq != NX_TXDESC_CNT4) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of BCN TX queue (%d != %d)\n", ++ NX_TXDESC_CNT4, shared->comp_info.bcn_txq); ++ res = -1; ++ } ++ #else ++ if (shared->comp_info.bcn_txq > 0) { ++ wiphy_err(wiphy, "BCMC enabled in firmware but disabled in driver\n"); ++ res = -1; ++ } ++ #endif /* NX_TXQ_CNT == 5 */ ++ ++ if (shared->comp_info.ipc_shared_size != sizeof(ipc_shared_env)) { ++ wiphy_err(wiphy, "Different sizes of IPC shared between driver and FW (%zd != %d)\n", ++ sizeof(ipc_shared_env), shared->comp_info.ipc_shared_size); ++ res = -1; ++ } ++ ++ if (shared->comp_info.msg_api != MSG_API_VER) { ++ wiphy_warn(wiphy, "WARNING: Different supported message API versions between "\ ++ "driver and FW (%d != %d)\n", MSG_API_VER, shared->comp_info.msg_api); ++ } ++ ++ return res; ++} ++#endif ++#endif /* !CONFIG_RWNX_FHOST */ ++ ++ ++void get_userconfig_txpwr_lvl_in_fdrv(txpwr_lvl_conf_t *txpwr_lvl) ++{ ++ txpwr_lvl->enable = userconfig_info.txpwr_lvl.enable; ++ txpwr_lvl->dsss = userconfig_info.txpwr_lvl.dsss; ++ txpwr_lvl->ofdmlowrate_2g4 = userconfig_info.txpwr_lvl.ofdmlowrate_2g4; ++ txpwr_lvl->ofdm64qam_2g4 = userconfig_info.txpwr_lvl.ofdm64qam_2g4; ++ txpwr_lvl->ofdm256qam_2g4 = userconfig_info.txpwr_lvl.ofdm256qam_2g4; ++ txpwr_lvl->ofdm1024qam_2g4 = userconfig_info.txpwr_lvl.ofdm1024qam_2g4; ++ txpwr_lvl->ofdmlowrate_5g = userconfig_info.txpwr_lvl.ofdmlowrate_5g; ++ txpwr_lvl->ofdm64qam_5g = userconfig_info.txpwr_lvl.ofdm64qam_5g; ++ txpwr_lvl->ofdm256qam_5g = userconfig_info.txpwr_lvl.ofdm256qam_5g; ++ txpwr_lvl->ofdm1024qam_5g = userconfig_info.txpwr_lvl.ofdm1024qam_5g; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl->enable); ++ AICWFDBG(LOGINFO, "%s:dsss:%d\r\n", __func__, txpwr_lvl->dsss); ++ AICWFDBG(LOGINFO, "%s:ofdmlowrate_2g4:%d\r\n", __func__, txpwr_lvl->ofdmlowrate_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdm64qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm64qam_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdm256qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm256qam_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdm1024qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm1024qam_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdmlowrate_5g:%d\r\n", __func__, txpwr_lvl->ofdmlowrate_5g); ++ AICWFDBG(LOGINFO, "%s:ofdm64qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm64qam_5g); ++ AICWFDBG(LOGINFO, "%s:ofdm256qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm256qam_5g); ++ AICWFDBG(LOGINFO, "%s:ofdm1024qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm1024qam_5g); ++} ++ ++void get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_conf_v2_t *txpwr_lvl_v2) ++{ ++ *txpwr_lvl_v2 = userconfig_info.txpwr_lvl_v2; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v2->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[11]); ++} ++ ++void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3) ++{ ++ *txpwr_lvl_v3 = userconfig_info.txpwr_lvl_v3; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v3->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_1m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_2m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_5m5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_11m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[11]); ++} ++ ++void get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_conf_v4_t *txpwr_lvl_v4) ++{ ++ *txpwr_lvl_v4 = userconfig_info.txpwr_lvl_v4; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v4->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[11]); ++} ++ ++void get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj) ++{ ++ *txpwr_lvl_adj = userconfig_info.txpwr_lvl_adj; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_adj->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_1_4:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_5_9:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_10_13:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[2]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_42:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_58:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_106:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_122:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_138:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_155:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[5]); ++} ++ ++#ifdef CONFIG_POWER_LIMIT ++#define GetLineFromBuffer(buffer) strsep(&buffer, "\n") ++ ++int isAllSpaceOrTab(uint8_t *data, uint8_t size) ++{ ++ uint8_t cnt = 0, NumOfSpaceAndTab = 0; ++ while (size > cnt) { ++ if (data[cnt] == ' ' || data[cnt] == '\t' || data[cnt] == '\0') ++ ++NumOfSpaceAndTab; ++ ++cnt; ++ } ++ return size == NumOfSpaceAndTab; ++} ++ ++int IsCommentString(char *szStr) ++{ ++ if (*szStr == '#' && *(szStr + 1) == ' ') ++ return 1; ++ else ++ return 0; ++} ++ ++int ParseQualifiedString(char *In, u32 *Start, char *Out, char LeftQualifier, char RightQualifier) ++{ ++ u32 i = 0, j = 0; ++ char c = In[(*Start)++]; ++ if (c != LeftQualifier) ++ return 0; ++ i = (*Start); ++ c = In[(*Start)++]; ++ while (c != RightQualifier && c != '\0') ++ c = In[(*Start)++]; ++ if (c == '\0') ++ return 0; ++ j = (*Start) - 2; ++ strncpy((char *)Out, (const char *)(In + i), j - i + 1); ++ return 1; ++} ++ ++int GetU1ByteIntegerFromStringInDecimal(char *Str, u8 *pInt) ++{ ++ u16 i = 0; ++ *pInt = 0; ++ while (Str[i] != '\0') { ++ if (Str[i] >= '0' && Str[i] <= '9') { ++ *pInt *= 10; ++ *pInt += (Str[i] - '0'); ++ } else ++ return 0; ++ ++i; ++ } ++ return 1; ++} ++int GetS1ByteIntegerFromStringInDecimal(char *str, s8 *val) ++{ ++ u8 negative = 0; ++ u16 i = 0; ++ *val = 0; ++ while (str[i] != '\0') { ++ if (i == 0 && (str[i] == '+' || str[i] == '-')) { ++ if (str[i] == '-') ++ negative = 1; ++ } else if (str[i] >= '0' && str[i] <= '9') { ++ *val *= 10; ++ *val += (str[i] - '0'); ++ } else ++ return 0; ++ ++i; ++ } ++ if (negative) ++ *val = -*val; ++ return 1; ++} ++ ++int8_t rwnx_plat_powerlimit_save(u8_l band, char *channel, u8_l bw, char *limit, char *name) ++{ ++ u8 channel_num, powerLimit_val, reg_idx; ++ ++ if (GetU1ByteIntegerFromStringInDecimal((char *)channel, &channel_num) == 0 ++ || GetS1ByteIntegerFromStringInDecimal((char *)limit, &powerLimit_val) == 0) { ++ AICWFDBG(LOGERROR, "Illegal index of power limit table [ch %s][val %s]\n", channel, limit); ++ return -1; ++ } ++ ++ reg_idx = get_region_index(name); ++ ++ if (band == PHY_BAND_2G4) { ++ uint8_t cur_idx = powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_2g4[bw]; ++ AICWFDBG(LOGINFO, "reg_idx=%d, band=%d, bw=%d, cur_idx=%d, ch=%s, pwr=%s\n", ++ reg_idx, band, bw, cur_idx, channel, limit); ++ if (cur_idx < MAC_DOMAINCHANNEL_24G_MAX) { ++ powerlimit_info.txpwr_lmt[reg_idx].ch_num_2g4[bw][cur_idx] = channel_num; ++ powerlimit_info.txpwr_lmt[reg_idx].max_pwr_2g4[bw][cur_idx] = powerLimit_val; ++ powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_2g4[bw]++; ++ } else { ++ AICWFDBG(LOGERROR, "band %d chan_cnt reached %d\n", band, MAC_DOMAINCHANNEL_24G_MAX); ++ AICWFDBG(LOGERROR, "channel=%s(%d) powerLimit=%s(%d)\n", channel, channel_num, limit, powerLimit_val); ++ } ++ } else if (band == PHY_BAND_5G) { ++ uint8_t cur_idx = powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_5g[bw]; ++ AICWFDBG(LOGINFO, "reg_idx=%d, band=%d, bw=%d, cur_idx=%d, ch=%s, pwr=%s\n", ++ reg_idx, band, bw, cur_idx, channel, limit); ++ if (cur_idx < MAC_DOMAINCHANNEL_5G_MAX) { ++ powerlimit_info.txpwr_lmt[reg_idx].ch_num_5g[bw][cur_idx] = channel_num; ++ powerlimit_info.txpwr_lmt[reg_idx].max_pwr_5g[bw][cur_idx] = powerLimit_val; ++ powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_5g[bw]++; ++ } else { ++ AICWFDBG(LOGERROR, "band %d chan_cnt reached %d\n", band, MAC_DOMAINCHANNEL_5G_MAX); ++ AICWFDBG(LOGERROR, "channel=%s(%d) powerLimit=%s(%d)\n", channel, channel_num, limit, powerLimit_val); ++ } ++ } ++ ++ return 0; ++} ++ ++ ++void rwnx_plat_powerlimit_parsing(char *buffer, int size, char *cc) ++{ ++#define LD_STAGE_EXC_MAPPING 0 ++#define LD_STAGE_TAB_DEFINE 1 ++#define LD_STAGE_TAB_START 2 ++#define LD_STAGE_COLUMN_DEFINE 3 ++#define LD_STAGE_CH_ROW 4 ++ ++ uint8_t loadingStage = LD_STAGE_EXC_MAPPING; ++ uint32_t i = 0, forCnt = 0; ++ uint32_t i_cc; ++ char *szLine, *ptmp; ++ char band[10], colNumBuf[10], bandwidth[10]; ++ uint8_t colNum = 0, band_cc = 0, bw_cc = 0; ++ char **reg_name = NULL; ++ // clear powerlimit info at first ++ memset((void *)&powerlimit_info, 0, sizeof(powerlimit_info_t)); ++ ptmp = buffer; ++ for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { ++ if (isAllSpaceOrTab(szLine, sizeof(*szLine))) ++ continue; ++ if (IsCommentString(szLine)) ++ continue; ++ ++ if (loadingStage == LD_STAGE_EXC_MAPPING) { ++ if (szLine[0] == '#' || szLine[1] == '#') { ++ loadingStage = LD_STAGE_TAB_DEFINE; ++ } else { ++ continue; ++ } ++ } ++ ++ if (loadingStage == LD_STAGE_TAB_DEFINE) { ++ /* read "## 2.4G" */ ++ if (szLine[0] != '#' || szLine[1] != '#') ++ continue; ++ ++ /* skip the space */ ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ szLine[--i] = ' '; /* return the space in front of the regulation info */ ++ ++ /* Parse the label of the table */ ++ memset((void *)band, 0, 10); ++ memset((void *)bandwidth, 0, 10); ++ memset((void *)colNumBuf, 0, 10); ++ ++ if (!ParseQualifiedString(szLine, &i, band, ' ', ',')) { ++ AICWFDBG(LOGERROR, "Fail to parse band!\n"); ++ goto exit; ++ } ++ if (strncmp(band, "2.4G", 4) == 0) { ++ band_cc = PHY_BAND_2G4; ++ } else if (strncmp(band, "5G", 2) == 0) { ++ band_cc = PHY_BAND_5G; ++ } ++ ++ if (!ParseQualifiedString(szLine, &i, bandwidth, ' ', ',')) { ++ AICWFDBG(LOGERROR, "Fail to parse bandwidth!\n"); ++ goto exit; ++ } ++ if (strncmp(bandwidth, "20M", 3) == 0) ++ bw_cc = PHY_CHNL_BW_20; ++ else if (strncmp(bandwidth, "40M", 3) == 0) ++ bw_cc = PHY_CHNL_BW_40; ++ else if (strncmp(bandwidth, "80M", 3) == 0) ++ bw_cc = PHY_CHNL_BW_80; ++ ++ if (!ParseQualifiedString(szLine, &i, colNumBuf, '#', '#')) { ++ AICWFDBG(LOGERROR, "Fail to parse column number!\n"); ++ goto exit; ++ } ++ if (!GetU1ByteIntegerFromStringInDecimal(colNumBuf, &colNum)) { ++ AICWFDBG(LOGERROR, "Column number \"%s\" is not unsigned decimal\n", colNumBuf); ++ goto exit; ++ } ++ if (colNum == 0) { ++ AICWFDBG(LOGERROR, "Column number is 0\n"); ++ goto exit; ++ } ++ ++ AICWFDBG(LOGINFO, "band=%s, bandwidth=%s, colnum=%d\n", band, bandwidth, colNum); ++ loadingStage = LD_STAGE_TAB_START; ++ } else if (loadingStage == LD_STAGE_TAB_START) { ++ /* read "## START" */ ++ if (szLine[0] != '#' || szLine[1] != '#') ++ continue; ++ ++ /* skip the space */ ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ if (strncmp((u8 *)(szLine + i), "START", 5)) { ++ AICWFDBG(LOGERROR, "Missing \"## START\" label\n"); ++ goto exit; ++ } ++ ++ loadingStage = LD_STAGE_COLUMN_DEFINE; ++ } else if (loadingStage == LD_STAGE_COLUMN_DEFINE) { ++ /* read "## FCC ETSI" */ ++ if (szLine[0] != '#' || szLine[1] != '#') ++ continue; ++ ++ /* skip the space */ ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ reg_name = (char **)kmalloc(sizeof(char *) * colNum, GFP_KERNEL); ++ if (!reg_name) { ++ AICWFDBG(LOGERROR, "reg_name alloc fail\n"); ++ goto exit; ++ } ++ ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ /* skip the space */ ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ i++; ++ i_cc = i; ++ ++ while (szLine[i] != ' ' && szLine[i] != '\t' && szLine[i] != '\0') ++ i++; ++ ++ reg_name[forCnt] = (char *)kmalloc(i - i_cc + 1, GFP_KERNEL); ++ if (!reg_name[forCnt]) { ++ AICWFDBG(LOGERROR, "reg_name element alloc fail\n"); ++ goto exit; ++ } ++ ++ strncpy(reg_name[forCnt], szLine + i_cc, i - i_cc); ++ reg_name[forCnt][i - i_cc] = '\0'; ++ AICWFDBG(LOGINFO, "reg_name: %s\n", reg_name[forCnt]); ++ ++ } ++ ++ loadingStage = LD_STAGE_CH_ROW; ++ } else if (loadingStage == LD_STAGE_CH_ROW) { ++ char channel[10] = {0}, powerLimit[10] = {0}; ++ u8 cnt = 0; ++ ++ /* the table ends */ ++ if (szLine[0] == '#' && szLine[1] == '#') { ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ if (strncmp((u8 *)(szLine + i), "END", 3) == 0) { ++ loadingStage = LD_STAGE_TAB_DEFINE; ++ if (reg_name) { ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ if (reg_name[forCnt]) { ++ kfree(reg_name[forCnt]); ++ reg_name[forCnt] = NULL; ++ } ++ } ++ kfree(reg_name); ++ reg_name = NULL; ++ } ++ colNum = 0; ++ continue; ++ } else { ++ AICWFDBG(LOGERROR, "Missing \"## END\" label\n"); ++ goto exit; ++ } ++ } ++ ++ if ((szLine[0] != 'c' && szLine[0] != 'C') || ++ (szLine[1] != 'h' && szLine[1] != 'H')) { ++ AICWFDBG(LOGERROR, "Wrong channel prefix: '%c','%c'(%d,%d)\n", szLine[0], szLine[1], szLine[0], szLine[1]); ++ continue; ++ } ++ i = 2;/* move to the location behind 'h' */ ++ ++ /* load the channel number */ ++ cnt = 0; ++ while (szLine[i] >= '0' && szLine[i] <= '9') { ++ channel[cnt] = szLine[i]; ++ ++cnt; ++ ++i; ++ } ++ ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ /* skip the space between channel number and the power limit value */ ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ /* load the power limit value */ ++ memset((void *)powerLimit, 0, 10); ++ ++ if (szLine[i] == 'N' && szLine[i + 1] == 'A') { ++ /* ++ * means channel not available ++ */ ++ sprintf(powerLimit, "%d", POWER_LIMIT_INVALID_VAL); ++ i += 2; ++ } else if ((szLine[i] >= '0' && szLine[i] <= '9') ++ || szLine[i] == '+' || szLine[i] == '-') { ++ /* case of dBm value */ ++ cnt = 0; ++ while ((szLine[i] >= '0' && szLine[i] <= '9') ++ || szLine[i] == '+' || szLine[i] == '-' ++ ) { ++ powerLimit[cnt] = szLine[i]; ++ ++cnt; ++ ++i; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "Wrong limit expression \"%c%c\"(%d, %d)\n", ++ szLine[i], szLine[i + 1], szLine[i], szLine[i + 1]); ++ goto exit; ++ } ++ ++ if (rwnx_plat_powerlimit_save(band_cc, channel, bw_cc, powerLimit, reg_name[forCnt]) < 0) ++ goto exit; ++ } ++ } ++ } ++ ++ powerlimit_info.flags |= POWER_LIMIT_CC_MATCHED_BIT; ++exit: ++ if (reg_name) { ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ if (reg_name[forCnt]) { ++ kfree(reg_name[forCnt]); ++ reg_name[forCnt] = NULL; ++ } ++ } ++ kfree(reg_name); ++ reg_name = NULL; ++ } ++ ++ return; ++} ++ ++ ++/// 5G lower bound freq ++#define PHY_FREQ_5G 5000 ++ ++uint16_t phy_channel_to_freq(uint8_t band, int channel) ++{ ++ if ((band == PHY_BAND_2G4) && (channel >= 1) && (channel <= 14)) { ++ if (channel == 14) ++ return 2484; ++ else ++ return 2407 + channel * 5; ++ } else if ((band == PHY_BAND_5G) && (channel >= 1) && (channel <= 165)) { ++ return PHY_FREQ_5G + channel * 5; ++ } ++ return 0; ++} ++ ++int8_t get_powerlimit_by_freq(uint8_t band, uint16_t freq, uint8_t r_idx) ++{ ++ int8_t ret = POWER_LIMIT_INVALID_VAL; ++ uint8_t idx; ++ if (!(powerlimit_info.flags & POWER_LIMIT_CC_MATCHED_BIT)) { ++ AICWFDBG(LOGERROR, "powerlimit flag not set\n"); ++ return ret; ++ } ++ ++ if (band == PHY_BAND_2G4) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_2g4[0]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ int ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_2g4[0][idx]; ++ uint16_t freq_tmp = phy_channel_to_freq(PHY_BAND_2G4, ch_num); ++ if (freq == freq_tmp) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_2g4[0][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d(freq=%d), pwr=%d\n", idx, ch_num, freq, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "powerlimit search failed: band=%d freq=%d\n", band, freq); ++ } else if (band == PHY_BAND_5G) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_5g[0]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ int ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_5g[0][idx]; ++ uint16_t freq_tmp = phy_channel_to_freq(PHY_BAND_5G, ch_num); ++ if (freq == freq_tmp) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_5g[0][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d(freq=%d), pwr=%d\n", idx, ch_num, freq, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "powerlimit search failed: band=%d freq=%d\n", band, freq); ++ } ++ return ret; ++} ++ ++int8_t get_powerlimit_by_chnum(uint8_t chnum, uint8_t r_idx, uint8_t bw) ++{ ++ int8_t ret = POWER_LIMIT_INVALID_VAL; ++ uint8_t idx; ++ if (!(powerlimit_info.flags & POWER_LIMIT_CC_MATCHED_BIT)) { ++ AICWFDBG(LOGERROR, "powerlimit flag not set\n"); ++ return ret; ++ } ++ ++ if (chnum <= 14) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_2g4[bw]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ uint8_t ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_2g4[bw][idx]; ++ if (chnum == ch_num) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_2g4[bw][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d, pwr=%d\n", idx, ch_num, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "%s powerlimit search failed: chnum=%d, please confirm the center frequency\n", ++ __func__, chnum); ++ } else if (chnum <= 165) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_5g[bw]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ uint8_t ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_5g[bw][idx]; ++ if (chnum == ch_num) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_5g[bw][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d, pwr=%d\n", idx, ch_num, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "%s powerlimit search failed: chnum=%d, please confirm the center frequency\n", ++ __func__, chnum); ++ } ++ ++ return ret; ++} ++#endif ++ ++/** ++ * rwnx_plat_userconfig_load ---Load aic_userconfig.txt ++ *@filename name of config ++*/ ++static int rwnx_plat_userconfig_load(struct rwnx_hw *rwnx_hw) { ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ ++ rwnx_plat_userconfig_upload_android(rwnx_hw, aic_fw_path, FW_USERCONFIG_NAME); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC){ ++ rwnx_plat_userconfig_load_8800dc(rwnx_hw); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ rwnx_plat_userconfig_load_8800dw(rwnx_hw); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ rwnx_plat_userconfig_load_8800d80(rwnx_hw); ++#ifdef CONFIG_POWER_LIMIT ++ rwnx_plat_powerlimit_load_8800d80(rwnx_hw); ++#endif ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ rwnx_plat_userconfig_load_8800d80x2(rwnx_hw); ++#ifdef CONFIG_POWER_LIMIT ++ rwnx_plat_powerlimit_load_8800d80x2(rwnx_hw); ++#endif ++ } ++ return 0; ++} ++ ++void get_userconfig_txpwr_loss(txpwr_loss_conf_t *txpwr_loss) ++{ ++ txpwr_loss->loss_enable_2g4 = userconfig_info.txpwr_loss.loss_enable_2g4; ++ txpwr_loss->loss_value_2g4 = userconfig_info.txpwr_loss.loss_value_2g4; ++ txpwr_loss->loss_enable_5g = userconfig_info.txpwr_loss.loss_enable_5g; ++ txpwr_loss->loss_value_5g = userconfig_info.txpwr_loss.loss_value_5g; ++ ++ AICWFDBG(LOGDEBUG, "%s:loss_enable_2g4: %d, val_2g4: %d, loss_enable_5g: %d, val_5g: %d\r\n", __func__, ++ txpwr_loss->loss_enable_2g4, txpwr_loss->loss_value_2g4, ++ txpwr_loss->loss_enable_5g, txpwr_loss->loss_value_5g); ++ ++} ++ ++/** ++ * rwnx_platform_on() - Start the platform ++ * ++ * @rwnx_hw: Main driver data ++ * @config: Config to restore (NULL if nothing to restore) ++ * ++ * It starts the platform : ++ * - load fw and ucodes ++ * - initialize IPC ++ * - boot the fw ++ * - enable link communication/IRQ ++ * ++ * Called by 802.11 part ++ */ ++int rwnx_platform_on(struct rwnx_hw *rwnx_hw, void *config) ++{ ++ int ret; ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ (void)ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (rwnx_plat->enabled) ++ return 0; ++ ++ #ifndef CONFIG_ROM_PATCH_EN ++ #ifdef CONFIG_DOWNLOAD_FW ++ ret = rwnx_plat_fmac_load(rwnx_hw, (char*)config); ++ if (ret) ++ return ret; ++ #endif /* !CONFIG_ROM_PATCH_EN */ ++ #endif ++ ++#if 0 ++ ret = rwnx_plat_patch_load(rwnx_hw); ++ if (ret) { ++ return ret; ++ } ++#endif ++ ++ ++ rwnx_plat_userconfig_load(rwnx_hw); ++ ++ //rwnx_plat->enabled = true; ++ ++ return 0; ++} ++ ++/** ++ * rwnx_platform_off() - Stop the platform ++ * ++ * @rwnx_hw: Main driver data ++ * @config: Updated with pointer to config, to be able to restore it with ++ * rwnx_platform_on(). It's up to the caller to free the config. Set to NULL ++ * if configuration is not needed. ++ * ++ * Called by 802.11 part ++ */ ++void rwnx_platform_off(struct rwnx_hw *rwnx_hw, void **config) ++{ ++#if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) ++ tasklet_kill(&rwnx_hw->task); ++ rwnx_hw->plat->enabled = false; ++ return ; ++#endif ++ ++ if (!rwnx_hw->plat->enabled) { ++ if (config) ++ *config = NULL; ++ return; ++ } ++ ++ if (config) ++ *config = rwnx_term_save_config(rwnx_hw->plat); ++ ++ rwnx_hw->plat->disable(rwnx_hw); ++ ++ tasklet_kill(&rwnx_hw->task); ++ rwnx_platform_reset(rwnx_hw->plat); ++ ++ rwnx_hw->plat->enabled = false; ++} ++ ++/** ++ * rwnx_platform_init() - Initialize the platform ++ * ++ * @rwnx_plat: platform data (already updated by platform driver) ++ * @platform_data: Pointer to store the main driver data pointer (aka rwnx_hw) ++ * That will be set as driver data for the platform driver ++ * Return: 0 on success, < 0 otherwise ++ * ++ * Called by the platform driver after it has been probed ++ */ ++int rwnx_platform_init(struct rwnx_plat *rwnx_plat, void **platform_data) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_plat->enabled = false; ++ g_rwnx_plat = rwnx_plat; ++ ++#if defined CONFIG_RWNX_FULLMAC ++ return rwnx_cfg80211_init(rwnx_plat, platform_data); ++#elif defined CONFIG_RWNX_FHOST ++ return rwnx_fhost_init(rwnx_plat, platform_data); ++#endif ++} ++ ++/** ++ * rwnx_platform_deinit() - Deinitialize the platform ++ * ++ * @rwnx_hw: main driver data ++ * ++ * Called by the platform driver after it is removed ++ */ ++void rwnx_platform_deinit(struct rwnx_hw *rwnx_hw) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#if defined CONFIG_RWNX_FULLMAC ++ rwnx_cfg80211_deinit(rwnx_hw); ++#elif defined CONFIG_RWNX_FHOST ++ rwnx_fhost_deinit(rwnx_hw); ++#endif ++} ++ ++/** ++ * rwnx_platform_register_drv() - Register all possible platform drivers ++ */ ++int rwnx_platform_register_drv(void) ++{ ++ return rwnx_pci_register_drv(); ++} ++ ++ ++/** ++ * rwnx_platform_unregister_drv() - Unegister all platform drivers ++ */ ++void rwnx_platform_unregister_drv(void) ++{ ++ return rwnx_pci_unregister_drv(); ++} ++ ++struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ return rwnx_plat->sdiodev->dev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ return rwnx_plat->usbdev->dev; ++#endif ++ return &(rwnx_plat->pci_dev->dev); ++} ++ ++ ++#ifndef CONFIG_RWNX_SDM ++MODULE_FIRMWARE(RWNX_AGC_FW_NAME); ++MODULE_FIRMWARE(RWNX_FCU_FW_NAME); ++MODULE_FIRMWARE(RWNX_LDPC_RAM_NAME); ++#endif ++MODULE_FIRMWARE(RWNX_MAC_FW_NAME); ++#ifndef CONFIG_RWNX_TL4 ++MODULE_FIRMWARE(RWNX_MAC_FW_NAME2); ++#endif ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h +new file mode 100644 +index 000000000000..1ce300dbfed5 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h +@@ -0,0 +1,159 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_platorm.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_PLATFORM_H_ ++#define _RWNX_PLATFORM_H_ ++ ++#include ++#include "lmac_msg.h" ++ ++#define RWNX_CONFIG_FW_NAME "rwnx_settings.ini" ++#define RWNX_PHY_CONFIG_TRD_NAME "rwnx_trident.ini" ++#define RWNX_PHY_CONFIG_KARST_NAME "rwnx_karst.ini" ++#define RWNX_AGC_FW_NAME "agcram.bin" ++#define RWNX_LDPC_RAM_NAME "ldpcram.bin" ++#ifdef CONFIG_RWNX_FULLMAC ++#define RWNX_MAC_FW_BASE_NAME "fmacfw" ++#elif defined CONFIG_RWNX_FHOST ++#define RWNX_MAC_FW_BASE_NAME "fhostfw" ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_TL4 ++#define RWNX_MAC_FW_NAME RWNX_MAC_FW_BASE_NAME".hex" ++#else ++#define RWNX_MAC_FW_NAME RWNX_MAC_FW_BASE_NAME".ihex" ++#define RWNX_MAC_FW_NAME2 RWNX_MAC_FW_BASE_NAME".bin" ++#endif ++ ++#define RWNX_FCU_FW_NAME "fcuram.bin" ++#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++#define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_lite_8800dc.bin" ++#endif ++ ++/** ++ * Type of memory to access (cf rwnx_plat.get_address) ++ * ++ * @RWNX_ADDR_CPU To access memory of the embedded CPU ++ * @RWNX_ADDR_SYSTEM To access memory/registers of one subsystem of the ++ * embedded system ++ * ++ */ ++enum rwnx_platform_addr { ++ RWNX_ADDR_CPU, ++ RWNX_ADDR_SYSTEM, ++ RWNX_ADDR_MAX, ++}; ++ ++#define POWER_LEVEL_INVALID_VAL (127) ++ ++typedef enum { ++ REGIONS_SRRC, ++ REGIONS_FCC, ++ REGIONS_ETSI, ++ REGIONS_JP, ++ REGIONS_DEFAULT, ++} Regions_code; ++ ++struct rwnx_hw; ++ ++/** ++ * struct rwnx_plat - Operation pointers for RWNX PCI platform ++ * ++ * @pci_dev: pointer to pci dev ++ * @enabled: Set if embedded platform has been enabled (i.e. fw loaded and ++ * ipc started) ++ * @enable: Configure communication with the fw (i.e. configure the transfers ++ * enable and register interrupt) ++ * @disable: Stop communication with the fw ++ * @deinit: Free all ressources allocated for the embedded platform ++ * @get_address: Return the virtual address to access the requested address on ++ * the platform. ++ * @ack_irq: Acknowledge the irq at link level. ++ * @get_config_reg: Return the list (size + pointer) of registers to restore in ++ * order to reload the platform while keeping the current configuration. ++ * ++ * @priv Private data for the link driver ++ */ ++struct rwnx_plat { ++ struct pci_dev *pci_dev; ++ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ bool enabled; ++ ++ int (*enable)(struct rwnx_hw *rwnx_hw); ++ int (*disable)(struct rwnx_hw *rwnx_hw); ++ void (*deinit)(struct rwnx_plat *rwnx_plat); ++ u8* (*get_address)(struct rwnx_plat *rwnx_plat, int addr_name, ++ unsigned int offset); ++ void (*ack_irq)(struct rwnx_plat *rwnx_plat); ++ int (*get_config_reg)(struct rwnx_plat *rwnx_plat, const u32 **list); ++ ++ u8 priv[0] __aligned(sizeof(void *)); ++}; ++ ++#define RWNX_ADDR(plat, base, offset) \ ++ plat->get_address(plat, base, offset) ++ ++#define RWNX_REG_READ(plat, base, offset) \ ++ readl(plat->get_address(plat, base, offset)) ++ ++#define RWNX_REG_WRITE(val, plat, base, offset) \ ++ writel(val, plat->get_address(plat, base, offset)) ++ ++extern struct rwnx_plat *g_rwnx_plat; ++ ++int rwnx_platform_init(struct rwnx_plat *rwnx_plat, void **platform_data); ++void rwnx_platform_deinit(struct rwnx_hw *rwnx_hw); ++ ++int rwnx_platform_on(struct rwnx_hw *rwnx_hw, void *config); ++void rwnx_platform_off(struct rwnx_hw *rwnx_hw, void **config); ++ ++int rwnx_platform_register_drv(void); ++void rwnx_platform_unregister_drv(void); ++ ++void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx); ++void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst); ++void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap); ++s8_l get_txpwr_max(s8_l power); ++void set_txpwr_loss_ofst(s8_l value); ++ ++void get_userconfig_txpwr_lvl_in_fdrv(txpwr_lvl_conf_t *txpwr_lvl); ++void get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_conf_v2_t *txpwr_lvl_v2); ++void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3); ++void get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_conf_v4_t *txpwr_lvl_v4); ++void get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj); ++uint8_t get_ccode_region(char * ccode); ++u8 get_region_index(char * name); ++ ++#ifdef CONFIG_POWER_LIMIT ++int8_t rwnx_plat_powerlimit_save(u8_l band, char *channel, u8_l bw, char *limit, char *name); ++void rwnx_plat_powerlimit_parsing(char *buffer, int size, char *cc); ++int8_t get_powerlimit_by_freq(uint8_t band, uint16_t freq, uint8_t r_idx); ++int8_t get_powerlimit_by_chnum(uint8_t chnum, uint8_t r_idx, uint8_t bw); ++#endif ++ ++void get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst_conf_t *txpwr_ofst); ++void get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x_conf_t *txpwr_ofst2x); ++void get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2); ++void get_userconfig_txpwr_loss(txpwr_loss_conf_t *txpwr_loss); ++extern struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat); ++ ++static inline unsigned int rwnx_platform_get_irq(struct rwnx_plat *rwnx_plat) ++{ ++ return rwnx_plat->pci_dev->irq; ++} ++ ++#endif /* _RWNX_PLATFORM_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h +new file mode 100644 +index 000000000000..5442f588212f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h +@@ -0,0 +1,133 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_prof.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_PROF_H_ ++#define _RWNX_PROF_H_ ++ ++#include "reg_access.h" ++#include "rwnx_platform.h" ++ ++static inline void rwnx_prof_set(struct rwnx_hw *rwnx_hw, int val) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_SET_PROFILING_ADDR); ++} ++ ++static inline void rwnx_prof_clear(struct rwnx_hw *rwnx_hw, int val) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_CLEAR_PROFILING_ADDR); ++} ++ ++#if 0 ++/* Defines for SW Profiling registers values */ ++enum { ++ TX_IPC_IRQ, ++ TX_IPC_EVT, ++ TX_PREP_EVT, ++ TX_DMA_IRQ, ++ TX_MAC_IRQ, ++ TX_PAYL_HDL, ++ TX_CFM_EVT, ++ TX_IPC_CFM, ++ RX_MAC_IRQ, // 8 ++ RX_TRIGGER_EVT, ++ RX_DMA_IRQ, ++ RX_DMA_EVT, ++ RX_IPC_IND, ++ RX_MPDU_XFER, ++ DBG_PROF_MAX ++}; ++#endif ++ ++enum { ++ SW_PROF_HOSTBUF_IDX = 12, ++ /****** IPC IRQs related signals ******/ ++ /* E2A direction */ ++ SW_PROF_IRQ_E2A_RXDESC = 16, // to make sure we let 16 bits available for LMAC FW ++ SW_PROF_IRQ_E2A_TXCFM, ++ SW_PROF_IRQ_E2A_DBG, ++ SW_PROF_IRQ_E2A_MSG, ++ SW_PROF_IPC_MSGPUSH, ++ SW_PROF_MSGALLOC, ++ SW_PROF_MSGIND, ++ SW_PROF_DBGIND, ++ ++ /* A2E direction */ ++ SW_PROF_IRQ_A2E_TXCFM_BACK, ++ ++ /****** Driver functions related signals ******/ ++ SW_PROF_WAIT_QUEUE_STOP, ++ SW_PROF_WAIT_QUEUE_WAKEUP, ++ SW_PROF_RWNXDATAIND, ++ SW_PROF_RWNX_IPC_IRQ_HDLR, ++ SW_PROF_RWNX_IPC_THR_IRQ_HDLR, ++ SW_PROF_IEEE80211RX, ++ SW_PROF_RWNX_PATTERN, ++ SW_PROF_MAX ++}; ++ ++// [LT]For debug purpose only ++#if (0) ++#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (21) ++#define SW_PROF_CHAN_CTXT_CFM_BIT (22) ++#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (23) ++#define SW_PROF_CHAN_CTXT_PUSH_BIT (24) ++#define SW_PROF_CHAN_CTXT_QUEUE_BIT (25) ++#define SW_PROF_CHAN_CTXT_TX_BIT (26) ++#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (27) ++#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (28) ++#define SW_PROF_CHAN_CTXT_SWTCH_BIT (29) ++ ++// TO DO: update this ++ ++#define REG_SW_SET_PROFILING_CHAN(env, bit) \ ++ rwnx_prof_set((struct rwnx_hw *)env, BIT(bit)) ++ ++#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) \ ++ rwnx_prof_clear((struct rwnx_hw *)env, BIT(bit)) ++ ++#else ++#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (0) ++#define SW_PROF_CHAN_CTXT_CFM_BIT (0) ++#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (0) ++#define SW_PROF_CHAN_CTXT_PUSH_BIT (0) ++#define SW_PROF_CHAN_CTXT_QUEUE_BIT (0) ++#define SW_PROF_CHAN_CTXT_TX_BIT (0) ++#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (0) ++#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (0) ++#define SW_PROF_CHAN_CTXT_SWTCH_BIT (0) ++ ++#define REG_SW_SET_PROFILING_CHAN(env, bit) do {} while (0) ++#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) do {} while (0) ++#endif ++ ++#ifdef CONFIG_RWNX_SW_PROFILING ++/* Macros for SW PRofiling registers access */ ++#define REG_SW_SET_PROFILING(env, bit) \ ++ rwnx_prof_set((struct rwnx_hw *)env, BIT(bit)) ++ ++#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) \ ++ rwnx_prof_set((struct rwnx_hw *)env, val << (SW_PROF_HOSTBUF_IDX)) ++ ++#define REG_SW_CLEAR_PROFILING(env, bit) \ ++ rwnx_prof_clear((struct rwnx_hw *)env, BIT(bit)) ++ ++#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) \ ++ rwnx_prof_clear((struct rwnx_hw *)env, 0x0F << (SW_PROF_HOSTBUF_IDX)) ++ ++#else ++#define REG_SW_SET_PROFILING(env, value) do {} while (0) ++#define REG_SW_CLEAR_PROFILING(env, value) do {} while (0) ++#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) do {} while (0) ++#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) do {} while (0) ++#endif ++ ++#endif /* _RWNX_PROF_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c +new file mode 100644 +index 000000000000..5017fd36f3bf +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c +@@ -0,0 +1,1657 @@ ++/** ++****************************************************************************** ++ * ++ * @file rwnx_radar.c ++ * ++ * @brief Functions to handle radar detection ++ * Radar detection is copied (and adapted) from ath driver source code. ++ * ++ * Copyright (c) 2012 Neratec Solutions AG ++ * Copyright (C) RivieraWaves 2015-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++#include ++ ++#include "rwnx_radar.h" ++#include "rwnx_defs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++ ++/* ++ * tolerated deviation of radar time stamp in usecs on both sides ++ * TODO: this might need to be HW-dependent ++ */ ++#define PRI_TOLERANCE 16 ++ ++/** ++ * struct radar_types - contains array of patterns defined for one DFS domain ++ * @domain: DFS regulatory domain ++ * @num_radar_types: number of radar types to follow ++ * @radar_types: radar types array ++ */ ++struct radar_types { ++ enum nl80211_dfs_regions region; ++ u32 num_radar_types; ++ const struct radar_detector_specs *spec_riu; ++ const struct radar_detector_specs *spec_fcu; ++}; ++ ++/** ++ * Type of radar waveform: ++ * RADAR_WAVEFORM_SHORT : waveform defined by ++ * - pulse width ++ * - pulse interval in a burst (pri) ++ * - number of pulses in a burst (ppb) ++ * ++ * RADAR_WAVEFORM_WEATHER : ++ * same than SHORT except that ppb is dependent of pri ++ * ++ * RADAR_WAVEFORM_INTERLEAVED : ++ * same than SHORT except there are several value of pri (interleaved) ++ * ++ * RADAR_WAVEFORM_LONG : ++ * ++ */ ++enum radar_waveform_type { ++ RADAR_WAVEFORM_SHORT, ++ RADAR_WAVEFORM_WEATHER, ++ RADAR_WAVEFORM_INTERLEAVED, ++ RADAR_WAVEFORM_LONG ++}; ++ ++/** ++ * struct radar_detector_specs - detector specs for a radar pattern type ++ * @type_id: pattern type, as defined by regulatory ++ * @width_min: minimum radar pulse width in [us] ++ * @width_max: maximum radar pulse width in [us] ++ * @pri_min: minimum pulse repetition interval in [us] (including tolerance) ++ * @pri_max: minimum pri in [us] (including tolerance) ++ * @num_pri: maximum number of different pri for this type ++ * @ppb: pulses per bursts for this type ++ * @ppb_thresh: number of pulses required to trigger detection ++ * @max_pri_tolerance: pulse time stamp tolerance on both sides [us] ++ * @type: Type of radar waveform ++ */ ++struct radar_detector_specs { ++ u8 type_id; ++ u8 width_min; ++ u8 width_max; ++ u16 pri_min; ++ u16 pri_max; ++ u8 num_pri; ++ u8 ppb; ++ u8 ppb_thresh; ++ u8 max_pri_tolerance; ++ enum radar_waveform_type type; ++}; ++ ++ ++/* percentage on ppb threshold to trigger detection */ ++#define MIN_PPB_THRESH 50 ++#define PPB_THRESH(PPB) ((PPB * MIN_PPB_THRESH + 50) / 100) ++#define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF) ++ ++/* width tolerance */ ++#define WIDTH_TOLERANCE 2 ++#define WIDTH_LOWER(X) (X) ++#define WIDTH_UPPER(X) (X) ++ ++#define ETSI_PATTERN_SHORT(ID, WMIN, WMAX, PMIN, PMAX, PPB) \ ++ { \ ++ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ ++ (PRF2PRI(PMAX) - PRI_TOLERANCE), \ ++ (PRF2PRI(PMIN) + PRI_TOLERANCE), 1, PPB, \ ++ PPB_THRESH(PPB), PRI_TOLERANCE, RADAR_WAVEFORM_SHORT \ ++ } ++ ++#define ETSI_PATTERN_INTERLEAVED(ID, WMIN, WMAX, PMIN, PMAX, PRFMIN, PRFMAX, PPB) \ ++ { \ ++ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ ++ (PRF2PRI(PMAX) * PRFMIN- PRI_TOLERANCE), \ ++ (PRF2PRI(PMIN) * PRFMAX + PRI_TOLERANCE), \ ++ PRFMAX, PPB * PRFMAX, \ ++ PPB_THRESH(PPB), PRI_TOLERANCE, RADAR_WAVEFORM_INTERLEAVED \ ++ } ++ ++/* radar types as defined by ETSI EN-301-893 v1.7.1 */ ++static const struct radar_detector_specs etsi_radar_ref_types_v17_riu[] = { ++ ETSI_PATTERN_SHORT(0, 0, 8, 700, 700, 18), ++ ETSI_PATTERN_SHORT(1, 0, 10, 200, 1000, 10), ++ ETSI_PATTERN_SHORT(2, 0, 22, 200, 1600, 15), ++ ETSI_PATTERN_SHORT(3, 0, 22, 2300, 4000, 25), ++ ETSI_PATTERN_SHORT(4, 20, 38, 2000, 4000, 20), ++ ETSI_PATTERN_INTERLEAVED(5, 0, 8, 300, 400, 2, 3, 10), ++ ETSI_PATTERN_INTERLEAVED(6, 0, 8, 400, 1200, 2, 3, 15), ++}; ++ ++static const struct radar_detector_specs etsi_radar_ref_types_v17_fcu[] = { ++ ETSI_PATTERN_SHORT(0, 0, 8, 700, 700, 18), ++ ETSI_PATTERN_SHORT(1, 0, 8, 200, 1000, 10), ++ ETSI_PATTERN_SHORT(2, 0, 16, 200, 1600, 15), ++ ETSI_PATTERN_SHORT(3, 0, 16, 2300, 4000, 25), ++ ETSI_PATTERN_SHORT(4, 20, 34, 2000, 4000, 20), ++ ETSI_PATTERN_INTERLEAVED(5, 0, 8, 300, 400, 2, 3, 10), ++ ETSI_PATTERN_INTERLEAVED(6, 0, 8, 400, 1200, 2, 3, 15), ++}; ++ ++static const struct radar_types etsi_radar_types_v17 = { ++ .region = NL80211_DFS_ETSI, ++ .num_radar_types = ARRAY_SIZE(etsi_radar_ref_types_v17_riu), ++ .spec_riu = etsi_radar_ref_types_v17_riu, ++ .spec_fcu = etsi_radar_ref_types_v17_fcu, ++}; ++ ++#define FCC_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB, TYPE) \ ++ { \ ++ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ ++ PMIN - PRI_TOLERANCE, \ ++ PMAX * PRF + PRI_TOLERANCE, PRF, PPB * PRF, \ ++ PPB_THRESH(PPB), PRI_TOLERANCE, TYPE \ ++ } ++ ++static const struct radar_detector_specs fcc_radar_ref_types_riu[] = { ++ FCC_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(1, 0, 8, 518, 3066, 1, 102, RADAR_WAVEFORM_WEATHER), ++ FCC_PATTERN(2, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(3, 6, 20, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(4, 10, 28, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(5, 50, 110, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ FCC_PATTERN(6, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_detector_specs fcc_radar_ref_types_fcu[] = { ++ FCC_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(1, 0, 8, 518, 3066, 1, 102, RADAR_WAVEFORM_WEATHER), ++ FCC_PATTERN(2, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(3, 6, 12, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(4, 10, 22, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(5, 50, 104, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ FCC_PATTERN(6, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_types fcc_radar_types = { ++ .region = NL80211_DFS_FCC, ++ .num_radar_types = ARRAY_SIZE(fcc_radar_ref_types_riu), ++ .spec_riu = fcc_radar_ref_types_riu, ++ .spec_fcu = fcc_radar_ref_types_fcu, ++}; ++ ++#define JP_PATTERN FCC_PATTERN ++static const struct radar_detector_specs jp_radar_ref_types_riu[] = { ++ JP_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(1, 2, 8, 3846, 3846, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(2, 0, 8, 1388, 1388, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(3, 0, 8, 4000, 4000, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(4, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(5, 6, 20, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(6, 10, 28, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(7, 50, 110, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ JP_PATTERN(8, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_detector_specs jp_radar_ref_types_fcu[] = { ++ JP_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(1, 2, 6, 3846, 3846, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(2, 0, 8, 1388, 1388, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(3, 2, 2, 4000, 4000, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(4, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(5, 6, 12, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(6, 10, 22, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(7, 50, 104, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ JP_PATTERN(8, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_types jp_radar_types = { ++ .region = NL80211_DFS_JP, ++ .num_radar_types = ARRAY_SIZE(jp_radar_ref_types_riu), ++ .spec_riu = jp_radar_ref_types_riu, ++ .spec_fcu = jp_radar_ref_types_fcu, ++}; ++ ++static const struct radar_types *dfs_domains[] = { ++ &etsi_radar_types_v17, ++ &fcc_radar_types, ++ &jp_radar_types, ++}; ++ ++ ++/** ++ * struct pri_sequence - sequence of pulses matching one PRI ++ * @head: list_head ++ * @pri: pulse repetition interval (PRI) in usecs ++ * @dur: duration of sequence in usecs ++ * @count: number of pulses in this sequence ++ * @count_falses: number of not matching pulses in this sequence ++ * @first_ts: time stamp of first pulse in usecs ++ * @last_ts: time stamp of last pulse in usecs ++ * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur) ++ * @ppb_thresh: Number of pulses to validate detection ++ * (need for weather radar whose value depends of pri) ++ */ ++struct pri_sequence { ++ struct list_head head; ++ u32 pri; ++ u32 dur; ++ u32 count; ++ u32 count_falses; ++ u64 first_ts; ++ u64 last_ts; ++ u64 deadline_ts; ++ u8 ppb_thresh; ++}; ++ ++ ++/** ++ * struct pulse_elem - elements in pulse queue ++ * @ts: time stamp in usecs ++ */ ++struct pulse_elem { ++ struct list_head head; ++ u64 ts; ++}; ++ ++/** ++ * struct pri_detector - PRI detector element for a dedicated radar type ++ * @head: ++ * @rs: detector specs for this detector element ++ * @last_ts: last pulse time stamp considered for this element in usecs ++ * @sequences: list_head holding potential pulse sequences ++ * @pulses: list connecting pulse_elem objects ++ * @count: number of pulses in queue ++ * @max_count: maximum number of pulses to be queued ++ * @window_size: window size back from newest pulse time stamp in usecs ++ * @freq: ++ */ ++struct pri_detector { ++ struct list_head head; ++ const struct radar_detector_specs *rs; ++ u64 last_ts; ++ struct list_head sequences; ++ struct list_head pulses; ++ u32 count; ++ u32 max_count; ++ u32 window_size; ++ struct pri_detector_ops *ops; ++ u16 freq; ++}; ++ ++/** ++ * struct pri_detector_ops - PRI detector ops (dependent of waveform type) ++ * @init : Initialize pri_detector structure ++ * @add_pulse : Add a pulse to the pri-detector ++ * @reset_on_pri_overflow : Should the pri_detector be resetted when pri overflow ++ */ ++struct pri_detector_ops { ++ void (*init)(struct pri_detector *pde); ++ struct pri_sequence * (*add_pulse)(struct pri_detector *pde, u16 len, u64 ts, u16 pri); ++ int reset_on_pri_overflow; ++}; ++ ++ ++/****************************************************************************** ++ * PRI (pulse repetition interval) sequence detection ++ *****************************************************************************/ ++/** ++ * Singleton Pulse and Sequence Pools ++ * ++ * Instances of pri_sequence and pulse_elem are kept in singleton pools to ++ * reduce the number of dynamic allocations. They are shared between all ++ * instances and grow up to the peak number of simultaneously used objects. ++ * ++ * Memory is freed after all references to the pools are released. ++ */ ++static u32 singleton_pool_references; ++static LIST_HEAD(pulse_pool); ++static LIST_HEAD(pseq_pool); ++static DEFINE_SPINLOCK(pool_lock); ++ ++static void pool_register_ref(void) ++{ ++ spin_lock_bh(&pool_lock); ++ singleton_pool_references++; ++ spin_unlock_bh(&pool_lock); ++} ++ ++static void pool_deregister_ref(void) ++{ ++ spin_lock_bh(&pool_lock); ++ singleton_pool_references--; ++ if (singleton_pool_references == 0) { ++ /* free singleton pools with no references left */ ++ struct pri_sequence *ps, *ps0; ++ struct pulse_elem *p, *p0; ++ ++ list_for_each_entry_safe(p, p0, &pulse_pool, head) { ++ list_del(&p->head); ++ kfree(p); ++ } ++ list_for_each_entry_safe(ps, ps0, &pseq_pool, head) { ++ list_del(&ps->head); ++ kfree(ps); ++ } ++ } ++ spin_unlock_bh(&pool_lock); ++} ++ ++static void pool_put_pulse_elem(struct pulse_elem *pe) ++{ ++ spin_lock_bh(&pool_lock); ++ list_add(&pe->head, &pulse_pool); ++ spin_unlock_bh(&pool_lock); ++} ++ ++static void pool_put_pseq_elem(struct pri_sequence *pse) ++{ ++ spin_lock_bh(&pool_lock); ++ list_add(&pse->head, &pseq_pool); ++ spin_unlock_bh(&pool_lock); ++} ++ ++static struct pri_sequence *pool_get_pseq_elem(void) ++{ ++ struct pri_sequence *pse = NULL; ++ spin_lock_bh(&pool_lock); ++ if (!list_empty(&pseq_pool)) { ++ pse = list_first_entry(&pseq_pool, struct pri_sequence, head); ++ list_del(&pse->head); ++ } ++ spin_unlock_bh(&pool_lock); ++ ++ if (pse == NULL) { ++ pse = kmalloc(sizeof(*pse), GFP_ATOMIC); ++ } ++ ++ return pse; ++} ++ ++static struct pulse_elem *pool_get_pulse_elem(void) ++{ ++ struct pulse_elem *pe = NULL; ++ spin_lock_bh(&pool_lock); ++ if (!list_empty(&pulse_pool)) { ++ pe = list_first_entry(&pulse_pool, struct pulse_elem, head); ++ list_del(&pe->head); ++ } ++ spin_unlock_bh(&pool_lock); ++ return pe; ++} ++ ++static struct pulse_elem *pulse_queue_get_tail(struct pri_detector *pde) ++{ ++ struct list_head *l = &pde->pulses; ++ if (list_empty(l)) ++ return NULL; ++ return list_entry(l->prev, struct pulse_elem, head); ++} ++ ++static bool pulse_queue_dequeue(struct pri_detector *pde) ++{ ++ struct pulse_elem *p = pulse_queue_get_tail(pde); ++ if (p != NULL) { ++ list_del_init(&p->head); ++ pde->count--; ++ /* give it back to pool */ ++ pool_put_pulse_elem(p); ++ } ++ return (pde->count > 0); ++} ++ ++/** ++ * pulse_queue_check_window - remove pulses older than window ++ * @pde: pointer on pri_detector ++ * ++ * dequeue pulse that are too old. ++ */ ++static ++void pulse_queue_check_window(struct pri_detector *pde) ++{ ++ u64 min_valid_ts; ++ struct pulse_elem *p; ++ ++ /* there is no delta time with less than 2 pulses */ ++ if (pde->count < 2) ++ return; ++ ++ if (pde->last_ts <= pde->window_size) ++ return; ++ ++ min_valid_ts = pde->last_ts - pde->window_size; ++ while ((p = pulse_queue_get_tail(pde)) != NULL) { ++ if (p->ts >= min_valid_ts) ++ return; ++ pulse_queue_dequeue(pde); ++ } ++} ++ ++/** ++ * pulse_queue_enqueue - Queue one pulse ++ * @pde: pointer on pri_detector ++ * ++ * Add one pulse to the list. If the maximum number of pulses ++ * if reached, remove oldest one. ++ */ ++static ++bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts) ++{ ++ struct pulse_elem *p = pool_get_pulse_elem(); ++ if (p == NULL) { ++ p = kmalloc(sizeof(*p), GFP_ATOMIC); ++ if (p == NULL) { ++ return false; ++ } ++ } ++ INIT_LIST_HEAD(&p->head); ++ p->ts = ts; ++ list_add(&p->head, &pde->pulses); ++ pde->count++; ++ pde->last_ts = ts; ++ pulse_queue_check_window(pde); ++ if (pde->count >= pde->max_count) ++ pulse_queue_dequeue(pde); ++ ++ return true; ++} ++ ++ ++/*************************************************************************** ++ * Short waveform ++ **************************************************************************/ ++/** ++ * pde_get_multiple() - get number of multiples considering a given tolerance ++ * @return factor if abs(val - factor*fraction) <= tolerance, 0 otherwise ++ */ ++static ++u32 pde_get_multiple(u32 val, u32 fraction, u32 tolerance) ++{ ++ u32 remainder; ++ u32 factor; ++ u32 delta; ++ ++ if (fraction == 0) ++ return 0; ++ ++ delta = (val < fraction) ? (fraction - val) : (val - fraction); ++ ++ if (delta <= tolerance) ++ /* val and fraction are within tolerance */ ++ return 1; ++ ++ factor = val / fraction; ++ remainder = val % fraction; ++ if (remainder > tolerance) { ++ /* no exact match */ ++ if ((fraction - remainder) <= tolerance) ++ /* remainder is within tolerance */ ++ factor++; ++ else ++ factor = 0; ++ } ++ return factor; ++} ++ ++/** ++ * pde_short_create_sequences - create_sequences function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * @ts: timestamp of the pulse ++ * @min_count: Minimum number of pulse to be present in the sequence. ++ * (With this pulse there is already a sequence with @min_count ++ * pulse, so if we can't create a sequence with more pulse don't ++ * create it) ++ * @return: false if an error occured (memory allocation) true otherwise ++ * ++ * For each pulses queued check if we can create a sequence with ++ * pri = (ts - pulse_queued.ts) which contains more than @min_count pulses. ++ * ++ */ ++static ++bool pde_short_create_sequences(struct pri_detector *pde, ++ u64 ts, u32 min_count) ++{ ++ struct pulse_elem *p; ++ u16 pulse_idx = 0; ++ ++ list_for_each_entry(p, &pde->pulses, head) { ++ struct pri_sequence ps, *new_ps; ++ struct pulse_elem *p2; ++ u32 tmp_false_count; ++ u64 min_valid_ts; ++ u32 delta_ts = ts - p->ts; ++ pulse_idx++; ++ ++ if (delta_ts < pde->rs->pri_min) ++ /* ignore too small pri */ ++ continue; ++ ++ if (delta_ts > pde->rs->pri_max) ++ /* stop on too large pri (sorted list) */ ++ break; ++ ++ /* build a new sequence with new potential pri */ ++ ps.count = 2; ++ ps.count_falses = pulse_idx - 1; ++ ps.first_ts = p->ts; ++ ps.last_ts = ts; ++ ps.pri = ts - p->ts; ++ ps.dur = ps.pri * (pde->rs->ppb - 1) ++ + 2 * pde->rs->max_pri_tolerance; ++ ++ p2 = p; ++ tmp_false_count = 0; ++ if (ps.dur > ts) ++ min_valid_ts = 0; ++ else ++ min_valid_ts = ts - ps.dur; ++ /* check which past pulses are candidates for new sequence */ ++ list_for_each_entry_continue(p2, &pde->pulses, head) { ++ u32 factor; ++ if (p2->ts < min_valid_ts) ++ /* stop on crossing window border */ ++ break; ++ /* check if pulse match (multi)PRI */ ++ factor = pde_get_multiple(ps.last_ts - p2->ts, ps.pri, ++ pde->rs->max_pri_tolerance); ++ if (factor > 0) { ++ ps.count++; ++ ps.first_ts = p2->ts; ++ /* ++ * on match, add the intermediate falses ++ * and reset counter ++ */ ++ ps.count_falses += tmp_false_count; ++ tmp_false_count = 0; ++ } else { ++ /* this is a potential false one */ ++ tmp_false_count++; ++ } ++ } ++ if (ps.count <= min_count) { ++ /* did not reach minimum count, drop sequence */ ++ continue; ++ } ++ /* this is a valid one, add it */ ++ ps.deadline_ts = ps.first_ts + ps.dur; ++ if (pde->rs->type == RADAR_WAVEFORM_WEATHER) { ++ ps.ppb_thresh = 19000000 / (360 * ps.pri); ++ ps.ppb_thresh = PPB_THRESH(ps.ppb_thresh); ++ } else { ++ ps.ppb_thresh = pde->rs->ppb_thresh; ++ } ++ ++ new_ps = pool_get_pseq_elem(); ++ if (new_ps == NULL) { ++ return false; ++ } ++ memcpy(new_ps, &ps, sizeof(ps)); ++ INIT_LIST_HEAD(&new_ps->head); ++ list_add(&new_ps->head, &pde->sequences); ++ } ++ return true; ++} ++ ++/** ++ * pde_short_add_to_existing_seqs - add_to_existing_seqs function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * @ts: timestamp of the pulse ++ * ++ * Check all sequemces created for this pde. ++ * - If the sequence is too old delete it. ++ * - Else if the delta with the previous pulse match the pri of the sequence ++ * add the pulse to this sequence. If the pulse cannot be added it is added ++ * to the false pulses for this sequence ++ * ++ * @return the length of the longest sequence in which the pulse has been added ++ */ ++static ++u32 pde_short_add_to_existing_seqs(struct pri_detector *pde, u64 ts) ++{ ++ u32 max_count = 0; ++ struct pri_sequence *ps, *ps2; ++ list_for_each_entry_safe(ps, ps2, &pde->sequences, head) { ++ u32 delta_ts; ++ u32 factor; ++ ++ /* first ensure that sequence is within window */ ++ if (ts > ps->deadline_ts) { ++ list_del_init(&ps->head); ++ pool_put_pseq_elem(ps); ++ continue; ++ } ++ ++ delta_ts = ts - ps->last_ts; ++ factor = pde_get_multiple(delta_ts, ps->pri, ++ pde->rs->max_pri_tolerance); ++ ++ if (factor > 0) { ++ ps->last_ts = ts; ++ ps->count++; ++ ++ if (max_count < ps->count) ++ max_count = ps->count; ++ } else { ++ ps->count_falses++; ++ } ++ } ++ return max_count; ++} ++ ++ ++/** ++ * pde_short_check_detection - check_detection function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * ++ * Check all sequemces created for this pde. ++ * - If a sequence contains more pulses than the threshold and more matching ++ * that false pulses. ++ * ++ * @return The first complete sequence, and NULL if no sequence is complete. ++ */ ++static ++struct pri_sequence *pde_short_check_detection(struct pri_detector *pde) ++{ ++ struct pri_sequence *ps; ++ ++ if (list_empty(&pde->sequences)) ++ return NULL; ++ ++ list_for_each_entry(ps, &pde->sequences, head) { ++ /* ++ * we assume to have enough matching confidence if we ++ * 1) have enough pulses ++ * 2) have more matching than false pulses ++ */ ++ if ((ps->count >= ps->ppb_thresh) && ++ (ps->count * pde->rs->num_pri > ps->count_falses)) { ++ return ps; ++ } ++ } ++ return NULL; ++} ++ ++/** ++ * pde_short_init - init function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * ++ * Initialize pri_detector window size to the maximun size of one burst ++ * for the radar specification associated. ++ */ ++static ++void pde_short_init(struct pri_detector *pde) ++{ ++ pde->window_size = pde->rs->pri_max * pde->rs->ppb * pde->rs->num_pri; ++ pde->max_count = pde->rs->ppb * 2; ++} ++ ++static void pri_detector_reset(struct pri_detector *pde, u64 ts); ++/** ++ * pde_short_add_pulse - Add pulse to a pri_detector for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * ++ * @pde : pointer on pri_detector ++ * @len : width of the pulse ++ * @ts : timestamp of the pulse received ++ * @pri : Delta in us with the previous pulse. ++ * (0 means that delta in bigger than 65535 us) ++ * ++ * Process on pulse within this pri_detector ++ * - First try to add it to existing sequence ++ * - Then try to create a new and longest sequence ++ * - Check if this pulse complete a sequence ++ * - If not save this pulse in the list ++ */ ++static ++struct pri_sequence *pde_short_add_pulse(struct pri_detector *pde, ++ u16 len, u64 ts, u16 pri) ++{ ++ u32 max_updated_seq; ++ struct pri_sequence *ps; ++ const struct radar_detector_specs *rs = pde->rs; ++ ++ if (pde->count == 0) { ++ /* This is the first pulse after reset, no need to check sequences */ ++ pulse_queue_enqueue(pde, ts); ++ return NULL; ++ } ++ ++ if ((ts - pde->last_ts) < rs->max_pri_tolerance) { ++ /* if delta to last pulse is too short, don't use this pulse */ ++ return NULL; ++ } ++ ++ max_updated_seq = pde_short_add_to_existing_seqs(pde, ts); ++ ++ if (!pde_short_create_sequences(pde, ts, max_updated_seq)) { ++ pri_detector_reset(pde, ts); ++ return NULL; ++ } ++ ++ ps = pde_short_check_detection(pde); ++ ++ if (ps == NULL) ++ pulse_queue_enqueue(pde, ts); ++ ++ return ps; ++} ++ ++ ++ ++/** ++ * pri detector ops to detect short radar waveform ++ * A Short waveform is defined by : ++ * The width of pulses. ++ * The interval between two pulses inside a burst (called pri) ++ * (some waveform may have or 2/3 interleaved pri) ++ * The number of pulses per burst (ppb) ++ */ ++static struct pri_detector_ops pri_detector_short = { ++ .init = pde_short_init, ++ .add_pulse = pde_short_add_pulse, ++ .reset_on_pri_overflow = 1, ++}; ++ ++ ++/*************************************************************************** ++ * Long waveform ++ **************************************************************************/ ++#define LONG_RADAR_DURATION 12000000 ++#define LONG_RADAR_BURST_MIN_DURATION (12000000 / 20) ++#define LONG_RADAR_MAX_BURST 20 ++ ++/** ++ * pde_long_init - init function for LONG radar waveform ++ * @pde: pointer on pri_detector ++ * ++ * Initialize pri_detector window size to the long waveform radar ++ * waveform (ie. 12s) and max_count ++ */ ++static ++void pde_long_init(struct pri_detector *pde) ++{ ++ pde->window_size = LONG_RADAR_DURATION; ++ pde->max_count = LONG_RADAR_MAX_BURST; /* only count burst not pulses */ ++} ++ ++ ++/** ++ * pde_long_add_pulse - Add pulse to a pri_detector for ++ * LONG radar waveform ++ * ++ * @pde : pointer on pri_detector ++ * @len : width of the pulse ++ * @ts : timestamp of the pulse received ++ * @pri : Delta in us with the previous pulse. ++ * ++ * ++ * For long pulse we only handle one sequence. Since each burst ++ * have a different set of parameters (number of pulse, pri) than ++ * the previous one we only use pulse width to add the pulse in the ++ * sequence. ++ * We only queue one pulse per burst and valid the radar when enough burst ++ * has been detected. ++ */ ++static ++struct pri_sequence *pde_long_add_pulse(struct pri_detector *pde, ++ u16 len, u64 ts, u16 pri) ++{ ++ struct pri_sequence *ps; ++ const struct radar_detector_specs *rs = pde->rs; ++ ++ if (list_empty(&pde->sequences)) { ++ /* First pulse, create a new sequence */ ++ ps = pool_get_pseq_elem(); ++ if (ps == NULL) { ++ return NULL; ++ } ++ ++ /*For long waveform, "count" represents the number of burst detected */ ++ ps->count = 1; ++ /*"count_false" represents the number of pulse in the current burst */ ++ ps->count_falses = 1; ++ ps->first_ts = ts; ++ ps->last_ts = ts; ++ ps->deadline_ts = ts + pde->window_size; ++ ps->pri = 0; ++ INIT_LIST_HEAD(&ps->head); ++ list_add(&ps->head, &pde->sequences); ++ pulse_queue_enqueue(pde, ts); ++ } else { ++ u32 delta_ts; ++ ++ ps = (struct pri_sequence *)pde->sequences.next; ++ ++ delta_ts = ts - ps->last_ts; ++ ps->last_ts = ts; ++ ++ if (delta_ts < rs->pri_max) { ++ /* ignore pulse too close from previous one */ ++ } else if ((delta_ts >= rs->pri_min) && ++ (delta_ts <= rs->pri_max)) { ++ /* this is a new pulse in the current burst, ignore it ++ (i.e don't queue it) */ ++ ps->count_falses++; ++ } else if ((ps->count > 2) && ++ (ps->dur + delta_ts) < LONG_RADAR_BURST_MIN_DURATION) { ++ /* not enough time between burst, ignore pulse */ ++ } else { ++ /* a new burst */ ++ ps->count++; ++ ps->count_falses = 1; ++ ++ /* reset the start of the sequence if deadline reached */ ++ if (ts > ps->deadline_ts) { ++ struct pulse_elem *p; ++ u64 min_valid_ts; ++ ++ min_valid_ts = ts - pde->window_size; ++ while ((p = pulse_queue_get_tail(pde)) != NULL) { ++ if (p->ts >= min_valid_ts) { ++ ps->first_ts = p->ts; ++ ps->deadline_ts = p->ts + pde->window_size; ++ break; ++ } ++ pulse_queue_dequeue(pde); ++ ps->count--; ++ } ++ } ++ ++ /* valid radar if enough burst detected and delta with first burst ++ is at least duration/2 */ ++ if (ps->count > pde->rs->ppb_thresh && ++ (ts - ps->first_ts) > (pde->window_size / 2)) { ++ return ps; ++ } else { ++ pulse_queue_enqueue(pde, ts); ++ ps->dur = delta_ts; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++/** ++ * pri detector ops to detect long radar waveform ++ */ ++static struct pri_detector_ops pri_detector_long = { ++ .init = pde_long_init, ++ .add_pulse = pde_long_add_pulse, ++ .reset_on_pri_overflow = 0, ++}; ++ ++ ++/*************************************************************************** ++ * PRI detector init/reset/exit/get ++ **************************************************************************/ ++/** ++ * pri_detector_init- Create a new pri_detector ++ * ++ * @dpd: dfs_pattern_detector instance pointer ++ * @radar_type: index of radar pattern ++ * @freq: Frequency of the pri detector ++ */ ++struct pri_detector *pri_detector_init(struct dfs_pattern_detector *dpd, ++ u16 radar_type, u16 freq) ++{ ++ struct pri_detector *pde; ++ ++ pde = kzalloc(sizeof(*pde), GFP_ATOMIC); ++ if (pde == NULL) ++ return NULL; ++ ++ INIT_LIST_HEAD(&pde->sequences); ++ INIT_LIST_HEAD(&pde->pulses); ++ INIT_LIST_HEAD(&pde->head); ++ list_add(&pde->head, &dpd->detectors[radar_type]); ++ ++ pde->rs = &dpd->radar_spec[radar_type]; ++ pde->freq = freq; ++ ++ if (pde->rs->type == RADAR_WAVEFORM_LONG) { ++ /* for LONG WAVEFORM */ ++ pde->ops = &pri_detector_long; ++ } else { ++ /* for SHORT, WEATHER and INTERLEAVED */ ++ pde->ops = &pri_detector_short; ++ } ++ ++ /* Init dependent of specs */ ++ pde->ops->init(pde); ++ ++ pool_register_ref(); ++ return pde; ++} ++ ++/** ++ * pri_detector_reset - Reset pri_detector ++ * ++ * @pde: pointer on pri_detector ++ * @ts: New ts reference for the pri_detector ++ * ++ * free pulse queue and sequences list and give objects back to pools ++ */ ++static ++void pri_detector_reset(struct pri_detector *pde, u64 ts) ++{ ++ struct pri_sequence *ps, *ps0; ++ struct pulse_elem *p, *p0; ++ list_for_each_entry_safe(ps, ps0, &pde->sequences, head) { ++ list_del_init(&ps->head); ++ pool_put_pseq_elem(ps); ++ } ++ list_for_each_entry_safe(p, p0, &pde->pulses, head) { ++ list_del_init(&p->head); ++ pool_put_pulse_elem(p); ++ } ++ pde->count = 0; ++ pde->last_ts = ts; ++} ++ ++/** ++ * pri_detector_exit - Delete pri_detector ++ * ++ * @pde: pointer on pri_detector ++ */ ++static ++void pri_detector_exit(struct pri_detector *pde) ++{ ++ pri_detector_reset(pde, 0); ++ pool_deregister_ref(); ++ list_del(&pde->head); ++ kfree(pde); ++} ++ ++/** ++ * pri_detector_get() - get pri detector for a given frequency and type ++ * @dpd: dfs_pattern_detector instance pointer ++ * @freq: frequency in MHz ++ * @radar_type: index of radar pattern ++ * @return pointer to pri detector on success, NULL otherwise ++ * ++ * Return existing pri detector for the given frequency or return a ++ * newly create one. ++ * Pri detector are "merged" by frequency so that if a pri detector for a freq ++ * of +/- 2Mhz already exists don't create a new one. ++ * ++ * Maybe will need to adapt frequency merge for pattern with chirp. ++ */ ++static struct pri_detector * ++pri_detector_get(struct dfs_pattern_detector *dpd, u16 freq, u16 radar_type) ++{ ++ struct pri_detector *pde, *cur = NULL; ++ list_for_each_entry(pde, &dpd->detectors[radar_type], head) { ++ if (pde->freq == freq) { ++ if (pde->count) ++ return pde; ++ else ++ cur = pde; ++ } else if (pde->freq - 2 == freq && pde->count) { ++ return pde; ++ } else if (pde->freq + 2 == freq && pde->count) { ++ return pde; ++ } ++ } ++ ++ if (cur) ++ return cur; ++ else ++ return pri_detector_init(dpd, radar_type, freq); ++} ++ ++ ++/****************************************************************************** ++ * DFS Pattern Detector ++ *****************************************************************************/ ++/** ++ * dfs_pattern_detector_reset() - reset all channel detectors ++ * ++ * @dpd: dfs_pattern_detector ++ */ ++static void dfs_pattern_detector_reset(struct dfs_pattern_detector *dpd) ++{ ++ struct pri_detector *pde; ++ int i; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry(pde, &dpd->detectors[i], head) ++ pri_detector_reset(pde, dpd->last_pulse_ts); ++ } ++ ++ dpd->last_pulse_ts = 0; ++ dpd->prev_jiffies = jiffies; ++} ++ ++/** ++ * dfs_pattern_detector_reset() - delete all channel detectors ++ * ++ * @dpd: dfs_pattern_detector ++ */ ++static void dfs_pattern_detector_exit(struct dfs_pattern_detector *dpd) ++{ ++ struct pri_detector *pde, *pde0; ++ int i; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry_safe(pde, pde0, &dpd->detectors[i], head) ++ pri_detector_exit(pde); ++ } ++ ++ kfree(dpd); ++} ++ ++/** ++ * dfs_pattern_detector_pri_overflow - reset all channel detectors on pri ++ * overflow ++ * @dpd: dfs_pattern_detector ++ */ ++static void dfs_pattern_detector_pri_overflow(struct dfs_pattern_detector *dpd) ++{ ++ struct pri_detector *pde; ++ int i; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry(pde, &dpd->detectors[i], head) ++ if (pde->ops->reset_on_pri_overflow) ++ pri_detector_reset(pde, dpd->last_pulse_ts); ++ } ++} ++ ++/** ++ * dfs_pattern_detector_add_pulse - Process one pulse ++ * ++ * @dpd: dfs_pattern_detector ++ * @chain: Chain that correspond to this pattern_detector (only for debug) ++ * @freq: frequency of the pulse ++ * @pri: Delta with previous pulse. (0 if delta is too big for u16) ++ * @len: width of the pulse ++ * @now: jiffies value when pulse was received ++ * ++ * Get (or create) the channel_detector for this frequency. Then add the pulse ++ * in each pri_detector created in this channel_detector. ++ * ++ * ++ * @return True is the pulse complete a radar pattern, false otherwise ++ */ ++static bool dfs_pattern_detector_add_pulse(struct dfs_pattern_detector *dpd, ++ enum rwnx_radar_chain chain, ++ u16 freq, u16 pri, u16 len, u32 now) ++{ ++ u32 i; ++ ++ /* ++ * pulses received for a non-supported or un-initialized ++ * domain are treated as detected radars for fail-safety ++ */ ++ if (dpd->region == NL80211_DFS_UNSET) ++ return true; ++ ++ /* Compute pulse time stamp */ ++ if (pri == 0) { ++ u32 delta_jiffie; ++ if (unlikely(now < dpd->prev_jiffies)) { ++ delta_jiffie = 0xffffffff - dpd->prev_jiffies + now; ++ } else { ++ delta_jiffie = now - dpd->prev_jiffies; ++ } ++ dpd->last_pulse_ts += jiffies_to_usecs(delta_jiffie); ++ dpd->prev_jiffies = now; ++ dfs_pattern_detector_pri_overflow(dpd); ++ } else { ++ dpd->last_pulse_ts += pri; ++ } ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ struct pri_sequence *ps; ++ struct pri_detector *pde; ++ const struct radar_detector_specs *rs = &dpd->radar_spec[i]; ++ ++ /* no need to look up for pde if len is not within range */ ++ if ((rs->width_min > len) || ++ (rs->width_max < len)) { ++ continue; ++ } ++ ++ pde = pri_detector_get(dpd, freq, i); ++ ps = pde->ops->add_pulse(pde, len, dpd->last_pulse_ts, pri); ++ ++ if (ps != NULL) { ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_detected(chain, dpd->region, pde->freq, i, ps->pri); ++#endif ++ // reset everything instead of just the channel detector ++ dfs_pattern_detector_reset(dpd); ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++/** ++ * get_dfs_domain_radar_types() - get radar types for a given DFS domain ++ * @param domain DFS domain ++ * @return radar_types ptr on success, NULL if DFS domain is not supported ++ */ ++static const struct radar_types * ++get_dfs_domain_radar_types(enum nl80211_dfs_regions region) ++{ ++ u32 i; ++ for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) { ++ if (dfs_domains[i]->region == region) ++ return dfs_domains[i]; ++ } ++ return NULL; ++} ++ ++/** ++ * get_dfs_max_radar_types() - get maximum radar types for all supported domain ++ * @return the maximum number of radar pattern supported by on region ++ */ ++static u16 get_dfs_max_radar_types(void) ++{ ++ u32 i; ++ u16 max = 0; ++ for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) { ++ if (dfs_domains[i]->num_radar_types > max) ++ max = dfs_domains[i]->num_radar_types; ++ } ++ return max; ++} ++ ++/** ++ * dfs_pattern_detector_set_domain - set DFS domain ++ * ++ * @dpd: dfs_pattern_detector ++ * @region: DFS region ++ * ++ * set DFS domain, resets detector lines upon domain changes ++ */ ++static ++bool dfs_pattern_detector_set_domain(struct dfs_pattern_detector *dpd, ++ enum nl80211_dfs_regions region, u8 chain) ++{ ++ const struct radar_types *rt; ++ struct pri_detector *pde, *pde0; ++ int i; ++ ++ if (dpd->region == region) ++ return true; ++ ++ dpd->region = NL80211_DFS_UNSET; ++ ++ rt = get_dfs_domain_radar_types(region); ++ if (rt == NULL) ++ return false; ++ ++ /* delete all pri detectors for previous DFS domain */ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry_safe(pde, pde0, &dpd->detectors[i], head) ++ pri_detector_exit(pde); ++ } ++ ++ if (chain == RWNX_RADAR_RIU) ++ dpd->radar_spec = rt->spec_riu; ++ else ++ dpd->radar_spec = rt->spec_fcu; ++ dpd->num_radar_types = rt->num_radar_types; ++ ++ dpd->region = region; ++ ++ AICWFDBG(LOGINFO,"set_region %d \n",region); ++ return true; ++} ++ ++/** ++ * dfs_pattern_detector_init - Initialize dfs_pattern_detector ++ * ++ * @region: DFS region ++ * @return: pointer on dfs_pattern_detector ++ * ++ */ ++static struct dfs_pattern_detector * ++dfs_pattern_detector_init(enum nl80211_dfs_regions region, u8 chain) ++{ ++ struct dfs_pattern_detector *dpd; ++ u16 i, max_radar_type = get_dfs_max_radar_types(); ++ ++ dpd = kmalloc(sizeof(*dpd) + max_radar_type * sizeof(dpd->detectors[0]), ++ GFP_KERNEL); ++ if (dpd == NULL) ++ return NULL; ++ ++ dpd->region = NL80211_DFS_UNSET; ++ dpd->enabled = RWNX_RADAR_DETECT_DISABLE; ++ dpd->last_pulse_ts = 0; ++ dpd->prev_jiffies = jiffies; ++ dpd->num_radar_types = 0; ++ for (i = 0; i < max_radar_type; i++) ++ INIT_LIST_HEAD(&dpd->detectors[i]); ++ ++ if (dfs_pattern_detector_set_domain(dpd, region, chain)) ++ return dpd; ++ ++ kfree(dpd); ++ return NULL; ++} ++ ++ ++/****************************************************************************** ++ * driver interface ++ *****************************************************************************/ ++static u16 rwnx_radar_get_center_freq(struct rwnx_hw *rwnx_hw, u8 chain) ++{ ++ if (chain == RWNX_RADAR_FCU) ++ return rwnx_hw->phy.sec_chan.center_freq1; ++ ++ if (chain == RWNX_RADAR_RIU) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) { ++ WARN(1, "Radar pulse without channel information"); ++ } else ++ return rwnx_hw->chanctx_table[rwnx_hw->cur_chanctx].chan_def.center_freq1; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } ++ ++ return 0; ++} ++ ++static void rwnx_radar_detected(struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct cfg80211_chan_def chan_def; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) { ++ WARN(1, "Radar detected without channel information"); ++ return; ++ } ++ ++ /* ++ recopy chan_def in local variable because rwnx_radar_cancel_cac may ++ clean the variable (if in CAC and it's the only vif using this context) ++ and CAC should be aborted before reporting the radar. ++ */ ++ chan_def = rwnx_hw->chanctx_table[rwnx_hw->cur_chanctx].chan_def; ++ ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ cfg80211_radar_event(rwnx_hw->wiphy, &chan_def, GFP_KERNEL); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++static void rwnx_radar_process_pulse(struct work_struct *ws) ++{ ++ struct rwnx_radar *radar = container_of(ws, struct rwnx_radar, ++ detection_work); ++ struct rwnx_hw *rwnx_hw = container_of(radar, struct rwnx_hw, radar); ++ int chain; ++ u32 pulses[RWNX_RADAR_LAST][RWNX_RADAR_PULSE_MAX]; ++ u16 pulses_count[RWNX_RADAR_LAST]; ++ u32 now = jiffies; /* would be better to store jiffies value in IT handler */ ++ ++ /* recopy pulses locally to avoid too long spin_lock */ ++ spin_lock_bh(&radar->lock); ++ for (chain = RWNX_RADAR_RIU; chain < RWNX_RADAR_LAST; chain++) { ++ int start, count; ++ ++ count = radar->pulses[chain].count; ++ start = radar->pulses[chain].index - count; ++ if (start < 0) ++ start += RWNX_RADAR_PULSE_MAX; ++ ++ pulses_count[chain] = count; ++ if (count == 0) ++ continue; ++ ++ if ((start + count) > RWNX_RADAR_PULSE_MAX) { ++ u16 count1 = (RWNX_RADAR_PULSE_MAX - start); ++ memcpy(&(pulses[chain][0]), ++ &(radar->pulses[chain].buffer[start]), ++ count1 * sizeof(struct radar_pulse)); ++ memcpy(&(pulses[chain][count1]), ++ &(radar->pulses[chain].buffer[0]), ++ (count - count1) * sizeof(struct radar_pulse)); ++ } else { ++ memcpy(&(pulses[chain][0]), ++ &(radar->pulses[chain].buffer[start]), ++ count * sizeof(struct radar_pulse)); ++ } ++ radar->pulses[chain].count = 0; ++ } ++ spin_unlock_bh(&radar->lock); ++ ++ ++ /* now process pulses */ ++ for (chain = RWNX_RADAR_RIU; chain < RWNX_RADAR_LAST; chain++) { ++ int i; ++ u16 freq; ++ ++ if (pulses_count[chain] == 0) ++ continue; ++ ++ freq = rwnx_radar_get_center_freq(rwnx_hw, chain); ++ ++ for (i = 0; i < pulses_count[chain] ; i++) { ++ struct radar_pulse *p = (struct radar_pulse *)&pulses[chain][i]; ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_pulse(chain, p); ++#endif ++ if (dfs_pattern_detector_add_pulse(radar->dpd[chain], chain, ++ (s16)freq + (2 * p->freq), ++ p->rep, (p->len * 2), now)) { ++ ++ u16 idx = radar->detected[chain].index; ++ ++ if (chain == RWNX_RADAR_RIU) { ++ /* operating chain, inform upper layer to change channel */ ++ if (radar->dpd[chain]->enabled == RWNX_RADAR_DETECT_REPORT) { ++ rwnx_radar_detected(rwnx_hw); ++ /* no need to report new radar until upper layer set a ++ new channel. This prevent warning if a new radar is ++ detected while mac80211 is changing channel */ ++ rwnx_radar_detection_enable(radar, ++ RWNX_RADAR_DETECT_DISABLE, ++ chain); ++ /* purge any event received since the beginning of the ++ function (we are sure not to interfer with tasklet ++ as we disable detection just before) */ ++ radar->pulses[chain].count = 0; ++ } ++ } else { ++ /* secondary radar detection chain, simply report info in ++ debugfs for now */ ++ } ++ ++ radar->detected[chain].freq[idx] = (s16)freq + (2 * p->freq); ++ radar->detected[chain].time[idx] = ktime_get_real_seconds(); ++ radar->detected[chain].index = ((idx + 1) % ++ NX_NB_RADAR_DETECTED); ++ radar->detected[chain].count++; ++ /* no need to process next pulses for this chain */ ++ break; ++ } ++ } ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static void rwnx_radar_cac_work(struct work_struct *ws) ++{ ++ struct delayed_work *dw = container_of(ws, struct delayed_work, work); ++ struct rwnx_radar *radar = container_of(dw, struct rwnx_radar, cac_work); ++ struct rwnx_hw *rwnx_hw = container_of(radar, struct rwnx_hw, radar); ++ struct rwnx_chanctx *ctxt; ++ ++ if (radar->cac_vif == NULL) { ++ WARN(1, "CAC finished but no vif set"); ++ return; ++ } ++ ++ ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index]; ++ cfg80211_cac_event(radar->cac_vif->ndev, ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ &ctxt->chan_def, ++ #endif ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) ++ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0); ++ #else ++ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); ++ #endif ++ rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif); ++ rwnx_chanctx_unlink(radar->cac_vif); ++ ++ radar->cac_vif = NULL; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++bool rwnx_radar_detection_init(struct rwnx_radar *radar) ++{ ++ spin_lock_init(&radar->lock); ++ ++ radar->dpd[RWNX_RADAR_RIU] = dfs_pattern_detector_init(NL80211_DFS_UNSET, ++ RWNX_RADAR_RIU); ++ if (radar->dpd[RWNX_RADAR_RIU] == NULL) ++ return false; ++ ++ radar->dpd[RWNX_RADAR_FCU] = dfs_pattern_detector_init(NL80211_DFS_UNSET, ++ RWNX_RADAR_FCU); ++ if (radar->dpd[RWNX_RADAR_FCU] == NULL) { ++ rwnx_radar_detection_deinit(radar); ++ return false; ++ } ++ ++ INIT_WORK(&radar->detection_work, rwnx_radar_process_pulse); ++#ifdef CONFIG_RWNX_FULLMAC ++ INIT_DELAYED_WORK(&radar->cac_work, rwnx_radar_cac_work); ++ radar->cac_vif = NULL; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ return true; ++} ++ ++void rwnx_radar_detection_deinit(struct rwnx_radar *radar) ++{ ++ if (radar->dpd[RWNX_RADAR_RIU]) { ++ dfs_pattern_detector_exit(radar->dpd[RWNX_RADAR_RIU]); ++ radar->dpd[RWNX_RADAR_RIU] = NULL; ++ } ++ if (radar->dpd[RWNX_RADAR_FCU]) { ++ dfs_pattern_detector_exit(radar->dpd[RWNX_RADAR_FCU]); ++ radar->dpd[RWNX_RADAR_FCU] = NULL; ++ } ++} ++ ++bool rwnx_radar_set_domain(struct rwnx_radar *radar, ++ enum nl80211_dfs_regions region) ++{ ++ if (radar->dpd[0] == NULL) ++ return false; ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_set_region(region); ++#endif ++ return (dfs_pattern_detector_set_domain(radar->dpd[RWNX_RADAR_RIU], ++ region, RWNX_RADAR_RIU) && ++ dfs_pattern_detector_set_domain(radar->dpd[RWNX_RADAR_FCU], ++ region, RWNX_RADAR_FCU)); ++} ++ ++void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain) ++{ ++ if (chain < RWNX_RADAR_LAST) { ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_enable_detection(radar->dpd[chain]->region, enable, chain); ++#endif ++ spin_lock_bh(&radar->lock); ++ radar->dpd[chain]->enabled = enable; ++ spin_unlock_bh(&radar->lock); ++ } ++} ++ ++bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, u8 chain) ++{ ++ return radar->dpd[chain]->enabled != RWNX_RADAR_DETECT_DISABLE; ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_radar_start_cac(struct rwnx_radar *radar, u32 cac_time_ms, ++ struct rwnx_vif *vif) ++{ ++ WARN(radar->cac_vif != NULL, "CAC already in progress"); ++ radar->cac_vif = vif; ++ schedule_delayed_work(&radar->cac_work, msecs_to_jiffies(cac_time_ms)); ++} ++ ++void rwnx_radar_cancel_cac(struct rwnx_radar *radar) ++{ ++ struct rwnx_hw *rwnx_hw = container_of(radar, struct rwnx_hw, radar); ++ ++ if (radar->cac_vif == NULL) { ++ return; ++ } ++ ++ if (cancel_delayed_work(&radar->cac_work)) { ++ struct rwnx_chanctx *ctxt; ++ ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index]; ++ rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif); ++ cfg80211_cac_event(radar->cac_vif->ndev, ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ &ctxt->chan_def, ++ #endif ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) ++ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0); ++ #else ++ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); ++ #endif ++ rwnx_chanctx_unlink(radar->cac_vif); ++ } ++ ++ radar->cac_vif = NULL; ++} ++ ++void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_chanctx *ctxt; ++ ++ /* If no information on current channel do nothing */ ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) ++ return; ++ ++ ctxt = &rwnx_hw->chanctx_table[rwnx_hw->cur_chanctx]; ++ if (ctxt->chan_def.chan->flags & IEEE80211_CHAN_RADAR) { ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_REPORT, ++ RWNX_RADAR_RIU); ++ } else { ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_DISABLE, ++ RWNX_RADAR_RIU); ++ } ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/***************************************************************************** ++ * Debug functions ++ *****************************************************************************/ ++static ++int rwnx_radar_dump_pri_detector(char *buf, size_t len, ++ struct pri_detector *pde) ++{ ++ char freq_info[] = "Freq = %3.dMhz\n"; ++ char seq_info[] = " pri | count | false \n"; ++ struct pri_sequence *seq; ++ int res, write = 0; ++ ++ if (list_empty(&pde->sequences)) { ++ return 0; ++ } ++ ++ if (buf == NULL) { ++ int nb_seq = 1; ++ list_for_each_entry(seq, &pde->sequences, head) { ++ nb_seq++; ++ } ++ ++ return (sizeof(freq_info) + nb_seq * sizeof(seq_info)); ++ } ++ ++ res = scnprintf(buf, len, freq_info, pde->freq); ++ write += res; ++ len -= res; ++ ++ res = scnprintf(&buf[write], len, "%s", seq_info); ++ write += res; ++ len -= res; ++ ++ list_for_each_entry(seq, &pde->sequences, head) { ++ res = scnprintf(&buf[write], len, " %6.d | %2.d | %.2d \n", ++ seq->pri, seq->count, seq->count_falses); ++ write += res; ++ len -= res; ++ } ++ ++ return write; ++} ++ ++int rwnx_radar_dump_pattern_detector(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain) ++{ ++ struct dfs_pattern_detector *dpd = radar->dpd[chain]; ++ char info[] = "Type = %3.d\n"; ++ struct pri_detector *pde; ++ int i, res, write = 0; ++ ++ /* if buf is NULL return size needed for dump */ ++ if (buf == NULL) { ++ int size_needed = 0; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ list_for_each_entry(pde, &dpd->detectors[i], head) { ++ size_needed += rwnx_radar_dump_pri_detector(NULL, 0, pde); ++ } ++ size_needed += sizeof(info); ++ ++ return size_needed; ++ } ++ } ++ ++ /* */ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ res = scnprintf(&buf[write], len, info, i); ++ ++ write += res; ++ len -= res; ++ list_for_each_entry(pde, &dpd->detectors[i], head) { ++ res = rwnx_radar_dump_pri_detector(&buf[write], len, pde); ++ write += res; ++ len -= res; ++ } ++ } ++ ++ return write; ++} ++ ++ ++int rwnx_radar_dump_radar_detected(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain) ++{ ++ struct rwnx_radar_detected *detect = &(radar->detected[chain]); ++ char info[] = "2001/02/02 - 02:20 5126MHz\n"; ++ int idx, i, res, write = 0; ++ int count = detect->count; ++ ++ if (count > NX_NB_RADAR_DETECTED) ++ count = NX_NB_RADAR_DETECTED; ++ ++ if (buf == NULL) { ++ return (count * sizeof(info)) + 1; ++ } ++ ++ idx = (detect->index - detect->count) % NX_NB_RADAR_DETECTED; ++ ++ for (i = 0; i < count; i++) { ++ struct tm tm; ++ time64_to_tm(detect->time[idx], 0, &tm); ++ ++ res = scnprintf(&buf[write], len, ++ "%.4d/%.2d/%.2d - %.2d:%.2d %4.4dMHz\n", ++ (int)tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, ++ tm.tm_hour, tm.tm_min, detect->freq[idx]); ++ write += res; ++ len -= res; ++ ++ idx = (idx + 1) % NX_NB_RADAR_DETECTED; ++ } ++ ++ return write; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h +new file mode 100644 +index 000000000000..8bc36f527f62 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h +@@ -0,0 +1,160 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_radar.h ++ * ++ * @brief Functions to handle radar detection ++ * ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_RADAR_H_ ++#define _RWNX_RADAR_H_ ++ ++#include ++ ++struct rwnx_vif; ++struct rwnx_hw; ++ ++enum rwnx_radar_chain { ++ RWNX_RADAR_RIU = 0, ++ RWNX_RADAR_FCU, ++ RWNX_RADAR_LAST ++}; ++ ++enum rwnx_radar_detector { ++ RWNX_RADAR_DETECT_DISABLE = 0, /* Ignore radar pulses */ ++ RWNX_RADAR_DETECT_ENABLE = 1, /* Process pattern detection but do not ++ report radar to upper layer (for test) */ ++ RWNX_RADAR_DETECT_REPORT = 2 /* Process pattern detection and report ++ radar to upper layer. */ ++}; ++ ++#ifdef CONFIG_RWNX_RADAR ++#include ++#include ++ ++#define RWNX_RADAR_PULSE_MAX 32 ++ ++/** ++ * struct rwnx_radar_pulses - List of pulses reported by HW ++ * @index: write index ++ * @count: number of valid pulses ++ * @buffer: buffer of pulses ++ */ ++struct rwnx_radar_pulses { ++ /* Last radar pulses received */ ++ int index; ++ int count; ++ u32 buffer[RWNX_RADAR_PULSE_MAX]; ++}; ++ ++/** ++ * struct dfs_pattern_detector - DFS pattern detector ++ * @region: active DFS region, NL80211_DFS_UNSET until set ++ * @num_radar_types: number of different radar types ++ * @last_pulse_ts: time stamp of last valid pulse in usecs ++ * @prev_jiffies: ++ * @radar_detector_specs: array of radar detection specs ++ * @channel_detectors: list connecting channel_detector elements ++ */ ++struct dfs_pattern_detector { ++ u8 enabled; ++ enum nl80211_dfs_regions region; ++ u8 num_radar_types; ++ u64 last_pulse_ts; ++ u32 prev_jiffies; ++ const struct radar_detector_specs *radar_spec; ++ struct list_head detectors[]; ++}; ++ ++#define NX_NB_RADAR_DETECTED 4 ++ ++/** ++ * struct rwnx_radar_detected - List of radar detected ++ */ ++struct rwnx_radar_detected { ++ u16 index; ++ u16 count; ++ s64 time[NX_NB_RADAR_DETECTED]; ++ s16 freq[NX_NB_RADAR_DETECTED]; ++}; ++ ++ ++struct rwnx_radar { ++ struct rwnx_radar_pulses pulses[RWNX_RADAR_LAST]; ++ struct dfs_pattern_detector *dpd[RWNX_RADAR_LAST]; ++ struct rwnx_radar_detected detected[RWNX_RADAR_LAST]; ++ struct work_struct detection_work; /* Work used to process radar pulses */ ++ spinlock_t lock; /* lock for pulses processing */ ++ ++ /* In softmac cac is handled by mac80211 */ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct delayed_work cac_work; /* Work used to handle CAC */ ++ struct rwnx_vif *cac_vif; /* vif on which we started CAC */ ++#endif ++}; ++ ++bool rwnx_radar_detection_init(struct rwnx_radar *radar); ++void rwnx_radar_detection_deinit(struct rwnx_radar *radar); ++bool rwnx_radar_set_domain(struct rwnx_radar *radar, ++ enum nl80211_dfs_regions region); ++void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain); ++bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, u8 chain); ++void rwnx_radar_start_cac(struct rwnx_radar *radar, u32 cac_time_ms, ++ struct rwnx_vif *vif); ++void rwnx_radar_cancel_cac(struct rwnx_radar *radar); ++void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw); ++int rwnx_radar_dump_pattern_detector(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain); ++int rwnx_radar_dump_radar_detected(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain); ++ ++#else ++ ++struct rwnx_radar { ++}; ++ ++static inline bool rwnx_radar_detection_init(struct rwnx_radar *radar) ++{return true; } ++ ++static inline void rwnx_radar_detection_deinit(struct rwnx_radar *radar) ++{} ++ ++static inline bool rwnx_radar_set_domain(struct rwnx_radar *radar, ++ enum nl80211_dfs_regions region) ++{return true; } ++ ++static inline void rwnx_radar_detection_enable(struct rwnx_radar *radar, ++ u8 enable, u8 chain) ++{} ++ ++static inline bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, ++ u8 chain) ++{return false; } ++ ++static inline void rwnx_radar_start_cac(struct rwnx_radar *radar, ++ u32 cac_time_ms, struct rwnx_vif *vif) ++{} ++ ++static inline void rwnx_radar_cancel_cac(struct rwnx_radar *radar) ++{} ++ ++static inline void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw) ++{} ++ ++static inline int rwnx_radar_dump_pattern_detector(char *buf, size_t len, ++ struct rwnx_radar *radar, ++ u8 chain) ++{return 0; } ++ ++static inline int rwnx_radar_dump_radar_detected(char *buf, size_t len, ++ struct rwnx_radar *radar, ++ u8 chain) ++{return 0; } ++ ++#endif /* CONFIG_RWNX_RADAR */ ++ ++#endif // _RWNX_RADAR_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c +new file mode 100644 +index 000000000000..148dca51c1df +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c +@@ -0,0 +1,2531 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_rx.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_rx.h" ++#include "rwnx_tx.h" ++#include "rwnx_prof.h" ++#include "ipc_host.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "aicwf_txrxif.h" ++#ifdef AICWF_ARP_OFFLOAD ++#include ++#include ++#include "rwnx_msg_tx.h" ++#endif ++ ++#ifndef IEEE80211_MAX_CHAINS ++#define IEEE80211_MAX_CHAINS 4 ++#endif ++ ++u8 dhcped; // = 0; ++ ++u16 tx_legrates_lut_rate[] = { ++ 10, ++ 20, ++ 55, ++ 110, ++ 60, ++ 90, ++ 120, ++ 180, ++ 240, ++ 360, ++ 480, ++ 540 ++}; ++ ++struct rwnx_legrate legrates_lut[] = { ++ [0] = { .idx = 0, .rate = 10}, ++ [1] = { .idx = 1, .rate = 20}, ++ [2] = { .idx = 2, .rate = 55}, ++ [3] = { .idx = 3, .rate = 110}, ++ [4] = { .idx = -1, .rate = 0}, ++ [5] = { .idx = -1, .rate = 0}, ++ [6] = { .idx = -1, .rate = 0}, ++ [7] = { .idx = -1, .rate = 0}, ++ [8] = { .idx = 10, .rate = 480}, ++ [9] = { .idx = 8, .rate = 240}, ++ [10] = { .idx = 6, .rate = 120}, ++ [11] = { .idx = 4, .rate = 60}, ++ [12] = { .idx = 11, .rate = 540}, ++ [13] = { .idx = 9, .rate = 360}, ++ [14] = { .idx = 7, .rate = 180}, ++ [15] = { .idx = 5, .rate = 90}, ++}; ++ ++struct vendor_radiotap_hdr { ++ u8 oui[3]; ++ u8 subns; ++ u16 len; ++ u8 data[]; ++}; ++ ++/** ++ * rwnx_rx_get_vif - Return pointer to the destination vif ++ * ++ * @rwnx_hw: main driver data ++ * @vif_idx: vif index present in rx descriptor ++ * ++ * Select the vif that should receive this frame. Returns NULL if the destination ++ * vif is not active or vif is not specified in the descriptor. ++ */ ++static inline ++struct rwnx_vif *rwnx_rx_get_vif(struct rwnx_hw *rwnx_hw, int vif_idx) ++{ ++ struct rwnx_vif *rwnx_vif = NULL; ++ ++ if (vif_idx < NX_VIRT_DEV_MAX) { ++ rwnx_vif = rwnx_hw->vif_table[vif_idx]; ++ ++ if(!rwnx_vif){ ++ AICWFDBG(LOGERROR, "%s rwnx_hw->vif_table[%d] NULL\r\n", __func__, vif_idx); ++ return NULL; ++ }else if(!rwnx_vif->up){ ++ AICWFDBG(LOGERROR, "%s rwnx_hw->vif_table[%d] is down\r\n", __func__, vif_idx); ++ return NULL; ++ } ++ } ++ ++ return rwnx_vif; ++} ++ ++/** ++ * rwnx_rx_vector_convert - Convert a legacy RX vector into a new RX vector format ++ * ++ * @rwnx_hw: main driver data. ++ * @rx_vect1: Rx vector 1 descriptor of the received frame. ++ * @rx_vect2: Rx vector 2 descriptor of the received frame. ++ */ ++static void rwnx_rx_vector_convert(struct rwnx_hw *rwnx_hw, ++ struct rx_vector_1 *rx_vect1, ++ struct rx_vector_2 *rx_vect2) ++{ ++ struct rx_vector_1_old rx_vect1_leg; ++ struct rx_vector_2_old rx_vect2_leg; ++ u32_l phy_vers = rwnx_hw->version_cfm.version_phy_2; ++ ++ // Check if we need to do the conversion. Only if old modem is used ++ if (__MDM_MAJOR_VERSION(phy_vers) > 0) { ++ rx_vect1->rssi1 = rx_vect1->rssi_leg; ++ return; ++ } ++ ++ // Copy the received vector locally ++ memcpy(&rx_vect1_leg, rx_vect1, sizeof(struct rx_vector_1_old)); ++ ++ // Reset it ++ memset(rx_vect1, 0, sizeof(struct rx_vector_1)); ++ ++ // Perform the conversion ++ rx_vect1->format_mod = rx_vect1_leg.format_mod; ++ rx_vect1->ch_bw = rx_vect1_leg.ch_bw; ++ rx_vect1->antenna_set = rx_vect1_leg.antenna_set; ++ rx_vect1->leg_length = rx_vect1_leg.leg_length; ++ rx_vect1->leg_rate = rx_vect1_leg.leg_rate; ++ rx_vect1->rssi1 = rx_vect1_leg.rssi1; ++ ++ switch (rx_vect1->format_mod) { ++ case FORMATMOD_NON_HT: ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ rx_vect1->leg.lsig_valid = rx_vect1_leg.lsig_valid; ++ rx_vect1->leg.chn_bw_in_non_ht = rx_vect1_leg.num_extn_ss; ++ rx_vect1->leg.dyn_bw_in_non_ht = rx_vect1_leg.dyn_bw; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ rx_vect1->ht.aggregation = rx_vect1_leg.aggregation; ++ rx_vect1->ht.fec = rx_vect1_leg.fec_coding; ++ rx_vect1->ht.lsig_valid = rx_vect1_leg.lsig_valid; ++ rx_vect1->ht.length = rx_vect1_leg.ht_length; ++ rx_vect1->ht.mcs = rx_vect1_leg.mcs; ++ rx_vect1->ht.num_extn_ss = rx_vect1_leg.num_extn_ss; ++ rx_vect1->ht.short_gi = rx_vect1_leg.short_gi; ++ rx_vect1->ht.smoothing = rx_vect1_leg.smoothing; ++ rx_vect1->ht.sounding = rx_vect1_leg.sounding; ++ rx_vect1->ht.stbc = rx_vect1_leg.stbc; ++ break; ++ case FORMATMOD_VHT: ++ rx_vect1->vht.beamformed = !rx_vect1_leg.smoothing; ++ rx_vect1->vht.fec = rx_vect1_leg.fec_coding; ++ rx_vect1->vht.length = rx_vect1_leg.ht_length | rx_vect1_leg._ht_length << 8; ++ rx_vect1->vht.mcs = rx_vect1_leg.mcs & 0x0F; ++ rx_vect1->vht.nss = rx_vect1_leg.stbc ? rx_vect1_leg.n_sts/2 : rx_vect1_leg.n_sts; ++ rx_vect1->vht.doze_not_allowed = rx_vect1_leg.doze_not_allowed; ++ rx_vect1->vht.short_gi = rx_vect1_leg.short_gi; ++ rx_vect1->vht.sounding = rx_vect1_leg.sounding; ++ rx_vect1->vht.stbc = rx_vect1_leg.stbc; ++ rx_vect1->vht.group_id = rx_vect1_leg.group_id; ++ rx_vect1->vht.partial_aid = rx_vect1_leg.partial_aid; ++ rx_vect1->vht.first_user = rx_vect1_leg.first_user; ++ break; ++ } ++ ++ if (!rx_vect2) ++ return; ++ ++ // Copy the received vector 2 locally ++ memcpy(&rx_vect2_leg, rx_vect2, sizeof(struct rx_vector_2_old)); ++ ++ // Reset it ++ memset(rx_vect2, 0, sizeof(struct rx_vector_2)); ++ ++ rx_vect2->rcpi1 = rx_vect2_leg.rcpi; ++ rx_vect2->rcpi2 = rx_vect2_leg.rcpi; ++ rx_vect2->rcpi3 = rx_vect2_leg.rcpi; ++ rx_vect2->rcpi4 = rx_vect2_leg.rcpi; ++ ++ rx_vect2->evm1 = rx_vect2_leg.evm1; ++ rx_vect2->evm2 = rx_vect2_leg.evm2; ++ rx_vect2->evm3 = rx_vect2_leg.evm3; ++ rx_vect2->evm4 = rx_vect2_leg.evm4; ++} ++ ++/** ++ * rwnx_rx_statistic - save some statistics about received frames ++ * ++ * @rwnx_hw: main driver data. ++ * @hw_rxhdr: Rx Hardware descriptor of the received frame. ++ * @sta: STA that sent the frame. ++ */ ++static void rwnx_rx_statistic(struct rwnx_hw *rwnx_hw, struct hw_rxhdr *hw_rxhdr, ++ struct rwnx_sta *sta) ++{ ++#if 1//def CONFIG_RWNX_DEBUGFS ++ struct rwnx_stats *stats = &rwnx_hw->stats; ++ struct rwnx_rx_rate_stats *rate_stats = &sta->stats.rx_rate; ++ struct rx_vector_1 *rxvect = &hw_rxhdr->hwvect.rx_vect1; ++ int mpdu, ampdu, mpdu_prev, rate_idx; ++ ++ /* save complete hwvect */ ++ sta->stats.last_rx = hw_rxhdr->hwvect; ++ ++ /* update ampdu rx stats */ ++ mpdu = hw_rxhdr->hwvect.mpdu_cnt; ++ ampdu = hw_rxhdr->hwvect.ampdu_cnt; ++ mpdu_prev = stats->ampdus_rx_map[ampdu]; ++ ++ if (mpdu_prev < mpdu) { ++ stats->ampdus_rx_miss += mpdu - mpdu_prev - 1; ++ } else { ++ stats->ampdus_rx[mpdu_prev]++; ++ } ++ stats->ampdus_rx_map[ampdu] = mpdu; ++ ++ /* update rx rate statistic */ ++ if (!rate_stats->size) ++ return; ++ ++ if (rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) { ++ int mcs; ++ int bw = rxvect->ch_bw; ++ int sgi; ++ int nss; ++ switch (rxvect->format_mod) { ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ mcs = rxvect->ht.mcs % 8; ++ nss = rxvect->ht.mcs / 8; ++ sgi = rxvect->ht.short_gi; ++ rate_idx = N_CCK + N_OFDM + nss * 32 + mcs * 4 + bw * 2 + sgi; ++ break; ++ case FORMATMOD_VHT: ++ mcs = rxvect->vht.mcs; ++ nss = rxvect->vht.nss; ++ sgi = rxvect->vht.short_gi; ++ rate_idx = N_CCK + N_OFDM + N_HT + nss * 80 + mcs * 8 + bw * 2 + sgi; ++ break; ++ case FORMATMOD_HE_SU: ++ mcs = rxvect->he.mcs; ++ nss = rxvect->he.nss; ++ sgi = rxvect->he.gi_type; ++ rate_idx = N_CCK + N_OFDM + N_HT + N_VHT + nss * 144 + mcs * 12 + bw * 3 + sgi; ++ break; ++ default: ++ mcs = rxvect->he.mcs; ++ nss = rxvect->he.nss; ++ sgi = rxvect->he.gi_type; ++ rate_idx = N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU ++ + nss * 216 + mcs * 18 + rxvect->he.ru_size * 3 + sgi; ++ break; ++ } ++ } else { ++ int idx = legrates_lut[rxvect->leg_rate].idx; ++ if (idx < 4) { ++ rate_idx = idx * 2 + rxvect->pre_type; ++ } else { ++ rate_idx = N_CCK + idx - 4; ++ } ++ } ++ if (rate_idx < rate_stats->size) { ++ if (!rate_stats->table[rate_idx]) ++ rate_stats->rate_cnt++; ++ rate_stats->table[rate_idx]++; ++ rate_stats->cpt++; ++ } else { ++ wiphy_err(rwnx_hw->wiphy, "RX: Invalid index conversion => %d/%d\n", ++ rate_idx, rate_stats->size); ++ } ++#endif ++} ++ ++/** ++ * rwnx_rx_data_skb - Process one data frame ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: vif that received the buffer ++ * @skb: skb received ++ * @rxhdr: HW rx descriptor ++ * @return: true if buffer has been forwarded to upper layer ++ * ++ * If buffer is amsdu , it is first split into a list of skb. ++ * Then each skb may be: ++ * - forwarded to upper layer ++ * - resent on wireless interface ++ * ++ * When vif is a STA interface, every skb is only forwarded to upper layer. ++ * When vif is an AP interface, multicast skb are forwarded and resent, whereas ++ * skb for other BSS's STA are only resent. ++ */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#define RAISE_RX_SOFTIRQ() \ ++ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) ++#endif /* LINUX_VERSION_CODE */ ++ ++void rwnx_rx_data_skb_resend(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *rxhdr) ++{ ++ struct sk_buff *rx_skb = skb; ++ const struct ethhdr *eth; ++ struct sk_buff *skb_copy; ++ ++ rx_skb->dev = rwnx_vif->ndev; ++ skb_reset_mac_header(rx_skb); ++ eth = eth_hdr(rx_skb); ++ ++ //printk("resend\n"); ++ /* resend pkt on wireless interface */ ++ /* always need to copy buffer when forward=0 to get enough headrom for tsdesc */ ++ skb_copy = skb_copy_expand(rx_skb, sizeof(struct rwnx_txhdr) + ++ RWNX_SWTXHDR_ALIGN_SZ + 3 + 24 + 8, 0, GFP_ATOMIC); ++ ++ if (skb_copy) { ++ int res; ++ skb_copy->protocol = htons(ETH_P_802_3); ++ skb_reset_network_header(skb_copy); ++ skb_reset_mac_header(skb_copy); ++ ++ rwnx_vif->is_resending = true; ++ res = dev_queue_xmit(skb_copy); ++ rwnx_vif->is_resending = false; ++ /* note: buffer is always consummed by dev_queue_xmit */ ++ if (res == NET_XMIT_DROP) { ++ rwnx_vif->net_stats.rx_dropped++; ++ rwnx_vif->net_stats.tx_dropped++; ++ } else if (res != NET_XMIT_SUCCESS) { ++ netdev_err(rwnx_vif->ndev, ++ "Failed to re-send buffer to driver (res=%d)", ++ res); ++ rwnx_vif->net_stats.tx_errors++; ++ } ++ } else { ++ netdev_err(rwnx_vif->ndev, "Failed to copy skb"); ++ } ++} ++ ++static void rwnx_rx_data_skb_forward(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *rxhdr) ++{ ++ struct sk_buff *rx_skb; ++ ++ rx_skb = skb; ++ rx_skb->dev = rwnx_vif->ndev; ++ skb_reset_mac_header(rx_skb); ++ ++ #ifdef CONFIG_BR_SUPPORT ++ void *br_port = NULL; ++ ++ if (1) {//(check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ /* Insert NAT2.5 RX here! */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb); ++ ++ if (nat25_handle_frame(rwnx_vif, rx_skb) == -1) { ++ /* priv->ext_stats.rx_data_drops++; */ ++ /* DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); */ ++ /* return FAIL; */ ++ ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ /* Update statistics */ ++ rwnx_vif->net_stats.rx_packets++; ++ rwnx_vif->net_stats.rx_bytes += rx_skb->len; ++ ++ //printk("forward\n"); ++ ++ rx_skb->protocol = eth_type_trans(rx_skb, rwnx_vif->ndev); ++ memset(rx_skb->cb, 0, sizeof(rx_skb->cb)); ++ REG_SW_SET_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++ #ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_hw,rx_skb->data, cpu_to_le16(rx_skb->len)); ++ #endif ++ ++ #ifdef CONFIG_RX_NETIF_RECV_SKB //modify by aic ++ local_bh_disable(); ++ netif_receive_skb(rx_skb); ++ local_bh_enable(); ++ #else ++ if (in_interrupt()) { ++ netif_rx(rx_skb); ++ } else { ++ /* ++ * If the receive is not processed inside an ISR, the softirqd must be woken explicitly to service the NET_RX_SOFTIRQ. ++ * * In 2.6 kernels, this is handledby netif_rx_ni(), but in earlier kernels, we need to do it manually. ++ */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(rx_skb); ++ #else ++ ulong flags; ++ netif_rx(rx_skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++ #endif ++ } ++ #endif ++ REG_SW_CLEAR_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++ rwnx_hw->stats.last_rx = jiffies; ++} ++ ++ ++static bool rwnx_rx_data_skb(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *rxhdr) ++{ ++ struct sk_buff_head list; ++ struct sk_buff *rx_skb; ++ bool amsdu = rxhdr->flags_is_amsdu; ++ u8 flags_dst_idx = rxhdr->flags_dst_idx; ++ bool resend = false, forward = true; ++ ++ skb->dev = rwnx_vif->ndev; ++ ++ __skb_queue_head_init(&list); ++ ++ if (amsdu) { ++ #if 1 ++ rwnx_rxdata_process_amsdu(rwnx_hw, skb, rxhdr->flags_vif_idx, &list); //rxhdr not used below since skb free! ++ #else ++ int count; ++ ieee80211_amsdu_to_8023s(skb, &list, rwnx_vif->ndev->dev_addr, ++ RWNX_VIF_TYPE(rwnx_vif), 0, NULL, NULL); ++ ++ count = skb_queue_len(&list); ++ if (count > ARRAY_SIZE(rwnx_hw->stats.amsdus_rx)) ++ count = ARRAY_SIZE(rwnx_hw->stats.amsdus_rx); ++ rwnx_hw->stats.amsdus_rx[count - 1]++; ++ #endif ++ } else { ++ rwnx_hw->stats.amsdus_rx[0]++; ++ __skb_queue_head(&list, skb); ++ } ++ ++ if (((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP) || ++ (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN) || ++ (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO)) && ++ !(rwnx_vif->ap.flags & RWNX_AP_ISOLATE)) { ++ const struct ethhdr *eth; ++ rx_skb = skb_peek(&list); ++ skb_reset_mac_header(rx_skb); ++ eth = eth_hdr(rx_skb); ++ ++ if (unlikely(is_multicast_ether_addr(eth->h_dest))) { ++ /* broadcast pkt need to be forwared to upper layer and resent ++ on wireless interface */ ++ resend = true; ++ } else { ++ /* unicast pkt for STA inside the BSS, no need to forward to upper ++ layer simply resend on wireless interface */ ++ if (flags_dst_idx != RWNX_INVALID_STA) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[flags_dst_idx]; ++ if (sta->valid && (sta->vlan_idx == rwnx_vif->vif_index)) { ++ forward = false; ++ resend = true; ++ } ++ } ++ } ++ } else if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT) { ++ const struct ethhdr *eth; ++ rx_skb = skb_peek(&list); ++ skb_reset_mac_header(rx_skb); ++ eth = eth_hdr(rx_skb); ++ ++ if (!is_multicast_ether_addr(eth->h_dest)) { ++ /* unicast pkt for STA inside the BSS, no need to forward to upper ++ layer simply resend on wireless interface */ ++ if (flags_dst_idx != RWNX_INVALID_STA) { ++ forward = false; ++ resend = true; ++ } ++ } ++ } ++ ++ while (!skb_queue_empty(&list)) { ++ rx_skb = __skb_dequeue(&list); ++ ++ /* resend pkt on wireless interface */ ++ if (resend) { ++ struct sk_buff *skb_copy; ++ /* always need to copy buffer when forward=0 to get enough headrom for tsdesc */ ++ skb_copy = skb_copy_expand(rx_skb, sizeof(struct rwnx_txhdr) + ++ RWNX_SWTXHDR_ALIGN_SZ + 3 + 24 + 8, 0, GFP_ATOMIC); ++ ++ if (skb_copy) { ++ int res; ++ skb_copy->protocol = htons(ETH_P_802_3); ++ skb_reset_network_header(skb_copy); ++ skb_reset_mac_header(skb_copy); ++ ++ rwnx_vif->is_resending = true; ++ res = dev_queue_xmit(skb_copy); ++ rwnx_vif->is_resending = false; ++ /* note: buffer is always consummed by dev_queue_xmit */ ++ if (res == NET_XMIT_DROP) { ++ rwnx_vif->net_stats.rx_dropped++; ++ rwnx_vif->net_stats.tx_dropped++; ++ } else if (res != NET_XMIT_SUCCESS) { ++ netdev_err(rwnx_vif->ndev, ++ "Failed to re-send buffer to driver (res=%d)", ++ res); ++ rwnx_vif->net_stats.tx_errors++; ++ } ++ } else { ++ netdev_err(rwnx_vif->ndev, "Failed to copy skb"); ++ } ++ } ++ ++ /* forward pkt to upper layer */ ++ if (forward) { ++ #ifdef CONFIG_BR_SUPPORT ++ void *br_port = NULL; ++ ++ if (1) {//(check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ /* Insert NAT2.5 RX here! */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb); ++ ++ if (nat25_handle_frame(rwnx_vif, rx_skb) == -1) { ++ /* priv->ext_stats.rx_data_drops++; */ ++ /* DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); */ ++ /* return FAIL; */ ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ /* Update statistics */ ++ rwnx_vif->net_stats.rx_packets++; ++ rwnx_vif->net_stats.rx_bytes += rx_skb->len; ++ ++ rx_skb->protocol = eth_type_trans(rx_skb, rwnx_vif->ndev); ++#ifdef AICWF_ARP_OFFLOAD ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) ++ arpoffload_proc(rx_skb, rwnx_vif); ++#endif ++ memset(rx_skb->cb, 0, sizeof(rx_skb->cb)); ++ REG_SW_SET_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_hw,rx_skb->data, cpu_to_le16(rx_skb->len)); ++#endif ++ ++ #ifdef CONFIG_RX_NETIF_RECV_SKB //modify by aic ++ local_bh_disable(); ++ netif_receive_skb(rx_skb); ++ local_bh_enable(); ++ #else ++ if (in_interrupt()) { ++ netif_rx(rx_skb); ++ } else { ++ /* ++ * If the receive is not processed inside an ISR, the softirqd must be woken explicitly to service the NET_RX_SOFTIRQ. ++ * * In 2.6 kernels, this is handledby netif_rx_ni(), but in earlier kernels, we need to do it manually. ++ */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(rx_skb); ++ #else ++ ulong flags; ++ netif_rx(rx_skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++ #endif ++ } ++ #endif ++ REG_SW_CLEAR_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++ rwnx_hw->stats.last_rx = jiffies; ++ } ++ } ++ ++ return forward; ++} ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) ++const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len, ++ const u8 *match, int match_len, ++ int match_offset) ++{ ++ const struct element *elem; ++ ++ /* 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; ++ ++ for_each_element_id(elem, eid, ies, len) { ++ if (elem->datalen >= match_offset - 2 + match_len && ++ !memcmp(elem->data + match_offset - 2, match, match_len)) ++ return (void *)elem; ++ } ++ ++ return NULL; ++} ++#endif ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) ++static inline const u8 *cfg80211_find_ext_ie(u8 ext_eid, const u8* ies, int len) ++{ ++ return cfg80211_find_ie_match(WLAN_EID_EXTENSION, ies, len, ++ &ext_eid, 1, 2); ++} ++#endif ++#endif ++ ++ ++/** ++ * rwnx_rx_mgmt - Process one 802.11 management frame ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: vif to upload the buffer to ++ * @skb: skb received ++ * @rxhdr: HW rx descriptor ++ * ++ * Forward the management frame to a given interface. ++ */ ++static void rwnx_rx_mgmt(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *hw_rxhdr) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; ++ struct rx_vector_1 *rxvect = &hw_rxhdr->hwvect.rx_vect1; ++ ++ //printk("rwnx_rx_mgmt\n"); ++ ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ struct aic_sta *sta = &rwnx_hw->aic_table[rwnx_vif->ap.aic_index]; ++ const u8* ie; ++ u32 len; ++ ++ if(skb->data[0]!=0x80) ++ AICWFDBG(LOGDEBUG,"rxmgmt:%x,%x\n", skb->data[0], skb->data[1]); ++ ++ if (ieee80211_is_assoc_req(mgmt->frame_control) && rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) { ++ printk("ASSOC_REQ: sta_idx %d MAC %pM\n", rwnx_vif->ap.aic_index, mgmt->sa); ++ sta->sta_idx = rwnx_vif->ap.aic_index; ++ len = skb->len - (mgmt->u.assoc_req.variable - skb->data); ++ ++ #ifdef CONFIG_HE_FOR_OLD_KERNEL ++ struct ieee80211_he_cap_elem *he; ++ struct ieee80211_he_mcs_nss_supp *he_mcs; ++ ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, mgmt->u.assoc_req.variable, len); ++ if (ie && ie[1] >= sizeof(*he) + 1) { ++ printk("assoc_req: find he\n"); ++ he = (struct ieee80211_he_cap_elem *)(ie+3); ++ he_mcs = (struct ieee80211_he_mcs_nss_supp *)((u8 *)he + sizeof(*he)); ++ memcpy(&sta->he_cap_elem,ie+3,sizeof(struct ieee80211_he_cap_elem)); ++ ++ sta->he_mcs_nss_supp.rx_mcs_80 = he_mcs->rx_mcs_80; ++ sta->he_mcs_nss_supp.tx_mcs_80 = he_mcs->tx_mcs_80; ++ sta->he = true; ++ } ++ else { ++ printk("assoc_req: no find he\n"); ++ sta->he = false; ++ } ++ #endif ++ ++ #ifdef CONFIG_VHT_FOR_OLD_KERNEL ++ struct ieee80211_vht_cap *vht; ++ ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.assoc_req.variable, len); ++ if (ie && ie[1] >= sizeof(*vht)) { ++ printk("assoc_req: find vht\n"); ++ memcpy(&sta->vht_cap_info,ie+2,4); ++ memcpy(&sta->supp_mcs,ie+2+4,sizeof(struct ieee80211_vht_mcs_info)); ++ sta->vht = true; ++ } else { ++ printk("assoc_req: no find vht\n"); ++ sta->vht = false; ++ } ++ #endif ++ } ++#endif ++ ++ /*if (ieee80211_is_mgmt(mgmt->frame_control) && ++ (skb->len <= 24 || skb->len > 768)) { ++ printk("mgmt err\n"); ++ return; ++ }*/ ++ if (ieee80211_is_beacon(mgmt->frame_control)) { ++ if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT) && ++ hw_rxhdr->flags_new_peer) { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ GFP_ATOMIC); ++#else ++ cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ GFP_ATOMIC); ++#endif ++#else ++ ++#ifdef CONFIG_GKI ++ /* TODO: the value of parameter sig_dbm need to be confirmed */ ++ rwnx_cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ rxvect->rssi1, GFP_ATOMIC); ++#else ++ /* TODO: the value of parameter sig_dbm need to be confirmed */ ++ cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ rxvect->rssi1, GFP_ATOMIC); ++#endif ++ ++#endif ++ } else { ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_report_obss_beacon(rwnx_hw->wiphy, skb->data, skb->len, ++ hw_rxhdr->phy_info.phy_prim20_freq, ++ rxvect->rssi1); ++#else ++ cfg80211_report_obss_beacon(rwnx_hw->wiphy, skb->data, skb->len, ++ hw_rxhdr->phy_info.phy_prim20_freq, ++ rxvect->rssi1); ++#endif ++ } ++ } else if ((ieee80211_is_deauth(mgmt->frame_control) || ++ ieee80211_is_disassoc(mgmt->frame_control)) && ++ (mgmt->u.deauth.reason_code == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA || ++ mgmt->u.deauth.reason_code == WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)) { ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) // TODO: process unprot mgmt ++ cfg80211_rx_unprot_mlme_mgmt(rwnx_vif->ndev, skb->data, skb->len); ++ #endif ++ } else if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION) && ++ (ieee80211_is_action(mgmt->frame_control) && ++ (mgmt->u.action.category == 6))) { ++ struct cfg80211_ft_event_params ft_event; ++ ft_event.target_ap = (uint8_t *)&mgmt->u.action + ETH_ALEN + 2; ++ ft_event.ies = (uint8_t *)&mgmt->u.action + ETH_ALEN * 2 + 2; ++ ft_event.ies_len = skb->len - (ft_event.ies - (uint8_t *)mgmt); ++ ft_event.ric_ies = NULL; ++ ft_event.ric_ies_len = 0; ++ cfg80211_ft_event(rwnx_vif->ndev, &ft_event); ++ } else { ++ cfg80211_rx_mgmt(&rwnx_vif->wdev, hw_rxhdr->phy_info.phy_prim20_freq, ++ rxvect->rssi1, skb->data, skb->len, 0); ++ } ++} ++ ++/** ++ * rwnx_rx_mgmt_any - Process one 802.11 management frame ++ * ++ * @rwnx_hw: main driver data ++ * @skb: skb received ++ * @rxhdr: HW rx descriptor ++ * ++ * Process the management frame and free the corresponding skb. ++ * If vif is not specified in the rx descriptor, the the frame is uploaded ++ * on all active vifs. ++ */ ++static void rwnx_rx_mgmt_any(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, ++ struct hw_rxhdr *hw_rxhdr) ++{ ++ struct rwnx_vif *rwnx_vif; ++ int vif_idx = hw_rxhdr->flags_vif_idx; ++#ifdef CREATE_TRACE_POINTS ++ trace_mgmt_rx(hw_rxhdr->phy_info.phy_prim20_freq, vif_idx, ++ hw_rxhdr->flags_sta_idx, (struct ieee80211_mgmt *)skb->data); ++#endif ++ if (vif_idx == RWNX_INVALID_VIF) { ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (!rwnx_vif->up) ++ continue; ++ rwnx_rx_mgmt(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } ++ } else { ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, vif_idx); ++ if (rwnx_vif) ++ rwnx_rx_mgmt(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } ++ ++ dev_kfree_skb(skb); ++} ++ ++/** ++ * rwnx_rx_rtap_hdrlen - Return radiotap header length ++ * ++ * @rxvect: Rx vector used to fill the radiotap header ++ * @has_vend_rtap: boolean indicating if vendor specific data is present ++ * ++ * Compute the length of the radiotap header based on @rxvect and vendor ++ * specific data (if any). ++ */ ++static u8 rwnx_rx_rtap_hdrlen(struct rx_vector_1 *rxvect, ++ bool has_vend_rtap) ++{ ++ u8 rtap_len; ++ ++ /* Compute radiotap header length */ ++ rtap_len = sizeof(struct ieee80211_radiotap_header) + 8; ++ ++ // Check for multiple antennas ++ if (hweight32(rxvect->antenna_set) > 1) ++ // antenna and antenna signal fields ++ rtap_len += 4 * hweight8(rxvect->antenna_set); ++ ++ // TSFT ++ if (!has_vend_rtap) { ++ rtap_len = ALIGN(rtap_len, 8); ++ rtap_len += 8; ++ } ++ ++ // IEEE80211_HW_SIGNAL_DBM ++ rtap_len++; ++ ++ // Check if single antenna ++ if (hweight32(rxvect->antenna_set) == 1) ++ rtap_len++; //Single antenna ++ ++ // padding for RX FLAGS ++ rtap_len = ALIGN(rtap_len, 2); ++ ++ // Check for HT frames ++ if ((rxvect->format_mod == FORMATMOD_HT_MF) || ++ (rxvect->format_mod == FORMATMOD_HT_GF)) ++ rtap_len += 3; ++ ++ // Check for AMPDU ++ if (!(has_vend_rtap) && ((rxvect->format_mod >= FORMATMOD_VHT) || ++ ((rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) && ++ (rxvect->ht.aggregation)))) { ++ rtap_len = ALIGN(rtap_len, 4); ++ rtap_len += 8; ++ } ++ ++ // Check for VHT frames ++ if (rxvect->format_mod == FORMATMOD_VHT) { ++ rtap_len = ALIGN(rtap_len, 2); ++ rtap_len += 12; ++ } ++ ++ // Check for HE frames ++ if (rxvect->format_mod == FORMATMOD_HE_SU) { ++ rtap_len = ALIGN(rtap_len, 2); ++ rtap_len += sizeof(struct ieee80211_radiotap_he); ++ } ++ ++ // Check for multiple antennas ++ if (hweight32(rxvect->antenna_set) > 1) { ++ // antenna and antenna signal fields ++ rtap_len += 2 * hweight8(rxvect->antenna_set); ++ } ++ ++ // Check for vendor specific data ++ if (has_vend_rtap) { ++ /* vendor presence bitmap */ ++ rtap_len += 4; ++ /* alignment for fixed 6-byte vendor data header */ ++ rtap_len = ALIGN(rtap_len, 2); ++ } ++ ++ return rtap_len; ++} ++ ++/** ++ * rwnx_rx_add_rtap_hdr - Add radiotap header to sk_buff ++ * ++ * @rwnx_hw: main driver data ++ * @skb: skb received (will include the radiotap header) ++ * @rxvect: Rx vector ++ * @phy_info: Information regarding the phy ++ * @hwvect: HW Info (NULL if vendor specific data is available) ++ * @rtap_len: Length of the radiotap header ++ * @vend_rtap_len: radiotap vendor length (0 if not present) ++ * @vend_it_present: radiotap vendor present ++ * ++ * Builds a radiotap header and add it to @skb. ++ */ ++static void rwnx_rx_add_rtap_hdr(struct rwnx_hw *rwnx_hw, ++ struct sk_buff *skb, ++ struct rx_vector_1 *rxvect, ++ struct phy_channel_info_desc *phy_info, ++ struct hw_vect *hwvect, ++ int rtap_len, ++ u8 vend_rtap_len, ++ u32 vend_it_present) ++{ ++ struct ieee80211_radiotap_header *rtap; ++ u8 *pos, rate_idx; ++ __le32 *it_present; ++ u32 it_present_val = 0; ++ bool fec_coding = false; ++ bool short_gi = false; ++ bool stbc = false; ++ bool aggregation = false; ++ ++ rtap = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); ++ memset((u8 *) rtap, 0, rtap_len); ++ ++ rtap->it_version = 0; ++ rtap->it_pad = 0; ++ rtap->it_len = cpu_to_le16(rtap_len + vend_rtap_len); ++ ++ it_present = &rtap->it_present; ++ ++ // Check for multiple antennas ++ if (hweight32(rxvect->antenna_set) > 1) { ++ int chain; ++ unsigned long chains = rxvect->antenna_set; ++ ++ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { ++ it_present_val |= ++ BIT(IEEE80211_RADIOTAP_EXT) | ++ BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE); ++ put_unaligned_le32(it_present_val, it_present); ++ it_present++; ++ it_present_val = BIT(IEEE80211_RADIOTAP_ANTENNA) | ++ BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); ++ } ++ } ++ ++ // Check if vendor specific data is present ++ if (vend_rtap_len) { ++ it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | ++ BIT(IEEE80211_RADIOTAP_EXT); ++ put_unaligned_le32(it_present_val, it_present); ++ it_present++; ++ it_present_val = vend_it_present; ++ } ++ ++ put_unaligned_le32(it_present_val, it_present); ++ pos = (void *)(it_present + 1); ++ ++ // IEEE80211_RADIOTAP_TSFT ++ if (hwvect) { ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); ++ // padding ++ while ((pos - (u8 *)rtap) & 7) ++ *pos++ = 0; ++ put_unaligned_le64((((u64)le32_to_cpu(hwvect->tsf_hi) << 32) + ++ (u64)le32_to_cpu(hwvect->tsf_lo)), pos); ++ pos += 8; ++ } ++ ++ // IEEE80211_RADIOTAP_FLAGS ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_FLAGS); ++ if (hwvect && (!hwvect->frm_successful_rx)) ++ *pos |= IEEE80211_RADIOTAP_F_BADFCS; ++ if (!rxvect->pre_type ++ && (rxvect->format_mod <= FORMATMOD_NON_HT_DUP_OFDM)) ++ *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; ++ pos++; ++ ++ // IEEE80211_RADIOTAP_RATE ++ // check for HT, VHT or HE frames ++ if (rxvect->format_mod >= FORMATMOD_HE_SU) { ++ rate_idx = rxvect->he.mcs; ++ fec_coding = rxvect->he.fec; ++ stbc = rxvect->he.stbc; ++ aggregation = true; ++ *pos = 0; ++ } else if (rxvect->format_mod == FORMATMOD_VHT) { ++ rate_idx = rxvect->vht.mcs; ++ fec_coding = rxvect->vht.fec; ++ short_gi = rxvect->vht.short_gi; ++ stbc = rxvect->vht.stbc; ++ aggregation = true; ++ *pos = 0; ++ } else if (rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) { ++ rate_idx = rxvect->ht.mcs; ++ fec_coding = rxvect->ht.fec; ++ short_gi = rxvect->ht.short_gi; ++ stbc = rxvect->ht.stbc; ++ aggregation = rxvect->ht.aggregation; ++ *pos = 0; ++ } else { ++ struct ieee80211_supported_band *band = ++ rwnx_hw->wiphy->bands[phy_info->phy_band]; ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); ++ BUG_ON((rate_idx = legrates_lut[rxvect->leg_rate].idx) == -1); ++ if (phy_info->phy_band == NL80211_BAND_5GHZ) ++ rate_idx -= 4; /* rwnx_ratetable_5ghz[0].hw_value == 4 */ ++ *pos = DIV_ROUND_UP(band->bitrates[rate_idx].bitrate, 5); ++ } ++ pos++; ++ ++ // IEEE80211_RADIOTAP_CHANNEL ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CHANNEL); ++ put_unaligned_le16(phy_info->phy_prim20_freq, pos); ++ pos += 2; ++ ++ if (phy_info->phy_band == NL80211_BAND_5GHZ) ++ put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, pos); ++ else if (rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) ++ put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, pos); ++ else ++ put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, pos); ++ pos += 2; ++ ++ if (hweight32(rxvect->antenna_set) == 1) { ++ // IEEE80211_RADIOTAP_DBM_ANTSIGNAL ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); ++ *pos++ = rxvect->rssi1; ++ ++ // IEEE80211_RADIOTAP_ANTENNA ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_ANTENNA); ++ *pos++ = rxvect->antenna_set; ++ } ++ ++ // IEEE80211_RADIOTAP_LOCK_QUALITY is missing ++ // IEEE80211_RADIOTAP_DB_ANTNOISE is missing ++ ++ // IEEE80211_RADIOTAP_RX_FLAGS ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RX_FLAGS); ++ // 2 byte alignment ++ if ((pos - (u8 *)rtap) & 1) ++ *pos++ = 0; ++ put_unaligned_le16(0, pos); ++ //Right now, we only support fcs error (no RX_FLAG_FAILED_PLCP_CRC) ++ pos += 2; ++ ++ // Check if HT ++ if ((rxvect->format_mod == FORMATMOD_HT_MF) ++ || (rxvect->format_mod == FORMATMOD_HT_GF)) { ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); ++ *pos++ = IEEE80211_RADIOTAP_MCS_HAVE_MCS | ++ IEEE80211_RADIOTAP_MCS_HAVE_GI | ++ IEEE80211_RADIOTAP_MCS_HAVE_BW; ++ *pos = 0; ++ if (short_gi) ++ *pos |= IEEE80211_RADIOTAP_MCS_SGI; ++ if (rxvect->ch_bw == PHY_CHNL_BW_40) ++ *pos |= IEEE80211_RADIOTAP_MCS_BW_40; ++ if (rxvect->format_mod == FORMATMOD_HT_GF) ++ *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; ++ if (fec_coding) ++ *pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC; ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ *pos++ |= stbc << 5; ++ #else ++ *pos++ |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; ++ #endif ++ *pos++ = rate_idx; ++ } ++ ++ // check for HT or VHT frames ++ if (aggregation && hwvect) { ++ // 4 byte alignment ++ while ((pos - (u8 *)rtap) & 3) ++ pos++; ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); ++ put_unaligned_le32(hwvect->ampdu_cnt, pos); ++ pos += 4; ++ put_unaligned_le32(0, pos); ++ pos += 4; ++ } ++ ++ // Check for VHT frames ++ if (rxvect->format_mod == FORMATMOD_VHT) { ++ u16 vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | ++ IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; ++ u8 vht_nss = rxvect->vht.nss + 1; ++ ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); ++ ++ if ((rxvect->ch_bw == PHY_CHNL_BW_160) ++ && phy_info->phy_center2_freq) ++ vht_details &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; ++ put_unaligned_le16(vht_details, pos); ++ pos += 2; ++ ++ // flags ++ if (short_gi) ++ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; ++ if (stbc) ++ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; ++ pos++; ++ ++ // bandwidth ++ if (rxvect->ch_bw == PHY_CHNL_BW_40) ++ *pos++ = 1; ++ if (rxvect->ch_bw == PHY_CHNL_BW_80) ++ *pos++ = 4; ++ else if ((rxvect->ch_bw == PHY_CHNL_BW_160) ++ && phy_info->phy_center2_freq) ++ *pos++ = 0; //80P80 ++ else if (rxvect->ch_bw == PHY_CHNL_BW_160) ++ *pos++ = 11; ++ else // 20 MHz ++ *pos++ = 0; ++ ++ // MCS/NSS ++ *pos = (rate_idx << 4) | vht_nss; ++ pos += 4; ++ if (fec_coding) ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++ *pos |= 0x01; ++ #else ++ *pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0; ++ #endif ++ pos++; ++ // group ID ++ pos++; ++ // partial_aid ++ pos += 2; ++ } ++ ++ // Check for HE frames ++ if (rxvect->format_mod == FORMATMOD_HE_SU) { ++ struct ieee80211_radiotap_he he; ++ #define HE_PREP(f, val) cpu_to_le16(FIELD_PREP(IEEE80211_RADIOTAP_HE_##f, val)) ++ #define D1_KNOWN(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_##f##_KNOWN) ++ #define D2_KNOWN(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_##f##_KNOWN) ++ ++ he.data1 = D1_KNOWN(DATA_MCS) | D1_KNOWN(BSS_COLOR) | D1_KNOWN(BEAM_CHANGE) | ++ D1_KNOWN(UL_DL) | D1_KNOWN(CODING) | D1_KNOWN(STBC) | ++ D1_KNOWN(BW_RU_ALLOC) | D1_KNOWN(DOPPLER) | D1_KNOWN(DATA_DCM); ++ he.data2 = D2_KNOWN(GI) | D2_KNOWN(TXBF); ++ ++ if (stbc) { ++ he.data6 |= HE_PREP(DATA6_NSTS, 2); ++ he.data3 |= HE_PREP(DATA3_STBC, 1); ++ } else { ++ he.data6 |= HE_PREP(DATA6_NSTS, rxvect->he.nss); ++ } ++ ++ he.data3 |= HE_PREP(DATA3_BSS_COLOR, rxvect->he.bss_color); ++ he.data3 |= HE_PREP(DATA3_BEAM_CHANGE, rxvect->he.beam_change); ++ he.data3 |= HE_PREP(DATA3_UL_DL, rxvect->he.uplink_flag); ++ he.data3 |= HE_PREP(DATA3_BSS_COLOR, rxvect->he.bss_color); ++ he.data3 |= HE_PREP(DATA3_DATA_MCS, rxvect->he.mcs); ++ he.data3 |= HE_PREP(DATA3_DATA_DCM, rxvect->he.dcm); ++ he.data3 |= HE_PREP(DATA3_CODING, rxvect->he.fec); ++ ++ he.data5 |= HE_PREP(DATA5_GI, rxvect->he.gi_type); ++ he.data5 |= HE_PREP(DATA5_TXBF, rxvect->he.beamformed); ++ he.data5 |= HE_PREP(DATA5_LTF_SIZE, rxvect->he.he_ltf_type + 1); ++ ++ switch (rxvect->ch_bw) { ++ case PHY_CHNL_BW_20: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ); ++ break; ++ case PHY_CHNL_BW_40: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ); ++ break; ++ case PHY_CHNL_BW_80: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ); ++ break; ++ case PHY_CHNL_BW_160: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ); ++ break; ++ default: ++ WARN_ONCE(1, "Invalid SU BW %d\n", rxvect->ch_bw); ++ } ++ ++ he.data6 |= HE_PREP(DATA6_DOPPLER, rxvect->he.doppler); ++ ++ /* ensure 2 byte alignment */ ++ while ((pos - (u8 *)rtap) & 1) ++ pos++; ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE); ++ memcpy(pos, &he, sizeof(he)); ++ pos += sizeof(he); ++ } ++ ++ // Rx Chains ++ if (hweight32(rxvect->antenna_set) > 1) { ++ int chain; ++ unsigned long chains = rxvect->antenna_set; ++ u8 rssis[4] = {rxvect->rssi1, rxvect->rssi1, rxvect->rssi1, rxvect->rssi1}; ++ ++ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { ++ *pos++ = rssis[chain]; ++ *pos++ = chain; ++ } ++ } ++} ++ ++/** ++ * rwnx_rx_monitor - Build radiotap header for skb an send it to netdev ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: vif that received the buffer ++ * @skb: sk_buff received ++ * @hw_rxhdr_ptr: Pointer to HW RX header ++ * @rtap_len: Radiotap Header length ++ * ++ * Add radiotap header to the receved skb and send it to netdev ++ */ ++static int rwnx_rx_monitor(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *hw_rxhdr_ptr, ++ u8 rtap_len) ++{ ++ skb->dev = rwnx_vif->ndev; ++ ++ if (rwnx_vif->wdev.iftype != NL80211_IFTYPE_MONITOR) { ++ netdev_err(rwnx_vif->ndev, "not a monitor vif\n"); ++ return -1; ++ } ++ ++ /* Add RadioTap Header */ ++ rwnx_rx_add_rtap_hdr(rwnx_hw, skb, &hw_rxhdr_ptr->hwvect.rx_vect1, ++ &hw_rxhdr_ptr->phy_info, &hw_rxhdr_ptr->hwvect, ++ rtap_len, 0, 0); ++ ++ skb_reset_mac_header(skb); ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ skb->pkt_type = PACKET_OTHERHOST; ++ skb->protocol = htons(ETH_P_802_2); ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_hw,skb->data, cpu_to_le16(skb->len)); ++#endif ++ ++ local_bh_disable(); ++ netif_receive_skb(skb); ++ local_bh_enable(); ++ ++ return 0; ++} ++ ++#ifdef AICWF_ARP_OFFLOAD ++void arpoffload_proc(struct sk_buff *skb, struct rwnx_vif *rwnx_vif) ++{ ++ struct iphdr *iphead = (struct iphdr *)(skb->data); ++ struct udphdr *udph; ++ struct DHCPInfo *dhcph; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { // IP ++ if (iphead->protocol == IPPROTO_UDP) { // UDP ++ udph = (struct udphdr *)((u8 *)iphead + (iphead->ihl << 2)); ++ if ((udph->source == __constant_htons(SERVER_PORT)) ++ && (udph->dest == __constant_htons(CLIENT_PORT))) { // DHCP offset/ack ++ dhcph = (struct DHCPInfo *)((u8 *)udph + sizeof(struct udphdr)); ++ if (dhcph->cookie == htonl(DHCP_MAGIC) && dhcph->op == 2 && ++ !memcmp(dhcph->chaddr, rwnx_vif->ndev->dev_addr, 6)) { // match magic word ++ u32 length = ntohs(udph->len) - sizeof(struct udphdr) - offsetof(struct DHCPInfo, options); ++ u16 offset = 0; ++ u8 *option = dhcph->options; ++ while (option[offset] != DHCP_OPTION_END && offset < length) { ++ if (option[offset] == DHCP_OPTION_MESSAGE_TYPE) { ++ if (option[offset+2] == DHCP_ACK) { ++ dhcped = 1; ++ AICWFDBG(LOGINFO, "paired=%x, should=%x\n", rwnx_vif->sta.paired_cipher_type, WLAN_CIPHER_SUITE_CCMP); ++ if (rwnx_vif->sta.paired_cipher_type == WLAN_CIPHER_SUITE_CCMP || \ ++ rwnx_vif->sta.paired_cipher_type == WLAN_CIPHER_SUITE_AES_CMAC || \ ++ ((rwnx_vif->sta.group_cipher_type == 0xff) && \ ++ (rwnx_vif->sta.paired_cipher_type == 0xff))) ++ rwnx_send_arpoffload_en_req(rwnx_vif->rwnx_hw, rwnx_vif, dhcph->yiaddr, 1); ++ else ++ rwnx_send_arpoffload_en_req(rwnx_vif->rwnx_hw, rwnx_vif, dhcph->yiaddr, 0); ++ } ++ } ++ offset += 2 + option[offset+1]; ++ } ++ } ++ } ++ } ++ } ++} ++#endif ++ ++#ifdef AICWF_RX_REORDER ++void reord_rxframe_free(spinlock_t *lock, struct list_head *q, struct list_head *list) ++{ ++ spin_lock_bh(lock); ++ list_add(list, q); ++ spin_unlock_bh(lock); ++} ++ ++struct recv_msdu *reord_rxframe_alloc(spinlock_t *lock, struct list_head *q) ++{ ++ struct recv_msdu *rxframe; ++ ++ spin_lock_bh(lock); ++ if (list_empty(q)) { ++ spin_unlock_bh(lock); ++ return NULL; ++ } ++ rxframe = list_entry(q->next, struct recv_msdu, rxframe_list); ++ list_del_init(q->next); ++ spin_unlock_bh(lock); ++ return rxframe; ++} ++ ++struct reord_ctrl_info *reord_init_sta(struct aicwf_rx_priv *rx_priv, const u8 *mac_addr) ++{ ++ u8 i = 0; ++ struct reord_ctrl *preorder_ctrl = NULL; ++ struct reord_ctrl_info *reord_info; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++#else ++ struct aicwf_bus *bus_if = rx_priv->usbdev->bus_if; ++#endif ++ ++ if (bus_if->state == BUS_DOWN_ST || rx_priv == NULL) { ++ AICWFDBG(LOGERROR, "bad stat!\n"); ++ return NULL; ++ } ++ ++ AICWFDBG(LOGINFO, "reord_init_sta:%pM\n", mac_addr); ++ reord_info = kmalloc(sizeof(struct reord_ctrl_info), GFP_ATOMIC); ++ if (!reord_info) ++ return NULL; ++ ++ memcpy(reord_info->mac_addr, mac_addr, ETH_ALEN); ++ for (i = 0; i < 8; i++) { ++ preorder_ctrl = &reord_info->preorder_ctrl[i]; ++ preorder_ctrl->enable = true; ++ preorder_ctrl->ind_sn = 0xffff; ++ preorder_ctrl->wsize_b = AICWF_REORDER_WINSIZE; ++ preorder_ctrl->rx_priv = rx_priv; ++ INIT_LIST_HEAD(&preorder_ctrl->reord_list); ++ spin_lock_init(&preorder_ctrl->reord_list_lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ init_timer(&preorder_ctrl->reord_timer); ++ preorder_ctrl->reord_timer.data = (ulong) preorder_ctrl; ++ preorder_ctrl->reord_timer.function = reord_timeout_handler; ++#else ++ timer_setup(&preorder_ctrl->reord_timer, reord_timeout_handler, 0); ++#endif ++ INIT_WORK(&preorder_ctrl->reord_timer_work, reord_timeout_worker); ++ } ++ ++ return reord_info; ++} ++ ++int reord_flush_tid(struct aicwf_rx_priv *rx_priv, struct sk_buff *skb, u8 tid) ++{ ++ struct reord_ctrl_info *reord_info; ++ struct reord_ctrl *preorder_ctrl; ++ struct rwnx_vif *rwnx_vif = (struct rwnx_vif *)rx_priv->rwnx_vif; ++ struct ethhdr *eh = (struct ethhdr *)(skb->data); ++ u8 *mac; ++ unsigned long flags; ++ u8 found = 0; ++ struct list_head *phead, *plist; ++ struct recv_msdu *prframe; ++ int ret; ++ ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) ++ mac = eh->h_dest; ++ else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) ++ mac = eh->h_source; ++ else { ++ AICWFDBG(LOGERROR, "error mode:%d!\n", rwnx_vif->wdev.iftype); ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry(reord_info, &rx_priv->stas_reord_list, list) { ++ if (!memcmp(mac, reord_info->mac_addr, ETH_ALEN)) { ++ found = 1; ++ preorder_ctrl = &reord_info->preorder_ctrl[tid]; ++ break; ++ } ++ } ++ if (!found) { ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ return 0; ++ } ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ ++ if (preorder_ctrl->enable == false) ++ return 0; ++ spin_lock_irqsave(&preorder_ctrl->reord_list_lock, flags); ++ phead = &preorder_ctrl->reord_list; ++ while (1) { ++ if (list_empty(phead)) { ++ break; ++ } ++ plist = phead->next; ++ prframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ reord_single_frame_ind(rx_priv, prframe); ++ list_del_init(&(prframe->reord_pending_list)); ++ } ++ ++ AICWFDBG(LOGINFO, "flush:tid=%d", tid); ++ preorder_ctrl->enable = false; ++ spin_unlock_irqrestore(&preorder_ctrl->reord_list_lock, flags); ++ if (timer_pending(&preorder_ctrl->reord_timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete_sync(&preorder_ctrl->reord_timer); ++#else ++ ret = del_timer_sync(&preorder_ctrl->reord_timer); ++#endif ++ cancel_work_sync(&preorder_ctrl->reord_timer_work); ++ ++ return 0; ++} ++ ++ ++void reord_deinit_sta(struct aicwf_rx_priv *rx_priv, struct reord_ctrl_info *reord_info) ++{ ++ u8 i = 0; ++ unsigned long flags; ++ struct reord_ctrl *preorder_ctrl = NULL; ++ int ret; ++ ++ if (rx_priv == NULL) { ++ txrx_err("bad rx_priv!\n"); ++ return; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ struct recv_msdu *req, *next; ++ preorder_ctrl = &reord_info->preorder_ctrl[i]; ++ if(preorder_ctrl->enable){ ++ preorder_ctrl->enable = false; ++ if (timer_pending(&preorder_ctrl->reord_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete_sync(&preorder_ctrl->reord_timer); ++#else ++ ret = del_timer_sync(&preorder_ctrl->reord_timer); ++#endif ++ } ++ cancel_work_sync(&preorder_ctrl->reord_timer_work); ++ } ++ spin_lock_irqsave(&preorder_ctrl->reord_list_lock, flags); ++ list_for_each_entry_safe(req, next, &preorder_ctrl->reord_list, reord_pending_list) { ++ list_del_init(&req->reord_pending_list); ++ if (req->pkt != NULL) ++ dev_kfree_skb(req->pkt); ++ req->pkt = NULL; ++ reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &req->rxframe_list); ++ } ++ spin_unlock_irqrestore(&preorder_ctrl->reord_list_lock, flags); ++ ++ } ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_del(&reord_info->list); ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ kfree(reord_info); ++} ++ ++int reord_single_frame_ind(struct aicwf_rx_priv *rx_priv, struct recv_msdu *prframe) ++{ ++ struct list_head *rxframes_freequeue = NULL; ++ struct sk_buff *skb = NULL; ++ struct rwnx_vif *rwnx_vif = (struct rwnx_vif *)rx_priv->rwnx_vif; ++ struct sk_buff_head list; ++ struct sk_buff *rx_skb; ++ ++ rxframes_freequeue = &rx_priv->rxframes_freequeue; ++ skb = prframe->pkt; ++ ++ #ifdef CONFIG_BR_SUPPORT ++ void *br_port = NULL; ++ ++ if (1) {//(check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ /* Insert NAT2.5 RX here! */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb); ++ ++ if (nat25_handle_frame(rwnx_vif, skb) == -1) { ++ /* priv->ext_stats.rx_data_drops++; */ ++ /* DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); */ ++ /* return FAIL; */ ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ if (skb == NULL) { ++ txrx_err("skb is NULL\n"); ++ return -1; ++ } ++ ++ if(!prframe->forward) { ++ //printk("single: %d not forward: drop\n", prframe->seq_num); ++ dev_kfree_skb(skb); ++ prframe->pkt = NULL; ++ reord_rxframe_free(&rx_priv->freeq_lock, rxframes_freequeue, &prframe->rxframe_list); ++ return 0; ++ } ++ ++ //skb->data = prframe->rx_data; ++ //skb_set_tail_pointer(skb, prframe->len); ++ //skb->len = prframe->len; ++ __skb_queue_head_init(&list); ++ //printk("sg:%d\n", prframe->is_amsdu); ++ if(prframe->is_amsdu) { ++ rwnx_rxdata_process_amsdu(rwnx_vif->rwnx_hw, skb, rwnx_vif->vif_index, &list); //rxhdr not used below since skb free! ++ } else { ++ __skb_queue_head(&list, skb); ++ } ++ ++ ++ while (!skb_queue_empty(&list)) { ++ rx_skb = __skb_dequeue(&list); ++ ++ rwnx_vif->net_stats.rx_packets++; ++ rwnx_vif->net_stats.rx_bytes += rx_skb->len; ++ //printk("netif sn=%d, len=%d\n", precv_frame->attrib.seq_num, skb->len); ++ ++ rx_skb->dev = rwnx_vif->ndev; ++ rx_skb->protocol = eth_type_trans(rx_skb, rwnx_vif->ndev); ++ ++#ifdef AICWF_ARP_OFFLOAD ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ arpoffload_proc(rx_skb, rwnx_vif); ++ } ++#endif ++ memset(rx_skb->cb, 0, sizeof(rx_skb->cb)); ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_vif->rwnx_hw,rx_skb->data, cpu_to_le16(rx_skb->len)); ++#endif ++ ++#ifdef CONFIG_RX_NETIF_RECV_SKB//AIDEN test ++ local_bh_disable(); ++ netif_receive_skb(rx_skb); ++ local_bh_enable(); ++#else ++ if (in_interrupt()) { ++ netif_rx(rx_skb); ++ } else { ++ /* ++ * If the receive is not processed inside an ISR, the softirqd must be woken explicitly to service the NET_RX_SOFTIRQ. ++ * * In 2.6 kernels, this is handledby netif_rx_ni(), but in earlier kernels, we need to do it manually. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(rx_skb); ++#else ++ ulong flags; ++ netif_rx(rx_skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++#endif ++ } ++#endif /* CONFIG_RX_NETIF_RECV_SKB */ ++ } ++ ++ prframe->pkt = NULL; ++ reord_rxframe_free(&rx_priv->freeq_lock, rxframes_freequeue, &prframe->rxframe_list); ++ ++ return 0; ++} ++ ++bool reord_rxframes_process(struct aicwf_rx_priv *rx_priv, struct reord_ctrl *preorder_ctrl, int bforced) ++{ ++ struct list_head *phead, *plist; ++ struct recv_msdu *prframe; ++ bool bPktInBuf = false; ++ ++ if (bforced == true) { ++ phead = &preorder_ctrl->reord_list; ++ if (list_empty(phead)) { ++ return false; ++ } ++ ++ plist = phead->next; ++ prframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ preorder_ctrl->ind_sn = prframe->seq_num; ++ } ++ ++ phead = &preorder_ctrl->reord_list; ++ if (list_empty(phead)) { ++ return bPktInBuf; ++ } ++ ++ list_for_each_entry(prframe, phead, reord_pending_list) { ++ if (!SN_LESS(preorder_ctrl->ind_sn, prframe->seq_num)) { ++ if (SN_EQUAL(preorder_ctrl->ind_sn, prframe->seq_num)) { ++ preorder_ctrl->ind_sn = (preorder_ctrl->ind_sn + 1) & 0xFFF; ++ } ++ } else { ++ bPktInBuf = true; ++ break; ++ } ++ } ++ ++ return bPktInBuf; ++} ++ ++void reord_rxframes_ind(struct aicwf_rx_priv *rx_priv, ++ struct reord_ctrl *preorder_ctrl) ++{ ++ struct list_head *phead, *plist; ++ struct recv_msdu *prframe; ++ ++ phead = &preorder_ctrl->reord_list; ++ while (1) { ++ //spin_lock_bh(&preorder_ctrl->reord_list_lock); ++ if (list_empty(phead)) { ++ // spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ break; ++ } ++ ++ plist = phead->next; ++ prframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ ++ if (!SN_LESS(preorder_ctrl->ind_sn, prframe->seq_num)) { ++ list_del_init(&(prframe->reord_pending_list)); ++ // spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ reord_single_frame_ind(rx_priv, prframe); ++ } else { ++ // spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ break; ++ } ++ } ++} ++ ++int reorder_timeout = REORDER_UPDATE_TIME; ++module_param(reorder_timeout, int, 0660); ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void reord_timeout_handler (ulong data) ++#else ++void reord_timeout_handler (struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct reord_ctrl *preorder_ctrl = (struct reord_ctrl *)data; ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ struct reord_ctrl *preorder_ctrl = timer_container_of(preorder_ctrl, t, reord_timer); ++#else ++ struct reord_ctrl *preorder_ctrl = from_timer(preorder_ctrl, t, reord_timer); ++#endif ++#endif ++ ++#if 0 //AIDEN ++ struct aicwf_rx_priv *rx_priv = preorder_ctrl->rx_priv; ++ ++ if (reord_rxframes_process(rx_priv, preorder_ctrl, true) == true) { ++ mod_timer(&preorder_ctrl->reord_timer, jiffies + msecs_to_jiffies(REORDER_UPDATE_TIME)); ++ } ++#endif ++ ++ if (!work_pending(&preorder_ctrl->reord_timer_work)) ++ schedule_work(&preorder_ctrl->reord_timer_work); ++} ++ ++void reord_timeout_worker(struct work_struct *work) ++{ ++ struct reord_ctrl *preorder_ctrl = container_of(work, struct reord_ctrl, reord_timer_work); ++ struct aicwf_rx_priv *rx_priv = preorder_ctrl->rx_priv; ++ ++ spin_lock_bh(&preorder_ctrl->reord_list_lock); ++#if 1//AIDEN ++ if (reord_rxframes_process(rx_priv, preorder_ctrl, true)==true) { ++ mod_timer(&preorder_ctrl->reord_timer, jiffies + msecs_to_jiffies(reorder_timeout/*REORDER_UPDATE_TIME*/)); ++ } ++#endif ++ ++ reord_rxframes_ind(rx_priv, preorder_ctrl); ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ ++ return ; ++} ++ ++int reord_process_unit(struct aicwf_rx_priv *rx_priv, struct sk_buff *skb, u16 seq_num, u8 tid, u8 forward, u8 is_amsdu) ++{ ++ int ret = 0; ++ u8 *mac; ++ struct recv_msdu *pframe; ++ struct reord_ctrl *preorder_ctrl; ++ struct reord_ctrl_info *reord_info; ++ struct rwnx_vif *rwnx_vif = (struct rwnx_vif *)rx_priv->rwnx_vif; ++ struct ethhdr *eh = (struct ethhdr *)(skb->data); ++ u8 *da = eh->h_dest; ++ u8 is_mcast = ((*da) & 0x01) ? 1 : 0; ++ ++ if (rwnx_vif == NULL || skb->len <= 14) { ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ pframe = reord_rxframe_alloc(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue); ++ if (!pframe) { ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ INIT_LIST_HEAD(&pframe->reord_pending_list); ++ pframe->seq_num = seq_num; ++ pframe->tid = tid; ++ pframe->rx_data = skb->data; ++ //pframe->len = skb->len; ++ pframe->pkt = skb; ++ pframe->forward = forward; ++ preorder_ctrl = pframe->preorder_ctrl; ++ pframe->is_amsdu = is_amsdu; ++ ++ if ((ntohs(eh->h_proto) == ETH_P_PAE) || is_mcast) ++ return reord_single_frame_ind(rx_priv, pframe); ++ ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) ++ mac = eh->h_dest; ++ else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) ++ mac = eh->h_source; ++ else { ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry(reord_info, &rx_priv->stas_reord_list, list) { ++ if (!memcmp(mac, reord_info->mac_addr, ETH_ALEN)) { ++ preorder_ctrl = &reord_info->preorder_ctrl[pframe->tid]; ++ break; ++ } ++ } ++ ++ if (&reord_info->list == &rx_priv->stas_reord_list) { ++ reord_info = reord_init_sta(rx_priv, mac); ++ if (!reord_info) { ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ list_add_tail(&reord_info->list, &rx_priv->stas_reord_list); ++ preorder_ctrl = &reord_info->preorder_ctrl[pframe->tid]; ++ } else { ++ if (preorder_ctrl->enable == false) { ++ preorder_ctrl->enable = true; ++ preorder_ctrl->ind_sn = 0xffff; ++ preorder_ctrl->wsize_b = AICWF_REORDER_WINSIZE; ++ preorder_ctrl->rx_priv = rx_priv; ++ } ++ } ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ ++ if (preorder_ctrl->enable == false) { ++ spin_lock_bh(&preorder_ctrl->reord_list_lock); ++ preorder_ctrl->ind_sn = pframe->seq_num; ++ reord_single_frame_ind(rx_priv, pframe); ++ preorder_ctrl->ind_sn = (preorder_ctrl->ind_sn + 1)%4096; ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ return 0; ++ } ++ ++ spin_lock_bh(&preorder_ctrl->reord_list_lock); ++ if (reord_need_check(preorder_ctrl, pframe->seq_num)) { ++#if 1 ++ if(pframe->rx_data[42] == 0x80){//this is rtp package ++ if(pframe->seq_num == preorder_ctrl->ind_sn){ ++ printk("%s pframe->seq_num1:%d \r\n", __func__, pframe->seq_num); ++ reord_single_frame_ind(rx_priv, pframe);//not need to reorder ++ }else{ ++ printk("%s free pframe->seq_num:%d \r\n", __func__, pframe->seq_num); ++ if (pframe->pkt){ ++ dev_kfree_skb(pframe->pkt); ++ pframe->pkt = NULL; ++ } ++ reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &pframe->rxframe_list); ++ } ++ }else{ ++ //printk("%s pframe->seq_num2:%d \r\n", __func__, pframe->seq_num); ++ reord_single_frame_ind(rx_priv, pframe);//not need to reorder ++ } ++#else ++ reord_single_frame_ind(rx_priv, pframe);//not need to reor ++#endif ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ return 0; ++ } ++ ++ if (reord_rxframe_enqueue(preorder_ctrl, pframe)) { ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ goto fail; ++ } ++ ++ if (reord_rxframes_process(rx_priv, preorder_ctrl, false) == true) { ++ if (!timer_pending(&preorder_ctrl->reord_timer)) { ++ ret = mod_timer(&preorder_ctrl->reord_timer, jiffies + msecs_to_jiffies(reorder_timeout/*REORDER_UPDATE_TIME*/)); ++ } ++ } else { ++ if (timer_pending(&preorder_ctrl->reord_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete(&preorder_ctrl->reord_timer); ++#else ++ ret = del_timer(&preorder_ctrl->reord_timer); ++#endif ++ } ++ } ++ ++ reord_rxframes_ind(rx_priv, preorder_ctrl); ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ ++ return 0; ++ ++fail: ++ if (pframe->pkt) { ++ dev_kfree_skb(pframe->pkt); ++ pframe->pkt = NULL; ++ } ++ reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &pframe->rxframe_list); ++ return ret; ++} ++ ++int reord_need_check(struct reord_ctrl *preorder_ctrl, u16 seq_num) ++{ ++ u8 wsize = preorder_ctrl->wsize_b; ++ u16 wend = (preorder_ctrl->ind_sn + wsize -1) & 0xFFF; ++ ++ if (preorder_ctrl->ind_sn == 0xFFFF) { ++ preorder_ctrl->ind_sn = seq_num; ++ } ++ ++ if (SN_LESS(seq_num, preorder_ctrl->ind_sn)) { ++ return -1; ++ } ++ ++ if (SN_EQUAL(seq_num, preorder_ctrl->ind_sn)) { ++ preorder_ctrl->ind_sn = (preorder_ctrl->ind_sn + 1) & 0xFFF; ++ } else if (SN_LESS(wend, seq_num)) { ++ if (seq_num >= (wsize-1)) ++ preorder_ctrl->ind_sn = seq_num-(wsize-1); ++ else ++ preorder_ctrl->ind_sn = 0xFFF - (wsize - (seq_num + 1)) + 1; ++ } ++ ++ return 0; ++} ++ ++int reord_rxframe_enqueue(struct reord_ctrl *preorder_ctrl, struct recv_msdu *prframe) ++{ ++ struct list_head *preord_list = &preorder_ctrl->reord_list; ++ struct list_head *phead, *plist; ++ struct recv_msdu *pnextrframe; ++ ++ phead = preord_list; ++ plist = phead->next; ++ ++ while (phead != plist) { ++ pnextrframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ if (SN_LESS(pnextrframe->seq_num, prframe->seq_num)) { ++ plist = plist->next; ++ continue; ++ } else if (SN_EQUAL(pnextrframe->seq_num, prframe->seq_num)) { ++ return -1; ++ } else { ++ break; ++ } ++ } ++ list_add_tail(&(prframe->reord_pending_list), plist); ++ ++ return 0; ++} ++#endif /* AICWF_RX_REORDER */ ++ ++void remove_sec_hdr_mgmt_frame(struct hw_rxhdr *hw_rxhdr, struct sk_buff *skb) ++{ ++ u8 hdr_len = 24; ++ u8 mgmt_header[24] = {0}; ++ ++ if (!hw_rxhdr->hwvect.ga_frame) { ++ if (((skb->data[0] & 0x0C) == 0) && (skb->data[1] & 0x40) == 0x40) { //protect management frame ++ printk("frame type %x\n", skb->data[0]); ++ if (hw_rxhdr->hwvect.decr_status == RWNX_RX_HD_DECR_CCMP128) { ++ memcpy(mgmt_header, skb->data, hdr_len); ++ skb_pull(skb, 8); ++ memcpy(skb->data, mgmt_header, hdr_len); ++ hw_rxhdr->hwvect.len -= 8; ++ } else { ++ printk("unsupport decr_status:%d\n", hw_rxhdr->hwvect.decr_status); ++ } ++ } ++ } ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++void defrag_timeout_cb(ulong data) ++#else ++void defrag_timeout_cb(struct timer_list *t) ++#endif ++{ ++ struct defrag_ctrl_info *defrag_ctrl = NULL; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ defrag_ctrl = (struct defrag_ctrl_info *)data; ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ defrag_ctrl = timer_container_of(defrag_ctrl, t, defrag_timer); ++#else ++ defrag_ctrl = from_timer(defrag_ctrl, t, defrag_timer); ++#endif ++#endif ++ ++ printk("%s:%p\r\n", __func__, defrag_ctrl); ++ spin_lock_bh(&defrag_ctrl->rwnx_hw->defrag_lock); ++ list_del_init(&defrag_ctrl->list); ++ dev_kfree_skb(defrag_ctrl->skb); ++ kfree(defrag_ctrl); ++ spin_unlock_bh(&defrag_ctrl->rwnx_hw->defrag_lock); ++} ++ ++void rwnx_rxdata_process_amsdu(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, u8 vif_idx, ++ struct sk_buff_head *list) ++{ ++ u16 len_alligned = 0; ++ u16 sublen = 0; ++ struct sk_buff *sub_skb = NULL; ++ struct rwnx_vif *rwnx_vif; ++ ++ //if (is_amsdu) ++ { ++ //skb_pull(skb, pull_len-8); ++ /* |amsdu sub1 | amsdu sub2 | ... */ ++ len_alligned = 0; ++ sublen = 0; ++ sub_skb = NULL; ++ while (skb->len > 16) { ++ sublen = (skb->data[12]<<8)|(skb->data[13]); ++ if (skb->len > (sublen+14)) ++ len_alligned = roundup(sublen + 14, 4); ++ else if (skb->len == (sublen+14)) ++ len_alligned = sublen+14; ++ else { ++ printk("accroding to amsdu: this will not happen\n"); ++ break; ++ } ++ //printk("sublen = %d, %x, %x, %x, %x\r\n", sublen,skb->data[0], skb->data[1], skb->data[12], skb->data[13]); ++#if 1 ++ sub_skb = __dev_alloc_skb(sublen - 6 + 12, GFP_ATOMIC); ++ if(!sub_skb){ ++ printk("sub_skb alloc fail:%d\n", sublen); ++ break; ++ } ++ skb_put(sub_skb, sublen - 6 + 12); ++ memcpy(sub_skb->data, skb->data, MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[6], &skb->data[6], MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[12], &skb->data[14 + 6], sublen - 6); ++ ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, vif_idx); ++ if (!rwnx_vif) { ++ printk("Frame received but no active vif (%d)", vif_idx); ++ //dev_kfree_skb(sub_skb); ++ break; ++ } ++ ++ __skb_queue_tail(list, sub_skb); ++ ++ //printk("a:%p\n", sub_skb); ++ //if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, sub_skb, hw_rxhdr)) ++ // dev_kfree_skb(sub_skb); ++#endif ++ skb_pull(skb, len_alligned); ++ } ++ //printk("af:%p\n", skb); ++ ++ dev_kfree_skb(skb); ++ //return 0; ++ } ++} ++ ++u8 rwnx_rxdataind_aicwf(struct rwnx_hw *rwnx_hw, void *hostid, void *rx_priv) ++{ ++ struct hw_rxhdr *hw_rxhdr; ++ struct rxdesc_tag *rxdesc = NULL; ++ struct rwnx_vif *rwnx_vif; ++ struct sk_buff *skb = hostid; ++ int msdu_offset = sizeof(struct hw_rxhdr) + 2; ++ u16_l status = 0; ++ struct aicwf_rx_priv *rx_priv_tmp; ++ u8 hdr_len = 24; ++ u8 ra[MAC_ADDR_LEN] = {0}; ++ u8 ta[MAC_ADDR_LEN] = {0}; ++ u8 ether_type[2] = {0}; ++ u8 pull_len = 0; ++ u16 seq_num = 0; ++ u8_l frag_num = 0; ++ u8 tid = 0; ++ u8 is_qos = 0; ++ u8 is_frag = 0; ++ struct defrag_ctrl_info *defrag_info = NULL; ++ struct defrag_ctrl_info *defrag_info_tmp = NULL; ++ struct sk_buff *skb_tmp = NULL; ++ int ret; ++ u8 sta_idx = 0; ++ u16_l frame_ctrl; ++ u8 is_amsdu = 0; ++ bool resend = false, forward = true; ++ const struct ethhdr *eth; ++ ++ hw_rxhdr = (struct hw_rxhdr *)skb->data; ++ ++#ifdef AICWF_RX_REORDER ++ if (hw_rxhdr->is_monitor_vif) { ++ status = RX_STAT_MONITOR; ++ //printk("monitor rx\n"); ++ } ++#endif ++ ++ if (hw_rxhdr->flags_upload) ++ status |= RX_STAT_FORWARD; ++ ++ /* Check if we need to delete the buffer */ ++ if (status & RX_STAT_DELETE) { ++ /* Remove the SK buffer from the rxbuf_elems table */ ++ #if 0 ++ rwnx_ipc_rxbuf_elem_pull(rwnx_hw, skb); ++ #endif ++ /* Free the buffer */ ++ dev_kfree_skb(skb); ++ goto end; ++ } ++ ++ /* Check if we need to forward the buffer coming from a monitor interface */ ++ if (status & RX_STAT_MONITOR) { ++ struct sk_buff *skb_monitor = NULL; ++ struct hw_rxhdr hw_rxhdr_copy; ++ u8 rtap_len; ++ u16 frm_len = 0; ++ ++ //Check if monitor interface exists and is open ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, rwnx_hw->monitor_vif); ++ if (!rwnx_vif) { ++ dev_err(rwnx_hw->dev, "Received monitor frame but there is no monitor interface open\n"); ++ goto check_len_update; ++ } ++ ++ rwnx_rx_vector_convert(rwnx_hw, ++ &hw_rxhdr->hwvect.rx_vect1, ++ &hw_rxhdr->hwvect.rx_vect2); ++ rtap_len = rwnx_rx_rtap_hdrlen(&hw_rxhdr->hwvect.rx_vect1, false); ++ ++ if (status == RX_STAT_MONITOR) ++ { ++ /* Remove the SK buffer from the rxbuf_elems table. It will also ++ unmap the buffer and then sync the buffer for the cpu */ ++ //rwnx_ipc_rxbuf_elem_pull(rwnx_hw, skb); ++ skb->data += (msdu_offset + 2); //sdio/usb word allign ++ ++ //Save frame length ++ frm_len = le32_to_cpu(hw_rxhdr->hwvect.len); ++ ++ // Reserve space for frame ++ skb->len = frm_len; ++ ++ //Check if there is enough space to add the radiotap header ++ if (skb_headroom(skb) > rtap_len) { ++ ++ skb_monitor = skb; ++ ++ //Duplicate the HW Rx Header to override with the radiotap header ++ memcpy(&hw_rxhdr_copy, hw_rxhdr, sizeof(hw_rxhdr_copy)); ++ ++ hw_rxhdr = &hw_rxhdr_copy; ++ } else { ++ //Duplicate the skb and extend the headroom ++ skb_monitor = skb_copy_expand(skb, rtap_len, 0, GFP_ATOMIC); ++ ++ //Reset original skb->data pointer ++ skb->data = (void*) hw_rxhdr; ++ } ++ } else { ++ #ifdef CONFIG_RWNX_MON_DATA ++ skb_monitor = skb_copy_expand(skb, rtap_len, 0, GFP_ATOMIC); ++ skb_monitor->data += (msdu_offset + 2); //sdio/usb word allign ++ ++ //Save frame length ++ frm_len = le32_to_cpu(hw_rxhdr->hwvect.len); ++ #endif ++ } ++ ++ skb_reset_tail_pointer(skb_monitor); ++ skb_monitor->len = 0; ++ skb_put(skb_monitor, frm_len); ++ ++ if (rwnx_rx_monitor(rwnx_hw, rwnx_vif, skb_monitor, hw_rxhdr, rtap_len)) ++ dev_kfree_skb(skb_monitor); ++ ++ if (status == RX_STAT_MONITOR) { ++ if (skb_monitor != skb) { ++ dev_kfree_skb(skb); ++ } ++ } ++ } ++ ++ ++check_len_update: ++ /* Check if we need to update the length */ ++ if (status & RX_STAT_LEN_UPDATE) { ++ if (rxdesc) ++ hw_rxhdr->hwvect.len = rxdesc->frame_len; ++ ++ if (status & RX_STAT_ETH_LEN_UPDATE) { ++ /* Update Length Field inside the Ethernet Header */ ++ struct ethhdr *hdr = (struct ethhdr *)((u8 *)hw_rxhdr + msdu_offset); ++ ++ if (rxdesc) ++ hdr->h_proto = htons(rxdesc->frame_len - sizeof(struct ethhdr)); ++ } ++ ++ goto end; ++ } ++ ++ /* Check if it must be discarded after informing upper layer */ ++ if (status & RX_STAT_SPURIOUS) { ++ struct ieee80211_hdr *hdr; ++ ++ hdr = (struct ieee80211_hdr *)(skb->data + msdu_offset); ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ if (rwnx_vif) { ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, GFP_ATOMIC); ++#else ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, GFP_ATOMIC); ++#else ++ cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, -1, GFP_ATOMIC); ++#endif ++#endif ++ } ++ goto end; ++ } ++ ++ /* Check if we need to forward the buffer */ ++ if (status & RX_STAT_FORWARD) { ++ rwnx_rx_vector_convert(rwnx_hw, ++ &hw_rxhdr->hwvect.rx_vect1, ++ &hw_rxhdr->hwvect.rx_vect2); ++ skb_pull(skb, msdu_offset + 2); //+2 since sdio allign 58->60 ++ ++#define MAC_FCTRL_MOREFRAG 0x0400 ++ frame_ctrl = (skb->data[1] << 8) | skb->data[0]; ++ seq_num = ((skb->data[22] & 0xf0) >> 4) | (skb->data[23] << 4); ++ frag_num = (skb->data[22] & 0x0f); ++ is_amsdu = 0; ++ ++ if ((skb->data[0] & 0x0f) == 0x08) { ++ if ((skb->data[0] & 0x80) == 0x80) {//qos data ++ hdr_len = 26; ++ tid = skb->data[24] & 0x0F; ++ is_qos = 1; ++ if (skb->data[24] & 0x80) ++ is_amsdu = 1; ++ } ++ ++ if(skb->data[1] & 0x80)// htc ++ hdr_len += 4; ++ ++ if ((skb->data[1] & 0x3) == 0x1) {// to ds ++ memcpy(ra, &skb->data[16], MAC_ADDR_LEN); ++ memcpy(ta, &skb->data[10], MAC_ADDR_LEN); ++ } else if ((skb->data[1] & 0x3) == 0x2) { //from ds ++ memcpy(ta, &skb->data[16], MAC_ADDR_LEN); ++ memcpy(ra, &skb->data[4], MAC_ADDR_LEN); ++ } ++ ++ pull_len += (hdr_len + 8); ++ ++ switch (hw_rxhdr->hwvect.decr_status) { ++ case RWNX_RX_HD_DECR_CCMP128: ++ pull_len += 8;//ccmp_header ++ //skb_pull(&skb->data[skb->len-8], 8); //ccmp_mic_len ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 8], 2); ++ break; ++ case RWNX_RX_HD_DECR_TKIP: ++ pull_len += 8;//tkip_header ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 8], 2); ++ break; ++ case RWNX_RX_HD_DECR_WEP: ++ pull_len += 4;//wep_header ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 4], 2); ++ break; ++ case RWNX_RX_HD_DECR_WAPI: ++ pull_len += 18;//wapi_header ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 18], 2); ++ break; ++ ++ default: ++ memcpy(ether_type, &skb->data[hdr_len + 6], 2); ++ break; ++ } ++ if(is_amsdu) ++ hw_rxhdr->flags_is_amsdu = 1; ++ else ++ hw_rxhdr->flags_is_amsdu = 0; ++ ++ if (is_amsdu) { ++ #if 1 ++ skb_pull(skb, pull_len-8); ++ #else ++ skb_pull(skb, pull_len-8); ++ /* |amsdu sub1 | amsdu sub2 | ... */ ++ len_alligned = 0; ++ sublen = 0; ++ sub_skb = NULL; ++ //printk("is_len:%d, pull:%d\n", skb->len, pull_len); ++ while (skb->len > 16) { ++ sublen = (skb->data[12]<<8)|(skb->data[13]); ++ if (skb->len > (sublen+14)) ++ len_alligned = roundup(sublen + 14, 4); ++ else if (skb->len == (sublen+14)) ++ len_alligned = sublen+14; ++ else { ++ printk("accroding to amsdu: this will not happen\n"); ++ break; ++ } ++ //printk("sublen = %d, %x, %x, %x, %x\r\n", sublen,skb->data[0], skb->data[1], skb->data[12], skb->data[13]); ++#if 1 ++ sub_skb = __dev_alloc_skb(sublen - 6 + 12, GFP_KERNEL); ++ skb_put(sub_skb, sublen - 6 + 12); ++ memcpy(sub_skb->data, skb->data, MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[6], &skb->data[6], MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[12], &skb->data[14 + 6], sublen - 6); ++ ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ if (!rwnx_vif) { ++ printk("Frame received but no active vif (%d)", hw_rxhdr->flags_vif_idx); ++ dev_kfree_skb(sub_skb); ++ break; ++ } ++ ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, sub_skb, hw_rxhdr)) ++ dev_kfree_skb(sub_skb); ++#endif ++ skb_pull(skb, len_alligned); ++ } ++ dev_kfree_skb(skb); ++ return 0; ++ #endif ++ } ++ ++ if (hw_rxhdr->flags_dst_idx != RWNX_INVALID_STA) ++ sta_idx = hw_rxhdr->flags_dst_idx; ++ ++ if (!hw_rxhdr->flags_need_reord && ((frame_ctrl & MAC_FCTRL_MOREFRAG) || frag_num)) { ++ printk("rxfrag:%d,%d,%d,sn=%d,%d\r\n", (frame_ctrl & MAC_FCTRL_MOREFRAG), frag_num, skb->len, seq_num,pull_len); ++ if (frame_ctrl & MAC_FCTRL_MOREFRAG) { ++ spin_lock_bh(&rwnx_hw->defrag_lock); ++ if (!list_empty(&rwnx_hw->defrag_list)) { ++ list_for_each_entry(defrag_info_tmp, &rwnx_hw->defrag_list, list) { ++ if ((defrag_info_tmp->sn == seq_num) && (defrag_info_tmp->tid == tid) && \ ++ defrag_info_tmp->sta_idx == sta_idx) { ++ defrag_info = defrag_info_tmp; ++ break; ++ } ++ } ++ } ++ ++ //printk("rx frag: sn=%d, fn=%d, skb->len=%d\r\n", seq_num, frag_num, skb->len); ++ if (defrag_info) { ++ is_frag = 1; ++ if (defrag_info->next_fn != frag_num) { ++ printk("discard:%d:%d\n", defrag_info->next_fn, frag_num); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ ++ skb_put(defrag_info->skb, skb->len-(pull_len-8)); ++ memcpy(&defrag_info->skb->data[defrag_info->frm_len], \ ++ &skb->data[pull_len-8], skb->len - (pull_len-8)); ++ //printk("middle:%d,%d\n", skb->len-(pull_len-8), skb->len); ++ defrag_info->frm_len += (skb->len - (pull_len - 8)); ++ defrag_info->next_fn++; ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } else { ++ defrag_info = kzalloc(sizeof(struct defrag_ctrl_info), GFP_KERNEL); ++ if (defrag_info == NULL) { ++ printk("no defrag_ctrl_info\r\n"); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ defrag_info->skb = __dev_alloc_skb(2000, GFP_KERNEL); ++ if (defrag_info->skb == NULL) { ++ printk("no fragment skb\r\n"); ++ dev_kfree_skb(skb); ++ kfree(defrag_info); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ is_frag = 1; ++ skb_pull(skb, pull_len); ++ skb_push(skb, 14); ++ memcpy(skb->data, ra, MAC_ADDR_LEN); ++ memcpy(&skb->data[6], ta, MAC_ADDR_LEN); ++ memcpy(&skb->data[12], ether_type, 2); ++ defrag_info->sn = seq_num; ++ defrag_info->next_fn = 1; ++ defrag_info->tid = tid; ++ defrag_info->sta_idx = sta_idx; ++ ++ skb_put(defrag_info->skb, skb->len); ++ memcpy(defrag_info->skb->data, skb->data, skb->len); ++ defrag_info->frm_len = skb->len; ++ defrag_info->rwnx_hw = rwnx_hw; ++ //printk("first:%p,%p,%p,%p,%p, %d,%d\r\n", defrag_info, defrag_info->skb, defrag_info->skb->head, defrag_info->skb->tail, defrag_info->skb->end, defrag_info->frm_len, skb->len); ++ list_add_tail(&defrag_info->list, &rwnx_hw->defrag_list); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ init_timer(&defrag_info->defrag_timer); ++ defrag_info->defrag_timer.data = (unsigned long)defrag_info; ++ defrag_info->defrag_timer.function = defrag_timeout_cb; ++#else ++ timer_setup(&defrag_info->defrag_timer, defrag_timeout_cb, 0); ++#endif ++ ret = mod_timer(&defrag_info->defrag_timer, jiffies + msecs_to_jiffies(DEFRAG_MAX_WAIT)); ++ dev_kfree_skb(skb); ++ return 0; ++ } ++ } else { ++ //check whether the last fragment ++ if (!list_empty(&rwnx_hw->defrag_list)) { ++ spin_lock_bh(&rwnx_hw->defrag_lock); ++ list_for_each_entry(defrag_info_tmp, &rwnx_hw->defrag_list, list) { ++ if (((defrag_info_tmp->sn == seq_num) && (defrag_info_tmp->tid == tid) && \ ++ defrag_info_tmp->sta_idx == sta_idx)) { ++ defrag_info = defrag_info_tmp; ++ break; ++ } ++ } ++ ++ if (!defrag_info) ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ else { ++ if (defrag_info->next_fn != frag_num) { ++ printk("discard:%d:%d\n", defrag_info->next_fn, frag_num); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ ++ skb_put(defrag_info->skb, skb->len - (pull_len-8)); ++ memcpy(&defrag_info->skb->data[defrag_info->frm_len], \ ++ &skb->data[pull_len-8], skb->len - (pull_len-8)); ++ defrag_info->frm_len += (skb->len - (pull_len-8)); ++ is_frag = 1; ++ //printk("last: sn=%d, fn=%d, %d, %d\r\n", seq_num, frag_num, defrag_info->frm_len, skb->len); ++ ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ if (!rwnx_vif) { ++ printk("Frame received but no active vif (%d)", hw_rxhdr->flags_vif_idx); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ dev_kfree_skb(skb); ++ ++ skb_tmp = defrag_info->skb; ++ list_del_init(&defrag_info->list); ++ if (timer_pending(&defrag_info->defrag_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete(&defrag_info->defrag_timer); ++#else ++ ret = del_timer(&defrag_info->defrag_timer); ++#endif ++ } ++ kfree(defrag_info); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb_tmp, hw_rxhdr)) ++ dev_kfree_skb(skb_tmp); ++ ++ return 0; ++ } ++ } ++ } ++ } ++ ++ if (!is_frag && !is_amsdu) { ++ skb_pull(skb, pull_len); ++ skb_push(skb, 14); ++ memcpy(skb->data, ra, MAC_ADDR_LEN); ++ memcpy(&skb->data[6], ta, MAC_ADDR_LEN); ++ memcpy(&skb->data[12], ether_type, 2); ++ } ++ } ++ ++ if (hw_rxhdr->flags_is_80211_mpdu) { ++ remove_sec_hdr_mgmt_frame(hw_rxhdr, skb); ++ rwnx_rx_mgmt_any(rwnx_hw, skb, hw_rxhdr); ++ } else { ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ ++ if (!rwnx_vif) { ++ dev_err(rwnx_hw->dev, "Frame received but no active vif(%d)", ++ hw_rxhdr->flags_vif_idx); ++ dev_kfree_skb(skb); ++ goto end; ++ } ++ ++ if (hw_rxhdr->flags_sta_idx != RWNX_INVALID_STA) { ++ struct rwnx_sta *sta; ++ ++ sta = &rwnx_hw->sta_table[hw_rxhdr->flags_sta_idx]; ++ rwnx_rx_statistic(rwnx_hw, hw_rxhdr, sta); ++ ++ if (sta->vlan_idx != rwnx_vif->vif_index) { ++ rwnx_vif = rwnx_hw->vif_table[sta->vlan_idx]; ++ if (!rwnx_vif) { ++ dev_kfree_skb(skb); ++ goto end; ++ } ++ } ++ ++ if (hw_rxhdr->flags_is_4addr && !rwnx_vif->use_4addr) { ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev, ++ sta->mac_addr, GFP_ATOMIC); ++#else ++ cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ sta->mac_addr, GFP_ATOMIC); ++#else ++ sta->mac_addr, -1, GFP_ATOMIC); ++#endif ++#endif ++ } ++ } ++ ++ skb->priority = 256 + tid;//hw_rxhdr->flags_user_prio; ++ ++#ifdef AICWF_RX_REORDER ++ rx_priv_tmp = rx_priv; ++ rx_priv_tmp->rwnx_vif = (void *)rwnx_vif; ++ ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ if (is_qos && hw_rxhdr->flags_need_reord) ++ reord_process_unit((struct aicwf_rx_priv *)rx_priv, skb, seq_num, tid, 1, hw_rxhdr->flags_is_amsdu); ++ else if (is_qos && !hw_rxhdr->flags_need_reord) { ++ reord_flush_tid((struct aicwf_rx_priv *)rx_priv, skb, tid); ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr) && !hw_rxhdr->flags_is_amsdu) ++ dev_kfree_skb(skb); ++ } else { ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr) && !hw_rxhdr->flags_is_amsdu) ++ dev_kfree_skb(skb); ++ } ++ } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { ++#if 1 ++ skb_reset_mac_header(skb); ++ eth = eth_hdr(skb); ++ //printk("da:%pM, %x,%x, len=%d\n", eth->h_dest, skb->data[12], skb->data[13], skb->len); ++ ++ if (unlikely(is_multicast_ether_addr(eth->h_dest))) { ++ /* broadcast pkt need to be forwared to upper layer and resent ++ on wireless interface */ ++ resend = true; ++ } else { ++ /* unicast pkt for STA inside the BSS, no need to forward to upper ++ layer simply resend on wireless interface */ ++ if (hw_rxhdr->flags_dst_idx != RWNX_INVALID_STA) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[hw_rxhdr->flags_dst_idx]; ++ if (sta->valid && (sta->vlan_idx == rwnx_vif->vif_index)) { ++ resend = true; ++ forward = false; ++ } ++ } ++ } ++ ++ if (resend) ++ rwnx_rx_data_skb_resend(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ ++ if (forward) { ++ if (is_qos && hw_rxhdr->flags_need_reord) ++ reord_process_unit((struct aicwf_rx_priv *)rx_priv, skb, seq_num, tid, 1, hw_rxhdr->flags_is_amsdu); ++ else if (is_qos && !hw_rxhdr->flags_need_reord) { ++ reord_flush_tid((struct aicwf_rx_priv *)rx_priv, skb, tid); ++ rwnx_rx_data_skb_forward(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } else ++ rwnx_rx_data_skb_forward(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } else if(resend) { ++ if (is_qos && hw_rxhdr->flags_need_reord) ++ reord_process_unit((struct aicwf_rx_priv *)rx_priv, skb, seq_num, tid, 0, hw_rxhdr->flags_is_amsdu); ++ else if (is_qos && !hw_rxhdr->flags_need_reord) { ++ reord_flush_tid((struct aicwf_rx_priv *)rx_priv, skb, tid); ++ dev_kfree_skb(skb); ++ } ++ }else ++ dev_kfree_skb(skb); ++#else ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr)) ++ dev_kfree_skb(skb); ++#endif ++ } ++#else ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr)) ++ dev_kfree_skb(skb); ++#endif ++ } ++ } ++ ++end: ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h +new file mode 100644 +index 000000000000..b831bc8e4012 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h +@@ -0,0 +1,396 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_rx.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_RX_H_ ++#define _RWNX_RX_H_ ++ ++#include "aicwf_txrxif.h" ++ ++#define SERVER_PORT 67 ++#define CLIENT_PORT 68 ++#define DHCP_MAGIC 0x63825363 ++#define DHCP_ACK 5 ++#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ ++#define DHCP_OPTION_END 255 ++ ++enum rx_status_bits { ++ /// The buffer can be forwarded to the networking stack ++ RX_STAT_FORWARD = 1 << 0, ++ /// A new buffer has to be allocated ++ RX_STAT_ALLOC = 1 << 1, ++ /// The buffer has to be deleted ++ RX_STAT_DELETE = 1 << 2, ++ /// The length of the buffer has to be updated ++ RX_STAT_LEN_UPDATE = 1 << 3, ++ /// The length in the Ethernet header has to be updated ++ RX_STAT_ETH_LEN_UPDATE = 1 << 4, ++ /// Simple copy ++ RX_STAT_COPY = 1 << 5, ++ /// Spurious frame (inform upper layer and discard) ++ RX_STAT_SPURIOUS = 1 << 6, ++ /// packet for monitor interface ++ RX_STAT_MONITOR = 1 << 7, ++}; ++ ++ ++/* ++ * Decryption status subfields. ++ * { ++ */ ++#define RWNX_RX_HD_DECR_UNENC 0 // ENCRYPTION TYPE NONE ++#define RWNX_RX_HD_DECR_WEP 1 // ENCRYPTION TYPE WEP ++#define RWNX_RX_HD_DECR_TKIP 2 // ENCRYPTION TYPE TKIP ++#define RWNX_RX_HD_DECR_CCMP128 3 // ENCRYPTION TYPE CCMP128 ++#define RWNX_RX_HD_DECR_CCMP256 4 // ENCRYPTION TYPE CCMP256 ++#define RWNX_RX_HD_DECR_GCMP128 5 // ENCRYPTION TYPE GCMP128 ++#define RWNX_RX_HD_DECR_GCMP256 6 // ENCRYPTION TYPE GCMP256 ++#define RWNX_RX_HD_DECR_WAPI 7 // ENCRYPTION TYPE WAPI ++// @} ++ ++//#ifdef CONFIG_RWNX_MON_DATA ++#if 0 ++#define RX_MACHDR_BACKUP_LEN 64 ++#endif ++ ++struct rx_vector_1_old { ++ /** Receive Vector 1a */ ++ u32 leg_length :12; ++ u32 leg_rate : 4; ++ u32 ht_length :16; ++ ++ /** Receive Vector 1b */ ++ u32 _ht_length : 4; // FIXME ++ u32 short_gi : 1; ++ u32 stbc : 2; ++ u32 smoothing : 1; ++ u32 mcs : 7; ++ u32 pre_type : 1; ++ u32 format_mod : 3; ++ u32 ch_bw : 2; ++ u32 n_sts : 3; ++ u32 lsig_valid : 1; ++ u32 sounding : 1; ++ u32 num_extn_ss : 2; ++ u32 aggregation : 1; ++ u32 fec_coding : 1; ++ u32 dyn_bw : 1; ++ u32 doze_not_allowed : 1; ++ ++ /** Receive Vector 1c */ ++ u32 antenna_set : 8; ++ u32 partial_aid : 9; ++ u32 group_id : 6; ++ u32 first_user : 1; ++ s32 rssi1 : 8; ++ ++ /** Receive Vector 1d */ ++ s32 rssi2 : 8; ++ s32 rssi3 : 8; ++ s32 rssi4 : 8; ++ u32 reserved_1d : 8; ++}; ++ ++struct rx_leg_vect { ++ u8 dyn_bw_in_non_ht : 1; ++ u8 chn_bw_in_non_ht : 2; ++ u8 rsvd_nht : 4; ++ u8 lsig_valid : 1; ++} __packed; ++ ++struct rx_ht_vect { ++ u16 sounding : 1; ++ u16 smoothing : 1; ++ u16 short_gi : 1; ++ u16 aggregation : 1; ++ u16 stbc : 1; ++ u16 num_extn_ss : 2; ++ u16 lsig_valid : 1; ++ u16 mcs : 7; ++ u16 fec : 1; ++ u16 length :16; ++} __packed; ++ ++struct rx_vht_vect { ++ u8 sounding : 1; ++ u8 beamformed : 1; ++ u8 short_gi : 1; ++ u8 rsvd_vht1 : 1; ++ u8 stbc : 1; ++ u8 doze_not_allowed : 1; ++ u8 first_user : 1; ++ u8 rsvd_vht2 : 1; ++ u16 partial_aid : 9; ++ u16 group_id : 6; ++ u16 rsvd_vht3 : 1; ++ u32 mcs : 4; ++ u32 nss : 3; ++ u32 fec : 1; ++ u32 length :20; ++ u32 rsvd_vht4 : 4; ++} __packed; ++ ++struct rx_he_vect { ++ u8 sounding : 1; ++ u8 beamformed : 1; ++ u8 gi_type : 2; ++ u8 stbc : 1; ++ u8 rsvd_he1 : 3; ++ ++ u8 uplink_flag : 1; ++ u8 beam_change : 1; ++ u8 dcm : 1; ++ u8 he_ltf_type : 2; ++ u8 doppler : 1; ++ u8 rsvd_he2 : 2; ++ ++ u8 bss_color : 6; ++ u8 rsvd_he3 : 2; ++ ++ u8 txop_duration : 7; ++ u8 rsvd_he4 : 1; ++ ++ u8 pe_duration : 4; ++ u8 spatial_reuse : 4; ++ ++ u8 sig_b_comp_mode : 1; ++ u8 dcm_sig_b : 1; ++ u8 mcs_sig_b : 3; ++ u8 ru_size : 3; ++ ++ u32 mcs : 4; ++ u32 nss : 3; ++ u32 fec : 1; ++ u32 length :20; ++ u32 rsvd_he6 : 4; ++} __packed; ++ ++struct rx_vector_1 { ++ u8 format_mod : 4; ++ u8 ch_bw : 3; ++ u8 pre_type : 1; ++ u8 antenna_set : 8; ++ s32 rssi_leg : 8; ++ u32 leg_length :12; ++ u32 leg_rate : 4; ++ s32 rssi1 : 8; ++ ++ union { ++ struct rx_leg_vect leg; ++ struct rx_ht_vect ht; ++ struct rx_vht_vect vht; ++ struct rx_he_vect he; ++ }; ++} __packed; ++ ++struct rx_vector_2_old { ++ /** Receive Vector 2a */ ++ u32 rcpi : 8; ++ u32 evm1 : 8; ++ u32 evm2 : 8; ++ u32 evm3 : 8; ++ ++ /** Receive Vector 2b */ ++ u32 evm4 : 8; ++ u32 reserved2b_1 : 8; ++ u32 reserved2b_2 : 8; ++ u32 reserved2b_3 : 8; ++ ++}; ++ ++struct rx_vector_2 { ++ /** Receive Vector 2a */ ++ u32 rcpi1 : 8; ++ u32 rcpi2 : 8; ++ u32 rcpi3 : 8; ++ u32 rcpi4 : 8; ++ ++ /** Receive Vector 2b */ ++ u32 evm1 : 8; ++ u32 evm2 : 8; ++ u32 evm3 : 8; ++ u32 evm4 : 8; ++}; ++ ++struct phy_channel_info_desc { ++ /** PHY channel information 1 */ ++ u32 phy_band : 8; ++ u32 phy_channel_type : 8; ++ u32 phy_prim20_freq : 16; ++ /** PHY channel information 2 */ ++ u32 phy_center1_freq : 16; ++ u32 phy_center2_freq : 16; ++}; ++ ++struct hw_vect { ++ /** Total length for the MPDU transfer */ ++ u32 len :16; ++ ++ u32 reserved : 8;//data type is included ++ /** AMPDU Status Information */ ++ u32 mpdu_cnt : 6; ++ u32 ampdu_cnt : 2; ++ ++ /** TSF Low */ ++ __le32 tsf_lo; ++ /** TSF High */ ++ __le32 tsf_hi; ++ ++ /** Receive Vector 1 */ ++ struct rx_vector_1 rx_vect1; ++ /** Receive Vector 2 */ ++ struct rx_vector_2 rx_vect2; ++ ++ /** Status **/ ++ u32 rx_vect2_valid : 1; ++ u32 resp_frame : 1; ++ /** Decryption Status */ ++ u32 decr_status : 3; ++ u32 rx_fifo_oflow : 1; ++ ++ /** Frame Unsuccessful */ ++ u32 undef_err : 1; ++ u32 phy_err : 1; ++ u32 fcs_err : 1; ++ u32 addr_mismatch : 1; ++ u32 ga_frame : 1; ++ u32 current_ac : 2; ++ ++ u32 frm_successful_rx : 1; ++ /** Descriptor Done */ ++ u32 desc_done_rx : 1; ++ /** Key Storage RAM Index */ ++ u32 key_sram_index : 10; ++ /** Key Storage RAM Index Valid */ ++ u32 key_sram_v : 1; ++ u32 type : 2; ++ u32 subtype : 4; ++}; ++ ++//#ifdef CONFIG_RWNX_MON_DATA ++#if 0 ++/// MAC header backup descriptor ++struct mon_machdrdesc { ++ /// Length of the buffer ++ u32 buf_len; ++ /// Buffer containing mac header, LLC and SNAP ++ u8 buffer[RX_MACHDR_BACKUP_LEN]; ++}; ++#endif ++ ++struct hw_rxhdr { ++ /** RX vector */ ++ struct hw_vect hwvect; ++ ++ /** PHY channel information */ ++ struct phy_channel_info_desc phy_info; ++ ++ /** RX flags */ ++ u32 flags_is_amsdu : 1; ++ u32 flags_is_80211_mpdu: 1; ++ u32 flags_is_4addr : 1; ++ u32 flags_new_peer : 1; ++#if defined(AICWF_SDIO_SUPPORT) || defined(AICWF_USB_SUPPORT) ++ u32 flags_user_prio : 1; // aic: fw not fill any more ++ u32 flags_need_reord : 1; ++ u32 flags_upload : 1; ++#else ++ u32 flags_user_prio : 3; ++#endif ++#ifndef AICWF_RX_REORDER ++ u32 flags_rsvd0 : 1; ++#else ++ u32 is_monitor_vif : 1; ++#endif ++ u32 flags_vif_idx : 8; // 0xFF if invalid VIF index ++ u32 flags_sta_idx : 8; // 0xFF if invalid STA index ++ u32 flags_dst_idx : 8; // 0xFF if unknown destination STA ++//#ifdef CONFIG_RWNX_MON_DATA ++#if 0 ++ /// MAC header backup descriptor (used only for MSDU when there is a monitor and a data interface) ++ struct mon_machdrdesc mac_hdr_backup; ++#endif ++ /** Pattern indicating if the buffer is available for the driver */ ++ u32 pattern; ++}; ++ ++struct rwnx_legrate { ++ int idx; ++ int rate; ++}; ++ ++extern struct rwnx_legrate legrates_lut[]; ++extern u16 tx_legrates_lut_rate[]; ++ ++struct DHCPInfo { ++ u8 op; ++ u8 htype; ++ u8 hlen; ++ u8 hops; ++ u32 xid; ++ u16 secs; ++ u16 flags; ++ u32 ciaddr; ++ u32 yiaddr; ++ u32 siaddr; ++ u32 giaddr; ++ u8 chaddr[16]; ++ u8 sname[64]; ++ u8 file[128]; ++ u32 cookie; ++ u8 options[308]; /* 312 - cookie */ ++}; ++ ++u8 rwnx_rxdataind_aicwf(struct rwnx_hw *rwnx_hw, void *hostid, void *rx_priv); ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv); ++ ++#ifdef AICWF_ARP_OFFLOAD ++void arpoffload_proc(struct sk_buff *skb, struct rwnx_vif *rwnx_vif); ++#endif ++#ifdef AICWF_RX_REORDER ++struct recv_msdu *reord_rxframe_alloc(spinlock_t *lock, struct list_head *q); ++void reord_rxframe_free(spinlock_t *lock, struct list_head *q, struct list_head *list); ++struct reord_ctrl_info *reord_init_sta(struct aicwf_rx_priv *rx_priv, const u8 *mac_addr); ++void reord_deinit_sta(struct aicwf_rx_priv *rx_priv, struct reord_ctrl_info *reord_info); ++int reord_need_check(struct reord_ctrl *preorder_ctrl, u16 seq_num); ++int reord_rxframe_enqueue(struct reord_ctrl *preorder_ctrl, struct recv_msdu *prframe); ++void reord_timeout_worker(struct work_struct *work); ++int reord_single_frame_ind(struct aicwf_rx_priv *rx_priv, struct recv_msdu *prframe); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void reord_timeout_handler (ulong data); ++#else ++void reord_timeout_handler (struct timer_list *t); ++#endif ++ ++#endif ++void rwnx_rxdata_process_amsdu(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, u8 vif_idx, ++ struct sk_buff_head *list); ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 197) ++struct element { ++ u8 id; ++ u8 datalen; ++ u8 data[]; ++}; ++/* element iteration helpers */ ++#define for_each_element(_elem, _data, _datalen) \ ++ for (_elem = (const struct element *)(_data); \ ++ (const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \ ++ (int)sizeof(*_elem) && \ ++ (const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \ ++ (int)sizeof(*_elem) + _elem->datalen; \ ++ _elem = (const struct element *)(_elem->data + _elem->datalen)) ++ ++#define for_each_element_id(element, _id, data, datalen) \ ++ for_each_element(element, data, datalen) \ ++ if (element->id == (_id)) ++#endif ++#endif ++ ++#endif /* _RWNX_RX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c +new file mode 100644 +index 000000000000..52ffbf64c6fb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c +@@ -0,0 +1,266 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_strs.c ++ * ++ * @brief Miscellaneous debug strings ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "lmac_msg.h" ++static const char *const rwnx_mmid2str[MSG_I(MM_MAX)] = { ++ [MSG_I(MM_RESET_REQ)] = "MM_RESET_REQ", ++ [MSG_I(MM_RESET_CFM)] = "MM_RESET_CFM", ++ [MSG_I(MM_START_REQ)] = "MM_START_REQ", ++ [MSG_I(MM_START_CFM)] = "MM_START_CFM", ++ [MSG_I(MM_VERSION_REQ)] = "MM_VERSION_REQ", ++ [MSG_I(MM_VERSION_CFM)] = "MM_VERSION_CFM", ++ [MSG_I(MM_ADD_IF_REQ)] = "MM_ADD_IF_REQ", ++ [MSG_I(MM_ADD_IF_CFM)] = "MM_ADD_IF_CFM", ++ [MSG_I(MM_REMOVE_IF_REQ)] = "MM_REMOVE_IF_REQ", ++ [MSG_I(MM_REMOVE_IF_CFM)] = "MM_REMOVE_IF_CFM", ++ [MSG_I(MM_STA_ADD_REQ)] = "MM_STA_ADD_REQ", ++ [MSG_I(MM_STA_ADD_CFM)] = "MM_STA_ADD_CFM", ++ [MSG_I(MM_STA_DEL_REQ)] = "MM_STA_DEL_REQ", ++ [MSG_I(MM_STA_DEL_CFM)] = "MM_STA_DEL_CFM", ++ [MSG_I(MM_SET_FILTER_REQ)] = "MM_SET_FILTER_REQ", ++ [MSG_I(MM_SET_FILTER_CFM)] = "MM_SET_FILTER_CFM", ++ [MSG_I(MM_SET_CHANNEL_REQ)] = "MM_SET_CHANNEL_REQ", ++ [MSG_I(MM_SET_CHANNEL_CFM)] = "MM_SET_CHANNEL_CFM", ++ [MSG_I(MM_SET_DTIM_REQ)] = "MM_SET_DTIM_REQ", ++ [MSG_I(MM_SET_DTIM_CFM)] = "MM_SET_DTIM_CFM", ++ [MSG_I(MM_SET_BEACON_INT_REQ)] = "MM_SET_BEACON_INT_REQ", ++ [MSG_I(MM_SET_BEACON_INT_CFM)] = "MM_SET_BEACON_INT_CFM", ++ [MSG_I(MM_SET_BASIC_RATES_REQ)] = "MM_SET_BASIC_RATES_REQ", ++ [MSG_I(MM_SET_BASIC_RATES_CFM)] = "MM_SET_BASIC_RATES_CFM", ++ [MSG_I(MM_SET_BSSID_REQ)] = "MM_SET_BSSID_REQ", ++ [MSG_I(MM_SET_BSSID_CFM)] = "MM_SET_BSSID_CFM", ++ [MSG_I(MM_SET_EDCA_REQ)] = "MM_SET_EDCA_REQ", ++ [MSG_I(MM_SET_EDCA_CFM)] = "MM_SET_EDCA_CFM", ++ [MSG_I(MM_SET_MODE_REQ)] = "MM_SET_MODE_REQ", ++ [MSG_I(MM_SET_MODE_CFM)] = "MM_SET_MODE_CFM", ++ [MSG_I(MM_SET_VIF_STATE_REQ)] = "MM_SET_VIF_STATE_REQ", ++ [MSG_I(MM_SET_VIF_STATE_CFM)] = "MM_SET_VIF_STATE_CFM", ++ [MSG_I(MM_SET_SLOTTIME_REQ)] = "MM_SET_SLOTTIME_REQ", ++ [MSG_I(MM_SET_SLOTTIME_CFM)] = "MM_SET_SLOTTIME_CFM", ++ [MSG_I(MM_SET_IDLE_REQ)] = "MM_SET_IDLE_REQ", ++ [MSG_I(MM_SET_IDLE_CFM)] = "MM_SET_IDLE_CFM", ++ [MSG_I(MM_KEY_ADD_REQ)] = "MM_KEY_ADD_REQ", ++ [MSG_I(MM_KEY_ADD_CFM)] = "MM_KEY_ADD_CFM", ++ [MSG_I(MM_KEY_DEL_REQ)] = "MM_KEY_DEL_REQ", ++ [MSG_I(MM_KEY_DEL_CFM)] = "MM_KEY_DEL_CFM", ++ [MSG_I(MM_BA_ADD_REQ)] = "MM_BA_ADD_REQ", ++ [MSG_I(MM_BA_ADD_CFM)] = "MM_BA_ADD_CFM", ++ [MSG_I(MM_BA_DEL_REQ)] = "MM_BA_DEL_REQ", ++ [MSG_I(MM_BA_DEL_CFM)] = "MM_BA_DEL_CFM", ++ [MSG_I(MM_PRIMARY_TBTT_IND)] = "MM_PRIMARY_TBTT_IND", ++ [MSG_I(MM_SECONDARY_TBTT_IND)] = "MM_SECONDARY_TBTT_IND", ++ [MSG_I(MM_SET_POWER_REQ)] = "MM_SET_POWER_REQ", ++ [MSG_I(MM_SET_POWER_CFM)] = "MM_SET_POWER_CFM", ++ [MSG_I(MM_DBG_TRIGGER_REQ)] = "MM_DBG_TRIGGER_REQ", ++ [MSG_I(MM_SET_PS_MODE_REQ)] = "MM_SET_PS_MODE_REQ", ++ [MSG_I(MM_SET_PS_MODE_CFM)] = "MM_SET_PS_MODE_CFM", ++ [MSG_I(MM_CHAN_CTXT_ADD_REQ)] = "MM_CHAN_CTXT_ADD_REQ", ++ [MSG_I(MM_CHAN_CTXT_ADD_CFM)] = "MM_CHAN_CTXT_ADD_CFM", ++ [MSG_I(MM_CHAN_CTXT_DEL_REQ)] = "MM_CHAN_CTXT_DEL_REQ", ++ [MSG_I(MM_CHAN_CTXT_DEL_CFM)] = "MM_CHAN_CTXT_DEL_CFM", ++ [MSG_I(MM_CHAN_CTXT_LINK_REQ)] = "MM_CHAN_CTXT_LINK_REQ", ++ [MSG_I(MM_CHAN_CTXT_LINK_CFM)] = "MM_CHAN_CTXT_LINK_CFM", ++ [MSG_I(MM_CHAN_CTXT_UNLINK_REQ)] = "MM_CHAN_CTXT_UNLINK_REQ", ++ [MSG_I(MM_CHAN_CTXT_UNLINK_CFM)] = "MM_CHAN_CTXT_UNLINK_CFM", ++ [MSG_I(MM_CHAN_CTXT_UPDATE_REQ)] = "MM_CHAN_CTXT_UPDATE_REQ", ++ [MSG_I(MM_CHAN_CTXT_UPDATE_CFM)] = "MM_CHAN_CTXT_UPDATE_CFM", ++ [MSG_I(MM_CHAN_CTXT_SCHED_REQ)] = "MM_CHAN_CTXT_SCHED_REQ", ++ [MSG_I(MM_CHAN_CTXT_SCHED_CFM)] = "MM_CHAN_CTXT_SCHED_CFM", ++ [MSG_I(MM_BCN_CHANGE_REQ)] = "MM_BCN_CHANGE_REQ", ++ [MSG_I(MM_BCN_CHANGE_CFM)] = "MM_BCN_CHANGE_CFM", ++ [MSG_I(MM_TIM_UPDATE_REQ)] = "MM_TIM_UPDATE_REQ", ++ [MSG_I(MM_TIM_UPDATE_CFM)] = "MM_TIM_UPDATE_CFM", ++ [MSG_I(MM_CONNECTION_LOSS_IND)] = "MM_CONNECTION_LOSS_IND", ++ [MSG_I(MM_CHANNEL_SWITCH_IND)] = "MM_CHANNEL_SWITCH_IND", ++ [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = "MM_CHANNEL_PRE_SWITCH_IND", ++ [MSG_I(MM_REMAIN_ON_CHANNEL_REQ)] = "MM_REMAIN_ON_CHANNEL_REQ", ++ [MSG_I(MM_REMAIN_ON_CHANNEL_CFM)] = "MM_REMAIN_ON_CHANNEL_CFM", ++ [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = "MM_REMAIN_ON_CHANNEL_EXP_IND", ++ [MSG_I(MM_PS_CHANGE_IND)] = "MM_PS_CHANGE_IND", ++ [MSG_I(MM_TRAFFIC_REQ_IND)] = "MM_TRAFFIC_REQ_IND", ++ [MSG_I(MM_SET_PS_OPTIONS_REQ)] = "MM_SET_PS_OPTIONS_REQ", ++ [MSG_I(MM_SET_PS_OPTIONS_CFM)] = "MM_SET_PS_OPTIONS_CFM", ++ [MSG_I(MM_P2P_VIF_PS_CHANGE_IND)] = "MM_P2P_VIF_PS_CHANGE_IND", ++ [MSG_I(MM_CSA_COUNTER_IND)] = "MM_CSA_COUNTER_IND", ++ [MSG_I(MM_CHANNEL_SURVEY_IND)] = "MM_CHANNEL_SURVEY_IND", ++ [MSG_I(MM_SET_P2P_NOA_REQ)] = "MM_SET_P2P_NOA_REQ", ++ [MSG_I(MM_SET_P2P_OPPPS_REQ)] = "MM_SET_P2P_OPPPS_REQ", ++ [MSG_I(MM_SET_P2P_NOA_CFM)] = "MM_SET_P2P_NOA_CFM", ++ [MSG_I(MM_SET_P2P_OPPPS_CFM)] = "MM_SET_P2P_OPPPS_CFM", ++ [MSG_I(MM_CFG_RSSI_REQ)] = "MM_CFG_RSSI_REQ", ++ [MSG_I(MM_RSSI_STATUS_IND)] = "MM_RSSI_STATUS_IND", ++ [MSG_I(MM_CSA_FINISH_IND)] = "MM_CSA_FINISH_IND", ++ [MSG_I(MM_CSA_TRAFFIC_IND)] = "MM_CSA_TRAFFIC_IND", ++ [MSG_I(MM_MU_GROUP_UPDATE_REQ)] = "MM_MU_GROUP_UPDATE_REQ", ++ [MSG_I(MM_MU_GROUP_UPDATE_CFM)] = "MM_MU_GROUP_UPDATE_CFM", ++ ++ [MSG_I(MM_SET_ARPOFFLOAD_REQ)] = "MM_SET_ARPOFFLOAD_REQ", ++ [MSG_I(MM_SET_ARPOFFLOAD_CFM)] = "MM_SET_ARPOFFLOAD_CFM", ++ [MSG_I(MM_SET_AGG_DISABLE_REQ)] = "MM_SET_AGG_DISABLE_REQ", ++ [MSG_I(MM_SET_AGG_DISABLE_CFM)] = "MM_SET_AGG_DISABLE_CFM", ++ [MSG_I(MM_SET_COEX_REQ)] = "MM_SET_COEX_REQ", ++ [MSG_I(MM_SET_COEX_CFM)] = "MM_SET_COEX_CFM", ++ [MSG_I(MM_SET_RF_CONFIG_REQ)] = "MM_SET_RF_CONFIG_REQ", ++ [MSG_I(MM_SET_RF_CONFIG_CFM)] = "MM_SET_RF_CONFIG_CFM", ++ [MSG_I(MM_SET_RF_CALIB_REQ)] = "MM_SET_RF_CALIB_REQ", ++ [MSG_I(MM_SET_RF_CALIB_CFM)] = "MM_SET_RF_CALIB_CFM", ++ ++ [MSG_I(MM_GET_MAC_ADDR_REQ)] = "MM_GET_MAC_ADDR_REQ", ++ [MSG_I(MM_GET_MAC_ADDR_CFM)] = "MM_GET_MAC_ADDR_CFM", ++ [MSG_I(MM_GET_STA_INFO_REQ)] = "MM_GET_STA_INFO_REQ", ++ [MSG_I(MM_GET_STA_INFO_CFM)] = "MM_GET_STA_INFO_CFM", ++ [MSG_I(MM_SET_TXPWR_IDX_LVL_REQ)] = "MM_SET_TXPWR_IDX_LVL_REQ", ++ [MSG_I(MM_SET_TXPWR_IDX_LVL_CFM)] = "MM_SET_TXPWR_IDX_LVL_CFM", ++ [MSG_I(MM_SET_TXPWR_OFST_REQ)] = "MM_SET_TXPWR_OFST_REQ", ++ [MSG_I(MM_SET_TXPWR_OFST_CFM)] = "MM_SET_TXPWR_OFST_CFM", ++ [MSG_I(MM_SET_STACK_START_REQ)] = "MM_SET_STACK_START_REQ", ++ [MSG_I(MM_SET_STACK_START_CFM)] = "MM_SET_STACK_START_CFM", ++ [MSG_I(MM_APM_STALOSS_IND)] = "MM_APM_STALOSS_IND", ++ [MSG_I(MM_SET_VENDOR_HWCONFIG_REQ)] = "MM_SET_VENDOR_HWCONFIG_REQ", ++ [MSG_I(MM_SET_VENDOR_HWCONFIG_CFM)] = "MM_SET_VENDOR_HWCONFIG_CFM", ++ [MSG_I(MM_GET_FW_VERSION_REQ)] = "MM_GET_FW_VERSION_REQ", ++ [MSG_I(MM_GET_FW_VERSION_CFM)] = "MM_GET_FW_VERSION_CFM", ++ [MSG_I(MM_SET_RESUME_RESTORE_REQ)] = "MM_SET_RESUME_RESTORE_REQ", ++ [MSG_I(MM_SET_RESUME_RESTORE_CFM)] = "MM_SET_RESUME_RESTORE_CFM", ++ [MSG_I(MM_GET_WIFI_DISABLE_REQ)] = "MM_GET_WIFI_DISABLE_REQ", ++ [MSG_I(MM_GET_WIFI_DISABLE_CFM)] = "MM_GET_WIFI_DISABLE_CFM", ++ [MSG_I(MM_CFG_RSSI_CFM)] = "MM_CFG_RSSI_CFM", ++}; ++ ++static const char *const rwnx_dbgid2str[MSG_I(DBG_MAX)] = { ++ [MSG_I(DBG_MEM_READ_REQ)] = "DBG_MEM_READ_REQ", ++ [MSG_I(DBG_MEM_READ_CFM)] = "DBG_MEM_READ_CFM", ++ [MSG_I(DBG_MEM_WRITE_REQ)] = "DBG_MEM_WRITE_REQ", ++ [MSG_I(DBG_MEM_WRITE_CFM)] = "DBG_MEM_WRITE_CFM", ++ [MSG_I(DBG_SET_MOD_FILTER_REQ)] = "DBG_SET_MOD_FILTER_REQ", ++ [MSG_I(DBG_SET_MOD_FILTER_CFM)] = "DBG_SET_MOD_FILTER_CFM", ++ [MSG_I(DBG_SET_SEV_FILTER_REQ)] = "DBG_SET_SEV_FILTER_REQ", ++ [MSG_I(DBG_SET_SEV_FILTER_CFM)] = "DBG_SET_SEV_FILTER_CFM", ++ [MSG_I(DBG_ERROR_IND)] = "DBG_ERROR_IND", ++ [MSG_I(DBG_GET_SYS_STAT_REQ)] = "DBG_GET_SYS_STAT_REQ", ++ [MSG_I(DBG_GET_SYS_STAT_CFM)] = "DBG_GET_SYS_STAT_CFM", ++}; ++ ++static const char *const rwnx_scanid2str[MSG_I(SCAN_MAX)] = { ++ [MSG_I(SCAN_START_REQ)] = "SCAN_START_REQ", ++ [MSG_I(SCAN_START_CFM)] = "SCAN_START_CFM", ++ [MSG_I(SCAN_DONE_IND)] = "SCAN_DONE_IND", ++}; ++ ++static const char *const rwnx_tdlsid2str[MSG_I(TDLS_MAX)] = { ++ [MSG_I(TDLS_CHAN_SWITCH_CFM)] = "TDLS_CHAN_SWITCH_CFM", ++ [MSG_I(TDLS_CHAN_SWITCH_REQ)] = "TDLS_CHAN_SWITCH_REQ", ++ [MSG_I(TDLS_CHAN_SWITCH_IND)] = "TDLS_CHAN_SWITCH_IND", ++ [MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = "TDLS_CHAN_SWITCH_BASE_IND", ++ [MSG_I(TDLS_CANCEL_CHAN_SWITCH_REQ)] = "TDLS_CANCEL_CHAN_SWITCH_REQ", ++ [MSG_I(TDLS_CANCEL_CHAN_SWITCH_CFM)] = "TDLS_CANCEL_CHAN_SWITCH_CFM", ++ [MSG_I(TDLS_PEER_PS_IND)] = "TDLS_PEER_PS_IND", ++ [MSG_I(TDLS_PEER_TRAFFIC_IND_REQ)] = "TDLS_PEER_TRAFFIC_IND_REQ", ++ [MSG_I(TDLS_PEER_TRAFFIC_IND_CFM)] = "TDLS_PEER_TRAFFIC_IND_CFM", ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++static const char *const rwnx_scanuid2str[MSG_I(SCANU_MAX)] = { ++ [MSG_I(SCANU_START_REQ)] = "SCANU_START_REQ", ++ [MSG_I(SCANU_START_CFM)] = "SCANU_START_CFM", ++ [MSG_I(SCANU_JOIN_REQ)] = "SCANU_JOIN_REQ", ++ [MSG_I(SCANU_JOIN_CFM)] = "SCANU_JOIN_CFM", ++ [MSG_I(SCANU_RESULT_IND)] = "SCANU_RESULT_IND", ++ [MSG_I(SCANU_FAST_REQ)] = "SCANU_FAST_REQ", ++ [MSG_I(SCANU_FAST_CFM)] = "SCANU_FAST_CFM", ++ [MSG_I(SCANU_VENDOR_IE_REQ)] = "SCANU_VENDOR_IE_REQ", ++ [MSG_I(SCANU_VENDOR_IE_CFM)] = "SCANU_VENDOR_IE_CFM", ++ [MSG_I(SCANU_START_CFM_ADDTIONAL)] = "SCANU_START_CFM_ADDTIONAL", ++ [MSG_I(SCANU_CANCEL_REQ)] = "SCANU_CANCEL_REQ", ++ [MSG_I(SCANU_CANCEL_CFM)] = "SCANU_CANCEL_CFM", ++}; ++ ++static const char *const rwnx_meid2str[MSG_I(ME_MAX)] = { ++ [MSG_I(ME_CONFIG_REQ)] = "ME_CONFIG_REQ", ++ [MSG_I(ME_CONFIG_CFM)] = "ME_CONFIG_CFM", ++ [MSG_I(ME_CHAN_CONFIG_REQ)] = "ME_CHAN_CONFIG_REQ", ++ [MSG_I(ME_CHAN_CONFIG_CFM)] = "ME_CHAN_CONFIG_CFM", ++ [MSG_I(ME_SET_CONTROL_PORT_REQ)] = "ME_SET_CONTROL_PORT_REQ", ++ [MSG_I(ME_SET_CONTROL_PORT_CFM)] = "ME_SET_CONTROL_PORT_CFM", ++ [MSG_I(ME_TKIP_MIC_FAILURE_IND)] = "ME_TKIP_MIC_FAILURE_IND", ++ [MSG_I(ME_STA_ADD_REQ)] = "ME_STA_ADD_REQ", ++ [MSG_I(ME_STA_ADD_CFM)] = "ME_STA_ADD_CFM", ++ [MSG_I(ME_STA_DEL_REQ)] = "ME_STA_DEL_REQ", ++ [MSG_I(ME_STA_DEL_CFM)] = "ME_STA_DEL_CFM", ++ [MSG_I(ME_TX_CREDITS_UPDATE_IND)]= "ME_TX_CREDITS_UPDATE_IND", ++ [MSG_I(ME_RC_STATS_REQ)] = "ME_RC_STATS_REQ", ++ [MSG_I(ME_RC_STATS_CFM)] = "ME_RC_STATS_CFM", ++ [MSG_I(ME_RC_SET_RATE_REQ)] = "ME_RC_SET_RATE_REQ", ++ [MSG_I(ME_TRAFFIC_IND_REQ)] = "ME_TRAFFIC_IND_REQ", ++ [MSG_I(ME_TRAFFIC_IND_CFM)] = "ME_TRAFFIC_IND_CFM", ++ [MSG_I(ME_SET_PS_MODE_REQ)] = "ME_SET_PS_MODE_REQ", ++ [MSG_I(ME_SET_PS_MODE_CFM)] = "ME_SET_PS_MODE_CFM", ++}; ++ ++static const char *const rwnx_smid2str[MSG_I(SM_MAX)] = { ++ [MSG_I(SM_CONNECT_REQ)] = "SM_CONNECT_REQ", ++ [MSG_I(SM_CONNECT_CFM)] = "SM_CONNECT_CFM", ++ [MSG_I(SM_CONNECT_IND)] = "SM_CONNECT_IND", ++ [MSG_I(SM_DISCONNECT_REQ)] = "SM_DISCONNECT_REQ", ++ [MSG_I(SM_DISCONNECT_CFM)] = "SM_DISCONNECT_CFM", ++ [MSG_I(SM_DISCONNECT_IND)] = "SM_DISCONNECT_IND", ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_IND)] = "SM_EXTERNAL_AUTH_REQUIRED_IND", ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP", ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM", ++}; ++ ++static const char *const rwnx_apmid2str[MSG_I(APM_MAX)] = { ++ [MSG_I(APM_START_REQ)] = "APM_START_REQ", ++ [MSG_I(APM_START_CFM)] = "APM_START_CFM", ++ [MSG_I(APM_STOP_REQ)] = "APM_STOP_REQ", ++ [MSG_I(APM_STOP_CFM)] = "APM_STOP_CFM", ++ [MSG_I(APM_START_CAC_REQ)] = "APM_START_CAC_REQ", ++ [MSG_I(APM_START_CAC_CFM)] = "APM_START_CAC_CFM", ++ [MSG_I(APM_STOP_CAC_REQ)] = "APM_STOP_CAC_REQ", ++ [MSG_I(APM_STOP_CAC_CFM)] = "APM_STOP_CAC_CFM", ++ [MSG_I(APM_SET_BEACON_IE_REQ)] = "APM_SET_BEACON_IE_REQ", ++ [MSG_I(APM_SET_BEACON_IE_CFM)] = "APM_SET_BEACON_IE_CFM", ++}; ++ ++static const char *const rwnx_meshid2str[MSG_I(MESH_MAX)] = { ++ [MSG_I(MESH_START_REQ)] = "MESH_START_REQ", ++ [MSG_I(MESH_START_CFM)] = "MESH_START_CFM", ++ [MSG_I(MESH_STOP_REQ)] = "MESH_STOP_REQ", ++ [MSG_I(MESH_STOP_CFM)] = "MESH_STOP_CFM", ++ [MSG_I(MESH_UPDATE_REQ)] = "MESH_UPDATE_REQ", ++ [MSG_I(MESH_UPDATE_CFM)] = "MESH_UPDATE_CFM", ++ [MSG_I(MESH_PATH_CREATE_REQ)] = "MESH_PATH_CREATE_REQ", ++ [MSG_I(MESH_PATH_CREATE_CFM)] = "MESH_PATH_CREATE_CFM", ++ [MSG_I(MESH_PATH_UPDATE_REQ)] = "MESH_PATH_UPDATE_REQ", ++ [MSG_I(MESH_PATH_UPDATE_CFM)] = "MESH_PATH_UPDATE_CFM", ++ [MSG_I(MESH_PROXY_ADD_REQ)] = "MESH_PROXY_ADD_REQ", ++ [MSG_I(MESH_PEER_UPDATE_IND)] = "MESH_PEER_UPDATE_IND", ++ [MSG_I(MESH_PATH_UPDATE_IND)] = "MESH_PATH_UPDATE_IND", ++ [MSG_I(MESH_PROXY_UPDATE_IND)] = "MESH_PROXY_UPDATE_IND", ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++const char *const *rwnx_id2str[TASK_LAST_EMB + 1] = { ++ [TASK_MM] = rwnx_mmid2str, ++ [TASK_DBG] = rwnx_dbgid2str, ++ [TASK_SCAN] = rwnx_scanid2str, ++ [TASK_TDLS] = rwnx_tdlsid2str, ++#ifdef CONFIG_RWNX_FULLMAC ++ [TASK_SCANU] = rwnx_scanuid2str, ++ [TASK_ME] = rwnx_meid2str, ++ [TASK_SM] = rwnx_smid2str, ++ [TASK_APM] = rwnx_apmid2str, ++ [TASK_MESH] = rwnx_meshid2str, ++#endif ++}; +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h +new file mode 100644 +index 000000000000..7dc83aba8bea +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h +@@ -0,0 +1,31 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_strs.h ++ * ++ * @brief Miscellaneous debug strings ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_STRS_H_ ++#define _RWNX_STRS_H_ ++ ++#ifdef CONFIG_RWNX_FHOST ++ ++#define RWNX_ID2STR(tag) "Cmd" ++ ++#else ++#include "lmac_msg.h" ++ ++#define RWNX_ID2STR(tag) (((MSG_T(tag) < ARRAY_SIZE(rwnx_id2str)) && \ ++ (rwnx_id2str[MSG_T(tag)]) && \ ++ ((rwnx_id2str[MSG_T(tag)])[MSG_I(tag)])) ? \ ++ (rwnx_id2str[MSG_T(tag)])[MSG_I(tag)] : "unknown") ++ ++extern const char *const *rwnx_id2str[TASK_LAST_EMB + 1]; ++#endif /* CONFIG_RWNX_FHOST */ ++ ++#endif /* _RWNX_STRS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c +new file mode 100644 +index 000000000000..7d9afb935ac7 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c +@@ -0,0 +1,786 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tx.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++/** ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_tdls.h" ++#include "rwnx_compat.h" ++ ++/** ++ * FUNCTION DEFINITIONS ++ ****************************************************************************** ++ */ ++ ++static u16 ++rwnx_get_tdls_sta_capab(struct rwnx_vif *rwnx_vif, u16 status_code) ++{ ++ u16 capab = 0; ++ ++ /* The capability will be 0 when sending a failure code */ ++ if (status_code != 0) ++ return capab; ++ ++ if (rwnx_vif->sta.ap->band != NL80211_BAND_2GHZ) ++ return capab; ++ ++ capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; ++ capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; ++ ++ return capab; ++} ++ ++static int ++rwnx_tdls_prepare_encap_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, struct sk_buff *skb) ++{ ++ struct ieee80211_tdls_data *tf; ++ tf = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_data) - sizeof(tf->u)); ++ ++ // set eth header ++ memcpy(tf->da, peer, ETH_ALEN); ++ memcpy(tf->sa, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ tf->ether_type = cpu_to_be16(ETH_P_TDLS); ++ ++ // set common TDLS info ++ tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; ++ tf->category = WLAN_CATEGORY_TDLS; ++ tf->action_code = action_code; ++ ++ // set action specific TDLS info ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ skb_put(skb, sizeof(tf->u.setup_req)); ++ tf->u.setup_req.dialog_token = dialog_token; ++ tf->u.setup_req.capability = ++ cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code)); ++ break; ++ ++ case WLAN_TDLS_SETUP_RESPONSE: ++ skb_put(skb, sizeof(tf->u.setup_resp)); ++ tf->u.setup_resp.status_code = cpu_to_le16(status_code); ++ tf->u.setup_resp.dialog_token = dialog_token; ++ tf->u.setup_resp.capability = ++ cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code)); ++ break; ++ ++ case WLAN_TDLS_SETUP_CONFIRM: ++ skb_put(skb, sizeof(tf->u.setup_cfm)); ++ tf->u.setup_cfm.status_code = cpu_to_le16(status_code); ++ tf->u.setup_cfm.dialog_token = dialog_token; ++ break; ++ ++ case WLAN_TDLS_TEARDOWN: ++ skb_put(skb, sizeof(tf->u.teardown)); ++ tf->u.teardown.reason_code = cpu_to_le16(status_code); ++ break; ++ ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ skb_put(skb, sizeof(tf->u.discover_req)); ++ tf->u.discover_req.dialog_token = dialog_token; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++rwnx_prep_tdls_direct(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt; ++ ++ mgmt = (void *)skb_put(skb, 24); ++ memset(mgmt, 0, 24); ++ memcpy(mgmt->da, peer, ETH_ALEN); ++ memcpy(mgmt->sa, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ memcpy(mgmt->bssid, rwnx_vif->sta.ap->mac_addr, ETH_ALEN); ++ ++ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | ++ IEEE80211_STYPE_ACTION); ++ ++ switch (action_code) { ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); ++ mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; ++ mgmt->u.action.u.tdls_discover_resp.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES; ++ mgmt->u.action.u.tdls_discover_resp.dialog_token = dialog_token; ++ mgmt->u.action.u.tdls_discover_resp.capability = ++ cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++rwnx_add_srates_ie(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ u8 i, rates, *pos; ++ int rate; ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ rates = 8; ++ ++ if (skb_tailroom(skb) < rates + 2) ++ return -ENOMEM; ++ ++ pos = skb_put(skb, rates + 2); ++ *pos++ = WLAN_EID_SUPP_RATES; ++ *pos++ = rates; ++ for (i = 0; i < rates; i++) { ++ rate = rwnx_band_2GHz->bitrates[i].bitrate; ++ rate = DIV_ROUND_UP(rate, 5); ++ *pos++ = (u8)rate; ++ } ++ ++ return 0; ++} ++ ++static int ++rwnx_add_ext_srates_ie(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ u8 i, exrates, *pos; ++ int rate; ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ exrates = rwnx_band_2GHz->n_bitrates - 8; ++ ++ if (skb_tailroom(skb) < exrates + 2) ++ return -ENOMEM; ++ ++ pos = skb_put(skb, exrates + 2); ++ *pos++ = WLAN_EID_EXT_SUPP_RATES; ++ *pos++ = exrates; ++ for (i = 8; i < (8+exrates); i++) { ++ rate = rwnx_band_2GHz->bitrates[i].bitrate; ++ rate = DIV_ROUND_UP(rate, 5); ++ *pos++ = (u8)rate; ++ } ++ ++ return 0; ++} ++ ++static void ++rwnx_tdls_add_supp_channels(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ /* ++ * Add possible channels for TDLS. These are channels that are allowed ++ * to be active. ++ */ ++ u8 subband_cnt = 0; ++ u8 *pos_subband; ++ u8 *pos = skb_put(skb, 2); ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ]; ++ ++ *pos++ = WLAN_EID_SUPPORTED_CHANNELS; ++ ++ /* ++ * 5GHz and 2GHz channels numbers can overlap. Ignore this for now, as ++ * this doesn't happen in real world scenarios. ++ */ ++ ++ /* 2GHz, with 5MHz spacing */ ++ pos_subband = skb_put(skb, 2); ++ if (rwnx_band_2GHz->n_channels > 0) { ++ *pos_subband++ = ieee80211_frequency_to_channel(rwnx_band_2GHz->channels[0].center_freq); ++ *pos_subband++ = rwnx_band_2GHz->n_channels; ++ subband_cnt++; ++ } ++ ++ /* 5GHz, with 20MHz spacing */ ++ pos_subband = skb_put(skb, 2); ++ if (rwnx_hw->band_5g_support) { ++ if (rwnx_band_5GHz->n_channels > 0) { ++ *pos_subband++ = ieee80211_frequency_to_channel(rwnx_band_5GHz->channels[0].center_freq); ++ *pos_subband++ = rwnx_band_5GHz->n_channels; ++ subband_cnt++; ++ } ++ } ++ /* length */ ++ *pos = 2 * subband_cnt; ++} ++ ++static void ++rwnx_tdls_add_ext_capab(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 7); ++ bool chan_switch = rwnx_hw->wiphy->features & ++ NL80211_FEATURE_TDLS_CHANNEL_SWITCH; ++ ++ *pos++ = WLAN_EID_EXT_CAPABILITY; ++ *pos++ = 5; /* len */ ++ *pos++ = 0x0; ++ *pos++ = 0x0; ++ *pos++ = 0x0; ++ *pos++ = WLAN_EXT_CAPA4_TDLS_BUFFER_STA | ++ (chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0); ++ *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; ++} ++ ++static void ++rwnx_add_wmm_info_ie(struct sk_buff *skb, u8 qosinfo) ++{ ++ u8 *pos = (void *)skb_put(skb, 9); ++ ++ *pos++ = WLAN_EID_VENDOR_SPECIFIC; ++ *pos++ = 7; /* len */ ++ *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ ++ *pos++ = 0x50; ++ *pos++ = 0xf2; ++ *pos++ = 2; /* WME */ ++ *pos++ = 0; /* WME info */ ++ *pos++ = 1; /* WME ver */ ++ *pos++ = qosinfo; /* U-APSD no in use */ ++} ++ ++/* translate numbering in the WMM parameter IE to the mac80211 notation */ ++static u8 rwnx_ac_from_wmm(int ac) ++{ ++ switch (ac) { ++ default: ++ WARN_ON_ONCE(1); ++ __attribute__((__fallthrough__)); ++ case 0: ++ return AC_BE; ++ case 1: ++ return AC_BK; ++ case 2: ++ return AC_VI; ++ case 3: ++ return AC_VO; ++ } ++} ++ ++static void ++rwnx_add_wmm_param_ie(struct sk_buff *skb, u8 acm_bits, u32 *ac_params) ++{ ++ struct ieee80211_wmm_param_ie *wmm; ++ int i, j; ++ u8 cw_min, cw_max; ++ bool acm; ++ ++ wmm = (void *)skb_put(skb, sizeof(struct ieee80211_wmm_param_ie)); ++ memset(wmm, 0, sizeof(*wmm)); ++ ++ wmm->element_id = WLAN_EID_VENDOR_SPECIFIC; ++ wmm->len = sizeof(*wmm) - 2; ++ ++ wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */ ++ wmm->oui[1] = 0x50; ++ wmm->oui[2] = 0xf2; ++ wmm->oui_type = 2; /* WME */ ++ wmm->oui_subtype = 1; /* WME param */ ++ wmm->version = 1; /* WME ver */ ++ wmm->qos_info = 0; /* U-APSD not in use */ ++ ++ /* ++ * Use the EDCA parameters defined for the BSS, or default if the AP ++ * doesn't support it, as mandated by 802.11-2012 section 10.22.4 ++ */ ++ for (i = 0; i < AC_MAX; i++) { ++ j = rwnx_ac_from_wmm(i); ++ cw_min = (ac_params[j] & 0xF0) >> 4; ++ cw_max = (ac_params[j] & 0xF00) >> 8; ++ acm = (acm_bits & (1 << j)) != 0; ++ ++ wmm->ac[i].aci_aifsn = (i << 5) | (acm << 4) | (ac_params[j] & 0xF); ++ wmm->ac[i].cw = (cw_max << 4) | cw_min; ++ wmm->ac[i].txop_limit = (ac_params[j] & 0x0FFFF000) >> 12; ++ } ++} ++ ++static void ++rwnx_tdls_add_oper_classes(struct rwnx_vif *rwnx_vif, struct sk_buff *skb) ++{ ++ u8 *pos; ++ u8 op_class; ++ struct cfg80211_chan_def chan_def; ++ struct ieee80211_channel chan; ++ ++ chan.band = rwnx_vif->sta.ap->band; ++ chan.center_freq = rwnx_vif->sta.ap->center_freq; ++ chan_def.chan = &chan; ++ chan_def.width = rwnx_vif->sta.ap->width; ++ chan_def.center_freq1 = rwnx_vif->sta.ap->center_freq1; ++ chan_def.center_freq2 = rwnx_vif->sta.ap->center_freq2; ++#ifdef CONFIG_GKI ++ if (!rwnx_ieee80211_chandef_to_operating_class(&chan_def, &op_class)) ++#else ++ if (!ieee80211_chandef_to_operating_class(&chan_def, &op_class)) ++#endif ++ return; ++ ++ pos = skb_put(skb, 4); ++ *pos++ = WLAN_EID_SUPPORTED_REGULATORY_CLASSES; ++ *pos++ = 2; /* len */ ++ ++ // current op class ++ *pos++ = op_class; ++ *pos++ = op_class; /* give current operating class as alternate too */ ++ ++ // need to add 5GHz classes? ++} ++ ++static void ++rwnx_ie_build_ht_cap(struct sk_buff *skb, struct ieee80211_sta_ht_cap *ht_cap, ++ u16 cap) ++{ ++ u8 *pos; ++ __le16 tmp; ++ ++ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); ++ *pos++ = WLAN_EID_HT_CAPABILITY; ++ *pos++ = sizeof(struct ieee80211_ht_cap); ++ memset(pos, 0, sizeof(struct ieee80211_ht_cap)); ++ ++ /* capability flags */ ++ tmp = cpu_to_le16(cap); ++ memcpy(pos, &tmp, sizeof(u16)); ++ pos += sizeof(u16); ++ ++ /* AMPDU parameters */ ++ *pos++ = ht_cap->ampdu_factor | ++ (ht_cap->ampdu_density << ++ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); ++ ++ /* MCS set */ ++ memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs)); ++ pos += sizeof(ht_cap->mcs); ++ ++ /* extended capabilities */ ++ pos += sizeof(__le16); ++ ++ /* BF capabilities */ ++ pos += sizeof(__le32); ++ ++ /* antenna selection */ ++ pos += sizeof(u8); ++} ++ ++static void ++rwnx_ie_build_vht_cap(struct sk_buff *skb, struct ieee80211_sta_vht_cap *vht_cap, ++ u32 cap) ++{ ++ u8 *pos; ++ __le32 tmp; ++ ++ pos = skb_put(skb, 14); ++ ++ *pos++ = WLAN_EID_VHT_CAPABILITY; ++ *pos++ = sizeof(struct ieee80211_vht_cap); ++ memset(pos, 0, sizeof(struct ieee80211_vht_cap)); ++ ++ /* capability flags */ ++ tmp = cpu_to_le32(cap); ++ memcpy(pos, &tmp, sizeof(u32)); ++ pos += sizeof(u32); ++ ++ /* VHT MCS set */ ++ memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs)); ++ pos += sizeof(vht_cap->vht_mcs); ++} ++ ++static void ++rwnx_tdls_add_bss_coex_ie(struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 3); ++ ++ *pos++ = WLAN_EID_BSS_COEX_2040; ++ *pos++ = 1; /* len */ ++ ++ *pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST; ++} ++ ++static void ++rwnx_tdls_add_link_ie(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, ++ bool initiator) ++{ ++ struct ieee80211_tdls_lnkie *lnkid; ++ const u8 *init_addr, *rsp_addr; ++ ++ if (initiator) { ++ init_addr = rwnx_hw->wiphy->perm_addr; ++ rsp_addr = peer; ++ } else { ++ init_addr = peer; ++ rsp_addr = rwnx_hw->wiphy->perm_addr; ++ } ++ ++ lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); ++ ++ lnkid->ie_type = WLAN_EID_LINK_ID; ++ lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; ++ ++ memcpy(lnkid->bssid, rwnx_vif->sta.ap->mac_addr, ETH_ALEN); ++ memcpy(lnkid->init_sta, init_addr, ETH_ALEN); ++ memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN); ++} ++ ++static void ++rwnx_tdls_add_aid_ie(struct rwnx_vif *rwnx_vif, struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 4); ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) ++ *pos++ = WLAN_EID_AID; ++ #else ++ *pos++ = 197; ++ #endif ++ *pos++ = 2; /* len */ ++ *pos++ = rwnx_vif->sta.ap->aid; ++} ++ ++static u8 * ++rwnx_ie_build_ht_oper(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, ++ u16 prot_mode) ++{ ++ struct ieee80211_ht_operation *ht_oper; ++ /* Build HT Information */ ++ *pos++ = WLAN_EID_HT_OPERATION; ++ *pos++ = sizeof(struct ieee80211_ht_operation); ++ ht_oper = (struct ieee80211_ht_operation *)pos; ++ ht_oper->primary_chan = ieee80211_frequency_to_channel( ++ rwnx_vif->sta.ap->center_freq); ++ switch (rwnx_vif->sta.ap->width) { ++ case NL80211_CHAN_WIDTH_160: ++ case NL80211_CHAN_WIDTH_80P80: ++ case NL80211_CHAN_WIDTH_80: ++ case NL80211_CHAN_WIDTH_40: ++ if (rwnx_vif->sta.ap->center_freq1 > rwnx_vif->sta.ap->center_freq) ++ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; ++ else ++ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; ++ break; ++ default: ++ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; ++ break; ++ } ++ if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && ++ rwnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20_NOHT && ++ rwnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20) ++ ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; ++ ++ ht_oper->operation_mode = cpu_to_le16(prot_mode); ++ ht_oper->stbc_param = 0x0000; ++ ++ /* It seems that Basic MCS set and Supported MCS set ++ are identical for the first 10 bytes */ ++ memset(&ht_oper->basic_set, 0, 16); ++ memcpy(&ht_oper->basic_set, &ht_cap->mcs, 10); ++ ++ return pos + sizeof(struct ieee80211_ht_operation); ++} ++ ++static u8 * ++rwnx_ie_build_vht_oper(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, ++ u16 prot_mode) ++{ ++ struct ieee80211_vht_operation *vht_oper; ++ /* Build HT Information */ ++ *pos++ = WLAN_EID_VHT_OPERATION; ++ *pos++ = sizeof(struct ieee80211_vht_operation); ++ vht_oper = (struct ieee80211_vht_operation *)pos; ++ ++ switch (rwnx_vif->sta.ap->width) { ++ case NL80211_CHAN_WIDTH_80: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; // Channel Width ++ CCFS0(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0 ++ CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.) ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ; // Channel Width ++ CCFS0(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0 ++ CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.) ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ; // Channel Width ++ CCFS0(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq1); // Channel Center Frequency Segment 0 ++ CCFS1(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq2); // Channel Center Frequency Segment 1 ++ break; ++ default: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT; ++ CCFS0(vht_oper) = 0; ++ CCFS1(vht_oper) = 0; ++ break; ++ } ++ ++ vht_oper->basic_mcs_set = cpu_to_le16(rwnx_hw->mod_params->mcs_map); ++ ++ return pos + sizeof(struct ieee80211_vht_operation); ++ ++} ++ ++static void ++rwnx_tdls_add_setup_start_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, ++ u8 action_code, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len) ++{ ++ enum nl80211_band band = rwnx_vif->sta.ap->band; ++ struct ieee80211_supported_band *sband; ++ struct ieee80211_sta_ht_cap ht_cap; ++ struct ieee80211_sta_vht_cap vht_cap; ++ size_t offset = 0, noffset; ++ u8 *pos; ++ ++ rcu_read_lock(); ++ ++ rwnx_add_srates_ie(rwnx_hw, skb); ++ rwnx_add_ext_srates_ie(rwnx_hw, skb); ++ rwnx_tdls_add_supp_channels(rwnx_hw, skb); ++ rwnx_tdls_add_ext_capab(rwnx_hw, skb); ++ ++ /* add the QoS element if we support it */ ++ if (/*local->hw.queues >= IEEE80211_NUM_ACS &&*/ ++ action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES) ++ rwnx_add_wmm_info_ie(skb, 0); /* no U-APSD */ ++ ++ rwnx_tdls_add_oper_classes(rwnx_vif, skb); ++ ++ /* ++ * with TDLS we can switch channels, and HT-caps are not necessarily ++ * the same on all bands. The specification limits the setup to a ++ * single HT-cap, so use the current band for now. ++ */ ++ sband = rwnx_hw->wiphy->bands[band]; ++ memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); ++ if (((action_code == WLAN_TDLS_SETUP_REQUEST) || ++ (action_code == WLAN_TDLS_SETUP_RESPONSE) || ++ (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES)) && ++ ht_cap.ht_supported /* (!sta || sta->sta.ht_cap.ht_supported)*/) { ++ rwnx_ie_build_ht_cap(skb, &ht_cap, ht_cap.cap); ++ } ++ ++ if (ht_cap.ht_supported && ++ (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) ++ rwnx_tdls_add_bss_coex_ie(skb); ++ ++ rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator); ++ ++ memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); ++ if (vht_cap.vht_supported) { ++ rwnx_tdls_add_aid_ie(rwnx_vif, skb); ++ rwnx_ie_build_vht_cap(skb, &vht_cap, vht_cap.cap); ++ // Operating mode Notification (optional) ++ } ++ ++ /* add any remaining IEs */ ++ if (extra_ies_len) { ++ noffset = extra_ies_len; ++ pos = skb_put(skb, noffset - offset); ++ memcpy(pos, extra_ies + offset, noffset - offset); ++ } ++ ++ rcu_read_unlock(); ++} ++ ++ ++static void ++rwnx_tdls_add_setup_cfm_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len) ++{ ++ struct ieee80211_supported_band *sband; ++ enum nl80211_band band = rwnx_vif->sta.ap->band; ++ struct ieee80211_sta_ht_cap ht_cap; ++ struct ieee80211_sta_vht_cap vht_cap; ++ ++ size_t offset = 0, noffset; ++ struct rwnx_sta *sta, *ap_sta; ++ u8 *pos; ++ ++ rcu_read_lock(); ++ ++ sta = rwnx_get_sta(rwnx_hw, peer); ++ ap_sta = rwnx_vif->sta.ap; ++ if (WARN_ON_ONCE(!sta || !ap_sta)) { ++ rcu_read_unlock(); ++ return; ++ } ++ ++ /* add the QoS param IE if both the peer and we support it */ ++ if (sta->qos) ++ rwnx_add_wmm_param_ie(skb, ap_sta->acm, ap_sta->ac_param); ++ ++ /* if HT support is only added in TDLS, we need an HT-operation IE */ ++ sband = rwnx_hw->wiphy->bands[band]; ++ memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); ++ if (ht_cap.ht_supported && !ap_sta->ht && sta->ht) { ++ pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); ++ /* send an empty HT operation IE */ ++ rwnx_ie_build_ht_oper(rwnx_hw, rwnx_vif, pos, &ht_cap, 0); ++ } ++ ++ rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator); ++ ++ memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); ++ if (vht_cap.vht_supported && !ap_sta->vht && sta->vht) { ++ pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_operation)); ++ rwnx_ie_build_vht_oper(rwnx_hw, rwnx_vif, pos, &ht_cap, 0); ++ // Operating mode Notification (optional) ++ } ++ ++ /* add any remaining IEs */ ++ if (extra_ies_len) { ++ noffset = extra_ies_len; ++ pos = skb_put(skb, noffset - offset); ++ memcpy(pos, extra_ies + offset, noffset - offset); ++ } ++ ++ rcu_read_unlock(); ++} ++ ++static void ++rwnx_tdls_add_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, ++ u8 action_code, u16 status_code, ++ bool initiator, const u8 *extra_ies, ++ size_t extra_ies_len, u8 oper_class, ++ struct cfg80211_chan_def *chandef) ++{ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ if (status_code == 0) ++ rwnx_tdls_add_setup_start_ies(rwnx_hw, rwnx_vif, skb, peer, action_code, ++ initiator, extra_ies, extra_ies_len); ++ break; ++ case WLAN_TDLS_SETUP_CONFIRM: ++ if (status_code == 0) ++ rwnx_tdls_add_setup_cfm_ies(rwnx_hw, rwnx_vif, skb, peer, initiator, ++ extra_ies, extra_ies_len); ++ break; ++ ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ if (extra_ies_len) ++ memcpy(skb_put(skb, extra_ies_len), extra_ies, ++ extra_ies_len); ++ if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN) ++ rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator); ++ break; ++ } ++} ++ ++int ++rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len, u8 oper_class, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct sk_buff *skb; ++ int ret = 0; ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ]; ++ int channels = rwnx_band_2GHz->n_channels; ++ ++ if (rwnx_hw->band_5g_support) ++ channels += rwnx_band_5GHz->n_channels; ++ ++ skb = netdev_alloc_skb(rwnx_vif->ndev, ++ sizeof(struct ieee80211_tdls_data) + // ethhdr + TDLS info ++ 10 + /* supported rates */ ++ 6 + /* extended supported rates */ ++ (2 + channels) + /* supported channels */ ++ sizeof(struct ieee_types_extcap) + ++ sizeof(struct ieee80211_wmm_param_ie) + ++ 4 + /* oper classes */ ++ 28 + //sizeof(struct ieee80211_ht_cap) + ++ sizeof(struct ieee_types_bss_co_2040) + ++ sizeof(struct ieee80211_tdls_lnkie) + ++ (2 + sizeof(struct ieee80211_vht_cap)) + ++ 4 + /*AID*/ ++ (2 + sizeof(struct ieee80211_ht_operation)) + ++ extra_ies_len); ++ ++ if (!skb) ++ return 0; ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ ret = rwnx_tdls_prepare_encap_data(rwnx_hw, rwnx_vif, peer, action_code, ++ dialog_token, status_code, skb); ++ break; ++ ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ ret = rwnx_prep_tdls_direct(rwnx_hw, rwnx_vif, peer, action_code, ++ dialog_token, status_code, skb); ++ break; ++ ++ default: ++ ret = -ENOTSUPP; ++ break; ++ } ++ ++ if (ret < 0) ++ goto fail; ++ ++ rwnx_tdls_add_ies(rwnx_hw, rwnx_vif, skb, peer, action_code, status_code, ++ initiator, extra_ies, extra_ies_len, oper_class, chandef); ++ ++ if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) { ++ u64 cookie; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ struct cfg80211_mgmt_tx_params params; ++ ++ params.len = skb->len; ++ params.buf = skb->data; ++ ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, ¶ms, false, &cookie); ++ #else ++ ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, NULL, false, 0, skb->data, skb->len, false, false, &cookie); ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ ++ return ret; ++ } ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ skb->priority = 2; ++ break; ++ default: ++ skb->priority = 5; ++ break; ++ } ++ ++ ret = rwnx_select_txq(rwnx_vif, skb); ++ ret = rwnx_start_xmit(skb, rwnx_vif->ndev); ++ ++ return ret; ++ ++fail: ++ dev_kfree_skb(skb); ++ return ret; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h +new file mode 100644 +index 000000000000..590b420f6ec6 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h +@@ -0,0 +1,54 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tdls.h ++ * ++ * @brief TDLS function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef RWNX_TDLS_H_ ++#define RWNX_TDLS_H_ ++ ++#include "rwnx_defs.h" ++ ++struct ieee_types_header { ++ u8 element_id; ++ u8 len; ++} __packed; ++ ++struct ieee_types_bss_co_2040 { ++ struct ieee_types_header ieee_hdr; ++ u8 bss_2040co; ++} __packed; ++ ++struct ieee_types_extcap { ++ struct ieee_types_header ieee_hdr; ++ u8 ext_capab[8]; ++} __packed; ++ ++struct ieee_types_vht_cap { ++ struct ieee_types_header ieee_hdr; ++ struct ieee80211_vht_cap vhtcap; ++} __packed; ++ ++struct ieee_types_vht_oper { ++ struct ieee_types_header ieee_hdr; ++ struct ieee80211_vht_operation vhtoper; ++} __packed; ++ ++struct ieee_types_aid { ++ struct ieee_types_header ieee_hdr; ++ u16 aid; ++} __packed; ++ ++int rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len, u8 oper_class, ++ struct cfg80211_chan_def *chandef); ++ ++#endif /* RWNX_TDLS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c +new file mode 100644 +index 000000000000..ef97354d08df +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c +@@ -0,0 +1,230 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_testmode.c ++ * ++ * @brief Test mode function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#include ++#include ++ ++#include "rwnx_testmode.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_dini.h" ++#include "reg_access.h" ++ ++/* ++ * This function handles the user application commands for register access. ++ * ++ * It retrieves command ID carried with RWNX_TM_ATTR_COMMAND and calls to the ++ * handlers respectively. ++ * ++ * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the ++ * mandatory fields(RWNX_TM_ATTR_REG_OFFSET,RWNX_TM_ATTR_REG_VALUE32) ++ * are missing; Otherwise 0 is replied indicating the success of the command execution. ++ * ++ * If RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_READ, the register read ++ * value is returned with RWNX_TM_ATTR_REG_VALUE32. ++ * ++ * @hw: ieee80211_hw object that represents the device ++ * @tb: general message fields from the user space ++ */ ++int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) ++{ ++ struct rwnx_hw *rwnx_hw = hw->priv; ++ u32 mem_addr, val32; ++ struct sk_buff *skb; ++ int status = 0; ++ ++ /* First check if register address is there */ ++ if (!tb[RWNX_TM_ATTR_REG_OFFSET]) { ++ printk("Error finding register offset\n"); ++ return -ENOMSG; ++ } ++ ++ mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]); ++ ++ switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { ++ case RWNX_TM_CMD_APP2DEV_REG_READ: ++ { ++ struct dbg_mem_read_cfm mem_read_cfm; ++ ++ /*** Send the command to the LMAC ***/ ++ status = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &mem_read_cfm); ++ if (status) ++ return status; ++ ++ /* Allocate the answer message */ ++ skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); ++ if (!skb) { ++ printk("Error allocating memory\n"); ++ return -ENOMEM; ++ } ++ ++ val32 = mem_read_cfm.memdata; ++ if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, val32)) ++ goto nla_put_failure; ++ ++ /* Send the answer to upper layer */ ++ status = cfg80211_testmode_reply(skb); ++ if (status < 0) ++ printk("Error sending msg : %d\n", status); ++ } ++ break; ++ ++ case RWNX_TM_CMD_APP2DEV_REG_WRITE: ++ { ++ if (!tb[RWNX_TM_ATTR_REG_VALUE32]) { ++ printk("Error finding value to write\n"); ++ return -ENOMSG; ++ } else { ++ val32 = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]); ++ /* Send the command to the LMAC */ ++ status = rwnx_send_dbg_mem_write_req(rwnx_hw, mem_addr, val32); ++ if (status) ++ return status; ++ } ++ } ++ break; ++ ++ default: ++ printk("Unknown testmode register command ID\n"); ++ return -ENOSYS; ++ } ++ ++ return status; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -EMSGSIZE; ++} ++ ++/* ++ * This function handles the user application commands for Debug filter settings. ++ * ++ * @hw: ieee80211_hw object that represents the device ++ * @tb: general message fields from the user space ++ */ ++int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb) ++{ ++ struct rwnx_hw *rwnx_hw = hw->priv; ++ u32 filter; ++ int status = 0; ++ ++ /* First check if the filter is there */ ++ if (!tb[RWNX_TM_ATTR_REG_FILTER]) { ++ printk("Error finding filter value\n"); ++ return -ENOMSG; ++ } ++ ++ filter = nla_get_u32(tb[RWNX_TM_ATTR_REG_FILTER]); ++ RWNX_DBG("testmode debug filter, setting: 0x%x\n", filter); ++ ++ switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { ++ case RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER: ++ { ++ /* Send the command to the LMAC */ ++ status = rwnx_send_dbg_set_mod_filter_req(rwnx_hw, filter); ++ if (status) ++ return status; ++ } ++ break; ++ case RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER: ++ { ++ /* Send the command to the LMAC */ ++ status = rwnx_send_dbg_set_sev_filter_req(rwnx_hw, filter); ++ if (status) ++ return status; ++ } ++ break; ++ ++ default: ++ printk("Unknown testmode register command ID\n"); ++ return -ENOSYS; ++ } ++ ++ return status; ++} ++ ++/* ++ * This function handles the user application commands for register access without using ++ * the normal LMAC messaging way. ++ * This time register access will be done through direct PCI BAR windows. This can be used ++ * to access registers even when the :AMC FW is stuck. ++ * ++ * @hw: ieee80211_hw object that represents the device ++ * @tb: general message fields from the user space ++ */ ++int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb) ++{ ++ struct rwnx_hw *rwnx_hw = hw->priv; ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ u32 mem_addr; ++ struct sk_buff *skb; ++ int status = 0; ++ volatile unsigned int reg_value = 0; ++ unsigned int offset; ++ ++ /* First check if register address is there */ ++ if (!tb[RWNX_TM_ATTR_REG_OFFSET]) { ++ printk("Error finding register offset\n"); ++ return -ENOMSG; ++ } ++ ++ mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]); ++ offset = mem_addr & 0x00FFFFFF; ++ ++ switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { ++ case RWNX_TM_CMD_APP2DEV_REG_READ_DBG: ++ { ++ /*** Send the command to the LMAC ***/ ++ reg_value = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, offset); ++ ++ /* Allocate the answer message */ ++ skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); ++ if (!skb) { ++ printk("Error allocating memory\n"); ++ return -ENOMEM; ++ } ++ ++ if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, reg_value)) ++ goto nla_put_failure; ++ ++ /* Send the answer to upper layer */ ++ status = cfg80211_testmode_reply(skb); ++ if (status < 0) ++ printk("Error sending msg : %d\n", status); ++ } ++ break; ++ ++ case RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG: ++ { ++ if (!tb[RWNX_TM_ATTR_REG_VALUE32]) { ++ printk("Error finding value to write\n"); ++ return -ENOMSG; ++ } else { ++ reg_value = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]); ++ ++ /* Send the command to the LMAC */ ++ RWNX_REG_WRITE(reg_value, rwnx_plat, RWNX_ADDR_SYSTEM, ++ offset); ++ } ++ } ++ break; ++ ++ default: ++ printk("Unknown testmode register command ID\n"); ++ return -ENOSYS; ++ } ++ ++ return status; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -EMSGSIZE; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h +new file mode 100644 +index 000000000000..9d1bca47eb50 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h +@@ -0,0 +1,64 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_testmode.h ++ * ++ * @brief Test mode function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef RWNX_TESTMODE_H_ ++#define RWNX_TESTMODE_H_ ++ ++#include ++#include ++ ++/* Commands from user space to kernel space(RWNX_TM_CMD_APP2DEV_XX) and ++ * from and kernel space to user space(RWNX_TM_CMD_DEV2APP_XX). ++ * The command ID is carried with RWNX_TM_ATTR_COMMAND. ++ */ ++enum rwnx_tm_cmd_t { ++ /* commands from user application to access register */ ++ RWNX_TM_CMD_APP2DEV_REG_READ = 1, ++ RWNX_TM_CMD_APP2DEV_REG_WRITE, ++ ++ /* commands from user application to select the Debug levels */ ++ RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER, ++ RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER, ++ ++ /* commands to access registers without sending messages to LMAC layer, ++ * this must be used when LMAC FW is stuck. */ ++ RWNX_TM_CMD_APP2DEV_REG_READ_DBG, ++ RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG, ++ ++ RWNX_TM_CMD_MAX, ++}; ++ ++enum rwnx_tm_attr_t { ++ RWNX_TM_ATTR_NOT_APPLICABLE = 0, ++ ++ RWNX_TM_ATTR_COMMAND, ++ ++ /* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_XXX, ++ * The mandatory fields are: ++ * RWNX_TM_ATTR_REG_OFFSET for the offset of the target register; ++ * RWNX_TM_ATTR_REG_VALUE32 for value */ ++ RWNX_TM_ATTR_REG_OFFSET, ++ RWNX_TM_ATTR_REG_VALUE32, ++ ++ /* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_SET_DBGXXXFILTER, ++ * The mandatory field is RWNX_TM_ATTR_REG_FILTER. */ ++ RWNX_TM_ATTR_REG_FILTER, ++ ++ RWNX_TM_ATTR_MAX, ++}; ++ ++/***********************************************************************/ ++int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb); ++int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb); ++int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb); ++ ++#endif /* RWNX_TESTMODE_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c +new file mode 100644 +index 000000000000..5a57acc20c71 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c +@@ -0,0 +1,2344 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tx.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_tx.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_mesh.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "aicwf_txrxif.h" ++#ifdef CONFIG_RWNX_MON_XMIT ++#include ++#endif ++ ++/****************************************************************************** ++ * Power Save functions ++ *****************************************************************************/ ++/** ++ * rwnx_set_traffic_status - Inform FW if traffic is available for STA in PS ++ * ++ * @rwnx_hw: Driver main data ++ * @sta: Sta in PS mode ++ * @available: whether traffic is buffered for the STA ++ * @ps_id: type of PS data requested (@LEGACY_PS_ID or @UAPSD_ID) ++ */ ++void rwnx_set_traffic_status(struct rwnx_hw *rwnx_hw, ++ struct rwnx_sta *sta, ++ bool available, ++ u8 ps_id) ++{ ++ if (sta->tdls.active) { ++ rwnx_send_tdls_peer_traffic_ind_req(rwnx_hw, ++ rwnx_hw->vif_table[sta->vif_idx]); ++ } else { ++ bool uapsd = (ps_id != LEGACY_PS_ID); ++ rwnx_send_me_traffic_ind(rwnx_hw, sta->sta_idx, uapsd, available); ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_traffic_update(sta->sta_idx, available, uapsd); ++#endif ++ } ++} ++ ++/** ++ * rwnx_ps_bh_enable - Enable/disable PS mode for one STA ++ * ++ * @rwnx_hw: Driver main data ++ * @sta: Sta which enters/leaves PS mode ++ * @enable: PS mode status ++ * ++ * This function will enable/disable PS mode for one STA. ++ * When enabling PS mode: ++ * - Stop all STA's txq for RWNX_TXQ_STOP_STA_PS reason ++ * - Count how many buffers are already ready for this STA ++ * - For BC/MC sta, update all queued SKB to use hw_queue BCMC ++ * - Update TIM if some packet are ready ++ * ++ * When disabling PS mode: ++ * - Start all STA's txq for RWNX_TXQ_STOP_STA_PS reason ++ * - For BC/MC sta, update all queued SKB to use hw_queue AC_BE ++ * - Update TIM if some packet are ready (otherwise fw will not update TIM ++ * in beacon for this STA) ++ * ++ * All counter/skb updates are protected from TX path by taking tx_lock ++ * ++ * NOTE: _bh_ in function name indicates that this function is called ++ * from a bottom_half tasklet. ++ */ ++void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ bool enable) ++{ ++ struct rwnx_txq *txq; ++ ++ if (enable) { ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_enable(sta); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ sta->ps.active = true; ++ sta->ps.sp_cnt[LEGACY_PS_ID] = 0; ++ sta->ps.sp_cnt[UAPSD_ID] = 0; ++ rwnx_txq_sta_stop(sta, RWNX_TXQ_STOP_STA_PS, rwnx_hw); ++ ++ if (is_multicast_sta(sta->sta_idx)) { ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ sta->ps.pkt_ready[LEGACY_PS_ID] = skb_queue_len(&txq->sk_list); ++ sta->ps.pkt_ready[UAPSD_ID] = 0; ++ //txq->hwq = &rwnx_hw->hwq[RWNX_HWQ_BCMC]; ++ } else { ++ int i; ++ sta->ps.pkt_ready[LEGACY_PS_ID] = 0; ++ sta->ps.pkt_ready[UAPSD_ID] = 0; ++ foreach_sta_txq(sta, txq, i, rwnx_hw) { ++ sta->ps.pkt_ready[txq->ps_id] += skb_queue_len(&txq->sk_list); ++ } ++ } ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ //if (sta->ps.pkt_ready[LEGACY_PS_ID]) ++ //srwnx_set_traffic_status(rwnx_hw, sta, true, LEGACY_PS_ID); ++ ++ //if (sta->ps.pkt_ready[UAPSD_ID]) ++ // rwnx_set_traffic_status(rwnx_hw, sta, true, UAPSD_ID); ++ } else { ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_disable(sta->sta_idx); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ sta->ps.active = false; ++ ++ if (is_multicast_sta(sta->sta_idx)) { ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ txq->hwq = &rwnx_hw->hwq[RWNX_HWQ_BE]; ++ txq->push_limit = 0; ++ } else { ++ int i; ++ foreach_sta_txq(sta, txq, i, rwnx_hw) { ++ txq->push_limit = 0; ++ } ++ } ++ ++ rwnx_txq_sta_start(sta, RWNX_TXQ_STOP_STA_PS, rwnx_hw); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ if (sta->ps.pkt_ready[LEGACY_PS_ID]) ++ rwnx_set_traffic_status(rwnx_hw, sta, false, LEGACY_PS_ID); ++ ++ //if (sta->ps.pkt_ready[UAPSD_ID]) ++ // rwnx_set_traffic_status(rwnx_hw, sta, false, UAPSD_ID); ++ ++ tasklet_schedule(&rwnx_hw->task); ++ } ++} ++ ++/** ++ * rwnx_ps_bh_traffic_req - Handle traffic request for STA in PS mode ++ * ++ * @rwnx_hw: Driver main data ++ * @sta: Sta which enters/leaves PS mode ++ * @pkt_req: number of pkt to push ++ * @ps_id: type of PS data requested (@LEGACY_PS_ID or @UAPSD_ID) ++ * ++ * This function will make sure that @pkt_req are pushed to fw ++ * whereas the STA is in PS mode. ++ * If request is 0, send all traffic ++ * If request is greater than available pkt, reduce request ++ * Note: request will also be reduce if txq credits are not available ++ * ++ * All counter updates are protected from TX path by taking tx_lock ++ * ++ * NOTE: _bh_ in function name indicates that this function is called ++ * from the bottom_half tasklet. ++ */ ++void rwnx_ps_bh_traffic_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ u16 pkt_req, u8 ps_id) ++{ ++ int pkt_ready_all; ++ struct rwnx_txq *txq; ++ int schedule = 0; ++ ++ //if (WARN(!sta->ps.active, "sta %pM is not in Power Save mode", ++ // sta->mac_addr)) ++ // return; ++ if (!sta->ps.active) { ++ AICWFDBG(LOGTRACE,"sta %pM is not in Power Save mode", sta->mac_addr); ++ return; ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_traffic_req(sta, pkt_req, ps_id); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ /* Fw may ask to stop a service period with PS_SP_INTERRUPTED. This only ++ happens for p2p-go interface if NOA starts during a service period */ ++ if ((pkt_req == PS_SP_INTERRUPTED) && (ps_id == UAPSD_ID)) { ++ int tid; ++ sta->ps.sp_cnt[ps_id] = 0; ++ foreach_sta_txq(sta, txq, tid, rwnx_hw) { ++ txq->push_limit = 0; ++ } ++ goto done; ++ } ++ ++ pkt_ready_all = (sta->ps.pkt_ready[ps_id] - sta->ps.sp_cnt[ps_id]); ++ ++ /* Don't start SP until previous one is finished or we don't have ++ packet ready (which must not happen for U-APSD) */ ++ if (sta->ps.sp_cnt[ps_id] || pkt_ready_all <= 0) { ++ goto done; ++ } ++ ++ /* Adapt request to what is available. */ ++ if (pkt_req == 0 || pkt_req > pkt_ready_all) { ++ pkt_req = pkt_ready_all; ++ } ++ ++ /* Reset the SP counter */ ++ sta->ps.sp_cnt[ps_id] = 0; ++ schedule = 1; ++ ++ /* "dispatch" the request between txq */ ++ if (is_multicast_sta(sta->sta_idx)) { ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ //if (txq->credits <= 0) ++ // goto done; ++ if (pkt_req > txq->credits) ++ pkt_req = txq->credits; ++ txq->push_limit = pkt_req; ++ sta->ps.sp_cnt[ps_id] = pkt_req; ++ rwnx_txq_add_to_hw_list(txq); ++ } else { ++ int i, tid; ++ ++ //foreach_sta_txq_prio(sta, txq, tid, i, rwnx_hw) { ++ for (i = 0; i < NX_NB_TID_PER_STA; i++) { ++ u16 txq_len; ++ tid = nx_tid_prio[i]; ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ txq_len = skb_queue_len(&txq->sk_list); ++ ++ if (txq->ps_id != ps_id) ++ continue; ++ ++ if (txq_len > txq->credits) ++ txq_len = txq->credits; ++ ++ if (txq_len == 0) ++ continue; ++ ++ if (txq_len < pkt_req) { ++ /* Not enough pkt queued in this txq, add this ++ txq to hwq list and process next txq */ ++ pkt_req -= txq_len; ++ txq->push_limit = txq_len; ++ sta->ps.sp_cnt[ps_id] += txq_len; ++ rwnx_txq_add_to_hw_list(txq); ++ } else { ++ /* Enough pkt in this txq to comlete the request ++ add this txq to hwq list and stop processing txq */ ++ txq->push_limit = pkt_req; ++ sta->ps.sp_cnt[ps_id] += pkt_req; ++ rwnx_txq_add_to_hw_list(txq); ++ break; ++ } ++ } ++ } ++ ++done: ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ if (schedule) ++ tasklet_schedule(&rwnx_hw->task); ++} ++ ++/****************************************************************************** ++ * TX functions ++ *****************************************************************************/ ++#define PRIO_STA_NULL 0xAA ++ ++static const int rwnx_down_hwq2tid[3] = { ++ [RWNX_HWQ_BK] = 2, ++ [RWNX_HWQ_BE] = 3, ++ [RWNX_HWQ_VI] = 5, ++}; ++ ++static void rwnx_downgrade_ac(struct rwnx_sta *sta, struct sk_buff *skb) ++{ ++ int8_t ac = rwnx_tid2hwq[skb->priority]; ++ ++ if (WARN((ac > RWNX_HWQ_VO), ++ "Unexepcted ac %d for skb before downgrade", ac)) ++ ac = RWNX_HWQ_VO; ++ ++ while (sta->acm & BIT(ac)) { ++ if (ac == RWNX_HWQ_BK) { ++ skb->priority = 1; ++ return; ++ } ++ ac--; ++ skb->priority = rwnx_down_hwq2tid[ac]; ++ } ++} ++ ++u16 rwnx_select_txq(struct rwnx_vif *rwnx_vif, struct sk_buff *skb) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct wireless_dev *wdev = &rwnx_vif->wdev; ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_txq *txq; ++ u16 netdev_queue; ++ bool tdls_mgmgt_frame = false; ++ int nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC; ++ } ++ ++ switch (wdev->iftype) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ { ++ struct ethhdr *eth; ++ eth = (struct ethhdr *)skb->data; ++ if (eth->h_proto == cpu_to_be16(ETH_P_TDLS)) { ++ tdls_mgmgt_frame = true; ++ } ++ if ((rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) && ++ (rwnx_vif->sta.tdls_sta != NULL) && ++ (memcmp(eth->h_dest, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) ++ sta = rwnx_vif->sta.tdls_sta; ++ else ++ sta = rwnx_vif->sta.ap; ++ break; ++ } ++ case NL80211_IFTYPE_AP_VLAN: ++ if (rwnx_vif->ap_vlan.sta_4a) { ++ sta = rwnx_vif->ap_vlan.sta_4a; ++ break; ++ } ++ ++ /* AP_VLAN interface is not used for a 4A STA, ++ fallback searching sta amongs all AP's clients */ ++ rwnx_vif = rwnx_vif->ap_vlan.master; ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ { ++ struct rwnx_sta *cur; ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ ++ if (is_multicast_ether_addr(eth->h_dest)) { ++ sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ } else { ++ spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ list_for_each_entry(cur, &rwnx_vif->ap.sta_list, list) { ++ if (!memcmp(cur->mac_addr, eth->h_dest, ETH_ALEN)) { ++ sta = cur; ++ break; ++ } ++ } ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ } ++ ++ break; ++ } ++ case NL80211_IFTYPE_MESH_POINT: ++ { ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ ++ if (!rwnx_vif->is_resending) { ++ /* ++ * If ethernet source address is not the address of a mesh wireless interface, we are proxy for ++ * this address and have to inform the HW ++ */ ++ if (memcmp(ð->h_source[0], &rwnx_vif->ndev->perm_addr[0], ETH_ALEN)) { ++ /* Check if LMAC is already informed */ ++ if (!rwnx_get_mesh_proxy_info(rwnx_vif, (u8 *)ð->h_source, true)) { ++ rwnx_send_mesh_proxy_add_req(rwnx_hw, rwnx_vif, (u8 *)ð->h_source); ++ } ++ } ++ } ++ ++ if (is_multicast_ether_addr(eth->h_dest)) { ++ sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ } else { ++ /* Path to be used */ ++ struct rwnx_mesh_path *p_mesh_path = NULL; ++ struct rwnx_mesh_path *p_cur_path; ++ /* Check if destination is proxied by a peer Mesh STA */ ++ struct rwnx_mesh_proxy *p_mesh_proxy = rwnx_get_mesh_proxy_info(rwnx_vif, (u8 *)ð->h_dest, false); ++ /* Mesh Target address */ ++ struct mac_addr *p_tgt_mac_addr; ++ ++ if (p_mesh_proxy) { ++ p_tgt_mac_addr = &p_mesh_proxy->proxy_addr; ++ } else { ++ p_tgt_mac_addr = (struct mac_addr *)ð->h_dest; ++ } ++ ++ /* Look for path with provided target address */ ++ list_for_each_entry(p_cur_path, &rwnx_vif->ap.mpath_list, list) { ++ if (!memcmp(&p_cur_path->tgt_mac_addr, p_tgt_mac_addr, ETH_ALEN)) { ++ p_mesh_path = p_cur_path; ++ break; ++ } ++ } ++ ++ if (p_mesh_path) { ++ sta = p_mesh_path->p_nhop_sta; ++ } else { ++ rwnx_send_mesh_path_create_req(rwnx_hw, rwnx_vif, (u8 *)p_tgt_mac_addr); ++ } ++ } ++ ++ break; ++ } ++ default: ++ break; ++ } ++ ++ if (sta && sta->qos) { ++ if (tdls_mgmgt_frame) { ++ skb_set_queue_mapping(skb, NX_STA_NDEV_IDX(skb->priority, sta->sta_idx)); ++ } else { ++ /* use the data classifier to determine what 802.1d tag the ++ * data frame has */ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) ++ skb->priority = cfg80211_classify8021d(skb) & IEEE80211_QOS_CTL_TAG1D_MASK; ++ #else ++ skb->priority = cfg80211_classify8021d(skb, NULL) & IEEE80211_QOS_CTL_TAG1D_MASK; ++ #endif ++ } ++ if (sta->acm) ++ rwnx_downgrade_ac(sta, skb); ++ ++ txq = rwnx_txq_sta_get(sta, skb->priority, rwnx_hw); ++ netdev_queue = txq->ndev_idx; ++ } else if (sta) { ++ skb->priority = 0xFF; ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ netdev_queue = txq->ndev_idx; ++ } else { ++ /* This packet will be dropped in xmit function, still need to select ++ an active queue for xmit to be called. As it most likely to happen ++ for AP interface, select BCMC queue ++ (TODO: select another queue if BCMC queue is stopped) */ ++ skb->priority = PRIO_STA_NULL; ++ netdev_queue = nx_bcmc_txq_ndev_idx; ++ } ++ ++#ifndef CONFIG_ONE_TXQ ++ BUG_ON(netdev_queue >= NX_NB_NDEV_TXQ); ++#endif ++ ++ return netdev_queue; ++} ++ ++/** ++ * rwnx_set_more_data_flag - Update MORE_DATA flag in tx sw desc ++ * ++ * @rwnx_hw: Driver main data ++ * @sw_txhdr: Header for pkt to be pushed ++ * ++ * If STA is in PS mode ++ * - Set EOSP in case the packet is the last of the UAPSD service period ++ * - Set MORE_DATA flag if more pkt are ready for this sta ++ * - Update TIM if this is the last pkt buffered for this sta ++ * ++ * note: tx_lock already taken. ++ */ ++static inline void rwnx_set_more_data_flag(struct rwnx_hw *rwnx_hw, ++ struct rwnx_sw_txhdr *sw_txhdr) ++{ ++ struct rwnx_sta *sta = sw_txhdr->rwnx_sta; ++ struct rwnx_vif *vif = sw_txhdr->rwnx_vif; ++ struct rwnx_txq *txq = sw_txhdr->txq; ++ ++ if (unlikely(sta->ps.active)) { ++ sta->ps.pkt_ready[txq->ps_id]--; ++ sta->ps.sp_cnt[txq->ps_id]--; ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_push(sta); ++#endif ++ if (((txq->ps_id == UAPSD_ID) || (vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) || (sta->tdls.active)) ++ && !sta->ps.sp_cnt[txq->ps_id]) { ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_EOSP; ++ } ++ ++ if (sta->ps.pkt_ready[txq->ps_id]) { ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_MORE_DATA; ++ } else { ++ rwnx_set_traffic_status(rwnx_hw, sta, false, txq->ps_id); ++ } ++ } ++} ++ ++/** ++ * rwnx_get_tx_priv - Get STA and tid for one skb ++ * ++ * @rwnx_vif: vif ptr ++ * @skb: skb ++ * @tid: pointer updated with the tid to use for this skb ++ * ++ * @return: pointer on the destination STA (may be NULL) ++ * ++ * skb has already been parsed in rwnx_select_queue function ++ * simply re-read information form skb. ++ */ ++static struct rwnx_sta *rwnx_get_tx_priv(struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, ++ u8 *tid) ++{ ++ static struct rwnx_hw *rwnx_hw; ++ struct rwnx_sta *sta; ++ int sta_idx; ++ int nx_remote_sta_max = NX_REMOTE_STA_MAX; ++ int nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX; ++ ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_remote_sta_max = NX_REMOTE_STA_MAX_FOR_OLD_IC; ++ nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC; ++ } ++ ++ ++ rwnx_hw = rwnx_vif->rwnx_hw; ++ *tid = skb->priority; ++ if (unlikely(skb->priority == PRIO_STA_NULL)) { ++ return NULL; ++ } else { ++ int ndev_idx = skb_get_queue_mapping(skb); ++ ++ if (ndev_idx == nx_bcmc_txq_ndev_idx) ++ sta_idx = nx_remote_sta_max + master_vif_idx(rwnx_vif); ++ else ++ sta_idx = ndev_idx / NX_NB_TID_PER_STA; ++ ++ sta = &rwnx_hw->sta_table[sta_idx]; ++ } ++ ++ return sta; ++} ++ ++/** ++ * rwnx_prep_tx - Prepare buffer for DMA transmission ++ * ++ * @rwnx_hw: Driver main data ++ * @txhdr: Tx descriptor ++ * ++ * Maps hw_txhdr and buffer data for transmission via DMA. ++ * - Data buffer with be downloaded by embebded side. ++ * - hw_txhdr will be uploaded by embedded side when buffer has been ++ * transmitted over the air. ++ */ ++static int rwnx_prep_tx(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr) ++{ ++#if 0 ++ struct rwnx_sw_txhdr *sw_txhdr = txhdr->sw_hdr; ++ struct rwnx_hw_txhdr *hw_txhdr = &txhdr->hw_hdr; ++ dma_addr_t dma_addr; ++ ++ /* MAP (and sync) memory for DMA */ ++ dma_addr = dma_map_single(rwnx_hw->dev, hw_txhdr, ++ sw_txhdr->map_len, DMA_BIDIRECTIONAL); ++ if (WARN_ON(dma_mapping_error(rwnx_hw->dev, dma_addr))) ++ return -1; ++ ++ sw_txhdr->dma_addr = dma_addr; ++#endif ++ return 0; ++} ++ ++/** ++ * rwnx_tx_push - Push one packet to fw ++ * ++ * @rwnx_hw: Driver main data ++ * @txhdr: tx desc of the buffer to push ++ * @flags: push flags (see @rwnx_push_flags) ++ * ++ * Push one packet to fw. Sw desc of the packet has already been updated. ++ * Only MORE_DATA flag will be set if needed. ++ */ ++void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags) ++{ ++ struct rwnx_sw_txhdr *sw_txhdr = txhdr->sw_hdr; ++ struct sk_buff *skb = sw_txhdr->skb; ++ struct rwnx_txq *txq = sw_txhdr->txq; ++ u16 hw_queue = txq->hwq->id; ++ int user = 0; ++ ++ lockdep_assert_held(&rwnx_hw->tx_lock); ++ ++ //printk("rwnx_tx_push\n"); ++ /* RETRY flag is not always set so retest here */ ++ if (txq->nb_retry) { ++ flags |= RWNX_PUSH_RETRY; ++ txq->nb_retry--; ++ if (txq->nb_retry == 0) { ++ WARN(skb != txq->last_retry_skb, ++ "last retry buffer is not the expected one"); ++ txq->last_retry_skb = NULL; ++ } ++ } else if (!(flags & RWNX_PUSH_RETRY)) { ++ txq->pkt_sent++; ++ } ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (txq->amsdu == sw_txhdr) { ++ WARN((flags & RWNX_PUSH_RETRY), "End A-MSDU on a retry"); ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].done++; ++ txq->amsdu = NULL; ++ } else if (!(flags & RWNX_PUSH_RETRY) && ++ !(sw_txhdr->desc.host.flags & TXU_CNTRL_AMSDU)) { ++ rwnx_hw->stats.amsdus[0].done++; ++ } ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++ /* Wait here to update hw_queue, as for multicast STA hwq may change ++ between queue and push (because of PS) */ ++ sw_txhdr->hw_queue = hw_queue; ++ ++ //sw_txhdr->desc.host.packet_addr = hw_queue; //use packet_addr field for hw_txq ++ sw_txhdr->desc.host.ac = hw_queue; //use ac field for hw_txq ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ /* MU group is only selected during hwq processing */ ++ sw_txhdr->desc.host.mumimo_info = txq->mumimo_info; ++ user = RWNX_TXQ_POS_ID(txq); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++ if (sw_txhdr->rwnx_sta) { ++ /* only for AP mode */ ++ rwnx_set_more_data_flag(rwnx_hw, sw_txhdr); ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_push_desc(skb, sw_txhdr, flags); ++#endif ++ #if 0 ++ txq->credits--; ++ #endif ++ txq->pkt_pushed[user]++; ++ //printk("txq->credits=%d\n",txq->credits); ++ #if 0 ++ if (txq->credits <= 0) ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); ++ #endif ++ ++ if (txq->push_limit) ++ txq->push_limit--; ++#if 0 ++ rwnx_ipc_txdesc_push(rwnx_hw, &sw_txhdr->desc, skb, hw_queue, user); ++#else ++#ifdef AICWF_SDIO_SUPPORT ++ if (((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT) && \ ++ ((*(skb->data+sw_txhdr->headroom) == 0xd0) || (*(skb->data+sw_txhdr->headroom) == 0x10) || (*(skb->data+sw_txhdr->headroom) == 0x30))) || \ ++ (sw_txhdr->desc.host.ethertype == 0x8e88) || (sw_txhdr->desc.host.ethertype == 0xb488)) { ++ sw_txhdr->need_cfm = 1; ++ sw_txhdr->desc.host.hostid = ((1<<31) | rwnx_hw->sdio_env.txdesc_free_idx[0]); ++ aicwf_sdio_host_txdesc_push(&(rwnx_hw->sdio_env), 0, (long)skb); ++ if((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT)) ++ AICWFDBG(LOGINFO, "need cfm mgmt:%x,user_idx=%d, skb=%p\n", *(skb->data+sw_txhdr->headroom), rwnx_hw->sdio_env.txdesc_free_idx[0], skb); ++ else ++ AICWFDBG(LOGINFO, "need cfm ethertype:%8x,user_idx=%d, skb=%p\n", sw_txhdr->desc.host.ethertype, rwnx_hw->sdio_env.txdesc_free_idx[0], skb); ++ } else { ++ sw_txhdr->need_cfm = 0; ++ sw_txhdr->desc.host.hostid = 0; ++ if (sw_txhdr->raw_frame) { ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_MGMT; ++ AICWFDBG(LOGDEBUG, "%s TXU_CNTRL_MGMT sw_txhdr->desc.host.flags:%x\r\n", __func__, ++ sw_txhdr->desc.host.flags); ++ } ++ if (sw_txhdr->fixed_rate) { ++ sw_txhdr->desc.host.hostid = (0x01UL << 30) | sw_txhdr->rate_config; ++ AICWFDBG(LOGDEBUG, "%s TXU_CNTRL_MGMT hostid:%x\r\n", __func__, ++ sw_txhdr->desc.host.hostid); ++ } else { ++ sw_txhdr->desc.host.hostid = 0; ++ } ++ ++ sw_txhdr->rwnx_vif->net_stats.tx_packets++; ++ sw_txhdr->rwnx_vif->net_stats.tx_bytes += sw_txhdr->frame_len; ++ rwnx_hw->stats.last_tx = jiffies; ++ } ++ aicwf_frame_tx((void *)(rwnx_hw->sdiodev), skb); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ if (((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT) && \ ++ ((*(skb->data+sw_txhdr->headroom) == 0xd0) || (*(skb->data+sw_txhdr->headroom) == 0x10) || (*(skb->data+sw_txhdr->headroom) == 0x30))) || \ ++ (sw_txhdr->desc.host.ethertype == 0x8e88)) { ++ printk("push need cfm flags 0x%x\n", sw_txhdr->desc.host.flags); ++ sw_txhdr->need_cfm = 1; ++ sw_txhdr->desc.host.hostid = ((1<<31) | rwnx_hw->usb_env.txdesc_free_idx[0]); ++ aicwf_usb_host_txdesc_push(&(rwnx_hw->usb_env), 0, (long)(skb)); ++ } else { ++ sw_txhdr->need_cfm = 0; ++ sw_txhdr->desc.host.hostid = 0; ++ ++ sw_txhdr->rwnx_vif->net_stats.tx_packets++; ++ sw_txhdr->rwnx_vif->net_stats.tx_bytes += sw_txhdr->frame_len; ++ rwnx_hw->stats.last_tx = jiffies; ++ } ++ aicwf_frame_tx((void *)(rwnx_hw->usbdev), skb); ++#endif ++#endif ++#if 0 ++ txq->hwq->credits[user]--; ++#endif ++ rwnx_hw->stats.cfm_balance[hw_queue]++; ++} ++ ++ ++ ++/** ++ * rwnx_tx_retry - Push an AMPDU pkt that need to be retried ++ * ++ * @rwnx_hw: Driver main data ++ * @skb: pkt to re-push ++ * @txhdr: tx desc of the pkt to re-push ++ * @sw_retry: Indicates if fw decide to retry this buffer ++ * (i.e. it has never been transmitted over the air) ++ * ++ * Called when a packet needs to be repushed to the firmware. ++ * First update sw descriptor and then queue it in the retry list. ++ */ ++static void rwnx_tx_retry(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, ++ struct rwnx_txhdr *txhdr, bool sw_retry) ++{ ++ struct rwnx_sw_txhdr *sw_txhdr = txhdr->sw_hdr; ++ struct tx_cfm_tag *cfm = &txhdr->hw_hdr.cfm; ++ struct rwnx_txq *txq = sw_txhdr->txq; ++ int peek_off = offsetof(struct rwnx_hw_txhdr, cfm); ++ int peek_len = sizeof(((struct rwnx_hw_txhdr *)0)->cfm); ++ ++ if (!sw_retry) { ++ /* update sw desc */ ++ #if 0 ++ sw_txhdr->desc.host.sn = cfm->sn; ++ sw_txhdr->desc.host.pn[0] = cfm->pn[0]; ++ sw_txhdr->desc.host.pn[1] = cfm->pn[1]; ++ sw_txhdr->desc.host.pn[2] = cfm->pn[2]; ++ sw_txhdr->desc.host.pn[3] = cfm->pn[3]; ++ sw_txhdr->desc.host.timestamp = cfm->timestamp; ++ #endif ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_RETRY; ++ ++ #ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->desc.host.flags & TXU_CNTRL_AMSDU) ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].failed++; ++ #endif ++ } ++ ++ /* MORE_DATA will be re-set if needed when pkt will be repushed */ ++ sw_txhdr->desc.host.flags &= ~TXU_CNTRL_MORE_DATA; ++ ++ cfm->status.value = 0; ++ dma_sync_single_for_device(rwnx_hw->dev, sw_txhdr->dma_addr + peek_off, ++ peek_len, DMA_BIDIRECTIONAL); ++ ++ txq->credits++; ++ if (txq->credits > 0) ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_FULL); ++ ++ /* Queue the buffer */ ++ rwnx_txq_queue_skb(skb, txq, rwnx_hw, true); ++} ++ ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++/* return size of subframe (including header) */ ++static inline int rwnx_amsdu_subframe_length(struct ethhdr *eth, int eth_len) ++{ ++ /* ethernet header is replaced with amdsu header that have the same size ++ Only need to check if LLC/SNAP header will be added */ ++ int len = eth_len; ++ ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ len += sizeof(rfc1042_header) + 2; ++ } ++ ++ return len; ++} ++ ++static inline bool rwnx_amsdu_is_aggregable(struct sk_buff *skb) ++{ ++ /* need to add some check on buffer to see if it can be aggregated ? */ ++ return true; ++} ++ ++ ++/** ++ * rwnx_amsdu_del_subframe_header - remove AMSDU header ++ * ++ * amsdu_txhdr: amsdu tx descriptor ++ * ++ * Move back the ethernet header at the "beginning" of the data buffer. ++ * (which has been moved in @rwnx_amsdu_add_subframe_header) ++ */ ++static void rwnx_amsdu_del_subframe_header(struct rwnx_amsdu_txhdr *amsdu_txhdr) ++{ ++ struct sk_buff *skb = amsdu_txhdr->skb; ++ struct ethhdr *eth; ++ u8 *pos; ++ ++ pos = skb->data; ++ pos += sizeof(struct rwnx_amsdu_txhdr); ++ eth = (struct ethhdr *)pos; ++ pos += amsdu_txhdr->pad + sizeof(struct ethhdr); ++ ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ pos += sizeof(rfc1042_header) + 2; ++ } ++ ++ memmove(pos, eth, sizeof(*eth)); ++ skb_pull(skb, (pos - skb->data)); ++} ++ ++/** ++ * rwnx_amsdu_add_subframe_header - Add AMSDU header and link subframe ++ * ++ * @rwnx_hw Driver main data ++ * @skb Buffer to aggregate ++ * @sw_txhdr Tx descriptor for the first A-MSDU subframe ++ * ++ * return 0 on sucess, -1 otherwise ++ * ++ * This functions Add A-MSDU header and LLC/SNAP header in the buffer ++ * and update sw_txhdr of the first subframe to link this buffer. ++ * If an error happens, the buffer will be queued as a normal buffer. ++ * ++ * ++ * Before After ++ * +-------------+ +-------------+ ++ * | HEADROOM | | HEADROOM | ++ * | | +-------------+ <- data ++ * | | | amsdu_txhdr | ++ * | | | * pad size | ++ * | | +-------------+ ++ * | | | ETH hdr | keep original eth hdr ++ * | | | | to restore it once transmitted ++ * | | +-------------+ <- packet_addr[x] ++ * | | | Pad | ++ * | | +-------------+ ++ * data -> +-------------+ | AMSDU HDR | ++ * | ETH hdr | +-------------+ ++ * | | | LLC/SNAP | ++ * +-------------+ +-------------+ ++ * | DATA | | DATA | ++ * | | | | ++ * +-------------+ +-------------+ ++ * ++ * Called with tx_lock hold ++ */ ++static int rwnx_amsdu_add_subframe_header(struct rwnx_hw *rwnx_hw, ++ struct sk_buff *skb, ++ struct rwnx_sw_txhdr *sw_txhdr) ++{ ++ struct rwnx_amsdu *amsdu = &sw_txhdr->amsdu; ++ struct rwnx_amsdu_txhdr *amsdu_txhdr; ++ struct ethhdr *amsdu_hdr, *eth = (struct ethhdr *)skb->data; ++ int headroom_need, map_len, msdu_len; ++ dma_addr_t dma_addr; ++ u8 *pos, *map_start; ++ ++ msdu_len = skb->len - sizeof(*eth); ++ headroom_need = sizeof(*amsdu_txhdr) + amsdu->pad + ++ sizeof(*amsdu_hdr); ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ headroom_need += sizeof(rfc1042_header) + 2; ++ msdu_len += sizeof(rfc1042_header) + 2; ++ } ++ ++ /* we should have enough headroom (checked in xmit) */ ++ if (WARN_ON(skb_headroom(skb) < headroom_need)) { ++ return -1; ++ } ++ ++ /* allocate headroom */ ++ pos = skb_push(skb, headroom_need); ++ amsdu_txhdr = (struct rwnx_amsdu_txhdr *)pos; ++ pos += sizeof(*amsdu_txhdr); ++ ++ /* move eth header */ ++ memmove(pos, eth, sizeof(*eth)); ++ eth = (struct ethhdr *)pos; ++ pos += sizeof(*eth); ++ ++ /* Add padding from previous subframe */ ++ map_start = pos; ++ memset(pos, 0, amsdu->pad); ++ pos += amsdu->pad; ++ ++ /* Add AMSDU hdr */ ++ amsdu_hdr = (struct ethhdr *)pos; ++ memcpy(amsdu_hdr->h_dest, eth->h_dest, ETH_ALEN); ++ memcpy(amsdu_hdr->h_source, eth->h_source, ETH_ALEN); ++ amsdu_hdr->h_proto = htons(msdu_len); ++ pos += sizeof(*amsdu_hdr); ++ ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); ++ pos += sizeof(rfc1042_header); ++ } ++ ++ /* MAP (and sync) memory for DMA */ ++ map_len = msdu_len + amsdu->pad + sizeof(*amsdu_hdr); ++ dma_addr = dma_map_single(rwnx_hw->dev, map_start, map_len, ++ DMA_BIDIRECTIONAL); ++ if (WARN_ON(dma_mapping_error(rwnx_hw->dev, dma_addr))) { ++ pos -= sizeof(*eth); ++ memmove(pos, eth, sizeof(*eth)); ++ skb_pull(skb, headroom_need); ++ return -1; ++ } ++ ++ /* update amdsu_txhdr */ ++ amsdu_txhdr->map_len = map_len; ++ amsdu_txhdr->dma_addr = dma_addr; ++ amsdu_txhdr->skb = skb; ++ amsdu_txhdr->pad = amsdu->pad; ++ amsdu_txhdr->msdu_len = msdu_len; ++ ++ /* update rwnx_sw_txhdr (of the first subframe) */ ++ BUG_ON(amsdu->nb != sw_txhdr->desc.host.packet_cnt); ++ sw_txhdr->desc.host.packet_addr[amsdu->nb] = dma_addr; ++ sw_txhdr->desc.host.packet_len[amsdu->nb] = map_len; ++ sw_txhdr->desc.host.packet_cnt++; ++ amsdu->nb++; ++ ++ amsdu->pad = AMSDU_PADDING(map_len - amsdu->pad); ++ list_add_tail(&amsdu_txhdr->list, &amsdu->hdrs); ++ amsdu->len += map_len; ++ ++ trace_amsdu_subframe(sw_txhdr); ++ return 0; ++} ++ ++/** ++ * rwnx_amsdu_add_subframe - Add this buffer as an A-MSDU subframe if possible ++ * ++ * @rwnx_hw Driver main data ++ * @skb Buffer to aggregate if possible ++ * @sta Destination STA ++ * @txq sta's txq used for this buffer ++ * ++ * Tyr to aggregate the buffer in an A-MSDU. If it succeed then the ++ * buffer is added as a new A-MSDU subframe with AMSDU and LLC/SNAP ++ * headers added (so FW won't have to modify this subframe). ++ * ++ * To be added as subframe : ++ * - sta must allow amsdu ++ * - buffer must be aggregable (to be defined) ++ * - at least one other aggregable buffer is pending in the queue ++ * or an a-msdu (with enough free space) is currently in progress ++ * ++ * returns true if buffer has been added as A-MDSP subframe, false otherwise ++ * ++ */ ++static bool rwnx_amsdu_add_subframe(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, ++ struct rwnx_sta *sta, struct rwnx_txq *txq) ++{ ++ bool res = false; ++ struct ethhdr *eth; ++ ++ /* immediately return if amsdu are not allowed for this sta */ ++ if (!txq->amsdu_len || rwnx_hw->mod_params->amsdu_maxnb < 2 || ++ !rwnx_amsdu_is_aggregable(skb) ++ ) ++ return false; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (txq->amsdu) { ++ /* aggreagation already in progress, add this buffer if enough space ++ available, otherwise end the current amsdu */ ++ struct rwnx_sw_txhdr *sw_txhdr = txq->amsdu; ++ eth = (struct ethhdr *)(skb->data); ++ ++ if (((sw_txhdr->amsdu.len + sw_txhdr->amsdu.pad + ++ rwnx_amsdu_subframe_length(eth, skb->len)) > txq->amsdu_len) || ++ rwnx_amsdu_add_subframe_header(rwnx_hw, skb, sw_txhdr)) { ++ txq->amsdu = NULL; ++ goto end; ++ } ++ ++ if (sw_txhdr->amsdu.nb >= rwnx_hw->mod_params->amsdu_maxnb) { ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].done++; ++ /* max number of subframes reached */ ++ txq->amsdu = NULL; ++ } ++ } else { ++ /* Check if a new amsdu can be started with the previous buffer ++ (if any) and this one */ ++ struct sk_buff *skb_prev = skb_peek_tail(&txq->sk_list); ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ int len1, len2; ++ ++ if (!skb_prev || !rwnx_amsdu_is_aggregable(skb_prev)) ++ goto end; ++ ++ txhdr = (struct rwnx_txhdr *)skb_prev->data; ++ sw_txhdr = txhdr->sw_hdr; ++ if ((sw_txhdr->amsdu.len) || ++ (sw_txhdr->desc.host.flags & TXU_CNTRL_RETRY)) ++ /* previous buffer is already a complete amsdu or a retry */ ++ goto end; ++ ++ eth = (struct ethhdr *)(skb_prev->data + sw_txhdr->headroom); ++ len1 = rwnx_amsdu_subframe_length(eth, (sw_txhdr->frame_len + ++ sizeof(struct ethhdr))); ++ ++ eth = (struct ethhdr *)(skb->data); ++ len2 = rwnx_amsdu_subframe_length(eth, skb->len); ++ ++ if (len1 + AMSDU_PADDING(len1) + len2 > txq->amsdu_len) ++ /* not enough space to aggregate those two buffers */ ++ goto end; ++ ++ /* Add subframe header. ++ Note: Fw will take care of adding AMDSU header for the first ++ subframe while generating 802.11 MAC header */ ++ INIT_LIST_HEAD(&sw_txhdr->amsdu.hdrs); ++ sw_txhdr->amsdu.len = len1; ++ sw_txhdr->amsdu.nb = 1; ++ sw_txhdr->amsdu.pad = AMSDU_PADDING(len1); ++ if (rwnx_amsdu_add_subframe_header(rwnx_hw, skb, sw_txhdr)) ++ goto end; ++ ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_AMSDU; ++ ++ if (sw_txhdr->amsdu.nb < rwnx_hw->mod_params->amsdu_maxnb) ++ txq->amsdu = sw_txhdr; ++ else ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].done++; ++ } ++ ++ res = true; ++ ++end: ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ return res; ++} ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++#ifdef CONFIG_BR_SUPPORT ++int aic_br_client_tx(struct rwnx_vif *vif, struct sk_buff **pskb) ++{ ++ struct sk_buff *skb = *pskb; ++ ++ /* if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) */ ++ { ++ void dhcp_flag_bcast(struct rwnx_vif *vif, struct sk_buff *skb); ++ int res, is_vlan_tag = 0, i, do_nat25 = 1; ++ unsigned short vlan_hdr = 0; ++ void *br_port = NULL; ++ ++ /* mac_clone_handle_frame(priv, skb); */ ++ ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = vif->ndev->br_port; ++#else /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) */ ++ rcu_read_lock(); ++ br_port = rcu_dereference(vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) */ ++#ifdef BR_SUPPORT_DEBUG ++ printk("SA=%pM, br_mac=%pM, type=0x%x, da[0]=%x, scdb=%pM, vif_type=%d\n", skb->data + MACADDRLEN, vif->br_mac, *((unsigned short *)(skb->data + MACADDRLEN * 2)), ++ skb->data[0], vif->scdb_mac,RWNX_VIF_TYPE(vif)); ++#endif ++ spin_lock_bh(&vif->br_ext_lock); ++ if (!(skb->data[0] & 1) && ++ br_port && ++ memcmp(skb->data + MACADDRLEN, vif->br_mac, MACADDRLEN) && ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) != __constant_htons(ETH_P_8021Q) && ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP) && ++ !memcmp(vif->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN) && vif->scdb_entry) { ++ memcpy(skb->data + MACADDRLEN, vif->ndev->dev_addr, MACADDRLEN); ++ vif->scdb_entry->ageing_timer = jiffies; ++ spin_unlock_bh(&vif->br_ext_lock); ++ } else ++ /* if (!priv->pmib->ethBrExtInfo.nat25_disable) */ ++ { ++ /* if (priv->dev->br_port && ++ * !memcmp(skb->data+MACADDRLEN, priv->br_mac, MACADDRLEN)) { */ ++#if 1 ++ if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_8021Q)) { ++ is_vlan_tag = 1; ++ vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2)); ++ skb_pull(skb, 4); ++ } ++ /* if SA == br_mac && skb== IP => copy SIP to br_ip ?? why */ ++ if (!memcmp(skb->data + MACADDRLEN, vif->br_mac, MACADDRLEN) && ++ (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP))) ++ memcpy(vif->br_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4); ++ ++ if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP)) { ++ if (memcmp(vif->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN)) { ++ #if 1 ++ void *scdb_findEntry(struct rwnx_vif *vif, unsigned char *macAddr, unsigned char *ipAddr); ++ ++ vif->scdb_entry = (struct nat25_network_db_entry *)scdb_findEntry(vif, ++ skb->data + MACADDRLEN, skb->data + WLAN_ETHHDR_LEN + 12); ++ if (vif->scdb_entry != NULL) { ++ memcpy(vif->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN); ++ memcpy(vif->scdb_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4); ++ vif->scdb_entry->ageing_timer = jiffies; ++ do_nat25 = 0; ++ } ++ #endif ++ } else { ++ if (vif->scdb_entry) { ++ vif->scdb_entry->ageing_timer = jiffies; ++ do_nat25 = 0; ++ } else { ++ memset(vif->scdb_mac, 0, MACADDRLEN); ++ memset(vif->scdb_ip, 0, 4); ++ } ++ } ++ } ++ spin_unlock_bh(&vif->br_ext_lock); ++#endif /* 1 */ ++ if (do_nat25) { ++ #if 1 ++ int nat25_db_handle(struct rwnx_vif *vif, struct sk_buff *skb, int method); ++ if (nat25_db_handle(vif, skb, NAT25_CHECK) == 0) { ++ struct sk_buff *newskb; ++ ++ if (is_vlan_tag) { ++ skb_push(skb, 4); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr; ++ } ++ ++ newskb = skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); ++ if (newskb == NULL) { ++ /* priv->ext_stats.tx_drops++; */ ++ printk("TX DROP: skb_copy fail!\n"); ++ /* goto stop_proc; */ ++ return -1; ++ } ++ dev_kfree_skb_any(skb); ++ ++ *pskb = skb = newskb; ++ if (is_vlan_tag) { ++ vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2)); ++ skb_pull(skb, 4); ++ } ++ } ++ ++ if (skb_is_nonlinear(skb)) ++ printk("%s(): skb_is_nonlinear!!\n", __FUNCTION__); ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) ++ res = skb_linearize(skb, GFP_ATOMIC); ++#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) */ ++ res = skb_linearize(skb); ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) */ ++ if (res < 0) { ++ printk("TX DROP: skb_linearize fail!\n"); ++ /* goto free_and_stop; */ ++ return -1; ++ } ++ ++ res = nat25_db_handle(vif, skb, NAT25_INSERT); ++ if (res < 0) { ++ if (res == -2) { ++ /* priv->ext_stats.tx_drops++; */ ++ printk("TX DROP: nat25_db_handle fail!\n"); ++ /* goto free_and_stop; */ ++ return -1; ++ ++ } ++ /* we just print warning message and let it go */ ++ /* DEBUG_WARN("%s()-%d: nat25_db_handle INSERT Warning!\n", __FUNCTION__, __LINE__); */ ++ /* return -1; */ /* return -1 will cause system crash on 2011/08/30! */ ++ return 0; ++ } ++ #endif ++ } ++ ++ memcpy(skb->data + MACADDRLEN, vif->ndev->dev_addr, MACADDRLEN); ++ ++ dhcp_flag_bcast(vif, skb); ++ ++ if (is_vlan_tag) { ++ skb_push(skb, 4); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr; ++ } ++ } ++#if 0 ++ else { ++ if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_8021Q)) ++ is_vlan_tag = 1; ++ ++ if (is_vlan_tag) { ++ if (ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A_VALN(skb->data)) ++ memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN); ++ } else { ++ if (ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A(skb->data)) ++ memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN); ++ } ++ } ++#endif /* 0 */ ++ ++ /* check if SA is equal to our MAC */ ++ if (memcmp(skb->data + MACADDRLEN, vif->ndev->dev_addr, MACADDRLEN)) { ++ /* priv->ext_stats.tx_drops++; */ ++ printk("TX DROP: untransformed frame SA:%02X%02X%02X%02X%02X%02X!\n", ++ skb->data[6], skb->data[7], skb->data[8], skb->data[9], skb->data[10], skb->data[11]); ++ /* goto free_and_stop; */ ++ return -1; ++ } ++ } ++ printk("%s:exit\n",__func__); ++ return 0; ++} ++#endif /* CONFIG_BR_SUPPORT */ ++ ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++/* return: ++ * 0, msg buf freed by the real driver ++ * others, skb need free by the caller,remember not use msg->skb! ++ */ ++ ++int intf_tx(struct rwnx_hw *priv,struct msg_buf *msg) ++{ ++ struct rwnx_vif *rwnx_vif = msg->rwnx_vif; ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct rwnx_sta *sta; ++ struct rwnx_txq *txq; ++ int headroom; ++ //int max_headroom; ++ int hdr_pads; ++ ++ u16 frame_len; ++ u16 frame_oft; ++ u8 tid; ++ struct sk_buff *skb=msg->skb; ++ struct ethhdr eth_t; ++ ++ move_tcpack_msg(rwnx_hw,msg); ++ kfree(msg); ++ ++ memcpy(ð_t, skb->data, sizeof(struct ethhdr)); ++ ++ /* Get the STA id and TID information */ ++ sta = rwnx_get_tx_priv(rwnx_vif, skb, &tid); ++ if (!sta) ++ goto free; ++ ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ if (txq->idx == TXQ_INACTIVE) ++ goto free; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (rwnx_amsdu_add_subframe(rwnx_hw, skb, sta, txq)) ++ return NETDEV_TX_OK; ++#endif ++ ++#ifdef CONFIG_BR_SUPPORT ++ if (1) {//(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ void *br_port = NULL; ++ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ s32 res = aic_br_client_tx(rwnx_vif, &skb); ++ if (res == -1) { ++ goto free; ++ } ++ } ++ } ++#endif /* CONFIG_BR_SUPPORT */ ++ ++ ++ /* Retrieve the pointer to the Ethernet data */ ++ // eth = (struct ethhdr *)skb->data; ++ ++ skb_pull(skb, 14); ++ //hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)eth); ++ hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)skb->data); ++ headroom = sizeof(struct rwnx_txhdr) + hdr_pads; ++ ++ skb_push(skb, headroom); ++ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) ++ goto free; ++ txhdr->sw_hdr = sw_txhdr; ++ desc = &sw_txhdr->desc; ++ ++ frame_len = (u16)skb->len - headroom;// - sizeof(*eth); ++ ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = rwnx_vif; ++ sw_txhdr->skb = skb; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ sw_txhdr->amsdu.len = 0; ++ sw_txhdr->amsdu.nb = 0; ++#endif ++ sw_txhdr->raw_frame = 0; ++ sw_txhdr->fixed_rate = 0; ++ ++ // Fill-in the descriptor ++ memcpy(&desc->host.eth_dest_addr, eth_t.h_dest, ETH_ALEN); ++ memcpy(&desc->host.eth_src_addr, eth_t.h_source, ETH_ALEN); ++ desc->host.ethertype = eth_t.h_proto; ++ desc->host.staid = sta->sta_idx; ++ desc->host.tid = tid; ++ if (unlikely(rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) ++ desc->host.vif_idx = rwnx_vif->ap_vlan.master->vif_index; ++ else ++ desc->host.vif_idx = rwnx_vif->vif_index; ++ ++ if (rwnx_vif->use_4addr && (sta->sta_idx < NX_REMOTE_STA_MAX)) ++ desc->host.flags = TXU_CNTRL_USE_4ADDR; ++ else ++ desc->host.flags = 0; ++ ++ if ((rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) && ++ rwnx_vif->sta.tdls_sta && ++ (memcmp(desc->host.eth_dest_addr.array, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) { ++ desc->host.flags |= TXU_CNTRL_TDLS; ++ rwnx_vif->sta.tdls_sta->tdls.last_tid = desc->host.tid; ++ //rwnx_vif->sta.tdls_sta->tdls.last_sn = desc->host.sn; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) { ++ if (rwnx_vif->is_resending) { ++ desc->host.flags |= TXU_CNTRL_MESH_FWD; ++ } ++ } ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_len[0] = frame_len; ++#else ++ desc->host.packet_len = frame_len; ++#endif ++ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ if (unlikely(rwnx_prep_tx(rwnx_hw, txhdr))) { ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_BUSY; ++ } ++ ++ /* Fill-in TX descriptor */ ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr) ++ + hdr_pads;// + sizeof(*eth); ++#if 0 ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_cnt = 1; ++#else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++#endif ++#endif ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ return 0;//NETDEV_TX_OK ++ ++free: ++ dev_kfree_skb_any(skb); ++ ++ return 0;//NETDEV_TX_OK ++} ++#endif ++ ++/** ++ * netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, ++ * struct net_device *dev); ++ * Called when a packet needs to be transmitted. ++ * Must return NETDEV_TX_OK , NETDEV_TX_BUSY. ++ * (can also return NETDEV_TX_LOCKED if NETIF_F_LLTX) ++ * ++ * - Initialize the desciptor for this pkt (stored in skb before data) ++ * - Push the pkt in the corresponding Txq ++ * - If possible (i.e. credit available and not in PS) the pkt is pushed ++ * to fw ++ */ ++netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct rwnx_sta *sta; ++ struct rwnx_txq *txq; ++ int headroom; ++ int max_headroom; ++ int hdr_pads; ++ ++ u16 frame_len; ++ u16 frame_oft; ++ u8 tid; ++ ++ struct ethhdr eth_t; ++#ifdef CONFIG_FILTER_TCP_ACK ++ struct msg_buf *msgbuf = NULL; ++#endif ++ ++#ifdef CONFIG_ONE_TXQ ++ skb->queue_mapping = rwnx_select_txq(rwnx_vif, skb); ++#endif ++ ++ sk_pacing_shift_update(skb->sk, rwnx_hw->tcp_pacing_shift); ++ max_headroom = sizeof(struct rwnx_txhdr); ++ ++ /* check whether the current skb can be used */ ++ if (skb_shared(skb) || (skb_headroom(skb) < max_headroom) || ++ (skb_cloned(skb) && (dev->priv_flags & IFF_BRIDGE_PORT))) { ++ struct sk_buff *newskb = skb_copy_expand(skb, max_headroom, 0, ++ GFP_ATOMIC); ++ if (unlikely(newskb == NULL)) ++ goto free; ++ ++ dev_kfree_skb_any(skb); ++ ++ skb = newskb; ++ } ++ ++ if(skb->priority < 3) ++ skb->priority = 0; ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ if(cpu_to_le16(skb->len) <= MAX_TCP_ACK){ ++ msgbuf=intf_tcp_alloc_msg(msgbuf); ++ msgbuf->rwnx_vif=rwnx_vif; ++ msgbuf->skb=skb; ++ if(filter_send_tcp_ack(rwnx_hw,msgbuf,skb->data,cpu_to_le16(skb->len))){ ++ return NETDEV_TX_OK; ++ }else{ ++ move_tcpack_msg(rwnx_hw,msgbuf); ++ kfree(msgbuf); ++ } ++ } ++#endif ++ ++ memcpy(ð_t, skb->data, sizeof(struct ethhdr)); ++ ++ /* Get the STA id and TID information */ ++ sta = rwnx_get_tx_priv(rwnx_vif, skb, &tid); ++ if (!sta) ++ goto free; ++ ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ if (txq->idx == TXQ_INACTIVE) ++ goto free; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (rwnx_amsdu_add_subframe(rwnx_hw, skb, sta, txq)) ++ return NETDEV_TX_OK; ++#endif ++ ++ #ifdef CONFIG_BR_SUPPORT ++ if (1) {//(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ void *br_port = NULL; ++ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ s32 res = aic_br_client_tx(rwnx_vif, &skb); ++ if (res == -1) { ++ goto free; ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ ++ /* Retrieve the pointer to the Ethernet data */ ++ // eth = (struct ethhdr *)skb->data; ++ ++ skb_pull(skb, 14); ++ //hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)eth); ++ hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)skb->data); ++ headroom = sizeof(struct rwnx_txhdr) + hdr_pads; ++ ++ skb_push(skb, headroom); ++ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) ++ goto free; ++ txhdr->sw_hdr = sw_txhdr; ++ desc = &sw_txhdr->desc; ++ ++ frame_len = (u16)skb->len - headroom;// - sizeof(*eth); ++ ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = rwnx_vif; ++ sw_txhdr->skb = skb; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ sw_txhdr->amsdu.len = 0; ++ sw_txhdr->amsdu.nb = 0; ++#endif ++ sw_txhdr->raw_frame = 0; ++ sw_txhdr->fixed_rate = 0; ++ ++ // Fill-in the descriptor ++ memcpy(&desc->host.eth_dest_addr, eth_t.h_dest, ETH_ALEN); ++ memcpy(&desc->host.eth_src_addr, eth_t.h_source, ETH_ALEN); ++ desc->host.ethertype = eth_t.h_proto; ++ desc->host.staid = sta->sta_idx; ++ desc->host.tid = tid; ++ if (unlikely(rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) ++ desc->host.vif_idx = rwnx_vif->ap_vlan.master->vif_index; ++ else ++ desc->host.vif_idx = rwnx_vif->vif_index; ++ ++ if (rwnx_vif->use_4addr && (sta->sta_idx < NX_REMOTE_STA_MAX)) ++ desc->host.flags = TXU_CNTRL_USE_4ADDR; ++ else ++ desc->host.flags = 0; ++ ++ if ((rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) && ++ rwnx_vif->sta.tdls_sta && ++ (memcmp(desc->host.eth_dest_addr.array, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) { ++ desc->host.flags |= TXU_CNTRL_TDLS; ++ rwnx_vif->sta.tdls_sta->tdls.last_tid = desc->host.tid; ++ //rwnx_vif->sta.tdls_sta->tdls.last_sn = desc->host.sn; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) { ++ if (rwnx_vif->is_resending) { ++ desc->host.flags |= TXU_CNTRL_MESH_FWD; ++ } ++ } ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_len[0] = frame_len; ++#else ++ desc->host.packet_len = frame_len; ++#endif ++ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ if (unlikely(rwnx_prep_tx(rwnx_hw, txhdr))) { ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_BUSY; ++ } ++ ++ /* Fill-in TX descriptor */ ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr) ++ + hdr_pads;// + sizeof(*eth); ++#if 0 ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_cnt = 1; ++#else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++#endif ++#endif ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ return NETDEV_TX_OK; ++ ++free: ++ dev_kfree_skb_any(skb); ++ ++ return NETDEV_TX_OK; ++} ++ ++#ifdef CONFIG_RWNX_MON_XMIT ++/** ++ * netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, ++ * struct net_device *dev); ++ * Called when a packet needs to be transmitted. ++ * Must return NETDEV_TX_OK , NETDEV_TX_BUSY. ++ * (can also return NETDEV_TX_LOCKED if NETIF_F_LLTX) ++ * ++ * - Initialize the desciptor for this pkt (stored in skb before data) ++ * - Push the pkt in the corresponding Txq ++ * - If possible (i.e. credit available and not in PS) the pkt is pushed ++ * to fw ++ */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)) ++#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20 ++#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 ++#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 ++#endif ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)) ++#define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01 ++#endif ++ ++char bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; ++netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ int rtap_len, ret, idx; ++ struct ieee80211_radiotap_header *rtap_hdr; // net/ieee80211_radiotap.h ++ struct ieee80211_radiotap_iterator iterator; // net/cfg80211.h ++ u8_l *rtap_buf = (u8_l *)skb->data; ++ u8_l rate; ++ ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct rwnx_sta *sta; ++ struct rwnx_txq *txq; ++ u16_l frame_len, headroom, frame_oft; ++ u8_l tid, rate_fmt = FORMATMOD_NON_HT, rate_idx = 0, txsig_bw = PHY_CHNL_BW_20; ++ u8_l *pframe, *data; ++ bool robust; ++ struct sk_buff *skb_mgmt; ++ bool offchan = false; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ rtap_hdr = (struct ieee80211_radiotap_header*)(rtap_buf); ++ rtap_len = ieee80211_get_radiotap_len(rtap_buf);//max_length ++ frame_len = skb->len; ++ ++ AICWFDBG(LOGINFO, "rwnx_start_monitor_if_xmit, skb_len=%d, rtap_len=%d\n", skb->len, rtap_len); ++//rwnx_data_dump((char*)__func__, skb->data, skb->len); ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ if (unlikely(rtap_hdr->it_version)){ ++ AICWFDBG(LOGERROR, "%s itv \r\n", __func__); ++ goto free_tag; ++ } ++ ++ if (unlikely(skb->len < rtap_len)){ ++ AICWFDBG(LOGERROR, "%s skb->len < rtap_len \r\n", __func__); ++ goto free_tag; ++ } ++ ++ if (unlikely(rtap_len < sizeof(struct ieee80211_radiotap_header))){ ++ AICWFDBG(LOGERROR, "%s rtap_len < sizeof(struct ieee80211_radiotap_header) \r\n", __func__); ++ goto free_tag; ++ } ++ ++ frame_len -= rtap_len; ++ pframe = rtap_buf + rtap_len; ++ ++ // Parse radiotap for injection items and overwrite attribs as needed ++ ret = ieee80211_radiotap_iterator_init(&iterator, rtap_hdr, rtap_len, NULL); ++ while (!ret) { ++ ret = ieee80211_radiotap_iterator_next(&iterator); ++ if (ret) { ++ continue; ++ } ++ AICWFDBG(LOGDEBUG, "%s iterator.this_arg_index:%d iterator.this_arg:%x\r\n", __func__, ++ iterator.this_arg_index, *iterator.this_arg); ++ switch (iterator.this_arg_index) { ++ case IEEE80211_RADIOTAP_RATE: ++ // This is basic 802.11b/g rate; use MCS/VHT for higher rates ++ rate = *iterator.this_arg; ++ AICWFDBG(LOGDEBUG, "rate=0x%x\n", rate); ++ for (idx = 0; idx < HW_RATE_MAX; idx++) { ++ if ((rate * 5) == tx_legrates_lut_rate[idx]) { ++ AICWFDBG(LOGDEBUG, "%s datarate:%d \r\n", __func__, tx_legrates_lut_rate[idx]); ++ break; ++ } ++ } ++ ++ if (idx < HW_RATE_MAX) { ++ rate_idx = idx; ++ AICWFDBG(LOGDEBUG, "rate_idx = %d \r\n", rate_idx); ++ } else { ++ AICWFDBG(LOGERROR, "invalid radiotap rate: %d\n", rate); ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_TX_FLAGS: { ++ u16_l txflags = get_unaligned_le16(iterator.this_arg); ++ AICWFDBG(LOGDEBUG, "txflags=0x%x\n", txflags); ++ if ((txflags & IEEE80211_RADIOTAP_F_TX_NOACK) == 0) { ++ AICWFDBG(LOGDEBUG, " TX_NOACK\n"); ++ } ++ if (txflags & 0x0010) { // Use preconfigured seq num ++ // NOTE: this is currently ignored due to qos_en=_FALSE and HW seq num override ++ AICWFDBG(LOGDEBUG, " GetSequence\n"); ++ } ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_MCS: { ++ u8_l mcs_have = iterator.this_arg[0]; ++ AICWFDBG(LOGDEBUG, "mcs_have=0x%x\n", mcs_have); ++ rate_fmt = FORMATMOD_HT_MF; ++ if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_BW) { ++ u8_l bw = (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_BW_MASK); ++ u8_l ch_offset = 0; ++ if (bw == IEEE80211_RADIOTAP_MCS_BW_40) { ++ txsig_bw = PHY_CHNL_BW_40; ++ } else if (bw == IEEE80211_RADIOTAP_MCS_BW_20L) { ++ bw = IEEE80211_RADIOTAP_MCS_BW_20; ++ ch_offset = 1; // CHNL_OFFSET_LOWER; ++ } else if (bw == IEEE80211_RADIOTAP_MCS_BW_20U) { ++ bw = IEEE80211_RADIOTAP_MCS_BW_20; ++ ch_offset = 2; // CHNL_OFFSET_UPPER; ++ } ++ AICWFDBG(LOGDEBUG, " bw=%d, ch_offset=%d\n", bw, ch_offset); ++ } ++ if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_MCS) { ++ u8_l fixed_rate = iterator.this_arg[2] & 0x7f; ++ if (fixed_rate > 31) { ++ fixed_rate = 0; ++ } ++ rate_idx = fixed_rate; ++ AICWFDBG(LOGDEBUG, " fixed_rate=0x%x\n", fixed_rate); ++ } ++ if ((mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_GI) && (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_SGI)) { ++ AICWFDBG(LOGDEBUG, " sgi\n"); ++ } ++ if ((mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_FEC) && (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_FEC_LDPC)) { ++ AICWFDBG(LOGDEBUG, " ldpc\n"); ++ } ++ if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_STBC) { ++ u8 stbc = (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT; ++ AICWFDBG(LOGDEBUG, " stbc=0x%x\n", stbc); ++ } ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_VHT: { ++ unsigned int mcs, nss; ++ u8 known = iterator.this_arg[0]; ++ u8 flags = iterator.this_arg[2]; ++ rate_fmt = FORMATMOD_VHT; ++ AICWFDBG(LOGDEBUG, "known=0x%x, flags=0x%x\n", known, flags); ++ // NOTE: this code currently only supports 1SS for radiotap defined rates ++ if ((known & IEEE80211_RADIOTAP_VHT_KNOWN_STBC) && (flags & IEEE80211_RADIOTAP_VHT_FLAG_STBC)) { ++ AICWFDBG(LOGDEBUG, " stbc\n"); ++ } ++ if ((known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) && (flags & IEEE80211_RADIOTAP_VHT_FLAG_SGI)) { ++ AICWFDBG(LOGDEBUG, " sgi\n"); ++ } ++ if (known & IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) { ++ u8_l bw = iterator.this_arg[3] & 0x1F; ++ AICWFDBG(LOGDEBUG, " bw=0x%x\n",bw); ++ // NOTE: there are various L and U, but we just use straight 20/40/80 ++ // since it's not clear how to set CHNL_OFFSET_LOWER/_UPPER with different ++ // sideband sizes/configurations. TODO. ++ // Also, any 160 is treated as 80 due to lack of WIDTH_160. ++ txsig_bw = PHY_CHNL_BW_40; ++ if (bw == 0) { ++ txsig_bw = PHY_CHNL_BW_20; ++ AICWFDBG(LOGDEBUG, " 20M\n"); ++ } else if (bw >=1 && bw <= 3) { ++ AICWFDBG(LOGDEBUG, " 40M\n"); ++ } else if (bw >=4 && bw <= 10) { ++ AICWFDBG(LOGDEBUG, " 80M\n"); ++ } else if (bw >= 11 && bw <= 25) { ++ AICWFDBG(LOGDEBUG, " 160M\n"); ++ } ++ } ++ // User 0 ++ nss = iterator.this_arg[4] & 0x0F; // Number of spatial streams ++ AICWFDBG(LOGDEBUG, " nss=0x%x\n", nss); ++ if (nss > 0) { ++ if (nss > 4) nss = 4; ++ mcs = (iterator.this_arg[4]>>4) & 0x0F; // MCS rate index ++ if (mcs > 8) mcs = 9; ++ rate_idx = mcs; ++ AICWFDBG(LOGDEBUG, " mcs=0x%x\n", mcs); ++ if (iterator.this_arg[8] & IEEE80211_RADIOTAP_CODING_LDPC_USER0) { ++ AICWFDBG(LOGDEBUG, " ldpc\n"); ++ } ++ } ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_HE: { ++ u16 data1 = ((u16)iterator.this_arg[1] << 8) | iterator.this_arg[0]; ++ u16 data2 = ((u16)iterator.this_arg[3] << 8) | iterator.this_arg[2]; ++ u16 data3 = ((u16)iterator.this_arg[5] << 8) | iterator.this_arg[4]; ++ u16 data5 = ((u16)iterator.this_arg[9] << 8) | iterator.this_arg[8]; ++ u8 fmt_he = data1 & IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK; ++ if (fmt_he == IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU) { ++ rate_fmt = FORMATMOD_HE_MU; ++ } else if (fmt_he == IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU) { ++ rate_fmt = FORMATMOD_HE_ER; ++ } else { ++ rate_fmt = FORMATMOD_HE_SU; ++ } ++ if (data1 & IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN) { ++ u8 mcs = (data3 & IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS) >> 8; ++ if (mcs > 11) mcs = 11; ++ rate_idx = mcs; ++ } ++ if (data1 & IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN) { ++ u8 bw = data5 & IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC; ++ txsig_bw = (bw == IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ) ? PHY_CHNL_BW_20 : PHY_CHNL_BW_40; ++ } ++ if (data2 & IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN) { ++ u8 gi = (data5 & IEEE80211_RADIOTAP_HE_DATA5_GI) >> 4; ++ AICWFDBG(LOGDEBUG, " gi: %d\n", gi); ++ } ++ } ++ break; ++ ++ default: ++ AICWFDBG(LOGERROR, "unparsed arg: 0x%x\n",iterator.this_arg_index); ++ break; ++ } ++ } ++ ++ #if 0 ++ // dump buffer ++ tmp_len = 128; ++ if (skb->len < 128) { ++ tmp_len = skb->len; ++ } ++ for (idx = 0; idx < tmp_len; idx+=16) { ++ printk("[%04X] %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", idx, ++ rtap_buf[idx+0],rtap_buf[idx+1],rtap_buf[idx+2],rtap_buf[idx+3], ++ rtap_buf[idx+4],rtap_buf[idx+5],rtap_buf[idx+6],rtap_buf[idx+7], ++ rtap_buf[idx+8],rtap_buf[idx+9],rtap_buf[idx+10],rtap_buf[idx+11], ++ rtap_buf[idx+12],rtap_buf[idx+13],rtap_buf[idx+14],rtap_buf[idx+15]); ++ } ++ #endif ++ //rwnx_data_dump((char*)__func__, pframe, frame_len); ++ ++ /* Get the STA id and TID information */ ++ sta = rwnx_get_tx_priv(vif, skb, &tid); ++ //if (!sta) { ++ // printk("sta=null, tid=0x%x\n", tid); ++ //} ++ /* Set TID and Queues indexes */ ++ if (sta) { ++ txq = rwnx_txq_sta_get(sta, 8, rwnx_hw); ++ } else { ++ if (offchan) ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ else ++ txq = rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE); ++ } ++ if (txq->idx == TXQ_INACTIVE) { ++ AICWFDBG(LOGERROR, "TXQ_INACTIVE\n"); ++ goto free_tag; ++ } ++ // prepare to xmit ++ headroom = sizeof(struct rwnx_txhdr); ++ skb_mgmt = dev_alloc_skb(headroom + frame_len); ++ if (!skb_mgmt) { ++ AICWFDBG(LOGERROR, "skb_mgmt alloc fail\n"); ++ goto free_tag; ++ } ++ skb_reserve(skb_mgmt, headroom); ++ data = skb_put(skb_mgmt, frame_len); ++ /* Copy the provided data */ ++ memcpy(data, pframe, frame_len); ++ robust = ieee80211_is_robust_mgmt_frame( ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)) ++ (void*)skb_mgmt ++#else ++ skb_mgmt ++#endif ++ ); ++ skb_push(skb_mgmt, headroom); ++ /* Fill the TX Header */ ++ txhdr = (struct rwnx_txhdr *)skb_mgmt->data; ++ txhdr->hw_hdr.cfm.status.value = 0; ++ /* Fill the SW TX Header */ ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) { ++ dev_kfree_skb(skb_mgmt); ++ AICWFDBG(LOGERROR, "sw_txhdr alloc fail\n"); ++ goto free_tag; ++ } ++ txhdr->sw_hdr = sw_txhdr; ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = vif; ++ sw_txhdr->skb = skb_mgmt; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb_mgmt->len - offsetof(struct rwnx_txhdr, hw_hdr); ++ sw_txhdr->raw_frame = 1; ++ sw_txhdr->fixed_rate = 1; ++ sw_txhdr->rate_config = ((rate_fmt << FORMAT_MOD_TX_RCX_OFT) & FORMAT_MOD_TX_RCX_MASK) | ++ ((txsig_bw << BW_TX_RCX_OFT) & BW_TX_RCX_MASK) | ++ ((rate_idx << MCS_INDEX_TX_RCX_OFT) & MCS_INDEX_TX_RCX_MASK); // from radiotap ++ /* Fill the Descriptor to be provided to the MAC SW */ ++ desc = &sw_txhdr->desc; ++ desc->host.staid = (sta) ? sta->sta_idx : 0xFF; ++ desc->host.vif_idx = vif->vif_index; ++ desc->host.tid = 0xFF; ++ desc->host.flags = TXU_CNTRL_MGMT; ++ if (robust) { ++ desc->host.flags |= TXU_CNTRL_MGMT_ROBUST; ++ } ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr); ++ #if 0 ++ #ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_len[0] = frame_len; ++ desc->host.packet_cnt = 1; ++ #else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_len = frame_len; ++ #endif ++ #else ++ desc->host.packet_len = frame_len; ++ #endif ++ ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ memcpy(desc->host.eth_dest_addr.array, bcast, ETH_ALEN); ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ AICWFDBG(LOGTRACE, "%s send data\r\n", __func__); ++ if (rwnx_txq_queue_skb(skb_mgmt, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++free_tag: ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++} ++#endif ++ ++ ++/** ++ * rwnx_start_mgmt_xmit - Transmit a management frame ++ * ++ * @vif: Vif that send the frame ++ * @sta: Destination of the frame. May be NULL if the destiantion is unknown ++ * to the AP. ++ * @params: Mgmt frame parameters ++ * @offchan: Indicate whether the frame must be send via the offchan TXQ. ++ * (is is redundant with params->offchan ?) ++ * @cookie: updated with a unique value to identify the frame with upper layer ++ * ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct cfg80211_mgmt_tx_params *params, bool offchan, ++ u64 *cookie) ++#else ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct ieee80211_channel *channel, bool offchan, ++ unsigned int wait, const u8 *buf, size_t len, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ bool no_cck, ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) ++ bool dont_wait_for_ack, ++ #endif ++ u64 *cookie) ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++{ ++ struct rwnx_hw *rwnx_hw = vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct sk_buff *skb; ++ u16 frame_len, headroom, frame_oft; ++ u8 *data; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ struct rwnx_txq *txq; ++ bool robust; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ const u8 *buf = params->buf; ++ size_t len = params->len; ++ bool no_cck = params->no_cck; ++ #endif ++ ++ AICWFDBG(LOGDEBUG,"mgmt xmit %x %x ",buf[0],buf[1]); ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ headroom = sizeof(struct rwnx_txhdr); ++ frame_len = len; ++ ++ //---------------------------------------------------------------------- ++ ++ /* Set TID and Queues indexes */ ++ if (sta) { ++ txq = rwnx_txq_sta_get(sta, 8, rwnx_hw); ++ } else { ++ if (offchan) ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ else ++ txq = rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE); ++ } ++ ++ /* Ensure that TXQ is active */ ++ if (txq->idx == TXQ_INACTIVE) { ++ netdev_dbg(vif->ndev, "TXQ inactive\n"); ++ return -EBUSY; ++ } ++ ++ /* ++ * Create a SK Buff object that will contain the provided data ++ */ ++ skb = dev_alloc_skb(headroom + frame_len); ++ ++ if (!skb) { ++ return -ENOMEM; ++ } ++ ++ *cookie = (unsigned long)skb; ++ ++ /* ++ * Move skb->data pointer in order to reserve room for rwnx_txhdr ++ * headroom value will be equal to sizeof(struct rwnx_txhdr) ++ */ ++ skb_reserve(skb, headroom); ++ ++ /* ++ * Extend the buffer data area in order to contain the provided packet ++ * len value (for skb) will be equal to param->len ++ */ ++ data = skb_put(skb, frame_len); ++ /* Copy the provided data */ ++ memcpy(data, buf, frame_len); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) ++ robust = ieee80211_is_robust_mgmt_frame(skb); ++#else ++ if (skb->len < 25){ ++ robust = false; ++ } ++ robust = ieee80211_is_robust_mgmt_frame((void *)skb->data); ++#endif ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) ++ /* Update CSA counter if present */ ++ if (unlikely(params->n_csa_offsets) && ++ vif->wdev.iftype == NL80211_IFTYPE_AP && ++ vif->ap.csa) { ++ int i; ++ ++ data = skb->data; ++ for (i = 0; i < params->n_csa_offsets ; i++) { ++ data[params->csa_offsets[i]] = vif->ap.csa->count; ++ } ++ } ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ ++ /* ++ * Go back to the beginning of the allocated data area ++ * skb->data pointer will move backward ++ */ ++ skb_push(skb, headroom); ++ ++ //---------------------------------------------------------------------- ++ ++ /* Fill the TX Header */ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ //---------------------------------------------------------------------- ++ ++ /* Fill the SW TX Header */ ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) { ++ dev_kfree_skb(skb); ++ return -ENOMEM; ++ } ++ txhdr->sw_hdr = sw_txhdr; ++ ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = vif; ++ sw_txhdr->skb = skb; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ sw_txhdr->amsdu.len = 0; ++ sw_txhdr->amsdu.nb = 0; ++#endif ++ sw_txhdr->raw_frame = 0; ++ sw_txhdr->fixed_rate = 0; ++ ++ //---------------------------------------------------------------------- ++ ++ /* Fill the Descriptor to be provided to the MAC SW */ ++ desc = &sw_txhdr->desc; ++ ++ desc->host.ethertype = 0; ++ desc->host.staid = (sta) ? sta->sta_idx : 0xFF; ++ desc->host.vif_idx = vif->vif_index; ++ desc->host.tid = 0xFF; ++ desc->host.flags = TXU_CNTRL_MGMT; ++ if (robust) ++ desc->host.flags |= TXU_CNTRL_MGMT_ROBUST; ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_len[0] = frame_len; ++#else ++ desc->host.packet_len = frame_len; ++#endif ++ ++ if (no_cck) { ++ desc->host.flags |= TXU_CNTRL_MGMT_NO_CCK; ++ } ++ ++ /* Get DMA Address */ ++ if (unlikely(rwnx_prep_tx(rwnx_hw, txhdr))) { ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ dev_kfree_skb(skb); ++ return -EBUSY; ++ } ++ ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr); ++#if 0 ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_cnt = 1; ++#else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++#endif ++#endif ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ //---------------------------------------------------------------------- ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ return 0; ++} ++ ++/** ++ * rwnx_txdatacfm - FW callback for TX confirmation ++ * ++ * called with tx_lock hold ++ */ ++int rwnx_txdatacfm(void *pthis, void *host_id) ++{ ++ struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)pthis; ++ struct sk_buff *skb = host_id; ++ struct rwnx_txhdr *txhdr; ++ union rwnx_hw_txstatus rwnx_txst; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct rwnx_hwq *hwq; ++ struct rwnx_txq *txq; ++ int headroom; ++ //int peek_off = offsetof(struct rwnx_hw_txhdr, cfm); ++ //int peek_len = sizeof(((struct rwnx_hw_txhdr *)0)->cfm); ++ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ sw_txhdr = txhdr->sw_hdr; ++ ++ /* Read status in the TX control header */ ++ rwnx_txst = txhdr->hw_hdr.cfm.status; ++ ++ /* Check status in the header. If status is null, it means that the buffer ++ * was not transmitted and we have to return immediately */ ++ if (rwnx_txst.value == 0) { ++ return -1; ++ } ++ ++#ifdef AICWF_USB_SUPPORT ++ if (rwnx_hw->usbdev->state == USB_DOWN_ST) { ++ headroom = sw_txhdr->headroom; ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ consume_skb(skb); ++ return 0; ++ } ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ if(rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { ++ headroom = sw_txhdr->headroom; ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ consume_skb(skb); ++ return 0; ++ } ++#endif ++ ++ txq = sw_txhdr->txq; ++ /* don't use txq->hwq as it may have changed between push and confirm */ ++ hwq = &rwnx_hw->hwq[sw_txhdr->hw_queue]; ++ rwnx_txq_confirm_any(rwnx_hw, txq, hwq, sw_txhdr); ++ ++ /* Update txq and HW queue credits */ ++ if (sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT) { ++ printk("done=%d retry_required=%d sw_retry_required=%d acknowledged=%d\n", ++ rwnx_txst.tx_done, rwnx_txst.retry_required, ++ rwnx_txst.sw_retry_required, rwnx_txst.acknowledged); ++#ifdef CREATE_TRACE_POINTS ++ trace_mgmt_cfm(sw_txhdr->rwnx_vif->vif_index, ++ (sw_txhdr->rwnx_sta) ? sw_txhdr->rwnx_sta->sta_idx : 0xFF, ++ rwnx_txst.acknowledged); ++#endif ++ /* Confirm transmission to CFG80211 */ ++ cfg80211_mgmt_tx_status(&sw_txhdr->rwnx_vif->wdev, ++ (unsigned long)skb, ++ (skb->data + sw_txhdr->headroom), ++ sw_txhdr->frame_len, ++ rwnx_txst.acknowledged, ++ GFP_ATOMIC); ++ } else if ((txq->idx != TXQ_INACTIVE) && ++ (rwnx_txst.retry_required || rwnx_txst.sw_retry_required)) { ++ bool sw_retry = (rwnx_txst.sw_retry_required) ? true : false; ++ ++ /* Reset the status */ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ /* The confirmed packet was part of an AMPDU and not acked ++ * correctly, so reinject it in the TX path to be retried */ ++ rwnx_tx_retry(rwnx_hw, skb, txhdr, sw_retry); ++ return 0; ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_skb_confirm(skb, txq, hwq, &txhdr->hw_hdr.cfm); ++#endif ++ /* STA may have disconnect (and txq stopped) when buffers were stored ++ in fw. In this case do nothing when they're returned */ ++ if (txq->idx != TXQ_INACTIVE) { ++ #if 0 ++ if (txhdr->hw_hdr.cfm.credits) { ++ txq->credits += txhdr->hw_hdr.cfm.credits; ++ if (txq->credits <= 0) ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); ++ else if (txq->credits > 0) ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_FULL); ++ } ++ #endif ++ ++ /* continue service period */ ++ if (unlikely(txq->push_limit && !rwnx_txq_is_full(txq))) { ++ rwnx_txq_add_to_hw_list(txq); ++ } ++ } ++ ++ if (txhdr->hw_hdr.cfm.ampdu_size && ++ txhdr->hw_hdr.cfm.ampdu_size < IEEE80211_MAX_AMPDU_BUF) ++ rwnx_hw->stats.ampdus_tx[txhdr->hw_hdr.cfm.ampdu_size - 1]++; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ txq->amsdu_len = txhdr->hw_hdr.cfm.amsdu_size; ++#endif ++ ++ /* Update statistics */ ++ sw_txhdr->rwnx_vif->net_stats.tx_packets++; ++ sw_txhdr->rwnx_vif->net_stats.tx_bytes += sw_txhdr->frame_len; ++ ++ /* Release SKBs */ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->desc.host.flags & TXU_CNTRL_AMSDU) { ++ struct rwnx_amsdu_txhdr *amsdu_txhdr; ++ list_for_each_entry(amsdu_txhdr, &sw_txhdr->amsdu.hdrs, list) { ++ rwnx_amsdu_del_subframe_header(amsdu_txhdr); ++ consume_skb(amsdu_txhdr->skb); ++ } ++ } ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++ headroom = sw_txhdr->headroom; ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ consume_skb(skb); ++ ++ return 0; ++} ++ ++/** ++ * rwnx_txq_credit_update - Update credit for one txq ++ * ++ * @rwnx_hw: Driver main data ++ * @sta_idx: STA idx ++ * @tid: TID ++ * @update: offset to apply in txq credits ++ * ++ * Called when fw send ME_TX_CREDITS_UPDATE_IND message. ++ * Apply @update to txq credits, and stop/start the txq if needed ++ */ ++void rwnx_txq_credit_update(struct rwnx_hw *rwnx_hw, int sta_idx, u8 tid, ++ s8 update) ++{ ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[sta_idx]; ++ struct rwnx_txq *txq; ++ ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ if (txq->idx != TXQ_INACTIVE) { ++ //txq->credits += update; ++#ifdef CREATE_TRACE_POINTS ++ trace_credit_update(txq, update); ++#endif ++ if (txq->credits <= 0) ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); ++ else ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_FULL); ++ } ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h +new file mode 100644 +index 000000000000..b7c863ff3284 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h +@@ -0,0 +1,196 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tx.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_TX_H_ ++#define _RWNX_TX_H_ ++ ++#include ++#include ++#include ++#include "lmac_types.h" ++#include "ipc_shared.h" ++#include "rwnx_txq.h" ++#include "hal_desc.h" ++ ++#define RWNX_HWQ_BK 0 ++#define RWNX_HWQ_BE 1 ++#define RWNX_HWQ_VI 2 ++#define RWNX_HWQ_VO 3 ++#define RWNX_HWQ_BCMC 4 ++#define RWNX_HWQ_NB NX_TXQ_CNT ++#define RWNX_HWQ_ALL_ACS (RWNX_HWQ_BK | RWNX_HWQ_BE | RWNX_HWQ_VI | RWNX_HWQ_VO) ++#define RWNX_HWQ_ALL_ACS_BIT (BIT(RWNX_HWQ_BK) | BIT(RWNX_HWQ_BE) | \ ++ BIT(RWNX_HWQ_VI) | BIT(RWNX_HWQ_VO)) ++ ++#define RWNX_TX_LIFETIME_MS 1000 ++#define RWNX_TX_MAX_RATES NX_TX_MAX_RATES ++ ++#define RWNX_SWTXHDR_ALIGN_SZ 4 ++#define RWNX_SWTXHDR_ALIGN_MSK (RWNX_SWTXHDR_ALIGN_SZ - 1) ++#define RWNX_SWTXHDR_ALIGN_PADS(x) \ ++ ((RWNX_SWTXHDR_ALIGN_SZ - ((x) & RWNX_SWTXHDR_ALIGN_MSK)) \ ++ & RWNX_SWTXHDR_ALIGN_MSK) ++#if RWNX_SWTXHDR_ALIGN_SZ & RWNX_SWTXHDR_ALIGN_MSK ++#error bad RWNX_SWTXHDR_ALIGN_SZ ++#endif ++ ++#define AMSDU_PADDING(x) ((4 - ((x) & 0x3)) & 0x3) ++ ++#define TXU_CNTRL_RETRY BIT(0) ++#define TXU_CNTRL_MORE_DATA BIT(2) ++#define TXU_CNTRL_MGMT BIT(3) ++#define TXU_CNTRL_MGMT_NO_CCK BIT(4) ++#define TXU_CNTRL_AMSDU BIT(6) ++#define TXU_CNTRL_MGMT_ROBUST BIT(7) ++#define TXU_CNTRL_USE_4ADDR BIT(8) ++#define TXU_CNTRL_EOSP BIT(9) ++#define TXU_CNTRL_MESH_FWD BIT(10) ++#define TXU_CNTRL_TDLS BIT(11) ++ ++extern const int rwnx_tid2hwq[IEEE80211_NUM_TIDS]; ++ ++/** ++ * struct rwnx_amsdu_txhdr - Structure added in skb headroom (instead of ++ * rwnx_txhdr) for amsdu subframe buffer (except for the first subframe ++ * that has a normal rwnx_txhdr) ++ * ++ * @list List of other amsdu subframe (rwnx_sw_txhdr.amsdu.hdrs) ++ * @map_len Length to be downloaded for this subframe ++ * @dma_addr Buffer address form embedded point of view ++ * @skb skb ++ * @pad padding added before this subframe ++ * (only use when amsdu must be dismantled) ++ * @msdu_len Size, in bytes, of the MSDU (without padding nor amsdu header) ++ */ ++struct rwnx_amsdu_txhdr { ++ struct list_head list; ++ size_t map_len; ++ dma_addr_t dma_addr; ++ struct sk_buff *skb; ++ u16 pad; ++ u16 msdu_len; ++}; ++ ++/** ++ * struct rwnx_amsdu - Structure to manage creation of an A-MSDU, updated ++ * only In the first subframe of an A-MSDU ++ * ++ * @hdrs List of subframe of rwnx_amsdu_txhdr ++ * @len Current size for this A-MDSU (doesn't take padding into account) ++ * 0 means that no amsdu is in progress ++ * @nb Number of subframe in the amsdu ++ * @pad Padding to add before adding a new subframe ++ */ ++struct rwnx_amsdu { ++ struct list_head hdrs; ++ u16 len; ++ u8 nb; ++ u8 pad; ++}; ++ ++/** ++ * struct rwnx_sw_txhdr - Software part of tx header ++ * ++ * @rwnx_sta sta to which this buffer is addressed ++ * @rwnx_vif vif that send the buffer ++ * @txq pointer to TXQ used to send the buffer ++ * @hw_queue Index of the HWQ used to push the buffer. ++ * May be different than txq->hwq->id on confirmation. ++ * @frame_len Size of the frame (doesn't not include mac header) ++ * (Only used to update stat, can't we use skb->len instead ?) ++ * @headroom Headroom added in skb to add rwnx_txhdr ++ * (Only used to remove it before freeing skb, is it needed ?) ++ * @amsdu Description of amsdu whose first subframe is this buffer ++ * (amsdu.nb = 0 means this buffer is not part of amsdu) ++ * @skb skb received from transmission ++ * @map_len Length mapped for DMA (only rwnx_hw_txhdr and data are mapped) ++ * @dma_addr DMA address after mapping ++ * @desc Buffer description that will be copied in shared mem for FW ++ */ ++struct rwnx_sw_txhdr { ++ struct rwnx_sta *rwnx_sta; ++ struct rwnx_vif *rwnx_vif; ++ struct rwnx_txq *txq; ++ u8 hw_queue; ++ u16 frame_len; ++ u16 headroom; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ struct rwnx_amsdu amsdu; ++#endif ++ u32 need_cfm; ++ struct sk_buff *skb; ++ ++ size_t map_len; ++ dma_addr_t dma_addr; ++ struct txdesc_api desc; ++ ++ u8 raw_frame; ++ u8 fixed_rate; ++ u16 rate_config; ++}; ++ ++/** ++ * struct rwnx_txhdr - Stucture to control transimission of packet ++ * (Added in skb headroom) ++ * ++ * @sw_hdr: Information from driver ++ * @cache_guard: ++ * @hw_hdr: Information for/from hardware ++ */ ++struct rwnx_txhdr { ++ struct rwnx_sw_txhdr *sw_hdr; ++ char cache_guard[L1_CACHE_BYTES]; ++ struct rwnx_hw_txhdr hw_hdr; ++}; ++ ++u16 rwnx_select_txq(struct rwnx_vif *rwnx_vif, struct sk_buff *skb); ++netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct cfg80211_mgmt_tx_params *params, bool offchan, ++ u64 *cookie); ++#else ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct ieee80211_channel *channel, bool offchan, ++ unsigned int wait, const u8 *buf, size_t len, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ bool no_cck, ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) ++ bool dont_wait_for_ack, ++ #endif ++ u64 *cookie); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ ++#ifdef CONFIG_RWNX_MON_XMIT ++int rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *dev); ++#endif ++int rwnx_txdatacfm(void *pthis, void *host_id); ++ ++struct rwnx_hw; ++struct rwnx_sta; ++void rwnx_set_traffic_status(struct rwnx_hw *rwnx_hw, ++ struct rwnx_sta *sta, ++ bool available, ++ u8 ps_id); ++void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ bool enable); ++void rwnx_ps_bh_traffic_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ u16 pkt_req, u8 ps_id); ++ ++void rwnx_switch_vif_sta_txq(struct rwnx_sta *sta, struct rwnx_vif *old_vif, ++ struct rwnx_vif *new_vif); ++ ++int rwnx_dbgfs_print_sta(char *buf, size_t size, struct rwnx_sta *sta, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_credit_update(struct rwnx_hw *rwnx_hw, int sta_idx, u8 tid, ++ s8 update); ++void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags); ++ ++#endif /* _RWNX_TX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c +new file mode 100644 +index 000000000000..9bdc07268407 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c +@@ -0,0 +1,1371 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_txq.c ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++#include "rwnx_tx.h" ++#include "ipc_host.h" ++#include "rwnx_events.h" ++ ++/****************************************************************************** ++ * Utils functions ++ *****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++const int nx_tid_prio[NX_NB_TID_PER_STA] = {7, 6, 5, 4, 3, 0, 2, 1}; ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++extern int tx_fc_low_water; ++extern int tx_fc_high_water; ++#endif ++ ++static inline int rwnx_txq_sta_idx(struct rwnx_sta *sta, u8 tid) ++{ ++ if (is_multicast_sta(sta->sta_idx)){ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ return NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + sta->vif_idx; ++ }else{ ++ return NX_FIRST_VIF_TXQ_IDX + sta->vif_idx; ++ } ++ }else{ ++ return (sta->sta_idx * NX_NB_TXQ_PER_STA) + tid; ++ } ++} ++ ++static inline int rwnx_txq_vif_idx(struct rwnx_vif *vif, u8 type) ++{ ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ return NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + master_vif_idx(vif) + (type * NX_VIRT_DEV_MAX); ++ }else{ ++ return NX_FIRST_VIF_TXQ_IDX + master_vif_idx(vif) + (type * NX_VIRT_DEV_MAX); ++ } ++ ++} ++ ++struct rwnx_txq *rwnx_txq_sta_get(struct rwnx_sta *sta, u8 tid, ++ struct rwnx_hw *rwnx_hw) ++{ ++ if (tid >= NX_NB_TXQ_PER_STA) ++ tid = 0; ++ ++ return &rwnx_hw->txq[rwnx_txq_sta_idx(sta, tid)]; ++} ++ ++struct rwnx_txq *rwnx_txq_vif_get(struct rwnx_vif *vif, u8 type) ++{ ++ if (type > NX_UNK_TXQ_TYPE) ++ type = NX_BCMC_TXQ_TYPE; ++ ++ return &vif->rwnx_hw->txq[rwnx_txq_vif_idx(vif, type)]; ++} ++ ++static inline struct rwnx_sta *rwnx_txq_2_sta(struct rwnx_txq *txq) ++{ ++ return txq->sta; ++} ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ ++/****************************************************************************** ++ * Init/Deinit functions ++ *****************************************************************************/ ++/** ++ * rwnx_txq_init - Initialize a TX queue ++ * ++ * @txq: TX queue to be initialized ++ * @idx: TX queue index ++ * @status: TX queue initial status ++ * @hwq: Associated HW queue ++ * @ndev: Net device this queue belongs to ++ * (may be null for non netdev txq) ++ * ++ * Each queue is initialized with the credit of @NX_TXQ_INITIAL_CREDITS. ++ */ ++static void rwnx_txq_init(struct rwnx_txq *txq, int idx, u8 status, ++ struct rwnx_hwq *hwq, int tid, ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_sta *sta, struct net_device *ndev ++#endif ++ ) ++{ ++ int i; ++ int nx_first_unk_txq_idx = NX_FIRST_UNK_TXQ_IDX; ++ int nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX; ++ int nx_first_vif_txq_idx = NX_FIRST_VIF_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_first_unk_txq_idx = NX_FIRST_UNK_TXQ_IDX_FOR_OLD_IC; ++ nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC; ++ nx_first_vif_txq_idx = NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ ++ txq->idx = idx; ++ txq->status = status; ++ txq->credits = NX_TXQ_INITIAL_CREDITS; ++ txq->pkt_sent = 0; ++ skb_queue_head_init(&txq->sk_list); ++ txq->last_retry_skb = NULL; ++ txq->nb_retry = 0; ++ txq->hwq = hwq; ++ txq->sta = sta; ++ for (i = 0; i < CONFIG_USER_MAX ; i++) ++ txq->pkt_pushed[i] = 0; ++ txq->push_limit = 0; ++ txq->tid = tid; ++#ifdef CONFIG_MAC80211_TXQ ++ txq->nb_ready_mac80211 = 0; ++#endif ++#ifdef CONFIG_RWNX_FULLMAC ++ txq->ps_id = LEGACY_PS_ID; ++ if (idx < nx_first_vif_txq_idx) { ++ int sta_idx = sta->sta_idx; ++ int tid = idx - (sta_idx * NX_NB_TXQ_PER_STA); ++ if (tid < NX_NB_TID_PER_STA) ++ txq->ndev_idx = NX_STA_NDEV_IDX(tid, sta_idx); ++ else ++ txq->ndev_idx = NDEV_NO_TXQ; ++ } else if (idx < nx_first_unk_txq_idx) { ++ txq->ndev_idx = nx_bcmc_txq_ndev_idx; ++ } else { ++ txq->ndev_idx = NDEV_NO_TXQ; ++ } ++ txq->ndev = ndev; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ txq->amsdu = NULL; ++ txq->amsdu_len = 0; ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++/** ++ * rwnx_txq_flush - Flush all buffers queued for a TXQ ++ * ++ * @rwnx_hw: main driver data ++ * @txq: txq to flush ++ */ ++void rwnx_txq_flush(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq) ++{ ++ struct sk_buff *skb; ++ ++ ++ while ((skb = skb_dequeue(&txq->sk_list)) != NULL) { ++ struct rwnx_sw_txhdr *sw_txhdr = ((struct rwnx_txhdr *)skb->data)->sw_hdr; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->desc.host.packet_cnt > 1) { ++ struct rwnx_amsdu_txhdr *amsdu_txhdr; ++ list_for_each_entry(amsdu_txhdr, &sw_txhdr->amsdu.hdrs, list) { ++ //dma_unmap_single(rwnx_hw->dev, amsdu_txhdr->dma_addr, ++ // amsdu_txhdr->map_len, DMA_TO_DEVICE); ++ dev_kfree_skb_any(amsdu_txhdr->skb); ++ } ++ } ++#endif ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ //dma_unmap_single(rwnx_hw->dev, sw_txhdr->dma_addr, sw_txhdr->map_len, ++ // DMA_TO_DEVICE); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ dev_kfree_skb_any(skb); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } ++} ++ ++/** ++ * rwnx_txq_deinit - De-initialize a TX queue ++ * ++ * @rwnx_hw: Driver main data ++ * @txq: TX queue to be de-initialized ++ * Any buffer stuck in a queue will be freed. ++ */ ++static void rwnx_txq_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq) ++{ ++ if (txq->idx == TXQ_INACTIVE) ++ return; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ rwnx_txq_del_from_hw_list(txq); ++ txq->idx = TXQ_INACTIVE; ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ rwnx_txq_flush(rwnx_hw, txq); ++} ++ ++/** ++ * rwnx_txq_vif_init - Initialize all TXQ linked to a vif ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: Pointer on VIF ++ * @status: Intial txq status ++ * ++ * Softmac : 1 VIF TXQ per HWQ ++ * ++ * Fullmac : 1 VIF TXQ for BC/MC ++ * 1 VIF TXQ for MGMT to unknown STA ++ */ ++void rwnx_txq_vif_init(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 status) ++{ ++ struct rwnx_txq *txq; ++ int idx; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ idx = rwnx_txq_vif_idx(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_init(txq, idx, status, &rwnx_hw->hwq[RWNX_HWQ_BE], 0, ++ &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index], rwnx_vif->ndev); ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ idx = rwnx_txq_vif_idx(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_init(txq, idx, status, &rwnx_hw->hwq[RWNX_HWQ_VO], TID_MGT, ++ NULL, rwnx_vif->ndev); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++/** ++ * rwnx_txq_vif_deinit - Deinitialize all TXQ linked to a vif ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_vif_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_deinit(rwnx_hw, txq); ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_deinit(rwnx_hw, txq); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++ ++/** ++ * rwnx_txq_sta_init - Initialize TX queues for a STA ++ * ++ * @rwnx_hw: Main driver data ++ * @rwnx_sta: STA for which tx queues need to be initialized ++ * @status: Intial txq status ++ * ++ * This function initialize all the TXQ associated to a STA. ++ * Softmac : 1 TXQ per TID ++ * ++ * Fullmac : 1 TXQ per TID (limited to 8) ++ * 1 TXQ for MGMT ++ */ ++void rwnx_txq_sta_init(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ u8 status) ++{ ++ struct rwnx_txq *txq; ++ int tid, idx; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[rwnx_sta->vif_idx]; ++ idx = rwnx_txq_sta_idx(rwnx_sta, 0); ++ ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_init(txq, idx, status, &rwnx_hw->hwq[rwnx_tid2hwq[tid]], tid, ++ rwnx_sta, rwnx_vif->ndev); ++ txq->ps_id = rwnx_sta->uapsd_tids & (1 << tid) ? UAPSD_ID : LEGACY_PS_ID; ++ idx++; ++ } ++ ++#endif /* CONFIG_RWNX_FULLMAC*/ ++} ++ ++/** ++ * rwnx_txq_sta_deinit - Deinitialize TX queues for a STA ++ * ++ * @rwnx_hw: Main driver data ++ * @rwnx_sta: STA for which tx queues need to be deinitialized ++ */ ++void rwnx_txq_sta_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) ++{ ++ struct rwnx_txq *txq; ++ int tid; ++ ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_deinit(rwnx_hw, txq); ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/** ++ * rwnx_txq_unk_vif_init - Initialize TXQ for unknown STA linked to a vif ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_unk_vif_init(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txq *txq; ++ int idx; ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ idx = rwnx_txq_vif_idx(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_init(txq, idx, 0, &rwnx_hw->hwq[RWNX_HWQ_VO], TID_MGT, NULL, rwnx_vif->ndev); ++} ++ ++/** ++ * rwnx_txq_tdls_vif_deinit - Deinitialize TXQ for unknown STA linked to a vif ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_unk_vif_deinit(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq; ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_deinit(rwnx_vif->rwnx_hw, txq); ++} ++ ++/** ++ * rwnx_init_unk_txq - Initialize TX queue for the transmission on a offchannel ++ * ++ * @vif: Interface for which the queue has to be initialized ++ * ++ * NOTE: Offchannel txq is only active for the duration of the ROC ++ */ ++void rwnx_txq_offchan_init(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txq *txq; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ rwnx_txq_init(txq, nx_off_chan_txq_idx, RWNX_TXQ_STOP_CHAN, ++ &rwnx_hw->hwq[RWNX_HWQ_VO], TID_MGT, NULL, rwnx_vif->ndev); ++} ++ ++/** ++ * rwnx_deinit_offchan_txq - Deinitialize TX queue for offchannel ++ * ++ * @vif: Interface that manages the STA ++ * ++ * This function deintialize txq for one STA. ++ * Any buffer stuck in a queue will be freed. ++ */ ++void rwnx_txq_offchan_deinit(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq; ++ ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ txq = &rwnx_vif->rwnx_hw->txq[nx_off_chan_txq_idx]; ++ rwnx_txq_deinit(rwnx_vif->rwnx_hw, txq); ++} ++ ++ ++/** ++ * rwnx_txq_tdls_vif_init - Initialize TXQ vif for TDLS ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_tdls_vif_init(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ ++ if (!(rwnx_hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return; ++ ++ rwnx_txq_unk_vif_init(rwnx_vif); ++} ++ ++/** ++ * rwnx_txq_tdls_vif_deinit - Deinitialize TXQ vif for TDLS ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_tdls_vif_deinit(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ ++ if (!(rwnx_hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return; ++ ++ rwnx_txq_unk_vif_deinit(rwnx_vif); ++} ++#endif ++ ++/****************************************************************************** ++ * Start/Stop functions ++ *****************************************************************************/ ++/** ++ * rwnx_txq_add_to_hw_list - Add TX queue to a HW queue schedule list. ++ * ++ * @txq: TX queue to add ++ * ++ * Add the TX queue if not already present in the HW queue list. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq) ++{ ++ if (!(txq->status & RWNX_TXQ_IN_HWQ_LIST)) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_add_to_hw(txq); ++#endif ++ txq->status |= RWNX_TXQ_IN_HWQ_LIST; ++ list_add_tail(&txq->sched_list, &txq->hwq->list); ++ txq->hwq->need_processing = true; ++ } ++} ++ ++/** ++ * rwnx_txq_del_from_hw_list - Delete TX queue from a HW queue schedule list. ++ * ++ * @txq: TX queue to delete ++ * ++ * Remove the TX queue from the HW queue list if present. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_del_from_hw_list(struct rwnx_txq *txq) ++{ ++ if (txq->status & RWNX_TXQ_IN_HWQ_LIST) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_del_from_hw(txq); ++#endif ++ txq->status &= ~RWNX_TXQ_IN_HWQ_LIST; ++ list_del(&txq->sched_list); ++ } ++} ++ ++/** ++ * rwnx_txq_skb_ready - Check if skb are available for the txq ++ * ++ * @txq: Pointer on txq ++ * @return True if there are buffer ready to be pushed on this txq, ++ * false otherwise ++ */ ++static inline bool rwnx_txq_skb_ready(struct rwnx_txq *txq) ++{ ++#ifdef CONFIG_MAC80211_TXQ ++ if (txq->nb_ready_mac80211 != NOT_MAC80211_TXQ) ++ return ((txq->nb_ready_mac80211 > 0) || !skb_queue_empty(&txq->sk_list)); ++ else ++#endif ++ return !skb_queue_empty(&txq->sk_list); ++} ++ ++/** ++ * rwnx_txq_start - Try to Start one TX queue ++ * ++ * @txq: TX queue to start ++ * @reason: reason why the TX queue is started (among RWNX_TXQ_STOP_xxx) ++ * ++ * Re-start the TX queue for one reason. ++ * If after this the txq is no longer stopped and some buffers are ready, ++ * the TX queue is also added to HW queue list. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_start(struct rwnx_txq *txq, u16 reason) ++{ ++ BUG_ON(txq == NULL); ++ if (txq->idx != TXQ_INACTIVE && (txq->status & reason)) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_start(txq, reason); ++#endif ++ txq->status &= ~reason; ++ if (!rwnx_txq_is_stopped(txq) && rwnx_txq_skb_ready(txq)) ++ rwnx_txq_add_to_hw_list(txq); ++ } ++} ++ ++/** ++ * rwnx_txq_stop - Stop one TX queue ++ * ++ * @txq: TX queue to stop ++ * @reason: reason why the TX queue is stopped (among RWNX_TXQ_STOP_xxx) ++ * ++ * Stop the TX queue. It will remove the TX queue from HW queue list ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_stop(struct rwnx_txq *txq, u16 reason) ++{ ++ BUG_ON(txq == NULL); ++ if (txq->idx != TXQ_INACTIVE) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_stop(txq, reason); ++#endif ++ txq->status |= reason; ++ rwnx_txq_del_from_hw_list(txq); ++ } ++} ++ ++ ++/** ++ * rwnx_txq_sta_start - Start all the TX queue linked to a STA ++ * ++ * @sta: STA whose TX queues must be re-started ++ * @reason: Reason why the TX queue are restarted (among RWNX_TXQ_STOP_xxx) ++ * @rwnx_hw: Driver main data ++ * ++ * This function will re-start all the TX queues of the STA for the reason ++ * specified. It can be : ++ * - RWNX_TXQ_STOP_STA_PS: the STA is no longer in power save mode ++ * - RWNX_TXQ_STOP_VIF_PS: the VIF is in power save mode (p2p absence) ++ * - RWNX_TXQ_STOP_CHAN: the STA's VIF is now on the current active channel ++ * ++ * Any TX queue with buffer ready and not Stopped for other reasons, will be ++ * added to the HW queue list ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_sta_start(struct rwnx_sta *rwnx_sta, u16 reason ++#ifdef CONFIG_RWNX_FULLMAC ++ , struct rwnx_hw *rwnx_hw ++#endif ++ ) ++{ ++ struct rwnx_txq *txq; ++ int tid; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_sta_start(rwnx_sta->sta_idx); ++#endif ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_start(txq, reason); ++ } ++} ++ ++ ++/** ++ * rwnx_stop_sta_txq - Stop all the TX queue linked to a STA ++ * ++ * @sta: STA whose TX queues must be stopped ++ * @reason: Reason why the TX queue are stopped (among RWNX_TX_STOP_xxx) ++ * @rwnx_hw: Driver main data ++ * ++ * This function will stop all the TX queues of the STA for the reason ++ * specified. It can be : ++ * - RWNX_TXQ_STOP_STA_PS: the STA is in power save mode ++ * - RWNX_TXQ_STOP_VIF_PS: the VIF is in power save mode (p2p absence) ++ * - RWNX_TXQ_STOP_CHAN: the STA's VIF is not on the current active channel ++ * ++ * Any TX queue present in a HW queue list will be removed from this list. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_sta_stop(struct rwnx_sta *rwnx_sta, u16 reason ++#ifdef CONFIG_RWNX_FULLMAC ++ , struct rwnx_hw *rwnx_hw ++#endif ++ ) ++{ ++ struct rwnx_txq *txq; ++ int tid; ++ ++ if (!rwnx_sta) ++ return; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_sta_stop(rwnx_sta->sta_idx); ++#endif ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_stop(txq, reason); ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_start(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ if (rwnx_vif->sta.tdls_sta) ++ rwnx_txq_sta_start(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_tdls_sta_stop(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_stop(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ if (rwnx_vif->sta.tdls_sta) ++ rwnx_txq_sta_stop(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline void rwnx_txq_vif_for_each_sta(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ void (*f)(struct rwnx_sta *, u16, struct rwnx_hw *), u16 reason) { ++ ++ switch (RWNX_VIF_TYPE(rwnx_vif)) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ { ++ if (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) ++ f(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ if (!WARN_ON(rwnx_vif->sta.ap == NULL)) ++ f(rwnx_vif->sta.ap, reason, rwnx_hw); ++ break; ++ } ++ case NL80211_IFTYPE_AP_VLAN: ++ rwnx_vif = rwnx_vif->ap_vlan.master; ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_MESH_POINT: ++ case NL80211_IFTYPE_P2P_GO: ++ { ++ struct rwnx_sta *sta; ++ list_for_each_entry(sta, &rwnx_vif->ap.sta_list, list) { ++ f(sta, reason, rwnx_hw); ++ } ++ break; ++ } ++ default: ++ BUG(); ++ break; ++ } ++} ++#endif ++ ++/** ++ * rwnx_txq_vif_start - START TX queues of all STA associated to the vif ++ * and vif's TXQ ++ * ++ * @vif: Interface to start ++ * @reason: Start reason (RWNX_TXQ_STOP_CHAN or RWNX_TXQ_STOP_VIF_PS) ++ * @rwnx_hw: Driver main data ++ * ++ * Iterate over all the STA associated to the vif and re-start them for the ++ * reason @reason ++ * Take tx_lock ++ */ ++void rwnx_txq_vif_start(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_txq *txq; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_start(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ //Reject if monitor interface ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MONITOR) ++ goto end; ++ ++ if (rwnx_vif->roc_tdls && rwnx_vif->sta.tdls_sta && rwnx_vif->sta.tdls_sta->tdls.chsw_en) { ++ rwnx_txq_sta_start(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ } ++ if (!rwnx_vif->roc_tdls) { ++ rwnx_txq_vif_for_each_sta(rwnx_hw, rwnx_vif, rwnx_txq_sta_start, reason); ++ } ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_start(txq, reason); ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_start(txq, reason); ++ ++end: ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++ ++ ++/** ++ * rwnx_txq_vif_stop - STOP TX queues of all STA associated to the vif ++ * ++ * @vif: Interface to stop ++ * @arg: Stop reason (RWNX_TXQ_STOP_CHAN or RWNX_TXQ_STOP_VIF_PS) ++ * @rwnx_hw: Driver main data ++ * ++ * Iterate over all the STA associated to the vif and stop them for the ++ * reason RWNX_TXQ_STOP_CHAN or RWNX_TXQ_STOP_VIF_PS ++ * Take tx_lock ++ */ ++void rwnx_txq_vif_stop(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_txq *txq; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_stop(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ //Reject if monitor interface ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MONITOR) ++ goto end; ++ ++ rwnx_txq_vif_for_each_sta(rwnx_hw, rwnx_vif, rwnx_txq_sta_stop, reason); ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_stop(txq, reason); ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_stop(txq, reason); ++ ++end: ++#endif /* CONFIG_RWNX_FULLMAC*/ ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++/** ++ * rwnx_start_offchan_txq - START TX queue for offchannel frame ++ * ++ * @rwnx_hw: Driver main data ++ */ ++void rwnx_txq_offchan_start(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_txq *txq; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_CHAN); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++ ++/** ++ * rwnx_switch_vif_sta_txq - Associate TXQ linked to a STA to a new vif ++ * ++ * @sta: STA whose txq must be switched ++ * @old_vif: Vif currently associated to the STA (may no longer be active) ++ * @new_vif: vif which should be associated to the STA for now on ++ * ++ * This function will switch the vif (i.e. the netdev) associated to all STA's ++ * TXQ. This is used when AP_VLAN interface are created. ++ * If one STA is associated to an AP_vlan vif, it will be moved from the master ++ * AP vif to the AP_vlan vif. ++ * If an AP_vlan vif is removed, then STA will be moved back to mastert AP vif. ++ * ++ */ ++void rwnx_txq_sta_switch_vif(struct rwnx_sta *sta, struct rwnx_vif *old_vif, ++ struct rwnx_vif *new_vif) ++{ ++ struct rwnx_hw *rwnx_hw = new_vif->rwnx_hw; ++ struct rwnx_txq *txq; ++ int i; ++ ++ /* start TXQ on the new interface, and update ndev field in txq */ ++ if (!netif_carrier_ok(new_vif->ndev)) ++ netif_carrier_on(new_vif->ndev); ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ for (i = 0; i < NX_NB_TID_PER_STA; i++, txq++) { ++ txq->ndev = new_vif->ndev; ++ netif_wake_subqueue(txq->ndev, txq->ndev_idx); ++ } ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/****************************************************************************** ++ * TXQ queue/schedule functions ++ *****************************************************************************/ ++/** ++ * rwnx_txq_queue_skb - Queue a buffer in a TX queue ++ * ++ * @skb: Buffer to queue ++ * @txq: TX Queue in which the buffer must be added ++ * @rwnx_hw: Driver main data ++ * @retry: Should it be queued in the retry list ++ * ++ * @return: Retrun 1 if txq has been added to hwq list, 0 otherwise ++ * ++ * Add a buffer in the buffer list of the TX queue ++ * and add this TX queue in the HW queue list if the txq is not stopped. ++ * If this is a retry packet it is added after the last retry packet or at the ++ * beginning if there is no retry packet queued. ++ * ++ * If the STA is in PS mode and this is the first packet queued for this txq ++ * update TIM. ++ * ++ * To be called with tx_lock hold ++ */ ++int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, ++ struct rwnx_hw *rwnx_hw, bool retry) ++{ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (unlikely(txq->sta && txq->sta->ps.active)) { ++ txq->sta->ps.pkt_ready[txq->ps_id]++; ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_queue(txq->sta); ++#endif ++ if (txq->sta->ps.pkt_ready[txq->ps_id] == 1) { ++ rwnx_set_traffic_status(rwnx_hw, txq->sta, true, txq->ps_id); ++ } ++ } ++#endif ++ ++ if (!retry) { ++ /* add buffer in the sk_list */ ++ skb_queue_tail(&txq->sk_list, skb); ++ } else { ++ if (txq->last_retry_skb) ++#ifdef CONFIG_GKI ++ rwnx_skb_append(txq->last_retry_skb, skb, &txq->sk_list); ++#else ++ skb_append(txq->last_retry_skb, skb, &txq->sk_list); ++#endif ++ else ++ skb_queue_head(&txq->sk_list, skb); ++ ++ txq->last_retry_skb = skb; ++ txq->nb_retry++; ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_queue_skb(skb, txq, retry); ++#endif ++ /* Flowctrl corresponding netdev queue if needed */ ++#ifdef CONFIG_RWNX_FULLMAC ++#ifndef CONFIG_ONE_TXQ ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ if ((txq->ndev_idx != NDEV_NO_TXQ) && ((skb_queue_len(&txq->sk_list) > RWNX_NDEV_FLOW_CTRL_STOP) && ++ !rwnx_hw->sdiodev->flowctrl)) { ++// (atomic_read(&rwnx_hw->sdiodev->tx_priv->tx_pktcnt) >= tx_fc_high_water))) { ++#else ++ /* If too many buffer are queued for this TXQ stop netdev queue */ ++ if ((txq->ndev_idx != NDEV_NO_TXQ) && ++ (skb_queue_len(&txq->sk_list) > RWNX_NDEV_FLOW_CTRL_STOP)) { ++#endif ++ ++ txq->status |= RWNX_TXQ_NDEV_FLOW_CTRL; ++ netif_stop_subqueue(txq->ndev, txq->ndev_idx); ++#ifdef CREATE_TRACE_POINT ++ trace_txq_flowctrl_stop(txq); ++#endif ++ } ++#endif /* CONFIG_ONE_TXQ */ ++#else /* ! CONFIG_RWNX_FULLMAC */ ++ ++ if (!retry && ++txq->hwq->len == txq->hwq->len_stop) { ++ trace_hwq_flowctrl_stop(txq->hwq->id); ++ ieee80211_stop_queue(rwnx_hw->hw, txq->hwq->id); ++ rwnx_hw->stats.queues_stops++; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ /* add it in the hwq list if not stopped and not yet present */ ++ if (!rwnx_txq_is_stopped(txq)) { ++ rwnx_txq_add_to_hw_list(txq); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * rwnx_txq_confirm_any - Process buffer confirmed by fw ++ * ++ * @rwnx_hw: Driver main data ++ * @txq: TX Queue ++ * @hwq: HW Queue ++ * @sw_txhdr: software descriptor of the confirmed packet ++ * ++ * Process a buffer returned by the fw. It doesn't check buffer status ++ * and only does systematic counter update: ++ * - hw credit ++ * - buffer pushed to fw ++ * ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_confirm_any(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, ++ struct rwnx_hwq *hwq, struct rwnx_sw_txhdr *sw_txhdr) ++{ ++ int user = 0; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ int group_id; ++ ++ user = RWNX_MUMIMO_INFO_POS_ID(sw_txhdr->desc.host.mumimo_info); ++ group_id = RWNX_MUMIMO_INFO_GROUP_ID(sw_txhdr->desc.host.mumimo_info); ++ ++ if ((txq->idx != TXQ_INACTIVE) && ++ (txq->pkt_pushed[user] == 1) && ++ (txq->status & RWNX_TXQ_STOP_MU_POS)) ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_MU_POS); ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++ if (txq->pkt_pushed[user]) ++ txq->pkt_pushed[user]--; ++ ++ hwq->need_processing = true; ++ rwnx_hw->stats.cfm_balance[hwq->id]--; ++} ++ ++/****************************************************************************** ++ * HWQ processing ++ *****************************************************************************/ ++static inline ++bool rwnx_txq_take_mu_lock(struct rwnx_hw *rwnx_hw) ++{ ++ bool res = false; ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ if (rwnx_hw->mod_params->mutx) ++ res = (down_trylock(&rwnx_hw->mu.lock) == 0); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ return res; ++} ++ ++static inline ++void rwnx_txq_release_mu_lock(struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ up(&rwnx_hw->mu.lock); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++} ++ ++static inline ++void rwnx_txq_set_mu_info(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, ++ int group_id, int pos) ++{ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ trace_txq_select_mu_group(txq, group_id, pos); ++ if (group_id) { ++ txq->mumimo_info = group_id | (pos << 6); ++ rwnx_mu_set_active_group(rwnx_hw, group_id); ++ } else ++ txq->mumimo_info = 0; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++} ++ ++static inline ++s8 rwnx_txq_get_credits(struct rwnx_txq *txq) ++{ ++ s8 cred = txq->credits; ++ /* if destination is in PS mode, push_limit indicates the maximum ++ number of packet that can be pushed on this txq. */ ++ if (txq->push_limit && (cred > txq->push_limit)) { ++ cred = txq->push_limit; ++ } ++ return cred; ++} ++ ++/** ++ * skb_queue_extract - Extract buffer from skb list ++ * ++ * @list: List of skb to extract from ++ * @head: List of skb to append to ++ * @nb_elt: Number of skb to extract ++ * ++ * extract the first @nb_elt of @list and append them to @head ++ * It is assume that: ++ * - @list contains more that @nb_elt ++ * - There is no need to take @list nor @head lock to modify them ++ */ ++static inline void skb_queue_extract(struct sk_buff_head *list, ++ struct sk_buff_head *head, int nb_elt) ++{ ++ int i; ++ struct sk_buff *first, *last, *ptr; ++ ++ first = ptr = list->next; ++ for (i = 0; i < nb_elt; i++) { ++ ptr = ptr->next; ++ } ++ last = ptr->prev; ++ ++ /* unlink nb_elt in list */ ++ list->qlen -= nb_elt; ++ list->next = ptr; ++ ptr->prev = (struct sk_buff *)list; ++ ++ /* append nb_elt at end of head */ ++ head->qlen += nb_elt; ++ last->next = (struct sk_buff *)head; ++ head->prev->next = first; ++ first->prev = head->prev; ++ head->prev = last; ++} ++ ++ ++#ifdef CONFIG_MAC80211_TXQ ++/** ++ * rwnx_txq_mac80211_dequeue - Dequeue buffer from mac80211 txq and ++ * add them to push list ++ * ++ * @rwnx_hw: Main driver data ++ * @sk_list: List of buffer to push (initialized without lock) ++ * @txq: TXQ to dequeue buffers from ++ * @max: Max number of buffer to dequeue ++ * ++ * Dequeue buffer from mac80211 txq, prepare them for transmission and chain them ++ * to the list of buffer to push. ++ * ++ * @return true if no more buffer are queued in mac80211 txq and false otherwise. ++ */ ++static bool rwnx_txq_mac80211_dequeue(struct rwnx_hw *rwnx_hw, ++ struct sk_buff_head *sk_list, ++ struct rwnx_txq *txq, int max) ++{ ++ struct ieee80211_txq *mac_txq; ++ struct sk_buff *skb; ++ unsigned long mac_txq_len; ++ ++ if (txq->nb_ready_mac80211 == NOT_MAC80211_TXQ) ++ return true; ++ ++ mac_txq = container_of((void *)txq, struct ieee80211_txq, drv_priv); ++ ++ for (; max > 0; max--) { ++ skb = rwnx_tx_dequeue_prep(rwnx_hw, mac_txq); ++ if (skb == NULL) ++ return true; ++ ++ __skb_queue_tail(sk_list, skb); ++ } ++ ++ /* re-read mac80211 txq current length. ++ It is mainly for debug purpose to trace dropped packet. There is no ++ problems to have nb_ready_mac80211 != actual mac80211 txq length */ ++ ieee80211_txq_get_depth(mac_txq, &mac_txq_len, NULL); ++ if (txq->nb_ready_mac80211 > mac_txq_len) ++ trace_txq_drop(txq, txq->nb_ready_mac80211 - mac_txq_len); ++ txq->nb_ready_mac80211 = mac_txq_len; ++ ++ return (txq->nb_ready_mac80211 == 0); ++} ++#endif ++ ++/** ++ * rwnx_txq_get_skb_to_push - Get list of buffer to push for one txq ++ * ++ * @rwnx_hw: main driver data ++ * @hwq: HWQ on wich buffers will be pushed ++ * @txq: TXQ to get buffers from ++ * @user: user postion to use ++ * @sk_list_push: list to update ++ * ++ * ++ * This function will returned a list of buffer to push for one txq. ++ * It will take into account the number of credit of the HWQ for this user ++ * position and TXQ (and push_limit). ++ * This allow to get a list that can be pushed without having to test for ++ * hwq/txq status after each push ++ * ++ * If a MU group has been selected for this txq, it will also update the ++ * counter for the group ++ * ++ * @return true if txq no longer have buffer ready after the ones returned. ++ * false otherwise ++ */ ++static ++bool rwnx_txq_get_skb_to_push(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq, ++ struct rwnx_txq *txq, int user, ++ struct sk_buff_head *sk_list_push) ++{ ++ int nb_ready = skb_queue_len(&txq->sk_list); ++ int credits = rwnx_txq_get_credits(txq); ++ bool res = false; ++ ++ __skb_queue_head_init(sk_list_push); ++ ++ if (credits >= nb_ready) { ++ skb_queue_splice_init(&txq->sk_list, sk_list_push); ++#ifdef CONFIG_MAC80211_TXQ ++ res = rwnx_txq_mac80211_dequeue(rwnx_hw, sk_list_push, txq, credits - nb_ready); ++ credits = skb_queue_len(sk_list_push); ++#else ++ res = true; ++ credits = nb_ready; ++#endif ++ } else { ++ skb_queue_extract(&txq->sk_list, sk_list_push, credits); ++ ++ /* When processing PS service period (i.e. push_limit != 0), no longer ++ process this txq if the buffers extracted will complete the SP for ++ this txq */ ++ if (txq->push_limit && (credits == txq->push_limit)) ++ res = true; ++ } ++ ++ rwnx_mu_set_active_sta(rwnx_hw, rwnx_txq_2_sta(txq), credits); ++ ++ return res; ++} ++ ++/** ++ * rwnx_txq_select_user - Select User queue for a txq ++ * ++ * @rwnx_hw: main driver data ++ * @mu_lock: true is MU lock is taken ++ * @txq: TXQ to select MU group for ++ * @hwq: HWQ for the TXQ ++ * @user: Updated with user position selected ++ * ++ * @return false if it is no possible to process this txq. ++ * true otherwise ++ * ++ * This function selects the MU group to use for a TXQ. ++ * The selection is done as follow: ++ * ++ * - return immediately for STA that don't belongs to any group and select ++ * group 0 / user 0 ++ * ++ * - If MU tx is disabled (by user mutx_on, or because mu group are being ++ * updated !mu_lock), select group 0 / user 0 ++ * ++ * - Use the best group selected by @rwnx_mu_group_sta_select. ++ * ++ * Each time a group is selected (except for the first case where sta ++ * doesn't belongs to a MU group), the function checks that no buffer is ++ * pending for this txq on another user position. If this is the case stop ++ * the txq (RWNX_TXQ_STOP_MU_POS) and return false. ++ * ++ */ ++static ++bool rwnx_txq_select_user(struct rwnx_hw *rwnx_hw, bool mu_lock, ++ struct rwnx_txq *txq, struct rwnx_hwq *hwq, int *user) ++{ ++ int pos = 0; ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ int id, group_id = 0; ++ struct rwnx_sta *sta = rwnx_txq_2_sta(txq); ++ ++ /* for sta that belong to no group return immediately */ ++ if (!sta || !sta->group_info.cnt) ++ goto end; ++ ++ /* If MU is disabled, need to check user */ ++ if (!rwnx_hw->mod_params->mutx_on || !mu_lock) ++ goto check_user; ++ ++ /* Use the "best" group selected */ ++ group_id = sta->group_info.group; ++ ++ if (group_id > 0) ++ pos = rwnx_mu_group_sta_get_pos(rwnx_hw, sta, group_id); ++ ++check_user: ++ /* check that we can push on this user position */ ++#if CONFIG_USER_MAX == 2 ++ id = (pos + 1) & 0x1; ++ if (txq->pkt_pushed[id]) { ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_MU_POS); ++ return false; ++ } ++ ++#else ++ for (id = 0 ; id < CONFIG_USER_MAX ; id++) { ++ if (id != pos && txq->pkt_pushed[id]) { ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_MU_POS); ++ return false; ++ } ++ } ++#endif ++ ++end: ++ rwnx_txq_set_mu_info(rwnx_hw, txq, group_id, pos); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++ *user = pos; ++ return true; ++} ++ ++ ++/** ++ * rwnx_hwq_process - Process one HW queue list ++ * ++ * @rwnx_hw: Driver main data ++ * @hw_queue: HW queue index to process ++ * ++ * The function will iterate over all the TX queues linked in this HW queue ++ * list. For each TX queue, push as many buffers as possible in the HW queue. ++ * (NB: TX queue have at least 1 buffer, otherwise it wouldn't be in the list) ++ * - If TX queue no longer have buffer, remove it from the list and check next ++ * TX queue ++ * - If TX queue no longer have credits or has a push_limit (PS mode) and it ++ * is reached , remove it from the list and check next TX queue ++ * - If HW queue is full, update list head to start with the next TX queue on ++ * next call if current TX queue already pushed "too many" pkt in a row, and ++ * return ++ * ++ * To be called when HW queue list is modified: ++ * - when a buffer is pushed on a TX queue ++ * - when new credits are received ++ * - when a STA returns from Power Save mode or receives traffic request. ++ * - when Channel context change ++ * ++ * To be called with tx_lock hold ++ */ ++#define ALL_HWQ_MASK ((1 << CONFIG_USER_MAX) - 1) ++ ++void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq) ++{ ++ struct rwnx_txq *txq, *next; ++ int user, credit_map = 0; ++ bool mu_enable; ++#ifdef CREATE_TRACE_POINTS ++ trace_process_hw_queue(hwq); ++#endif ++ hwq->need_processing = false; ++ ++ mu_enable = rwnx_txq_take_mu_lock(rwnx_hw); ++ if (!mu_enable) ++ credit_map = ALL_HWQ_MASK - 1; ++ ++ list_for_each_entry_safe(txq, next, &hwq->list, sched_list) { ++ struct rwnx_txhdr *txhdr = NULL; ++ struct sk_buff_head sk_list_push; ++ struct sk_buff *skb; ++ bool txq_empty; ++#ifdef CREATE_TRACE_POINTS ++ trace_process_txq(txq); ++#endif ++ /* sanity check for debug */ ++ BUG_ON(!(txq->status & RWNX_TXQ_IN_HWQ_LIST)); ++ if(txq->idx == TXQ_INACTIVE){ ++ printk("%s txq->idx == TXQ_INACTIVE \r\n", __func__); ++ rwnx_txq_del_from_hw_list(txq); ++ rwnx_txq_flush(rwnx_hw, txq); ++ continue; ++ } ++ BUG_ON(txq->idx == TXQ_INACTIVE); ++ BUG_ON(txq->credits <= 0); ++ BUG_ON(!rwnx_txq_skb_ready(txq)); ++ ++ if (!rwnx_txq_select_user(rwnx_hw, mu_enable, txq, hwq, &user)) { ++ printk("select user:%d\n", user); ++ continue; ++ } ++ ++ txq_empty = rwnx_txq_get_skb_to_push(rwnx_hw, hwq, txq, user, ++ &sk_list_push); ++ while ((skb = __skb_dequeue(&sk_list_push)) != NULL) { ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ rwnx_tx_push(rwnx_hw, txhdr, 0); ++ } ++ ++ if (txq_empty) { ++ rwnx_txq_del_from_hw_list(txq); ++ txq->pkt_sent = 0; ++ } else if (rwnx_txq_is_scheduled(txq)) { ++ /* txq not empty, ++ - To avoid starving need to process other txq in the list ++ - For better aggregation, need to send "as many consecutive ++ pkt as possible" for he same txq ++ ==> Add counter to trigger txq switch ++ */ ++ if (txq->pkt_sent > hwq->size) { ++ txq->pkt_sent = 0; ++ list_rotate_left(&hwq->list); ++ } ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ /* Unable to complete PS traffic request because of hwq credit */ ++ if (txq->push_limit && txq->sta) { ++ if (txq->ps_id == LEGACY_PS_ID) { ++ /* for legacy PS abort SP and wait next ps-poll */ ++ txq->sta->ps.sp_cnt[txq->ps_id] -= txq->push_limit; ++ txq->push_limit = 0; ++ } ++ /* for u-apsd need to complete the SP to send EOSP frame */ ++ } ++#ifndef CONFIG_ONE_TXQ ++ /* restart netdev queue if number of queued buffer is below threshold */ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && ++ (skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART)) { ++#else ++ if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && ++ skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART) { ++#endif ++ ++ txq->status &= ~RWNX_TXQ_NDEV_FLOW_CTRL; ++ netif_wake_subqueue(txq->ndev, txq->ndev_idx); ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_flowctrl_restart(txq); ++#endif ++ } ++#endif /* CONFIG_ONE_TXQ */ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } ++ ++ ++ if (mu_enable) ++ rwnx_txq_release_mu_lock(rwnx_hw); ++} ++ ++/** ++ * rwnx_hwq_process_all - Process all HW queue list ++ * ++ * @rwnx_hw: Driver main data ++ * ++ * Loop over all HWQ, and process them if needed ++ * To be called with tx_lock hold ++ */ ++void rwnx_hwq_process_all(struct rwnx_hw *rwnx_hw) ++{ ++ int id; ++ ++ rwnx_mu_group_sta_select(rwnx_hw); ++ ++ for (id = ARRAY_SIZE(rwnx_hw->hwq) - 1; id >= 0 ; id--) { ++ if (rwnx_hw->hwq[id].need_processing) { ++ rwnx_hwq_process(rwnx_hw, &rwnx_hw->hwq[id]); ++ } ++ } ++} ++ ++/** ++ * rwnx_hwq_init - Initialize all hwq structures ++ * ++ * @rwnx_hw: Driver main data ++ * ++ */ ++void rwnx_hwq_init(struct rwnx_hw *rwnx_hw) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(rwnx_hw->hwq); i++) { ++ struct rwnx_hwq *hwq = &rwnx_hw->hwq[i]; ++ ++ hwq->id = i; ++ hwq->size = nx_txdesc_cnt[i]; ++ INIT_LIST_HEAD(&hwq->list); ++ ++ } ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h +new file mode 100644 +index 000000000000..9653d014bf70 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h +@@ -0,0 +1,404 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_txq.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++#ifndef _RWNX_TXQ_H_ ++#define _RWNX_TXQ_H_ ++ ++#include ++#include ++#include ++ ++#include ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/** ++ * Fullmac TXQ configuration: ++ * - STA: 1 TXQ per TID (limited to 8) ++ * 1 TXQ for bufferable MGT frames ++ * - VIF: 1 TXQ for Multi/Broadcast + ++ * 1 TXQ for MGT for unknown STAs or non-bufferable MGT frames ++ * - 1 TXQ for offchannel transmissions ++ * ++ * ++ * Txq mapping looks like ++ * for NX_REMOTE_STA_MAX=10 and NX_VIRT_DEV_MAX=4 ++ * ++ * | TXQ | NDEV_ID | VIF | STA | TID | HWQ | ++ * |-----+---------+-----+-------+------+-----|- ++ * | 0 | 0 | | 0 | 0 | 1 | 9 TXQ per STA ++ * | 1 | 1 | | 0 | 1 | 0 | (8 data + 1 mgmt) ++ * | 2 | 2 | | 0 | 2 | 0 | ++ * | 3 | 3 | | 0 | 3 | 1 | ++ * | 4 | 4 | | 0 | 4 | 2 | ++ * | 5 | 5 | | 0 | 5 | 2 | ++ * | 6 | 6 | | 0 | 6 | 3 | ++ * | 7 | 7 | | 0 | 7 | 3 | ++ * | 8 | N/A | | 0 | MGMT | 3 | ++ * |-----+---------+-----+-------+------+-----|- ++ * | ... | | | | | | Same for all STAs ++ * |-----+---------+-----+-------+------+-----|- ++ * | 90 | 80 | 0 | BC/MC | 0 | 1/4 | 1 TXQ for BC/MC per VIF ++ * | ... | | | | | | ++ * | 93 | 80 | 3 | BC/MC | 0 | 1/4 | ++ * |-----+---------+-----+-------+------+-----|- ++ * | 94 | N/A | 0 | N/A | MGMT | 3 | 1 TXQ for unknown STA per VIF ++ * | ... | | | | | | ++ * | 97 | N/A | 3 | N/A | MGMT | 3 | ++ * |-----+---------+-----+-------+------+-----|- ++ * | 98 | N/A | | N/A | MGMT | 3 | 1 TXQ for offchannel frame ++ */ ++#define NX_NB_TID_PER_STA 8 ++#define NX_NB_TXQ_PER_STA (NX_NB_TID_PER_STA + 1) ++#define NX_NB_TXQ_PER_VIF 2 ++#define NX_NB_TXQ ((NX_NB_TXQ_PER_STA * NX_REMOTE_STA_MAX) + \ ++ (NX_NB_TXQ_PER_VIF * NX_VIRT_DEV_MAX) + 1) ++ ++#define NX_FIRST_VIF_TXQ_IDX (NX_REMOTE_STA_MAX * NX_NB_TXQ_PER_STA) ++#define NX_FIRST_BCMC_TXQ_IDX NX_FIRST_VIF_TXQ_IDX ++#define NX_FIRST_UNK_TXQ_IDX (NX_FIRST_BCMC_TXQ_IDX + NX_VIRT_DEV_MAX) ++ ++#define NX_OFF_CHAN_TXQ_IDX (NX_FIRST_VIF_TXQ_IDX + \ ++ (NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF)) ++ ++#define NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC (NX_REMOTE_STA_MAX_FOR_OLD_IC * NX_NB_TXQ_PER_STA) ++#define NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC ++#define NX_FIRST_UNK_TXQ_IDX_FOR_OLD_IC (NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC + NX_VIRT_DEV_MAX) ++ ++#define NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC (NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + \ ++ (NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF)) ++ ++ ++#define NX_BCMC_TXQ_TYPE 0 ++#define NX_UNK_TXQ_TYPE 1 ++ ++/** ++ * Each data TXQ is a netdev queue. TXQ to send MGT are not data TXQ as ++ * they did not recieved buffer from netdev interface. ++ * Need to allocate the maximum case. ++ * AP : all STAs + 1 BC/MC ++ */ ++#define NX_NB_NDEV_TXQ ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX) + 1) ++#define NX_NB_NDEV_TXQ_FOR_OLD_IC ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC) + 1) ++ ++#define NX_BCMC_TXQ_NDEV_IDX (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX) ++#define NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC) ++#define NX_STA_NDEV_IDX(tid, sta_idx) ((tid) + (sta_idx) * NX_NB_TID_PER_STA) ++#define NDEV_NO_TXQ 0xffff ++#if (NX_NB_NDEV_TXQ >= NDEV_NO_TXQ) ++#error("Need to increase struct rwnx_txq->ndev_idx size") ++#endif ++ ++/* stop netdev queue when number of queued buffers if greater than this */ ++#define RWNX_NDEV_FLOW_CTRL_STOP 64 ++/* restart netdev queue when number of queued buffers is lower than this */ ++#define RWNX_NDEV_FLOW_CTRL_RESTART 64 ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#define TXQ_INACTIVE 0xffff ++#if (NX_NB_TXQ >= TXQ_INACTIVE) ++#error("Need to increase struct rwnx_txq->idx size") ++#endif ++ ++#define NX_TXQ_INITIAL_CREDITS 64 ++ ++/** ++ * TXQ tid sorted by decreasing priority ++ */ ++extern const int nx_tid_prio[NX_NB_TID_PER_STA]; ++ ++/** ++ * struct rwnx_hwq - Structure used to save information relative to ++ * an AC TX queue (aka HW queue) ++ * @list: List of TXQ, that have buffers ready for this HWQ ++ * @credits: available credit for the queue (i.e. nb of buffers that ++ * can be pushed to FW ) ++ * @id Id of the HWQ among RWNX_HWQ_.... ++ * @size size of the queue ++ * @need_processing Indicate if hwq should be processed ++ * @len number of packet ready to be pushed to fw for this HW queue ++ * @len_stop threshold to stop mac80211(i.e. netdev) queues. Stop queue when ++ * driver has more than @len_stop packets ready. ++ * @len_start threshold to wake mac8011 queues. Wake queue when driver has ++ * less than @len_start packets ready. ++ */ ++struct rwnx_hwq { ++ struct list_head list; ++ u8 size; ++ u8 id; ++ bool need_processing; ++}; ++ ++/** ++ * enum rwnx_push_flags - Flags of pushed buffer ++ * ++ * @RWNX_PUSH_RETRY Pushing a buffer for retry ++ * @RWNX_PUSH_IMMEDIATE Pushing a buffer without queuing it first ++ */ ++enum rwnx_push_flags { ++ RWNX_PUSH_RETRY = BIT(0), ++ RWNX_PUSH_IMMEDIATE = BIT(1), ++}; ++ ++/** ++ * enum rwnx_txq_flags - TXQ status flag ++ * ++ * @RWNX_TXQ_IN_HWQ_LIST: The queue is scheduled for transmission ++ * @RWNX_TXQ_STOP_FULL: No more credits for the queue ++ * @RWNX_TXQ_STOP_CSA: CSA is in progress ++ * @RWNX_TXQ_STOP_STA_PS: Destiniation sta is currently in power save mode ++ * @RWNX_TXQ_STOP_VIF_PS: Vif owning this queue is currently in power save mode ++ * @RWNX_TXQ_STOP_CHAN: Channel of this queue is not the current active channel ++ * @RWNX_TXQ_STOP_MU_POS: TXQ is stopped waiting for all the buffers pushed to ++ * fw to be confirmed ++ * @RWNX_TXQ_STOP: All possible reason to have a txq stopped ++ * @RWNX_TXQ_NDEV_FLOW_CTRL: associated netdev queue is currently stopped. ++ * Note: when a TXQ is flowctrl it is NOT stopped ++ */ ++enum rwnx_txq_flags { ++ RWNX_TXQ_IN_HWQ_LIST = BIT(0), ++ RWNX_TXQ_STOP_FULL = BIT(1), ++ RWNX_TXQ_STOP_CSA = BIT(2), ++ RWNX_TXQ_STOP_STA_PS = BIT(3), ++ RWNX_TXQ_STOP_VIF_PS = BIT(4), ++ RWNX_TXQ_STOP_CHAN = BIT(5), ++ RWNX_TXQ_STOP_MU_POS = BIT(6), ++ RWNX_TXQ_STOP = (RWNX_TXQ_STOP_FULL | RWNX_TXQ_STOP_CSA | ++ RWNX_TXQ_STOP_STA_PS | RWNX_TXQ_STOP_VIF_PS | ++ RWNX_TXQ_STOP_CHAN), ++ RWNX_TXQ_NDEV_FLOW_CTRL = BIT(7), ++}; ++ ++ ++/** ++ * struct rwnx_txq - Structure used to save information relative to ++ * a RA/TID TX queue ++ * ++ * @idx: Unique txq idx. Set to TXQ_INACTIVE if txq is not used. ++ * @status: bitfield of @rwnx_txq_flags. ++ * @credits: available credit for the queue (i.e. nb of buffers that ++ * can be pushed to FW). ++ * @pkt_sent: number of consecutive pkt sent without leaving HW queue list ++ * @pkt_pushed: number of pkt currently pending for transmission confirmation ++ * @sched_list: list node for HW queue schedule list (rwnx_hwq.list) ++ * @sk_list: list of buffers to push to fw ++ * @last_retry_skb: pointer on the last skb in @sk_list that is a retry. ++ * (retry skb are stored at the beginning of the list) ++ * NULL if no retry skb is queued in @sk_list ++ * @nb_retry: Number of retry packet queued. ++ * @hwq: Pointer on the associated HW queue. ++ * @push_limit: number of packet to push before removing the txq from hwq list. ++ * (we always have push_limit < skb_queue_len(sk_list)) ++ * @tid: TID ++ * ++ * SOFTMAC specific: ++ * @baw: Block Ack window information ++ * @amsdu_anchor: pointer to rwnx_sw_txhdr of the first subframe of the A-MSDU. ++ * NULL if no A-MSDU frame is in construction ++ * @amsdu_ht_len_cap: ++ * @amsdu_vht_len_cap: ++ * @nb_ready_mac80211: Number of buffer ready in mac80211 txq ++ * ++ * FULLMAC specific ++ * @ps_id: Index to use for Power save mode (LEGACY or UAPSD) ++ * @ndev_idx: txq idx from netdev point of view (0xFF for non netdev queue) ++ * @ndev: pointer to ndev of the corresponding vif ++ * @amsdu: pointer to rwnx_sw_txhdr of the first subframe of the A-MSDU. ++ * NULL if no A-MSDU frame is in construction ++ * @amsdu_len: Maximum size allowed for an A-MSDU. 0 means A-MSDU not allowed ++ */ ++struct rwnx_txq { ++ u16 idx; ++ u8 status; ++ s8 credits; ++ u8 pkt_sent; ++ u8 pkt_pushed[CONFIG_USER_MAX]; ++ struct list_head sched_list; ++ struct sk_buff_head sk_list; ++ struct sk_buff *last_retry_skb; ++ struct rwnx_hwq *hwq; ++ int nb_retry; ++ u8 push_limit; ++ u8 tid; ++#ifdef CONFIG_MAC80211_TXQ ++ unsigned long nb_ready_mac80211; ++#endif ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_sta *sta; ++ u8 ps_id; ++ u16 ndev_idx; ++ struct net_device *ndev; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ struct rwnx_sw_txhdr *amsdu; ++ u16 amsdu_len; ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++#endif /* CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ u8 mumimo_info; ++#endif ++}; ++ ++struct rwnx_sta; ++struct rwnx_vif; ++struct rwnx_hw; ++struct rwnx_sw_txhdr; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++#define RWNX_TXQ_GROUP_ID(txq) ((txq)->mumimo_info & 0x3f) ++#define RWNX_TXQ_POS_ID(txq) (((txq)->mumimo_info >> 6) & 0x3) ++#else ++#define RWNX_TXQ_GROUP_ID(txq) 0 ++#define RWNX_TXQ_POS_ID(txq) 0 ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++static inline bool rwnx_txq_is_stopped(struct rwnx_txq *txq) ++{ ++ return (txq->status & RWNX_TXQ_STOP); ++} ++ ++static inline bool rwnx_txq_is_full(struct rwnx_txq *txq) ++{ ++ return (txq->status & RWNX_TXQ_STOP_FULL); ++} ++ ++static inline bool rwnx_txq_is_scheduled(struct rwnx_txq *txq) ++{ ++ return (txq->status & RWNX_TXQ_IN_HWQ_LIST); ++} ++ ++/** ++ * foreach_sta_txq - Macro to iterate over all TXQ of a STA in increasing ++ * TID order ++ * ++ * @sta: pointer to rwnx_sta ++ * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration ++ * @tid: int updated with the TXQ tid at each iteration ++ * @rwnx_hw: main driver data ++ */ ++#ifdef CONFIG_MAC80211_TXQ ++#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \ ++ for (tid = 0, txq = rwnx_txq_sta_get(sta, 0); \ ++ tid < NX_NB_TXQ_PER_STA; \ ++ tid++, txq = rwnx_txq_sta_get(sta, tid)) ++ ++#elif defined(CONFIG_RWNX_FULLMAC) /* CONFIG_RWNX_FULLMAC */ ++#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \ ++ for (tid = 0, txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); \ ++ tid < (is_multicast_sta(sta->sta_idx) ? 1 : NX_NB_TXQ_PER_STA); \ ++ tid++, txq++) ++ ++#endif ++ ++/** ++ * foreach_sta_txq_prio - Macro to iterate over all TXQ of a STA in ++ * decreasing priority order ++ * ++ * @sta: pointer to rwnx_sta ++ * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration ++ * @tid: int updated with the TXQ tid at each iteration ++ * @i: int updated with ieration count ++ * @rwnx_hw: main driver data ++ * ++ * Note: For fullmac txq for mgmt frame is skipped ++ */ ++#ifdef CONFIG_RWNX_FULLMAC ++#define foreach_sta_txq_prio(sta, txq, tid, i, rwnx_hw) \ ++ for (i = 0, tid = nx_tid_prio[0], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); \ ++ i < NX_NB_TID_PER_STA; \ ++ i++, tid = nx_tid_prio[i], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw)) ++#endif ++ ++/** ++ * foreach_vif_txq - Macro to iterate over all TXQ of a VIF (in AC order) ++ * ++ * @vif: pointer to rwnx_vif ++ * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration ++ * @ac: int updated with the TXQ ac at each iteration ++ */ ++#ifdef CONFIG_MAC80211_TXQ ++#define foreach_vif_txq(vif, txq, ac) \ ++ for (ac = RWNX_HWQ_BK, txq = rwnx_txq_vif_get(vif, ac); \ ++ ac < NX_NB_TXQ_PER_VIF; \ ++ ac++, txq = rwnx_txq_vif_get(vif, ac)) ++ ++#else ++#define foreach_vif_txq(vif, txq, ac) \ ++ for (ac = RWNX_HWQ_BK, txq = &vif->txqs[0]; \ ++ ac < NX_NB_TXQ_PER_VIF; \ ++ ac++, txq++) ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++struct rwnx_txq *rwnx_txq_sta_get(struct rwnx_sta *sta, u8 tid, ++ struct rwnx_hw *rwnx_hw); ++struct rwnx_txq *rwnx_txq_vif_get(struct rwnx_vif *vif, u8 type); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/** ++ * rwnx_txq_vif_get_status - return status bits related to the vif ++ * ++ * @rwnx_vif: Pointer to vif structure ++ */ ++static inline u8 rwnx_txq_vif_get_status(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq = rwnx_txq_vif_get(rwnx_vif, 0); ++ return (txq->status & (RWNX_TXQ_STOP_CHAN | RWNX_TXQ_STOP_VIF_PS)); ++} ++ ++void rwnx_txq_vif_init(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 status); ++void rwnx_txq_vif_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); ++void rwnx_txq_sta_init(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ u8 status); ++void rwnx_txq_sta_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_unk_vif_init(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_unk_vif_deinit(struct rwnx_vif *vif); ++void rwnx_txq_offchan_init(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_offchan_deinit(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_tdls_vif_init(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_tdls_vif_deinit(struct rwnx_vif *vif); ++void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_tdls_sta_stop(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++#endif ++ ++ ++void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq); ++void rwnx_txq_del_from_hw_list(struct rwnx_txq *txq); ++void rwnx_txq_stop(struct rwnx_txq *txq, u16 reason); ++void rwnx_txq_start(struct rwnx_txq *txq, u16 reason); ++void rwnx_txq_vif_start(struct rwnx_vif *vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_vif_stop(struct rwnx_vif *vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_sta_start(struct rwnx_sta *sta, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_sta_stop(struct rwnx_sta *sta, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_offchan_start(struct rwnx_hw *rwnx_hw); ++void rwnx_txq_sta_switch_vif(struct rwnx_sta *sta, struct rwnx_vif *old_vif, ++ struct rwnx_vif *new_vif); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, ++ struct rwnx_hw *rwnx_hw, bool retry); ++void rwnx_txq_confirm_any(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, ++ struct rwnx_hwq *hwq, struct rwnx_sw_txhdr *sw_txhdr); ++ ++ ++void rwnx_hwq_init(struct rwnx_hw *rwnx_hw); ++void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq); ++void rwnx_hwq_process_all(struct rwnx_hw *rwnx_hw); ++ ++#endif /* _RWNX_TXQ_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c +new file mode 100644 +index 000000000000..6b3c6f29bf10 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c +@@ -0,0 +1,39 @@ ++/** ++ * rwnx_utils.c ++ * ++ * IPC utility function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ */ ++#include "rwnx_utils.h" ++#include "rwnx_defs.h" ++#include "rwnx_rx.h" ++#include "rwnx_tx.h" ++#include "rwnx_msg_rx.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_prof.h" ++#include "ipc_host.h" ++ ++extern int get_testmode(void); ++extern void get_fw_path(char* fw_path); ++extern int testmode; ++extern char aic_fw_path[200]; ++ ++ ++int rwnx_init_aic(struct rwnx_hw *rwnx_hw) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_host_init(&(rwnx_hw->sdio_env), NULL, NULL, rwnx_hw); ++#else ++ aicwf_usb_host_init(&(rwnx_hw->usb_env), NULL, NULL, rwnx_hw); ++#endif ++ rwnx_cmd_mgr_init(rwnx_hw->cmd_mgr); ++ ++ testmode = get_testmode(); ++ memset(aic_fw_path, 0, 200); ++ get_fw_path(aic_fw_path); ++ ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h +new file mode 100644 +index 000000000000..f71a601c2af3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h +@@ -0,0 +1,133 @@ ++/** ++ * rwnx_ipc_utils.h ++ * ++ * IPC utility function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ */ ++#ifndef _RWNX_IPC_UTILS_H_ ++#define _RWNX_IPC_UTILS_H_ ++ ++#include ++#include ++#include ++#include "aicwf_debug.h" ++ ++ ++#include "lmac_msg.h" ++#if 0 ++#ifdef CONFIG_RWNX_DBG ++/* #define RWNX_DBG(format, arg...) pr_warn(format, ## arg) */ ++#define RWNX_DBG printk ++#else ++#define RWNX_DBG(a...) do {} while (0) ++#endif ++ ++#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ ++#endif ++enum rwnx_dev_flag { ++ RWNX_DEV_RESTARTING, ++ RWNX_DEV_STACK_RESTARTING, ++ RWNX_DEV_STARTED, ++}; ++ ++struct rwnx_hw; ++struct rwnx_sta; ++ ++/** ++ * struct rwnx_ipc_elem - Generic IPC buffer of fixed size ++ * ++ * @addr: Host address of the buffer. ++ * @dma_addr: DMA address of the buffer. ++ */ ++struct rwnx_ipc_elem { ++ void *addr; ++ dma_addr_t dma_addr; ++}; ++ ++/** ++ * struct rwnx_ipc_elem_pool - Generic pool of IPC buffers of fixed size ++ * ++ * @nb: Number of buffers currenlty allocated in the pool ++ * @buf: Array of buffers (size of array is @nb) ++ * @pool: DMA pool in which buffers have been allocated ++ */ ++struct rwnx_ipc_elem_pool { ++ int nb; ++ struct rwnx_ipc_elem *buf; ++ struct dma_pool *pool; ++}; ++ ++/** ++ * struct rwnx_ipc_elem - Generic IPC buffer of variable size ++ * ++ * @addr: Host address of the buffer. ++ * @dma_addr: DMA address of the buffer. ++ * @size: Size, in bytes, of the buffer ++ */ ++struct rwnx_ipc_elem_var { ++ void *addr; ++ dma_addr_t dma_addr; ++ size_t size; ++}; ++ ++/** ++ * struct rwnx_ipc_dbgdump_elem - IPC buffer for debug dump ++ * ++ * @mutex: Mutex to protect access to debug dump ++ * @buf: IPC buffer ++ */ ++struct rwnx_ipc_dbgdump_elem { ++ struct mutex mutex; ++ struct rwnx_ipc_elem_var buf; ++}; ++ ++static const u32 rwnx_rxbuff_pattern = 0xCAFEFADE; ++ ++/* ++ * Maximum Length of Radiotap header vendor specific data(in bytes) ++ */ ++#define RADIOTAP_HDR_VEND_MAX_LEN 16 ++ ++/* ++ * Maximum Radiotap Header Length without vendor specific data (in bytes) ++ */ ++#define RADIOTAP_HDR_MAX_LEN 80 ++ ++/* ++ * Unsupported HT Frame data length (in bytes) ++ */ ++#define UNSUP_RX_VEC_DATA_LEN 2 ++ ++/** ++ * struct rwnx_ipc_skb_elem - IPC buffer for SKB element ++ * ++ * @skb: Pointer to the skb buffer allocated ++ * @dma_addr: DMA address of the data buffer fo skb ++ * ++ */ ++struct rwnx_ipc_skb_elem { ++ struct sk_buff *skb; ++ dma_addr_t dma_addr; ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++/* Maximum number of rx buffer the fw may use at the same time */ ++#define RWNX_RXBUFF_MAX (64 * NX_REMOTE_STA_MAX) ++ ++/** ++ * struct rwnx_ipc_rxbuf_elems - IPC buffers for RX ++ * ++ * @skb: Array of buffer push to FW. ++ * @idx: Index of the last pushed skb.(Use to find the next free entry quicker) ++ * ++ * Note: contrary to softmac version, dma_addr are stored inside skb->cb. ++ */ ++struct rwnx_ipc_rxbuf_elems { ++ struct sk_buff *skb[RWNX_RXBUFF_MAX]; ++ int idx; ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++#endif /* _RWNX_IPC_UTILS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c +new file mode 100644 +index 000000000000..72e3c850b48e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c +@@ -0,0 +1,195 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_v7.c - Support for v7 platform ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_v7.h" ++#include "rwnx_defs.h" ++#include "rwnx_irqs.h" ++#include "reg_access.h" ++#include "hal_desc.h" ++ ++struct rwnx_v7 { ++ u8 *pci_bar0_vaddr; ++ u8 *pci_bar1_vaddr; ++}; ++ ++static int rwnx_v7_platform_enable(struct rwnx_hw *rwnx_hw) ++{ ++ int ret; ++ ++ /* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */ ++ ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0, ++ "rwnx", rwnx_hw); ++ return ret; ++} ++ ++static int rwnx_v7_platform_disable(struct rwnx_hw *rwnx_hw) ++{ ++ free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw); ++ return 0; ++} ++ ++static void rwnx_v7_platform_deinit(struct rwnx_plat *rwnx_plat) ++{ ++ #ifdef CONFIG_PCI ++ struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; ++ ++ pci_disable_device(rwnx_plat->pci_dev); ++ iounmap(rwnx_v7->pci_bar0_vaddr); ++ iounmap(rwnx_v7->pci_bar1_vaddr); ++ pci_release_regions(rwnx_plat->pci_dev); ++ pci_clear_master(rwnx_plat->pci_dev); ++ pci_disable_msi(rwnx_plat->pci_dev); ++ #endif ++ kfree(rwnx_plat); ++} ++ ++static u8 *rwnx_v7_get_address(struct rwnx_plat *rwnx_plat, int addr_name, ++ unsigned int offset) ++{ ++ struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; ++ ++ if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name)) ++ return NULL; ++ ++ if (addr_name == RWNX_ADDR_CPU) ++ return rwnx_v7->pci_bar0_vaddr + offset; ++ else ++ return rwnx_v7->pci_bar1_vaddr + offset; ++} ++ ++static void rwnx_v7_ack_irq(struct rwnx_plat *rwnx_plat) ++{ ++ ++} ++ ++static const u32 rwnx_v7_config_reg[] = { ++ NXMAC_DEBUG_PORT_SEL_ADDR, ++ SYSCTRL_DIAG_CONF_ADDR, ++ SYSCTRL_PHYDIAG_CONF_ADDR, ++ SYSCTRL_RIUDIAG_CONF_ADDR, ++ RF_V7_DIAGPORT_CONF1_ADDR, ++}; ++ ++static const u32 rwnx_v7_he_config_reg[] = { ++ SYSCTRL_DIAG_CONF0, ++ SYSCTRL_DIAG_CONF1, ++ SYSCTRL_DIAG_CONF2, ++ SYSCTRL_DIAG_CONF3, ++}; ++ ++static int rwnx_v7_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list) ++{ ++ u32 fpga_sign; ++ ++ if (!list) ++ return 0; ++ ++ fpga_sign = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_SIGNATURE_ADDR); ++ if (__FPGA_TYPE(fpga_sign) == 0xc0ca) { ++ *list = rwnx_v7_he_config_reg; ++ return ARRAY_SIZE(rwnx_v7_he_config_reg); ++ } else { ++ *list = rwnx_v7_config_reg; ++ return ARRAY_SIZE(rwnx_v7_config_reg); ++ } ++} ++ ++ ++/** ++ * rwnx_v7_platform_init - Initialize the DINI platform ++ * ++ * @pci_dev PCI device ++ * @rwnx_plat Pointer on struct rwnx_stat * to be populated ++ * ++ * @return 0 on success, < 0 otherwise ++ * ++ * Allocate and initialize a rwnx_plat structure for the dini platform. ++ */ ++int rwnx_v7_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat) ++{ ++ struct rwnx_v7 *rwnx_v7; ++ u16 pci_cmd; ++ int ret = 0; ++ ++ *rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_v7), ++ GFP_KERNEL); ++ if (!*rwnx_plat) ++ return -ENOMEM; ++ ++ rwnx_v7 = (struct rwnx_v7 *)(*rwnx_plat)->priv; ++ ++ /* Hotplug fixups */ ++ pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd); ++ pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; ++ pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd); ++ //pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2); ++ ++ ret = pci_enable_device(pci_dev); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_enable_device failed\n"); ++ goto out_enable; ++ } ++ ++ pci_set_master(pci_dev); ++ ++#if 0 ++ ret = pci_request_regions(pci_dev, KBUILD_MODNAME); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_request_regions failed\n"); ++ goto out_request; ++ } ++#endif ++ #ifdef CONFIG_PCI ++ if (pci_enable_msi(pci_dev)) { ++ dev_err(&(pci_dev->dev), "pci_enable_msi failed\n"); ++ goto out_msi; ++ ++ } ++ #endif ++ ++ rwnx_v7->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0); ++ if (!rwnx_v7->pci_bar0_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0); ++ ret = -ENOMEM; ++ goto out_bar0; ++ } ++ rwnx_v7->pci_bar1_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 1); ++ if (!rwnx_v7->pci_bar1_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 1); ++ ret = -ENOMEM; ++ goto out_bar1; ++ } ++ ++ (*rwnx_plat)->enable = rwnx_v7_platform_enable; ++ (*rwnx_plat)->disable = rwnx_v7_platform_disable; ++ (*rwnx_plat)->deinit = rwnx_v7_platform_deinit; ++ (*rwnx_plat)->get_address = rwnx_v7_get_address; ++ (*rwnx_plat)->ack_irq = rwnx_v7_ack_irq; ++ (*rwnx_plat)->get_config_reg = rwnx_v7_get_config_reg; ++ ++ return 0; ++ ++out_bar1: ++ iounmap(rwnx_v7->pci_bar0_vaddr); ++out_bar0: ++#ifdef CONFIG_PCI ++ pci_disable_msi(pci_dev); ++out_msi: ++#endif ++ pci_release_regions(pci_dev); ++//out_request: ++#ifdef CONFIG_PCI ++ pci_clear_master(pci_dev); ++#endif ++ pci_disable_device(pci_dev); ++out_enable: ++ kfree(*rwnx_plat); ++ return ret; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h +new file mode 100644 +index 000000000000..c2e39765ae1c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h +@@ -0,0 +1,20 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_v7.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_V7_H_ ++#define _RWNX_V7_H_ ++ ++#include ++#include "rwnx_platform.h" ++ ++int rwnx_v7_platform_init(struct pci_dev *pci_dev, ++ struct rwnx_plat **rwnx_plat); ++ ++#endif /* _RWNX_V7_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h +new file mode 100644 +index 000000000000..46ecb5de1ca5 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h +@@ -0,0 +1,12 @@ ++#ifndef _RWNX_VERSION_H_ ++#define _RWNX_VERSION_H_ ++ ++#include "rwnx_version_gen.h" ++ ++static inline void rwnx_print_version(void) ++{ ++ AICWFDBG(LOGINFO, RWNX_VERS_BANNER"\n"); ++ AICWFDBG(LOGINFO, "RELEASE_DATE:%s \r\n", RELEASE_DATE); ++} ++ ++#endif /* _RWNX_VERSION_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h +new file mode 100644 +index 000000000000..6fcb679c8934 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h +@@ -0,0 +1,4 @@ ++#define RWNX_VERS_REV "241c091M (master)" ++#define RWNX_VERS_MOD "6.4.3.0" ++#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" ++#define RELEASE_DATE "2025_0410_b99ca8b6" +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c +new file mode 100644 +index 000000000000..7c785e952c3d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c +@@ -0,0 +1,96 @@ ++#include ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#else ++#include ++#endif ++#include "rwnx_defs.h" ++#include "rwnx_wakelock.h" ++ ++struct wakeup_source *rwnx_wakeup_init(const char *name) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0) ++ struct wakeup_source *ws; ++ ws = wakeup_source_create(name); ++ wakeup_source_add(ws); ++ return ws; ++#else ++ return NULL; ++#endif ++} ++ ++void rwnx_wakeup_deinit(struct wakeup_source *ws) ++{ ++ if (ws && ws->active) ++ __pm_relax(ws); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0) ++ wakeup_source_remove(ws); ++ wakeup_source_destroy(ws); ++#endif ++} ++ ++struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name) ++{ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ return wakeup_source_register(dev, name); ++#else ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_PLATFORM_ROCKCHIP) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) ++ return wakeup_source_register(dev, name); ++#else ++ return wakeup_source_register(name); ++#endif ++ ++#else ++ return wakeup_source_register(name); ++#endif//#if defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_PLATFORM_ROCKCHIP) ++ ++#endif//LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++} ++ ++void rwnx_wakeup_unregister(struct wakeup_source *ws) ++{ ++ if (ws && ws->active) ++ __pm_relax(ws); ++ wakeup_source_unregister(ws); ++} ++ ++void rwnx_wakeup_lock(struct wakeup_source *ws) ++{ ++ __pm_stay_awake(ws); ++} ++ ++void rwnx_wakeup_unlock(struct wakeup_source *ws) ++{ ++ __pm_relax(ws); ++} ++ ++void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec) ++{ ++ __pm_wakeup_event(ws, msec); ++} ++ ++void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw) ++{ ++ rwnx_hw->ws_tx = rwnx_wakeup_init("rwnx_tx_wakelock"); ++ rwnx_hw->ws_rx = rwnx_wakeup_init("rwnx_rx_wakelock"); ++ rwnx_hw->ws_irqrx = rwnx_wakeup_init("rwnx_irqrx_wakelock"); ++ rwnx_hw->ws_pwrctrl = rwnx_wakeup_init("rwnx_pwrcrl_wakelock"); ++} ++ ++void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw) ++{ ++ rwnx_wakeup_deinit(rwnx_hw->ws_tx); ++ rwnx_wakeup_deinit(rwnx_hw->ws_rx); ++ rwnx_wakeup_deinit(rwnx_hw->ws_irqrx); ++ rwnx_wakeup_deinit(rwnx_hw->ws_pwrctrl); ++ rwnx_hw->ws_tx = NULL; ++ rwnx_hw->ws_rx = NULL; ++ rwnx_hw->ws_irqrx = NULL; ++ rwnx_hw->ws_pwrctrl = NULL; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h +new file mode 100644 +index 000000000000..9c9655a46be2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h +@@ -0,0 +1,21 @@ ++#ifndef __RWNX_WAKELOCK_H ++#define __RWNX_WAKELOCK_H ++ ++#include ++#include ++#include ++ ++struct wakeup_source *rwnx_wakeup_init(const char *name); ++void rwnx_wakeup_deinit(struct wakeup_source *ws); ++ ++struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name); ++void rwnx_wakeup_unregister(struct wakeup_source *ws); ++ ++void rwnx_wakeup_lock(struct wakeup_source *ws); ++void rwnx_wakeup_unlock(struct wakeup_source *ws); ++void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec); ++ ++void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw); ++void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c +new file mode 100644 +index 000000000000..f59409946e39 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c +@@ -0,0 +1,137 @@ ++/** ++ * sdio_host.c ++ * ++ * SDIO host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#include "sdio_host.h" ++//#include "ipc_compat.h" ++#include "rwnx_tx.h" ++#include "rwnx_platform.h" ++#include "aicwf_debug.h" ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_sdio_host_init(struct sdio_host_env_tag *env, ++ void *cb, ++ void *shared_env_ptr, ++ void *pthis) ++{ ++ // Reset the environments ++ ++ // Reset the Host environment ++ memset(env, 0, sizeof(struct sdio_host_env_tag)); ++ // Save the pointer to the register base ++ env->pthis = pthis; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++volatile struct txdesc_host *aicwf_sdio_host_txdesc_get(struct sdio_host_env_tag *env, const int queue_idx) ++{ ++ // struct ipc_shared_env_tag *shared_env_ptr = env->shared; ++ volatile struct txdesc_host *txdesc_free = NULL; ++ uint32_t used_idx = env->txdesc_used_idx[queue_idx]; ++ uint32_t free_idx = env->txdesc_free_idx[queue_idx]; ++ ++ // ASSERT_ERR(queue_idx < SDIO_TXQUEUE_CNT); ++ // ASSERT_ERR((free_idx - used_idx) <= SDIO_TXDESC_CNT); ++ ++ // Check if a free descriptor is available ++ if (free_idx != (used_idx + SDIO_TXDESC_CNT)) { ++ // Get the pointer to the first free descriptor ++ // txdesc_free = shared_env_ptr->txdesc[queue_idx] + (free_idx % IPC_TXDESC_CNT); ++ } else { ++ txdesc_free = NULL; ++ } ++ ++ return txdesc_free; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_sdio_host_txdesc_push(struct sdio_host_env_tag *env, const int queue_idx, const uint64_t host_id) ++{ ++ //printk("push, %d, %d, 0x%llx \r\n", queue_idx, env->txdesc_free_idx[queue_idx], host_id); ++ // Save the host id in the environment ++ env->tx_host_id[queue_idx][env->txdesc_free_idx[queue_idx] % SDIO_TXDESC_CNT] = host_id; ++ ++ // Increment the index ++ env->txdesc_free_idx[queue_idx]++; ++ if (env->txdesc_free_idx[queue_idx] == 0x80000000) ++ env->txdesc_free_idx[queue_idx] = 0; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_sdio_host_tx_cfm_handler(struct sdio_host_env_tag *env, u32 *data) ++{ ++ u32 queue_idx = 0;// data[0]; ++ //struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)env->pthis; ++ struct sk_buff *skb = NULL; ++ struct rwnx_txhdr *txhdr; ++ ++ // TX confirmation descriptors have been received ++ // REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM); ++ //while (1) ++ { ++ // Get the used index and increase it. We do the increase before knowing if the ++ // current buffer is confirmed because the callback function may call the ++ // ipc_host_txdesc_get() in case flow control was enabled and the index has to be ++ // already at the good value to ensure that the test of FIFO full is correct ++ //uint32_t used_idx = env->txdesc_used_idx[queue_idx]++; ++ uint32_t used_idx = data[1]; ++ unsigned long host_id = env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT]; ++ ++ // Reset the host id in the array ++ env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = 0; ++ ++ // call the external function to indicate that a TX packet is freed ++ if (host_id == 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ AICWFDBG(LOGERROR, "ERROR:No more confirmations\r\n"); ++ //break; ++ } ++ // set the cfm status ++ skb = (struct sk_buff *)host_id; ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ txhdr->hw_hdr.cfm.status = (union rwnx_hw_txstatus)data[0]; ++ AICWFDBG(LOGINFO, "sdio_host_tx_cfm_handler:used_idx=%d, 0x%p, status=%x\r\n", used_idx, env->pthis, txhdr->hw_hdr.cfm.status.value); ++ //if (env->cb.send_data_cfm(env->pthis, host_id) != 0) ++ if (rwnx_txdatacfm(env->pthis, (void *)host_id) != 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = host_id; ++ // and exit the loop ++ AICWFDBG(LOGERROR, "ERROR:rwnx_txdatacfm,\r\n"); ++ // break; ++ } ++ } ++} ++ ++int aicwf_rwnx_sdio_platform_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct rwnx_plat *rwnx_plat = NULL; ++ void *drvdata; ++ int ret = -ENODEV; ++ ++ rwnx_plat = kzalloc(sizeof(struct rwnx_plat), GFP_KERNEL); ++ ++ if (!rwnx_plat) { ++ return -ENOMEM; ++ } ++ ++ rwnx_plat->sdiodev = sdiodev; ++ ret = rwnx_platform_init(rwnx_plat, &drvdata); ++ ++ return ret; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h +new file mode 100644 +index 000000000000..670e9e08663d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h +@@ -0,0 +1,41 @@ ++/** ++ * sdio_host.h ++ * ++ * SDIO host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#ifndef _SDIO_HOST_H_ ++#define _SDIO_HOST_H_ ++ ++#include "lmac_types.h" ++#include "aicwf_sdio.h" ++ ++#define SDIO_TXQUEUE_CNT NX_TXQ_CNT ++#define SDIO_TXDESC_CNT NX_TXDESC_CNT ++ ++ ++/// Definition of the IPC Host environment structure. ++struct sdio_host_env_tag { ++ // Index used that points to the first free TX desc ++ uint32_t txdesc_free_idx[SDIO_TXQUEUE_CNT]; ++ // Index used that points to the first used TX desc ++ uint32_t txdesc_used_idx[SDIO_TXQUEUE_CNT]; ++ // Array storing the currently pushed host ids, per IPC queue ++ uint64_t tx_host_id[SDIO_TXQUEUE_CNT][SDIO_TXDESC_CNT]; ++ ++ /// Pointer to the attached object (used in callbacks and register accesses) ++ void *pthis; ++}; ++ ++extern void aicwf_sdio_host_init(struct sdio_host_env_tag *env, ++ void *cb, void *shared_env_ptr, void *pthis); ++ ++extern void aicwf_sdio_host_txdesc_push(struct sdio_host_env_tag *env, const int queue_idx, const uint64_t host_id); ++ ++extern void aicwf_sdio_host_tx_cfm_handler(struct sdio_host_env_tag *env, u32 *data); ++extern int aicwf_rwnx_sdio_platform_init(struct aic_sdio_dev *sdiodev); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c +new file mode 100644 +index 000000000000..c5c86d0de27b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c +@@ -0,0 +1,146 @@ ++/** ++ * usb_host.c ++ * ++ * USB host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#include "usb_host.h" ++//#include "ipc_compat.h" ++#include "rwnx_tx.h" ++#include "rwnx_platform.h" ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_usb_host_init(struct usb_host_env_tag *env, ++ void *cb, ++ void *shared_env_ptr, ++ void *pthis) ++{ ++ // Reset the environments ++ ++ // Reset the Host environment ++ memset(env, 0, sizeof(struct usb_host_env_tag)); ++ //printk("[Gaofx]rwnx_init_aic pthis %p !\n", pthis); ++ // Save the pointer to the register base ++ env->pthis = pthis; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++volatile struct txdesc_host *aicwf_usb_host_txdesc_get(struct usb_host_env_tag *env, const int queue_idx) ++{ ++ // struct ipc_shared_env_tag *shared_env_ptr = env->shared; ++ volatile struct txdesc_host *txdesc_free = NULL; ++ uint32_t used_idx = env->txdesc_used_idx[queue_idx]; ++ uint32_t free_idx = env->txdesc_free_idx[queue_idx]; ++ ++ // ASSERT_ERR(queue_idx < SDIO_TXQUEUE_CNT); ++ // ASSERT_ERR((free_idx - used_idx) <= USB_TXDESC_CNT); ++ ++ // Check if a free descriptor is available ++ if (free_idx != (used_idx + USB_TXDESC_CNT)) { ++ // Get the pointer to the first free descriptor ++ // txdesc_free = shared_env_ptr->txdesc[queue_idx] + (free_idx % IPC_TXDESC_CNT); ++ } else { ++ txdesc_free = NULL; ++ } ++ ++ return txdesc_free; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_usb_host_txdesc_push(struct usb_host_env_tag *env, const int queue_idx, const uint64_t host_id) ++{ ++ //printk("push, %d, %d, 0x%llx \r\n", queue_idx, env->txdesc_free_idx[queue_idx], host_id); ++ // Save the host id in the environment ++ env->tx_host_id[queue_idx][env->txdesc_free_idx[queue_idx] % USB_TXDESC_CNT] = host_id; ++ ++ // Increment the index ++ env->txdesc_free_idx[queue_idx]++; ++ if (env->txdesc_free_idx[queue_idx] == 0x80000000) ++ env->txdesc_free_idx[queue_idx] = 0; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_usb_host_tx_cfm_handler(struct usb_host_env_tag *env, u32 *data) ++{ ++ u32 queue_idx = 0;//data[0]; ++ //struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)env->pthis; ++ struct sk_buff *skb = NULL; ++ struct rwnx_txhdr *txhdr; ++ printk("%s enter \n", __func__); ++ //printk("sdio_host_tx_cfm_handler, %d, 0x%08x\r\n", queue_idx, data[1]); ++ // TX confirmation descriptors have been received ++ // REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM); ++ //while (1) ++ { ++ // Get the used index and increase it. We do the increase before knowing if the ++ // current buffer is confirmed because the callback function may call the ++ // ipc_host_txdesc_get() in case flow control was enabled and the index has to be ++ // already at the good value to ensure that the test of FIFO full is correct ++ //uint32_t used_idx = env->txdesc_used_idx[queue_idx]++; ++ uint32_t used_idx = data[1]; ++ uint64_t host_id = env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT]; ++ ++ // Reset the host id in the array ++ env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT] = 0; ++ ++ // call the external function to indicate that a TX packet is freed ++ if (host_id == 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ printk("ERROR:No more confirmations\r\n"); ++ return; ++ //break; ++ } ++ // set the cfm status ++ skb = (struct sk_buff *)(uint64_t)host_id; ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ txhdr->hw_hdr.cfm.status = (union rwnx_hw_txstatus)data[0]; ++ //txhdr->hw_hdr.status = data[1]; ++ //printk("sdio_host_tx_cfm_handler, 0x%p\r\n", env->pthis); ++ //if (env->cb.send_data_cfm(env->pthis, host_id) != 0) ++ if (rwnx_txdatacfm(env->pthis, (void *)host_id) != 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT] = host_id; ++ // and exit the loop ++ printk("ERROR:rwnx_txdatacfm,\r\n"); ++ // break; ++ } ++ } ++} ++ ++int aicwf_rwnx_usb_platform_init(struct aic_usb_dev *usbdev) ++{ ++ struct rwnx_plat *rwnx_plat = NULL; ++ void *drvdata; ++ int ret = -ENODEV; ++ ++ rwnx_plat = kzalloc(sizeof(struct rwnx_plat), GFP_KERNEL); ++ ++ if (!rwnx_plat) ++ return -ENOMEM; ++ ++// rwnx_plat->pci_dev = pci_dev; ++ rwnx_plat->usbdev = usbdev; ++ ++ ret = rwnx_platform_init(rwnx_plat, &drvdata); ++#if 0 ++ pci_set_drvdata(pci_dev, drvdata); ++ ++ if (ret) ++ rwnx_plat->deinit(rwnx_plat); ++#endif ++ return ret; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h +new file mode 100644 +index 000000000000..012b90c9770a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h +@@ -0,0 +1,41 @@ ++/** ++ * usb_host.h ++ * ++ * USB host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#ifndef _USB_HOST_H_ ++#define _USB_HOST_H_ ++ ++#include "lmac_types.h" ++#include "aicwf_usb.h" ++ ++#define USB_TXQUEUE_CNT NX_TXQ_CNT ++#define USB_TXDESC_CNT NX_TXDESC_CNT ++ ++ ++/// Definition of the IPC Host environment structure. ++struct usb_host_env_tag { ++ // Index used that points to the first free TX desc ++ uint32_t txdesc_free_idx[USB_TXQUEUE_CNT]; ++ // Index used that points to the first used TX desc ++ uint32_t txdesc_used_idx[USB_TXQUEUE_CNT]; ++ // Array storing the currently pushed host ids, per IPC queue ++ uint64_t tx_host_id[USB_TXQUEUE_CNT][USB_TXDESC_CNT]; ++ ++ /// Pointer to the attached object (used in callbacks and register accesses) ++ void *pthis; ++}; ++ ++extern void aicwf_usb_host_init(struct usb_host_env_tag *env, ++ void *cb, void *shared_env_ptr, void *pthis); ++ ++extern void aicwf_usb_host_txdesc_push(struct usb_host_env_tag *env, const int queue_idx, const uint64_t host_id); ++ ++extern void aicwf_usb_host_tx_cfm_handler(struct usb_host_env_tag *env, u32 *data); ++extern int aicwf_rwnx_usb_platform_init(struct aic_usb_dev *usbdev); ++ ++#endif diff --git a/patch/kernel/archive/rockchip64-6.18/drv-add-aic8800-sdio.patch b/patch/kernel/archive/rockchip64-6.18/drv-add-aic8800-sdio.patch new file mode 100644 index 000000000000..673ae0921e8f --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/drv-add-aic8800-sdio.patch @@ -0,0 +1,90985 @@ +diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig +index c6599594dc99..81a95a3a4e9a 100644 +--- a/drivers/net/wireless/Kconfig ++++ b/drivers/net/wireless/Kconfig +@@ -19,6 +19,7 @@ menuconfig WLAN + if WLAN + + source "drivers/net/wireless/admtek/Kconfig" ++source "drivers/net/wireless/aic8800_sdio/Kconfig" + source "drivers/net/wireless/ath/Kconfig" + source "drivers/net/wireless/atmel/Kconfig" + source "drivers/net/wireless/broadcom/Kconfig" +diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile +index e1c4141c6004..6837a10805ff 100644 +--- a/drivers/net/wireless/Makefile ++++ b/drivers/net/wireless/Makefile +@@ -4,6 +4,7 @@ + # + + obj-$(CONFIG_WLAN_VENDOR_ADMTEK) += admtek/ ++obj-$(CONFIG_SPARD_WLAN_SUPPORT) += aic8800_sdio/ + obj-$(CONFIG_WLAN_VENDOR_ATH) += ath/ + obj-$(CONFIG_WLAN_VENDOR_ATMEL) += atmel/ + obj-$(CONFIG_WLAN_VENDOR_BROADCOM) += broadcom/ +diff --git a/drivers/net/wireless/aic8800_sdio/Kconfig b/drivers/net/wireless/aic8800_sdio/Kconfig +new file mode 100644 +index 000000000000..e12a89df7899 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/Kconfig +@@ -0,0 +1,17 @@ ++config AIC_WLAN_SUPPORT ++ bool "AIC wireless Support" ++ default y ++ help ++ This is support for aic wireless chip. ++ ++config AIC_FW_PATH ++ depends on AIC_WLAN_SUPPORT ++ string "Firmware & config file path" ++ default "/lib/firmware/aic8800/SDIO/aic8800D80" ++ help ++ Path to the firmware & config file. ++ ++if AIC_WLAN_SUPPORT ++source "drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig" ++source "drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig" ++endif +diff --git a/drivers/net/wireless/aic8800_sdio/Makefile b/drivers/net/wireless/aic8800_sdio/Makefile +new file mode 100644 +index 000000000000..6f02ee9570cd +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/Makefile +@@ -0,0 +1,92 @@ ++CONFIG_AIC8800_BTLPM_SUPPORT := m ++CONFIG_AIC8800_WLAN_SUPPORT := m ++CONFIG_AIC_WLAN_SUPPORT := m ++ ++obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) += aic8800_btlpm/ ++obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/ ++obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800_bsp/ ++ ++MAKEFLAGS +=-j$(shell nproc) ++ ++########## config option ########## ++export CONFIG_USE_FW_REQUEST = n ++export CONFIG_PREALLOC_RX_SKB = y ++export CONFIG_PREALLOC_TXQ = y ++export CONFIG_OOB = n ++export CONFIG_GPIO_WAKEUP = n ++export CONFIG_RESV_MEM_SUPPORT = y ++################################### ++ ++########## Platform support list ########## ++export CONFIG_PLATFORM_ROCKCHIP = n ++export CONFIG_PLATFORM_ROCKCHIP2 = n ++export CONFIG_PLATFORM_ALLWINNER = n ++export CONFIG_PLATFORM_AMLOGIC = n ++export CONFIG_PLATFORM_UBUNTU = y ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ARCH = arm64 ++KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-y += -DANDROID_PLATFORM ++ccflags-y += -DCONFIG_PLATFORM_ROCKCHIP ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++KDIR := /home/yaya/E/Rockchip/3126/Android6/kernel ++ARCH ?= arm ++CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android5/rk3288_JHY/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- ++ccflags-y += -DANDROID_PLATFORM ++ccflags-y += -DCONFIG_PLATFORM_ROCKCHIP2 ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++KDIR = /home/yaya/E/Allwinner/A133/Android10/linux-4.9 ++ARCH = arm64 ++CROSS_COMPILE = /home/yaya/E/Allwinner/r818/Android10/lichee/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++export CONFIG_SUPPORT_LPM = y ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ARCH = arm ++CROSS_COMPILE = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel- ++KDIR = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/out/target/product/u202/obj/KERNEL_OBJ/ ++ccflags-y += -DANDROID_PLATFORM ++export CONFIG_SUPPORT_LPM = y ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++KDIR = /lib/modules/$(shell uname -r)/build ++PWD = $(shell pwd) ++KVER = $(shell uname -r) ++MODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800 ++SUBARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/armv.l/arm/ -e s/aarch64/arm64/) ++ARCH ?= $(SUBARCH) ++CROSS_COMPILE ?= ++endif ++########################################### ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 aic8800_bsp/aic8800_bsp.ko $(MODDESTDIR)/ ++ install -p -m 644 aic8800_fdrv/aic8800_fdrv.ko $(MODDESTDIR)/ ++ install -p -m 644 aic8800_btlpm/aic8800_btlpm.ko $(MODDESTDIR)/ ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/aic8800_bsp.ko ++ rm -rfv $(MODDESTDIR)/aic8800_fdrv.ko ++ rm -rfv $(MODDESTDIR)/aic8800_btlpm.ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ cd aic8800_bsp/;make clean;cd .. ++ cd aic8800_fdrv/;make clean;cd .. ++ cd aic8800_btlpm/;make clean;cd .. ++ rm -rf modules.order Module.symvers .modules.order.cmd .Module.symvers.cmd .tmp_versions/ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore +new file mode 100644 +index 000000000000..c3c2d151e157 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile +new file mode 100644 +index 000000000000..3e3849d0652a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile +@@ -0,0 +1,155 @@ ++CONFIG_SDIO_SUPPORT := y ++CONFIG_SDIO_PWRCTRL := y ++CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800/SDIO/aic8800D80" ++export CONFIG_AIC_FW_PATH ++ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\" ++ ++MODULE_NAME := aic8800_bsp ++ifeq ($(CONFIG_SDIO_SUPPORT), y) ++ccflags-y += -DAICWF_SDIO_SUPPORT ++ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL ++endif ++ ++CONFIG_GPIO_WAKEUP ?= n ++CONFIG_M2D_OTA_AUTO_SUPPORT = n ++CONFIG_M2D_OTA_LZMA_SUPPORT = n ++CONFIG_LINK_DET_5G = y ++CONFIG_MCU_MESSAGE = n ++CONFIG_FIRMWARE_ARRAY = n ++# Need to set fw path in BOARD_KERNEL_CMDLINE ++CONFIG_USE_FW_REQUEST ?= n ++CONFIG_FDRV_NO_REG_SDIO = n ++CONFIG_VRF_DCDC_MODE = y ++CONFIG_OOB ?= n ++CONFIG_PREALLOC_TXQ = y ++CONFIG_DPD = y ++CONFIG_FORCE_DPD_CALIB = y ++CONFIG_LOFT_CALIB = n ++CONFIG_EXT_FEM_8800DCDW = n ++CONFIG_RESV_MEM_SUPPORT ?= y ++CONFIG_AMSDU_RX = y ++CONFIG_IRQ_FALL ?= n ++CONFIG_SDIO_BT = n ++CONFIG_RADAR_OR_IR_DETECT =n ++CONFIG_FOR_IPCAM = n ++ ++ifeq ($(CONFIG_EXT_FEM_8800DCDW), y) ++CONFIG_DPD = n ++CONFIG_FORCE_DPD_CALIB = n ++CONFIG_LOFT_CALIB = y ++endif ++ ++ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP ++ccflags-$(CONFIG_M2D_OTA_AUTO_SUPPORT) += -DCONFIG_M2D_OTA_AUTO_SUPPORT ++ccflags-$(CONFIG_M2D_OTA_LZMA_SUPPORT) += -DCONFIG_M2D_OTA_LZMA_SUPPORT ++ccflags-$(CONFIG_LINK_DET_5G) += -DCONFIG_LINK_DET_5G ++ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE ++ccflags-$(CONFIG_FIRMWARE_ARRAY) += -DCONFIG_FIRMWARE_ARRAY ++ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST ++ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO ++ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE ++ccflags-$(CONFIG_OOB) += -DCONFIG_OOB ++ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ ++ccflags-$(CONFIG_DPD) += -DCONFIG_DPD ++ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD ++ccflags-$(CONFIG_LOFT_CALIB) += -DCONFIG_LOFT_CALIB ++ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW ++ccflags-$(CONFIG_RESV_MEM_SUPPORT) += -DCONFIG_RESV_MEM_SUPPORT ++ccflags-$(CONFIG_AMSDU_RX) += -DCONFIG_AMSDU_RX ++ccflags-$(CONFIG_IRQ_FALL) += -DCONFIG_IRQ_FALL ++ccflags-$(CONFIG_SDIO_BT) += -DCONFIG_SDIO_BT ++ccflags-$(CONFIG_RADAR_OR_IR_DETECT) += -DCONFIG_RADAR_OR_IR_DETECT ++ccflags-$(CONFIG_FOR_IPCAM) += -DCONFIG_FOR_IPCAM ++ ++ ++obj-m := $(MODULE_NAME).o ++$(MODULE_NAME)-y := \ ++ aic8800dc_compat.o \ ++ aic8800d80_compat.o \ ++ aic_bsp_main.o \ ++ aic_bsp_driver.o \ ++ aicsdio.o \ ++ aicsdio_txrxif.o \ ++ md5.o ++ ++$(MODULE_NAME)-$(CONFIG_PREALLOC_TXQ) += aicwf_txq_prealloc.o ++ ++ifeq ($(CONFIG_FIRMWARE_ARRAY),y) ++$(MODULE_NAME)-y += aicwf_firmware_array.o ++endif ++ ++########## Platform support list ########## ++CONFIG_PLATFORM_ROCKCHIP ?= n ++CONFIG_PLATFORM_ROCKCHIP2 ?= n ++CONFIG_PLATFORM_ALLWINNER ?=n ++CONFIG_PLATFORM_INGENIC_T20 ?= n ++CONFIG_PLATFORM_AMLOGIC ?= n ++CONFIG_PLATFORM_UBUNTU ?= y ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 ++ARCH ?= arm64 ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/ ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ++ ++endif ++ ++ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y) ++KDIR ?= /home/yaya/E/T40/kernel ++ARCH ?= mips ++CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC ++KDIR ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/out/target/product/u202/obj/KERNEL_OBJ/ ++ARCH ?= arm ++CROSS_COMPILE ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++ccflags-$(CONFIG_PLATFORM_UBUNTU) += -DCONFIG_PLATFORM_UBUNTU ++KDIR ?= /lib/modules/$(shell uname -r)/build ++PWD ?= $(shell pwd) ++KVER ?= $(shell uname -r) ++MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ++ARCH ?= x86_64 ++CROSS_COMPILE ?= ++ ++ifeq ($(CONFIG_AW_BSP), y) ++ccflags-y += -DCONFIG_PLATFORM_ALLWINNER ++endif ++ ++endif ++########################################### ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk built-in.a ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c +new file mode 100644 +index 000000000000..847da05ad75c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c +@@ -0,0 +1,267 @@ ++#include "aic8800d80_compat.h" ++#include "aic_bsp_driver.h" ++ ++extern struct aicbsp_info_t aicbsp_info; ++extern int adap_test; ++ ++typedef u32 (*array2_tbl_t)[2]; ++ ++#define AIC_PATCH_MAGIG_NUM 0x48435450 // "PTCH" ++#define AIC_PATCH_MAGIG_NUM_2 0x50544348 // "HCTP" ++#define AIC_PATCH_BLOCK_MAX 4 ++ ++typedef struct { ++ uint32_t magic_num; ++ uint32_t pair_start; ++ uint32_t magic_num_2; ++ uint32_t pair_count; ++ uint32_t block_dst[AIC_PATCH_BLOCK_MAX]; ++ uint32_t block_src[AIC_PATCH_BLOCK_MAX]; ++ uint32_t block_size[AIC_PATCH_BLOCK_MAX]; // word count ++} aic_patch_t; ++ ++#define AIC_PATCH_OFST(mem) ((size_t) &((aic_patch_t *)0)->mem) ++#define AIC_PATCH_ADDR(mem) ((u32)(aic_patch_str_base + AIC_PATCH_OFST(mem))) ++ ++u32 aicbsp_syscfg_tbl_8800d80[][2] = { ++}; ++ ++int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev) ++{ ++ int syscfg_num = sizeof(aicbsp_syscfg_tbl_8800d80) / sizeof(u32) / 2; ++ int ret, cnt; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl_8800d80[cnt][0], aicbsp_syscfg_tbl_8800d80[cnt][1]); ++ if (ret) { ++ printk("%x write fail: %d\n", aicbsp_syscfg_tbl_8800d80[cnt][0], ret); ++ return ret; ++ } ++ } ++ return 0; ++} ++ ++ ++u32 adaptivity_patch_tbl_8800d80[][2] = { ++ {0x000C, 0x0000320A}, //linkloss_thd ++ {0x009C, 0x00000000}, //ac_param_conf ++ {0x0168, 0x00010000}, //tx_adaptivity_en ++}; ++ ++#define USER_PWROFST_COVER_CALIB_FLAG 0x01U ++#define USER_CHAN_MAX_TXPWR_EN_FLAG (0x01U << 1) ++#define USER_TX_USE_ANA_F_FLAG (0x01U << 2) ++#define USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG (0x01U << 3) ++ ++#define CFG_PWROFST_COVER_CALIB 1 ++#define CFG_USER_CHAN_MAX_TXPWR_EN 1 ++#define CFG_USER_TX_USE_ANA_F 0 ++#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE 0 ++ ++ ++#define CFG_USER_EXT_FLAGS_EN (CFG_PWROFST_COVER_CALIB || CFG_USER_CHAN_MAX_TXPWR_EN || CFG_USER_TX_USE_ANA_F || CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE) ++ ++u32 patch_tbl_8800d80[][2] = { ++ #ifdef USE_5G ++ {0x00b4, 0xf3010001}, ++ #else ++ {0x00b4, 0xf3010000}, ++ #endif ++#if defined(CONFIG_AMSDU_RX) ++ {0x170, 0x0100000a}, ++#endif ++#ifdef CONFIG_IRQ_FALL ++ {0x00000170, 0x0000010a}, //irqf ++#endif ++ ++ #if CFG_USER_EXT_FLAGS_EN ++ {0x0188, 0x00000000 ++ #if CFG_PWROFST_COVER_CALIB ++ | USER_PWROFST_COVER_CALIB_FLAG ++ #endif ++ #if CFG_USER_CHAN_MAX_TXPWR_EN ++ | USER_CHAN_MAX_TXPWR_EN_FLAG ++ #endif ++ #if CFG_USER_TX_USE_ANA_F ++ | USER_TX_USE_ANA_F_FLAG ++ #endif ++ #if CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE ++ | USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG ++ #endif ++ }, // user_ext_flags ++ #endif ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ {0x019c, 0x00000100}, //enable radar detect ++#endif ++}; ++ ++#ifdef CONFIG_OOB ++// for 8800d40/d80 map data1 isr to gpiob1 ++u32 gpio_cfg_tbl_8800d40d80[][2] = { ++ {0x40504084, 0x00000006}, ++ {0x40500040, 0x00000000}, ++ {0x40100030, 0x00000001}, ++ {0x40241020, 0x00000001}, ++ {0x40240030, 0x00000004}, ++ {0x40240020, 0x03020700}, ++}; ++#endif ++ ++int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev) ++{ ++#ifdef CONFIG_OOB ++ int ret, cnt; ++ int gpiocfg_num = sizeof(gpio_cfg_tbl_8800d40d80) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < gpiocfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, gpio_cfg_tbl_8800d40d80[cnt][0], gpio_cfg_tbl_8800d40d80[cnt][1]); ++ if (ret) { ++ printk("%x write fail: %d\n", gpio_cfg_tbl_8800d40d80[cnt][0], ret); ++ return ret; ++ } ++ } ++#endif ++ ++ return 0; ++} ++ ++#define NEW_PATCH_BUFFER_MAP 1 ++ ++int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev) ++{ ++ const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0198; ++ u32 aic_patch_addr; ++ u32 config_base, aic_patch_str_base; ++ #if (NEW_PATCH_BUFFER_MAP) ++ u32 patch_buff_addr, patch_buff_base, rd_version_addr, rd_version_val; ++ #endif ++ uint32_t start_addr = 0x0016F800; ++ u32 patch_addr = start_addr; ++ u32 patch_cnt = sizeof(patch_tbl_8800d80)/sizeof(u32)/2; ++ struct dbg_mem_read_cfm rd_patch_addr_cfm; ++ int ret = 0; ++ int cnt = 0; ++ //adap test ++ int adap_patch_cnt = 0; ++ ++ if (adap_test) { ++ printk("%s for adaptivity test \r\n", __func__); ++ adap_patch_cnt = sizeof(adaptivity_patch_tbl_8800d80)/sizeof(u32)/2; ++ } ++ ++ aic_patch_addr = rd_patch_addr + 8; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch rd fail\n"); ++ return ret; ++ } ++ ++ config_base = rd_patch_addr_cfm.memdata; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, aic_patch_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch str rd fail\n"); ++ return ret; ++ } ++ aic_patch_str_base = rd_patch_addr_cfm.memdata; ++ ++ #if (NEW_PATCH_BUFFER_MAP) ++ rd_version_addr = RAM_FMAC_FW_ADDR + 0x01C; ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_version_addr, &rd_patch_addr_cfm))) { ++ printk("version val[0x%x] rd fail: %d\n", rd_version_addr, ret); ++ return ret; ++ } ++ rd_version_val = rd_patch_addr_cfm.memdata; ++ printk("rd_version_val=%08X\n", rd_version_val); ++ sdiodev->fw_version_uint = rd_version_val; ++ if (rd_version_val > 0x06090100) { ++ patch_buff_addr = rd_patch_addr + 12; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, patch_buff_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch buf rd fail\n"); ++ return ret; ++ } ++ patch_buff_base = rd_patch_addr_cfm.memdata; ++ patch_addr = start_addr = patch_buff_base; ++ } ++ #endif ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num)); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num_2), AIC_PATCH_MAGIG_NUM_2); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num_2)); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_start), patch_addr); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_start)); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_count), patch_cnt + adap_patch_cnt); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_count)); ++ return ret; ++ } ++ ++ for (cnt = 0; cnt < patch_cnt; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl_8800d80[cnt][0]+config_base); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl_8800d80[cnt][1]); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ return ret; ++ } ++ } ++ ++ if (adap_test){ ++ int tmp_cnt = patch_cnt + adap_patch_cnt; ++ for (cnt = patch_cnt; cnt < tmp_cnt; cnt++) { ++ int tbl_idx = cnt - patch_cnt; ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, adaptivity_patch_tbl_8800d80[tbl_idx][0]+config_base); ++ if(ret) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, adaptivity_patch_tbl_8800d80[tbl_idx][1]); ++ if(ret) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ return ret; ++ } ++ } ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[0]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[0]), ret); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[1]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[1]), ret); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[2]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[2]), ret); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[3]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[3]), ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h +new file mode 100644 +index 000000000000..20956582620f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h +@@ -0,0 +1,24 @@ ++#ifndef _AIC8800D80_COMPAT_H_ ++#define _AIC8800D80_COMPAT_H_ ++ ++#include "aicsdio.h" ++/*typedef u32 (*array2_tbl_t)[2]; ++ ++typedef uint8_t u8_l; ++typedef int8_t s8_l; ++typedef bool bool_l; ++typedef uint16_t u16_l; ++typedef int16_t s16_l; ++typedef uint32_t u32_l; ++typedef int32_t s32_l; ++typedef uint64_t u64_l;*/ ++ ++int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev); ++int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev); ++int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev); ++ ++ ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c +new file mode 100644 +index 000000000000..8efd2b81e194 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c +@@ -0,0 +1,2633 @@ ++#include ++#include "aic8800dc_compat.h" ++#include "aic_bsp_driver.h" ++ ++u8 chip_sub_id = 0; ++u8 chip_mcu_id = 0; ++extern int testmode; ++ ++u32 syscfg_tbl_8800dc[][2] = { ++ {0x40500010, 0x00000004}, ++ {0x40500010, 0x00000006},//160m clk ++}; ++ ++u32 syscfg_tbl_8800dc_sdio_u01[][2] = { ++ {0x40030000, 0x00036724}, // loop forever after assert_err ++ {0x0011E800, 0xE7FE4070}, ++ {0x40030084, 0x0011E800}, ++ {0x40030080, 0x00000001}, ++ {0x4010001C, 0x00000000}, ++}; ++ ++u32 syscfg_tbl_8800dc_sdio_u02[][2] = { ++ {0x40030000, 0x00036DA4}, // loop forever after assert_err ++ {0x0011E800, 0xE7FE4070}, ++ {0x40030084, 0x0011E800}, ++ {0x40030080, 0x00000001}, ++ {0x4010001C, 0x00000000}, ++}; ++#ifdef CONFIG_OOB ++u32 oobcfg_tbl_8800dc_sdio_u02[][2] = { ++ {0x40504044, 0x2},//oob_enable ++ {0x40500060, 0x03020700}, ++ {0x40500040, 0}, ++ {0x40100030, 1}, ++ {0x40241020, 1}, ++ {0x402400f0, 0x340022}, ++}; ++#endif //CONFIG_OOB ++ ++ ++u32 syscfg_tbl_masked_8800dc[][3] = { ++ //#ifdef CONFIG_PMIC_SETTING ++ #if defined(CONFIG_VRF_DCDC_MODE) ++ {0x7000216C, (0x3 << 2), (0x1 << 2)}, // pmic_pmu_init ++ {0x700021BC, (0x3 << 2), (0x1 << 2)}, ++ {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, ++ {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x70002170, (0xF << 0), (0x1 << 0)}, ++ {0x70002190, (0x3F << 0), (24 << 0)}, ++ {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, ++ {0x700010A0, (0x1 << 11), (0x1 << 11)}, ++ {0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))}, ++ {0x70001038, (0x1 << 8), (0x1 << 8)}, ++ {0x70001094, (0x3 << 2), (0x0 << 2)}, ++ {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x1 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ {0x70001028, (0xf << 2), (0x1 << 2)}, ++ #else ++ {0x7000216C, (0x3 << 2), (0x1 << 2)}, // pmic_pmu_init ++ {0x700021BC, (0x3 << 2), (0x1 << 2)}, ++ {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, ++ {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x70002170, (0xF << 0), (0x1 << 0)}, ++ {0x70002190, (0x3F << 0), (24 << 0)}, ++ {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, ++ {0x700010A0, (0x1 << 11), (0x1 << 11)}, ++ {0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))}, ++ {0x70001038, (0x1 << 8), (0x1 << 8)}, ++ {0x70001094, (0x3 << 2), (0x0 << 2)}, ++ {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x0 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ {0x70001028, (0xf << 2), (0x1 << 2)}, ++ #endif ++ //#endif /* CONFIG_PMIC_SETTING */ ++ {0x00000000, 0x00000000, 0x00000000}, // last one ++}; ++ ++u32 syscfg_tbl_masked_8800dc_h[][3] = { ++ {0x7000216C, ((0x3 << 2) | (0x3 << 4)), ((0x2 << 2) | (0x2 << 4))}, // pmic_pmu_init ++ {0x70002138, (0xFF << 0), (0xFF << 0)}, ++ {0x7000213C, (0xFF << 0), (0xFF << 0)}, ++ {0x70002144, (0xFF << 0), (0xFF << 0)}, ++ {0x700021BC, (0x3 << 2), (0x1 << 2)}, ++ {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, ++ {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x70002170, (0xF << 0), (0x1 << 0)}, ++ {0x70002190, (0x3F << 0), (24 << 0)}, ++ {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, ++ {0x700010A0, (0x1 << 11), (0x1 << 11)}, ++ //{0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))}, ++ {0x70001038, (0x1 << 8), (0x1 << 8)}, ++ {0x70001094, (0x3 << 2), (0x0 << 2)}, ++ {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, ++ #if defined(CONFIG_VRF_DCDC_MODE) ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x1 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ #else ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x0 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ #endif ++ {0x70001028, (0xf << 2), (0x1 << 2)}, ++ ++ {0x00000000, 0x00000000, 0x00000000}, // last one ++}; ++ ++u32 syscfg_tbl_masked_8800dc_u01[][3] = { ++ //#ifdef CONFIG_PMIC_SETTING ++ {0x70001000, (0x1 << 16), (0x1 << 16)}, // for low temperature ++ {0x70001028, (0x1 << 6), (0x1 << 6)}, ++ {0x70001000, (0x1 << 16), (0x0 << 16)}, ++ //#endif /* CONFIG_PMIC_SETTING */ ++}; ++ ++u32 patch_tbl_wifisetting_8800dc_u01[][2] = ++{ ++ {0x010c,0x01001E01} ++}; ++ ++u32 patch_tbl_wifisetting_8800dc_u02[][2] = ++{ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ {0x0124,0x01011E01} ++#else ++ {0x0124,0x01001E01} ++#endif ++}; ++ ++ ++ ++uint32_t ldpc_cfg_ram[] = { ++#if 0//def CONFIG_FPGA_VERIFICATION ++ 0x00363638, ++ 0x1DF8F834, ++ 0x1DF8F834, ++ 0x1DF8F834, ++ 0x1DF8F834, ++ 0x002F2F31, ++ 0x1DF8F82C, ++ 0x1DF8F82C, ++ 0x1DF8F82C, ++ 0x1DF8F82C, ++ 0x00363639, ++ 0x1AA5F834, ++ 0x1AA5F834, ++ 0x1ADEF834, ++ 0x1ADEF834, ++ 0x003A3A3E, ++ 0x1578F436, ++ 0x1578F436, ++ 0x1578F436, ++ 0x15B6F436, ++ 0x003B3B40, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x003B3B41, ++ 0x1DC4F838, ++ 0x1DC4F838, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x003B3B40, ++ 0x1781F838, ++ 0x1781F838, ++ 0x1781F838, ++ 0x17C4F838, ++ 0x003B3B40, ++ 0x0E81F838, ++ 0x0E81F838, ++ 0x0E81F838, ++ 0x0E82F838, ++ 0x003F3F43, ++ 0x1A92F83D, ++ 0x1A92F83E, ++ 0x1A92F83D, ++ 0x1ADDF83D, ++ 0x00272729, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F843, ++ 0x1DF8F843, ++ 0x00272729, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F842, ++ 0x1DF8F842, ++ 0x00262628, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00252528, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00262628, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00242427, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x00232326, ++ 0x1DF8F821, ++ 0x1DF8F820, ++ 0x1DF8F820, ++ 0x1DF8F820, ++ 0x00262628, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00242427, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x001F1F21, ++ 0x1DF8F81D, ++ 0x1DF8F81D, ++ 0x1DF8F81D, ++ 0x1DF8F81D, ++ 0x00262643, ++ 0x1DF8F822, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x0018182B, ++ 0x1DF8F816, ++ 0x1DBDF815, ++ 0x1DF8F815, ++ 0x1DF8F815, ++ 0x0018182A, ++ 0x1195F836, ++ 0x1195F815, ++ 0x1195F815, ++ 0x1196F815, ++ 0x0028282C, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0027272C, ++ 0x1DF8F824, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x0082824A, ++ 0x1ADFF841, ++ 0x1ADDF822, ++ 0x1ADEF822, ++ 0x1ADFF822, ++ 0x003E3E40, ++ 0x09D1F81D, ++ 0x095BF81D, ++ 0x095BF81D, ++ 0x095BF81D, ++ 0x0029292D, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x0028282C, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0029292D, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x0028282E, ++ 0x1DF8F825, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0026262C, ++ 0x1DF8F823, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x0028282D, ++ 0x1DF8F825, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x00282852, ++ 0x1DF8F827, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0029294E, ++ 0x1DF8F823, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x00212143, ++ 0x1DF8F821, ++ 0x1DECF81D, ++ 0x1DF4F81D, ++ 0x1DF8F81D, ++ 0x0086864D, ++ 0x1CF0F844, ++ 0x1CEDF823, ++ 0x1CEFF822, ++ 0x1CF0F822, ++ 0x0047474D, ++ 0x1BE8F823, ++ 0x1BE8F823, ++ 0x1BE9F822, ++ 0x1BEAF822, ++ 0x0018182F, ++ 0x14B0F83C, ++ 0x14B0F814, ++ 0x14B0F814, ++ 0x14B0F814, ++ 0x00404040, ++ 0x0AE1F81E, ++ 0x0A61F81D, ++ 0x0A61F81D, ++ 0x0A61F81D, ++ 0x002C2C40, ++ 0x09555526, ++ 0x09555512, ++ 0x09555513, ++ 0x09555512, ++ 0x00181840, ++ 0x06333329, ++ 0x06333314, ++ 0x06333314, ++ 0x06333314, ++ 0x002B2B2F, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x002B2B32, ++ 0x1DF8F829, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x002A2A2F, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x002A2A57, ++ 0x1DF8F82B, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x00919152, ++ 0x1DF8F84B, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x004C4C51, ++ 0x1DF8F826, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x00444440, ++ 0x0CF8F820, ++ 0x0C6EF81F, ++ 0x0C6EF81F, ++ 0x0C6EF81F, ++ 0x00424240, ++ 0x0D75753E, ++ 0x0D75751E, ++ 0x0D75751E, ++ 0x0D75751E, ++ 0x00191940, ++ 0x0539392E, ++ 0x05393914, ++ 0x05393914, ++ 0x05393914, ++ 0x002F2F32, ++ 0x1AA5F82C, ++ 0x1AA5F82C, ++ 0x1ADEF82C, ++ 0x1ADEF82C, ++ 0x002F2F40, ++ 0x0C6EDE2C, ++ 0x0C6EDE2C, ++ 0x0C6EDE2C, ++ 0x0C6EDE2C, ++ 0x00323240, ++ 0x053BB62E, ++ 0x053BB62E, ++ 0x053BB62E, ++ 0x053BB62E, ++ 0x00333339, ++ 0x1DC4F82F, ++ 0x1DC4F82F, ++ 0x1DF8F82F, ++ 0x1DF8F82F, ++ 0x00333340, ++ 0x0E81F82F, ++ 0x0E81F82F, ++ 0x0E81F82F, ++ 0x0E82F82F, ++ 0x00333340, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x00404040, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x00363640, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x00404040, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x00292940, ++ 0x07484825, ++ 0x07484812, ++ 0x07484812, ++ 0x07484812, ++ 0x00404040, ++ 0x07343428, ++ 0x07343414, ++ 0x07343414, ++ 0x07343414, ++ 0x00404040, ++ 0x0538382A, ++ 0x05383814, ++ 0x05383814, ++ 0x05383814, ++ 0x00404040, ++ 0x05292914, ++ 0x05292909, ++ 0x05292909, ++ 0x05292909, ++ 0x000B0B40, ++ 0x02111108, ++ 0x0211110E, ++ 0x02111108, ++ 0x02111108, ++ 0x00404040, ++ 0x063E3E2E, ++ 0x063E3E15, ++ 0x063E3E14, ++ 0x063E3E14, ++ 0x00404040, ++ 0x062E2E14, ++ 0x062E2E09, ++ 0x062E2E09, ++ 0x062E2E09, ++ 0x000B0B40, ++ 0x02131308, ++ 0x0213130F, ++ 0x02131308, ++ 0x02131308 ++#else ++ 0x00767679, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x006E6E72, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x0076767B, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x007E7E85, ++ 0x1DF4F876, ++ 0x1DF4F876, ++ 0x1DF4F876, ++ 0x1DF8F876, ++ 0x0081818A, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x0081818D, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x0081818A, ++ 0x1DF8F87B, ++ 0x1DF8F87C, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x007E7E40, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x008B8B92, ++ 0x1DF8F887, ++ 0x1DF8F889, ++ 0x1DF8F887, ++ 0x1DF8F887, ++ 0x00515155, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F889, ++ 0x1DF8F889, ++ 0x00515154, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F888, ++ 0x1DF8F888, ++ 0x004F4F53, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004F4F53, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004F4F53, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004E4E53, ++ 0x1DF8F849, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x004D4D52, ++ 0x1DF8F847, ++ 0x1DF8F847, ++ 0x1DF8F847, ++ 0x1DF8F847, ++ 0x004F4F55, ++ 0x1DF8F84B, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004E4E53, ++ 0x1DF8F849, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x0049494D, ++ 0x1DF8F844, ++ 0x1DF8F844, ++ 0x1DF8F844, ++ 0x1DF8F844, ++ 0x0051518F, ++ 0x1DF8F849, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x00424277, ++ 0x1DF8F83F, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x00424275, ++ 0x1DF8F89E, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x0055555C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x0053535C, ++ 0x1DF8F84C, ++ 0x1DF8F84B, ++ 0x1DF8F84B, ++ 0x1DF8F84B, ++ 0x00F8F89E, ++ 0x1DF8F88C, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x00898940, ++ 0x18F8F846, ++ 0x18CFF845, ++ 0x18CFF844, ++ 0x18CFF844, ++ 0x0056565F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x0055555E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x0056565F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x00555561, ++ 0x1DF8F850, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x0053535F, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x0055555F, ++ 0x1DF8F84F, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x005555AA, ++ 0x1DF8F854, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x005959A6, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x004F4F9B, ++ 0x1DF8F84E, ++ 0x1DF8F846, ++ 0x1DF8F846, ++ 0x1DF8F846, ++ 0x00F8F8A5, ++ 0x1DF8F894, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x009898A4, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x00464686, ++ 0x1DF8F8B3, ++ 0x1DF8F83D, ++ 0x1DF8F83D, ++ 0x1DF8F83D, ++ 0x008E8E40, ++ 0x1AF8F848, ++ 0x1ADFF848, ++ 0x1ADFF846, ++ 0x1ADFF846, ++ 0x007F7F40, ++ 0x18D2D275, ++ 0x18D2D23A, ++ 0x18D2D23A, ++ 0x18D2D239, ++ 0x00454540, ++ 0x0F868664, ++ 0x0F86863E, ++ 0x0F86863D, ++ 0x0F86863D, ++ 0x005C5C64, ++ 0x1DF8F856, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x005B5B68, ++ 0x1DF8F858, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x005A5A64, ++ 0x1DF8F855, ++ 0x1DF8F854, ++ 0x1DF8F854, ++ 0x1DF8F854, ++ 0x005A5AB5, ++ 0x1DF8F85B, ++ 0x1DF8F855, ++ 0x1DF8F854, ++ 0x1DF8F854, ++ 0x00F8F8B0, ++ 0x1DF8F8A3, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x00A4A4AE, ++ 0x1DF8F854, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x009A9A40, ++ 0x1DF8F84E, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x009C9C40, ++ 0x1DF8F895, ++ 0x1DF8F849, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x00494940, ++ 0x1197976F, ++ 0x11979742, ++ 0x11979741, ++ 0x11979741, ++ 0x006E6E74, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x006E6E40, ++ 0x1ADEF869, ++ 0x1ADEF869, ++ 0x1ADEF869, ++ 0x1ADEF869, ++ 0x00757540, ++ 0x0D78F86E, ++ 0x0D78F86E, ++ 0x0D78F86E, ++ 0x0D79F86E, ++ 0x00787885, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x00787840, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x00787840, ++ 0x0E81F873, ++ 0x0E81F873, ++ 0x0E81F873, ++ 0x0E82F873, ++ 0x00404040, ++ 0x0E82F873, ++ 0x0E82F873, ++ 0x0E82F873, ++ 0x0E82F873, ++ 0x00818140, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x00404040, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x00737340, ++ 0x14B2B26B, ++ 0x14B2B235, ++ 0x14B2B235, ++ 0x14B2B235, ++ 0x00404040, ++ 0x0E828260, ++ 0x0E82823D, ++ 0x0E82823C, ++ 0x0E82823C, ++ 0x00404040, ++ 0x0F8B8B66, ++ 0x0F8B8B3F, ++ 0x0F8B8B3D, ++ 0x0F8B8B3D, ++ 0x00404040, ++ 0x0B68683D, ++ 0x0B68681E, ++ 0x0B68681E, ++ 0x0B68681E, ++ 0x00222240, ++ 0x06434318, ++ 0x06434329, ++ 0x06434318, ++ 0x06434318, ++ 0x00404040, ++ 0x129D9D72, ++ 0x129D9D43, ++ 0x129D9D41, ++ 0x129D9D41, ++ 0x00404040, ++ 0x0D757542, ++ 0x0D757520, ++ 0x0D757520, ++ 0x0D757520, ++ 0x00232340, ++ 0x084C4C19, ++ 0x084C4C2C, ++ 0x084C4C19, ++ 0x084C4C19 ++#endif ++}; ++ ++uint32_t agc_cfg_ram[] = { ++ 0x20000000, ++ 0x0400000E, ++ 0x3000200E, ++ 0x5B000000, ++ 0x0400004B, ++ 0x3000008E, ++ 0x32000000, ++ 0x0400007B, ++ 0x40000000, ++ 0xF8000026, ++ 0x04000011, ++ 0x4819008E, ++ 0x9C000020, ++ 0x08000191, ++ 0x38008000, ++ 0x0A000000, ++ 0x08104411, ++ 0x38018000, ++ 0x0C004641, ++ 0x08D00014, ++ 0x30000000, ++ 0x01000000, ++ 0x04000017, ++ 0x30000000, ++ 0x3C000000, ++ 0x0400001A, ++ 0x38020000, ++ 0x40000001, ++ 0x0800001D, ++ 0x3808008E, ++ 0x14000050, ++ 0x08000020, ++ 0x4000008E, ++ 0xA400007B, ++ 0x00000101, ++ 0x3000339F, ++ 0x41000700, ++ 0x04104420, ++ 0x90000000, ++ 0x49000000, ++ 0xF00E842F, ++ 0xEC0E842C, ++ 0xEC0E842C, ++ 0x04000032, ++ 0x30000000, ++ 0x48000101, ++ 0x04000032, ++ 0x30000000, ++ 0x48000202, ++ 0x04000032, ++ 0x30000000, ++ 0x46000000, ++ 0x04000011, ++ 0x58010006, ++ 0x3D040472, ++ 0xDC204439, ++ 0x081DD4D2, ++ 0x480A0006, ++ 0xDC2044DC, ++ 0x081DD43C, ++ 0x38050004, ++ 0x0EF1F1C3, ++ 0x342044DC, ++ 0x30000000, ++ 0x01000000, ++ 0x04000042, ++ 0x30000000, ++ 0x33000000, ++ 0x04104445, ++ 0x38008000, ++ 0x2200109C, ++ 0x08104448, ++ 0x38008000, ++ 0x23D4509C, ++ 0x08104417, ++ 0x9000A000, ++ 0x32000000, ++ 0x18000063, ++ 0x14000060, ++ 0x1C000051, ++ 0x10000057, ++ 0x38028000, ++ 0x0C000001, ++ 0x08D04466, ++ 0x3000200F, ++ 0x00000000, ++ 0x00000000, ++ 0x38030000, ++ 0x0C002601, ++ 0x08D0445A, ++ 0x30000000, ++ 0x3D020230, ++ 0x0400005D, ++ 0x30000000, ++ 0x3E000100, ++ 0x04000066, ++ 0x38028000, ++ 0x0C001601, ++ 0x34204466, ++ 0x38028000, ++ 0x0C000A01, ++ 0x34204466, ++ 0x38008004, ++ 0xFF000000, ++ 0x0800007B, ++ 0x3800802F, ++ 0x26000000, ++ 0x0800006C, ++ 0x380404AF, ++ 0x1F191010, ++ 0x0800006F, ++ 0x20000CAF, ++ 0x04000071, ++ 0x60000CAF, ++ 0x18700079, ++ 0x14000077, ++ 0x10000075, ++ 0x28140CAF, ++ 0x09B00084, ++ 0x280A0CAF, ++ 0x09B00084, ++ 0x28060CAF, ++ 0x09B00084, ++ 0x28048086, ++ 0x0800007D, ++ 0x38000086, ++ 0x22800000, ++ 0x04000080, ++ 0x30000000, ++ 0x0EF1F101, ++ 0x36004883, ++ 0x28020000, ++ 0x08000085, ++ 0x3802008E, ++ 0x3D040431, ++ 0x08000088, ++ 0x3805008E, ++ 0x1F241821, ++ 0x0800008B, ++ 0x3000008E, ++ 0xA0163021, ++ 0x0400008E, ++ 0x3000008E, ++ 0x0EF10012, ++ 0x34000091, ++ 0x300000CC, ++ 0x50000000, ++ 0x04000094, ++ 0x380095FE, ++ 0x32010000, ++ 0x04000097, ++ 0x50001FFE, ++ 0x5A010000, ++ 0x6DC9989B, ++ 0xFC19D4B9, ++ 0x30000186, ++ 0x3D840373, ++ 0x0400009E, ++ 0x3000008E, ++ 0x0A000000, ++ 0x040000A1, ++ 0x3000008E, ++ 0x22C00000, ++ 0x040000A4, ++ 0x9000028E, ++ 0x32010001, ++ 0x8E4000AA, ++ 0xC80000B0, ++ 0x00000000, ++ 0x00000000, ++ 0x3000008E, ++ 0x32010001, ++ 0x040000CB, ++ 0x3000008E, ++ 0x29000000, ++ 0x94045011, ++ 0x300019B6, ++ 0x32010000, ++ 0x040000B3, ++ 0x300019B6, ++ 0x3D040431, ++ 0x040000B6, ++ 0x300019B6, ++ 0x22800000, ++ 0x04000097, ++ 0x30000186, ++ 0x3D840473, ++ 0x040000BC, ++ 0x3000008E, ++ 0x29030000, ++ 0x040000BF, ++ 0x9AEE028E, ++ 0x32010100, ++ 0x7C0000C5, ++ 0xCC0000B0, ++ 0x080000B0, ++ 0x00000000, ++ 0x3000008E, ++ 0x32010100, ++ 0x040000C8, ++ 0x3000028E, ++ 0x29000000, ++ 0x94045011, ++ 0x5000038E, ++ 0x29000000, ++ 0x94045011, ++ 0xC0000035, ++ 0x38010006, ++ 0x3D040472, ++ 0x080000D2, ++ 0x30000004, ++ 0x0EF1F141, ++ 0x340000D5, ++ 0x28040004, ++ 0x080000D7, ++ 0x2808000E, ++ 0x080000D9, ++ 0x3000018E, ++ 0x0EF10052, ++ 0x340000DC, ++ 0x3000038E, ++ 0x29000000, ++ 0x94045011, ++ 0x38020000, ++ 0x32000000, ++ 0x080000E2, ++ 0x60000000, ++ 0xD80000E6, ++ 0xD40000E9, ++ 0x040000EC, ++ 0x30000000, ++ 0x0EF1F121, ++ 0x360048EF, ++ 0x30000000, ++ 0x0C002421, ++ 0x360048EF, ++ 0x30000000, ++ 0x0C000021, ++ 0x360048EF, ++ 0x28020000, ++ 0x0800007B, ++ 0x50001EFE, ++ 0x5A010000, ++ 0x6DC998F5, ++ 0xFC19D4F8, ++ 0x3000028E, ++ 0x32000040, ++ 0x040000FB, ++ 0x3AEE028E, ++ 0x32000080, ++ 0x040000FB, ++ 0x30000000, ++ 0x0EF1F101, ++ 0x360048FE, ++ 0x28020000, ++ 0x08000100, ++ 0x3802008E, ++ 0x3D040431, ++ 0x08000103, ++ 0x3805008E, ++ 0x1F241821, ++ 0x08000106, ++ 0x3000008E, ++ 0xA0163021, ++ 0x04000109, ++ 0x3000008E, ++ 0x0EF10012, ++ 0x3400010C, ++ 0x300014F6, ++ 0x32010000, ++ 0x04000114, ++ 0x20000000, ++ 0x04000111, ++ 0x300000EC, ++ 0x50000000, ++ 0x040000F1, ++ 0x300014F6, ++ 0x32030000, ++ 0x04000117, ++ 0x30001086, ++ 0x3D840473, ++ 0x0400011A, ++ 0x5000108E, ++ 0x22C00000, ++ 0x8E47C0CB, ++ 0xCB30011E, ++ 0x300019B6, ++ 0x32040000, ++ 0x04000121, ++ 0x300019B6, ++ 0x3D040431, ++ 0x04000124, ++ 0x300019B6, ++ 0x22800000, ++ 0x04000111, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x30000186, ++ 0x3D840473, ++ 0x0400012D, ++ 0x5000038E, ++ 0x29000000, ++ 0x94045011, ++ 0xC0000131, ++ 0x380C800E, ++ 0xFF000000, ++ 0x08000134, ++ 0x30000004, ++ 0x0FF1F103, ++ 0x34000137, ++ 0x28020000, ++ 0x08000139, ++ 0x3000038E, ++ 0x29000000, ++ 0x94045011, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x58010006, ++ 0x3D040472, ++ 0xDC204543, ++ 0x081DD4D2, ++ 0x480A0006, ++ 0xDC2044DC, ++ 0x081DD546, ++ 0x38050004, ++ 0x0EF1F141, ++ 0x342044DC, ++ 0x2802800E, ++ 0x080000DC, ++ 0x48000035, ++ 0x0400014A, ++ 0x7896638F, ++ 0x4100000F, ++ 0x8C00014F, ++ 0x080450C4, ++ 0x90104574, ++ 0x88C8620F, ++ 0xC000015A, ++ 0x90104574, ++ 0x08104554, ++ 0x94104557, ++ 0x3000628F, ++ 0x29000000, ++ 0x9404517A, ++ 0x3000638F, ++ 0x29000000, ++ 0x0410457A, ++ 0x3800E005, ++ 0x3D010131, ++ 0x0810455D, ++ 0xA832600F, ++ 0x90104574, ++ 0x08000154, ++ 0x94104557, ++ 0xC6104567, ++ 0xC4185563, ++ 0x5802E00F, ++ 0x0FEEEA07, ++ 0x80000174, ++ 0x3420456B, ++ 0x5802E00F, ++ 0x0EEEEA07, ++ 0x80000174, ++ 0x3420456B, ++ 0x30004000, ++ 0x33000001, ++ 0x0400016E, ++ 0x38034005, ++ 0x3D030373, ++ 0x08000171, ++ 0x30006007, ++ 0x33000000, ++ 0x04000174, ++ 0x3000608F, ++ 0x29000000, ++ 0x94045177, ++ 0x4000608F, ++ 0xA010457D, ++ 0x0410457A, ++ 0x3000608F, ++ 0x64000101, ++ 0x04104411, ++ 0x3000608F, ++ 0x64000101, ++ 0x04104580, ++ 0x3000618F, ++ 0x42000001, ++ 0x04000183, ++ 0x38028000, ++ 0x32000000, ++ 0x08104586, ++ 0x280A618F, ++ 0x08000188, ++ 0x480A618F, ++ 0xBC00018B, ++ 0x0800018E, ++ 0x3000618F, ++ 0x34000001, ++ 0x04000005, ++ 0x3000618F, ++ 0x34000000, ++ 0x04000008, ++ 0x3000008F, ++ 0x0EEAED0F, ++ 0x36000194, ++ 0x38038000, ++ 0x34000000, ++ 0x08000197, ++ 0x38028005, ++ 0x29010002, ++ 0x0800019A, ++ 0x3000028F, ++ 0x2200209C, ++ 0x0400019D, ++ 0x3000028F, ++ 0x23D4509C, ++ 0x040001A0, ++ 0x2814028F, ++ 0x080001A2, ++ 0x3000028F, ++ 0x43010201, ++ 0x040001A5, ++ 0x3000128F, ++ 0x32000100, ++ 0x040001A8, ++ 0x5AEE138F, ++ 0x4100000F, ++ 0x7C0001AC, ++ 0x080000F9, ++ 0x592C138F, ++ 0x29000000, ++ 0x8C0001B0, ++ 0x080000F9, ++ 0x2000138F, ++ 0x94045011, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++#if !defined(CONFIG_EXT_FEM_8800DCDW) ++uint32_t txgain_map[96] = { ++#ifdef CONFIG_FPGA_VERIFICATION ++ 0x20c0c971, ++ 0x20c0c980, ++ 0x20c0c992, ++ 0x20c0c9a6, ++ 0x20c0c9bf, ++ 0x20c0caa5, ++ 0x20c0cabd, ++ 0x20c0cba0, ++ 0x20c0cbb6, ++ 0x20c0cbea, ++ 0x20c0ccc5, ++ 0x20c0cdac, ++ 0x20c0cdd0, ++ 0x20c0ceb2, ++ 0x20c0ceff, ++ 0x20c0cfff, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c927, ++ 0x20c0c92c, ++ 0x20c0c931, ++ 0x20c0c937, ++ 0x20c0c93f, ++ 0x20c0c946, ++ 0x20c0c94f, ++ 0x20c0c959, ++ 0x20c0c964, ++ 0x20c0cbee, ++ 0x20c0cce0, ++ 0x20c0ccff, ++ 0x20c0cde2, ++ 0x20c0cdfe, ++ 0x20c0cede, ++ 0x20c0cefc, ++ 0x20c0cfd9, ++ 0x20c0cff8, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c98c, ++ 0x20c0ca79, ++ 0x20c0ca89, ++ 0x20c0cb74, ++ 0x20c0cb84, ++ 0x20c0cb94, ++ 0x20c0cba8, ++ 0x20c0cbbb, ++ 0x20c0cbd2, ++ 0x20c0cbee, ++ 0x20c0cce0, ++ 0x20c0ccff, ++ 0x20c0cde2, ++ 0x20c0cdfe, ++ 0x20c0cede, ++ 0x20c0cefc, ++ 0x20c0cfd9, ++ 0x20c0cff8, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c98c, ++ 0x20c0ca79, ++ 0x20c0ca89, ++ 0x20c0cb74, ++ 0x20c0cb84, ++ 0x20c0cb94, ++ 0x20c0cba8, ++ 0x20c0cbbb, ++ 0x20c0cbd2, ++#else ++ //11b ++ 0x00ffd780, ++ 0x00ffd872, ++ 0x00ffd880, ++ 0x00ffd972, ++ 0x00ffd980, ++ 0x00ffda75, ++ 0x00ffda86, ++ 0x00ffdb77, ++ 0x00ffdb86, ++ 0x00ffdc78, ++ 0x00ffdc89, ++ 0x00ffdd79, ++ 0x00ffdd89, ++ 0x00ffde83, ++ 0x00ffdf79, ++ 0x00ffdf8b, ++ 0x00ffd072, ++ 0x00ffd072, ++ 0x00ffd080, ++ 0x00ffd172, ++ 0x00ffd180, ++ 0x00ffd272, ++ 0x00ffd280, ++ 0x00ffd36d, ++ 0x00ffd379, ++ 0x00ffd46d, ++ 0x00ffd479, ++ 0x00ffd572, ++ 0x00ffd580, ++ 0x00ffd672, ++ 0x00ffd680, ++ 0x00ffd772, ++ //high ++ 0x00ffc87d, ++ 0x00ffc88b, ++ 0x00ffc979, ++ 0x00ffc989, ++ 0x00ffcc4b, ++ 0x00ffcc54, ++ 0x00ffcc5e, ++ 0x00ffcc69, ++ 0x00ffcc78, ++ 0x00ffcc85, ++ 0x00ffcd70, ++ 0x00ffcd80, ++ 0x00ffce70, ++ 0x00ffce80, ++ 0x00ffcf7d, ++ 0x00ffcf90, ++ 0x00ffc080, ++ 0x00ffc090, ++ 0x00ffc180, ++ 0x00ffc190, ++ 0x00ffc27b, ++ 0x00ffc28b, ++ 0x00ffc37b, ++ 0x00ffc390, ++ 0x00ffc485, ++ 0x00ffc495, ++ 0x00ffc579, ++ 0x00ffc589, ++ 0x00ffc679, ++ 0x00ffc689, ++ 0x00ffc780, ++ 0x00ffc790, ++ //low ++ 0x00ffc87d, ++ 0x00ffc88b, ++ 0x00ffc979, ++ 0x00ffc989, ++ 0x00ffcc4b, ++ 0x00ffcc54, ++ 0x00ffcc5e, ++ 0x00ffcc69, ++ 0x00ffcc78, ++ 0x00ffcc85, ++ 0x00ffcd70, ++ 0x00ffcd80, ++ 0x00ffcd90, ++ 0x00ffcf68, ++ 0x00ffcf75, ++ 0x00ffcf83, ++ 0x00ffc080, ++ 0x00ffc090, ++ 0x00ffc180, ++ 0x00ffc190, ++ 0x00ffc27b, ++ 0x00ffc28b, ++ 0x00ffc37b, ++ 0x00ffc390, ++ 0x00ffc485, ++ 0x00ffc495, ++ 0x00ffc579, ++ 0x00ffc589, ++ 0x00ffc679, ++ 0x00ffc689, ++ 0x00ffc780, ++ 0x00ffc790, ++#endif ++}; ++ ++const uint32_t txgain_map_h[96] = ++{ ++ //11b ++ 0xffd888, //11 ++ 0xffd979, //12 ++ 0xffd988, //13 ++ 0xffda79, //14 ++ 0xffda88, //15 ++ 0xffdb79, //16 ++ 0xffdb88, //17 ++ 0xffdc72, //18 ++ 0xffdc80, //19 ++ 0xffdd80, //20 ++ 0xffde66, //21 ++ 0xffde72, //22 ++ 0xffde80, //23 ++ 0xffdf79, //24 ++ 0xffdf88, //25 ++ 0xffdf98, //26 ++ 0xffd079, //-5 ++ 0xffd088, //-4 ++ 0xffd179, //-3 ++ 0xffd188, //-2 ++ 0xffd288, //-1 ++ 0xffd36c, //0 ++ 0xffd379, //1 ++ 0xffd388, //2 ++ 0xffd479, //3 ++ 0xffd488, //4 ++ 0xffd579, //5 ++ 0xffd588, //6 ++ 0xffd679, //7 ++ 0xffd688, //8 ++ 0xffd779, //9 ++ 0xffd879, //10 ++ //high ++ 0xffc879, //8 ++ 0xffc96b, //9 ++ 0xffc979, //10 ++ 0xffcc45, //11 ++ 0xffcc4d, //12 ++ 0xffcc56, //13 ++ 0xffcc60, //14 ++ 0xffcc6b, //15 ++ 0xffcc79, //16 ++ 0xffcd72, //17 ++ 0xffce60, //18 ++ 0xffce72, //19 ++ 0xffcf72, //20 ++ 0xffcf80, //21 ++ 0xffcf90, //22 ++ 0xffcf90, //23 ++ 0xffc079, //-8 ++ 0xffc16b, //-7 ++ 0xffc179, //-6 ++ 0xffc26b, //-5 ++ 0xffc279, //-4 ++ 0xffc36b, //-3 ++ 0xffc379, //-2 ++ 0xffc46b, //-1 ++ 0xffc479, //0 ++ 0xffc56b, //1 ++ 0xffc579, //2 ++ 0xffc66b, //3 ++ 0xffc679, //4 ++ 0xffc76b, //5 ++ 0xffc779, //6 ++ 0xffc86b, //7 ++ //low ++ 0xffc879, //8 ++ 0xffc96b, //9 ++ 0xffc979, //10 ++ 0xffcc45, //11 ++ 0xffcc4d, //12 ++ 0xffcc56, //13 ++ 0xffcc60, //14 ++ 0xffcc6b, //15 ++ 0xffcc79, //16 ++ 0xffcd72, //17 ++ 0xffcf5b, //18 ++ 0xffcf66, //19 ++ 0xffcf72, //20 ++ 0xffcf80, //21 ++ 0xffcf90, //22 ++ 0xffcf90, //23 ++ 0xffc079, //-8 ++ 0xffc16b, //-7 ++ 0xffc179, //-6 ++ 0xffc26b, //-5 ++ 0xffc279, //-4 ++ 0xffc36b, //-3 ++ 0xffc379, //-2 ++ 0xffc46b, //-1 ++ 0xffc479, //0 ++ 0xffc56b, //1 ++ 0xffc579, //2 ++ 0xffc66b, //3 ++ 0xffc679, //4 ++ 0xffc76b, //5 ++ 0xffc779, //6 ++ 0xffc86b, //7 ++}; ++ ++#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ ++const uint32_t txgain_map_femkct[96] = ++{ ++ //11b ++ 0x00ffd780,//15 ++ 0x00ffd872,//16 ++ 0x00ffd880,//17 ++ 0x00ffd972,//18 ++ 0x00ffd980,//19 ++ 0x00ffda72,//20 ++ 0x00ffda80,//21 ++ 0x00ffdb72,//22 ++ 0x00ffdb80,//23 ++ 0x00ffdc72,//24 ++ 0x00ffdc80,//25 ++ 0x00ffdd72,//26 ++ 0x00ffdd80,//27 ++ 0x00ffde72,//28 ++ 0x00ffde80,//29 ++ 0x00ffdf72,//30 ++ 0x00ffd072,//-1 ++ 0x00ffd072,//0 ++ 0x00ffd080,//1 ++ 0x00ffd172,//2 ++ 0x00ffd180,//3 ++ 0x00ffd272,//4 ++ 0x00ffd280,//5 ++ 0x00ffd36d,//6 ++ 0x00ffd379,//7 ++ 0x00ffd46d,//8 ++ 0x00ffd479,//9 ++ 0x00ffd572,//10 ++ 0x00ffd580,//11 ++ 0x00ffd672,//12 ++ 0x00ffd680,//13 ++ 0x00ffd772,//14 ++ //high ++ 0x00ffc872,//11 ++ 0x00ffc880,//12 ++ 0x00ffc972,//13 ++ 0x00ffc980,//14 ++ 0x00ffca72,//15 ++ 0x00ffca80,//16 ++ 0x00ffcb72,//17 ++ 0x00ffcb80,//18 ++ 0x00ffcc72,//19 ++ 0x00ffcc80,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//25 ++ 0x00ffcf80,//26 ++ 0x00ffc072,//-5 ++ 0x00ffc080,//-4 ++ 0x00ffc172,//-3 ++ 0x00ffc180,//-2 ++ 0x00ffc272,//-1 ++ 0x00ffc280,//0 ++ 0x00ffc372,//1 ++ 0x00ffc380,//2 ++ 0x00ffc472,//3 ++ 0x00ffc480,//4 ++ 0x00ffc572,//5 ++ 0x00ffc580,//6 ++ 0x00ffc672,//7 ++ 0x00ffc680,//8 ++ 0x00ffc772,//9 ++ 0x00ffc780,//10 ++ //low ++ 0x00ffc872,//11 ++ 0x00ffc880,//12 ++ 0x00ffc972,//13 ++ 0x00ffc980,//14 ++ 0x00ffca72,//15 ++ 0x00ffca80,//16 ++ 0x00ffcb72,//17 ++ 0x00ffcb80,//18 ++ 0x00ffcc72,//19 ++ 0x00ffcc80,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//26 ++ 0x00ffcf80,//27 ++ 0x00ffc072,//-5 ++ 0x00ffc080,//-4 ++ 0x00ffc172,//-3 ++ 0x00ffc180,//-2 ++ 0x00ffc272,//-1 ++ 0x00ffc280,//0 ++ 0x00ffc372,//1 ++ 0x00ffc380,//2 ++ 0x00ffc472,//3 ++ 0x00ffc480,//4 ++ 0x00ffc572,//5 ++ 0x00ffc580,//6 ++ 0x00ffc672,//7 ++ 0x00ffc680,//8 ++ 0x00ffc772,//9 ++ 0x00ffc780,//10 ++}; ++ ++const uint32_t txgain_map_femkct_h[96] = ++{ ++ //11b ++ 0x00ffd872,//15 ++ 0x00ffd880,//16 ++ 0x00ffd972,//17 ++ 0x00ffd980,//18 ++ 0x00ffd990,//19 ++ 0x00ffda72,//20 ++ 0x00ffda80,//21 ++ 0x00ffdb72,//22 ++ 0x00ffdb80,//23 ++ 0x00ffdc72,//24 ++ 0x00ffdc80,//25 ++ 0x00ffdd72,//26 ++ 0x00ffdd80,//27 ++ 0x00ffde72,//28 ++ 0x00ffde80,//29 ++ 0x00ffdf72,//30 ++ 0x00ffd072,//-1 ++ 0x00ffd072,//0 ++ 0x00ffd080,//1 ++ 0x00ffd172,//2 ++ 0x00ffd180,//3 ++ 0x00ffd272,//4 ++ 0x00ffd280,//5 ++ 0x00ffd379,//6 ++ 0x00ffd46d,//7 ++ 0x00ffd479,//8 ++ 0x00ffd572,//9 ++ 0x00ffd580,//10 ++ 0x00ffd672,//11 ++ 0x00ffd680,//12 ++ 0x00ffd772,//13 ++ 0x00ffd780,//14 ++ //high ++ 0x00ffc880,//11 ++ 0x00ffc972,//12 ++ 0x00ffc980,//13 ++ 0x00ffca72,//14 ++ 0x00ffca80,//15 ++ 0x00ffcb72,//16 ++ 0x00ffcb80,//17 ++ 0x00ffcc72,//18 ++ 0x00ffcc80,//19 ++ 0x00ffcc90,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//25 ++ 0x00ffcf80,//26 ++ 0x00ffc080,//-5 ++ 0x00ffc172,//-4 ++ 0x00ffc180,//-3 ++ 0x00ffc272,//-2 ++ 0x00ffc280,//-1 ++ 0x00ffc372,//0 ++ 0x00ffc380,//1 ++ 0x00ffc472,//2 ++ 0x00ffc480,//3 ++ 0x00ffc572,//4 ++ 0x00ffc580,//5 ++ 0x00ffc672,//6 ++ 0x00ffc680,//7 ++ 0x00ffc772,//8 ++ 0x00ffc780,//9 ++ 0x00ffc872,//10 ++ //low ++ 0x00ffc880,//11 ++ 0x00ffc972,//12 ++ 0x00ffc980,//13 ++ 0x00ffca72,//14 ++ 0x00ffca80,//15 ++ 0x00ffcb72,//16 ++ 0x00ffcb80,//17 ++ 0x00ffcc72,//18 ++ 0x00ffcc80,//19 ++ 0x00ffcc90,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//25 ++ 0x00ffcf80,//26 ++ 0x00ffc080,//-5 ++ 0x00ffc172,//-4 ++ 0x00ffc180,//-3 ++ 0x00ffc272,//-2 ++ 0x00ffc280,//-1 ++ 0x00ffc372,//0 ++ 0x00ffc380,//1 ++ 0x00ffc472,//2 ++ 0x00ffc480,//3 ++ 0x00ffc572,//4 ++ 0x00ffc580,//5 ++ 0x00ffc672,//6 ++ 0x00ffc680,//7 ++ 0x00ffc772,//8 ++ 0x00ffc780,//9 ++ 0x00ffc872,//10 ++}; ++#endif ++ ++u32 jump_tbl[][2] = ++{ ++#ifndef CONFIG_FOR_IPCOM ++ {296, 0x180001}, ++ {137, 0x180011}, ++ {303, 0x1810f9}, ++ {168, 0x18186d}, ++ {308, 0x181bbd}, ++ {288, 0x1820c1}, ++#else ++ {308, 0x181001}, ++ {288, 0x181031}, ++ {296, 0x18120d}, ++ {137, 0x18121d}, ++ {303, 0x182305}, ++ {168, 0x182a79}, ++ {258, 0x182ae1}, ++#endif ++}; ++ ++u32 jump_tbl_u02[][2] = ++{ ++ {303, 0x00180d25}, ++ {168, 0x001814a5}, ++ {265, 0x001816b1}, ++ {266, 0x00181849}, ++ {256, 0x001818ad}, ++ {288, 0x00181bf9}, ++ {333, 0x00182d0d}, ++ { 26, 0x00182d45} ++}; ++ ++ ++u32 patch_tbl_func[][2] = ++{ ++#ifndef CONFIG_FOR_IPCOM ++ {0x00110054, 0x0018186D}, // same as jump_tbl idx 168 ++ {0x0011005C, 0x0018186D}, // same as jump_tbl idx 168 ++#else ++ {0x00110054, 0x00182A79}, // same as jump_tbl idx 168 ++ {0x0011005C, 0x00182A79}, // same as jump_tbl idx 168 ++ {0x001118D4, 0x00000011}, ++#endif ++}; ++ ++u32 patch_tbl_func_u02[][2] = ++{ ++ {0x00110054, 0x001814a5}, // same as jump_tbl idx 168 ++ {0x0011005C, 0x001814a5}, // same as jump_tbl idx 168 ++ {0x001109c0, 0x00181e3d}, ++ {0x00110bb4, 0x001824e1}, ++ {0x00110f08, 0x00182d25}, ++}; ++ ++ ++u32 patch_tbl_rf_func[][2] = ++{ ++ {0x00110bf0, 0x00180001}, ++}; ++ ++ ++//adap test ++u32 adaptivity_patch_tbl_8800dc[][2] = { ++ {0x000C, 0x0000320A}, //linkloss_thd ++ {0x009C, 0x00000000}, //ac_param_conf ++ {0x0128, 0xF6140001}, //tx_adaptivity_en ++}; ++//adap test ++ ++ ++static u8 chip_id = 0; ++#define CHIP_ID_H_MASK 0xC0 ++#define IS_CHIP_ID_H() ((chip_id & CHIP_ID_H_MASK) == CHIP_ID_H_MASK) ++ ++//Crystal provided by CPU (start) ++int set_bbpll_config(struct aic_sdio_dev *rwnx_hw){ ++// {0x40505010, 0x7C301010},//bbpll ++ int ret = 0; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ ++ //Read crystal provided by CPU or not. ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40500148, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x rd fail: %d\n", 0x40500148, ret); ++ return -1; ++ } ++ ++ AICWFDBG(LOGDEBUG, "%s rd_mem_addr_cfm.memdata:%x \r\n", __func__, rd_mem_addr_cfm.memdata); ++ ++ if(!(rd_mem_addr_cfm.memdata & 0x01)){ ++ AICWFDBG(LOGINFO, "%s Crystal not provided by CPU \r\n", __func__); ++ return 0; ++ }else{ ++ AICWFDBG(LOGINFO, "%s Crystal provided by CPU \r\n", __func__); ++ //Read 0x40505010 value to check bbpll set or not. ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40505010, &rd_mem_addr_cfm); ++ if(ret < 0){ ++ AICWFDBG(LOGERROR, "%s error ret_val:%d\r\n", __func__, ret); ++ return -1; ++ } ++ ++ if((rd_mem_addr_cfm.memdata >> 29) == 3){ ++ AICWFDBG(LOGERROR, "%s Not need to set \r\n", __func__); ++ return 0; ++ }else{ ++ rd_mem_addr_cfm.memdata |= ((0x1 << 29) | (0x1 << 30)); ++ rd_mem_addr_cfm.memdata &= (~(0x1 << 31)); ++ rwnx_send_dbg_mem_write_req(rwnx_hw, 0x40505010, rd_mem_addr_cfm.memdata); ++ } ++ } ++ return 0; ++} ++//Crystal provided by CPU (end) ++ ++ ++void system_config_8800dc(struct aic_sdio_dev *rwnx_hw) ++{ ++ int syscfg_num; ++ array3_tbl_t p_syscfg_msk_tbl; ++ int ret, cnt; ++ const u32 mem_addr = 0x40500000; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++#ifdef CONFIG_OOB ++ int oobcfg_num; ++#endif ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x rd fail: %d\n", mem_addr, ret); ++ return; ++ } ++ chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16); ++ //printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ if (((rd_mem_addr_cfm.memdata >> 25) & 0x01UL) == 0x00UL) { ++ chip_mcu_id = 1; ++ } ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x00000020, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x00000020] rd fail: %d\n", ret); ++ return; ++ } ++ chip_sub_id = (u8)(rd_mem_addr_cfm.memdata); ++ //printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ AICWFDBG(LOGINFO, "chip_id=%x, chip_sub_id=%x!!\n", chip_id, chip_sub_id); ++ ++ //Crystal provided by CPU (start) ++ ret = set_bbpll_config(rwnx_hw); ++ if (ret) { ++ AICWFDBG(LOGERROR, "set_bbpll_config fail: %d\n", ret); ++ return; ++ } ++ //Crystal provided by CPU (end) ++ ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40500010, &rd_mem_addr_cfm); ++ AICWFDBG(LOGDEBUG, "[0x40500010]=%x\n", rd_mem_addr_cfm.memdata); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x40500010] rd fail: %d\n", ret); ++ return; ++ } ++ ++ syscfg_num = sizeof(syscfg_tbl_8800dc) / sizeof(uint32_t) / 2; ++ ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc[cnt][0], syscfg_tbl_8800dc[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", syscfg_tbl_8800dc[cnt][0], ret); ++ return; ++ } ++ } ++ ++ if (chip_mcu_id == 0) { ++ if (chip_sub_id == 0) { ++ syscfg_num = sizeof(syscfg_tbl_8800dc_sdio_u01) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc_sdio_u01[cnt][0], syscfg_tbl_8800dc_sdio_u01[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", syscfg_tbl_8800dc_sdio_u01[cnt][0], ret); ++ return; ++ } ++ } ++ } else if ((chip_sub_id == 1) || (chip_sub_id == 2)) { ++ syscfg_num = sizeof(syscfg_tbl_8800dc_sdio_u02) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc_sdio_u02[cnt][0], syscfg_tbl_8800dc_sdio_u02[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", syscfg_tbl_8800dc_sdio_u02[cnt][0], ret); ++ return; ++ } ++ } ++ } ++ } ++#ifdef CONFIG_OOB ++ if ((chip_sub_id == 1) || (chip_sub_id == 2)) { ++ oobcfg_num = sizeof(oobcfg_tbl_8800dc_sdio_u02) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < oobcfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, oobcfg_tbl_8800dc_sdio_u02[cnt][0], oobcfg_tbl_8800dc_sdio_u02[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", oobcfg_tbl_8800dc_sdio_u02[cnt][0], ret); ++ return; ++ } ++ } ++ } ++#endif ++ if (IS_CHIP_ID_H()) { ++ syscfg_num = sizeof(syscfg_tbl_masked_8800dc_h) / sizeof(u32) / 3; ++ p_syscfg_msk_tbl = syscfg_tbl_masked_8800dc_h; ++ } else { ++ syscfg_num = sizeof(syscfg_tbl_masked_8800dc) / sizeof(u32) / 3; ++ p_syscfg_msk_tbl = syscfg_tbl_masked_8800dc; ++ } ++ ++ ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ if (p_syscfg_msk_tbl[cnt][0] == 0x00000000) { ++ break; ++ } else if (p_syscfg_msk_tbl[cnt][0] == 0x70001000) { ++ if (chip_mcu_id == 0) { ++ p_syscfg_msk_tbl[cnt][1] |= ((0x1 << 8) | (0x1 << 15)); // mask ++ p_syscfg_msk_tbl[cnt][2] |= ((0x1 << 8) | (0x1 << 15)); ++ } ++ } ++ ++ ret = rwnx_send_dbg_mem_mask_write_req(rwnx_hw, ++ p_syscfg_msk_tbl[cnt][0], p_syscfg_msk_tbl[cnt][1], p_syscfg_msk_tbl[cnt][2]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x mask write fail: %d\n", p_syscfg_msk_tbl[cnt][0], ret); ++ return; ++ } ++ } ++ ++ if (chip_sub_id == 0) { ++ syscfg_num = sizeof(syscfg_tbl_masked_8800dc_u01) / sizeof(u32) / 3; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_mask_write_req(rwnx_hw, ++ syscfg_tbl_masked_8800dc_u01[cnt][0], syscfg_tbl_masked_8800dc_u01[cnt][1], syscfg_tbl_masked_8800dc_u01[cnt][2]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x mask write fail: %d\n", syscfg_tbl_masked_8800dc_u01[cnt][0], ret); ++ return; ++ } ++ } ++ } ++ ++} ++ ++extern int adap_test; ++ ++void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw) ++{ ++ int ret = 0; ++ int cnt = 0; ++ if (testmode == 0) { ++ const u32 cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ int i; ++ u32 wifisetting_cfg_addr; ++ u32 ldpc_cfg_addr; ++ u32 agc_cfg_addr; ++ u32 txgain_cfg_addr; ++ u32 jump_tbl_addr = 0; ++ ++ u32 patch_tbl_wifisetting_num;// = sizeof(patch_tbl_wifisetting_8800dc_u02)/sizeof(u32)/2; ++ u32 ldpc_cfg_size = sizeof(ldpc_cfg_ram); ++ u32 agc_cfg_size = sizeof(agc_cfg_ram); ++ u32 txgain_cfg_size, *txgain_cfg_array; ++ u32 jump_tbl_size = 0; ++ u32 patch_tbl_func_num = 0; ++ ++ //adap test ++ int adap_patch_num = 0; ++ //adap test ++ ++ ++ array2_tbl_t jump_tbl_base = NULL; ++ array2_tbl_t patch_tbl_func_base = NULL; ++ array2_tbl_t patch_tbl_wifisetting_8800dc_base = NULL; ++ ++ if (chip_sub_id == 0) { ++ jump_tbl_base = jump_tbl; ++ jump_tbl_size = sizeof(jump_tbl)/2; ++ patch_tbl_func_base = patch_tbl_func; ++ patch_tbl_func_num = sizeof(patch_tbl_func)/sizeof(u32)/2; ++ patch_tbl_wifisetting_num = sizeof(patch_tbl_wifisetting_8800dc_u01)/sizeof(u32)/2; ++ patch_tbl_wifisetting_8800dc_base = patch_tbl_wifisetting_8800dc_u01; ++ } else if ((chip_sub_id == 1) || (chip_sub_id == 2)) { ++ patch_tbl_wifisetting_num = sizeof(patch_tbl_wifisetting_8800dc_u02)/sizeof(u32)/2; ++ patch_tbl_wifisetting_8800dc_base = patch_tbl_wifisetting_8800dc_u02; ++ } else { ++ printk("unsupported id: %d", chip_sub_id); ++ return; ++ } ++ ++ //struct dbg_mem_read_cfm cfm; ++ //int i; ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base, ret); ++ } ++ wifisetting_cfg_addr = cfm.memdata; ++ ++ if(chip_sub_id == 0){ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 4, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 4, ret); ++ } ++ jump_tbl_addr = cfm.memdata; ++ } ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 8, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 8, ret); ++ } ++ ldpc_cfg_addr = cfm.memdata; ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0xc, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 0xc, ret); ++ } ++ agc_cfg_addr = cfm.memdata; ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x10, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 0x10, ret); ++ } ++ txgain_cfg_addr = cfm.memdata; ++ ++ AICWFDBG(LOGINFO, "wifisetting_cfg_addr=%x, ldpc_cfg_addr=%x, agc_cfg_addr=%x, txgain_cfg_addr=%x\n", wifisetting_cfg_addr, ldpc_cfg_addr, agc_cfg_addr, txgain_cfg_addr); ++ ++ for (cnt = 0; cnt < patch_tbl_wifisetting_num; cnt++) { ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, wifisetting_cfg_addr + patch_tbl_wifisetting_8800dc_base[cnt][0], patch_tbl_wifisetting_8800dc_base[cnt][1]))) { ++ AICWFDBG(LOGERROR, "wifisetting %x write fail\n", patch_tbl_wifisetting_8800dc_base[cnt][0]); ++ } ++ } ++ ++//adap test ++ if(adap_test){ ++ AICWFDBG(LOGINFO, "%s for adaptivity test \r\n", __func__); ++ adap_patch_num = sizeof(adaptivity_patch_tbl_8800dc)/sizeof(u32)/2; ++ for(cnt = 0; cnt < adap_patch_num; cnt++) ++ { ++ if((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, wifisetting_cfg_addr + adaptivity_patch_tbl_8800dc[cnt][0], adaptivity_patch_tbl_8800dc[cnt][1]))) { ++ AICWFDBG(LOGERROR, "%x write fail\n", wifisetting_cfg_addr + adaptivity_patch_tbl_8800dc[cnt][0]); ++ } ++ } ++ } ++//adap test ++ ++ if (ldpc_cfg_size > 512) {// > 0.5KB data ++ for (i = 0; i < (ldpc_cfg_size - 512); i += 512) {//each time write 0.5KB ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ldpc_cfg_addr + i, 512, ldpc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "ldpc upload fail: %x, err:%d\r\n", ldpc_cfg_addr + i, ret); ++ break; ++ } ++ } ++ } ++ ++ if (!ret && (i < ldpc_cfg_size)) {// < 0.5KB data ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ldpc_cfg_addr + i, ldpc_cfg_size - i, ldpc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "ldpc upload fail: %x, err:%d\r\n", ldpc_cfg_addr + i, ret); ++ } ++ } ++ ++ if (agc_cfg_size > 512) {// > 0.5KB data ++ for (i = 0; i < (agc_cfg_size - 512); i += 512) {//each time write 0.5KB ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, agc_cfg_addr + i, 512, agc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "agc upload fail: %x, err:%d\r\n", agc_cfg_addr + i, ret); ++ break; ++ } ++ } ++ } ++ ++ if (!ret && (i < agc_cfg_size)) {// < 0.5KB data ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, agc_cfg_addr + i, agc_cfg_size - i, agc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "agc upload fail: %x, err:%d\r\n", agc_cfg_addr + i, ret); ++ } ++ } ++ ++ #if !defined(CONFIG_FPGA_VERIFICATION) ++ if ((IS_CHIP_ID_H())) { ++ #if defined(CONFIG_EXT_FEM_8800DCDW) ++ txgain_cfg_size = sizeof(txgain_map_femkct_h); ++ txgain_cfg_array = (u32 *)txgain_map_femkct_h; ++ #else ++ txgain_cfg_size = sizeof(txgain_map_h); ++ txgain_cfg_array = (u32 *)txgain_map_h; ++ #endif ++ } else { ++ #if defined(CONFIG_EXT_FEM_8800DCDW) ++ txgain_cfg_size = sizeof(txgain_map_femkct); ++ txgain_cfg_array = (u32 *)txgain_map_femkct; ++ #else ++ txgain_cfg_size = sizeof(txgain_map); ++ txgain_cfg_array = (u32 *)txgain_map; ++ #endif ++ } ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, txgain_cfg_addr, txgain_cfg_size, txgain_cfg_array); ++ if (ret) { ++ AICWFDBG(LOGERROR, "txgain upload fail: %x, err:%d\r\n", txgain_cfg_addr, ret); ++ } ++ ++ if (chip_sub_id == 0) { ++ for (cnt = 0; cnt < jump_tbl_size/4; cnt+=1) { ++ AICWFDBG(LOGDEBUG, "%x = %x\n", jump_tbl_base[cnt][0]*4+jump_tbl_addr, jump_tbl_base[cnt][1]); ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, jump_tbl_base[cnt][0]*4+jump_tbl_addr, jump_tbl_base[cnt][1]))) { ++ AICWFDBG(LOGERROR, "%x write fail\n", jump_tbl_addr+8*cnt); ++ } ++ } ++ for (cnt = 0; cnt < patch_tbl_func_num; cnt++) { ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, patch_tbl_func_base[cnt][0], patch_tbl_func_base[cnt][1]))) { ++ AICWFDBG(LOGERROR, "patch_tbl_func %x write fail\n", patch_tbl_func_base[cnt][0]); ++ } ++ } ++ } else if (chip_sub_id == 1) { ++ ret = aicwf_patch_table_load(rwnx_hw, RWNX_MAC_PATCH_TABLE_8800DC_U02); ++ if(ret){ ++ printk("patch_tbl upload fail: err:%d\r\n", ret); ++ } ++ } else if (chip_sub_id == 2) { ++ ret = aicwf_patch_table_load(rwnx_hw, RWNX_MAC_PATCH_TABLE_8800DC_H_U02); ++ if(ret){ ++ printk("patch_tbl upload fail: err:%d\r\n", ret); ++ } ++ } else { ++ printk("unsupported id: %d\n", chip_sub_id); ++ } ++ ++ #endif ++ } else { ++ if (chip_sub_id == 0) { ++ u32 patch_tbl_rf_func_num = sizeof(patch_tbl_rf_func)/sizeof(u32)/2; ++ for (cnt = 0; cnt < patch_tbl_rf_func_num; cnt++) { ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, patch_tbl_rf_func[cnt][0], patch_tbl_rf_func[cnt][1]))) { ++ AICWFDBG(LOGERROR, "patch_tbl_rf_func %x write fail\n", patch_tbl_rf_func[cnt][0]); ++ } ++ } ++ } ++ } ++} ++ ++int aicwf_misc_ram_init_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t misc_ram_size = 12; ++ int i; ++ ++ if (testmode == FW_RFTEST_MODE) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ // init misc ram ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr); ++ for (i = 0; i < (misc_ram_size / 4); i++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, misc_ram_addr + i * 4, 0); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] wr fail: %d\n", misc_ram_addr + i * 4, ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++ ++#ifdef CONFIG_DPD ++int aicwf_dpd_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ uint32_t fw_addr, boot_type; ++ int valid_flag; ++ ++ printk("%s\n", __func__); ++ ++ ret = aicwf_misc_ram_valid_check_8800dc(sdiodev, &valid_flag); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram check fail: %d\n", ret); ++ return ret; ++ } ++ if (valid_flag) { ++ AICWFDBG(LOGINFO, "misc ram valid, skip calib process\n"); ++ return ret; ++ } ++ ret = aicwf_plat_calib_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ /* fw start */ ++ fw_addr = 0x00130009; ++ boot_type = HOST_START_APP_FNCALL; ++ AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); ++ ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type, NULL); ++ if (ret) { ++ AICWFDBG(LOGINFO, "start app fail: %d\n", ret); ++ return ret; ++ } ++ { // read dpd res ++ const uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_word_cnt; ++ int i; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ // bit_mask ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ dpd_res->bit_mask[i] = cfm.memdata; ++ } ++ // dpd_high ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, dpd_high); ++ ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, dpd_high) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ dpd_res->dpd_high[i] = cfm.memdata; ++ } ++ // loft_res ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ dpd_res->loft_res[i] = cfm.memdata; ++ } ++ } ++ return ret; ++} ++ ++int aicwf_dpd_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", dpd_res->bit_mask[1]); ++ if (dpd_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void dpd_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == FW_RFTEST_MODE) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy dpd_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", dpd_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // dpd_high ++ AICWFDBG(LOGINFO, "dpd_high[0]=%x\n", dpd_res->dpd_high[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, dpd_high); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, dpd_high); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->dpd_high[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "dpd_high wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", dpd_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++ ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_DPDRESULT_NAME_8800DC; ++ struct device *dev = sdiodev->dev; ++ AICWFDBG(LOGINFO, "%s: dpd_res file path:%s \r\n", __func__, filename); ++ /* load file */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of dpd_res file\n"); ++ if (dst) { ++ #ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++ #endif ++ dst = NULL; ++ } ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d, dst[0]=%x\n", filename, size, dst[0]); ++ memcpy((u8 *)dpd_res, (u8 *)dst, sizeof(rf_misc_ram_lite_t)); ++ if (dst) { ++ #ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++ #endif ++ dst = NULL; ++ } ++ return ret; ++} ++ ++int aicwf_dpd_result_write_8800dc(void *buf, int buf_len) ++{ ++ int sum = 0, len = 0; ++ char *path = NULL; ++ struct file *fp = NULL; ++ loff_t pos = 0; ++ mm_segment_t fs; ++ ++ AICWFDBG(LOGINFO, "%s\n", __func__); ++ ++ path = __getname(); ++ if (!path) { ++ AICWFDBG(LOGINFO, "get path fail\n"); ++ return -1; ++ } ++ ++ len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", AICBSP_FW_PATH, FW_DPDRESULT_NAME_8800DC); ++ printk("%s\n", path); ++ ++ fp = filp_open(path, O_RDWR | O_CREAT, 0644); ++ if (IS_ERR(fp)) { ++ AICWFDBG(LOGINFO, "fp open fial\n"); ++ __putname(path); ++ fp = NULL; ++ return -1; ++ } ++ ++ fs = get_fs(); ++ set_fs(KERNEL_DS); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ sum = kernel_write(fp, buf, buf_len, &pos); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) ++ sum = kernel_write(fp, (char *)buf, buf_len, pos); ++#else ++ sum = vfs_write(fp, (char *)buf, buf_len, &pos); ++#endif ++ ++ set_fs(fs); ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ ++ return 0; ++} ++#endif /* !CONFIG_FORCE_DPD_CALIB */ ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++int aicwf_loft_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res) ++{ ++ int ret = 0; ++ uint32_t fw_addr, boot_type; ++ int valid_flag; ++ ++ printk("%s\n", __func__); ++ ++ ret = aicwf_misc_ram_valid_check_8800dc(sdiodev, &valid_flag); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram check fail: %d\n", ret); ++ return ret; ++ } ++ if (valid_flag) { ++ AICWFDBG(LOGINFO, "misc ram valid, skip calib process\n"); ++ return ret; ++ } ++ ret = aicwf_plat_calib_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ /* fw start */ ++ fw_addr = 0x00130009; ++ boot_type = HOST_START_APP_FNCALL; ++ AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); ++ ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type, NULL); ++ if (ret) { ++ AICWFDBG(LOGINFO, "start app fail: %d\n", ret); ++ return ret; ++ } ++ { // read loft res ++ const uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_word_cnt; ++ int i; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ // bit_mask ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ loft_res->bit_mask[i] = cfm.memdata; ++ } ++ // loft_res ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ loft_res->loft_res[i] = cfm.memdata; ++ } ++ } ++ return ret; ++} ++ ++int aicwf_loft_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", loft_res->bit_mask[1]); ++ if (loft_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void loft_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == FW_RFTEST_MODE) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy loft_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", loft_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", loft_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h +new file mode 100644 +index 000000000000..23b8185761eb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h +@@ -0,0 +1,41 @@ ++#ifndef _AIC8800DC_COMPAT_H_ ++#define _AIC8800DC_COMPAT_H_ ++ ++#include "aicsdio.h" ++typedef u32 (*array2_tbl_t)[2]; ++typedef u32 (*array3_tbl_t)[3]; ++ ++typedef uint8_t u8_l; ++typedef int8_t s8_l; ++typedef bool bool_l; ++typedef uint16_t u16_l; ++typedef int16_t s16_l; ++typedef uint32_t u32_l; ++typedef int32_t s32_l; ++typedef uint64_t u64_l; ++ ++extern u8 chip_sub_id; ++extern u8 chip_mcu_id; ++#define FW_PATH_MAX_LEN 200 ++ ++void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw); ++void system_config_8800dc(struct aic_sdio_dev *rwnx_hw); ++int aicwf_misc_ram_init_8800dc(struct aic_sdio_dev *sdiodev); ++ ++#ifdef CONFIG_DPD ++int aicwf_dpd_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res); ++int aicwf_dpd_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res); ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res); ++int aicwf_dpd_result_write_8800dc(void *buf, int buf_len); ++#endif/* !CONFIG_FORCE_DPD_CALIB */ ++#endif ++#ifdef CONFIG_LOFT_CALIB ++int aicwf_loft_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res); ++int aicwf_loft_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res); ++#endif ++ ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c +new file mode 100644 +index 000000000000..658979c535a2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c +@@ -0,0 +1,2214 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.c ++ * ++ * Handles queueing (push to IPC, ack/cfm from IPC) of commands issued to ++ * LMAC FW ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) ++#include ++#endif ++#include ++#include "aicsdio_txrxif.h" ++#include "aicsdio.h" ++#include "aic_bsp_driver.h" ++#include "md5.h" ++#include "aic8800dc_compat.h" ++#include "aic8800d80_compat.h" ++#include "aicwf_firmware_array.h" ++#define FW_PATH_MAX 200 ++ ++extern int adap_test; ++extern char aic_fw_path[FW_PATH_MAX]; ++extern struct aic_sdio_dev *aicbsp_sdiodev; ++ ++static void cmd_dump(const struct rwnx_cmd *cmd) ++{ ++ printk(KERN_CRIT "tkn[%d] flags:%04x result:%3d cmd:%4d - reqcfm(%4d)\n", ++ cmd->tkn, cmd->flags, cmd->result, cmd->id, cmd->reqid); ++} ++ ++static void cmd_complete(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ //printk("cmdcmp\n"); ++ lockdep_assert_held(&cmd_mgr->lock); ++ ++ list_del(&cmd->list); ++ cmd_mgr->queue_sz--; ++ ++ cmd->flags |= RWNX_CMD_FLAG_DONE; ++ if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) { ++ kfree(cmd); ++ } else { ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) { ++ cmd->result = 0; ++ complete(&cmd->complete); ++ } ++ } ++} ++ ++static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ bool defer_push = false; ++ int err = 0; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ ++ if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { ++ printk(KERN_CRIT"cmd queue crashed\n"); ++ cmd->result = -EPIPE; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EPIPE; ++ } ++ ++ if (!list_empty(&cmd_mgr->cmds)) { ++ struct rwnx_cmd *last; ++ ++ if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) { ++ printk(KERN_CRIT"Too many cmds (%d) already queued\n", ++ cmd_mgr->max_queue_sz); ++ cmd->result = -ENOMEM; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -ENOMEM; ++ } ++ last = list_entry(cmd_mgr->cmds.prev, struct rwnx_cmd, list); ++ if (last->flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_PUSH)) { ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ defer_push = true; ++ } ++ } ++ ++ if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM) ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM; ++ ++ cmd->tkn = cmd_mgr->next_tkn++; ++ cmd->result = -EINTR; ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ init_completion(&cmd->complete); ++ ++ list_add_tail(&cmd->list, &cmd_mgr->cmds); ++ cmd_mgr->queue_sz++; ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ if (!defer_push) { ++ //printk("queue:id=%x, param_len=%u\n", cmd->a2e_msg->id, cmd->a2e_msg->param_len); ++ rwnx_set_cmd_tx((void *)(cmd_mgr->sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ //rwnx_ipc_msg_push(rwnx_hw, cmd, RWNX_CMD_A2EMSG_LEN(cmd->a2e_msg)); ++ kfree(cmd->a2e_msg); ++ } else { ++ //WAKE_CMD_WORK(cmd_mgr); ++ printk("ERR: never defer push!!!!"); ++ return 0; ++ } ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) { ++ unsigned long tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz); ++ if (!wait_for_completion_killable_timeout(&cmd->complete, tout)) { ++ printk(KERN_CRIT"cmd timed-out\n"); ++ cmd_dump(cmd); ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED; ++ if (!(cmd->flags & RWNX_CMD_FLAG_DONE)) { ++ cmd->result = -ETIMEDOUT; ++ cmd_complete(cmd_mgr, cmd); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ err = -ETIMEDOUT; ++ } else { ++ kfree(cmd); ++ } ++ } else { ++ cmd->result = 0; ++ } ++ ++ return err; ++} ++ ++static int cmd_mgr_run_callback(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd, ++ struct rwnx_cmd_e2amsg *msg, msg_cb_fct cb) ++{ ++ int res; ++ ++ if (!cb) { ++ return 0; ++ } ++ spin_lock(&cmd_mgr->cb_lock); ++ res = cb(cmd, msg); ++ spin_unlock(&cmd_mgr->cb_lock); ++ ++ return res; ++} ++ ++static int cmd_mgr_msgind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd_e2amsg *msg, ++ msg_cb_fct cb) ++{ ++ struct rwnx_cmd *cmd; ++ bool found = false; ++ ++ //printk("cmd->id=%x\n", msg->id); ++ spin_lock(&cmd_mgr->lock); ++ list_for_each_entry(cmd, &cmd_mgr->cmds, list) { ++ if (cmd->reqid == msg->id && ++ (cmd->flags & RWNX_CMD_FLAG_WAIT_CFM)) { ++ ++ if (!cmd_mgr_run_callback(cmd_mgr, cmd, msg, cb)) { ++ found = true; ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_CFM; ++ ++ if (WARN((msg->param_len > RWNX_CMD_E2AMSG_LEN_MAX), ++ "Unexpect E2A msg len %d > %d\n", msg->param_len, ++ RWNX_CMD_E2AMSG_LEN_MAX)) { ++ msg->param_len = RWNX_CMD_E2AMSG_LEN_MAX; ++ } ++ ++ if (cmd->e2a_msg && msg->param_len) ++ memcpy(cmd->e2a_msg, &msg->param, msg->param_len); ++ ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) ++ cmd_complete(cmd_mgr, cmd); ++ ++ break; ++ } ++ } ++ } ++ spin_unlock(&cmd_mgr->lock); ++ ++ if (!found) ++ cmd_mgr_run_callback(cmd_mgr, NULL, msg, cb); ++ ++ return 0; ++} ++ ++static void cmd_mgr_print(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ cmd_dump(cur); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++static void cmd_mgr_drain(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur, *nxt; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry_safe(cur, nxt, &cmd_mgr->cmds, list) { ++ list_del(&cur->list); ++ cmd_mgr->queue_sz--; ++ if (!(cur->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ complete(&cur->complete); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ cmd_mgr->max_queue_sz = RWNX_CMD_MAX_QUEUED; ++ INIT_LIST_HEAD(&cmd_mgr->cmds); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_INITED; ++ spin_lock_init(&cmd_mgr->lock); ++ spin_lock_init(&cmd_mgr->cb_lock); ++ cmd_mgr->queue = &cmd_mgr_queue; ++ cmd_mgr->print = &cmd_mgr_print; ++ cmd_mgr->drain = &cmd_mgr_drain; ++ cmd_mgr->llind = NULL;//&cmd_mgr_llind; ++ cmd_mgr->msgind = &cmd_mgr_msgind; ++ ++#if 0 ++ INIT_WORK(&cmd_mgr->cmdWork, cmd_mgr_task_process); ++ cmd_mgr->cmd_wq = create_singlethread_workqueue("cmd_wq"); ++ if (!cmd_mgr->cmd_wq) { ++ txrx_err("insufficient memory to create cmd workqueue.\n"); ++ return; ++ } ++#endif ++} ++ ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ if(cmd_mgr->print) ++ cmd_mgr->print(cmd_mgr); ++ if(cmd_mgr->drain) ++ cmd_mgr->drain(cmd_mgr); ++ if(cmd_mgr->print) ++ cmd_mgr->print(cmd_mgr); ++ memset(cmd_mgr, 0, sizeof(*cmd_mgr)); ++} ++ ++void rwnx_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ struct aicwf_bus *bus = sdiodev->bus_if; ++ u8 *buffer = bus->cmd_buf; ++ u16 index = 0; ++ ++ memset(buffer, 0, CMD_BUF_MAX); ++ buffer[0] = (len+4) & 0x00ff; ++ buffer[1] = ((len+4) >> 8) &0x0f; ++ buffer[2] = 0x11; ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ buffer[3] = 0x0; ++ else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ buffer[3] = crc8_ponl_107(&buffer[0], 3); // crc8 ++ index += 4; ++ //there is a dummy word ++ index += 4; ++ ++ //make sure little endian ++ put_u16(&buffer[index], msg->id); ++ index += 2; ++ put_u16(&buffer[index], msg->dest_id); ++ index += 2; ++ put_u16(&buffer[index], msg->src_id); ++ index += 2; ++ put_u16(&buffer[index], msg->param_len); ++ index += 2; ++ memcpy(&buffer[index], (u8 *)msg->param, msg->param_len); ++ ++ aicwf_bus_txmsg(bus, buffer, len + 8); ++} ++ ++static inline void *rwnx_msg_zalloc(lmac_msg_id_t const id, ++ lmac_task_id_t const dest_id, ++ lmac_task_id_t const src_id, ++ uint16_t const param_len) ++{ ++ struct lmac_msg *msg; ++ gfp_t flags; ++ ++ if (in_softirq()) ++ flags = GFP_ATOMIC; ++ else ++ flags = GFP_KERNEL; ++ ++ msg = (struct lmac_msg *)kzalloc(sizeof(struct lmac_msg) + param_len, ++ flags); ++ if (msg == NULL) { ++ printk(KERN_CRIT "%s: msg allocation failed\n", __func__); ++ return NULL; ++ } ++ msg->id = id; ++ msg->dest_id = dest_id; ++ msg->src_id = src_id; ++ msg->param_len = param_len; ++ ++ return msg->param; ++} ++ ++static void rwnx_msg_free(struct lmac_msg *msg, const void *msg_params) ++{ ++ kfree(msg); ++} ++ ++ ++static int rwnx_send_msg(struct aic_sdio_dev *sdiodev, const void *msg_params, ++ int reqcfm, lmac_msg_id_t reqid, void *cfm) ++{ ++ struct lmac_msg *msg; ++ struct rwnx_cmd *cmd; ++ bool nonblock; ++ int ret = 0; ++ ++ msg = container_of((void *)msg_params, struct lmac_msg, param); ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ rwnx_msg_free(msg, msg_params); ++ printk("bus is down\n"); ++ return 0; ++ } ++ ++ nonblock = 0; ++ cmd = kzalloc(sizeof(struct rwnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL); ++ cmd->result = -EINTR; ++ cmd->id = msg->id; ++ cmd->reqid = reqid; ++ cmd->a2e_msg = msg; ++ cmd->e2a_msg = cfm; ++ if (nonblock) ++ cmd->flags = RWNX_CMD_FLAG_NONBLOCK; ++ if (reqcfm) ++ cmd->flags |= RWNX_CMD_FLAG_REQ_CFM; ++ ++ if (reqcfm) { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; // we don't need ack any more ++ ret = sdiodev->cmd_mgr.queue(&sdiodev->cmd_mgr, cmd); ++ } else { ++ rwnx_set_cmd_tx((void *)(sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ } ++ ++ if (!reqcfm) ++ kfree(cmd); ++ ++ return ret; ++} ++ ++ ++int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_size, u32 *mem_data) ++{ ++ struct dbg_mem_block_write_req *mem_blk_write_req; ++ ++ /* Build the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req = rwnx_msg_zalloc(DBG_MEM_BLOCK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_block_write_req)); ++ if (!mem_blk_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req->memaddr = mem_addr; ++ mem_blk_write_req->memsize = mem_size; ++ memcpy(mem_blk_write_req->memdata, mem_data, mem_size); ++ ++ /* Send the DBG_MEM_BLOCK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_blk_write_req, 1, DBG_MEM_BLOCK_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm) ++{ ++ struct dbg_mem_read_req *mem_read_req; ++ ++ /* Build the DBG_MEM_READ_REQ message */ ++ mem_read_req = rwnx_msg_zalloc(DBG_MEM_READ_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_read_req)); ++ if (!mem_read_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_READ_REQ message */ ++ mem_read_req->memaddr = mem_addr; ++ ++ /* Send the DBG_MEM_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_read_req, 1, DBG_MEM_READ_CFM, cfm); ++} ++ ++ ++int rwnx_send_dbg_mem_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_data) ++{ ++ struct dbg_mem_write_req *mem_write_req; ++ ++ /* Build the DBG_MEM_WRITE_REQ message */ ++ mem_write_req = rwnx_msg_zalloc(DBG_MEM_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_write_req)); ++ if (!mem_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_WRITE_REQ message */ ++ mem_write_req->memaddr = mem_addr; ++ mem_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_write_req, 1, DBG_MEM_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_mask_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_mask, u32 mem_data) ++{ ++ struct dbg_mem_mask_write_req *mem_mask_write_req; ++ ++ /* Build the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req = rwnx_msg_zalloc(DBG_MEM_MASK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_mask_write_req)); ++ if (!mem_mask_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req->memaddr = mem_addr; ++ mem_mask_write_req->memmask = mem_mask; ++ mem_mask_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_MASK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_mask_write_req, 1, DBG_MEM_MASK_WRITE_CFM, NULL); ++} ++ ++ ++int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm) ++{ ++ struct dbg_start_app_req *start_app_req; ++ ++ /* Build the DBG_START_APP_REQ message */ ++ start_app_req = rwnx_msg_zalloc(DBG_START_APP_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_start_app_req)); ++ if (!start_app_req) { ++ printk("start app nomen\n"); ++ return -ENOMEM; ++ } ++ ++ /* Set parameters for the DBG_START_APP_REQ message */ ++ start_app_req->bootaddr = boot_addr; ++ start_app_req->boottype = boot_type; ++ ++ /* Send the DBG_START_APP_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, start_app_req, 1, DBG_START_APP_CFM, start_app_cfm); ++} ++ ++static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = { ++}; ++ ++static msg_cb_fct *msg_hdlrs[] = { ++ [TASK_DBG] = dbg_hdlrs, ++}; ++ ++void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg) ++{ ++ sdiodev->cmd_mgr.msgind(&sdiodev->cmd_mgr, msg, ++ msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) ++MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver"); ++#else ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#endif ++#endif ++ ++#define MD5(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] ++#define MD5PINRT "file md5:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\r\n" ++ ++int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device) ++{ ++ ++#ifdef CONFIG_USE_FW_REQUEST ++ const struct firmware *fw = NULL; ++ u32 *dst = NULL; ++ void *buffer=NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ int size = 0; ++ int ret = 0; ++ ++ printk("%s: request firmware = %s \n", __func__ ,name); ++ ++ ++ ret = request_firmware(&fw, name, NULL); ++ ++ if (ret < 0) { ++ printk("Load %s fail\n", name); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ size = fw->size; ++ dst = (u32 *)fw->data; ++ ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ memcpy(buffer, dst, size); ++ ++ *fw_buf = buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ release_firmware(fw); ++ ++ return size; ++#else ++ void *buffer = NULL; ++ char *path = NULL; ++ struct file *fp = NULL; ++ int size = 0, len = 0;// i = 0; ++ ssize_t rdlen = 0; ++ //u32 *src = NULL, *dst = NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ ++ #ifdef CONFIG_FIRMWARE_ARRAY ++ size = aicwf_get_firmware_array((char*)name, fw_buf); ++ printk("%s size:%d \r\n", __func__, size); ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)*fw_buf, size); ++ MD5Final(&md5, decrypt); ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ return size; ++ #endif ++ ++ /* get the firmware path */ ++ path = __getname(); ++ if (!path) { ++ *fw_buf = NULL; ++ return -1; ++ } ++ ++ if(strlen(aic_fw_path) > 0){ ++ len = snprintf(path, AICBSP_FW_PATH_MAX, "%s/%s", aic_fw_path, name); ++ }else{ ++ len = snprintf(path, AICBSP_FW_PATH_MAX, "%s/%s", AICBSP_FW_PATH, name); ++ } ++ if (len >= AICBSP_FW_PATH_MAX) { ++ printk("%s: %s file's path too long\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ return -1; ++ } ++ ++ printk("%s :firmware path = %s \n", __func__, path); ++ ++ /* open the firmware file */ ++ fp = filp_open(path, O_RDONLY, 0); ++ if (IS_ERR_OR_NULL(fp)) { ++ printk("%s: %s file failed to open\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ fp = NULL; ++ return -1; ++ } ++ ++ size = i_size_read(file_inode(fp)); ++ if (size <= 0) { ++ printk("%s: %s file size invalid %d\n", __func__, name, size); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ } ++ ++ /* start to read from firmware file */ ++ buffer = vmalloc(size); ++ ++ if (!buffer) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ }else{ ++ memset(buffer, 0, size); ++ } ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) ++ rdlen = kernel_read(fp, buffer, size, &fp->f_pos); ++#else ++ rdlen = kernel_read(fp, fp->f_pos, buffer, size); ++#endif ++ ++ if (size != rdlen) { ++ printk("%s: %s file rdlen invalid %ld\n", __func__, name, (long int)rdlen); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ vfree(buffer); ++ buffer = NULL; ++ return -1; ++ } ++ if (rdlen > 0) { ++ fp->f_pos += rdlen; ++ } ++ ++#if 0 ++ /*start to transform the data format*/ ++ src = (u32 *)buffer; ++ dst = (u32 *)vmalloc(size); ++ ++ if (!dst) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ vfree(buffer); ++ buffer = NULL; ++ return -1; ++ }else{ ++ memset(dst, 0, size); ++ } ++ ++ for (i = 0; i < (size/4); i++) { ++ dst[i] = src[i]; ++ } ++#endif ++ ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ //vfree(buffer); ++ //buffer = NULL; ++ *fw_buf = (u32*)buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ return size; ++#endif ++} ++ ++extern int testmode; ++ ++#ifdef CONFIG_M2D_OTA_AUTO_SUPPORT ++extern char saved_sdk_ver[64]; ++ ++int rwnx_plat_m2d_flash_ota_android(struct aic_sdio_dev *sdiodev, char *filename) ++{ ++ struct device *dev = sdiodev->dev; ++ unsigned int i=0; ++ int size; ++ u32 *dst=NULL; ++ int err=0; ++ int ret; ++ u8 bond_id; ++ const u32 mem_addr = 0x40500000; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm); ++ if (ret) { ++ printk("m2d %x rd fail: %d\n", mem_addr, ret); ++ return ret; ++ } ++ bond_id = (u8)(rd_mem_addr_cfm.memdata >> 24); ++ printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ if (bond_id & (1<<1)) { ++ //flash is invalid ++ printk("m2d flash is invalid\n"); ++ return -1; ++ } ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if(size<=0){ ++ printk("wrong size of m2d file\n"); ++ vfree(dst); ++ dst = NULL; ++ return -1; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload m2d %s flash, size=%d\n", filename, size); ++ ++ /*send info first*/ ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_INFO_ADDR, 4, (u32 *)&size); ++ ++ /*send data first*/ ++ if (size > 1024) {// > 1KB data ++ for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, 1024, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ break; ++ } ++ } ++ } ++ ++ if (!err && (i < size)) {// <1KB data ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, size - i, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ } ++ } ++ ++ if (dst) { ++ vfree(dst); ++ dst = NULL; ++ } ++ testmode = FW_NORMAL_MODE; ++ aicbsp_info.cpmode = testmode; ++ ++ printk("m2d flash update complete\n\n"); ++ ++ return err; ++} ++ ++int rwnx_plat_m2d_flash_ota_check(struct aic_sdio_dev *sdiodev, char *filename) ++{ ++ struct device *dev = sdiodev->dev; ++ unsigned int i=0,j=0; ++ int size; ++ u32 *dst=NULL; ++ int err=0; ++ int ret=0; ++ u8 bond_id; ++ const u32 mem_addr = 0x40500000; ++ const u32 mem_addr_code_start = AIC_M2D_OTA_CODE_START_ADDR; ++ const u32 mem_addr_sdk_ver = AIC_M2D_OTA_VER_ADDR; ++ const u32 driver_code_start_idx = (AIC_M2D_OTA_CODE_START_ADDR-AIC_M2D_OTA_FLASH_ADDR)/4; ++ const u32 driver_sdk_ver_idx = (AIC_M2D_OTA_VER_ADDR-AIC_M2D_OTA_FLASH_ADDR)/4; ++ u32 driver_sdk_ver_addr_idx = 0; ++ u32 code_start_addr = 0xffffffff; ++ u32 sdk_ver_addr = 0xffffffff; ++ u32 drv_code_start_addr = 0xffffffff; ++ u32 drv_sdk_ver_addr = 0xffffffff; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ char m2d_sdk_ver[64]; ++ char flash_sdk_ver[64]; ++ u32 flash_ver[16]; ++ u32 ota_ver[16]; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm); ++ if (ret) { ++ printk("m2d %x rd fail: %d\n", mem_addr, ret); ++ return ret; ++ } ++ bond_id = (u8)(rd_mem_addr_cfm.memdata >> 24); ++ printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ if (bond_id & (1<<1)) { ++ //flash is invalid ++ printk("m2d flash is invalid\n"); ++ return -1; ++ } ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr_code_start, &rd_mem_addr_cfm); ++ if (ret){ ++ printk("mem_addr_code_start %x rd fail: %d\n", mem_addr_code_start, ret); ++ return ret; ++ } ++ code_start_addr = rd_mem_addr_cfm.memdata; ++ ++ #if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr_sdk_ver, &rd_mem_addr_cfm); ++ if (ret){ ++ printk("mem_addr_sdk_ver %x rd fail: %d\n", mem_addr_code_start, ret); ++ return ret; ++ } ++ sdk_ver_addr = rd_mem_addr_cfm.memdata; ++ #else ++ sdk_ver_addr = mem_addr_sdk_ver; ++ #endif ++ printk("code_start_addr: 0x%x, sdk_ver_addr: 0x%x\n", code_start_addr,sdk_ver_addr); ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if(size<=0){ ++ printk("wrong size of m2d file\n"); ++ vfree(dst); ++ dst = NULL; ++ return -1; ++ } ++ if(code_start_addr == 0xffffffff && sdk_ver_addr == 0xffffffff) { ++ printk("########m2d flash old version , must be upgrade\n"); ++ drv_code_start_addr = dst[driver_code_start_idx]; ++ drv_sdk_ver_addr = dst[driver_sdk_ver_idx]; ++ ++ printk("drv_code_start_addr: 0x%x, drv_sdk_ver_addr: 0x%x\n", drv_code_start_addr,drv_sdk_ver_addr); ++ ++ if(drv_sdk_ver_addr == 0xffffffff){ ++ printk("########driver m2d_ota.bin is old ,not need upgrade\n"); ++ return -1; ++ } ++ ++ } else { ++ for(i=0;i<16;i++){ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, (sdk_ver_addr+i*4), &rd_mem_addr_cfm); ++ if (ret){ ++ printk("mem_addr_sdk_ver %x rd fail: %d\n", mem_addr_code_start, ret); ++ return ret; ++ } ++ flash_ver[i] = rd_mem_addr_cfm.memdata; ++ } ++ memcpy((u8 *)flash_sdk_ver,(u8 *)flash_ver,64); ++ memcpy((u8 *)saved_sdk_ver,(u8 *)flash_sdk_ver,64); ++ printk("flash SDK Version: %s\r\n\r\n", flash_sdk_ver); ++ ++ drv_code_start_addr = dst[driver_code_start_idx]; ++ drv_sdk_ver_addr = dst[driver_sdk_ver_idx]; ++ ++ printk("drv_code_start_addr: 0x%x, drv_sdk_ver_addr: 0x%x\n", drv_code_start_addr,drv_sdk_ver_addr); ++ ++ if(drv_sdk_ver_addr == 0xffffffff){ ++ printk("########driver m2d_ota.bin is old ,not need upgrade\n"); ++ return -1; ++ } ++ ++ #if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++ driver_sdk_ver_addr_idx = (drv_sdk_ver_addr-drv_code_start_addr)/4; ++ #else ++ driver_sdk_ver_addr_idx = driver_sdk_ver_idx; ++ #endif ++ printk("driver_sdk_ver_addr_idx %d\n",driver_sdk_ver_addr_idx); ++ ++ if (driver_sdk_ver_addr_idx){ ++ for(j = 0; j < 16; j++){ ++ ota_ver[j] = dst[driver_sdk_ver_addr_idx+j]; ++ } ++ memcpy((u8 *)m2d_sdk_ver,(u8 *)ota_ver,64); ++ printk("m2d_ota SDK Version: %s\r\n\r\n", m2d_sdk_ver); ++ } else { ++ return -1; ++ } ++ ++ if(!strcmp(m2d_sdk_ver,flash_sdk_ver)){ ++ printk("######## m2d %s flash is not need upgrade\r\n", filename); ++ return -1; ++ } ++ } ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload m2d %s flash, size=%d\n", filename, size); ++ ++ /*send info first*/ ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_INFO_ADDR, 4, (u32 *)&size); ++ ++ /*send data first*/ ++ if (size > 1024) {// > 1KB data ++ for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, 1024, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ break; ++ } ++ } ++ } ++ ++ if (!err && (i < size)) {// <1KB data ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, size - i, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ } ++ } ++ ++ if (dst) { ++ vfree(dst); ++ dst = NULL; ++ } ++ testmode = FW_NORMAL_MODE; ++ ++ printk("m2d flash update complete\n\n"); ++ ++ return err; ++} ++#endif//CONFIG_M2D_OTA_AUTO_SUPPORT ++ ++int aicwf_patch_table_load(struct aic_sdio_dev *rwnx_hw, char *filename) ++{ ++ struct device *dev = rwnx_hw->dev; ++ int err = 0; ++ unsigned int i = 0, size; ++ u32 *dst = NULL; ++ u8 *describle; ++ u32 fmacfw_patch_tbl_8800dc_u02_describe_size = 124; ++ u32 fmacfw_patch_tbl_8800dc_u02_describe_base;//read from patch_tbl ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload %s \n", filename); ++ ++ size = rwnx_load_firmware(&dst, filename,dev); ++ if (!dst) { ++ printk("No such file or directory\n"); ++ return -1; ++ } ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ dst = NULL; ++ err = -1; ++ } ++ ++ printk("tbl size = %d \n",size); ++ ++ fmacfw_patch_tbl_8800dc_u02_describe_base = dst[0]; ++ AICWFDBG(LOGINFO, "FMACFW_PATCH_TBL_8800DC_U02_DESCRIBE_BASE = %x \n",fmacfw_patch_tbl_8800dc_u02_describe_base); ++ ++ if (!err && (i < size)) { ++ err=rwnx_send_dbg_mem_block_write_req(rwnx_hw, fmacfw_patch_tbl_8800dc_u02_describe_base, fmacfw_patch_tbl_8800dc_u02_describe_size + 4, dst); ++ if(err){ ++ printk("write describe information fail \n"); ++ } ++ ++ describle=kzalloc(fmacfw_patch_tbl_8800dc_u02_describe_size,GFP_KERNEL); ++ memcpy(describle,&dst[1],fmacfw_patch_tbl_8800dc_u02_describe_size); ++ printk("%s",describle); ++ kfree(describle); ++ describle=NULL; ++ } ++ ++ if (!err && (i < size)) { ++ for (i =(128/4); i < (size/4); i +=2) { ++ printk("patch_tbl: %x %x\n", dst[i], dst[i+1]); ++ err = rwnx_send_dbg_mem_write_req(rwnx_hw, dst[i], dst[i+1]); ++ } ++ if (err) { ++ printk("bin upload fail: %x, err:%d\r\n", dst[i], err); ++ } ++ } ++ ++ if (dst) { ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++#endif ++ dst = NULL; ++ } ++ ++ ++ return err; ++ ++} ++ ++extern char aic_fw_path[200]; ++int aicwf_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ #if !defined(CONFIG_FPGA_VERIFICATION) ++ if (chip_sub_id == 0) { ++ printk("u01 is loaing ###############\n"); ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_8800DC); ++ } else if (chip_sub_id == 1) { ++ printk("u02 is loaing ###############\n"); ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_8800DC_U02); ++ } else if (chip_sub_id == 2) { ++ printk("h_u02 is loaing ###############\n"); ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_8800DC_H_U02); ++ } else { ++ printk("unsupported id: %d\n", chip_sub_id); ++ } ++ #endif ++ return ret; ++} ++ ++int aicwf_plat_rftest_load_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, RAM_LMAC_FW_ADDR, RWNX_MAC_FW_RF_BASE_NAME_8800DC); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ return ret; ++} ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++int aicwf_misc_ram_valid_check_8800dc(struct aic_sdio_dev *sdiodev, int *valid_out) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_word_cnt; ++ uint32_t bit_mask[4]; ++ int i; ++ if (valid_out) { ++ *valid_out = 0; ++ } ++ if (testmode == FW_RFTEST_MODE) { ++ ++ uint32_t vect1 = 0; ++ uint32_t vect2 = 0; ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0004; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "cfg_base:%x vcet1 rd fail: %d\n", cfg_base, ret); ++ return ret; ++ } ++ vect1 = cfm.memdata; ++ if ((vect1 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) { ++ AICWFDBG(LOGERROR, "vect1 invalid: %x\n", vect1); ++ return ret; ++ } ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0008; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "cfg_base:%x vcet2 rd fail: %d\n", cfg_base, ret); ++ return ret; ++ } ++ vect2 = cfm.memdata; ++ if ((vect2 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) { ++ AICWFDBG(LOGERROR, "vect2 invalid: %x\n", vect2); ++ return ret; ++ } ++ ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ // init misc ram ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr); ++ // bit_mask ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ bit_mask[i] = cfm.memdata; ++ } ++ AICWFDBG(LOGTRACE, "bit_mask:%x,%x,%x,%x\n",bit_mask[0],bit_mask[1],bit_mask[2],bit_mask[3]); ++ if ((bit_mask[0] == 0) && ((bit_mask[1] & 0xFFF00000) == 0x80000000) && ++ (bit_mask[2] == 0) && ((bit_mask[3] & 0xFFFFFF00) == 0x00000000)) { ++ if (valid_out) { ++ *valid_out = 1; ++ } ++ } ++ return ret; ++} ++ ++int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ if (chip_sub_id == 1) { ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_CALIB_ADDR, RWNX_MAC_CALIB_NAME_8800DC_U02); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ } else if (chip_sub_id == 2) { ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_CALIB_ADDR, RWNX_MAC_CALIB_NAME_8800DC_H_U02); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++#endif ++ ++#ifdef CONFIG_DPD ++#ifndef CONFIG_FORCE_DPD_CALIB ++int is_file_exist(char* name) ++{ ++ char *path = NULL; ++ struct file *fp = NULL; ++ int len; ++ ++ path = __getname(); ++ if (!path) { ++ AICWFDBG(LOGINFO, "%s getname fail\n", __func__); ++ return -1; ++ } ++ ++ len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", AICBSP_FW_PATH, name); ++ ++ fp = filp_open(path, O_RDONLY, 0); ++ if (IS_ERR(fp)) { ++ __putname(path); ++ fp = NULL; ++ return 0; ++ } else { ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return 1; ++ } ++} ++ ++EXPORT_SYMBOL(is_file_exist); ++#endif ++#endif ++ ++#ifdef CONFIG_DPD ++rf_misc_ram_lite_t dpd_res = {{0},}; ++EXPORT_SYMBOL(dpd_res); ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++rf_misc_ram_lite_t loft_res_local = {{0},}; ++EXPORT_SYMBOL(loft_res_local); ++#endif ++ ++static int rwnx_plat_patch_load(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ AICWFDBG(LOGINFO, "testmode=%d\n", testmode); ++ if (chip_sub_id == 0) { ++ if (testmode == FW_NORMAL_MODE) { ++ AICWFDBG(LOGINFO, "rwnx_plat_patch_loading\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ } else if (testmode == FW_RFTEST_MODE) { ++ ret = aicwf_plat_rftest_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ } else if (chip_sub_id >= 1) { ++ if (testmode == FW_NORMAL_MODE) { ++ AICWFDBG(LOGINFO, "rwnx_plat_patch_loading\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ #ifdef CONFIG_DPD ++ #ifdef CONFIG_FORCE_DPD_CALIB ++ if (1) { ++ AICWFDBG(LOGINFO, "dpd calib & write\n"); ++ ret = aicwf_dpd_calib_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "dpd calib fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #else ++ if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 1) { ++ AICWFDBG(LOGINFO, "dpd bin load\n"); ++ ret = aicwf_dpd_result_load_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ ret = aicwf_dpd_result_apply_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "apply dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ else ++ #elif defined(CONFIG_LOFT_CALIB) ++ if (1) { ++ AICWFDBG(LOGINFO, "loft calib\n"); ++ ret = aicwf_loft_calib_8800dc(sdiodev, &loft_res_local); ++ if (ret) { ++ AICWFDBG(LOGINFO, "loft calib fail: %d\n", ret); ++ return ret; ++ } ++ } else ++ #endif ++ { ++ ret = aicwf_misc_ram_init_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram init fail: %d\n", ret); ++ return ret; ++ } ++ } ++ } else if (testmode == FW_RFTEST_MODE) { ++ #ifdef CONFIG_DPD ++ #ifdef CONFIG_FORCE_DPD_CALIB ++ if (1) { ++ AICWFDBG(LOGINFO, "patch load\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ AICWFDBG(LOGINFO, "dpd calib & write\n"); ++ ret = aicwf_dpd_calib_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "dpd calib fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif/*CONFIG_FORCE_DPD_CALIB*/ ++ #elif defined(CONFIG_LOFT_CALIB) ++ { ++ AICWFDBG(LOGINFO, "patch load\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ AICWFDBG(LOGINFO, "loft calib\n"); ++ ret = aicwf_loft_calib_8800dc(sdiodev, &loft_res_local); ++ if (ret) { ++ AICWFDBG(LOGINFO, "loft calib fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif/*CONFIG_DPD*/ ++ ret = aicwf_plat_rftest_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ } else if (testmode == FW_DPDCALIB_MODE) { ++ #if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++ if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 0) { ++ AICWFDBG(LOGINFO, "patch load\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ AICWFDBG(LOGINFO, "dpd calib & write\n"); ++ ret = aicwf_dpd_calib_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "dpd calib fail: %d\n", ret); ++ return ret; ++ } ++ ret = aicwf_dpd_result_write_8800dc((void *)&dpd_res, DPD_RESULT_SIZE_8800DC); ++ if (ret) { ++ AICWFDBG(LOGINFO, "file write fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ return 1; // exit calib mode ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, ++ const char *filename) ++{ ++ struct device *dev = sdiodev->dev; ++ unsigned int i = 0; ++ int size; ++ u32 *dst = NULL; ++ int err = 0; ++ ++ printk("%s\n",__func__); ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++#endif ++ dst = NULL; ++ return -1; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ if (size > 1024) {// > 1KB data ++ for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, fw_addr + i, 1024, dst + i / 4); ++ if (err) { ++ printk("bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ break; ++ } ++ } ++ } ++ ++ if (!err && (i < size)) {// <1KB data ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, fw_addr + i, size - i, dst + i / 4); ++ if (err) { ++ printk("bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ } ++ } ++ ++ if (dst) { ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++#endif ++ dst = NULL; ++ } ++ ++ return err; ++} ++ ++int aicbt_patch_table_free(struct aicbt_patch_table **head) ++{ ++ struct aicbt_patch_table *p = *head, *n = NULL; ++ while (p) { ++ n = p->next; ++ vfree(p->name); ++ vfree(p->data); ++ vfree(p); ++ p = n; ++ } ++ *head = NULL; ++ return 0; ++} ++ ++struct aicbt_patch_table *aicbt_patch_table_alloc(const char *filename) ++{ ++ uint8_t *rawdata = NULL, *p; ++ int size; ++ struct aicbt_patch_table *head = NULL, *new = NULL, *cur = NULL; ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware((u32 **)&rawdata, filename, NULL); ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ goto err; ++ } ++ ++ p = rawdata; ++ if (memcmp(p, AICBT_PT_TAG, sizeof(AICBT_PT_TAG) < 16 ? sizeof(AICBT_PT_TAG) : 16)) { ++ printk("TAG err\n"); ++ goto err; ++ } ++ p += 16; ++ ++ while (p - rawdata < size) { ++ new = (struct aicbt_patch_table *)vmalloc(sizeof(struct aicbt_patch_table)); ++ memset(new, 0, sizeof(struct aicbt_patch_table)); ++ if (head == NULL) { ++ head = new; ++ cur = new; ++ } else { ++ cur->next = new; ++ cur = cur->next; ++ } ++ ++ cur->name = (char *)vmalloc(sizeof(char) * 16); ++ memset(cur->name, 0, sizeof(char) * 16); ++ memcpy(cur->name, p, 16); ++ p += 16; ++ ++ cur->type = *(uint32_t *)p; ++ p += 4; ++ ++ cur->len = *(uint32_t *)p; ++ p += 4; ++ ++ if((cur->type ) >= 1000 ) {//Temp Workaround ++ cur->len = 0; ++ }else{ ++ if(cur->len > 0){ ++ cur->data = (uint32_t *)vmalloc(sizeof(uint8_t) * cur->len * 8); ++ memset(cur->data, 0, sizeof(uint8_t) * cur->len * 8); ++ memcpy(cur->data, p, cur->len * 8); ++ p += cur->len * 8; ++ } ++ } ++ } ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(rawdata); ++#endif ++ return head; ++ ++err: ++ aicbt_patch_table_free(&head); ++ if (rawdata) ++ vfree(rawdata); ++ return NULL; ++} ++int aicbt_patch_info_unpack(struct aicbt_patch_info_t *patch_info, struct aicbt_patch_table *head_t) ++{ ++ uint8_t *patch_info_array = (uint8_t*)patch_info; ++ int base_len = 0; ++ int memcpy_len = 0; ++ ++ if (AICBT_PT_INF == head_t->type) { ++ base_len = ((offsetof(struct aicbt_patch_info_t, ext_patch_nb_addr) - offsetof(struct aicbt_patch_info_t, adid_addrinf) )/sizeof(uint32_t))/2; ++ AICWFDBG(LOGDEBUG, "%s head_t->len:%d base_len:%d \r\n", __func__, head_t->len, base_len); ++ ++ if (head_t->len > base_len){ ++ patch_info->info_len = base_len; ++ memcpy_len = patch_info->info_len + 1;//include ext patch nb ++ } else{ ++ patch_info->info_len = head_t->len; ++ memcpy_len = patch_info->info_len; ++ } ++ AICWFDBG(LOGDEBUG, "%s memcpy_len:%d \r\n", __func__, memcpy_len); ++ ++ if (patch_info->info_len == 0) ++ return 0; ++ ++ memcpy(((patch_info_array) + sizeof(patch_info->info_len)), ++ head_t->data, ++ memcpy_len * sizeof(uint32_t) * 2); ++ AICWFDBG(LOGDEBUG, "%s adid_addrinf:%x addr_adid:%x \r\n", __func__, ++ ((struct aicbt_patch_info_t *)patch_info_array)->adid_addrinf, ++ ((struct aicbt_patch_info_t *)patch_info_array)->addr_adid); ++ ++ if (patch_info->ext_patch_nb > 0){ ++ int index = 0; ++ patch_info->ext_patch_param = (uint32_t *)(head_t->data + ((memcpy_len) * 2)); ++ ++ for(index = 0; index < patch_info->ext_patch_nb; index++){ ++ AICWFDBG(LOGDEBUG, "%s id:%x addr:%x \r\n", __func__, ++ *(patch_info->ext_patch_param + (index * 2)), ++ *(patch_info->ext_patch_param + (index * 2) + 1)); ++ } ++ } ++ ++ } ++ return 0; ++} ++ ++int aicbt_ext_patch_data_load(struct aic_sdio_dev *sdiodev, struct aicbt_patch_info_t *patch_info) ++{ ++ int ret = 0; ++ uint32_t ext_patch_nb = patch_info->ext_patch_nb; ++ char ext_patch_file_name[50]; ++ int index = 0; ++ uint32_t id = 0; ++ uint32_t addr = 0; ++ ++ ++ if (ext_patch_nb > 0){ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8800DC) { ++ AICWFDBG(LOGDEBUG, "[0x40506004]: 0x04318000\n"); ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, 0x40506004, 0x04318000); ++ AICWFDBG(LOGDEBUG, "[0x40506004]: 0x04338000\n"); ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, 0x40506004, 0x04338000); ++ } ++ for (index = 0; index < patch_info->ext_patch_nb; index++){ ++ id = *(patch_info->ext_patch_param + (index * 2)); ++ addr = *(patch_info->ext_patch_param + (index * 2) + 1); ++ memset(ext_patch_file_name, 0, sizeof(ext_patch_file_name)); ++ sprintf(ext_patch_file_name,"%s%d.bin", ++ aicbsp_firmware_list[aicbsp_info.cpmode].bt_ext_patch, ++ id); ++ AICWFDBG(LOGDEBUG, "%s ext_patch_file_name:%s ext_patch_id:%x ext_patch_addr:%x \r\n", ++ __func__,ext_patch_file_name, id, addr); ++ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, addr, ext_patch_file_name)) { ++ ret = -1; ++ break; ++ } ++ } ++ } ++ return ret; ++} ++ ++ ++int aicbt_patch_trap_data_load(struct aic_sdio_dev *sdiodev, struct aicbt_patch_table *head) ++{ ++ struct aicbt_patch_info_t patch_info = { ++ .info_len = 0, ++ .adid_addrinf = 0, ++ .addr_adid = 0, ++ .patch_addrinf = 0, ++ .addr_patch = 0, ++ .reset_addr = 0, ++ .reset_val = 0, ++ .adid_flag_addr = 0, ++ .adid_flag = 0, ++ .ext_patch_nb_addr = 0, ++ .ext_patch_nb = 0, ++ }; ++ if(head == NULL){ ++ return -1; ++ } ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR; ++ patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR; ++ } ++ else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC){ ++ if(aicbsp_info.chip_rev == CHIP_REV_U01){ ++ patch_info.addr_adid = RAM_8800DC_U01_ADID_ADDR; ++ }else if(aicbsp_info.chip_rev == CHIP_REV_U02){ ++ patch_info.addr_adid = RAM_8800DC_U02_ADID_ADDR; ++ } ++ patch_info.addr_patch = RAM_8800DC_FW_PATCH_ADDR; ++ aicbt_patch_info_unpack(&patch_info, head); ++ if(patch_info.reset_addr == 0) { ++ patch_info.reset_addr = FW_RESET_START_ADDR; ++ patch_info.reset_val = FW_RESET_START_VAL; ++ patch_info.adid_flag_addr = FW_ADID_FLAG_ADDR; ++ patch_info.adid_flag = FW_ADID_FLAG_VAL; ++ if (rwnx_send_dbg_mem_write_req(sdiodev, patch_info.reset_addr, patch_info.reset_val)) ++ return -1; ++ if (rwnx_send_dbg_mem_write_req(sdiodev, patch_info.adid_flag_addr, patch_info.adid_flag)) ++ return -1; ++ } ++ } else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ if (aicbsp_info.chip_rev == CHIP_REV_U01) { ++ patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80; ++ patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80; ++ } else if (aicbsp_info.chip_rev == CHIP_REV_U02 || aicbsp_info.chip_rev == CHIP_REV_U03) { ++ patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80_U02; ++ patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80_U02; ++ } ++ aicbt_patch_info_unpack(&patch_info, head); ++ if(patch_info.info_len == 0) { ++ printk("%s, aicbt_patch_info_unpack fail\n", __func__); ++ return -1; ++ } ++ } else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ aicbt_patch_info_unpack(&patch_info, head); ++ if(patch_info.info_len == 0) { ++ printk("%s, aicbt_patch_info_unpack fail\n", __func__); ++ return -1; ++ } ++ } ++ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, patch_info.addr_adid, aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid)) ++ return -1; ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, patch_info.addr_patch, aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch)) ++ return -1; ++ if (aicbt_ext_patch_data_load(sdiodev, &patch_info)) ++ return -1; ++ return 0; ++ ++} ++ ++static struct aicbt_info_t aicbt_info[]={ ++ { ++ .btmode = AICBT_BTMODE_DEFAULT, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT, ++ },//PRODUCT_ID_AIC8801 ++ { ++ .btmode = AICBT_BTMODE_BT_WIFI_COMBO, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800dc, ++ },//PRODUCT_ID_AIC8800DC ++ { ++ .btmode = AICBT_BTMODE_BT_WIFI_COMBO, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800dc, ++ },//PRODUCT_ID_AIC8800DW ++ { ++ .btmode = AICBT_BTMODE_DEFAULT_8800d80, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800d80, ++ },//PRODUCT_ID_AIC8800D80 ++ { ++ .btmode = AICBT_BTMODE_DEFAULT_8800d80x2, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800d80x2, ++ }//PRODUCT_ID_AIC8800D80x2 ++ ++}; ++ ++ ++int aicbt_patch_table_load(struct aic_sdio_dev *sdiodev, struct aicbt_patch_table *head) ++{ ++ struct aicbt_patch_table *p; ++ int ret = 0, i; ++ uint32_t *data = NULL; ++ if(head == NULL){ ++ return -1; ++ } ++ ++ for (p = head; p != NULL; p = p->next) { ++ data = p->data; ++ if (AICBT_PT_BTMODE == p->type) { ++ *(data + 1) = aicbsp_info.hwinfo < 0; ++ *(data + 3) = aicbsp_info.hwinfo; ++ *(data + 5) = (sdiodev->chipid == PRODUCT_ID_AIC8800DC?aicbsp_info.cpmode:0);//0;//aicbsp_info.cpmode; ++ ++ *(data + 7) = aicbt_info[sdiodev->chipid].btmode; ++ *(data + 9) = aicbt_info[sdiodev->chipid].btport; ++ *(data + 11) = aicbt_info[sdiodev->chipid].uart_baud; ++ *(data + 13) = aicbt_info[sdiodev->chipid].uart_flowctrl; ++ *(data + 15) = aicbt_info[sdiodev->chipid].lpm_enable; ++ *(data + 17) = aicbt_info[sdiodev->chipid].txpwr_lvl; ++ ++ printk("%s bt btmode[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].btmode); ++ printk("%s bt uart_baud[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].uart_baud); ++ printk("%s bt uart_flowctrl[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].uart_flowctrl); ++ printk("%s bt lpm_enable[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].lpm_enable); ++ printk("%s bt tx_pwr[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].txpwr_lvl); ++ } ++ ++ if (AICBT_PT_VER == p->type) { ++ printk("aicbsp: bt patch version: %s\n", (char *)p->data); ++ continue; ++ } ++ ++ for (i = 0; i < p->len; i++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, *data, *(data + 1)); ++ if (ret != 0) ++ return ret; ++ data += 2; ++ } ++ if (p->type == AICBT_PT_PWRON) ++ udelay(500); ++ } ++ ++ ++ ///aicbt_patch_table_free(&head); ++ return 0; ++} ++ ++ ++int aicbt_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ struct aicbt_patch_table *head = aicbt_patch_table_alloc(aicbsp_firmware_list[aicbsp_info.cpmode].bt_table); ++ if (head == NULL){ ++ printk("aicbt_patch_table_alloc fail\n"); ++ return -1; ++ } ++ ++ if (aicbt_patch_trap_data_load(sdiodev, head)) { ++ printk("aicbt_patch_trap_data_load fail\n"); ++ ret = -1; ++ goto err; ++ } ++ ++ if (aicbt_patch_table_load(sdiodev, head)) { ++ printk("aicbt_patch_table_load fail\n"); ++ ret = -1; ++ goto err; ++ } ++ ++err: ++ aicbt_patch_table_free(&head); ++ return ret; ++} ++ ++static int aicwifi_start_from_bootrom(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ ++ /* memory access */ ++ const u32 fw_addr = RAM_FMAC_FW_ADDR; ++ struct dbg_start_app_cfm start_app_cfm; ++ ++ /* fw start */ ++ ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, HOST_START_APP_AUTO, &start_app_cfm); ++ if (ret) { ++ return -1; ++ } ++ aicbsp_info.hwinfo_r = start_app_cfm.bootstatus & 0xFF; ++ ++ return 0; ++} ++ ++static int start_from_bootrom_8800DC(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ u32 rd_addr; ++ u32 fw_addr; ++ u32 boot_type; ++ struct dbg_mem_read_cfm rd_cfm; ++ ++ /* memory access */ ++ if(testmode == 1){ ++ rd_addr = RAM_LMAC_FW_ADDR; ++ fw_addr = RAM_LMAC_FW_ADDR; ++ } ++ else{ ++ rd_addr = RAM_FMAC_FW_ADDR; ++ fw_addr = RAM_FMAC_FW_ADDR; ++ } ++ ++ AICWFDBG(LOGINFO, "Read FW mem: %08x\n", rd_addr); ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_addr, &rd_cfm))) { ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "cfm: [%08x] = %08x\n", rd_cfm.memaddr, rd_cfm.memdata); ++ ++ if (testmode == 0) { ++ boot_type = HOST_START_APP_DUMMY; ++ } else { ++ boot_type = HOST_START_APP_AUTO; ++ } ++ /* fw start */ ++ AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); ++ if ((ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type ,NULL))) { ++ return -1; ++ } ++ return 0; ++} ++ ++u32 adaptivity_patch_tbl[][2] = { ++ {0x0004, 0x0000320A}, //linkloss_thd ++ {0x0094, 0x00000000}, //ac_param_conf ++ {0x00F8, 0x00010138}, //tx_adaptivity_en ++}; ++ ++u32 patch_tbl[][2] = { ++#if !defined(CONFIG_LINK_DET_5G) ++ {0x0104, 0x00000000}, //link_det_5g ++#endif ++#if defined(CONFIG_MCU_MESSAGE) ++ {0x004c, 0x0000004B}, //pkt_cnt_1724=0x4B ++ {0x0050, 0x0011FC00}, //ipc_base_addr ++#endif ++}; ++ ++u32 syscfg_tbl_masked[][3] = { ++ {0x40506024, 0x000000FF, 0x000000DF}, // for clk gate lp_level ++}; ++ ++u32 rf_tbl_masked[][3] = { ++ {0x40344058, 0x00800000, 0x00000000},// pll trx ++}; ++ ++static int aicwifi_sys_config(struct aic_sdio_dev *sdiodev) ++{ ++ int ret, cnt; ++ int syscfg_num = sizeof(syscfg_tbl_masked) / sizeof(u32) / 3; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, ++ syscfg_tbl_masked[cnt][0], syscfg_tbl_masked[cnt][1], syscfg_tbl_masked[cnt][2]); ++ if (ret) { ++ printk("%x mask write fail: %d\n", syscfg_tbl_masked[cnt][0], ret); ++ return ret; ++ } ++ } ++ ++ ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, ++ rf_tbl_masked[0][0], rf_tbl_masked[0][1], rf_tbl_masked[0][2]); ++ if (ret) { ++ printk("rf config %x write fail: %d\n", rf_tbl_masked[0][0], ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int aicwifi_patch_config(struct aic_sdio_dev *sdiodev) ++{ ++ const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0180; ++ u32 config_base; ++ uint32_t start_addr = 0x1e6000; ++ u32 patch_addr = start_addr; ++ u32 patch_num = sizeof(patch_tbl)/4; ++ struct dbg_mem_read_cfm rd_patch_addr_cfm; ++ u32 patch_addr_reg = 0x1e5318; ++ u32 patch_num_reg = 0x1e531c; ++ int ret = 0; ++ u16 cnt = 0; ++ int tmp_cnt = 0; ++ int adap_patch_num = 0; ++ ++ if (aicbsp_info.cpmode == AICBSP_CPMODE_TEST) { ++ patch_addr_reg = 0x1e5304; ++ patch_num_reg = 0x1e5308; ++ } ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch rd fail\n"); ++ return ret; ++ } ++ ++ config_base = rd_patch_addr_cfm.memdata; ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_addr_reg, patch_addr); ++ if (ret) { ++ printk("0x%x write fail\n", patch_addr_reg); ++ return ret; ++ } ++ ++ if(adap_test){ ++ printk("%s for adaptivity test \r\n", __func__); ++ adap_patch_num = sizeof(adaptivity_patch_tbl)/4; ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_num_reg, patch_num + adap_patch_num); ++ }else{ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_num_reg, patch_num); ++ } ++ if (ret) { ++ printk("0x%x write fail\n", patch_num_reg); ++ return ret; ++ } ++ ++ for (cnt = 0; cnt < patch_num/2; cnt += 1) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl[cnt][0]+config_base); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl[cnt][1]); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ return ret; ++ } ++ } ++ ++ tmp_cnt = cnt; ++ ++ if(adap_test){ ++ for(cnt = 0; cnt < adap_patch_num/2; cnt+=1) ++ { ++ if((ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*(cnt+tmp_cnt), adaptivity_patch_tbl[cnt][0]+config_base))) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ } ++ ++ if((ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*(cnt+tmp_cnt)+4, adaptivity_patch_tbl[cnt][1]))) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int aicwifi_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ #ifdef CONFIG_M2D_OTA_AUTO_SUPPORT ++ if (testmode == FW_M2D_OTA_MODE) { ++ rwnx_plat_m2d_flash_ota_android(sdiodev, FW_M2D_OTA_NAME); ++ } else if (testmode == FW_NORMAL_MODE) { ++ rwnx_plat_m2d_flash_ota_check(sdiodev, FW_M2D_OTA_NAME); ++ } ++ #endif ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { ++ printk("download wifi fw fail\n"); ++ return -1; ++ } ++ if (testmode == FW_NORMAL_MODE) { ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_PATCH_ADDR, RAM_FMAC_FW_PATCH_NAME)) { ++ printk("download wifi fw patch fail\n"); ++ return -1; ++ } ++ } ++ ++ if (aicwifi_patch_config(sdiodev)) { ++ printk("aicwifi_patch_config fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_sys_config(sdiodev)) { ++ printk("aicwifi_sys_config fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_start_from_bootrom(sdiodev)) { ++ printk("wifi start fail\n"); ++ return -1; ++ } ++ }else if (sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ printk("############ aicwifi_init begin \n"); ++ ++ system_config_8800dc(sdiodev); ++ printk("############ system_config_8800dc done\n"); ++ ++ ret = rwnx_plat_patch_load(sdiodev); ++ if (ret) { ++ printk("patch load return %d\n", ret); ++ return ret; ++ } ++ printk("############ rwnx_plat_patch_load done\n"); ++ ++ //rwnx_plat_userconfig_load(sdiodev); ++ ++ aicwf_patch_config_8800dc(sdiodev); ++ printk("############ aicwf_patch_config_8800dc done\n"); ++ ++ start_from_bootrom_8800DC(sdiodev); ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { ++ printk("8800d80 download wifi fw fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_patch_config_8800d80(sdiodev)) { ++ printk("aicwifi_patch_config_8800d80 fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_sys_config_8800d80(sdiodev)) { ++ printk("aicwifi_patch_config_8800d80 fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_start_from_bootrom(sdiodev)) { ++ printk("8800d80 wifi start fail\n"); ++ return -1; ++ } ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { ++ printk("8800d80x2 download wifi fw fail\n"); ++ return -1; ++ } ++ if (aicwifi_start_from_bootrom(sdiodev)) { ++ printk("8800d80x2 wifi start fail\n"); ++ return -1; ++ } ++ } ++ ++#if (defined(CONFIG_GPIO_WAKEUP) || defined(CONFIG_SDIO_PWRCTRL)) ++ if (aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 4)) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ return -1; ++ } ++#endif ++ return 0; ++} ++ ++u32 aicbsp_syscfg_tbl[][2] = { ++ {0x40500014, 0x00000101}, // 1) ++ {0x40500018, 0x00000109}, // 2) ++ {0x40500004, 0x00000010}, // 3) the order should not be changed ++ ++ // def CONFIG_PMIC_SETTING ++ // U02 bootrom only ++ {0x40040000, 0x00001AC8}, // 1) fix panic ++ {0x40040084, 0x00011580}, ++ {0x40040080, 0x00000001}, ++ {0x40100058, 0x00000000}, ++ ++ {0x50000000, 0x03220204}, // 2) pmic interface init ++ {0x50019150, 0x00000002}, // 3) for 26m xtal, set div1 ++ {0x50017008, 0x00000000}, // 4) stop wdg ++}; ++ ++static int aicbsp_system_config(struct aic_sdio_dev *sdiodev) ++{ ++ int syscfg_num = sizeof(aicbsp_syscfg_tbl) / sizeof(u32) / 2; ++ int ret, cnt; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl[cnt][0], aicbsp_syscfg_tbl[cnt][1]); ++ if (ret) { ++ sdio_err("%x write fail: %d\n", aicbsp_syscfg_tbl[cnt][0], ret); ++ return ret; ++ } ++ } ++ return 0; ++} ++ ++ ++ ++int aicbsp_platform_init(struct aic_sdio_dev *sdiodev) ++{ ++ rwnx_cmd_mgr_init(&sdiodev->cmd_mgr); ++ sdiodev->cmd_mgr.sdiodev = (void *)sdiodev; ++ ++ return 0; ++} ++ ++void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev) ++{ ++ (void)sdiodev; ++} ++ ++int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev) ++{ ++ u32 mem_addr; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ u32 btenable = 0; ++ u8 is_chip_id_h = 0; ++ int ret = 0; ++ ++ mem_addr = 0x40500000; ++ ++ testmode = aicbsp_info.cpmode; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)(rd_mem_addr_cfm.memdata >> 16); ++ btenable = 1; ++ ++ if (aicbsp_info.chip_rev != CHIP_REV_U02 && ++ aicbsp_info.chip_rev != CHIP_REV_U03 && ++ aicbsp_info.chip_rev != CHIP_REV_U04) { ++ pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ return -1; ++ } ++ ++ if (aicbsp_info.chip_rev != CHIP_REV_U02) ++ aicbsp_firmware_list = fw_u03; ++ ++ if (aicbsp_system_config(sdiodev)) ++ return -1; ++ } ++ else if (sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); ++ is_chip_id_h = (u8)(((rd_mem_addr_cfm.memdata >> 16) & 0xC0) == 0xC0); ++ ++ btenable = ((rd_mem_addr_cfm.memdata >> 26) & 0x1); ++ AICWFDBG(LOGINFO, "btenable = %d \n",btenable); ++ ++ if(btenable == 0){ ++ sdiodev->chipid = PRODUCT_ID_AIC8800DW; ++ AICWFDBG(LOGINFO, "AIC8800DC change to AIC8800DW \n"); ++ } ++ ++ if (aicbsp_info.chip_rev != CHIP_REV_U01 && ++ aicbsp_info.chip_rev != CHIP_REV_U02 && ++ aicbsp_info.chip_rev != CHIP_REV_U03 && ++ aicbsp_info.chip_rev != CHIP_REV_U04) { ++ pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ return -1; ++ } ++ if (is_chip_id_h) { ++ AICWFDBG(LOGINFO, "IS_CHIP_ID_H \n"); ++ aicbsp_firmware_list = fw_8800dc_h_u02; ++ } else { ++ if(aicbsp_info.chip_rev == CHIP_REV_U01){ ++ aicbsp_firmware_list = fw_8800dc_u01; ++ }else{ ++ aicbsp_firmware_list = fw_8800dc_u02; ++ } ++ } ++ } ++ else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); ++ is_chip_id_h = (u8)(((rd_mem_addr_cfm.memdata >> 16) & 0xC0) == 0xC0); ++ btenable = 1; ++ if (is_chip_id_h) { ++ AICWFDBG(LOGINFO, "IS_CHIP_ID_H \n"); ++ aicbsp_firmware_list = fw_8800d80_h_u02; ++ } else { ++ if (aicbsp_info.chip_rev == CHIP_REV_U01) ++ aicbsp_firmware_list = fw_8800d80_u01; ++ if (aicbsp_info.chip_rev == CHIP_REV_U02 || aicbsp_info.chip_rev == CHIP_REV_U03) ++ aicbsp_firmware_list = fw_8800d80_u02; ++ } ++ if (aicbsp_system_config_8800d80(sdiodev)) ++ return -1; ++ } ++ else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ btenable = 1; ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); ++ if (aicbsp_info.chip_rev >= (CHIP_REV_U04 + 8)) ++ aicbsp_firmware_list = fw_8800d80x2; ++ else{ ++ pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ return -1; ++ } ++ } ++ ++ AICWFDBG(LOGINFO, "aicbsp: %s, chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ ++ #ifndef CONFIG_MCU_MESSAGE ++ if (testmode != 4) { ++ if(btenable == 1){ ++ if (aicbt_init(sdiodev)) ++ return -1; ++ } ++ } ++ #endif ++ ++ ret = aicwifi_init(sdiodev); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path) ++{ ++ if (aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ feature->sdio_clock = FEATURE_SDIO_CLOCK; ++ }else if (aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800D80 || aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ feature->sdio_clock = FEATURE_SDIO_CLOCK_V3; ++ } ++ feature->sdio_phase = FEATURE_SDIO_PHASE; ++ feature->hwinfo = aicbsp_info.hwinfo; ++ feature->fwlog_en = aicbsp_info.fwlog_en; ++ feature->irqf = aicbsp_info.irqf; ++ if(fw_path != NULL){ ++ sprintf(fw_path,"%s", AICBSP_FW_PATH); ++ } ++ ++ sdio_dbg("%s, set FEATURE_SDIO_CLOCK %d MHz\n", __func__, feature->sdio_clock/1000000); ++ return 0; ++} ++ ++EXPORT_SYMBOL_GPL(aicbsp_get_feature); ++ ++#ifdef CONFIG_RESV_MEM_SUPPORT ++static struct skb_buff_pool resv_skb[] = { ++ {AIC_RESV_MEM_TXDATA, 1536*64, "resv_mem_txdata", 0, NULL}, ++}; ++ ++int aicbsp_resv_mem_init(void) ++{ ++ int i = 0; ++ printk("%s \n",__func__); ++ for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) { ++ resv_skb[i].skb = dev_alloc_skb(resv_skb[i].size); ++ } ++ return 0; ++} ++ ++int aicbsp_resv_mem_deinit(void) ++{ ++ int i = 0; ++ printk("%s \n",__func__); ++ for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) { ++ if (resv_skb[i].used == 0 && resv_skb[i].skb) ++ dev_kfree_skb(resv_skb[i].skb); ++ } ++ return 0; ++} ++ ++struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id) ++{ ++ if (resv_skb[id].size < length) { ++ pr_err("aicbsp: %s, no enough mem\n", __func__); ++ goto fail; ++ } ++ ++ if (resv_skb[id].used) { ++ pr_err("aicbsp: %s, mem in use\n", __func__); ++ goto fail; ++ } ++ ++ if (resv_skb[id].skb == NULL) { ++ pr_err("aicbsp: %s, mem not initialazed\n", __func__); ++ resv_skb[id].skb = dev_alloc_skb(resv_skb[id].size); ++ if (resv_skb[id].skb == NULL) { ++ pr_err("aicbsp: %s, mem reinitial still fail\n", __func__); ++ goto fail; ++ } ++ } ++ ++ printk("aicbsp: %s, alloc %s succuss, id: %d, size: %d\n", __func__, ++ resv_skb[id].name, resv_skb[id].id, resv_skb[id].size); ++ ++ resv_skb[id].used = 1; ++ return resv_skb[id].skb; ++ ++fail: ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(aicbsp_resv_mem_alloc_skb); ++ ++void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id) ++{ ++ resv_skb[id].used = 0; ++ printk("aicbsp: %s, free %s succuss, id: %d, size: %d\n", __func__, ++ resv_skb[id].name, resv_skb[id].id, resv_skb[id].size); ++} ++EXPORT_SYMBOL_GPL(aicbsp_resv_mem_kfree_skb); ++ ++#else ++ ++int aicbsp_resv_mem_init(void) ++{ ++ return 0; ++} ++ ++int aicbsp_resv_mem_deinit(void) ++{ ++ return 0; ++} ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h +new file mode 100644 +index 000000000000..f18253d168a3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h +@@ -0,0 +1,598 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.h ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _AIC_BSP_DRIVER_H ++#define _AIC_BSP_DRIVER_H ++ ++#include ++#include ++#include ++#include "aic_bsp_export.h" ++ ++#define RWNX_80211_CMD_TIMEOUT_MS 6000//500//300 ++ ++#define RWNX_CMD_FLAG_NONBLOCK BIT(0) ++#define RWNX_CMD_FLAG_REQ_CFM BIT(1) ++#define RWNX_CMD_FLAG_WAIT_PUSH BIT(2) ++#define RWNX_CMD_FLAG_WAIT_ACK BIT(3) ++#define RWNX_CMD_FLAG_WAIT_CFM BIT(4) ++#define RWNX_CMD_FLAG_DONE BIT(5) ++/* ATM IPC design makes it possible to get the CFM before the ACK, ++ * otherwise this could have simply been a state enum */ ++#define RWNX_CMD_WAIT_COMPLETE(flags) \ ++ (!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM))) ++ ++#define RWNX_CMD_MAX_QUEUED 8 ++ ++#define IPC_E2A_MSG_PARAM_SIZE 256 ++ ++#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ ++ ++/* message levels */ ++#define LOGERROR 0x0001 ++#define LOGINFO 0x0002 ++#define LOGTRACE 0x0004 ++#define LOGDEBUG 0x0008 ++#define LOGDATA 0x0010 ++ ++extern int aicwf_dbg_level_bsp; ++ ++#define AICWF_LOG "AICWFDBG(" ++ ++#define AICWFDBG(level, args, arg...) \ ++do { \ ++ if (aicwf_dbg_level_bsp & level) { \ ++ printk(AICWF_LOG#level")\t" args, ##arg); \ ++ } \ ++} while (0) ++ ++#define RWNX_DBG(fmt, ...) \ ++do { \ ++ if (aicwf_dbg_level_bsp & LOGTRACE) { \ ++ printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \ ++ } \ ++} while (0) ++ ++/// Message structure for MSGs from Emb to App ++struct ipc_e2a_msg { ++ u16 id; ///< Message id. ++ u16 dummy_dest_id; ++ u16 dummy_src_id; ++ u16 param_len; ///< Parameter embedded struct length. ++ u32 pattern; ///< Used to stamp a valid MSG buffer ++ u32 param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++typedef u16 lmac_msg_id_t; ++typedef u16 lmac_task_id_t; ++ ++struct lmac_msg { ++ lmac_msg_id_t id; ///< Message id. ++ lmac_task_id_t dest_id; ///< Destination kernel identifier. ++ lmac_task_id_t src_id; ///< Source kernel identifier. ++ u16 param_len; ///< Parameter embedded struct length. ++ u32 param[]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++#define rwnx_cmd_e2amsg ipc_e2a_msg ++#define rwnx_cmd_a2emsg lmac_msg ++#define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len) ++#define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4) ++ ++static inline void put_u16(u8 *buf, u16 data) ++{ ++ buf[0] = (u8)(data&0x00ff); ++ buf[1] = (u8)((data >> 8)&0x00ff); ++} ++ ++enum rwnx_cmd_mgr_state { ++ RWNX_CMD_MGR_STATE_DEINIT, ++ RWNX_CMD_MGR_STATE_INITED, ++ RWNX_CMD_MGR_STATE_CRASHED, ++}; ++ ++struct rwnx_cmd { ++ struct list_head list; ++ lmac_msg_id_t id; ++ lmac_msg_id_t reqid; ++ struct rwnx_cmd_a2emsg *a2e_msg; ++ char *e2a_msg; ++ u32 tkn; ++ u16 flags; ++ struct completion complete; ++ u32 result; ++}; ++ ++struct aic_sdio_dev; ++struct rwnx_cmd; ++typedef int (*msg_cb_fct)(struct rwnx_cmd *cmd, struct rwnx_cmd_e2amsg *msg); ++ ++struct rwnx_cmd_mgr { ++ enum rwnx_cmd_mgr_state state; ++ spinlock_t lock; ++ u32 next_tkn; ++ u32 queue_sz; ++ u32 max_queue_sz; ++ spinlock_t cb_lock; ++ void *sdiodev; ++ ++ struct list_head cmds; ++ ++ int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct); ++ void (*print)(struct rwnx_cmd_mgr *); ++ void (*drain)(struct rwnx_cmd_mgr *); ++ ++ struct work_struct cmdWork; ++ struct workqueue_struct *cmd_wq; ++}; ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr); ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr); ++int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd); ++void rwnx_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len); ++ ++enum { ++ TASK_NONE = (u8) -1, ++ ++ // MAC Management task. ++ TASK_MM = 0, ++ // DEBUG task ++ TASK_DBG, ++ /// SCAN task ++ TASK_SCAN, ++ /// TDLS task ++ TASK_TDLS, ++ /// SCANU task ++ TASK_SCANU, ++ /// ME task ++ TASK_ME, ++ /// SM task ++ TASK_SM, ++ /// APM task ++ TASK_APM, ++ /// BAM task ++ TASK_BAM, ++ /// MESH task ++ TASK_MESH, ++ /// RXU task ++ TASK_RXU, ++ // This is used to define the last task that is running on the EMB processor ++ TASK_LAST_EMB = TASK_RXU, ++ ++ // nX API task ++ TASK_API, ++ TASK_MAX, ++}; ++ ++#define LMAC_FIRST_MSG(task) ((lmac_msg_id_t)((task) << 10)) ++#define DRV_TASK_ID 100 ++#define MSG_I(msg) ((msg) & ((1<<10)-1)) ++#define MSG_T(msg) ((lmac_task_id_t)((msg) >> 10)) ++ ++enum dbg_msg_tag { ++ /// Memory read request ++ DBG_MEM_READ_REQ = LMAC_FIRST_MSG(TASK_DBG), ++ /// Memory read confirm ++ DBG_MEM_READ_CFM, ++ /// Memory write request ++ DBG_MEM_WRITE_REQ, ++ /// Memory write confirm ++ DBG_MEM_WRITE_CFM, ++ /// Module filter request ++ DBG_SET_MOD_FILTER_REQ, ++ /// Module filter confirm ++ DBG_SET_MOD_FILTER_CFM, ++ /// Severity filter request ++ DBG_SET_SEV_FILTER_REQ, ++ /// Severity filter confirm ++ DBG_SET_SEV_FILTER_CFM, ++ /// LMAC/MAC HW fatal error indication ++ DBG_ERROR_IND, ++ /// Request to get system statistics ++ DBG_GET_SYS_STAT_REQ, ++ /// COnfirmation of system statistics ++ DBG_GET_SYS_STAT_CFM, ++ /// Memory block write request ++ DBG_MEM_BLOCK_WRITE_REQ, ++ /// Memory block write confirm ++ DBG_MEM_BLOCK_WRITE_CFM, ++ /// Start app request ++ DBG_START_APP_REQ, ++ /// Start app confirm ++ DBG_START_APP_CFM, ++ /// Start npc request ++ DBG_START_NPC_REQ, ++ /// Start npc confirm ++ DBG_START_NPC_CFM, ++ /// Memory mask write request ++ DBG_MEM_MASK_WRITE_REQ, ++ /// Memory mask write confirm ++ DBG_MEM_MASK_WRITE_CFM, ++ ++ DBG_RFTEST_CMD_REQ, ++ DBG_RFTEST_CMD_CFM, ++ DBG_BINDING_REQ, ++ DBG_BINDING_CFM, ++ DBG_BINDING_IND, ++ ++ DBG_CUSTOM_MSG_REQ, ++ DBG_CUSTOM_MSG_CFM, ++ DBG_CUSTOM_MSG_IND, ++ ++ DBG_GPIO_WRITE_REQ, ++ DBG_GPIO_WRITE_CFM, ++ ++ ++ /// Max number of Debug messages ++ DBG_MAX, ++}; ++ ++#if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++#define FW_M2D_OTA_NAME "m2d_ota.bin" ++#else ++#define FW_M2D_OTA_NAME "m2d_ota_lzma.bin" ++#endif ++ ++enum { ++ HOST_START_APP_AUTO = 1, ++ HOST_START_APP_CUSTOM, ++ HOST_START_APP_FNCALL = 4, ++ HOST_START_APP_DUMMY = 5, ++}; ++ ++ ++struct dbg_mem_block_write_req { ++ u32 memaddr; ++ u32 memsize; ++ u32 memdata[1024 / sizeof(u32)]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_CFM message. ++struct dbg_mem_block_write_cfm { ++ u32 wstatus; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_REQ message. ++struct dbg_mem_write_req { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_CFM message. ++struct dbg_mem_write_cfm { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_REQ message. ++struct dbg_mem_read_req { ++ u32 memaddr; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_CFM message. ++struct dbg_mem_read_cfm { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_REQ message. ++struct dbg_mem_mask_write_req { ++ u32 memaddr; ++ u32 memmask; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_CFM message. ++struct dbg_mem_mask_write_cfm { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_REQ message. ++struct dbg_start_app_req { ++ u32 bootaddr; ++ u32 boottype; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_CFM message. ++struct dbg_start_app_cfm { ++ u32 bootstatus; ++}; ++ ++int aicwf_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev); ++int aicwf_plat_rftest_load_8800dc(struct aic_sdio_dev *sdiodev); ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++int aicwf_misc_ram_valid_check_8800dc(struct aic_sdio_dev *sdiodev, int *valid_out); ++int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev); ++#endif ++ ++int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device); ++int aicwf_patch_table_load(struct aic_sdio_dev *rwnx_hw, char *filename); ++ ++int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm); ++int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_size, u32 *mem_data); ++int rwnx_send_dbg_mem_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_data); ++int rwnx_send_dbg_mem_mask_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_mask, u32 mem_data); ++int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm); ++ ++int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, const char *filename); ++ ++void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg); ++int aicbsp_platform_init(struct aic_sdio_dev *sdiodev); ++void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev); ++int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev); ++#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++int is_file_exist(char* name); ++#endif ++int aicbsp_resv_mem_init(void); ++int aicbsp_resv_mem_deinit(void); ++ ++#define AICBSP_FW_PATH CONFIG_AIC_FW_PATH ++#define AICBSP_FW_PATH_MAX 200 ++ ++#define RAM_FMAC_FW_ADDR 0x00120000 ++#define RAM_FMAC_FW_PATCH_ADDR 0x00190000 ++#define FW_RAM_ADID_BASE_ADDR 0x00161928 ++#define FW_RAM_ADID_BASE_ADDR_U03 0x00161928 ++#define FW_RAM_PATCH_BASE_ADDR 0x00100000 ++#define RAM_8800DC_U01_ADID_ADDR 0x00101788 ++#define RAM_8800DC_U02_ADID_ADDR 0x001017d8 ++#define RAM_8800DC_FW_PATCH_ADDR 0x00184000 ++#define FW_RESET_START_ADDR 0x40500128 ++#define FW_RESET_START_VAL 0x40 ++#define FW_ADID_FLAG_ADDR 0x40500150 ++#define FW_ADID_FLAG_VAL 0x01 ++#define FW_RAM_ADID_BASE_ADDR_8800D80 0x002017E0 ++#define FW_RAM_PATCH_BASE_ADDR_8800D80 0x0020B2B0 ++#define FW_RAM_ADID_BASE_ADDR_8800D80_U02 0x00201940 ++#define FW_RAM_PATCH_BASE_ADDR_8800D80_U02 0x0020b43c ++ ++#define AICBT_PT_TAG "AICBT_PT_TAG" ++ ++ ++/***************************************************************************** ++ * Addresses within RWNX_ADDR_CPU ++ *****************************************************************************/ ++#define RAM_LMAC_FW_ADDR 0x00150000 ++ ++#define ROM_FMAC_FW_ADDR 0x00010000 ++#define ROM_FMAC_PATCH_ADDR 0x00180000 ++ ++#define RAM_FMAC_FW_PATCH_NAME "fmacfw_patch.bin" ++#define RWNX_MAC_CALIB_BASE_NAME_8800DC "fmacfw_calib_8800dc" ++#define RWNX_MAC_CALIB_NAME_8800DC_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_u02.bin" ++#ifdef CONFIG_SDIO_BT ++#define RWNX_MAC_CALIB_NAME_8800DC_H_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_hbt_u02.bin" ++#else ++#define RWNX_MAC_CALIB_NAME_8800DC_H_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_h_u02.bin" ++#endif ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++#define ROM_FMAC_CALIB_ADDR 0x00130000 ++#endif ++#ifdef CONFIG_DPD ++#ifndef CONFIG_FORCE_DPD_CALIB ++#define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_lite_8800dc.bin" ++#endif ++#endif ++ ++#define RWNX_MAC_FW_RF_BASE_NAME_8800DC "lmacfw_rf_8800dc.bin" ++ ++#ifdef CONFIG_FOR_IPCOM ++#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc_ipc" ++#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin" ++#else ++#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc" ++#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin" ++#define RWNX_MAC_PATCH_NAME2_8800DC_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_u02.bin" ++#ifdef CONFIG_SDIO_BT ++#define RWNX_MAC_PATCH_NAME2_8800DC_H_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_hbt_u02.bin" ++#else ++#define RWNX_MAC_PATCH_NAME2_8800DC_H_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_h_u02.bin" ++#endif ++#endif ++ ++#define RWNX_MAC_PATCH_TABLE_NAME_8800DC "fmacfw_patch_tbl_8800dc" ++#define RWNX_MAC_PATCH_TABLE_8800DC RWNX_MAC_PATCH_TABLE_NAME_8800DC ".bin" ++#define RWNX_MAC_PATCH_TABLE_8800DC_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_u02.bin" ++#ifdef CONFIG_SDIO_BT ++#define RWNX_MAC_PATCH_TABLE_8800DC_H_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_hbt_u02.bin" ++#else ++#define RWNX_MAC_PATCH_TABLE_8800DC_H_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_h_u02.bin" ++#endif ++ ++#define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc" ++#define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin" ++#define FW_USERCONFIG_NAME_8800DC "aic_userconfig_8800dc.txt" ++ ++enum { ++ FW_NORMAL_MODE = 0, ++ FW_RFTEST_MODE = 1, ++ FW_BLE_SCAN_WAKEUP_MODE = 2, ++ FW_M2D_OTA_MODE = 3, ++ FW_DPDCALIB_MODE = 4, ++ FW_BLE_SCAN_AD_FILTER_MODE = 5, ++}; ++ ++enum aicbt_patch_table_type { ++ AICBT_PT_INF = 0x00, ++ AICBT_PT_TRAP = 0x1, ++ AICBT_PT_B4, ++ AICBT_PT_BTMODE, ++ AICBT_PT_PWRON, ++ AICBT_PT_AF, ++ AICBT_PT_VER, ++}; ++ ++enum aicbt_btport_type { ++ AICBT_BTPORT_NULL, ++ AICBT_BTPORT_MB, ++ AICBT_BTPORT_UART, ++}; ++ ++/* btmode ++ * used for force bt mode,if not AICBSP_MODE_NULL ++ * efuse valid and vendor_info will be invalid, even has beed set valid ++*/ ++enum aicbt_btmode_type { ++ AICBT_BTMODE_BT_ONLY_SW = 0x0, // bt only mode with switch ++ AICBT_BTMODE_BT_WIFI_COMBO, // wifi/bt combo mode ++ AICBT_BTMODE_BT_ONLY, // bt only mode without switch ++ AICBT_BTMODE_BT_ONLY_TEST, // bt only test mode ++ AICBT_BTMODE_BT_WIFI_COMBO_TEST, // wifi/bt combo test mode ++ AICBT_BTMODE_BT_ONLY_COANT, // bt only mode with no external switch ++ AICBT_MODE_NULL = 0xFF, // invalid value ++}; ++ ++/* uart_baud ++ * used for config uart baud when btport set to uart, ++ * otherwise meaningless ++*/ ++enum aicbt_uart_baud_type { ++ AICBT_UART_BAUD_115200 = 115200, ++ AICBT_UART_BAUD_921600 = 921600, ++ AICBT_UART_BAUD_1_5M = 1500000, ++ AICBT_UART_BAUD_3_25M = 3250000, ++}; ++ ++enum aicbt_uart_flowctrl_type { ++ AICBT_UART_FLOWCTRL_DISABLE = 0x0, // uart without flow ctrl ++ AICBT_UART_FLOWCTRL_ENABLE, // uart with flow ctrl ++}; ++ ++enum aicbsp_cpmode_type { ++ AICBSP_CPMODE_WORK, ++ AICBSP_CPMODE_TEST, ++ AICBSP_CPMODE_MAX, ++}; ++ ++enum chip_rev { ++ CHIP_REV_U01 = 1, ++ CHIP_REV_U02 = 3, ++ CHIP_REV_U03 = 7, ++ CHIP_REV_U04 = 7, ++}; ++ ++#define AIC_M2D_OTA_INFO_ADDR 0x88000020 ++#define AIC_M2D_OTA_DATA_ADDR 0x88000040 ++#if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++#define AIC_M2D_OTA_FLASH_ADDR 0x08004000 ++#define AIC_M2D_OTA_CODE_START_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x0188) ++#define AIC_M2D_OTA_VER_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x018C) ++#else ++#define AIC_M2D_OTA_FLASH_ADDR 0x08005000 ++#define AIC_M2D_OTA_CODE_START_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x1188) ++#define AIC_M2D_OTA_VER_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x0010) ++#endif ++///aic bt tx pwr lvl :lsb->msb: first byte, min pwr lvl; second byte, max pwr lvl; ++///pwr lvl:20(min), 30 , 40 , 50 , 60(max) ++#define AICBT_TXPWR_LVL 0x00006020 ++#define AICBT_TXPWR_LVL_8800dc 0x00006f2f ++#define AICBT_TXPWR_LVL_8800d80 0x00006f2f ++#define AICBT_TXPWR_LVL_8800d80x2 0x00006f2f ++ ++ ++#define AICBSP_HWINFO_DEFAULT (-1) ++#define AICBSP_CPMODE_DEFAULT AICBSP_CPMODE_WORK ++#define AICBSP_FWLOG_EN_DEFAULT 0 ++ ++#define AICBT_BTMODE_DEFAULT_8800d80x2 AICBT_BTMODE_BT_ONLY_COANT ++#define AICBT_BTMODE_DEFAULT_8800d80 AICBT_BTMODE_BT_ONLY_COANT ++#define AICBT_BTMODE_DEFAULT AICBT_BTMODE_BT_ONLY_SW ++#ifdef CONFIG_SDIO_BT ++#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_MB ++#else ++#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_UART ++#endif ++#define AICBT_UART_BAUD_DEFAULT AICBT_UART_BAUD_1_5M ++#define AICBT_UART_FC_DEFAULT AICBT_UART_FLOWCTRL_ENABLE ++#define AICBT_LPM_ENABLE_DEFAULT 0 ++#define AICBT_TXPWR_LVL_DEFAULT AICBT_TXPWR_LVL ++#define AICBT_TXPWR_LVL_DEFAULT_8800dc AICBT_TXPWR_LVL_8800dc ++#define AICBT_TXPWR_LVL_DEFAULT_8800d80 AICBT_TXPWR_LVL_8800d80 ++#define AICBT_TXPWR_LVL_DEFAULT_8800d80x2 AICBT_TXPWR_LVL_8800d80x2 ++ ++ ++#define FEATURE_SDIO_CLOCK 50000000 // 0: default, other: target clock rate ++#define FEATURE_SDIO_CLOCK_V3 150000000 // 0: default, other: target clock rate ++#define FEATURE_SDIO_PHASE 2 // 0: default, 2: 180° ++ ++struct aicbt_patch_table { ++ char *name; ++ uint32_t type; ++ uint32_t *data; ++ uint32_t len; ++ struct aicbt_patch_table *next; ++}; ++ ++struct aicbt_info_t { ++ uint32_t btmode; ++ uint32_t btport; ++ uint32_t uart_baud; ++ uint32_t uart_flowctrl; ++ uint32_t lpm_enable; ++ uint32_t txpwr_lvl; ++}; ++ ++struct aicbt_patch_info_t { ++ uint32_t info_len; ++//base len start ++ uint32_t adid_addrinf; ++ uint32_t addr_adid; ++ uint32_t patch_addrinf; ++ uint32_t addr_patch; ++ uint32_t reset_addr; ++ uint32_t reset_val; ++ uint32_t adid_flag_addr; ++ uint32_t adid_flag; ++//base len end ++//ext patch nb ++ uint32_t ext_patch_nb_addr; ++ uint32_t ext_patch_nb; ++ uint32_t *ext_patch_param; ++}; ++ ++struct aicbsp_firmware { ++ const char *desc; ++ const char *bt_adid; ++ const char *bt_patch; ++ const char *bt_table; ++ const char *wl_fw; ++ const char *bt_ext_patch; ++}; ++ ++struct aicbsp_info_t { ++ int hwinfo; ++ int hwinfo_r; ++ uint32_t cpmode; ++ uint32_t chip_rev; ++ bool fwlog_en; ++ uint8_t irqf; ++}; ++ ++extern struct aicbsp_info_t aicbsp_info; ++extern struct mutex aicbsp_power_lock; ++extern const struct aicbsp_firmware *aicbsp_firmware_list; ++extern const struct aicbsp_firmware fw_u02[]; ++extern const struct aicbsp_firmware fw_u03[]; ++extern const struct aicbsp_firmware fw_8800dc_u01[]; ++extern const struct aicbsp_firmware fw_8800dc_u02[]; ++extern const struct aicbsp_firmware fw_8800dc_h_u02[]; ++extern const struct aicbsp_firmware fw_8800d80_u01[]; ++extern const struct aicbsp_firmware fw_8800d80_u02[]; ++extern const struct aicbsp_firmware fw_8800d80_h_u02[]; ++extern const struct aicbsp_firmware fw_8800d80x2[]; ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h +new file mode 100644 +index 000000000000..5535df6e0d14 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h +@@ -0,0 +1,71 @@ ++#ifndef __AIC_BSP_EXPORT_H ++#define __AIC_BSP_EXPORT_H ++ ++enum aicbsp_subsys { ++ AIC_BLUETOOTH, ++ AIC_WIFI, ++}; ++ ++enum aicbsp_pwr_state { ++ AIC_PWR_OFF, ++ AIC_PWR_ON, ++}; ++ ++enum skb_buff_id { ++ AIC_RESV_MEM_TXDATA, ++}; ++ ++struct skb_buff_pool { ++ uint32_t id; ++ uint32_t size; ++ const char *name; ++ uint8_t used; ++ struct sk_buff *skb; ++}; ++ ++struct aicbsp_feature_t { ++ int hwinfo; ++ uint32_t sdio_clock; ++ uint8_t sdio_phase; ++ bool fwlog_en; ++ uint8_t irqf; ++}; ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++typedef struct { ++ uint32_t bit_mask[3]; ++ uint32_t reserved; ++ uint32_t dpd_high[96]; ++ uint32_t dpd_11b[96]; ++ uint32_t dpd_low[96]; ++ uint32_t idac_11b[48]; ++ uint32_t idac_high[48]; ++ uint32_t idac_low[48]; ++ uint32_t loft_res[18]; ++ uint32_t rx_iqim_res[16]; ++} rf_misc_ram_t; ++ ++typedef struct { ++ uint32_t bit_mask[4]; ++ uint32_t dpd_high[96]; ++ uint32_t loft_res[18]; ++} rf_misc_ram_lite_t; ++ ++#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) ++#define DPD_RESULT_SIZE_8800DC sizeof(rf_misc_ram_lite_t) ++#endif ++ ++#ifdef CONFIG_DPD ++extern rf_misc_ram_lite_t dpd_res; ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++extern rf_misc_ram_lite_t loft_res_local; ++#endif ++ ++int aicbsp_set_subsys(int, int); ++int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path); ++struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id); ++void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c +new file mode 100644 +index 000000000000..406781997f6f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c +@@ -0,0 +1,456 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aic_bsp_driver.h" ++#include "rwnx_version_gen.h" ++#include "aicwf_txq_prealloc.h" ++ ++ ++#define DRV_DESCRIPTION "AIC BSP" ++#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi" ++#define DRV_AUTHOR "AICSemi" ++#define DRV_VERS_MOD "1.0" ++ ++int aicwf_dbg_level_bsp = LOGERROR; ++ ++struct semaphore aicbsp_probe_semaphore; ++ ++static struct platform_device *aicbsp_pdev; ++ ++const struct aicbsp_firmware *aicbsp_firmware_list = fw_u02; ++ ++const struct aicbsp_firmware fw_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(sdio u02)", ++ .bt_adid = "fw_adid.bin", ++ .bt_patch = "fw_patch.bin", ++ .bt_table = "fw_patch_table.bin", ++ #ifdef CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt.bin" ++ #else ++ .wl_fw = "fmacfw.bin" ++ #endif ++ }, ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(sdio u02)", ++ .bt_adid = "fw_adid.bin", ++ .bt_patch = "fw_patch.bin", ++ .bt_table = "fw_patch_table.bin", ++ .wl_fw = "fmacfw_rf.bin" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_u03[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(sdio u03/u04)", ++ .bt_adid = "fw_adid_u03.bin", ++ .bt_patch = "fw_patch_u03.bin", ++ .bt_table = "fw_patch_table_u03.bin", ++ #ifdef CONFIG_MCU_MESSAGE ++ .wl_fw = "fmacfw_8800m_custmsg.bin" ++ #elif defined(CONFIG_SDIO_BT) ++ .wl_fw = "fmacfwbt.bin" ++ #else ++ .wl_fw = "fmacfw.bin" ++ #endif ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(sdio u03/u04)", ++ .bt_adid = "fw_adid_u03.bin", ++ .bt_patch = "fw_patch_u03.bin", ++ .bt_table = "fw_patch_table_u03.bin", ++ .wl_fw = "fmacfw_rf.bin" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800dc_u01[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(sdio u01)", ++ .bt_adid = "fw_adid_8800dc.bin", ++ .bt_patch = "fw_patch_8800dc.bin", ++ .bt_table = "fw_patch_table_8800dc.bin", ++ .wl_fw = "fmacfw_8800dc.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(sdio u01)", ++ .bt_adid = "fw_adid_8800dc.bin", ++ .bt_patch = "fw_patch_8800dc.bin", ++ .bt_table = "fw_patch_table_8800dc.bin", ++ .wl_fw = "fmacfw_rf_8800dc.bin" ++ }, ++}; ++ ++ ++const struct aicbsp_firmware fw_8800dc_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800dc sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02.bin", ++ .bt_patch = "fw_patch_8800dc_u02.bin", ++ .bt_table = "fw_patch_table_8800dc_u02.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02_ext", ++ .wl_fw = "fmacfw_patch_8800dc_u02.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800dc sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02.bin", ++ .bt_patch = "fw_patch_8800dc_u02.bin", ++ .bt_table = "fw_patch_table_8800dc_u02.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02_ext", ++ .wl_fw = "lmacfw_rf_8800dc.bin" //u01,u02 lmacfw load same bin ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800dc_h_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800dc_h sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02h.bin", ++ .bt_patch = "fw_patch_8800dc_u02h.bin", ++ .bt_table = "fw_patch_table_8800dc_u02h.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02h_ext", ++ .wl_fw = "fmacfw_patch_8800dc_h_u02.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800dc_h sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02h.bin", ++ .bt_patch = "fw_patch_8800dc_u02h.bin", ++ .bt_table = "fw_patch_table_8800dc_u02h.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02h_ext", ++ .wl_fw = "lmacfw_rf_8800dc.bin" //u01,u02 lmacfw load same bin ++ }, ++}; ++ ++ ++const struct aicbsp_firmware fw_8800d80_u01[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80 sdio u01)", ++ .bt_adid = "fw_adid_8800d80.bin", ++ .bt_patch = "fw_patch_8800d80.bin", ++ .bt_table = "fw_patch_table_8800d80.bin", ++ .wl_fw = "fmacfw_8800d80.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80 sdio u01)", ++ .bt_adid = "fw_adid_8800d80.bin", ++ .bt_patch = "fw_patch_8800d80.bin", ++ .bt_table = "fw_patch_table_8800d80.bin", ++ .wl_fw = "lmacfw_rf_8800d80.bin" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800d80_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80 sdio u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ #if defined CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_u02.bin", ++ #elif defined CONFIG_FOR_IPCAM ++ .wl_fw = "fmacfw_8800d80_u02_ipc.bin", ++ #else ++ .wl_fw = "fmacfw_8800d80_u02.bin", ++ #endif ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80 sdio u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ .wl_fw = "lmacfw_rf_8800d80_u02.bin", ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800d80_h_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80 sdio h_u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ #if defined CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_h_u02.bin", ++ #elif defined CONFIG_FOR_IPCAM ++ .wl_fw = "fmacfw_8800d80_h_u02_ipc.bin", ++ #else ++ .wl_fw = "fmacfw_8800d80_h_u02.bin", ++ #endif ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80 sdio u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ .wl_fw = "lmacfw_rf_8800d80_u02.bin", ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800d80x2[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80x2 sdio)", ++ .bt_adid = "fw_adid_8800d80x2_u05.bin", ++ .bt_patch = "fw_patch_8800d80x2_u05.bin", ++ .bt_table = "fw_patch_table_8800d80x2_u05.bin", ++ #ifdef CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_h_u02.bin", ++ #else ++ .wl_fw = "fmacfw_8800d80x2.bin", ++ #endif ++ .bt_ext_patch = "fw_patch_8800d80x2_u05_ext" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80x2 sdio)", ++ .bt_adid = "fw_adid_8800d80x2_u05.bin", ++ .bt_patch = "fw_patch_8800d80x2_u05.bin", ++ .bt_table = "fw_patch_table_8800d80x2_u05.bin", ++ .wl_fw = "lmacfw_rf_8800d80x2.bin", ++ .bt_ext_patch = "fw_patch_8800d80x2_u05_ext" ++ }, ++}; ++ ++struct aicbsp_info_t aicbsp_info = { ++ .hwinfo_r = AICBSP_HWINFO_DEFAULT, ++ .hwinfo = AICBSP_HWINFO_DEFAULT, ++ .cpmode = AICBSP_CPMODE_DEFAULT, ++ .fwlog_en = AICBSP_FWLOG_EN_DEFAULT, ++#ifdef CONFIG_IRQ_FALL ++ .irqf = 1, ++#else ++ .irqf = 0, ++#endif ++}; ++ ++struct mutex aicbsp_power_lock; ++ ++static struct platform_driver aicbsp_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "aic_bsp", ++ }, ++ //.probe = aicbsp_probe, ++ //.remove = aicbsp_remove, ++}; ++ ++static ssize_t cpmode_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t count = 0; ++ uint8_t i = 0; ++ ++ count += sprintf(&buf[count], "Support mode value:\n"); ++ ++ for (i = 0; i < AICBSP_CPMODE_MAX; i++) { ++ if (aicbsp_firmware_list[i].desc) ++ count += sprintf(&buf[count], " %2d: %s\n", i, aicbsp_firmware_list[i].desc); ++ } ++ ++ count += sprintf(&buf[count], "Current: %d, firmware info:\n", aicbsp_info.cpmode); ++ count += sprintf(&buf[count], " BT ADID : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid); ++ count += sprintf(&buf[count], " BT PATCH: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch); ++ count += sprintf(&buf[count], " BT TABLE: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_table); ++ count += sprintf(&buf[count], " WIFI FW : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw); ++ return count; ++} ++ ++static ssize_t cpmode_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ int err = kstrtoul(buf, 0, &val); ++ if (err) ++ return err; ++ ++ if (val >= AICBSP_CPMODE_MAX) { ++ pr_err("mode value must less than %d\n", AICBSP_CPMODE_MAX); ++ return -EINVAL; ++ } ++ ++ aicbsp_info.cpmode = val; ++ printk("%s, set mode to: %lu[%s] done\n", __func__, val, aicbsp_firmware_list[val].desc); ++ ++ return count; ++} ++ ++static ssize_t hwinfo_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t count = 0; ++ ++ count += sprintf(&buf[count], "chip hw rev: "); ++ if (aicbsp_info.hwinfo_r < 0) ++ count += sprintf(&buf[count], "-1(not avalible)\n"); ++ else ++ count += sprintf(&buf[count], "0x%02X\n", aicbsp_info.chip_rev); ++ ++ count += sprintf(&buf[count], "hwinfo read: "); ++ if (aicbsp_info.hwinfo_r < 0) ++ count += sprintf(&buf[count], "%d(not avalible), ", aicbsp_info.hwinfo_r); ++ else ++ count += sprintf(&buf[count], "0x%02X, ", aicbsp_info.hwinfo_r); ++ ++ if (aicbsp_info.hwinfo < 0) ++ count += sprintf(&buf[count], "set: %d(not avalible)\n", aicbsp_info.hwinfo); ++ else ++ count += sprintf(&buf[count], "set: 0x%02X\n", aicbsp_info.hwinfo); ++ ++ return count; ++} ++ ++static ssize_t hwinfo_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ long val; ++ int err = kstrtol(buf, 0, &val); ++ ++ if (err) { ++ pr_err("invalid input\n"); ++ return err; ++ } ++ ++ if ((val == -1) || (val >= 0 && val <= 0xFF)) { ++ aicbsp_info.hwinfo = val; ++ } else { ++ pr_err("invalid values\n"); ++ return -EINVAL; ++ } ++ return count; ++} ++ ++static ssize_t fwdebug_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t count = 0; ++ ++ count += sprintf(&buf[count], "fw log status: %s\n", ++ aicbsp_info.fwlog_en ? "on" : "off"); ++ ++ return count; ++} ++ ++static ssize_t fwdebug_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ long val; ++ int err = kstrtol(buf, 0, &val); ++ ++ if (err) { ++ pr_err("invalid input\n"); ++ return err; ++ } ++ ++ if (val > 1 || val < 0) { ++ pr_err("must be 0 or 1\n"); ++ return -EINVAL; ++ } ++ ++ aicbsp_info.fwlog_en = val; ++ return count; ++} ++ ++static DEVICE_ATTR(cpmode, S_IRUGO | S_IWUSR, ++ cpmode_show, cpmode_store); ++ ++static DEVICE_ATTR(hwinfo, S_IRUGO | S_IWUSR, ++ hwinfo_show, hwinfo_store); ++ ++static DEVICE_ATTR(fwdebug, S_IRUGO | S_IWUSR, ++ fwdebug_show, fwdebug_store); ++ ++static struct attribute *aicbsp_attributes[] = { ++ &dev_attr_cpmode.attr, ++ &dev_attr_hwinfo.attr, ++ &dev_attr_fwdebug.attr, ++ NULL, ++}; ++ ++static struct attribute_group aicbsp_attribute_group = { ++ .name = "aicbsp_info", ++ .attrs = aicbsp_attributes, ++}; ++ ++int testmode = AICBSP_CPMODE_DEFAULT; ++int adap_test = 0; ++module_param(testmode, int, 0660); ++module_param(adap_test, int, 0660); ++ ++ ++static int __init aicbsp_init(void) ++{ ++ int ret; ++ printk("%s\n", __func__); ++ printk("RELEASE_DATE:%s\r\n", RELEASE_DATE); ++ ++ aicbsp_info.cpmode = testmode; ++ ++ aicbsp_resv_mem_init(); ++ ++ sema_init(&aicbsp_probe_semaphore, 0); ++ ++ ret = platform_driver_register(&aicbsp_driver); ++ if (ret) { ++ pr_err("register platform driver failed: %d\n", ret); ++ return ret; ++ } ++ ++ aicbsp_pdev = platform_device_alloc("aic-bsp", -1); ++ ret = platform_device_add(aicbsp_pdev); ++ if (ret) { ++ pr_err("register platform device failed: %d\n", ret); ++ return ret; ++ } ++ ++ ret = sysfs_create_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group); ++ if (ret) { ++ pr_err("register sysfs create group failed!\n"); ++ return ret; ++ } ++ ++ mutex_init(&aicbsp_power_lock); ++#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 ++ aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON); ++#endif ++ return 0; ++} ++ ++void aicbsp_sdio_exit(void); ++extern struct aic_sdio_dev *aicbsp_sdiodev; ++ ++static void __exit aicbsp_exit(void) ++{ ++#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 ++ if(aicbsp_sdiodev){ ++ aicbsp_sdio_exit(); ++ } ++#endif ++ sysfs_remove_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group); ++ platform_device_del(aicbsp_pdev); ++ platform_driver_unregister(&aicbsp_driver); ++ mutex_destroy(&aicbsp_power_lock); ++ aicbsp_resv_mem_deinit(); ++#ifdef CONFIG_PREALLOC_TXQ ++ aicwf_prealloc_txq_free(); ++#endif ++ printk("%s\n", __func__); ++} ++ ++module_init(aicbsp_init); ++module_exit(aicbsp_exit); ++ ++MODULE_DESCRIPTION(DRV_DESCRIPTION); ++MODULE_VERSION(DRV_VERS_MOD); ++MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c +new file mode 100644 +index 000000000000..9ed440f912eb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c +@@ -0,0 +1,2040 @@ ++/** ++ * aicwf_sdmmc.c ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aicsdio_txrxif.h" ++#include "aicsdio.h" ++#include "aic_bsp_driver.h" ++#include ++#include ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#include ++#endif /* CONFIG_PLATFORM_ROCKCHIP */ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#include ++#endif /* CONFIG_PLATFORM_ROCKCHIP */ ++ ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++extern void sunxi_mmc_rescan_card(unsigned ids); ++extern void sunxi_wlan_set_power(int on); ++extern int sunxi_wlan_get_bus_index(void); ++static int aicbsp_bus_index = -1; ++#endif ++ ++#ifdef CONFIG_PLATFORM_AMLOGIC//for AML ++#include ++extern void sdio_reinit(void); ++extern void extern_wifi_set_enable(int is_on); ++extern void set_power_control_lock(int lock); ++#endif//for AML ++ ++ ++static int aicbsp_platform_power_on(void); ++static void aicbsp_platform_power_off(void); ++ ++struct aic_sdio_dev *aicbsp_sdiodev = NULL; ++static struct semaphore *aicbsp_notify_semaphore; ++extern struct semaphore aicbsp_probe_semaphore; ++ ++static const struct sdio_device_id aicbsp_sdmmc_ids[]; ++static bool aicbsp_load_fw_in_fdrv = false; ++ ++#define FW_PATH_MAX 200 ++ ++//#ifdef CONFIG_PLATFORM_UBUNTU ++//static const char* aic_default_fw_path = "/lib/firmware/aic8800_sdio"; ++//#else ++static const char* aic_default_fw_path = CONFIG_AIC_FW_PATH; ++//#endif ++char aic_fw_path[FW_PATH_MAX]; ++module_param_string(aic_fw_path, aic_fw_path, FW_PATH_MAX, 0660); ++#ifdef CONFIG_M2D_OTA_AUTO_SUPPORT ++char saved_sdk_ver[64]; ++module_param_string(saved_sdk_ver, saved_sdk_ver,64, 0660); ++#endif ++ ++extern int testmode; ++ ++ ++#define SDIO_DEVICE_ID_AIC8801_FUNC2 0x0146 ++#define SDIO_DEVICE_ID_AIC8800D80_FUNC2 0x0182 ++ ++/* SDIO Device ID */ ++#define SDIO_VENDOR_ID_AIC8801 0x5449 ++#define SDIO_VENDOR_ID_AIC8800DC 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80X2 0xc8a1 ++ ++#define SDIO_DEVICE_ID_AIC8801 0x0145 ++#define SDIO_DEVICE_ID_AIC8800DC 0xc08d ++#define SDIO_DEVICE_ID_AIC8800D80 0x0082 ++#define SDIO_DEVICE_ID_AIC8800D80X2 0x2082 ++ ++ ++static int aicbsp_dummy_probe(struct sdio_func *func, const struct sdio_device_id *id) ++{ ++ if (func && (func->num != 2)) ++ return 0; ++ ++ if(func->vendor != SDIO_VENDOR_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801_FUNC2 && ++ func->vendor != SDIO_VENDOR_ID_AIC8800DC && ++ func->device != SDIO_DEVICE_ID_AIC8800DC && ++ func->vendor != SDIO_VENDOR_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80_FUNC2){ ++ printk("VID:%x DID:%X \r\n", func->vendor, func->device); ++ aicbsp_load_fw_in_fdrv = true; ++ } ++ ++ if (aicbsp_notify_semaphore) ++ up(aicbsp_notify_semaphore); ++ return 0; ++} ++ ++static void aicbsp_dummy_remove(struct sdio_func *func) ++{ ++} ++ ++static struct sdio_driver aicbsp_dummy_sdmmc_driver = { ++ .probe = aicbsp_dummy_probe, ++ .remove = aicbsp_dummy_remove, ++ .name = "aicbsp_dummy_sdmmc", ++ .id_table = aicbsp_sdmmc_ids, ++}; ++ ++static int aicbsp_reg_sdio_notify(void *semaphore) ++{ ++ aicbsp_notify_semaphore = semaphore; ++ return sdio_register_driver(&aicbsp_dummy_sdmmc_driver); ++} ++ ++static void aicbsp_unreg_sdio_notify(void) ++{ ++ mdelay(15); ++ sdio_unregister_driver(&aicbsp_dummy_sdmmc_driver); ++} ++ ++static const char *aicbsp_subsys_name(int subsys) ++{ ++ switch (subsys) { ++ case AIC_BLUETOOTH: ++ return "AIC_BLUETOOTH"; ++ case AIC_WIFI: ++ return "AIC_WIFI"; ++ default: ++ return "unknown subsys"; ++ } ++} ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#if 1//FOR RK SUSPEND ++void rfkill_rk_sleep_bt(bool sleep); ++#endif ++#endif ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#if 1//FOR RK SUSPEND ++void rfkill_rk_sleep_bt(bool sleep); ++#endif ++#endif ++ ++int aicbsp_set_subsys(int subsys, int state) ++{ ++ static int pre_power_map; ++ int cur_power_map; ++ int pre_power_state; ++ int cur_power_state; ++ ++ mutex_lock(&aicbsp_power_lock); ++ aicbsp_load_fw_in_fdrv = false; ++ cur_power_map = pre_power_map; ++ if (state) ++ cur_power_map |= (1 << subsys); ++ else ++ cur_power_map &= ~(1 << subsys); ++ ++ pre_power_state = pre_power_map > 0; ++ cur_power_state = cur_power_map > 0; ++ ++ sdio_dbg("%s, subsys: %s, state to: %d\n", __func__, aicbsp_subsys_name(subsys), state); ++ ++ if (cur_power_state != pre_power_state) { ++ sdio_dbg("%s, power state change to %d dure to %s\n", __func__, cur_power_state, aicbsp_subsys_name(subsys)); ++ if (cur_power_state) { ++ if (aicbsp_platform_power_on() < 0) ++ goto err0; ++ if (aicbsp_sdio_init()) ++ goto err1; ++ if (aicbsp_driver_fw_init(aicbsp_sdiodev)) ++ goto err2; ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ aicbsp_sdio_release(aicbsp_sdiodev); ++#endif ++ ++#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(true); ++ printk("%s BT wake default to SLEEP\r\n", __func__); ++#endif ++#endif ++ ++//#ifndef CONFIG_PLATFORM_ROCKCHIP ++// aicbsp_sdio_exit(); ++//#endif ++ } else { ++ #ifndef CONFIG_PLATFORM_ROCKCHIP ++ aicbsp_sdio_exit(); ++ #endif ++ aicbsp_platform_power_off(); ++ } ++ } else { ++ sdio_dbg("%s, power state no need to change, current: %d\n", __func__, cur_power_state); ++ } ++ pre_power_map = cur_power_map; ++ mutex_unlock(&aicbsp_power_lock); ++ ++ return cur_power_state; ++ ++err2: ++ aicbsp_sdio_release(aicbsp_sdiodev); ++ aicbsp_sdio_exit(); ++ ++err1: ++ aicbsp_platform_power_off(); ++ ++err0: ++ sdio_dbg("%s, fail to set %s power state to %d\n", __func__, aicbsp_subsys_name(subsys), state); ++ mutex_unlock(&aicbsp_power_lock); ++ return -1; ++} ++EXPORT_SYMBOL_GPL(aicbsp_set_subsys); ++ ++bool aicbsp_get_load_fw_in_fdrv(void){ ++ return aicbsp_load_fw_in_fdrv; ++} ++ ++EXPORT_SYMBOL_GPL(aicbsp_get_load_fw_in_fdrv); ++ ++static int aicwf_sdio_chipmatch(struct aic_sdio_dev *sdio_dev, uint16_t vid, uint16_t did){ ++ ++ if(vid == SDIO_VENDOR_ID_AIC8801 && did == SDIO_DEVICE_ID_AIC8801){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8801; ++ AICWFDBG(LOGINFO, "%s USE AIC8801\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800DC && did == SDIO_DEVICE_ID_AIC8800DC){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800DC; ++ AICWFDBG(LOGINFO, "%s USE AIC8800DC\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80 && did == SDIO_DEVICE_ID_AIC8800D80){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80X2 && did == SDIO_DEVICE_ID_AIC8800D80X2){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80X2; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80X2\r\n", __func__); ++ return 0; ++ }else{ ++ return -1; ++ } ++} ++ ++void *aicbsp_get_drvdata(void *args) ++{ ++ (void)args; ++ if (aicbsp_sdiodev) ++ return aicbsp_sdiodev->bus_if; ++ return dev_get_drvdata((const struct device *)args); ++} ++ ++ ++static int aicbsp_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ struct mmc_host *host; ++ struct aic_sdio_dev *sdiodev; ++ struct aicwf_bus *bus_if; ++ int err = -ENODEV; ++ ++ if (func == NULL) { ++ sdio_err("%s func is null\n", __func__); ++ return err; ++ } ++ ++ sdio_dbg("%s:%d vid:0x%04X did:0x%04X\n", __func__, func->num, ++ func->vendor, func->device); ++ ++ if(func->vendor != SDIO_VENDOR_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801_FUNC2 && ++ func->vendor != SDIO_VENDOR_ID_AIC8800DC && ++ func->device != SDIO_DEVICE_ID_AIC8800DC && ++ func->vendor != SDIO_VENDOR_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80_FUNC2){ ++ aicbsp_load_fw_in_fdrv = true; ++ return err; ++ } ++ ++ if (func->num != 2) { ++ return err; ++ } ++ ++ host = func->card->host; ++ host->caps |= MMC_CAP_NONREMOVABLE; ++ ++ func = func->card->sdio_func[1 - 1]; //replace 2 with 1 ++ ++ sdio_dbg("%s after replace:%d\n", __func__, func->num); ++ ++ bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_KERNEL); ++ if (!bus_if) { ++ sdio_err("alloc bus fail\n"); ++ return -ENOMEM; ++ } ++ ++ ++ sdiodev = kzalloc(sizeof(struct aic_sdio_dev), GFP_KERNEL); ++ if (!sdiodev) { ++ sdio_err("alloc sdiodev fail\n"); ++ kfree(bus_if); ++ return -ENOMEM; ++ } ++ aicbsp_sdiodev = sdiodev; ++ ++ err = aicwf_sdio_chipmatch(sdiodev, func->vendor, func->device); ++ ++ sdiodev->func = func; ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdiodev->func_msg = func->card->sdio_func[1]; ++ } ++ sdiodev->bus_if = bus_if; ++ bus_if->bus_priv.sdio = sdiodev; ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ dev_set_drvdata(&sdiodev->func_msg->dev, bus_if); ++ printk("the device is PRODUCT_ID_AIC8800DC \n"); ++ } ++ dev_set_drvdata(&func->dev, bus_if); ++ sdiodev->dev = &func->dev; ++ ++ if (sdiodev->chipid != PRODUCT_ID_AIC8800D80 && sdiodev->chipid != PRODUCT_ID_AIC8800D80X2) { ++ err = aicwf_sdio_func_init(sdiodev); ++ } else { ++ err = aicwf_sdiov3_func_init(sdiodev); ++ } ++ if (err < 0) { ++ sdio_err("sdio func init fail\n"); ++ goto fail; ++ } ++ ++ if (aicwf_sdio_bus_init(sdiodev) == NULL) { ++ sdio_err("sdio bus init err\r\n"); ++ goto fail; ++ } ++ ++ aicbsp_platform_init(sdiodev); ++ ++ up(&aicbsp_probe_semaphore); ++ ++ return 0; ++fail: ++ aicwf_sdio_func_deinit(sdiodev); ++ dev_set_drvdata(&func->dev, NULL); ++ kfree(sdiodev); ++ kfree(bus_if); ++ return err; ++} ++ ++ ++static void aicbsp_sdio_remove(struct sdio_func *func) ++{ ++ struct mmc_host *host; ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_sdio_dev *sdiodev = NULL; ++ ++ AICWFDBG(LOGINFO, "%s\n", __func__); ++ if (aicbsp_sdiodev == NULL) { ++ AICWFDBG(LOGERROR, "%s: allready unregister\n", __func__); ++ goto done; ++ } ++ if (func == NULL) { ++ AICWFDBG(LOGERROR, "%s, sdio func is null\n", __func__); ++ goto done; ++ } ++ ++ host = func->card->host; ++ host->caps &= ~MMC_CAP_NONREMOVABLE; ++ ++ bus_if = aicbsp_get_drvdata(&func->dev); ++ ++ if (!bus_if) { ++ AICWFDBG(LOGERROR, "%s bus_if is NULL \r\n", __func__); ++ goto done; ++ } ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ if (!sdiodev) { ++ AICWFDBG(LOGERROR, "%s sdiodev is NULL \r\n", __func__); ++ goto done; ++ } ++ ++ aicwf_sdio_release(sdiodev); ++ aicwf_sdio_func_deinit(sdiodev); ++ ++ dev_set_drvdata(&sdiodev->func->dev, NULL); ++ kfree(sdiodev); ++ ++done: ++ if (bus_if) ++ kfree(bus_if); ++ aicbsp_sdiodev = NULL; ++ sdio_dbg("%s done\n", __func__); ++} ++ ++ ++static int aicbsp_sdio_suspend(struct device *dev) ++{ ++ struct sdio_func *func = dev_to_sdio_func(dev); ++ int err; ++ mmc_pm_flag_t sdio_flags; ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(false); ++#endif ++#endif ++ ++ sdio_dbg("%s, func->num = %d\n", __func__, func->num); ++ if (func->num != 2) ++ return 0; ++ ++ sdio_flags = sdio_get_host_pm_caps(func); ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ sdio_dbg("%s: can't keep power while host is suspended\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* keep power while host suspended */ ++ err = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); ++ if (err) { ++ sdio_dbg("%s: error while trying to keep power\n", __func__); ++ return err; ++ } ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(true); ++ printk("%s BT wake to SLEEP\r\n", __func__); ++#endif ++#endif ++ ++ return 0; ++} ++ ++static int aicbsp_sdio_resume(struct device *dev) ++{ ++ sdio_dbg("%s\n", __func__); ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(false); ++#endif ++#endif ++ ++ return 0; ++} ++ ++static const struct sdio_device_id aicbsp_sdmmc_ids[] = { ++ {SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN)}, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(sdio, aicbsp_sdmmc_ids); ++ ++static const struct dev_pm_ops aicbsp_sdio_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(aicbsp_sdio_suspend, aicbsp_sdio_resume) ++}; ++ ++static struct sdio_driver aicbsp_sdio_driver = { ++ .probe = aicbsp_sdio_probe, ++ .remove = aicbsp_sdio_remove, ++ .name = AICBSP_SDIO_NAME, ++ .id_table = aicbsp_sdmmc_ids, ++ .drv = { ++ .pm = &aicbsp_sdio_pm_ops, ++ }, ++}; ++ ++static int aicbsp_platform_power_on(void) ++{ ++ int ret = 0; ++ struct semaphore aic_chipup_sem; ++ sdio_dbg("%s\n", __func__); ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ if (aicbsp_bus_index < 0) ++ aicbsp_bus_index = sunxi_wlan_get_bus_index(); ++ if (aicbsp_bus_index < 0) ++ return aicbsp_bus_index; ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++ mdelay(200); ++ extern_wifi_set_enable(1); ++ mdelay(200); ++ sdio_reinit(); ++ set_power_control_lock(1); ++#endif ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ rockchip_wifi_power(0); ++ mdelay(50); ++ rockchip_wifi_power(1); ++ mdelay(50); ++ rockchip_wifi_set_carddetect(1); ++#endif /*CONFIG_PLATFORM_ROCKCHIP2*/ ++ ++ sema_init(&aic_chipup_sem, 0); ++ ret = aicbsp_reg_sdio_notify(&aic_chipup_sem); ++ if (ret) { ++ sdio_dbg("%s aicbsp_reg_sdio_notify fail(%d)\n", __func__, ret); ++ return ret; ++ } ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ sunxi_wlan_set_power(0); ++ mdelay(50); ++ sunxi_wlan_set_power(1); ++ mdelay(50); ++ sunxi_mmc_rescan_card(aicbsp_bus_index); ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++ if (down_timeout(&aic_chipup_sem, msecs_to_jiffies(2000)) == 0) { ++ aicbsp_unreg_sdio_notify(); ++ if(aicbsp_load_fw_in_fdrv){ ++ printk("%s load fw in fdrv\r\n", __func__); ++ return -1; ++ } ++ return 0; ++ } ++ ++ aicbsp_unreg_sdio_notify(); ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ sunxi_wlan_set_power(0); ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++#endif ++ ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ rockchip_wifi_power(0); ++#endif /*CONFIG_PLATFORM_ROCKCHIP2*/ ++ ++ return -1; ++} ++ ++static void aicbsp_platform_power_off(void) ++{ ++//TODO wifi disable and sdio card detection ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ if (aicbsp_bus_index < 0) ++ aicbsp_bus_index = sunxi_wlan_get_bus_index(); ++ if (aicbsp_bus_index < 0) { ++ sdio_dbg("no aicbsp_bus_index\n"); ++ return; ++ } ++ sunxi_wlan_set_power(0); ++ mdelay(100); ++ sunxi_mmc_rescan_card(aicbsp_bus_index); ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ rockchip_wifi_set_carddetect(0); ++ mdelay(200); ++ rockchip_wifi_power(0); ++ mdelay(200); ++#endif /*CONFIG_PLATFORM_ROCKCHIP*/ ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++#endif ++ ++ ++ sdio_dbg("%s\n", __func__); ++} ++ ++ ++int aicbsp_sdio_init(void) ++{ ++ ++ if (sdio_register_driver(&aicbsp_sdio_driver)) { ++ return -1; ++ } else { ++ //may add mmc_rescan here ++ } ++ if (down_timeout(&aicbsp_probe_semaphore, msecs_to_jiffies(2000)) != 0){ ++ printk("%s aicbsp_sdio_probe fail\r\n", __func__); ++ return -1; ++ } ++ ++ ++ return 0; ++} ++ ++void aicbsp_sdio_exit(void) ++{ ++ sdio_unregister_driver(&aicbsp_sdio_driver); ++} ++ ++void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev) ++{ ++ sdiodev->bus_if->state = BUS_DOWN_ST; ++ sdio_claim_host(sdiodev->func); ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func_msg); ++ sdio_release_irq(sdiodev->func_msg); ++ sdio_release_host(sdiodev->func_msg); ++ } ++} ++ ++int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ *val = sdio_readb(sdiodev->func, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_readb_func2(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func_msg); ++ *val = sdio_readb(sdiodev->func_msg, regaddr, &ret); ++ sdio_release_host(sdiodev->func_msg); ++ return ret; ++} ++ ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ sdio_writeb(sdiodev->func, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_writeb_func2(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func_msg); ++ sdio_writeb(sdiodev->func_msg, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func_msg); ++ return ret; ++} ++ ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = -1; ++ u8 fc_reg = 0; ++ u32 count = 0; ++ ++ while (true) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.flow_ctrl_reg, &fc_reg); ++ if (ret) { ++ return -1; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ fc_reg = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; ++ } ++ ++ if (fc_reg != 0) { ++ ret = fc_reg; ++ return ret; ++ } else { ++ if (count >= FLOW_CTRL_RETRY_COUNT) { ++ ret = -fc_reg; ++ break; ++ } ++ count++; ++ if (count < 30) ++ udelay(200); ++ else if (count < 40) ++ mdelay(1); ++ else ++ mdelay(10); ++ } ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_send_msg(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) ++{ ++ int ret = 0; ++ ++ sdio_claim_host(sdiodev->func_msg); ++ ret = sdio_writesb(sdiodev->func_msg, 7, buf, count); ++ sdio_release_host(sdiodev->func_msg); ++ ++ return ret; ++} ++ ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) ++{ ++ int ret = 0; ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, buf, count); ++ sdio_release_host(sdiodev->func); ++ ++ return ret; ++} ++ ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, ++ u32 size, u8 msg) ++{ ++ int ret; ++ ++ if ((!skbbuf) || (!size)) { ++ return -EINVAL;; ++ } ++ ++ if(!msg) { ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_readsb(sdiodev->func, skbbuf->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func); ++ } else { ++ sdio_claim_host(sdiodev->func_msg); ++ ret = sdio_readsb(sdiodev->func_msg, skbbuf->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func_msg); ++ } ++ ++ ++ if (ret < 0) { ++ return ret; ++ } ++ skbbuf->len = size; ++ ++ return ret; ++} ++ ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++int aicwf_sdio_wakeup(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ int read_retry; ++ int write_retry = 20; ++ int wakeup_reg_val = 0; ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ wakeup_reg_val = 1; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ wakeup_reg_val = 0x11; ++ } ++ ++ if (sdiodev->state == SDIO_SLEEP_ST) { ++ //if (sdiodev->rwnx_hw->vif_started) { ++ down(&sdiodev->pwrctl_wakeup_sema); ++ while (write_retry) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, wakeup_reg_val); ++ if (ret) { ++ txrx_err("sdio wakeup fail\n"); ++ ret = -1; ++ } else { ++ read_retry = 10; ++ while (read_retry) { ++ u8 val; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val); ++ if ((ret == 0) && (val & 0x10)) { ++ break; ++ } ++ read_retry--; ++ udelay(200); ++ } ++ if (read_retry != 0) ++ break; ++ } ++ sdio_dbg("write retry: %d \n", write_retry); ++ write_retry--; ++ udelay(100); ++ } ++ up(&sdiodev->pwrctl_wakeup_sema); ++ // } ++ } ++ ++ sdiodev->state = SDIO_ACTIVE_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ ++ return ret; ++} ++ ++extern u8 dhcped; ++int aicwf_sdio_sleep_allow(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = sdiodev->bus_if; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, 0x10); ++ if (ret) { ++ sdio_err("Write sleep fail!\n"); ++ } ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ return ret; ++ } ++ ++ if (sdiodev->state == SDIO_ACTIVE_ST) { ++ { ++ sdio_dbg("s\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, 0x10); ++ if (ret) ++ sdio_err("Write sleep fail!\n"); ++ } ++ sdiodev->state = SDIO_SLEEP_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ } else { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target) ++{ ++ int ret = 0; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ return -1; ++ } ++ ++ if (sdiodev->state == target) { ++ if (target == SDIO_ACTIVE_ST) { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ return ret; ++ } ++ ++ switch (target) { ++ case SDIO_ACTIVE_ST: ++ aicwf_sdio_wakeup(sdiodev); ++ break; ++ case SDIO_SLEEP_ST: ++ aicwf_sdio_sleep_allow(sdiodev); ++ break; ++ } ++ ++ return ret; ++} ++#endif ++ ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++{ ++ int ret = 0; ++ u8 *frame; ++ u32 len = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("tx bus is down!\n"); ++ return -EINVAL; ++ } ++ ++ frame = (u8 *) (pkt->data); ++ len = pkt->len; ++ len = (len + SDIOWIFI_FUNC_BLOCKSIZE - 1) / SDIOWIFI_FUNC_BLOCKSIZE * SDIOWIFI_FUNC_BLOCKSIZE; ++ ret = aicwf_sdio_send_pkt(sdiodev, pkt->data, len); ++ if (ret) ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", ret); ++ ++ return ret; ++} ++ ++static int aicwf_sdio_intr_get_len_bytemode(struct aic_sdio_dev *sdiodev, u8 *byte_len) ++{ ++ int ret = 0; ++ ++ if (!byte_len) ++ return -EBADE; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ *byte_len = 0; ++ } else { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.bytemode_len_reg, byte_len); ++ sdiodev->rx_priv->data_len = (*byte_len)*4; ++ } ++ ++ return ret; ++} ++ ++static void aicwf_sdio_bus_stop(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = aicbsp_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret; ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ sdio_dbg("%s\n", __func__); ++ if (sdiodev->pwrctl_tsk) { ++ complete_all(&sdiodev->pwrctrl_trgg); ++ kthread_stop(sdiodev->pwrctl_tsk); ++ sdiodev->pwrctl_tsk = NULL; ++ } ++#endif ++ bus_if->state = BUS_DOWN_ST; ++ ret = down_interruptible(&sdiodev->tx_priv->txctl_sema); ++ if (ret) ++ sdio_err("down txctl_sema fail\n"); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++#endif ++ if (!ret) ++ up(&sdiodev->tx_priv->txctl_sema); ++ aicwf_frame_queue_flush(&sdiodev->tx_priv->txq); ++} ++ ++struct sk_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev, u8 msg) ++{ ++ int ret = 0; ++ u32 size = 0; ++ struct sk_buff *skb = NULL; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("bus down\n"); ++ return NULL; ++ } ++ ++ size = sdiodev->rx_priv->data_len; ++ skb = __dev_alloc_skb(size, GFP_KERNEL); ++ if (!skb) { ++ return NULL; ++ } ++ ++ ret = aicwf_sdio_recv_pkt(sdiodev, skb, size, msg); ++ if (ret) { ++ dev_kfree_skb(skb); ++ skb = NULL; ++ } ++ ++ return skb; ++} ++ ++static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++ u16 len; ++ u8 *payload = sdiodev->tx_priv->cmd_buf; ++ u16 payload_len = sdiodev->tx_priv->cmd_len; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ int adjust_len = 0; ++ int buffer_cnt = 0; ++ u8 retry = 0; ++ ++ len = payload_len; ++ if ((len % TX_ALIGNMENT) != 0) { ++ adjust_len = roundup(len, TX_ALIGNMENT); ++ memcpy(payload+payload_len, adjust_str, (adjust_len - len)); ++ payload_len += (adjust_len - len); ++ } ++ len = payload_len; ++ ++ //link tail is necessary ++ if ((len % SDIOWIFI_FUNC_BLOCKSIZE) != 0) { ++ memset(payload+payload_len, 0, TAIL_LEN); ++ payload_len += TAIL_LEN; ++ len = (payload_len/SDIOWIFI_FUNC_BLOCKSIZE + 1) * SDIOWIFI_FUNC_BLOCKSIZE; ++ } else ++ len = payload_len; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); ++ while ((buffer_cnt <= 0 || (buffer_cnt > 0 && len > (buffer_cnt * BUFFER_SIZE))) && retry < 10) { ++ retry++; ++ buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); ++ printk("buffer_cnt = %d\n", buffer_cnt); ++ } ++ } ++ down(&sdiodev->tx_priv->cmd_txsema); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if (buffer_cnt > 0 && len < (buffer_cnt * BUFFER_SIZE)) { ++ err = aicwf_sdio_send_pkt(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ err = aicwf_sdio_send_msg(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ ++ sdiodev->tx_priv->cmd_txstate = false; ++ if (!err) ++ sdiodev->tx_priv->cmd_tx_succ = true; ++ else ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ return err; ++} ++ ++static void aicwf_sdio_tx_process(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("Bus is down\n"); ++ return; ++ } ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++#endif ++ ++ //config ++ sdio_info("send cmd\n"); ++ if (sdiodev->tx_priv->cmd_txstate) { ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txctl down bus->txctl_sema fail\n"); ++ return; ++ } ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ txrx_err("txctl up bus->txctl_sema fail\n"); ++ return; ++ } ++ ++ err = aicwf_sdio_tx_msg(sdiodev); ++ up(&sdiodev->tx_priv->txctl_sema); ++ if (waitqueue_active(&sdiodev->tx_priv->cmd_txdone_wait)) ++ wake_up(&sdiodev->tx_priv->cmd_txdone_wait); ++ } ++ ++ //data ++ sdio_info("send data\n"); ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txdata down bus->txctl_sema\n"); ++ return; ++ } ++ ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("sdio state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ return; ++ } ++ ++ if(!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) ++ sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ while (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) { ++ aicwf_sdio_send(sdiodev->tx_priv); ++ if (sdiodev->tx_priv->cmd_txstate) ++ break; ++ } ++ ++ up(&sdiodev->tx_priv->txctl_sema); ++} ++ ++static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) ++{ ++ uint prio; ++ int ret = -EBADE; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ prio = (pkt->priority & 0x7); ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ if (!aicwf_frame_enq(sdiodev->dev, &sdiodev->tx_priv->txq, pkt, prio)) { ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return -ENOSR; ++ } else { ++ ret = 0; ++ } ++ ++ if (bus_if->state != BUS_UP_ST) { ++ sdio_err("bus_if stopped\n"); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return -1; ++ } ++ ++ atomic_inc(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ complete(&bus_if->bustx_trgg); ++ ++ return ret; ++} ++ ++static int aicwf_sdio_bus_txmsg(struct device *dev, u8 *msg, uint msglen) ++{ ++ int ret = -1; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ down(&sdiodev->tx_priv->cmd_txsema); ++ sdiodev->tx_priv->cmd_txstate = true; ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ sdiodev->tx_priv->cmd_buf = msg; ++ sdiodev->tx_priv->cmd_len = msglen; ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ if (bus_if->state != BUS_UP_ST) { ++ sdio_err("bus has stop\n"); ++ return -1; ++ } ++ ++ complete(&bus_if->bustx_trgg); ++ ++ if (sdiodev->tx_priv->cmd_txstate) { ++ int timeout = msecs_to_jiffies(CMD_TX_TIMEOUT); ++ ret = wait_event_timeout(sdiodev->tx_priv->cmd_txdone_wait, \ ++ !(sdiodev->tx_priv->cmd_txstate), timeout); ++ } ++ ++ if (!sdiodev->tx_priv->cmd_txstate && sdiodev->tx_priv->cmd_tx_succ) { ++ ret = 0; ++ } else { ++ sdio_err("send faild:%d, %d,%x\n", sdiodev->tx_priv->cmd_txstate, sdiodev->tx_priv->cmd_tx_succ, ret); ++ ret = -EIO; ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv) ++{ ++ struct sk_buff *pkt; ++ struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; ++ u16 aggr_len = 0; ++ int retry_times = 0; ++ int max_retry_times = 5; ++ ++ aggr_len = (tx_priv->tail - tx_priv->head); ++ if (((atomic_read(&tx_priv->aggr_count) == 0) && (aggr_len != 0)) ++ || ((atomic_read(&tx_priv->aggr_count) != 0) && (aggr_len == 0))) { ++ if (aggr_len > 0) ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++ goto done; ++ } ++ ++ if (tx_priv->fw_avail_bufcnt <= 0) { //flow control failed ++ tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ while (tx_priv->fw_avail_bufcnt <= 0 && retry_times < max_retry_times) { ++ retry_times++; ++ tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ } ++ if (tx_priv->fw_avail_bufcnt <= 0) { ++ sdio_err("fc retry %d fail\n", tx_priv->fw_avail_bufcnt); ++ goto done; ++ } ++ } ++ ++ if (atomic_read(&tx_priv->aggr_count) == tx_priv->fw_avail_bufcnt) { ++ if (atomic_read(&tx_priv->aggr_count) > 0) { ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); //send and check the next pkt; ++ } ++ } else { ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ pkt = aicwf_frame_dequeue(&sdiodev->tx_priv->txq); ++ if (pkt == NULL) { ++ sdio_err("txq no pkt\n"); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ goto done; ++ } ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ ++ if (tx_priv == NULL || tx_priv->tail == NULL || pkt == NULL) ++ txrx_err("null error\n"); ++ if (aicwf_sdio_aggr(tx_priv, pkt)) { ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++ sdio_err("add aggr pkts failed!\n"); ++ goto done; ++ } ++ ++ //when aggr finish or there is cmd to send, just send this aggr pkt to fw ++ if ((int)atomic_read(&sdiodev->tx_priv->tx_pktcnt) == 0 || sdiodev->tx_priv->cmd_txstate) { //no more pkt send it! ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); ++ } else ++ goto done; ++ } ++ ++done: ++ return 0; ++} ++ ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt) ++{ ++ //struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; ++ u8 *start_ptr = tx_priv->tail; ++ u8 sdio_header[4]; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ u16 curr_len = 0; ++ int allign_len = 0; ++ ++ //sdio_header[0] =((pkt->len - sizeof(struct rwnx_txhdr) + sizeof(struct txdesc_api)) & 0xff); ++ //sdio_header[1] =(((pkt->len - sizeof(struct rwnx_txhdr) + sizeof(struct txdesc_api)) >> 8)&0x0f); ++ sdio_header[2] = 0x01; //data ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ sdio_header[3] = 0; //reserved ++ else if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ sdio_header[3] = crc8_ponl_107(&sdio_header[0], 3); // crc8 ++ ++ memcpy(tx_priv->tail, (u8 *)&sdio_header, sizeof(sdio_header)); ++ tx_priv->tail += sizeof(sdio_header); ++ //payload ++ //memcpy(tx_priv->tail, (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ //tx_priv->tail += sizeof(struct txdesc_api); //hostdesc ++ //memcpy(tx_priv->tail, (u8 *)((u8 *)txhdr + txhdr->sw_hdr->headroom), pkt->len-txhdr->sw_hdr->headroom); ++ //tx_priv->tail += (pkt->len - txhdr->sw_hdr->headroom); ++ ++ //word alignment ++ curr_len = tx_priv->tail - tx_priv->head; ++ if (curr_len & (TX_ALIGNMENT - 1)) { ++ allign_len = roundup(curr_len, TX_ALIGNMENT)-curr_len; ++ memcpy(tx_priv->tail, adjust_str, allign_len); ++ tx_priv->tail += allign_len; ++ } ++ ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ start_ptr[0] = ((tx_priv->tail - start_ptr - 4) & 0xff); ++ start_ptr[1] = (((tx_priv->tail - start_ptr - 4)>>8) & 0x0f); ++ } ++ ++ tx_priv->aggr_buf->dev = pkt->dev; ++ ++ #if 0 ++ if (!txhdr->sw_hdr->need_cfm) { ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, txhdr->sw_hdr->headroom); ++ consume_skb(pkt); ++ } ++ #endif ++ ++ consume_skb(pkt); ++ atomic_inc(&tx_priv->aggr_count); ++ return 0; ++} ++ ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv) ++{ ++ struct sk_buff *tx_buf = tx_priv->aggr_buf; ++ int ret = 0; ++ int curr_len = 0; ++ ++ //link tail is necessary ++ curr_len = tx_priv->tail - tx_priv->head; ++ if ((curr_len % TXPKT_BLOCKSIZE) != 0) { ++ memset(tx_priv->tail, 0, TAIL_LEN); ++ tx_priv->tail += TAIL_LEN; ++ } ++ ++ tx_buf->len = tx_priv->tail - tx_priv->head; ++ ret = aicwf_sdio_txpkt(tx_priv->sdiodev, tx_buf); ++ if (ret < 0) { ++ sdio_err("fail to send aggr pkt!\n"); ++ } ++ ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++} ++ ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv) ++{ ++ struct sk_buff *aggr_buf = tx_priv->aggr_buf; ++ ++ tx_priv->tail = tx_priv->head; ++ aggr_buf->len = 0; ++ atomic_set(&tx_priv->aggr_count, 0); ++} ++ ++static int aicwf_sdio_bus_start(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ sdio_claim_host(sdiodev->func); ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ sdio_release_host(sdiodev->func); ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func); ++ ++ //since we have func2 we don't register irq handler ++ sdio_claim_irq(sdiodev->func, NULL); ++ sdio_claim_irq(sdiodev->func_msg, NULL); ++ ++ sdiodev->func->irq_handler = (sdio_irq_handler_t *)aicwf_sdio_hal_irqhandler; ++ sdiodev->func_msg->irq_handler = (sdio_irq_handler_t *)aicwf_sdio_hal_irqhandler_func2; ++ sdio_release_host(sdiodev->func); ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ ++ if (ret != 0) ++ sdio_err("func2 intr register failed:%d\n", ret); ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdio_claim_host(sdiodev->func); ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++ ++ sdio_f0_writeb(sdiodev->func, 0x07, 0x04, &ret); ++ if (ret) { ++ sdio_err("set func0 int en fail %d\n", ret); ++ } ++ sdio_release_host(sdiodev->func); ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ } ++ ++ bus_if->state = BUS_UP_ST; ++ return ret; ++} ++ ++int aicwf_sdio_bustx_thread(void *data) ++{ ++ struct aicwf_bus *bus = (struct aicwf_bus *) data; ++ struct aic_sdio_dev *sdiodev = bus->bus_priv.sdio; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ sdio_err("sdio bustx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) > 0) || (sdiodev->tx_priv->cmd_txstate == true)) ++ aicwf_sdio_tx_process(sdiodev); ++ } ++ } ++ ++ return 0; ++} ++ ++int aicwf_sdio_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ sdio_err("sdio busrx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ aicwf_process_rxframes(rx_priv); ++ } ++ } ++ ++ return 0; ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static void aicwf_sdio_bus_pwrctl(struct timer_list *t) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ struct aic_sdio_dev *sdiodev = timer_container_of(sdiodev, t, timer); ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, timer); ++#endif ++#else ++static void aicwf_sdio_bus_pwrctl(ulong data) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#endif ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus down\n"); ++ return; ++ } ++ ++ if (sdiodev->pwrctl_tsk) { ++ complete(&sdiodev->pwrctrl_trgg); ++ } ++} ++#endif ++ ++static void aicwf_sdio_enq_rxpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++{ ++ struct aicwf_rx_priv *rx_priv = sdiodev->rx_priv; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (!aicwf_rxframe_enqueue(sdiodev->dev, &rx_priv->rxq, pkt)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ aicwf_dev_skb_free(pkt); ++ return; ++ } ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ ++ atomic_inc(&rx_priv->rx_cnt); ++} ++ ++#define SDIO_OTHER_INTERRUPT (0x1ul << 7) ++ ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(&func->dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ u8 intstatus = 0; ++ u8 byte_len = 0; ++ struct sk_buff *pkt = NULL; ++ int ret; ++ ++ //AICWFDBG(LOGDEBUG,"%s bsp enter \r\n", __func__); ++ ++ if(aicbsp_sdiodev->sdio_hal_irqhandler){ ++ aicbsp_sdiodev->sdio_hal_irqhandler(func); ++ return; ++ } ++ ++ if (!bus_if || bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus err\n"); ++ return; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ ++ while(intstatus){ ++ sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; ++ if (intstatus > 0) { ++ if(intstatus < 64) { ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } else { ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ } ++ }else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ do { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.misc_int_status_reg, &intstatus); ++ if (!ret) { ++ break; ++ } ++ sdio_err("ret=%d, intstatus=%x\r\n",ret, intstatus); ++ } while (1); ++ if (intstatus & SDIO_OTHER_INTERRUPT) { ++ u8 int_pending; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ int_pending &= ~0x01; // dev to host soft irq ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ } ++ ++ if (intstatus > 0) { ++ uint8_t intmaskf2 = intstatus | (0x1UL << 3); ++ if (intmaskf2 > 120U) { // func2 ++ if (intmaskf2 == 127U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 1);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev, 1); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7U) * SDIOWIFI_FUNC_BLOCKSIZE; ++ pkt = aicwf_sdio_readframes(sdiodev, 1); ++ } ++ } else { // func1 ++ if (intstatus == 120U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 0);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7FU) * SDIOWIFI_FUNC_BLOCKSIZE; ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ } ++ ++ complete(&bus_if->busrx_trgg); ++} ++ ++void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(&func->dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ u8 intstatus = 0; ++ u8 byte_len = 0; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_buff *pkt = NULL; ++ #else ++ struct sk_buff *pkt = NULL; ++ #endif ++ int ret; ++ ++ if (!bus_if || bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus err\n"); ++ return; ++ } ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ if (list_empty(&aic_rx_buff_list.rxbuff_list)) { ++ printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); ++ return; ++ } ++ #endif ++ ++ ret = aicwf_sdio_readb_func2(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ ++ while(intstatus) { ++ sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; ++ if (intstatus > 0) { ++ if(intstatus < 64) { ++ pkt = aicwf_sdio_readframes(sdiodev,1); ++ } else { ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ pkt = aicwf_sdio_readframes(sdiodev,1); ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt){ ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ } ++ ret = aicwf_sdio_readb_func2(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ } ++ ++ complete(&bus_if->busrx_trgg); ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration) ++{ ++ uint timeout; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST && duration) ++ return; ++ ++ spin_lock_bh(&sdiodev->pwrctl_lock); ++ if (!duration) { ++ if (timer_pending(&sdiodev->timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&sdiodev->timer); ++#else ++ del_timer_sync(&sdiodev->timer); ++#endif ++ } else { ++ sdiodev->active_duration = duration; ++ timeout = msecs_to_jiffies(sdiodev->active_duration); ++ mod_timer(&sdiodev->timer, jiffies + timeout); ++ } ++ spin_unlock_bh(&sdiodev->pwrctl_lock); ++} ++#endif ++ ++static struct aicwf_bus_ops aicwf_sdio_bus_ops = { ++ .stop = aicwf_sdio_bus_stop, ++ .start = aicwf_sdio_bus_start, ++ .txdata = aicwf_sdio_bus_txdata, ++ .txmsg = aicwf_sdio_bus_txmsg, ++}; ++ ++void aicwf_sdio_release_func2(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ sdio_dbg("%s\n", __func__); ++ sdio_claim_host(sdiodev->func_msg); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); ++ } ++ sdio_release_irq(sdiodev->func_msg); ++ sdio_release_host(sdiodev->func_msg); ++ ++} ++ ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) ++{ ++ struct aicwf_bus *bus_if = NULL; ++ struct aicwf_bus *bus_if_t = NULL; ++ int ret = 0; ++ ++ sdio_dbg("%s\n", __func__); ++ if (sdiodev->func == NULL) { ++ printk("%s, NULL sdio func\n", __func__); ++ return; ++ } ++ ++ bus_if = aicbsp_get_drvdata(sdiodev->dev); ++ if (bus_if) ++ bus_if->state = BUS_DOWN_ST; ++ ++ bus_if_t = dev_get_drvdata(sdiodev->dev); ++ ++ if ((bus_if_t != NULL) && (sdiodev->bus_if == bus_if_t)) { ++ sdio_dbg("%s bsp release\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!, ret=%d\n", sdiodev->sdio_reg.intr_config_reg, ret); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ aicwf_sdio_release_func2(sdiodev); ++ } ++ ++ if (sdiodev->dev) ++ aicwf_bus_deinit(sdiodev->dev); ++ ++ if (sdiodev->tx_priv) ++ aicwf_tx_deinit(sdiodev->tx_priv); ++ ++ if (sdiodev->rx_priv) ++ aicwf_rx_deinit(sdiodev->rx_priv); ++ ++ rwnx_cmd_mgr_deinit(&sdiodev->cmd_mgr); ++} ++ ++ ++ ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev) ++{ ++ sdio_dbg("%s\n", __func__); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_CONFIG_REG; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_SLEEP_REG; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_WAKEUP_REG; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_REG; ++ sdiodev->sdio_reg.register_block = SDIOWIFI_REGISTER_BLOCK; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG; ++ sdiodev->sdio_reg.block_cnt_reg = SDIOWIFI_BLOCK_CNT_REG; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG_V3; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_ENABLE_REG_V3; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_INTR_PENDING_REG_V3; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_INTR_TO_DEVICE_REG_V3; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_Q1_REG_V3; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG_V3; ++ sdiodev->sdio_reg.misc_int_status_reg = SDIOWIFI_MISC_INT_STATUS_REG_V3; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR_V3; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR_V3; ++ } ++} ++ ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 block_bit0 = 0x1; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ struct aicbsp_feature_t feature; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++#if 0//SDIO PHASE SETTING ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ sdio_f0_writeb(sdiodev->func, feature.sdio_phase, 0x13, &ret); ++ if (ret < 0) { ++ sdio_err("write func0 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#endif ++ ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ sdio_err("set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_err("enable func fail %d.\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ udelay(100); ++#if 1//SDIO CLOCK SETTING ++ if (feature.sdio_clock > 0) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++ sdio_release_host(sdiodev->func); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ ++ sdio_claim_host(sdiodev->func_msg); ++ ++ //set sdio blocksize ++ ret = sdio_set_block_size(sdiodev->func_msg, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set func2 blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func_msg); ++ return ret; ++ } ++ ++ //set sdio enable func ++ ret = sdio_enable_func(sdiodev->func_msg); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "enable func2 fail %d.\n", ret); ++ } ++ ++ sdio_release_host(sdiodev->func_msg); ++ ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ } ++ ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ //u8 val; ++ struct aicbsp_feature_t feature; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ sdio_err("set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_err("enable func fail %d.\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ++ sdio_f0_writeb(sdiodev->func, 0x7F, 0xF2, &ret); ++ if (ret) { ++ sdio_err("set fn0 0xF2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#if 0 ++ if (host->ios.timing == MMC_TIMING_UHS_DDR50) { ++ val = 0x21;//0x1D;//0x5; ++ } else { ++ val = 0x01;//0x19;//0x1; ++ } ++ val |= SDIOCLK_FREE_RUNNING_BIT; ++ sdio_f0_writeb(sdiodev->func, val, 0xF0, &ret); ++ if (ret) { ++ sdio_err("set iopad ctrl fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x0, 0xF8, &ret); ++ if (ret) { ++ sdio_err("set iopad delay2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x40, 0xF1, &ret); ++ if (ret) { ++ sdio_err("set iopad delay1 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ msleep(1); ++#if 1//SDIO CLOCK SETTING ++ if ((feature.sdio_clock > 0) && (host->ios.timing != MMC_TIMING_UHS_DDR50)) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++#endif ++ sdio_release_host(sdiodev->func); ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev) ++{ ++ struct aicwf_bus *bus_if = NULL; ++ ++ if (sdiodev->func == NULL) { ++ sdio_err("%s, NULL sdio func\n", __func__); ++ return; ++ } ++ ++ bus_if = dev_get_drvdata(sdiodev->dev); ++ if (bus_if == NULL) { ++ sdio_err("%s, bus_if is null\n", __func__); ++ return; ++ } ++ ++ if (sdiodev->bus_if == bus_if) { ++ sdio_dbg("%s bsp disable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ sdio_disable_func(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func_msg); ++ sdio_disable_func(sdiodev->func_msg); ++ sdio_release_host(sdiodev->func_msg); ++ } ++ ++} ++ ++ ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret; ++ struct aicwf_bus *bus_if; ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ spin_lock_init(&sdiodev->pwrctl_lock); ++ sema_init(&sdiodev->pwrctl_wakeup_sema, 1); ++#endif ++ ++ bus_if = sdiodev->bus_if; ++ bus_if->dev = sdiodev->dev; ++ bus_if->ops = &aicwf_sdio_bus_ops; ++ bus_if->state = BUS_DOWN_ST; ++#if defined(CONFIG_SDIO_PWRCTRL) ++ sdiodev->state = SDIO_SLEEP_ST; ++ sdiodev->active_duration = SDIOWIFI_PWR_CTRL_INTERVAL; ++#else ++ sdiodev->state = SDIO_ACTIVE_ST; ++#endif ++ ++ rx_priv = aicwf_rx_init(sdiodev); ++ if (!rx_priv) { ++ sdio_err("rx init fail\n"); ++ goto fail; ++ } ++ sdiodev->rx_priv = rx_priv; ++ ++ tx_priv = aicwf_tx_init(sdiodev); ++ if (!tx_priv) { ++ sdio_err("tx init fail\n"); ++ goto fail; ++ } ++ sdiodev->tx_priv = tx_priv; ++ aicwf_frame_queue_init(&tx_priv->txq, 8, TXQLEN); ++ spin_lock_init(&tx_priv->txqlock); ++ sema_init(&tx_priv->txctl_sema, 1); ++ sema_init(&tx_priv->cmd_txsema, 1); ++ init_waitqueue_head(&tx_priv->cmd_txdone_wait); ++ atomic_set(&tx_priv->tx_pktcnt, 0); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ timer_setup(&sdiodev->timer, aicwf_sdio_bus_pwrctl, 0); ++#else ++ init_timer(&sdiodev->timer); ++ sdiodev->timer.data = (ulong) sdiodev; ++ sdiodev->timer.function = aicwf_sdio_bus_pwrctl; ++#endif ++ init_completion(&sdiodev->pwrctrl_trgg); ++#endif ++ ret = aicwf_bus_init(0, sdiodev->dev); ++ if (ret < 0) { ++ sdio_err("bus init fail\n"); ++ goto fail; ++ } ++ ++ ret = aicwf_bus_start(bus_if); ++ if (ret != 0) { ++ sdio_err("bus start fail\n"); ++ goto fail; ++ } ++ ++ return sdiodev; ++ ++fail: ++ aicwf_sdio_release(sdiodev); ++ return NULL; ++} ++ ++void get_fw_path(char* fw_path){ ++ if (strlen(aic_fw_path) > 0) { ++ memcpy(fw_path, aic_fw_path, strlen(aic_fw_path)); ++ }else{ ++ memcpy(fw_path, aic_default_fw_path, strlen(aic_default_fw_path)); ++ } ++} ++ ++int get_testmode(void){ ++ return testmode; ++} ++ ++struct sdio_func *get_sdio_func(void){ ++ return aicbsp_sdiodev->func; ++} ++ ++void set_irq_handler(void *fn){ ++ aicbsp_sdiodev->sdio_hal_irqhandler = (sdio_irq_handler_t *)fn; ++} ++ ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size) ++{ ++ uint8_t i; ++ uint8_t crc = 0; ++ if (cal_size==0) { ++ return crc; ++ } ++ while (cal_size--) { ++ for (i = 0x80; i > 0; i /= 2) { ++ if (crc & 0x80) { ++ crc *= 2; ++ crc ^= 0x07; //polynomial X8 + X2 + X + 1,(0x107) ++ } else { ++ crc *= 2; ++ } ++ if ((*p_buffer) & i) { ++ crc ^= 0x07; ++ } ++ } ++ p_buffer++; ++ } ++ return crc; ++} ++ ++EXPORT_SYMBOL(get_fw_path); ++EXPORT_SYMBOL(get_testmode); ++EXPORT_SYMBOL(get_sdio_func); ++EXPORT_SYMBOL(set_irq_handler); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h +new file mode 100644 +index 000000000000..65d73510ad3a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h +@@ -0,0 +1,149 @@ ++/** ++ * aicwf_sdio.h ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_SDMMC_H_ ++#define _AICWF_SDMMC_H_ ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include ++#include ++#include ++#include ++#include "aic_bsp_driver.h" ++ ++#define AICBSP_SDIO_NAME "aicbsp_sdio" ++#define SDIOWIFI_FUNC_BLOCKSIZE 512 ++ ++#define SDIO_VENDOR_ID_AIC 0x8800 ++#define SDIO_DEVICE_ID_AIC 0x0001 ++#define SDIOWIFI_BYTEMODE_LEN_REG 0x02 ++#define SDIOWIFI_INTR_CONFIG_REG 0x04 ++#define SDIOWIFI_SLEEP_REG 0x05 ++#define SDIOWIFI_WAKEUP_REG 0x09 ++#define SDIOWIFI_FLOW_CTRL_REG 0x0A ++#define SDIOWIFI_REGISTER_BLOCK 0x0B ++#define SDIOWIFI_BYTEMODE_ENABLE_REG 0x11 ++#define SDIOWIFI_BLOCK_CNT_REG 0x12 ++#define SDIOWIFI_FLOWCTRL_MASK_REG 0x7F ++#define SDIOWIFI_WR_FIFO_ADDR 0x07 ++#define SDIOWIFI_RD_FIFO_ADDR 0x08 ++ ++#define SDIOWIFI_INTR_ENABLE_REG_V3 0x00 ++#define SDIOWIFI_INTR_PENDING_REG_V3 0x01 ++#define SDIOWIFI_INTR_TO_DEVICE_REG_V3 0x02 ++#define SDIOWIFI_FLOW_CTRL_Q1_REG_V3 0x03 ++#define SDIOWIFI_MISC_INT_STATUS_REG_V3 0x04 ++#define SDIOWIFI_BYTEMODE_LEN_REG_V3 0x05 ++#define SDIOWIFI_BYTEMODE_LEN_MSB_REG_V3 0x06 ++#define SDIOWIFI_BYTEMODE_ENABLE_REG_V3 0x07 ++#define SDIOWIFI_MISC_CTRL_REG_V3 0x08 ++#define SDIOWIFI_FLOW_CTRL_Q2_REG_V3 0x09 ++#define SDIOWIFI_CLK_TEST_RESULT_REG_V3 0x0A ++#define SDIOWIFI_RD_FIFO_ADDR_V3 0x0F ++#define SDIOWIFI_WR_FIFO_ADDR_V3 0x10 ++ ++#define SDIOCLK_FREE_RUNNING_BIT (1 << 6) ++ ++#define SDIOWIFI_PWR_CTRL_INTERVAL 30 ++#define FLOW_CTRL_RETRY_COUNT 50 ++#define BUFFER_SIZE 1536 ++#define TAIL_LEN 4 ++#define TXQLEN (2048*4) ++ ++#define SDIO_SLEEP_ST 0 ++#define SDIO_ACTIVE_ST 1 ++ ++typedef enum { ++ SDIO_TYPE_DATA = 0X00, ++ SDIO_TYPE_CFG = 0X10, ++ SDIO_TYPE_CFG_CMD_RSP = 0X11, ++ SDIO_TYPE_CFG_DATA_CFM = 0X12 ++} sdio_type; ++ ++enum AICWF_IC{ ++ PRODUCT_ID_AIC8801 = 0, ++ PRODUCT_ID_AIC8800DC, ++ PRODUCT_ID_AIC8800DW, ++ PRODUCT_ID_AIC8800D80, ++ PRODUCT_ID_AIC8800D80X2 ++}; ++ ++struct aic_sdio_reg { ++ u8 bytemode_len_reg; ++ u8 intr_config_reg; ++ u8 sleep_reg; ++ u8 wakeup_reg; ++ u8 flow_ctrl_reg; ++ u8 flowctrl_mask_reg; ++ u8 register_block; ++ u8 bytemode_enable_reg; ++ u8 block_cnt_reg; ++ u8 misc_int_status_reg; ++ u8 rd_fifo_addr; ++ u8 wr_fifo_addr; ++}; ++ ++struct aic_sdio_dev { ++ struct rwnx_cmd_mgr cmd_mgr; ++ struct sdio_func *func; ++ struct sdio_func *func_msg; ++ struct device *dev; ++ struct aicwf_bus *bus_if; ++ ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ u32 state; ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ //for sdio pwr ctrl ++ struct timer_list timer; ++ uint active_duration; ++ struct completion pwrctrl_trgg; ++ struct task_struct *pwrctl_tsk; ++ spinlock_t pwrctl_lock; ++ struct semaphore pwrctl_wakeup_sema; ++#endif ++ u16 chipid; ++ u32 fw_version_uint; ++ struct aic_sdio_reg sdio_reg; ++ void (*sdio_hal_irqhandler) (struct sdio_func *func); ++}; ++ ++void *aicbsp_get_drvdata(void *args); ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func); ++void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func); ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration); ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target); ++#endif ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size, u8 msg); ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count); ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev); ++void aicbsp_sdio_exit(void); ++int aicbsp_sdio_init(void); ++void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt); ++int aicwf_sdio_bustx_thread(void *data); ++int aicwf_sdio_busrx_thread(void *data); ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt); ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv); ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv); ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv); ++extern void aicwf_hostif_ready(void); ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv); ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size); ++#endif /* AICWF_SDIO_SUPPORT */ ++ ++#endif /*_AICWF_SDMMC_H_*/ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c +new file mode 100644 +index 000000000000..84e6ca71c7ae +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c +@@ -0,0 +1,464 @@ ++/** ++ * aicwf_bus.c ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aicsdio_txrxif.h" ++#include "aic_bsp_driver.h" ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if; ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return -1; ++ } ++ bus_if = dev_get_drvdata(dev); ++ bus_if->cmd_buf = kzalloc(CMD_BUF_MAX, GFP_KERNEL); ++ if (!bus_if->cmd_buf) { ++ ret = -ENOMEM; ++ txrx_err("proto_attach failed\n"); ++ goto fail; ++ } ++ memset(bus_if->cmd_buf, '\0', CMD_BUF_MAX); ++ ++ init_completion(&bus_if->bustx_trgg); ++ init_completion(&bus_if->busrx_trgg); ++#ifdef AICWF_SDIO_SUPPORT ++ bus_if->bustx_thread = kthread_run(aicwf_sdio_bustx_thread, (void *)bus_if, "aicwf_bustx_thread"); ++ if (IS_ERR(bus_if->bustx_thread)) { ++ bus_if->bustx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ ret = -1; ++ goto fail; ++ } ++ ++ bus_if->busrx_thread = kthread_run(aicwf_sdio_busrx_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busrx_thread"); ++ if (IS_ERR(bus_if->busrx_thread)) { ++ bus_if->busrx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ ret = -1; ++ goto fail; ++ } ++ ++#endif ++ return ret; ++fail: ++ aicwf_bus_deinit(dev); ++ ++ return ret; ++} ++ ++void aicwf_bus_deinit(struct device *dev) ++{ ++ struct aicwf_bus *bus_if; ++ struct aic_sdio_dev *sdiodev; ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return; ++ } ++ sdio_dbg("%s", __func__); ++ bus_if = aicbsp_get_drvdata(dev); ++ aicwf_bus_stop(bus_if); ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ ++ if (bus_if->cmd_buf) { ++ kfree(bus_if->cmd_buf); ++ bus_if->cmd_buf = NULL; ++ } ++ ++ if (bus_if->bustx_thread) { ++ complete_all(&bus_if->bustx_trgg); ++ kthread_stop(bus_if->bustx_thread); ++ bus_if->bustx_thread = NULL; ++ } ++} ++ ++void aicwf_frame_tx(void *dev, struct sk_buff *skb) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ aicwf_bus_txdata(sdiodev->bus_if, skb); ++} ++ ++struct aicwf_tx_priv *aicwf_tx_init(void *arg) ++{ ++ struct aicwf_tx_priv *tx_priv; ++ ++ tx_priv = kzalloc(sizeof(struct aicwf_tx_priv), GFP_KERNEL); ++ if (!tx_priv) ++ return NULL; ++ ++ tx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++ ++ atomic_set(&tx_priv->aggr_count, 0); ++ tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN); ++ if (!tx_priv->aggr_buf) { ++ txrx_err("Alloc bus->txdata_buf failed!\n"); ++ kfree(tx_priv); ++ return NULL; ++ } ++ tx_priv->head = tx_priv->aggr_buf->data; ++ tx_priv->tail = tx_priv->aggr_buf->data; ++ ++ return tx_priv; ++} ++ ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv) ++{ ++ if (tx_priv && tx_priv->aggr_buf) ++ dev_kfree_skb(tx_priv->aggr_buf); ++ ++ kfree(tx_priv); ++ //tx_priv = NULL; ++} ++ ++static bool aicwf_another_ptk(struct sk_buff *skb) ++{ ++ u8 *data; ++ u16 aggr_len = 0; ++ ++ if (skb->data == NULL || skb->len == 0) { ++ return false; ++ } ++ data = skb->data; ++ aggr_len = (*skb->data | (*(skb->data + 1) << 8)); ++ if (aggr_len == 0) { ++ return false; ++ } ++ ++ return true; ++} ++ ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv) ++{ ++ int ret = 0; ++ unsigned long flags = 0; ++ struct sk_buff *skb = NULL; ++ u16 pkt_len = 0; ++ struct sk_buff *skb_inblock = NULL; ++ u16 aggr_len = 0, adjust_len = 0; ++ u8 *data = NULL; ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ skb = aicwf_frame_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (skb == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ while (aicwf_another_ptk(skb)) { ++ data = skb->data; ++ pkt_len = (*skb->data | (*(skb->data + 1) << 8)); ++ ++ if ((skb->data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv ++ if (skb_inblock == NULL) { ++ txrx_err("no more space!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ #if 0 ++ rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ #endif ++ skb_pull(skb, adjust_len); ++ } else { // type : config ++ aggr_len = pkt_len; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len+4, GFP_KERNEL); ++ if (skb_inblock == NULL) { ++ txrx_err("no more space!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ ++ skb_put(skb_inblock, aggr_len+4); ++ memcpy(skb_inblock->data, data, aggr_len+4); ++ if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) ++ rwnx_rx_handle_msg(rx_priv->sdiodev, (struct ipc_e2a_msg *)(skb_inblock->data + 4)); ++ #if 0 ++ if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) ++ aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(skb_inblock->data + 4)); ++ #endif ++ skb_pull(skb, adjust_len+4); ++ } ++ } ++ ++ /* skb_inblock no used currently, just free it! */ ++ dev_kfree_skb(skb_inblock); ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(rx_priv->sdiodev, SDIO_ACTIVE_ST); ++#endif ++ ++ return ret; ++} ++ ++static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize) ++{ ++ int i; ++ struct recv_msdu *req, *reqs; ++ ++ reqs = vmalloc(qsize*sizeof(struct recv_msdu)); ++ if (reqs == NULL) ++ return NULL; ++ ++ req = reqs; ++ for (i = 0; i < qsize; i++) { ++ INIT_LIST_HEAD(&req->rxframe_list); ++ list_add(&req->rxframe_list, q); ++ req->len = 0; ++ req++; ++ } ++ ++ return reqs; ++} ++ ++struct aicwf_rx_priv *aicwf_rx_init(void *arg) ++{ ++ struct aicwf_rx_priv *rx_priv; ++ rx_priv = kzalloc(sizeof(struct aicwf_rx_priv), GFP_KERNEL); ++ if (!rx_priv) ++ return NULL; ++ ++ rx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++ aicwf_frame_queue_init(&rx_priv->rxq, 1, MAX_RXQLEN); ++ spin_lock_init(&rx_priv->rxqlock); ++ atomic_set(&rx_priv->rx_cnt, 0); ++ ++ INIT_LIST_HEAD(&rx_priv->rxframes_freequeue); ++ spin_lock_init(&rx_priv->freeq_lock); ++ rx_priv->recv_frames = aicwf_rxframe_queue_init(&rx_priv->rxframes_freequeue, MAX_REORD_RXFRAME); ++ if (!rx_priv->recv_frames) { ++ txrx_err("no enough buffer for free recv frame queue!\n"); ++ kfree(rx_priv); ++ return NULL; ++ } ++ spin_lock_init(&rx_priv->stas_reord_lock); ++ INIT_LIST_HEAD(&rx_priv->stas_reord_list); ++ ++ return rx_priv; ++} ++ ++ ++static void aicwf_recvframe_queue_deinit(struct list_head *q) ++{ ++ struct recv_msdu *req, *next; ++ ++ list_for_each_entry_safe(req, next, q, rxframe_list) { ++ list_del_init(&req->rxframe_list); ++ } ++} ++ ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv) ++{ ++ if (rx_priv->sdiodev->bus_if->busrx_thread) { ++ complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg); ++ kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread); ++ rx_priv->sdiodev->bus_if->busrx_thread = NULL; ++ } ++ ++ aicwf_frame_queue_flush(&rx_priv->rxq); ++ aicwf_recvframe_queue_deinit(&rx_priv->rxframes_freequeue); ++ if (rx_priv->recv_frames) ++ vfree(rx_priv->recv_frames); ++ ++ kfree(rx_priv); ++ //rx_priv = NULL; ++} ++ ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt) ++{ ++ return aicwf_frame_enq(dev, q, pkt, 0); ++} ++ ++ ++void aicwf_dev_skb_free(struct sk_buff *skb) ++{ ++ if (!skb) ++ return; ++ ++ dev_kfree_skb_any(skb); ++} ++ ++static struct sk_buff *aicwf_frame_queue_penq(struct frame_queue *pq, int prio, struct sk_buff *p) ++{ ++ struct sk_buff_head *q; ++ ++ if (pq->queuelist[prio].qlen >= pq->qmax) ++ return NULL; ++ ++ q = &pq->queuelist[prio]; ++ __skb_queue_tail(q, p); ++ pq->qcnt++; ++ if (pq->hi_prio < prio) ++ pq->hi_prio = (u16)prio; ++ ++ return p; ++} ++ ++void aicwf_frame_queue_flush(struct frame_queue *pq) ++{ ++ int prio; ++ struct sk_buff_head *q; ++ struct sk_buff *p, *next; ++ ++ for (prio = 0; prio < pq->num_prio; prio++) { ++ q = &pq->queuelist[prio]; ++ skb_queue_walk_safe(q, p, next) { ++ skb_unlink(p, q); ++ aicwf_dev_skb_free(p); ++ pq->qcnt--; ++ } ++ } ++} ++ ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len) ++{ ++ int prio; ++ ++ memset(pq, 0, offsetof(struct frame_queue, queuelist) + (sizeof(struct sk_buff_head) * num_prio)); ++ pq->num_prio = (u16)num_prio; ++ pq->qmax = (u16)max_len; ++ ++ for (prio = 0; prio < num_prio; prio++) { ++ skb_queue_head_init(&pq->queuelist[prio]); ++ } ++} ++ ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out) ++{ ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ for (prio = 0; prio < pq->hi_prio; prio++) ++ if (!skb_queue_empty(&pq->queuelist[prio])) ++ break; ++ ++ if (prio_out) ++ *prio_out = prio; ++ ++ return skb_peek_tail(&pq->queuelist[prio]); ++} ++ ++bool aicwf_is_framequeue_empty(struct frame_queue *pq) ++{ ++ int prio, len = 0; ++ ++ for (prio = 0; prio <= pq->hi_prio; prio++) ++ len += pq->queuelist[prio].qlen; ++ ++ if (len > 0) ++ return false; ++ else ++ return true; ++} ++ ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq) ++{ ++ struct sk_buff_head *q; ++ struct sk_buff *p; ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ while ((prio = pq->hi_prio) > 0 && skb_queue_empty(&pq->queuelist[prio])) ++ pq->hi_prio--; ++ ++ q = &pq->queuelist[prio]; ++ p = __skb_dequeue(q); ++ if (p == NULL) ++ return NULL; ++ ++ pq->qcnt--; ++ ++ return p; ++} ++ ++static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio) ++{ ++ struct sk_buff_head *q = &pq->queuelist[prio]; ++ struct sk_buff *p = skb_dequeue_tail(q); ++ ++ if (!p) ++ return NULL; ++ ++ pq->qcnt--; ++ return p; ++} ++ ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio) ++{ ++ struct sk_buff *p = NULL; ++ int prio_modified = -1; ++ ++ if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { ++ aicwf_frame_queue_penq(q, prio, pkt); ++ return true; ++ } ++ if (q->queuelist[prio].qlen >= q->qmax) { ++ prio_modified = prio; ++ } else if (q->qcnt >= q->qmax) { ++ p = aicwf_frame_queue_peek_tail(q, &prio_modified); ++ if (prio_modified > prio) ++ return false; ++ } ++ ++ if (prio_modified >= 0) { ++ if (prio_modified == prio) ++ return false; ++ ++ p = aicwf_skb_dequeue_tail(q, prio_modified); ++ aicwf_dev_skb_free(p); ++ ++ p = aicwf_frame_queue_penq(q, prio_modified, pkt); ++ if (p == NULL) ++ txrx_err("failed\n"); ++ } ++ ++ return p != NULL; ++} ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h +new file mode 100644 +index 000000000000..801e0ea4965c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h +@@ -0,0 +1,214 @@ ++/** ++ * aicwf_txrxif.h ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_TXRXIF_H_ ++#define _AICWF_TXRXIF_H_ ++ ++#include ++#include ++#include "aicsdio.h" ++ ++#define CMD_BUF_MAX 1536 ++#define TXPKT_BLOCKSIZE 512 ++#define MAX_AGGR_TXPKT_LEN (1536*4) ++#define CMD_TX_TIMEOUT 5000 ++#define TX_ALIGNMENT 4 ++ ++#define RX_HWHRD_LEN 60 //58->60 word allined ++#define CCMP_OR_WEP_INFO 8 ++#define MAX_RXQLEN 2000 ++#define RX_ALIGNMENT 4 ++ ++#define DEBUG_ERROR_LEVEL 0 ++#define DEBUG_DEBUG_LEVEL 1 ++#define DEBUG_INFO_LEVEL 2 ++ ++#define DBG_LEVEL DEBUG_DEBUG_LEVEL ++ ++#define txrx_err(fmt, ...) pr_err("aicbsp: txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define sdio_err(fmt, ...) pr_err("aicbsp: sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define usb_err(fmt, ...) pr_err("aicbsp: usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL ++#define sdio_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#define usb_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#else ++#define sdio_dbg(fmt, ...) ++#define usb_dbg(fmt, ...) ++#endif ++#if DBG_LEVEL >= DEBUG_INFO_LEVEL ++#define sdio_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#define usb_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#else ++#define sdio_info(fmt, ...) ++#define usb_info(fmt, ...) ++#endif ++ ++enum aicwf_bus_state { ++ BUS_DOWN_ST, ++ BUS_UP_ST ++}; ++ ++struct aicwf_bus_ops { ++ int (*start) (struct device *dev); ++ void (*stop) (struct device *dev); ++ int (*txdata) (struct device *dev, struct sk_buff *skb); ++ int (*txmsg) (struct device *dev, u8 *msg, uint len); ++}; ++ ++struct frame_queue { ++ u16 num_prio; ++ u16 hi_prio; ++ u16 qmax; /* max number of queued frames */ ++ u16 qcnt; ++ struct sk_buff_head queuelist[8]; ++}; ++ ++struct aicwf_bus { ++ union { ++ struct aic_sdio_dev *sdio; ++ struct aic_usb_dev *usb; ++ } bus_priv; ++ struct device *dev; ++ struct aicwf_bus_ops *ops; ++ enum aicwf_bus_state state; ++ u8 *cmd_buf; ++ struct completion bustx_trgg; ++ struct completion busrx_trgg; ++ struct task_struct *bustx_thread; ++ struct task_struct *busrx_thread; ++}; ++ ++struct aicwf_tx_priv { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++ int fw_avail_bufcnt; ++ //for cmd tx ++ u8 *cmd_buf; ++ uint cmd_len; ++ bool cmd_txstate; ++ bool cmd_tx_succ; ++ struct semaphore cmd_txsema; ++ wait_queue_head_t cmd_txdone_wait; ++ //for data tx ++ atomic_t tx_pktcnt; ++ ++ struct frame_queue txq; ++ spinlock_t txqlock; ++ struct semaphore txctl_sema; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ struct sk_buff *aggr_buf; ++ atomic_t aggr_count; ++ u8 *head; ++ u8 *tail; ++}; ++ ++ ++#define MAX_REORD_RXFRAME 250 ++#define REORDER_UPDATE_TIME 50 ++#define AICWF_REORDER_WINSIZE 64 ++#define SN_LESS(a, b) (((a-b)&0x800) != 0) ++#define SN_EQUAL(a, b) (a == b) ++ ++struct reord_ctrl { ++ struct aicwf_rx_priv *rx_priv; ++ u8 enable; ++ u16 ind_sn; ++ u8 wsize_b; ++ spinlock_t reord_list_lock; ++ struct list_head reord_list; ++ struct timer_list reord_timer; ++ struct work_struct reord_timer_work; ++}; ++ ++struct reord_ctrl_info { ++ u8 mac_addr[6]; ++ struct reord_ctrl preorder_ctrl[8]; ++ struct list_head list; ++}; ++ ++struct recv_msdu { ++ struct sk_buff *pkt; ++ u8 tid; ++ u16 seq_num; ++ uint len; ++ u8 *rx_data; ++ //for pending rx reorder list ++ struct list_head reord_pending_list; ++ //for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue ++ struct list_head rxframe_list; ++ struct reord_ctrl *preorder_ctrl; ++}; ++ ++struct aicwf_rx_priv { ++ struct aic_sdio_dev *sdiodev; ++ void *rwnx_vif; ++ atomic_t rx_cnt; ++ u32 data_len; ++ spinlock_t rxqlock; ++ struct frame_queue rxq; ++ ++ spinlock_t freeq_lock; ++ struct list_head rxframes_freequeue; ++ struct list_head stas_reord_list; ++ spinlock_t stas_reord_lock; ++ struct recv_msdu *recv_frames; ++}; ++ ++static inline int aicwf_bus_start(struct aicwf_bus *bus) ++{ ++ return bus->ops->start(bus->dev); ++} ++ ++static inline void aicwf_bus_stop(struct aicwf_bus *bus) ++{ ++ bus->ops->stop(bus->dev); ++} ++ ++static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb) ++{ ++ return bus->ops->txdata(bus->dev, skb); ++} ++ ++static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len) ++{ ++ return bus->ops->txmsg(bus->dev, msg, len); ++} ++ ++static inline void aicwf_sched_timeout(u32 millisec) ++{ ++ ulong timeout = 0, expires = 0; ++ expires = jiffies + msecs_to_jiffies(millisec); ++ timeout = millisec; ++ ++ while (timeout) { ++ timeout = schedule_timeout(timeout); ++ if (time_after(jiffies, expires)) ++ break; ++ } ++} ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev); ++void aicwf_bus_deinit(struct device *dev); ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv); ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv); ++struct aicwf_tx_priv *aicwf_tx_init(void *arg); ++struct aicwf_rx_priv *aicwf_rx_init(void *arg); ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len); ++void aicwf_frame_queue_flush(struct frame_queue *pq); ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio); ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt); ++bool aicwf_is_framequeue_empty(struct frame_queue *pq); ++void aicwf_frame_tx(void *dev, struct sk_buff *skb); ++void aicwf_dev_skb_free(struct sk_buff *skb); ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq); ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out); ++ ++#endif /* _AICWF_TXRXIF_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c +new file mode 100644 +index 000000000000..77130f76bafa +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c +@@ -0,0 +1,16138 @@ ++#include ++ ++char fmacfw[259592] = { ++0x00, 0x38, 0x18, 0x00, 0x89, 0x01, 0x12, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0xA1, 0xCA, 0x12, 0x00, 0xA9, 0xCA, 0x12, 0x00, ++0xB1, 0xCA, 0x12, 0x00, 0xB9, 0xCA, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x12, 0x00, ++0xA5, 0xC6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0xBB, 0x12, 0x00, 0x19, 0x1E, 0x14, 0x00, 0x35, 0xEE, 0x12, 0x00, ++0x49, 0xED, 0x12, 0x00, 0x79, 0x5C, 0x13, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x79, 0x5C, 0x13, 0x00, 0x49, 0x11, 0x12, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x65, 0x5A, 0x12, 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, 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, 0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, ++0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, 0x7D, 0x4A, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x99, 0x1A, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x8D, 0x52, 0x12, 0x00, 0x79, 0x51, 0x12, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xCD, 0x5B, 0x12, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x05, 0x48, 0x00, 0x68, 0x10, 0xF0, 0x00, 0x4F, ++0x0C, 0xBF, 0x04, 0x48, 0x20, 0xF0, 0x7F, 0x40, 0x80, 0xF3, 0x08, 0x88, 0x02, 0x48, 0x00, 0x47, 0x44, 0x01, 0x50, 0x40, ++0x00, 0x38, 0x18, 0x00, 0x05, 0xC7, 0x12, 0x00, 0xF0, 0xB4, 0x86, 0x07, 0x46, 0xD0, 0x54, 0x1E, 0x00, 0x2A, 0x3C, 0xD0, ++0xCA, 0xB2, 0x03, 0x46, 0x01, 0xE0, 0x01, 0x3C, 0x37, 0xD3, 0x03, 0xF8, 0x01, 0x2B, 0x9D, 0x07, 0xF9, 0xD1, 0x03, 0x2C, ++0x2A, 0xD9, 0xCD, 0xB2, 0x45, 0xEA, 0x05, 0x25, 0x0F, 0x2C, 0x45, 0xEA, 0x05, 0x45, 0x34, 0xD9, 0xA4, 0xF1, 0x10, 0x02, ++0x22, 0xF0, 0x0F, 0x0C, 0x03, 0xF1, 0x20, 0x07, 0x16, 0x09, 0x67, 0x44, 0x03, 0xF1, 0x10, 0x02, 0x42, 0xE9, 0x04, 0x55, ++0x42, 0xE9, 0x02, 0x55, 0x10, 0x32, 0xBA, 0x42, 0xF8, 0xD1, 0x72, 0x1C, 0x14, 0xF0, 0x0C, 0x0F, 0x03, 0xEB, 0x02, 0x12, ++0x04, 0xF0, 0x0F, 0x06, 0x13, 0xD0, 0x33, 0x1F, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x42, 0xF8, 0x04, 0x5B, ++0x93, 0x42, 0xFB, 0xD1, 0x06, 0xF0, 0x03, 0x04, 0x2C, 0xB1, 0xCA, 0xB2, 0x1C, 0x44, 0x03, 0xF8, 0x01, 0x2B, 0x9C, 0x42, ++0xFB, 0xD1, 0xF0, 0xBC, 0x70, 0x47, 0x34, 0x46, 0x13, 0x46, 0x00, 0x2C, 0xF3, 0xD1, 0xF8, 0xE7, 0x14, 0x46, 0x03, 0x46, ++0xC1, 0xE7, 0x1A, 0x46, 0x26, 0x46, 0xE0, 0xE7, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x68, 0x91, 0x4F, 0x4F, 0xD9, 0xF8, ++0x00, 0x60, 0xDF, 0xF8, 0x64, 0xC1, 0x33, 0x89, 0xD6, 0xF8, 0x34, 0xE0, 0xC7, 0xF8, 0x10, 0xE0, 0xD6, 0xE9, 0x09, 0x10, ++0xD6, 0xE9, 0x0B, 0x45, 0x39, 0x60, 0xC9, 0x08, 0x03, 0x29, 0x78, 0x60, 0x4F, 0xEA, 0xD0, 0x00, 0x38, 0xBF, 0x03, 0x21, ++0xBC, 0x60, 0x03, 0x28, 0x4F, 0xEA, 0xD4, 0x04, 0x38, 0xBF, 0x03, 0x20, 0xFD, 0x60, 0x03, 0x2C, 0x4F, 0xEA, 0xD5, 0x05, ++0x4F, 0xF0, 0x54, 0x02, 0x4F, 0xEA, 0xDE, 0x07, 0x2C, 0xF0, 0x03, 0x0C, 0x38, 0xBF, 0x03, 0x24, 0xDF, 0xF8, 0x1C, 0xE1, ++0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0xA1, 0xC8, 0xF8, 0x00, 0x10, 0x03, 0x2D, 0x03, 0xFB, 0x02, 0x22, 0x38, 0xBF, ++0x03, 0x25, 0x62, 0x44, 0x03, 0x2F, 0x38, 0xBF, 0x03, 0x27, 0x72, 0x45, 0xC8, 0xE9, 0x01, 0x04, 0xC8, 0xE9, 0x03, 0x57, ++0xCA, 0xF8, 0x00, 0xC0, 0x4F, 0xD8, 0x01, 0x33, 0xDF, 0xF8, 0xF4, 0xE0, 0x2E, 0x4A, 0xDF, 0xF8, 0xF4, 0x80, 0xDF, 0xF8, ++0xF4, 0x90, 0x4F, 0xF0, 0x58, 0x0C, 0x0C, 0xFB, 0x03, 0xE3, 0xD2, 0xF8, 0x00, 0xC0, 0x2A, 0x4A, 0x13, 0x60, 0x4F, 0xF4, ++0xAC, 0x72, 0x02, 0xFB, 0x01, 0x33, 0x02, 0xFB, 0x00, 0x30, 0x02, 0xFB, 0x04, 0x04, 0x02, 0xFB, 0x05, 0x45, 0xDC, 0xF8, ++0x00, 0x10, 0xC8, 0xF8, 0x00, 0x50, 0x02, 0xFB, 0x07, 0x52, 0xC9, 0xF8, 0x00, 0x40, 0x21, 0x4F, 0x21, 0x4D, 0x22, 0x4C, ++0x38, 0x60, 0x2B, 0x60, 0xC4, 0xF8, 0x00, 0xE0, 0x41, 0xB9, 0xDC, 0xF8, 0x04, 0x30, 0x04, 0x33, 0x11, 0x1D, 0x23, 0xF0, ++0x03, 0x03, 0xCC, 0xF8, 0x00, 0x10, 0x1A, 0x44, 0xDC, 0xF8, 0x08, 0x30, 0x13, 0xB9, 0x04, 0x32, 0xCC, 0xF8, 0x08, 0x20, ++0x18, 0x4B, 0xF2, 0x68, 0x1A, 0x60, 0x33, 0x78, 0x02, 0x2B, 0x0E, 0xD0, 0x01, 0x2B, 0x01, 0xD0, 0xBD, 0xE8, 0xF0, 0x87, ++0x72, 0x69, 0x00, 0x2A, 0xFA, 0xD0, 0x13, 0x49, 0x91, 0x42, 0xF7, 0xD9, 0xBD, 0xE8, 0xF0, 0x47, 0x11, 0x48, 0x05, 0xF0, ++0xC1, 0xBF, 0x32, 0x69, 0xF3, 0xE7, 0x71, 0x46, 0x0F, 0x48, 0x05, 0xF0, 0xBB, 0xFF, 0xD9, 0xF8, 0x00, 0x60, 0xD8, 0xF8, ++0x00, 0x10, 0x33, 0x89, 0xD8, 0xE9, 0x01, 0x04, 0xD8, 0xE9, 0x03, 0x57, 0x01, 0x33, 0xA1, 0xE7, 0x7C, 0x28, 0x17, 0x00, ++0x30, 0x36, 0x17, 0x00, 0xEC, 0x57, 0x18, 0x00, 0xF4, 0x57, 0x18, 0x00, 0xF0, 0x57, 0x18, 0x00, 0x14, 0x63, 0x18, 0x00, ++0x00, 0x38, 0x18, 0x00, 0x00, 0x38, 0x18, 0x00, 0x44, 0x76, 0x15, 0x00, 0x18, 0x76, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, ++0x2B, 0x07, 0x18, 0x00, 0x00, 0x24, 0x18, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x40, 0x61, 0x17, 0x00, 0xE0, 0x9F, 0x18, 0x00, ++0xFC, 0x57, 0x18, 0x00, 0xF8, 0x57, 0x18, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x49, 0x4C, 0x4A, 0x49, 0x4A, 0x4E, 0x4B, 0x4A, ++0x4B, 0x4D, 0x4C, 0x48, 0x0C, 0x60, 0x04, 0xF1, 0x44, 0x07, 0x21, 0x1D, 0xD4, 0xF8, 0xD0, 0x30, 0x37, 0x60, 0x04, 0xF1, ++0x80, 0x07, 0x11, 0x60, 0x2F, 0x60, 0x47, 0x49, 0x47, 0x4A, 0x04, 0xF1, 0x90, 0x05, 0x23, 0xF0, 0x7F, 0x43, 0x05, 0x60, ++0x04, 0xF1, 0xA8, 0x00, 0x08, 0x60, 0x23, 0xF0, 0xFF, 0x03, 0x04, 0xF1, 0xAA, 0x01, 0x11, 0x60, 0x83, 0xB1, 0x94, 0xF8, ++0xD1, 0x30, 0x23, 0xB1, 0x3F, 0x4A, 0x53, 0x6D, 0x23, 0xF0, 0x01, 0x03, 0x53, 0x65, 0x94, 0xF8, 0xD2, 0x30, 0x00, 0x2B, ++0x5B, 0xD1, 0x3B, 0x4B, 0x4F, 0xF0, 0x80, 0x62, 0xC3, 0xF8, 0x10, 0x21, 0x39, 0x4D, 0x3A, 0x4F, 0xD5, 0xF8, 0x30, 0x32, ++0xDF, 0xF8, 0xF8, 0x80, 0x98, 0x47, 0x01, 0x21, 0x00, 0x20, 0x05, 0xF0, 0x5F, 0xFF, 0x00, 0x20, 0x05, 0xF0, 0x9A, 0xFF, ++0x01, 0x21, 0x02, 0x20, 0x05, 0xF0, 0x58, 0xFF, 0x02, 0x20, 0x05, 0xF0, 0x93, 0xFF, 0x01, 0x21, 0x03, 0x20, 0x05, 0xF0, ++0x51, 0xFF, 0x03, 0x20, 0x05, 0xF0, 0x8C, 0xFF, 0x3B, 0x68, 0x03, 0xF0, 0x0F, 0x03, 0xA3, 0xF1, 0x0A, 0x03, 0xB3, 0xFA, ++0x83, 0xF3, 0x5B, 0x09, 0x88, 0xF8, 0x02, 0x30, 0x25, 0xF0, 0x0E, 0xFA, 0x05, 0xF0, 0x90, 0xFA, 0x06, 0xF0, 0x54, 0xF8, ++0xD5, 0xF8, 0x74, 0x32, 0x98, 0x47, 0x94, 0xF8, 0x44, 0x10, 0x23, 0x48, 0x24, 0xF0, 0xEE, 0xF8, 0x07, 0xF0, 0x8C, 0xF8, ++0x06, 0xF0, 0xA8, 0xF9, 0x98, 0xF8, 0x02, 0x30, 0x0B, 0xB3, 0xD5, 0xF8, 0x6C, 0x34, 0x98, 0x47, 0x1D, 0x4A, 0x1E, 0x49, ++0x13, 0x68, 0x23, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0x0F, 0x03, 0x3B, 0x60, 0x02, 0x20, 0x24, 0xF0, ++0x27, 0xF9, 0x33, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x02, 0xD1, 0x17, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD5, 0xF8, 0x80, 0x32, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x0D, 0x4A, 0x53, 0x6D, 0x23, 0xF0, 0x02, 0x03, 0x53, 0x65, 0x9D, 0xE7, 0x11, 0x49, ++0x02, 0x20, 0x24, 0xF0, 0x11, 0xF9, 0xE8, 0xE7, 0x2C, 0x19, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, ++0xC8, 0x35, 0x17, 0x00, 0x30, 0x36, 0x17, 0x00, 0xAC, 0x35, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x00, 0x58, 0x40, 0x70, 0x76, 0x15, 0x00, 0x10, 0x00, 0x58, 0x40, ++0x80, 0x76, 0x15, 0x00, 0x00, 0x41, 0x04, 0x40, 0x8C, 0x76, 0x15, 0x00, 0x3C, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x20, 0x4B, ++0x04, 0x46, 0x1E, 0x68, 0x1D, 0x68, 0x00, 0xF0, 0xAB, 0xFE, 0x07, 0x46, 0x00, 0xF0, 0xAA, 0xFE, 0x01, 0x2C, 0xC6, 0xF3, ++0x03, 0x26, 0xC5, 0xF3, 0xC0, 0x65, 0x14, 0xD0, 0x02, 0x2C, 0x0E, 0xD0, 0x3C, 0xB1, 0x18, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x1C, 0xDB, 0x00, 0x20, 0xF8, 0xBD, 0x90, 0xB9, 0x05, 0xBB, 0x70, 0x1E, 0x18, 0xBF, 0x01, 0x20, ++0xF8, 0xBD, 0x01, 0x2E, 0x0D, 0xD0, 0x68, 0x1D, 0xF8, 0xBD, 0x30, 0xB9, 0x01, 0x2E, 0x17, 0xD0, 0x00, 0x2F, 0x0C, 0xBF, ++0x03, 0x20, 0x09, 0x20, 0xF8, 0xBD, 0x0B, 0x20, 0xF8, 0xBD, 0x0A, 0x20, 0xF8, 0xBD, 0x00, 0x2D, 0x14, 0xBF, 0x07, 0x20, ++0x04, 0x20, 0xF8, 0xBD, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xB5, 0x12, 0x24, 0xF0, 0xDC, 0xFA, 0x00, 0x20, 0xF8, 0xBD, ++0x08, 0x20, 0xF8, 0xBD, 0x02, 0x20, 0xF8, 0xBD, 0x00, 0x00, 0x33, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x10, 0xB4, 0x09, 0x49, 0x0B, 0x69, 0x83, 0xB0, 0x18, 0x44, 0x20, 0x24, 0x01, 0x94, 0x01, 0x9B, ++0x5A, 0x1E, 0x01, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x0B, 0x69, 0x1B, 0x1A, 0x00, 0x2B, 0xF5, 0xDB, 0x03, 0xB0, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x08, 0xB5, 0xFF, 0xF7, 0x9D, 0xFF, 0x03, 0x4B, 0x1A, 0x78, 0x82, 0x42, ++0x18, 0xBF, 0x18, 0x70, 0x08, 0xBD, 0x00, 0xBF, 0x60, 0x25, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4B, 0x10, 0x4C, 0x18, 0x68, ++0xC0, 0xF3, 0x01, 0x60, 0xFF, 0xF7, 0x8C, 0xFF, 0x08, 0x22, 0x05, 0x46, 0x00, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0xB6, 0xFD, ++0x0B, 0x48, 0x0C, 0x4A, 0x00, 0xEB, 0x05, 0x10, 0xFF, 0x21, 0xC3, 0x88, 0x80, 0x88, 0x10, 0x60, 0xC3, 0xF3, 0x85, 0x12, ++0x03, 0xF0, 0x3F, 0x03, 0x1A, 0x44, 0x21, 0x70, 0x4F, 0xF4, 0x96, 0x63, 0xB3, 0xFB, 0xF2, 0xF3, 0x63, 0x70, 0x38, 0xBD, ++0x00, 0x00, 0x33, 0x40, 0x60, 0x25, 0x17, 0x00, 0x98, 0x76, 0x15, 0x00, 0x6C, 0x00, 0x34, 0x40, 0x01, 0x4B, 0x58, 0x78, ++0x70, 0x47, 0x00, 0xBF, 0x60, 0x25, 0x17, 0x00, 0x10, 0xB4, 0x13, 0x4B, 0x13, 0x49, 0x11, 0x22, 0x1A, 0x60, 0x08, 0x69, ++0x83, 0xB0, 0x0A, 0x30, 0x20, 0x24, 0x00, 0x94, 0x00, 0x9B, 0x5A, 0x1E, 0x00, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x0A, 0x69, ++0x12, 0x1A, 0x00, 0x2A, 0xF5, 0xDB, 0x0A, 0x4A, 0x0A, 0x4C, 0x13, 0x60, 0x09, 0x69, 0x20, 0x20, 0x0A, 0x31, 0x01, 0x90, ++0x01, 0x9B, 0x5A, 0x1E, 0x01, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x23, 0x69, 0x5B, 0x1A, 0x00, 0x2B, 0xF5, 0xDB, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x00, 0x34, 0x40, 0x00, 0x10, 0x50, 0x40, 0x16, 0x4A, 0x13, 0x68, ++0x43, 0xF4, 0x80, 0x53, 0x10, 0xB4, 0x13, 0x60, 0x00, 0xBF, 0x02, 0xF5, 0x99, 0x42, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x53, ++0x13, 0x60, 0x00, 0xBF, 0x10, 0x4B, 0x11, 0x48, 0x03, 0xF5, 0x00, 0x64, 0xC0, 0x1A, 0x1A, 0x18, 0x53, 0xF8, 0x04, 0x1B, ++0x11, 0x60, 0xA3, 0x42, 0xF9, 0xD1, 0x00, 0xBF, 0x09, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x00, 0xBF, ++0x1A, 0x68, 0x22, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x00, 0xBF, 0x07, 0x4A, 0x5D, 0xF8, 0x04, 0x4B, 0x13, 0x68, 0x23, 0xF0, ++0x00, 0x53, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x90, 0xB3, 0x33, 0x40, 0xB0, 0x05, 0x17, 0x00, 0x00, 0xA0, 0x33, 0x40, ++0x10, 0x00, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x15, 0x46, 0x1C, 0x46, 0x9D, 0xF8, 0x18, 0x80, 0x0E, 0x46, ++0xFF, 0xF7, 0x94, 0xFF, 0x6C, 0x4A, 0x13, 0x68, 0x01, 0x2F, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x00, 0xF0, 0x98, 0x80, ++0x69, 0x4A, 0x6A, 0x49, 0x13, 0x68, 0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x40, 0x43, 0x13, 0x60, 0x0B, 0x68, 0x02, 0xF5, ++0xD9, 0x32, 0x02, 0xF5, 0xA2, 0x72, 0x43, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, ++0x61, 0x4A, 0x10, 0x68, 0x20, 0xF4, 0xFF, 0x40, 0x20, 0xF0, 0x7F, 0x00, 0x4F, 0xF0, 0x80, 0x63, 0xB3, 0xFB, 0xF5, 0xF3, ++0xC3, 0xF3, 0x0E, 0x03, 0x03, 0x43, 0x01, 0x2C, 0x13, 0x60, 0x60, 0xD0, 0x02, 0x2C, 0x48, 0xD0, 0x00, 0x25, 0x59, 0x4B, ++0x1E, 0x68, 0x26, 0xF0, 0x03, 0x06, 0x35, 0x43, 0x1D, 0x60, 0x00, 0x23, 0x56, 0x4A, 0x57, 0x49, 0x13, 0x60, 0x0B, 0x68, ++0x56, 0x4D, 0x57, 0x48, 0x57, 0x4E, 0x22, 0x06, 0x02, 0xF0, 0x40, 0x72, 0x23, 0xF0, 0x40, 0x73, 0x13, 0x43, 0x0B, 0x60, ++0x29, 0x68, 0x23, 0x04, 0x21, 0xF4, 0x40, 0x31, 0x03, 0xF4, 0x40, 0x33, 0x0B, 0x43, 0x2B, 0x60, 0x03, 0x68, 0x23, 0xF0, ++0x80, 0x43, 0x03, 0x60, 0x31, 0x68, 0x05, 0xF5, 0x82, 0x35, 0x04, 0xF0, 0x0F, 0x03, 0x21, 0xF0, 0x0F, 0x01, 0x05, 0xF5, ++0x88, 0x75, 0x0B, 0x43, 0x33, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0x40, 0x73, 0x1A, 0x43, 0x2A, 0x60, 0xEC, 0xB9, 0x50, 0xF8, ++0x08, 0x3C, 0x45, 0x49, 0x45, 0x4A, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0xC8, 0x53, 0x40, 0xF8, 0x08, 0x3C, 0x0B, 0x68, ++0x23, 0xF0, 0x30, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0x1C, 0x43, 0x13, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0xAD, 0x1B, 0x00, 0x2D, 0x42, 0xDD, 0x0A, 0x2D, 0xCC, 0xBF, 0x00, 0x25, 0x01, 0x25, 0xAF, 0xE7, 0x01, 0x2C, ++0x41, 0xD0, 0x38, 0x4A, 0x38, 0x49, 0x13, 0x68, 0x38, 0x48, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0x60, 0x63, 0x13, 0x60, ++0x08, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0xF5, 0x28, 0x42, 0xB5, 0x42, 0x53, 0x6B, 0x88, 0xBF, 0x01, 0x21, 0x23, 0xF0, ++0x03, 0x03, 0x98, 0xBF, 0x02, 0x21, 0x43, 0xEA, 0x01, 0x03, 0x02, 0xF1, 0x34, 0x02, 0x13, 0x60, 0x94, 0xBF, 0x01, 0x23, ++0x00, 0x23, 0x95, 0xE7, 0x1D, 0x49, 0x1E, 0x48, 0x0B, 0x68, 0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0xC0, 0x33, 0x0B, 0x60, ++0x03, 0x68, 0x01, 0xF5, 0xD9, 0x31, 0x01, 0xF5, 0xA2, 0x71, 0x23, 0xF0, 0x01, 0x03, 0x03, 0x60, 0x0B, 0x68, 0x18, 0xF0, ++0x04, 0x0F, 0x43, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x3F, 0xF4, 0x64, 0xAF, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, ++0x5E, 0xE7, 0x15, 0xF1, 0x0A, 0x0F, 0xB4, 0xBF, 0x03, 0x25, 0x02, 0x25, 0x6B, 0xE7, 0x1A, 0x48, 0x14, 0x49, 0x03, 0x68, ++0x14, 0x4A, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0xC0, 0x53, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x30, 0x03, 0x43, 0xF0, ++0x10, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0xD8, 0x43, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, ++0x24, 0x03, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x20, 0x08, 0x33, 0x40, 0x4C, 0x08, 0x33, 0x40, 0x80, 0xB0, 0x33, 0x40, ++0x50, 0x08, 0x33, 0x40, 0x24, 0x08, 0x33, 0x40, 0x10, 0x03, 0x32, 0x40, 0x0C, 0x08, 0x33, 0x40, 0x00, 0x08, 0x33, 0x40, ++0x08, 0x00, 0x34, 0x40, 0x8C, 0x08, 0x33, 0x40, 0x34, 0x08, 0x33, 0x40, 0x18, 0x08, 0x33, 0x40, 0x06, 0x0C, 0x8E, 0x01, ++0x04, 0x08, 0x33, 0x40, 0x44, 0x49, 0x45, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0xFC, 0x63, 0x70, 0xB4, 0x0B, 0x60, 0x13, 0x68, ++0x42, 0x4C, 0x43, 0x4D, 0x43, 0x4E, 0x23, 0xF4, 0xE0, 0x23, 0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0xE0, 0x03, 0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x23, 0x68, 0xA1, 0xF5, 0x0F, 0x41, 0x23, 0xF4, 0x00, 0x03, 0x23, 0x60, ++0x04, 0x39, 0x0C, 0x23, 0x2B, 0x60, 0x0B, 0x68, 0x32, 0x6A, 0x23, 0xF4, 0xFE, 0x43, 0x23, 0xF0, 0x7F, 0x03, 0x13, 0x43, ++0x40, 0xF6, 0xB4, 0x12, 0x90, 0x42, 0x0B, 0x60, 0x34, 0x4B, 0x26, 0xD0, 0x72, 0x6A, 0x1A, 0x60, 0xA0, 0xF6, 0x6C, 0x13, ++0x3C, 0x2B, 0x22, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, ++0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, ++0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, ++0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x00, 0x21, 0x4A, 0x1A, 0x60, 0x21, 0x4A, 0x21, 0x49, 0x13, 0x68, ++0x91, 0xF8, 0xB4, 0x10, 0x23, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x99, 0xB1, 0x1E, 0x49, 0x1F, 0x4B, 0x0A, 0x68, 0x22, 0xF4, ++0xFE, 0x62, 0x0A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x9A, 0x68, 0x22, 0xF0, ++0x0F, 0x02, 0x9A, 0x60, 0xDA, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0xDA, 0x60, 0x70, 0xBC, 0x70, 0x47, 0x15, 0x49, 0x16, 0x4B, ++0xB0, 0x6A, 0x72, 0x6B, 0x08, 0x60, 0x1A, 0x60, 0xD9, 0xE7, 0x12, 0x4B, 0xF4, 0x6A, 0xB1, 0x6B, 0x11, 0x4A, 0x1C, 0x60, ++0x40, 0xF6, 0xA8, 0x13, 0x98, 0x42, 0x11, 0x60, 0xCF, 0xD1, 0x0F, 0x4B, 0x11, 0x22, 0x1A, 0x60, 0xCB, 0xE7, 0x00, 0xBF, ++0x04, 0x40, 0x34, 0x40, 0x34, 0x21, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x00, 0xB3, 0x33, 0x40, 0xDC, 0x18, 0x17, 0x00, ++0x20, 0x03, 0x33, 0x40, 0x1B, 0x88, 0xB3, 0x01, 0x30, 0x20, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x78, 0x40, 0x34, 0x40, ++0x00, 0x30, 0x50, 0x40, 0x30, 0x40, 0x34, 0x40, 0x2C, 0x40, 0x34, 0x40, 0x24, 0x01, 0x58, 0x40, 0x70, 0x47, 0x00, 0xBF, ++0x3A, 0x49, 0x3B, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0xFC, 0x63, 0x43, 0xF4, 0xA8, 0x63, 0x30, 0xB4, 0x0B, 0x60, 0x13, 0x68, ++0x37, 0x4C, 0x38, 0x4D, 0x23, 0xF4, 0xE0, 0x23, 0x43, 0xF4, 0x00, 0x33, 0x13, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xE0, 0x03, ++0x13, 0x60, 0x23, 0x68, 0x33, 0x4A, 0xA1, 0xF5, 0x0F, 0x41, 0x43, 0xF4, 0x00, 0x03, 0x23, 0x60, 0x04, 0x39, 0x0C, 0x23, ++0x2B, 0x60, 0x0B, 0x68, 0xD4, 0x6C, 0x23, 0xF4, 0xFE, 0x43, 0x23, 0xF0, 0x7F, 0x03, 0x23, 0x43, 0x41, 0xF2, 0xC8, 0x44, ++0xA0, 0x42, 0x0B, 0x60, 0x40, 0xD8, 0x2A, 0x4B, 0x12, 0x6C, 0x1A, 0x60, 0x29, 0x4A, 0x2A, 0x4C, 0x13, 0x68, 0x2A, 0x4D, ++0x2A, 0x48, 0x2B, 0x49, 0x23, 0xF0, 0x80, 0x63, 0x13, 0x60, 0x13, 0x68, 0x94, 0xF8, 0xB4, 0x40, 0x23, 0xF0, 0x0F, 0x03, ++0x43, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x80, 0x63, 0x2B, 0x60, 0x03, 0x68, ++0x43, 0xF4, 0x70, 0x63, 0x03, 0x60, 0x0B, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x0B, 0x60, 0xDC, 0xB1, 0x01, 0xF5, 0x01, 0x51, ++0x1D, 0x4B, 0x8A, 0x68, 0x22, 0xF4, 0xFE, 0x62, 0x42, 0xF4, 0x88, 0x62, 0x8A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x0F, 0x02, ++0x42, 0xF0, 0x03, 0x02, 0x1A, 0x60, 0x9A, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x03, 0x02, 0x9A, 0x60, 0xDA, 0x68, ++0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x03, 0x02, 0x08, 0x31, 0xDA, 0x60, 0x30, 0xBC, 0x70, 0x47, 0x41, 0xF2, 0x44, 0x63, ++0x98, 0x42, 0x08, 0x4B, 0x94, 0xBF, 0x52, 0x6C, 0x92, 0x6C, 0x1A, 0x60, 0xB8, 0xE7, 0x00, 0xBF, 0x04, 0x40, 0x34, 0x40, ++0x34, 0x21, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x00, 0xB3, 0x33, 0x40, 0xDC, 0x18, 0x17, 0x00, 0x30, 0x40, 0x34, 0x40, ++0x38, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x3C, 0x40, 0x34, 0x40, 0x08, 0x01, 0x58, 0x40, 0x30, 0x20, 0x34, 0x40, ++0x00, 0x30, 0x50, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x85, 0xB0, 0x0F, 0x46, 0x9D, 0xF8, 0x3C, 0x10, ++0x02, 0x91, 0xCD, 0xE9, 0x00, 0x23, 0x05, 0x46, 0x14, 0x46, 0x1E, 0x46, 0x02, 0x46, 0x3B, 0x46, 0xAE, 0x49, 0xAF, 0x48, ++0x9D, 0xF8, 0x38, 0xA0, 0xDF, 0xF8, 0x08, 0x83, 0xDF, 0xF8, 0x08, 0x93, 0x23, 0xF0, 0x4C, 0xFD, 0xAB, 0x49, 0x22, 0x46, ++0x04, 0x20, 0x23, 0xF0, 0x97, 0xFD, 0x30, 0x46, 0xFF, 0xF7, 0x06, 0xFD, 0x39, 0x46, 0x33, 0x46, 0xD8, 0xF8, 0x40, 0x71, ++0xCD, 0xF8, 0x00, 0xA0, 0x22, 0x46, 0x28, 0x46, 0xB8, 0x47, 0x99, 0xF8, 0x2A, 0x30, 0xAB, 0x42, 0x0A, 0xD0, 0xD8, 0xF8, ++0x80, 0x34, 0x28, 0x46, 0x98, 0x47, 0x99, 0xF8, 0x2A, 0x20, 0x9F, 0x49, 0x2B, 0x46, 0x04, 0x20, 0x23, 0xF0, 0x7C, 0xFD, ++0x9D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA8, 0x80, 0x00, 0x2D, 0x00, 0xF0, 0xB7, 0x80, ++0x41, 0xF2, 0x43, 0x63, 0x9C, 0x42, 0x00, 0xF2, 0xAE, 0x80, 0x41, 0xF2, 0x7B, 0x53, 0x9C, 0x42, 0x8B, 0xBF, 0x4F, 0xF0, ++0xEC, 0x09, 0x4F, 0xF0, 0xFC, 0x09, 0x3B, 0x27, 0x3F, 0x27, 0x20, 0x46, 0x35, 0xF0, 0x0E, 0xFD, 0x02, 0x46, 0x0B, 0x46, ++0x82, 0x46, 0x8B, 0x46, 0x35, 0xF0, 0xBC, 0xFB, 0x8D, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0x98, 0xFE, 0x8C, 0x4B, 0x00, 0x22, ++0x35, 0xF0, 0x6A, 0xFD, 0x35, 0xF0, 0x62, 0xFB, 0x36, 0xF0, 0x00, 0xF8, 0x52, 0x46, 0x5B, 0x46, 0x88, 0x49, 0x05, 0x46, ++0x00, 0x20, 0x35, 0xF0, 0x89, 0xFE, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x35, 0xF0, 0x5A, 0xFD, 0x35, 0xF0, 0x52, 0xFB, ++0x35, 0xF0, 0xF0, 0xFF, 0x03, 0x46, 0x38, 0x46, 0x1F, 0x46, 0x35, 0xF0, 0xE7, 0xFC, 0x80, 0x4B, 0x00, 0x22, 0x35, 0xF0, ++0x4D, 0xFD, 0x02, 0x46, 0x0B, 0x46, 0x50, 0x46, 0x59, 0x46, 0x35, 0xF0, 0x71, 0xFE, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, ++0x35, 0xF0, 0x42, 0xFD, 0x35, 0xF0, 0x3A, 0xFB, 0x35, 0xF0, 0xD8, 0xFF, 0x77, 0x4B, 0x78, 0x4A, 0xD3, 0xF8, 0x00, 0xE0, ++0x2E, 0xF4, 0x00, 0x0E, 0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x4E, 0xF4, 0x80, 0x0E, 0xC3, 0xF8, 0x00, 0xE0, ++0xD3, 0xF8, 0x00, 0xE0, 0x2E, 0xF4, 0x00, 0x1E, 0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x4E, 0xF0, 0x08, 0x0E, ++0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x01, 0x46, 0x2E, 0xF0, 0x04, 0x0E, 0x6A, 0x48, 0xC3, 0xF8, 0x00, 0xE0, ++0x03, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x03, 0x60, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x53, 0x03, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0xFF, 0x63, 0x23, 0xF0, 0x04, 0x03, 0x43, 0xEA, 0x09, 0x03, 0x13, 0x60, 0x20, 0x46, 0xD8, 0xF8, 0xA8, 0x34, 0x89, 0x46, ++0x98, 0x47, 0x20, 0x46, 0xD8, 0xF8, 0xAC, 0x34, 0x64, 0x08, 0x98, 0x47, 0x5C, 0x4B, 0x5D, 0x4A, 0x1D, 0x60, 0x17, 0x60, ++0xC3, 0xF8, 0x48, 0x90, 0x00, 0x2E, 0x00, 0xF0, 0x8D, 0x80, 0x01, 0x2E, 0x04, 0xD1, 0x59, 0x4A, 0x13, 0x68, 0x23, 0xF4, ++0x00, 0x63, 0x13, 0x60, 0x57, 0x49, 0x58, 0x4B, 0x08, 0x68, 0x58, 0x4A, 0x03, 0x40, 0x43, 0xEA, 0x04, 0x33, 0x01, 0x20, ++0x0B, 0x60, 0x10, 0x60, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x2D, 0x7F, 0xF6, 0x55, 0xAF, 0x52, 0x49, 0x53, 0x48, ++0x40, 0xF6, 0x4A, 0x22, 0x23, 0xF0, 0xEE, 0xFE, 0x41, 0xF2, 0x43, 0x63, 0x9C, 0x42, 0x7F, 0xF6, 0x52, 0xAF, 0x4F, 0xF0, ++0xF0, 0x09, 0x3C, 0x27, 0x57, 0xE7, 0x20, 0x46, 0x35, 0xF0, 0x66, 0xFC, 0x4B, 0x4B, 0x00, 0x22, 0x82, 0x46, 0x8B, 0x46, ++0x35, 0xF0, 0xCA, 0xFC, 0x39, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0xF0, 0xFD, 0x38, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0xC2, 0xFC, ++0x35, 0xF0, 0xBA, 0xFA, 0x35, 0xF0, 0x58, 0xFF, 0x52, 0x46, 0x5B, 0x46, 0x05, 0x46, 0x42, 0x49, 0x00, 0x20, 0x35, 0xF0, ++0xE1, 0xFD, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x35, 0xF0, 0xB2, 0xFC, 0x35, 0xF0, 0xAA, 0xFA, 0x35, 0xF0, 0x48, 0xFF, ++0x24, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x07, 0x46, 0x59, 0x46, 0x50, 0x46, 0x35, 0xF0, 0xD0, 0xFD, 0x00, 0x22, 0x4F, 0xF0, ++0x83, 0x43, 0x35, 0xF0, 0xA1, 0xFC, 0x35, 0xF0, 0x99, 0xFA, 0x35, 0xF0, 0x37, 0xFF, 0x27, 0x4B, 0x28, 0x4A, 0x19, 0x68, ++0x21, 0xF4, 0x00, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x80, 0x01, 0x19, 0x60, 0x19, 0x68, 0x41, 0xF4, 0x00, 0x11, ++0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x08, 0x01, 0x19, 0x60, 0x19, 0x68, 0x41, 0xF0, 0x04, 0x01, 0x19, 0x60, 0x13, 0x68, ++0x23, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x81, 0x46, 0x23, 0xF0, 0x00, 0x53, 0x19, 0x48, 0x13, 0x60, 0x03, 0x68, ++0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, 0x04, 0x03, 0x43, 0xF0, 0xEC, 0x03, 0x03, 0x60, 0xD8, 0xF8, 0xA0, 0x34, 0x20, 0x46, ++0x98, 0x47, 0xD8, 0xF8, 0xA4, 0x34, 0x20, 0x46, 0x98, 0x47, 0x69, 0xE7, 0x13, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x63, ++0x13, 0x60, 0x73, 0xE7, 0xAF, 0xF3, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xA2, 0x40, 0x78, 0x78, 0x15, 0x00, ++0x58, 0x77, 0x15, 0x00, 0x8C, 0x77, 0x15, 0x00, 0x9C, 0x77, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x00, 0x6A, 0x40, ++0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0xB9, 0x40, 0x00, 0x00, 0x54, 0x40, 0x14, 0x40, 0x34, 0x40, 0x3C, 0x40, 0x34, 0x40, ++0x30, 0x40, 0x34, 0x40, 0x10, 0x20, 0x34, 0x40, 0x54, 0x20, 0x34, 0x40, 0x20, 0x40, 0x34, 0x40, 0x1C, 0x20, 0x34, 0x40, ++0xFF, 0x0F, 0x00, 0xE0, 0x84, 0x21, 0x34, 0x40, 0x70, 0x79, 0x15, 0x00, 0xB4, 0x77, 0x15, 0x00, 0x00, 0x00, 0x10, 0x40, ++0x00, 0x00, 0xA4, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0xF8, 0xB5, 0x43, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x6B, 0xDB, 0xFF, 0xF7, 0xBD, 0xFB, 0x40, 0x49, 0x40, 0x4A, 0x0B, 0x68, 0x40, 0x48, 0x43, 0xF0, ++0x00, 0x63, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x03, 0x68, 0xC3, 0xF3, 0x03, 0x23, 0x02, 0x2B, ++0x06, 0xD1, 0xA2, 0xF5, 0x99, 0x42, 0x04, 0x3A, 0x13, 0x68, 0x43, 0xF0, 0x03, 0x03, 0x13, 0x60, 0x36, 0x4B, 0x1B, 0x68, ++0xC3, 0xF3, 0x03, 0x13, 0x02, 0x2B, 0x02, 0xD1, 0x34, 0x4B, 0x35, 0x4A, 0x1A, 0x60, 0x35, 0x4A, 0x35, 0x49, 0x13, 0x68, ++0xDF, 0xF8, 0x04, 0xC1, 0x34, 0x4D, 0x35, 0x4F, 0x35, 0x4C, 0x36, 0x48, 0x36, 0x4E, 0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, ++0x07, 0x03, 0x43, 0xF4, 0xE0, 0x63, 0x13, 0x60, 0x4F, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x04, 0x23, 0xCC, 0xF8, 0x00, 0x30, ++0x01, 0x22, 0xC4, 0x23, 0x3A, 0x60, 0x2B, 0x60, 0x00, 0x23, 0x23, 0x60, 0x6F, 0x24, 0x04, 0x60, 0x2C, 0x4C, 0xB0, 0x27, ++0x37, 0x60, 0x23, 0x60, 0xC3, 0x60, 0xAB, 0x61, 0x6B, 0x25, 0xE5, 0x60, 0x29, 0x4D, 0x83, 0x61, 0x2A, 0x60, 0xA3, 0x61, ++0x07, 0x24, 0x44, 0x62, 0xEC, 0x26, 0x27, 0x4C, 0xEE, 0x60, 0x03, 0x25, 0xC5, 0x62, 0x23, 0x60, 0xD0, 0xF8, 0xEC, 0x31, ++0x93, 0x42, 0x00, 0xF5, 0xF6, 0x70, 0x0F, 0xD9, 0x22, 0x4B, 0xA0, 0xF5, 0x56, 0x70, 0x1A, 0x60, 0x03, 0x68, 0x23, 0xF0, ++0x7F, 0x43, 0x43, 0xF0, 0x20, 0x43, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x40, 0x73, 0x43, 0xF4, 0x80, 0x73, 0x0B, 0x60, ++0xF8, 0xBD, 0x1B, 0x4A, 0x13, 0x68, 0x12, 0x68, 0x1B, 0x0E, 0x02, 0x33, 0x03, 0xEB, 0x83, 0x03, 0xC2, 0xF3, 0x07, 0x42, ++0x02, 0xEB, 0x43, 0x03, 0x1E, 0x2B, 0x86, 0xD0, 0x15, 0x49, 0x16, 0x48, 0x40, 0xF6, 0x2C, 0x32, 0x23, 0xF0, 0xBC, 0xFD, ++0x7F, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x10, 0x00, 0x34, 0x40, 0x14, 0x00, 0x34, 0x40, 0x00, 0x00, 0x33, 0x40, ++0x04, 0xB1, 0x33, 0x40, 0x34, 0x34, 0x34, 0x00, 0xB4, 0xB3, 0x33, 0x40, 0x00, 0x10, 0x34, 0x40, 0x08, 0x12, 0x34, 0x40, ++0x04, 0x12, 0x34, 0x40, 0x0C, 0x12, 0x34, 0x40, 0x10, 0x12, 0x34, 0x40, 0x14, 0x12, 0x34, 0x40, 0x18, 0x12, 0x34, 0x40, ++0x2C, 0x12, 0x34, 0x40, 0x40, 0x12, 0x34, 0x40, 0x0C, 0x10, 0x34, 0x40, 0x3C, 0x00, 0x33, 0x40, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0x77, 0x15, 0x00, 0x00, 0x12, 0x34, 0x40, 0x10, 0xB5, 0x1A, 0x4C, 0x82, 0xB0, 0xD4, 0xF8, 0x3C, 0x31, 0x98, 0x47, ++0x18, 0x4B, 0x19, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, ++0x15, 0x4A, 0x1A, 0x60, 0x19, 0x68, 0x12, 0x4A, 0x41, 0xF0, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xDB, ++0x11, 0x4B, 0x13, 0x60, 0x13, 0x68, 0x0D, 0x49, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x0B, 0x68, 0xDB, 0x0F, 0xFC, 0xD1, ++0xCD, 0xE9, 0x00, 0x33, 0x40, 0xF6, 0x85, 0x12, 0x11, 0x46, 0x18, 0x46, 0xD4, 0xF8, 0x28, 0x42, 0xA0, 0x47, 0x09, 0x49, ++0x09, 0x4B, 0x0A, 0x4A, 0x0C, 0x20, 0x08, 0x60, 0x1A, 0x60, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0x20, 0x00, 0x58, 0x40, 0xBF, 0x3F, 0x42, 0x01, 0xA2, 0x30, 0x43, 0x01, 0xDD, 0x1D, 0x44, 0x01, 0x00, 0xB3, 0x33, 0x40, ++0xC0, 0xB3, 0x33, 0x40, 0xA0, 0xA0, 0x28, 0x28, 0x70, 0xB5, 0x13, 0x4B, 0x13, 0x4D, 0x04, 0x46, 0xED, 0x1A, 0x03, 0xF2, ++0x3C, 0x50, 0x5A, 0x19, 0x53, 0xF8, 0x04, 0x1B, 0x11, 0x60, 0x83, 0x42, 0xF9, 0xD1, 0xFF, 0xF7, 0xEB, 0xFA, 0x0E, 0x4B, ++0x0E, 0x4E, 0xD3, 0xF8, 0x24, 0x32, 0x20, 0x46, 0x98, 0x47, 0x00, 0x23, 0x86, 0xF8, 0x2A, 0x30, 0x0F, 0xCC, 0x35, 0x46, ++0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, 0x23, 0x68, 0x2B, 0x60, 0x05, 0x21, 0x4F, 0xF0, 0xFF, 0x12, 0xFF, 0x23, 0x86, 0xF8, ++0x2B, 0x10, 0x72, 0x62, 0x33, 0x85, 0x70, 0xBD, 0xB0, 0x0D, 0x17, 0x00, 0x00, 0x90, 0x33, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0x08, 0xB5, 0x05, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x00, 0xD4, 0x08, 0xBD, 0x14, 0xF0, 0xF4, 0xFD, ++0x02, 0x4B, 0x08, 0x22, 0x1A, 0x60, 0x08, 0xBD, 0xA8, 0x10, 0x34, 0x40, 0xAC, 0x10, 0x34, 0x40, 0x03, 0x4A, 0x04, 0x4B, ++0x12, 0x68, 0x02, 0x60, 0x1B, 0x68, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x3C, 0x00, 0x33, 0x40, ++0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0x9D, 0xF8, 0x38, 0x40, 0xBD, 0xF8, 0x30, 0xA0, 0x9D, 0xF8, 0x34, 0x90, 0x00, 0x2C, ++0x43, 0xD1, 0x98, 0x46, 0x25, 0x4B, 0x1B, 0x78, 0x05, 0x46, 0x0E, 0x46, 0x17, 0x46, 0xD3, 0xB1, 0x23, 0x4C, 0x24, 0x4A, ++0xCD, 0xF8, 0x00, 0x90, 0x00, 0x23, 0xD2, 0xF8, 0x28, 0xB2, 0x01, 0x93, 0x42, 0x46, 0x33, 0x46, 0x39, 0x46, 0x28, 0x46, ++0xD8, 0x47, 0x84, 0xF8, 0x2A, 0x50, 0x84, 0xF8, 0x2B, 0x60, 0x84, 0xF8, 0x2C, 0x90, 0xA7, 0x84, 0xA4, 0xF8, 0x26, 0x80, ++0xA4, 0xF8, 0x28, 0xA0, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0x4A, 0x15, 0x4C, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, ++0x13, 0x60, 0x94, 0xF8, 0x2A, 0x30, 0x83, 0x42, 0xDB, 0xD1, 0x94, 0xF8, 0x2B, 0x30, 0x8B, 0x42, 0xD7, 0xD1, 0x94, 0xF8, ++0x2C, 0x30, 0x4B, 0x45, 0xD3, 0xD1, 0xA3, 0x8C, 0xBB, 0x42, 0xD0, 0xD1, 0xE3, 0x8C, 0x43, 0x45, 0xCD, 0xD1, 0x23, 0x8D, ++0x53, 0x45, 0xCA, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x23, 0xF0, 0x35, 0xBA, 0x08, 0x49, ++0x09, 0x48, 0x22, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x23, 0xF0, 0x2D, 0xBA, 0x00, 0xBF, 0x3C, 0x36, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x8C, 0x78, 0x15, 0x00, 0x38, 0x78, 0x15, 0x00, ++0x18, 0x78, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x71, 0xB9, 0x0A, 0x4A, 0x93, 0x8C, 0x92, 0xF8, 0x2B, 0x00, 0x92, 0xF8, ++0x2A, 0x10, 0xD2, 0xF8, 0x26, 0x20, 0x62, 0x60, 0x1B, 0x04, 0x43, 0xEA, 0x00, 0x23, 0x0B, 0x43, 0x23, 0x60, 0x10, 0xBD, ++0x0A, 0x46, 0x03, 0x48, 0x03, 0x49, 0x23, 0xF0, 0x07, 0xFA, 0xEA, 0xE7, 0xBC, 0x34, 0x17, 0x00, 0x18, 0x78, 0x15, 0x00, ++0x9C, 0x78, 0x15, 0x00, 0x04, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x00, 0xD1, 0x70, 0x47, 0x03, 0x49, 0x03, 0x48, 0x23, 0xF0, ++0xF7, 0xB9, 0x00, 0xBF, 0x38, 0x00, 0x32, 0x40, 0xAC, 0x78, 0x15, 0x00, 0x60, 0x78, 0x15, 0x00, 0x4F, 0xF4, 0x7A, 0x70, ++0x70, 0x47, 0x00, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0x01, 0x28, 0x94, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x00, 0xBF, ++0xFC, 0x13, 0x34, 0x40, 0x04, 0x4A, 0x13, 0x68, 0xC0, 0x00, 0x00, 0xF0, 0x08, 0x00, 0x23, 0xF0, 0x08, 0x03, 0x18, 0x43, ++0x10, 0x60, 0x70, 0x47, 0xA0, 0x10, 0x34, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x80, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x00, 0x33, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x00, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, ++0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x80, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x06, 0x4B, 0x02, 0x68, ++0x1A, 0x60, 0x42, 0x68, 0x5A, 0x60, 0x0A, 0x68, 0x9A, 0x60, 0x4A, 0x68, 0xDA, 0x60, 0x8A, 0x68, 0x1A, 0x61, 0xCA, 0x68, ++0x5A, 0x61, 0x70, 0x47, 0xA8, 0x08, 0x33, 0x40, 0x30, 0xB4, 0x06, 0x49, 0x06, 0x4D, 0x07, 0x4B, 0x00, 0x24, 0xC0, 0xF3, ++0x0A, 0x00, 0x40, 0xF2, 0xFF, 0x72, 0x28, 0x60, 0x0C, 0x60, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0xC4, 0x08, 0x33, 0x40, ++0xC0, 0x08, 0x33, 0x40, 0xC8, 0x08, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x03, 0x20, 0x01, 0x38, 0xC0, 0xB2, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x03, 0x10, 0x01, 0x38, 0xC0, 0xB2, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0x00, 0xF0, 0x0F, 0x00, 0x01, 0x38, 0xC0, 0xB2, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0xF0, 0xB5, 0xBE, 0x4C, 0x94, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x76, 0xD1, ++0xBC, 0x4B, 0x93, 0xF8, 0xBD, 0x50, 0x00, 0x2D, 0x66, 0xD0, 0xE0, 0x8C, 0x40, 0xF6, 0x7B, 0x14, 0xA0, 0x42, 0x40, 0xF2, ++0xCA, 0x80, 0x40, 0xF6, 0x94, 0x14, 0xA0, 0x42, 0xB6, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x01, 0x60, 0x90, 0xF9, 0x02, 0x60, ++0x93, 0xF8, 0xBE, 0x40, 0xB3, 0x48, 0x06, 0xF1, 0x0F, 0x05, 0x1E, 0x2D, 0x00, 0x5D, 0xA8, 0xBF, 0x1E, 0x25, 0x0A, 0x2C, ++0x4F, 0xEA, 0x20, 0x17, 0x00, 0xF0, 0x0F, 0x0C, 0x25, 0xEA, 0xE5, 0x75, 0x00, 0xF3, 0xCF, 0x80, 0x00, 0xF0, 0xE4, 0x80, ++0xAB, 0x48, 0x04, 0xEB, 0x44, 0x04, 0x10, 0xF9, 0x14, 0xE0, 0x75, 0x45, 0x00, 0xEB, 0x44, 0x04, 0x00, 0xF3, 0x06, 0x81, ++0x64, 0x78, 0xA4, 0xEB, 0x0E, 0x04, 0x2C, 0x44, 0x60, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, 0x07, 0xF1, 0xFF, 0x37, ++0xB8, 0xBF, 0x20, 0x46, 0x60, 0x44, 0x80, 0xF3, 0x04, 0x00, 0x40, 0xEA, 0x07, 0x10, 0x08, 0x70, 0x93, 0xF8, 0xBF, 0x10, ++0x9D, 0x4B, 0x5B, 0x5C, 0x0A, 0x29, 0x4F, 0xEA, 0x23, 0x10, 0x03, 0xF0, 0x0F, 0x03, 0x17, 0xDC, 0x00, 0xF0, 0xD1, 0x80, ++0x01, 0x31, 0x97, 0x4C, 0x01, 0xEB, 0x41, 0x01, 0x14, 0xF9, 0x11, 0x60, 0xAE, 0x42, 0x04, 0xEB, 0x41, 0x01, 0xC0, 0xF2, ++0xD2, 0x80, 0x49, 0x78, 0x89, 0x1B, 0x0D, 0x44, 0x6D, 0xB2, 0x6F, 0xF0, 0x04, 0x01, 0x01, 0x38, 0x8D, 0x42, 0xAC, 0xBF, ++0x5B, 0x19, 0x5B, 0x18, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x00, 0x13, 0x13, 0x70, 0xF0, 0xBD, 0x93, 0xF8, 0xAC, 0x40, ++0xE5, 0x07, 0x68, 0xD5, 0x93, 0xF8, 0xB7, 0x00, 0x08, 0x70, 0x93, 0xF8, 0xAD, 0x30, 0x13, 0x70, 0xF0, 0xBD, 0x81, 0x4B, ++0x93, 0xF8, 0xBD, 0x50, 0x00, 0x2D, 0x3A, 0xD0, 0xE0, 0x8C, 0x41, 0xF2, 0xC8, 0x44, 0xA0, 0x42, 0x4F, 0xD9, 0xB0, 0xF5, ++0xAF, 0x5F, 0x7D, 0xD8, 0x7F, 0x48, 0x90, 0xF9, 0x01, 0x60, 0x93, 0xF8, 0xC3, 0x00, 0x7E, 0x4B, 0x1B, 0x5C, 0x0A, 0x28, ++0x4F, 0xEA, 0x23, 0x15, 0x03, 0xF0, 0x0F, 0x03, 0x1D, 0xDC, 0x06, 0xF1, 0x0F, 0x04, 0x1E, 0x2C, 0xA8, 0xBF, 0x1E, 0x24, ++0x0A, 0x28, 0x24, 0xEA, 0xE4, 0x74, 0x7A, 0xD0, 0x76, 0x4E, 0x00, 0xEB, 0x40, 0x00, 0x16, 0xF9, 0x10, 0x70, 0xBC, 0x42, ++0x06, 0xEB, 0x40, 0x00, 0x00, 0xF3, 0x9E, 0x80, 0x40, 0x78, 0xC0, 0x1B, 0x04, 0x44, 0x64, 0xB2, 0x6F, 0xF0, 0x04, 0x00, ++0x01, 0x3D, 0x84, 0x42, 0xAC, 0xBF, 0x1B, 0x19, 0x1B, 0x18, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x05, 0x13, 0xDB, 0xB2, ++0x13, 0x70, 0x0B, 0x70, 0xF0, 0xBD, 0x93, 0xF8, 0xAC, 0x40, 0xA4, 0x07, 0x04, 0xD5, 0x93, 0xF8, 0xAE, 0x30, 0x0B, 0x70, ++0x13, 0x70, 0xF0, 0xBD, 0x90, 0xF9, 0x00, 0x30, 0x61, 0x48, 0x6F, 0xF0, 0x04, 0x04, 0xA3, 0x42, 0xB8, 0xBF, 0x23, 0x46, ++0x12, 0x2B, 0xA8, 0xBF, 0x12, 0x23, 0x05, 0x33, 0x5B, 0x10, 0xC3, 0x5C, 0x0B, 0x70, 0x13, 0x70, 0xF0, 0xBD, 0x59, 0x48, ++0x90, 0xF9, 0x00, 0x60, 0xB1, 0xE7, 0x53, 0x48, 0x90, 0xF9, 0x00, 0x60, 0x3A, 0xE7, 0x90, 0xF9, 0x00, 0x30, 0x51, 0x4D, ++0x52, 0x4C, 0x01, 0x2B, 0x6F, 0xF0, 0x01, 0x06, 0x18, 0x46, 0xB8, 0xBF, 0x01, 0x20, 0xB3, 0x42, 0xB8, 0xBF, 0x33, 0x46, ++0x17, 0x28, 0xA8, 0xBF, 0x17, 0x20, 0x14, 0x2B, 0xA8, 0xBF, 0x14, 0x23, 0x01, 0x38, 0x02, 0x33, 0x40, 0x10, 0x5B, 0x10, ++0x28, 0x5C, 0xE3, 0x5C, 0x08, 0x70, 0x13, 0x70, 0xF0, 0xBD, 0x74, 0x1C, 0x55, 0xDA, 0xA5, 0xF1, 0x0D, 0x00, 0x40, 0xB2, ++0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, 0xA7, 0xF1, 0x02, 0x07, 0xB8, 0xBF, 0x20, 0x46, 0x3B, 0xE7, 0x41, 0xF2, 0x44, 0x64, ++0xA0, 0x42, 0x3F, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x02, 0x60, 0x90, 0xF9, 0x03, 0x60, 0x7A, 0xE7, 0xB0, 0x1C, 0x53, 0xDB, ++0x01, 0x2E, 0x00, 0xF3, 0x8D, 0x80, 0xA5, 0xF1, 0x0F, 0x00, 0x40, 0xB2, 0x28, 0xE7, 0x03, 0x36, 0x43, 0xDA, 0x09, 0x3C, ++0x64, 0xB2, 0x6F, 0xF0, 0x04, 0x00, 0x01, 0x3D, 0x84, 0x42, 0xAC, 0xBF, 0x1B, 0x19, 0x1B, 0x18, 0x8D, 0xE7, 0x03, 0x36, ++0x30, 0xDA, 0x09, 0x3D, 0x6D, 0xB2, 0x6F, 0xF0, 0x04, 0x01, 0x01, 0x38, 0x8D, 0x42, 0xAC, 0xBF, 0x5B, 0x19, 0x5B, 0x18, ++0x38, 0xE7, 0x91, 0xF9, 0x04, 0x40, 0xAC, 0x42, 0x3B, 0xDD, 0xCC, 0x78, 0x89, 0x78, 0x61, 0x1A, 0x0D, 0x44, 0x43, 0xFA, ++0x85, 0xF3, 0x2D, 0xE7, 0x94, 0xF9, 0x04, 0xE0, 0x75, 0x45, 0x57, 0xDA, 0xE0, 0x78, 0xA4, 0x78, 0x00, 0x1B, 0x28, 0x44, ++0x40, 0xB2, 0xFB, 0xE6, 0x90, 0xF9, 0x04, 0x60, 0xB4, 0x42, 0x43, 0xDA, 0xC6, 0x78, 0x80, 0x78, 0x30, 0x1A, 0x04, 0x44, ++0x43, 0xFA, 0x84, 0xF3, 0x61, 0xE7, 0xA5, 0xF1, 0x0F, 0x04, 0x60, 0xB2, 0x03, 0x28, 0xA8, 0xBF, 0x03, 0x20, 0xE9, 0xE6, ++0x0F, 0x3D, 0x6D, 0xB2, 0x05, 0x2D, 0xD4, 0xBF, 0x5B, 0x19, 0x05, 0x33, 0x0A, 0xE7, 0x0F, 0x3C, 0x64, 0xB2, 0x05, 0x2C, ++0xD4, 0xBF, 0x1B, 0x19, 0x05, 0x33, 0x4C, 0xE7, 0xA5, 0xF1, 0x0A, 0x00, 0x40, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, ++0x07, 0xF1, 0xFF, 0x37, 0xB8, 0xBF, 0x20, 0x46, 0xD0, 0xE6, 0x49, 0x79, 0x09, 0x1B, 0x0D, 0x44, 0x6D, 0xB2, 0x05, 0x2D, ++0xD4, 0xBF, 0x5B, 0x19, 0x05, 0x33, 0x01, 0x30, 0xEE, 0xE6, 0x00, 0xBF, 0xBC, 0x34, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0x68, 0x25, 0x17, 0x00, 0xEC, 0x12, 0x17, 0x00, 0xB8, 0x78, 0x15, 0x00, 0xF8, 0x12, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, ++0x04, 0x13, 0x17, 0x00, 0x0C, 0x79, 0x15, 0x00, 0x40, 0x79, 0x80, 0x1B, 0x04, 0x44, 0x64, 0xB2, 0x05, 0x2C, 0xD4, 0xBF, ++0x1B, 0x19, 0x05, 0x33, 0x01, 0x35, 0x1A, 0xE7, 0x60, 0x79, 0xA0, 0xEB, 0x0E, 0x00, 0x28, 0x44, 0x40, 0xB2, 0x05, 0x28, ++0xA8, 0xBF, 0x05, 0x20, 0x01, 0x37, 0x9F, 0xE6, 0xA5, 0xF1, 0x11, 0x00, 0x40, 0xB2, 0x03, 0x28, 0x07, 0xF1, 0x02, 0x07, ++0xA8, 0xBF, 0x03, 0x20, 0x96, 0xE6, 0x00, 0xBF, 0xF0, 0xB4, 0xB9, 0x4B, 0x93, 0xF8, 0x2A, 0x20, 0xDC, 0x8C, 0x52, 0xBB, ++0xC0, 0xB9, 0x03, 0x29, 0x00, 0xF2, 0x91, 0x80, 0xB5, 0x4A, 0xB6, 0x4B, 0x92, 0xF8, 0xBE, 0x50, 0x5B, 0x5D, 0x02, 0x46, ++0x01, 0x46, 0x07, 0x46, 0x40, 0xF6, 0x7B, 0x10, 0x84, 0x42, 0x00, 0xF2, 0xBA, 0x80, 0xB1, 0x48, 0x90, 0xF9, 0x00, 0x60, ++0x00, 0x29, 0x00, 0xF0, 0xC0, 0x80, 0xD8, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x04, 0x28, 0x40, 0xF2, 0x8F, 0x80, 0x09, 0x29, ++0x40, 0xF2, 0x8E, 0x80, 0xA7, 0x4B, 0x93, 0xF8, 0xC2, 0x50, 0x08, 0x2D, 0x40, 0xF3, 0x17, 0x81, 0x01, 0x21, 0x0F, 0x46, ++0x09, 0x25, 0xD4, 0x23, 0xE0, 0xE7, 0x04, 0x28, 0x44, 0xD9, 0x09, 0x29, 0x44, 0xD9, 0xA0, 0x4B, 0xA2, 0x49, 0x93, 0xF8, ++0xC6, 0x30, 0x09, 0x2B, 0xA8, 0xBF, 0x09, 0x23, 0x41, 0xF2, 0xC8, 0x42, 0x94, 0x42, 0xC8, 0x5C, 0x4F, 0xF0, 0x00, 0x05, ++0x53, 0xD9, 0xB4, 0xF5, 0xAF, 0x5F, 0x00, 0xF2, 0xCC, 0x80, 0x9B, 0x4A, 0x92, 0xF9, 0x01, 0x20, 0x00, 0x2D, 0xD1, 0xD1, ++0x0A, 0x2B, 0x4F, 0xEA, 0x20, 0x14, 0x00, 0xF0, 0x0F, 0x00, 0x1E, 0xDC, 0x02, 0xF1, 0x0F, 0x01, 0x1E, 0x29, 0xA8, 0xBF, ++0x1E, 0x21, 0x0A, 0x2B, 0x21, 0xEA, 0xE1, 0x71, 0x00, 0xF0, 0x3C, 0x81, 0x91, 0x4A, 0x03, 0xEB, 0x43, 0x03, 0x12, 0xF9, ++0x13, 0x50, 0x8D, 0x42, 0x02, 0xEB, 0x43, 0x02, 0x80, 0xF2, 0xF6, 0x80, 0x92, 0xF9, 0x04, 0x50, 0x8D, 0x42, 0x40, 0xF3, ++0x40, 0x81, 0xD3, 0x78, 0x92, 0x78, 0x9B, 0x1A, 0x19, 0x44, 0x40, 0xFA, 0x81, 0xF0, 0x80, 0xF3, 0x04, 0x00, 0x40, 0xEA, ++0x04, 0x10, 0xC0, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x01, 0x28, 0x0C, 0xD9, 0x07, 0x29, 0x2C, 0xD8, 0x04, 0x29, 0x0A, 0xD8, ++0x7B, 0x4B, 0x93, 0xF8, 0xC3, 0x30, 0xA3, 0xF1, 0x0B, 0x05, 0xB5, 0xFA, 0x85, 0xF5, 0x6D, 0x09, 0x09, 0xE0, 0x09, 0x29, ++0xF4, 0xD9, 0x76, 0x4B, 0x93, 0xF8, 0xC4, 0x30, 0x0A, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0xA8, 0xBF, 0x0A, 0x23, 0x75, 0x49, ++0x41, 0xF2, 0xC8, 0x42, 0x94, 0x42, 0xC8, 0x5C, 0xAB, 0xD8, 0x73, 0x4A, 0x92, 0xF9, 0x00, 0x20, 0xAE, 0xE7, 0x09, 0x29, ++0x26, 0xD8, 0x6C, 0x4B, 0x93, 0xF8, 0xBF, 0x50, 0x0B, 0x2D, 0x00, 0xF0, 0xF0, 0x80, 0x6F, 0x4B, 0x00, 0x22, 0x5B, 0x5D, ++0x11, 0x46, 0x01, 0x27, 0x68, 0xE7, 0x66, 0x4B, 0x93, 0xF8, 0xC5, 0x30, 0x09, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0xA8, 0xBF, ++0x09, 0x23, 0xDE, 0xE7, 0x01, 0x28, 0xE6, 0xD0, 0x07, 0x29, 0x0B, 0xD9, 0x5F, 0x4A, 0x65, 0x4B, 0x92, 0xF8, 0xC1, 0x50, ++0x0A, 0x2D, 0xA8, 0xBF, 0x0A, 0x25, 0x00, 0x22, 0x5B, 0x5D, 0x11, 0x46, 0x01, 0x27, 0x4F, 0xE7, 0x04, 0x29, 0xD8, 0xD9, ++0x58, 0x4A, 0x5E, 0x4B, 0x92, 0xF8, 0xC0, 0x50, 0xA5, 0xF1, 0x0B, 0x01, 0xB1, 0xFA, 0x81, 0xF1, 0x5B, 0x5D, 0x00, 0x22, ++0x49, 0x09, 0x01, 0x27, 0x40, 0xE7, 0x40, 0xF6, 0x94, 0x10, 0x84, 0x42, 0x52, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x01, 0x60, ++0x90, 0xF9, 0x02, 0x60, 0x00, 0x29, 0x7F, 0xF4, 0x40, 0xAF, 0x06, 0xF1, 0x0F, 0x01, 0x1E, 0x29, 0xA8, 0xBF, 0x1E, 0x21, ++0x0B, 0x2D, 0x21, 0xEA, 0xE1, 0x74, 0x4F, 0xEA, 0x23, 0x10, 0x29, 0x46, 0x03, 0xF0, 0x0F, 0x03, 0xA8, 0xBF, 0x0B, 0x21, ++0x00, 0x2F, 0x3B, 0xD1, 0x0A, 0x2D, 0x2C, 0xDC, 0x48, 0xD0, 0x49, 0x4D, 0x01, 0xEB, 0x41, 0x01, 0x15, 0xF9, 0x11, 0x60, ++0xB4, 0x42, 0x05, 0xEB, 0x41, 0x01, 0x34, 0xDC, 0x49, 0x78, 0x89, 0x1B, 0x21, 0x44, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, ++0x01, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x00, 0x13, 0xD8, 0xB2, ++0x00, 0x2A, 0x3F, 0xF4, 0x11, 0xAF, 0x82, 0x42, 0xBF, 0xF6, 0x0E, 0xAF, 0xD0, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x41, 0xF2, ++0x44, 0x62, 0x94, 0x42, 0x33, 0x4A, 0x94, 0xBF, 0x92, 0xF9, 0x02, 0x20, 0x92, 0xF9, 0x03, 0x20, 0x2C, 0xE7, 0x01, 0x36, ++0x2A, 0xDA, 0xA4, 0xF1, 0x0D, 0x01, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0x02, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, ++0x1B, 0x19, 0xDA, 0xE7, 0x0A, 0x2D, 0xD8, 0xDC, 0x58, 0xD0, 0x01, 0x31, 0xC1, 0xE7, 0x91, 0xF9, 0x04, 0x50, 0xAC, 0x42, ++0x1E, 0xDA, 0xCD, 0x78, 0x89, 0x78, 0x69, 0x1A, 0x21, 0x44, 0x43, 0xFA, 0x81, 0xF3, 0xCA, 0xE7, 0xB1, 0x1C, 0x2B, 0xDB, ++0x01, 0x2E, 0x76, 0xDC, 0xA4, 0xF1, 0x0F, 0x01, 0x43, 0xFA, 0x81, 0xF3, 0xC1, 0xE7, 0x1F, 0x4B, 0x08, 0xBF, 0xD4, 0x22, ++0x5B, 0x5D, 0x00, 0x21, 0x01, 0x27, 0xC7, 0xE6, 0xA4, 0xF1, 0x0F, 0x01, 0x49, 0xB2, 0x03, 0x29, 0xD4, 0xBF, 0x5B, 0x18, ++0x03, 0x33, 0xB2, 0xE7, 0x49, 0x79, 0x49, 0x1B, 0x21, 0x44, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x05, 0x33, ++0x01, 0x30, 0xA8, 0xE7, 0x53, 0x78, 0x5B, 0x1B, 0x19, 0x44, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x03, 0x01, 0x3C, 0x99, 0x42, ++0xAC, 0xBF, 0x40, 0x18, 0xC0, 0x18, 0x08, 0xE7, 0xA4, 0xF1, 0x0A, 0x01, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0x01, 0x38, ++0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x91, 0xE7, 0x00, 0xBF, 0xBC, 0x34, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xEC, 0x12, 0x17, 0x00, 0x68, 0x25, 0x17, 0x00, 0x04, 0x13, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x0C, 0x79, 0x15, 0x00, ++0xF8, 0x12, 0x17, 0x00, 0xB8, 0x78, 0x15, 0x00, 0x03, 0x36, 0x35, 0xDA, 0xA4, 0xF1, 0x09, 0x01, 0x49, 0xB2, 0x6F, 0xF0, ++0x04, 0x04, 0x01, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x71, 0xE7, 0x01, 0x21, 0x0F, 0x46, 0x00, 0x22, ++0x0F, 0x23, 0x79, 0xE6, 0x03, 0x32, 0x09, 0xDA, 0x09, 0x39, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x03, 0x01, 0x3C, 0x99, 0x42, ++0xAC, 0xBF, 0x40, 0x18, 0xC0, 0x18, 0xCC, 0xE6, 0x0F, 0x39, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x40, 0x18, 0x05, 0x30, ++0xC5, 0xE6, 0x53, 0x79, 0x5B, 0x1B, 0x19, 0x44, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x40, 0x18, 0x05, 0x30, 0x01, 0x34, ++0xBB, 0xE6, 0xA4, 0xF1, 0x11, 0x01, 0x49, 0xB2, 0x03, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x03, 0x33, 0x02, 0x30, 0x46, 0xE7, ++0xA4, 0xF1, 0x0F, 0x01, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x05, 0x33, 0x3E, 0xE7, 0x14, 0x22, 0xF6, 0x23, ++0x02, 0x70, 0x0B, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x08, 0xB5, 0x09, 0x49, 0x09, 0x48, 0x22, 0xF0, 0xF3, 0xFD, 0x09, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x08, 0xBD, 0xBD, 0xE8, 0x08, 0x40, 0x05, 0x49, 0x06, 0x48, ++0x39, 0x22, 0x23, 0xF0, 0x5F, 0xB8, 0x00, 0xBF, 0x50, 0x79, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x1F, 0x49, 0x20, 0x4A, 0x88, 0x68, 0x20, 0x4B, 0x10, 0xB4, 0xD2, 0xF8, ++0x14, 0x44, 0x04, 0x65, 0x10, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0xA0, 0x42, 0x44, 0x65, 0x20, 0x20, 0x18, 0x60, ++0x88, 0x68, 0xD2, 0xF8, 0xA0, 0x42, 0xC4, 0x65, 0x80, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0xD8, 0x40, 0x84, 0x64, ++0x04, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0x0C, 0x44, 0xC4, 0x64, 0xF8, 0x24, 0x08, 0x20, 0x83, 0xF8, 0x03, 0x43, ++0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0x1C, 0x41, 0xC0, 0xF8, 0x0C, 0x41, 0x4F, 0xF4, 0x00, 0x20, 0x58, 0x60, 0x89, 0x68, ++0xD2, 0xF8, 0x2C, 0x21, 0xC1, 0xF8, 0x10, 0x21, 0x4F, 0xF4, 0x80, 0x10, 0x4F, 0xF4, 0x00, 0x41, 0x4F, 0xF4, 0x00, 0x12, ++0x58, 0x60, 0x99, 0x60, 0x1A, 0x60, 0x62, 0xB6, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xED, 0x00, 0xE0, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, 0x33, 0x49, 0x34, 0x4B, 0x0A, 0x68, 0x00, 0x28, 0x22, 0xF4, 0x00, 0x62, ++0xF0, 0xB5, 0x32, 0x4D, 0x0A, 0x60, 0x06, 0xBF, 0x1D, 0x46, 0x30, 0x26, 0x20, 0x26, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x2A, 0x4F, 0x2C, 0x4C, 0x3A, 0x68, 0x22, 0xF4, 0x80, 0x52, 0x3A, 0x60, 0x3A, 0x68, ++0x42, 0xF4, 0x80, 0x62, 0x3A, 0x60, 0x3A, 0x68, 0x42, 0xF4, 0x00, 0x62, 0x3A, 0x60, 0xB6, 0x00, 0x19, 0x46, 0x3A, 0x46, ++0x4F, 0xF0, 0xFF, 0x0E, 0xC8, 0x1C, 0xC0, 0xB2, 0xAC, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x43, 0x13, 0x60, ++0x5C, 0xF8, 0x04, 0x3B, 0x23, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, ++0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, 0xFC, 0xD5, 0x01, 0x38, 0xC0, 0xB2, 0x70, 0x45, 0xE8, 0xD1, 0x04, 0x31, 0x04, 0x30, ++0xB1, 0x42, 0x5F, 0xFA, 0x80, 0xFE, 0x05, 0xF1, 0x10, 0x05, 0xDD, 0xD1, 0x3B, 0x68, 0x23, 0xF4, 0x80, 0x63, 0x3B, 0x60, ++0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, ++0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, ++0x80, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0xF0, 0xBD, 0x00, 0xBF, 0x60, 0x40, 0x34, 0x40, ++0x1C, 0x13, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, 0x64, 0x40, 0x34, 0x40, 0x44, 0x4A, 0x45, 0x49, 0x13, 0x68, 0xF0, 0xB4, ++0x44, 0x4D, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x00, 0x28, 0x0C, 0xBF, 0x28, 0x46, 0x08, 0x46, 0x32, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x3B, 0x4A, 0x3E, 0x4D, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x53, 0x13, 0x60, ++0x13, 0x68, 0x43, 0xF4, 0x80, 0x63, 0x13, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x03, 0x21, 0xA0, 0xF1, ++0x0C, 0x04, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x54, 0xF8, 0x21, 0x30, 0x2B, 0x60, 0x13, 0x68, ++0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9E, 0x04, 0xFC, 0xD5, ++0x04, 0x31, 0x43, 0x29, 0xE9, 0xD1, 0x28, 0x4B, 0x2B, 0x4E, 0x2A, 0x4D, 0x04, 0x1F, 0x02, 0x21, 0x1A, 0x68, 0x22, 0xF0, ++0xFF, 0x02, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, ++0x00, 0xBF, 0x1A, 0x68, 0x90, 0x04, 0xFC, 0xD5, 0x37, 0x68, 0x54, 0xF8, 0x21, 0x20, 0x18, 0x68, 0x27, 0xF0, 0x7F, 0x47, ++0x02, 0xF0, 0x7F, 0x42, 0x20, 0xF0, 0xFF, 0x00, 0x3A, 0x43, 0x08, 0x43, 0x18, 0x60, 0x2A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x80, 0x72, 0x1A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x1A, 0x68, 0x92, 0x04, 0xFC, 0xD5, 0x04, 0x31, ++0x42, 0x29, 0xD3, 0xD1, 0x1A, 0x68, 0x22, 0xF4, 0x80, 0x62, 0x1A, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, ++0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x00, 0x62, 0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x60, 0x40, 0x34, 0x40, 0x1C, 0x16, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, ++0x64, 0x40, 0x34, 0x40, 0x68, 0x40, 0x34, 0x40, 0x2C, 0x49, 0x2D, 0x4B, 0x0A, 0x68, 0x30, 0xB4, 0x2C, 0x4C, 0x00, 0x28, ++0x22, 0xF4, 0x80, 0x72, 0x0C, 0xBF, 0x18, 0x46, 0x20, 0x46, 0x0A, 0x60, 0x0C, 0xBF, 0x20, 0x24, 0x10, 0x24, 0x32, 0x23, ++0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x22, 0x49, 0x24, 0x4D, 0x0A, 0x68, 0x22, 0xF4, 0x00, 0x72, ++0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x72, 0x04, 0x38, 0x0A, 0x60, ++0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x50, 0xF8, 0x04, 0x2F, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF0, ++0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, 0xFC, 0xD5, 0x01, 0x33, ++0x9C, 0x42, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, ++0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x80, 0x72, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x6C, 0x40, 0x34, 0x40, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, ++0x70, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0xA6, 0x49, 0xA7, 0x4C, 0xA7, 0x4B, 0xA8, 0x4A, 0xDF, 0xF8, 0xE8, 0xE2, ++0x00, 0x28, 0x0E, 0xBF, 0xA4, 0x46, 0x8C, 0x46, 0x9E, 0x46, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0xA3, 0x4C, 0xA4, 0x49, ++0x23, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x23, 0x60, 0x01, 0x23, 0x13, 0x60, 0x0B, 0x68, 0xA1, 0x4A, 0x23, 0xF4, 0x00, 0x63, ++0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x24, 0x00, 0xBF, 0x01, 0x3C, 0x14, 0xF0, 0xFF, 0x04, ++0xFA, 0xD1, 0xDF, 0xF8, 0x64, 0x82, 0x99, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x98, 0x4F, 0x23, 0xF4, 0x80, 0x53, 0xC8, 0xF8, ++0x00, 0x30, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x80, 0x63, 0xC8, 0xF8, ++0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x00, 0x63, 0xC8, 0xF8, 0x00, 0x30, 0x42, 0x46, 0xFF, 0x26, 0xE1, 0x1C, ++0xC9, 0xB2, 0x75, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x55, 0xF8, 0x04, 0x3B, 0x3B, 0x60, ++0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, ++0xFC, 0xD5, 0x01, 0x39, 0xC9, 0xB2, 0x8E, 0x42, 0xE8, 0xD1, 0x04, 0x34, 0x04, 0x36, 0x80, 0x2C, 0xF6, 0xB2, 0x0E, 0xF1, ++0x10, 0x0E, 0xDE, 0xD1, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x80, 0x63, 0xC8, 0xF8, 0x00, 0x30, 0xC8, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x74, 0x4C, 0x75, 0x49, 0x22, 0x68, 0x22, 0xF4, 0x00, 0x62, 0x22, 0x60, ++0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x72, 0x10, 0x34, 0xAC, 0xF1, 0x04, 0x0C, ++0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x5C, 0xF8, 0x04, 0x2F, 0x22, 0x60, 0x0A, 0x68, ++0x42, 0xF0, 0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, 0xFC, 0xD5, ++0x01, 0x33, 0x10, 0x2B, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x5D, 0x49, 0x5E, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x13, 0x68, ++0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x54, 0x49, ++0x54, 0x4B, 0x0C, 0x68, 0x56, 0x4A, 0x57, 0x4D, 0x44, 0xF4, 0x80, 0x54, 0x0C, 0x60, 0x1C, 0x68, 0x44, 0xF4, 0x00, 0x74, ++0x1C, 0x60, 0x0C, 0x68, 0x44, 0xF4, 0x00, 0x64, 0x0C, 0x60, 0x19, 0x68, 0x51, 0x4C, 0x41, 0xF4, 0x80, 0x71, 0x19, 0x60, ++0x11, 0x68, 0x50, 0x4B, 0x41, 0xF4, 0x80, 0x51, 0x11, 0x60, 0x29, 0x68, 0x21, 0xF4, 0x80, 0x21, 0x29, 0x60, 0x21, 0x68, ++0x21, 0xF0, 0x00, 0x51, 0x21, 0x60, 0xA5, 0xF5, 0xBC, 0x45, 0x1C, 0x68, 0x2C, 0x60, 0x49, 0x49, 0x5D, 0x68, 0x0D, 0x60, ++0x48, 0x4C, 0x9D, 0x68, 0x25, 0x60, 0xDD, 0x68, 0x8D, 0x60, 0x1D, 0x69, 0xA5, 0x60, 0x5C, 0x69, 0x0C, 0x61, 0xD3, 0xE9, ++0x06, 0x64, 0x44, 0x4D, 0x44, 0x4B, 0x2E, 0x60, 0x8C, 0x61, 0x9B, 0x78, 0x18, 0x31, 0xCB, 0xB1, 0xA5, 0xF6, 0x78, 0x65, ++0x41, 0x4C, 0x2B, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x00, 0x73, 0x2B, 0x60, 0x23, 0x68, 0x01, 0xF5, 0xBB, 0x41, ++0x7C, 0x31, 0x43, 0xF0, 0x80, 0x63, 0x23, 0x60, 0x0B, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0x40, 0x63, 0x43, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x36, 0x4B, 0x93, 0xF8, 0xFA, 0x30, 0x38, 0xB9, 0x43, 0xBB, 0x35, 0x4A, ++0x13, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0xCB, 0xB1, 0x32, 0x49, 0x32, 0x4A, 0x0B, 0x68, ++0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xB5, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xB5, 0x03, ++0x13, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x32, 0x23, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x23, ++0x43, 0xF4, 0x32, 0x23, 0x13, 0x60, 0x24, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, ++0x21, 0x49, 0x22, 0x4A, 0x0B, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, ++0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x0B, 0x60, ++0x13, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x13, 0x60, 0xBB, 0xE7, 0x00, 0xBF, 0x9C, 0x18, 0x17, 0x00, ++0x1C, 0x18, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x60, 0x40, 0x34, 0x40, ++0x6C, 0x40, 0x34, 0x40, 0x64, 0x40, 0x34, 0x40, 0x58, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, ++0x1C, 0x20, 0x34, 0x40, 0xDC, 0x18, 0x17, 0x00, 0x1C, 0xC2, 0x33, 0x40, 0x20, 0xC2, 0x33, 0x40, 0x30, 0xC2, 0x33, 0x40, ++0x3C, 0x36, 0x17, 0x00, 0x38, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0xAC, 0xB3, 0x33, 0x40, ++0xD4, 0xB3, 0x33, 0x40, 0x1C, 0x13, 0x17, 0x00, 0x10, 0xB4, 0x1C, 0x4B, 0x1C, 0x4C, 0x0F, 0xCB, 0x85, 0xB0, 0x0D, 0xF1, ++0x10, 0x0C, 0x0C, 0xE9, 0x0F, 0x00, 0x63, 0x68, 0xDB, 0x06, 0x16, 0xD5, 0x61, 0x68, 0xA3, 0x69, 0x5C, 0xFA, 0x83, 0xF3, ++0xC8, 0x04, 0x13, 0xF8, 0x10, 0x2C, 0x22, 0xD4, 0x60, 0x68, 0x14, 0x49, 0x14, 0x4B, 0x10, 0xF4, 0x80, 0x7F, 0x08, 0xBF, ++0x0B, 0x46, 0x11, 0x06, 0x44, 0xBF, 0x5B, 0x00, 0x02, 0xF0, 0x7F, 0x02, 0xB3, 0xFB, 0xF2, 0xF3, 0x00, 0xE0, 0x0F, 0x4B, ++0x0B, 0x4A, 0x0F, 0x4C, 0x52, 0x69, 0x0F, 0x48, 0x0F, 0x49, 0xD2, 0xB2, 0xB3, 0xFB, 0xF2, 0xF3, 0x23, 0x60, 0xD0, 0xF8, ++0x84, 0x20, 0xD2, 0xB2, 0xB3, 0xFB, 0xF2, 0xF3, 0x0B, 0x60, 0x05, 0xB0, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x09, 0x4B, ++0xE1, 0xE7, 0x00, 0xBF, 0x60, 0x79, 0x15, 0x00, 0x00, 0x00, 0x50, 0x40, 0x00, 0x38, 0x9C, 0x1C, 0x00, 0xD0, 0x12, 0x13, ++0x00, 0x75, 0x19, 0x03, 0x18, 0x13, 0x17, 0x00, 0x00, 0x00, 0x10, 0x40, 0x14, 0x13, 0x17, 0x00, 0x00, 0x70, 0x38, 0x39, ++0x70, 0xB4, 0x5D, 0x4C, 0x5D, 0x48, 0x23, 0x68, 0x5D, 0x4D, 0x5E, 0x49, 0x5E, 0x4A, 0x23, 0xF4, 0xC0, 0x63, 0x43, 0xF4, ++0x00, 0x73, 0x23, 0x60, 0x03, 0x68, 0x95, 0xF8, 0xFA, 0x40, 0x23, 0xF4, 0xBC, 0x03, 0x23, 0xF4, 0x70, 0x53, 0x43, 0xF4, ++0x60, 0x23, 0x43, 0xF4, 0x80, 0x63, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x60, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0xFE, 0x33, 0x43, 0xF4, 0x98, 0x33, 0x13, 0x60, 0x00, 0x2C, 0x00, 0xF0, 0x8F, 0x80, 0xA2, 0xF5, 0x11, 0x12, 0xA2, 0xF6, ++0x4C, 0x52, 0x13, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x13, 0x60, 0x4C, 0x4D, 0x4C, 0x48, 0x2B, 0x68, 0x4C, 0x4C, 0x4D, 0x4A, ++0x4D, 0x49, 0x4E, 0x4E, 0x43, 0xF0, 0x80, 0x63, 0x2B, 0x60, 0x03, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x03, 0x60, 0x23, 0x68, ++0x23, 0xF4, 0x7F, 0x73, 0x43, 0xF0, 0x04, 0x03, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x80, 0x53, 0x43, 0xF4, 0x00, 0x63, ++0x03, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xCC, 0x03, 0x43, 0xF0, 0xC4, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x03, 0xF0, 0x7F, 0x43, ++0xA5, 0xF5, 0xF8, 0x55, 0x43, 0xF4, 0x78, 0x13, 0x0C, 0x3D, 0x43, 0xF4, 0x78, 0x73, 0x0B, 0x60, 0x2B, 0x68, 0x1B, 0x0C, ++0xA4, 0xF5, 0x00, 0x54, 0x1B, 0x04, 0x34, 0x3C, 0x43, 0xF0, 0x84, 0x03, 0x2B, 0x60, 0x23, 0x68, 0x37, 0x4D, 0x23, 0xF4, ++0x40, 0x63, 0x43, 0xF4, 0x00, 0x63, 0x23, 0x60, 0xD0, 0xF8, 0x04, 0x31, 0x02, 0xF5, 0xF8, 0x52, 0x23, 0xF4, 0xE0, 0x23, ++0x18, 0x32, 0x43, 0xF4, 0x80, 0x33, 0xC0, 0xF8, 0x04, 0x31, 0x13, 0x68, 0x23, 0xF0, 0x76, 0x53, 0x23, 0xF0, 0x07, 0x03, ++0x01, 0xF5, 0xF7, 0x51, 0x43, 0xF0, 0x04, 0x53, 0x04, 0x31, 0x43, 0xF0, 0x07, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x04, 0xF5, ++0x00, 0x54, 0x02, 0xF1, 0xEF, 0x52, 0x00, 0xF5, 0x01, 0x50, 0x1C, 0x34, 0x02, 0xF5, 0x3D, 0x22, 0x02, 0xF6, 0x44, 0x02, ++0x1D, 0x40, 0x08, 0x30, 0x22, 0x4B, 0x0D, 0x60, 0x32, 0x60, 0x23, 0x60, 0x03, 0x68, 0x21, 0x4A, 0x21, 0x4C, 0x23, 0xF4, ++0x7F, 0x23, 0x23, 0xF4, 0x00, 0x63, 0x43, 0xF4, 0x32, 0x33, 0x03, 0x60, 0xCB, 0x68, 0x43, 0xF4, 0x00, 0x63, 0xCB, 0x60, ++0x13, 0x68, 0x23, 0xF0, 0x09, 0x03, 0x43, 0xF4, 0x80, 0x53, 0x13, 0x60, 0x23, 0x68, 0x1B, 0x07, 0x08, 0xD5, 0xA2, 0xF5, ++0x0F, 0x12, 0xA2, 0xF5, 0x03, 0x52, 0x24, 0x3A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x53, 0x13, 0x60, 0x70, 0xBC, 0x70, 0x47, ++0x12, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x00, 0x73, 0x13, 0x60, 0x70, 0xE7, 0x20, 0x40, 0x34, 0x40, ++0x24, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x28, 0x40, 0x34, 0x40, 0x04, 0x01, 0x58, 0x40, 0x38, 0x40, 0x34, 0x40, ++0x30, 0x20, 0x34, 0x40, 0x48, 0x40, 0x34, 0x40, 0x28, 0x21, 0x34, 0x40, 0x24, 0x21, 0x34, 0x40, 0x2C, 0x40, 0x34, 0x40, ++0x03, 0x00, 0x00, 0xFF, 0x08, 0x51, 0x2E, 0x1A, 0x08, 0x01, 0x58, 0x40, 0x94, 0x40, 0x04, 0x40, 0xB8, 0xB3, 0x33, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xDE, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xE6, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xE8, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x24, 0x1C, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xEA, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x2D, 0xE9, 0xF0, 0x47, 0x4C, 0x4B, 0x4D, 0x4D, 0x08, 0x22, 0xC3, 0xF8, 0x00, 0x21, 0xAB, 0x78, 0x33, 0xB9, 0x4B, 0x4A, ++0x93, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x43, 0xF4, 0x00, 0x33, 0x93, 0x60, 0x47, 0x4A, 0x13, 0x6B, 0x03, 0xF0, 0x22, 0x03, ++0x02, 0x2B, 0xFA, 0xD1, 0x93, 0x68, 0x45, 0x4C, 0x41, 0x49, 0x45, 0x48, 0x23, 0xF4, 0x00, 0x63, 0x43, 0xF0, 0x01, 0x13, ++0x43, 0xF4, 0x04, 0x43, 0x93, 0x60, 0x06, 0x23, 0x23, 0x60, 0x53, 0x6D, 0x40, 0x4C, 0x23, 0xF4, 0x40, 0x13, 0x53, 0x65, ++0x4F, 0xF4, 0x00, 0x63, 0xC1, 0xF8, 0x34, 0x31, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x03, ++0x01, 0x40, 0x0B, 0x43, 0x13, 0x60, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x08, 0xD1, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, ++0x09, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x08, 0x40, 0x18, 0x43, 0x10, 0x60, 0x2E, 0x49, 0x2C, 0x4E, 0x0B, 0x68, 0x0A, 0x68, ++0x30, 0x48, 0xC3, 0xF3, 0x09, 0x03, 0x22, 0xF4, 0x7F, 0x72, 0x22, 0xF0, 0x03, 0x02, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x43, ++0x0B, 0x60, 0x73, 0x6F, 0x2B, 0x4A, 0x43, 0xF0, 0x02, 0x03, 0x73, 0x67, 0x03, 0x68, 0x2A, 0x4E, 0x23, 0xF4, 0x00, 0x63, ++0x03, 0x60, 0x13, 0x68, 0x96, 0xF8, 0xA9, 0x00, 0x43, 0xF0, 0x80, 0x73, 0x13, 0x60, 0x68, 0xB1, 0x0B, 0x6B, 0x5F, 0x06, ++0x05, 0xD4, 0x0B, 0x6B, 0x58, 0x07, 0x02, 0xD5, 0x22, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x1A, 0x4B, 0x1A, 0x6B, 0x52, 0x06, ++0x40, 0xF1, 0x10, 0x82, 0x1F, 0x4B, 0xD6, 0xF8, 0xA0, 0x20, 0x1A, 0x60, 0xAB, 0x78, 0x00, 0x2B, 0x3E, 0xD0, 0x1D, 0x4B, ++0x1A, 0x68, 0x13, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x6C, 0x82, 0x11, 0x4B, 0x0E, 0x48, 0x02, 0x21, 0x11, 0x70, 0x1A, 0x6D, ++0xA9, 0x78, 0x42, 0xF4, 0x80, 0x22, 0x1A, 0x65, 0x02, 0x69, 0x22, 0xF0, 0x80, 0x02, 0x02, 0x61, 0x5A, 0x6A, 0x22, 0xF0, ++0xFF, 0x02, 0x42, 0xF0, 0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, 0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, ++0x00, 0x29, 0x33, 0xD0, 0x03, 0xF0, 0xB0, 0xFC, 0x0C, 0x4F, 0x33, 0xE0, 0x00, 0x00, 0x50, 0x40, 0x3C, 0x36, 0x17, 0x00, ++0x00, 0x60, 0x50, 0x40, 0x10, 0x00, 0x58, 0x40, 0x00, 0xFC, 0xFF, 0xFF, 0x78, 0x36, 0x17, 0x00, 0x00, 0x01, 0x58, 0x40, ++0x20, 0x01, 0x58, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, 0x74, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xC0, 0x4B, 0xC1, 0x49, 0x1A, 0x6D, 0x42, 0xF4, 0x80, 0x22, 0x1A, 0x65, 0x0A, 0x69, 0x22, 0xF0, ++0x80, 0x02, 0x0A, 0x61, 0x5A, 0x6A, 0x22, 0xF0, 0xFF, 0x02, 0x42, 0xF0, 0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, ++0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, 0xB7, 0x4F, 0xD7, 0xF8, 0xCC, 0x30, 0x98, 0x47, 0x03, 0xF0, 0xF4, 0xF9, ++0xD7, 0xF8, 0x9C, 0x34, 0x98, 0x47, 0xB2, 0x4B, 0xB3, 0x49, 0x1B, 0x68, 0xB3, 0x4A, 0xA8, 0x78, 0x1B, 0x0C, 0x0B, 0x70, ++0x04, 0x23, 0x1B, 0x68, 0x1B, 0x09, 0x13, 0x70, 0x10, 0xB9, 0xD7, 0xF8, 0x80, 0x34, 0x98, 0x47, 0xAE, 0x48, 0xAF, 0x4D, ++0xFF, 0xF7, 0x78, 0xFE, 0xAE, 0x48, 0xFF, 0xF7, 0x9D, 0xFE, 0x03, 0x46, 0x1A, 0x0C, 0xAD, 0x49, 0x2A, 0x70, 0x1B, 0x0F, ++0x02, 0x22, 0x0B, 0x70, 0xAB, 0x48, 0x11, 0x46, 0xFF, 0xF7, 0xE2, 0xFE, 0x4F, 0xF4, 0x80, 0x52, 0x11, 0x46, 0xA9, 0x48, ++0xFF, 0xF7, 0xDC, 0xFE, 0xA8, 0x4A, 0xA9, 0x49, 0xA9, 0x48, 0xFF, 0xF7, 0xD7, 0xFE, 0x2B, 0x78, 0x01, 0x2B, 0x00, 0xF0, ++0x8E, 0x81, 0xA7, 0x48, 0x4F, 0xF4, 0x7F, 0x52, 0x4F, 0xF4, 0x9E, 0x51, 0xFF, 0xF7, 0xCC, 0xFE, 0x04, 0x22, 0xA4, 0x48, ++0x11, 0x46, 0xFF, 0xF7, 0xC7, 0xFE, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x04, 0xD0, 0xA1, 0x48, 0x07, 0x22, 0x00, 0x21, ++0xFF, 0xF7, 0xBE, 0xFE, 0x01, 0x21, 0x02, 0x20, 0x03, 0xF0, 0x5C, 0xFE, 0x04, 0x22, 0x9D, 0x48, 0x00, 0x21, 0xFF, 0xF7, ++0xB5, 0xFE, 0x01, 0x21, 0x03, 0x20, 0x03, 0xF0, 0x53, 0xFE, 0x08, 0x22, 0x98, 0x48, 0x00, 0x21, 0xFF, 0xF7, 0xAC, 0xFE, ++0x00, 0x21, 0x05, 0x20, 0x03, 0xF0, 0x4A, 0xFE, 0x95, 0x48, 0x20, 0x22, 0x00, 0x21, 0xFF, 0xF7, 0xA3, 0xFE, 0x20, 0x22, ++0x11, 0x46, 0x93, 0x48, 0xFF, 0xF7, 0x9E, 0xFE, 0x20, 0x22, 0x11, 0x46, 0x91, 0x48, 0xFF, 0xF7, 0x99, 0xFE, 0x02, 0x22, ++0x90, 0x48, 0x11, 0x46, 0xFF, 0xF7, 0x94, 0xFE, 0x4F, 0xF4, 0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x00, 0xF0, ++0x60, 0x00, 0x20, 0x28, 0x00, 0xF0, 0x74, 0x81, 0x4F, 0xF4, 0xFC, 0x02, 0x11, 0x46, 0x89, 0x48, 0xFF, 0xF7, 0x84, 0xFE, ++0x88, 0x4A, 0x89, 0x48, 0x4F, 0xF0, 0x46, 0x41, 0xFF, 0xF7, 0x7E, 0xFE, 0x87, 0x48, 0x3F, 0x22, 0x1F, 0x21, 0xFF, 0xF7, ++0x79, 0xFE, 0x4F, 0xF4, 0x80, 0x22, 0x85, 0x48, 0x00, 0x21, 0xFF, 0xF7, 0x73, 0xFE, 0x84, 0x48, 0x4F, 0xF4, 0x8E, 0x71, ++0xFF, 0xF7, 0x46, 0xFE, 0x82, 0x48, 0x4F, 0xF4, 0xF8, 0x22, 0x4F, 0xF4, 0xD8, 0x21, 0xFF, 0xF7, 0x67, 0xFE, 0x40, 0x22, ++0x11, 0x46, 0x7F, 0x48, 0xFF, 0xF7, 0x62, 0xFE, 0x4F, 0xF4, 0xC0, 0x32, 0x11, 0x46, 0x7D, 0x48, 0xFF, 0xF7, 0x5C, 0xFE, ++0x7C, 0x48, 0x4F, 0xF4, 0xE0, 0x62, 0x4F, 0xF4, 0x00, 0x71, 0xFF, 0xF7, 0x55, 0xFE, 0x96, 0xF8, 0xC7, 0x70, 0xB7, 0xB3, ++0x78, 0x4A, 0x96, 0xF8, 0xC8, 0x10, 0x78, 0x4B, 0x96, 0xF8, 0xC9, 0x00, 0x11, 0x70, 0x96, 0xF8, 0xCA, 0x10, 0x50, 0x70, ++0x91, 0x70, 0x96, 0xF8, 0xCB, 0x50, 0x96, 0xF8, 0xCC, 0x00, 0x96, 0xF8, 0xCD, 0x10, 0x96, 0xF8, 0xCE, 0x20, 0x1D, 0x70, ++0x58, 0x70, 0x99, 0x70, 0xDA, 0x70, 0x4F, 0xF4, 0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x10, 0xF4, 0x60, 0x2F, ++0xC0, 0xF3, 0x42, 0x41, 0x0E, 0xD0, 0x6A, 0x4A, 0x8D, 0x01, 0x02, 0xF1, 0x40, 0x00, 0x52, 0xF8, 0x04, 0x3F, 0x23, 0xF4, ++0xE0, 0x73, 0x2B, 0x43, 0x90, 0x42, 0x13, 0x60, 0xF7, 0xD1, 0x65, 0x48, 0x03, 0xF0, 0x68, 0xFD, 0x23, 0x68, 0x1C, 0x78, ++0x01, 0x2C, 0x00, 0xF0, 0xEF, 0x80, 0xBD, 0xE8, 0xF0, 0x87, 0x4F, 0xF4, 0xD2, 0x76, 0x0A, 0x20, 0x33, 0x68, 0xDF, 0xF8, ++0x6C, 0xA1, 0x98, 0x47, 0x33, 0x68, 0x05, 0x46, 0x0B, 0x20, 0x98, 0x47, 0x33, 0x68, 0x80, 0x46, 0x0F, 0x20, 0x98, 0x47, ++0x5F, 0xEA, 0x95, 0x7C, 0x3A, 0x46, 0x0C, 0xBF, 0x4F, 0xF0, 0x08, 0x09, 0x4F, 0xF0, 0x10, 0x09, 0x4F, 0xEA, 0x15, 0x6E, ++0xD3, 0x00, 0x25, 0xFA, 0x03, 0xF3, 0xDF, 0xB2, 0xC3, 0xF3, 0x03, 0x13, 0xBC, 0xF1, 0x00, 0x0F, 0x38, 0xD1, 0x00, 0x2B, ++0x54, 0xD1, 0x00, 0x2F, 0x40, 0xF0, 0x1F, 0x81, 0x01, 0x32, 0x03, 0x2A, 0xEE, 0xD1, 0xDF, 0xF8, 0x24, 0xE1, 0x07, 0x0E, ++0x00, 0x21, 0xCB, 0x00, 0x28, 0xFA, 0x03, 0xF3, 0xDE, 0xB2, 0xC3, 0xF3, 0x03, 0x13, 0xBC, 0xF1, 0x00, 0x0F, 0x0B, 0xD1, ++0xEB, 0xB1, 0x08, 0x22, 0x93, 0x42, 0x28, 0xBF, 0xD3, 0x1A, 0x5B, 0xB2, 0x0E, 0xF8, 0x01, 0x30, 0x01, 0x31, 0x04, 0x29, ++0xEB, 0xD1, 0x9C, 0xE7, 0x4D, 0x00, 0x6A, 0x1C, 0x47, 0xFA, 0x02, 0xF2, 0x12, 0x01, 0x02, 0xF0, 0x10, 0x02, 0x13, 0x43, ++0x13, 0xF0, 0xFF, 0x03, 0x1F, 0xD1, 0x47, 0xFA, 0x05, 0xF3, 0x1B, 0x01, 0x03, 0xF0, 0x10, 0x03, 0x06, 0xF0, 0x0F, 0x06, ++0x1E, 0x43, 0x00, 0x2E, 0xE6, 0xD0, 0x33, 0x46, 0x4A, 0x46, 0xDD, 0xE7, 0x56, 0x00, 0x71, 0x1C, 0x4E, 0xFA, 0x01, 0xF1, ++0x09, 0x01, 0x01, 0xF0, 0x10, 0x01, 0x0B, 0x43, 0x13, 0xF0, 0xFF, 0x03, 0x09, 0xD0, 0x10, 0x21, 0x8B, 0x42, 0x28, 0xBF, ++0xCB, 0x1A, 0x5B, 0xB2, 0x0A, 0xF8, 0x02, 0x30, 0xB8, 0xE7, 0x10, 0x22, 0xC8, 0xE7, 0x4E, 0xFA, 0x06, 0xF3, 0x1B, 0x01, ++0x03, 0xF0, 0x10, 0x03, 0x07, 0xF0, 0x0F, 0x07, 0x1F, 0x43, 0xAA, 0xE7, 0x08, 0x21, 0xEB, 0xE7, 0x00, 0x60, 0x50, 0x40, ++0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x11, 0x13, 0x17, 0x00, 0x12, 0x13, 0x17, 0x00, 0x04, 0x02, 0x22, 0x03, ++0x10, 0x13, 0x17, 0x00, 0x00, 0x00, 0x01, 0x50, 0x70, 0x25, 0x17, 0x00, 0x50, 0x91, 0x01, 0x50, 0x20, 0x91, 0x01, 0x50, ++0xC0, 0xFD, 0x01, 0x00, 0xC0, 0xF1, 0x01, 0x00, 0x24, 0x91, 0x01, 0x50, 0x08, 0x88, 0x01, 0x50, 0x18, 0x88, 0x01, 0x50, ++0x2C, 0x91, 0x01, 0x50, 0x00, 0x10, 0x01, 0x50, 0x0C, 0x10, 0x01, 0x50, 0x10, 0x10, 0x01, 0x50, 0x18, 0x10, 0x01, 0x50, ++0x00, 0x30, 0x01, 0x50, 0x00, 0x88, 0x01, 0x50, 0x00, 0x00, 0xC0, 0xFF, 0x04, 0x88, 0x01, 0x50, 0x28, 0x91, 0x01, 0x50, ++0x5C, 0x00, 0x01, 0x50, 0x58, 0x00, 0x01, 0x50, 0x74, 0x91, 0x01, 0x50, 0x18, 0x91, 0x01, 0x50, 0x00, 0x91, 0x01, 0x50, ++0x30, 0x88, 0x01, 0x50, 0x68, 0x25, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x18, 0x18, 0x17, 0x00, 0x74, 0x79, 0x15, 0x00, ++0x1B, 0x6B, 0x59, 0x07, 0x7F, 0xF5, 0xEC, 0xAD, 0xD6, 0xF8, 0xA0, 0x30, 0x3F, 0x48, 0x40, 0x49, 0x40, 0x4A, 0x43, 0xF0, ++0x00, 0x73, 0x01, 0x27, 0x07, 0x70, 0x0B, 0x60, 0x53, 0x6F, 0x43, 0xF0, 0x10, 0x03, 0x53, 0x67, 0xE0, 0xE5, 0x3C, 0x4A, ++0x3C, 0x49, 0x3D, 0x48, 0xFF, 0xF7, 0x40, 0xFD, 0x3C, 0x48, 0x4F, 0xF4, 0x08, 0x42, 0x4F, 0xF4, 0x00, 0x41, 0xFF, 0xF7, ++0x39, 0xFD, 0x3A, 0x4A, 0x3A, 0x49, 0x3B, 0x48, 0xFF, 0xF7, 0x34, 0xFD, 0x3A, 0x48, 0x8F, 0x22, 0x06, 0x21, 0xFF, 0xF7, ++0x2F, 0xFD, 0x66, 0xE6, 0x38, 0x49, 0x39, 0x48, 0x4F, 0xF0, 0xFF, 0x32, 0xFF, 0xF7, 0x28, 0xFD, 0x4F, 0xF0, 0xFF, 0x32, ++0x36, 0x48, 0x4F, 0xF0, 0x02, 0x11, 0xFF, 0xF7, 0x21, 0xFD, 0x35, 0x49, 0x35, 0x48, 0xFF, 0xF7, 0xF5, 0xFC, 0x22, 0x46, ++0x21, 0x46, 0x34, 0x48, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x16, 0xBD, 0x32, 0x48, 0x0F, 0x22, 0x01, 0x21, 0xFF, 0xF7, ++0x11, 0xFD, 0x02, 0x22, 0x11, 0x46, 0x30, 0x48, 0xFF, 0xF7, 0x0C, 0xFD, 0x02, 0x22, 0x11, 0x46, 0x2E, 0x48, 0xFF, 0xF7, ++0x07, 0xFD, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x2A, 0x48, 0xFF, 0xF7, 0x01, 0xFD, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, ++0x28, 0x48, 0xFF, 0xF7, 0xFB, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x27, 0x48, 0xFF, 0xF7, 0xF6, 0xFC, 0x25, 0x48, 0x4F, 0xF4, ++0x00, 0x52, 0x00, 0x21, 0xFF, 0xF7, 0xF0, 0xFC, 0x64, 0xE6, 0x23, 0x4B, 0x0F, 0x49, 0x1A, 0x6D, 0x22, 0x4F, 0x42, 0xF4, ++0x80, 0x22, 0x1A, 0x65, 0x0A, 0x69, 0x22, 0xF0, 0x80, 0x02, 0x0A, 0x61, 0x5A, 0x6A, 0x22, 0xF0, 0xFF, 0x02, 0x42, 0xF0, ++0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, 0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, 0x03, 0xF0, 0x48, 0xFA, ++0xCC, 0xE5, 0x3B, 0x46, 0x49, 0x46, 0x1D, 0xE7, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, 0x00, 0x00, 0x50, 0x40, ++0xC0, 0x3F, 0x00, 0x40, 0x40, 0x12, 0x00, 0x40, 0x08, 0x88, 0x01, 0x50, 0x04, 0x91, 0x01, 0x50, 0xE0, 0x01, 0x00, 0x22, ++0xC0, 0x00, 0x00, 0x02, 0x08, 0x91, 0x01, 0x50, 0x00, 0x91, 0x01, 0x50, 0x00, 0x01, 0x00, 0x03, 0x0C, 0x80, 0x01, 0x50, ++0x18, 0x80, 0x01, 0x50, 0x0A, 0x33, 0x41, 0x01, 0x38, 0x91, 0x01, 0x50, 0x04, 0x00, 0x01, 0x50, 0x04, 0x20, 0x01, 0x50, ++0x04, 0x10, 0x01, 0x50, 0x08, 0x10, 0x01, 0x50, 0x00, 0x10, 0x01, 0x50, 0x00, 0x60, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x10, 0x4B, 0x11, 0x4A, 0x19, 0x68, 0x21, 0xF4, 0x78, 0x11, 0x41, 0xF4, 0x50, 0x11, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, ++0x78, 0x11, 0x41, 0xF4, 0xA0, 0x11, 0x19, 0x60, 0x11, 0x69, 0x18, 0x68, 0x20, 0xF4, 0x78, 0x10, 0x40, 0xF4, 0x50, 0x10, ++0x32, 0x31, 0x18, 0x60, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x78, 0x13, ++0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x70, 0x47, 0x58, 0x40, 0x34, 0x40, 0x00, 0x10, 0x50, 0x40, 0x1E, 0x49, 0x1F, 0x4A, ++0x0B, 0x68, 0x43, 0xF4, 0x00, 0x13, 0x10, 0xB4, 0x0B, 0x60, 0x13, 0x68, 0x59, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x59, 0x07, 0xF6, 0xD5, 0x15, 0x49, 0x15, 0x4A, 0x0B, 0x68, ++0x43, 0xF4, 0xC0, 0x23, 0x0B, 0x60, 0x13, 0x68, 0x9B, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, ++0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x9B, 0x07, 0xF6, 0xD5, 0x0E, 0x4C, 0x0E, 0x48, 0x23, 0x68, 0x0E, 0x4A, 0x0F, 0x49, ++0x43, 0xF4, 0x00, 0x33, 0x23, 0x60, 0x03, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x43, 0xF0, 0x80, 0x73, 0x03, 0x60, 0x13, 0x68, ++0x43, 0xF4, 0xA4, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0xA1, 0xBD, 0x00, 0xBF, ++0x58, 0x40, 0x34, 0x40, 0x80, 0x40, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x10, 0x00, 0x34, 0x40, 0x30, 0x20, 0x34, 0x40, ++0x9C, 0x79, 0x15, 0x00, 0x10, 0xB5, 0x10, 0x4C, 0x10, 0x48, 0x23, 0x68, 0x10, 0x49, 0x11, 0x4A, 0x23, 0xF4, 0x05, 0x43, ++0x23, 0xF0, 0xEC, 0x03, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x00, 0x33, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x73, ++0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xC0, 0x23, 0x0A, 0x20, 0x13, 0x60, 0xFD, 0xF7, 0xD6, 0xFC, 0xBD, 0xE8, 0x10, 0x40, ++0x06, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0x73, 0xBD, 0x00, 0xBF, 0x30, 0x20, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, ++0x10, 0x00, 0x34, 0x40, 0x58, 0x40, 0x34, 0x40, 0xB8, 0x79, 0x15, 0x00, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, ++0x00, 0x2B, 0xFA, 0xD1, 0x19, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, ++0xFA, 0xD1, 0x16, 0x4A, 0x13, 0x68, 0xDB, 0x07, 0x11, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, ++0xFA, 0xD1, 0x13, 0x68, 0xDB, 0x07, 0xF6, 0xD5, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, ++0x13, 0x68, 0xDB, 0x07, 0xED, 0xD5, 0x0B, 0x4B, 0x1A, 0x68, 0x53, 0x0C, 0x00, 0x2A, 0xBC, 0xBF, 0x6F, 0xEA, 0x43, 0x43, ++0x6F, 0xEA, 0x53, 0x43, 0x03, 0x60, 0xC2, 0xF3, 0x4E, 0x03, 0x12, 0x04, 0x44, 0xBF, 0x6F, 0xEA, 0x43, 0x43, 0x6F, 0xEA, ++0x53, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x84, 0x21, 0x34, 0x40, 0x00, 0x22, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x2A, 0x4F, 0x2B, 0x4D, 0x3B, 0x68, 0x2B, 0x4A, 0x23, 0xF4, 0x7F, 0x53, 0x3B, 0x60, 0x2B, 0x68, 0x43, 0xF4, 0x80, 0x63, ++0x2B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x01, 0x20, 0xFD, 0xF7, 0x72, 0xFC, 0x00, 0x24, 0x26, 0x46, ++0x4F, 0xF0, 0x07, 0x08, 0x02, 0x20, 0xFD, 0xF7, 0x6B, 0xFC, 0x2B, 0x68, 0xDA, 0x05, 0x54, 0xBF, 0x01, 0x36, 0x06, 0xF1, ++0xFF, 0x36, 0x76, 0xB2, 0x1B, 0x06, 0x3B, 0x68, 0x54, 0xBF, 0x01, 0x34, 0x04, 0xF1, 0xFF, 0x34, 0x00, 0x2E, 0x23, 0xF4, ++0x7F, 0x53, 0xDC, 0xBF, 0x70, 0x42, 0x43, 0xEA, 0x80, 0x23, 0x64, 0xB2, 0xD4, 0xBF, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xEA, ++0x86, 0x23, 0x00, 0x2C, 0xDC, 0xBF, 0x60, 0x42, 0x43, 0xEA, 0x80, 0x13, 0x08, 0xF1, 0xFF, 0x32, 0xCC, 0xBF, 0x43, 0xEA, ++0x84, 0x13, 0x43, 0xF4, 0x00, 0x73, 0x12, 0xF0, 0xFF, 0x08, 0x3B, 0x60, 0xD2, 0xD1, 0x0A, 0x48, 0x0A, 0x49, 0x02, 0x68, ++0x22, 0xF4, 0x80, 0x62, 0x02, 0x60, 0x0A, 0x68, 0xC3, 0xF3, 0x83, 0x10, 0x22, 0xF0, 0x40, 0x02, 0xC3, 0xF3, 0x83, 0x23, ++0x0A, 0x60, 0x43, 0xEA, 0x00, 0x10, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x50, 0x40, 0x34, 0x40, 0x14, 0x40, 0x34, 0x40, ++0x5C, 0x40, 0x34, 0x40, 0x01, 0x28, 0x15, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x4B, 0x78, 0x10, 0x2B, 0x19, 0xD8, 0x30, 0x23, ++0x8B, 0x70, 0x70, 0x47, 0xD2, 0xE9, 0x00, 0x32, 0x00, 0x2B, 0x24, 0xDD, 0x00, 0x2A, 0x37, 0xDB, 0xB3, 0xEB, 0x42, 0x0F, ++0x0B, 0x78, 0xCC, 0xBF, 0x10, 0x3B, 0x18, 0x3B, 0x4B, 0x70, 0x70, 0x47, 0x13, 0x68, 0xB3, 0xF5, 0x00, 0x5F, 0x10, 0xDA, ++0x00, 0x2B, 0x1A, 0xDD, 0x40, 0x23, 0x0B, 0x70, 0x70, 0x47, 0x30, 0x2B, 0x0C, 0xD9, 0x60, 0x2B, 0x1A, 0xD8, 0x92, 0x68, ++0x00, 0x2A, 0x28, 0xDB, 0x60, 0x2B, 0xDC, 0xD1, 0x20, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x20, 0x23, 0x0B, 0x70, 0x70, 0x47, ++0x18, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x00, 0x2A, 0x1E, 0xDD, 0x0B, 0x78, 0x20, 0x3B, 0x4B, 0x70, 0x70, 0x47, 0x13, 0xF5, ++0x00, 0x5F, 0xD4, 0xBF, 0xE0, 0x23, 0xC0, 0x23, 0x0B, 0x70, 0x70, 0x47, 0xC0, 0x2B, 0x09, 0xD8, 0x92, 0x68, 0x00, 0x2A, ++0x19, 0xDD, 0x60, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x0B, 0x78, 0x20, 0x33, 0x4B, 0x70, 0x70, 0x47, 0xD8, 0x2B, 0x0D, 0xD8, ++0xE8, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xA0, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xB3, 0xEB, 0x42, 0x0F, 0x0B, 0x78, 0xB4, 0xBF, ++0x10, 0x33, 0x18, 0x33, 0x4B, 0x70, 0x70, 0x47, 0xD0, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xA0, 0x2B, 0xFA, 0xD1, 0xE0, 0x23, ++0x8B, 0x70, 0x70, 0x47, 0x01, 0x28, 0x1D, 0xD0, 0x02, 0x28, 0x08, 0xD0, 0x09, 0x78, 0x01, 0x39, 0x05, 0x29, 0x69, 0xD8, ++0xDF, 0xE8, 0x01, 0xF0, 0x3C, 0x42, 0x39, 0x33, 0x2D, 0x2A, 0x10, 0xB4, 0x1C, 0x68, 0xB4, 0xF5, 0x00, 0x5F, 0x19, 0xDA, ++0x00, 0x2C, 0x4A, 0xDD, 0x5B, 0x68, 0x00, 0x2B, 0x13, 0x78, 0xAA, 0xBF, 0x03, 0x20, 0x10, 0x33, 0x10, 0x3B, 0x53, 0x70, ++0x08, 0x70, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x1B, 0x68, 0xB3, 0xF5, 0x00, 0x5F, 0x04, 0xDA, 0x00, 0x2B, 0x2B, 0xDD, ++0x50, 0x23, 0x13, 0x70, 0x70, 0x47, 0x30, 0x23, 0x13, 0x70, 0x70, 0x47, 0x13, 0x78, 0x01, 0x20, 0x10, 0x33, 0x53, 0x70, ++0x08, 0x70, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xC8, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0x21, 0xDD, ++0x70, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0x18, 0xDD, 0x90, 0x23, 0x93, 0x70, 0x70, 0x47, 0x38, 0x23, ++0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0xF0, 0xDD, 0x20, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, ++0xF0, 0xDD, 0x40, 0x23, 0x93, 0x70, 0x70, 0x47, 0x13, 0xF5, 0x00, 0x5F, 0xD4, 0xBF, 0xD0, 0x23, 0xB0, 0x23, 0x13, 0x70, ++0x70, 0x47, 0xE0, 0x23, 0x93, 0x70, 0x70, 0x47, 0xC0, 0x23, 0x93, 0x70, 0x70, 0x47, 0x14, 0xF5, 0x00, 0x5F, 0x05, 0xDC, ++0x13, 0x78, 0x04, 0x20, 0x10, 0x3B, 0x53, 0x70, 0x08, 0x70, 0xB4, 0xE7, 0x5B, 0x68, 0x00, 0x2B, 0x13, 0x78, 0xCC, 0xBF, ++0x05, 0x20, 0x06, 0x20, 0x10, 0x3B, 0x53, 0x70, 0x08, 0x70, 0xAA, 0xE7, 0x88, 0x23, 0x93, 0x70, 0x70, 0x47, 0x00, 0xBF, ++0x30, 0xB4, 0x0F, 0x29, 0x15, 0x46, 0x1C, 0x46, 0x02, 0x9A, 0x03, 0xD0, 0x30, 0xBC, 0x19, 0x46, 0xFF, 0xF7, 0x1C, 0xBF, ++0x13, 0x46, 0x29, 0x46, 0x22, 0x46, 0x30, 0xBC, 0xFF, 0xF7, 0x7A, 0xBF, 0x70, 0xB4, 0x50, 0xEA, 0x01, 0x04, 0x02, 0xD1, ++0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x08, 0x18, 0x18, 0xBF, 0x00, 0x21, 0x03, 0xD1, 0x20, 0xE0, 0xE9, 0xB2, 0x81, 0x42, ++0x1D, 0xDA, 0x53, 0xF8, 0x21, 0x40, 0x94, 0x42, 0x01, 0xF1, 0x01, 0x05, 0x03, 0xEB, 0x81, 0x06, 0xF4, 0xDC, 0xC0, 0xB2, ++0x88, 0x42, 0x0F, 0xD9, 0x44, 0x1E, 0x61, 0x1A, 0x1C, 0x1F, 0xC9, 0xB2, 0x04, 0xEB, 0x80, 0x04, 0xA4, 0xEB, 0x81, 0x04, ++0x03, 0xEB, 0x80, 0x03, 0x53, 0xF8, 0x04, 0x1C, 0x43, 0xF8, 0x04, 0x19, 0xA3, 0x42, 0xF9, 0xD1, 0x32, 0x60, 0x70, 0xBC, ++0x70, 0x47, 0x70, 0xBC, 0x43, 0xF8, 0x20, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0xF1, 0xFF, 0x3C, ++0x85, 0xB0, 0xCC, 0xF3, 0x47, 0x0C, 0x4F, 0xF0, 0x80, 0x34, 0x48, 0xF2, 0x80, 0x03, 0x01, 0x28, 0xCD, 0xE9, 0x01, 0xC4, ++0xAD, 0xF8, 0x0C, 0x30, 0x40, 0xF2, 0x83, 0x80, 0x80, 0x24, 0xA2, 0x46, 0x16, 0x46, 0x00, 0x25, 0x01, 0x23, 0x43, 0xF2, ++0xB0, 0x69, 0x8E, 0x46, 0x00, 0x92, 0x18, 0xE0, 0x80, 0x2C, 0x04, 0xBF, 0x04, 0xAA, 0x02, 0xEB, 0x45, 0x01, 0x4F, 0xEA, ++0x45, 0x07, 0x04, 0xAA, 0x17, 0x44, 0x04, 0xBF, 0x03, 0xF1, 0xFF, 0x34, 0x01, 0xF8, 0x08, 0x4C, 0x07, 0xF8, 0x07, 0x3C, ++0x01, 0x33, 0xDB, 0xB2, 0x98, 0x42, 0x22, 0xD0, 0x04, 0xAA, 0x02, 0xEB, 0x45, 0x01, 0x11, 0xF8, 0x08, 0x4C, 0x37, 0x68, ++0x56, 0xF8, 0x04, 0x1F, 0x7F, 0x1A, 0x77, 0x45, 0xE0, 0xDD, 0x80, 0x2C, 0xEE, 0xD0, 0x00, 0x9A, 0x52, 0xF8, 0x24, 0x10, ++0x49, 0x45, 0x4F, 0xEA, 0x45, 0x07, 0x04, 0xAA, 0x55, 0xDD, 0x02, 0xEB, 0x45, 0x01, 0x11, 0xF8, 0x07, 0x8C, 0x61, 0x46, ++0x0C, 0x44, 0xA0, 0x45, 0x61, 0xDB, 0x01, 0x33, 0xDB, 0xB2, 0x01, 0x35, 0x98, 0x42, 0xED, 0xB2, 0xDC, 0xD1, 0x02, 0x2D, ++0x00, 0x9A, 0x68, 0xD9, 0x9D, 0xF8, 0x08, 0x10, 0x80, 0x29, 0x3A, 0xD0, 0x9D, 0xF8, 0x09, 0x30, 0x52, 0xF8, 0x21, 0x40, ++0x52, 0xF8, 0x23, 0x50, 0x58, 0x1C, 0x40, 0x1A, 0x64, 0x1B, 0xC0, 0xB2, 0x02, 0xAD, 0x94, 0xFB, 0xF0, 0xF4, 0x01, 0x27, ++0xA4, 0xB2, 0x00, 0x26, 0x95, 0xF8, 0x02, 0xE0, 0xBE, 0xF1, 0x80, 0x0F, 0x5F, 0xFA, 0x87, 0xFC, 0x16, 0xD0, 0x95, 0xF8, ++0x03, 0x80, 0x52, 0xF8, 0x2E, 0x30, 0x08, 0xF1, 0x01, 0x01, 0xA1, 0xEB, 0x0E, 0x01, 0xC9, 0xB2, 0x52, 0xF8, 0x28, 0xE0, ++0x81, 0x42, 0xA3, 0xEB, 0x0E, 0x03, 0x93, 0xFB, 0xF1, 0xF3, 0x9B, 0xB2, 0x32, 0xD8, 0x61, 0xD0, 0x02, 0x2F, 0x05, 0xF1, ++0x02, 0x05, 0x34, 0xD1, 0x04, 0xAB, 0x03, 0xEB, 0x46, 0x06, 0x16, 0xF8, 0x08, 0x1C, 0x16, 0xF8, 0x07, 0x3C, 0x5B, 0x1A, ++0x01, 0x33, 0x01, 0xEB, 0x63, 0x03, 0xDB, 0xB2, 0x01, 0x93, 0x01, 0x9B, 0x52, 0xF8, 0x23, 0x00, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x02, 0xEB, 0x45, 0x08, 0x00, 0x9A, 0x18, 0xF8, 0x07, 0x8C, 0x52, 0xF8, 0x28, 0xB0, 0x25, 0x4A, 0x93, 0x45, ++0xA3, 0xDB, 0xB1, 0xF5, 0x7A, 0x7F, 0x02, 0xDA, 0x23, 0x4A, 0x93, 0x45, 0x9D, 0xDA, 0x02, 0x21, 0x0C, 0x44, 0xA0, 0x45, ++0x9D, 0xDA, 0x04, 0xAA, 0x17, 0x44, 0x07, 0xF8, 0x08, 0xAC, 0x07, 0xF8, 0x07, 0xAC, 0x75, 0xE7, 0x02, 0x2F, 0x1C, 0x46, ++0x08, 0x46, 0x66, 0x46, 0x05, 0xF1, 0x02, 0x05, 0xCA, 0xD0, 0x02, 0x27, 0xAA, 0xE7, 0x04, 0xAB, 0x03, 0xEB, 0x45, 0x01, ++0x6D, 0x00, 0x11, 0xF8, 0x08, 0x3C, 0x80, 0x2B, 0x8E, 0xD0, 0x52, 0xF8, 0x23, 0x00, 0x11, 0xF8, 0x07, 0x1C, 0x43, 0xF2, ++0xB0, 0x64, 0xA0, 0x42, 0x0A, 0xDC, 0x0F, 0x4E, 0x52, 0xF8, 0x21, 0x40, 0xB4, 0x42, 0x05, 0xDB, 0xB0, 0xF5, 0x7A, 0x7F, ++0x13, 0xDA, 0x14, 0xF5, 0x7A, 0x7F, 0x10, 0xDD, 0x9C, 0x44, 0x61, 0x45, 0xBF, 0xF6, 0x78, 0xAF, 0x04, 0xAB, 0x1D, 0x44, ++0x80, 0x23, 0x05, 0xF8, 0x08, 0x3C, 0x05, 0xF8, 0x07, 0x3C, 0x6F, 0xE7, 0xA3, 0x42, 0x9B, 0xD2, 0x1C, 0x46, 0x66, 0x46, ++0x98, 0xE7, 0x4F, 0xF0, 0x02, 0x0C, 0xEB, 0xE7, 0x50, 0xC9, 0xFF, 0xFF, 0x19, 0xFC, 0xFF, 0xFF, 0xD0, 0xED, 0x00, 0x7A, ++0x90, 0xED, 0x01, 0x7A, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, ++0x01, 0x6A, 0xB4, 0xEE, 0xE6, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x5E, 0xDA, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x08, 0xDD, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, 0x01, 0x6A, 0xB4, 0xEE, 0xE6, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x50, 0xD9, ++0xD0, 0xED, 0x02, 0x6A, 0xF4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0xD1, 0xED, 0x00, 0x5A, 0x91, 0xED, ++0x02, 0x6A, 0xF4, 0xEE, 0xC6, 0x5A, 0xF1, 0xEE, 0x10, 0xFA, 0x40, 0xDA, 0xF4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x32, 0xDC, 0xB4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0x91, 0xED, 0x01, 0x6A, 0xD1, 0xED, 0x02, 0x7A, ++0xB4, 0xEE, 0xE7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x2D, 0xDA, 0xB4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xDD, ++0x91, 0xED, 0x01, 0x7A, 0xD1, 0xED, 0x02, 0x7A, 0xB4, 0xEE, 0xE7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x1F, 0xD9, 0xD1, 0xED, ++0x00, 0x7A, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x1A, 0xDD, 0x91, 0xED, 0x01, 0x7A, 0xB5, 0xEE, 0xC0, 0x7A, ++0xF1, 0xEE, 0x10, 0xFA, 0x13, 0xDD, 0x91, 0xED, 0x02, 0x7A, 0xB5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x0C, 0xDD, ++0x01, 0x20, 0x70, 0x47, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, 0x02, 0x7A, 0xB4, 0xEE, 0xE7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, ++0xC3, 0xD8, 0x02, 0x20, 0x70, 0x47, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x01, 0xD4, 0x00, 0x20, 0x70, 0x47, ++0xD1, 0xED, 0x01, 0x7A, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0xF6, 0xD5, 0xD1, 0xED, 0x02, 0x7A, 0xF5, 0xEE, ++0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x4C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x28, 0x00, 0xF0, ++0xC7, 0x80, 0x2D, 0xE9, 0xF0, 0x47, 0x00, 0x22, 0xA1, 0xF1, 0x02, 0x08, 0x82, 0xB0, 0x44, 0x46, 0x17, 0x46, 0x94, 0x46, ++0x10, 0x46, 0x4F, 0xF0, 0x01, 0x0E, 0x02, 0xE0, 0x05, 0x2E, 0x11, 0xD0, 0x01, 0x32, 0x34, 0xF9, 0x02, 0x5F, 0x0E, 0xFA, ++0x02, 0xF3, 0x00, 0x2D, 0xD6, 0xB2, 0x43, 0xEA, 0x00, 0x03, 0xF3, 0xDA, 0x01, 0x2A, 0xD8, 0xB2, 0x40, 0xF2, 0x83, 0x80, ++0x01, 0x37, 0x05, 0x2E, 0xFF, 0xB2, 0xED, 0xD1, 0x04, 0x2F, 0x00, 0xF0, 0x81, 0x80, 0x02, 0x2F, 0x00, 0xF2, 0x81, 0x80, ++0xBC, 0xF1, 0x00, 0x0F, 0x0B, 0xD1, 0xB1, 0xF9, 0x02, 0x30, 0xB1, 0xF9, 0x00, 0x20, 0x03, 0xF1, 0x09, 0x04, 0x94, 0x42, ++0x02, 0xDB, 0x09, 0x3B, 0x9A, 0x42, 0x00, 0xDA, 0x4A, 0x80, 0xB1, 0xF9, 0x04, 0x20, 0xB1, 0xF9, 0x06, 0x30, 0x03, 0x24, ++0x40, 0xF2, 0x04, 0x55, 0x9A, 0x42, 0x8D, 0xF8, 0x01, 0x40, 0xAD, 0xF8, 0x02, 0x50, 0xC0, 0xF2, 0x8E, 0x80, 0xB1, 0xF9, ++0x08, 0x20, 0xB1, 0xF9, 0x0A, 0x30, 0x9A, 0x42, 0x25, 0x46, 0x4F, 0xF0, 0x06, 0x09, 0x4F, 0xF0, 0x04, 0x07, 0x4F, 0xF0, ++0x02, 0x04, 0x80, 0xF2, 0x8E, 0x80, 0x40, 0xF2, 0x05, 0x43, 0xAD, 0xF8, 0x02, 0x30, 0x4F, 0xF0, 0x05, 0x0E, 0x4F, 0xF0, ++0x08, 0x08, 0x04, 0x26, 0x0A, 0x22, 0xCB, 0x5F, 0x8F, 0x5E, 0xBB, 0x42, 0x07, 0xDA, 0xBA, 0x46, 0x72, 0x46, 0x8D, 0xF8, ++0x02, 0x40, 0x1F, 0x46, 0xA6, 0x46, 0x53, 0x46, 0x14, 0x46, 0x31, 0xF9, 0x09, 0x20, 0x31, 0xF9, 0x08, 0x80, 0x42, 0x45, ++0x05, 0xDA, 0x8D, 0xF8, 0x03, 0x50, 0x8D, 0xF8, 0x01, 0x60, 0x42, 0x46, 0x35, 0x46, 0x97, 0x42, 0x05, 0xDD, 0x8D, 0xF8, ++0x02, 0x50, 0x8D, 0xF8, 0x01, 0xE0, 0x3A, 0x46, 0x75, 0x46, 0x9D, 0xF8, 0x02, 0xE0, 0x9D, 0xF8, 0x01, 0x60, 0x31, 0xF9, ++0x1E, 0x70, 0x31, 0xF9, 0x16, 0x80, 0x07, 0x32, 0xFE, 0x1D, 0x93, 0x42, 0xD4, 0xBF, 0x04, 0x23, 0x00, 0x23, 0xB0, 0x45, ++0x9D, 0xF8, 0x03, 0x60, 0x31, 0xF9, 0x16, 0x20, 0x02, 0xF1, 0x07, 0x02, 0xD8, 0xBF, 0x43, 0xF0, 0x02, 0x03, 0xBA, 0x42, ++0xA8, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0x06, 0x2B, 0x4E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x4A, 0xA9, 0xA1, 0x9B, 0x93, 0x4A, ++0xB1, 0x00, 0x0C, 0xF1, 0x01, 0x0C, 0x5F, 0xFA, 0x8C, 0xFC, 0x69, 0xE7, 0xBC, 0xF1, 0x02, 0x0F, 0x78, 0xD0, 0x00, 0x23, ++0x1C, 0x46, 0x1A, 0x46, 0x40, 0xFA, 0x03, 0xF5, 0xEF, 0x07, 0x05, 0xD4, 0x31, 0xF8, 0x13, 0x50, 0x01, 0x34, 0x2A, 0x44, ++0xE4, 0xB2, 0x12, 0xB2, 0x01, 0x33, 0x06, 0x2B, 0xF2, 0xD1, 0x92, 0xFB, 0xF4, 0xF2, 0x00, 0x23, 0x40, 0xFA, 0x03, 0xF4, ++0xE6, 0x07, 0x48, 0xBF, 0x21, 0xF8, 0x13, 0x20, 0x01, 0x33, 0x06, 0x2B, 0xF6, 0xD1, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, ++0x8B, 0x1E, 0x80, 0x20, 0x0A, 0x31, 0x33, 0xF9, 0x02, 0x2F, 0x00, 0x2A, 0xB8, 0xBF, 0x18, 0x80, 0x99, 0x42, 0xF8, 0xD1, ++0x70, 0x47, 0xB1, 0xF9, 0x08, 0x20, 0xB1, 0xF9, 0x0A, 0x30, 0x02, 0x25, 0x9A, 0x42, 0x8D, 0xF8, 0x01, 0x50, 0x4F, 0xF0, ++0x04, 0x09, 0x4F, 0xF0, 0x06, 0x07, 0xFF, 0xF6, 0x72, 0xAF, 0x4F, 0xF0, 0x0A, 0x08, 0x08, 0x22, 0x4F, 0xF0, 0x04, 0x0E, ++0x75, 0xE7, 0xBC, 0xF1, 0x00, 0x0F, 0x69, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x02, 0x23, 0x40, 0xFA, 0x03, 0xF5, 0xED, 0x07, ++0x05, 0xD4, 0x31, 0xF8, 0x13, 0x50, 0x01, 0x34, 0x2A, 0x44, 0xE4, 0xB2, 0x12, 0xB2, 0x01, 0x33, 0x06, 0x2B, 0xF2, 0xD1, ++0x64, 0xB9, 0xC3, 0x07, 0x03, 0xD4, 0x0B, 0x88, 0x1A, 0x44, 0x12, 0xB2, 0x01, 0x24, 0x87, 0x07, 0x04, 0xD4, 0x4B, 0x88, ++0x01, 0x34, 0x13, 0x44, 0xE4, 0xB2, 0x1A, 0xB2, 0x00, 0x23, 0x92, 0xFB, 0xF4, 0xF4, 0x00, 0xE0, 0x01, 0x33, 0x40, 0xFA, ++0x03, 0xF2, 0xD6, 0x07, 0xDD, 0xB2, 0x03, 0xD5, 0x01, 0x2B, 0x14, 0xD9, 0x21, 0xF8, 0x13, 0x40, 0x05, 0x2D, 0xF3, 0xD1, ++0xBC, 0xF1, 0x01, 0x0F, 0xA9, 0xD1, 0xC2, 0x07, 0x0F, 0xD4, 0x83, 0x07, 0xA5, 0xD5, 0x0B, 0x88, 0x4B, 0x80, 0xA2, 0xE7, ++0x0A, 0x31, 0x80, 0x23, 0x28, 0xF8, 0x02, 0x3F, 0x88, 0x45, 0xFB, 0xD1, 0x9B, 0xE7, 0xBC, 0xF1, 0x02, 0x0F, 0xDF, 0xD1, ++0xE6, 0xE7, 0x4B, 0x88, 0x0B, 0x80, 0x94, 0xE7, 0x01, 0x22, 0x02, 0xFA, 0x0E, 0xF3, 0xB2, 0x40, 0x13, 0x43, 0x18, 0x43, ++0xC0, 0xB2, 0xB1, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x04, 0xF4, 0x20, 0x43, 0xC0, 0xB2, 0xAB, 0xE7, 0x01, 0x23, 0x03, 0xFA, ++0x06, 0xF6, 0x30, 0x43, 0xA3, 0x40, 0x18, 0x43, 0xC0, 0xB2, 0xA3, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x04, 0xF4, 0x20, 0x43, ++0xAB, 0x40, 0x18, 0x43, 0xC0, 0xB2, 0x9B, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x06, 0xF6, 0x30, 0x43, 0xC0, 0xB2, 0x95, 0xE7, ++0x40, 0xF0, 0x3C, 0x00, 0x92, 0xE7, 0x00, 0xBF, 0xF0, 0xB5, 0xD1, 0xED, 0x01, 0x6A, 0x91, 0xED, 0x00, 0x7A, 0x2D, 0xED, ++0x08, 0x8B, 0xF4, 0xEE, 0xC7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x83, 0xB0, 0x0C, 0x46, 0x07, 0x46, 0x15, 0x46, 0x1E, 0x46, ++0x05, 0xDC, 0xF0, 0xEE, 0x66, 0x7A, 0xF0, 0xEE, 0x47, 0x6A, 0xB0, 0xEE, 0x67, 0x7A, 0xD4, 0xED, 0x02, 0x7A, 0xF4, 0xEE, ++0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xDC, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x48, 0xBF, 0xB0, 0xEE, ++0x67, 0x7A, 0xF0, 0xEE, 0x66, 0x7A, 0x77, 0xEE, 0xC7, 0x7A, 0xB0, 0xEE, 0x08, 0xBA, 0xFC, 0xEE, 0xE7, 0x7A, 0x17, 0xEE, ++0x90, 0x3A, 0xB3, 0x70, 0xD4, 0xED, 0x00, 0x8A, 0x94, 0xED, 0x01, 0xAA, 0xD4, 0xED, 0x02, 0x9A, 0x6A, 0xEE, 0x0A, 0x7A, ++0x28, 0xEE, 0xA8, 0x6A, 0x69, 0xEE, 0xA9, 0xAA, 0x36, 0xEE, 0x27, 0x6A, 0x38, 0xEE, 0x8A, 0x7A, 0x76, 0xEE, 0x2A, 0xAA, ++0x37, 0xEE, 0x29, 0x9A, 0x2A, 0xEE, 0x8B, 0xBA, 0x69, 0xEE, 0x09, 0x7A, 0x3B, 0xEE, 0x67, 0xBA, 0xB5, 0xEE, 0xC0, 0xBA, ++0xF1, 0xEE, 0x10, 0xFA, 0x40, 0xF3, 0xD0, 0x80, 0x1B, 0xEE, 0x10, 0x0A, 0x33, 0xF0, 0x44, 0xF8, 0x6F, 0xA3, 0xD3, 0xE9, ++0x00, 0x23, 0x33, 0xF0, 0x09, 0xFB, 0x80, 0xB1, 0x9F, 0xED, 0x6E, 0xBA, 0x33, 0x78, 0x6E, 0x49, 0x43, 0xF0, 0x04, 0x03, ++0x33, 0x70, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0x73, 0xF8, 0xD4, 0xED, 0x00, 0x8A, 0x94, 0xED, 0x01, 0xAA, 0xD4, 0xED, ++0x02, 0x9A, 0x95, 0xED, 0x00, 0x4A, 0xD5, 0xED, 0x01, 0x4A, 0x95, 0xED, 0x02, 0x5A, 0xF7, 0xEE, 0x00, 0x7A, 0x87, 0xEE, ++0x8B, 0x6A, 0x0D, 0x2F, 0xF0, 0xEE, 0x08, 0x6A, 0x26, 0xEE, 0x49, 0x7A, 0x66, 0xEE, 0x26, 0x6A, 0x2A, 0xEE, 0x86, 0x6A, ++0x66, 0xEE, 0xA8, 0x7A, 0x66, 0xEE, 0x8A, 0x5A, 0x67, 0xEE, 0x28, 0x8A, 0x27, 0xEE, 0x0A, 0xAA, 0x77, 0xEE, 0x87, 0x7A, ++0x26, 0xEE, 0xA9, 0x8A, 0x78, 0xEE, 0x86, 0x8A, 0x67, 0xEE, 0x29, 0x9A, 0x75, 0xEE, 0x87, 0x5A, 0x3A, 0xEE, 0x06, 0xAA, ++0x38, 0xEE, 0x07, 0x8A, 0x67, 0xEE, 0x84, 0x7A, 0x68, 0xEE, 0x84, 0x8A, 0x79, 0xEE, 0x86, 0x9A, 0x25, 0xEE, 0xA4, 0x7A, ++0x2A, 0xEE, 0x24, 0xAA, 0x77, 0xEE, 0x87, 0x7A, 0x78, 0xEE, 0x8A, 0x8A, 0x28, 0xEE, 0x05, 0x8A, 0x69, 0xEE, 0x85, 0x9A, ++0x37, 0xEE, 0x88, 0x8A, 0x78, 0xEE, 0xA9, 0x8A, 0x2E, 0xD9, 0xF3, 0xEE, 0x04, 0x7A, 0xB4, 0xEE, 0xE7, 0x8A, 0xF1, 0xEE, ++0x10, 0xFA, 0x27, 0xD5, 0x33, 0x78, 0x44, 0x49, 0x43, 0xF0, 0x08, 0x03, 0x33, 0x70, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, ++0x1D, 0xF8, 0xB7, 0xEE, 0x00, 0x8A, 0xF0, 0xEE, 0x00, 0x6A, 0xB1, 0xEE, 0x68, 0x7A, 0xC7, 0xEE, 0x08, 0x7A, 0x9F, 0xED, ++0x3D, 0x7A, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x21, 0xDC, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x4E, 0xD4, 0xB6, 0xEE, 0x00, 0x7A, 0x77, 0xEE, 0x87, 0x7A, 0xFC, 0xEE, 0xE7, 0x7A, 0xCD, 0xED, 0x01, 0x7A, 0x9D, 0xF8, ++0x04, 0x30, 0x12, 0xE0, 0x18, 0xEE, 0x10, 0x0A, 0x32, 0xF0, 0xBA, 0xFF, 0x2A, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x33, 0xF0, ++0x7F, 0xFA, 0x00, 0x28, 0xCC, 0xD1, 0x68, 0xEE, 0x08, 0x6A, 0xF7, 0xEE, 0x00, 0x7A, 0x76, 0xEE, 0xA7, 0x6A, 0xD2, 0xE7, ++0xFF, 0x23, 0x73, 0x70, 0xD4, 0xED, 0x00, 0x7A, 0x94, 0xED, 0x01, 0x7A, 0xD4, 0xED, 0x02, 0x4A, 0x95, 0xED, 0x00, 0x5A, ++0xD5, 0xED, 0x01, 0x5A, 0x95, 0xED, 0x02, 0x6A, 0x68, 0xEE, 0x27, 0x7A, 0x28, 0xEE, 0x07, 0x7A, 0x77, 0xEE, 0xA8, 0x7A, ++0x37, 0xEE, 0x28, 0x7A, 0x28, 0xEE, 0x24, 0x8A, 0x77, 0xEE, 0xC5, 0x7A, 0x37, 0xEE, 0x65, 0x7A, 0x38, 0xEE, 0x28, 0x8A, ++0x27, 0xEE, 0x07, 0x7A, 0x38, 0xEE, 0x46, 0x8A, 0x67, 0xEE, 0xA7, 0x7A, 0x28, 0xEE, 0x08, 0x8A, 0x77, 0xEE, 0x87, 0x7A, ++0x37, 0xEE, 0x88, 0x8A, 0xC8, 0xEE, 0x26, 0x7A, 0xC6, 0xED, 0x01, 0x7A, 0x03, 0xB0, 0xBD, 0xEC, 0x08, 0x8B, 0xF0, 0xBD, ++0x00, 0x23, 0xCC, 0xE7, 0xF1, 0xEE, 0x4B, 0x7A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x72, 0xFF, 0x06, 0xA3, 0xD3, 0xE9, ++0x00, 0x23, 0x33, 0xF0, 0x37, 0xFA, 0x00, 0x28, 0x3F, 0xF4, 0x3D, 0xAF, 0x9F, 0xED, 0x08, 0xBA, 0x2A, 0xE7, 0x00, 0xBF, ++0xAF, 0xF3, 0x00, 0x80, 0xF1, 0x68, 0xE3, 0x88, 0xB5, 0xF8, 0xE4, 0x3E, 0x00, 0x50, 0xC3, 0x47, 0xD4, 0x79, 0x15, 0x00, ++0x00, 0x7A, 0x15, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xAC, 0xC5, 0x27, 0xB7, 0x2D, 0xE9, 0xF0, 0x47, 0x09, 0x29, 0x8E, 0xB0, ++0x88, 0x46, 0x1D, 0x46, 0x70, 0xD9, 0x03, 0x28, 0x6E, 0xD0, 0x4F, 0xF0, 0x86, 0x4A, 0x57, 0x1E, 0x00, 0x26, 0x0D, 0xF1, ++0x18, 0x09, 0x00, 0x22, 0x10, 0x46, 0xF1, 0xB2, 0xD3, 0xB2, 0x8B, 0x42, 0x19, 0xD0, 0x00, 0x2B, 0x00, 0xF0, 0xAF, 0x80, ++0xBB, 0x5C, 0x07, 0xEE, 0x90, 0x3A, 0x0E, 0xAB, 0xF8, 0xEE, 0x67, 0x7A, 0x03, 0xEB, 0x80, 0x03, 0x43, 0xED, 0x0E, 0x7A, ++0x84, 0x00, 0x55, 0xF8, 0x22, 0x30, 0x07, 0xEE, 0x90, 0x3A, 0x0E, 0xAB, 0xF8, 0xEE, 0xE7, 0x7A, 0x1C, 0x44, 0x01, 0x30, ++0xC0, 0xB2, 0x44, 0xED, 0x0B, 0x7A, 0x01, 0x32, 0x04, 0x2A, 0xDF, 0xD1, 0x00, 0x23, 0x03, 0xA9, 0x68, 0x46, 0x09, 0xF8, ++0x36, 0x30, 0xFF, 0xF7, 0x9F, 0xFC, 0x10, 0xF0, 0x0E, 0x0F, 0x09, 0xF8, 0x36, 0x00, 0x00, 0xF0, 0x95, 0x80, 0x01, 0x36, ++0x04, 0x2E, 0xCC, 0xD1, 0x07, 0xAD, 0x00, 0x24, 0x2A, 0x46, 0x23, 0x46, 0x80, 0x21, 0x12, 0xF8, 0x04, 0x0C, 0x00, 0x28, ++0x40, 0xF0, 0x82, 0x80, 0x0E, 0xA8, 0x80, 0x29, 0x00, 0xEB, 0xC1, 0x00, 0x00, 0xF0, 0x8A, 0x80, 0x92, 0xED, 0x00, 0x7A, ++0x50, 0xED, 0x07, 0x7A, 0xB4, 0xEE, 0x67, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x98, 0xBF, 0x19, 0x46, 0x01, 0x33, 0xDB, 0xB2, ++0x04, 0x2B, 0x02, 0xF1, 0x08, 0x02, 0xE4, 0xD1, 0x00, 0x2C, 0x00, 0xF0, 0x84, 0x80, 0x80, 0x29, 0x76, 0xD0, 0x0E, 0xAB, ++0x03, 0xEB, 0xC1, 0x00, 0x42, 0x46, 0x10, 0xF8, 0x1F, 0x4C, 0x10, 0xF8, 0x20, 0x3C, 0x55, 0x49, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x22, 0xFF, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x13, 0x78, 0xD5, 0xED, 0x00, 0x6A, 0x95, 0xED, ++0x01, 0x7A, 0xD5, 0xED, 0x02, 0x7A, 0x05, 0xEE, 0x90, 0x3A, 0x53, 0x78, 0x06, 0xEE, 0x10, 0x3A, 0xF8, 0xEE, 0x65, 0x5A, ++0xB8, 0xEE, 0x46, 0x6A, 0xF8, 0xEE, 0xE6, 0x6A, 0xB8, 0xEE, 0xC7, 0x7A, 0xF8, 0xEE, 0xE7, 0x7A, 0x4F, 0xF0, 0x86, 0x42, ++0x00, 0x23, 0xB8, 0xF1, 0x09, 0x0F, 0xCD, 0xED, 0x01, 0x5A, 0x8D, 0xED, 0x02, 0x6A, 0xCD, 0xED, 0x03, 0x6A, 0x8D, 0xED, ++0x04, 0x7A, 0xCD, 0xED, 0x05, 0x7A, 0x00, 0x92, 0x8D, 0xF8, 0x18, 0x30, 0x16, 0xD8, 0x06, 0xAB, 0x03, 0xAA, 0x69, 0x46, ++0x40, 0x46, 0xFF, 0xF7, 0x17, 0xFE, 0x9D, 0xF8, 0x18, 0x30, 0x13, 0xF0, 0x0E, 0x0F, 0x4C, 0xD1, 0x9D, 0xF8, 0x19, 0x40, ++0x35, 0x49, 0x42, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xE2, 0xFE, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, ++0x03, 0xA9, 0x68, 0x46, 0xFF, 0xF7, 0x1C, 0xFC, 0x10, 0xF0, 0x0E, 0x0F, 0x8D, 0xF8, 0x18, 0x00, 0x18, 0xBF, 0x03, 0x46, ++0x49, 0xD0, 0xC8, 0xF1, 0x09, 0x04, 0x64, 0x01, 0xE6, 0xE7, 0x0E, 0xAB, 0x03, 0xEB, 0x80, 0x03, 0x84, 0x00, 0x43, 0xF8, ++0x38, 0xAC, 0x54, 0xE7, 0x06, 0x07, 0x1B, 0xD4, 0x01, 0x28, 0x08, 0xBF, 0x01, 0x24, 0x87, 0xE7, 0x09, 0xEB, 0xC6, 0x03, ++0x03, 0xAA, 0x69, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xE3, 0xFD, 0x62, 0xE7, 0x19, 0x46, 0x7D, 0xE7, 0x00, 0x23, 0x15, 0xF8, ++0x04, 0x2C, 0x01, 0x2A, 0x17, 0xD0, 0x01, 0x33, 0xDB, 0xB2, 0x04, 0x2B, 0x05, 0xF1, 0x08, 0x05, 0xF5, 0xD1, 0x80, 0x29, ++0x7F, 0xF4, 0x7B, 0xAF, 0x17, 0x49, 0x42, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xA4, 0xFE, 0xC8, 0xF1, 0x09, 0x04, ++0x64, 0x01, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x80, 0x24, 0xB2, 0xE7, 0x0E, 0xAA, 0x80, 0x29, 0x02, 0xEB, ++0xC1, 0x02, 0x0A, 0xD0, 0x95, 0xED, 0x00, 0x7A, 0x52, 0xED, 0x07, 0x7A, 0xB4, 0xEE, 0x67, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x98, 0xBF, 0x19, 0x46, 0xD7, 0xE7, 0x19, 0x46, 0xD5, 0xE7, 0x06, 0xAB, 0x03, 0xAA, 0x69, 0x46, 0x40, 0x46, 0xFF, 0xF7, ++0xAB, 0xFD, 0x9D, 0xF8, 0x18, 0x30, 0x13, 0xF0, 0x0E, 0x0F, 0x93, 0xD0, 0xA9, 0xE7, 0x00, 0xBF, 0x14, 0x7A, 0x15, 0x00, ++0x30, 0x7A, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x9A, 0x4A, 0xDF, 0xF8, 0x8C, 0x82, 0x13, 0x68, 0x2D, 0xED, 0x08, 0x8B, ++0x23, 0xF4, 0xFF, 0x43, 0x43, 0xF4, 0xCE, 0x35, 0x8B, 0xB0, 0x43, 0xF4, 0x1D, 0x43, 0x0C, 0x46, 0x45, 0xF4, 0x80, 0x75, ++0x01, 0x46, 0x13, 0x60, 0x01, 0x20, 0x15, 0x60, 0x0D, 0x46, 0x03, 0x91, 0xFC, 0xF7, 0xBA, 0xFD, 0xA2, 0x7B, 0x8F, 0x48, ++0x02, 0xF0, 0x0F, 0x03, 0x01, 0x68, 0x12, 0x09, 0x9B, 0x02, 0x43, 0xEA, 0x82, 0x13, 0x21, 0xF4, 0x7F, 0x52, 0x13, 0x43, ++0x03, 0x60, 0x02, 0x20, 0xFC, 0xF7, 0xAA, 0xFD, 0xAB, 0x6B, 0xC3, 0xF3, 0x07, 0x22, 0x02, 0x92, 0x4F, 0xEA, 0x02, 0x4B, ++0xDA, 0xB2, 0x01, 0x92, 0x4F, 0xEA, 0x03, 0x6A, 0x4F, 0xF0, 0x00, 0x09, 0xDD, 0xE9, 0x01, 0x32, 0xB9, 0xF1, 0x00, 0x0F, ++0x18, 0xBF, 0x13, 0x46, 0xA3, 0xF1, 0x40, 0x02, 0x12, 0xB2, 0x40, 0x33, 0x5F, 0xFA, 0x89, 0xF1, 0x00, 0x2A, 0xAD, 0xF8, ++0x14, 0x20, 0xAD, 0xF8, 0x16, 0x30, 0x00, 0x91, 0xC0, 0xF2, 0xEA, 0x80, 0xFF, 0x2B, 0x01, 0xD9, 0x77, 0x4B, 0x05, 0x93, ++0x00, 0x25, 0x2E, 0x46, 0x05, 0x24, 0x48, 0xF2, 0x80, 0x07, 0xBD, 0xF9, 0x14, 0x30, 0x08, 0xA9, 0x06, 0xA8, 0xB9, 0xF1, ++0x00, 0x0F, 0x00, 0xF0, 0xC3, 0x80, 0x4A, 0xEA, 0x03, 0x43, 0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0xFF, 0xF7, 0xAE, 0xF8, ++0xBD, 0xF9, 0x16, 0x30, 0x4A, 0xEA, 0x03, 0x43, 0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0x09, 0xA9, 0x07, 0xA8, 0xFF, 0xF7, ++0xA3, 0xF8, 0xDD, 0xE9, 0x06, 0x02, 0xDD, 0xE9, 0x08, 0x13, 0x01, 0x3C, 0x12, 0x1A, 0x5B, 0x1A, 0x14, 0xF0, 0xFF, 0x04, ++0x16, 0x44, 0x1D, 0x44, 0xD9, 0xD1, 0x62, 0x4B, 0x83, 0xFB, 0x06, 0x12, 0xF6, 0x17, 0xC6, 0xEB, 0x62, 0x06, 0x07, 0xEE, ++0x90, 0x6A, 0x83, 0xFB, 0x05, 0x13, 0xED, 0x17, 0xC5, 0xEB, 0x63, 0x05, 0xB8, 0xEE, 0xE7, 0x7A, 0x07, 0xEE, 0x90, 0x5A, ++0xF8, 0xEE, 0xE7, 0x7A, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x9D, 0x80, 0x00, 0x9B, 0x01, 0x2B, 0x40, 0xF0, 0x9D, 0x80, ++0xC7, 0xEE, 0x27, 0x9A, 0x03, 0x9B, 0x54, 0x49, 0x54, 0x4F, 0x4F, 0xF4, 0x00, 0x50, 0x1E, 0x1F, 0x03, 0xF1, 0x3C, 0x08, ++0xB6, 0xEE, 0x00, 0xAA, 0x79, 0xEE, 0x88, 0x9A, 0xF7, 0xEE, 0x00, 0xAA, 0x69, 0xEE, 0x8A, 0x9A, 0x8A, 0xEE, 0xA9, 0x8A, ++0xFD, 0xEE, 0xC8, 0x8A, 0x18, 0xEE, 0x90, 0x2A, 0x20, 0xF0, 0xCA, 0xFD, 0xF8, 0xEE, 0xE8, 0x8A, 0xDF, 0xED, 0x49, 0x7A, ++0x49, 0x49, 0x38, 0xEE, 0x68, 0x8A, 0x4F, 0xF4, 0x00, 0x50, 0x28, 0xEE, 0x27, 0x8A, 0xFD, 0xEE, 0xC8, 0x7A, 0x17, 0xEE, ++0x90, 0x2A, 0x20, 0xF0, 0xB9, 0xFD, 0x69, 0xEE, 0xA9, 0x7A, 0x39, 0xEE, 0xAA, 0xBA, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, ++0x71, 0xFD, 0x40, 0x4B, 0x00, 0x22, 0x32, 0xF0, 0x0F, 0xFC, 0x7A, 0xEE, 0xE9, 0xAA, 0x04, 0x46, 0x0D, 0x46, 0x56, 0xF8, ++0x04, 0x3F, 0xC3, 0xF3, 0x07, 0x22, 0x08, 0xEE, 0x90, 0x2A, 0xDB, 0xB2, 0x08, 0xEE, 0x10, 0x3A, 0xF8, 0xEE, 0xE8, 0x8A, ++0xB8, 0xEE, 0xC8, 0x8A, 0x68, 0xEE, 0xAA, 0x8A, 0x28, 0xEE, 0x0B, 0x8A, 0x69, 0xEE, 0xA8, 0x7A, 0x78, 0xEE, 0x67, 0x7A, ++0x29, 0xEE, 0x88, 0x8A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x4E, 0xFD, 0x22, 0x46, 0x2B, 0x46, 0x32, 0xF0, 0xCC, 0xFE, ++0x33, 0xF0, 0x5A, 0xF8, 0x78, 0xEE, 0x28, 0x7A, 0x09, 0xEE, 0x10, 0x0A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x40, 0xFD, ++0x22, 0x46, 0x2B, 0x46, 0x32, 0xF0, 0xBE, 0xFE, 0x33, 0xF0, 0x4C, 0xF8, 0x07, 0xEE, 0x90, 0x0A, 0x77, 0xEE, 0x8A, 0x7A, ++0x39, 0xEE, 0x0A, 0x9A, 0xFD, 0xEE, 0xE7, 0x7A, 0xB0, 0x45, 0x17, 0xEE, 0x90, 0x3A, 0xFD, 0xEE, 0xC9, 0x7A, 0x4F, 0xEA, ++0x03, 0x23, 0xCD, 0xED, 0x00, 0x7A, 0x9D, 0xF8, 0x00, 0x20, 0x03, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x02, 0x03, 0x43, 0xEA, ++0x07, 0x03, 0x33, 0x60, 0xB5, 0xD1, 0x0B, 0xB0, 0xBD, 0xEC, 0x08, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0xEA, 0x03, 0x63, ++0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0x08, 0xA9, 0x06, 0xA8, 0xFE, 0xF7, 0xE9, 0xFF, 0xBD, 0xF9, 0x16, 0x30, 0x4B, 0xEA, ++0x03, 0x63, 0x3B, 0x43, 0x39, 0xE7, 0xF1, 0xEE, 0x67, 0x7A, 0x87, 0xEE, 0x87, 0x8A, 0x09, 0xF1, 0x01, 0x09, 0x01, 0xE7, ++0x4F, 0xF4, 0x00, 0x03, 0x05, 0x93, 0x15, 0xE7, 0x58, 0x40, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, 0x80, 0x00, 0xFF, 0x00, ++0x67, 0x66, 0x66, 0x66, 0x48, 0x7A, 0x15, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x7A, 0x44, 0x58, 0x7A, 0x15, 0x00, ++0x00, 0x00, 0xF0, 0x3F, 0x4C, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0xB5, 0x4C, 0x2D, 0xED, 0x04, 0x8B, 0x27, 0x68, ++0xAD, 0xF2, 0xE4, 0x7D, 0x06, 0x46, 0x0D, 0x46, 0x14, 0x46, 0xB2, 0x49, 0x0A, 0x94, 0x3A, 0x46, 0x4F, 0xF4, 0x00, 0x50, ++0x9A, 0x46, 0xCD, 0xE9, 0x13, 0x56, 0x20, 0xF0, 0x17, 0xFD, 0xAE, 0x4B, 0xAE, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x10, 0xFD, 0xAC, 0x4B, 0xAD, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x09, 0xFD, 0xAB, 0x4B, ++0xAB, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x02, 0xFD, 0xA9, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, ++0xFD, 0xFC, 0x16, 0xF0, 0x01, 0x03, 0x15, 0x93, 0x07, 0xD1, 0xA6, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x61, 0x43, 0xF4, ++0xC0, 0x53, 0x11, 0x60, 0x13, 0x60, 0x14, 0x9A, 0xC2, 0xF3, 0x40, 0x03, 0x03, 0x33, 0x12, 0xF0, 0x0C, 0x0F, 0x09, 0xEE, ++0x10, 0x3A, 0xC2, 0xF3, 0x81, 0x03, 0x00, 0xF0, 0x9C, 0x82, 0x01, 0x2B, 0x14, 0xBF, 0x0A, 0x23, 0x05, 0x23, 0x08, 0xEE, ++0x90, 0x3A, 0x9A, 0x4A, 0x9A, 0x4E, 0x14, 0x68, 0xDF, 0xF8, 0x7C, 0xE2, 0x99, 0x4B, 0x9A, 0x49, 0xDF, 0xF8, 0x78, 0x92, ++0xDF, 0xF8, 0x78, 0xB2, 0x98, 0x48, 0xDF, 0xF8, 0x78, 0xC2, 0x98, 0x4F, 0xDF, 0xF8, 0x74, 0x82, 0x24, 0xF0, 0x04, 0x04, ++0x14, 0x60, 0x35, 0x68, 0x00, 0x24, 0x25, 0xF4, 0x70, 0x45, 0x35, 0x60, 0xCE, 0xF8, 0x00, 0x40, 0x1D, 0x68, 0x45, 0xF0, ++0x80, 0x05, 0x1D, 0x60, 0x0D, 0x68, 0x45, 0xF0, 0x00, 0x45, 0x0D, 0x60, 0x15, 0x68, 0x01, 0x26, 0x45, 0xF0, 0x04, 0x05, ++0x15, 0x60, 0xCB, 0xF8, 0x00, 0x60, 0xC9, 0xF8, 0x00, 0x40, 0x15, 0x68, 0x25, 0xF0, 0x04, 0x05, 0x15, 0x60, 0x0D, 0x68, ++0x25, 0xF0, 0x00, 0x45, 0x0D, 0x60, 0x1D, 0x68, 0x25, 0xF0, 0x80, 0x05, 0x1D, 0x60, 0x15, 0x68, 0x45, 0xF0, 0x04, 0x05, ++0x15, 0x60, 0x82, 0x4D, 0x2A, 0x68, 0x42, 0xF0, 0x02, 0x02, 0x2A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x42, 0x22, 0xF0, ++0x04, 0x02, 0x42, 0xF4, 0x80, 0x42, 0x32, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x07, 0x22, 0x42, 0xF0, 0xC0, 0x62, ++0x42, 0xF4, 0x84, 0x72, 0x1A, 0x60, 0x0B, 0x68, 0x03, 0xF0, 0x00, 0x43, 0x43, 0xEA, 0x0A, 0x03, 0x0B, 0x60, 0x03, 0x68, ++0x43, 0xF0, 0x3F, 0x03, 0x03, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x0B, 0x94, 0x43, 0xF4, 0x00, 0x63, 0x38, 0xAA, 0x78, 0xA9, ++0x10, 0x92, 0x0F, 0x91, 0xCC, 0xF8, 0x00, 0x30, 0x0D, 0xF1, 0x7F, 0x03, 0xCD, 0xE9, 0x11, 0x21, 0x0D, 0x93, 0x08, 0xEE, ++0x10, 0x4A, 0x0D, 0xF1, 0xAF, 0x03, 0x81, 0x46, 0x0E, 0x93, 0x00, 0x23, 0x0C, 0x93, 0x9D, 0xF8, 0x30, 0x50, 0x18, 0xEE, ++0x10, 0x3A, 0x2B, 0x43, 0x09, 0x93, 0x00, 0x24, 0x3D, 0xE0, 0x0C, 0x9B, 0x00, 0x2B, 0x6C, 0xD0, 0x66, 0x00, 0x0D, 0x9B, ++0x26, 0x44, 0x48, 0xF2, 0x80, 0x0B, 0x13, 0xF8, 0x06, 0xA0, 0x0E, 0x9B, 0x9E, 0x5D, 0x4F, 0xEA, 0x0A, 0x63, 0x43, 0xEA, ++0x0A, 0x43, 0x43, 0xEA, 0x0B, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0x19, 0xA9, 0x18, 0xA8, 0xFE, 0xF7, 0xE3, 0xFE, 0xB2, 0x45, ++0x0A, 0xD0, 0x33, 0x06, 0x43, 0xEA, 0x06, 0x46, 0x46, 0xEA, 0x0B, 0x06, 0xC8, 0xF8, 0x00, 0x60, 0x19, 0xA9, 0x17, 0xA8, ++0xFE, 0xF7, 0xD6, 0xFE, 0x04, 0xEB, 0x84, 0x03, 0xB8, 0xAA, 0xDE, 0x00, 0x00, 0x21, 0x02, 0xEB, 0xC3, 0x03, 0x28, 0x46, ++0x18, 0x9A, 0xFF, 0xF7, 0x51, 0xF8, 0x0D, 0xF5, 0xAC, 0x63, 0x33, 0x44, 0x19, 0x9A, 0x01, 0x34, 0x00, 0x21, 0x28, 0x46, ++0xFF, 0xF7, 0x48, 0xF8, 0x10, 0x2C, 0xB8, 0xAE, 0x0D, 0xF5, 0xAC, 0x6B, 0x59, 0xD0, 0x3B, 0x68, 0x23, 0xF4, 0xFF, 0x43, ++0x43, 0xEA, 0x44, 0x23, 0x43, 0xF4, 0x01, 0x42, 0x43, 0xF4, 0xC0, 0x33, 0x43, 0xF4, 0x80, 0x73, 0x3A, 0x60, 0x01, 0x20, ++0x3B, 0x60, 0xFC, 0xF7, 0x71, 0xFB, 0x09, 0x9B, 0xE6, 0xB2, 0x00, 0x2B, 0x3D, 0xD0, 0x0A, 0x9B, 0xD9, 0xF8, 0x00, 0x10, ++0x1A, 0x5D, 0x02, 0xF0, 0x0F, 0x03, 0x9B, 0x02, 0x12, 0x09, 0x43, 0xEA, 0x82, 0x13, 0x21, 0xF4, 0x7F, 0x52, 0x13, 0x43, ++0xC9, 0xF8, 0x00, 0x30, 0x02, 0x20, 0xFC, 0xF7, 0x5B, 0xFB, 0x0B, 0x9B, 0x00, 0x2B, 0x98, 0xD1, 0x4F, 0xF0, 0x80, 0x33, ++0xC8, 0xF8, 0x00, 0x30, 0x19, 0xA9, 0x18, 0xA8, 0xFE, 0xF7, 0x8C, 0xFE, 0xB4, 0xE7, 0x10, 0x9B, 0x04, 0xEB, 0x44, 0x0B, ++0x03, 0xEB, 0x04, 0x12, 0x20, 0xAB, 0x18, 0xEE, 0x10, 0x0A, 0x5B, 0x44, 0x00, 0x92, 0x31, 0x46, 0x0D, 0xF1, 0x5A, 0x02, ++0xFE, 0xF7, 0xF2, 0xFF, 0x0F, 0x9B, 0x4F, 0xEA, 0x04, 0x1A, 0x0A, 0xEB, 0x03, 0x02, 0x2C, 0xAB, 0x31, 0x46, 0x00, 0x92, ++0x18, 0xEE, 0x10, 0x0A, 0x5B, 0x44, 0x0D, 0xF1, 0x5B, 0x02, 0x66, 0x00, 0xFE, 0xF7, 0xE2, 0xFF, 0x73, 0xE7, 0xFE, 0xF7, ++0xA7, 0xFE, 0x0A, 0x9B, 0x18, 0x55, 0x02, 0x20, 0xFC, 0xF7, 0x28, 0xFB, 0xCE, 0xE7, 0x0C, 0x9B, 0x18, 0xEE, 0x90, 0x2A, ++0x01, 0x33, 0x93, 0x42, 0x0C, 0x93, 0x7F, 0xF4, 0x58, 0xAF, 0x18, 0xEE, 0x90, 0xAA, 0x00, 0x25, 0x45, 0xE0, 0x00, 0xBF, ++0x10, 0x20, 0x34, 0x40, 0x60, 0x7A, 0x15, 0x00, 0x1C, 0x20, 0x34, 0x40, 0x74, 0x7A, 0x15, 0x00, 0x04, 0x22, 0x34, 0x40, ++0x88, 0x7A, 0x15, 0x00, 0x18, 0x00, 0x58, 0x40, 0x9C, 0x7A, 0x15, 0x00, 0xB0, 0x7A, 0x15, 0x00, 0x04, 0x40, 0x34, 0x40, ++0x30, 0x20, 0x34, 0x40, 0x60, 0x20, 0x34, 0x40, 0x5C, 0x20, 0x34, 0x40, 0x64, 0x20, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, ++0x58, 0x40, 0x34, 0x40, 0x80, 0x21, 0x34, 0x40, 0x68, 0x20, 0x34, 0x40, 0x0C, 0xB6, 0x33, 0x40, 0x08, 0xB6, 0x33, 0x40, ++0x20, 0x40, 0x34, 0x40, 0x4C, 0x40, 0x34, 0x40, 0x06, 0x2D, 0x34, 0xBF, 0x32, 0x21, 0x64, 0x21, 0x09, 0x91, 0xFE, 0xF7, ++0xDB, 0xFF, 0x11, 0x9B, 0x09, 0x99, 0x84, 0x46, 0x43, 0xF8, 0x04, 0xC0, 0x5A, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xD2, 0xFF, ++0x01, 0x35, 0x12, 0x9B, 0x10, 0x2D, 0x18, 0x51, 0x06, 0xF1, 0x28, 0x06, 0x0B, 0xF1, 0x28, 0x0B, 0x14, 0xD0, 0xBA, 0xF1, ++0x01, 0x0F, 0x32, 0x46, 0x4F, 0xEA, 0x05, 0x14, 0x50, 0x46, 0xDF, 0xD1, 0x11, 0x9B, 0x30, 0x68, 0x18, 0x51, 0x01, 0x35, ++0x12, 0x9B, 0xDB, 0xF8, 0x00, 0x10, 0x19, 0x51, 0x10, 0x2D, 0x06, 0xF1, 0x28, 0x06, 0x0B, 0xF1, 0x28, 0x0B, 0xEA, 0xD1, ++0x11, 0x9A, 0x0B, 0x9B, 0x04, 0x32, 0x11, 0x92, 0x12, 0x9A, 0x04, 0x32, 0x12, 0x92, 0x0D, 0x9A, 0x01, 0x32, 0x0D, 0x92, ++0x0E, 0x9A, 0x01, 0x32, 0x01, 0x33, 0x0E, 0x92, 0x19, 0xEE, 0x10, 0x2A, 0x0B, 0x93, 0xDB, 0xB2, 0x9A, 0x42, 0x08, 0xEE, ++0x10, 0x3A, 0x3F, 0xF6, 0xE0, 0xAE, 0x20, 0xAD, 0x2C, 0xAC, 0xAB, 0x46, 0x0B, 0x95, 0xDD, 0xF8, 0x40, 0x80, 0x0F, 0x9F, ++0x09, 0x94, 0x19, 0xEE, 0x10, 0x5A, 0xA2, 0x46, 0x00, 0x26, 0x09, 0xE0, 0x13, 0x9A, 0x42, 0xF8, 0x26, 0x30, 0x01, 0x36, ++0x0B, 0xF1, 0x03, 0x0B, 0x08, 0xF1, 0x10, 0x08, 0x0A, 0xF1, 0x03, 0x0A, 0x5F, 0xFA, 0x86, 0xF9, 0x49, 0x46, 0x43, 0x46, ++0x5A, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x98, 0xFB, 0x07, 0xEB, 0x06, 0x13, 0x04, 0x46, 0x52, 0x46, 0x49, 0x46, 0x28, 0x46, ++0xFF, 0xF7, 0x90, 0xFB, 0x03, 0x02, 0xE2, 0xB2, 0x03, 0xF4, 0x7F, 0x43, 0x13, 0x43, 0x43, 0xF0, 0x00, 0x43, 0x09, 0x2E, ++0x43, 0xF4, 0x00, 0x03, 0xDA, 0xD9, 0x1A, 0xAB, 0x03, 0xEB, 0x46, 0x02, 0x1D, 0xAB, 0x03, 0xEB, 0x46, 0x03, 0xB9, 0xF1, ++0x0F, 0x0F, 0x22, 0xF8, 0x14, 0x4C, 0x23, 0xF8, 0x14, 0x0C, 0xD0, 0xD1, 0x14, 0x9B, 0x09, 0x9C, 0x0B, 0x9D, 0xC3, 0xF3, ++0x40, 0x10, 0x1A, 0xA9, 0x09, 0x90, 0xFF, 0xF7, 0xD3, 0xF8, 0x09, 0x98, 0x1D, 0xA9, 0xFF, 0xF7, 0xCF, 0xF8, 0x13, 0x9B, ++0xDF, 0xF8, 0x98, 0xC1, 0x1D, 0xA8, 0x1A, 0xA9, 0x03, 0xF1, 0x24, 0x06, 0x03, 0xF1, 0x3C, 0x07, 0x30, 0xF9, 0x02, 0x3B, ++0x31, 0xF9, 0x02, 0x2B, 0x1B, 0x02, 0x03, 0xF4, 0x7F, 0x43, 0xD2, 0xB2, 0x13, 0x43, 0x43, 0xEA, 0x0C, 0x03, 0x46, 0xF8, ++0x04, 0x3F, 0xBE, 0x42, 0xF0, 0xD1, 0x10, 0x9B, 0xDF, 0xF8, 0x6C, 0x81, 0xDD, 0xF8, 0x3C, 0xA0, 0x03, 0xF5, 0x80, 0x77, ++0x00, 0x26, 0x99, 0x46, 0xD9, 0xF8, 0x0C, 0x20, 0xAB, 0x78, 0xD9, 0xF8, 0x08, 0xC0, 0x68, 0x78, 0xD9, 0xF8, 0x04, 0x10, ++0x06, 0x92, 0x15, 0xF8, 0x03, 0x2B, 0x05, 0x93, 0x59, 0xF8, 0x10, 0x3B, 0x00, 0x93, 0xCD, 0xE9, 0x03, 0x0C, 0xCD, 0xE9, ++0x01, 0x21, 0x80, 0x23, 0x32, 0x46, 0x41, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xC6, 0xFA, 0xDA, 0xF8, 0x0C, 0x20, ++0xA3, 0x78, 0x60, 0x78, 0xDA, 0xF8, 0x04, 0x10, 0xDA, 0xF8, 0x08, 0xC0, 0x06, 0x92, 0x14, 0xF8, 0x03, 0x2B, 0x05, 0x93, ++0x5A, 0xF8, 0x10, 0x3B, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x21, 0xCD, 0xE9, 0x03, 0x0C, 0x32, 0x46, 0x36, 0x49, 0x80, 0x23, ++0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xAC, 0xFA, 0x4F, 0x45, 0x06, 0xF1, 0x01, 0x06, 0xC7, 0xD1, 0x13, 0x9B, 0x32, 0x4E, ++0x1D, 0x1F, 0x00, 0x24, 0x55, 0xF8, 0x04, 0x3F, 0xC3, 0xF3, 0x07, 0x22, 0x00, 0x92, 0xDB, 0xB2, 0x22, 0x46, 0x31, 0x46, ++0x01, 0x34, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x97, 0xFA, 0x10, 0x2C, 0xF0, 0xD1, 0x14, 0x9B, 0xDB, 0x06, 0x0D, 0xD5, ++0x15, 0x9B, 0x3B, 0xB1, 0x27, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x61, 0x43, 0xF4, 0xC0, 0x53, 0x11, 0x60, 0x13, 0x60, ++0x0A, 0x99, 0x13, 0x98, 0xFF, 0xF7, 0x0C, 0xFC, 0x22, 0x49, 0x23, 0x4A, 0x0B, 0x68, 0x23, 0x4E, 0x23, 0x4C, 0x24, 0x48, ++0x23, 0xF0, 0x02, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xEE, 0x43, 0x23, 0xF0, 0x09, 0x03, 0x43, 0xF4, 0x58, 0x53, ++0xA1, 0xF5, 0xD6, 0x41, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x74, 0x39, 0x02, 0xF5, 0xFF, 0x52, 0x1C, 0x32, 0x00, 0x23, ++0x4F, 0xF0, 0x80, 0x35, 0x33, 0x60, 0x25, 0x60, 0x03, 0x60, 0x0B, 0x60, 0x13, 0x68, 0x17, 0x49, 0x23, 0xF4, 0x7F, 0x43, ++0x00, 0xF5, 0x09, 0x40, 0x23, 0xF0, 0x80, 0x03, 0xFC, 0x30, 0x43, 0xF4, 0x80, 0x34, 0x13, 0x60, 0x14, 0x60, 0x03, 0x68, ++0x23, 0xF4, 0xC0, 0x53, 0x03, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x4F, 0xFA, 0x0D, 0xF2, 0xE4, 0x7D, 0xBD, 0xEC, ++0x04, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x23, 0x08, 0xEE, 0x90, 0x3A, 0x65, 0xE5, 0x00, 0xBF, 0xF0, 0x7A, 0x15, 0x00, ++0x1C, 0x7B, 0x15, 0x00, 0x04, 0x40, 0x34, 0x40, 0x80, 0x21, 0x34, 0x40, 0x5C, 0x20, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, ++0x4C, 0x40, 0x34, 0x40, 0x08, 0xB6, 0x33, 0x40, 0x3C, 0x7B, 0x15, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC4, 0x7A, 0x15, 0x00, ++0xF0, 0xB5, 0x07, 0x78, 0x43, 0x68, 0x83, 0xB0, 0x0E, 0x46, 0x3A, 0x46, 0x27, 0x49, 0x01, 0x93, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x22, 0xFA, 0x01, 0x9B, 0x30, 0x1F, 0x06, 0xF1, 0x3C, 0x01, 0x4F, 0xF0, 0x80, 0x32, 0x40, 0xF8, 0x04, 0x2F, ++0x88, 0x42, 0xFB, 0xD1, 0x06, 0xF1, 0x3F, 0x00, 0x06, 0xF1, 0x4F, 0x02, 0x00, 0x24, 0x00, 0xF8, 0x01, 0x4F, 0x82, 0x42, ++0xFB, 0xD1, 0x30, 0x46, 0x34, 0x65, 0x06, 0xF1, 0x94, 0x05, 0x40, 0xF8, 0x54, 0x4F, 0x00, 0x24, 0x40, 0xF8, 0x04, 0x4F, ++0xA8, 0x42, 0xFB, 0xD1, 0xBA, 0x09, 0x18, 0xD0, 0x15, 0x4C, 0xDF, 0xF8, 0x74, 0xC0, 0x21, 0x68, 0x14, 0x4D, 0x15, 0x4A, ++0x15, 0x48, 0x21, 0xF4, 0x00, 0x11, 0x21, 0x60, 0xF9, 0x09, 0x00, 0x29, 0x08, 0xBF, 0x62, 0x46, 0x2A, 0x60, 0x05, 0x68, ++0x11, 0x49, 0x12, 0x4C, 0x12, 0x4A, 0x01, 0xEA, 0x05, 0x01, 0x08, 0xBF, 0x22, 0x46, 0x0A, 0x43, 0x02, 0x60, 0x01, 0x93, ++0xFE, 0xF7, 0x08, 0xFC, 0x0E, 0x4A, 0x01, 0x9B, 0xD2, 0xF8, 0xBC, 0x44, 0x38, 0x46, 0x06, 0xF1, 0x40, 0x02, 0x31, 0x46, ++0xA0, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFE, 0xF7, 0x44, 0xBC, 0x50, 0x7B, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, ++0x10, 0x20, 0x34, 0x40, 0x76, 0x62, 0xF7, 0x0B, 0x1C, 0x20, 0x34, 0x40, 0xFF, 0x0F, 0x00, 0xE0, 0x00, 0x50, 0x98, 0x00, ++0x00, 0x90, 0x9B, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x76, 0x62, 0xB7, 0x0B, 0x17, 0x4B, 0x01, 0x22, 0x30, 0xB4, 0x1A, 0x60, ++0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0x08, 0xDB, ++0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x00, 0x2B, 0xF6, 0xDA, 0x0E, 0x4A, ++0x0C, 0x4B, 0x15, 0x68, 0x1C, 0x68, 0xC5, 0xF3, 0x10, 0x02, 0xED, 0x03, 0x44, 0xBF, 0x6F, 0xEA, 0x02, 0x42, 0x6F, 0xEA, ++0x12, 0x42, 0xC4, 0xF3, 0x10, 0x03, 0x02, 0x60, 0xE2, 0x03, 0x44, 0xBF, 0x6F, 0xEA, 0x03, 0x43, 0x6F, 0xEA, 0x13, 0x43, ++0x30, 0xBC, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x6C, 0x08, 0x62, 0x40, 0x90, 0x08, 0x62, 0x40, 0x8C, 0x08, 0x62, 0x40, ++0x30, 0xB4, 0x11, 0x4C, 0x11, 0x4D, 0x12, 0x4B, 0x04, 0xEA, 0x02, 0x42, 0xC1, 0xF3, 0x0E, 0x01, 0x0A, 0x43, 0x2A, 0x60, ++0x1A, 0x68, 0x00, 0xF0, 0x07, 0x00, 0x22, 0xF0, 0xE0, 0x62, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x00, 0x42, ++0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x1A, 0x68, ++0x22, 0xF0, 0x00, 0x42, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0xFF, 0x7F, 0x44, 0x05, 0x62, 0x40, ++0x28, 0x05, 0x62, 0x40, 0x38, 0xB5, 0x28, 0x4C, 0x28, 0x4A, 0x23, 0x68, 0x28, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x43, ++0x43, 0xF0, 0x80, 0x03, 0x23, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x03, 0x02, ++0x42, 0xF0, 0x02, 0x03, 0x0B, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x1D, 0x4B, ++0x42, 0xF0, 0x03, 0x02, 0x1A, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x19, 0x4A, ++0x13, 0x68, 0x98, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, ++0x98, 0x07, 0xF6, 0xD5, 0x13, 0x4C, 0x22, 0x68, 0x51, 0x00, 0x0E, 0xD4, 0x12, 0x4D, 0x29, 0x46, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x28, 0xF9, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x22, 0x68, 0x53, 0x00, ++0xF1, 0xD5, 0x0C, 0x4A, 0x0C, 0x49, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x03, 0x13, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0xBD, 0xE8, ++0x38, 0x40, 0x20, 0xF0, 0x13, 0xB9, 0x00, 0xBF, 0x08, 0x01, 0x60, 0x40, 0x08, 0x05, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, ++0x80, 0x40, 0x34, 0x40, 0x04, 0x22, 0x34, 0x40, 0x68, 0x7B, 0x15, 0x00, 0x04, 0x00, 0x62, 0x40, 0x7C, 0x7B, 0x15, 0x00, ++0x10, 0xB5, 0x0F, 0x4C, 0x0F, 0x4A, 0x23, 0x68, 0x0F, 0x48, 0x10, 0x49, 0x23, 0xF4, 0x80, 0x03, 0x23, 0x60, 0x13, 0x68, ++0x23, 0xF0, 0x03, 0x03, 0x13, 0x60, 0x13, 0x60, 0x03, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, ++0x01, 0x03, 0x0B, 0x60, 0x14, 0x20, 0xFC, 0xF7, 0x45, 0xF8, 0xBD, 0xE8, 0x10, 0x40, 0x06, 0x49, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0xE2, 0xB8, 0x04, 0x00, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, 0x08, 0x01, 0x60, 0x40, 0x08, 0x05, 0x62, 0x40, ++0x88, 0x7B, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0x07, 0x46, 0x10, 0x1A, 0x0E, 0x46, 0x9B, 0x46, 0xDD, 0xE9, ++0x0E, 0x54, 0x9D, 0xF8, 0x30, 0x90, 0x9D, 0xF8, 0x34, 0x80, 0x32, 0xF0, 0x65, 0xFD, 0x82, 0x46, 0xAB, 0xEB, 0x06, 0x00, ++0x32, 0xF0, 0x60, 0xFD, 0xBA, 0xF1, 0x00, 0x0F, 0x11, 0xD0, 0x07, 0xFA, 0x09, 0xF7, 0x07, 0xEE, 0x90, 0x7A, 0xB8, 0xEE, ++0xE7, 0x7A, 0x07, 0xEE, 0x90, 0xAA, 0xF8, 0xEE, 0xE7, 0x7A, 0xC7, 0xEE, 0x27, 0x6A, 0xFD, 0xEE, 0xE6, 0x7A, 0xCD, 0xED, ++0x01, 0x7A, 0x9D, 0xF9, 0x04, 0xA0, 0x85, 0xF8, 0x00, 0xA0, 0xA8, 0xB1, 0x06, 0xFA, 0x08, 0xF6, 0x07, 0xEE, 0x90, 0x6A, ++0xB8, 0xEE, 0xE7, 0x7A, 0x07, 0xEE, 0x90, 0x0A, 0xF8, 0xEE, 0xE7, 0x7A, 0xC7, 0xEE, 0x27, 0x6A, 0xFD, 0xEE, 0xE6, 0x7A, ++0xCD, 0xED, 0x01, 0x7A, 0x9D, 0xF9, 0x04, 0x30, 0x23, 0x70, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x03, 0x46, 0x23, 0x70, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0xA1, 0x4F, 0xA2, 0x4C, 0x3D, 0x68, 0xA2, 0x4E, ++0xAD, 0xB2, 0x25, 0x43, 0x2D, 0xED, 0x02, 0x8B, 0x3D, 0x60, 0x35, 0x68, 0x91, 0xB0, 0x25, 0xF0, 0x01, 0x05, 0x86, 0x46, ++0x35, 0x60, 0x8C, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x9B, 0x49, 0xCD, 0xF8, 0x1C, 0xE0, 0xCD, 0xE9, 0x08, 0x23, 0x08, 0xEE, ++0x10, 0xCA, 0x75, 0x46, 0x20, 0xF0, 0x72, 0xF8, 0x3B, 0x68, 0x9B, 0xB2, 0x23, 0x43, 0x3B, 0x60, 0x00, 0x2D, 0x00, 0xF0, ++0x16, 0x81, 0x00, 0x26, 0x34, 0x46, 0x35, 0x46, 0x0D, 0xF1, 0x34, 0x0B, 0x0D, 0xF1, 0x30, 0x0A, 0x32, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x96, 0xFE, 0xDD, 0xE9, 0x0C, 0x32, ++0x8A, 0x49, 0xCD, 0xE9, 0x00, 0x32, 0x4F, 0xF4, 0x00, 0x50, 0x23, 0x46, 0x2A, 0x46, 0x20, 0xF0, 0x4F, 0xF8, 0x0C, 0x9B, ++0x00, 0x2B, 0xC0, 0xF2, 0xA5, 0x80, 0x00, 0x2E, 0x00, 0xF0, 0xB9, 0x80, 0x01, 0x2E, 0x00, 0xF0, 0xDD, 0x80, 0x0D, 0x9B, ++0x15, 0xF1, 0x7C, 0x0F, 0xAC, 0xBF, 0x2A, 0x1F, 0x2A, 0x1D, 0x00, 0x2B, 0x80, 0xF2, 0xA1, 0x80, 0x01, 0x2E, 0x4F, 0xF0, ++0x02, 0x08, 0x00, 0xF0, 0xDA, 0x80, 0x7B, 0x2C, 0x00, 0xF3, 0xA1, 0x80, 0x23, 0x1D, 0x4F, 0xF0, 0x02, 0x09, 0xA3, 0xF1, ++0x80, 0x01, 0x38, 0x68, 0xC9, 0xB2, 0x09, 0x04, 0xA2, 0xF1, 0x80, 0x0C, 0x41, 0xEA, 0x0C, 0x61, 0x80, 0xB2, 0x01, 0x43, ++0x39, 0x60, 0x32, 0x21, 0x00, 0xBF, 0x01, 0x39, 0x89, 0xB2, 0x00, 0x29, 0xFA, 0xD1, 0x0F, 0xA9, 0x0E, 0xA8, 0xCD, 0xE9, ++0x05, 0x23, 0xFF, 0xF7, 0x55, 0xFE, 0xDD, 0xE9, 0x0E, 0x10, 0xDD, 0xE9, 0x05, 0x23, 0x01, 0x90, 0x00, 0x91, 0x4F, 0xF4, ++0x00, 0x50, 0x68, 0x49, 0x20, 0xF0, 0x0E, 0xF8, 0x0D, 0xF1, 0x2F, 0x03, 0x03, 0x93, 0x0D, 0xF1, 0x2E, 0x03, 0xCD, 0xE9, ++0x01, 0x93, 0xDD, 0xE9, 0x0C, 0x01, 0xDD, 0xE9, 0x0E, 0x23, 0xCD, 0xF8, 0x00, 0x80, 0xFF, 0xF7, 0x27, 0xFF, 0x9D, 0xF9, ++0x2F, 0x30, 0x9D, 0xF9, 0x2E, 0x20, 0x5E, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, 0xF6, 0xFF, 0x9D, 0xF9, 0x2F, 0x30, ++0x9D, 0xF9, 0x2E, 0x20, 0x39, 0x68, 0xE4, 0x1A, 0x6F, 0xF0, 0x7F, 0x03, 0x9C, 0x42, 0xB8, 0xBF, 0x1C, 0x46, 0xAD, 0x1A, ++0x7F, 0x2C, 0xA8, 0xBF, 0x7F, 0x24, 0x9D, 0x42, 0xB8, 0xBF, 0x1D, 0x46, 0x04, 0xEB, 0x03, 0x08, 0x7F, 0x2D, 0xA8, 0xBF, ++0x7F, 0x25, 0x5F, 0xFA, 0x88, 0xF8, 0xA5, 0xF1, 0x80, 0x02, 0x4F, 0xEA, 0x08, 0x43, 0x43, 0xEA, 0x02, 0x63, 0x89, 0xB2, ++0x0B, 0x43, 0x01, 0x36, 0x3B, 0x60, 0x07, 0x9B, 0xF6, 0xB2, 0xB3, 0x42, 0x5F, 0xFA, 0x82, 0xF9, 0x7F, 0xF4, 0x68, 0xAF, ++0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0xFE, 0xFD, ++0xDD, 0xE9, 0x0C, 0x13, 0x2A, 0x46, 0x01, 0x93, 0x00, 0x91, 0x23, 0x46, 0x3F, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, ++0xB7, 0xFF, 0x08, 0x9B, 0x83, 0xF8, 0x00, 0x90, 0x09, 0x9B, 0xDD, 0xE9, 0x0C, 0x12, 0x18, 0xEE, 0x10, 0x0A, 0x83, 0xF8, ++0x00, 0x80, 0xFF, 0xF7, 0x1D, 0xFE, 0x11, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0xB3, 0x01, 0x2E, ++0x29, 0xD0, 0x0D, 0x9B, 0x7B, 0x2D, 0xD4, 0xBF, 0x2A, 0x1D, 0x2A, 0x1F, 0x00, 0x2B, 0xFF, 0xF6, 0x5F, 0xAF, 0x01, 0x2E, ++0x4F, 0xF0, 0x02, 0x08, 0x26, 0xD0, 0x14, 0xF1, 0x7C, 0x0F, 0xFF, 0xF6, 0x5F, 0xAF, 0x23, 0x1F, 0x4F, 0xF0, 0x02, 0x09, ++0x5D, 0xE7, 0x0D, 0x9B, 0x00, 0x2B, 0xA5, 0xF1, 0x20, 0x02, 0x0A, 0xDA, 0x4F, 0xF0, 0x05, 0x08, 0xC1, 0x46, 0x04, 0xF1, ++0x20, 0x03, 0x52, 0xE7, 0x0D, 0x9B, 0x00, 0x2B, 0x05, 0xF1, 0x20, 0x02, 0xF4, 0xDB, 0x4F, 0xF0, 0x05, 0x08, 0xC1, 0x46, ++0xA4, 0xF1, 0x20, 0x03, 0x47, 0xE7, 0x6F, 0x2D, 0xD3, 0xDC, 0x0D, 0x9B, 0x00, 0x2B, 0x05, 0xF1, 0x10, 0x02, 0x4F, 0xF0, ++0x04, 0x08, 0x12, 0xDB, 0x14, 0xF1, 0x70, 0x0F, 0xD5, 0xDB, 0xA4, 0xF1, 0x10, 0x03, 0x4F, 0xF0, 0x04, 0x09, 0x36, 0xE7, ++0x15, 0xF1, 0x70, 0x0F, 0xFF, 0xF6, 0x1F, 0xAF, 0x0D, 0x9B, 0x00, 0x2B, 0xA5, 0xF1, 0x10, 0x02, 0x4F, 0xF0, 0x04, 0x08, ++0xEC, 0xDA, 0x6F, 0x2C, 0x3F, 0xF7, 0x23, 0xAF, 0x04, 0xF1, 0x10, 0x03, 0x4F, 0xF0, 0x04, 0x09, 0x23, 0xE7, 0x07, 0x9C, ++0x4F, 0xF0, 0x80, 0x08, 0x25, 0x46, 0xC1, 0x46, 0x0D, 0xF1, 0x34, 0x0B, 0x0D, 0xF1, 0x30, 0x0A, 0x7E, 0xE7, 0x00, 0xBF, ++0x4C, 0x40, 0x34, 0x40, 0x00, 0x00, 0x80, 0x80, 0x1C, 0x40, 0x34, 0x40, 0x94, 0x7B, 0x15, 0x00, 0xA8, 0x7B, 0x15, 0x00, ++0xCC, 0x7B, 0x15, 0x00, 0xF0, 0x7B, 0x15, 0x00, 0x0C, 0x7C, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x22, 0x4B, 0x23, 0x4E, ++0x1A, 0x68, 0x00, 0x25, 0x22, 0xF4, 0x7F, 0x52, 0x1A, 0x60, 0x98, 0x46, 0x2F, 0x46, 0x4F, 0xF0, 0x07, 0x09, 0x02, 0x20, ++0xFB, 0xF7, 0x86, 0xFE, 0x33, 0x68, 0xD8, 0xF8, 0x00, 0x40, 0xDA, 0x05, 0x54, 0xBF, 0x01, 0x37, 0x07, 0xF1, 0xFF, 0x37, ++0x7F, 0xB2, 0x1B, 0x06, 0x54, 0xBF, 0x01, 0x35, 0x05, 0xF1, 0xFF, 0x35, 0x00, 0x2F, 0x24, 0xF4, 0x7F, 0x54, 0xDC, 0xBF, ++0x7B, 0x42, 0x44, 0xEA, 0x83, 0x24, 0x6D, 0xB2, 0xD4, 0xBF, 0x44, 0xF4, 0x00, 0x54, 0x44, 0xEA, 0x87, 0x24, 0x00, 0x2D, ++0xDC, 0xBF, 0x6B, 0x42, 0x44, 0xEA, 0x83, 0x14, 0x09, 0xF1, 0xFF, 0x33, 0xCC, 0xBF, 0x44, 0xEA, 0x85, 0x14, 0x44, 0xF4, ++0x00, 0x74, 0x13, 0xF0, 0xFF, 0x09, 0xC8, 0xF8, 0x00, 0x40, 0xD0, 0xD1, 0x07, 0x49, 0x2B, 0x46, 0x3A, 0x46, 0x4F, 0xF4, ++0x00, 0x50, 0x1F, 0xF0, 0xF7, 0xFE, 0xC4, 0xF3, 0x87, 0x10, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x50, 0x40, 0x34, 0x40, ++0x14, 0x40, 0x34, 0x40, 0x34, 0x7C, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x4E, 0x4A, 0x4F, 0x4D, 0x13, 0x68, 0x87, 0xB0, ++0xC1, 0xF3, 0x03, 0x24, 0x03, 0x93, 0x23, 0xF0, 0x00, 0x43, 0x23, 0xF4, 0xE0, 0x03, 0x43, 0xEA, 0x04, 0x53, 0x43, 0xF0, ++0x0A, 0x03, 0x13, 0x60, 0x2C, 0x68, 0x48, 0x4B, 0x24, 0xF4, 0xC0, 0x54, 0xC1, 0xF3, 0x01, 0x62, 0x22, 0x43, 0x2A, 0x60, ++0x1A, 0x68, 0x01, 0xF0, 0x0F, 0x04, 0xC1, 0xF3, 0x03, 0x15, 0x42, 0xF0, 0x3F, 0x02, 0xA5, 0x42, 0x02, 0x94, 0xC1, 0xF3, ++0x03, 0x3A, 0x1A, 0x60, 0x5E, 0xD8, 0xDF, 0xF8, 0x04, 0x81, 0x3E, 0x4E, 0xDF, 0xF8, 0x00, 0xB1, 0x44, 0x19, 0x99, 0x46, ++0xEF, 0xB2, 0xD8, 0xF8, 0x00, 0x20, 0x22, 0xF4, 0xFF, 0x42, 0x42, 0xEA, 0x45, 0x22, 0x42, 0xF4, 0x40, 0x40, 0x42, 0xF4, ++0xE0, 0x31, 0xC8, 0xF8, 0x00, 0x00, 0x2A, 0x46, 0xC8, 0xF8, 0x00, 0x10, 0x4F, 0xF4, 0x00, 0x50, 0x33, 0x49, 0x1F, 0xF0, ++0xA9, 0xFE, 0x32, 0x68, 0x42, 0xF4, 0x80, 0x62, 0x32, 0x60, 0xDB, 0xF8, 0x00, 0x20, 0x42, 0xF0, 0x40, 0x02, 0xCB, 0xF8, ++0x00, 0x20, 0x32, 0x22, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0xFF, 0xF7, 0x5D, 0xFF, 0x04, 0xF8, ++0x01, 0x0B, 0x32, 0x68, 0x22, 0xF4, 0x80, 0x62, 0x32, 0x60, 0xD9, 0xF8, 0x00, 0x20, 0x22, 0xF0, 0x40, 0x02, 0xC9, 0xF8, ++0x00, 0x20, 0x32, 0x22, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0x0D, 0xF1, 0x17, 0x03, 0x01, 0x93, ++0x0D, 0xF1, 0x16, 0x03, 0x39, 0x46, 0x00, 0x93, 0x05, 0xAA, 0x0D, 0xF1, 0x15, 0x03, 0x50, 0x46, 0xFF, 0xF7, 0xE8, 0xFD, ++0x01, 0x35, 0x02, 0x9B, 0x9D, 0xF8, 0x16, 0xC0, 0x9D, 0xF8, 0x17, 0x00, 0x9D, 0xF8, 0x14, 0x10, 0x9D, 0xF8, 0x15, 0x20, ++0x84, 0xF8, 0x04, 0xC0, 0xEF, 0xB2, 0xBB, 0x42, 0x60, 0x72, 0xA1, 0x73, 0xE2, 0x74, 0xA8, 0xD2, 0x11, 0x4A, 0x0D, 0x48, ++0x13, 0x68, 0x0D, 0x49, 0x0A, 0x4C, 0x23, 0xF4, 0x7F, 0x43, 0x23, 0xF0, 0x80, 0x03, 0x13, 0x60, 0x43, 0xF4, 0x80, 0x33, ++0x13, 0x60, 0x03, 0x68, 0x23, 0xF4, 0xC0, 0x53, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x3F, 0x03, 0x0B, 0x60, 0x03, 0x9B, ++0x23, 0x60, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1C, 0x05, 0x62, 0x40, 0x04, 0x40, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, ++0x14, 0x40, 0x34, 0x40, 0x54, 0x7C, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, 0x5C, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, ++0x3C, 0x4D, 0x3D, 0x49, 0x81, 0x46, 0x89, 0xB0, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, 0x34, 0xFE, 0x2B, 0x68, 0xD9, 0xF8, ++0x00, 0x40, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE2, 0xB2, 0x04, 0xF0, 0x7F, 0x0A, 0xC4, 0xF3, 0x03, 0x18, 0x04, 0xF0, ++0x0F, 0x04, 0x4A, 0xDB, 0x33, 0x4D, 0x34, 0x4F, 0x2E, 0x68, 0x2B, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x2B, 0x60, 0xD7, 0xF8, ++0x00, 0xB0, 0x3B, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x3B, 0x60, 0x50, 0x46, 0xFF, 0xF7, 0xB2, 0xFC, 0xD9, 0xF8, 0x00, 0x10, ++0x01, 0xA8, 0xFF, 0xF7, 0x25, 0xFF, 0xFF, 0xF7, 0x0D, 0xFD, 0xC7, 0xF8, 0x00, 0xB0, 0x2B, 0x68, 0x2B, 0x68, 0x06, 0xF4, ++0x80, 0x76, 0x1E, 0x43, 0xA0, 0x45, 0x2E, 0x60, 0x26, 0xD8, 0x25, 0x48, 0x0D, 0xF1, 0x05, 0x03, 0xA4, 0xEB, 0x08, 0x04, ++0x43, 0x44, 0x01, 0xAA, 0x42, 0x44, 0x53, 0xFA, 0x84, 0xF4, 0x00, 0xEB, 0x08, 0x10, 0x15, 0x78, 0x53, 0x79, 0x92, 0xF8, ++0x0A, 0xC0, 0xD7, 0x7B, 0x16, 0x7D, 0x29, 0x06, 0x1B, 0x04, 0x01, 0xF0, 0x70, 0x41, 0x43, 0xEA, 0x0C, 0x63, 0x41, 0xEA, ++0x05, 0x51, 0x3B, 0x43, 0x01, 0x32, 0x09, 0x0E, 0x43, 0xEA, 0x06, 0x23, 0xA2, 0x42, 0x80, 0xF8, 0x07, 0x12, 0xC0, 0xF8, ++0x00, 0x32, 0x00, 0xF1, 0x10, 0x00, 0xE4, 0xD1, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0xF0, 0x0C, 0x0F, 0x08, 0xD1, ++0xA0, 0x45, 0xAF, 0xD9, 0x0E, 0x49, 0x0F, 0x48, 0x41, 0xF2, 0x7F, 0x02, 0x1F, 0xF0, 0xFA, 0xFF, 0xA8, 0xE7, 0x0B, 0x49, ++0x0C, 0x48, 0x41, 0xF2, 0x7E, 0x02, 0x1F, 0xF0, 0xF3, 0xFF, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEB, 0xDB, ++0x9C, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x7C, 0x15, 0x00, 0x00, 0x04, 0x60, 0x40, 0x18, 0x00, 0x58, 0x40, ++0x1C, 0x13, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x88, 0x7C, 0x15, 0x00, 0x78, 0x7C, 0x15, 0x00, 0x24, 0x4B, 0x25, 0x4A, ++0x06, 0x21, 0x10, 0xB4, 0xC3, 0xF8, 0x00, 0x11, 0x53, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x53, 0x60, 0x53, 0x68, 0x43, 0xF4, ++0x00, 0x33, 0x53, 0x60, 0x13, 0x6B, 0x03, 0xF0, 0x44, 0x03, 0x04, 0x2B, 0xFA, 0xD1, 0x1D, 0x4B, 0x1D, 0x4C, 0x1B, 0x68, ++0x1D, 0x48, 0x19, 0x49, 0xA4, 0xFB, 0x03, 0x43, 0x9B, 0x0C, 0x43, 0xF0, 0x00, 0x44, 0x44, 0xF4, 0xA0, 0x14, 0x43, 0xF4, ++0xA0, 0x13, 0x03, 0x60, 0x04, 0x60, 0x03, 0x60, 0x53, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x43, 0xF4, 0xC4, 0x33, 0x43, 0xF0, ++0x02, 0x03, 0x4F, 0xF4, 0x80, 0x50, 0x53, 0x60, 0xC1, 0xF8, 0x34, 0x01, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, ++0x4B, 0x6F, 0x43, 0xF0, 0x01, 0x03, 0x4B, 0x67, 0x53, 0x6C, 0x43, 0xF0, 0x08, 0x43, 0x53, 0x64, 0x53, 0x6D, 0x23, 0xF4, ++0x00, 0x13, 0x53, 0x65, 0x53, 0x6D, 0x43, 0xF0, 0x02, 0x03, 0x53, 0x65, 0x53, 0x6D, 0x23, 0xF4, 0x00, 0x63, 0x53, 0x65, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, 0x18, 0x13, 0x17, 0x00, 0x83, 0xDE, 0x1B, 0x43, ++0x08, 0x00, 0x58, 0x40, 0x3B, 0x4A, 0x3C, 0x48, 0x13, 0x68, 0x3C, 0x49, 0xDF, 0xF8, 0x24, 0xC1, 0x43, 0xF0, 0x7C, 0x53, ++0xF0, 0xB4, 0x13, 0x60, 0x39, 0x4C, 0x3A, 0x4B, 0x23, 0x60, 0x03, 0xF1, 0xBE, 0x43, 0xA3, 0xF5, 0x69, 0x03, 0xA3, 0xF6, ++0x77, 0x33, 0x03, 0x60, 0x36, 0x4B, 0x0B, 0x60, 0x36, 0x4F, 0x37, 0x4E, 0x37, 0x4D, 0x40, 0xF6, 0x77, 0x13, 0xCC, 0xF8, ++0x00, 0x30, 0x36, 0x4B, 0x3B, 0x60, 0x04, 0xF5, 0x00, 0x24, 0x01, 0xF5, 0x2F, 0x11, 0x00, 0xF5, 0x2F, 0x10, 0x49, 0xF2, ++0x02, 0x43, 0x02, 0xF5, 0x00, 0x22, 0x33, 0x60, 0x0C, 0x34, 0x30, 0x4B, 0x2B, 0x60, 0x01, 0xF5, 0x05, 0x61, 0x00, 0xF6, ++0x58, 0x00, 0x02, 0xF6, 0x7C, 0x02, 0x07, 0xF5, 0x2F, 0x17, 0x2C, 0x4D, 0x25, 0x60, 0x07, 0xF6, 0x68, 0x07, 0x0B, 0x60, ++0x06, 0xF5, 0x37, 0x16, 0x03, 0x60, 0x13, 0x60, 0x40, 0xF6, 0x34, 0x03, 0x3B, 0x60, 0x06, 0xF2, 0xE4, 0x46, 0x26, 0x4B, ++0x33, 0x60, 0x01, 0xF5, 0xFE, 0x31, 0x03, 0xF1, 0x50, 0x53, 0x88, 0x31, 0x03, 0xF5, 0x54, 0x13, 0x0F, 0x33, 0x0B, 0x60, ++0x00, 0xF5, 0xFE, 0x30, 0x03, 0xF1, 0x48, 0x43, 0x1F, 0x4D, 0x00, 0xF5, 0x90, 0x70, 0x02, 0xF5, 0xFE, 0x32, 0xA3, 0xF5, ++0x78, 0x13, 0x02, 0xF5, 0xB4, 0x72, 0xA3, 0xF2, 0x1F, 0x63, 0x4F, 0xF0, 0x36, 0x36, 0x2B, 0x60, 0x06, 0x60, 0x4F, 0xF4, ++0x7F, 0x40, 0x10, 0x60, 0x04, 0xF5, 0x01, 0x34, 0x02, 0xF1, 0xAC, 0x42, 0x20, 0x34, 0x15, 0x4B, 0x15, 0x4D, 0x25, 0x60, ++0xA2, 0xF5, 0xB5, 0x12, 0x45, 0xF2, 0x55, 0x30, 0xA2, 0xF6, 0x8A, 0x62, 0xC1, 0xF8, 0xA8, 0x00, 0xF0, 0xBC, 0x1A, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x0C, 0x00, 0x58, 0x40, 0x2C, 0x40, 0x34, 0x40, 0x30, 0x40, 0x34, 0x40, 0x04, 0x01, 0x58, 0x40, ++0xFB, 0x23, 0x09, 0x00, 0x08, 0x51, 0x2E, 0x1A, 0x24, 0x40, 0x34, 0x40, 0x28, 0x40, 0x34, 0x40, 0x8C, 0x04, 0x60, 0x40, ++0x94, 0xC5, 0x2E, 0x00, 0x34, 0x08, 0x50, 0x00, 0x58, 0x00, 0x7E, 0x02, 0x13, 0x20, 0x20, 0x20, 0xA0, 0x05, 0x62, 0x40, ++0x1C, 0x05, 0x62, 0x40, 0x0F, 0x12, 0x15, 0x0C, 0x20, 0x40, 0x34, 0x40, 0x63, 0x49, 0x64, 0x4A, 0x0B, 0x68, 0x23, 0xF4, ++0x00, 0x63, 0xF0, 0xB4, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0xDF, 0xF8, 0x6C, 0xC1, 0x5B, 0x4A, 0xDC, 0xF8, 0x00, 0x30, 0x5A, 0x4F, 0x5B, 0x4E, ++0x23, 0xF4, 0x80, 0x53, 0xCC, 0xF8, 0x00, 0x30, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, 0xDC, 0xF8, 0x00, 0x30, ++0x43, 0xF4, 0x80, 0x63, 0xCC, 0xF8, 0x00, 0x30, 0xDC, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x00, 0x63, 0xCC, 0xF8, 0x00, 0x30, ++0x62, 0x46, 0xFF, 0x25, 0x2B, 0x1D, 0x2C, 0x46, 0xDD, 0xB2, 0x29, 0x46, 0x38, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, ++0x0B, 0x43, 0x13, 0x60, 0x50, 0xF8, 0x04, 0x3B, 0x33, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, ++0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, 0xFC, 0xD5, 0x01, 0x39, 0xC9, 0xB2, 0xA1, 0x42, 0xE8, 0xD1, ++0x8F, 0x2D, 0x07, 0xF1, 0x10, 0x07, 0xDF, 0xD1, 0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x80, 0x63, 0xCC, 0xF8, 0x00, 0x30, ++0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x36, 0x4D, 0x37, 0x49, 0x2A, 0x68, 0x39, 0x48, ++0x39, 0x4C, 0x22, 0xF4, 0x00, 0x62, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, ++0x80, 0x72, 0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x50, 0xF8, 0x04, 0x2F, 0x22, 0x60, ++0x0A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, ++0xFC, 0xD5, 0x01, 0x33, 0x20, 0x2B, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x1F, 0x4C, 0x24, 0x48, 0x22, 0x68, 0x24, 0x49, 0x24, 0x4D, 0x22, 0xF4, ++0x80, 0x72, 0x22, 0x60, 0x02, 0x68, 0x22, 0xF0, 0x02, 0x02, 0x02, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x62, 0x0A, 0x60, ++0x32, 0x22, 0x2B, 0x60, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0x13, 0x49, 0x13, 0x4A, 0x08, 0x68, ++0x1A, 0x4D, 0x1B, 0x4C, 0x1B, 0x4B, 0x40, 0xF4, 0x80, 0x50, 0x08, 0x60, 0x08, 0x68, 0x40, 0xF4, 0x00, 0x60, 0x08, 0x60, ++0x11, 0x68, 0x41, 0xF4, 0x00, 0x71, 0x11, 0x60, 0x11, 0x68, 0x41, 0xF4, 0x80, 0x71, 0x11, 0x60, 0x2A, 0x68, 0x42, 0xF4, ++0x80, 0x52, 0x2A, 0x60, 0x22, 0x68, 0x22, 0xF4, 0x80, 0x22, 0x22, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x00, 0x52, 0x1A, 0x60, ++0x1A, 0x68, 0x42, 0xF0, 0x80, 0x42, 0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x60, 0x40, 0x34, 0x40, 0x6C, 0x40, 0x34, 0x40, ++0x1C, 0x13, 0x17, 0x00, 0x64, 0x40, 0x34, 0x40, 0x18, 0x18, 0x17, 0x00, 0x70, 0x40, 0x34, 0x40, 0x18, 0x00, 0x58, 0x40, ++0x58, 0x40, 0x34, 0x40, 0x08, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, 0x1C, 0x20, 0x34, 0x40, ++0x10, 0xB5, 0x09, 0x4C, 0x82, 0xB0, 0xD4, 0xF8, 0xC0, 0x34, 0x01, 0x90, 0x98, 0x47, 0xD4, 0xF8, 0xC4, 0x34, 0x98, 0x47, ++0xD4, 0xF8, 0xC8, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0xCC, 0x34, 0x00, 0x21, 0x01, 0xA8, 0x98, 0x47, 0x02, 0xB0, 0x10, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x2D, 0x4C, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x17, 0xD0, 0x0F, 0x24, 0x4F, 0xF4, ++0x00, 0x62, 0x11, 0x46, 0x29, 0x48, 0xFD, 0xF7, 0x61, 0xFA, 0x4F, 0xF4, 0x40, 0x72, 0x28, 0x48, 0x00, 0x21, 0xFD, 0xF7, ++0x5B, 0xFA, 0x21, 0x46, 0x26, 0x48, 0xFD, 0xF7, 0x2F, 0xFA, 0x02, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x24, 0x48, 0x11, 0x46, ++0xFD, 0xF7, 0x50, 0xBA, 0x04, 0xF0, 0x2E, 0xFD, 0x22, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0xC3, 0xF8, 0x80, 0x20, 0xBF, 0xF3, ++0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0x1F, 0x48, 0x1F, 0xF0, 0x52, 0xFB, 0x1E, 0x4A, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF0, ++0x02, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x13, 0x69, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x61, 0x13, 0x69, 0xDB, 0x07, 0xFC, 0xD4, ++0x18, 0x48, 0x1F, 0xF0, 0x41, 0xFB, 0x18, 0x4A, 0x18, 0x48, 0x4F, 0xF4, 0x00, 0x21, 0xFD, 0xF7, 0x2B, 0xFA, 0x17, 0x4B, ++0x4F, 0xF4, 0x80, 0x61, 0x4F, 0xF4, 0x00, 0x02, 0xC3, 0xF8, 0x28, 0x11, 0xC3, 0xF8, 0x18, 0x21, 0x23, 0x68, 0x1B, 0x78, ++0x02, 0x2B, 0xB5, 0xD1, 0x04, 0xF0, 0xB6, 0xFE, 0x00, 0x28, 0xB1, 0xD0, 0x0F, 0x4B, 0x10, 0x48, 0xD3, 0xF8, 0x00, 0x41, ++0x21, 0x46, 0x1F, 0xF0, 0x23, 0xFB, 0xAA, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x0C, 0x88, 0x01, 0x50, 0x14, 0x88, 0x01, 0x50, ++0x00, 0x70, 0x01, 0x50, 0x08, 0x70, 0x01, 0x50, 0x00, 0xE1, 0x00, 0xE0, 0x9C, 0x7C, 0x15, 0x00, 0x00, 0x00, 0x20, 0x40, ++0xA8, 0x7C, 0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x90, 0x01, 0x50, 0x00, 0x00, 0x10, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0xB8, 0x7C, 0x15, 0x00, 0x38, 0xB5, 0x36, 0x4C, 0x36, 0x48, 0x44, 0x22, 0x00, 0x21, 0xFB, 0xF7, 0x91, 0xF8, 0x23, 0x68, ++0x1A, 0x07, 0xC3, 0xF3, 0xC0, 0x01, 0x51, 0xD5, 0x22, 0x46, 0x00, 0xBF, 0x13, 0x68, 0xDB, 0x06, 0xFB, 0xD5, 0x30, 0x4D, ++0x30, 0x48, 0x29, 0x68, 0x30, 0x4B, 0x00, 0x68, 0x30, 0x4A, 0xC1, 0xF8, 0x44, 0x02, 0x00, 0x21, 0x19, 0x60, 0x11, 0x60, ++0x19, 0x68, 0x2E, 0x48, 0x2E, 0x4C, 0x21, 0xF0, 0x03, 0x01, 0x41, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, ++0x0C, 0x01, 0x41, 0xF0, 0x08, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x40, 0x71, 0x41, 0xF4, 0x00, 0x71, 0x19, 0x60, ++0x19, 0x68, 0x21, 0xF4, 0x40, 0x61, 0x41, 0xF4, 0x00, 0x61, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x40, 0x51, 0x41, 0xF4, ++0x00, 0x51, 0x19, 0x60, 0x11, 0x68, 0x21, 0xF0, 0x40, 0x51, 0x41, 0xF0, 0x00, 0x51, 0x11, 0x60, 0x11, 0x68, 0x21, 0xF0, ++0x40, 0x41, 0x41, 0xF0, 0x00, 0x41, 0x11, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x32, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x40, 0x22, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x12, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x02, 0x1A, 0x60, ++0x1A, 0x68, 0x42, 0xF0, 0x40, 0x72, 0x1A, 0x60, 0x04, 0x60, 0x38, 0xBD, 0x23, 0x68, 0x09, 0x4D, 0x43, 0xF0, 0x08, 0x03, ++0x23, 0x60, 0x28, 0x68, 0x4F, 0xF4, 0x12, 0x72, 0xFB, 0xF7, 0x30, 0xF8, 0x23, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x23, 0x60, ++0xA4, 0xE7, 0x00, 0xBF, 0x80, 0x40, 0x04, 0x40, 0x04, 0x35, 0x17, 0x00, 0x00, 0x38, 0x18, 0x00, 0x84, 0x1A, 0x17, 0x00, ++0x14, 0x41, 0x04, 0x40, 0x18, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x33, 0x1F, 0x00, 0xC0, 0x0C, 0x4B, 0x10, 0xB5, ++0x1C, 0x68, 0x14, 0xF4, 0xF8, 0x54, 0x00, 0xD1, 0x10, 0xBD, 0x60, 0x08, 0x1E, 0xF0, 0x02, 0xF8, 0x08, 0x4A, 0x09, 0x49, ++0x09, 0x4B, 0x0C, 0x60, 0x14, 0x60, 0x1A, 0x78, 0x00, 0x2A, 0xF3, 0xD0, 0x07, 0x4A, 0x01, 0x21, 0x59, 0x70, 0x13, 0x68, ++0x0B, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x1C, 0x41, 0x04, 0x40, 0x08, 0x41, 0x04, 0x40, 0x10, 0x41, 0x04, 0x40, ++0x3C, 0x36, 0x17, 0x00, 0x10, 0x00, 0x58, 0x40, 0x2D, 0xE9, 0xF8, 0x4F, 0x29, 0x4B, 0x06, 0x46, 0x53, 0xF8, 0x20, 0x00, ++0x1E, 0xF0, 0x04, 0xF8, 0x27, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x26, 0x4B, 0xD3, 0xF8, 0x00, 0xA0, 0xDA, 0xF8, ++0x3C, 0x32, 0x0A, 0xF5, 0x0F, 0x7B, 0x8B, 0xB3, 0x23, 0x4D, 0xDF, 0xF8, 0x98, 0x90, 0xDF, 0xF8, 0x98, 0x80, 0x05, 0xF2, ++0x14, 0x57, 0x1D, 0xE0, 0x95, 0xF8, 0x10, 0x35, 0x85, 0xF8, 0x11, 0x45, 0x01, 0x33, 0xA9, 0xFB, 0x03, 0x24, 0xA4, 0x09, ++0x04, 0xEB, 0xC4, 0x04, 0x04, 0xEB, 0xC4, 0x04, 0x1C, 0x1B, 0x85, 0xF8, 0x10, 0x45, 0x1E, 0xF0, 0xA1, 0xF8, 0xD8, 0xF8, ++0x00, 0x20, 0x05, 0xEB, 0x04, 0x11, 0x02, 0x44, 0xC1, 0xE9, 0x01, 0x26, 0x38, 0x46, 0x1E, 0xF0, 0x53, 0xF8, 0xDA, 0xF8, ++0x3C, 0x32, 0x5B, 0xB1, 0x95, 0xF8, 0x11, 0x15, 0x95, 0xF8, 0x12, 0x25, 0x91, 0x42, 0x58, 0x46, 0x01, 0xF1, 0x01, 0x04, ++0xD8, 0xD3, 0x0D, 0x48, 0x01, 0xF0, 0x54, 0xF8, 0x08, 0x4B, 0x01, 0x24, 0x1C, 0x60, 0x20, 0x20, 0x08, 0x36, 0x1D, 0xF0, ++0x9B, 0xFF, 0x04, 0xFA, 0x06, 0xF6, 0x08, 0x4B, 0x06, 0xF4, 0xF8, 0x56, 0x1E, 0x60, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, ++0x80, 0x7E, 0x15, 0x00, 0x4C, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x58, 0x58, 0x17, 0x00, 0xCC, 0x7C, 0x15, 0x00, ++0x0C, 0x41, 0x04, 0x40, 0xE7, 0x87, 0x45, 0xCA, 0x84, 0x1A, 0x17, 0x00, 0x1D, 0x4B, 0x10, 0xB5, 0x1C, 0x68, 0xA0, 0x06, ++0x2C, 0xD4, 0xE1, 0x06, 0x20, 0xD4, 0xA2, 0x07, 0x16, 0xD4, 0x63, 0x00, 0x08, 0xD5, 0x19, 0x4B, 0x01, 0x20, 0xD3, 0xF8, ++0x78, 0x34, 0x98, 0x47, 0x17, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x00, 0x2C, 0x00, 0xDB, 0x10, 0xBD, 0x13, 0x4B, ++0xD3, 0xF8, 0x68, 0x34, 0x98, 0x47, 0x12, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x80, 0x50, ++0x1D, 0xF0, 0x5E, 0xFF, 0x0E, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0xE0, 0xE7, 0x0C, 0x49, 0x0B, 0x4A, 0x10, 0x23, 0x0B, 0x60, ++0x4F, 0xF4, 0x00, 0x10, 0x13, 0x60, 0x1D, 0xF0, 0x51, 0xFF, 0xD4, 0xE7, 0x07, 0x49, 0x06, 0x4A, 0x20, 0x23, 0x0B, 0x60, ++0x4F, 0xF4, 0x80, 0x10, 0x13, 0x60, 0x1D, 0xF0, 0x47, 0xFF, 0xC8, 0xE7, 0x1C, 0x41, 0x04, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x10, 0x41, 0x04, 0x40, 0x06, 0x4A, 0x07, 0x49, 0x12, 0x68, 0xD2, 0xF8, 0x24, 0x02, 0x20, 0x23, ++0x0B, 0x60, 0x08, 0xB1, 0x01, 0x20, 0x70, 0x47, 0x03, 0x4A, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x38, 0x18, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x15, 0x4C, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x14, 0x4B, ++0x18, 0x68, 0xD0, 0xF8, 0x24, 0x32, 0xBB, 0xB1, 0x00, 0xF5, 0x09, 0x70, 0x1E, 0xF0, 0x02, 0xF8, 0x10, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x22, 0x60, 0x01, 0xDB, 0x14, 0x30, 0x10, 0xBD, 0x00, 0x28, 0xFB, 0xD1, ++0x0B, 0x49, 0x0C, 0x48, 0x40, 0xF2, 0x92, 0x32, 0x1F, 0xF0, 0x00, 0xFC, 0x14, 0x20, 0x10, 0xBD, 0x06, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x22, 0x60, 0xF5, 0xDA, 0xEE, 0xE7, 0x00, 0xBF, 0x54, 0x40, 0x04, 0x40, ++0x00, 0x38, 0x18, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xE4, 0x7C, 0x15, 0x00, 0x10, 0xB5, 0x0A, 0x4C, ++0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x09, 0x4B, 0x1B, 0x68, 0xD3, 0xF8, 0x14, 0x02, 0x40, 0xB1, 0x03, 0xF5, 0x05, 0x70, ++0x1D, 0xF0, 0xCC, 0xFF, 0x01, 0x23, 0x23, 0x60, 0x00, 0xB1, 0x04, 0x30, 0x10, 0xBD, 0x01, 0x23, 0x23, 0x60, 0x10, 0xBD, ++0x58, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x01, 0x4B, 0x08, 0x22, 0x1A, 0x60, 0x70, 0x47, ++0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x41, 0x04, 0x40, ++0x01, 0x4B, 0x80, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x00, 0x41, 0x04, 0x40, 0xF8, 0xB5, 0x04, 0x46, 0x40, 0x89, 0x29, 0x4F, ++0x10, 0x30, 0x1D, 0xF0, 0xA3, 0xFB, 0x3E, 0x68, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x22, 0xDB, 0xA3, 0x88, ++0x62, 0x89, 0xE0, 0x88, 0xAB, 0x80, 0x00, 0x21, 0x0C, 0x23, 0x2B, 0x81, 0x6A, 0x81, 0xE8, 0x80, 0x29, 0x60, 0xE3, 0x18, ++0x62, 0xB1, 0x01, 0x3A, 0x22, 0xF0, 0x03, 0x02, 0x10, 0x32, 0x14, 0x44, 0x05, 0xF1, 0x08, 0x02, 0x53, 0xF8, 0x04, 0x1B, ++0x42, 0xF8, 0x04, 0x1F, 0xA3, 0x42, 0xF9, 0xD1, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x05, 0xF1, 0x0C, 0x00, ++0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0xD8, 0xBA, 0x00, 0x28, 0xDA, 0xD1, 0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x6F, 0x42, ++0x1F, 0xF0, 0x82, 0xFB, 0x3E, 0x68, 0xD2, 0xE7, 0x0D, 0x28, 0x0D, 0xD8, 0x0B, 0x28, 0xEB, 0xD9, 0x0C, 0x49, 0x0E, 0x48, ++0x4F, 0xF4, 0x90, 0x62, 0x1F, 0xF0, 0x76, 0xFB, 0x05, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0xBE, 0xBA, ++0x06, 0x49, 0x09, 0x48, 0xBB, 0x22, 0x1F, 0xF0, 0x6B, 0xFB, 0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x90, 0x62, 0x1F, 0xF0, ++0x65, 0xFB, 0xED, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x7C, 0x15, 0x00, 0x20, 0x7D, 0x15, 0x00, ++0x10, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x05, 0x46, 0x40, 0x89, 0x2B, 0x4F, 0x10, 0x30, 0x1D, 0xF0, 0x43, 0xFB, 0x3E, 0x68, ++0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x2A, 0xDB, 0xAB, 0x88, 0x6A, 0x89, 0xEF, 0x88, 0xA3, 0x80, 0x00, 0x21, ++0x0C, 0x23, 0x23, 0x81, 0x62, 0x81, 0xE7, 0x80, 0x21, 0x60, 0xEB, 0x18, 0x62, 0xB1, 0x01, 0x3A, 0x22, 0xF0, 0x03, 0x02, ++0x10, 0x32, 0x2A, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x53, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0F, 0x93, 0x42, 0xF9, 0xD1, ++0x1A, 0x4A, 0x53, 0x7D, 0x59, 0x1C, 0x51, 0x75, 0x2B, 0x81, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x12, 0xDB, 0x17, 0x4B, ++0x04, 0x22, 0x04, 0xF1, 0x0C, 0x00, 0x1A, 0x60, 0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0x70, 0xBA, 0x00, 0x28, 0xD2, 0xD1, ++0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x8E, 0x42, 0x1F, 0xF0, 0x1A, 0xFB, 0x3E, 0x68, 0xCA, 0xE7, 0x0D, 0x2F, 0x08, 0xD8, ++0x0B, 0x2F, 0xE8, 0xD9, 0x0C, 0x49, 0x0E, 0x48, 0x40, 0xF2, 0xA3, 0x42, 0x1F, 0xF0, 0x0E, 0xFB, 0xE1, 0xE7, 0x09, 0x49, ++0x0B, 0x48, 0xBB, 0x22, 0x1F, 0xF0, 0x08, 0xFB, 0x06, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xA3, 0x42, 0x1F, 0xF0, 0x02, 0xFB, ++0xD5, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x04, 0x35, 0x17, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0x79, 0x15, 0x00, ++0xFC, 0x7C, 0x15, 0x00, 0x20, 0x7D, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x0B, 0x4C, 0x23, 0x68, 0x9A, 0x07, ++0x0A, 0xD5, 0x0A, 0x4F, 0x0A, 0x4E, 0x02, 0x25, 0x38, 0x68, 0x35, 0x60, 0x04, 0x30, 0xFF, 0xF7, 0x8B, 0xFF, 0x23, 0x68, ++0x9B, 0x07, 0xF7, 0xD4, 0x4F, 0xF0, 0x80, 0x50, 0x1D, 0xF0, 0x0C, 0xFE, 0x04, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0xF8, 0xBD, ++0x04, 0x41, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x47, ++0xDF, 0xF8, 0x20, 0x93, 0xD9, 0xF8, 0x00, 0x20, 0x13, 0x78, 0x03, 0x2B, 0x82, 0xB0, 0x04, 0x46, 0x00, 0xF0, 0x16, 0x81, ++0x00, 0x27, 0x3E, 0x46, 0x01, 0x2B, 0x00, 0xF0, 0xC2, 0x80, 0x02, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0x00, 0xF0, 0xD3, 0x80, ++0x62, 0x89, 0xA3, 0x88, 0x33, 0x80, 0xF2, 0x80, 0x7A, 0xB9, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x03, 0x2B, 0x1C, 0xD0, ++0x02, 0x2B, 0x2F, 0xD0, 0x01, 0x2B, 0x00, 0xF0, 0x89, 0x80, 0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x1D, 0xF0, ++0x41, 0xBA, 0xA3, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x20, 0x81, 0x06, 0xF1, 0x0C, 0x00, ++0x04, 0xF1, 0x0C, 0x01, 0x31, 0xF0, 0x40, 0xFD, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x03, 0x2B, 0xE2, 0xD1, 0x9B, 0x4E, ++0x33, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x9A, 0x4B, 0x18, 0x68, 0x39, 0x1F, 0x00, 0xF5, 0x03, 0x70, 0x1D, 0xF0, 0x36, 0xFE, ++0x97, 0x4B, 0x01, 0x21, 0x02, 0x22, 0x31, 0x60, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x02, 0x2B, 0xCF, 0xD1, ++0x60, 0x89, 0x10, 0xF0, 0x03, 0x03, 0x40, 0xF0, 0xE9, 0x80, 0x19, 0x46, 0x9C, 0x46, 0x90, 0x4E, 0x42, 0xF2, 0x34, 0x03, ++0xF2, 0x5A, 0xB2, 0xF5, 0xC3, 0x7F, 0x00, 0xF2, 0xFD, 0x80, 0x57, 0x1C, 0xBF, 0xB2, 0x4F, 0xEA, 0xC2, 0x0E, 0x8B, 0x4B, ++0xA8, 0xF8, 0x0C, 0x20, 0xD3, 0xF8, 0x00, 0xA0, 0x00, 0xF1, 0x10, 0x03, 0x0A, 0xEB, 0x0E, 0x00, 0x0C, 0xEB, 0x03, 0x02, ++0x45, 0x60, 0x2A, 0xF8, 0x0E, 0x20, 0xC2, 0x78, 0x02, 0xF0, 0x31, 0x02, 0x42, 0xF0, 0x04, 0x02, 0xC2, 0x70, 0x96, 0xF8, ++0x02, 0x2C, 0x42, 0xF2, 0x34, 0x0C, 0x0B, 0x44, 0x01, 0x32, 0x01, 0x21, 0x4F, 0xF0, 0x00, 0x0E, 0x26, 0xF8, 0x0C, 0x70, ++0x86, 0xF8, 0x02, 0x2C, 0xC8, 0xE9, 0x01, 0x03, 0x88, 0xF8, 0x0E, 0x10, 0xC8, 0xF8, 0x00, 0xE0, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x76, 0x4B, 0x19, 0x60, 0x76, 0x4E, 0x76, 0x48, 0x33, 0x68, 0x41, 0x46, 0x01, 0x33, ++0x33, 0x60, 0x1D, 0xF0, 0xE3, 0xFD, 0x74, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x33, 0x68, 0x33, 0xB1, 0x6E, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x01, 0x2B, ++0x7F, 0xF4, 0x77, 0xAF, 0x01, 0xF0, 0xF2, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x0C, 0x81, 0xA1, 0x7A, 0x68, 0x4A, 0x0C, 0x31, ++0x29, 0x70, 0x61, 0x89, 0x0C, 0x31, 0x00, 0x27, 0x09, 0x12, 0x11, 0x26, 0x69, 0x70, 0xAE, 0x70, 0xEF, 0x70, 0x61, 0x89, ++0x86, 0x68, 0x47, 0x60, 0x10, 0x31, 0xC1, 0xF3, 0x0B, 0x01, 0x32, 0x40, 0x0A, 0x43, 0x42, 0xF0, 0x00, 0x42, 0x05, 0x60, ++0x82, 0x60, 0x03, 0xF0, 0x35, 0xF8, 0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x1D, 0xF0, 0x99, 0xB9, 0x63, 0x89, ++0x6C, 0x2B, 0x40, 0xF2, 0x8C, 0x80, 0x58, 0x4B, 0x1B, 0x68, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x05, 0x46, ++0x00, 0x2D, 0x00, 0xF0, 0x8A, 0x80, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0xF1, 0x04, 0x06, 0x7F, 0xF4, ++0x2D, 0xAF, 0x63, 0x89, 0x6C, 0x2B, 0x7A, 0xD9, 0x4D, 0x4B, 0x1B, 0x68, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, ++0x05, 0x46, 0x00, 0x2D, 0x75, 0xD0, 0x42, 0x4A, 0x42, 0xF2, 0x24, 0x03, 0xD3, 0x58, 0x00, 0x2B, 0x00, 0xF0, 0x9A, 0x80, ++0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x3D, 0x4E, 0x42, 0x48, ++0x33, 0x68, 0x01, 0x33, 0x33, 0x60, 0x1D, 0xF0, 0xB7, 0xFD, 0x33, 0x68, 0x80, 0x46, 0x33, 0xB1, 0x37, 0x4A, 0x01, 0x3B, ++0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xA3, 0x7A, 0x0C, 0x33, 0x2B, 0x70, 0x63, 0x89, 0x0C, 0x33, ++0x1B, 0x12, 0x11, 0x22, 0x6B, 0x70, 0x00, 0x23, 0xAA, 0x70, 0xEB, 0x70, 0x2E, 0x1D, 0xF3, 0xE6, 0x28, 0x4D, 0x2B, 0x68, ++0x00, 0x2B, 0xFC, 0xD0, 0x27, 0x4B, 0x18, 0x68, 0xD0, 0xF8, 0x04, 0x32, 0xD3, 0xB1, 0x00, 0xF5, 0x01, 0x70, 0x1D, 0xF0, ++0x93, 0xFD, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x2A, 0x60, 0xC0, 0xF2, 0x8B, 0x80, ++0x07, 0x1D, 0xD9, 0xF8, 0x00, 0x20, 0x3E, 0x46, 0x27, 0x4B, 0xB3, 0x60, 0x13, 0x78, 0xCD, 0xE6, 0xC3, 0xF1, 0x04, 0x03, ++0x5F, 0xFA, 0x83, 0xFC, 0x61, 0x46, 0x12, 0xE7, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x01, 0x21, 0x00, 0x2B, ++0x29, 0x60, 0xC0, 0xF2, 0x82, 0x80, 0x04, 0x26, 0x37, 0x46, 0xE9, 0xE7, 0xB2, 0xF5, 0x80, 0x6F, 0x7F, 0xF6, 0xDC, 0xAE, ++0x4F, 0xF4, 0xB1, 0x62, 0x1A, 0x49, 0x1B, 0x48, 0x1F, 0xF0, 0x76, 0xF9, 0x62, 0x89, 0xD3, 0xE6, 0x4F, 0xF0, 0x00, 0x0E, ++0x72, 0x46, 0x01, 0x27, 0x01, 0xE7, 0x01, 0xF0, 0xCF, 0xFF, 0x05, 0x46, 0x76, 0xE7, 0x05, 0xF0, 0x2B, 0xF8, 0x05, 0x46, ++0x87, 0xE7, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x11, 0x48, 0x00, 0xF0, 0x1D, 0xFD, 0xB2, 0xE6, 0x38, 0x36, 0x17, 0x00, ++0x50, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x00, 0x41, 0x04, 0x40, 0x7C, 0x36, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xF0, 0xFF, 0x7F, ++0x1C, 0x58, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x2A, 0xDE, 0xDE, 0xAD, 0x70, 0x79, 0x15, 0x00, 0xDC, 0x7D, 0x15, 0x00, ++0x68, 0x7D, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x20, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x1F, 0x4D, 0x20, 0x4A, 0x2B, 0x68, 0xD2, 0xF8, 0x44, 0x24, 0x01, 0x33, 0x2B, 0x60, 0x90, 0x47, ++0x2A, 0x68, 0x03, 0x46, 0x32, 0xB1, 0x19, 0x49, 0x01, 0x3A, 0x09, 0x68, 0x2A, 0x60, 0x0A, 0xB9, 0x01, 0xB1, 0x62, 0xB6, ++0x18, 0x48, 0x01, 0x93, 0x1D, 0xF0, 0x4E, 0xFD, 0x00, 0x90, 0x17, 0x48, 0x1D, 0xF0, 0x4A, 0xFD, 0xDD, 0xE9, 0x00, 0x13, ++0x02, 0x46, 0x15, 0x48, 0x00, 0xF0, 0xD0, 0xFC, 0x65, 0xE6, 0x14, 0x48, 0x00, 0xF0, 0xCC, 0xFC, 0x61, 0xE6, 0x60, 0xB1, ++0x07, 0x1D, 0x7F, 0xF4, 0x72, 0xAF, 0x40, 0xF2, 0x31, 0x52, 0x10, 0x49, 0x10, 0x48, 0x1F, 0xF0, 0x05, 0xF9, 0x3E, 0x46, ++0xD9, 0xF8, 0x00, 0x20, 0x6A, 0xE7, 0x40, 0xF2, 0x26, 0x32, 0x0B, 0x49, 0x0C, 0x48, 0x04, 0x26, 0x1F, 0xF0, 0xFA, 0xF8, ++0x37, 0x46, 0xD9, 0xF8, 0x00, 0x20, 0x5F, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xA0, 0x56, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0xA4, 0x7D, 0x15, 0x00, 0x08, 0x7E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x54, 0x7D, 0x15, 0x00, 0x44, 0x7D, 0x15, 0x00, 0x10, 0xB4, 0x15, 0x49, 0x15, 0x4C, 0x16, 0x4B, 0x4F, 0xF4, 0x4C, 0x02, ++0x22, 0x60, 0x0A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x30, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0xC0, 0x02, 0x1A, 0x60, ++0x1A, 0x68, 0x22, 0xF4, 0x40, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x4F, 0xF0, 0x60, 0x50, 0x22, 0xF4, 0x40, 0x42, 0x1A, 0x60, ++0x20, 0x60, 0x08, 0x60, 0x1A, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x22, 0xF4, 0x40, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, ++0x40, 0x72, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x40, 0x62, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x0C, 0x40, 0x04, 0x40, ++0x08, 0x40, 0x04, 0x40, 0x18, 0x40, 0x04, 0x40, 0x10, 0xB5, 0x01, 0x46, 0x04, 0x46, 0x05, 0x48, 0x1E, 0xF0, 0x30, 0xFE, ++0x04, 0x4A, 0x05, 0x4B, 0x14, 0x60, 0x4F, 0xF0, 0x80, 0x72, 0x1A, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x2C, 0x7E, 0x15, 0x00, ++0x98, 0x40, 0x04, 0x40, 0x00, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF0, 0x00, 0x72, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF0, 0x80, 0x62, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x40, 0x04, 0x40, ++0x08, 0xB5, 0x25, 0x4B, 0x19, 0x68, 0x4A, 0x03, 0x04, 0xD5, 0x4F, 0xF4, 0x80, 0x22, 0x43, 0xF8, 0x14, 0x2C, 0x08, 0xBD, ++0x08, 0x03, 0x04, 0xD5, 0x20, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x08, 0xBD, 0x4A, 0x02, 0x0F, 0xD4, 0x0B, 0x02, ++0x1D, 0xD4, 0x08, 0x01, 0x10, 0xD5, 0x1C, 0x4B, 0x1A, 0x4A, 0xDB, 0x7D, 0x4F, 0xF0, 0x00, 0x61, 0x01, 0x2B, 0x11, 0x60, ++0xE9, 0xD1, 0xBD, 0xE8, 0x08, 0x40, 0x23, 0xF0, 0xED, 0xBE, 0x15, 0x4B, 0x4F, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x08, 0xBD, ++0x11, 0xF0, 0x80, 0x53, 0x16, 0xD0, 0x12, 0x49, 0x10, 0x4B, 0x01, 0x20, 0x4F, 0xF0, 0x80, 0x52, 0x48, 0x75, 0x1A, 0x60, ++0x08, 0xBD, 0x0D, 0x4B, 0x0E, 0x48, 0x4F, 0xF4, 0x00, 0x02, 0x1A, 0x60, 0x00, 0xF0, 0x0E, 0xFC, 0x03, 0x20, 0x00, 0xF0, ++0x93, 0xFC, 0x0B, 0x4B, 0x4F, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x08, 0xBD, 0x8A, 0x00, 0xC4, 0xD5, 0x05, 0x49, 0x04, 0x4A, ++0x4B, 0x75, 0x4F, 0xF0, 0x00, 0x53, 0x13, 0x60, 0x08, 0xBD, 0x00, 0xBF, 0x1C, 0x40, 0x04, 0x40, 0x08, 0x40, 0x04, 0x40, ++0x4C, 0x36, 0x17, 0x00, 0x40, 0x7E, 0x15, 0x00, 0x00, 0x40, 0x04, 0x40, 0x15, 0x4B, 0xD3, 0xF8, 0x24, 0x31, 0x59, 0x06, ++0x09, 0xD5, 0x10, 0xB5, 0x13, 0x4C, 0x23, 0x68, 0x1A, 0x07, 0x88, 0xB0, 0xC3, 0xF3, 0xC0, 0x00, 0x03, 0xD4, 0x08, 0xB0, ++0x10, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x0F, 0x49, 0x20, 0x22, 0x68, 0x46, 0x31, 0xF0, 0xC6, 0xFA, 0x0D, 0x4B, 0x1B, 0x68, ++0x23, 0x68, 0xC3, 0xF3, 0x40, 0x00, 0x9B, 0x07, 0xEF, 0xD5, 0x0B, 0x4B, 0x0B, 0x4A, 0x4F, 0xF4, 0x00, 0x11, 0x19, 0x60, ++0x10, 0x68, 0x10, 0xF4, 0x40, 0x13, 0xFB, 0xD0, 0x08, 0x4A, 0xC0, 0xF3, 0x00, 0x50, 0x13, 0x60, 0xE1, 0xE7, 0x00, 0xBF, ++0x00, 0x00, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x30, 0x95, 0x16, 0x00, 0x30, 0x60, 0x50, 0x40, 0x00, 0x40, 0x04, 0x40, ++0x04, 0x40, 0x04, 0x40, 0x08, 0x40, 0x04, 0x40, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x09, 0xD1, 0x0B, 0x4B, 0x4F, 0xF4, ++0x00, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x09, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x07, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x52, 0x72, 0x1E, 0xF0, ++0xE1, 0xBF, 0x00, 0xBF, 0x00, 0x40, 0x04, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x38, 0xB5, 0x22, 0x48, 0xFC, 0xF7, 0xFA, 0xFB, 0x83, 0x07, 0x23, 0xD5, 0x20, 0x48, 0x00, 0xF0, 0x8B, 0xFB, 0x20, 0x48, ++0xFC, 0xF7, 0xF2, 0xFB, 0x04, 0x46, 0x1F, 0x48, 0xFC, 0xF7, 0xEE, 0xFB, 0x03, 0x46, 0x1D, 0x48, 0x1C, 0x40, 0xFC, 0xF7, ++0xE9, 0xFB, 0x84, 0x42, 0x1F, 0xD0, 0x05, 0x20, 0x00, 0xF0, 0x14, 0xFC, 0x01, 0x28, 0x04, 0x46, 0x17, 0xD0, 0x03, 0x20, ++0x00, 0xF0, 0x06, 0xFC, 0x02, 0x25, 0x21, 0x46, 0x15, 0x48, 0x00, 0xF0, 0x6F, 0xFB, 0x28, 0x46, 0xBD, 0xE8, 0x38, 0x40, ++0xFF, 0xF7, 0xB2, 0xBF, 0x01, 0x46, 0x12, 0x48, 0x00, 0xF0, 0x66, 0xFB, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x08, 0xDB, 0x38, 0xBD, 0x05, 0x46, 0xE9, 0xE7, 0x20, 0x22, 0x0D, 0x48, 0x11, 0x46, 0xFC, 0xF7, 0x12, 0xFC, ++0xD9, 0xE7, 0xBD, 0xE8, 0x38, 0x40, 0x0B, 0x49, 0x0B, 0x48, 0x4F, 0xF4, 0xD3, 0x62, 0x1E, 0xF0, 0x93, 0xBF, 0x00, 0xBF, ++0x08, 0x30, 0x01, 0x50, 0x54, 0x7E, 0x15, 0x00, 0x20, 0x10, 0x01, 0x50, 0x18, 0x10, 0x01, 0x50, 0x60, 0x7E, 0x15, 0x00, ++0x6C, 0x7E, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x24, 0x10, 0x01, 0x50, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x02, 0x48, 0x38, 0x22, 0x00, 0x21, 0xFA, 0xF7, 0x91, 0xBA, 0x00, 0xBF, 0x48, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x5D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x80, 0x46, 0x0F, 0x46, 0x16, 0x46, 0xC0, 0xF2, 0xA8, 0x80, ++0x00, 0x23, 0x3B, 0x62, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x56, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xB5, 0x01, 0x05, 0xF1, 0x80, 0x42, 0x02, 0xF5, 0xE2, 0x24, 0x53, 0x49, 0x23, 0x68, 0x08, 0x68, 0x43, 0xF0, 0x01, 0x03, ++0x00, 0xF1, 0x01, 0x0C, 0x02, 0xF5, 0xE0, 0x22, 0x23, 0x60, 0xC1, 0xF8, 0x00, 0xC0, 0x23, 0x68, 0xDB, 0x03, 0xFC, 0xD5, ++0xDF, 0xF8, 0x38, 0xE1, 0x5E, 0xF8, 0x26, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0x05, 0xF1, 0x80, 0x43, 0x03, 0xF5, ++0xE0, 0x23, 0x41, 0xF2, 0x0C, 0x0A, 0x53, 0xF8, 0x0A, 0xA0, 0x1A, 0xF4, 0x00, 0x6F, 0x61, 0xD0, 0x05, 0xF1, 0x80, 0x43, ++0x03, 0xF5, 0xE0, 0x23, 0x41, 0xF2, 0x08, 0x09, 0xDF, 0xF8, 0x0C, 0xA1, 0x43, 0xF8, 0x09, 0xA0, 0x41, 0xF2, 0x0C, 0x05, ++0x4F, 0xF0, 0x14, 0x0A, 0x43, 0xF8, 0x05, 0xA0, 0x41, 0xF2, 0x10, 0x0B, 0x41, 0xF2, 0x14, 0x0A, 0x00, 0x25, 0x43, 0xF8, ++0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x18, 0x0B, 0x41, 0xF2, 0x1C, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, ++0x0A, 0x50, 0x03, 0xF5, 0x81, 0x5B, 0x41, 0xF2, 0x24, 0x0A, 0xCB, 0xF8, 0x00, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, ++0x28, 0x0B, 0x41, 0xF2, 0x2C, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x34, 0x0B, 0x41, 0xF2, ++0x38, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x3C, 0x0B, 0x41, 0xF2, 0x30, 0x0A, 0x43, 0xF8, ++0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x80, 0xBD, 0x68, 0x45, 0xF4, 0x00, 0x25, 0xBD, 0x60, 0x53, 0xF8, 0x09, 0x50, 0x45, 0xF0, ++0x01, 0x05, 0x43, 0xF8, 0x09, 0x50, 0x41, 0xF2, 0x04, 0x05, 0x53, 0x59, 0x43, 0xF0, 0x01, 0x03, 0x53, 0x51, 0x23, 0x68, ++0x4E, 0xF8, 0x26, 0x70, 0x23, 0xF0, 0x01, 0x03, 0x23, 0x60, 0xBC, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0x14, 0x4B, 0x08, 0x60, ++0x1B, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x41, 0xF2, 0x18, 0x02, 0x9D, 0x58, 0x2D, 0x03, ++0x07, 0xD5, 0x9D, 0x58, 0x41, 0xF2, 0x30, 0x0A, 0x25, 0xF4, 0x00, 0x25, 0x9D, 0x50, 0x43, 0xF8, 0x0A, 0x80, 0xD9, 0xF8, ++0x08, 0x30, 0x23, 0xF4, 0x00, 0x23, 0xC9, 0xF8, 0x08, 0x30, 0xC9, 0xF8, 0x20, 0x80, 0xD8, 0xE7, 0x0D, 0x2A, 0x7F, 0xF7, ++0x55, 0xAF, 0x06, 0x49, 0x06, 0x48, 0x4E, 0x22, 0x1E, 0xF0, 0xBA, 0xFE, 0x4E, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0x7E, 0x15, 0x00, 0x48, 0x35, 0x17, 0x00, ++0x10, 0x00, 0x01, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x01, 0x30, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x63, 0x70, 0x47, 0x00, 0xBF, ++0x3F, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x40, 0x70, 0xB4, 0x18, 0x4D, 0x18, 0x4C, 0x2E, 0x6B, 0xB1, 0xF5, 0x00, 0x6F, ++0x46, 0xF0, 0x80, 0x56, 0x2E, 0x63, 0x60, 0x60, 0xEB, 0x63, 0x20, 0x60, 0x0B, 0x46, 0x28, 0xBF, 0x4F, 0xF4, 0x00, 0x63, ++0x80, 0x07, 0x11, 0xD0, 0xC1, 0xF3, 0x10, 0x05, 0x10, 0x48, 0x43, 0xF0, 0x0C, 0x53, 0x21, 0xF0, 0x70, 0x41, 0xA3, 0x60, ++0xE5, 0x60, 0x21, 0x61, 0x60, 0x61, 0x0B, 0x49, 0x00, 0x23, 0x23, 0x62, 0x08, 0x46, 0x70, 0xBC, 0xFF, 0xF7, 0x04, 0xBF, ++0xC1, 0xF3, 0x10, 0x05, 0x43, 0xF0, 0x23, 0x43, 0x21, 0xF0, 0x70, 0x41, 0x4F, 0xF0, 0x04, 0x10, 0xA3, 0x60, 0xE5, 0x60, ++0x21, 0x61, 0x60, 0x61, 0xEB, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x07, 0x40, 0x74, 0x25, 0x17, 0x00, 0x01, 0x00, 0x04, 0x00, ++0x01, 0x23, 0x06, 0x4A, 0x03, 0xFA, 0x00, 0xF0, 0x93, 0x69, 0x03, 0x42, 0xFC, 0xD1, 0x13, 0x6B, 0x23, 0xF0, 0x80, 0x53, ++0x13, 0x63, 0x10, 0x6C, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x07, 0x40, 0x08, 0x4A, 0xD3, 0x68, 0x19, 0x04, 0x44, 0xBF, ++0x4F, 0xF4, 0x00, 0x01, 0x91, 0x60, 0x5B, 0x05, 0x00, 0xD4, 0x70, 0x47, 0x03, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x9A, 0x60, ++0x4F, 0xF0, 0x80, 0x40, 0x1D, 0xF0, 0x4E, 0xB9, 0x00, 0x10, 0x50, 0x40, 0x11, 0x4A, 0x13, 0x68, 0x13, 0xF0, 0x01, 0x01, ++0x0A, 0xD1, 0x23, 0xF4, 0x40, 0x73, 0x43, 0xF4, 0x90, 0x73, 0x43, 0xF0, 0x01, 0x03, 0x11, 0x20, 0x11, 0x61, 0x51, 0x61, ++0x50, 0x60, 0x13, 0x60, 0x5A, 0x04, 0x03, 0xD4, 0x08, 0x4A, 0x43, 0xF4, 0x80, 0x43, 0x13, 0x60, 0x07, 0x4B, 0x08, 0x49, ++0x9A, 0x68, 0xD1, 0xF8, 0xD0, 0x10, 0xC2, 0xF8, 0xB4, 0x10, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF0, 0x00, 0x52, 0x1A, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x06, 0x4B, 0x07, 0x49, ++0x9A, 0x68, 0xD1, 0xF8, 0xD0, 0x10, 0xC2, 0xF8, 0xB4, 0x10, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF0, 0x00, 0x52, 0x1A, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x3E, 0x4B, 0x1A, 0x68, 0x00, 0x2A, 0x6F, 0xD1, ++0x3D, 0x49, 0xD1, 0xF8, 0xA4, 0x10, 0x00, 0x29, 0xF0, 0xB4, 0x56, 0xDA, 0x3B, 0x48, 0x00, 0x68, 0x00, 0x28, 0x4E, 0xD0, ++0x3A, 0x4D, 0x3B, 0x48, 0x3B, 0x4C, 0x2A, 0x60, 0x01, 0x25, 0x02, 0x60, 0x25, 0x60, 0xC2, 0x68, 0x39, 0x4D, 0x3A, 0x4C, ++0x42, 0xF4, 0x80, 0x72, 0xC2, 0x60, 0x03, 0x22, 0x2A, 0x60, 0x62, 0x68, 0x92, 0x07, 0x21, 0xF0, 0x00, 0x41, 0x57, 0xD5, ++0x35, 0x4A, 0x12, 0x68, 0x10, 0x09, 0x81, 0x42, 0x4D, 0xD2, 0xB2, 0xFB, 0xF1, 0xF1, 0xC1, 0xF3, 0x42, 0x04, 0x01, 0xF0, ++0x0F, 0x02, 0x12, 0x1B, 0xC1, 0xF3, 0x07, 0x1C, 0x04, 0xEB, 0x02, 0x14, 0xC1, 0xF3, 0x07, 0x31, 0x2A, 0x4A, 0x28, 0x4D, ++0x10, 0x68, 0x2C, 0x4E, 0x2C, 0x4F, 0x40, 0xF0, 0x80, 0x00, 0x10, 0x60, 0xC7, 0xF8, 0x00, 0xC0, 0x29, 0x60, 0x34, 0x60, ++0x11, 0x68, 0x21, 0x4C, 0x22, 0x48, 0x28, 0x4E, 0x21, 0xF0, 0x80, 0x01, 0x11, 0x60, 0x07, 0x22, 0x22, 0x60, 0x02, 0x68, ++0x25, 0x4C, 0x26, 0x49, 0xD4, 0xF8, 0xBC, 0x40, 0x22, 0xF4, 0xFF, 0x72, 0x22, 0xF0, 0x01, 0x02, 0x42, 0xF0, 0x01, 0x02, ++0x02, 0x60, 0x01, 0x22, 0x2A, 0x60, 0xB0, 0x68, 0x4F, 0xF4, 0x80, 0x32, 0xC0, 0xF8, 0x80, 0x40, 0x0A, 0x60, 0x01, 0x22, ++0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x10, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0xF7, 0xD0, 0x10, 0x48, 0x17, 0x4C, 0x16, 0x49, ++0xD4, 0xF8, 0xBC, 0x40, 0x16, 0x4A, 0x01, 0x25, 0x05, 0x60, 0x88, 0x68, 0x4F, 0xF4, 0x80, 0x31, 0xC0, 0xF8, 0x80, 0x40, ++0x11, 0x60, 0xE8, 0xE7, 0x70, 0x47, 0x00, 0x24, 0x21, 0x46, 0x4F, 0xF0, 0x01, 0x0C, 0xB9, 0xE7, 0x0F, 0x48, 0x10, 0x4A, ++0xA7, 0xE7, 0x00, 0xBF, 0xA4, 0x25, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x68, 0x28, 0x17, 0x00, 0x08, 0x10, 0x04, 0x40, ++0x04, 0x10, 0x04, 0x40, 0x24, 0x10, 0x04, 0x40, 0x0C, 0x10, 0x04, 0x40, 0x00, 0x00, 0x10, 0x40, 0x14, 0x13, 0x17, 0x00, ++0x28, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, ++0x50, 0x97, 0x31, 0x00, 0x00, 0x75, 0x19, 0x03, 0x03, 0x4A, 0x13, 0x68, 0x1B, 0x03, 0xFC, 0xD4, 0x02, 0x4B, 0x18, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0x03, 0x4A, 0x13, 0x68, 0xDB, 0x07, 0xFC, 0xD5, ++0x02, 0x4B, 0x18, 0x68, 0xC0, 0xB2, 0x70, 0x47, 0x14, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0xF0, 0xB5, 0x03, 0x46, ++0xC3, 0xB0, 0xEF, 0xF3, 0x05, 0x85, 0x73, 0x4C, 0x22, 0x68, 0x12, 0x78, 0x02, 0x2A, 0x04, 0xD1, 0x71, 0x4A, 0xB2, 0xF8, ++0xAA, 0x20, 0x52, 0x04, 0x56, 0xD4, 0x00, 0x91, 0x00, 0x22, 0x4F, 0xF4, 0x80, 0x71, 0x02, 0xA8, 0x1D, 0xF0, 0x46, 0xFE, ++0x06, 0x46, 0x00, 0x2E, 0x31, 0xDD, 0x6B, 0x4B, 0x1B, 0x68, 0x1B, 0xB9, 0x6A, 0x4B, 0xD3, 0xF8, 0x28, 0x33, 0x98, 0x47, ++0x1D, 0xB9, 0x69, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x68, 0x4B, 0x1B, 0x68, 0x33, 0xB9, 0x67, 0x4A, 0x13, 0x68, ++0x1F, 0x03, 0xFC, 0xD4, 0x66, 0x4B, 0x5F, 0x22, 0x1A, 0x60, 0x5F, 0x4B, 0xB3, 0xF8, 0xAA, 0x30, 0x13, 0xF4, 0x80, 0x43, ++0x18, 0xD1, 0x02, 0xA9, 0x60, 0x4A, 0x61, 0x48, 0x77, 0x18, 0x4F, 0xF0, 0x0D, 0x0C, 0x11, 0xF8, 0x01, 0x4B, 0x0A, 0x2C, ++0x1C, 0xD0, 0x13, 0x68, 0x1B, 0x03, 0xFC, 0xD4, 0x04, 0x60, 0xB9, 0x42, 0x11, 0xF8, 0x01, 0x3C, 0xF3, 0xD1, 0x15, 0xB9, ++0x55, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x30, 0x46, 0x43, 0xB0, 0xF0, 0xBD, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x1C, 0xD0, ++0x02, 0x2B, 0xF2, 0xD1, 0x53, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xED, 0xD0, 0x00, 0x2D, 0xEF, 0xD1, 0x26, 0xE0, ++0x0D, 0x2B, 0xE0, 0xD0, 0x13, 0x68, 0x1C, 0x03, 0xFC, 0xD4, 0xC0, 0xF8, 0x00, 0xC0, 0x11, 0xF8, 0x01, 0x4C, 0xD8, 0xE7, ++0x00, 0x91, 0x00, 0x22, 0x4F, 0xF4, 0x80, 0x71, 0x03, 0xA8, 0x1D, 0xF0, 0xEF, 0xFD, 0x06, 0x46, 0xA7, 0xE7, 0x46, 0x4F, ++0x3B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xD2, 0xD0, 0x00, 0x2D, 0xD4, 0xD1, 0x43, 0x48, 0x1D, 0xF0, 0x07, 0xF9, 0x04, 0x28, ++0x62, 0xD8, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0xC8, 0xD1, 0x3B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xC4, 0xD0, 0x3E, 0x48, ++0x1D, 0xF0, 0xFA, 0xF8, 0x04, 0x28, 0xBF, 0xD9, 0x3B, 0x48, 0x3C, 0x4C, 0x1D, 0xF0, 0xB4, 0xF8, 0x42, 0xF2, 0x34, 0x03, ++0x13, 0x25, 0xE2, 0x5A, 0x8D, 0xF8, 0x08, 0x60, 0x00, 0x23, 0xB2, 0xF5, 0xC3, 0x7F, 0x02, 0xAF, 0x01, 0x46, 0x7D, 0x80, ++0x7B, 0x70, 0x4D, 0xD8, 0x55, 0x1C, 0xAD, 0xB2, 0xD3, 0x00, 0x33, 0x48, 0x8A, 0x81, 0xD0, 0xF8, 0x00, 0xC0, 0x0C, 0xEB, ++0x03, 0x00, 0x32, 0x1D, 0x47, 0x60, 0x2C, 0xF8, 0x03, 0x20, 0xC3, 0x78, 0x03, 0xF0, 0x31, 0x03, 0x43, 0xF0, 0x04, 0x03, ++0xC3, 0x70, 0x94, 0xF8, 0x02, 0x3C, 0x42, 0xF2, 0x34, 0x0C, 0x01, 0x33, 0x84, 0xF8, 0x02, 0x3C, 0x01, 0x27, 0x00, 0x23, ++0x24, 0xF8, 0x0C, 0x50, 0xC1, 0xE9, 0x01, 0x02, 0x8F, 0x73, 0x0B, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, ++0x72, 0xB6, 0x22, 0x4B, 0x1F, 0x60, 0x22, 0x4C, 0x22, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1D, 0xF0, 0x32, 0xF8, ++0x13, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x23, 0x68, 0x00, 0x2B, 0x3F, 0xF4, 0x76, 0xAF, 0x19, 0x4A, 0x01, 0x3B, ++0x12, 0x68, 0x23, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0x6F, 0xAF, 0x00, 0x2A, 0x3F, 0xF4, 0x6C, 0xAF, 0x62, 0xB6, 0x69, 0xE7, ++0x7C, 0x2E, 0x32, 0x46, 0xA8, 0xBF, 0x7C, 0x22, 0x92, 0xB2, 0x02, 0xA9, 0x13, 0x20, 0x02, 0xF0, 0xF9, 0xFA, 0x5F, 0xE7, ++0x1A, 0x46, 0x01, 0x25, 0xB1, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xA4, 0x25, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x40, 0x40, 0x04, 0x40, 0x68, 0x28, 0x17, 0x00, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, ++0x74, 0x36, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x0F, 0xB4, 0x00, 0xB5, 0x83, 0xB0, 0x04, 0xA9, ++0x05, 0x4B, 0x51, 0xF8, 0x04, 0x0B, 0xD3, 0xF8, 0x30, 0x34, 0x01, 0x91, 0x98, 0x47, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xEB, ++0x04, 0xB0, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x01, 0x22, 0x90, 0x42, 0x10, 0xB4, 0x02, 0xFA, 0x00, 0xF4, 0x11, 0xDD, ++0xA0, 0xF1, 0x08, 0x03, 0x93, 0x42, 0x0D, 0xD9, 0x0F, 0x28, 0x25, 0xDD, 0x1F, 0x28, 0x12, 0xDC, 0x15, 0x4A, 0x52, 0xF8, ++0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x43, 0xF0, 0x02, 0x03, 0x42, 0xF8, 0x20, 0x30, 0x08, 0xE0, 0x10, 0x4A, 0x52, 0xF8, ++0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x43, 0xF0, 0x01, 0x03, 0x42, 0xF8, 0x20, 0x30, 0x0D, 0x4B, 0x5A, 0x68, 0x22, 0x43, ++0x5A, 0x60, 0x9A, 0x68, 0x29, 0xB9, 0x22, 0xEA, 0x04, 0x02, 0x9A, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x22, 0x43, ++0x9A, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x03, 0x4A, 0x52, 0xF8, 0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x42, 0xF8, ++0x20, 0x30, 0xE6, 0xE7, 0x00, 0x30, 0x50, 0x40, 0x00, 0x40, 0x50, 0x40, 0x04, 0x49, 0x01, 0x22, 0x0B, 0x68, 0x02, 0xFA, ++0x00, 0xF0, 0x23, 0xEA, 0x00, 0x03, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x40, 0x50, 0x40, 0x10, 0xB5, 0x01, 0x29, ++0x82, 0xB0, 0x04, 0x46, 0x10, 0xD0, 0x20, 0xF0, 0x03, 0x03, 0x0F, 0x22, 0x9A, 0x40, 0x11, 0x46, 0x0D, 0x48, 0xFC, 0xF7, ++0x51, 0xF8, 0x01, 0x22, 0xA2, 0x40, 0x0C, 0x48, 0x11, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7, 0x48, 0xB8, ++0x01, 0xFA, 0x00, 0xF2, 0x11, 0x46, 0x07, 0x48, 0x01, 0x92, 0xFC, 0xF7, 0x41, 0xF8, 0x01, 0x9A, 0x05, 0x48, 0x11, 0x46, ++0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7, 0x39, 0xB8, 0x00, 0xBF, 0x2C, 0x10, 0x01, 0x50, 0x04, 0x10, 0x01, 0x50, ++0x08, 0x10, 0x01, 0x50, 0x01, 0x23, 0x03, 0xFA, 0x00, 0xF2, 0x11, 0x46, 0x01, 0x48, 0xFC, 0xF7, 0x2B, 0xB8, 0x00, 0xBF, ++0x00, 0x10, 0x01, 0x50, 0x01, 0x22, 0x82, 0x40, 0x00, 0x21, 0x01, 0x48, 0xFC, 0xF7, 0x22, 0xB8, 0x00, 0x10, 0x01, 0x50, ++0x10, 0xB5, 0x04, 0x46, 0x03, 0x48, 0xFB, 0xF7, 0xCB, 0xFF, 0xE0, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x10, 0xBD, 0x00, 0xBF, ++0x00, 0x10, 0x01, 0x50, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x0E, 0x48, 0x0F, 0x4A, ++0x03, 0x68, 0x0F, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x03, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, ++0x43, 0xF0, 0xC2, 0x03, 0x13, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x03, 0x60, 0x13, 0x68, ++0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0xC2, 0x20, 0x13, 0x60, 0xC8, 0x71, 0x70, 0x47, 0xAC, 0xB3, 0x33, 0x40, ++0xD4, 0xB3, 0x33, 0x40, 0x80, 0x35, 0x17, 0x00, 0x24, 0x4B, 0x25, 0x48, 0x1B, 0x68, 0x2D, 0xE9, 0xF0, 0x41, 0x24, 0x4D, ++0x24, 0x4F, 0x6A, 0x79, 0x95, 0xF9, 0x07, 0x10, 0x3C, 0x68, 0x23, 0x4E, 0x03, 0xF0, 0x0F, 0x03, 0x1A, 0x44, 0x52, 0xB2, ++0x89, 0x1A, 0x6F, 0xF0, 0x3D, 0x03, 0x99, 0x42, 0xB8, 0xBF, 0x19, 0x46, 0x5F, 0xFA, 0x81, 0xFC, 0x24, 0xF0, 0xFF, 0x04, ++0x44, 0xEA, 0x0C, 0x04, 0x3C, 0x60, 0x33, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xEA, 0x0C, 0x03, 0x33, 0x60, 0x3C, 0x68, ++0xCB, 0x1E, 0x5F, 0xFA, 0x83, 0xFC, 0x24, 0xF4, 0x7F, 0x24, 0x44, 0xEA, 0x0C, 0x34, 0x3C, 0x60, 0x33, 0x68, 0x23, 0xF4, ++0x7F, 0x23, 0x4C, 0xB2, 0x43, 0xEA, 0x0C, 0x33, 0x33, 0x60, 0x21, 0x46, 0xEC, 0x71, 0x1E, 0xF0, 0xC3, 0xF8, 0x3D, 0x34, ++0x0E, 0xDB, 0x0D, 0x4B, 0x29, 0x89, 0x1A, 0x69, 0x0C, 0x4B, 0x47, 0xF2, 0x30, 0x54, 0x05, 0xF1, 0x0C, 0x00, 0x04, 0xFB, ++0x01, 0x21, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x81, 0x1C, 0x01, 0x32, 0x40, ++0xB8, 0x7E, 0x15, 0x00, 0x80, 0x35, 0x17, 0x00, 0xAC, 0xB3, 0x33, 0x40, 0xD4, 0xB3, 0x33, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x12, 0x4A, 0x12, 0x68, 0xD2, 0xE9, 0x06, 0x01, 0x38, 0xB5, 0x11, 0x4B, 0x15, 0x6A, 0x18, 0x60, ++0x59, 0x60, 0x50, 0x6A, 0x0F, 0x4C, 0xD2, 0xE9, 0x0A, 0x12, 0xC3, 0xE9, 0x02, 0x50, 0xC3, 0xE9, 0x04, 0x12, 0xD4, 0xF8, ++0x2C, 0x33, 0x98, 0x47, 0xD4, 0xF8, 0xC0, 0x30, 0x98, 0x47, 0xFB, 0xF7, 0xAF, 0xFA, 0x09, 0x4B, 0x1B, 0x68, 0x1B, 0x78, ++0x03, 0x2B, 0x02, 0xD1, 0xD4, 0xF8, 0x20, 0x31, 0x98, 0x47, 0xBD, 0xE8, 0x38, 0x40, 0xFF, 0xF7, 0x79, 0xBB, 0x00, 0xBF, ++0xC8, 0x35, 0x17, 0x00, 0xB0, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x30, 0xB4, 0x08, 0x4B, ++0x08, 0x48, 0x18, 0x60, 0xC2, 0x25, 0x40, 0xF6, 0xEC, 0x20, 0x4F, 0xF4, 0x7A, 0x74, 0x06, 0x49, 0x06, 0x4A, 0xDD, 0x71, ++0x98, 0x80, 0x1C, 0x81, 0x19, 0x61, 0x30, 0xBC, 0x1A, 0x62, 0x70, 0x47, 0x80, 0x35, 0x17, 0x00, 0x01, 0x00, 0x00, 0x14, ++0x95, 0x64, 0x12, 0x00, 0x4D, 0x64, 0x12, 0x00, 0x90, 0xF8, 0x62, 0x30, 0xCB, 0xB9, 0x0D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x03, 0xDB, 0x00, 0x23, 0x84, 0xF8, 0xAC, 0x30, 0x10, 0xBD, 0x90, 0xF8, ++0xAC, 0x30, 0x01, 0x2B, 0xF7, 0xD0, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xE7, 0x12, 0x1E, 0xF0, 0xBB, 0xFA, 0x00, 0x23, ++0x84, 0xF8, 0xAC, 0x30, 0x10, 0xBD, 0x70, 0x47, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xCC, 0x7E, 0x15, 0x00, ++0x13, 0x4A, 0x90, 0xF8, 0x22, 0x30, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, ++0x1B, 0xD1, 0x0F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x08, 0xDB, 0x94, 0xF8, ++0x23, 0x10, 0x0B, 0x48, 0x1E, 0xF0, 0x1E, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x70, 0x32, 0x10, 0xBD, 0x90, 0xF8, 0x70, 0x32, ++0x01, 0x2B, 0xF2, 0xD0, 0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xF3, 0x12, 0x1E, 0xF0, 0x8A, 0xFA, 0xEB, 0xE7, 0x70, 0x47, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x10, 0x7F, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x7E, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x41, 0x90, 0xF8, 0x62, 0x40, 0x1C, 0xB9, 0x90, 0xF8, 0x64, 0x30, 0x06, 0x46, 0x0B, 0xB9, 0xBD, 0xE8, ++0xF0, 0x81, 0xD0, 0xE9, 0x24, 0x23, 0xD0, 0xF8, 0x98, 0x10, 0x42, 0x48, 0xDF, 0xF8, 0x30, 0x81, 0x1D, 0xF0, 0xF0, 0xFF, ++0x45, 0x46, 0x06, 0xF5, 0xB2, 0x77, 0x28, 0x46, 0x06, 0x22, 0x39, 0x46, 0x30, 0xF0, 0xD8, 0xFC, 0x14, 0x35, 0x40, 0xB1, ++0x01, 0x34, 0x05, 0x2C, 0xF5, 0xD1, 0x3A, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5B, 0xDB, 0x04, 0xEB, ++0x84, 0x03, 0x08, 0xEB, 0x83, 0x03, 0xA2, 0x00, 0xD9, 0x79, 0x00, 0x29, 0xD9, 0xD1, 0x1B, 0x7A, 0x03, 0xBB, 0xD6, 0xF8, ++0x90, 0x30, 0x31, 0x2B, 0x29, 0xD9, 0xD6, 0xF8, 0x94, 0x10, 0xB1, 0xEB, 0x53, 0x0F, 0x3B, 0xD8, 0x14, 0x44, 0x08, 0xEB, ++0x84, 0x08, 0x98, 0xF8, 0x06, 0x30, 0x00, 0x2B, 0x48, 0xD1, 0x00, 0x23, 0xC6, 0xE9, 0x24, 0x33, 0x29, 0x4A, 0xC6, 0xF8, ++0x98, 0x30, 0x12, 0x69, 0x28, 0x49, 0x29, 0x4B, 0x06, 0xF1, 0x9C, 0x00, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, ++0x11, 0x44, 0x18, 0x47, 0xD6, 0xF8, 0x98, 0x30, 0x53, 0xB3, 0xD6, 0xF8, 0x90, 0x30, 0x00, 0x2B, 0x37, 0xD0, 0x11, 0x19, ++0x08, 0xEB, 0x81, 0x01, 0x00, 0x20, 0x08, 0x72, 0xD3, 0xE7, 0x0B, 0x2B, 0x12, 0xD8, 0xD6, 0xF8, 0x98, 0x20, 0x14, 0x2A, ++0xDB, 0xD9, 0x00, 0x2B, 0xD9, 0xD1, 0x1B, 0x48, 0x1D, 0xF0, 0x9A, 0xFF, 0x18, 0x4B, 0x01, 0x22, 0x88, 0xF8, 0x06, 0x20, ++0x30, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xD6, 0xF8, 0x94, 0x10, 0x14, 0x4A, 0xA2, 0xFB, ++0x03, 0x02, 0x22, 0xF0, 0x03, 0x00, 0x00, 0xEB, 0x92, 0x02, 0x8A, 0x42, 0xE1, 0xD8, 0xE6, 0xE7, 0xD6, 0xF8, 0x90, 0x30, ++0xD5, 0xE7, 0x0F, 0x49, 0x0F, 0x48, 0x40, 0xF2, 0x13, 0x22, 0x1E, 0xF0, 0xF5, 0xF9, 0x9C, 0xE7, 0x00, 0x23, 0x0D, 0x48, ++0x88, 0xF8, 0x06, 0x30, 0x1D, 0xF0, 0x74, 0xFF, 0xAF, 0xE7, 0x0B, 0x48, 0xD4, 0xE7, 0x00, 0xBF, 0x1C, 0x7F, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x80, 0xC3, 0xC9, 0x01, 0x88, 0x1A, 0x17, 0x00, 0x44, 0x7F, 0x15, 0x00, ++0xAB, 0xAA, 0xAA, 0xAA, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x3C, 0x7F, 0x15, 0x00, 0x30, 0x7F, 0x15, 0x00, ++0xCC, 0x35, 0x17, 0x00, 0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, 0x01, 0xD0, 0x04, 0xF0, ++0xEF, 0xBC, 0x03, 0xF0, 0xD5, 0xBF, 0x00, 0xF0, 0xD7, 0xBF, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x46, ++0x00, 0xF0, 0x6C, 0xFE, 0x01, 0x20, 0x08, 0xBD, 0x70, 0xB5, 0x30, 0x4C, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x1E, 0xD0, ++0x02, 0x2B, 0x14, 0xD1, 0x2D, 0x4B, 0x2E, 0x49, 0x2E, 0x4A, 0xC3, 0xE9, 0x06, 0x12, 0x2E, 0x4D, 0xD5, 0xF8, 0x14, 0x31, ++0x98, 0x47, 0xD5, 0xF8, 0x18, 0x31, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x36, 0xD0, 0x02, 0x2B, 0x1D, 0xD0, ++0x03, 0x2B, 0x0E, 0xD0, 0x70, 0xBD, 0x03, 0x2B, 0xED, 0xD1, 0x22, 0x4B, 0x25, 0x49, 0x26, 0x4A, 0xC3, 0xE9, 0x08, 0x12, ++0xE7, 0xE7, 0x1F, 0x4B, 0x24, 0x49, 0x25, 0x4A, 0xC3, 0xE9, 0x02, 0x12, 0xE1, 0xE7, 0x24, 0x4B, 0x1B, 0x4C, 0x24, 0x4A, ++0x1A, 0x60, 0x04, 0xF0, 0x87, 0xFC, 0x23, 0x6A, 0x22, 0x48, 0x98, 0x47, 0x63, 0x6A, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, ++0x1D, 0x4B, 0x20, 0x49, 0x20, 0x4A, 0x19, 0x60, 0x13, 0x4D, 0x42, 0xF2, 0x34, 0x03, 0x00, 0x21, 0xD1, 0x52, 0x04, 0xF0, ++0x1B, 0xF8, 0x03, 0xF0, 0x35, 0xFF, 0xAB, 0x69, 0x18, 0x48, 0x98, 0x47, 0xEB, 0x69, 0x98, 0x47, 0x04, 0xF0, 0x1A, 0xFC, ++0x23, 0x68, 0x1B, 0x78, 0xCA, 0xE7, 0x12, 0x4B, 0x09, 0x4D, 0x16, 0x4A, 0x1A, 0x60, 0x00, 0xF0, 0xCB, 0xFE, 0x00, 0xF0, ++0xE9, 0xFE, 0x00, 0xF0, 0x13, 0xFF, 0xAB, 0x68, 0x0E, 0x48, 0x98, 0x47, 0xEB, 0x68, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, ++0xB6, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x28, 0x58, 0x17, 0x00, 0xA1, 0xA9, 0x12, 0x00, 0x85, 0xA9, 0x12, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x3D, 0xB2, 0x12, 0x00, 0x29, 0xB2, 0x12, 0x00, 0x0D, 0x7A, 0x12, 0x00, 0xF9, 0x79, 0x12, 0x00, ++0x1C, 0x58, 0x17, 0x00, 0xBC, 0x60, 0x17, 0x00, 0xB8, 0x7F, 0x15, 0x00, 0xA4, 0x60, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x28, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x0B, 0x4C, 0x50, 0x22, 0x51, 0x23, 0x04, 0xF2, 0x14, 0x50, 0xA4, 0xF8, 0x10, 0x25, ++0x84, 0xF8, 0x12, 0x35, 0x1C, 0xF0, 0xD8, 0xFC, 0x27, 0x22, 0x28, 0x23, 0x04, 0xF5, 0xF4, 0x60, 0xA4, 0xF8, 0x9C, 0x27, ++0x84, 0xF8, 0x9E, 0x37, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0xF0, 0xCC, 0xBC, 0x58, 0x58, 0x17, 0x00, 0x70, 0xB5, 0x41, 0xF6, ++0x10, 0x02, 0x25, 0x4D, 0x25, 0x4C, 0x4C, 0xF2, 0xBF, 0x03, 0x41, 0xF6, 0x12, 0x00, 0x00, 0x26, 0xAB, 0x52, 0x41, 0xF6, ++0x14, 0x01, 0x05, 0xF5, 0xC1, 0x52, 0xA5, 0xF8, 0x00, 0x3C, 0x2E, 0x54, 0x05, 0xF6, 0x08, 0x40, 0x6E, 0x50, 0x16, 0x70, ++0x85, 0xF8, 0x02, 0x6C, 0xC5, 0xF8, 0x04, 0x6C, 0x1C, 0xF0, 0xAE, 0xFC, 0xA4, 0xF1, 0x0C, 0x00, 0x1C, 0xF0, 0xAA, 0xFC, ++0x04, 0xF5, 0x00, 0x60, 0x1C, 0xF0, 0xA6, 0xFC, 0x04, 0xF6, 0x08, 0x00, 0x1C, 0xF0, 0xA2, 0xFC, 0x42, 0xF2, 0x34, 0x03, ++0x31, 0x46, 0x4F, 0xF4, 0x00, 0x62, 0x20, 0x46, 0xEE, 0x52, 0x85, 0xF8, 0x02, 0x6C, 0xC5, 0xF8, 0x04, 0x6C, 0xF9, 0xF7, ++0x05, 0xFC, 0x04, 0xF5, 0x00, 0x65, 0x2E, 0x46, 0x21, 0x46, 0x30, 0x46, 0x10, 0x34, 0x1C, 0xF0, 0x91, 0xFC, 0xAC, 0x42, ++0xF8, 0xD1, 0x09, 0x4A, 0x00, 0x21, 0x02, 0xF5, 0xB4, 0x70, 0xA2, 0xF1, 0x24, 0x03, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, ++0xFB, 0xD1, 0x03, 0xF1, 0x24, 0x02, 0x82, 0x42, 0xF5, 0xD1, 0x70, 0xBD, 0x7C, 0x36, 0x17, 0x00, 0xA0, 0x4E, 0x17, 0x00, ++0xD8, 0x56, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x40, 0x20, 0x85, 0xB0, 0x1C, 0xF0, 0xF6, 0xFB, 0xA7, 0x4B, 0x9B, 0x68, ++0x03, 0x93, 0x00, 0x2B, 0x00, 0xF0, 0x80, 0x81, 0xDF, 0xF8, 0xB0, 0x92, 0xDF, 0xF8, 0xB0, 0xB2, 0x09, 0xE0, 0x94, 0xF8, ++0x64, 0x30, 0x63, 0xB1, 0x03, 0x9B, 0x1B, 0x68, 0x03, 0x93, 0x03, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0x71, 0x81, 0x03, 0x9C, ++0x20, 0x46, 0x07, 0xF0, 0x33, 0xFF, 0x00, 0x28, 0xEF, 0xD0, 0x03, 0x9B, 0x9A, 0x4C, 0x03, 0xF5, 0xA3, 0x65, 0x01, 0x26, ++0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0x60, 0x23, 0x68, 0x28, 0x46, 0x01, 0x33, ++0x23, 0x60, 0x1C, 0xF0, 0x8B, 0xFC, 0x23, 0x68, 0x5A, 0x1E, 0x2B, 0xB1, 0xD9, 0xF8, 0x00, 0x30, 0x22, 0x60, 0x0A, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x05, 0x21, 0x38, 0xB1, 0xDB, 0xF8, 0x24, 0x34, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, ++0xE7, 0xD4, 0xE3, 0xE7, 0x89, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0xC8, 0xD1, 0xDD, 0xF8, 0x0C, 0xA0, 0x87, 0x4E, ++0x04, 0x23, 0x01, 0x93, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, 0x00, 0xF0, 0x8C, 0x80, 0x9D, 0xF8, 0x04, 0x70, 0x0A, 0xF5, ++0xA2, 0x68, 0x40, 0x46, 0x1C, 0xF0, 0x62, 0xFC, 0x80, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, ++0x43, 0x7F, 0x7F, 0xDB, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x62, 0x92, 0xF8, 0x25, 0x10, 0x19, 0xB9, 0xE9, 0x8B, ++0x08, 0x07, 0x40, 0xF1, 0x07, 0x81, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x62, 0x92, 0xF8, 0x24, 0x20, 0x01, 0x2A, ++0x00, 0xF0, 0x9E, 0x80, 0xDB, 0xF8, 0x24, 0x34, 0x28, 0x46, 0x39, 0x46, 0x98, 0x47, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, ++0xD7, 0xD1, 0x0A, 0xF5, 0x9D, 0x65, 0xA8, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, ++0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0xDA, 0xF8, 0xE8, 0x14, 0x5A, 0x1C, 0x22, 0x60, 0x2A, 0xB1, 0xD9, 0xF8, 0x00, 0x20, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x00, 0x29, 0x34, 0xD0, 0x4A, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x02, 0x63, 0x93, 0xF8, 0x25, 0x00, 0x00, 0x28, 0x00, 0xF0, 0x87, 0x80, 0x93, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x46, 0xD0, ++0xC9, 0x7E, 0xDB, 0xF8, 0x34, 0x31, 0x10, 0x46, 0x98, 0x47, 0x00, 0x28, 0x00, 0xF0, 0xD7, 0x80, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x40, 0x46, 0x01, 0x33, 0x23, 0x60, ++0x1C, 0xF0, 0x00, 0xFC, 0x23, 0x68, 0x05, 0x46, 0x33, 0xB1, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0xDB, 0xF8, 0x24, 0x34, 0x39, 0x46, 0x28, 0x46, 0x98, 0x47, 0x00, 0x2D, 0xB4, 0xD1, 0x01, 0x9B, ++0x01, 0x3B, 0x1D, 0x46, 0x38, 0x46, 0x01, 0x93, 0x0B, 0xF0, 0x26, 0xFA, 0x2B, 0x46, 0x01, 0x33, 0xAA, 0xF1, 0x08, 0x0A, ++0x3F, 0xF4, 0x38, 0xAF, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, 0x7F, 0xF4, 0x74, 0xAF, 0x9D, 0xF8, 0x04, 0x70, 0x9C, 0xE7, ++0x09, 0x2B, 0x7F, 0xF6, 0x7D, 0xAF, 0x3C, 0x49, 0x3C, 0x48, 0x4F, 0xF4, 0x96, 0x72, 0x1D, 0xF0, 0xE1, 0xFF, 0x6B, 0x7F, ++0x74, 0xE7, 0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x02, 0x92, ++0x01, 0x33, 0x40, 0x46, 0x23, 0x60, 0x1C, 0xF0, 0xC1, 0xFB, 0x23, 0x68, 0x02, 0x9A, 0x05, 0x46, 0x33, 0xB1, 0x01, 0x3B, ++0xD9, 0xF8, 0x00, 0x10, 0x23, 0x60, 0x0B, 0xB9, 0x01, 0xB1, 0x62, 0xB6, 0x01, 0x9B, 0x4F, 0x20, 0x00, 0xFB, 0x02, 0x30, ++0x41, 0x30, 0x06, 0xEB, 0xC0, 0x00, 0x29, 0x46, 0x1C, 0xF0, 0x68, 0xFB, 0x00, 0x2D, 0x7F, 0xF4, 0x6F, 0xAF, 0xB8, 0xE7, ++0x23, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x4D, 0xDB, 0xEA, 0x8B, 0xD2, 0x07, 0x7F, 0xF5, 0x5D, 0xAF, ++0x01, 0x9A, 0x4F, 0x20, 0x46, 0x32, 0x10, 0xFB, 0x03, 0x20, 0x29, 0x46, 0x06, 0xEB, 0xC0, 0x00, 0x1C, 0xF0, 0x50, 0xFB, ++0x51, 0xE7, 0x93, 0xF8, 0x23, 0x10, 0x1B, 0x48, 0x1D, 0xF0, 0x24, 0xFD, 0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x01, 0x23, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x40, 0x46, 0x01, 0x33, 0x23, 0x60, 0x1C, 0xF0, 0x80, 0xFB, ++0x4F, 0xF0, 0x00, 0x42, 0x39, 0x46, 0x05, 0x46, 0x28, 0xF0, 0x2A, 0xFE, 0x23, 0x68, 0x00, 0x2B, 0x85, 0xD0, 0x01, 0x3B, ++0xD9, 0xF8, 0x00, 0x20, 0x23, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0x7F, 0xAF, 0x00, 0x2A, 0x3F, 0xF4, 0x7C, 0xAF, 0x62, 0xB6, ++0x00, 0x2D, 0x7F, 0xF4, 0x2F, 0xAF, 0x78, 0xE7, 0x00, 0x88, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x50, 0x7F, 0x15, 0x00, 0x7C, 0x7F, 0x15, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xEA, 0x8B, 0xD1, 0x07, 0xB2, 0xD4, 0x11, 0x49, 0x11, 0x48, 0x02, 0x93, ++0x40, 0xF2, 0x35, 0x12, 0x1D, 0xF0, 0x5A, 0xFF, 0x02, 0x9B, 0xA5, 0xE7, 0x92, 0xF8, 0x23, 0x10, 0x0D, 0x48, 0x1D, 0xF0, ++0xD9, 0xFC, 0x28, 0x46, 0x4F, 0xF0, 0x00, 0x42, 0x39, 0x46, 0x28, 0xF0, 0xED, 0xFD, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, ++0x7F, 0xF4, 0xD3, 0xAE, 0xF9, 0xE6, 0x07, 0x4A, 0x01, 0x23, 0x82, 0xF8, 0x00, 0x32, 0x42, 0xE7, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0x8C, 0x7F, 0x15, 0x00, 0x7C, 0x7F, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, 0x07, 0xD0, 0x06, 0x4B, 0xD3, 0xF8, 0x30, 0x31, ++0x18, 0x47, 0x04, 0x4B, 0xD3, 0xF8, 0x08, 0x33, 0x18, 0x47, 0x03, 0xF0, 0x8F, 0xBF, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x03, 0xD1, 0x06, 0x4B, ++0xD3, 0xF8, 0x34, 0x34, 0x18, 0x47, 0x04, 0xF0, 0x93, 0xBB, 0x03, 0x4B, 0xD3, 0xF8, 0x00, 0x33, 0x18, 0x47, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x07, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, ++0x01, 0xD0, 0x04, 0xF0, 0x83, 0xBB, 0x04, 0xF0, 0x7B, 0xB8, 0x03, 0x4B, 0xD3, 0xF8, 0x0C, 0x33, 0x18, 0x47, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, ++0x03, 0xD1, 0x06, 0x4B, 0xD3, 0xF8, 0x38, 0x34, 0x18, 0x47, 0x04, 0xF0, 0x6D, 0xBB, 0x03, 0x4B, 0xD3, 0xF8, 0x04, 0x33, ++0x18, 0x47, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, ++0x05, 0xD0, 0x02, 0x2B, 0x01, 0xD0, 0x04, 0xF0, 0x5D, 0xBB, 0x04, 0xF0, 0xAD, 0xB9, 0x01, 0xF0, 0x6B, 0xB9, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x08, 0xB5, 0x0C, 0x22, 0x08, 0x23, 0x01, 0x21, 0x40, 0xF2, 0x0D, 0x40, 0x1B, 0xF0, 0xE6, 0xFD, ++0xBD, 0xE8, 0x08, 0x40, 0x1B, 0xF0, 0x12, 0xBE, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x82, 0x46, 0x00, 0x68, 0x05, 0x91, ++0x03, 0x90, 0x07, 0x92, 0x62, 0xB1, 0xB0, 0xFB, 0xF2, 0xF3, 0x11, 0x46, 0x02, 0xFB, 0x13, 0x02, 0x0B, 0x46, 0x00, 0x2A, ++0x40, 0xF0, 0xDE, 0x80, 0x03, 0x9A, 0x04, 0x3B, 0x1A, 0x44, 0x03, 0x92, 0x9A, 0xF8, 0x08, 0x30, 0x00, 0x2B, 0x00, 0xF0, ++0xD2, 0x80, 0x00, 0x23, 0xDF, 0xF8, 0xC0, 0x81, 0xDF, 0xF8, 0xC0, 0x91, 0x00, 0x93, 0x1F, 0x46, 0xD3, 0x46, 0x08, 0xE0, ++0x00, 0x9B, 0x9B, 0xF8, 0x08, 0x20, 0x01, 0x33, 0xDF, 0xB2, 0xBA, 0x42, 0x00, 0x93, 0x40, 0xF2, 0xC0, 0x80, 0x05, 0x9B, ++0xDB, 0xF8, 0x0C, 0x10, 0x33, 0xF8, 0x27, 0x00, 0x03, 0xEB, 0x87, 0x02, 0x00, 0x24, 0x55, 0x88, 0x07, 0xEB, 0x47, 0x02, ++0x01, 0xEB, 0x82, 0x06, 0x41, 0xF8, 0x22, 0x40, 0xB4, 0x80, 0x00, 0x2D, 0xE4, 0xD0, 0x03, 0x1D, 0x01, 0x93, 0x03, 0x9B, ++0x75, 0x80, 0x03, 0xF1, 0x04, 0x0A, 0x02, 0x95, 0xB0, 0x80, 0x55, 0x46, 0xCD, 0xF8, 0x18, 0xB0, 0xA2, 0x46, 0x04, 0x97, ++0x34, 0xE0, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x37, 0xD3, 0x04, 0x9B, 0x05, 0xF8, 0x04, 0x3C, 0xD8, 0xF8, ++0x00, 0x30, 0xAB, 0x42, 0x41, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x3C, 0xD3, 0x55, 0x23, 0x05, 0xF8, ++0x03, 0x3C, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x46, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x41, 0xD3, ++0x00, 0x23, 0x05, 0xF8, 0x02, 0x3C, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x4B, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, ++0xAB, 0x42, 0x46, 0xD3, 0xCB, 0xF8, 0x04, 0x70, 0x33, 0x88, 0x01, 0x99, 0x01, 0x33, 0x01, 0x34, 0x33, 0x80, 0x02, 0x9B, ++0xA2, 0xB2, 0x93, 0x42, 0x0D, 0x44, 0x48, 0xD9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x57, 0x46, 0xA5, 0xF1, 0x04, 0x0B, ++0xAA, 0x46, 0xC2, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, ++0xBE, 0xD2, 0x31, 0x48, 0x29, 0x46, 0xFF, 0xF7, 0xE9, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0xBD, 0xD9, 0xD9, 0xF8, ++0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0xB9, 0xD2, 0x29, 0x48, 0x29, 0x46, ++0xFF, 0xF7, 0xD8, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0xB8, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, ++0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0xB4, 0xD2, 0x22, 0x48, 0x29, 0x46, 0xFF, 0xF7, 0xC7, 0xF9, 0xD8, 0xF8, ++0x00, 0x30, 0xAB, 0x42, 0xB3, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, ++0xAB, 0x42, 0xAF, 0xD2, 0x29, 0x46, 0x1A, 0x48, 0xFF, 0xF7, 0xB6, 0xF9, 0xAC, 0xE7, 0x0A, 0x46, 0x5D, 0x1E, 0x03, 0x99, ++0xDD, 0xF8, 0x18, 0xB0, 0xAD, 0xB2, 0x05, 0xFB, 0x02, 0x13, 0x05, 0xFB, 0x02, 0x25, 0x48, 0x19, 0x07, 0x99, 0x03, 0x90, ++0x04, 0x33, 0xB3, 0x60, 0x00, 0x29, 0x3F, 0xF4, 0x47, 0xAF, 0xB0, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, 0x13, 0x02, 0x0B, 0x46, ++0x22, 0xB1, 0x8B, 0x1A, 0x03, 0x2B, 0x9C, 0xBF, 0x0A, 0x46, 0x9B, 0x18, 0x03, 0x9A, 0x04, 0x3B, 0x1A, 0x44, 0x03, 0x92, ++0x36, 0xE7, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x8B, 0x1A, 0x03, 0x2B, 0x9C, 0xBF, 0x0A, 0x46, 0x9B, 0x18, 0x1B, 0xE7, ++0xE0, 0x7F, 0x15, 0x00, 0x10, 0x80, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, 0x64, 0x80, 0x15, 0x00, 0xC8, 0x25, 0x17, 0x00, ++0xE4, 0x25, 0x17, 0x00, 0xF8, 0xB5, 0x06, 0x7A, 0x00, 0x2E, 0x00, 0xF0, 0xBC, 0x80, 0xC5, 0x68, 0x00, 0x2D, 0x00, 0xF0, ++0x82, 0x80, 0x2C, 0x46, 0x01, 0x23, 0x09, 0xE0, 0x22, 0x88, 0xA2, 0xB9, 0x9E, 0x42, 0x0F, 0xD9, 0x03, 0xEB, 0x43, 0x04, ++0x05, 0xEB, 0x84, 0x04, 0x01, 0x33, 0xDB, 0xB2, 0xA0, 0x88, 0x88, 0x42, 0x03, 0xEB, 0x43, 0x02, 0xF0, 0xD2, 0x9E, 0x42, ++0x02, 0xD9, 0x05, 0xEB, 0x82, 0x04, 0xF3, 0xE7, 0x9E, 0x42, 0x00, 0xF0, 0x9E, 0x80, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x4E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x4E, 0x4E, 0x23, 0x88, 0x35, 0x68, 0x6A, 0x1C, 0x32, 0x60, ++0x00, 0x2B, 0x5D, 0xD0, 0x4B, 0x4F, 0xA5, 0x68, 0x3A, 0x68, 0xAA, 0x42, 0x28, 0xD8, 0x79, 0x68, 0x11, 0x44, 0x8D, 0x42, ++0x24, 0xD8, 0x29, 0x68, 0xA1, 0x60, 0x01, 0x3B, 0xAA, 0x42, 0x23, 0x80, 0x32, 0xD8, 0x7B, 0x68, 0x13, 0x44, 0xAB, 0x42, ++0x2E, 0xD3, 0x15, 0xF8, 0x03, 0x1C, 0x55, 0x29, 0x53, 0xD1, 0xAA, 0x23, 0x05, 0xF8, 0x03, 0x3C, 0x3B, 0x68, 0x9D, 0x42, ++0x5D, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9D, 0x42, 0x59, 0xD8, 0x01, 0x23, 0x05, 0xF8, 0x02, 0x3C, 0x33, 0x68, 0x00, 0x2B, ++0x34, 0xD0, 0x36, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x7B, 0xBB, 0x72, 0xB3, 0x35, 0xE0, 0x35, 0x48, 0x01, 0x68, ++0x8D, 0x42, 0x03, 0xD3, 0x40, 0x68, 0x01, 0x44, 0x8D, 0x42, 0xD2, 0xD9, 0x29, 0x46, 0x32, 0x48, 0xFF, 0xF7, 0x12, 0xF9, ++0x23, 0x88, 0x3A, 0x68, 0x00, 0x21, 0x01, 0x3B, 0xAA, 0x42, 0xA1, 0x60, 0x23, 0x80, 0xCC, 0xD9, 0x2B, 0x48, 0x03, 0x68, ++0xAB, 0x42, 0x1F, 0xD8, 0x41, 0x68, 0x19, 0x44, 0xA9, 0x42, 0x1B, 0xD3, 0x15, 0xF8, 0x03, 0x1C, 0x55, 0x29, 0x1C, 0xD1, ++0xAA, 0x42, 0x37, 0xD9, 0x42, 0x68, 0x13, 0x44, 0x9D, 0x42, 0xC2, 0xD9, 0x29, 0x46, 0x24, 0x48, 0xFF, 0xF7, 0xF4, 0xF8, ++0xC0, 0xE7, 0x23, 0x48, 0xFF, 0xF7, 0xF0, 0xF8, 0x28, 0x46, 0xF8, 0xBD, 0xC2, 0xB1, 0x1A, 0x4B, 0x35, 0x60, 0x1B, 0x68, ++0xA5, 0xB9, 0x9B, 0xB1, 0x62, 0xB6, 0xF5, 0xE7, 0x29, 0x46, 0x1D, 0x48, 0xFF, 0xF7, 0xE2, 0xF8, 0x00, 0x21, 0x33, 0x68, ++0x33, 0xB1, 0x13, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x17, 0x48, 0x2A, 0x46, ++0xFF, 0xF7, 0xD4, 0xF8, 0x00, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x0F, 0x4A, 0x13, 0x68, 0x9D, 0x42, 0x03, 0xD3, 0x52, 0x68, ++0x13, 0x44, 0x9D, 0x42, 0x9D, 0xD9, 0x29, 0x46, 0x10, 0x48, 0xFF, 0xF7, 0xC5, 0xF8, 0x9B, 0xE7, 0x79, 0x68, 0x0A, 0x44, ++0x95, 0x42, 0x8A, 0xD9, 0x9D, 0x42, 0xC5, 0xD3, 0xC0, 0xE7, 0x0C, 0x48, 0xFF, 0xF7, 0xBA, 0xF8, 0x00, 0x25, 0xC7, 0xE7, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xCC, 0x80, 0x15, 0x00, ++0x10, 0x80, 0x15, 0x00, 0x98, 0x80, 0x15, 0x00, 0x00, 0x81, 0x15, 0x00, 0x28, 0x81, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, ++0xB4, 0x80, 0x15, 0x00, 0x00, 0x29, 0x00, 0xF0, 0x0F, 0x81, 0x2D, 0xE9, 0xF8, 0x43, 0x03, 0x68, 0x8B, 0x42, 0x05, 0x46, ++0x0C, 0x46, 0x59, 0xD8, 0x42, 0x68, 0x13, 0x44, 0x99, 0x42, 0x55, 0xD8, 0x83, 0x4F, 0x3B, 0x68, 0x99, 0x42, 0x55, 0xD3, ++0x7A, 0x68, 0x13, 0x44, 0x99, 0x42, 0x51, 0xD8, 0x14, 0xF8, 0x04, 0x6C, 0x2B, 0x7A, 0xB3, 0x42, 0x48, 0xD9, 0xD5, 0xF8, ++0x0C, 0x80, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x7A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x7A, 0x4D, ++0x38, 0x68, 0x2B, 0x68, 0x84, 0x42, 0x03, 0xF1, 0x01, 0x03, 0x2B, 0x60, 0x25, 0xD3, 0x7B, 0x68, 0x03, 0x44, 0x9C, 0x42, ++0x21, 0xD8, 0x14, 0xF8, 0x03, 0x9C, 0xB9, 0xF1, 0xAA, 0x0F, 0x00, 0xF0, 0xAB, 0x80, 0xB9, 0xF1, 0xFF, 0x0F, 0x20, 0xD1, ++0x7B, 0x68, 0x18, 0x44, 0x84, 0x42, 0x00, 0xF2, 0xA1, 0x80, 0x14, 0xF8, 0x02, 0x0C, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0xF8, ++0x02, 0x0C, 0x00, 0x28, 0x47, 0xD0, 0x2B, 0x68, 0x33, 0xB1, 0x67, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x40, 0xB2, 0xBD, 0xE8, 0xF8, 0x83, 0x64, 0x4B, 0x1A, 0x68, 0x94, 0x42, 0x1E, 0xD2, 0x63, 0x48, ++0x21, 0x46, 0xFF, 0xF7, 0x47, 0xF8, 0x2B, 0x68, 0x33, 0xB1, 0x5D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x4F, 0xF0, 0xFF, 0x30, 0xBD, 0xE8, 0xF8, 0x83, 0x59, 0x4B, 0x1A, 0x68, 0x94, 0x42, 0x03, 0xD3, ++0x5B, 0x68, 0x1A, 0x44, 0x94, 0x42, 0xA5, 0xD9, 0x57, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0x2E, 0xF8, 0x00, 0x26, 0xA1, 0xE7, ++0x59, 0x68, 0x11, 0x44, 0x8C, 0x42, 0xDC, 0xD8, 0x14, 0xF8, 0x03, 0x9C, 0xB9, 0xF1, 0xAA, 0x0F, 0x6C, 0xD0, 0xB9, 0xF1, ++0xFF, 0x0F, 0xD8, 0xD1, 0x84, 0x42, 0xB5, 0xD2, 0x1A, 0x68, 0x94, 0x42, 0x03, 0xD3, 0x5B, 0x68, 0x1A, 0x44, 0x94, 0x42, ++0xB3, 0xD9, 0x4B, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0x13, 0xF8, 0xB9, 0xF1, 0xFF, 0x0F, 0x5D, 0xD0, 0x06, 0xEB, 0x46, 0x06, ++0x08, 0xEB, 0x86, 0x09, 0x38, 0xF8, 0x26, 0x20, 0xB9, 0xF8, 0x02, 0x30, 0x9A, 0x42, 0x4F, 0xEA, 0x86, 0x06, 0xBC, 0xD2, ++0x3B, 0x68, 0x9C, 0x42, 0x31, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x2D, 0xD8, 0x55, 0x23, 0x04, 0xF8, 0x03, 0x3C, ++0x3B, 0x68, 0x9C, 0x42, 0x1A, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x16, 0xD8, 0xD9, 0xF8, 0x08, 0x30, 0x23, 0x60, ++0x38, 0xF8, 0x06, 0x30, 0x28, 0x68, 0xC9, 0xF8, 0x08, 0x40, 0x01, 0x33, 0x28, 0xF8, 0x06, 0x30, 0x38, 0xB1, 0x2E, 0x4B, ++0x01, 0x38, 0x1B, 0x68, 0x28, 0x60, 0x10, 0xB9, 0x0B, 0xB1, 0x62, 0xB6, 0xA2, 0xE7, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, ++0x2A, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, 0xE0, 0xD9, 0x21, 0x46, 0x2A, 0x48, ++0xFE, 0xF7, 0xD0, 0xFF, 0xDE, 0xE7, 0x24, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, ++0xC9, 0xD9, 0x21, 0x46, 0x24, 0x48, 0xFE, 0xF7, 0xC3, 0xFF, 0xC7, 0xE7, 0x1D, 0x4B, 0xA1, 0xE7, 0x14, 0xF8, 0x02, 0x0C, ++0x01, 0x38, 0xC0, 0xB2, 0x04, 0xF8, 0x02, 0x0C, 0x00, 0x28, 0x7F, 0xF4, 0x5C, 0xAF, 0xA5, 0xE7, 0x84, 0x42, 0xBF, 0xF4, ++0x4B, 0xAF, 0x96, 0xE7, 0x3B, 0x68, 0x9C, 0x42, 0x11, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x0D, 0xD8, 0x01, 0x23, ++0x04, 0xF8, 0x02, 0x3C, 0x2B, 0x68, 0x33, 0xB1, 0x0D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x01, 0x20, 0x60, 0xE7, 0x0B, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, ++0xE9, 0xD9, 0x21, 0x46, 0x0C, 0x48, 0xFE, 0xF7, 0x91, 0xFF, 0xE7, 0xE7, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0x47, 0x00, 0xBF, ++0xC8, 0x25, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x00, 0x81, 0x15, 0x00, ++0x50, 0x81, 0x15, 0x00, 0x80, 0x81, 0x15, 0x00, 0x64, 0x80, 0x15, 0x00, 0x10, 0x80, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, ++0x0B, 0x4A, 0x13, 0x68, 0x83, 0x42, 0x05, 0xD8, 0x52, 0x68, 0x13, 0x44, 0x98, 0x42, 0x01, 0xD8, 0x01, 0x20, 0x70, 0x47, ++0x07, 0x4A, 0x13, 0x68, 0x98, 0x42, 0x06, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x98, 0x42, 0x8C, 0xBF, 0x00, 0x20, 0x01, 0x20, ++0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0xC8, 0x25, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x10, 0x4B, 0x70, 0xB5, ++0x10, 0x4C, 0xDC, 0x60, 0x15, 0x46, 0x0E, 0x46, 0x03, 0x24, 0x01, 0x46, 0x20, 0x22, 0x18, 0x46, 0x5D, 0x60, 0x1C, 0x72, ++0x1E, 0x60, 0xFF, 0xF7, 0xCD, 0xFC, 0x0B, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x01, 0x21, 0x4F, 0xF0, 0x02, 0x15, 0x04, 0x24, ++0x4F, 0xF4, 0x80, 0x20, 0x5A, 0x60, 0x00, 0x22, 0xC3, 0xE9, 0x05, 0x40, 0xDD, 0x60, 0x19, 0x60, 0x99, 0x60, 0x1A, 0x61, ++0x9A, 0x83, 0x70, 0xBD, 0xE4, 0x25, 0x17, 0x00, 0xF4, 0x25, 0x17, 0x00, 0xA8, 0x25, 0x17, 0x00, 0x38, 0xB5, 0x0F, 0x4B, ++0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0x46, 0x0D, 0xD0, 0x0D, 0x48, 0x7C, 0x21, 0xFF, 0xF7, 0xAB, 0xFD, 0x04, 0x46, ++0x2C, 0xB1, 0x20, 0x46, 0xFF, 0xF7, 0xAC, 0xFF, 0x38, 0xB1, 0x04, 0xF8, 0x01, 0x5C, 0x20, 0x46, 0x38, 0xBD, 0x00, 0xF0, ++0xC3, 0xF9, 0x04, 0x46, 0xF2, 0xE7, 0x21, 0x46, 0x04, 0x48, 0xFE, 0xF7, 0x17, 0xFF, 0x20, 0x46, 0x38, 0xBD, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xAC, 0x81, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0xFF, 0xF7, 0x92, 0xFF, ++0x98, 0xB1, 0x31, 0x4B, 0x14, 0xF8, 0x04, 0x2C, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x23, 0xD0, 0x02, 0x2B, 0x2A, 0xD0, ++0x03, 0x2B, 0x15, 0xD1, 0x2C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x30, 0xDB, 0x02, 0x2A, 0x30, 0xD0, ++0x10, 0xBD, 0x29, 0x48, 0x21, 0x46, 0xFE, 0xF7, 0xF1, 0xFE, 0x25, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x11, 0xD0, ++0x02, 0x2B, 0x18, 0xD0, 0x03, 0x2B, 0x29, 0xD0, 0x20, 0x46, 0xFF, 0xF7, 0x6D, 0xFF, 0x90, 0xB3, 0x21, 0x46, 0x21, 0x48, ++0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x3C, 0xBE, 0x02, 0x2A, 0x0F, 0xD0, 0x00, 0x2A, 0xE3, 0xD1, 0x20, 0x46, 0xBD, 0xE8, ++0x10, 0x40, 0x00, 0xF0, 0x9B, 0xB9, 0x02, 0x2A, 0x26, 0xD0, 0x00, 0x2A, 0xDA, 0xD1, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, ++0x03, 0xF0, 0xF2, 0xB9, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x45, 0xB9, 0x02, 0x2A, 0x0C, 0xD1, 0x13, 0x4B, ++0x20, 0x46, 0xD3, 0xF8, 0xE8, 0x34, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC1, 0xDA, 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x49, 0x0D, 0x48, 0xBE, 0x22, 0x1D, 0xF0, 0xF5, 0xBA, 0x21, 0x46, ++0x0B, 0x48, 0xFE, 0xF7, 0xAD, 0xFE, 0xC7, 0xE7, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x03, 0xF0, 0x21, 0xB9, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x50, 0x81, 0x15, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xD4, 0x81, 0x15, 0x00, 0xE4, 0x81, 0x15, 0x00, 0x30, 0xB5, 0x1A, 0x4C, 0x1A, 0x4A, 0x23, 0x68, ++0x1A, 0x48, 0x5D, 0x88, 0x99, 0x88, 0xB2, 0xF8, 0xD4, 0x20, 0x85, 0xB0, 0x04, 0x3A, 0xAD, 0xF8, 0x02, 0x50, 0xDD, 0x88, ++0xAD, 0xF8, 0x06, 0x10, 0x19, 0x89, 0xAD, 0xF8, 0x0A, 0x50, 0xD3, 0xE9, 0x05, 0x35, 0xAD, 0xF8, 0x0E, 0x10, 0x01, 0x21, ++0x03, 0x60, 0x01, 0x72, 0x10, 0x4B, 0x45, 0x60, 0x0C, 0x21, 0xC3, 0x60, 0xAD, 0xF8, 0x0C, 0x20, 0x40, 0xF2, 0x3C, 0x63, ++0xAD, 0xF8, 0x00, 0x10, 0x7C, 0x25, 0x69, 0x46, 0x20, 0x22, 0xAD, 0xF8, 0x08, 0x30, 0xAD, 0xF8, 0x04, 0x50, 0xFF, 0xF7, ++0xE9, 0xFB, 0x23, 0x68, 0x01, 0xA8, 0xD3, 0xE9, 0x07, 0x12, 0xFF, 0xF7, 0x07, 0xFF, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, 0xD8, 0x25, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, ++0x0C, 0x48, 0x1B, 0xF0, 0x3F, 0xFE, 0x2B, 0x68, 0x5B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, 0x00, 0x24, 0x0C, 0x21, ++0x38, 0x46, 0xFF, 0xF7, 0xCB, 0xFC, 0x01, 0x46, 0x30, 0x46, 0x1B, 0xF0, 0x35, 0xFE, 0x2B, 0x68, 0x01, 0x34, 0x5A, 0x88, ++0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, 0x78, 0x36, 0x17, 0x00, 0x08, 0x60, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x4C, 0x80, 0x0F, 0x48, 0x1B, 0xF0, 0x1D, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0x1B, 0x89, ++0xB3, 0xB1, 0x0D, 0x4D, 0x0D, 0x4F, 0x0B, 0x4E, 0x00, 0x24, 0x4F, 0xF4, 0xD7, 0x61, 0x38, 0x46, 0xFF, 0xF7, 0xA6, 0xFC, ++0x01, 0x46, 0x30, 0x46, 0x1B, 0xF0, 0x10, 0xFE, 0xD8, 0xF8, 0x00, 0x20, 0x2B, 0x68, 0x11, 0x89, 0x01, 0x34, 0xA2, 0xB2, ++0x01, 0x33, 0x91, 0x42, 0x2B, 0x60, 0xEC, 0xD8, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x60, 0x17, 0x00, 0x18, 0x26, 0x17, 0x00, ++0xE4, 0x25, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, 0x0C, 0x48, 0x1B, 0xF0, 0xF3, 0xFD, 0x2B, 0x68, ++0x9B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, 0x00, 0x24, 0x7C, 0x21, 0x38, 0x46, 0xFF, 0xF7, 0x7F, 0xFC, 0x01, 0x46, ++0x30, 0x46, 0x1B, 0xF0, 0xE9, 0xFD, 0x2B, 0x68, 0x01, 0x34, 0x9A, 0x88, 0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, ++0x78, 0x36, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, ++0x1B, 0xF0, 0x10, 0xFE, 0x23, 0x68, 0x33, 0xB1, 0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x08, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, ++0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0xAB, 0xFD, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x08, 0x60, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x0C, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0xCE, 0xFD, 0x18, 0xB1, 0x0A, 0x4A, ++0x13, 0x68, 0x01, 0x3B, 0x13, 0x60, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x60, 0x17, 0x00, ++0x18, 0x26, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0x61, 0xFD, 0x0A, 0x49, ++0x23, 0x68, 0x0A, 0x68, 0x01, 0x32, 0x0A, 0x60, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x60, 0x17, 0x00, ++0x18, 0x26, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0x7E, 0xFD, 0x23, 0x68, 0x33, 0xB1, ++0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, ++0x19, 0xFD, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x41, 0x4B, 0xDF, 0xF8, 0x20, 0xB1, 0x1B, 0x68, 0x40, 0x4D, 0x1F, 0x8E, 0xDF, 0xF8, 0x18, 0x91, 0xDF, 0xF8, 0x18, 0x81, ++0x8B, 0x89, 0x0C, 0x46, 0x06, 0x46, 0x9F, 0x42, 0x6A, 0xD9, 0xD8, 0xF8, 0x00, 0x30, 0x04, 0x2B, 0x63, 0xD9, 0xD6, 0xE9, ++0x01, 0x03, 0x1B, 0x69, 0x98, 0x47, 0x82, 0x46, 0x00, 0x28, 0x62, 0xD0, 0xFF, 0xF7, 0x0E, 0xFF, 0x00, 0x28, 0x4A, 0xD0, ++0x00, 0x22, 0x34, 0x4B, 0x02, 0x60, 0x1B, 0x68, 0x42, 0x60, 0x53, 0x44, 0x82, 0x60, 0x03, 0x60, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x4A, 0xDB, 0xF8, 0x00, 0x30, 0xD2, 0xF8, ++0x00, 0xC0, 0x43, 0xF0, 0x01, 0x03, 0x0C, 0xF1, 0x01, 0x01, 0x11, 0x60, 0xCB, 0xF8, 0x00, 0x30, 0xDB, 0xF8, 0x00, 0x30, ++0x9B, 0x07, 0xFB, 0xD4, 0x2B, 0x68, 0x1B, 0xBB, 0xD9, 0xF8, 0x00, 0x30, 0xC9, 0xF8, 0x00, 0x00, 0x2B, 0x68, 0xB4, 0xF8, ++0x0C, 0xE0, 0x60, 0x60, 0x0E, 0xF1, 0x01, 0x0E, 0x98, 0xB2, 0x01, 0x30, 0x1F, 0xFA, 0x8E, 0xF3, 0xA3, 0x81, 0x28, 0x60, ++0xDB, 0xF8, 0x00, 0x00, 0x20, 0xF0, 0x01, 0x00, 0xCB, 0xF8, 0x00, 0x00, 0x00, 0x29, 0xB4, 0xD0, 0x18, 0x49, 0xC2, 0xF8, ++0x00, 0xC0, 0x0A, 0x68, 0xBC, 0xF1, 0x00, 0x0F, 0xAD, 0xD1, 0x00, 0x2A, 0xAB, 0xD0, 0x62, 0xB6, 0xA3, 0x89, 0xA8, 0xE7, ++0x63, 0x68, 0x00, 0x2B, 0xDC, 0xD0, 0x58, 0x60, 0xDA, 0xE7, 0x12, 0x48, 0xFE, 0xF7, 0xAA, 0xFC, 0xD6, 0xE9, 0x01, 0x03, ++0x51, 0x46, 0x5B, 0x69, 0x98, 0x47, 0x09, 0x4B, 0xA2, 0x89, 0x1B, 0x68, 0x5B, 0x8E, 0x9A, 0x42, 0x02, 0xD2, 0x04, 0x20, ++0x1B, 0xF0, 0xEA, 0xFB, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0xD8, 0xF8, 0x00, 0x10, 0x08, 0x48, 0xFE, 0xF7, 0x94, 0xFC, ++0xED, 0xE7, 0x00, 0xBF, 0xC8, 0x35, 0x17, 0x00, 0x64, 0x00, 0x24, 0x40, 0x34, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x24, 0x82, 0x15, 0x00, 0x0C, 0x82, 0x15, 0x00, 0x60, 0x00, 0x24, 0x40, 0x68, 0x00, 0x24, 0x40, ++0x18, 0x26, 0x17, 0x00, 0x08, 0xB5, 0x03, 0x4B, 0xD3, 0xF8, 0xF8, 0x32, 0x98, 0x47, 0x01, 0x20, 0x08, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0A, 0x4A, 0x0A, 0x49, 0x0B, 0x4C, 0x00, 0x23, 0xC2, 0xE9, 0x02, 0x03, 0xC2, 0xE9, ++0x04, 0x33, 0xC2, 0xE9, 0x00, 0x33, 0xC1, 0xE9, 0x00, 0x33, 0x8B, 0x81, 0x8B, 0x60, 0x8B, 0x73, 0x10, 0x46, 0xD4, 0xF8, ++0x10, 0x31, 0x98, 0x47, 0x01, 0x20, 0x10, 0xBD, 0x28, 0x60, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0xB9, 0x4B, 0xD3, 0xF8, 0x14, 0x35, 0x00, 0x2B, 0x00, 0xF0, 0x30, 0x81, 0xEF, 0xF3, ++0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0xB4, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xDF, 0xF8, 0x04, 0x93, 0xB1, 0x4B, ++0xD9, 0xF8, 0x00, 0x20, 0xD3, 0xF8, 0x14, 0x35, 0x51, 0x1C, 0xC9, 0xF8, 0x00, 0x10, 0x31, 0xB1, 0xAD, 0x49, 0xC9, 0xF8, ++0x00, 0x20, 0x09, 0x68, 0x0A, 0xB9, 0x01, 0xB1, 0x62, 0xB6, 0x93, 0xF8, 0x0C, 0xB0, 0x5A, 0x7B, 0x5C, 0x68, 0x05, 0x92, ++0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x38, 0x81, 0x00, 0x2C, 0x00, 0xF0, 0x35, 0x81, 0x9B, 0x68, 0x00, 0x2B, 0x00, 0xF0, ++0x31, 0x81, 0xA3, 0x4B, 0x07, 0x93, 0x9B, 0x89, 0x1F, 0xFA, 0x8B, 0xF2, 0x5B, 0x45, 0x06, 0x92, 0xC0, 0xF0, 0x5C, 0x81, ++0xDF, 0xF8, 0xB0, 0xA2, 0x00, 0x26, 0xAA, 0xE0, 0xD4, 0xE9, 0x00, 0x53, 0x03, 0x93, 0x6B, 0x1E, 0xB3, 0xF5, 0xE8, 0x1F, ++0x27, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x95, 0x4A, 0x01, 0x23, 0x13, 0x60, 0x03, 0x9B, ++0xD9, 0xF8, 0x00, 0x70, 0x01, 0x93, 0x23, 0x68, 0x93, 0x48, 0x00, 0x93, 0x5A, 0x46, 0x23, 0x46, 0x31, 0x46, 0x01, 0x37, ++0xC9, 0xF8, 0x00, 0x70, 0x1C, 0xF0, 0xC4, 0xFD, 0x4F, 0xF4, 0x80, 0x71, 0xA4, 0xF1, 0x80, 0x00, 0x1D, 0xF0, 0x9C, 0xF9, ++0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x88, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x20, 0x46, 0xFF, 0xF7, 0x1A, 0xFE, 0x6B, 0x7E, 0x2F, 0x7E, 0x09, 0x2B, 0x09, 0xD8, 0x83, 0x4A, 0x4F, 0xF4, ++0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x25, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xDD, 0x80, 0x6B, 0x8B, 0x13, 0xF0, ++0x08, 0x0F, 0x7E, 0x4B, 0x40, 0xF0, 0xBC, 0x80, 0x1A, 0x46, 0x04, 0x93, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x23, ++0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xCC, 0x80, 0x95, 0xF8, 0x16, 0x80, 0xB8, 0xF1, 0x05, 0x0F, 0x00, 0xF2, ++0x09, 0x81, 0x75, 0x4C, 0x75, 0x48, 0x1B, 0xF0, 0xF1, 0xFB, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, ++0xC0, 0xF2, 0xA5, 0x80, 0xE1, 0x8B, 0x71, 0x4B, 0xE2, 0x6C, 0x13, 0xF8, 0x08, 0xC0, 0x21, 0xF0, 0x01, 0x01, 0x00, 0x23, ++0xE1, 0x83, 0x63, 0x64, 0x13, 0x61, 0xE3, 0x62, 0x6B, 0x4B, 0x29, 0x46, 0x0C, 0xF1, 0x01, 0x0C, 0x1C, 0x22, 0x20, 0x1D, ++0x03, 0xF8, 0x08, 0xC0, 0x2F, 0xF0, 0x8A, 0xFA, 0xE1, 0x8B, 0xDA, 0xF8, 0x00, 0x00, 0x00, 0x23, 0x21, 0xF4, 0x00, 0x42, ++0x84, 0xF8, 0x42, 0x30, 0x22, 0xF0, 0x02, 0x02, 0x2D, 0x1A, 0x63, 0x62, 0x23, 0x65, 0x0B, 0x07, 0xE2, 0x83, 0xA5, 0x64, ++0x00, 0xF1, 0x87, 0x80, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, ++0x13, 0x44, 0x5A, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x02, 0x44, 0x41, 0xF8, 0x23, 0x20, ++0xA4, 0x20, 0x04, 0x9B, 0x00, 0xFB, 0x07, 0x80, 0x99, 0x30, 0x21, 0x46, 0x03, 0xEB, 0xC0, 0x00, 0x03, 0x9C, 0x1B, 0xF0, ++0x61, 0xFB, 0x01, 0x36, 0xF3, 0xB2, 0x9B, 0x45, 0x16, 0xD9, 0x05, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0x51, 0xAF, 0x4D, 0x49, ++0x4F, 0xF4, 0x80, 0x60, 0x1C, 0xF0, 0x7E, 0xFD, 0x20, 0x46, 0xD4, 0xE9, 0x00, 0x54, 0xFF, 0xF7, 0x93, 0xFD, 0xDA, 0xF8, ++0x00, 0x00, 0x01, 0x36, 0x28, 0x1A, 0xFF, 0xF7, 0x4B, 0xFC, 0xF3, 0xB2, 0x9B, 0x45, 0xE8, 0xD8, 0x07, 0x9A, 0x06, 0x99, ++0x93, 0x89, 0x5B, 0x1A, 0x93, 0x81, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4A, 0x01, 0x23, ++0x13, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x3D, 0x48, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x75, 0xFB, 0x2F, 0x49, ++0x91, 0xF8, 0x11, 0x35, 0xD1, 0xF8, 0x14, 0x25, 0x01, 0x3B, 0x81, 0xF8, 0x11, 0x35, 0x00, 0x2A, 0x00, 0xF0, 0x94, 0x80, ++0xD9, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0xDC, 0xAE, 0x28, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, ++0x00, 0x2B, 0x7F, 0xF4, 0xD4, 0xAE, 0x00, 0x2A, 0x3F, 0xF4, 0xD1, 0xAE, 0x62, 0xB6, 0x21, 0x4B, 0xD3, 0xF8, 0x14, 0x35, ++0x00, 0x2B, 0x7F, 0xF4, 0xD0, 0xAE, 0x40, 0x20, 0x1B, 0xF0, 0x6A, 0xFA, 0x04, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, ++0x1B, 0xF0, 0x64, 0xBA, 0x1F, 0x4C, 0x04, 0x93, 0x4F, 0xF0, 0x05, 0x08, 0x50, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0x58, 0xAF, ++0x21, 0x49, 0x22, 0x48, 0x4F, 0xF4, 0xE5, 0x72, 0x1C, 0xF0, 0x4C, 0xFF, 0x50, 0xE7, 0x04, 0x9B, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x07, 0x30, 0x21, 0x46, 0x00, 0xF5, 0xA3, 0x60, 0x03, 0x9C, 0x1B, 0xF0, 0xEC, 0xFA, 0x89, 0xE7, 0xDA, 0xF8, ++0x00, 0x00, 0x03, 0x9C, 0x28, 0x1A, 0xFF, 0xF7, 0xE7, 0xFB, 0x82, 0xE7, 0x0A, 0x4B, 0x16, 0x48, 0x07, 0x93, 0x1D, 0x46, ++0xFE, 0xF7, 0xEE, 0xFA, 0xAB, 0x89, 0x1F, 0xFA, 0x8B, 0xF2, 0x5B, 0x45, 0x06, 0x92, 0x27, 0xD3, 0xBB, 0xF1, 0x00, 0x0F, ++0x7F, 0xF4, 0xC8, 0xAE, 0x8C, 0xE7, 0x00, 0xBF, 0x58, 0x58, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, ++0x50, 0x82, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, ++0x74, 0x28, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0xB4, 0x82, 0x15, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x9C, 0x82, 0x15, 0x00, 0x34, 0x82, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x10, 0x48, 0xFE, 0xF7, ++0xBD, 0xFA, 0xBB, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0x9D, 0xAE, 0x61, 0xE7, 0x0D, 0x48, 0x0E, 0x4C, 0x1C, 0xF0, 0x7E, 0xFC, ++0x80, 0x21, 0xA5, 0xF1, 0x40, 0x00, 0x1D, 0xF0, 0x57, 0xF8, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0xE9, 0xAE, 0x08, 0x49, 0x08, 0x48, 0x4F, 0xF4, 0xE3, 0x72, 0x1C, 0xF0, 0xE7, 0xFE, 0xE1, 0xE6, 0x20, 0x20, 0x1B, 0xF0, ++0x11, 0xFA, 0x67, 0xE7, 0x44, 0x82, 0x15, 0x00, 0x74, 0x82, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x88, 0x82, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x24, 0x91, 0xDF, 0xF8, 0x24, 0x81, 0x42, 0x4F, 0x43, 0x4B, ++0xD3, 0xF8, 0xA0, 0x27, 0x00, 0x2A, 0x5E, 0xD0, 0x15, 0x7B, 0xD2, 0xF8, 0x04, 0xA0, 0x56, 0x7B, 0x65, 0xB3, 0x4F, 0xF0, ++0x00, 0x0B, 0x11, 0xE0, 0xDA, 0xE9, 0x00, 0x4A, 0xFF, 0xF7, 0xB0, 0xFC, 0x20, 0x46, 0xFD, 0xF7, 0x03, 0xFB, 0xD8, 0xF8, ++0x00, 0x00, 0x0B, 0xF1, 0x01, 0x0B, 0x20, 0x1A, 0xFF, 0xF7, 0x64, 0xFB, 0x5F, 0xFA, 0x8B, 0xF1, 0xA9, 0x42, 0x17, 0xD2, ++0x50, 0x46, 0x39, 0x46, 0x00, 0x2E, 0xE9, 0xD0, 0x4F, 0xF4, 0x80, 0x60, 0x1C, 0xF0, 0x80, 0xFC, 0x50, 0x46, 0xDA, 0xE9, ++0x00, 0x4A, 0xFF, 0xF7, 0x95, 0xFC, 0xD8, 0xF8, 0x00, 0x00, 0x0B, 0xF1, 0x01, 0x0B, 0x20, 0x1A, 0xFF, 0xF7, 0x4C, 0xFB, ++0x5F, 0xFA, 0x8B, 0xF1, 0xA9, 0x42, 0xE7, 0xD3, 0x28, 0x4A, 0x93, 0x89, 0x5D, 0x1B, 0x95, 0x81, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x25, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x23, 0x48, 0x01, 0x33, ++0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x76, 0xFA, 0x1D, 0x49, 0xD9, 0xF8, 0x00, 0x20, 0x91, 0xF8, 0x9D, 0x37, 0x01, 0x3B, ++0x81, 0xF8, 0x9D, 0x37, 0x00, 0x2A, 0xAA, 0xD0, 0x1A, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, ++0xA3, 0xD1, 0x00, 0x2B, 0xA1, 0xD0, 0x62, 0xB6, 0x13, 0x4B, 0xD3, 0xF8, 0xA0, 0x27, 0x00, 0x2A, 0xA0, 0xD1, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x4F, 0xF4, ++0x00, 0x00, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x8A, 0xF9, 0x04, 0x20, 0x1B, 0xF0, 0x63, 0xF9, 0xD9, 0xF8, ++0x00, 0x30, 0x3B, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0xBD, 0xE8, 0xF8, 0x8F, 0xB0, 0x82, 0x15, 0x00, 0x58, 0x58, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0xF8, 0x5F, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0xD8, 0x80, ++0xDF, 0xF8, 0xD8, 0x90, 0xDF, 0xF8, 0xD8, 0xA0, 0xD9, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0x41, 0xD0, 0x1F, 0x89, 0x5D, 0x68, ++0xBF, 0xB1, 0x00, 0x24, 0x26, 0x46, 0x23, 0x46, 0xB3, 0x42, 0xAB, 0x46, 0x04, 0xF1, 0x01, 0x04, 0x6D, 0x68, 0x08, 0xD1, ++0xDA, 0xF8, 0x8C, 0x32, 0x98, 0x47, 0x9B, 0xF8, 0x0B, 0x30, 0x03, 0xF0, 0x7F, 0x03, 0x1E, 0x44, 0xB6, 0xB2, 0x58, 0x46, ++0xFF, 0xF7, 0x0A, 0xFC, 0xA3, 0xB2, 0xBB, 0x42, 0xEA, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x1F, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x1E, 0x48, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x1B, 0xF0, ++0xF7, 0xF9, 0x99, 0xF8, 0x02, 0x3C, 0xD8, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0x89, 0xF8, 0x02, 0x3C, 0x00, 0x2A, 0xC7, 0xD0, ++0x15, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xD1, 0x00, 0x2B, 0xBE, 0xD0, 0x62, 0xB6, ++0xD9, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0xBD, 0xD1, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x10, 0x20, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x0E, 0xF9, ++0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x84, 0x42, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x7C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0xB4, 0x80, 0x2A, 0x4E, 0xC1, 0x46, ++0xA8, 0xF1, 0x06, 0x07, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0x33, 0xD0, 0x1D, 0x89, 0x5C, 0x68, 0x7D, 0xB1, 0x4F, 0xF0, ++0x00, 0x0B, 0x20, 0x68, 0xA2, 0x46, 0x0B, 0xF1, 0x01, 0x0B, 0x64, 0x68, 0xFF, 0xF7, 0x5E, 0xFA, 0x50, 0x46, 0xFF, 0xF7, ++0x9D, 0xFB, 0x1F, 0xFA, 0x8B, 0xF2, 0xAA, 0x42, 0xF1, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x1B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x33, 0x68, 0x48, 0x46, 0x01, 0x33, 0x33, 0x60, 0x1B, 0xF0, 0x8B, 0xF9, 0x3B, 0x78, ++0x32, 0x68, 0x01, 0x3B, 0x3B, 0x70, 0x00, 0x2A, 0xD4, 0xD0, 0x14, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0x32, 0x60, 0x00, 0x2A, ++0xCE, 0xD1, 0x00, 0x2B, 0xCC, 0xD0, 0x62, 0xB6, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0xCB, 0xD1, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x33, 0x68, 0x08, 0x20, 0x01, 0x33, 0x33, 0x60, ++0x1B, 0xF0, 0xA8, 0xF8, 0x33, 0x68, 0x33, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x94, 0x4E, 0x17, 0x00, ++0x10, 0xB5, 0x04, 0x20, 0x1B, 0xF0, 0x92, 0xF8, 0x03, 0x4B, 0x04, 0x49, 0xD3, 0xF8, 0x10, 0x31, 0x03, 0x48, 0xBD, 0xE8, ++0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x28, 0x60, 0x17, 0x00, 0xF8, 0xB5, 0xA8, 0x4B, ++0xA8, 0x4A, 0x1B, 0x68, 0x14, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB7, 0x81, 0x65, 0x05, 0x18, 0xD5, ++0xA4, 0x4A, 0x13, 0x68, 0x98, 0x00, 0xFC, 0xD4, 0xA3, 0x4B, 0xA2, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x13, 0xF0, 0x00, 0x53, ++0xFB, 0xD1, 0xA1, 0x49, 0xA1, 0x48, 0x0A, 0x68, 0x42, 0xF0, 0x10, 0x02, 0x0A, 0x60, 0x02, 0x78, 0x02, 0xB1, 0x03, 0x70, ++0x9E, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0xE0, 0x81, 0x21, 0x05, 0x09, 0xD5, 0x97, 0x4A, 0x13, 0x68, 0x9B, 0x00, ++0xFC, 0xD4, 0x9A, 0x4B, 0x94, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0xE2, 0x04, 0x05, 0xD5, 0x94, 0x49, ++0x96, 0x4B, 0x97, 0x4A, 0x01, 0x20, 0x08, 0x70, 0x1A, 0x60, 0x66, 0x06, 0x04, 0xD5, 0x95, 0x4B, 0x95, 0x48, 0x19, 0x68, ++0x1C, 0xF0, 0x9C, 0xFA, 0x14, 0xF4, 0x9B, 0x7F, 0x40, 0xF0, 0x89, 0x81, 0xA5, 0x05, 0x00, 0xF1, 0x8D, 0x81, 0x20, 0x06, ++0x00, 0xF1, 0x94, 0x81, 0x21, 0x04, 0x00, 0xF1, 0x9F, 0x81, 0xE2, 0x02, 0x00, 0xF1, 0xA6, 0x81, 0xA3, 0x02, 0x03, 0xD5, ++0x8B, 0x4B, 0x4F, 0xF4, 0x00, 0x12, 0x1A, 0x60, 0xE7, 0x03, 0x41, 0xD5, 0x89, 0x4B, 0x93, 0xF8, 0x11, 0x15, 0x93, 0xF8, ++0x12, 0x25, 0x91, 0x42, 0x80, 0xF0, 0xB1, 0x81, 0x93, 0xF8, 0x10, 0x05, 0x85, 0x4A, 0x86, 0x4D, 0x86, 0x4E, 0x01, 0x30, ++0xA2, 0xFB, 0x00, 0x72, 0x92, 0x09, 0x02, 0xEB, 0xC2, 0x02, 0x02, 0xEB, 0xC2, 0x02, 0x82, 0x1A, 0x01, 0x31, 0x83, 0xF8, ++0x11, 0x15, 0x83, 0xF8, 0x10, 0x25, 0x03, 0xEB, 0x02, 0x11, 0x30, 0x68, 0x2E, 0x68, 0x4E, 0x60, 0x6E, 0x68, 0x8E, 0x60, ++0x28, 0x3D, 0xC0, 0xF3, 0x00, 0x26, 0x08, 0x73, 0x4E, 0x73, 0x28, 0x68, 0x40, 0xF0, 0x10, 0x00, 0x11, 0x01, 0x28, 0x60, ++0x28, 0x68, 0x86, 0x06, 0xFC, 0xD4, 0x19, 0x44, 0x75, 0x4B, 0x8A, 0x68, 0x75, 0x48, 0x52, 0x68, 0x1A, 0x60, 0x2B, 0x68, ++0x23, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x1B, 0xF0, 0x6F, 0xF8, 0x20, 0x20, 0x1A, 0xF0, 0xCA, 0xFF, 0x69, 0x4B, 0x4F, 0xF4, ++0x80, 0x32, 0x1A, 0x60, 0x65, 0x03, 0x4E, 0xD5, 0x67, 0x4B, 0x93, 0xF8, 0x9D, 0x17, 0x93, 0xF8, 0x9E, 0x27, 0x91, 0x42, ++0x80, 0xF0, 0x7B, 0x81, 0x93, 0xF8, 0x9C, 0x07, 0x68, 0x4A, 0x69, 0x4F, 0x69, 0x4D, 0xDF, 0xF8, 0xE0, 0xC1, 0x01, 0x30, ++0xA2, 0xFB, 0x00, 0x62, 0x56, 0x09, 0x06, 0xEB, 0x86, 0x06, 0xA0, 0xEB, 0xC6, 0x06, 0x4A, 0x1C, 0x83, 0xF8, 0x9D, 0x27, ++0x83, 0xF8, 0x9C, 0x67, 0x03, 0xEB, 0x06, 0x11, 0x3A, 0x68, 0x28, 0x68, 0xC1, 0xF8, 0x20, 0x05, 0x06, 0xF1, 0x52, 0x07, ++0x03, 0xEB, 0x07, 0x15, 0xDC, 0xF8, 0x00, 0x10, 0x5C, 0x48, 0x69, 0x60, 0xC2, 0xF3, 0x00, 0x21, 0x69, 0x72, 0x2A, 0x72, ++0x05, 0x68, 0x45, 0xF0, 0x04, 0x05, 0x05, 0x60, 0x31, 0x01, 0x05, 0x46, 0x2A, 0x68, 0x10, 0x07, 0xFC, 0xD4, 0x03, 0xEB, ++0x07, 0x12, 0x01, 0xF2, 0x1C, 0x51, 0x50, 0x68, 0x53, 0x4A, 0x40, 0x68, 0x10, 0x60, 0x2A, 0x68, 0x52, 0x48, 0x22, 0xF0, ++0x04, 0x02, 0x19, 0x44, 0x2A, 0x60, 0x1B, 0xF0, 0x1F, 0xF8, 0x4F, 0xF4, 0x00, 0x00, 0x1A, 0xF0, 0x79, 0xFF, 0x41, 0x4B, ++0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0xA2, 0x03, 0x1B, 0xD5, 0x4B, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0x35, 0x81, ++0x49, 0x48, 0x90, 0xF8, 0x02, 0x1C, 0x90, 0xF8, 0x01, 0x2C, 0x91, 0x42, 0xC0, 0xF0, 0xA2, 0x80, 0x46, 0x48, 0x1C, 0xF0, ++0xDF, 0xF9, 0x36, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x1A, 0x60, 0x44, 0x4B, 0x1B, 0x68, 0x23, 0xB9, 0x43, 0x4A, 0x13, 0x78, ++0x23, 0xF0, 0x01, 0x03, 0x13, 0x70, 0x23, 0x03, 0x1D, 0xD5, 0x3C, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0x09, 0x81, ++0x3A, 0x48, 0x41, 0xF6, 0x12, 0x04, 0x41, 0xF6, 0x11, 0x03, 0x02, 0x5D, 0xC3, 0x5C, 0x93, 0x42, 0x10, 0xD8, 0x11, 0x46, ++0x39, 0x48, 0x1C, 0xF0, 0xBF, 0xF9, 0x26, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x37, 0x4B, 0x1B, 0x68, 0x23, 0xB9, ++0x33, 0x4A, 0x13, 0x78, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x70, 0xF8, 0xBD, 0x41, 0xF6, 0x10, 0x05, 0x32, 0x4B, 0x41, 0x5D, ++0x01, 0x31, 0xA3, 0xFB, 0x01, 0x63, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, 0xA1, 0xEB, 0x83, 0x13, 0x43, 0x55, 0x03, 0xF1, ++0xC1, 0x01, 0x2D, 0x4E, 0x00, 0xEB, 0x01, 0x11, 0x35, 0x68, 0x4D, 0x60, 0x2B, 0x4D, 0x00, 0xEB, 0x03, 0x13, 0x01, 0x32, ++0x2D, 0x68, 0xA3, 0xF8, 0x18, 0x5C, 0x02, 0x55, 0x28, 0x48, 0x1A, 0xF0, 0xB9, 0xFF, 0x08, 0x20, 0x1A, 0xF0, 0x14, 0xFF, ++0x0E, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0xCF, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x24, 0x00, 0x24, 0x40, ++0x40, 0x00, 0x24, 0x40, 0x01, 0x09, 0x00, 0x32, 0x44, 0x00, 0x24, 0x40, 0x1C, 0x26, 0x17, 0x00, 0x3C, 0x36, 0x17, 0x00, ++0x02, 0x09, 0x00, 0x32, 0x2C, 0x00, 0x24, 0x40, 0x09, 0x70, 0x00, 0xCF, 0x08, 0x00, 0x24, 0x40, 0xDC, 0x82, 0x15, 0x00, ++0x28, 0x00, 0x24, 0x40, 0x58, 0x58, 0x17, 0x00, 0xE7, 0x87, 0x45, 0xCA, 0x88, 0x00, 0x24, 0x40, 0x90, 0x00, 0x24, 0x40, ++0x74, 0x00, 0x24, 0x40, 0x6C, 0x5D, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, 0x84, 0x00, 0x24, 0x40, 0x7C, 0x00, 0x24, 0x40, ++0x60, 0x00, 0x24, 0x40, 0x6C, 0x00, 0x24, 0x40, 0xF8, 0x5F, 0x17, 0x00, 0x1D, 0x26, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x80, 0x83, 0x15, 0x00, 0xA0, 0x00, 0x24, 0x40, 0x9C, 0x4E, 0x17, 0x00, 0x98, 0x83, 0x15, 0x00, 0x98, 0x00, 0x24, 0x40, ++0xAB, 0xAA, 0xAA, 0xAA, 0xA4, 0x00, 0x24, 0x40, 0xA8, 0x00, 0x24, 0x40, 0x94, 0x4E, 0x17, 0x00, 0x80, 0x00, 0x24, 0x40, ++0x90, 0xF8, 0x00, 0x2C, 0x4B, 0x4B, 0x4C, 0x4D, 0x01, 0x32, 0xA3, 0xFB, 0x02, 0x63, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, ++0xA2, 0xEB, 0x83, 0x13, 0x00, 0xEB, 0x03, 0x12, 0x2D, 0x68, 0x55, 0x60, 0x46, 0x4D, 0x80, 0xF8, 0x00, 0x3C, 0x2B, 0x68, ++0x13, 0x81, 0x01, 0x31, 0x80, 0xF8, 0x02, 0x1C, 0x11, 0x46, 0x00, 0xF6, 0x08, 0x40, 0x1A, 0xF0, 0x49, 0xFF, 0x10, 0x20, ++0x1A, 0xF0, 0xA4, 0xFE, 0x3F, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x1A, 0x60, 0x3F, 0xE7, 0x00, 0x2C, 0x7F, 0xF4, 0x46, 0xAE, ++0x3C, 0x49, 0x3D, 0x48, 0x26, 0x22, 0x1C, 0xF0, 0x8D, 0xFB, 0x14, 0xF4, 0x9B, 0x7F, 0x3F, 0xF4, 0x77, 0xAE, 0x3A, 0x48, ++0x21, 0x46, 0x1C, 0xF0, 0x0B, 0xF9, 0xA5, 0x05, 0x7F, 0xF5, 0x73, 0xAE, 0x37, 0x48, 0x1C, 0xF0, 0x05, 0xF9, 0x32, 0x4B, ++0x4F, 0xF4, 0x00, 0x72, 0x20, 0x06, 0x1A, 0x60, 0x7F, 0xF5, 0x6C, 0xAE, 0x33, 0x48, 0x1C, 0xF0, 0xFB, 0xF8, 0x33, 0x4A, ++0x2C, 0x49, 0x13, 0x68, 0x80, 0x20, 0x23, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x08, 0x60, 0x21, 0x04, 0x7F, 0xF5, 0x61, 0xAE, ++0x2E, 0x48, 0x1C, 0xF0, 0xED, 0xF8, 0x26, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0x1A, 0x60, 0xE2, 0x02, 0x7F, 0xF5, 0x5A, 0xAE, ++0x2A, 0x4A, 0x2B, 0x4B, 0x15, 0x68, 0x2B, 0x48, 0x1A, 0x78, 0x29, 0x46, 0xFD, 0xF7, 0x14, 0xFF, 0x29, 0x4A, 0x1E, 0x4B, ++0x15, 0x60, 0x4F, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x4A, 0xE6, 0x27, 0x4A, 0x01, 0x21, 0x59, 0x70, 0x13, 0x68, 0x26, 0x49, ++0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x02, 0x20, 0x1C, 0xF0, 0x1C, 0xF9, 0x13, 0xE6, 0x23, 0x48, 0x1C, 0xF0, 0xC8, 0xF8, ++0x13, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x1A, 0x60, 0x80, 0xE6, 0x00, 0x22, 0x02, 0x20, 0x1A, 0x70, 0xFD, 0xF7, 0x86, 0xFF, ++0xF0, 0xE6, 0x1D, 0x48, 0x1C, 0xF0, 0xBA, 0xF8, 0x0C, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0xC3, 0xE6, 0x00, 0x22, ++0x02, 0x20, 0x1A, 0x70, 0xFD, 0xF7, 0x78, 0xFF, 0x17, 0x48, 0x90, 0xF8, 0x02, 0x1C, 0x90, 0xF8, 0x01, 0x2C, 0x91, 0x42, ++0xBF, 0xF4, 0xC6, 0xAE, 0x66, 0xE7, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, 0xAC, 0x00, 0x24, 0x40, 0xB0, 0x00, 0x24, 0x40, ++0x28, 0x00, 0x24, 0x40, 0x70, 0x79, 0x15, 0x00, 0xC0, 0x82, 0x15, 0x00, 0xEC, 0x82, 0x15, 0x00, 0x08, 0x83, 0x15, 0x00, ++0x1C, 0x83, 0x15, 0x00, 0x4C, 0x00, 0x24, 0x40, 0x30, 0x83, 0x15, 0x00, 0x30, 0x00, 0x24, 0x40, 0x45, 0x00, 0x24, 0x40, ++0x48, 0x83, 0x15, 0x00, 0x34, 0x00, 0x24, 0x40, 0x10, 0x00, 0x58, 0x40, 0xD0, 0x82, 0x15, 0x00, 0xCC, 0x7C, 0x15, 0x00, ++0x64, 0x83, 0x15, 0x00, 0x7C, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x47, 0x4B, 0x1A, 0x68, 0x42, 0xF0, 0x10, 0x02, 0x1A, 0x60, ++0x1B, 0x68, 0x5A, 0x07, 0x7F, 0xD4, 0x44, 0x49, 0x0B, 0x68, 0x9B, 0x00, 0xFC, 0xD4, 0x43, 0x4B, 0x41, 0x4A, 0x0B, 0x60, ++0x13, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0x13, 0x68, 0x9E, 0x07, 0x03, 0xD4, 0x3C, 0x4A, 0x13, 0x68, 0xDD, 0x07, 0xFC, 0xD5, ++0x3A, 0x4A, 0x3D, 0x4D, 0x13, 0x68, 0x3D, 0x48, 0x3D, 0x49, 0x3E, 0x4C, 0x3E, 0x4F, 0x3F, 0x4E, 0x43, 0xF0, 0x02, 0x03, ++0x13, 0x60, 0x2B, 0x68, 0x03, 0x40, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x2B, 0x68, 0x9B, 0xB2, 0x43, 0xF4, 0x80, 0x13, ++0x2B, 0x60, 0x0B, 0x68, 0x03, 0x40, 0x43, 0xF0, 0x10, 0x03, 0x0B, 0x60, 0x0B, 0x68, 0x9B, 0xB2, 0x43, 0xF4, 0x80, 0x13, ++0x0B, 0x60, 0x4F, 0xF6, 0xFF, 0x73, 0x23, 0x60, 0x52, 0xF8, 0x34, 0x3C, 0x03, 0x40, 0x43, 0xF4, 0x88, 0x53, 0x43, 0xF0, ++0x11, 0x03, 0x42, 0xF8, 0x34, 0x3C, 0x03, 0x23, 0xAB, 0x64, 0x4F, 0xF4, 0xFC, 0x53, 0x3B, 0x60, 0x4F, 0xF0, 0xFF, 0x33, ++0x33, 0x60, 0x2A, 0x48, 0x2A, 0x4B, 0x23, 0x62, 0x00, 0x24, 0x20, 0x23, 0x04, 0x60, 0x41, 0xF8, 0xAC, 0x3C, 0x52, 0xF8, ++0x34, 0x3C, 0x27, 0x4C, 0x27, 0x48, 0x23, 0xF4, 0x7F, 0x03, 0x43, 0xF4, 0x80, 0x33, 0x42, 0xF8, 0x34, 0x3C, 0x41, 0xF8, ++0x84, 0x4C, 0x1C, 0xF0, 0x1B, 0xF8, 0x17, 0x4B, 0x17, 0x49, 0x1A, 0x68, 0x94, 0x00, 0xFC, 0xD4, 0x19, 0x60, 0x1A, 0x68, ++0x90, 0x00, 0xFC, 0xD4, 0x1A, 0x68, 0x12, 0xF0, 0x06, 0x0F, 0xF4, 0xD0, 0x10, 0x4A, 0x13, 0x68, 0x99, 0x00, 0xFC, 0xD4, ++0x1A, 0x4B, 0x0E, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x9B, 0x00, 0xFC, 0xD4, 0x18, 0x48, 0x1C, 0xF0, 0x01, 0xF8, 0x18, 0x4B, ++0x18, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0xFC, 0x12, 0x91, 0x67, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF4, 0x80, 0x42, 0x1A, 0x60, ++0xF8, 0xBD, 0x14, 0x4B, 0x0C, 0x4A, 0x1A, 0x60, 0xFE, 0xF7, 0x9A, 0xFB, 0xED, 0xE7, 0x00, 0xBF, 0x44, 0x00, 0x24, 0x40, ++0x40, 0x00, 0x24, 0x40, 0x00, 0x02, 0x00, 0x20, 0x04, 0x00, 0x24, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x24, 0x40, ++0x0C, 0x00, 0x24, 0x40, 0xB4, 0x00, 0x24, 0x40, 0x28, 0x00, 0x24, 0x40, 0x38, 0x00, 0x24, 0x40, 0x09, 0x60, 0x00, 0xCF, ++0x00, 0x00, 0x20, 0x4E, 0xB8, 0x83, 0x15, 0x00, 0x06, 0x03, 0x00, 0x30, 0xCC, 0x83, 0x15, 0x00, 0x00, 0xED, 0x00, 0xE0, ++0x88, 0x1A, 0x17, 0x00, 0x2C, 0x00, 0x24, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x82, 0xB0, 0xEF, 0xF3, 0x10, 0x83, ++0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x24, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x23, 0x4E, 0x24, 0x4B, 0x35, 0x68, 0x1B, 0x68, ++0x01, 0x35, 0x35, 0x60, 0x1C, 0x78, 0x01, 0x2C, 0x2B, 0xD0, 0x21, 0x4C, 0x23, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x23, 0x60, ++0x23, 0x68, 0x9B, 0x05, 0xFC, 0xD4, 0x1E, 0x4B, 0x18, 0x68, 0xC8, 0xB1, 0x1D, 0x4B, 0x1E, 0x4C, 0xD3, 0xF8, 0x04, 0x0C, ++0x47, 0x60, 0x20, 0x68, 0x01, 0x44, 0x21, 0x60, 0x17, 0x49, 0xC3, 0xF8, 0x04, 0x2C, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x73, ++0x0B, 0x60, 0x35, 0xB1, 0x10, 0x4B, 0x01, 0x3D, 0x1B, 0x68, 0x35, 0x60, 0x0D, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x02, 0xB0, ++0xBD, 0xE8, 0xF0, 0x81, 0x11, 0x48, 0x1F, 0x60, 0x04, 0x68, 0x0F, 0x4B, 0x21, 0x44, 0x01, 0x60, 0xE6, 0xE7, 0xDF, 0xF8, ++0x3C, 0x80, 0x98, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0xCD, 0xD1, 0x02, 0x20, 0xCD, 0xE9, 0x00, 0x12, 0xFD, 0xF7, 0x3C, 0xFE, ++0xDD, 0xE9, 0x00, 0x12, 0x35, 0x68, 0x88, 0xF8, 0x00, 0x40, 0xC2, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x74, 0x36, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0xA0, 0x00, 0x24, 0x40, 0x7C, 0x36, 0x17, 0x00, 0x9C, 0x00, 0x24, 0x40, ++0x1D, 0x26, 0x17, 0x00, 0x30, 0xB4, 0x85, 0x68, 0x06, 0x4C, 0xC3, 0xF3, 0x0B, 0x03, 0x2C, 0x40, 0x02, 0x9D, 0x1C, 0x43, ++0x44, 0xEA, 0xC5, 0x74, 0x84, 0x60, 0xC0, 0xE9, 0x00, 0x12, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xF0, 0xFF, 0x7F, ++0xF8, 0xB5, 0x04, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x23, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x22, 0x4D, 0x23, 0x4B, 0x29, 0x68, 0x1B, 0x68, 0x01, 0x31, 0x29, 0x60, 0x1E, 0x78, 0x01, 0x2E, 0x30, 0xD0, 0x20, 0x4A, ++0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x13, 0x68, 0x1B, 0x06, 0xFC, 0xD4, 0x1D, 0x4B, 0x1A, 0x68, 0xF2, 0xB1, ++0x1C, 0x4B, 0x1D, 0x48, 0x41, 0xF6, 0x14, 0x02, 0x9A, 0x58, 0x54, 0x60, 0x02, 0x68, 0x01, 0x32, 0x02, 0x60, 0x41, 0xF6, ++0x14, 0x02, 0x15, 0x4E, 0x9C, 0x50, 0x18, 0x48, 0x32, 0x68, 0x03, 0x78, 0x22, 0xF0, 0x40, 0x02, 0x43, 0xF0, 0x02, 0x03, ++0x32, 0x60, 0x03, 0x70, 0x31, 0xB1, 0x0C, 0x4B, 0x01, 0x39, 0x1B, 0x68, 0x29, 0x60, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, ++0xF8, 0xBD, 0x0E, 0x48, 0x1C, 0x60, 0x02, 0x68, 0x0B, 0x4B, 0x01, 0x32, 0x02, 0x60, 0xE2, 0xE7, 0x0C, 0x4F, 0x3B, 0x78, ++0x00, 0x2B, 0xCA, 0xD1, 0x02, 0x20, 0xFD, 0xF7, 0xC9, 0xFD, 0x29, 0x68, 0x3E, 0x70, 0xC4, 0xE7, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0x98, 0x00, 0x24, 0x40, 0x7C, 0x36, 0x17, 0x00, ++0x94, 0x00, 0x24, 0x40, 0x9C, 0x4E, 0x17, 0x00, 0x1D, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x80, 0x46, 0x04, 0x20, ++0x0F, 0x46, 0x15, 0x46, 0xFE, 0xF7, 0xF0, 0xFD, 0x68, 0xB3, 0x04, 0x46, 0xFE, 0xF7, 0x34, 0xFF, 0x06, 0x46, 0x00, 0xB3, ++0xC5, 0xF3, 0x03, 0x23, 0x4F, 0xF0, 0x00, 0x09, 0x25, 0x70, 0x63, 0x70, 0x2A, 0x46, 0x84, 0xF8, 0x02, 0x80, 0x39, 0x46, ++0x84, 0xF8, 0x03, 0x90, 0x20, 0x1D, 0x2E, 0xF0, 0xF9, 0xFB, 0xB2, 0x68, 0x0E, 0x4B, 0xC6, 0xF8, 0x04, 0x90, 0x04, 0x35, ++0x13, 0x40, 0xC5, 0xF3, 0x0B, 0x05, 0x1D, 0x43, 0x45, 0xF0, 0x00, 0x45, 0x34, 0x60, 0xB5, 0x60, 0x30, 0x46, 0xBD, 0xE8, ++0xF8, 0x43, 0xFF, 0xF7, 0x71, 0xBF, 0x07, 0x48, 0x1C, 0xF0, 0xCC, 0xFF, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0xFE, 0xF7, ++0xE7, 0xBD, 0xBD, 0xE8, 0xF8, 0x43, 0x03, 0x48, 0x1C, 0xF0, 0xC2, 0xBF, 0x00, 0xF0, 0xFF, 0x7F, 0xEC, 0x83, 0x15, 0x00, ++0xD8, 0x83, 0x15, 0x00, 0x05, 0x4B, 0x1B, 0x78, 0x33, 0xB9, 0x05, 0x4B, 0x18, 0x68, 0x6F, 0xEA, 0x10, 0x10, 0x00, 0xF0, ++0x01, 0x00, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x1C, 0x26, 0x17, 0x00, 0x44, 0x00, 0x24, 0x40, 0x44, 0x4A, 0x13, 0x69, ++0x43, 0xF0, 0x01, 0x03, 0x30, 0xB4, 0x13, 0x61, 0x13, 0x69, 0xD9, 0x07, 0xFC, 0xD4, 0x40, 0x4A, 0x13, 0x69, 0x00, 0x2B, ++0xFC, 0xDA, 0xD3, 0x68, 0x3E, 0x48, 0x3D, 0x49, 0x43, 0xF0, 0x80, 0x43, 0x43, 0xF0, 0x07, 0x03, 0xD3, 0x60, 0xD3, 0x68, ++0x18, 0x43, 0xD0, 0x60, 0xD3, 0x68, 0x23, 0xF4, 0x71, 0x53, 0x23, 0xF0, 0x28, 0x03, 0xD3, 0x60, 0x13, 0x69, 0x43, 0xF0, ++0x01, 0x03, 0x13, 0x61, 0x0B, 0x69, 0xDA, 0x07, 0xFC, 0xD4, 0x32, 0x4B, 0x1A, 0x69, 0x00, 0x2A, 0xFC, 0xDA, 0xDA, 0x68, ++0x30, 0x48, 0x2F, 0x49, 0x42, 0xF0, 0x80, 0x42, 0x42, 0xF0, 0x07, 0x02, 0xDA, 0x60, 0xDA, 0x68, 0x10, 0x43, 0xD8, 0x60, ++0xDA, 0x68, 0x22, 0xF4, 0x71, 0x52, 0x22, 0xF0, 0x28, 0x02, 0xDA, 0x60, 0xD3, 0xF8, 0x00, 0x28, 0x22, 0xF4, 0xC0, 0x52, ++0x22, 0xF0, 0x03, 0x02, 0xC3, 0xF8, 0x00, 0x28, 0xD3, 0xF8, 0x00, 0x28, 0x42, 0xF4, 0x00, 0x02, 0x42, 0xF0, 0x04, 0x02, ++0xC3, 0xF8, 0x00, 0x28, 0x00, 0x24, 0x4F, 0xF0, 0xFF, 0x35, 0x01, 0x22, 0x9C, 0x61, 0x01, 0x2A, 0x5D, 0x61, 0xC3, 0xF8, ++0x1C, 0x48, 0xC3, 0xF8, 0x14, 0x48, 0xC3, 0xF8, 0x10, 0x48, 0xA2, 0xF1, 0x02, 0x03, 0x28, 0x46, 0x01, 0xEB, 0x43, 0x13, ++0x0B, 0xD0, 0x05, 0x2A, 0xC3, 0xF8, 0x28, 0x0B, 0xC3, 0xF8, 0x28, 0x09, 0x0A, 0xD0, 0x01, 0x32, 0x93, 0x1E, 0x01, 0x2A, ++0x01, 0xEB, 0x43, 0x13, 0xF3, 0xD1, 0xC1, 0xF8, 0x08, 0x0B, 0xC1, 0xF8, 0x08, 0x09, 0xF4, 0xE7, 0x0F, 0x48, 0x10, 0x4B, ++0x0C, 0x4A, 0x88, 0x61, 0x4B, 0x63, 0x53, 0x6B, 0x1B, 0x01, 0xFC, 0xD5, 0xD2, 0xF8, 0x04, 0x38, 0x23, 0xF0, 0x02, 0x03, ++0xC2, 0xF8, 0x04, 0x38, 0xD2, 0xF8, 0x04, 0x38, 0x2E, 0x21, 0x43, 0xF4, 0x00, 0x43, 0xC2, 0xF8, 0x04, 0x38, 0x91, 0x60, ++0x93, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x30, 0xBC, 0x93, 0x60, 0x70, 0x47, 0x00, 0x00, 0x20, 0x40, 0x10, 0x00, 0x06, 0x40, ++0x00, 0x38, 0x00, 0x80, 0x41, 0x00, 0x44, 0x02, 0x0A, 0x4B, 0x0B, 0x49, 0x1A, 0x68, 0x08, 0x68, 0x0A, 0x49, 0x0B, 0x4B, ++0xC2, 0xE9, 0x00, 0x10, 0xC3, 0xF8, 0x14, 0x2B, 0xD3, 0xF8, 0x08, 0x2B, 0xC3, 0xF8, 0x08, 0x2B, 0xD3, 0xF8, 0x00, 0x2B, ++0x42, 0xF0, 0x04, 0x42, 0xC3, 0xF8, 0x00, 0x2B, 0x70, 0x47, 0x00, 0xBF, 0x5C, 0x60, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, ++0x40, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x20, 0x40, 0x12, 0x4A, 0x13, 0x4B, 0x11, 0x68, 0x18, 0x68, 0x12, 0x4B, 0x30, 0xB4, ++0x12, 0x4C, 0x4F, 0xF0, 0x20, 0x62, 0x00, 0x25, 0x65, 0x81, 0xC1, 0xE9, 0x00, 0x20, 0x1A, 0x69, 0x22, 0xF4, 0xFC, 0x62, ++0x42, 0xF0, 0x20, 0x02, 0x1A, 0x61, 0x18, 0x69, 0x10, 0xF0, 0x20, 0x00, 0xFB, 0xD1, 0xD3, 0xF8, 0x08, 0x29, 0xC3, 0xF8, ++0x08, 0x29, 0xC3, 0xF8, 0x14, 0x19, 0xD3, 0xF8, 0x00, 0x29, 0x42, 0xF0, 0x04, 0x42, 0x30, 0xBC, 0xC3, 0xF8, 0x00, 0x29, ++0x70, 0x47, 0x00, 0xBF, 0x40, 0x60, 0x17, 0x00, 0x58, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xB4, 0x27, 0x17, 0x00, ++0x70, 0xB5, 0x0B, 0x4B, 0x04, 0x46, 0x01, 0x38, 0x03, 0xEB, 0x00, 0x10, 0x10, 0x22, 0x05, 0x7A, 0x00, 0x21, 0xF7, 0xF7, ++0x4D, 0xFB, 0x55, 0xB1, 0x06, 0x48, 0x00, 0xEB, 0x84, 0x04, 0x23, 0x6A, 0x2B, 0xB1, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, ++0x08, 0x46, 0x01, 0x22, 0x18, 0x47, 0x70, 0xBD, 0x08, 0x28, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0x70, 0xB5, 0x0B, 0x4B, ++0x04, 0x46, 0x01, 0x38, 0x03, 0xEB, 0x00, 0x10, 0x10, 0x22, 0xC5, 0x7A, 0x00, 0x21, 0xF7, 0xF7, 0x31, 0xFB, 0x55, 0xB1, ++0x06, 0x48, 0x00, 0xEB, 0x84, 0x04, 0x23, 0x6B, 0x2B, 0xB1, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0x08, 0x46, 0x01, 0x22, ++0x18, 0x47, 0x70, 0xBD, 0xC8, 0x27, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x24, 0x82, 0xB0, 0xE0, 0xB2, ++0x01, 0x90, 0x01, 0x34, 0xFF, 0xF7, 0xC0, 0xFF, 0x01, 0x98, 0xFF, 0xF7, 0xD9, 0xFF, 0x05, 0x2C, 0xF5, 0xD1, 0x02, 0xB0, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0xB5, 0x0C, 0x46, 0x00, 0x28, 0x39, 0xD0, 0x09, 0xBB, 0x1D, 0x4B, 0x1D, 0x4A, 0x1B, 0x68, ++0x51, 0x81, 0x1D, 0x4D, 0x4F, 0xF0, 0x42, 0x42, 0x1A, 0x60, 0xDA, 0x78, 0x42, 0xF0, 0x04, 0x02, 0xDA, 0x70, 0xD9, 0x78, ++0x28, 0x68, 0x19, 0x4A, 0x58, 0x60, 0x01, 0xF0, 0x07, 0x01, 0x41, 0xF0, 0x08, 0x01, 0xD9, 0x70, 0xD2, 0xF8, 0x08, 0x19, ++0xC2, 0xF8, 0x08, 0x19, 0xC2, 0xF8, 0x14, 0x39, 0xD2, 0xF8, 0x00, 0x39, 0x43, 0xF0, 0x04, 0x43, 0xC2, 0xF8, 0x00, 0x39, ++0x38, 0xBD, 0x0E, 0x4D, 0x01, 0x46, 0x22, 0x46, 0x28, 0x68, 0x2E, 0xF0, 0x71, 0xFA, 0x09, 0x4B, 0x09, 0x4A, 0x1B, 0x68, ++0x54, 0x81, 0x4F, 0xF0, 0x40, 0x41, 0xC2, 0x22, 0x40, 0x2C, 0x19, 0x60, 0x1C, 0x80, 0xDA, 0x70, 0xD3, 0xD1, 0xD2, 0xB2, ++0x6F, 0xF3, 0x82, 0x02, 0xDA, 0x70, 0xD2, 0xE7, 0x02, 0x4D, 0xEC, 0xE7, 0x40, 0x60, 0x17, 0x00, 0xB4, 0x27, 0x17, 0x00, ++0x58, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xF0, 0xB4, 0x80, 0xB3, 0x27, 0x4D, 0x43, 0x1E, 0x05, 0xEB, 0x43, 0x16, ++0x08, 0x36, 0x05, 0xEB, 0x43, 0x15, 0x2F, 0x68, 0x17, 0xF0, 0x80, 0x2F, 0x22, 0xD0, 0x23, 0x4B, 0x3B, 0x40, 0xB3, 0xF5, ++0x00, 0x3F, 0x2C, 0xD0, 0x21, 0x4C, 0xD4, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x00, 0x73, 0xC4, 0xF8, 0x04, 0x38, 0x63, 0x69, ++0x1B, 0x06, 0xFC, 0xD5, 0x2B, 0x68, 0x19, 0x43, 0x41, 0xF0, 0x00, 0x61, 0x41, 0xF4, 0x00, 0x41, 0x29, 0x60, 0x1A, 0xB1, ++0x2B, 0x68, 0x23, 0xEA, 0x02, 0x02, 0x2A, 0x60, 0x60, 0xB9, 0x16, 0x4A, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x80, 0x63, ++0xC2, 0xF8, 0x04, 0x38, 0xF0, 0xBC, 0xFF, 0xF7, 0x3D, 0xBF, 0x12, 0x4E, 0x12, 0x4D, 0xD2, 0xE7, 0x00, 0x2F, 0x0C, 0xDB, ++0x3B, 0x04, 0xEE, 0xD4, 0x2B, 0x68, 0x23, 0xF4, 0x00, 0x43, 0x2B, 0x60, 0xE9, 0xE7, 0xB1, 0xF1, 0x00, 0x6F, 0xCF, 0xD1, ++0x00, 0x2A, 0xCD, 0xD1, 0xEA, 0xE7, 0x02, 0x23, 0x33, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x2B, 0x60, 0x33, 0x68, ++0x9A, 0x07, 0xFC, 0xD5, 0x3B, 0x04, 0xD8, 0xD4, 0xE8, 0xE7, 0x00, 0xBF, 0x20, 0x0B, 0x20, 0x40, 0x00, 0x00, 0x02, 0x80, ++0x00, 0x00, 0x20, 0x40, 0x08, 0x0B, 0x20, 0x40, 0x00, 0x0B, 0x20, 0x40, 0x70, 0xB4, 0x70, 0xB3, 0x44, 0x1E, 0x36, 0x4B, ++0x66, 0x01, 0x03, 0xEB, 0x44, 0x14, 0xF5, 0x58, 0x15, 0xF0, 0x80, 0x2F, 0x4D, 0xD0, 0x08, 0x36, 0x33, 0x44, 0x32, 0x4E, ++0x2E, 0x40, 0xB6, 0xF5, 0x00, 0x3F, 0x29, 0xD1, 0xB1, 0xF1, 0x00, 0x6F, 0x46, 0xD0, 0x40, 0x26, 0x1E, 0x60, 0x23, 0x68, ++0x0B, 0x43, 0x43, 0xF0, 0x00, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x23, 0x60, 0x00, 0x2A, 0x45, 0xD1, 0x29, 0x4A, 0x83, 0x01, ++0x43, 0xF0, 0x20, 0x03, 0x13, 0x61, 0x13, 0x69, 0x99, 0x06, 0xFC, 0xD4, 0x2B, 0x04, 0x03, 0xD4, 0x23, 0x68, 0x23, 0xF4, ++0x00, 0x43, 0x23, 0x60, 0x48, 0xBB, 0x70, 0xBC, 0x70, 0x47, 0x22, 0x4C, 0x25, 0x68, 0x15, 0xF0, 0x80, 0x2F, 0xF8, 0xD0, ++0x1D, 0x4E, 0x20, 0x4B, 0x2E, 0x40, 0xB6, 0xF5, 0x00, 0x3F, 0xD5, 0xD0, 0x40, 0x26, 0x1E, 0x60, 0x26, 0x68, 0x31, 0x43, ++0x41, 0xF0, 0x00, 0x61, 0x41, 0xF4, 0x00, 0x41, 0x00, 0x2D, 0x21, 0x60, 0xD6, 0xDA, 0xAE, 0x03, 0x04, 0xD4, 0x19, 0x68, ++0x49, 0x06, 0xFC, 0xD5, 0x40, 0x21, 0x19, 0x60, 0xDA, 0xB9, 0x02, 0x22, 0x1A, 0x60, 0x22, 0x68, 0x42, 0xF0, 0x80, 0x42, ++0x22, 0x60, 0x1A, 0x68, 0x96, 0x07, 0xFC, 0xD5, 0xC6, 0xE7, 0x70, 0xBC, 0xFF, 0xF7, 0xD4, 0xBE, 0x00, 0x2A, 0xCF, 0xD0, ++0x40, 0x21, 0x19, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x23, 0x60, 0x23, 0x68, 0x23, 0xEA, ++0x02, 0x02, 0x22, 0x60, 0xB4, 0xE7, 0x21, 0x68, 0x21, 0xEA, 0x02, 0x02, 0x22, 0x60, 0xDE, 0xE7, 0x20, 0x09, 0x20, 0x40, ++0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x40, 0x00, 0x09, 0x20, 0x40, 0x08, 0x09, 0x20, 0x40, 0x49, 0xB9, 0x0A, 0x4B, ++0x0A, 0x4A, 0x01, 0x28, 0x0C, 0xBF, 0x18, 0x46, 0x10, 0x46, 0x00, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x01, 0x28, ++0x0C, 0xBF, 0x04, 0x48, 0x04, 0x48, 0x49, 0x01, 0x08, 0x44, 0x00, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x09, 0x20, 0x40, 0x00, 0x0B, 0x20, 0x40, 0x38, 0xB9, 0x04, 0x29, 0x0D, 0xD8, 0x02, 0x46, 0x08, 0x46, 0x4F, 0xF0, ++0x00, 0x61, 0xFF, 0xF7, 0x07, 0xBF, 0x04, 0x29, 0x05, 0xD8, 0x08, 0x46, 0x00, 0x22, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, ++0x5B, 0xBF, 0x70, 0x47, 0x38, 0xB9, 0x04, 0x29, 0x0D, 0xD8, 0x02, 0x46, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0xFF, 0xF7, ++0xF5, 0xBE, 0x04, 0x29, 0x05, 0xD8, 0x08, 0x46, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x11, 0xFF, 0xF7, 0x49, 0xBF, 0x70, 0x47, ++0x40, 0xB9, 0x04, 0x29, 0x0F, 0xD8, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x12, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, 0xE2, 0xBE, ++0x04, 0x29, 0x06, 0xD8, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x12, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, 0x35, 0xBF, 0x70, 0x47, ++0xFF, 0xF7, 0xC6, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0x04, 0x46, 0x0D, 0x46, 0x57, 0x48, 0x00, 0x21, 0x1B, 0xF0, 0x04, 0xFC, ++0x00, 0x2C, 0x00, 0xF0, 0x95, 0x80, 0x23, 0x68, 0x00, 0x2B, 0x7B, 0xD0, 0x63, 0x68, 0x00, 0x2B, 0x78, 0xD0, 0xA3, 0x68, ++0x00, 0x2B, 0x75, 0xD0, 0x63, 0x69, 0x00, 0x2B, 0x72, 0xD0, 0x4F, 0x4E, 0x33, 0x78, 0x03, 0xF0, 0xFF, 0x07, 0x00, 0x2B, ++0x6F, 0xD1, 0xDF, 0xF8, 0x68, 0x81, 0x21, 0x46, 0x40, 0x46, 0x01, 0x24, 0x48, 0x22, 0x34, 0x70, 0x2E, 0xF0, 0x06, 0xF9, ++0x48, 0x4B, 0xD3, 0xF8, 0x94, 0x30, 0x00, 0x2B, 0x77, 0xD0, 0x47, 0x48, 0x1B, 0xF0, 0xDE, 0xFB, 0x46, 0x4B, 0xD3, 0xF8, ++0x00, 0x28, 0x12, 0xF4, 0xFE, 0x6F, 0x5B, 0xD0, 0x44, 0x49, 0x45, 0x4A, 0xD1, 0xF8, 0x00, 0xC0, 0x44, 0x49, 0x12, 0x68, ++0xDF, 0xF8, 0x30, 0x91, 0x09, 0x68, 0xC9, 0xF8, 0x04, 0x70, 0x04, 0x20, 0xC9, 0xF8, 0x08, 0x70, 0x89, 0xF8, 0x00, 0x70, ++0xC2, 0xF8, 0x04, 0xC0, 0x30, 0x70, 0xC3, 0xF8, 0x14, 0x2B, 0xC8, 0x78, 0x3C, 0x4A, 0x40, 0xF0, 0xC0, 0x00, 0xD2, 0xF8, ++0x00, 0xC0, 0xC8, 0x70, 0x9C, 0xF8, 0x03, 0x00, 0x39, 0x4A, 0x40, 0xF0, 0xC0, 0x00, 0x17, 0x68, 0x8C, 0xF8, 0x03, 0x00, ++0xF8, 0x78, 0xD2, 0xF8, 0x04, 0xE0, 0x40, 0xF0, 0xC0, 0x00, 0xF8, 0x70, 0x9E, 0xF8, 0x03, 0x00, 0xD2, 0xE9, 0x02, 0xC7, ++0x40, 0xF0, 0xC0, 0x02, 0x8E, 0xF8, 0x03, 0x20, 0x9C, 0xF8, 0x03, 0x20, 0x42, 0xF0, 0xC0, 0x02, 0x8C, 0xF8, 0x03, 0x20, ++0xFA, 0x78, 0x42, 0xF0, 0xC0, 0x02, 0xFA, 0x70, 0xC3, 0xF8, 0x14, 0x19, 0xFF, 0xF7, 0x86, 0xFD, 0xD8, 0xF8, 0x44, 0x30, ++0x89, 0xF8, 0x00, 0x40, 0x03, 0xB1, 0x98, 0x47, 0x26, 0x4B, 0x27, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0x04, 0x11, 0xD1, 0x67, ++0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF4, 0x00, 0x42, 0x01, 0x2D, 0x1A, 0x60, 0x23, 0xD0, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, ++0x02, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x03, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x9A, 0x68, 0xD2, 0x07, 0x14, 0xD5, 0x9A, 0x68, ++0x22, 0xF0, 0x01, 0x02, 0x9A, 0x60, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, 0xFF, 0xF7, ++0xC9, 0xFC, 0xD9, 0xE7, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x14, 0x48, 0xFD, 0xF7, 0x9C, 0xF9, 0x04, 0x20, 0xE2, 0xE7, ++0xFF, 0xF7, 0xBE, 0xFC, 0xCE, 0xE7, 0x11, 0x4B, 0x11, 0x48, 0x1B, 0x69, 0x1B, 0xF0, 0x5C, 0xFB, 0x33, 0x78, 0x04, 0x2B, ++0xFC, 0xD1, 0xD2, 0xE7, 0xFC, 0x83, 0x15, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x00, 0x00, 0x10, 0x40, 0x08, 0x84, 0x15, 0x00, ++0x00, 0x00, 0x20, 0x40, 0x60, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x44, 0x60, 0x17, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x84, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x34, 0x84, 0x15, 0x00, 0x20, 0x26, 0x17, 0x00, 0xB4, 0x27, 0x17, 0x00, 0x14, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0xC3, 0xF8, ++0x80, 0x20, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0x11, 0x4A, 0x11, 0x4B, 0x12, 0x48, 0x00, 0x21, 0x11, 0x70, ++0x9A, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x9A, 0x60, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, ++0x1A, 0x69, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x61, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, ++0x1A, 0x69, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x61, 0x48, 0x22, 0xF7, 0xF7, 0x9F, 0xB8, 0x00, 0xBF, 0x00, 0xE1, 0x00, 0xE0, ++0x6F, 0x26, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x4E, 0x1E, 0xF7, 0xB2, ++0x03, 0x2F, 0x41, 0xD8, 0x14, 0x46, 0x0D, 0x46, 0x9B, 0x46, 0x02, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0x04, 0xF0, 0xFD, 0x01, ++0x01, 0x29, 0x5B, 0xD0, 0xDF, 0x1C, 0xBF, 0x10, 0x7F, 0x00, 0xBF, 0xB2, 0xBA, 0x46, 0x4F, 0xEA, 0x07, 0x49, 0x4F, 0xEA, ++0x45, 0x18, 0x08, 0xF1, 0x80, 0x48, 0x08, 0xF5, 0x00, 0x18, 0xD8, 0xF8, 0x00, 0x19, 0x11, 0xF0, 0x80, 0x2F, 0x68, 0xD1, ++0xA2, 0x04, 0x02, 0xF4, 0x40, 0x22, 0xCB, 0xF3, 0x0A, 0x03, 0x3B, 0x4C, 0x13, 0x43, 0x43, 0xEA, 0x85, 0x53, 0x21, 0x88, ++0x43, 0xF0, 0xC0, 0x53, 0x43, 0xF4, 0x00, 0x43, 0xC8, 0xF8, 0x00, 0x39, 0x01, 0xEB, 0x0A, 0x03, 0xB3, 0xF5, 0xC0, 0x6F, ++0x5E, 0xDC, 0x34, 0x4A, 0x40, 0x36, 0x02, 0xEB, 0x86, 0x06, 0x41, 0xEA, 0x09, 0x03, 0x73, 0x60, 0xD2, 0xF8, 0x1C, 0x38, ++0x0F, 0x44, 0x01, 0x21, 0x01, 0xFA, 0x05, 0xF5, 0x1D, 0x43, 0x27, 0x80, 0xC2, 0xF8, 0x1C, 0x58, 0xBD, 0xE8, 0xF8, 0x8F, ++0x4E, 0x01, 0x06, 0xF1, 0x80, 0x46, 0x06, 0xF5, 0x00, 0x16, 0xD6, 0xF8, 0x00, 0x2B, 0x12, 0xF0, 0x80, 0x2F, 0x33, 0xD1, ++0xA4, 0x04, 0x04, 0xF4, 0x40, 0x24, 0xCB, 0xF3, 0x0A, 0x03, 0x23, 0x43, 0x43, 0xF0, 0xC0, 0x53, 0x21, 0x4A, 0x43, 0xF4, ++0x00, 0x43, 0xC6, 0xF8, 0x00, 0x3B, 0xD2, 0xF8, 0x1C, 0x38, 0x4F, 0xF4, 0x80, 0x31, 0x01, 0xFA, 0x05, 0xF5, 0x1D, 0x43, ++0xC2, 0xF8, 0x1C, 0x58, 0xBD, 0xE8, 0xF8, 0x8F, 0xB3, 0xF5, 0x48, 0x7F, 0x20, 0xD8, 0xDF, 0x1C, 0xBF, 0x10, 0x7F, 0x00, ++0xBF, 0xB2, 0xBA, 0x46, 0x4F, 0xEA, 0x07, 0x49, 0xBB, 0xF5, 0x80, 0x6F, 0x9D, 0xD9, 0x6F, 0xF4, 0x80, 0x63, 0x0B, 0xEB, ++0x03, 0x01, 0xB1, 0xF5, 0x80, 0x6F, 0x25, 0xBF, 0x10, 0x4B, 0xA3, 0xFB, 0x0B, 0x13, 0x4F, 0xEA, 0x5B, 0x0B, 0xC3, 0xF3, ++0x4F, 0x0B, 0x8E, 0xE7, 0xFF, 0xF7, 0x34, 0xFE, 0xC8, 0xE7, 0x10, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0x2F, 0xFE, 0x91, 0xE7, ++0x4F, 0xF4, 0xC8, 0x7A, 0x57, 0x46, 0x4F, 0xF0, 0xC8, 0x79, 0xDF, 0xE7, 0x06, 0x48, 0x52, 0x46, 0x4F, 0xF4, 0xC0, 0x63, ++0xFD, 0xF7, 0x9E, 0xF8, 0x21, 0x88, 0x98, 0xE7, 0x48, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xAB, 0xAA, 0xAA, 0xAA, ++0x40, 0x84, 0x15, 0x00, 0xF8, 0xB5, 0x27, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x3C, 0xD1, 0x44, 0x1E, 0xDF, 0xB2, 0xE3, 0xB2, ++0x04, 0x2B, 0x39, 0xD8, 0x8D, 0x07, 0x3D, 0xD1, 0x22, 0x4E, 0x4F, 0xEA, 0x04, 0x1E, 0x06, 0xEB, 0x04, 0x1C, 0x56, 0xF8, ++0x0E, 0x50, 0x8D, 0xBB, 0x43, 0x01, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x00, 0x13, 0xD3, 0xF8, 0x00, 0x0B, 0x00, 0x04, ++0x2A, 0xD5, 0x1B, 0x48, 0x46, 0xF8, 0x0E, 0x10, 0x50, 0xF8, 0x24, 0x00, 0x19, 0x4F, 0x01, 0x26, 0x8C, 0xF8, 0x08, 0x60, ++0xC6, 0x78, 0x64, 0x01, 0x04, 0xF1, 0x80, 0x44, 0xBA, 0x42, 0x04, 0xF5, 0x00, 0x14, 0x06, 0xF0, 0x31, 0x06, 0x28, 0xBF, ++0x3A, 0x46, 0x46, 0xF0, 0x0E, 0x06, 0xCC, 0xF8, 0x04, 0x20, 0x02, 0x80, 0x41, 0x60, 0xC6, 0x70, 0xC4, 0xF8, 0x34, 0x0B, ++0xD3, 0xF8, 0x00, 0x2B, 0x42, 0xF0, 0x04, 0x42, 0x28, 0x46, 0xC3, 0xF8, 0x00, 0x2B, 0xF8, 0xBD, 0x01, 0x20, 0xF8, 0xBD, ++0x02, 0x20, 0xF8, 0xBD, 0x38, 0x46, 0xF8, 0xBD, 0x05, 0x20, 0xF8, 0xBD, 0x06, 0x48, 0xFD, 0xF7, 0x47, 0xF8, 0x03, 0x20, ++0xF8, 0xBD, 0x00, 0xBF, 0x6F, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, 0xFF, 0xFF, 0x07, 0x00, ++0x80, 0x84, 0x15, 0x00, 0xF8, 0xB5, 0x28, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x3E, 0xD1, 0x44, 0x1E, 0xDF, 0xB2, 0xE3, 0xB2, ++0x04, 0x2B, 0x3B, 0xD8, 0x8D, 0x07, 0x3F, 0xD1, 0x23, 0x4E, 0x4F, 0xEA, 0x04, 0x1E, 0x06, 0xEB, 0x04, 0x1C, 0x56, 0xF8, ++0x0E, 0x50, 0x9D, 0xBB, 0x43, 0x01, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x00, 0x13, 0xD3, 0xF8, 0x00, 0x0B, 0x00, 0x04, ++0x2C, 0xD5, 0x1C, 0x48, 0x46, 0xF8, 0x0E, 0x10, 0x50, 0xF8, 0x24, 0x00, 0x1A, 0x4F, 0x01, 0x26, 0x8C, 0xF8, 0x08, 0x60, ++0xC6, 0x78, 0x64, 0x01, 0x04, 0xF1, 0x80, 0x44, 0xBA, 0x42, 0x04, 0xF5, 0x00, 0x14, 0x06, 0xF0, 0x31, 0x06, 0x28, 0xBF, ++0x3A, 0x46, 0x46, 0xF0, 0x0E, 0x06, 0xCC, 0xF8, 0x04, 0x20, 0x02, 0x80, 0x41, 0x60, 0xC6, 0x70, 0xC4, 0xF8, 0x34, 0x0B, ++0xD3, 0xF8, 0x00, 0x2B, 0x22, 0xF0, 0x04, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x28, 0x46, 0xC3, 0xF8, 0x00, 0x2B, 0xF8, 0xBD, ++0x01, 0x20, 0xF8, 0xBD, 0x02, 0x20, 0xF8, 0xBD, 0x38, 0x46, 0xF8, 0xBD, 0x05, 0x20, 0xF8, 0xBD, 0x06, 0x48, 0xFC, 0xF7, ++0xEB, 0xFF, 0x03, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x6F, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, ++0xFF, 0xFF, 0x07, 0x00, 0x80, 0x84, 0x15, 0x00, 0x10, 0xB5, 0x0C, 0x4C, 0x0C, 0x4B, 0xE0, 0x89, 0x18, 0x80, 0x20, 0xB9, ++0x0B, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x0A, 0x4B, 0x5B, 0x69, 0x4B, 0xB1, 0xC0, 0xB2, 0x98, 0x47, ++0x30, 0xB1, 0x06, 0x4A, 0x04, 0x21, 0x07, 0x23, 0x11, 0x70, 0x23, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, ++0xB4, 0x27, 0x17, 0x00, 0x6C, 0x26, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x46, ++0x00, 0x28, 0x70, 0xD1, 0x01, 0xF0, 0x21, 0x03, 0x21, 0x2B, 0x7F, 0xD0, 0xE1, 0x07, 0x76, 0xD5, 0x14, 0xF0, 0x08, 0x01, ++0x00, 0xF0, 0x8B, 0x80, 0xB5, 0x4D, 0x2B, 0x78, 0x00, 0x2B, 0x40, 0xF0, 0x76, 0x82, 0x63, 0x06, 0x40, 0xF1, 0x15, 0x81, ++0xB2, 0x4B, 0xD3, 0xF8, 0x14, 0x3B, 0x08, 0x3B, 0x00, 0x22, 0xC5, 0xE9, 0x01, 0x22, 0x02, 0x20, 0x28, 0x70, 0x1A, 0x78, ++0x29, 0x7B, 0xD2, 0x09, 0x62, 0xF3, 0xC7, 0x11, 0x29, 0x73, 0x19, 0x78, 0x2A, 0x7B, 0x49, 0x11, 0x61, 0xF3, 0x46, 0x12, ++0x2A, 0x73, 0x19, 0x78, 0x61, 0xF3, 0x04, 0x02, 0x2A, 0x73, 0x5A, 0x78, 0x6A, 0x73, 0xD9, 0x78, 0x9A, 0x78, 0x42, 0xEA, ++0x01, 0x22, 0xEA, 0x81, 0x59, 0x79, 0x1A, 0x79, 0x42, 0xEA, 0x01, 0x22, 0x2A, 0x82, 0xDA, 0x79, 0x9B, 0x79, 0x43, 0xEA, ++0x02, 0x23, 0x6B, 0x82, 0x23, 0xB9, 0x95, 0xF9, 0x0C, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x73, 0x82, 0x9A, 0x4B, 0x9B, 0x4C, ++0xD3, 0xF8, 0x14, 0x28, 0xE1, 0x68, 0x22, 0xF0, 0x10, 0x02, 0xC3, 0xF8, 0x14, 0x28, 0xD3, 0xF8, 0x10, 0x28, 0x22, 0xF0, ++0x10, 0x02, 0xC3, 0xF8, 0x10, 0x28, 0x21, 0xB1, 0x91, 0x48, 0x88, 0x47, 0x00, 0x28, 0x40, 0xF0, 0xB5, 0x80, 0x92, 0x4F, ++0x2B, 0x7B, 0x3A, 0x78, 0x13, 0xF0, 0x60, 0x0F, 0xD6, 0xB2, 0x40, 0xF0, 0xCF, 0x80, 0x68, 0x7B, 0x0B, 0x28, 0x00, 0xF2, ++0xDA, 0x80, 0xDF, 0xE8, 0x10, 0xF0, 0xDE, 0x00, 0x27, 0x01, 0xD8, 0x00, 0xFA, 0x00, 0xD8, 0x00, 0x8C, 0x00, 0x5D, 0x01, ++0xD8, 0x00, 0x4F, 0x01, 0x44, 0x01, 0x98, 0x01, 0x85, 0x01, 0x82, 0x4D, 0x2B, 0x78, 0x02, 0x2B, 0x53, 0xD0, 0xCA, 0x07, ++0x55, 0xD4, 0xA1, 0x06, 0x02, 0xD5, 0x2B, 0x78, 0x06, 0x2B, 0x3D, 0xD0, 0xF8, 0xBD, 0x7C, 0x4D, 0x22, 0x07, 0x2B, 0x78, ++0x35, 0xD5, 0x01, 0x2B, 0x8B, 0xD0, 0xF8, 0xBD, 0x79, 0x4A, 0xD2, 0xF8, 0x10, 0x3B, 0x03, 0xF0, 0x7F, 0x03, 0x40, 0x2B, ++0x7F, 0xF4, 0x78, 0xAF, 0xD2, 0xF8, 0x10, 0x3B, 0x18, 0x03, 0x7F, 0xF5, 0x73, 0xAF, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, ++0xDB, 0xBA, 0x74, 0x4B, 0x6F, 0x4D, 0x1E, 0x68, 0xF3, 0x78, 0x13, 0xF0, 0x01, 0x03, 0x40, 0xF0, 0xE2, 0x81, 0x2A, 0x78, ++0x02, 0x2A, 0x3F, 0xF4, 0x6E, 0xAF, 0x03, 0x2A, 0x00, 0xF0, 0xE6, 0x81, 0x05, 0x2A, 0x0D, 0xD1, 0x68, 0x4A, 0x2B, 0x70, ++0xD2, 0xF8, 0x14, 0x38, 0x23, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xD2, 0xF8, 0x10, 0x38, 0x23, 0xF0, 0x10, 0x03, ++0xC2, 0xF8, 0x10, 0x38, 0xFF, 0xF7, 0xBA, 0xFA, 0xBF, 0xE7, 0x02, 0x2B, 0xBD, 0xD1, 0x54, 0xE7, 0xFF, 0xF7, 0xB4, 0xFA, ++0x5D, 0x4A, 0x07, 0x23, 0x2B, 0x70, 0xD2, 0xF8, 0x14, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xBD, 0xE8, ++0xF8, 0x40, 0xFF, 0xF7, 0xC5, 0xBA, 0x5B, 0x48, 0xFC, 0xF7, 0xEC, 0xFE, 0x41, 0xE7, 0x04, 0x2B, 0x00, 0xF0, 0xDD, 0x81, ++0x07, 0x2B, 0xA4, 0xD1, 0x52, 0x4B, 0x57, 0x49, 0x00, 0x20, 0x28, 0x70, 0xD3, 0xF8, 0x14, 0x28, 0x22, 0xF0, 0x10, 0x02, ++0xC3, 0xF8, 0x14, 0x28, 0xD3, 0xF8, 0x10, 0x28, 0x22, 0xF0, 0x10, 0x02, 0xC3, 0xF8, 0x10, 0x28, 0x0A, 0x78, 0x00, 0x2A, ++0x96, 0xD0, 0xD3, 0xF8, 0x04, 0x48, 0x12, 0x01, 0x02, 0xF0, 0x70, 0x02, 0x24, 0xF0, 0x70, 0x04, 0x22, 0x43, 0xC3, 0xF8, ++0x04, 0x28, 0x08, 0x70, 0xF8, 0xBD, 0x43, 0x48, 0xE9, 0x89, 0xD0, 0xF8, 0x00, 0x28, 0x0B, 0x01, 0x22, 0xF4, 0xFE, 0x62, ++0x03, 0xF4, 0xFE, 0x63, 0x13, 0x43, 0x07, 0x22, 0xC0, 0xF8, 0x00, 0x38, 0x2A, 0x70, 0x00, 0x29, 0x40, 0xF0, 0xF2, 0x81, ++0x02, 0x23, 0x3B, 0x70, 0x04, 0x2E, 0x40, 0xF0, 0x9F, 0x80, 0x3B, 0x78, 0x04, 0x2B, 0x01, 0xD0, 0xFF, 0xF7, 0xE8, 0xFA, ++0x2B, 0x78, 0x03, 0x2B, 0x26, 0xD0, 0x04, 0x2B, 0x00, 0xF0, 0xAB, 0x80, 0x07, 0x2B, 0x00, 0xF0, 0x91, 0x80, 0x00, 0x24, ++0x22, 0x46, 0x20, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x2C, 0x70, 0xFF, 0xF7, 0x2F, 0xFB, 0x22, 0x46, 0x20, 0x46, 0x4F, 0xF4, ++0x00, 0x11, 0xFF, 0xF7, 0x85, 0xFB, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0x49, 0xBA, 0x2B, 0x4B, 0x1B, 0x68, 0x5B, 0x68, ++0xEA, 0xE6, 0x2C, 0x48, 0xFC, 0xF7, 0x8A, 0xFE, 0x04, 0x2E, 0xE4, 0xD1, 0x3B, 0x78, 0x04, 0x2B, 0xE1, 0xD0, 0xFF, 0xF7, ++0xBF, 0xFA, 0xDE, 0xE7, 0x6B, 0x68, 0x00, 0x2B, 0x7F, 0xF4, 0x57, 0xAF, 0x25, 0x4B, 0x6B, 0x60, 0x53, 0xE7, 0x04, 0x2E, ++0xD5, 0xD1, 0x3B, 0x78, 0x04, 0x2B, 0xF0, 0xD1, 0xD1, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0x00, 0xF0, 0xCB, 0x81, 0x2B, 0x8A, ++0x00, 0x2B, 0xE3, 0xD1, 0x2B, 0x7B, 0x03, 0xF0, 0x1F, 0x03, 0x01, 0x2B, 0x00, 0xF0, 0xCF, 0x81, 0x02, 0x2B, 0x00, 0xF0, ++0xC1, 0x80, 0x00, 0x2B, 0xE7, 0xD1, 0x19, 0x4A, 0x19, 0x4B, 0x12, 0x78, 0x1A, 0x80, 0x02, 0x21, 0x04, 0x22, 0x6B, 0x60, ++0x29, 0x81, 0x2A, 0x70, 0x5A, 0xE0, 0x3B, 0x78, 0x04, 0x2B, 0x02, 0xD0, 0x2B, 0x8A, 0x00, 0x2B, 0xC8, 0xD1, 0x2B, 0x7B, ++0x13, 0xF0, 0x1F, 0x03, 0x00, 0xF0, 0xB9, 0x81, 0x02, 0x2B, 0x03, 0xD1, 0xEB, 0x89, 0x00, 0x2B, 0x00, 0xF0, 0xBF, 0x81, ++0x07, 0x23, 0x04, 0x2E, 0x2B, 0x70, 0xA0, 0xD1, 0xC9, 0xE7, 0x00, 0xBF, 0xB4, 0x27, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, ++0x20, 0x26, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x98, 0x84, 0x15, 0x00, 0x70, 0x26, 0x17, 0x00, ++0xD8, 0x84, 0x15, 0x00, 0x74, 0x26, 0x17, 0x00, 0x6E, 0x26, 0x17, 0x00, 0x50, 0x28, 0x17, 0x00, 0x3B, 0x78, 0x04, 0x2B, ++0x02, 0xD0, 0x2B, 0x8A, 0x00, 0x2B, 0x9B, 0xD1, 0x2B, 0x7B, 0x03, 0xF0, 0x1F, 0x03, 0x02, 0x2B, 0xD8, 0xD1, 0xEB, 0x89, ++0x00, 0x2B, 0xD5, 0xD1, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, 0xC0, 0xF3, 0xC0, 0x10, 0xFF, 0xF7, 0xBF, 0xFB, 0x07, 0x23, ++0x04, 0x2E, 0x2B, 0x70, 0x00, 0xF0, 0x95, 0x81, 0xFF, 0xF7, 0xE6, 0xF9, 0xE7, 0xE6, 0xA9, 0x4B, 0xD3, 0xF8, 0xE0, 0x34, ++0x98, 0x47, 0x04, 0x46, 0x04, 0x2E, 0x5A, 0xD0, 0x00, 0x2C, 0x7F, 0xF4, 0x59, 0xAF, 0x60, 0xE7, 0xA4, 0x4B, 0x6B, 0x60, ++0x02, 0x22, 0x04, 0x23, 0x2A, 0x81, 0x2B, 0x70, 0x04, 0x2E, 0x3F, 0xF4, 0x4A, 0xAF, 0x29, 0x89, 0x68, 0x68, 0xFF, 0xF7, ++0x43, 0xFA, 0xCE, 0xE6, 0xE8, 0x89, 0x03, 0x0A, 0x01, 0x3B, 0x01, 0x0A, 0x0E, 0x2B, 0x3F, 0xF6, 0x62, 0xAF, 0x01, 0xA2, ++0x52, 0xF8, 0x23, 0xF0, 0xC1, 0x97, 0x12, 0x00, 0x05, 0x98, 0x12, 0x00, 0xF1, 0x97, 0x12, 0x00, 0xFF, 0x95, 0x12, 0x00, ++0xFF, 0x95, 0x12, 0x00, 0x65, 0x98, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, ++0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, ++0x45, 0x98, 0x12, 0x00, 0xA3, 0x69, 0x00, 0x2B, 0x3F, 0xF4, 0x40, 0xAF, 0xE9, 0x89, 0x28, 0x8A, 0x98, 0x47, 0x00, 0x28, ++0x3F, 0xF4, 0x3A, 0xAF, 0x85, 0x4A, 0x86, 0x4B, 0x29, 0x8A, 0x11, 0x80, 0xEA, 0x89, 0x1A, 0x70, 0x07, 0x23, 0x2B, 0x70, ++0x06, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0xDA, 0xB2, 0x7F, 0xF4, 0x2C, 0xAF, 0x7E, 0x4B, 0x7F, 0x49, 0x18, 0x88, 0x2A, 0x70, ++0x01, 0x23, 0x28, 0x82, 0x69, 0x60, 0x2B, 0x81, 0xAE, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0xA1, 0xD0, 0xFF, 0xF7, 0xE4, 0xF9, ++0x00, 0x2C, 0x7F, 0xF4, 0xF9, 0xAE, 0x00, 0xE7, 0x01, 0x46, 0xFF, 0xF7, 0x0B, 0xFB, 0x00, 0x28, 0x00, 0xF0, 0x05, 0x81, ++0x74, 0x4B, 0x01, 0x22, 0x1A, 0x80, 0x3A, 0xE7, 0x23, 0x68, 0x01, 0x20, 0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0x0A, 0xAF, ++0x03, 0x78, 0x12, 0x2B, 0x7F, 0xF4, 0x06, 0xAF, 0x42, 0x78, 0x01, 0x2A, 0x7F, 0xF4, 0x02, 0xAF, 0x2B, 0x81, 0x68, 0x60, ++0x6B, 0x8A, 0x2A, 0x89, 0x9A, 0x42, 0x88, 0xBF, 0x2B, 0x81, 0x04, 0x23, 0x2B, 0x70, 0x83, 0xE7, 0xA3, 0x68, 0xC0, 0xB2, ++0x98, 0x47, 0x68, 0x60, 0x00, 0x28, 0x3F, 0xF4, 0xF1, 0xAE, 0x03, 0x78, 0x2B, 0x81, 0xED, 0xE7, 0x63, 0x68, 0x00, 0x20, ++0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0xE8, 0xAE, 0x03, 0x78, 0x09, 0x2B, 0x7F, 0xF4, 0xE4, 0xAE, 0x43, 0x78, 0x02, 0x2B, ++0x7F, 0xF4, 0xE0, 0xAE, 0xC2, 0x78, 0x83, 0x78, 0x68, 0x60, 0x43, 0xEA, 0x02, 0x23, 0x2B, 0x81, 0xC3, 0x79, 0x58, 0x4A, ++0x13, 0xF0, 0x40, 0x0F, 0x13, 0x78, 0x14, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x70, 0xCD, 0xE7, ++0x23, 0x68, 0x0F, 0x20, 0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0xC8, 0xAE, 0x03, 0x78, 0x05, 0x2B, 0x7F, 0xF4, 0xC4, 0xAE, ++0x43, 0x78, 0x0F, 0x2B, 0x7F, 0xF4, 0xC0, 0xAE, 0x83, 0x78, 0xBB, 0xE7, 0x23, 0x68, 0x06, 0x20, 0x98, 0x47, 0x00, 0x28, ++0x3F, 0xF4, 0xB8, 0xAE, 0x03, 0x78, 0x0A, 0x2B, 0x7F, 0xF4, 0xB4, 0xAE, 0x42, 0x78, 0x06, 0x2A, 0x7F, 0xF4, 0xB0, 0xAE, ++0xAC, 0xE7, 0x2B, 0x78, 0x00, 0x2B, 0x51, 0xD1, 0x01, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x00, 0x21, 0x01, 0x20, 0xFF, 0xF7, ++0xB3, 0xFA, 0x84, 0xE5, 0x68, 0x89, 0x2B, 0x89, 0x36, 0x88, 0x6A, 0x68, 0x3C, 0x49, 0x1B, 0x1A, 0xC6, 0xF1, 0x40, 0x06, ++0x9B, 0xB2, 0x9E, 0x42, 0xA8, 0xBF, 0x1E, 0x46, 0x10, 0x44, 0x09, 0x68, 0xB2, 0xB2, 0x2D, 0xF0, 0x07, 0xFC, 0x6A, 0x89, ++0x2B, 0x89, 0x16, 0x44, 0xB6, 0xB2, 0xB3, 0x42, 0x6E, 0x81, 0x7F, 0xF4, 0x11, 0xAE, 0x33, 0x4B, 0x1B, 0x69, 0x0B, 0xB1, ++0x28, 0x46, 0x98, 0x47, 0xA0, 0x06, 0x35, 0xD4, 0x06, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x29, 0x89, 0x6A, 0x89, 0x88, 0x1A, ++0x80, 0xB2, 0x30, 0xB9, 0x05, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x2B, 0x48, 0xFC, 0xF7, 0x00, 0xFD, 0x88, 0xE5, 0x40, 0x28, ++0x22, 0xD0, 0x40, 0x28, 0x28, 0xBF, 0x40, 0x20, 0x00, 0x26, 0x02, 0x44, 0x92, 0xB2, 0x91, 0x42, 0x6A, 0x81, 0x29, 0xD3, ++0x89, 0x1A, 0x89, 0xB2, 0x40, 0x29, 0x0F, 0xD8, 0x79, 0xB9, 0x66, 0xBB, 0x21, 0x4A, 0x05, 0x23, 0x2B, 0x70, 0xD2, 0xF8, ++0x10, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x10, 0x38, 0xF8, 0xBD, 0x01, 0x20, 0xFF, 0xF7, 0x65, 0xFA, 0xA9, 0xE7, ++0x40, 0x21, 0x68, 0x68, 0x10, 0x44, 0xFF, 0xF7, 0x27, 0xF9, 0x98, 0xE5, 0x01, 0x26, 0xDE, 0xE7, 0xFF, 0xF7, 0x8E, 0xF8, ++0x15, 0x4A, 0x07, 0x23, 0x2B, 0x70, 0xD2, 0xF8, 0x14, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xFF, 0xF7, ++0xA1, 0xF8, 0x8A, 0xE5, 0x10, 0x48, 0xFC, 0xF7, 0xC7, 0xFC, 0x29, 0x89, 0x6A, 0x89, 0xCF, 0xE7, 0x03, 0x23, 0x3B, 0x70, ++0x0C, 0xE6, 0x08, 0x46, 0xFF, 0xF7, 0x0A, 0xF9, 0x7B, 0xE5, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x6C, 0x26, 0x17, 0x00, ++0x6A, 0x26, 0x17, 0x00, 0x68, 0x26, 0x17, 0x00, 0x50, 0x28, 0x17, 0x00, 0x6E, 0x26, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, ++0x20, 0x26, 0x17, 0x00, 0xB4, 0x84, 0x15, 0x00, 0x00, 0x00, 0x20, 0x40, 0xF0, 0x84, 0x15, 0x00, 0x2B, 0x7B, 0x03, 0xF0, ++0x1F, 0x03, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x7F, 0xF4, 0x39, 0xAE, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, 0x04, 0x29, ++0x2A, 0xD9, 0x17, 0x4B, 0x00, 0x22, 0x1A, 0x80, 0x35, 0xE6, 0xE8, 0x89, 0x02, 0x28, 0x19, 0xD0, 0x00, 0xF1, 0xFF, 0x3C, ++0x07, 0x23, 0xDC, 0xF1, 0x00, 0x04, 0x44, 0xEB, 0x0C, 0x04, 0x2B, 0x70, 0x7E, 0xE6, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, ++0xC0, 0xF3, 0xC0, 0x10, 0xFF, 0xF7, 0x18, 0xFA, 0x07, 0x23, 0x04, 0x2E, 0x2B, 0x70, 0x7F, 0xF4, 0x6B, 0xAE, 0x3B, 0x78, ++0x04, 0x2B, 0x3F, 0xF4, 0x67, 0xAE, 0xC9, 0xE5, 0x2B, 0x8A, 0x07, 0x49, 0x1B, 0x0A, 0x07, 0x22, 0x04, 0x2E, 0x0B, 0x70, ++0x2A, 0x70, 0x7F, 0xF4, 0x5D, 0xAE, 0xF0, 0xE7, 0xC0, 0xF3, 0xC0, 0x10, 0xC7, 0xE6, 0x00, 0xBF, 0x50, 0x28, 0x17, 0x00, ++0x70, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xB4, 0x4B, 0xB5, 0x4D, 0xD3, 0xF8, 0x00, 0x38, 0x13, 0xF4, 0xFE, 0x6F, ++0x03, 0xD0, 0x2B, 0x78, 0x04, 0x2B, 0x00, 0xF0, 0x8F, 0x81, 0xAF, 0x4C, 0xB0, 0x4A, 0xB1, 0x48, 0x00, 0x21, 0x02, 0x23, ++0x2B, 0x70, 0x11, 0x70, 0x1A, 0xF0, 0x1A, 0xFE, 0xD4, 0xF8, 0x00, 0x3E, 0x23, 0xF0, 0x01, 0x03, 0xC4, 0xF8, 0x00, 0x3E, ++0xD4, 0xF8, 0x04, 0x38, 0x23, 0xF0, 0x01, 0x03, 0xC4, 0xF8, 0x04, 0x38, 0xFF, 0xF7, 0x7E, 0xF8, 0xA3, 0x69, 0x1D, 0x06, ++0x03, 0xD5, 0xA3, 0x69, 0x23, 0xF0, 0x80, 0x03, 0xA3, 0x61, 0xA0, 0x4B, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF4, 0x00, 0x72, ++0xC3, 0xF8, 0x04, 0x28, 0x5A, 0x69, 0x14, 0x06, 0xFC, 0xD5, 0x01, 0x23, 0x01, 0x2B, 0x9E, 0x4C, 0x9E, 0x4D, 0x9F, 0x4A, ++0x9F, 0x4F, 0x4F, 0xF0, 0x02, 0x0C, 0x1C, 0xD0, 0x4F, 0xEA, 0x43, 0x1E, 0x5E, 0xF8, 0x02, 0x10, 0x11, 0xF0, 0x80, 0x2F, ++0x10, 0xD0, 0x5E, 0xF8, 0x02, 0x00, 0x00, 0x29, 0x40, 0xEA, 0x05, 0x00, 0x4E, 0xF8, 0x02, 0x00, 0xC0, 0xF2, 0x0F, 0x81, ++0x08, 0x04, 0x05, 0xD4, 0x5E, 0xF8, 0x02, 0x10, 0x21, 0xF4, 0x00, 0x41, 0x4E, 0xF8, 0x02, 0x10, 0x05, 0x2B, 0x0A, 0xD0, ++0x01, 0x33, 0x01, 0x2B, 0xE2, 0xD1, 0x21, 0x68, 0x11, 0xF0, 0x80, 0x2F, 0xF8, 0xD0, 0x21, 0x68, 0x29, 0x43, 0x21, 0x60, ++0xF4, 0xE7, 0x84, 0x4B, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF4, 0x80, 0x62, 0xC3, 0xF8, 0x04, 0x28, 0xD3, 0xF8, 0x04, 0x28, ++0x42, 0xF0, 0x80, 0x02, 0xC3, 0xF8, 0x04, 0x28, 0x5A, 0x69, 0x51, 0x06, 0xFC, 0xD5, 0x01, 0x23, 0x01, 0x2B, 0x83, 0x4F, ++0xDF, 0xF8, 0x40, 0x82, 0xDF, 0xF8, 0xF8, 0xC1, 0x81, 0x4D, 0xDF, 0xF8, 0x3C, 0xE2, 0x4F, 0xF0, 0x40, 0x06, 0x4F, 0xF0, ++0x02, 0x09, 0x19, 0xD0, 0x5A, 0x01, 0x05, 0xEB, 0x43, 0x10, 0x51, 0x59, 0x11, 0xF0, 0x80, 0x2F, 0x0D, 0xD0, 0x72, 0x44, ++0x16, 0x60, 0x04, 0x68, 0x00, 0x29, 0x44, 0xEA, 0x0C, 0x04, 0x04, 0x60, 0x11, 0xDB, 0x0A, 0x04, 0x03, 0xD4, 0x02, 0x68, ++0x22, 0xF4, 0x00, 0x42, 0x02, 0x60, 0x05, 0x2B, 0x1A, 0xD0, 0x01, 0x33, 0x01, 0x2B, 0xE5, 0xD1, 0x39, 0x68, 0x11, 0xF0, ++0x80, 0x2F, 0xF8, 0xD0, 0x42, 0x46, 0x38, 0x46, 0xE6, 0xE7, 0x8C, 0x03, 0x09, 0xD5, 0xC2, 0xF8, 0x00, 0x90, 0x04, 0x68, ++0x44, 0xF0, 0x80, 0x44, 0x04, 0x60, 0x14, 0x68, 0xA4, 0x07, 0xFC, 0xD5, 0xE1, 0xE7, 0x14, 0x68, 0x64, 0x06, 0xFC, 0xD5, ++0x16, 0x60, 0xF0, 0xE7, 0x5B, 0x4B, 0x4F, 0xF4, 0x86, 0x62, 0x1A, 0x61, 0x1A, 0x69, 0x12, 0xF0, 0x30, 0x0F, 0xFB, 0xD1, ++0xD3, 0xF8, 0x04, 0x28, 0x4F, 0xF0, 0x01, 0x14, 0x42, 0xF4, 0x80, 0x72, 0x29, 0x20, 0x09, 0x21, 0xC3, 0xF8, 0x04, 0x28, ++0xC3, 0xF8, 0x1C, 0x48, 0xC3, 0xF8, 0x14, 0x08, 0xC3, 0xF8, 0x10, 0x18, 0x9A, 0x69, 0x42, 0xF4, 0x40, 0x22, 0x9A, 0x61, ++0x9A, 0x6C, 0x14, 0x03, 0x4C, 0xD4, 0x4C, 0x4D, 0x55, 0x4B, 0xD5, 0xF8, 0x00, 0x28, 0x55, 0x48, 0x00, 0x24, 0x22, 0xF4, ++0xFE, 0x62, 0xC5, 0xF8, 0x00, 0x28, 0x21, 0x46, 0xC3, 0xE9, 0x01, 0x44, 0x40, 0x22, 0x1C, 0x70, 0xF6, 0xF7, 0xDE, 0xFA, ++0x21, 0x46, 0x40, 0x22, 0x4E, 0x48, 0xF6, 0xF7, 0xD9, 0xFA, 0x4E, 0x4A, 0x4E, 0x4B, 0x11, 0x68, 0x4E, 0x4A, 0x1B, 0x68, ++0x12, 0x68, 0x59, 0x60, 0xC5, 0xF8, 0x14, 0x3B, 0xD1, 0x78, 0x4C, 0x4B, 0x4C, 0x48, 0x1F, 0x68, 0x4C, 0x4B, 0x06, 0x6A, ++0x18, 0x68, 0xD3, 0xF8, 0x04, 0xC0, 0x41, 0xF0, 0xC0, 0x01, 0xD1, 0x70, 0xF9, 0x78, 0x41, 0xF0, 0xC0, 0x01, 0xF9, 0x70, ++0xC1, 0x78, 0x41, 0xF0, 0xC0, 0x01, 0xC1, 0x70, 0x9C, 0xF8, 0x03, 0x10, 0xD3, 0xE9, 0x02, 0x70, 0x41, 0xF0, 0xC0, 0x03, ++0x8C, 0xF8, 0x03, 0x30, 0xFB, 0x78, 0x43, 0xF0, 0xC0, 0x03, 0xFB, 0x70, 0xC3, 0x78, 0x43, 0xF0, 0xC0, 0x03, 0xC3, 0x70, ++0xC5, 0xF8, 0x14, 0x29, 0x0E, 0xB1, 0x20, 0x46, 0xB0, 0x47, 0xBD, 0xE8, 0xF8, 0x43, 0x3A, 0x48, 0x1A, 0xF0, 0x10, 0xBD, ++0x39, 0x49, 0x3A, 0x4C, 0x24, 0x4A, 0x40, 0xF2, 0x17, 0x15, 0x5D, 0x62, 0x4F, 0xF4, 0x9C, 0x70, 0x9C, 0x62, 0x08, 0x80, ++0xD3, 0xF8, 0x04, 0x18, 0x41, 0xF0, 0x80, 0x01, 0xC3, 0xF8, 0x04, 0x18, 0x53, 0x69, 0x58, 0x06, 0xFC, 0xD5, 0x1C, 0x49, ++0x0B, 0x69, 0x00, 0x2B, 0xFC, 0xDA, 0x4F, 0xF4, 0x84, 0x63, 0x19, 0x4A, 0x0B, 0x61, 0x13, 0x69, 0x99, 0x06, 0xFC, 0xD4, ++0xD2, 0xF8, 0x04, 0x38, 0x15, 0x49, 0x43, 0xF4, 0x80, 0x73, 0xC2, 0xF8, 0x04, 0x38, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, ++0x00, 0x73, 0xC2, 0xF8, 0x04, 0x38, 0x4B, 0x69, 0x1A, 0x06, 0xFC, 0xD5, 0x0B, 0x69, 0x0E, 0x4A, 0x43, 0xF0, 0x10, 0x03, ++0x0B, 0x61, 0x13, 0x69, 0xDB, 0x06, 0xFC, 0xD4, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x80, 0x63, 0xC2, 0xF8, 0x04, 0x38, ++0x75, 0xE7, 0x4E, 0xF8, 0x07, 0xC0, 0x5E, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x80, 0x40, 0x4E, 0xF8, 0x02, 0x00, 0x0E, 0xEB, ++0x07, 0x06, 0x30, 0x68, 0x80, 0x07, 0xFC, 0xD5, 0xE2, 0xE6, 0x00, 0xBF, 0x00, 0x00, 0x20, 0x40, 0x6F, 0x26, 0x17, 0x00, ++0x6E, 0x26, 0x17, 0x00, 0x20, 0x85, 0x15, 0x00, 0x00, 0x0B, 0x20, 0x40, 0x00, 0x80, 0x00, 0x08, 0xE0, 0x0A, 0x20, 0x40, ++0xE8, 0x0A, 0x20, 0x40, 0x00, 0x09, 0x20, 0x40, 0xE0, 0x08, 0x20, 0x40, 0xB4, 0x27, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, ++0xC8, 0x27, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x20, 0x26, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, 0x28, 0x85, 0x15, 0x00, 0x48, 0x28, 0x17, 0x00, 0x17, 0x01, 0x21, 0x00, ++0x08, 0x09, 0x20, 0x40, 0xE8, 0x08, 0x20, 0x40, 0x05, 0x48, 0x1E, 0x21, 0x1A, 0xF0, 0x90, 0xFC, 0x4F, 0xF4, 0xF0, 0x42, ++0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0x7F, 0xFC, 0x64, 0xE6, 0x0C, 0x85, 0x15, 0x00, 0x08, 0xB5, 0x04, 0x49, ++0x04, 0x48, 0x1A, 0xF0, 0x81, 0xFC, 0x04, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x08, 0xBD, 0x00, 0xBF, 0x54, 0x85, 0x15, 0x00, ++0xCC, 0xB5, 0x15, 0x00, 0x52, 0x28, 0x17, 0x00, 0x01, 0x4B, 0x18, 0x78, 0x70, 0x47, 0x00, 0xBF, 0x52, 0x28, 0x17, 0x00, ++0x08, 0xB5, 0x07, 0x48, 0x1A, 0xF0, 0x6C, 0xFC, 0x06, 0x4B, 0x07, 0x4A, 0x00, 0x21, 0x19, 0x70, 0xD2, 0xF8, 0x00, 0x3E, ++0x23, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x00, 0x3E, 0x08, 0xBD, 0x00, 0xBF, 0x30, 0x85, 0x15, 0x00, 0x52, 0x28, 0x17, 0x00, ++0x00, 0x00, 0x20, 0x40, 0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x1A, 0x4C, 0x1A, 0x4D, 0x23, 0x68, 0x2A, 0x78, 0x01, 0x33, 0x23, 0x60, 0x1A, 0xB1, 0x18, 0x4A, 0x12, 0x78, ++0x04, 0x2A, 0x08, 0xD0, 0x33, 0xB1, 0x13, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x38, 0xBD, 0x13, 0x4A, 0x13, 0x49, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x0A, 0x69, ++0x02, 0xF5, 0x0C, 0x52, 0x28, 0x32, 0x0B, 0x69, 0xD3, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x0B, 0x4A, 0x0C, 0x48, 0xD2, 0xF8, ++0x04, 0x38, 0x23, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x1A, 0xF0, 0x23, 0xFC, 0x00, 0x22, 0x23, 0x68, 0x2A, 0x70, ++0xD8, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x52, 0x28, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, ++0x00, 0x00, 0x20, 0x40, 0x00, 0x10, 0x50, 0x40, 0x3C, 0x85, 0x15, 0x00, 0x38, 0xB5, 0x04, 0x46, 0x0D, 0x46, 0xFF, 0xF7, ++0xB1, 0xFF, 0x15, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x20, 0xD1, 0x62, 0x1E, 0xD3, 0xB2, 0x04, 0x2B, 0x1E, 0xD8, 0x60, 0x01, ++0x00, 0xF1, 0x80, 0x40, 0x00, 0xF5, 0x00, 0x10, 0xD0, 0xF8, 0x00, 0x39, 0x1B, 0x04, 0x17, 0xD5, 0x0D, 0x49, 0x53, 0x01, ++0x03, 0xF1, 0x80, 0x43, 0x01, 0xEB, 0x02, 0x12, 0x03, 0xF5, 0x00, 0x13, 0x01, 0x21, 0xD1, 0x72, 0xC3, 0xF8, 0x34, 0x59, ++0xD0, 0xF8, 0x00, 0x39, 0x43, 0xF0, 0x04, 0x43, 0xC0, 0xF8, 0x00, 0x39, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x20, 0x38, 0xBD, ++0x02, 0x20, 0x38, 0xBD, 0x05, 0x20, 0x38, 0xBD, 0x6F, 0x26, 0x17, 0x00, 0xC8, 0x27, 0x17, 0x00, 0x93, 0x4B, 0x5A, 0x69, ++0x2D, 0xE9, 0xF0, 0x4F, 0x5A, 0x61, 0x9C, 0x69, 0x14, 0x40, 0xE1, 0x04, 0x85, 0xB0, 0x0A, 0xD5, 0x8F, 0x4B, 0xD3, 0xF8, ++0xDC, 0x34, 0x98, 0x47, 0x14, 0xF4, 0x00, 0x5A, 0x40, 0xF0, 0xAB, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, ++0x44, 0xA2, 0xA2, 0x04, 0x04, 0xEA, 0x0A, 0x0A, 0x04, 0xF4, 0x80, 0x25, 0x04, 0xF4, 0x00, 0x29, 0x04, 0xF4, 0x00, 0x6B, ++0x00, 0xF1, 0x9F, 0x80, 0x00, 0x2D, 0x42, 0xD0, 0x81, 0x4D, 0x83, 0x4E, 0xD5, 0xF8, 0x18, 0x28, 0xD5, 0xF8, 0x1C, 0x38, ++0x00, 0x24, 0x02, 0xEA, 0x03, 0x08, 0x01, 0x20, 0x00, 0xFA, 0x04, 0xF3, 0x13, 0xEA, 0x08, 0x0F, 0xE7, 0xB2, 0x2D, 0xD0, ++0x00, 0x2C, 0x00, 0xF0, 0xA0, 0x80, 0x63, 0x1E, 0x05, 0xEB, 0x43, 0x13, 0xD3, 0xF8, 0x28, 0x29, 0xC3, 0xF8, 0x28, 0x29, ++0xD5, 0xF8, 0x10, 0x18, 0x11, 0x40, 0x11, 0xF0, 0x09, 0x0F, 0x74, 0xD0, 0x16, 0xF8, 0x05, 0x3C, 0xD3, 0xB1, 0x56, 0xF8, ++0x0C, 0x3C, 0x01, 0x93, 0xD2, 0x43, 0x56, 0xF8, 0x10, 0x3C, 0x02, 0x93, 0x12, 0xF0, 0x01, 0x03, 0x00, 0x93, 0x40, 0xF0, ++0xB6, 0x80, 0x10, 0x22, 0x00, 0x21, 0xA6, 0xF1, 0x10, 0x00, 0xF6, 0xF7, 0x15, 0xF9, 0x6A, 0x4B, 0x03, 0xEB, 0x84, 0x03, ++0x1B, 0x6B, 0x1B, 0xB1, 0xDD, 0xE9, 0x00, 0x21, 0x02, 0x98, 0x98, 0x47, 0x04, 0x2F, 0x02, 0xD0, 0x01, 0x34, 0x10, 0x36, ++0xC5, 0xE7, 0xB9, 0xF1, 0x00, 0x0F, 0x3C, 0xD0, 0x5E, 0x4D, 0x62, 0x4E, 0xD5, 0xF8, 0x18, 0x78, 0xD5, 0xF8, 0x1C, 0x38, ++0xDF, 0xF8, 0x90, 0x81, 0xDF, 0xF8, 0x74, 0x91, 0x1F, 0x40, 0x00, 0x24, 0x4F, 0xF4, 0x80, 0x33, 0xA3, 0x40, 0x3B, 0x42, ++0x0C, 0xD0, 0xC4, 0xB1, 0x63, 0x1E, 0x05, 0xEB, 0x43, 0x13, 0xD3, 0xF8, 0x28, 0x2B, 0xC3, 0xF8, 0x28, 0x2B, 0xD5, 0xF8, ++0x14, 0x38, 0x13, 0x40, 0xDB, 0x07, 0x5F, 0xD4, 0xE3, 0xB2, 0x04, 0x2B, 0x1B, 0xD0, 0x01, 0x34, 0x4F, 0xF4, 0x80, 0x33, ++0xA3, 0x40, 0x3B, 0x42, 0x06, 0xF1, 0x10, 0x06, 0xF4, 0xD0, 0x00, 0x2C, 0xE6, 0xD1, 0xD5, 0xF8, 0x08, 0x1B, 0xC5, 0xF8, ++0x08, 0x1B, 0xD5, 0xF8, 0x14, 0x38, 0x0B, 0x40, 0xDA, 0x06, 0x7B, 0xD4, 0x13, 0xF0, 0x29, 0x0F, 0xE9, 0xD0, 0x44, 0x4B, ++0x20, 0x46, 0xD3, 0xF8, 0x00, 0x31, 0x98, 0x47, 0xE3, 0xE7, 0xBB, 0xF1, 0x00, 0x0F, 0x03, 0xD0, 0x3F, 0x4B, 0xD3, 0xF8, ++0x8C, 0x34, 0x98, 0x47, 0xBA, 0xF1, 0x00, 0x0F, 0xBF, 0xF6, 0x60, 0xAF, 0x3B, 0x4B, 0xD3, 0xF8, 0x90, 0x34, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x3C, 0x48, 0xFC, 0xF7, 0x56, 0xF9, 0xA4, 0xE7, 0x4F, 0xF0, 0x00, 0x0B, 0xD9, 0x46, ++0x5D, 0x46, 0x33, 0x4B, 0xD3, 0xF8, 0x08, 0x38, 0x13, 0xF0, 0x06, 0x0F, 0xC3, 0xF3, 0x47, 0x02, 0x04, 0xD0, 0xD3, 0x07, ++0x02, 0xD5, 0x34, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2C, 0x4B, 0x33, 0x4A, 0xC3, 0xF8, 0x00, 0x29, 0xC3, 0xF8, 0x00, 0x2B, ++0xFE, 0xF7, 0xF4, 0xFC, 0x4A, 0xE7, 0xD5, 0xF8, 0x08, 0x19, 0xC5, 0xF8, 0x08, 0x19, 0xD5, 0xF8, 0x10, 0x38, 0x0B, 0x40, ++0x13, 0xF0, 0x18, 0x0F, 0x2B, 0xD1, 0xDF, 0x07, 0x80, 0xD5, 0x23, 0x4B, 0xD3, 0xF8, 0x00, 0x31, 0x98, 0x47, 0x7B, 0xE7, ++0x16, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0x9B, 0xD0, 0x58, 0xF8, 0x24, 0x30, 0x56, 0xF8, 0x0C, 0x1C, 0x1B, 0x88, 0x02, 0x93, ++0x30, 0x46, 0xA3, 0x00, 0x50, 0xF8, 0x10, 0x2D, 0x03, 0x92, 0x01, 0x91, 0x10, 0x22, 0x00, 0x21, 0x00, 0x93, 0xF6, 0xF7, ++0x71, 0xF8, 0x00, 0x9B, 0x4B, 0x44, 0x1B, 0x6A, 0x00, 0x2B, 0x85, 0xD0, 0xDD, 0xE9, 0x01, 0x01, 0x00, 0x22, 0x41, 0x1A, ++0x03, 0x98, 0x98, 0x47, 0x7E, 0xE7, 0x39, 0x46, 0xFE, 0xF7, 0x8A, 0xFE, 0x45, 0xE7, 0xD5, 0xF8, 0x10, 0x38, 0x23, 0xF0, ++0x10, 0x03, 0xC5, 0xF8, 0x10, 0x38, 0x22, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x20, 0x46, 0xFE, 0xF7, 0xE9, 0xFD, 0x49, 0xE7, ++0xD5, 0xF8, 0x14, 0x38, 0x23, 0xF0, 0x10, 0x03, 0xC5, 0xF8, 0x14, 0x38, 0x22, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x20, 0x46, ++0xFE, 0xF7, 0x80, 0xFD, 0x63, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x20, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x27, 0x17, 0x00, ++0x20, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x48, 0x85, 0x15, 0x00, 0x4C, 0x28, 0x17, 0x00, 0x00, 0x80, 0x00, 0x08, ++0x00, 0x3C, 0x0C, 0x88, 0x40, 0x60, 0x17, 0x00, 0x38, 0xB9, 0x0C, 0x4A, 0x0C, 0x4B, 0x10, 0x70, 0x18, 0x70, 0x0C, 0x4B, ++0x1B, 0x68, 0x5B, 0xB1, 0x18, 0x47, 0x01, 0x28, 0x09, 0xD0, 0x09, 0x4B, 0x02, 0x38, 0x1B, 0x68, 0x01, 0x28, 0x94, 0xBF, ++0x02, 0x20, 0x03, 0x20, 0x00, 0x2B, 0xF3, 0xD1, 0x70, 0x47, 0x05, 0x4A, 0x05, 0x4B, 0x10, 0x70, 0x18, 0x70, 0xEA, 0xE7, ++0x59, 0x28, 0x17, 0x00, 0x5A, 0x28, 0x17, 0x00, 0x60, 0x28, 0x17, 0x00, 0x5B, 0x28, 0x17, 0x00, 0x5C, 0x28, 0x17, 0x00, ++0x00, 0x48, 0x70, 0x47, 0x54, 0x86, 0x15, 0x00, 0x01, 0x28, 0x15, 0xD1, 0x08, 0xB5, 0x0B, 0x4B, 0x1B, 0x68, 0x0B, 0xB1, ++0x04, 0x20, 0x98, 0x47, 0x02, 0x22, 0x11, 0x46, 0x4F, 0xF4, 0x00, 0x73, 0x01, 0x20, 0xFE, 0xF7, 0x65, 0xFF, 0x4F, 0xF4, ++0x00, 0x73, 0x02, 0x22, 0x01, 0x21, 0x00, 0x20, 0xFE, 0xF7, 0x5E, 0xFF, 0x01, 0x20, 0x08, 0xBD, 0x00, 0x20, 0x70, 0x47, ++0x60, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x58, 0x4E, 0xDF, 0xF8, 0x9C, 0xE1, 0x33, 0x88, 0x57, 0x4C, 0x00, 0x2A, ++0x03, 0xF1, 0x01, 0x03, 0x0C, 0xBF, 0x02, 0x25, 0x03, 0x25, 0x9B, 0xB2, 0x00, 0x27, 0x33, 0x80, 0x8E, 0xF8, 0x00, 0x50, ++0x27, 0x70, 0x9E, 0xF8, 0x00, 0xC0, 0xBC, 0xF1, 0x02, 0x0F, 0x4C, 0xD1, 0x03, 0x29, 0x04, 0x46, 0x0D, 0x46, 0x8E, 0xF8, ++0x00, 0x70, 0x55, 0xD9, 0x43, 0x78, 0x4C, 0x4A, 0x07, 0x78, 0x12, 0x78, 0x90, 0xF8, 0x02, 0x80, 0x1B, 0x02, 0x03, 0xF4, ++0x70, 0x63, 0x1F, 0x43, 0x00, 0x2A, 0x78, 0xD1, 0xB8, 0xF1, 0x01, 0x0F, 0x64, 0xD0, 0xB8, 0xF1, 0x11, 0x0F, 0x55, 0xD1, ++0xDF, 0xF8, 0x44, 0x81, 0x98, 0xF8, 0x9D, 0x27, 0x98, 0xF8, 0x9E, 0x37, 0x9A, 0x42, 0x77, 0xD2, 0x3B, 0x1D, 0xAB, 0x42, ++0x02, 0xD0, 0x7B, 0x1D, 0x9D, 0x42, 0x6E, 0xD1, 0x3D, 0x4B, 0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x98, 0xF8, 0x9C, 0x37, ++0x3B, 0x49, 0x98, 0xF8, 0x9D, 0x27, 0x01, 0x33, 0xA1, 0xFB, 0x03, 0x01, 0x49, 0x09, 0x01, 0xEB, 0x81, 0x01, 0xA3, 0xEB, ++0xC1, 0x01, 0x08, 0xEB, 0x01, 0x15, 0x04, 0x34, 0x53, 0x1C, 0x88, 0xF8, 0x9C, 0x17, 0x34, 0x48, 0xC5, 0xF8, 0x20, 0x45, ++0x05, 0xF2, 0x1C, 0x51, 0xC5, 0xF8, 0x24, 0x75, 0x88, 0xF8, 0x9D, 0x37, 0x19, 0xF0, 0x22, 0xF8, 0x4F, 0xF4, 0x00, 0x00, ++0x18, 0xF0, 0x7C, 0xFF, 0x0B, 0xE0, 0x9E, 0xF8, 0x00, 0x10, 0x2C, 0x48, 0xFC, 0xF7, 0x28, 0xF8, 0x47, 0xF2, 0x30, 0x52, ++0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0xE1, 0xF9, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x31, 0x88, 0x26, 0x48, ++0x89, 0xB2, 0x2A, 0x46, 0xFC, 0xF7, 0x18, 0xF8, 0x24, 0x4B, 0x18, 0x68, 0x20, 0x1A, 0xFD, 0xF7, 0x05, 0xF9, 0x1D, 0x4B, ++0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x41, 0x46, 0x1F, 0x48, 0xFC, 0xF7, 0x08, 0xF8, ++0x31, 0x88, 0x1E, 0x48, 0x89, 0xB2, 0x2B, 0x46, 0x3A, 0x46, 0xFC, 0xF7, 0x01, 0xF8, 0xE7, 0xE7, 0xBD, 0x42, 0x02, 0xD0, ++0x7B, 0x1C, 0xAB, 0x42, 0x12, 0xD1, 0x11, 0x4D, 0xD5, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x20, 0x1D, 0xD5, 0xF8, 0x0C, 0x31, ++0x98, 0x47, 0x40, 0x20, 0x18, 0xF0, 0x3E, 0xFF, 0xCD, 0xE7, 0x0A, 0x46, 0x4F, 0xF4, 0x00, 0x70, 0x11, 0x49, 0x1A, 0xF0, ++0x03, 0xFA, 0x7F, 0xE7, 0x31, 0x88, 0x10, 0x48, 0xDE, 0xE7, 0x31, 0x88, 0x0F, 0x48, 0xDB, 0xE7, 0x0F, 0x48, 0xFB, 0xF7, ++0xDF, 0xFF, 0xC5, 0xE7, 0x56, 0x28, 0x17, 0x00, 0x58, 0x28, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xCD, 0xCC, 0xCC, 0xCC, 0xF8, 0x5F, 0x17, 0x00, 0xD0, 0x85, 0x15, 0x00, 0xC0, 0x85, 0x15, 0x00, 0x80, 0x1A, 0x17, 0x00, ++0xB0, 0x85, 0x15, 0x00, 0x78, 0x85, 0x15, 0x00, 0x68, 0x85, 0x15, 0x00, 0x70, 0x85, 0x15, 0x00, 0x84, 0x85, 0x15, 0x00, ++0x98, 0x85, 0x15, 0x00, 0x59, 0x28, 0x17, 0x00, 0x58, 0x58, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x2A, 0x2A, 0x4B, ++0x0C, 0xBF, 0x02, 0x21, 0x03, 0x21, 0x19, 0x70, 0x19, 0x78, 0x02, 0x29, 0x3D, 0xD1, 0x27, 0x4C, 0x22, 0x78, 0x00, 0x21, ++0x19, 0x70, 0x52, 0xB3, 0x25, 0x4D, 0x26, 0x4F, 0xA5, 0xF1, 0x08, 0x06, 0x0A, 0xE0, 0x01, 0x2A, 0x41, 0x46, 0x38, 0x46, ++0x28, 0xD1, 0x13, 0x2B, 0x40, 0x46, 0x01, 0xD0, 0xFD, 0xF7, 0x90, 0xF8, 0x23, 0x78, 0xD3, 0xB1, 0x28, 0x46, 0x18, 0xF0, ++0xCD, 0xFF, 0x42, 0x68, 0x23, 0x78, 0xD2, 0xF8, 0x04, 0x80, 0x01, 0x3B, 0x01, 0x46, 0x30, 0x46, 0x23, 0x70, 0x18, 0xF0, ++0x7F, 0xFF, 0x98, 0xF8, 0x02, 0x30, 0x1A, 0x09, 0xE3, 0xD1, 0x17, 0x4A, 0x13, 0x88, 0x10, 0x20, 0x01, 0x33, 0x13, 0x80, ++0x18, 0xF0, 0xD2, 0xFE, 0x23, 0x78, 0x00, 0x2B, 0xE4, 0xD1, 0x13, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x01, 0x20, ++0xBD, 0xE8, 0xF0, 0x81, 0xFB, 0xF7, 0x78, 0xFF, 0x40, 0x46, 0x20, 0x21, 0x1A, 0xF0, 0x1C, 0xFD, 0xD4, 0xE7, 0x19, 0x78, ++0x0C, 0x48, 0xFB, 0xF7, 0x6F, 0xFF, 0x47, 0xF2, 0x30, 0x52, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0x28, 0xF9, ++0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x5A, 0x28, 0x17, 0x00, 0x64, 0x60, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, ++0xF0, 0x85, 0x15, 0x00, 0x54, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x86, 0x15, 0x00, 0x10, 0x4B, 0x11, 0x49, ++0x11, 0x4A, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x00, 0x68, 0x18, 0x60, 0xDF, 0xF8, 0x44, 0x80, 0x0E, 0x4F, 0x0F, 0x4E, ++0x00, 0x23, 0x0B, 0x70, 0x13, 0x70, 0x29, 0x7A, 0xD8, 0xF8, 0x08, 0x31, 0x00, 0x39, 0x18, 0xBF, 0x01, 0x21, 0x38, 0x46, ++0x98, 0x47, 0x04, 0x46, 0x01, 0x46, 0x30, 0x46, 0x1A, 0xF0, 0x04, 0xF9, 0x00, 0x2C, 0xF0, 0xD1, 0x20, 0x46, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x60, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x5A, 0x28, 0x17, 0x00, 0x38, 0x1A, 0x17, 0x00, ++0x20, 0x86, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x1D, 0x4D, 0x2B, 0x78, 0xFB, 0xB9, 0xD8, 0xB1, 0x0A, 0x46, ++0xC9, 0xB1, 0x1B, 0x4F, 0x3B, 0x78, 0xE3, 0xB9, 0x1A, 0x4C, 0x01, 0x26, 0x3E, 0x70, 0xD4, 0xF8, 0x30, 0x3B, 0x23, 0xF0, ++0xFF, 0x53, 0x23, 0xF4, 0xC0, 0x13, 0x01, 0x46, 0xC4, 0xF8, 0x30, 0x3B, 0x30, 0x46, 0xFE, 0xF7, 0x7B, 0xFE, 0x04, 0x46, ++0xC8, 0xB9, 0x13, 0x4B, 0x1E, 0x70, 0x2B, 0x78, 0x73, 0xB9, 0x20, 0x46, 0xF8, 0xBD, 0x6F, 0xF0, 0x0A, 0x04, 0xFA, 0xE7, ++0x6F, 0xF0, 0x0D, 0x04, 0xF7, 0xE7, 0x39, 0x78, 0x0D, 0x48, 0xFB, 0xF7, 0xFD, 0xFE, 0x6F, 0xF0, 0x02, 0x04, 0xF0, 0xE7, ++0x31, 0x46, 0xFE, 0xF7, 0xB3, 0xFC, 0x3C, 0x70, 0x6F, 0xF0, 0x0D, 0x04, 0xE9, 0xE7, 0x01, 0x46, 0x07, 0x48, 0xFB, 0xF7, ++0xEF, 0xFE, 0x4F, 0xF0, 0xFF, 0x34, 0xE2, 0xE7, 0x5B, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, ++0x58, 0x28, 0x17, 0x00, 0x30, 0x86, 0x15, 0x00, 0x48, 0x86, 0x15, 0x00, 0xF8, 0xB5, 0x20, 0x4D, 0x2B, 0x78, 0x2B, 0xBB, ++0x08, 0xB3, 0x0A, 0x46, 0xF9, 0xB1, 0x1E, 0x4F, 0x3B, 0x78, 0x13, 0xBB, 0x1D, 0x4C, 0x01, 0x26, 0x3E, 0x70, 0xD4, 0xF8, ++0x30, 0x3B, 0x23, 0xF0, 0xFF, 0x53, 0x23, 0xF4, 0xC0, 0x13, 0xC4, 0xF8, 0x30, 0x3B, 0xD4, 0xF8, 0x00, 0x38, 0x43, 0xF4, ++0x00, 0x53, 0x01, 0x46, 0xC4, 0xF8, 0x00, 0x38, 0x30, 0x46, 0xFE, 0xF7, 0x87, 0xFE, 0x04, 0x46, 0xC8, 0xB9, 0x13, 0x4B, ++0x1E, 0x70, 0x2B, 0x78, 0x73, 0xB9, 0x20, 0x46, 0xF8, 0xBD, 0x6F, 0xF0, 0x0A, 0x04, 0xFA, 0xE7, 0x6F, 0xF0, 0x0D, 0x04, ++0xF7, 0xE7, 0x39, 0x78, 0x0D, 0x48, 0xFB, 0xF7, 0xAF, 0xFE, 0x6F, 0xF0, 0x02, 0x04, 0xF0, 0xE7, 0x31, 0x46, 0xFE, 0xF7, ++0x65, 0xFC, 0x3C, 0x70, 0x6F, 0xF0, 0x0D, 0x04, 0xE9, 0xE7, 0x01, 0x46, 0x07, 0x48, 0xFB, 0xF7, 0xA1, 0xFE, 0x4F, 0xF0, ++0xFF, 0x34, 0xE2, 0xE7, 0x5B, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x58, 0x28, 0x17, 0x00, ++0x30, 0x86, 0x15, 0x00, 0x48, 0x86, 0x15, 0x00, 0xF8, 0xB5, 0x26, 0x4C, 0xFF, 0xF7, 0xFE, 0xFB, 0x23, 0x78, 0x00, 0x2B, ++0x42, 0xD1, 0x24, 0x4D, 0x28, 0x46, 0x18, 0xF0, 0xFB, 0xFE, 0xDF, 0xF8, 0x90, 0xC0, 0xC0, 0xB2, 0x8C, 0xF8, 0x00, 0x00, ++0x00, 0x28, 0x31, 0xD0, 0x1F, 0x4A, 0x2F, 0x68, 0x42, 0xF2, 0x30, 0x03, 0x01, 0x28, 0xD6, 0x58, 0x28, 0xD0, 0xBD, 0x89, ++0xB3, 0x89, 0xAB, 0x42, 0x11, 0xD2, 0x39, 0x46, 0x03, 0x46, 0x03, 0xE0, 0x53, 0xB1, 0x95, 0x89, 0x0E, 0x46, 0x11, 0x46, ++0xC2, 0x1A, 0xD2, 0xB2, 0x01, 0x3B, 0xF5, 0xB1, 0x0A, 0x68, 0xDB, 0xB2, 0x00, 0x2A, 0xF3, 0xD1, 0x8C, 0xF8, 0x00, 0x30, ++0x0E, 0x46, 0xB3, 0x7B, 0x72, 0x68, 0x79, 0x68, 0x01, 0x3B, 0x02, 0xEB, 0xC3, 0x02, 0x01, 0x20, 0xD3, 0x78, 0x20, 0x70, ++0x23, 0xF0, 0x0A, 0x03, 0x43, 0xF0, 0x0A, 0x03, 0xD3, 0x70, 0x02, 0x20, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0x0A, 0xBC, ++0x00, 0x2E, 0xEA, 0xD1, 0x6F, 0xF0, 0x61, 0x00, 0xF8, 0xBD, 0x8C, 0xF8, 0x00, 0x20, 0xE4, 0xE7, 0x6F, 0xF0, 0x62, 0x00, ++0xF8, 0xBD, 0x00, 0xBF, 0x5A, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x64, 0x60, 0x17, 0x00, ++0x01, 0x28, 0x07, 0xD0, 0x06, 0x28, 0x07, 0xD0, 0x04, 0x4B, 0x0F, 0x28, 0x0C, 0xBF, 0x18, 0x46, 0x00, 0x20, 0x70, 0x47, ++0x02, 0x48, 0x70, 0x47, 0x02, 0x48, 0x70, 0x47, 0x74, 0x86, 0x15, 0x00, 0x80, 0x86, 0x15, 0x00, 0x94, 0x86, 0x15, 0x00, ++0x06, 0x28, 0x0B, 0xD8, 0x01, 0x38, 0x05, 0x28, 0x16, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x05, 0x03, 0x13, 0x0F, 0x11, 0x03, ++0x09, 0x48, 0x70, 0x47, 0x09, 0x48, 0x70, 0x47, 0x12, 0x30, 0xC0, 0xB2, 0x06, 0x4B, 0x02, 0x28, 0x34, 0xBF, 0x18, 0x46, ++0x00, 0x20, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, ++0xC4, 0x86, 0x15, 0x00, 0xB4, 0x86, 0x15, 0x00, 0xA0, 0x86, 0x15, 0x00, 0xA8, 0x86, 0x15, 0x00, 0xD8, 0x86, 0x15, 0x00, ++0xEC, 0x86, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x1D, 0x4F, 0x1E, 0x48, 0x18, 0xF0, 0xE4, 0xFD, 0x3B, 0x68, 0x1B, 0x89, ++0x93, 0xB3, 0xDF, 0xF8, 0x7C, 0x90, 0x1B, 0x4E, 0xDF, 0xF8, 0x78, 0x80, 0xDF, 0xF8, 0x78, 0xB0, 0xDF, 0xF8, 0x78, 0xA0, ++0x00, 0x25, 0x0C, 0xE0, 0x21, 0x46, 0x15, 0x48, 0x18, 0xF0, 0xD6, 0xFD, 0x3A, 0x68, 0x33, 0x88, 0x11, 0x89, 0x01, 0x35, ++0xAA, 0xB2, 0x01, 0x33, 0x91, 0x42, 0x33, 0x80, 0x1A, 0xD9, 0xB9, 0xF8, 0xD4, 0x10, 0x04, 0x39, 0x89, 0xB2, 0x40, 0x46, ++0xFC, 0xF7, 0x58, 0xFC, 0x04, 0x46, 0x00, 0x28, 0xE8, 0xD1, 0xA9, 0xB2, 0x58, 0x46, 0x19, 0xF0, 0x99, 0xFF, 0xDA, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDE, 0xDA, 0x07, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0xFB, 0x72, 0x1A, 0xF0, ++0x07, 0xFA, 0xD7, 0xE7, 0xBD, 0xE8, 0xF8, 0x8F, 0x78, 0x36, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xF0, 0x86, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x0C, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0xD2, 0xFD, 0x18, 0xB1, 0x0A, 0x4A, ++0x13, 0x88, 0x01, 0x3B, 0x13, 0x80, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, ++0x66, 0x28, 0x17, 0x00, 0x38, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x28, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x27, 0x4C, 0x28, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x65, 0xFD, 0x26, 0x4A, ++0x26, 0x49, 0x13, 0x88, 0x0D, 0x78, 0x01, 0x33, 0x9B, 0xB2, 0x13, 0x80, 0x24, 0x4A, 0x11, 0x78, 0x9D, 0xB9, 0x49, 0xB9, ++0x23, 0x68, 0x33, 0xB1, 0x1C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, ++0x1E, 0x49, 0x09, 0x78, 0x99, 0x42, 0xF1, 0xD8, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0x15, 0x70, 0x1B, 0xE0, 0x00, 0x29, ++0xEA, 0xD0, 0x19, 0x49, 0x09, 0x78, 0x99, 0x42, 0xE6, 0xD8, 0x18, 0x4B, 0x00, 0x21, 0x11, 0x70, 0xD3, 0xF8, 0x00, 0x28, ++0x22, 0xF4, 0x00, 0x52, 0xC3, 0xF8, 0x00, 0x28, 0xD3, 0xF8, 0x20, 0x2B, 0x8A, 0x42, 0x05, 0xDA, 0xD3, 0xF8, 0x20, 0x2B, ++0x42, 0xF0, 0x80, 0x62, 0xC3, 0xF8, 0x20, 0x2B, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0x17, 0xF0, 0xA9, 0xFF, 0x0D, 0x49, ++0x4F, 0xF4, 0x00, 0x70, 0x19, 0xF0, 0x4E, 0xFF, 0x0B, 0x4B, 0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0xC4, 0xE7, 0x00, 0xBF, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, 0x68, 0x60, 0x17, 0x00, ++0x64, 0x28, 0x17, 0x00, 0x88, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x87, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xF8, 0xB5, 0x0C, 0x4D, 0x0C, 0x48, 0x18, 0xF0, 0x01, 0xFD, 0x2B, 0x68, 0x9B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, ++0x00, 0x24, 0x7C, 0x21, 0x38, 0x46, 0xFC, 0xF7, 0x8D, 0xFB, 0x01, 0x46, 0x30, 0x46, 0x18, 0xF0, 0xF7, 0xFC, 0x2B, 0x68, ++0x01, 0x34, 0x9A, 0x88, 0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, 0x78, 0x36, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, ++0xE4, 0x25, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x1E, 0xFD, 0x23, 0x68, 0x33, 0xB1, ++0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, ++0xB9, 0xFC, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x48, ++0xFF, 0xF7, 0x5E, 0xFD, 0x03, 0x48, 0x19, 0xF0, 0x7B, 0xFE, 0x01, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0xFC, 0x87, 0x15, 0x00, ++0x28, 0x87, 0x15, 0x00, 0x70, 0xB5, 0x3C, 0x4D, 0x3C, 0x4C, 0x2A, 0x68, 0x3C, 0x49, 0x12, 0x69, 0x3C, 0x4B, 0x22, 0x60, ++0x02, 0xF1, 0x40, 0x06, 0x00, 0x24, 0x0E, 0x60, 0x3A, 0x4E, 0x98, 0x60, 0xC3, 0xE9, 0x00, 0x44, 0x21, 0x46, 0x10, 0x46, ++0x4F, 0xF4, 0xA0, 0x72, 0xC3, 0xE9, 0x04, 0x44, 0xDC, 0x60, 0xB4, 0x81, 0xF5, 0xF7, 0xEC, 0xFB, 0x2B, 0x68, 0x34, 0x49, ++0x58, 0x69, 0x34, 0x4A, 0x34, 0x4B, 0x08, 0x60, 0x21, 0x46, 0x00, 0xF1, 0x08, 0x04, 0x14, 0x60, 0x00, 0xF1, 0x10, 0x02, ++0x1A, 0x60, 0x00, 0xF1, 0x18, 0x02, 0x5A, 0x60, 0x00, 0xF1, 0x20, 0x02, 0x9A, 0x60, 0x2E, 0x4C, 0x00, 0xF1, 0x28, 0x02, ++0xDA, 0x60, 0x00, 0xF1, 0x30, 0x03, 0x4F, 0xF4, 0x4B, 0x62, 0x23, 0x60, 0xF5, 0xF7, 0xCE, 0xFB, 0x29, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2E, 0xDB, 0x27, 0x4B, 0x28, 0x49, 0xB3, 0xF8, 0xD4, 0x20, 0x0C, 0x68, 0xB3, 0xF8, ++0xD6, 0x00, 0xB3, 0xF8, 0xE6, 0x10, 0x25, 0x4D, 0x25, 0x4E, 0x12, 0x1B, 0x25, 0x4C, 0x04, 0x3A, 0x22, 0x60, 0x04, 0x38, ++0x24, 0x4C, 0x30, 0x60, 0x05, 0xFB, 0x01, 0xF1, 0x93, 0xF8, 0xE0, 0x00, 0x22, 0x4D, 0x20, 0x70, 0x22, 0x4A, 0x93, 0xF8, ++0xE1, 0x00, 0x28, 0x70, 0x93, 0xF8, 0xE2, 0x50, 0x20, 0x48, 0x15, 0x70, 0x20, 0x4C, 0x21, 0x4A, 0x93, 0xF8, 0xE3, 0x50, ++0x93, 0xF8, 0xE4, 0x30, 0x03, 0x70, 0x1F, 0x4B, 0x25, 0x70, 0x91, 0x42, 0xD4, 0xBF, 0x19, 0x60, 0x1A, 0x60, 0x01, 0x20, ++0x70, 0xBD, 0x2B, 0x68, 0x9B, 0x69, 0xB3, 0xF5, 0x4B, 0x6F, 0xCB, 0xD2, 0x19, 0x49, 0x1A, 0x48, 0x40, 0xF2, 0xF2, 0x22, ++0x1A, 0xF0, 0x76, 0xF8, 0xC4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, 0x58, 0x60, 0x17, 0x00, ++0xA4, 0x60, 0x17, 0x00, 0x8C, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, ++0x54, 0x60, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x40, 0x42, 0x0F, 0x00, ++0x9C, 0x60, 0x17, 0x00, 0x78, 0x60, 0x17, 0x00, 0x7C, 0x60, 0x17, 0x00, 0x88, 0x60, 0x17, 0x00, 0xA0, 0x60, 0x17, 0x00, ++0x68, 0x60, 0x17, 0x00, 0xA1, 0x60, 0x17, 0x00, 0xFF, 0xA2, 0xE1, 0x11, 0x6C, 0x60, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x3C, 0x87, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x43, 0x7E, 0x07, 0x7E, 0x09, 0x2B, 0x05, 0x46, 0x09, 0xD8, 0x49, 0x4A, ++0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x25, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x81, 0x80, 0x6B, 0x8B, ++0xDF, 0xF8, 0x30, 0x81, 0x1A, 0x07, 0x5A, 0xD4, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x83, 0x93, 0xF8, 0x64, 0x30, ++0x00, 0x2B, 0x73, 0xD0, 0x3E, 0x4B, 0xAE, 0x7D, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x63, 0xDB, 0x3C, 0x48, ++0x18, 0xF0, 0x0C, 0xFC, 0x04, 0x46, 0x00, 0x28, 0x4C, 0xD0, 0x3A, 0x48, 0xE1, 0x8B, 0x83, 0x5D, 0xE2, 0x6C, 0x4F, 0xF0, ++0x00, 0x09, 0x01, 0x33, 0x21, 0xF0, 0x01, 0x01, 0x83, 0x55, 0xE1, 0x83, 0xC4, 0xF8, 0x44, 0x90, 0x29, 0x46, 0xC2, 0xF8, ++0x10, 0x90, 0x20, 0x1D, 0x1C, 0x22, 0xC4, 0xF8, 0x2C, 0x90, 0x2C, 0xF0, 0xA9, 0xFA, 0x30, 0x4B, 0xE1, 0x8B, 0x1B, 0x68, ++0x84, 0xF8, 0x42, 0x90, 0xEB, 0x1A, 0x04, 0x3B, 0x21, 0xF4, 0x00, 0x42, 0x22, 0xF0, 0x02, 0x02, 0xA3, 0x64, 0x0B, 0x07, ++0xC4, 0xF8, 0x24, 0x90, 0xC4, 0xF8, 0x50, 0x90, 0xE2, 0x83, 0x29, 0xD4, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, ++0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x23, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, ++0x23, 0x20, 0x02, 0x44, 0x41, 0xF8, 0x23, 0x20, 0xA4, 0x20, 0x00, 0xFB, 0x07, 0x60, 0x99, 0x30, 0x21, 0x46, 0x08, 0xEB, ++0xC0, 0x00, 0xBD, 0xE8, 0xF8, 0x43, 0x18, 0xF0, 0x7F, 0xBB, 0x16, 0x48, 0x18, 0xF0, 0xC0, 0xFB, 0x05, 0x26, 0x04, 0x46, ++0x00, 0x28, 0xB2, 0xD1, 0x13, 0x4B, 0x16, 0x48, 0x99, 0x5D, 0xFB, 0xF7, 0x83, 0xFB, 0xFE, 0xE7, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x07, 0x80, 0x21, 0x46, 0x00, 0xF5, 0xA3, 0x60, 0xBD, 0xE8, 0xF8, 0x43, 0x18, 0xF0, 0x67, 0xBB, 0x05, 0x2E, ++0x99, 0xD9, 0x0E, 0x49, 0x0E, 0x48, 0x40, 0xF2, 0x5F, 0x32, 0x19, 0xF0, 0xB3, 0xFF, 0x92, 0xE7, 0x07, 0x4B, 0x18, 0x68, ++0x28, 0x1A, 0x04, 0x38, 0xBD, 0xE8, 0xF8, 0x43, 0xFC, 0xF7, 0x58, 0xBC, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x58, 0x17, 0x00, 0x74, 0x28, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x60, 0x87, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x88, 0x82, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x48, 0x81, ++0xDF, 0xF8, 0x48, 0x91, 0xDF, 0xF8, 0x48, 0xA1, 0x59, 0xE0, 0x47, 0x48, 0x18, 0xF0, 0x7A, 0xFB, 0x04, 0x46, 0xDF, 0xF8, ++0x40, 0xE1, 0x1C, 0x22, 0x29, 0x46, 0x04, 0x30, 0x00, 0x2C, 0x63, 0xD0, 0xB4, 0xF8, 0x1E, 0xB0, 0x1E, 0xF8, 0x07, 0xC0, ++0xE3, 0x6C, 0x66, 0x64, 0x2B, 0xF0, 0x01, 0x0B, 0x0C, 0xF1, 0x01, 0x0C, 0xA4, 0xF8, 0x1E, 0xB0, 0x1E, 0x61, 0xE6, 0x62, ++0x0E, 0xF8, 0x07, 0xC0, 0x2C, 0xF0, 0x16, 0xFA, 0x95, 0xF8, 0x20, 0x20, 0xE3, 0x8B, 0x38, 0x48, 0x12, 0xF0, 0x01, 0x0F, ++0x14, 0xBF, 0x4F, 0xF4, 0x00, 0x52, 0x4F, 0xF4, 0x08, 0x52, 0x2A, 0x61, 0x84, 0xF8, 0x42, 0x60, 0xC5, 0xE9, 0x05, 0x66, ++0x62, 0x7F, 0x10, 0x32, 0x92, 0x02, 0x45, 0xF8, 0x18, 0x2C, 0x21, 0x7F, 0x26, 0x65, 0xA4, 0x22, 0x99, 0x37, 0x23, 0xF4, ++0x00, 0x43, 0x12, 0xFB, 0x01, 0x77, 0x23, 0xF0, 0x02, 0x03, 0x4C, 0x3D, 0xA5, 0x64, 0x00, 0xEB, 0xC7, 0x00, 0xE3, 0x83, ++0x21, 0x46, 0x18, 0xF0, 0xF5, 0xFA, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x24, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x24, 0x4C, 0x24, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x2A, 0xFB, 0x98, 0xF8, 0x11, 0x35, ++0x22, 0x68, 0x01, 0x3B, 0x88, 0xF8, 0x11, 0x35, 0x3A, 0xBB, 0xD8, 0xF8, 0x14, 0x35, 0x00, 0x26, 0xDB, 0xB1, 0xD9, 0xF8, ++0x00, 0x20, 0x5D, 0x68, 0xB2, 0xF9, 0x00, 0x30, 0xAF, 0x7D, 0x00, 0x2B, 0x99, 0xDA, 0x05, 0x2F, 0x97, 0xD9, 0x18, 0x49, ++0x4F, 0xF4, 0x66, 0x72, 0x50, 0x46, 0x19, 0xF0, 0x1F, 0xFF, 0x90, 0xE7, 0x15, 0x48, 0x1E, 0xF8, 0x07, 0x10, 0xFB, 0xF7, ++0xD5, 0xFA, 0x14, 0x4B, 0x18, 0x68, 0x28, 0x1A, 0x04, 0x38, 0xFC, 0xF7, 0xC1, 0xFB, 0x20, 0x20, 0x18, 0xF0, 0x3E, 0xFA, ++0xBD, 0xE8, 0xF8, 0x4F, 0x40, 0x20, 0x18, 0xF0, 0x15, 0xBA, 0x08, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0x22, 0x60, 0x00, 0x2A, ++0x7F, 0xF4, 0x74, 0xAF, 0x00, 0x2B, 0x3F, 0xF4, 0x71, 0xAF, 0x62, 0xB6, 0x6E, 0xE7, 0x00, 0xBF, 0x20, 0x58, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x60, 0x87, 0x15, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x58, 0x58, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x82, 0x15, 0x00, ++0x74, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xB8, 0x90, 0x29, 0x4D, 0x2A, 0x4F, 0xDF, 0xF8, 0xAC, 0x80, ++0x29, 0x4E, 0x20, 0xE0, 0x5C, 0x68, 0x20, 0x46, 0xFA, 0xF7, 0x1E, 0xFB, 0x38, 0x68, 0x20, 0x1A, 0x04, 0x38, 0xFC, 0xF7, ++0x81, 0xFB, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, ++0x00, 0x30, 0x30, 0x46, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0xB3, 0xFA, 0x95, 0xF8, 0x9D, 0x37, 0xD9, 0xF8, ++0x00, 0x20, 0x01, 0x3B, 0x85, 0xF8, 0x9D, 0x37, 0x0A, 0xBB, 0xD5, 0xF8, 0xA0, 0x37, 0x00, 0x2B, 0xDA, 0xD1, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x14, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x4F, 0xF4, ++0x00, 0x00, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0xD4, 0xF9, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x0D, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x01, 0x3A, ++0xD8, 0xF8, 0x00, 0x30, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, 0xB3, 0xD1, 0x00, 0x2B, 0xB1, 0xD0, 0x62, 0xB6, 0xAF, 0xE7, ++0x58, 0x58, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0xF8, 0x5F, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x0E, 0x4B, 0x10, 0xB5, 0xD3, 0xF8, 0x90, 0x32, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0A, 0x4C, 0x23, 0x68, 0x10, 0x20, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x9E, 0xF9, ++0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF8, 0xB5, 0x16, 0x4C, 0x16, 0x4E, 0x17, 0x4F, ++0x14, 0x4D, 0x15, 0xE0, 0x58, 0x68, 0xFC, 0xF7, 0x05, 0xFB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, ++0x01, 0x23, 0x33, 0x60, 0x3B, 0x68, 0x28, 0x46, 0x01, 0x33, 0x3B, 0x60, 0x18, 0xF0, 0x3A, 0xFA, 0x0E, 0x4A, 0x39, 0x68, ++0x13, 0x78, 0x01, 0x3B, 0x13, 0x70, 0x39, 0xB9, 0x23, 0x68, 0x00, 0x2B, 0xE6, 0xD1, 0xBD, 0xE8, 0xF8, 0x40, 0x08, 0x20, ++0x18, 0xF0, 0x6A, 0xB9, 0x01, 0x39, 0x33, 0x68, 0x39, 0x60, 0x00, 0x29, 0xDA, 0xD1, 0x00, 0x2B, 0xD8, 0xD0, 0x62, 0xB6, ++0xD6, 0xE7, 0x00, 0xBF, 0x94, 0x4E, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x8E, 0x4E, 0x17, 0x00, ++0x59, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x67, 0xD1, 0x2D, 0xE9, 0xF0, 0x47, 0x57, 0x4D, 0x2B, 0x78, 0x00, 0x2B, 0x47, 0xD1, ++0x56, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x5B, 0xD1, 0x55, 0x49, 0x56, 0x4A, 0x09, 0x78, 0x12, 0x88, 0x91, 0x42, 0x5E, 0xD2, ++0x54, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x04, 0x46, 0x00, 0x28, 0x78, 0xD0, 0x2B, 0x78, 0x00, 0x2B, ++0x4D, 0xD0, 0x4C, 0x4B, 0xDF, 0xF8, 0x60, 0xA1, 0x1B, 0x78, 0x4E, 0x4F, 0xDA, 0xF8, 0x00, 0x00, 0x00, 0x2B, 0x7B, 0xD1, ++0x4C, 0x4B, 0x39, 0x68, 0xD3, 0xF8, 0x40, 0x34, 0x20, 0x44, 0x98, 0x47, 0x00, 0x28, 0x39, 0xD0, 0x01, 0x46, 0x49, 0x48, ++0xDF, 0xF8, 0x08, 0x91, 0xDF, 0xF8, 0x18, 0x81, 0xFB, 0xF7, 0xAE, 0xF9, 0x05, 0x26, 0x2B, 0x78, 0x00, 0x2B, 0x48, 0xD1, ++0xDA, 0xF8, 0x00, 0x00, 0xD8, 0xF8, 0x40, 0x34, 0x39, 0x68, 0x20, 0x44, 0x98, 0x47, 0x28, 0xB3, 0x01, 0x3E, 0xF2, 0xD1, ++0x05, 0x21, 0x3F, 0x48, 0xFB, 0xF7, 0x9C, 0xF9, 0x20, 0x46, 0xFC, 0xF7, 0x8B, 0xFA, 0xBD, 0xE8, 0xF0, 0x47, 0x04, 0x20, ++0x18, 0xF0, 0xE2, 0xB8, 0x34, 0x4B, 0x1B, 0x88, 0x00, 0x2B, 0x46, 0xD0, 0x31, 0x4A, 0x12, 0x78, 0x9A, 0x42, 0xB9, 0xD3, ++0x36, 0x4A, 0x2E, 0x4B, 0x12, 0x68, 0x01, 0x21, 0x19, 0x70, 0x00, 0x2A, 0x47, 0xD1, 0x34, 0x4B, 0x34, 0x49, 0x1A, 0x88, ++0x4F, 0xF4, 0x00, 0x70, 0x92, 0xB2, 0x19, 0xF0, 0x97, 0xFB, 0xA9, 0xE7, 0xBD, 0xE8, 0xF0, 0x87, 0x70, 0x47, 0xDF, 0xF8, ++0xC8, 0xA0, 0x28, 0x4F, 0xDA, 0xF8, 0x00, 0x00, 0xB4, 0xE7, 0x1A, 0x78, 0x00, 0x2A, 0x9D, 0xD1, 0x28, 0x4A, 0x12, 0x68, ++0x01, 0x21, 0x19, 0x70, 0x92, 0xBB, 0x27, 0x4B, 0x27, 0x49, 0x1A, 0x88, 0xBD, 0xE8, 0xF0, 0x47, 0x4F, 0xF4, 0x00, 0x70, ++0x92, 0xB2, 0x19, 0xF0, 0x7B, 0xBB, 0x99, 0xF8, 0x00, 0x30, 0xDA, 0xF8, 0x00, 0x00, 0x2B, 0xB9, 0xD8, 0xF8, 0x40, 0x34, ++0x39, 0x68, 0x20, 0x44, 0x98, 0x47, 0xB2, 0xE7, 0x39, 0x68, 0x20, 0x44, 0xFF, 0xF7, 0x72, 0xFA, 0xAD, 0xE7, 0x04, 0x20, ++0x18, 0xF0, 0x9C, 0xF8, 0xBD, 0xE8, 0xF0, 0x47, 0x19, 0x48, 0xFB, 0xF7, 0x49, 0xB9, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x49, ++0x4F, 0xF4, 0x00, 0x70, 0x19, 0xF0, 0x5C, 0xBB, 0x39, 0x68, 0x20, 0x44, 0xFF, 0xF7, 0x5E, 0xFA, 0x84, 0xE7, 0x40, 0xF2, ++0x1F, 0x40, 0x17, 0xF0, 0xF9, 0xFA, 0xB2, 0xE7, 0x40, 0xF2, 0x1F, 0x40, 0x17, 0xF0, 0xF4, 0xFA, 0xC7, 0xE7, 0x00, 0xBF, ++0x58, 0x28, 0x17, 0x00, 0x68, 0x60, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0x7C, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, ++0xA4, 0x60, 0x17, 0x00, 0x78, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x8C, 0x87, 0x15, 0x00, 0xAC, 0x87, 0x15, 0x00, ++0x6C, 0x60, 0x17, 0x00, 0x56, 0x28, 0x17, 0x00, 0x7C, 0x87, 0x15, 0x00, 0x98, 0x87, 0x15, 0x00, 0x84, 0x87, 0x15, 0x00, ++0x80, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x0F, 0x48, 0x19, 0xF0, 0xD8, 0xFA, 0x0E, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, ++0x98, 0x47, 0x80, 0xB1, 0x0C, 0x4B, 0x0D, 0x49, 0x1A, 0x68, 0x0D, 0x4B, 0x09, 0x68, 0xD3, 0xF8, 0x40, 0x34, 0x10, 0x44, ++0x98, 0x47, 0x01, 0x1E, 0x00, 0xDB, 0x08, 0xBD, 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x48, 0xFB, 0xF7, 0xF7, 0xB8, 0xBD, 0xE8, ++0x08, 0x40, 0x07, 0x48, 0xFB, 0xF7, 0xF2, 0xB8, 0xC0, 0x87, 0x15, 0x00, 0xA4, 0x60, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, ++0x78, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xCC, 0x87, 0x15, 0x00, 0xE4, 0x87, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x20, ++0x18, 0xF0, 0x52, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x09, 0x4C, 0x0A, 0x4A, 0x23, 0x68, 0xD2, 0xF8, 0x3C, 0x24, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x33, 0xB1, ++0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x11, 0x4D, 0x11, 0x4F, 0x28, 0x68, 0x00, 0xF5, 0x0D, 0x70, ++0x18, 0xF0, 0xA4, 0xF8, 0x28, 0x68, 0x00, 0xF5, 0x0F, 0x70, 0x18, 0xF0, 0x9F, 0xF8, 0x3B, 0x68, 0x1B, 0x89, 0x93, 0xB1, ++0x0B, 0x4E, 0x00, 0x24, 0x4F, 0xF4, 0xD7, 0x61, 0x30, 0x46, 0xFB, 0xF7, 0x2B, 0xFF, 0x01, 0x46, 0x28, 0x68, 0x00, 0xF5, ++0x0D, 0x70, 0x18, 0xF0, 0x93, 0xF8, 0x3B, 0x68, 0x01, 0x34, 0x1A, 0x89, 0xA3, 0xB2, 0x9A, 0x42, 0xEE, 0xD8, 0xF8, 0xBD, ++0x00, 0x38, 0x18, 0x00, 0x78, 0x36, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x12, 0x4A, ++0x01, 0x46, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0E, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4C, 0x0E, 0x4A, 0x23, 0x68, 0x10, 0x68, 0x01, 0x33, 0x00, 0xF5, 0x0D, 0x70, 0x23, 0x60, ++0x18, 0xF0, 0x6C, 0xF8, 0x23, 0x68, 0x33, 0xB1, 0x06, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x02, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x4C, 0x40, 0x04, 0x40, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x00, 0x38, 0x18, 0x00, 0x08, 0xB5, 0x03, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x19, 0xF0, 0x7A, 0xFA, ++0x01, 0x20, 0x08, 0xBD, 0x08, 0x88, 0x15, 0x00, 0x05, 0x4A, 0x06, 0x49, 0x00, 0x23, 0xC2, 0xE9, 0x02, 0x03, 0xC2, 0xE9, ++0x04, 0x33, 0xC2, 0xE9, 0x00, 0x33, 0x8B, 0x81, 0x01, 0x20, 0x70, 0x47, 0xBC, 0x60, 0x17, 0x00, 0xD4, 0x60, 0x17, 0x00, ++0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x0C, 0x92, 0xDF, 0xF8, 0x0C, 0x82, 0xD9, 0xF8, 0x14, 0x35, 0x00, 0x2B, 0x00, 0xF0, ++0x8F, 0x80, 0xDF, 0xF8, 0xE8, 0xA1, 0xDF, 0xF8, 0x00, 0xB2, 0x78, 0xE0, 0x71, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, ++0x06, 0x12, 0x92, 0xF8, 0x64, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xB2, 0x80, 0x6D, 0x4A, 0x1F, 0x7A, 0x13, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA1, 0x80, 0x6A, 0x48, 0x18, 0xF0, 0x5B, 0xF8, 0x04, 0x46, 0x00, 0x28, 0x6C, 0xD0, ++0xC2, 0x8B, 0xC1, 0x6C, 0x1A, 0xF8, 0x07, 0xC0, 0x00, 0x23, 0x22, 0xF0, 0x01, 0x02, 0xC2, 0x83, 0x43, 0x64, 0x0C, 0xF1, ++0x01, 0x0C, 0x0B, 0x61, 0x1C, 0x22, 0xC3, 0x62, 0x29, 0x46, 0x04, 0x30, 0x0A, 0xF8, 0x07, 0xC0, 0x2B, 0xF0, 0xFA, 0xFE, ++0xE2, 0x8B, 0xDB, 0xF8, 0x00, 0x10, 0x6D, 0x1A, 0xC2, 0xF3, 0x0E, 0x01, 0x00, 0x23, 0xE1, 0x83, 0x11, 0x07, 0x84, 0xF8, ++0x42, 0x30, 0x23, 0x65, 0xA5, 0x64, 0x6F, 0xD4, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, ++0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x53, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x02, 0x44, ++0x41, 0xF8, 0x23, 0x20, 0xA4, 0x20, 0x00, 0xFB, 0x06, 0x76, 0x4A, 0x48, 0x99, 0x36, 0x21, 0x46, 0x00, 0xEB, 0xC6, 0x00, ++0x17, 0xF0, 0xD6, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x48, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xD8, 0xF8, 0x00, 0x30, 0x46, 0x48, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0x0A, 0xF8, 0x99, 0xF8, 0x11, 0x35, ++0xD8, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0x89, 0xF8, 0x11, 0x35, 0x3A, 0xB1, 0x3E, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, ++0x00, 0x20, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD9, 0xF8, 0x14, 0x35, 0x83, 0xB1, 0x5D, 0x68, 0x6A, 0x8B, 0x2E, 0x7E, ++0x14, 0x07, 0x81, 0xD5, 0x34, 0x48, 0x17, 0xF0, 0xEF, 0xFF, 0x05, 0x27, 0x04, 0x46, 0x00, 0x28, 0x92, 0xD1, 0x35, 0x4B, ++0x35, 0x48, 0xD9, 0x5D, 0xFA, 0xF7, 0xB2, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2E, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x20, 0x20, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x17, 0xF0, 0x14, 0xFF, ++0x40, 0x20, 0x17, 0xF0, 0xED, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x25, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, ++0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x24, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x21, 0x46, ++0x00, 0xFB, 0x06, 0x30, 0x17, 0xF0, 0x7A, 0xFF, 0xA2, 0xE7, 0x05, 0x2F, 0x7F, 0xF6, 0x5C, 0xAF, 0x1F, 0x49, 0x20, 0x48, ++0xB8, 0x22, 0x19, 0xF0, 0xC5, 0xFB, 0x55, 0xE7, 0xDB, 0xF8, 0x00, 0x00, 0x28, 0x1A, 0xFC, 0xF7, 0x6D, 0xF8, 0xEF, 0xF3, ++0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x12, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x11, 0x48, ++0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x17, 0xF0, 0x9F, 0xFF, 0x99, 0xF8, 0x11, 0x25, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0x3A, ++0x89, 0xF8, 0x11, 0x25, 0x00, 0x2B, 0x9B, 0xD0, 0x08, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x00, 0x2B, ++0x94, 0xD1, 0x00, 0x2A, 0x92, 0xD0, 0x90, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, ++0x7C, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x74, 0x28, 0x17, 0x00, 0x1C, 0x88, 0x15, 0x00, ++0x30, 0x8D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x88, 0x82, 0x15, 0x00, 0x58, 0x58, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x84, 0x1A, 0x17, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x04, 0x20, 0x17, 0xF0, ++0xA5, 0xBE, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0xD0, 0xF8, 0xA8, 0x44, 0xD1, 0xF8, 0xB0, 0x50, 0x07, 0x46, 0x0E, 0x46, ++0x00, 0x2C, 0x00, 0xF0, 0x8F, 0x80, 0xA2, 0x49, 0xA2, 0x4A, 0x4F, 0xF0, 0xFF, 0x33, 0x0B, 0x60, 0x13, 0x60, 0x94, 0xF8, ++0x60, 0x80, 0xB8, 0xF1, 0x04, 0x0F, 0x00, 0xF2, 0xB9, 0x81, 0xDF, 0xE8, 0x18, 0xF0, 0x49, 0x00, 0xF3, 0x00, 0x45, 0x01, ++0x03, 0x01, 0x05, 0x00, 0x9A, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, 0x22, 0x6F, ++0xDA, 0x60, 0x22, 0x6D, 0xDA, 0x61, 0x62, 0x6D, 0x1A, 0x62, 0xA2, 0x6D, 0x5A, 0x62, 0x94, 0x4B, 0x94, 0x4A, 0xE1, 0x6D, ++0x1B, 0x68, 0x11, 0x60, 0x1B, 0x78, 0x13, 0xF0, 0x02, 0x0F, 0xC1, 0x46, 0x4F, 0xF4, 0x80, 0x63, 0x4F, 0xF4, 0x80, 0x51, ++0x4F, 0xF0, 0x01, 0x08, 0x48, 0xD0, 0x97, 0xF8, 0x63, 0xC0, 0x94, 0xF8, 0x62, 0x00, 0x8C, 0x4A, 0x43, 0xEA, 0x0C, 0x13, ++0x43, 0xEA, 0x00, 0x43, 0x0B, 0x43, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0x00, 0x2D, ++0x48, 0xD0, 0x81, 0x4B, 0x7F, 0x49, 0xD6, 0xF8, 0x26, 0x00, 0x72, 0x8D, 0x08, 0x60, 0x1A, 0x60, 0x95, 0xF8, 0x60, 0x30, ++0x04, 0x2B, 0x00, 0xF2, 0x68, 0x81, 0xDF, 0xE8, 0x13, 0xF0, 0x78, 0x00, 0x41, 0x00, 0xD4, 0x00, 0xCF, 0x00, 0xC5, 0x00, ++0x00, 0x21, 0x4F, 0xF0, 0x01, 0x09, 0x77, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, ++0x22, 0x6F, 0xDA, 0x60, 0x73, 0x4B, 0x1B, 0x68, 0xB9, 0xF1, 0x02, 0x0F, 0x1B, 0x78, 0x40, 0xF0, 0xF2, 0x80, 0xD8, 0x07, ++0x40, 0xF1, 0x20, 0x81, 0x71, 0x48, 0x22, 0x6D, 0x02, 0x60, 0x62, 0x6D, 0x42, 0x60, 0xA2, 0x6D, 0x82, 0x60, 0xE2, 0x6D, ++0xC2, 0x60, 0x9B, 0x07, 0x00, 0xF1, 0xFF, 0x80, 0x4F, 0xF4, 0x00, 0x73, 0x97, 0xF8, 0x63, 0xC0, 0x94, 0xF8, 0x62, 0x00, ++0x67, 0x4A, 0x43, 0xEA, 0x0C, 0x13, 0x43, 0xEA, 0x00, 0x43, 0x0B, 0x43, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, ++0x58, 0x00, 0xFC, 0xD4, 0x00, 0x2D, 0xB6, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0xA1, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0xAE, 0xE7, ++0x4F, 0xF0, 0x02, 0x09, 0x59, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, ++0xDA, 0x60, 0xB9, 0xF1, 0x04, 0x0F, 0x40, 0xF0, 0x96, 0x80, 0x57, 0x4B, 0x2A, 0x6D, 0x1A, 0x60, 0x6A, 0x6D, 0x5A, 0x60, ++0xAA, 0x6D, 0x9A, 0x60, 0x50, 0x4B, 0x51, 0x4A, 0xE9, 0x6D, 0x1B, 0x68, 0x11, 0x60, 0x1B, 0x78, 0x99, 0x07, 0x40, 0xF1, ++0xD6, 0x80, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF4, 0x80, 0x69, 0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x4A, 0x4A, ++0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, 0x08, 0x03, 0x43, 0xEA, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, ++0x13, 0x68, 0x58, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x01, 0x09, 0x3D, 0x4B, ++0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, 0xDA, 0x60, 0xB9, 0xF1, 0x02, 0x0F, ++0x62, 0xD1, 0x38, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0xDA, 0x07, 0x40, 0xF1, 0xB3, 0x80, 0x38, 0x4A, 0x29, 0x6D, 0x11, 0x60, ++0x69, 0x6D, 0x51, 0x60, 0xA9, 0x6D, 0x91, 0x60, 0xE9, 0x6D, 0xD1, 0x60, 0x9A, 0x07, 0x7A, 0xD4, 0x4F, 0xF4, 0x00, 0x79, ++0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x2E, 0x4A, 0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, 0x08, 0x03, ++0x43, 0xEA, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x59, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, ++0x4F, 0xF0, 0x02, 0x09, 0x22, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, 0x22, 0x6F, ++0xDA, 0x60, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x01, 0x08, 0x51, 0xE7, 0x4F, 0xF0, 0x01, 0x09, 0xC8, 0x46, 0x4F, 0xF4, ++0x80, 0x51, 0x42, 0xE7, 0x18, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, ++0xDA, 0x60, 0x80, 0xE7, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF0, 0x01, 0x09, 0xA7, 0xE7, 0x95, 0xF8, 0x74, 0x30, 0x10, 0x2B, ++0x00, 0xF0, 0x83, 0x80, 0x20, 0x2B, 0x7B, 0xD0, 0x0D, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, ++0x9A, 0x60, 0x2A, 0x6F, 0xDA, 0x60, 0x4F, 0xF0, 0x03, 0x09, 0xB9, 0xF1, 0x02, 0x0F, 0x4F, 0xEA, 0x08, 0x38, 0x9C, 0xD0, ++0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9E, 0x07, 0x56, 0xD4, 0x4F, 0xEA, 0x09, 0x29, 0xA7, 0xE7, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0xD4, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, ++0xC8, 0x00, 0x32, 0x40, 0x94, 0xF8, 0x74, 0x30, 0x10, 0x2B, 0x5B, 0xD0, 0x20, 0x2B, 0x4A, 0xD0, 0x4F, 0xF0, 0x03, 0x09, ++0xA6, 0xE7, 0x9A, 0x07, 0x42, 0xD5, 0x09, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x01, 0x2B, 0x14, 0xD9, 0x4F, 0xEA, 0x09, 0x23, ++0xCB, 0xE6, 0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x3A, 0x4A, 0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, ++0x08, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, 0x97, 0xF8, ++0x63, 0x30, 0x94, 0xF8, 0x62, 0x00, 0x31, 0x4A, 0x41, 0xEA, 0x03, 0x13, 0x43, 0xEA, 0x00, 0x43, 0x43, 0xF0, 0x80, 0x43, ++0x13, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0xB9, 0xE6, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF4, 0x80, 0x69, 0x5F, 0xE7, ++0x29, 0x48, 0x02, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x02, 0x60, 0xE2, 0xE6, 0x26, 0x49, 0x0A, 0x68, 0x22, 0xF0, 0x01, 0x02, ++0x0A, 0x60, 0x4F, 0xE7, 0x09, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x01, 0x2B, 0xC7, 0xD9, 0x4F, 0xEA, 0x09, 0x29, 0x14, 0xE7, ++0x4F, 0xEA, 0x09, 0x23, 0xD6, 0xE6, 0x4F, 0xF4, 0x00, 0x51, 0x4F, 0xF0, 0x03, 0x09, 0xB0, 0xE6, 0x4F, 0xF4, 0x00, 0x58, ++0x4F, 0xF0, 0x03, 0x09, 0x1F, 0xE7, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x03, 0x09, 0x1A, 0xE7, 0x00, 0x21, 0x88, 0x46, ++0x4F, 0xF0, 0x03, 0x09, 0xA1, 0xE6, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xD6, 0xAE, ++0x12, 0x49, 0x13, 0x48, 0xA6, 0x22, 0x19, 0xF0, 0xA7, 0xF9, 0xCF, 0xE6, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x06, 0xDB, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x01, 0x08, 0x87, 0xE6, 0x09, 0x49, ++0x09, 0x48, 0x4F, 0x22, 0x19, 0xF0, 0x94, 0xF9, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x01, 0x08, ++0x7B, 0xE6, 0x00, 0xBF, 0xC4, 0x00, 0x32, 0x40, 0x64, 0x05, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xA3, 0x4E, 0x0D, 0x46, 0xD6, 0xF8, 0xF0, 0x70, 0x04, 0x46, 0xF4, 0xF7, ++0xF7, 0xFE, 0xB8, 0x47, 0xA0, 0x4A, 0xA1, 0x49, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x0A, 0x68, 0x9F, 0x4B, ++0x42, 0xF4, 0x80, 0x32, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x7F, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x02, ++0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xFE, 0x02, 0x42, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x97, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x4F, 0xF4, 0x40, 0x52, 0x00, 0x2B, 0xC1, 0xF8, 0x04, 0x21, 0xC0, 0xF2, 0xAD, 0x80, 0x92, 0x4B, 0x8E, 0x4A, ++0x92, 0x49, 0x19, 0x60, 0x13, 0x68, 0x92, 0x4F, 0x43, 0xF4, 0x00, 0x53, 0x13, 0x60, 0xF5, 0xF7, 0x49, 0xFD, 0xDF, 0xF8, ++0x9C, 0xC2, 0x8F, 0x49, 0xDC, 0xF8, 0x00, 0x20, 0x43, 0x1C, 0x9B, 0x06, 0x22, 0xF0, 0xE0, 0x52, 0x03, 0xF0, 0xE0, 0x53, ++0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0x0B, 0x68, 0x89, 0x4A, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, ++0x02, 0x03, 0x13, 0x60, 0x3B, 0x68, 0x9A, 0x03, 0x00, 0xF1, 0xAF, 0x80, 0x84, 0x4A, 0x28, 0x8C, 0x13, 0x68, 0x80, 0x49, ++0x9B, 0xB2, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x60, 0x0B, 0x68, 0x1F, 0x04, 0x00, 0xF1, 0x87, 0x80, 0x75, 0x4B, 0xDF, 0xF8, ++0x50, 0xE2, 0x1A, 0x68, 0xDF, 0xF8, 0x4C, 0xC2, 0x7C, 0x48, 0x7D, 0x4F, 0x7D, 0x49, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, ++0x4F, 0xF4, 0x40, 0x72, 0xCE, 0xF8, 0x00, 0x20, 0xE2, 0x6D, 0xCC, 0xF8, 0x00, 0x20, 0xB4, 0xF8, 0x60, 0x20, 0x02, 0x60, ++0xA2, 0x6B, 0xA0, 0x8F, 0x3A, 0x60, 0xD4, 0xF8, 0x90, 0x21, 0x08, 0x60, 0x91, 0x78, 0x74, 0x4A, 0x02, 0xEB, 0x81, 0x01, ++0x50, 0x68, 0x49, 0x69, 0xC7, 0xF8, 0xBC, 0x10, 0x19, 0x68, 0x21, 0xF4, 0xE0, 0x61, 0x19, 0x60, 0x13, 0x68, 0x6F, 0x49, ++0x6F, 0x4A, 0x03, 0x43, 0x3B, 0x64, 0x6F, 0x48, 0x6F, 0x4B, 0x08, 0x60, 0x13, 0x60, 0xD6, 0xF8, 0xB0, 0x31, 0x94, 0xF8, ++0x63, 0x10, 0x95, 0xF8, 0x23, 0x00, 0x98, 0x47, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x70, 0xFD, 0x09, 0xF0, 0xAC, 0xFB, ++0x68, 0x4B, 0x93, 0xF8, 0xB6, 0x30, 0x23, 0xB1, 0x67, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0xD6, 0xF8, ++0x60, 0x32, 0x98, 0x47, 0x64, 0x4A, 0x65, 0x49, 0xD6, 0xF8, 0x9C, 0x34, 0x11, 0x60, 0x98, 0x47, 0x4D, 0x4A, 0x63, 0x48, ++0x13, 0x68, 0x30, 0x24, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x01, 0x21, 0x04, 0x60, 0x00, 0x20, 0x17, 0xF0, 0xDE, 0xF9, ++0x5E, 0x4B, 0x1B, 0x68, 0x5A, 0x78, 0x22, 0xB1, 0x5D, 0x49, 0x0A, 0x68, 0x42, 0xF0, 0x40, 0x02, 0x0A, 0x60, 0x5C, 0x49, ++0x9B, 0x78, 0x0A, 0x68, 0xD8, 0x06, 0x4C, 0xBF, 0x22, 0xF0, 0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x58, 0x4A, ++0x13, 0xF0, 0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, 0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0x3C, 0x4B, 0x1B, 0x68, 0xB3, 0xF1, 0xC8, 0x5F, 0xBF, 0xF4, 0x4D, 0xAF, 0x50, 0x49, 0x50, 0x48, 0xF3, 0x22, ++0x19, 0xF0, 0x9C, 0xF8, 0x46, 0xE7, 0xF5, 0xF7, 0x35, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x74, 0xAF, 0x6B, 0x68, 0x9A, 0x06, ++0x7F, 0xF5, 0x70, 0xAF, 0x28, 0x8C, 0xF5, 0xF7, 0x71, 0xFC, 0x07, 0xF0, 0xB9, 0xFF, 0xD6, 0xF8, 0xE0, 0x33, 0x98, 0x47, ++0x94, 0xF8, 0x62, 0x30, 0x04, 0x2B, 0x3F, 0xF4, 0x63, 0xAF, 0xD6, 0xF8, 0x30, 0x33, 0x94, 0xF8, 0x63, 0x00, 0x98, 0x47, ++0x5C, 0xE7, 0xF5, 0xF7, 0x3F, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x4C, 0xAF, 0xF5, 0xF7, 0x6E, 0xFC, 0xDF, 0xF8, 0xF4, 0x80, ++0xD8, 0xF8, 0x00, 0x30, 0x00, 0x02, 0x23, 0xF4, 0xE0, 0x63, 0x00, 0xF4, 0xE0, 0x60, 0x18, 0x43, 0xC8, 0xF8, 0x00, 0x00, ++0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, ++0x43, 0xF0, 0x04, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF0, 0x01, 0x03, 0xC8, 0xF8, 0x00, 0x30, ++0x3B, 0x68, 0x1B, 0x04, 0x0F, 0xD4, 0x15, 0x4B, 0x1B, 0x68, 0x9B, 0x03, 0x7F, 0xF5, 0x22, 0xAF, 0xF5, 0xF7, 0x18, 0xFC, ++0x00, 0x28, 0x3F, 0xF4, 0x1D, 0xAF, 0x27, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x16, 0xE7, 0xF5, 0xF7, ++0xDF, 0xFB, 0x00, 0x28, 0xEB, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, 0x80, 0x63, 0xC8, 0xF8, ++0x00, 0x30, 0xE2, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x54, 0x00, 0x32, 0x40, 0x64, 0x00, 0x32, 0x40, ++0x38, 0x36, 0x17, 0x00, 0xD8, 0x00, 0x32, 0x40, 0x10, 0x19, 0x04, 0x00, 0x04, 0x00, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x68, 0x00, 0x32, 0x40, 0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0xC0, 0x07, 0xF9, 0x80, ++0x2C, 0x19, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, 0xC0, 0xB3, 0x33, 0x40, 0xA0, 0xA0, 0x28, 0x28, 0x38, 0x00, 0x32, 0x40, ++0x34, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, 0x80, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x40, 0x88, 0x15, 0x00, 0x50, 0x03, 0x32, 0x40, 0x9C, 0x00, 0x32, 0x40, 0x1C, 0x00, 0x32, 0x40, 0x10, 0x00, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x47, 0x5B, 0x4B, 0x5C, 0x4A, 0x1D, 0x68, 0xD2, 0xF8, 0x20, 0x80, 0x15, 0xF0, 0x01, 0x05, 0xD8, 0xF8, ++0xE4, 0x90, 0x84, 0xB0, 0x00, 0xF0, 0x83, 0x80, 0x1A, 0x68, 0x57, 0x4F, 0x22, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x00, 0x23, ++0x7B, 0x70, 0x01, 0x22, 0x54, 0x48, 0x55, 0x49, 0x03, 0x68, 0x55, 0x4C, 0x43, 0xF0, 0x10, 0x03, 0x03, 0x60, 0x0B, 0x68, ++0x00, 0xF5, 0xEC, 0x10, 0x00, 0xF6, 0x6C, 0x70, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x23, 0x68, 0x01, 0x69, 0x00, 0x91, ++0x02, 0x20, 0x4E, 0x49, 0x4E, 0x4C, 0x18, 0xF0, 0x9D, 0xFD, 0x3B, 0x78, 0x00, 0x2B, 0x42, 0xD0, 0xD4, 0xF8, 0x3C, 0x31, ++0xD8, 0xF8, 0x40, 0x60, 0x00, 0x20, 0x98, 0x47, 0x49, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x62, 0xDB, ++0xD4, 0xF8, 0x9C, 0x34, 0xDF, 0xF8, 0x38, 0xA1, 0x98, 0x47, 0xD4, 0xF8, 0x80, 0x34, 0x30, 0x79, 0x98, 0x47, 0x4F, 0xF0, ++0x00, 0x0C, 0x33, 0x89, 0xF2, 0x88, 0x71, 0x79, 0x30, 0x79, 0xCD, 0xF8, 0x08, 0xC0, 0x96, 0xF8, 0x0D, 0xC0, 0xCD, 0xF8, ++0x04, 0xC0, 0xB6, 0xF8, 0x0A, 0xC0, 0xCD, 0xF8, 0x00, 0xC0, 0xF5, 0xF7, 0x9F, 0xFA, 0xD4, 0xF8, 0x3C, 0x33, 0x96, 0xF9, ++0x0C, 0x00, 0x98, 0x47, 0x9A, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x33, 0xD0, 0xD4, 0xF8, 0xA8, 0x34, 0xBA, 0xF8, 0x26, 0x00, ++0x98, 0x47, 0xBA, 0xF8, 0x26, 0x00, 0xD4, 0xF8, 0xAC, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0xD8, 0x34, 0x49, 0x46, 0x40, 0x46, ++0x98, 0x47, 0x00, 0x23, 0xC7, 0xE9, 0x01, 0x33, 0x3B, 0x70, 0x00, 0x2D, 0x33, 0xD0, 0x2B, 0x49, 0x2B, 0x4A, 0x0B, 0x68, ++0x23, 0xF4, 0x00, 0x73, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x28, 0x4A, 0x28, 0x48, 0x13, 0x68, ++0x28, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x83, 0x68, 0xD4, 0xF8, 0xA0, 0x22, 0x5A, 0x65, ++0x20, 0x23, 0x0B, 0x60, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x16, 0x4F, 0x2A, 0x46, 0x81, 0xE7, 0xD4, 0xF8, 0xA0, 0x34, ++0xBA, 0xF8, 0x26, 0x00, 0x98, 0x47, 0xBA, 0xF8, 0x26, 0x00, 0xD4, 0xF8, 0xA4, 0x34, 0x98, 0x47, 0xCA, 0xE7, 0x33, 0x7E, ++0xFF, 0x2B, 0x99, 0xD1, 0x19, 0x49, 0x1A, 0x48, 0x40, 0xF2, 0x89, 0x12, 0x18, 0xF0, 0x4C, 0xFF, 0x92, 0xE7, 0x40, 0x46, ++0x0B, 0xF0, 0xF6, 0xF8, 0xD8, 0xF8, 0x04, 0x30, 0x15, 0x4A, 0x43, 0xF0, 0x01, 0x03, 0xC8, 0xF8, 0x04, 0x30, 0x92, 0xF8, ++0xB6, 0x30, 0x00, 0x2B, 0xC7, 0xD0, 0x03, 0xF0, 0x99, 0xF8, 0xC4, 0xE7, 0x10, 0x00, 0x58, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x3C, 0x36, 0x17, 0x00, 0x94, 0x80, 0x32, 0x40, 0x84, 0x40, 0x04, 0x40, 0x88, 0x00, 0x32, 0x40, 0x88, 0x88, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x8C, 0x00, 0x32, 0x40, 0x78, 0x00, 0x32, 0x40, ++0x00, 0xED, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE0, 0x70, 0x79, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0xF8, 0xB5, 0x3F, 0x4F, 0x3F, 0x4C, 0x3E, 0x6A, 0x3F, 0x49, 0xD6, 0xF8, 0xE4, 0x50, 0x4F, 0xF4, ++0xBE, 0x72, 0x20, 0x46, 0x2B, 0xF0, 0xB0, 0xF9, 0x31, 0x46, 0x4F, 0xF4, 0xA4, 0x62, 0x04, 0xF5, 0xBE, 0x70, 0x2B, 0xF0, ++0xA9, 0xF9, 0x29, 0x46, 0x4F, 0xF4, 0x1E, 0x72, 0x04, 0xF2, 0x9C, 0x60, 0x2B, 0xF0, 0xA2, 0xF9, 0x06, 0xF1, 0xEC, 0x01, ++0xE8, 0x22, 0x04, 0xF6, 0x14, 0x10, 0x2B, 0xF0, 0x9B, 0xF9, 0x31, 0x6C, 0x1C, 0x22, 0x04, 0xF6, 0xFC, 0x10, 0x2B, 0xF0, ++0x95, 0xF9, 0x2F, 0x49, 0x34, 0x22, 0x04, 0xF6, 0x18, 0x20, 0x2B, 0xF0, 0x8F, 0xF9, 0x2D, 0x49, 0x18, 0x22, 0x04, 0xF6, ++0x4C, 0x20, 0x2B, 0xF0, 0x89, 0xF9, 0x2B, 0x49, 0x4F, 0xF4, 0x40, 0x72, 0x04, 0xF6, 0x64, 0x20, 0x2B, 0xF0, 0x82, 0xF9, ++0x28, 0x49, 0x4F, 0xF4, 0x98, 0x62, 0x04, 0xF6, 0x64, 0x50, 0x2B, 0xF0, 0x7B, 0xF9, 0x26, 0x49, 0x26, 0x48, 0x40, 0x22, ++0x2B, 0xF0, 0x76, 0xF9, 0x39, 0x46, 0x28, 0x22, 0x24, 0x48, 0x2B, 0xF0, 0x71, 0xF9, 0x24, 0x49, 0x24, 0x48, 0x60, 0x22, ++0x2B, 0xF0, 0x6C, 0xF9, 0x23, 0x4A, 0x24, 0x4B, 0x12, 0x68, 0xD3, 0xF8, 0x84, 0x60, 0xB2, 0xF8, 0x3C, 0xC0, 0xD3, 0xF8, ++0x80, 0x20, 0xD3, 0xE9, 0x22, 0x07, 0x41, 0xF2, 0x10, 0x33, 0x41, 0xF2, 0x30, 0x31, 0x24, 0xF8, 0x03, 0xC0, 0x41, 0xF2, ++0x2C, 0x33, 0x66, 0x50, 0xE2, 0x50, 0x41, 0xF2, 0x38, 0x36, 0x41, 0xF2, 0x3C, 0x33, 0x41, 0xF2, 0x34, 0x31, 0x18, 0x4A, ++0xE2, 0x50, 0xA7, 0x51, 0x17, 0x4B, 0x60, 0x50, 0x05, 0xF5, 0xBC, 0x70, 0x05, 0xF5, 0xCE, 0x71, 0x50, 0xF8, 0x04, 0x2F, ++0x1A, 0xB1, 0x14, 0x7B, 0x9C, 0x70, 0x12, 0x89, 0x1A, 0x80, 0x88, 0x42, 0x03, 0xF1, 0x04, 0x03, 0xF4, 0xD1, 0xF8, 0xBD, ++0x1C, 0x9E, 0x17, 0x00, 0x00, 0x40, 0x1E, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0x34, 0xE0, 0x17, 0x00, 0xF4, 0xDF, 0x17, 0x00, 0x24, 0x52, 0x1E, 0x00, 0x64, 0x52, 0x1E, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x8C, 0x52, 0x1E, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, ++0xEC, 0x52, 0x1E, 0x00, 0x70, 0xB5, 0x65, 0x4A, 0x53, 0x78, 0x00, 0x2B, 0x7F, 0xD1, 0x64, 0x4B, 0x1B, 0x68, 0x3B, 0xB1, ++0x63, 0x48, 0xD9, 0x68, 0x00, 0x69, 0x09, 0x1A, 0xB1, 0xF5, 0xFA, 0x6F, 0x00, 0xF1, 0xA5, 0x80, 0x13, 0x78, 0x00, 0x2B, ++0x68, 0xD0, 0xD2, 0xE9, 0x01, 0x35, 0x5D, 0x48, 0x5D, 0x4A, 0x5E, 0x49, 0x04, 0x69, 0x0E, 0x68, 0xB2, 0xF8, 0xB0, 0x00, ++0xB2, 0xF8, 0xB2, 0x10, 0xB2, 0x8E, 0x2B, 0x44, 0x1B, 0x1B, 0x1B, 0x1A, 0x5B, 0x1A, 0x9B, 0x1A, 0x00, 0x2B, 0xC0, 0xF2, ++0x98, 0x80, 0xFF, 0xF7, 0x37, 0xFF, 0x56, 0x4B, 0x1B, 0x6A, 0x1C, 0x6C, 0x23, 0x79, 0x20, 0x89, 0x00, 0x2B, 0x56, 0xD0, ++0x2A, 0xF0, 0xC8, 0xFB, 0x02, 0x46, 0x0B, 0x46, 0x2A, 0xF0, 0x78, 0xFA, 0x50, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0x54, 0xFD, ++0x4F, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0x26, 0xFC, 0x2A, 0xF0, 0x1E, 0xFA, 0x2A, 0xF0, 0xBC, 0xFE, 0x05, 0x46, 0x20, 0x89, ++0x2A, 0xF0, 0xB4, 0xFB, 0x02, 0x46, 0x0B, 0x46, 0x00, 0x20, 0x49, 0x49, 0x2A, 0xF0, 0x42, 0xFD, 0x00, 0x22, 0x4F, 0xF0, ++0x83, 0x43, 0x2A, 0xF0, 0x13, 0xFC, 0x2A, 0xF0, 0x0B, 0xFA, 0x2A, 0xF0, 0xA9, 0xFE, 0x03, 0x46, 0x20, 0x89, 0x1C, 0x46, ++0x2A, 0xF0, 0xA0, 0xFB, 0x34, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x2A, 0xF0, 0x2F, 0xFD, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, ++0x2A, 0xF0, 0x00, 0xFC, 0x2A, 0xF0, 0xF8, 0xF9, 0x2A, 0xF0, 0x96, 0xFE, 0x3A, 0x4B, 0x3B, 0x49, 0x03, 0xF5, 0x99, 0x56, ++0x02, 0x46, 0x35, 0x60, 0x41, 0xF2, 0x24, 0x30, 0x41, 0xF2, 0x28, 0x35, 0x1C, 0x50, 0x5A, 0x51, 0x02, 0x20, 0x18, 0xF0, ++0xD5, 0xFB, 0x35, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x33, 0x49, 0x02, 0x20, 0x18, 0xF0, 0xCC, 0xFB, ++0x30, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x30, 0x49, 0xF5, 0xE7, 0x2A, 0xF0, 0x71, 0xFB, 0x2F, 0x4B, ++0x00, 0x22, 0x2A, 0xF0, 0xD7, 0xFB, 0x25, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0xFD, 0xFC, 0x24, 0x4B, 0x00, 0x22, 0x2A, 0xF0, ++0xCF, 0xFB, 0x2A, 0xF0, 0xC7, 0xF9, 0x2A, 0xF0, 0x65, 0xFE, 0x05, 0x46, 0x20, 0x89, 0x2A, 0xF0, 0x5D, 0xFB, 0x02, 0x46, ++0x0B, 0x46, 0x00, 0x20, 0x24, 0x49, 0x2A, 0xF0, 0xEB, 0xFC, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x2A, 0xF0, 0xBC, 0xFB, ++0x2A, 0xF0, 0xB4, 0xF9, 0x2A, 0xF0, 0x52, 0xFE, 0x03, 0x46, 0x20, 0x89, 0x1C, 0x46, 0x2A, 0xF0, 0x49, 0xFB, 0x0B, 0xA3, ++0xD3, 0xE9, 0x00, 0x23, 0xA7, 0xE7, 0x5A, 0x68, 0x1A, 0x49, 0x02, 0x20, 0x18, 0xF0, 0x92, 0xFB, 0x13, 0x4B, 0x4F, 0xF0, ++0x00, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x17, 0x49, 0xBB, 0xE7, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x10, 0xB3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xA2, 0x40, 0x3C, 0x36, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x00, 0x6A, 0x40, ++0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0xB9, 0x40, 0x00, 0x40, 0x1E, 0x00, 0x20, 0x89, 0x15, 0x00, 0x00, 0x41, 0x04, 0x40, ++0x1C, 0x89, 0x15, 0x00, 0xC4, 0x88, 0x15, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0xA4, 0x40, 0xE8, 0x88, 0x15, 0x00, ++0x00, 0x89, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, 0x56, 0x4E, 0xDF, 0xF8, 0x90, 0x81, 0x96, 0xF8, ++0xDF, 0x31, 0x96, 0xF8, 0xBF, 0x56, 0xDF, 0xF8, 0x88, 0xB1, 0x53, 0x4C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xF7, ++0x83, 0xB0, 0x08, 0xEB, 0x07, 0x09, 0x06, 0xF5, 0xBE, 0x71, 0x48, 0x46, 0x01, 0x93, 0x4F, 0xF4, 0x1E, 0x7A, 0x00, 0x97, ++0x2B, 0xF0, 0x0E, 0xF8, 0x07, 0xF1, 0xEC, 0x00, 0x0A, 0xFB, 0x05, 0xF5, 0x06, 0xF6, 0x14, 0x11, 0xE8, 0x22, 0x40, 0x44, ++0x2B, 0xF0, 0x04, 0xF8, 0x05, 0xEB, 0x0B, 0x03, 0x18, 0x46, 0x52, 0x46, 0x06, 0xF2, 0x9C, 0x61, 0x08, 0xEE, 0x10, 0x3A, ++0x2A, 0xF0, 0xFA, 0xFF, 0x06, 0xF6, 0xFC, 0x11, 0x1C, 0x22, 0xD9, 0xF8, 0x40, 0x00, 0x3F, 0x4F, 0xDF, 0xF8, 0x30, 0xA1, ++0x2A, 0xF0, 0xF0, 0xFF, 0x06, 0xF6, 0x18, 0x21, 0x34, 0x22, 0x3C, 0x48, 0x2A, 0xF0, 0xEA, 0xFF, 0x31, 0x46, 0x4F, 0xF4, ++0xBE, 0x72, 0x3A, 0x48, 0x2A, 0xF0, 0xE4, 0xFF, 0x06, 0xF6, 0x4C, 0x21, 0x18, 0x22, 0x38, 0x48, 0x2A, 0xF0, 0xDE, 0xFF, ++0x06, 0xF6, 0x64, 0x21, 0x4F, 0xF4, 0x18, 0x62, 0x35, 0x48, 0x2A, 0xF0, 0xD7, 0xFF, 0x06, 0xF6, 0x64, 0x51, 0x4F, 0xF4, ++0x98, 0x62, 0x33, 0x48, 0x33, 0x4E, 0x2A, 0xF0, 0xCF, 0xFF, 0x40, 0x22, 0xA4, 0xF1, 0xC8, 0x01, 0x31, 0x48, 0x2A, 0xF0, ++0xC9, 0xFF, 0x28, 0x22, 0xA4, 0xF1, 0x88, 0x01, 0x2F, 0x48, 0x2A, 0xF0, 0xC3, 0xFF, 0x2F, 0x48, 0x60, 0x22, 0xA4, 0xF1, ++0x60, 0x01, 0x2A, 0xF0, 0xBD, 0xFF, 0x05, 0xF5, 0xBE, 0x75, 0xAB, 0x44, 0x5B, 0xF8, 0x04, 0x3B, 0x50, 0x46, 0x19, 0x46, ++0x4B, 0xB1, 0xA2, 0x78, 0x1A, 0x73, 0xD7, 0xF8, 0xDC, 0x22, 0x25, 0x88, 0x1D, 0x81, 0xC3, 0xE9, 0x45, 0x23, 0x17, 0xF0, ++0x01, 0xF9, 0x04, 0x34, 0xB4, 0x42, 0xED, 0xD1, 0x1B, 0x48, 0x22, 0x4D, 0x49, 0x46, 0x17, 0xF0, 0xF9, 0xF8, 0x21, 0x48, ++0x49, 0x46, 0x17, 0xF0, 0xA5, 0xF8, 0x00, 0x9E, 0x06, 0xF1, 0xE4, 0x00, 0x18, 0xEE, 0x10, 0x1A, 0x40, 0x44, 0x17, 0xF0, ++0x9D, 0xF8, 0x01, 0x9A, 0xA4, 0x24, 0x99, 0x23, 0x14, 0xFB, 0x02, 0x34, 0x08, 0xEB, 0xC4, 0x04, 0x35, 0x44, 0x20, 0x46, ++0x17, 0xF0, 0x8E, 0xF8, 0x04, 0xF1, 0x28, 0x00, 0x08, 0x34, 0x17, 0xF0, 0x89, 0xF8, 0xAC, 0x42, 0xF5, 0xD1, 0x00, 0x9B, ++0x03, 0xF5, 0xA3, 0x60, 0x40, 0x44, 0x03, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x4F, 0x17, 0xF0, 0x7C, 0xB8, ++0x00, 0x40, 0x1E, 0x00, 0xEC, 0x52, 0x1E, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x34, 0xE0, 0x17, 0x00, 0x10, 0x53, 0x1E, 0x00, 0xF4, 0xDF, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x08, 0x8D, 0x17, 0x00, 0x08, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0xF8, 0xDE, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x6C, 0x4E, 0x6D, 0x4A, 0x33, 0x68, 0xDF, 0xF8, ++0x00, 0x82, 0x0D, 0x46, 0x09, 0x8C, 0x9B, 0xB2, 0x43, 0xEA, 0x01, 0x43, 0xD0, 0xF8, 0x90, 0x11, 0x33, 0x60, 0x8B, 0x78, ++0x67, 0x49, 0x02, 0xEB, 0x83, 0x03, 0x1C, 0x3E, 0x5B, 0x69, 0x0B, 0x60, 0x31, 0x68, 0x21, 0xF4, 0xE0, 0x61, 0x04, 0x46, ++0x50, 0x68, 0x31, 0x60, 0x13, 0x68, 0x62, 0x49, 0x62, 0x4A, 0x03, 0x43, 0x0B, 0x60, 0x62, 0x4B, 0x62, 0x49, 0x11, 0x60, ++0x62, 0x4A, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x9F, 0x03, 0x70, 0xD4, 0x60, 0x4B, 0x1B, 0x68, 0x1A, 0x68, 0xE2, 0xB1, ++0x5F, 0x49, 0x0A, 0x60, 0x5A, 0x68, 0xF2, 0xB1, 0xC2, 0xF3, 0x0B, 0x01, 0x00, 0x29, 0x61, 0xD1, 0xE1, 0x68, 0x5C, 0x48, ++0x22, 0xF4, 0x7F, 0x62, 0x22, 0xF0, 0x0F, 0x02, 0xC1, 0xF3, 0x0B, 0x01, 0x0A, 0x43, 0x02, 0x60, 0x9A, 0x68, 0xA2, 0xB9, ++0x57, 0x4A, 0x21, 0x69, 0x11, 0x60, 0xDB, 0x68, 0xA3, 0xB9, 0x56, 0x4B, 0x62, 0x69, 0x1A, 0x60, 0x12, 0xE0, 0x51, 0x4A, ++0xA1, 0x68, 0x11, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0xE0, 0xD1, 0x4F, 0x4A, 0xE1, 0x68, 0x11, 0x60, 0x9A, 0x68, 0x00, 0x2A, ++0xEA, 0xD0, 0x4D, 0x49, 0x0A, 0x60, 0xDB, 0x68, 0x00, 0x2B, 0xEA, 0xD0, 0x4B, 0x4A, 0x13, 0x60, 0x4B, 0x4B, 0xD3, 0xF8, ++0x60, 0x32, 0x98, 0x47, 0x4A, 0x4B, 0x1B, 0x68, 0x9C, 0x01, 0x06, 0xD4, 0x49, 0x4B, 0x3E, 0x4A, 0x01, 0x21, 0x19, 0x60, ++0x13, 0x68, 0x0B, 0x43, 0x13, 0x60, 0x28, 0x46, 0x1B, 0xF0, 0xE4, 0xFA, 0x43, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x04, 0x03, ++0x13, 0x60, 0x01, 0x21, 0x00, 0x20, 0x16, 0xF0, 0x51, 0xFD, 0x41, 0x4B, 0x1B, 0x68, 0x5A, 0x78, 0x22, 0xB1, 0x40, 0x49, ++0x0A, 0x68, 0x42, 0xF0, 0x40, 0x02, 0x0A, 0x60, 0x3E, 0x49, 0x9B, 0x78, 0x0A, 0x68, 0xD8, 0x06, 0x4C, 0xBF, 0x22, 0xF0, ++0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x3A, 0x4A, 0x13, 0xF0, 0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, ++0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x2B, 0x49, 0x0A, 0x60, 0xB8, 0xE7, 0xF4, 0xF7, ++0xD7, 0xFF, 0x00, 0x28, 0x8A, 0xD0, 0xF5, 0xF7, 0x07, 0xF8, 0x31, 0x4F, 0x3B, 0x68, 0x00, 0x02, 0x23, 0xF4, 0xE0, 0x63, ++0x00, 0xF4, 0xE0, 0x60, 0x18, 0x43, 0x38, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0x3B, 0x60, ++0x3B, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x3B, 0x60, 0x3B, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, ++0x1B, 0x04, 0x0F, 0xD4, 0x24, 0x4B, 0x1B, 0x68, 0x9E, 0x03, 0x7F, 0xF5, 0x69, 0xAF, 0xF4, 0xF7, 0xB9, 0xFF, 0x00, 0x28, ++0x3F, 0xF4, 0x64, 0xAF, 0x1E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x5D, 0xE7, 0xF4, 0xF7, 0x80, 0xFF, ++0x00, 0x28, 0xEB, 0xD0, 0x33, 0x68, 0x43, 0xF4, 0x00, 0x23, 0x33, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, ++0x80, 0x63, 0x3B, 0x60, 0xE0, 0xE7, 0x00, 0xBF, 0x68, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, ++0x60, 0x00, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0xC0, 0x07, 0xF9, 0x80, ++0xAC, 0x35, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, ++0x80, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x50, 0x03, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x33, 0x4D, 0xDF, 0xF8, 0xE4, 0x80, 0xD5, 0xF8, 0xD0, 0x34, 0x32, 0x4E, 0x41, 0xF2, 0x12, 0x32, 0x18, 0xF8, 0x02, 0x70, ++0x98, 0x47, 0xD5, 0xF8, 0x9C, 0x34, 0x98, 0x47, 0xD8, 0xF8, 0xBC, 0x41, 0xF4, 0xF7, 0x46, 0xF9, 0x2C, 0x49, 0xD5, 0xF8, ++0x88, 0x24, 0x0B, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x0B, 0x60, 0x20, 0x79, 0x90, 0x47, 0x23, 0x79, 0x86, 0xF8, 0x2A, 0x30, ++0x62, 0x79, 0x86, 0xF8, 0x2B, 0x20, 0x62, 0x7B, 0x86, 0xF8, 0x2C, 0x20, 0xE1, 0x88, 0x20, 0x89, 0x62, 0x89, 0x32, 0x85, ++0xFF, 0xB2, 0xB1, 0x84, 0xF0, 0x84, 0xD3, 0xB9, 0xD5, 0xF8, 0xA0, 0x34, 0x98, 0x47, 0xF0, 0x8C, 0xD5, 0xF8, 0xA4, 0x34, ++0x98, 0x47, 0x1D, 0x4E, 0x94, 0xF9, 0x0C, 0x00, 0xD5, 0xF8, 0x3C, 0x33, 0x98, 0x47, 0xD5, 0xF8, 0xD4, 0x34, 0x06, 0xF5, ++0xA4, 0x61, 0x30, 0x46, 0x98, 0x47, 0x17, 0xF0, 0x0D, 0x0F, 0x0C, 0xD0, 0xD5, 0xF8, 0x54, 0x32, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0xD5, 0xF8, 0xA8, 0x34, 0x98, 0x47, 0xF0, 0x8C, 0xD5, 0xF8, 0xAC, 0x34, 0x98, 0x47, 0xE3, 0xE7, 0xBB, 0x07, ++0x14, 0xD5, 0x0F, 0x4A, 0xD8, 0xF8, 0x80, 0x31, 0x11, 0x69, 0x0E, 0x48, 0xD5, 0xF8, 0xE0, 0x21, 0x46, 0x61, 0x05, 0x24, ++0x44, 0x77, 0x01, 0xF5, 0x1C, 0x51, 0x43, 0xF0, 0x02, 0x03, 0xC8, 0xF8, 0x80, 0x31, 0x10, 0x31, 0xBD, 0xE8, 0xF0, 0x41, ++0x0C, 0x30, 0x10, 0x47, 0xBD, 0xE8, 0xF0, 0x81, 0x88, 0x1A, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, ++0x7C, 0x41, 0x1E, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x40, 0x1E, 0x00, 0x38, 0xB5, 0x50, 0xBB, ++0x1A, 0x4B, 0x1A, 0x68, 0x52, 0xB1, 0x1A, 0x4B, 0x1A, 0x49, 0x18, 0x69, 0xD3, 0x68, 0xB1, 0xF8, 0xB0, 0x10, 0x1B, 0x1A, ++0x5B, 0x1A, 0xB3, 0xF5, 0xFA, 0x6F, 0x17, 0xD4, 0x16, 0x4A, 0x13, 0x78, 0x7B, 0xB1, 0xD2, 0xE9, 0x01, 0x34, 0x12, 0x48, ++0x14, 0x4D, 0x12, 0x49, 0x00, 0x69, 0x2A, 0x68, 0xB1, 0xF8, 0xB0, 0x10, 0x92, 0x8E, 0x23, 0x44, 0x1B, 0x1A, 0x5B, 0x1A, ++0x9B, 0x1A, 0x00, 0x2B, 0x0E, 0xDB, 0x0F, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x38, 0xBD, 0x52, 0x68, 0x0D, 0x49, ++0x02, 0x20, 0x18, 0xF0, 0xDB, 0xF8, 0x0A, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x38, 0xBD, 0x09, 0x49, 0x02, 0x20, ++0x18, 0xF0, 0xD2, 0xF8, 0xF5, 0xE7, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0x3C, 0x36, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x41, 0x04, 0x40, 0xE8, 0x88, 0x15, 0x00, 0x28, 0x89, 0x15, 0x00, ++0xF0, 0xB5, 0x1B, 0x4B, 0x01, 0x22, 0x85, 0xB0, 0xDA, 0x60, 0xEF, 0xF3, 0x14, 0x81, 0xEF, 0xF3, 0x03, 0x82, 0xEF, 0xF3, ++0x09, 0x85, 0xEF, 0xF3, 0x08, 0x84, 0xEF, 0xF3, 0x10, 0x83, 0x70, 0x46, 0xCD, 0xE9, 0x01, 0x30, 0x00, 0x94, 0x13, 0x48, ++0x2B, 0x46, 0x18, 0xF0, 0x59, 0xF8, 0x15, 0xB9, 0x34, 0xB9, 0x05, 0xB0, 0xF0, 0xBD, 0x10, 0x48, 0x18, 0xF0, 0x52, 0xF8, ++0x00, 0x2C, 0xF8, 0xD0, 0x0E, 0x48, 0x0F, 0x4F, 0x0F, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0x18, 0xF0, 0x49, 0xF8, 0x04, 0xF5, ++0x80, 0x75, 0x06, 0xE0, 0x54, 0xF8, 0x04, 0x1B, 0x30, 0x46, 0x18, 0xF0, 0x41, 0xF8, 0xA5, 0x42, 0xE7, 0xD0, 0x23, 0x07, ++0xF6, 0xD1, 0x21, 0x46, 0x38, 0x46, 0x18, 0xF0, 0x39, 0xF8, 0xF1, 0xE7, 0x00, 0xA0, 0x10, 0x40, 0x40, 0x89, 0x15, 0x00, ++0x94, 0x89, 0x15, 0x00, 0xA0, 0x89, 0x15, 0x00, 0xAC, 0x89, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0x30, 0xB4, 0x0C, 0x4C, ++0x0C, 0x49, 0xD4, 0xF8, 0x3C, 0x31, 0x0C, 0x4A, 0x0C, 0x4D, 0x43, 0xF0, 0x04, 0x03, 0xC4, 0xF8, 0x3C, 0x31, 0xC0, 0x03, ++0x03, 0x24, 0xF4, 0x23, 0x08, 0x60, 0x8C, 0x60, 0x82, 0xF8, 0x44, 0x33, 0xAB, 0x68, 0x07, 0x49, 0xC3, 0xF8, 0x50, 0x11, ++0x10, 0x23, 0x30, 0xBC, 0x93, 0x60, 0x70, 0x47, 0x00, 0x00, 0x50, 0x40, 0x00, 0xA0, 0x10, 0x40, 0x00, 0xE1, 0x00, 0xE0, ++0x00, 0xED, 0x00, 0xE0, 0xA9, 0xC5, 0x12, 0x00, 0x01, 0x4B, 0x1A, 0x68, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, ++0x02, 0x4A, 0x93, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x93, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, 0x02, 0x4A, 0x93, 0x68, ++0x43, 0xF0, 0x02, 0x03, 0x93, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, 0x08, 0xB5, 0x06, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0xFE, 0xE7, 0x03, 0x49, 0x04, 0x48, 0xBA, 0x22, 0x18, 0xF0, 0x5F, 0xFA, 0xF8, 0xE7, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x0B, 0x4B, 0x41, 0xF2, 0x1C, 0x32, 0x41, 0xF2, ++0x18, 0x31, 0x9A, 0x58, 0x5B, 0x58, 0x72, 0xB1, 0x10, 0xB4, 0x08, 0x4C, 0x00, 0x22, 0x19, 0x68, 0x58, 0x68, 0x08, 0x60, ++0x21, 0x68, 0x02, 0x32, 0x91, 0x42, 0x03, 0xF1, 0x08, 0x03, 0xF6, 0xD8, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x70, 0x47, ++0x00, 0x40, 0x1E, 0x00, 0x1C, 0x53, 0x1E, 0x00, 0x32, 0x49, 0x33, 0x4B, 0x99, 0x42, 0x10, 0xB5, 0x0C, 0xD2, 0x01, 0x3B, ++0x5B, 0x1A, 0x31, 0x4A, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x52, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0B, ++0x9A, 0x42, 0xF9, 0xD1, 0x2C, 0x4A, 0x2D, 0x4B, 0x9A, 0x42, 0x0A, 0xD2, 0x01, 0x3B, 0x9B, 0x1A, 0x23, 0xF0, 0x03, 0x03, ++0x04, 0x33, 0x13, 0x44, 0x00, 0x21, 0x42, 0xF8, 0x04, 0x1B, 0x9A, 0x42, 0xFB, 0xD1, 0x27, 0x49, 0x27, 0x4B, 0x99, 0x42, ++0x0D, 0xD2, 0x01, 0x3B, 0x5B, 0x1A, 0x26, 0x4A, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x08, 0x46, 0x52, 0xF8, ++0x04, 0x4B, 0x40, 0xF8, 0x04, 0x4B, 0x9A, 0x42, 0xF9, 0xD1, 0x21, 0x4A, 0x21, 0x48, 0xD2, 0xF8, 0x88, 0x30, 0x43, 0xF4, ++0x70, 0x03, 0xC2, 0xF8, 0x88, 0x30, 0x91, 0x60, 0x00, 0x23, 0xFF, 0x21, 0xC2, 0x18, 0x01, 0x33, 0x50, 0x2B, 0x82, 0xF8, ++0x00, 0x13, 0xF9, 0xD1, 0x1A, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x80, 0x6F, 0x16, 0x4B, 0x1B, 0x68, 0x4F, 0xF6, 0xF0, 0x72, ++0x03, 0xEA, 0x02, 0x03, 0x0D, 0xD0, 0x4C, 0xF2, 0x40, 0x22, 0x93, 0x42, 0x0D, 0xD0, 0x14, 0x4C, 0xF5, 0xF7, 0xBC, 0xFC, ++0xD4, 0xF8, 0x7C, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0x74, 0x34, 0x98, 0x47, 0xFE, 0xE7, 0x4D, 0xF2, 0x10, 0x22, 0x93, 0x42, ++0xF1, 0xD1, 0x0E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xED, 0xE7, 0x00, 0xBF, 0x80, 0x01, 0x17, 0x00, 0x5C, 0x25, 0x17, 0x00, ++0x2C, 0xD2, 0x15, 0x00, 0x60, 0x25, 0x17, 0x00, 0x28, 0x07, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x80, 0x01, 0x17, 0x00, ++0x00, 0x00, 0x12, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x68, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x72, 0x4F, 0x73, 0x4E, 0x86, 0xB0, 0x3D, 0x46, 0x00, 0x24, 0x21, 0x46, ++0x55, 0xF8, 0x04, 0x2B, 0x30, 0x46, 0x01, 0x34, 0xF9, 0xF7, 0x6A, 0xFD, 0x0D, 0x2C, 0xF6, 0xD1, 0xD7, 0xE9, 0x11, 0x21, ++0x3B, 0x6C, 0x6C, 0x4D, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x21, 0x6B, 0x48, 0x79, 0x6B, 0xD7, 0xE9, 0x0E, 0x23, 0xF9, 0xF7, ++0x5B, 0xFD, 0x29, 0x68, 0x6A, 0x68, 0xAB, 0x68, 0xE8, 0x68, 0x00, 0x90, 0x66, 0x48, 0xF9, 0xF7, 0x53, 0xFD, 0x69, 0x6A, ++0xAA, 0x6A, 0xEB, 0x6A, 0x28, 0x6B, 0xEC, 0x6B, 0xCD, 0xE9, 0x00, 0x04, 0x62, 0x48, 0xF9, 0xF7, 0x49, 0xFD, 0xAC, 0x6A, ++0x14, 0xF0, 0xFF, 0x01, 0x68, 0xD1, 0xC4, 0xF3, 0x07, 0x25, 0x14, 0xF4, 0x7F, 0x4F, 0x29, 0x46, 0x44, 0xD1, 0x21, 0x0C, ++0x2E, 0xD1, 0xFB, 0x6C, 0x1C, 0x07, 0x23, 0xD5, 0x5A, 0x48, 0xF9, 0xF7, 0x37, 0xFD, 0x3B, 0x6D, 0xD8, 0x07, 0x21, 0xD4, ++0x58, 0x48, 0xF9, 0xF7, 0x31, 0xFD, 0xFB, 0x6C, 0x59, 0x07, 0x4C, 0xBF, 0x56, 0x48, 0x57, 0x48, 0xF9, 0xF7, 0x2A, 0xFD, ++0x39, 0x6D, 0xEF, 0xF3, 0x10, 0x82, 0xEF, 0xF3, 0x13, 0x83, 0xEF, 0xF3, 0x11, 0x80, 0x00, 0x90, 0x52, 0x48, 0xF9, 0xF7, ++0x1F, 0xFD, 0xBC, 0x6C, 0x00, 0x2C, 0x71, 0xD1, 0x7C, 0x6C, 0x00, 0x2C, 0x56, 0xD1, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, ++0x4D, 0x48, 0xF9, 0xF7, 0x13, 0xFD, 0xDD, 0xE7, 0x4C, 0x48, 0xF9, 0xF7, 0x0F, 0xFD, 0xDC, 0xE7, 0xC4, 0xF3, 0x40, 0x63, ++0xC4, 0xF3, 0x00, 0x60, 0xC4, 0xF3, 0xC0, 0x42, 0x03, 0x93, 0xC4, 0xF3, 0x80, 0x43, 0xCD, 0xE9, 0x01, 0x20, 0x00, 0x93, ++0xC4, 0xF3, 0x00, 0x42, 0xC4, 0xF3, 0x40, 0x43, 0x43, 0x48, 0xF9, 0xF7, 0xFB, 0xFC, 0xBC, 0xE7, 0xC4, 0xF3, 0xC0, 0x33, ++0xC4, 0xF3, 0x00, 0x30, 0xC4, 0xF3, 0xC0, 0x22, 0x04, 0x93, 0xC4, 0xF3, 0x40, 0x36, 0xC4, 0xF3, 0x80, 0x23, 0xCD, 0xE9, ++0x00, 0x32, 0xCD, 0xE9, 0x02, 0x06, 0xC4, 0xF3, 0x40, 0x23, 0x3A, 0x48, 0xC4, 0xF3, 0x00, 0x22, 0xF9, 0xF7, 0xE4, 0xFC, ++0x2D, 0x06, 0xA2, 0xD5, 0x2A, 0x4B, 0x37, 0x48, 0x99, 0x6B, 0xF9, 0xF7, 0xDD, 0xFC, 0x9C, 0xE7, 0xC4, 0xF3, 0xC0, 0x16, ++0xC4, 0xF3, 0x40, 0x10, 0xC4, 0xF3, 0x00, 0x12, 0xC4, 0xF3, 0xC0, 0x03, 0xCD, 0xE9, 0x02, 0x06, 0xCD, 0xE9, 0x00, 0x32, ++0x2F, 0x48, 0xC4, 0xF3, 0x40, 0x03, 0x04, 0xF0, 0x01, 0x02, 0xF9, 0xF7, 0xC9, 0xFC, 0x26, 0x06, 0x81, 0xD5, 0x69, 0x6B, ++0x2B, 0x48, 0xF9, 0xF7, 0xC3, 0xFC, 0x7C, 0xE7, 0x2A, 0x48, 0x2B, 0x4F, 0x2B, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0xF9, 0xF7, ++0xBB, 0xFC, 0x04, 0xF5, 0x80, 0x75, 0x06, 0xE0, 0x54, 0xF8, 0x04, 0x1B, 0x30, 0x46, 0xF9, 0xF7, 0xB3, 0xFC, 0xA5, 0x42, ++0x97, 0xD0, 0x23, 0x07, 0xF6, 0xD1, 0x21, 0x46, 0x38, 0x46, 0xF9, 0xF7, 0xAB, 0xFC, 0xF1, 0xE7, 0x21, 0x48, 0xDF, 0xF8, ++0x7C, 0x80, 0x1F, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0xF9, 0xF7, 0xA2, 0xFC, 0x04, 0xF5, 0x80, 0x75, 0x07, 0xE0, 0x54, 0xF8, ++0x04, 0x1B, 0x30, 0x46, 0xF9, 0xF7, 0x9A, 0xFC, 0xA5, 0x42, 0x3F, 0xF4, 0x7B, 0xAF, 0x22, 0x07, 0xF5, 0xD1, 0x21, 0x46, ++0x40, 0x46, 0xF9, 0xF7, 0x91, 0xFC, 0xF0, 0xE7, 0xE4, 0x60, 0x17, 0x00, 0xC0, 0x89, 0x15, 0x00, 0x00, 0xED, 0x00, 0xE0, ++0xD0, 0x89, 0x15, 0x00, 0x1C, 0x8A, 0x15, 0x00, 0x50, 0x8A, 0x15, 0x00, 0xF0, 0x8B, 0x15, 0x00, 0x10, 0x8C, 0x15, 0x00, ++0x34, 0x8C, 0x15, 0x00, 0x40, 0x8C, 0x15, 0x00, 0x4C, 0x8C, 0x15, 0x00, 0x24, 0x8C, 0x15, 0x00, 0x00, 0x8C, 0x15, 0x00, ++0x8C, 0x8B, 0x15, 0x00, 0x04, 0x8B, 0x15, 0x00, 0x7C, 0x8B, 0x15, 0x00, 0x90, 0x8A, 0x15, 0x00, 0xF4, 0x8A, 0x15, 0x00, ++0x80, 0x8C, 0x15, 0x00, 0xAC, 0x89, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0xA0, 0x89, 0x15, 0x00, 0x08, 0xB5, 0x02, 0x48, ++0xF9, 0xF7, 0x60, 0xFC, 0xFE, 0xE7, 0x00, 0xBF, 0x8C, 0x8C, 0x15, 0x00, 0x04, 0x46, 0x08, 0xB5, 0x10, 0x48, 0xF9, 0xF7, ++0x57, 0xFC, 0x30, 0x2C, 0x10, 0xD0, 0x40, 0x2C, 0x16, 0xD0, 0x20, 0x2C, 0x10, 0xD0, 0x0D, 0x48, 0xF9, 0xF7, 0x4E, 0xFC, ++0x0C, 0x48, 0xF9, 0xF7, 0x4B, 0xFC, 0xFF, 0xF7, 0xD1, 0xFE, 0x0B, 0x48, 0xF9, 0xF7, 0x46, 0xFC, 0xFF, 0xF7, 0xE0, 0xFF, ++0x09, 0x48, 0xF9, 0xF7, 0x41, 0xFC, 0xF1, 0xE7, 0x08, 0x48, 0xF9, 0xF7, 0x3D, 0xFC, 0xED, 0xE7, 0x07, 0x48, 0xF9, 0xF7, ++0x39, 0xFC, 0xE9, 0xE7, 0x98, 0x8C, 0x15, 0x00, 0xE8, 0x8C, 0x15, 0x00, 0xF4, 0x8C, 0x15, 0x00, 0x00, 0x8D, 0x15, 0x00, ++0xD0, 0x8C, 0x15, 0x00, 0xC0, 0x8C, 0x15, 0x00, 0xDC, 0x8C, 0x15, 0x00, 0x4F, 0xF0, 0x10, 0x03, 0x00, 0xF0, 0x0C, 0xB8, ++0x4F, 0xF0, 0x20, 0x03, 0x00, 0xF0, 0x08, 0xB8, 0x4F, 0xF0, 0x30, 0x03, 0x00, 0xF0, 0x04, 0xB8, 0x4F, 0xF0, 0x40, 0x03, ++0x00, 0xF0, 0x00, 0xB8, 0xEF, 0xF3, 0x08, 0x80, 0x4F, 0xF0, 0x04, 0x01, 0x72, 0x46, 0x0A, 0x42, 0x01, 0xD0, 0xEF, 0xF3, ++0x09, 0x80, 0x9C, 0x46, 0x24, 0x49, 0x02, 0x68, 0x0A, 0x60, 0x04, 0x31, 0x42, 0x68, 0x0A, 0x60, 0x04, 0x31, 0x82, 0x68, ++0x0A, 0x60, 0x04, 0x31, 0xC2, 0x68, 0x0A, 0x60, 0x04, 0x31, 0xF0, 0xC1, 0x47, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x4F, 0x46, ++0x0F, 0x60, 0x04, 0x31, 0x57, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x5F, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x02, 0x69, 0x0A, 0x60, ++0x08, 0x31, 0x42, 0x69, 0x0A, 0x60, 0x04, 0x31, 0x82, 0x69, 0x0A, 0x60, 0x04, 0x31, 0xC2, 0x69, 0x0A, 0x60, 0x04, 0x31, ++0x03, 0x46, 0x20, 0x33, 0x4F, 0xF4, 0x00, 0x76, 0x32, 0x42, 0x00, 0xD0, 0x04, 0x33, 0x75, 0x46, 0x4F, 0xF0, 0x10, 0x06, ++0x35, 0x42, 0x00, 0xD1, 0x48, 0x33, 0x0C, 0x46, 0x10, 0x3C, 0x23, 0x60, 0xEF, 0xF3, 0x09, 0x82, 0x0A, 0x60, 0x04, 0x31, ++0xEF, 0xF3, 0x08, 0x82, 0x0A, 0x60, 0x04, 0x31, 0x72, 0x46, 0x0A, 0x60, 0x04, 0x31, 0xEF, 0xF3, 0x14, 0x82, 0x0A, 0x60, ++0x03, 0x4B, 0x60, 0x46, 0x01, 0x49, 0x98, 0x47, 0xFE, 0xE7, 0x00, 0x00, 0xE4, 0x60, 0x17, 0x00, 0x3D, 0xCA, 0x12, 0x00, ++0x08, 0xB5, 0x08, 0x4B, 0x00, 0x22, 0x5A, 0x70, 0x18, 0xF0, 0x3E, 0xF8, 0x1A, 0xF0, 0x14, 0xFC, 0x05, 0x4B, 0xD3, 0xF8, ++0xA8, 0x31, 0x98, 0x47, 0x16, 0xF0, 0x88, 0xFB, 0xBD, 0xE8, 0x08, 0x40, 0x18, 0xF0, 0x42, 0xB8, 0x70, 0x28, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x4B, 0x4E, 0x4C, 0x4A, 0x4C, 0x49, 0x4D, 0x48, 0x17, 0xF0, 0x6E, 0xFD, ++0x33, 0x68, 0xDB, 0x78, 0x00, 0x2B, 0x40, 0xF0, 0x89, 0x80, 0x62, 0xB6, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, ++0xDF, 0xF8, 0x3C, 0x81, 0xDF, 0xF8, 0x3C, 0x91, 0x45, 0x4D, 0x46, 0x4F, 0x46, 0x4C, 0xDF, 0xF8, 0x38, 0xB1, 0x4F, 0xF0, ++0x01, 0x0A, 0x33, 0x68, 0xDB, 0x78, 0xFB, 0xB9, 0x98, 0xF8, 0x00, 0x30, 0x13, 0xB3, 0x18, 0xF0, 0x71, 0xFE, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0xA0, 0x2B, 0x68, 0x3A, 0x68, 0x01, 0x33, 0x2B, 0x60, ++0xBA, 0xB1, 0x00, 0x2B, 0xE9, 0xD0, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x2B, 0x60, 0x00, 0x2B, 0xE3, 0xD1, 0x00, 0x2A, ++0xE1, 0xD0, 0x62, 0xB6, 0x33, 0x68, 0xDB, 0x78, 0x00, 0x2B, 0xDF, 0xD0, 0xFF, 0xF7, 0x2C, 0xFD, 0x98, 0xF8, 0x00, 0x30, ++0x00, 0x2B, 0xDC, 0xD1, 0x16, 0xF0, 0xF8, 0xFA, 0xD9, 0xE7, 0xD4, 0xF8, 0x7C, 0x32, 0x98, 0x47, 0x33, 0x68, 0xDB, 0x78, ++0x00, 0x2B, 0x37, 0xD1, 0xDB, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x01, 0x2B, 0x17, 0xD0, 0xBF, 0xF3, 0x4F, 0x8F, 0x30, 0xBF, ++0xBF, 0xF3, 0x6F, 0x8F, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0xD4, 0xF8, 0x78, 0x32, 0x98, 0x47, 0x00, 0x28, ++0xF1, 0xD0, 0x33, 0x68, 0xDB, 0x78, 0x23, 0xBB, 0xD4, 0xF8, 0x84, 0x32, 0x98, 0x47, 0x2B, 0x68, 0x00, 0x2B, 0xB0, 0xD0, ++0xC5, 0xE7, 0x1D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xE3, 0xD0, 0x1C, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x17, 0xD0, ++0x01, 0x2B, 0x05, 0xD0, 0x00, 0x2B, 0xDA, 0xD1, 0x18, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xD6, 0xD0, 0x17, 0x4B, 0x5B, 0x78, ++0x00, 0x2B, 0xD2, 0xD0, 0x16, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x53, 0x13, 0x60, 0xCC, 0xE7, 0xFF, 0xF7, 0xEA, 0xFC, ++0xC4, 0xE7, 0xFF, 0xF7, 0xEF, 0xFC, 0xD7, 0xE7, 0xFB, 0xF7, 0x32, 0xFE, 0x00, 0x28, 0xEF, 0xD1, 0x0B, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0xDF, 0xE7, 0x10, 0x20, 0xFF, 0xF7, 0xB1, 0xFC, 0x72, 0xE7, 0x34, 0x36, 0x17, 0x00, 0xDC, 0xD1, 0x15, 0x00, ++0x00, 0xD2, 0x15, 0x00, 0x1C, 0x8D, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x3D, 0x61, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x3C, 0x61, 0x17, 0x00, 0x70, 0x28, 0x17, 0x00, 0x00, 0x60, 0x50, 0x40, ++0x3C, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x72, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x71, 0x4C, 0x72, 0x4A, 0x23, 0x68, 0x72, 0x49, ++0x72, 0x4D, 0x01, 0x33, 0x4F, 0xF4, 0x80, 0x60, 0x23, 0x60, 0x17, 0xF0, 0xF9, 0xFC, 0x4F, 0xF0, 0x00, 0x40, 0x16, 0xF0, ++0x4D, 0xFA, 0xD5, 0xF8, 0xEC, 0x30, 0x98, 0x47, 0x6C, 0x4B, 0x6D, 0x4A, 0x19, 0x68, 0x21, 0xF0, 0x7F, 0x41, 0x19, 0x60, ++0x19, 0x68, 0x41, 0xF0, 0x10, 0x01, 0x19, 0x60, 0x11, 0x69, 0x64, 0x31, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, ++0x66, 0x4E, 0xD5, 0xF8, 0x10, 0x24, 0x33, 0x68, 0x40, 0xF2, 0x11, 0x17, 0x3B, 0x43, 0x33, 0x60, 0x90, 0x47, 0x60, 0x49, ++0x62, 0x4A, 0x0B, 0x68, 0xDF, 0xF8, 0xAC, 0xC1, 0x23, 0xF0, 0x10, 0x03, 0x0B, 0x60, 0x33, 0x68, 0x23, 0xF4, 0x88, 0x73, ++0x23, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x0B, 0x23, 0x10, 0x68, 0x13, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0xDB, 0x06, 0x18, 0xD5, ++0x59, 0x4B, 0x40, 0xF2, 0x01, 0x2C, 0x19, 0x68, 0xC3, 0xF8, 0x00, 0xC0, 0x19, 0x60, 0x33, 0x68, 0xA2, 0xF5, 0x7C, 0x72, ++0x1F, 0x43, 0x37, 0x60, 0x11, 0x68, 0x02, 0x31, 0x13, 0x68, 0x5B, 0x1A, 0x00, 0x2B, 0xFB, 0xDB, 0x4E, 0x4A, 0x13, 0x68, ++0x23, 0xF4, 0x88, 0x73, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x4C, 0x4B, 0x18, 0x60, 0x0A, 0xF0, 0xBD, 0xFF, 0x00, 0x20, ++0x16, 0xF0, 0x8E, 0xF8, 0x00, 0x28, 0x6C, 0xD0, 0x49, 0x4E, 0x09, 0xF0, 0xA1, 0xFB, 0xB3, 0x79, 0x00, 0x2B, 0x4F, 0xD0, ++0x47, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x66, 0xD0, 0x33, 0x78, 0x00, 0x2B, 0x47, 0xD0, 0x44, 0x4B, 0x77, 0x79, ++0x1A, 0x68, 0x96, 0xF9, 0x07, 0x30, 0x96, 0xF9, 0x04, 0xE0, 0xDF, 0xF8, 0x20, 0xC1, 0x41, 0x48, 0xDC, 0xF8, 0x00, 0x10, ++0xD5, 0xF8, 0xE0, 0x81, 0x37, 0x4D, 0x02, 0xF0, 0x0F, 0x02, 0x17, 0x44, 0x7F, 0xB2, 0x3B, 0x44, 0x73, 0x45, 0xA8, 0xBF, ++0x73, 0x46, 0x5F, 0xFA, 0x83, 0xFE, 0x21, 0xF0, 0xFF, 0x01, 0x41, 0xEA, 0x0E, 0x01, 0xCC, 0xF8, 0x00, 0x10, 0x02, 0x68, ++0x22, 0xF0, 0xFF, 0x02, 0x42, 0xEA, 0x0E, 0x02, 0x02, 0x60, 0xDC, 0xF8, 0x00, 0x10, 0xDA, 0x1E, 0x5F, 0xFA, 0x82, 0xFE, ++0x21, 0xF4, 0x7F, 0x21, 0x41, 0xEA, 0x0E, 0x31, 0xCC, 0xF8, 0x00, 0x10, 0x02, 0x68, 0xB6, 0xF8, 0x08, 0xC0, 0x22, 0xF4, ++0x7F, 0x22, 0x42, 0xEA, 0x0E, 0x32, 0x02, 0x60, 0x2A, 0x69, 0x2A, 0x48, 0x5D, 0xB2, 0x4E, 0xF6, 0x60, 0x21, 0x01, 0xFB, ++0x0C, 0x21, 0xF5, 0x71, 0xC0, 0x47, 0x00, 0x23, 0x26, 0x48, 0xB3, 0x71, 0x29, 0x46, 0x3A, 0x46, 0x17, 0xF0, 0xFC, 0xFB, ++0x24, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x17, 0xF0, 0x47, 0xFC, 0x08, 0xF0, 0x85, 0xFE, 0x18, 0xB1, 0x4F, 0xF4, 0x80, 0x10, ++0x16, 0xF0, 0x74, 0xF9, 0x23, 0x68, 0x33, 0xB1, 0x0D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF0, 0x80, 0x60, 0x16, 0xF0, 0x89, 0xF9, 0x8D, 0xE7, 0x17, 0x4B, 0x1B, 0x68, ++0x00, 0x22, 0x1A, 0x60, 0xF8, 0xF7, 0x8C, 0xFA, 0x33, 0x78, 0x00, 0x2B, 0xDA, 0xD0, 0xB3, 0x79, 0x00, 0x2B, 0x8F, 0xD1, ++0xD6, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x30, 0x8E, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x04, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x18, 0x00, 0x34, 0x40, 0x10, 0x05, 0x32, 0x40, ++0x00, 0x10, 0x34, 0x40, 0x80, 0x35, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x01, 0x32, 0x40, 0xD4, 0xB3, 0x33, 0x40, ++0x8C, 0x35, 0x17, 0x00, 0x30, 0x8D, 0x15, 0x00, 0x40, 0x8D, 0x15, 0x00, 0x00, 0x38, 0x18, 0x00, 0x0C, 0x05, 0x32, 0x40, ++0xAC, 0xB3, 0x33, 0x40, 0x22, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x20, 0x4B, ++0xD3, 0xF8, 0x04, 0x31, 0x1A, 0x03, 0x10, 0xB5, 0x16, 0xD4, 0x00, 0x22, 0x93, 0x00, 0x03, 0xF1, 0x60, 0x43, 0x03, 0xF5, ++0x61, 0x43, 0x01, 0x2A, 0xD3, 0xF8, 0x00, 0x01, 0x1B, 0x68, 0x00, 0xEA, 0x03, 0x00, 0x04, 0xD0, 0x30, 0xB9, 0x02, 0x2A, ++0x05, 0xD0, 0x01, 0x32, 0xEE, 0xE7, 0x30, 0xF4, 0x00, 0x23, 0xFA, 0xD0, 0x01, 0x20, 0x10, 0xBD, 0x12, 0x4B, 0x1C, 0x68, ++0x41, 0xF6, 0x33, 0x70, 0x20, 0x40, 0xF7, 0xD1, 0x63, 0x00, 0x0F, 0xD4, 0x00, 0x2C, 0x07, 0xDA, 0x0E, 0x4B, 0xD3, 0xF8, ++0x68, 0x34, 0x98, 0x47, 0x0D, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x08, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0xC3, 0xF8, ++0x84, 0x21, 0xD0, 0xE7, 0x07, 0x4B, 0xD3, 0xF8, 0x78, 0x34, 0x98, 0x47, 0x06, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, ++0xE6, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, 0x1C, 0x41, 0x04, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x38, 0xB5, 0x3F, 0x4C, 0x3F, 0x4D, 0x23, 0x68, 0x3F, 0x49, 0x03, 0xF0, 0x0F, 0x03, 0x02, 0x20, ++0x2B, 0x70, 0x17, 0xF0, 0x9F, 0xFB, 0x23, 0x68, 0x18, 0x07, 0x40, 0xD0, 0x3B, 0x49, 0x3C, 0x4A, 0x0B, 0x68, 0x00, 0x20, ++0x23, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x20, 0x60, 0x13, 0x68, 0x59, 0x07, 0xFC, 0xD5, 0x38, 0x4B, 0x35, 0x49, 0x38, 0x4A, ++0x04, 0x20, 0x18, 0x60, 0x0B, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x63, 0x13, 0x60, ++0x33, 0x4B, 0x1B, 0x78, 0x01, 0x22, 0x6A, 0x70, 0x9B, 0xB1, 0x32, 0x49, 0x32, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0x00, 0x13, ++0x0B, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x2F, 0x4B, 0x19, 0x68, 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, ++0x01, 0x20, 0x41, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x10, 0x60, 0x20, 0x4B, 0x2A, 0x4A, 0x2B, 0x49, 0x20, 0x20, 0x18, 0x60, ++0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x26, 0xD0, 0x01, 0x2B, 0x06, 0xD0, ++0x38, 0xBD, 0x1E, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x63, 0x13, 0x60, 0xD0, 0xE7, 0x22, 0x4A, 0x13, 0x68, 0x5B, 0x03, ++0xFC, 0xD5, 0x21, 0x4A, 0x11, 0x69, 0x1C, 0x31, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x1E, 0x49, 0x1F, 0x4A, ++0x0B, 0x68, 0x43, 0xF4, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x6D, 0x43, 0xF4, 0x00, 0x43, 0x13, 0x65, 0xD3, 0x6D, 0x23, 0xF0, ++0x03, 0x03, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xF0, 0x01, 0x03, 0xD3, 0x65, 0x38, 0xBD, 0x17, 0x4B, 0x1A, 0x68, 0x42, 0xF0, ++0x01, 0x02, 0x1A, 0x60, 0x1B, 0x68, 0x5A, 0x07, 0xD2, 0xD5, 0x14, 0x4B, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x38, 0xBD, ++0x38, 0x00, 0x32, 0x40, 0x70, 0x28, 0x17, 0x00, 0x50, 0x8D, 0x15, 0x00, 0x74, 0x80, 0x32, 0x40, 0x6C, 0x80, 0x32, 0x40, ++0x70, 0x80, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, 0x3D, 0x61, 0x17, 0x00, 0x58, 0x40, 0x34, 0x40, 0x40, 0x42, 0x04, 0x40, ++0x18, 0x00, 0x58, 0x40, 0x10, 0x00, 0x58, 0x40, 0x78, 0x36, 0x17, 0x00, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x14, 0x00, 0x24, 0x40, 0x00, 0x60, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x00, 0x41, 0x04, 0x40, 0x00, 0x28, 0x00, 0xF0, ++0xE7, 0x80, 0x2D, 0xE9, 0xF8, 0x4F, 0x90, 0xF8, 0x64, 0x30, 0x04, 0x46, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x8F, 0x83, 0x4B, ++0x83, 0x4A, 0x84, 0x4F, 0xDF, 0xF8, 0x2C, 0x92, 0xDF, 0xF8, 0x64, 0x82, 0x82, 0x4E, 0x83, 0x48, 0x0D, 0x46, 0x83, 0x49, ++0x4F, 0xF0, 0x02, 0x0B, 0xD1, 0xF8, 0x70, 0xC4, 0xC3, 0xF8, 0x80, 0xB1, 0x92, 0x68, 0x80, 0x49, 0xC2, 0xF8, 0x44, 0xC0, ++0x01, 0x22, 0xC3, 0xF8, 0x00, 0xB0, 0x3A, 0x70, 0xD9, 0xF8, 0x10, 0x20, 0x0B, 0x68, 0x7A, 0x60, 0x23, 0xF0, 0x02, 0x03, ++0x0B, 0x60, 0xD8, 0xF8, 0x00, 0x10, 0xB6, 0xF8, 0xB2, 0xC0, 0x8B, 0x8F, 0x01, 0x68, 0x63, 0x44, 0xB3, 0xEB, 0x41, 0x1F, ++0x4F, 0xEA, 0x41, 0x1A, 0xD1, 0xD2, 0x74, 0x49, 0x58, 0x46, 0x17, 0xF0, 0xC9, 0xFA, 0xD9, 0xF8, 0x10, 0x20, 0xFB, 0x68, ++0x9B, 0x1A, 0x00, 0x2B, 0x80, 0xF2, 0xB6, 0x80, 0xB4, 0xF8, 0x68, 0x20, 0x6E, 0x4B, 0xA8, 0x68, 0x41, 0xF2, 0x13, 0x31, ++0x01, 0x2A, 0x5C, 0x5C, 0x40, 0xF2, 0x9F, 0x80, 0x01, 0x3A, 0x00, 0xFB, 0x02, 0xAA, 0x41, 0xF2, 0x13, 0x31, 0x52, 0x46, ++0x5B, 0x5C, 0x68, 0x49, 0x02, 0x20, 0x17, 0xF0, 0xAD, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB6, 0xF8, 0xB2, 0x00, 0x9A, 0x8F, ++0x60, 0x49, 0x64, 0x4B, 0xDF, 0xF8, 0xA8, 0xC1, 0x1C, 0x69, 0x0B, 0x68, 0x02, 0x44, 0xAA, 0xEB, 0x02, 0x02, 0x22, 0xF0, ++0x03, 0x05, 0x03, 0xF0, 0x03, 0x03, 0x2B, 0x43, 0x5E, 0x4D, 0x0B, 0x60, 0x2B, 0x68, 0xBA, 0x60, 0x43, 0xF0, 0x01, 0x03, ++0x2B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0xDC, 0xF8, 0x00, 0x10, 0xC3, 0xF3, 0x09, 0x03, 0x21, 0xF4, 0x7F, 0x71, 0x43, 0xF0, ++0x01, 0x03, 0x21, 0xF0, 0x03, 0x01, 0x0B, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0x2B, 0x68, 0x22, 0x44, 0x5B, 0x07, 0xFA, 0x60, ++0x03, 0xD5, 0x52, 0x4B, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x51, 0x49, 0x51, 0x4A, 0x0B, 0x68, 0x43, 0xF0, 0x08, 0x03, ++0x0B, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4E, 0x4C, 0x45, 0x49, 0x23, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x23, 0x60, ++0x01, 0x23, 0x13, 0x60, 0x0B, 0x68, 0x45, 0x4A, 0x43, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x11, 0x69, 0x01, 0xF5, 0x96, 0x71, ++0x13, 0x69, 0x5B, 0x1A, 0x00, 0x2B, 0xFB, 0xDB, 0x45, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x7F, 0xF4, 0x5D, 0xAF, ++0x43, 0x49, 0x44, 0x4C, 0x4B, 0x6A, 0x24, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xDF, 0x03, 0x4B, 0x62, 0x4B, 0x6A, ++0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0x5F, 0x43, 0x4B, 0x62, 0xB4, 0xB1, 0x3D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x3F, 0xDB, 0xE3, 0x68, 0x62, 0x68, 0x3A, 0x49, 0x02, 0x20, 0x17, 0xF0, 0x3C, 0xFA, 0xB6, 0xF8, 0xB2, 0x10, ++0xE2, 0x68, 0x2D, 0x4B, 0x52, 0x1A, 0x4F, 0xF4, 0x80, 0x20, 0x04, 0x21, 0x98, 0x60, 0x1A, 0x63, 0x99, 0x60, 0x34, 0x49, ++0x2F, 0x4A, 0x0B, 0x68, 0x43, 0xF4, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x6D, 0x43, 0xF4, 0x00, 0x43, 0x13, 0x65, 0xD3, 0x6D, ++0x23, 0xF0, 0x03, 0x03, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xF0, 0x01, 0x03, 0xD3, 0x65, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x53, ++0x13, 0x60, 0x1E, 0xE7, 0x70, 0x47, 0x41, 0xF2, 0x14, 0x32, 0x9C, 0x5C, 0x01, 0x2C, 0x7F, 0xF6, 0x5E, 0xAF, 0x5C, 0x5C, ++0xDC, 0xB1, 0x5A, 0x5C, 0x01, 0x3A, 0x00, 0xFB, 0x02, 0xAA, 0x56, 0xE7, 0x14, 0x4A, 0x22, 0x49, 0x41, 0xF2, 0x13, 0x33, ++0x58, 0x46, 0xD3, 0x5C, 0x52, 0x46, 0x17, 0xF0, 0x03, 0xFA, 0x54, 0xE7, 0x12, 0x69, 0xE3, 0x68, 0x9A, 0x1A, 0x10, 0x1A, ++0x00, 0x28, 0xBA, 0xDA, 0x1B, 0x49, 0x1C, 0x48, 0x40, 0xF2, 0x4F, 0x22, 0x17, 0xF0, 0x20, 0xFC, 0xB2, 0xE7, 0x9A, 0x5C, ++0x3A, 0xE7, 0x00, 0xBF, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0xED, 0x00, 0xE0, 0x3C, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0x40, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x84, 0x00, 0x32, 0x40, 0x54, 0x8D, 0x15, 0x00, 0x00, 0x40, 0x1E, 0x00, ++0x70, 0x8D, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x00, 0x41, 0x04, 0x40, 0x10, 0x00, 0x58, 0x40, ++0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x78, 0x36, 0x17, 0x00, 0x00, 0x60, 0x50, 0x40, 0xD0, 0x9C, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0xC8, 0x8D, 0x15, 0x00, 0x14, 0x00, 0x24, 0x40, 0x5C, 0x8D, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x80, 0x8D, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x70, 0xB5, 0x45, 0x4C, 0x21, 0x68, 0x0B, 0x78, 0x73, 0xB9, 0x44, 0x4B, ++0x44, 0x4D, 0x9B, 0x68, 0x01, 0x22, 0x2A, 0x70, 0x00, 0x2B, 0x3E, 0xD1, 0x0A, 0x78, 0x42, 0x49, 0x01, 0x23, 0x02, 0x20, ++0x17, 0xF0, 0xAC, 0xF9, 0x01, 0x23, 0x2B, 0x70, 0x3F, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x40, 0xD0, 0x02, 0x2B, ++0x28, 0xD0, 0x11, 0xF0, 0x8F, 0xFD, 0x28, 0xB3, 0x3B, 0x4B, 0xD3, 0xF8, 0xF8, 0x31, 0x0B, 0xBB, 0x3A, 0x4B, 0x3B, 0x4D, ++0x1B, 0x68, 0x95, 0xF8, 0x24, 0x20, 0xC3, 0xF3, 0x40, 0x63, 0x13, 0x43, 0x18, 0xD0, 0x6B, 0x7F, 0xB3, 0xB9, 0x37, 0x4E, ++0xD6, 0xF8, 0xF4, 0x30, 0x98, 0x47, 0x88, 0xB1, 0xF8, 0xF7, 0x7E, 0xFB, 0x34, 0x4A, 0xC0, 0xB2, 0x10, 0x70, 0x00, 0x28, ++0x35, 0xD0, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD8, 0xD6, 0xF8, 0xB4, 0x34, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, ++0x02, 0x2B, 0x22, 0xD0, 0x70, 0xBD, 0x93, 0xF8, 0x64, 0x20, 0x42, 0xB9, 0x1B, 0x68, 0x00, 0x2B, 0xC0, 0xD0, 0x93, 0xF8, ++0x62, 0x20, 0x00, 0x2A, 0xF5, 0xD0, 0x02, 0x2A, 0xF6, 0xD1, 0x0A, 0x78, 0x1F, 0x49, 0x00, 0x23, 0x02, 0x20, 0x17, 0xF0, ++0x67, 0xF9, 0x00, 0x23, 0x2B, 0x70, 0x70, 0xBD, 0x23, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x15, 0xD0, 0xFB, 0xF7, 0x5A, 0xFA, ++0x00, 0x28, 0xE1, 0xD0, 0x1E, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xB4, 0xD0, 0x70, 0xBD, 0x28, 0x6A, 0xD6, 0xF8, 0xB8, 0x34, ++0xD0, 0xF8, 0xE4, 0x10, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x19, 0x49, 0x02, 0x20, 0x17, 0xF0, 0x4B, 0xF9, 0xC4, 0xE7, ++0xF8, 0xF7, 0x3C, 0xFB, 0x13, 0x4B, 0x18, 0x70, 0xFB, 0xF7, 0x40, 0xFA, 0x18, 0xB1, 0x10, 0x4B, 0xD3, 0xF8, 0xB4, 0x34, ++0x98, 0x47, 0x12, 0x4A, 0x13, 0x68, 0x5B, 0x03, 0xFC, 0xD5, 0x11, 0x4A, 0x11, 0x69, 0x1C, 0x31, 0x13, 0x69, 0xCB, 0x1A, ++0x00, 0x2B, 0xFB, 0xDA, 0x70, 0xBD, 0x00, 0xBF, 0x74, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x3C, 0x61, 0x17, 0x00, ++0xD8, 0x8D, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x3D, 0x61, 0x17, 0x00, 0x9C, 0x4E, 0x17, 0x00, 0xD4, 0x8D, 0x15, 0x00, 0x20, 0x10, 0x04, 0x40, ++0x00, 0x10, 0x50, 0x40, 0x38, 0xB5, 0x43, 0x4D, 0x6B, 0x78, 0x03, 0xB9, 0x38, 0xBD, 0x42, 0x48, 0x42, 0x49, 0x03, 0x68, ++0x42, 0x4A, 0x23, 0xF0, 0x10, 0x03, 0x03, 0x60, 0x4B, 0x6F, 0x43, 0xF0, 0x10, 0x03, 0x4B, 0x67, 0x13, 0x68, 0x23, 0xF0, ++0x00, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x3C, 0x4C, 0x3C, 0x49, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x43, ++0x23, 0x60, 0x02, 0x20, 0x17, 0xF0, 0xF6, 0xF8, 0x00, 0x23, 0x22, 0x46, 0x6B, 0x70, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD5, ++0x36, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x3C, 0xDB, 0x31, 0x4B, 0x34, 0x4A, 0x19, 0x68, 0x21, 0xF0, ++0x80, 0x41, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x2F, 0x4B, ++0x2F, 0x48, 0x19, 0x68, 0x2F, 0x4C, 0x41, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, 0x01, 0x25, 0x21, 0xF0, 0x02, 0x01, ++0x19, 0x60, 0x15, 0x60, 0x03, 0x68, 0x43, 0xF4, 0x00, 0x13, 0x03, 0x60, 0x23, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x2E, 0xD0, ++0x01, 0x2B, 0x26, 0xD0, 0x26, 0x4B, 0x1B, 0x78, 0x53, 0xB1, 0x1D, 0x4A, 0x25, 0x49, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x73, ++0x13, 0x60, 0x02, 0x20, 0xBD, 0xE8, 0x38, 0x40, 0x17, 0xF0, 0xB8, 0xB8, 0x16, 0x4A, 0x20, 0x49, 0x53, 0x6F, 0x23, 0xF0, ++0x10, 0x03, 0x53, 0x67, 0x02, 0x20, 0xBD, 0xE8, 0x38, 0x40, 0x17, 0xF0, 0xAD, 0xB8, 0x1C, 0x4B, 0x2A, 0x78, 0x1B, 0x68, ++0x03, 0xF0, 0x0F, 0x03, 0x9A, 0x42, 0xBB, 0xD0, 0x19, 0x49, 0x1A, 0x48, 0x4F, 0xF4, 0x3A, 0x72, 0x17, 0xF0, 0xCA, 0xFA, ++0xB4, 0xE7, 0x18, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x43, 0x13, 0x60, 0xD2, 0xE7, 0x16, 0x4A, 0x13, 0x68, 0x23, 0xF0, ++0x01, 0x03, 0x13, 0x60, 0x0D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xCC, 0xD1, 0xD6, 0xE7, 0x00, 0xBF, 0x70, 0x28, 0x17, 0x00, ++0x10, 0x00, 0x58, 0x40, 0x00, 0x00, 0x50, 0x40, 0xE0, 0x50, 0x34, 0x40, 0x48, 0x80, 0x32, 0x40, 0xEC, 0x8D, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x58, 0x40, 0x34, 0x40, 0x78, 0x36, 0x17, 0x00, ++0x4C, 0x36, 0x17, 0x00, 0x28, 0x8E, 0x15, 0x00, 0x38, 0x00, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x8D, 0x15, 0x00, ++0x14, 0x00, 0x24, 0x40, 0x84, 0x40, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x47, 0x1F, 0x48, 0x20, 0x4D, 0x15, 0xF0, 0x36, 0xFE, ++0x1F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0x1D, 0x4E, 0x28, 0x68, 0xDF, 0xF8, 0x7C, 0x90, ++0xDF, 0xF8, 0x60, 0x80, 0xD9, 0xF8, 0x00, 0x30, 0x1A, 0x89, 0x54, 0x24, 0x02, 0xFB, 0x04, 0x42, 0x00, 0x21, 0xF2, 0xF7, ++0x91, 0xFD, 0x4F, 0xF0, 0x00, 0x0A, 0x58, 0x27, 0x29, 0x68, 0x33, 0x68, 0x1F, 0xFA, 0x8A, 0xF2, 0x04, 0xFB, 0x02, 0x11, ++0x07, 0xFB, 0x02, 0x33, 0xCB, 0x64, 0x40, 0x46, 0x15, 0xF0, 0x16, 0xFE, 0xD9, 0xF8, 0x00, 0x30, 0x0A, 0xF1, 0x01, 0x0A, ++0x1A, 0x89, 0x1F, 0xFA, 0x8A, 0xF3, 0x9A, 0x42, 0xEA, 0xD2, 0xBD, 0xE8, 0xF0, 0x87, 0x28, 0x68, 0x08, 0x4E, 0x10, 0xB1, ++0x33, 0x68, 0x00, 0x2B, 0xD2, 0xD1, 0x07, 0x48, 0x07, 0x49, 0x5B, 0x22, 0x17, 0xF0, 0x54, 0xFA, 0x28, 0x68, 0xCB, 0xE7, ++0x20, 0x58, 0x17, 0x00, 0x40, 0x61, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x14, 0x63, 0x18, 0x00, 0x40, 0x8E, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0x0D, 0x49, 0x00, 0xEB, 0xC0, 0x03, 0x10, 0xB4, 0x9C, 0x00, 0x00, 0x22, ++0x01, 0xEB, 0x83, 0x03, 0x16, 0x30, 0x0A, 0x51, 0x01, 0xEB, 0xC0, 0x00, 0x4F, 0xF4, 0x55, 0x64, 0x4F, 0xF0, 0xFF, 0x31, ++0xC3, 0xE9, 0x02, 0x41, 0xC0, 0xE9, 0x01, 0x22, 0x5D, 0xF8, 0x04, 0x4B, 0x5A, 0x60, 0x83, 0xF8, 0x20, 0x20, 0x5A, 0x61, ++0x19, 0x61, 0x70, 0x47, 0x44, 0x61, 0x17, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x80, 0x6C, 0x18, 0xB1, 0xF9, 0xF7, 0xCE, 0xFE, ++0x00, 0x23, 0xA3, 0x64, 0x10, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, 0x38, 0x4C, 0xDF, 0xF8, 0xF0, 0x80, 0x38, 0x4F, ++0x38, 0x4D, 0x04, 0xF5, 0x20, 0x76, 0xC4, 0xF8, 0x00, 0x80, 0xF3, 0xF7, 0x0F, 0xFE, 0x80, 0x03, 0x60, 0x60, 0xF3, 0xF7, ++0x0B, 0xFE, 0x01, 0x23, 0x01, 0x30, 0x03, 0xFA, 0x00, 0xF0, 0x01, 0x38, 0x00, 0x23, 0xC4, 0xE9, 0x02, 0x03, 0xC4, 0xE9, ++0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x27, 0x61, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, ++0x63, 0x62, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0xA3, 0x62, 0x2B, 0x68, 0x2A, 0x68, ++0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0xE3, 0x62, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, ++0x13, 0x43, 0x4F, 0xF4, 0x08, 0x51, 0x4F, 0xF4, 0x7C, 0x12, 0xA2, 0x63, 0xC4, 0xE9, 0x0C, 0x31, 0x40, 0x34, 0xB4, 0x42, ++0xC5, 0xD1, 0x1B, 0x4C, 0x1B, 0x4F, 0x18, 0x4E, 0xDF, 0xF8, 0x60, 0x80, 0x04, 0xF5, 0x80, 0x75, 0x27, 0x60, 0xF3, 0xF7, ++0xCF, 0xFD, 0x80, 0x03, 0x60, 0x60, 0xF3, 0xF7, 0xCB, 0xFD, 0x01, 0x23, 0x01, 0x30, 0x03, 0xFA, 0x00, 0xF0, 0x01, 0x38, ++0x00, 0x23, 0xC4, 0xE9, 0x02, 0x03, 0xC4, 0xE9, 0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x26, 0x61, 0xD8, 0xF8, 0x00, 0x20, ++0xD8, 0xF8, 0x00, 0x10, 0xA3, 0x62, 0x12, 0x02, 0xC9, 0xB2, 0x92, 0xB2, 0x0A, 0x43, 0x4F, 0xF4, 0x7C, 0x11, 0x62, 0x62, ++0xC4, 0xE9, 0x0B, 0x33, 0xC4, 0xE9, 0x0D, 0x31, 0x40, 0x34, 0xAC, 0x42, 0xD8, 0xD1, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, ++0x04, 0x39, 0x18, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0xA0, 0x00, 0x32, 0x40, 0x04, 0x38, 0x18, 0x00, 0x1E, 0xAB, 0xDC, 0xBA, ++0xF0, 0xB5, 0x16, 0x4C, 0x24, 0x68, 0x24, 0x78, 0x1D, 0x46, 0xE3, 0x07, 0x87, 0xB0, 0x16, 0x46, 0x06, 0xD5, 0x50, 0x19, ++0x00, 0x21, 0x08, 0x22, 0xF2, 0xF7, 0xA8, 0xFC, 0x07, 0xB0, 0xF0, 0xBD, 0xC3, 0x7E, 0x00, 0x93, 0x02, 0xAC, 0x07, 0x46, ++0x07, 0xF1, 0x12, 0x03, 0x20, 0x46, 0x07, 0xF1, 0x0C, 0x02, 0x1A, 0xF0, 0xE7, 0xFF, 0x2A, 0x46, 0x31, 0x46, 0x20, 0x46, ++0x1B, 0xF0, 0x08, 0xF8, 0x20, 0x46, 0x1B, 0xF0, 0xA3, 0xF8, 0x35, 0x44, 0x21, 0x46, 0x04, 0xAA, 0x60, 0x1A, 0x14, 0xF8, ++0x01, 0x3B, 0x43, 0x55, 0x94, 0x42, 0xF9, 0xD1, 0x07, 0xB0, 0xF0, 0xBD, 0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x83, 0x6C, 0x90, 0xF8, 0x42, 0xA0, 0x90, 0xF8, 0x33, 0x40, 0x90, 0xF8, 0x35, 0x20, 0x87, 0x88, 0x90, 0xF8, 0x32, 0x80, ++0xD3, 0xF8, 0x24, 0xC0, 0xC6, 0x6C, 0x93, 0xF8, 0x20, 0xE0, 0xA3, 0xEB, 0x0A, 0x05, 0xA8, 0x35, 0x22, 0x44, 0x01, 0x3F, ++0xAA, 0xEB, 0x04, 0x04, 0x3A, 0x44, 0x08, 0xEB, 0x05, 0x09, 0x2C, 0xF0, 0x02, 0x07, 0x04, 0xEB, 0x09, 0x0B, 0x5F, 0x62, ++0x54, 0x19, 0x03, 0xF1, 0x0C, 0x0A, 0xB8, 0xF1, 0x00, 0x0F, 0x03, 0xD0, 0x09, 0xF1, 0xFF, 0x32, 0xC6, 0xE9, 0x09, 0x52, ++0xF2, 0x6C, 0xC3, 0xF8, 0x14, 0xB0, 0x00, 0x25, 0x42, 0xF4, 0x80, 0x72, 0x1C, 0xF0, 0x01, 0x0F, 0x9C, 0x61, 0x1D, 0x61, ++0xC6, 0xF8, 0x20, 0xA0, 0xDD, 0x61, 0xF2, 0x64, 0x16, 0xD1, 0x40, 0x6A, 0x00, 0xF4, 0x60, 0x14, 0xB4, 0xF5, 0x60, 0x1F, ++0x01, 0xD0, 0x80, 0x02, 0x0E, 0xD4, 0x09, 0x48, 0x71, 0x44, 0x01, 0xEB, 0xC1, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x47, 0xF0, ++0x01, 0x07, 0x91, 0xF8, 0x20, 0x00, 0x5F, 0x62, 0x01, 0x30, 0x81, 0xF8, 0x20, 0x00, 0xF2, 0x64, 0x00, 0x22, 0x1A, 0x61, ++0xBD, 0xE8, 0xF0, 0x8F, 0x44, 0x61, 0x17, 0x00, 0x0A, 0x88, 0x03, 0x7F, 0x0A, 0x49, 0x12, 0xF4, 0x00, 0x5F, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x03, 0x12, 0x4F, 0xF4, 0xA4, 0x60, 0x92, 0xF8, 0xDA, 0x20, 0x00, 0xFB, 0x03, 0x13, 0x14, 0xBF, ++0x42, 0xF0, 0x02, 0x02, 0x02, 0xF0, 0xFD, 0x02, 0x83, 0xF8, 0xDA, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x43, 0x6A, 0x2D, 0xE9, 0xF0, 0x47, 0x91, 0x46, 0x9A, 0x02, 0xD0, 0xF8, 0x48, 0x80, 0x06, 0x46, 0x0F, 0x46, 0x29, 0xD5, ++0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x24, 0xD0, 0x50, 0x4C, 0x88, 0xF8, 0x20, 0x90, 0xD4, 0xF8, 0x80, 0x33, ++0x39, 0x46, 0x30, 0x46, 0x98, 0x47, 0x31, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x99, 0x42, 0x68, 0xD0, 0x4A, 0x4B, 0xB1, 0x6C, ++0x93, 0xF8, 0x05, 0x31, 0x00, 0x2B, 0x59, 0xD1, 0xB3, 0x68, 0x00, 0x2B, 0x49, 0xDB, 0x4B, 0x6A, 0x46, 0x4A, 0xCA, 0x60, ++0x23, 0xF0, 0x10, 0x03, 0x4B, 0x62, 0x30, 0x46, 0xD4, 0xF8, 0x04, 0x34, 0x8E, 0x60, 0x3A, 0x46, 0x98, 0x47, 0x00, 0x20, ++0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0x2C, 0xA0, 0x08, 0xF1, 0x24, 0x04, 0x0A, 0xF1, 0x40, 0x00, 0x53, 0x46, 0x53, 0xF8, ++0x04, 0x5B, 0x44, 0xF8, 0x04, 0x5F, 0x83, 0x42, 0xF9, 0xD1, 0xF3, 0x8B, 0x9D, 0x04, 0xCA, 0xD5, 0x38, 0x4B, 0x39, 0x49, ++0x1A, 0x68, 0x73, 0x7F, 0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, ++0x4C, 0x41, 0x38, 0xDB, 0x41, 0x46, 0xDA, 0xF8, 0x14, 0x20, 0xD4, 0xF8, 0x9C, 0x30, 0xC8, 0xF8, 0x40, 0x20, 0xDA, 0xF8, ++0x24, 0x20, 0xC8, 0xF8, 0x50, 0x20, 0xC3, 0xF3, 0xC2, 0x22, 0x05, 0x2A, 0xC8, 0xF8, 0x3C, 0x30, 0x31, 0xD0, 0xDA, 0xF8, ++0x3C, 0x30, 0x5C, 0x07, 0x5E, 0xBF, 0xD8, 0xF8, 0x2C, 0x30, 0x23, 0xF4, 0xC0, 0x73, 0xC8, 0xF8, 0x2C, 0x30, 0x88, 0x46, ++0x9F, 0xE7, 0x32, 0x8B, 0x33, 0x65, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0xAF, 0xD1, 0x8B, 0x6B, 0x23, 0xF4, 0x7F, 0x43, ++0x43, 0xF4, 0x60, 0x63, 0x8B, 0x63, 0xA8, 0xE7, 0xF2, 0x8B, 0x10, 0x07, 0xA5, 0xD4, 0xB2, 0x68, 0x52, 0x00, 0x58, 0xBF, ++0x81, 0xF8, 0x39, 0x30, 0x9F, 0xE7, 0xF3, 0x6C, 0x19, 0x48, 0xDA, 0x6A, 0x16, 0xF0, 0xFA, 0xFD, 0x90, 0xE7, 0x00, 0x2C, ++0xC4, 0xD1, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0x17, 0xF0, 0x6B, 0xF8, 0xB1, 0x6C, 0xBD, 0xE7, 0x03, 0xF4, ++0xC0, 0x63, 0xD8, 0xF8, 0x4C, 0x20, 0x94, 0xF8, 0xA1, 0x00, 0xB3, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x34, ++0x4F, 0xF4, 0x00, 0x34, 0x22, 0xF4, 0x40, 0x33, 0x23, 0x43, 0x20, 0xB1, 0x43, 0xF4, 0x80, 0x23, 0xC8, 0xF8, 0x4C, 0x30, ++0xB7, 0xE7, 0x23, 0xF4, 0x80, 0x23, 0xC8, 0xF8, 0x4C, 0x30, 0xB2, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xDE, 0xFA, 0xFE, 0xCA, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x78, 0x8E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x43, 0x6A, 0x85, 0x6C, 0x13, 0xF4, 0x00, 0x18, 0x83, 0xB0, 0x04, 0x46, ++0x05, 0xF1, 0x28, 0x07, 0x08, 0xD0, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x00, 0xF0, 0x93, 0x80, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0xC3, 0x8B, 0xC6, 0x6C, 0x1A, 0x07, 0x38, 0xD5, 0xDF, 0xF8, 0x58, 0x92, 0xD9, 0xF8, 0x00, 0x20, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xCF, 0x80, 0x71, 0x6A, 0x09, 0xB9, 0x32, 0x6A, 0x91, 0x68, 0x18, 0x06, ++0x09, 0xD5, 0x94, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xDD, 0x80, 0x94, 0xF8, 0x35, 0x30, 0x00, 0x2B, 0x40, 0xF0, ++0xDF, 0x80, 0xF3, 0x6C, 0x23, 0xF4, 0xF0, 0x03, 0xF3, 0x64, 0x0B, 0x79, 0xB7, 0x63, 0x13, 0xF0, 0x01, 0x0F, 0x08, 0xBF, ++0x4F, 0xF4, 0x00, 0x78, 0x00, 0x23, 0xC6, 0xF8, 0x48, 0x80, 0x33, 0x65, 0xEB, 0x6A, 0x2A, 0x6E, 0x72, 0x63, 0x43, 0xF0, ++0x02, 0x03, 0xEB, 0x62, 0x20, 0x46, 0x06, 0xF0, 0xBB, 0xF8, 0xA2, 0x6C, 0x53, 0x6A, 0x43, 0xF0, 0x10, 0x03, 0x53, 0x62, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x74, 0x4B, 0xD3, 0xF8, 0x28, 0x34, 0x98, 0x47, 0xEB, 0x6D, 0xB3, 0x64, 0x22, 0x7F, ++0x71, 0x49, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x12, 0x92, 0xF8, 0x62, 0x20, 0x5A, 0xBB, 0x6E, 0x49, 0x62, 0x7F, ++0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x52, 0x68, 0x91, 0x06, 0x22, 0xD5, 0xE2, 0x8B, 0x12, 0xF4, 0x00, 0x5F, ++0xE2, 0x6A, 0xD2, 0x6B, 0x14, 0xBF, 0xC2, 0xF3, 0x00, 0x12, 0xC2, 0xF3, 0xC0, 0x02, 0xBA, 0xB9, 0x70, 0x6A, 0x02, 0x88, ++0x91, 0xB2, 0x12, 0x04, 0x12, 0xD5, 0xC1, 0xF3, 0x0E, 0x01, 0x01, 0x80, 0x94, 0xF8, 0x33, 0x10, 0x94, 0xF8, 0x32, 0x20, ++0x04, 0x39, 0x04, 0x3A, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x32, 0x20, 0xD6, 0xE9, 0x0A, 0x21, 0x04, 0x39, 0x04, 0x3A, ++0xC6, 0xE9, 0x0A, 0x21, 0xDF, 0xF8, 0x70, 0x81, 0xB7, 0x63, 0xD8, 0xF8, 0x00, 0x20, 0xE7, 0x6C, 0xB2, 0xF9, 0x00, 0x20, ++0x00, 0x2A, 0x4F, 0xDB, 0x7A, 0x6A, 0x0A, 0xB9, 0x3A, 0x6A, 0x92, 0x68, 0x23, 0xF4, 0xC0, 0x63, 0xB3, 0x64, 0x12, 0x79, ++0xD2, 0x07, 0x5C, 0xBF, 0x43, 0xF4, 0x00, 0x73, 0xB3, 0x64, 0x9B, 0xE7, 0x83, 0x6A, 0x46, 0x6C, 0xC3, 0xF3, 0xC2, 0x22, ++0x05, 0x2A, 0x37, 0x63, 0x15, 0xD1, 0x03, 0xF4, 0xC0, 0x63, 0xEA, 0x6C, 0x90, 0xF8, 0x36, 0x10, 0xB3, 0xF5, 0x80, 0x6F, ++0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x33, 0x4F, 0xF4, 0x00, 0x33, 0x22, 0xF4, 0x40, 0x32, 0x1A, 0x43, 0x89, 0x06, 0x4C, 0xBF, ++0x42, 0xF4, 0x80, 0x22, 0x22, 0xF4, 0x80, 0x22, 0xEA, 0x64, 0x04, 0xF1, 0x28, 0x00, 0x04, 0xF0, 0xDD, 0xF9, 0xD4, 0xF8, ++0x48, 0xC0, 0xA2, 0x6A, 0xB0, 0x88, 0xDC, 0xF8, 0x24, 0x30, 0xE9, 0x6D, 0xEA, 0x63, 0xEA, 0x6A, 0x40, 0xF0, 0x08, 0x04, ++0xB4, 0x80, 0x41, 0xF4, 0xC0, 0x60, 0x2C, 0x6E, 0xF4, 0x62, 0x42, 0xF0, 0x02, 0x02, 0x30, 0x64, 0x43, 0xF0, 0x10, 0x03, ++0xEA, 0x62, 0x39, 0x46, 0x06, 0xF5, 0x82, 0x70, 0x34, 0x22, 0xCC, 0xF8, 0x24, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, ++0x29, 0xF0, 0xFE, 0xB9, 0xA2, 0x6C, 0x00, 0x2A, 0x3C, 0xD0, 0x7A, 0x6A, 0x00, 0x2A, 0xAD, 0xD1, 0x3A, 0x6A, 0x92, 0xB1, ++0xB3, 0x6C, 0xA8, 0xE7, 0x2D, 0xB3, 0x71, 0x6A, 0x00, 0x29, 0x7F, 0xF4, 0x30, 0xAF, 0x32, 0x6A, 0x0A, 0xB1, 0xE3, 0x8B, ++0x2A, 0xE7, 0x23, 0x49, 0x23, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x3F, 0xFF, 0x32, 0x6A, 0xF5, 0xE7, 0x1F, 0x49, ++0x1F, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x37, 0xFF, 0x3A, 0x6A, 0xE4, 0xE7, 0x20, 0x22, 0x20, 0x46, 0x01, 0x91, ++0x22, 0xF0, 0xD8, 0xF8, 0x01, 0x99, 0x20, 0xE7, 0xA2, 0x88, 0x01, 0x91, 0x20, 0x46, 0x23, 0xF0, 0x87, 0xFA, 0x01, 0x99, ++0x19, 0xE7, 0x14, 0x49, 0x15, 0x48, 0x4F, 0xF4, 0xD9, 0x72, 0x16, 0xF0, 0x21, 0xFF, 0x71, 0x6A, 0xA9, 0xB9, 0xD9, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCF, 0xDB, 0xD8, 0xE7, 0x4F, 0xF4, 0xD9, 0x72, 0x0B, 0x49, 0x0D, 0x48, ++0x16, 0xF0, 0x12, 0xFF, 0x7A, 0x6A, 0x42, 0xB9, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB7, 0xDB, ++0xD1, 0xE7, 0xE3, 0x8B, 0xED, 0xE6, 0xB3, 0x6C, 0x60, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x8E, 0x15, 0x00, 0x8C, 0x8E, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x05, 0x28, 0x1C, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x07, 0x0B, 0x0F, 0x13, 0x17, 0x03, 0x12, 0x4B, 0x20, 0x22, 0x1A, 0x60, ++0x70, 0x47, 0x10, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0E, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0C, 0x4B, ++0x08, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0A, 0x4B, 0x10, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x70, 0x47, 0x07, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x04, 0x49, 0x05, 0x48, ++0x4F, 0xF4, 0x77, 0x72, 0x16, 0xF0, 0xCA, 0xBE, 0x80, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x05, 0x28, 0x85, 0xB0, 0x06, 0x46, 0x00, 0xF0, 0xE5, 0x81, 0xAE, 0x4C, ++0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, 0xAB, 0x4B, 0xAC, 0x4F, 0xDF, 0xF8, 0xD4, 0x92, ++0x01, 0x22, 0x19, 0x46, 0xB2, 0x40, 0x71, 0x18, 0x00, 0x92, 0xA3, 0x7E, 0x02, 0x91, 0xD2, 0x43, 0x4F, 0xEA, 0x81, 0x08, ++0x01, 0x92, 0x00, 0x2B, 0x3A, 0xD0, 0x3B, 0x68, 0x65, 0x6A, 0x5B, 0x78, 0xD5, 0xF8, 0x8C, 0x20, 0x00, 0x2B, 0x00, 0xF0, ++0x8B, 0x80, 0x69, 0x6D, 0x00, 0x29, 0x00, 0xF0, 0x11, 0x81, 0x00, 0x2A, 0x80, 0xF2, 0x29, 0x81, 0x9D, 0x49, 0xD9, 0xF8, ++0x00, 0x30, 0x51, 0xF8, 0x26, 0x10, 0x0B, 0x44, 0x11, 0x02, 0xC8, 0xF8, 0x00, 0x30, 0x40, 0xF1, 0xA2, 0x80, 0xAB, 0x88, ++0x99, 0x06, 0x40, 0xF1, 0x43, 0x81, 0x97, 0x4A, 0x43, 0xF0, 0x10, 0x03, 0x52, 0xF8, 0x26, 0x00, 0xAB, 0x80, 0x15, 0xF0, ++0x87, 0xF9, 0x94, 0xF8, 0x50, 0x30, 0x3A, 0x68, 0x01, 0x3B, 0x84, 0xF8, 0x50, 0x30, 0x00, 0x23, 0xA3, 0x76, 0x63, 0x62, ++0x53, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0x6B, 0x6D, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0xA5, 0x62, 0xEB, 0x7A, ++0x01, 0x33, 0xEB, 0x72, 0xE5, 0x68, 0x00, 0x2D, 0x00, 0xF0, 0x90, 0x81, 0xD5, 0xF8, 0x4C, 0xB0, 0xDB, 0xF8, 0x50, 0xA0, ++0xBA, 0xF1, 0x00, 0x0F, 0x80, 0xF2, 0xA9, 0x81, 0x30, 0x46, 0xCB, 0xF8, 0x10, 0xA0, 0x04, 0xF0, 0x03, 0xF9, 0x6A, 0x6A, ++0x12, 0xF4, 0x00, 0x10, 0x11, 0xD1, 0xDB, 0xF8, 0x18, 0x10, 0x00, 0x29, 0x00, 0xF0, 0x97, 0x80, 0x8B, 0x6B, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x00, 0x1F, 0x8C, 0x46, 0x00, 0xF0, 0x29, 0x81, 0xDC, 0xF8, 0x3C, 0x30, 0x00, 0x2B, 0x80, 0xF2, ++0x9D, 0x81, 0x1A, 0xF4, 0x00, 0x0F, 0x0B, 0xD0, 0x6B, 0x7F, 0x0D, 0x2B, 0x08, 0xD8, 0x73, 0x48, 0x73, 0x49, 0x4F, 0xF4, ++0x1E, 0x7C, 0x0C, 0xFB, 0x03, 0x03, 0x09, 0x69, 0xC3, 0xF8, 0x58, 0x12, 0x02, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x60, 0x1F, ++0x00, 0xF0, 0x9E, 0x80, 0x04, 0xF1, 0x0C, 0x00, 0x15, 0xF0, 0x18, 0xFA, 0x6B, 0x6A, 0x9B, 0x02, 0x04, 0xD4, 0x94, 0xF8, ++0x50, 0x30, 0x01, 0x3B, 0x84, 0xF8, 0x50, 0x30, 0xAB, 0x88, 0x00, 0x2B, 0x5F, 0xD1, 0x28, 0x46, 0x02, 0xF0, 0x4C, 0xF8, ++0x60, 0x4A, 0xD9, 0xF8, 0x00, 0x30, 0x52, 0xF8, 0x26, 0x20, 0x13, 0x44, 0xC8, 0xF8, 0x00, 0x30, 0xA3, 0x7E, 0x6A, 0xE7, ++0x29, 0x69, 0x00, 0x29, 0x00, 0xF0, 0xA4, 0x80, 0xAB, 0x6C, 0x00, 0x2B, 0x80, 0xF2, 0x9D, 0x80, 0x57, 0x4B, 0xD9, 0xF8, ++0x00, 0x20, 0x53, 0xF8, 0x26, 0x10, 0xAB, 0x88, 0x0A, 0x44, 0xC8, 0xF8, 0x00, 0x20, 0x9A, 0x06, 0x3F, 0xF5, 0x77, 0xAF, ++0xDF, 0xF8, 0x6C, 0xB1, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x4F, 0xF0, 0x04, 0x0A, 0xAB, 0x88, 0x99, 0x06, 0x3F, 0xF5, ++0x6C, 0xAF, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xBA, 0xF1, 0x01, 0x0A, 0xF5, 0xD1, 0xAB, 0x88, 0x9A, 0x06, 0x3F, 0xF5, ++0x62, 0xAF, 0x04, 0xF1, 0x1C, 0x00, 0x15, 0xF0, 0xD3, 0xF9, 0xAB, 0x88, 0x5B, 0xE7, 0x2B, 0x69, 0x00, 0x2B, 0x7F, 0xF4, ++0x71, 0xAF, 0x46, 0x4B, 0x1B, 0x68, 0xEF, 0xF3, 0x10, 0x82, 0xD0, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x43, 0x4A, 0x01, 0x21, ++0x11, 0x60, 0x43, 0x4A, 0x01, 0x99, 0x10, 0x68, 0x3F, 0x4D, 0x0B, 0x40, 0x41, 0x1C, 0x11, 0x60, 0x2B, 0x60, 0x29, 0xB1, ++0x3D, 0x4B, 0x10, 0x60, 0x1B, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x3C, 0x4B, 0x00, 0x9A, 0x1A, 0x60, 0x00, 0x22, ++0xA3, 0x7E, 0x22, 0x60, 0x17, 0xE7, 0x51, 0x46, 0x28, 0x46, 0x32, 0x46, 0x01, 0xF0, 0xC6, 0xF9, 0x9C, 0xE7, 0x33, 0x4B, ++0x1B, 0x68, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x30, 0x4A, 0x01, 0x21, 0x11, 0x60, 0xDF, 0xF8, ++0xC0, 0xC0, 0x01, 0x99, 0xDC, 0xF8, 0x00, 0x00, 0x2B, 0x4A, 0x0B, 0x40, 0x41, 0x1C, 0xCC, 0xF8, 0x00, 0x10, 0x13, 0x60, ++0x39, 0xB1, 0x29, 0x4B, 0xCC, 0xF8, 0x00, 0x00, 0x1B, 0x68, 0x10, 0xB9, 0x00, 0x2B, 0x40, 0xF0, 0xA2, 0x80, 0x27, 0x4B, ++0x00, 0x9A, 0x1A, 0x60, 0x94, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x2B, 0x22, 0x60, 0x7C, 0xD0, 0x6A, 0x6A, 0x4C, 0xE7, ++0x6B, 0x6C, 0x63, 0x62, 0x01, 0x23, 0x40, 0x20, 0xA3, 0x76, 0x15, 0xF0, 0x91, 0xF8, 0x59, 0xE7, 0x94, 0xF8, 0x50, 0x10, ++0x01, 0x29, 0x7F, 0xF4, 0xEA, 0xAE, 0xE1, 0x6A, 0x00, 0x29, 0x3F, 0xF4, 0xE6, 0xAE, 0x21, 0x6B, 0x19, 0x48, 0x09, 0x7F, ++0x4F, 0xF0, 0xA4, 0x0C, 0x0C, 0xFB, 0x01, 0x61, 0x99, 0x31, 0x50, 0xF8, 0x31, 0x10, 0x00, 0x29, 0x7B, 0xD0, 0x00, 0x2B, ++0x3F, 0xF4, 0x62, 0xAF, 0x00, 0x2A, 0xFF, 0xF6, 0xD7, 0xAE, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x94, 0xF8, 0x50, 0x10, ++0x01, 0x29, 0x7F, 0xF4, 0x57, 0xAF, 0xE1, 0x6A, 0x00, 0x29, 0xE2, 0xD1, 0x52, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, ++0x4A, 0x80, 0x0C, 0x10, 0x34, 0x36, 0x17, 0x00, 0xB0, 0x35, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x80, 0x32, 0x40, ++0x18, 0x88, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xDF, 0xF8, 0x68, 0xB1, 0xDB, 0xF8, 0x9C, 0x32, ++0x98, 0x47, 0x4F, 0xF0, 0x04, 0x0A, 0xAB, 0x88, 0x9A, 0x06, 0x3F, 0xF5, 0xB2, 0xAE, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, ++0xBA, 0xF1, 0x01, 0x0A, 0xF5, 0xD1, 0x4D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xAB, 0x88, 0xBF, 0xF6, ++0xA4, 0xAE, 0x98, 0x06, 0x3F, 0xF5, 0xA1, 0xAE, 0x48, 0x49, 0x49, 0x48, 0x4F, 0xF4, 0xAC, 0x62, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x16, 0xF0, 0xEB, 0xBC, 0x43, 0x48, 0x8B, 0x68, 0x01, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x00, 0x29, 0x33, 0xDB, ++0x60, 0x46, 0x9C, 0x46, 0xCC, 0xE6, 0xE3, 0x6A, 0x00, 0x2B, 0x3F, 0xF4, 0x7F, 0xAF, 0x23, 0x6B, 0x3E, 0x4A, 0x1B, 0x7F, ++0xA4, 0x21, 0x01, 0xFB, 0x03, 0x63, 0x99, 0x33, 0x52, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x73, 0xAF, 0x3A, 0x4B, ++0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0x6D, 0xAF, 0x38, 0x4B, 0x30, 0x46, 0xD3, 0xF8, 0x5C, 0x33, 0x98, 0x47, ++0x66, 0xE7, 0x62, 0xB6, 0x5B, 0xE7, 0x33, 0x49, 0x91, 0xF8, 0xFF, 0x11, 0x00, 0x29, 0x7F, 0xF4, 0x7E, 0xAF, 0x31, 0x4B, ++0x03, 0x92, 0xD3, 0xF8, 0x5C, 0x33, 0x30, 0x46, 0x98, 0x47, 0x3B, 0x68, 0x03, 0x9A, 0x5B, 0x78, 0x00, 0x2B, 0x7F, 0xF4, ++0x75, 0xAF, 0xD5, 0xE6, 0x00, 0x2B, 0xC9, 0xD1, 0x25, 0x49, 0x2A, 0x48, 0x00, 0x93, 0x40, 0xF2, 0x56, 0x42, 0x16, 0xF0, ++0xD9, 0xFC, 0x00, 0x9B, 0xDB, 0x6B, 0xFF, 0xDE, 0x26, 0x4C, 0x1F, 0xE6, 0x26, 0x4B, 0x25, 0x60, 0x1B, 0x68, 0xEF, 0xF3, ++0x10, 0x82, 0xD0, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x23, 0x4A, 0x01, 0x21, 0x11, 0x60, 0x23, 0x4A, 0x01, 0x99, 0x10, 0x68, ++0x1F, 0x4C, 0x19, 0x40, 0x0B, 0x46, 0x41, 0x1C, 0x11, 0x60, 0x23, 0x60, 0x29, 0xB1, 0x1D, 0x4B, 0x10, 0x60, 0x1B, 0x68, ++0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x1C, 0x4B, 0x00, 0x9A, 0x1A, 0x60, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x6B, 0x6A, ++0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x7F, 0xF4, 0x41, 0xAF, 0x68, 0x6C, 0x31, 0x46, 0x0C, 0x30, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0x03, 0xF0, 0x28, 0xBF, 0x10, 0xB1, 0x31, 0x46, 0x03, 0xF0, 0x24, 0xFF, 0x10, 0x4B, 0x11, 0x4A, ++0x53, 0xF8, 0x26, 0x10, 0x02, 0x9B, 0x12, 0x68, 0x9B, 0x00, 0x0A, 0x44, 0x1A, 0x60, 0x2A, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xD4, 0x8E, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xC0, 0x8E, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x88, 0x80, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x43, 0x6A, 0x9B, 0x02, 0x03, 0xD5, 0x4B, 0x6A, ++0x5B, 0x07, 0x07, 0xD4, 0x70, 0x47, 0xC1, 0x6C, 0x05, 0x4B, 0x14, 0x31, 0xD3, 0xF8, 0x9C, 0x33, 0x08, 0x46, 0x18, 0x47, ++0x42, 0x6C, 0x93, 0x88, 0x43, 0xF0, 0x02, 0x03, 0x93, 0x80, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x43, 0x7F, ++0x0B, 0x4E, 0x4F, 0xF4, 0x1E, 0x75, 0x04, 0x46, 0x05, 0xFB, 0x03, 0xF5, 0x05, 0xF5, 0xFE, 0x70, 0x01, 0x23, 0xE1, 0x76, ++0x84, 0xF8, 0x5D, 0x30, 0x30, 0x44, 0x21, 0x46, 0x14, 0xF0, 0xFE, 0xFF, 0x04, 0x4B, 0x71, 0x19, 0x20, 0x46, 0x5B, 0x69, ++0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x83, 0x88, 0x2D, 0xE9, ++0xF0, 0x41, 0x04, 0x46, 0x0E, 0x46, 0x15, 0x46, 0xEB, 0xB1, 0x3A, 0x4B, 0xD0, 0xF8, 0x4C, 0x80, 0x1A, 0x68, 0xB2, 0xF9, ++0x00, 0x20, 0x00, 0x2A, 0x23, 0xDB, 0xD8, 0xF8, 0x24, 0x70, 0x17, 0xB9, 0xD8, 0xF8, 0x20, 0x30, 0x9F, 0x68, 0x04, 0x2D, ++0x03, 0xD1, 0x39, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x13, 0xFB, 0xE3, 0x7E, 0xFF, 0x2B, 0x25, 0xD0, 0x2F, 0x4F, 0x29, 0x46, ++0xD7, 0xF8, 0x00, 0x34, 0x20, 0x46, 0x98, 0x47, 0x05, 0xE0, 0x82, 0x6C, 0x2B, 0x4F, 0x53, 0x6A, 0x43, 0xF0, 0x10, 0x03, ++0x53, 0x62, 0xD7, 0xF8, 0xA4, 0x33, 0x2A, 0x46, 0x31, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x82, 0x6C, ++0x5A, 0xB3, 0xD8, 0xF8, 0x24, 0x70, 0x00, 0x2F, 0xDB, 0xD1, 0xD8, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0xD6, 0xD1, 0x21, 0x49, ++0x21, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x03, 0xFC, 0xCD, 0xE7, 0xE3, 0x8B, 0x1A, 0x07, 0x04, 0xD5, 0x3A, 0x88, ++0x02, 0xF0, 0xDC, 0x02, 0x10, 0x2A, 0x25, 0xD0, 0xBB, 0x7D, 0x13, 0xF0, 0x0F, 0x03, 0x07, 0xF1, 0x16, 0x07, 0x06, 0xD0, ++0x18, 0x4A, 0xB2, 0xF8, 0xFC, 0x21, 0x43, 0xEA, 0x02, 0x13, 0x3B, 0x80, 0xC4, 0xE7, 0x15, 0x49, 0xB1, 0xF8, 0xFC, 0x21, ++0x01, 0x32, 0x92, 0xB2, 0xA1, 0xF8, 0xFC, 0x21, 0xF3, 0xE7, 0x0F, 0x49, 0x11, 0x48, 0x4F, 0xF4, 0xD9, 0x72, 0x16, 0xF0, ++0xDF, 0xFB, 0xD8, 0xF8, 0x24, 0x70, 0x00, 0x2F, 0xA9, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC7, 0xDB, 0x9F, 0xE7, 0x7A, 0x8B, 0x00, 0x2A, 0xD6, 0xD1, 0x43, 0xF0, 0x20, 0x03, 0xE3, 0x83, 0x38, 0x1D, 0x20, 0xF0, ++0xF9, 0xFE, 0xCF, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x8E, 0x15, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x8C, 0x8E, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x46, 0x05, 0x29, 0x00, 0xF2, 0x33, 0x81, 0xDF, 0xE8, ++0x01, 0xF0, 0x36, 0x44, 0x51, 0x5E, 0x6B, 0x03, 0x9D, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0x00, 0xF0, ++0x04, 0x81, 0x9B, 0x4A, 0x9B, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x42, 0x1A, 0x60, 0x9A, 0x49, 0x9A, 0x4A, 0x9B, 0x4B, ++0x51, 0xF8, 0x24, 0x50, 0x12, 0x68, 0x9A, 0x48, 0x23, 0x44, 0x9B, 0x00, 0x01, 0x21, 0x2A, 0x44, 0x01, 0xFA, 0x04, 0xF4, ++0x1A, 0x60, 0x04, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x94, 0x4B, 0x19, 0x60, 0x94, 0x4B, ++0x94, 0x49, 0x18, 0x68, 0x0D, 0x68, 0x42, 0x1C, 0x2C, 0x43, 0x1A, 0x60, 0x0C, 0x60, 0x2A, 0xB1, 0x8E, 0x4A, 0x18, 0x60, ++0x13, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x84, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x13, 0x02, 0x2B, ++0x00, 0xF0, 0xAE, 0x80, 0x8A, 0x4A, 0x82, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0xCB, 0xE7, 0x7D, 0x4A, ++0x13, 0x68, 0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0x7D, 0xD0, 0x85, 0x4A, 0x7B, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x62, ++0x1A, 0x60, 0xBE, 0xE7, 0x76, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x33, 0x02, 0x2B, 0x4F, 0xD0, 0x7F, 0x4A, 0x75, 0x4B, ++0x10, 0x60, 0x4F, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0xB1, 0xE7, 0x70, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, ++0x21, 0xD0, 0x7A, 0x4A, 0x6E, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0xA4, 0xE7, 0x77, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0xDB, 0x75, 0x4A, 0x68, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, ++0x97, 0xE7, 0x63, 0x4B, 0x1B, 0x68, 0x03, 0xF0, 0x03, 0x03, 0x02, 0x2B, 0xF2, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x6F, 0x49, ++0x6F, 0x48, 0x4F, 0xF4, 0xEC, 0x62, 0x16, 0xF0, 0xFF, 0xBA, 0x60, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, ++0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, 0xF6, 0xD0, 0x63, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCA, 0xDA, 0x52, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, 0xC4, 0xD1, ++0xBD, 0xE8, 0x38, 0x40, 0x5E, 0x49, 0x60, 0x48, 0x40, 0xF2, 0x6C, 0x72, 0x16, 0xF0, 0xDE, 0xBA, 0x4F, 0x49, 0x0D, 0x68, ++0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x33, 0x02, 0x2B, ++0xF6, 0xD0, 0x53, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x9C, 0xDA, 0x42, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, ++0x01, 0x33, 0x02, 0x2B, 0x96, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x4E, 0x49, 0x50, 0x48, 0x4F, 0xF4, 0xEF, 0x62, 0x16, 0xF0, ++0xBD, 0xBA, 0x3F, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, ++0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0xF6, 0xD0, 0x42, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0x6E, 0xAF, 0x31, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0x7F, 0xF4, 0x67, 0xAF, 0xBD, 0xE8, 0x38, 0x40, ++0x3C, 0x49, 0x40, 0x48, 0x40, 0xF2, 0x84, 0x72, 0x16, 0xF0, 0x9A, 0xBA, 0x2D, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, ++0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x13, 0x02, 0x2B, 0xF6, 0xD0, 0x31, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0x3E, 0xAF, 0x1F, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x13, ++0x02, 0x2B, 0x7F, 0xF4, 0x37, 0xAF, 0xBD, 0xE8, 0x38, 0x40, 0x2B, 0x49, 0x2F, 0x48, 0x4F, 0xF4, 0xF2, 0x62, 0x16, 0xF0, ++0x77, 0xBA, 0x1C, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, ++0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0xF6, 0xD0, 0x1F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0xE8, 0xAE, 0x0E, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0x7F, 0xF4, 0xE1, 0xAE, 0xBD, 0xE8, 0x38, 0x40, ++0x19, 0x49, 0x1F, 0x48, 0x40, 0xF2, 0x9C, 0x72, 0x16, 0xF0, 0x54, 0xBA, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xBF, 0xF6, 0xD8, 0xAE, 0x13, 0x49, 0x19, 0x48, 0x40, 0xF2, 0xA2, 0x72, 0x16, 0xF0, 0x79, 0xFA, 0xD0, 0xE6, ++0x88, 0x81, 0x32, 0x40, 0x34, 0x83, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, ++0x4A, 0x80, 0x0C, 0x10, 0x88, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, ++0x9C, 0x81, 0x32, 0x40, 0xA0, 0x81, 0x32, 0x40, 0xA4, 0x81, 0x32, 0x40, 0xA8, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x98, 0x81, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0xF8, 0x8E, 0x15, 0x00, 0x18, 0x8F, 0x15, 0x00, 0x38, 0x8F, 0x15, 0x00, ++0x58, 0x8F, 0x15, 0x00, 0x78, 0x8F, 0x15, 0x00, 0x98, 0x8F, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x05, 0x2A, 0xF8, 0xB5, ++0x06, 0x46, 0x0D, 0x46, 0x35, 0xD0, 0x54, 0x21, 0x33, 0x4C, 0x01, 0xFB, 0x02, 0xF1, 0x02, 0xEB, 0x42, 0x03, 0x61, 0x58, ++0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, 0x00, 0x29, 0x37, 0xD0, 0x2E, 0x4F, 0x3B, 0x68, 0x5B, 0x78, 0xF3, 0xB1, ++0x4E, 0x60, 0x05, 0x2A, 0x0B, 0xD0, 0x2C, 0x48, 0x02, 0xEB, 0x42, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x91, 0xF8, 0x2E, 0x10, ++0x41, 0xB9, 0x90, 0xF8, 0x8C, 0x10, 0x00, 0x29, 0x3E, 0xD1, 0x10, 0x46, 0xFF, 0xF7, 0x2A, 0xFB, 0x3B, 0x68, 0x5B, 0x78, ++0x3B, 0xB9, 0xAA, 0x6B, 0x92, 0x02, 0x46, 0xBF, 0x01, 0x23, 0xC4, 0xE9, 0x01, 0x63, 0xC4, 0xE9, 0x01, 0x33, 0x25, 0x60, ++0xF8, 0xBD, 0xA0, 0x68, 0x00, 0x28, 0xDD, 0xD0, 0x61, 0x68, 0x4E, 0x60, 0xDB, 0xE7, 0x19, 0x4C, 0xD4, 0xF8, 0xA4, 0x11, ++0x04, 0xF5, 0xD2, 0x74, 0x00, 0x29, 0xCF, 0xD1, 0x11, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x44, 0xFE, 0x14, 0x4B, 0x1B, 0x68, ++0x5B, 0x78, 0xDF, 0xE7, 0x13, 0x4B, 0x02, 0xEB, 0x42, 0x00, 0x03, 0xEB, 0x80, 0x00, 0x51, 0x00, 0x90, 0xF8, 0x2E, 0x00, ++0x38, 0xB9, 0x93, 0xF8, 0x8C, 0x00, 0x93, 0xF8, 0x7E, 0x70, 0x00, 0x28, 0xE8, 0xD0, 0xBA, 0x42, 0xE6, 0xD1, 0x0A, 0x44, ++0x03, 0xEB, 0x82, 0x03, 0x5A, 0x6A, 0x42, 0xB1, 0x07, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0xC5, 0xE7, 0x90, 0xF8, 0x7E, 0x10, ++0x91, 0x42, 0xBC, 0xD1, 0xC0, 0xE7, 0x03, 0x4A, 0x5E, 0x62, 0x13, 0x68, 0x5B, 0x78, 0xBB, 0xE7, 0x20, 0x62, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x38, 0xB5, 0x83, 0x88, 0x33, 0xB1, 0x04, 0x46, 0x80, 0x6C, 0x18, 0xB1, ++0x63, 0x6A, 0x13, 0xF4, 0x00, 0x15, 0x00, 0xD0, 0x38, 0xBD, 0xF8, 0xF7, 0x75, 0xFE, 0xA5, 0x64, 0x38, 0xBD, 0x00, 0xBF, ++0x70, 0xB5, 0x20, 0x4C, 0x20, 0x4D, 0x02, 0xF0, 0xD9, 0xFC, 0xD4, 0xF8, 0x44, 0x33, 0x98, 0x47, 0xFE, 0xF7, 0x9E, 0xFF, ++0x00, 0xF0, 0xA8, 0xFD, 0xD4, 0xF8, 0xA8, 0x33, 0x00, 0x20, 0x98, 0x47, 0x04, 0xF0, 0xBA, 0xFE, 0x4F, 0xF4, 0x01, 0x72, ++0x00, 0x21, 0xA5, 0xF1, 0x0C, 0x00, 0xF1, 0xF7, 0xC3, 0xFC, 0x05, 0xF5, 0xD2, 0x76, 0x00, 0x24, 0x28, 0x46, 0x14, 0xF0, ++0x4D, 0xFD, 0x45, 0xF8, 0x0C, 0x4C, 0xAC, 0x73, 0x85, 0xF8, 0x44, 0x40, 0xC5, 0xE9, 0x06, 0x44, 0x05, 0xF1, 0x10, 0x00, ++0x54, 0x35, 0x14, 0xF0, 0x41, 0xFD, 0xB5, 0x42, 0xEE, 0xD1, 0x0C, 0x4D, 0x05, 0xF5, 0xD8, 0x70, 0x14, 0xF0, 0x3A, 0xFD, ++0x05, 0xF5, 0xE0, 0x70, 0xC5, 0xE9, 0x72, 0x44, 0xC5, 0xF8, 0xA4, 0x41, 0x85, 0xF8, 0xBE, 0x41, 0x85, 0xF8, 0xF4, 0x41, ++0x14, 0xF0, 0x2E, 0xFD, 0xA5, 0xF8, 0xFC, 0x41, 0x70, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x62, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x0C, 0x4B, 0x93, 0xF8, 0xFE, 0x31, 0x0B, 0xB1, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x04, 0x46, ++0x10, 0xF0, 0xBC, 0xF8, 0x20, 0xB1, 0x94, 0xF8, 0xC0, 0x34, 0x1B, 0xB9, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, ++0x94, 0xF8, 0xC1, 0x04, 0x11, 0xF0, 0x16, 0xFD, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x10, 0xBD, 0x20, 0x62, 0x17, 0x00, ++0x45, 0x4B, 0x01, 0x22, 0x70, 0xB4, 0x1B, 0x68, 0x02, 0xFA, 0x00, 0xF6, 0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, ++0x72, 0xB6, 0x41, 0x49, 0x0A, 0x60, 0x41, 0x4A, 0x3E, 0x4D, 0x14, 0x68, 0x23, 0xEA, 0x06, 0x03, 0x61, 0x1C, 0x11, 0x60, ++0x2B, 0x60, 0x29, 0xB1, 0x3B, 0x4B, 0x14, 0x60, 0x1B, 0x68, 0x0C, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x3A, 0x4B, 0x1E, 0x60, ++0x05, 0x28, 0x5D, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x12, 0x21, 0x3F, 0x30, 0x4E, 0x03, 0x37, 0x4B, 0x37, 0x4A, 0x4F, 0xF4, ++0x00, 0x11, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF0, 0x40, 0x7F, 0xFB, 0xD1, 0x34, 0x4B, 0x4F, 0xF4, 0x00, 0x12, 0x70, 0xBC, ++0x1A, 0x60, 0x70, 0x47, 0x2F, 0x4B, 0x30, 0x4A, 0x4F, 0xF4, 0x80, 0x31, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF0, 0x30, 0x0F, ++0xFB, 0xD1, 0x2D, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x28, 0x4B, 0x28, 0x4A, 0x4F, 0xF4, ++0x00, 0x31, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x7F, 0xFB, 0xD1, 0x25, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x70, 0xBC, ++0x1A, 0x60, 0x70, 0x47, 0x20, 0x4B, 0x21, 0x4A, 0x4F, 0xF4, 0x00, 0x21, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x3F, ++0xFB, 0xD1, 0x1E, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x19, 0x4B, 0x19, 0x4A, 0x4F, 0xF4, ++0x80, 0x21, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x5F, 0xFB, 0xD1, 0x16, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x70, 0xBC, ++0x1A, 0x60, 0x70, 0x47, 0x11, 0x4B, 0x12, 0x4A, 0x4F, 0xF4, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x9B, 0x07, 0xFC, 0xD1, ++0x0F, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0x1A, 0x60, 0x70, 0xBC, 0x70, 0x47, 0x0D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xF7, 0xDA, 0x70, 0xBC, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0xE7, 0x02, 0x16, 0xF0, 0xD5, 0xB8, 0x00, 0xBF, ++0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x80, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, ++0x88, 0x81, 0x32, 0x40, 0x84, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x70, 0xB5, 0x05, 0x28, 0x82, 0xB0, 0x04, 0x46, 0x0A, 0x46, 0x3B, 0xD0, 0x1E, 0x4B, 0x00, 0xEB, 0x40, 0x05, 0xC5, 0xEB, ++0xC5, 0x05, 0x03, 0xEB, 0x85, 0x05, 0x1C, 0x4E, 0x1C, 0x49, 0xD6, 0xF8, 0x84, 0x33, 0x01, 0x92, 0x01, 0xEB, 0xC4, 0x01, ++0x20, 0x46, 0x98, 0x47, 0x01, 0x9A, 0xD6, 0xF8, 0x84, 0x33, 0x05, 0xF1, 0x0C, 0x01, 0x20, 0x46, 0x98, 0x47, 0x00, 0x23, ++0x20, 0x46, 0x2B, 0x60, 0x6B, 0x61, 0xFE, 0xF7, 0x59, 0xFE, 0x13, 0x4B, 0x01, 0x22, 0x1B, 0x68, 0x02, 0xFA, 0x04, 0xF4, ++0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x0F, 0x49, 0x0A, 0x60, 0x0F, 0x4A, 0x0C, 0x4D, 0x11, 0x68, ++0x23, 0xEA, 0x04, 0x03, 0x48, 0x1C, 0x10, 0x60, 0x2B, 0x60, 0x28, 0xB1, 0x09, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x08, 0x4B, 0x1C, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x07, 0x4D, 0xC8, 0xE7, 0x20, 0x62, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x24, 0x64, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x88, 0x80, 0x32, 0x40, 0xC4, 0x63, 0x17, 0x00, 0x70, 0xB5, 0x0E, 0x4E, 0x82, 0xB0, 0x00, 0xF5, 0x9E, 0x64, 0x00, 0x25, ++0xE8, 0xB2, 0x21, 0x46, 0xD6, 0xF8, 0x84, 0x33, 0x01, 0x90, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0x01, 0x35, 0xA4, 0xF1, ++0x28, 0x01, 0x01, 0x98, 0xD6, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0x05, 0x2D, 0x04, 0xF1, 0x08, 0x04, ++0xEA, 0xD1, 0x02, 0xB0, 0x70, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x05, 0x29, 0x2D, 0xE9, 0xF0, 0x41, 0x0E, 0x46, ++0x04, 0x46, 0x64, 0xD0, 0x33, 0x4D, 0x01, 0xEB, 0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x05, 0xEB, 0x83, 0x05, 0x94, 0xF8, ++0x35, 0x10, 0x94, 0xF8, 0x33, 0x20, 0xA3, 0x88, 0x2E, 0x48, 0x0A, 0x44, 0x1A, 0x44, 0xE3, 0x6C, 0xE1, 0x8B, 0x58, 0x61, ++0x04, 0x32, 0xDA, 0x62, 0x00, 0x22, 0xC3, 0xE9, 0x0F, 0x22, 0xC3, 0xE9, 0x06, 0x22, 0xC3, 0xE9, 0x08, 0x22, 0x5A, 0x64, ++0x9A, 0x62, 0x9A, 0x63, 0xDA, 0x64, 0x1A, 0x63, 0x1A, 0x65, 0xCA, 0x07, 0x05, 0xD4, 0x22, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, ++0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x21, 0x4B, 0x1B, 0x6A, 0x23, 0xB1, 0x20, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x33, ++0x13, 0x60, 0xDF, 0xF8, 0x88, 0x80, 0x61, 0x7F, 0x20, 0x7F, 0x00, 0x22, 0x12, 0xF0, 0x5A, 0xF9, 0xD8, 0xF8, 0x48, 0x32, ++0xE1, 0x7E, 0x60, 0x7F, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x16, 0x4F, 0xD8, 0xF8, 0x68, 0x33, 0x3A, 0x68, 0x01, 0x32, 0x3A, 0x60, 0x31, 0x46, 0x20, 0x46, 0x98, 0x47, ++0xD8, 0xF8, 0x08, 0x34, 0x31, 0x46, 0x00, 0x22, 0x20, 0x46, 0x98, 0x47, 0x21, 0x46, 0x05, 0xF1, 0x0C, 0x00, 0x14, 0xF0, ++0x99, 0xFB, 0x3B, 0x68, 0x33, 0xB1, 0x0A, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x07, 0x4D, 0x9F, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, ++0x1C, 0x9E, 0x17, 0x00, 0x80, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x03, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, 0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x70, 0x47, 0x00, 0xBF, ++0x20, 0x62, 0x17, 0x00, 0x05, 0x29, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x46, 0x04, 0x46, 0x1C, 0xD0, 0x47, 0x4E, 0x01, 0xEB, ++0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x06, 0xEB, 0x83, 0x06, 0x22, 0x7F, 0x44, 0x4B, 0xE7, 0x6C, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x02, 0x30, 0xFF, 0xF7, 0x32, 0xFE, 0x68, 0xB9, 0x63, 0x7F, 0xFF, 0x2B, 0x67, 0xD0, 0x3F, 0x4B, 0x20, 0x46, ++0xD3, 0xF8, 0x90, 0x33, 0x29, 0x46, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x3C, 0x4E, 0xE7, 0xE7, 0x20, 0x46, ++0x1C, 0xF0, 0xEE, 0xFF, 0x00, 0x28, 0xEC, 0xD0, 0xFB, 0x6C, 0x43, 0xF4, 0x80, 0x73, 0xFB, 0x64, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x34, 0x4F, 0x96, 0xF8, 0x50, 0x30, 0x3A, 0x68, ++0xF1, 0x6A, 0xDF, 0xF8, 0xBC, 0x80, 0x01, 0x32, 0x01, 0x33, 0x3A, 0x60, 0x86, 0xF8, 0x50, 0x30, 0x19, 0xB1, 0xD8, 0xF8, ++0x5C, 0x33, 0x28, 0x46, 0x98, 0x47, 0x73, 0x69, 0x00, 0x2B, 0x42, 0xD0, 0x06, 0xF1, 0x0C, 0x00, 0x21, 0x46, 0x14, 0xF0, ++0x21, 0xFB, 0x3B, 0x68, 0x2B, 0xB1, 0x26, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x00, 0x2B, 0x31, 0xD0, 0x1F, 0x4A, ++0x24, 0x49, 0xD2, 0xF8, 0xF8, 0x31, 0x09, 0x6A, 0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x21, 0xB1, 0x21, 0x4A, 0x13, 0x68, ++0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x19, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x3B, 0x68, 0xD8, 0xF8, 0x04, 0x64, 0xA1, 0x6C, 0x01, 0x33, 0x3B, 0x60, 0x2A, 0x46, 0x20, 0x46, 0xB0, 0x47, ++0x3B, 0x68, 0x33, 0xB1, 0x12, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x01, 0x20, ++0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x46, 0x00, 0x21, 0x01, 0xF0, 0x7E, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x2A, ++0xCB, 0xD0, 0x62, 0xB6, 0xC9, 0xE7, 0xA3, 0x6C, 0x0B, 0x49, 0x5A, 0x6A, 0x9C, 0x60, 0x22, 0xF0, 0x10, 0x02, 0x5A, 0x62, ++0xD9, 0x60, 0xB3, 0xE7, 0x20, 0x62, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x80, 0x00, 0x32, 0x40, 0xDE, 0xFA, 0xFE, 0xCA, ++0x70, 0x47, 0x00, 0xBF, 0x20, 0x4B, 0x70, 0xB5, 0x1C, 0x68, 0xE1, 0x04, 0x2C, 0xD4, 0x1F, 0x4D, 0x2C, 0x42, 0x24, 0xD1, ++0x1E, 0x4B, 0x23, 0x40, 0x20, 0xD0, 0x22, 0x03, 0x0B, 0xD5, 0x1D, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x05, 0x24, ++0x1B, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xA0, 0x33, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x19, 0x4A, 0x12, 0x68, 0xB2, 0xF9, ++0x00, 0x20, 0xB3, 0xFA, 0x83, 0xF3, 0xC3, 0xF1, 0x19, 0x04, 0x00, 0x2A, 0xE4, 0xB2, 0x14, 0xDB, 0x05, 0x2C, 0xE6, 0xD0, ++0x10, 0x4A, 0xA1, 0x1D, 0x01, 0x23, 0x8B, 0x40, 0x13, 0x60, 0xE5, 0xE7, 0x70, 0xBD, 0x04, 0xF0, 0x07, 0xFB, 0x0C, 0x4B, ++0x1D, 0x60, 0xD5, 0xE7, 0x04, 0xF0, 0x56, 0xFA, 0x09, 0x4B, 0x4F, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0xCB, 0xE7, 0x06, 0x2C, ++0xE8, 0xD9, 0x09, 0x49, 0x09, 0x48, 0x40, 0xF6, 0xC2, 0x22, 0x15, 0xF0, 0xD9, 0xFE, 0xE3, 0xE7, 0x78, 0x80, 0x32, 0x40, ++0x00, 0x08, 0x00, 0x20, 0xC0, 0x07, 0x08, 0x00, 0x7C, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xB8, 0x8F, 0x15, 0x00, 0x38, 0xB5, 0x0D, 0x4B, 0x0D, 0x4D, 0x1C, 0x68, 0xE3, 0x06, 0x05, 0xEA, ++0x04, 0x05, 0x03, 0xD5, 0x0B, 0x4B, 0xD3, 0xF8, 0xF0, 0x33, 0x98, 0x47, 0x14, 0xF4, 0x70, 0x04, 0x08, 0xD0, 0x08, 0x4B, ++0xB4, 0xFA, 0x84, 0xF4, 0xC4, 0xF1, 0x0B, 0x00, 0xD3, 0xF8, 0x48, 0x33, 0xC0, 0xB2, 0x98, 0x47, 0x04, 0x4B, 0x1D, 0x60, ++0x38, 0xBD, 0x00, 0xBF, 0x78, 0x80, 0x32, 0x40, 0x1F, 0x00, 0xF0, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x7C, 0x80, 0x32, 0x40, ++0xFF, 0xF7, 0xDA, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1C, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x70, 0x90, 0x1A, 0x4F, 0xD9, 0xF8, 0x00, 0x30, 0xDF, 0xF8, 0x6C, 0x80, 0x01, 0x33, ++0xC9, 0xF8, 0x00, 0x30, 0x3D, 0x46, 0x46, 0x46, 0x04, 0x24, 0x95, 0xF8, 0x5E, 0x30, 0xE2, 0xB2, 0x63, 0xB9, 0x97, 0xF8, ++0x8C, 0x30, 0x97, 0xF8, 0x7E, 0x10, 0x10, 0x46, 0x0B, 0xB1, 0x91, 0x42, 0x04, 0xD0, 0xD6, 0xF8, 0x50, 0x31, 0x0B, 0xB1, ++0xFF, 0xF7, 0x1A, 0xFD, 0x01, 0x3C, 0x63, 0x1C, 0xA5, 0xF1, 0x0C, 0x05, 0xA6, 0xF1, 0x54, 0x06, 0xE7, 0xD1, 0xD9, 0xF8, ++0x00, 0x30, 0x01, 0x22, 0x88, 0xF8, 0xFF, 0x21, 0x3B, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x31, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x31, 0x4E, 0x31, 0x4D, 0x33, 0x68, 0x31, 0x4F, 0xDF, 0xF8, ++0xD0, 0xB0, 0xDF, 0xF8, 0xD0, 0xA0, 0xDF, 0xF8, 0xD0, 0x80, 0x01, 0x33, 0x00, 0x22, 0x33, 0x60, 0x85, 0xF8, 0xFF, 0x21, ++0xB9, 0x46, 0x04, 0x24, 0x99, 0xF8, 0x5E, 0x30, 0xE0, 0xB2, 0x00, 0x2B, 0x34, 0xD1, 0x97, 0xF8, 0x8C, 0x30, 0x97, 0xF8, ++0x7E, 0x20, 0x0B, 0xB1, 0x82, 0x42, 0x2D, 0xD0, 0xD5, 0xF8, 0x50, 0x31, 0x43, 0xB3, 0x01, 0x90, 0xFE, 0xF7, 0x36, 0xFF, ++0x5A, 0xF8, 0x24, 0x30, 0xDB, 0xF8, 0x00, 0x20, 0x20, 0x48, 0x1A, 0x44, 0x40, 0xF8, 0x24, 0x20, 0x01, 0x21, 0x1F, 0x4A, ++0x01, 0xFA, 0x04, 0xF3, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x82, 0x12, 0xF0, 0x01, 0x0F, 0x01, 0x98, 0x02, 0xD1, 0x72, 0xB6, ++0x14, 0x4A, 0x11, 0x60, 0x32, 0x68, 0xD8, 0xF8, 0x00, 0xC0, 0x51, 0x1C, 0x43, 0xEA, 0x0C, 0x03, 0x31, 0x60, 0xC8, 0xF8, ++0x00, 0x30, 0x29, 0xB1, 0x0E, 0x4B, 0x32, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x03, 0xF0, 0x32, 0xF8, ++0x01, 0x3C, 0x63, 0x1C, 0xA9, 0xF1, 0x0C, 0x09, 0xA5, 0xF1, 0x54, 0x05, 0xBE, 0xD1, 0x33, 0x68, 0x33, 0xB1, 0x06, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x40, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, ++0x14, 0xF0, 0xF8, 0xB8, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x28, 0x01, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x20, 0x01, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x4F, 0x5D, 0x4E, 0xDF, 0xF8, 0x90, 0x91, 0xB6, 0xF8, 0xFC, 0x31, 0x83, 0xB0, 0x4F, 0xF4, 0x78, 0x30, ++0x00, 0x93, 0x06, 0xF1, 0x0C, 0x05, 0x14, 0xF0, 0xFB, 0xF8, 0x01, 0x23, 0x86, 0xF8, 0xFE, 0x31, 0xAA, 0x46, 0x4F, 0xF4, ++0x9E, 0x67, 0x4F, 0xF0, 0x00, 0x0B, 0x01, 0x95, 0x53, 0x49, 0xD9, 0xF8, 0x84, 0x33, 0x5F, 0xFA, 0x8B, 0xF8, 0x40, 0x46, ++0x4F, 0xF0, 0x80, 0x42, 0x39, 0x44, 0x98, 0x47, 0x4F, 0x4B, 0x9D, 0x68, 0xA7, 0xF1, 0x28, 0x04, 0xC5, 0xB1, 0xE9, 0x19, ++0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x40, 0x46, 0x98, 0x47, 0x29, 0x19, 0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, ++0x80, 0x42, 0x40, 0x46, 0x98, 0x47, 0x05, 0xF5, 0xA3, 0x61, 0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x40, 0x46, ++0x98, 0x47, 0x2D, 0x68, 0x00, 0x2D, 0xE6, 0xD1, 0x51, 0x46, 0xD9, 0xF8, 0x84, 0x33, 0x40, 0x46, 0x08, 0x37, 0x4F, 0xF0, ++0x80, 0x42, 0x98, 0x47, 0xB7, 0xF5, 0xA3, 0x6F, 0x0B, 0xF1, 0x01, 0x0B, 0x0A, 0xF1, 0x54, 0x0A, 0xC8, 0xD1, 0xD9, 0xF8, ++0x84, 0x33, 0x39, 0x49, 0x01, 0x9D, 0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0x37, 0x49, 0xD9, 0xF8, 0x84, 0x33, ++0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0x02, 0xF0, 0x30, 0xF9, 0x00, 0xF0, 0x6A, 0xF9, 0xD9, 0xF8, 0xCC, 0x33, ++0x98, 0x47, 0x2C, 0x48, 0x4F, 0xF4, 0x01, 0x72, 0x00, 0x21, 0xF1, 0xF7, 0x89, 0xF8, 0x2B, 0x4B, 0xD3, 0xF8, 0x08, 0x80, ++0x00, 0x9B, 0xA6, 0xF8, 0xFC, 0x31, 0xB8, 0xF1, 0x00, 0x0F, 0x17, 0xD0, 0x2B, 0x46, 0x45, 0x46, 0x98, 0x46, 0x05, 0xF5, ++0x9E, 0x64, 0x05, 0xF5, 0xA3, 0x67, 0x20, 0x46, 0x14, 0xF0, 0x06, 0xF9, 0xA4, 0xF1, 0x28, 0x00, 0x08, 0x34, 0x14, 0xF0, ++0x01, 0xF9, 0xBC, 0x42, 0xF5, 0xD1, 0x20, 0x46, 0x14, 0xF0, 0xFC, 0xF8, 0x2D, 0x68, 0x00, 0x2D, 0xEB, 0xD1, 0x45, 0x46, ++0x1B, 0x4F, 0x00, 0x24, 0x28, 0x46, 0x14, 0xF0, 0xF3, 0xF8, 0x45, 0xF8, 0x0C, 0x4C, 0xAC, 0x73, 0x85, 0xF8, 0x44, 0x40, ++0xC5, 0xE9, 0x06, 0x44, 0x05, 0xF1, 0x10, 0x00, 0x54, 0x35, 0x14, 0xF0, 0xE7, 0xF8, 0xAF, 0x42, 0xEE, 0xD1, 0x12, 0x48, ++0x14, 0xF0, 0xE2, 0xF8, 0x12, 0x48, 0xC6, 0xF8, 0xA4, 0x41, 0xC6, 0xE9, 0x72, 0x44, 0x86, 0xF8, 0xBE, 0x41, 0x86, 0xF8, ++0xF4, 0x41, 0x14, 0xF0, 0xD7, 0xF8, 0x0E, 0x4A, 0x00, 0x21, 0x02, 0xF5, 0xB4, 0x70, 0xA2, 0xF1, 0x24, 0x03, 0x43, 0xF8, ++0x04, 0x1B, 0x93, 0x42, 0xFB, 0xD1, 0x03, 0xF1, 0x24, 0x02, 0x90, 0x42, 0xF5, 0xD1, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x20, 0x62, 0x17, 0x00, 0x34, 0x5F, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xD0, 0x63, 0x17, 0x00, 0x4C, 0x64, 0x17, 0x00, ++0xE0, 0x63, 0x17, 0x00, 0xD8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x03, 0x8C, 0x08, 0x8C, 0x83, 0x42, 0x08, 0xD8, ++0x05, 0xD2, 0xC0, 0x1A, 0x3F, 0x28, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x51, 0xB9, 0x81, 0x6C, 0x90, 0xF8, 0x42, 0x30, 0xCB, 0x1A, 0x93, 0xF8, 0xB8, 0x30, 0xDB, 0x07, ++0x02, 0xD4, 0x03, 0x8B, 0x08, 0x2B, 0x00, 0xD0, 0x70, 0x47, 0x91, 0xF8, 0xA8, 0x30, 0x03, 0xF0, 0xF0, 0x03, 0x40, 0x2B, ++0xF8, 0xD1, 0x91, 0xF8, 0xB1, 0x30, 0x06, 0x2B, 0x01, 0xD0, 0x01, 0x2B, 0xF2, 0xD1, 0x13, 0x68, 0x01, 0x33, 0x13, 0x60, ++0xEE, 0xE7, 0x00, 0xBF, 0x03, 0x6D, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x43, 0x56, 0x4A, 0x12, 0x68, ++0x12, 0x78, 0x02, 0x2A, 0x83, 0xB0, 0x04, 0x46, 0x0D, 0x46, 0x07, 0xD0, 0x01, 0x2A, 0x7E, 0xD0, 0x03, 0x2A, 0x00, 0xF0, ++0x8D, 0x80, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0xFB, 0xF7, 0x8A, 0xFB, 0x06, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x94, 0x80, ++0xDF, 0xF8, 0x60, 0x91, 0x42, 0xF2, 0x24, 0x03, 0x59, 0xF8, 0x03, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x87, 0x80, 0x48, 0x48, ++0x14, 0xF0, 0xA8, 0xF8, 0x4F, 0xF0, 0x00, 0x08, 0x08, 0x22, 0x12, 0x23, 0x32, 0x70, 0x86, 0xF8, 0x01, 0x80, 0x86, 0xF8, ++0x03, 0x80, 0xB3, 0x70, 0x23, 0x6D, 0x29, 0x68, 0x00, 0x91, 0x23, 0xF0, 0x40, 0x43, 0x07, 0x46, 0x69, 0x46, 0x30, 0x1D, ++0x01, 0x93, 0x27, 0xF0, 0x49, 0xFF, 0x42, 0xF2, 0x34, 0x03, 0x39, 0xF8, 0x03, 0x30, 0xB3, 0xF5, 0xC3, 0x7F, 0x62, 0xD8, ++0x03, 0xF1, 0x01, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xDA, 0x00, 0x37, 0x49, 0xBB, 0x81, 0x09, 0x68, 0x36, 0x4B, 0x01, 0xEB, ++0x02, 0x0C, 0x42, 0xF2, 0x34, 0x08, 0xCC, 0xF8, 0x04, 0x60, 0x88, 0x58, 0x03, 0x40, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF0, ++0x0C, 0x03, 0x8B, 0x50, 0x99, 0xF8, 0x02, 0x3C, 0x29, 0xF8, 0x08, 0xE0, 0x01, 0x33, 0x01, 0x22, 0x00, 0x20, 0x0C, 0x21, ++0x89, 0xF8, 0x02, 0x3C, 0xC7, 0xF8, 0x04, 0xC0, 0xBA, 0x73, 0x38, 0x60, 0xB9, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x02, 0xD4, 0x72, 0xB6, 0x26, 0x4B, 0x1A, 0x60, 0x26, 0x4E, 0x2B, 0x68, 0x31, 0x68, 0x22, 0x8C, 0x25, 0x48, 0x4D, 0x1C, ++0x21, 0x46, 0x35, 0x60, 0x15, 0xF0, 0xEC, 0xF9, 0x23, 0x48, 0x39, 0x46, 0x14, 0xF0, 0x0E, 0xF8, 0x22, 0x4B, 0xD3, 0xF8, ++0x44, 0x34, 0x98, 0x47, 0x33, 0x68, 0x00, 0x2B, 0x8D, 0xD0, 0x1B, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x00, 0x2B, ++0x87, 0xD1, 0x00, 0x2A, 0x85, 0xD0, 0x62, 0xB6, 0x83, 0xE7, 0x0E, 0x68, 0x00, 0x96, 0x23, 0xF0, 0x40, 0x43, 0x69, 0x46, ++0x08, 0x22, 0x12, 0x20, 0x01, 0x93, 0xF9, 0xF7, 0xD7, 0xFA, 0x2B, 0x68, 0x22, 0x8C, 0x15, 0x48, 0x21, 0x46, 0x15, 0xF0, ++0xC7, 0xF9, 0x72, 0xE7, 0x13, 0x4B, 0x0A, 0x68, 0x1B, 0x68, 0x1A, 0x60, 0xF6, 0xF7, 0x72, 0xF8, 0x6B, 0xE7, 0x42, 0x46, ++0x43, 0x46, 0x4F, 0xF0, 0x01, 0x0E, 0x9C, 0xE7, 0x0E, 0x48, 0xF6, 0xF7, 0xED, 0xFF, 0x62, 0xE7, 0x0D, 0x48, 0xF6, 0xF7, ++0xE9, 0xFF, 0x5E, 0xE7, 0x78, 0x36, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, 0x00, 0x00, 0xFF, 0x31, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x90, 0x15, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x20, 0x90, 0x15, 0x00, 0x00, 0x38, 0x18, 0x00, 0xDC, 0x8F, 0x15, 0x00, 0xD8, 0x83, 0x15, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x10, 0xB5, 0x0D, 0x4C, 0x30, 0x22, 0x00, 0x21, 0x20, 0x46, 0xF0, 0xF7, 0x21, 0xFF, 0x20, 0x46, 0x13, 0xF0, 0xAE, 0xFF, ++0x04, 0xF1, 0x08, 0x00, 0x13, 0xF0, 0xAA, 0xFF, 0x04, 0xF1, 0x10, 0x00, 0x13, 0xF0, 0xA6, 0xFF, 0x04, 0xF1, 0x18, 0x00, ++0x13, 0xF0, 0xA2, 0xFF, 0x04, 0xF1, 0x20, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0xF0, 0x9C, 0xBF, 0x24, 0x64, 0x17, 0x00, ++0x38, 0xB5, 0xC3, 0x6C, 0x04, 0x46, 0x09, 0x48, 0x19, 0x61, 0x00, 0xEB, 0xC2, 0x00, 0x21, 0x46, 0x15, 0x46, 0x13, 0xF0, ++0x93, 0xFF, 0x63, 0x6A, 0x9B, 0x02, 0x00, 0xD5, 0x38, 0xBD, 0x04, 0x4B, 0x53, 0xF8, 0x25, 0x00, 0xBD, 0xE8, 0x38, 0x40, ++0x13, 0xF0, 0xE6, 0xBE, 0x24, 0x64, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x38, 0xB5, 0x38, 0x4B, 0x93, 0xF8, 0x8C, 0x20, ++0x05, 0x46, 0x00, 0x2A, 0x42, 0xD1, 0x43, 0x6D, 0xC3, 0xF3, 0xC1, 0x23, 0x54, 0x22, 0x1C, 0x21, 0x33, 0x48, 0x12, 0xFB, ++0x03, 0x13, 0x18, 0x44, 0x13, 0xF0, 0xB6, 0xFF, 0x04, 0x46, 0x31, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, ++0x01, 0xDB, 0x14, 0xB9, 0x38, 0xBD, 0x00, 0x2C, 0x4C, 0xD0, 0xA2, 0x88, 0x68, 0x6D, 0x42, 0xF0, 0x20, 0x02, 0x81, 0x01, ++0xA2, 0x80, 0xF5, 0xD5, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF3, 0xCF, 0x31, 0xC0, 0xF3, 0xC9, 0x33, 0x26, 0xDB, ++0x62, 0x7A, 0x10, 0x3B, 0x93, 0x42, 0xE9, 0xD1, 0xEB, 0x69, 0x99, 0x68, 0x0B, 0x8A, 0x03, 0xF0, 0x1E, 0x02, 0x16, 0x2A, ++0x25, 0xD0, 0x82, 0x05, 0xE0, 0xD4, 0x2A, 0x8E, 0x1C, 0x2A, 0xDD, 0xD1, 0xA2, 0x7A, 0xB2, 0xEB, 0x13, 0x3F, 0xD9, 0xD1, ++0x04, 0xF1, 0xE0, 0x05, 0x12, 0x31, 0x28, 0x46, 0x0A, 0x22, 0x27, 0xF0, 0x37, 0xFE, 0xC4, 0xF8, 0xDC, 0x50, 0x1A, 0xE0, ++0x93, 0xF8, 0x7E, 0x30, 0x05, 0x2B, 0xBB, 0xD1, 0x14, 0x48, 0x13, 0xF0, 0x77, 0xFF, 0x04, 0x46, 0xBF, 0xE7, 0x11, 0xF4, ++0x7C, 0x7F, 0xD5, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x10, 0x49, 0x11, 0x48, 0xD0, 0x22, 0x15, 0xF0, 0x49, 0xBB, 0x10, 0x4B, ++0x28, 0x46, 0xD3, 0xF8, 0xB4, 0x33, 0x21, 0x46, 0x98, 0x47, 0x00, 0x28, 0xB4, 0xD0, 0xA3, 0x88, 0x43, 0xF0, 0x40, 0x03, ++0xA3, 0x80, 0x38, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x06, 0x49, 0x09, 0x48, 0x40, 0xF2, 0x5F, 0x12, 0x15, 0xF0, 0x34, 0xBB, ++0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xE0, 0x63, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x50, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x3C, 0x90, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xB0, 0x4B, 0xB1, 0x4C, ++0x1B, 0x68, 0xB1, 0x4A, 0xB3, 0xF9, 0x00, 0x30, 0x2D, 0xED, 0x02, 0x8B, 0x87, 0xB0, 0x01, 0x46, 0x01, 0x90, 0x00, 0x2B, ++0x04, 0xEB, 0xC0, 0x00, 0x08, 0xEE, 0x10, 0x0A, 0x52, 0xF8, 0x21, 0x40, 0xC0, 0xF2, 0x38, 0x83, 0x20, 0x46, 0x13, 0xF0, ++0x6B, 0xFE, 0xA6, 0x4B, 0x01, 0x9A, 0x53, 0xF8, 0x32, 0x40, 0x00, 0x2C, 0x00, 0xF0, 0xAD, 0x80, 0x00, 0x23, 0xCD, 0xE9, ++0x04, 0x33, 0x9B, 0x46, 0x98, 0x46, 0xA2, 0x4B, 0x62, 0x7F, 0x93, 0xF8, 0x00, 0x32, 0x03, 0x92, 0x01, 0x2B, 0x22, 0x7F, ++0xE6, 0x6C, 0x67, 0x6C, 0x02, 0x92, 0x00, 0xF0, 0xA1, 0x80, 0x00, 0x2F, 0x00, 0xF0, 0xA8, 0x80, 0x3B, 0x79, 0xD8, 0x06, ++0x40, 0xF1, 0x95, 0x80, 0x35, 0x69, 0x59, 0x06, 0x25, 0xF4, 0x00, 0x05, 0x0B, 0xF1, 0x01, 0x0B, 0x35, 0x61, 0x00, 0xF1, ++0x9B, 0x81, 0xDF, 0xF8, 0x70, 0xA2, 0x00, 0x21, 0xDA, 0xF8, 0x18, 0x34, 0x20, 0x46, 0x98, 0x47, 0x63, 0x6A, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x08, 0xBF, 0xA0, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x8B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x38, 0x92, 0xD9, 0xF8, 0x00, 0x30, 0x18, 0xEE, 0x10, 0x0A, 0x01, 0x33, ++0xC9, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0xE4, 0xFE, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x60, 0x1F, 0x00, 0xF0, ++0x5F, 0x81, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x7F, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x22, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0x00, 0xF0, 0x30, 0x81, 0xE2, 0x6A, 0xD3, 0x6B, ++0x98, 0x06, 0x40, 0xF1, 0xFD, 0x80, 0x15, 0xF4, 0x00, 0x05, 0x00, 0xF0, 0x7E, 0x81, 0xE1, 0x6C, 0x4F, 0x6A, 0x39, 0x88, ++0x88, 0xB2, 0x09, 0x04, 0x00, 0xF1, 0xEB, 0x81, 0x71, 0x4F, 0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0x36, 0xD0, 0x63, 0x7F, ++0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x6B, 0x49, 0xA0, 0x88, ++0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x12, 0x1A, 0x41, 0xF8, 0x23, 0x20, 0x68, 0x4B, 0x93, 0xF8, 0x04, 0x31, ++0x13, 0xB1, 0x00, 0x2D, 0x40, 0xF0, 0x33, 0x82, 0x06, 0xF1, 0x10, 0x01, 0x20, 0x46, 0xFF, 0xF7, 0xC9, 0xFD, 0xE3, 0x8B, ++0xDA, 0x07, 0x00, 0xF1, 0x93, 0x81, 0xA0, 0x6C, 0x30, 0xB1, 0xF7, 0xF7, 0x4F, 0xFF, 0x3B, 0x68, 0x1D, 0x78, 0x01, 0x2D, ++0x00, 0xF0, 0xCB, 0x81, 0x9D, 0xF8, 0x04, 0x00, 0x21, 0x46, 0x15, 0xF0, 0x5B, 0xFB, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, ++0xB3, 0xF5, 0x60, 0x1F, 0x00, 0xF0, 0x74, 0x81, 0x4F, 0x4B, 0x01, 0x9A, 0x53, 0xF8, 0x32, 0x40, 0x00, 0x2C, 0x7F, 0xF4, ++0x58, 0xAF, 0x07, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0x4A, 0x00, 0x23, 0x40, 0x20, 0x82, 0xF8, ++0x00, 0x32, 0x13, 0xF0, 0x87, 0xFD, 0x00, 0x2F, 0x7F, 0xF4, 0x58, 0xAF, 0xEF, 0xF3, 0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x45, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x47, 0x4D, 0x2B, 0x68, 0x18, 0xEE, 0x10, 0x0A, 0x01, 0x33, 0x2B, 0x60, ++0x13, 0xF0, 0x5A, 0xFE, 0x2B, 0x68, 0x3B, 0xB1, 0x3E, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x13, 0xB9, 0x00, 0x2A, ++0x40, 0xF0, 0xF3, 0x81, 0x20, 0x46, 0xD6, 0xF8, 0x10, 0x90, 0x94, 0xF8, 0x1C, 0xA0, 0x23, 0xF0, 0x95, 0xFF, 0xE2, 0x6A, ++0xD3, 0x6B, 0x98, 0x06, 0x40, 0xF1, 0x8C, 0x80, 0x19, 0xF4, 0x00, 0x0F, 0x0C, 0xD0, 0xE1, 0x6C, 0x4D, 0x6A, 0x29, 0x88, ++0x88, 0xB2, 0x09, 0x04, 0x00, 0xF1, 0xFE, 0x81, 0x32, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x00, 0x2B, 0x40, 0xF0, 0x86, 0x80, ++0x31, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x53, 0x93, 0xF8, 0xC0, 0x24, 0x42, 0xB1, 0x93, 0xF8, 0xC1, 0x34, ++0x2D, 0x4F, 0x03, 0xEB, 0x83, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x07, 0xEB, 0x83, 0x07, 0x63, 0x7F, 0x09, 0x2B, 0x08, 0xD8, ++0xE3, 0x8B, 0x18, 0x07, 0x05, 0xD4, 0x09, 0xF4, 0x01, 0x09, 0xB9, 0xF5, 0x80, 0x3F, 0x00, 0xF0, 0x2B, 0x82, 0x25, 0x4F, ++0x9D, 0xF8, 0x04, 0x50, 0xD7, 0xF8, 0x18, 0x34, 0x00, 0x21, 0x20, 0x46, 0x98, 0x47, 0xD7, 0xF8, 0xAC, 0x33, 0x00, 0x22, ++0x29, 0x46, 0x20, 0x46, 0x98, 0x47, 0x22, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0x00, 0xF0, 0x05, 0x81, 0x63, 0x7F, ++0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x11, 0x49, 0xA0, 0x88, ++0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x12, 0x1A, 0x41, 0xF8, 0x23, 0x20, 0x06, 0xF1, 0x10, 0x01, 0x20, 0x46, ++0xFF, 0xF7, 0x1C, 0xFD, 0xE3, 0x8B, 0xDB, 0x07, 0x00, 0xF1, 0x08, 0x81, 0x21, 0x46, 0x28, 0x46, 0x15, 0xF0, 0xB8, 0xFA, ++0x62, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x24, 0x64, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xB7, 0x4F, 0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, ++0x3F, 0xF4, 0x44, 0xAF, 0x15, 0xF4, 0x00, 0x05, 0x7F, 0xF4, 0x09, 0xAF, 0xB4, 0xF9, 0x1E, 0x30, 0xE2, 0x8B, 0x00, 0x2B, ++0xC0, 0xF2, 0x81, 0x80, 0x00, 0x25, 0x00, 0xE7, 0xAF, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x00, 0x2B, 0x3F, 0xF4, 0x7E, 0xAF, ++0x19, 0xF4, 0x00, 0x0F, 0x3F, 0xF4, 0x7A, 0xAF, 0xE3, 0x8B, 0x1D, 0x07, 0x3F, 0xF5, 0x76, 0xAF, 0x23, 0x7F, 0xA9, 0x4D, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x53, 0x03, 0xF1, 0x98, 0x02, 0x93, 0xF8, 0x62, 0x10, 0x20, 0x46, 0xFF, 0xF7, ++0xAF, 0xFC, 0x68, 0xE7, 0x33, 0x69, 0x03, 0xF0, 0x0F, 0x03, 0x09, 0x2B, 0x7F, 0xF4, 0xCA, 0xAE, 0x03, 0x9B, 0xA0, 0x48, ++0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x00, 0x90, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x3F, 0xF6, 0xBF, 0xAE, 0xE2, 0x6C, ++0xB0, 0xF8, 0x5E, 0x12, 0xD2, 0x6A, 0x8A, 0x42, 0x3F, 0xF4, 0xB8, 0xAE, 0x01, 0x33, 0x80, 0xF8, 0x5D, 0x32, 0xA0, 0xF8, ++0x5E, 0x22, 0xB1, 0xE6, 0x95, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9B, 0x80, 0x59, 0x46, ++0x40, 0x46, 0x04, 0x9A, 0x23, 0xF0, 0xCA, 0xFE, 0x38, 0x46, 0x02, 0xF0, 0x9D, 0xF8, 0x00, 0x23, 0x04, 0x93, 0x9B, 0x46, ++0x98, 0x46, 0x8C, 0xE6, 0xD7, 0xF8, 0xDC, 0x20, 0xDA, 0xB1, 0x11, 0x88, 0x23, 0x8C, 0xA3, 0xEB, 0x11, 0x13, 0xC3, 0xF3, ++0x0B, 0x03, 0x40, 0xF2, 0xFE, 0x71, 0x8B, 0x42, 0x0C, 0xD8, 0x3F, 0x2B, 0x4F, 0xEA, 0x13, 0x11, 0x08, 0xD8, 0x02, 0xEB, ++0x41, 0x02, 0x03, 0xF0, 0x0F, 0x03, 0x52, 0x88, 0x42, 0xFA, 0x03, 0xF3, 0xDA, 0x07, 0x04, 0xD4, 0x4F, 0xF4, 0x80, 0x23, ++0x1D, 0x43, 0x35, 0x61, 0x45, 0xE6, 0x04, 0x9B, 0x01, 0x33, 0x04, 0x93, 0x4F, 0xF4, 0x04, 0x03, 0xF6, 0xE7, 0x75, 0x4F, ++0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0x3F, 0xF4, 0xBF, 0xAE, 0xB4, 0xF9, 0x1E, 0x30, 0xE2, 0x8B, 0x00, 0x2B, 0xBF, 0xF6, ++0x7F, 0xAF, 0x71, 0x4D, 0x02, 0x99, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x53, 0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, ++0x3F, 0xF4, 0x74, 0xAF, 0xE6, 0x6C, 0x01, 0x98, 0x00, 0x21, 0xC2, 0xF3, 0x0E, 0x03, 0x31, 0x65, 0x43, 0xF0, 0x01, 0x03, ++0x61, 0x64, 0x31, 0x61, 0x02, 0x9E, 0xE3, 0x83, 0x9E, 0x30, 0xA4, 0x23, 0x13, 0xFB, 0x06, 0x00, 0xE1, 0x62, 0x61, 0x62, ++0x65, 0x4A, 0x05, 0xEB, 0xC0, 0x00, 0x21, 0x46, 0x13, 0xF0, 0x60, 0xFD, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, ++0x60, 0x1F, 0x00, 0xF0, 0xE4, 0x80, 0x01, 0x23, 0x05, 0x93, 0x8B, 0xE6, 0x05, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0xDC, 0x80, ++0x40, 0x20, 0x13, 0xF0, 0x1F, 0xFC, 0x00, 0x23, 0x05, 0x93, 0x81, 0xE6, 0x40, 0x20, 0x13, 0xF0, 0x19, 0xFC, 0x68, 0xE6, ++0x33, 0x69, 0x03, 0xF0, 0x0F, 0x03, 0x09, 0x2B, 0x7F, 0xF4, 0xF5, 0xAE, 0x03, 0x9B, 0x51, 0x48, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x03, 0x00, 0x90, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x3F, 0xF6, 0xEA, 0xAE, 0xE2, 0x6C, 0xB0, 0xF8, 0x5E, 0x12, ++0xD2, 0x6A, 0x8A, 0x42, 0x3F, 0xF4, 0xE3, 0xAE, 0x01, 0x33, 0x80, 0xF8, 0x5D, 0x32, 0xA0, 0xF8, 0x5E, 0x22, 0xDC, 0xE6, ++0x40, 0x20, 0x13, 0xF0, 0xF7, 0xFB, 0xF3, 0xE6, 0xB8, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0x61, 0xAF, 0x44, 0x49, 0x45, 0x48, ++0x40, 0xF2, 0x3D, 0x22, 0x15, 0xF0, 0xE2, 0xF8, 0x59, 0xE7, 0x00, 0xF0, 0x0C, 0x00, 0x08, 0x28, 0x7F, 0xF4, 0x10, 0xAE, ++0xD7, 0xF8, 0x1A, 0x10, 0x01, 0xF0, 0x3F, 0x01, 0x07, 0x29, 0x7F, 0xF4, 0x09, 0xAE, 0x23, 0xF0, 0x20, 0x03, 0xD3, 0x63, ++0x04, 0xE6, 0x3B, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x06, 0x46, 0x00, 0x28, 0x3F, 0xF4, 0x2C, 0xAE, ++0xF7, 0xF7, 0x96, 0xFE, 0x07, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x02, 0x81, 0x00, 0x22, 0x34, 0x4B, 0x02, 0x60, 0x1B, 0x68, ++0x42, 0x60, 0x1E, 0x44, 0x82, 0x60, 0x06, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x2F, 0x4B, ++0x1D, 0x60, 0x2F, 0x49, 0xD9, 0xF8, 0x00, 0x20, 0x0B, 0x68, 0x01, 0x32, 0x43, 0xF0, 0x01, 0x03, 0xC9, 0xF8, 0x00, 0x20, ++0x0B, 0x60, 0x2A, 0x4B, 0x1B, 0x68, 0x9E, 0x07, 0xFB, 0xD4, 0x29, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xE4, 0x80, ++0x27, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xF0, 0x80, 0x25, 0x4B, 0x25, 0x4D, 0x1F, 0x60, 0x22, 0x48, 0xA9, 0x89, ++0x03, 0x68, 0x6F, 0x60, 0x01, 0x31, 0xA9, 0x81, 0x01, 0x33, 0x1E, 0x49, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, ++0x0B, 0x60, 0x00, 0x2A, 0x3F, 0xF4, 0xEC, 0xAD, 0x18, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, ++0x7F, 0xF4, 0xE4, 0xAD, 0x00, 0x2B, 0x3F, 0xF4, 0xE1, 0xAD, 0x62, 0xB6, 0xDE, 0xE5, 0x23, 0x7F, 0x09, 0x4D, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x03, 0x55, 0x05, 0xF1, 0x98, 0x02, 0x95, 0xF8, 0x62, 0x10, 0x20, 0x46, 0xFF, 0xF7, 0x70, 0xFB, ++0xBE, 0xE5, 0x62, 0xB6, 0x0A, 0xE6, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x61, 0xF1, 0x12, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x90, 0x15, 0x00, ++0x28, 0x60, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0x64, 0x00, 0x24, 0x40, ++0x68, 0x00, 0x24, 0x40, 0x10, 0x60, 0x17, 0x00, 0x00, 0xF0, 0x0C, 0x00, 0x08, 0x28, 0x7F, 0xF4, 0xFD, 0xAD, 0xD5, 0xF8, ++0x1A, 0x10, 0x01, 0xF0, 0x3F, 0x01, 0x07, 0x29, 0x7F, 0xF4, 0xF6, 0xAD, 0x23, 0xF0, 0x20, 0x03, 0xD3, 0x63, 0xF1, 0xE5, ++0x4E, 0x4D, 0x02, 0x9B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x03, 0x50, 0xFE, 0xF7, 0xB8, 0xFE, 0x00, 0x28, 0x3F, 0xF4, ++0x19, 0xAF, 0x4A, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0x13, 0xAF, 0x01, 0x9A, 0x02, 0x99, 0xA4, 0x23, ++0x02, 0xF1, 0x9E, 0x06, 0x13, 0xFB, 0x01, 0x66, 0x03, 0xFB, 0x01, 0x23, 0x03, 0xF1, 0x9E, 0x04, 0x05, 0xEB, 0xC6, 0x06, ++0xD7, 0xB2, 0xA1, 0x46, 0x0C, 0xE0, 0x13, 0xF0, 0x09, 0xFC, 0xDA, 0xF8, 0x24, 0x34, 0x20, 0x46, 0x39, 0x46, 0x98, 0x47, ++0x3B, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0xF6, 0xAE, 0x55, 0xF8, 0x39, 0x40, 0x30, 0x46, 0x00, 0x2C, ++0xED, 0xD1, 0xEF, 0xE6, 0x36, 0x4B, 0x1B, 0x68, 0x1C, 0x42, 0x7F, 0xF4, 0xC3, 0xAC, 0x35, 0x49, 0x35, 0x48, 0x4F, 0xF4, ++0xF2, 0x72, 0x14, 0xF0, 0xFD, 0xFF, 0xBB, 0xE4, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x0A, 0x59, 0x99, 0xF8, 0x64, 0x10, ++0x00, 0x29, 0x3F, 0xF4, 0xCC, 0xAD, 0x2F, 0x48, 0x03, 0x99, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, 0x01, 0x01, 0x91, 0xF8, ++0x24, 0x10, 0x01, 0x29, 0x0F, 0xD0, 0x99, 0x07, 0x2F, 0xD4, 0x00, 0x2A, 0x3F, 0xF4, 0xBD, 0xAD, 0x97, 0xF8, 0x70, 0x30, ++0x01, 0x2B, 0x7F, 0xF4, 0xB8, 0xAD, 0x97, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0xB3, 0xAD, 0xE3, 0x8B, 0xE1, 0x6C, ++0x01, 0x98, 0x22, 0x4A, 0xC3, 0xF3, 0x0E, 0x03, 0x00, 0x26, 0x43, 0xF0, 0x01, 0x03, 0x0E, 0x65, 0x0E, 0x61, 0x9E, 0x30, ++0xE3, 0x83, 0xA4, 0x23, 0x13, 0xFB, 0x0A, 0x00, 0x05, 0xEB, 0xC0, 0x00, 0xE6, 0x62, 0x21, 0x46, 0x13, 0xF0, 0xFE, 0xFB, ++0x40, 0x20, 0x13, 0xF0, 0xCB, 0xFA, 0x2F, 0xE5, 0x30, 0x46, 0xF7, 0xF7, 0x6B, 0xFC, 0x1F, 0xE5, 0x15, 0x4D, 0x6B, 0x68, ++0x9B, 0xB1, 0x5F, 0x60, 0x1E, 0xE7, 0xB4, 0xF8, 0x40, 0x00, 0x20, 0xF0, 0x75, 0xFC, 0x00, 0x28, 0xD6, 0xD0, 0x99, 0xF8, ++0xC0, 0x24, 0x00, 0x2A, 0x3F, 0xF4, 0x85, 0xAD, 0xC6, 0xE7, 0x0E, 0x48, 0x14, 0xF0, 0x2E, 0xFD, 0xD9, 0xF8, 0x00, 0x20, ++0x09, 0xE7, 0x0C, 0x48, 0x14, 0xF0, 0x28, 0xFD, 0xD9, 0xF8, 0x00, 0x20, 0x06, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x61, 0xF1, 0x12, 0x00, 0x10, 0x60, 0x17, 0x00, 0xA8, 0x90, 0x15, 0x00, 0xB0, 0x90, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x27, 0x4F, 0xDF, 0xF8, 0xA0, 0xA0, 0x91, 0x46, 0x06, 0x46, 0x0D, 0x46, 0x42, 0xF0, 0x70, 0x58, 0x28, 0x46, 0x13, 0xF0, ++0x6D, 0xFB, 0x04, 0x46, 0x80, 0xB1, 0x42, 0x6C, 0xC1, 0x6C, 0x00, 0x2A, 0x38, 0xD0, 0xC1, 0xF8, 0x10, 0x80, 0xA2, 0x88, ++0x62, 0xB9, 0x20, 0x46, 0x00, 0xF0, 0xA2, 0xF9, 0x28, 0x46, 0x13, 0xF0, 0x5D, 0xFB, 0x04, 0x46, 0x00, 0x28, 0xEE, 0xD1, ++0xBD, 0xE8, 0xF0, 0x47, 0x00, 0xF0, 0xBC, 0xB9, 0x0A, 0x69, 0x42, 0xF4, 0x00, 0x02, 0x41, 0xF8, 0x10, 0x2F, 0x20, 0x46, ++0xFF, 0xF7, 0x7E, 0xFA, 0xD7, 0xF8, 0x18, 0x34, 0x01, 0x21, 0x20, 0x46, 0x98, 0x47, 0x63, 0x7F, 0x09, 0x2B, 0x0D, 0xD8, ++0xE2, 0x7E, 0x08, 0x2A, 0x0A, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x03, 0xF6, 0x0E, 0x03, 0xA1, 0x88, 0x5A, 0xF8, ++0x23, 0x20, 0x52, 0x1A, 0x4A, 0xF8, 0x23, 0x20, 0x31, 0x46, 0x20, 0x46, 0xD7, 0xF8, 0x78, 0x33, 0x98, 0x47, 0x21, 0x46, ++0x30, 0x46, 0x15, 0xF0, 0x03, 0xF8, 0xBD, 0xE7, 0x0A, 0x69, 0x00, 0x2A, 0xA8, 0xBF, 0xC1, 0xF8, 0x10, 0x90, 0xC2, 0xE7, ++0x88, 0x1A, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x6C, 0x80, 0x92, 0x46, 0x06, 0x46, ++0x0F, 0x46, 0x42, 0xF0, 0x70, 0x59, 0x38, 0x46, 0x13, 0xF0, 0x18, 0xFB, 0x04, 0x46, 0xF0, 0xB1, 0x42, 0x6C, 0xC3, 0x6C, ++0x12, 0xB3, 0xC3, 0xF8, 0x10, 0x90, 0xA2, 0x88, 0x00, 0x21, 0x20, 0x46, 0xCA, 0xB1, 0x1D, 0x69, 0x45, 0xF4, 0x00, 0x05, ++0x1D, 0x61, 0xD8, 0xF8, 0x18, 0x34, 0x98, 0x47, 0xD8, 0xF8, 0x78, 0x33, 0x20, 0x46, 0x31, 0x46, 0x98, 0x47, 0x21, 0x46, ++0x30, 0x46, 0x14, 0xF0, 0xD1, 0xFF, 0x38, 0x46, 0x13, 0xF0, 0xFA, 0xFA, 0x04, 0x46, 0x00, 0x28, 0xE0, 0xD1, 0xBD, 0xE8, ++0xF0, 0x47, 0x00, 0xF0, 0x59, 0xB9, 0x00, 0xF0, 0x33, 0xF9, 0xD4, 0xE7, 0x1A, 0x69, 0x00, 0x2A, 0xA8, 0xBF, 0xC3, 0xF8, ++0x10, 0xA0, 0xD8, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x14, 0x46, 0x05, 0x46, 0x0F, 0x46, 0x60, 0x22, 0x00, 0x21, ++0x1E, 0x46, 0xF0, 0xF7, 0x07, 0xFA, 0x4F, 0xF0, 0x01, 0x0C, 0x85, 0xF8, 0x5C, 0xC0, 0x00, 0x23, 0x07, 0x49, 0x08, 0x4A, ++0xAF, 0x64, 0x07, 0xF1, 0x68, 0x00, 0xEE, 0x62, 0xEC, 0x64, 0xC4, 0xE9, 0x0F, 0x33, 0x60, 0x62, 0x61, 0x61, 0x23, 0x63, ++0x63, 0x64, 0x32, 0x60, 0xF8, 0xBD, 0x00, 0xBF, 0xBE, 0xBA, 0xFE, 0xCA, 0x1E, 0xAB, 0xDC, 0xBA, 0x2D, 0xE9, 0xF8, 0x4F, ++0x07, 0x46, 0x3C, 0x48, 0x3C, 0x4C, 0xDF, 0xF8, 0x08, 0xA1, 0x3C, 0x4E, 0x3C, 0x4D, 0xDF, 0xF8, 0x04, 0xB1, 0x81, 0x46, ++0x13, 0xF0, 0x70, 0xFA, 0x09, 0xF1, 0x08, 0x00, 0x13, 0xF0, 0x6C, 0xFA, 0x04, 0xF5, 0xC0, 0x78, 0x00, 0x21, 0x20, 0x46, ++0x60, 0x22, 0x17, 0xB1, 0x94, 0xF8, 0x5D, 0x30, 0xC3, 0xB9, 0xF0, 0xF7, 0xD1, 0xF9, 0x00, 0x22, 0x32, 0x4B, 0xC4, 0xF8, ++0x48, 0xA0, 0x0A, 0xF1, 0x68, 0x0C, 0xC5, 0xE9, 0x0F, 0x22, 0x21, 0x46, 0x48, 0x46, 0xE6, 0x62, 0xE5, 0x64, 0xC5, 0xF8, ++0x14, 0xB0, 0x33, 0x60, 0x84, 0xF8, 0x5C, 0x20, 0x2A, 0x63, 0x6A, 0x64, 0xC5, 0xF8, 0x24, 0xC0, 0x13, 0xF0, 0x4E, 0xFA, ++0x60, 0x34, 0xA0, 0x45, 0x0A, 0xF5, 0xF4, 0x7A, 0x06, 0xF1, 0x40, 0x06, 0x05, 0xF1, 0x58, 0x05, 0xD6, 0xD1, 0x24, 0x4E, ++0xDF, 0xF8, 0x88, 0x90, 0xC6, 0xF8, 0x00, 0x90, 0x00, 0x24, 0xC6, 0xE9, 0x0D, 0x44, 0xF4, 0x63, 0xF1, 0xF7, 0x8E, 0xFA, ++0x80, 0x03, 0x70, 0x60, 0xF1, 0xF7, 0x8A, 0xFA, 0x01, 0x27, 0x43, 0x1C, 0x07, 0xFA, 0x03, 0xF3, 0x1B, 0x4D, 0xDF, 0xF8, ++0x78, 0x80, 0xF4, 0x60, 0x01, 0x3B, 0xB3, 0x60, 0x4F, 0xF4, 0x80, 0x63, 0xC6, 0xE9, 0x04, 0x83, 0xC6, 0xE9, 0x06, 0x44, ++0x34, 0x62, 0xC5, 0xF8, 0x00, 0x90, 0xC6, 0xE9, 0x0A, 0x44, 0xC5, 0xE9, 0x0D, 0x44, 0x34, 0x63, 0xEC, 0x63, 0xF1, 0xF7, ++0x6F, 0xFA, 0x80, 0x03, 0x68, 0x60, 0xF1, 0xF7, 0x6B, 0xFA, 0x38, 0x44, 0x87, 0x40, 0x01, 0x3F, 0x04, 0x23, 0xC5, 0xE9, ++0x02, 0x74, 0xC5, 0xE9, 0x06, 0x44, 0xC5, 0xE9, 0x0A, 0x44, 0xC5, 0xF8, 0x10, 0x80, 0x2C, 0x62, 0x2C, 0x63, 0x6B, 0x61, ++0xBD, 0xE8, 0xF8, 0x8F, 0x54, 0x64, 0x17, 0x00, 0x90, 0x28, 0x17, 0x00, 0x84, 0x3B, 0x18, 0x00, 0x04, 0x3D, 0x18, 0x00, ++0x1E, 0xAB, 0xDC, 0xBA, 0xC4, 0x3C, 0x18, 0x00, 0x84, 0x3C, 0x18, 0x00, 0x4C, 0x50, 0x18, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, ++0x04, 0x07, 0xFF, 0xFF, 0xF8, 0xB5, 0xD0, 0xE9, 0x12, 0x64, 0x63, 0x6A, 0x05, 0x46, 0x50, 0x1E, 0x03, 0x44, 0x04, 0x32, ++0xC4, 0xE9, 0x0A, 0x32, 0xC1, 0xB1, 0x01, 0x29, 0x1A, 0xD0, 0x06, 0xF1, 0x28, 0x01, 0x0F, 0x46, 0x34, 0x22, 0x38, 0x46, ++0x27, 0xF0, 0xD8, 0xF8, 0x0B, 0x4A, 0x13, 0x68, 0x12, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0x00, 0x22, ++0xF3, 0x64, 0xC4, 0xE9, 0x0D, 0x27, 0xE2, 0x64, 0x22, 0x62, 0xC5, 0xE9, 0x15, 0x22, 0xF8, 0xBD, 0x04, 0x49, 0x06, 0xF1, ++0x28, 0x07, 0xE7, 0xE7, 0x03, 0x49, 0x06, 0xF1, 0x28, 0x07, 0xE3, 0xE7, 0xA0, 0x00, 0x32, 0x40, 0xC4, 0x3C, 0x18, 0x00, ++0x84, 0x3C, 0x18, 0x00, 0x70, 0xB5, 0x05, 0x46, 0x05, 0x48, 0x0E, 0x46, 0x13, 0xF0, 0xFE, 0xF9, 0x04, 0x46, 0x18, 0xB1, ++0x32, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0xC2, 0xFF, 0x20, 0x46, 0x70, 0xBD, 0x54, 0x64, 0x17, 0x00, 0x16, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x2D, 0xE9, 0xF0, 0x41, 0xC4, 0x6C, 0x00, 0x2B, 0x62, 0x6A, 0x05, 0x46, 0x0E, 0x46, 0x16, 0xDB, ++0xE3, 0x6C, 0x11, 0x4F, 0x23, 0xF4, 0xF0, 0x03, 0xE3, 0x64, 0x00, 0x23, 0xC4, 0xE9, 0x06, 0x33, 0x12, 0x79, 0x23, 0x65, ++0x12, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x4F, 0xF4, 0x00, 0x73, 0xA3, 0x64, 0xD7, 0xF8, 0x98, 0x33, 0x31, 0x46, 0x28, 0x46, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xD3, 0x07, 0xE6, 0xD5, 0x4F, 0xF4, 0xB1, 0x72, 0x05, 0x49, 0x05, 0x48, 0x14, 0xF0, ++0xD9, 0xFD, 0x62, 0x6A, 0xDE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xDC, 0x90, 0x15, 0x00, 0x08, 0xB5, 0x01, 0x46, 0x04, 0x48, 0x13, 0xF0, 0x75, 0xF9, 0xBD, 0xE8, 0x08, 0x40, 0x4F, 0xF4, ++0x80, 0x20, 0x13, 0xF0, 0xCD, 0xB8, 0x00, 0xBF, 0x5C, 0x64, 0x17, 0x00, 0x70, 0xB5, 0x90, 0xF8, 0x5C, 0x30, 0x04, 0x46, ++0x0D, 0x46, 0x43, 0xB1, 0x35, 0xB1, 0x63, 0x6D, 0x23, 0xB1, 0xA0, 0x6D, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, ++0x70, 0xBD, 0x01, 0x46, 0x01, 0x48, 0x13, 0xF0, 0x59, 0xF9, 0xF1, 0xE7, 0x54, 0x64, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x4F, 0xF4, 0x80, 0x20, 0x13, 0xF0, 0xD2, 0xF8, 0xDF, 0xF8, 0x88, 0x80, 0x1D, 0x4F, 0x1E, 0x4E, 0x1E, 0x4D, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x30, 0x46, 0x01, 0x33, ++0xC8, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0x80, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0x04, 0x46, 0x33, 0xB1, 0x01, 0x3B, 0x3A, 0x68, ++0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD4, 0xB1, 0xD5, 0xF8, 0xF8, 0x31, 0x62, 0x6D, 0x01, 0x3B, ++0xC5, 0xF8, 0xF8, 0x31, 0x32, 0xB1, 0xE3, 0x6C, 0xA0, 0x6D, 0x19, 0x6D, 0x90, 0x47, 0x94, 0xF8, 0x5E, 0x30, 0x43, 0xB9, ++0x94, 0xF8, 0x5C, 0x30, 0x00, 0x2B, 0xD2, 0xD1, 0x08, 0x48, 0x21, 0x46, 0x13, 0xF0, 0x1A, 0xF9, 0xCD, 0xE7, 0x00, 0x23, ++0x84, 0xF8, 0x5E, 0x30, 0xC9, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x5C, 0x64, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x54, 0x64, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x78, 0x91, ++0x58, 0x4D, 0x80, 0x46, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x08, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x90, 0xF8, 0x22, 0xA0, ++0x03, 0xFB, 0x0A, 0x53, 0x0F, 0x46, 0x1B, 0x6C, 0x16, 0x46, 0x00, 0x2B, 0x00, 0xF0, 0x98, 0x80, 0x50, 0x49, 0x1A, 0x79, ++0x0B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5A, 0xDB, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x53, 0x18, 0x21, ++0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xFF, 0xF7, 0x1E, 0xFF, 0x04, 0x46, 0x00, 0x28, ++0x59, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x55, 0x28, 0x46, 0x21, 0x46, 0x12, 0xF0, 0x11, 0xF8, 0x95, 0xF8, ++0x62, 0x20, 0xA3, 0x6C, 0x02, 0x2A, 0x4F, 0xD0, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x08, 0x92, 0xE8, 0x6D, 0x52, 0xF8, ++0x26, 0x1F, 0xB5, 0xF8, 0x60, 0xC0, 0xB2, 0xF8, 0x04, 0xE0, 0x15, 0x68, 0xD9, 0x66, 0x91, 0x88, 0xA3, 0xF8, 0x7C, 0x10, ++0x00, 0x22, 0x9D, 0x67, 0x01, 0x21, 0x48, 0x25, 0xA3, 0xF8, 0x70, 0xE0, 0xC3, 0xF8, 0x72, 0x00, 0xA3, 0xF8, 0x76, 0xC0, ++0x83, 0xF8, 0x6A, 0x20, 0x83, 0xF8, 0x6B, 0x20, 0x83, 0xF8, 0x68, 0x50, 0x83, 0xF8, 0x69, 0x10, 0x2E, 0x49, 0xB1, 0xF8, ++0xFC, 0x51, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x08, 0x99, 0x01, 0x35, 0xAD, 0xB2, 0xA1, 0xF8, 0xFC, 0x51, 0x99, 0xF8, ++0x22, 0x20, 0x2D, 0x01, 0xA3, 0xF8, 0x7E, 0x50, 0x20, 0x46, 0xC4, 0xE9, 0x15, 0x76, 0x22, 0x77, 0x84, 0xF8, 0x1D, 0x80, ++0x05, 0x21, 0xFF, 0xF7, 0xE3, 0xFE, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x02, 0x2A, 0xA2, 0xD1, 0x20, 0x49, 0x21, 0x48, ++0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0xDC, 0xFC, 0x01, 0x20, 0x18, 0x21, 0xFF, 0xF7, 0xC4, 0xFE, 0x04, 0x46, 0x00, 0x28, ++0xA5, 0xD1, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x08, 0x91, 0xE8, 0x6D, 0x51, 0xF8, ++0x26, 0xEF, 0x83, 0xF8, 0x69, 0x20, 0x89, 0x88, 0xA3, 0xF8, 0x70, 0x10, 0x00, 0x22, 0xB5, 0xF8, 0x60, 0x10, 0xC3, 0xF8, ++0x72, 0x00, 0x4F, 0xF0, 0x48, 0x0C, 0xE8, 0x6D, 0x83, 0xF8, 0x6A, 0x20, 0x83, 0xF8, 0x6B, 0x20, 0xB5, 0xF8, 0x60, 0x20, ++0xC3, 0xF8, 0x6C, 0xE0, 0x83, 0xF8, 0x68, 0xC0, 0xA3, 0xF8, 0x76, 0x10, 0x98, 0x67, 0xA3, 0xF8, 0x7C, 0x20, 0xAD, 0xE7, ++0x04, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCB, 0xDA, 0xC4, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x38, 0xB1, 0x49, 0x4C, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0xB5, 0x06, 0x46, ++0x95, 0xF8, 0x22, 0x70, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x07, 0x40, 0x98, 0x46, 0x00, 0x6C, 0x43, 0x4B, 0x8A, 0x46, ++0x91, 0x46, 0x00, 0x28, 0x7A, 0xD0, 0x1B, 0x68, 0x02, 0x79, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x62, 0xDB, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x07, 0x43, 0x1A, 0x21, 0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, ++0xFF, 0xF7, 0x5C, 0xFE, 0x05, 0x46, 0x00, 0x28, 0x61, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x47, 0x38, 0x46, ++0x29, 0x46, 0x11, 0xF0, 0x4F, 0xFF, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0xB3, 0xAC, 0x6C, 0x53, 0xF8, 0x26, 0x1F, ++0x97, 0xF8, 0x62, 0xC0, 0xB3, 0xF8, 0x04, 0xE0, 0xF8, 0x6D, 0xB7, 0xF8, 0x60, 0x20, 0xA4, 0xF8, 0x76, 0x20, 0x00, 0x23, ++0xA4, 0xF8, 0x70, 0xE0, 0xE1, 0x66, 0xC4, 0xF8, 0x72, 0x00, 0x84, 0xF8, 0x6A, 0x30, 0x84, 0xF8, 0x6B, 0x30, 0xBC, 0xF1, ++0x00, 0x0F, 0x22, 0xD0, 0xF8, 0x6D, 0xA0, 0x67, 0x6F, 0xF0, 0x37, 0x01, 0x02, 0x23, 0xA4, 0xF8, 0x7C, 0x20, 0x84, 0xF8, ++0x68, 0x10, 0x84, 0xF8, 0x69, 0x30, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0xBB, 0x00, 0x27, 0x9B, 0xF8, 0x22, 0x30, ++0xA4, 0xF8, 0x80, 0xA0, 0x84, 0xF8, 0x7E, 0x70, 0x84, 0xF8, 0x7F, 0x70, 0x28, 0x46, 0xC5, 0xE9, 0x15, 0x98, 0x2B, 0x77, ++0x6E, 0x77, 0x05, 0x21, 0xFF, 0xF7, 0x24, 0xFE, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x6F, 0xF0, 0x37, 0x02, 0x01, 0x23, ++0xA1, 0x67, 0xA4, 0xF8, 0x7C, 0xE0, 0x84, 0xF8, 0x68, 0x20, 0x84, 0xF8, 0x69, 0x30, 0xDC, 0xE7, 0x02, 0x2A, 0x9A, 0xD1, ++0x0C, 0x49, 0x0D, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0x12, 0xFC, 0x01, 0x20, 0x1A, 0x21, 0xFF, 0xF7, 0xFA, 0xFD, ++0x05, 0x46, 0x00, 0x28, 0x9D, 0xD1, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xF0, 0xDA, 0xE9, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x9C, 0xA1, 0xDF, 0xF8, 0x9C, 0x81, 0x4F, 0xF4, 0x1E, 0x76, ++0x06, 0xFB, 0x00, 0xA6, 0x05, 0x46, 0x96, 0xF8, 0x22, 0x90, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x09, 0x80, 0x83, 0xB0, ++0x00, 0x6C, 0x00, 0x93, 0x0E, 0x1E, 0x17, 0x46, 0x9D, 0xF8, 0x30, 0x40, 0x9D, 0xF8, 0x34, 0xB0, 0x55, 0x4A, 0x0C, 0xBF, ++0x1E, 0x23, 0x1D, 0x23, 0x00, 0x28, 0x00, 0xF0, 0x9D, 0x80, 0x12, 0x68, 0x01, 0x79, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, ++0xC0, 0xF2, 0x85, 0x80, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x82, 0x92, 0xF8, 0xC0, 0x24, 0x0A, 0x43, 0x14, 0xBF, ++0x01, 0x20, 0x00, 0x20, 0x19, 0x46, 0xFF, 0xF7, 0xAF, 0xFD, 0x03, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x81, 0x80, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x09, 0x88, 0xD0, 0xF8, 0x48, 0x90, 0x01, 0x93, 0x40, 0x46, 0x19, 0x46, 0x11, 0xF0, 0x9E, 0xFE, ++0xD9, 0xF8, 0x38, 0x00, 0x01, 0x9B, 0x40, 0x4A, 0x99, 0x6C, 0xB8, 0xF8, 0x60, 0xE0, 0x00, 0x0C, 0x4F, 0xF0, 0x00, 0x0C, ++0x46, 0xEA, 0x07, 0x17, 0x00, 0x04, 0xC9, 0xF8, 0x38, 0x00, 0xD8, 0xF8, 0x5C, 0x00, 0x8F, 0x67, 0x81, 0xF8, 0x7C, 0xC0, ++0x81, 0xF8, 0x7D, 0xC0, 0x81, 0xF8, 0x7E, 0xC0, 0x81, 0xF8, 0x7F, 0xC0, 0x92, 0xF8, 0x43, 0x70, 0xDF, 0xF8, 0xE8, 0x80, ++0xC1, 0xF8, 0x72, 0x00, 0x24, 0x20, 0xB8, 0xF8, 0x04, 0x20, 0xA1, 0xF8, 0x76, 0xE0, 0x81, 0xF8, 0x68, 0x00, 0xD8, 0xF8, ++0x00, 0xE0, 0xA1, 0xF8, 0x70, 0x20, 0xB8, 0x06, 0xC1, 0xF8, 0x6C, 0xE0, 0x81, 0xF8, 0x69, 0xC0, 0x81, 0xF8, 0x6A, 0xC0, ++0x81, 0xF8, 0x6B, 0xC0, 0xC7, 0xF3, 0x40, 0x12, 0x0B, 0xD5, 0x27, 0x48, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x05, 0x02, ++0x52, 0x78, 0x12, 0xF0, 0x20, 0x0F, 0x0C, 0xBF, 0x62, 0x46, 0x4F, 0xF4, 0x80, 0x12, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x05, 0xA5, 0x64, 0x05, 0x28, 0x8C, 0x00, 0x9D, 0x44, 0xEA, 0x45, 0x34, 0x04, 0x43, 0x14, 0x43, 0xD8, 0x22, 0xC1, 0xF8, ++0x80, 0x40, 0x81, 0xF8, 0x84, 0x20, 0x6E, 0xB1, 0x0E, 0x9A, 0x5A, 0x65, 0x0F, 0x9A, 0x9A, 0x65, 0x59, 0x46, 0x18, 0x46, ++0xFF, 0xF7, 0x54, 0xFD, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x4A, 0x12, 0xF8, ++0x0B, 0x20, 0x92, 0x01, 0x81, 0xF8, 0x85, 0x20, 0xEA, 0xE7, 0x02, 0x29, 0x7F, 0xF4, 0x78, 0xAF, 0x0E, 0x48, 0x0F, 0x49, ++0x01, 0x93, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0x41, 0xFB, 0x01, 0x9B, 0x01, 0x20, 0x77, 0xE7, 0x01, 0x20, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xEC, 0xDB, 0x01, 0x20, 0x6C, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x62, 0x66, 0x17, 0x00, 0xA0, 0xB2, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xAC, 0xB2, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0x90, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x77, 0xD1, 0x03, 0x6C, 0x04, 0x46, 0x89, 0x46, 0x00, 0x2B, 0x79, 0xD0, 0x40, 0x4A, ++0x1B, 0x79, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x51, 0xDB, 0x94, 0xF8, 0xC0, 0x24, 0xDF, 0xF8, 0x08, 0x81, ++0x13, 0x43, 0xB8, 0xF8, 0x00, 0x10, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xFF, 0xF7, 0xEE, 0xFC, 0x06, 0x46, 0x00, 0x28, ++0x54, 0xD0, 0x01, 0x46, 0x20, 0x46, 0x11, 0xF0, 0xE5, 0xFD, 0xB5, 0x6C, 0x00, 0x27, 0x50, 0x23, 0x49, 0x46, 0x85, 0xF8, ++0x68, 0x30, 0x85, 0xF8, 0x69, 0x70, 0x85, 0xF8, 0x6A, 0x70, 0x85, 0xF8, 0x6B, 0x70, 0x05, 0xF1, 0x6C, 0x00, 0x06, 0x22, ++0x26, 0xF0, 0x90, 0xFD, 0x2B, 0x49, 0xE0, 0x6D, 0xB1, 0xF8, 0xFC, 0x31, 0xB4, 0xF8, 0x60, 0xC0, 0xB8, 0xF8, 0x00, 0x20, ++0xB4, 0xF8, 0x60, 0xE0, 0xC5, 0xF8, 0x72, 0x00, 0x01, 0x33, 0x9B, 0xB2, 0xE0, 0x6D, 0xA5, 0xF8, 0x76, 0xC0, 0x4F, 0xEA, ++0x03, 0x1C, 0xA8, 0x67, 0xA5, 0xF8, 0x7C, 0xE0, 0x18, 0x3A, 0xA1, 0xF8, 0xFC, 0x31, 0x05, 0xF1, 0x80, 0x00, 0xA5, 0xF8, ++0x7E, 0xC0, 0x1E, 0x49, 0x26, 0xF0, 0x70, 0xFD, 0xC6, 0xE9, 0x15, 0x77, 0x94, 0xF8, 0x63, 0x30, 0x33, 0x77, 0xFF, 0x23, ++0x73, 0x77, 0x30, 0x46, 0x05, 0x21, 0xFF, 0xF7, 0xBB, 0xFC, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x2B, 0xAB, 0xD1, ++0x15, 0x49, 0x16, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0xB4, 0xFA, 0xDF, 0xF8, 0x58, 0x80, 0x01, 0x20, 0xB8, 0xF8, ++0x00, 0x10, 0xFF, 0xF7, 0x99, 0xFC, 0x06, 0x46, 0x00, 0x28, 0xAA, 0xD1, 0xB8, 0xF8, 0x00, 0x10, 0x0E, 0x48, 0x14, 0xF0, ++0x2B, 0xF8, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x48, 0x19, 0x46, 0x14, 0xF0, 0x24, 0xF8, 0x01, 0x20, 0xBD, 0xE8, ++0xF8, 0x83, 0x03, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE0, 0xDA, 0xD9, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x2C, 0x2A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0x28, 0x91, 0x15, 0x00, ++0x14, 0x91, 0x15, 0x00, 0x14, 0x2C, 0x17, 0x00, 0x02, 0x4B, 0x40, 0xEA, 0x41, 0x01, 0x33, 0xF8, 0x11, 0x00, 0x70, 0x47, ++0xA0, 0x92, 0x15, 0x00, 0x02, 0x4B, 0x40, 0xEA, 0x41, 0x01, 0x58, 0x5C, 0x70, 0x47, 0x00, 0xBF, 0x40, 0x93, 0x15, 0x00, ++0xF0, 0xB4, 0x1D, 0x4C, 0x1D, 0x4D, 0x1E, 0x4F, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x02, 0x42, 0x16, 0x46, 0x92, 0xF8, ++0x22, 0x40, 0x4F, 0xF4, 0xA4, 0x6C, 0x0C, 0xFB, 0x04, 0x54, 0x56, 0xF8, 0x26, 0x5F, 0xB4, 0xF8, 0x60, 0xC0, 0x02, 0x46, ++0xE0, 0x6D, 0xB4, 0x88, 0xA2, 0xF8, 0x9C, 0x40, 0x00, 0x24, 0x54, 0x65, 0xC2, 0xF8, 0x8C, 0x40, 0x3C, 0x68, 0x3E, 0x68, ++0x9D, 0xF8, 0x10, 0x70, 0xC2, 0xF8, 0x9E, 0x00, 0x24, 0x02, 0xF6, 0xB2, 0x1B, 0x03, 0xA4, 0xB2, 0x40, 0xF6, 0x08, 0x00, ++0x34, 0x43, 0x40, 0xEA, 0xC7, 0x10, 0x43, 0xF0, 0x04, 0x03, 0x09, 0x01, 0xC2, 0xF8, 0x98, 0x50, 0xC2, 0xF8, 0xCC, 0x40, ++0xA2, 0xF8, 0xA2, 0xC0, 0xF0, 0xBC, 0xA2, 0xF8, 0xA4, 0x30, 0xA2, 0xF8, 0xA6, 0x10, 0xC2, 0xF8, 0xBC, 0x00, 0x70, 0x47, ++0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0xC2, 0x6C, 0x53, 0x6A, 0x13, 0xB3, 0x12, 0x49, ++0x12, 0x4B, 0xC9, 0x6E, 0x10, 0xB5, 0x04, 0x46, 0x18, 0x68, 0x63, 0x6A, 0x92, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, ++0x60, 0x1F, 0x42, 0xF8, 0x03, 0x1C, 0x08, 0xD0, 0xB0, 0xF9, 0x00, 0x30, 0x24, 0x68, 0x00, 0x2B, 0x04, 0xDB, 0xE2, 0x6C, ++0x53, 0x6A, 0x00, 0x2B, 0xED, 0xD1, 0x10, 0xBD, 0x00, 0x2C, 0xF8, 0xD1, 0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xF9, 0x22, ++0x14, 0xF0, 0x0E, 0xFA, 0xE3, 0x6C, 0xFF, 0xDE, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x04, 0x46, 0x9D, 0xF8, 0x48, 0x00, ++0x67, 0x6C, 0x07, 0x90, 0x9B, 0x46, 0x05, 0x28, 0x4F, 0xF0, 0x00, 0x03, 0x06, 0x91, 0x03, 0x92, 0x9A, 0x46, 0x00, 0xF0, ++0x12, 0x81, 0xAA, 0x4A, 0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x04, 0x93, 0xDF, 0xF8, ++0xC8, 0x92, 0xA6, 0x48, 0x12, 0xF0, 0xD4, 0xFD, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, ++0xC0, 0xF2, 0xF3, 0x80, 0xBB, 0x88, 0xAB, 0x80, 0x7B, 0x7A, 0x6B, 0x72, 0xBB, 0x7A, 0xAB, 0x72, 0x01, 0x23, 0xEB, 0x72, ++0xD7, 0xE9, 0x10, 0xC0, 0xFE, 0x6A, 0x79, 0x69, 0x3A, 0x6B, 0xEE, 0x62, 0x00, 0x23, 0x1E, 0x46, 0x69, 0x61, 0x6B, 0x62, ++0x19, 0x46, 0x98, 0x46, 0x02, 0x93, 0x05, 0xF1, 0x0C, 0x03, 0xC5, 0xE9, 0x10, 0xC0, 0x2A, 0x63, 0x05, 0x93, 0x01, 0x96, ++0x53, 0xE0, 0x9B, 0x45, 0x40, 0xF2, 0xB4, 0x80, 0xAB, 0xEB, 0x03, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x0A, 0xF1, 0x03, 0x0A, ++0x4F, 0xEA, 0x9A, 0x0A, 0x03, 0xEB, 0x8A, 0x03, 0x9B, 0xB2, 0x03, 0x9E, 0x19, 0x44, 0xB1, 0x42, 0x5A, 0xD8, 0xB8, 0xF1, ++0x00, 0x0F, 0x57, 0xD1, 0xDE, 0xF8, 0x24, 0x00, 0x28, 0xB1, 0x87, 0x4E, 0xDE, 0xF8, 0x28, 0x00, 0xF6, 0x6E, 0x40, 0xF8, ++0x03, 0x6C, 0xDC, 0x45, 0x65, 0x64, 0x0D, 0xD2, 0xDE, 0xF8, 0x4C, 0x20, 0x22, 0xF4, 0xFF, 0x22, 0x22, 0xF4, 0xC0, 0x62, ++0x42, 0xEA, 0x4A, 0x22, 0x42, 0xF4, 0x80, 0x70, 0x62, 0x62, 0x63, 0x46, 0xCE, 0xF8, 0x4C, 0x00, 0x69, 0x62, 0x79, 0x6A, ++0x02, 0xF4, 0x60, 0x12, 0xCB, 0x1A, 0xB2, 0xF5, 0x60, 0x1F, 0x7B, 0x62, 0x00, 0xF0, 0xAA, 0x80, 0x77, 0x4A, 0xD9, 0xF8, ++0x00, 0x30, 0x11, 0x68, 0x76, 0x4A, 0x91, 0xF8, 0x3E, 0x80, 0x12, 0x68, 0xB3, 0xF9, 0x00, 0x10, 0x23, 0x68, 0x02, 0xF0, ++0x3F, 0x02, 0x90, 0x45, 0x94, 0xBF, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x01, 0x08, 0x00, 0x29, 0x5D, 0xDB, 0x01, 0x9A, ++0x69, 0x6A, 0x02, 0x94, 0x01, 0x32, 0x01, 0x92, 0x1C, 0x46, 0xD4, 0xF8, 0x4C, 0xE0, 0x62, 0x6A, 0xDE, 0xF8, 0x2C, 0x30, ++0x9D, 0xF8, 0x04, 0x00, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0xC2, 0xF3, 0x49, 0x2C, 0x03, 0xEB, ++0x8C, 0x0C, 0x1F, 0xFA, 0x8C, 0xFC, 0xDC, 0x45, 0x97, 0xD3, 0x03, 0x9E, 0x63, 0x46, 0x19, 0x44, 0xB1, 0x42, 0xA4, 0xD9, ++0x02, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0xA2, 0x80, 0x02, 0x9B, 0x5B, 0x6A, 0x03, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x20, 0x1F, ++0x41, 0xD0, 0x02, 0x9E, 0xF2, 0x6C, 0x43, 0xF4, 0x60, 0x11, 0x43, 0xF4, 0x60, 0x13, 0x50, 0x73, 0xC5, 0xF8, 0x38, 0x61, ++0x73, 0x62, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x41, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x00, 0x2B, 0xD1, 0x64, ++0xD0, 0x61, 0x3D, 0xDB, 0x04, 0x9A, 0x92, 0xF8, 0x50, 0x30, 0x01, 0x33, 0x82, 0xF8, 0x50, 0x30, 0x63, 0x6A, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x60, 0x1F, 0x73, 0xD0, 0x1C, 0x32, 0x16, 0x46, 0x48, 0x4B, 0x06, 0x9A, 0x1B, 0x68, 0x14, 0x60, ++0x5B, 0x78, 0x13, 0xB9, 0x63, 0x6C, 0x0C, 0x33, 0x2B, 0x61, 0x29, 0x46, 0x30, 0x46, 0x12, 0xF0, 0xE7, 0xFC, 0x05, 0x98, ++0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2B, 0x9F, 0xD1, 0x40, 0x49, 0x40, 0x48, 0x02, 0x93, 0x40, 0xF2, 0xBD, 0x32, ++0x14, 0xF0, 0x0A, 0xF9, 0x02, 0x9B, 0x96, 0xE7, 0x4F, 0xF0, 0x00, 0x0A, 0x53, 0xE7, 0x02, 0x9E, 0x3B, 0x4B, 0x01, 0x21, ++0xD3, 0xF8, 0x58, 0x33, 0x30, 0x46, 0x98, 0x47, 0xF3, 0x6C, 0x75, 0x64, 0x14, 0x33, 0x05, 0x93, 0xD9, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC1, 0xDA, 0x04, 0x9B, 0xDB, 0x69, 0x9F, 0x42, 0xBD, 0xD0, 0x2F, 0x49, 0x32, 0x48, ++0x40, 0xF2, 0xC3, 0x32, 0x14, 0xF0, 0xEA, 0xF8, 0xB6, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0x0A, 0xAF, 0x2A, 0x49, 0x2E, 0x48, ++0x40, 0xF2, 0x27, 0x32, 0x14, 0xF0, 0xE0, 0xF8, 0x02, 0xE7, 0x2C, 0x4B, 0x04, 0x93, 0xF2, 0xE6, 0xD9, 0xF8, 0x00, 0x30, ++0xC5, 0xF8, 0x38, 0x41, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x16, 0xDB, 0x04, 0x9E, 0x1C, 0x36, 0x30, 0x46, 0x12, 0xF0, ++0xBF, 0xFC, 0x1E, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0x0B, 0xB9, 0x3B, 0x69, 0x2B, 0x61, 0x39, 0x46, 0xD7, 0xF8, 0x48, 0x01, ++0x12, 0xF0, 0x70, 0xFC, 0x06, 0x99, 0x22, 0x68, 0xE3, 0x6C, 0x0A, 0x60, 0x00, 0x22, 0xDA, 0x61, 0xA1, 0xE7, 0x04, 0x9B, ++0xDB, 0x69, 0xBB, 0x42, 0xE4, 0xD0, 0x14, 0x49, 0x16, 0x48, 0x40, 0xF2, 0xC3, 0x32, 0x14, 0xF0, 0xB3, 0xF8, 0xDD, 0xE7, ++0x04, 0x9E, 0x1C, 0x36, 0x30, 0x46, 0x12, 0xF0, 0x9D, 0xFC, 0x87, 0xE7, 0x0F, 0x4B, 0x07, 0x99, 0xD3, 0xF8, 0xBC, 0x33, ++0x07, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0x02, 0x9B, 0xD5, 0xF8, 0x48, 0x01, 0x05, 0x93, 0x29, 0x46, 0x12, 0xF0, 0x4A, 0xFC, ++0x85, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x8C, 0x64, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, ++0x54, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x64, 0x91, 0x15, 0x00, 0x4C, 0x91, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x0C, 0x46, 0x41, 0x7F, 0x63, 0x7F, 0x99, 0x42, 0x85, 0xB0, 0x05, 0xD1, 0xE3, 0x7E, 0x16, 0x46, 0xC2, 0x7E, 0x9A, 0x42, ++0x05, 0x46, 0x03, 0xD0, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD4, 0xE9, 0x11, 0x73, 0x00, 0x2B, 0x00, 0xF0, ++0x8F, 0x80, 0xBB, 0x88, 0x13, 0xF0, 0x08, 0x00, 0xF3, 0xD0, 0x13, 0xF0, 0x02, 0x00, 0xF0, 0xD0, 0x13, 0xF0, 0x01, 0x00, ++0x40, 0xF0, 0x86, 0x80, 0xDF, 0xF8, 0x4C, 0x91, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x93, 0x93, 0xF8, 0x4D, 0x20, 0x01, 0x2A, ++0xE3, 0xD0, 0xD3, 0xF8, 0x34, 0x80, 0xD8, 0xE9, 0x12, 0xBA, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0xDA, 0xF8, 0x20, 0x20, ++0x46, 0x4B, 0x12, 0x68, 0x9A, 0x42, 0xD6, 0xD1, 0x45, 0x4A, 0x46, 0x4B, 0x11, 0x68, 0x1A, 0x68, 0x91, 0xF8, 0x3E, 0x30, ++0x91, 0xF8, 0x3F, 0x10, 0x02, 0xF0, 0x3F, 0x02, 0x0B, 0x44, 0x9A, 0x42, 0xC8, 0xDD, 0xD8, 0xF8, 0x24, 0x20, 0x54, 0x23, ++0x03, 0xFB, 0x06, 0x93, 0x42, 0xF4, 0x60, 0x12, 0x18, 0x6B, 0xC8, 0xF8, 0x24, 0x20, 0xC7, 0xF8, 0x38, 0x81, 0x03, 0x93, ++0x03, 0xF0, 0xE0, 0xF8, 0x39, 0x4A, 0x03, 0x9B, 0x12, 0x68, 0x93, 0xF8, 0x4D, 0x10, 0x8A, 0xF8, 0x0D, 0x10, 0x52, 0x78, ++0x00, 0x2A, 0x4F, 0xD1, 0xEB, 0x6C, 0x3A, 0x61, 0xD9, 0x6C, 0xCA, 0xE9, 0x06, 0x22, 0x8A, 0x02, 0x44, 0xD5, 0x6B, 0x6C, ++0x07, 0xF1, 0x0C, 0x01, 0x19, 0x61, 0x54, 0x23, 0x03, 0xFB, 0x06, 0xF3, 0x0A, 0xF1, 0x14, 0x00, 0x09, 0xEB, 0x03, 0x02, ++0x49, 0xF8, 0x03, 0x00, 0x01, 0x23, 0xC2, 0xE9, 0x01, 0x13, 0xD8, 0xF8, 0x24, 0x30, 0xBA, 0x88, 0x43, 0xF4, 0x80, 0x73, ++0xCA, 0xF8, 0x4C, 0x30, 0x42, 0xF0, 0x01, 0x03, 0xBB, 0x80, 0xBB, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x50, 0x07, 0x06, 0xD4, ++0x11, 0x07, 0x37, 0xD4, 0xA1, 0x6C, 0x4A, 0x6A, 0x42, 0xF0, 0x04, 0x02, 0x4A, 0x62, 0x9B, 0x07, 0x06, 0xD5, 0x54, 0x23, ++0x03, 0xFB, 0x06, 0x93, 0x3A, 0x6B, 0x1B, 0x6B, 0x9B, 0x6A, 0x53, 0x61, 0x54, 0x24, 0x04, 0xFB, 0x06, 0x90, 0x04, 0xFB, ++0x06, 0x96, 0x1C, 0x30, 0x39, 0x46, 0x12, 0xF0, 0x91, 0xFB, 0x96, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x33, 0xF2, 0x62, ++0x86, 0xF8, 0x50, 0x30, 0x01, 0x20, 0x68, 0xE7, 0xBB, 0x88, 0x72, 0xE7, 0x01, 0x20, 0x64, 0xE7, 0x07, 0xF1, 0x0C, 0x01, ++0x99, 0x61, 0xBA, 0xE7, 0xB8, 0x7A, 0x93, 0xF8, 0x4E, 0x30, 0x7A, 0x7A, 0xB8, 0xF8, 0x22, 0x10, 0x00, 0x93, 0x03, 0x46, ++0x38, 0x46, 0xFF, 0xF7, 0x55, 0xFD, 0x07, 0xF1, 0x50, 0x03, 0xCA, 0xF8, 0x1C, 0x30, 0xB6, 0xE7, 0x42, 0xF0, 0x03, 0x03, ++0xBB, 0x80, 0xC8, 0xE7, 0xDE, 0xFA, 0xFE, 0xCA, 0xC8, 0x35, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x45, 0x6C, 0x0C, 0x68, 0x6E, 0x7A, 0x60, 0x7F, 0x9D, 0xF8, 0x20, 0x70, ++0x86, 0x42, 0x03, 0xD1, 0xAE, 0x7A, 0xE0, 0x7E, 0x86, 0x42, 0x02, 0xD0, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xE6, 0x6C, ++0xD5, 0xF8, 0x38, 0xE1, 0xD6, 0xF8, 0x24, 0xC0, 0xDE, 0xF8, 0x4C, 0x80, 0xBC, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x82, 0x80, ++0xBC, 0xF8, 0x00, 0x90, 0x19, 0xF4, 0x00, 0x4F, 0x1F, 0xFA, 0x89, 0xF0, 0x7A, 0xD1, 0x6F, 0xEA, 0x40, 0x40, 0x6F, 0xEA, ++0x50, 0x40, 0xAC, 0xF8, 0x00, 0x00, 0x94, 0xF8, 0x33, 0x90, 0x94, 0xF8, 0x32, 0x00, 0x09, 0xF1, 0x04, 0x09, 0x04, 0x30, ++0x84, 0xF8, 0x33, 0x90, 0x84, 0xF8, 0x32, 0x00, 0xF0, 0x6A, 0x00, 0xF1, 0x04, 0x0A, 0xB0, 0x6A, 0x00, 0xF1, 0x04, 0x09, ++0xC6, 0xE9, 0x0A, 0x9A, 0x0A, 0xF1, 0x03, 0x00, 0x20, 0xF0, 0x03, 0x00, 0x04, 0x30, 0x80, 0xB2, 0x83, 0x42, 0x5C, 0xD9, ++0xA3, 0xEB, 0x00, 0x09, 0x1F, 0xFA, 0x89, 0xF9, 0x09, 0xF1, 0x03, 0x09, 0x4F, 0xEA, 0x99, 0x09, 0x00, 0xEB, 0x89, 0x00, ++0x80, 0xB2, 0x6B, 0x6A, 0x18, 0x44, 0x90, 0x42, 0xBA, 0xD8, 0x28, 0x4A, 0xDE, 0xF8, 0x24, 0x30, 0x4F, 0xF0, 0x54, 0x0A, ++0x0A, 0xFB, 0x07, 0x27, 0x23, 0xF4, 0xC0, 0x13, 0x97, 0xF8, 0x50, 0x20, 0xDF, 0xF8, 0x90, 0xA0, 0x01, 0x3A, 0x87, 0xF8, ++0x50, 0x20, 0x43, 0xF4, 0x40, 0x12, 0xCE, 0xF8, 0x24, 0x20, 0x62, 0x6A, 0xDA, 0xF8, 0x00, 0x70, 0xD4, 0xF8, 0x00, 0xE0, ++0x22, 0xF4, 0xC0, 0x12, 0x42, 0xEA, 0x49, 0x29, 0x43, 0xF4, 0x40, 0x13, 0x49, 0xF4, 0xF0, 0x0A, 0x43, 0xF4, 0x80, 0x73, ++0xC8, 0xF8, 0x4C, 0x30, 0x49, 0xF4, 0xF0, 0x02, 0x00, 0x23, 0x4A, 0xF4, 0x80, 0x7A, 0x06, 0xF1, 0x14, 0x09, 0xC8, 0xF8, ++0x1C, 0x90, 0x62, 0x62, 0xC6, 0xF8, 0x4C, 0xA0, 0xB3, 0x61, 0xB3, 0x63, 0x68, 0x62, 0x65, 0x64, 0xC5, 0xF8, 0x38, 0x41, ++0xC1, 0xF8, 0x00, 0xE0, 0x7B, 0x78, 0x03, 0xB9, 0x2B, 0x61, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0x09, 0x4A, 0xB3, 0x6A, ++0xD2, 0x6E, 0x43, 0xF8, 0x03, 0x2C, 0x98, 0xF8, 0x0D, 0x30, 0x01, 0x33, 0x73, 0x73, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, ++0xD6, 0xF8, 0x2C, 0xA0, 0x9A, 0xE7, 0x4F, 0xF0, 0x00, 0x09, 0xAA, 0xE7, 0x20, 0x62, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x85, 0xB0, 0xD1, 0xF8, 0x00, 0xB0, 0x9D, 0xF8, 0x38, 0x90, 0xDF, 0xF8, ++0x20, 0xA1, 0xDB, 0xF8, 0x44, 0x60, 0xDA, 0xF8, 0x60, 0x43, 0x03, 0x93, 0x0F, 0x46, 0x90, 0x46, 0x59, 0x46, 0x4A, 0x46, ++0x05, 0x46, 0xA0, 0x47, 0x00, 0x28, 0x60, 0xD0, 0xE9, 0x6C, 0x03, 0x9B, 0xCA, 0x6A, 0x02, 0xF1, 0x03, 0x0E, 0x2E, 0xF0, ++0x03, 0x0E, 0x0E, 0xF1, 0x04, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0x73, 0x45, 0x01, 0xF1, 0x14, 0x0C, 0x54, 0xD8, 0x00, 0x20, ++0x72, 0x6A, 0x0E, 0xEB, 0x02, 0x03, 0x43, 0x45, 0x05, 0xD9, 0x34, 0x4A, 0x12, 0x68, 0x02, 0xF0, 0x3F, 0x02, 0x11, 0x2A, ++0x5D, 0xD9, 0x32, 0x4A, 0x6C, 0x6A, 0x4F, 0xF0, 0x54, 0x0E, 0x0E, 0xFB, 0x09, 0x22, 0x24, 0xF4, 0xC0, 0x14, 0x92, 0xF8, ++0x50, 0xE0, 0x44, 0xEA, 0x40, 0x24, 0x0E, 0xF1, 0xFF, 0x30, 0x82, 0xF8, 0x50, 0x00, 0x44, 0xF4, 0xD0, 0x0E, 0x72, 0x69, ++0xCA, 0x61, 0xC6, 0xF8, 0x14, 0xC0, 0x73, 0x62, 0xC5, 0xF8, 0x24, 0xE0, 0xDB, 0xF8, 0x24, 0x20, 0xD6, 0xF8, 0x38, 0xC1, ++0x6E, 0x64, 0x22, 0xF4, 0xC0, 0x12, 0x74, 0x46, 0x42, 0xF4, 0x40, 0x10, 0xDB, 0xF8, 0x4C, 0xE0, 0xDC, 0xF8, 0x4C, 0xC0, ++0x44, 0xF4, 0x80, 0x74, 0xCC, 0x64, 0x42, 0xF4, 0x40, 0x12, 0x40, 0xF4, 0x80, 0x70, 0x00, 0x24, 0x8C, 0x63, 0xCB, 0xF8, ++0x24, 0x20, 0xCE, 0xF8, 0x4C, 0x00, 0x9C, 0xF8, 0x0D, 0x20, 0x43, 0x45, 0x02, 0xF1, 0x01, 0x02, 0x8C, 0xF8, 0x0D, 0x20, ++0x16, 0xD9, 0xDA, 0xF8, 0x70, 0x63, 0x03, 0x9B, 0xCD, 0xF8, 0x00, 0x90, 0x42, 0x46, 0x39, 0x46, 0x28, 0x46, 0xB0, 0x47, ++0x20, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA3, 0xEB, 0x0E, 0x04, 0xA4, 0xB2, 0x03, 0x34, 0xA0, 0x08, 0x0E, 0xEB, ++0x80, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xA1, 0xE7, 0x58, 0x46, 0xFF, 0xF7, 0x53, 0xFC, 0xD6, 0xF8, 0x38, 0x31, 0x1B, 0x68, ++0x3B, 0x60, 0x01, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, ++0x54, 0x83, 0x32, 0x40, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, ++0x05, 0x46, 0x89, 0xB0, 0x6E, 0x6C, 0x9D, 0xF8, 0x50, 0x40, 0x04, 0x91, 0x0F, 0x46, 0x1C, 0x20, 0x54, 0x21, 0x11, 0xFB, ++0x04, 0x01, 0xD6, 0xF8, 0x38, 0x01, 0x06, 0x90, 0xAB, 0x48, 0x05, 0x94, 0x41, 0x18, 0x3C, 0x68, 0x01, 0x92, 0x08, 0x46, ++0x08, 0xEE, 0x10, 0x1A, 0x07, 0x93, 0xD4, 0xF8, 0x44, 0x80, 0xD4, 0xF8, 0x4C, 0x90, 0x12, 0xF0, 0x41, 0xFA, 0xA5, 0x4B, ++0x05, 0x9A, 0xD3, 0xF8, 0x60, 0x33, 0x28, 0x46, 0x21, 0x46, 0x98, 0x47, 0x00, 0x23, 0x02, 0x93, 0x00, 0x28, 0x00, 0xF0, ++0xF8, 0x80, 0xDF, 0xF8, 0x98, 0xA2, 0x9F, 0x48, 0xDA, 0xF8, 0x00, 0x20, 0x03, 0x68, 0x92, 0xF8, 0x3E, 0x20, 0x03, 0xF0, ++0x3F, 0x03, 0x9A, 0x42, 0x00, 0xF2, 0xFD, 0x80, 0x06, 0x9A, 0x04, 0x9D, 0x53, 0x6A, 0x2D, 0x68, 0x03, 0x90, 0x17, 0x46, ++0x23, 0xF4, 0xC0, 0x13, 0xD2, 0x6C, 0x43, 0xF4, 0x40, 0x11, 0x09, 0xF1, 0x14, 0x0C, 0x92, 0xF8, 0x0D, 0xB0, 0xC2, 0xF8, ++0x1C, 0xC0, 0x79, 0x62, 0x61, 0x6A, 0x07, 0x9F, 0x43, 0xF4, 0x40, 0x13, 0x21, 0xF4, 0xC0, 0x11, 0x43, 0xF4, 0x80, 0x73, ++0x41, 0xF4, 0x40, 0x11, 0xD3, 0x64, 0x61, 0x62, 0x6B, 0x6A, 0x43, 0xF4, 0x80, 0x73, 0xC9, 0xF8, 0x4C, 0x30, 0x02, 0x9B, ++0x99, 0x46, 0x4C, 0xE0, 0x9F, 0x42, 0x40, 0xF2, 0x93, 0x80, 0xFA, 0x1A, 0x92, 0xB2, 0x03, 0x32, 0x4F, 0xEA, 0x92, 0x09, ++0x03, 0xEB, 0x89, 0x03, 0x9B, 0xB2, 0x72, 0x6A, 0x01, 0x98, 0x1A, 0x44, 0x82, 0x42, 0x53, 0xD8, 0x03, 0x9D, 0xDA, 0xF8, ++0x00, 0x00, 0x2D, 0x68, 0x90, 0xF8, 0x3E, 0x00, 0x05, 0xF0, 0x3F, 0x05, 0xA8, 0x42, 0x49, 0xD8, 0xDC, 0xF8, 0x24, 0x00, ++0x28, 0xB1, 0x79, 0x4D, 0xDC, 0xF8, 0x28, 0x00, 0xED, 0x6E, 0x40, 0xF8, 0x03, 0x5C, 0xBE, 0x45, 0x66, 0x64, 0x0D, 0xD2, ++0xDC, 0xF8, 0x4C, 0x10, 0x21, 0xF4, 0xFF, 0x21, 0x21, 0xF4, 0xC0, 0x61, 0x41, 0xEA, 0x49, 0x21, 0x41, 0xF4, 0x80, 0x70, ++0x61, 0x62, 0x73, 0x46, 0xCC, 0xF8, 0x4C, 0x00, 0x72, 0x62, 0xD8, 0xF8, 0x24, 0x20, 0x01, 0xF4, 0x60, 0x11, 0xD3, 0x1A, ++0xB1, 0xF5, 0x60, 0x1F, 0xC8, 0xF8, 0x24, 0x30, 0x59, 0xD0, 0x69, 0x4B, 0x25, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x0B, 0xF1, 0x01, 0x0B, 0x00, 0x2B, 0x5F, 0xFA, 0x8B, 0xFB, 0x42, 0xDB, 0x69, 0x6A, 0x02, 0x94, 0x2C, 0x46, 0xD4, 0xF8, ++0x4C, 0xC0, 0xDC, 0xF8, 0x2C, 0x30, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0xC1, 0xF3, 0x49, 0x2E, ++0x03, 0xEB, 0x8E, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xBE, 0x45, 0xA1, 0xD3, 0x72, 0x6A, 0x01, 0x98, 0x73, 0x46, 0x1A, 0x44, ++0x82, 0x42, 0xAB, 0xD9, 0xDD, 0xF8, 0x08, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x7E, 0xD0, 0xD9, 0xF8, 0x4C, 0x10, 0x81, 0xF8, ++0x0D, 0xB0, 0xD9, 0xF8, 0x24, 0x30, 0xC6, 0xF8, 0x38, 0x91, 0x43, 0xF4, 0x60, 0x12, 0xC9, 0xF8, 0x24, 0x20, 0x62, 0x6A, ++0x43, 0xF4, 0x60, 0x13, 0x02, 0xF4, 0x60, 0x12, 0x43, 0xF4, 0x80, 0x73, 0x00, 0x20, 0xB2, 0xF5, 0x60, 0x1F, 0xCB, 0x64, ++0xC8, 0x61, 0x60, 0xD0, 0x48, 0x4B, 0x04, 0x9A, 0x1B, 0x68, 0x14, 0x60, 0x5D, 0x78, 0x00, 0x2D, 0x47, 0xD1, 0x63, 0x6C, ++0x0C, 0x33, 0x33, 0x61, 0x2C, 0xE0, 0x00, 0x2D, 0xBA, 0xD1, 0x43, 0x49, 0x43, 0x48, 0x40, 0xF2, 0xF4, 0x52, 0x13, 0xF0, ++0x7D, 0xFD, 0xB3, 0xE7, 0x4F, 0xF0, 0x00, 0x09, 0x71, 0xE7, 0x05, 0x9A, 0x11, 0x46, 0x37, 0x4A, 0x54, 0x23, 0x03, 0xFB, ++0x01, 0x23, 0x3A, 0x49, 0x93, 0xF8, 0x50, 0x20, 0x09, 0x68, 0xC6, 0xF8, 0x38, 0x41, 0x01, 0x3A, 0x83, 0xF8, 0x50, 0x20, ++0x4B, 0x78, 0x43, 0xB3, 0x18, 0xEE, 0x10, 0x0A, 0x12, 0xF0, 0x54, 0xF9, 0x41, 0x46, 0xD8, 0xF8, 0x48, 0x01, 0x12, 0xF0, ++0x0B, 0xF9, 0x04, 0x99, 0x22, 0x68, 0xE3, 0x6C, 0x0A, 0x60, 0x00, 0x22, 0xDA, 0x61, 0x01, 0x25, 0x18, 0xEE, 0x10, 0x0A, ++0x31, 0x46, 0x12, 0xF0, 0x23, 0xF9, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x05, 0x46, ++0x31, 0x46, 0x18, 0xEE, 0x10, 0x0A, 0x12, 0xF0, 0x17, 0xF9, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0x25, 0xE6, 0xE7, 0xD8, 0xF8, 0x10, 0x30, 0x33, 0x61, 0xD2, 0xE7, 0x18, 0xEE, 0x10, 0x0A, 0x31, 0x46, ++0x12, 0xF0, 0x06, 0xF9, 0x02, 0x9D, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0xEE, ++0x10, 0x0A, 0x12, 0xF0, 0x1B, 0xF9, 0x99, 0xE7, 0x06, 0x99, 0x4A, 0x6A, 0xCD, 0x6C, 0x42, 0xF4, 0x60, 0x13, 0xC5, 0xF8, ++0x1C, 0x90, 0x4B, 0x62, 0x63, 0x6A, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0x20, 0x17, 0x42, 0xF4, 0x60, 0x12, 0x43, 0xF4, ++0x20, 0x13, 0x42, 0xF4, 0x80, 0x72, 0x47, 0xF4, 0x80, 0x77, 0xEA, 0x64, 0x18, 0xEE, 0x10, 0x0A, 0x63, 0x62, 0x31, 0x46, ++0xCC, 0xF8, 0x4C, 0x70, 0x12, 0xF0, 0xDC, 0xF8, 0x04, 0x9B, 0x4D, 0x46, 0x1C, 0x60, 0xB4, 0xE7, 0x20, 0x62, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xA4, 0x91, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x82, 0x69, 0x03, 0x32, 0x22, 0xF0, 0x03, 0x02, ++0x04, 0x32, 0x93, 0xB2, 0x99, 0x42, 0x04, 0xD9, 0xC8, 0x1A, 0x80, 0xB2, 0x03, 0x30, 0x80, 0x08, 0x70, 0x47, 0x00, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, 0x43, 0x4A, 0x44, 0x4B, 0x11, 0x68, 0x18, 0x68, 0x88, 0x42, 0x08, 0xD0, ++0xD2, 0xE9, 0x01, 0x54, 0xD2, 0xE9, 0x03, 0x02, 0xC3, 0xE9, 0x00, 0x15, 0xC3, 0xE9, 0x02, 0x40, 0x1A, 0x61, 0x3E, 0x48, ++0x3C, 0x4D, 0x3E, 0x4F, 0xDF, 0xF8, 0x04, 0x81, 0x30, 0x22, 0x00, 0x21, 0x06, 0x46, 0xEE, 0xF7, 0xE3, 0xFF, 0x05, 0xF1, ++0x18, 0x09, 0x3B, 0x68, 0x55, 0xF8, 0x04, 0x0B, 0x4F, 0xF4, 0xAC, 0x72, 0x02, 0xFB, 0x03, 0xF2, 0x00, 0x21, 0xEE, 0xF7, ++0xD7, 0xFF, 0x57, 0xF8, 0x04, 0x3B, 0x00, 0x2B, 0x58, 0xDD, 0x4F, 0xF0, 0x00, 0x0B, 0xDA, 0x46, 0x55, 0xF8, 0x04, 0x4C, ++0x30, 0x4B, 0x5C, 0x44, 0x05, 0x20, 0x04, 0xF1, 0xA8, 0x01, 0x63, 0x64, 0x2E, 0x4B, 0xC4, 0xF8, 0xA8, 0x30, 0x84, 0xF8, ++0x97, 0x00, 0x04, 0xF1, 0x94, 0x03, 0x04, 0xF1, 0xAB, 0x00, 0x61, 0x67, 0x18, 0x21, 0x6F, 0xF0, 0x7B, 0x0C, 0x23, 0x66, ++0x60, 0x66, 0x4F, 0xF4, 0xC0, 0x63, 0x40, 0xF2, 0x43, 0x10, 0xA1, 0x66, 0x00, 0x21, 0xC4, 0xE9, 0x21, 0x30, 0xC4, 0xE9, ++0x0D, 0x11, 0xC4, 0xE9, 0x16, 0x11, 0xC4, 0xE9, 0x1E, 0x11, 0x84, 0xF8, 0x94, 0xC0, 0x84, 0xF8, 0x95, 0x10, 0x84, 0xF8, ++0x96, 0x10, 0xA1, 0x62, 0xE1, 0x63, 0xE1, 0x66, 0xC4, 0xF8, 0x80, 0x10, 0x21, 0x67, 0xC4, 0xF8, 0x48, 0x61, 0xC4, 0xF8, ++0x0C, 0x80, 0xC4, 0xF8, 0x50, 0x80, 0xF0, 0xF7, 0x7F, 0xF8, 0x80, 0x03, 0xC4, 0xF8, 0xAC, 0x00, 0xF0, 0xF7, 0x7A, 0xF8, ++0x4F, 0xF0, 0x01, 0x0C, 0x01, 0x30, 0x0C, 0xFA, 0x00, 0xF0, 0x12, 0x4B, 0xC4, 0xF8, 0xB8, 0x30, 0x01, 0x38, 0x00, 0x21, ++0xC4, 0xE9, 0x2C, 0x01, 0x21, 0x46, 0x30, 0x46, 0x12, 0xF0, 0x16, 0xF8, 0x57, 0xF8, 0x04, 0x1C, 0x0A, 0xF1, 0x01, 0x0A, ++0x8A, 0x45, 0x0B, 0xF5, 0xAC, 0x7B, 0xA9, 0xDB, 0x4D, 0x45, 0x06, 0xF1, 0x08, 0x06, 0x94, 0xD1, 0xBD, 0xE8, 0xF8, 0x8F, ++0xEC, 0x57, 0x18, 0x00, 0x74, 0x1F, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x00, 0x01, 0x20, 0x00, ++0x1E, 0xAB, 0xDC, 0xBA, 0x04, 0x07, 0xFF, 0xFF, 0xBE, 0xBA, 0xFE, 0xCA, 0x2D, 0xE9, 0xF8, 0x43, 0x18, 0x4A, 0x19, 0x4B, ++0x11, 0x68, 0x18, 0x68, 0x88, 0x42, 0x08, 0xD0, 0xD2, 0xE9, 0x01, 0x54, 0xD2, 0xE9, 0x03, 0x02, 0xC3, 0xE9, 0x00, 0x15, ++0xC3, 0xE9, 0x02, 0x40, 0x1A, 0x61, 0x13, 0x4C, 0x13, 0x4F, 0x11, 0x4E, 0x04, 0xF1, 0x30, 0x09, 0x20, 0x46, 0x11, 0xF0, ++0xDB, 0xFF, 0x57, 0xF8, 0x04, 0x3B, 0x00, 0x2B, 0x0E, 0xDD, 0x00, 0x25, 0xA8, 0x46, 0x31, 0x68, 0x20, 0x46, 0x29, 0x44, ++0x11, 0xF0, 0xD4, 0xFF, 0x57, 0xF8, 0x04, 0x3C, 0x08, 0xF1, 0x01, 0x08, 0x98, 0x45, 0x05, 0xF5, 0xAC, 0x75, 0xF2, 0xDB, ++0x08, 0x34, 0x4C, 0x45, 0x06, 0xF1, 0x04, 0x06, 0xE4, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0xEC, 0x57, 0x18, 0x00, ++0x74, 0x1F, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x28, 0x82, 0xB0, ++0x06, 0x46, 0x00, 0xF0, 0xBD, 0x80, 0x6A, 0x4C, 0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, ++0x94, 0xF8, 0x4D, 0x30, 0xE7, 0x6A, 0x65, 0x6B, 0x01, 0x2B, 0x69, 0xD1, 0xD5, 0xE9, 0x12, 0x38, 0x00, 0x22, 0x4F, 0xF4, ++0x80, 0x71, 0x6A, 0x62, 0xC8, 0xF8, 0x1C, 0x20, 0xC8, 0xF8, 0x4C, 0x10, 0x00, 0x2B, 0x4C, 0xD0, 0xBA, 0x88, 0x11, 0x07, ++0x49, 0xD5, 0xD3, 0xE9, 0x17, 0x21, 0x28, 0x33, 0xC8, 0xF8, 0x34, 0x10, 0xC8, 0xF8, 0x48, 0x20, 0xC8, 0xF8, 0x38, 0x30, ++0x2B, 0x7F, 0x58, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x63, 0xBB, 0x55, 0x4A, ++0x6B, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x5B, 0x68, 0x9A, 0x06, 0x23, 0xD5, 0xEB, 0x8B, 0x13, 0xF4, ++0x00, 0x5F, 0xEB, 0x6A, 0xDB, 0x6B, 0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0xC3, 0xB9, 0xD8, 0xF8, ++0x24, 0x10, 0x0B, 0x88, 0x9A, 0xB2, 0x1B, 0x04, 0x12, 0xD5, 0xC2, 0xF3, 0x0E, 0x02, 0x0A, 0x80, 0x95, 0xF8, 0x33, 0x20, ++0x95, 0xF8, 0x32, 0x30, 0x04, 0x3A, 0x04, 0x3B, 0x85, 0xF8, 0x33, 0x20, 0x85, 0xF8, 0x32, 0x30, 0xD8, 0xE9, 0x0A, 0x32, ++0x04, 0x3A, 0x04, 0x3B, 0xC8, 0xE9, 0x0A, 0x32, 0x28, 0x46, 0x02, 0xF0, 0x71, 0xFC, 0x3E, 0x4B, 0x08, 0xF1, 0x14, 0x01, ++0xD3, 0xF8, 0x9C, 0x33, 0x32, 0x46, 0x08, 0x46, 0x98, 0x47, 0xD7, 0xF8, 0x48, 0x01, 0x39, 0x46, 0x11, 0xF0, 0x4A, 0xFF, ++0x00, 0x23, 0x6B, 0x64, 0x94, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x33, 0x84, 0xF8, 0x50, 0x30, 0xE2, 0x62, 0x02, 0xB0, ++0xBD, 0xE8, 0xF0, 0x87, 0x6B, 0x6A, 0xDF, 0xF8, 0xCC, 0x90, 0x20, 0x6B, 0xD5, 0xE9, 0x12, 0xA8, 0x43, 0xF4, 0x60, 0x13, ++0x6B, 0x62, 0xC7, 0xF8, 0x38, 0x51, 0x02, 0xF0, 0x37, 0xFC, 0x94, 0xF8, 0x4D, 0x20, 0xD9, 0xF8, 0x00, 0x30, 0x88, 0xF8, ++0x0D, 0x20, 0x5B, 0x78, 0x00, 0x2B, 0x34, 0xD1, 0x3B, 0x61, 0x6B, 0x6A, 0xB9, 0x88, 0x43, 0xF4, 0x80, 0x73, 0x41, 0xF0, ++0x01, 0x02, 0xC8, 0xF8, 0x4C, 0x30, 0xBA, 0x80, 0xBA, 0xF1, 0x00, 0x0F, 0x09, 0xD0, 0x4D, 0x07, 0x07, 0xD4, 0x08, 0x07, ++0x31, 0xD4, 0x23, 0x6B, 0x99, 0x6C, 0x4B, 0x6A, 0x43, 0xF0, 0x04, 0x03, 0x4B, 0x62, 0x93, 0x07, 0x10, 0xD5, 0xD9, 0xF8, ++0x00, 0x30, 0x5B, 0x78, 0xA3, 0xB9, 0x08, 0xF1, 0x14, 0x01, 0x23, 0x6B, 0x3A, 0x6B, 0x98, 0x6A, 0x15, 0x4B, 0x50, 0x61, ++0xD3, 0xF8, 0x9C, 0x33, 0x32, 0x46, 0x07, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0x39, 0x46, 0x04, 0xF1, 0x1C, 0x00, 0x11, 0xF0, ++0xF9, 0xFE, 0xAF, 0xE7, 0x0F, 0x4C, 0x47, 0xE7, 0x07, 0xF1, 0x50, 0x01, 0xE9, 0xE7, 0x94, 0xF8, 0x4E, 0x00, 0xBB, 0x7A, ++0x7A, 0x7A, 0x69, 0x8C, 0x00, 0x90, 0x38, 0x46, 0xFF, 0xF7, 0xCA, 0xF8, 0x07, 0xF1, 0x50, 0x03, 0xC8, 0xF8, 0x1C, 0x30, ++0xBD, 0xE7, 0x41, 0xF0, 0x03, 0x02, 0xBA, 0x80, 0xCF, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xD0, 0xF8, 0x4C, 0x90, 0x8B, 0xB0, 0x09, 0xF1, 0x14, 0x03, 0x05, 0x29, 0x04, 0x46, 0x0E, 0x46, 0x00, 0x93, 0x00, 0xF0, ++0xAD, 0x81, 0x57, 0x4D, 0x01, 0xEB, 0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x05, 0xEB, 0x83, 0x05, 0x94, 0xF8, 0x1B, 0xB0, ++0x94, 0xF8, 0x1D, 0xA0, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x50, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xDF, 0xF8, 0x40, 0x81, 0xEA, 0x6A, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x00, 0x2A, 0x79, 0xD0, ++0x4A, 0x4F, 0x06, 0xE0, 0xD7, 0xF8, 0x5C, 0x33, 0x30, 0x46, 0x98, 0x47, 0xEA, 0x6A, 0x00, 0x2A, 0x70, 0xD0, 0x63, 0x6A, ++0x99, 0x02, 0xF5, 0xD5, 0x03, 0xF4, 0x60, 0x11, 0xB1, 0xF5, 0x20, 0x1F, 0xF0, 0xD0, 0x50, 0x7A, 0x61, 0x7F, 0x88, 0x42, ++0xEC, 0xD1, 0x90, 0x7A, 0xE1, 0x7E, 0x88, 0x42, 0xE8, 0xD1, 0xD9, 0xF8, 0x2C, 0x10, 0xB5, 0xF8, 0x48, 0x00, 0x03, 0x31, ++0x21, 0xF0, 0x03, 0x01, 0x04, 0x31, 0x89, 0xB2, 0x88, 0x42, 0x00, 0xF2, 0x5D, 0x81, 0x00, 0x20, 0x03, 0x90, 0x05, 0x90, ++0x86, 0x46, 0x68, 0x6B, 0x01, 0x90, 0x50, 0x6A, 0x02, 0x90, 0x01, 0x98, 0x95, 0xF8, 0x4F, 0xC0, 0xC0, 0x6C, 0x04, 0x90, ++0x03, 0x98, 0xA5, 0xF8, 0x4A, 0xE0, 0x08, 0x44, 0x02, 0x99, 0x05, 0xEB, 0x8C, 0x0E, 0x08, 0x44, 0x4F, 0xEA, 0x8C, 0x01, ++0x03, 0x91, 0xDE, 0xF8, 0x38, 0x10, 0x88, 0x42, 0x40, 0xF2, 0x82, 0x81, 0x95, 0xF8, 0x4E, 0x10, 0x61, 0x45, 0xBB, 0xD9, ++0x95, 0xF8, 0x4D, 0x10, 0x01, 0x29, 0xB7, 0xD0, 0xDE, 0xF8, 0x3C, 0xE0, 0x70, 0x45, 0xB3, 0xD8, 0x03, 0x9F, 0x17, 0x44, ++0xBB, 0x46, 0x01, 0x9F, 0xCB, 0xF8, 0x3C, 0x71, 0x0C, 0xF1, 0x01, 0x0C, 0x02, 0x9F, 0xCB, 0xF8, 0x34, 0x70, 0x85, 0xF8, ++0x4F, 0xC0, 0x05, 0x9F, 0x62, 0x64, 0x43, 0xEA, 0x47, 0x23, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0xE0, 0x03, 0x63, 0x62, ++0xC9, 0xF8, 0x4C, 0x30, 0x04, 0x9B, 0x1F, 0x46, 0x00, 0x9B, 0xFB, 0x61, 0x50, 0x62, 0x95, 0xF8, 0x4C, 0x20, 0x6C, 0x63, ++0x4B, 0x1C, 0xDB, 0xB2, 0x9A, 0x42, 0x85, 0xF8, 0x4D, 0x30, 0x0D, 0xD8, 0x10, 0x4B, 0x30, 0x46, 0xD3, 0xF8, 0x5C, 0x33, ++0x98, 0x47, 0x07, 0xE0, 0x63, 0x6A, 0x98, 0x02, 0x1C, 0xD4, 0x95, 0xF8, 0x50, 0x30, 0x01, 0x33, 0x85, 0xF8, 0x50, 0x30, ++0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x00, 0x20, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA3, 0x6A, 0xDB, 0x0A, 0x13, 0xF0, 0x06, 0x0F, 0xDD, 0xD0, 0xB0, 0x48, ++0x00, 0xEB, 0xC6, 0x00, 0x11, 0xF0, 0x4A, 0xFE, 0xE8, 0x62, 0x00, 0x28, 0x00, 0xF0, 0xEA, 0x80, 0xAC, 0x4F, 0x80, 0xF8, ++0x0A, 0xB0, 0x00, 0x23, 0x01, 0x21, 0x3A, 0x68, 0x80, 0xF8, 0x09, 0xA0, 0x03, 0x72, 0x43, 0x60, 0xC1, 0x72, 0xA3, 0x6A, ++0xB2, 0xF9, 0x00, 0x20, 0x61, 0x7F, 0x03, 0x91, 0xC3, 0xF3, 0xC1, 0x1B, 0xC3, 0xF3, 0xC7, 0x21, 0x00, 0x2A, 0xC3, 0xF3, ++0xC2, 0x23, 0x01, 0x93, 0xC0, 0xF2, 0xD2, 0x80, 0x01, 0x9B, 0x05, 0x2B, 0x00, 0xF0, 0xD9, 0x80, 0xD4, 0xF8, 0x28, 0xA0, ++0x63, 0x7F, 0x05, 0x93, 0x0A, 0xF0, 0x7F, 0x03, 0x04, 0x93, 0xCA, 0xF3, 0x40, 0x23, 0x06, 0x93, 0x01, 0x9B, 0x04, 0x2B, ++0x3B, 0x68, 0x00, 0xF0, 0xF2, 0x80, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x01, 0x81, 0x94, 0x4A, 0x05, 0x99, ++0x02, 0x92, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x23, 0x04, 0x9A, 0x9B, 0x8A, 0x08, 0x93, 0xC2, 0xF3, 0xC1, 0x02, ++0x01, 0x32, 0x09, 0x92, 0x0A, 0xF0, 0x07, 0x0A, 0x8D, 0x4B, 0x05, 0x93, 0x8D, 0x4B, 0x9C, 0x46, 0x06, 0x9B, 0x00, 0x27, ++0x43, 0xEA, 0xCA, 0x0A, 0x5F, 0xFA, 0x8B, 0xF3, 0x19, 0x46, 0x05, 0xF1, 0x38, 0x0B, 0x04, 0x93, 0x85, 0xF8, 0x4E, 0x10, ++0x00, 0x23, 0x31, 0x1D, 0xCD, 0xF8, 0x18, 0x90, 0x07, 0x94, 0xD1, 0x46, 0x85, 0xF8, 0x4F, 0x30, 0xDA, 0x46, 0x1E, 0x46, ++0x64, 0x46, 0x8B, 0x46, 0x01, 0x2A, 0xF1, 0xB2, 0x00, 0xF0, 0xA8, 0x80, 0x48, 0x46, 0xA0, 0x47, 0x7E, 0x4B, 0x09, 0x9A, ++0x33, 0xF8, 0x1B, 0xC0, 0x08, 0x99, 0x02, 0xFB, 0x0C, 0xFC, 0x00, 0xFB, 0x0C, 0xF0, 0xF8, 0x40, 0x81, 0x42, 0x28, 0xBF, ++0x01, 0x46, 0x4A, 0xF8, 0x04, 0x1B, 0x95, 0xF8, 0x4E, 0x10, 0x01, 0x36, 0x8E, 0x42, 0xE5, 0xDD, 0xCA, 0x46, 0x04, 0x99, ++0x05, 0x9B, 0x50, 0x46, 0xDD, 0xE9, 0x06, 0x94, 0x98, 0x47, 0x03, 0x9B, 0xD5, 0xF8, 0x38, 0xC0, 0x1E, 0x46, 0x02, 0x9B, ++0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x06, 0x32, 0x09, 0x9B, 0x16, 0x7F, 0xEA, 0x6A, 0x03, 0xFB, 0x06, 0xF6, 0x00, 0xFB, ++0x06, 0xF6, 0xFE, 0x40, 0xB6, 0xB2, 0xA5, 0xF8, 0x48, 0x60, 0xE1, 0x7E, 0x63, 0x7F, 0xEF, 0x6B, 0x9E, 0x20, 0x00, 0xFB, ++0x03, 0x13, 0x02, 0x99, 0x28, 0x6C, 0x01, 0xEB, 0x83, 0x03, 0x4F, 0xF0, 0x01, 0x0E, 0x93, 0xF8, 0x5A, 0x31, 0x85, 0xF8, ++0x4C, 0x30, 0xD9, 0xF8, 0x2C, 0x10, 0x00, 0x9B, 0x53, 0x61, 0x03, 0x31, 0x21, 0xF0, 0x03, 0x01, 0x04, 0x31, 0x00, 0x23, ++0x89, 0xB2, 0x51, 0x62, 0xC2, 0xF8, 0x54, 0x01, 0xC2, 0xE9, 0x53, 0xC7, 0xC2, 0xE9, 0x0D, 0x33, 0x93, 0x64, 0x93, 0x61, ++0xD3, 0x63, 0x85, 0xF8, 0x4D, 0xE0, 0xD9, 0xF8, 0x2C, 0x00, 0x03, 0x30, 0x20, 0xF0, 0x03, 0x00, 0x04, 0x30, 0x80, 0xB2, ++0xB0, 0x42, 0x57, 0xD2, 0x30, 0x1A, 0x80, 0xB2, 0x03, 0x30, 0x83, 0x10, 0x01, 0xEB, 0x83, 0x01, 0x80, 0x08, 0x5B, 0x02, ++0x66, 0x6A, 0xA5, 0xF8, 0x4A, 0x00, 0x33, 0x43, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0xD0, 0x03, 0x51, 0x62, 0xC5, 0xE9, ++0x0C, 0x44, 0x63, 0x62, 0x62, 0x64, 0xC9, 0xF8, 0x4C, 0x30, 0xFF, 0xE6, 0xA0, 0xEB, 0x01, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, ++0x0E, 0xF1, 0x03, 0x0E, 0x4F, 0xEA, 0xAE, 0x00, 0x05, 0x90, 0x80, 0x00, 0x4F, 0xEA, 0x9E, 0x0E, 0x03, 0x90, 0x98, 0xE6, ++0x3D, 0x4D, 0x57, 0xE6, 0x60, 0x62, 0xE8, 0xE6, 0x11, 0xF0, 0x06, 0x0F, 0x7F, 0xF4, 0x2A, 0xAF, 0x3A, 0x49, 0x3B, 0x48, ++0x4F, 0xF4, 0xEA, 0x72, 0x13, 0xF0, 0x60, 0xF9, 0x22, 0xE7, 0x09, 0xAB, 0x08, 0xAA, 0x01, 0x99, 0x20, 0x46, 0x02, 0xF0, ++0x39, 0xF9, 0x36, 0x4B, 0x05, 0x93, 0x36, 0x4B, 0x94, 0xF8, 0x36, 0x70, 0x09, 0x9A, 0x9C, 0x46, 0x2B, 0x4B, 0x02, 0x93, ++0x82, 0x46, 0xC7, 0xF3, 0x40, 0x17, 0x3F, 0xE7, 0x01, 0x9B, 0x04, 0x2B, 0x7F, 0xF4, 0x54, 0xAF, 0x4F, 0xEA, 0xE9, 0x02, ++0x00, 0x2E, 0x7F, 0xF4, 0x4F, 0xAF, 0x09, 0x2A, 0x04, 0xBF, 0x09, 0xF0, 0x07, 0x03, 0x43, 0xF0, 0x40, 0x09, 0x47, 0xE7, ++0x18, 0x46, 0xAD, 0xE7, 0x95, 0xF8, 0x4D, 0x10, 0x93, 0xE6, 0x04, 0x9A, 0xB3, 0xF9, 0x00, 0x30, 0x11, 0x09, 0x4A, 0x1C, ++0x00, 0x2B, 0x0A, 0xF0, 0x0F, 0x0A, 0x09, 0x92, 0x14, 0xDB, 0x19, 0x49, 0x05, 0x98, 0x02, 0x91, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x00, 0x13, 0x1B, 0x69, 0x08, 0x93, 0x0E, 0xE7, 0x1A, 0xF0, 0x60, 0x0F, 0x3F, 0xF4, 0xFB, 0xAE, 0x17, 0x49, ++0x1A, 0x48, 0x4F, 0xF4, 0xD2, 0x72, 0x13, 0xF0, 0x19, 0xF9, 0xF3, 0xE6, 0x03, 0x29, 0x04, 0xD8, 0xBA, 0xF1, 0x09, 0x0F, ++0x0D, 0xD8, 0x09, 0x9A, 0xE3, 0xE7, 0x10, 0x49, 0x14, 0x48, 0x40, 0xF2, 0x9B, 0x12, 0x13, 0xF0, 0x0B, 0xF9, 0x3B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEF, 0xDB, 0xF1, 0xE7, 0x0A, 0x49, 0x0F, 0x48, 0x4F, 0xF4, 0xCE, 0x72, 0x13, 0xF0, ++0xFF, 0xF8, 0xEA, 0xE7, 0x64, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x85, 0x06, 0x13, 0x00, ++0x75, 0x06, 0x13, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB8, 0x91, 0x15, 0x00, ++0x21, 0x3B, 0x13, 0x00, 0x05, 0x3B, 0x13, 0x00, 0x0C, 0x92, 0x15, 0x00, 0xE0, 0x91, 0x15, 0x00, 0xFC, 0x91, 0x15, 0x00, ++0xC3, 0x7A, 0x01, 0x3B, 0xDB, 0xB2, 0xC3, 0x72, 0x03, 0xB1, 0x70, 0x47, 0x01, 0x46, 0xD0, 0xF8, 0x48, 0x01, 0x11, 0xF0, ++0x83, 0xBC, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0xD0, 0xE9, 0x12, 0x67, 0x00, 0x23, 0x4F, 0xF4, 0x80, 0x72, 0x43, 0x62, ++0x43, 0x64, 0xFB, 0x61, 0xFA, 0x64, 0x00, 0x2E, 0x00, 0xF0, 0x81, 0x80, 0xD0, 0xF8, 0x2C, 0x80, 0x8A, 0x46, 0x05, 0x46, ++0x06, 0xF1, 0x28, 0x09, 0x08, 0xF1, 0x40, 0x01, 0x43, 0x46, 0x06, 0xF1, 0x24, 0x02, 0x53, 0xF8, 0x04, 0x4B, 0x42, 0xF8, ++0x04, 0x4F, 0x8B, 0x42, 0xF9, 0xD1, 0xEB, 0x8B, 0x9C, 0x04, 0x22, 0xD5, 0x48, 0x4B, 0x49, 0x49, 0x1A, 0x68, 0x6B, 0x7F, ++0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x41, 0x61, 0xDB, ++0xD8, 0xF8, 0x14, 0x20, 0xD4, 0xF8, 0x9C, 0x30, 0x32, 0x64, 0xD8, 0xF8, 0x24, 0x20, 0x32, 0x65, 0xC3, 0xF3, 0xC2, 0x22, ++0x05, 0x2A, 0xF3, 0x63, 0x5D, 0xD0, 0xD8, 0xF8, 0x3C, 0x30, 0x58, 0x07, 0x03, 0xD4, 0xF3, 0x6A, 0x23, 0xF4, 0xC0, 0x73, ++0xF3, 0x62, 0x39, 0x4A, 0x2B, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x7B, 0xB1, ++0x73, 0x6A, 0x43, 0xF0, 0x10, 0x03, 0x28, 0x46, 0x73, 0x62, 0x02, 0xF0, 0x47, 0xF9, 0xD6, 0xE9, 0x17, 0x23, 0x07, 0xF1, ++0x14, 0x00, 0xC7, 0xE9, 0x0D, 0x39, 0xBA, 0x64, 0xBD, 0xE8, 0xF0, 0x87, 0x2B, 0x4A, 0x6B, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, ++0x01, 0xFB, 0x03, 0x23, 0x5B, 0x68, 0x99, 0x06, 0xE6, 0xD5, 0xBA, 0xF1, 0x00, 0x0F, 0xE3, 0xD1, 0xEB, 0x8B, 0x13, 0xF4, ++0x00, 0x5F, 0xEB, 0x6A, 0xDB, 0x6B, 0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0x00, 0x2B, 0xD7, 0xD1, ++0x79, 0x6A, 0x0A, 0x88, 0x93, 0xB2, 0x12, 0x04, 0xD2, 0xD5, 0xC3, 0xF3, 0x0E, 0x03, 0x0B, 0x80, 0x95, 0xF8, 0x33, 0x20, ++0x95, 0xF8, 0x32, 0x30, 0x04, 0x3A, 0x04, 0x3B, 0x85, 0xF8, 0x33, 0x20, 0x85, 0xF8, 0x32, 0x30, 0xD7, 0xE9, 0x0A, 0x32, ++0x04, 0x3A, 0x04, 0x3B, 0xC7, 0xE9, 0x0A, 0x32, 0xBE, 0xE7, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x2C, 0x9B, 0xD1, ++0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0x13, 0xF0, 0x3C, 0xF8, 0x94, 0xE7, 0x03, 0xF4, 0xC0, 0x63, 0xF2, 0x6C, ++0x94, 0xF8, 0xA1, 0x10, 0xB3, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x30, 0x4F, 0xF4, 0x00, 0x30, 0x22, 0xF4, ++0x40, 0x33, 0x03, 0x43, 0x19, 0xB1, 0x43, 0xF4, 0x80, 0x23, 0xF3, 0x64, 0x8D, 0xE7, 0x23, 0xF4, 0x80, 0x23, 0xF3, 0x64, ++0x89, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x05, 0x28, 0x89, 0xB0, 0x81, 0x46, 0x00, 0xF0, 0x79, 0x81, 0xBE, 0x4A, ++0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x03, 0x93, 0x03, 0x9B, 0xDC, 0x68, 0xBA, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x09, 0xDA, 0x5D, 0xE1, 0xE3, 0x6C, 0x1B, 0x6D, 0x00, 0x2B, 0x80, 0xF2, ++0xFE, 0x80, 0x24, 0x68, 0x00, 0x2C, 0x00, 0xF0, 0xFA, 0x80, 0x63, 0x6A, 0x9A, 0x02, 0xF3, 0xD5, 0xB0, 0x4D, 0x2A, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x80, 0x81, 0xAE, 0x4B, 0x67, 0x6C, 0x1B, 0x68, 0xDB, 0xB2, 0x07, 0xEB, ++0x83, 0x03, 0xD3, 0xF8, 0x3C, 0x41, 0xE5, 0x6C, 0x63, 0x6A, 0xAA, 0x49, 0x43, 0xF4, 0x60, 0x10, 0x09, 0x68, 0x60, 0x62, ++0x49, 0x78, 0x23, 0xF4, 0xC0, 0x13, 0x00, 0x29, 0x40, 0xF0, 0x58, 0x81, 0x43, 0xF4, 0x60, 0x13, 0x43, 0xF4, 0x80, 0x73, ++0x00, 0x2A, 0x26, 0x68, 0xEB, 0x64, 0xE9, 0x61, 0xC0, 0xF2, 0x57, 0x81, 0x72, 0x6A, 0x02, 0xF4, 0x60, 0x1A, 0xBA, 0xF5, ++0x60, 0x1F, 0x00, 0xF0, 0xEC, 0x80, 0x9D, 0x48, 0x50, 0xF8, 0x39, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xE6, 0x80, 0x00, 0xEB, ++0xC9, 0x00, 0x11, 0xF0, 0xAD, 0xFB, 0xBB, 0x88, 0x83, 0x80, 0x7B, 0x7A, 0x43, 0x72, 0xBB, 0x7A, 0x83, 0x72, 0x01, 0x23, ++0xC3, 0x72, 0x72, 0x6A, 0xD6, 0xF8, 0x4C, 0xA0, 0xF9, 0x6A, 0xD7, 0xF8, 0x4C, 0xB1, 0xB5, 0x6C, 0x05, 0x95, 0x04, 0x46, ++0xD7, 0xE9, 0x10, 0x03, 0x22, 0xF4, 0xC0, 0x12, 0xE1, 0x62, 0x42, 0xF4, 0x20, 0x12, 0x00, 0x21, 0xC4, 0xE9, 0x10, 0x03, ++0xA1, 0x64, 0x3B, 0x6B, 0x72, 0x62, 0xCA, 0xF8, 0x4C, 0x20, 0xC4, 0xF8, 0x4C, 0xB1, 0x06, 0x93, 0xD7, 0xF8, 0x50, 0x31, ++0xC4, 0xF8, 0x50, 0x31, 0xD7, 0xF8, 0x54, 0x31, 0xC4, 0xF8, 0x54, 0x31, 0x04, 0xF1, 0x0C, 0x03, 0x0A, 0xF1, 0x14, 0x0C, ++0x28, 0x35, 0xC4, 0xE9, 0x0D, 0x11, 0xA1, 0x61, 0xE1, 0x63, 0x61, 0x62, 0x04, 0x93, 0x04, 0xF5, 0x82, 0x73, 0xC4, 0xF8, ++0x14, 0xC0, 0x25, 0x63, 0xBC, 0x46, 0x08, 0x46, 0x57, 0x46, 0x07, 0x93, 0xAA, 0x46, 0x8E, 0x46, 0x25, 0x46, 0x0C, 0x46, ++0x06, 0xE0, 0x5A, 0x6A, 0xDF, 0x6C, 0xD8, 0xF8, 0x34, 0x00, 0xD8, 0xF8, 0x4C, 0xB1, 0x1E, 0x46, 0xFB, 0x6A, 0x03, 0x33, ++0xC2, 0xF3, 0x49, 0x28, 0x23, 0xF0, 0x03, 0x03, 0x03, 0xEB, 0x88, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x18, 0x44, 0x01, 0x31, ++0x58, 0x45, 0x02, 0xF4, 0x60, 0x12, 0xC9, 0xB2, 0x06, 0xD9, 0x05, 0xEB, 0x8E, 0x00, 0x0E, 0xF1, 0x01, 0x0E, 0x44, 0x63, ++0x5F, 0xFA, 0x8E, 0xFE, 0x05, 0xEB, 0x8E, 0x08, 0x1C, 0x44, 0xC8, 0xF8, 0x3C, 0x61, 0xB2, 0xF5, 0x60, 0x1F, 0x33, 0x68, ++0x75, 0x64, 0x6C, 0x62, 0x00, 0xF0, 0x18, 0x81, 0x00, 0x2B, 0xD2, 0xD1, 0x2C, 0x46, 0x98, 0x46, 0x55, 0x46, 0xC4, 0xF8, ++0x38, 0x61, 0xBA, 0x46, 0x67, 0x46, 0x03, 0x98, 0x8A, 0xF8, 0x0D, 0x10, 0x90, 0xF8, 0x50, 0x30, 0x03, 0xF1, 0x01, 0x0C, ++0x03, 0x46, 0x22, 0x46, 0x1C, 0x30, 0x83, 0xF8, 0x50, 0xC0, 0x39, 0x46, 0x11, 0xF0, 0xA0, 0xFB, 0x53, 0x4B, 0x1B, 0x68, ++0x58, 0x78, 0x00, 0x28, 0x40, 0xF0, 0x11, 0x81, 0xD7, 0xF8, 0x38, 0x11, 0xF2, 0x6C, 0xDF, 0xF8, 0x30, 0xC1, 0xC9, 0x6C, ++0xD0, 0x61, 0x54, 0x23, 0x03, 0xFB, 0x09, 0xF3, 0x3A, 0x69, 0x5C, 0xF8, 0x03, 0x00, 0x22, 0x61, 0x14, 0x31, 0x04, 0x9A, ++0x3A, 0x61, 0x88, 0x42, 0x63, 0x44, 0x00, 0xF0, 0x2A, 0x81, 0x06, 0x9B, 0x07, 0x9A, 0xA3, 0xF1, 0x28, 0x00, 0x05, 0x9B, ++0xC0, 0x1A, 0x03, 0xF1, 0x5C, 0x01, 0x2B, 0x18, 0x1C, 0x68, 0x45, 0xF8, 0x04, 0x4B, 0x1B, 0x68, 0x42, 0xF8, 0x04, 0x3B, ++0x8D, 0x42, 0xF6, 0xD1, 0x3B, 0x4C, 0x48, 0x46, 0xFC, 0xF7, 0x10, 0xF8, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xD7, 0xF8, 0x38, 0x31, 0x04, 0xDB, 0xB3, 0x42, 0x1C, 0xD1, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0x42, 0xFA, 0xD0, ++0x36, 0x49, 0x37, 0x48, 0x40, 0xF6, 0x2A, 0x42, 0x12, 0xF0, 0xF2, 0xFE, 0xD7, 0xF8, 0x38, 0x31, 0xB3, 0x42, 0xF0, 0xD0, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x08, 0xDA, 0xB8, 0xF1, 0x00, 0x0F, 0x05, 0xD1, 0x2D, 0x49, 0x2F, 0x48, ++0x4F, 0xF4, 0x43, 0x62, 0x12, 0xF0, 0xE0, 0xFE, 0xD8, 0xF8, 0x24, 0x20, 0x46, 0x46, 0x02, 0xF4, 0x60, 0x1A, 0x26, 0x4B, ++0x1B, 0x68, 0x5B, 0x78, 0x00, 0x2B, 0x58, 0xD1, 0xD7, 0xF8, 0x38, 0x31, 0xD7, 0xF8, 0x10, 0x80, 0xDB, 0x6C, 0x07, 0xF1, ++0x0C, 0x05, 0x03, 0xF1, 0x14, 0x07, 0x1C, 0x4B, 0x04, 0x97, 0x54, 0x24, 0x04, 0xFB, 0x09, 0x34, 0x57, 0x46, 0xDF, 0xF8, ++0x88, 0xB0, 0xDF, 0xF8, 0x7C, 0x90, 0xA2, 0x46, 0x03, 0x9C, 0x94, 0xF8, 0x50, 0x10, 0xDB, 0xF8, 0x58, 0x33, 0x01, 0x31, ++0x84, 0xF8, 0x50, 0x10, 0x30, 0x46, 0x00, 0x21, 0x98, 0x47, 0x58, 0xB1, 0x13, 0x4B, 0x68, 0x60, 0x1B, 0x68, 0x59, 0x78, ++0xDA, 0xF8, 0x00, 0x30, 0x00, 0x29, 0x65, 0xD0, 0xAB, 0x42, 0x00, 0xF0, 0xAD, 0x80, 0x05, 0x46, 0xB7, 0xF5, 0x60, 0x1F, ++0x65, 0xD1, 0xC0, 0xF8, 0x04, 0x80, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2C, 0x7F, 0xF4, 0xA8, 0xAE, 0x0A, 0x49, ++0x0B, 0x48, 0x40, 0xF6, 0x8B, 0x32, 0x12, 0xF0, 0x99, 0xFE, 0xA0, 0xE6, 0x09, 0x4B, 0x03, 0x93, 0x8B, 0xE6, 0x00, 0xBF, ++0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x30, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x4C, 0x92, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x07, 0xF1, 0x50, 0x01, 0xA4, 0xE6, 0xD7, 0xF8, 0x54, 0x80, 0x07, 0xF1, 0x50, 0x05, 0x00, 0x27, 0xA9, 0xE7, 0x00, 0x2E, ++0x7F, 0xF4, 0xA6, 0xAE, 0x49, 0x49, 0x4A, 0x48, 0x40, 0xF6, 0xB6, 0x32, 0x12, 0xF0, 0x6E, 0xFE, 0x9E, 0xE6, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x3E, 0xD0, 0x40, 0xF6, 0x9B, 0x32, 0x42, 0x49, 0x44, 0x48, 0x12, 0xF0, 0x62, 0xFE, ++0x43, 0x4B, 0x67, 0x6C, 0x1B, 0x68, 0x2A, 0x68, 0xDB, 0xB2, 0x07, 0xEB, 0x83, 0x03, 0xB2, 0xF9, 0x00, 0x20, 0xD3, 0xF8, ++0x3C, 0x41, 0x00, 0x2A, 0xE5, 0x6C, 0xBF, 0xF6, 0x6F, 0xAE, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x60, 0x1F, ++0x60, 0xD0, 0x3A, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x64, 0xE6, 0x04, 0x9A, 0x93, 0x42, 0x99, 0xD1, 0xCA, 0xE9, ++0x01, 0x11, 0x05, 0x46, 0x96, 0xE7, 0x34, 0x4B, 0x36, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x3F, 0xDB, ++0x77, 0x6A, 0x07, 0xF4, 0x60, 0x17, 0x74, 0xE7, 0x20, 0x46, 0x2C, 0x46, 0x04, 0xEB, 0x8E, 0x0E, 0x55, 0x46, 0xC4, 0xF8, ++0x38, 0x61, 0xBA, 0x46, 0x98, 0x46, 0x67, 0x46, 0xCE, 0xF8, 0x34, 0x00, 0xE3, 0xE6, 0x27, 0x4B, 0x67, 0x6C, 0x1B, 0x68, ++0xDB, 0xB2, 0x07, 0xEB, 0x83, 0x03, 0xD3, 0xF8, 0x3C, 0x41, 0xE5, 0x6C, 0xCB, 0xE7, 0xB0, 0x6A, 0xA3, 0x7A, 0x62, 0x7A, ++0x71, 0x8C, 0xC0, 0xF3, 0xC1, 0x10, 0x00, 0x90, 0x20, 0x46, 0xFE, 0xF7, 0xA1, 0xFB, 0x54, 0x23, 0x1E, 0x49, 0xF2, 0x6C, ++0xD7, 0xF8, 0x54, 0xE0, 0x03, 0xFB, 0x09, 0xF3, 0x04, 0xF1, 0x50, 0x00, 0x51, 0xF8, 0x03, 0xC0, 0xD0, 0x61, 0x07, 0xF1, ++0x50, 0x02, 0xC4, 0xF8, 0x54, 0xE0, 0x94, 0x45, 0x04, 0x9C, 0x7C, 0x65, 0x7F, 0xF4, 0xE5, 0xAE, 0xC8, 0x50, 0xE2, 0xE6, ++0xCA, 0xF8, 0x00, 0x00, 0x05, 0x46, 0x4F, 0xE7, 0x00, 0x2E, 0xBD, 0xD1, 0x0B, 0x49, 0x40, 0xF6, 0x62, 0x42, 0x48, 0x46, ++0x12, 0xF0, 0xF2, 0xFD, 0xB6, 0xE7, 0x04, 0x99, 0x01, 0x22, 0xC3, 0xE9, 0x01, 0x12, 0xD0, 0xE6, 0x40, 0xF6, 0xA5, 0x32, ++0x04, 0x49, 0x0A, 0x48, 0x12, 0xF0, 0xE6, 0xFD, 0x06, 0x4B, 0x1A, 0x68, 0x63, 0x6A, 0xB2, 0xF9, 0x00, 0x20, 0xFC, 0xE5, ++0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x1C, 0x92, 0x15, 0x00, 0x30, 0x83, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x34, 0x92, 0x15, 0x00, 0x05, 0x28, 0x10, 0xB5, 0x25, 0xD0, 0x14, 0x4A, 0x00, 0xEB, 0x40, 0x03, ++0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x02, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0F, 0x4B, ++0x01, 0x21, 0x19, 0x60, 0x0E, 0x4C, 0x92, 0xF8, 0x50, 0x10, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x31, 0xB9, 0xD2, 0x6A, ++0x22, 0xB1, 0x0B, 0x4B, 0xD3, 0xF8, 0x5C, 0x33, 0x98, 0x47, 0x23, 0x68, 0x33, 0xB1, 0x06, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x05, 0x4A, 0xDE, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x03, 0x68, 0x13, 0xF4, ++0xE0, 0x3F, 0x1A, 0xD1, 0x9A, 0x04, 0x4C, 0xBF, 0x03, 0xF0, 0x0F, 0x02, 0x03, 0xF0, 0x07, 0x02, 0x02, 0x2A, 0xC3, 0xF3, ++0xC1, 0x11, 0x88, 0xBF, 0x4F, 0xF4, 0x80, 0x12, 0x23, 0xF0, 0xFF, 0x53, 0x98, 0xBF, 0x4F, 0xF4, 0x00, 0x22, 0x23, 0xF4, ++0xFE, 0x13, 0x42, 0xEA, 0x01, 0x62, 0x13, 0x43, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x03, 0x60, 0x70, 0x47, ++0xC3, 0x6B, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x10, 0xB4, 0x0E, 0x4C, 0x42, 0x6A, 0x24, 0x68, 0xB4, 0xF9, 0x00, 0x40, ++0x00, 0x2C, 0x01, 0xDA, 0xDB, 0x03, 0x0B, 0xD5, 0x53, 0x69, 0x23, 0xF4, 0xE0, 0x33, 0x00, 0x24, 0x43, 0xF4, 0x80, 0x43, ++0xC4, 0x63, 0x5D, 0xF8, 0x04, 0x4B, 0x53, 0x61, 0xFC, 0xF7, 0xA4, 0xB9, 0x04, 0x49, 0x05, 0x48, 0x5D, 0xF8, 0x04, 0x4B, ++0x40, 0xF6, 0xD9, 0x42, 0x12, 0xF0, 0x28, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x92, 0x15, 0x00, ++0x05, 0x28, 0x10, 0xB5, 0x17, 0xD0, 0x0D, 0x4C, 0x00, 0xEB, 0x40, 0x00, 0xC0, 0xEB, 0xC0, 0x00, 0x04, 0xEB, 0x80, 0x04, ++0xA1, 0x6A, 0x31, 0xB1, 0xCB, 0x7A, 0x01, 0x3B, 0xDB, 0xB2, 0xCB, 0x72, 0x13, 0xB1, 0x00, 0x23, 0xA3, 0x62, 0x10, 0xBD, ++0xD1, 0xF8, 0x48, 0x01, 0x11, 0xF0, 0xE8, 0xF8, 0x00, 0x23, 0xA3, 0x62, 0xF7, 0xE7, 0x02, 0x4C, 0xEC, 0xE7, 0x00, 0xBF, ++0x20, 0x62, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0xF0, 0xB4, 0xC5, 0x6C, 0x42, 0x6A, 0xEB, 0x6C, 0xD0, 0xE9, 0x11, 0x67, ++0x22, 0xF4, 0xC0, 0x12, 0x23, 0xF4, 0x60, 0x13, 0x05, 0xF1, 0x14, 0x0C, 0x42, 0xF4, 0x20, 0x14, 0x43, 0xF4, 0x20, 0x12, ++0x06, 0xF5, 0x82, 0x73, 0xC6, 0xF8, 0x14, 0xC0, 0x33, 0x63, 0x44, 0x62, 0xEA, 0x64, 0x06, 0xF1, 0x0C, 0x00, 0x07, 0xF1, ++0x24, 0x02, 0x06, 0xF5, 0x9C, 0x75, 0x53, 0xF8, 0x04, 0x4B, 0x42, 0xF8, 0x04, 0x4F, 0xAB, 0x42, 0xF9, 0xD1, 0x77, 0xB1, ++0x09, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0x33, 0xB9, 0xD6, 0xF8, 0x38, 0x31, 0xDB, 0x6C, 0x14, 0x33, 0x0B, 0x60, 0xF0, 0xBC, ++0x70, 0x47, 0x50, 0x36, 0x0E, 0x60, 0xF0, 0xBC, 0x70, 0x47, 0x01, 0x23, 0x38, 0x46, 0x73, 0x60, 0xF5, 0xE7, 0x00, 0xBF, ++0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x47, 0x6A, 0xD0, 0xF8, 0x4C, 0xE0, 0x85, 0xB0, 0x17, 0xF4, 0x00, 0x1C, ++0x9D, 0xF8, 0x38, 0x90, 0x04, 0x46, 0x0E, 0xF1, 0x14, 0x08, 0x0D, 0x46, 0x16, 0x46, 0x9A, 0x46, 0x2A, 0xD0, 0x07, 0xF4, ++0x60, 0x17, 0xB7, 0xF5, 0x20, 0x1F, 0x40, 0xF0, 0xBB, 0x80, 0xD0, 0xF8, 0x44, 0xB0, 0xBB, 0xF8, 0x04, 0x70, 0x07, 0xF0, ++0x03, 0x07, 0x03, 0x2F, 0x40, 0xF0, 0xB2, 0x80, 0xDF, 0xF8, 0x30, 0xC2, 0x83, 0x4F, 0xDC, 0xF8, 0x00, 0xC0, 0x3F, 0x68, ++0x9C, 0xF8, 0x3E, 0xC0, 0x07, 0xF0, 0x3F, 0x07, 0xBC, 0x45, 0x00, 0xF2, 0xA5, 0x80, 0xDB, 0xF8, 0x24, 0x70, 0x97, 0x42, ++0x40, 0xF2, 0xC1, 0x80, 0x7C, 0x4C, 0xCD, 0xF8, 0x38, 0x90, 0xD4, 0xF8, 0x70, 0x43, 0xA4, 0x46, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x60, 0x47, 0x83, 0x6C, 0x00, 0x2B, 0x00, 0xF0, 0x92, 0x80, 0x5B, 0x6A, 0x13, 0xF0, 0x10, 0x03, 0x00, 0xF0, ++0x8D, 0x80, 0x82, 0x88, 0x00, 0x2A, 0x00, 0xF0, 0x8F, 0x80, 0xC3, 0x8B, 0x1F, 0x07, 0x00, 0xF1, 0x8B, 0x80, 0xDE, 0xF8, ++0x24, 0x10, 0x00, 0x29, 0x00, 0xF0, 0xB9, 0x80, 0x08, 0x88, 0x83, 0xB2, 0x00, 0x04, 0x00, 0xF1, 0xB4, 0x80, 0x6F, 0xEA, ++0x43, 0x43, 0x6F, 0xEA, 0x53, 0x43, 0x0B, 0x80, 0x94, 0xF8, 0x33, 0x20, 0x94, 0xF8, 0x32, 0x30, 0x04, 0x32, 0x04, 0x33, ++0x84, 0xF8, 0x32, 0x30, 0x84, 0xF8, 0x33, 0x20, 0xDE, 0xE9, 0x0A, 0x12, 0xD3, 0x1D, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, ++0x9B, 0xB2, 0x04, 0x32, 0x04, 0x31, 0xB3, 0x42, 0xCE, 0xE9, 0x0A, 0x12, 0x6D, 0xD8, 0xA2, 0x88, 0x32, 0xB1, 0xE3, 0x8B, ++0x1F, 0x07, 0x03, 0xD4, 0x5A, 0x4B, 0xDB, 0x6E, 0x41, 0xF8, 0x03, 0x3C, 0x23, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x36, 0xD0, ++0x11, 0x46, 0xDF, 0xF8, 0x70, 0xB1, 0x54, 0x4F, 0x32, 0x46, 0x00, 0x29, 0x2C, 0xD0, 0xE1, 0x8B, 0x0E, 0x07, 0x29, 0xD4, ++0x99, 0x88, 0x39, 0xB3, 0xD9, 0x8B, 0x08, 0x07, 0x24, 0xD4, 0x4D, 0x49, 0xDB, 0xF8, 0x00, 0x00, 0x09, 0x68, 0x90, 0xF8, ++0x3E, 0x60, 0x01, 0xF0, 0x3F, 0x01, 0x8E, 0x42, 0x1A, 0xD8, 0x5B, 0x6A, 0xBC, 0xF1, 0x00, 0x0F, 0x4C, 0xD1, 0x9B, 0x02, ++0x17, 0xD5, 0xCD, 0xF8, 0x00, 0x90, 0xD7, 0xF8, 0x54, 0x63, 0x03, 0x92, 0x53, 0x46, 0x29, 0x46, 0x20, 0x46, 0xB0, 0x47, ++0x03, 0x9A, 0x00, 0x28, 0x77, 0xD0, 0x2B, 0x68, 0x00, 0x2B, 0x74, 0xD0, 0x60, 0x6A, 0xA1, 0x88, 0x00, 0xF4, 0x00, 0x1C, ++0x00, 0x29, 0xD2, 0xD1, 0xBC, 0xF1, 0x00, 0x0F, 0x47, 0xD1, 0x63, 0x6C, 0xD3, 0xB9, 0x3B, 0x48, 0x11, 0xF0, 0x2C, 0xF8, ++0x3A, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x56, 0xDB, 0x54, 0x23, 0x1C, 0x22, 0x37, 0x48, ++0x13, 0xFB, 0x09, 0x29, 0x00, 0x22, 0x01, 0x23, 0xAA, 0x80, 0xEB, 0x72, 0x48, 0x44, 0x29, 0x46, 0x65, 0x64, 0x10, 0xF0, ++0xF7, 0xFF, 0x01, 0xE0, 0x4F, 0xF0, 0x00, 0x08, 0x40, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDE, 0xF8, 0x2C, 0x30, ++0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x9E, 0x42, 0x9A, 0xD2, 0x25, 0x4B, 0x40, 0x46, 0xD3, 0xF8, ++0xBC, 0x33, 0x49, 0x46, 0x98, 0x47, 0x4F, 0xF0, 0x00, 0x08, 0xE9, 0xE7, 0xCD, 0xF8, 0x00, 0x90, 0x99, 0x02, 0x54, 0xBF, ++0xD7, 0xF8, 0x50, 0x63, 0xD7, 0xF8, 0x4C, 0x63, 0xAF, 0xE7, 0xFE, 0xF7, 0xD1, 0xF9, 0xDB, 0xF8, 0x38, 0x31, 0x67, 0x6A, ++0x1B, 0x68, 0x2B, 0x60, 0x5B, 0xB3, 0xA2, 0x88, 0x07, 0xF4, 0x00, 0x1C, 0x80, 0xE7, 0x63, 0x6C, 0xD3, 0xF8, 0x38, 0x21, ++0x03, 0xF1, 0x0C, 0x08, 0xD2, 0x6C, 0x00, 0x21, 0x40, 0x46, 0xD1, 0x61, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDE, 0xF8, ++0x2C, 0x30, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x9E, 0x42, 0xCC, 0xD3, 0x00, 0x29, 0x3F, 0xF4, ++0x65, 0xAF, 0xDE, 0xF8, 0x28, 0x10, 0x5D, 0xE7, 0x00, 0x28, 0xA6, 0xD1, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF6, 0x92, 0x52, ++0x12, 0xF0, 0xD6, 0xFB, 0x9F, 0xE7, 0x67, 0x6A, 0x07, 0xF4, 0x00, 0x1C, 0x8C, 0xE7, 0x07, 0xF4, 0x00, 0x1C, 0x89, 0xE7, ++0x54, 0x83, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x8C, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x90, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x28, ++0x2C, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x0B, 0x23, 0x13, 0x1B, 0x03, 0x00, 0x1B, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x03, 0x0F, ++0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x17, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x30, 0x0F, 0x0C, 0xBF, 0x01, 0x20, ++0x00, 0x20, 0x08, 0xBD, 0x13, 0x4B, 0x1B, 0x68, 0x13, 0xF4, 0x40, 0x5F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, ++0x0F, 0x4B, 0x1B, 0x68, 0x13, 0xF4, 0x40, 0x3F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x0B, 0x4B, 0x1B, 0x68, ++0x13, 0xF4, 0x40, 0x7F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x01, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xF3, 0x12, 0x12, 0xF0, 0x7E, 0xFB, ++0x00, 0x20, 0x08, 0xBD, 0x88, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x90, 0xF8, 0x25, 0x30, 0xE3, 0xB1, 0x10, 0xB5, 0x0F, 0x4A, 0x10, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x01, 0xF5, ++0x9C, 0x51, 0x84, 0xB0, 0x04, 0x46, 0x08, 0x31, 0x0C, 0x48, 0x98, 0x47, 0x00, 0x21, 0x02, 0x22, 0x05, 0x23, 0x94, 0xF8, ++0x23, 0x00, 0xCD, 0xE9, 0x00, 0x32, 0xCD, 0xE9, 0x02, 0x11, 0x25, 0x23, 0x40, 0xF6, 0xC4, 0x12, 0xFD, 0xF7, 0x5E, 0xFF, ++0x04, 0xB0, 0x10, 0xBD, 0x03, 0x4A, 0xC2, 0xE9, 0x01, 0x33, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x94, 0x64, 0x17, 0x00, 0x03, 0x68, 0x70, 0xB4, 0xC3, 0xF3, 0xC2, 0x24, 0x05, 0x2C, 0x01, 0xD0, 0x70, 0xBC, 0x70, 0x47, ++0xC3, 0xF3, 0x00, 0x26, 0x75, 0x00, 0x03, 0xF0, 0x7F, 0x04, 0x35, 0x44, 0x04, 0xEB, 0x44, 0x04, 0x05, 0xEB, 0x44, 0x04, ++0xC3, 0xF3, 0x41, 0x25, 0x2C, 0x44, 0x16, 0x4D, 0x35, 0xF8, 0x14, 0x50, 0xC3, 0xF3, 0xC0, 0x14, 0x05, 0xFA, 0x04, 0xF4, ++0x01, 0x3A, 0x02, 0xFB, 0x04, 0xF2, 0x8A, 0x42, 0xC3, 0xF3, 0xC1, 0x14, 0xE2, 0xD2, 0x13, 0xF4, 0xE0, 0x3F, 0x06, 0xD0, ++0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x00, 0x43, 0x70, 0xBC, 0x03, 0x60, 0x70, 0x47, 0x03, 0xF0, 0x0F, 0x02, 0x02, 0x2A, ++0x23, 0xF0, 0xFF, 0x53, 0x8C, 0xBF, 0x4F, 0xF4, 0x80, 0x12, 0x4F, 0xF4, 0x00, 0x22, 0x23, 0xF4, 0xFE, 0x13, 0x42, 0xEA, ++0x04, 0x62, 0x13, 0x43, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF4, 0x00, 0x43, 0xE8, 0xE7, 0x00, 0xBF, 0xE0, 0x94, 0x15, 0x00, ++0x70, 0xB5, 0x0C, 0x4D, 0x00, 0xEB, 0x40, 0x03, 0x05, 0xEB, 0x83, 0x03, 0x93, 0xF8, 0x2E, 0x20, 0x72, 0xB1, 0x04, 0x46, ++0x46, 0x00, 0x58, 0x6A, 0x00, 0x22, 0x83, 0xF8, 0x2E, 0x20, 0x10, 0xB1, 0x21, 0x46, 0xFB, 0xF7, 0x35, 0xFF, 0x34, 0x44, ++0x05, 0xEB, 0x84, 0x05, 0x00, 0x23, 0x6B, 0x62, 0x70, 0xBD, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x41, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x41, 0x4F, ++0x41, 0x4E, 0x3B, 0x68, 0xDF, 0xF8, 0x0C, 0x81, 0x01, 0x33, 0x00, 0x24, 0x3B, 0x60, 0x35, 0x46, 0xA2, 0x46, 0x4F, 0xF0, ++0x01, 0x0B, 0x96, 0xF8, 0x60, 0x10, 0x0B, 0xFA, 0x04, 0xF3, 0x0B, 0x42, 0x5F, 0xFA, 0x83, 0xF9, 0x4D, 0xD1, 0x96, 0xF8, ++0x61, 0x10, 0x11, 0xEA, 0x09, 0x0F, 0x30, 0xD0, 0xA8, 0x6A, 0x21, 0xEA, 0x03, 0x03, 0x86, 0xF8, 0x61, 0x30, 0x03, 0x07, ++0x4F, 0xD0, 0x33, 0x4B, 0x43, 0xF8, 0x24, 0x00, 0xE0, 0xB2, 0xD8, 0xF8, 0xD0, 0x33, 0x98, 0x47, 0x95, 0xF8, 0x2C, 0x30, ++0x85, 0xF8, 0x2D, 0x30, 0x49, 0xEA, 0x0A, 0x0A, 0x01, 0x34, 0x04, 0x2C, 0x05, 0xF1, 0x0C, 0x05, 0xD9, 0xD1, 0xBA, 0xF1, ++0x00, 0x0F, 0x47, 0xD0, 0x29, 0x4A, 0x2A, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x29, 0x48, 0x01, 0xF5, 0x00, 0x51, ++0x98, 0x47, 0x3B, 0x68, 0x33, 0xB1, 0x20, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x95, 0xF8, 0x2D, 0x30, 0x00, 0x2B, 0xDE, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x85, 0xF8, ++0x2D, 0x30, 0x5B, 0xB9, 0x32, 0x69, 0xA3, 0x1C, 0xE0, 0xB2, 0x52, 0xF8, 0x23, 0x30, 0x17, 0x4A, 0x42, 0xF8, 0x24, 0x30, ++0xD8, 0xF8, 0xD0, 0x33, 0x98, 0x47, 0xCD, 0xE7, 0x49, 0xEA, 0x0A, 0x0A, 0xCA, 0xE7, 0xE0, 0xB2, 0x01, 0x93, 0xFF, 0xF7, ++0xBD, 0xFE, 0x01, 0x9B, 0x00, 0x28, 0xF5, 0xD0, 0x96, 0xF8, 0x60, 0x10, 0x21, 0xEA, 0x03, 0x01, 0x86, 0xF8, 0x60, 0x10, ++0xA3, 0xE7, 0x95, 0xF8, 0x2E, 0x30, 0x00, 0x2B, 0xB2, 0xD1, 0x85, 0xF8, 0x2E, 0xB0, 0x96, 0xF8, 0x60, 0x30, 0x49, 0xEA, ++0x03, 0x03, 0x86, 0xF8, 0x60, 0x30, 0xA9, 0xE7, 0xC6, 0xF8, 0x18, 0xA0, 0xBD, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0xA8, 0x64, 0x17, 0x00, 0x70, 0xB5, 0x14, 0x4C, 0x94, 0xF8, 0x62, 0x20, 0x4A, 0xB1, 0x94, 0xF8, 0x61, 0x20, 0xA5, 0x69, ++0x01, 0x21, 0x01, 0xFA, 0x00, 0xF3, 0x13, 0x43, 0x84, 0xF8, 0x61, 0x30, 0x05, 0xB1, 0x70, 0xBD, 0x0D, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0xDB, 0x0B, 0x4B, 0x0C, 0x48, 0xD3, 0xF8, 0xC8, 0x33, 0xA3, 0x61, 0xBD, 0xE8, ++0x70, 0x40, 0x18, 0x47, 0xFF, 0xF7, 0x74, 0xFE, 0x00, 0x28, 0xF3, 0xD1, 0xBD, 0xE8, 0x70, 0x40, 0x06, 0x49, 0x07, 0x48, ++0x4F, 0xF4, 0x22, 0x72, 0x12, 0xF0, 0xF4, 0xB9, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xA8, 0x64, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x93, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x1D, 0x4D, 0x1E, 0x4E, ++0x1E, 0x4F, 0xDF, 0xF8, 0x80, 0x80, 0xDF, 0xF8, 0x80, 0x90, 0x2B, 0x68, 0x00, 0x24, 0x01, 0x2C, 0x11, 0xD0, 0x53, 0xF8, ++0x24, 0x30, 0x1B, 0xB9, 0x33, 0x69, 0xA2, 0x1C, 0x53, 0xF8, 0x22, 0x30, 0x47, 0xF8, 0x24, 0x30, 0xE0, 0xB2, 0xFF, 0xF7, ++0xFB, 0xFE, 0x03, 0x2C, 0x0D, 0xD0, 0x01, 0x34, 0x01, 0x2C, 0x2B, 0x68, 0xED, 0xD1, 0x5B, 0x68, 0x73, 0xB9, 0x33, 0x69, ++0xDB, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x01, 0x20, 0xFF, 0xF7, 0xEC, 0xFE, 0xF1, 0xE7, 0x0D, 0x48, 0x08, 0xF0, 0x3C, 0xFC, ++0x00, 0x23, 0xB3, 0x61, 0xBD, 0xE8, 0xF8, 0x83, 0xC3, 0xF3, 0x0B, 0x02, 0x00, 0x2A, 0xEE, 0xD1, 0x32, 0x69, 0xD2, 0x68, ++0x03, 0xEA, 0x09, 0x03, 0xC2, 0xF3, 0x0B, 0x02, 0x13, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0xE6, 0xE7, 0xAC, 0x35, 0x17, 0x00, ++0x94, 0x64, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0xA8, 0x64, 0x17, 0x00, 0x04, 0x02, 0x32, 0x40, 0x00, 0xF0, 0xFF, 0xFF, ++0x1A, 0x4A, 0x1B, 0x4B, 0xF0, 0xB4, 0x02, 0xF1, 0x74, 0x04, 0x94, 0xE8, 0x03, 0x00, 0x16, 0x69, 0xC3, 0xF8, 0xE0, 0x03, ++0xF0, 0x6D, 0xA3, 0xF8, 0xE4, 0x13, 0xB6, 0xF8, 0x60, 0x10, 0xC3, 0xF8, 0xE6, 0x03, 0xA3, 0xF8, 0xEA, 0x13, 0x94, 0xE8, ++0x03, 0x00, 0xD3, 0xF8, 0xD4, 0x53, 0xA3, 0xF8, 0xF0, 0x13, 0xD1, 0x6E, 0xC3, 0xF8, 0xEC, 0x03, 0xC3, 0xF8, 0xF6, 0x13, ++0x0D, 0x4F, 0x0E, 0x48, 0x03, 0xF5, 0x88, 0x64, 0x00, 0x21, 0x82, 0xF8, 0x88, 0x10, 0xC3, 0xF8, 0xBC, 0x43, 0x05, 0xF4, ++0x7F, 0x45, 0x03, 0xF5, 0x66, 0x74, 0x4F, 0xF4, 0x00, 0x52, 0xC3, 0xF8, 0xD4, 0x53, 0xC3, 0xF8, 0x9C, 0x13, 0x3C, 0x60, ++0xF0, 0xBC, 0x02, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x60, 0x5D, 0x18, 0x00, 0xAC, 0x81, 0x32, 0x40, ++0x80, 0x81, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x68, 0xB2, 0x03, 0x68, 0x90, 0x4C, 0xDB, 0xF8, 0x10, 0x20, ++0x80, 0x46, 0x53, 0xF8, 0x26, 0x0F, 0xA0, 0x64, 0xD0, 0x6D, 0x9D, 0x88, 0xC4, 0xF8, 0x4E, 0x00, 0x18, 0x68, 0xB8, 0xF8, ++0x12, 0x10, 0x9B, 0x88, 0xB2, 0xF8, 0x60, 0x20, 0x60, 0x65, 0x00, 0x27, 0x83, 0xB0, 0x04, 0xF1, 0x5C, 0x00, 0xA4, 0xF8, ++0x4C, 0x50, 0xA4, 0xF8, 0x52, 0x20, 0xA4, 0xF8, 0x58, 0x30, 0xA7, 0x61, 0xFE, 0xF7, 0x78, 0xFC, 0x63, 0x6F, 0xD8, 0xF8, ++0x00, 0x10, 0x80, 0x4A, 0x91, 0xF8, 0x23, 0xC0, 0xA5, 0x69, 0xDE, 0x1C, 0x42, 0xF2, 0x38, 0x0E, 0x26, 0xF0, 0x03, 0x06, ++0x24, 0x23, 0x39, 0x46, 0x04, 0x36, 0x13, 0xFB, 0x0C, 0xE7, 0x06, 0xEB, 0x80, 0x06, 0x4F, 0xEA, 0x40, 0x2E, 0x17, 0x44, ++0xB6, 0xB2, 0x89, 0x46, 0x04, 0xF1, 0x5C, 0x02, 0xA4, 0x46, 0x4F, 0xF4, 0x20, 0x10, 0xF2, 0x46, 0x01, 0x97, 0x1C, 0xE0, ++0x0F, 0x33, 0x1B, 0x09, 0x1B, 0x02, 0x43, 0xF0, 0x30, 0x03, 0x9B, 0xB2, 0x4A, 0xEA, 0x00, 0x00, 0x0B, 0x43, 0x90, 0x63, ++0xC2, 0xF8, 0x24, 0x90, 0xC2, 0xF8, 0x3C, 0x90, 0xA2, 0xF8, 0x58, 0x30, 0xCC, 0xF8, 0x08, 0x20, 0xA5, 0x69, 0x35, 0x44, ++0xA5, 0x61, 0x94, 0x46, 0x4F, 0xF4, 0x40, 0x10, 0x01, 0x31, 0x09, 0x29, 0x02, 0xF1, 0x5C, 0x02, 0x22, 0xD0, 0x01, 0x9F, ++0x57, 0xF8, 0x04, 0x3B, 0x01, 0x97, 0x00, 0x2B, 0xF4, 0xD0, 0xD8, 0xF8, 0x08, 0x70, 0x06, 0xEB, 0x05, 0x0E, 0xBE, 0x45, ++0x16, 0xD8, 0xB3, 0xF5, 0x7C, 0x7F, 0xD3, 0xD9, 0xB3, 0xF5, 0x80, 0x6F, 0x0D, 0xD9, 0xB3, 0xF5, 0x86, 0x4F, 0x45, 0xD8, ++0x6F, 0xF4, 0x7C, 0x75, 0x2B, 0x44, 0xC3, 0xF3, 0x07, 0x13, 0x1B, 0x02, 0x43, 0xF4, 0x80, 0x43, 0x43, 0xF0, 0x30, 0x03, ++0xC8, 0xE7, 0x44, 0xF2, 0x30, 0x03, 0xC5, 0xE7, 0x00, 0x2D, 0x3B, 0xD0, 0xDC, 0xF8, 0x38, 0x30, 0x03, 0xF4, 0x60, 0x11, ++0x00, 0x22, 0xB1, 0xF5, 0x20, 0x1F, 0xCC, 0xF8, 0x08, 0x20, 0x63, 0xD0, 0x4C, 0x49, 0x4D, 0x4A, 0x4D, 0x4E, 0x43, 0xF4, ++0x60, 0x13, 0xCC, 0xF8, 0x38, 0x30, 0x0D, 0x68, 0x10, 0x68, 0x04, 0x35, 0xC0, 0xF3, 0x05, 0x20, 0x06, 0xE0, 0x33, 0x68, ++0xDB, 0x04, 0x08, 0xD4, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0x03, 0xF0, 0x3F, 0x03, 0x98, 0x42, ++0xF3, 0xD0, 0xE3, 0x6B, 0x42, 0x48, 0x43, 0x49, 0x43, 0x4A, 0x04, 0x60, 0x03, 0xF4, 0x7F, 0x43, 0xE3, 0x63, 0x4F, 0xF4, ++0x00, 0x50, 0x00, 0x23, 0x08, 0x60, 0x63, 0x60, 0x8B, 0xF8, 0x88, 0x30, 0x62, 0x62, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0xB3, 0xF5, 0x88, 0x4F, 0x1F, 0xD8, 0x48, 0xF2, 0x30, 0x03, 0x87, 0xE7, 0xD4, 0xF8, 0x98, 0x30, 0x37, 0x4A, 0x35, 0x4E, ++0x35, 0x49, 0xC4, 0xF8, 0x94, 0x50, 0x03, 0xF4, 0x7F, 0x43, 0xC4, 0xF8, 0x98, 0x30, 0xA2, 0xF5, 0x79, 0x73, 0xC4, 0xE9, ++0x18, 0x55, 0x8B, 0xF8, 0x88, 0x50, 0x4F, 0xF4, 0x00, 0x50, 0x33, 0x60, 0x30, 0x23, 0x08, 0x60, 0xA4, 0xF8, 0xB4, 0x30, ++0xC4, 0xF8, 0x80, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0xF5, 0x0F, 0x3F, 0x2A, 0xD9, 0xB3, 0xF5, 0x11, 0x3F, ++0x32, 0xD9, 0x28, 0x4D, 0xAB, 0x42, 0x32, 0xD8, 0xA3, 0xF1, 0x01, 0x13, 0xA3, 0xF5, 0x44, 0x43, 0xC3, 0xF3, 0xC7, 0x33, ++0x1B, 0x02, 0x43, 0xF4, 0x40, 0x43, 0x43, 0xF0, 0x30, 0x03, 0x55, 0xE7, 0xDC, 0xF8, 0x3C, 0x30, 0xCC, 0xF8, 0x38, 0x20, ++0xCC, 0xF8, 0x04, 0x20, 0x8B, 0xF8, 0x88, 0x20, 0x19, 0x48, 0x1A, 0x49, 0x1A, 0x4A, 0xCC, 0xF8, 0x24, 0x20, 0x03, 0xF4, ++0x7F, 0x43, 0xCC, 0xF8, 0x3C, 0x30, 0x4F, 0xF4, 0x00, 0x53, 0xC0, 0xF8, 0x00, 0xC0, 0x0B, 0x60, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0xA3, 0xF5, 0x70, 0x53, 0x01, 0x3B, 0xC3, 0xF3, 0xC7, 0x23, 0x1B, 0x02, 0x43, 0xF4, 0x00, 0x43, 0x43, 0xF0, ++0x30, 0x03, 0x31, 0xE7, 0x4C, 0xF2, 0x30, 0x03, 0x2E, 0xE7, 0x4F, 0xF6, 0x30, 0x65, 0x4F, 0xF6, 0x30, 0x77, 0xB3, 0xF1, ++0xFF, 0x3F, 0x08, 0xBF, 0x3D, 0x46, 0x2B, 0x46, 0x24, 0xE7, 0x00, 0xBF, 0x60, 0x5D, 0x18, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x20, 0x01, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x78, 0x80, 0x32, 0x40, 0xAC, 0x81, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, ++0xA0, 0x61, 0x18, 0x00, 0x00, 0xC4, 0x20, 0x00, 0x94, 0x64, 0x17, 0x00, 0x1C, 0x4A, 0x1D, 0x49, 0x13, 0x68, 0xF0, 0xB4, ++0x03, 0xF5, 0xDA, 0x53, 0x1B, 0x4F, 0x1C, 0x4E, 0x1C, 0x4C, 0x1D, 0x4D, 0x18, 0x33, 0x3B, 0x60, 0x40, 0x23, 0x33, 0x60, ++0x23, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x23, 0x60, 0x17, 0x68, 0x0C, 0x68, 0x01, 0x23, 0x10, 0x3E, 0x04, 0x37, 0xC4, 0xF3, ++0x05, 0x24, 0x85, 0xF8, 0x8C, 0x30, 0x06, 0xE0, 0x33, 0x68, 0xDB, 0x04, 0x08, 0xD4, 0x13, 0x68, 0xDB, 0x1B, 0x00, 0x2B, ++0x04, 0xDA, 0x0B, 0x68, 0x03, 0xF0, 0x3F, 0x03, 0x9C, 0x42, 0xF3, 0xD0, 0xC3, 0x6B, 0x0E, 0x4C, 0x0E, 0x4A, 0x0F, 0x49, ++0x42, 0x62, 0x03, 0xF4, 0x7F, 0x43, 0xC3, 0x63, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x53, 0x42, 0x60, 0x85, 0xF8, 0x88, 0x20, ++0x20, 0x60, 0xF0, 0xBC, 0x0B, 0x60, 0x70, 0x47, 0x20, 0x01, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x40, 0x01, 0x32, 0x40, ++0x88, 0x80, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0xAC, 0x81, 0x32, 0x40, 0xA0, 0x61, 0x18, 0x00, ++0x80, 0x81, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x10, 0x4F, 0x0C, 0x23, 0x0E, 0x46, 0x54, 0x25, 0x04, 0x46, 0x15, 0xFB, ++0x01, 0x30, 0x05, 0xFB, 0x06, 0x75, 0x38, 0x44, 0xD4, 0xF8, 0x4C, 0x80, 0x10, 0xF0, 0xEC, 0xFB, 0x95, 0xF8, 0x50, 0x30, ++0xA2, 0x88, 0x01, 0x3B, 0x85, 0xF8, 0x50, 0x30, 0x22, 0xB9, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFD, 0xF7, 0x22, 0xBA, ++0xD8, 0xF8, 0x50, 0x10, 0x32, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFC, 0xF7, 0xF6, 0xBB, 0x20, 0x62, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x00, 0x23, 0x2E, 0x4D, 0x03, 0x60, 0x95, 0xF8, 0x8C, 0x30, 0x82, 0xB0, 0x00, 0x2B, 0x37, 0xD1, ++0x95, 0xF8, 0x85, 0x30, 0x03, 0x2B, 0x33, 0xD8, 0x29, 0x4E, 0xDF, 0xF8, 0xB4, 0xA0, 0x81, 0x46, 0x4F, 0xF0, 0x03, 0x08, ++0x14, 0xE0, 0x95, 0xF8, 0x7E, 0x30, 0xDA, 0xF8, 0x64, 0x73, 0x00, 0x93, 0x2A, 0x6F, 0xB5, 0xF8, 0x7A, 0x30, 0x49, 0x46, ++0x20, 0x46, 0xB8, 0x47, 0x07, 0x46, 0x20, 0xBB, 0x95, 0xF8, 0x85, 0x30, 0x08, 0xF1, 0xFF, 0x38, 0x98, 0x45, 0xA6, 0xF1, ++0x54, 0x06, 0x17, 0xDB, 0x96, 0xF8, 0x16, 0x31, 0x5F, 0xFA, 0x88, 0xF7, 0x01, 0x2B, 0x85, 0xF8, 0x7E, 0x70, 0x0F, 0xD0, ++0xD6, 0xF8, 0x08, 0x41, 0x00, 0x2C, 0xEB, 0xD0, 0x63, 0x6A, 0x9B, 0x02, 0xDB, 0xD4, 0xE3, 0x6C, 0x1B, 0x6D, 0x00, 0x2B, ++0xD7, 0xDA, 0x20, 0x46, 0x39, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xEF, 0xE7, 0x00, 0x27, 0x38, 0x46, 0x02, 0xB0, 0xBD, 0xE8, ++0xF0, 0x87, 0x0E, 0x4B, 0x64, 0x6C, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0xDB, 0xA3, 0x88, 0x38, 0x46, ++0x43, 0xF4, 0x00, 0x73, 0xA3, 0x80, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x2C, 0xF5, 0xD1, 0x06, 0x49, 0x07, 0x48, ++0x40, 0xF2, 0xDF, 0x42, 0x11, 0xF0, 0x88, 0xFF, 0xEE, 0xE7, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xDF, 0xF8, 0x8C, 0x92, 0x99, 0xF8, 0x7E, 0x80, 0x83, 0xB0, 0x04, 0x46, 0x00, 0x27, 0x40, 0x46, 0x01, 0x97, 0xFB, 0xF7, ++0x0D, 0xFE, 0x99, 0xF8, 0x7E, 0x00, 0xFF, 0xF7, 0x15, 0xFA, 0x00, 0x2C, 0x00, 0xF0, 0xA4, 0x80, 0x63, 0x6A, 0x9E, 0x02, ++0x76, 0xD5, 0x03, 0xF4, 0x60, 0x10, 0xB0, 0xF5, 0x60, 0x1F, 0x65, 0x6C, 0x00, 0xF0, 0xE1, 0x80, 0xB0, 0xF5, 0x40, 0x1F, ++0x00, 0xF0, 0xCE, 0x80, 0xAA, 0x88, 0x02, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0x8E, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x01, 0xC0, ++0x00, 0xF0, 0xFF, 0x80, 0x2A, 0x6B, 0x52, 0x69, 0x00, 0x21, 0xC2, 0xF3, 0xC1, 0x1E, 0xC5, 0xE9, 0x0E, 0x11, 0x69, 0x63, ++0x0E, 0x46, 0x0A, 0x46, 0x14, 0xE0, 0xD1, 0xF8, 0x4C, 0x31, 0x9A, 0x45, 0x02, 0xF1, 0x01, 0x03, 0x22, 0xD9, 0xDA, 0xB2, ++0x05, 0xEB, 0x82, 0x03, 0xB0, 0xF5, 0x60, 0x1F, 0x4E, 0x63, 0x56, 0x46, 0xC3, 0xF8, 0x3C, 0x41, 0x20, 0xD0, 0x24, 0x68, ++0x34, 0xB3, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x10, 0xE1, 0x6C, 0xD1, 0xF8, 0x2C, 0xA0, 0xC3, 0xF3, 0x49, 0x2B, 0x0A, 0xF1, ++0x03, 0x03, 0x23, 0xF0, 0x03, 0x03, 0x0B, 0xF1, 0x01, 0x0A, 0x03, 0xEB, 0x8A, 0x03, 0x9B, 0xB2, 0x96, 0x45, 0x05, 0xEB, ++0x82, 0x01, 0x03, 0xEB, 0x06, 0x0A, 0xD6, 0xD8, 0x05, 0xEB, 0x82, 0x03, 0xB0, 0xF5, 0x60, 0x1F, 0x56, 0x46, 0xC3, 0xF8, ++0x3C, 0x41, 0xDE, 0xD1, 0x6B, 0x6A, 0xB3, 0x42, 0x00, 0xF0, 0xCE, 0x80, 0x00, 0x23, 0xC5, 0xE9, 0x0D, 0x33, 0xEB, 0x63, ++0x00, 0x2F, 0x49, 0xD0, 0x08, 0xEB, 0x48, 0x03, 0x09, 0xEB, 0x83, 0x09, 0x01, 0x9A, 0xC9, 0xF8, 0x24, 0x70, 0xBC, 0xF1, ++0x00, 0x0F, 0x30, 0xD1, 0x93, 0x6B, 0x9B, 0x02, 0x00, 0xF1, 0x97, 0x80, 0x53, 0x68, 0x00, 0x2B, 0x4B, 0xD1, 0x61, 0x49, ++0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x01, 0xEB, 0x08, 0x03, 0xC3, 0xE9, 0x01, 0xCC, 0x41, 0xF8, 0x08, 0x20, 0x40, 0xE0, ++0xA3, 0x6C, 0x3B, 0xB3, 0xE3, 0x8B, 0xE2, 0x6C, 0x13, 0xF4, 0x00, 0x5F, 0xE3, 0x6A, 0xDB, 0x6B, 0x02, 0xF1, 0x14, 0x07, ++0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0x01, 0x97, 0x93, 0xB3, 0x52, 0x4B, 0x1B, 0x68, 0x93, 0xF8, ++0x01, 0xC0, 0x3A, 0x46, 0x08, 0xEB, 0x48, 0x03, 0x09, 0xEB, 0x83, 0x09, 0xC9, 0xF8, 0x24, 0x70, 0xBC, 0xF1, 0x00, 0x0F, ++0xCE, 0xD0, 0x53, 0x68, 0xFB, 0xB9, 0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x49, 0x4B, 0x43, 0xF8, 0x08, 0x20, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x45, 0x4B, 0x1B, 0x68, 0x93, 0xF8, 0x01, 0xC0, 0x44, 0x4B, 0x54, 0x22, 0x08, 0xEB, 0x48, 0x01, ++0x09, 0xEB, 0x81, 0x09, 0x02, 0xFB, 0x08, 0xF8, 0x00, 0x22, 0x43, 0xF8, 0x08, 0x20, 0xC9, 0xF8, 0x24, 0x20, 0x43, 0x44, ++0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0xC3, 0xE9, 0x01, 0xCC, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x50, 0x6A, 0x03, 0x88, ++0x1D, 0x04, 0x99, 0xB2, 0xC7, 0xD5, 0xC1, 0xF3, 0x0E, 0x01, 0x01, 0x80, 0x94, 0xF8, 0x33, 0x10, 0x94, 0xF8, 0x32, 0x30, ++0x32, 0x48, 0x04, 0x39, 0x04, 0x3B, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x32, 0x30, 0xD2, 0xE9, 0x0A, 0x31, 0x04, 0x39, ++0x04, 0x3B, 0xC2, 0xE9, 0x0A, 0x31, 0x00, 0x68, 0x3A, 0x46, 0x90, 0xF8, 0x01, 0xC0, 0xB3, 0xE7, 0x2B, 0x4B, 0x01, 0xA9, ++0xD3, 0xF8, 0x6C, 0x33, 0x20, 0x46, 0x98, 0x47, 0x26, 0x4A, 0x63, 0x6A, 0x12, 0x68, 0x07, 0x46, 0x92, 0xF8, 0x01, 0xC0, ++0x03, 0xF4, 0x60, 0x10, 0x2C, 0xE7, 0x24, 0x4B, 0x21, 0x4E, 0xD3, 0xF8, 0x58, 0x33, 0x39, 0x46, 0x20, 0x46, 0x98, 0x47, ++0x33, 0x68, 0x01, 0x90, 0x5B, 0x78, 0x07, 0x46, 0xD3, 0xB1, 0x08, 0xB1, 0x6B, 0x6D, 0x43, 0x60, 0xD5, 0xF8, 0x48, 0x01, ++0x29, 0x46, 0x10, 0xF0, 0x13, 0xFA, 0x33, 0x68, 0x93, 0xF8, 0x01, 0xC0, 0x58, 0xE7, 0x7B, 0x68, 0x00, 0x2B, 0xB4, 0xD1, ++0x15, 0x49, 0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x01, 0xEB, 0x08, 0x03, 0x01, 0x20, 0xC3, 0xE9, 0x01, 0x70, 0x41, 0xF8, ++0x08, 0x20, 0xA8, 0xE7, 0x00, 0x28, 0xE5, 0xD0, 0x2B, 0x69, 0x43, 0x60, 0xE2, 0xE7, 0x05, 0xF1, 0x0C, 0x07, 0xBC, 0xF1, ++0x00, 0x0F, 0x03, 0xD0, 0x05, 0xF1, 0x50, 0x02, 0x01, 0x92, 0xF7, 0xE6, 0xD5, 0xF8, 0x38, 0x21, 0xD2, 0x6C, 0x14, 0x32, ++0x01, 0x92, 0xF1, 0xE6, 0xD5, 0xF8, 0x38, 0x31, 0xA3, 0x42, 0x7F, 0xF4, 0x2D, 0xAF, 0x05, 0xEB, 0x82, 0x02, 0x56, 0x63, ++0x2C, 0xE7, 0x00, 0xBF, 0x34, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x70, 0xB5, 0x1E, 0x48, 0x82, 0xB0, 0x90, 0xF8, 0x88, 0x30, 0x00, 0x22, 0x01, 0x92, 0x93, 0xB1, 0x90, 0xF8, 0x7F, 0x30, ++0x04, 0x2B, 0x2A, 0xD0, 0x19, 0x4C, 0x01, 0xA8, 0xD4, 0xF8, 0xE8, 0x33, 0x98, 0x47, 0x08, 0xB3, 0xD4, 0xF8, 0xF8, 0x33, ++0x98, 0x47, 0xD4, 0xF8, 0xD4, 0x33, 0x01, 0x98, 0x98, 0x47, 0x02, 0xB0, 0x70, 0xBD, 0x13, 0x4A, 0x13, 0x4D, 0xD2, 0xF8, ++0x38, 0x14, 0x13, 0x4C, 0x80, 0xF8, 0x88, 0x30, 0xC2, 0xF8, 0x00, 0x34, 0x01, 0xF4, 0x7F, 0x41, 0x02, 0xF5, 0x88, 0x66, ++0x02, 0xF5, 0x7F, 0x70, 0x4F, 0xF4, 0x00, 0x53, 0xC2, 0xF8, 0x38, 0x14, 0xC2, 0xF8, 0x20, 0x64, 0x28, 0x60, 0x23, 0x60, ++0x02, 0xB0, 0x70, 0xBD, 0xFF, 0xF7, 0x28, 0xFC, 0xE1, 0xE7, 0x04, 0x4B, 0x68, 0x30, 0xD3, 0xF8, 0xF4, 0x33, 0x98, 0x47, ++0x02, 0xB0, 0x70, 0xBD, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x60, 0x5D, 0x18, 0x00, 0xAC, 0x81, 0x32, 0x40, ++0x80, 0x81, 0x32, 0x40, 0xF8, 0xB5, 0x2C, 0x4C, 0x2C, 0x4D, 0x40, 0xF2, 0x74, 0x42, 0x20, 0x46, 0x00, 0x21, 0x26, 0x46, ++0xED, 0xF7, 0xF4, 0xF8, 0x4F, 0xF4, 0xE4, 0x73, 0x28, 0x4A, 0x26, 0xF8, 0x44, 0x3F, 0x4F, 0xF6, 0x30, 0x70, 0x48, 0xF2, ++0xC8, 0x13, 0x04, 0xF5, 0x77, 0x77, 0x4F, 0xF0, 0x22, 0x0C, 0x04, 0xF2, 0xFD, 0x31, 0xC4, 0xF8, 0x40, 0x24, 0xA4, 0xF8, ++0xDC, 0x33, 0xA4, 0xF8, 0xF4, 0x03, 0x04, 0xF5, 0x88, 0x63, 0x00, 0x20, 0x4F, 0xF4, 0x00, 0x12, 0xDF, 0xF8, 0x74, 0xE0, ++0xC4, 0xF8, 0xB0, 0xC3, 0xC4, 0xE9, 0xEA, 0x71, 0xC4, 0xF8, 0xBC, 0x33, 0xC4, 0xF8, 0x20, 0x34, 0x63, 0x62, 0xA2, 0x63, ++0xC4, 0xF8, 0x98, 0x53, 0xC4, 0xF8, 0xFC, 0x53, 0x25, 0x60, 0xC4, 0xF8, 0xA4, 0x03, 0xC4, 0xF8, 0xCC, 0x03, 0xC4, 0xF8, ++0x30, 0x04, 0x04, 0xF1, 0x5B, 0x0C, 0x04, 0xF1, 0xB4, 0x03, 0x1E, 0x27, 0x04, 0xF5, 0x7C, 0x74, 0xA3, 0xF1, 0x14, 0x01, ++0x5A, 0x1C, 0x43, 0xF8, 0x58, 0x5C, 0x43, 0xF8, 0x40, 0x7C, 0x43, 0xF8, 0x24, 0x0C, 0x43, 0xF8, 0x14, 0xEC, 0x43, 0xF8, ++0x4C, 0x1C, 0x43, 0xF8, 0x08, 0x2C, 0x43, 0xE9, 0x12, 0x6C, 0x43, 0xF8, 0x0C, 0x3C, 0x5C, 0x33, 0x9C, 0x42, 0xE9, 0xD1, ++0xF8, 0xBD, 0x00, 0xBF, 0x60, 0x5D, 0x18, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, 0x1E, 0xAB, 0xDC, 0xBA, 0xDE, 0xFA, 0xFE, 0xCA, ++0x2D, 0xE9, 0xF0, 0x41, 0x13, 0x4A, 0x14, 0x4B, 0x92, 0xF8, 0x7E, 0x40, 0xD3, 0xF8, 0xAC, 0x33, 0x12, 0x4F, 0x00, 0x22, ++0x0E, 0x46, 0x21, 0x46, 0x05, 0x46, 0x4F, 0xF0, 0x54, 0x08, 0x98, 0x47, 0x0C, 0x20, 0x18, 0xFB, 0x04, 0x00, 0x38, 0x44, ++0x10, 0xF0, 0x5E, 0xF9, 0x22, 0x46, 0x31, 0x46, 0x28, 0x46, 0xFC, 0xF7, 0x77, 0xF9, 0x6B, 0x6A, 0x03, 0xF4, 0x60, 0x13, ++0xB3, 0xF5, 0x60, 0x1F, 0x05, 0xD1, 0x08, 0xFB, 0x04, 0x74, 0x6B, 0x6C, 0x63, 0x62, 0x02, 0x23, 0xA3, 0x76, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x90, 0xF8, 0x62, 0x40, 0x87, 0xB0, 0x84, 0xB9, 0x90, 0xF8, 0x64, 0x30, 0x6B, 0xB1, 0x90, 0xF8, 0x6C, 0x30, 0x58, 0x4A, ++0x01, 0x93, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x03, 0x25, 0x95, 0xF8, 0x25, 0x30, 0x13, 0xB1, 0x6B, 0x68, 0x9B, 0x06, ++0x02, 0xD4, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x10, 0x22, 0x21, 0x46, 0x02, 0xA8, 0xED, 0xF7, 0x4D, 0xF8, 0x95, 0xF8, ++0x23, 0x30, 0x4E, 0x4A, 0x4E, 0x49, 0x00, 0x94, 0x42, 0xF2, 0x34, 0x06, 0x03, 0xEB, 0xC3, 0x03, 0x06, 0xEB, 0x83, 0x03, ++0x9E, 0x18, 0x01, 0xF1, 0x08, 0x0B, 0xA6, 0x46, 0x22, 0x46, 0xA2, 0x46, 0x20, 0x46, 0x56, 0xF8, 0x04, 0x3F, 0xB3, 0xF5, ++0xFE, 0x0F, 0x1F, 0x46, 0x04, 0xF1, 0x01, 0x08, 0x28, 0xBF, 0x4F, 0xF4, 0xFE, 0x07, 0xF3, 0xB1, 0x42, 0x4C, 0x0B, 0x78, ++0xE3, 0x5C, 0x06, 0xAC, 0x04, 0xEB, 0x83, 0x0C, 0x22, 0xFA, 0x03, 0xF9, 0x5C, 0xF8, 0x10, 0x5C, 0x3D, 0x44, 0x55, 0x45, ++0x84, 0xBF, 0xAA, 0x46, 0x00, 0x93, 0x19, 0xF0, 0x01, 0x0F, 0x5F, 0xFA, 0x88, 0xF4, 0x38, 0x44, 0x4C, 0xF8, 0x10, 0x5C, ++0x07, 0xD1, 0x01, 0x25, 0x05, 0xFA, 0x03, 0xF3, 0x1A, 0x43, 0xAE, 0x44, 0xD2, 0xB2, 0x5F, 0xFA, 0x8E, 0xFE, 0x01, 0x31, ++0x8B, 0x45, 0xD2, 0xD1, 0x08, 0x2C, 0x41, 0xD0, 0xA4, 0xEB, 0x0E, 0x04, 0xE4, 0xB2, 0xA4, 0x02, 0x92, 0x01, 0xB0, 0xF5, ++0x7D, 0x6F, 0x1E, 0xD8, 0x0F, 0x30, 0x0A, 0xF1, 0x0F, 0x0A, 0xC0, 0xF3, 0x07, 0x13, 0xCA, 0xF3, 0x07, 0x1A, 0x00, 0x21, ++0x00, 0x98, 0x1B, 0x06, 0x43, 0xEA, 0x00, 0x33, 0x13, 0x43, 0x23, 0x43, 0x0B, 0x43, 0x01, 0x99, 0x08, 0x46, 0x21, 0x49, ++0x4F, 0xF4, 0x1E, 0x72, 0x43, 0xEA, 0x0A, 0x43, 0x02, 0xFB, 0x00, 0x12, 0x43, 0xF0, 0x0F, 0x03, 0xC2, 0xF8, 0x04, 0x32, ++0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB0, 0xF5, 0x7D, 0x4F, 0x0D, 0xD9, 0xB0, 0xF5, 0xFD, 0x2F, 0x18, 0xD8, 0x00, 0xF2, ++0xFF, 0x70, 0x0A, 0xF2, 0xFF, 0x7A, 0xC0, 0xF3, 0xC7, 0x23, 0xCA, 0xF3, 0xC7, 0x2A, 0x4F, 0xF4, 0x00, 0x41, 0xD7, 0xE7, ++0xFF, 0x30, 0x0A, 0xF1, 0xFF, 0x0A, 0xC0, 0xF3, 0x07, 0x23, 0xCA, 0xF3, 0x07, 0x2A, 0x4F, 0xF4, 0x80, 0x41, 0xCD, 0xE7, ++0x4F, 0xF4, 0x40, 0x64, 0x00, 0x22, 0xBE, 0xE7, 0x47, 0xF6, 0xFF, 0x73, 0xBA, 0xF5, 0xFE, 0x0F, 0x94, 0xBF, 0x9A, 0x44, ++0x03, 0xF5, 0xFE, 0x0A, 0xB0, 0xF5, 0xFE, 0x0F, 0x94, 0xBF, 0x18, 0x18, 0x03, 0xF5, 0xFE, 0x00, 0xC0, 0xF3, 0xC7, 0x33, ++0xCA, 0xF3, 0xC7, 0x3A, 0x4F, 0xF4, 0x40, 0x41, 0xB4, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0xC0, 0xB2, 0x15, 0x00, 0xA0, 0xB2, 0x15, 0x00, 0x49, 0x4B, 0x4A, 0x4A, 0x4F, 0xF4, 0x80, 0x11, 0x2D, 0xE9, 0xF0, 0x47, ++0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x1F, 0xFB, 0xD1, 0xDF, 0xF8, 0x34, 0x81, 0x45, 0x4A, 0x98, 0xF8, 0x8C, 0x30, ++0x4F, 0xF4, 0x80, 0x11, 0x11, 0x60, 0x00, 0x2B, 0x6E, 0xD0, 0x98, 0xF8, 0x7E, 0x60, 0xDF, 0xF8, 0x20, 0x91, 0x54, 0x23, ++0x03, 0xFB, 0x06, 0x93, 0x9A, 0x7E, 0x00, 0x2A, 0x38, 0xD0, 0x54, 0x20, 0x00, 0xFB, 0x06, 0x94, 0x20, 0x46, 0x62, 0x6A, ++0x93, 0x88, 0x43, 0xF0, 0x10, 0x03, 0x93, 0x80, 0x1C, 0x30, 0x10, 0xF0, 0x55, 0xF8, 0x37, 0x4B, 0x53, 0xF8, 0x26, 0x00, ++0x0F, 0xF0, 0x6A, 0xFF, 0x00, 0x23, 0xA3, 0x76, 0x63, 0x62, 0x06, 0xEB, 0x46, 0x04, 0x08, 0xEB, 0x84, 0x04, 0x94, 0xF8, ++0x2E, 0x50, 0x2D, 0xB9, 0x60, 0x6A, 0x18, 0xB1, 0x31, 0x46, 0xFB, 0xF7, 0x93, 0xF8, 0x65, 0x62, 0x2D, 0x4A, 0x2E, 0x49, ++0x13, 0x68, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x99, 0x40, 0x22, 0x0A, 0x60, 0x99, 0xF8, ++0x50, 0x30, 0x00, 0x22, 0x01, 0x3B, 0x30, 0x46, 0x89, 0xF8, 0x50, 0x30, 0x88, 0xF8, 0x8C, 0x20, 0xBD, 0xE8, 0xF0, 0x47, ++0xFE, 0xF7, 0x66, 0xBE, 0xDC, 0x68, 0x62, 0x6A, 0x92, 0x02, 0x2D, 0xD4, 0x54, 0x25, 0xDF, 0xF8, 0x98, 0xA0, 0x20, 0x4F, ++0x05, 0xFB, 0x06, 0x95, 0x11, 0xE0, 0xE3, 0x6C, 0x62, 0x6A, 0x19, 0x6D, 0x41, 0xF0, 0x00, 0x41, 0x41, 0xF4, 0x80, 0x01, ++0x19, 0x65, 0x93, 0x02, 0x20, 0x46, 0x17, 0xD5, 0xD7, 0xF8, 0xD8, 0x33, 0x98, 0x47, 0xAB, 0x7E, 0xEC, 0x68, 0x00, 0x2B, ++0xA9, 0xD1, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE7, 0xDA, 0x00, 0x2C, 0xE5, 0xD1, 0x12, 0x49, ++0x12, 0x48, 0x40, 0xF2, 0xB3, 0x72, 0x11, 0xF0, 0x0D, 0xFC, 0xDE, 0xE7, 0xBD, 0xE8, 0xF0, 0x87, 0xD7, 0xF8, 0xE4, 0x33, ++0x98, 0x47, 0xA8, 0xE7, 0x5A, 0x69, 0x61, 0x6C, 0x52, 0x6C, 0x8A, 0x42, 0xCC, 0xD1, 0xD2, 0xF8, 0x38, 0x21, 0x12, 0x68, ++0x5A, 0x61, 0xC7, 0xE7, 0x80, 0x81, 0x32, 0x40, 0x88, 0x81, 0x32, 0x40, 0x84, 0x81, 0x32, 0x40, 0xC4, 0x90, 0x15, 0x00, ++0x8C, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, ++0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x69, 0x4F, 0xDF, 0xF8, ++0xCC, 0x81, 0x97, 0xF8, 0x7E, 0x60, 0x54, 0x25, 0x05, 0xFB, 0x06, 0x85, 0xAB, 0x7E, 0x53, 0xBB, 0xDF, 0xF8, 0xA0, 0xA1, ++0xDF, 0xF8, 0xAC, 0x91, 0x15, 0xE0, 0xD4, 0xF8, 0x4C, 0xC0, 0xDF, 0xF8, 0xA0, 0xE1, 0xDC, 0xF8, 0x50, 0x30, 0x43, 0xF4, ++0x80, 0x02, 0x00, 0x2B, 0x20, 0x46, 0x11, 0x46, 0x26, 0xDA, 0x63, 0x6A, 0xCC, 0xF8, 0x50, 0x20, 0x9C, 0x02, 0x23, 0xD5, ++0xDE, 0xF8, 0xD8, 0x33, 0x98, 0x47, 0xAB, 0x7E, 0x7B, 0xB9, 0xDA, 0xF8, 0x00, 0x30, 0xEC, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xE2, 0xDA, 0x00, 0x2C, 0xE0, 0xD1, 0x53, 0x48, 0x4F, 0xF4, 0x02, 0x62, 0x49, 0x46, 0x11, 0xF0, 0xAE, 0xFB, ++0xD9, 0xE7, 0x54, 0x22, 0x02, 0xFB, 0x06, 0x82, 0x02, 0x2B, 0x54, 0x6A, 0x0C, 0xBF, 0x04, 0xF1, 0x0C, 0x03, 0x04, 0xF1, ++0x50, 0x03, 0xDB, 0x6B, 0x00, 0x2B, 0x29, 0xDB, 0xBD, 0xE8, 0xF0, 0x87, 0xDE, 0xF8, 0xE4, 0x33, 0x98, 0x47, 0x06, 0xEB, ++0x46, 0x04, 0x07, 0xEB, 0x84, 0x04, 0x94, 0xF8, 0x2E, 0x50, 0x2D, 0xB9, 0x60, 0x6A, 0x18, 0xB1, 0x31, 0x46, 0xFA, 0xF7, ++0xD1, 0xFF, 0x65, 0x62, 0x41, 0x4A, 0x42, 0x49, 0x13, 0x68, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x54, 0x23, 0x03, 0xFB, ++0x06, 0x88, 0x40, 0x22, 0x0A, 0x60, 0x98, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x3B, 0x30, 0x46, 0x88, 0xF8, 0x50, 0x30, ++0x87, 0xF8, 0x8C, 0x20, 0xBD, 0xE8, 0xF0, 0x47, 0xFE, 0xF7, 0xA4, 0xBD, 0x18, 0x02, 0x35, 0xD5, 0xA3, 0x88, 0x99, 0x06, ++0x13, 0xD4, 0xDF, 0xF8, 0xE0, 0x90, 0xD9, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x04, 0x25, 0xA3, 0x88, 0x9A, 0x06, 0x0A, 0xD4, ++0xD9, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x01, 0x3D, 0xF7, 0xD1, 0x2E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x42, 0xDB, 0x97, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x37, 0xD0, 0x2A, 0x49, 0x97, 0xF8, 0x64, 0x30, 0x0A, 0x68, 0x1B, 0x06, ++0x22, 0xF0, 0xE0, 0x62, 0x03, 0xF0, 0xE0, 0x63, 0x13, 0x43, 0x0B, 0x60, 0xA3, 0x88, 0x25, 0x4A, 0x43, 0xF0, 0x10, 0x03, ++0x52, 0xF8, 0x26, 0x00, 0xA3, 0x80, 0x0F, 0xF0, 0x4F, 0xFE, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x83, 0x00, 0x22, 0x9A, 0x76, ++0x5A, 0x62, 0xA2, 0xE7, 0x54, 0x20, 0x00, 0xFB, 0x06, 0x80, 0x1C, 0x30, 0x0F, 0xF0, 0x28, 0xFF, 0x97, 0xF8, 0x87, 0x30, ++0x00, 0x2B, 0xE5, 0xD0, 0x17, 0x4A, 0x97, 0xF8, 0x65, 0x00, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, 0x02, 0x63, 0x01, 0x33, ++0x83, 0x42, 0x28, 0xBF, 0x03, 0x46, 0x1B, 0x06, 0x03, 0xF0, 0xE0, 0x63, 0x21, 0xF0, 0xE0, 0x61, 0x0B, 0x43, 0x13, 0x60, ++0xD2, 0xE7, 0x10, 0x4B, 0x97, 0xF8, 0x7E, 0x00, 0xD3, 0xF8, 0xC0, 0x33, 0x98, 0x47, 0xCB, 0xE7, 0xA3, 0x88, 0x9B, 0x06, ++0xB9, 0xD4, 0xBD, 0xE8, 0xF0, 0x47, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0x6A, 0x02, 0x11, 0xF0, 0xDD, 0xBA, 0x00, 0xBF, ++0x94, 0x64, 0x17, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x54, 0x83, 0x32, 0x40, 0xC4, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD4, 0x8E, 0x15, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x10, 0xB5, 0x0D, 0x4C, 0x90, 0x22, 0x00, 0x21, 0x20, 0x46, 0xEC, 0xF7, 0x09, 0xFE, 0xFF, 0xF7, ++0x09, 0xFD, 0x40, 0xF2, 0xD3, 0x13, 0xE3, 0x66, 0xED, 0xF7, 0xA4, 0xFE, 0x07, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x70, 0x43, ++0x18, 0xB1, 0x43, 0xF0, 0x30, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x43, 0xF0, 0x10, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, ++0x94, 0x64, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x43, 0x2A, 0x4C, 0x65, 0x68, 0x95, 0xB0, 0x00, 0x2D, ++0x44, 0xD0, 0x29, 0x4E, 0xA7, 0x68, 0xD6, 0xF8, 0xD8, 0x31, 0x20, 0x46, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0x80, 0xB8, 0xF1, ++0x00, 0x0F, 0x26, 0xD0, 0x01, 0x25, 0x24, 0x49, 0x68, 0x46, 0x50, 0x22, 0x23, 0xF0, 0x66, 0xFD, 0xA3, 0x69, 0x94, 0xF8, ++0x62, 0x90, 0x23, 0xB1, 0x1E, 0x4E, 0x1F, 0x48, 0xD6, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xFF, 0xF7, 0xBD, 0xFF, 0xC4, 0xF8, ++0x10, 0x80, 0x84, 0xF8, 0x62, 0x90, 0x18, 0x4C, 0x6B, 0x46, 0x22, 0x46, 0x0C, 0xAE, 0x58, 0x69, 0x19, 0x7E, 0x90, 0x62, ++0x0C, 0x33, 0xB3, 0x42, 0x82, 0xF8, 0x2C, 0x10, 0x02, 0xF1, 0x0C, 0x02, 0xF5, 0xD1, 0xFD, 0xB9, 0x15, 0xB0, 0xBD, 0xE8, ++0xF0, 0x83, 0xFF, 0xF7, 0xA5, 0xFF, 0xC4, 0xF8, 0x10, 0x80, 0x10, 0x4B, 0x10, 0x4A, 0x19, 0x69, 0x0B, 0x48, 0xD6, 0xF8, ++0xE0, 0x31, 0xA7, 0x60, 0x01, 0xF5, 0x9C, 0x51, 0x08, 0x31, 0x62, 0x60, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, ++0xD4, 0xF8, 0x10, 0x80, 0xB8, 0xF1, 0x00, 0x0F, 0xC1, 0xD1, 0xFF, 0xF7, 0x8D, 0xFF, 0xC4, 0xF8, 0x10, 0x80, 0xDF, 0xE7, ++0x01, 0x4E, 0xE4, 0xE7, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xA8, 0x64, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x95, 0x24, 0x13, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x42, 0x6D, 0xC3, 0x69, 0x91, 0xF8, 0x09, 0xC0, 0x9D, 0x68, 0x03, 0x8E, ++0x88, 0x46, 0x91, 0x05, 0x02, 0xD5, 0x12, 0xF4, 0x80, 0x60, 0x3B, 0xD0, 0x12, 0x3B, 0x01, 0x2B, 0x05, 0xF1, 0x12, 0x05, ++0x3A, 0xDD, 0x28, 0x4A, 0xDF, 0xF8, 0xA0, 0x90, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x0C, 0x2C, 0x40, 0xF2, 0xFD, 0x7E, ++0x15, 0xE0, 0x03, 0x2B, 0x2A, 0xDD, 0x6A, 0x88, 0x12, 0xF0, 0x08, 0x06, 0xC2, 0xF3, 0x42, 0x01, 0x24, 0xD1, 0x19, 0xF8, ++0x01, 0x20, 0x04, 0x32, 0x9A, 0x42, 0x2B, 0xDC, 0xBC, 0xF8, 0x20, 0x10, 0xB9, 0x42, 0xA3, 0xEB, 0x02, 0x03, 0x11, 0xD0, ++0x01, 0x2B, 0x15, 0x44, 0x1A, 0xDD, 0x2C, 0x88, 0xC4, 0xF3, 0x0A, 0x07, 0x77, 0x45, 0x13, 0xD0, 0x14, 0xF4, 0x00, 0x60, ++0xE1, 0xD0, 0xBC, 0xF8, 0x20, 0x10, 0x02, 0x22, 0xB9, 0x42, 0xA3, 0xEB, 0x02, 0x03, 0xED, 0xD1, 0x14, 0xF4, 0x00, 0x60, ++0x0B, 0xD1, 0x98, 0xF8, 0x0A, 0x30, 0xB3, 0xEB, 0x14, 0x3F, 0x0D, 0xD0, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x22, 0xDB, 0xE7, ++0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0x23, 0xC8, 0xF8, 0xDC, 0x30, 0x01, 0x20, 0xF3, 0xE7, 0x30, 0x46, 0xF1, 0xE7, ++0x08, 0xF1, 0xE0, 0x04, 0x02, 0x3A, 0xA9, 0x1C, 0x20, 0x46, 0x23, 0xF0, 0xBD, 0xFC, 0xC8, 0xF8, 0xDC, 0x40, 0x01, 0x20, ++0xE6, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x00, 0x96, 0x15, 0x00, 0x85, 0x4B, 0x86, 0x4A, 0x19, 0x68, 0x43, 0x6D, ++0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0x24, 0xC5, 0x69, 0x82, 0xF8, 0x88, 0x40, 0xB1, 0xF9, 0x00, 0x10, 0xA1, 0x42, 0x83, 0xB0, ++0xC0, 0xF2, 0xC6, 0x80, 0x9E, 0x01, 0x40, 0xF1, 0xAD, 0x80, 0x00, 0x29, 0xC3, 0xF3, 0xCF, 0x30, 0xC3, 0xF3, 0xC9, 0x33, ++0xC0, 0xF2, 0xB3, 0x80, 0x7A, 0x49, 0x10, 0x3B, 0xDB, 0xB2, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x03, 0x14, 0x94, 0xF8, ++0x25, 0x00, 0x00, 0x28, 0x00, 0xF0, 0x9A, 0x80, 0x94, 0xF8, 0x22, 0x50, 0x54, 0xF8, 0x26, 0x0F, 0x50, 0x67, 0x73, 0x48, ++0x73, 0x4E, 0xA4, 0x88, 0x84, 0x80, 0x4F, 0xF4, 0xA4, 0x67, 0x10, 0x69, 0x07, 0xFB, 0x05, 0x65, 0xA8, 0x42, 0x40, 0xF0, ++0x93, 0x80, 0x6F, 0x48, 0x00, 0x68, 0x00, 0xF0, 0x3F, 0x00, 0x09, 0x28, 0x40, 0xF2, 0x8C, 0x80, 0x6C, 0x4C, 0x6D, 0x48, ++0x24, 0x68, 0x05, 0x68, 0xD2, 0xF8, 0x68, 0x80, 0xC4, 0xF3, 0x0B, 0x10, 0x04, 0xF0, 0x0F, 0x09, 0xC4, 0xF3, 0x01, 0x4E, ++0x24, 0x03, 0x00, 0x90, 0xA2, 0xF8, 0x7C, 0x00, 0x82, 0xF8, 0x7F, 0x90, 0x82, 0xF8, 0x83, 0xE0, 0xC5, 0xF3, 0x03, 0x10, ++0x05, 0xF0, 0x07, 0x06, 0x40, 0xF1, 0x8B, 0x80, 0x4F, 0xF0, 0x02, 0x0B, 0x4F, 0xF4, 0x80, 0x64, 0x5F, 0x46, 0x01, 0x94, ++0xC5, 0xF3, 0x00, 0x34, 0xC5, 0xF3, 0x42, 0x2C, 0x82, 0xF8, 0x80, 0x70, 0xF7, 0xB2, 0x82, 0xF8, 0x81, 0x00, 0x82, 0xF8, ++0x87, 0x40, 0x82, 0xF8, 0x82, 0xC0, 0x82, 0xF8, 0x84, 0x70, 0xB9, 0xF1, 0x00, 0x0F, 0x79, 0xD0, 0x92, 0xF8, 0x86, 0x50, ++0xDF, 0xF8, 0x64, 0x91, 0xD9, 0xF8, 0x00, 0x40, 0x00, 0x2C, 0xFB, 0xDA, 0xD9, 0xF8, 0x00, 0x90, 0x50, 0x4C, 0x02, 0x2E, ++0x09, 0xEA, 0x04, 0x04, 0x76, 0xD8, 0x4F, 0x4F, 0x00, 0xEB, 0x40, 0x09, 0x57, 0xF8, 0x26, 0x70, 0xD9, 0x44, 0x37, 0xF8, ++0x19, 0x90, 0xD8, 0xF8, 0x0C, 0x70, 0xDF, 0xF8, 0x3C, 0xA1, 0xBC, 0x42, 0x28, 0xBF, 0x3C, 0x46, 0x14, 0x67, 0xDA, 0xF8, ++0x00, 0xB0, 0x01, 0x9F, 0x98, 0xF8, 0x1C, 0x80, 0x4F, 0xF4, 0x1E, 0x7A, 0x0A, 0xFB, 0x03, 0x13, 0x07, 0x43, 0x01, 0x21, ++0x47, 0xEA, 0xCE, 0x1E, 0x01, 0xFA, 0x05, 0xF5, 0x4F, 0xEA, 0x1B, 0x67, 0xD3, 0xF8, 0x4C, 0x11, 0x93, 0x66, 0x00, 0x9B, ++0x27, 0x2C, 0x4E, 0xEA, 0x0C, 0x1C, 0x4F, 0xEA, 0x87, 0x17, 0x18, 0xFB, 0x05, 0xF8, 0x4C, 0xF4, 0x40, 0x5C, 0x46, 0xEA, ++0xC3, 0x06, 0x94, 0xBF, 0x00, 0x24, 0x01, 0x24, 0x47, 0xF0, 0x13, 0x07, 0x18, 0xFB, 0x09, 0xF9, 0x82, 0xF8, 0x88, 0x40, ++0xD7, 0x66, 0xA1, 0xF8, 0x82, 0xC0, 0xA1, 0xF8, 0x84, 0x60, 0xA2, 0xF8, 0x7A, 0x90, 0x09, 0xE0, 0xAB, 0x68, 0x59, 0x89, ++0xA2, 0xF8, 0x74, 0x10, 0x99, 0x89, 0xA2, 0xF8, 0x76, 0x10, 0xDB, 0x89, 0xA2, 0xF8, 0x78, 0x30, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x10, 0xF4, 0x7C, 0x7F, 0x7F, 0xF4, 0x49, 0xAF, 0x27, 0x49, 0x27, 0x48, 0x40, 0xF6, 0x53, 0x12, 0x07, 0xE0, ++0x00, 0x8E, 0x1C, 0x28, 0x3F, 0xF6, 0x36, 0xAF, 0x22, 0x49, 0x24, 0x48, 0x40, 0xF6, 0x46, 0x12, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x11, 0xF0, 0xF9, 0xB8, 0x4F, 0xF0, 0x01, 0x0B, 0x4F, 0xF4, 0x00, 0x74, 0x5F, 0x46, 0x01, 0x94, 0x73, 0xE7, ++0xAC, 0x0F, 0xDF, 0xF8, 0x7C, 0x90, 0xC5, 0xF3, 0x01, 0x65, 0x19, 0xF8, 0x04, 0x40, 0x82, 0xF8, 0x85, 0x40, 0x82, 0xF8, ++0x86, 0x50, 0x7B, 0xE7, 0x03, 0x3F, 0x00, 0xEB, 0x40, 0x09, 0xC7, 0xF3, 0x46, 0x0A, 0x0B, 0xEB, 0x49, 0x09, 0x4F, 0xF0, ++0x03, 0x0B, 0x1B, 0xFB, 0x0A, 0x99, 0xDF, 0xF8, 0x54, 0xA0, 0x3A, 0xF8, 0x19, 0x90, 0x07, 0xF0, 0x01, 0x07, 0x09, 0xFA, ++0x07, 0xF9, 0x1F, 0xFA, 0x89, 0xF9, 0x7A, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x08, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x58, 0x83, 0x32, 0x40, 0x5C, 0x83, 0x32, 0x40, ++0xFC, 0xFF, 0x0F, 0x00, 0x04, 0x96, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x50, 0x90, 0x15, 0x00, 0xB0, 0x93, 0x15, 0x00, ++0x60, 0x83, 0x32, 0x40, 0x64, 0x83, 0x32, 0x40, 0xA8, 0xB2, 0x15, 0x00, 0x70, 0x95, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x4C, ++0xD4, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xD4, 0xF8, 0xEC, 0x33, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0x10, 0xB5, 0x03, 0xF0, 0x85, 0xFB, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x04, 0x03, 0xD4, 0x07, 0x4B, 0x00, 0x24, 0x1C, 0x61, ++0x10, 0xBD, 0x04, 0x46, 0xED, 0xF7, 0x62, 0xFC, 0x00, 0x28, 0xF6, 0xD0, 0x02, 0x4B, 0x1C, 0x61, 0x10, 0xBD, 0x00, 0xBF, ++0x04, 0x00, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0x18, 0x4B, 0x1B, 0x69, 0x63, 0xB3, 0x93, 0xF8, 0x64, 0x20, 0x4A, 0xB3, ++0x16, 0x4A, 0x93, 0xF8, 0x6C, 0x30, 0x10, 0x68, 0x15, 0x49, 0x40, 0xF0, 0x10, 0x00, 0x30, 0xB4, 0x10, 0x60, 0x10, 0x68, ++0x13, 0x4D, 0x14, 0x4C, 0x40, 0xF4, 0x00, 0x60, 0x10, 0x60, 0x10, 0x68, 0x40, 0xF4, 0x80, 0x50, 0x10, 0x60, 0x2A, 0x68, ++0x10, 0x48, 0xC4, 0xF8, 0x50, 0x04, 0x42, 0xF4, 0x00, 0x72, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x32, 0x0A, 0x60, ++0x0A, 0x68, 0x10, 0x33, 0xDB, 0xB2, 0x43, 0xEA, 0x83, 0x23, 0x22, 0xF4, 0x00, 0x32, 0xC4, 0xF8, 0x4C, 0x34, 0x30, 0xBC, ++0x0A, 0x60, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x80, 0x80, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, ++0x24, 0x03, 0x32, 0x40, 0x60, 0x5D, 0x18, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0x08, 0xB5, 0x0F, 0x4B, 0x1B, 0x69, 0x1B, 0xB1, ++0x0E, 0x4B, 0xD3, 0xF8, 0xC4, 0x33, 0x98, 0x47, 0x0D, 0x48, 0x0E, 0x4B, 0x02, 0x68, 0x0E, 0x49, 0x22, 0xF4, 0x00, 0x72, ++0x02, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x10, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0x1A, 0x68, ++0x22, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x33, 0x0B, 0x60, 0x08, 0xBD, 0x94, 0x64, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x24, 0x03, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x43, 0x6C, 0x13, 0xB1, ++0x9B, 0x88, 0x9A, 0x05, 0x0C, 0xD4, 0xC3, 0x6A, 0xDB, 0x6B, 0x9B, 0x06, 0x43, 0xBF, 0x91, 0xF8, 0x2D, 0x31, 0x48, 0xF2, ++0x07, 0x00, 0x40, 0xEA, 0x43, 0x20, 0xD1, 0xF8, 0x04, 0x02, 0x70, 0x47, 0x01, 0x4B, 0xD8, 0x6E, 0x70, 0x47, 0x00, 0xBF, ++0x94, 0x64, 0x17, 0x00, 0x4B, 0x08, 0x03, 0x22, 0x02, 0xFB, 0x03, 0x00, 0x03, 0x4B, 0x33, 0xF8, 0x10, 0x00, 0x01, 0xF0, ++0x01, 0x01, 0x88, 0x40, 0x70, 0x47, 0x00, 0xBF, 0xE0, 0x94, 0x15, 0x00, 0x4B, 0x08, 0x03, 0x22, 0x02, 0xFB, 0x03, 0x00, ++0x03, 0x4B, 0x33, 0xF8, 0x10, 0x00, 0x01, 0xF0, 0x01, 0x01, 0x88, 0x40, 0x80, 0xB2, 0x70, 0x47, 0x70, 0x95, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x2B, 0x4F, 0x84, 0x6A, 0x3D, 0x68, 0x90, 0xF8, 0x1D, 0x80, 0xB5, 0xF9, 0x00, 0xC0, 0xBC, 0xF1, ++0x00, 0x0F, 0x16, 0x46, 0x99, 0x46, 0xC4, 0xF3, 0x41, 0x25, 0x12, 0xDB, 0xC4, 0xF3, 0x02, 0x12, 0x01, 0x32, 0x1A, 0x60, ++0x04, 0xF0, 0x0F, 0x04, 0x22, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x08, 0x23, 0x04, 0xEB, 0x44, 0x04, 0xDB, 0x68, ++0x33, 0x60, 0x05, 0xEB, 0x44, 0x00, 0xBD, 0xE8, 0xF8, 0x83, 0x05, 0x29, 0x1E, 0xD0, 0x1C, 0x49, 0x1C, 0x48, 0x40, 0xF6, ++0xF5, 0x12, 0x10, 0xF0, 0xF5, 0xFF, 0x39, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0xC4, 0xF3, 0x02, 0x12, 0x01, 0x32, 0x00, 0x29, ++0x4F, 0xEA, 0x14, 0x13, 0xC9, 0xF8, 0x00, 0x20, 0x04, 0xF0, 0x0F, 0x04, 0xDC, 0xDA, 0x5B, 0x07, 0x11, 0xD4, 0x0B, 0x2C, ++0xD8, 0xD9, 0x10, 0x49, 0x11, 0x48, 0x40, 0xF6, 0xFF, 0x12, 0x10, 0xF0, 0xDD, 0xFF, 0xD1, 0xE7, 0xC4, 0xF3, 0x02, 0x12, ++0x01, 0x32, 0x1A, 0x60, 0x23, 0x09, 0x5B, 0x07, 0x04, 0xF0, 0x0F, 0x04, 0xED, 0xD5, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, ++0xFE, 0x12, 0x10, 0xF0, 0xCD, 0xFF, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE2, 0xDB, 0xBC, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD8, 0x93, 0x15, 0x00, 0xF8, 0x93, 0x15, 0x00, ++0xE0, 0x91, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x14, 0x4E, 0xDF, 0xF8, 0x54, 0xC0, 0x35, 0x69, 0x04, 0x38, 0x31, 0x46, ++0x05, 0xF1, 0x08, 0x04, 0x05, 0xF1, 0x18, 0x0E, 0x00, 0x27, 0x50, 0xF8, 0x04, 0x2F, 0x13, 0x09, 0x02, 0xF0, 0x0F, 0x08, ++0x03, 0xF4, 0x7F, 0x63, 0x43, 0xEA, 0x08, 0x03, 0x12, 0x0C, 0x8B, 0x62, 0x81, 0xF8, 0x2C, 0x20, 0x25, 0xB1, 0x22, 0x68, ++0x02, 0xEA, 0x0C, 0x02, 0x13, 0x43, 0x8B, 0x62, 0x04, 0x34, 0xA6, 0x45, 0x4F, 0x62, 0x01, 0xF1, 0x0C, 0x01, 0xE6, 0xD1, ++0x01, 0x23, 0x86, 0xF8, 0x62, 0x30, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x00, 0xF0, 0xFF, 0xFF, ++0x03, 0x4B, 0x02, 0x78, 0x83, 0xF8, 0x64, 0x20, 0x42, 0x78, 0x83, 0xF8, 0x65, 0x20, 0x70, 0x47, 0x94, 0x64, 0x17, 0x00, ++0x0A, 0x4B, 0x9A, 0x69, 0x8A, 0xB1, 0x30, 0xB4, 0x01, 0xEB, 0x41, 0x02, 0x03, 0xEB, 0x82, 0x02, 0x4C, 0x00, 0x92, 0xF8, ++0x2E, 0x50, 0x05, 0xB1, 0x50, 0x62, 0x21, 0x44, 0x03, 0xEB, 0x81, 0x03, 0x01, 0x22, 0x30, 0xBC, 0x83, 0xF8, 0x2D, 0x20, ++0x70, 0x47, 0x70, 0x47, 0x94, 0x64, 0x17, 0x00, 0x08, 0x4A, 0x09, 0x4B, 0x11, 0x69, 0x09, 0x4A, 0x10, 0xB4, 0x01, 0xF5, ++0x9C, 0x51, 0x08, 0x4C, 0x5C, 0x60, 0x98, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x18, 0x46, 0x08, 0x31, 0xD2, 0xF8, 0xE0, 0x31, ++0x18, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x95, 0x24, 0x13, 0x00, ++0x08, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x40, 0xF2, 0xFF, 0x31, 0xB3, 0xF8, 0xBE, 0x24, ++0x8A, 0x42, 0x00, 0xD1, 0x70, 0x47, 0x43, 0x6C, 0x28, 0x30, 0x59, 0x6A, 0xFE, 0xF7, 0xF2, 0xBB, 0x18, 0x88, 0x17, 0x00, ++0xF8, 0xB5, 0x0E, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x40, 0xF2, 0xFF, 0x31, 0xB3, 0xF8, ++0xBE, 0x24, 0x8A, 0x42, 0x0F, 0xD0, 0xD0, 0xE9, 0x12, 0x67, 0x1D, 0x46, 0x06, 0xF1, 0x3C, 0x04, 0x4C, 0x36, 0x20, 0x46, ++0xF9, 0x6A, 0x04, 0x34, 0xFE, 0xF7, 0xD8, 0xFB, 0xB4, 0x42, 0x02, 0xD0, 0xB5, 0xF8, 0xBE, 0x24, 0xF5, 0xE7, 0xF8, 0xBD, ++0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x9C, 0x4E, 0xD0, 0xF8, 0x44, 0xB0, 0xC7, 0x6C, 0x96, 0xF8, 0x7E, 0x50, ++0x96, 0xF8, 0x87, 0x30, 0x11, 0xF4, 0x00, 0x09, 0x83, 0xB0, 0x04, 0x46, 0x8A, 0x46, 0x3E, 0xD0, 0x7B, 0xBB, 0xDF, 0xF8, ++0x58, 0x82, 0x28, 0x46, 0xD8, 0xF8, 0xC0, 0x33, 0x98, 0x47, 0xD8, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xBB, 0xF8, 0x04, 0x30, ++0x99, 0x06, 0x49, 0xD5, 0x13, 0xF0, 0x40, 0x02, 0x69, 0xD0, 0x58, 0x46, 0xFD, 0xF7, 0x14, 0xFE, 0x00, 0x23, 0xDF, 0xF8, ++0x4C, 0x82, 0x63, 0x64, 0xB9, 0xF1, 0x00, 0x0F, 0x4D, 0xD0, 0x89, 0x4B, 0x00, 0x22, 0xD3, 0xF8, 0xAC, 0x33, 0x29, 0x46, ++0x20, 0x46, 0x98, 0x47, 0x54, 0x20, 0x00, 0xFB, 0x05, 0x80, 0x0C, 0x30, 0x0F, 0xF0, 0xD2, 0xFA, 0xA3, 0x88, 0x00, 0x2B, ++0x47, 0xD1, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xFC, 0xF7, 0x0B, 0xB9, 0x7F, 0x48, 0x96, 0xF8, 0x64, 0x30, ++0x01, 0x68, 0xDF, 0xF8, 0xF0, 0x81, 0x1B, 0x06, 0x21, 0xF0, 0xE0, 0x61, 0x03, 0xF0, 0xE0, 0x63, 0x0B, 0x43, 0x03, 0x60, ++0xC7, 0xE7, 0x00, 0x2B, 0xC8, 0xD0, 0x77, 0x48, 0x96, 0xF8, 0x65, 0xE0, 0x01, 0x68, 0x02, 0x68, 0xC1, 0xF3, 0x02, 0x61, ++0x4B, 0x1C, 0x73, 0x45, 0x28, 0xBF, 0x73, 0x46, 0x1B, 0x06, 0x03, 0xF0, 0xE0, 0x63, 0x22, 0xF0, 0xE0, 0x6C, 0x43, 0xEA, ++0x0C, 0x03, 0x03, 0x60, 0xBB, 0xF8, 0x04, 0x30, 0x99, 0x06, 0xB5, 0xD4, 0x1C, 0x23, 0xDF, 0xF8, 0xC4, 0x81, 0x54, 0x20, ++0x10, 0xFB, 0x05, 0x30, 0x40, 0x44, 0x0F, 0xF0, 0x99, 0xFA, 0x58, 0x46, 0xFD, 0xF7, 0xC4, 0xFD, 0x00, 0x23, 0x63, 0x64, ++0xB9, 0xF1, 0x00, 0x0F, 0xB1, 0xD1, 0xCA, 0xF3, 0x07, 0x29, 0xB9, 0xF1, 0x04, 0x0F, 0x1F, 0xD9, 0x3B, 0x6D, 0x43, 0xF4, ++0x80, 0x33, 0x3B, 0x65, 0xA7, 0xE7, 0x2A, 0x46, 0x51, 0x46, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xFB, 0xF7, ++0x9D, 0xBA, 0x3B, 0x6D, 0x00, 0x92, 0x23, 0xF4, 0x00, 0x03, 0x2A, 0xF4, 0x00, 0x0A, 0x58, 0x46, 0x3B, 0x65, 0xCA, 0xF3, ++0x07, 0x29, 0xFD, 0xF7, 0xA1, 0xFD, 0x00, 0x9A, 0xDF, 0xF8, 0x64, 0x81, 0x62, 0x64, 0xB9, 0xF1, 0x04, 0x0F, 0xDF, 0xD8, ++0xD4, 0xF8, 0x48, 0xA0, 0xB9, 0xF1, 0x00, 0x0F, 0x25, 0xD0, 0x0A, 0xF1, 0x28, 0x0B, 0x05, 0xEB, 0x45, 0x03, 0x06, 0xEB, ++0x83, 0x03, 0x09, 0xF1, 0x01, 0x09, 0x59, 0x6A, 0xDA, 0xE9, 0x17, 0x32, 0xBB, 0x64, 0x4F, 0xEA, 0x09, 0x23, 0xC7, 0xE9, ++0x0D, 0x2B, 0x3B, 0x65, 0x07, 0xF1, 0x14, 0x02, 0x6B, 0x00, 0x00, 0x29, 0x4B, 0xD0, 0xB9, 0x61, 0x54, 0x20, 0x00, 0xFB, ++0x05, 0x88, 0x1D, 0x44, 0x98, 0xF8, 0x50, 0x30, 0x06, 0xEB, 0x85, 0x06, 0x01, 0x33, 0x72, 0x62, 0x88, 0xF8, 0x50, 0x30, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xE3, 0x6A, 0x0A, 0xF1, 0x28, 0x0B, 0x03, 0xF1, 0x40, 0x0C, 0x1A, 0x46, 0x0A, 0xF1, ++0x24, 0x01, 0x52, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0F, 0x62, 0x45, 0xF9, 0xD1, 0xE2, 0x8B, 0x92, 0x04, 0x26, 0xD5, ++0x33, 0x4A, 0x34, 0x48, 0x11, 0x68, 0x62, 0x7F, 0xB1, 0xF9, 0x00, 0x10, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, 0x02, 0x02, ++0x00, 0x29, 0xD2, 0xF8, 0x4C, 0x21, 0x00, 0x92, 0x29, 0xDB, 0x00, 0x9A, 0x59, 0x69, 0xD2, 0xF8, 0x9C, 0x20, 0xCA, 0xF8, ++0x40, 0x10, 0x59, 0x6A, 0xCA, 0xF8, 0x50, 0x10, 0xC2, 0xF3, 0xC2, 0x21, 0x05, 0x29, 0xCA, 0xF8, 0x3C, 0x20, 0x25, 0xD0, ++0xDB, 0x6B, 0x5B, 0x07, 0x05, 0xD4, 0xDA, 0xF8, 0x2C, 0x30, 0x23, 0xF4, 0xC0, 0x73, 0xCA, 0xF8, 0x2C, 0x30, 0x20, 0x46, ++0xFF, 0xF7, 0xDC, 0xFE, 0x9F, 0xE7, 0x54, 0x21, 0x01, 0xFB, 0x05, 0xF1, 0x1E, 0x48, 0x48, 0xF8, 0x01, 0x20, 0x00, 0x68, ++0x40, 0x78, 0x41, 0x44, 0x00, 0x28, 0xA9, 0xD1, 0xC1, 0xE9, 0x01, 0x00, 0xA6, 0xE7, 0x00, 0x2A, 0xD3, 0xD1, 0x19, 0x49, ++0x19, 0x48, 0x01, 0x93, 0x40, 0xF2, 0x4B, 0x12, 0x10, 0xF0, 0xFE, 0xFD, 0x01, 0x9B, 0xCA, 0xE7, 0x00, 0x98, 0xDA, 0xF8, ++0x4C, 0x10, 0x90, 0xF8, 0xA1, 0x00, 0x02, 0xF4, 0xC0, 0x62, 0xB2, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x3C, ++0x4F, 0xF4, 0x00, 0x3C, 0x21, 0xF4, 0x40, 0x32, 0x42, 0xEA, 0x0C, 0x02, 0x20, 0xB1, 0x42, 0xF4, 0x80, 0x22, 0xCA, 0xF8, ++0x4C, 0x20, 0xC1, 0xE7, 0x22, 0xF4, 0x80, 0x22, 0xCA, 0xF8, 0x4C, 0x20, 0xBC, 0xE7, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, 0x10, 0xB5, 0x05, 0x4C, 0x20, 0x46, 0x0F, 0xF0, ++0x6F, 0xF9, 0x10, 0xF0, 0x25, 0xFE, 0x01, 0x38, 0xC0, 0xB2, 0xE0, 0x72, 0xA0, 0x72, 0x10, 0xBD, 0x24, 0x65, 0x17, 0x00, ++0xC2, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x02, 0x38, 0x85, 0xB0, 0x98, 0xF8, 0x62, 0x30, ++0x02, 0x2B, 0x17, 0xD1, 0x4F, 0xF4, 0x1E, 0x79, 0x93, 0x46, 0x0C, 0x46, 0x09, 0xFB, 0x01, 0xF2, 0xBA, 0x49, 0x01, 0x92, ++0x8E, 0x18, 0xB0, 0xF8, 0x00, 0xA0, 0x96, 0xF8, 0x24, 0x90, 0xB9, 0xF1, 0x01, 0x0F, 0x05, 0x46, 0x41, 0xF2, 0x04, 0x42, ++0x07, 0xD0, 0x0A, 0xEA, 0x02, 0x0A, 0xBA, 0xF5, 0x80, 0x5F, 0x5A, 0xD0, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0xEA, ++0x02, 0x02, 0x00, 0xF0, 0x6B, 0x81, 0x0A, 0xF0, 0xFC, 0x03, 0xA4, 0x2B, 0x00, 0xF0, 0x75, 0x82, 0x0A, 0xF0, 0x8C, 0x03, ++0x88, 0x2B, 0xEF, 0xD1, 0x0A, 0xF4, 0x40, 0x7A, 0xBA, 0xF5, 0x40, 0x7F, 0x0C, 0xBF, 0xEF, 0x8B, 0x2F, 0x8B, 0xA7, 0x4B, ++0xA5, 0x49, 0xA7, 0x4A, 0x07, 0xF0, 0x07, 0x07, 0x4F, 0xF4, 0x1E, 0x75, 0xDB, 0x5D, 0x05, 0xFB, 0x04, 0x15, 0xD2, 0x5C, ++0x95, 0xF8, 0x2E, 0x31, 0x1A, 0x42, 0xD9, 0xD0, 0x95, 0xF8, 0x31, 0x30, 0x13, 0xF0, 0x0C, 0x0F, 0x00, 0xF0, 0x7E, 0x82, ++0x95, 0xF8, 0x32, 0x20, 0x12, 0xF0, 0x06, 0x0F, 0xCE, 0xD1, 0x18, 0x07, 0x95, 0xF8, 0x2F, 0x91, 0x40, 0xF1, 0x8A, 0x82, ++0x99, 0x4B, 0x02, 0x22, 0x85, 0xF8, 0x32, 0x20, 0xD3, 0xF8, 0x20, 0x33, 0x31, 0x46, 0x40, 0x46, 0x4A, 0x46, 0x98, 0x47, ++0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x7A, 0x82, 0xA9, 0xEB, 0x00, 0x09, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF3, 0x74, 0x82, ++0x8C, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x24, 0x00, 0x23, 0x1A, 0x46, 0x94, 0xF8, 0x23, 0x00, 0x47, 0xF0, ++0x10, 0x01, 0xFC, 0xF7, 0xA9, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x32, 0x30, 0xA4, 0xE7, 0x00, 0x22, 0x0C, 0x21, 0x49, 0x20, ++0x0E, 0xF0, 0x58, 0xFC, 0x4F, 0xF0, 0x01, 0x09, 0x86, 0xF8, 0x24, 0x90, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, 0x0E, 0xF0, ++0x7F, 0xFC, 0x96, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x58, 0xD1, 0x96, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x54, 0xD8, 0x96, 0xF8, ++0x22, 0x20, 0x77, 0x48, 0x7B, 0x4D, 0xCD, 0xF8, 0x08, 0x90, 0x9E, 0x23, 0xA4, 0x21, 0x11, 0xFB, 0x02, 0x31, 0x07, 0xFB, ++0x02, 0x07, 0x4F, 0x23, 0x46, 0x22, 0x13, 0xFB, 0x04, 0x24, 0x71, 0x4A, 0x02, 0xF5, 0x16, 0x73, 0x02, 0xEB, 0xC4, 0x04, ++0x01, 0x9A, 0x1A, 0x44, 0x00, 0xEB, 0xC1, 0x0A, 0x91, 0x46, 0xD6, 0xF8, 0x08, 0x32, 0x1B, 0xB3, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x6D, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0x2B, 0x68, 0xA4, 0xF1, 0x28, 0x00, 0x01, 0x33, ++0xAA, 0xF1, 0x28, 0x01, 0x01, 0x90, 0x2B, 0x60, 0x0F, 0xF0, 0x98, 0xF9, 0xD6, 0xE9, 0x82, 0x23, 0x01, 0x98, 0xC7, 0xF8, ++0xC8, 0x24, 0xC7, 0xF8, 0xCC, 0x34, 0x0F, 0xF0, 0x99, 0xF8, 0x2B, 0x68, 0x5A, 0x1E, 0x2B, 0xB1, 0x60, 0x4B, 0x2A, 0x60, ++0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD6, 0xF8, 0x30, 0x32, 0x50, 0x46, 0x21, 0x46, 0x08, 0x36, 0x0A, 0xF1, ++0x08, 0x0A, 0x08, 0x37, 0x23, 0xB1, 0x0F, 0xF0, 0x7B, 0xF9, 0x20, 0x46, 0x0F, 0xF0, 0x82, 0xF8, 0x08, 0x34, 0x4C, 0x45, ++0xC7, 0xD1, 0x40, 0x20, 0x0E, 0xF0, 0xDE, 0xFF, 0x4D, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x36, 0x96, 0xF8, ++0xDE, 0x20, 0x00, 0x2A, 0x40, 0xF0, 0x82, 0x80, 0x0B, 0xF1, 0x0A, 0x05, 0x48, 0x4B, 0xED, 0xB2, 0x4F, 0xF4, 0x1E, 0x79, ++0x09, 0xFB, 0x05, 0xF9, 0x03, 0xEB, 0x09, 0x04, 0x94, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x73, 0xD0, 0x02, 0x23, 0x0C, 0x21, ++0x49, 0x20, 0x0E, 0xF0, 0xD5, 0xFB, 0x4F, 0xF0, 0x01, 0x0A, 0x84, 0xF8, 0x24, 0xA0, 0x05, 0x70, 0x80, 0xF8, 0x01, 0xA0, ++0x0E, 0xF0, 0xFC, 0xFB, 0x94, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xA9, 0x81, 0x94, 0xF8, 0x23, 0x30, 0x09, 0x2B, ++0x00, 0xF2, 0xA4, 0x81, 0x94, 0xF8, 0x22, 0x00, 0xCD, 0xF8, 0x08, 0xA0, 0xA4, 0x21, 0x9E, 0x23, 0x11, 0xFB, 0x00, 0x33, ++0x4F, 0xF0, 0x46, 0x0A, 0x4F, 0x21, 0x11, 0xFB, 0x05, 0xAA, 0x36, 0x4A, 0x2E, 0x4E, 0x2E, 0x49, 0x07, 0xFB, 0x00, 0x67, ++0x01, 0xEB, 0xC3, 0x05, 0x30, 0x4E, 0xA2, 0xF5, 0x16, 0x73, 0x03, 0xEB, 0xCA, 0x0A, 0x91, 0x44, 0xD4, 0xF8, 0x08, 0x32, ++0x1B, 0xB3, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2A, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0x33, 0x68, ++0xAA, 0xF1, 0x28, 0x00, 0x01, 0x33, 0xA5, 0xF1, 0x28, 0x01, 0x01, 0x90, 0x33, 0x60, 0x0F, 0xF0, 0x13, 0xF9, 0xD4, 0xE9, ++0x82, 0x23, 0x01, 0x98, 0xC7, 0xF8, 0xC8, 0x24, 0xC7, 0xF8, 0xCC, 0x34, 0x0F, 0xF0, 0x14, 0xF8, 0x33, 0x68, 0x5A, 0x1E, ++0x2B, 0xB1, 0x1E, 0x4B, 0x32, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD4, 0xF8, 0x30, 0x32, 0x28, 0x46, ++0x51, 0x46, 0x08, 0x34, 0x08, 0x35, 0x08, 0x37, 0x23, 0xB1, 0x0F, 0xF0, 0xF7, 0xF8, 0x50, 0x46, 0x0E, 0xF0, 0xFE, 0xFF, ++0x0A, 0xF1, 0x08, 0x0A, 0xCA, 0x45, 0xC7, 0xD1, 0x40, 0x20, 0x0E, 0xF0, 0x59, 0xFF, 0x0B, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x0B, 0x23, 0x93, 0xF8, 0xDE, 0x20, 0x07, 0x48, 0x0B, 0x49, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0B, 0x03, ++0x01, 0x32, 0x83, 0xF8, 0xDE, 0x20, 0xD1, 0xF8, 0x0C, 0x32, 0x40, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, ++0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0xA4, 0xB2, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x0C, 0x21, 0x49, 0x20, 0x02, 0x92, 0x0E, 0xF0, ++0x41, 0xFB, 0x02, 0x9A, 0x86, 0xF8, 0x24, 0x20, 0x04, 0x70, 0x42, 0x70, 0x0E, 0xF0, 0x6A, 0xFB, 0x96, 0xF8, 0x24, 0x30, ++0x00, 0x2B, 0x60, 0xD1, 0x96, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x5C, 0xD8, 0x96, 0xF8, 0x22, 0x20, 0xA8, 0x48, 0xCD, 0xF8, ++0x08, 0x90, 0xA4, 0x21, 0x9E, 0x23, 0x11, 0xFB, 0x02, 0x33, 0xA6, 0x49, 0xDF, 0xF8, 0xA0, 0xA2, 0x03, 0x94, 0x07, 0xFB, ++0x02, 0x19, 0x4F, 0x25, 0x01, 0xEB, 0xC3, 0x07, 0x46, 0x22, 0x01, 0x9B, 0x15, 0xFB, 0x04, 0x25, 0x00, 0xF5, 0x16, 0x72, ++0x13, 0x44, 0x3C, 0x46, 0x00, 0xEB, 0xC5, 0x05, 0x1F, 0x46, 0xD6, 0xF8, 0x08, 0x22, 0x3A, 0xB3, 0xEF, 0xF3, 0x10, 0x82, ++0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x99, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0xA5, 0xF1, 0x28, 0x00, ++0x01, 0x32, 0xA4, 0xF1, 0x28, 0x01, 0x01, 0x90, 0xCA, 0xF8, 0x00, 0x20, 0x0F, 0xF0, 0x7E, 0xF8, 0xD6, 0xE9, 0x82, 0x21, ++0x01, 0x98, 0xC9, 0xF8, 0xC8, 0x24, 0xC9, 0xF8, 0xCC, 0x14, 0x0E, 0xF0, 0x7F, 0xFF, 0xDA, 0xF8, 0x00, 0x20, 0x51, 0x1E, ++0x32, 0xB1, 0x8B, 0x4B, 0xCA, 0xF8, 0x00, 0x10, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD6, 0xF8, 0x30, 0x22, ++0x20, 0x46, 0x29, 0x46, 0x08, 0x36, 0x08, 0x34, 0x09, 0xF1, 0x08, 0x09, 0x22, 0xB1, 0x0F, 0xF0, 0x5F, 0xF8, 0x28, 0x46, ++0x0E, 0xF0, 0x66, 0xFF, 0x08, 0x35, 0xBD, 0x42, 0xC3, 0xD1, 0x40, 0x20, 0x03, 0x9C, 0x0E, 0xF0, 0xC1, 0xFE, 0x7E, 0x4D, ++0x21, 0x46, 0xEB, 0x68, 0x40, 0x46, 0x98, 0x47, 0x79, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x33, 0x93, 0xF8, ++0xDE, 0xA0, 0x0A, 0xF1, 0xFF, 0x3A, 0x5F, 0xFA, 0x8A, 0xFA, 0x83, 0xF8, 0xDE, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, ++0x84, 0x80, 0x0B, 0xF1, 0x0A, 0x06, 0x6F, 0x49, 0xF6, 0xB2, 0x4F, 0xF4, 0x1E, 0x79, 0x09, 0xFB, 0x06, 0xF9, 0x01, 0xEB, ++0x09, 0x04, 0x94, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x71, 0xD0, 0x02, 0x23, 0x52, 0x46, 0x0C, 0x21, 0x49, 0x20, 0x0E, 0xF0, ++0xAB, 0xFA, 0x84, 0xF8, 0x24, 0xA0, 0x06, 0x70, 0x80, 0xF8, 0x01, 0xA0, 0x0E, 0xF0, 0xD4, 0xFA, 0x94, 0xF8, 0x24, 0x30, ++0x00, 0x2B, 0x60, 0xD1, 0x94, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x5C, 0xD8, 0x94, 0xF8, 0x22, 0x10, 0x5E, 0x4A, 0xDF, 0xF8, ++0x88, 0xC1, 0xDF, 0xF8, 0x80, 0xA1, 0x02, 0x96, 0x9E, 0x23, 0xA4, 0x20, 0x10, 0xFB, 0x01, 0x30, 0x07, 0xFB, 0x01, 0x27, ++0x4F, 0x23, 0x46, 0x21, 0x13, 0xFB, 0x06, 0x13, 0xAC, 0xF5, 0x16, 0x71, 0x02, 0xEB, 0xC0, 0x0B, 0xE1, 0x44, 0x01, 0xEB, ++0xC3, 0x03, 0x5E, 0x46, 0xCB, 0x46, 0xB9, 0x46, 0x1F, 0x46, 0xD4, 0xF8, 0x08, 0x22, 0x3A, 0xB3, 0xEF, 0xF3, 0x10, 0x82, ++0xD3, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x4E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0xA7, 0xF1, 0x28, 0x00, ++0x01, 0x32, 0xA6, 0xF1, 0x28, 0x01, 0x01, 0x90, 0xCA, 0xF8, 0x00, 0x20, 0x0E, 0xF0, 0xE8, 0xFF, 0xD4, 0xE9, 0x82, 0x21, ++0x01, 0x98, 0xC9, 0xF8, 0xC8, 0x24, 0xC9, 0xF8, 0xCC, 0x14, 0x0E, 0xF0, 0xE9, 0xFE, 0xDA, 0xF8, 0x00, 0x20, 0x51, 0x1E, ++0x32, 0xB1, 0x40, 0x4B, 0xCA, 0xF8, 0x00, 0x10, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD4, 0xF8, 0x30, 0x22, ++0x30, 0x46, 0x39, 0x46, 0x08, 0x34, 0x08, 0x36, 0x09, 0xF1, 0x08, 0x09, 0x22, 0xB1, 0x0E, 0xF0, 0xC9, 0xFF, 0x38, 0x46, ++0x0E, 0xF0, 0xD0, 0xFE, 0x08, 0x37, 0x5F, 0x45, 0xC3, 0xD1, 0x40, 0x20, 0x02, 0x9E, 0x0E, 0xF0, 0x2B, 0xFE, 0xEB, 0x68, ++0x31, 0x46, 0x40, 0x46, 0x98, 0x47, 0xD5, 0xF8, 0x0C, 0x32, 0x40, 0x46, 0xDC, 0xE6, 0x96, 0xF8, 0x31, 0x20, 0x12, 0xF0, ++0x02, 0x07, 0x16, 0xD0, 0x96, 0xF8, 0x32, 0x30, 0x2B, 0x49, 0x43, 0xF0, 0x01, 0x03, 0x86, 0xF8, 0x32, 0x30, 0x4A, 0x46, ++0xD1, 0xF8, 0x20, 0x33, 0x40, 0x46, 0x31, 0x46, 0x98, 0x47, 0x96, 0xF8, 0x32, 0x30, 0x23, 0xF0, 0x01, 0x03, 0x86, 0xF8, ++0x32, 0x30, 0x71, 0xE5, 0x96, 0xF8, 0xDE, 0x20, 0xB4, 0xE6, 0x04, 0x23, 0x3A, 0x46, 0x0C, 0x21, 0x4A, 0x20, 0x0E, 0xF0, ++0x15, 0xFA, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, 0x87, 0x70, 0x0E, 0xF0, 0x3F, 0xFA, 0x61, 0xE5, 0x95, 0xF8, 0x32, 0x30, ++0x13, 0xF0, 0x06, 0x04, 0x7F, 0xF4, 0x50, 0xAD, 0x02, 0x26, 0x95, 0xF8, 0x23, 0x00, 0x85, 0xF8, 0x32, 0x60, 0x47, 0xF0, ++0x10, 0x01, 0x23, 0x46, 0x22, 0x46, 0xFB, 0xF7, 0x45, 0xFE, 0x85, 0xF8, 0x32, 0x40, 0x41, 0xE5, 0x95, 0xF8, 0x31, 0x30, ++0x59, 0x07, 0x7F, 0xF5, 0x87, 0xAD, 0x0B, 0x4B, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x04, 0x30, 0x04, 0x23, 0x80, 0xF8, ++0x32, 0x30, 0x00, 0x22, 0x0C, 0x21, 0x4A, 0x20, 0x0E, 0xF0, 0xE8, 0xF9, 0x01, 0x22, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, ++0x82, 0x70, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x0E, 0xF0, 0x0E, 0xBA, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x05, 0x8E, 0x87, 0xB0, 0xAD, 0xB1, 0x7A, 0x4B, 0xC6, 0x69, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, ++0x11, 0xDB, 0x77, 0x4A, 0x65, 0x6D, 0x12, 0x68, 0x12, 0x78, 0x92, 0x07, 0x03, 0xD5, 0x05, 0xF0, 0x3C, 0x02, 0x3C, 0x2A, ++0x77, 0xD0, 0x73, 0x4A, 0xAA, 0x43, 0x0E, 0xD0, 0x01, 0x25, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2E, ++0xEB, 0xD1, 0x6F, 0x49, 0x6F, 0x48, 0x4F, 0xF4, 0xD4, 0x72, 0x35, 0x46, 0x10, 0xF0, 0x5A, 0xFA, 0xF1, 0xE7, 0x00, 0x2B, ++0xC5, 0xF3, 0xCF, 0x30, 0xC5, 0xF3, 0xC9, 0x31, 0x68, 0xDB, 0x6A, 0x4A, 0x10, 0x39, 0xC9, 0xB2, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x25, 0x00, 0x00, 0x28, 0x68, 0xD0, 0xD6, 0xF8, 0x08, 0xB0, 0x0D, 0x29, 0xBB, 0xF8, ++0x00, 0x00, 0x00, 0x90, 0x69, 0xD9, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x22, 0x13, 0x8C, 0xFF, 0x2B, 0x67, 0xD0, ++0x01, 0x92, 0x01, 0x9B, 0xDF, 0xF8, 0x88, 0x81, 0x93, 0xF8, 0x22, 0x90, 0xDF, 0xF8, 0x84, 0xA1, 0x02, 0x91, 0x4F, 0xF4, ++0xA4, 0x67, 0x07, 0xFB, 0x09, 0x87, 0xDA, 0xF8, 0xB8, 0x32, 0x97, 0xF8, 0x63, 0x20, 0x58, 0x46, 0x98, 0x47, 0x97, 0xF8, ++0x64, 0x30, 0x00, 0x2B, 0xBA, 0xD0, 0x00, 0x9B, 0x13, 0xF0, 0x04, 0x03, 0x03, 0x93, 0x05, 0xD1, 0x02, 0x99, 0x97, 0xF8, ++0x63, 0x00, 0x01, 0x22, 0x0C, 0xF0, 0x96, 0xFB, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0x88, 0x98, 0xF8, 0x62, 0x30, ++0x00, 0x2B, 0xA7, 0xD1, 0x00, 0x9A, 0x02, 0xF0, 0xFC, 0x07, 0x80, 0x2F, 0x4A, 0xD0, 0x50, 0x2F, 0x67, 0xD0, 0x03, 0x9B, ++0x00, 0x2B, 0x9D, 0xD1, 0xDA, 0xF8, 0x44, 0x32, 0x29, 0x46, 0x58, 0x46, 0x42, 0x46, 0x98, 0x47, 0x98, 0xF8, 0xC0, 0x34, ++0x00, 0x2B, 0x93, 0xD0, 0xD0, 0x2F, 0x91, 0xD1, 0xB1, 0x68, 0x63, 0x6B, 0x22, 0x8E, 0x40, 0x46, 0x0B, 0xF0, 0x5C, 0xFF, ++0x8A, 0xE7, 0x37, 0x4A, 0x25, 0xF0, 0x40, 0x05, 0x45, 0xF4, 0x00, 0x55, 0xAA, 0x43, 0x65, 0x65, 0x82, 0xD1, 0x90, 0xE7, ++0x10, 0xF4, 0x7C, 0x73, 0x93, 0xD1, 0x32, 0x49, 0x34, 0x48, 0x40, 0xF2, 0xE3, 0x12, 0x1D, 0x46, 0x10, 0xF0, 0xE0, 0xF9, ++0x77, 0xE7, 0x25, 0xF0, 0x00, 0x75, 0x65, 0x65, 0x01, 0x25, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2E, 0x48, ++0x00, 0x69, 0xC3, 0xF8, 0x58, 0x02, 0x90, 0xE7, 0x00, 0x9B, 0x03, 0xF0, 0xFC, 0x03, 0x80, 0x2B, 0xED, 0xD1, 0xD3, 0x6A, ++0x01, 0x93, 0x93, 0xF8, 0x23, 0x20, 0x25, 0xF0, 0xFF, 0x73, 0x10, 0x32, 0x23, 0xF4, 0xC0, 0x33, 0x43, 0xEA, 0xC2, 0x33, ++0x63, 0x65, 0x86, 0xE7, 0x04, 0xF1, 0x14, 0x07, 0x01, 0x9A, 0xDA, 0xF8, 0x98, 0x51, 0x05, 0x93, 0x41, 0x46, 0x05, 0xAB, ++0x38, 0x46, 0xA8, 0x47, 0xDA, 0xF8, 0x40, 0x32, 0x21, 0x8E, 0x05, 0x46, 0x42, 0x46, 0x05, 0x98, 0x98, 0x47, 0xDA, 0xF8, ++0x4C, 0x34, 0x40, 0x46, 0x98, 0x47, 0x00, 0x2D, 0x3F, 0xF4, 0x41, 0xAF, 0xDA, 0xF8, 0xE4, 0x31, 0x3A, 0x46, 0x31, 0x46, ++0x40, 0x46, 0x98, 0x47, 0x39, 0xE7, 0x14, 0x4B, 0x5A, 0x7F, 0x07, 0x2A, 0x7F, 0xF4, 0x34, 0xAF, 0x93, 0xF8, 0x24, 0x00, ++0x00, 0x28, 0x7F, 0xF4, 0x2F, 0xAF, 0x10, 0x4C, 0x10, 0x4D, 0x58, 0x77, 0xD4, 0xE9, 0x00, 0x12, 0x22, 0xF4, 0x00, 0x72, ++0x01, 0x20, 0x11, 0x43, 0x62, 0x60, 0x29, 0x60, 0x83, 0xF8, 0x24, 0x00, 0x05, 0x46, 0x20, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x00, 0x20, 0x00, 0x02, 0x70, 0x79, 0x15, 0x00, 0x10, 0x96, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x50, 0x90, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0xA3, 0x7A, 0xE2, 0x7A, 0x01, 0x33, 0xDB, 0xB2, ++0x9A, 0x42, 0xA3, 0x72, 0x00, 0xD3, 0x10, 0xBD, 0x10, 0xF0, 0xF6, 0xF9, 0x00, 0x23, 0xA3, 0x72, 0x10, 0xBD, 0x00, 0xBF, ++0x24, 0x65, 0x17, 0x00, 0x10, 0xB5, 0x10, 0x4C, 0xA3, 0x7A, 0xD3, 0xB9, 0xE3, 0x7A, 0xA3, 0x72, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4A, 0x0C, 0x4C, 0x11, 0x68, 0x23, 0x68, ++0x48, 0x1C, 0x23, 0xF4, 0x80, 0x73, 0x10, 0x60, 0x23, 0x60, 0x28, 0xB1, 0x05, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xF0, 0xCF, 0xF9, 0xE1, 0xE7, 0x24, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x08, 0xB5, 0x00, 0xF0, 0x29, 0xFC, 0xFF, 0xF7, 0x93, 0xFB, 0xBD, 0xE8, ++0x08, 0x40, 0x1A, 0xF0, 0x9F, 0xB8, 0x00, 0xBF, 0x0A, 0x4A, 0x0B, 0x4B, 0x10, 0xB5, 0xD2, 0xE9, 0x20, 0x04, 0xD2, 0xE9, ++0x22, 0x12, 0x04, 0x44, 0x0A, 0x44, 0xC3, 0xE9, 0x01, 0x40, 0xC3, 0xE9, 0x03, 0x12, 0x18, 0x60, 0x59, 0x61, 0xFF, 0xF7, ++0x7D, 0xFB, 0xBD, 0xE8, 0x10, 0x40, 0x1A, 0xF0, 0x89, 0xB8, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x68, 0x81, 0xDF, 0xF8, 0x68, 0x91, 0xDF, 0xF8, 0x68, 0xA1, 0xDF, 0xF8, 0x68, 0xB1, ++0x4D, 0x4F, 0x87, 0xB0, 0x00, 0x25, 0x3C, 0xE0, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF5, 0x80, 0x1F, 0x4E, 0xD8, 0x20, 0x2D, ++0x4C, 0xD0, 0x10, 0xF0, 0x8D, 0xF9, 0x00, 0x28, 0x61, 0xD0, 0x1A, 0xF0, 0x81, 0xFC, 0x00, 0x28, 0x5D, 0xD0, 0x62, 0x69, ++0x5A, 0x45, 0x0E, 0xD0, 0x43, 0x4B, 0xB9, 0x68, 0x1E, 0x68, 0x53, 0xF8, 0x04, 0x0C, 0x7B, 0x68, 0xCD, 0xE9, 0x02, 0x60, ++0xCD, 0xE9, 0x00, 0x31, 0x3F, 0x48, 0x3B, 0x68, 0x21, 0x46, 0x0F, 0xF0, 0x97, 0xFE, 0x20, 0x46, 0x3D, 0x4E, 0x01, 0xF0, ++0x41, 0xF9, 0x00, 0x22, 0xD6, 0xF8, 0x94, 0x32, 0x8D, 0xF8, 0x17, 0x20, 0x0D, 0xF1, 0x17, 0x01, 0x20, 0x46, 0x98, 0x47, ++0x58, 0xBB, 0x9D, 0xF8, 0x17, 0x30, 0x73, 0xB3, 0x36, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x31, 0xD0, 0x03, 0x2B, ++0x02, 0xD1, 0xD6, 0xF8, 0x8C, 0x32, 0x98, 0x47, 0x01, 0x35, 0x01, 0xF0, 0x09, 0xF9, 0x4F, 0xF4, 0x80, 0x33, 0xC9, 0xF8, ++0x00, 0x30, 0x04, 0x46, 0x4F, 0xF4, 0x80, 0x10, 0x0E, 0xF0, 0x18, 0xFC, 0x98, 0xF8, 0xB8, 0x30, 0x94, 0xB3, 0x00, 0x2B, ++0xB2, 0xD1, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF5, 0x80, 0x1F, 0x01, 0xD8, 0x03, 0x2D, 0xB2, 0xDD, 0x4F, 0xF4, 0x80, 0x10, ++0x0E, 0xF0, 0xE4, 0xFB, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD6, 0xF8, 0xC8, 0x32, 0x20, 0x46, 0x98, 0x47, 0x00, 0x28, ++0xD0, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0xC4, 0xF8, 0x1D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0xCD, 0xD1, 0xD6, 0xF8, ++0x90, 0x32, 0x98, 0x47, 0xCE, 0xE7, 0x1A, 0x4B, 0x01, 0x22, 0x83, 0xF8, 0x45, 0x20, 0x1A, 0xF0, 0x1B, 0xFC, 0xB0, 0xFA, ++0x80, 0xF2, 0x17, 0x49, 0x52, 0x09, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x8D, 0xFE, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x1B, 0xB1, 0x13, 0x4D, 0x95, 0xF8, 0x21, 0x30, 0x3B, 0xB9, 0x12, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, ++0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD5, 0xE9, 0x05, 0x12, 0x28, 0x69, 0xF3, 0xF7, 0x5E, 0xFE, 0x6C, 0x61, 0xEC, 0x61, ++0x2C, 0x61, 0xAC, 0x61, 0x85, 0xF8, 0x21, 0x40, 0xEB, 0xE7, 0x00, 0xBF, 0xEC, 0x34, 0x17, 0x00, 0xD4, 0x81, 0x32, 0x40, ++0x3C, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x28, 0x96, 0x15, 0x00, ++0x30, 0x65, 0x17, 0x00, 0x80, 0x80, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x7C, 0x80, 0x32, 0x40, 0x80, 0xB6, 0x17, 0x00, ++0x0D, 0xF0, 0xAD, 0xBA, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0x86, 0xBB, 0x2D, 0xE9, 0xF8, 0x43, 0x30, 0x4D, 0x2C, 0x68, ++0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0xA2, 0xFB, 0x00, 0x2C, 0x31, 0xD0, 0xDF, 0xF8, 0xC4, 0x90, 0x2C, 0x4F, 0x2E, 0x46, ++0x4F, 0xF0, 0x01, 0x08, 0x23, 0x7C, 0xD9, 0x07, 0x02, 0xD4, 0x2B, 0x89, 0x01, 0x33, 0x2B, 0x81, 0x30, 0x46, 0x0E, 0xF0, ++0x53, 0xFC, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC7, 0xF8, 0x00, 0x80, 0xD9, 0xF8, 0x00, 0x30, ++0x62, 0x68, 0x01, 0x33, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x30, 0x21, 0x74, 0x0A, 0xB1, 0xA0, 0x68, 0x90, 0x47, 0xE0, 0x68, ++0x08, 0xB1, 0x00, 0xF0, 0x77, 0xFB, 0xD9, 0xF8, 0x00, 0x30, 0x33, 0xB1, 0x01, 0x3B, 0x3A, 0x68, 0xC9, 0xF8, 0x00, 0x30, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x2C, 0x68, 0x00, 0x2C, 0xD3, 0xD1, 0xAA, 0x7A, 0xEB, 0x7A, 0x9A, 0x42, 0x20, 0xD0, ++0x13, 0x4B, 0x14, 0x48, 0x1B, 0x69, 0x14, 0x4A, 0xC8, 0x33, 0x4F, 0xF4, 0x80, 0x71, 0x03, 0x60, 0x11, 0x60, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0E, 0x4A, 0x0E, 0x4C, 0x11, 0x68, ++0x23, 0x68, 0x48, 0x1C, 0x43, 0xF4, 0x80, 0x73, 0x10, 0x60, 0x23, 0x60, 0x28, 0xB1, 0x05, 0x4B, 0x11, 0x60, 0x1B, 0x68, ++0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x48, 0x01, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, ++0x2D, 0xE9, 0xF8, 0x43, 0x27, 0x4D, 0x2C, 0x68, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0x30, 0xFB, 0x9C, 0xB3, 0xDF, 0xF8, ++0x9C, 0x80, 0xDF, 0xF8, 0x9C, 0x90, 0x00, 0x27, 0x2E, 0x46, 0x27, 0xE0, 0x01, 0x27, 0x30, 0x46, 0x0E, 0xF0, 0xE6, 0xFB, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x00, 0x30, ++0x62, 0x68, 0x01, 0x33, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x30, 0x21, 0x74, 0x0A, 0xB1, 0xA0, 0x68, 0x90, 0x47, 0xE0, 0x68, ++0x08, 0xB1, 0x00, 0xF0, 0x09, 0xFB, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0xC9, 0xF8, ++0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x2C, 0x68, 0x24, 0xB1, 0x23, 0x7C, 0xDA, 0x07, 0xD5, 0xD4, 0x00, 0x2F, ++0xD2, 0xD0, 0x0B, 0x4C, 0x94, 0xF8, 0x45, 0x30, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0x80, 0x10, 0x0E, 0xF0, ++0xCD, 0xFA, 0x07, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x94, 0xFD, 0x00, 0x23, 0x84, 0xF8, 0x45, 0x30, 0xBD, 0xE8, ++0xF8, 0x83, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x96, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x2B, 0x4E, 0x34, 0x68, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0xD4, 0xFA, ++0x00, 0x2C, 0x3F, 0xD0, 0x28, 0x4D, 0x2B, 0x88, 0x00, 0x2B, 0x3B, 0xD0, 0xDF, 0xF8, 0xA4, 0x80, 0xDF, 0xF8, 0xA4, 0x90, ++0x37, 0x46, 0x23, 0x7C, 0xD9, 0x07, 0x01, 0xD4, 0x2B, 0x88, 0x6B, 0xB3, 0x38, 0x46, 0x0E, 0xF0, 0x83, 0xFB, 0xEF, 0xF3, ++0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x00, 0x30, 0x22, 0x7C, ++0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0xD3, 0x07, 0x02, 0xD4, 0x2B, 0x88, 0x01, 0x3B, 0x2B, 0x80, 0x63, 0x68, 0x00, 0x22, ++0x22, 0x74, 0x0B, 0xB1, 0xA0, 0x68, 0x98, 0x47, 0xE0, 0x68, 0x08, 0xB1, 0x00, 0xF0, 0xA0, 0xFA, 0xD9, 0xF8, 0x00, 0x30, ++0x3B, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x34, 0x68, ++0x00, 0x2C, 0xCC, 0xD1, 0x0B, 0x4C, 0x94, 0xF8, 0x45, 0x30, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0x80, 0x10, ++0x0E, 0xF0, 0x68, 0xFA, 0x07, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x2F, 0xFD, 0x00, 0x23, 0x84, 0xF8, 0x45, 0x30, ++0xBD, 0xE8, 0xF8, 0x83, 0x24, 0x65, 0x17, 0x00, 0x54, 0x28, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x96, 0x15, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF8, 0xB5, 0x0D, 0x4E, 0x35, 0x68, 0x95, 0xB1, 0x34, 0x89, 0x01, 0x34, ++0xA4, 0xB2, 0x37, 0x46, 0x38, 0x46, 0x0E, 0xF0, 0x2D, 0xFB, 0x6B, 0x68, 0x0B, 0xB1, 0xA8, 0x68, 0x98, 0x47, 0x0F, 0xF0, ++0x99, 0xFF, 0x35, 0x68, 0x34, 0x81, 0x01, 0x34, 0xA4, 0xB2, 0x00, 0x2D, 0xF0, 0xD1, 0xBD, 0xE8, 0xF8, 0x40, 0x00, 0xF0, ++0xF5, 0xB9, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x44, 0x4F, 0x06, 0x68, 0x15, 0x88, 0xDF, 0xF8, ++0x20, 0x91, 0xDF, 0xF8, 0x20, 0xA1, 0xDF, 0xF8, 0x20, 0xB1, 0x85, 0xB0, 0x4F, 0xF0, 0x00, 0x08, 0xCD, 0xE9, 0x02, 0x02, ++0x87, 0xF8, 0x02, 0x80, 0xCD, 0xF8, 0x04, 0x80, 0x4A, 0xE0, 0xC4, 0x1A, 0x2C, 0x44, 0x0C, 0x44, 0x55, 0x1B, 0xA9, 0xB2, ++0xA4, 0xB2, 0x00, 0x25, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x36, 0x4A, 0x01, 0x23, 0x13, 0x60, ++0xBA, 0xF8, 0x00, 0x30, 0xDB, 0xF8, 0x00, 0x20, 0xD9, 0xF8, 0x00, 0xC0, 0x00, 0x92, 0x02, 0xEB, 0xC3, 0x00, 0xB2, 0x68, ++0x42, 0x60, 0x00, 0x9A, 0x0C, 0xF1, 0x01, 0x0E, 0xC9, 0xF8, 0x00, 0xE0, 0x42, 0xF8, 0x33, 0x10, 0xFA, 0x78, 0x01, 0x33, ++0x01, 0x32, 0x88, 0x44, 0xAA, 0xF8, 0x00, 0x30, 0xFA, 0x70, 0x64, 0xBB, 0xC3, 0x78, 0xA7, 0xF8, 0x00, 0x80, 0x43, 0xF0, ++0x04, 0x03, 0x01, 0x22, 0xC3, 0x70, 0xBA, 0x70, 0xB8, 0x60, 0xBE, 0xF1, 0x00, 0x0F, 0x38, 0xD0, 0x21, 0x4B, 0xC9, 0xF8, ++0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, 0x31, 0xD1, 0x00, 0x2B, 0x2F, 0xD0, 0x62, 0xB6, 0x00, 0x2C, 0x2C, 0xD0, ++0x1C, 0x4B, 0x1A, 0x68, 0x73, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x1A, 0xDB, 0x01, 0x96, 0x21, 0x46, 0x1E, 0x46, ++0xF3, 0x68, 0x30, 0x89, 0x01, 0x33, 0x9B, 0xB2, 0x1A, 0x1A, 0x92, 0xB2, 0x4C, 0x19, 0x94, 0x42, 0xAB, 0xDA, 0x00, 0x24, ++0xB0, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, 0xE7, 0xD0, 0x0F, 0x4B, 0xC9, 0xF8, 0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, ++0xE0, 0xD1, 0x00, 0x2B, 0xDB, 0xD1, 0xDD, 0xE7, 0x00, 0x2B, 0xE2, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x00, 0x93, 0x4F, 0xF4, ++0x17, 0x72, 0x0F, 0xF0, 0xA9, 0xFE, 0x00, 0x9B, 0xD9, 0xE7, 0x02, 0x9B, 0x01, 0x98, 0x1E, 0x60, 0x03, 0x9B, 0x1D, 0x80, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x54, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xB0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x41, 0x4F, 0xB2, 0xF8, 0x00, 0xA0, 0x06, 0x68, 0xDF, 0xF8, 0x0C, 0xB1, 0x87, 0xB0, 0x4F, 0xF0, ++0x00, 0x08, 0xCD, 0xE9, 0x04, 0x02, 0x01, 0x22, 0x0B, 0x46, 0x87, 0xF8, 0x20, 0x20, 0xC1, 0x46, 0xCD, 0xF8, 0x0C, 0x80, ++0x39, 0xE0, 0x05, 0x44, 0xAD, 0x1A, 0xA1, 0xEB, 0x0A, 0x03, 0xAD, 0xB2, 0x9B, 0xB2, 0x00, 0x2D, 0x02, 0x93, 0x08, 0xBF, ++0x4F, 0xF0, 0x01, 0x09, 0xF2, 0xF7, 0x3C, 0xFC, 0x4F, 0xF0, 0x00, 0x0A, 0x02, 0x9B, 0x04, 0x46, 0x00, 0x28, 0x3A, 0xD0, ++0x7A, 0x68, 0x02, 0xB9, 0x38, 0x60, 0xDB, 0xF8, 0x00, 0x00, 0xF9, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x19, 0x44, 0x01, 0x32, ++0x00, 0x28, 0xF9, 0x60, 0x7A, 0x60, 0xB1, 0x68, 0x36, 0xDB, 0xCD, 0xF8, 0x00, 0x90, 0x00, 0x22, 0x20, 0x46, 0xF3, 0xF7, ++0x6F, 0xFC, 0xB8, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0xC8, 0xF8, 0x04, 0x40, 0xBC, 0x60, 0x05, 0xB3, 0xDB, 0xF8, 0x00, 0x20, ++0x73, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x2E, 0xDB, 0x03, 0x96, 0xA0, 0x46, 0x1E, 0x46, 0x2B, 0x46, 0xF2, 0x68, ++0x35, 0x89, 0x01, 0x32, 0x92, 0xB2, 0x51, 0x1B, 0x89, 0xB2, 0x03, 0xEB, 0x0A, 0x00, 0x88, 0x42, 0xBB, 0xDA, 0x02, 0x93, ++0xF2, 0xF7, 0x02, 0xFC, 0x00, 0x25, 0x02, 0x9B, 0x4F, 0xF0, 0x01, 0x09, 0x04, 0x46, 0x00, 0x28, 0xC4, 0xD1, 0x87, 0xF8, ++0x20, 0x00, 0x04, 0x9B, 0x03, 0x98, 0x1E, 0x60, 0x05, 0x9B, 0xA3, 0xF8, 0x00, 0xA0, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x00, 0x29, 0xC6, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x02, 0x93, 0x40, 0xF2, 0x9E, 0x22, 0x0F, 0xF0, 0x17, 0xFE, 0xB1, 0x68, ++0x02, 0x9B, 0xBC, 0xE7, 0x00, 0x2B, 0xCE, 0xD1, 0x05, 0x49, 0x07, 0x48, 0x02, 0x93, 0x40, 0xF2, 0xB3, 0x22, 0x0F, 0xF0, ++0x0B, 0xFE, 0x02, 0x9B, 0xC5, 0xE7, 0x00, 0xBF, 0x30, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x96, 0x15, 0x00, ++0xA0, 0x96, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x08, 0x91, 0x07, 0x68, 0xD9, 0xF8, ++0x00, 0x40, 0x1D, 0x88, 0x94, 0xF8, 0x00, 0xC0, 0xDF, 0xF8, 0xFC, 0xA0, 0x85, 0xB0, 0xB1, 0xF5, 0xC8, 0x6F, 0x0E, 0x9E, ++0x03, 0x93, 0x06, 0xEB, 0x46, 0x06, 0x28, 0xBF, 0x4F, 0xF4, 0xC8, 0x61, 0xBC, 0xF1, 0x03, 0x0F, 0x08, 0xBF, 0x34, 0x4B, ++0x02, 0x90, 0x07, 0xEB, 0x06, 0x16, 0x06, 0xF1, 0x14, 0x06, 0x90, 0x46, 0x08, 0xBF, 0x1E, 0x60, 0x00, 0x20, 0x2C, 0xE0, ++0xAE, 0xEB, 0x03, 0x04, 0x2C, 0x44, 0x0C, 0x44, 0x52, 0x1B, 0xA4, 0xB2, 0x91, 0xB2, 0x00, 0x25, 0xBC, 0xF1, 0x03, 0x0F, ++0x0D, 0xD1, 0xB1, 0xF5, 0x00, 0x6F, 0x0B, 0x46, 0x28, 0xBF, 0x4F, 0xF4, 0x00, 0x63, 0x43, 0xF0, 0x23, 0x43, 0x4F, 0xF0, ++0x04, 0x12, 0xB3, 0x60, 0xF1, 0x60, 0x31, 0x61, 0x72, 0x61, 0x88, 0x44, 0xA4, 0xB3, 0xDA, 0xF8, 0x00, 0x20, 0x7B, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xF1, 0x14, 0x0B, 0x1C, 0xDB, 0xBC, 0xF1, 0x03, 0x0F, 0x01, 0xD1, 0xC6, 0xF8, ++0x20, 0xB0, 0x38, 0x46, 0x5E, 0x46, 0x1F, 0x46, 0x21, 0x46, 0xD7, 0xE9, 0x02, 0x43, 0x01, 0x33, 0x1F, 0xFA, 0x84, 0xFE, ++0x9B, 0xB2, 0xA3, 0xEB, 0x0E, 0x02, 0x05, 0xEB, 0x04, 0x0B, 0x92, 0xB2, 0x4C, 0x19, 0x94, 0x42, 0xC6, 0xF8, 0x04, 0x80, ++0xC6, 0xF8, 0x00, 0xB0, 0xC0, 0xDA, 0x00, 0x24, 0xC6, 0xE7, 0x00, 0x2B, 0xE0, 0xD1, 0x4F, 0xF4, 0x4A, 0x72, 0x0D, 0x49, ++0x0D, 0x48, 0x01, 0x93, 0x0F, 0xF0, 0x90, 0xFD, 0xD9, 0xF8, 0x00, 0x20, 0x01, 0x9B, 0x92, 0xF8, 0x00, 0xC0, 0xD3, 0xE7, ++0xBC, 0xF1, 0x03, 0x0F, 0x02, 0xD1, 0x05, 0x4B, 0x34, 0x62, 0x5E, 0x60, 0x02, 0x9B, 0x1F, 0x60, 0x03, 0x9B, 0x1D, 0x80, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x60, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, ++0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x61, 0xB3, 0x0B, 0x8A, 0xDA, 0x07, 0x12, 0xD4, 0x16, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x20, 0x02, 0xE0, 0x0B, 0x8A, 0xDB, 0x07, 0x0A, 0xD4, 0x00, 0x2A, 0x49, 0x68, 0xF9, 0xDA, 0x00, 0x29, ++0xF7, 0xD1, 0x11, 0x49, 0x11, 0x48, 0x40, 0xF2, 0xE6, 0x32, 0x0F, 0xF0, 0x29, 0xBD, 0xCB, 0x68, 0x23, 0xF0, 0x03, 0x03, ++0x04, 0x33, 0x0E, 0x49, 0x4A, 0x68, 0x9A, 0x42, 0x8A, 0x68, 0x08, 0xBF, 0x0B, 0x68, 0xC0, 0xF8, 0x98, 0x30, 0x22, 0xF0, ++0x00, 0x40, 0x83, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, 0x13, 0x43, 0x8B, 0x60, 0x70, 0x47, ++0x00, 0xF1, 0xA0, 0x03, 0xE9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, ++0xEC, 0x34, 0x17, 0x00, 0x18, 0x4B, 0x19, 0x4A, 0x18, 0x68, 0x19, 0x49, 0xDF, 0xF8, 0x7C, 0xC0, 0xF0, 0xB5, 0xD0, 0xE9, ++0x00, 0x34, 0x17, 0x4D, 0x13, 0x60, 0x1C, 0x44, 0x2B, 0x60, 0x25, 0x1F, 0x0D, 0x60, 0x15, 0x4E, 0x15, 0x4D, 0x11, 0x68, ++0x31, 0x60, 0x29, 0x60, 0xD0, 0xE9, 0x02, 0x10, 0xDF, 0xF8, 0x5C, 0xE0, 0x12, 0x4F, 0x54, 0x60, 0x08, 0x44, 0x69, 0x60, ++0x11, 0x4C, 0x93, 0x60, 0x11, 0x4E, 0x03, 0x1F, 0xCE, 0xF8, 0x00, 0x30, 0xCC, 0xF8, 0x00, 0x10, 0x39, 0x60, 0x6E, 0x61, ++0x23, 0x68, 0x10, 0x61, 0x03, 0xF4, 0x00, 0x23, 0x43, 0xF4, 0xF0, 0x23, 0x43, 0xF0, 0x25, 0x03, 0xD1, 0x60, 0x51, 0x61, ++0x23, 0x60, 0xF0, 0xBD, 0x30, 0x36, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, 0xCC, 0x81, 0x32, 0x40, 0xC8, 0x81, 0x32, 0x40, ++0xD0, 0x81, 0x32, 0x40, 0xD4, 0x81, 0x32, 0x40, 0xE4, 0x81, 0x32, 0x40, 0x0C, 0x01, 0x32, 0x40, 0x05, 0x12, 0x00, 0x0C, ++0xE0, 0x81, 0x32, 0x40, 0xDC, 0x81, 0x32, 0x40, 0x10, 0xB4, 0x0A, 0x4C, 0x0A, 0x49, 0x22, 0x68, 0x83, 0x02, 0x03, 0xF4, ++0x80, 0x63, 0x22, 0xF4, 0x80, 0x62, 0x13, 0x43, 0x23, 0x60, 0x0B, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0xC0, 0x04, 0x00, 0xF4, ++0x00, 0x20, 0x23, 0xF4, 0x00, 0x23, 0x18, 0x43, 0x08, 0x60, 0x70, 0x47, 0x24, 0x03, 0x32, 0x40, 0x0C, 0x01, 0x32, 0x40, ++0x90, 0xF8, 0x9C, 0x20, 0xD0, 0xF8, 0x98, 0x30, 0x6A, 0xB9, 0x0E, 0x4A, 0x12, 0x68, 0x22, 0xF0, 0x00, 0x41, 0x8B, 0x42, ++0x02, 0xF0, 0x00, 0x42, 0x0A, 0x49, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, 0x13, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x08, 0x4A, ++0x12, 0x68, 0x22, 0xF0, 0x00, 0x41, 0x8B, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x04, 0x49, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, ++0x13, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0xD0, 0x81, 0x32, 0x40, 0xE0, 0x81, 0x32, 0x40, 0x10, 0xB5, 0x03, 0x8E, ++0x82, 0xB0, 0xC3, 0xB1, 0x2D, 0x4B, 0xC4, 0x69, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x38, 0xDB, 0xA3, 0x68, ++0x42, 0x6D, 0x1B, 0x88, 0x03, 0xF0, 0xFC, 0x03, 0x24, 0x2B, 0x43, 0xD0, 0x94, 0x2B, 0x03, 0xD1, 0x42, 0xF2, 0x02, 0x03, ++0x93, 0x43, 0x36, 0xD0, 0xE3, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x07, 0xE0, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x18, 0xDB, 0x00, 0xF1, 0xA0, 0x03, 0x1E, 0x49, 0x0A, 0x69, 0x9A, 0x42, 0x4A, 0x69, 0x08, 0xBF, ++0xCB, 0x68, 0xC0, 0xF8, 0x98, 0x30, 0x22, 0xF0, 0x00, 0x44, 0xA3, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x38, 0xBF, 0x02, 0xF1, ++0x00, 0x42, 0x13, 0x43, 0x4B, 0x61, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x9E, 0xBF, 0xC3, 0x69, 0x00, 0x2B, ++0xE3, 0xD0, 0x12, 0x49, 0x12, 0x48, 0x4F, 0xF4, 0xD7, 0x72, 0x05, 0xE0, 0x00, 0x2C, 0xC4, 0xD1, 0x0E, 0x49, 0x10, 0x48, ++0x4F, 0xF4, 0xC2, 0x72, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0x0F, 0xF0, 0x2F, 0xBC, 0x0D, 0x4B, 0x01, 0x90, 0xD3, 0xF8, ++0x74, 0x33, 0x98, 0x47, 0x01, 0x98, 0xC1, 0xE7, 0x93, 0x04, 0xBF, 0xD5, 0x08, 0x4B, 0x01, 0x90, 0xD3, 0xF8, 0xFC, 0x33, ++0x98, 0x47, 0x01, 0x98, 0xB8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0x96, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x29, 0x46, 0xD0, 0x2D, 0xE9, 0xF8, 0x4F, ++0x07, 0x46, 0xDF, 0xF8, 0x8C, 0xA0, 0xDF, 0xF8, 0x8C, 0xB0, 0x08, 0x46, 0x1F, 0x49, 0x99, 0x46, 0x4F, 0xF0, 0x00, 0x08, ++0xD7, 0xE9, 0x02, 0x45, 0x01, 0x35, 0xAB, 0xB2, 0xA6, 0xB2, 0x9D, 0x1B, 0xAD, 0xB2, 0xAD, 0x1A, 0xA8, 0x42, 0x23, 0xDB, ++0xF6, 0x1A, 0x16, 0x44, 0x06, 0x44, 0xB6, 0xB2, 0xA8, 0xB2, 0xC5, 0x1C, 0x4F, 0xEA, 0x98, 0x03, 0xAD, 0x08, 0x14, 0x44, ++0x09, 0xEB, 0x83, 0x03, 0x08, 0xD0, 0x1A, 0x46, 0x03, 0xEB, 0x85, 0x05, 0xE3, 0x1A, 0xD4, 0x58, 0x42, 0xF8, 0x04, 0x4B, ++0xAA, 0x42, 0xFA, 0xD1, 0xBE, 0xB1, 0xDA, 0xF8, 0x00, 0x30, 0x7F, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x80, 0x44, 0x00, 0x2B, ++0x1F, 0xFA, 0x88, 0xF8, 0x04, 0xDB, 0x30, 0x46, 0x00, 0x22, 0xD1, 0xE7, 0x00, 0x26, 0xDE, 0xE7, 0x00, 0x2F, 0xF8, 0xD1, ++0x40, 0xF2, 0x2D, 0x42, 0x58, 0x46, 0x0F, 0xF0, 0xFF, 0xFB, 0x02, 0x49, 0xF1, 0xE7, 0xBD, 0xE8, 0xF8, 0x8F, 0x70, 0x47, ++0x70, 0x79, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xEC, 0x96, 0x15, 0x00, 0x38, 0xB5, 0x13, 0x4C, 0x94, 0xF8, 0x21, 0x30, ++0xA3, 0xB9, 0x20, 0x61, 0x11, 0x48, 0xE3, 0x69, 0xE2, 0x68, 0x61, 0x69, 0x65, 0x68, 0x90, 0xF8, 0xB9, 0x00, 0x13, 0x44, ++0x29, 0x44, 0xA2, 0x68, 0x61, 0x61, 0x01, 0x25, 0xB3, 0xEB, 0x40, 0x2F, 0xE3, 0x61, 0x84, 0xF8, 0x21, 0x50, 0xA2, 0x61, ++0x03, 0xD2, 0x38, 0xBD, 0xA3, 0x69, 0x58, 0x60, 0xE8, 0xE7, 0x20, 0x69, 0xF3, 0xF7, 0x90, 0xF9, 0x00, 0x23, 0xC4, 0xE9, ++0x04, 0x33, 0xC4, 0xE9, 0x06, 0x33, 0x84, 0xF8, 0x21, 0x30, 0x38, 0xBD, 0x30, 0x65, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0xAB, 0x4E, 0xD0, 0xF8, 0x1C, 0xC0, 0x35, 0x68, 0x86, 0xB0, 0x04, 0x46, 0xCD, 0xF8, 0x14, 0xC0, ++0xAD, 0xF8, 0x0E, 0x30, 0x2B, 0x78, 0x02, 0x2B, 0x91, 0x46, 0x00, 0xF0, 0xAD, 0x80, 0x01, 0x2B, 0xDF, 0xF8, 0xC4, 0x82, ++0x22, 0xD0, 0x01, 0x20, 0x00, 0x23, 0xD8, 0xF8, 0xAC, 0x52, 0x4A, 0x46, 0xCD, 0xE9, 0x00, 0x30, 0x0D, 0xF1, 0x0E, 0x03, ++0x05, 0xA8, 0xA8, 0x47, 0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0x46, 0x1F, 0xD0, 0x01, 0x2B, 0x59, 0xD0, 0xD8, 0xF8, ++0x98, 0x32, 0x05, 0x99, 0x20, 0x46, 0x2A, 0x46, 0x98, 0x47, 0x0E, 0x9B, 0x63, 0x60, 0x0F, 0x9B, 0x95, 0x48, 0xA3, 0x60, ++0x21, 0x46, 0x0D, 0xF0, 0x3F, 0xFF, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xD8, 0xF8, 0xB0, 0x52, 0x00, 0x23, 0x00, 0x93, ++0x0D, 0xF1, 0x0E, 0x02, 0x05, 0xA8, 0xA8, 0x47, 0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0x46, 0xDF, 0xD1, 0xDF, 0xF8, ++0x64, 0x92, 0x99, 0xF8, 0x02, 0x30, 0x00, 0x2B, 0xDB, 0xD0, 0xB9, 0xF8, 0x00, 0x30, 0x7A, 0x68, 0x3A, 0x33, 0xBB, 0x60, ++0xD3, 0x78, 0x6F, 0xF3, 0x87, 0x13, 0xD3, 0x70, 0x99, 0xF8, 0x03, 0x30, 0xBB, 0x73, 0x00, 0x23, 0x3B, 0x60, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x7F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x20, 0xA2, 0x7E, 0x48, ++0xDA, 0xF8, 0x00, 0x30, 0x39, 0x46, 0x01, 0x33, 0xCA, 0xF8, 0x00, 0x30, 0x0D, 0xF0, 0x08, 0xFF, 0xD8, 0xF8, 0x44, 0x34, ++0x98, 0x47, 0xDA, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x75, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCA, 0xF8, 0x00, 0x30, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x00, 0x23, 0xC9, 0xE9, 0x00, 0x33, 0x32, 0x68, 0x13, 0x78, 0x01, 0x2B, 0xA5, 0xD1, 0xF2, 0xF7, ++0x15, 0xF9, 0x07, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x92, 0x80, 0x6D, 0x4E, 0x96, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x00, 0xF0, ++0x96, 0x80, 0x73, 0x68, 0x81, 0x68, 0x32, 0x68, 0x03, 0xF1, 0x01, 0x0C, 0x4F, 0xEA, 0x0C, 0x63, 0x21, 0xF0, 0xFE, 0x41, ++0x03, 0xF0, 0xFE, 0x43, 0x0B, 0x43, 0x00, 0x21, 0x83, 0x60, 0x00, 0x91, 0x3A, 0x23, 0x04, 0xF1, 0x30, 0x01, 0xC6, 0xF8, ++0x04, 0xC0, 0xF3, 0xF7, 0x43, 0xF9, 0x60, 0x4A, 0xF3, 0x68, 0x92, 0xF8, 0xB8, 0x20, 0x3A, 0x33, 0xF3, 0x60, 0x38, 0x46, ++0x00, 0x2A, 0x40, 0xF0, 0xA7, 0x80, 0xD6, 0xE9, 0x01, 0x12, 0xF3, 0xF7, 0xD3, 0xF8, 0x5A, 0x49, 0x0A, 0x78, 0x00, 0x23, ++0x42, 0xF0, 0x01, 0x02, 0x0A, 0x70, 0x73, 0x60, 0xF3, 0x60, 0x33, 0x60, 0xB3, 0x60, 0x86, 0xF8, 0x20, 0x30, 0x68, 0xE7, ++0x54, 0x4D, 0x42, 0xF2, 0x24, 0x03, 0xEA, 0x58, 0x00, 0x2A, 0x68, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x4A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x42, 0xF2, 0x34, 0x02, 0xDF, 0xF8, 0x44, 0x81, 0xA8, 0x5A, 0xD8, 0xF8, ++0x00, 0x30, 0x02, 0x91, 0x01, 0x33, 0xB0, 0xF5, 0xC3, 0x7F, 0xC8, 0xF8, 0x00, 0x30, 0x48, 0x48, 0xDF, 0xF8, 0x3C, 0xA1, ++0x84, 0xBF, 0x00, 0x23, 0xAB, 0x52, 0x0D, 0xF0, 0xD7, 0xFE, 0x45, 0x4A, 0x02, 0x99, 0xD2, 0xF8, 0x00, 0xC0, 0x42, 0xF2, ++0x34, 0x0E, 0x07, 0x46, 0x35, 0xF8, 0x0E, 0x30, 0xBB, 0x81, 0x0C, 0xEB, 0xC3, 0x00, 0x04, 0xF1, 0x30, 0x02, 0x42, 0x60, ++0x4C, 0xF8, 0x33, 0xA0, 0xDF, 0xF8, 0x08, 0xC1, 0x78, 0x60, 0x95, 0xF8, 0x02, 0xAC, 0x9C, 0xF8, 0x03, 0x00, 0xD8, 0xF8, ++0x00, 0x20, 0x01, 0x33, 0x0A, 0xF1, 0x01, 0x0A, 0x01, 0x30, 0x25, 0xF8, 0x0E, 0x30, 0x85, 0xF8, 0x02, 0xAC, 0x8C, 0xF8, ++0x03, 0x00, 0x3A, 0xB1, 0x2B, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, 0x00, 0x20, 0x0A, 0xB9, 0x00, 0x2B, 0x48, 0xD1, ++0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x7F, 0xF4, 0xFE, 0xAE, 0xDF, 0xF8, 0xC4, 0x80, 0x00, 0x23, 0xD8, 0xF8, 0xB4, 0x52, ++0x21, 0xE7, 0x23, 0x7C, 0x29, 0x48, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x0F, 0xF0, 0x2E, 0xF8, 0x20, 0x4B, 0x83, 0xF8, ++0x20, 0x70, 0x26, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x76, 0xF8, 0x23, 0x7C, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, ++0xF9, 0xE6, 0x03, 0x7C, 0xDF, 0xF8, 0x8C, 0x80, 0x43, 0xF0, 0x01, 0x03, 0x03, 0x74, 0xD8, 0xF8, 0x98, 0x32, 0x61, 0x46, ++0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x19, 0x4C, ++0xD8, 0xF8, 0x44, 0x24, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x01, 0x46, 0x33, 0xB1, 0x0A, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x11, 0x48, 0xF0, 0xF7, 0x31, 0xFE, 0xE0, 0xE6, ++0xFF, 0xF7, 0x7E, 0xFE, 0x59, 0xE7, 0x62, 0xB6, 0xB4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x24, 0x65, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x30, 0x65, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x9C, 0x4E, 0x17, 0x00, ++0x7C, 0x36, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, 0x0C, 0x97, 0x15, 0x00, 0x20, 0x97, 0x15, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xF8, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x54, 0x65, 0x17, 0x00, 0x3C, 0x00, 0x00, 0xC0, ++0x2D, 0xE9, 0xF0, 0x4F, 0xAE, 0x4B, 0xDF, 0xF8, 0x00, 0xA3, 0xC1, 0x69, 0x9A, 0xF8, 0x32, 0x20, 0x1B, 0x68, 0x87, 0xB0, ++0x04, 0x46, 0x05, 0x91, 0xAD, 0xF8, 0x12, 0x20, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xF0, 0x3F, 0x81, 0x02, 0x2B, 0x77, 0xD0, ++0xA6, 0x4A, 0x27, 0x8E, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xBF, 0x80, 0x01, 0x2B, 0xA3, 0x4E, ++0x4F, 0xF0, 0x00, 0x03, 0x00, 0xF0, 0x3A, 0x81, 0xCD, 0xE9, 0x00, 0x33, 0x39, 0x46, 0xD6, 0xF8, 0xAC, 0x52, 0x0D, 0xF1, ++0x12, 0x03, 0x5A, 0x46, 0x05, 0xA8, 0xA8, 0x47, 0x07, 0xEB, 0x0B, 0x01, 0xCA, 0xF8, 0x1C, 0x10, 0x07, 0x46, 0x00, 0x21, ++0x04, 0xF1, 0x58, 0x00, 0xEB, 0xF7, 0x7E, 0xFD, 0x94, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xF0, 0xB8, 0x80, ++0x01, 0x2B, 0x00, 0xF0, 0x49, 0x81, 0x02, 0x2B, 0x41, 0xD1, 0xDF, 0xF8, 0x88, 0xA2, 0x9A, 0xF8, 0x02, 0x30, 0x00, 0x2B, ++0x3B, 0xD0, 0xBA, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x04, 0x20, 0x3A, 0x33, 0xC8, 0xF8, 0x08, 0x30, 0xD3, 0x78, 0x6F, 0xF3, ++0x87, 0x13, 0xD3, 0x70, 0x9A, 0xF8, 0x03, 0x30, 0x88, 0xF8, 0x0E, 0x30, 0x00, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xEF, 0xF3, ++0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x83, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x14, 0xB2, 0x82, 0x48, ++0xDB, 0xF8, 0x00, 0x30, 0x41, 0x46, 0x01, 0x33, 0xCB, 0xF8, 0x00, 0x30, 0x0D, 0xF0, 0x8C, 0xFD, 0xD6, 0xF8, 0x44, 0x34, ++0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x79, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x72, 0x4B, 0x1A, 0x68, 0x00, 0x23, 0xCA, 0xE9, 0x00, 0x33, 0x13, 0x78, 0x03, 0x2B, 0x00, 0xF0, ++0x9E, 0x81, 0xD6, 0xF8, 0x98, 0x32, 0x05, 0x99, 0x3A, 0x46, 0x20, 0x46, 0x98, 0x47, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x6E, 0x4E, 0x42, 0xF2, 0x24, 0x03, 0xF2, 0x58, 0x00, 0x2A, 0x00, 0xF0, 0x60, 0x81, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x66, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x42, 0xF2, 0x34, 0x02, 0x67, 0x4F, 0xB1, 0x5A, 0x3B, 0x68, ++0x66, 0x48, 0x01, 0x33, 0xB1, 0xF5, 0xC3, 0x7F, 0x3B, 0x60, 0x84, 0xBF, 0x00, 0x23, 0xB3, 0x52, 0x0D, 0xF0, 0x92, 0xFD, ++0x62, 0x4A, 0x42, 0xF2, 0x34, 0x0E, 0xD2, 0xF8, 0x00, 0xC0, 0x36, 0xF8, 0x0E, 0x30, 0x83, 0x81, 0x0C, 0xEB, 0xC3, 0x01, ++0x04, 0xF1, 0x30, 0x02, 0x4A, 0x60, 0x5D, 0x4A, 0x4C, 0xF8, 0x33, 0x20, 0xDF, 0xF8, 0x94, 0xC1, 0x41, 0x60, 0x96, 0xF8, ++0x02, 0x1C, 0x9C, 0xF8, 0x03, 0x20, 0x80, 0x46, 0x38, 0x68, 0x01, 0x33, 0x01, 0x31, 0x01, 0x32, 0x26, 0xF8, 0x0E, 0x30, ++0x86, 0xF8, 0x02, 0x1C, 0x8C, 0xF8, 0x03, 0x20, 0x30, 0xB1, 0x4C, 0x4B, 0x01, 0x38, 0x1B, 0x68, 0x38, 0x60, 0x08, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x46, 0x4B, 0x27, 0x8E, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0xDA, 0x00, 0x2F, ++0x00, 0xF0, 0x07, 0x81, 0xB7, 0xF5, 0x40, 0x5F, 0x00, 0xF2, 0x0A, 0x81, 0x3E, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, ++0x7F, 0xF4, 0x34, 0xAF, 0x3D, 0x4E, 0x39, 0x46, 0xD6, 0xF8, 0xB4, 0x72, 0x00, 0x23, 0x00, 0x93, 0x0D, 0xF1, 0x12, 0x02, ++0x05, 0xA8, 0xB8, 0x47, 0x07, 0x46, 0x3C, 0xE7, 0x3F, 0x4A, 0x40, 0x48, 0x53, 0x68, 0x60, 0x66, 0x04, 0xF1, 0x30, 0x00, ++0xA0, 0x66, 0x04, 0xF1, 0x68, 0x00, 0x3D, 0x49, 0xC4, 0xF8, 0x6C, 0x90, 0x18, 0x62, 0x3A, 0x23, 0x21, 0x67, 0x63, 0x67, ++0x4F, 0xF0, 0x04, 0x11, 0xA3, 0x67, 0x00, 0x23, 0x03, 0x90, 0xE1, 0x67, 0xC4, 0xF8, 0x88, 0x30, 0x10, 0x68, 0x03, 0x99, ++0x05, 0x22, 0xF0, 0xF7, 0xC5, 0xF9, 0x34, 0x4A, 0x13, 0x68, 0x18, 0x05, 0xFC, 0xD5, 0x13, 0x68, 0x59, 0x03, 0x03, 0xD5, ++0x11, 0x68, 0x41, 0xF0, 0x80, 0x61, 0x11, 0x60, 0x1A, 0x05, 0x21, 0xD5, 0xEF, 0xF3, 0x05, 0x80, 0x2D, 0x49, 0x41, 0xF2, ++0x4C, 0x12, 0x8B, 0x58, 0x43, 0xF0, 0x00, 0x63, 0x8B, 0x50, 0x00, 0x28, 0x40, 0xF0, 0xF3, 0x80, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1C, 0x4B, 0x25, 0x48, 0x19, 0x68, 0x00, 0x25, ++0x4A, 0x1C, 0x1A, 0x60, 0x45, 0x61, 0x2A, 0xB1, 0x15, 0x4A, 0x19, 0x60, 0x13, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, ++0x1F, 0x4D, 0x2B, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x1E, 0x4B, 0x18, 0x68, 0xA9, 0xF1, 0x14, 0x01, 0x00, 0xF5, 0x0B, 0x70, ++0x0D, 0xF0, 0xAC, 0xFC, 0x01, 0x23, 0x2B, 0x60, 0xEF, 0xF7, 0x2E, 0xFD, 0x31, 0xE7, 0x0A, 0xF1, 0x40, 0x00, 0x0F, 0xF0, ++0x67, 0xF9, 0x05, 0x4B, 0x1B, 0x68, 0x81, 0x46, 0x1B, 0x78, 0x00, 0xF1, 0x3C, 0x0B, 0xB5, 0xE6, 0x39, 0x46, 0xD6, 0xF8, ++0xB0, 0x72, 0x8C, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0xA8, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x3C, 0x00, 0x00, 0xC0, 0x60, 0x65, 0x17, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x3A, 0x00, 0x00, 0xA3, 0x4C, 0x11, 0x07, 0x40, ++0x00, 0x00, 0x07, 0x40, 0x48, 0x35, 0x17, 0x00, 0x54, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0xB0, 0xDE, 0x17, 0x00, ++0x54, 0x65, 0x17, 0x00, 0xF1, 0xF7, 0x92, 0xFE, 0x83, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0xDF, 0xF8, 0x38, 0xA1, 0x9A, 0xF8, ++0x20, 0x30, 0x00, 0x2B, 0x41, 0xD0, 0xDA, 0xF8, 0x04, 0x30, 0x81, 0x68, 0xDA, 0xF8, 0x00, 0x20, 0x03, 0xF1, 0x01, 0x0C, ++0x4F, 0xEA, 0x0C, 0x63, 0x21, 0xF0, 0xFE, 0x41, 0x03, 0xF0, 0xFE, 0x43, 0x0B, 0x43, 0x00, 0x21, 0x83, 0x60, 0x00, 0x91, ++0x3A, 0x23, 0x04, 0xF1, 0x30, 0x01, 0xCA, 0xF8, 0x04, 0xC0, 0xF2, 0xF7, 0xBF, 0xFE, 0x3C, 0x4A, 0xDA, 0xF8, 0x0C, 0x30, ++0x92, 0xF8, 0xB8, 0x20, 0x3A, 0x33, 0xCA, 0xF8, 0x0C, 0x30, 0x58, 0x46, 0x00, 0x2A, 0x63, 0xD1, 0xDA, 0xE9, 0x01, 0x12, ++0xF2, 0xF7, 0x4E, 0xFE, 0x35, 0x49, 0x0A, 0x78, 0x00, 0x23, 0x42, 0xF0, 0x01, 0x02, 0x0A, 0x70, 0xCA, 0xF8, 0x04, 0x30, ++0xCA, 0xF8, 0x0C, 0x30, 0xCA, 0xF8, 0x00, 0x30, 0xCA, 0xF8, 0x08, 0x30, 0x8A, 0xF8, 0x20, 0x30, 0x12, 0xE0, 0x23, 0x7C, ++0x2D, 0x48, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x0E, 0xF0, 0x00, 0xFE, 0x2B, 0x4B, 0x83, 0xF8, 0x20, 0xB0, 0x2B, 0x49, ++0x4F, 0xF4, 0x80, 0x60, 0x0E, 0xF0, 0x48, 0xFE, 0x23, 0x7C, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x27, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x02, 0x2B, 0x3F, 0xF4, 0x5D, 0xAE, 0x9A, 0xE6, 0x25, 0x49, 0x25, 0x48, 0x40, 0xF2, 0x21, 0x52, 0x0F, 0xF0, ++0x2F, 0xF8, 0x9C, 0xE6, 0x21, 0x49, 0x23, 0x48, 0x40, 0xF2, 0x23, 0x52, 0x0F, 0xF0, 0x28, 0xF8, 0x95, 0xE6, 0x23, 0x7C, ++0x20, 0x4E, 0x05, 0x99, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0xD6, 0xF8, 0x98, 0x32, 0x20, 0x46, 0x98, 0x47, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1A, 0x4C, 0xD6, 0xF8, 0x44, 0x24, ++0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x01, 0x46, 0x33, 0xB1, 0x14, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x12, 0x48, 0xF0, 0xF7, 0xEF, 0xFB, 0x6E, 0xE6, 0xFF, 0xF7, 0x3C, 0xFC, ++0x9C, 0xE7, 0x10, 0x4B, 0x00, 0x22, 0x5A, 0x61, 0x1E, 0xE7, 0x0F, 0x4A, 0xE8, 0xE6, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, ++0x9C, 0x4E, 0x17, 0x00, 0x0C, 0x97, 0x15, 0x00, 0x30, 0x65, 0x17, 0x00, 0x20, 0x97, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x34, 0x97, 0x15, 0x00, 0x44, 0x97, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xFC, 0x96, 0x15, 0x00, 0x48, 0x35, 0x17, 0x00, 0x60, 0x65, 0x17, 0x00, 0x0D, 0x4B, 0xC1, 0x69, ++0xD3, 0xF8, 0x98, 0x32, 0x10, 0xB5, 0x00, 0x22, 0x04, 0x46, 0x98, 0x47, 0x0A, 0x48, 0x03, 0x68, 0x53, 0xB1, 0x23, 0x7C, ++0x43, 0xF0, 0x01, 0x03, 0x00, 0x22, 0x23, 0x74, 0x62, 0x60, 0x21, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x0D, 0xF0, 0xA0, 0xBB, ++0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x19, 0xBB, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x24, 0x65, 0x17, 0x00, ++0x0C, 0x4A, 0x0D, 0x49, 0x93, 0x68, 0x09, 0x68, 0x8B, 0x42, 0x11, 0xD0, 0x51, 0x68, 0x23, 0xF0, 0x00, 0x40, 0x09, 0x1A, ++0x9F, 0x29, 0x0C, 0xD8, 0x11, 0x68, 0x03, 0xF0, 0x00, 0x43, 0x88, 0x42, 0x88, 0xBF, 0x03, 0xF1, 0x00, 0x43, 0x0B, 0x43, ++0x93, 0x60, 0x23, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0xEC, 0x34, 0x17, 0x00, 0xD4, 0x81, 0x32, 0x40, ++0x1E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x21, 0xDB, 0x1B, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x9B, 0x07, 0x04, 0xD5, 0x63, 0x6D, 0x03, 0xF0, 0x3C, 0x03, 0x3C, 0x2B, 0x25, 0xD0, 0x23, 0x8E, 0x53, 0xB1, ++0x62, 0x6D, 0x02, 0xF0, 0x7C, 0x02, 0x08, 0x2A, 0x0D, 0xD0, 0x0C, 0x2A, 0x19, 0xD0, 0x04, 0x2A, 0x09, 0xD0, 0x04, 0x3B, ++0x23, 0x86, 0x00, 0x23, 0x10, 0x4A, 0x23, 0x74, 0x84, 0xF8, 0x9C, 0x30, 0xE4, 0x60, 0x62, 0x60, 0x10, 0xBD, 0x08, 0x3B, ++0x23, 0x86, 0xF4, 0xE7, 0x0C, 0x4B, 0x42, 0x69, 0x9A, 0x42, 0xD9, 0xD0, 0x0B, 0x49, 0x0C, 0x48, 0x40, 0xF2, 0x14, 0x62, ++0x0E, 0xF0, 0x98, 0xFF, 0xD2, 0xE7, 0x0C, 0x3B, 0x23, 0x86, 0xE6, 0xE7, 0x23, 0x8E, 0x04, 0x3B, 0x9B, 0xB2, 0x23, 0x86, ++0xD5, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x3D, 0x48, 0x13, 0x00, 0x0D, 0xF0, 0xAD, 0xBA, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x97, 0x15, 0x00, 0x06, 0x4B, 0x07, 0x4A, 0x4F, 0xF4, 0x80, 0x31, 0x19, 0x60, 0x13, 0x68, ++0x23, 0xF4, 0x80, 0x33, 0x13, 0x60, 0x4F, 0xF4, 0x80, 0x10, 0x0D, 0xF0, 0x7F, 0xBA, 0x00, 0xBF, 0x7C, 0x80, 0x32, 0x40, ++0x80, 0x80, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x47, 0x21, 0x4D, 0x22, 0x4E, 0x6B, 0x69, 0x32, 0x68, 0x93, 0x42, 0x84, 0xB0, ++0x38, 0xD0, 0xDF, 0xF8, 0x88, 0x80, 0x1F, 0x4F, 0xDF, 0xF8, 0x84, 0x90, 0x20, 0xE0, 0x6B, 0x69, 0x1D, 0x48, 0x23, 0xF0, ++0x00, 0x44, 0x21, 0x46, 0x62, 0x69, 0xBA, 0x42, 0x0A, 0xD0, 0xD6, 0xF8, 0x00, 0xE0, 0xD9, 0xF8, 0x00, 0xA0, 0xCD, 0xE9, ++0x00, 0xC3, 0xCD, 0xE9, 0x02, 0xEA, 0xEB, 0x68, 0x0E, 0xF0, 0xD4, 0xFC, 0x20, 0x46, 0xFF, 0xF7, 0x7F, 0xFF, 0x01, 0x23, ++0x84, 0xF8, 0x9C, 0x30, 0xD8, 0xF8, 0xC0, 0x32, 0x20, 0x46, 0x98, 0x47, 0x6B, 0x69, 0x32, 0x68, 0x93, 0x42, 0x11, 0xD0, ++0xD5, 0xF8, 0x10, 0xC0, 0x23, 0xF0, 0x00, 0x41, 0xAC, 0xEB, 0x01, 0x02, 0x9F, 0x2A, 0x03, 0xF0, 0x00, 0x43, 0xD4, 0xD8, ++0xEA, 0x68, 0x91, 0x42, 0x88, 0xBF, 0x03, 0xF1, 0x00, 0x43, 0x13, 0x43, 0x6B, 0x61, 0xCD, 0xE7, 0x04, 0xB0, 0xBD, 0xE8, ++0xF0, 0x87, 0x00, 0xBF, 0xEC, 0x34, 0x17, 0x00, 0xE4, 0x81, 0x32, 0x40, 0x0D, 0xF0, 0xAD, 0xBA, 0x90, 0x97, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xE0, 0x81, 0x32, 0x40, 0x00, 0xB5, 0x10, 0x4A, 0x10, 0x4B, 0x12, 0x68, 0x89, 0xB0, 0x08, 0x33, ++0x03, 0x92, 0x53, 0xF8, 0x08, 0x2C, 0x04, 0x92, 0x53, 0xF8, 0x04, 0x2C, 0x05, 0x92, 0x1B, 0x68, 0x06, 0x93, 0x01, 0xA8, ++0x00, 0x21, 0xEB, 0xF7, 0x73, 0xFA, 0x03, 0x9B, 0x03, 0xF0, 0x0F, 0x03, 0x02, 0x2B, 0x02, 0xD0, 0x09, 0xB0, 0x5D, 0xF8, ++0x04, 0xFB, 0x01, 0xA8, 0x0E, 0xF0, 0x8C, 0xFF, 0x09, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x00, 0xBF, 0xB0, 0x10, 0x34, 0x40, ++0xB4, 0x10, 0x34, 0x40, 0x38, 0xB5, 0xD0, 0xF8, 0xFC, 0x31, 0x04, 0x46, 0x00, 0xF5, 0xFE, 0x75, 0x4B, 0xB1, 0x28, 0x46, ++0x0D, 0xF0, 0xDE, 0xFA, 0x01, 0x21, 0xFA, 0xF7, 0x2B, 0xF9, 0xD4, 0xF8, 0xFC, 0x31, 0x00, 0x2B, 0xF5, 0xD1, 0x4F, 0xF4, ++0x1E, 0x72, 0x00, 0x21, 0x20, 0x46, 0xEA, 0xF7, 0xF9, 0xF9, 0x23, 0x46, 0x04, 0xF1, 0x48, 0x01, 0x21, 0x22, 0x83, 0xF8, ++0xA4, 0x21, 0x83, 0xF8, 0xA5, 0x21, 0x08, 0x33, 0x8B, 0x42, 0xF8, 0xD1, 0xFF, 0x23, 0x84, 0xF8, 0x22, 0x30, 0x38, 0xBD, ++0x2D, 0xE9, 0xF0, 0x43, 0x49, 0x48, 0x4A, 0x4F, 0x83, 0xB0, 0x81, 0x46, 0x0D, 0xF0, 0x72, 0xFA, 0x07, 0xF5, 0x0C, 0x75, ++0x00, 0x26, 0x40, 0xF2, 0x16, 0x38, 0xA5, 0xF5, 0x0C, 0x71, 0x08, 0x46, 0x01, 0x91, 0xFF, 0xF7, 0xC7, 0xFF, 0x01, 0x99, ++0x48, 0x46, 0x0D, 0xF0, 0x67, 0xFA, 0xA5, 0xF1, 0x28, 0x04, 0x20, 0x46, 0x0D, 0xF0, 0x5E, 0xFA, 0x04, 0xF1, 0x28, 0x00, ++0x08, 0x34, 0x0D, 0xF0, 0x59, 0xFA, 0xAC, 0x42, 0xF5, 0xD1, 0x4F, 0x36, 0x46, 0x45, 0x04, 0xF5, 0x1E, 0x75, 0xE4, 0xD1, ++0x38, 0x4D, 0x40, 0xF2, 0x52, 0x48, 0xA5, 0xF1, 0x28, 0x04, 0x20, 0x46, 0x0D, 0xF0, 0x4A, 0xFA, 0x04, 0xF1, 0x28, 0x00, ++0x08, 0x34, 0x0D, 0xF0, 0x45, 0xFA, 0xAC, 0x42, 0xF5, 0xD1, 0x4F, 0x36, 0x46, 0x45, 0x04, 0xF5, 0x1E, 0x75, 0xEE, 0xD1, ++0x2F, 0x48, 0x30, 0x4D, 0x30, 0x4C, 0x00, 0xF1, 0x30, 0x06, 0xFF, 0xF7, 0x97, 0xFF, 0x41, 0xF6, 0xF8, 0x12, 0x4F, 0xF0, ++0x00, 0x08, 0x41, 0xF6, 0x64, 0x11, 0x41, 0xF6, 0xD0, 0x03, 0xBD, 0x50, 0x06, 0xF5, 0x12, 0x70, 0x86, 0xF8, 0x00, 0x80, ++0x4F, 0xF0, 0x20, 0x62, 0x7C, 0x50, 0xFA, 0x50, 0xFF, 0xF7, 0x84, 0xFF, 0x41, 0xF6, 0x58, 0x30, 0x41, 0xF6, 0x70, 0x41, ++0x07, 0xF8, 0x00, 0x80, 0x41, 0xF6, 0xDC, 0x32, 0x05, 0xF1, 0x40, 0x00, 0x78, 0x50, 0x41, 0xF6, 0x48, 0x33, 0x04, 0xF5, ++0xA4, 0x61, 0xB9, 0x50, 0x06, 0xF5, 0x98, 0x60, 0x1C, 0x4A, 0xFA, 0x50, 0xFF, 0xF7, 0x6E, 0xFF, 0x41, 0xF6, 0xD0, 0x52, ++0x41, 0xF6, 0xE8, 0x61, 0x41, 0xF6, 0x54, 0x63, 0x18, 0x48, 0x07, 0xF8, 0x02, 0x80, 0xC6, 0xF8, 0xE0, 0x04, 0x04, 0xF5, ++0x24, 0x62, 0x06, 0xF5, 0xE7, 0x60, 0x05, 0xF1, 0x80, 0x06, 0x7E, 0x50, 0xFA, 0x50, 0xFF, 0xF7, 0x59, 0xFF, 0x42, 0xF2, ++0x60, 0x16, 0x11, 0x4A, 0x42, 0xF2, 0xCC, 0x00, 0x42, 0xF2, 0x48, 0x01, 0x42, 0xF2, 0x38, 0x03, 0xC0, 0x35, 0x04, 0xF5, ++0x76, 0x64, 0xBD, 0x51, 0x3C, 0x50, 0x07, 0xF8, 0x01, 0x80, 0xFA, 0x50, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x00, 0xBF, ++0xF8, 0x87, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x48, 0x80, 0x17, 0x00, 0x18, 0x7E, 0x17, 0x00, 0x04, 0x38, 0x18, 0x00, ++0xC0, 0x8C, 0x17, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x02, 0x0C, 0x00, 0x00, 0x03, 0x0D, 0x2D, 0xE9, 0xF0, 0x41, ++0x05, 0x46, 0x79, 0x48, 0x95, 0xF8, 0x19, 0x80, 0x0E, 0x46, 0x0D, 0xF0, 0x11, 0xFA, 0x00, 0x28, 0x00, 0xF0, 0xE1, 0x80, ++0x6B, 0x7F, 0x04, 0x46, 0x00, 0x2B, 0x40, 0xF0, 0xA5, 0x80, 0x73, 0x4F, 0x05, 0xF1, 0x12, 0x02, 0x11, 0x68, 0x2B, 0x68, ++0x92, 0x88, 0x62, 0x85, 0xC4, 0xF8, 0x26, 0x10, 0x63, 0x60, 0x28, 0x7E, 0x6E, 0x4B, 0x6F, 0x4A, 0x6F, 0x49, 0x10, 0x28, ++0x38, 0xBF, 0x10, 0x20, 0x20, 0x77, 0x28, 0x8A, 0xA0, 0x82, 0xA8, 0x68, 0x20, 0x61, 0x68, 0x68, 0xE0, 0x60, 0xE8, 0x68, ++0xA0, 0x61, 0xE0, 0x1B, 0xC0, 0x10, 0x03, 0xFB, 0x00, 0xF3, 0xDB, 0xB2, 0x68, 0x7E, 0x84, 0xF8, 0x22, 0x00, 0x33, 0x70, ++0x4F, 0xF4, 0x80, 0x70, 0x84, 0xF8, 0x23, 0x30, 0x0E, 0xF0, 0xC6, 0xFB, 0x62, 0x48, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x08, 0x03, 0x4F, 0xF4, 0xC8, 0x31, 0x93, 0xF8, 0xC0, 0x24, 0xA1, 0x60, 0x22, 0xB1, 0x93, 0xF8, 0xC2, 0x24, 0x01, 0x32, ++0x83, 0xF8, 0xC2, 0x24, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xF8, 0xE8, 0x11, 0x04, 0xF5, 0xF4, 0x72, 0x23, 0x46, 0x04, 0xF5, ++0xFD, 0x75, 0x22, 0xF8, 0x02, 0x1F, 0xAA, 0x42, 0xFB, 0xD1, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x08, 0xF8, 0x00, 0xEB, ++0x08, 0x05, 0x00, 0x22, 0x31, 0x78, 0x84, 0xF8, 0x30, 0x20, 0xD5, 0xF8, 0xB0, 0x54, 0x4F, 0x4A, 0x02, 0xEB, 0x81, 0x12, ++0x29, 0x07, 0xC4, 0xF8, 0x48, 0x21, 0x4D, 0x49, 0x56, 0xBF, 0x08, 0xF5, 0x95, 0x62, 0x04, 0xF1, 0xB0, 0x02, 0x12, 0x18, ++0xC4, 0xF8, 0xB4, 0x20, 0x0A, 0x69, 0xA2, 0xF5, 0x74, 0x22, 0xA2, 0xF5, 0x10, 0x72, 0x04, 0xF1, 0x48, 0x01, 0xC3, 0xF8, ++0xA0, 0x21, 0x08, 0x33, 0x8B, 0x42, 0xFA, 0xD1, 0xEA, 0x06, 0x03, 0xD5, 0x63, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x63, 0x60, ++0x08, 0xF1, 0xE4, 0x08, 0x40, 0x44, 0x21, 0x46, 0x0D, 0xF0, 0x4C, 0xF9, 0x3D, 0x4B, 0xC4, 0xF8, 0x04, 0x32, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x3A, 0x4B, 0xE0, 0x6A, 0x1A, 0x68, ++0x01, 0x25, 0x51, 0x19, 0x19, 0x60, 0x84, 0xF8, 0x25, 0x50, 0x08, 0xB1, 0x80, 0xF8, 0x25, 0x50, 0x21, 0xB1, 0x33, 0x49, ++0x1A, 0x60, 0x0B, 0x68, 0x00, 0x2A, 0x42, 0xD0, 0xF6, 0xB2, 0x0D, 0x2E, 0x07, 0xD8, 0x4F, 0xF4, 0x1E, 0x73, 0x2C, 0x4A, ++0x06, 0xFB, 0x03, 0x76, 0x13, 0x69, 0xC6, 0xF8, 0x58, 0x32, 0x00, 0x20, 0x84, 0xF8, 0x5C, 0x02, 0xBD, 0xE8, 0xF0, 0x81, ++0x1F, 0x48, 0x0D, 0xF0, 0x61, 0xF9, 0x00, 0x28, 0x34, 0xD0, 0x2A, 0x46, 0xE0, 0x62, 0xC4, 0x62, 0xA9, 0x7F, 0x52, 0xF8, ++0x12, 0x3F, 0x95, 0xF8, 0x1D, 0xC0, 0xC0, 0xF8, 0x26, 0x30, 0x01, 0x23, 0x8B, 0x40, 0x91, 0x88, 0x41, 0x85, 0x01, 0x3B, ++0x41, 0x8D, 0x16, 0x4F, 0x1B, 0x02, 0x1B, 0xB2, 0x21, 0xEA, 0x03, 0x01, 0x09, 0xB2, 0x41, 0x85, 0xB5, 0xF8, 0x16, 0xE0, ++0xAE, 0xEB, 0x0C, 0x2C, 0x03, 0xEA, 0x0C, 0x03, 0xA0, 0xEB, 0x07, 0x0E, 0xDF, 0xF8, 0x3C, 0xC0, 0x4F, 0xEA, 0xEE, 0x0E, ++0x0B, 0x43, 0x0C, 0xFB, 0x0E, 0xF1, 0x4F, 0xF0, 0xFF, 0x0C, 0x43, 0x85, 0x80, 0xF8, 0x23, 0x10, 0xA0, 0xF8, 0x20, 0xC0, ++0x2A, 0xE7, 0x00, 0x2B, 0xBA, 0xD0, 0x62, 0xB6, 0xB8, 0xE7, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x48, 0x21, 0x46, ++0x0D, 0xF0, 0xE2, 0xF8, 0x01, 0x20, 0xBD, 0xE7, 0xF8, 0x87, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xAF, 0x16, 0x37, 0x61, ++0xEC, 0x97, 0x15, 0x00, 0xDC, 0x97, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x04, 0x39, 0x18, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x0F, 0xCC, 0xFF, 0xFF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x33, 0x4F, 0xDF, 0xF8, ++0xE4, 0x80, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x74, 0x4F, 0xF4, 0xA4, 0x63, 0x94, 0xF8, 0x22, 0x60, 0x03, 0xFB, ++0x06, 0x83, 0x05, 0x46, 0x93, 0xF8, 0xC0, 0x24, 0x22, 0xB1, 0x93, 0xF8, 0xC2, 0x24, 0x01, 0x3A, 0x83, 0xF8, 0xC2, 0x24, ++0x29, 0x4A, 0x2A, 0x49, 0x2B, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0E, 0xF0, 0xD5, 0xFA, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, ++0x06, 0x80, 0xE4, 0x30, 0x21, 0x46, 0x0D, 0xF0, 0xF3, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x21, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x21, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x73, 0x11, 0x68, 0xD8, 0x6A, ++0x4E, 0x1C, 0x4F, 0xF0, 0x00, 0x0C, 0x16, 0x60, 0x83, 0xF8, 0x25, 0xC0, 0xD8, 0xB1, 0x80, 0xF8, 0x25, 0xC0, 0x96, 0xB9, ++0xFF, 0xF7, 0xE4, 0xFD, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x75, 0x16, 0x48, 0xE9, 0x6A, 0x0D, 0xF0, 0x80, 0xF8, ++0x20, 0x46, 0xFF, 0xF7, 0xD9, 0xFD, 0x21, 0x46, 0x12, 0x48, 0xBD, 0xE8, 0xF0, 0x41, 0x0D, 0xF0, 0x77, 0xB8, 0x0E, 0x48, ++0x11, 0x60, 0x02, 0x68, 0x41, 0xB1, 0xD8, 0x6A, 0xE6, 0xE7, 0x00, 0x2E, 0xEE, 0xD0, 0x0A, 0x4B, 0x11, 0x60, 0x1A, 0x68, ++0x00, 0x29, 0xE9, 0xD1, 0x02, 0xB1, 0x62, 0xB6, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x73, 0xD8, 0x6A, 0x00, 0x28, ++0xE0, 0xD0, 0xD5, 0xE7, 0x68, 0x65, 0x17, 0x00, 0x00, 0x98, 0x15, 0x00, 0xDC, 0x97, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xF8, 0x87, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x44, 0x78, 0xDF, 0xF8, ++0x14, 0x81, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0xF6, 0x08, 0xEB, 0x06, 0x07, 0x38, 0x36, 0x87, 0xF8, 0x9A, 0x10, ++0x90, 0xF8, 0x28, 0x30, 0x87, 0xF8, 0x98, 0x30, 0x03, 0x78, 0x87, 0xF8, 0x99, 0x30, 0x46, 0x44, 0x05, 0x46, 0x48, 0x22, ++0x30, 0x46, 0x00, 0x21, 0x97, 0xF8, 0x22, 0x90, 0xE9, 0xF7, 0xA0, 0xFF, 0x97, 0xF8, 0x98, 0x30, 0x04, 0x2B, 0x55, 0xD8, ++0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x3F, 0x54, 0x03, 0x27, 0x00, 0x21, 0xF0, 0x29, 0xF8, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x04, 0x83, 0x03, 0xF1, 0x80, 0x02, 0x20, 0xF0, 0x7F, 0x40, 0xC3, 0xF8, 0x80, 0x00, 0x00, 0x23, 0x53, 0x60, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, 0x01, 0x22, 0xD5, 0xE9, 0x02, 0x40, 0x29, 0x69, 0x83, 0xF8, 0x9B, 0x20, 0x6A, 0x69, ++0xC3, 0xF8, 0xB0, 0x60, 0xC3, 0xE9, 0x27, 0x40, 0xC3, 0xE9, 0x29, 0x12, 0x2A, 0x79, 0x83, 0xF8, 0xAC, 0x20, 0xBD, 0xE8, ++0xF8, 0x83, 0x20, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x39, 0x19, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x99, 0xF8, ++0x62, 0x00, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x04, 0x81, 0x02, 0x28, 0xC1, 0xE9, 0x20, 0x23, 0xD7, 0xD1, 0x15, 0xA3, ++0xD3, 0xE9, 0x00, 0x23, 0xC1, 0xE9, 0x20, 0x23, 0xD1, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, 0xAA, 0x69, ++0xC3, 0xF8, 0x88, 0x20, 0xEA, 0x69, 0xC3, 0xF8, 0x8C, 0x20, 0x2A, 0x6A, 0xC3, 0xF8, 0x90, 0x20, 0x00, 0x20, 0x6A, 0x6A, ++0xC3, 0xF8, 0x94, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x20, 0x01, 0xBC, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, ++0x00, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x20, 0x01, 0xB3, 0xE7, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, 0x36, 0x5C, 0x36, 0x5C, ++0x36, 0x5C, 0x36, 0x5C, 0x37, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x23, 0x01, 0x22, 0x80, 0xF8, 0x30, 0x20, 0x80, 0xF8, 0x9B, 0x30, 0xC0, 0xF8, 0xB0, 0x30, 0x70, 0x47, 0x00, 0xBF, ++0x2D, 0xE9, 0xF0, 0x47, 0xD1, 0xF8, 0xFC, 0xA1, 0x82, 0xB0, 0xBA, 0xF1, 0x00, 0x0F, 0x32, 0xD0, 0x00, 0x24, 0xDF, 0xF8, ++0x6C, 0x80, 0x0D, 0x46, 0x06, 0x46, 0x91, 0x46, 0x27, 0x46, 0x10, 0xE0, 0x80, 0xF8, 0x5D, 0x70, 0xD8, 0xF8, 0x98, 0x33, ++0xC1, 0x7E, 0x01, 0x34, 0x98, 0x47, 0xB9, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x4C, 0x45, 0x1F, 0xD0, 0xD5, 0xF8, 0xFC, 0xA1, ++0xBA, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x30, 0x46, 0x01, 0x97, 0xF8, 0xF7, 0x6B, 0xFA, 0x03, 0x46, 0x50, 0x46, 0x9B, 0xB1, ++0x15, 0xF0, 0x34, 0xFC, 0x03, 0x46, 0x01, 0xAA, 0x29, 0x46, 0x30, 0x46, 0x63, 0xB1, 0xD8, 0xF8, 0x10, 0x30, 0x98, 0x47, ++0x01, 0x9B, 0x3B, 0xB9, 0x00, 0x28, 0xD9, 0xD1, 0x05, 0xF5, 0xFE, 0x70, 0x0C, 0xF0, 0xC2, 0xFF, 0xD4, 0xE7, 0x54, 0x46, ++0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x88, 0x1A, 0x17, 0x00, 0x0A, 0x4B, 0x9B, 0x68, 0x93, 0xF8, 0x62, 0x20, ++0x7A, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x62, 0xB1, 0x93, 0xF8, 0x6D, 0x20, 0x4A, 0xB1, 0x93, 0xF8, 0x6E, 0x20, 0x08, 0x2A, ++0x05, 0xD8, 0x01, 0x23, 0x93, 0x40, 0x01, 0x3B, 0x02, 0x4A, 0x1B, 0x02, 0x13, 0x60, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, ++0x2C, 0x00, 0x32, 0x40, 0x10, 0xB5, 0x90, 0xF8, 0xC0, 0x34, 0x04, 0x46, 0x00, 0x2B, 0x2D, 0xD1, 0x23, 0x6C, 0x1B, 0xB1, ++0x1B, 0x4B, 0x20, 0x46, 0x1B, 0x6B, 0x98, 0x47, 0x63, 0x68, 0xD8, 0x07, 0x1A, 0xD5, 0x19, 0x4A, 0x11, 0x68, 0x89, 0x01, ++0x17, 0xD5, 0x23, 0xF0, 0x01, 0x03, 0x63, 0x60, 0x16, 0x4A, 0x41, 0xF2, 0x14, 0x33, 0xD3, 0x5C, 0x01, 0x2B, 0x41, 0xF2, ++0x13, 0x33, 0x8C, 0xBF, 0x01, 0x21, 0x00, 0x21, 0xD1, 0x54, 0x12, 0x4B, 0x93, 0xF8, 0xB6, 0x30, 0x23, 0xB1, 0x11, 0x4B, ++0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x0C, 0xD0, 0x10, 0xBD, 0x12, 0x68, 0x92, 0x01, 0xFB, 0xD4, 0x0D, 0x4A, 0x92, 0xF8, ++0x24, 0x20, 0x00, 0x2A, 0xF6, 0xD0, 0xDE, 0xE7, 0x0A, 0xF0, 0x34, 0xF8, 0xCE, 0xE7, 0xF8, 0xF7, 0x1D, 0xFD, 0x09, 0x4A, ++0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, ++0x00, 0x40, 0x1E, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, ++0x19, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x18, 0x22, 0x80, 0x46, 0x00, 0x21, 0xE9, 0xF7, 0x72, 0xFE, 0x40, 0x46, 0x0C, 0xF0, ++0xFF, 0xFE, 0x08, 0xF1, 0x08, 0x00, 0x14, 0x4C, 0x14, 0x4F, 0x0C, 0xF0, 0xF9, 0xFE, 0x04, 0xF5, 0xA4, 0x56, 0x45, 0x46, ++0x4F, 0xF4, 0xA4, 0x62, 0x00, 0x21, 0x20, 0x46, 0xE9, 0xF7, 0x60, 0xFE, 0x7F, 0x23, 0xD7, 0xF8, 0x50, 0x24, 0x24, 0x63, ++0x05, 0x21, 0x84, 0xF8, 0x62, 0x10, 0x84, 0xF8, 0x65, 0x30, 0x84, 0xF8, 0x66, 0x30, 0xE2, 0x62, 0x21, 0x46, 0x28, 0x46, ++0x04, 0xF5, 0xA4, 0x64, 0x0C, 0xF0, 0xE2, 0xFE, 0xB4, 0x42, 0xE5, 0xD1, 0xFF, 0x23, 0x88, 0xF8, 0x10, 0x30, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x06, 0x4B, ++0x9C, 0x68, 0x3C, 0xB1, 0x05, 0x4D, 0xD5, 0xF8, 0x5C, 0x34, 0x20, 0x46, 0x98, 0x47, 0x24, 0x68, 0x00, 0x2C, 0xF8, 0xD1, ++0x38, 0xBD, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAC, 0x4D, 0x8D, 0xB0, ++0x2C, 0x68, 0x05, 0x90, 0x88, 0x46, 0x17, 0x46, 0x04, 0x93, 0x00, 0x2C, 0x00, 0xF0, 0xA4, 0x80, 0x00, 0x2A, 0x40, 0xF0, ++0x9E, 0x80, 0xAC, 0x68, 0x00, 0x2C, 0x00, 0xF0, 0x42, 0x81, 0x05, 0x9B, 0xA4, 0x48, 0x1A, 0x68, 0x9B, 0x88, 0x06, 0x92, ++0x4F, 0xF0, 0x00, 0x09, 0x07, 0x93, 0xCB, 0x46, 0xBA, 0x46, 0xE7, 0x6D, 0xB4, 0xF8, 0x60, 0x60, 0x94, 0xF8, 0xC0, 0x34, ++0x39, 0x46, 0x32, 0x46, 0x0E, 0xF0, 0x76, 0xF8, 0x94, 0xF8, 0xC0, 0x34, 0x9A, 0x48, 0x1B, 0xB9, 0x8B, 0xEA, 0x07, 0x0B, ++0x89, 0xEA, 0x06, 0x09, 0x24, 0x68, 0x00, 0x2C, 0xEB, 0xD1, 0x57, 0x46, 0x00, 0x2F, 0x00, 0xF0, 0x99, 0x80, 0x95, 0x4B, ++0x95, 0x48, 0x49, 0xF4, 0x40, 0x74, 0xDD, 0xE9, 0x06, 0x12, 0x1C, 0x60, 0xC0, 0xF8, 0x00, 0xB0, 0x5B, 0x46, 0xCD, 0xE9, ++0x00, 0x97, 0x91, 0x48, 0x0E, 0xF0, 0x58, 0xF8, 0x8B, 0x48, 0x0C, 0xF0, 0xBF, 0xFE, 0x05, 0x99, 0x8E, 0x4A, 0x80, 0xF8, ++0x62, 0x80, 0x04, 0x46, 0x8D, 0x4B, 0x82, 0x1A, 0x08, 0x68, 0xE0, 0x65, 0x52, 0x11, 0x89, 0x88, 0xA4, 0xF8, 0x60, 0x10, ++0x03, 0xFB, 0x02, 0xF2, 0xD3, 0xB2, 0x40, 0xF6, 0x47, 0x21, 0x40, 0xF6, 0x43, 0x22, 0xA1, 0x60, 0xE2, 0x60, 0x86, 0x49, ++0x86, 0x4A, 0x21, 0x61, 0x62, 0x61, 0x40, 0xF2, 0xFF, 0x31, 0x00, 0x22, 0x84, 0xF8, 0xC0, 0x74, 0xA4, 0xF8, 0xBE, 0x14, ++0x84, 0xF8, 0x63, 0x30, 0x84, 0xF8, 0x4C, 0x30, 0x22, 0x64, 0x84, 0xF8, 0x84, 0x20, 0x17, 0xB1, 0xEA, 0x7C, 0x01, 0x32, ++0xEA, 0x74, 0xB8, 0xF1, 0x02, 0x0F, 0x00, 0xF0, 0x89, 0x80, 0xB8, 0xF1, 0x04, 0x0F, 0x00, 0xF0, 0xC3, 0x80, 0xB8, 0xF1, ++0x00, 0x0F, 0x00, 0xF0, 0x9C, 0x80, 0x6B, 0x7C, 0xAA, 0x7C, 0x13, 0x44, 0x01, 0x2B, 0x78, 0xDD, 0x74, 0x48, 0x75, 0x4E, ++0xD0, 0xE9, 0x00, 0x12, 0x42, 0xF4, 0x80, 0x72, 0x11, 0x43, 0x42, 0x60, 0x31, 0x60, 0x01, 0x2B, 0x4D, 0xD0, 0x00, 0x2F, ++0x52, 0xD1, 0x04, 0x9A, 0x94, 0xF8, 0x63, 0x30, 0x6E, 0x48, 0x13, 0x70, 0x21, 0x46, 0x0C, 0xF0, 0x29, 0xFE, 0x04, 0xF5, ++0x99, 0x66, 0x04, 0xF5, 0x9E, 0x69, 0x30, 0x46, 0x0C, 0xF0, 0x1E, 0xFE, 0x06, 0xF1, 0x28, 0x00, 0x08, 0x36, 0x0C, 0xF0, ++0x19, 0xFE, 0x4E, 0x45, 0xF5, 0xD1, 0x04, 0xF5, 0xA3, 0x60, 0x0C, 0xF0, 0x13, 0xFE, 0x00, 0x24, 0x03, 0xE0, 0x63, 0x4B, ++0x1B, 0x78, 0x23, 0xB3, 0x01, 0x24, 0xAA, 0x7C, 0x6B, 0x7C, 0x61, 0x49, 0x13, 0x44, 0x00, 0x20, 0x01, 0x2B, 0x08, 0x60, ++0x04, 0xDC, 0xFF, 0xF7, 0x91, 0xFE, 0xAA, 0x7C, 0x6B, 0x7C, 0x13, 0x44, 0x04, 0x99, 0x09, 0x78, 0x4F, 0xF4, 0x80, 0x70, ++0xCD, 0xE9, 0x02, 0x71, 0xCD, 0xE9, 0x00, 0x28, 0x58, 0x49, 0x59, 0x4A, 0x0E, 0xF0, 0x22, 0xF8, 0x20, 0x46, 0x0D, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x9B, 0x8B, 0xEA, 0x03, 0x0B, 0x07, 0x9B, 0x89, 0xEA, 0x03, 0x09, 0x5F, 0xE7, 0xAC, 0x68, ++0x00, 0x2C, 0x7C, 0xD0, 0xEB, 0x7C, 0x02, 0x2B, 0x7F, 0xF4, 0x37, 0xAF, 0xD2, 0xE7, 0x4F, 0x4A, 0x13, 0x68, 0x43, 0xF0, ++0x01, 0x03, 0x13, 0x60, 0x00, 0x2F, 0xAC, 0xD0, 0xB8, 0xF1, 0x00, 0x01, 0x18, 0xBF, 0x01, 0x21, 0x94, 0xF8, 0x63, 0x00, ++0x09, 0xF0, 0x22, 0xFD, 0x48, 0x4B, 0x84, 0xF8, 0xC1, 0x04, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x9C, 0xDA, ++0xFF, 0x28, 0x9A, 0xD1, 0x44, 0x49, 0x45, 0x48, 0x40, 0xF2, 0x0B, 0x22, 0x0E, 0xF0, 0x1A, 0xFA, 0x93, 0xE7, 0x00, 0x2A, ++0x8D, 0xD0, 0x83, 0xE7, 0xAA, 0x7C, 0x00, 0x2A, 0x00, 0xF0, 0xA8, 0x80, 0x39, 0x46, 0x3F, 0x48, 0x0A, 0x33, 0x4F, 0xF4, ++0x1E, 0x76, 0x06, 0xFB, 0x03, 0x03, 0x01, 0x32, 0x01, 0x20, 0xAA, 0x74, 0x83, 0xF8, 0x25, 0x00, 0x11, 0xB1, 0x3A, 0x4B, ++0xC4, 0xE9, 0x07, 0x34, 0x39, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x80, 0x31, 0x98, 0x47, 0x6B, 0x7C, 0x64, 0xE7, 0x36, 0x4B, ++0x36, 0x49, 0xD3, 0xF8, 0xCC, 0x31, 0xE3, 0x61, 0xFF, 0x23, 0x84, 0xF8, 0x6C, 0x30, 0x34, 0x4A, 0x6B, 0x7C, 0x24, 0x62, ++0xA4, 0xF8, 0x8A, 0x80, 0xC4, 0xF8, 0xB8, 0x40, 0xC4, 0xF8, 0xB4, 0x10, 0x01, 0x33, 0x92, 0xF8, 0x04, 0x21, 0xDB, 0xB2, ++0x6B, 0x74, 0x00, 0x2A, 0x3F, 0xF4, 0x4C, 0xAF, 0x2C, 0x4A, 0xC4, 0xF8, 0xA4, 0x40, 0xC4, 0xE9, 0x24, 0x88, 0xC4, 0xF8, ++0x98, 0x80, 0xC4, 0xF8, 0xA0, 0x20, 0x41, 0xE7, 0x2A, 0x7C, 0xFF, 0x2A, 0x17, 0xD1, 0xAA, 0x68, 0x2B, 0x74, 0x00, 0x2A, ++0x4C, 0xD0, 0x14, 0x49, 0x24, 0x4B, 0x4E, 0x68, 0x12, 0x6C, 0x13, 0x48, 0x0B, 0x60, 0x33, 0x43, 0x03, 0x60, 0x00, 0x2A, ++0x3F, 0xF4, 0x2F, 0xAF, 0x1B, 0x4B, 0x10, 0x7E, 0x1B, 0x6D, 0x98, 0x47, 0x29, 0xE7, 0x05, 0x98, 0x01, 0xF0, 0x4E, 0xFE, ++0xEA, 0xE6, 0x01, 0x24, 0x6E, 0xE7, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x14, 0x98, 0x15, 0x00, 0x1C, 0x00, 0x32, 0x40, ++0x18, 0x00, 0x32, 0x40, 0x2C, 0x98, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x19, 0x9C, 0x8F, 0xC1, 0x32, 0xE4, 0x05, 0x00, ++0x22, 0xF3, 0x02, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0x08, 0x88, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, ++0x2C, 0x00, 0x32, 0x40, 0x74, 0x98, 0x15, 0x00, 0xC8, 0x98, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x50, 0x98, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0xB1, 0x7F, 0x13, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xD5, 0x65, 0x12, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x81, 0x66, 0x12, 0x00, 0xDC, 0xFF, 0xFF, 0x7F, 0x10, 0x4E, 0x11, 0x4A, ++0x09, 0x92, 0x40, 0xF6, 0x85, 0x12, 0xD6, 0xF8, 0xE8, 0x30, 0x0A, 0x92, 0x98, 0x47, 0x73, 0x6C, 0x0D, 0xF1, 0x23, 0x01, ++0x09, 0xA8, 0x98, 0x47, 0x00, 0x28, 0xB6, 0xD1, 0x63, 0x68, 0x32, 0x6D, 0x9D, 0xF8, 0x23, 0x00, 0x43, 0xF0, 0x80, 0x03, ++0x63, 0x60, 0x90, 0x47, 0x6B, 0x7C, 0xD3, 0xE6, 0x01, 0xF0, 0x32, 0xFE, 0xAA, 0x7C, 0x94, 0xF8, 0x63, 0x30, 0x94, 0xF8, ++0xC0, 0x14, 0x50, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x00, 0x85, 0x09, 0x2D, 0xE9, 0xF0, 0x4F, 0x02, 0x46, 0x6A, 0x4D, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xF3, 0x8B, 0xB0, 0xEF, 0x18, 0x04, 0x90, 0x39, 0x46, 0x66, 0x48, 0x06, 0x93, ++0x0C, 0xF0, 0x4A, 0xFD, 0x97, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xDD, 0x80, 0x04, 0x2B, 0x00, 0xF0, 0x98, 0x80, ++0xDF, 0xF8, 0x98, 0xA1, 0x60, 0x4C, 0x00, 0x2B, 0x00, 0xF0, 0x89, 0x80, 0x9A, 0xF8, 0x12, 0x30, 0x9A, 0xF8, 0x11, 0x20, ++0x1A, 0x44, 0x01, 0x2A, 0x5E, 0xD0, 0x0A, 0xB9, 0x5B, 0x4B, 0x1A, 0x60, 0x06, 0x9E, 0xD4, 0xF8, 0xD8, 0x31, 0x06, 0xF1, ++0x18, 0x00, 0x28, 0x44, 0x98, 0x47, 0x06, 0xF1, 0x28, 0x00, 0xD4, 0xF8, 0xD8, 0x31, 0x28, 0x44, 0x98, 0x47, 0x04, 0x9A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0x93, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0x3A, 0xD1, 0x04, 0x9A, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0x05, 0x26, 0x93, 0xF8, 0x63, 0x00, 0x0A, 0xF0, 0x02, 0xFA, 0x4B, 0x4B, 0x1A, 0x69, ++0xBA, 0x42, 0x04, 0xBF, 0x00, 0x22, 0x1A, 0x61, 0x00, 0x21, 0x4F, 0xF4, 0xA4, 0x62, 0x38, 0x46, 0xE9, 0xF7, 0x22, 0xFC, ++0x04, 0x99, 0x9A, 0xF8, 0x11, 0x20, 0x9A, 0xF8, 0x12, 0x30, 0xD4, 0xF8, 0x50, 0xC4, 0x01, 0x91, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x01, 0x55, 0x7F, 0x24, 0x00, 0x93, 0x3F, 0x49, 0xC5, 0xF8, 0x2C, 0xC0, 0x13, 0x44, 0x4F, 0xF4, 0x80, 0x70, ++0x3D, 0x4A, 0x2F, 0x63, 0x85, 0xF8, 0x62, 0x60, 0x85, 0xF8, 0x65, 0x40, 0x85, 0xF8, 0x66, 0x40, 0x0D, 0xF0, 0xC2, 0xFE, ++0x39, 0x48, 0x39, 0x46, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x0C, 0xF0, 0x91, 0xBC, 0x93, 0xF8, 0xC1, 0x04, 0x01, 0x21, ++0x09, 0xF0, 0x2E, 0xFC, 0x9A, 0xF8, 0x13, 0x30, 0x01, 0x3B, 0x8A, 0xF8, 0x13, 0x30, 0xB9, 0xE7, 0x31, 0x4A, 0xDA, 0xF8, ++0x08, 0x60, 0xDF, 0xF8, 0xC8, 0xE0, 0xDF, 0xF8, 0xC8, 0x90, 0xDF, 0xF8, 0xC8, 0x80, 0xD2, 0xE9, 0x00, 0x01, 0x21, 0xF0, ++0x10, 0x0C, 0x4C, 0xEA, 0x00, 0x00, 0xC2, 0xF8, 0x04, 0xC0, 0xCE, 0xF8, 0x00, 0x00, 0xB0, 0x6B, 0xB6, 0x8F, 0xC9, 0xF8, ++0x00, 0x00, 0xC8, 0xF8, 0x00, 0x60, 0x00, 0x2B, 0x88, 0xD1, 0x13, 0x68, 0x21, 0xF4, 0x88, 0x71, 0x0B, 0x43, 0x51, 0x60, ++0xCE, 0xF8, 0x00, 0x30, 0x80, 0xE7, 0x9A, 0xF8, 0x11, 0x20, 0x9A, 0xF8, 0x12, 0x30, 0x01, 0x3A, 0xD2, 0xB2, 0x8A, 0xF8, ++0x11, 0x20, 0x71, 0xE7, 0xEA, 0xF7, 0x50, 0xFC, 0x00, 0x28, 0x40, 0xF0, 0x28, 0x81, 0xDF, 0xF8, 0x60, 0xA0, 0x12, 0x4C, ++0x9A, 0xF8, 0x10, 0x00, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x53, 0x5A, 0x68, 0x19, 0x6C, 0x22, 0xF0, 0x80, 0x02, ++0x5A, 0x60, 0x09, 0xB1, 0x63, 0x6D, 0x98, 0x47, 0x9A, 0xF8, 0x12, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x0D, 0x81, 0x0E, 0x48, ++0x0E, 0x49, 0x42, 0x68, 0x0E, 0x4E, 0x01, 0x60, 0x0A, 0x43, 0x32, 0x60, 0xFF, 0x21, 0x9A, 0xF8, 0x11, 0x20, 0x8A, 0xF8, ++0x10, 0x10, 0x49, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x08, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, ++0x94, 0x64, 0x17, 0x00, 0xB8, 0x98, 0x15, 0x00, 0xDC, 0x98, 0x15, 0x00, 0x00, 0x88, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x8C, 0x84, 0x03, 0x35, 0x60, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x04, 0x9E, 0xDF, 0xF8, ++0x28, 0xA2, 0x7F, 0x49, 0x9A, 0xF8, 0x12, 0x20, 0x7E, 0x4C, 0xDF, 0xF8, 0x20, 0xB2, 0x06, 0xF1, 0x0A, 0x08, 0x08, 0xEB, ++0x88, 0x03, 0x4F, 0xF4, 0x1E, 0x70, 0xC8, 0xEB, 0x03, 0x13, 0x4F, 0xF0, 0xA4, 0x0C, 0x00, 0xFB, 0x08, 0x18, 0x46, 0x33, ++0x9E, 0x20, 0xCD, 0xE9, 0x08, 0x7A, 0x1C, 0xFB, 0x06, 0x06, 0x01, 0x3A, 0x00, 0x20, 0x01, 0xEB, 0xC3, 0x03, 0x03, 0x93, ++0x8A, 0xF8, 0x12, 0x20, 0x88, 0xF8, 0x25, 0x00, 0x05, 0x90, 0x05, 0xEB, 0xC6, 0x06, 0xB9, 0x46, 0xD8, 0xF8, 0x08, 0x32, ++0x9D, 0xF8, 0x14, 0x70, 0x3B, 0xB1, 0x03, 0x99, 0xD4, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x28, 0x39, 0x38, 0x46, ++0x98, 0x47, 0xD8, 0xF8, 0x30, 0x32, 0x33, 0xB1, 0xD4, 0xF8, 0x84, 0x33, 0x03, 0x99, 0x4F, 0xF0, 0x80, 0x42, 0x38, 0x46, ++0x98, 0x47, 0xD9, 0xF8, 0xF0, 0x34, 0x00, 0x2B, 0x00, 0xF0, 0x93, 0x80, 0x30, 0x46, 0x0C, 0xF0, 0x55, 0xFC, 0xA6, 0xF1, ++0x28, 0x0A, 0x07, 0x90, 0x50, 0x46, 0x0C, 0xF0, 0x4F, 0xFC, 0x07, 0x99, 0x02, 0x46, 0x5B, 0x48, 0x0D, 0xF0, 0xA0, 0xFD, ++0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x58, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xDB, 0xF8, 0x00, 0x20, ++0xD4, 0xF8, 0x84, 0x33, 0x01, 0x32, 0xCB, 0xF8, 0x00, 0x20, 0x31, 0x46, 0x4F, 0xF0, 0x80, 0x42, 0x38, 0x46, 0x98, 0x47, ++0xD4, 0xF8, 0x84, 0x33, 0x51, 0x46, 0x38, 0x46, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, ++0x4B, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x00, 0x2A, 0x66, 0xD1, 0x05, 0x9B, 0x03, 0x9A, ++0x01, 0x33, 0x08, 0x32, 0x05, 0x2B, 0x05, 0x93, 0x08, 0xF1, 0x08, 0x08, 0x06, 0xF1, 0x08, 0x06, 0x09, 0xF1, 0x08, 0x09, ++0x03, 0x92, 0xA1, 0xD1, 0x04, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0xDD, 0xE9, 0x08, 0x7A, 0xD3, 0xF8, ++0x18, 0x35, 0x00, 0x2B, 0x4F, 0xD0, 0x06, 0x9B, 0x03, 0xF5, 0xA3, 0x66, 0x2E, 0x44, 0x30, 0x46, 0x0C, 0xF0, 0x04, 0xFC, ++0x01, 0x46, 0x38, 0x48, 0x0D, 0xF0, 0x56, 0xFD, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x33, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xDB, 0xF8, 0x00, 0x20, 0xD4, 0xF8, 0x84, 0x33, 0x01, 0x32, 0xCB, 0xF8, 0x00, 0x20, 0x31, 0x46, ++0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x2A, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x00, 0x2A, 0x43, 0xD1, 0x9A, 0xF8, 0x12, 0x20, 0x00, 0x2A, 0x3C, 0xD0, 0x9A, 0xF8, ++0x11, 0x30, 0x13, 0x44, 0x01, 0x2B, 0x7F, 0xF4, 0x71, 0xAE, 0x23, 0x49, 0xDA, 0xF8, 0x08, 0x00, 0x22, 0x4E, 0xD1, 0xE9, ++0x00, 0x23, 0x23, 0xF0, 0x10, 0x03, 0x4B, 0x60, 0x1A, 0x43, 0x20, 0x49, 0x20, 0x4B, 0x32, 0x60, 0x86, 0x6B, 0x82, 0x8F, ++0x0E, 0x60, 0x1A, 0x60, 0x5E, 0xE6, 0xD9, 0xF8, 0xC8, 0x34, 0x00, 0x2B, 0x7F, 0xF4, 0x68, 0xAF, 0xA6, 0xF1, 0x28, 0x0A, ++0x72, 0xE7, 0x62, 0xB6, 0x96, 0xE7, 0x06, 0x9B, 0x03, 0xF5, 0xA3, 0x66, 0x2E, 0x44, 0xB5, 0xE7, 0x01, 0xF0, 0x4E, 0xFC, ++0x9A, 0xF8, 0x12, 0x30, 0xF4, 0xE6, 0x00, 0x20, 0xEA, 0xF7, 0x2C, 0xFB, 0x12, 0x4B, 0x1A, 0x68, 0xD2, 0x05, 0x7F, 0xF5, ++0xD0, 0xAE, 0x4F, 0xF4, 0x80, 0x72, 0xC3, 0xF8, 0x80, 0x20, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0xC6, 0xE6, ++0x01, 0xF0, 0x5E, 0xFC, 0x2C, 0xE6, 0x62, 0xB6, 0xB9, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x88, 0x98, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0xA0, 0x98, 0x15, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, ++0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0x88, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x2E, 0x78, 0x95, 0xF8, 0x29, 0x80, 0x4F, 0x4C, 0x00, 0xFB, ++0x08, 0xF0, 0xC6, 0xEB, 0x06, 0x17, 0x00, 0xEB, 0xC7, 0x07, 0x27, 0x44, 0x4F, 0xF0, 0x78, 0x0A, 0x1A, 0xFB, 0x06, 0x0A, ++0x87, 0xF8, 0x3A, 0x12, 0x0A, 0xF5, 0xEC, 0x79, 0x95, 0xF8, 0x28, 0x30, 0x87, 0xF8, 0x38, 0x32, 0xA1, 0x44, 0x87, 0xF8, ++0x39, 0x62, 0x48, 0x46, 0x48, 0x22, 0x00, 0x21, 0xE9, 0xF7, 0x46, 0xFA, 0x97, 0xF8, 0x38, 0x32, 0x37, 0x01, 0x05, 0x2B, ++0x0C, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x41, 0x51, 0x0B, 0x41, 0x6A, 0x03, 0x0A, 0xF5, 0x0A, 0x70, 0x20, 0x44, 0x10, 0x22, ++0x05, 0xF1, 0x08, 0x01, 0x20, 0xF0, 0xC2, 0xF9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, 0xBA, 0x1B, 0x03, 0xEB, ++0xC2, 0x03, 0x23, 0x44, 0x00, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x88, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, ++0xBA, 0x1B, 0x03, 0xEB, 0xC2, 0x02, 0x22, 0x44, 0x23, 0x44, 0x92, 0xF8, 0x38, 0x12, 0x05, 0x29, 0x4F, 0xF0, 0x01, 0x00, ++0x0C, 0xBF, 0xC3, 0xF8, 0xAC, 0x94, 0xC3, 0xF8, 0xA8, 0x94, 0x4F, 0xF4, 0xA4, 0x63, 0x82, 0xF8, 0x3B, 0x02, 0x03, 0xFB, ++0x08, 0xF8, 0xD5, 0xE9, 0x02, 0x01, 0xD5, 0xE9, 0x04, 0x23, 0xBF, 0x1B, 0x08, 0xEB, 0xC7, 0x07, 0x3C, 0x44, 0xC4, 0xE9, ++0x8F, 0x01, 0xC4, 0xE9, 0x91, 0x23, 0x2B, 0x79, 0x84, 0xF8, 0x4C, 0x32, 0xBD, 0xE8, 0xF0, 0x87, 0x20, 0xF0, 0x90, 0xFA, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, 0xBA, 0x1B, 0x03, 0xEB, 0xC2, 0x03, 0x23, 0x44, 0x20, 0xF0, 0x7F, 0x40, ++0x00, 0x21, 0xC3, 0xE9, 0x88, 0x01, 0xC5, 0xE7, 0x4F, 0xF4, 0xA4, 0x60, 0xBB, 0x1B, 0x00, 0xFB, 0x08, 0xF0, 0x00, 0xEB, ++0xC3, 0x00, 0x20, 0x44, 0xA9, 0x69, 0xC0, 0xF8, 0x28, 0x12, 0xE9, 0x69, 0xC0, 0xF8, 0x2C, 0x12, 0x29, 0x6A, 0xC0, 0xF8, ++0x30, 0x12, 0x00, 0x22, 0x69, 0x6A, 0xC0, 0xF8, 0x34, 0x12, 0x00, 0x23, 0xC0, 0xE9, 0x88, 0x23, 0xAC, 0xE7, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF2, 0x05, 0xA1, 0xD1, 0xE9, 0x00, 0x01, 0xBB, 0x1B, 0x02, 0xEB, 0xC3, 0x03, 0x23, 0x44, ++0xC3, 0xE9, 0x88, 0x01, 0x9E, 0xE7, 0x00, 0xBF, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x18, 0x88, 0x17, 0x00, ++0x78, 0x22, 0x10, 0xB4, 0xC1, 0xEB, 0x01, 0x13, 0xD0, 0xF8, 0xA8, 0x44, 0x02, 0xFB, 0x01, 0x01, 0x00, 0xEB, 0xC3, 0x03, ++0x01, 0xF5, 0xEC, 0x71, 0x00, 0x22, 0x8C, 0x42, 0x83, 0xF8, 0x3B, 0x22, 0x06, 0xD0, 0xD0, 0xF8, 0xAC, 0x34, 0x8B, 0x42, ++0x1C, 0xD0, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x90, 0xF8, 0x3B, 0x32, 0xC0, 0xF8, 0xA8, 0x24, 0x00, 0xF5, 0xEC, 0x71, ++0x7B, 0xB9, 0x90, 0xF8, 0xB3, 0x32, 0x00, 0xF5, 0x14, 0x71, 0x53, 0xB9, 0x90, 0xF8, 0x2B, 0x33, 0x00, 0xF5, 0x32, 0x71, ++0x2B, 0xB9, 0x90, 0xF8, 0xA3, 0x33, 0x00, 0xF5, 0x50, 0x71, 0x00, 0x2B, 0xE1, 0xD0, 0xC0, 0xF8, 0xA8, 0x14, 0xE2, 0xE7, ++0x90, 0xF8, 0x1B, 0x34, 0x00, 0x22, 0xC0, 0xF8, 0xAC, 0x24, 0x43, 0xB9, 0x90, 0xF8, 0x93, 0x34, 0x00, 0x2B, 0xD8, 0xD0, ++0x00, 0xF5, 0x86, 0x63, 0xC0, 0xF8, 0xAC, 0x34, 0xD3, 0xE7, 0x00, 0xF5, 0x6E, 0x73, 0xF9, 0xE7, 0x70, 0xB5, 0xD0, 0xF8, ++0xE4, 0x40, 0x54, 0xB1, 0x05, 0x4E, 0x05, 0x46, 0x21, 0x46, 0xD6, 0xF8, 0x20, 0x33, 0x00, 0x22, 0x28, 0x46, 0x98, 0x47, ++0x24, 0x68, 0x00, 0x2C, 0xF6, 0xD1, 0x70, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x04, 0x4A, 0x05, 0x4B, 0x11, 0x69, 0xD3, 0xF8, ++0xE0, 0x31, 0x01, 0xF5, 0x1C, 0x51, 0x28, 0x30, 0x10, 0x31, 0x18, 0x47, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x0B, 0x4B, 0x1A, 0x78, 0x02, 0xB9, 0x70, 0x47, 0x5B, 0x68, 0x1B, 0x07, 0xFB, 0xD4, 0x43, 0x68, 0x70, 0xB5, 0x04, 0x46, ++0x03, 0xB1, 0x70, 0xBD, 0x06, 0x4D, 0x28, 0x30, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xD5, 0xF8, 0x50, 0x34, 0x20, 0x46, ++0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF0, 0xB4, 0xA0, 0xF8, ++0xD2, 0x10, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1F, 0x4D, ++0x1F, 0x4B, 0x2E, 0x68, 0x9A, 0x7C, 0x77, 0x1C, 0x01, 0x2A, 0x2F, 0x60, 0x2B, 0xD9, 0x1D, 0x4C, 0x1A, 0x7D, 0x4F, 0xF4, ++0xA4, 0x6C, 0x0C, 0xFB, 0x02, 0x42, 0xB2, 0xF8, 0xD2, 0x40, 0xA1, 0x42, 0x1C, 0xD3, 0x9B, 0x68, 0x5B, 0xB1, 0x01, 0x21, ++0xB3, 0xF8, 0xD2, 0x20, 0x83, 0xF8, 0xD5, 0x10, 0xB2, 0xFB, 0xF4, 0xF2, 0x83, 0xF8, 0xD4, 0x20, 0x1B, 0x68, 0x00, 0x2B, ++0xF4, 0xD1, 0x12, 0x4A, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x23, 0x43, 0x13, 0x60, 0x2F, 0xB1, 0x0A, 0x4B, 0x2E, 0x60, ++0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, 0x70, 0x47, 0x90, 0xF8, 0x63, 0x20, 0x1A, 0x75, 0x0C, 0x46, ++0xDD, 0xE7, 0x90, 0xF8, 0x63, 0x20, 0x1A, 0x75, 0x40, 0xF2, 0x01, 0x13, 0x0C, 0x46, 0xA0, 0xF8, 0xD4, 0x30, 0xE2, 0xE7, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x21, 0x04, 0x46, 0x82, 0xB0, 0x03, 0x23, 0x00, 0x22, 0x58, 0x20, 0x0B, 0xF0, 0xEA, 0xFC, ++0x3B, 0x4F, 0xFF, 0x22, 0x7B, 0x6D, 0x8D, 0xF8, 0x07, 0x20, 0x05, 0x46, 0x94, 0xF8, 0x63, 0x00, 0x98, 0x47, 0xB4, 0xF8, ++0xB6, 0x14, 0x94, 0xF8, 0xB4, 0x04, 0x10, 0xF0, 0xED, 0xF9, 0x94, 0xF8, 0xB5, 0x24, 0xB4, 0xF8, 0xB8, 0x64, 0xB4, 0xF8, ++0xBA, 0x14, 0x84, 0xF8, 0xC5, 0x21, 0x04, 0x2A, 0x08, 0xBF, 0x03, 0x22, 0x03, 0x46, 0xC4, 0xF8, 0x90, 0x01, 0xA4, 0xF8, ++0x94, 0x61, 0xA4, 0xF8, 0x96, 0x11, 0x84, 0xF8, 0xC4, 0x21, 0x00, 0x28, 0x50, 0xD0, 0x1B, 0x79, 0x84, 0xF8, 0xBC, 0x34, ++0x7B, 0x6C, 0x0D, 0xF1, 0x07, 0x01, 0x04, 0xF2, 0xB4, 0x40, 0x98, 0x47, 0x9D, 0xF8, 0x07, 0x10, 0x68, 0x70, 0xA9, 0x70, ++0x06, 0x46, 0x94, 0xF8, 0x63, 0x00, 0x28, 0x70, 0x94, 0xF8, 0x62, 0x30, 0x2B, 0xBB, 0x84, 0xF8, 0x8A, 0x30, 0x7E, 0xBB, ++0xFB, 0x6C, 0x94, 0xF8, 0x6C, 0x80, 0x98, 0x47, 0xD7, 0xF8, 0xD8, 0x31, 0x04, 0xF1, 0x28, 0x00, 0x98, 0x47, 0x1A, 0x4A, ++0x1A, 0x49, 0xD7, 0xF8, 0xE0, 0x31, 0x09, 0x69, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x08, 0x28, 0x04, 0xF1, 0x18, 0x00, ++0xD8, 0xF8, 0x08, 0x20, 0x11, 0x44, 0x98, 0x47, 0x01, 0x23, 0x84, 0xF8, 0x78, 0x60, 0x84, 0xF8, 0x8B, 0x30, 0x28, 0x46, ++0x0B, 0xF0, 0xBE, 0xFC, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x2B, 0xF7, 0xD1, 0x00, 0x23, 0x84, 0xF8, 0xDB, 0x30, ++0x00, 0x2E, 0xF2, 0xD1, 0xFB, 0x6C, 0x98, 0x47, 0x0A, 0x4B, 0x01, 0x22, 0x5A, 0x72, 0xEC, 0xE7, 0xD7, 0xF8, 0xBC, 0x31, ++0x20, 0x46, 0x98, 0x47, 0x28, 0x46, 0x0B, 0xF0, 0xA7, 0xFC, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1B, 0x79, 0xFF, 0xDE, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0xD8, 0x9C, 0x17, 0x00, 0x07, 0x4A, 0x93, 0x7C, ++0x51, 0x7C, 0x0B, 0x44, 0x01, 0x2B, 0x06, 0xD1, 0x90, 0x68, 0x90, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x18, 0xBF, 0x00, 0x20, ++0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x05, 0x4A, 0x06, 0x49, 0x93, 0x7C, 0x50, 0x7C, ++0x03, 0x44, 0x00, 0x22, 0x01, 0x2B, 0x0A, 0x60, 0x01, 0xDC, 0xFF, 0xF7, 0x65, 0xB9, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, ++0x2C, 0x00, 0x32, 0x40, 0x13, 0x4B, 0x00, 0x22, 0x02, 0x70, 0x9B, 0x68, 0x03, 0xB3, 0x10, 0xB4, 0x01, 0x46, 0x01, 0x24, ++0x10, 0x46, 0x08, 0xE0, 0x93, 0xF8, 0x64, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0xC0, 0x24, 0x72, 0xB9, 0x01, 0x30, 0x1B, 0x68, ++0x7B, 0xB1, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xF2, 0xD0, 0x93, 0xF8, 0x64, 0x20, 0x00, 0x2A, 0xF5, 0xD0, 0x93, 0xF8, ++0xC0, 0x24, 0x00, 0x2A, 0xF1, 0xD0, 0x0C, 0x70, 0x1B, 0x68, 0x00, 0x2B, 0xEF, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x18, 0x46, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, 0x10, 0xB5, 0x04, 0x23, 0x04, 0x46, 0xFF, 0x22, 0x00, 0x21, 0x87, 0x20, ++0x0B, 0xF0, 0x16, 0xFC, 0x04, 0x60, 0xBD, 0xE8, 0x10, 0x40, 0x0B, 0xF0, 0x41, 0xBC, 0x00, 0xBF, 0x11, 0xF4, 0x00, 0x01, ++0x70, 0xB5, 0x04, 0x46, 0x16, 0xD0, 0x00, 0x25, 0x2A, 0x4B, 0x80, 0xF8, 0x78, 0x50, 0x19, 0x69, 0x29, 0x48, 0x2A, 0x4B, ++0x80, 0xF8, 0x24, 0x50, 0x40, 0xF2, 0x01, 0x72, 0x01, 0xF5, 0x1C, 0x51, 0x44, 0x61, 0x82, 0x83, 0xD3, 0xF8, 0xE0, 0x31, ++0x10, 0x31, 0x0C, 0x30, 0x98, 0x47, 0x84, 0xF8, 0x6B, 0x50, 0x70, 0xBD, 0x90, 0xF8, 0x6B, 0x30, 0x21, 0x4A, 0x01, 0x33, ++0xDB, 0xB2, 0x12, 0x68, 0x80, 0xF8, 0x6B, 0x30, 0x52, 0x78, 0x9A, 0x42, 0x25, 0xD0, 0x90, 0xF8, 0x64, 0x30, 0xC3, 0xB9, ++0x1C, 0x4B, 0x5B, 0x78, 0x23, 0xB1, 0x1C, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x15, 0x4B, 0x1A, 0x7A, ++0x0A, 0xB1, 0x01, 0x3A, 0x1A, 0x72, 0x14, 0x4A, 0x17, 0x48, 0xD2, 0xF8, 0xD8, 0x21, 0x01, 0x21, 0x99, 0x83, 0x90, 0x47, ++0x63, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x70, 0xBD, 0x0E, 0x4B, 0x90, 0xF8, 0x63, 0x00, 0xD3, 0xF8, 0x94, 0x34, ++0x10, 0x49, 0x22, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x80, 0xF8, 0x6B, 0x10, 0x4F, 0xF4, 0x80, 0x60, 0x0D, 0x49, ++0x0D, 0xF0, 0x74, 0xFA, 0x05, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, ++0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, ++0x34, 0x04, 0x32, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x99, 0x71, 0x13, 0x00, 0xF0, 0x98, 0x15, 0x00, 0x30, 0xB4, 0x01, 0x25, ++0x00, 0x24, 0x1D, 0x70, 0x14, 0x70, 0x04, 0x28, 0x20, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x03, 0x18, 0x09, 0x05, 0x14, 0x00, ++0x00, 0x21, 0x19, 0x70, 0x01, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x09, 0x78, 0x10, 0x29, 0x0F, 0xD0, 0x20, 0x29, ++0x01, 0xD1, 0x02, 0x21, 0x19, 0x70, 0x03, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x04, 0x23, 0x13, 0x70, 0x30, 0xBC, ++0x70, 0x47, 0x02, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x21, 0x19, 0x70, 0xF0, 0xE7, 0x05, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE1, 0xDA, 0x30, 0xBC, 0x03, 0x49, 0x03, 0x48, 0xAD, 0x22, 0x0D, 0xF0, 0x50, 0xBC, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x22, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x0F, 0x33, ++0x23, 0xB1, 0x13, 0x68, 0xC3, 0xF3, 0x0F, 0x33, 0x96, 0x2B, 0x36, 0xD9, 0x96, 0x20, 0x1E, 0x49, 0x1E, 0x4B, 0x0A, 0x68, ++0x18, 0x81, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x96, 0x2A, 0x25, 0xD9, 0x96, 0x22, ++0x19, 0x49, 0x5A, 0x81, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x96, 0x2A, ++0x15, 0xD9, 0x96, 0x22, 0x14, 0x49, 0x9A, 0x81, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, ++0x0F, 0x32, 0x96, 0x2A, 0x03, 0xD9, 0x96, 0x22, 0xDA, 0x81, 0x1A, 0x82, 0x70, 0x47, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, ++0xDA, 0x81, 0x1A, 0x82, 0x70, 0x47, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0xE6, 0xE7, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, ++0xD6, 0xE7, 0x10, 0x68, 0xC0, 0xF3, 0x0F, 0x30, 0xC5, 0xE7, 0x00, 0xBF, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, 0x38, 0xB5, 0x0B, 0x4C, 0x34, 0x22, 0x00, 0x21, ++0x20, 0x46, 0xE8, 0xF7, 0x0B, 0xFF, 0x09, 0x48, 0x09, 0x4A, 0x0A, 0x49, 0x22, 0x60, 0x01, 0x25, 0x00, 0x23, 0xE5, 0x77, ++0x02, 0x60, 0x63, 0x82, 0x63, 0x60, 0xD1, 0xF8, 0xA0, 0x31, 0x98, 0x47, 0x05, 0x4B, 0x63, 0x62, 0x38, 0xBD, 0x00, 0xBF, ++0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x88, 0x1A, 0x17, 0x00, 0x7D, 0x71, 0x13, 0x00, ++0x38, 0xB5, 0x51, 0x4D, 0x51, 0x4C, 0xAB, 0x78, 0x13, 0xB9, 0xD4, 0xF8, 0xE4, 0x30, 0x98, 0x47, 0xFF, 0xF7, 0xD4, 0xFF, ++0xFF, 0xF7, 0x6A, 0xF8, 0xFE, 0xF7, 0xF8, 0xFC, 0x09, 0xF0, 0xDC, 0xFC, 0x07, 0xF0, 0x78, 0xFD, 0x08, 0xF0, 0xAA, 0xFE, ++0xD4, 0xF8, 0x8C, 0x33, 0x98, 0x47, 0xAB, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x82, 0x80, 0xFD, 0xF7, 0x61, 0xFA, 0x45, 0x4D, ++0x2B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x7D, 0xD4, 0x03, 0xF0, 0x70, 0xFD, 0x09, 0xF0, 0x7C, 0xFE, 0x63, 0x6E, 0x98, 0x47, ++0xD4, 0xF8, 0x7C, 0x31, 0x98, 0x47, 0xEF, 0xF7, 0x0D, 0xF8, 0xEF, 0xF7, 0x0D, 0xF8, 0xEF, 0xF7, 0x0D, 0xF8, 0x3C, 0x4B, ++0x93, 0xF8, 0xFA, 0x30, 0x00, 0x2B, 0x62, 0xD1, 0xD4, 0xF8, 0xE4, 0x34, 0x98, 0x47, 0x39, 0x4A, 0x29, 0x68, 0x13, 0x68, ++0x38, 0x48, 0x39, 0x4D, 0xC3, 0xF3, 0x15, 0x03, 0x43, 0xF0, 0x20, 0x73, 0x13, 0x60, 0x8B, 0x78, 0x02, 0x68, 0xDC, 0x06, ++0x4C, 0xBF, 0x22, 0xF0, 0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x02, 0x60, 0x32, 0x4A, 0x33, 0x4C, 0x33, 0x48, 0x13, 0xF0, ++0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, 0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0x22, 0x68, 0x2F, 0x4B, ++0x42, 0xF0, 0x00, 0x62, 0x22, 0x60, 0x02, 0x68, 0x2D, 0x4C, 0x22, 0xF4, 0x70, 0x02, 0x42, 0xF4, 0x00, 0x12, 0x02, 0x60, ++0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x62, 0x42, 0xF4, 0xC0, 0x62, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0x60, 0x52, 0x42, 0xF4, ++0x00, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x32, 0x42, 0xF4, 0x40, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x60, 0x22, 0x1A, 0x60, 0x2B, 0x68, 0x20, 0x4A, 0x23, 0x40, 0x43, 0xF4, 0xBB, 0x63, 0xA0, 0xF5, 0x66, 0x70, 0x43, 0xF0, ++0x04, 0x03, 0x2B, 0x60, 0x03, 0x68, 0xA5, 0xF1, 0xF6, 0x55, 0xA5, 0xF5, 0x32, 0x25, 0x23, 0x40, 0x43, 0xF0, 0x3F, 0x03, ++0xA5, 0xF6, 0xFF, 0x15, 0x03, 0x60, 0x15, 0x60, 0x4B, 0x78, 0x2B, 0xB1, 0xD2, 0xF8, 0x24, 0x31, 0x43, 0xF0, 0x40, 0x03, ++0xC2, 0xF8, 0x24, 0x31, 0x38, 0xBD, 0x12, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x9B, 0xE7, 0xFD, 0xF7, 0xD5, 0xF9, 0x7C, 0xE7, ++0x03, 0x20, 0xEE, 0xF7, 0x8B, 0xFC, 0x7D, 0xE7, 0x3C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x2C, 0x19, 0x17, 0x00, 0xF0, 0x00, 0x32, 0x40, 0x80, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, ++0x40, 0x04, 0x32, 0x40, 0x34, 0x04, 0x32, 0x40, 0x2C, 0x04, 0x32, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x32, 0x40, ++0x80, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x1C, 0x46, 0x05, 0x8C, 0x93, 0xF8, 0x62, 0x30, 0xD2, 0xF8, 0x20, 0x90, ++0x87, 0x69, 0xD0, 0xF8, 0x1C, 0xB0, 0x89, 0xB0, 0x16, 0x46, 0xAD, 0x02, 0xDD, 0xE9, 0x12, 0x20, 0xD3, 0xB9, 0xB4, 0xF8, ++0x68, 0xC0, 0xBC, 0xF1, 0x00, 0x0F, 0x15, 0xD0, 0xD2, 0x8B, 0xB3, 0x6A, 0x0C, 0xFB, 0x02, 0xF2, 0x05, 0x92, 0x18, 0x07, ++0x05, 0xFB, 0x0C, 0xF2, 0x06, 0x92, 0x19, 0xD0, 0x00, 0x23, 0xB7, 0xEB, 0x09, 0x0A, 0x4F, 0xF4, 0xFA, 0x76, 0x07, 0x93, ++0x05, 0x9B, 0x03, 0xF5, 0xC8, 0x73, 0xC4, 0xE9, 0x1F, 0xA3, 0x74, 0xE0, 0x00, 0x28, 0x40, 0xF0, 0xC1, 0x80, 0x06, 0x95, ++0x4F, 0xF0, 0x01, 0x0A, 0xD0, 0x8B, 0xB2, 0x6A, 0x0A, 0xFB, 0x00, 0xF0, 0x12, 0x07, 0x05, 0x90, 0x40, 0xF0, 0x32, 0x81, ++0xF2, 0x6A, 0xDF, 0xF8, 0x94, 0xC2, 0xDF, 0xF8, 0xD4, 0x82, 0xDC, 0xF8, 0x00, 0x30, 0x9F, 0x48, 0xC2, 0xF3, 0x03, 0x12, ++0x23, 0xF0, 0x7F, 0x03, 0x18, 0xF8, 0x02, 0x20, 0x02, 0xF0, 0x7F, 0x02, 0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0xB3, 0x6A, ++0x99, 0x4A, 0xC3, 0xF3, 0xC0, 0x13, 0x41, 0xEA, 0x03, 0x51, 0x4F, 0xF0, 0x00, 0x43, 0x01, 0x60, 0x13, 0x60, 0xBF, 0xF3, ++0x4F, 0x8F, 0x00, 0xBF, 0x13, 0x68, 0x58, 0x00, 0xFC, 0xD5, 0x93, 0x4B, 0x19, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x00, 0x29, ++0xC0, 0xF2, 0xB4, 0x80, 0x8E, 0x4A, 0x12, 0x68, 0x1F, 0xFA, 0x82, 0xFA, 0xB2, 0x6A, 0x12, 0x07, 0x40, 0xF0, 0xA3, 0x80, ++0xF2, 0x6A, 0x8C, 0x49, 0x88, 0x48, 0xD1, 0xF8, 0x00, 0xC0, 0xC2, 0xF3, 0x03, 0x12, 0x2C, 0xF0, 0x7F, 0x0C, 0x18, 0xF8, ++0x02, 0x20, 0x02, 0xF0, 0x7F, 0x02, 0x42, 0xEA, 0x0C, 0x02, 0x0A, 0x60, 0xB2, 0x6A, 0xC2, 0xF3, 0xC0, 0x12, 0x08, 0x31, ++0x12, 0x05, 0x42, 0xF0, 0x18, 0x02, 0x4F, 0xF0, 0x00, 0x46, 0x02, 0x60, 0x0E, 0x60, 0xBF, 0xF3, 0x4F, 0x8F, 0x00, 0xBF, ++0x0A, 0x68, 0x56, 0x00, 0xFC, 0xD5, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x73, 0xDB, 0x77, 0x4A, 0x94, 0xF8, ++0x62, 0x30, 0x16, 0x68, 0x00, 0x22, 0xB6, 0xB2, 0xAA, 0xEB, 0x06, 0x0A, 0x07, 0x92, 0xB7, 0xEB, 0x09, 0x09, 0x19, 0xEB, ++0x0A, 0x0A, 0x00, 0x2B, 0x84, 0xD0, 0x4F, 0xEA, 0xE5, 0x79, 0x2A, 0x46, 0x4B, 0x46, 0x38, 0x46, 0x59, 0x46, 0x1F, 0xF0, ++0x67, 0xFB, 0xBA, 0x1B, 0x02, 0x92, 0x07, 0x9A, 0x00, 0xFB, 0x09, 0xF3, 0x6B, 0xEB, 0x02, 0x02, 0x05, 0xFB, 0x01, 0x33, ++0x03, 0x92, 0xA0, 0xFB, 0x05, 0x01, 0x19, 0x44, 0xDD, 0xE9, 0x02, 0x23, 0x99, 0x42, 0x08, 0xBF, 0x90, 0x42, 0x38, 0xBF, ++0xCD, 0xE9, 0x02, 0x01, 0x64, 0x4B, 0x06, 0x9A, 0x1B, 0x68, 0xDD, 0xE9, 0x02, 0x67, 0xB6, 0x18, 0x99, 0x01, 0x34, 0xD4, ++0x05, 0x9B, 0xF1, 0x1A, 0xA1, 0xF5, 0xC8, 0x71, 0x5F, 0x4F, 0x60, 0x4B, 0x3E, 0x69, 0x1B, 0x68, 0xF6, 0x1A, 0x0E, 0x44, ++0xE9, 0xF7, 0xDC, 0xFD, 0x3B, 0x69, 0xF3, 0x1A, 0xA3, 0xF5, 0x86, 0x53, 0x0C, 0x3B, 0x18, 0x1A, 0x00, 0x28, 0x63, 0x6A, ++0xB8, 0xBF, 0x76, 0x19, 0xB3, 0x42, 0x24, 0xD0, 0x57, 0x4B, 0x1A, 0x6A, 0xA2, 0x42, 0x43, 0xD0, 0x56, 0x4D, 0x31, 0x46, ++0xD5, 0xF8, 0xE0, 0x31, 0x04, 0xF1, 0x18, 0x00, 0x98, 0x47, 0xD5, 0xF8, 0xA8, 0x30, 0x20, 0x46, 0x09, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x18, 0x47, 0x90, 0xF8, 0x02, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0x90, 0xF8, 0x03, 0xA0, 0x05, 0xFB, ++0x0A, 0xF0, 0x06, 0x90, 0x36, 0xE7, 0x4B, 0x49, 0x05, 0x9B, 0xC9, 0x1A, 0xA1, 0xEB, 0x0A, 0x0A, 0x0A, 0xEB, 0x06, 0x01, ++0xC6, 0xE7, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0B, 0x68, 0x58, 0x00, 0x88, 0xD4, 0x45, 0x49, 0x45, 0x48, 0x4F, 0xF4, ++0xBE, 0x72, 0x0D, 0xF0, 0xD7, 0xF9, 0x00, 0x22, 0x94, 0xF8, 0x62, 0x30, 0x07, 0x92, 0xAA, 0xF5, 0xFA, 0x7A, 0x4F, 0xF4, ++0xFA, 0x76, 0x82, 0xE7, 0x12, 0x68, 0x51, 0x00, 0x3F, 0xF5, 0x48, 0xAF, 0x3B, 0x49, 0x3C, 0x48, 0x4F, 0xF4, 0xBE, 0x72, ++0x0D, 0xF0, 0xC4, 0xF9, 0x4F, 0xF4, 0xFA, 0x7A, 0x2F, 0x4B, 0x41, 0xE7, 0x30, 0x4A, 0x66, 0x62, 0x12, 0x68, 0x92, 0x01, ++0xB6, 0xD4, 0x36, 0x4A, 0x36, 0x4D, 0x12, 0x68, 0x93, 0xF8, 0x24, 0x10, 0x41, 0xF2, 0x13, 0x30, 0xC2, 0xF3, 0x07, 0x42, ++0x2A, 0x54, 0x00, 0x29, 0x32, 0xD1, 0x32, 0x4A, 0x32, 0x49, 0x12, 0x68, 0x09, 0x68, 0x41, 0xF2, 0x14, 0x30, 0xD2, 0xB2, ++0x2A, 0x54, 0x01, 0x22, 0x83, 0xF8, 0x24, 0x20, 0x0B, 0x78, 0x93, 0x42, 0x06, 0xD1, 0x2D, 0x49, 0x2D, 0x4A, 0x0B, 0x60, ++0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x41, 0xF2, 0x13, 0x32, 0x41, 0xF2, 0x14, 0x33, 0xA8, 0x5C, 0xE9, 0x5C, ++0x88, 0x42, 0x1D, 0xD2, 0x17, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDA, 0x41, 0xF2, 0x13, 0x32, ++0x41, 0xF2, 0x14, 0x33, 0xAA, 0x5C, 0xEB, 0x5C, 0x9A, 0x42, 0x07, 0xD3, 0x18, 0x49, 0x20, 0x48, 0x15, 0x4D, 0x40, 0xF2, ++0xD7, 0x12, 0x0D, 0xF0, 0xAF, 0xF9, 0x7E, 0xE7, 0x12, 0x4D, 0x7C, 0xE7, 0x00, 0x22, 0x4F, 0xF4, 0xFA, 0x76, 0x07, 0x92, ++0x92, 0x46, 0x28, 0xE7, 0x12, 0x4E, 0x14, 0x48, 0xA9, 0x5C, 0xEA, 0x5C, 0x33, 0x68, 0x06, 0x68, 0x16, 0x48, 0xF6, 0xB2, ++0x1B, 0x0C, 0x00, 0x96, 0x0C, 0xF0, 0x20, 0xFF, 0xD4, 0xE7, 0x00, 0xBF, 0x60, 0x81, 0x32, 0x40, 0x6C, 0x81, 0x32, 0x40, ++0x38, 0x36, 0x17, 0x00, 0x64, 0x81, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0xA4, 0x80, 0x32, 0x40, ++0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xFE, 0xFF, 0xFF, 0x70, 0x79, 0x15, 0x00, 0x04, 0x99, 0x15, 0x00, ++0x44, 0x80, 0x32, 0x40, 0x00, 0x40, 0x1E, 0x00, 0x90, 0x00, 0x32, 0x40, 0x74, 0x36, 0x17, 0x00, 0x70, 0x80, 0x32, 0x40, ++0x74, 0x80, 0x32, 0x40, 0x3C, 0x99, 0x15, 0x00, 0x28, 0x99, 0x15, 0x00, 0x40, 0xA9, 0x15, 0x00, 0x0B, 0x02, 0x10, 0xB5, ++0x04, 0x46, 0x03, 0xD5, 0x00, 0x23, 0x80, 0xF8, 0x78, 0x30, 0x10, 0xBD, 0x4F, 0xF4, 0x80, 0x60, 0x04, 0x49, 0x0C, 0xF0, ++0x37, 0xFF, 0x04, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0xB0, 0x99, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x70, 0x93, 0xD9, 0xF8, 0x20, 0xB0, 0x83, 0xB0, 0x4F, 0xF4, ++0x00, 0x20, 0x0B, 0xF0, 0x79, 0xFC, 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xF5, 0x80, 0xBA, 0x4C, 0xDF, 0xF8, 0x58, 0xA3, ++0xA1, 0x7F, 0xB9, 0x4F, 0xDF, 0xF8, 0x54, 0x83, 0xB8, 0x4E, 0x00, 0x29, 0x00, 0xF0, 0xEA, 0x80, 0x08, 0x07, 0x0E, 0xD5, ++0xB6, 0x4B, 0xDB, 0xF8, 0x70, 0x00, 0x1B, 0x68, 0xDA, 0xF8, 0x10, 0x20, 0x5B, 0x68, 0x03, 0x44, 0x9B, 0x1A, 0x00, 0x2B, ++0xC0, 0xF2, 0xCB, 0x80, 0x01, 0xF0, 0xF7, 0x01, 0xA1, 0x77, 0x4A, 0x07, 0x00, 0xF1, 0x99, 0x80, 0x8B, 0x07, 0x15, 0xD5, ++0xDB, 0xF8, 0x04, 0x30, 0x23, 0xF0, 0x02, 0x03, 0xCB, 0xF8, 0x04, 0x30, 0x99, 0xF8, 0x1D, 0x30, 0x05, 0x2B, 0x08, 0xD1, ++0xA8, 0x4D, 0xA9, 0x48, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x23, 0xA1, 0x7F, 0x89, 0xF8, 0x1D, 0x30, 0x01, 0xF0, ++0xFD, 0x01, 0xA1, 0x77, 0xCD, 0x07, 0x2E, 0xD5, 0x33, 0x68, 0x58, 0x01, 0x40, 0xF1, 0xA3, 0x80, 0x31, 0x68, 0x09, 0x0C, ++0x11, 0xF4, 0x7C, 0x7F, 0x00, 0xF0, 0xAA, 0x80, 0x9E, 0x4A, 0x10, 0x39, 0x01, 0xF0, 0xFF, 0x01, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x25, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xA1, 0x80, 0x99, 0x4A, 0x93, 0xF8, 0x22, 0x10, ++0x13, 0x68, 0x98, 0x4A, 0xB3, 0xF9, 0x00, 0x30, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x22, 0x00, 0x2B, 0x00, 0x92, ++0xC0, 0xF2, 0x9F, 0x80, 0x3B, 0x68, 0x13, 0xF4, 0xE0, 0x2F, 0x00, 0xF0, 0xA8, 0x80, 0xA1, 0x7F, 0x01, 0xF0, 0xFE, 0x01, ++0xA1, 0x77, 0x8A, 0x06, 0x9D, 0xD5, 0x8E, 0x4E, 0x8E, 0x49, 0x35, 0x68, 0xC5, 0xF3, 0x41, 0x17, 0x3A, 0x46, 0x02, 0x20, ++0x0C, 0xF0, 0xAA, 0xFE, 0x00, 0x23, 0xC5, 0xF3, 0x47, 0x15, 0x8B, 0xF8, 0x78, 0x30, 0x00, 0x2F, 0x40, 0xF0, 0xB2, 0x80, ++0x87, 0x4B, 0x80, 0x4E, 0x5A, 0x78, 0x1A, 0x70, 0x86, 0x4A, 0x87, 0x4D, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, ++0xDB, 0xF8, 0x04, 0x30, 0xD6, 0xF8, 0xD8, 0x21, 0x23, 0xF0, 0x01, 0x03, 0xCB, 0xF8, 0x04, 0x30, 0x0B, 0xF1, 0x28, 0x00, ++0x90, 0x47, 0x2A, 0x68, 0x13, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x24, 0x81, 0x78, 0x49, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, ++0x0B, 0x60, 0x13, 0x78, 0x01, 0x2B, 0x12, 0xD1, 0x01, 0xF5, 0xFF, 0x41, 0x34, 0x31, 0x78, 0x4A, 0xDA, 0xF8, 0x10, 0x30, ++0x08, 0x68, 0xB2, 0xF8, 0xB2, 0x10, 0xD6, 0xF8, 0xE0, 0x21, 0x03, 0xEB, 0x40, 0x13, 0x59, 0x1A, 0x0B, 0xF1, 0x18, 0x00, ++0x90, 0x47, 0x2B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x00, 0x81, 0xA1, 0x7F, 0x01, 0xF0, 0xDF, 0x01, 0xA1, 0x77, ++0x4B, 0xE7, 0x6D, 0x49, 0x61, 0x4D, 0x02, 0x20, 0x0C, 0xF0, 0x60, 0xFE, 0x6B, 0x49, 0x63, 0x68, 0x0A, 0x68, 0x22, 0xF0, ++0x04, 0x02, 0x0A, 0x60, 0x22, 0x68, 0x43, 0xF4, 0x00, 0x73, 0x1A, 0x43, 0x4A, 0x61, 0xD5, 0xF8, 0x98, 0x14, 0x63, 0x60, ++0x9B, 0xF8, 0x63, 0x00, 0xD5, 0xF8, 0x94, 0x34, 0x5A, 0x46, 0x98, 0x47, 0x3B, 0x68, 0xA1, 0x7F, 0x23, 0xF0, 0x7C, 0x73, ++0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0xF0, 0xFB, 0x01, 0x43, 0xF4, 0x80, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xA1, 0x77, ++0x3E, 0xE7, 0x5B, 0x48, 0x0C, 0xF0, 0xEA, 0xFD, 0x7F, 0xE7, 0x00, 0x22, 0x9B, 0xF8, 0x6C, 0x00, 0x11, 0x46, 0xF8, 0xF7, ++0x01, 0xFB, 0x60, 0xB1, 0xA1, 0x7F, 0x2B, 0xE7, 0x55, 0x48, 0x0C, 0xF0, 0xDD, 0xFD, 0x72, 0xE7, 0x54, 0x48, 0x0C, 0xF0, ++0xD9, 0xFD, 0x6E, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x10, 0x30, 0xA1, 0x7F, 0xCB, 0xF8, 0x70, 0x30, ++0x1A, 0xE7, 0x93, 0x45, 0x3F, 0xF4, 0x5E, 0xAF, 0x4D, 0x49, 0x4E, 0x48, 0x40, 0xF2, 0x22, 0x32, 0x0D, 0xF0, 0x40, 0xF8, ++0x3B, 0x68, 0x13, 0xF4, 0xE0, 0x2F, 0x7F, 0xF4, 0x58, 0xAF, 0x32, 0x68, 0x33, 0x68, 0x49, 0x49, 0xD0, 0x0F, 0xC3, 0xF3, ++0x80, 0x73, 0x05, 0x46, 0x02, 0x46, 0x02, 0x20, 0x01, 0x93, 0x0C, 0xF0, 0x05, 0xFE, 0x01, 0x9B, 0x53, 0xEA, 0x05, 0x02, ++0x28, 0x46, 0x3F, 0xF4, 0x46, 0xAF, 0x2F, 0x4D, 0x00, 0x9A, 0x19, 0x46, 0xD5, 0xF8, 0x3C, 0x32, 0x98, 0x47, 0x33, 0x68, ++0x23, 0xF0, 0x00, 0x43, 0x33, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x80, 0x43, 0x33, 0x60, 0x36, 0xE7, 0xDA, 0xF8, 0x10, 0x10, ++0x01, 0xF5, 0x9C, 0x51, 0x32, 0x46, 0x08, 0x31, 0x05, 0xE0, 0xDA, 0xF8, 0x10, 0x30, 0xCB, 0x1A, 0x00, 0x2B, 0xC0, 0xF2, ++0xC2, 0x80, 0x13, 0x68, 0x1B, 0x07, 0xF6, 0xD5, 0xDF, 0xF8, 0x90, 0x80, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x08, 0x03, ++0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0xDE, 0x06, 0x19, 0xD5, 0x2C, 0x49, 0x19, 0x4E, 0x02, 0x20, 0x0C, 0xF0, ++0xCF, 0xFD, 0x2B, 0x4B, 0xDF, 0xF8, 0x74, 0xC0, 0x1A, 0x68, 0xD6, 0xF8, 0x3C, 0x32, 0x12, 0x0C, 0x8C, 0xF8, 0x00, 0x20, ++0x05, 0xF0, 0x01, 0x01, 0x78, 0x08, 0x5A, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x10, 0x03, 0xC8, 0xF8, ++0x00, 0x30, 0x1B, 0xE7, 0x21, 0x4B, 0x22, 0x49, 0x0B, 0x4E, 0x01, 0x25, 0x1D, 0x60, 0x02, 0x20, 0x0C, 0xF0, 0xB2, 0xFD, ++0x0F, 0x4A, 0x1F, 0x49, 0x53, 0x78, 0x0D, 0x60, 0xAB, 0x42, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x13, 0x70, 0x09, 0xE7, ++0x98, 0x9C, 0x17, 0x00, 0x74, 0x00, 0x32, 0x40, 0x70, 0x00, 0x32, 0x40, 0xC8, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x28, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, ++0x20, 0x9A, 0x15, 0x00, 0x13, 0x53, 0x1E, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xC0, 0x99, 0x15, 0x00, 0x4C, 0x00, 0x32, 0x40, 0xC4, 0x99, 0x15, 0x00, 0xDC, 0x99, 0x15, 0x00, 0xF0, 0x99, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x04, 0x9A, 0x15, 0x00, 0x14, 0x9A, 0x15, 0x00, 0x40, 0x9A, 0x15, 0x00, 0x44, 0x80, 0x32, 0x40, ++0x64, 0x85, 0x32, 0x40, 0x4C, 0x9A, 0x15, 0x00, 0x68, 0x85, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x36, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0xF7, 0xF7, 0x35, 0xF9, 0xF9, 0xE6, 0xEF, 0xF3, 0x10, 0x83, ++0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x32, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x31, 0x4B, 0x2F, 0x4F, 0x1A, 0x68, 0x01, 0x32, ++0x1A, 0x60, 0x00, 0x21, 0x3A, 0x68, 0x39, 0x60, 0x02, 0xF0, 0x0F, 0x08, 0xDA, 0xF8, 0x10, 0x20, 0x31, 0x46, 0x16, 0x46, ++0x0A, 0x46, 0x47, 0xF2, 0x30, 0x50, 0x04, 0xE0, 0xDA, 0xF8, 0x10, 0x10, 0x89, 0x1B, 0x81, 0x42, 0x1B, 0xD8, 0x39, 0x68, ++0x09, 0x07, 0xF7, 0xD1, 0x25, 0x48, 0x26, 0x49, 0xD0, 0xF8, 0x00, 0xC0, 0x0F, 0x68, 0x16, 0x46, 0xDA, 0xF8, 0x10, 0x20, ++0xB8, 0xF1, 0x00, 0x0F, 0x1A, 0xD1, 0x22, 0x4A, 0x04, 0x21, 0x11, 0x60, 0x1A, 0x68, 0x32, 0xB1, 0x1B, 0x49, 0x01, 0x3A, ++0x1A, 0x60, 0x0B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x2A, 0x68, 0xA0, 0xE6, 0x1C, 0x49, 0x00, 0x92, 0x02, 0x20, ++0x0C, 0xF0, 0x24, 0xFD, 0x15, 0x4B, 0x00, 0x9A, 0xD3, 0xE7, 0x19, 0x49, 0x02, 0x20, 0x0C, 0xF0, 0x1D, 0xFD, 0x3B, 0xE7, ++0x07, 0xEA, 0x0C, 0x07, 0x7F, 0x07, 0xE0, 0xD4, 0xCD, 0xE9, 0x00, 0x16, 0x80, 0x46, 0x16, 0x46, 0x01, 0xE0, 0x7A, 0x07, ++0x12, 0xD4, 0x00, 0x9A, 0xD8, 0xF8, 0x00, 0x70, 0x12, 0x68, 0xDA, 0xF8, 0x10, 0x10, 0x47, 0xF2, 0x30, 0x50, 0x89, 0x1B, ++0x81, 0x42, 0x07, 0xEA, 0x02, 0x07, 0xF0, 0xD9, 0x0B, 0x49, 0x02, 0x20, 0x0C, 0xF0, 0x00, 0xFD, 0x03, 0x4B, 0xEA, 0xE7, ++0x01, 0x9E, 0xC4, 0xE7, 0x38, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, ++0x74, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x5C, 0x9A, 0x15, 0x00, 0x2C, 0x9A, 0x15, 0x00, 0x68, 0x9A, 0x15, 0x00, ++0x10, 0xB5, 0x00, 0x20, 0x0B, 0xF0, 0xD0, 0xF8, 0x01, 0x28, 0x05, 0xD1, 0x05, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, ++0x60, 0x31, 0x18, 0x47, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x0B, 0xF0, 0x1A, 0xB8, 0x88, 0x1A, 0x17, 0x00, ++0x03, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0x01, 0x21, 0x00, 0x20, 0x0B, 0xF0, 0x11, 0xB8, 0x00, 0xBF, 0x38, 0x00, 0x32, 0x40, ++0xF8, 0xB5, 0x90, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x46, 0xD0, 0x90, 0xF8, 0x8A, 0x30, 0x04, 0x46, 0x00, 0x2B, 0x42, 0xD1, ++0x3D, 0x4E, 0x3E, 0x49, 0x94, 0xF8, 0x6C, 0x30, 0x3D, 0x4A, 0x67, 0x6A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, ++0x9D, 0x68, 0x13, 0x6A, 0xA3, 0x42, 0x3D, 0x44, 0x54, 0xD0, 0xD6, 0xF8, 0xE0, 0x31, 0x29, 0x46, 0x04, 0xF1, 0x18, 0x00, ++0x98, 0x47, 0x20, 0x46, 0xFF, 0xF7, 0x82, 0xF8, 0xD4, 0xF8, 0x80, 0x10, 0xD6, 0xF8, 0x14, 0x32, 0x39, 0x44, 0x20, 0x46, ++0x98, 0x47, 0xD6, 0xF8, 0xA4, 0x30, 0x2A, 0x46, 0x39, 0x46, 0x20, 0x46, 0x98, 0x47, 0xD8, 0xB9, 0x94, 0xF8, 0x78, 0x30, ++0x62, 0x68, 0x2C, 0x49, 0x01, 0x33, 0xDB, 0xB2, 0x42, 0xF0, 0x01, 0x02, 0x09, 0x68, 0x84, 0xF8, 0x78, 0x30, 0x62, 0x60, ++0x0A, 0x78, 0x93, 0x42, 0x21, 0xD8, 0x39, 0xD0, 0xB3, 0xEB, 0x52, 0x0F, 0x26, 0xD0, 0xB3, 0xEB, 0x92, 0x0F, 0x4F, 0xEA, ++0x92, 0x01, 0x21, 0xD0, 0x01, 0xEB, 0x41, 0x01, 0x8B, 0x42, 0x1D, 0xD0, 0xF8, 0xBD, 0x90, 0xF8, 0x8C, 0x20, 0x00, 0x2A, ++0xB8, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x01, 0x2B, 0x80, 0xF8, 0x8A, 0x30, 0x29, 0xD9, 0x02, 0x2B, 0x16, 0x4E, 0xB0, 0xD1, ++0x90, 0xF8, 0x63, 0x00, 0xD6, 0xF8, 0xC0, 0x31, 0x00, 0x21, 0x98, 0x47, 0xA9, 0xE7, 0xD6, 0xF8, 0x64, 0x11, 0x94, 0xF8, ++0x6C, 0x00, 0x22, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xF8, 0xF7, 0x30, 0xB9, 0xBD, 0xE8, 0xF8, 0x40, 0xEA, 0xF7, 0x5A, 0xBE, ++0x0F, 0x4B, 0x65, 0x62, 0x93, 0xF8, 0xB5, 0x30, 0x00, 0x2B, 0xAA, 0xD1, 0x0D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, ++0x9F, 0xD1, 0xA4, 0xE7, 0xEA, 0xF7, 0x4C, 0xFE, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0x06, 0xF0, 0x47, 0xBD, 0xBD, 0xE8, ++0xF8, 0x40, 0xFF, 0xF7, 0x9B, 0xB8, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0xC8, 0x35, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x4B, 0x2D, 0xE9, 0xF0, 0x47, 0x9C, 0x68, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x34, 0x4D, 0x2B, 0x68, ++0x04, 0x20, 0x01, 0x33, 0x2B, 0x60, 0xF6, 0xF7, 0xF1, 0xFC, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xF6, 0xF7, 0x8C, 0xFD, ++0x2B, 0x68, 0x2B, 0xB1, 0x2C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x4C, 0xD0, 0xDF, 0xF8, 0xB4, 0x80, ++0x00, 0x2C, 0x43, 0xD0, 0x29, 0x4F, 0x2A, 0x4E, 0x40, 0xF6, 0xE7, 0x35, 0x02, 0xE0, 0x24, 0x68, 0x00, 0x2C, 0x3B, 0xD0, ++0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0xF8, 0xD1, 0x94, 0xF8, 0xD5, 0x30, 0x01, 0x3B, 0xDB, 0xB2, 0x84, 0xF8, 0xD5, 0x30, ++0x00, 0x2B, 0xF0, 0xD1, 0x94, 0xF8, 0xD4, 0x30, 0x84, 0xF8, 0xD5, 0x30, 0x20, 0x46, 0xFE, 0xF7, 0xD3, 0xFF, 0x61, 0x6A, ++0xD8, 0xF8, 0x14, 0x32, 0x01, 0xF6, 0xE8, 0x31, 0x20, 0x46, 0x98, 0x47, 0x3B, 0x68, 0xB4, 0xF8, 0xD2, 0x20, 0x59, 0x01, ++0xB5, 0xEB, 0x43, 0x1F, 0x28, 0xBF, 0x01, 0xEB, 0x82, 0x21, 0x32, 0x69, 0x23, 0x6C, 0xA2, 0xF6, 0xE8, 0x39, 0x89, 0x44, ++0x20, 0x46, 0x4A, 0x46, 0x1B, 0xB1, 0xD8, 0xF8, 0xA4, 0x30, 0x61, 0x6A, 0x98, 0x47, 0x94, 0xF8, 0xC0, 0x34, 0x04, 0xF1, ++0x18, 0x00, 0x49, 0x46, 0x00, 0x2B, 0xC6, 0xD0, 0xD8, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0x24, 0x68, 0x00, 0x2C, 0xC3, 0xD1, ++0xD8, 0xF8, 0x84, 0x31, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x00, 0x2A, 0xB0, 0xD0, 0x62, 0xB6, 0xAE, 0xE7, 0x00, 0xBF, ++0x00, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x40, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0xF0, 0x4A, 0xBE, 0x14, 0x4B, 0x15, 0x4A, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x10, 0xB5, ++0x14, 0x68, 0x00, 0x2B, 0x04, 0xF0, 0x40, 0x74, 0x14, 0xDB, 0x20, 0x46, 0x0B, 0xF0, 0x04, 0xF9, 0x0F, 0x4B, 0x9B, 0x7C, ++0x3B, 0xB9, 0x0F, 0x4A, 0x0F, 0x4B, 0x10, 0x6A, 0xD3, 0xF8, 0xCC, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x0C, 0x4B, ++0x20, 0x46, 0xD3, 0xF8, 0x68, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0xB4, 0xF1, 0x40, 0x7F, 0xE7, 0xD1, 0x08, 0x49, ++0x08, 0x48, 0x4F, 0xF4, 0x9D, 0x62, 0x0C, 0xF0, 0xBB, 0xFD, 0xE0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x9A, 0x15, 0x00, ++0xF0, 0xB5, 0x2D, 0x4E, 0x2D, 0x4B, 0xDF, 0xF8, 0xC8, 0xE0, 0xDF, 0xF8, 0xC8, 0xC0, 0x2C, 0x4F, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x00, 0x62, 0x15, 0x8D, 0xD4, 0x8C, 0x44, 0xEA, 0x05, 0x44, 0x1C, 0x60, 0x52, 0x8D, 0x27, 0x4D, 0x5A, 0x60, ++0x00, 0x24, 0x27, 0x4A, 0xCE, 0xF8, 0x00, 0x40, 0x4F, 0xF0, 0x00, 0x53, 0xCC, 0xF8, 0x00, 0x40, 0x2C, 0x60, 0x00, 0xF1, ++0x10, 0x05, 0x3C, 0x60, 0xEC, 0xB2, 0x13, 0x60, 0x13, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0xDD, 0x00, 0x26, 0xD4, 0x15, 0x68, ++0xC5, 0xF3, 0x07, 0x43, 0xA3, 0x42, 0x4F, 0xEA, 0x15, 0x45, 0x1F, 0xD0, 0xED, 0xB2, 0xDF, 0xF8, 0x5C, 0xE0, 0xDF, 0xF8, ++0x68, 0xC0, 0x18, 0x4F, 0x2D, 0x04, 0x4F, 0xF0, 0xFF, 0x33, 0x45, 0xF0, 0x80, 0x45, 0xCE, 0xF8, 0x00, 0x30, 0xCC, 0xF8, ++0x00, 0x30, 0x15, 0x60, 0x3B, 0x68, 0x5A, 0x00, 0xFC, 0xD4, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x00, 0x63, 0x0C, 0x48, ++0x1D, 0x8D, 0xDA, 0x8C, 0x42, 0xEA, 0x05, 0x42, 0x02, 0x60, 0x0D, 0x4A, 0x5B, 0x8D, 0x13, 0x60, 0x0B, 0x01, 0x43, 0xEA, ++0x04, 0x43, 0x09, 0x4A, 0x43, 0xF0, 0x80, 0x43, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, ++0x20, 0x46, 0xF0, 0xBD, 0x68, 0x65, 0x17, 0x00, 0xBC, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0xB4, 0x00, 0x32, 0x40, ++0xC4, 0x00, 0x32, 0x40, 0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x82, 0xB0, 0x47, 0x78, 0x90, 0xF8, 0x29, 0x60, 0x01, 0x23, 0x8D, 0xF8, 0x06, 0x30, 0xFF, 0x2F, 0x4F, 0xF0, 0x00, 0x03, ++0x04, 0x46, 0x00, 0xF1, 0x04, 0x08, 0x8D, 0xF8, 0x07, 0x30, 0x00, 0xF0, 0x83, 0x80, 0x74, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x73, 0xDB, 0x3A, 0x46, 0x94, 0xF8, 0x28, 0x30, 0x70, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x0C, 0xF0, ++0xF5, 0xFA, 0x07, 0xF1, 0x10, 0x05, 0x6E, 0x4B, 0xED, 0xB2, 0xD3, 0xF8, 0x18, 0x33, 0x29, 0x46, 0x20, 0x46, 0x98, 0x47, ++0x6B, 0x4A, 0x6C, 0x48, 0x6C, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0x22, 0x17, 0x8D, 0xD3, 0x8C, 0x43, 0xEA, ++0x07, 0x43, 0x03, 0x60, 0x53, 0x8D, 0x0B, 0x60, 0x0D, 0xF1, 0x06, 0x03, 0x0D, 0xF1, 0x07, 0x02, 0x94, 0xF8, 0x28, 0x00, ++0x41, 0x46, 0xFF, 0xF7, 0x7B, 0xF8, 0x63, 0x4B, 0xA2, 0x68, 0x1A, 0x60, 0xE2, 0x68, 0x5A, 0x60, 0x22, 0x69, 0x9A, 0x60, ++0x62, 0x69, 0xDA, 0x60, 0x9D, 0xF8, 0x07, 0x30, 0x04, 0x2B, 0x65, 0xD0, 0x5D, 0x4A, 0x12, 0x68, 0x02, 0x2B, 0x12, 0x78, ++0x1F, 0xD1, 0xD1, 0x07, 0x00, 0xF1, 0x85, 0x80, 0x5A, 0x48, 0x01, 0x68, 0x21, 0xF0, 0x01, 0x01, 0x01, 0x60, 0x92, 0x07, ++0x17, 0xD5, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x56, 0x4A, 0x2B, 0x04, 0x43, 0xEA, 0x00, 0x33, 0x43, 0xEA, ++0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0x28, 0x46, ++0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x97, 0x07, 0x6F, 0xD4, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x4A, 0x4A, ++0x1B, 0x02, 0x43, 0xEA, 0x00, 0x33, 0x43, 0xEA, 0x05, 0x43, 0x43, 0xEA, 0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, ++0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x59, 0x00, 0xFC, 0xD4, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x0D, 0x2F, ++0x89, 0xD9, 0x40, 0x49, 0x40, 0x48, 0x40, 0xF2, 0x5C, 0x52, 0x0C, 0xF0, 0xAB, 0xFC, 0x82, 0xE7, 0x90, 0xF8, 0x28, 0x30, ++0x05, 0x2B, 0x4E, 0xD0, 0x34, 0x48, 0x35, 0x4A, 0x25, 0x78, 0x3B, 0x49, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x60, 0x13, 0x60, ++0x94, 0xF8, 0x28, 0x30, 0x94, 0xF8, 0x29, 0x20, 0x4F, 0xF4, 0x80, 0x70, 0x0C, 0xF0, 0x6C, 0xFA, 0x05, 0xEB, 0x86, 0x05, ++0x29, 0x4B, 0xED, 0xB2, 0xD3, 0xF8, 0x48, 0x34, 0x29, 0x46, 0x20, 0x46, 0x98, 0x47, 0x83, 0xE7, 0x30, 0x4A, 0xA1, 0x69, ++0x11, 0x60, 0xE1, 0x69, 0x51, 0x60, 0x21, 0x6A, 0x91, 0x60, 0x27, 0x4A, 0x2D, 0x49, 0x60, 0x6A, 0x12, 0x68, 0x08, 0x60, ++0x12, 0x78, 0x90, 0x07, 0xB1, 0xD5, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x23, 0x4A, 0x1B, 0x02, 0x43, 0xEA, ++0x00, 0x33, 0x43, 0xEA, 0x05, 0x43, 0x43, 0xEA, 0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, ++0x13, 0x68, 0x58, 0x00, 0xFC, 0xD4, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1D, 0x49, 0xA0, 0x69, 0x08, 0x60, ++0xE0, 0x69, 0x48, 0x60, 0x20, 0x6A, 0x88, 0x60, 0x60, 0x6A, 0xC8, 0x60, 0x75, 0xE7, 0x5A, 0x1E, 0x01, 0x2A, 0xDA, 0xD8, ++0x73, 0xE7, 0x18, 0x4B, 0x05, 0x78, 0x1B, 0x68, 0x09, 0x4A, 0x1B, 0x0E, 0x03, 0x3B, 0x2B, 0x44, 0x03, 0xEB, 0x46, 0x03, ++0xDD, 0xB2, 0x29, 0x46, 0xD2, 0xF8, 0x48, 0x34, 0x98, 0x47, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0xB4, 0x9A, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x64, 0x05, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, ++0x70, 0x79, 0x15, 0x00, 0xA0, 0x9A, 0x15, 0x00, 0x90, 0x9A, 0x15, 0x00, 0xC8, 0x00, 0x32, 0x40, 0xD4, 0x00, 0x32, 0x40, ++0xD8, 0x00, 0x32, 0x40, 0x33, 0x4A, 0x13, 0x68, 0xB0, 0xEB, 0x13, 0x6F, 0x70, 0xB5, 0x04, 0x46, 0x46, 0xD8, 0x0F, 0x28, ++0x24, 0xD8, 0x30, 0x4B, 0x30, 0x4D, 0x31, 0x49, 0x31, 0x48, 0x4F, 0xF0, 0xFF, 0x32, 0x1A, 0x60, 0xA3, 0x10, 0x2A, 0x60, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x00, 0xD1, 0xF8, 0x54, 0x34, 0x04, 0xF0, 0x03, 0x01, 0x98, 0x47, 0x2B, 0x4A, ++0x2B, 0x49, 0x2C, 0x4E, 0x2C, 0x4D, 0x2D, 0x48, 0x24, 0x04, 0x00, 0x23, 0x44, 0xF0, 0x80, 0x44, 0x33, 0x60, 0x2B, 0x60, ++0x13, 0x60, 0x03, 0x60, 0x0A, 0x46, 0x0C, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0x70, 0xBD, 0xA0, 0xF1, 0x10, 0x05, ++0x25, 0x48, 0x4F, 0xF4, 0x1E, 0x73, 0xED, 0xB2, 0x03, 0xFB, 0x05, 0x05, 0x28, 0x46, 0x95, 0xF8, 0x22, 0x60, 0xFD, 0xF7, ++0xD3, 0xFF, 0x1A, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x06, 0x36, 0x96, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0xE8, 0xD0, ++0x28, 0x8D, 0xEB, 0x8C, 0x11, 0x49, 0x12, 0x4A, 0x43, 0xEA, 0x00, 0x43, 0x0B, 0x60, 0x6B, 0x8D, 0x13, 0x60, 0xCC, 0xE7, ++0x13, 0x68, 0x15, 0x68, 0x0F, 0x48, 0x0E, 0x4A, 0x1B, 0x0E, 0x01, 0x33, 0xE3, 0x1A, 0x61, 0x1E, 0xA1, 0xEB, 0x15, 0x61, ++0x03, 0xEB, 0xD3, 0x73, 0x5B, 0x10, 0x4F, 0xF4, 0xA4, 0x64, 0x01, 0xF0, 0x01, 0x01, 0x04, 0xFB, 0x03, 0x00, 0x04, 0x31, ++0xBD, 0xE8, 0x70, 0x40, 0xD2, 0xF8, 0x54, 0x34, 0x18, 0x47, 0x00, 0xBF, 0xD8, 0x00, 0x32, 0x40, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xB4, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, ++0xAC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0x68, 0x65, 0x17, 0x00, 0xF0, 0xB4, 0x0E, 0x49, ++0x0E, 0x4F, 0x0F, 0x4E, 0x0F, 0x4D, 0x10, 0x4C, 0x4F, 0xF0, 0xFF, 0x32, 0x00, 0xF1, 0x10, 0x03, 0x0E, 0x48, 0x3A, 0x60, ++0xDB, 0xB2, 0x0A, 0x60, 0x00, 0x21, 0x01, 0x60, 0x1B, 0x04, 0x18, 0x30, 0x43, 0xF0, 0x80, 0x43, 0x31, 0x60, 0x02, 0x46, ++0x29, 0x60, 0x21, 0x60, 0x03, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0xF0, 0xBC, 0x70, 0x47, 0xC0, 0x00, 0x32, 0x40, ++0xBC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0xB4, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, ++0x08, 0xB5, 0x4F, 0xF0, 0x80, 0x60, 0x0A, 0xF0, 0xA5, 0xFE, 0x00, 0x21, 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x46, 0x0A, 0xF0, ++0x89, 0xBC, 0x00, 0xBF, 0x14, 0x4B, 0x15, 0x49, 0x1A, 0x68, 0x22, 0xF0, 0x02, 0x02, 0xF0, 0xB4, 0x1A, 0x60, 0x1A, 0x68, ++0x12, 0x4F, 0x13, 0x4E, 0x13, 0x4D, 0x14, 0x4C, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x4F, 0xF4, 0x40, 0x72, 0x3A, 0x60, ++0x07, 0x68, 0x82, 0x88, 0x00, 0x20, 0x30, 0x60, 0x28, 0x60, 0x27, 0x60, 0x0E, 0x4C, 0x0A, 0x60, 0x19, 0x68, 0x62, 0x68, ++0x0D, 0x4D, 0xA6, 0xF5, 0x00, 0x46, 0x44, 0x3E, 0x2A, 0x43, 0x21, 0xF4, 0xE0, 0x61, 0x19, 0x60, 0x25, 0x60, 0x32, 0x60, ++0xF0, 0xBC, 0xFC, 0xF7, 0x57, 0xBE, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x14, 0x00, 0x32, 0x40, 0x1C, 0x00, 0x32, 0x40, ++0xA4, 0x80, 0x32, 0x40, 0xA8, 0x80, 0x32, 0x40, 0x10, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x8C, 0x84, 0x03, 0x35, ++0x0B, 0x49, 0x0C, 0x48, 0x38, 0xB5, 0x02, 0x68, 0x4B, 0x68, 0x0B, 0x4C, 0x0B, 0x4D, 0x42, 0xF0, 0x02, 0x02, 0x23, 0x43, ++0x02, 0x60, 0x0C, 0x60, 0x00, 0x20, 0x2B, 0x60, 0xFC, 0xF7, 0x36, 0xFE, 0x07, 0x4B, 0x08, 0x49, 0x08, 0x4A, 0x19, 0x60, ++0x13, 0x68, 0x0B, 0x43, 0x13, 0x60, 0x38, 0xBD, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x8C, 0xA4, 0x07, 0x35, ++0x60, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x74, 0x80, 0x32, 0x40, 0x0D, 0x49, 0x0E, 0x48, ++0x38, 0xB5, 0x02, 0x68, 0x4B, 0x68, 0x0D, 0x4C, 0x0D, 0x4D, 0x22, 0xF0, 0x02, 0x02, 0x23, 0x43, 0x02, 0x60, 0x0C, 0x60, ++0x00, 0x20, 0x2B, 0x60, 0xFC, 0xF7, 0x10, 0xFE, 0x09, 0x4B, 0x0A, 0x4A, 0x0A, 0x49, 0x19, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x38, 0xBD, 0x00, 0xBF, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, ++0x8C, 0x84, 0x03, 0x35, 0x60, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, ++0x00, 0xEB, 0x80, 0x03, 0xC0, 0xEB, 0x03, 0x10, 0x04, 0x4B, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0x90, 0xF8, 0xA5, 0x01, ++0x21, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x68, 0x65, 0x17, 0x00, 0x00, 0xEB, 0x80, 0x03, 0xC0, 0xEB, 0x03, 0x10, ++0x04, 0x4B, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0x90, 0xF8, 0xA4, 0x01, 0x21, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, ++0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x37, 0x4A, 0x37, 0x4B, 0x92, 0xF8, 0x30, 0x10, 0x1B, 0x68, 0x00, 0x29, 0x45, 0xD1, ++0x00, 0x28, 0x40, 0xD0, 0x9B, 0xB2, 0x01, 0x21, 0x80, 0xEA, 0xE0, 0x76, 0x00, 0x28, 0x4F, 0xEA, 0x83, 0x23, 0x82, 0xF8, ++0x30, 0x10, 0xA6, 0xEB, 0xE0, 0x76, 0x4E, 0xDD, 0xB6, 0xEB, 0x53, 0x0F, 0x23, 0xFA, 0x01, 0xF4, 0x98, 0xBF, 0x04, 0x46, ++0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x29, 0x49, 0x01, 0x20, 0x08, 0x60, 0x28, 0x4D, 0x29, 0x4F, ++0x29, 0x68, 0x29, 0x48, 0x01, 0x31, 0x00, 0x68, 0x29, 0x60, 0x39, 0x69, 0x00, 0x2C, 0x4F, 0xEA, 0x40, 0x17, 0x01, 0xEB, ++0x40, 0x11, 0x4F, 0xEA, 0x93, 0x00, 0x25, 0xDD, 0xB8, 0x42, 0x1A, 0xD8, 0x64, 0x36, 0xDB, 0x1B, 0x9E, 0x42, 0x31, 0xD9, ++0x20, 0x4B, 0x94, 0x62, 0x09, 0x1A, 0xD3, 0xF8, 0xE0, 0x31, 0x1F, 0x48, 0x98, 0x47, 0x2B, 0x68, 0x43, 0xB1, 0x18, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x1B, 0xB9, 0x12, 0xB1, 0x62, 0xB6, 0x00, 0xE0, 0x04, 0x46, 0x20, 0x46, 0xF8, 0xBD, ++0x00, 0x24, 0x20, 0x46, 0xF8, 0xBD, 0x15, 0x4E, 0x94, 0x62, 0x19, 0x44, 0x09, 0x1A, 0xD6, 0xF8, 0xE0, 0x31, 0x13, 0x48, ++0x98, 0x47, 0xE6, 0xE7, 0x30, 0x44, 0xB8, 0x42, 0x0E, 0xD3, 0x0F, 0x4B, 0x0F, 0x48, 0xD3, 0xF8, 0xE0, 0x31, 0x94, 0x62, ++0x64, 0x31, 0x98, 0x47, 0xDB, 0xE7, 0x5C, 0x08, 0xB6, 0xEB, 0x53, 0x0F, 0x8C, 0xBF, 0x64, 0x42, 0x04, 0x46, 0xAF, 0xE7, ++0x20, 0x46, 0xFE, 0xF7, 0x57, 0xFD, 0xD0, 0xE7, 0x98, 0x9C, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x40, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xB8, 0x9C, 0x17, 0x00, ++0x13, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x0E, 0xDB, 0x11, 0x4B, 0xDB, 0x7F, 0x2B, 0xB1, ++0x10, 0x4A, 0x93, 0x7C, 0x52, 0x7C, 0x13, 0x44, 0x01, 0x2B, 0x11, 0xDD, 0x0E, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, ++0x60, 0x31, 0x18, 0x47, 0x00, 0x20, 0x0A, 0xF0, 0xED, 0xFB, 0x03, 0x28, 0xEB, 0xD0, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF2, ++0x06, 0x72, 0x0C, 0xF0, 0x25, 0xFA, 0xE4, 0xE7, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x0A, 0xF0, 0x36, 0xBB, ++0x38, 0x36, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC4, 0x9A, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x39, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x61, 0xDB, ++0x37, 0x49, 0x04, 0x20, 0x0B, 0xF0, 0xDC, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x34, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0xFC, 0x80, 0x32, 0x4C, 0xD8, 0xF8, 0x00, 0x30, 0x32, 0x4D, 0x01, 0x33, 0x00, 0x22, ++0xC8, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x22, 0x60, 0x2F, 0x69, 0x03, 0xF0, 0x0F, 0x09, 0x47, 0xF2, 0x30, 0x56, 0x05, 0xE0, ++0xF6, 0xF7, 0x22, 0xFB, 0x2B, 0x69, 0xDB, 0x1B, 0xB3, 0x42, 0x2C, 0xD8, 0x23, 0x68, 0x19, 0x07, 0xF6, 0xD1, 0x28, 0x4A, ++0x28, 0x48, 0x53, 0x68, 0x28, 0x49, 0x04, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x53, 0x60, 0x0B, 0x68, 0xB9, 0xF1, 0x00, 0x0F, ++0x22, 0xD1, 0x25, 0x4B, 0x25, 0x49, 0x04, 0x20, 0x18, 0x60, 0x0B, 0xF0, 0xA7, 0xFF, 0x24, 0x4B, 0x93, 0xF8, 0x5A, 0x30, ++0x0B, 0xBB, 0x03, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0xE1, 0xFA, 0x21, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x21, 0x51, 0x82, ++0x3B, 0xB1, 0x15, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, ++0xF8, 0x83, 0x1A, 0x49, 0x04, 0x20, 0x0B, 0xF0, 0x8B, 0xFF, 0xC4, 0xE7, 0x23, 0x40, 0x5A, 0x07, 0xD9, 0xD4, 0x02, 0x68, ++0x0B, 0x68, 0x13, 0x40, 0x5B, 0x07, 0xFA, 0xD5, 0xD3, 0xE7, 0xF6, 0xF7, 0x07, 0xFB, 0xDA, 0xE7, 0x00, 0x20, 0x0A, 0xF0, ++0x65, 0xFB, 0x04, 0x28, 0x98, 0xD1, 0x10, 0x49, 0x10, 0x48, 0x40, 0xF2, 0x14, 0x72, 0x0C, 0xF0, 0x9D, 0xF9, 0x91, 0xE7, ++0x38, 0x36, 0x17, 0x00, 0x14, 0x9B, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x1C, 0x9E, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x28, 0x9B, 0x15, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x5C, 0x9A, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x9A, 0x15, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x24, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x31, 0xDB, 0x00, 0x20, ++0x0A, 0xF0, 0x32, 0xFB, 0x02, 0x28, 0x05, 0xD0, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0x82, 0xBA, ++0x1C, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x19, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x19, 0x4C, 0x23, 0x68, 0x4F, 0xF0, 0x80, 0x60, 0x01, 0x33, 0x23, 0x60, 0x0A, 0xF0, 0x85, 0xFC, 0x16, 0x4B, ++0x1B, 0x68, 0x5B, 0x07, 0x02, 0xD5, 0x15, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xDC, 0xD0, 0x0F, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x00, 0x2B, 0xD6, 0xD1, 0x00, 0x2A, 0xD4, 0xD0, 0x62, 0xB6, 0xD2, 0xE7, 0x00, 0x20, ++0x0A, 0xF0, 0x00, 0xFB, 0x03, 0x28, 0x04, 0xD0, 0x00, 0x20, 0x0A, 0xF0, 0xFB, 0xFA, 0x00, 0x28, 0xC3, 0xD1, 0x09, 0x49, ++0x09, 0x48, 0x40, 0xF2, 0x4F, 0x72, 0x0C, 0xF0, 0x33, 0xF9, 0xBC, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x3C, 0x9B, 0x15, 0x00, 0x08, 0xB5, 0x00, 0x20, 0x0A, 0xF0, 0xDE, 0xFA, 0x04, 0x28, 0x00, 0xD0, 0x08, 0xBD, 0xBD, 0xE8, ++0x08, 0x40, 0x01, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0x2D, 0xBA, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x78, 0xA0, ++0xDA, 0xF8, 0x1C, 0x33, 0x17, 0x46, 0x05, 0x46, 0x0E, 0x46, 0x98, 0x47, 0x04, 0x46, 0x60, 0xBB, 0x96, 0xF8, 0x00, 0x90, ++0x16, 0x4A, 0x95, 0xF8, 0x19, 0x80, 0xDA, 0xF8, 0xB0, 0x31, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x09, 0x29, 0x41, 0x46, ++0x89, 0xF8, 0x5D, 0x02, 0xA9, 0xF8, 0x5E, 0x02, 0x30, 0x78, 0x98, 0x47, 0x38, 0x70, 0xD9, 0xF8, 0x2C, 0x30, 0x2B, 0xB1, ++0xDA, 0xF8, 0xB0, 0x21, 0x93, 0xF8, 0x23, 0x00, 0x69, 0x7E, 0x90, 0x47, 0x0A, 0x49, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x08, 0x11, 0x91, 0xF8, 0x62, 0x30, 0x43, 0xB9, 0x33, 0x78, 0x81, 0xF8, 0x6C, 0x30, 0x6B, 0x7F, 0x81, 0xF8, 0x6D, 0x30, ++0xAB, 0x7F, 0x81, 0xF8, 0x6E, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x7C, 0x4E, 0x7D, 0x4C, 0x4F, 0xF4, 0x1E, 0x77, 0x07, 0xFB, 0x00, 0x67, ++0x4F, 0xF0, 0x4F, 0x08, 0x46, 0x23, 0x18, 0xFB, 0x00, 0x38, 0x97, 0xF8, 0x22, 0xB0, 0x85, 0xB0, 0x05, 0x46, 0x06, 0xEB, ++0xC8, 0x08, 0x4F, 0xF0, 0x00, 0x09, 0xD7, 0xF8, 0x08, 0x32, 0x5F, 0xFA, 0x89, 0xFA, 0xA8, 0xF1, 0x28, 0x01, 0x4F, 0xF0, ++0x80, 0x42, 0x09, 0xF1, 0x01, 0x09, 0x50, 0x46, 0x13, 0xB1, 0xD4, 0xF8, 0x84, 0x33, 0x98, 0x47, 0xD7, 0xF8, 0x30, 0x32, ++0x41, 0x46, 0x08, 0x37, 0x08, 0xF1, 0x08, 0x08, 0x4F, 0xF0, 0x80, 0x42, 0x50, 0x46, 0x13, 0xB1, 0xD4, 0xF8, 0x84, 0x33, ++0x98, 0x47, 0xB9, 0xF1, 0x05, 0x0F, 0xE0, 0xD1, 0x65, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x33, 0x93, 0xF8, ++0x62, 0x10, 0xC1, 0xB9, 0xFF, 0x22, 0x83, 0xF8, 0x6C, 0x20, 0xD4, 0xF8, 0xAC, 0x31, 0x28, 0x46, 0x98, 0x47, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x05, 0x66, 0xF3, 0x6A, 0x23, 0xB1, 0x93, 0xF8, 0x23, 0x00, 0xD4, 0xF8, 0xAC, 0x31, 0x98, 0x47, ++0xD4, 0xF8, 0x24, 0x33, 0x28, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x4F, 0xF4, 0x1E, 0x78, 0x08, 0xFB, ++0x05, 0x62, 0x92, 0xF8, 0x24, 0x90, 0xB9, 0xF1, 0x01, 0x0F, 0x02, 0xD0, 0x02, 0x29, 0xED, 0xD0, 0xDD, 0xE7, 0x93, 0xF8, ++0xDE, 0x20, 0x01, 0x3A, 0xD2, 0xB2, 0x83, 0xF8, 0xDE, 0x20, 0x00, 0x2A, 0xF4, 0xD1, 0x93, 0xF8, 0x63, 0xA0, 0x0A, 0xF1, ++0x0A, 0x0A, 0x5F, 0xFA, 0x8A, 0xFA, 0x08, 0xFB, 0x0A, 0xF3, 0x06, 0xEB, 0x03, 0x08, 0x00, 0x93, 0x98, 0xF8, 0x24, 0x30, ++0x73, 0xB9, 0x44, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x37, 0x38, 0x46, 0x97, 0xF8, 0x63, 0x10, 0xE3, 0x68, ++0x0A, 0x31, 0xC9, 0xB2, 0x98, 0x47, 0x97, 0xF8, 0x62, 0x10, 0xD7, 0xE7, 0x02, 0x23, 0x0C, 0x21, 0x49, 0x20, 0x01, 0x92, ++0x09, 0xF0, 0x64, 0xFF, 0x01, 0x9A, 0x88, 0xF8, 0x24, 0x20, 0x80, 0xF8, 0x00, 0xA0, 0x42, 0x70, 0x09, 0xF0, 0x8C, 0xFF, ++0x98, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0xDE, 0xD1, 0x98, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0xDA, 0xD8, 0x98, 0xF8, 0x22, 0x00, ++0x31, 0x4B, 0xCD, 0xF8, 0x04, 0x90, 0x9E, 0x22, 0xA4, 0x21, 0x11, 0xFB, 0x00, 0x21, 0x2D, 0x4A, 0x03, 0x95, 0x07, 0xFB, ++0x00, 0x27, 0x2B, 0x48, 0x02, 0x97, 0x4F, 0xF0, 0x4F, 0x0C, 0x46, 0x27, 0x1C, 0xFB, 0x0A, 0x77, 0x00, 0xEB, 0xC1, 0x0A, ++0x00, 0x99, 0x28, 0x4A, 0x02, 0x9D, 0xC1, 0x46, 0x88, 0x46, 0x06, 0xEB, 0xC7, 0x07, 0x98, 0x44, 0xD9, 0xF8, 0x08, 0x12, ++0x31, 0xB3, 0xEF, 0xF3, 0x10, 0x81, 0xCB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x21, 0x4B, 0x01, 0x99, 0x19, 0x60, 0x11, 0x68, ++0xA7, 0xF1, 0x28, 0x00, 0x4B, 0x1C, 0xAA, 0xF1, 0x28, 0x01, 0x13, 0x60, 0x00, 0x90, 0x0A, 0xF0, 0xA1, 0xFC, 0xD9, 0xF8, ++0x08, 0x12, 0xD9, 0xF8, 0x0C, 0x32, 0x00, 0x98, 0xC5, 0xF8, 0xC8, 0x14, 0xC5, 0xF8, 0xCC, 0x34, 0x0A, 0xF0, 0xA0, 0xFB, ++0x14, 0x4A, 0x11, 0x68, 0x48, 0x1E, 0x29, 0xB1, 0x13, 0x4B, 0x10, 0x60, 0x19, 0x68, 0x08, 0xB9, 0x01, 0xB1, 0x62, 0xB6, ++0xD9, 0xF8, 0x30, 0x32, 0x50, 0x46, 0x39, 0x46, 0x09, 0xF1, 0x08, 0x09, 0x0A, 0xF1, 0x08, 0x0A, 0x08, 0x35, 0x2B, 0xB1, ++0x0A, 0xF0, 0x80, 0xFC, 0x38, 0x46, 0x0A, 0xF0, 0x87, 0xFB, 0x08, 0x4A, 0x08, 0x37, 0x47, 0x45, 0xC2, 0xD1, 0x40, 0x20, ++0x03, 0x9D, 0x0A, 0xF0, 0xE1, 0xFA, 0x7A, 0xE7, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xC0, 0x67, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x23, 0x04, 0x46, 0x00, 0x22, ++0x06, 0x21, 0x43, 0x20, 0x09, 0xF0, 0xE0, 0xFE, 0x94, 0xF8, 0x63, 0x30, 0x03, 0x70, 0xBD, 0xE8, 0x10, 0x40, 0x09, 0xF0, ++0x09, 0xBF, 0x00, 0xBF, 0x70, 0xB5, 0x90, 0xF9, 0x87, 0x30, 0x04, 0x46, 0x90, 0xF9, 0x86, 0x00, 0x94, 0xF8, 0x88, 0x20, ++0x94, 0xF8, 0x89, 0x60, 0x84, 0xF8, 0x86, 0x10, 0xBB, 0xB1, 0x0D, 0x46, 0x52, 0xB2, 0xAE, 0xB9, 0x88, 0x42, 0x10, 0xDD, ++0x9B, 0x1A, 0x99, 0x42, 0x0D, 0xDA, 0x01, 0x26, 0x00, 0x22, 0x03, 0x23, 0x0C, 0x21, 0x57, 0x20, 0x09, 0xF0, 0xBC, 0xFE, ++0x94, 0xF8, 0x63, 0x20, 0x02, 0x70, 0x46, 0x70, 0x85, 0x70, 0x09, 0xF0, 0xE5, 0xFE, 0x84, 0xF8, 0x89, 0x60, 0x70, 0xBD, ++0x01, 0x2E, 0xFA, 0xD1, 0x88, 0x42, 0xF8, 0xDA, 0x13, 0x44, 0x99, 0x42, 0xF5, 0xDD, 0x00, 0x26, 0xE6, 0xE7, 0x00, 0xBF, ++0x14, 0x4B, 0x93, 0xF9, 0x00, 0x20, 0x22, 0xB3, 0x30, 0xB4, 0x9C, 0x78, 0x90, 0xF9, 0x86, 0x00, 0x93, 0xF9, 0x01, 0x50, ++0x6C, 0xB9, 0x88, 0x42, 0x08, 0xDD, 0x52, 0x1B, 0x91, 0x42, 0x05, 0xDA, 0x0D, 0x49, 0x0A, 0x68, 0x42, 0xF4, 0x00, 0x72, ++0x0A, 0x60, 0x01, 0x24, 0x9C, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x01, 0x2C, 0xFA, 0xD1, 0x88, 0x42, 0xF8, 0xDA, 0x2A, 0x44, ++0x91, 0x42, 0xF5, 0xDD, 0x05, 0x49, 0x0A, 0x68, 0x00, 0x24, 0x22, 0xF4, 0x00, 0x72, 0x0A, 0x60, 0x9C, 0x70, 0x30, 0xBC, ++0x70, 0x47, 0x70, 0x47, 0xA4, 0x1F, 0x17, 0x00, 0xB0, 0xB3, 0x33, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x0C, 0x46, 0x06, 0x46, ++0x80, 0x68, 0x91, 0xF8, 0x8B, 0x10, 0xD0, 0xF8, 0x08, 0x80, 0x60, 0x6F, 0xB6, 0xF8, 0x1C, 0xB0, 0xDF, 0xF8, 0x1C, 0xA1, ++0x87, 0xB0, 0x00, 0x25, 0x05, 0x90, 0x03, 0x92, 0x1F, 0x46, 0x84, 0xF8, 0x78, 0x50, 0x49, 0xB1, 0x94, 0xF8, 0x63, 0x00, ++0xDA, 0xF8, 0xC0, 0x31, 0x01, 0x21, 0x98, 0x47, 0xA4, 0xF8, 0x8A, 0x50, 0x84, 0xF8, 0x8C, 0x50, 0x3A, 0x4B, 0x3B, 0x4D, ++0x1B, 0x68, 0x22, 0x6F, 0x5B, 0x68, 0x01, 0x21, 0x84, 0xF8, 0x85, 0x10, 0x29, 0x69, 0x5B, 0x1A, 0xD3, 0x42, 0x58, 0xD4, ++0x96, 0xF9, 0x2D, 0x10, 0x04, 0x91, 0xE8, 0xF7, 0x35, 0xFB, 0x34, 0x4B, 0x04, 0x99, 0x5B, 0x7C, 0x01, 0x2B, 0x59, 0xD0, ++0xDA, 0xF8, 0x9C, 0x31, 0x20, 0x46, 0xAB, 0xF1, 0x24, 0x05, 0x98, 0x47, 0xAD, 0xB2, 0x00, 0x22, 0x04, 0x21, 0x08, 0xF1, ++0x20, 0x00, 0x0A, 0xF0, 0x19, 0xFC, 0x00, 0x23, 0x01, 0x2D, 0x3B, 0x60, 0x08, 0xF1, 0x24, 0x02, 0x22, 0xD9, 0x04, 0x96, ++0x3E, 0x46, 0x27, 0x46, 0x2C, 0x46, 0x09, 0xE0, 0x32, 0x60, 0xC9, 0xF5, 0x7F, 0x42, 0xFE, 0x32, 0x14, 0x44, 0xA4, 0xB2, ++0x01, 0x2C, 0x05, 0xEB, 0x09, 0x02, 0x10, 0xD9, 0x92, 0xF8, 0x01, 0x90, 0x15, 0x46, 0x09, 0xF1, 0x01, 0x0C, 0xA4, 0x45, ++0x15, 0xF8, 0x02, 0x1B, 0x07, 0xDA, 0x05, 0x29, 0xEA, 0xD0, 0x02, 0x46, 0x49, 0x46, 0x28, 0x46, 0x0A, 0xF0, 0xF4, 0xFB, ++0xE5, 0xE7, 0x3C, 0x46, 0x37, 0x46, 0x04, 0x9E, 0x60, 0x67, 0x3B, 0x68, 0x01, 0x93, 0x03, 0x9B, 0x00, 0x93, 0x32, 0x46, ++0x59, 0x46, 0x40, 0x46, 0x23, 0x46, 0xDA, 0xF8, 0xD0, 0x51, 0xA8, 0x47, 0x04, 0x20, 0x0A, 0xF0, 0xA1, 0xF8, 0x01, 0x28, ++0x04, 0xD0, 0x60, 0x6F, 0x05, 0x9B, 0xC0, 0x1A, 0x18, 0xBF, 0x01, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x22, ++0x94, 0xF8, 0x6C, 0x00, 0x11, 0x46, 0xF7, 0xF7, 0x75, 0xF9, 0x00, 0x28, 0x9E, 0xD1, 0x2B, 0x69, 0x23, 0x67, 0x9B, 0xE7, ++0x20, 0x46, 0xFF, 0xF7, 0x3F, 0xFF, 0x04, 0x99, 0xA0, 0xE7, 0x00, 0xBF, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x00, 0x22, 0x05, 0x46, 0x0C, 0x46, 0x02, 0x23, 0x0C, 0x21, ++0x59, 0x20, 0x09, 0xF0, 0xD3, 0xFD, 0x05, 0x70, 0x44, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x09, 0xF0, 0xFD, 0xBD, 0x00, 0xBF, ++0x08, 0xB5, 0x03, 0x4B, 0x08, 0x46, 0xD3, 0xF8, 0x74, 0x31, 0x98, 0x47, 0x01, 0x20, 0x08, 0xBD, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0xB5, 0x04, 0x4A, 0x08, 0x78, 0xD2, 0xF8, 0x5C, 0x22, 0x19, 0x46, 0x90, 0x47, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x0E, 0x46, 0x2F, 0x20, 0x19, 0x46, 0x02, 0x23, 0x34, 0x78, 0x09, 0xF0, 0xAE, 0xFD, ++0x0D, 0x49, 0x76, 0x78, 0x0D, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x05, 0x46, 0x07, 0xFB, 0x04, 0x10, 0x29, 0x46, 0x90, 0xF8, ++0x65, 0x20, 0x80, 0xF8, 0x66, 0x60, 0x01, 0xF8, 0x01, 0x2F, 0x7F, 0x22, 0xD3, 0xF8, 0x40, 0x33, 0x80, 0xF8, 0x65, 0x20, ++0x2A, 0x46, 0x98, 0x47, 0x28, 0x46, 0x09, 0xF0, 0xC5, 0xFD, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x18, 0x46, 0x38, 0xB5, 0x0D, 0x46, 0x03, 0x23, 0x01, 0x46, 0x0B, 0x20, 0x09, 0xF0, 0x86, 0xFD, ++0x06, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xC4, 0x31, 0xA2, 0x1C, 0x61, 0x1C, 0x28, 0x46, 0x98, 0x47, 0x20, 0x70, 0x20, 0x46, ++0x09, 0xF0, 0xAA, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x0E, 0x4E, 0x0D, 0x46, 0x1C, 0x46, ++0x19, 0x46, 0x28, 0x46, 0xD6, 0xF8, 0x80, 0x30, 0x17, 0x46, 0x98, 0x47, 0x0C, 0xB9, 0x00, 0x20, 0xF8, 0xBD, 0x06, 0x46, ++0x3A, 0x46, 0x21, 0x46, 0x03, 0x23, 0x47, 0x20, 0x09, 0xF0, 0x62, 0xFD, 0x2A, 0x78, 0x02, 0x70, 0x04, 0x22, 0x46, 0x70, ++0x82, 0x70, 0x09, 0xF0, 0x8B, 0xFD, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x0C, 0x46, ++0x76, 0x20, 0x19, 0x46, 0x0C, 0x23, 0x09, 0xF0, 0x4F, 0xFD, 0x23, 0x78, 0x0C, 0x4A, 0x0D, 0x4C, 0x4F, 0xF4, 0x1E, 0x71, ++0x01, 0xFB, 0x03, 0x23, 0x4F, 0xF4, 0xA4, 0x65, 0x93, 0xF8, 0x22, 0x20, 0xD3, 0xF8, 0x48, 0x11, 0x05, 0xFB, 0x02, 0x42, ++0x49, 0x69, 0x92, 0xF8, 0x86, 0x20, 0x02, 0x72, 0x00, 0x24, 0xC0, 0xE9, 0x00, 0x14, 0x09, 0xF0, 0x67, 0xFD, 0x20, 0x46, ++0x38, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xF0, 0xB5, 0x00, 0x22, 0x0D, 0x46, 0x85, 0xB0, ++0x01, 0x23, 0x0C, 0x21, 0x53, 0x20, 0x09, 0xF0, 0x27, 0xFD, 0x01, 0x22, 0x02, 0x70, 0x04, 0x46, 0x28, 0x78, 0x04, 0x28, ++0x28, 0xD8, 0x1D, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x03, 0xB3, 0xAB, 0x78, ++0x23, 0xB3, 0x19, 0x4A, 0x19, 0x49, 0x16, 0x68, 0x09, 0x69, 0x17, 0x68, 0xB0, 0xF8, 0xD2, 0x20, 0xC9, 0x1B, 0x92, 0x02, ++0xEF, 0x68, 0xB6, 0xFB, 0xF2, 0xF6, 0x06, 0xFB, 0x02, 0x22, 0x14, 0x4E, 0x39, 0x44, 0x6F, 0x68, 0xD6, 0xF8, 0x04, 0x62, ++0x01, 0x97, 0x0A, 0x44, 0xA9, 0x68, 0x00, 0x91, 0x02, 0x92, 0xEA, 0x78, 0x00, 0x21, 0xB0, 0x47, 0xFF, 0x28, 0x01, 0xD0, ++0x00, 0x23, 0x23, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x25, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, 0x08, 0x4B, 0x69, 0x78, ++0xD3, 0xF8, 0x08, 0x32, 0x98, 0x47, 0x20, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x19, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, ++0x18, 0x88, 0x17, 0x00, 0xA4, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x19, 0x46, ++0x05, 0x20, 0x1C, 0x23, 0x09, 0xF0, 0xD8, 0xFC, 0x2C, 0x4D, 0x2D, 0x4B, 0x03, 0x60, 0x2A, 0x68, 0x2C, 0x4B, 0x42, 0x60, ++0x1B, 0x68, 0x83, 0x60, 0x0A, 0x22, 0x04, 0x23, 0x83, 0x76, 0x02, 0x83, 0x04, 0x46, 0x00, 0xF1, 0x10, 0x01, 0x0C, 0x30, ++0xE8, 0xF7, 0x9E, 0xF8, 0x26, 0x4B, 0x63, 0x61, 0x2B, 0x68, 0x98, 0x03, 0x24, 0xD4, 0x21, 0x4B, 0x1B, 0x68, 0x99, 0x03, ++0x2C, 0xD4, 0x1F, 0x4B, 0x1B, 0x68, 0x9A, 0x04, 0x03, 0xD5, 0x63, 0x69, 0x43, 0xF4, 0x00, 0x23, 0x63, 0x61, 0xE8, 0xF7, ++0x2F, 0xF9, 0x18, 0xB1, 0x63, 0x69, 0x43, 0xF4, 0x80, 0x33, 0x63, 0x61, 0x17, 0x4B, 0x1B, 0x68, 0x1B, 0x04, 0x22, 0xD4, ++0xE8, 0xF7, 0x2E, 0xF9, 0x63, 0x69, 0x08, 0xB1, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF0, 0x40, 0x53, 0x20, 0x46, 0x63, 0x61, ++0x09, 0xF0, 0xCE, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0xE8, 0xF7, 0x3E, 0xF9, 0x00, 0x28, 0xD6, 0xD0, 0x63, 0x69, 0x43, 0xF4, ++0x00, 0x33, 0x63, 0x61, 0x0A, 0x4B, 0x1B, 0x68, 0x99, 0x03, 0xD2, 0xD5, 0xE8, 0xF7, 0x3A, 0xF9, 0x00, 0x28, 0xCE, 0xD0, ++0x63, 0x69, 0x43, 0xF4, 0x00, 0x13, 0x63, 0x61, 0xC9, 0xE7, 0xE8, 0xF7, 0x03, 0xF9, 0x00, 0x28, 0xD8, 0xD0, 0x63, 0x69, ++0x43, 0xF0, 0x80, 0x43, 0x63, 0x61, 0xD3, 0xE7, 0x04, 0x00, 0x32, 0x40, 0x01, 0x03, 0x04, 0x06, 0x08, 0x00, 0x32, 0x40, ++0x5F, 0xFA, 0x10, 0x00, 0xF0, 0xB5, 0x23, 0x48, 0x4D, 0x79, 0x00, 0x68, 0x8C, 0x79, 0x50, 0xF8, 0x25, 0xC0, 0x21, 0x4F, ++0x0E, 0x68, 0x4F, 0xF4, 0xA4, 0x70, 0x00, 0xFB, 0x04, 0x50, 0x02, 0x30, 0x83, 0xB0, 0x47, 0xF8, 0x20, 0x60, 0x19, 0x46, ++0xBC, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0xCC, 0xF3, 0x0B, 0x03, 0x1B, 0xBB, 0x2C, 0xF4, 0x7F, 0x6C, 0x2C, 0xF0, 0x0F, 0x0C, ++0xC6, 0xF3, 0x0B, 0x06, 0x4C, 0xEA, 0x06, 0x06, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x74, 0x94, 0xF8, 0x64, 0x30, ++0x73, 0xB1, 0x01, 0x2D, 0x1A, 0xD0, 0x02, 0x2D, 0x12, 0xD0, 0xA5, 0xB1, 0x0F, 0x4B, 0x1E, 0x60, 0x0F, 0x4B, 0xD3, 0xF8, ++0xA0, 0x31, 0xCD, 0xE9, 0x00, 0x21, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0x1B, 0x20, 0x09, 0xF0, 0xA5, 0xFC, 0x00, 0x20, ++0x03, 0xB0, 0xF0, 0xBD, 0x66, 0x46, 0xE1, 0xE7, 0x08, 0x4B, 0x1E, 0x60, 0xEC, 0xE7, 0x08, 0x4B, 0x1E, 0x60, 0xE9, 0xE7, ++0x07, 0x4B, 0x1E, 0x60, 0xE6, 0xE7, 0x00, 0xBF, 0xAC, 0x35, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x0C, 0x02, 0x32, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x38, 0xB5, 0x07, 0x48, ++0x8C, 0x78, 0x0D, 0x88, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x04, 0x04, 0x19, 0x46, 0x70, 0x20, 0xA4, 0xF8, 0xBE, 0x54, ++0x09, 0xF0, 0x7A, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0x18, 0x88, 0x17, 0x00, 0x10, 0xB5, 0x08, 0x4C, 0x08, 0x78, 0xD4, 0xF8, ++0xC8, 0x41, 0x82, 0xB0, 0x01, 0x92, 0x00, 0x93, 0xA0, 0x47, 0xDD, 0xE9, 0x00, 0x12, 0x0D, 0x20, 0x09, 0xF0, 0x68, 0xFC, ++0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0x08, 0x78, 0x64, 0x6D, ++0x82, 0xB0, 0x01, 0x92, 0x00, 0x93, 0xA0, 0x47, 0xDD, 0xE9, 0x00, 0x12, 0x3A, 0x20, 0x09, 0xF0, 0x55, 0xFC, 0x00, 0x20, ++0x02, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0C, 0x78, 0x08, 0x46, 0x19, 0x46, 0x24, 0xB1, 0x25, 0x4B, ++0x93, 0xF8, 0xA9, 0x30, 0x00, 0x2B, 0x36, 0xD1, 0x23, 0x4B, 0x24, 0x4E, 0x24, 0x4D, 0x00, 0x24, 0x1C, 0x70, 0x34, 0x68, ++0x24, 0xF0, 0x00, 0x74, 0x34, 0x60, 0x6C, 0x6F, 0x24, 0xF0, 0x10, 0x04, 0x6C, 0x67, 0x1E, 0x4D, 0x2C, 0x68, 0x24, 0xF4, ++0x00, 0x64, 0x2C, 0x60, 0xC4, 0x78, 0x9C, 0x70, 0x84, 0x78, 0x00, 0x25, 0x5D, 0x70, 0xC4, 0xB1, 0x1A, 0x4C, 0x23, 0x68, ++0x43, 0xF0, 0x00, 0x43, 0x23, 0x60, 0x03, 0x79, 0x63, 0xB1, 0x18, 0x4C, 0x85, 0x68, 0x18, 0x4B, 0x25, 0x60, 0x1C, 0x68, ++0xC4, 0xF3, 0x13, 0x04, 0x1C, 0x60, 0xC4, 0x68, 0x18, 0x68, 0x40, 0xEA, 0x04, 0x50, 0x18, 0x60, 0x66, 0x20, 0x09, 0xF0, ++0x17, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x0E, 0x4C, 0x23, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x23, 0x60, 0xE5, 0xE7, 0x08, 0x4B, ++0x08, 0x4E, 0x09, 0x4D, 0x01, 0x24, 0x1C, 0x70, 0x34, 0x68, 0x44, 0xF0, 0x00, 0x74, 0x34, 0x60, 0x6C, 0x6F, 0x44, 0xF0, ++0x10, 0x04, 0x6C, 0x67, 0xC7, 0xE7, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, ++0x00, 0x00, 0x50, 0x40, 0x48, 0x30, 0x34, 0x40, 0xF4, 0x00, 0x60, 0x40, 0xF8, 0x00, 0x60, 0x40, 0x70, 0xB5, 0x08, 0x46, ++0x07, 0x4C, 0x09, 0x68, 0x46, 0x68, 0x05, 0x89, 0xC4, 0xF8, 0xBD, 0x10, 0x78, 0x20, 0x19, 0x46, 0xC4, 0xF8, 0xC1, 0x60, ++0xA4, 0xF8, 0xC5, 0x50, 0x09, 0xF0, 0xE2, 0xFB, 0x00, 0x20, 0x70, 0xBD, 0x2C, 0x19, 0x17, 0x00, 0x38, 0xB5, 0x08, 0x46, ++0x0E, 0x49, 0x44, 0x78, 0x0C, 0x70, 0x84, 0x78, 0x4C, 0x70, 0xC4, 0x78, 0x8C, 0x70, 0x0C, 0x4C, 0x05, 0x79, 0x41, 0x79, ++0x61, 0x70, 0x25, 0x70, 0xC1, 0x79, 0x85, 0x79, 0xA5, 0x70, 0xE1, 0x70, 0x08, 0x4C, 0x41, 0x68, 0x05, 0x68, 0xC4, 0xF8, ++0xCB, 0x10, 0x7A, 0x20, 0x19, 0x46, 0xC4, 0xF8, 0xC7, 0x50, 0x09, 0xF0, 0xC1, 0xFB, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xBF, ++0x68, 0x25, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x48, 0x09, 0x68, 0x01, 0x60, ++0x19, 0x46, 0x72, 0x20, 0x09, 0xF0, 0xB0, 0xFB, 0x00, 0x20, 0x08, 0xBD, 0x34, 0x00, 0x32, 0x40, 0x30, 0xB5, 0x19, 0x46, ++0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x16, 0x4C, ++0x16, 0x4D, 0x23, 0x68, 0x01, 0x33, 0xCD, 0xE9, 0x00, 0x21, 0x23, 0x60, 0x08, 0xF0, 0x12, 0xFA, 0xE7, 0xF7, 0x96, 0xFF, ++0x09, 0xF0, 0x02, 0xFB, 0x0E, 0xF0, 0x22, 0xF8, 0xD5, 0xF8, 0x10, 0x34, 0x98, 0x47, 0xD5, 0xF8, 0xA8, 0x31, 0x98, 0x47, ++0x23, 0x68, 0xDD, 0xE9, 0x00, 0x21, 0x33, 0xB1, 0x08, 0x48, 0x01, 0x3B, 0x00, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x00, 0xB1, ++0x62, 0xB6, 0x01, 0x20, 0x09, 0xF0, 0x7E, 0xFB, 0x00, 0x21, 0x08, 0x46, 0x09, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x03, 0xB0, ++0x30, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x18, 0x46, ++0x21, 0x4E, 0x02, 0x23, 0x0D, 0x46, 0x01, 0x46, 0x25, 0x20, 0x09, 0xF0, 0xFF, 0xFA, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0x46, 0x0C, 0xDB, 0x1C, 0x4B, 0x28, 0x46, 0xD3, 0xF8, 0xB8, 0x31, 0x98, 0x47, 0x00, 0x25, 0x60, 0x70, ++0x25, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x1E, 0xFB, 0x28, 0x46, 0x70, 0xBD, 0x2B, 0x78, 0x05, 0x2B, 0x19, 0xD8, 0x2B, 0x79, ++0x20, 0x2B, 0x0A, 0xD8, 0x95, 0xF8, 0x28, 0x30, 0x05, 0x2B, 0xE8, 0xD9, 0x11, 0x49, 0x12, 0x48, 0x40, 0xF2, 0xFB, 0x62, ++0x0B, 0xF0, 0xBE, 0xFB, 0xE1, 0xE7, 0x0E, 0x49, 0x0F, 0x48, 0x4F, 0xF4, 0xDF, 0x62, 0x0B, 0xF0, 0xB7, 0xFB, 0x33, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE9, 0xDB, 0xD5, 0xE7, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0xF2, 0x62, 0x0B, 0xF0, ++0xAB, 0xFB, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDB, 0xC9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xE4, 0x9B, 0x15, 0x00, 0xBC, 0x9B, 0x15, 0x00, 0x90, 0x9B, 0x15, 0x00, ++0x11, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x70, 0xB5, 0x0C, 0x46, 0x16, 0x46, 0x1D, 0x46, 0x0B, 0xDB, ++0x20, 0x78, 0x0D, 0x4B, 0xD3, 0xF8, 0xB4, 0x31, 0x98, 0x47, 0x32, 0x46, 0x29, 0x46, 0x27, 0x20, 0x09, 0xF0, 0x0A, 0xFB, ++0x00, 0x20, 0x70, 0xBD, 0x08, 0x4B, 0x08, 0x78, 0x1B, 0x68, 0x1B, 0x0E, 0x09, 0x33, 0x98, 0x42, 0xED, 0xDD, 0x06, 0x49, ++0x06, 0x48, 0x40, 0xF2, 0x22, 0x72, 0x0B, 0xF0, 0x75, 0xFB, 0xE5, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xD8, 0x00, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0x14, 0x9C, 0x15, 0x00, 0x16, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x68, ++0x15, 0x4F, 0x0C, 0x46, 0xB0, 0xF9, 0x00, 0x10, 0x25, 0x78, 0x00, 0x29, 0x16, 0x46, 0x98, 0x46, 0x11, 0xDB, 0x4F, 0xF4, ++0xA4, 0x60, 0x00, 0xFB, 0x05, 0x70, 0x62, 0x88, 0xA0, 0xF8, 0x68, 0x20, 0x23, 0x79, 0x80, 0xF8, 0x6A, 0x30, 0x32, 0x46, ++0x41, 0x46, 0x4C, 0x20, 0x09, 0xF0, 0xD4, 0xFA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, ++0x05, 0x72, 0x92, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xE5, 0xD0, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF6, 0x5B, 0x22, 0x0B, 0xF0, ++0x3D, 0xFB, 0xDE, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, ++0x13, 0x4B, 0x70, 0xB5, 0x1B, 0x68, 0x0C, 0x78, 0xB3, 0xF9, 0x00, 0x30, 0x11, 0x4E, 0x00, 0x2B, 0x0D, 0x46, 0x0D, 0xDB, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x63, 0x6A, 0x78, 0x83, 0xF8, 0x87, 0x20, 0xAA, 0x78, 0x83, 0xF8, 0x88, 0x20, ++0x00, 0x20, 0x83, 0xF8, 0x89, 0x00, 0x70, 0xBD, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x63, 0x93, 0xF8, 0x62, 0x30, ++0x00, 0x2B, 0xE9, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF6, 0x78, 0x52, 0x0B, 0xF0, 0x0E, 0xFB, 0xE2, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x20, 0x48, 0x2D, 0xE9, ++0xF0, 0x41, 0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x84, 0xB0, 0x0E, 0x46, 0x15, 0x46, 0x98, 0x46, 0x29, 0xDB, ++0x30, 0x46, 0xE7, 0xF7, 0xAB, 0xFD, 0x00, 0x24, 0x19, 0x4F, 0x00, 0x94, 0x40, 0xF6, 0xB4, 0x13, 0x21, 0x46, 0x1A, 0x46, ++0x20, 0x46, 0xCD, 0xE9, 0x01, 0x44, 0xE7, 0xF7, 0xEB, 0xFD, 0xD7, 0xF8, 0x3C, 0x33, 0x0F, 0x20, 0x98, 0x47, 0x13, 0x4B, ++0xB6, 0xF8, 0x44, 0x20, 0x9A, 0x83, 0x41, 0x46, 0x2A, 0x46, 0x03, 0x20, 0x09, 0xF0, 0x62, 0xFA, 0xD7, 0xF8, 0x60, 0x31, ++0x98, 0x47, 0xD7, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x28, 0x46, 0x02, 0x21, 0x09, 0xF0, 0xEA, 0xFB, 0x20, 0x46, 0x04, 0xB0, ++0xBD, 0xE8, 0xF0, 0x81, 0x10, 0x46, 0x09, 0xF0, 0x8B, 0xFC, 0x00, 0x28, 0xD0, 0xD0, 0x06, 0x49, 0x06, 0x48, 0x4F, 0xF4, ++0xA7, 0x72, 0x0B, 0xF0, 0xC3, 0xFA, 0xC9, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x58, 0x9C, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x46, 0x49, 0x78, 0x16, 0x46, 0x1D, 0x46, 0xE1, 0xB1, ++0x01, 0x29, 0x63, 0x88, 0x3C, 0xD0, 0x02, 0x29, 0x32, 0xD0, 0x03, 0x29, 0x0C, 0xBF, 0x20, 0x48, 0x20, 0x48, 0xA2, 0x88, ++0x18, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x1D, 0xF0, 0x49, 0xFD, 0xE3, 0x88, 0x23, 0xB1, 0x1D, 0x4B, 0x20, 0x78, 0xD3, 0xF8, ++0x80, 0x34, 0x98, 0x47, 0x32, 0x46, 0x29, 0x46, 0x68, 0x20, 0x09, 0xF0, 0x1D, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x04, 0xF1, ++0x08, 0x01, 0x4F, 0xF4, 0x40, 0x72, 0x16, 0x48, 0x1D, 0xF0, 0x34, 0xFD, 0x04, 0xF5, 0x42, 0x71, 0x4F, 0xF4, 0x00, 0x72, ++0x13, 0x48, 0x1D, 0xF0, 0x2D, 0xFD, 0x04, 0xF5, 0xA1, 0x61, 0x80, 0x22, 0x0C, 0x48, 0x1D, 0xF0, 0x27, 0xFD, 0x40, 0x22, ++0x04, 0xF5, 0xB1, 0x61, 0x0A, 0x48, 0x1D, 0xF0, 0x21, 0xFD, 0xD6, 0xE7, 0x0B, 0x48, 0xA2, 0x88, 0x18, 0x44, 0x04, 0xF1, ++0x08, 0x01, 0x1D, 0xF0, 0x19, 0xFD, 0xCE, 0xE7, 0x06, 0x48, 0xA2, 0x88, 0x18, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x1D, 0xF0, ++0x11, 0xFD, 0xC6, 0xE7, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, ++0x1C, 0x16, 0x17, 0x00, 0x38, 0xB5, 0x19, 0x46, 0x81, 0x20, 0x40, 0x23, 0x09, 0xF0, 0x78, 0xF9, 0x00, 0x25, 0x04, 0x46, ++0x08, 0x49, 0x00, 0xF8, 0x01, 0x5B, 0x24, 0x22, 0x1D, 0xF0, 0xF8, 0xFC, 0x23, 0x78, 0x24, 0x33, 0xDB, 0xB2, 0xE2, 0x18, ++0x23, 0x70, 0x20, 0x46, 0x55, 0x70, 0x09, 0xF0, 0x97, 0xF9, 0x28, 0x46, 0x38, 0xBD, 0x00, 0xBF, 0xDC, 0xD1, 0x15, 0x00, ++0x10, 0xB5, 0x82, 0xB0, 0x08, 0x46, 0x1C, 0x46, 0x01, 0x92, 0xFA, 0xF7, 0x83, 0xFA, 0x06, 0x49, 0x4F, 0xF4, 0x80, 0x70, ++0x0B, 0xF0, 0x0E, 0xF8, 0x01, 0x9A, 0x21, 0x46, 0x6C, 0x20, 0x09, 0xF0, 0xB9, 0xF9, 0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, ++0x7C, 0x9C, 0x15, 0x00, 0x25, 0x48, 0x2D, 0xE9, 0xF8, 0x43, 0x00, 0x68, 0xDF, 0xF8, 0xA0, 0x90, 0x0C, 0x46, 0xB0, 0xF9, ++0x00, 0x10, 0x65, 0x79, 0x00, 0x29, 0x17, 0x46, 0x1E, 0x46, 0x2D, 0xDB, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x05, 0xF0, ++0x09, 0xEB, 0x00, 0x08, 0x21, 0x79, 0x98, 0xF8, 0xAC, 0x20, 0x23, 0x68, 0xC8, 0xF8, 0xC4, 0x34, 0x01, 0x2A, 0x88, 0xF8, ++0xC3, 0x14, 0x0A, 0xD1, 0x17, 0x4B, 0xB0, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x48, 0x44, 0x98, 0x47, 0x00, 0x22, 0xD8, 0xF8, ++0xC4, 0x34, 0x88, 0xF8, 0xAC, 0x20, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x05, 0x95, 0x11, 0x49, 0x95, 0xF8, 0xC3, 0x24, ++0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0xD0, 0xFF, 0x3A, 0x46, 0x31, 0x46, 0x62, 0x20, 0x09, 0xF0, 0x7B, 0xF9, 0x00, 0x20, ++0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0x93, 0x93, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xC9, 0xD0, ++0x06, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0x27, 0x62, 0x0B, 0xF0, 0xE4, 0xF9, 0xC2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x8C, 0x9C, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x00, 0xB5, 0x83, 0xB0, 0x08, 0x46, 0x01, 0x92, 0x00, 0x93, 0xFA, 0xF7, 0x45, 0xFA, 0xDD, 0xE9, 0x00, 0x12, 0x6E, 0x20, ++0x09, 0xF0, 0x50, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0xF0, 0xB5, 0x0C, 0x46, 0x0E, 0x78, 0x60, 0x78, ++0x89, 0x78, 0x83, 0xB0, 0x1D, 0x46, 0x01, 0x92, 0x9E, 0xB9, 0xFE, 0xF7, 0xD5, 0xFE, 0x01, 0x9A, 0x00, 0xBB, 0x03, 0x26, ++0x29, 0x46, 0x03, 0x23, 0x2B, 0x20, 0x09, 0xF0, 0xD1, 0xF8, 0x62, 0x78, 0x02, 0x70, 0xA2, 0x78, 0x42, 0x70, 0x86, 0x70, ++0x09, 0xF0, 0xFA, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0xFE, 0xF7, 0xD1, 0xFE, 0x01, 0x9A, 0x00, 0x28, 0xEA, 0xD0, ++0x60, 0x78, 0x14, 0x4B, 0xA1, 0x78, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x00, 0x30, 0x15, 0xF0, 0x9D, 0xFC, 0x02, 0x26, ++0x01, 0x9A, 0xDF, 0xE7, 0x61, 0x78, 0x94, 0xF8, 0x02, 0xC0, 0x0D, 0x48, 0x0D, 0x4F, 0x01, 0xEB, 0x81, 0x03, 0xC1, 0xEB, ++0x03, 0x13, 0x63, 0x44, 0x00, 0xEB, 0xC3, 0x03, 0x4F, 0xF0, 0x9E, 0x0E, 0x93, 0xF8, 0xA5, 0x31, 0x0E, 0xFB, 0x01, 0xC1, ++0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x81, 0x01, 0x07, 0xEB, 0xC3, 0x03, 0x81, 0xF8, 0x5A, 0x61, 0x1E, 0x81, 0x02, 0x26, ++0xC2, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x46, 0x02, 0xF0, 0x0C, 0xFA, ++0x01, 0x20, 0x08, 0xBD, 0x70, 0xB5, 0x48, 0x78, 0xFF, 0x28, 0x0C, 0x46, 0x16, 0x46, 0x1D, 0x46, 0x01, 0xD0, 0x17, 0xF0, ++0xB3, 0xF9, 0x21, 0x78, 0xA0, 0x78, 0x0A, 0x4B, 0x0A, 0x4A, 0x00, 0x39, 0x18, 0xBF, 0x01, 0x21, 0x00, 0x38, 0x18, 0xBF, ++0x01, 0x20, 0x18, 0x70, 0x11, 0x70, 0x02, 0x46, 0x06, 0x48, 0x0A, 0xF0, 0xDD, 0xFE, 0x32, 0x46, 0x29, 0x46, 0x64, 0x20, ++0x09, 0xF0, 0xD8, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0xB9, 0x34, 0x17, 0x00, 0xB8, 0x34, 0x17, 0x00, 0x9C, 0x9C, 0x15, 0x00, ++0xF8, 0xB5, 0x19, 0x46, 0x74, 0x20, 0x06, 0x23, 0x09, 0xF0, 0x62, 0xF8, 0x4F, 0xF4, 0xD2, 0x77, 0x04, 0x46, 0x3B, 0x68, ++0x08, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x06, 0x46, 0x09, 0x20, 0x98, 0x47, 0x36, 0x0C, 0x36, 0x04, 0x56, 0xEA, 0x00, 0x03, ++0x1A, 0xD1, 0x3B, 0x68, 0x07, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x05, 0x46, 0x08, 0x20, 0x98, 0x47, 0x83, 0xB2, 0x19, 0x0A, ++0x28, 0x0A, 0x2A, 0x0C, 0x63, 0x70, 0x2B, 0x0E, 0x21, 0x70, 0x20, 0x71, 0xE2, 0x70, 0xA3, 0x70, 0xEA, 0xB2, 0x07, 0x48, ++0x65, 0x71, 0x0A, 0xF0, 0xA5, 0xFE, 0x20, 0x46, 0x09, 0xF0, 0x6A, 0xF8, 0x00, 0x20, 0xF8, 0xBD, 0x05, 0x04, 0x45, 0xEA, ++0x16, 0x45, 0x03, 0x0C, 0xE7, 0xE7, 0x00, 0xBF, 0xC0, 0x9C, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x46, 0x48, 0x7A, ++0x09, 0x7A, 0x16, 0x46, 0xE2, 0x88, 0x84, 0xB0, 0xCD, 0xE9, 0x00, 0x21, 0x02, 0x90, 0x62, 0x88, 0x5E, 0x48, 0x21, 0x88, ++0x1D, 0x46, 0xA3, 0x88, 0x0A, 0xF0, 0x86, 0xFE, 0xB4, 0xF8, 0x00, 0xC0, 0x67, 0x88, 0xA0, 0x88, 0xE2, 0x88, 0x5A, 0x4B, ++0xBC, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x9E, 0x80, 0x19, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0x0B, 0x68, 0xDF, 0xF8, 0x6C, 0xE1, ++0x03, 0xEA, 0x08, 0x03, 0x43, 0xEA, 0x0C, 0x33, 0x0B, 0x60, 0xDE, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x08, 0x03, 0x43, 0xEA, ++0x0C, 0x33, 0xCE, 0xF8, 0x00, 0x30, 0x00, 0x2F, 0x79, 0xD0, 0x4B, 0x68, 0xDF, 0xF8, 0x44, 0xE1, 0xDF, 0xF8, 0x48, 0xC1, ++0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, 0x07, 0x33, 0x4B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, ++0x07, 0x33, 0xCC, 0xF8, 0x00, 0x30, 0x00, 0x28, 0x3F, 0xD0, 0x8F, 0x68, 0xDF, 0xF8, 0x1C, 0xE1, 0xDF, 0xF8, 0x14, 0xC1, ++0x07, 0xEA, 0x0E, 0x07, 0x47, 0xEA, 0x00, 0x37, 0x8F, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, ++0x00, 0x33, 0xCC, 0xF8, 0x00, 0x30, 0x00, 0x2A, 0x38, 0xD0, 0xC8, 0x68, 0xDF, 0xF8, 0xF4, 0xC0, 0x38, 0x4F, 0x00, 0xEA, ++0x0C, 0x00, 0x40, 0xEA, 0x02, 0x30, 0xC8, 0x60, 0x3B, 0x68, 0x03, 0xEA, 0x0C, 0x03, 0x43, 0xEA, 0x02, 0x33, 0x3B, 0x60, ++0x23, 0x7A, 0x33, 0x4A, 0x00, 0x2B, 0x31, 0xD0, 0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x63, 0x7A, 0x2F, 0x4A, ++0x00, 0x2B, 0x31, 0xD0, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x2C, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, 0x98, 0x47, ++0x32, 0x46, 0x29, 0x46, 0x7F, 0x20, 0x09, 0xF0, 0x17, 0xF8, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x88, 0x68, ++0xDF, 0xF8, 0x9C, 0xC0, 0x25, 0x4F, 0x00, 0xEA, 0x0C, 0x00, 0x88, 0x60, 0x3B, 0x68, 0x03, 0xEA, 0x0C, 0x03, 0x3B, 0x60, ++0x00, 0x2A, 0xC6, 0xD1, 0xCA, 0x68, 0x21, 0x4F, 0x1C, 0x48, 0x3A, 0x40, 0xCA, 0x60, 0x03, 0x68, 0x1B, 0x4A, 0x3B, 0x40, ++0x03, 0x60, 0x23, 0x7A, 0x00, 0x2B, 0xCD, 0xD1, 0x13, 0x68, 0x23, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x63, 0x7A, 0x16, 0x4A, ++0x00, 0x2B, 0xCD, 0xD1, 0x13, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xCC, 0xE7, 0x4F, 0x68, 0xDF, 0xF8, 0x50, 0xE0, ++0xDF, 0xF8, 0x54, 0xC0, 0x07, 0xEA, 0x0E, 0x07, 0x4F, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0xCC, 0xF8, ++0x00, 0x30, 0x88, 0xE7, 0x19, 0x68, 0xDF, 0xF8, 0x34, 0xE0, 0x0B, 0x68, 0xDF, 0xF8, 0x30, 0xC0, 0x03, 0xEA, 0x0E, 0x03, ++0x0B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0xCC, 0xF8, 0x00, 0x30, 0x64, 0xE7, 0xD8, 0x9C, 0x15, 0x00, ++0xAC, 0x35, 0x17, 0x00, 0x0C, 0x02, 0x32, 0x40, 0x24, 0x02, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, ++0xFF, 0x0F, 0x00, 0xF0, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x8A, 0x46, 0x83, 0xB0, ++0x49, 0x7C, 0x28, 0x48, 0xDF, 0xF8, 0xBC, 0x90, 0x27, 0x4F, 0x16, 0x46, 0xDA, 0xF8, 0x0C, 0x20, 0x00, 0x92, 0x01, 0x91, ++0x9A, 0xF8, 0x10, 0xB0, 0xDA, 0xF8, 0x00, 0x10, 0x1D, 0x46, 0xDA, 0xE9, 0x01, 0x23, 0x0A, 0xF0, 0xA5, 0xFD, 0x21, 0x4A, ++0x21, 0x49, 0x9A, 0xF8, 0x11, 0x00, 0x82, 0xF8, 0x05, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0B, 0xF3, 0x03, 0xF1, ++0x08, 0x02, 0x01, 0xEB, 0x02, 0x08, 0x01, 0xEB, 0x03, 0x0B, 0xAA, 0xF1, 0x04, 0x0A, 0x00, 0x24, 0x5A, 0xF8, 0x04, 0x0F, ++0xE3, 0xB2, 0x90, 0xB1, 0x48, 0xF8, 0x24, 0x00, 0x16, 0x4A, 0x9B, 0xF8, 0x64, 0x10, 0x12, 0x68, 0x42, 0xF8, 0x24, 0x00, ++0x49, 0xB1, 0x01, 0x2C, 0x13, 0xD0, 0x02, 0x2B, 0x17, 0xD0, 0x9B, 0xB1, 0x38, 0x60, 0x11, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, ++0x98, 0x47, 0x01, 0x34, 0x04, 0x2C, 0xE5, 0xD1, 0x32, 0x46, 0x29, 0x46, 0x83, 0x20, 0x08, 0xF0, 0x73, 0xFF, 0x00, 0x20, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC9, 0xF8, 0x00, 0x00, 0xEC, 0xE7, 0x08, 0x4B, 0x18, 0x60, 0xE9, 0xE7, 0x08, 0x4B, ++0x18, 0x60, 0xE6, 0xE7, 0x18, 0x9D, 0x15, 0x00, 0x0C, 0x02, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xAC, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, ++0xF8, 0xB5, 0x7C, 0x20, 0x0C, 0x46, 0x19, 0x46, 0x02, 0x23, 0x08, 0xF0, 0xE5, 0xFE, 0x23, 0x78, 0x05, 0x46, 0x00, 0x2B, ++0x5F, 0xD0, 0x35, 0x48, 0x0A, 0xF0, 0x46, 0xFD, 0x34, 0x4B, 0x1B, 0x68, 0x00, 0x22, 0x1A, 0x70, 0x4F, 0xF4, 0xD2, 0x73, ++0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x68, 0x70, 0x62, 0x78, 0x06, 0x46, 0x00, 0x2A, 0x45, 0xD0, 0x2E, 0x4F, 0xC0, 0xF3, ++0x40, 0x11, 0x42, 0x06, 0x87, 0xF8, 0xB4, 0x10, 0x4F, 0xD4, 0x2C, 0x48, 0x0F, 0x22, 0x01, 0x21, 0xE8, 0xF7, 0x1C, 0xFC, ++0x02, 0x22, 0x11, 0x46, 0x29, 0x48, 0xE8, 0xF7, 0x17, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x28, 0x48, 0xE8, 0xF7, 0x12, 0xFC, ++0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x24, 0x48, 0xE8, 0xF7, 0x0C, 0xFC, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x22, 0x48, ++0xE8, 0xF7, 0x06, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x20, 0x48, 0xE8, 0xF7, 0x01, 0xFC, 0x4F, 0xF4, 0x00, 0x52, 0x00, 0x21, ++0x1D, 0x48, 0xE8, 0xF7, 0xFB, 0xFB, 0x97, 0xF8, 0xB4, 0x10, 0x01, 0x22, 0x23, 0x78, 0x6B, 0xB1, 0xE3, 0x78, 0x2B, 0xB1, ++0xB7, 0xF8, 0xAA, 0x30, 0x43, 0xF4, 0x80, 0x43, 0xA7, 0xF8, 0xAA, 0x30, 0x16, 0x48, 0xF3, 0xB2, 0x0A, 0xF0, 0xFA, 0xFC, ++0x97, 0xF8, 0xB4, 0x10, 0x29, 0x70, 0x28, 0x46, 0x08, 0xF0, 0xBC, 0xFE, 0x00, 0x20, 0xF8, 0xBD, 0xA3, 0x78, 0x0B, 0x4F, ++0xC3, 0xF3, 0x40, 0x11, 0x5B, 0x06, 0x87, 0xF8, 0xB4, 0x10, 0xB8, 0xD5, 0xE0, 0xE7, 0x0D, 0x48, 0x0A, 0xF0, 0xE6, 0xFC, ++0x04, 0x4B, 0x1B, 0x68, 0x03, 0x22, 0x1A, 0x70, 0x9E, 0xE7, 0x00, 0x22, 0xD6, 0xE7, 0x00, 0xBF, 0x48, 0x9D, 0x15, 0x00, ++0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x04, 0x20, 0x01, 0x50, 0x04, 0x10, 0x01, 0x50, 0x08, 0x10, 0x01, 0x50, ++0x00, 0x10, 0x01, 0x50, 0x68, 0x9D, 0x15, 0x00, 0x58, 0x9D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x18, 0x46, 0xB1, 0xB0, ++0x0C, 0x46, 0x10, 0x23, 0x01, 0x46, 0x6A, 0x20, 0x04, 0x94, 0x08, 0xF0, 0x59, 0xFE, 0x4F, 0xF4, 0xD2, 0x73, 0x02, 0x46, ++0x1B, 0x68, 0x05, 0x92, 0x06, 0x20, 0x98, 0x47, 0x04, 0x46, 0x01, 0x46, 0x91, 0x48, 0x0A, 0xF0, 0xB5, 0xFC, 0x14, 0xF4, ++0x7F, 0x4F, 0xC4, 0xF3, 0x07, 0x25, 0x6F, 0xD1, 0x26, 0x0E, 0xE5, 0xB2, 0x6E, 0xD0, 0xF4, 0xB2, 0x00, 0x2D, 0x6F, 0xD1, ++0x04, 0x9B, 0x19, 0x7D, 0x00, 0x29, 0x40, 0xF0, 0x83, 0x80, 0x00, 0x2E, 0x40, 0xF0, 0x89, 0x80, 0x59, 0x7D, 0x31, 0xB1, ++0x86, 0x48, 0x0A, 0xF0, 0x9D, 0xFC, 0x04, 0x9B, 0x5C, 0x7D, 0x00, 0x2C, 0x7F, 0xD1, 0x04, 0x9B, 0xDB, 0x68, 0x00, 0x2B, ++0x40, 0xF0, 0x8D, 0x80, 0x04, 0x9B, 0xDF, 0xF8, 0x40, 0xB2, 0x99, 0x68, 0x1A, 0x68, 0x7F, 0x4B, 0xDF, 0xF8, 0x38, 0xA2, ++0xD3, 0xF8, 0x70, 0x32, 0x7D, 0x4C, 0xCD, 0xE9, 0x08, 0x21, 0x08, 0xA8, 0x0A, 0xA9, 0x98, 0x47, 0x1A, 0xAE, 0x6F, 0xF0, ++0x3F, 0x08, 0x09, 0xAF, 0x0A, 0xAB, 0x07, 0x97, 0xA8, 0xEB, 0x03, 0x08, 0x35, 0x46, 0x0D, 0xF1, 0x78, 0x09, 0x06, 0x96, ++0xE3, 0x79, 0x00, 0x93, 0x08, 0xEB, 0x05, 0x02, 0x23, 0x68, 0x03, 0x92, 0x59, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, ++0xBD, 0xFC, 0x15, 0xF8, 0x01, 0x6B, 0x57, 0xF8, 0x04, 0x3F, 0x03, 0x9A, 0x00, 0x96, 0x51, 0x46, 0x23, 0x60, 0xE6, 0x71, ++0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, 0xB0, 0xFC, 0x4D, 0x45, 0x04, 0xF1, 0x10, 0x04, 0xE3, 0xD1, 0xDF, 0xF8, 0xD8, 0xB1, ++0x06, 0x9E, 0x9B, 0xF8, 0xB4, 0x30, 0x00, 0x2B, 0x52, 0xD1, 0xDF, 0xF8, 0xD0, 0xA1, 0x61, 0x4B, 0x00, 0x20, 0xD3, 0xF8, ++0xB0, 0x34, 0x98, 0x47, 0x05, 0x98, 0x5F, 0x4C, 0x5F, 0x4A, 0x60, 0x4B, 0x82, 0x60, 0xC0, 0xE9, 0x00, 0x4A, 0xC3, 0x60, ++0x08, 0xF0, 0x0C, 0xFE, 0x00, 0x20, 0x31, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x23, 0x0E, 0x0B, 0xD1, 0x26, 0x0C, 0xF4, 0xB2, ++0x00, 0x2D, 0x8F, 0xD0, 0x3C, 0xB9, 0x04, 0x9B, 0x59, 0x7D, 0x00, 0x29, 0x40, 0xF0, 0x99, 0x80, 0x00, 0x24, 0x00, 0xE0, ++0xDC, 0xB2, 0x1F, 0x2D, 0x28, 0xBF, 0x1F, 0x25, 0xE9, 0x06, 0x41, 0xEA, 0x85, 0x51, 0x51, 0x4A, 0x51, 0x48, 0xE8, 0xF7, ++0x17, 0xFB, 0x51, 0x48, 0x29, 0x46, 0x0A, 0xF0, 0x23, 0xFC, 0x86, 0xE7, 0x4F, 0x48, 0x0A, 0xF0, 0x1F, 0xFC, 0x04, 0x9B, ++0x1D, 0x7D, 0x00, 0x2E, 0x70, 0xD0, 0x00, 0x2D, 0xE7, 0xD1, 0x3F, 0x2C, 0x21, 0x46, 0x4B, 0x48, 0x28, 0xBF, 0x3F, 0x21, ++0x3F, 0x22, 0x03, 0x91, 0xE8, 0xF7, 0x00, 0xFB, 0x03, 0x99, 0x48, 0x48, 0x0A, 0xF0, 0x0C, 0xFC, 0x04, 0x9B, 0xDB, 0x68, ++0x00, 0x2B, 0x3F, 0xF4, 0x73, 0xAF, 0x04, 0x9B, 0x18, 0x69, 0xEB, 0xF7, 0x6F, 0xF8, 0x6D, 0xE7, 0x42, 0x4A, 0x38, 0x4D, ++0x93, 0x69, 0xD5, 0xF8, 0x28, 0x42, 0xDF, 0xF8, 0x20, 0xA1, 0x40, 0x4F, 0x43, 0xF0, 0x01, 0x03, 0x93, 0x61, 0x04, 0x9B, ++0x5B, 0x68, 0x08, 0x93, 0x41, 0xF2, 0x7C, 0x52, 0x00, 0x23, 0x11, 0x46, 0xCD, 0xE9, 0x00, 0x33, 0x01, 0x20, 0xA0, 0x47, ++0x39, 0x4A, 0x01, 0x23, 0x82, 0xF8, 0x2A, 0x30, 0x0A, 0xA9, 0xD5, 0xF8, 0x70, 0x32, 0x37, 0x4D, 0x08, 0xA8, 0x98, 0x47, ++0x54, 0x46, 0xCD, 0xF8, 0x10, 0xA0, 0xDD, 0xF8, 0x1C, 0xA0, 0xE3, 0x79, 0x00, 0x93, 0x06, 0xEB, 0x08, 0x02, 0x23, 0x68, ++0x03, 0x92, 0x39, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, 0x22, 0xFC, 0x16, 0xF8, 0x01, 0xCB, 0x5A, 0xF8, 0x04, 0x3F, ++0x03, 0x9A, 0xCD, 0xF8, 0x00, 0xC0, 0x29, 0x46, 0x23, 0x60, 0x84, 0xF8, 0x07, 0xC0, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, ++0x13, 0xFC, 0x4E, 0x45, 0x04, 0xF1, 0x10, 0x04, 0xE1, 0xD1, 0x9B, 0xF8, 0xB4, 0x30, 0xDD, 0xF8, 0x10, 0xA0, 0x00, 0x2B, ++0x3F, 0xF4, 0x65, 0xAF, 0x13, 0x4B, 0x00, 0x20, 0xD3, 0xF8, 0x80, 0x34, 0x98, 0x47, 0x1D, 0x4B, 0x1E, 0x49, 0x93, 0xF8, ++0x2A, 0x20, 0x08, 0x20, 0x00, 0x23, 0x0A, 0xF0, 0xFB, 0xFB, 0x5B, 0xE7, 0x59, 0x7D, 0x1C, 0x46, 0x39, 0xB1, 0x0A, 0x48, ++0x0A, 0xF0, 0xA4, 0xFB, 0x64, 0x7D, 0x00, 0x2D, 0x3F, 0xF4, 0x05, 0xAF, 0x6D, 0xE7, 0x00, 0x2D, 0x3F, 0xF4, 0x03, 0xAF, ++0x66, 0xE7, 0x04, 0x48, 0x0A, 0xF0, 0x98, 0xFB, 0x04, 0x9B, 0x5C, 0x7D, 0x63, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x15, 0x00, ++0xBC, 0x9D, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, ++0x00, 0x00, 0xC0, 0xFF, 0x04, 0x88, 0x01, 0x50, 0xD0, 0x9D, 0x15, 0x00, 0xAC, 0x9D, 0x15, 0x00, 0x28, 0x91, 0x01, 0x50, ++0xE4, 0x9D, 0x15, 0x00, 0x00, 0x80, 0x50, 0x40, 0x44, 0x9E, 0x15, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x64, 0x9E, 0x15, 0x00, ++0x9C, 0x77, 0x15, 0x00, 0xFC, 0x9D, 0x15, 0x00, 0x20, 0x9E, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, ++0x38, 0xB5, 0x00, 0x22, 0x0D, 0x46, 0x01, 0x23, 0x0C, 0x21, 0x54, 0x20, 0x08, 0xF0, 0xFA, 0xFC, 0x01, 0x23, 0x03, 0x70, ++0x04, 0x46, 0x28, 0x78, 0x04, 0x28, 0x0D, 0xD8, 0x0C, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, ++0xC0, 0x34, 0x2B, 0xB1, 0x00, 0x23, 0x23, 0x70, 0x69, 0x78, 0x31, 0xB1, 0x06, 0xF0, 0xA2, 0xFB, 0x20, 0x46, 0x08, 0xF0, ++0x13, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x06, 0xF0, 0xBD, 0xFB, 0x20, 0x46, 0x08, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x38, 0xBD, ++0x18, 0x88, 0x17, 0x00, 0x70, 0xB5, 0x10, 0x46, 0x14, 0x46, 0x0D, 0x46, 0x1E, 0x46, 0x08, 0xF0, 0x73, 0xFF, 0x03, 0x28, ++0x25, 0xD0, 0x20, 0x46, 0x08, 0xF0, 0x6E, 0xFF, 0x04, 0x28, 0x20, 0xD0, 0x2A, 0x78, 0x1B, 0x4D, 0x20, 0x46, 0xEA, 0x77, ++0x72, 0xB9, 0x08, 0xF0, 0x65, 0xFF, 0x02, 0x28, 0x17, 0xD0, 0x18, 0x4B, 0xD3, 0xF8, 0x60, 0x31, 0x98, 0x47, 0x23, 0x20, ++0x22, 0x46, 0x31, 0x46, 0x08, 0xF0, 0x20, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x08, 0xF0, 0x56, 0xFF, 0x58, 0xB1, 0x02, 0x28, ++0xF9, 0xD0, 0x10, 0x4B, 0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x20, 0x46, 0x02, 0x21, 0x08, 0xF0, 0xA3, 0xFE, 0x02, 0x20, ++0x70, 0xBD, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x02, 0xDB, 0x00, 0x23, 0x6B, 0x82, 0xE0, 0xE7, ++0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0xF8, 0xD0, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x31, 0x62, 0x0A, 0xF0, 0x76, 0xFD, ++0xF1, 0xE7, 0x00, 0xBF, 0x98, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, ++0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x70, 0xB5, 0x1E, 0x4D, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x0E, 0x46, 0x14, 0x46, 0x1C, 0xDB, 0x20, 0x46, 0x08, 0xF0, 0x1C, 0xFF, 0x58, 0xB1, 0x02, 0x28, 0x08, 0xD0, 0x18, 0x4B, ++0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x20, 0x46, 0x02, 0x21, 0x08, 0xF0, 0x69, 0xFE, 0x02, 0x20, 0x70, 0xBD, 0x2B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x13, 0xDB, 0x20, 0x46, 0x03, 0x21, 0x08, 0xF0, 0x5E, 0xFE, 0x33, 0x68, 0x98, 0x47, ++0x00, 0x20, 0x70, 0xBD, 0x10, 0x46, 0x08, 0xF0, 0xFF, 0xFE, 0x04, 0x28, 0xDD, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, ++0x71, 0x62, 0x0A, 0xF0, 0x37, 0xFD, 0xD6, 0xE7, 0x09, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0xE7, 0xD0, 0x05, 0x49, 0x08, 0x48, ++0x4F, 0xF4, 0xCF, 0x62, 0x0A, 0xF0, 0x2C, 0xFD, 0xE0, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xAC, 0x9E, 0x15, 0x00, 0x38, 0x00, 0x32, 0x40, 0x84, 0x9E, 0x15, 0x00, 0x70, 0xB5, 0x12, 0x4C, ++0x88, 0x78, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x40, 0x82, 0xB0, 0x90, 0xF8, 0x62, 0x40, 0x1E, 0x46, 0x84, 0xB9, ++0x90, 0xF8, 0x6C, 0x00, 0x0C, 0x4D, 0x0C, 0x88, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x00, 0x51, 0xA4, 0x02, 0x8C, 0x60, ++0x31, 0x46, 0x15, 0x20, 0x08, 0xF0, 0x8A, 0xFC, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x06, 0x4C, 0x09, 0x88, 0xD4, 0xF8, ++0x60, 0x44, 0x01, 0x92, 0xA0, 0x47, 0x01, 0x9A, 0xF0, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x88, 0x79, 0x19, 0x4D, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x00, 0xF6, ++0x06, 0xF1, 0x38, 0x00, 0x28, 0x44, 0x35, 0x44, 0x82, 0xB0, 0x90, 0x46, 0x06, 0x22, 0x1F, 0x46, 0x0C, 0x46, 0x1C, 0xF0, ++0x85, 0xFF, 0x95, 0xF8, 0xC0, 0x34, 0x73, 0xB9, 0x10, 0x49, 0x11, 0x4B, 0x20, 0x68, 0xA2, 0x88, 0x08, 0x60, 0x1A, 0x60, ++0x42, 0x46, 0x39, 0x46, 0x19, 0x20, 0x08, 0xF0, 0x57, 0xFC, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x0D, 0xF1, ++0x07, 0x00, 0xFC, 0xF7, 0x9F, 0xFF, 0x00, 0x28, 0xF0, 0xD1, 0x08, 0x49, 0x08, 0x48, 0xD1, 0xE9, 0x00, 0x23, 0x43, 0xF0, ++0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, 0x02, 0x60, 0xE6, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x20, 0x00, 0x32, 0x40, ++0x24, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x0D, 0x46, 0x9E, 0x4F, ++0x95, 0xF8, 0x03, 0xA0, 0x4F, 0xF4, 0xA4, 0x61, 0x89, 0xB0, 0x01, 0xFB, 0x0A, 0xFB, 0x07, 0xEB, 0x0B, 0x06, 0x00, 0x24, ++0x0D, 0xF1, 0x1F, 0x00, 0x90, 0x46, 0x99, 0x46, 0x8D, 0xF8, 0x1F, 0x40, 0xFC, 0xF7, 0x72, 0xFF, 0x96, 0xF8, 0x62, 0x30, ++0xAA, 0x78, 0x86, 0xF8, 0x64, 0x20, 0x04, 0x46, 0x00, 0x2B, 0x40, 0xF0, 0xED, 0x80, 0x96, 0xF8, 0x6C, 0x10, 0x02, 0x91, ++0x00, 0x2A, 0x00, 0xF0, 0x45, 0x81, 0x8E, 0x4A, 0x8E, 0x4B, 0x03, 0x92, 0x8C, 0x46, 0x8E, 0x49, 0x18, 0x69, 0xD2, 0xF8, ++0xE0, 0x31, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x0C, 0x12, 0x0B, 0xF1, 0x18, 0x01, 0x79, 0x18, 0x04, 0x91, 0x91, 0x68, ++0x05, 0x92, 0x41, 0x18, 0x04, 0x98, 0x98, 0x47, 0x05, 0x9A, 0x2B, 0x88, 0x13, 0x84, 0xFC, 0xF7, 0x39, 0xFF, 0x05, 0x9A, ++0x96, 0xF8, 0xC0, 0x14, 0x01, 0x94, 0x13, 0x8C, 0x92, 0xF8, 0x23, 0x20, 0x00, 0x91, 0x4F, 0xF4, 0x80, 0x70, 0x7F, 0x49, ++0x0A, 0xF0, 0x3C, 0xFA, 0x96, 0xF8, 0xC0, 0x34, 0x33, 0xB9, 0x7D, 0x4A, 0x29, 0x88, 0x13, 0x68, 0x9B, 0xB2, 0x43, 0xEA, ++0x01, 0x43, 0x13, 0x60, 0x7A, 0x4B, 0x1B, 0x68, 0x18, 0x04, 0x00, 0xF1, 0xD2, 0x81, 0x79, 0x49, 0x79, 0x4B, 0xB1, 0xF8, ++0x1C, 0xC0, 0x02, 0x99, 0x08, 0x46, 0x72, 0x49, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x00, 0x12, 0x4F, 0xF4, 0xA4, 0x6B, ++0x90, 0x68, 0x02, 0x92, 0x0B, 0xFB, 0x0A, 0x7B, 0x0C, 0xF1, 0x14, 0x0C, 0x00, 0xFB, 0x0C, 0xFC, 0xA3, 0xFB, 0x0C, 0x3C, ++0xDB, 0xF8, 0x04, 0x00, 0x4F, 0xEA, 0x9C, 0x4C, 0x00, 0x23, 0xA2, 0xF8, 0x1E, 0xC0, 0x40, 0xF0, 0x01, 0x00, 0xDF, 0xF8, ++0x90, 0xC1, 0xAB, 0xF8, 0x68, 0x30, 0x8B, 0xF8, 0x6A, 0x30, 0x8B, 0xF8, 0x8C, 0x30, 0x8B, 0xF8, 0x78, 0x30, 0xCB, 0xF8, ++0x74, 0x30, 0xCB, 0xF8, 0x04, 0x00, 0xDC, 0xF8, 0x10, 0x00, 0xCB, 0xF8, 0x70, 0x00, 0x30, 0x46, 0x04, 0xF0, 0xF4, 0xFA, ++0x9B, 0xF8, 0xC0, 0x04, 0x5D, 0x49, 0x00, 0x23, 0x00, 0x28, 0x40, 0xF0, 0x76, 0x81, 0x5D, 0x4B, 0x02, 0x9A, 0x9B, 0x7C, ++0x00, 0x2B, 0x40, 0xF0, 0x8B, 0x81, 0x00, 0x2C, 0x40, 0xF0, 0xD5, 0x81, 0xDF, 0xF8, 0x7C, 0xB1, 0xDB, 0xF8, 0x20, 0x30, ++0x00, 0x2B, 0x40, 0xF0, 0x81, 0x81, 0x9D, 0xF8, 0x1F, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x87, 0x82, 0x53, 0x49, 0x93, 0x68, ++0x0A, 0x68, 0xCB, 0xF8, 0x20, 0x60, 0x12, 0x0C, 0x12, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x13, 0x43, 0x0B, 0x60, 0xDD, 0xE9, ++0x03, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x8B, 0xF8, 0x24, 0x40, 0xD3, 0xF8, 0x60, 0x32, 0x98, 0x47, ++0xAA, 0x78, 0x11, 0x46, 0x30, 0x46, 0x05, 0xF0, 0x5B, 0xFF, 0xAB, 0x78, 0x00, 0x2B, 0x38, 0xD0, 0x45, 0x4B, 0x1B, 0x68, ++0x1A, 0x68, 0x00, 0x2A, 0x00, 0xF0, 0xE0, 0x80, 0x43, 0x49, 0x0A, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0x00, 0xF0, 0xE5, 0x80, ++0xC2, 0xF3, 0x0B, 0x01, 0x00, 0x29, 0x40, 0xF0, 0x4F, 0x81, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x0A, 0x71, 0x22, 0xF4, ++0x7F, 0x62, 0xC9, 0x68, 0x3B, 0x48, 0x22, 0xF0, 0x0F, 0x02, 0xC1, 0xF3, 0x0B, 0x01, 0x0A, 0x43, 0x02, 0x60, 0x9A, 0x68, ++0x00, 0x2A, 0x40, 0xF0, 0xD9, 0x80, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, 0x35, 0x49, 0x12, 0x69, 0x0A, 0x60, ++0xDB, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xD4, 0x80, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x77, 0x30, 0x4B, 0x7A, 0x69, ++0x1A, 0x60, 0x21, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, 0x98, 0x47, 0x42, 0x46, 0x49, 0x46, 0x1F, 0x20, 0x08, 0xF0, 0x30, 0xFB, ++0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x80, 0xB1, 0x22, 0x4B, 0x9C, 0x68, 0x6C, 0xB1, 0x94, 0xF8, 0x62, 0x30, ++0x3B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x23, 0xB1, 0xA6, 0x42, 0x02, 0xD0, 0x94, 0xF8, 0xC0, 0x34, 0x13, 0xB1, 0x24, 0x68, ++0x00, 0x2C, 0xF1, 0xD1, 0x00, 0x2A, 0x00, 0xF0, 0xB2, 0x80, 0x1F, 0x4B, 0x19, 0x6A, 0xA1, 0x42, 0x9D, 0xD1, 0x0E, 0x49, ++0x1D, 0x4C, 0xD1, 0xF8, 0x64, 0x12, 0x00, 0x22, 0x1A, 0x62, 0x83, 0xF8, 0x24, 0x20, 0x88, 0x47, 0x0F, 0x4A, 0x1A, 0x48, ++0xD2, 0xE9, 0x00, 0x13, 0x43, 0xF0, 0x10, 0x03, 0x19, 0x43, 0x01, 0x60, 0x17, 0x48, 0x18, 0x49, 0x20, 0x60, 0x53, 0x60, ++0x0B, 0x68, 0x03, 0x43, 0x0B, 0x60, 0xAA, 0x78, 0x83, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0xD0, 0x9E, 0x15, 0x00, 0x68, 0x00, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x83, 0xDE, 0x1B, 0x43, 0x00, 0x88, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, 0xAC, 0x35, 0x17, 0x00, ++0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x70, 0x80, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x74, 0x80, 0x32, 0x40, 0xAC, 0x4B, 0x03, 0x93, ++0x0B, 0xF1, 0x18, 0x00, 0x38, 0x44, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0xD3, 0xF8, 0xDC, 0x33, 0x98, 0x47, ++0xA7, 0x49, 0x96, 0xF8, 0xC0, 0x24, 0x23, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0x0A, 0xF9, 0xA4, 0x4B, 0x1B, 0x68, ++0x19, 0x04, 0x00, 0xF1, 0xD8, 0x80, 0xA3, 0x4B, 0x9B, 0x7F, 0x3B, 0xB9, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, ++0x82, 0xF8, 0xC3, 0x34, 0xC2, 0xF8, 0xC4, 0x34, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x73, 0x93, 0xF8, 0xC0, 0x34, ++0x00, 0x2B, 0x00, 0xF0, 0x8C, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0x8E, 0x80, 0x98, 0x4B, 0x9C, 0x68, 0x00, 0x2C, 0x00, 0xF0, ++0x89, 0x80, 0x94, 0xF8, 0x62, 0x30, 0x4B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x33, 0xB1, 0xA6, 0x42, 0x04, 0xD0, 0x94, 0xF8, ++0xC0, 0x34, 0x00, 0x2B, 0x00, 0xF0, 0x4A, 0x81, 0x24, 0x68, 0x00, 0x2C, 0xEF, 0xD1, 0x77, 0xE0, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x0A, 0x72, 0x8C, 0x49, 0x92, 0x68, 0x0A, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0x7F, 0xF4, 0x1B, 0xAF, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, 0x88, 0x49, 0xD2, 0x68, 0x0A, 0x60, 0x9A, 0x68, 0x00, 0x2A, 0x3F, 0xF4, 0x27, 0xAF, ++0x85, 0x49, 0x0A, 0x60, 0xDB, 0x68, 0x00, 0x2B, 0x3F, 0xF4, 0x2C, 0xAF, 0x83, 0x4A, 0x13, 0x60, 0x7A, 0x4B, 0xD3, 0xF8, ++0xA0, 0x31, 0x98, 0x47, 0x2F, 0xE7, 0x81, 0x48, 0x81, 0x49, 0x03, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x03, 0x60, 0x0B, 0x6A, ++0x00, 0x2B, 0x7F, 0xF4, 0xE6, 0xAE, 0x00, 0x2C, 0x3F, 0xF4, 0xE3, 0xAE, 0xDF, 0xF8, 0xC4, 0xB1, 0x0C, 0x62, 0x81, 0xF8, ++0x24, 0x20, 0x04, 0xF1, 0x18, 0x00, 0xDB, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xDB, 0xF8, 0x60, 0x32, 0x98, 0x47, 0x76, 0x49, ++0xDF, 0xF8, 0xE4, 0xC1, 0x75, 0x48, 0xD4, 0xF8, 0x38, 0xE0, 0xA4, 0x8F, 0xD1, 0xE9, 0x00, 0x32, 0x22, 0xF0, 0x10, 0x02, ++0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0xC0, 0xF8, 0x00, 0xE0, 0x70, 0x4B, 0x4C, 0xF8, 0x3C, 0x4C, 0x00, 0xF5, 0x00, 0x40, ++0x54, 0x30, 0x6E, 0x4C, 0x1C, 0x60, 0x03, 0x68, 0x4A, 0x60, 0x23, 0xF4, 0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, 0x03, 0x60, ++0x1A, 0xE0, 0xCC, 0xB1, 0x64, 0x4A, 0x10, 0x6A, 0xB0, 0xB1, 0x13, 0x62, 0x82, 0xF8, 0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, ++0x64, 0x32, 0x98, 0x47, 0x60, 0x49, 0x64, 0x48, 0xD1, 0xE9, 0x00, 0x23, 0x43, 0xF0, 0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, ++0x02, 0x60, 0xAA, 0x78, 0x9F, 0xE6, 0x02, 0x2C, 0x65, 0xD0, 0x01, 0x2C, 0x00, 0xF0, 0xC0, 0x80, 0xAA, 0x78, 0x98, 0xE6, ++0x52, 0x49, 0x0A, 0x60, 0x94, 0xE7, 0xE6, 0xF7, 0x1F, 0xFE, 0x00, 0x28, 0x3F, 0xF4, 0x29, 0xAE, 0x02, 0x9A, 0x11, 0x46, ++0x57, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x23, 0x5B, 0x68, 0x9A, 0x06, 0x7F, 0xF5, 0x1E, 0xAE, 0x28, 0x88, ++0xE6, 0xF7, 0x54, 0xFE, 0xF9, 0xF7, 0x9C, 0xF9, 0x51, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0x41, 0xF8, 0x03, 0x9B, ++0xD3, 0xF8, 0xE0, 0x33, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x73, 0x93, 0xF8, 0x62, 0x20, 0x04, 0x2A, ++0x3F, 0xF4, 0x07, 0xAE, 0x93, 0xF8, 0x63, 0x00, 0x03, 0x9B, 0xD3, 0xF8, 0x30, 0x33, 0x98, 0x47, 0xFF, 0xE5, 0xE6, 0xF7, ++0xF1, 0xFD, 0x00, 0x28, 0x3F, 0xF4, 0x23, 0xAF, 0x41, 0x4B, 0x02, 0x99, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0x3B, ++0xDB, 0xF8, 0x04, 0x30, 0x9B, 0x06, 0x7F, 0xF5, 0x18, 0xAF, 0x96, 0xF8, 0x62, 0x30, 0x04, 0x2B, 0x3F, 0xF4, 0x13, 0xAF, ++0x96, 0xF8, 0x63, 0x00, 0x06, 0xF0, 0x2A, 0xFB, 0x0D, 0xE7, 0x01, 0x2C, 0xB0, 0xD1, 0x30, 0x4C, 0x22, 0x6A, 0xB2, 0x42, ++0xAC, 0xD0, 0x23, 0x62, 0x02, 0x93, 0xDD, 0xE9, 0x03, 0x30, 0xD3, 0xF8, 0xD8, 0x21, 0x90, 0x47, 0x02, 0x9B, 0x84, 0xF8, ++0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, 0x64, 0x32, 0x98, 0x47, 0xAA, 0x78, 0x37, 0xE6, 0x26, 0x4C, 0x23, 0x6A, 0x00, 0x2B, ++0x98, 0xD1, 0x1E, 0x4B, 0x98, 0x68, 0x20, 0xB9, 0xA3, 0xE0, 0x00, 0x68, 0x00, 0x28, 0x00, 0xF0, 0xA0, 0x80, 0x90, 0xF8, ++0x62, 0x30, 0x00, 0x2B, 0xF7, 0xD1, 0x90, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF3, 0xD0, 0x86, 0x42, 0xF1, 0xD0, 0x90, 0xF8, ++0xC0, 0x34, 0x00, 0x2B, 0xED, 0xD1, 0x1F, 0x49, 0x17, 0x4A, 0x20, 0x62, 0x9B, 0x46, 0x90, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, ++0x1E, 0x7C, 0x0C, 0xFB, 0x03, 0x13, 0x11, 0x68, 0x9B, 0x68, 0x09, 0x0C, 0x09, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x0B, 0x43, ++0x13, 0x60, 0x03, 0x9B, 0x18, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x84, 0xF8, 0x24, 0xB0, 0xD3, 0xF8, ++0x60, 0x32, 0x98, 0x47, 0xAA, 0x78, 0xFE, 0xE5, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x9F, 0x15, 0x00, 0x04, 0x00, 0x32, 0x40, ++0x64, 0xBA, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, ++0x0C, 0x02, 0x32, 0x40, 0x64, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x20, 0x00, 0x32, 0x40, ++0x70, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x60, 0x00, 0x32, 0x40, 0x68, 0x65, 0x17, 0x00, 0xF0, 0x9E, 0x15, 0x00, ++0x29, 0x4A, 0x11, 0x6A, 0xB1, 0x42, 0x7F, 0xF4, 0x3B, 0xAF, 0x13, 0x62, 0x82, 0xF8, 0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, ++0x64, 0x32, 0x98, 0x47, 0xAA, 0x78, 0xCC, 0xE5, 0xDF, 0xF8, 0x88, 0xB0, 0xDB, 0xF8, 0x20, 0x20, 0x00, 0x2A, 0x7F, 0xF4, ++0x2B, 0xAF, 0x94, 0xF8, 0x6C, 0x30, 0x1F, 0x48, 0x1F, 0x49, 0xCB, 0xF8, 0x20, 0x40, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, ++0x03, 0x03, 0x08, 0x68, 0x9B, 0x68, 0x02, 0x92, 0x00, 0x0C, 0x00, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x03, 0x43, 0x0B, 0x60, ++0x03, 0x9B, 0x04, 0xF1, 0x18, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x02, 0x9A, 0x8B, 0xF8, 0x24, 0x20, ++0xD3, 0xF8, 0x60, 0x32, 0xDF, 0xF8, 0x50, 0xB0, 0x98, 0x47, 0x11, 0x49, 0xDF, 0xF8, 0x4C, 0xC0, 0x10, 0x48, 0xD4, 0xF8, ++0x38, 0xE0, 0xA4, 0x8F, 0xD1, 0xE9, 0x00, 0x23, 0x23, 0xF0, 0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, 0xCB, 0xF8, 0x00, 0x20, ++0xCC, 0xF8, 0x00, 0xE0, 0x04, 0x60, 0xAA, 0x78, 0x8F, 0xE5, 0x01, 0x2B, 0x7F, 0xF4, 0xF2, 0xAE, 0xE1, 0xE6, 0x00, 0x23, ++0x93, 0xF8, 0x6C, 0x30, 0xFF, 0xDE, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x24, 0x00, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x38, 0xB5, 0x07, 0x20, ++0x0C, 0x46, 0x19, 0x46, 0x02, 0x23, 0x08, 0xF0, 0x7F, 0xF8, 0x23, 0x46, 0x07, 0x4D, 0x13, 0xF8, 0x02, 0x1B, 0x22, 0x7A, ++0xD5, 0xF8, 0x58, 0x54, 0x04, 0x46, 0x18, 0x46, 0x63, 0x1C, 0xA8, 0x47, 0x20, 0x70, 0x20, 0x46, 0x08, 0xF0, 0xA0, 0xF8, ++0x00, 0x20, 0x38, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xB5, 0x08, 0x78, 0x03, 0x28, 0x83, 0xB0, 0x19, 0x46, 0x07, 0xD8, ++0xCD, 0xE9, 0x00, 0x23, 0x0C, 0x4B, 0xD3, 0xF8, 0x64, 0x34, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0x0A, 0x4B, 0x9B, 0x68, ++0x33, 0xB1, 0x09, 0x20, 0x08, 0xF0, 0xC0, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x04, 0x4B, 0xD3, 0xF8, ++0xE8, 0x30, 0xCD, 0xE9, 0x00, 0x21, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0xEF, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x78, 0x0C, 0x46, 0x16, 0x46, 0x98, 0x46, 0x00, 0x2D, 0x3B, 0xD1, ++0x91, 0xF8, 0x02, 0xC0, 0x26, 0x49, 0x27, 0x4A, 0x11, 0xF8, 0x0C, 0x00, 0xE1, 0x78, 0x52, 0xF8, 0x20, 0x20, 0x60, 0x78, ++0x24, 0x4F, 0x25, 0x4B, 0x91, 0x42, 0xB8, 0xBF, 0x4A, 0x08, 0x00, 0xEB, 0x80, 0x01, 0xC0, 0xEB, 0x01, 0x11, 0x61, 0x44, ++0x07, 0xEB, 0xC1, 0x01, 0x4F, 0xF0, 0x9E, 0x0E, 0x91, 0xF8, 0xA5, 0x11, 0x0E, 0xFB, 0x00, 0xC0, 0xA8, 0xBF, 0x02, 0xEB, ++0xD2, 0x72, 0x07, 0xEB, 0x80, 0x00, 0xA8, 0xBF, 0xC2, 0xF3, 0x47, 0x02, 0x01, 0xEB, 0x41, 0x01, 0x80, 0xF8, 0x5A, 0x21, ++0x03, 0xEB, 0xC1, 0x01, 0xA2, 0x88, 0x0A, 0x81, 0x32, 0x46, 0x41, 0x46, 0x03, 0x23, 0x29, 0x20, 0x08, 0xF0, 0x0C, 0xF8, ++0x62, 0x78, 0x02, 0x70, 0xA2, 0x78, 0x42, 0x70, 0x85, 0x70, 0x08, 0xF0, 0x35, 0xF8, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, ++0x48, 0x78, 0x0B, 0x49, 0xA2, 0x88, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0x10, 0xA1, 0x78, 0x14, 0xF0, 0xA0, 0xFB, ++0x08, 0xB9, 0x04, 0x25, 0xE2, 0xE7, 0x07, 0x49, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x00, 0x25, 0xDB, 0xE7, ++0xC0, 0xB2, 0x15, 0x00, 0x7C, 0x28, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x54, 0x00, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x43, 0x04, 0x46, 0x87, 0xB0, 0x10, 0x46, 0x15, 0x46, 0x0E, 0x46, 0x1F, 0x46, 0x08, 0xF0, 0x7C, 0xFA, ++0x40, 0xB1, 0x02, 0x38, 0x80, 0xB2, 0x02, 0x28, 0x4D, 0xD8, 0x02, 0x24, 0x20, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, ++0xDF, 0xF8, 0x88, 0x83, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x65, 0xDB, 0x3B, 0x2C, 0x00, 0xF2, ++0xA7, 0x80, 0x05, 0x2C, 0x40, 0xF2, 0xE3, 0x80, 0x06, 0x3C, 0x35, 0x2C, 0x4A, 0xD8, 0xDF, 0xE8, 0x14, 0xF0, 0xBF, 0x01, ++0x49, 0x00, 0xB5, 0x01, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x88, 0x01, 0x49, 0x00, 0x6E, 0x01, ++0x49, 0x00, 0x5A, 0x01, 0x49, 0x00, 0x50, 0x01, 0x49, 0x00, 0x3A, 0x01, 0x49, 0x00, 0x30, 0x01, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0x1D, 0x01, 0x49, 0x00, 0x13, 0x01, 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0xF6, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0xEF, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0x49, 0x00, 0xE2, 0x00, 0xB1, 0x4B, 0xB1, 0x4C, 0x1B, 0x68, 0x28, 0x46, 0x03, 0xF0, 0x0F, 0x03, 0xE3, 0x74, ++0x08, 0xF0, 0x20, 0xFA, 0xAE, 0x4B, 0xA0, 0x74, 0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x28, 0x46, 0x02, 0x21, 0x08, 0xF0, ++0x6F, 0xF9, 0x9E, 0xE7, 0xDF, 0xF8, 0xA0, 0x82, 0x02, 0x24, 0x98, 0xF8, 0x13, 0x30, 0xA5, 0x4A, 0x1B, 0x01, 0xDB, 0xB2, ++0x13, 0x60, 0x28, 0x46, 0x98, 0xF8, 0x12, 0x10, 0x08, 0xF0, 0x60, 0xF9, 0x20, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, ++0x9E, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x40, 0xF0, 0x6F, 0x81, 0x3B, 0x2C, 0x67, 0xD8, 0x05, 0x2C, 0x67, 0xD9, 0x06, 0x3C, ++0x35, 0x2C, 0x64, 0xD8, 0xDF, 0xE8, 0x14, 0xF0, 0x56, 0x01, 0x63, 0x00, 0x4C, 0x01, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, ++0x63, 0x00, 0x63, 0x00, 0x1F, 0x01, 0x63, 0x00, 0x05, 0x01, 0x63, 0x00, 0xF1, 0x00, 0x63, 0x00, 0xE7, 0x00, 0x63, 0x00, ++0xD1, 0x00, 0x63, 0x00, 0xC7, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0xB4, 0x00, 0x63, 0x00, 0xAA, 0x00, 0x63, 0x00, ++0x97, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x8D, 0x00, 0x63, 0x00, ++0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x86, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, ++0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x79, 0x00, 0x87, 0x2C, 0x3C, 0xD1, ++0xDF, 0xF8, 0xF0, 0x81, 0xDF, 0xF8, 0xF0, 0x91, 0x00, 0x27, 0x88, 0xF8, 0x30, 0x70, 0x30, 0x68, 0xD9, 0xF8, 0xF8, 0x30, ++0x98, 0x47, 0x04, 0x46, 0x00, 0x28, 0x40, 0xF0, 0x19, 0x81, 0x98, 0xF8, 0x31, 0x30, 0x00, 0x2B, 0x97, 0xD0, 0x05, 0xA8, ++0x88, 0xF8, 0x31, 0x40, 0x01, 0xF0, 0x74, 0xFD, 0x00, 0x28, 0x90, 0xD0, 0x05, 0x9A, 0x71, 0x49, 0x92, 0xF8, 0x63, 0x30, ++0x92, 0xF8, 0xC1, 0x04, 0x03, 0xEB, 0xC3, 0x02, 0x03, 0xEB, 0x42, 0x03, 0x01, 0xEB, 0x43, 0x01, 0x05, 0xF0, 0x9C, 0xFF, ++0x81, 0xE7, 0x87, 0x2C, 0xD4, 0xD0, 0x6A, 0x49, 0x6A, 0x48, 0xDF, 0xF8, 0x98, 0x81, 0x40, 0xF6, 0x06, 0x22, 0x09, 0xF0, ++0xCB, 0xFF, 0x02, 0x24, 0x75, 0xE7, 0x87, 0x2C, 0xC8, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xED, 0xDB, 0xDF, 0xF8, 0x78, 0x81, 0x02, 0x24, 0x69, 0xE7, 0x5D, 0x4B, 0xDF, 0xF8, 0x6C, 0x81, 0x9B, 0x6D, 0x30, 0x46, ++0x98, 0x47, 0x2A, 0x46, 0x39, 0x46, 0x3C, 0x20, 0x07, 0xF0, 0x38, 0xFF, 0x00, 0x24, 0x5C, 0xE7, 0x30, 0x46, 0x09, 0xF0, ++0xD3, 0xFF, 0xDF, 0xF8, 0x50, 0x81, 0x00, 0x24, 0x55, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x28, 0x20, 0xFF, 0xF7, ++0x7B, 0xFE, 0xDF, 0xF8, 0x3C, 0x81, 0x04, 0x46, 0x4B, 0xE7, 0x52, 0x4B, 0x32, 0x78, 0x1B, 0x68, 0x51, 0x48, 0xDF, 0xF8, ++0x2C, 0x81, 0xDB, 0xB2, 0x03, 0xFB, 0x02, 0xF3, 0x42, 0xEA, 0x03, 0x23, 0x03, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x21, 0x20, ++0x07, 0xF0, 0x14, 0xFF, 0x00, 0x24, 0x38, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x1E, 0x20, 0xFF, 0xF7, 0xD4, 0xFA, ++0xDF, 0xF8, 0x00, 0x81, 0x04, 0x46, 0x2E, 0xE7, 0x45, 0x48, 0x33, 0x78, 0x02, 0x68, 0xDF, 0xF8, 0xF4, 0x80, 0x9B, 0x03, ++0x22, 0xF4, 0xE0, 0x32, 0x03, 0xF4, 0xE0, 0x33, 0x13, 0x43, 0x03, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x1D, 0x20, 0x07, 0xF0, ++0xF7, 0xFE, 0x00, 0x24, 0x1B, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x18, 0x20, 0xFF, 0xF7, 0x77, 0xFA, 0xDF, 0xF8, ++0xC8, 0x80, 0x04, 0x46, 0x11, 0xE7, 0x73, 0x79, 0xDF, 0xF8, 0xBC, 0x80, 0x36, 0x4A, 0x31, 0x68, 0x92, 0x6A, 0x08, 0xEB, ++0x83, 0x00, 0x41, 0x61, 0x22, 0xB1, 0x12, 0x79, 0x9A, 0x42, 0x04, 0xBF, 0x32, 0x4B, 0x19, 0x60, 0x39, 0x46, 0x2A, 0x46, ++0x17, 0x20, 0x07, 0xF0, 0xD7, 0xFE, 0x00, 0x24, 0xFB, 0xE6, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x14, 0x20, 0xFF, 0xF7, ++0x2B, 0xFA, 0xDF, 0xF8, 0x88, 0x80, 0x04, 0x46, 0xF1, 0xE6, 0x2A, 0x4A, 0x31, 0x78, 0x13, 0x68, 0xDF, 0xF8, 0x78, 0x80, ++0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x39, 0x46, 0x2A, 0x46, ++0x13, 0x20, 0x07, 0xF0, 0xB9, 0xFE, 0x00, 0x24, 0xDD, 0xE6, 0x39, 0x46, 0x02, 0x23, 0x2A, 0x46, 0x11, 0x20, 0x07, 0xF0, ++0x49, 0xFE, 0x72, 0x7A, 0xF3, 0x88, 0xB1, 0x7A, 0x02, 0x91, 0xCD, 0xE9, 0x00, 0x32, 0x04, 0x46, 0xB3, 0x88, 0x72, 0x88, ++0x71, 0x78, 0x30, 0x78, 0xDF, 0xF8, 0x34, 0x80, 0xE6, 0xF7, 0x1E, 0xFA, 0x20, 0x46, 0x07, 0xF0, 0x67, 0xFE, 0x00, 0x24, ++0xC3, 0xE6, 0xDF, 0xF8, 0x24, 0x80, 0x33, 0x68, 0xD8, 0xF8, 0x04, 0x10, 0x11, 0x4A, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0x43, ++0x13, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x0F, 0x20, 0x07, 0xF0, 0x8E, 0xFE, 0x00, 0x24, 0xB2, 0xE6, 0x38, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0xE4, 0x00, 0x32, 0x40, 0xE8, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x30, 0x9D, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, ++0x90, 0x00, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x08, 0x20, ++0xFF, 0xF7, 0x96, 0xFD, 0xDF, 0xF8, 0x2C, 0x81, 0x04, 0x46, 0x8C, 0xE6, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x06, 0x20, ++0xFF, 0xF7, 0x72, 0xFD, 0xDF, 0xF8, 0x18, 0x81, 0x04, 0x46, 0x82, 0xE6, 0xD9, 0xF8, 0x6C, 0x31, 0x30, 0x68, 0x98, 0x47, ++0x3C, 0x46, 0x7C, 0xE6, 0x3F, 0x49, 0x40, 0x48, 0x40, 0xF6, 0xC9, 0x12, 0x09, 0xF0, 0xCA, 0xFE, 0x3B, 0x2C, 0x3F, 0xF6, ++0xFE, 0xAE, 0x05, 0x2C, 0x7F, 0xF6, 0xFD, 0xAE, 0x06, 0x3C, 0x35, 0x2C, 0x3F, 0xF6, 0xF9, 0xAE, 0x01, 0xA3, 0x53, 0xF8, ++0x24, 0xF0, 0x00, 0xBF, 0xBD, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xA9, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x4F, 0xAD, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0x1B, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xF3, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xDF, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xB3, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x9F, 0xAC, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x79, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0x65, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x3F, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0x2B, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x1D, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x03, 0xAC, 0x13, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xC0, 0x68, 0xCB, 0x68, 0xC0, 0x1A, 0xC0, 0x0F, ++0x70, 0x47, 0x00, 0xBF, 0x01, 0x48, 0x08, 0xF0, 0xE9, 0xB9, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, 0x06, 0x4B, 0x38, 0xB1, ++0xC1, 0x68, 0x04, 0x22, 0x4F, 0xF4, 0x80, 0x20, 0x98, 0x60, 0x19, 0x63, 0x9A, 0x60, 0x70, 0x47, 0x4F, 0xF4, 0x80, 0x62, ++0x9A, 0x60, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x33, 0x4A, 0xF8, 0xB5, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0x0C, 0x46, ++0x05, 0x46, 0x57, 0xDB, 0x30, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x46, 0xDB, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2B, 0x4F, 0x2C, 0x4E, 0x3B, 0x68, 0x32, 0x68, ++0x01, 0x33, 0x95, 0x42, 0x3B, 0x60, 0x19, 0xD0, 0x29, 0x46, 0x30, 0x46, 0x08, 0xF0, 0x08, 0xFA, 0x30, 0x46, 0x27, 0x4A, ++0xEC, 0x60, 0x29, 0x46, 0x08, 0xF0, 0x40, 0xFA, 0x30, 0x68, 0x85, 0x42, 0x16, 0xD0, 0x3B, 0x68, 0x23, 0xB1, 0x1F, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0xA3, 0xB1, 0x1A, 0x4B, 0x19, 0x69, 0x64, 0x1A, 0x00, 0x2C, 0x17, 0xDB, 0xF8, 0xBD, ++0x30, 0x46, 0x08, 0xF0, 0xE3, 0xF9, 0x30, 0x46, 0x1A, 0x4A, 0xEC, 0x60, 0x29, 0x46, 0x08, 0xF0, 0x27, 0xFA, 0x30, 0x68, ++0x18, 0x4B, 0xD3, 0xF8, 0xDC, 0x31, 0x98, 0x47, 0xE3, 0xE7, 0x00, 0x2A, 0xE8, 0xD0, 0x62, 0xB6, 0x0E, 0x4B, 0x19, 0x69, ++0x64, 0x1A, 0x00, 0x2C, 0xE7, 0xDA, 0xBD, 0xE8, 0xF8, 0x40, 0x4F, 0xF0, 0x80, 0x40, 0x08, 0xF0, 0xE3, 0xB8, 0x09, 0x4B, ++0x1B, 0x69, 0xE3, 0x1A, 0x00, 0x2B, 0xB3, 0xDA, 0x0D, 0x49, 0x0E, 0x48, 0x7D, 0x22, 0x09, 0xF0, 0xCF, 0xFD, 0xAD, 0xE7, ++0x13, 0x69, 0x41, 0x68, 0x0B, 0x48, 0x22, 0x46, 0x09, 0xF0, 0x4E, 0xFB, 0xA0, 0xE7, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, ++0x38, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, 0xE9, 0xAE, 0x13, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x74, 0x9F, 0x15, 0x00, 0x4C, 0x9F, 0x15, 0x00, 0x38, 0xB5, 0x01, 0x46, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0F, 0x4C, 0x10, 0x4D, ++0x23, 0x68, 0x2A, 0x68, 0x01, 0x33, 0x8A, 0x42, 0x23, 0x60, 0x28, 0x46, 0x0B, 0xD0, 0x08, 0xF0, 0x99, 0xF9, 0x23, 0x68, ++0x33, 0xB1, 0x08, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x08, 0xF0, ++0x81, 0xF9, 0x06, 0x4B, 0x28, 0x68, 0xD3, 0xF8, 0xDC, 0x31, 0x98, 0x47, 0xED, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x2C, 0x4F, 0x2D, 0x4D, ++0xDF, 0xF8, 0xC8, 0xA0, 0xDF, 0xF8, 0xC0, 0x80, 0x2B, 0x4E, 0xB9, 0x46, 0x01, 0xE0, 0xA0, 0x68, 0x98, 0x47, 0x4F, 0xF0, ++0x80, 0x40, 0x08, 0xF0, 0x9F, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, ++0x00, 0x30, 0x2B, 0x68, 0x3C, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x4C, 0xB3, 0x32, 0x69, 0xE3, 0x68, 0x9B, 0x1A, 0x32, 0x2B, ++0x08, 0xD4, 0xDA, 0xF8, 0xDC, 0x31, 0x20, 0x46, 0x98, 0x47, 0x32, 0x69, 0xE3, 0x68, 0x9B, 0x1A, 0x00, 0x2B, 0x2A, 0xDA, ++0x48, 0x46, 0x08, 0xF0, 0x43, 0xF9, 0x2B, 0x68, 0x33, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x63, 0x68, 0xCB, 0xDA, 0x00, 0x2B, ++0xC9, 0xD1, 0x11, 0x49, 0x11, 0x48, 0xEB, 0x22, 0x09, 0xF0, 0x3C, 0xFD, 0x63, 0x68, 0xC2, 0xE7, 0xDA, 0xF8, 0xDC, 0x31, ++0x20, 0x46, 0x98, 0x47, 0x2B, 0x68, 0x33, 0xB1, 0x0C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF0, 0x87, 0x2B, 0x68, 0x00, 0x2B, 0xFA, 0xD0, 0xF2, 0xE7, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x9F, 0x15, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x11, 0xF4, 0x00, 0x05, 0x04, 0x46, 0x0E, 0xD1, 0x90, 0xF8, ++0x5C, 0x22, 0x1E, 0x49, 0x1E, 0x48, 0x01, 0x32, 0xD2, 0xB2, 0x84, 0xF8, 0x5C, 0x22, 0x09, 0xF0, 0x8D, 0xFA, 0x94, 0xF8, ++0x5C, 0x32, 0x09, 0x2B, 0x15, 0xD8, 0x70, 0xBD, 0x17, 0x49, 0x19, 0x48, 0x09, 0xF0, 0x84, 0xFA, 0x94, 0xF8, 0x23, 0x30, ++0x00, 0x22, 0x0D, 0x2B, 0x84, 0xF8, 0x5C, 0x22, 0xF3, 0xD8, 0x15, 0x49, 0x15, 0x4A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x03, 0x13, 0x12, 0x69, 0xC3, 0xF8, 0x58, 0x22, 0x70, 0xBD, 0x2A, 0x46, 0x08, 0x23, 0x0C, 0x21, 0x7D, 0x20, 0x07, 0xF0, ++0x05, 0xFC, 0x94, 0xF8, 0x23, 0x30, 0x03, 0x70, 0x94, 0xF8, 0x22, 0x30, 0x43, 0x70, 0x06, 0x46, 0x04, 0xF1, 0x26, 0x01, ++0x84, 0xF8, 0x5C, 0x52, 0x02, 0x30, 0x06, 0x22, 0x1B, 0xF0, 0x7E, 0xFF, 0x30, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x07, 0xF0, ++0x21, 0xBC, 0x00, 0xBF, 0x34, 0xA0, 0x15, 0x00, 0x9C, 0x9F, 0x15, 0x00, 0xB4, 0x9F, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x63, 0x30, 0x63, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x0A, 0x33, ++0x04, 0xFB, 0x03, 0xF3, 0x11, 0x46, 0x02, 0xF1, 0x28, 0x04, 0x1C, 0x44, 0x1A, 0x44, 0x83, 0xB0, 0x0B, 0x46, 0xD2, 0xF8, ++0x08, 0x12, 0x00, 0x29, 0x40, 0xF0, 0xA2, 0x80, 0xD2, 0xF8, 0x30, 0x12, 0x08, 0x32, 0x00, 0x29, 0x40, 0xF0, 0x9C, 0x80, ++0xA2, 0x42, 0xF2, 0xD1, 0x57, 0x4A, 0x58, 0x4C, 0xDF, 0xF8, 0x70, 0xB1, 0x4F, 0xF4, 0xA4, 0x61, 0x93, 0xF8, 0x25, 0x60, ++0x2E, 0xB1, 0x93, 0xF8, 0x22, 0x60, 0x01, 0xFB, 0x06, 0x46, 0xB0, 0x42, 0x06, 0xD0, 0x03, 0xF5, 0x1E, 0x73, 0x9A, 0x42, ++0xF2, 0xD1, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x93, 0xF8, 0x23, 0x60, 0x0D, 0x2E, 0x77, 0xD9, 0x4F, 0xF0, 0x00, 0x08, ++0xDB, 0xF8, 0x10, 0xE0, 0x1E, 0x46, 0x03, 0xF1, 0x28, 0x0C, 0xD6, 0xF8, 0x08, 0x72, 0x77, 0xB9, 0xD6, 0xF8, 0x30, 0x72, ++0x08, 0x36, 0x57, 0xB9, 0xB4, 0x45, 0xF6, 0xD1, 0xCE, 0xF5, 0x64, 0x0E, 0x0E, 0xF5, 0x61, 0x4E, 0x0E, 0xF1, 0xC0, 0x0E, ++0x1E, 0xEB, 0x08, 0x0F, 0xDB, 0xD5, 0x90, 0xF8, 0x63, 0x60, 0x93, 0xF8, 0x20, 0xE0, 0x00, 0x96, 0x35, 0x46, 0xC6, 0xEB, ++0x86, 0x17, 0x3C, 0x4E, 0x4F, 0xEA, 0xDE, 0x08, 0x06, 0xEB, 0x87, 0x07, 0x0E, 0xF0, 0x07, 0x0C, 0x01, 0x26, 0x18, 0xF8, ++0x07, 0x90, 0x06, 0xFA, 0x0C, 0xFC, 0x1C, 0xEA, 0x09, 0x0F, 0x07, 0xEB, 0xDE, 0x06, 0x01, 0x96, 0x5F, 0xFA, 0x8C, 0xFA, ++0x0F, 0xFA, 0x85, 0xFE, 0xBD, 0xD1, 0x4A, 0xEA, 0x09, 0x09, 0x08, 0xF8, 0x07, 0x90, 0xB0, 0xF8, 0xD0, 0x90, 0x90, 0xF8, ++0xD8, 0xC0, 0x09, 0xF1, 0x01, 0x09, 0xC4, 0x45, 0xA0, 0xF8, 0xD0, 0x90, 0x3E, 0xD8, 0xAF, 0x00, 0x90, 0xF8, 0xD9, 0x90, ++0xC1, 0x45, 0x0B, 0xD2, 0x00, 0x9D, 0x28, 0x4E, 0x80, 0xF8, 0xD9, 0x80, 0x07, 0xEB, 0x05, 0x0A, 0x06, 0xEB, 0xCA, 0x0A, ++0x01, 0x9E, 0xCA, 0xF8, 0x20, 0x60, 0xC1, 0x46, 0x23, 0x4E, 0x00, 0x9D, 0xCC, 0xF1, 0x06, 0x0C, 0xCC, 0x44, 0x06, 0xEB, ++0xCE, 0x0E, 0x1F, 0xFA, 0x8C, 0xFC, 0x1E, 0x4E, 0xA0, 0xF8, 0xCE, 0xC0, 0xAC, 0xF1, 0x02, 0x08, 0x8E, 0xF8, 0x01, 0x80, ++0x4F, 0xF0, 0x28, 0x0C, 0x2F, 0x44, 0x06, 0xEB, 0xC7, 0x07, 0x0C, 0xFB, 0x05, 0x66, 0x90, 0xF8, 0xD8, 0xC0, 0x8E, 0xF8, ++0x04, 0xC0, 0x14, 0x36, 0x0E, 0xF1, 0x04, 0x0E, 0xC7, 0xF8, 0x0C, 0xE0, 0x7E, 0x60, 0x7C, 0xE7, 0x0D, 0x4D, 0x4F, 0xF4, ++0x1E, 0x77, 0x07, 0xFB, 0x06, 0x56, 0xD6, 0xF8, 0x58, 0x82, 0x81, 0xE7, 0x0F, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x61, 0xE7, ++0x00, 0x9D, 0x0B, 0x4E, 0x05, 0xEB, 0x85, 0x09, 0x08, 0xF0, 0x1E, 0x0C, 0x06, 0xEB, 0xC9, 0x09, 0x67, 0x44, 0x80, 0xF8, ++0xD8, 0xC0, 0xC9, 0xF8, 0x1C, 0x70, 0xAF, 0x00, 0xB2, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x7E, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x3C, 0x4C, 0x18, 0x00, 0x9C, 0x4B, 0x18, 0x00, 0x2C, 0x50, 0x18, 0x00, 0x16, 0x2C, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF8, 0x43, 0x02, 0x88, 0xC3, 0x78, 0x04, 0x46, 0xB2, 0xB9, 0x82, 0x78, 0x00, 0x2A, ++0x40, 0xF0, 0xAD, 0x80, 0x88, 0x48, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x03, 0x83, 0xF8, 0xDA, 0x20, 0x34, 0xF8, ++0x04, 0x1C, 0x42, 0x20, 0x00, 0x22, 0x07, 0xF0, 0x5B, 0xFB, 0xA4, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0xF8, 0x43, 0x07, 0xF0, ++0x69, 0xBB, 0x80, 0x48, 0x80, 0x4D, 0x94, 0xF8, 0x02, 0xE0, 0xC3, 0xEB, 0x83, 0x11, 0x00, 0xEB, 0x81, 0x00, 0x01, 0x26, ++0xC2, 0xF3, 0xC7, 0x01, 0x02, 0xF0, 0x07, 0x02, 0x06, 0xFA, 0x02, 0xF2, 0x0F, 0x5C, 0x0E, 0x18, 0x5F, 0xFA, 0x82, 0xFC, ++0x05, 0xEB, 0xC3, 0x05, 0xBE, 0xF1, 0x00, 0x0F, 0x4D, 0xD0, 0x1C, 0xEA, 0x07, 0x0F, 0xD8, 0xD1, 0xDF, 0xF8, 0xC4, 0xE1, ++0x4F, 0xF4, 0xA4, 0x62, 0x4C, 0xEA, 0x07, 0x07, 0x02, 0xFB, 0x03, 0xE2, 0x37, 0x70, 0xB2, 0xF8, 0xD0, 0x70, 0x92, 0xF8, ++0xD8, 0xC0, 0x01, 0x37, 0x8C, 0x45, 0xA2, 0xF8, 0xD0, 0x70, 0x6C, 0x4F, 0x0A, 0xD9, 0x03, 0xEB, 0x83, 0x0C, 0x01, 0xF0, ++0xFE, 0x08, 0x07, 0xEB, 0xCC, 0x0C, 0x40, 0x44, 0xCC, 0xF8, 0x1C, 0x00, 0x82, 0xF8, 0xD8, 0x80, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x03, 0xE0, 0x4F, 0xEA, 0x83, 0x0C, 0x90, 0xF8, 0xD9, 0x80, 0x88, 0x45, 0x07, 0xD2, 0x0C, 0xEB, 0x03, 0x02, ++0x07, 0xEB, 0xC2, 0x02, 0x80, 0xF8, 0xD9, 0x10, 0x88, 0x46, 0x16, 0x62, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xEE, ++0x0C, 0xEB, 0x03, 0x01, 0x9E, 0xF8, 0xD8, 0x20, 0x2A, 0x71, 0xC2, 0xF1, 0x06, 0x02, 0x28, 0x20, 0x42, 0x44, 0x07, 0xEB, ++0xC1, 0x01, 0x00, 0xFB, 0x03, 0x73, 0x92, 0xB2, 0x2E, 0x1D, 0x14, 0x33, 0x90, 0x1E, 0xCE, 0x60, 0x4B, 0x60, 0xAE, 0xF8, ++0xCE, 0x20, 0x68, 0x70, 0x8D, 0xE7, 0x1C, 0xEA, 0x07, 0x0F, 0x8A, 0xD0, 0xDF, 0xF8, 0x28, 0xE1, 0x4F, 0xF4, 0xA4, 0x68, ++0x08, 0xFB, 0x03, 0xF8, 0x27, 0xEA, 0x02, 0x02, 0x0E, 0xEB, 0x08, 0x0C, 0x32, 0x70, 0xBC, 0xF8, 0xD0, 0x70, 0x01, 0x3F, ++0xBF, 0xB2, 0xAC, 0xF8, 0xD0, 0x70, 0x00, 0x2F, 0x4D, 0xD0, 0x9C, 0xF8, 0xD8, 0x70, 0x01, 0xF0, 0xFE, 0x02, 0x97, 0x42, ++0x29, 0xD0, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE2, 0x92, 0xF8, 0xD9, 0x70, 0x8F, 0x42, 0x35, 0xD0, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE3, 0x93, 0xF8, 0xD8, 0x10, 0x29, 0x71, 0xC1, 0xF1, 0x06, 0x01, 0x39, 0x44, 0x89, 0xB2, ++0x8A, 0x1E, 0xA3, 0xF8, 0xCE, 0x10, 0x6A, 0x70, 0x59, 0xE7, 0x32, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x13, ++0x01, 0x22, 0x83, 0xF8, 0xDA, 0x20, 0x50, 0xE7, 0x3A, 0x5C, 0x07, 0xF1, 0x01, 0x08, 0x00, 0x2A, 0x51, 0xD1, 0x5F, 0xFA, ++0x88, 0xF7, 0x8C, 0xF8, 0xD8, 0x70, 0xFB, 0x2F, 0xF4, 0xD1, 0xFA, 0x22, 0x17, 0x46, 0xDF, 0xF8, 0xA8, 0x90, 0x03, 0xEB, ++0x83, 0x08, 0x4F, 0xF4, 0xA4, 0x6C, 0x09, 0xEB, 0xC8, 0x08, 0x0C, 0xFB, 0x03, 0xEC, 0x02, 0x44, 0xC8, 0xF8, 0x1C, 0x20, ++0x8C, 0xF8, 0xD8, 0x70, 0xC1, 0xE7, 0x41, 0xB3, 0x37, 0x78, 0x01, 0x39, 0xB4, 0x46, 0xC9, 0xB2, 0x01, 0x3E, 0x57, 0xBB, ++0x82, 0xF8, 0xD9, 0x10, 0xF5, 0xE7, 0x0E, 0xF1, 0xD8, 0x02, 0x06, 0x21, 0xAC, 0xF8, 0xCE, 0x10, 0xFF, 0x21, 0x28, 0xF8, ++0x02, 0x10, 0x19, 0x4A, 0x9C, 0xF8, 0xCE, 0x10, 0x2F, 0x71, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x6E, 0x1D, ++0x8A, 0x1E, 0xDE, 0x60, 0x6A, 0x70, 0xE2, 0x78, 0x9C, 0xF8, 0xD9, 0x50, 0x12, 0x49, 0x02, 0xEB, 0x82, 0x02, 0x28, 0x44, ++0x01, 0xEB, 0x82, 0x02, 0x18, 0x62, 0x5A, 0x60, 0x09, 0xE7, 0x0F, 0x46, 0x0C, 0x4A, 0x03, 0xEB, 0x83, 0x01, 0x02, 0xEB, ++0xC1, 0x02, 0x10, 0x62, 0x97, 0xE7, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE2, 0x60, 0x46, 0x92, 0xF8, 0xD9, 0x70, ++0xF0, 0xE7, 0x07, 0xF0, 0xFE, 0x07, 0x3A, 0x46, 0xB1, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x3C, 0x4C, 0x18, 0x00, ++0x2C, 0x50, 0x18, 0x00, 0x9C, 0x4B, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x89, 0x46, 0xD0, 0xF8, ++0xB8, 0x50, 0x89, 0x88, 0x99, 0xF8, 0x08, 0xA0, 0x90, 0xF8, 0x63, 0xB0, 0xD5, 0xF8, 0x24, 0x80, 0x2A, 0x4B, 0xB9, 0xF8, ++0x06, 0x70, 0xD3, 0xF8, 0x54, 0x31, 0x29, 0x4E, 0xA1, 0xEB, 0x0A, 0x0A, 0x04, 0x46, 0x42, 0x46, 0xA0, 0xF8, 0xCC, 0xA0, ++0x58, 0x46, 0x98, 0x47, 0xB9, 0xF8, 0x06, 0x30, 0x6A, 0x6A, 0x21, 0x6C, 0x23, 0x48, 0x03, 0xF1, 0xFF, 0x3C, 0x62, 0x44, ++0xAA, 0x62, 0x99, 0xF8, 0x08, 0xC0, 0x06, 0xEB, 0xCB, 0x06, 0xDB, 0x43, 0x0B, 0xEB, 0x8B, 0x0B, 0x0C, 0xF1, 0x01, 0x0C, ++0x00, 0xEB, 0x8B, 0x0B, 0x62, 0x44, 0x53, 0x44, 0x13, 0x44, 0x00, 0x20, 0xCB, 0xE9, 0x02, 0x23, 0x03, 0x37, 0xCB, 0xF8, ++0x10, 0x00, 0x31, 0xB3, 0x94, 0xF8, 0xC0, 0x34, 0x0A, 0x79, 0x16, 0x49, 0xE3, 0xB1, 0x16, 0x4A, 0x16, 0x48, 0x13, 0x68, ++0x12, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0x00, 0x22, 0x4B, 0x62, 0xC5, 0xE9, 0x0D, 0x21, 0xE8, 0x64, ++0x94, 0xF8, 0x63, 0x30, 0x10, 0x4A, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x01, 0x22, 0x2B, 0x62, 0x84, 0xF8, ++0xD6, 0x20, 0x18, 0xF8, 0x07, 0x30, 0xF3, 0x70, 0xBD, 0xE8, 0xF8, 0x8F, 0x0A, 0x4B, 0x82, 0x42, 0x08, 0xBF, 0x19, 0x46, ++0xDD, 0xE7, 0x04, 0x49, 0xDB, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x50, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, ++0x84, 0x3C, 0x18, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x41, 0x00, 0x00, 0x01, 0x9C, 0x4B, 0x18, 0x00, 0xC4, 0x3C, 0x18, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x4D, 0x4D, 0x90, 0xF8, 0x63, 0x30, 0xD0, 0xF8, 0xB8, 0x80, 0x05, 0xEB, 0xC3, 0x05, 0x04, 0x46, ++0x2F, 0x79, 0x00, 0xF1, 0x6C, 0x06, 0xFF, 0xF7, 0x7D, 0xFD, 0xB0, 0xF8, 0xCC, 0x30, 0xB0, 0xF8, 0xCE, 0x20, 0x13, 0x44, ++0x04, 0x33, 0xC8, 0xF8, 0x2C, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x54, 0xD1, 0x42, 0x4A, 0xD8, 0xF8, 0x24, 0x10, ++0xB2, 0xF8, 0xFC, 0x31, 0x01, 0x33, 0x9B, 0xB2, 0x18, 0x01, 0xA2, 0xF8, 0xFC, 0x31, 0xC8, 0x82, 0x94, 0xF8, 0xD7, 0x30, ++0xAB, 0x70, 0x94, 0xF8, 0xDA, 0x90, 0xCB, 0xBB, 0xB9, 0xF1, 0x00, 0x0F, 0x31, 0xD1, 0x07, 0xF0, 0xFE, 0x07, 0x38, 0x4B, ++0x1B, 0x78, 0x0B, 0xB1, 0x47, 0xF0, 0x01, 0x07, 0xEB, 0x78, 0x84, 0xF8, 0xD7, 0x30, 0x2F, 0x71, 0x94, 0xF8, 0xD7, 0x30, ++0x94, 0xF8, 0xDB, 0x50, 0x01, 0x3B, 0x84, 0xF8, 0xD7, 0x30, 0xBD, 0xB1, 0x01, 0x3D, 0x94, 0xF8, 0xDC, 0x30, 0xED, 0xB2, ++0x84, 0xF8, 0xDB, 0x50, 0x63, 0xB1, 0xD8, 0xF8, 0x24, 0x20, 0xD5, 0x54, 0x94, 0xF8, 0xDD, 0x30, 0x23, 0xB1, 0xD8, 0xF8, ++0x24, 0x20, 0x94, 0xF8, 0xDB, 0x10, 0xD1, 0x54, 0x94, 0xF8, 0xDB, 0x50, 0x7D, 0xBB, 0x01, 0x23, 0x84, 0xF8, 0xDB, 0x30, ++0x20, 0x46, 0x31, 0x46, 0x06, 0xF0, 0xE0, 0xFC, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x47, 0xF0, 0x01, 0x07, 0x4F, 0xF0, ++0x01, 0x09, 0xCA, 0xE7, 0x19, 0xF0, 0x02, 0x09, 0x1A, 0xBF, 0x47, 0xF0, 0x01, 0x07, 0x4F, 0xF0, 0x01, 0x09, 0x07, 0xF0, ++0xFE, 0x07, 0xC8, 0xE7, 0x90, 0xF8, 0xC1, 0x04, 0x05, 0xF0, 0x7E, 0xF9, 0x00, 0x28, 0xA4, 0xD0, 0x94, 0xF8, 0x63, 0x10, ++0x15, 0x4A, 0xD8, 0xF8, 0x2C, 0x30, 0x01, 0xEB, 0x81, 0x01, 0x02, 0xEB, 0x81, 0x02, 0x19, 0x18, 0x93, 0x68, 0xC8, 0xF8, ++0x2C, 0x10, 0x01, 0x3B, 0x18, 0x44, 0xD0, 0x60, 0x93, 0xE7, 0x02, 0x23, 0x00, 0x22, 0x0C, 0x21, 0x4E, 0x20, 0x94, 0xF8, ++0x63, 0x70, 0x07, 0xF0, 0xE3, 0xF8, 0x07, 0x70, 0x45, 0x70, 0x07, 0xF0, 0x0F, 0xF9, 0x94, 0xF8, 0xDB, 0x30, 0x00, 0x2B, ++0xBF, 0xD0, 0x20, 0x46, 0x31, 0x46, 0x06, 0xF0, 0xA3, 0xFC, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x2C, 0x50, 0x18, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x16, 0x2C, 0x17, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0xF8, 0xB5, 0x18, 0x4D, 0x18, 0x4F, 0x2E, 0x68, ++0x04, 0x46, 0x36, 0xF8, 0x04, 0x1C, 0x00, 0x22, 0x40, 0x20, 0x07, 0xF0, 0x29, 0xF9, 0xD7, 0xF8, 0x78, 0x31, 0x29, 0x68, ++0x20, 0x46, 0x98, 0x47, 0x2A, 0x68, 0x00, 0x23, 0x84, 0xF8, 0xDB, 0x30, 0x93, 0x7A, 0x84, 0xF8, 0xDC, 0x30, 0xD2, 0x7A, ++0x84, 0xF8, 0xDD, 0x20, 0x0C, 0x3E, 0xD4, 0xF8, 0xB8, 0x20, 0x23, 0xB1, 0x52, 0x6A, 0xD3, 0x5C, 0x01, 0x33, 0x84, 0xF8, ++0xDB, 0x30, 0x2B, 0x7A, 0x00, 0x22, 0x6A, 0x72, 0x13, 0xB1, 0xD7, 0xF8, 0x84, 0x31, 0x98, 0x47, 0x00, 0x23, 0x30, 0x46, ++0x2B, 0x60, 0xBD, 0xE8, 0xF8, 0x40, 0x07, 0xF0, 0x17, 0xB9, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0xB5, 0x0E, 0x4D, 0x44, 0x7A, 0x0E, 0x4A, 0x0E, 0x49, 0x03, 0x46, 0x4F, 0xF4, 0x1A, 0x70, 0x00, 0xFB, 0x04, 0x50, ++0x01, 0x25, 0x55, 0x72, 0x00, 0x25, 0x95, 0x72, 0x9A, 0x88, 0x68, 0x30, 0x1B, 0xF0, 0x0C, 0xFC, 0x08, 0x4A, 0x09, 0x4B, ++0x4F, 0xF4, 0xA4, 0x60, 0x29, 0x46, 0x00, 0xFB, 0x04, 0x20, 0xD3, 0xF8, 0x94, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, ++0xFC, 0x41, 0x18, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x14, 0x2A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x7E, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x1B, 0x68, 0x7D, 0x4D, 0xB3, 0xF9, 0x00, 0x30, 0x6E, 0x68, 0x00, 0x2B, 0x83, 0xB0, ++0x04, 0x46, 0x44, 0xDB, 0x01, 0x3E, 0x6E, 0x60, 0x00, 0x2E, 0x4D, 0xD0, 0xDF, 0xF8, 0xE0, 0x91, 0x77, 0x4D, 0x78, 0x4E, ++0x78, 0x4F, 0xDF, 0xF8, 0x00, 0xA2, 0xDF, 0xF8, 0x00, 0x82, 0x03, 0xE0, 0x05, 0xF5, 0x1E, 0x75, 0xB5, 0x42, 0x2F, 0xD0, ++0x95, 0xF8, 0x25, 0x20, 0x4F, 0xF4, 0xA4, 0x61, 0x00, 0x2A, 0xF5, 0xD0, 0x95, 0xF8, 0x22, 0x30, 0x01, 0xFB, 0x03, 0x73, ++0x9C, 0x42, 0xEF, 0xD1, 0x95, 0xF8, 0x23, 0x30, 0x0D, 0x2B, 0x9B, 0xBF, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x93, ++0x00, 0x22, 0xD3, 0xF8, 0x58, 0x22, 0xDA, 0xF8, 0x10, 0x30, 0xA8, 0xEB, 0x03, 0x03, 0xD3, 0x42, 0xDE, 0xD5, 0x20, 0x46, ++0xF2, 0xF7, 0x96, 0xFF, 0x00, 0x28, 0xD9, 0xD0, 0x63, 0x49, 0x95, 0xF8, 0x23, 0x00, 0x2A, 0x46, 0xF4, 0xF7, 0xAE, 0xFB, ++0x00, 0x28, 0xD1, 0xD1, 0x95, 0xF8, 0x23, 0x10, 0x5F, 0x48, 0x08, 0xF0, 0x89, 0xFE, 0xCB, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0x2E, 0xB8, 0xD1, 0x5C, 0x49, 0x5C, 0x48, 0x4F, 0xF4, 0x3F, 0x72, 0x09, 0xF0, 0xF7, 0xF8, 0x6E, 0x68, ++0x01, 0x3E, 0x6E, 0x60, 0x00, 0x2E, 0xB1, 0xD1, 0xDF, 0xF8, 0x74, 0xB1, 0xFC, 0xF7, 0xCC, 0xFF, 0x94, 0xF8, 0x63, 0x30, ++0x9B, 0xF8, 0x00, 0x20, 0x03, 0xF1, 0x0A, 0x08, 0x00, 0x2A, 0x58, 0xD1, 0xDF, 0xF8, 0x2C, 0x91, 0x51, 0x4B, 0x1B, 0x78, ++0x53, 0xB3, 0x08, 0xEB, 0x88, 0x02, 0x4F, 0xF4, 0x1E, 0x73, 0xC8, 0xEB, 0x02, 0x12, 0x4E, 0x4F, 0x01, 0x92, 0x03, 0xFB, ++0x08, 0x9B, 0x4F, 0xF0, 0x00, 0x0A, 0xDB, 0xF8, 0x08, 0x32, 0x5F, 0xFA, 0x8A, 0xF6, 0x0B, 0xF5, 0x02, 0x78, 0x53, 0xB1, ++0x40, 0x46, 0x07, 0xF0, 0xBB, 0xFC, 0xD7, 0xF8, 0x24, 0x34, 0x31, 0x46, 0x98, 0x47, 0xDB, 0xF8, 0x08, 0x32, 0x00, 0x2B, ++0xF4, 0xD1, 0xDB, 0xF8, 0x30, 0x22, 0x00, 0x2A, 0x5B, 0xD1, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x04, 0x0F, 0x0B, 0xF1, ++0x08, 0x0B, 0xE2, 0xD1, 0x3B, 0x4B, 0x1A, 0x70, 0xAB, 0x7A, 0x03, 0xBB, 0xEB, 0x68, 0x63, 0xB1, 0x39, 0x4F, 0xDF, 0xF8, ++0xF8, 0x80, 0xD7, 0xF8, 0xD4, 0x61, 0x40, 0x46, 0x07, 0xF0, 0x9A, 0xFC, 0x0C, 0x30, 0xB0, 0x47, 0xEB, 0x68, 0x00, 0x2B, ++0xF5, 0xD1, 0x94, 0xF8, 0x63, 0x00, 0x05, 0x44, 0x29, 0x7D, 0x19, 0xB1, 0x30, 0x4B, 0xD3, 0xF8, 0x90, 0x31, 0x98, 0x47, ++0x94, 0xF8, 0xDB, 0x30, 0x01, 0x2B, 0x7F, 0xF4, 0x59, 0xAF, 0x20, 0x46, 0xFB, 0xF7, 0xBE, 0xFA, 0x54, 0xE7, 0x2A, 0x4F, ++0x28, 0x68, 0xD7, 0xF8, 0x8C, 0x31, 0x98, 0x47, 0xD8, 0xE7, 0x04, 0x23, 0x32, 0x46, 0x0C, 0x21, 0x4A, 0x20, 0x06, 0xF0, ++0xA5, 0xFF, 0x80, 0xF8, 0x00, 0x80, 0x46, 0x70, 0x86, 0x70, 0x06, 0xF0, 0xCF, 0xFF, 0x9B, 0xF8, 0x00, 0x30, 0xDF, 0xF8, ++0x60, 0x90, 0x00, 0x2B, 0x96, 0xD0, 0x4F, 0xF4, 0x1E, 0x7A, 0x0A, 0xFB, 0x08, 0x9A, 0x9A, 0xF8, 0x31, 0x30, 0x9B, 0x07, ++0x0B, 0xD5, 0x1A, 0x4F, 0x09, 0x22, 0x8A, 0xF8, 0x32, 0x20, 0xD7, 0xF8, 0x20, 0x33, 0x32, 0x46, 0x51, 0x46, 0x20, 0x46, ++0x98, 0x47, 0x8A, 0xF8, 0x32, 0x60, 0x00, 0x23, 0x8B, 0xF8, 0x00, 0x30, 0x7E, 0xE7, 0x01, 0x98, 0x46, 0x30, 0x50, 0x44, ++0x09, 0xEB, 0xC0, 0x00, 0x07, 0xF0, 0x4C, 0xFC, 0x0E, 0x4B, 0x31, 0x46, 0xD3, 0xF8, 0x24, 0x34, 0x98, 0x47, 0x0D, 0x48, ++0x08, 0xF0, 0xDA, 0xFD, 0xFE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x7E, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x51, 0xB1, 0x13, 0x00, 0xF8, 0x9F, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0x9F, 0x15, 0x00, 0x16, 0x2C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xDC, 0x9F, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, ++0xC0, 0xE1, 0xE4, 0x00, 0x10, 0x2A, 0x17, 0x00, 0xE4, 0x9C, 0x17, 0x00, 0x38, 0xB5, 0x0E, 0x4D, 0x0E, 0x4C, 0x18, 0x22, ++0x00, 0x21, 0x28, 0x46, 0xE4, 0xF7, 0x42, 0xFB, 0x05, 0xF1, 0x0C, 0x00, 0x07, 0xF0, 0xCE, 0xFB, 0x20, 0x46, 0x04, 0xF0, ++0xD9, 0xFF, 0x04, 0xF1, 0x26, 0x00, 0x04, 0xF0, 0xD5, 0xFF, 0x04, 0xF1, 0x4C, 0x00, 0x04, 0xF0, 0xD1, 0xFF, 0x04, 0xF1, ++0x72, 0x00, 0xBD, 0xE8, 0x38, 0x40, 0x04, 0xF0, 0xCB, 0xBF, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x64, 0x3E, 0x18, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x90, 0xF8, 0x63, 0x30, 0x3F, 0x4D, 0x40, 0x49, 0x40, 0x4F, 0xDF, 0xF8, 0x1C, 0x91, 0x04, 0x46, ++0x03, 0xEB, 0x83, 0x02, 0x3E, 0x48, 0x4F, 0xF4, 0x1A, 0x76, 0x03, 0xEB, 0x42, 0x02, 0x06, 0xFB, 0x03, 0x11, 0x05, 0xEB, ++0xC2, 0x02, 0x00, 0xEB, 0x83, 0x13, 0x04, 0xF1, 0x6C, 0x00, 0xF4, 0xF7, 0xFD, 0xF8, 0x94, 0xF8, 0x63, 0x30, 0x37, 0x49, ++0xDF, 0xF8, 0xF0, 0xC0, 0x36, 0x48, 0x06, 0x22, 0xA4, 0xF8, 0xCE, 0x20, 0x00, 0x25, 0x01, 0xEB, 0xC3, 0x02, 0x4F, 0xF0, ++0x05, 0x0E, 0xFF, 0x26, 0xA4, 0xF8, 0xD8, 0x60, 0x84, 0xF8, 0xD7, 0x50, 0xA4, 0xF8, 0xD0, 0x50, 0x84, 0xF8, 0xDA, 0x50, ++0x04, 0x26, 0x01, 0xF8, 0x33, 0xE0, 0x56, 0x70, 0x94, 0xF8, 0xD7, 0x10, 0x91, 0x70, 0x01, 0x21, 0x15, 0x71, 0x55, 0x71, ++0xD1, 0x70, 0x94, 0xF8, 0xD9, 0x10, 0x03, 0xEB, 0x83, 0x08, 0xC3, 0xEB, 0x83, 0x16, 0x00, 0xEB, 0x86, 0x00, 0x0C, 0xEB, ++0xC8, 0x06, 0x01, 0x44, 0x07, 0xEB, 0x88, 0x03, 0x31, 0x62, 0x02, 0xEB, 0x0E, 0x01, 0xC6, 0xE9, 0x03, 0x15, 0x4C, 0xF8, ++0x38, 0x90, 0xB2, 0x60, 0x73, 0x60, 0xB3, 0x61, 0x29, 0x46, 0xFC, 0x22, 0xC6, 0xF8, 0x14, 0x90, 0xE4, 0xF7, 0xCE, 0xFA, ++0x07, 0xEB, 0x88, 0x03, 0x47, 0xF8, 0x28, 0x90, 0x5D, 0x60, 0x1D, 0x61, 0x94, 0xF8, 0xC0, 0x34, 0x93, 0xB1, 0x94, 0xF8, ++0x63, 0x30, 0x15, 0x48, 0x15, 0x49, 0x03, 0xEB, 0xC3, 0x02, 0x03, 0xEB, 0x42, 0x02, 0x03, 0xEB, 0x83, 0x03, 0x01, 0xEB, ++0x42, 0x01, 0x00, 0xEB, 0x83, 0x02, 0xC2, 0xE9, 0x01, 0x51, 0x40, 0xF8, 0x23, 0x90, 0x15, 0x61, 0xD4, 0xF8, 0xB8, 0x30, ++0x0D, 0x49, 0x00, 0x22, 0x5A, 0x63, 0xDA, 0x64, 0x1A, 0x62, 0xD1, 0xF8, 0x88, 0x31, 0xC4, 0xE9, 0x30, 0x34, 0xBD, 0xE8, ++0xF8, 0x83, 0x00, 0xBF, 0x9C, 0x40, 0x18, 0x00, 0xFC, 0x41, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, 0x4C, 0x3F, 0x18, 0x00, ++0x2C, 0x50, 0x18, 0x00, 0x3C, 0x4C, 0x18, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xDE, 0xFA, 0xFE, 0xCA, 0x9C, 0x4B, 0x18, 0x00, 0x05, 0x4B, 0x5A, 0x68, 0x18, 0x60, 0x12, 0xB1, 0x01, 0x22, 0x9A, 0x72, ++0x70, 0x47, 0x03, 0x4B, 0xD3, 0xF8, 0x8C, 0x31, 0x18, 0x47, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x06, 0x4B, 0x5A, 0x68, 0x1A, 0xB9, 0x06, 0x4B, 0xD3, 0xF8, 0xD4, 0x31, 0x18, 0x47, 0xA0, 0xF1, 0x0C, 0x01, 0x03, 0xF1, ++0x0C, 0x00, 0x07, 0xF0, 0x05, 0xBB, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x40, 0x4B, 0x41, 0x4A, 0x1B, 0x68, 0x94, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x3F, 0x4E, 0x00, 0x2B, 0x41, 0xDB, 0x75, 0x7A, ++0x00, 0x2D, 0x4A, 0xD1, 0x3D, 0x4A, 0x35, 0x72, 0x17, 0x68, 0x7F, 0x01, 0x6C, 0xB1, 0xDF, 0xF8, 0xF8, 0x90, 0xDF, 0xF8, ++0xF8, 0x80, 0xAA, 0x46, 0x4F, 0xF0, 0x01, 0x0B, 0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x04, 0xD0, 0x24, 0x68, 0x00, 0x2C, ++0xF8, 0xD1, 0xBD, 0xE8, 0xF8, 0x8F, 0x94, 0xF8, 0xD6, 0x30, 0x00, 0x2B, 0xF6, 0xD0, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, ++0xF2, 0xD0, 0x94, 0xF8, 0xD5, 0x20, 0x94, 0xF8, 0xD4, 0x30, 0x9A, 0x42, 0xEC, 0xD1, 0xD9, 0xF8, 0x70, 0x31, 0x20, 0x46, ++0x98, 0x47, 0x20, 0xB1, 0x98, 0xF8, 0x00, 0x30, 0x01, 0x33, 0x88, 0xF8, 0x00, 0x30, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD0, ++0xA7, 0xF1, 0x32, 0x02, 0x40, 0xF6, 0xB6, 0x33, 0x9A, 0x42, 0x18, 0xD8, 0xD5, 0xB9, 0x20, 0x46, 0x02, 0xF0, 0x7A, 0xFE, ++0x83, 0x46, 0xF0, 0xB9, 0x88, 0xF8, 0x00, 0x50, 0xD0, 0xE7, 0x73, 0x68, 0x00, 0x2B, 0xBA, 0xD0, 0x1D, 0x49, 0x1E, 0x48, ++0x40, 0xF2, 0x2F, 0x42, 0x08, 0xF0, 0xFE, 0xFE, 0x75, 0x7A, 0x00, 0x2D, 0xB4, 0xD0, 0x01, 0x23, 0x33, 0x72, 0xBD, 0xE8, ++0xF8, 0x8F, 0x20, 0x46, 0x02, 0xF0, 0x62, 0xFE, 0x88, 0xF8, 0x00, 0xA0, 0x24, 0x68, 0x4F, 0xF0, 0x00, 0x0B, 0x01, 0x25, ++0x00, 0x2C, 0xB1, 0xD1, 0xB7, 0xE7, 0x94, 0xF8, 0x63, 0x30, 0x84, 0xF8, 0x88, 0x30, 0xFF, 0x23, 0x84, 0xF8, 0x89, 0x30, ++0x04, 0x21, 0x04, 0xF1, 0x6C, 0x00, 0xF4, 0xF7, 0xDB, 0xF8, 0x73, 0x68, 0x08, 0xB1, 0x01, 0x33, 0x73, 0x60, 0x01, 0x2B, ++0x02, 0xD0, 0x4F, 0xF0, 0x00, 0x0B, 0x9F, 0xE7, 0xFC, 0xF7, 0x58, 0xFD, 0x4F, 0xF0, 0x00, 0x0B, 0x9A, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x40, 0x80, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x20, 0xA0, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x10, 0x2A, 0x17, 0x00, 0xF8, 0xB5, 0x27, 0x4F, 0x7B, 0x68, 0x04, 0x46, ++0x0E, 0x46, 0x13, 0xB1, 0x3C, 0x44, 0x21, 0x75, 0xF8, 0xBD, 0x02, 0x29, 0x34, 0xD0, 0x03, 0x29, 0x21, 0xD0, 0x01, 0x29, ++0x14, 0xD0, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x32, 0xDB, 0x1F, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x04, 0x53, 0x3C, 0x44, 0x00, 0x22, 0x22, 0x75, 0x93, 0xF8, 0xC1, 0x04, 0x31, 0x46, 0xBD, 0xE8, 0xF8, 0x40, ++0x04, 0xF0, 0xC6, 0xBE, 0x18, 0x4B, 0x19, 0x4A, 0x16, 0x4D, 0x00, 0xEB, 0x80, 0x01, 0x03, 0xEB, 0x81, 0x03, 0x02, 0xEB, ++0x81, 0x02, 0x5A, 0x60, 0xE6, 0xE7, 0x12, 0x4D, 0x14, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x52, 0x00, 0xEB, ++0xC0, 0x03, 0x00, 0xEB, 0x43, 0x03, 0x01, 0xEB, 0x43, 0x01, 0x92, 0xF8, 0xC1, 0x04, 0x04, 0xF0, 0x47, 0xFE, 0xD5, 0xE7, ++0x0A, 0x4A, 0x09, 0x4D, 0x00, 0xEB, 0x80, 0x01, 0x02, 0xEB, 0x81, 0x02, 0x53, 0x60, 0xCD, 0xE7, 0x09, 0x49, 0x0A, 0x48, ++0x04, 0x4D, 0x40, 0xF2, 0xC6, 0x42, 0x08, 0xF0, 0x71, 0xFE, 0xC5, 0xE7, 0xD8, 0x9C, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x4C, 0x40, 0x18, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x04, 0x23, 0x00, 0x22, 0x0C, 0x21, 0x44, 0x20, 0x06, 0xF0, 0x76, 0xFD, ++0x23, 0x7E, 0x03, 0x70, 0x04, 0x2B, 0x09, 0xD0, 0x00, 0x23, 0x00, 0x22, 0x43, 0x70, 0xC2, 0x70, 0xA3, 0x7E, 0x83, 0x70, ++0xBD, 0xE8, 0x10, 0x40, 0x06, 0xF0, 0x98, 0xBD, 0xE3, 0x89, 0x00, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0xF1, 0xE7, 0x00, 0xBF, ++0x38, 0xB5, 0x05, 0xF0, 0xE1, 0xFA, 0x0C, 0x23, 0x05, 0x46, 0x19, 0x46, 0x00, 0x22, 0x4F, 0x20, 0x06, 0xF0, 0x58, 0xFD, ++0x2B, 0x88, 0x03, 0x80, 0x04, 0x46, 0x28, 0x46, 0x05, 0xF0, 0xDE, 0xFA, 0x10, 0x4A, 0x11, 0x4D, 0x11, 0x49, 0xA2, 0xFB, ++0x00, 0x03, 0x9B, 0x09, 0x63, 0x60, 0x2B, 0x68, 0xA2, 0xFB, 0x03, 0x23, 0x9B, 0x09, 0x00, 0x22, 0xA3, 0x60, 0xA2, 0x70, ++0x0A, 0x23, 0x0A, 0x68, 0x52, 0xB2, 0x01, 0x3B, 0x3A, 0xB9, 0x13, 0xF0, 0xFF, 0x03, 0xF8, 0xD1, 0x20, 0x46, 0xBD, 0xE8, ++0x38, 0x40, 0x06, 0xF0, 0x67, 0xBD, 0xA2, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0x38, 0x40, 0x06, 0xF0, 0x61, 0xBD, 0x00, 0xBF, ++0xD3, 0x4D, 0x62, 0x10, 0x20, 0x02, 0x32, 0x40, 0x0C, 0xB2, 0x33, 0x40, 0x10, 0xB5, 0xC1, 0x89, 0x04, 0x46, 0x02, 0x23, ++0x00, 0x22, 0x48, 0x20, 0x06, 0xF0, 0x22, 0xFD, 0x22, 0x7E, 0x42, 0x70, 0xA1, 0x7E, 0x05, 0x4A, 0x01, 0x70, 0x13, 0x68, ++0x23, 0xF0, 0x04, 0x03, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0x60, 0x06, 0xF0, 0x45, 0xBD, 0x00, 0xBF, 0x94, 0x40, 0x04, 0x40, ++0xF0, 0xB5, 0x04, 0x68, 0x0E, 0x68, 0xA5, 0x1B, 0x32, 0xD4, 0x8E, 0x46, 0xAB, 0x42, 0x0C, 0xD2, 0xDE, 0xE9, 0x00, 0x76, ++0xDC, 0x19, 0xF6, 0x1B, 0xED, 0x1A, 0xAB, 0x42, 0x06, 0xEB, 0x04, 0x07, 0xA4, 0x46, 0x1C, 0x44, 0xF8, 0xD3, 0xCE, 0xE9, ++0x00, 0xC7, 0xB5, 0xEB, 0x53, 0x0F, 0x05, 0xD9, 0xDE, 0xE9, 0x00, 0x54, 0x1D, 0x44, 0x23, 0x44, 0xCE, 0xE9, 0x00, 0x53, ++0x43, 0x68, 0x4C, 0x68, 0x1D, 0x1B, 0x00, 0x2D, 0x09, 0xDB, 0xB2, 0xB1, 0x05, 0x68, 0x09, 0x68, 0x53, 0x60, 0x68, 0x1A, ++0x00, 0x28, 0x17, 0xDA, 0x58, 0x1B, 0x15, 0x60, 0xF0, 0xBD, 0xAA, 0xB1, 0x05, 0x68, 0x09, 0x68, 0x54, 0x60, 0x6B, 0x1A, ++0x00, 0x2B, 0xA8, 0xBF, 0x60, 0x1A, 0x18, 0xDB, 0x11, 0x60, 0xF0, 0xBD, 0x35, 0x1B, 0x86, 0x46, 0xCA, 0xE7, 0x00, 0x68, ++0x0A, 0x68, 0x81, 0x1A, 0x00, 0x29, 0x0C, 0xDA, 0x18, 0x1A, 0xF0, 0xBD, 0x58, 0x1A, 0xF1, 0xE7, 0x00, 0x68, 0x0B, 0x68, ++0xC1, 0x1A, 0x00, 0x29, 0xA8, 0xBF, 0xE0, 0x1A, 0xE0, 0xDA, 0x20, 0x1A, 0xF0, 0xBD, 0x98, 0x1A, 0xF0, 0xBD, 0x60, 0x1B, ++0xD9, 0xE7, 0x00, 0xBF, 0x70, 0xB5, 0x19, 0x4E, 0x90, 0xF8, 0xC1, 0x44, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0x05, 0x46, ++0x93, 0xF8, 0x20, 0x20, 0x0A, 0xB9, 0x1B, 0x7C, 0xFB, 0xB9, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x64, 0x94, 0xF8, 0x50, 0x20, ++0x12, 0xB9, 0x94, 0xF8, 0x40, 0x30, 0x7B, 0xB9, 0x0F, 0x4B, 0x9B, 0x68, 0x5B, 0xB1, 0x95, 0xF8, 0x63, 0x10, 0xFF, 0x20, ++0x93, 0xF8, 0x4E, 0x20, 0x8A, 0x42, 0x08, 0xBF, 0x83, 0xF8, 0x4E, 0x00, 0x1B, 0x68, 0x00, 0x2B, 0xF6, 0xD1, 0x70, 0xBD, ++0x08, 0x4B, 0x01, 0x21, 0xD3, 0xF8, 0x08, 0x32, 0x28, 0x46, 0x98, 0x47, 0xE8, 0xE7, 0x05, 0x4B, 0x11, 0x46, 0xD3, 0xF8, ++0x08, 0x32, 0x98, 0x47, 0xD9, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x48, 0x4B, 0x93, 0xF8, 0x5A, 0x30, 0x9B, 0xB0, 0x01, 0x2B, 0x08, 0x90, 0x40, 0xF2, 0x93, 0x81, ++0xDF, 0xF8, 0x20, 0x91, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB7, 0x81, 0x08, 0x9C, ++0x40, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x94, 0x30, 0x98, 0x47, 0x23, 0x6C, 0x94, 0xF8, 0x63, 0x20, 0xDA, 0x76, 0x94, 0xF8, ++0x62, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xB9, 0x81, 0x02, 0x2A, 0x08, 0xBF, 0x08, 0x9A, 0x39, 0x48, 0x0A, 0xBF, 0xB2, 0xF8, ++0xD2, 0x20, 0x4F, 0xF4, 0xC8, 0x32, 0x92, 0x02, 0x0A, 0x92, 0x1A, 0x7E, 0x02, 0x2A, 0x02, 0xF1, 0x01, 0x03, 0x00, 0xF0, ++0xB9, 0x81, 0xC3, 0xEB, 0xC3, 0x04, 0x00, 0xEB, 0x84, 0x04, 0xD9, 0x00, 0x24, 0x7E, 0xFF, 0x2C, 0x0D, 0xD1, 0x01, 0x2A, ++0x02, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, 0xC3, 0xEB, 0xC3, 0x02, 0x00, 0xEB, 0x82, 0x02, 0xD9, 0x00, 0x12, 0x7E, ++0xFF, 0x2A, 0x00, 0xF0, 0x98, 0x82, 0x28, 0x4A, 0xCB, 0x1A, 0x00, 0xEB, 0x83, 0x03, 0x96, 0x68, 0x5B, 0x7E, 0x06, 0x93, ++0x00, 0x2E, 0x00, 0xF0, 0x4A, 0x81, 0x0A, 0x9B, 0x4F, 0xF0, 0x00, 0x0B, 0x5B, 0x00, 0x0B, 0x93, 0x5F, 0x46, 0x03, 0xE0, ++0x36, 0x68, 0x00, 0x2E, 0x00, 0xF0, 0x9A, 0x80, 0x33, 0x6C, 0x00, 0x2B, 0xF8, 0xD0, 0x08, 0x9A, 0x12, 0x6C, 0x93, 0x42, ++0xF4, 0xD0, 0x96, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x93, 0x81, 0x02, 0x2B, 0x0A, 0xBF, 0xB6, 0xF8, 0xD2, 0x30, ++0x4F, 0xF4, 0xC8, 0x3B, 0x4F, 0xEA, 0x83, 0x2B, 0x0B, 0x9B, 0x5B, 0x45, 0x04, 0xD8, 0x0A, 0x9B, 0xBB, 0xFB, 0xF3, 0xF2, ++0xBB, 0xFB, 0xF2, 0xFB, 0x06, 0x9B, 0x4F, 0xEA, 0x5B, 0x00, 0xB0, 0xFB, 0xF3, 0xF5, 0x09, 0x95, 0xE5, 0xF7, 0x7C, 0xF8, ++0x43, 0xF2, 0xB0, 0x64, 0x20, 0x44, 0xA8, 0x42, 0x00, 0xF2, 0x18, 0x81, 0x00, 0x2F, 0x00, 0xF0, 0x1C, 0x81, 0x06, 0x9B, ++0x09, 0x9A, 0x03, 0xFB, 0x02, 0xF3, 0x07, 0x93, 0x10, 0xAC, 0x00, 0x25, 0x10, 0xE0, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x01, 0x35, 0xAF, 0x42, ++0x04, 0xF1, 0x14, 0x04, 0x00, 0xF0, 0x03, 0x81, 0x22, 0x68, 0x5A, 0x45, 0xF6, 0xD1, 0x72, 0x6A, 0x0C, 0x92, 0xD4, 0xE9, ++0x02, 0x01, 0x0D, 0xF1, 0x38, 0x0C, 0x0D, 0xF1, 0x30, 0x0A, 0x02, 0xF5, 0x1C, 0x5E, 0x8C, 0xE8, 0x03, 0x00, 0x0E, 0xF1, ++0x10, 0x0E, 0x52, 0x46, 0x61, 0x46, 0x50, 0x46, 0x5B, 0x46, 0xCD, 0xF8, 0x34, 0xE0, 0xFF, 0xF7, 0xB7, 0xFE, 0xD9, 0xF8, ++0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x80, 0x46, 0xC0, 0xF2, 0x2D, 0x81, 0x06, 0x9B, 0x5A, 0x1E, 0x07, 0x9B, ++0xB3, 0xFB, 0xF2, 0xF2, 0x05, 0x92, 0xE5, 0xF7, 0x31, 0xF8, 0x05, 0x9A, 0x61, 0x68, 0xA2, 0xF5, 0x7A, 0x62, 0x12, 0x1A, ++0x8A, 0x42, 0x38, 0xBF, 0x0A, 0x46, 0x42, 0x45, 0xC6, 0xD9, 0x05, 0x92, 0x05, 0xEB, 0x85, 0x05, 0xE5, 0xF7, 0x22, 0xF8, ++0x1A, 0xAB, 0x03, 0xEB, 0x85, 0x05, 0x96, 0xF8, 0x63, 0x10, 0x05, 0x9A, 0x55, 0xF8, 0x18, 0x3C, 0x36, 0x68, 0x01, 0x24, ++0x8C, 0x40, 0x02, 0x44, 0x9A, 0xE8, 0x03, 0x00, 0x23, 0x43, 0x02, 0xF5, 0x7A, 0x62, 0xA5, 0xF1, 0x20, 0x04, 0x84, 0xE8, ++0x03, 0x00, 0x45, 0xF8, 0x24, 0x2C, 0x45, 0xF8, 0x18, 0x3C, 0x00, 0x2E, 0x7F, 0xF4, 0x66, 0xAF, 0x00, 0x2F, 0x00, 0xF0, ++0xA2, 0x80, 0xDF, 0xF8, 0x88, 0xA3, 0xDD, 0xF8, 0x20, 0xB0, 0x05, 0x96, 0x09, 0x96, 0x0B, 0x96, 0x07, 0x96, 0x12, 0xAC, ++0x06, 0x97, 0x54, 0xF8, 0x08, 0x7C, 0x0A, 0x9B, 0xB7, 0xFB, 0xF3, 0xF2, 0x03, 0xFB, 0x12, 0x72, 0x00, 0x2A, 0x00, 0xF0, ++0x3A, 0x81, 0xE4, 0xF7, 0xED, 0xFF, 0x54, 0xE9, 0x01, 0x63, 0xA3, 0xF5, 0xBB, 0x53, 0x10, 0x3B, 0x1D, 0x1A, 0xE4, 0xF7, ++0xE5, 0xFF, 0xDA, 0xF8, 0x10, 0x30, 0x54, 0xF8, 0x08, 0x1C, 0xEB, 0x1A, 0x06, 0xF5, 0x7A, 0x66, 0x00, 0x2B, 0x06, 0xEB, ++0x00, 0x07, 0xC0, 0xF2, 0xEA, 0x80, 0xDA, 0xF8, 0x10, 0x20, 0x6B, 0x1A, 0x9A, 0x1A, 0x00, 0x2A, 0x80, 0xF2, 0xDB, 0x80, ++0xCD, 0xE9, 0x01, 0x75, 0xBE, 0x4B, 0x00, 0x91, 0xD3, 0xF8, 0x04, 0x32, 0xDF, 0xF8, 0x1C, 0x83, 0x1E, 0x46, 0x00, 0x22, ++0xFF, 0x23, 0x01, 0x21, 0x58, 0x46, 0xB0, 0x47, 0xEB, 0x19, 0xB9, 0x4E, 0x25, 0x60, 0x63, 0x60, 0x07, 0x46, 0x00, 0x25, ++0xA3, 0x68, 0xEB, 0x40, 0xDB, 0x07, 0x22, 0xD5, 0x72, 0x6A, 0x54, 0xF8, 0x08, 0x3C, 0x0E, 0x92, 0x02, 0xF5, 0x1C, 0x5C, ++0x0C, 0xF1, 0x10, 0x0C, 0x00, 0x22, 0x0E, 0xA9, 0x20, 0x46, 0xCD, 0xF8, 0x3C, 0xC0, 0xFF, 0xF7, 0x21, 0xFE, 0xD9, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xC3, 0x80, 0x0E, 0x9A, 0x63, 0x68, 0x9B, 0xF8, 0x63, 0x10, ++0x86, 0xF8, 0x4E, 0x10, 0x9B, 0x1A, 0x00, 0x22, 0x73, 0x65, 0x86, 0xF8, 0x4F, 0x70, 0xA6, 0xF8, 0x58, 0x20, 0x01, 0x35, ++0x04, 0x2D, 0x06, 0xF5, 0xA4, 0x66, 0xD3, 0xD1, 0x05, 0x9B, 0x06, 0x9A, 0x01, 0x33, 0x9A, 0x42, 0x05, 0x93, 0x04, 0xF1, ++0x14, 0x04, 0x90, 0xD1, 0x07, 0x9B, 0x33, 0xB3, 0x0B, 0x9B, 0x0A, 0x99, 0x03, 0xF5, 0x9C, 0x50, 0x09, 0x9B, 0x08, 0x30, ++0x83, 0x42, 0xA8, 0xBF, 0x03, 0x46, 0x18, 0x46, 0x01, 0xEB, 0xD1, 0x73, 0xB0, 0xEB, 0x63, 0x0F, 0x4F, 0xEA, 0x63, 0x02, ++0x00, 0xF3, 0x18, 0x81, 0x52, 0x42, 0x82, 0x42, 0xC4, 0xBF, 0x0A, 0x9B, 0xC0, 0x18, 0x8F, 0x4B, 0xD3, 0xF8, 0x6C, 0x31, ++0x98, 0x47, 0x08, 0x9C, 0x8E, 0x4A, 0x94, 0xF8, 0x4D, 0x30, 0x20, 0x65, 0x43, 0xF0, 0x20, 0x03, 0x01, 0x21, 0x84, 0xF8, ++0x4D, 0x30, 0x82, 0xF8, 0x31, 0x10, 0x1B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xE4, 0xF7, 0x5C, 0xFF, 0x03, 0x19, 0x09, 0x93, ++0x00, 0x2F, 0x7F, 0xF4, 0xE4, 0xAE, 0xD9, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x7B, 0xDB, 0x1A, 0xAB, ++0x07, 0xEB, 0x87, 0x02, 0x70, 0x6A, 0x03, 0xEB, 0x82, 0x02, 0x09, 0x9B, 0x42, 0xF8, 0x28, 0xBC, 0x00, 0xF5, 0x1C, 0x51, ++0x42, 0xE9, 0x09, 0x30, 0x10, 0x31, 0x42, 0xF8, 0x1C, 0x1C, 0xBC, 0x00, 0x96, 0xF8, 0x63, 0x20, 0x3C, 0x44, 0x1A, 0xAB, ++0x03, 0xEB, 0x84, 0x04, 0x01, 0x23, 0x93, 0x40, 0x01, 0x37, 0x44, 0xF8, 0x18, 0x3C, 0x8F, 0xE6, 0x03, 0x6C, 0xDB, 0x7E, ++0xFF, 0x2B, 0x3F, 0xF4, 0x44, 0xAE, 0x90, 0xF8, 0x63, 0x20, 0x9A, 0x42, 0x3F, 0xF4, 0x3F, 0xAE, 0x6E, 0x49, 0x6F, 0x48, ++0x40, 0xF2, 0xA7, 0x22, 0x08, 0xF0, 0x8E, 0xFB, 0x37, 0xE6, 0x08, 0x9A, 0x6C, 0x49, 0x92, 0xF8, 0x6C, 0x20, 0x4F, 0xF4, ++0x1E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x6A, 0x48, 0x92, 0x68, 0x0A, 0x92, 0x1A, 0x7E, 0x02, 0x2A, 0x02, 0xF1, 0x01, 0x03, ++0x7F, 0xF4, 0x47, 0xAE, 0x03, 0x7E, 0xFF, 0x2B, 0x40, 0xF0, 0xEE, 0x80, 0x01, 0x23, 0x4D, 0xE6, 0x06, 0x9B, 0x01, 0x2B, ++0x3F, 0xF6, 0xCF, 0xAE, 0x5D, 0x49, 0x61, 0x48, 0x40, 0xF2, 0xD3, 0x22, 0x08, 0xF0, 0x6C, 0xFB, 0xC7, 0xE6, 0x5C, 0x4A, ++0x96, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0xD3, 0xF8, 0x08, 0xB0, 0x6A, 0xE6, 0xDA, 0xF8, ++0x10, 0x20, 0x1D, 0x46, 0x5B, 0x1A, 0x9A, 0x1A, 0x00, 0x2A, 0xF8, 0xDA, 0x1C, 0xE7, 0xDA, 0xF8, 0x10, 0x30, 0x0D, 0x44, ++0xEB, 0x1A, 0x00, 0x2B, 0xBF, 0xF6, 0x16, 0xAF, 0xDA, 0xF8, 0x10, 0x30, 0x0D, 0x44, 0xEB, 0x1A, 0x00, 0x2B, 0xF2, 0xDB, ++0x0E, 0xE7, 0x96, 0xF8, 0x4E, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0x38, 0xAF, 0x47, 0x49, 0x4F, 0xF4, 0x58, 0x72, 0x40, 0x46, ++0x08, 0xF0, 0x40, 0xFB, 0x30, 0xE7, 0x02, 0x2F, 0x00, 0xF0, 0x98, 0x80, 0x1A, 0xAB, 0x07, 0xEB, 0x87, 0x02, 0x70, 0x6A, ++0x03, 0xEB, 0x82, 0x02, 0x09, 0x9B, 0x42, 0xF8, 0x28, 0xBC, 0x00, 0xF5, 0x1C, 0x51, 0x42, 0xE9, 0x09, 0x30, 0x10, 0x31, ++0x42, 0xF8, 0x1C, 0x1C, 0xBC, 0x00, 0x96, 0xF8, 0x63, 0x20, 0x1F, 0x2A, 0x7F, 0xF6, 0x7E, 0xAF, 0x37, 0x49, 0x3C, 0x48, ++0x40, 0xF2, 0xED, 0x22, 0x08, 0xF0, 0x20, 0xFB, 0x74, 0xE7, 0x3A, 0x4B, 0xDA, 0xF8, 0x10, 0x00, 0x19, 0x68, 0x0A, 0x9B, ++0x00, 0xEB, 0x41, 0x10, 0x9F, 0x42, 0x28, 0xBF, 0x1F, 0x46, 0x00, 0xF5, 0x1C, 0x55, 0x10, 0x35, 0x3B, 0x46, 0x0E, 0xA9, ++0x0E, 0x90, 0x20, 0x46, 0x0F, 0x95, 0xFF, 0xF7, 0x17, 0xFD, 0x0E, 0x9E, 0x23, 0x68, 0x54, 0xF8, 0x04, 0x5C, 0x9A, 0x1B, ++0x00, 0x2A, 0x1D, 0x44, 0x62, 0x68, 0xA5, 0xF5, 0xFA, 0x65, 0xB4, 0xBF, 0xB6, 0x1A, 0x3E, 0x1A, 0xAD, 0x1A, 0xE4, 0xF7, ++0x91, 0xFE, 0x00, 0xF5, 0x7A, 0x60, 0xA8, 0x42, 0x34, 0xDC, 0x54, 0xE9, 0x02, 0x78, 0xE4, 0xF7, 0x89, 0xFE, 0xA7, 0xF5, ++0x5A, 0x53, 0x30, 0x3B, 0xA3, 0xEB, 0x08, 0x03, 0x07, 0x9A, 0xAD, 0x1B, 0x1B, 0x1A, 0x2B, 0x44, 0xDA, 0xB1, 0x09, 0x9A, ++0xAA, 0x42, 0x1F, 0xDB, 0x0B, 0x9A, 0x9A, 0x42, 0x0A, 0xDD, 0x0A, 0x9A, 0x13, 0x44, 0x15, 0x44, 0x09, 0x9A, 0xAA, 0x42, ++0xFF, 0xF6, 0x83, 0xAE, 0x0B, 0x9A, 0x9A, 0x42, 0x3F, 0xF7, 0x7F, 0xAE, 0x0B, 0x9A, 0xAA, 0x42, 0xB8, 0xBF, 0x2A, 0x46, ++0x0B, 0x92, 0x09, 0x9A, 0x9A, 0x42, 0xA8, 0xBF, 0x1A, 0x46, 0x09, 0x92, 0x73, 0xE6, 0x09, 0x93, 0x01, 0x23, 0x0B, 0x95, ++0x07, 0x93, 0x6E, 0xE6, 0x40, 0x1A, 0xEA, 0xE6, 0x0A, 0x9A, 0xAD, 0x1A, 0x9B, 0x1A, 0xE1, 0xE7, 0xE4, 0xF7, 0x56, 0xFE, ++0x00, 0xF5, 0x7A, 0x65, 0xC5, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x48, 0xA0, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0xD0, 0xA0, 0x15, 0x00, ++0x00, 0xA1, 0x15, 0x00, 0x40, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x10, 0xA1, 0x15, 0x00, 0x40, 0xF2, 0xE7, 0x22, ++0x14, 0x49, 0x15, 0x48, 0x08, 0xF0, 0x9E, 0xFA, 0xD9, 0xF8, 0x00, 0x20, 0x09, 0x9B, 0xB2, 0xF9, 0x00, 0x20, 0xCD, 0xF8, ++0x68, 0xB0, 0x1B, 0x93, 0x73, 0x6A, 0x1C, 0x93, 0x03, 0xF5, 0x1C, 0x53, 0x10, 0x33, 0x00, 0x2A, 0x1D, 0x93, 0x4F, 0xF0, ++0x08, 0x04, 0xFF, 0xF6, 0x60, 0xAF, 0xDF, 0xE6, 0x00, 0x23, 0x19, 0x46, 0x67, 0xE5, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0xDA, 0x04, 0x49, 0x05, 0x48, 0x40, 0xF2, 0xAE, 0x22, 0x08, 0xF0, 0x7B, 0xFA, 0x00, 0x23, ++0x5B, 0x7E, 0xFF, 0xDE, 0x70, 0x79, 0x15, 0x00, 0xE4, 0xA0, 0x15, 0x00, 0xC4, 0xA0, 0x15, 0x00, 0x0A, 0x4B, 0x03, 0xF1, ++0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x02, 0xD0, 0xDA, 0x7E, 0xFF, 0x2A, 0x04, 0xD1, 0x1C, 0x33, 0x8B, 0x42, 0xF6, 0xD1, ++0x00, 0x20, 0x70, 0x47, 0x04, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x02, 0x32, 0x02, 0x60, 0x01, 0x20, 0x70, 0x47, ++0x90, 0x9D, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x0E, 0x46, 0x85, 0xB0, 0x14, 0x46, 0x05, 0x46, ++0x00, 0x28, 0x54, 0xD0, 0x07, 0x46, 0x00, 0x2C, 0x3A, 0xD0, 0xA3, 0x7A, 0xFF, 0x2B, 0x37, 0xD0, 0x3D, 0x4A, 0x23, 0x7A, ++0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0x5E, 0xD0, 0x02, 0x2A, 0x52, 0xD0, ++0x4F, 0xF4, 0x48, 0x4A, 0x4F, 0xF4, 0xC8, 0x39, 0x60, 0x68, 0xDF, 0xF8, 0xE0, 0x80, 0x00, 0xF5, 0x1C, 0x5B, 0xE4, 0xF7, ++0xC9, 0xFD, 0x0B, 0xF1, 0x10, 0x0B, 0x03, 0x46, 0xE1, 0x7A, 0xD8, 0xF8, 0xFC, 0x21, 0x28, 0x46, 0x9B, 0x44, 0x90, 0x47, ++0x83, 0x1B, 0x13, 0xEB, 0x0A, 0x0F, 0x05, 0xD5, 0xAA, 0xEB, 0x06, 0x03, 0x48, 0x44, 0xC3, 0x42, 0xFC, 0xD4, 0x83, 0x1B, ++0x00, 0x2B, 0x0B, 0xF5, 0x0C, 0x53, 0xB8, 0xBF, 0x00, 0xF1, 0xFF, 0x36, 0x28, 0x33, 0x9B, 0x1B, 0x00, 0x2B, 0x31, 0xDB, ++0x0B, 0xF5, 0x7A, 0x60, 0x80, 0x1B, 0x06, 0xE0, 0xE4, 0xF7, 0xA6, 0xFD, 0xDF, 0xF8, 0x8C, 0x80, 0x00, 0xF5, 0x5A, 0x50, ++0x30, 0x30, 0x00, 0x22, 0x01, 0x23, 0xCD, 0xE9, 0x01, 0x06, 0xD8, 0xF8, 0x04, 0x42, 0x00, 0x92, 0x38, 0x46, 0x19, 0x46, ++0xA0, 0x47, 0xFF, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x17, 0x4B, 0x03, 0xF1, 0x54, 0x01, ++0x1A, 0x7E, 0xFF, 0x2A, 0x02, 0xD0, 0xDF, 0x7E, 0xFF, 0x2F, 0x1C, 0xD1, 0x1C, 0x33, 0x99, 0x42, 0xF6, 0xD1, 0x00, 0x20, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0xF8, 0xD2, 0x30, 0x4F, 0xEA, 0x83, 0x29, 0x4F, 0xEA, 0x43, 0x2A, 0xA9, 0xE7, ++0x41, 0xF2, 0x88, 0x30, 0xD5, 0xE7, 0x93, 0xF8, 0x6C, 0x30, 0x0A, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, ++0xD3, 0xF8, 0x08, 0x90, 0x4F, 0xEA, 0x59, 0x0A, 0x9A, 0xE7, 0x03, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x37, ++0x7F, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0xB5, 0x0C, 0x46, 0x02, 0x7A, 0x17, 0x49, 0x23, 0x7A, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x02, 0x12, 0x05, 0xFB, ++0x03, 0x13, 0x12, 0x6C, 0x1B, 0x6C, 0x9A, 0x42, 0x0D, 0xD0, 0x45, 0x68, 0xE4, 0xF7, 0x4A, 0xFD, 0x64, 0x68, 0x06, 0x46, ++0xE4, 0xF7, 0x46, 0xFD, 0x2A, 0x1B, 0x06, 0xD4, 0x63, 0x1B, 0x00, 0x2B, 0x0C, 0xDB, 0xA5, 0x42, 0x08, 0xD0, 0x00, 0x20, ++0x70, 0xBD, 0xA4, 0xF5, 0x5A, 0x53, 0x30, 0x3B, 0x5B, 0x1B, 0x9E, 0x1B, 0x00, 0x2E, 0xF1, 0xDA, 0x01, 0x20, 0x70, 0xBD, ++0xA2, 0xF5, 0x5A, 0x53, 0x30, 0x3B, 0x1B, 0x1A, 0x00, 0x2B, 0xF7, 0xDB, 0xA5, 0x42, 0xEC, 0xD1, 0xF4, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x83, 0xB0, 0x0D, 0x46, 0x00, 0xF1, 0x44, 0x08, 0x91, 0x46, ++0x22, 0xB9, 0x90, 0xF8, 0x4D, 0x30, 0xDB, 0x07, 0x00, 0xF1, 0xA3, 0x80, 0xDF, 0xF8, 0x64, 0xA1, 0xD7, 0xF8, 0x40, 0xB0, ++0xDA, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x79, 0xD1, 0xDA, 0xF8, 0x50, 0x30, 0x0B, 0xB1, 0x9B, 0x45, 0x2E, 0xD1, 0xBD, 0x64, ++0xE4, 0xF7, 0x0A, 0xFD, 0x05, 0xF5, 0x5A, 0x53, 0xDA, 0xF8, 0x10, 0x40, 0x2F, 0x33, 0x1E, 0x18, 0x00, 0x2C, 0x00, 0xF0, ++0x88, 0x80, 0xDF, 0xF8, 0x38, 0xA1, 0x0B, 0xE0, 0xDA, 0xF8, 0xA0, 0x30, 0x98, 0x47, 0xD3, 0x46, 0x40, 0xBB, 0x63, 0x68, ++0xEB, 0x1A, 0x00, 0x2B, 0x08, 0xDB, 0x24, 0x68, 0x00, 0x2C, 0x78, 0xD0, 0x63, 0x68, 0xF3, 0x1A, 0x00, 0x2B, 0x21, 0x46, ++0x40, 0x46, 0xED, 0xDA, 0x3F, 0x48, 0x42, 0x46, 0x21, 0x46, 0x06, 0xF0, 0xD9, 0xFD, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, ++0x01, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x54, 0x60, 0xE4, 0xF7, 0xDA, 0xFC, ++0xAE, 0x1B, 0xA6, 0xF5, 0x7A, 0x66, 0x30, 0x1A, 0xC4, 0x0F, 0x00, 0x2C, 0xC5, 0xD0, 0xDF, 0xF8, 0xDC, 0xB0, 0x00, 0x24, ++0x97, 0xF8, 0xC0, 0x34, 0x4B, 0xB1, 0x31, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, ++0x70, 0x30, 0x01, 0x2B, 0x1D, 0xD0, 0x97, 0xF8, 0x62, 0x30, 0xDB, 0xF8, 0x2C, 0x40, 0x7B, 0xB1, 0x02, 0x2B, 0x0A, 0xBF, ++0xB7, 0xF8, 0xD2, 0x10, 0x4F, 0xF4, 0xC8, 0x31, 0x89, 0x02, 0x09, 0xF1, 0x01, 0x02, 0x29, 0x44, 0x38, 0x46, 0x23, 0x46, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x22, 0x4A, 0x97, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, ++0x03, 0x23, 0x99, 0x68, 0xED, 0xE7, 0xDB, 0xF8, 0x90, 0x30, 0x22, 0x46, 0x29, 0x46, 0x38, 0x46, 0x98, 0x47, 0x97, 0xF8, ++0x62, 0x30, 0xDB, 0xF8, 0x2C, 0x40, 0x00, 0x2B, 0xDA, 0xD1, 0xE9, 0xE7, 0xDA, 0xF8, 0x24, 0x20, 0x01, 0x92, 0x56, 0x68, ++0xE4, 0xF7, 0x92, 0xFC, 0x01, 0x9A, 0x93, 0x68, 0x06, 0xF5, 0x7A, 0x66, 0x9B, 0x45, 0x06, 0xEB, 0x00, 0x04, 0x0A, 0xD0, ++0xE4, 0xF7, 0x88, 0xFC, 0x01, 0x9A, 0xD3, 0x68, 0x04, 0xF5, 0x7A, 0x64, 0x04, 0x44, 0x13, 0xB1, 0x04, 0xF5, 0x1C, 0x54, ++0x10, 0x34, 0x2C, 0x1B, 0xE4, 0x0F, 0x00, 0x2C, 0x3F, 0xF4, 0x6D, 0xAF, 0xA5, 0xE7, 0x00, 0x24, 0x8A, 0xE7, 0x05, 0x48, ++0x41, 0x46, 0x06, 0xF0, 0xD9, 0xFC, 0x97, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x01, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x51, 0xE7, ++0x40, 0x9D, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x81, 0x46, 0x1A, 0x48, 0x88, 0x46, 0x17, 0x46, 0x06, 0xF0, 0xB4, 0xFC, 0x18, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x0C, 0xDB, 0x16, 0x4D, 0x28, 0x46, 0x21, 0x46, 0x50, 0xF8, 0x20, 0x6F, ++0xE7, 0x60, 0xC4, 0xE9, 0x01, 0x98, 0x06, 0xF0, 0x5F, 0xFC, 0x4E, 0xB1, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x28, 0xF0, 0xD1, ++0x0F, 0x49, 0x10, 0x48, 0xD6, 0x22, 0x08, 0xF0, 0xA9, 0xF8, 0xEA, 0xE7, 0x0E, 0x4B, 0x61, 0x68, 0x1B, 0x69, 0xAC, 0x64, ++0xCB, 0x1A, 0x14, 0x2B, 0x07, 0xD4, 0x0C, 0x4B, 0x05, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x47, ++0x18, 0x47, 0x6B, 0x6C, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x48, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x48, 0xA1, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0xC1, 0x4B, 0xDF, 0xF8, 0x0C, 0x83, 0x1D, 0x69, 0xD0, 0xF8, 0x40, 0x90, 0x2F, 0x7A, 0x6B, 0x68, ++0x89, 0xB0, 0x4F, 0xF4, 0xA4, 0x6A, 0xA3, 0xF5, 0x7A, 0x63, 0x0A, 0xFB, 0x07, 0x8B, 0x0C, 0x46, 0x03, 0x92, 0x01, 0x93, ++0x06, 0x46, 0xE4, 0xF7, 0x05, 0xFC, 0x01, 0x9B, 0xDB, 0xF8, 0x40, 0x20, 0x1B, 0x1B, 0x1B, 0x1A, 0x4A, 0x45, 0x01, 0x93, ++0x66, 0xD0, 0x6B, 0x68, 0x02, 0x93, 0xE4, 0xF7, 0xF9, 0xFB, 0x02, 0x9B, 0x99, 0xF8, 0x1B, 0x20, 0x04, 0x90, 0xA3, 0xF5, ++0x7A, 0x63, 0x19, 0x1A, 0xFF, 0x2A, 0x02, 0x91, 0x20, 0xD1, 0x96, 0xF8, 0x4E, 0x60, 0x05, 0x93, 0xFF, 0x2E, 0x40, 0xF0, ++0x8F, 0x80, 0x01, 0x9B, 0x03, 0x9A, 0x18, 0x46, 0x10, 0x44, 0xB2, 0xEB, 0x50, 0x0F, 0x4F, 0xEA, 0x50, 0x03, 0x00, 0xF2, ++0xA9, 0x80, 0x03, 0x9A, 0xA4, 0x4E, 0xA4, 0x1A, 0x1C, 0x44, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x87, 0x2A, 0x46, ++0xD6, 0xF8, 0x88, 0x30, 0x39, 0x6C, 0x20, 0x46, 0x98, 0x47, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0A, 0xFB, 0x02, 0x8A, ++0x50, 0x46, 0x07, 0xAA, 0x06, 0xA9, 0xDB, 0xF8, 0x40, 0x90, 0x01, 0x93, 0x03, 0xF0, 0xE8, 0xFB, 0x83, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0x8C, 0x80, 0x07, 0x9C, 0x02, 0x99, 0x01, 0x9B, 0x0A, 0x1B, 0x00, 0x2A, 0xC0, 0xF2, 0x41, 0x81, 0x06, 0x9A, ++0xD1, 0x1A, 0x04, 0x9B, 0xD9, 0x42, 0x7D, 0xD5, 0x14, 0x1B, 0xE4, 0xF7, 0xB1, 0xFB, 0x00, 0xF5, 0x0C, 0x50, 0x28, 0x30, ++0x84, 0x42, 0x40, 0xF2, 0x3B, 0x81, 0x8B, 0x4E, 0x07, 0x98, 0xD6, 0xF8, 0x88, 0x30, 0x49, 0x46, 0x00, 0x22, 0x98, 0x47, ++0x06, 0x9C, 0xD6, 0xF8, 0x88, 0x90, 0xE4, 0xF7, 0x9F, 0xFB, 0xA4, 0xF5, 0x7A, 0x64, 0x20, 0x1A, 0xDA, 0xF8, 0x40, 0x10, ++0x02, 0x9C, 0x00, 0x22, 0xC8, 0x47, 0xBA, 0xE7, 0xE4, 0xF7, 0x94, 0xFB, 0x01, 0x9B, 0xA3, 0xF5, 0x7A, 0x62, 0x12, 0x1A, ++0x41, 0xF2, 0x87, 0x33, 0x9A, 0x42, 0x01, 0x92, 0xB9, 0xDD, 0x6F, 0x68, 0xE4, 0xF7, 0x88, 0xFB, 0x99, 0xF8, 0x1B, 0xB0, ++0x02, 0x97, 0x3B, 0x1A, 0xBB, 0xF1, 0xFF, 0x0F, 0x01, 0x9A, 0x04, 0x90, 0xA3, 0xF5, 0x7A, 0x67, 0x70, 0xD0, 0x0A, 0xFB, ++0x0B, 0x80, 0x07, 0xAA, 0x06, 0xA9, 0x03, 0xF0, 0x9B, 0xFB, 0x00, 0x28, 0x40, 0xF0, 0xE6, 0x80, 0xE4, 0xF7, 0x72, 0xFB, ++0x06, 0x9E, 0xC6, 0xF5, 0x9C, 0x52, 0x08, 0x32, 0x00, 0xF5, 0x7A, 0x60, 0x22, 0x44, 0x12, 0xEB, 0x40, 0x03, 0x00, 0xF1, ++0xF9, 0x80, 0xE4, 0xF7, 0x65, 0xFB, 0x07, 0x9C, 0x04, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0xDB, 0x1B, 0xC3, 0x42, 0x8C, 0xD5, ++0x64, 0x4E, 0xDF, 0xF8, 0x98, 0xA1, 0x5F, 0xE0, 0x07, 0xAA, 0x0A, 0xFB, 0x06, 0x80, 0x06, 0xA9, 0x03, 0xF0, 0x78, 0xFB, ++0x83, 0x46, 0xE4, 0xF7, 0x51, 0xFB, 0x06, 0x9A, 0xA2, 0xF5, 0x7A, 0x62, 0x10, 0x1A, 0xDD, 0xE9, 0x04, 0x23, 0x06, 0x90, ++0xA2, 0xEB, 0x03, 0x0A, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD1, 0x02, 0x9B, 0x10, 0xEB, 0x0A, 0x0F, 0x54, 0xBF, 0x1C, 0x46, ++0x04, 0x46, 0xE4, 0xF7, 0x3D, 0xFB, 0x07, 0x9B, 0x03, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0x53, 0x44, 0xC3, 0x42, 0x65, 0xD4, ++0x50, 0x4E, 0x58, 0xE7, 0x06, 0x9E, 0x02, 0x9B, 0x9A, 0x1B, 0x00, 0x2A, 0xF8, 0xDB, 0xE4, 0xF7, 0x2D, 0xFB, 0x00, 0xF5, ++0x0C, 0x50, 0x36, 0x1B, 0x28, 0x30, 0x86, 0x42, 0x49, 0x4E, 0x11, 0xD9, 0x49, 0x46, 0x20, 0x46, 0x5A, 0x46, 0xD6, 0xF8, ++0x88, 0x30, 0x98, 0x47, 0x06, 0x9C, 0xD6, 0xF8, 0x88, 0x90, 0xE4, 0xF7, 0x1B, 0xFB, 0xA4, 0xF5, 0x7A, 0x64, 0xDA, 0xF8, ++0x40, 0x10, 0x20, 0x1A, 0x5A, 0x46, 0xC8, 0x47, 0x07, 0x9C, 0x02, 0x9B, 0x1B, 0x1B, 0x00, 0x2B, 0xBF, 0xF6, 0x33, 0xAF, ++0x02, 0x9C, 0x30, 0xE7, 0x96, 0xF8, 0x4E, 0x00, 0x01, 0x93, 0xFF, 0x28, 0x51, 0xD1, 0x03, 0x99, 0x0A, 0x44, 0xB1, 0xEB, ++0x52, 0x0F, 0x4F, 0xEA, 0x52, 0x03, 0xA1, 0xD8, 0x03, 0x9A, 0x35, 0x4E, 0xDF, 0xF8, 0xD8, 0xA0, 0xA4, 0x1A, 0x1C, 0x44, ++0x99, 0xF8, 0x18, 0x30, 0xD6, 0xF8, 0x88, 0x80, 0x02, 0x2B, 0x03, 0xF1, 0x01, 0x01, 0x7B, 0xD0, 0xC1, 0xEB, 0xC1, 0x01, ++0x0A, 0xEB, 0x81, 0x01, 0x0A, 0x7E, 0xFF, 0x2A, 0x0E, 0xD1, 0x01, 0x2B, 0x03, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, ++0xC3, 0xEB, 0xC3, 0x03, 0x0A, 0xEB, 0x83, 0x0A, 0x9A, 0xF8, 0x18, 0x30, 0xFF, 0x2B, 0x14, 0xBF, 0x51, 0x46, 0x00, 0x21, ++0x20, 0x46, 0x00, 0x22, 0xC0, 0x47, 0xD6, 0xF8, 0x88, 0x30, 0x2A, 0x46, 0x49, 0x46, 0x38, 0x46, 0x98, 0x47, 0x09, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x06, 0x83, 0x1B, 0x4E, 0x19, 0x6C, 0xD6, 0xF8, 0x88, 0x30, ++0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0xD6, 0xF8, 0x88, 0x30, 0x07, 0x98, 0x49, 0x46, 0x00, 0x22, 0x98, 0x47, 0xBB, 0xF1, ++0x00, 0x0F, 0xAD, 0xD0, 0x06, 0x9C, 0x02, 0x9B, 0x1A, 0xEB, 0x04, 0x0F, 0x58, 0xBF, 0x1C, 0x46, 0xD9, 0xE6, 0x07, 0xAA, ++0x06, 0xA9, 0x0A, 0xFB, 0x00, 0x80, 0x03, 0xF0, 0xD3, 0xFA, 0x06, 0x9C, 0xE4, 0xF7, 0xAC, 0xFA, 0x01, 0x9B, 0x1B, 0x1B, ++0xC3, 0x42, 0x3F, 0xF5, 0xD6, 0xAE, 0x06, 0x9C, 0x08, 0x4E, 0xDF, 0xF8, 0x28, 0xA0, 0xE4, 0xF7, 0xA1, 0xFA, 0x07, 0x9B, ++0xA4, 0xF5, 0x7A, 0x64, 0xFA, 0x1A, 0x24, 0x1A, 0x17, 0xEA, 0x22, 0x07, 0x38, 0xBF, 0x1F, 0x46, 0x9C, 0xE7, 0x00, 0xBF, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0xDD, 0xE9, 0x06, 0x64, ++0xE4, 0xF7, 0x8A, 0xFA, 0x02, 0x9B, 0x04, 0x9A, 0xF6, 0x1A, 0x32, 0x44, 0x13, 0x1A, 0x00, 0x2B, 0x5B, 0xDB, 0xE4, 0xF7, ++0x81, 0xFA, 0x3B, 0x1B, 0xA3, 0xF5, 0x0C, 0x53, 0x28, 0x3B, 0x18, 0x1A, 0x00, 0x28, 0xBF, 0xF6, 0x1B, 0xAF, 0xA6, 0xE6, ++0x37, 0x4E, 0x67, 0xE7, 0x9A, 0xF8, 0x18, 0x30, 0xFF, 0x2B, 0x5F, 0xD1, 0x01, 0x23, 0x89, 0xE7, 0x02, 0x9C, 0x37, 0xE7, ++0xE4, 0xF7, 0x6C, 0xFA, 0x02, 0x9B, 0xF6, 0x1A, 0x04, 0x9B, 0x33, 0x44, 0x1B, 0x1A, 0x00, 0x2B, 0x4A, 0xDB, 0x01, 0x97, ++0xE4, 0xF7, 0x62, 0xFA, 0x07, 0x9B, 0x03, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0xDB, 0x1B, 0xC3, 0x42, 0x4A, 0xD5, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x0B, 0x83, 0x27, 0x4E, 0x1A, 0x6C, 0xDF, 0xF8, 0x9C, 0xA0, 0x11, 0x7E, 0xD6, 0xF8, 0x88, 0x30, ++0x02, 0x29, 0x01, 0xF1, 0x01, 0x02, 0x2B, 0xD0, 0xC2, 0xEB, 0xC2, 0x00, 0x0A, 0xEB, 0x80, 0x00, 0x00, 0x7E, 0xFF, 0x28, ++0x37, 0xD1, 0x01, 0x29, 0x01, 0xF1, 0x02, 0x02, 0x08, 0xBF, 0x00, 0x22, 0xC2, 0xEB, 0xC2, 0x01, 0x0A, 0xEB, 0x81, 0x01, ++0x09, 0x7E, 0xFF, 0x29, 0x08, 0xBF, 0x00, 0x21, 0x29, 0xD1, 0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x0B, 0x88, 0x01, 0x98, 0xD8, 0xF8, 0x40, 0x10, 0xD6, 0xF8, 0x88, 0x30, 0x00, 0x22, 0x98, 0x47, 0x07, 0x9C, ++0x2C, 0xE7, 0x06, 0x9E, 0xE4, 0xF7, 0x24, 0xFA, 0xA6, 0xF5, 0x7A, 0x66, 0x37, 0x1A, 0x9C, 0xE7, 0x9A, 0xF8, 0x18, 0x20, ++0xFF, 0x2A, 0x0D, 0xD1, 0x01, 0x22, 0xD9, 0xE7, 0x06, 0x9E, 0xE4, 0xF7, 0x17, 0xFA, 0xA6, 0xF5, 0x7A, 0x66, 0x33, 0x1A, ++0x01, 0x93, 0xAD, 0xE7, 0x05, 0x49, 0x33, 0xE7, 0x01, 0x9F, 0xAF, 0xE6, 0x00, 0x22, 0x1C, 0x21, 0x01, 0xFB, 0x02, 0xA1, ++0xD1, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x30, 0xB5, 0x0E, 0x48, 0x83, 0xB0, 0x06, 0xF0, ++0x59, 0xFA, 0x01, 0x90, 0xA0, 0xB1, 0x0C, 0x4B, 0x0C, 0x4C, 0xD3, 0xF8, 0xD8, 0x31, 0x0C, 0x48, 0x98, 0x47, 0x00, 0x23, ++0x01, 0x99, 0xA3, 0x64, 0x04, 0xF1, 0x18, 0x05, 0x20, 0x34, 0x28, 0x46, 0x06, 0xF0, 0x04, 0xFA, 0x20, 0x46, 0x06, 0xF0, ++0x45, 0xFA, 0x01, 0x46, 0x00, 0x28, 0xF6, 0xD1, 0x03, 0xB0, 0x30, 0xBD, 0x50, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x4C, 0x4B, 0x42, 0x69, 0x1F, 0x69, 0x4C, 0x4B, ++0x4C, 0x4C, 0x98, 0x42, 0x83, 0xB0, 0x05, 0x46, 0x17, 0x44, 0x6F, 0xD0, 0xA3, 0x6A, 0xAB, 0x42, 0x04, 0xD0, 0xE4, 0xF7, ++0xCD, 0xF9, 0x07, 0xF5, 0x7A, 0x67, 0x07, 0x44, 0x94, 0xF8, 0x5B, 0x80, 0x94, 0xF8, 0x58, 0x30, 0xC4, 0xE9, 0x14, 0x57, ++0xB8, 0xF1, 0x00, 0x0F, 0x57, 0xD1, 0x42, 0x4E, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x73, 0x6B, 0x98, 0x47, ++0xD6, 0xF8, 0x88, 0x30, 0x42, 0x46, 0x41, 0x46, 0x38, 0x46, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, ++0x3A, 0xD0, 0x3A, 0x4B, 0xDF, 0xF8, 0xF8, 0x90, 0xDB, 0x1B, 0x01, 0x93, 0x4F, 0xF4, 0xA4, 0x68, 0x0C, 0xE0, 0x02, 0x2A, ++0x04, 0xBF, 0xB0, 0xF8, 0xD2, 0x20, 0x91, 0x02, 0x61, 0x44, 0x00, 0x22, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, ++0x00, 0x0F, 0x25, 0xD0, 0xDB, 0xF8, 0x04, 0xA0, 0xE4, 0xF7, 0x96, 0xF9, 0x01, 0x9B, 0xAA, 0xEB, 0x00, 0x00, 0xD8, 0x42, ++0x1C, 0xD5, 0x9B, 0xF8, 0x08, 0x00, 0xDB, 0xF8, 0x04, 0xC0, 0xF3, 0x6A, 0x08, 0xFB, 0x00, 0x90, 0x4F, 0xF4, 0xC8, 0x31, ++0x90, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xDC, 0xD1, 0x90, 0xF8, 0x6C, 0x20, 0x24, 0x4F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, ++0x02, 0x72, 0x91, 0x68, 0x00, 0x22, 0x61, 0x44, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, 0xD9, 0xD1, ++0xE3, 0x6A, 0xD3, 0xB1, 0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1B, 0xDB, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x43, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x94, 0xF8, 0x58, 0x30, ++0x5A, 0x07, 0x8B, 0xD4, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD6, 0xF8, ++0x9C, 0x30, 0x28, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x94, 0xF8, 0x58, 0x30, 0x13, 0xF0, 0x0C, 0x0F, ++0xDE, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0x86, 0x62, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x07, 0xF0, 0xAC, 0xBD, ++0x00, 0x10, 0x50, 0x40, 0x00, 0x9E, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x60, 0xF0, 0xFF, 0xFF, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x5C, 0xA1, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x10, 0xB5, 0x22, 0x4C, 0x94, 0xF8, 0x58, 0x30, 0xD8, 0x07, 0x11, 0xD5, 0x20, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, ++0x00, 0x2A, 0x22, 0xDB, 0x23, 0xF0, 0x01, 0x03, 0x43, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x1B, 0x4B, 0x1C, 0x48, ++0xDB, 0x6D, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x03, 0xF0, 0x06, 0x02, 0x02, 0x2A, 0x11, 0xD1, 0x15, 0x4A, 0x12, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x17, 0xDB, 0x23, 0xF0, 0x02, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x58, 0x30, ++0x10, 0x4B, 0x12, 0x48, 0xDB, 0x6D, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x10, 0xBD, 0x59, 0x07, 0xDA, 0xD5, 0x0F, 0x49, ++0x0F, 0x48, 0x40, 0xF2, 0x9B, 0x62, 0x07, 0xF0, 0x61, 0xFD, 0x94, 0xF8, 0x58, 0x30, 0xD1, 0xE7, 0x1A, 0x07, 0xE5, 0xD5, ++0x09, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0xA6, 0x62, 0x07, 0xF0, 0x56, 0xFD, 0x94, 0xF8, 0x58, 0x30, 0xDC, 0xE7, 0x00, 0xBF, ++0x30, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x9E, 0x17, 0x00, 0xE4, 0x9D, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x8C, 0xA1, 0x15, 0x00, 0xC0, 0xA1, 0x15, 0x00, 0x0D, 0x4A, 0x92, 0xF8, 0x58, 0x30, 0xD9, 0x06, ++0x14, 0xD4, 0x92, 0xF8, 0x5A, 0x00, 0x43, 0xF0, 0x10, 0x03, 0x82, 0xF8, 0x58, 0x30, 0x50, 0xB1, 0x08, 0x49, 0x09, 0x4B, ++0x09, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x01, 0xF5, 0xEA, 0x41, 0x02, 0xF1, 0x30, 0x00, 0x30, 0x31, 0x18, 0x47, 0x04, 0x4B, ++0xDB, 0x6B, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0xB5, 0x32, 0x4C, 0x00, 0x23, 0x05, 0x46, 0xA3, 0x62, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x2E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x4A, 0x2E, 0x4E, 0x11, 0x68, 0x73, 0x68, 0x48, 0x1C, 0x23, 0xF0, 0x02, 0x03, ++0x10, 0x60, 0x73, 0x60, 0x18, 0xB1, 0x28, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0xF9, 0xB1, 0x29, 0x49, 0x94, 0xF8, 0x5C, 0x30, ++0x0A, 0x68, 0x9B, 0x00, 0x22, 0xF0, 0x04, 0x02, 0x03, 0xF0, 0x04, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x2B, 0x7E, 0x03, 0x2B, ++0x26, 0xD0, 0x04, 0x2B, 0x94, 0xF8, 0x58, 0x30, 0x19, 0xD0, 0x23, 0xF0, 0x10, 0x02, 0xFF, 0x21, 0x9B, 0x07, 0x29, 0x76, ++0x84, 0xF8, 0x58, 0x20, 0x02, 0xD0, 0x1D, 0x4B, 0x1B, 0x6C, 0x98, 0x47, 0xE3, 0x6A, 0x23, 0xB1, 0x70, 0xBD, 0x00, 0x2B, ++0xDD, 0xD0, 0x62, 0xB6, 0xDB, 0xE7, 0x18, 0x4B, 0xD3, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xBD, 0xE8, 0x70, 0x40, 0xFB, 0xF7, ++0x93, 0xBA, 0x23, 0xF0, 0x04, 0x02, 0x84, 0xF8, 0x58, 0x20, 0xEA, 0x89, 0x92, 0xB9, 0x03, 0xF0, 0xDB, 0x03, 0xDC, 0xE7, ++0x94, 0xF8, 0x58, 0x30, 0x23, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x58, 0x30, 0xFE, 0xF7, 0x84, 0xFE, 0xFF, 0x22, 0x02, 0x21, ++0x86, 0x20, 0x05, 0xF0, 0x49, 0xFC, 0x94, 0xF8, 0x58, 0x30, 0xCC, 0xE7, 0x28, 0x46, 0xFE, 0xF7, 0xB1, 0xFE, 0x94, 0xF8, ++0x58, 0x30, 0xC6, 0xE7, 0x30, 0x9D, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x4C, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x6B, 0x4F, 0x6C, 0x4E, 0x04, 0x46, 0x6C, 0x48, ++0x06, 0xF0, 0x96, 0xF8, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0xC0, 0xF2, 0x85, 0x80, 0x33, 0x78, ++0x00, 0x2B, 0x44, 0xD0, 0x66, 0x4C, 0x01, 0x2B, 0x42, 0xD1, 0x94, 0xF8, 0x58, 0x30, 0x19, 0x07, 0x00, 0xF1, 0x9D, 0x80, ++0x5A, 0x07, 0x40, 0xF1, 0xB0, 0x80, 0x62, 0x4F, 0xE3, 0x6A, 0xBB, 0x42, 0x02, 0xD0, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, ++0xA3, 0x6A, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, 0x00, 0x23, 0xC4, 0xE9, 0x0A, 0x73, 0x39, 0x7E, 0x04, 0x23, 0x03, 0x29, ++0x3B, 0x74, 0x00, 0xF0, 0xA0, 0x80, 0x02, 0x29, 0x24, 0xD9, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x55, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x55, 0x4A, 0x55, 0x48, 0x17, 0x68, 0x43, 0x68, 0x79, 0x1C, 0x43, 0xF0, 0x02, 0x03, ++0x11, 0x60, 0x43, 0x60, 0x29, 0xB1, 0x4F, 0x4B, 0x17, 0x60, 0x1B, 0x68, 0x0F, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x4F, 0x4A, ++0xA3, 0x6A, 0x11, 0x68, 0xC1, 0xF3, 0x80, 0x01, 0x84, 0xF8, 0x5C, 0x10, 0x11, 0x68, 0x21, 0xF0, 0x04, 0x01, 0x11, 0x60, ++0x01, 0xE0, 0x44, 0x4C, 0xA3, 0x6A, 0x01, 0x22, 0x1A, 0x74, 0x22, 0x6D, 0x00, 0x23, 0x33, 0x70, 0x00, 0x2A, 0x31, 0xD0, ++0x94, 0xF8, 0x5A, 0x20, 0x23, 0x65, 0x00, 0x2A, 0x53, 0xD0, 0x01, 0x2A, 0x53, 0xD0, 0x23, 0x69, 0x00, 0x2B, 0x50, 0xD0, ++0x1B, 0x7A, 0x40, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x18, 0x6C, 0xA8, 0x60, 0x18, 0xB1, 0x3D, 0x4B, ++0xD3, 0xF8, 0x9C, 0x30, 0x98, 0x47, 0x3C, 0x48, 0x29, 0x46, 0x05, 0xF0, 0xDF, 0xFF, 0xA0, 0x6A, 0x03, 0x7E, 0x02, 0x2B, ++0x02, 0xD9, 0x37, 0x4B, 0x9B, 0x6B, 0x98, 0x47, 0x20, 0x6A, 0xA0, 0x64, 0x58, 0xB3, 0x36, 0x4B, 0x41, 0x68, 0x1B, 0x69, ++0xCB, 0x1A, 0x14, 0x2B, 0x27, 0xD4, 0x31, 0x4B, 0x33, 0x48, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, ++0xA8, 0x68, 0xDD, 0xE7, 0x84, 0x42, 0x32, 0xD0, 0x2F, 0x49, 0x30, 0x48, 0x40, 0xF2, 0x4F, 0x72, 0x07, 0xF0, 0x12, 0xFC, ++0x33, 0x78, 0x00, 0x2B, 0x7F, 0xF4, 0x72, 0xAF, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB1, 0xDA, 0x1D, 0x4C, ++0xA3, 0x6A, 0x00, 0x2B, 0xAF, 0xD1, 0x26, 0x49, 0x27, 0x48, 0x40, 0xF2, 0x51, 0x72, 0x07, 0xF0, 0xFF, 0xFB, 0x33, 0x78, ++0x61, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x63, 0x6C, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x22, 0x4F, 0x64, 0xE7, 0xAA, 0x60, ++0xBB, 0xE7, 0x21, 0x48, 0x02, 0x7E, 0xFF, 0x2A, 0xB1, 0xD1, 0x90, 0xF8, 0x34, 0x20, 0xFF, 0x2A, 0x12, 0xD1, 0x90, 0xF8, ++0x50, 0x20, 0xFF, 0x2A, 0x10, 0xD1, 0xAB, 0x60, 0xAD, 0xE7, 0x33, 0x78, 0x00, 0x2B, 0xD8, 0xD0, 0x44, 0xE7, 0xE7, 0x6A, ++0x00, 0x2F, 0x87, 0xD0, 0x52, 0xE7, 0x02, 0x20, 0x05, 0xF0, 0xF2, 0xFC, 0x39, 0x7E, 0x5A, 0xE7, 0x1C, 0x30, 0x98, 0xE7, ++0x38, 0x30, 0x96, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x17, 0x2C, 0x17, 0x00, 0x50, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, ++0x00, 0x9E, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x9D, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xF4, 0xA1, 0x15, 0x00, 0x10, 0xA2, 0x15, 0x00, 0xE4, 0x9D, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x0D, 0x4B, 0x93, 0xF8, 0x58, 0x20, 0x11, 0x07, 0x03, 0xD4, 0x52, 0x07, 0x0D, 0xD5, 0x0B, 0x49, 0x00, 0xE0, 0x0B, 0x49, ++0xDA, 0x6A, 0x8A, 0x42, 0x03, 0xD0, 0x0A, 0xB1, 0x01, 0x20, 0x10, 0x74, 0xD9, 0x62, 0x08, 0x4B, 0xD3, 0xF8, 0x98, 0x30, ++0x18, 0x47, 0xDB, 0x6A, 0x00, 0x2B, 0xF8, 0xD1, 0x05, 0x49, 0x08, 0x20, 0x07, 0xF0, 0x68, 0xB9, 0x30, 0x9D, 0x17, 0x00, ++0x00, 0x9E, 0x17, 0x00, 0xE4, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x28, 0xA2, 0x15, 0x00, 0x0B, 0x4A, 0x92, 0xF8, ++0x59, 0x30, 0x43, 0xB1, 0x01, 0x3B, 0xDB, 0xB2, 0x82, 0xF8, 0x59, 0x30, 0x1B, 0xB9, 0x08, 0x4A, 0x11, 0x78, 0x01, 0x29, ++0x00, 0xD0, 0x70, 0x47, 0x10, 0xB5, 0x06, 0x4C, 0x13, 0x70, 0xD4, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xE3, 0x6F, 0xBD, 0xE8, ++0x10, 0x40, 0x18, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x17, 0x2C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x1D, 0x4B, ++0x1D, 0x49, 0x1E, 0x4A, 0xD3, 0xF8, 0xE0, 0x33, 0x8C, 0x68, 0x95, 0x6A, 0x98, 0x47, 0x1C, 0x4B, 0x5B, 0x78, 0x23, 0xB1, ++0x1B, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x1A, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x13, 0x60, ++0x1C, 0xB3, 0x18, 0x4F, 0x8C, 0x26, 0x01, 0xE0, 0x24, 0x68, 0xF4, 0xB1, 0x23, 0x6C, 0xAB, 0x42, 0xFA, 0xD1, 0x94, 0xF8, ++0x62, 0x30, 0x00, 0x2B, 0xF6, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x22, ++0x11, 0x46, 0x3B, 0xB1, 0x94, 0xF8, 0xC1, 0x34, 0x06, 0xFB, 0x03, 0x73, 0x93, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0xE5, 0xD0, ++0x94, 0xF8, 0x6C, 0x00, 0xF2, 0xF7, 0xD6, 0xFD, 0x24, 0x68, 0x00, 0x2C, 0xE0, 0xD1, 0xF8, 0xBD, 0x88, 0x1A, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, ++0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x08, 0x81, 0x3D, 0x4A, 0x3E, 0x4E, 0xD8, 0xF8, 0xDC, 0x33, ++0x94, 0x68, 0x96, 0xF8, 0x59, 0x90, 0x83, 0xB0, 0x98, 0x47, 0xB5, 0x6A, 0x00, 0x2D, 0x5E, 0xD0, 0x39, 0x4A, 0x3A, 0x49, ++0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x4B, 0x78, 0x4F, 0x46, 0x00, 0x2B, 0x4D, 0xD1, 0x00, 0x2C, 0x3A, 0xD0, ++0xDF, 0xF8, 0xD8, 0xB0, 0xDF, 0xF8, 0xD8, 0xA0, 0x4F, 0xF0, 0x06, 0x09, 0x01, 0xE0, 0x24, 0x68, 0x7C, 0xB3, 0x23, 0x6C, ++0x9D, 0x42, 0xFA, 0xD1, 0x94, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xF6, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, ++0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x4F, 0xF0, 0x8C, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0xEA, 0xD0, 0x94, 0xF8, 0xC0, 0x34, ++0x3B, 0xB1, 0x94, 0xF8, 0xC1, 0x34, 0x01, 0xFB, 0x03, 0xA3, 0x93, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0xDF, 0xD0, 0x2B, 0x7C, ++0x85, 0xF8, 0x10, 0x90, 0xD8, 0xF8, 0xB0, 0x10, 0x01, 0x93, 0xF2, 0xF7, 0x79, 0xFD, 0x01, 0x9B, 0x00, 0xB9, 0x01, 0x37, ++0x01, 0x22, 0x2B, 0x74, 0x8B, 0xF8, 0x00, 0x20, 0x24, 0x68, 0x00, 0x2C, 0xCF, 0xD1, 0x5F, 0xFA, 0x87, 0xF9, 0x96, 0xF8, ++0x59, 0x40, 0xF5, 0x6A, 0x86, 0xF8, 0x59, 0x90, 0x3C, 0x1B, 0xAD, 0xB1, 0x27, 0xB1, 0x03, 0x23, 0x2B, 0x74, 0xD8, 0xF8, ++0x60, 0x31, 0x98, 0x47, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD2, 0xF8, 0xE8, 0x33, 0x43, 0xF0, 0x00, 0x43, ++0xC2, 0xF8, 0xE8, 0x33, 0xAA, 0xE7, 0x00, 0x24, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD8, 0xF8, 0x60, 0x31, ++0x98, 0x47, 0x00, 0x2F, 0xF5, 0xD0, 0x96, 0xF8, 0x59, 0x30, 0x01, 0x3B, 0x2C, 0x46, 0x86, 0xF8, 0x59, 0x30, 0xE3, 0xE7, ++0x00, 0x88, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x17, 0x2C, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0xD4, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xA3, 0x6E, ++0x98, 0x47, 0x18, 0xB9, 0xE3, 0x6F, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x43, 0x4D, 0x4E, 0x4E, 0x4F, 0xF4, 0x6A, 0x85, 0xB0, 0x00, 0x25, 0xE2, 0x88, 0x61, 0x79, 0x23, 0x89, ++0x20, 0x79, 0x02, 0x95, 0x65, 0x7B, 0x01, 0x95, 0x65, 0x89, 0x00, 0x95, 0xE3, 0xF7, 0x72, 0xFD, 0xD7, 0xF8, 0x3C, 0x33, ++0x94, 0xF9, 0x0C, 0x00, 0x98, 0x47, 0x21, 0x79, 0x44, 0x4B, 0x45, 0x4A, 0x03, 0xEB, 0x81, 0x03, 0x5B, 0x69, 0x13, 0x60, ++0x23, 0x7E, 0x03, 0x2B, 0x02, 0xD0, 0x20, 0x46, 0xFE, 0xF7, 0xFE, 0xFB, 0xB3, 0x6A, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, ++0x00, 0x23, 0xC6, 0xE9, 0x0A, 0x43, 0x23, 0x7E, 0x04, 0x22, 0x02, 0x2B, 0x22, 0x74, 0x4E, 0xD9, 0x96, 0xF8, 0x5A, 0x20, ++0x00, 0x2A, 0x4A, 0xD0, 0x03, 0x2B, 0x52, 0xD0, 0x04, 0x2B, 0x24, 0xD0, 0xFB, 0x6E, 0x98, 0x47, 0x23, 0x7E, 0x02, 0x2B, ++0x1F, 0xD8, 0x34, 0x4B, 0x9D, 0x68, 0x00, 0x2D, 0x37, 0xD0, 0xDF, 0xF8, 0xE4, 0x90, 0x4F, 0xF0, 0x01, 0x08, 0x01, 0xE0, ++0x2D, 0x68, 0x8D, 0xB1, 0x2B, 0x6C, 0xA3, 0x42, 0xFA, 0xD1, 0x95, 0xF8, 0x63, 0x30, 0xD7, 0xF8, 0x5C, 0x24, 0xC3, 0xEB, ++0xC3, 0x03, 0x09, 0xEB, 0x83, 0x03, 0x28, 0x46, 0x83, 0xF8, 0x1B, 0x80, 0x90, 0x47, 0x2D, 0x68, 0x00, 0x2D, 0xED, 0xD1, ++0x23, 0x7E, 0x02, 0x2B, 0x1B, 0xD9, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x22, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x22, 0x4A, 0x22, 0x4C, 0x11, 0x68, 0x63, 0x68, 0x48, 0x1C, 0x43, 0xF0, 0x02, 0x03, 0x10, 0x60, 0x63, 0x60, ++0x28, 0xBB, 0x1F, 0x4B, 0x19, 0x68, 0x1A, 0x68, 0xC1, 0xF3, 0x80, 0x01, 0x22, 0xF0, 0x04, 0x02, 0x86, 0xF8, 0x5C, 0x10, ++0x1A, 0x60, 0xD7, 0xF8, 0x60, 0x31, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, 0x18, 0x4A, 0x92, 0xF8, 0xFF, 0x21, ++0x00, 0x2A, 0xAF, 0xD0, 0xF1, 0xF7, 0xA2, 0xFB, 0x23, 0x7E, 0x03, 0x2B, 0xAC, 0xD1, 0x14, 0x4B, 0x00, 0x22, 0x1A, 0x60, ++0x02, 0x21, 0xFF, 0x22, 0x85, 0x20, 0x05, 0xF0, 0x77, 0xF9, 0x23, 0x7E, 0x02, 0x2B, 0xE4, 0xD9, 0xC7, 0xE7, 0x09, 0x4B, ++0x11, 0x60, 0x1B, 0x68, 0x00, 0x29, 0xD4, 0xD1, 0x00, 0x2B, 0xD2, 0xD0, 0x62, 0xB6, 0xD0, 0xE7, 0x30, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x20, 0x62, 0x17, 0x00, 0x20, 0x02, 0x32, 0x40, ++0x80, 0x9F, 0x17, 0x00, 0x70, 0xB5, 0x25, 0x4D, 0xEA, 0x6A, 0x04, 0x46, 0x0A, 0xB1, 0xE8, 0x62, 0x70, 0xBD, 0xAE, 0x6A, ++0x86, 0x42, 0x3D, 0xD0, 0x5E, 0xB1, 0x33, 0x7E, 0x03, 0x2B, 0x08, 0xD0, 0x01, 0x23, 0x0C, 0x21, 0x45, 0x20, 0x05, 0xF0, ++0xD7, 0xF8, 0x33, 0x7E, 0x03, 0x70, 0x05, 0xF0, 0x03, 0xF9, 0x1B, 0x4B, 0x5B, 0x68, 0x00, 0x2B, 0x1C, 0xDD, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x17, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x17, 0x4E, 0x33, 0x68, 0x04, 0x20, ++0x01, 0x33, 0x33, 0x60, 0xF1, 0xF7, 0x42, 0xF8, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xF1, 0xF7, 0xDD, 0xF8, 0x33, 0x68, ++0x33, 0xB1, 0x0F, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x02, 0x22, 0xEC, 0x62, ++0x04, 0x23, 0x22, 0x74, 0x00, 0x21, 0xFF, 0x22, 0x84, 0x20, 0x05, 0xF0, 0xA9, 0xF8, 0x09, 0x4B, 0x1B, 0x6E, 0x03, 0x60, ++0xBD, 0xE8, 0x70, 0x40, 0x05, 0xF0, 0xD2, 0xB8, 0x04, 0x23, 0x33, 0x74, 0x70, 0xBD, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, ++0xD8, 0x9C, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x0A, 0x4D, ++0x04, 0x46, 0xD5, 0xF8, 0x6C, 0x31, 0x00, 0x6D, 0x98, 0x47, 0xD5, 0xF8, 0x00, 0x32, 0x20, 0x65, 0x01, 0x46, 0x20, 0x46, ++0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x40, 0x03, 0x43, 0xF0, 0x20, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x38, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x02, 0x6D, 0x41, 0x6A, 0x70, 0xB5, 0x17, 0x4D, 0x04, 0x46, 0xD5, 0xF8, 0xE0, 0x31, 0x11, 0x44, ++0x18, 0x30, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x20, 0x02, 0xDB, 0x07, 0x84, 0xF8, 0x4D, 0x20, 0x0E, 0xD5, ++0x10, 0x4B, 0x5B, 0x6A, 0x23, 0xB1, 0xDA, 0x68, 0x04, 0xF1, 0x44, 0x03, 0x9A, 0x42, 0x07, 0xD0, 0xEB, 0x6A, 0x61, 0x6A, ++0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x70, 0xBD, 0x6B, 0x6B, 0x98, 0x47, 0xEB, 0x6A, 0x61, 0x6A, ++0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0x06, 0x4A, 0xD5, 0xF8, 0x84, 0x30, 0x11, 0x69, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, ++0x70, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF8, 0x43, ++0xDF, 0xF8, 0xB8, 0x80, 0x90, 0xF8, 0x4E, 0x70, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x07, 0x85, 0x95, 0xF8, 0x4D, 0x60, ++0x16, 0xF0, 0x60, 0x06, 0x1F, 0xD1, 0x26, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xFC, 0x31, 0x89, 0x46, 0x90, 0xF8, 0x4F, 0x10, ++0x28, 0x46, 0x98, 0x47, 0x63, 0x6D, 0xA0, 0xEB, 0x09, 0x01, 0x58, 0x1A, 0x00, 0xB2, 0x80, 0xEA, 0xE0, 0x73, 0xA3, 0xEB, ++0xE0, 0x73, 0x9B, 0xB2, 0xB3, 0xF5, 0xFA, 0x6F, 0xA4, 0xF8, 0x58, 0x00, 0x09, 0xD9, 0x95, 0xF8, 0x4D, 0x30, 0x23, 0xF0, ++0x40, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x85, 0xF8, 0x4D, 0x30, 0xBD, 0xE8, 0xF8, 0x83, 0xC8, 0x2B, 0xFB, 0xD9, 0x15, 0x4B, ++0x9B, 0x68, 0x9B, 0xB1, 0x95, 0xF8, 0x63, 0x10, 0x30, 0x46, 0x93, 0xF8, 0x4E, 0x20, 0x8A, 0x42, 0x07, 0xD1, 0xB3, 0xF9, ++0x58, 0x20, 0x90, 0x42, 0xA8, 0xBF, 0x10, 0x46, 0x96, 0x42, 0xB8, 0xBF, 0x16, 0x46, 0x1B, 0x68, 0x00, 0x2B, 0xF0, 0xD1, ++0x60, 0xB9, 0x73, 0x10, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x87, 0x97, 0xF8, 0x4D, 0x20, 0x3B, 0x65, 0x42, 0xF0, ++0x40, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0xD8, 0xE7, 0x00, 0x2E, 0xD6, 0xD1, 0x00, 0xEB, 0xD0, 0x73, 0x5B, 0x10, 0xED, 0xE7, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x23, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x60, 0x22, ++0x00, 0x21, 0x22, 0x4F, 0x06, 0x46, 0xE2, 0xF7, 0xD3, 0xFB, 0x00, 0x25, 0x3C, 0x46, 0xA8, 0x46, 0x00, 0x21, 0x1C, 0x22, ++0x20, 0x46, 0xE2, 0xF7, 0xCB, 0xFB, 0xFF, 0x23, 0x02, 0x2D, 0xE3, 0x81, 0x23, 0x76, 0xE3, 0x76, 0x21, 0x46, 0x30, 0x46, ++0x04, 0xD8, 0x05, 0xF0, 0x55, 0xFC, 0x01, 0x35, 0x1C, 0x34, 0xED, 0xE7, 0x03, 0x2D, 0x22, 0xD0, 0x04, 0x2D, 0xF8, 0xD1, ++0x14, 0x48, 0x05, 0xF0, 0x47, 0xFC, 0x14, 0x48, 0x05, 0xF0, 0x44, 0xFC, 0x13, 0x49, 0x11, 0x48, 0x05, 0xF0, 0x44, 0xFC, ++0x12, 0x49, 0x0F, 0x48, 0x05, 0xF0, 0x40, 0xFC, 0x11, 0x49, 0x0D, 0x48, 0x05, 0xF0, 0x3C, 0xFC, 0x10, 0x49, 0x0B, 0x48, ++0x05, 0xF0, 0x38, 0xFC, 0x0F, 0x4A, 0x07, 0x4B, 0xD2, 0xF8, 0xAC, 0x10, 0xD0, 0x6B, 0x58, 0x63, 0x00, 0x22, 0xC3, 0xE9, ++0x11, 0x12, 0xBD, 0xE8, 0xF0, 0x81, 0xA7, 0xF8, 0x5E, 0x80, 0x87, 0xF8, 0x59, 0x80, 0xD2, 0xE7, 0x30, 0x9D, 0x17, 0x00, ++0x90, 0x9D, 0x17, 0x00, 0x48, 0x9D, 0x17, 0x00, 0x50, 0x9D, 0x17, 0x00, 0xF0, 0x9C, 0x17, 0x00, 0x00, 0x9D, 0x17, 0x00, ++0x10, 0x9D, 0x17, 0x00, 0x20, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x21, 0x4C, 0x24, 0x68, ++0xB4, 0xF9, 0x00, 0x40, 0x83, 0xB0, 0x00, 0x2C, 0x9D, 0xF8, 0x28, 0x90, 0x9D, 0xF8, 0x2C, 0x80, 0x1D, 0x4C, 0x07, 0x46, ++0x0D, 0x46, 0x16, 0x46, 0x27, 0xDB, 0x1C, 0x49, 0x84, 0xF8, 0x58, 0x70, 0x91, 0xF8, 0x58, 0x20, 0xA4, 0xF8, 0x5C, 0x50, ++0xA4, 0xF8, 0x5A, 0x50, 0x42, 0xF0, 0x02, 0x07, 0x84, 0xF8, 0x60, 0x60, 0xFF, 0x25, 0x03, 0x26, 0x01, 0x20, 0xA3, 0x66, ++0xD3, 0x06, 0x84, 0xF8, 0x61, 0x90, 0x84, 0xF8, 0x6E, 0x80, 0x81, 0xF8, 0x58, 0x70, 0x84, 0xF8, 0x6C, 0x60, 0xA4, 0xF8, ++0x62, 0x50, 0x84, 0xF8, 0x64, 0x00, 0x05, 0xD4, 0x0D, 0x4B, 0x1B, 0x6C, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x94, 0xF8, 0x6C, 0x20, 0xFF, 0x2A, 0xD3, 0xD0, 0x08, 0x49, 0x08, 0x48, 0x01, 0x93, ++0x40, 0xF6, 0x8C, 0x22, 0x07, 0xF0, 0x26, 0xF8, 0x01, 0x9B, 0xCA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x48, 0xA2, 0x15, 0x00, 0xF0, 0xB5, 0x65, 0x4F, ++0x04, 0x46, 0x83, 0xB0, 0x97, 0xF8, 0x80, 0x00, 0xE3, 0x68, 0x22, 0x78, 0x00, 0x90, 0x0E, 0x46, 0x08, 0x20, 0x61, 0x49, ++0x06, 0xF0, 0xE0, 0xFD, 0x25, 0x78, 0x25, 0xB3, 0x01, 0x2D, 0x2F, 0xD1, 0x97, 0xF8, 0x88, 0x30, 0xFF, 0x2B, 0x1A, 0xD0, ++0x97, 0xF8, 0x80, 0x30, 0x03, 0x2B, 0x2B, 0xD8, 0x01, 0x2B, 0x5A, 0x4C, 0x44, 0xD8, 0x09, 0xD1, 0x94, 0xF8, 0x58, 0x30, ++0x07, 0xF1, 0x70, 0x00, 0x23, 0xF0, 0x05, 0x03, 0x84, 0xF8, 0x58, 0x30, 0xFE, 0xF7, 0xE4, 0xF9, 0x94, 0xF8, 0x58, 0x30, ++0x03, 0xF0, 0x12, 0x02, 0xFF, 0x21, 0x10, 0x2A, 0x87, 0xF8, 0x88, 0x10, 0x24, 0xD0, 0x00, 0x25, 0x28, 0x46, 0x03, 0xB0, ++0xF0, 0xBD, 0x97, 0xF8, 0x88, 0x30, 0xFF, 0x2B, 0x3A, 0xD0, 0x4B, 0x4A, 0x92, 0xF8, 0x58, 0x30, 0x99, 0x06, 0x03, 0xD5, ++0x23, 0xF0, 0x20, 0x03, 0x82, 0xF8, 0x58, 0x30, 0x01, 0x25, 0x28, 0x46, 0x03, 0xB0, 0xF0, 0xBD, 0x04, 0x2B, 0x17, 0xD1, ++0x44, 0x48, 0x45, 0x4D, 0xA0, 0xF1, 0x40, 0x04, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x22, 0xD5, 0xF8, 0xAC, 0x30, ++0x20, 0x6A, 0xA2, 0x64, 0x98, 0x47, 0xD1, 0xE7, 0x3E, 0x4A, 0x3F, 0x48, 0xD2, 0xF8, 0xD8, 0x21, 0x23, 0xF0, 0x10, 0x03, ++0x84, 0xF8, 0x58, 0x30, 0x90, 0x47, 0xD0, 0xE7, 0x37, 0x4C, 0xC5, 0xE7, 0x94, 0xF8, 0x58, 0x30, 0xE2, 0x6A, 0x23, 0xF0, ++0x04, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x2A, 0xB1, 0x07, 0xF1, 0x70, 0x03, 0x9A, 0x42, 0x50, 0xD0, 0x00, 0x23, 0xE3, 0x62, ++0x33, 0x48, 0xFE, 0xF7, 0x99, 0xF9, 0xB3, 0xE7, 0x97, 0xF8, 0x80, 0x30, 0x04, 0x2B, 0xC0, 0xD0, 0x04, 0x20, 0x05, 0xF0, ++0x5D, 0xF9, 0x01, 0x28, 0xBB, 0xD0, 0x04, 0x23, 0x87, 0xF8, 0x88, 0x30, 0xA3, 0x78, 0x87, 0xF8, 0x74, 0x30, 0xE3, 0x78, ++0x87, 0xF8, 0x75, 0x30, 0xA3, 0x88, 0xE2, 0x88, 0xA7, 0xF8, 0x76, 0x30, 0x01, 0x21, 0x23, 0x89, 0x87, 0xF8, 0x80, 0x10, ++0xA7, 0xF8, 0x78, 0x20, 0xE2, 0x68, 0xA7, 0xF8, 0x7A, 0x30, 0x4F, 0xF4, 0x7A, 0x73, 0x03, 0xFB, 0x02, 0xF3, 0x23, 0x2A, ++0x84, 0xBF, 0xA3, 0xF5, 0x08, 0x43, 0xB8, 0x3B, 0xA7, 0xF8, 0x7E, 0x60, 0xC7, 0xF8, 0x84, 0x30, 0x63, 0x78, 0x17, 0x4A, ++0x87, 0xF8, 0x8A, 0x30, 0x23, 0x7C, 0x87, 0xF8, 0x7C, 0x30, 0x16, 0x49, 0x92, 0xF8, 0x58, 0x30, 0x66, 0xB9, 0x43, 0xF0, ++0x04, 0x03, 0xC9, 0x6D, 0x14, 0x48, 0x82, 0xF8, 0x58, 0x30, 0x88, 0x47, 0x13, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, ++0x13, 0x60, 0x8A, 0xE7, 0x43, 0xF0, 0x01, 0x03, 0x09, 0x6C, 0x82, 0xF8, 0x58, 0x30, 0x88, 0x47, 0xF2, 0xE7, 0x23, 0x6D, ++0x93, 0x42, 0xAB, 0xD1, 0x08, 0x4B, 0x04, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x23, 0xA3, 0x64, ++0xA2, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, 0x68, 0xA2, 0x15, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x60, 0x9D, 0x17, 0x00, 0x00, 0x9E, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x36, 0x4E, 0x84, 0xB0, 0x04, 0x46, 0x0F, 0x46, 0x33, 0x46, 0x00, 0x25, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, 0x1A, 0x79, ++0x20, 0x78, 0x90, 0x42, 0x1B, 0xD0, 0x01, 0x35, 0x03, 0x2D, 0x03, 0xF1, 0x1C, 0x03, 0xF3, 0xD1, 0x2E, 0x48, 0x05, 0xF0, ++0x15, 0xFB, 0x03, 0x46, 0x70, 0xB3, 0x2D, 0x4A, 0x86, 0x1B, 0xB6, 0x10, 0x02, 0xFB, 0x06, 0xF6, 0xF6, 0xB2, 0x06, 0x76, ++0x3E, 0x70, 0x20, 0x68, 0x61, 0x68, 0x04, 0x33, 0x03, 0xC3, 0x22, 0x89, 0x1A, 0x80, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, ++0xF0, 0x81, 0xD9, 0x88, 0x62, 0x88, 0x8A, 0x42, 0xDF, 0xD1, 0x93, 0xF8, 0x05, 0xC0, 0x61, 0x78, 0x8C, 0x45, 0x08, 0xD0, ++0x02, 0xD2, 0xBC, 0xF1, 0x03, 0x0F, 0x13, 0xD1, 0x8C, 0x45, 0xD4, 0xD9, 0x03, 0x29, 0xD2, 0xD0, 0x07, 0xE0, 0x19, 0x89, ++0xA2, 0x88, 0x91, 0x42, 0xCD, 0xD1, 0x59, 0x89, 0xE2, 0x88, 0x91, 0x42, 0xC9, 0xD1, 0x3D, 0x70, 0x00, 0x20, 0xDF, 0xE7, ++0x01, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0xDF, 0xF8, 0x48, 0xE0, 0xB4, 0xF8, 0x04, 0x80, 0xB4, 0xF8, 0x06, 0xC0, ++0xDE, 0xF8, 0x28, 0x30, 0xC5, 0xEB, 0xC5, 0x04, 0x06, 0xEB, 0x84, 0x04, 0xA3, 0x42, 0x61, 0x71, 0xA4, 0xF8, 0x08, 0x80, ++0xA4, 0xF8, 0x0A, 0xC0, 0xE5, 0xD1, 0x9E, 0xF8, 0x5A, 0x40, 0x01, 0x2C, 0xE1, 0xD1, 0x1C, 0x24, 0x04, 0xFB, 0x05, 0x66, ++0x00, 0x24, 0x76, 0x7B, 0xCD, 0xF8, 0x00, 0xC0, 0xCD, 0xE9, 0x01, 0x64, 0x43, 0x46, 0xE3, 0xF7, 0xCF, 0xF9, 0xD4, 0xE7, ++0x90, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0xB7, 0x6D, 0xDB, 0xB6, 0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x98, 0x80, ++0x20, 0x4D, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0xC0, 0xEB, 0xC0, 0x06, 0x00, 0x2B, 0x04, 0x46, 0x05, 0xEB, ++0x86, 0x06, 0x12, 0xDB, 0xC7, 0x00, 0x1B, 0x48, 0x31, 0x46, 0x3C, 0x1B, 0x05, 0xF0, 0x5C, 0xFA, 0x05, 0xEB, 0x84, 0x04, ++0x30, 0x46, 0x1C, 0x22, 0x00, 0x21, 0xE2, 0xF7, 0xC1, 0xF9, 0xFF, 0x23, 0xE3, 0x81, 0x23, 0x76, 0xE3, 0x76, 0xBD, 0xE8, ++0xF0, 0x81, 0xC0, 0xEB, 0xC0, 0x03, 0x05, 0xEB, 0x83, 0x03, 0xC7, 0x00, 0x1B, 0x7E, 0xFF, 0x2B, 0x0C, 0xD0, 0x3B, 0x1B, ++0x05, 0xEB, 0x83, 0x03, 0x5B, 0x7E, 0x00, 0x2B, 0xDF, 0xD0, 0x0C, 0x49, 0x0C, 0x48, 0x40, 0xF6, 0x5C, 0x32, 0x06, 0xF0, ++0x8F, 0xFE, 0xD8, 0xE7, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0x5A, 0x32, 0x06, 0xF0, 0x88, 0xFE, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE6, 0xDB, 0xCB, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0xA2, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xDF, 0xF8, 0x4C, 0x82, 0xDF, 0xF8, 0x24, 0xA2, 0xD8, 0xF8, 0x00, 0x20, 0x84, 0x4F, 0xB2, 0xF9, 0x00, 0x30, 0xC1, 0xEB, ++0xC1, 0x06, 0x00, 0x2B, 0x85, 0xB0, 0x0C, 0x46, 0x05, 0x46, 0x0A, 0xEB, 0x86, 0x06, 0x5F, 0xDB, 0x4F, 0xEA, 0xC4, 0x0B, ++0xAB, 0xEB, 0x04, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x4A, 0x7E, 0xDF, 0xF8, 0x1C, 0x92, 0x01, 0x32, ++0x03, 0xFB, 0x05, 0x73, 0xD2, 0xB2, 0x00, 0x20, 0x01, 0x2A, 0x4A, 0x76, 0x1E, 0x64, 0x83, 0xF8, 0x4D, 0x00, 0x6B, 0xD0, ++0xDF, 0xF8, 0x04, 0x82, 0x99, 0xF8, 0x5B, 0x10, 0x99, 0xF8, 0x5A, 0x30, 0x4F, 0xF4, 0x80, 0x70, 0xCD, 0xE9, 0x00, 0x31, ++0x6F, 0x49, 0x23, 0x46, 0x06, 0xF0, 0x12, 0xFC, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0x73, 0xFF, 0x21, 0x93, 0xF8, ++0xC0, 0x24, 0x83, 0xF8, 0x4E, 0x10, 0x4A, 0xB1, 0x69, 0x49, 0x93, 0xF8, 0xC1, 0x24, 0x8C, 0x20, 0x00, 0xFB, 0x02, 0x12, ++0x92, 0xF8, 0x70, 0x20, 0x01, 0x2A, 0x20, 0xD0, 0x65, 0x4B, 0x03, 0xF1, 0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, ++0xDA, 0x7E, 0xFF, 0x2A, 0x40, 0xF0, 0xAA, 0x80, 0x1C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0xD8, 0xF8, 0xB4, 0x30, 0x30, 0x46, ++0x98, 0x47, 0x5E, 0x4B, 0x1B, 0x7C, 0xAB, 0x42, 0x08, 0xD0, 0xFF, 0x2B, 0x06, 0xD0, 0xD8, 0xF8, 0x50, 0x30, 0x20, 0x46, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x93, 0xF8, 0x4D, 0x20, 0x42, 0xF0, ++0x10, 0x02, 0x83, 0xF8, 0x4D, 0x20, 0xE4, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x73, 0x1B, 0x6C, 0x5B, 0xB1, ++0x50, 0x49, 0x51, 0x48, 0x40, 0xF6, 0x6B, 0x32, 0x06, 0xF0, 0xF4, 0xFD, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x8D, 0xDA, 0xC4, 0xEB, 0xC4, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0xC4, 0x0B, 0x1B, 0x7E, 0xFF, 0x2B, ++0x86, 0xD1, 0x46, 0x49, 0x47, 0x48, 0x40, 0xF6, 0x6C, 0x32, 0x06, 0xF0, 0xDF, 0xFD, 0x7F, 0xE7, 0x99, 0xF8, 0x5A, 0x00, ++0x0A, 0x74, 0x42, 0x1C, 0xD8, 0xF8, 0x00, 0x30, 0xD2, 0xB2, 0x89, 0xF8, 0x5A, 0x20, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x28, 0xDB, 0x02, 0x2A, 0x3C, 0xD0, 0x3E, 0x48, 0x31, 0x46, 0x05, 0xF0, 0x77, 0xF9, 0x99, 0xF8, 0x58, 0x30, 0x13, 0xF0, ++0x0C, 0x0F, 0x0F, 0xD0, 0xD8, 0xF8, 0x00, 0x20, 0xD9, 0xF8, 0x20, 0x30, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x20, 0xDB, ++0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0x9E, 0x60, 0x9A, 0xF8, 0x19, 0x20, 0x6B, 0xE7, 0xD9, 0xF8, 0x2C, 0x30, ++0x8B, 0xB3, 0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0xDF, 0xF8, 0xD0, 0x80, 0x9A, 0xF8, 0x19, 0x20, 0xC9, 0xF8, ++0x2C, 0x60, 0x5F, 0xE7, 0x02, 0x2A, 0xD4, 0xD9, 0x40, 0xF6, 0x81, 0x32, 0x25, 0x49, 0x29, 0x48, 0x06, 0xF0, 0xA0, 0xFD, ++0x99, 0xF8, 0x5A, 0x20, 0xCB, 0xE7, 0x00, 0x2B, 0xDC, 0xD1, 0x21, 0x49, 0x25, 0x48, 0x03, 0x93, 0x4F, 0xF4, 0x39, 0x62, ++0x06, 0xF0, 0x94, 0xFD, 0x03, 0x9B, 0xD3, 0xE7, 0x22, 0x48, 0x05, 0xF0, 0x37, 0xF9, 0x16, 0x4B, 0x03, 0xF5, 0xA4, 0x51, ++0x93, 0xF8, 0x4D, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x4D, 0x20, 0x03, 0xF5, 0xA4, 0x63, 0x99, 0x42, 0xF5, 0xD1, ++0xB1, 0xE7, 0xDF, 0xF8, 0x74, 0x80, 0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0xD8, 0xF8, 0x9C, 0x30, 0x30, 0x46, ++0x98, 0x47, 0x9A, 0xF8, 0x19, 0x20, 0x2B, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x72, 0x12, 0x6C, 0xB2, 0x42, ++0x3F, 0xF4, 0x51, 0xAF, 0x03, 0xFB, 0x05, 0x77, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x10, 0x03, 0x87, 0xF8, 0x4D, 0x30, ++0x47, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0xE0, 0xA2, 0x15, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x38, 0x9D, 0x17, 0x00, ++0xB8, 0xA2, 0x15, 0x00, 0xD4, 0xA2, 0x15, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xBC, 0xA2, 0xDF, 0xF8, 0xB4, 0x82, 0xDA, 0xF8, 0x00, 0x30, ++0x4F, 0xF4, 0xA4, 0x69, 0xB3, 0xF9, 0x00, 0x30, 0x09, 0xFB, 0x00, 0xF9, 0x08, 0xEB, 0x09, 0x02, 0x00, 0x2B, 0x14, 0x6C, ++0x85, 0xB0, 0x05, 0x46, 0xC0, 0xF2, 0x99, 0x80, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x05, 0x86, 0x9A, 0x4F, 0x96, 0xF8, ++0x4D, 0x00, 0x21, 0x7C, 0x97, 0xF8, 0x5A, 0x30, 0x62, 0x7E, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x01, 0x97, 0xF8, 0x5B, 0x30, ++0x95, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x06, 0xF0, 0xEF, 0xFA, 0x09, 0xF1, 0x44, 0x01, 0x07, 0xF1, 0x10, 0x00, 0x41, 0x44, ++0x05, 0xF0, 0x0E, 0xF9, 0x96, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x01, 0x02, 0x86, 0xF8, 0x4D, 0x20, 0x9A, 0x07, 0x09, 0xD5, ++0x97, 0xF8, 0x5B, 0x30, 0x97, 0xF8, 0x5A, 0x20, 0x01, 0x3B, 0xDB, 0xB2, 0x01, 0x2A, 0x87, 0xF8, 0x5B, 0x30, 0x5D, 0xD9, ++0xDF, 0xF8, 0x3C, 0xB2, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x05, 0x85, 0x00, 0x23, 0x85, 0xF8, 0x4D, 0x30, 0x2B, 0x64, ++0x66, 0x7E, 0x23, 0x7C, 0x01, 0x3E, 0xF6, 0xB2, 0x66, 0x76, 0x00, 0x2B, 0x45, 0xD0, 0x95, 0xF8, 0x63, 0x30, 0xE2, 0x7E, ++0x9A, 0x42, 0x00, 0xF0, 0x85, 0x80, 0x7C, 0x4B, 0x03, 0xF1, 0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, 0xD8, 0x7E, ++0xFF, 0x28, 0x40, 0xF0, 0xBD, 0x80, 0x1C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0x00, 0x2E, 0x4E, 0xD0, 0xDB, 0xF8, 0xB4, 0x30, ++0x20, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x97, 0xF8, 0x5A, 0x30, 0x00, 0x20, 0xB8, 0x62, 0x00, 0x2B, ++0x59, 0xD0, 0x21, 0x7E, 0xDB, 0xF8, 0x9C, 0x50, 0x6C, 0x4A, 0x02, 0x29, 0x01, 0xF1, 0x01, 0x03, 0x00, 0xF0, 0xC0, 0x80, ++0xC3, 0xEB, 0xC3, 0x06, 0x02, 0xEB, 0x86, 0x06, 0xD8, 0x00, 0x36, 0x7E, 0xFF, 0x2E, 0x40, 0xF0, 0xC3, 0x80, 0x01, 0x29, ++0x01, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, 0xC3, 0xEB, 0xC3, 0x01, 0x02, 0xEB, 0x81, 0x01, 0xD8, 0x00, 0x09, 0x7E, ++0xFF, 0x29, 0x08, 0xBF, 0x00, 0x20, 0x40, 0xF0, 0xB3, 0x80, 0xA8, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0xCC, 0xD1, 0xDB, 0xF8, ++0x48, 0x30, 0x20, 0x7E, 0x98, 0x47, 0xC7, 0xE7, 0x00, 0x2B, 0x9F, 0xD1, 0x97, 0xF8, 0x58, 0x30, 0xDF, 0xF8, 0x78, 0xB1, ++0x5B, 0x06, 0x9B, 0xD5, 0x38, 0x6D, 0xDB, 0xF8, 0x5C, 0x30, 0x98, 0x47, 0x96, 0xE7, 0x00, 0x2C, 0x7F, 0xF4, 0x64, 0xAF, ++0x51, 0x49, 0x52, 0x48, 0x40, 0xF6, 0xC4, 0x32, 0x06, 0xF0, 0x8C, 0xFC, 0x5C, 0xE7, 0x50, 0x48, 0x21, 0x46, 0x05, 0xF0, ++0x83, 0xF8, 0x26, 0x74, 0x97, 0xF8, 0x5A, 0x30, 0xDA, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0xDB, 0xB2, 0x87, 0xF8, 0x5A, 0x30, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x0A, 0xDB, 0x03, 0xBB, 0xBB, 0x6A, 0xA3, 0x42, 0xA2, 0xD0, 0xFB, 0x6A, 0xA3, 0x42, ++0x31, 0xD0, 0x66, 0x7E, 0x00, 0x2E, 0xC8, 0xD0, 0x94, 0xE7, 0x01, 0x2B, 0xF2, 0xD9, 0x3F, 0x49, 0x41, 0x48, 0x4F, 0xF4, ++0x40, 0x62, 0x06, 0xF0, 0x67, 0xFC, 0x97, 0xF8, 0x5A, 0x30, 0xE9, 0xE7, 0xDB, 0xF8, 0x94, 0x30, 0x08, 0xEB, 0x09, 0x00, ++0x98, 0x47, 0x66, 0x7E, 0xFF, 0x23, 0xE3, 0x76, 0x00, 0x2E, 0x7F, 0xF4, 0x7F, 0xAF, 0xCC, 0xE7, 0x38, 0x48, 0x04, 0xF0, ++0xFD, 0xFF, 0x38, 0x4B, 0x03, 0xF5, 0xA4, 0x51, 0x93, 0xF8, 0x4D, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x4D, 0x20, ++0x03, 0xF5, 0xA4, 0x63, 0x99, 0x42, 0xF5, 0xD1, 0x3B, 0x6D, 0x00, 0x2B, 0xCB, 0xD1, 0xDB, 0xF8, 0x34, 0x30, 0x98, 0x47, ++0xC7, 0xE7, 0x21, 0x7E, 0x27, 0x4A, 0x02, 0x29, 0x01, 0xF1, 0x01, 0x03, 0x29, 0xD0, 0xC3, 0xEB, 0xC3, 0x05, 0x02, 0xEB, ++0x85, 0x05, 0xD8, 0x00, 0x2D, 0x7E, 0xFF, 0x2D, 0x35, 0xD1, 0x01, 0x29, 0x01, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, ++0xC3, 0xEB, 0xC3, 0x01, 0x02, 0xEB, 0x81, 0x01, 0xD8, 0x00, 0x09, 0x7E, 0xFF, 0x29, 0x08, 0xBF, 0x00, 0x22, 0x26, 0xD1, ++0xFA, 0x62, 0xAE, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x80, 0x03, 0x6C, 0xA3, 0x42, 0x3F, 0xF4, 0x3E, 0xAF, ++0x66, 0xB1, 0xDB, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0x7F, 0xF4, 0x38, 0xAF, 0x85, 0xE7, 0x13, 0x7E, ++0xFF, 0x2B, 0x0E, 0xD1, 0x01, 0x23, 0xDD, 0xE7, 0xDB, 0xF8, 0x94, 0x30, 0x98, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0x7F, 0xF4, ++0x2B, 0xAF, 0x78, 0xE7, 0x13, 0x7E, 0xFF, 0x2B, 0x07, 0xD1, 0x01, 0x23, 0x48, 0xE7, 0x00, 0x23, 0x18, 0x46, 0xC3, 0x1A, ++0x02, 0xEB, 0x83, 0x02, 0xD4, 0xE7, 0x03, 0x46, 0xC0, 0x1A, 0x02, 0xEB, 0x80, 0x00, 0x48, 0xE7, 0x30, 0x9D, 0x17, 0x00, ++0x08, 0xA3, 0x15, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF8, 0xA2, 0x15, 0x00, 0x38, 0x9D, 0x17, 0x00, ++0x28, 0xA3, 0x15, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x43, 0x03, 0x46, 0x05, 0x78, 0x29, 0x4E, 0x2A, 0x4A, 0x04, 0x46, 0x53, 0xF8, 0x02, 0x0F, 0x97, 0x6A, ++0x59, 0x68, 0xB3, 0xF8, 0x08, 0xC0, 0xC5, 0xEB, 0xC5, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x04, 0x33, 0x03, 0xC3, 0xC5, 0xEB, ++0xC5, 0x02, 0x06, 0xEB, 0x82, 0x02, 0x97, 0x42, 0x85, 0xB0, 0xA3, 0xF8, 0x00, 0xC0, 0x02, 0xD0, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x83, 0x4F, 0xEA, 0xC5, 0x08, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x1A, 0x4F, 0xDF, 0xF8, 0x68, 0x90, 0x3B, 0x68, 0xD9, 0xF8, 0xA0, 0x22, 0x01, 0x33, 0x3B, 0x60, 0x90, 0x47, ++0xD9, 0xF8, 0x88, 0x32, 0x00, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x33, 0xB1, 0x11, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xE2, 0x7A, 0x23, 0x89, 0x00, 0x93, 0x00, 0x21, 0xCD, 0xE9, 0x01, 0x21, 0xA8, 0xEB, ++0x05, 0x05, 0xE3, 0x88, 0xA0, 0x78, 0xA2, 0x88, 0xE1, 0x78, 0x06, 0xEB, 0x85, 0x06, 0xE2, 0xF7, 0x91, 0xFE, 0xD9, 0xF8, ++0x3C, 0x33, 0x96, 0xF9, 0x0C, 0x00, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x12, 0x4D, ++0x12, 0x4A, 0x2B, 0x7C, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x03, 0x24, 0x06, 0x46, 0x22, 0x6C, 0x4A, 0xB1, 0x0F, 0x4C, ++0x18, 0x46, 0x63, 0x6D, 0x98, 0x47, 0xE3, 0x6C, 0x28, 0x7C, 0x31, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x05, 0x22, ++0x11, 0x46, 0x02, 0x23, 0x41, 0xF2, 0x17, 0x40, 0x04, 0xF0, 0x7E, 0xFA, 0x01, 0x22, 0x02, 0x70, 0x94, 0xF8, 0x63, 0x20, ++0x42, 0x70, 0x04, 0xF0, 0xA7, 0xFA, 0x03, 0x4C, 0xE9, 0xE7, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x6B, 0x4D, 0x2C, 0x69, 0x07, 0x46, 0x8B, 0x46, 0x91, 0x46, 0x8C, 0xB3, ++0x63, 0x68, 0xD0, 0xF8, 0x40, 0xA0, 0xD5, 0xF8, 0x28, 0x80, 0x8B, 0x42, 0x12, 0xD0, 0x05, 0xF1, 0x10, 0x06, 0xA3, 0xEB, ++0x0B, 0x03, 0x00, 0x2B, 0x21, 0x46, 0x30, 0x46, 0x26, 0xDA, 0x04, 0xF0, 0x33, 0xFF, 0x63, 0x7A, 0x23, 0xF0, 0x01, 0x03, ++0x63, 0x72, 0x2C, 0x69, 0xF4, 0xB1, 0x63, 0x68, 0x5B, 0x45, 0xEE, 0xD1, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x4F, 0xF0, ++0x00, 0x04, 0x1B, 0xD8, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x02, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, ++0xB8, 0xEB, 0x0A, 0x00, 0x03, 0xF1, 0x01, 0x03, 0x18, 0xBF, 0x01, 0x20, 0x85, 0xF8, 0x5B, 0x30, 0xBD, 0xE8, 0xF8, 0x8F, ++0xD0, 0xF8, 0x40, 0xA0, 0xD5, 0xF8, 0x28, 0x80, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x4F, 0xF0, 0x01, 0x04, 0xE3, 0xD9, ++0x97, 0xF8, 0x4E, 0x30, 0xFF, 0x2B, 0x26, 0xD0, 0x49, 0x4E, 0x59, 0x46, 0x73, 0x6F, 0x38, 0x46, 0x98, 0x47, 0x00, 0x2C, ++0x41, 0xD0, 0x97, 0xF8, 0x4D, 0x30, 0x97, 0xF8, 0xC0, 0x24, 0x43, 0xF0, 0x04, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x82, 0xB1, ++0x42, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x06, 0xD1, ++0xBB, 0x6C, 0x4B, 0x45, 0x03, 0xD0, 0xA3, 0xEB, 0x09, 0x02, 0x32, 0x2A, 0x5D, 0xD4, 0xB8, 0xEB, 0x0A, 0x00, 0x18, 0xBF, ++0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x97, 0xF8, 0xC0, 0x34, 0xB3, 0xB3, 0x35, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, ++0x01, 0xFB, 0x03, 0x21, 0x91, 0xF8, 0x70, 0x10, 0x01, 0x29, 0x35, 0xD0, 0x00, 0x2C, 0x4F, 0xD1, 0x30, 0x48, 0x07, 0xF1, ++0x44, 0x01, 0x04, 0xF0, 0xC9, 0xFE, 0x97, 0xF8, 0x4D, 0x30, 0x03, 0xF0, 0xFE, 0x03, 0x43, 0xF0, 0x02, 0x03, 0x87, 0xF8, ++0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, 0x01, 0x33, 0x85, 0xF8, 0x5B, 0x30, 0xD7, 0xE7, 0x97, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0xE8, 0xD0, 0x24, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, ++0xDE, 0xD1, 0xF3, 0x6A, 0x49, 0x46, 0x00, 0x22, 0x38, 0x46, 0x98, 0x47, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x08, 0x03, ++0xDD, 0xE7, 0x00, 0x2C, 0xD2, 0xD0, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x04, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0xB6, 0xE7, ++0x97, 0xF8, 0x4D, 0x10, 0xC8, 0x06, 0x0B, 0xD5, 0x12, 0x4E, 0x38, 0x46, 0xD6, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x97, 0xF8, ++0x4D, 0x30, 0x23, 0xF0, 0x10, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x8A, 0xE7, 0x4E, 0x06, 0x10, 0xD4, 0x54, 0xB9, 0x0B, 0x4E, ++0xD7, 0xE7, 0xA9, 0xEB, 0x03, 0x03, 0x32, 0x2B, 0x9D, 0xD5, 0xC7, 0xF8, 0x48, 0x90, 0x9A, 0xE7, 0x97, 0xF8, 0x4D, 0x10, ++0x41, 0xF0, 0x04, 0x01, 0x87, 0xF8, 0x4D, 0x10, 0x85, 0xE7, 0x03, 0x4E, 0x38, 0x46, 0x33, 0x6F, 0x98, 0x47, 0x72, 0xE7, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x4D, 0x4D, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x2B, 0xD9, 0x90, 0xF8, 0x4D, 0x20, 0x04, 0x46, 0xD0, 0x06, 0x0F, 0xD5, ++0x49, 0x4B, 0x03, 0xF1, 0x54, 0x00, 0x19, 0x7E, 0xFF, 0x29, 0x02, 0xD0, 0xD9, 0x7E, 0xFF, 0x29, 0x3B, 0xD1, 0x1C, 0x33, ++0x98, 0x42, 0xF6, 0xD1, 0x02, 0xF0, 0xEF, 0x02, 0x84, 0xF8, 0x4D, 0x20, 0x91, 0x07, 0x14, 0xD4, 0x53, 0x07, 0x6E, 0x6A, ++0x44, 0xBF, 0x22, 0xF0, 0x04, 0x02, 0x84, 0xF8, 0x4D, 0x20, 0x26, 0xB1, 0xF2, 0x68, 0x04, 0xF1, 0x44, 0x03, 0x9A, 0x42, ++0x09, 0xD0, 0x3B, 0x4B, 0x61, 0x6A, 0xDB, 0x6A, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xBD, 0xE8, ++0xF0, 0x81, 0xD4, 0xF8, 0x48, 0x80, 0x67, 0x6A, 0xA8, 0xEB, 0x07, 0x03, 0x00, 0x2B, 0x20, 0xDB, 0xA7, 0xEB, 0x08, 0x03, ++0x00, 0x2B, 0x29, 0xDB, 0x30, 0x4D, 0x6B, 0x6B, 0x98, 0x47, 0xEB, 0x6A, 0x61, 0x6A, 0x20, 0x46, 0x00, 0x22, 0x98, 0x47, ++0x2D, 0x4A, 0xD5, 0xF8, 0x84, 0x30, 0x11, 0x69, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x2A, 0x4A, ++0x27, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x20, 0xD3, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x20, ++0xBA, 0xE7, 0xE2, 0xF7, 0xA5, 0xFD, 0xA7, 0xF5, 0x7A, 0x67, 0xA7, 0xEB, 0x08, 0x07, 0x38, 0x1A, 0x00, 0x28, 0x0C, 0xDB, ++0x67, 0x6A, 0xD4, 0xF8, 0x48, 0x80, 0xD1, 0xE7, 0xE2, 0xF7, 0x98, 0xFD, 0xA8, 0xF5, 0x7A, 0x68, 0xA8, 0xEB, 0x07, 0x07, ++0x3F, 0x1A, 0x00, 0x2F, 0xCC, 0xDA, 0x67, 0x6A, 0xA7, 0x64, 0xE2, 0xF7, 0x8D, 0xFD, 0x73, 0x68, 0xFF, 0x1A, 0x3F, 0x1A, ++0xB7, 0xF5, 0x7A, 0x6F, 0xB5, 0xD5, 0xA4, 0x6C, 0xE2, 0xF7, 0x84, 0xFD, 0xAB, 0x6C, 0xA4, 0xF5, 0x7A, 0x64, 0x24, 0x1A, ++0xB3, 0x42, 0x74, 0x60, 0xAB, 0xD1, 0x0D, 0x4C, 0x0F, 0x48, 0xD4, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x0B, 0x4B, 0x71, 0x68, ++0x1B, 0x69, 0xAE, 0x64, 0xCB, 0x1A, 0x14, 0x2B, 0x05, 0xD4, 0xD4, 0xF8, 0xE0, 0x31, 0x09, 0x48, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x6B, 0x6C, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x18, 0x88, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x45, 0x4D, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x04, 0x46, 0x90, 0xF8, 0x4D, 0x30, 0x51, 0xD9, 0x9E, 0x06, 0x04, 0xD5, ++0x41, 0x4B, 0x9B, 0x6F, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x67, 0x6A, 0x13, 0xF0, 0x04, 0x06, 0x3D, 0xD1, 0x99, 0x07, ++0x42, 0xD5, 0x03, 0xF0, 0xFD, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x20, 0x01, 0x3A, 0xD2, 0xB2, 0x85, 0xF8, ++0x5B, 0x20, 0x4A, 0xB9, 0x95, 0xF8, 0x58, 0x20, 0x52, 0x06, 0x5B, 0xD5, 0x34, 0x4B, 0x28, 0x6D, 0xDB, 0x6D, 0x98, 0x47, ++0x94, 0xF8, 0x4D, 0x30, 0xD4, 0xF8, 0x48, 0x80, 0x13, 0xF0, 0x08, 0x02, 0x42, 0xD0, 0x94, 0xF8, 0x62, 0x20, 0x23, 0xF0, ++0x08, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x00, 0x2A, 0x4A, 0xD0, 0x02, 0x2A, 0x0A, 0xBF, 0xB4, 0xF8, 0xD2, 0x30, 0x4F, 0xF4, ++0xC8, 0x33, 0x9B, 0x02, 0xA8, 0xEB, 0x03, 0x08, 0xB6, 0xB1, 0xEB, 0x6A, 0x26, 0x4A, 0x15, 0x69, 0x93, 0xB9, 0x24, 0x4E, ++0x73, 0x6B, 0x98, 0x47, 0xD6, 0xF8, 0x84, 0x30, 0xA5, 0xEB, 0x08, 0x02, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x13, 0xF0, 0x01, 0x02, 0x23, 0xD0, 0x23, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0xBD, 0xE8, 0xF0, 0x81, ++0x9A, 0x07, 0xFB, 0xD5, 0x23, 0xF0, 0x02, 0x03, 0x80, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, 0x01, 0x3B, 0xDB, 0xB2, ++0x85, 0xF8, 0x5B, 0x30, 0x00, 0x2B, 0xEF, 0xD1, 0x95, 0xF8, 0x58, 0x30, 0x5F, 0x06, 0xEB, 0xD5, 0x10, 0x4B, 0x28, 0x6D, ++0xDB, 0x6D, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x0D, 0x4B, 0x39, 0x46, 0xDB, 0x6A, 0x20, 0x46, 0x98, 0x47, 0xC7, 0xE7, ++0x0A, 0x4B, 0x39, 0x46, 0xDB, 0x6A, 0x20, 0x46, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0xD3, 0xE7, 0x01, 0x26, 0xA7, 0xE7, ++0x07, 0x4A, 0x94, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x9B, 0x68, 0xB2, 0xE7, 0x00, 0xBF, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0x28, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x6C, 0x05, 0x46, 0x3E, 0xDB, 0x24, 0x4E, 0x96, 0xF8, ++0x58, 0x20, 0x12, 0xF0, 0x20, 0x04, 0x03, 0xD1, 0x96, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x01, 0xD8, 0xBD, 0xE8, 0xF0, 0x81, ++0x14, 0x23, 0x22, 0x46, 0x21, 0x46, 0x46, 0x20, 0x95, 0xF8, 0x6C, 0x80, 0x04, 0xF0, 0x2E, 0xF8, 0x04, 0x70, 0x95, 0xF8, ++0x63, 0x10, 0x41, 0x70, 0x39, 0x79, 0x19, 0x4A, 0x81, 0x70, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x08, 0x28, 0x7A, 0x79, ++0xC2, 0x70, 0xD8, 0xF8, 0x08, 0x20, 0x15, 0x4D, 0xB7, 0xF8, 0x06, 0xC0, 0x3C, 0x89, 0x79, 0x89, 0x01, 0x81, 0xA2, 0xF5, ++0x9C, 0x52, 0x08, 0x3A, 0xA5, 0xFB, 0x02, 0x52, 0x92, 0x09, 0xA0, 0xF8, 0x04, 0xC0, 0xC4, 0x80, 0xC2, 0x60, 0x3A, 0x7B, ++0x02, 0x74, 0x04, 0xF0, 0x3B, 0xF8, 0x96, 0xF8, 0x58, 0x30, 0x43, 0xF0, 0x20, 0x03, 0x86, 0xF8, 0x58, 0x30, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0x2F, 0xBE, 0xD1, 0x07, 0x49, 0x07, 0x48, 0x40, 0xF6, 0x71, 0x52, 0x06, 0xF0, 0xDD, 0xF8, 0xB7, 0xE7, ++0x38, 0x36, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xD3, 0x4D, 0x62, 0x10, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0xA0, 0x15, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x0A, 0x4B, 0x9B, 0x6A, 0x83, 0xB1, 0x1A, 0x7E, 0x02, 0x2A, 0x05, 0xD8, ++0x00, 0x6C, 0xC0, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x9B, 0x7E, 0x90, 0xF8, 0x63, 0x00, 0x18, 0x1A, ++0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x18, 0x46, 0x70, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x10, 0x4A, 0x93, 0x6A, ++0xDB, 0xB1, 0x19, 0x7E, 0x02, 0x29, 0x0E, 0xD8, 0x00, 0x6C, 0xC0, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x88, 0xB1, ++0xD2, 0x6A, 0x7A, 0xB1, 0x18, 0x7C, 0xA0, 0xF1, 0x06, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x90, 0xF8, ++0x63, 0x10, 0x98, 0x7E, 0x40, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x00, 0x28, 0xED, 0xD1, 0x70, 0x47, 0x18, 0x46, ++0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x0E, 0x4B, 0x9B, 0x6A, 0x23, 0xB1, 0x02, 0x6C, 0x98, 0x88, 0x91, 0x88, ++0x88, 0x42, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x58, 0x7B, 0x51, 0x7B, 0x88, 0x42, 0xF9, 0xD1, 0xD8, 0x88, 0xD1, 0x88, ++0x88, 0x42, 0xF5, 0xD1, 0x18, 0x89, 0x11, 0x89, 0x88, 0x42, 0xF1, 0xD1, 0x5B, 0x89, 0x50, 0x89, 0x18, 0x1A, 0xB0, 0xFA, ++0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x43, 0x7E, 0xDB, 0xB1, 0x0E, 0x4B, 0x30, 0xB4, ++0x7F, 0x21, 0x03, 0xF5, 0xA4, 0x54, 0x1A, 0x6C, 0x82, 0x42, 0x08, 0xD0, 0x03, 0xF5, 0xA4, 0x63, 0xA3, 0x42, 0xF8, 0xD1, ++0x7F, 0x29, 0x30, 0xBC, 0x18, 0xBF, 0x01, 0x73, 0x70, 0x47, 0x93, 0xF9, 0x66, 0x20, 0x93, 0xF9, 0x65, 0x50, 0xAA, 0x42, ++0xA8, 0xBF, 0x2A, 0x46, 0x91, 0x42, 0xA8, 0xBF, 0x11, 0x46, 0xEB, 0xE7, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x70, 0xB5, 0x11, 0x4E, 0x11, 0x4A, 0xD6, 0xF8, 0x4C, 0x32, 0x04, 0x46, 0x98, 0x47, 0xD0, 0xB1, 0x0F, 0x4B, 0x10, 0x4D, ++0x5B, 0x78, 0x00, 0x22, 0x2A, 0x77, 0x23, 0xB1, 0x0E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x2B, 0x7A, ++0x0B, 0xB1, 0x01, 0x3B, 0x2B, 0x72, 0xD6, 0xF8, 0xD8, 0x31, 0x0A, 0x48, 0x98, 0x47, 0x00, 0x23, 0x6B, 0x77, 0x63, 0x68, ++0x23, 0xF4, 0x01, 0x73, 0x23, 0xF0, 0x02, 0x03, 0x63, 0x60, 0x70, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xDD, 0xEA, 0x13, 0x00, ++0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x70, 0xB5, 0x14, 0x4D, ++0x14, 0x4A, 0xD5, 0xF8, 0x4C, 0x32, 0x04, 0x46, 0x98, 0x47, 0xF8, 0xB1, 0x12, 0x4A, 0x13, 0x4B, 0x52, 0x78, 0x01, 0x21, ++0x19, 0x77, 0x22, 0xB1, 0x11, 0x49, 0x0A, 0x68, 0x22, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x1A, 0x7A, 0x0A, 0xB1, 0x01, 0x3A, ++0x1A, 0x72, 0x0E, 0x4A, 0x0E, 0x49, 0x12, 0x68, 0x09, 0x69, 0xD0, 0x8E, 0x5C, 0x61, 0x04, 0x26, 0x5E, 0x77, 0x01, 0x44, ++0xD5, 0xF8, 0xE0, 0x21, 0x0A, 0x48, 0x90, 0x47, 0x63, 0x68, 0x43, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x70, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x3D, 0xEB, 0x13, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, ++0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4A, 0x0B, 0x46, 0x0C, 0x46, ++0x05, 0x46, 0x0F, 0x49, 0x02, 0x20, 0x05, 0xF0, 0xB3, 0xFD, 0x0E, 0x4B, 0x0E, 0x4A, 0xD3, 0xF8, 0x4C, 0x32, 0x21, 0x46, ++0x28, 0x46, 0x98, 0x47, 0x30, 0xB1, 0x0C, 0x4A, 0x13, 0x7A, 0x23, 0xB1, 0x01, 0x3B, 0xDB, 0xB2, 0x13, 0x72, 0x03, 0xB1, ++0x38, 0xBD, 0x01, 0x23, 0x13, 0x70, 0x51, 0x88, 0xBD, 0xE8, 0x38, 0x40, 0x00, 0x22, 0x32, 0x20, 0x03, 0xF0, 0x4A, 0xBF, ++0x68, 0xA3, 0x15, 0x00, 0x44, 0xA3, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xB1, 0xEB, 0x13, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x38, 0xB5, 0x18, 0x4A, 0x0B, 0x46, 0x0C, 0x46, 0x05, 0x46, 0x17, 0x49, 0x02, 0x20, 0x05, 0xF0, 0x87, 0xFD, 0x16, 0x4B, ++0x16, 0x4A, 0xD3, 0xF8, 0x4C, 0x32, 0x21, 0x46, 0x28, 0x46, 0x98, 0x47, 0xF8, 0xB1, 0x14, 0x48, 0x03, 0x7A, 0xBB, 0xB9, ++0x13, 0x4B, 0x9B, 0x68, 0x63, 0xB1, 0x93, 0xF8, 0x62, 0x20, 0x32, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x1A, 0xB1, 0x5A, 0x68, ++0x22, 0xF0, 0x0E, 0x02, 0x5A, 0x60, 0x1B, 0x68, 0x00, 0x2B, 0xF2, 0xD1, 0x00, 0x22, 0x02, 0x70, 0x41, 0x88, 0xBD, 0xE8, ++0x38, 0x40, 0x32, 0x20, 0x03, 0xF0, 0x14, 0xBF, 0x01, 0x3B, 0xDB, 0xB2, 0x03, 0x72, 0x00, 0x2B, 0xE2, 0xD0, 0x38, 0xBD, ++0x78, 0xA3, 0x15, 0x00, 0x44, 0xA3, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x09, 0xEC, 0x13, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x38, 0xB5, 0x11, 0xF4, 0x00, 0x03, 0x04, 0x46, 0x2A, 0xD1, 0x90, 0xF8, 0x6B, 0x00, 0x25, 0x49, ++0x01, 0x30, 0xC0, 0xB2, 0x09, 0x68, 0x84, 0xF8, 0x6B, 0x00, 0x49, 0x78, 0x81, 0x42, 0x29, 0xD0, 0x94, 0xF8, 0x64, 0x50, ++0x00, 0x2D, 0x34, 0xD1, 0x1F, 0x4A, 0x20, 0x4B, 0x52, 0x78, 0x01, 0x21, 0x19, 0x77, 0x22, 0xB1, 0x1E, 0x49, 0x0A, 0x68, ++0x22, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x1A, 0x7A, 0x0A, 0xB1, 0x01, 0x3A, 0x1A, 0x72, 0x1B, 0x4A, 0x1B, 0x48, 0xD2, 0xF8, ++0xD8, 0x21, 0x00, 0x21, 0x59, 0x77, 0x90, 0x47, 0x63, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x28, 0x46, 0x38, 0xBD, ++0x28, 0xB1, 0x00, 0x23, 0x01, 0x25, 0x80, 0xF8, 0x6B, 0x30, 0x28, 0x46, 0x38, 0xBD, 0x01, 0x25, 0x28, 0x46, 0x38, 0xBD, ++0x11, 0x49, 0x84, 0xF8, 0x6B, 0x30, 0x4F, 0xF4, 0x80, 0x60, 0x05, 0xF0, 0x11, 0xFD, 0x0C, 0x4B, 0x20, 0x46, 0xD3, 0xF8, ++0xBC, 0x31, 0x01, 0x25, 0x98, 0x47, 0x28, 0x46, 0x38, 0xBD, 0x11, 0x46, 0x1D, 0x46, 0x94, 0xF8, 0x6C, 0x00, 0x22, 0x46, ++0xF1, 0xF7, 0xD0, 0xF9, 0x28, 0x46, 0x38, 0xBD, 0xC8, 0x35, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x34, 0x04, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x28, 0x9E, 0x17, 0x00, 0x4C, 0xA3, 0x15, 0x00, 0x70, 0xB5, 0x13, 0x4D, ++0x2B, 0x78, 0x13, 0xB3, 0x2B, 0x7F, 0x03, 0xB3, 0x11, 0x4A, 0x12, 0x49, 0x13, 0x68, 0x8C, 0x68, 0x43, 0xF0, 0x04, 0x03, ++0x00, 0x21, 0x13, 0x60, 0x29, 0x72, 0xB4, 0xB1, 0x0E, 0x4E, 0x94, 0xF8, 0x62, 0x30, 0x7B, 0xB9, 0x94, 0xF8, 0x64, 0x30, ++0x63, 0xB1, 0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x22, 0x46, 0x07, 0xD0, 0xD6, 0xF8, 0x34, 0x12, 0xF1, 0xF7, 0xA0, 0xF9, ++0x10, 0xB9, 0x2B, 0x7A, 0x01, 0x33, 0x2B, 0x72, 0x24, 0x68, 0x00, 0x2C, 0xE9, 0xD1, 0x70, 0xBD, 0x1C, 0x9E, 0x17, 0x00, ++0x4C, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x12, 0x4D, 0x2B, 0x7F, 0xFB, 0xB9, ++0x11, 0x49, 0x12, 0x48, 0x0A, 0x68, 0x84, 0x68, 0x2B, 0x72, 0x22, 0xF0, 0x04, 0x02, 0x0A, 0x60, 0xB4, 0xB1, 0x0F, 0x4E, ++0x94, 0xF8, 0x62, 0x30, 0x7B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x63, 0xB1, 0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x22, 0x46, ++0x07, 0xD0, 0xD6, 0xF8, 0x58, 0x12, 0xF1, 0xF7, 0x73, 0xF9, 0x10, 0xB9, 0x2B, 0x7A, 0x01, 0x33, 0x2B, 0x72, 0x24, 0x68, ++0x00, 0x2C, 0xE9, 0xD1, 0x70, 0xBD, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x2E, 0x4B, 0x2E, 0x4D, 0x1B, 0x68, 0x2E, 0x4A, 0x1B, 0x78, 0xD2, 0xF8, 0xF8, 0x21, ++0x01, 0x2B, 0x6B, 0x68, 0x04, 0x46, 0x03, 0xF0, 0x20, 0x03, 0x44, 0xD0, 0x13, 0x43, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, ++0x94, 0xF8, 0xAC, 0x30, 0x53, 0xB1, 0x27, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x13, 0xB1, 0x94, 0xF8, 0x64, 0x30, 0x33, 0xBB, ++0x00, 0x23, 0x6B, 0x77, 0x63, 0x60, 0x70, 0xBD, 0x21, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0xF6, 0xD0, 0x94, 0xF8, ++0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, 0xC0, 0xB1, 0x1D, 0x4B, 0x1A, 0x68, 0x92, 0x01, 0x05, 0xD4, 0x1B, 0x68, 0x9B, 0x01, ++0x11, 0xD4, 0x95, 0xF8, 0x24, 0x30, 0x73, 0xB1, 0x6B, 0x7F, 0x05, 0x2B, 0x05, 0xD1, 0x63, 0x68, 0x00, 0x22, 0x23, 0xF0, ++0x02, 0x03, 0x63, 0x60, 0x6A, 0x77, 0x15, 0x4B, 0xBD, 0xE8, 0x70, 0x40, 0xD3, 0xF8, 0x50, 0x32, 0x18, 0x47, 0x13, 0x4B, ++0x13, 0x4A, 0x19, 0x68, 0x10, 0x4B, 0xC9, 0x8E, 0x6C, 0x61, 0x01, 0x20, 0x68, 0x77, 0x12, 0x69, 0xD3, 0xF8, 0xE0, 0x31, ++0x0F, 0x48, 0xBD, 0xE8, 0x70, 0x40, 0x11, 0x44, 0x18, 0x47, 0x13, 0x43, 0x01, 0xD0, 0x00, 0x20, 0xBA, 0xE7, 0xE9, 0xF7, ++0x37, 0xFD, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0xB4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0x28, 0x22, 0x20, 0x46, 0x00, 0x21, 0xE1, 0xF7, ++0x5F, 0xF9, 0x04, 0x4A, 0x01, 0x23, 0xD2, 0xF8, 0x38, 0x22, 0x22, 0x61, 0x23, 0x77, 0x10, 0xBD, 0x1C, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x4C, 0x23, 0x78, 0x33, 0xB9, 0x0B, 0x4B, 0xD3, 0xF8, 0xF8, 0x31, 0x98, 0x47, ++0x08, 0xB9, 0x00, 0x20, 0x10, 0xBD, 0x63, 0x68, 0x00, 0x2B, 0xFA, 0xD1, 0x07, 0x4B, 0x9B, 0x68, 0x13, 0xB9, 0x05, 0xE0, ++0x1B, 0x68, 0x1B, 0xB1, 0x5A, 0x68, 0x00, 0x2A, 0xFA, 0xD0, 0xF0, 0xE7, 0x01, 0x20, 0x10, 0xBD, 0x1C, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x08, 0x4B, 0x09, 0x4A, 0x1B, 0x68, 0x51, 0x80, 0x1B, 0x78, 0x02, 0x2B, ++0x07, 0x4B, 0x03, 0xD0, 0x07, 0x49, 0x00, 0x28, 0x18, 0xBF, 0x0B, 0x46, 0x00, 0x20, 0x10, 0x72, 0x4F, 0xF4, 0x00, 0x01, ++0x18, 0x47, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x09, 0xEC, 0x13, 0x00, 0xB1, 0xEB, 0x13, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x92, 0xF8, 0x6C, 0x30, 0x42, 0x4C, 0x43, 0x4E, 0x51, 0x68, 0x4F, 0xF4, 0x1E, 0x75, 0x91, 0x46, ++0x05, 0xFB, 0x03, 0x43, 0x32, 0x78, 0x1D, 0x8C, 0x21, 0xF0, 0x01, 0x07, 0xC9, 0xF8, 0x04, 0x70, 0x00, 0x2A, 0x49, 0xD0, ++0x04, 0x46, 0x00, 0x28, 0x46, 0xD0, 0x99, 0xF8, 0x6A, 0x30, 0x00, 0x2B, 0x44, 0xD0, 0x00, 0xF1, 0x04, 0x08, 0x98, 0xF8, ++0x00, 0x30, 0x03, 0xF0, 0xFE, 0x03, 0xB3, 0xEB, 0xD5, 0x0F, 0x4F, 0xEA, 0xD5, 0x00, 0x31, 0xD8, 0x61, 0x78, 0x04, 0x39, ++0x19, 0x44, 0x88, 0x42, 0x2C, 0xD8, 0x20, 0x44, 0xC3, 0x1A, 0x05, 0xF0, 0x07, 0x05, 0x59, 0x79, 0x01, 0x23, 0x03, 0xFA, ++0x05, 0xF5, 0x29, 0x42, 0x22, 0xD0, 0x2C, 0x4B, 0x19, 0x68, 0x8A, 0x05, 0x03, 0xD5, 0x19, 0x68, 0x21, 0xF4, 0x00, 0x71, ++0x19, 0x60, 0x29, 0x4C, 0xD4, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x28, 0x48, 0xD9, 0xF8, 0x04, 0x30, 0x00, 0x68, 0x27, 0x49, ++0xD4, 0xF8, 0xE0, 0x41, 0x40, 0x8F, 0x43, 0xF0, 0x04, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0x09, 0x69, 0xC6, 0xF8, 0x14, 0x90, ++0x06, 0x23, 0x73, 0x77, 0x01, 0x44, 0x23, 0x46, 0x20, 0x48, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0xD9, 0xF8, 0x04, 0x30, ++0x23, 0xF0, 0x04, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0xBD, 0xE8, 0xF0, 0x87, 0x03, 0x79, 0x00, 0xF1, 0x04, 0x08, 0xD8, 0x07, ++0x1E, 0xD5, 0x14, 0x4B, 0x47, 0xF0, 0x02, 0x07, 0xC9, 0xF8, 0x04, 0x70, 0x19, 0x68, 0x89, 0x05, 0x03, 0xD5, 0x19, 0x68, ++0x21, 0xF4, 0x00, 0x71, 0x19, 0x60, 0x73, 0x7F, 0x00, 0x2B, 0xA8, 0xD1, 0x0E, 0x4B, 0x0F, 0x49, 0x1B, 0x68, 0x09, 0x69, ++0x1F, 0x8F, 0x0B, 0x4B, 0xC6, 0xF8, 0x14, 0x90, 0x05, 0x20, 0x70, 0x77, 0xD3, 0xF8, 0xE0, 0x31, 0x0A, 0x48, 0x39, 0x44, ++0x98, 0x47, 0x98, 0xE7, 0x21, 0xF0, 0x03, 0x01, 0xC9, 0xF8, 0x04, 0x10, 0x93, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x28, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x21, 0x4E, 0x14, 0x46, 0x52, 0x68, 0x35, 0x78, 0x22, 0xF0, 0x01, 0x03, ++0x63, 0x60, 0x00, 0x2D, 0x32, 0xD0, 0x0F, 0x46, 0x94, 0xF8, 0x6A, 0x10, 0xA1, 0xB9, 0x00, 0x28, 0x2E, 0xD0, 0x1B, 0x4A, ++0x1B, 0x49, 0x10, 0x68, 0x1B, 0x4A, 0x00, 0x8F, 0xD2, 0xF8, 0xE0, 0x21, 0x43, 0xF0, 0x02, 0x03, 0x63, 0x60, 0x09, 0x69, ++0x74, 0x61, 0x05, 0x23, 0x01, 0x44, 0x73, 0x77, 0x06, 0xF1, 0x0C, 0x00, 0x90, 0x47, 0x63, 0x68, 0xAF, 0xB1, 0x13, 0x4D, ++0x43, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xD5, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x0D, 0x4B, 0x0E, 0x4A, 0x1B, 0x68, 0x11, 0x69, ++0x58, 0x8F, 0x74, 0x61, 0x06, 0x22, 0xD5, 0xF8, 0xE0, 0x31, 0x72, 0x77, 0x01, 0x44, 0xBD, 0xE8, 0xF0, 0x41, 0x0A, 0x48, ++0x18, 0x47, 0x23, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x22, 0xF0, 0x03, 0x03, 0x00, 0x2F, 0xF6, 0xD0, ++0xDF, 0xE7, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x28, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x21, 0x4D, 0x2B, 0x78, 0xAB, 0xB1, 0x03, 0x79, 0x06, 0x88, 0xDF, 0x07, ++0x14, 0x46, 0x12, 0xD5, 0x6B, 0x7F, 0x05, 0x2B, 0x07, 0xD1, 0x1D, 0x4B, 0x05, 0xF1, 0x0C, 0x00, 0xD3, 0xF8, 0xD8, 0x31, ++0x98, 0x47, 0x00, 0x23, 0x6B, 0x77, 0xB5, 0x04, 0x23, 0xD4, 0x63, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x63, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0x88, 0x05, 0xFB, 0xD4, 0x15, 0x4A, 0x15, 0x4B, 0x12, 0x68, 0x1B, 0x69, 0xD1, 0x8E, 0x11, 0x4F, 0x6C, 0x61, ++0x02, 0x22, 0x19, 0x44, 0x6A, 0x77, 0xD7, 0xF8, 0xE0, 0x31, 0x05, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0xB1, 0x04, 0x63, 0x68, ++0x0E, 0xD5, 0x5A, 0x07, 0x5C, 0xBF, 0x43, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xD7, 0xF8, 0x54, 0x32, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x94, 0xF8, 0x6A, 0x30, 0x00, 0x2B, 0xDB, 0xD0, 0xD6, 0xE7, 0x23, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x38, 0xB5, 0x23, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x3F, 0xD0, 0xFF, 0x28, 0x3D, 0xD0, 0xFF, 0x29, 0x3B, 0xD0, 0x20, 0x4A, ++0x20, 0x49, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x20, 0x4F, 0xF4, 0xA4, 0x64, 0x90, 0xF8, 0x22, 0x20, 0x04, 0xFB, ++0x02, 0x12, 0x92, 0xF8, 0x62, 0x10, 0x00, 0x29, 0x2B, 0xD1, 0x92, 0xF8, 0x64, 0x10, 0x41, 0xB3, 0x18, 0x48, 0x19, 0x49, ++0x00, 0x68, 0x09, 0x69, 0xC5, 0x8E, 0x18, 0x4C, 0x5A, 0x61, 0x03, 0x20, 0x58, 0x77, 0xD4, 0xF8, 0xE0, 0x21, 0x03, 0xF1, ++0x0C, 0x00, 0x29, 0x44, 0x90, 0x47, 0x14, 0x4B, 0x1B, 0x68, 0x5B, 0x07, 0x15, 0xD5, 0x13, 0x4B, 0x93, 0xF8, 0xB6, 0x30, ++0x73, 0xB1, 0x12, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x09, 0xD1, 0x10, 0x49, 0x11, 0x4A, 0x0B, 0x68, 0x23, 0xF4, ++0x00, 0x73, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0xD4, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x00, 0x20, ++0x38, 0xBD, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, ++0x90, 0xB3, 0x33, 0x40, 0x8C, 0x00, 0x32, 0x40, 0x3B, 0x4A, 0xDF, 0xF8, 0x1C, 0xC1, 0x13, 0x68, 0x3A, 0x49, 0xF0, 0xB5, ++0x3A, 0x4F, 0x3B, 0x4C, 0xB7, 0xF8, 0xB2, 0x00, 0x3A, 0x4D, 0x3B, 0x4E, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x23, 0x68, ++0x39, 0x4A, 0x43, 0xF0, 0x80, 0x53, 0x23, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x70, 0x23, 0xCC, 0xF8, 0x00, 0x30, ++0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0x10, 0x03, 0xCC, 0xF8, 0x00, 0x30, 0x2B, 0x68, 0x23, 0xF0, ++0xFC, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x0B, 0x68, 0x40, 0x09, 0x00, 0xF1, 0x20, 0x0C, 0xC3, 0xF3, 0x15, 0x03, ++0x43, 0xEA, 0x8C, 0x53, 0x0B, 0x60, 0x83, 0xB0, 0x33, 0x68, 0x29, 0x49, 0x1B, 0x78, 0xCD, 0xF8, 0x00, 0xC0, 0x02, 0x20, ++0x05, 0xF0, 0x0A, 0xFA, 0x32, 0x68, 0x13, 0x78, 0x01, 0x2B, 0x15, 0xD0, 0x02, 0x2B, 0x11, 0xD1, 0x23, 0x48, 0x24, 0x49, ++0x03, 0x68, 0x24, 0x4C, 0x1D, 0x4A, 0x43, 0xF4, 0x80, 0x33, 0x03, 0x60, 0x0B, 0x68, 0x3F, 0x20, 0x23, 0xF0, 0x00, 0x73, ++0x0B, 0x60, 0x20, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x03, 0xB0, 0xF0, 0xBD, 0x97, 0xF8, 0xB5, 0x10, ++0x69, 0xB1, 0x19, 0x49, 0x19, 0x48, 0x0B, 0x68, 0x23, 0xF0, 0x00, 0x73, 0x0B, 0x60, 0x2B, 0x68, 0x24, 0x21, 0x43, 0xF4, ++0x00, 0x13, 0x2B, 0x60, 0x01, 0x60, 0x13, 0x78, 0xD8, 0xE7, 0x12, 0x48, 0x12, 0x4E, 0x01, 0x68, 0x12, 0x4D, 0x41, 0xF0, ++0x00, 0x71, 0x01, 0x60, 0x04, 0x21, 0x31, 0x60, 0x2B, 0x60, 0x23, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, ++0x23, 0x60, 0x13, 0x78, 0xC6, 0xE7, 0x00, 0xBF, 0x90, 0x00, 0x32, 0x40, 0xF0, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0x74, 0x80, 0x32, 0x40, 0x6C, 0x00, 0x32, 0x40, 0x74, 0x36, 0x17, 0x00, 0x88, 0xA3, 0x15, 0x00, 0x5C, 0xA3, 0x15, 0x00, ++0x44, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x78, 0x00, 0x32, 0x40, ++0x15, 0x48, 0x16, 0x4A, 0x16, 0x49, 0x38, 0xB5, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x02, 0x20, 0x05, 0xF0, ++0xA7, 0xF9, 0x13, 0x4B, 0x9B, 0x7C, 0x23, 0xB9, 0x12, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x11, 0x4C, ++0x11, 0x48, 0x23, 0x68, 0x0E, 0x49, 0x11, 0x4D, 0x11, 0x4A, 0x23, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF0, ++0x80, 0x43, 0x03, 0x60, 0x0B, 0x68, 0x00, 0x20, 0x23, 0xF0, 0x80, 0x53, 0x0B, 0x60, 0x28, 0x60, 0x13, 0x68, 0x23, 0xF0, ++0x01, 0x03, 0x13, 0x60, 0x38, 0xBD, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x98, 0xA3, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x44, 0x00, 0x32, 0x40, 0x90, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x70, 0xB5, 0x90, 0xF8, 0x72, 0x30, 0x01, 0x2B, 0x04, 0x46, 0x11, 0xD0, 0x02, 0x2B, 0x00, 0xD0, ++0x70, 0xBD, 0x0C, 0x4D, 0x41, 0x6F, 0x01, 0x23, 0x80, 0xF8, 0x72, 0x30, 0xD5, 0xF8, 0xE0, 0x31, 0x60, 0x30, 0x98, 0x47, ++0xD5, 0xF8, 0x18, 0x32, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x04, 0x4B, 0x00, 0x22, 0x80, 0xF8, 0x72, 0x20, ++0xBD, 0xE8, 0x70, 0x40, 0xD3, 0xF8, 0x18, 0x32, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x4F, 0xF0, 0x00, 0x0C, 0x4F, 0xF0, 0x01, 0x0E, 0x83, 0xB0, 0x06, 0x46, 0x04, 0x46, 0x00, 0xF1, 0x60, 0x05, 0x03, 0x46, ++0x67, 0x46, 0x71, 0x46, 0x1A, 0x7C, 0x02, 0x2A, 0x13, 0xD1, 0xDA, 0x7C, 0x01, 0x2A, 0x10, 0xD8, 0x96, 0xF8, 0x87, 0x20, ++0x32, 0xB1, 0x93, 0xF8, 0x21, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x20, 0x01, 0x2A, 0x06, 0xD0, 0xDA, 0x68, 0x00, 0x29, ++0x00, 0xF0, 0xC0, 0x80, 0x01, 0x37, 0x94, 0x46, 0x00, 0x21, 0x30, 0x33, 0x9D, 0x42, 0xE5, 0xD1, 0x01, 0x22, 0x8E, 0x46, ++0x33, 0x46, 0x4F, 0xF0, 0x00, 0x09, 0x00, 0x92, 0xA0, 0x46, 0x1A, 0x7C, 0x02, 0x2A, 0x1D, 0xD1, 0xD9, 0x7C, 0x01, 0x29, ++0x1A, 0xD9, 0x96, 0xF8, 0x87, 0x20, 0x32, 0xB1, 0x93, 0xF8, 0x21, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x20, 0x01, 0x2A, ++0x10, 0xD0, 0xD3, 0xE9, 0x06, 0x04, 0xDA, 0x68, 0x04, 0xEB, 0x02, 0x0A, 0xAA, 0xEB, 0x00, 0x00, 0xBE, 0xF1, 0x00, 0x0F, ++0x42, 0xD0, 0x00, 0x21, 0x00, 0x91, 0x01, 0x37, 0x81, 0x46, 0x94, 0x46, 0x4F, 0xF0, 0x00, 0x0E, 0x30, 0x33, 0x9D, 0x42, ++0xDB, 0xD1, 0x01, 0x96, 0x44, 0x46, 0x00, 0x9E, 0x18, 0xE0, 0x00, 0x2F, 0x5F, 0xD1, 0xA1, 0xEB, 0x09, 0x02, 0x00, 0x2A, ++0x58, 0xDB, 0xAC, 0xEB, 0x03, 0x02, 0x00, 0x2A, 0x0B, 0xDB, 0xA3, 0xEB, 0x09, 0x00, 0xAC, 0xEB, 0x01, 0x02, 0x39, 0xEA, ++0x20, 0x09, 0x28, 0xBF, 0x99, 0x46, 0x3C, 0xEA, 0x22, 0x0C, 0x28, 0xBF, 0x8C, 0x46, 0x30, 0x34, 0xA5, 0x42, 0x0F, 0xD0, ++0x23, 0x7C, 0x01, 0x2B, 0xF9, 0xD1, 0xE3, 0x68, 0xA1, 0x69, 0x19, 0x44, 0xBE, 0xF1, 0x00, 0x0F, 0xDD, 0xD0, 0x30, 0x34, ++0x00, 0x26, 0xA5, 0x42, 0x99, 0x46, 0x8C, 0x46, 0xB6, 0x46, 0xEF, 0xD1, 0x33, 0x46, 0x01, 0x9E, 0xC6, 0xF8, 0x80, 0xC0, ++0x0B, 0xB1, 0x0C, 0xF1, 0x0A, 0x09, 0xC6, 0xF8, 0x7C, 0x90, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA0, 0xEB, 0x0C, 0x0A, ++0xBA, 0xF1, 0x00, 0x0F, 0x80, 0xF2, 0x88, 0x80, 0xA4, 0xEB, 0x02, 0x0B, 0x02, 0xEB, 0x0C, 0x0A, 0x01, 0x39, 0x83, 0x44, ++0xA0, 0xEB, 0x0A, 0x0A, 0x01, 0xE0, 0x01, 0x39, 0xB2, 0xD0, 0x0B, 0xEB, 0x02, 0x00, 0x22, 0x44, 0x1A, 0xEB, 0x02, 0x0F, ++0xF7, 0xD4, 0xAC, 0xEB, 0x02, 0x04, 0x3C, 0xEA, 0x24, 0x0C, 0x28, 0xBF, 0x94, 0x46, 0x01, 0x29, 0x3D, 0xD0, 0x62, 0x46, ++0x00, 0x99, 0x00, 0x29, 0x99, 0xD1, 0xA0, 0xEB, 0x09, 0x01, 0x10, 0xEA, 0x21, 0x00, 0x38, 0xBF, 0x48, 0x46, 0x94, 0xE7, ++0x99, 0x46, 0x8C, 0x46, 0xB3, 0xE7, 0xA1, 0xEB, 0x0C, 0x02, 0x00, 0x2A, 0x94, 0xF8, 0x13, 0x80, 0x61, 0xDA, 0x08, 0xF1, ++0xFF, 0x30, 0xB8, 0xF1, 0x00, 0x0F, 0xA8, 0xD0, 0xD4, 0xF8, 0x1C, 0xB0, 0x9A, 0x46, 0x03, 0xE0, 0x42, 0x1E, 0x00, 0x28, ++0xA1, 0xD0, 0x10, 0x46, 0xDA, 0x44, 0x01, 0xEB, 0x0A, 0x08, 0xA8, 0xEB, 0x0C, 0x02, 0xD2, 0x1A, 0x00, 0x2A, 0xA8, 0xEB, ++0x03, 0x08, 0xF1, 0xDB, 0xA6, 0xB1, 0xAC, 0xEB, 0x0A, 0x03, 0x00, 0x2B, 0x29, 0xDB, 0x58, 0xB3, 0xE3, 0x69, 0xC4, 0x46, ++0x0A, 0xEB, 0x03, 0x09, 0x00, 0x26, 0x8A, 0xE7, 0xAC, 0xEB, 0x02, 0x01, 0x12, 0xEA, 0x21, 0x02, 0x38, 0xBF, 0x62, 0x46, ++0x38, 0xE7, 0x48, 0x46, 0x62, 0x46, 0x5E, 0xE7, 0xA9, 0xEB, 0x0A, 0x03, 0x00, 0x2B, 0x11, 0xDB, 0xAC, 0xEB, 0x0A, 0x03, ++0x00, 0x2B, 0x15, 0xDB, 0xA8, 0xEB, 0x09, 0x03, 0x00, 0x2B, 0x14, 0xDB, 0x1B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x29, 0xDB, 0xE3, 0x69, 0xC4, 0x46, 0x0A, 0xEB, 0x03, 0x09, 0x4F, 0xF0, 0x00, 0x0E, 0x67, 0xE7, 0xD1, 0x46, ++0x00, 0x26, 0x64, 0xE7, 0xC4, 0x46, 0x62, 0xE7, 0xD1, 0x46, 0xB6, 0x46, 0x5F, 0xE7, 0x01, 0x28, 0x15, 0xDD, 0xE3, 0x69, ++0x9A, 0x44, 0xAA, 0xEB, 0x09, 0x03, 0xC4, 0x46, 0x39, 0xEA, 0x23, 0x09, 0x28, 0xBF, 0xD1, 0x46, 0xB6, 0x46, 0x52, 0xE7, ++0xAC, 0xEB, 0x02, 0x01, 0x12, 0xEA, 0x21, 0x02, 0x38, 0xBF, 0x62, 0x46, 0x8A, 0xE7, 0x40, 0x46, 0x9A, 0x46, 0x88, 0x46, ++0xB0, 0xE7, 0xC4, 0x46, 0xB6, 0x46, 0x44, 0xE7, 0x04, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x4D, 0x12, 0x05, 0xF0, 0x64, 0xFA, ++0xCE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x03, 0x7C, 0x02, 0x2B, 0x83, 0xB0, 0x04, 0x46, 0x69, 0xD0, 0x90, 0xF8, 0x40, 0x30, 0x02, 0x2B, 0x54, 0xD0, 0x94, 0xF8, ++0x73, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x18, 0xD1, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x40, 0xF0, 0xD2, 0x80, 0x94, 0xF8, ++0x70, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xB8, 0x80, 0xDF, 0xF8, 0x24, 0x93, 0xC3, 0x4B, 0x94, 0xF8, 0x71, 0x20, 0xD3, 0xF8, ++0x5C, 0x34, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x90, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x94, 0xF8, ++0x72, 0x30, 0x01, 0x2B, 0x00, 0xF0, 0x54, 0x81, 0x94, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x00, 0xF0, 0xB9, 0x81, 0xB9, 0x4A, ++0x92, 0xF8, 0x00, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xA8, 0x80, 0x52, 0x68, 0x11, 0x07, 0x00, 0xF1, 0xD4, 0x81, ++0x94, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0xD0, 0x92, 0x02, 0x23, ++0x0C, 0x21, 0x00, 0x22, 0x4D, 0x20, 0x03, 0xF0, 0x15, 0xF9, 0x01, 0x25, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x45, 0x70, ++0x03, 0xF0, 0x3E, 0xF9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x00, 0x22, 0x84, 0xF8, 0x85, 0x20, 0x18, 0x6C, ++0x29, 0x46, 0xFF, 0xF7, 0x15, 0xF9, 0x55, 0xE0, 0x90, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x7B, 0xD0, 0xFF, 0x23, 0x00, 0x21, ++0x94, 0xF8, 0x51, 0x20, 0x00, 0x2A, 0x6F, 0xD0, 0x94, 0xF8, 0x50, 0x20, 0x01, 0x2A, 0x6B, 0xD1, 0x00, 0x29, 0x9A, 0xD0, ++0x11, 0xE0, 0x90, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x5F, 0xD0, 0x90, 0xF8, 0x21, 0x30, 0x23, 0xB1, 0x90, 0xF8, 0x20, 0x30, ++0x01, 0x2B, 0x00, 0xF0, 0xA6, 0x81, 0x94, 0xF8, 0x40, 0x20, 0x23, 0x7D, 0x02, 0x2A, 0x00, 0xF0, 0x9E, 0x81, 0x01, 0x2B, ++0xB8, 0xD0, 0x94, 0xF8, 0x86, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x0D, 0x81, 0x94, 0xF8, 0x72, 0x50, 0x94, 0xF8, ++0x85, 0x30, 0xA5, 0xF1, 0x01, 0x06, 0xB6, 0xFA, 0x86, 0xF6, 0x76, 0x09, 0xB3, 0x42, 0x00, 0xF0, 0x4C, 0x81, 0x02, 0x23, ++0x0C, 0x21, 0x52, 0x46, 0x4D, 0x20, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x20, 0x92, 0x03, 0xF0, 0xC1, 0xF8, 0x6F, 0x1E, ++0x18, 0xBF, 0x01, 0x27, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x47, 0x70, 0x03, 0xF0, 0xE8, 0xF8, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x08, 0x93, 0x84, 0xF8, 0x85, 0x60, 0x18, 0x6C, 0x39, 0x46, 0xFF, 0xF7, 0xC0, 0xF8, 0x01, 0x2D, 0x4C, 0xD0, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x93, 0xF8, 0x62, 0x20, 0x02, 0x2A, 0x00, 0xF0, 0xF1, 0x80, 0x94, 0xF8, ++0x70, 0x30, 0x7B, 0xB9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x98, 0x98, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x07, 0xD0, ++0x6E, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x01, 0x22, 0x83, 0xF8, 0x24, 0x20, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x90, 0xF8, 0x40, 0x20, 0x03, 0x7D, 0x02, 0x2A, 0xA8, 0xD1, 0x94, 0xF8, 0x44, 0x20, 0x93, 0x42, 0x28, 0xBF, ++0x13, 0x46, 0xA2, 0xE7, 0xFF, 0x23, 0xF7, 0xE7, 0x94, 0xF8, 0x85, 0x20, 0x01, 0x2A, 0x3F, 0xF4, 0x30, 0xAF, 0x94, 0xF8, ++0x71, 0x80, 0xDF, 0xF8, 0x88, 0x91, 0x02, 0x23, 0x0C, 0x21, 0x00, 0x22, 0x4D, 0x20, 0x03, 0xF0, 0x71, 0xF8, 0x00, 0x25, ++0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x45, 0x70, 0x03, 0xF0, 0x9A, 0xF8, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, ++0x01, 0x22, 0x84, 0xF8, 0x85, 0x20, 0x18, 0x6C, 0x29, 0x46, 0xFF, 0xF7, 0x71, 0xF8, 0x94, 0xF8, 0x70, 0xE0, 0xBE, 0xF1, ++0x00, 0x0F, 0x40, 0xF0, 0xD4, 0x80, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x08, 0x97, 0x97, 0xF8, 0x6C, 0x10, 0xFF, 0x29, ++0x00, 0xF0, 0xF0, 0x80, 0x4A, 0x4D, 0x01, 0x94, 0x4F, 0xF4, 0x1E, 0x7B, 0xA4, 0x23, 0x0B, 0xFB, 0x01, 0xF0, 0x03, 0xFB, ++0x08, 0xF3, 0x05, 0xF5, 0x16, 0x7B, 0x2E, 0x18, 0x9E, 0x33, 0x58, 0x44, 0x00, 0x90, 0x09, 0xEB, 0xC3, 0x0B, 0x4F, 0xF0, ++0x4F, 0x0C, 0x46, 0x20, 0x1C, 0xFB, 0x01, 0x01, 0x5C, 0x46, 0x40, 0x4A, 0xDD, 0xF8, 0x00, 0xB0, 0x86, 0xF8, 0x24, 0xE0, ++0x05, 0xEB, 0xC1, 0x05, 0xD6, 0xF8, 0x08, 0x12, 0x39, 0xB3, 0xEF, 0xF3, 0x10, 0x81, 0xCB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x39, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x11, 0x68, 0xA5, 0xF1, 0x28, 0x00, 0x4B, 0x1C, 0xA4, 0xF1, 0x28, 0x01, 0x13, 0x60, ++0x00, 0x90, 0x03, 0xF0, 0x9D, 0xFD, 0xD6, 0xF8, 0x08, 0x12, 0xD6, 0xF8, 0x0C, 0x32, 0x00, 0x98, 0xC7, 0xF8, 0xC8, 0x14, ++0xC7, 0xF8, 0xCC, 0x34, 0x03, 0xF0, 0x9C, 0xFC, 0x2C, 0x4A, 0x11, 0x68, 0x48, 0x1E, 0x31, 0xB1, 0x2B, 0x4B, 0x10, 0x60, ++0x19, 0x68, 0x10, 0xB9, 0x00, 0x29, 0x40, 0xF0, 0xB5, 0x80, 0xD6, 0xF8, 0x30, 0x32, 0x20, 0x46, 0x29, 0x46, 0x08, 0x36, ++0x08, 0x34, 0x08, 0x37, 0x2B, 0xB1, 0x03, 0xF0, 0x7D, 0xFD, 0x28, 0x46, 0x03, 0xF0, 0x84, 0xFC, 0x20, 0x4A, 0x08, 0x35, ++0x5D, 0x45, 0xC3, 0xD1, 0x01, 0x9C, 0x40, 0x20, 0x03, 0xF0, 0xDE, 0xFB, 0x94, 0xF8, 0x70, 0x20, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x08, 0x98, 0x98, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x13, 0xD0, 0x00, 0x2A, 0x7F, 0xF4, 0x55, 0xAF, 0xBA, 0xF1, ++0x00, 0x0F, 0x7F, 0xF4, 0x51, 0xAF, 0x99, 0xE6, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0x8E, 0xAE, 0x94, 0xF8, ++0x71, 0x80, 0xDF, 0xF8, 0x48, 0x90, 0x4F, 0xF0, 0x00, 0x0A, 0x5C, 0xE7, 0xD8, 0xF8, 0x04, 0x30, 0x43, 0xF0, 0x20, 0x03, ++0xC8, 0xF8, 0x04, 0x30, 0x00, 0x2A, 0x7F, 0xF4, 0x3B, 0xAF, 0xE4, 0xE7, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, ++0x35, 0xAF, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x1C, 0x90, 0x4F, 0xF0, 0x01, 0x0A, 0x46, 0xE7, 0x88, 0x1A, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x3C, 0x49, 0x5A, 0x68, 0x49, 0x68, 0x22, 0xF0, 0x20, 0x02, 0x00, 0x29, 0x5A, 0x60, 0x7F, 0xF7, 0x06, 0xAF, 0xEF, 0xF3, ++0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x36, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x36, 0x4D, 0x2B, 0x68, 0x04, 0x20, ++0x01, 0x33, 0x2B, 0x60, 0xEE, 0xF7, 0x1C, 0xFF, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xEE, 0xF7, 0xB7, 0xFF, 0x2B, 0x68, ++0x00, 0x2B, 0x3F, 0xF4, 0xEE, 0xAE, 0x2D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0xE7, 0xAE, ++0x00, 0x2A, 0x3F, 0xF4, 0xE4, 0xAE, 0x62, 0xB6, 0xE1, 0xE6, 0x40, 0x20, 0x03, 0xF0, 0x6E, 0xFB, 0x94, 0xF8, 0x70, 0x20, ++0x8E, 0xE7, 0x94, 0xF8, 0x70, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0xEA, 0xAE, 0x01, 0x2D, 0x7F, 0xF4, 0xE7, 0xAE, 0x2D, 0xE6, ++0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x80, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x93, 0xF8, 0xDE, 0x20, ++0x93, 0xF8, 0xC2, 0x34, 0x9A, 0x42, 0x20, 0xD0, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0xD3, 0xAE, 0x4F, 0xF0, ++0x00, 0x0A, 0xE8, 0xE6, 0x97, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x7F, 0xF4, 0x76, 0xAF, 0x7B, 0x68, 0x43, 0xF0, 0x20, 0x03, ++0x7B, 0x60, 0xBA, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0xC3, 0xAE, 0x0B, 0xE6, 0x62, 0xB6, 0x48, 0xE7, 0x94, 0xF8, 0x85, 0x20, ++0x01, 0x2A, 0x7F, 0xF4, 0x70, 0xAF, 0x00, 0x2B, 0x3F, 0xF4, 0x00, 0xAE, 0xB6, 0xE6, 0x94, 0xF8, 0x85, 0x30, 0x00, 0x2B, ++0x7F, 0xF4, 0x27, 0xAE, 0xB0, 0xE6, 0x01, 0x21, 0x42, 0xE6, 0x90, 0xF8, 0x40, 0x30, 0x02, 0x2B, 0x7F, 0xF4, 0xE3, 0xAD, ++0x3A, 0xE6, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xF4, 0x92, 0x47, 0x7C, 0xB6, 0x49, 0x90, 0xF8, 0x10, 0xB0, 0x8C, 0x23, 0x03, 0xFB, ++0x07, 0x93, 0x83, 0xB0, 0x93, 0xF8, 0x71, 0x20, 0x93, 0xF8, 0x70, 0x30, 0x00, 0x92, 0x07, 0xEB, 0x87, 0x06, 0x4F, 0xF4, ++0xA4, 0x6A, 0xC6, 0xEB, 0xC6, 0x06, 0x01, 0x2B, 0x05, 0x46, 0x0A, 0xFB, 0x02, 0x1A, 0x09, 0xEB, 0x86, 0x06, 0x00, 0xF0, ++0x0B, 0x81, 0xAA, 0x4B, 0xC4, 0x6A, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xD3, 0x80, 0xDA, 0xF8, ++0x7C, 0x30, 0xE4, 0x1A, 0xA4, 0x4B, 0xA5, 0x49, 0xDF, 0xF8, 0x94, 0x82, 0xBB, 0xF1, 0x01, 0x0F, 0x17, 0xD0, 0xBB, 0xF1, ++0x02, 0x0F, 0x00, 0xF0, 0x82, 0x80, 0x1A, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x7F, 0xDB, 0xD8, 0xF8, 0x10, 0x20, ++0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0x80, 0xF2, 0xE9, 0x80, 0xBB, 0xF1, 0x00, 0x0F, 0xE7, 0xD1, ++0xDF, 0xF8, 0x70, 0x82, 0x20, 0xE0, 0xA8, 0x69, 0xDF, 0xF8, 0x68, 0x82, 0x95, 0x4B, 0x1B, 0x69, 0x04, 0x44, 0xE3, 0x1A, ++0xA3, 0xF5, 0x9C, 0x53, 0x08, 0x3B, 0x00, 0x2B, 0x80, 0xF2, 0xFA, 0x80, 0xEA, 0x7C, 0xFF, 0x2A, 0x1B, 0xD0, 0x01, 0x3A, ++0xD2, 0xB2, 0xEA, 0x74, 0xBA, 0xB9, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x97, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x5D, 0xD0, ++0xD8, 0xF8, 0xE8, 0x31, 0x28, 0x46, 0x98, 0x47, 0x87, 0x4B, 0x1B, 0x69, 0xD8, 0xF8, 0x1C, 0x32, 0x30, 0x46, 0x98, 0x47, ++0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x4F, 0xF0, 0x8C, 0x0E, 0x0E, 0xFB, ++0x07, 0x9E, 0xD5, 0xE9, 0x06, 0x0B, 0x9E, 0xF8, 0x70, 0x30, 0xAB, 0xEB, 0x00, 0x01, 0x01, 0x2B, 0x0C, 0x44, 0x47, 0xD0, ++0x7A, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xA8, 0xBF, 0x4F, 0xF0, 0x01, 0x0B, ++0xBE, 0xDB, 0x53, 0xB9, 0x72, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB0, 0x80, 0xDA, 0xF8, ++0x7C, 0x30, 0x23, 0x44, 0xEB, 0x62, 0x21, 0x46, 0xD8, 0xF8, 0xE0, 0x31, 0x28, 0x46, 0x98, 0x47, 0x85, 0xF8, 0x10, 0xB0, ++0xD8, 0xF8, 0x1C, 0x32, 0x30, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x98, 0x47, 0x00, 0x9A, 0x11, 0x46, ++0x63, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xA4, 0x80, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, 0x90, 0x81, 0x9B, 0xE7, 0x5F, 0x48, 0x4F, 0xF4, 0x31, 0x72, 0x04, 0xF0, ++0x53, 0xFF, 0x5A, 0x4B, 0x5A, 0x49, 0x77, 0xE7, 0xD8, 0xF8, 0x08, 0x32, 0xA9, 0x7C, 0x50, 0x46, 0x98, 0x47, 0x58, 0x4B, ++0x1B, 0x69, 0x9F, 0xE7, 0x9E, 0xF8, 0x84, 0x10, 0x00, 0x29, 0x36, 0xD0, 0xA9, 0x6A, 0x01, 0x91, 0x69, 0x6A, 0x01, 0xEB, ++0x0B, 0x0C, 0x01, 0x99, 0x01, 0x39, 0xC5, 0xE9, 0x09, 0xC1, 0x00, 0x29, 0x5E, 0xD1, 0x2A, 0x75, 0xBB, 0xF1, 0x00, 0x0F, ++0x05, 0xD0, 0x4F, 0xF0, 0x00, 0x43, 0xB3, 0xFB, 0xFB, 0xF3, 0x01, 0x3B, 0xAB, 0x62, 0x00, 0x9B, 0x19, 0x46, 0x46, 0x4B, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x32, 0xD8, 0xF8, 0x90, 0x31, 0x92, 0xF8, 0x63, 0x00, 0x03, 0x21, 0x98, 0x47, ++0x43, 0x4B, 0x1B, 0x69, 0xE3, 0x1A, 0xA3, 0xF5, 0x9C, 0x53, 0x08, 0x3B, 0x00, 0x2B, 0x71, 0xDA, 0xA8, 0x69, 0x51, 0xE7, ++0x9A, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x28, 0xAF, 0x3B, 0x49, 0x3D, 0x48, 0x58, 0x22, 0x04, 0xF0, 0x0E, 0xFF, ++0x21, 0xE7, 0x39, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xFF, 0xF6, 0x3E, 0xAF, ++0xD8, 0xF8, 0xE0, 0x21, 0x01, 0x93, 0x21, 0x46, 0x28, 0x46, 0x90, 0x47, 0x01, 0x9B, 0x2B, 0x74, 0xD8, 0xF8, 0x1C, 0x32, ++0x30, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x98, 0x47, 0x00, 0x9A, 0x11, 0x46, 0x28, 0x4A, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x8A, 0xD1, 0x31, 0xE0, 0xC4, 0x68, 0xFD, 0xE6, ++0xBB, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x16, 0xAF, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0xDF, 0xF8, 0x98, 0x80, 0x97, 0xF8, ++0x70, 0x30, 0x54, 0xE7, 0x1F, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xFF, 0xF6, ++0x0B, 0xAF, 0x9B, 0x46, 0x9E, 0xF8, 0x70, 0x30, 0x47, 0xE7, 0x9A, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x4B, 0xAF, ++0x15, 0x49, 0x18, 0x48, 0x49, 0x22, 0x04, 0xF0, 0xC3, 0xFE, 0x44, 0xE7, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x4F, 0xF0, ++0x02, 0x0B, 0x97, 0xF8, 0x70, 0x30, 0x34, 0xE7, 0xBB, 0xF1, 0x01, 0x0F, 0x7F, 0xF4, 0x58, 0xAF, 0x00, 0x9A, 0x11, 0x46, ++0x09, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x5A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x5A, 0x60, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x4F, 0xF0, 0x01, 0x0B, 0x97, 0xF8, 0x70, 0x30, 0x1A, 0xE7, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x64, 0x7D, 0x15, 0x00, ++0x40, 0x9C, 0x15, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x00, 0x22, 0x04, 0x46, 0x0D, 0x46, ++0x10, 0x23, 0x0C, 0x21, 0x55, 0x20, 0x02, 0xF0, 0xA5, 0xFD, 0x05, 0xEB, 0x45, 0x03, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, ++0x04, 0xEB, 0x03, 0x13, 0x45, 0x70, 0x1A, 0x7C, 0x22, 0xB9, 0xC2, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0xF0, 0xC6, 0xBD, ++0x1A, 0x7D, 0xC2, 0x70, 0x00, 0x2A, 0xF7, 0xD0, 0x93, 0xF8, 0x20, 0x20, 0x82, 0x70, 0xD3, 0xE9, 0x06, 0x12, 0x5B, 0x6A, ++0xC3, 0x60, 0xC0, 0xE9, 0x01, 0x12, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0xF0, 0xB5, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, ++0x16, 0x46, 0x2D, 0x4D, 0x4F, 0xF4, 0xA4, 0x62, 0xB3, 0x42, 0x04, 0x46, 0x02, 0xFB, 0x01, 0x58, 0x0B, 0xD3, 0xC2, 0x7C, ++0x01, 0x2A, 0x30, 0xD0, 0xC5, 0x69, 0x9B, 0x1B, 0xB3, 0xFB, 0xF5, 0xF3, 0x03, 0xFB, 0x05, 0x55, 0x2E, 0x44, 0x5F, 0x1C, ++0x00, 0xE0, 0x00, 0x27, 0x23, 0x4B, 0xE6, 0x62, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0xE3, 0x7C, ++0xD8, 0xF8, 0x7C, 0x00, 0xFF, 0x2B, 0xA6, 0xEB, 0x00, 0x00, 0x31, 0xD0, 0xBB, 0x42, 0x94, 0xBF, 0xDB, 0x1A, 0xDB, 0x1B, ++0x1B, 0x4A, 0xDB, 0xB2, 0xE3, 0x74, 0x12, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0x0C, 0xDA, 0x18, 0x49, 0x5B, 0xB1, 0xE5, 0x69, ++0xFF, 0x2B, 0x28, 0x44, 0x0A, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0xE3, 0x74, 0x0A, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0xF3, 0xDB, ++0x03, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x0A, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0xED, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, ++0x98, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xD2, 0xD0, 0x0B, 0x48, 0x0C, 0x49, 0x58, 0x22, 0x04, 0xF0, 0x15, 0xFE, 0xE3, 0x7C, ++0xD8, 0xF8, 0x7C, 0x00, 0xFF, 0x2B, 0xA6, 0xEB, 0x00, 0x00, 0xCD, 0xD1, 0x04, 0x4A, 0x12, 0x69, 0x82, 0x1A, 0x00, 0x2A, ++0xD3, 0xDB, 0xE1, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x40, 0x9C, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x70, 0xB5, 0x08, 0x4E, 0xD6, 0xF8, 0xEC, 0x41, 0x05, 0x46, 0xA0, 0x47, 0x04, 0x46, 0x30, 0xB1, ++0xD6, 0xF8, 0xE0, 0x31, 0x01, 0x46, 0x28, 0x46, 0x98, 0x47, 0x01, 0x23, 0x2B, 0x74, 0xE0, 0xB2, 0x70, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x03, 0x7C, 0x43, 0xB1, 0x10, 0xB5, 0x04, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, ++0x00, 0x23, 0x23, 0x74, 0x10, 0xBD, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x5C, 0x4F, 0x00, 0xEB, ++0x80, 0x04, 0xC4, 0xEB, 0xC4, 0x04, 0x4F, 0xEA, 0x84, 0x0A, 0x83, 0xB0, 0x05, 0x46, 0x07, 0xEB, 0x84, 0x04, 0x0E, 0x46, ++0x00, 0x29, 0x74, 0xD0, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x73, 0x91, 0x46, 0xCA, 0x78, 0x93, 0xF8, 0x84, 0x10, 0x00, 0x29, ++0x40, 0xF0, 0x8A, 0x80, 0x4F, 0xF0, 0x8C, 0x08, 0x08, 0xFB, 0x05, 0x78, 0x01, 0x21, 0x98, 0xF8, 0x79, 0x30, 0x88, 0xF8, ++0x78, 0x20, 0x88, 0xF8, 0x84, 0x10, 0xAB, 0xB1, 0xDF, 0xF8, 0x30, 0xB1, 0x20, 0x46, 0xDB, 0xF8, 0xE8, 0x31, 0x98, 0x47, ++0x00, 0x22, 0x0A, 0xF1, 0x30, 0x00, 0xDB, 0xF8, 0xE8, 0x31, 0x88, 0xF8, 0x79, 0x20, 0x38, 0x44, 0x98, 0x47, 0x00, 0x22, ++0xDB, 0xF8, 0x18, 0x32, 0x88, 0xF8, 0x79, 0x20, 0x20, 0x46, 0x98, 0x47, 0xB6, 0xF8, 0x01, 0x20, 0x3F, 0x49, 0x02, 0x3A, ++0x81, 0xFB, 0x02, 0x31, 0xD3, 0x17, 0xC3, 0xEB, 0xA1, 0x03, 0x13, 0xF0, 0xFF, 0x0B, 0x2E, 0xD0, 0x8C, 0x23, 0x03, 0xFB, ++0x05, 0x73, 0x00, 0x93, 0x06, 0xF1, 0x05, 0x08, 0x4F, 0xF0, 0x00, 0x0A, 0x01, 0x95, 0x98, 0xF8, 0x00, 0x20, 0x36, 0x49, ++0x22, 0x75, 0x0A, 0xF1, 0x01, 0x0A, 0x20, 0x46, 0x4B, 0x46, 0x9A, 0xB1, 0x01, 0x2A, 0xD8, 0xF8, 0x05, 0x50, 0x00, 0xD9, ++0x75, 0xB1, 0xD8, 0xF8, 0x01, 0xC0, 0xE2, 0x74, 0xC4, 0xE9, 0x06, 0xC5, 0x00, 0x9A, 0xD1, 0xF8, 0xF4, 0x51, 0x92, 0xF8, ++0x71, 0x10, 0xD8, 0xF8, 0x09, 0x20, 0xA8, 0x47, 0x00, 0x28, 0x45, 0xD1, 0x5F, 0xFA, 0x8A, 0xF3, 0x5B, 0x45, 0x08, 0xF1, ++0x0D, 0x08, 0x04, 0xF1, 0x30, 0x04, 0xDA, 0xD3, 0x01, 0x9D, 0x96, 0xF9, 0x04, 0x20, 0x33, 0x79, 0x00, 0x2A, 0x2D, 0xDB, ++0x8C, 0x20, 0x00, 0xFB, 0x05, 0x75, 0x00, 0x23, 0x85, 0xF8, 0x73, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xF0, ++0x8C, 0x08, 0x08, 0xFB, 0x00, 0x78, 0x98, 0xF8, 0x79, 0x30, 0x88, 0xF8, 0x84, 0x10, 0x00, 0x2B, 0xEC, 0xD0, 0xDF, 0xF8, ++0x60, 0x90, 0x20, 0x46, 0xD9, 0xF8, 0xE8, 0x31, 0x98, 0x47, 0x0A, 0xF1, 0x30, 0x00, 0xD9, 0xF8, 0xE8, 0x31, 0x88, 0xF8, ++0x79, 0x60, 0x38, 0x44, 0x98, 0x47, 0xD9, 0xF8, 0x18, 0x32, 0x88, 0xF8, 0x79, 0x60, 0x20, 0x46, 0x98, 0x47, 0xD7, 0xE7, ++0x93, 0xF8, 0x78, 0x30, 0x93, 0x42, 0x7F, 0xF4, 0x71, 0xAF, 0xD7, 0xE7, 0x8C, 0x20, 0x00, 0xFB, 0x05, 0x75, 0x03, 0xF0, ++0x7F, 0x03, 0x85, 0xF8, 0x73, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x9A, 0x92, 0xF8, 0x79, 0x30, 0x01, 0x33, ++0x82, 0xF8, 0x79, 0x30, 0xB2, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x4F, 0xEC, 0xC4, 0x4E, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0xB5, 0x01, 0x22, 0x05, 0x48, 0x00, 0x21, 0xE0, 0xF7, 0x2C, 0xF8, 0x04, 0x4B, 0xFF, 0x22, 0x83, 0xF8, 0x71, 0x20, ++0x83, 0xF8, 0xFD, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x44, 0x9E, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x25, 0x4C, 0x94, 0xF8, 0x71, 0x30, 0xFF, 0x2B, 0x07, 0x46, 0x0E, 0x46, 0x08, 0xD0, 0x94, 0xF8, 0xFD, 0x30, 0xFF, 0x2B, ++0x18, 0xBF, 0xFF, 0x25, 0x36, 0xD0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x25, 0xA8, 0x46, 0x4F, 0xF0, 0x30, 0x0A, ++0xA1, 0x46, 0x8C, 0x22, 0x00, 0x21, 0x48, 0x46, 0xE0, 0xF7, 0x04, 0xF8, 0x8C, 0x23, 0x03, 0xFB, 0x08, 0x43, 0x01, 0x2E, ++0x83, 0xF8, 0x71, 0x70, 0x83, 0xF8, 0x70, 0x60, 0x03, 0xD1, 0x15, 0x4A, 0x13, 0x78, 0x01, 0x33, 0x13, 0x70, 0x8C, 0x23, ++0x03, 0xFB, 0x08, 0x43, 0x12, 0x4A, 0xC3, 0xF8, 0x08, 0x90, 0x54, 0x44, 0x00, 0x21, 0x01, 0x26, 0x9C, 0x63, 0x99, 0x74, ++0x0F, 0x4C, 0xD2, 0xF8, 0x10, 0x12, 0x5D, 0x74, 0x83, 0xF8, 0x41, 0x50, 0xC3, 0xF8, 0x68, 0x90, 0x83, 0xF8, 0x42, 0x60, ++0x5C, 0x66, 0x59, 0x60, 0x59, 0x63, 0x48, 0x46, 0xD2, 0xF8, 0x18, 0x32, 0x98, 0x47, 0xC8, 0xE7, 0x01, 0x25, 0xA8, 0x46, ++0x4F, 0xF0, 0xBC, 0x0A, 0x04, 0xF1, 0x8C, 0x09, 0xC9, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x41, 0xF4, 0x13, 0x00, 0x0E, 0x4A, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x23, 0x10, 0xB4, 0x93, 0xF8, ++0x71, 0x40, 0xFF, 0x2C, 0x0A, 0xD0, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x09, 0xD0, 0x29, 0xB1, 0x8C, 0x23, 0x03, 0xFB, ++0x00, 0x20, 0xFF, 0x23, 0x80, 0xF8, 0x71, 0x30, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x04, 0x4C, 0x23, 0x78, 0x01, 0x3B, ++0x23, 0x70, 0x00, 0x29, 0xF6, 0xD0, 0xEF, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, 0x90, 0xF8, 0xC0, 0x34, ++0xBB, 0xB3, 0x2D, 0xE9, 0xF0, 0x47, 0x90, 0xF8, 0x62, 0x40, 0x0C, 0x43, 0x2F, 0xD1, 0x90, 0xF8, 0xC1, 0x54, 0xDF, 0xF8, ++0x64, 0x80, 0x17, 0x4F, 0x05, 0xEB, 0x85, 0x00, 0xC0, 0xEB, 0xC0, 0x00, 0x08, 0xEB, 0x80, 0x09, 0xD7, 0xF8, 0xE8, 0x31, ++0x86, 0x00, 0x48, 0x46, 0x98, 0x47, 0x06, 0xF1, 0x30, 0x00, 0xD7, 0xF8, 0xE8, 0x31, 0x40, 0x44, 0x98, 0x47, 0x8C, 0x23, ++0x03, 0xFB, 0x05, 0x85, 0x95, 0xF8, 0x72, 0x30, 0x85, 0xF8, 0x73, 0x40, 0x85, 0xF8, 0x78, 0x40, 0x85, 0xF8, 0x84, 0x40, ++0x3B, 0xB1, 0x06, 0xF1, 0x60, 0x00, 0xD7, 0xF8, 0xD8, 0x31, 0x40, 0x44, 0x98, 0x47, 0x85, 0xF8, 0x72, 0x40, 0xD7, 0xF8, ++0x18, 0x32, 0x48, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x87, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0x48, 0x9E, 0x17, 0x00, 0x03, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0x85, 0x00, 0x70, 0x47, 0x00, 0xBF, ++0x48, 0x9E, 0x17, 0x00, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x70, 0xB5, 0x05, 0x46, 0x0C, 0x46, ++0x16, 0x46, 0x0E, 0xDB, 0x95, 0xF8, 0xC1, 0x34, 0x0C, 0x4A, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0xD3, 0xF8, 0x80, 0x20, ++0x22, 0x60, 0xD8, 0x6F, 0x30, 0x60, 0x23, 0x68, 0xC0, 0x1A, 0xC0, 0x0F, 0x70, 0xBD, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0xEC, 0xD1, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x06, 0x52, 0x04, 0xF0, 0x23, 0xFC, 0xE5, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x48, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA4, 0xA3, 0x15, 0x00, 0x70, 0xB5, 0x35, 0x4E, 0x33, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, 0x12, 0xDB, 0x90, 0xF8, 0xC1, 0x24, 0x31, 0x48, 0x8C, 0x23, 0x01, 0xEB, ++0x41, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, 0x1B, 0x7C, 0x01, 0x2B, 0x28, 0xD0, ++0x02, 0x2B, 0x1D, 0xD0, 0x00, 0x20, 0x70, 0xBD, 0x90, 0xF8, 0xC0, 0x34, 0x0B, 0xB1, 0x01, 0x29, 0x30, 0xD9, 0x27, 0x49, ++0x27, 0x48, 0x40, 0xF2, 0x14, 0x52, 0x04, 0xF0, 0xF3, 0xFB, 0x95, 0xF8, 0xC1, 0x24, 0x22, 0x48, 0x8C, 0x23, 0x04, 0xEB, ++0x44, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, 0x1B, 0x7C, 0x01, 0x2B, 0x0A, 0xD0, ++0x02, 0x2B, 0x13, 0xD1, 0x8C, 0x23, 0x0C, 0x44, 0x03, 0xFB, 0x02, 0xF1, 0x01, 0xEB, 0x04, 0x11, 0x01, 0x44, 0xC8, 0x68, ++0x70, 0xBD, 0x8C, 0x23, 0x0C, 0x44, 0x03, 0xFB, 0x02, 0xF1, 0x01, 0xEB, 0x04, 0x14, 0x01, 0x19, 0xC8, 0x68, 0x8B, 0x69, ++0x18, 0x44, 0x70, 0xBD, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC8, 0xDA, 0x10, 0xE0, 0x90, 0xF8, 0xC1, 0x24, ++0x0C, 0x48, 0x8C, 0x23, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, ++0x1B, 0x7C, 0x01, 0x2B, 0xDF, 0xD0, 0x02, 0x2B, 0xD4, 0xD0, 0x06, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0xA4, 0x62, 0x04, 0xF0, ++0xC9, 0xFB, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xB0, 0xA3, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x43, 0xD0, 0x2D, 0xE9, 0xF0, 0x41, ++0x28, 0x4F, 0x90, 0xF8, 0xC1, 0x24, 0x44, 0x68, 0x8C, 0x26, 0x06, 0xFB, 0x02, 0x76, 0x02, 0xEB, 0x82, 0x03, 0x96, 0xF8, ++0x73, 0xC0, 0x01, 0x25, 0xC3, 0xEB, 0xC3, 0x03, 0x24, 0xF0, 0x40, 0x04, 0x86, 0xF8, 0x86, 0x50, 0x4F, 0xEA, 0x83, 0x0E, ++0x07, 0xEB, 0x83, 0x05, 0x44, 0x60, 0xBC, 0xF1, 0x00, 0x0F, 0x06, 0xD1, 0x1C, 0x4E, 0x28, 0x46, 0xD6, 0xF8, 0x18, 0x32, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x96, 0xF8, 0x70, 0x30, 0x01, 0xEB, 0x8C, 0x24, 0x3B, 0xB9, 0x17, 0x4B, 0x18, 0x69, ++0x01, 0xF5, 0x96, 0x73, 0xC1, 0x1A, 0x11, 0xF1, 0x32, 0x0F, 0x14, 0xD4, 0x8C, 0x23, 0x03, 0xFB, 0x02, 0x72, 0x11, 0x4E, ++0x0E, 0xF1, 0x60, 0x00, 0x01, 0x23, 0x38, 0x44, 0x21, 0x46, 0x82, 0xF8, 0x72, 0x30, 0xD6, 0xF8, 0xE0, 0x31, 0x98, 0x47, ++0xD6, 0xF8, 0x18, 0x32, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x70, 0x47, 0x08, 0x4D, 0x74, 0x67, 0x0E, 0xF1, ++0x60, 0x00, 0x02, 0x22, 0x38, 0x44, 0x19, 0x46, 0x86, 0xF8, 0x72, 0x20, 0xD5, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0xB4, 0x0A, 0x49, ++0x90, 0xF8, 0xC1, 0x34, 0x09, 0x4C, 0x8C, 0x20, 0x03, 0xEB, 0x83, 0x02, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x25, 0xC2, 0xEB, ++0xC2, 0x02, 0x83, 0xF8, 0x86, 0x50, 0x01, 0xEB, 0x82, 0x00, 0xD4, 0xF8, 0x18, 0x32, 0x30, 0xBC, 0x18, 0x47, 0x00, 0xBF, ++0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x90, 0xF8, 0xC0, 0x44, 0x00, 0x2C, 0x3E, 0xD0, ++0x90, 0xF8, 0x62, 0x30, 0x05, 0x46, 0x00, 0x2B, 0x3C, 0xD1, 0x27, 0x4B, 0x90, 0xF8, 0xC1, 0x74, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x88, 0x46, 0x16, 0x46, 0x36, 0xDB, 0xD8, 0xF8, 0x08, 0x00, 0xB2, 0x8B, 0x00, 0xF1, 0x24, 0x03, ++0x10, 0x44, 0x83, 0x42, 0x02, 0xD3, 0x38, 0xE0, 0x98, 0x42, 0x36, 0xD9, 0x5D, 0x78, 0x1A, 0x78, 0xA9, 0x1C, 0xDD, 0x2A, ++0x1C, 0x46, 0x0B, 0x44, 0xF6, 0xD1, 0x62, 0x79, 0x09, 0x2A, 0xF3, 0xD1, 0x06, 0x34, 0x04, 0x3D, 0x14, 0xFA, 0x85, 0xF5, ++0xAC, 0x42, 0x06, 0xD3, 0xEC, 0xE7, 0xB4, 0xF8, 0x01, 0x10, 0x03, 0x31, 0x0C, 0x44, 0xA5, 0x42, 0xE6, 0xD9, 0x22, 0x78, ++0x0C, 0x2A, 0xF6, 0xD1, 0x00, 0x2C, 0xE1, 0xD0, 0xB2, 0x68, 0x0F, 0x4B, 0x92, 0x68, 0xD3, 0xF8, 0xF0, 0x31, 0x92, 0x69, ++0x38, 0x46, 0x21, 0x46, 0x98, 0x47, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x24, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, ++0x01, 0x2F, 0xC6, 0xD9, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x73, 0x52, 0x04, 0xF0, 0xD8, 0xFA, 0x95, 0xF8, 0xC1, 0x74, ++0xBD, 0xE7, 0x00, 0x24, 0xE2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xD8, 0xA3, 0x15, 0x00, 0xF0, 0xB5, 0x0C, 0x7E, 0x7F, 0x2C, 0x83, 0xB0, 0x23, 0xD1, 0x4A, 0x7F, 0x0A, 0xBB, 0xCA, 0x7F, ++0xDD, 0x2A, 0x1E, 0xD1, 0x91, 0xF8, 0x24, 0x20, 0x09, 0x2A, 0x1A, 0xD1, 0x91, 0xF8, 0x25, 0x20, 0x0C, 0x2A, 0x01, 0xF1, ++0x25, 0x04, 0x14, 0xD1, 0x11, 0x4A, 0x12, 0x49, 0x12, 0x68, 0xD1, 0xF8, 0xF0, 0x61, 0xB2, 0xF9, 0x00, 0x20, 0x90, 0xF8, ++0xC1, 0x74, 0x00, 0x2A, 0x05, 0x46, 0x0A, 0xDB, 0xEA, 0x6F, 0x21, 0x46, 0x1A, 0x44, 0x38, 0x46, 0x33, 0x46, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x40, 0x18, 0x47, 0x03, 0xB0, 0xF0, 0xBD, 0x90, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xF0, 0xD0, 0x06, 0x49, ++0x06, 0x48, 0x01, 0x93, 0x49, 0x22, 0x04, 0xF0, 0x95, 0xFA, 0x01, 0x9B, 0xE8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x12, 0x4B, 0x18, 0x78, 0xF8, 0xB1, 0x12, 0x4B, ++0x58, 0x7C, 0xD8, 0xB9, 0x9A, 0x7C, 0x01, 0x2A, 0x19, 0xD8, 0x9B, 0x68, 0x13, 0xB9, 0x16, 0xE0, 0x1B, 0x68, 0xAB, 0xB1, ++0x93, 0xF8, 0x62, 0x20, 0x02, 0x2A, 0xF9, 0xD1, 0x93, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0xF5, 0xD0, 0x93, 0xF8, 0xC1, 0x34, ++0x08, 0x4A, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x85, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x44, 0x9E, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, ++0x18, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x1B, 0xB1, 0x90, 0xF8, 0x62, 0x30, ++0x02, 0x2B, 0x00, 0xD0, 0x70, 0x47, 0x70, 0xB5, 0x90, 0xF8, 0xC1, 0x34, 0x11, 0x4C, 0x8C, 0x22, 0x02, 0xFB, 0x03, 0x42, ++0x00, 0x39, 0x03, 0xEB, 0x83, 0x03, 0x92, 0xF8, 0x84, 0x50, 0x18, 0xBF, 0x01, 0x21, 0xC3, 0xEB, 0xC3, 0x03, 0x82, 0xF8, ++0x87, 0x10, 0x04, 0xEB, 0x83, 0x04, 0x35, 0xB9, 0x09, 0x4D, 0xD5, 0xF8, 0x18, 0x32, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, ++0x18, 0x47, 0x06, 0x4D, 0x92, 0xF8, 0x71, 0x00, 0xD5, 0xF8, 0x90, 0x31, 0x03, 0x21, 0x98, 0x47, 0xF1, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0E, 0x4E, 0x90, 0xF8, 0xC1, 0x44, ++0x0D, 0x4D, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0x01, 0x22, 0x04, 0xEB, 0x84, 0x04, 0x93, 0xF8, 0x71, 0x00, 0x83, 0xF8, ++0x73, 0x10, 0x83, 0xF8, 0x72, 0x20, 0xC4, 0xEB, 0xC4, 0x04, 0xD5, 0xF8, 0x90, 0x31, 0x03, 0x21, 0x98, 0x47, 0xD5, 0xF8, ++0x18, 0x32, 0x06, 0xEB, 0x84, 0x00, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x1D, 0x4F, 0x90, 0xF8, 0xC1, 0x44, 0x8C, 0x26, 0x06, 0xFB, 0x04, 0x76, 0x04, 0xEB, 0x84, 0x00, ++0x96, 0xF8, 0x72, 0x20, 0xC0, 0xEB, 0xC0, 0x00, 0x4F, 0xF0, 0x00, 0x09, 0x07, 0xEB, 0x80, 0x05, 0x86, 0xF8, 0x73, 0x90, ++0x9A, 0xB9, 0xDF, 0xF8, 0x54, 0x80, 0xD8, 0xF8, 0x18, 0x32, 0x28, 0x46, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x74, ++0x94, 0xF8, 0x79, 0x30, 0x9B, 0xB9, 0xD8, 0xF8, 0x90, 0x31, 0x94, 0xF8, 0x71, 0x00, 0x02, 0x21, 0xBD, 0xE8, 0xF0, 0x47, ++0x18, 0x47, 0x83, 0x00, 0xDF, 0xF8, 0x28, 0x80, 0x03, 0xF1, 0x60, 0x00, 0x38, 0x44, 0xD8, 0xF8, 0xD8, 0x31, 0x98, 0x47, ++0x86, 0xF8, 0x72, 0x90, 0xE1, 0xE7, 0xD8, 0xF8, 0x90, 0x31, 0x94, 0xF8, 0x71, 0x00, 0x03, 0x21, 0xBD, 0xE8, 0xF0, 0x47, ++0x18, 0x47, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x90, 0xF8, 0xC0, 0x34, 0x63, 0xB1, 0x90, 0xF8, ++0xC1, 0x34, 0x06, 0x4A, 0x06, 0x48, 0x03, 0xEB, 0x83, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x00, 0xEB, 0x83, 0x00, 0xD2, 0xF8, ++0x18, 0x32, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x42, 0x4E, 0x90, 0xF8, 0xC1, 0x84, 0xDD, 0xF8, 0x30, 0xC0, 0x8C, 0x24, 0x04, 0xFB, 0x08, 0x64, 0x94, 0xF8, 0x70, 0x70, ++0x01, 0x2F, 0x0F, 0xD1, 0x08, 0xEB, 0x88, 0x05, 0x94, 0xF8, 0x10, 0x90, 0xC5, 0xEB, 0xC5, 0x05, 0xA8, 0x00, 0x06, 0xEB, ++0x85, 0x05, 0xB9, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x94, 0xF8, 0x40, 0x40, 0x00, 0x2C, 0x64, 0xD0, 0x4F, 0xF0, 0xFF, 0x09, ++0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x28, 0x46, 0xCA, 0x46, 0x8C, 0x24, 0x4F, 0xEA, 0x4A, 0x07, 0x04, 0xFB, 0x08, 0xF4, ++0x07, 0xEB, 0x0A, 0x0B, 0x06, 0xEB, 0x04, 0x0E, 0x04, 0xEB, 0x0B, 0x14, 0x00, 0x29, 0x06, 0xEB, 0x04, 0x01, 0x9E, 0xF8, ++0x79, 0xB0, 0xCB, 0x74, 0x0B, 0x75, 0x0A, 0x9B, 0xCB, 0x61, 0x0B, 0xF1, 0x01, 0x0B, 0x0B, 0x9B, 0x8B, 0x61, 0x0C, 0xBF, ++0x01, 0x24, 0x00, 0x24, 0xC1, 0xF8, 0x24, 0xC0, 0x81, 0xF8, 0x21, 0x20, 0x81, 0xF8, 0x20, 0x40, 0x8E, 0xF8, 0x79, 0xB0, ++0x04, 0xD0, 0x9E, 0xF8, 0x7A, 0x30, 0x01, 0x33, 0x8E, 0xF8, 0x7A, 0x30, 0x0A, 0x9B, 0x73, 0xB1, 0x8C, 0x23, 0x07, 0xEB, ++0x0A, 0x02, 0x03, 0xFB, 0x08, 0xF3, 0x03, 0xEB, 0x02, 0x13, 0x33, 0x44, 0x0A, 0x99, 0x4F, 0xF0, 0x00, 0x42, 0xB2, 0xFB, ++0xF1, 0xF2, 0x01, 0x3A, 0x9A, 0x62, 0x15, 0x4C, 0x61, 0x46, 0xD4, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, ++0x08, 0xF8, 0x57, 0x44, 0x08, 0xEB, 0x07, 0x17, 0x37, 0x44, 0x46, 0x44, 0x01, 0x23, 0x96, 0xF8, 0x71, 0x00, 0x3B, 0x74, ++0x03, 0x21, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x47, 0x49, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0xA4, 0xFA, 0xD4, 0xF8, 0x1C, 0x32, ++0x28, 0x46, 0x98, 0x47, 0x28, 0x46, 0xD4, 0xF8, 0x18, 0x32, 0x98, 0x47, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x30, 0x30, ++0xB9, 0x46, 0x30, 0x44, 0xBA, 0x46, 0x9C, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x90, 0xF8, 0xC1, 0x64, 0x37, 0x4D, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0xF3, 0xE8, 0x18, 0x90, 0xF8, 0x70, 0x00, 0x01, 0x28, ++0x5C, 0xD1, 0x01, 0x29, 0x0C, 0x46, 0x57, 0xD8, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x01, 0x13, 0x2B, 0x44, 0x4F, 0xEA, ++0x44, 0x08, 0x19, 0x7C, 0x00, 0x29, 0x4D, 0xD0, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x48, 0xD0, 0x06, 0xEB, ++0x86, 0x07, 0x04, 0xEB, 0x44, 0x00, 0xDF, 0xF8, 0xA4, 0x90, 0xC7, 0xEB, 0xC7, 0x07, 0x00, 0x01, 0x00, 0xEB, 0x87, 0x00, ++0xD9, 0xF8, 0xD8, 0x31, 0x28, 0x44, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0xFA, 0xA0, 0x44, 0x0A, 0xEB, 0x08, 0x18, ++0xA8, 0x44, 0x00, 0x23, 0x05, 0xEB, 0x87, 0x07, 0x88, 0xF8, 0x10, 0x30, 0xD9, 0xF8, 0x1C, 0x22, 0x38, 0x46, 0x90, 0x47, ++0xD9, 0xF8, 0x18, 0x22, 0x38, 0x46, 0x90, 0x47, 0x05, 0xEB, 0x0A, 0x03, 0x98, 0xF8, 0x20, 0x10, 0x93, 0xF8, 0x79, 0x20, ++0x01, 0x3A, 0xD2, 0xB2, 0x01, 0x29, 0x83, 0xF8, 0x79, 0x20, 0x04, 0xD1, 0x93, 0xF8, 0x7A, 0x10, 0x01, 0x39, 0x83, 0xF8, ++0x7A, 0x10, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0x53, 0x93, 0xF8, 0x73, 0x10, 0x01, 0xB9, 0x92, 0xB1, 0x8C, 0x23, 0x03, 0xFB, ++0x06, 0x55, 0x03, 0x21, 0xD9, 0xF8, 0x90, 0x31, 0x95, 0xF8, 0x71, 0x00, 0x98, 0x47, 0x38, 0x46, 0x21, 0x46, 0xFF, 0xF7, ++0x29, 0xFA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xD9, 0xF8, 0x90, 0x21, 0x93, 0xF8, ++0x71, 0x00, 0x02, 0x21, 0x90, 0x47, 0xEE, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x1F, 0x4F, 0x90, 0xF8, 0xC1, 0x84, 0x8C, 0x25, 0x05, 0xFB, 0x08, 0x75, 0x08, 0xEB, 0x88, 0x03, 0x95, 0xF8, 0x20, 0x20, ++0xC3, 0xEB, 0xC3, 0x03, 0x0E, 0x46, 0x9C, 0x00, 0xAA, 0xB9, 0x2B, 0x7C, 0x9B, 0xB1, 0xE9, 0x68, 0xDF, 0xF8, 0x5C, 0x90, ++0x31, 0x44, 0xD9, 0xF8, 0xE0, 0x31, 0x38, 0x19, 0x98, 0x47, 0x95, 0xF8, 0x50, 0x30, 0x13, 0xB9, 0x95, 0xF8, 0x40, 0x30, ++0x6B, 0xB9, 0xD9, 0xF8, 0x1C, 0x32, 0x38, 0x19, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x95, 0xF8, 0x50, 0x30, 0xAB, 0xB9, ++0x95, 0xF8, 0x40, 0x30, 0x93, 0xB1, 0xDF, 0xF8, 0x2C, 0x90, 0x8C, 0x23, 0x03, 0xFB, 0x08, 0x73, 0x04, 0xF1, 0x30, 0x00, ++0xD9, 0x6B, 0xD9, 0xF8, 0xE0, 0x31, 0x38, 0x44, 0x31, 0x44, 0x98, 0x47, 0xD9, 0xF8, 0x1C, 0x32, 0x38, 0x19, 0xBD, 0xE8, ++0xF0, 0x47, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x87, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x0A, 0x4B, 0x8C, 0x22, ++0x02, 0xFB, 0x00, 0x33, 0x93, 0xF8, 0x71, 0x20, 0xFF, 0x2A, 0x0B, 0xD0, 0x93, 0xF8, 0x84, 0x00, 0x48, 0xB1, 0x93, 0xF8, ++0x88, 0x00, 0x00, 0xEB, 0x40, 0x03, 0x00, 0xEB, 0x83, 0x00, 0x0B, 0x30, 0xC0, 0xB2, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x48, 0x9E, 0x17, 0x00, 0x30, 0xB4, 0xDD, 0x23, 0x50, 0x25, 0x6F, 0x24, 0x9A, 0x21, 0x09, 0x22, 0x03, 0x70, 0x0C, 0x23, ++0x85, 0x70, 0xC4, 0x70, 0x01, 0x71, 0x42, 0x71, 0x83, 0x71, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x43, ++0x2D, 0x4E, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x63, 0x93, 0xF8, 0x78, 0x20, 0x4A, 0x72, 0x93, 0xF8, 0x73, 0x40, 0x01, 0x32, ++0x83, 0xF8, 0x78, 0x20, 0x00, 0x2C, 0x46, 0xD0, 0x64, 0xF0, 0x7F, 0x04, 0x8C, 0x72, 0x00, 0xEB, 0x80, 0x03, 0xC3, 0xEB, ++0xC3, 0x03, 0x4F, 0xF0, 0x8C, 0x0C, 0xDF, 0xF8, 0x8C, 0x90, 0xDF, 0xF8, 0x8C, 0x80, 0x06, 0xEB, 0x83, 0x03, 0x0C, 0xFB, ++0x00, 0x6C, 0x01, 0xF1, 0x0B, 0x02, 0x01, 0xF1, 0x25, 0x0E, 0x00, 0x24, 0x1D, 0x7C, 0xC5, 0xB1, 0x9C, 0xF8, 0x87, 0x50, ++0x15, 0xB1, 0x93, 0xF8, 0x21, 0x50, 0x55, 0xBB, 0x1D, 0x7D, 0x15, 0x70, 0xD3, 0xE9, 0x06, 0x57, 0xC2, 0xF8, 0x01, 0x50, ++0xC2, 0xF8, 0x05, 0x70, 0xD9, 0xF8, 0x00, 0x50, 0xD8, 0xF8, 0x10, 0x70, 0xED, 0x1B, 0x5F, 0x6A, 0x01, 0x34, 0x3D, 0x44, ++0xE4, 0xB2, 0xC2, 0xF8, 0x09, 0x50, 0x0D, 0x32, 0x72, 0x45, 0x03, 0xF1, 0x30, 0x03, 0xDF, 0xD1, 0x8C, 0x22, 0x04, 0xEB, ++0x44, 0x03, 0x04, 0xEB, 0x83, 0x03, 0x02, 0xFB, 0x00, 0x60, 0x03, 0xF1, 0x09, 0x02, 0x80, 0xF8, 0x88, 0x40, 0x02, 0x33, ++0x4A, 0x70, 0xA1, 0xF8, 0x07, 0x30, 0xBD, 0xE8, 0xF0, 0x83, 0x8C, 0x72, 0xB9, 0xE7, 0x93, 0xF8, 0x20, 0x50, 0x01, 0x2D, ++0xD0, 0xD1, 0xE2, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0xA4, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x02, 0x29, 0x20, 0xD0, ++0x03, 0x29, 0x0F, 0xD0, 0x01, 0x29, 0x06, 0xD0, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1E, 0xDB, ++0x70, 0x47, 0x13, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x80, 0xF8, 0x84, 0x10, 0x70, 0x47, 0x0F, 0x4B, 0x8C, 0x22, ++0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0x84, 0x30, 0x00, 0x2B, 0xEF, 0xD1, 0x0C, 0x4B, 0x90, 0xF8, 0x71, 0x00, 0xD3, 0xF8, ++0x90, 0x31, 0x01, 0x21, 0x18, 0x47, 0x08, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x00, 0x23, 0x80, 0xF8, 0x84, 0x30, ++0x70, 0x47, 0x06, 0x49, 0x06, 0x48, 0x4F, 0xF4, 0xEA, 0x62, 0x03, 0xF0, 0xA5, 0xBF, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x90, 0xF8, 0xC0, 0x34, ++0x33, 0xB1, 0x90, 0xF8, 0x64, 0x30, 0x1B, 0xB1, 0x43, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x43, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0x2D, 0xE9, 0xF0, 0x47, 0x36, 0x4F, 0x02, 0x7E, 0xDF, 0xF8, 0xE0, 0x80, 0x35, 0x49, 0xD8, 0xF8, 0xB0, 0x33, 0x0E, 0x69, ++0x05, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x70, 0x98, 0x47, 0xEB, 0x7E, 0x00, 0x2B, 0x3A, 0xD0, 0xD5, 0xE9, ++0x04, 0x43, 0x02, 0x2C, 0x8C, 0xBF, 0x01, 0x24, 0x00, 0x24, 0x02, 0x2B, 0x6B, 0x7E, 0x95, 0xF8, 0x18, 0xA0, 0x88, 0xBF, ++0x44, 0xF0, 0x02, 0x04, 0x63, 0x40, 0x9B, 0x07, 0x44, 0xD1, 0xD1, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x0A, 0x7A, ++0x6C, 0x76, 0xDA, 0xF8, 0xE4, 0x00, 0x18, 0xB3, 0xDF, 0xF8, 0x94, 0xC0, 0x4F, 0xF0, 0x00, 0x0E, 0x90, 0xF8, 0x23, 0x10, ++0x00, 0x68, 0x01, 0xEB, 0x41, 0x04, 0x64, 0x44, 0x4B, 0x00, 0x62, 0x78, 0xA4, 0x78, 0x02, 0x2A, 0x0B, 0x44, 0x88, 0xBF, ++0x01, 0x22, 0x0C, 0xEB, 0x03, 0x01, 0x98, 0xBF, 0x00, 0x22, 0x02, 0x2C, 0x88, 0xBF, 0x42, 0xF0, 0x02, 0x02, 0x0C, 0xF8, ++0x03, 0x20, 0x81, 0xF8, 0x01, 0xE0, 0x81, 0xF8, 0x02, 0xE0, 0x00, 0x28, 0xE2, 0xD1, 0x01, 0xE0, 0x95, 0xF8, 0x18, 0x90, ++0x11, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x77, 0x9B, 0x6A, 0x39, 0x6C, 0x00, 0x22, 0x5B, 0x1A, 0xC5, 0xE9, ++0x04, 0x22, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0x06, 0xF5, 0xC3, 0x31, 0xEB, 0x76, 0xD8, 0xF8, 0xE0, 0x31, 0x28, 0x46, ++0xA0, 0x31, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x21, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0xC4, 0xFC, 0x95, 0xF8, 0x18, 0x90, ++0xB4, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x60, 0x9F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x10, 0x4D, 0xDF, 0xF8, 0x44, 0x80, 0xC0, 0xEB, 0xC0, 0x03, 0x05, 0xEB, ++0x83, 0x03, 0xC0, 0xEB, 0xC0, 0x06, 0x9B, 0x7E, 0x04, 0x46, 0x05, 0xEB, 0x86, 0x06, 0xC7, 0x00, 0x1B, 0xB1, 0xD8, 0xF8, ++0xD8, 0x31, 0x30, 0x46, 0x98, 0x47, 0x3F, 0x1B, 0x05, 0xEB, 0x87, 0x05, 0x1C, 0x22, 0x00, 0x21, 0x30, 0x46, 0xDF, 0xF7, ++0x0F, 0xFA, 0xD8, 0xF8, 0x34, 0x33, 0xAE, 0x60, 0x2C, 0x76, 0x6B, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x80, 0x9F, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x00, 0x20, 0xFF, 0xF7, 0xD4, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0xD1, 0xFF, 0x02, 0x20, ++0xFF, 0xF7, 0xCE, 0xFF, 0x03, 0x20, 0xFF, 0xF7, 0xCB, 0xFF, 0x05, 0x4B, 0x00, 0x22, 0x03, 0xF1, 0x1E, 0x01, 0x5A, 0x70, ++0x9A, 0x70, 0x03, 0xF8, 0x03, 0x2B, 0x8B, 0x42, 0xF9, 0xD1, 0x08, 0xBD, 0x60, 0x9F, 0x17, 0x00, 0x0B, 0x4A, 0xC0, 0xEB, ++0xC0, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x99, 0x7E, 0x71, 0xB9, 0x30, 0xB4, 0x08, 0x49, 0x09, 0x4C, 0x09, 0x69, 0xD4, 0xF8, ++0xE0, 0x41, 0x01, 0x25, 0x01, 0xF5, 0xC3, 0x31, 0x9D, 0x76, 0x18, 0x46, 0xA0, 0x31, 0x23, 0x46, 0x30, 0xBC, 0x18, 0x47, ++0x70, 0x47, 0x00, 0xBF, 0x80, 0x9F, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x09, 0x29, 0x08, 0xB5, ++0x09, 0xD9, 0x6A, 0xBB, 0x21, 0x4B, 0xC0, 0xEB, 0xC0, 0x00, 0x03, 0xEB, 0x80, 0x00, 0x03, 0x69, 0x01, 0x33, 0x03, 0x61, ++0x08, 0xBD, 0x8A, 0xB1, 0x1C, 0x4B, 0x1D, 0x4A, 0xC0, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x80, 0x00, ++0x11, 0x44, 0x42, 0x69, 0x8B, 0x78, 0x01, 0x32, 0x02, 0x2B, 0x42, 0x61, 0xEE, 0xD8, 0x01, 0x33, 0x8B, 0x70, 0x08, 0xBD, ++0x13, 0x4B, 0x14, 0x4A, 0xC0, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x80, 0x00, 0x11, 0x44, 0x03, 0x69, ++0x4A, 0x78, 0x01, 0x33, 0x02, 0x2A, 0x03, 0x61, 0xDC, 0xD8, 0x01, 0x32, 0x4A, 0x70, 0x08, 0xBD, 0x0A, 0x4A, 0x0C, 0x4B, ++0x1C, 0x21, 0x01, 0xFB, 0x00, 0x20, 0x1A, 0x68, 0x43, 0x69, 0xB2, 0xF9, 0x00, 0x20, 0x01, 0x33, 0x00, 0x2A, 0x43, 0x61, ++0x05, 0xDA, 0x07, 0x49, 0x07, 0x48, 0x40, 0xF2, 0x69, 0x12, 0x03, 0xF0, 0x6F, 0xFE, 0x00, 0x23, 0x9B, 0x78, 0xFF, 0xDE, ++0x80, 0x9F, 0x17, 0x00, 0x60, 0x9F, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF8, 0xA3, 0x15, 0x00, ++0x70, 0xB5, 0x1E, 0x46, 0x0D, 0x46, 0x01, 0x23, 0x31, 0x46, 0x40, 0xF6, 0x01, 0x00, 0x01, 0xF0, 0x77, 0xFD, 0x04, 0x46, ++0x02, 0x20, 0x02, 0xF0, 0x15, 0xF8, 0x18, 0x4A, 0x18, 0x49, 0x03, 0x46, 0x04, 0x20, 0x03, 0xF0, 0x25, 0xFC, 0x02, 0x20, ++0x02, 0xF0, 0x0C, 0xF8, 0xA0, 0xB9, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x16, 0xDB, 0x13, 0x4A, ++0x00, 0x23, 0x23, 0x70, 0x28, 0x46, 0x15, 0x60, 0x93, 0x72, 0x16, 0x81, 0x01, 0x25, 0x00, 0xF0, 0x7D, 0xF9, 0x20, 0x46, ++0x01, 0xF0, 0x86, 0xFD, 0x28, 0x46, 0x70, 0xBD, 0x08, 0x23, 0x20, 0x46, 0x23, 0x70, 0x00, 0x25, 0x01, 0xF0, 0x7E, 0xFD, ++0x28, 0x46, 0x70, 0xBD, 0x95, 0xF8, 0x6F, 0x31, 0x00, 0x2B, 0xE4, 0xD1, 0x06, 0x49, 0x07, 0x48, 0x46, 0x22, 0x03, 0xF0, ++0x25, 0xFE, 0xDE, 0xE7, 0x84, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xF4, 0x9F, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x08, 0xA4, 0x15, 0x00, 0x17, 0x4A, 0x18, 0x4B, 0x12, 0x68, 0x70, 0xB5, 0xB2, 0xF9, 0x00, 0x20, ++0x1D, 0x68, 0x9C, 0x7A, 0x00, 0x2A, 0x19, 0xDB, 0x14, 0x4A, 0x15, 0x48, 0xD2, 0xE9, 0x00, 0x63, 0x04, 0xEB, 0x44, 0x04, ++0x05, 0xEB, 0x44, 0x04, 0x43, 0xF4, 0x08, 0x53, 0xE1, 0x78, 0x53, 0x60, 0x33, 0x43, 0x03, 0x60, 0xCB, 0x07, 0x03, 0xD4, ++0x0E, 0x4B, 0xD3, 0xF8, 0xEC, 0x32, 0x98, 0x47, 0x03, 0x21, 0x02, 0x20, 0x01, 0xF0, 0x0E, 0xFF, 0x00, 0x20, 0x70, 0xBD, ++0x02, 0x20, 0x01, 0xF0, 0xB1, 0xFF, 0x02, 0x28, 0xE0, 0xD0, 0x08, 0x49, 0x08, 0x48, 0x9C, 0x22, 0x03, 0xF0, 0xEA, 0xFD, ++0xDA, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xF4, 0x9F, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x1C, 0xA4, 0x15, 0x00, 0x38, 0xB5, 0x22, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x32, 0xDB, 0x20, 0x49, 0x20, 0x48, 0x21, 0x4C, 0xD1, 0xE9, 0x00, 0x32, 0x22, 0xF4, 0x08, 0x52, ++0x13, 0x43, 0x03, 0x60, 0xA3, 0x7A, 0x20, 0x68, 0x4A, 0x60, 0x90, 0xF8, 0x6F, 0x51, 0x01, 0x33, 0xDB, 0xB2, 0x9D, 0x42, ++0xA3, 0x72, 0x01, 0xD9, 0xE3, 0x7A, 0x93, 0xB1, 0x0C, 0x38, 0x01, 0xF0, 0x55, 0xFD, 0xE3, 0x7A, 0x8B, 0xB1, 0x16, 0x4B, ++0x21, 0x89, 0xD3, 0xF8, 0xF0, 0x32, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0xE3, 0x72, 0x00, 0x21, 0x02, 0x20, 0x01, 0xF0, ++0xC5, 0xFE, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xF0, 0x8D, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x21, 0x89, 0x02, 0x22, 0x40, 0xF6, ++0x02, 0x00, 0x01, 0xF0, 0x27, 0xFD, 0xEE, 0xE7, 0x02, 0x20, 0x01, 0xF0, 0x5D, 0xFF, 0x03, 0x28, 0xC7, 0xD0, 0x08, 0x49, ++0x08, 0x48, 0xC2, 0x22, 0x03, 0xF0, 0x96, 0xFD, 0xC1, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x60, 0x00, 0x32, 0x40, 0xF4, 0x9F, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x4C, 0xA4, 0x15, 0x00, ++0x38, 0xB5, 0x02, 0x20, 0x1D, 0x46, 0x01, 0xF0, 0x41, 0xFF, 0x0A, 0x4A, 0x0A, 0x49, 0x04, 0x46, 0x03, 0x46, 0x04, 0x20, ++0x03, 0xF0, 0x50, 0xFB, 0x24, 0xB1, 0x08, 0x4B, 0x01, 0x22, 0xDA, 0x72, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x4B, 0x29, 0x46, ++0xD3, 0xF8, 0xF0, 0x32, 0x01, 0x20, 0x98, 0x47, 0x00, 0x20, 0x38, 0xBD, 0x9C, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, ++0xF4, 0x9F, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x15, 0x4A, 0x03, 0x88, 0x11, 0x68, 0x40, 0xF6, 0x6C, 0x12, 0x93, 0x42, ++0x08, 0x69, 0x1F, 0xD0, 0x40, 0xF6, 0x85, 0x12, 0x93, 0x42, 0x1B, 0xD0, 0x40, 0xF6, 0x9E, 0x12, 0x93, 0x42, 0x17, 0xD0, ++0x40, 0xF6, 0xA8, 0x12, 0x93, 0x42, 0x13, 0xD0, 0x41, 0xF2, 0x3C, 0x42, 0x93, 0x42, 0x0F, 0xD0, 0x41, 0xF2, 0x64, 0x42, ++0x93, 0x42, 0x0B, 0xD0, 0x41, 0xF2, 0x85, 0x62, 0x93, 0x42, 0x07, 0xD0, 0x41, 0xF2, 0x99, 0x62, 0x93, 0x42, 0x03, 0xD0, ++0x41, 0xF2, 0xAD, 0x62, 0x93, 0x42, 0x02, 0xD1, 0x00, 0xF5, 0x9C, 0x40, 0x20, 0x30, 0x70, 0x47, 0xC8, 0x35, 0x17, 0x00, ++0x08, 0xB5, 0x0C, 0x22, 0x00, 0x21, 0x08, 0x48, 0xDF, 0xF7, 0x48, 0xF8, 0x00, 0x21, 0x02, 0x20, 0x01, 0xF0, 0x44, 0xFE, ++0x05, 0x4B, 0x06, 0x4A, 0x1A, 0x60, 0x03, 0xF1, 0x14, 0x01, 0x00, 0x22, 0x99, 0x60, 0x1A, 0x61, 0x5A, 0x60, 0x08, 0xBD, ++0xF4, 0x9F, 0x17, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xDE, 0xFA, 0xFE, 0xCA, 0x2D, 0xE9, 0xF0, 0x41, 0x2A, 0x4F, 0xBB, 0x7A, ++0x3E, 0x68, 0x03, 0xEB, 0x43, 0x03, 0x06, 0xEB, 0x43, 0x05, 0x82, 0xB0, 0x95, 0xF8, 0x03, 0x80, 0x18, 0xF0, 0x05, 0x0F, ++0x4F, 0xEA, 0x43, 0x04, 0x28, 0xD0, 0x24, 0x4B, 0x1B, 0x68, 0x5B, 0x69, 0x96, 0xF8, 0x6E, 0xC1, 0x95, 0xF9, 0x04, 0x20, ++0x31, 0x5B, 0xA8, 0x78, 0xCD, 0xE9, 0x00, 0x8C, 0xFC, 0xF7, 0x94, 0xFC, 0x7B, 0x68, 0x93, 0xB1, 0xAA, 0x78, 0x31, 0x5B, ++0xDA, 0xB9, 0xA1, 0xF6, 0x6C, 0x10, 0x48, 0x28, 0x0A, 0xD8, 0x40, 0xF6, 0xB4, 0x12, 0x91, 0x42, 0x28, 0xD0, 0x18, 0x48, ++0xA1, 0xF6, 0x67, 0x12, 0xA0, 0xFB, 0x02, 0x12, 0xC2, 0xF3, 0x87, 0x02, 0x9A, 0x70, 0x02, 0x21, 0x08, 0x46, 0x02, 0xB0, ++0xBD, 0xE8, 0xF0, 0x41, 0x01, 0xF0, 0xFA, 0xBD, 0x28, 0x46, 0xFF, 0xF7, 0x7B, 0xFF, 0x03, 0x46, 0xD4, 0xE7, 0x01, 0x2A, ++0x02, 0xD0, 0x00, 0x22, 0x9A, 0x70, 0xEE, 0xE7, 0xA1, 0xF5, 0x9C, 0x51, 0xA1, 0xF1, 0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, ++0x4D, 0x7F, 0xF4, 0xD8, 0x07, 0x4A, 0x08, 0x39, 0xA2, 0xFB, 0x01, 0x12, 0xC2, 0xF3, 0x87, 0x02, 0x9A, 0x70, 0xDE, 0xE7, ++0x0E, 0x22, 0x9A, 0x70, 0xDB, 0xE7, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, ++0x70, 0xB5, 0x0B, 0x4E, 0x0B, 0x4C, 0x33, 0x68, 0x05, 0x46, 0xB3, 0xF8, 0x6C, 0x11, 0x20, 0x46, 0x02, 0xF0, 0x7A, 0xFB, ++0x70, 0x60, 0xFF, 0xF7, 0x95, 0xFF, 0x54, 0xF8, 0x0C, 0x2C, 0xB5, 0xF8, 0x6C, 0x11, 0x01, 0x3A, 0x0A, 0x44, 0x00, 0x21, ++0x44, 0xE9, 0x02, 0x21, 0x70, 0xBD, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0xE8, 0x61, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0xDF, 0xF8, 0xD8, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x93, 0x06, 0x46, 0x93, 0xF8, 0xC0, 0x04, 0x93, 0xF8, ++0x6C, 0x50, 0x88, 0x46, 0x17, 0x46, 0x00, 0x28, 0x52, 0xD1, 0x1B, 0x6C, 0x18, 0x79, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, ++0x1A, 0x21, 0xEE, 0xF7, 0x75, 0xFE, 0x04, 0x46, 0x00, 0x28, 0x4E, 0xD0, 0x28, 0x4A, 0xDF, 0xF8, 0xA8, 0xE0, 0x4F, 0xF4, ++0x1E, 0x71, 0x01, 0xFB, 0x05, 0x21, 0xD0, 0xE9, 0x12, 0x3C, 0x0A, 0x46, 0xBE, 0xF8, 0xFC, 0x51, 0x52, 0xF8, 0x26, 0x0F, ++0xD8, 0x66, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x06, 0x99, 0x40, 0x20, 0x83, 0xF8, 0x68, 0x00, 0x90, 0x88, 0xA3, 0xF8, ++0x70, 0x00, 0xD9, 0xF8, 0x5C, 0x00, 0xB9, 0xF8, 0x60, 0x90, 0xC3, 0xF8, 0x72, 0x00, 0x01, 0x35, 0x90, 0x88, 0xA3, 0xF8, ++0x76, 0x90, 0xAD, 0xB2, 0xD2, 0xF8, 0x00, 0x90, 0xA3, 0xF8, 0x7C, 0x00, 0x00, 0x20, 0x83, 0xF8, 0x69, 0x00, 0x83, 0xF8, ++0x6A, 0x00, 0x83, 0xF8, 0x6B, 0x00, 0xC3, 0xF8, 0x78, 0x90, 0xAE, 0xF8, 0xFC, 0x51, 0x2D, 0x01, 0x83, 0xF8, 0x80, 0x00, ++0x83, 0xF8, 0x81, 0x00, 0xA3, 0xF8, 0x7E, 0x50, 0xCC, 0xF8, 0x20, 0x00, 0x26, 0x77, 0x91, 0xF8, 0x23, 0x30, 0x63, 0x77, ++0xC4, 0xE9, 0x15, 0x87, 0x20, 0x46, 0x05, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xEE, 0xF7, 0x3A, 0xBE, 0x01, 0x20, 0x1A, 0x21, ++0xEE, 0xF7, 0x26, 0xFE, 0x04, 0x46, 0x00, 0x28, 0xB0, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x52, 0x4B, 0x83, 0xB0, 0x1D, 0x68, 0x9B, 0x7A, ++0x01, 0x93, 0x95, 0xF8, 0x70, 0x31, 0x95, 0xF8, 0x6E, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0x8B, 0x80, 0x4D, 0x4B, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x08, 0x38, 0x08, 0xF1, 0x5C, 0x07, 0x05, 0xF1, 0xFD, 0x09, 0x00, 0x26, 0x98, 0xF8, 0xC0, 0x34, ++0x00, 0x2B, 0x7F, 0xD1, 0x01, 0x9B, 0x03, 0xEB, 0x43, 0x03, 0x05, 0xEB, 0x43, 0x03, 0x9B, 0x78, 0x00, 0x2B, 0x77, 0xD1, ++0x95, 0xF8, 0x71, 0x01, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x19, 0xF8, 0x01, 0x3C, 0xB5, 0xF8, 0x6C, 0x11, 0x1A, 0x33, ++0x19, 0x44, 0xEE, 0xF7, 0xE9, 0xFD, 0x4A, 0x46, 0x01, 0x46, 0x00, 0x28, 0x63, 0xD0, 0xD0, 0xE9, 0x12, 0x3C, 0x40, 0x24, ++0x00, 0x20, 0x83, 0xF8, 0x68, 0x40, 0x83, 0xF8, 0x69, 0x00, 0x83, 0xF8, 0x6A, 0x00, 0x83, 0xF8, 0x6B, 0x00, 0x95, 0xF8, ++0x60, 0x01, 0xC0, 0x07, 0x58, 0xD4, 0xD5, 0xF8, 0x60, 0x01, 0xB5, 0xF8, 0x64, 0x41, 0xA3, 0xF8, 0x70, 0x40, 0xD8, 0x66, ++0x05, 0xF5, 0xB0, 0x7A, 0xDF, 0xF8, 0xC0, 0xE0, 0x38, 0x68, 0xBE, 0xF8, 0xFC, 0x41, 0xB7, 0xF8, 0x04, 0xB0, 0xC3, 0xF8, ++0x72, 0x00, 0x01, 0x34, 0xDA, 0xF8, 0x00, 0x00, 0xBA, 0xF8, 0x04, 0xA0, 0xA3, 0xF8, 0x76, 0xB0, 0xA4, 0xB2, 0x4F, 0xF0, ++0x00, 0x0B, 0x98, 0x67, 0xA3, 0xF8, 0x7C, 0xA0, 0xAE, 0xF8, 0xFC, 0x41, 0x83, 0xF8, 0x80, 0xB0, 0x19, 0xF8, 0x01, 0x0C, ++0x83, 0xF8, 0x81, 0x00, 0x19, 0xF8, 0x01, 0x0C, 0x24, 0x01, 0xA3, 0xF8, 0x7E, 0x40, 0x40, 0xB1, 0x81, 0x33, 0x09, 0xEB, ++0x00, 0x04, 0x12, 0xF8, 0x01, 0x0B, 0x03, 0xF8, 0x01, 0x0F, 0xA2, 0x42, 0xF9, 0xD1, 0xB5, 0xF8, 0x6C, 0x21, 0xDC, 0xF8, ++0x28, 0x30, 0x16, 0x48, 0xCC, 0xF8, 0x20, 0x00, 0x9B, 0x1A, 0x00, 0x22, 0xCC, 0xF8, 0x28, 0x30, 0xC1, 0xE9, 0x15, 0x22, ++0x95, 0xF8, 0x6E, 0x31, 0x0B, 0x77, 0xFF, 0x23, 0x4B, 0x77, 0x08, 0x46, 0x05, 0x21, 0xEE, 0xF7, 0x99, 0xFD, 0x95, 0xF8, ++0x70, 0x31, 0x01, 0x36, 0xB3, 0x42, 0x09, 0xF1, 0x21, 0x09, 0x3F, 0xF7, 0x7F, 0xAF, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x01, 0x20, 0x8A, 0xE7, 0x07, 0x48, 0x04, 0x68, 0x80, 0x88, 0xDC, 0x66, 0xA3, 0xF8, 0x70, 0x00, 0x05, 0xF5, 0xB0, 0x7A, ++0xA6, 0xE7, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xAC, 0xB2, 0x15, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x38, 0xB5, 0x02, 0x22, 0x05, 0x46, 0x01, 0x23, 0x40, 0xF6, 0x04, 0x00, 0x01, 0xF0, 0x92, 0xFA, ++0x04, 0x46, 0x02, 0x20, 0x01, 0xF0, 0x30, 0xFD, 0x05, 0x4A, 0x06, 0x49, 0x03, 0x46, 0x04, 0x20, 0x03, 0xF0, 0x40, 0xF9, ++0x25, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0x38, 0x40, 0x01, 0xF0, 0xB2, 0xBA, 0xBC, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, ++0x03, 0x4A, 0x93, 0x7A, 0x10, 0x68, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x43, 0x00, 0x70, 0x47, 0xF4, 0x9F, 0x17, 0x00, ++0xC3, 0x78, 0x13, 0xF0, 0x05, 0x0F, 0x03, 0xD0, 0x02, 0x4B, 0x1B, 0x68, 0x58, 0x69, 0x70, 0x47, 0xFF, 0xF7, 0xE8, 0xBD, ++0xC8, 0x35, 0x17, 0x00, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDA, 0x0C, 0x4B, 0x1B, 0x68, ++0x1B, 0x07, 0x0D, 0xD1, 0x0B, 0x48, 0x0C, 0x49, 0x02, 0x68, 0x4B, 0x68, 0x22, 0xF0, 0x80, 0x02, 0x02, 0x60, 0x23, 0xF0, ++0x04, 0x03, 0x4F, 0xF0, 0x80, 0x60, 0x4B, 0x60, 0x01, 0xF0, 0x3C, 0xBE, 0x06, 0x49, 0x07, 0x48, 0x84, 0x22, 0x03, 0xF0, ++0xFB, 0xBA, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x5A, 0x4A, 0x5B, 0x49, 0x13, 0x68, 0xF0, 0xB4, 0x14, 0x68, 0x5A, 0x4E, ++0x5A, 0x4D, 0x24, 0xF0, 0xFF, 0x04, 0x04, 0x43, 0x14, 0x60, 0x14, 0x68, 0x17, 0x68, 0xC4, 0xF3, 0x09, 0x24, 0x27, 0xF4, ++0x7F, 0x37, 0xDB, 0xB2, 0x00, 0xFB, 0x04, 0xF4, 0x27, 0xF4, 0x40, 0x77, 0xB4, 0xFB, 0xF3, 0xF4, 0x01, 0xEA, 0x04, 0x24, ++0x3C, 0x43, 0x14, 0x60, 0x11, 0x68, 0x14, 0x68, 0xC1, 0xF3, 0x89, 0x41, 0x2C, 0x40, 0x00, 0xFB, 0x01, 0xF1, 0xB1, 0xFB, ++0xF3, 0xF1, 0x06, 0xEA, 0x81, 0x41, 0x21, 0x43, 0x11, 0x60, 0x11, 0x68, 0x49, 0x4E, 0x4A, 0x4C, 0x0D, 0x40, 0x45, 0xF0, ++0x89, 0x65, 0x15, 0x60, 0x32, 0x68, 0x35, 0x68, 0x47, 0x49, 0xC2, 0xF3, 0x0F, 0x22, 0x25, 0xF4, 0x7F, 0x05, 0x25, 0xF4, ++0x7F, 0x45, 0x00, 0xFB, 0x02, 0xF2, 0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x2A, 0x43, 0x32, 0x60, 0x0A, 0x68, ++0x0D, 0x68, 0x40, 0x4C, 0xC2, 0xF3, 0x09, 0x52, 0x25, 0xF0, 0x7F, 0x55, 0x00, 0xFB, 0x02, 0xF2, 0x25, 0xF4, 0x40, 0x15, ++0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x52, 0x2A, 0x43, 0x0A, 0x60, 0x0A, 0x68, 0x0C, 0x68, 0xC2, 0xF3, 0x09, 0x02, ++0x24, 0xF4, 0x7F, 0x74, 0x00, 0xFB, 0x02, 0xF2, 0x24, 0xF0, 0x03, 0x04, 0xB2, 0xFB, 0xF3, 0xF2, 0xC2, 0xF3, 0x09, 0x02, ++0x22, 0x43, 0x1D, 0x28, 0x0A, 0x60, 0x44, 0xD8, 0x4A, 0x68, 0x42, 0xF0, 0x03, 0x02, 0x4A, 0x60, 0x2E, 0x49, 0x2B, 0x4C, ++0x0A, 0x68, 0x2E, 0x4E, 0x0F, 0x68, 0x2E, 0x4D, 0xC2, 0xF3, 0x0F, 0x22, 0x37, 0x40, 0x00, 0xFB, 0x02, 0xF2, 0xB2, 0xFB, ++0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x3A, 0x43, 0x0A, 0x60, 0x2A, 0x68, 0x2F, 0x68, 0xC2, 0xF3, 0x0F, 0x22, 0x00, 0xFB, ++0x02, 0xF2, 0x3E, 0x40, 0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x32, 0x43, 0x2A, 0x60, 0x0A, 0x69, 0x0D, 0x69, ++0x1D, 0x4C, 0xC2, 0xF3, 0x09, 0x52, 0x25, 0xF0, 0x7F, 0x55, 0x00, 0xFB, 0x02, 0xF2, 0x25, 0xF4, 0x40, 0x15, 0xB2, 0xFB, ++0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x52, 0x2A, 0x43, 0x0A, 0x61, 0x0C, 0x69, 0x0A, 0x69, 0xC4, 0xF3, 0x09, 0x04, 0x22, 0xF4, ++0x7F, 0x72, 0x00, 0xFB, 0x04, 0xF0, 0x22, 0xF0, 0x03, 0x02, 0xB0, 0xFB, 0xF3, 0xF0, 0xC0, 0xF3, 0x09, 0x00, 0x10, 0x43, ++0xF0, 0xBC, 0x08, 0x61, 0x70, 0x47, 0x11, 0x49, 0x0A, 0x68, 0x3B, 0x28, 0x22, 0xF0, 0x03, 0x02, 0x94, 0xBF, 0x42, 0xF0, ++0x02, 0x02, 0x42, 0xF0, 0x01, 0x02, 0x0A, 0x60, 0xB2, 0xE7, 0x00, 0xBF, 0xE4, 0x00, 0x32, 0x40, 0x00, 0xFF, 0x03, 0x00, ++0x00, 0x00, 0xFC, 0x0F, 0xFF, 0xFF, 0x03, 0xF0, 0xE8, 0x00, 0x32, 0x40, 0x00, 0xFF, 0xFF, 0x00, 0xEC, 0x00, 0x32, 0x40, ++0x00, 0x00, 0xF0, 0x3F, 0xF4, 0x00, 0x32, 0x40, 0xFF, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x32, 0x40, 0xF0, 0x00, 0x32, 0x40, ++0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2C, 0xDB, 0xF0, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x18, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x18, 0x4B, 0x18, 0x49, 0x1B, 0x68, 0x0E, 0x68, 0x18, 0x4C, ++0x18, 0x4A, 0x19, 0x4D, 0x19, 0x4F, 0x03, 0xF5, 0xC3, 0x43, 0x28, 0x33, 0x70, 0x1C, 0x08, 0x60, 0x23, 0x60, 0x17, 0x4C, ++0x80, 0x23, 0x13, 0x60, 0x2A, 0x68, 0x63, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x43, 0xF0, 0x04, 0x03, 0x2A, 0x60, 0x63, 0x60, ++0x00, 0x23, 0x3B, 0x60, 0x28, 0xB1, 0x09, 0x4B, 0x0E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, ++0x70, 0x47, 0x0B, 0x4B, 0x1B, 0x68, 0x1A, 0x07, 0xCE, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0xD9, 0x22, 0x03, 0xF0, 0xE4, 0xB9, ++0x38, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x44, 0x01, 0x32, 0x40, ++0x88, 0x80, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xD4, 0xA4, 0x15, 0x00, 0x03, 0x4A, 0x01, 0x23, 0x13, 0x60, 0x13, 0x68, 0x13, 0xF0, 0xFF, 0x0F, 0xFB, 0xD1, 0x70, 0x47, ++0x50, 0x80, 0x32, 0x40, 0x70, 0xB5, 0x76, 0x4A, 0x01, 0x23, 0x82, 0xB0, 0x13, 0x60, 0x13, 0x68, 0x13, 0xF0, 0xFF, 0x0F, ++0xFB, 0xD1, 0x73, 0x4B, 0xD3, 0xF8, 0xF0, 0x40, 0xDE, 0xF7, 0x66, 0xFF, 0xA0, 0x47, 0x71, 0x4B, 0x71, 0x49, 0x72, 0x4A, ++0x19, 0x60, 0x13, 0x68, 0x71, 0x49, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x0B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x86, 0x80, 0x6D, 0x48, 0x6E, 0x4B, 0x6A, 0x49, 0x6E, 0x4C, 0x6E, 0x4A, 0x04, 0x60, 0x1A, 0x60, 0x0A, 0x68, ++0x6D, 0x4C, 0x6E, 0x4D, 0x42, 0xF0, 0x80, 0x62, 0x42, 0xF4, 0xF8, 0x62, 0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x62, ++0x0A, 0x60, 0x50, 0xF8, 0x84, 0x2C, 0x69, 0x49, 0xA3, 0xF5, 0x00, 0x43, 0x1C, 0x3B, 0x42, 0xF4, 0x80, 0x32, 0x40, 0xF8, ++0x84, 0x2C, 0x25, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x7F, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x02, 0x1A, 0x60, ++0x1A, 0x68, 0x22, 0xF4, 0xFE, 0x02, 0x42, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x8A, 0x78, 0x2A, 0xB9, 0x1A, 0x68, 0x12, 0x0C, ++0x12, 0x04, 0x42, 0xF0, 0x64, 0x02, 0x1A, 0x60, 0x5A, 0x4B, 0x5B, 0x49, 0x50, 0x4C, 0x5B, 0x4E, 0x5B, 0x4D, 0x00, 0x22, ++0x4F, 0xF4, 0x40, 0x50, 0x08, 0x60, 0x1A, 0x60, 0x0D, 0xF1, 0x06, 0x01, 0x0D, 0xF1, 0x07, 0x00, 0xE0, 0xF7, 0x1C, 0xF9, ++0x9D, 0xF8, 0x07, 0x20, 0x9D, 0xF8, 0x06, 0x00, 0x54, 0x49, 0x13, 0x02, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x43, 0x0B, 0x60, ++0x23, 0x68, 0x52, 0x4A, 0x43, 0xF4, 0x80, 0x53, 0x23, 0x60, 0x23, 0x68, 0x41, 0xF6, 0x25, 0x40, 0x43, 0xF4, 0x00, 0x53, ++0x23, 0x60, 0xC1, 0xF8, 0x70, 0x04, 0x13, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x13, 0x60, 0xDF, 0xF7, 0x77, 0xFD, 0x32, 0x68, ++0x49, 0x49, 0x43, 0x1C, 0x9B, 0x06, 0x22, 0xF0, 0xE0, 0x52, 0x03, 0xF0, 0xE0, 0x53, 0x13, 0x43, 0x33, 0x60, 0x23, 0x68, ++0x45, 0x4A, 0x43, 0xF0, 0x20, 0x03, 0x23, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, ++0x02, 0x03, 0x13, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x23, 0x60, 0x2B, 0x68, 0x99, 0x03, 0x13, 0xD4, 0x3D, 0x4A, ++0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x2A, 0x4B, 0x1B, 0x68, 0xB3, 0xF1, 0xC8, 0x5F, ++0xBF, 0xF4, 0x74, 0xAF, 0x37, 0x49, 0x38, 0x48, 0x40, 0xF2, 0x21, 0x12, 0x03, 0xF0, 0x46, 0xF9, 0x6C, 0xE7, 0xDF, 0xF7, ++0x05, 0xFD, 0x00, 0x28, 0xE7, 0xD0, 0xDF, 0xF7, 0x35, 0xFD, 0x33, 0x4E, 0x32, 0x68, 0x00, 0x02, 0x00, 0xF4, 0xE0, 0x63, ++0x22, 0xF4, 0xE0, 0x62, 0x13, 0x43, 0x33, 0x60, 0x33, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0x33, 0x60, ++0x33, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x33, 0x60, 0x33, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x2B, 0x68, 0x1B, 0x04, ++0x0D, 0xD4, 0x1E, 0x4B, 0x1B, 0x68, 0x9A, 0x03, 0xC7, 0xD5, 0xDF, 0xF7, 0xE9, 0xFC, 0x00, 0x28, 0xC3, 0xD0, 0x22, 0x4A, ++0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE7, 0xDF, 0xF7, 0xB1, 0xFC, 0x00, 0x28, 0xED, 0xD0, 0x23, 0x68, ++0x43, 0xF4, 0x00, 0x23, 0x23, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, 0x80, 0x63, 0x33, 0x60, 0xE2, 0xE7, ++0x50, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0x4C, 0x00, 0x32, 0x40, ++0x38, 0x36, 0x17, 0x00, 0xD8, 0x00, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x10, 0x19, 0x04, 0x00, 0xC0, 0x07, 0xF9, 0x80, ++0x60, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x3C, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, 0x58, 0x01, 0x32, 0x40, ++0x9C, 0x00, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, 0xA0, 0x00, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x00, 0x04, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0x40, 0x88, 0x15, 0x00, 0x50, 0x03, 0x32, 0x40, ++0x05, 0x49, 0x06, 0x4A, 0x0B, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x1D, 0x4A, 0x1E, 0x49, 0x13, 0x68, 0x1E, 0x48, ++0x30, 0xB4, 0x23, 0xF0, 0x80, 0x03, 0x00, 0x25, 0x3C, 0x24, 0x13, 0x60, 0x0D, 0x60, 0x0A, 0x46, 0x04, 0x60, 0x13, 0x68, ++0x1B, 0x07, 0xFC, 0xD1, 0x17, 0x4A, 0x18, 0x49, 0x13, 0x68, 0x18, 0x4D, 0x18, 0x48, 0x19, 0x4C, 0x43, 0xF4, 0x80, 0x33, ++0x13, 0x60, 0x0B, 0x68, 0x02, 0xF5, 0x00, 0x42, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x60, 0x20, 0x32, 0x4F, 0xF0, 0xFF, 0x33, ++0x2B, 0x60, 0x04, 0x60, 0x13, 0x68, 0x12, 0x4C, 0x12, 0x49, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x22, 0x68, 0x4B, 0x68, ++0xA0, 0xF5, 0x00, 0x40, 0x24, 0x38, 0x42, 0xF0, 0x00, 0x42, 0x22, 0x60, 0x02, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x42, 0xF0, ++0x80, 0x02, 0x02, 0x60, 0x30, 0xBC, 0x4B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x38, 0x00, 0x32, 0x40, ++0x54, 0x00, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x7C, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x44, 0xF1, 0x73, 0x0B, ++0x80, 0x80, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x0B, 0x49, 0x0C, 0x4A, 0x0C, 0x4B, 0x10, 0xB4, 0x04, 0x68, 0x80, 0x88, ++0x0C, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x10, 0x60, 0x1A, 0x46, 0x19, 0x60, 0x10, 0x68, 0x81, 0x00, 0xFC, 0xD4, 0xC3, 0x00, ++0x5D, 0xBF, 0x00, 0x0C, 0x10, 0x38, 0xC0, 0xB2, 0xFF, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, 0x38, 0xB5, 0x11, 0x4B, 0x11, 0x48, 0x19, 0x68, 0x42, 0x68, 0x11, 0x4C, ++0x11, 0x4D, 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x23, 0x68, 0x0E, 0x49, ++0x43, 0xF4, 0xE0, 0x63, 0x2A, 0x43, 0x23, 0x60, 0x05, 0x60, 0x01, 0x20, 0x0A, 0x60, 0xF3, 0xF7, 0x51, 0xFB, 0x23, 0x68, ++0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x23, 0x68, 0x43, 0xF4, 0x00, 0x53, 0x23, 0x60, 0x38, 0xBD, ++0x74, 0x80, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x60, 0x00, 0x32, 0x40, ++0x80, 0xEA, 0xE0, 0x72, 0xF0, 0xB4, 0xA2, 0xEB, 0xE0, 0x72, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x16, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x16, 0x4D, 0x16, 0x4B, 0x2E, 0x68, 0x1B, 0x68, 0x16, 0x49, 0x77, 0x1C, 0x00, 0x28, ++0x09, 0x68, 0x2F, 0x60, 0x43, 0xF0, 0x80, 0x73, 0x15, 0xDD, 0x8A, 0x42, 0x18, 0xD8, 0x11, 0x49, 0x0F, 0x4C, 0x0A, 0x68, ++0x10, 0x1A, 0x08, 0x60, 0x23, 0x60, 0x08, 0x60, 0x23, 0x60, 0x08, 0x60, 0x00, 0x20, 0x23, 0x60, 0x2F, 0xB1, 0x08, 0x4B, ++0x2E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, 0x70, 0x47, 0xEA, 0xD0, 0xC9, 0x43, 0x20, 0x32, ++0x91, 0x42, 0xE6, 0xD2, 0x4F, 0xF0, 0xFF, 0x30, 0xEE, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x4C, 0x00, 0x32, 0x40, 0xA4, 0x80, 0x32, 0x40, 0x35, 0x4B, 0x1B, 0x68, 0x70, 0xB5, 0xC3, 0xF3, 0x40, 0x64, 0x9B, 0x01, ++0x12, 0xD4, 0x33, 0x49, 0x33, 0x48, 0x0B, 0x69, 0x33, 0x4A, 0x05, 0x68, 0x08, 0x69, 0xB2, 0xF8, 0xB0, 0x10, 0xB2, 0xF8, ++0xB2, 0x20, 0xA3, 0xF5, 0xFA, 0x63, 0x03, 0xEB, 0x45, 0x13, 0x1B, 0x1A, 0x5B, 0x1A, 0x9B, 0x1A, 0x00, 0x2B, 0x17, 0xDB, ++0x2C, 0x4B, 0x1D, 0x68, 0x9D, 0xB1, 0x28, 0x48, 0x29, 0x4E, 0xEA, 0x68, 0x03, 0x69, 0xB6, 0xF8, 0xB0, 0x40, 0xB6, 0xF8, ++0xB2, 0x10, 0xD3, 0x1A, 0xA3, 0xF5, 0xFA, 0x63, 0x1B, 0x1B, 0x5B, 0x1A, 0x00, 0x2B, 0x07, 0xDB, 0x24, 0x4B, 0x1B, 0x68, ++0x1C, 0x78, 0x01, 0x2C, 0x0B, 0xD0, 0x01, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x12, 0xDB, 0x00, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x18, 0xDB, 0x15, 0x4B, 0x52, 0x1A, 0x4F, 0xF4, 0x80, 0x20, 0x04, 0x21, 0x98, 0x60, 0x1A, 0x63, 0x20, 0x46, 0x99, 0x60, ++0x70, 0xBD, 0x03, 0x69, 0xD2, 0x1A, 0x02, 0xF5, 0x9C, 0x52, 0x08, 0x32, 0x00, 0x2A, 0xE5, 0xDA, 0x12, 0x49, 0x13, 0x48, ++0x40, 0xF2, 0x3E, 0x22, 0x02, 0xF0, 0x92, 0xFF, 0x00, 0x24, 0xD5, 0xE7, 0x03, 0x69, 0xD3, 0x1A, 0x5B, 0x1A, 0x00, 0x2B, ++0xE1, 0xDA, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF2, 0x43, 0x22, 0x02, 0xF0, 0x85, 0xFF, 0xEA, 0x68, 0xB6, 0xF8, 0xB2, 0x10, ++0xD7, 0xE7, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x40, 0x80, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0xD0, 0x9C, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0xA4, 0x15, 0x00, ++0x80, 0x8D, 0x15, 0x00, 0x70, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x0B, 0x4B, 0x0B, 0x49, 0x0C, 0x4D, 0x0E, 0x68, 0x1A, 0x68, 0x28, 0x68, 0x09, 0x68, 0x54, 0x1C, 0xB1, 0x42, ++0x18, 0xBF, 0x28, 0x68, 0x1C, 0x60, 0x2C, 0xB1, 0x03, 0x4C, 0x1A, 0x60, 0x23, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, ++0x70, 0xBC, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x80, 0x32, 0x40, 0xA4, 0x80, 0x32, 0x40, ++0x3B, 0x4A, 0x3C, 0x4B, 0x10, 0xB5, 0x14, 0x68, 0x1C, 0x60, 0x61, 0x05, 0x1D, 0xD4, 0xE2, 0x05, 0x16, 0xD4, 0xA3, 0x05, ++0x10, 0xD4, 0xE0, 0x06, 0x31, 0xD4, 0x37, 0x4B, 0x1A, 0x78, 0x22, 0xB1, 0x14, 0xF0, 0x2F, 0x0F, 0x1C, 0xBF, 0x01, 0x22, ++0x9A, 0x71, 0x34, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0D, 0xDB, 0x10, 0xBD, 0x31, 0x48, 0x02, 0xF0, ++0xAD, 0xFC, 0xFE, 0xE7, 0xF2, 0xF7, 0x96, 0xFD, 0xA3, 0x05, 0xE6, 0xD5, 0xF6, 0xE7, 0x2E, 0x48, 0x02, 0xF0, 0xA4, 0xFC, ++0xFE, 0xE7, 0xE1, 0x07, 0x1C, 0xD4, 0xA2, 0x07, 0x42, 0xD4, 0x63, 0x07, 0x38, 0xD4, 0x20, 0x07, 0x2E, 0xD4, 0x21, 0x06, ++0x24, 0xD4, 0x62, 0x06, 0x1A, 0xD4, 0xA3, 0x06, 0xE3, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x25, 0x49, 0x25, 0x48, 0x40, 0xF2, ++0xB5, 0x22, 0x02, 0xF0, 0xD5, 0xBE, 0x04, 0x20, 0xEC, 0xF7, 0xA4, 0xFD, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xEC, 0xF7, ++0x3F, 0xFE, 0xC4, 0xE7, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0x2B, 0x72, 0x02, 0xF0, 0xC4, 0xBE, ++0xBD, 0xE8, 0x10, 0x40, 0x18, 0x49, 0x1B, 0x48, 0x40, 0xF2, 0xB3, 0x22, 0x02, 0xF0, 0xBC, 0xBE, 0xBD, 0xE8, 0x10, 0x40, ++0x14, 0x49, 0x18, 0x48, 0x40, 0xF2, 0xB1, 0x22, 0x02, 0xF0, 0xB4, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x10, 0x49, 0x15, 0x48, ++0x40, 0xF2, 0xAF, 0x22, 0x02, 0xF0, 0xAC, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x49, 0x12, 0x48, 0x40, 0xF2, 0xAE, 0x22, ++0x02, 0xF0, 0xA4, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x49, 0x0F, 0x48, 0x40, 0xF2, 0xAD, 0x22, 0x02, 0xF0, 0x9C, 0xBE, ++0x84, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x80, 0x35, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x5C, 0xA5, 0x15, 0x00, ++0x28, 0xA5, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x80, 0xA6, 0x15, 0x00, 0x90, 0xA5, 0x15, 0x00, 0x58, 0xA6, 0x15, 0x00, ++0x30, 0xA6, 0x15, 0x00, 0x08, 0xA6, 0x15, 0x00, 0xE0, 0xA5, 0x15, 0x00, 0xB8, 0xA5, 0x15, 0x00, 0x38, 0xB5, 0x62, 0x4A, ++0x62, 0x4B, 0x11, 0x68, 0x1C, 0x68, 0x62, 0x4B, 0x0C, 0x40, 0x23, 0x40, 0x54, 0x60, 0x00, 0x2B, 0x54, 0xD1, 0x60, 0x4B, ++0x23, 0x40, 0x00, 0x2B, 0x4B, 0xD1, 0x62, 0x07, 0x03, 0xD5, 0x5E, 0x4B, 0xD3, 0xF8, 0xDC, 0x30, 0x98, 0x47, 0x23, 0x07, ++0x03, 0xD5, 0x5B, 0x4B, 0xD3, 0xF8, 0xD4, 0x30, 0x98, 0x47, 0xE5, 0x00, 0x2E, 0xD4, 0xE0, 0x05, 0x28, 0xD4, 0x58, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x38, 0xBD, 0x61, 0x02, 0x3C, 0xD4, 0xA2, 0x02, 0x42, 0xD4, ++0x63, 0x06, 0x48, 0xD4, 0xE5, 0x04, 0x4E, 0xD4, 0xA0, 0x04, 0x54, 0xD4, 0x61, 0x04, 0x5A, 0xD4, 0x22, 0x04, 0x60, 0xD4, ++0xE3, 0x03, 0x66, 0xD4, 0xA5, 0x03, 0x6C, 0xD4, 0xE0, 0x01, 0x72, 0xD4, 0xA1, 0x01, 0x78, 0xD4, 0xE2, 0x02, 0x7E, 0xD4, ++0x23, 0x01, 0xE4, 0xD5, 0xBD, 0xE8, 0x38, 0x40, 0x47, 0x49, 0x48, 0x48, 0x40, 0xF2, 0x19, 0x32, 0x02, 0xF0, 0x38, 0xBE, ++0x46, 0x48, 0x02, 0xF0, 0xED, 0xFB, 0xD2, 0xE7, 0x45, 0x4B, 0x46, 0x4A, 0x1D, 0x68, 0x93, 0x7F, 0x05, 0xF0, 0x3F, 0x01, ++0x0B, 0x43, 0x4F, 0xF4, 0x00, 0x20, 0x93, 0x77, 0x01, 0xF0, 0x64, 0xF9, 0x41, 0x4B, 0x1D, 0x60, 0xC1, 0xE7, 0x4F, 0xF0, ++0x80, 0x70, 0x01, 0xF0, 0x5D, 0xF9, 0xAE, 0xE7, 0x4F, 0xF0, 0x00, 0x70, 0x01, 0xF0, 0x58, 0xF9, 0xA5, 0xE7, 0xBD, 0xE8, ++0x38, 0x40, 0x35, 0x49, 0x3A, 0x48, 0x40, 0xF2, 0x0B, 0x32, 0x02, 0xF0, 0x13, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x31, 0x49, ++0x37, 0x48, 0x4F, 0xF4, 0x43, 0x72, 0x02, 0xF0, 0x0B, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x2D, 0x49, 0x34, 0x48, 0x40, 0xF2, ++0x0D, 0x32, 0x02, 0xF0, 0x03, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x29, 0x49, 0x31, 0x48, 0x4F, 0xF4, 0x44, 0x72, 0x02, 0xF0, ++0xFB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x25, 0x49, 0x2E, 0x48, 0x40, 0xF2, 0x11, 0x32, 0x02, 0xF0, 0xF3, 0xBD, 0xBD, 0xE8, ++0x38, 0x40, 0x21, 0x49, 0x2B, 0x48, 0x40, 0xF2, 0x12, 0x32, 0x02, 0xF0, 0xEB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x1D, 0x49, ++0x28, 0x48, 0x40, 0xF2, 0x13, 0x32, 0x02, 0xF0, 0xE3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x19, 0x49, 0x25, 0x48, 0x4F, 0xF4, ++0x45, 0x72, 0x02, 0xF0, 0xDB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x15, 0x49, 0x22, 0x48, 0x40, 0xF2, 0x15, 0x32, 0x02, 0xF0, ++0xD3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x11, 0x49, 0x1F, 0x48, 0x40, 0xF2, 0x16, 0x32, 0x02, 0xF0, 0xCB, 0xBD, 0xBD, 0xE8, ++0x38, 0x40, 0x0D, 0x49, 0x1C, 0x48, 0x40, 0xF2, 0x17, 0x32, 0x02, 0xF0, 0xC3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x09, 0x49, ++0x19, 0x48, 0x4F, 0xF4, 0x46, 0x72, 0x02, 0xF0, 0xBB, 0xBD, 0x00, 0xBF, 0x6C, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, ++0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x08, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x10, 0xA9, 0x15, 0x00, 0xA8, 0xA6, 0x15, 0x00, 0x90, 0x80, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x94, 0x80, 0x32, 0x40, ++0xD8, 0xA6, 0x15, 0x00, 0x00, 0xA7, 0x15, 0x00, 0x34, 0xA7, 0x15, 0x00, 0x68, 0xA7, 0x15, 0x00, 0x90, 0xA7, 0x15, 0x00, ++0xC0, 0xA7, 0x15, 0x00, 0xF0, 0xA7, 0x15, 0x00, 0x20, 0xA8, 0x15, 0x00, 0x50, 0xA8, 0x15, 0x00, 0x80, 0xA8, 0x15, 0x00, ++0xB4, 0xA8, 0x15, 0x00, 0xE8, 0xA8, 0x15, 0x00, 0x10, 0xB5, 0x18, 0x4B, 0x84, 0xB0, 0xD3, 0xF8, 0x20, 0x32, 0x8D, 0xF8, ++0x07, 0x00, 0x0D, 0xF1, 0x0F, 0x02, 0x0D, 0xF1, 0x0E, 0x01, 0x0D, 0xF1, 0x07, 0x00, 0x98, 0x47, 0x12, 0x4A, 0x13, 0x49, ++0x13, 0x68, 0x9D, 0xF8, 0x0E, 0x40, 0x91, 0xF8, 0xBA, 0x00, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x04, 0x23, 0x13, 0x60, ++0x18, 0xB1, 0x0E, 0x4B, 0x93, 0xF8, 0x2A, 0x30, 0x4B, 0xB1, 0x0A, 0x4A, 0x9D, 0xF8, 0x0F, 0x10, 0x13, 0x68, 0x23, 0xF0, ++0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x04, 0xB0, 0x10, 0xBD, 0x13, 0x68, 0x91, 0xF8, 0xBB, 0x10, 0x23, 0xF0, 0xFF, 0x03, ++0x0B, 0x43, 0x13, 0x60, 0x04, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0x30, 0xB5, 0x90, 0xF9, 0x65, 0x50, 0x7F, 0x2D, 0x83, 0xB0, 0x0E, 0xD0, 0x90, 0xF9, 0x66, 0x30, ++0x0B, 0x48, 0x9D, 0x42, 0xA8, 0xBF, 0x1D, 0x46, 0x8D, 0xF8, 0x07, 0x50, 0xD0, 0xF8, 0x20, 0x32, 0x0D, 0xF1, 0x07, 0x00, ++0x98, 0x47, 0x03, 0xB0, 0x30, 0xBD, 0x0C, 0x46, 0x05, 0x49, 0x13, 0x46, 0x0A, 0x68, 0x12, 0x0A, 0x22, 0x70, 0x0A, 0x68, ++0x1A, 0x70, 0x03, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x91, 0xF9, 0x00, 0x30, ++0x7F, 0x2B, 0x40, 0xD0, 0xF0, 0xB5, 0x20, 0x4E, 0x90, 0xF9, 0x65, 0x70, 0xD6, 0xF8, 0x20, 0x32, 0x85, 0xB0, 0x0C, 0x46, ++0x05, 0x46, 0x11, 0x46, 0x20, 0x46, 0x0D, 0xF1, 0x0F, 0x02, 0x01, 0x91, 0x98, 0x47, 0x94, 0xF9, 0x00, 0x30, 0x95, 0xF9, ++0x66, 0x20, 0x85, 0xF8, 0x65, 0x30, 0x93, 0x42, 0x20, 0xDC, 0x94, 0xF9, 0x00, 0x30, 0xBB, 0x42, 0x1A, 0xD0, 0xD5, 0xF8, ++0xE4, 0x30, 0x43, 0xB1, 0x93, 0xF8, 0x56, 0x21, 0x42, 0xF0, 0x10, 0x02, 0x83, 0xF8, 0x56, 0x21, 0x1B, 0x68, 0x00, 0x2B, ++0xF6, 0xD1, 0x28, 0x6C, 0x60, 0xB1, 0xD6, 0xF8, 0xB4, 0x30, 0x98, 0x47, 0x28, 0x46, 0xFC, 0xF7, 0x5D, 0xFC, 0x28, 0xB1, ++0x2A, 0x6C, 0xD6, 0xF8, 0x3C, 0x33, 0x92, 0xF9, 0x0C, 0x00, 0x98, 0x47, 0x05, 0xB0, 0xF0, 0xBD, 0x22, 0x70, 0x01, 0x99, ++0xD6, 0xF8, 0x20, 0x32, 0x0D, 0xF1, 0x0F, 0x02, 0x20, 0x46, 0x98, 0x47, 0xD5, 0xE7, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0x10, 0xB5, 0x15, 0x4B, 0x82, 0xB0, 0x0C, 0x46, 0xD3, 0xF8, 0x38, 0x33, 0x0D, 0xF1, 0x07, 0x02, 0x0D, 0xF1, 0x06, 0x01, ++0x98, 0x47, 0xE2, 0x6C, 0x10, 0x4B, 0x94, 0x6B, 0x93, 0xF8, 0xBD, 0x30, 0x61, 0x69, 0xC1, 0xF3, 0xC2, 0x20, 0xC9, 0xB2, ++0x6B, 0xB9, 0x01, 0xF0, 0x7C, 0x01, 0x50, 0xEA, 0x01, 0x03, 0x0C, 0xBF, 0x9D, 0xF8, 0x06, 0x30, 0x9D, 0xF8, 0x07, 0x30, ++0x43, 0xEA, 0x03, 0x23, 0x63, 0x62, 0x02, 0xB0, 0x10, 0xBD, 0x01, 0xF0, 0x7F, 0x01, 0xDF, 0xF7, 0xB1, 0xFA, 0x40, 0xEA, ++0x00, 0x20, 0x60, 0x62, 0x02, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x00, 0x29, 0x11, 0xDD, ++0x10, 0xB4, 0x01, 0x39, 0x00, 0x23, 0x01, 0x24, 0x10, 0xF0, 0x01, 0x0F, 0x1C, 0xBF, 0x04, 0xFA, 0x01, 0xF2, 0x13, 0x43, ++0x01, 0x39, 0x4F, 0xEA, 0x50, 0x00, 0xF5, 0xD2, 0x18, 0x46, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x23, 0x18, 0x46, ++0x70, 0x47, 0x00, 0xBF, 0x0B, 0x1F, 0x03, 0x44, 0x01, 0x44, 0x03, 0xF8, 0x01, 0x2B, 0x8B, 0x42, 0x4F, 0xEA, 0x12, 0x22, ++0xF9, 0xD1, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x8D, 0x88, 0x0C, 0x7D, 0x00, 0x95, 0x0D, 0x68, 0x01, 0x95, ++0x03, 0x93, 0x1C, 0xB1, 0x0B, 0x69, 0xAB, 0x42, 0x00, 0xF0, 0xAC, 0x81, 0x01, 0x9B, 0xD9, 0x4F, 0x9C, 0xB2, 0x4F, 0xEA, ++0x13, 0x4C, 0xCC, 0x80, 0xA1, 0xF8, 0x08, 0xC0, 0x53, 0x78, 0x16, 0x78, 0x46, 0xEA, 0x03, 0x26, 0x4E, 0x81, 0xD3, 0x78, ++0x95, 0x78, 0x45, 0xEA, 0x03, 0x25, 0x8D, 0x81, 0x92, 0xF8, 0x05, 0xE0, 0x13, 0x79, 0x43, 0xEA, 0x0E, 0x23, 0xCB, 0x81, ++0x4F, 0xF0, 0x00, 0x09, 0x09, 0xF0, 0x01, 0x0A, 0x00, 0xEB, 0x4A, 0x02, 0x10, 0xF8, 0x1A, 0x80, 0x92, 0xF8, 0x01, 0xE0, ++0x02, 0x92, 0x48, 0xEA, 0x0E, 0x22, 0x5A, 0x40, 0x4F, 0xEA, 0x12, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, ++0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x4F, 0xEA, 0x4A, 0x08, 0x14, 0x44, ++0x08, 0xF1, 0x04, 0x02, 0xA4, 0xB2, 0x00, 0xEB, 0x02, 0x0E, 0xCC, 0x80, 0x82, 0x5C, 0x9E, 0xF8, 0x01, 0xE0, 0x42, 0xEA, ++0x0E, 0x2E, 0x84, 0xEA, 0x0E, 0x0E, 0xCE, 0xF3, 0x0F, 0x22, 0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x12, 0x20, 0x37, 0xF8, ++0x1E, 0xB0, 0x4F, 0xEA, 0x12, 0x2E, 0x4E, 0xEA, 0x02, 0x2E, 0x8E, 0xEA, 0x0B, 0x0B, 0xDC, 0x44, 0x08, 0xF1, 0x08, 0x0E, ++0x1F, 0xFA, 0x8C, 0xFC, 0x00, 0xEB, 0x0E, 0x02, 0xA1, 0xF8, 0x08, 0xC0, 0x10, 0xF8, 0x0E, 0xE0, 0x52, 0x78, 0x4E, 0xEA, ++0x02, 0x22, 0x8C, 0xEA, 0x02, 0x02, 0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, 0x12, 0xB0, ++0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x0B, 0x0B, 0x08, 0xF1, 0x0C, 0x08, 0x5E, 0x44, 0x00, 0xEB, ++0x08, 0x02, 0xB6, 0xB2, 0x4E, 0x81, 0x92, 0xF8, 0x01, 0xE0, 0x10, 0xF8, 0x08, 0x20, 0x42, 0xEA, 0x0E, 0x22, 0x72, 0x40, ++0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, 0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, ++0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x15, 0x44, 0xAD, 0xB2, 0x02, 0x9A, 0x8D, 0x81, 0x92, 0xF8, 0x01, 0xE0, 0x10, 0xF8, ++0x1A, 0x20, 0x42, 0xEA, 0x0E, 0x22, 0x6A, 0x40, 0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, ++0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x19, 0xFA, 0x82, 0xF2, 0x13, 0x44, ++0x09, 0xF1, 0x01, 0x09, 0x9B, 0xB2, 0xB9, 0xF1, 0x08, 0x0F, 0xCB, 0x81, 0x7F, 0xF4, 0x6E, 0xAF, 0x01, 0x9A, 0x0A, 0x61, ++0x4F, 0xF0, 0x01, 0x0E, 0x81, 0xF8, 0x14, 0xE0, 0x00, 0x9A, 0x90, 0xF8, 0x01, 0x80, 0x90, 0xF8, 0x00, 0xE0, 0x90, 0xF8, ++0x03, 0x90, 0x1A, 0x44, 0x4E, 0xEA, 0x08, 0x2E, 0x92, 0xB2, 0x82, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x28, 0x5F, 0xFA, ++0x8E, 0xFE, 0x37, 0xF8, 0x18, 0xA0, 0x37, 0xF8, 0x1E, 0x80, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, ++0x08, 0x0A, 0x90, 0xF8, 0x02, 0x80, 0x90, 0xF8, 0x05, 0xE0, 0x54, 0x44, 0xA4, 0xB2, 0x48, 0xEA, 0x09, 0x28, 0x84, 0xEA, ++0x08, 0x08, 0x4F, 0xEA, 0x18, 0x2A, 0x5F, 0xFA, 0x88, 0xF8, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x18, 0x90, 0x4F, 0xEA, ++0x1A, 0x28, 0x48, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x04, 0x90, 0x90, 0xF8, 0x07, 0x80, 0xD4, 0x44, ++0x1F, 0xFA, 0x8C, 0xFC, 0x49, 0xEA, 0x0E, 0x2E, 0x8C, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, 0x5F, 0xFA, 0x8E, 0xFE, ++0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x1E, 0x90, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, ++0x90, 0xF8, 0x06, 0x90, 0x90, 0xF8, 0x09, 0xE0, 0x56, 0x44, 0xB6, 0xB2, 0x49, 0xEA, 0x08, 0x28, 0x86, 0xEA, 0x08, 0x08, ++0x4F, 0xEA, 0x18, 0x2A, 0x5F, 0xFA, 0x88, 0xF8, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x18, 0x90, 0x4F, 0xEA, 0x1A, 0x28, ++0x48, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x08, 0x90, 0x90, 0xF8, 0x0B, 0x80, 0x55, 0x44, 0xAD, 0xB2, ++0x49, 0xEA, 0x0E, 0x2E, 0x85, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, 0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x1A, 0xA0, ++0x37, 0xF8, 0x1E, 0x90, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x0A, 0xE0, ++0x90, 0xF8, 0x0D, 0x90, 0x53, 0x44, 0x9B, 0xB2, 0x4E, 0xEA, 0x08, 0x2E, 0x83, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, ++0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x1E, 0x80, 0x07, 0x7B, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, ++0x0A, 0x2E, 0x8E, 0xEA, 0x08, 0x08, 0x42, 0x44, 0x92, 0xB2, 0x47, 0xEA, 0x09, 0x29, 0x82, 0xEA, 0x09, 0x07, 0xFF, 0x03, ++0x82, 0xEA, 0x09, 0x09, 0x90, 0xF8, 0x0F, 0xE0, 0x47, 0xEA, 0x59, 0x09, 0x87, 0x7B, 0x4C, 0x44, 0xA4, 0xB2, 0x47, 0xEA, ++0x0E, 0x27, 0x84, 0xEA, 0x07, 0x0E, 0x4F, 0xEA, 0xCE, 0x3E, 0x67, 0x40, 0x4E, 0xEA, 0x57, 0x07, 0x67, 0x44, 0xBF, 0xB2, ++0x4F, 0xEA, 0xC7, 0x3C, 0x4C, 0xEA, 0x57, 0x0C, 0x66, 0x44, 0xB6, 0xB2, 0x4F, 0xEA, 0xC6, 0x3C, 0x4C, 0xEA, 0x56, 0x0C, ++0x65, 0x44, 0xAD, 0xB2, 0x4F, 0xEA, 0xC5, 0x3C, 0x4C, 0xEA, 0x55, 0x0C, 0x63, 0x44, 0x1F, 0xFA, 0x83, 0xF9, 0x00, 0x9B, ++0xAD, 0xF8, 0x18, 0x60, 0x4F, 0xEA, 0x13, 0x2E, 0x0E, 0xF0, 0x7F, 0x0C, 0xAD, 0xF8, 0x16, 0x70, 0xAD, 0xF8, 0x1A, 0x50, ++0x03, 0x9E, 0x00, 0x9D, 0xB5, 0x70, 0x4C, 0xF0, 0x20, 0x0C, 0x86, 0xF8, 0x00, 0xE0, 0x86, 0xF8, 0x01, 0xC0, 0x4F, 0xEA, ++0xC9, 0x38, 0x45, 0x78, 0x03, 0x78, 0xAD, 0xF8, 0x1C, 0x90, 0x48, 0xEA, 0x59, 0x08, 0x42, 0x44, 0x92, 0xB2, 0x43, 0xEA, ++0x05, 0x23, 0xAD, 0xF8, 0x1E, 0x20, 0x5A, 0x40, 0x52, 0x08, 0xF2, 0x70, 0x33, 0x46, 0x06, 0xF1, 0x0C, 0x00, 0x05, 0xAA, ++0x01, 0xE0, 0x32, 0xF8, 0x02, 0x4F, 0x1C, 0x71, 0x25, 0x0A, 0x5D, 0x71, 0x02, 0x33, 0x98, 0x42, 0xF7, 0xD1, 0x00, 0x23, ++0x0B, 0x75, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xCC, 0x88, 0xB1, 0xF8, 0x08, 0xC0, 0x4E, 0x89, 0x8D, 0x89, 0xCB, 0x89, ++0x00, 0x4F, 0xFD, 0xE6, 0x50, 0xA9, 0x15, 0x00, 0xF0, 0xB4, 0x13, 0x4F, 0x01, 0x22, 0x3C, 0x1F, 0x00, 0x23, 0xC7, 0xF8, ++0x00, 0x24, 0xC7, 0xF8, 0x04, 0x34, 0x22, 0x46, 0x42, 0xF8, 0x04, 0x3F, 0x01, 0x33, 0xB3, 0xF5, 0x80, 0x7F, 0xF9, 0xD1, ++0x00, 0x23, 0xDF, 0xF8, 0x30, 0xC0, 0x1D, 0x46, 0xC2, 0x5C, 0x54, 0xF8, 0x04, 0x6F, 0x2A, 0x44, 0x32, 0x44, 0xD5, 0xB2, ++0x01, 0x33, 0x57, 0xF8, 0x25, 0x20, 0x22, 0x60, 0x8B, 0x42, 0xA8, 0xBF, 0x00, 0x23, 0xA4, 0x45, 0x47, 0xF8, 0x25, 0x60, ++0xEE, 0xD1, 0x00, 0x20, 0xF0, 0xBC, 0x70, 0x47, 0x18, 0x2C, 0x17, 0x00, 0x14, 0x30, 0x17, 0x00, 0x71, 0xB3, 0x18, 0x4B, ++0xF0, 0xB5, 0xD3, 0xF8, 0x00, 0x54, 0xD3, 0xF8, 0x04, 0x24, 0x53, 0xF8, 0x25, 0x60, 0x32, 0x44, 0x01, 0x39, 0xD2, 0xB2, ++0x89, 0xB2, 0x01, 0x31, 0x53, 0xF8, 0x22, 0x40, 0x01, 0x44, 0x6F, 0x1C, 0x43, 0xF8, 0x22, 0x60, 0x43, 0xF8, 0x25, 0x40, ++0xFD, 0xB2, 0x34, 0x44, 0xE4, 0xB2, 0x53, 0xF8, 0x25, 0x60, 0x53, 0xF8, 0x24, 0x70, 0x10, 0xF8, 0x01, 0x4B, 0x02, 0xEB, ++0x06, 0x0C, 0x96, 0x46, 0x5F, 0xFA, 0x8C, 0xF2, 0x67, 0x40, 0x88, 0x42, 0x53, 0xF8, 0x22, 0x40, 0x00, 0xF8, 0x01, 0x7C, ++0xE5, 0xD1, 0xC3, 0xF8, 0x00, 0x54, 0xC3, 0xF8, 0x04, 0xE4, 0xF0, 0xBD, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x2C, 0x17, 0x00, ++0xFF, 0xF7, 0xCA, 0xBF, 0x83, 0x68, 0x8A, 0x68, 0x03, 0x48, 0x9B, 0x1A, 0x83, 0x42, 0x94, 0xBF, 0x00, 0x20, 0x01, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0xA3, 0xE1, 0x11, 0x83, 0x88, 0xB3, 0xEB, 0x11, 0x4F, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, ++0xC0, 0x88, 0x89, 0xB2, 0x40, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, ++0xDF, 0xF8, 0x4C, 0xB1, 0xDB, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0x46, 0x89, 0x46, 0x15, 0x46, ++0x5E, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, ++0x2C, 0x81, 0xDF, 0xF8, 0x2C, 0xA1, 0xD8, 0xF8, 0x00, 0x30, 0xDA, 0xF8, 0x14, 0x60, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, ++0x1E, 0xB1, 0xB3, 0x88, 0xBB, 0x42, 0x40, 0xD0, 0x00, 0x26, 0x37, 0x49, 0x37, 0x48, 0x49, 0xEA, 0x07, 0x42, 0x00, 0xF0, ++0xF5, 0xF9, 0x04, 0x46, 0x00, 0x28, 0x47, 0xD0, 0x34, 0x4B, 0x35, 0x4A, 0x1B, 0x69, 0x32, 0x48, 0x1D, 0x44, 0xA5, 0x60, ++0x21, 0x46, 0x00, 0xF0, 0x87, 0xFE, 0x9E, 0xB9, 0xDA, 0xF8, 0x14, 0x30, 0xA3, 0x42, 0x13, 0xD0, 0xD8, 0xF8, 0x00, 0x30, ++0x2B, 0xB1, 0x29, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x8B, 0xB1, 0x29, 0x4B, 0x1A, 0x69, 0xAD, 0x1A, ++0x00, 0x2D, 0x14, 0xDB, 0xBD, 0xE8, 0xF8, 0x8F, 0xDA, 0xF8, 0x14, 0x40, 0x00, 0x2C, 0xEB, 0xD0, 0x25, 0x4B, 0xA1, 0x68, ++0xD3, 0xF8, 0xE0, 0x31, 0x24, 0x48, 0x98, 0x47, 0xE4, 0xE7, 0x00, 0x2A, 0xEB, 0xD0, 0x62, 0xB6, 0x1E, 0x4B, 0x1A, 0x69, ++0xAD, 0x1A, 0x00, 0x2D, 0xEA, 0xDA, 0xBD, 0xE8, 0xF8, 0x4F, 0x4F, 0xF0, 0x00, 0x50, 0x00, 0xF0, 0x29, 0xBD, 0xF6, 0x88, ++0xA6, 0xEB, 0x09, 0x06, 0xB6, 0xFA, 0x86, 0xF6, 0x76, 0x09, 0xB8, 0xE7, 0xB2, 0xB1, 0x19, 0x4B, 0x9A, 0x42, 0x9C, 0xD9, ++0x18, 0x49, 0x19, 0x48, 0x94, 0x22, 0x02, 0xF0, 0x0F, 0xFA, 0x96, 0xE7, 0x0C, 0x20, 0x00, 0xF0, 0xFB, 0xF9, 0xDB, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x09, 0xDB, 0xA7, 0x80, 0xA4, 0xF8, 0x06, 0x90, 0xA9, 0xE7, ++0x0E, 0x49, 0x10, 0x48, 0x93, 0x22, 0x02, 0xF0, 0xFB, 0xF9, 0x82, 0xE7, 0x00, 0x28, 0xF3, 0xD1, 0x0A, 0x49, 0x0D, 0x48, ++0xA5, 0x22, 0x02, 0xF0, 0xF3, 0xF9, 0xED, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x59, 0x26, 0x14, 0x00, 0x94, 0xB6, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x41, 0x26, 0x14, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0xB6, 0x17, 0x00, 0xFF, 0xA2, 0xE1, 0x11, ++0x70, 0x79, 0x15, 0x00, 0x5C, 0xAB, 0x15, 0x00, 0x50, 0xAB, 0x15, 0x00, 0x78, 0xAB, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0xF8, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x25, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x25, 0x4D, 0x25, 0x4E, 0x2B, 0x68, 0x74, 0x69, 0x01, 0x33, 0x2B, 0x60, 0x74, 0xB1, ++0xA3, 0x88, 0x83, 0x42, 0x02, 0xD1, 0xE3, 0x88, 0x8B, 0x42, 0x11, 0xD0, 0x41, 0xEA, 0x00, 0x42, 0x1F, 0x49, 0x20, 0x48, ++0x00, 0xF0, 0x54, 0xF9, 0x04, 0x46, 0x38, 0xBB, 0x2B, 0x68, 0x33, 0xB1, 0x18, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xF8, 0xBD, 0x06, 0xF1, 0x14, 0x00, 0x00, 0xF0, 0x98, 0xFD, 0x77, 0x69, 0x17, 0x4B, ++0xDF, 0xB1, 0xD3, 0xF8, 0xE0, 0x31, 0xB9, 0x68, 0x06, 0xF1, 0x20, 0x00, 0x98, 0x47, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x0A, 0xDA, 0x12, 0x4A, 0xBB, 0x68, 0x12, 0x69, 0x9B, 0x1A, 0x00, 0x2B, 0x04, 0xDA, 0x10, 0x49, ++0x10, 0x48, 0xE7, 0x22, 0x02, 0xF0, 0x8E, 0xF9, 0x20, 0x46, 0x00, 0xF0, 0xED, 0xF9, 0x2B, 0x68, 0xD3, 0xE7, 0xD3, 0xF8, ++0xD8, 0x31, 0x06, 0xF1, 0x20, 0x00, 0x98, 0x47, 0xF4, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x80, 0xB6, 0x17, 0x00, 0x59, 0x26, 0x14, 0x00, 0x94, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, 0x80, 0xAB, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x28, 0x4D, 0x29, 0x4F, ++0xDF, 0xF8, 0xB0, 0x80, 0x28, 0x4E, 0xDF, 0xF8, 0xB0, 0x90, 0x21, 0xE0, 0xA1, 0x68, 0x33, 0x69, 0xCB, 0x1A, 0x32, 0x2B, ++0x07, 0xD4, 0xD9, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0xA3, 0x68, 0x32, 0x69, 0x9B, 0x1A, 0x00, 0x2B, 0x30, 0xDA, 0x21, 0x48, ++0x00, 0xF0, 0x44, 0xFD, 0x2B, 0x68, 0x04, 0x46, 0x5A, 0x1E, 0x2B, 0xB1, 0xD8, 0xF8, 0x00, 0x30, 0x2A, 0x60, 0x0A, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0xA0, 0x88, 0xE1, 0x88, 0xFF, 0x22, 0x00, 0xF0, 0xCB, 0xF8, 0x20, 0x46, 0x00, 0xF0, 0xA4, 0xF9, ++0x4F, 0xF0, 0x00, 0x50, 0x00, 0xF0, 0x6C, 0xFC, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, ++0xC8, 0xF8, 0x00, 0x30, 0x2A, 0x68, 0x7C, 0x69, 0x10, 0x48, 0x53, 0x1C, 0x2B, 0x60, 0x00, 0x2C, 0xCA, 0xD1, 0x2B, 0xB1, ++0x0E, 0x4B, 0x2A, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x2B, 0x68, 0x00, 0x2B, ++0xFA, 0xD0, 0x09, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0xF4, 0xD1, 0x00, 0x2A, 0xF2, 0xD0, 0xF0, 0xE7, ++0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x94, 0xB6, 0x17, 0x00, 0xA0, 0xB6, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x0E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0E, 0x4D, 0x0E, 0x4C, 0x2B, 0x68, 0x4F, 0xF0, 0x00, 0x50, 0x01, 0x33, 0x2B, 0x60, ++0x00, 0xF0, 0x28, 0xFC, 0x01, 0xE0, 0x00, 0xF0, 0x59, 0xF9, 0x20, 0x46, 0x00, 0xF0, 0xE4, 0xFC, 0x00, 0x28, 0xF8, 0xD1, ++0x2B, 0x68, 0x33, 0xB1, 0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x94, 0xB6, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x80, 0x46, 0x03, 0xF1, ++0x0C, 0x00, 0x1D, 0x46, 0x0F, 0x46, 0x16, 0x46, 0x00, 0xF0, 0xC8, 0xF8, 0x0F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0x46, 0x0F, 0xDB, 0x00, 0x21, 0xA4, 0xF8, 0x04, 0x80, 0x04, 0xF1, 0x0C, 0x08, 0xE7, 0x80, 0x26, 0x81, ++0x65, 0x81, 0x2A, 0x46, 0x21, 0x60, 0x40, 0x46, 0xDD, 0xF7, 0xDC, 0xFB, 0x40, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x28, ++0xED, 0xD1, 0x04, 0x49, 0x04, 0x48, 0x52, 0x22, 0x02, 0xF0, 0xBA, 0xF8, 0xE7, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, 0x16, 0x4B, 0x1A, 0x68, 0x30, 0xF8, 0x06, 0x3C, 0xB2, 0xF9, 0x00, 0x10, ++0x00, 0x29, 0x10, 0xB5, 0xDA, 0xB2, 0x04, 0x46, 0x0C, 0xDB, 0x0B, 0x2A, 0x13, 0xD8, 0x11, 0x48, 0xA4, 0xF1, 0x0C, 0x01, ++0x00, 0xF0, 0x4C, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0xA4, 0xBB, 0x0D, 0x2A, 0xF0, 0xD9, ++0x0B, 0x49, 0x0C, 0x48, 0xBB, 0x22, 0x02, 0xF0, 0x93, 0xF8, 0x34, 0xF8, 0x06, 0x3C, 0x34, 0xF8, 0x04, 0x2C, 0x34, 0xF8, ++0x08, 0x1C, 0x08, 0x48, 0x01, 0xF0, 0x10, 0xFE, 0xA4, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0xF0, 0xDE, 0xB8, ++0x38, 0x36, 0x17, 0x00, 0x84, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0xB4, 0xAB, 0x15, 0x00, ++0x08, 0xB5, 0x00, 0x23, 0xFF, 0xF7, 0x94, 0xFF, 0xBD, 0xE8, 0x08, 0x40, 0xFF, 0xF7, 0xC0, 0xBF, 0x10, 0xB4, 0x5D, 0xF8, ++0x04, 0x4B, 0x20, 0xF8, 0x08, 0x1C, 0x20, 0xF8, 0x06, 0x2C, 0x20, 0xF8, 0x04, 0x3C, 0xFF, 0xF7, 0xB5, 0xBF, 0x00, 0xBF, ++0x00, 0xF0, 0xC6, 0xB8, 0x2D, 0xE9, 0xF0, 0x41, 0x04, 0x68, 0xD4, 0xB1, 0x07, 0x46, 0x0D, 0x46, 0x16, 0x46, 0x4F, 0xF0, ++0x00, 0x08, 0x02, 0xE0, 0xA0, 0x46, 0x93, 0xB1, 0x1C, 0x46, 0x31, 0x46, 0x20, 0x46, 0xA8, 0x47, 0x23, 0x68, 0x00, 0x28, ++0xF6, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0x0C, 0xD0, 0xC8, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x5B, 0xB1, 0x00, 0x23, 0x23, 0x60, ++0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x24, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x3B, 0x60, 0x00, 0x2B, 0xF3, 0xD1, ++0xC7, 0xF8, 0x04, 0x80, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x0F, 0x48, 0x30, 0xB4, 0x20, 0xF0, 0x03, 0x00, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4A, 0x0C, 0x4B, ++0x11, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x4C, 0x1C, 0x1B, 0x1A, 0x00, 0x25, 0x14, 0x60, 0xC0, 0xE9, 0x00, 0x53, 0x2C, 0xB1, ++0x04, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x03, 0xA0, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0xF8, 0xB5, 0x31, 0x4F, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x03, 0x30, 0x20, 0xF0, 0x03, 0x04, 0x00, 0x2B, 0x04, 0xF1, 0x04, 0x06, 0x48, 0xDB, 0x2C, 0x4B, 0xDB, 0x69, ++0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2A, 0x4A, 0x01, 0x21, 0x11, 0x60, 0x29, 0x4D, 0x2A, 0x68, ++0x02, 0xF1, 0x01, 0x0C, 0xC5, 0xF8, 0x00, 0xC0, 0x00, 0x2B, 0x3E, 0xD0, 0x04, 0xF1, 0x0C, 0x00, 0x00, 0x21, 0x05, 0xE0, ++0x4C, 0x68, 0xA2, 0x42, 0x38, 0xBF, 0x19, 0x46, 0x1B, 0x68, 0x43, 0xB1, 0x5A, 0x68, 0x82, 0x42, 0xFA, 0xD3, 0x00, 0x29, ++0xF4, 0xD1, 0x19, 0x46, 0x1B, 0x68, 0x00, 0x2B, 0xF6, 0xD1, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x12, 0xDB, ++0x0A, 0x46, 0x4B, 0x68, 0x9B, 0x1B, 0x98, 0x18, 0x4B, 0x60, 0x04, 0x30, 0x9E, 0x50, 0xBC, 0xF1, 0x00, 0x0F, 0x07, 0xD0, ++0x13, 0x4A, 0x0C, 0xF1, 0xFF, 0x33, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xF8, 0xBD, 0x00, 0x29, ++0xEA, 0xD1, 0x10, 0x49, 0x10, 0x48, 0x97, 0x22, 0x01, 0xF0, 0xC0, 0xFF, 0x00, 0x22, 0xD5, 0xF8, 0x00, 0xC0, 0x11, 0x46, ++0xE1, 0xE7, 0x07, 0x2E, 0xB4, 0xD8, 0x0A, 0x49, 0x0B, 0x48, 0x7B, 0x22, 0x01, 0xF0, 0xB4, 0xFF, 0xAE, 0xE7, 0x3A, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xE8, 0xDB, 0x5B, 0x68, 0xFF, 0xDE, 0x38, 0x36, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x08, 0xAC, 0x15, 0x00, 0xE0, 0xAB, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xF4, 0x90, 0x36, 0x4A, 0xD9, 0xF8, 0x00, 0x30, 0xD4, 0x69, 0xB3, 0xF9, 0x00, 0x30, ++0x50, 0xF8, 0x04, 0x8C, 0x00, 0x2B, 0x06, 0x46, 0xA0, 0xF1, 0x04, 0x05, 0x2F, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x2E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x48, 0xD0, 0xF8, 0x00, 0xC0, 0x0C, 0xF1, 0x01, 0x07, ++0x07, 0x60, 0x00, 0x2C, 0x47, 0xD0, 0x63, 0x68, 0x1A, 0x19, 0xAA, 0x42, 0x23, 0xD0, 0xAC, 0x42, 0x06, 0xD9, 0x37, 0xE0, ++0x63, 0x68, 0x1A, 0x19, 0xAA, 0x42, 0x1C, 0xD0, 0xAC, 0x42, 0x26, 0xD8, 0x21, 0x46, 0x24, 0x68, 0x00, 0x2C, 0xF5, 0xD1, ++0x0D, 0x60, 0x46, 0xE9, 0x01, 0x48, 0x47, 0xB1, 0x1E, 0x4B, 0xC0, 0xF8, 0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, ++0x01, 0xD1, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0xA0, 0x42, 0xCD, 0xD8, 0x1A, 0x49, 0x1A, 0x48, 0xC7, 0x22, ++0x01, 0xF0, 0x56, 0xFF, 0xC7, 0xE7, 0x43, 0x44, 0x22, 0x68, 0x63, 0x60, 0xE1, 0x18, 0x8A, 0x42, 0xE5, 0xD1, 0xD2, 0xE9, ++0x00, 0x21, 0x0B, 0x44, 0x22, 0x60, 0x63, 0x60, 0xDF, 0xE7, 0x05, 0xEB, 0x08, 0x03, 0x9C, 0x42, 0x0D, 0x60, 0xD8, 0xD1, ++0x23, 0x68, 0x46, 0xF8, 0x04, 0x3C, 0x52, 0x1B, 0x32, 0x60, 0xD4, 0xE7, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0xDB, 0x00, 0x23, 0x1D, 0x60, 0xFF, 0xDE, 0x25, 0x60, 0xFF, 0xDE, 0x06, 0x49, 0x07, 0x48, 0xE2, 0x22, ++0x01, 0xF0, 0x2E, 0xFF, 0xF4, 0xE7, 0x00, 0xBF, 0x80, 0xB6, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x18, 0xAC, 0x15, 0x00, 0x3C, 0xAC, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xC0, 0x88, 0x40, 0x1A, ++0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x2A, 0xB3, 0xF8, 0xB5, 0x53, 0x1E, 0x0F, 0x46, 0x0A, 0x68, 0x01, 0xE0, ++0x59, 0x1C, 0x11, 0xD0, 0x32, 0xF8, 0x33, 0x40, 0x84, 0x42, 0x4F, 0xEA, 0xC3, 0x06, 0x02, 0xEB, 0xC3, 0x05, 0x03, 0xF1, ++0xFF, 0x33, 0xF3, 0xD1, 0x0B, 0x4B, 0x68, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x02, 0xDB, 0xF8, 0xBD, ++0x00, 0x20, 0xF8, 0xBD, 0x00, 0x28, 0xFA, 0xD1, 0x06, 0x49, 0x07, 0x48, 0xF4, 0x22, 0x01, 0xF0, 0xF5, 0xFE, 0x3B, 0x68, ++0x1E, 0x44, 0x70, 0x68, 0xF8, 0xBD, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x50, 0xAC, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x44, 0x4F, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, ++0x0D, 0x46, 0x4F, 0xEA, 0x10, 0x29, 0xC6, 0xB2, 0x3B, 0xDB, 0x40, 0x4B, 0x03, 0xEB, 0x06, 0x16, 0xB3, 0x68, 0x03, 0xEB, ++0x49, 0x09, 0x3E, 0x48, 0x2A, 0x46, 0x21, 0x46, 0x01, 0xF0, 0x56, 0xFC, 0xB9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x01, 0xD1, ++0xBD, 0xE8, 0xF8, 0x83, 0xDF, 0xF8, 0x0C, 0x81, 0x38, 0x4F, 0x39, 0x4E, 0xA9, 0xF8, 0x00, 0x50, 0x19, 0xE0, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0x33, 0x60, 0x34, 0x4D, 0x35, 0x48, 0x2B, 0x68, 0x01, 0x33, ++0x2B, 0x60, 0x00, 0xF0, 0x61, 0xFA, 0x2A, 0x68, 0x53, 0x1E, 0x22, 0xB1, 0x32, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0xB3, 0xF9, 0x41, 0x46, 0x22, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0x40, 0xFE, ++0x01, 0x46, 0x00, 0x28, 0xDD, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x2E, 0x23, 0xD8, 0x33, 0xD0, 0x20, 0x4B, 0x03, 0xEB, ++0x06, 0x16, 0xF3, 0x89, 0x4B, 0x45, 0x0B, 0xD9, 0xB3, 0x68, 0x03, 0xEB, 0x49, 0x09, 0xB9, 0xF1, 0x00, 0x0F, 0xBA, 0xD1, ++0x20, 0x49, 0x21, 0x48, 0xB9, 0x22, 0x01, 0xF0, 0x8B, 0xFE, 0xB4, 0xE7, 0xB4, 0x22, 0x1D, 0x49, 0x1E, 0x48, 0x01, 0xF0, ++0x85, 0xFE, 0x3A, 0x68, 0xB3, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xEB, 0x49, 0x09, 0xA7, 0xDA, 0xB9, 0xF1, ++0x00, 0x0F, 0xA4, 0xD1, 0xE8, 0xE7, 0x15, 0x49, 0x17, 0x48, 0xB2, 0x22, 0x01, 0xF0, 0x74, 0xFE, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x93, 0xDA, 0x0D, 0x2E, 0x04, 0xD0, 0x0F, 0x49, 0x12, 0x48, 0xBB, 0x22, 0x01, 0xF0, 0x68, 0xFE, ++0x0C, 0x49, 0x11, 0x48, 0xB3, 0x22, 0x01, 0xF0, 0x63, 0xFE, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC1, 0xDB, ++0x81, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x14, 0xAD, 0x15, 0x00, 0xC8, 0xAC, 0x15, 0x00, 0x8C, 0xB6, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x84, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB8, 0xAC, 0x15, 0x00, ++0x98, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, 0x41, 0x2D, 0x14, 0x00, ++0x70, 0xB5, 0x20, 0x4D, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x4F, 0xEA, 0x10, 0x26, 0xC4, 0xB2, 0x06, 0xDB, ++0x1C, 0x4D, 0x24, 0x01, 0x25, 0x44, 0xAB, 0x68, 0x33, 0xF8, 0x16, 0x00, 0x70, 0xBD, 0x0C, 0x2C, 0x11, 0xD8, 0x21, 0xD0, ++0x17, 0x4D, 0x05, 0xEB, 0x04, 0x13, 0x24, 0x01, 0xDB, 0x89, 0xB3, 0x42, 0xF0, 0xD8, 0x25, 0x44, 0x14, 0x49, 0x15, 0x48, ++0xD9, 0x22, 0x01, 0xF0, 0x1F, 0xFE, 0xAB, 0x68, 0x33, 0xF8, 0x16, 0x00, 0x70, 0xBD, 0x10, 0x49, 0x11, 0x48, 0xD7, 0x22, ++0x01, 0xF0, 0x16, 0xFE, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDA, 0x0D, 0x2C, 0x04, 0xD0, 0x0A, 0x49, ++0x0C, 0x48, 0xBB, 0x22, 0x01, 0xF0, 0x0A, 0xFE, 0x07, 0x49, 0x0B, 0x48, 0xD8, 0x22, 0x01, 0xF0, 0x05, 0xFE, 0x2B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xD3, 0xDB, 0xC8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x14, 0xAD, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x98, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x68, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x67, 0x4D, 0x68, 0x48, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x00, 0xF0, 0xCF, 0xF9, 0x2B, 0x68, 0x04, 0x46, 0x2B, 0xB1, ++0x61, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x54, 0xD0, 0x00, 0x2C, 0x39, 0xD0, 0x60, 0x4F, 0xB4, 0xF8, ++0x06, 0xA0, 0x3B, 0x68, 0xB4, 0xF8, 0x04, 0x80, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5F, 0xFA, 0x8A, 0xF6, 0x4F, 0xEA, ++0x1A, 0x2A, 0x48, 0xDB, 0xDF, 0xF8, 0x90, 0x91, 0x36, 0x01, 0x59, 0xF8, 0x06, 0x10, 0xB1, 0x44, 0x00, 0x29, 0x52, 0xD0, ++0xD9, 0xF8, 0x08, 0x30, 0x33, 0xF8, 0x1A, 0x30, 0x01, 0xEB, 0xC3, 0x01, 0x40, 0x46, 0x8A, 0x88, 0xFF, 0xF7, 0x9C, 0xFE, ++0x06, 0x46, 0x00, 0x28, 0x45, 0xD0, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x4E, 0x48, 0x01, 0xF0, 0x31, 0xFB, 0x23, 0x89, ++0xE2, 0x88, 0xA0, 0x88, 0x04, 0xF1, 0x0C, 0x01, 0xB0, 0x47, 0x01, 0x28, 0x08, 0xD0, 0x02, 0x28, 0x7B, 0xD0, 0x00, 0x28, ++0x50, 0xD0, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x79, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x3E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x41, 0x4A, 0x2B, 0x68, 0x52, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x00, 0x2A, ++0x40, 0xD0, 0x33, 0xB1, 0x38, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, ++0xF0, 0x87, 0x00, 0x2A, 0xA8, 0xD0, 0x62, 0xB6, 0xA6, 0xE7, 0x0C, 0x2E, 0x36, 0xD8, 0x48, 0xD0, 0xDF, 0xF8, 0xF8, 0x90, ++0x09, 0xEB, 0x06, 0x13, 0x36, 0x01, 0xDB, 0x89, 0x53, 0x45, 0xAE, 0xD8, 0x32, 0x49, 0x33, 0x48, 0x4F, 0xF4, 0x89, 0x72, ++0x01, 0xF0, 0x6C, 0xFD, 0xA7, 0xE7, 0xD9, 0xF8, 0x04, 0x10, 0x69, 0xB1, 0x8A, 0x88, 0x40, 0x46, 0xFF, 0xF7, 0x4C, 0xFE, ++0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x06, 0x46, 0x27, 0x48, 0x01, 0xF0, 0xE3, 0xFA, 0x00, 0x2E, 0xAF, 0xD1, 0x05, 0xE0, ++0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x23, 0x48, 0x01, 0xF0, 0xDA, 0xFA, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x24, 0x48, ++0x01, 0xF0, 0xD4, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0xE5, 0xFC, 0xAF, 0xE7, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0x74, 0xF8, ++0x2B, 0x68, 0xB8, 0xE7, 0x1B, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0x88, 0x72, 0x01, 0xF0, 0x3E, 0xFD, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0x72, 0xAF, 0x0D, 0x2E, 0x04, 0xD0, 0x14, 0x49, 0x18, 0x48, 0xBB, 0x22, 0x01, 0xF0, ++0x31, 0xFD, 0x12, 0x49, 0x16, 0x48, 0x40, 0xF2, 0x11, 0x12, 0x01, 0xF0, 0x2B, 0xFD, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xAB, 0xDB, 0x5E, 0xE7, 0x12, 0x48, 0x21, 0x46, 0x00, 0xF0, 0xCD, 0xF8, 0x85, 0xE7, 0x09, 0x49, 0x10, 0x48, ++0x40, 0xF2, 0x6D, 0x12, 0x01, 0xF0, 0x1A, 0xFD, 0x7E, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x84, 0xB6, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xB4, 0xAB, 0x15, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x98, 0xAC, 0x15, 0x00, 0xDC, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, ++0x8C, 0xB6, 0x17, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x14, 0xAD, 0x15, 0x00, 0x00, 0x20, 0x70, 0x47, 0x02, 0x20, 0x70, 0x47, ++0x30, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4A, ++0x09, 0x4D, 0x11, 0x68, 0x2B, 0x68, 0x4C, 0x1C, 0x18, 0x43, 0x14, 0x60, 0x28, 0x60, 0x2C, 0xB1, 0x03, 0x4B, 0x11, 0x60, ++0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x80, 0xB6, 0x17, 0x00, 0x4F, 0xF0, 0x00, 0x50, 0xFF, 0xF7, 0xDC, 0xBF, 0x30, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0A, 0x4A, 0x0A, 0x4D, 0x11, 0x68, 0x2B, 0x68, 0x4C, 0x1C, ++0x23, 0xEA, 0x00, 0x00, 0x14, 0x60, 0x28, 0x60, 0x2C, 0xB1, 0x04, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, ++0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x18, 0x4E, 0x34, 0x68, 0xDC, 0xB1, 0xDF, 0xF8, 0x68, 0x80, 0x17, 0x4D, 0x17, 0x4F, 0xDF, 0xF8, ++0x64, 0xA0, 0xDF, 0xF8, 0x64, 0x90, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB4, 0xFA, 0x84, 0xF4, ++0x12, 0xDB, 0x55, 0xF8, 0x34, 0x30, 0x05, 0xEB, 0xC4, 0x04, 0x60, 0x68, 0x98, 0x47, 0x3B, 0x68, 0x34, 0x68, 0xDB, 0x78, ++0x1B, 0xB9, 0x00, 0x2C, 0xEB, 0xD1, 0xBD, 0xE8, 0xF0, 0x87, 0xE9, 0xF7, 0x09, 0xFA, 0x00, 0x2C, 0xE5, 0xD1, 0xF8, 0xE7, ++0x1D, 0x2C, 0x03, 0xDC, 0x55, 0xF8, 0x34, 0x30, 0x00, 0x2B, 0xE8, 0xD1, 0xDC, 0x22, 0x51, 0x46, 0x48, 0x46, 0x01, 0xF0, ++0x7D, 0xFC, 0xE0, 0xE7, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x21, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xE4, 0xAD, 0x15, 0x00, 0x08, 0xB5, 0xFF, 0xF7, 0x35, 0xFC, 0x08, 0x4B, 0x08, 0x49, 0xD8, 0x61, ++0x00, 0x22, 0xC3, 0xE9, 0x03, 0x22, 0xC3, 0xE9, 0x01, 0x22, 0xC3, 0xE9, 0x05, 0x22, 0x59, 0x62, 0x4F, 0xF0, 0xFF, 0x30, ++0xBD, 0xE8, 0x08, 0x40, 0xFF, 0xF7, 0x8A, 0xBF, 0x80, 0xB6, 0x17, 0x00, 0xD1, 0x31, 0x14, 0x00, 0x00, 0x23, 0xC0, 0xE9, ++0x00, 0x33, 0x70, 0x47, 0x38, 0xB5, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, ++0x07, 0xDB, 0x2B, 0x68, 0x6B, 0xB1, 0x6B, 0x68, 0x1C, 0x60, 0x00, 0x23, 0x6C, 0x60, 0x23, 0x60, 0x38, 0xBD, 0x00, 0x29, ++0xF5, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x48, 0x22, 0x01, 0xF0, 0x3C, 0xFC, 0xEF, 0xE7, 0x00, 0x23, 0x2C, 0x60, 0x6C, 0x60, ++0x23, 0x60, 0x38, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x14, 0xAE, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, 0x04, 0xDB, 0x2B, 0x68, 0x53, 0xB1, 0x23, 0x60, ++0x2C, 0x60, 0x38, 0xBD, 0x00, 0x29, 0xF8, 0xD1, 0x05, 0x49, 0x06, 0x48, 0x5F, 0x22, 0x01, 0xF0, 0x1B, 0xFC, 0xF2, 0xE7, ++0x6C, 0x60, 0x23, 0x60, 0x2C, 0x60, 0x38, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x14, 0xAE, 0x15, 0x00, ++0x03, 0x68, 0x33, 0xB1, 0x42, 0x68, 0x19, 0x68, 0x01, 0x60, 0x9A, 0x42, 0x04, 0xBF, 0x00, 0x22, 0x42, 0x60, 0x18, 0x46, ++0x70, 0x47, 0x00, 0xBF, 0x38, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, ++0x0B, 0xDB, 0x2B, 0x68, 0x43, 0xB1, 0xA3, 0x42, 0x02, 0xD1, 0x14, 0xE0, 0xA3, 0x42, 0x0C, 0xD0, 0x1A, 0x46, 0x1B, 0x68, ++0x00, 0x2B, 0xF9, 0xD1, 0x38, 0xBD, 0x00, 0x28, 0xF1, 0xD1, 0x0C, 0x49, 0x0C, 0x48, 0x84, 0x22, 0x01, 0xF0, 0xE8, 0xFB, ++0xEB, 0xE7, 0x6B, 0x68, 0xA3, 0x42, 0x0A, 0xD0, 0x23, 0x68, 0x13, 0x60, 0x38, 0xBD, 0x6B, 0x68, 0x22, 0x68, 0x2A, 0x60, ++0xA3, 0x42, 0xEB, 0xD1, 0x00, 0x23, 0x6B, 0x60, 0x38, 0xBD, 0x6A, 0x60, 0xF2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x28, 0xAE, 0x15, 0x00, 0x03, 0x68, 0x2B, 0xB1, 0x00, 0x20, 0x1B, 0x68, 0x01, 0x30, 0x00, 0x2B, ++0xFB, 0xD1, 0x70, 0x47, 0x18, 0x46, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0xD0, 0xE9, 0x00, 0x47, 0x80, 0x46, 0x0D, 0x46, ++0x16, 0x46, 0x1F, 0xB1, 0x39, 0x46, 0x28, 0x46, 0x90, 0x47, 0x88, 0xB1, 0x00, 0x27, 0x24, 0xB9, 0x1A, 0xE0, 0x23, 0x68, ++0x27, 0x46, 0x8B, 0xB1, 0x1C, 0x46, 0x21, 0x46, 0x28, 0x46, 0xB0, 0x47, 0x00, 0x28, 0xF6, 0xD0, 0x2C, 0x60, 0x67, 0xB9, ++0xC8, 0xF8, 0x00, 0x50, 0xBD, 0xE8, 0xF0, 0x81, 0x3D, 0x60, 0xC8, 0xF8, 0x04, 0x50, 0x28, 0x60, 0xBD, 0xE8, 0xF0, 0x81, ++0xC8, 0xF8, 0x04, 0x50, 0x2B, 0x60, 0x3D, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x23, 0xC8, 0xF8, 0x04, 0x50, 0x2B, 0x60, ++0xEA, 0xE7, 0x00, 0xBF, 0x03, 0x68, 0xB9, 0xB1, 0xCB, 0xB1, 0x8B, 0x42, 0x10, 0xB4, 0x04, 0x46, 0x02, 0xD1, 0x07, 0xE0, ++0x99, 0x42, 0x05, 0xD0, 0x1B, 0x68, 0x00, 0x2B, 0xFA, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x63, 0x68, 0x08, 0x68, ++0x10, 0x60, 0x8B, 0x42, 0x0A, 0x60, 0xF6, 0xD1, 0x62, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x11, 0x46, 0xFF, 0xF7, ++0x49, 0xBF, 0x70, 0x47, 0x81, 0xB1, 0x03, 0x68, 0x8B, 0x42, 0x0A, 0xD0, 0x2B, 0xB1, 0x18, 0x68, 0x88, 0x42, 0x03, 0xD0, ++0x03, 0x46, 0x00, 0x2B, 0xF9, 0xD1, 0x70, 0x47, 0x11, 0x60, 0x1A, 0x60, 0x70, 0x47, 0x11, 0x46, 0xFF, 0xF7, 0x36, 0xBF, ++0x11, 0x46, 0xFF, 0xF7, 0x0F, 0xBF, 0x00, 0xBF, 0x0B, 0x46, 0x09, 0x68, 0x99, 0xB1, 0x02, 0x46, 0x00, 0x68, 0x48, 0xB1, ++0x10, 0xB4, 0x54, 0x68, 0x58, 0x68, 0x21, 0x60, 0x50, 0x60, 0x00, 0x22, 0x5D, 0xF8, 0x04, 0x4B, 0x1A, 0x60, 0x70, 0x47, ++0x93, 0xE8, 0x03, 0x00, 0x82, 0xE8, 0x03, 0x00, 0x00, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x70, 0x47, 0xF8, 0xB5, 0x1F, 0x4F, ++0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0x46, 0x0D, 0x46, 0x14, 0x46, 0x0A, 0xDB, 0x25, 0xB3, 0x23, 0x68, ++0x2B, 0x60, 0x73, 0x68, 0xA3, 0x42, 0x4F, 0xF0, 0x00, 0x03, 0x08, 0xBF, 0x75, 0x60, 0x23, 0x60, 0xF8, 0xBD, 0xE0, 0xB1, ++0xB5, 0xB1, 0x2B, 0x68, 0xA3, 0x42, 0x0A, 0xD0, 0x13, 0x49, 0x14, 0x48, 0x40, 0xF2, 0x75, 0x12, 0x01, 0xF0, 0x2A, 0xFB, ++0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE5, 0xDA, 0x00, 0x2C, 0xE3, 0xD1, 0x0D, 0x49, 0x0E, 0x48, 0x4F, 0xF4, ++0xBB, 0x72, 0x01, 0xF0, 0x1D, 0xFB, 0xDB, 0xE7, 0x00, 0x2C, 0xF6, 0xD0, 0x23, 0x68, 0x33, 0x60, 0xD9, 0xE7, 0x07, 0x49, ++0x09, 0x48, 0x4F, 0xF4, 0xBA, 0x72, 0x01, 0xF0, 0x11, 0xFB, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xD7, 0xDB, ++0xCA, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x38, 0xAE, 0x15, 0x00, 0x74, 0xAE, 0x15, 0x00, ++0x28, 0xAE, 0x15, 0x00, 0x81, 0xB1, 0x10, 0xB4, 0x08, 0x4C, 0x01, 0x44, 0x10, 0xF8, 0x01, 0x3B, 0x83, 0xEA, 0x12, 0x63, ++0x81, 0x42, 0x54, 0xF8, 0x23, 0x30, 0x83, 0xEA, 0x02, 0x22, 0xF5, 0xD1, 0x10, 0x46, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x10, 0x46, 0x70, 0x47, 0x84, 0xAE, 0x15, 0x00, 0xF8, 0xB5, 0x0F, 0x18, 0xB8, 0x42, 0xBC, 0x46, 0x06, 0xD3, 0x1D, 0xE0, ++0x44, 0x78, 0x2E, 0x78, 0x02, 0x34, 0xFF, 0x2E, 0x20, 0x44, 0x06, 0xD0, 0x46, 0x1C, 0xB7, 0x42, 0x05, 0x46, 0xF5, 0xD8, ++0x00, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x87, 0x42, 0xFA, 0xD3, 0x1C, 0x80, 0x00, 0x2D, 0xF7, 0xD0, 0xEE, 0x1C, 0x66, 0x45, ++0xF4, 0xD8, 0xAE, 0x78, 0x96, 0x42, 0xF2, 0xD0, 0x0C, 0x1B, 0x84, 0x45, 0xA1, 0xB2, 0x01, 0xD9, 0x0F, 0x18, 0xE7, 0xE7, ++0x06, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE5, 0xDA, 0x84, 0x45, 0xE3, 0xD0, 0x03, 0x49, 0x04, 0x48, ++0x7F, 0x22, 0x01, 0xF0, 0xB9, 0xFA, 0xDD, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x84, 0xB2, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x01, 0xEB, 0x00, 0x08, 0x40, 0x45, 0xC6, 0x46, 0x2D, 0xD2, 0x02, 0xF1, 0x05, 0x0C, 0xC2, 0xF1, ++0x02, 0x07, 0x05, 0xE0, 0x44, 0x78, 0x35, 0x78, 0x02, 0x34, 0xDD, 0x2D, 0x20, 0x44, 0x07, 0xD0, 0x45, 0x1C, 0xA8, 0x45, ++0x06, 0x46, 0xF5, 0xD8, 0x00, 0x26, 0x30, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x80, 0x45, 0xF9, 0xD3, 0x1C, 0x80, 0x00, 0x2E, ++0xF6, 0xD0, 0xF5, 0x1D, 0xAE, 0x45, 0xF3, 0xD3, 0x15, 0x46, 0x01, 0xE0, 0x65, 0x45, 0xF0, 0xD0, 0x05, 0xEB, 0x06, 0x08, ++0x15, 0xF8, 0x01, 0x9B, 0x18, 0xF8, 0x07, 0x80, 0xC1, 0x45, 0xF5, 0xD0, 0x0C, 0x1B, 0x86, 0x45, 0xA1, 0xB2, 0x02, 0xD9, ++0x01, 0xEB, 0x00, 0x08, 0xDC, 0xE7, 0x07, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDA, 0x86, 0x45, ++0xD8, 0xD0, 0x04, 0x49, 0x04, 0x48, 0xB4, 0x22, 0x01, 0xF0, 0x70, 0xFA, 0xD2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0xB2, 0x15, 0x00, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x70, 0xB4, 0x03, 0xE0, ++0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x10, 0xD9, 0x44, 0x78, 0x06, 0x78, 0xA3, 0x1C, 0x01, 0x2E, 0x03, 0xEB, 0x00, 0x05, ++0xF4, 0xD1, 0xA9, 0x42, 0x07, 0xD3, 0x38, 0xB1, 0x0A, 0x2B, 0x04, 0xD8, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x70, 0x70, 0xBC, ++0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x17, 0xD9, ++0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, 0xA3, 0x1C, 0x32, 0x2E, ++0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x70, 0x70, 0xBC, ++0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x70, 0xB4, 0x03, 0xE0, 0x73, 0x1C, 0x99, 0x42, 0x30, 0x46, 0x10, 0xD9, 0x45, 0x78, 0x04, 0x78, 0xAB, 0x1C, 0x1E, 0x18, ++0x00, 0x2C, 0xF5, 0xD1, 0xB1, 0x42, 0x05, 0xD3, 0x10, 0xB1, 0x22, 0x2B, 0x02, 0xD8, 0x15, 0x70, 0x70, 0xBC, 0x70, 0x47, ++0x20, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x17, 0xD9, 0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, ++0xA3, 0x1C, 0x07, 0x2E, 0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x07, 0x2B, 0x02, 0xD9, ++0x14, 0x70, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x17, 0xD9, 0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, ++0xA3, 0x1C, 0x30, 0x2E, 0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x13, 0x2B, 0x02, 0xD9, ++0x14, 0x70, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x25, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x05, 0x2B, 0x18, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, ++0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x3C, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, ++0x06, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x1A, 0xD9, 0x30, 0xB4, 0x03, 0xE0, 0x63, 0x1C, 0x99, 0x42, ++0x20, 0x46, 0x11, 0xD9, 0x43, 0x78, 0x05, 0x78, 0x02, 0x33, 0x3E, 0x2D, 0x03, 0xEB, 0x00, 0x04, 0xF4, 0xD1, 0xA1, 0x42, ++0x08, 0xD3, 0x40, 0xB1, 0xA3, 0xF1, 0x03, 0x03, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0x30, 0xBC, 0x13, 0x70, 0x70, 0x47, ++0x00, 0x20, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x2B, 0xD9, ++0x30, 0xB4, 0x03, 0xE0, 0x18, 0x46, 0x01, 0x33, 0x99, 0x42, 0x16, 0xD9, 0x44, 0x78, 0x05, 0x78, 0xA3, 0x1C, 0xC4, 0x2D, ++0x03, 0x44, 0xF5, 0xD1, 0x99, 0x42, 0x0E, 0xD3, 0x70, 0xB1, 0x02, 0x30, 0x04, 0x44, 0x07, 0xE0, 0x43, 0x78, 0x05, 0x78, ++0x02, 0x33, 0xC2, 0x2D, 0x03, 0xEB, 0x00, 0x01, 0x06, 0xD0, 0x08, 0x46, 0x43, 0x1C, 0x9C, 0x42, 0xF4, 0xD8, 0x00, 0x20, ++0x30, 0xBC, 0x70, 0x47, 0x8C, 0x42, 0xFA, 0xD3, 0x00, 0x28, 0xF9, 0xD0, 0xA3, 0xF1, 0x05, 0x03, 0xB3, 0xFA, 0x83, 0xF3, ++0x5B, 0x09, 0x30, 0xBC, 0x13, 0x70, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x03, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x4C, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x12, 0x2B, 0x18, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, ++0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x2A, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, ++0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, ++0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xC7, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, ++0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, ++0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x20, 0x2C, 0x03, 0xEB, 0x00, 0x02, ++0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x36, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x05, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xB5, 0x83, 0xB0, ++0x06, 0x4A, 0x0D, 0xF1, 0x06, 0x03, 0xFF, 0xF7, 0xC1, 0xFD, 0x20, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0x1A, 0x2B, 0x18, 0xBF, ++0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x98, 0xB2, 0x15, 0x00, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x2D, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x1C, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x47, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x06, 0x2B, 0x38, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x1D, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x63, 0x1C, 0x99, 0x42, 0x20, 0x46, 0x13, 0xD9, ++0x43, 0x78, 0x02, 0x78, 0x02, 0x33, 0x1C, 0x18, 0x00, 0x2A, 0xF5, 0xD1, 0xA1, 0x42, 0x03, 0xD2, 0x10, 0x46, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x28, 0xFA, 0xD0, 0x06, 0x2B, 0x38, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x53, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x04, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x55, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x02, 0x2B, 0x08, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, ++0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xBF, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, ++0x0E, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, 0x06, 0x03, 0x23, 0x22, 0xFF, 0xF7, 0xB2, 0xFC, ++0x40, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0xA3, 0xF1, 0x18, 0x02, 0x21, 0x2A, 0x9A, 0xBF, 0x03, 0x3B, 0x23, 0x70, 0x00, 0x20, ++0x02, 0xB0, 0x10, 0xBD, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, ++0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x3D, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, ++0x06, 0xD3, 0x30, 0xB1, 0x18, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, ++0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xC0, 0x2C, 0x03, 0xEB, 0x00, 0x02, ++0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x07, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, ++0x06, 0x03, 0x24, 0x22, 0xFF, 0xF7, 0x5E, 0xFC, 0x40, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0xA3, 0xF1, 0x09, 0x02, 0x09, 0x2A, ++0x9A, 0xBF, 0x03, 0x3B, 0x23, 0x70, 0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x06, 0x03, ++0x26, 0x22, 0xFF, 0xF7, 0x4B, 0xFC, 0x20, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0x10, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0xFB, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x06, 0x03, 0x25, 0x22, 0xFF, 0xF7, 0x3B, 0xFC, 0x20, 0xB1, ++0xBD, 0xF8, 0x06, 0x30, 0x04, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x43, 0x79, 0x02, 0x79, ++0x58, 0x00, 0x40, 0xEA, 0xD2, 0x10, 0x80, 0x05, 0x70, 0x47, 0x00, 0xBF, 0x43, 0x79, 0x07, 0x48, 0x83, 0xEA, 0x13, 0x13, ++0x5B, 0x01, 0xC1, 0xF3, 0x08, 0x01, 0x03, 0xF4, 0xF0, 0x73, 0x0B, 0x44, 0x00, 0xEA, 0x83, 0x50, 0x40, 0xF4, 0x7C, 0x10, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x28, 0x08, 0xDA, 0x10, 0xF1, 0x6D, 0x0F, 0x01, 0xDA, 0x00, 0x20, ++0x70, 0x47, 0x6E, 0x30, 0x40, 0x00, 0xC0, 0xB2, 0x70, 0x47, 0xDC, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, ++0x1D, 0x46, 0x95, 0xB0, 0x90, 0x46, 0xDD, 0xF8, 0x78, 0xB0, 0x15, 0xF8, 0x01, 0x2B, 0x03, 0x91, 0x07, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0x7F, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x91, 0x83, 0x00, 0x24, 0xCD, 0xE9, 0x00, 0x44, 0x03, 0x9E, 0x02, 0x94, ++0xA1, 0x46, 0xA2, 0x46, 0xA2, 0xF1, 0x20, 0x03, 0x58, 0x2B, 0x5A, 0xD8, 0xDF, 0xE8, 0x13, 0xF0, 0x35, 0x01, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x34, 0x03, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x17, 0x03, 0x35, 0x01, ++0x59, 0x00, 0x35, 0x01, 0x36, 0x03, 0x59, 0x00, 0x12, 0x01, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x10, 0x01, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x01, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0xA2, 0xF1, 0x31, 0x01, 0x08, 0x29, ++0x40, 0xF2, 0xE2, 0x80, 0x00, 0x21, 0x9E, 0x48, 0x00, 0xEB, 0xCA, 0x0A, 0x1A, 0xF8, 0x01, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, ++0x00, 0xF2, 0xD8, 0x83, 0xDF, 0xE8, 0x0A, 0xF0, 0x75, 0x5B, 0x45, 0x9A, 0x70, 0x8E, 0x80, 0x06, 0x07, 0x21, 0xEE, 0xE7, ++0xA2, 0xF1, 0x41, 0x03, 0x37, 0x2B, 0x00, 0xF2, 0x05, 0x82, 0xDF, 0xE8, 0x13, 0xF0, 0x05, 0x02, 0x03, 0x02, 0x03, 0x02, ++0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x54, 0x02, ++0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, ++0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x05, 0x02, ++0x29, 0x01, 0x5E, 0x01, 0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0xA3, 0x01, 0x03, 0x02, 0x03, 0x02, ++0x03, 0x02, 0x54, 0x02, 0x03, 0x02, 0x03, 0x02, 0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0xF8, 0x01, 0x03, 0x02, 0x29, 0x01, ++0x03, 0x02, 0x03, 0x02, 0x29, 0x01, 0x10, 0x2B, 0x00, 0xF2, 0xCA, 0x80, 0xDF, 0xE8, 0x13, 0xF0, 0xD2, 0x00, 0xC8, 0x00, ++0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xD9, 0x00, ++0xC8, 0x00, 0xE0, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC1, 0x00, 0x00, 0x23, 0x00, 0x93, 0x02, 0x93, 0x4F, 0xF0, 0xFF, 0x33, ++0x01, 0x93, 0x4F, 0xF0, 0x01, 0x0A, 0x15, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0x7F, 0xF4, 0x28, 0xAF, 0x00, 0x2E, 0x62, 0xD0, ++0x00, 0x23, 0x3B, 0x70, 0x20, 0x46, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x23, 0x01, 0x93, 0x4F, 0xF0, 0x04, 0x0A, ++0xED, 0xE7, 0x2E, 0xB1, 0xA0, 0x45, 0x9C, 0xBF, 0x07, 0xF8, 0x01, 0x2B, 0x06, 0xF1, 0xFF, 0x36, 0x01, 0x34, 0x4F, 0xF0, ++0x00, 0x0A, 0xE2, 0xE7, 0x68, 0x2A, 0x7B, 0xD0, 0x6C, 0x2A, 0x3F, 0xD0, 0x57, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC0, 0xF2, 0x92, 0x82, 0x4F, 0xF0, 0x06, 0x0A, 0xD4, 0xE7, 0x2A, 0x2A, 0x61, 0xD0, 0x01, 0x9B, 0x30, 0x3A, ++0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x43, 0x03, 0x01, 0x93, 0x4F, 0xF0, 0x05, 0x0A, 0xC8, 0xE7, 0x2A, 0x2A, 0x5B, 0xD0, ++0x02, 0x9B, 0x30, 0x3A, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x43, 0x03, 0x02, 0x93, 0x4F, 0xF0, 0x03, 0x0A, 0xBC, 0xE7, ++0x06, 0x21, 0x4C, 0xE7, 0x44, 0x4B, 0x03, 0xEB, 0xCA, 0x0A, 0x9A, 0xF8, 0x03, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, ++0x25, 0x83, 0x01, 0xA3, 0x53, 0xF8, 0x2A, 0xF0, 0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0xBB, 0x40, 0x14, 0x00, ++0xD9, 0x3F, 0x14, 0x00, 0x85, 0x3F, 0x14, 0x00, 0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, ++0x00, 0x9B, 0x43, 0xF0, 0x02, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x06, 0x0A, 0x97, 0xE7, 0x05, 0x21, 0x27, 0xE7, 0x03, 0x9B, ++0x00, 0x2B, 0x9B, 0xD0, 0x20, 0x46, 0x07, 0xF8, 0x01, 0x6C, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0x49, 0x01, 0xEB, ++0xCA, 0x0A, 0x9A, 0xF8, 0x04, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, 0xF7, 0x82, 0x01, 0xA1, 0x51, 0xF8, 0x2A, 0xF0, ++0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0x2F, 0x3F, 0x14, 0x00, 0xDD, 0x3F, 0x14, 0x00, 0x85, 0x3F, 0x14, 0x00, ++0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, 0x5B, 0xF8, 0x04, 0x3B, 0x01, 0x93, 0x4F, 0xF0, ++0x05, 0x0A, 0x6A, 0xE7, 0x5B, 0xF8, 0x04, 0x3B, 0x02, 0x93, 0x4F, 0xF0, 0x03, 0x0A, 0x64, 0xE7, 0x00, 0x9B, 0x43, 0xF0, ++0x01, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x06, 0x0A, 0x5D, 0xE7, 0x14, 0x46, 0x00, 0x2A, 0x3F, 0xF4, 0x63, 0xAF, 0x03, 0x90, ++0x7D, 0xE6, 0x00, 0x9B, 0x43, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x50, 0xE7, 0x10, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9E, 0x82, 0x4F, 0xF0, 0x02, 0x0A, 0x46, 0xE7, 0x00, 0x9B, 0x43, 0xF0, ++0x10, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x3F, 0xE7, 0x00, 0x9B, 0x43, 0xF0, 0x08, 0x03, 0x00, 0x93, 0x4F, 0xF0, ++0x02, 0x0A, 0x38, 0xE7, 0x00, 0x9B, 0x43, 0xF0, 0x20, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x31, 0xE7, 0x00, 0xBF, ++0x24, 0xB3, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x9B, 0x9B, 0x07, 0x00, 0xF1, 0x94, 0x81, 0x00, 0x9B, 0xD8, 0x07, ++0x40, 0xF1, 0x90, 0x81, 0x64, 0x2A, 0x00, 0xF0, 0x32, 0x82, 0x5B, 0xF8, 0x04, 0x1B, 0x58, 0x3A, 0x89, 0xB2, 0x20, 0x2A, ++0x00, 0xF2, 0x24, 0x82, 0xDF, 0xE8, 0x12, 0xF0, 0x5A, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, ++0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x4E, 0x02, 0x22, 0x02, 0x72, 0x00, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, ++0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x36, 0x02, 0x22, 0x02, ++0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x72, 0x00, 0x22, 0x02, 0x22, 0x02, 0x69, 0x02, 0x02, 0x9B, 0x59, 0x1E, 0x5B, 0xF8, ++0x04, 0x3B, 0x8D, 0xF8, 0x10, 0x30, 0x00, 0x9B, 0x04, 0xAA, 0x03, 0xF0, 0x40, 0x00, 0x01, 0x23, 0x00, 0x28, 0x70, 0xD1, ++0x00, 0x98, 0x80, 0x06, 0x40, 0xF1, 0x15, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0xEA, 0x81, 0x10, 0x46, 0x02, 0xEB, 0x03, 0x09, ++0xA4, 0xEB, 0x02, 0x0E, 0x09, 0xE0, 0xE0, 0x45, 0x04, 0xD8, 0x07, 0x78, 0x02, 0xF8, 0x01, 0x7B, 0x01, 0x3E, 0x17, 0x46, ++0x01, 0x30, 0x48, 0x45, 0x07, 0xD0, 0x00, 0xEB, 0x0E, 0x0C, 0x3A, 0x46, 0x00, 0x2E, 0xF0, 0xD1, 0x01, 0x30, 0x48, 0x45, ++0xF4, 0xD1, 0x23, 0x44, 0x00, 0x29, 0x40, 0xF3, 0xCA, 0x81, 0xCC, 0x18, 0x20, 0x21, 0x08, 0xE0, 0x98, 0x45, 0x03, 0xD8, ++0x02, 0xF8, 0x01, 0x1B, 0x01, 0x3E, 0x17, 0x46, 0x01, 0x33, 0xA3, 0x42, 0x05, 0xD0, 0x3A, 0x46, 0x00, 0x2E, 0xF3, 0xD1, ++0x01, 0x33, 0xA3, 0x42, 0xF6, 0xD1, 0x4F, 0xF0, 0x07, 0x0A, 0xB2, 0xE6, 0x00, 0x9B, 0x99, 0x07, 0x03, 0xD4, 0x00, 0x9B, ++0xDA, 0x07, 0x00, 0xF1, 0xBC, 0x81, 0x5B, 0xF8, 0x04, 0x1B, 0x00, 0x29, 0xC0, 0xF2, 0xBE, 0x81, 0xDF, 0xF8, 0x5C, 0xA4, ++0x00, 0x23, 0x0D, 0xF1, 0x50, 0x0E, 0xAA, 0xFB, 0x01, 0x2C, 0x4F, 0xEA, 0xDC, 0x0C, 0x0C, 0xEB, 0x8C, 0x00, 0xA1, 0xEB, ++0x40, 0x00, 0x89, 0x46, 0x30, 0x30, 0xB9, 0xF1, 0x09, 0x0F, 0x72, 0x46, 0x61, 0x46, 0x0E, 0xF8, 0x01, 0x0D, 0x18, 0x46, ++0x03, 0xF1, 0x01, 0x03, 0xEB, 0xD8, 0x00, 0x99, 0x09, 0x06, 0x00, 0xF1, 0x9E, 0x81, 0x00, 0x99, 0x09, 0x07, 0x40, 0xF1, ++0xE7, 0x81, 0x83, 0x1C, 0x2B, 0x20, 0x0E, 0xF8, 0x01, 0x0C, 0x00, 0x98, 0x02, 0x99, 0x00, 0xF0, 0x40, 0x00, 0x02, 0x3A, ++0xC9, 0x1A, 0x00, 0x28, 0x8E, 0xD0, 0x00, 0x29, 0x14, 0xDD, 0x0C, 0x44, 0x4F, 0xF0, 0x30, 0x0E, 0x08, 0xE0, 0xE0, 0x45, ++0x03, 0xD8, 0x00, 0xF8, 0x01, 0xEB, 0x01, 0x3E, 0x07, 0x46, 0x01, 0x39, 0x00, 0xF0, 0xB0, 0x80, 0xA4, 0xEB, 0x01, 0x0C, ++0x38, 0x46, 0x00, 0x2E, 0xF1, 0xD1, 0x01, 0x39, 0xF5, 0xD1, 0x00, 0x21, 0x00, 0x2B, 0x7F, 0xF4, 0x7C, 0xAF, 0x91, 0x46, ++0xA7, 0xE7, 0x5B, 0xF8, 0x04, 0x2B, 0x00, 0x2A, 0x40, 0xF0, 0x2C, 0x81, 0x00, 0x9B, 0x02, 0x99, 0x03, 0xF0, 0x40, 0x00, ++0x00, 0x23, 0x65, 0xE7, 0x4A, 0x46, 0xF7, 0xE7, 0x5B, 0xF8, 0x04, 0x3B, 0x02, 0x9A, 0xDF, 0xF8, 0xB0, 0xE3, 0x9C, 0x46, ++0x1C, 0xF8, 0x01, 0x3B, 0x00, 0x2A, 0x00, 0xF0, 0x09, 0x81, 0x19, 0x11, 0x15, 0x2A, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, ++0x01, 0x10, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, 0x10, 0x10, 0x28, 0xBF, 0x15, 0x22, 0x02, 0xEB, 0x42, 0x01, 0x01, 0x3A, ++0x8D, 0xF8, 0x11, 0x30, 0x01, 0xF1, 0xFF, 0x33, 0xC1, 0xF1, 0x01, 0x01, 0x1D, 0xD0, 0x0C, 0xEB, 0x02, 0x0A, 0x0D, 0xF1, ++0x13, 0x02, 0x1C, 0xF0, 0x03, 0x0F, 0x1C, 0xF8, 0x01, 0x0B, 0x4F, 0xEA, 0x20, 0x19, 0x00, 0xF0, 0x0F, 0x00, 0x1E, 0xF8, ++0x09, 0x90, 0x82, 0xF8, 0x00, 0x90, 0x1E, 0xF8, 0x00, 0x00, 0x50, 0x70, 0x0C, 0xBF, 0x4F, 0xF0, 0x3A, 0x09, 0x4F, 0xF0, ++0x2E, 0x09, 0xE2, 0x45, 0x02, 0xF8, 0x01, 0x9C, 0x02, 0xF1, 0x03, 0x02, 0xE5, 0xD1, 0x00, 0x9A, 0x02, 0xF0, 0x40, 0x02, ++0x00, 0x2A, 0x40, 0xF0, 0x69, 0x81, 0x00, 0x98, 0x02, 0x92, 0x80, 0x06, 0x04, 0xAA, 0x3F, 0xF5, 0x1F, 0xAF, 0x00, 0x2B, ++0x7F, 0xF4, 0x1F, 0xAF, 0xA1, 0xE7, 0x5B, 0xF8, 0x04, 0x1B, 0xDF, 0xF8, 0x14, 0xE3, 0x8C, 0x46, 0x4F, 0xF0, 0x3A, 0x09, ++0x1C, 0xF8, 0x06, 0x3B, 0x1A, 0x11, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, 0x02, 0x20, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, ++0x11, 0x30, 0x8D, 0xF8, 0x10, 0x20, 0x01, 0x31, 0x04, 0xAB, 0x11, 0xF8, 0x01, 0x2B, 0x83, 0xF8, 0x02, 0x90, 0x10, 0x11, ++0x02, 0xF0, 0x0F, 0x02, 0x1E, 0xF8, 0x00, 0x00, 0x1E, 0xF8, 0x02, 0x20, 0xD8, 0x70, 0x8C, 0x45, 0x1A, 0x71, 0x03, 0xF1, ++0x03, 0x03, 0xEE, 0xD1, 0x02, 0x9B, 0xA3, 0xF1, 0x11, 0x01, 0x00, 0x9B, 0x04, 0xAA, 0x03, 0xF0, 0x40, 0x00, 0x11, 0x23, ++0xE4, 0xE6, 0x00, 0x29, 0x7F, 0xF7, 0x6C, 0xAF, 0x21, 0x44, 0x4F, 0xF0, 0x20, 0x0C, 0x08, 0xE0, 0xA0, 0x45, 0x03, 0xD8, ++0x00, 0xF8, 0x01, 0xCB, 0x01, 0x3E, 0x07, 0x46, 0x01, 0x34, 0xA1, 0x42, 0x05, 0xD0, 0x38, 0x46, 0x00, 0x2E, 0xF3, 0xD1, ++0x01, 0x34, 0xA1, 0x42, 0xF6, 0xD1, 0x0C, 0x46, 0x00, 0x21, 0x00, 0x2B, 0x7F, 0xF4, 0xD3, 0xAE, 0x55, 0xE7, 0x04, 0x23, ++0x9A, 0x49, 0x01, 0xEB, 0xCA, 0x0A, 0x1A, 0xF8, 0x03, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, 0x1F, 0x81, 0x01, 0xA3, ++0x53, 0xF8, 0x2A, 0xF0, 0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0xC9, 0x40, 0x14, 0x00, 0xD9, 0x3F, 0x14, 0x00, ++0x85, 0x3F, 0x14, 0x00, 0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, 0x01, 0x23, 0xE1, 0xE7, ++0x02, 0x21, 0x26, 0xE5, 0x58, 0x3A, 0x5B, 0xF8, 0x04, 0x1B, 0x20, 0x2A, 0x00, 0xF2, 0x98, 0x80, 0x01, 0xA3, 0x53, 0xF8, ++0x22, 0xF0, 0x00, 0xBF, 0xED, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0xD5, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x17, 0x42, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0xA5, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x1D, 0x42, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x0B, 0x46, 0x14, 0x00, 0x03, 0x9E, 0x14, 0x46, ++0x4A, 0xE5, 0x64, 0x49, 0x64, 0x48, 0x4F, 0xF4, 0xA2, 0x72, 0x00, 0xF0, 0x49, 0xFB, 0x4F, 0xF0, 0x06, 0x0A, 0x3C, 0xE5, ++0x1A, 0x11, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, 0x02, 0x20, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, 0x10, 0x20, 0x8D, 0xF8, ++0x11, 0x30, 0x6F, 0xF0, 0x2E, 0x01, 0x2F, 0x23, 0x0F, 0x22, 0xFC, 0xE6, 0x13, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x97, 0x80, ++0x01, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0xCC, 0xAE, 0x01, 0x9B, 0x11, 0x46, 0xC2, 0xF1, 0x01, 0x00, 0x00, 0x2B, 0x00, 0xEB, ++0x01, 0x0C, 0x0F, 0xDD, 0x11, 0xF8, 0x01, 0xEF, 0x01, 0x3B, 0xBE, 0xF1, 0x00, 0x0F, 0x10, 0xD0, 0x00, 0x2B, 0xF3, 0xD1, ++0x02, 0x99, 0x00, 0x98, 0x01, 0x93, 0x63, 0x46, 0xC9, 0x1A, 0x00, 0xF0, 0x40, 0x00, 0x1F, 0xE6, 0x00, 0xEB, 0x01, 0x0C, ++0x11, 0xF8, 0x01, 0xEF, 0xBE, 0xF1, 0x00, 0x0F, 0xE4, 0xD1, 0x01, 0x93, 0x63, 0x46, 0x02, 0x99, 0x00, 0x98, 0xC9, 0x1A, ++0x00, 0xF0, 0x40, 0x00, 0x10, 0xE6, 0x1C, 0x46, 0x4F, 0xF0, 0x07, 0x0A, 0xF9, 0xE4, 0x23, 0x46, 0x91, 0x46, 0x2B, 0xE6, ++0x00, 0x9B, 0x02, 0x99, 0x03, 0xF0, 0x40, 0x00, 0x14, 0xAA, 0x00, 0x23, 0x02, 0xE6, 0x5B, 0xF8, 0x04, 0x1B, 0x09, 0xB2, ++0x41, 0xE6, 0x83, 0x1C, 0x2D, 0x20, 0x64, 0xE6, 0x00, 0x9B, 0x43, 0xF0, 0x80, 0x03, 0x49, 0x42, 0x00, 0x93, 0x3B, 0xE6, ++0x00, 0x9B, 0x43, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x08, 0x23, 0x40, 0x20, 0x02, 0x93, 0xDF, 0xF8, 0xD0, 0xC0, 0x14, 0xAA, ++0x01, 0xF0, 0x0F, 0x03, 0x09, 0x09, 0x1C, 0xF8, 0x03, 0x30, 0x02, 0xF8, 0x01, 0x3D, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, ++0xF4, 0xD1, 0x02, 0x99, 0xC9, 0x1A, 0xDD, 0xE5, 0x14, 0xAA, 0x01, 0xF0, 0x01, 0x03, 0x30, 0x33, 0x02, 0xF8, 0x01, 0x3D, ++0x49, 0x08, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, 0xF5, 0xD1, 0xBA, 0xE7, 0xDF, 0xF8, 0x90, 0xE0, 0x14, 0xAA, 0x01, 0xF0, ++0x0F, 0x03, 0x09, 0x09, 0x1E, 0xF8, 0x03, 0x30, 0x02, 0xF8, 0x01, 0x3D, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, 0xF4, 0xD1, ++0xAB, 0xE7, 0x00, 0x9B, 0x03, 0xF0, 0x40, 0x00, 0xCF, 0xE7, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0x11, 0x12, 0x00, 0xF0, ++0xAF, 0xFA, 0x4F, 0xF0, 0x02, 0x0A, 0xA2, 0xE4, 0x00, 0x22, 0x02, 0x92, 0x04, 0xAA, 0xBA, 0xE5, 0x00, 0x99, 0xC9, 0x06, ++0x06, 0xD4, 0x02, 0x98, 0xC1, 0x1A, 0x00, 0x98, 0x72, 0x46, 0x00, 0xF0, 0x40, 0x00, 0xA7, 0xE5, 0x83, 0x1C, 0x20, 0x20, ++0x0D, 0xE6, 0x00, 0x99, 0x01, 0xF0, 0x40, 0x00, 0x02, 0x99, 0x9F, 0xE5, 0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xBF, 0xF6, 0x86, 0xAC, 0x04, 0x49, 0x04, 0x48, 0x4F, 0xF4, 0x12, 0x72, 0x00, 0xF0, 0x89, 0xFA, 0x7E, 0xE4, ++0x24, 0xB3, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, ++0x10, 0xB3, 0x15, 0x00, 0xFC, 0xB2, 0x15, 0x00, 0x0F, 0xB4, 0x2D, 0xE9, 0xF0, 0x47, 0x21, 0x4E, 0xD6, 0xF8, 0x04, 0x31, ++0x82, 0xB0, 0xFB, 0xB1, 0x0A, 0x9C, 0xDF, 0xF8, 0x80, 0x80, 0xDF, 0xF8, 0x80, 0xA0, 0xDF, 0xF8, 0x80, 0x90, 0xA7, 0x1C, ++0x20, 0x46, 0x14, 0xF8, 0x01, 0x5B, 0x29, 0x06, 0xA5, 0xF1, 0x80, 0x02, 0x0A, 0xD5, 0x88, 0x2D, 0x13, 0xD8, 0xD6, 0xF8, ++0x00, 0x31, 0xDB, 0x43, 0xD3, 0x40, 0xDB, 0x07, 0x08, 0xD4, 0xA7, 0x42, 0x20, 0x46, 0xED, 0xD1, 0x12, 0x4B, 0x0B, 0xA9, ++0xD3, 0xF8, 0x30, 0x34, 0x01, 0x91, 0x98, 0x47, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x04, 0xB0, 0x70, 0x47, 0xD8, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x20, 0x05, 0xF1, 0x66, 0x03, 0x00, 0x2A, 0xDB, 0xB2, 0x05, 0xDB, 0xD6, 0xF8, 0x04, 0x31, ++0x9A, 0x3D, 0xAB, 0x42, 0xE3, 0xD8, 0xEB, 0xE7, 0x05, 0x2B, 0xF7, 0xD9, 0x40, 0xF2, 0xA9, 0x22, 0x51, 0x46, 0x48, 0x46, ++0x00, 0xF0, 0x36, 0xFA, 0xF0, 0xE7, 0x00, 0xBF, 0xB0, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xCC, 0xB2, 0x15, 0x00, 0x0E, 0xB4, 0x09, 0x4B, 0x00, 0xB5, 0x1B, 0x68, 0x1B, 0x88, 0x18, 0x42, ++0x82, 0xB0, 0x06, 0xD0, 0x06, 0x4B, 0x03, 0x98, 0xD3, 0xF8, 0x30, 0x34, 0x04, 0xA9, 0x01, 0x91, 0x98, 0x47, 0x02, 0xB0, ++0x5D, 0xF8, 0x04, 0xEB, 0x03, 0xB0, 0x70, 0x47, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x05, 0x48, ++0xFF, 0xF7, 0x94, 0xFF, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0xFE, 0xF7, 0x35, 0xF8, 0xE0, 0xF7, 0x0F, 0xFC, 0xFE, 0xE7, ++0x64, 0xB3, 0x15, 0x00, 0x08, 0xB5, 0x05, 0x48, 0xFF, 0xF7, 0x86, 0xFF, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0xFE, 0xF7, ++0x27, 0xF8, 0xE0, 0xF7, 0x01, 0xFC, 0xFE, 0xE7, 0x7C, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x17, 0x48, 0x00, 0x68, 0x00, 0x78, ++0x02, 0x28, 0x83, 0xB0, 0x1D, 0x46, 0x06, 0xD1, 0x48, 0x78, 0x83, 0x1E, 0x01, 0x2B, 0x0C, 0x46, 0x0E, 0xD9, 0x05, 0x28, ++0x0C, 0xD0, 0x11, 0x48, 0x01, 0x92, 0xFF, 0xF7, 0x69, 0xFF, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, 0x1C, 0x40, 0xFE, 0xF7, ++0x63, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x23, 0x78, 0x53, 0xB9, 0xA3, 0x78, 0x01, 0x92, 0x1B, 0xB1, 0xE1, 0xF7, ++0x17, 0xFE, 0x01, 0x9A, 0xEE, 0xE7, 0xE1, 0xF7, 0x1D, 0xFE, 0x01, 0x9A, 0xEA, 0xE7, 0x01, 0x21, 0x01, 0x92, 0xE1, 0xF7, ++0xE1, 0xFD, 0x60, 0x78, 0x01, 0x9A, 0xED, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x88, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x83, 0xB0, ++0x0C, 0x46, 0x09, 0x48, 0x09, 0x68, 0x01, 0x92, 0x1D, 0x46, 0xFF, 0xF7, 0x3F, 0xFF, 0x07, 0x4B, 0x21, 0x68, 0xC3, 0xF8, ++0x04, 0x11, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, 0x07, 0x40, 0xFE, 0xF7, 0x35, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, ++0xA0, 0xB3, 0x15, 0x00, 0xB0, 0xB6, 0x17, 0x00, 0x30, 0xB5, 0x83, 0xB0, 0x0C, 0x46, 0x09, 0x48, 0x09, 0x68, 0x01, 0x92, ++0x1D, 0x46, 0xFF, 0xF7, 0x25, 0xFF, 0x07, 0x4B, 0x21, 0x68, 0xC3, 0xF8, 0x00, 0x11, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, ++0x05, 0x40, 0xFE, 0xF7, 0x1B, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0xC8, 0xB3, 0x15, 0x00, 0xB0, 0xB6, 0x17, 0x00, ++0x18, 0x46, 0x38, 0xB5, 0x0D, 0x46, 0x04, 0x23, 0x01, 0x46, 0x4F, 0xF4, 0x82, 0x60, 0xFE, 0xF7, 0xA3, 0xF8, 0x22, 0x4B, ++0xA9, 0x88, 0x93, 0xF8, 0xA9, 0x30, 0x04, 0x46, 0xEB, 0xB1, 0x4B, 0x1E, 0x01, 0x2B, 0x0D, 0xD9, 0x02, 0x29, 0x2A, 0xD0, ++0x03, 0x29, 0x2F, 0xD0, 0x04, 0x29, 0x1C, 0xD1, 0x1B, 0x4B, 0x2A, 0x68, 0xDA, 0x65, 0x4F, 0xF0, 0x80, 0x72, 0xC3, 0xF8, ++0x34, 0x21, 0x14, 0xE0, 0x18, 0x48, 0x17, 0x4A, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x53, 0x6F, 0x16, 0x48, ++0x43, 0xF0, 0x10, 0x03, 0x53, 0x67, 0x01, 0x23, 0x03, 0x70, 0x01, 0x29, 0xE2, 0xD1, 0x10, 0x4B, 0x2A, 0x68, 0xDA, 0x63, ++0x40, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0x00, 0x25, 0x0F, 0x48, 0x25, 0x60, 0xFF, 0xF7, 0xDA, 0xFE, 0x20, 0x46, 0xFE, 0xF7, ++0x9F, 0xF8, 0x28, 0x46, 0x38, 0xBD, 0x08, 0x4B, 0x2A, 0x68, 0x9A, 0x65, 0x20, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0xEE, 0xE7, ++0x04, 0x4B, 0x2A, 0x68, 0x1A, 0x64, 0x80, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0xE7, 0xE7, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, ++0x00, 0x00, 0x50, 0x40, 0xE0, 0x50, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, 0xF0, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x18, 0x46, ++0x0C, 0x46, 0x08, 0x23, 0x01, 0x46, 0x85, 0xB0, 0x40, 0xF2, 0x12, 0x40, 0xFE, 0xF7, 0x4A, 0xF8, 0x18, 0x4B, 0x22, 0x68, ++0x1B, 0x68, 0x1B, 0x78, 0x01, 0x3B, 0x01, 0x2B, 0x05, 0x46, 0x19, 0xD9, 0x11, 0x68, 0xA3, 0x68, 0x60, 0x68, 0x4B, 0x40, ++0x03, 0x40, 0x4B, 0x40, 0x13, 0x60, 0x22, 0x68, 0x2A, 0x60, 0x11, 0x68, 0xA3, 0x68, 0x69, 0x60, 0xCD, 0xE9, 0x01, 0x11, ++0x00, 0x92, 0x61, 0x68, 0x0D, 0x48, 0x1A, 0x46, 0xFF, 0xF7, 0x96, 0xFE, 0x28, 0x46, 0xFE, 0xF7, 0x5B, 0xF8, 0x00, 0x20, ++0x05, 0xB0, 0x30, 0xBD, 0x09, 0x4B, 0x9A, 0x42, 0x07, 0xD1, 0xD4, 0xE9, 0x01, 0x03, 0x11, 0x68, 0x4B, 0x40, 0x03, 0x40, ++0x4B, 0x40, 0x13, 0x60, 0x22, 0x68, 0xA3, 0x68, 0xC5, 0xE9, 0x00, 0x23, 0x19, 0x46, 0xE1, 0xE7, 0x78, 0x36, 0x17, 0x00, ++0x04, 0xB4, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, 0x10, 0xB5, 0x19, 0x46, 0x40, 0xF2, 0x0A, 0x40, 0x0C, 0x23, 0xFE, 0xF7, ++0x0B, 0xF8, 0x00, 0x24, 0xC0, 0xE9, 0x00, 0x44, 0x84, 0x60, 0xFE, 0xF7, 0x35, 0xF8, 0x20, 0x46, 0x10, 0xBD, 0x00, 0xBF, ++0x30, 0xB5, 0x18, 0x46, 0x83, 0xB0, 0x08, 0x23, 0x0C, 0x46, 0x01, 0x46, 0x40, 0xF2, 0x03, 0x40, 0xFD, 0xF7, 0xF8, 0xFF, ++0x10, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x3B, 0x01, 0x2B, 0x05, 0x46, 0x13, 0xD9, 0xD4, 0xE9, 0x00, 0x32, 0x1A, 0x60, ++0x23, 0x68, 0x03, 0x60, 0x19, 0x68, 0x62, 0x68, 0x41, 0x60, 0xCD, 0xE9, 0x00, 0x11, 0x09, 0x48, 0x11, 0x46, 0xFF, 0xF7, ++0x4B, 0xFE, 0x28, 0x46, 0xFE, 0xF7, 0x10, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0xD4, 0xE9, 0x00, 0x32, 0xC0, 0xE9, ++0x00, 0x32, 0x11, 0x46, 0xED, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x58, 0xB4, 0x15, 0x00, 0x38, 0xB5, 0x0D, 0x46, ++0x40, 0xF2, 0x01, 0x40, 0x19, 0x46, 0x08, 0x23, 0xFD, 0xF7, 0xCA, 0xFF, 0x29, 0x68, 0x0B, 0x68, 0x04, 0x46, 0xC4, 0xE9, ++0x00, 0x13, 0x1A, 0x46, 0x03, 0x48, 0xFF, 0xF7, 0x29, 0xFE, 0x20, 0x46, 0xFD, 0xF7, 0xEE, 0xFF, 0x00, 0x20, 0x38, 0xBD, ++0x98, 0xB4, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x46, 0x40, 0xF2, 0x0E, 0x40, 0x19, 0x46, 0x04, 0x23, 0xFD, 0xF7, 0xB2, 0xFF, ++0x61, 0x68, 0x02, 0x29, 0x05, 0x46, 0x20, 0xD9, 0x03, 0x29, 0x11, 0xD0, 0x13, 0x48, 0xFF, 0xF7, 0x11, 0xFE, 0x4F, 0xF4, ++0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0xC0, 0xB2, 0x28, 0x60, 0x0F, 0x48, 0xFF, 0xF7, 0x07, 0xFE, 0x28, 0x46, ++0xFD, 0xF7, 0xCC, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x24, 0x68, 0x0C, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0xFD, 0xFD, 0x5C, 0xB1, ++0xA2, 0x02, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0xFD, 0xF7, 0xEC, 0xFD, 0xE3, 0xE7, 0x22, 0x68, 0x06, 0x48, 0xFF, 0xF7, ++0xF1, 0xFD, 0xDE, 0xE7, 0xE0, 0xF7, 0x70, 0xFA, 0xFE, 0xE7, 0x00, 0xBF, 0xF4, 0xB4, 0x15, 0x00, 0x08, 0xB5, 0x15, 0x00, ++0xE8, 0xB4, 0x15, 0x00, 0xC8, 0xB4, 0x15, 0x00, 0x30, 0xB5, 0x40, 0xF2, 0x0C, 0x40, 0x83, 0xB0, 0x0C, 0x46, 0x19, 0x46, ++0x04, 0x23, 0xFD, 0xF7, 0x73, 0xFF, 0x05, 0x46, 0x20, 0x68, 0x00, 0x23, 0x82, 0x07, 0x62, 0x68, 0x2B, 0x60, 0x1C, 0xBF, ++0xFF, 0x23, 0x2B, 0x60, 0x93, 0x07, 0x1C, 0xBF, 0x01, 0x23, 0x2B, 0x60, 0x04, 0xF1, 0x08, 0x01, 0x12, 0xF0, 0xEA, 0xFA, ++0xD4, 0xE9, 0x00, 0x12, 0x28, 0x68, 0xA3, 0x68, 0x00, 0x90, 0x0A, 0x44, 0x04, 0x48, 0xFF, 0xF7, 0xC1, 0xFD, 0x28, 0x46, ++0xFD, 0xF7, 0x86, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x1C, 0xB5, 0x15, 0x00, 0x70, 0xB5, 0x06, 0x46, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x11, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x10, 0x4C, 0x11, 0x48, ++0x25, 0x68, 0x22, 0xF0, 0x7F, 0x43, 0x01, 0x35, 0x0A, 0x46, 0x31, 0x46, 0x25, 0x60, 0xFF, 0xF7, 0xA3, 0xFD, 0x0D, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x05, 0xDB, 0xFC, 0xF7, 0x41, 0xFF, 0x4F, 0xF0, 0x00, 0x40, 0xFE, 0xF7, 0x1D, 0xFB, 0x23, 0x68, ++0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x70, 0xBD, 0x00, 0xBF, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x78, 0xB5, 0x15, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0xB5, 0x04, 0x46, ++0x72, 0xB6, 0x07, 0x4D, 0x07, 0x48, 0x00, 0x26, 0x22, 0xF0, 0x7F, 0x43, 0x2E, 0x60, 0x0A, 0x46, 0x21, 0x46, 0xFF, 0xF7, ++0x79, 0xFD, 0x04, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xFD, 0xD1, 0x70, 0xBD, 0x38, 0x00, 0x32, 0x40, 0x78, 0xB5, 0x15, 0x00, ++0xD0, 0x22, 0x17, 0x00, 0x10, 0xB4, 0x0C, 0x46, 0x22, 0xF0, 0x7F, 0x43, 0x01, 0x46, 0x22, 0x46, 0x02, 0x48, 0x5D, 0xF8, ++0x04, 0x4B, 0xFF, 0xF7, 0x63, 0xBD, 0x00, 0xBF, 0x90, 0xB5, 0x15, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x07, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x06, 0x4B, 0x1A, 0x68, 0x51, 0x1C, 0x19, 0x60, 0x29, 0xB1, 0x03, 0x49, ++0x1A, 0x60, 0x0B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x10, 0xB5, 0x06, 0x4C, 0x4F, 0xF4, 0x84, 0x72, 0x20, 0x46, 0x00, 0x21, 0xDB, 0xF7, 0xD2, 0xFA, 0x4F, 0xF0, 0xFF, 0x32, ++0x02, 0x23, 0xC4, 0xE9, 0x40, 0x23, 0x10, 0xBD, 0xB0, 0xB6, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x22, 0x00, 0x21, 0x02, 0x48, ++0xDB, 0xF7, 0xC4, 0xFA, 0x00, 0x20, 0x08, 0xBD, 0xB8, 0xB7, 0x17, 0x00, 0xE0, 0xF7, 0xB4, 0xBC, 0x01, 0x4B, 0xD3, 0xF8, ++0x24, 0x31, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x02, 0x20, 0x70, 0x47, 0xE0, 0xF7, 0xCC, 0xBB, 0x04, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x03, 0x2B, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0xE0, 0xF7, 0x5F, 0xBB, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, ++0xE0, 0xF7, 0x6E, 0xBB, 0x70, 0xB5, 0x04, 0x68, 0x9C, 0xB1, 0x0A, 0x4E, 0x05, 0x46, 0x03, 0xE0, 0xFE, 0xF7, 0x32, 0xFB, ++0x2C, 0x68, 0x64, 0xB1, 0x28, 0x46, 0xFE, 0xF7, 0x71, 0xFB, 0xE3, 0x68, 0x21, 0x46, 0x30, 0x46, 0x00, 0x2B, 0xF3, 0xD1, ++0xA2, 0x68, 0x2C, 0x68, 0x13, 0x81, 0x00, 0x2C, 0xF2, 0xD1, 0x70, 0xBD, 0x24, 0x65, 0x17, 0x00, 0x38, 0xB5, 0x14, 0x4B, ++0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xD0, 0x38, 0xBD, 0x04, 0x46, 0xE0, 0xF7, 0x80, 0xFB, 0x05, 0x46, 0xB8, 0xB1, ++0x4C, 0xF2, 0xDE, 0x03, 0xA3, 0x61, 0x21, 0x46, 0x1C, 0x22, 0x12, 0xF0, 0x07, 0xFA, 0x0C, 0x4C, 0x23, 0x68, 0x00, 0x2B, ++0xFC, 0xD0, 0x0B, 0x4B, 0x18, 0x68, 0x29, 0x1F, 0x00, 0xF5, 0x07, 0x70, 0xFE, 0xF7, 0x02, 0xFB, 0x01, 0x23, 0x23, 0x60, ++0xBD, 0xE8, 0x38, 0x40, 0xE0, 0xF7, 0x90, 0xBB, 0xBD, 0xE8, 0x38, 0x40, 0x04, 0x48, 0xFF, 0xF7, 0xD1, 0xBC, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x58, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0xA8, 0xB5, 0x15, 0x00, 0x01, 0x4B, 0xD3, 0xF8, ++0x28, 0x31, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x04, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0F, 0x4D, 0x10, 0x48, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0xFE, 0xF7, ++0xD7, 0xFA, 0x05, 0x2C, 0x03, 0xD8, 0x0D, 0x4A, 0x13, 0x5D, 0x01, 0x3B, 0x13, 0x55, 0x2B, 0x68, 0x33, 0xB1, 0x07, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x07, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, 0x01, 0x3B, ++0xC2, 0xF8, 0xF8, 0x31, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, ++0x74, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x4C, 0xDF, 0xF8, 0x3C, 0x80, 0x0C, 0x4F, ++0x0C, 0x4E, 0x04, 0xF5, 0x7C, 0x75, 0x62, 0x69, 0x30, 0x46, 0x13, 0x46, 0x3A, 0xB1, 0x12, 0x78, 0x21, 0x69, 0x20, 0x2A, ++0x0C, 0xBF, 0x42, 0x46, 0x3A, 0x46, 0xE1, 0xF7, 0xB1, 0xFA, 0x10, 0x34, 0xAC, 0x42, 0xF0, 0xD1, 0x00, 0x20, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x24, 0x30, 0x17, 0x00, 0xC4, 0xB5, 0x15, 0x00, 0xC8, 0xB5, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xF8, 0xB5, 0x10, 0xF8, 0x01, 0x3C, 0x09, 0x2B, 0x00, 0xF1, 0xFF, 0x36, 0x30, 0xD1, 0x1C, 0x4C, 0x23, 0x68, 0x99, 0x42, ++0x0D, 0x46, 0x08, 0xDA, 0x1A, 0x4F, 0x38, 0x46, 0x00, 0xF0, 0x64, 0xFD, 0x23, 0x68, 0x01, 0x3B, 0xAB, 0x42, 0x23, 0x60, ++0xF7, 0xDC, 0x17, 0x4D, 0xAE, 0x42, 0x19, 0xD9, 0x16, 0x4F, 0x06, 0xE0, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x00, 0xF0, ++0x53, 0xFD, 0xAE, 0x42, 0x10, 0xD0, 0x15, 0xF8, 0x01, 0x0B, 0x09, 0x28, 0xF4, 0xD1, 0x20, 0x68, 0x00, 0xF0, 0x07, 0x00, ++0x38, 0x44, 0x00, 0xF0, 0x49, 0xFD, 0x23, 0x68, 0x23, 0xF0, 0x07, 0x03, 0x08, 0x33, 0xAE, 0x42, 0x23, 0x60, 0xEE, 0xD1, ++0x0A, 0x4A, 0x13, 0x68, 0x01, 0x3B, 0x30, 0x46, 0x13, 0x60, 0xF8, 0xBD, 0x04, 0x48, 0x00, 0xF0, 0x39, 0xFD, 0x02, 0x4A, ++0x13, 0x68, 0x01, 0x3B, 0x13, 0x60, 0xF1, 0xE7, 0x24, 0x34, 0x17, 0x00, 0x1C, 0xB8, 0x15, 0x00, 0x28, 0x34, 0x17, 0x00, ++0x20, 0xB8, 0x15, 0x00, 0x68, 0x34, 0x17, 0x00, 0x61, 0xB3, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0x64, 0x90, 0x16, 0x4F, ++0xDF, 0xF8, 0x58, 0x80, 0x0E, 0x46, 0x45, 0x1E, 0x00, 0x24, 0x08, 0xE0, 0x15, 0xF8, 0x01, 0x1F, 0x38, 0x46, 0xFF, 0xF7, ++0x11, 0xFC, 0x23, 0x07, 0x10, 0xD0, 0xB4, 0x42, 0x13, 0xD0, 0x14, 0xF0, 0x07, 0x0F, 0x04, 0xF1, 0x01, 0x04, 0xF1, 0xD1, ++0x48, 0x46, 0xFF, 0xF7, 0x05, 0xFC, 0x15, 0xF8, 0x01, 0x1F, 0x38, 0x46, 0xFF, 0xF7, 0x00, 0xFC, 0x23, 0x07, 0xEE, 0xD1, ++0x40, 0x46, 0xFF, 0xF7, 0xFB, 0xFB, 0xB4, 0x42, 0xEB, 0xD1, 0xBD, 0xE8, 0xF8, 0x43, 0x04, 0x48, 0xFF, 0xF7, 0xF4, 0xBB, ++0x02, 0x48, 0xFF, 0xF7, 0xF1, 0xBB, 0x00, 0xBF, 0xD8, 0xB5, 0x15, 0x00, 0xB4, 0x79, 0x15, 0x00, 0xD4, 0xB5, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x87, 0xB0, 0x04, 0x93, 0x00, 0x29, 0x7E, 0xD0, 0x04, 0x2A, 0x14, 0x46, 0x02, 0xD0, 0x53, 0x1E, ++0x01, 0x2B, 0x78, 0xD8, 0x65, 0x42, 0x04, 0xFB, 0x01, 0xF3, 0xDF, 0xF8, 0x8C, 0x91, 0x03, 0x93, 0x05, 0x40, 0x5C, 0x48, ++0x29, 0x46, 0xE1, 0xF7, 0x09, 0xFA, 0x03, 0x9A, 0x2B, 0x0E, 0x10, 0x2A, 0x17, 0x46, 0x28, 0xBF, 0x10, 0x27, 0x01, 0x2B, ++0x68, 0xD0, 0x2B, 0x0D, 0xB3, 0xF5, 0xA0, 0x6F, 0x64, 0xD0, 0x00, 0x2A, 0x00, 0xF0, 0x9C, 0x80, 0xDF, 0xF8, 0x60, 0x81, ++0xDF, 0xF8, 0x60, 0xA1, 0x2E, 0x46, 0x4F, 0xF0, 0x00, 0x0B, 0x0A, 0xE0, 0x02, 0x2C, 0x0A, 0xBF, 0x31, 0x88, 0x31, 0x78, ++0x50, 0x46, 0xA3, 0x44, 0xE1, 0xF7, 0xEA, 0xF9, 0x5F, 0x45, 0x26, 0x44, 0x0A, 0xD9, 0x04, 0x2C, 0x40, 0x46, 0xF1, 0xD1, ++0x31, 0x68, 0x48, 0x48, 0xA3, 0x44, 0xE1, 0xF7, 0xDF, 0xF9, 0x5F, 0x45, 0x26, 0x44, 0xF4, 0xD8, 0x04, 0x9B, 0xB3, 0xB3, ++0x03, 0x9B, 0x0F, 0x2B, 0x7D, 0xD8, 0x4F, 0xF0, 0x00, 0x08, 0xC7, 0xF1, 0x10, 0x03, 0x04, 0xF1, 0xFF, 0x3A, 0x05, 0x94, ++0xDF, 0xF8, 0x14, 0xB1, 0x44, 0x46, 0x98, 0x46, 0x04, 0xE0, 0x58, 0x46, 0x00, 0xF0, 0x9A, 0xFC, 0xA0, 0x45, 0x0C, 0xD0, ++0x1A, 0xEA, 0x04, 0x0F, 0x04, 0xF1, 0x01, 0x04, 0xF5, 0xD1, 0x20, 0x20, 0x00, 0xF0, 0x8E, 0xFC, 0x58, 0x46, 0x00, 0xF0, ++0x8D, 0xFC, 0xA0, 0x45, 0xF2, 0xD1, 0x34, 0x48, 0x05, 0x9C, 0x00, 0xF0, 0x87, 0xFC, 0x03, 0x9B, 0x00, 0x2B, 0x4D, 0xD0, ++0x4F, 0xF0, 0x00, 0x08, 0x15, 0xF8, 0x08, 0x00, 0xA0, 0xF1, 0x1F, 0x03, 0x5F, 0x2B, 0x88, 0xBF, 0x2E, 0x20, 0x08, 0xF1, ++0x01, 0x08, 0x00, 0xF0, 0x75, 0xFC, 0x47, 0x45, 0xF2, 0xD8, 0x35, 0x46, 0x29, 0x48, 0x00, 0xF0, 0x71, 0xFC, 0x03, 0x9B, ++0xDB, 0x1B, 0x03, 0x93, 0x8D, 0xD1, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x03, 0x9B, 0x8B, 0xB3, 0xDF, 0xF8, 0x84, 0xA0, ++0x4F, 0xF0, 0x00, 0x08, 0x09, 0xE0, 0xCD, 0xF8, 0x00, 0xC0, 0xE1, 0xF7, 0x8D, 0xF9, 0x08, 0xF1, 0x04, 0x08, 0x47, 0x45, ++0x05, 0xF1, 0x04, 0x05, 0x1A, 0xD9, 0x28, 0x46, 0xDD, 0xF7, 0xEE, 0xF9, 0x04, 0x2C, 0x06, 0x46, 0x4F, 0xEA, 0x10, 0x6C, ++0xC0, 0xF3, 0x07, 0x43, 0xC0, 0xF3, 0x07, 0x22, 0xC1, 0xB2, 0x48, 0x46, 0x0F, 0xD0, 0x02, 0x2C, 0xE5, 0xD1, 0x15, 0x48, ++0x32, 0x0C, 0xB1, 0xB2, 0x08, 0xF1, 0x04, 0x08, 0xE1, 0xF7, 0x70, 0xF9, 0x47, 0x45, 0x05, 0xF1, 0x04, 0x05, 0xE4, 0xD8, ++0x00, 0x23, 0x04, 0x93, 0xC6, 0xE7, 0x31, 0x46, 0x50, 0x46, 0xE1, 0xF7, 0x65, 0xF9, 0xD6, 0xE7, 0x0A, 0x48, 0x07, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0x00, 0xF0, 0x30, 0xBC, 0x04, 0x9B, 0x00, 0x2B, 0xB8, 0xD0, 0x2E, 0x46, 0x81, 0xE7, 0x04, 0x48, ++0x00, 0xF0, 0x28, 0xFC, 0xA2, 0xE7, 0x00, 0xBF, 0xE0, 0xB5, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0x1C, 0xB6, 0x15, 0x00, ++0xD0, 0x79, 0x15, 0x00, 0xE8, 0xB5, 0x15, 0x00, 0xF4, 0xB5, 0x15, 0x00, 0x14, 0xB6, 0x15, 0x00, 0x0C, 0xB6, 0x15, 0x00, ++0xD4, 0xB5, 0x15, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x22, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x22, 0x4C, 0x22, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0xFE, 0xF7, 0x1E, 0xF9, 0x20, 0x48, 0xFE, 0xF7, ++0x1B, 0xF9, 0x20, 0x49, 0x1D, 0x48, 0xFE, 0xF7, 0x1B, 0xF9, 0x1F, 0x49, 0x1B, 0x48, 0xFE, 0xF7, 0x17, 0xF9, 0x1E, 0x49, ++0x19, 0x48, 0xFE, 0xF7, 0x13, 0xF9, 0x1D, 0x49, 0x17, 0x48, 0xFE, 0xF7, 0x0F, 0xF9, 0x23, 0x68, 0x33, 0xB1, 0x13, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x01, 0x22, ++0x00, 0xF0, 0xFC, 0xFB, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x04, 0x22, 0x00, 0xF0, 0xF6, 0xFB, 0x17, 0x4B, 0x18, 0x49, ++0x18, 0x48, 0x03, 0x22, 0x00, 0xF0, 0xF0, 0xFB, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x04, 0x22, 0x00, 0xF0, 0xEA, 0xFB, ++0xBD, 0xE8, 0x10, 0x40, 0x16, 0x4B, 0x17, 0x49, 0x17, 0x48, 0x02, 0x22, 0x00, 0xF0, 0xE2, 0xBB, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xD8, 0xB8, 0x17, 0x00, 0xC0, 0xB7, 0x17, 0x00, 0xC8, 0xB7, 0x17, 0x00, 0x0C, 0xB8, 0x17, 0x00, ++0x50, 0xB8, 0x17, 0x00, 0x94, 0xB8, 0x17, 0x00, 0x69, 0x4D, 0x14, 0x00, 0x24, 0xB6, 0x15, 0x00, 0x30, 0xB6, 0x15, 0x00, ++0x61, 0x56, 0x14, 0x00, 0x38, 0xB6, 0x15, 0x00, 0x7C, 0xAB, 0x15, 0x00, 0x2D, 0x57, 0x14, 0x00, 0x4C, 0xB6, 0x15, 0x00, ++0x58, 0xB6, 0x15, 0x00, 0xED, 0x55, 0x14, 0x00, 0x5C, 0xB6, 0x15, 0x00, 0x68, 0xB6, 0x15, 0x00, 0x99, 0x57, 0x14, 0x00, ++0x6C, 0xB6, 0x15, 0x00, 0x7C, 0xB6, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x54, 0x4D, 0x55, 0x4E, 0x29, 0x68, 0x31, 0x60, ++0x17, 0x28, 0x04, 0x46, 0x10, 0xD8, 0x17, 0x28, 0x00, 0xF2, 0x8E, 0x80, 0xDF, 0xE8, 0x00, 0xF0, 0x15, 0x8C, 0x8C, 0x71, ++0x8C, 0x8C, 0x8C, 0x8C, 0x48, 0x8C, 0x1A, 0x8C, 0x8C, 0x1A, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x55, 0x8C, 0x60, ++0x7F, 0x28, 0x39, 0xD0, 0x49, 0x4F, 0x3B, 0x68, 0x3D, 0x2B, 0x65, 0xDD, 0x07, 0x20, 0x00, 0xF0, 0x75, 0xFB, 0x4F, 0xF0, ++0xFF, 0x34, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x44, 0x4E, 0x45, 0x48, 0x33, 0x68, 0xDF, 0xF8, 0x20, 0x81, 0x00, 0x22, ++0x1A, 0x70, 0x00, 0xF0, 0x69, 0xFB, 0x34, 0x68, 0xA4, 0xEB, 0x08, 0x04, 0x00, 0x2C, 0xEE, 0xDB, 0x0F, 0xD1, 0x3F, 0x48, ++0x00, 0xF0, 0x60, 0xFB, 0x00, 0x24, 0x3D, 0x48, 0x12, 0xF0, 0x70, 0xF9, 0x38, 0x4B, 0x28, 0x60, 0x00, 0x22, 0xC6, 0xF8, ++0x00, 0x80, 0x1A, 0x60, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x48, 0xFE, 0xF7, 0xB2, 0xF8, 0x07, 0x46, 0x00, 0x28, ++0x48, 0xD0, 0x41, 0x46, 0x04, 0x30, 0x12, 0xF0, 0xED, 0xF8, 0x34, 0x48, 0x39, 0x46, 0xFE, 0xF7, 0x63, 0xF8, 0xE4, 0xE7, ++0x2C, 0x4B, 0x2D, 0x4E, 0x1B, 0x68, 0x30, 0x68, 0x0B, 0xB1, 0xFF, 0xF7, 0xC9, 0xFD, 0x4F, 0xF0, 0xFF, 0x34, 0x30, 0x60, ++0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x27, 0x4A, 0x25, 0x4B, 0x2B, 0x49, 0x11, 0x60, 0x4F, 0xF0, 0xFF, 0x34, 0x00, 0x22, ++0x1A, 0x60, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x4F, 0x21, 0x4E, 0x3B, 0x68, 0x30, 0x68, 0x0B, 0xB9, 0xAE, 0xE7, ++0x29, 0x68, 0xFF, 0xF7, 0xAF, 0xFD, 0x3B, 0x68, 0x30, 0x60, 0x00, 0x2B, 0xA7, 0xDD, 0x03, 0x78, 0x20, 0x2B, 0xF5, 0xD1, ++0xA3, 0xE7, 0xDF, 0xF8, 0x78, 0x80, 0x18, 0x4E, 0x00, 0x23, 0x88, 0xF8, 0x00, 0x30, 0xB0, 0xE7, 0x01, 0x31, 0x20, 0x46, ++0x31, 0x60, 0x00, 0xF0, 0x0D, 0xFB, 0x13, 0x49, 0x0B, 0x68, 0x1C, 0x70, 0x3A, 0x68, 0x01, 0x33, 0x01, 0x32, 0x0B, 0x60, ++0x3A, 0x60, 0x4F, 0xF0, 0xFF, 0x34, 0x8E, 0xE7, 0x13, 0x48, 0x00, 0xF0, 0x01, 0xFB, 0xA0, 0xE7, 0x0A, 0x4F, 0x3B, 0x68, ++0x3D, 0x2B, 0x81, 0xDC, 0x09, 0x28, 0xE5, 0xD1, 0x0F, 0x48, 0x01, 0xF0, 0x07, 0x01, 0x08, 0x44, 0x00, 0xF0, 0xF4, 0xFA, ++0x33, 0x68, 0x23, 0xF0, 0x07, 0x03, 0x08, 0x33, 0x33, 0x60, 0xDE, 0xE7, 0x6C, 0x34, 0x17, 0x00, 0x24, 0x34, 0x17, 0x00, ++0x68, 0x34, 0x17, 0x00, 0xD4, 0x22, 0x17, 0x00, 0xD0, 0x79, 0x15, 0x00, 0xA0, 0xB6, 0x15, 0x00, 0xD8, 0xB8, 0x17, 0x00, ++0xC0, 0xB7, 0x17, 0x00, 0x28, 0x34, 0x17, 0x00, 0x84, 0xB6, 0x15, 0x00, 0x20, 0xB8, 0x15, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, ++0x2C, 0x68, 0x3F, 0x2C, 0x0D, 0xD8, 0x0B, 0x4F, 0x4F, 0xEA, 0x04, 0x1C, 0x07, 0xEB, 0x04, 0x16, 0x01, 0x34, 0x47, 0xF8, ++0x0C, 0x00, 0xC6, 0xE9, 0x01, 0x12, 0xF3, 0x60, 0x2C, 0x60, 0x00, 0x20, 0xF8, 0xBD, 0x05, 0x48, 0xE0, 0xF7, 0xF0, 0xFF, ++0x4F, 0xF0, 0xFF, 0x30, 0xF8, 0xBD, 0x00, 0xBF, 0x20, 0x30, 0x17, 0x00, 0x24, 0x30, 0x17, 0x00, 0xA8, 0xB6, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x95, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x76, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0xDF, 0xF8, 0xFC, 0xB1, 0x75, 0x48, 0xDB, 0xF8, 0x00, 0x30, 0x01, 0x33, 0xCB, 0xF8, 0x00, 0x30, 0xFE, 0xF7, ++0x05, 0xF8, 0xDB, 0xF8, 0x00, 0x30, 0x06, 0x46, 0x3B, 0xB1, 0x6E, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x00, 0x2E, 0x00, 0xF0, 0x94, 0x80, 0x33, 0x1D, 0x03, 0xAC, 0x01, 0x22, 0x4F, 0xF0, ++0x00, 0x0C, 0x57, 0x1E, 0x3D, 0x46, 0x19, 0x46, 0x13, 0xF8, 0x01, 0x0B, 0x20, 0x28, 0xFA, 0xD0, 0x09, 0x28, 0xF8, 0xD0, ++0x00, 0x28, 0x00, 0xF0, 0xA0, 0x80, 0x22, 0x28, 0x00, 0xF0, 0x83, 0x80, 0x21, 0x60, 0x08, 0x78, 0x15, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0xAC, 0x80, 0x0B, 0x46, 0x06, 0xE0, 0x09, 0x28, 0x06, 0xD0, 0x13, 0xF8, 0x01, 0x0F, 0x00, 0x28, 0x00, 0xF0, ++0xA3, 0x80, 0x20, 0x28, 0xF6, 0xD1, 0x19, 0x78, 0x00, 0x29, 0x00, 0xF0, 0x9D, 0x80, 0x01, 0x32, 0x11, 0x2A, 0x03, 0xF8, ++0x01, 0xCB, 0x04, 0xF1, 0x04, 0x04, 0xD4, 0xD1, 0x52, 0x48, 0x10, 0x21, 0xE0, 0xF7, 0x8E, 0xFF, 0x10, 0x25, 0xDD, 0xF8, ++0x0C, 0x90, 0x2E, 0x21, 0x48, 0x46, 0x11, 0xF0, 0x95, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x83, 0x80, 0xA0, 0xEB, 0x09, 0x04, ++0x4B, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x28, 0xDD, 0x4A, 0x4F, 0x01, 0x95, 0x4F, 0xF0, 0x00, 0x08, 0xC2, 0x46, 0x3D, 0x46, ++0x05, 0xE0, 0x46, 0x4B, 0x1A, 0x68, 0x92, 0x45, 0x07, 0xF1, 0x10, 0x07, 0x16, 0xDA, 0x39, 0x68, 0x22, 0x46, 0x48, 0x46, ++0x0A, 0xF1, 0x01, 0x0A, 0x12, 0xF0, 0xBE, 0xF8, 0x00, 0x28, 0xF0, 0xD1, 0x38, 0x68, 0x12, 0xF0, 0x4B, 0xF8, 0x84, 0x42, ++0x43, 0xD0, 0x3C, 0x4B, 0x1A, 0x68, 0x92, 0x45, 0x3D, 0x46, 0x08, 0xF1, 0x01, 0x08, 0x07, 0xF1, 0x10, 0x07, 0xE8, 0xDB, ++0xB8, 0xF1, 0x01, 0x0F, 0x2B, 0x46, 0x01, 0x9D, 0x37, 0xD0, 0x03, 0x99, 0x36, 0x48, 0xE0, 0xF7, 0x51, 0xFF, 0x36, 0x48, ++0x00, 0xF0, 0x20, 0xFA, 0x35, 0x48, 0x00, 0xF0, 0x1D, 0xFA, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x2A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDB, 0xF8, 0x00, 0x30, 0x30, 0x48, 0x01, 0x33, 0x31, 0x46, 0xCB, 0xF8, 0x00, 0x30, ++0xFD, 0xF7, 0x2A, 0xFF, 0x25, 0x48, 0xFD, 0xF7, 0x6B, 0xFF, 0xDB, 0xF8, 0x00, 0x30, 0x06, 0x46, 0x00, 0x2B, 0x7F, 0xF4, ++0x64, 0xAF, 0x00, 0x2E, 0x7F, 0xF4, 0x6C, 0xAF, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0x1C, 0x23, 0x60, 0x49, 0x78, ++0x15, 0x46, 0x19, 0xB9, 0x28, 0xE0, 0x13, 0xF8, 0x01, 0x1F, 0x29, 0xB3, 0x22, 0x29, 0xFA, 0xD1, 0x81, 0xE7, 0x01, 0x9D, ++0x3B, 0x46, 0x9A, 0x68, 0xAA, 0x42, 0x24, 0xDB, 0xDB, 0x68, 0x00, 0x2B, 0xC8, 0xD0, 0x28, 0x46, 0x03, 0xA9, 0x98, 0x47, ++0x00, 0x28, 0xC3, 0xD0, 0xBF, 0xE7, 0x14, 0xAB, 0x03, 0xEB, 0x87, 0x03, 0x43, 0xF8, 0x44, 0x0C, 0x00, 0x2F, 0xB8, 0xD0, ++0xDD, 0xF8, 0x0C, 0x90, 0x2E, 0x21, 0x48, 0x46, 0x11, 0xF0, 0x12, 0xFF, 0x00, 0x28, 0x7F, 0xF4, 0x7D, 0xAF, 0x48, 0x46, ++0x11, 0xF0, 0xE4, 0xFF, 0x04, 0x46, 0x79, 0xE7, 0x14, 0xAB, 0x03, 0xEB, 0x82, 0x02, 0x00, 0x23, 0x42, 0xF8, 0x44, 0x3C, ++0x67, 0xE7, 0x59, 0x68, 0x0A, 0x48, 0xE0, 0xF7, 0xF1, 0xFE, 0x9E, 0xE7, 0x38, 0x61, 0x17, 0x00, 0xC0, 0xB7, 0x17, 0x00, ++0xC4, 0xB6, 0x15, 0x00, 0x20, 0x30, 0x17, 0x00, 0x24, 0x30, 0x17, 0x00, 0xE4, 0xB6, 0x15, 0x00, 0x08, 0xB7, 0x15, 0x00, ++0xA0, 0xB6, 0x15, 0x00, 0xD8, 0xB8, 0x17, 0x00, 0xFC, 0xB6, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF0, 0xB4, 0x05, 0x78, ++0x30, 0x2D, 0x2B, 0xD0, 0x00, 0x2A, 0x08, 0xBF, 0x0A, 0x22, 0x2D, 0x2D, 0x32, 0xD0, 0x00, 0x27, 0x00, 0x26, 0xA5, 0xF1, ++0x30, 0x03, 0x5F, 0xFA, 0x83, 0xFC, 0x25, 0xF0, 0x20, 0x04, 0xBC, 0xF1, 0x09, 0x0F, 0xA4, 0xF1, 0x41, 0x04, 0x12, 0xD9, ++0x05, 0x2C, 0x06, 0xD9, 0x07, 0xB1, 0x76, 0x42, 0x01, 0xB1, 0x08, 0x60, 0x30, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0xA5, 0xF1, ++0x61, 0x04, 0xA5, 0xF1, 0x20, 0x03, 0x19, 0x2C, 0xDB, 0xB2, 0x94, 0xBF, 0x37, 0x3B, 0xA5, 0xF1, 0x37, 0x03, 0x93, 0x42, ++0xEC, 0xD2, 0x10, 0xF8, 0x01, 0x5F, 0x02, 0xFB, 0x06, 0x36, 0xDA, 0xE7, 0x45, 0x78, 0x78, 0x2D, 0x00, 0xF1, 0x01, 0x03, ++0x0A, 0xD0, 0x18, 0x46, 0x00, 0x2A, 0xCE, 0xD1, 0x2D, 0x2D, 0x4F, 0xF0, 0x08, 0x02, 0xCC, 0xD1, 0x01, 0x27, 0x45, 0x78, ++0x38, 0x44, 0xC9, 0xE7, 0x84, 0x78, 0xA4, 0xF1, 0x30, 0x06, 0x09, 0x2E, 0x09, 0xD9, 0x24, 0xF0, 0x20, 0x06, 0x41, 0x3E, ++0x05, 0x2E, 0x04, 0xD9, 0x3A, 0xB9, 0x17, 0x46, 0x18, 0x46, 0x08, 0x22, 0xBA, 0xE7, 0x02, 0x30, 0x25, 0x46, 0x10, 0x22, ++0xB3, 0xE7, 0x18, 0x46, 0xB3, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x0A, 0x22, 0x0C, 0x46, 0x05, 0x46, 0x48, 0x68, 0x00, 0x21, ++0xFF, 0xF7, 0xA2, 0xFF, 0xC0, 0xB1, 0x01, 0x28, 0x10, 0xD1, 0x02, 0x2D, 0x1C, 0xDD, 0x10, 0x22, 0xA0, 0x68, 0x00, 0x21, ++0xFF, 0xF7, 0x98, 0xFF, 0x0E, 0x4B, 0x1B, 0x68, 0x01, 0x46, 0x19, 0x80, 0x0D, 0x48, 0x89, 0xB2, 0xFF, 0xF7, 0x34, 0xF8, ++0x00, 0x20, 0x38, 0xBD, 0x01, 0x46, 0x0B, 0x48, 0xFF, 0xF7, 0x2E, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x4B, 0x09, 0x48, ++0x1B, 0x68, 0x19, 0x88, 0xFF, 0xF7, 0x26, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x48, 0xFF, 0xF7, 0x21, 0xF8, 0x00, 0x20, ++0x38, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x2C, 0xB7, 0x15, 0x00, 0x50, 0xB7, 0x15, 0x00, 0x18, 0xB7, 0x15, 0x00, ++0x40, 0xB7, 0x15, 0x00, 0x01, 0x28, 0xF8, 0xB5, 0x2A, 0xDD, 0x0D, 0x46, 0x04, 0x46, 0x10, 0x22, 0x68, 0x68, 0x00, 0x21, ++0xFF, 0xF7, 0x66, 0xFF, 0x02, 0x2C, 0x06, 0x46, 0x0D, 0xD1, 0x03, 0x0E, 0x01, 0x2B, 0x22, 0xD0, 0x03, 0x0D, 0xB3, 0xF5, ++0xA0, 0x6F, 0x1E, 0xD0, 0x32, 0x68, 0x24, 0x48, 0x31, 0x46, 0xFE, 0xF7, 0xFB, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0x22, ++0xA8, 0x68, 0x11, 0x46, 0x00, 0xF0, 0x18, 0xF9, 0x03, 0x2C, 0x07, 0x46, 0x19, 0xD1, 0x04, 0x20, 0x01, 0x2F, 0x1C, 0xD0, ++0xC2, 0xB2, 0x39, 0x46, 0x30, 0x46, 0x00, 0x23, 0xFF, 0xF7, 0xFE, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x18, 0x48, 0xFE, 0xF7, ++0xE3, 0xFF, 0x01, 0x20, 0xF8, 0xBD, 0x30, 0x46, 0xDC, 0xF7, 0x7E, 0xFE, 0x31, 0x46, 0x02, 0x46, 0x12, 0x48, 0xFE, 0xF7, ++0xD9, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0x22, 0xE8, 0x68, 0x11, 0x46, 0xFF, 0xF7, 0x2E, 0xFF, 0xE0, 0xE7, 0x33, 0x0E, ++0x01, 0x2B, 0xEC, 0xD0, 0x33, 0x0D, 0xB3, 0xF5, 0xA0, 0x6F, 0xE8, 0xD0, 0x01, 0x28, 0x06, 0xD1, 0x32, 0x78, 0x0A, 0x48, ++0x31, 0x46, 0xFE, 0xF7, 0xC3, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x02, 0x28, 0xBE, 0xD1, 0x32, 0x88, 0x06, 0x48, 0x92, 0xB2, ++0x31, 0x46, 0xFE, 0xF7, 0xB9, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x7C, 0xB7, 0x15, 0x00, 0x64, 0xB7, 0x15, 0x00, ++0x90, 0xB7, 0x15, 0x00, 0xA4, 0xB7, 0x15, 0x00, 0x02, 0x28, 0x38, 0xB5, 0x21, 0xDD, 0x0D, 0x46, 0x10, 0x22, 0x68, 0x68, ++0x00, 0x21, 0xFF, 0xF7, 0x01, 0xFF, 0x10, 0x22, 0x04, 0x46, 0x00, 0x21, 0xA8, 0x68, 0xFF, 0xF7, 0xFB, 0xFE, 0x21, 0x46, ++0x02, 0x46, 0x05, 0x46, 0x0F, 0x48, 0xFE, 0xF7, 0x99, 0xFF, 0x23, 0x0E, 0x01, 0x2B, 0x06, 0xD0, 0x23, 0x0D, 0xB3, 0xF5, ++0xA0, 0x6F, 0x0D, 0xD0, 0x25, 0x60, 0x00, 0x20, 0x38, 0xBD, 0x20, 0x46, 0x29, 0x46, 0xDC, 0xF7, 0x53, 0xFE, 0x00, 0x20, ++0x38, 0xBD, 0x07, 0x48, 0xFE, 0xF7, 0x86, 0xFF, 0x01, 0x20, 0x38, 0xBD, 0xB4, 0xF1, 0xA0, 0x4F, 0xF1, 0xD1, 0x28, 0x46, ++0xDC, 0xF7, 0xF6, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x7C, 0xB7, 0x15, 0x00, 0xB8, 0xB7, 0x15, 0x00, 0x02, 0x28, 0x38, 0xB5, ++0x46, 0xDC, 0x01, 0x28, 0x32, 0xD0, 0x00, 0x22, 0x48, 0x68, 0x11, 0x46, 0xFF, 0xF7, 0xCA, 0xFE, 0x25, 0x4A, 0x26, 0x4B, ++0x02, 0xFB, 0x00, 0xF2, 0x9A, 0x42, 0x04, 0x46, 0x3E, 0xD8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x21, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x21, 0x4D, 0x21, 0x49, 0x2B, 0x68, 0x0A, 0x60, 0x01, 0x33, 0x2B, 0x60, 0x82, 0xB1, ++0x1F, 0x49, 0x09, 0x78, 0xF9, 0xB9, 0x33, 0xB1, 0x1A, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x1B, 0x48, 0x21, 0x46, 0xFE, 0xF7, 0x49, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, ++0xFC, 0xF7, 0xE8, 0xFF, 0x2B, 0x68, 0xEA, 0xE7, 0x12, 0x4A, 0x15, 0x4B, 0x11, 0x68, 0x15, 0x48, 0xA3, 0xFB, 0x01, 0x31, ++0x89, 0x0C, 0xFE, 0xF7, 0x37, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0xFC, 0xF7, 0x26, 0xFF, ++0x2B, 0x68, 0xD8, 0xE7, 0x0E, 0x48, 0xFE, 0xF7, 0x2B, 0xFF, 0x4F, 0xF0, 0xFF, 0x30, 0x38, 0xBD, 0x0C, 0x48, 0xFE, 0xF7, ++0x25, 0xFF, 0x4F, 0xF0, 0xFF, 0x30, 0x38, 0xBD, 0x40, 0x42, 0x0F, 0x00, 0xFF, 0xA2, 0xE1, 0x11, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x6C, 0x60, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0xF8, 0xB7, 0x15, 0x00, 0x83, 0xDE, 0x1B, 0x43, ++0xE8, 0xB7, 0x15, 0x00, 0xD0, 0xB7, 0x15, 0x00, 0x08, 0xB8, 0x15, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0x01, 0xE0, 0x04, 0x2A, ++0x05, 0xD0, 0x23, 0x68, 0x03, 0xF0, 0x0F, 0x02, 0xDB, 0x07, 0xF8, 0xD5, 0x10, 0xBD, 0xE0, 0xF7, 0x1D, 0xFC, 0xFF, 0xF7, ++0x6B, 0xFC, 0xF4, 0xE7, 0x08, 0x10, 0x04, 0x40, 0xE0, 0xF7, 0x0A, 0xBC, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x78, 0x28, 0xB1, ++0xE0, 0xF7, 0x04, 0xFC, 0x14, 0xF8, 0x01, 0x0F, 0x00, 0x28, 0xF9, 0xD1, 0x10, 0xBD, 0x00, 0xBF, 0x10, 0xB5, 0x04, 0x4C, ++0xD4, 0xF8, 0xB8, 0x30, 0x98, 0x47, 0xD4, 0xF8, 0x28, 0x33, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0xFF, 0xF7, 0x2E, 0xBD, 0xFF, 0xF7, 0x0C, 0xBD, 0xFF, 0xF7, 0x36, 0xBE, 0x70, 0xB4, 0x02, 0x68, 0x1C, 0x4C, 0x2D, 0x21, ++0xA3, 0x89, 0x11, 0x70, 0x02, 0x68, 0x1A, 0x21, 0x51, 0x70, 0x23, 0xF0, 0x1C, 0x03, 0x02, 0x68, 0x9B, 0xB2, 0x43, 0xF0, ++0x0C, 0x03, 0x53, 0x80, 0xA3, 0x7B, 0x13, 0x71, 0x06, 0x68, 0x04, 0xF1, 0x0F, 0x03, 0x04, 0xF1, 0x1F, 0x05, 0x13, 0xF8, ++0x01, 0x1B, 0x1A, 0x1B, 0x32, 0x44, 0xAB, 0x42, 0x02, 0xF8, 0x0B, 0x1C, 0xF7, 0xD1, 0x01, 0x68, 0x0E, 0x4A, 0x00, 0x23, ++0xCB, 0x73, 0x01, 0x68, 0x0B, 0x74, 0x05, 0x68, 0x23, 0x8C, 0xA5, 0xF8, 0x15, 0x30, 0x05, 0xF1, 0x17, 0x03, 0x1B, 0x35, ++0x12, 0xF8, 0x01, 0x1B, 0x03, 0xF8, 0x01, 0x1B, 0xAB, 0x42, 0xF9, 0xD1, 0x03, 0x68, 0x94, 0xF8, 0x28, 0x20, 0xDA, 0x76, ++0x03, 0x68, 0x1C, 0x33, 0x03, 0x60, 0x70, 0xBC, 0x1C, 0x20, 0x70, 0x47, 0xE4, 0xB8, 0x17, 0x00, 0x08, 0xB9, 0x17, 0x00, ++0x03, 0x68, 0x28, 0x4A, 0xFF, 0x21, 0x70, 0xB4, 0x19, 0x70, 0x03, 0x68, 0x23, 0x21, 0x99, 0x70, 0x05, 0x68, 0xEB, 0x1C, ++0x05, 0xF1, 0x09, 0x04, 0x12, 0xF8, 0x01, 0x1F, 0x03, 0xF8, 0x01, 0x1B, 0xA3, 0x42, 0xF9, 0xD1, 0x20, 0x4A, 0xA2, 0xF1, ++0x41, 0x01, 0x02, 0xF1, 0x0B, 0x06, 0xA2, 0xF1, 0x38, 0x03, 0x12, 0xF8, 0x01, 0x4F, 0x5B, 0x1A, 0xB2, 0x42, 0x5C, 0x55, ++0xF7, 0xD1, 0x91, 0xF8, 0x42, 0x30, 0xB1, 0xF8, 0x50, 0x40, 0xB1, 0xF8, 0x4E, 0x20, 0xEC, 0x82, 0x1C, 0x07, 0xAA, 0x82, ++0x05, 0xF1, 0x18, 0x06, 0x4F, 0xEA, 0x63, 0x02, 0x07, 0xD5, 0xB1, 0xF8, 0x52, 0x40, 0xB1, 0xF8, 0x54, 0x30, 0x6B, 0x83, ++0x2C, 0x83, 0x05, 0xF1, 0x1C, 0x06, 0x13, 0x07, 0x04, 0xD5, 0xB1, 0xF8, 0x56, 0x30, 0x33, 0x80, 0x73, 0x80, 0x04, 0x36, ++0x0C, 0x4C, 0x32, 0x46, 0x14, 0xF8, 0x01, 0x5F, 0x15, 0x70, 0x91, 0xF8, 0x75, 0x51, 0x93, 0x1B, 0x9D, 0x42, 0x02, 0xF1, ++0x01, 0x02, 0xF5, 0xDA, 0x03, 0x68, 0xD2, 0x1A, 0x91, 0x1E, 0x59, 0x70, 0x03, 0x68, 0x13, 0x44, 0x03, 0x60, 0x70, 0xBC, ++0x10, 0x46, 0x70, 0x47, 0x1F, 0xB9, 0x17, 0x00, 0x25, 0xB9, 0x17, 0x00, 0x3D, 0xB9, 0x17, 0x00, 0x70, 0xB4, 0x0F, 0x4C, ++0x03, 0x46, 0x22, 0x6B, 0x09, 0xB1, 0x22, 0xF4, 0xC0, 0x52, 0x19, 0x68, 0xBF, 0x20, 0x08, 0x70, 0x19, 0x68, 0x0C, 0x20, ++0x48, 0x70, 0x18, 0x68, 0xA1, 0x8E, 0xC0, 0xF8, 0x02, 0x20, 0x1A, 0x68, 0x60, 0x8F, 0xE6, 0x8E, 0x25, 0x8F, 0xD1, 0x80, ++0x02, 0xF1, 0x0E, 0x01, 0x16, 0x81, 0x55, 0x81, 0x90, 0x81, 0x70, 0xBC, 0x0E, 0x20, 0x19, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0xE4, 0xB8, 0x17, 0x00, 0x03, 0x68, 0x10, 0xB4, 0xC7, 0x24, 0x1C, 0x70, 0x03, 0x68, 0x01, 0x24, 0x5C, 0x70, 0x03, 0x68, ++0x42, 0xEA, 0x01, 0x11, 0x99, 0x70, 0x03, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x03, 0x33, 0x03, 0x60, 0x03, 0x20, 0x70, 0x47, ++0x03, 0x68, 0x46, 0x22, 0x1A, 0x70, 0x03, 0x68, 0x05, 0x22, 0x5A, 0x70, 0x03, 0x68, 0x70, 0x22, 0x9A, 0x70, 0x02, 0x68, ++0x00, 0x23, 0xD3, 0x70, 0x02, 0x68, 0x13, 0x71, 0x02, 0x68, 0x53, 0x71, 0x02, 0x68, 0x93, 0x71, 0x03, 0x68, 0x07, 0x33, ++0x03, 0x60, 0x07, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x30, 0xB4, 0x02, 0x9C, 0x01, 0x80, 0x42, 0x80, 0x83, 0x80, 0x84, 0xB1, ++0x10, 0x22, 0x80, 0x23, 0x82, 0x71, 0xC3, 0x71, 0xE5, 0x18, 0x22, 0x46, 0x13, 0x46, 0x08, 0x33, 0x12, 0xF8, 0x01, 0x1B, ++0x1B, 0x1B, 0xAA, 0x42, 0x19, 0x54, 0xF7, 0xD1, 0x88, 0x20, 0x30, 0xBC, 0x70, 0x47, 0x06, 0x20, 0x30, 0xBC, 0x70, 0x47, ++0x01, 0x80, 0x02, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x8F, 0xB0, 0x1F, 0x46, 0x1A, 0x9E, 0x03, 0x93, ++0x34, 0x8F, 0xB6, 0xF8, 0x36, 0x80, 0x0D, 0x46, 0x03, 0x46, 0x01, 0x2C, 0x38, 0x46, 0x38, 0xBF, 0x01, 0x24, 0x07, 0x93, ++0x17, 0x46, 0x01, 0xF0, 0xC1, 0xFE, 0xB5, 0xF8, 0xAE, 0x90, 0x07, 0x9B, 0x09, 0xF0, 0x10, 0x09, 0x40, 0xEA, 0x09, 0x00, ++0x06, 0xF1, 0x40, 0x02, 0x5C, 0x80, 0x02, 0x92, 0x18, 0x80, 0x1F, 0xFA, 0x80, 0xF9, 0x14, 0x46, 0x00, 0x2F, 0x00, 0xF0, ++0xDE, 0x81, 0x3A, 0x88, 0x9A, 0x80, 0x7A, 0x88, 0xDA, 0x80, 0xBA, 0x88, 0x1A, 0x81, 0x0A, 0x22, 0x17, 0x46, 0x18, 0x99, ++0x98, 0x18, 0x08, 0x60, 0x00, 0x21, 0x07, 0x90, 0x95, 0xF8, 0x7E, 0x00, 0x99, 0x54, 0x07, 0x9B, 0x00, 0xF1, 0x02, 0x0E, ++0x58, 0x70, 0x00, 0x28, 0x40, 0xF0, 0xC7, 0x80, 0x07, 0x9B, 0x95, 0xF8, 0xB0, 0x10, 0x0E, 0xEB, 0x03, 0x00, 0x01, 0x22, ++0x07, 0x90, 0x0E, 0xF8, 0x03, 0x20, 0x07, 0x9B, 0x08, 0x29, 0x8C, 0x46, 0x28, 0xBF, 0x4F, 0xF0, 0x08, 0x0C, 0x83, 0xF8, ++0x01, 0xC0, 0x07, 0x9B, 0x1F, 0xFA, 0x8E, 0xFE, 0x0C, 0xF1, 0x02, 0x0A, 0x05, 0xF1, 0xB1, 0x02, 0x51, 0xB1, 0x0C, 0xF1, ++0xB1, 0x0C, 0xAC, 0x44, 0x12, 0xF8, 0x01, 0x0B, 0xD1, 0x18, 0x49, 0x1B, 0x94, 0x45, 0x01, 0xF8, 0xB0, 0x0C, 0xF7, 0xD1, ++0x95, 0xF8, 0xB0, 0x20, 0xD6, 0x44, 0x0A, 0xEB, 0x03, 0x01, 0x08, 0x2A, 0x77, 0x44, 0x07, 0x91, 0x1A, 0xD9, 0x32, 0x21, ++0x0A, 0xF8, 0x03, 0x10, 0x07, 0x9B, 0xA2, 0xF1, 0x08, 0x01, 0x59, 0x70, 0x02, 0xF1, 0xB1, 0x0C, 0x07, 0x9B, 0xA2, 0xF1, ++0x06, 0x0E, 0xAC, 0x44, 0x05, 0xF1, 0xB9, 0x02, 0x12, 0xF8, 0x01, 0x0B, 0xD1, 0x18, 0x49, 0x1B, 0x94, 0x45, 0x01, 0xF8, ++0xB8, 0x0C, 0xF7, 0xD1, 0x73, 0x44, 0x77, 0x44, 0x07, 0x93, 0xBF, 0xB2, 0x19, 0xF4, 0x80, 0x7F, 0x40, 0xF0, 0xB5, 0x80, ++0x07, 0xA8, 0xFF, 0xF7, 0x3F, 0xFF, 0x47, 0x44, 0x07, 0x9B, 0x80, 0xB2, 0xBF, 0xB2, 0xB8, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, ++0x02, 0x9A, 0x42, 0x44, 0x94, 0x46, 0x14, 0xF8, 0x01, 0x1B, 0xE2, 0x18, 0x92, 0x1B, 0x64, 0x45, 0x02, 0xF8, 0x41, 0x1C, ++0xF7, 0xD1, 0xD5, 0xF8, 0xE0, 0x40, 0x07, 0x44, 0x43, 0x44, 0xE2, 0x07, 0xBF, 0xB2, 0x07, 0x93, 0x1A, 0xD5, 0xB4, 0x4A, ++0x07, 0xCA, 0x0A, 0xAE, 0x03, 0xC6, 0x00, 0x20, 0x0A, 0xA9, 0x32, 0x80, 0xAD, 0xF8, 0x36, 0x00, 0xCD, 0xF8, 0x32, 0x00, ++0x8D, 0xF8, 0x30, 0x00, 0x5B, 0x1A, 0x0C, 0xA8, 0xDD, 0x22, 0x01, 0xE0, 0x11, 0xF8, 0x01, 0x2F, 0x5A, 0x54, 0x88, 0x42, ++0xFA, 0xD1, 0x07, 0x9B, 0x09, 0x37, 0x09, 0x33, 0xBF, 0xB2, 0x07, 0x93, 0xA6, 0x07, 0x04, 0xD5, 0xA6, 0x4B, 0x93, 0xF8, ++0x76, 0x31, 0xDC, 0x07, 0x53, 0xD4, 0xA5, 0x4B, 0x9B, 0x7D, 0x01, 0x2B, 0x5A, 0xD0, 0xD5, 0xF8, 0xE0, 0x30, 0x18, 0x07, ++0x04, 0xD5, 0xA0, 0x4A, 0x92, 0xF8, 0x76, 0x21, 0x51, 0x07, 0x3C, 0xD4, 0x5A, 0x07, 0x22, 0xD5, 0x9C, 0x4D, 0x95, 0xF8, ++0x76, 0x31, 0x9B, 0x07, 0x1D, 0xD5, 0x03, 0x99, 0x9B, 0x4B, 0x9C, 0x4C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x33, ++0x07, 0xA8, 0x93, 0xF8, 0xC0, 0x14, 0xD4, 0xF8, 0x50, 0x21, 0x90, 0x47, 0x07, 0x44, 0x28, 0x8F, 0xD4, 0xF8, 0x4C, 0x61, ++0x01, 0xF0, 0x9A, 0xFC, 0x95, 0xF8, 0x75, 0x21, 0x04, 0x2A, 0x01, 0x46, 0x08, 0xBF, 0x03, 0x22, 0x07, 0xA8, 0xB0, 0x47, ++0xBF, 0xB2, 0x38, 0x44, 0x87, 0xB2, 0x18, 0x9B, 0x1A, 0x68, 0x07, 0x9B, 0x9B, 0x1A, 0x19, 0x9A, 0x38, 0x46, 0x13, 0x80, ++0x0F, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x7F, 0x30, 0x07, 0x9B, 0x28, 0x44, 0x05, 0xF1, 0x7F, 0x02, 0x12, 0xF8, 0x01, 0xCB, ++0xD1, 0x18, 0x49, 0x1B, 0x90, 0x42, 0x01, 0xF8, 0x7E, 0xCC, 0xF7, 0xD1, 0x2B, 0xE7, 0x82, 0x4B, 0x07, 0xA8, 0xD3, 0xF8, ++0x44, 0x31, 0x98, 0x47, 0x38, 0x44, 0xD5, 0xF8, 0xE0, 0x30, 0x87, 0xB2, 0xB8, 0xE7, 0x7D, 0x4B, 0x07, 0xA8, 0xD3, 0xF8, ++0x48, 0x31, 0x98, 0x47, 0x78, 0x4B, 0x9B, 0x7D, 0x38, 0x44, 0x01, 0x2B, 0x87, 0xB2, 0xA4, 0xD1, 0xB5, 0xF8, 0xE4, 0x30, ++0x00, 0x2B, 0xA0, 0xD0, 0x07, 0x9B, 0x36, 0x22, 0x1A, 0x70, 0x07, 0x9B, 0x03, 0x22, 0x5A, 0x70, 0x07, 0x9B, 0xB5, 0xF8, ++0xE4, 0x20, 0x5A, 0x80, 0x95, 0xF8, 0xE6, 0x20, 0x1A, 0x71, 0x07, 0x9B, 0x05, 0x37, 0x05, 0x33, 0xBF, 0xB2, 0x07, 0x93, ++0x8D, 0xE7, 0x07, 0x9B, 0x21, 0x22, 0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x02, 0x22, 0x59, 0x1C, 0x07, 0x91, ++0x0A, 0xA8, 0x1A, 0x70, 0x0D, 0xF1, 0x27, 0x01, 0xDB, 0xF7, 0x8E, 0xFE, 0xD5, 0xF8, 0xA4, 0x30, 0x9D, 0xF9, 0x28, 0x20, ++0x93, 0xF9, 0x04, 0x30, 0x9A, 0x42, 0xC8, 0xBF, 0x8D, 0xF8, 0x28, 0x30, 0x07, 0x9B, 0x9D, 0xF8, 0x27, 0x20, 0x59, 0x1C, ++0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x9D, 0xF8, 0x28, 0x20, 0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x24, 0x22, ++0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x04, 0x93, 0x1A, 0x46, 0x02, 0xF1, 0x01, 0x0B, 0xD5, 0xF8, 0xA4, 0x30, ++0xCD, 0xF8, 0x1C, 0xB0, 0x9B, 0x78, 0x4F, 0x4A, 0x00, 0x2B, 0x52, 0xD1, 0x01, 0x23, 0x92, 0xF8, 0x72, 0xA1, 0x05, 0x93, ++0x76, 0x32, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x8C, 0x80, 0x00, 0x21, 0x06, 0x95, 0x01, 0x91, 0x08, 0x46, 0x8E, 0x46, ++0xA1, 0x46, 0x0D, 0x46, 0x1A, 0x96, 0xD3, 0x78, 0x13, 0xF0, 0x02, 0x03, 0x1F, 0xD1, 0x94, 0x78, 0xB2, 0xF8, 0x00, 0xC0, ++0x00, 0x2C, 0x43, 0xD1, 0xAC, 0xF6, 0x6C, 0x14, 0x48, 0x2C, 0x3A, 0xD8, 0x40, 0xF6, 0xB4, 0x13, 0x9C, 0x45, 0x6F, 0xD0, ++0x40, 0x4C, 0xAC, 0xF6, 0x67, 0x13, 0xA4, 0xFB, 0x03, 0x43, 0x9C, 0x08, 0xC3, 0xF3, 0x87, 0x03, 0x00, 0x28, 0x45, 0xD0, ++0xA4, 0xEB, 0x0E, 0x0E, 0x05, 0x9C, 0xA6, 0x45, 0x44, 0xD1, 0x01, 0x30, 0xC0, 0xB2, 0x9E, 0x46, 0x06, 0x32, 0x01, 0x31, ++0xCB, 0xB2, 0x9A, 0x45, 0xD7, 0xD8, 0x01, 0x9B, 0x1A, 0x9E, 0x03, 0xF1, 0x02, 0x0E, 0x29, 0x46, 0x5F, 0xFA, 0x8E, 0xF3, ++0x06, 0x9D, 0x4C, 0x46, 0x9E, 0x46, 0x0B, 0xF1, 0x01, 0x02, 0x07, 0x92, 0x8B, 0xF8, 0x00, 0x10, 0x07, 0x9A, 0x51, 0x1C, ++0x07, 0x91, 0x06, 0x37, 0x10, 0x70, 0x04, 0x9A, 0x1E, 0xFA, 0x87, 0xF7, 0xBF, 0xB2, 0x13, 0x70, 0xC0, 0xE6, 0x04, 0x23, ++0x92, 0xF8, 0x73, 0xA1, 0x05, 0x93, 0xCA, 0x32, 0xAB, 0xE7, 0xD8, 0xB9, 0x86, 0x46, 0x05, 0x46, 0x01, 0x20, 0xD5, 0xE7, ++0x01, 0x2C, 0xF8, 0xD1, 0xAC, 0xF5, 0x9C, 0x5C, 0xAC, 0xF1, 0x0D, 0x04, 0xA4, 0xB2, 0xB4, 0xF5, 0x4D, 0x7F, 0xF0, 0xD8, ++0x1D, 0x4B, 0xAC, 0xF1, 0x08, 0x0C, 0xA3, 0xFB, 0x0C, 0x43, 0x9C, 0x08, 0xC3, 0xF3, 0x87, 0x03, 0x00, 0x28, 0xB9, 0xD1, ++0x9E, 0x46, 0x1D, 0x46, 0x01, 0x20, 0xBD, 0xE7, 0x0B, 0xF1, 0x01, 0x04, 0x07, 0x94, 0x8B, 0xF8, 0x00, 0x50, 0x07, 0x9C, ++0x01, 0x9E, 0x04, 0xF1, 0x01, 0x0C, 0x06, 0xF1, 0x02, 0x0E, 0xCD, 0xF8, 0x1C, 0xC0, 0x00, 0xF1, 0x02, 0x0C, 0x20, 0x70, ++0x5F, 0xFA, 0x8E, 0xF0, 0x01, 0x90, 0xDD, 0xF8, 0x1C, 0xB0, 0x9E, 0x46, 0x5F, 0xFA, 0x8C, 0xF0, 0xA4, 0xE7, 0x04, 0x22, ++0x17, 0x46, 0x26, 0xE6, 0x0E, 0x23, 0x1C, 0x46, 0x94, 0xE7, 0x02, 0x23, 0x50, 0x46, 0x51, 0x46, 0x9E, 0x46, 0xA8, 0xE7, ++0x2C, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xCD, 0xCC, 0xCC, 0xCC, 0x03, 0x22, 0x00, 0x23, 0x30, 0xB4, 0x02, 0x70, 0x43, 0x70, 0x4B, 0x7C, 0x83, 0x70, 0x0B, 0x7C, ++0x8C, 0x7B, 0xCA, 0x7B, 0x4D, 0x89, 0xA0, 0xF8, 0x05, 0x50, 0x9B, 0x00, 0x43, 0xEA, 0x44, 0x03, 0x43, 0xEA, 0x82, 0x13, ++0xA0, 0xF8, 0x03, 0x30, 0x0B, 0x89, 0x1B, 0x01, 0xA0, 0xF8, 0x07, 0x30, 0x30, 0xBC, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, ++0x30, 0xB4, 0x22, 0xF0, 0x01, 0x02, 0xBD, 0xF8, 0x08, 0x40, 0xA0, 0xF8, 0x05, 0x20, 0x03, 0x25, 0x01, 0x22, 0xA0, 0xF8, ++0x03, 0x40, 0x83, 0x70, 0x05, 0x70, 0x42, 0x70, 0x2C, 0xB1, 0x00, 0x23, 0xC3, 0x71, 0x03, 0x72, 0x30, 0xBC, 0x09, 0x20, ++0x70, 0x47, 0x4B, 0x89, 0xA0, 0xF8, 0x07, 0x30, 0x30, 0xBC, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x10, 0xB4, 0x02, 0x23, ++0x03, 0x24, 0x04, 0x70, 0x43, 0x70, 0x0B, 0x7C, 0x49, 0x7B, 0x5D, 0xF8, 0x04, 0x4B, 0x82, 0x80, 0x1B, 0x03, 0x9B, 0xB2, ++0x01, 0x29, 0x08, 0xBF, 0x43, 0xF4, 0x00, 0x63, 0x43, 0x80, 0x06, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, ++0x82, 0xB0, 0x16, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0x07, 0x46, 0x88, 0x46, 0xFD, 0xF7, 0x7A, 0xFB, 0xA8, 0xB3, 0x9D, 0xF8, ++0x07, 0x40, 0x83, 0x1C, 0x7C, 0xB1, 0x02, 0x34, 0x20, 0x44, 0x00, 0x24, 0x1D, 0x78, 0x25, 0xF0, 0x81, 0x02, 0x7E, 0x2A, ++0x03, 0xF1, 0x01, 0x03, 0x03, 0xD0, 0x32, 0x19, 0x01, 0x34, 0x55, 0x70, 0xE4, 0xB2, 0x98, 0x42, 0xF2, 0xD1, 0x0D, 0xF1, ++0x07, 0x02, 0x41, 0x46, 0x38, 0x46, 0xFD, 0xF7, 0x7F, 0xFB, 0xB0, 0xB1, 0x9D, 0xF8, 0x07, 0x30, 0x81, 0x1C, 0x93, 0xB1, ++0x02, 0x33, 0x1F, 0x18, 0x0A, 0x78, 0x22, 0xF0, 0x81, 0x00, 0x63, 0x1C, 0x7E, 0x28, 0x06, 0xEB, 0x04, 0x05, 0x01, 0xF1, ++0x01, 0x01, 0xDB, 0xB2, 0x03, 0xD0, 0x0B, 0x2B, 0x6A, 0x70, 0x1C, 0x46, 0x01, 0xD8, 0x8F, 0x42, 0xEE, 0xD1, 0x34, 0x70, ++0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x04, 0x46, 0x34, 0x70, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x10, 0xB5, 0x14, 0x46, ++0xFD, 0xF7, 0xE8, 0xFC, 0x00, 0xB1, 0x80, 0x78, 0x84, 0xF8, 0xDA, 0x00, 0x10, 0xBD, 0x00, 0xBF, 0xF0, 0xB5, 0x83, 0xB0, ++0x14, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0xFD, 0xF7, 0x8B, 0xFB, 0x60, 0xB3, 0xD4, 0xF8, 0xA4, 0xE0, 0x9E, 0xF8, 0x02, 0x40, ++0x4C, 0xB3, 0x01, 0x2C, 0xBE, 0xF8, 0x00, 0x30, 0x40, 0xD0, 0x00, 0x24, 0x04, 0x25, 0x9D, 0xF8, 0x07, 0x70, 0x02, 0x37, ++0xFF, 0xB2, 0x08, 0x2F, 0x8D, 0xF8, 0x07, 0x70, 0x19, 0xD9, 0x05, 0x26, 0x06, 0xEB, 0x00, 0x0C, 0x33, 0x5C, 0x9C, 0xF8, ++0x01, 0x10, 0x69, 0xB1, 0x9C, 0x42, 0x25, 0xD0, 0x01, 0x39, 0xC9, 0xB2, 0x00, 0x22, 0x01, 0xE0, 0x9C, 0x42, 0x1F, 0xD0, ++0x2B, 0x44, 0x8A, 0x42, 0xDB, 0xB2, 0x02, 0xF1, 0x01, 0x02, 0xF7, 0xD1, 0x03, 0x36, 0xF6, 0xB2, 0xF3, 0x1C, 0x9F, 0x42, ++0xE6, 0xDC, 0x03, 0xB0, 0xF0, 0xBD, 0xBE, 0xF8, 0x00, 0x30, 0xA3, 0xF6, 0x6C, 0x12, 0x48, 0x2A, 0x12, 0xD8, 0x40, 0xF6, ++0xB4, 0x12, 0x93, 0x42, 0x20, 0xD0, 0x12, 0x4A, 0xA3, 0xF6, 0x67, 0x14, 0xA2, 0xFB, 0x04, 0x34, 0xC4, 0xF3, 0x87, 0x04, ++0x01, 0x25, 0xC8, 0xE7, 0x9C, 0xF8, 0x02, 0x30, 0x8E, 0xF8, 0x04, 0x30, 0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x25, 0xC0, 0xE7, ++0xA3, 0xF5, 0x9C, 0x53, 0xA3, 0xF1, 0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, 0x4D, 0x7F, 0xB6, 0xD8, 0x05, 0x4C, 0x08, 0x3B, ++0xA4, 0xFB, 0x03, 0x34, 0xC4, 0xF3, 0x87, 0x04, 0x04, 0x25, 0xB0, 0xE7, 0x0E, 0x24, 0x01, 0x25, 0xAD, 0xE7, 0x00, 0xBF, ++0xCD, 0xCC, 0xCC, 0xCC, 0x10, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0x96, 0xFC, 0x48, 0xB1, 0x83, 0x78, 0xC2, 0x78, 0x43, 0xEA, ++0x02, 0x23, 0xA4, 0xF8, 0xE4, 0x30, 0x03, 0x79, 0x84, 0xF8, 0xE6, 0x30, 0x10, 0xBD, 0x84, 0xF8, 0xE6, 0x00, 0xA4, 0xF8, ++0xE4, 0x00, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x82, 0xB0, 0x1C, 0x46, 0x05, 0x46, 0x0E, 0x46, 0x91, 0x46, 0xFD, 0xF7, ++0x49, 0xFB, 0x31, 0x46, 0x07, 0x46, 0x28, 0x46, 0xFD, 0xF7, 0x64, 0xFB, 0x57, 0xEA, 0x00, 0x03, 0x72, 0xD0, 0x80, 0x46, ++0x0D, 0xF1, 0x07, 0x02, 0x31, 0x46, 0x28, 0x46, 0xFD, 0xF7, 0x7A, 0xFB, 0x82, 0x46, 0x18, 0xB1, 0x9D, 0xF8, 0x07, 0x30, ++0x00, 0x2B, 0x65, 0xD0, 0x31, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0x28, 0x46, 0xFD, 0xF7, 0x90, 0xFB, 0x01, 0x46, 0x00, 0x28, ++0x58, 0xD1, 0x00, 0x2F, 0x7A, 0xD0, 0xBB, 0x78, 0x38, 0x79, 0x89, 0xF8, 0x00, 0x30, 0x97, 0xF8, 0x03, 0xC0, 0x00, 0x28, ++0x08, 0xBF, 0x02, 0x20, 0xBC, 0xF1, 0x0E, 0x0F, 0x0C, 0xF1, 0xFF, 0x33, 0x8C, 0xBF, 0x01, 0x27, 0x00, 0x27, 0x4D, 0xD8, ++0x0D, 0x2B, 0x70, 0xD8, 0xBC, 0xF1, 0x0E, 0x0F, 0x00, 0xF0, 0x97, 0x80, 0x0C, 0xEB, 0x8C, 0x06, 0x06, 0xF6, 0x67, 0x16, ++0x00, 0x29, 0x4A, 0xD0, 0x8D, 0x78, 0xCA, 0x78, 0x91, 0xF8, 0x04, 0xE0, 0x05, 0xF1, 0xFF, 0x38, 0xB8, 0xF1, 0x02, 0x0F, ++0x9A, 0xBF, 0x01, 0x35, 0xED, 0xB2, 0x01, 0x25, 0xBC, 0xF1, 0x0E, 0x0F, 0x93, 0xB2, 0x1F, 0xFA, 0x8E, 0xF1, 0x57, 0xD8, ++0x02, 0xF1, 0xFF, 0x3C, 0xBC, 0xF1, 0x0D, 0x0F, 0x72, 0xD8, 0x0E, 0x2A, 0x00, 0xF0, 0x90, 0x80, 0x03, 0xEB, 0x83, 0x03, ++0x03, 0xF6, 0x67, 0x13, 0x61, 0xB1, 0x0E, 0xF1, 0xFF, 0x32, 0x0D, 0x2A, 0x60, 0xD8, 0xBE, 0xF1, 0x0E, 0x0F, 0x00, 0xF0, ++0x9A, 0x80, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF6, 0x67, 0x11, 0x89, 0xB2, 0x4B, 0x4A, 0x92, 0xF8, 0x75, 0x21, 0xAA, 0x42, ++0x24, 0xD2, 0x01, 0x2A, 0x67, 0xD0, 0x02, 0x2A, 0x5E, 0xD0, 0x00, 0x2A, 0x08, 0xBF, 0x33, 0x46, 0x15, 0x46, 0x1B, 0xE0, ++0x9D, 0xF8, 0x07, 0x30, 0x00, 0x2B, 0xA2, 0xD1, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xA4, 0x2B, 0x22, 0xD8, ++0x0C, 0xEB, 0x8C, 0x06, 0x06, 0xF5, 0x9C, 0x56, 0x08, 0x36, 0x00, 0x29, 0xB4, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x31, 0xD0, ++0x9A, 0xF8, 0x02, 0x50, 0x01, 0x2D, 0x3A, 0xD0, 0x03, 0x2D, 0x50, 0xD0, 0x0D, 0x46, 0x33, 0x46, 0x27, 0x70, 0x65, 0x70, ++0x66, 0x80, 0xA3, 0x80, 0xE1, 0x80, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x98, 0xF8, 0x02, 0x30, 0x98, 0xF8, 0x05, 0x00, ++0x89, 0xF8, 0x00, 0x30, 0x98, 0xF8, 0x04, 0xC0, 0x81, 0xE7, 0x4F, 0xF6, 0xFF, 0x76, 0x93, 0xE7, 0x01, 0x3A, 0xA4, 0x2A, ++0x19, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x53, 0x08, 0x33, 0x00, 0x29, 0xB7, 0xD0, 0x0E, 0xF1, 0xFF, 0x3E, ++0xBE, 0xF1, 0xA4, 0x0F, 0x0A, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, 0x9C, 0x51, 0x08, 0x31, 0x89, 0xB2, 0xAB, 0xE7, ++0x51, 0x46, 0x55, 0x46, 0x33, 0x46, 0xD1, 0xE7, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xE7, 0x4F, 0xF6, 0xFF, 0x73, 0xE7, 0xE7, ++0x4F, 0xF6, 0xFF, 0x73, 0x90, 0xE7, 0x06, 0xF1, 0x0A, 0x03, 0x9B, 0xB2, 0xC4, 0xE7, 0x40, 0xF6, 0xB4, 0x16, 0x69, 0xE7, ++0x9E, 0x42, 0x94, 0xBF, 0x28, 0x3B, 0x28, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0xBA, 0xE7, 0x02, 0x2D, 0x0F, 0xD0, 0x03, 0xF1, ++0x28, 0x05, 0xB5, 0x42, 0x15, 0xDA, 0x3C, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0xB0, 0xE7, 0xA6, 0xF1, 0x0A, 0x03, 0x9B, 0xB2, ++0x01, 0x25, 0xAB, 0xE7, 0x40, 0xF6, 0xB4, 0x13, 0x70, 0xE7, 0x9E, 0x42, 0x03, 0xD8, 0x14, 0x3B, 0x9B, 0xB2, 0x15, 0x46, ++0xA2, 0xE7, 0x14, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0x9E, 0xE7, 0x9E, 0x42, 0xF9, 0xD8, 0xA3, 0xF1, 0x27, 0x05, 0xAE, 0x42, ++0xF1, 0xDA, 0x3C, 0x3B, 0x9B, 0xB2, 0x15, 0x46, 0x94, 0xE7, 0x40, 0xF6, 0xB4, 0x11, 0x67, 0xE7, 0xE4, 0xB8, 0x17, 0x00, ++0x70, 0xB5, 0x1D, 0x46, 0x14, 0x46, 0xFD, 0xF7, 0x95, 0xFB, 0x00, 0x23, 0x2B, 0x70, 0x00, 0x28, 0x48, 0xD0, 0x02, 0x7A, ++0xA1, 0x7C, 0x02, 0xF0, 0x0F, 0x03, 0x99, 0x42, 0x40, 0xD0, 0x01, 0x21, 0x29, 0x70, 0xA3, 0x74, 0x22, 0x74, 0xD0, 0xF8, ++0x0A, 0x20, 0x13, 0x0A, 0xD1, 0x08, 0x02, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x03, 0x12, 0x04, 0xBF, 0x40, 0xF6, 0x43, 0x23, ++0x63, 0x60, 0xD0, 0xF8, 0x0E, 0x30, 0x18, 0xBF, 0x62, 0x60, 0x1D, 0x0A, 0x03, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x05, 0x12, ++0x08, 0xBF, 0x40, 0xF6, 0x47, 0x22, 0x22, 0x60, 0xD0, 0xF8, 0x12, 0x20, 0x95, 0x08, 0x16, 0x0A, 0x02, 0xF0, 0x0F, 0x02, ++0x52, 0xEA, 0x06, 0x12, 0x08, 0xBF, 0x12, 0x4A, 0xA2, 0x60, 0xD0, 0xF8, 0x16, 0x20, 0xC3, 0xF3, 0x00, 0x13, 0x50, 0x08, ++0x05, 0xF0, 0x04, 0x05, 0x01, 0xF0, 0x02, 0x01, 0x2B, 0x43, 0x00, 0xF0, 0x08, 0x00, 0x49, 0xB2, 0x03, 0x43, 0x0B, 0x43, ++0x11, 0x0A, 0x02, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x01, 0x12, 0x63, 0x74, 0x0A, 0xBF, 0x07, 0x4B, 0xE2, 0x60, 0xE3, 0x60, ++0x01, 0x20, 0x70, 0xBD, 0x40, 0xF6, 0x43, 0x23, 0xC4, 0xE9, 0x00, 0x33, 0xC4, 0xE9, 0x02, 0x33, 0x70, 0xBD, 0x00, 0xBF, ++0x32, 0xE4, 0x05, 0x00, 0x22, 0xF3, 0x02, 0x00, 0x38, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0x4A, 0xFB, 0xE8, 0xB1, 0xC2, 0x78, ++0x83, 0x78, 0x43, 0xEA, 0x02, 0x23, 0x23, 0x80, 0x23, 0x46, 0x02, 0x79, 0x03, 0xF8, 0x02, 0x2F, 0x04, 0xF1, 0x12, 0x05, ++0xC4, 0xF1, 0x03, 0x02, 0xC1, 0x18, 0x89, 0x5C, 0x03, 0xF8, 0x01, 0x1F, 0xAB, 0x42, 0xF9, 0xD1, 0x43, 0x7D, 0x82, 0x7D, ++0xB0, 0xF8, 0x17, 0x10, 0xA1, 0x61, 0x43, 0xEA, 0x02, 0x23, 0xA3, 0x82, 0xC3, 0x7E, 0x23, 0x77, 0x01, 0x20, 0x38, 0xBD, ++0xF8, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0xCA, 0xFB, 0xB8, 0xB1, 0xC7, 0x79, 0x43, 0x7A, 0x85, 0x79, 0x02, 0x7A, 0x81, 0x7A, ++0xC6, 0x7A, 0x45, 0xEA, 0x07, 0x25, 0x42, 0xEA, 0x03, 0x22, 0xD0, 0xF8, 0x02, 0x70, 0x03, 0x7B, 0x40, 0x7B, 0x27, 0x60, ++0x43, 0xEA, 0x00, 0x23, 0x41, 0xEA, 0x06, 0x21, 0xA5, 0x80, 0x21, 0x81, 0xE2, 0x80, 0x63, 0x81, 0x01, 0x20, 0xF8, 0xBD, ++0xF0, 0xB5, 0x83, 0xB0, 0x15, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0xFD, 0xF7, 0xC9, 0xFB, 0x00, 0x28, 0x45, 0xD0, 0x9D, 0xF8, ++0x07, 0x30, 0xC6, 0x1C, 0xC5, 0xF1, 0x04, 0x04, 0x1E, 0x44, 0x04, 0x44, 0x6B, 0x1E, 0x69, 0x1D, 0x1A, 0x5D, 0x03, 0xF8, ++0x01, 0x2F, 0x8B, 0x42, 0xFA, 0xD1, 0x05, 0xF1, 0x10, 0x02, 0x19, 0x5D, 0x03, 0xF8, 0x01, 0x1F, 0x93, 0x42, 0xFA, 0xD1, ++0x02, 0x7D, 0x47, 0x7D, 0x83, 0x7D, 0xC4, 0x7D, 0xA9, 0x79, 0x42, 0xEA, 0x07, 0x22, 0x43, 0xEA, 0x04, 0x23, 0x6A, 0x82, ++0x4A, 0x10, 0x09, 0x07, 0xAB, 0x82, 0x00, 0xF1, 0x18, 0x03, 0x0E, 0xD5, 0x00, 0xF1, 0x1C, 0x01, 0xB1, 0x42, 0x1C, 0xD8, ++0x5F, 0x78, 0x04, 0x7E, 0x83, 0x7E, 0xC0, 0x7E, 0x44, 0xEA, 0x07, 0x24, 0x43, 0xEA, 0x00, 0x20, 0xEC, 0x82, 0x0B, 0x46, ++0x28, 0x83, 0x12, 0x07, 0x12, 0xD5, 0x1A, 0x1D, 0xB2, 0x42, 0x0C, 0xD8, 0x58, 0x78, 0x19, 0x78, 0x9A, 0x78, 0xDB, 0x78, ++0x41, 0xEA, 0x00, 0x21, 0x42, 0xEA, 0x03, 0x23, 0x01, 0x20, 0x69, 0x83, 0xAB, 0x83, 0x03, 0xB0, 0xF0, 0xBD, 0x00, 0x20, ++0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, ++0x07, 0x02, 0xFD, 0xF7, 0xC7, 0xFB, 0x40, 0xB1, 0xD0, 0xF8, 0x03, 0x30, 0xC4, 0xF8, 0xDC, 0x30, 0x00, 0x38, 0x18, 0xBF, ++0x01, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x01, 0x4B, 0xF6, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x01, 0x80, 0xF8, 0xB5, 0x1D, 0x46, ++0x14, 0x46, 0xFD, 0xF7, 0xC7, 0xFB, 0x00, 0x23, 0x2B, 0x70, 0x00, 0xB3, 0xC2, 0x78, 0x61, 0x7C, 0x02, 0xF0, 0x0F, 0x03, ++0x99, 0x42, 0x1B, 0xD0, 0x01, 0x26, 0x2E, 0x70, 0x22, 0x74, 0x63, 0x74, 0xB0, 0xF8, 0x05, 0x10, 0x03, 0x79, 0x02, 0x89, ++0xB0, 0xF8, 0x0B, 0x70, 0xC5, 0x89, 0x43, 0xEA, 0x01, 0x23, 0x63, 0x60, 0xC1, 0x79, 0x41, 0xEA, 0x02, 0x21, 0x21, 0x60, ++0x82, 0x7A, 0x42, 0xEA, 0x07, 0x22, 0xA2, 0x60, 0x43, 0x7B, 0x43, 0xEA, 0x05, 0x23, 0x30, 0x46, 0xE3, 0x60, 0xF8, 0xBD, ++0x01, 0x20, 0xF8, 0xBD, 0x10, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0xAC, 0xFB, 0x40, 0xB1, 0xC3, 0x78, 0x03, 0xF0, 0x07, 0x02, ++0xC3, 0xF3, 0xC2, 0x03, 0x22, 0x70, 0x63, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x03, 0x22, 0x05, 0x23, 0x22, 0x70, 0x63, 0x70, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0xB5, 0x07, 0x48, 0x1C, 0x46, 0x15, 0x46, 0xFE, 0x22, 0x10, 0xF0, 0x67, 0xFD, 0x2A, 0x46, ++0x21, 0x46, 0x41, 0xF2, 0x03, 0x40, 0xFC, 0xF7, 0x41, 0xFA, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x5A, 0xB9, 0x17, 0x00, ++0x70, 0xB5, 0x32, 0x4C, 0x08, 0x78, 0x24, 0x68, 0x01, 0x28, 0x19, 0x46, 0x20, 0x70, 0x29, 0xD0, 0x02, 0x28, 0x05, 0xD0, ++0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0x2E, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x2B, 0x4C, 0x2C, 0x48, 0x23, 0x68, 0x2C, 0x4E, ++0x2C, 0x4D, 0x43, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x03, 0x68, 0x2B, 0x4C, 0x23, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x3F, 0x23, ++0x33, 0x60, 0x2B, 0x68, 0x28, 0x48, 0x23, 0xF0, 0x01, 0x03, 0x2B, 0x60, 0x23, 0x6D, 0x23, 0xF4, 0x80, 0x23, 0x23, 0x65, ++0x03, 0x69, 0x43, 0xF0, 0x80, 0x03, 0x03, 0x61, 0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0x0C, 0xFA, 0x00, 0x20, 0x70, 0xBD, ++0x20, 0x4B, 0x1B, 0x4C, 0x93, 0xF8, 0xB5, 0x30, 0x0B, 0xBB, 0x23, 0x68, 0x19, 0x4E, 0x1E, 0x4D, 0x43, 0xF0, 0x00, 0x73, ++0x23, 0x60, 0x04, 0xF5, 0x00, 0x44, 0x04, 0x23, 0x28, 0x34, 0x33, 0x60, 0x28, 0x60, 0x23, 0x68, 0x23, 0xF4, 0x80, 0x23, ++0x23, 0xF0, 0x01, 0x03, 0x23, 0x60, 0x13, 0x4C, 0x13, 0x48, 0x23, 0x6D, 0x43, 0xF4, 0x80, 0x23, 0x23, 0x65, 0x03, 0x69, ++0x23, 0xF0, 0x80, 0x03, 0x03, 0x61, 0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0xE5, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0x23, 0x68, ++0x09, 0x48, 0x08, 0x4D, 0x23, 0xF0, 0x00, 0x73, 0x23, 0x60, 0x03, 0x68, 0x24, 0x24, 0x43, 0xF4, 0x00, 0x13, 0x03, 0x60, ++0x2C, 0x60, 0xE2, 0xE7, 0x74, 0x36, 0x17, 0x00, 0x44, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x00, 0x60, 0x50, 0x40, 0x00, 0x00, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x70, 0x80, 0x32, 0x40, ++0xF8, 0xB5, 0x4C, 0x78, 0x08, 0x78, 0x16, 0x46, 0x1D, 0x46, 0x2C, 0xB3, 0x17, 0x4C, 0x18, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x00, 0x44, 0x4F, 0xF4, 0xA4, 0x61, 0x94, 0xF8, 0x22, 0x20, 0x01, 0xFB, 0x02, 0x32, 0x02, 0x23, 0x92, 0xF8, ++0x62, 0x70, 0x84, 0xF8, 0x30, 0x30, 0x5F, 0xB9, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xFC, 0xF7, 0x3E, 0xF9, ++0x07, 0x70, 0x94, 0xF8, 0x22, 0x20, 0x42, 0x70, 0xFC, 0xF7, 0x68, 0xF9, 0x32, 0x46, 0x29, 0x46, 0x41, 0xF2, 0x05, 0x40, ++0xFC, 0xF7, 0x9A, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x04, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x00, 0x30, 0x01, 0x23, ++0x80, 0xF8, 0x30, 0x30, 0xEE, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0x0C, 0x20, 0x0C, 0x46, 0x17, 0x46, 0x00, 0x21, 0x05, 0x22, 0x1E, 0x46, 0x01, 0x23, 0xFC, 0xF7, 0x17, 0xF9, 0xDF, 0xF8, ++0x6C, 0x90, 0xDF, 0xF8, 0x6C, 0x80, 0xD9, 0xF8, 0x24, 0x30, 0x05, 0x46, 0x20, 0x78, 0x98, 0x47, 0x23, 0x78, 0x2B, 0x70, ++0x28, 0x46, 0xFC, 0xF7, 0x39, 0xF9, 0x20, 0x78, 0xD9, 0xF8, 0xD8, 0x31, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0xF0, ++0x00, 0xF5, 0x18, 0x70, 0x40, 0x44, 0x98, 0x47, 0x63, 0x78, 0x43, 0xB9, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x0A, 0x40, ++0xFC, 0xF7, 0x5E, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x23, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, ++0xFC, 0xF7, 0xEC, 0xF8, 0x00, 0x22, 0x02, 0x70, 0x22, 0x78, 0x05, 0xFB, 0x02, 0x88, 0x98, 0xF8, 0x22, 0x20, 0x42, 0x70, ++0xFC, 0xF7, 0x12, 0xF9, 0xE4, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x0C, 0x46, 0x89, 0x78, 0x25, 0x78, 0xDF, 0xF8, 0xAC, 0x80, 0x1E, 0x46, 0x17, 0x46, 0x63, 0x78, 0xA1, 0xB1, 0x00, 0x2B, ++0x44, 0xD1, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x02, 0xF0, 0xFB, 0x02, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x2E, 0x11, 0x83, 0xF8, 0x31, 0x20, 0x0F, 0x29, 0x1E, 0xD1, 0x0A, 0xE0, ++0x2B, 0xBB, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, ++0x31, 0x20, 0x04, 0x23, 0x05, 0x22, 0x00, 0x21, 0x41, 0x20, 0xFC, 0xF7, 0xAB, 0xF8, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x05, 0x85, 0x95, 0xF8, 0x22, 0x30, 0x2A, 0x8C, 0x02, 0x80, 0xC3, 0x70, 0x63, 0x78, 0x83, 0x70, 0xFC, 0xF7, 0xCE, 0xF8, ++0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x0D, 0x40, 0xFC, 0xF7, 0x00, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x42, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x31, 0x20, 0xD8, 0xE7, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x42, 0xF0, 0x04, 0x02, 0xB9, 0xE7, 0x00, 0xBF, ++0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x31, 0x20, 0x0D, 0x46, 0x4B, 0x4C, 0x91, 0x46, 0x98, 0x46, 0x05, 0x22, ++0x01, 0x23, 0x00, 0x21, 0xFC, 0xF7, 0x72, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x76, 0x31, 0x95, 0xF8, 0x67, 0x30, 0x82, 0x46, ++0x5B, 0xB1, 0x01, 0x23, 0x84, 0xF8, 0x76, 0x31, 0x2F, 0x46, 0x0F, 0xCF, 0x04, 0xF1, 0x0C, 0x06, 0x0F, 0xC6, 0x97, 0xE8, ++0x0F, 0x00, 0x86, 0xE8, 0x0F, 0x00, 0x95, 0xF8, 0x68, 0x30, 0x5B, 0xB1, 0x94, 0xF8, 0x76, 0x21, 0x3C, 0x4B, 0x42, 0xF0, ++0x02, 0x02, 0x84, 0xF8, 0x76, 0x21, 0x05, 0xF1, 0x20, 0x02, 0x07, 0xCA, 0x83, 0xE8, 0x07, 0x00, 0x95, 0xF8, 0x69, 0x30, ++0x93, 0xB1, 0x94, 0xF8, 0x76, 0x31, 0x36, 0x4E, 0x43, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x76, 0x31, 0x05, 0xF1, 0x2C, 0x07, ++0x0F, 0xCF, 0x0F, 0xC6, 0x0F, 0xCF, 0x0F, 0xC6, 0x0F, 0xCF, 0x0F, 0xC6, 0x97, 0xE8, 0x03, 0x00, 0x86, 0xE8, 0x03, 0x00, ++0x95, 0xF8, 0x6A, 0x30, 0x2B, 0xB1, 0x94, 0xF8, 0x76, 0x31, 0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x76, 0x31, 0x95, 0xF8, ++0x66, 0x30, 0x84, 0xF8, 0x75, 0x31, 0x4A, 0x46, 0x41, 0x46, 0x41, 0xF2, 0x01, 0x40, 0xFC, 0xF7, 0x8F, 0xF8, 0x94, 0xF8, ++0x76, 0x31, 0x13, 0xF0, 0x01, 0x03, 0x14, 0xD1, 0x84, 0xF8, 0x74, 0x31, 0x95, 0xF8, 0x6B, 0x30, 0xB5, 0xF8, 0x64, 0x10, ++0x84, 0xF8, 0x77, 0x31, 0x95, 0xF8, 0x6D, 0x20, 0xA1, 0x85, 0x00, 0x2A, 0x14, 0xBF, 0x02, 0x22, 0x01, 0x22, 0x84, 0xF8, ++0x78, 0x21, 0xF3, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xDA, 0xF7, 0xE3, 0xFC, 0x94, 0xF8, 0x76, 0x31, 0x01, 0x30, ++0x40, 0x10, 0x5B, 0x07, 0x84, 0xF8, 0x74, 0x01, 0xE2, 0xD5, 0x94, 0xF8, 0x75, 0x21, 0x94, 0xF8, 0x44, 0x30, 0x02, 0x2A, ++0x88, 0xBF, 0x94, 0xF8, 0x49, 0x20, 0x4F, 0xEA, 0x93, 0x03, 0x88, 0xBF, 0x03, 0xEA, 0x92, 0x13, 0x03, 0xF0, 0x01, 0x03, ++0x84, 0xF8, 0x74, 0x30, 0xD0, 0xE7, 0xFF, 0x23, 0x23, 0x81, 0x50, 0x46, 0x8A, 0xF8, 0x00, 0x20, 0xFC, 0xF7, 0x1A, 0xF8, ++0x01, 0x21, 0x05, 0x20, 0xFC, 0xF7, 0xE0, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, ++0x14, 0xB9, 0x17, 0x00, 0x20, 0xB9, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x41, 0xF2, 0x08, 0x40, 0x97, 0xB0, 0x0C, 0x46, ++0x19, 0x46, 0x03, 0x23, 0xFB, 0xF7, 0xD2, 0xFF, 0x4F, 0xF0, 0x00, 0x0A, 0xCD, 0xE9, 0x0C, 0xAA, 0x05, 0x46, 0xAD, 0xF8, ++0x2E, 0xA0, 0x8D, 0xF8, 0x2C, 0xA0, 0x08, 0xF0, 0xEB, 0xFB, 0x94, 0xF8, 0x81, 0x70, 0xA2, 0x6F, 0x06, 0x90, 0x4F, 0xF4, ++0xA4, 0x61, 0x01, 0xFB, 0x07, 0xF1, 0x12, 0xF0, 0x02, 0x06, 0x07, 0x91, 0x1B, 0xD0, 0x12, 0xF0, 0x04, 0x06, 0x04, 0xF1, ++0x14, 0x08, 0x40, 0xF0, 0xDC, 0x81, 0xB1, 0x46, 0x0B, 0xAB, 0x12, 0xF0, 0x20, 0x02, 0x0D, 0xF1, 0x34, 0x0C, 0x02, 0x93, ++0x0C, 0xAB, 0xCD, 0xE9, 0x00, 0x3C, 0x18, 0xBF, 0x04, 0xF1, 0x40, 0x02, 0x0D, 0xF1, 0x2E, 0x03, 0x49, 0x46, 0x40, 0x46, ++0x00, 0xF0, 0x00, 0xFE, 0x94, 0xF8, 0x81, 0x30, 0x00, 0xE0, 0x3B, 0x46, 0x00, 0x22, 0xDF, 0xF8, 0xC4, 0x93, 0x20, 0x68, ++0x0C, 0x99, 0xB4, 0xF8, 0x04, 0xE0, 0xBD, 0xF8, 0x2E, 0xC0, 0x0E, 0x92, 0x8D, 0xF8, 0x55, 0x20, 0x8D, 0xF8, 0x56, 0x20, ++0x9D, 0xF8, 0x2C, 0x20, 0x8D, 0xF8, 0x51, 0x30, 0xCD, 0xF8, 0x4A, 0x00, 0x10, 0x91, 0x8D, 0xF8, 0x50, 0x20, 0xD9, 0xF8, ++0xC4, 0x31, 0x11, 0x96, 0xAD, 0xF8, 0x4E, 0xE0, 0xAD, 0xF8, 0x48, 0xC0, 0x0D, 0xF1, 0x2D, 0x02, 0x29, 0x46, 0x0E, 0xA8, ++0x98, 0x47, 0x83, 0x46, 0x68, 0x70, 0x00, 0x28, 0x40, 0xF0, 0x1C, 0x81, 0x23, 0x46, 0x2E, 0x78, 0x53, 0xF8, 0x06, 0x0F, ++0xDF, 0xF8, 0x70, 0x83, 0x59, 0x68, 0x9A, 0x68, 0x93, 0xF8, 0x0C, 0xE0, 0xD4, 0xF8, 0x78, 0xC0, 0x04, 0x96, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x06, 0xF3, 0x08, 0xEB, 0x03, 0x0A, 0x08, 0x93, 0x0A, 0xF1, 0xB8, 0x03, 0x07, 0xC3, 0x1C, 0xF0, ++0x01, 0x0F, 0x83, 0xF8, 0x00, 0xE0, 0x40, 0xF0, 0x06, 0x81, 0xC7, 0x4B, 0x05, 0x93, 0x1C, 0xF0, 0x08, 0x0F, 0x08, 0xD0, ++0x04, 0x9A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0x5A, 0x68, 0x42, 0xF0, 0x08, 0x02, 0x5A, 0x60, 0x04, 0x9A, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0x94, 0xF8, 0x7E, 0x20, 0x83, 0xF8, 0x2E, 0x21, 0x94, 0xF8, 0x7F, 0x10, ++0xB4, 0xF8, 0x7C, 0x20, 0x1A, 0x84, 0x83, 0xF8, 0x2F, 0x11, 0x50, 0x46, 0x09, 0x93, 0x00, 0xF0, 0xBB, 0xFE, 0xA2, 0x6F, ++0xD2, 0x06, 0x06, 0xD5, 0x94, 0xF9, 0x80, 0x20, 0x94, 0xF8, 0x80, 0x10, 0x00, 0x2A, 0x80, 0xF2, 0x77, 0x81, 0xBB, 0xF1, ++0x00, 0x0F, 0x40, 0xF0, 0x7F, 0x81, 0x05, 0x9B, 0xAF, 0x48, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x34, 0x04, 0x9B, ++0xB4, 0xF8, 0xE0, 0x20, 0x4F, 0xF4, 0x1E, 0x7B, 0x0B, 0xFB, 0x03, 0x86, 0xD4, 0xF8, 0xB0, 0x34, 0x96, 0xF8, 0x56, 0x11, ++0xC6, 0xF8, 0x68, 0xA2, 0x03, 0xF0, 0x01, 0x03, 0xC3, 0xF1, 0x02, 0x03, 0x86, 0xF8, 0x30, 0x30, 0x41, 0xF0, 0x10, 0x01, ++0xA3, 0x4B, 0x86, 0xF8, 0x56, 0x11, 0x52, 0xBA, 0x4F, 0xF0, 0x01, 0x0A, 0xC6, 0xF8, 0x64, 0x02, 0xB2, 0x86, 0x08, 0x98, ++0x86, 0xF8, 0x70, 0xA2, 0x1A, 0x69, 0x9E, 0x49, 0xD9, 0xF8, 0xE0, 0x31, 0x00, 0xF5, 0x18, 0x70, 0x40, 0x44, 0x11, 0x44, ++0x98, 0x47, 0x06, 0x9B, 0xAB, 0x70, 0x00, 0x2B, 0x00, 0xF0, 0x9A, 0x80, 0x94, 0xF8, 0xDE, 0x20, 0x86, 0xF8, 0x24, 0x30, ++0x00, 0x2A, 0x40, 0xF0, 0x85, 0x80, 0x94, 0xF8, 0x63, 0x60, 0x0A, 0x36, 0xF6, 0xB2, 0x0B, 0xFB, 0x06, 0xF3, 0x08, 0xEB, ++0x03, 0x0B, 0x04, 0x93, 0x9B, 0xF8, 0x24, 0x30, 0x53, 0x45, 0x77, 0xD0, 0x02, 0x23, 0x0C, 0x21, 0x49, 0x20, 0xFB, 0xF7, ++0xDB, 0xFE, 0x8B, 0xF8, 0x24, 0xA0, 0x06, 0x70, 0x80, 0xF8, 0x01, 0xA0, 0xFB, 0xF7, 0x04, 0xFF, 0x9B, 0xF8, 0x24, 0x30, ++0x00, 0x2B, 0x40, 0xF0, 0x48, 0x81, 0x9B, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x00, 0xF2, 0x43, 0x81, 0x9B, 0xF8, 0x22, 0x00, ++0x05, 0x9C, 0xCD, 0xF8, 0x18, 0xA0, 0x9E, 0x23, 0xA4, 0x21, 0x4F, 0xF4, 0xA4, 0x6C, 0x11, 0xFB, 0x00, 0x31, 0x0C, 0xFB, ++0x00, 0x4A, 0x4F, 0x23, 0x46, 0x20, 0x13, 0xFB, 0x06, 0x03, 0x7B, 0x4A, 0x05, 0x98, 0x7B, 0x4C, 0x08, 0x95, 0x08, 0xEB, ++0xC3, 0x08, 0x04, 0x9B, 0x00, 0xEB, 0xC1, 0x06, 0x13, 0x44, 0x35, 0x46, 0x1E, 0x46, 0xDB, 0xF8, 0x08, 0x22, 0x1A, 0xB3, ++0xEF, 0xF3, 0x10, 0x82, 0xD3, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x73, 0x4B, 0x06, 0x9A, 0x1A, 0x60, 0x22, 0x68, 0xA8, 0xF1, ++0x28, 0x00, 0x01, 0x32, 0xA5, 0xF1, 0x28, 0x01, 0x04, 0x90, 0x22, 0x60, 0xFC, 0xF7, 0x18, 0xFC, 0xDB, 0xE9, 0x82, 0x21, ++0x04, 0x98, 0xCA, 0xF8, 0xC8, 0x24, 0xCA, 0xF8, 0xCC, 0x14, 0xFC, 0xF7, 0x19, 0xFB, 0x22, 0x68, 0x51, 0x1E, 0x2A, 0xB1, ++0x66, 0x4B, 0x21, 0x60, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xDB, 0xF8, 0x30, 0x22, 0x28, 0x46, 0x41, 0x46, ++0x0B, 0xF1, 0x08, 0x0B, 0x08, 0x35, 0x0A, 0xF1, 0x08, 0x0A, 0x22, 0xB1, 0xFC, 0xF7, 0xFA, 0xFB, 0x40, 0x46, 0xFC, 0xF7, ++0x01, 0xFB, 0x08, 0xF1, 0x08, 0x08, 0x46, 0x45, 0xC5, 0xD1, 0x40, 0x20, 0x08, 0x9D, 0xFC, 0xF7, 0x5B, 0xFA, 0x05, 0x9A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x23, 0x93, 0xF8, 0xDE, 0x20, 0x05, 0x9C, 0xD9, 0xF8, 0x0C, 0x32, 0x4F, 0xF4, ++0xA4, 0x61, 0x01, 0xFB, 0x07, 0x47, 0x07, 0x99, 0x01, 0x32, 0x21, 0x44, 0x08, 0x46, 0x87, 0xF8, 0xDE, 0x20, 0x98, 0x47, ++0x28, 0x46, 0xFB, 0xF7, 0x87, 0xFE, 0x00, 0x20, 0x17, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x04, 0x30, 0x05, 0x93, ++0x1C, 0xF0, 0x02, 0x0F, 0x43, 0xF0, 0x01, 0x03, 0xCA, 0xF8, 0x04, 0x30, 0x3F, 0xF4, 0xEF, 0xAE, 0x45, 0x4B, 0x93, 0xF8, ++0x76, 0x31, 0x09, 0x93, 0x13, 0xF0, 0x01, 0x0B, 0x3F, 0xF4, 0xE7, 0xAE, 0x04, 0xF1, 0x14, 0x0E, 0xBE, 0xE8, 0x0F, 0x00, ++0x0A, 0xF1, 0xC8, 0x0B, 0xAB, 0xE8, 0x0F, 0x00, 0x9E, 0xE8, 0x0F, 0x00, 0x05, 0x9E, 0x1C, 0xF0, 0x20, 0x0F, 0x46, 0xF0, ++0x03, 0x0E, 0x8B, 0xE8, 0x0F, 0x00, 0xCA, 0xF8, 0x04, 0xE0, 0x22, 0xD0, 0x09, 0x9B, 0x58, 0x07, 0x1F, 0xD5, 0x04, 0xF1, ++0x40, 0x0E, 0xBE, 0xE8, 0x0F, 0x00, 0x0A, 0xF1, 0xF4, 0x0B, 0xAB, 0xE8, 0x0F, 0x00, 0xBE, 0xE8, 0x0F, 0x00, 0xAB, 0xE8, ++0x0F, 0x00, 0xBE, 0xE8, 0x0F, 0x00, 0xAB, 0xE8, 0x0F, 0x00, 0x9E, 0xE8, 0x03, 0x00, 0x46, 0xF0, 0x23, 0x03, 0xCA, 0xF8, ++0x04, 0x30, 0x09, 0x9B, 0x8B, 0xE8, 0x03, 0x00, 0x19, 0x07, 0x04, 0xD5, 0x50, 0x46, 0xEC, 0xF7, 0x85, 0xFF, 0xD4, 0xF8, ++0x78, 0xC0, 0x1C, 0xF0, 0x04, 0x0F, 0x1F, 0xD0, 0x24, 0x4B, 0x04, 0x9A, 0x93, 0xF8, 0x76, 0x31, 0x13, 0xF0, 0x02, 0x0F, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0xD3, 0xF8, 0x04, 0xC0, 0x02, 0xD1, 0x1C, 0xF0, 0x20, 0x0F, 0x0F, 0xD0, ++0x04, 0xF1, 0x34, 0x03, 0x93, 0xE8, 0x07, 0x00, 0x04, 0x9E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0x83, 0x03, 0xF1, ++0xE8, 0x0E, 0x8E, 0xE8, 0x07, 0x00, 0x4C, 0xF0, 0x04, 0x02, 0x5A, 0x60, 0x07, 0x9A, 0x0D, 0x4B, 0x05, 0x93, 0x02, 0xF1, ++0xEC, 0x01, 0x19, 0x44, 0x50, 0x46, 0x00, 0xF0, 0x53, 0xFB, 0xD4, 0xF8, 0x78, 0xC0, 0x83, 0x46, 0x81, 0xE6, 0x07, 0x4B, ++0x05, 0x93, 0x0B, 0x44, 0x04, 0xF1, 0x34, 0x09, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x43, 0xD0, 0x03, 0x2B, 0x2F, 0xD0, ++0xA3, 0xB3, 0x56, 0x46, 0x16, 0xE6, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x1D, 0x66, 0x12, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x40, 0x4B, 0x4C, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x09, 0x9B, 0x0A, 0x09, 0x93, 0xF8, 0x23, 0x00, 0x01, 0xF0, 0x03, 0x01, ++0x01, 0xF0, 0x34, 0xF8, 0xBB, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x81, 0xAE, 0x04, 0x9A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x02, 0x83, 0xFF, 0x21, 0x93, 0xF8, 0x23, 0x00, 0x00, 0x22, 0x01, 0xF0, 0x25, 0xF8, 0x74, 0xE6, 0x20, 0x46, 0xFC, 0xF7, ++0x61, 0xFF, 0xA2, 0x6F, 0x06, 0x46, 0xE3, 0xE5, 0x09, 0x4B, 0x01, 0xF5, 0xB2, 0x70, 0x03, 0x44, 0xB4, 0xF8, 0x7C, 0x10, ++0x18, 0x46, 0xFC, 0xF7, 0x5D, 0xFF, 0xA2, 0x6F, 0x06, 0x46, 0xD7, 0xE5, 0x07, 0x9B, 0x03, 0xF1, 0x5C, 0x00, 0x05, 0x9B, ++0xF1, 0xE7, 0x94, 0xF8, 0xDE, 0x20, 0x1B, 0xE7, 0x18, 0x88, 0x17, 0x00, 0xF0, 0xB5, 0x0C, 0x46, 0x21, 0x4D, 0x09, 0x78, ++0x6F, 0x68, 0x1E, 0x46, 0x63, 0x78, 0x01, 0x20, 0x83, 0xB0, 0x98, 0x40, 0xC1, 0xB1, 0x38, 0x43, 0x95, 0xF8, 0x77, 0x31, ++0x68, 0x60, 0x5B, 0xB1, 0x05, 0x20, 0x01, 0x92, 0xFC, 0xF7, 0x10, 0xF8, 0x01, 0x28, 0x2C, 0xD0, 0x17, 0xF0, 0xFF, 0x0F, ++0x23, 0x78, 0x01, 0x9A, 0x0B, 0xD0, 0x63, 0xB1, 0x41, 0xF2, 0x1A, 0x40, 0x31, 0x46, 0xFB, 0xF7, 0xC9, 0xFD, 0x00, 0x20, ++0x03, 0xB0, 0xF0, 0xBD, 0x27, 0xEA, 0x00, 0x00, 0xE4, 0xE7, 0x00, 0x2B, 0xF2, 0xD0, 0x01, 0x23, 0x00, 0x21, 0x31, 0x20, ++0x01, 0x92, 0xFB, 0xF7, 0x53, 0xFD, 0x6B, 0x68, 0x01, 0x9A, 0x2E, 0x81, 0x63, 0xB1, 0x00, 0x23, 0x03, 0x70, 0x01, 0x92, ++0xFB, 0xF7, 0x7A, 0xFD, 0x01, 0x9A, 0x01, 0x21, 0x10, 0x46, 0xFB, 0xF7, 0x3F, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, ++0x95, 0xF8, 0x78, 0x31, 0xF0, 0xE7, 0x02, 0x20, 0xDC, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0x11, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x14, 0x46, 0x0E, 0xDB, 0x0E, 0x4B, 0x19, 0x89, 0xFF, 0x29, 0x04, 0xD0, ++0x22, 0x46, 0x41, 0xF2, 0x18, 0x40, 0xFB, 0xF7, 0x91, 0xFD, 0x20, 0x46, 0x00, 0x21, 0xFB, 0xF7, 0x1F, 0xFF, 0x00, 0x20, ++0x10, 0xBD, 0x10, 0x46, 0xFB, 0xF7, 0xC2, 0xFF, 0x01, 0x28, 0xEB, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x7F, 0x22, ++0xFD, 0xF7, 0xFA, 0xFD, 0xE4, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x3C, 0xB8, 0x15, 0x00, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x14, 0x46, 0x0E, 0xDB, ++0x0E, 0x4B, 0x19, 0x89, 0xFF, 0x29, 0x04, 0xD0, 0x22, 0x46, 0x41, 0xF2, 0x1A, 0x40, 0xFB, 0xF7, 0x65, 0xFD, 0x20, 0x46, ++0x00, 0x21, 0xFB, 0xF7, 0xF3, 0xFE, 0x00, 0x20, 0x10, 0xBD, 0x10, 0x46, 0xFB, 0xF7, 0x96, 0xFF, 0x01, 0x28, 0xEB, 0xD0, ++0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x15, 0x32, 0xFD, 0xF7, 0xCE, 0xFD, 0xE4, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0xB8, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x46, 0x41, 0xF2, 0x0F, 0x40, ++0x19, 0x46, 0xC8, 0x23, 0xFB, 0xF7, 0xDA, 0xFC, 0x22, 0x78, 0x37, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, ++0x06, 0x46, 0xD3, 0xF8, 0x4C, 0x51, 0x02, 0x70, 0x00, 0x2D, 0x5C, 0xD0, 0xB5, 0xF8, 0xB4, 0x00, 0xB5, 0xF8, 0x90, 0x10, ++0xB5, 0xF8, 0x92, 0x20, 0xD5, 0xF8, 0x94, 0x30, 0xB3, 0x60, 0x70, 0x80, 0xB1, 0x80, 0xF2, 0x80, 0x95, 0xF8, 0xA4, 0x30, ++0x33, 0x73, 0xB5, 0xF8, 0x98, 0x30, 0x73, 0x73, 0x08, 0x22, 0x05, 0xF1, 0x88, 0x01, 0x06, 0xF1, 0x0E, 0x00, 0x10, 0xF0, ++0x3D, 0xF8, 0x78, 0x22, 0x29, 0x1D, 0x06, 0xF1, 0x16, 0x00, 0x10, 0xF0, 0x37, 0xF8, 0xB5, 0xF8, 0xB4, 0x30, 0x83, 0xB1, ++0x00, 0x24, 0x00, 0x22, 0xE1, 0xB2, 0x28, 0x46, 0x0C, 0xF0, 0x2C, 0xFE, 0xA3, 0xB2, 0x06, 0xEB, 0x83, 0x03, 0xB5, 0xF8, ++0xB4, 0x20, 0xC3, 0xF8, 0x9C, 0x00, 0x01, 0x34, 0xA3, 0xB2, 0x9A, 0x42, 0xEF, 0xD8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x05, 0xF1, 0x7C, 0x03, 0x07, 0xCB, 0x14, 0x4C, 0xC6, 0xF8, ++0x8E, 0x00, 0x23, 0x68, 0xC6, 0xF8, 0x92, 0x10, 0x01, 0x33, 0xC6, 0xF8, 0x96, 0x20, 0x28, 0x46, 0x00, 0x22, 0x0A, 0x21, ++0x23, 0x60, 0x0C, 0xF0, 0x07, 0xFE, 0x23, 0x68, 0xC6, 0xF8, 0xC4, 0x00, 0x33, 0xB1, 0x0A, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x30, 0x46, 0xFB, 0xF7, 0xA3, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x45, 0x80, ++0x30, 0x46, 0xFB, 0xF7, 0x9D, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x70, 0xB5, 0x23, 0x4A, 0x0B, 0x78, 0x12, 0x68, 0x0C, 0x46, 0x22, 0x49, 0xB2, 0xF9, 0x00, 0x20, ++0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x22, 0xDB, 0x66, 0x88, 0x4F, 0xF6, ++0xFF, 0x73, 0x9E, 0x42, 0x0B, 0xD1, 0x95, 0xF8, 0xA2, 0x30, 0xA5, 0xF8, 0xBA, 0x60, 0x03, 0xF0, 0xCF, 0x03, 0x85, 0xF8, ++0xA2, 0x30, 0x1B, 0x06, 0x1C, 0xD4, 0x00, 0x20, 0x70, 0xBD, 0x31, 0x46, 0x28, 0x46, 0x0C, 0xF0, 0x65, 0xFD, 0x00, 0x28, ++0xF7, 0xD0, 0x95, 0xF8, 0xA2, 0x30, 0xA5, 0xF8, 0xBA, 0x60, 0x23, 0xF0, 0x30, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x85, 0xF8, ++0xA2, 0x30, 0x00, 0x20, 0x70, 0xBD, 0x00, 0x2D, 0xDA, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0xAF, 0x32, 0xFD, 0xF7, ++0x0B, 0xFD, 0xD3, 0xE7, 0x20, 0x78, 0x0C, 0xF0, 0xC9, 0xFB, 0x95, 0xF8, 0xA2, 0x30, 0x03, 0xF0, 0x7F, 0x03, 0x85, 0xF8, ++0xA2, 0x30, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0xF8, 0xB5, 0x05, 0x20, 0x0E, 0x46, 0x15, 0x46, 0x1C, 0x46, 0xFB, 0xF7, 0xAF, 0xFE, 0x01, 0x28, ++0x4F, 0xD0, 0x2A, 0x46, 0x0C, 0x23, 0x21, 0x46, 0x41, 0xF2, 0x12, 0x40, 0xFB, 0xF7, 0x04, 0xFC, 0x37, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x2A, 0xDB, 0x35, 0x4B, 0x1C, 0x7C, 0xDA, 0xF7, 0x7F, 0xF8, 0x00, 0x28, ++0x30, 0xD1, 0xF3, 0x7A, 0x53, 0xB1, 0x32, 0x4B, 0x32, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0x2C, 0x12, 0x11, 0x66, 0xA3, 0xF5, ++0x40, 0x63, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x2E, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x77, 0x3C, 0x6C, ++0x4C, 0xB3, 0x23, 0x7E, 0x2B, 0x70, 0xB3, 0x7A, 0xE3, 0xB9, 0x23, 0x1D, 0x03, 0xCB, 0x1B, 0x88, 0x6B, 0x81, 0xC5, 0xF8, ++0x02, 0x00, 0xC5, 0xF8, 0x06, 0x10, 0x28, 0x46, 0xFB, 0xF7, 0x04, 0xFC, 0x00, 0x20, 0xF8, 0xBD, 0x1F, 0x4F, 0x3C, 0x7C, ++0xFF, 0x2C, 0xD2, 0xD1, 0x21, 0x49, 0x22, 0x48, 0x40, 0xF2, 0xEB, 0x32, 0xFD, 0xF7, 0xAA, 0xFC, 0x3C, 0x7C, 0xCA, 0xE7, ++0xF0, 0x7A, 0xDA, 0xF7, 0x53, 0xF8, 0xCA, 0xE7, 0x1D, 0x48, 0xFC, 0xF7, 0xD1, 0xF8, 0x01, 0x28, 0x0A, 0xD0, 0x3C, 0x6C, ++0xDB, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xFF, 0x23, 0x28, 0x46, 0x2B, 0x70, 0xFB, 0xF7, 0xE4, 0xFB, 0x20, 0x46, 0xF8, 0xBD, ++0x05, 0x22, 0x0C, 0x23, 0x00, 0x21, 0x3B, 0x20, 0xFB, 0xF7, 0xAC, 0xFB, 0x39, 0x6C, 0x03, 0x46, 0x09, 0x7E, 0x03, 0xF8, ++0x02, 0x1B, 0x31, 0x89, 0x37, 0x68, 0x74, 0x68, 0xC0, 0xF8, 0x02, 0x70, 0x19, 0x81, 0x5C, 0x60, 0xFB, 0xF7, 0xCE, 0xFB, ++0x31, 0x68, 0x72, 0x68, 0x33, 0x89, 0x6B, 0x81, 0xC5, 0xF8, 0x02, 0x10, 0xC5, 0xF8, 0x06, 0x20, 0xBD, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x60, 0xB8, 0x15, 0x00, 0x08, 0x88, 0x17, 0x00, 0xF8, 0xB5, 0x05, 0x20, 0x0C, 0x46, 0x15, 0x46, ++0x1E, 0x46, 0xFB, 0xF7, 0x1F, 0xFE, 0x01, 0x28, 0x3C, 0xD0, 0x1F, 0x4F, 0x3B, 0x68, 0x73, 0xB1, 0x22, 0x78, 0xB2, 0xB1, ++0x61, 0x78, 0x01, 0x22, 0x8A, 0x40, 0x13, 0x43, 0x31, 0x46, 0x2A, 0x46, 0x41, 0xF2, 0x18, 0x40, 0x3B, 0x60, 0xFB, 0xF7, ++0xD3, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x23, 0x78, 0x3B, 0xB9, 0x2A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x18, 0x40, 0xFB, 0xF7, ++0xC9, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x01, 0x23, 0x00, 0x21, 0x2A, 0x46, 0x22, 0x20, 0xFB, 0xF7, 0x59, 0xFB, 0x23, 0x78, ++0x61, 0x78, 0x8B, 0xB1, 0x3A, 0x68, 0x01, 0x23, 0x8B, 0x40, 0x13, 0x43, 0xB3, 0xFA, 0x83, 0xF2, 0x52, 0x09, 0x3B, 0x60, ++0x3E, 0x81, 0x02, 0x70, 0xFB, 0xF7, 0x7A, 0xFB, 0x28, 0x46, 0x01, 0x21, 0xFB, 0xF7, 0x40, 0xFD, 0x00, 0x20, 0xF8, 0xBD, ++0x3B, 0x68, 0x01, 0x22, 0x8A, 0x40, 0x23, 0xEA, 0x02, 0x03, 0xEB, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xE4, 0xB8, 0x17, 0x00, ++0xF8, 0xB5, 0x05, 0x20, 0x0D, 0x46, 0x17, 0x46, 0x1E, 0x46, 0xFB, 0xF7, 0xD5, 0xFD, 0x01, 0x28, 0x24, 0xD0, 0x13, 0x4C, ++0x2B, 0x78, 0x61, 0x68, 0x00, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0x84, 0xF8, 0x77, 0x31, 0x81, 0xB9, 0x01, 0x23, 0x05, 0x22, ++0x31, 0x20, 0xFB, 0xF7, 0x23, 0xFB, 0x94, 0xF8, 0x77, 0x31, 0xFF, 0x22, 0x22, 0x81, 0x73, 0xB9, 0x03, 0x70, 0xFB, 0xF7, ++0x4B, 0xFB, 0x01, 0x21, 0x05, 0x20, 0xFB, 0xF7, 0x11, 0xFD, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x14, 0x40, 0xFB, 0xF7, ++0x79, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x94, 0xF8, 0x78, 0x31, 0xED, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xE4, 0xB8, 0x17, 0x00, ++0x08, 0xB5, 0x4F, 0xF4, 0xBE, 0x72, 0x00, 0x21, 0x09, 0x48, 0xD8, 0xF7, 0xFB, 0xFE, 0x00, 0x21, 0x05, 0x20, 0xFB, 0xF7, ++0xF7, 0xFC, 0x04, 0xF0, 0xFB, 0xFF, 0x04, 0xF0, 0x7D, 0xFA, 0x02, 0xF0, 0x25, 0xF9, 0x09, 0xF0, 0x41, 0xF9, 0xBD, 0xE8, ++0x08, 0x40, 0x0E, 0xF0, 0xD5, 0xB8, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0xA8, 0xB9, 0x10, 0x4B, 0x93, 0xF8, 0x72, 0x01, ++0x76, 0x33, 0xC8, 0xB1, 0x00, 0xEB, 0x40, 0x00, 0x10, 0xB4, 0x03, 0xEB, 0x40, 0x04, 0x01, 0xE0, 0xA3, 0x42, 0x0D, 0xD0, ++0x1A, 0x88, 0x8A, 0x42, 0x18, 0x46, 0x03, 0xF1, 0x06, 0x03, 0xF7, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x05, 0x4B, ++0x93, 0xF8, 0x73, 0x01, 0xCA, 0x33, 0xE8, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, ++0xE4, 0xB8, 0x17, 0x00, 0xF0, 0xB9, 0x4B, 0x1E, 0x0D, 0x2B, 0x31, 0xD8, 0x0E, 0x29, 0x32, 0xD0, 0x01, 0xEB, 0x81, 0x01, ++0x01, 0xF6, 0x67, 0x11, 0x19, 0x4B, 0x93, 0xF8, 0x72, 0x01, 0x76, 0x33, 0x60, 0xB3, 0x00, 0xEB, 0x40, 0x00, 0x10, 0xB4, ++0x03, 0xEB, 0x40, 0x04, 0x01, 0xE0, 0xA3, 0x42, 0x1A, 0xD0, 0x1A, 0x88, 0x8A, 0x42, 0x18, 0x46, 0x03, 0xF1, 0x06, 0x03, ++0xF7, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x01, 0x28, 0x06, 0xD0, 0x4F, 0xF6, 0xFF, 0x71, 0x0C, 0x4B, 0x93, 0xF8, ++0x73, 0x01, 0xCA, 0x33, 0xE4, 0xE7, 0x4B, 0x1E, 0xA4, 0x2B, 0xF5, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, 0x9C, 0x51, ++0x08, 0x31, 0xF1, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x4F, 0xF6, 0xFF, 0x71, 0xD0, 0xE7, 0x40, 0xF6, ++0xB4, 0x11, 0xCD, 0xE7, 0x70, 0x47, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0xF0, 0xB4, 0x03, 0x46, 0x42, 0x48, 0x5C, 0x68, ++0x90, 0xF8, 0x75, 0x21, 0xA5, 0x06, 0x2E, 0xD5, 0x93, 0xF8, 0xFA, 0x70, 0x93, 0xF8, 0xFC, 0x50, 0x93, 0xF8, 0x01, 0x61, ++0x7C, 0x10, 0xFF, 0x06, 0x4F, 0xEA, 0xD5, 0x05, 0x55, 0xD5, 0x04, 0x24, 0x05, 0xEA, 0xD6, 0x16, 0x90, 0xF8, 0x74, 0x50, ++0xB3, 0xF8, 0xC8, 0x00, 0xB5, 0x42, 0x28, 0xBF, 0x35, 0x46, 0x94, 0x42, 0x28, 0xBF, 0x14, 0x46, 0x83, 0xF8, 0x2C, 0x41, ++0x91, 0xF8, 0xD9, 0x20, 0x04, 0x2A, 0x46, 0xD0, 0xA2, 0x42, 0x28, 0xBF, 0x22, 0x46, 0x04, 0x2A, 0x43, 0xD0, 0xD2, 0xB2, ++0x00, 0xF0, 0x0C, 0x00, 0x0C, 0x38, 0x83, 0xF8, 0x2D, 0x21, 0x83, 0xF8, 0x30, 0x51, 0x18, 0xBF, 0x01, 0x20, 0xF0, 0xBC, ++0x70, 0x47, 0x90, 0xF8, 0x74, 0x51, 0x60, 0x07, 0x13, 0xD5, 0xD3, 0xF8, 0xE8, 0x00, 0x00, 0xF0, 0x0C, 0x04, 0x04, 0x2C, ++0x44, 0xD0, 0x08, 0x2C, 0x0C, 0xBF, 0x04, 0x24, 0x02, 0x24, 0xC0, 0xF3, 0x02, 0x20, 0x04, 0x28, 0x27, 0xD8, 0x85, 0x42, ++0x28, 0xBF, 0x05, 0x46, 0xB3, 0xF8, 0xC8, 0x00, 0xCD, 0xE7, 0xB3, 0xF8, 0xC8, 0x00, 0x10, 0xF0, 0x02, 0x04, 0xC0, 0xF3, ++0x01, 0x26, 0x28, 0xD0, 0x01, 0x2A, 0x28, 0xBF, 0x01, 0x22, 0x83, 0xF8, 0x2C, 0x21, 0x14, 0x46, 0x91, 0xF8, 0xD9, 0x20, ++0xB5, 0x42, 0x28, 0xBF, 0x35, 0x46, 0x04, 0x2A, 0xC2, 0xD1, 0x02, 0x2C, 0x22, 0x46, 0x28, 0xBF, 0x02, 0x22, 0xD2, 0xB2, ++0xC2, 0xE7, 0x67, 0x07, 0x09, 0xD5, 0x03, 0x24, 0xA6, 0xE7, 0x04, 0x2C, 0xF3, 0xD1, 0x03, 0x22, 0xBA, 0xE7, 0xB3, 0xF8, ++0xC8, 0x00, 0x00, 0x25, 0xA7, 0xE7, 0xA6, 0x07, 0x47, 0xBF, 0x05, 0xF0, 0x01, 0x06, 0x02, 0x24, 0x04, 0xF0, 0x01, 0x04, ++0x05, 0xF0, 0x01, 0x06, 0x96, 0xE7, 0xB5, 0x42, 0x83, 0xF8, 0x2C, 0x41, 0x28, 0xBF, 0x35, 0x46, 0x22, 0x46, 0xA5, 0xE7, ++0x03, 0x24, 0xBC, 0xE7, 0xE4, 0xB8, 0x17, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x01, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x14, 0xBF, ++0x07, 0x20, 0x09, 0x20, 0x70, 0x47, 0x08, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xF0, 0x03, 0x00, 0x01, 0x28, 0x04, 0xD0, ++0x02, 0x28, 0x14, 0xBF, 0x07, 0x20, 0x0B, 0x20, 0x70, 0x47, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x10, 0xB4, 0x0E, 0x22, ++0x04, 0x46, 0x07, 0x20, 0x44, 0xFA, 0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, ++0x02, 0x02, 0x02, 0xD1, 0x11, 0xF0, 0xFF, 0x00, 0xF2, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xC3, 0x78, 0x33, 0xB9, ++0x83, 0x78, 0x33, 0xB9, 0x40, 0x78, 0x00, 0x28, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x02, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x23, 0x40, 0xFA, 0x03, 0xF2, 0x12, 0xF0, 0x01, 0x0F, 0xD9, 0xB2, 0x03, 0xF1, 0x01, 0x03, ++0x02, 0xD1, 0x0C, 0x2B, 0xF5, 0xD1, 0x19, 0x46, 0x08, 0x46, 0x70, 0x47, 0x68, 0xB1, 0x00, 0x23, 0xC3, 0xF1, 0x0B, 0x02, ++0x40, 0xFA, 0x02, 0xF2, 0xD2, 0x07, 0xD9, 0xB2, 0x03, 0xF1, 0x01, 0x03, 0x05, 0xD4, 0x0C, 0x2B, 0xF4, 0xD1, 0xFF, 0x20, ++0x70, 0x47, 0x0C, 0x20, 0x70, 0x47, 0xC1, 0xF1, 0x0B, 0x01, 0xC8, 0xB2, 0x70, 0x47, 0x00, 0xBF, 0xF0, 0xB5, 0xDD, 0xE9, ++0x05, 0x56, 0x00, 0x24, 0x1C, 0x80, 0x2C, 0x60, 0x34, 0x60, 0x50, 0xB3, 0x84, 0x78, 0xC4, 0xF3, 0x82, 0x0C, 0xBC, 0xF1, ++0x02, 0x0F, 0x04, 0xF0, 0x03, 0x04, 0x23, 0xDC, 0x4F, 0xF0, 0x01, 0x0C, 0x04, 0xF1, 0x0D, 0x00, 0x4F, 0xF0, 0x01, 0x0E, ++0x0E, 0xFA, 0x00, 0xF0, 0x07, 0x9F, 0x01, 0x38, 0x80, 0xB2, 0x87, 0xF8, 0x00, 0xC0, 0x18, 0x80, 0xF9, 0xB1, 0x09, 0x68, ++0xC1, 0xF3, 0xC2, 0x51, 0x01, 0xF1, 0x0D, 0x03, 0x0E, 0xFA, 0x03, 0xF3, 0x01, 0x3B, 0x2B, 0x60, 0x4A, 0xB1, 0x07, 0x29, ++0x11, 0xD1, 0xD3, 0x78, 0xC3, 0xF3, 0xC1, 0x03, 0x14, 0x33, 0x0E, 0xFA, 0x03, 0xF7, 0x01, 0x3F, 0x37, 0x60, 0xF0, 0xBD, ++0xAC, 0xF1, 0x03, 0x00, 0x4F, 0xF0, 0x01, 0x0C, 0x0C, 0xFA, 0x00, 0xFC, 0x5F, 0xFA, 0x8C, 0xFC, 0xD4, 0xE7, 0x33, 0x60, ++0xF0, 0xBD, 0x00, 0x2A, 0xF1, 0xD0, 0x03, 0x2C, 0x01, 0xD0, 0x30, 0x60, 0xF0, 0xBD, 0xD3, 0x78, 0xC3, 0xF3, 0xC1, 0x03, ++0x10, 0x33, 0x0E, 0xFA, 0x03, 0xF7, 0x01, 0x3F, 0x37, 0x60, 0xF0, 0xBD, 0x00, 0xF0, 0x7F, 0x03, 0x48, 0x2B, 0x31, 0xD8, ++0x10, 0xF0, 0x7E, 0x0F, 0x2C, 0xD0, 0x02, 0x3B, 0x46, 0x2B, 0x29, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x26, 0x28, 0x24, 0x28, ++0x28, 0x28, 0x28, 0x28, 0x28, 0x35, 0x37, 0x28, 0x28, 0x28, 0x28, 0x28, 0x39, 0x28, 0x28, 0x28, 0x3B, 0x28, 0x3D, 0x28, ++0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x3F, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, ++0x28, 0x28, 0x41, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, ++0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x33, 0x00, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0xFF, 0x20, 0x70, 0x47, ++0x60, 0x2B, 0x04, 0xD0, 0x6C, 0x2B, 0x14, 0xBF, 0xFF, 0x20, 0x0B, 0x20, 0x70, 0x47, 0x0A, 0x20, 0x70, 0x47, 0x09, 0x20, ++0x70, 0x47, 0x02, 0x20, 0x70, 0x47, 0x04, 0x20, 0x70, 0x47, 0x05, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x06, 0x20, ++0x70, 0x47, 0x07, 0x20, 0x70, 0x47, 0x08, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, 0x90, 0xF8, 0x00, 0xB0, ++0xBB, 0xF1, 0x00, 0x0F, 0x34, 0xD0, 0xDF, 0xF8, 0x70, 0x80, 0xDF, 0xF8, 0x70, 0xA0, 0xDF, 0xF8, 0x70, 0x90, 0x05, 0x46, ++0x0E, 0x46, 0x04, 0x46, 0x00, 0x27, 0x9E, 0xB9, 0x60, 0x78, 0xFF, 0xF7, 0x9B, 0xFF, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x4F, 0xF0, 0x01, 0x03, 0x0E, 0xDB, 0x0B, 0x28, 0x0E, 0xDD, 0x01, 0x34, 0x63, 0x1B, 0x5B, 0x45, ++0xED, 0xDB, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x94, 0xF9, 0x01, 0x30, 0x60, 0x78, 0x00, 0x2B, 0xE7, 0xDB, 0xF2, 0xE7, ++0x0B, 0x28, 0x04, 0xDC, 0x03, 0xFA, 0x00, 0xF0, 0x07, 0x43, 0xBF, 0xB2, 0xEB, 0xE7, 0x4F, 0xF4, 0x15, 0x72, 0x51, 0x46, ++0x48, 0x46, 0xFD, 0xF7, 0xC5, 0xF9, 0x95, 0xF8, 0x00, 0xB0, 0xE2, 0xE7, 0x5F, 0x46, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xB8, 0x15, 0x00, 0xF0, 0xB4, 0x00, 0x24, 0x4F, 0xF6, 0xFF, 0x77, ++0x03, 0x26, 0x40, 0xFA, 0x04, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x06, 0xFA, 0x04, 0xF2, 0x41, 0xFA, 0x04, 0xF5, 0x03, 0x2B, ++0x27, 0xEA, 0x02, 0x02, 0x05, 0xF0, 0x03, 0x05, 0x0A, 0xD0, 0x03, 0x2D, 0x08, 0xD0, 0xAB, 0x42, 0x28, 0xBF, 0x2B, 0x46, ++0xA3, 0x40, 0x02, 0x34, 0x1A, 0x43, 0x10, 0x2C, 0x97, 0xB2, 0xE6, 0xD1, 0x38, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0xBF, ++0x08, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x41, 0xF2, 0x21, 0x42, 0xD0, 0xF8, 0x90, 0x31, 0x98, 0x78, ++0x41, 0xF2, 0x21, 0x53, 0x01, 0x28, 0x14, 0xBF, 0x10, 0x46, 0x18, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0xD0, 0xF8, 0xDC, 0x30, 0xC3, 0xF3, 0x05, 0x60, 0x5B, 0x00, 0x54, 0xBF, 0x40, 0xF4, 0x80, 0x70, 0x40, 0xF4, 0x40, 0x70, ++0x70, 0x47, 0x00, 0xBF, 0x10, 0xB5, 0x04, 0x46, 0x0C, 0xF0, 0x86, 0xFB, 0x03, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x5C, 0x31, ++0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x90, 0xF8, 0xB8, 0x00, 0x18, 0xDB, 0x68, 0xB1, 0x05, 0xF1, 0xB8, 0x03, 0x1C, 0x18, ++0x00, 0x20, 0x13, 0xF8, 0x01, 0x2F, 0x22, 0xF0, 0x80, 0x01, 0x81, 0x42, 0xC8, 0xBF, 0x02, 0xF0, 0x7F, 0x00, 0xA3, 0x42, ++0xF5, 0xD1, 0xFF, 0xF7, 0xFF, 0xFE, 0x01, 0x46, 0x28, 0x46, 0x0C, 0xF0, 0x5F, 0xF9, 0x00, 0x23, 0x85, 0xF8, 0x56, 0x31, ++0x38, 0xBD, 0x00, 0x28, 0xE5, 0xD1, 0x05, 0x48, 0x05, 0x49, 0x40, 0xF2, 0xC1, 0x22, 0xFD, 0xF7, 0x25, 0xF9, 0x95, 0xF8, ++0xB8, 0x00, 0xDB, 0xE7, 0x38, 0x36, 0x17, 0x00, 0xB0, 0xB8, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x90, 0xF8, 0x56, 0x31, 0xD0, 0xF8, 0x48, 0x71, 0x99, 0xB0, 0x00, 0x2B, 0x00, 0xF0, 0xDB, 0x80, 0xFA, 0x6B, 0x09, 0x92, ++0x7A, 0x68, 0x05, 0x92, 0x07, 0xF1, 0x14, 0x04, 0xBA, 0x68, 0x07, 0x92, 0x10, 0xAE, 0x0D, 0xF1, 0x50, 0x08, 0x05, 0x46, ++0x22, 0x46, 0xB4, 0x46, 0x40, 0x46, 0x07, 0xF1, 0x24, 0x0B, 0x52, 0xF8, 0x04, 0x1B, 0x4C, 0xF8, 0x04, 0x1B, 0x5A, 0x45, ++0xD1, 0x68, 0x40, 0xF8, 0x04, 0x1B, 0xF6, 0xD1, 0x13, 0xF0, 0x01, 0x02, 0x06, 0x92, 0x40, 0xF0, 0xC0, 0x80, 0x09, 0x9A, ++0xC2, 0xF3, 0xC0, 0x02, 0x06, 0x92, 0x9A, 0x06, 0x00, 0xF1, 0x16, 0x81, 0x98, 0x07, 0x1A, 0xD5, 0xDF, 0xF8, 0x64, 0x93, ++0x06, 0xF1, 0x10, 0x0E, 0x31, 0x46, 0x51, 0xF8, 0x04, 0x2B, 0xC2, 0xF3, 0xC2, 0x2A, 0x02, 0xF0, 0x7C, 0x00, 0x5A, 0xEA, ++0x00, 0x00, 0xC2, 0xF3, 0xC1, 0x1C, 0x02, 0xEA, 0x09, 0x02, 0x06, 0xD0, 0xD5, 0xF8, 0x50, 0x01, 0x02, 0x43, 0x42, 0xEA, ++0x0C, 0x62, 0x41, 0xF8, 0x04, 0x2C, 0x8E, 0x45, 0xE9, 0xD1, 0xD9, 0x06, 0x5C, 0xD5, 0x95, 0xF8, 0x22, 0x10, 0xC3, 0x4A, ++0xC3, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x20, 0xD3, 0xF8, 0x38, 0x33, 0x0D, 0xF1, 0x3F, 0x02, 0x0D, 0xF1, ++0x3E, 0x01, 0x98, 0x47, 0x06, 0xF1, 0x10, 0x03, 0x06, 0x94, 0x08, 0x95, 0x0D, 0xF1, 0x50, 0x09, 0x1C, 0x46, 0x35, 0x46, ++0xBA, 0x4B, 0x59, 0xF8, 0x04, 0xAB, 0x55, 0xF8, 0x04, 0x1B, 0x93, 0xF8, 0xBD, 0x30, 0x4F, 0xEA, 0x1A, 0x4A, 0xC1, 0xF3, ++0xC7, 0x22, 0xC1, 0xF3, 0xC2, 0x20, 0x5F, 0xFA, 0x81, 0xFC, 0x4F, 0xEA, 0x0A, 0x4A, 0x01, 0xF0, 0x7F, 0x01, 0xD3, 0xB9, ++0x0C, 0xF0, 0x7C, 0x0C, 0x50, 0xEA, 0x0C, 0x03, 0x00, 0xF0, 0x29, 0x81, 0xAD, 0x4B, 0x93, 0xF8, 0xBA, 0x30, 0x00, 0x2B, ++0x00, 0xF0, 0xF3, 0x80, 0xAB, 0x4B, 0x93, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xED, 0x80, 0x00, 0x28, 0x40, 0xF0, ++0x2F, 0x81, 0x09, 0x29, 0x00, 0xF2, 0x2C, 0x81, 0x02, 0xF0, 0x06, 0x02, 0x2D, 0xE1, 0xD9, 0xF7, 0x47, 0xFE, 0xA4, 0x4B, ++0x1A, 0x7D, 0x00, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x5A, 0x7D, 0x00, 0x2A, 0x00, 0xF0, 0x02, 0x81, 0x4A, 0xEA, 0x00, 0x20, ++0x40, 0xF0, 0xA8, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xAC, 0x42, 0xBD, 0xD1, 0x08, 0x9D, 0x06, 0x9C, 0x95, 0xF8, 0x56, 0x31, ++0x5A, 0x06, 0x13, 0xD5, 0x94, 0x4A, 0x95, 0xF8, 0x22, 0x30, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x07, 0x9A, ++0xD3, 0xF8, 0xC8, 0x31, 0x22, 0xF0, 0x7C, 0x72, 0x00, 0x2B, 0x07, 0x92, 0x04, 0xDB, 0xC3, 0xF3, 0x05, 0x63, 0x42, 0xEA, ++0x03, 0x53, 0x07, 0x93, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x8D, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x8C, 0x4A, 0x05, 0x9B, 0x11, 0x68, 0x7B, 0x60, 0x48, 0x1C, 0x07, 0x9B, 0xBB, 0x60, 0x10, 0x60, 0x56, 0xF8, 0x04, 0x3B, ++0x44, 0xF8, 0x04, 0x3B, 0x58, 0xF8, 0x04, 0x3B, 0xE3, 0x60, 0xA3, 0x45, 0xF6, 0xD1, 0x28, 0xB1, 0x82, 0x4B, 0x11, 0x60, ++0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x00, 0x23, 0x85, 0xF8, 0x56, 0x31, 0x38, 0x46, 0x19, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0xD5, 0xF8, 0x4C, 0x01, 0x95, 0xF8, 0x30, 0x21, 0x0D, 0x92, 0xCD, 0xE9, 0x0B, 0x34, 0x00, 0x22, 0x08, 0x92, ++0x00, 0xF1, 0x88, 0x0E, 0x0A, 0x92, 0x31, 0x46, 0x82, 0x46, 0x3E, 0xF8, 0x02, 0x3B, 0x03, 0xEB, 0x43, 0x03, 0x0A, 0xEB, ++0x83, 0x03, 0x58, 0x89, 0xC0, 0xF3, 0x0D, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x4F, 0xEA, 0xD3, 0x29, 0x19, 0xF0, 0x06, 0x0C, ++0x00, 0xF0, 0x8E, 0x80, 0x09, 0xF0, 0x07, 0x09, 0xB9, 0xF1, 0x04, 0x0F, 0x03, 0xF0, 0x7F, 0x0C, 0x00, 0xF0, 0xE5, 0x80, ++0xB9, 0xF1, 0x05, 0x0F, 0x00, 0xF0, 0xE4, 0x80, 0xCC, 0xF3, 0xC1, 0x0C, 0x00, 0x2A, 0x00, 0xF0, 0xD1, 0x80, 0x08, 0x98, ++0x00, 0x28, 0x40, 0xF0, 0x95, 0x80, 0x08, 0x68, 0x20, 0xF0, 0x60, 0x40, 0x20, 0xF4, 0x7F, 0x50, 0x20, 0xF0, 0x3F, 0x00, ++0x18, 0x43, 0x08, 0x60, 0x01, 0x32, 0x04, 0x2A, 0x01, 0xF1, 0x04, 0x01, 0xCB, 0xD1, 0x05, 0x9A, 0x22, 0xF4, 0xC0, 0x71, ++0x08, 0x9A, 0x05, 0x91, 0xDD, 0xE9, 0x0B, 0x34, 0x22, 0xB1, 0x0A, 0x9A, 0x01, 0x32, 0x41, 0xEA, 0xC2, 0x12, 0x05, 0x92, ++0x06, 0x9A, 0x00, 0x2A, 0x7E, 0xD1, 0x09, 0x9A, 0x22, 0xF0, 0x08, 0x02, 0x43, 0xF0, 0x02, 0x03, 0xFA, 0x63, 0x9A, 0x06, ++0x85, 0xF8, 0x56, 0x31, 0x7F, 0xF5, 0xEA, 0xAE, 0xD5, 0xF8, 0x4C, 0x01, 0x7A, 0x69, 0x90, 0xF8, 0xA0, 0x30, 0xDF, 0xF8, ++0x38, 0xE1, 0x05, 0x99, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x0E, 0xEA, 0x02, 0x0E, 0xB3, 0xF8, 0x0A, 0xC0, ++0xCC, 0xF3, 0x0D, 0x02, 0xC1, 0xF3, 0xC1, 0x13, 0x42, 0xF0, 0x80, 0x42, 0x11, 0xF4, 0xC0, 0x7F, 0xCC, 0xF3, 0x80, 0x3C, ++0x4E, 0xEA, 0x02, 0x01, 0x03, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x80, 0xF8, 0xA1, 0xC0, 0xC0, 0xF8, 0x9C, 0x10, 0x4F, 0xF0, ++0x00, 0x02, 0x06, 0x98, 0x00, 0x93, 0x03, 0x90, 0x14, 0xBF, 0x01, 0x23, 0x13, 0x46, 0xCD, 0xE9, 0x01, 0x22, 0x38, 0x46, ++0x0C, 0xF0, 0x56, 0xFF, 0x95, 0xF8, 0x56, 0x31, 0xB6, 0xE6, 0x9D, 0xF8, 0x3F, 0x00, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, ++0x0A, 0x00, 0x02, 0xF0, 0x06, 0x02, 0x49, 0xF8, 0x04, 0x0C, 0x00, 0x2A, 0x3F, 0xF4, 0x20, 0xAF, 0x09, 0x29, 0x7F, 0xF6, ++0x1D, 0xAF, 0x29, 0x4B, 0x59, 0xF8, 0x04, 0x2C, 0x93, 0xF8, 0xAF, 0x10, 0x12, 0x0C, 0x41, 0xEA, 0x01, 0x21, 0x12, 0x04, ++0x0A, 0x43, 0x49, 0xF8, 0x04, 0x2C, 0x0F, 0xE7, 0x08, 0x68, 0xCD, 0xF8, 0x18, 0xC0, 0x20, 0xF0, 0x60, 0x40, 0x20, 0xF4, ++0x7F, 0x50, 0x20, 0xF0, 0x3F, 0x00, 0x18, 0x43, 0x08, 0x60, 0x83, 0xE7, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, 0x0A, 0x00, ++0x49, 0xF8, 0x04, 0x0C, 0xFC, 0xE6, 0x9D, 0xF8, 0x3E, 0x20, 0x42, 0xEA, 0x02, 0x22, 0x42, 0xEA, 0x0A, 0x02, 0x49, 0xF8, ++0x04, 0x2C, 0xF3, 0xE6, 0x0A, 0x98, 0xAC, 0xEB, 0x00, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x08, 0x90, 0x62, 0xE7, ++0x09, 0x9A, 0x42, 0xF0, 0x08, 0x02, 0x7F, 0xE7, 0x12, 0xF0, 0x06, 0x02, 0x0B, 0xD0, 0x04, 0x29, 0x09, 0xD8, 0x0C, 0x4B, ++0x93, 0xF8, 0xBB, 0x00, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, 0x0A, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xB5, 0xE7, 0x07, 0x4B, ++0xB3, 0xF8, 0xBB, 0x00, 0x40, 0xBA, 0x80, 0xB2, 0x40, 0xEA, 0x0A, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xAB, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xFF, 0x3F, 0x00, 0xE0, 0x00, 0xC0, 0xFF, 0x1F, 0x0D, 0x98, 0x84, 0x45, ++0x0A, 0x98, 0x38, 0xBF, 0x60, 0x46, 0x0A, 0x90, 0x08, 0x98, 0x38, 0xBF, 0x01, 0x20, 0x08, 0x90, 0x27, 0xE7, 0x4F, 0xEA, ++0x1C, 0x1C, 0x1D, 0xE7, 0x14, 0xAC, 0x03, 0xF4, 0xC0, 0x69, 0x54, 0xF8, 0x22, 0x40, 0xB9, 0xF5, 0x80, 0x6F, 0x0C, 0xBF, ++0x4F, 0xF4, 0x00, 0x39, 0x4F, 0xF4, 0x80, 0x39, 0x24, 0xF4, 0x40, 0x34, 0x44, 0xEA, 0x09, 0x09, 0x40, 0x04, 0x14, 0xAC, ++0x4C, 0xBF, 0x49, 0xF4, 0x80, 0x20, 0x29, 0xF4, 0x80, 0x20, 0x44, 0xF8, 0x22, 0x00, 0x4F, 0xEA, 0x1C, 0x1C, 0x01, 0xE7, ++0xF0, 0xB4, 0xD2, 0xF8, 0xA4, 0x50, 0x2C, 0x88, 0x30, 0xBB, 0x00, 0x29, 0x44, 0xD0, 0x51, 0x4E, 0x03, 0x46, 0x96, 0xF8, ++0x75, 0x01, 0x26, 0x46, 0x01, 0x28, 0x4F, 0xD9, 0x8F, 0x78, 0x17, 0xF0, 0x03, 0x07, 0x3C, 0xD0, 0xAD, 0x78, 0xCB, 0x78, ++0x09, 0x79, 0x00, 0x2D, 0x41, 0xD1, 0x5E, 0x1E, 0x0D, 0x2E, 0x40, 0xD8, 0x0E, 0x2B, 0x00, 0xF0, 0x86, 0x80, 0x03, 0xEB, ++0x83, 0x03, 0x03, 0xF6, 0x67, 0x13, 0x00, 0x29, 0x47, 0xD0, 0x03, 0x2F, 0x60, 0xD0, 0x02, 0x2F, 0x57, 0xD0, 0x02, 0x20, ++0x1C, 0x46, 0x00, 0x21, 0x03, 0x46, 0x05, 0xE0, 0x3E, 0x4B, 0x93, 0xF8, 0x75, 0x31, 0x5B, 0xB9, 0x18, 0x46, 0x00, 0x21, ++0xA2, 0xF8, 0xA8, 0x40, 0x82, 0xF8, 0xD8, 0x30, 0xF0, 0xBC, 0x82, 0xF8, 0xD9, 0x00, 0xA2, 0xF8, 0xAA, 0x10, 0x70, 0x47, ++0xC0, 0x78, 0x10, 0xF0, 0x03, 0x00, 0x12, 0xD0, 0x01, 0x28, 0x4F, 0xF6, 0xF6, 0x76, 0x08, 0xBF, 0x0A, 0x26, 0x26, 0x44, ++0xB6, 0xB2, 0x51, 0xBB, 0x01, 0x23, 0x34, 0x46, 0x18, 0x46, 0xE5, 0xE7, 0x08, 0x46, 0x0B, 0x46, 0xE2, 0xE7, 0x34, 0x46, ++0x39, 0x46, 0x18, 0x46, 0xDE, 0xE7, 0x99, 0xB1, 0x1F, 0x46, 0x26, 0x46, 0x03, 0x46, 0x38, 0x46, 0xB2, 0xE7, 0x01, 0x2D, ++0x1A, 0xD0, 0x4F, 0xF6, 0xFF, 0x73, 0xC2, 0xE7, 0x34, 0x46, 0xCF, 0xE7, 0x4F, 0xF6, 0xD8, 0x71, 0x9C, 0x42, 0x94, 0xBF, ++0x0C, 0x46, 0x28, 0x24, 0x23, 0x44, 0x9C, 0xB2, 0x03, 0x46, 0x00, 0x21, 0xC6, 0xE7, 0x02, 0x2F, 0x11, 0xD0, 0x03, 0x2F, ++0x20, 0xD0, 0x02, 0x20, 0x1C, 0x46, 0x03, 0x46, 0xBE, 0xE7, 0x18, 0x46, 0x01, 0x23, 0x95, 0xE7, 0x5E, 0x1E, 0xA4, 0x2E, ++0xE1, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x53, 0x08, 0x33, 0xA1, 0xE7, 0x02, 0x28, 0xDE, 0xD0, 0x03, 0x20, ++0x1C, 0x46, 0x00, 0x21, 0x03, 0x46, 0xAB, 0xE7, 0x85, 0xB9, 0x4C, 0x1E, 0x0D, 0x2C, 0x0A, 0xD8, 0x0E, 0x29, 0x19, 0xD0, ++0x01, 0xEB, 0x81, 0x01, 0x01, 0xF6, 0x67, 0x11, 0x04, 0x28, 0x94, 0xD1, 0x1C, 0x46, 0x03, 0x23, 0x9C, 0xE7, 0x4F, 0xF6, ++0xFF, 0x71, 0xF7, 0xE7, 0x01, 0x2D, 0xFA, 0xD1, 0x4C, 0x1E, 0xA4, 0x2C, 0xF7, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, ++0x9C, 0x51, 0x08, 0x31, 0xEC, 0xE7, 0x40, 0xF6, 0xB4, 0x13, 0x7A, 0xE7, 0x40, 0xF6, 0xB4, 0x11, 0xE6, 0xE7, 0x00, 0xBF, ++0xE4, 0xB8, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x7B, 0x4F, 0xDF, 0xF8, 0x08, 0x92, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x00, 0x73, 0x04, 0x46, 0x93, 0xF8, 0x22, 0x60, 0x58, 0x68, 0x77, 0x4B, 0x1B, 0x68, 0x10, 0xF0, 0x20, 0x0A, 0xB3, 0xF9, ++0x00, 0x30, 0x0D, 0x46, 0x90, 0x46, 0x4F, 0xD0, 0x00, 0x2B, 0xC0, 0xF2, 0x9F, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x04, 0x73, 0x0E, 0x21, 0xB3, 0xF8, 0x06, 0xC1, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, ++0x02, 0xF1, 0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, 0xB3, 0x80, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0x90, 0x46, ++0xB9, 0xF8, 0x50, 0xC0, 0x0E, 0x21, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, ++0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, 0x9B, 0x80, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0x5D, 0x4B, 0x4F, 0xF4, ++0x1E, 0x70, 0x00, 0xFB, 0x04, 0x74, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x06, 0x36, 0x94, 0xF8, 0x2C, 0x31, 0x96, 0xF8, ++0xC4, 0x11, 0x94, 0xF8, 0x23, 0x00, 0x04, 0x2B, 0x08, 0xBF, 0x03, 0x23, 0xA9, 0x42, 0x28, 0xBF, 0x29, 0x46, 0x99, 0x42, ++0x28, 0xBF, 0x19, 0x46, 0x84, 0xF8, 0x2D, 0x11, 0x0B, 0xF0, 0x22, 0xFD, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x08, 0x03, ++0x84, 0xF8, 0x56, 0x31, 0xBD, 0xE8, 0xF8, 0x8F, 0x10, 0xF0, 0x04, 0x0B, 0x28, 0xD0, 0x00, 0x2B, 0x58, 0xDB, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x04, 0x73, 0x0E, 0x22, 0xB3, 0xF8, 0xEC, 0xC0, 0x07, 0x20, 0x4C, 0xFA, 0x02, 0xF3, 0x03, 0xF0, ++0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, 0x6A, 0xD1, 0x11, 0xF0, 0xFF, 0x00, 0xF2, 0xD1, ++0xB9, 0xF8, 0x38, 0xC0, 0x0E, 0x21, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, ++0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x54, 0xD1, 0x10, 0xF0, 0xFF, 0x02, 0xF2, 0xD1, 0xAF, 0xE7, 0x00, 0x2B, 0x3A, 0xDB, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x73, 0x03, 0xF1, 0xCB, 0x02, 0x93, 0xF8, 0xCE, 0x30, 0x00, 0x2B, 0x54, 0xD1, ++0x93, 0x78, 0x00, 0x2B, 0x4B, 0xD1, 0x53, 0x78, 0x01, 0x20, 0x00, 0x2B, 0x48, 0xD1, 0x99, 0xF8, 0x12, 0x30, 0x00, 0x2B, ++0x4B, 0xD1, 0x99, 0xF8, 0x11, 0x30, 0x00, 0x2B, 0x49, 0xD1, 0x99, 0xF8, 0x10, 0x20, 0x00, 0x3A, 0x18, 0xBF, 0x01, 0x22, ++0x93, 0x45, 0x58, 0x46, 0x28, 0xBF, 0x10, 0x46, 0xC2, 0xB2, 0x89, 0xE7, 0x99, 0xF8, 0x76, 0x31, 0x59, 0x07, 0x3F, 0xF5, ++0x5C, 0xAF, 0x21, 0x49, 0x21, 0x48, 0x40, 0xF2, 0x55, 0x52, 0xFC, 0xF7, 0x99, 0xFD, 0x54, 0xE7, 0x99, 0xF8, 0x76, 0x31, ++0x9A, 0x07, 0xA2, 0xD4, 0x1B, 0x49, 0x1D, 0x48, 0x40, 0xF2, 0x62, 0x52, 0xFC, 0xF7, 0x8E, 0xFD, 0x9B, 0xE7, 0x99, 0xF8, ++0x76, 0x31, 0xDB, 0x07, 0xC0, 0xD4, 0x16, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x6D, 0x52, 0xFC, 0xF7, 0x83, 0xFD, 0xB9, 0xE7, ++0x42, 0x45, 0x28, 0xBF, 0x42, 0x46, 0xD2, 0xB2, 0x62, 0xE7, 0x90, 0x45, 0x28, 0xBF, 0x90, 0x46, 0x4C, 0xE7, 0x52, 0x45, ++0x28, 0xBF, 0x52, 0x46, 0xD2, 0xB2, 0x59, 0xE7, 0x40, 0x45, 0x28, 0xBF, 0x40, 0x46, 0x82, 0x46, 0x92, 0xE7, 0x02, 0x20, ++0x80, 0x45, 0x28, 0xBF, 0x80, 0x46, 0xC3, 0x46, 0xB1, 0xE7, 0x03, 0x20, 0xF8, 0xE7, 0x03, 0x22, 0xBA, 0xE7, 0x02, 0x22, ++0xB8, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC4, 0xB8, 0x15, 0x00, 0xD4, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x2D, 0xED, 0x02, 0x8B, 0xDF, 0xF8, 0xE4, 0xA3, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0xF3, 0x0A, 0xEB, 0x03, 0x06, ++0x8B, 0xB0, 0xB6, 0xF8, 0xC2, 0x41, 0x02, 0x93, 0x01, 0x90, 0xD6, 0xF8, 0x90, 0x31, 0x96, 0xF8, 0xC6, 0x51, 0x04, 0x95, ++0x00, 0x20, 0xA6, 0xF8, 0xC2, 0x01, 0x98, 0x78, 0x02, 0x9D, 0xD6, 0xF8, 0xC8, 0x31, 0x03, 0x94, 0x03, 0xF0, 0x7F, 0x43, ++0x05, 0xF1, 0xEC, 0x0C, 0x24, 0x32, 0x05, 0x93, 0x0A, 0xEB, 0x0C, 0x03, 0xD6, 0xF8, 0xE4, 0x40, 0x96, 0xF8, 0xC5, 0x71, ++0x08, 0xEE, 0x10, 0x2A, 0x08, 0xEE, 0x90, 0x3A, 0xA1, 0xF1, 0x24, 0x09, 0x00, 0x28, 0x00, 0xF0, 0xDD, 0x81, 0x1F, 0xFA, ++0x89, 0xF8, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x03, 0xA9, 0xD9, 0xF8, 0xCC, 0x31, 0xDD, 0x07, 0x05, 0xD5, ++0x99, 0xF8, 0x62, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x5C, 0x82, 0xD2, 0x4B, 0x93, 0xF8, 0x76, 0xB1, 0x1B, 0xF0, ++0x01, 0x0B, 0x40, 0xF0, 0xE9, 0x81, 0xD9, 0x46, 0x48, 0x46, 0x18, 0xEE, 0x90, 0x2A, 0x59, 0x46, 0xFF, 0xF7, 0xF8, 0xFD, ++0x02, 0x9B, 0x03, 0xF2, 0xB4, 0x43, 0x18, 0xEE, 0x10, 0x0A, 0x53, 0x44, 0x0D, 0xF1, 0x25, 0x02, 0x41, 0x46, 0xFD, 0xF7, ++0xD5, 0xFF, 0x10, 0xF0, 0xFF, 0x09, 0x1F, 0xD0, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x6B, 0x0B, 0xFB, 0x03, 0xAB, 0x9B, 0xF8, ++0x62, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x9D, 0x81, 0x9B, 0xF8, 0x8A, 0x10, 0x00, 0x29, 0x00, 0xF0, 0x6F, 0x82, 0x89, 0x45, ++0x07, 0xD0, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x01, 0x22, 0x83, 0xF8, 0x8C, 0x20, 0x01, 0x9A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x83, 0xF8, 0x8A, 0x90, 0x18, 0xEE, 0x90, 0x2A, 0x41, 0x46, 0x18, 0xEE, ++0x10, 0x0A, 0xFD, 0xF7, 0x25, 0xFF, 0x01, 0x9A, 0x04, 0x99, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x93, 0xF8, ++0xC6, 0x21, 0x8A, 0x42, 0x0E, 0xD0, 0xD3, 0xF8, 0x90, 0x11, 0xAC, 0x4B, 0x09, 0x79, 0xD3, 0xF8, 0x40, 0x33, 0x8A, 0x1A, ++0x8D, 0xF8, 0x26, 0x20, 0x0D, 0xF1, 0x26, 0x01, 0x0D, 0xF1, 0x27, 0x02, 0x30, 0x46, 0x98, 0x47, 0x01, 0x9B, 0x4F, 0xF4, ++0xA4, 0x68, 0x08, 0xFB, 0x03, 0xA8, 0x98, 0xF8, 0xC5, 0x31, 0xBB, 0x42, 0x00, 0xF2, 0x01, 0x81, 0x00, 0x2C, 0x00, 0xF0, ++0x8E, 0x80, 0x01, 0x9B, 0x9F, 0x4E, 0x03, 0x9D, 0xDD, 0xF8, 0x14, 0x90, 0x4F, 0xF4, 0xA4, 0x68, 0x08, 0xFB, 0x03, 0xA8, ++0xB8, 0xF8, 0xC2, 0x21, 0xAA, 0x42, 0x1D, 0xD0, 0x29, 0x46, 0x30, 0x46, 0xFC, 0xF7, 0x1A, 0xFA, 0x94, 0xF8, 0x56, 0x31, ++0xB8, 0xF8, 0xC2, 0x21, 0x94, 0xF8, 0x23, 0x00, 0x43, 0xF0, 0x02, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x53, 0x07, 0x4F, 0xF0, ++0x00, 0x01, 0x58, 0xBF, 0x4F, 0xF4, 0x80, 0x63, 0xC4, 0xF8, 0x50, 0x11, 0x4E, 0xBF, 0xA4, 0xF8, 0x54, 0x11, 0xA4, 0xF8, ++0x54, 0x31, 0x01, 0x21, 0x0B, 0xF0, 0x02, 0xFC, 0x98, 0xF8, 0xC5, 0x31, 0xBB, 0x42, 0x4B, 0xD0, 0x04, 0x2B, 0x94, 0xF8, ++0x2C, 0xA1, 0x5F, 0xD0, 0x53, 0x45, 0x28, 0xBF, 0x53, 0x46, 0x04, 0x2B, 0x00, 0xF0, 0x93, 0x80, 0x5F, 0xFA, 0x83, 0xFA, ++0x94, 0xF8, 0x2D, 0x31, 0x53, 0x45, 0x3B, 0xD0, 0x63, 0x68, 0x13, 0xF0, 0x20, 0x0B, 0x58, 0xD0, 0x7F, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA7, 0x80, 0xB4, 0xF8, 0x06, 0xC1, 0x0E, 0x22, 0x07, 0x20, 0x4C, 0xFA, ++0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, 0x02, 0xD1, 0x11, 0xF0, ++0xFF, 0x00, 0xF2, 0xD1, 0x70, 0x4B, 0x07, 0x22, 0xB3, 0xF8, 0x50, 0xE0, 0x0E, 0x23, 0x4E, 0xFA, 0x03, 0xF1, 0x01, 0xF0, ++0x03, 0x01, 0x03, 0x29, 0x02, 0xF1, 0xFF, 0x3C, 0xA3, 0xF1, 0x02, 0x03, 0x40, 0xF0, 0xF4, 0x80, 0x1C, 0xF0, 0xFF, 0x02, ++0xF1, 0xD1, 0x94, 0xF8, 0x23, 0x00, 0x84, 0xF8, 0x2D, 0xA1, 0x51, 0x46, 0x0B, 0xF0, 0x54, 0xFB, 0x94, 0xF8, 0x56, 0x31, ++0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x56, 0x31, 0xD8, 0xF8, 0xC8, 0x31, 0x03, 0xF0, 0x7F, 0x43, 0x4B, 0x45, 0x08, 0xD0, ++0x63, 0x68, 0x9B, 0x06, 0x05, 0xD5, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x24, 0x68, ++0x00, 0x2C, 0x7F, 0xF4, 0x7B, 0xAF, 0x0B, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0xBA, 0xF1, 0x03, 0x0F, ++0x35, 0xD8, 0xBA, 0xF1, 0x02, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, 0x02, 0x0A, 0x9E, 0xE7, 0x13, 0xF0, 0x04, 0x0F, 0x52, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x2B, 0xD0, 0x00, 0x2B, 0xC0, 0xF2, 0xA7, 0x80, 0xB4, 0xF8, 0xEC, 0xC0, 0x0E, 0x22, ++0x07, 0x20, 0x4C, 0xFA, 0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, ++0x40, 0xF0, 0x97, 0x81, 0x11, 0xF0, 0xFF, 0x00, 0xF1, 0xD1, 0x42, 0x4B, 0xB3, 0xF8, 0x38, 0xC0, 0x0E, 0x21, 0x07, 0x22, ++0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, 0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, ++0x7F, 0x81, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0xA1, 0xE7, 0x4F, 0xF0, 0x03, 0x0A, 0x6B, 0xE7, 0x00, 0x2B, 0x5E, 0xDB, ++0x94, 0xF8, 0xCE, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xDF, 0x81, 0x94, 0xF8, 0xCD, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xE0, 0x81, ++0x94, 0xF8, 0xCC, 0x20, 0x11, 0x1E, 0x18, 0xBF, 0x01, 0x21, 0x2E, 0x4A, 0x93, 0x7C, 0x00, 0x2B, 0x40, 0xF0, 0xD2, 0x81, ++0x53, 0x7C, 0x00, 0x2B, 0x40, 0xF0, 0xD0, 0x81, 0x13, 0x7C, 0x1A, 0x1E, 0x18, 0xBF, 0x01, 0x22, 0x8A, 0x42, 0x28, 0xBF, ++0x0A, 0x46, 0x7C, 0xE7, 0x25, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x58, 0x07, 0x3F, 0xF5, 0x53, 0xAF, 0x26, 0x49, 0x27, 0x48, ++0x40, 0xF2, 0xCD, 0x12, 0xFC, 0xF7, 0xA8, 0xFB, 0x4B, 0xE7, 0x0C, 0x23, 0x05, 0x22, 0x00, 0x21, 0x3B, 0x20, 0xFA, 0xF7, ++0xBF, 0xFA, 0x1F, 0x4B, 0xD8, 0xF8, 0x40, 0x20, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x81, 0x46, 0xC0, 0xF2, ++0x18, 0x81, 0x13, 0x7E, 0x89, 0xF8, 0x00, 0x30, 0xD6, 0xF8, 0x90, 0x31, 0x99, 0x78, 0x89, 0xF8, 0x02, 0x10, 0x96, 0xF8, ++0xC5, 0x11, 0x89, 0xF8, 0x03, 0x10, 0xB3, 0xF8, 0x00, 0xC0, 0xB6, 0xF8, 0x94, 0x01, 0xB6, 0xF8, 0x96, 0x11, 0xA9, 0xF8, ++0x08, 0x10, 0xA9, 0xF8, 0x06, 0x00, 0xA9, 0xF8, 0x04, 0xC0, 0x12, 0x7B, 0x89, 0xF8, 0x0A, 0x20, 0xDB, 0x78, 0x89, 0xF8, ++0x0B, 0x30, 0x48, 0x46, 0xFA, 0xF7, 0xC4, 0xFA, 0xCC, 0xE6, 0x06, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0xDA, 0x07, 0x9B, 0xD4, ++0x07, 0x49, 0x09, 0x48, 0x40, 0xF2, 0xE5, 0x12, 0xFC, 0xF7, 0x6A, 0xFB, 0x94, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x0C, 0xB9, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xC4, 0xB8, 0x15, 0x00, ++0xE4, 0xB8, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0xB9, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x99, 0x07, 0x3F, 0xF5, 0x53, 0xAF, ++0xB7, 0x49, 0xB8, 0x48, 0x4F, 0xF4, 0xED, 0x72, 0xFC, 0xF7, 0x4C, 0xFB, 0x4B, 0xE7, 0x02, 0x2B, 0x08, 0xBF, 0x8B, 0xF8, ++0xDB, 0x90, 0x73, 0xE6, 0x82, 0x42, 0x28, 0xBF, 0x02, 0x46, 0x0A, 0xE7, 0x1F, 0xFA, 0x89, 0xF8, 0x41, 0x46, 0x10, 0x46, ++0xFB, 0xF7, 0x42, 0xFA, 0x00, 0x28, 0x3F, 0xF4, 0x1A, 0xAE, 0xB6, 0xF8, 0xC2, 0x31, 0x82, 0x78, 0x23, 0xF0, 0x07, 0x03, ++0x9B, 0xB2, 0xD1, 0x07, 0x48, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0xA6, 0xF8, 0xC2, 0x31, 0x53, 0x07, 0x7F, 0xF5, 0x0B, 0xAE, ++0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0xB3, 0xF8, 0xC2, 0x21, 0x42, 0xF0, 0x04, 0x02, 0xA3, 0xF8, ++0xC2, 0x21, 0x00, 0xE6, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0xFB, 0xF7, 0x89, 0xFB, 0x9A, 0x4B, 0x93, 0xF8, 0x76, 0xB1, ++0x1B, 0xF0, 0x06, 0x0B, 0x81, 0x46, 0x3F, 0xF4, 0x0B, 0xAE, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0xFB, 0xF7, 0x9C, 0xFB, ++0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x83, 0x46, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0x00, 0xF0, ++0xAA, 0x80, 0x8E, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x59, 0x07, 0x7F, 0xF5, 0xF5, 0xAD, 0x18, 0xEE, 0x90, 0x2A, 0x18, 0xEE, ++0x10, 0x0A, 0x41, 0x46, 0xFD, 0xF7, 0xD6, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x09, 0x81, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x02, 0xA3, 0xD3, 0xF8, 0xC8, 0x31, 0xC3, 0xF3, 0x09, 0x12, 0x15, 0x46, 0xA2, 0xB1, 0x04, 0x23, 0x05, 0x22, ++0x00, 0x21, 0x6F, 0x20, 0xFA, 0xF7, 0xFE, 0xF9, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xA2, 0x06, 0x92, ++0x92, 0xF8, 0x63, 0x10, 0x81, 0x70, 0x05, 0x80, 0xFA, 0xF7, 0x22, 0xFA, 0x06, 0x9A, 0xD2, 0xF8, 0xC8, 0x31, 0x05, 0x9A, ++0x03, 0xF0, 0x7F, 0x43, 0x93, 0x42, 0x3F, 0xF4, 0xC5, 0xAD, 0x04, 0x23, 0x05, 0x22, 0x00, 0x21, 0x71, 0x20, 0xFA, 0xF7, ++0xE3, 0xF9, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0xD3, 0xF8, 0xC8, 0x21, 0xC2, 0xF3, 0x05, 0x63, ++0x52, 0x00, 0x54, 0xBF, 0x43, 0xF4, 0x80, 0x73, 0x43, 0xF4, 0x40, 0x73, 0x03, 0x60, 0xFA, 0xF7, 0x01, 0xFA, 0xAB, 0xE5, ++0x02, 0x9B, 0x03, 0xF5, 0xD6, 0x72, 0x52, 0x44, 0x0D, 0xF1, 0x27, 0x03, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0x06, 0x92, ++0xFD, 0xF7, 0x92, 0xFE, 0x9D, 0xF8, 0x27, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x93, 0xAD, 0x06, 0x9A, 0x06, 0x97, 0x03, 0x9F, ++0x25, 0x46, 0x4C, 0x46, 0x91, 0x46, 0x08, 0x23, 0x05, 0x22, 0x00, 0x21, 0x1A, 0x20, 0xFA, 0xF7, 0xB3, 0xF9, 0x59, 0xF8, ++0x04, 0x1B, 0x80, 0xF8, 0x05, 0xB0, 0x94, 0xF8, 0x63, 0x20, 0x82, 0x71, 0x4F, 0xF0, 0x00, 0x02, 0x01, 0x60, 0x0B, 0xF1, ++0x01, 0x0B, 0x02, 0x71, 0xFA, 0xF7, 0xD4, 0xF9, 0xBB, 0xF1, 0x04, 0x0F, 0xE7, 0xD1, 0x03, 0x97, 0x2C, 0x46, 0x06, 0x9F, ++0x70, 0xE5, 0x00, 0x2A, 0x7F, 0xF4, 0xE5, 0xAE, 0x45, 0x22, 0x4C, 0x49, 0x4D, 0x48, 0xFC, 0xF7, 0x77, 0xFA, 0xD8, 0xF8, ++0x40, 0x20, 0xDC, 0xE6, 0x9B, 0xF8, 0x8C, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x96, 0xAD, 0x9D, 0xF8, 0x25, 0x30, 0x01, 0x2B, ++0x7F, 0xF4, 0x91, 0xAD, 0x46, 0x4B, 0x9B, 0xF8, 0x63, 0x00, 0xD3, 0xF8, 0xC0, 0x31, 0x98, 0x47, 0x9B, 0xF8, 0x8A, 0x10, ++0x00, 0x29, 0x3F, 0xF4, 0x86, 0xAD, 0x7A, 0xE5, 0x5A, 0x45, 0x28, 0xBF, 0x5A, 0x46, 0xD2, 0xB2, 0x21, 0xE6, 0x83, 0x46, ++0x69, 0xE6, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0x06, 0x93, 0xFB, 0xF7, 0x77, 0xF9, 0xB0, 0xB1, 0x06, 0x9B, 0x3A, 0x49, ++0x93, 0xF8, 0x6C, 0x20, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, 0x5B, 0x68, 0x13, 0xF0, 0x24, 0x0F, 0x0A, 0xD0, ++0x90, 0xF9, 0x02, 0x30, 0x81, 0x78, 0x00, 0x2B, 0x05, 0xDB, 0x10, 0x46, 0x0A, 0x09, 0x01, 0xF0, 0x03, 0x01, 0xFF, 0xF7, ++0xDD, 0xFB, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x06, 0x93, 0xD3, 0xF8, 0xCC, 0x31, 0x18, 0x07, ++0x7F, 0xF5, 0x2D, 0xAF, 0x02, 0x23, 0x05, 0x22, 0x00, 0x21, 0x6D, 0x20, 0xFA, 0xF7, 0x46, 0xF9, 0x41, 0x46, 0x02, 0x46, ++0x07, 0x90, 0x18, 0xEE, 0x10, 0x0A, 0xFD, 0xF7, 0x45, 0xFF, 0x07, 0x9A, 0x10, 0x46, 0xFA, 0xF7, 0x6B, 0xF9, 0x22, 0x4B, ++0x1B, 0x69, 0x00, 0x2B, 0x3F, 0xF4, 0x17, 0xAF, 0x02, 0x9B, 0x03, 0xF5, 0xA8, 0x72, 0x18, 0xEE, 0x10, 0x0A, 0x0D, 0xF1, ++0x27, 0x03, 0x52, 0x44, 0x41, 0x46, 0xFD, 0xF7, 0x05, 0xFF, 0x9D, 0xF8, 0x27, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x07, 0xAF, ++0x10, 0x23, 0x05, 0x22, 0x00, 0x21, 0x6B, 0x20, 0xFA, 0xF7, 0x20, 0xF9, 0x06, 0x9A, 0x11, 0x46, 0x15, 0x46, 0xD2, 0xF8, ++0x50, 0xE1, 0xD2, 0xF8, 0x54, 0x21, 0xD1, 0xF8, 0x58, 0x11, 0xD5, 0xF8, 0x5C, 0x51, 0xC5, 0x60, 0xC0, 0xE9, 0x00, 0xE2, ++0x81, 0x60, 0xFA, 0xF7, 0x3F, 0xF9, 0xEE, 0xE6, 0x03, 0x21, 0x28, 0xE6, 0x03, 0x22, 0x33, 0xE6, 0x02, 0x22, 0x31, 0xE6, ++0x02, 0x21, 0x22, 0xE6, 0x40, 0xF2, 0xFF, 0x33, 0x1D, 0x46, 0xFD, 0xE6, 0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xD4, 0xB8, 0x15, 0x00, 0xF4, 0xB8, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x70, 0xB5, 0x0C, 0x46, 0x84, 0xB0, 0x89, 0x78, 0x0C, 0x4D, 0x26, 0x79, 0x8D, 0xF8, 0x04, 0x10, 0xAD, 0xF8, 0x08, 0x20, ++0x01, 0x46, 0x9D, 0xF8, 0x20, 0x20, 0x20, 0x88, 0xE4, 0x78, 0xAD, 0xF8, 0x0A, 0x30, 0xAD, 0xF8, 0x06, 0x00, 0x6B, 0x6C, ++0x8D, 0xF8, 0x0C, 0x60, 0x8D, 0xF8, 0x0D, 0x40, 0x8D, 0xF8, 0x05, 0x20, 0x01, 0xA8, 0x98, 0x47, 0x04, 0xB0, 0x70, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x03, 0x68, 0x30, 0xB4, 0x0C, 0x68, 0x5A, 0x40, 0x84, 0xEA, 0xF2, 0x34, 0x22, 0x44, 0x13, 0x0A, ++0x15, 0x02, 0x05, 0xF0, 0xFF, 0x25, 0x03, 0xF0, 0xFF, 0x13, 0x2B, 0x43, 0x63, 0x40, 0x1A, 0x44, 0x83, 0xEA, 0x72, 0x73, ++0x1A, 0x44, 0x83, 0xEA, 0xB2, 0x03, 0x1A, 0x44, 0x0B, 0x60, 0x30, 0xBC, 0x02, 0x60, 0x70, 0x47, 0xF8, 0xB5, 0x1F, 0x88, ++0xD3, 0xF8, 0x02, 0x50, 0x0B, 0x68, 0x96, 0x88, 0x12, 0x68, 0x03, 0x60, 0x9D, 0xF8, 0x18, 0x40, 0x4B, 0x68, 0x43, 0x60, ++0x00, 0x23, 0xFF, 0x2C, 0x83, 0x60, 0x03, 0x73, 0x00, 0xF1, 0x04, 0x01, 0x46, 0xEA, 0x07, 0x46, 0x14, 0xBF, 0x04, 0xF0, ++0x07, 0x04, 0x00, 0x24, 0xFF, 0xF7, 0xCC, 0xFF, 0x32, 0x46, 0xFF, 0xF7, 0xC9, 0xFF, 0x2A, 0x46, 0xFF, 0xF7, 0xC6, 0xFF, ++0x22, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0xC1, 0xBF, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x21, 0xF0, 0x03, 0x06, ++0x01, 0xF0, 0x03, 0x01, 0xC1, 0xF1, 0x04, 0x03, 0x37, 0x68, 0x90, 0xF8, 0x0C, 0xC0, 0x85, 0x68, 0xDB, 0xB2, 0x04, 0x36, ++0xC9, 0x00, 0x9A, 0x42, 0x83, 0xB0, 0x27, 0xFA, 0x01, 0xF1, 0xB1, 0x46, 0x78, 0xD2, 0xC2, 0xF1, 0x04, 0x04, 0xE3, 0x00, ++0x4F, 0xF0, 0xFF, 0x34, 0x4F, 0xF0, 0x00, 0x0B, 0xDC, 0x40, 0x21, 0x40, 0xD8, 0x46, 0x5F, 0x46, 0x0C, 0xEB, 0x02, 0x04, ++0x03, 0x2C, 0x52, 0xD8, 0x4F, 0xEA, 0xCC, 0x0C, 0x01, 0xFA, 0x0C, 0xF1, 0x0D, 0x43, 0xB8, 0xF1, 0x00, 0x0F, 0x22, 0xD0, ++0xE3, 0x00, 0xC4, 0xF1, 0x04, 0x0A, 0x00, 0x93, 0x4F, 0xEA, 0x88, 0x03, 0x4F, 0xEA, 0xCA, 0x0A, 0x01, 0x1D, 0x01, 0x93, ++0x06, 0xEB, 0x88, 0x08, 0xB1, 0x46, 0xD9, 0xF8, 0x00, 0x30, 0x00, 0x9A, 0x03, 0xFA, 0x02, 0xF2, 0xBA, 0xF1, 0x20, 0x0F, ++0x42, 0xEA, 0x05, 0x02, 0x09, 0xF1, 0x04, 0x09, 0x14, 0xBF, 0x23, 0xFA, 0x0A, 0xF5, 0x00, 0x25, 0xFF, 0xF7, 0x76, 0xFF, ++0xC1, 0x45, 0xEC, 0xD1, 0x01, 0x9B, 0x33, 0x44, 0x99, 0x46, 0x5F, 0x45, 0x20, 0xD9, 0x07, 0xF0, 0x03, 0x07, 0xC7, 0xF1, ++0x04, 0x03, 0xDA, 0x00, 0x20, 0x2A, 0xD9, 0xF8, 0x00, 0x10, 0x40, 0xD0, 0x4F, 0xF0, 0xFF, 0x33, 0xD3, 0x40, 0x0B, 0x40, ++0xE2, 0x00, 0x03, 0xFA, 0x02, 0xF2, 0x15, 0x43, 0x27, 0x44, 0x03, 0x2F, 0x2F, 0xD9, 0xC4, 0xF1, 0x04, 0x04, 0xE4, 0x00, ++0x20, 0x2C, 0x14, 0xBF, 0xE3, 0x40, 0x00, 0x23, 0x2A, 0x46, 0x01, 0x1D, 0x3C, 0x1F, 0x1D, 0x46, 0xFF, 0xF7, 0x4E, 0xFF, ++0x85, 0x60, 0x04, 0x73, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xEA, 0xCC, 0x02, 0xCC, 0xF1, 0x04, 0x0C, 0x4F, 0xEA, ++0xCC, 0x0C, 0xBC, 0xF1, 0x20, 0x0F, 0x01, 0xFA, 0x02, 0xF2, 0x42, 0xEA, 0x05, 0x02, 0x18, 0xBF, 0x21, 0xFA, 0x0C, 0xF5, ++0x00, 0xF1, 0x04, 0x01, 0x08, 0xBF, 0x00, 0x25, 0x04, 0x3C, 0xFF, 0xF7, 0x33, 0xFF, 0x9A, 0xE7, 0xD7, 0x1A, 0x4F, 0xEA, ++0x97, 0x08, 0x1A, 0x46, 0x27, 0xF0, 0x03, 0x0B, 0x8A, 0xE7, 0x3C, 0x46, 0x85, 0x60, 0x04, 0x73, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0x23, 0xC4, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x10, 0x4B, 0x85, 0x68, 0x1B, 0x68, 0x02, 0x7B, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x0D, 0xDB, 0x5A, 0x23, 0xD2, 0x00, 0x03, 0xFA, 0x02, 0xF2, 0x2A, 0x43, 0x21, 0x1D, ++0x20, 0x46, 0xFF, 0xF7, 0x0F, 0xFF, 0xBD, 0xE8, 0x38, 0x40, 0x00, 0x22, 0xFF, 0xF7, 0x0A, 0xBF, 0x03, 0x2A, 0xEF, 0xD9, ++0x40, 0xF2, 0x41, 0x12, 0x03, 0x49, 0x04, 0x48, 0xFC, 0xF7, 0xB8, 0xF8, 0x22, 0x7B, 0xE7, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x20, 0xB9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x06, 0x20, 0x83, 0xB0, 0x00, 0x24, 0xCD, 0xE9, ++0x00, 0x44, 0x91, 0xF8, 0x3D, 0x90, 0x0D, 0x46, 0x17, 0x46, 0x1E, 0x46, 0xFA, 0xF7, 0x62, 0xFA, 0x09, 0x28, 0x79, 0xD0, ++0x01, 0x23, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF6, 0x01, 0x00, 0xF9, 0xF7, 0xB7, 0xFF, 0x80, 0x46, 0x06, 0x20, 0xFA, 0xF7, ++0x55, 0xFA, 0x48, 0xB1, 0x08, 0x26, 0x40, 0x46, 0x88, 0xF8, 0x00, 0x60, 0xF9, 0xF7, 0xDC, 0xFF, 0x20, 0x46, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, 0xAC, 0xA1, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0xA3, 0x93, 0xF8, 0x62, 0x20, ++0x00, 0x2A, 0x4F, 0xD1, 0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x4B, 0xD1, 0xDF, 0xF8, 0x94, 0xB1, 0x5A, 0x4A, 0x5B, 0x49, ++0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x95, 0xF8, 0x3B, 0x30, 0x01, 0x22, 0x02, 0x2B, 0xCA, 0x75, 0x0E, 0xD0, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0xA2, 0x92, 0xF8, 0x64, 0x10, 0x29, 0xB9, 0x53, 0x4C, 0x21, 0x68, 0xB1, 0xF9, ++0x00, 0x10, 0x00, 0x29, 0x7F, 0xDB, 0x03, 0x2B, 0x57, 0xD0, 0x3A, 0x46, 0x4F, 0xF4, 0x55, 0x73, 0x31, 0x46, 0x41, 0xF6, ++0x02, 0x00, 0xCB, 0xF8, 0x00, 0x50, 0xF9, 0xF7, 0x73, 0xFF, 0x95, 0xF8, 0x3B, 0x30, 0xCB, 0xF8, 0x04, 0x00, 0x00, 0x27, ++0x02, 0x2B, 0x8B, 0xF8, 0x16, 0x70, 0x4F, 0xD0, 0x9B, 0xF8, 0x1E, 0x60, 0x3E, 0xB3, 0x95, 0xF8, 0x3D, 0x10, 0x44, 0x48, ++0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x01, 0xA1, 0x06, 0x22, 0x38, 0x31, 0x0E, 0xF0, 0xE4, 0xFA, 0x09, 0x21, 0x06, 0x20, ++0xFA, 0xF7, 0x52, 0xF9, 0x95, 0xF8, 0x3D, 0x00, 0x39, 0x46, 0x04, 0xFB, 0x00, 0xA0, 0x01, 0xF0, 0xCB, 0xF8, 0x3E, 0x46, ++0x01, 0x24, 0x9C, 0xE7, 0x95, 0xF8, 0x3B, 0x30, 0x02, 0x2B, 0xAF, 0xD0, 0x2C, 0x6B, 0x14, 0xF0, 0x20, 0x04, 0x17, 0xD1, ++0x09, 0x26, 0x92, 0xE7, 0x02, 0x24, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0xA9, 0x68, 0x46, 0x00, 0xF0, ++0x75, 0xFD, 0xDD, 0xE9, 0x00, 0x01, 0x28, 0xB1, 0x21, 0xB1, 0x32, 0x46, 0x00, 0xF0, 0x14, 0xFE, 0x01, 0x24, 0x80, 0xE7, ++0x00, 0xF0, 0x90, 0xFD, 0x01, 0x24, 0x7C, 0xE7, 0xDF, 0xF8, 0xBC, 0xB0, 0x28, 0x48, 0x01, 0x23, 0x8B, 0xF8, 0x1E, 0x30, ++0xFB, 0xF7, 0x8E, 0xFD, 0x8C, 0xE7, 0xE9, 0x8E, 0x05, 0xF1, 0x40, 0x00, 0x02, 0xF0, 0x32, 0xF8, 0x00, 0x28, 0xC4, 0xBF, ++0x00, 0x23, 0x85, 0xF8, 0x3B, 0x30, 0x9C, 0xE7, 0x95, 0xF8, 0x3D, 0x10, 0x1F, 0x48, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, ++0x01, 0xA1, 0x06, 0x22, 0x38, 0x31, 0x01, 0x24, 0x8B, 0xF8, 0x16, 0x40, 0x0E, 0xF0, 0x94, 0xFA, 0x09, 0x21, 0x06, 0x20, ++0xFA, 0xF7, 0x02, 0xF9, 0x95, 0xF8, 0x3D, 0x00, 0x39, 0x46, 0x06, 0xFB, 0x00, 0xA0, 0x01, 0xF0, 0x7B, 0xF8, 0x3E, 0x46, ++0x4D, 0xE7, 0x92, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x09, 0xD0, 0x12, 0x49, 0x12, 0x48, 0x64, 0x22, 0xFB, 0xF7, 0xD8, 0xFF, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0B, 0xDA, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0xA9, 0xD9, 0xF8, ++0x40, 0x30, 0x23, 0xB1, 0x09, 0x49, 0x0B, 0x48, 0x65, 0x22, 0xFB, 0xF7, 0xC7, 0xFF, 0x95, 0xF8, 0x3B, 0x30, 0x62, 0xE7, ++0x94, 0x40, 0x04, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x84, 0xBA, 0x17, 0x00, 0x40, 0xB9, 0x15, 0x00, ++0x7C, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x4C, 0xB9, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x64, 0xBA, 0x17, 0x00, 0x38, 0xB5, 0x0B, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0F, 0x49, 0x1C, 0x78, 0xFB, 0xF7, 0x7C, 0xFD, ++0x06, 0x20, 0xFA, 0xF7, 0x63, 0xF9, 0xA8, 0xB9, 0x0C, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, ++0x62, 0x50, 0x15, 0xB9, 0x94, 0xF8, 0x64, 0x00, 0x00, 0xB9, 0x38, 0xBD, 0x09, 0x21, 0x06, 0x20, 0xFA, 0xF7, 0xAA, 0xF8, ++0x20, 0x46, 0x01, 0x21, 0x01, 0xF0, 0x26, 0xF8, 0x28, 0x46, 0x38, 0xBD, 0x02, 0x20, 0x38, 0xBD, 0x70, 0xB9, 0x15, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x08, 0xB5, 0x06, 0x20, 0xFA, 0xF7, 0x42, 0xF9, 0x05, 0x28, 0x04, 0xD0, 0x06, 0x20, 0xFA, 0xF7, ++0x3D, 0xF9, 0x06, 0x28, 0x04, 0xD1, 0x01, 0x20, 0x01, 0xF0, 0x9C, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xFA, 0xF7, ++0x33, 0xF9, 0x07, 0x28, 0xF5, 0xD0, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x16, 0x4B, 0x00, 0xB5, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x20, 0x00, 0x23, 0x83, 0xB0, 0x9A, 0x42, 0xCD, 0xE9, 0x00, 0x33, 0x15, 0xDB, 0x68, 0x46, 0x01, 0xA9, 0x00, 0xF0, ++0xB7, 0xFC, 0x00, 0x98, 0x40, 0xB1, 0x01, 0x99, 0x31, 0xB1, 0x00, 0x22, 0x00, 0xF0, 0x56, 0xFD, 0x00, 0x20, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0xFB, 0x01, 0x20, 0x01, 0xF0, 0x75, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x06, 0x20, ++0xFA, 0xF7, 0x0A, 0xF9, 0x01, 0x28, 0xE4, 0xD0, 0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x8F, 0x72, 0xFB, 0xF7, 0x42, 0xFF, ++0xDD, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x80, 0xB9, 0x15, 0x00, 0x93, 0x4B, 0x2D, 0xE9, ++0xF0, 0x4F, 0x1B, 0x68, 0x92, 0x4D, 0xB3, 0xF9, 0x00, 0x30, 0x2F, 0x68, 0x00, 0x2B, 0x89, 0xB0, 0xC0, 0xF2, 0x91, 0x80, ++0x97, 0xF8, 0x3D, 0x80, 0x8E, 0x4E, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x08, 0x64, 0xD4, 0xF8, 0xCC, 0x31, 0x00, 0x2B, ++0x18, 0xDB, 0x6B, 0x7D, 0x33, 0xB9, 0x01, 0x20, 0x01, 0xF0, 0x42, 0xF9, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x00, 0x23, 0x07, 0xA9, 0x06, 0xA8, 0xCD, 0xE9, 0x06, 0x33, 0x00, 0xF0, 0x6B, 0xFC, 0xDD, 0xE9, 0x06, 0x01, 0x01, 0x22, ++0x00, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x07, 0xA8, 0x00, 0xF0, 0xE1, 0xFD, 0x00, 0x28, ++0x74, 0xD1, 0x01, 0x46, 0x20, 0x23, 0x06, 0x22, 0x0A, 0x20, 0xF9, 0xF7, 0x1D, 0xFE, 0x94, 0xF8, 0xC0, 0x34, 0x05, 0x46, ++0x2B, 0xB1, 0xD4, 0xF8, 0xCC, 0x21, 0x22, 0xF0, 0x08, 0x02, 0xC4, 0xF8, 0xCC, 0x21, 0x74, 0x4A, 0x92, 0xF8, 0x04, 0x21, ++0x4A, 0xB1, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x08, 0xF2, 0xB1, 0x18, 0xD1, 0xF8, 0x90, 0x01, 0x80, 0x78, 0x01, 0x28, ++0x6D, 0xD0, 0x6E, 0x4B, 0x97, 0xF8, 0x3D, 0x00, 0xDB, 0x6C, 0x9D, 0xF8, 0x1C, 0x10, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x6B, ++0x00, 0x23, 0x2B, 0x60, 0x0B, 0xFB, 0x08, 0xFB, 0x97, 0xF8, 0x3D, 0x20, 0x6A, 0x76, 0x06, 0xEB, 0x0B, 0x0A, 0xDA, 0xF8, ++0x64, 0x01, 0xBA, 0xF8, 0x68, 0x21, 0xAB, 0x76, 0x9A, 0xF8, 0x8B, 0x31, 0x6B, 0x77, 0x9A, 0xF8, 0x8C, 0x31, 0xAB, 0x77, ++0xDA, 0xF8, 0xCC, 0x31, 0xC5, 0xF8, 0x12, 0x00, 0x13, 0xF0, 0x02, 0x04, 0xEA, 0x82, 0x1B, 0xD0, 0x0B, 0xF1, 0xEC, 0x09, ++0x13, 0xF0, 0x04, 0x04, 0xB1, 0x44, 0x6E, 0xD1, 0x21, 0x46, 0x13, 0xF0, 0x08, 0x02, 0x05, 0xF1, 0x18, 0x03, 0x18, 0xBF, ++0x0B, 0xF5, 0x8C, 0x72, 0x05, 0xF1, 0x04, 0x0C, 0x02, 0x93, 0x05, 0xF1, 0x08, 0x03, 0xCD, 0xE9, 0x00, 0x3C, 0x18, 0xBF, ++0x92, 0x19, 0x48, 0x46, 0x05, 0xF1, 0x10, 0x03, 0xFE, 0xF7, 0x22, 0xFC, 0x28, 0x46, 0xEC, 0x60, 0xF9, 0xF7, 0xF0, 0xFD, ++0x03, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0xB6, 0xFF, 0x0F, 0xE0, 0x06, 0x20, 0xFA, 0xF7, 0x5A, 0xF8, 0x02, 0x28, 0x3F, 0xF4, ++0x69, 0xAF, 0x47, 0x49, 0x47, 0x48, 0x4F, 0xF4, 0xA3, 0x72, 0xFB, 0xF7, 0x91, 0xFE, 0x61, 0xE7, 0x01, 0x20, 0x01, 0xF0, ++0xB1, 0xF8, 0x3A, 0x6B, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x66, 0x53, 0x07, 0xC6, 0xF8, 0xB0, 0x24, 0x7F, 0xF5, ++0x65, 0xAF, 0xD6, 0xF8, 0xCC, 0x31, 0x00, 0x20, 0x23, 0xF0, 0x0E, 0x03, 0xC6, 0xF8, 0xCC, 0x31, 0x09, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0xD1, 0xF8, 0xCC, 0x11, 0x11, 0xF0, 0x0C, 0x0F, 0x8C, 0xD0, 0x00, 0x2B, 0x8A, 0xD1, 0xDF, 0xF8, 0xD8, 0x90, ++0x02, 0xF5, 0xB2, 0x72, 0xB4, 0x18, 0x9A, 0x46, 0xCB, 0x46, 0x58, 0x46, 0x06, 0x22, 0x21, 0x46, 0x0E, 0xF0, 0xDC, 0xF8, ++0x0B, 0xF1, 0x14, 0x0B, 0x18, 0xB3, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x05, 0x0F, 0xF2, 0xD1, 0x2C, 0x49, 0x50, 0x22, ++0x01, 0xF1, 0x14, 0x00, 0x0E, 0xF0, 0xFE, 0xF8, 0x29, 0x48, 0x21, 0x46, 0x06, 0x22, 0x0E, 0xF0, 0xF9, 0xF8, 0x01, 0x23, ++0xA9, 0xF8, 0x06, 0x30, 0x89, 0xF8, 0x08, 0x30, 0x65, 0xE7, 0x0B, 0xF5, 0xB2, 0x70, 0x0B, 0xF5, 0x86, 0x71, 0x31, 0x44, ++0x30, 0x44, 0x05, 0x91, 0xFA, 0xF7, 0x28, 0xFF, 0xDA, 0xF8, 0xCC, 0x31, 0x05, 0x99, 0x04, 0x46, 0x83, 0xE7, 0x0A, 0xEB, ++0x8A, 0x03, 0x09, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0x8A, 0x0B, 0x9A, 0x79, 0x14, 0x23, 0x03, 0xFB, 0x0A, 0x93, 0x4A, 0xB1, ++0xDB, 0x79, 0x53, 0xB1, 0x0B, 0xEB, 0x0A, 0x03, 0x09, 0xEB, 0x83, 0x09, 0x01, 0x23, 0x89, 0xF8, 0x08, 0x30, 0x42, 0xE7, ++0x01, 0x22, 0x9A, 0x71, 0xF4, 0xE7, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x08, 0x64, 0x00, 0x92, 0xB4, 0xF8, 0x68, 0x31, ++0xB4, 0xF8, 0x66, 0x21, 0xB4, 0xF8, 0x64, 0x11, 0x0C, 0x48, 0xFB, 0xF7, 0x9F, 0xFB, 0xD4, 0xF8, 0xCC, 0x31, 0x23, 0xF0, ++0x0C, 0x03, 0xC4, 0xF8, 0xCC, 0x31, 0xDF, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x2C, 0x19, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xB9, 0x15, 0x00, 0xCC, 0x35, 0x17, 0x00, ++0xCC, 0xB9, 0x15, 0x00, 0x08, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x06, 0x20, ++0xF9, 0xF7, 0xB6, 0xFF, 0x04, 0x28, 0x06, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0xB1, 0xFF, 0x09, 0x28, 0x01, 0xD0, 0x00, 0x20, ++0x08, 0xBD, 0x00, 0xF0, 0xF5, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0xA6, 0xFF, 0x04, 0x28, 0xEA, 0xD0, ++0x06, 0x20, 0xF9, 0xF7, 0xA1, 0xFF, 0x00, 0x28, 0xE5, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0x9C, 0xFF, 0x09, 0x28, 0xE0, 0xD0, ++0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x16, 0x72, 0xFB, 0xF7, 0xD4, 0xFD, 0xD9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xE4, 0xB9, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x03, 0xDB, 0x00, 0xF0, 0xCD, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x7E, 0xFF, 0x04, 0x28, 0xF6, 0xD0, ++0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x79, 0x22, 0xFB, 0xF7, 0xB6, 0xFD, 0x00, 0xF0, 0xBE, 0xFC, 0x00, 0x20, 0x08, 0xBD, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x6C, 0xBA, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0xAD, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x5E, 0xFF, ++0x09, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x29, 0x32, 0xFB, 0xF7, 0x96, 0xFD, 0x00, 0xF0, 0x9E, 0xFC, ++0x00, 0x20, 0x08, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x9C, 0xBA, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0x8D, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, ++0xF9, 0xF7, 0x3E, 0xFF, 0x09, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x43, 0x32, 0xFB, 0xF7, 0x76, 0xFD, ++0x00, 0xF0, 0x7E, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x9C, 0xBA, 0x15, 0x00, ++0x37, 0x4B, 0x30, 0xB5, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x83, 0xB0, 0x37, 0xDB, 0x06, 0x20, 0xF9, 0xF7, ++0x21, 0xFF, 0x09, 0x28, 0x10, 0xD0, 0x32, 0x4B, 0x9A, 0x7D, 0x01, 0x2A, 0x50, 0xD0, 0x1B, 0x68, 0x93, 0xF8, 0x3B, 0x30, ++0x02, 0x2B, 0x3A, 0xD9, 0x03, 0x2B, 0x3F, 0xD1, 0x2D, 0x48, 0x01, 0xF0, 0xF5, 0xFC, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, ++0x29, 0x4C, 0xA2, 0x6A, 0x23, 0x7D, 0x00, 0x25, 0xC2, 0xF8, 0xCC, 0x51, 0x00, 0x2B, 0x40, 0xD1, 0xA0, 0x68, 0x0C, 0x30, ++0xF9, 0xF7, 0x90, 0xFC, 0xA3, 0x7D, 0x00, 0x22, 0x01, 0x2B, 0xA2, 0x60, 0x01, 0xD0, 0xA1, 0x7F, 0x61, 0xB3, 0x00, 0x24, ++0x01, 0xA9, 0x68, 0x46, 0xCD, 0xE9, 0x00, 0x44, 0x00, 0xF0, 0x8C, 0xFA, 0xDD, 0xE9, 0x00, 0x01, 0x22, 0x46, 0x00, 0xF0, ++0x2D, 0xFB, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0xE9, 0xFE, 0x04, 0x28, 0xC2, 0xD0, 0x06, 0x20, ++0xF9, 0xF7, 0xE4, 0xFE, 0x09, 0x28, 0xBD, 0xD0, 0x15, 0x49, 0x16, 0x48, 0x40, 0xF2, 0x93, 0x22, 0xFB, 0xF7, 0x1C, 0xFD, ++0xB6, 0xE7, 0x00, 0x21, 0x01, 0x20, 0x01, 0xF0, 0x2B, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x01, 0x20, 0x00, 0xF0, ++0x35, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x23, 0xFE, 0xDA, 0xE7, 0x01, 0xF0, 0x48, 0xF9, ++0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x04, 0x00, 0xF9, 0xF7, 0x85, 0xFC, 0x25, 0x75, ++0xB6, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x08, 0xAC, 0x0F, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0xBA, 0x15, 0x00, 0x4B, 0x88, 0x03, 0xF0, 0xFC, 0x03, 0xB0, 0x2B, 0x10, 0xB5, 0x0C, 0x46, 0x13, 0xD0, 0x10, 0x2B, ++0x0A, 0xD0, 0x30, 0x2B, 0x08, 0xD0, 0xC0, 0x2B, 0x01, 0xD0, 0xA0, 0x2B, 0x14, 0xD1, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, ++0x01, 0xF0, 0x78, 0xBB, 0x06, 0x20, 0xF9, 0xF7, 0x9B, 0xFE, 0x07, 0x28, 0x13, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x06, 0x20, ++0xF9, 0xF7, 0x94, 0xFE, 0x05, 0x28, 0xF8, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0x37, 0xFA, 0xF4, 0xE7, 0xD0, 0x2B, 0xF2, 0xD1, ++0x23, 0x7B, 0x08, 0x2B, 0xEF, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0xD4, 0xFB, 0xEB, 0xE7, 0x20, 0x46, 0x01, 0xF0, 0x70, 0xFA, ++0xE7, 0xE7, 0x00, 0xBF, 0x10, 0xB5, 0x06, 0x20, 0x0C, 0x46, 0xF9, 0xF7, 0x7B, 0xFE, 0x06, 0x28, 0x01, 0xD0, 0x00, 0x20, ++0x10, 0xBD, 0x60, 0x88, 0x01, 0xF0, 0xC8, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4C, 0x0D, 0x4A, 0x23, 0x68, 0xD2, 0x7D, 0x01, 0x33, ++0x01, 0x2A, 0x23, 0x60, 0x0C, 0xD0, 0x33, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x07, 0x48, 0xFB, 0xF7, 0x1C, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0x00, 0xF0, 0x16, 0xFB, 0x23, 0x68, 0xEE, 0xE7, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x28, 0xBB, 0x15, 0x00, 0x38, 0xB5, 0x06, 0x20, ++0x0D, 0x46, 0xF9, 0xF7, 0x43, 0xFE, 0x30, 0xB9, 0x04, 0x46, 0x29, 0x88, 0xA8, 0x78, 0x00, 0xF0, 0xB7, 0xFD, 0x20, 0x46, ++0x38, 0xBD, 0x02, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x8B, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x89, 0xB0, 0x0C, 0x46, 0xC0, 0xF2, 0xFD, 0x80, 0x25, 0x78, 0x00, 0x2D, 0x40, 0xF0, 0xF2, 0x80, 0x63, 0x78, ++0x00, 0x93, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x03, 0xF4, 0x82, 0x4B, 0xDF, 0xF8, 0x18, 0xA2, 0x1F, 0x19, 0x4F, 0xF4, ++0xA4, 0x6C, 0x97, 0xF8, 0x22, 0xE0, 0x0C, 0xFB, 0x0E, 0xAC, 0x0C, 0xF5, 0xCE, 0x73, 0x0F, 0xCB, 0x07, 0xF1, 0xB8, 0x06, ++0x07, 0xC6, 0xDC, 0xF8, 0xCC, 0x81, 0x33, 0x70, 0x18, 0xF0, 0x01, 0x0F, 0x03, 0xD0, 0x7B, 0x68, 0x43, 0xF0, 0x01, 0x03, ++0x7B, 0x60, 0x18, 0xF0, 0x02, 0x0F, 0x58, 0xD0, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x0E, 0xA3, 0x03, 0xF1, 0xEC, 0x0B, ++0x00, 0x9E, 0x01, 0x93, 0xBB, 0xE8, 0x0F, 0x00, 0xB4, 0x46, 0x6E, 0x4E, 0x4F, 0xF4, 0x1E, 0x79, 0x09, 0xFB, 0x0C, 0x69, ++0x09, 0xF1, 0xC8, 0x0C, 0xAC, 0xE8, 0x0F, 0x00, 0x9B, 0xE8, 0x0F, 0x00, 0xD9, 0xF8, 0x04, 0xB0, 0x18, 0xF0, 0x08, 0x0F, ++0x4B, 0xF0, 0x02, 0x06, 0x8C, 0xE8, 0x0F, 0x00, 0xC9, 0xF8, 0x04, 0x60, 0x15, 0xD0, 0x01, 0x9B, 0x03, 0xF5, 0x8C, 0x76, ++0x0F, 0xCE, 0x09, 0xF1, 0xF4, 0x0C, 0xAC, 0xE8, 0x0F, 0x00, 0x0F, 0xCE, 0xAC, 0xE8, 0x0F, 0x00, 0x0F, 0xCE, 0xAC, 0xE8, ++0x0F, 0x00, 0x96, 0xE8, 0x03, 0x00, 0x8C, 0xE8, 0x03, 0x00, 0x4B, 0xF0, 0x22, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0x18, 0xF0, ++0x04, 0x0F, 0x16, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x00, 0x9E, 0x03, 0xFB, 0x0E, 0xA3, 0x03, 0xF5, 0x86, 0x73, 0x93, 0xE8, ++0x07, 0x00, 0xB4, 0x46, 0x51, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x0C, 0x63, 0x03, 0xF1, 0xE8, 0x06, 0x86, 0xE8, ++0x07, 0x00, 0x5A, 0x68, 0x42, 0xF0, 0x04, 0x02, 0x5A, 0x60, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x0E, 0xA1, 0xEC, 0x31, ++0x38, 0x46, 0xFE, 0xF7, 0x81, 0xF8, 0x48, 0x4B, 0xD3, 0xF8, 0x14, 0x33, 0x98, 0x47, 0x47, 0x4B, 0x1B, 0x78, 0x00, 0x2B, ++0x66, 0xD0, 0x00, 0x9A, 0x42, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, 0x93, 0xF8, 0xB8, 0x20, 0x00, 0x23, ++0xCD, 0xE9, 0x02, 0x33, 0xCD, 0xE9, 0x05, 0x33, 0x04, 0x93, 0x07, 0x93, 0x00, 0x2A, 0x70, 0xD0, 0x01, 0x3A, 0xD2, 0xB2, ++0xB8, 0x34, 0x02, 0xAE, 0x0D, 0xF1, 0x14, 0x0C, 0x9B, 0x46, 0x0D, 0xF1, 0x09, 0x03, 0x01, 0x92, 0x0C, 0x44, 0x03, 0xEB, ++0x02, 0x09, 0x31, 0x46, 0x62, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0x40, 0xF2, 0x05, 0x2A, 0x07, 0xE0, 0x01, 0xF8, 0x01, 0x0B, ++0x49, 0x45, 0x82, 0xF8, 0x00, 0x80, 0x02, 0xF1, 0x01, 0x02, 0x14, 0xD0, 0x14, 0xF8, 0x01, 0x0F, 0x00, 0xF0, 0x7F, 0x03, ++0x02, 0x3B, 0xDB, 0xB2, 0x09, 0x2B, 0x08, 0xFA, 0x03, 0xFE, 0xED, 0xD8, 0x1E, 0xEA, 0x0A, 0x0F, 0xEA, 0xD0, 0x01, 0xF8, ++0x01, 0x0B, 0x49, 0x45, 0x82, 0xF8, 0x00, 0xB0, 0x02, 0xF1, 0x01, 0x02, 0xEA, 0xD1, 0x01, 0x9A, 0x0C, 0xF1, 0x01, 0x03, ++0x1A, 0x44, 0x11, 0x46, 0x00, 0x9A, 0x10, 0x46, 0x1E, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x24, 0x00, 0xE0, ++0x01, 0x33, 0x9C, 0xF8, 0x00, 0x20, 0x9C, 0x46, 0x2A, 0xB1, 0x62, 0x19, 0x30, 0x78, 0x82, 0xF8, 0xB9, 0x00, 0x01, 0x35, ++0xED, 0xB2, 0x8B, 0x42, 0x06, 0xF1, 0x01, 0x06, 0xF0, 0xD1, 0x00, 0x9A, 0x11, 0x46, 0x13, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x01, 0x23, 0x83, 0xF8, 0xB8, 0x50, 0x38, 0x46, 0xFE, 0xF7, 0x1D, 0xFA, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x01, 0x20, 0x00, 0xF0, 0x98, 0xFD, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x20, 0xF9, 0xF7, ++0x2D, 0xFD, 0x03, 0x28, 0x3F, 0xF4, 0xFD, 0xAE, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF2, 0xF1, 0x12, 0xFB, 0xF7, 0x64, 0xFB, ++0xF5, 0xE6, 0x15, 0x46, 0xD9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xB8, 0x34, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0xBB, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0xB5, 0x06, 0x20, ++0xF9, 0xF7, 0x0E, 0xFD, 0x08, 0x28, 0x06, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0x09, 0xFD, 0x09, 0x28, 0x33, 0xD0, 0x00, 0x20, ++0x70, 0xBD, 0x22, 0x4A, 0x22, 0x4B, 0x14, 0x68, 0x94, 0xF8, 0x3D, 0x60, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x06, 0x36, ++0x06, 0x23, 0x1A, 0x46, 0x00, 0x21, 0x4B, 0x20, 0x96, 0xF8, 0x6C, 0x50, 0xF9, 0xF7, 0x52, 0xFA, 0x94, 0xF8, 0x3A, 0x20, ++0x02, 0x71, 0x22, 0x8F, 0x42, 0x80, 0x94, 0xF8, 0x3D, 0x20, 0x02, 0x70, 0xF9, 0xF7, 0x78, 0xFA, 0xD6, 0xF8, 0xB0, 0x34, ++0x15, 0x4A, 0xA1, 0x8E, 0x4F, 0xF4, 0x1E, 0x70, 0x03, 0xF0, 0x01, 0x03, 0x00, 0xFB, 0x05, 0x22, 0xC3, 0xF1, 0x02, 0x03, ++0x49, 0xBA, 0x02, 0x2B, 0x82, 0xF8, 0x30, 0x30, 0x91, 0x86, 0x08, 0xD0, 0x00, 0x20, 0x00, 0xF0, 0x39, 0xFD, 0x00, 0x20, ++0x70, 0xBD, 0x00, 0xF0, 0x1B, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF9, 0xF7, ++0x27, 0xFA, 0x00, 0x22, 0x02, 0x70, 0x94, 0xF8, 0x3D, 0x20, 0x42, 0x70, 0xF9, 0xF7, 0x50, 0xFA, 0xE8, 0xE7, 0x00, 0xBF, ++0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0xB5, 0x06, 0x46, 0x06, 0x20, 0x0D, 0x46, ++0xF9, 0xF7, 0xB4, 0xFC, 0x2B, 0x46, 0x02, 0x46, 0x0A, 0x49, 0x04, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFB, 0xF7, 0xC2, 0xF8, ++0x08, 0x4B, 0x1D, 0x42, 0x04, 0xD0, 0x24, 0xF0, 0x02, 0x01, 0x89, 0xB2, 0x05, 0x29, 0x00, 0xD0, 0x70, 0xBD, 0x30, 0x46, ++0xE6, 0xF7, 0xDC, 0xFC, 0x01, 0x23, 0x86, 0xF8, 0x5E, 0x30, 0x70, 0xBD, 0x70, 0xBB, 0x15, 0x00, 0x00, 0x00, 0x03, 0x40, ++0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x08, 0x40, 0x09, 0x48, ++0xF9, 0xF7, 0x74, 0xBE, 0x08, 0x4B, 0xDB, 0x68, 0x00, 0x2B, 0xF6, 0xD0, 0x07, 0x48, 0x08, 0x49, 0x70, 0x22, 0xFB, 0xF7, ++0xC3, 0xFA, 0xBD, 0xE8, 0x08, 0x40, 0x02, 0x48, 0xF9, 0xF7, 0x66, 0xBE, 0x38, 0x36, 0x17, 0x00, 0x70, 0xBA, 0x17, 0x00, ++0x64, 0xBA, 0x17, 0x00, 0x80, 0xBB, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x03, 0x4A, 0x04, 0x4B, 0x00, 0x21, 0x06, 0x20, ++0xD1, 0x75, 0x19, 0x60, 0xF9, 0xF7, 0xC4, 0xBB, 0x4C, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x70, 0xB5, 0x11, 0x4B, ++0x1E, 0x68, 0x00, 0x23, 0x03, 0x60, 0x0B, 0x60, 0x96, 0xF8, 0x22, 0x30, 0xDB, 0x07, 0x05, 0x46, 0x0C, 0x46, 0x08, 0xD5, ++0x30, 0x46, 0x03, 0xF0, 0x57, 0xFB, 0x58, 0xB1, 0x83, 0x1C, 0x2B, 0x60, 0xC3, 0x6A, 0x23, 0x60, 0x70, 0xBD, 0x06, 0xF1, ++0x22, 0x00, 0x28, 0x60, 0x03, 0xF0, 0x46, 0xFB, 0x00, 0x28, 0xF5, 0xD1, 0x32, 0x8D, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, ++0x1C, 0xBF, 0x28, 0x36, 0x26, 0x60, 0x70, 0xBD, 0x64, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x3B, 0x4C, 0x4F, 0xF4, ++0xBA, 0x73, 0x06, 0x22, 0x84, 0xB0, 0x80, 0x46, 0x0F, 0x46, 0x4F, 0xF4, 0x80, 0x50, 0x04, 0x21, 0x25, 0x68, 0xF9, 0xF7, ++0x91, 0xF9, 0x95, 0xF8, 0x3D, 0x30, 0x80, 0xF8, 0x6E, 0x31, 0x04, 0x46, 0x0F, 0xCD, 0x4F, 0xF0, 0x00, 0x0C, 0x04, 0xF1, ++0xFC, 0x06, 0xC4, 0xF8, 0x68, 0xC1, 0xA4, 0xF8, 0x6C, 0xC1, 0x0F, 0xC6, 0x0F, 0xCD, 0x0F, 0xC6, 0x01, 0x23, 0x2A, 0x68, ++0x32, 0x70, 0x84, 0xF8, 0x70, 0x31, 0xB8, 0xF1, 0x00, 0x0F, 0x19, 0xD0, 0xD8, 0xF8, 0x00, 0x00, 0xC4, 0xF8, 0x60, 0x01, ++0xB8, 0xF8, 0x04, 0x30, 0xA4, 0xF8, 0x64, 0x31, 0xCF, 0xB1, 0x38, 0x68, 0x20, 0x60, 0xBB, 0x88, 0xA3, 0x80, 0x01, 0x23, ++0x84, 0xF8, 0x6F, 0x31, 0x20, 0x46, 0xF9, 0xF7, 0x95, 0xF9, 0x01, 0x21, 0x06, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x41, ++0xF9, 0xF7, 0x58, 0xBB, 0x1C, 0x4B, 0x18, 0x68, 0x9B, 0x88, 0xC4, 0xF8, 0x60, 0x01, 0xA4, 0xF8, 0x64, 0x31, 0x00, 0x2F, ++0xE5, 0xD1, 0x19, 0x4B, 0x02, 0x93, 0x93, 0xF8, 0xFD, 0x50, 0x93, 0xF8, 0xFC, 0x00, 0x8D, 0xF8, 0x05, 0x50, 0x03, 0xF1, ++0x54, 0x02, 0x03, 0x92, 0x84, 0xF8, 0x6F, 0x71, 0x0D, 0xF1, 0x08, 0x0C, 0x06, 0x26, 0xB8, 0xB1, 0x5C, 0xF8, 0x27, 0x30, ++0x16, 0xFB, 0x00, 0x30, 0xDA, 0x78, 0x92, 0x07, 0x0D, 0xD4, 0x94, 0xF8, 0x6F, 0x21, 0x51, 0x1C, 0x84, 0xF8, 0x6F, 0x11, ++0x02, 0xEB, 0x42, 0x02, 0x19, 0x68, 0x44, 0xF8, 0x12, 0x10, 0x04, 0xEB, 0x42, 0x02, 0x99, 0x88, 0x91, 0x80, 0x06, 0x33, ++0x83, 0x42, 0xEB, 0xD1, 0x00, 0x2F, 0xC1, 0xD1, 0x28, 0x46, 0x01, 0x27, 0xE1, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, ++0xAC, 0xB2, 0x15, 0x00, 0x5A, 0xB9, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x8B, 0x78, 0x0D, 0x46, 0x80, 0x46, 0x17, 0x46, ++0x1B, 0xB9, 0x37, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x49, 0xDB, 0x36, 0x4C, 0xDF, 0xF8, 0xEC, 0xA0, 0x4F, 0xF0, 0x00, 0x09, ++0x4F, 0xF4, 0xBA, 0x73, 0x06, 0x22, 0x04, 0x21, 0x41, 0xF2, 0x02, 0x00, 0xDA, 0xF8, 0x00, 0xB0, 0x84, 0xF8, 0x17, 0x90, ++0xF9, 0xF7, 0x04, 0xF9, 0x04, 0x46, 0x28, 0x68, 0x20, 0x60, 0x4F, 0xF0, 0x01, 0x0C, 0xB5, 0xF8, 0x04, 0xE0, 0x84, 0xF8, ++0x6F, 0xC1, 0x5E, 0x46, 0x0F, 0xCE, 0x04, 0xF1, 0xFC, 0x05, 0xA4, 0xF8, 0x04, 0xE0, 0x0F, 0xC5, 0x0F, 0xCE, 0x0F, 0xC5, ++0x33, 0x68, 0x2B, 0x70, 0x84, 0xF8, 0x70, 0xC1, 0xA4, 0xF8, 0x6C, 0x91, 0xC4, 0xF8, 0x68, 0x91, 0x9B, 0xF8, 0x3D, 0x30, ++0x84, 0xF8, 0x6E, 0x31, 0xD8, 0xF8, 0x00, 0x00, 0xC4, 0xF8, 0x60, 0x01, 0xB8, 0xF8, 0x04, 0x30, 0xA4, 0xF8, 0x64, 0x31, ++0x1F, 0xB1, 0xE3, 0x78, 0x43, 0xEA, 0x0C, 0x03, 0xE3, 0x70, 0xB7, 0xFA, 0x87, 0xF2, 0x20, 0x46, 0x52, 0x09, 0x8A, 0xF8, ++0x15, 0x20, 0xF9, 0xF7, 0x01, 0xF9, 0xBD, 0xE8, 0xF8, 0x4F, 0x02, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0xC5, 0xBA, 0x12, 0x4B, ++0x10, 0x4C, 0xD3, 0xF8, 0x24, 0x31, 0x5B, 0x06, 0xB0, 0xD5, 0xE3, 0x7D, 0x01, 0x2B, 0xAD, 0xD1, 0x0E, 0x4A, 0x63, 0x70, ++0x13, 0x68, 0x0E, 0x49, 0x0E, 0x48, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x08, 0x60, 0x0D, 0x4A, 0xC4, 0xF8, 0x0C, 0x80, ++0x06, 0x21, 0x41, 0xF6, 0x09, 0x00, 0x25, 0x61, 0xA7, 0x75, 0xF8, 0xF7, 0x0D, 0xFF, 0xBD, 0xE8, 0xF8, 0x4F, 0xDC, 0xF7, ++0xF9, 0xB8, 0x00, 0xBF, 0x48, 0x30, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x00, 0x00, 0x50, 0x40, 0x34, 0x04, 0x32, 0x40, ++0x20, 0x04, 0x32, 0x40, 0x40, 0x1F, 0xDC, 0x05, 0xA0, 0x86, 0x01, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x27, 0x4D, 0xDF, 0xF8, 0xA0, 0x80, 0xAF, 0x7D, 0xD8, 0xF8, 0x00, 0x90, 0x4F, 0xF4, 0xBA, 0x73, 0x06, 0x22, 0x04, 0x21, ++0x41, 0xF2, 0x02, 0x00, 0xF9, 0xF7, 0x8A, 0xF8, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, 0x09, 0x00, 0xF8, 0xF7, 0x92, 0xFF, ++0xD5, 0xE9, 0x03, 0x23, 0x4F, 0xF0, 0x00, 0x0C, 0x85, 0xF8, 0x17, 0xC0, 0x10, 0x68, 0xC4, 0xF8, 0x60, 0x01, 0x18, 0x68, ++0x95, 0x88, 0x20, 0x60, 0x4F, 0xF0, 0x01, 0x0E, 0xB3, 0xF8, 0x04, 0xA0, 0x84, 0xF8, 0x6F, 0xE1, 0x4E, 0x46, 0x0F, 0xCE, ++0xA4, 0xF8, 0x64, 0x51, 0x04, 0xF1, 0xFC, 0x05, 0xA4, 0xF8, 0x04, 0xA0, 0x0F, 0xC5, 0x0F, 0xCE, 0x0F, 0xC5, 0x33, 0x68, ++0x2B, 0x70, 0x84, 0xF8, 0x70, 0xE1, 0xA4, 0xF8, 0x6C, 0xC1, 0xC4, 0xF8, 0x68, 0xC1, 0x99, 0xF8, 0x3D, 0x30, 0x84, 0xF8, ++0x6E, 0x31, 0x1F, 0xB1, 0xE3, 0x78, 0x43, 0xEA, 0x0E, 0x03, 0xE3, 0x70, 0xB7, 0xFA, 0x87, 0xF3, 0x20, 0x46, 0x5B, 0x09, ++0x88, 0xF8, 0x15, 0x30, 0xF9, 0xF7, 0x7E, 0xF8, 0xBD, 0xE8, 0xF0, 0x47, 0x02, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0x42, 0xBA, ++0x4C, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x30, 0xB5, 0x14, 0x4A, 0x14, 0x4B, 0x11, 0x68, 0x14, 0x4A, 0x91, 0xF8, ++0x3D, 0x10, 0x54, 0x6C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0xF2, 0x99, 0x18, 0x85, 0xB0, 0xD1, 0xF8, 0x90, 0x31, ++0x91, 0xF8, 0xC5, 0x51, 0x8D, 0xF8, 0x05, 0x50, 0x0A, 0x46, 0x99, 0x78, 0xD2, 0xF8, 0x94, 0x21, 0x8D, 0xF8, 0x04, 0x10, ++0x19, 0x88, 0x02, 0x92, 0x1A, 0x79, 0xAD, 0xF8, 0x06, 0x10, 0x8D, 0xF8, 0x0C, 0x20, 0xDB, 0x78, 0x8D, 0xF8, 0x0D, 0x30, ++0x01, 0x46, 0x01, 0xA8, 0xA0, 0x47, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x48, 0xF9, 0xF7, 0xE2, 0xFC, 0x0B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0x46, 0x05, 0xDB, 0x04, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0xF9, 0xF7, 0x33, 0xB8, 0x00, 0x28, ++0xF7, 0xD1, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x0D, 0x22, 0xFB, 0xF7, 0xDD, 0xF8, 0xF0, 0xE7, 0x70, 0xBA, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x02, 0x23, 0x04, 0x46, ++0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF8, 0xF7, 0xE8, 0xFF, 0x06, 0x22, 0x02, 0x23, 0x06, 0x46, 0x05, 0x21, ++0x41, 0xF2, 0x17, 0x40, 0xF8, 0xF7, 0xE0, 0xFF, 0x38, 0x4F, 0x39, 0x49, 0x05, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, ++0x91, 0xFE, 0xFF, 0xF7, 0xE1, 0xFD, 0x20, 0x46, 0xE5, 0xF7, 0x4A, 0xF8, 0x4F, 0xF0, 0x00, 0x08, 0x94, 0xF8, 0x6C, 0x00, ++0x7B, 0x6A, 0x98, 0x47, 0x86, 0xF8, 0x00, 0x80, 0x94, 0xF8, 0x63, 0x30, 0x73, 0x70, 0x2F, 0x48, 0xA6, 0xF1, 0x0C, 0x01, ++0xF9, 0xF7, 0x52, 0xFC, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x3F, 0xD1, 0x94, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x0D, 0xD0, ++0x01, 0x23, 0x00, 0x21, 0x06, 0x22, 0x0C, 0x20, 0xF8, 0xF7, 0xB6, 0xFF, 0x01, 0x46, 0x94, 0xF8, 0x6C, 0x30, 0x01, 0xF8, ++0x0C, 0x39, 0x23, 0x48, 0xF9, 0xF7, 0x3C, 0xFC, 0x23, 0x6C, 0x6B, 0xB1, 0x01, 0x23, 0x00, 0x21, 0x06, 0x22, 0x39, 0x20, ++0xF8, 0xF7, 0xA6, 0xFF, 0x01, 0x46, 0x94, 0xF8, 0x63, 0x30, 0x01, 0xF8, 0x0C, 0x39, 0x1B, 0x48, 0xF9, 0xF7, 0x2C, 0xFC, ++0x00, 0x26, 0x2E, 0x70, 0x94, 0xF8, 0x63, 0x20, 0x18, 0x4B, 0x6A, 0x70, 0x93, 0xF8, 0x04, 0x31, 0x43, 0xB1, 0xD7, 0xF8, ++0xD8, 0x31, 0x04, 0xF1, 0x9C, 0x00, 0x98, 0x47, 0xC4, 0xE9, 0x24, 0x66, 0xC4, 0xF8, 0x98, 0x60, 0x00, 0x23, 0xA5, 0xF1, ++0x0C, 0x01, 0xC4, 0xF8, 0xCC, 0x31, 0x0E, 0x48, 0xF9, 0xF7, 0x12, 0xFC, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7, 0x6C, 0xBF, ++0x41, 0x46, 0x04, 0x23, 0x06, 0x22, 0x1E, 0x20, 0xF8, 0xF7, 0x7A, 0xFF, 0x80, 0xF8, 0x02, 0x80, 0x94, 0xF8, 0x63, 0x30, ++0xC3, 0x70, 0xA0, 0xF1, 0x0C, 0x01, 0x04, 0x48, 0xF9, 0xF7, 0xFE, 0xFB, 0xAE, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0xA8, 0xBB, 0x15, 0x00, 0x70, 0xBA, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x6A, 0x4B, 0xDF, 0xF8, ++0xB4, 0xA1, 0x1D, 0x68, 0x83, 0xB0, 0x95, 0xF8, 0x3D, 0x20, 0x00, 0x92, 0x16, 0x46, 0x02, 0x23, 0x06, 0x22, 0x05, 0x21, ++0x41, 0xF2, 0x19, 0x40, 0xF8, 0xF7, 0x54, 0xFF, 0x08, 0x23, 0x81, 0x46, 0x06, 0x22, 0x00, 0x21, 0x18, 0x20, 0xF8, 0xF7, ++0x4D, 0xFF, 0x08, 0x23, 0x07, 0x46, 0x06, 0x22, 0x00, 0x21, 0x16, 0x20, 0xF8, 0xF7, 0x46, 0xFF, 0x4F, 0xF4, 0xA4, 0x64, ++0x04, 0xFB, 0x06, 0xF4, 0x04, 0x23, 0x06, 0x46, 0x06, 0x22, 0x00, 0x21, 0x14, 0x20, 0xF8, 0xF7, 0x3B, 0xFF, 0x02, 0x23, ++0x06, 0x22, 0x05, 0x21, 0x83, 0x46, 0x41, 0xF2, 0x17, 0x40, 0xF8, 0xF7, 0x33, 0xFF, 0x80, 0x46, 0xFF, 0xF7, 0x3A, 0xFD, ++0x4F, 0xF0, 0x01, 0x02, 0x89, 0xF8, 0x00, 0x20, 0x95, 0xF8, 0x3D, 0x30, 0x89, 0xF8, 0x01, 0x30, 0x0A, 0xEB, 0x04, 0x03, ++0x01, 0x93, 0x4B, 0x4B, 0xA9, 0xF1, 0x0C, 0x01, 0x03, 0xF1, 0x0C, 0x00, 0xF9, 0xF7, 0xAC, 0xFB, 0x01, 0x9B, 0xD3, 0xF8, ++0x64, 0x01, 0xB3, 0xF8, 0x68, 0x21, 0xBA, 0x80, 0x44, 0x4B, 0x38, 0x60, 0x95, 0xF8, 0x3D, 0x20, 0xBA, 0x71, 0x03, 0xF1, ++0x0C, 0x00, 0xA7, 0xF1, 0x0C, 0x01, 0xF9, 0xF7, 0x9B, 0xFB, 0x01, 0x9B, 0xD3, 0xF8, 0x90, 0x31, 0x04, 0xF5, 0xCE, 0x70, ++0x9B, 0x78, 0x73, 0x71, 0x01, 0x21, 0x50, 0x44, 0xFD, 0xF7, 0xFE, 0xFD, 0x73, 0x79, 0x30, 0x60, 0x95, 0xF8, 0x3D, 0x20, ++0x32, 0x71, 0x2B, 0xB9, 0xC1, 0x07, 0x4F, 0xD5, 0x36, 0x4B, 0x4F, 0xF4, 0x80, 0x62, 0x5A, 0x61, 0xA6, 0xF1, 0x0C, 0x01, ++0x34, 0x48, 0xF9, 0xF7, 0x7F, 0xFB, 0x00, 0x9B, 0x32, 0x48, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x03, 0xA6, 0xAB, 0xF1, ++0x0C, 0x01, 0xB6, 0xF8, 0x98, 0x31, 0xAB, 0xF8, 0x00, 0x30, 0x95, 0xF8, 0x3D, 0x30, 0x8B, 0xF8, 0x02, 0x30, 0xF9, 0xF7, ++0x6D, 0xFB, 0xD6, 0xF8, 0xCC, 0x31, 0x1B, 0x07, 0x36, 0xD4, 0x04, 0xF5, 0xD6, 0x74, 0x00, 0x26, 0x26, 0x4F, 0xA2, 0x44, ++0x34, 0x46, 0x08, 0x23, 0x06, 0x22, 0x00, 0x21, 0x1A, 0x20, 0xF8, 0xF7, 0xCF, 0xFE, 0x5A, 0xF8, 0x04, 0x3B, 0x03, 0x60, ++0x46, 0x71, 0x95, 0xF8, 0x3D, 0x30, 0x83, 0x71, 0x04, 0x71, 0xA0, 0xF1, 0x0C, 0x01, 0x01, 0x36, 0x38, 0x46, 0xF9, 0xF7, ++0x4F, 0xFB, 0x04, 0x2E, 0xE9, 0xD1, 0x01, 0x23, 0x88, 0xF8, 0x00, 0x30, 0x95, 0xF8, 0x3D, 0x30, 0x17, 0x48, 0x88, 0xF8, ++0x01, 0x30, 0xA8, 0xF1, 0x0C, 0x01, 0xF9, 0xF7, 0x41, 0xFB, 0xFF, 0xF7, 0x9D, 0xFE, 0x31, 0x46, 0x06, 0x20, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0xF9, 0xF7, 0xA4, 0xB8, 0xC2, 0x06, 0xB1, 0xD5, 0x0D, 0x4B, 0x04, 0x22, 0x5A, 0x61, 0xAD, 0xE7, ++0x06, 0x22, 0x00, 0x21, 0x04, 0x23, 0x71, 0x20, 0xF8, 0xF7, 0x9E, 0xFE, 0x04, 0xF1, 0xEC, 0x03, 0x06, 0x46, 0x0A, 0xEB, ++0x03, 0x00, 0xFD, 0xF7, 0x0F, 0xFE, 0x31, 0x46, 0x03, 0x46, 0x41, 0xF8, 0x0C, 0x39, 0x04, 0x48, 0xF9, 0xF7, 0x1E, 0xFB, ++0xB3, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0xC4, 0x3C, 0x18, 0x00, 0x70, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x06, 0x23, 0x2D, 0xE9, 0xF0, 0x41, 0x1A, 0x46, 0x04, 0x46, 0x0F, 0x46, 0x41, 0xF6, 0x05, 0x00, 0x0C, 0x21, 0xF8, 0xF7, ++0x7B, 0xFE, 0x38, 0x4E, 0x94, 0xF8, 0xC0, 0x34, 0xB4, 0x62, 0x05, 0x46, 0x00, 0x2B, 0x3F, 0xD0, 0x35, 0x4B, 0x9B, 0x68, ++0x00, 0x2B, 0x61, 0xD0, 0x93, 0xF8, 0x62, 0x20, 0x7A, 0xB9, 0x33, 0x49, 0x33, 0x4A, 0xD8, 0x6D, 0x08, 0x60, 0xB3, 0xF8, ++0x60, 0x10, 0x11, 0x60, 0x93, 0xF8, 0x64, 0x20, 0x2A, 0xB1, 0x30, 0x49, 0x98, 0x6B, 0x30, 0x4A, 0x08, 0x60, 0x99, 0x8F, ++0x11, 0x60, 0x2F, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x2C, 0xDB, 0xDF, 0xF8, 0xC4, 0x80, 0x00, 0x20, 0xDB, 0xF7, 0x86, 0xFE, ++0x00, 0x22, 0xD8, 0xF8, 0xD8, 0x31, 0x84, 0xF8, 0xAC, 0x20, 0x04, 0xF1, 0xB0, 0x00, 0x98, 0x47, 0xD8, 0xF8, 0x10, 0x33, ++0x20, 0x46, 0x98, 0x47, 0x2F, 0x80, 0x94, 0xF8, 0x63, 0x30, 0xAB, 0x70, 0xB3, 0x7D, 0x01, 0x2B, 0x08, 0xBF, 0xEB, 0x70, ++0xB3, 0x7F, 0xA3, 0xF1, 0x01, 0x03, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0xA5, 0xF1, 0x0C, 0x02, 0x2B, 0x71, 0xB2, 0x60, ++0xBD, 0xE8, 0xF0, 0x81, 0x1A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xD6, 0xDA, 0x13, 0x4B, 0x9B, 0x68, 0x00, 0x2B, 0xD2, 0xD0, ++0x00, 0x21, 0x93, 0xF8, 0x62, 0x20, 0x1A, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x02, 0xB1, 0x01, 0x31, 0x1B, 0x68, 0x00, 0x2B, ++0xF5, 0xD1, 0x01, 0x29, 0xC5, 0xD1, 0x11, 0x4A, 0x11, 0x49, 0x53, 0x70, 0x0B, 0x68, 0x11, 0x4A, 0x43, 0xF0, 0x00, 0x43, ++0x0B, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x43, 0xF4, 0xBB, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0xB4, 0xE7, ++0x07, 0x4B, 0x1B, 0x68, 0xB1, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x10, 0x00, 0x32, 0x40, ++0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x48, 0x30, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, ++0x34, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0A, 0x46, 0x04, 0x46, 0x05, 0x49, ++0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, 0xA4, 0xFC, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x60, 0xBF, ++0xBC, 0xBB, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xC8, 0x81, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x00, 0x84, ++0x0B, 0x46, 0x02, 0x46, 0x06, 0x46, 0x0F, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x66, 0x49, 0x94, 0xF8, 0x6C, 0x90, 0xFA, 0xF7, ++0x89, 0xFC, 0x94, 0xF8, 0x62, 0x50, 0x15, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x3B, 0xB9, 0xBD, 0xE8, 0xF8, 0x43, 0x06, 0x22, ++0x0C, 0x21, 0x41, 0xF6, 0x04, 0x00, 0xF8, 0xF7, 0x2B, 0xBE, 0x5E, 0x4B, 0x01, 0x25, 0x09, 0x21, 0x06, 0x20, 0x1D, 0x75, ++0xF8, 0xF7, 0xB6, 0xFF, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x79, 0xD1, 0xD4, 0xF8, 0x90, 0x31, 0x9D, 0x78, 0x2C, 0x1E, ++0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x06, 0x85, 0x28, 0x46, 0x18, 0xBF, 0x01, 0x24, 0xE4, 0xF7, 0x11, 0xFD, 0x00, 0x28, ++0x74, 0xD0, 0x20, 0x46, 0x4F, 0xF4, 0xC0, 0x71, 0xE6, 0xF7, 0x72, 0xF8, 0x04, 0x46, 0x01, 0x46, 0x28, 0x46, 0x00, 0x2C, ++0x6C, 0xD0, 0xF8, 0xF7, 0x69, 0xF9, 0x4C, 0x4B, 0xD4, 0xF8, 0x48, 0x80, 0x4B, 0x49, 0xE8, 0x6D, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x09, 0x39, 0xB1, 0xF8, 0xFC, 0x31, 0x59, 0xF8, 0x26, 0x2F, 0xC8, 0xF8, 0x6C, 0x20, 0x6F, 0xF0, 0x3F, 0x02, ++0x88, 0xF8, 0x68, 0x20, 0xB9, 0xF8, 0x04, 0x20, 0xA8, 0xF8, 0x70, 0x20, 0xB5, 0xF8, 0x60, 0x20, 0xA8, 0xF8, 0x76, 0x20, ++0x01, 0x33, 0xD9, 0xF8, 0x00, 0x20, 0xC8, 0xF8, 0x72, 0x00, 0x9B, 0xB2, 0xB9, 0xF8, 0x04, 0x00, 0xC8, 0xF8, 0x78, 0x20, ++0x00, 0x22, 0xA8, 0xF8, 0x7C, 0x00, 0x88, 0xF8, 0x69, 0x20, 0x88, 0xF8, 0x6A, 0x20, 0x88, 0xF8, 0x6B, 0x20, 0x18, 0x01, ++0xA1, 0xF8, 0xFC, 0x31, 0x35, 0x4B, 0xA8, 0xF8, 0x7E, 0x00, 0x26, 0x77, 0xA5, 0x65, 0x63, 0x65, 0x95, 0xF8, 0x6C, 0x30, ++0x63, 0x77, 0x84, 0xF8, 0x33, 0x20, 0x84, 0xF8, 0x35, 0x20, 0xC0, 0x21, 0x20, 0x46, 0x07, 0xF0, 0x5F, 0xF9, 0x01, 0x28, ++0x06, 0x46, 0x08, 0xF1, 0x68, 0x09, 0x34, 0xD0, 0x39, 0x46, 0x08, 0xF1, 0x80, 0x00, 0xFB, 0xF7, 0xDD, 0xFD, 0x02, 0x2E, ++0x00, 0xF1, 0x18, 0x05, 0x3D, 0xD0, 0xE2, 0x6C, 0x53, 0x6A, 0x01, 0x3B, 0x2B, 0x44, 0x04, 0x35, 0xC2, 0xE9, 0x0A, 0x35, ++0x05, 0x21, 0x20, 0x46, 0xE6, 0xF7, 0x20, 0xF8, 0x05, 0x46, 0x88, 0xB1, 0xBD, 0xE8, 0xF8, 0x83, 0x2C, 0x46, 0x4F, 0xF4, ++0xA4, 0x65, 0x05, 0xFB, 0x06, 0x85, 0x28, 0x46, 0xE4, 0xF7, 0x9C, 0xFC, 0x00, 0x28, 0x8A, 0xD1, 0x01, 0x46, 0x28, 0x46, ++0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0xA8, 0xBE, 0xA4, 0x6D, 0x17, 0x49, 0x02, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, ++0xDF, 0xFB, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0x9B, 0xBE, 0x18, 0x22, 0x49, 0x46, 0x20, 0x46, ++0x05, 0xF0, 0x84, 0xFF, 0x94, 0xF8, 0x33, 0x50, 0x18, 0x35, 0x09, 0xEB, 0x05, 0x00, 0x39, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, ++0x94, 0xF8, 0x35, 0x20, 0x15, 0x44, 0x05, 0x44, 0xC1, 0xE7, 0x2A, 0x46, 0x49, 0x46, 0x20, 0x46, 0x07, 0xF0, 0x4A, 0xF9, ++0x05, 0x44, 0xBA, 0xE7, 0xD4, 0xBB, 0x15, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0xD1, 0x9D, 0x14, 0x00, 0xBC, 0xBB, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x66, 0x4D, 0x67, 0x49, ++0xD5, 0xE9, 0x00, 0x34, 0x93, 0xF8, 0x3D, 0x70, 0x67, 0x72, 0x0A, 0x68, 0x20, 0x80, 0x22, 0xF0, 0x10, 0x02, 0x4F, 0xF4, ++0xA4, 0x66, 0x83, 0xB0, 0x80, 0x46, 0x06, 0xFB, 0x07, 0xF6, 0x0A, 0x60, 0x00, 0x28, 0x6C, 0xD1, 0xDF, 0xF8, 0x98, 0x91, ++0x09, 0xEB, 0x06, 0x01, 0x91, 0xF8, 0x6C, 0x20, 0xD1, 0xF8, 0x64, 0x01, 0xB1, 0xF8, 0x68, 0xC1, 0xA2, 0x72, 0x0A, 0x6C, ++0xA4, 0xF8, 0x06, 0xC0, 0xC4, 0xF8, 0x02, 0x00, 0x10, 0x7E, 0xE0, 0x72, 0x10, 0x79, 0x84, 0xF8, 0x36, 0x03, 0xD0, 0x88, ++0xB2, 0xF8, 0x08, 0xC0, 0xA4, 0xF8, 0x38, 0x03, 0x50, 0x89, 0xC4, 0xE9, 0xCF, 0xC0, 0x52, 0x79, 0x84, 0xF8, 0x3A, 0x23, ++0xD1, 0xF8, 0xCC, 0x21, 0x02, 0xF0, 0x01, 0x02, 0x22, 0x73, 0x00, 0x2A, 0x6D, 0xD1, 0x42, 0x46, 0x62, 0x73, 0x1A, 0x6B, ++0x4F, 0xF4, 0xA4, 0x63, 0x02, 0xF0, 0x20, 0x02, 0x03, 0xFB, 0x07, 0x93, 0x22, 0x72, 0x93, 0xF8, 0xC0, 0x24, 0xA2, 0xB1, ++0xB3, 0xF8, 0x5E, 0x00, 0xB3, 0xF8, 0x5C, 0x20, 0x42, 0x49, 0x42, 0xEA, 0x00, 0x42, 0x0A, 0x60, 0x41, 0x4A, 0xB3, 0xF8, ++0x60, 0x10, 0x11, 0x60, 0x58, 0x8F, 0x1A, 0x8F, 0x3F, 0x49, 0x42, 0xEA, 0x00, 0x42, 0x0A, 0x60, 0x3E, 0x4A, 0x9B, 0x8F, ++0x13, 0x60, 0x20, 0x46, 0xF8, 0xF7, 0xC8, 0xFC, 0x94, 0xF8, 0x3A, 0x33, 0xB4, 0xF8, 0x3C, 0x03, 0x40, 0xEA, 0x03, 0x40, ++0x40, 0xF0, 0x00, 0x40, 0xDB, 0xF7, 0xC0, 0xFC, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x97, 0x01, 0x22, 0x35, 0x4B, ++0x87, 0xF8, 0xAC, 0x20, 0x1A, 0x69, 0x34, 0x49, 0x34, 0x4B, 0x06, 0xF1, 0xB0, 0x00, 0x48, 0x44, 0x11, 0x44, 0xD3, 0xF8, ++0xE0, 0x31, 0x98, 0x47, 0x00, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x72, 0xFE, 0x12, 0xE0, 0x2F, 0x4B, 0x1B, 0x68, 0x00, 0x2B, ++0x26, 0xDB, 0x2E, 0x4B, 0x06, 0x20, 0x09, 0x21, 0x1E, 0x44, 0xF8, 0xF7, 0x67, 0xFE, 0x29, 0x4A, 0xAE, 0x62, 0xA4, 0xF1, ++0x0C, 0x03, 0xD2, 0xF8, 0x10, 0x23, 0xAB, 0x60, 0x30, 0x46, 0x90, 0x47, 0xB4, 0xF8, 0x34, 0x33, 0x62, 0x7A, 0x26, 0x49, ++0x00, 0x93, 0x4F, 0xF4, 0x80, 0x70, 0x43, 0x46, 0xFA, 0xF7, 0x12, 0xFB, 0x28, 0x68, 0x0C, 0x38, 0xF8, 0xF7, 0xD2, 0xFC, ++0x00, 0x23, 0x2B, 0x60, 0xAB, 0x75, 0xAB, 0x77, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x91, 0xF8, 0xBD, 0x21, 0x8F, 0xE7, ++0x1C, 0x4B, 0x9A, 0x68, 0x62, 0xB1, 0x00, 0x21, 0x92, 0xF8, 0x62, 0x30, 0x1B, 0xB9, 0x92, 0xF8, 0x64, 0x30, 0x03, 0xB1, ++0x01, 0x31, 0x12, 0x68, 0x00, 0x2A, 0xF5, 0xD1, 0x00, 0x29, 0xC8, 0xD1, 0x15, 0x4B, 0x16, 0x49, 0x00, 0x22, 0x5A, 0x70, ++0x0B, 0x68, 0x15, 0x4A, 0x43, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x43, 0xF4, 0xBB, 0x63, ++0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0xB6, 0xE7, 0x64, 0xBA, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0x10, 0x00, 0x32, 0x40, ++0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x40, 0x4B, 0x4C, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x48, 0x30, 0x34, 0x40, 0x18, 0x88, 0x17, 0x00, 0xE8, 0xBB, 0x15, 0x00, 0x00, 0x88, 0x17, 0x00, ++0x4C, 0x36, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0x4B, 0x8C, 0x4E, ++0xD3, 0xF8, 0x00, 0x90, 0x8B, 0x4A, 0x99, 0xF8, 0x3D, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x05, 0x64, 0x89, 0xB0, ++0x07, 0x46, 0x88, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x86, 0x49, 0x94, 0xF8, 0x6C, 0xA0, 0xFA, 0xF7, 0xAB, 0xFA, 0x94, 0xF8, ++0xC0, 0x34, 0x00, 0x2B, 0x40, 0xF0, 0x82, 0x80, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x78, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, ++0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0xB2, 0xFE, 0x04, 0x46, 0x00, 0x28, 0x7C, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x05, 0x65, 0x28, 0x46, 0x21, 0x46, 0xF7, 0xF7, 0xA5, 0xFF, 0x78, 0x4B, 0xA2, 0x6C, 0x78, 0x49, 0x4F, 0xF4, 0x1E, 0x70, ++0x00, 0xFB, 0x0A, 0x3A, 0x53, 0x46, 0xB1, 0xF8, 0xFC, 0x61, 0x53, 0xF8, 0x26, 0x0F, 0xD0, 0x66, 0x6F, 0xF0, 0x4F, 0x00, ++0x82, 0xF8, 0x68, 0x00, 0x98, 0x88, 0xA2, 0xF8, 0x70, 0x00, 0xE8, 0x6D, 0xC2, 0xF8, 0x72, 0x00, 0x01, 0x36, 0xB5, 0xF8, ++0x60, 0x00, 0xA2, 0xF8, 0x76, 0x00, 0x4F, 0xF0, 0x00, 0x0B, 0x18, 0x68, 0x9B, 0x88, 0xA2, 0xF8, 0x7C, 0x30, 0xB6, 0xB2, ++0x90, 0x67, 0x82, 0xF8, 0x69, 0xB0, 0x82, 0xF8, 0x6A, 0xB0, 0x82, 0xF8, 0x6B, 0xB0, 0x65, 0x4B, 0xA1, 0xF8, 0xFC, 0x61, ++0x30, 0x01, 0x95, 0xF8, 0x63, 0x10, 0xA2, 0xF8, 0x7E, 0x00, 0x21, 0x77, 0x95, 0xF8, 0x6C, 0x10, 0x1B, 0x68, 0x61, 0x77, ++0x84, 0xF8, 0x33, 0xB0, 0x84, 0xF8, 0x35, 0xB0, 0x1B, 0x78, 0x99, 0xF8, 0x3B, 0x10, 0x9B, 0x07, 0x02, 0xF1, 0x68, 0x05, ++0x38, 0xD4, 0x01, 0x29, 0x44, 0xD0, 0x18, 0x26, 0xCD, 0xF8, 0x00, 0x80, 0x3A, 0x46, 0xA8, 0x19, 0x00, 0x23, 0xFB, 0xF7, ++0xFF, 0xFB, 0x30, 0x44, 0xE1, 0x6C, 0x94, 0xF8, 0x35, 0x30, 0x4A, 0x6A, 0xA4, 0x65, 0x18, 0x44, 0x01, 0x3A, 0x02, 0x44, ++0x03, 0x1D, 0x50, 0x48, 0x60, 0x65, 0xC1, 0xE9, 0x0A, 0x23, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, 0x59, 0xFE, 0x4D, 0x4B, ++0x1B, 0x68, 0x06, 0x21, 0xDA, 0x68, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, 0xD1, 0xF9, 0x05, 0x21, 0x06, 0x20, 0xF8, 0xF7, ++0x69, 0xFD, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0x35, 0xFE, 0x04, 0x46, ++0x00, 0x28, 0x82, 0xD1, 0x01, 0x20, 0xFF, 0xF7, 0x67, 0xFE, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x29, 0x01, 0xD1, ++0x03, 0x2F, 0x17, 0xD0, 0xCD, 0xF8, 0x00, 0x80, 0x3A, 0x46, 0x05, 0xF1, 0x18, 0x00, 0x00, 0x23, 0xFB, 0xF7, 0xC4, 0xFB, ++0x18, 0x30, 0xC3, 0xE7, 0x03, 0x2F, 0xB8, 0xD1, 0x29, 0x46, 0x20, 0x46, 0x18, 0x22, 0x05, 0xF0, 0xB1, 0xFD, 0x94, 0xF8, ++0x33, 0x00, 0x99, 0xF8, 0x3B, 0x10, 0x00, 0xF1, 0x18, 0x06, 0xAD, 0xE7, 0xDA, 0xF8, 0xB4, 0x30, 0x29, 0x46, 0x18, 0x22, ++0x20, 0x46, 0x1E, 0x68, 0x05, 0xF0, 0xA2, 0xFD, 0x94, 0xF8, 0x33, 0x00, 0x99, 0xF8, 0x3B, 0x10, 0xCD, 0xF8, 0x00, 0x80, ++0x00, 0xF1, 0x18, 0x08, 0x05, 0xEB, 0x08, 0x09, 0x5B, 0x46, 0x3A, 0x46, 0x48, 0x46, 0xFB, 0xF7, 0x9D, 0xFB, 0x05, 0x46, ++0x3A, 0x46, 0x29, 0x46, 0x4F, 0xF0, 0xFF, 0x33, 0x48, 0x46, 0xDB, 0xF7, 0x67, 0xFD, 0x96, 0xF8, 0x60, 0x30, 0x21, 0x8F, ++0x62, 0x8F, 0xAD, 0xF8, 0x10, 0x10, 0x8D, 0xF8, 0x12, 0x20, 0x06, 0xF1, 0x64, 0x01, 0x93, 0xB1, 0x03, 0x2B, 0x1A, 0xD0, ++0x03, 0x20, 0xDB, 0xF7, 0x8F, 0xFD, 0x29, 0x1D, 0x02, 0x46, 0x89, 0xB2, 0x48, 0x46, 0x03, 0x91, 0xF7, 0xF7, 0x20, 0xFF, ++0x48, 0x46, 0x03, 0x99, 0xF8, 0xF7, 0x16, 0xF9, 0x05, 0xEB, 0x08, 0x00, 0x78, 0xE7, 0x05, 0x22, 0x0D, 0xF1, 0x13, 0x00, ++0x0C, 0xF0, 0x88, 0xFE, 0x04, 0xA8, 0x08, 0x21, 0xF8, 0xF7, 0xDE, 0xF8, 0xE4, 0xE7, 0x0D, 0x22, 0x0D, 0xF1, 0x13, 0x00, ++0x0C, 0xF0, 0x7E, 0xFE, 0x04, 0xA8, 0x10, 0x21, 0xF8, 0xF7, 0xD4, 0xF8, 0xDA, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x9C, 0xBC, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x89, 0x95, 0x14, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x77, 0x4F, 0x78, 0x4E, ++0xD7, 0xF8, 0x00, 0x80, 0x77, 0x4A, 0x98, 0xF8, 0x3D, 0x50, 0x77, 0x49, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x05, 0x64, ++0x87, 0xB0, 0x4F, 0xF4, 0x80, 0x70, 0x94, 0xF8, 0x6C, 0xA0, 0xFA, 0xF7, 0x81, 0xF9, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0x40, 0xF0, 0xAA, 0x80, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x78, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, ++0xE5, 0xF7, 0x88, 0xFD, 0x04, 0x46, 0x00, 0x28, 0x00, 0xF0, 0xA5, 0x80, 0x4F, 0xF4, 0xA4, 0x6B, 0x0B, 0xFB, 0x05, 0xFB, ++0x06, 0xEB, 0x0B, 0x00, 0x21, 0x46, 0xD7, 0xF8, 0x04, 0x90, 0xF7, 0xF7, 0x77, 0xFE, 0xBA, 0x7D, 0xA3, 0x6C, 0x01, 0x2A, ++0x03, 0xF1, 0x68, 0x0C, 0x00, 0xF0, 0x99, 0x80, 0xBA, 0x7F, 0x00, 0x2A, 0x00, 0xF0, 0xA7, 0x80, 0x20, 0x22, 0x00, 0x21, ++0x83, 0xF8, 0x68, 0x20, 0x5B, 0x4A, 0x83, 0xF8, 0x69, 0x10, 0x5B, 0x49, 0x5B, 0x4F, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x0A, 0x10, 0xB7, 0xF8, 0xFC, 0xE1, 0x50, 0xF8, 0x26, 0xAF, 0xC3, 0xF8, 0x6C, 0xA0, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, ++0x05, 0x65, 0xB0, 0xF8, 0x04, 0xA0, 0xA3, 0xF8, 0x70, 0xA0, 0x0B, 0xF1, 0xEC, 0x01, 0x0E, 0xF1, 0x01, 0x0E, 0xD0, 0xF8, ++0x00, 0xA0, 0xB0, 0xF8, 0x04, 0xB0, 0xE8, 0x6D, 0xC3, 0xF8, 0x72, 0x00, 0x1F, 0xFA, 0x8E, 0xFE, 0x31, 0x44, 0x00, 0x26, ++0xB5, 0xF8, 0x60, 0x00, 0xC3, 0xF8, 0x78, 0xA0, 0x83, 0xF8, 0x6A, 0x60, 0x83, 0xF8, 0x6B, 0x60, 0x4F, 0xEA, 0x0E, 0x1A, ++0x46, 0x4E, 0xA3, 0xF8, 0x76, 0x00, 0xA3, 0xF8, 0x7C, 0xB0, 0x0C, 0xF1, 0x18, 0x00, 0xA7, 0xF8, 0xFC, 0xE1, 0x0D, 0xF1, ++0x12, 0x0C, 0xA3, 0xF8, 0x7E, 0xA0, 0x05, 0xAF, 0x95, 0xF8, 0x63, 0x30, 0xCD, 0xF8, 0x08, 0x80, 0xD6, 0xF8, 0x58, 0x61, ++0xCD, 0xE9, 0x00, 0x7C, 0xB0, 0x47, 0x95, 0xF8, 0x63, 0x30, 0x23, 0x77, 0x95, 0xF8, 0x6C, 0x30, 0xE1, 0x6C, 0x63, 0x77, ++0x4B, 0x6A, 0xBD, 0xF8, 0x12, 0x20, 0x37, 0x4D, 0xA4, 0x65, 0x17, 0x33, 0x03, 0x44, 0xB2, 0xF5, 0x48, 0x7F, 0x00, 0xF1, ++0x1C, 0x00, 0x65, 0x65, 0xC1, 0xE9, 0x0A, 0x30, 0x3B, 0xD8, 0x05, 0x98, 0x6A, 0xB1, 0x4A, 0x44, 0x13, 0x38, 0x13, 0x32, ++0xA0, 0xEB, 0x09, 0x00, 0x09, 0xF1, 0x13, 0x03, 0xC1, 0x5C, 0x03, 0xF8, 0x01, 0x1F, 0x93, 0x42, 0xFA, 0xD1, 0xBD, 0xF8, ++0x12, 0x20, 0xA9, 0xF8, 0x0E, 0x20, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, 0x07, 0xFD, 0x27, 0x4B, 0x1B, 0x68, 0x06, 0x21, ++0x9A, 0x68, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, 0x7F, 0xF8, 0x07, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x17, 0xFC, 0x07, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0xE3, 0xFC, 0x04, 0x46, 0x00, 0x28, 0x7F, 0xF4, ++0x5B, 0xAF, 0x01, 0x20, 0xFF, 0xF7, 0x14, 0xFD, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x20, 0x22, 0x00, 0x21, 0x83, 0xF8, ++0x68, 0x20, 0x83, 0xF8, 0x69, 0x10, 0x16, 0x4A, 0x69, 0xE7, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x08, 0xDB, 0x00, 0x23, 0xA9, 0xF8, 0x0E, 0x30, 0xCB, 0xE7, 0x83, 0xF8, 0x68, 0x20, 0x83, 0xF8, 0x69, 0x20, 0x5A, 0xE7, ++0x0F, 0x49, 0x10, 0x48, 0x4F, 0xF4, 0x82, 0x62, 0xFA, 0xF7, 0xE8, 0xFA, 0xEF, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0xAC, 0xBC, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x84, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x89, 0x95, 0x14, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x7C, 0xBA, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0xB5, 0x0B, 0x4D, 0x04, 0x46, 0x04, 0x23, ++0x00, 0x21, 0x06, 0x22, 0x1E, 0x20, 0x2D, 0x68, 0xF8, 0xF7, 0xC6, 0xF9, 0x01, 0x22, 0x04, 0x80, 0x82, 0x70, 0x95, 0xF8, ++0x3D, 0x20, 0xC2, 0x70, 0xF8, 0xF7, 0xEE, 0xF9, 0xBD, 0xE8, 0x38, 0x40, 0x08, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0xB2, 0xBB, ++0x64, 0xBA, 0x17, 0x00, 0x70, 0xB5, 0x00, 0xF1, 0x0C, 0x06, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, ++0xBB, 0xF8, 0xB5, 0x88, 0x19, 0x49, 0x2A, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, 0x5E, 0xF8, 0x45, 0xB9, 0xA3, 0x89, ++0x13, 0xB1, 0x01, 0x2B, 0x09, 0xD0, 0x70, 0xBD, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xBE, 0xBE, 0x28, 0x46, 0xBD, 0xE8, ++0x70, 0x40, 0xFF, 0xF7, 0x9D, 0xBC, 0x73, 0x88, 0x04, 0x2B, 0xF3, 0xD0, 0x02, 0x2B, 0x11, 0xD0, 0x0D, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0xFF, 0xF7, 0x8D, 0xBC, 0x09, 0x49, ++0x09, 0x48, 0x4F, 0xF4, 0x8C, 0x62, 0xFA, 0xF7, 0x7B, 0xFA, 0xF3, 0xE7, 0x04, 0xF1, 0x14, 0x01, 0x03, 0x20, 0xBD, 0xE8, ++0x70, 0x40, 0xFF, 0xF7, 0x6F, 0xBD, 0x00, 0xBF, 0x00, 0xBC, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x69, 0x4B, 0xD3, 0xE9, 0x00, 0x2A, 0x05, 0x46, 0x83, 0xB0, 0x06, 0x21, ++0x00, 0x24, 0x41, 0xF6, 0x08, 0x00, 0x92, 0xF8, 0x3D, 0x80, 0x8D, 0xF8, 0x06, 0x40, 0xF8, 0xF7, 0x6D, 0xF8, 0x29, 0x88, ++0xEE, 0x89, 0x4F, 0xF4, 0xA4, 0x67, 0x05, 0x29, 0x05, 0xF1, 0x0C, 0x09, 0x07, 0xFB, 0x08, 0xF7, 0x34, 0xD9, 0xBA, 0xF8, ++0x0E, 0x30, 0x06, 0x39, 0x89, 0xB2, 0xCA, 0x18, 0x05, 0xF1, 0x12, 0x0B, 0xB2, 0xF5, 0x48, 0x7F, 0x5C, 0x46, 0x09, 0xDD, ++0x58, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x81, 0x80, 0xC3, 0xF5, 0x48, 0x71, 0x89, 0xB2, ++0x0A, 0xF1, 0x14, 0x00, 0x18, 0x44, 0x8B, 0x44, 0x39, 0xB1, 0xA4, 0xF1, 0x12, 0x03, 0x14, 0xF8, 0x01, 0x2B, 0x5B, 0x1B, ++0x5C, 0x45, 0x1A, 0x54, 0xF7, 0xD1, 0xAA, 0xF8, 0x10, 0x10, 0x32, 0x46, 0x4C, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, ++0xE3, 0xFF, 0x9E, 0xB1, 0x4A, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x2B, 0xBB, 0x30, 0x46, 0xFF, 0xF7, 0x29, 0xFC, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x44, 0x49, 0xAA, 0xF8, 0x10, 0x40, 0x32, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0xD0, 0xFF, ++0x00, 0x2E, 0xEB, 0xD1, 0xB9, 0xF8, 0x04, 0x00, 0x40, 0x4C, 0xC0, 0xF3, 0x0D, 0x00, 0xFF, 0xF7, 0x3F, 0xFF, 0x3D, 0x4B, ++0x93, 0xF8, 0x04, 0x31, 0x63, 0xB3, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x08, 0x45, 0xD5, 0xF8, 0x90, 0x31, 0x9A, 0x78, ++0x01, 0x2A, 0x48, 0xD0, 0x38, 0x4E, 0x28, 0xE0, 0x12, 0x2E, 0xD7, 0xD1, 0x35, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, ++0x08, 0x38, 0xD8, 0xF8, 0x90, 0x21, 0x92, 0x78, 0x01, 0x2A, 0xCD, 0xD1, 0x98, 0xF8, 0xC0, 0x44, 0x00, 0x2C, 0xC9, 0xD1, ++0x30, 0x4D, 0x07, 0xF5, 0xB2, 0x77, 0x1F, 0x44, 0xA8, 0x46, 0x40, 0x46, 0x06, 0x22, 0x39, 0x46, 0x0C, 0xF0, 0x3E, 0xFC, ++0x08, 0xF1, 0x14, 0x08, 0x00, 0x28, 0x3F, 0xD0, 0x01, 0x34, 0x05, 0x2C, 0xF3, 0xD1, 0xB7, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x08, 0x43, 0x24, 0x4E, 0xD3, 0xF8, 0x90, 0x31, 0x1B, 0x79, 0xD6, 0xF8, 0x40, 0x53, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x08, 0x48, 0xE0, 0x19, 0x98, 0xF8, 0xC6, 0x21, 0x9B, 0x1A, 0x8D, 0xF8, 0x07, 0x30, 0x0D, 0xF1, 0x06, 0x02, ++0x0D, 0xF1, 0x07, 0x01, 0xA8, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0x49, 0x1B, 0x48, 0x40, 0xF2, 0x8B, 0x42, ++0xFA, 0xF7, 0xB6, 0xF9, 0xBA, 0xF8, 0x0E, 0x30, 0x75, 0xE7, 0xD5, 0xF8, 0xCC, 0x21, 0x12, 0xF0, 0x0C, 0x0F, 0xB1, 0xD0, ++0x95, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0xAD, 0xD1, 0x13, 0x4B, 0x14, 0x49, 0x1B, 0x69, 0x0E, 0x4E, 0x07, 0xF1, 0x9C, 0x00, ++0x19, 0x44, 0x20, 0x44, 0xD6, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0xD5, 0xF8, 0x90, 0x31, 0xCA, 0xE7, 0x04, 0xEB, 0x84, 0x04, ++0x05, 0xEB, 0x84, 0x04, 0x01, 0x23, 0xE3, 0x71, 0x74, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x14, 0xBC, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xCC, 0x35, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x80, 0x96, 0x98, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x04, 0x46, 0x06, 0x20, 0x25, 0x7A, 0xF8, 0xF7, 0x1F, 0xFB, 0x09, 0x28, 0x0A, 0xD0, 0x06, 0x20, 0xF8, 0xF7, 0x1A, 0xFB, ++0x48, 0xB1, 0x2D, 0x4A, 0x23, 0x7A, 0x12, 0x68, 0x92, 0xF8, 0x3D, 0x20, 0x9A, 0x42, 0x0D, 0xD0, 0x02, 0x20, 0xBD, 0xE8, ++0xF0, 0x87, 0x29, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0xF5, 0x7E, 0x19, 0x96, 0xF8, 0x64, 0x00, 0x60, 0xB9, ++0xBD, 0xE8, 0xF0, 0x87, 0x24, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0x15, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0x60, 0xFB, ++0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xA4, 0x89, 0x1F, 0x49, 0x22, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0x08, 0xFF, ++0x1D, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x0B, 0xB1, 0x08, 0x2C, 0x0A, 0xD0, 0x09, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x40, 0xFA, ++0x78, 0x19, 0x21, 0x46, 0xFF, 0xF7, 0xBC, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0x90, 0x31, 0x9B, 0x78, ++0x01, 0x2B, 0xEF, 0xD1, 0x96, 0xF8, 0xC0, 0x64, 0x00, 0x2E, 0xEB, 0xD1, 0xDF, 0xF8, 0x44, 0x90, 0x05, 0xF5, 0xB2, 0x7A, ++0xC8, 0x46, 0xBA, 0x44, 0x40, 0x46, 0x06, 0x22, 0x51, 0x46, 0x0C, 0xF0, 0x83, 0xFB, 0x08, 0xF1, 0x14, 0x08, 0x18, 0xB1, ++0x01, 0x36, 0x05, 0x2E, 0xF4, 0xD1, 0xD9, 0xE7, 0x06, 0xEB, 0x86, 0x06, 0x09, 0xEB, 0x86, 0x06, 0x01, 0x23, 0xB3, 0x71, ++0xD2, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2C, 0xBC, 0x15, 0x00, 0x50, 0xBC, 0x15, 0x00, ++0x2C, 0x19, 0x17, 0x00, 0xCC, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x46, 0x4B, 0x04, 0x7A, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, 0x64, 0x30, 0xC3, 0xB1, 0x94, 0xF8, 0x62, 0x30, 0xAB, 0xB9, 0xC3, 0x79, 0xFF, 0x2B, ++0x05, 0x46, 0x11, 0xD0, 0x94, 0xF8, 0x6C, 0x20, 0x9A, 0x42, 0x0D, 0xD1, 0x3D, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x02, 0x66, 0x96, 0xF8, 0x30, 0x30, 0x02, 0x2B, 0x04, 0xD1, 0x90, 0xF8, 0x0D, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x01, 0xD0, ++0xBD, 0xE8, 0xF8, 0x83, 0x80, 0x79, 0xB5, 0xF8, 0x0E, 0x80, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, ++0xE5, 0xF7, 0xAE, 0xFA, 0x07, 0x46, 0x00, 0x28, 0xF0, 0xD0, 0x01, 0x46, 0x20, 0x46, 0xF7, 0xF7, 0xA5, 0xFB, 0x32, 0x46, ++0xDF, 0xF8, 0xB4, 0xC0, 0xBB, 0x6C, 0x52, 0xF8, 0x26, 0x0F, 0xBC, 0xF8, 0xFC, 0x11, 0xD8, 0x66, 0x6F, 0xF0, 0x2F, 0x00, ++0x83, 0xF8, 0x68, 0x00, 0x01, 0x31, 0x90, 0x88, 0xA3, 0xF8, 0x70, 0x00, 0x89, 0xB2, 0xE0, 0x6D, 0xB4, 0xF8, 0x60, 0x40, ++0xA3, 0xF8, 0x76, 0x40, 0xC3, 0xF8, 0x72, 0x00, 0x14, 0x68, 0x90, 0x88, 0x83, 0xF8, 0x69, 0x90, 0x0A, 0x01, 0x83, 0xF8, ++0x6A, 0x90, 0x83, 0xF8, 0x6B, 0x90, 0x9C, 0x67, 0xA3, 0xF8, 0x7C, 0x00, 0xAC, 0xF8, 0xFC, 0x11, 0xA3, 0xF8, 0x7E, 0x20, ++0x2A, 0x7A, 0x3A, 0x77, 0xEA, 0x79, 0x7A, 0x77, 0x03, 0xF1, 0x68, 0x04, 0x87, 0xF8, 0x33, 0x90, 0x87, 0xF8, 0x35, 0x90, ++0x08, 0x22, 0xD0, 0x21, 0x38, 0x46, 0x06, 0xF0, 0xA5, 0xFB, 0x21, 0x46, 0x38, 0x46, 0x18, 0x22, 0x05, 0xF0, 0x04, 0xFA, ++0x97, 0xF8, 0x33, 0x30, 0x18, 0x33, 0x1A, 0x19, 0x08, 0x21, 0x19, 0x55, 0x01, 0x21, 0x51, 0x70, 0xF9, 0x6C, 0xA2, 0xF8, ++0x02, 0x80, 0x97, 0xF8, 0x35, 0x00, 0x4A, 0x6A, 0x04, 0x30, 0x03, 0x44, 0x01, 0x3A, 0x1A, 0x44, 0x04, 0x33, 0xC1, 0xE9, ++0x0A, 0x23, 0x38, 0x46, 0x05, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xE5, 0xF7, 0x5F, 0xBA, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x31, 0x4B, 0x32, 0x4A, 0x1B, 0x68, 0x2D, 0xE9, 0xF0, 0x41, 0xB3, 0xF9, ++0x00, 0x30, 0xD2, 0xF8, 0x00, 0x80, 0x2F, 0x4F, 0x98, 0xF8, 0x3D, 0x50, 0x00, 0x2B, 0x06, 0x46, 0x45, 0xDB, 0x2C, 0x23, ++0x06, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x06, 0x00, 0xF7, 0xF7, 0x64, 0xFF, 0x4F, 0xF4, 0xA4, 0x61, 0x03, 0x46, 0x98, 0xF8, ++0x3D, 0x20, 0x03, 0xF8, 0x01, 0x2B, 0x01, 0xFB, 0x05, 0x71, 0x01, 0xF5, 0xB5, 0x72, 0x04, 0x46, 0x01, 0xF5, 0xC5, 0x71, ++0xD2, 0xF8, 0x00, 0xE0, 0xD2, 0xF8, 0x04, 0xC0, 0x90, 0x68, 0xD2, 0xF8, 0x0C, 0x80, 0xC3, 0xF8, 0x0C, 0x80, 0x10, 0x32, ++0x8A, 0x42, 0xC3, 0xF8, 0x00, 0xE0, 0xC3, 0xF8, 0x04, 0xC0, 0x98, 0x60, 0x03, 0xF1, 0x10, 0x03, 0xEC, 0xD1, 0x4F, 0xF4, ++0xA4, 0x61, 0x12, 0x78, 0x1A, 0x70, 0x01, 0xFB, 0x05, 0x75, 0x36, 0xBA, 0xD5, 0xF8, 0x64, 0x01, 0xB5, 0xF8, 0x68, 0x31, ++0xE3, 0x84, 0x06, 0x21, 0xC4, 0xF8, 0x22, 0x00, 0xA6, 0x62, 0x08, 0x46, 0xF8, 0xF7, 0x2A, 0xF9, 0x41, 0xF6, 0x08, 0x00, ++0x0E, 0x4A, 0x06, 0x21, 0xF7, 0xF7, 0x88, 0xFD, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xF7, 0xF7, 0x55, 0xBF, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x05, 0x73, 0xD3, 0xF8, 0xCC, 0x31, 0x00, 0x2B, 0xB1, 0xDB, 0x07, 0x49, 0x07, 0x48, 0x4F, 0xF4, ++0xAB, 0x62, 0xF9, 0xF7, 0xF9, 0xFF, 0xAA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xC0, 0x27, 0x09, 0x00, 0x70, 0x79, 0x15, 0x00, 0x74, 0xBC, 0x15, 0x00, 0x10, 0xB5, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, ++0x08, 0x00, 0xF7, 0xF7, 0x11, 0xFE, 0x1C, 0xB9, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x20, 0xBC, 0x20, 0x46, 0xBD, 0xE8, ++0x10, 0x40, 0xFF, 0xF7, 0xFF, 0xB9, 0x00, 0xBF, 0x08, 0xB5, 0x06, 0x20, 0xF8, 0xF7, 0x96, 0xF9, 0xA0, 0xF1, 0x06, 0x00, ++0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x08, 0xBD, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x07, 0x02, 0xF8, 0xF7, 0xDE, 0xFD, ++0xB8, 0xB1, 0x9D, 0xF8, 0x07, 0x30, 0x1D, 0x2B, 0x16, 0xD9, 0x02, 0x89, 0x92, 0x00, 0x0A, 0x3B, 0x92, 0xB2, 0x9B, 0x1A, ++0xDB, 0xB2, 0x15, 0x2B, 0x0E, 0xD9, 0x0A, 0x30, 0x02, 0x3B, 0x81, 0x5A, 0x89, 0x00, 0x89, 0xB2, 0x5B, 0x1A, 0xDB, 0xB2, ++0x13, 0x2B, 0x10, 0x44, 0x04, 0xD9, 0x04, 0x30, 0x40, 0x5A, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x00, 0x20, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0xFB, 0x2D, 0xE9, 0xF0, 0x4F, 0x4F, 0xF4, 0xA4, 0x68, 0x95, 0xB0, 0xDF, 0xF8, 0x50, 0x93, 0xDF, 0xF8, ++0x50, 0xB3, 0x08, 0xFB, 0x00, 0xF3, 0x07, 0x93, 0x4B, 0x44, 0x05, 0x46, 0xD3, 0xF8, 0x90, 0x01, 0x93, 0xF8, 0x6C, 0x40, ++0x80, 0x78, 0x02, 0x93, 0x17, 0x46, 0x4F, 0xF4, 0x1E, 0x78, 0x00, 0x38, 0x08, 0xFB, 0x04, 0xB6, 0x0A, 0x46, 0x3B, 0x78, ++0xD6, 0xF8, 0xB0, 0xA0, 0x04, 0x94, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0x05, 0x92, 0x06, 0x93, 0xE5, 0xF7, ++0x6F, 0xF9, 0x00, 0x28, 0x00, 0xF0, 0xED, 0x80, 0x02, 0x9B, 0x04, 0x46, 0x21, 0x46, 0x18, 0x46, 0xF7, 0xF7, 0x64, 0xFA, ++0xB9, 0x4B, 0x96, 0xF8, 0x23, 0x00, 0xD3, 0xF8, 0x34, 0x21, 0xA3, 0x6C, 0x02, 0x93, 0x00, 0x21, 0x90, 0x47, 0x02, 0x9B, ++0x03, 0x90, 0x03, 0xF1, 0x68, 0x02, 0x08, 0x92, 0x00, 0x28, 0x40, 0xF0, 0xD9, 0x80, 0xB2, 0x49, 0xB1, 0xF8, 0xFC, 0x21, ++0x01, 0x32, 0x92, 0xB2, 0x08, 0x20, 0x83, 0xF8, 0x68, 0x00, 0x10, 0x01, 0x01, 0x26, 0x80, 0xB2, 0x83, 0xF8, 0x69, 0x60, ++0x09, 0x90, 0xA1, 0xF8, 0xFC, 0x21, 0x04, 0x99, 0x02, 0x93, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0xB2, 0x4F, 0xF4, ++0xA4, 0x66, 0x52, 0xF8, 0x26, 0x1F, 0xD9, 0x66, 0x06, 0xFB, 0x05, 0x96, 0x91, 0x88, 0xF0, 0x6D, 0xB6, 0xF8, 0x60, 0x20, ++0xA3, 0xF8, 0x76, 0x20, 0x4F, 0xF0, 0x00, 0x08, 0xA3, 0xF8, 0x70, 0x10, 0xC3, 0xF8, 0x72, 0x00, 0x05, 0x99, 0x83, 0xF8, ++0x6A, 0x80, 0x83, 0xF8, 0x6B, 0x80, 0x06, 0x22, 0x03, 0xF1, 0x78, 0x00, 0x0C, 0xF0, 0xDC, 0xF9, 0x09, 0x9B, 0x96, 0xF8, ++0x63, 0x20, 0x19, 0x01, 0x02, 0x9B, 0xA3, 0xF8, 0x7E, 0x10, 0x22, 0x77, 0x96, 0xF8, 0x6C, 0x20, 0x62, 0x77, 0x03, 0x9A, ++0x00, 0x2A, 0x00, 0xF0, 0xE1, 0x80, 0x1A, 0x22, 0x83, 0xF8, 0x80, 0x80, 0x83, 0xF8, 0x81, 0x80, 0x02, 0x92, 0x7A, 0x78, ++0x00, 0x21, 0x12, 0xF0, 0x40, 0x02, 0xCD, 0xE9, 0x0A, 0x11, 0x40, 0xF0, 0xB5, 0x80, 0x84, 0xF8, 0x33, 0x20, 0x84, 0xF8, ++0x35, 0x20, 0x89, 0x4B, 0x02, 0x9A, 0x93, 0xE8, 0x03, 0x00, 0x08, 0x9B, 0x13, 0x44, 0x1E, 0x46, 0x0D, 0xF1, 0x30, 0x0C, ++0x07, 0x9B, 0x8C, 0xE8, 0x03, 0x00, 0x08, 0x22, 0x61, 0x46, 0x30, 0x46, 0x03, 0xF1, 0x5C, 0x08, 0x0C, 0xF0, 0xA8, 0xF9, ++0x7F, 0x4B, 0xD3, 0xE9, 0x02, 0x01, 0x08, 0x22, 0x0E, 0xAB, 0x83, 0xE8, 0x03, 0x00, 0xC8, 0x44, 0x19, 0x46, 0xB0, 0x18, ++0x0C, 0xF0, 0x9C, 0xF9, 0x06, 0x22, 0x41, 0x46, 0x06, 0xF1, 0x10, 0x00, 0x0C, 0xF0, 0x96, 0xF9, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x05, 0x95, 0x9D, 0xF9, 0x18, 0x20, 0xD5, 0xF8, 0xC4, 0x34, 0xB3, 0x75, 0xD5, 0xF8, 0xC4, 0x34, 0x1B, 0x0A, ++0xF3, 0x75, 0xB5, 0xF8, 0xC6, 0x34, 0x33, 0x76, 0x95, 0xF8, 0xC7, 0x34, 0x73, 0x76, 0x7B, 0x78, 0x58, 0x06, 0x67, 0xD4, ++0x00, 0x2A, 0xB8, 0xBF, 0x07, 0xF1, 0x2A, 0x01, 0x4F, 0xF0, 0x0A, 0x02, 0xA8, 0xBF, 0x07, 0xF1, 0x28, 0x01, 0x06, 0xF1, ++0x1A, 0x00, 0x0C, 0xF0, 0x73, 0xF9, 0xE2, 0x6C, 0x94, 0xF8, 0x35, 0x50, 0x53, 0x6A, 0x02, 0x99, 0xA4, 0x65, 0x24, 0x35, ++0x0D, 0x44, 0x01, 0x3B, 0x2B, 0x44, 0x00, 0x20, 0x29, 0x1D, 0x60, 0x65, 0xC2, 0xE9, 0x0A, 0x31, 0x03, 0x9B, 0x6B, 0xB1, ++0x04, 0x9B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0xB3, 0x93, 0xF8, 0x23, 0x30, 0x02, 0xFB, 0x03, 0xBB, 0x9B, 0xF8, ++0xA5, 0x91, 0xB9, 0xF1, 0x21, 0x0F, 0x6A, 0xD1, 0x7B, 0x78, 0x59, 0x06, 0x2F, 0xD5, 0x9A, 0xF8, 0x60, 0x30, 0x01, 0x2B, ++0x00, 0xF0, 0x53, 0x81, 0x52, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x09, 0xD5, 0x9A, 0xF8, 0x60, 0x30, 0x01, 0x2B, ++0x0A, 0xF1, 0x64, 0x09, 0x40, 0xF2, 0x36, 0x81, 0x03, 0x2B, 0x00, 0xF0, 0x34, 0x81, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, ++0x8F, 0xF8, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x96, 0xF8, 0x23, 0x20, 0x08, 0xFB, 0x02, 0xB8, 0x6F, 0xF0, 0x77, 0x02, ++0xB8, 0xF8, 0x34, 0x11, 0x83, 0xF8, 0x68, 0x20, 0x4A, 0x1C, 0x01, 0x20, 0xC2, 0xF3, 0x0B, 0x02, 0x83, 0xF8, 0x69, 0x00, ++0x09, 0x91, 0x03, 0x90, 0xA8, 0xF8, 0x34, 0x21, 0x21, 0xE7, 0x3D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9A, 0x07, 0xDE, 0xD5, ++0xBA, 0xF1, 0x00, 0x0F, 0xDB, 0xD0, 0xD0, 0xE7, 0x00, 0x2A, 0xB8, 0xBF, 0x07, 0xF1, 0x32, 0x01, 0x4F, 0xF0, 0x0A, 0x02, ++0xA8, 0xBF, 0x07, 0xF1, 0x30, 0x01, 0x06, 0xF1, 0x1A, 0x00, 0x0C, 0xF0, 0x0B, 0xF9, 0x96, 0xE7, 0xE2, 0x6C, 0xB3, 0xF8, ++0x68, 0x10, 0x90, 0x6B, 0x41, 0xF4, 0x80, 0x41, 0xC2, 0x68, 0xA3, 0xF8, 0x68, 0x10, 0x22, 0xF4, 0x7F, 0x73, 0x9A, 0xF8, ++0x62, 0x20, 0x08, 0x99, 0x23, 0xF0, 0x03, 0x03, 0x13, 0x43, 0xC3, 0x60, 0x9A, 0xF8, 0x60, 0x30, 0x02, 0x98, 0x0E, 0x18, ++0x04, 0x2B, 0x00, 0xF2, 0xD3, 0x81, 0xDF, 0xE8, 0x03, 0xF0, 0x1E, 0x51, 0xBA, 0x1E, 0x85, 0x00, 0x18, 0x22, 0x02, 0x92, ++0x21, 0xE7, 0x4F, 0xEA, 0x09, 0x20, 0x40, 0xF0, 0x08, 0x00, 0xF7, 0xF7, 0xFD, 0xFF, 0x01, 0x28, 0x8C, 0xD1, 0x1E, 0x4B, ++0x09, 0x99, 0x09, 0xEB, 0x49, 0x09, 0x03, 0xEB, 0xC9, 0x09, 0x02, 0x22, 0xD9, 0xF8, 0x14, 0x00, 0x02, 0x90, 0x05, 0xF0, ++0x1D, 0xFB, 0x02, 0x98, 0x05, 0xF0, 0xF8, 0xFA, 0x7C, 0xE7, 0x04, 0x23, 0x84, 0xF8, 0x33, 0x30, 0x84, 0xF8, 0x35, 0x30, ++0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, ++0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0xBD, 0xF8, 0x02, 0x99, 0x08, 0x9A, 0xBD, 0xF8, 0x28, 0x30, 0x53, 0x52, ++0xBD, 0xF8, 0x2A, 0x30, 0x9A, 0xF8, 0x61, 0x20, 0x43, 0xEA, 0x82, 0x33, 0x73, 0x80, 0x94, 0xF8, 0x33, 0x30, 0xCB, 0x18, ++0x02, 0x93, 0xF0, 0xE6, 0x88, 0x1A, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x8C, 0xBC, 0x15, 0x00, 0x34, 0x36, 0x17, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x08, 0x22, 0x0C, 0x23, 0x84, 0xF8, 0x33, 0x20, ++0x84, 0xF8, 0x35, 0x30, 0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, ++0xE3, 0xE9, 0x12, 0x01, 0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0x89, 0xF8, 0xBD, 0xF8, 0x28, 0x20, 0x02, 0x99, ++0x42, 0xF4, 0x00, 0x53, 0x03, 0xF4, 0xFE, 0x43, 0x43, 0xEA, 0x12, 0x23, 0x08, 0x9A, 0x53, 0x52, 0x9D, 0xF8, 0x28, 0x30, ++0x9A, 0xF8, 0x61, 0x20, 0x43, 0xEA, 0x82, 0x33, 0x43, 0xF4, 0x00, 0x53, 0x73, 0x80, 0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, ++0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0x94, 0xF8, 0x33, 0x30, 0xCB, 0x18, 0x02, 0x93, 0xAE, 0xE6, 0x10, 0x23, 0x12, 0x21, ++0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x35, 0x30, 0x0F, 0x2A, 0xDA, 0xF8, 0x48, 0x30, 0xDA, 0xF8, 0x4C, 0x20, 0x40, 0xF2, ++0x00, 0x81, 0x02, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, 0x08, 0x22, ++0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0x50, 0xF8, 0x9A, 0xF8, 0x61, 0x30, 0x33, 0x80, 0xBD, 0xF8, 0x28, 0x30, 0x73, 0x80, ++0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, 0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0xBD, 0xF8, 0x2E, 0x30, 0x33, 0x81, 0x45, 0xF6, ++0x36, 0x43, 0x73, 0x81, 0xB3, 0x81, 0xF3, 0x81, 0x33, 0x82, 0x02, 0x9A, 0x94, 0xF8, 0x33, 0x30, 0x1A, 0x44, 0x02, 0x92, ++0x79, 0xE6, 0x08, 0x23, 0x84, 0xF8, 0x33, 0x30, 0x84, 0xF8, 0x35, 0x30, 0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, ++0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, 0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, ++0x21, 0xF8, 0x08, 0x9A, 0xBD, 0xF8, 0x28, 0x30, 0x10, 0x46, 0x02, 0x9A, 0x83, 0x52, 0x9A, 0xF8, 0x61, 0x30, 0x9B, 0x03, ++0x43, 0xF4, 0x00, 0x53, 0x73, 0x80, 0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, 0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0x94, 0xF8, ++0x33, 0x30, 0xD3, 0x18, 0x02, 0x93, 0x4E, 0xE6, 0x31, 0xD0, 0x03, 0x9B, 0x0D, 0xF1, 0x40, 0x0B, 0x00, 0x2B, 0x5D, 0xD1, ++0x94, 0xF8, 0x33, 0x70, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xEC, 0x37, 0x2F, 0x44, 0xBF, 0xB2, ++0x5C, 0xE0, 0x05, 0x99, 0x06, 0x22, 0x04, 0xF1, 0x0C, 0x00, 0x0B, 0xF0, 0xF3, 0xFF, 0x06, 0x22, 0x41, 0x46, 0x04, 0xF1, ++0x12, 0x00, 0x0B, 0xF0, 0xED, 0xFF, 0x03, 0x9B, 0x00, 0x22, 0xE2, 0x76, 0x00, 0x2B, 0x78, 0xD0, 0x94, 0xF8, 0x35, 0x10, ++0x94, 0xF8, 0x33, 0x30, 0x69, 0x48, 0x0B, 0x44, 0xEB, 0x1A, 0xD0, 0xF8, 0x7C, 0x73, 0x00, 0x92, 0x1A, 0x3B, 0x32, 0x46, ++0x0A, 0xF1, 0x50, 0x01, 0x20, 0x46, 0xB8, 0x47, 0x8A, 0xE6, 0x03, 0x9B, 0x94, 0xF8, 0x33, 0x70, 0x00, 0x2B, 0x00, 0xF0, ++0x82, 0x80, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xF2, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, ++0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x30, 0x46, 0xDA, 0xF7, 0x7E, 0xFE, 0xDA, 0xF8, 0x48, 0xC0, 0xDA, 0xF8, 0x4C, 0x00, ++0x57, 0x49, 0x4F, 0xEA, 0x1C, 0x43, 0x43, 0xEA, 0x00, 0x43, 0x0D, 0xF1, 0x40, 0x0B, 0x0B, 0x60, 0x42, 0x46, 0x5B, 0x46, ++0x48, 0x46, 0xA1, 0xF8, 0x04, 0xC0, 0xF7, 0xF7, 0x45, 0xF8, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0x05, 0xFA, 0x9A, 0xF8, ++0x60, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x85, 0x80, 0x94, 0xF8, 0x33, 0x70, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, ++0x7F, 0x47, 0xEA, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x39, 0x1F, 0x30, 0x46, 0xDA, 0xF7, ++0x51, 0xFE, 0x9A, 0xF8, 0x60, 0x30, 0xBA, 0xF8, 0x48, 0x10, 0xBA, 0xF8, 0x4A, 0x20, 0xAD, 0xF8, 0x40, 0x10, 0x8D, 0xF8, ++0x42, 0x20, 0x49, 0x46, 0x7B, 0xBB, 0x05, 0x22, 0x0D, 0xF1, 0x43, 0x00, 0x0B, 0xF0, 0x84, 0xFF, 0x58, 0x46, 0x08, 0x21, ++0xF7, 0xF7, 0xDA, 0xF9, 0x03, 0x20, 0xDA, 0xF7, 0x71, 0xFE, 0x39, 0x46, 0x02, 0x46, 0x30, 0x46, 0xF7, 0xF7, 0x04, 0xF8, ++0x39, 0x46, 0x30, 0x46, 0xF7, 0xF7, 0xFA, 0xF9, 0x20, 0x46, 0x05, 0x21, 0xE4, 0xF7, 0xC6, 0xFE, 0x35, 0xE6, 0x94, 0xF8, ++0x35, 0x20, 0x94, 0xF8, 0x33, 0x30, 0x2D, 0x49, 0x13, 0x44, 0xD1, 0xF8, 0x7C, 0x73, 0x03, 0x99, 0x00, 0x91, 0xEB, 0x1A, ++0x18, 0x3B, 0x32, 0x46, 0x0A, 0xF1, 0x50, 0x01, 0x20, 0x46, 0xB8, 0x47, 0x10, 0xE6, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, ++0xFE, 0xE6, 0x0D, 0x22, 0x0D, 0xF1, 0x43, 0x00, 0x0B, 0xF0, 0x54, 0xFF, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0xAA, 0xF9, ++0xCE, 0xE7, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xF4, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, ++0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x30, 0x46, 0xDA, 0xF7, 0xFC, 0xFD, 0xDA, 0xF8, 0x48, 0xC0, 0xDA, 0xF8, 0x4C, 0x00, ++0x16, 0x49, 0x4F, 0xEA, 0x1C, 0x43, 0x43, 0xEA, 0x00, 0x43, 0x0D, 0xF1, 0x40, 0x0B, 0x0B, 0x60, 0x42, 0x46, 0x5B, 0x46, ++0x48, 0x46, 0xA1, 0xF8, 0x04, 0xC0, 0xF6, 0xF7, 0xC3, 0xFF, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0x83, 0xF9, 0x9A, 0xF8, ++0x60, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x20, 0xAF, 0x03, 0x2B, 0xA1, 0xD1, 0x1C, 0xE7, 0x03, 0x2B, 0x9E, 0xD1, 0x77, 0xE7, ++0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xDC, 0xAE, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, ++0x2C, 0x62, 0xF9, 0xF7, 0x6B, 0xFC, 0xD4, 0xE6, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x34, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x05, 0xDB, 0x0A, 0x4B, 0x00, 0x20, 0x5B, 0x68, 0x98, 0x47, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x10, 0xFE, ++0x02, 0x28, 0xF4, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x31, 0x12, 0xF9, 0xF7, 0x48, 0xFC, 0xED, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xC0, 0xBC, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x0C, 0x46, 0x36, 0x49, 0x60, 0x7C, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x10, 0x86, 0xB0, 0x90, 0xF8, 0x62, 0x10, ++0x00, 0x25, 0x02, 0x29, 0x98, 0x46, 0x8D, 0xF8, 0x0B, 0x50, 0x10, 0xD0, 0x04, 0x25, 0x41, 0x46, 0x02, 0x23, 0x41, 0xF6, ++0x05, 0x40, 0xF7, 0xF7, 0x43, 0xFB, 0x05, 0x70, 0x9D, 0xF8, 0x0B, 0x20, 0x42, 0x70, 0xF7, 0xF7, 0x6D, 0xFB, 0x00, 0x20, ++0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x90, 0xF8, 0x64, 0x10, 0x09, 0xB1, 0x08, 0x25, 0xEA, 0xE7, 0x07, 0x20, 0x01, 0x92, ++0xF7, 0xF7, 0xD2, 0xFD, 0x01, 0x9A, 0x00, 0x28, 0xF6, 0xD1, 0xA7, 0x78, 0x20, 0x7C, 0x21, 0x88, 0x1F, 0x4E, 0x8D, 0xF8, ++0x0C, 0x70, 0x8D, 0xF8, 0x0D, 0x00, 0xA7, 0x68, 0xE0, 0x68, 0xAD, 0xF8, 0x0E, 0x10, 0x21, 0x79, 0x75, 0x6C, 0xAD, 0xF8, ++0x12, 0x00, 0x8D, 0xF8, 0x14, 0x10, 0xAD, 0xF8, 0x10, 0x70, 0x0D, 0xF1, 0x0B, 0x01, 0x03, 0xA8, 0xA8, 0x47, 0x01, 0x9A, ++0x05, 0x46, 0x10, 0xBB, 0xF6, 0x6C, 0x60, 0x7C, 0x9D, 0xF8, 0x0B, 0x10, 0xB0, 0x47, 0xEF, 0xF3, 0x10, 0x81, 0x11, 0xF0, ++0x01, 0x0F, 0x01, 0x9A, 0x03, 0xD1, 0x72, 0xB6, 0x0E, 0x49, 0x01, 0x20, 0x08, 0x60, 0x0E, 0x48, 0x0E, 0x4F, 0x04, 0x68, ++0x79, 0x68, 0x66, 0x1C, 0x41, 0xF0, 0x10, 0x01, 0x06, 0x60, 0x79, 0x60, 0x00, 0x2E, 0xAE, 0xD0, 0x07, 0x49, 0x04, 0x60, ++0x09, 0x68, 0x00, 0x2C, 0xA9, 0xD1, 0x00, 0x29, 0xA7, 0xD0, 0x62, 0xB6, 0xA5, 0xE7, 0x01, 0x25, 0xA3, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x43, 0x0C, 0x46, 0x85, 0xB0, 0x90, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x4A, 0x69, 0x4D, 0x49, 0x4E, 0x4F, ++0x99, 0x46, 0xF9, 0xF7, 0x8D, 0xF9, 0x94, 0xF8, 0x33, 0x60, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x06, 0x75, 0x95, 0xF8, ++0x62, 0x10, 0x02, 0x29, 0x11, 0xD0, 0x04, 0x25, 0x42, 0x46, 0x49, 0x46, 0x04, 0x23, 0x41, 0xF6, 0x01, 0x40, 0xF7, 0xF7, ++0xC3, 0xFA, 0x05, 0x70, 0x94, 0xF8, 0x33, 0x20, 0x42, 0x70, 0xF7, 0xF7, 0xED, 0xFA, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x83, 0x07, 0x20, 0xF7, 0xF7, 0x58, 0xFD, 0xC0, 0xB9, 0x95, 0xF8, 0x64, 0x30, 0xBB, 0xB9, 0x3B, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x13, 0xDB, 0x23, 0x7F, 0x39, 0x49, 0x00, 0x93, 0xD4, 0xE9, 0x05, 0x23, 0x0C, 0x60, ++0x0D, 0xF1, 0x0D, 0x00, 0x04, 0xF1, 0x0E, 0x01, 0xFD, 0xF7, 0xAC, 0xF9, 0x05, 0x46, 0x70, 0xB1, 0x01, 0x25, 0xD1, 0xE7, ++0x08, 0x25, 0xCF, 0xE7, 0x09, 0x25, 0xCD, 0xE7, 0x2B, 0x6C, 0x00, 0x2B, 0xE8, 0xD0, 0x2F, 0x49, 0x2F, 0x48, 0x56, 0x22, ++0xF9, 0xF7, 0x72, 0xFB, 0xE2, 0xE7, 0xE1, 0x89, 0x20, 0x7C, 0xDF, 0xF8, 0xB4, 0x80, 0xFB, 0xF7, 0x9B, 0xFF, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x06, 0xF2, 0x07, 0xEB, 0x02, 0x09, 0xC9, 0xF8, 0x90, 0x01, 0x94, 0xF9, 0x12, 0x30, 0x03, 0x71, ++0xD4, 0xE9, 0x05, 0x31, 0xA9, 0xF8, 0x96, 0x11, 0xA9, 0xF8, 0x94, 0x31, 0x23, 0x7F, 0x89, 0xF8, 0xC5, 0x31, 0x04, 0x2B, ++0x08, 0xBF, 0x03, 0x23, 0x89, 0xF8, 0xC4, 0x31, 0x89, 0xF8, 0xC6, 0x51, 0xD8, 0xF8, 0x4C, 0x30, 0x94, 0xF8, 0x33, 0x00, ++0x9D, 0xF8, 0x0D, 0x10, 0x15, 0x46, 0x98, 0x47, 0x23, 0x7C, 0xA3, 0xB1, 0x00, 0xF0, 0x8C, 0xFA, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x06, 0x73, 0x78, 0x19, 0xD3, 0xF8, 0x90, 0x31, 0xD8, 0xF8, 0x40, 0x43, 0x1B, 0x79, 0x8D, 0xF8, 0x0E, 0x30, ++0x0D, 0xF1, 0x0F, 0x02, 0x0D, 0xF1, 0x0E, 0x01, 0xA0, 0x47, 0x01, 0x20, 0x92, 0xE7, 0x05, 0xF5, 0xCE, 0x70, 0x38, 0x44, ++0x01, 0x21, 0xFC, 0xF7, 0x45, 0xF9, 0x10, 0xF0, 0x0F, 0x00, 0x1A, 0xBF, 0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x1F, 0x03, ++0x01, 0x23, 0x89, 0xF8, 0xC1, 0x31, 0xD9, 0xE7, 0xEC, 0xBC, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x94, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x4F, 0x88, ++0x0D, 0x48, 0x0C, 0x46, 0x16, 0x46, 0x04, 0x31, 0x3A, 0x46, 0x1D, 0x46, 0x0B, 0xF0, 0xAE, 0xFD, 0xDF, 0xF8, 0x28, 0xC0, ++0x32, 0x46, 0x29, 0x46, 0x02, 0x23, 0x41, 0xF6, 0x09, 0x40, 0xAC, 0xF8, 0x00, 0x70, 0xF7, 0xF7, 0x1B, 0xFA, 0x01, 0x22, ++0x02, 0x70, 0x22, 0x78, 0x42, 0x70, 0xF7, 0xF7, 0x45, 0xFA, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x14, 0x2A, 0x17, 0x00, ++0x14, 0x2C, 0x17, 0x00, 0x08, 0xB5, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x07, 0x20, ++0xF7, 0xF7, 0xA6, 0xFC, 0x01, 0x28, 0x06, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0xA1, 0xFC, 0x03, 0x28, 0x01, 0xD0, 0x00, 0x20, ++0x08, 0xBD, 0x00, 0xF0, 0x01, 0xFA, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x96, 0xFC, 0x01, 0x28, 0xEA, 0xD0, ++0x07, 0x20, 0xF7, 0xF7, 0x91, 0xFC, 0x00, 0x28, 0xE5, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x8C, 0xFC, 0x03, 0x28, 0xE0, 0xD0, ++0x03, 0x49, 0x04, 0x48, 0xC2, 0x22, 0xF9, 0xF7, 0xC5, 0xFA, 0xDA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xFC, 0xBC, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, ++0xDB, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x70, 0xFC, 0x01, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, ++0xE6, 0x22, 0xF9, 0xF7, 0xA9, 0xFA, 0x00, 0xF0, 0xCD, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0xBD, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x03, 0xDB, 0x00, 0xF0, 0xBB, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x50, 0xFC, 0x03, 0x28, 0xF6, 0xD0, ++0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0xF9, 0xF7, 0x88, 0xFA, 0x00, 0xF0, 0xAC, 0xF9, 0x00, 0x20, 0x08, 0xBD, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB4, 0xBD, 0x15, 0x00, 0x08, 0xB5, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x06, 0xDB, 0x07, 0x20, 0xF7, 0xF7, 0x34, 0xFC, 0x03, 0x28, 0x12, 0xD0, 0x00, 0x20, 0x08, 0xBD, ++0x07, 0x20, 0xF7, 0xF7, 0x2D, 0xFC, 0x03, 0x28, 0xF3, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x28, 0xFC, 0x00, 0x28, 0xEE, 0xD0, ++0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0x65, 0x12, 0xF9, 0xF7, 0x60, 0xFA, 0xE7, 0xE7, 0x00, 0xF0, 0x83, 0xF9, 0x00, 0x20, ++0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xDC, 0xBD, 0x15, 0x00, 0xF8, 0xB5, 0x0C, 0x46, ++0x4F, 0xF4, 0x80, 0x70, 0x13, 0x49, 0x16, 0x46, 0x1D, 0x46, 0xF9, 0xF7, 0x21, 0xF8, 0x24, 0x78, 0x11, 0x4B, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, 0x62, 0x70, 0x02, 0x2F, 0x02, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x3B, 0xB9, ++0x32, 0x46, 0x29, 0x46, 0x41, 0xF6, 0x03, 0x40, 0xF7, 0xF7, 0xBE, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x07, 0x20, 0xF7, 0xF7, ++0xF3, 0xFB, 0x05, 0x46, 0x28, 0xB9, 0x06, 0x4B, 0x20, 0x46, 0x9B, 0x68, 0x98, 0x47, 0x28, 0x46, 0xF8, 0xBD, 0x38, 0x46, ++0xF8, 0xBD, 0x00, 0xBF, 0x30, 0xBE, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0C, 0x46, ++0x21, 0x49, 0x20, 0x78, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x10, 0x82, 0xB0, 0x90, 0xF8, 0x62, 0x50, 0x02, 0x2D, ++0x19, 0x46, 0x06, 0xD0, 0x41, 0xF6, 0x07, 0x40, 0xF7, 0xF7, 0x96, 0xF9, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x90, 0xF8, ++0x64, 0x30, 0x00, 0x2B, 0xF4, 0xD1, 0x07, 0x20, 0xCD, 0xE9, 0x00, 0x21, 0xF7, 0xF7, 0xC4, 0xFB, 0xDD, 0xE9, 0x00, 0x21, ++0x00, 0x28, 0xEB, 0xD1, 0x12, 0x4B, 0x20, 0x78, 0x5B, 0x6D, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0x13, 0xF0, 0x01, 0x0F, ++0xDD, 0xE9, 0x00, 0x21, 0x03, 0xD1, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x0D, 0x48, 0x0D, 0x4E, 0x04, 0x68, ++0x73, 0x68, 0x65, 0x1C, 0x23, 0xF0, 0x10, 0x03, 0x05, 0x60, 0x73, 0x60, 0x00, 0x2D, 0xD1, 0xD0, 0x06, 0x4B, 0x04, 0x60, ++0x1B, 0x68, 0x00, 0x2C, 0xCC, 0xD1, 0x00, 0x2B, 0xCA, 0xD0, 0x62, 0xB6, 0xC8, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x22, 0x4C, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0x07, 0x20, 0xF7, 0xF7, 0x88, 0xFB, 0x01, 0x28, 0x13, 0xD1, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0x9B, 0xF9, 0x00, 0x20, 0x10, 0xBD, 0x19, 0x4B, ++0x5B, 0x68, 0x00, 0x2B, 0xF7, 0xD0, 0x18, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x0B, 0x12, 0xF9, 0xF7, 0xB3, 0xF9, 0xF0, 0xE7, ++0x07, 0x20, 0xF7, 0xF7, 0x6F, 0xFB, 0x03, 0x28, 0xED, 0xD1, 0x07, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x03, 0x40, 0xF7, 0xF7, ++0x2D, 0xF9, 0x00, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0xBB, 0xFA, 0xE2, 0xE7, 0x07, 0x20, 0xF7, 0xF7, 0x5F, 0xFB, 0x01, 0x28, ++0xD1, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x5A, 0xFB, 0x00, 0x28, 0xCC, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x55, 0xFB, 0x03, 0x28, ++0xC7, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x03, 0x12, 0xF9, 0xF7, 0x8D, 0xF9, 0xC0, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x94, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0xBE, 0x15, 0x00, 0xFC, 0xBC, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x08, 0x40, 0x09, 0x48, 0xF7, 0xF7, 0x1E, 0xBD, ++0x08, 0x4B, 0x5B, 0x68, 0x00, 0x2B, 0xF6, 0xD0, 0x07, 0x48, 0x08, 0x49, 0x2D, 0x22, 0xF9, 0xF7, 0x6D, 0xF9, 0xBD, 0xE8, ++0x08, 0x40, 0x02, 0x48, 0xF7, 0xF7, 0x10, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x98, 0xBA, 0x17, 0x00, 0x94, 0xBA, 0x17, 0x00, ++0x3C, 0xBE, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0x00, 0x21, 0x20, 0x46, 0x10, 0x22, 0xD4, 0xF7, ++0x6F, 0xFC, 0x00, 0x21, 0x21, 0x73, 0x07, 0x20, 0xBD, 0xE8, 0x10, 0x40, 0xF7, 0xF7, 0x68, 0xBA, 0x94, 0xBA, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0xD8, 0x80, 0x05, 0x46, 0x04, 0x23, 0x07, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x01, 0x40, ++0xD8, 0xF8, 0x00, 0x60, 0xF7, 0xF7, 0x5E, 0xF8, 0x04, 0x46, 0x95, 0xB1, 0x96, 0xF8, 0x33, 0x30, 0x63, 0x70, 0x20, 0x46, ++0x25, 0x70, 0xF7, 0xF7, 0x85, 0xF8, 0xA6, 0xF1, 0x0C, 0x00, 0xF7, 0xF7, 0xCD, 0xF8, 0x00, 0x21, 0xC8, 0xF8, 0x00, 0x10, ++0x07, 0x20, 0xBD, 0xE8, 0xF0, 0x47, 0xF7, 0xF7, 0x43, 0xBA, 0x04, 0x23, 0x29, 0x46, 0x07, 0x22, 0x1E, 0x20, 0x96, 0xF8, ++0x33, 0x70, 0xF7, 0xF7, 0x41, 0xF8, 0x21, 0x4A, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x07, 0x29, 0x4F, 0xF0, 0x01, 0x0A, ++0x80, 0xF8, 0x02, 0xA0, 0x99, 0xF8, 0x63, 0x20, 0xC2, 0x70, 0xF7, 0xF7, 0x63, 0xF8, 0xF1, 0x6A, 0x32, 0x8E, 0xD9, 0xF8, ++0x40, 0x30, 0xC9, 0xF8, 0xB0, 0x14, 0xA9, 0xF8, 0xE0, 0x20, 0x89, 0xF8, 0xDE, 0x50, 0x1B, 0x7E, 0xA3, 0x70, 0x96, 0xF8, ++0x33, 0x30, 0xDF, 0xF8, 0x54, 0xC0, 0x0A, 0x33, 0xE3, 0x70, 0x96, 0xE8, 0x0F, 0x00, 0x4F, 0xF4, 0x1E, 0x7E, 0x0A, 0x37, ++0x0E, 0xFB, 0x07, 0xC7, 0x07, 0xF1, 0xB8, 0x0C, 0xAC, 0xE8, 0x07, 0x00, 0x02, 0x22, 0x87, 0xF8, 0x30, 0x20, 0x8C, 0xF8, ++0x00, 0x30, 0x38, 0x46, 0xFB, 0xF7, 0xA0, 0xFF, 0x97, 0xF8, 0x56, 0x31, 0xA7, 0xF8, 0x26, 0xA0, 0x43, 0xF0, 0x10, 0x03, ++0x87, 0xF8, 0x56, 0x31, 0x96, 0xF8, 0x33, 0x30, 0x03, 0xF1, 0x0A, 0x02, 0x87, 0xF8, 0x23, 0x20, 0xA4, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x94, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x48, 0xF7, 0xF7, 0xC6, 0xFC, ++0x0B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x05, 0xDB, 0x04, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, ++0x10, 0x40, 0xF7, 0xF7, 0x17, 0xB8, 0x00, 0x28, 0xF7, 0xD1, 0x05, 0x49, 0x05, 0x48, 0xCB, 0x22, 0xF9, 0xF7, 0xC2, 0xF8, ++0xF1, 0xE7, 0x00, 0xBF, 0x98, 0xBA, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x4F, 0x44, 0x4B, 0xDF, 0xF8, 0x1C, 0xB1, 0x1C, 0x68, 0x07, 0x22, 0x08, 0x23, 0x00, 0x21, 0x18, 0x20, ++0x94, 0xF8, 0x33, 0x90, 0xF6, 0xF7, 0xC8, 0xFF, 0x08, 0x23, 0x07, 0x22, 0x00, 0x21, 0x06, 0x46, 0x16, 0x20, 0xF6, 0xF7, ++0xC1, 0xFF, 0x04, 0x23, 0x07, 0x22, 0x00, 0x21, 0x05, 0x46, 0x14, 0x20, 0xF6, 0xF7, 0xBA, 0xFF, 0x02, 0x23, 0x07, 0x22, ++0x05, 0x21, 0x80, 0x46, 0x41, 0xF2, 0x17, 0x40, 0xF6, 0xF7, 0xB2, 0xFF, 0x4F, 0xF4, 0xA4, 0x6A, 0x0A, 0xFB, 0x09, 0xBA, ++0x07, 0x46, 0xFF, 0xF7, 0x0B, 0xFF, 0x9A, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x49, 0xD0, 0x2F, 0x4A, 0x13, 0x68, 0x23, 0xF0, ++0x04, 0x03, 0x13, 0x60, 0xDA, 0xF8, 0x04, 0x30, 0x43, 0xF0, 0x20, 0x03, 0xCA, 0xF8, 0x04, 0x30, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x09, 0xB9, 0xA6, 0xF1, 0x0C, 0x01, 0xD9, 0xF8, 0x5C, 0x00, 0xB9, 0xF8, 0x60, 0x30, 0xB3, 0x80, 0x30, 0x60, ++0x94, 0xF8, 0x33, 0x30, 0xB3, 0x71, 0x23, 0x48, 0xF7, 0xF7, 0x18, 0xFC, 0x23, 0x7C, 0x6B, 0x71, 0x01, 0x21, 0x20, 0x46, ++0xFB, 0xF7, 0x80, 0xFE, 0x28, 0x60, 0x94, 0xF8, 0x33, 0x30, 0x2B, 0x71, 0xA5, 0xF1, 0x0C, 0x01, 0x1B, 0x48, 0xF7, 0xF7, ++0x09, 0xFC, 0x23, 0x8D, 0xA8, 0xF8, 0x00, 0x30, 0x94, 0xF8, 0x33, 0x30, 0x88, 0xF8, 0x02, 0x30, 0xA8, 0xF1, 0x0C, 0x01, ++0x01, 0x25, 0x15, 0x48, 0xF7, 0xF7, 0xFC, 0xFB, 0x3D, 0x70, 0x94, 0xF8, 0x33, 0x30, 0x12, 0x48, 0x7B, 0x70, 0xA7, 0xF1, ++0x0C, 0x01, 0xF7, 0xF7, 0xF3, 0xFB, 0xFF, 0xF7, 0x6B, 0xFF, 0x29, 0x46, 0x07, 0x20, 0xBD, 0xE8, 0xF8, 0x4F, 0xF7, 0xF7, ++0x57, 0xB9, 0x02, 0x23, 0x07, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF6, 0xF7, 0x56, 0xFF, 0x01, 0x23, 0x03, 0x70, ++0x9A, 0xF8, 0x63, 0x30, 0x43, 0x70, 0x03, 0x4B, 0x01, 0x46, 0x0C, 0x39, 0x18, 0x1D, 0xF7, 0xF7, 0xD9, 0xFB, 0xAD, 0xE7, ++0x94, 0xBA, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x98, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0xB5, 0x0E, 0x4C, ++0x0C, 0x23, 0x07, 0x22, 0x00, 0x21, 0x3F, 0x20, 0x24, 0x68, 0xF6, 0xF7, 0x39, 0xFF, 0xA1, 0x8C, 0xE2, 0x8C, 0x25, 0x6A, ++0x05, 0x60, 0x81, 0x80, 0xC2, 0x80, 0x94, 0xF8, 0x32, 0x20, 0x02, 0x72, 0x94, 0xF8, 0x33, 0x20, 0x42, 0x72, 0xF6, 0xF7, ++0x5B, 0xFF, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0x1F, 0xB9, 0x00, 0xBF, 0x94, 0xBA, 0x17, 0x00, ++0xF8, 0xB5, 0x07, 0x22, 0x04, 0x46, 0x02, 0x23, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF6, 0xF7, 0x19, 0xFF, 0x02, 0x23, ++0x06, 0x46, 0x07, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x17, 0x40, 0xF6, 0xF7, 0x11, 0xFF, 0x00, 0x27, 0x05, 0x46, 0xFF, 0xF7, ++0x6D, 0xFE, 0x37, 0x70, 0x94, 0xF8, 0x63, 0x30, 0x73, 0x70, 0x1D, 0x48, 0xA6, 0xF1, 0x0C, 0x01, 0xF7, 0xF7, 0x92, 0xFB, ++0x94, 0xF8, 0x64, 0x30, 0x0B, 0xBB, 0x23, 0x6C, 0x6B, 0xB1, 0x01, 0x23, 0x00, 0x21, 0x07, 0x22, 0x39, 0x20, 0xF6, 0xF7, ++0xF9, 0xFE, 0x01, 0x46, 0x94, 0xF8, 0x63, 0x30, 0x01, 0xF8, 0x0C, 0x39, 0x12, 0x48, 0xF7, 0xF7, 0x7F, 0xFB, 0x00, 0x23, ++0x2B, 0x70, 0x94, 0xF8, 0x63, 0x30, 0x0F, 0x48, 0x6B, 0x70, 0xA5, 0xF1, 0x0C, 0x01, 0xF7, 0xF7, 0x75, 0xFB, 0xFF, 0xF7, ++0xED, 0xFE, 0xBD, 0xE8, 0xF8, 0x40, 0x03, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0xD9, 0xB8, 0x39, 0x46, 0x04, 0x23, 0x07, 0x22, ++0x1E, 0x20, 0xF6, 0xF7, 0xD9, 0xFE, 0x87, 0x70, 0x94, 0xF8, 0x63, 0x30, 0xC3, 0x70, 0xA0, 0xF1, 0x0C, 0x01, 0x02, 0x48, ++0xF7, 0xF7, 0x5E, 0xFB, 0xCD, 0xE7, 0x00, 0xBF, 0x98, 0xBA, 0x17, 0x00, 0x15, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, ++0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x13, 0xD1, 0x43, 0x7F, 0x0D, 0x2B, 0x10, 0xD8, 0x82, 0x88, ++0x2A, 0xB9, 0x82, 0x6C, 0xB2, 0xF8, 0x68, 0x20, 0xB2, 0xF5, 0x12, 0x7F, 0x08, 0xD0, 0x0C, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, ++0x01, 0xFB, 0x03, 0x22, 0x92, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x02, 0xD0, 0x01, 0x23, 0x18, 0x46, 0x70, 0x47, 0x92, 0xF8, ++0x32, 0x20, 0x12, 0xF0, 0x03, 0x02, 0xF8, 0xD1, 0xC1, 0x8B, 0x41, 0xF4, 0x80, 0x51, 0x13, 0x46, 0xC1, 0x83, 0xF2, 0xE7, ++0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xC3, 0x8B, 0xDB, 0x04, 0x00, 0xD4, 0x70, 0x47, 0x10, 0xB5, 0x0C, 0x46, ++0xC2, 0x7E, 0x15, 0x49, 0x94, 0xF8, 0x2E, 0x31, 0x8A, 0x5C, 0x13, 0x42, 0x1A, 0xD0, 0x94, 0xF8, 0x31, 0x20, 0x11, 0x07, ++0x1A, 0xD4, 0x42, 0xF0, 0x08, 0x02, 0x0F, 0x2B, 0x84, 0xF8, 0x31, 0x20, 0x14, 0xD1, 0x05, 0x22, 0x04, 0x23, 0x00, 0x21, ++0x41, 0x20, 0xF6, 0xF7, 0x7F, 0xFE, 0x22, 0x8C, 0x02, 0x80, 0x94, 0xF8, 0x22, 0x20, 0xC2, 0x70, 0x01, 0x22, 0x82, 0x70, ++0xBD, 0xE8, 0x10, 0x40, 0xF6, 0xF7, 0xA4, 0xBE, 0x94, 0xF8, 0x31, 0x30, 0x9A, 0x07, 0x00, 0xD5, 0x10, 0xBD, 0x43, 0xF0, ++0x02, 0x03, 0x84, 0xF8, 0x31, 0x30, 0xE4, 0xE7, 0xA4, 0xB2, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x90, 0xF8, 0x62, 0x70, ++0x02, 0x2F, 0x91, 0x46, 0x5A, 0xD1, 0x91, 0xF8, 0x32, 0x20, 0x0E, 0x46, 0x00, 0x2A, 0x55, 0xD0, 0x12, 0xF0, 0x01, 0x08, ++0x91, 0xF8, 0x31, 0x30, 0x04, 0xBF, 0x08, 0x27, 0x4F, 0xF0, 0x04, 0x08, 0x1F, 0x42, 0x78, 0xD0, 0xD1, 0xF8, 0xFC, 0x41, ++0x00, 0x2C, 0x68, 0xD0, 0xA2, 0xF1, 0x02, 0x02, 0xB2, 0xFA, 0x82, 0xF2, 0x91, 0xF8, 0x2E, 0x11, 0x3C, 0x4D, 0x52, 0x09, ++0x4F, 0xF0, 0x00, 0x0A, 0x04, 0xE0, 0x23, 0x68, 0xA2, 0x46, 0x00, 0x2B, 0x59, 0xD0, 0x1C, 0x46, 0xE3, 0x7E, 0xEB, 0x5C, ++0x19, 0x42, 0x0C, 0xBF, 0x01, 0x23, 0x00, 0x23, 0x93, 0x42, 0xF2, 0xD0, 0x51, 0x46, 0x22, 0x46, 0x06, 0xF5, 0xFE, 0x70, ++0xF7, 0xF7, 0xC8, 0xFB, 0x96, 0xF8, 0x32, 0x10, 0x11, 0xF0, 0x08, 0x0F, 0x0C, 0xBF, 0x03, 0x23, 0x04, 0x23, 0xE3, 0x76, ++0xBA, 0xF1, 0x00, 0x0F, 0x52, 0xD0, 0xDA, 0xF8, 0x00, 0x30, 0x0B, 0xB3, 0xA1, 0xF1, 0x02, 0x01, 0xB1, 0xFA, 0x81, 0xF1, ++0x96, 0xF8, 0x2E, 0x01, 0x49, 0x09, 0x01, 0xE0, 0x1B, 0x68, 0xBB, 0xB1, 0xDA, 0x7E, 0xAA, 0x5C, 0x10, 0x42, 0x0C, 0xBF, ++0x01, 0x22, 0x00, 0x22, 0x8A, 0x42, 0xF5, 0xD0, 0xA2, 0x6C, 0xB2, 0xF8, 0x68, 0x30, 0x43, 0xF4, 0x00, 0x53, 0xA2, 0xF8, ++0x68, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x24, 0xC9, 0xF8, 0x00, 0x40, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, ++0x96, 0xF8, 0x31, 0x10, 0x21, 0xEA, 0x07, 0x07, 0x17, 0xEA, 0x08, 0x01, 0x86, 0xF8, 0x31, 0x70, 0x07, 0xEA, 0x08, 0x05, ++0xE4, 0xD1, 0x04, 0x23, 0x05, 0x22, 0x41, 0x20, 0xF6, 0xF7, 0xF0, 0xFD, 0x32, 0x8C, 0x02, 0x80, 0x96, 0xF8, 0x22, 0x20, ++0xC2, 0x70, 0x85, 0x70, 0xF6, 0xF7, 0x18, 0xFE, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0xDA, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0x91, 0x12, 0xF8, 0xF7, 0xD3, 0xFE, 0x01, 0x23, ++0x00, 0x24, 0xC9, 0xF8, 0x00, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0xFC, 0x31, 0xAB, 0xE7, 0x00, 0xBF, ++0xA4, 0xB2, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0xB5, 0x90, 0xF8, ++0x62, 0x30, 0x02, 0x2B, 0x14, 0xD1, 0x13, 0x4C, 0x13, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0x44, 0x21, 0x46, ++0xD3, 0xF8, 0x20, 0x33, 0x00, 0x22, 0x98, 0x47, 0x94, 0xF8, 0x31, 0x10, 0x11, 0xF0, 0x0A, 0x0F, 0x04, 0xD0, 0x01, 0xF0, ++0xF5, 0x05, 0x84, 0xF8, 0x31, 0x50, 0x05, 0xB1, 0x38, 0xBD, 0x29, 0x46, 0x04, 0x23, 0x05, 0x22, 0x41, 0x20, 0xF6, 0xF7, ++0xA5, 0xFD, 0x94, 0xF8, 0x22, 0x20, 0x21, 0x8C, 0xC2, 0x70, 0x85, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x01, 0x80, 0xF6, 0xF7, ++0xCB, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x03, 0x6C, 0x2D, 0xE9, 0xF0, 0x41, 0x04, 0x46, ++0x88, 0x46, 0x00, 0x2B, 0x6C, 0xD0, 0x3A, 0x4A, 0x1B, 0x79, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x53, 0xDB, ++0x94, 0xF8, 0xC0, 0x24, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE4, 0xF7, 0x4C, 0xF8, ++0x05, 0x46, 0x00, 0x28, 0x56, 0xD0, 0x01, 0x46, 0x20, 0x46, 0xF6, 0xF7, 0x43, 0xF9, 0xAE, 0x6C, 0x00, 0x27, 0x6F, 0xF0, ++0x3F, 0x03, 0x41, 0x46, 0x86, 0xF8, 0x68, 0x30, 0x86, 0xF8, 0x69, 0x70, 0x86, 0xF8, 0x6A, 0x70, 0x86, 0xF8, 0x6B, 0x70, ++0x06, 0xF1, 0x6C, 0x00, 0x06, 0x22, 0x0B, 0xF0, 0xED, 0xF8, 0x26, 0x4A, 0xE0, 0x6D, 0xB2, 0xF8, 0xFC, 0x31, 0xB4, 0xF8, ++0x60, 0x10, 0xB4, 0xF8, 0x60, 0xC0, 0xC6, 0xF8, 0x72, 0x00, 0x01, 0x33, 0x9B, 0xB2, 0xE0, 0x6D, 0xA6, 0xF8, 0x76, 0x10, ++0x19, 0x01, 0xB0, 0x67, 0xA6, 0xF8, 0x7C, 0xC0, 0xA2, 0xF8, 0xFC, 0x31, 0xA6, 0xF8, 0x7E, 0x10, 0xC5, 0xE9, 0x15, 0x74, ++0x94, 0xF8, 0x63, 0x30, 0x2B, 0x77, 0xFF, 0x23, 0x6B, 0x77, 0x06, 0xF1, 0x80, 0x00, 0x07, 0x21, 0xF9, 0xF7, 0xCE, 0xFD, ++0xE9, 0x6C, 0x4B, 0x6A, 0x17, 0x33, 0x1A, 0x18, 0x00, 0xF1, 0x1C, 0x03, 0xC1, 0xE9, 0x0A, 0x23, 0x28, 0x46, 0x05, 0x21, ++0xBD, 0xE8, 0xF0, 0x41, 0xE4, 0xF7, 0x12, 0xB8, 0x02, 0x2B, 0xA9, 0xD1, 0x0D, 0x49, 0x0E, 0x48, 0x4F, 0xF4, 0x09, 0x72, ++0xF8, 0xF7, 0x0E, 0xFE, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE3, 0xF7, 0xF5, 0xFF, 0x05, 0x46, 0x00, 0x28, 0xA8, 0xD1, ++0xBD, 0xE8, 0xF0, 0x81, 0x03, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEF, 0xDA, 0xE8, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0xF8, 0xB5, 0x14, 0x4A, ++0x14, 0x4D, 0x41, 0xF2, 0x0A, 0x00, 0x41, 0xF2, 0x08, 0x07, 0x00, 0x26, 0x16, 0x52, 0x0C, 0x46, 0xD3, 0x53, 0x41, 0xF2, ++0x0C, 0x06, 0xD1, 0xF8, 0x64, 0x11, 0xD4, 0xF8, 0x60, 0x01, 0x90, 0x51, 0x0B, 0x2B, 0x14, 0x60, 0xA9, 0x80, 0x0D, 0xD0, ++0x19, 0x46, 0x04, 0x22, 0x02, 0x23, 0x41, 0xF2, 0x09, 0x00, 0xF6, 0xF7, 0xF5, 0xFC, 0x01, 0x22, 0x42, 0x70, 0x94, 0xF8, ++0x6E, 0x21, 0x02, 0x70, 0xF6, 0xF7, 0x1E, 0xFD, 0x04, 0x4B, 0xD3, 0xF8, 0xF4, 0x32, 0x98, 0x47, 0x01, 0x20, 0xF8, 0xBD, ++0xA8, 0xBA, 0x17, 0x00, 0xB4, 0xCA, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1A, 0x46, 0x70, 0xB5, 0x40, 0x23, 0x14, 0x4C, ++0x0D, 0x46, 0x41, 0xF2, 0x06, 0x00, 0x11, 0x46, 0x04, 0x22, 0xF6, 0xF7, 0xD7, 0xFC, 0xA3, 0x88, 0x06, 0x46, 0x13, 0xB1, ++0x2A, 0x78, 0x93, 0x42, 0x06, 0xD8, 0x00, 0x23, 0x30, 0x46, 0x33, 0x70, 0xF6, 0xF7, 0xFC, 0xFC, 0x00, 0x20, 0x70, 0xBD, ++0x04, 0xEB, 0x82, 0x14, 0x08, 0x34, 0x0F, 0xCC, 0x35, 0x46, 0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, ++0x94, 0xE8, 0x0F, 0x00, 0x85, 0xE8, 0x0F, 0x00, 0x30, 0x46, 0xF6, 0xF7, 0xE9, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, ++0xA8, 0xBA, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x22, 0x01, 0x23, 0x02, 0x21, 0x40, 0xF6, 0x03, 0x00, 0xF6, 0xF7, 0xAC, 0xFC, ++0xF6, 0xF7, 0xDA, 0xFC, 0x04, 0x20, 0xF6, 0xF7, 0x49, 0xFF, 0x03, 0x49, 0x02, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x5A, 0xFB, ++0x00, 0x20, 0x08, 0xBD, 0x6C, 0xBE, 0x15, 0x00, 0x08, 0xB5, 0x19, 0x46, 0x04, 0x22, 0x01, 0x23, 0x41, 0xF2, 0x0B, 0x00, ++0xF6, 0xF7, 0x96, 0xFC, 0xF6, 0xF7, 0xC4, 0xFC, 0x02, 0x49, 0x08, 0x20, 0xF8, 0xF7, 0x48, 0xFB, 0x00, 0x20, 0x08, 0xBD, ++0x80, 0xBE, 0x15, 0x00, 0x1A, 0x46, 0x38, 0xB5, 0x41, 0xF2, 0x08, 0x00, 0x0D, 0x46, 0x02, 0x23, 0x11, 0x46, 0x04, 0x22, ++0xF6, 0xF7, 0x82, 0xFC, 0x06, 0x49, 0x04, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x35, 0xFB, 0x01, 0x23, 0x23, 0x70, 0xAB, 0x78, ++0x63, 0x70, 0x20, 0x46, 0xF6, 0xF7, 0xA6, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0x98, 0xBE, 0x15, 0x00, 0x10, 0xB5, 0x41, 0xF2, ++0x08, 0x00, 0x04, 0x4C, 0x04, 0x49, 0x1A, 0x46, 0x23, 0x5A, 0x08, 0x20, 0xF8, 0xF7, 0x20, 0xFB, 0x02, 0x20, 0x10, 0xBD, ++0xA8, 0xBA, 0x17, 0x00, 0xB4, 0xBE, 0x15, 0x00, 0xF8, 0xB5, 0x36, 0x4C, 0x91, 0xF8, 0x6E, 0x21, 0x35, 0x4E, 0x21, 0x60, ++0x0D, 0x46, 0x41, 0xF2, 0x08, 0x00, 0x4F, 0xF4, 0xA4, 0x67, 0x41, 0xF2, 0x0A, 0x01, 0x07, 0xFB, 0x02, 0x62, 0x01, 0x26, ++0x23, 0x52, 0x66, 0x52, 0x00, 0x23, 0xC2, 0xF8, 0xCC, 0x31, 0x05, 0xF5, 0xB0, 0x77, 0x97, 0xE8, 0x03, 0x00, 0xDF, 0xF8, ++0xC4, 0xC0, 0x41, 0xF2, 0x0C, 0x02, 0xAC, 0xF8, 0x04, 0x10, 0x41, 0xF2, 0x3B, 0x01, 0xA0, 0x50, 0x63, 0x54, 0x38, 0x46, ++0x1A, 0x46, 0x19, 0x46, 0x00, 0xF0, 0x4A, 0xF9, 0x18, 0xB1, 0x90, 0xF8, 0x3D, 0x10, 0x03, 0x46, 0x91, 0xB9, 0x97, 0xE8, ++0x03, 0x00, 0x21, 0x4B, 0x41, 0xF2, 0x34, 0x02, 0x99, 0x80, 0x20, 0x4B, 0xA0, 0x50, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x28, 0xDB, 0x1D, 0x4B, 0xD3, 0xF8, 0xF4, 0x32, 0x98, 0x47, 0x01, 0x20, 0xF8, 0xBD, 0x02, 0x46, 0x41, 0xF2, ++0x34, 0x0C, 0x52, 0xF8, 0x02, 0x0F, 0x93, 0xF8, 0x3E, 0x70, 0x44, 0xF8, 0x0C, 0x00, 0x14, 0x48, 0x92, 0x88, 0x82, 0x80, ++0xBE, 0x40, 0x41, 0xF2, 0x38, 0x00, 0x01, 0x3E, 0x22, 0x5A, 0x36, 0x02, 0x36, 0xB2, 0x22, 0xEA, 0x06, 0x02, 0x12, 0xB2, ++0x22, 0x52, 0xDB, 0x88, 0xA3, 0xEB, 0x01, 0x21, 0x0E, 0x40, 0x0C, 0x4B, 0x16, 0x43, 0x26, 0x52, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xD6, 0xDA, 0x95, 0xF8, 0x60, 0x31, 0xDB, 0x07, 0xD2, 0xD5, 0x08, 0x49, 0x08, 0x48, 0xA1, 0x22, ++0xF8, 0xF7, 0xD8, 0xFC, 0xCC, 0xE7, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xDC, 0xCA, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD0, 0xBE, 0x15, 0x00, 0xB4, 0xCA, 0x17, 0x00, ++0x1A, 0x46, 0x38, 0xB5, 0x41, 0xF2, 0x08, 0x00, 0x0D, 0x46, 0x02, 0x23, 0x11, 0x46, 0x04, 0x22, 0xF6, 0xF7, 0xDA, 0xFB, ++0x0A, 0x49, 0x04, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x8D, 0xFA, 0x29, 0x46, 0x08, 0x48, 0x31, 0xF8, 0x03, 0x2B, 0x20, 0xF8, ++0x03, 0x2B, 0x0A, 0xF0, 0x55, 0xFF, 0x01, 0x23, 0x23, 0x70, 0xAB, 0x78, 0x63, 0x70, 0x20, 0x46, 0xF6, 0xF7, 0xF6, 0xFB, ++0x00, 0x20, 0x38, 0xBD, 0xF0, 0xBE, 0x15, 0x00, 0x68, 0xCB, 0x17, 0x00, 0x08, 0x78, 0x08, 0xB9, 0x00, 0x20, 0x70, 0x47, ++0x08, 0xB5, 0x00, 0xF0, 0x31, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x70, 0xB5, 0x0B, 0x4E, 0x41, 0xF2, 0x08, 0x05, ++0x01, 0x23, 0x0C, 0x46, 0x04, 0x22, 0x71, 0x5B, 0x41, 0xF2, 0x0B, 0x00, 0xF6, 0xF7, 0xAA, 0xFB, 0xF6, 0xF7, 0xD8, 0xFB, ++0x72, 0x5B, 0x05, 0x49, 0x08, 0x20, 0xF8, 0xF7, 0x5B, 0xFA, 0x20, 0x78, 0x00, 0xF0, 0x18, 0xF8, 0x00, 0x20, 0x70, 0xBD, ++0xA8, 0xBA, 0x17, 0x00, 0x00, 0xBF, 0x15, 0x00, 0x08, 0xB5, 0x05, 0x49, 0x41, 0xF2, 0x0B, 0x02, 0x8B, 0x5C, 0x01, 0x33, ++0x8B, 0x54, 0x00, 0xF0, 0x65, 0xFD, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x08, 0x46, 0x00, 0xF0, ++0x19, 0xB9, 0x00, 0xBF, 0xF0, 0xB5, 0x39, 0x4C, 0x41, 0xF2, 0x0A, 0x05, 0x83, 0xB0, 0x63, 0x5D, 0x06, 0x46, 0x00, 0x2B, ++0x43, 0xD0, 0x41, 0xF2, 0x08, 0x02, 0x03, 0x23, 0xA1, 0x5A, 0x41, 0xF2, 0x03, 0x00, 0x04, 0x22, 0xF6, 0xF7, 0x76, 0xFB, ++0x05, 0x46, 0x23, 0x68, 0x30, 0x49, 0x93, 0xF8, 0x6E, 0x21, 0x00, 0x96, 0x41, 0xF2, 0x0A, 0x07, 0x08, 0x20, 0xE3, 0x5D, ++0xF8, 0xF7, 0x22, 0xFA, 0xE3, 0x5D, 0x63, 0xB9, 0x2B, 0x49, 0x2C, 0x4A, 0x0B, 0x68, 0x2C, 0x48, 0x23, 0xF0, 0x04, 0x03, ++0x0B, 0x60, 0x13, 0x68, 0x01, 0x88, 0x1B, 0x0C, 0x1B, 0x04, 0x0B, 0x43, 0x13, 0x60, 0x20, 0x68, 0x27, 0x4B, 0x90, 0xF8, ++0x6E, 0x21, 0x2A, 0x70, 0x6E, 0x70, 0xA2, 0x88, 0xAA, 0x70, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x20, 0xD0, 0x0C, 0x38, ++0xF6, 0xF7, 0xC8, 0xFB, 0x00, 0x26, 0x28, 0x46, 0x26, 0x60, 0xF6, 0xF7, 0x77, 0xFB, 0x1F, 0x4A, 0x53, 0x68, 0x31, 0x46, ++0x23, 0xF0, 0x20, 0x03, 0x04, 0x20, 0x53, 0x60, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xF6, 0xF7, 0x35, 0xBD, 0xA3, 0x88, ++0xF3, 0xB1, 0x41, 0xF2, 0x08, 0x02, 0x03, 0x23, 0xA1, 0x5A, 0x41, 0xF2, 0x01, 0x00, 0x04, 0x22, 0xF6, 0xF7, 0x30, 0xFB, ++0x05, 0x46, 0xB8, 0xE7, 0x13, 0x4B, 0x93, 0xF8, 0xB5, 0x30, 0x00, 0x2B, 0xD9, 0xD0, 0x12, 0x49, 0x12, 0x4B, 0x0A, 0x68, ++0x22, 0xF0, 0x7C, 0x72, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x12, ++0x1A, 0x60, 0xCA, 0xE7, 0xD6, 0xF7, 0xCC, 0xFB, 0x63, 0x5D, 0x00, 0x2B, 0xDB, 0xD0, 0x94, 0xE7, 0xA8, 0xBA, 0x17, 0x00, ++0x30, 0xBF, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x20, 0x04, 0x32, 0x40, 0x28, 0x25, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x00, 0x32, 0x40, 0x6C, 0x00, 0x32, 0x40, 0x08, 0xB5, 0x00, 0x21, ++0x04, 0x20, 0xF6, 0xF7, 0xF5, 0xFC, 0xBD, 0xE8, 0x08, 0x40, 0x03, 0x48, 0x4F, 0xF4, 0x86, 0x52, 0x00, 0x21, 0xD3, 0xF7, ++0xED, 0xBE, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x3C, 0x4D, 0x83, 0xB0, 0xA8, 0x46, 0x2B, 0x46, ++0x00, 0x22, 0x08, 0xE0, 0x5F, 0x89, 0x04, 0x88, 0xA7, 0x42, 0x14, 0xD0, 0x01, 0x32, 0x40, 0x2A, 0x03, 0xF1, 0x40, 0x03, ++0x1C, 0xD0, 0x1C, 0x7A, 0x03, 0xF1, 0x08, 0x06, 0x00, 0x2C, 0xF1, 0xD1, 0x00, 0x29, 0xF3, 0xD0, 0x08, 0xEB, 0x82, 0x12, ++0x80, 0x23, 0x82, 0xF8, 0x44, 0x30, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x9F, 0x89, 0x44, 0x88, 0xA7, 0x42, ++0xE6, 0xD1, 0xDF, 0x89, 0x84, 0x88, 0xA7, 0x42, 0xF3, 0xD0, 0x01, 0x32, 0x40, 0x2A, 0x03, 0xF1, 0x40, 0x03, 0xE2, 0xD1, ++0x00, 0x29, 0x46, 0xD0, 0x26, 0x4F, 0x4F, 0xF0, 0x00, 0x0B, 0x4F, 0xF0, 0x21, 0x0A, 0x06, 0xE0, 0x0B, 0xF1, 0x01, 0x0B, ++0xBB, 0xF1, 0x40, 0x0F, 0x05, 0xF1, 0x40, 0x05, 0x39, 0xD0, 0x2B, 0x7A, 0x05, 0xF1, 0x08, 0x06, 0x00, 0x2B, 0xF3, 0xD0, ++0x95, 0xF8, 0x45, 0x40, 0x00, 0x2C, 0xEF, 0xD1, 0x38, 0x68, 0x30, 0xB3, 0x90, 0xF8, 0x70, 0x31, 0x1B, 0xB3, 0x05, 0xF1, ++0x11, 0x01, 0x4F, 0xF0, 0xFD, 0x09, 0x06, 0xE0, 0x38, 0x68, 0x01, 0x34, 0x90, 0xF8, 0x70, 0x31, 0xE4, 0xB2, 0xA3, 0x42, ++0x15, 0xD9, 0x04, 0xEB, 0x44, 0x13, 0x03, 0x44, 0x93, 0xF8, 0xFC, 0x30, 0x00, 0x2B, 0xF1, 0xD0, 0x2A, 0x7C, 0x9A, 0x42, ++0xEE, 0xD1, 0x1A, 0xFB, 0x04, 0x93, 0x18, 0x44, 0x01, 0x91, 0x0A, 0xF0, 0xE1, 0xFD, 0x01, 0x99, 0x00, 0x28, 0xE5, 0xD1, ++0x3B, 0x68, 0x93, 0xF8, 0x70, 0x31, 0x9C, 0x42, 0xC6, 0xD1, 0x08, 0xEB, 0x8B, 0x11, 0x80, 0x20, 0x00, 0x23, 0x81, 0xF8, ++0x44, 0x00, 0x0B, 0x72, 0xA5, 0xE7, 0x00, 0x26, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA8, 0xBA, 0x17, 0x00, ++0xF4, 0x9F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, 0x61, 0x4B, 0x99, 0xB0, 0x1C, 0x68, 0x03, 0x46, ++0x04, 0x93, 0x04, 0x20, 0x94, 0xF8, 0x6E, 0x31, 0x07, 0x93, 0xF6, 0xF7, 0x03, 0xFD, 0x01, 0x28, 0x05, 0xD0, 0x00, 0x20, ++0x19, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x58, 0x49, 0x41, 0xF2, 0x0C, 0x03, 0xCA, 0x5C, 0xD2, 0x07, ++0x19, 0xD4, 0xCA, 0x5A, 0x04, 0x9B, 0x9B, 0x8B, 0x9A, 0x42, 0x00, 0xF0, 0x85, 0x80, 0x52, 0x49, 0x41, 0xF2, 0x34, 0x02, ++0x8A, 0x5A, 0x9A, 0x42, 0xE7, 0xD1, 0x04, 0x9A, 0x41, 0xF2, 0x36, 0x03, 0xD2, 0x8B, 0xCB, 0x5A, 0x9A, 0x42, 0xE0, 0xD1, ++0x04, 0x9A, 0x41, 0xF2, 0x38, 0x03, 0x12, 0x8C, 0xCB, 0x5A, 0x9A, 0x42, 0xD9, 0xD1, 0x04, 0x98, 0x30, 0xF8, 0x30, 0x3B, ++0x0B, 0x90, 0x24, 0x3B, 0x9B, 0xB2, 0x0D, 0xF1, 0x37, 0x02, 0x19, 0x46, 0x08, 0xEE, 0x10, 0x3A, 0xF7, 0xF7, 0xE4, 0xF8, ++0x00, 0x28, 0x73, 0xD0, 0x9D, 0xF8, 0x37, 0x60, 0x10, 0xAD, 0x4E, 0xB1, 0xAF, 0x19, 0x2B, 0x46, 0xC5, 0xF1, 0x02, 0x01, ++0xC2, 0x18, 0x52, 0x5C, 0x03, 0xF8, 0x01, 0x2B, 0xBB, 0x42, 0xF9, 0xD1, 0x04, 0x9F, 0x38, 0x46, 0x01, 0x21, 0x2B, 0x46, ++0x32, 0x46, 0x1C, 0x30, 0xFF, 0xF7, 0x24, 0xFF, 0x01, 0x46, 0x0A, 0x90, 0x00, 0x28, 0xB0, 0xD0, 0xBB, 0x8B, 0x43, 0x80, ++0xFB, 0x8B, 0x83, 0x80, 0x3B, 0x8C, 0xC3, 0x80, 0x97, 0xF8, 0x2C, 0x30, 0x97, 0xF8, 0x2D, 0x20, 0x43, 0xEA, 0x02, 0x23, ++0x03, 0x86, 0xFB, 0x8D, 0x43, 0x86, 0x03, 0xF0, 0x01, 0x03, 0xC3, 0xF1, 0x02, 0x03, 0x43, 0x85, 0x00, 0x2E, 0x46, 0xD1, ++0x0A, 0x9B, 0x1E, 0x72, 0x27, 0x4A, 0x41, 0xF2, 0x3A, 0x03, 0xD3, 0x5C, 0x00, 0x2B, 0x40, 0xF0, 0xA5, 0x82, 0x24, 0x4A, ++0x41, 0xF2, 0x0A, 0x03, 0xD5, 0x5C, 0x00, 0x2D, 0x48, 0xD1, 0x94, 0xF8, 0x70, 0x11, 0x00, 0x29, 0x44, 0xD0, 0x0A, 0x9B, ++0x26, 0x46, 0x03, 0xF1, 0x09, 0x07, 0x98, 0x46, 0x08, 0x46, 0x05, 0xE0, 0x01, 0x35, 0xA8, 0x42, 0x06, 0xF1, 0x21, 0x06, ++0x03, 0x46, 0x34, 0xDD, 0x96, 0xF8, 0xFC, 0x30, 0x83, 0xB3, 0x98, 0xF8, 0x08, 0x20, 0x9A, 0x42, 0xF2, 0xD1, 0x39, 0x46, ++0x06, 0xF1, 0xFD, 0x00, 0x0A, 0xF0, 0x26, 0xFD, 0x00, 0x28, 0x00, 0xF0, 0x2C, 0x83, 0x94, 0xF8, 0x70, 0x01, 0xE7, 0xE7, ++0x04, 0x99, 0x0F, 0x48, 0xC9, 0x8B, 0x41, 0xF2, 0x0E, 0x02, 0x82, 0x5A, 0x91, 0x42, 0x7F, 0xF4, 0x72, 0xAF, 0x04, 0x99, ++0x41, 0xF2, 0x10, 0x02, 0x09, 0x8C, 0x82, 0x5A, 0x91, 0x42, 0x7F, 0xF4, 0x6A, 0xAF, 0x7C, 0xE7, 0x06, 0x46, 0x10, 0xAD, ++0x96, 0xE7, 0x0B, 0x46, 0x03, 0xF8, 0x08, 0x6F, 0x2E, 0x44, 0x15, 0xF8, 0x01, 0x2B, 0x03, 0xF8, 0x01, 0x2F, 0xAE, 0x42, ++0xF9, 0xD1, 0xAF, 0xE7, 0xA8, 0xBA, 0x17, 0x00, 0x03, 0x46, 0x9D, 0x42, 0x3F, 0xF4, 0x43, 0xAF, 0x18, 0xEE, 0x10, 0x1A, ++0x0B, 0x98, 0xF7, 0xF7, 0x45, 0xF9, 0x00, 0x28, 0x00, 0xF0, 0x3A, 0x82, 0x04, 0x9B, 0x9A, 0x79, 0x83, 0x78, 0x00, 0x2A, ++0x40, 0xF0, 0x56, 0x82, 0x59, 0x1E, 0x0D, 0x29, 0x00, 0xF2, 0x4F, 0x82, 0x0E, 0x2B, 0x00, 0xF0, 0xEB, 0x82, 0x03, 0xEB, ++0x83, 0x03, 0x03, 0xF6, 0x67, 0x11, 0x10, 0x46, 0xFA, 0xF7, 0x98, 0xFE, 0x0A, 0x99, 0x04, 0x9B, 0xC8, 0x62, 0x91, 0xF9, ++0x3C, 0x20, 0x93, 0xF9, 0x09, 0x30, 0x9A, 0x42, 0xB8, 0xBF, 0x81, 0xF8, 0x3C, 0x30, 0x04, 0x99, 0x03, 0x88, 0x8A, 0x88, ++0x9A, 0x42, 0x00, 0xD0, 0x8B, 0x80, 0x41, 0xF2, 0xBD, 0x03, 0xB4, 0x4A, 0x00, 0x25, 0xD5, 0x54, 0x18, 0xEE, 0x10, 0x3A, ++0x00, 0x2B, 0x6C, 0xD0, 0x0B, 0x9B, 0x8D, 0xED, 0x05, 0x8A, 0x2C, 0x46, 0xA8, 0x46, 0x06, 0x93, 0xDD, 0xE9, 0x05, 0x10, ++0xF7, 0xF7, 0xFC, 0xF9, 0x08, 0x90, 0x00, 0x28, 0x5F, 0xD0, 0x43, 0x78, 0xAA, 0x4A, 0x81, 0x78, 0x11, 0x70, 0x5E, 0x1E, ++0x02, 0x33, 0xB6, 0xB2, 0x09, 0x93, 0x00, 0xF1, 0x03, 0x0A, 0x00, 0x2E, 0x44, 0xD0, 0x31, 0x46, 0x50, 0x46, 0xF7, 0xF7, ++0x09, 0xFA, 0x07, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0x90, 0xF8, 0x01, 0x90, 0x00, 0xF1, 0x02, 0x0B, 0x09, 0xF1, 0x02, 0x03, ++0xF6, 0x1A, 0x58, 0x46, 0x04, 0x21, 0xB6, 0xB2, 0x9A, 0x44, 0xF7, 0xF7, 0x1D, 0xFA, 0x00, 0x28, 0x00, 0xF0, 0x81, 0x81, ++0x49, 0x46, 0x58, 0x46, 0xF7, 0xF7, 0x36, 0xFA, 0x07, 0xF1, 0x04, 0x08, 0x04, 0x46, 0x49, 0x46, 0x58, 0x46, 0x0E, 0xAA, ++0xF6, 0xF7, 0xE8, 0xFF, 0x05, 0x46, 0x00, 0x2C, 0xD7, 0xD0, 0x00, 0x2D, 0xD5, 0xD0, 0x92, 0x4B, 0x98, 0xF8, 0x00, 0xC0, ++0x1A, 0x78, 0xA7, 0x78, 0xA3, 0xF1, 0x81, 0x00, 0x81, 0x1D, 0x98, 0xF8, 0x01, 0x30, 0x01, 0xF8, 0x32, 0x70, 0x4C, 0xEA, ++0x03, 0x21, 0x53, 0x1C, 0xDB, 0xB2, 0x07, 0x1D, 0x10, 0x2B, 0x40, 0xF8, 0x32, 0x50, 0x80, 0xF8, 0x81, 0x30, 0x27, 0xF8, ++0x32, 0x10, 0x12, 0xD0, 0x4F, 0xF0, 0x00, 0x08, 0x00, 0x2E, 0xBA, 0xD1, 0x06, 0x9B, 0x08, 0x9A, 0x05, 0x99, 0x9B, 0x1A, ++0x19, 0x44, 0x09, 0x9B, 0xA1, 0xEB, 0x03, 0x0B, 0x1F, 0xFA, 0x8B, 0xF1, 0xD3, 0x18, 0x05, 0x91, 0x06, 0x93, 0x00, 0x29, ++0x98, 0xD1, 0x0A, 0x99, 0x00, 0x23, 0x4B, 0x63, 0x8B, 0x63, 0x41, 0xF2, 0x0A, 0x02, 0x77, 0x4B, 0x9B, 0x5C, 0x00, 0x2B, ++0x00, 0xF0, 0xB4, 0x80, 0x0A, 0x9A, 0x07, 0x9F, 0x76, 0x4C, 0x56, 0x8D, 0x51, 0x8E, 0x13, 0x46, 0x4F, 0xF4, 0xA4, 0x65, ++0x53, 0xF8, 0x02, 0x0F, 0x12, 0x8E, 0x9B, 0x88, 0x05, 0xFB, 0x07, 0xF5, 0x67, 0x19, 0xA7, 0xF8, 0x68, 0x31, 0xA7, 0xF8, ++0x98, 0x21, 0xFF, 0x23, 0x0A, 0x9A, 0xA7, 0xF8, 0x8E, 0x61, 0xC7, 0xF8, 0x64, 0x01, 0xA7, 0xF8, 0x9A, 0x11, 0x87, 0xF8, ++0x61, 0x31, 0x87, 0xF8, 0xBE, 0x31, 0x13, 0x7A, 0x05, 0xF1, 0xEC, 0x06, 0x26, 0x44, 0x00, 0x2B, 0x40, 0xF0, 0xA2, 0x81, ++0x0A, 0x9A, 0xD2, 0x6A, 0xC7, 0xF8, 0x90, 0x21, 0xA7, 0xF8, 0xC2, 0x31, 0x07, 0x9B, 0x0A, 0x9A, 0x0B, 0x98, 0x4F, 0xF4, ++0xA4, 0x67, 0x07, 0xFB, 0x03, 0x47, 0x92, 0xF8, 0x3D, 0x30, 0x87, 0xF8, 0x8B, 0x31, 0x92, 0xF8, 0x3E, 0x30, 0x87, 0xF8, ++0x8C, 0x31, 0x05, 0xF5, 0xCE, 0x78, 0x00, 0x23, 0xA0, 0x44, 0xC7, 0xF8, 0xCC, 0x31, 0x18, 0xEE, 0x10, 0x1A, 0x42, 0x46, ++0xF9, 0xF7, 0xA4, 0xFB, 0x0A, 0x9B, 0xDB, 0x6A, 0x9B, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0xB3, 0x81, 0x05, 0xF5, 0xD6, 0x72, ++0x18, 0xEE, 0x10, 0x1A, 0x0B, 0x98, 0x22, 0x44, 0x0E, 0xAB, 0xF9, 0xF7, 0x6D, 0xFD, 0x80, 0xB1, 0x07, 0x9A, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, 0xB3, 0xF8, 0x9A, 0x11, 0xD3, 0xF8, 0xCC, 0x21, 0x41, 0xF4, 0x00, 0x71, 0x42, 0xF0, ++0x01, 0x02, 0xA3, 0xF8, 0x9A, 0x11, 0xC3, 0xF8, 0xCC, 0x21, 0x45, 0x4F, 0x97, 0xF8, 0x76, 0x31, 0xDB, 0x07, 0x09, 0xD5, ++0x07, 0x9B, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x03, 0x49, 0xD9, 0xF8, 0xCC, 0x31, 0xD8, 0x07, 0x00, 0xF1, 0x98, 0x81, ++0x00, 0x21, 0x88, 0x46, 0x40, 0x46, 0x32, 0x46, 0xFB, 0xF7, 0x52, 0xFA, 0x0B, 0x9D, 0x18, 0xEE, 0x10, 0x1A, 0x28, 0x46, ++0x32, 0x46, 0xF9, 0xF7, 0xAD, 0xFB, 0x28, 0x46, 0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, 0xF9, 0xF7, 0xB1, 0xFB, 0x28, 0x46, ++0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, 0xF9, 0xF7, 0x13, 0xFC, 0x07, 0x9A, 0x31, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x02, 0x44, 0x29, 0x6D, 0xD4, 0xF8, 0xCC, 0x31, 0x43, 0xF0, 0x00, 0x43, 0x41, 0xF2, 0x3B, 0x02, 0xC4, 0xF8, 0xCC, 0x31, ++0x25, 0x4B, 0x01, 0x20, 0x98, 0x54, 0x2A, 0x6A, 0x00, 0x29, 0x00, 0xF0, 0x1C, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x19, 0x81, ++0x0B, 0x7E, 0x03, 0x2B, 0x08, 0xD1, 0x25, 0x4B, 0x05, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xD5, 0xE9, ++0x11, 0x30, 0x98, 0x47, 0x0A, 0x9A, 0x14, 0x78, 0xDC, 0xB9, 0x19, 0x48, 0x1F, 0x4B, 0x81, 0x88, 0x1B, 0x68, 0x01, 0x31, ++0x89, 0xB2, 0x81, 0x80, 0x1B, 0x88, 0x5B, 0x07, 0x11, 0xD5, 0x13, 0x7A, 0x00, 0x2B, 0x40, 0xF0, 0x7A, 0x81, 0x1A, 0x4D, ++0x0A, 0x9A, 0x04, 0x9C, 0xD2, 0x6A, 0x94, 0xF9, 0x09, 0x00, 0x12, 0x88, 0x00, 0x90, 0xCD, 0xE9, 0x01, 0x35, 0x16, 0x48, ++0x23, 0x7B, 0xF7, 0xF7, 0x89, 0xFE, 0x0A, 0x99, 0x00, 0x25, 0x01, 0x22, 0x0A, 0x70, 0x81, 0xF8, 0x3D, 0x50, 0x81, 0xF8, ++0x3E, 0x50, 0x41, 0xF2, 0xBD, 0x03, 0x08, 0x46, 0x05, 0x49, 0xCB, 0x5C, 0x00, 0x2B, 0x4D, 0xD0, 0x0D, 0x4C, 0x83, 0x46, ++0x04, 0xF1, 0x80, 0x0A, 0x04, 0xF1, 0x81, 0x09, 0x43, 0xE0, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x64, 0xCB, 0x17, 0x00, ++0x65, 0xCB, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x48, 0xBF, 0x15, 0x00, 0x84, 0xBF, 0x15, 0x00, 0xE4, 0xCA, 0x17, 0x00, 0x9A, 0xF8, 0x00, 0x70, ++0x08, 0x2F, 0x2B, 0xD8, 0x5A, 0x46, 0x21, 0x68, 0x52, 0xF8, 0x02, 0x0F, 0x4E, 0x78, 0x0E, 0x90, 0x92, 0x88, 0xAD, 0xF8, ++0x3C, 0x20, 0xBB, 0xF8, 0x06, 0x20, 0xBD, 0xF9, 0x3C, 0x10, 0x4F, 0xF0, 0x01, 0x08, 0x02, 0xEB, 0x03, 0x22, 0x08, 0xFA, ++0x07, 0xF3, 0x4A, 0x40, 0x01, 0x3B, 0x02, 0xEA, 0x03, 0x22, 0x00, 0x23, 0x81, 0xEA, 0x02, 0x0C, 0x0E, 0xA8, 0x1A, 0x46, ++0x19, 0x46, 0xAD, 0xF8, 0x3C, 0xC0, 0xFF, 0xF7, 0xDF, 0xFC, 0x68, 0xB3, 0x99, 0xF8, 0x00, 0x30, 0x01, 0x35, 0x9D, 0x42, ++0x04, 0xF1, 0x08, 0x04, 0x02, 0xDA, 0xA3, 0x79, 0x00, 0x2B, 0xCF, 0xD1, 0x04, 0x98, 0x04, 0x23, 0x0C, 0x22, 0x41, 0xF2, ++0x04, 0x01, 0xF6, 0xF7, 0x2D, 0xF8, 0x01, 0x20, 0x5C, 0xE5, 0xB8, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x62, 0xAE, 0x4C, 0xB1, ++0x00, 0x2D, 0x7F, 0xF4, 0x88, 0xAE, 0x49, 0x46, 0x58, 0x46, 0x0E, 0xAA, 0xF6, 0xF7, 0x66, 0xFE, 0x05, 0x46, 0x7E, 0xE6, ++0x49, 0x46, 0x58, 0x46, 0xF7, 0xF7, 0xA6, 0xF8, 0x04, 0x46, 0x00, 0x2D, 0x3F, 0xF4, 0x6F, 0xAE, 0x00, 0x28, 0x3F, 0xF4, ++0x4C, 0xAE, 0x74, 0xE6, 0x23, 0x68, 0x41, 0x46, 0x02, 0x33, 0x32, 0x46, 0x0E, 0xA8, 0xFF, 0xF7, 0xA9, 0xFC, 0x86, 0x46, ++0x00, 0x28, 0xD1, 0xD0, 0xD8, 0x46, 0xB8, 0xE8, 0x0F, 0x00, 0xF4, 0x46, 0xAC, 0xE8, 0x0F, 0x00, 0xB8, 0xE8, 0x0F, 0x00, ++0xAC, 0xE8, 0x0F, 0x00, 0xB8, 0xE8, 0x0F, 0x00, 0xAC, 0xE8, 0x0F, 0x00, 0x98, 0xE8, 0x0F, 0x00, 0x8C, 0xE8, 0x0F, 0x00, ++0x0E, 0x98, 0xCE, 0xF8, 0x02, 0x00, 0xBD, 0xF8, 0x3C, 0x30, 0x8E, 0xF8, 0x08, 0x60, 0x21, 0x68, 0xAE, 0xF8, 0x06, 0x30, ++0x5E, 0xB1, 0x08, 0x36, 0x06, 0x39, 0x76, 0x44, 0xA1, 0xEB, 0x0E, 0x01, 0x0E, 0xF1, 0x08, 0x03, 0xCA, 0x5C, 0x03, 0xF8, ++0x01, 0x2F, 0x9E, 0x42, 0xFA, 0xD1, 0x7E, 0x49, 0x8E, 0xF8, 0x3E, 0x70, 0x8B, 0x88, 0xA2, 0x79, 0x8E, 0xF8, 0x3D, 0x20, ++0x01, 0x33, 0x01, 0x22, 0x8B, 0x80, 0x8E, 0xF8, 0x00, 0x20, 0x91, 0xE7, 0x04, 0x9B, 0x93, 0xF9, 0x09, 0x20, 0x0A, 0x9B, ++0x93, 0xF9, 0x3C, 0x30, 0x9A, 0x42, 0x7F, 0xF7, 0xE2, 0xAD, 0x04, 0x9C, 0xA1, 0x88, 0xA0, 0x79, 0xFA, 0xF7, 0x64, 0xFC, ++0x0A, 0x9A, 0xD0, 0x62, 0x63, 0x7A, 0x82, 0xF8, 0x3C, 0x30, 0xD6, 0xE5, 0x0A, 0x9B, 0x6E, 0x49, 0x07, 0x22, 0x03, 0xF1, ++0x09, 0x00, 0x0A, 0xF0, 0x9D, 0xFA, 0x00, 0x28, 0x7F, 0xF4, 0xE3, 0xAC, 0x9E, 0xE5, 0x4F, 0xF6, 0xFF, 0x71, 0xB4, 0xE5, ++0x01, 0x2A, 0xFA, 0xD1, 0x59, 0x1E, 0xA4, 0x29, 0xF7, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x51, 0x08, 0x31, ++0xA9, 0xE5, 0xB2, 0xFA, 0x82, 0xF2, 0x62, 0x48, 0x52, 0x09, 0xF7, 0xF7, 0x95, 0xFD, 0xEB, 0xE6, 0x02, 0xF1, 0x09, 0x00, ++0x0A, 0xF0, 0xAC, 0xFC, 0xA8, 0xB1, 0x0A, 0x9B, 0x07, 0xF5, 0xB5, 0x77, 0x03, 0xF1, 0x08, 0x08, 0x03, 0xF1, 0x28, 0x0E, ++0xC4, 0x46, 0xBC, 0xE8, 0x0F, 0x00, 0xF4, 0x45, 0x38, 0x60, 0x79, 0x60, 0xBA, 0x60, 0xFB, 0x60, 0xE0, 0x46, 0x07, 0xF1, ++0x10, 0x07, 0xF3, 0xD1, 0x9C, 0xF8, 0x00, 0x30, 0x3B, 0x70, 0x0A, 0x9B, 0x07, 0x98, 0x19, 0x7A, 0x0A, 0x9B, 0xDA, 0x6A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x43, 0x00, 0x27, 0xC3, 0xF8, 0x90, 0x21, 0xA3, 0xF8, 0xC2, 0x71, 0x00, 0x29, ++0x3F, 0xF4, 0x38, 0xAE, 0x0B, 0x44, 0x05, 0xF2, 0x6B, 0x11, 0x12, 0x88, 0x48, 0x48, 0x83, 0xF8, 0x6B, 0x71, 0x21, 0x44, ++0xF7, 0xF7, 0x5E, 0xFD, 0x2C, 0xE6, 0x40, 0x46, 0x01, 0x21, 0xFA, 0xF7, 0xED, 0xFD, 0x10, 0xF0, 0x0F, 0x00, 0x1A, 0xBF, ++0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x1F, 0x03, 0x01, 0x23, 0x87, 0xF8, 0xC1, 0x31, 0x3D, 0xE6, 0x18, 0xEE, 0x10, 0x1A, ++0x0B, 0x98, 0x32, 0x46, 0xF9, 0xF7, 0x0C, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x5F, 0xAE, 0xD9, 0xF8, 0xCC, 0x31, 0x0B, 0x98, ++0x43, 0xF0, 0x02, 0x03, 0x18, 0xEE, 0x10, 0x1A, 0xC9, 0xF8, 0xCC, 0x31, 0xF7, 0xF7, 0x24, 0xF8, 0x97, 0xF8, 0x76, 0x31, ++0x59, 0x07, 0x80, 0x46, 0x30, 0xD4, 0x9A, 0x07, 0x0A, 0xD4, 0x07, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, ++0xD3, 0xF8, 0xCC, 0x11, 0x11, 0xF0, 0x08, 0x01, 0x3F, 0xF4, 0x44, 0xAE, 0x05, 0xF5, 0x86, 0x72, 0x18, 0xEE, 0x10, 0x1A, ++0x0B, 0x98, 0x22, 0x44, 0xF9, 0xF7, 0x08, 0xFC, 0x30, 0xBB, 0x01, 0x46, 0x38, 0xE6, 0x02, 0xF1, 0x09, 0x05, 0x28, 0x46, ++0x16, 0x46, 0x0A, 0xF0, 0x33, 0xFC, 0x20, 0xB9, 0x1E, 0x4B, 0x22, 0x4D, 0x99, 0x88, 0x33, 0x7A, 0x7A, 0xE6, 0x0A, 0x9A, ++0x1B, 0x49, 0x13, 0x7A, 0x89, 0x88, 0x1A, 0x44, 0x54, 0x72, 0x73, 0xE6, 0x40, 0xF6, 0xB4, 0x11, 0x15, 0xE5, 0x94, 0xF8, ++0x70, 0x31, 0xF6, 0xE4, 0x05, 0xF5, 0x8C, 0x72, 0x18, 0xEE, 0x10, 0x1A, 0x0B, 0x98, 0x22, 0x44, 0xF9, 0xF7, 0x02, 0xFC, ++0xA0, 0xB9, 0x97, 0xF8, 0x76, 0x31, 0xC2, 0xE7, 0x07, 0x9A, 0x0B, 0x98, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, ++0x18, 0xEE, 0x10, 0x1A, 0xD3, 0xF8, 0xCC, 0x21, 0x42, 0xF0, 0x04, 0x02, 0xC3, 0xF8, 0xCC, 0x21, 0xF6, 0xF7, 0xF2, 0xFF, ++0x01, 0x46, 0x01, 0xE6, 0xD9, 0xF8, 0xCC, 0x31, 0x0B, 0x98, 0x43, 0xF0, 0x08, 0x03, 0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, ++0xC9, 0xF8, 0xCC, 0x31, 0xF9, 0xF7, 0x36, 0xFC, 0xDD, 0xE7, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x54, 0xBF, 0x15, 0x00, ++0x68, 0xBF, 0x15, 0x00, 0x5C, 0xBF, 0x15, 0x00, 0x48, 0xBF, 0x15, 0x00, 0x00, 0x23, 0x1A, 0x46, 0x19, 0x46, 0xFF, 0xF7, ++0x71, 0xBB, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0x03, 0x78, 0x43, 0xB3, 0x16, 0x4C, 0x07, 0x46, 0x4F, 0xF0, 0x00, 0x08, ++0x04, 0xF5, 0x80, 0x56, 0x6F, 0xF0, 0x7F, 0x05, 0x00, 0xF1, 0x01, 0x09, 0x02, 0xE0, 0x40, 0x34, 0xB4, 0x42, 0x17, 0xD0, ++0x23, 0x7A, 0xAB, 0xB1, 0x94, 0xF9, 0x44, 0x30, 0xAB, 0x42, 0xF6, 0xDD, 0x23, 0x7C, 0x3A, 0x78, 0x9A, 0x42, 0xF2, 0xD1, ++0x49, 0x46, 0x04, 0xF1, 0x11, 0x00, 0x0A, 0xF0, 0x97, 0xF9, 0x00, 0x28, 0xEB, 0xD1, 0x94, 0xF9, 0x44, 0x50, 0x04, 0xF1, ++0x08, 0x08, 0x40, 0x34, 0xB4, 0x42, 0xE7, 0xD1, 0x40, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x98, 0x46, 0x40, 0x46, 0xBD, 0xE8, ++0xF8, 0x83, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x41, 0xF2, 0x0B, 0x03, 0xC2, 0x4D, 0xE9, 0x5C, ++0x2E, 0x68, 0x01, 0x29, 0x82, 0xB0, 0x00, 0xF2, 0xB8, 0x81, 0x96, 0xF8, 0x6F, 0x01, 0x00, 0x27, 0x00, 0x28, 0x00, 0xF0, ++0x57, 0x81, 0x33, 0x46, 0x00, 0x24, 0x03, 0xE0, 0x01, 0x34, 0x84, 0x42, 0x00, 0xF0, 0x50, 0x81, 0x9A, 0x78, 0x8A, 0x42, ++0x03, 0xF1, 0x06, 0x03, 0xF6, 0xD1, 0x17, 0xB1, 0x41, 0xF2, 0x0B, 0x03, 0xE9, 0x54, 0x4F, 0xF4, 0xBA, 0x73, 0x02, 0x21, ++0x04, 0x22, 0x4F, 0xF4, 0x00, 0x60, 0xF5, 0xF7, 0x03, 0xFE, 0x96, 0xF8, 0x6E, 0x31, 0x80, 0xF8, 0x6E, 0x31, 0x07, 0x46, ++0xD6, 0xE9, 0x58, 0x01, 0xC7, 0xF8, 0x60, 0x01, 0xA7, 0xF8, 0x64, 0x11, 0x96, 0xF8, 0x70, 0x01, 0x87, 0xF8, 0x70, 0x01, ++0x96, 0xF8, 0x71, 0x31, 0x87, 0xF8, 0x71, 0x31, 0x96, 0xF8, 0x6F, 0x31, 0x9C, 0x42, 0x80, 0xF2, 0x79, 0x81, 0x41, 0xF2, ++0x0B, 0x02, 0x04, 0xEB, 0x44, 0x04, 0x06, 0x21, 0x15, 0xF8, 0x02, 0x80, 0x06, 0xEB, 0x44, 0x04, 0x11, 0xFB, 0x03, 0x61, ++0xA3, 0x78, 0x43, 0x45, 0x10, 0xD1, 0x97, 0xF8, 0x6F, 0x31, 0xD4, 0xF8, 0x00, 0xC0, 0x03, 0xEB, 0x43, 0x02, 0x01, 0x33, ++0x47, 0xF8, 0x12, 0xC0, 0x07, 0xEB, 0x42, 0x02, 0xB4, 0xF8, 0x04, 0xC0, 0xA2, 0xF8, 0x04, 0xC0, 0x87, 0xF8, 0x6F, 0x31, ++0x06, 0x34, 0xA1, 0x42, 0xE8, 0xD1, 0xF0, 0xB1, 0x4F, 0xF0, 0x21, 0x0A, 0xFC, 0x21, 0x1A, 0xFB, 0x00, 0x1A, 0x73, 0x18, ++0x03, 0xF1, 0x20, 0x09, 0x7A, 0x18, 0xD3, 0xF8, 0x00, 0xC0, 0x5C, 0x68, 0x98, 0x68, 0xD3, 0xF8, 0x0C, 0xE0, 0xC2, 0xF8, ++0x0C, 0xE0, 0x10, 0x33, 0x4B, 0x45, 0xC2, 0xF8, 0x00, 0xC0, 0x54, 0x60, 0x90, 0x60, 0x02, 0xF1, 0x10, 0x02, 0xEE, 0xD1, ++0x21, 0x31, 0x1B, 0x78, 0x13, 0x70, 0x51, 0x45, 0xE5, 0xD1, 0x2B, 0x68, 0xDF, 0xF8, 0x2C, 0xC2, 0xB3, 0xF8, 0x6C, 0x91, ++0x81, 0x4C, 0xB9, 0xF1, 0xC9, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, 0x00, 0x09, 0xB8, 0xF1, 0x01, 0x0F, 0x66, 0x46, 0x00, 0xF0, ++0xE5, 0x80, 0x93, 0xF8, 0x71, 0x21, 0x7C, 0x4B, 0x00, 0x2A, 0xA3, 0xF1, 0x04, 0x02, 0x0A, 0xBF, 0x13, 0x46, 0x4F, 0xF0, ++0x08, 0x0E, 0x4F, 0xF0, 0x0C, 0x0E, 0x78, 0x4A, 0x01, 0x20, 0x08, 0x21, 0x10, 0x75, 0x15, 0x32, 0x61, 0x70, 0x58, 0x18, ++0x13, 0xF8, 0x01, 0x1B, 0x02, 0xF8, 0x01, 0x1F, 0x98, 0x42, 0xF9, 0xD1, 0x72, 0x4B, 0x01, 0x93, 0xB9, 0xF1, 0x00, 0x0F, ++0x40, 0xF0, 0x99, 0x80, 0xBE, 0xF1, 0x08, 0x0F, 0x19, 0xD0, 0x01, 0x9B, 0x6E, 0x4A, 0x58, 0x1C, 0x32, 0x21, 0x01, 0x90, ++0x19, 0x70, 0x01, 0x9B, 0xAE, 0xF1, 0x08, 0x0E, 0x59, 0x1C, 0x5F, 0xFA, 0x8E, 0xFE, 0x01, 0x91, 0x83, 0xF8, 0x00, 0xE0, ++0x01, 0x9B, 0x18, 0x1D, 0x12, 0xF8, 0x01, 0x1B, 0x03, 0xF8, 0x01, 0x1B, 0x98, 0x42, 0xF9, 0xD1, 0x01, 0x9B, 0x73, 0x44, ++0x01, 0x93, 0x41, 0xF2, 0x0B, 0x03, 0xEB, 0x5C, 0x63, 0xB9, 0x01, 0x9B, 0x03, 0x22, 0x59, 0x1C, 0x01, 0x91, 0x1A, 0x70, ++0x01, 0x9B, 0x01, 0x22, 0x59, 0x1C, 0x01, 0x91, 0x1A, 0x70, 0x01, 0x9B, 0x13, 0x44, 0x01, 0x93, 0xB9, 0xF1, 0x00, 0x0F, ++0x36, 0xD1, 0xDF, 0xF8, 0x7C, 0x81, 0x98, 0xF8, 0x76, 0x31, 0xD8, 0x07, 0x06, 0xD5, 0x56, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, ++0x48, 0x31, 0x98, 0x47, 0x98, 0xF8, 0x76, 0x31, 0x41, 0xF2, 0x0B, 0x02, 0xAA, 0x5C, 0x01, 0x2A, 0x4A, 0xD0, 0x5D, 0x07, ++0x04, 0xD5, 0x4F, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, 0x44, 0x31, 0x98, 0x47, 0x4D, 0x4D, 0x01, 0x98, 0x29, 0x46, 0x31, 0xF8, ++0x03, 0x2B, 0x0A, 0xF0, 0xB1, 0xF8, 0x4B, 0x4A, 0x01, 0x99, 0x12, 0x68, 0x2B, 0x88, 0xB2, 0xF9, 0x00, 0x20, 0x0B, 0x44, ++0x00, 0x2A, 0x01, 0x93, 0xA3, 0xEB, 0x04, 0x03, 0x5D, 0xDB, 0x00, 0x22, 0xA7, 0xF8, 0x6C, 0x31, 0xC7, 0xF8, 0x68, 0x21, ++0x38, 0x46, 0xF5, 0xF7, 0x45, 0xFD, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x32, 0x78, 0x3B, 0x2A, 0x60, 0xD0, 0xDF, 0xF8, ++0x08, 0x81, 0x98, 0xF8, 0x76, 0x31, 0xD9, 0x07, 0x58, 0xD5, 0x39, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, 0x48, 0x31, 0x98, 0x47, ++0xB9, 0xF1, 0x00, 0x0F, 0xC2, 0xD0, 0x01, 0x99, 0x32, 0x78, 0x0B, 0x46, 0x76, 0x1A, 0x49, 0x44, 0x00, 0xE0, 0xF2, 0x5C, ++0x03, 0xF8, 0x01, 0x2B, 0x99, 0x42, 0xFA, 0xD1, 0x01, 0x9A, 0x98, 0xF8, 0x76, 0x31, 0x4A, 0x44, 0x01, 0x92, 0x41, 0xF2, ++0x0B, 0x02, 0xAA, 0x5C, 0x01, 0x2A, 0xB4, 0xD1, 0x9E, 0x07, 0xB2, 0xD5, 0x29, 0x4B, 0x00, 0x21, 0xD3, 0xF8, 0x50, 0x31, ++0x01, 0xA8, 0x98, 0x47, 0x98, 0xF8, 0x76, 0x31, 0xA9, 0xE7, 0x9C, 0xF8, 0x00, 0x20, 0x0A, 0x2A, 0x7F, 0xF4, 0x62, 0xAF, ++0x9C, 0xF8, 0x01, 0x60, 0x02, 0x36, 0x16, 0xF0, 0xFF, 0x06, 0x09, 0xD0, 0x22, 0x49, 0x98, 0x19, 0x01, 0xE0, 0x11, 0xF8, ++0x01, 0x2F, 0x03, 0xF8, 0x01, 0x2B, 0x83, 0x42, 0xF9, 0xD1, 0x01, 0x9B, 0x33, 0x44, 0xA9, 0xEB, 0x06, 0x09, 0x01, 0x93, ++0x1F, 0xFA, 0x89, 0xF9, 0x66, 0x44, 0x49, 0xE7, 0x01, 0x27, 0xB9, 0x42, 0x53, 0xD0, 0x39, 0x46, 0xA0, 0xE6, 0xB3, 0xF5, ++0x96, 0x7F, 0x9E, 0xD9, 0x16, 0x49, 0x17, 0x48, 0xB4, 0x22, 0xF7, 0xF7, 0x99, 0xFD, 0x01, 0x9B, 0x1B, 0x1B, 0x96, 0xE7, ++0x0A, 0x4B, 0x4F, 0xF0, 0x08, 0x0E, 0x22, 0xE7, 0x01, 0x99, 0xAE, 0xE7, 0x70, 0x78, 0x01, 0x99, 0x02, 0x30, 0x10, 0xF0, ++0xFF, 0x00, 0x42, 0xD0, 0x0B, 0x46, 0xA6, 0xEB, 0x03, 0x0C, 0x01, 0x44, 0x1C, 0xE0, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, ++0xE8, 0x61, 0x18, 0x00, 0xB8, 0xB2, 0x15, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xF2, 0x61, 0x18, 0x00, 0xBC, 0xB2, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0xCB, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x63, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x9C, 0xBF, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x1C, 0xF8, 0x03, 0x20, 0x03, 0xF8, 0x01, 0x2B, 0x99, 0x42, 0xF9, 0xD1, ++0xDF, 0xF8, 0x48, 0x80, 0x01, 0x9B, 0x98, 0xF8, 0x76, 0x21, 0x03, 0x44, 0xA9, 0xEB, 0x00, 0x09, 0x01, 0x93, 0xD3, 0x07, ++0x1F, 0xFA, 0x89, 0xF9, 0x06, 0x44, 0x7F, 0xF5, 0x6F, 0xAF, 0x68, 0xE7, 0x41, 0xF2, 0x0B, 0x03, 0x15, 0xF8, 0x03, 0x80, ++0xA3, 0xE6, 0x41, 0xF2, 0x0B, 0x03, 0x02, 0x22, 0xEA, 0x54, 0x00, 0x20, 0xFF, 0xF7, 0xDE, 0xF8, 0x4F, 0xE7, 0xDF, 0xF8, ++0x10, 0x80, 0x98, 0xF8, 0x76, 0x31, 0xDB, 0x07, 0x3F, 0xF5, 0x55, 0xAF, 0x5D, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, ++0xF0, 0xB5, 0x4C, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x83, 0xB0, 0x04, 0xD1, 0x4A, 0x4A, 0x13, 0x68, 0x23, 0xF4, ++0x00, 0x13, 0x13, 0x60, 0x48, 0x4C, 0x49, 0x4D, 0x23, 0x68, 0x5B, 0x07, 0x4E, 0xD4, 0x48, 0x4E, 0x41, 0xF2, 0x0A, 0x03, ++0xEB, 0x5C, 0x5B, 0xB9, 0x44, 0x4A, 0x19, 0x46, 0x02, 0xF5, 0x80, 0x54, 0x80, 0x20, 0x11, 0x72, 0x82, 0xF8, 0x44, 0x00, ++0x40, 0x32, 0x94, 0x42, 0xF9, 0xD1, 0xA9, 0x80, 0x29, 0x68, 0x91, 0xF8, 0x70, 0x21, 0x01, 0x2A, 0x5F, 0xD0, 0x00, 0x24, ++0x20, 0x46, 0x41, 0xF2, 0x3A, 0x02, 0xA8, 0x54, 0x91, 0xF8, 0x6E, 0x21, 0x91, 0xF8, 0x6F, 0x11, 0x08, 0x20, 0xCD, 0xE9, ++0x00, 0x41, 0x38, 0x49, 0xF7, 0xF7, 0xDC, 0xFA, 0x41, 0xF2, 0x0A, 0x03, 0xEB, 0x5C, 0x83, 0xB9, 0x35, 0x49, 0x36, 0x4A, ++0x0B, 0x68, 0x36, 0x48, 0x43, 0xF0, 0x04, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x03, 0x80, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, ++0x43, 0xF4, 0xBB, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x73, 0x68, 0x01, 0x21, 0x43, 0xF0, 0x20, 0x03, 0x04, 0x20, ++0x73, 0x60, 0xF5, 0xF7, 0x01, 0xFE, 0x2B, 0x68, 0xD3, 0xF8, 0x68, 0x11, 0x19, 0xB1, 0xB3, 0xF8, 0x6C, 0x21, 0xC8, 0x2A, ++0x23, 0xD9, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFF, 0xF7, 0xCE, 0xBD, 0x2B, 0x68, 0x25, 0x4A, 0x93, 0xF8, 0x6E, 0x31, ++0x24, 0x49, 0x1E, 0x4E, 0x10, 0x68, 0x24, 0x4A, 0xC0, 0x8E, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x03, 0x13, 0x03, 0x21, ++0x71, 0x77, 0x11, 0x69, 0x20, 0x4A, 0x73, 0x61, 0x01, 0x44, 0xD2, 0xF8, 0xE0, 0x31, 0x06, 0xF1, 0x0C, 0x00, 0x98, 0x47, ++0x01, 0x23, 0x33, 0x77, 0x23, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x23, 0x60, 0x92, 0xE7, 0x1A, 0x48, 0x09, 0xF0, 0x60, 0xFF, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFF, 0xF7, 0xA7, 0xBD, 0x91, 0xF8, 0xFC, 0x20, 0x07, 0x2A, 0x9B, 0xD1, 0x01, 0xF1, ++0xFD, 0x00, 0x14, 0x49, 0x09, 0xF0, 0x22, 0xFF, 0x41, 0xF2, 0x0A, 0x03, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0xEB, 0x5C, ++0x29, 0x68, 0x04, 0x46, 0x8F, 0xE7, 0x00, 0xBF, 0x74, 0x36, 0x17, 0x00, 0x6C, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, ++0xA8, 0xBA, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0xCC, 0xBF, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x20, 0x04, 0x32, 0x40, ++0x28, 0x25, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x18, 0x63, 0x18, 0x00, 0x54, 0xBF, 0x15, 0x00, 0x00, 0x22, 0x02, 0x81, 0xE7, 0xF7, 0xE0, 0xBA, 0x2D, 0xE9, 0xF0, 0x41, ++0x14, 0x46, 0x52, 0x78, 0x00, 0x2B, 0x18, 0xBF, 0x02, 0x23, 0x52, 0x06, 0x44, 0xBF, 0x08, 0x33, 0xDB, 0xB2, 0x23, 0x44, ++0x06, 0x46, 0x9A, 0x7F, 0x08, 0x2A, 0x0D, 0x46, 0x03, 0xD0, 0x00, 0x27, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0xDA, 0x7F, ++0x06, 0x2A, 0xF8, 0xD1, 0x93, 0xF8, 0x26, 0x70, 0x00, 0x2F, 0xF4, 0xD1, 0x93, 0xF8, 0x27, 0x80, 0xB8, 0xF1, 0x01, 0x0F, ++0x07, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0xED, 0xD1, 0x13, 0x49, 0x80, 0x20, 0xF7, 0xF7, 0x2E, 0xFA, 0xE8, 0xE7, 0x93, 0xF8, ++0x3A, 0x70, 0x93, 0xF8, 0x3B, 0xC0, 0x93, 0xF8, 0x38, 0x00, 0x93, 0xF8, 0x39, 0x20, 0x0B, 0x68, 0x0D, 0x49, 0x3F, 0x04, ++0x47, 0xEA, 0x0C, 0x67, 0x07, 0x43, 0x47, 0xEA, 0x02, 0x27, 0x3A, 0x46, 0x80, 0x20, 0xF7, 0xF7, 0x19, 0xFA, 0x2B, 0x68, ++0x9F, 0x42, 0x01, 0xD0, 0x47, 0x46, 0xCF, 0xE7, 0x06, 0x4B, 0x30, 0x78, 0x9B, 0x69, 0x22, 0x46, 0x04, 0xF1, 0x10, 0x01, ++0x47, 0x46, 0x98, 0x47, 0xC6, 0xE7, 0x00, 0xBF, 0x08, 0xC0, 0x15, 0x00, 0xE8, 0xBF, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xF8, 0xB5, 0x21, 0x4B, 0x21, 0x4D, 0x1E, 0x68, 0x95, 0xF8, 0x44, 0x40, 0xB6, 0xF9, 0x00, 0x70, 0x1F, 0x4B, 0x04, 0xEB, ++0x84, 0x06, 0x00, 0x2F, 0x8E, 0x46, 0x03, 0xEB, 0x06, 0x16, 0x23, 0xDB, 0xA7, 0x00, 0x07, 0xEB, 0x04, 0x0C, 0x03, 0xEB, ++0x0C, 0x1C, 0xCC, 0xF8, 0x0C, 0x00, 0x10, 0xB1, 0x01, 0x7C, 0x8C, 0xF8, 0x10, 0x10, 0x3C, 0x44, 0x03, 0xEB, 0x04, 0x13, ++0x31, 0x46, 0x5A, 0x64, 0xA3, 0xF8, 0x4C, 0xE0, 0x13, 0x48, 0xF5, 0xF7, 0xB5, 0xFF, 0x95, 0xF8, 0x44, 0x20, 0x12, 0x4B, ++0x01, 0x32, 0xA3, 0xFB, 0x02, 0x13, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, 0xA2, 0xEB, 0x83, 0x13, 0x85, 0xF8, 0x44, 0x30, ++0x30, 0x46, 0xF8, 0xBD, 0x04, 0xEB, 0x84, 0x01, 0x03, 0xEB, 0x01, 0x11, 0xA7, 0x00, 0xB1, 0xF8, 0x4C, 0x10, 0x00, 0x29, ++0xD3, 0xD0, 0x08, 0x49, 0x08, 0x48, 0xC6, 0x22, 0xF7, 0xF7, 0xBA, 0xFB, 0x00, 0x26, 0xED, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0xB0, 0xDE, 0x17, 0x00, 0xE0, 0x63, 0x18, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0xAB, 0xAA, 0xAA, 0xAA, 0x70, 0x79, 0x15, 0x00, ++0x14, 0xC0, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x4D, 0x42, 0x69, 0x04, 0x46, 0x04, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, ++0x21, 0x46, 0x28, 0x46, 0xF5, 0xF7, 0xCC, 0xFF, 0xA5, 0xF1, 0x08, 0x00, 0x21, 0x46, 0xF5, 0xF7, 0x77, 0xFF, 0x05, 0x4B, ++0xA5, 0xF1, 0x20, 0x00, 0xD3, 0xF8, 0x38, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x08, 0xDF, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xB3, 0x4B, 0x01, 0xF0, 0x7C, 0x04, 0x1A, 0x7A, 0x04, 0x3C, 0x00, 0xEB, ++0x02, 0x0C, 0x01, 0xF4, 0x80, 0x6E, 0x18, 0x2C, 0x0E, 0xD8, 0xDF, 0xE8, 0x04, 0xF0, 0x54, 0x0D, 0x0D, 0x0D, 0x58, 0x0D, ++0x0D, 0x0D, 0x8D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0xB5, 0x00, ++0x00, 0x24, 0xA7, 0x4D, 0x2D, 0x68, 0x2D, 0x78, 0xAD, 0x07, 0x03, 0xD5, 0x01, 0xF0, 0x3C, 0x01, 0x3C, 0x29, 0x02, 0xD0, ++0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xBE, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xD1, 0x80, 0xBC, 0xF8, 0x02, 0x10, 0x9E, 0x7A, ++0x9E, 0x4C, 0x8D, 0x0B, 0x4F, 0xF4, 0xA4, 0x61, 0xC5, 0xEB, 0x05, 0x17, 0x01, 0xFB, 0x06, 0xF1, 0x01, 0xEB, 0xC7, 0x01, ++0x21, 0x44, 0x2F, 0x01, 0x91, 0xF8, 0x3B, 0xE2, 0xBE, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xCC, 0x80, 0x91, 0xF8, 0x38, 0x12, ++0x01, 0x29, 0x00, 0xF0, 0xEB, 0x80, 0x02, 0x29, 0x00, 0xF0, 0xC1, 0x80, 0x0A, 0x1F, 0x01, 0x2A, 0x40, 0xF2, 0xBD, 0x80, ++0x1A, 0x7A, 0x04, 0x32, 0x1A, 0x72, 0xDC, 0xF8, 0x00, 0x00, 0xC1, 0x17, 0xC3, 0xE9, 0x04, 0x01, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x06, 0xF2, 0x79, 0x1B, 0x02, 0xF5, 0xEC, 0x72, 0x02, 0xEB, 0xC1, 0x02, 0x22, 0x44, 0x1A, 0x62, 0x01, 0x24, ++0xC2, 0xE7, 0x14, 0x1D, 0x1C, 0x72, 0x01, 0x24, 0xB5, 0xE7, 0x02, 0xF1, 0x08, 0x04, 0x1C, 0x72, 0x30, 0xF8, 0x02, 0x80, ++0xBC, 0xF8, 0x06, 0x40, 0x9C, 0xF8, 0x02, 0xA0, 0x93, 0xF8, 0x30, 0x90, 0x4F, 0xEA, 0x08, 0x28, 0x1F, 0xFA, 0x88, 0xF8, ++0x46, 0x46, 0xF7, 0x17, 0x44, 0xEA, 0x07, 0x06, 0xBC, 0xF8, 0x04, 0x40, 0x4A, 0xEA, 0x04, 0x44, 0x44, 0xEA, 0x08, 0x04, ++0x49, 0xF0, 0x03, 0x09, 0xC3, 0xE9, 0x04, 0x46, 0x83, 0xF8, 0x30, 0x90, 0xBE, 0xF1, 0x00, 0x0F, 0x5F, 0xD0, 0x9E, 0x7A, ++0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x6E, 0x4E, 0x04, 0xF5, 0xEC, 0x74, ++0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x1C, 0x62, 0x01, 0x24, 0x80, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, ++0x50, 0xD0, 0x9E, 0x7A, 0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x63, 0x4E, ++0x04, 0xF5, 0xEC, 0x74, 0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x02, 0xF1, 0x08, 0x05, 0x1D, 0x72, ++0xBC, 0xF8, 0x04, 0x60, 0x93, 0xF8, 0x30, 0x80, 0x1C, 0x62, 0x84, 0x5A, 0xBC, 0xF8, 0x06, 0x50, 0x5D, 0x61, 0x44, 0xEA, ++0x06, 0x44, 0x48, 0xF0, 0x02, 0x05, 0x1C, 0x61, 0x83, 0xF8, 0x30, 0x50, 0x01, 0x24, 0x58, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, ++0x2F, 0xD0, 0x9E, 0x7A, 0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x4F, 0x4E, ++0x04, 0xF5, 0xEC, 0x74, 0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x02, 0xF1, 0x12, 0x05, 0x66, 0x46, ++0x1D, 0x72, 0x56, 0xF8, 0x02, 0x7F, 0x93, 0xF8, 0x30, 0x50, 0x76, 0x68, 0x1C, 0x62, 0x45, 0xF0, 0x02, 0x04, 0x83, 0xF8, ++0x30, 0x40, 0xC3, 0xE9, 0x04, 0x76, 0x01, 0x24, 0x33, 0xE7, 0x5C, 0x7A, 0x42, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, ++0x04, 0x54, 0xA8, 0xE7, 0x5C, 0x7A, 0x3F, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0x54, 0xB7, 0xE7, 0x5C, 0x7A, ++0x3B, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0x54, 0xD8, 0xE7, 0x59, 0x7A, 0x39, 0x4D, 0x4F, 0xF4, 0x1E, 0x74, ++0x04, 0xFB, 0x01, 0xF4, 0x29, 0x19, 0x91, 0xF8, 0x98, 0x10, 0x01, 0x29, 0x43, 0xD0, 0x02, 0x29, 0x04, 0xD1, 0x34, 0x48, ++0xF7, 0xF7, 0x36, 0xF8, 0x00, 0x24, 0x15, 0xE7, 0x0A, 0x1F, 0x01, 0x2A, 0xF7, 0xD9, 0x18, 0x7A, 0xBC, 0xF8, 0x02, 0x10, ++0x9D, 0x7A, 0x2B, 0x4E, 0x04, 0x30, 0x18, 0x72, 0xDC, 0xF8, 0x00, 0x40, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x05, 0xF2, ++0x89, 0x0B, 0xE5, 0x17, 0xC1, 0xEB, 0x01, 0x11, 0x02, 0xF5, 0xEC, 0x72, 0xC3, 0xE9, 0x04, 0x45, 0x02, 0xEB, 0xC1, 0x02, ++0x32, 0x44, 0x92, 0xF8, 0x63, 0x10, 0x00, 0x29, 0xDE, 0xD0, 0x1A, 0x62, 0x01, 0x24, 0xF3, 0xE6, 0x19, 0x7A, 0x93, 0xF8, ++0x30, 0xE0, 0x08, 0x31, 0x19, 0x72, 0x82, 0x5A, 0x9C, 0xF8, 0x02, 0x80, 0xBC, 0xF8, 0x04, 0x00, 0xBC, 0xF8, 0x06, 0x90, ++0x12, 0x02, 0x92, 0xB2, 0xD1, 0x17, 0x48, 0xEA, 0x00, 0x40, 0x49, 0xEA, 0x01, 0x09, 0x02, 0x43, 0x4E, 0xF0, 0x03, 0x0E, ++0xC3, 0xE9, 0x04, 0x29, 0x83, 0xF8, 0x30, 0xE0, 0x08, 0xE7, 0x19, 0x7A, 0x93, 0xF8, 0x30, 0x70, 0x08, 0x31, 0x19, 0x72, ++0x81, 0x5A, 0xBC, 0xF8, 0x04, 0x80, 0x9C, 0xF8, 0x02, 0x00, 0xBC, 0xF8, 0x06, 0x60, 0x09, 0x02, 0x89, 0xB2, 0x04, 0xF1, ++0x38, 0x02, 0x40, 0xEA, 0x08, 0x44, 0x0C, 0x43, 0xC9, 0x17, 0x47, 0xF0, 0x03, 0x07, 0x0E, 0x43, 0xC3, 0xE9, 0x04, 0x46, ++0x2A, 0x44, 0x83, 0xF8, 0x30, 0x70, 0xC0, 0xE7, 0xB0, 0xDE, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xA0, 0x65, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x34, 0xC0, 0x15, 0x00, 0x70, 0xB5, 0x18, 0x4E, 0x18, 0x4A, 0xB3, 0x7A, ++0x75, 0x7A, 0x12, 0x7C, 0x1B, 0x02, 0x43, 0xEA, 0x05, 0x43, 0xF5, 0x7A, 0x04, 0x46, 0x00, 0x6E, 0x43, 0xEA, 0x05, 0x63, ++0xFF, 0x2A, 0x0D, 0x46, 0x43, 0xEA, 0x00, 0x03, 0x17, 0xD0, 0x41, 0xF0, 0x80, 0x05, 0x43, 0xF0, 0x80, 0x03, 0xEA, 0x07, ++0x48, 0xBF, 0x43, 0xF0, 0x40, 0x03, 0x0D, 0x4A, 0x58, 0xBF, 0x23, 0xF0, 0x40, 0x03, 0x23, 0x66, 0x20, 0x46, 0xD2, 0xF8, ++0xA8, 0x32, 0x98, 0x47, 0x32, 0x6C, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xEF, 0xBD, 0x29, 0x06, ++0x58, 0xBF, 0x23, 0xF0, 0x80, 0x03, 0xE6, 0xD5, 0xE3, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x21, 0x4B, 0x21, 0x4E, 0x1B, 0x7C, 0xFF, 0x2B, 0x04, 0x46, 0x0D, 0x46, 0x21, 0xD0, ++0xB2, 0x7A, 0xFF, 0x2A, 0x32, 0xD0, 0x01, 0xF0, 0x01, 0x01, 0x45, 0xF0, 0x80, 0x05, 0x77, 0x7A, 0x20, 0x6E, 0x13, 0x02, ++0x43, 0xEA, 0x07, 0x43, 0x03, 0x43, 0x43, 0xF0, 0x82, 0x03, 0x11, 0xB3, 0x43, 0xF0, 0x40, 0x03, 0x16, 0x49, 0x23, 0x66, ++0x00, 0x22, 0xD1, 0xF8, 0xA8, 0x32, 0x86, 0xF8, 0x32, 0x20, 0x20, 0x46, 0x98, 0x47, 0x32, 0x6C, 0x29, 0x46, 0x20, 0x46, ++0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0xB8, 0xBD, 0xB3, 0x7A, 0x71, 0x7A, 0x02, 0x6E, 0x1B, 0x02, 0x43, 0xEA, 0x01, 0x43, ++0x13, 0x43, 0x2A, 0x06, 0x0D, 0xD4, 0x23, 0xF0, 0x80, 0x03, 0x05, 0xF0, 0x01, 0x01, 0x43, 0xF0, 0x02, 0x03, 0x00, 0x29, ++0xDC, 0xD1, 0x23, 0xF0, 0x40, 0x03, 0xDB, 0xE7, 0x00, 0x21, 0x80, 0x25, 0xCD, 0xE7, 0x05, 0xF0, 0x01, 0x01, 0xD0, 0xE7, ++0x00, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x32, 0x4B, 0x01, 0x88, 0x70, 0xB4, 0x19, 0x80, ++0xC2, 0x8A, 0x5A, 0x80, 0x01, 0xF0, 0x88, 0x06, 0xC2, 0xF3, 0x0B, 0x14, 0x00, 0x25, 0x02, 0xF0, 0x0F, 0x02, 0x88, 0x2E, ++0x9C, 0x80, 0x9A, 0x71, 0x8C, 0xB2, 0x83, 0xF8, 0x30, 0x50, 0x45, 0xD0, 0xDD, 0x71, 0x04, 0xF4, 0x40, 0x72, 0xB2, 0xF5, ++0x40, 0x7F, 0x04, 0xF0, 0xFC, 0x05, 0x0C, 0xBF, 0x1E, 0x22, 0x18, 0x22, 0x88, 0x2D, 0x08, 0xBF, 0x02, 0x32, 0x0E, 0x04, ++0x44, 0xBF, 0x04, 0x32, 0xD2, 0xB2, 0x1A, 0x72, 0x02, 0x79, 0xD5, 0x07, 0x44, 0xBF, 0x08, 0x22, 0x83, 0xF8, 0x30, 0x20, ++0xE4, 0x05, 0x12, 0xD5, 0x02, 0x8A, 0x9A, 0x84, 0x42, 0x8A, 0xDA, 0x84, 0x82, 0x8A, 0x1A, 0x85, 0x02, 0x88, 0x91, 0x05, ++0x12, 0xD5, 0xD2, 0x05, 0x18, 0xD5, 0x02, 0x8B, 0x5A, 0x85, 0x42, 0x8B, 0x9A, 0x85, 0x82, 0x8B, 0xDA, 0x85, 0x70, 0xBC, ++0x70, 0x47, 0x82, 0x88, 0x9A, 0x84, 0xC2, 0x88, 0xDA, 0x84, 0x02, 0x89, 0x1A, 0x85, 0x02, 0x88, 0x91, 0x05, 0xEC, 0xD4, ++0x42, 0x89, 0x5A, 0x85, 0x82, 0x89, 0x9A, 0x85, 0xC2, 0x89, 0xDA, 0x85, 0x70, 0xBC, 0x70, 0x47, 0x02, 0x8A, 0x5A, 0x85, ++0x42, 0x8A, 0x9A, 0x85, 0x82, 0x8A, 0xDA, 0x85, 0x70, 0xBC, 0x70, 0x47, 0x04, 0xF4, 0x40, 0x72, 0xB2, 0xF5, 0x40, 0x7F, ++0x0C, 0xBF, 0xC5, 0x8B, 0x05, 0x8B, 0x05, 0xF0, 0x07, 0x05, 0xDD, 0x71, 0xB1, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, ++0xF8, 0xB5, 0x05, 0x22, 0x18, 0x23, 0x0C, 0x21, 0x41, 0xF2, 0x06, 0x40, 0xF5, 0xF7, 0x74, 0xF8, 0x0F, 0x4A, 0x03, 0x46, ++0x51, 0x7A, 0x0F, 0x48, 0x94, 0x69, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x01, 0x01, 0xD2, 0xE9, 0x04, 0x67, 0x51, 0xF8, ++0x26, 0x0F, 0x89, 0x88, 0x99, 0x80, 0xC3, 0xE9, 0x02, 0x67, 0x18, 0x60, 0x91, 0x7A, 0x99, 0x74, 0xC4, 0xF3, 0x80, 0x24, ++0x1C, 0x74, 0x12, 0x6A, 0x92, 0xF8, 0x61, 0x20, 0x5A, 0x74, 0x18, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xF5, 0xF7, 0x84, 0xB8, ++0xB0, 0xDE, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x3C, 0x82, 0xD8, 0xF8, 0x00, 0x40, ++0x27, 0x78, 0x87, 0xB0, 0x17, 0xF0, 0x01, 0x07, 0x04, 0x46, 0x03, 0x93, 0x08, 0xD0, 0x43, 0x6D, 0x03, 0xF0, 0x07, 0x03, ++0x02, 0x2B, 0x7F, 0xD0, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x80, 0x4D, 0x89, 0x46, 0x00, 0x2A, 0x40, 0xF0, ++0xA2, 0x80, 0x02, 0x8E, 0x2B, 0x7A, 0xC6, 0x69, 0xD4, 0x1A, 0x03, 0x9A, 0xA4, 0xB2, 0x10, 0x31, 0x12, 0xB1, 0x07, 0x2C, ++0x40, 0xF2, 0xA9, 0x80, 0x08, 0x22, 0x48, 0x46, 0xFA, 0xF7, 0x92, 0xFF, 0x29, 0x7A, 0x8A, 0xB2, 0xD6, 0xE9, 0x02, 0x03, ++0x08, 0x3C, 0x01, 0x33, 0xA5, 0xB2, 0x1C, 0x1A, 0xA4, 0xB2, 0x4B, 0x19, 0x9C, 0x42, 0x01, 0x44, 0x80, 0xF2, 0x82, 0x80, ++0xDF, 0xF8, 0xD4, 0xA1, 0x13, 0x1B, 0x1D, 0x44, 0xA2, 0x1A, 0x92, 0xB2, 0x48, 0x46, 0xAD, 0xB2, 0xFA, 0xF7, 0x7A, 0xFF, ++0x00, 0x22, 0x95, 0xB1, 0xDA, 0xF8, 0x00, 0x30, 0x76, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x93, 0x42, 0x4D, 0xDB, 0xD6, 0xE9, ++0x02, 0x14, 0x01, 0x34, 0x64, 0x1A, 0xA4, 0xB2, 0xAC, 0x42, 0xE7, 0xD3, 0x2C, 0x46, 0x2A, 0x46, 0x48, 0x46, 0xFA, 0xF7, ++0x65, 0xFF, 0xDF, 0xF8, 0x98, 0xE1, 0x0D, 0xF1, 0x10, 0x0C, 0x08, 0x25, 0xD6, 0xE9, 0x02, 0x32, 0x01, 0x32, 0x98, 0xB2, ++0x92, 0xB2, 0xA2, 0xEB, 0x00, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x29, 0x19, 0x51, 0x45, 0x23, 0x44, 0x3B, 0xDD, 0xAA, 0xEB, ++0x04, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x0A, 0xF1, 0xFF, 0x3B, 0xBA, 0xF1, 0x00, 0x0F, 0x37, 0xD0, 0x82, 0x1A, 0x14, 0x44, ++0x25, 0x44, 0xAD, 0xB2, 0x59, 0x1C, 0x59, 0x44, 0xAC, 0xEB, 0x03, 0x00, 0x1A, 0x78, 0xC2, 0x54, 0x01, 0x33, 0x8B, 0x42, ++0xFA, 0xD1, 0xD4, 0x44, 0x65, 0xB3, 0xDE, 0xF8, 0x00, 0x30, 0x76, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x24, 0xA3, 0x42, ++0xD2, 0xDA, 0x00, 0x2E, 0xD0, 0xD1, 0x47, 0x49, 0x47, 0x48, 0x40, 0xF2, 0x66, 0x42, 0xF7, 0xF7, 0x6F, 0xF8, 0x7F, 0xE7, ++0xFF, 0xF7, 0x40, 0xFF, 0x00, 0x27, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2E, 0xAF, 0xD1, 0x3F, 0x49, ++0x3F, 0x48, 0x40, 0xF2, 0x3C, 0x42, 0xF7, 0xF7, 0x5F, 0xF8, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xAA, 0x46, ++0x05, 0xF1, 0xFF, 0x3B, 0x00, 0x25, 0xCB, 0xE7, 0x01, 0x44, 0x8A, 0x1A, 0x95, 0xB2, 0xD2, 0xE7, 0x03, 0x9B, 0x00, 0x2B, ++0x3C, 0xD1, 0xDD, 0xE9, 0x04, 0x23, 0xC9, 0xE9, 0x04, 0x23, 0x01, 0x27, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x2A, 0x44, 0x94, 0xB2, 0x95, 0xE7, 0x29, 0x6A, 0xEB, 0x79, 0x00, 0x93, 0x58, 0x31, 0x05, 0xF1, 0x2A, 0x03, 0x05, 0xF1, ++0x24, 0x02, 0x48, 0x46, 0xFA, 0xF7, 0xCE, 0xFE, 0x29, 0x7A, 0x23, 0x8E, 0xE6, 0x69, 0x5C, 0x1A, 0xA4, 0xB2, 0x8A, 0xB2, ++0x5C, 0xE7, 0xB5, 0x68, 0x03, 0x91, 0x22, 0x46, 0x48, 0x46, 0x1D, 0x44, 0xFA, 0xF7, 0xE6, 0xFE, 0x03, 0x99, 0xC4, 0xF1, ++0x08, 0x06, 0x04, 0xAB, 0xF6, 0xB2, 0x21, 0x44, 0xF2, 0x18, 0xC9, 0x1A, 0xC8, 0x5C, 0x03, 0xF8, 0x01, 0x0B, 0x9A, 0x42, ++0xFA, 0xD1, 0xD6, 0xF1, 0x08, 0x06, 0x07, 0xD0, 0x2B, 0x46, 0xD2, 0x1A, 0x35, 0x44, 0x19, 0x78, 0xD1, 0x54, 0x01, 0x33, ++0x9D, 0x42, 0xFA, 0xD1, 0x48, 0x46, 0xFA, 0xF7, 0x69, 0xFF, 0x04, 0x9A, 0xD9, 0xF8, 0x00, 0x30, 0x9A, 0x42, 0x0D, 0xD0, ++0xD8, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x9B, 0x07, 0x05, 0xD5, 0x03, 0x20, 0xD8, 0xF7, 0xCE, 0xF9, 0x0F, 0x4B, 0x98, 0x42, ++0x12, 0xD1, 0xFF, 0xF7, 0xD1, 0xFE, 0x0D, 0xE7, 0xD9, 0xF8, 0x04, 0x30, 0x05, 0x9A, 0x9A, 0x42, 0xEC, 0xD1, 0xD8, 0xF8, ++0x00, 0x30, 0x1B, 0x78, 0x9A, 0x07, 0xA6, 0xD5, 0x03, 0x20, 0xD8, 0xF7, 0xBB, 0xF9, 0x06, 0x4B, 0x98, 0x42, 0xA0, 0xD0, ++0x05, 0x48, 0xF6, 0xF7, 0xA1, 0xFD, 0xF9, 0xE6, 0xB0, 0xDE, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, ++0x1C, 0xDF, 0x44, 0x21, 0x44, 0xC0, 0x15, 0x00, 0x34, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x10, 0xB5, 0x10, 0x48, ++0xF5, 0xF7, 0xF8, 0xFB, 0x10, 0xB1, 0x04, 0x46, 0x20, 0x46, 0x10, 0xBD, 0x0D, 0x48, 0xF5, 0xF7, 0xF1, 0xFB, 0x0D, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x06, 0xDB, 0x62, 0x69, 0x04, 0x21, 0x00, 0x20, 0xFF, 0xF7, ++0xC7, 0xFB, 0x20, 0x46, 0x10, 0xBD, 0x00, 0x28, 0xF6, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xEA, 0x42, 0xF6, 0xF7, ++0xEB, 0xFF, 0xEF, 0xE7, 0x00, 0xDF, 0x17, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x54, 0xC0, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x63, 0x79, 0x62, 0x69, 0x83, 0x42, 0x14, 0xBF, 0x18, 0x21, ++0x08, 0x21, 0xFF, 0xF7, 0xA7, 0xFB, 0x08, 0xB1, 0xA3, 0x89, 0x83, 0x64, 0x10, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, ++0xA3, 0x4F, 0x8A, 0xB0, 0x05, 0x46, 0x14, 0x46, 0x1A, 0xB3, 0x3E, 0x88, 0x97, 0xF8, 0x07, 0x80, 0x16, 0xF4, 0x80, 0x66, ++0x22, 0xD1, 0x97, 0xF8, 0x06, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x6A, 0xD0, 0xBC, 0x6D, 0xBA, 0x88, 0x14, 0xB9, 0x31, 0xE1, ++0x24, 0x68, 0xEC, 0xB1, 0xA3, 0x79, 0x8B, 0x42, 0xFA, 0xD1, 0xE3, 0x79, 0x43, 0x45, 0xF7, 0xD1, 0x63, 0x89, 0x93, 0x42, ++0xF4, 0xD1, 0x23, 0x7A, 0x53, 0x45, 0x00, 0xF0, 0x90, 0x80, 0x4F, 0xF0, 0x00, 0x0A, 0x50, 0x46, 0x0A, 0xB0, 0xBD, 0xE8, ++0xF0, 0x87, 0x3E, 0x88, 0x16, 0xF4, 0x80, 0x66, 0x90, 0x46, 0xDC, 0xD0, 0xBC, 0x6D, 0xBA, 0x88, 0x97, 0xF8, 0x06, 0xA0, ++0x00, 0x2C, 0xE1, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0xEB, 0xD1, 0x03, 0x91, 0xFF, 0xF7, 0x88, 0xFF, 0x01, 0x26, 0x03, 0x99, ++0x81, 0x71, 0x80, 0xF8, 0x07, 0x80, 0x06, 0x72, 0xBA, 0x88, 0x80, 0xF8, 0x04, 0xA0, 0x39, 0x7A, 0x82, 0x4B, 0xC0, 0xF8, ++0x10, 0xA0, 0x41, 0x72, 0x19, 0x69, 0xDF, 0xF8, 0x0C, 0x92, 0x80, 0x4B, 0x42, 0x81, 0x01, 0xF5, 0xC3, 0x31, 0x83, 0x63, ++0xC0, 0x63, 0xD9, 0xF8, 0xE0, 0x31, 0x04, 0x46, 0xA0, 0x31, 0x34, 0x30, 0x98, 0x47, 0x97, 0xF8, 0x30, 0x30, 0xDA, 0x07, ++0x00, 0xF1, 0xC9, 0x80, 0x2B, 0x6E, 0x23, 0xF0, 0x20, 0x03, 0x2B, 0x66, 0xD9, 0xF8, 0xE8, 0x32, 0x01, 0x21, 0x28, 0x46, ++0x98, 0x47, 0x3B, 0x6C, 0xFA, 0x69, 0x73, 0x48, 0xC4, 0xE9, 0x04, 0x23, 0x97, 0xF8, 0x31, 0x30, 0x63, 0x71, 0x2B, 0x8E, ++0xA3, 0x81, 0x21, 0x46, 0xF5, 0xF7, 0x08, 0xFB, 0x6B, 0x4B, 0x4F, 0xF0, 0x01, 0x0A, 0x1B, 0x69, 0xA3, 0x61, 0x50, 0x46, ++0x0A, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x97, 0xF8, 0x30, 0x30, 0xD8, 0x07, 0x1D, 0xD5, 0x68, 0x4A, 0x01, 0x23, 0xD2, 0xF8, ++0xCC, 0x62, 0x04, 0xA9, 0x1A, 0x46, 0x28, 0x46, 0xB0, 0x47, 0x00, 0x28, 0x9B, 0xD0, 0x2B, 0x8E, 0x63, 0x4A, 0x08, 0x3B, ++0x12, 0x68, 0x2B, 0x86, 0x13, 0x78, 0x99, 0x07, 0x0B, 0xD5, 0x6B, 0x6D, 0x03, 0xF0, 0x3C, 0x02, 0x3C, 0x2A, 0x06, 0xD1, ++0x23, 0xF0, 0x7C, 0x03, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xF0, 0x08, 0x03, 0x6B, 0x65, 0x5B, 0x4B, 0xB8, 0x7A, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC3, 0x34, 0x00, 0x2B, 0x6D, 0xD1, 0x54, 0x4B, 0x28, 0x46, 0xD3, 0xF8, ++0xE8, 0x32, 0x03, 0x21, 0x98, 0x47, 0x4F, 0xF0, 0x01, 0x0A, 0x50, 0x46, 0x0A, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x29, 0x8E, ++0x94, 0xF8, 0x09, 0x80, 0xA3, 0x89, 0xDF, 0xF8, 0x30, 0x91, 0xA1, 0xEB, 0x08, 0x08, 0x1F, 0xFA, 0x88, 0xF8, 0x43, 0x44, ++0x0A, 0xF1, 0x01, 0x0A, 0x84, 0xF8, 0x08, 0xA0, 0xA3, 0x81, 0x97, 0xF8, 0x30, 0x30, 0xDB, 0x07, 0x22, 0xD5, 0xB6, 0xFA, ++0x86, 0xF3, 0xD9, 0xF8, 0xCC, 0x72, 0x5B, 0x09, 0x00, 0x22, 0x04, 0xF1, 0x1C, 0x01, 0x28, 0x46, 0xB8, 0x47, 0x00, 0x28, ++0x4C, 0xD0, 0x2B, 0x6E, 0x00, 0x2E, 0x57, 0xD0, 0x61, 0x7A, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, 0x40, 0x03, ++0x2B, 0x66, 0x41, 0x44, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0xD9, 0xF8, 0xA4, 0x62, 0x89, 0xB2, 0x28, 0x46, 0xB0, 0x47, ++0x23, 0x69, 0x43, 0x44, 0x23, 0x61, 0x87, 0xE7, 0x01, 0x27, 0x2B, 0x6E, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, ++0x40, 0x03, 0x2B, 0x66, 0x00, 0x23, 0xCD, 0xE9, 0x00, 0x33, 0x28, 0x46, 0xD9, 0xF8, 0xA4, 0x52, 0xA8, 0x47, 0x23, 0x69, ++0x43, 0x44, 0x23, 0x61, 0x00, 0x2E, 0x7F, 0xF4, 0x73, 0xAF, 0x20, 0x46, 0xFF, 0xF7, 0xEC, 0xFE, 0x62, 0x69, 0x39, 0x46, ++0x00, 0x20, 0xFF, 0xF7, 0x99, 0xFA, 0xD9, 0xF8, 0xD8, 0x31, 0x04, 0xF1, 0x34, 0x00, 0x98, 0x47, 0x21, 0x46, 0x20, 0x48, ++0xF5, 0xF7, 0xBA, 0xFA, 0x22, 0x48, 0x21, 0x46, 0xF5, 0xF7, 0x66, 0xFA, 0x5C, 0xE7, 0xEA, 0x69, 0x00, 0xF2, 0xC4, 0x41, ++0x92, 0x68, 0x23, 0x46, 0x63, 0x30, 0xFF, 0xF7, 0x31, 0xFA, 0x01, 0x28, 0x87, 0xD1, 0x04, 0xE7, 0x61, 0x7A, 0x41, 0x44, ++0x89, 0xB2, 0x04, 0x27, 0xC5, 0xE7, 0x32, 0x46, 0x53, 0x46, 0xD9, 0xF8, 0xCC, 0x62, 0x04, 0xF1, 0x1C, 0x01, 0x28, 0x46, ++0xB0, 0x47, 0x2D, 0xE7, 0xA0, 0x89, 0x61, 0x7A, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, 0x40, 0x03, 0x08, 0x38, ++0xA0, 0x81, 0x41, 0x44, 0x2B, 0x66, 0x28, 0x46, 0x33, 0x46, 0xCD, 0xE9, 0x00, 0x66, 0xD9, 0xF8, 0xA4, 0x52, 0x89, 0xB2, ++0xA8, 0x47, 0x23, 0x69, 0x43, 0x44, 0x23, 0x61, 0x01, 0x27, 0xB8, 0xE7, 0xA2, 0x46, 0xDC, 0xE6, 0xB0, 0xDE, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0xC5, 0xD3, 0x14, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x00, 0xDF, 0x17, 0x00, 0xF8, 0xB5, 0x03, 0x88, 0x13, 0x4D, 0x13, 0xF4, 0x00, 0x6F, 0x04, 0x46, ++0xC3, 0x8A, 0x0B, 0xD1, 0x05, 0xF1, 0x60, 0x07, 0x00, 0xF1, 0x0A, 0x06, 0x30, 0x68, 0xB2, 0x88, 0xBA, 0x80, 0x28, 0x66, ++0xA5, 0xF8, 0x66, 0x30, 0x01, 0x20, 0xF8, 0xBD, 0xB5, 0xF8, 0x66, 0x20, 0x9A, 0x42, 0x04, 0xD0, 0x00, 0xF1, 0x0A, 0x06, ++0x05, 0xF1, 0x60, 0x07, 0xEE, 0xE7, 0x05, 0xF1, 0x60, 0x07, 0x00, 0xF1, 0x0A, 0x06, 0x39, 0x46, 0x30, 0x46, 0x06, 0x22, ++0x09, 0xF0, 0xC6, 0xF8, 0x00, 0x28, 0xEA, 0xD0, 0xE3, 0x8A, 0xE1, 0xE7, 0xB0, 0xDE, 0x17, 0x00, 0xF0, 0xB4, 0x01, 0xB3, ++0x00, 0x22, 0x87, 0x7A, 0x94, 0x46, 0x07, 0xE0, 0x1E, 0x69, 0x1E, 0xB1, 0x01, 0x3C, 0xC3, 0xF8, 0x10, 0xC0, 0xC4, 0x72, ++0x8D, 0x42, 0x09, 0xD2, 0xBB, 0x18, 0xC4, 0x7A, 0x03, 0xF0, 0x3F, 0x03, 0x01, 0x32, 0x00, 0xEB, 0x83, 0x03, 0x95, 0xB2, ++0x00, 0x2C, 0xED, 0xD1, 0x03, 0x89, 0x0F, 0x44, 0x19, 0x44, 0x07, 0xF0, 0x3F, 0x07, 0xC1, 0xF3, 0x0B, 0x01, 0x87, 0x72, ++0x01, 0x81, 0xF0, 0xBC, 0x70, 0x47, 0x87, 0x7A, 0xF2, 0xE7, 0x00, 0xBF, 0xF8, 0xB5, 0x83, 0x7A, 0x04, 0x33, 0x50, 0xF8, ++0x23, 0x30, 0x53, 0xB3, 0xC1, 0x7A, 0x15, 0x4D, 0x15, 0x4F, 0x16, 0x4E, 0x04, 0x46, 0x15, 0xE0, 0xA3, 0x7A, 0x22, 0x89, ++0x18, 0x1D, 0x01, 0x33, 0x03, 0xF0, 0x3F, 0x03, 0x01, 0x39, 0x4F, 0xF0, 0x00, 0x0C, 0x44, 0xF8, 0x20, 0xC0, 0xC9, 0xB2, ++0x18, 0x1D, 0xA3, 0x72, 0xE1, 0x72, 0x54, 0xF8, 0x20, 0x00, 0x53, 0x1C, 0xC3, 0xF3, 0x0B, 0x03, 0x23, 0x81, 0x70, 0xB1, ++0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE4, 0xDA, 0x00, 0x29, 0xE2, 0xD1, 0x39, 0x46, 0x4F, 0xF4, 0xD6, 0x62, ++0x30, 0x46, 0xF6, 0xF7, 0xF5, 0xFD, 0xE1, 0x7A, 0xDA, 0xE7, 0xF8, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x9E, 0x23, 0x0C, 0x8A, 0x38, 0x4A, 0x03, 0xFB, 0x00, 0xF0, 0x00, 0xEB, ++0x14, 0x30, 0x02, 0xEB, 0x80, 0x00, 0xD0, 0xF8, 0x7C, 0x41, 0x4C, 0xB3, 0x94, 0xF8, 0x21, 0x31, 0x49, 0x8A, 0xC3, 0xB1, ++0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x30, 0xD5, 0x30, 0x48, 0x31, 0x4D, 0x03, 0x68, 0x2E, 0x68, 0x03, 0xF0, 0x60, 0x42, ++0x77, 0x1C, 0xB2, 0xF1, 0xC0, 0x4F, 0x2F, 0x60, 0x31, 0xD0, 0x2D, 0x4B, 0x80, 0x22, 0x1A, 0x60, 0x2F, 0xB1, 0x2C, 0x4B, ++0x2E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x22, 0x89, 0xB2, 0xEB, 0x11, 0x1F, 0x4F, 0xEA, 0x11, 0x13, ++0x06, 0xD0, 0x9B, 0x1A, 0x99, 0xB2, 0x1B, 0x05, 0x04, 0xD5, 0x94, 0xF8, 0x21, 0x31, 0x9B, 0xB1, 0xBD, 0xE8, 0xF0, 0x81, ++0x22, 0x4D, 0x20, 0x46, 0xD5, 0xF8, 0xD8, 0x32, 0xC1, 0xF3, 0x0B, 0x01, 0x98, 0x47, 0xD5, 0xF8, 0x38, 0x31, 0x1F, 0x48, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xC9, 0xE7, 0x1B, 0x48, 0xF6, 0xF7, ++0x23, 0xFB, 0x01, 0x23, 0x84, 0xF8, 0x21, 0x31, 0xE4, 0xE7, 0x19, 0x4A, 0x03, 0xF4, 0xF0, 0x33, 0xD2, 0xF8, 0x00, 0xC0, ++0xB3, 0xF5, 0xF0, 0x3F, 0x0C, 0xF1, 0x10, 0x0C, 0xC3, 0xD0, 0x96, 0x46, 0x03, 0x68, 0x03, 0xF0, 0x60, 0x42, 0xB2, 0xF1, ++0xC0, 0x4F, 0x02, 0xD0, 0x10, 0x4B, 0x1B, 0x68, 0xB9, 0xE7, 0x03, 0xF4, 0xF0, 0x33, 0xB3, 0xF5, 0xF0, 0x3F, 0xF7, 0xD0, ++0xDE, 0xF8, 0x00, 0x30, 0xA3, 0xEB, 0x0C, 0x03, 0x00, 0x2B, 0xEB, 0xDB, 0x00, 0x2F, 0xB6, 0xD0, 0xAF, 0xE7, 0x00, 0xBF, ++0x68, 0x65, 0x17, 0x00, 0x04, 0x05, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x54, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0x7C, 0xC0, 0x15, 0x00, 0x20, 0x01, 0x32, 0x40, 0x2D, 0xE9, 0xF8, 0x43, ++0x8D, 0x4F, 0x8E, 0x4B, 0xBC, 0x7A, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x80, 0x46, 0x94, 0xF8, 0xC3, 0x54, ++0x89, 0x46, 0x00, 0x2D, 0x40, 0xF0, 0x90, 0x80, 0xF8, 0x79, 0x88, 0x49, 0xBA, 0x88, 0x9E, 0x23, 0x03, 0xFB, 0x09, 0x03, ++0x01, 0xEB, 0x83, 0x03, 0xD3, 0xF8, 0x7C, 0x41, 0x23, 0x89, 0x9A, 0x42, 0x00, 0xF0, 0xA5, 0x80, 0xD2, 0x1A, 0x12, 0xF4, ++0x7C, 0x6F, 0xC2, 0xF3, 0x0B, 0x03, 0x38, 0xD1, 0xA6, 0x7A, 0x1E, 0x44, 0x06, 0xF0, 0x3F, 0x06, 0x01, 0x23, 0x04, 0xEB, ++0x86, 0x06, 0x84, 0xF8, 0x20, 0x31, 0x33, 0x69, 0x00, 0x2B, 0x6B, 0xD1, 0x8D, 0xB9, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, ++0x32, 0x30, 0x77, 0x49, 0x42, 0xF0, 0x20, 0x02, 0xC8, 0xF8, 0x60, 0x20, 0x23, 0xF0, 0xFF, 0x03, 0xD1, 0xF8, 0xE8, 0x22, ++0xA8, 0xF8, 0x32, 0x30, 0x40, 0x46, 0x03, 0x21, 0x90, 0x47, 0x71, 0x4B, 0x33, 0x61, 0xE3, 0x7A, 0x70, 0x4A, 0x01, 0x33, ++0x12, 0x68, 0xDB, 0xB2, 0xE3, 0x72, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xB1, 0x80, 0x01, 0x2B, 0x00, 0xF0, ++0xB9, 0x80, 0xC5, 0xF1, 0x01, 0x05, 0xED, 0xB2, 0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xFE, 0xFE, 0x28, 0x46, 0xBD, 0xE8, ++0xF8, 0x83, 0x40, 0xF2, 0xFE, 0x72, 0x93, 0x42, 0x40, 0xF2, 0x91, 0x80, 0x94, 0xF8, 0x20, 0x31, 0x13, 0xB1, 0x94, 0xF8, ++0x21, 0x31, 0x9B, 0xB3, 0x3B, 0x88, 0x1B, 0x05, 0x21, 0xD4, 0x7A, 0x88, 0x4F, 0xF4, 0x9E, 0x73, 0x03, 0xFB, 0x09, 0x03, ++0x01, 0xEB, 0x43, 0x03, 0xA3, 0xF8, 0xEA, 0x21, 0x15, 0xBB, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, 0x32, 0x30, 0x55, 0x49, ++0x42, 0xF0, 0x20, 0x02, 0x23, 0xF0, 0xFF, 0x03, 0xC8, 0xF8, 0x60, 0x20, 0xD1, 0xF8, 0xE8, 0x22, 0xA8, 0xF8, 0x32, 0x30, ++0x40, 0x46, 0x03, 0x21, 0x90, 0x47, 0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xCD, 0xFE, 0x01, 0x25, 0xCC, 0xE7, 0x4F, 0xF4, ++0x9E, 0x73, 0x03, 0xFB, 0x09, 0x03, 0x01, 0xEB, 0x43, 0x03, 0x7A, 0x88, 0xB3, 0xF8, 0xEA, 0x31, 0x93, 0x42, 0xD3, 0xD1, ++0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xBC, 0xFE, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0xC2, 0x69, 0x04, 0xF2, ++0xC4, 0x41, 0x92, 0x68, 0x01, 0x23, 0x04, 0xF1, 0x63, 0x00, 0xFF, 0xF7, 0x3B, 0xF8, 0x05, 0x46, 0xF8, 0x79, 0x3B, 0x49, ++0xBA, 0x88, 0x9E, 0x23, 0x03, 0xFB, 0x09, 0x03, 0x01, 0xEB, 0x83, 0x03, 0x01, 0x2D, 0xD3, 0xF8, 0x7C, 0x41, 0x23, 0x89, ++0x60, 0xD0, 0x9A, 0x42, 0x09, 0xD0, 0xD2, 0x1A, 0x12, 0xF4, 0x7C, 0x6F, 0x4F, 0xF0, 0x00, 0x05, 0xC2, 0xF3, 0x0B, 0x03, ++0x3F, 0xF4, 0x62, 0xAF, 0x99, 0xE7, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, 0x32, 0x30, 0x2E, 0x49, 0x42, 0xF0, 0x20, 0x02, ++0x23, 0xF0, 0xFF, 0x03, 0xC8, 0xF8, 0x60, 0x20, 0xD1, 0xF8, 0xE8, 0x22, 0xA8, 0xF8, 0x32, 0x30, 0x40, 0x46, 0x03, 0x21, ++0x90, 0x47, 0x23, 0x89, 0x01, 0x25, 0x01, 0x20, 0x28, 0x4A, 0xA1, 0x7A, 0x84, 0xF8, 0x20, 0x01, 0x12, 0x69, 0x62, 0x60, ++0x04, 0xEB, 0x81, 0x00, 0x02, 0x69, 0x12, 0xB1, 0xE2, 0x7A, 0x01, 0x3A, 0xE2, 0x72, 0x5A, 0x1C, 0x01, 0x31, 0xC2, 0xF3, ++0x0B, 0x02, 0x01, 0xF0, 0x3F, 0x01, 0x00, 0x23, 0x03, 0x61, 0x20, 0x46, 0x22, 0x81, 0xA1, 0x72, 0xFF, 0xF7, 0x4E, 0xFE, ++0x62, 0xE7, 0x18, 0x4A, 0xA3, 0xF1, 0x3F, 0x01, 0x89, 0xB2, 0xD2, 0xF8, 0xD8, 0x32, 0x20, 0x46, 0x98, 0x47, 0xBB, 0x88, ++0x21, 0x89, 0x5B, 0x1A, 0xC3, 0xF3, 0x0B, 0x03, 0x22, 0xE7, 0x40, 0x2B, 0x7F, 0xF6, 0x4C, 0xAF, 0x13, 0x49, 0x14, 0x48, ++0x40, 0xF2, 0xDB, 0x72, 0xF6, 0xF7, 0x5A, 0xFC, 0xE3, 0x7A, 0x43, 0xE7, 0x0E, 0x4A, 0x0B, 0x4B, 0x11, 0x69, 0xD3, 0xF8, ++0xE0, 0x31, 0x01, 0xF5, 0x43, 0x41, 0x04, 0xF5, 0x88, 0x70, 0x50, 0x31, 0x98, 0x47, 0x3A, 0xE7, 0x9A, 0x42, 0x7F, 0xF4, ++0x03, 0xAF, 0x00, 0x25, 0xB9, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x87, 0xA9, 0xDC, 0xFE, 0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x90, 0xC0, 0x15, 0x00, 0xC3, 0x7A, 0x03, 0xB9, 0x70, 0x47, 0x1A, 0x4B, 0x42, 0x68, 0x1B, 0x69, 0xC3, 0xF5, 0x43, 0x43, ++0x50, 0x33, 0xD3, 0x42, 0x10, 0xB5, 0x04, 0x46, 0x00, 0xD4, 0x10, 0xBD, 0x83, 0x7A, 0x1A, 0x1D, 0x50, 0xF8, 0x22, 0x20, ++0x42, 0xB9, 0x02, 0x89, 0x01, 0x33, 0x01, 0x32, 0x03, 0xF0, 0x3F, 0x03, 0xC2, 0xF3, 0x0B, 0x02, 0x83, 0x72, 0x02, 0x81, ++0x20, 0x46, 0xFF, 0xF7, 0xF1, 0xFD, 0xE3, 0x7A, 0x53, 0xB9, 0x0B, 0x4A, 0x0B, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, ++0x01, 0xF5, 0x43, 0x41, 0x04, 0xF5, 0x88, 0x70, 0x50, 0x31, 0x98, 0x47, 0x07, 0x48, 0x83, 0x6B, 0x00, 0x2B, 0xDC, 0xD0, ++0x04, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, 0x38, 0x31, 0x38, 0x30, 0x18, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x19, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x05, 0x46, ++0x04, 0xD0, 0x03, 0x88, 0x03, 0xF0, 0xEC, 0x03, 0xC4, 0x2B, 0x11, 0xD0, 0x15, 0x4F, 0x05, 0xF1, 0x04, 0x08, 0x07, 0xF5, ++0xA4, 0x56, 0xB9, 0x46, 0x3C, 0x46, 0x94, 0xF8, 0x64, 0x30, 0x1B, 0xB1, 0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x06, 0xD0, ++0x04, 0xF5, 0xA4, 0x64, 0xA6, 0x42, 0xF4, 0xD1, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x06, 0x22, 0x04, 0xF1, 0x5C, 0x01, ++0x40, 0x46, 0x08, 0xF0, 0x45, 0xFE, 0xA4, 0xEB, 0x07, 0x0A, 0x00, 0x28, 0xEE, 0xD1, 0x07, 0x49, 0x07, 0x48, 0xF6, 0xF7, ++0x4D, 0xF9, 0x05, 0xF1, 0x0A, 0x01, 0x09, 0xEB, 0x0A, 0x00, 0xFD, 0xF7, 0x49, 0xFD, 0xE7, 0xE7, 0x00, 0x88, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x20, 0xC1, 0x15, 0x00, 0xA8, 0xC0, 0x15, 0x00, 0x13, 0x4B, 0x93, 0xF8, 0x73, 0x20, 0x12, 0xB1, ++0x11, 0xF4, 0x00, 0x71, 0x00, 0xD0, 0x70, 0x47, 0x10, 0xB4, 0x42, 0x89, 0xB3, 0xF8, 0x6C, 0x40, 0x94, 0x42, 0x02, 0xD0, ++0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xB3, 0xF8, 0x6E, 0x40, 0x82, 0x89, 0x94, 0x42, 0xF7, 0xD1, 0xB3, 0xF8, 0x70, 0x40, ++0xC2, 0x89, 0x94, 0x42, 0xF2, 0xD1, 0x02, 0x88, 0x02, 0xF4, 0xA0, 0x52, 0xB2, 0xF5, 0x80, 0x5F, 0x06, 0xBF, 0x01, 0x22, ++0x83, 0xF8, 0x72, 0x20, 0x83, 0xF8, 0x72, 0x10, 0xE6, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0xF8, 0xB5, 0xBD, 0xF8, ++0x1C, 0x60, 0x06, 0x9D, 0xFF, 0x2A, 0x00, 0xEB, 0x06, 0x07, 0x2E, 0xD0, 0x14, 0x46, 0x82, 0x5D, 0x03, 0x3A, 0x12, 0x2A, ++0x18, 0xD8, 0xDF, 0xE8, 0x02, 0xF0, 0x2B, 0x17, 0x0A, 0x17, 0x30, 0x49, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, ++0x17, 0x17, 0x17, 0x17, 0x5C, 0x00, 0x1B, 0x78, 0x4B, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, ++0x62, 0x30, 0x02, 0x2B, 0x02, 0xD0, 0x7B, 0x78, 0x00, 0x2B, 0x6A, 0xD0, 0x01, 0x26, 0x2B, 0x88, 0xFF, 0x2B, 0x0A, 0xD0, ++0x44, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x57, 0xDB, 0x6F, 0xF0, 0xFF, 0x03, 0x2A, 0x88, 0x13, 0x43, ++0x2B, 0x80, 0x30, 0x46, 0xF8, 0xBD, 0x01, 0x26, 0x30, 0x46, 0xF8, 0xBD, 0x08, 0x23, 0x2B, 0x80, 0x00, 0x26, 0x00, 0x23, ++0xF2, 0xE7, 0x7E, 0x78, 0x00, 0x2E, 0x52, 0xD0, 0x01, 0x2E, 0xE1, 0xD1, 0x38, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x04, 0x23, 0x5E, 0x68, 0x16, 0xF0, 0x02, 0x06, 0xD9, 0xD0, 0xBE, 0x78, 0x16, 0xF0, 0x01, 0x06, 0x5A, 0xD0, 0x20, 0x46, ++0x00, 0x22, 0xFF, 0x21, 0xF9, 0xF7, 0xDC, 0xFC, 0x00, 0x26, 0xCE, 0xE7, 0x89, 0x1B, 0x03, 0x29, 0x2A, 0xDD, 0x1B, 0x78, ++0xFF, 0x2B, 0xC7, 0xD0, 0x29, 0x4A, 0x7E, 0x78, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, ++0x1E, 0x43, 0xBD, 0xD1, 0x06, 0x23, 0x2B, 0x80, 0xD1, 0xE7, 0x7B, 0x78, 0x01, 0x2B, 0x36, 0xD0, 0x02, 0x2B, 0xB5, 0xD1, ++0x22, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x23, 0x5E, 0x68, 0x16, 0xF0, 0x24, 0x06, 0xAD, 0xD0, 0x97, 0xF9, ++0x02, 0x30, 0xB9, 0x78, 0x00, 0x2B, 0x07, 0xDB, 0x0A, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x03, 0x01, 0xF9, 0xF7, 0xAE, 0xFC, ++0x00, 0x26, 0xA0, 0xE7, 0x00, 0x26, 0x9E, 0xE7, 0x17, 0x49, 0x18, 0x48, 0x40, 0xF6, 0x78, 0x12, 0xF6, 0xF7, 0x00, 0xFB, ++0x6F, 0xF0, 0xFF, 0x03, 0xA0, 0xE7, 0x0B, 0x23, 0x2B, 0x80, 0x01, 0x26, 0xA7, 0xE7, 0x10, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x04, 0x23, 0x5B, 0x68, 0x9B, 0x07, 0x89, 0xD5, 0xB9, 0x78, 0x01, 0x29, 0x86, 0xD8, 0x20, 0x46, 0xFF, 0x22, ++0xF9, 0xF7, 0x8E, 0xFC, 0x81, 0xE7, 0x07, 0xF1, 0x0A, 0x01, 0xB8, 0x1C, 0xD2, 0xF7, 0xB6, 0xFE, 0x00, 0x26, 0x7A, 0xE7, ++0xFF, 0x22, 0x20, 0x46, 0x11, 0x46, 0xF9, 0xF7, 0x81, 0xFC, 0x74, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xBC, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x89, 0xB0, 0x1F, 0x46, ++0x10, 0x9E, 0x34, 0x78, 0xFF, 0x2C, 0x47, 0xD0, 0x69, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x55, 0x00, 0xF0, ++0xFC, 0x04, 0x80, 0x2C, 0x95, 0xF8, 0x62, 0x80, 0x46, 0xD0, 0x0F, 0xD8, 0x40, 0x2C, 0x6B, 0xD0, 0x2C, 0xD9, 0x50, 0x2C, ++0x4F, 0xF0, 0x01, 0x04, 0x04, 0xD1, 0x13, 0x9A, 0x14, 0x70, 0x12, 0x9A, 0x04, 0x23, 0x13, 0x80, 0x20, 0x46, 0x09, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0xC0, 0x2C, 0x21, 0xD0, 0x10, 0xD9, 0xD0, 0x2C, 0x15, 0xD1, 0x13, 0x9B, 0x11, 0x98, 0xCD, 0xE9, ++0x01, 0x23, 0x12, 0x9B, 0x00, 0x93, 0x3A, 0x46, 0x33, 0x46, 0xFF, 0xF7, 0x11, 0xFF, 0x04, 0x46, 0x20, 0x46, 0x09, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0xA0, 0x2C, 0x0D, 0xD0, 0xB0, 0x2C, 0x02, 0xD1, 0xFC, 0xF7, 0xBA, 0xFA, 0x40, 0xB1, 0x01, 0x24, ++0x20, 0x46, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x00, 0xF0, 0xDC, 0x00, 0x10, 0x28, 0xF6, 0xD1, 0xB8, 0xF1, 0x00, 0x0F, ++0xF3, 0xD1, 0x12, 0x9A, 0x06, 0x23, 0x13, 0x80, 0x01, 0x24, 0xCF, 0xE7, 0x00, 0xF0, 0xFC, 0x00, 0xB0, 0x28, 0x72, 0xD0, ++0x28, 0xD8, 0x40, 0x28, 0x2A, 0xD0, 0x80, 0x28, 0xE5, 0xD1, 0x00, 0x25, 0x04, 0x20, 0x05, 0x91, 0xF4, 0xF7, 0x34, 0xFC, ++0x01, 0x28, 0x05, 0x99, 0x0E, 0xD1, 0x13, 0x9A, 0x3D, 0x4B, 0x10, 0x70, 0x12, 0x98, 0x1B, 0x68, 0x3A, 0x4D, 0x04, 0x22, ++0x02, 0x80, 0x93, 0xF8, 0x6E, 0x41, 0x34, 0x70, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x55, 0xFF, 0x2F, 0xCC, 0xD0, ++0x95, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xC8, 0xD0, 0x34, 0x4B, 0x30, 0x78, 0xD3, 0xF8, 0x54, 0x31, 0x11, 0x9A, 0x98, 0x47, ++0x01, 0x24, 0xA1, 0xE7, 0xD0, 0x28, 0xA8, 0xD0, 0x01, 0x24, 0xBD, 0xE7, 0x2F, 0x4B, 0x9A, 0x7C, 0x00, 0x2A, 0xB8, 0xD0, ++0x2E, 0x4A, 0x12, 0x68, 0x12, 0x78, 0x01, 0x3A, 0x01, 0x2A, 0xB2, 0xD8, 0x9D, 0x68, 0x00, 0x2D, 0xAF, 0xD0, 0x18, 0x39, ++0x2A, 0x4F, 0x1F, 0xFA, 0x81, 0xF8, 0x01, 0x24, 0x02, 0xE0, 0x2D, 0x68, 0x00, 0x2D, 0x87, 0xD0, 0x95, 0xF8, 0x62, 0x30, ++0x02, 0x2B, 0xF8, 0xD1, 0x95, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF4, 0xD0, 0x95, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0xF0, 0xD1, ++0x11, 0x9B, 0xB7, 0xF8, 0x00, 0x90, 0x03, 0xF1, 0x18, 0x00, 0x0D, 0xF1, 0x1E, 0x02, 0x41, 0x46, 0xF4, 0xF7, 0xFA, 0xFF, ++0xA9, 0xF1, 0x24, 0x01, 0x06, 0x46, 0x89, 0xB2, 0x0D, 0xF1, 0x1F, 0x02, 0x19, 0x48, 0xF4, 0xF7, 0xF1, 0xFF, 0x9D, 0xF8, ++0x1E, 0x30, 0x18, 0x49, 0x02, 0x36, 0x81, 0x46, 0x07, 0x22, 0x30, 0x46, 0x53, 0xB9, 0x11, 0x9B, 0x28, 0x46, 0x03, 0xF1, ++0x0A, 0x01, 0xE1, 0xF7, 0xED, 0xFE, 0x00, 0x24, 0xCD, 0xE7, 0xFC, 0xF7, 0x2F, 0xFA, 0x74, 0xE7, 0x08, 0xF0, 0x7C, 0xFC, ++0x00, 0x28, 0xC6, 0xD0, 0x9D, 0xF8, 0x1F, 0x30, 0x9D, 0xF8, 0x1E, 0x20, 0x9A, 0x42, 0xC0, 0xD1, 0x09, 0xF1, 0x02, 0x01, ++0x30, 0x46, 0x08, 0xF0, 0x6F, 0xFC, 0x00, 0x28, 0xE3, 0xD0, 0xB8, 0xE7, 0x18, 0x88, 0x17, 0x00, 0xA8, 0xBA, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x14, 0x2C, 0x17, 0x00, 0x38, 0x2A, 0x17, 0x00, ++0x54, 0xBF, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xC6, 0x69, 0x8D, 0xB0, 0xD6, 0xF8, 0x08, 0x90, 0x01, 0x23, 0x8D, 0xF8, ++0x24, 0x30, 0x04, 0x46, 0xB9, 0xF8, 0x00, 0x00, 0x10, 0xF4, 0x80, 0x60, 0x40, 0xF0, 0x8B, 0x80, 0xB9, 0xF8, 0x16, 0x70, ++0x17, 0xF0, 0x0F, 0x07, 0x00, 0xF0, 0x89, 0x80, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB9, 0xF8, 0x00, 0x30, 0x98, 0xF8, ++0x08, 0x20, 0x04, 0x92, 0xDF, 0xF8, 0x08, 0xE2, 0xB4, 0xF8, 0x30, 0xA0, 0xBD, 0xF8, 0x10, 0x10, 0xAD, 0xF8, 0x16, 0x30, ++0x4F, 0xF0, 0xFF, 0x0C, 0x18, 0x46, 0xAD, 0xF8, 0x26, 0xC0, 0xB3, 0x68, 0xDE, 0xF8, 0xE0, 0x92, 0x07, 0x93, 0x0D, 0xF1, ++0x25, 0x0C, 0x01, 0x93, 0xCD, 0xF8, 0x0C, 0xC0, 0x72, 0x4B, 0x06, 0x91, 0x0D, 0xF1, 0x26, 0x0C, 0x0A, 0x46, 0x00, 0x93, ++0x51, 0x46, 0x8D, 0xF8, 0x25, 0xB0, 0x80, 0xB2, 0xCD, 0xF8, 0x08, 0xC0, 0x2B, 0x46, 0xC8, 0x47, 0xBD, 0xF8, 0x26, 0x10, ++0xFF, 0x29, 0x00, 0xF0, 0x90, 0x80, 0x0A, 0xF1, 0x0C, 0x03, 0x9B, 0xB2, 0x0A, 0x22, 0x4F, 0xF4, 0x20, 0x50, 0xF4, 0xF7, ++0xB5, 0xF8, 0x59, 0x46, 0x81, 0x46, 0x0A, 0xA8, 0xD2, 0xF7, 0xFA, 0xFC, 0x9D, 0xF8, 0x25, 0x30, 0xD3, 0x46, 0x63, 0xB9, ++0x61, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xAE, 0x80, 0x04, 0x9B, 0x06, 0x9F, 0xAA, 0xEB, ++0x03, 0x0B, 0x1F, 0xFA, 0x8B, 0xFA, 0x4B, 0x46, 0x3A, 0x46, 0x51, 0x46, 0x23, 0xF8, 0x0C, 0xAB, 0x30, 0x46, 0xE6, 0xF7, ++0x35, 0xFD, 0x98, 0xF8, 0x0A, 0x30, 0x89, 0xF8, 0x08, 0x30, 0xBD, 0xF8, 0x16, 0x30, 0x89, 0xF8, 0x07, 0x50, 0xA9, 0xF8, ++0x02, 0x30, 0x94, 0xF9, 0x41, 0x50, 0xD2, 0xF7, 0x75, 0xFD, 0x0A, 0x9B, 0x89, 0xF8, 0x06, 0x30, 0x1A, 0x0C, 0x89, 0xF8, ++0x09, 0x50, 0xA9, 0xF8, 0x04, 0x20, 0x48, 0x46, 0xF4, 0xF7, 0xAE, 0xF8, 0xBD, 0xF8, 0x26, 0x30, 0x04, 0x2B, 0x10, 0xD1, ++0xE1, 0x6B, 0xB9, 0xF8, 0x04, 0x30, 0x62, 0x6B, 0x07, 0x98, 0xC1, 0xF3, 0x03, 0x11, 0x02, 0x91, 0x99, 0xF9, 0x09, 0x10, ++0x01, 0x91, 0x99, 0xF8, 0x06, 0x10, 0x00, 0x91, 0x59, 0x46, 0x07, 0xF0, 0x15, 0xFB, 0x00, 0x20, 0x0D, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x0D, 0x46, 0xD2, 0xF7, 0x4E, 0xFD, 0xFF, 0x2D, 0x38, 0xD0, 0x3C, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x31, 0xD0, ++0x99, 0xF8, 0x04, 0x30, 0xDF, 0xF8, 0xEC, 0x80, 0xDA, 0x07, 0x10, 0xD4, 0x98, 0xF8, 0x0A, 0x00, 0x37, 0x4A, 0xB9, 0xF8, ++0x04, 0x10, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0xF3, 0x5C, 0x33, 0x98, 0x18, 0x9B, 0x5A, 0x8B, 0x42, 0x45, 0xD0, ++0xFF, 0x23, 0x88, 0xF8, 0x0A, 0x30, 0x22, 0x8E, 0x30, 0x48, 0x09, 0xAB, 0x49, 0x46, 0x02, 0xF0, 0x81, 0xFB, 0x83, 0x46, ++0x00, 0x28, 0x3F, 0xF4, 0x50, 0xAF, 0x9D, 0xF8, 0x24, 0x00, 0x00, 0x28, 0x3F, 0xF4, 0x48, 0xAF, 0x2A, 0x4B, 0x20, 0x46, ++0xD3, 0xF8, 0xE4, 0x32, 0x03, 0x21, 0x98, 0x47, 0x9D, 0xF8, 0x24, 0x00, 0x3E, 0xE7, 0x8D, 0xF8, 0x24, 0x00, 0xF0, 0xE7, ++0xDF, 0xF8, 0x8C, 0x80, 0xE1, 0xE7, 0x63, 0x6D, 0x13, 0xF4, 0xC0, 0x6F, 0x1E, 0xD1, 0x1E, 0x4B, 0x9B, 0x68, 0x9B, 0xB3, ++0xB9, 0xF8, 0x04, 0x10, 0x01, 0xE0, 0x1B, 0x68, 0xB3, 0xB1, 0xB3, 0xF8, 0x5C, 0x20, 0x8A, 0x42, 0xF9, 0xD1, 0xB3, 0xF8, ++0x5E, 0x00, 0xB9, 0xF8, 0x06, 0x20, 0x90, 0x42, 0xF3, 0xD1, 0xB3, 0xF8, 0x60, 0x00, 0xB9, 0xF8, 0x08, 0x20, 0x90, 0x42, ++0xED, 0xD1, 0x93, 0xF8, 0x63, 0x30, 0xDF, 0xF8, 0x4C, 0x80, 0x88, 0xF8, 0x0A, 0x30, 0xBE, 0xE7, 0xFF, 0x23, 0xF8, 0xE7, ++0x42, 0x88, 0xB9, 0xF8, 0x06, 0x30, 0x9A, 0x42, 0xB4, 0xD1, 0x82, 0x88, 0xB9, 0xF8, 0x08, 0x30, 0x9A, 0x42, 0xAF, 0xD1, ++0xB1, 0xE7, 0x04, 0x9A, 0x93, 0x07, 0x3F, 0xF4, 0x4E, 0xAF, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0x97, 0x22, 0xF6, 0xF7, ++0xE7, 0xF8, 0x46, 0xE7, 0x2B, 0x46, 0xE0, 0xE7, 0xBA, 0xDE, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD0, 0xC0, 0x15, 0x00, ++0x1D, 0x48, 0x70, 0xB5, 0x00, 0xF1, 0x10, 0x06, 0xF4, 0xF7, 0x5E, 0xFC, 0x30, 0x46, 0x1B, 0x4C, 0xF4, 0xF7, 0x5A, 0xFC, ++0x04, 0xF5, 0x92, 0x55, 0x21, 0x46, 0x30, 0x46, 0x04, 0xF5, 0x92, 0x74, 0xF4, 0xF7, 0x56, 0xFC, 0xAC, 0x42, 0xF7, 0xD1, ++0x15, 0x48, 0xF4, 0xF7, 0x4D, 0xFC, 0x15, 0x48, 0xF4, 0xF7, 0x4A, 0xFC, 0x14, 0x49, 0x12, 0x48, 0xF4, 0xF7, 0x4A, 0xFC, ++0x13, 0x49, 0x10, 0x48, 0xF4, 0xF7, 0x46, 0xFC, 0x12, 0x49, 0x0E, 0x48, 0xF4, 0xF7, 0x42, 0xFC, 0x11, 0x4A, 0x12, 0x4B, ++0x12, 0x48, 0x4F, 0xF6, 0xFF, 0x71, 0xA2, 0xF8, 0x66, 0x10, 0x03, 0xF5, 0x70, 0x51, 0x00, 0x22, 0x03, 0xF8, 0x34, 0x2C, ++0x1A, 0x81, 0x43, 0xE9, 0x10, 0x03, 0x43, 0xF8, 0x30, 0x3C, 0x50, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0x70, 0xBD, 0x00, 0xBF, ++0xE8, 0xDE, 0x17, 0x00, 0x70, 0xCC, 0x17, 0x00, 0x00, 0xDF, 0x17, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x28, 0xDF, 0x17, 0x00, ++0x6C, 0xDF, 0x17, 0x00, 0xB0, 0xDF, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x24, 0x64, 0x18, 0x00, 0x75, 0xD2, 0x14, 0x00, ++0x70, 0xB5, 0x90, 0xF9, 0x00, 0x30, 0x82, 0xB0, 0x00, 0x2B, 0x01, 0xF0, 0x78, 0x02, 0x05, 0x46, 0xB8, 0xBF, 0x1A, 0x23, ++0x4F, 0xF0, 0x00, 0x00, 0xA8, 0xBF, 0x18, 0x23, 0x08, 0x2A, 0xAD, 0xF8, 0x06, 0x00, 0x19, 0xD0, 0x01, 0xF0, 0x7C, 0x01, ++0x04, 0x29, 0x1F, 0xD0, 0x06, 0x33, 0xDC, 0xB2, 0x2E, 0x19, 0x31, 0x46, 0x02, 0x22, 0x0D, 0xF1, 0x06, 0x00, 0x08, 0xF0, ++0xF3, 0xFA, 0x28, 0x79, 0x10, 0xF0, 0x01, 0x00, 0x0B, 0xD0, 0xBD, 0xF8, 0x06, 0x00, 0xA0, 0xF5, 0xC1, 0x60, 0xB0, 0xFA, ++0x80, 0xF0, 0x40, 0x09, 0x02, 0xB0, 0x70, 0xBD, 0x08, 0x33, 0xDB, 0xB2, 0xE6, 0xE7, 0xBD, 0xF8, 0x06, 0x30, 0x08, 0x2B, ++0x04, 0xD0, 0x01, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x04, 0x33, 0xDD, 0xE7, 0xF3, 0x7A, 0x02, 0x2B, 0xEE, 0xD0, 0x11, 0x2B, ++0xF5, 0xD1, 0xB2, 0x78, 0xA3, 0x1C, 0x02, 0xF0, 0x0F, 0x04, 0x03, 0xEB, 0x84, 0x04, 0x2C, 0x44, 0x14, 0xF8, 0x04, 0x3C, ++0xEF, 0x2B, 0xEA, 0xD1, 0x14, 0xF8, 0x03, 0x3C, 0xFF, 0x2B, 0xE6, 0xD1, 0x14, 0xF8, 0x02, 0x3C, 0xFF, 0x2B, 0xE2, 0xD1, ++0x14, 0xF8, 0x01, 0x0C, 0xFA, 0x38, 0x18, 0xBF, 0x01, 0x20, 0xD3, 0xE7, 0x70, 0xB5, 0x90, 0xF9, 0x00, 0x30, 0x82, 0xB0, ++0x00, 0x2B, 0x01, 0xF0, 0x78, 0x05, 0x4F, 0xF0, 0x00, 0x06, 0xB4, 0xBF, 0x1A, 0x23, 0x18, 0x23, 0x08, 0x2D, 0x14, 0x46, ++0xAD, 0xF8, 0x06, 0x60, 0x13, 0xD0, 0x01, 0xF0, 0x7C, 0x01, 0x04, 0x29, 0x12, 0xD0, 0x99, 0x1D, 0x50, 0xFA, 0x81, 0xF1, ++0x02, 0x22, 0x0D, 0xF1, 0x06, 0x00, 0x08, 0xF0, 0x9F, 0xFA, 0xBD, 0xF8, 0x06, 0x10, 0x48, 0xF6, 0x88, 0x63, 0x99, 0x42, ++0x06, 0xD0, 0x02, 0xB0, 0x70, 0xBD, 0x08, 0x33, 0xDB, 0xB2, 0xEC, 0xE7, 0x04, 0x33, 0xEA, 0xE7, 0x02, 0x48, 0x22, 0x46, ++0xF5, 0xF7, 0x6E, 0xFD, 0x02, 0xB0, 0x70, 0xBD, 0xEC, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x45, 0x6D, 0x2D, 0xED, ++0x02, 0x8B, 0xAF, 0x04, 0x87, 0xB0, 0x04, 0x46, 0x1F, 0xD4, 0xC1, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9E, 0x07, 0x03, 0xD5, ++0x05, 0xF0, 0x3C, 0x03, 0x3C, 0x2B, 0x16, 0xD0, 0xBD, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x71, 0xD0, 0xBC, 0x4E, 0xBD, 0x4D, ++0xB3, 0x72, 0x20, 0x46, 0xD5, 0xF8, 0xE4, 0x32, 0x80, 0x21, 0x98, 0x47, 0x01, 0x27, 0xD5, 0xF8, 0x38, 0x31, 0xB9, 0x48, ++0x98, 0x47, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0xD4, 0xF8, 0x1C, 0xA0, 0xB2, 0x4E, ++0xDA, 0xF8, 0x08, 0x80, 0x00, 0x23, 0xB8, 0xF8, 0x00, 0x90, 0x23, 0x66, 0x40, 0x46, 0xFF, 0x23, 0x73, 0x72, 0xB3, 0x72, ++0xFE, 0xF7, 0xE6, 0xFD, 0xA8, 0x01, 0x50, 0xD5, 0xC5, 0xF3, 0xC9, 0x37, 0xDF, 0xF8, 0xBC, 0xB2, 0x10, 0x3F, 0xFF, 0xB2, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x93, 0xF8, 0x25, 0x20, 0x00, 0x2A, 0x39, 0xD0, 0x93, 0xF8, 0x22, 0x10, ++0xA5, 0x48, 0xD3, 0xF8, 0xB0, 0x30, 0x77, 0x72, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x02, 0xB5, 0x61, 0x92, 0xF8, ++0x62, 0x20, 0xB1, 0x72, 0x02, 0x2A, 0x00, 0x93, 0x52, 0xD0, 0x09, 0xF4, 0x40, 0x73, 0xB3, 0xF5, 0x40, 0x7F, 0x03, 0xD1, ++0x23, 0x6E, 0x43, 0xF0, 0x04, 0x03, 0x23, 0x66, 0x33, 0x88, 0x5B, 0x04, 0x00, 0xF1, 0x90, 0x80, 0x98, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x01, 0x2B, 0x09, 0xF0, 0x0C, 0x03, 0x00, 0xF0, 0x90, 0x80, 0x08, 0x2B, 0x00, 0xF0, 0x97, 0x80, 0x4F, 0xF4, ++0x1E, 0x72, 0x02, 0xFB, 0x07, 0xB2, 0x92, 0xF8, 0x5D, 0x22, 0x01, 0x2A, 0x40, 0xF2, 0xE7, 0x80, 0x04, 0x2B, 0x00, 0xF0, ++0xFA, 0x80, 0x08, 0x2B, 0x00, 0xF0, 0x97, 0x80, 0x00, 0x2B, 0x33, 0xD0, 0x85, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x01, 0xD0, ++0x85, 0x4D, 0x8F, 0xE7, 0x84, 0x4D, 0x00, 0x27, 0x93, 0xE7, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x9D, 0xFB, 0x19, 0xF0, ++0x0C, 0x0F, 0x0B, 0xD1, 0xFF, 0xF7, 0xDA, 0xF8, 0x00, 0x28, 0xEB, 0xD0, 0x33, 0x88, 0x59, 0x04, 0x55, 0xD5, 0x05, 0xF0, ++0x7C, 0x03, 0x04, 0x2B, 0x4B, 0xD0, 0x40, 0x46, 0x21, 0x46, 0xFF, 0xF7, 0x4D, 0xFB, 0x78, 0x4D, 0x07, 0x46, 0x75, 0x4B, ++0x1B, 0x7C, 0xFF, 0x2B, 0x3F, 0xF4, 0x77, 0xAF, 0x00, 0x2F, 0x7F, 0xF4, 0x74, 0xAF, 0x6B, 0xE7, 0x96, 0xF8, 0x24, 0x30, ++0xDA, 0x07, 0xA8, 0xD4, 0x06, 0xF1, 0x24, 0x00, 0xF2, 0xF7, 0xB8, 0xFE, 0xF0, 0x72, 0xA2, 0xE7, 0x19, 0xF4, 0x00, 0x6F, ++0x00, 0xF0, 0xCF, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x72, 0x88, 0xB3, 0xF8, 0xE8, 0x31, 0x93, 0x42, ++0xBE, 0xD0, 0x96, 0xF8, 0x30, 0x10, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB7, 0x8D, 0x07, 0xA7, 0xF8, 0xE8, 0x21, ++0x0A, 0xD5, 0x35, 0x6A, 0xD6, 0xE9, 0x04, 0x01, 0xD5, 0xE9, 0x10, 0x23, 0x8B, 0x42, 0x08, 0xBF, 0x82, 0x42, 0xAB, 0xD2, ++0xC5, 0xE9, 0x10, 0x01, 0x5F, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD1, 0x98, 0xF8, 0x00, 0x30, 0x80, 0x2B, ++0x00, 0xF0, 0xCF, 0x80, 0x71, 0x7A, 0x57, 0x4D, 0x20, 0x46, 0xFF, 0xF7, 0x17, 0xFD, 0x07, 0x46, 0xB9, 0xE7, 0x29, 0x46, ++0x40, 0x46, 0xFE, 0xF7, 0x39, 0xFB, 0x00, 0x28, 0xAD, 0xD0, 0xFF, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x0B, 0xFD, 0x4F, 0x4D, ++0x07, 0x46, 0xAC, 0xE7, 0xB1, 0x69, 0x40, 0x46, 0xFE, 0xF7, 0x2C, 0xFB, 0x00, 0x28, 0x7F, 0xF4, 0x69, 0xAF, 0x83, 0xE7, ++0x08, 0x2B, 0x7F, 0xF4, 0x70, 0xAF, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x73, 0xFE, 0x00, 0x28, 0x3F, 0xF4, 0x7A, 0xAF, ++0x3B, 0x46, 0x22, 0x8E, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xC0, 0xFE, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, ++0x93, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x40, 0xF2, 0x87, 0x80, 0x41, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x73, 0xB1, 0xB3, 0x7A, ++0x3C, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x13, 0x93, 0xF8, 0x62, 0x20, 0x2A, 0xB9, 0xD3, 0xF8, 0x90, 0x21, ++0x92, 0x78, 0x01, 0x2A, 0x00, 0xF0, 0x8D, 0x80, 0x19, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x7F, 0xF4, 0x53, 0xAF, 0x09, 0xF0, ++0x80, 0x03, 0x00, 0x2B, 0x14, 0xBF, 0x4F, 0xF0, 0x01, 0x08, 0x4F, 0xF0, 0x00, 0x08, 0x71, 0xD0, 0x96, 0xF8, 0x30, 0x30, ++0x1A, 0x07, 0x40, 0xF1, 0x9A, 0x80, 0xF2, 0x79, 0x4F, 0xF4, 0x9E, 0x73, 0xF5, 0x32, 0x03, 0xFB, 0x07, 0x23, 0x0B, 0xEB, ++0x43, 0x03, 0x19, 0xF4, 0x00, 0x6F, 0x72, 0x88, 0x03, 0xD0, 0x19, 0x88, 0x91, 0x42, 0x3F, 0xF4, 0x35, 0xAF, 0x1F, 0x49, ++0x1A, 0x80, 0x0B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x04, 0xD5, 0x05, 0xF0, 0x3C, 0x05, 0x3C, 0x2D, 0x00, 0xF0, 0x8E, 0x80, ++0x1C, 0x4D, 0x39, 0x46, 0xD5, 0xF8, 0xC4, 0x32, 0x42, 0x46, 0x20, 0x46, 0x98, 0x47, 0x07, 0x46, 0x41, 0xE7, 0x00, 0x9A, ++0x00, 0x2A, 0x3F, 0xF4, 0x15, 0xAF, 0x92, 0xF8, 0x60, 0x20, 0x01, 0x3A, 0x01, 0x2A, 0x3F, 0xF6, 0x0F, 0xAF, 0x19, 0xF4, ++0x80, 0x4F, 0x3F, 0xF4, 0x0B, 0xAF, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x07, 0xB2, 0x02, 0x21, 0x82, 0xF8, 0x5D, 0x12, ++0x02, 0xE7, 0x09, 0xF0, 0xFC, 0x09, 0xB9, 0xF1, 0x84, 0x0F, 0x7F, 0xF4, 0x05, 0xAF, 0x0A, 0x4D, 0x41, 0x46, 0xD5, 0xF8, ++0xD0, 0x32, 0x38, 0x46, 0x98, 0x47, 0x05, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x7F, 0xF4, 0x90, 0xAE, 0xFF, 0xE6, 0x72, 0x88, ++0x37, 0xE7, 0x00, 0xBF, 0x34, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xE8, 0xDE, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0x75, 0xAF, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, 0x01, 0x2B, 0x3F, 0xF6, 0x6F, 0xAF, ++0x08, 0x23, 0xC0, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x03, 0xF5, 0xF4, 0x73, 0x93, 0xE7, 0x98, 0xF8, ++0x01, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x2C, 0xAF, 0xCA, 0xE6, 0xD3, 0xF8, 0xCC, 0x21, 0x12, 0xF0, 0x0C, 0x0F, 0x3F, 0xF4, ++0x6D, 0xAF, 0x98, 0xF8, 0x04, 0x20, 0xD0, 0x07, 0x3F, 0xF5, 0x68, 0xAF, 0xE2, 0x6B, 0x12, 0xF0, 0x0C, 0x0F, 0x3F, 0xF4, ++0x63, 0xAF, 0xD3, 0xF8, 0x90, 0x20, 0x01, 0x32, 0xC3, 0xF8, 0x90, 0x20, 0x98, 0xF8, 0x01, 0x20, 0x11, 0x07, 0x7F, 0xF5, ++0x59, 0xAF, 0xD3, 0xF8, 0x94, 0x20, 0x01, 0x32, 0xC3, 0xF8, 0x94, 0x20, 0x52, 0xE7, 0xF1, 0x79, 0x38, 0x46, 0xE9, 0xF7, ++0x33, 0xFB, 0x00, 0x28, 0x3F, 0xF4, 0x5F, 0xAF, 0x61, 0x4D, 0x39, 0x46, 0xD5, 0xF8, 0xD4, 0x32, 0x20, 0x46, 0x98, 0x47, ++0x07, 0x46, 0xBC, 0xE6, 0x33, 0x6A, 0x01, 0x93, 0x93, 0xF8, 0x60, 0x10, 0x01, 0x29, 0x03, 0xF1, 0x64, 0x09, 0x64, 0xD0, ++0x00, 0x29, 0x40, 0xF0, 0x97, 0x80, 0x08, 0xF1, 0x0E, 0x03, 0x5B, 0x00, 0xDA, 0xE9, 0x01, 0x25, 0x58, 0x19, 0x08, 0xEE, ++0x10, 0x0A, 0x00, 0x2A, 0x52, 0xD0, 0xDA, 0xF8, 0x0C, 0x20, 0x20, 0x8E, 0x01, 0x32, 0x52, 0x1B, 0x04, 0x30, 0xD2, 0x1A, ++0xC0, 0x1A, 0x93, 0xB2, 0x82, 0xB2, 0x9A, 0x42, 0x00, 0x92, 0x28, 0xBF, 0x1A, 0x46, 0x15, 0x46, 0x01, 0x29, 0x2F, 0xD0, ++0x00, 0x29, 0x50, 0xD0, 0x03, 0x29, 0x66, 0xD0, 0x18, 0xEE, 0x10, 0x0A, 0x29, 0x46, 0xF3, 0xF7, 0x2F, 0xFB, 0x4F, 0xF0, ++0xFF, 0x33, 0x18, 0xEE, 0x10, 0x0A, 0x03, 0x22, 0x29, 0x46, 0xD6, 0xF7, 0x29, 0xFF, 0xDA, 0xF8, 0x04, 0x30, 0x23, 0xB1, ++0x00, 0x9A, 0x55, 0x1B, 0xAD, 0xB2, 0x00, 0x2D, 0x67, 0xD1, 0x01, 0x9B, 0x93, 0xF8, 0x60, 0x30, 0x13, 0xB1, 0x03, 0x2B, ++0x7F, 0xF4, 0x2C, 0xAF, 0x03, 0x20, 0xD6, 0xF7, 0x4F, 0xFF, 0x3A, 0x4B, 0x98, 0x42, 0x01, 0x46, 0x3F, 0xD1, 0x63, 0x6D, ++0x23, 0xF0, 0x7C, 0x03, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xF0, 0x04, 0x03, 0x63, 0x65, 0x1B, 0xE7, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x07, 0xB2, 0x02, 0xAB, 0x32, 0x49, 0x26, 0x32, 0x48, 0x46, 0xF3, 0xF7, 0xDA, 0xF8, 0x10, 0x21, 0x02, 0xA8, ++0xF3, 0xF7, 0x9A, 0xFA, 0x01, 0x9B, 0x93, 0xF8, 0x60, 0x10, 0xBD, 0xE7, 0x22, 0x8E, 0x04, 0x32, 0xD3, 0x1A, 0x9D, 0xB2, ++0xB6, 0xE7, 0xD6, 0xE9, 0x04, 0x53, 0x28, 0x48, 0x2A, 0x0C, 0x42, 0xEA, 0x03, 0x42, 0x08, 0xF1, 0x10, 0x03, 0x02, 0x60, ++0x85, 0x80, 0x5B, 0x00, 0x94, 0xE7, 0x32, 0x8A, 0x73, 0x8A, 0xAD, 0xF8, 0x08, 0x20, 0x49, 0x46, 0x05, 0x22, 0x0D, 0xF1, ++0x0B, 0x00, 0x8D, 0xF8, 0x0A, 0x30, 0x08, 0xF0, 0x1F, 0xF8, 0x08, 0x21, 0x02, 0xA8, 0xF3, 0xF7, 0x75, 0xFA, 0x01, 0x9B, ++0x93, 0xF8, 0x60, 0x10, 0x9A, 0xE7, 0x1A, 0x48, 0xF5, 0xF7, 0xF4, 0xFA, 0x0A, 0xE6, 0x32, 0x8A, 0x73, 0x8A, 0xAD, 0xF8, ++0x08, 0x20, 0x49, 0x46, 0x0D, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x8D, 0xF8, 0x0A, 0x30, 0x08, 0xF0, 0x07, 0xF8, 0x02, 0xA8, ++0x10, 0x21, 0xF3, 0xF7, 0x5D, 0xFA, 0x87, 0xE7, 0x03, 0x29, 0x3F, 0xF4, 0x66, 0xAF, 0x00, 0x23, 0x66, 0xE7, 0xD3, 0xF8, ++0x08, 0x90, 0x29, 0x46, 0x48, 0x46, 0xF3, 0xF7, 0xB1, 0xFA, 0x03, 0x20, 0xD6, 0xF7, 0xE8, 0xFE, 0x20, 0x21, 0xC0, 0x43, ++0xF3, 0xF7, 0x64, 0xF8, 0x29, 0x46, 0x03, 0x46, 0x03, 0x22, 0x48, 0x46, 0xD6, 0xF7, 0xA6, 0xFE, 0x83, 0xE7, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x1C, 0xDF, 0x44, 0x21, 0x88, 0x34, 0x17, 0x00, 0x00, 0xC1, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x00, 0xEB, 0x81, 0x04, 0xD4, 0xF8, 0x7C, 0x61, 0x16, 0xB1, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x15, 0x48, 0x0D, 0x46, ++0x17, 0x46, 0xF4, 0xF7, 0x1B, 0xF9, 0x80, 0x46, 0x00, 0x28, 0xF4, 0xD0, 0x31, 0x46, 0x4F, 0xF4, 0x92, 0x72, 0xD1, 0xF7, ++0x3B, 0xF8, 0x07, 0xF0, 0x3F, 0x02, 0x0F, 0x4B, 0x88, 0xF8, 0x0C, 0x50, 0x88, 0xF8, 0x0A, 0x20, 0x19, 0x69, 0x0D, 0x4B, ++0xC8, 0xF8, 0x04, 0x10, 0xD3, 0xF8, 0xDC, 0x22, 0xA8, 0xF8, 0x08, 0x70, 0xC8, 0xE9, 0x45, 0x28, 0x01, 0xF5, 0x43, 0x41, ++0xC4, 0xF8, 0x7C, 0x81, 0x08, 0xF5, 0x88, 0x70, 0xD3, 0xF8, 0xE0, 0x31, 0x50, 0x31, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0xF8, 0xDE, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0xEB, 0x81, 0x04, 0x00, 0x2B, 0xD4, 0xF8, 0x7C, 0x51, 0x0D, 0xDB, 0x0C, 0x4B, ++0x05, 0xF5, 0x88, 0x70, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x0A, 0x48, 0x29, 0x46, 0xF4, 0xF7, 0x95, 0xF8, 0x00, 0x23, ++0xC4, 0xF8, 0x7C, 0x31, 0x38, 0xBD, 0x00, 0x2D, 0xEF, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF6, 0x7F, 0x52, 0xF5, 0xF7, ++0xDD, 0xFC, 0xE8, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xDE, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x10, 0xC1, 0x15, 0x00, 0x08, 0x4B, 0x93, 0xF8, 0x73, 0x20, 0x62, 0xB9, 0x02, 0x88, 0xA3, 0xF8, 0x6C, 0x20, 0x42, 0x88, ++0xA3, 0xF8, 0x6E, 0x20, 0x82, 0x88, 0xA3, 0xF8, 0x70, 0x20, 0x4F, 0xF4, 0x80, 0x72, 0xA3, 0xF8, 0x72, 0x20, 0x70, 0x47, ++0xB0, 0xDE, 0x17, 0x00, 0x03, 0x4B, 0x00, 0x22, 0x93, 0xF8, 0x72, 0x00, 0xA3, 0xF8, 0x72, 0x20, 0x70, 0x47, 0x00, 0xBF, ++0xB0, 0xDE, 0x17, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0xF3, 0xF7, 0xDD, 0xFF, 0x03, 0x4B, 0x03, 0x48, 0xD3, 0xF8, ++0x38, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0x06, 0x4B, 0x07, 0x4A, ++0x93, 0xF8, 0x44, 0x30, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x03, 0x13, 0xB3, 0xF8, 0x4C, 0x00, 0xB0, 0xFA, 0x80, 0xF0, ++0x40, 0x09, 0x70, 0x47, 0xB0, 0xDE, 0x17, 0x00, 0xE0, 0x63, 0x18, 0x00, 0xF8, 0xB5, 0x55, 0x4F, 0x46, 0x7F, 0x05, 0x7F, ++0x54, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x06, 0x74, 0xD4, 0xE9, 0x2C, 0xC3, 0x4F, 0xF4, 0xA4, 0x6E, 0x0E, 0xFB, ++0x05, 0x25, 0x1B, 0x68, 0xD5, 0xF8, 0xA8, 0xE4, 0x00, 0x22, 0x0A, 0x60, 0x4B, 0xB3, 0xBE, 0xF1, 0x00, 0x0F, 0x26, 0xD0, ++0xD5, 0xF8, 0xB0, 0x54, 0xAA, 0x07, 0x06, 0xD5, 0x05, 0x8B, 0xB4, 0xF8, 0x34, 0xE0, 0x6C, 0xBA, 0xA4, 0xB2, 0xA6, 0x45, ++0x1B, 0xD0, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0x9C, 0xF8, 0x60, 0x20, 0x01, 0x3A, 0x01, 0x2A, 0x1C, 0xD9, 0x93, 0xF8, ++0x60, 0x20, 0x04, 0x2A, 0x04, 0xD8, 0xDF, 0xE8, 0x02, 0xF0, 0x10, 0x20, 0x27, 0x10, 0x3C, 0x00, 0x3D, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDA, 0x3B, 0x49, 0x3C, 0x48, 0xC4, 0x22, 0xF5, 0xF7, 0x53, 0xFC, 0x00, 0x20, ++0xF8, 0xBD, 0xC2, 0x8B, 0x04, 0x24, 0xD5, 0x07, 0x0C, 0x60, 0x54, 0xD5, 0x20, 0x46, 0xF8, 0xBD, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x06, 0x76, 0x96, 0xF8, 0x5D, 0x22, 0x01, 0x2A, 0xDA, 0xD8, 0xED, 0xE7, 0xC2, 0x8B, 0x0C, 0x24, 0x0C, 0x60, ++0xD4, 0x07, 0x35, 0xD5, 0x08, 0x20, 0xF8, 0xBD, 0xC2, 0x8B, 0x08, 0x24, 0x0C, 0x60, 0xD1, 0x07, 0xF8, 0xD4, 0xD3, 0xE9, ++0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x16, 0x46, 0x0F, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x67, 0x06, 0x22, ++0x38, 0x30, 0x07, 0xF0, 0xCD, 0xFE, 0x20, 0x46, 0xF8, 0xBD, 0xC2, 0x8B, 0x10, 0x24, 0xD2, 0x07, 0x0C, 0x60, 0x13, 0xD4, ++0x93, 0xF8, 0x62, 0x20, 0x0F, 0x2A, 0xD3, 0xE9, 0x12, 0x21, 0x0F, 0xD9, 0x02, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x14, 0x46, ++0x0D, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x45, 0x08, 0x22, 0x38, 0x30, 0x07, 0xF0, 0xB4, 0xFE, 0x12, 0x20, 0xF8, 0xBD, ++0x12, 0x20, 0xF8, 0xBD, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0xEE, 0xE7, 0xD3, 0xE9, 0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, ++0x00, 0x01, 0x14, 0x46, 0x0D, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x45, 0x06, 0x22, 0x38, 0x30, 0x07, 0xF0, 0x9E, 0xFE, ++0xBA, 0xE7, 0xD3, 0xE9, 0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x16, 0x46, 0x0F, 0x46, 0x19, 0x46, 0xE1, 0xE9, ++0x12, 0x67, 0x22, 0x46, 0x38, 0x30, 0x07, 0xF0, 0x8F, 0xFE, 0x20, 0x46, 0xF8, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xF0, 0xB5, 0xC3, 0x8B, ++0x04, 0x46, 0xD8, 0x07, 0x83, 0xB0, 0x44, 0xD4, 0xE0, 0x7E, 0x66, 0x7F, 0x22, 0x7F, 0xFF, 0x28, 0x44, 0xD0, 0x4F, 0xF4, ++0x9E, 0x71, 0x01, 0xFB, 0x06, 0x01, 0x21, 0x48, 0x98, 0x31, 0x00, 0xEB, 0x41, 0x01, 0x1A, 0x25, 0x8F, 0x88, 0x78, 0x1C, ++0xC0, 0xF3, 0x0B, 0x00, 0x88, 0x80, 0x27, 0x84, 0xD9, 0x05, 0x1C, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x02, 0x33, ++0x48, 0xBF, 0x06, 0x35, 0x93, 0xF8, 0x62, 0x30, 0x43, 0xB9, 0x16, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x06, 0x36, ++0x73, 0x68, 0x9B, 0x06, 0x48, 0xBF, 0x04, 0x35, 0x01, 0xA9, 0x84, 0xF8, 0x32, 0x50, 0x20, 0x46, 0xFF, 0xF7, 0x16, 0xFF, ++0x23, 0x8B, 0xA2, 0x88, 0x22, 0x86, 0x5B, 0xBA, 0x9B, 0xB2, 0xB3, 0xF5, 0xC0, 0x6F, 0x28, 0x44, 0x88, 0xBF, 0x08, 0x30, ++0xC0, 0xB2, 0x01, 0x9B, 0x84, 0xF8, 0x33, 0x00, 0x8C, 0xBF, 0x08, 0x21, 0x00, 0x21, 0x84, 0xF8, 0x42, 0x00, 0x84, 0xF8, ++0x34, 0x10, 0x84, 0xF8, 0x35, 0x30, 0x00, 0x23, 0xC4, 0xE9, 0x09, 0x33, 0x03, 0xB0, 0xF0, 0xBD, 0x18, 0x25, 0xC7, 0xE7, ++0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x1D, 0xA0, 0xDF, 0xF8, 0x58, 0x92, ++0x90, 0xF8, 0x1C, 0x80, 0x92, 0x4F, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x0A, 0xF6, 0x09, 0xEB, 0x06, 0x02, 0x4F, 0xF4, ++0xA4, 0x64, 0x04, 0xFB, 0x08, 0x74, 0xD2, 0xF8, 0xB4, 0x30, 0x94, 0xF8, 0x62, 0xC0, 0xD3, 0xF8, 0x00, 0xB0, 0xD2, 0xF8, ++0xB0, 0x30, 0x83, 0xB0, 0x05, 0x46, 0x01, 0x93, 0xD4, 0xF8, 0xA8, 0x34, 0x00, 0x93, 0x0C, 0x46, 0xBC, 0xF1, 0x00, 0x0F, ++0x40, 0xF0, 0x8D, 0x80, 0x53, 0x68, 0x13, 0xF0, 0x20, 0x03, 0x40, 0xF0, 0x9F, 0x80, 0xE9, 0x7E, 0xB5, 0xF8, 0x1E, 0xC0, ++0xFF, 0x29, 0x0C, 0xBF, 0xA4, 0xF1, 0x18, 0x00, 0xA4, 0xF1, 0x1A, 0x00, 0x1C, 0xF4, 0x80, 0x72, 0x1D, 0xBF, 0x06, 0x38, ++0x00, 0xF1, 0x1E, 0x04, 0x02, 0x46, 0x00, 0xF1, 0x18, 0x04, 0xFF, 0x29, 0x00, 0xF0, 0x94, 0x80, 0x6F, 0xF0, 0x7F, 0x0C, ++0x4F, 0xF0, 0x00, 0x0E, 0x80, 0xF8, 0x00, 0xC0, 0x80, 0xF8, 0x01, 0xE0, 0x21, 0x80, 0x29, 0x8C, 0xB5, 0xF8, 0x1E, 0xC0, ++0x09, 0x01, 0x1C, 0xF4, 0x00, 0x7F, 0xC1, 0x82, 0x63, 0xD1, 0x01, 0x88, 0x0B, 0x43, 0x43, 0xF0, 0x08, 0x01, 0x1C, 0xF4, ++0x00, 0x6F, 0x01, 0x80, 0x69, 0xD0, 0x23, 0xF4, 0x40, 0x71, 0x41, 0xF0, 0x08, 0x01, 0x89, 0xB2, 0x01, 0x80, 0x4F, 0xF4, ++0xA4, 0x64, 0x1C, 0xF0, 0x04, 0x0F, 0x04, 0xFB, 0x08, 0xF4, 0x18, 0xBF, 0x41, 0xF4, 0x00, 0x51, 0x04, 0xF1, 0x5C, 0x03, ++0x18, 0xBF, 0x01, 0x80, 0x07, 0xEB, 0x03, 0x0C, 0xFB, 0x5A, 0x43, 0x81, 0xBC, 0xF8, 0x02, 0x30, 0x83, 0x81, 0x01, 0xF4, ++0x40, 0x71, 0xBC, 0xF8, 0x04, 0x30, 0xC3, 0x81, 0xB1, 0xF5, 0x80, 0x7F, 0x5C, 0xD0, 0xB1, 0xF5, 0x00, 0x7F, 0x76, 0xD0, ++0x00, 0x29, 0x40, 0xF0, 0x81, 0x80, 0xAB, 0x89, 0x83, 0x80, 0xEB, 0x89, 0xC3, 0x80, 0x2B, 0x8A, 0x03, 0x81, 0x04, 0xF5, ++0xB2, 0x74, 0x3B, 0x5B, 0x03, 0x82, 0x3C, 0x44, 0x63, 0x88, 0x43, 0x82, 0xA3, 0x88, 0x83, 0x82, 0xBB, 0xF1, 0x00, 0x0F, ++0x1C, 0xD0, 0x00, 0x9B, 0xD3, 0xB1, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x77, 0xD7, 0xF8, 0xB0, 0x34, 0x9B, 0x07, ++0x0A, 0xD5, 0x6A, 0x7F, 0x2B, 0x8B, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x02, 0x92, 0x5B, 0xBA, 0x92, 0x8E, 0x9B, 0xB2, ++0x9A, 0x42, 0x07, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x7B, 0xD0, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, 0x01, 0x2B, 0x6E, 0xD9, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x23, 0x75, 0xE7, 0x21, 0x88, 0x41, 0xF0, 0x10, 0x01, 0x21, 0x80, 0x01, 0x88, ++0xB5, 0xF8, 0x1E, 0xC0, 0x0B, 0x43, 0x43, 0xF0, 0x08, 0x01, 0x1C, 0xF4, 0x00, 0x6F, 0x01, 0x80, 0x95, 0xD1, 0x1C, 0xF4, ++0x80, 0x7F, 0x22, 0xD0, 0x43, 0xF4, 0x42, 0x71, 0x01, 0x80, 0x94, 0xE7, 0x32, 0x4B, 0x11, 0x46, 0xD3, 0xF8, 0xB8, 0x33, ++0x98, 0x47, 0x4F, 0xF4, 0x00, 0x43, 0x44, 0xF8, 0x04, 0x0D, 0x56, 0xE7, 0x00, 0x21, 0x81, 0x75, 0xC1, 0x75, 0x7A, 0xE7, ++0x26, 0x36, 0x09, 0xEB, 0x06, 0x03, 0x39, 0xF8, 0x06, 0x20, 0x82, 0x80, 0x5A, 0x88, 0xC2, 0x80, 0x9B, 0x88, 0x03, 0x81, ++0xAB, 0x89, 0x03, 0x82, 0xEB, 0x89, 0x43, 0x82, 0x2B, 0x8A, 0x83, 0x82, 0xA6, 0xE7, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, ++0x08, 0x74, 0x94, 0xF8, 0x62, 0x40, 0x00, 0x2C, 0x27, 0xD1, 0x43, 0xF4, 0x84, 0x71, 0x01, 0x80, 0x69, 0xE7, 0xAB, 0x89, ++0x83, 0x80, 0xEB, 0x89, 0xC3, 0x80, 0x2B, 0x8A, 0x03, 0x81, 0x6B, 0x8A, 0x03, 0x82, 0xAB, 0x8A, 0x43, 0x82, 0xEB, 0x8A, ++0x83, 0x82, 0x8D, 0xE7, 0x26, 0x36, 0x09, 0xEB, 0x06, 0x03, 0x39, 0xF8, 0x06, 0x10, 0x91, 0x80, 0x59, 0x88, 0xD1, 0x80, ++0x9B, 0x88, 0x13, 0x81, 0xAB, 0x89, 0x13, 0x82, 0xEB, 0x89, 0x53, 0x82, 0x2B, 0x8A, 0x93, 0x82, 0x6B, 0x8A, 0x13, 0x83, ++0xAB, 0x8A, 0x53, 0x83, 0xEB, 0x8A, 0x93, 0x83, 0x76, 0xE7, 0x02, 0x2C, 0x04, 0xBF, 0x43, 0xF4, 0x02, 0x71, 0x01, 0x80, ++0x3F, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x0A, 0x99, 0x99, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x88, 0xD9, 0x03, 0x88, ++0x43, 0xF4, 0x80, 0x43, 0x03, 0x80, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x06, 0x46, 0x54, 0x48, 0x75, 0x7F, 0x34, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x05, 0x03, 0x89, 0x46, 0xD3, 0xF8, 0xB4, 0x70, 0xD7, 0xF8, 0x00, 0x80, 0xB8, 0xF1, 0x00, 0x0F, 0x4C, 0xD0, ++0x17, 0x46, 0x4D, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x04, 0x24, 0xD4, 0xF8, 0xA8, 0x24, 0x00, 0x2A, 0x42, 0xD0, ++0xD4, 0xF8, 0xB0, 0x24, 0x92, 0x07, 0x05, 0xD5, 0x32, 0x8B, 0x99, 0x8E, 0x53, 0xBA, 0x9B, 0xB2, 0x99, 0x42, 0x38, 0xD0, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x05, 0xD5, 0xF8, 0xB0, 0x30, 0x23, 0xB1, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, ++0x01, 0x2B, 0x40, 0xD9, 0x98, 0xF8, 0x60, 0x30, 0x04, 0x2B, 0x67, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x2A, 0x03, 0x40, 0x2A, ++0x49, 0x00, 0x32, 0x8F, 0x42, 0xF4, 0x00, 0x53, 0x03, 0xF4, 0xFE, 0x43, 0x43, 0xEA, 0x12, 0x23, 0x29, 0xF8, 0x08, 0x3C, ++0x96, 0xF8, 0x38, 0x30, 0x98, 0xF8, 0x61, 0x20, 0xA9, 0xF1, 0x08, 0x09, 0x43, 0xEA, 0x82, 0x33, 0x43, 0xF4, 0x00, 0x53, ++0xA9, 0xF8, 0x02, 0x30, 0x73, 0x8F, 0xA9, 0xF8, 0x04, 0x30, 0xB3, 0x8F, 0xA9, 0xF8, 0x06, 0x30, 0xC7, 0xB1, 0xF2, 0x6A, ++0xD4, 0x68, 0x2B, 0x4B, 0x98, 0xF8, 0x62, 0x00, 0x23, 0x40, 0x03, 0x43, 0xD3, 0x60, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, ++0x33, 0x8F, 0x29, 0xF8, 0x04, 0x3C, 0x98, 0xF8, 0x61, 0x20, 0x73, 0x8F, 0xA9, 0xF1, 0x04, 0x09, 0x43, 0xEA, 0x82, 0x33, ++0xA9, 0xF8, 0x02, 0x30, 0x00, 0x2F, 0xE6, 0xD1, 0xB2, 0x6C, 0x28, 0x32, 0xE4, 0xE7, 0x95, 0xF8, 0x5D, 0x32, 0x01, 0x2B, ++0xBA, 0xD8, 0xE6, 0xE7, 0x33, 0x8F, 0x29, 0xF8, 0x08, 0x3C, 0x98, 0xF8, 0x61, 0x30, 0xA9, 0xF1, 0x08, 0x09, 0x9B, 0x03, ++0xCA, 0xE7, 0x98, 0xF8, 0x61, 0x30, 0x29, 0xF8, 0x12, 0x3C, 0xA9, 0xF1, 0x12, 0x09, 0x33, 0x8F, 0xA9, 0xF8, 0x02, 0x30, ++0x73, 0x8F, 0xA9, 0xF8, 0x04, 0x30, 0xB3, 0x8F, 0xA9, 0xF8, 0x06, 0x30, 0xF3, 0x8F, 0xA9, 0xF8, 0x08, 0x30, 0x45, 0xF6, ++0x36, 0x43, 0xA9, 0xF8, 0x0A, 0x30, 0xA9, 0xF8, 0x0C, 0x30, 0xA9, 0xF8, 0x0E, 0x30, 0xA9, 0xF8, 0x10, 0x30, 0xB7, 0xE7, ++0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB1, 0xDA, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xD9, 0x22, ++0xF5, 0xF7, 0xA8, 0xF9, 0xAA, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x00, 0xFC, 0x0F, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x70, 0xB5, 0x1A, 0x4D, 0x1A, 0x4E, 0xD5, 0xF8, ++0x68, 0x32, 0x04, 0x46, 0x98, 0x47, 0x60, 0x7F, 0xD5, 0xF8, 0x5C, 0x31, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0x60, ++0x98, 0x47, 0xE3, 0x8B, 0xE0, 0x62, 0x99, 0x04, 0x11, 0xD5, 0x63, 0x7F, 0x05, 0xFB, 0x03, 0x66, 0xD6, 0xF8, 0x4C, 0x31, ++0xD3, 0xF8, 0x9C, 0x20, 0xA2, 0x62, 0x93, 0xF8, 0xA1, 0x30, 0x2B, 0xB1, 0x94, 0xF8, 0x36, 0x30, 0x43, 0xF0, 0x20, 0x03, ++0x84, 0xF8, 0x36, 0x30, 0x70, 0xBD, 0x94, 0xF8, 0x36, 0x30, 0x03, 0xF0, 0x03, 0x02, 0x00, 0xEB, 0x82, 0x00, 0x42, 0x6A, ++0x41, 0x69, 0xA1, 0x62, 0x52, 0x03, 0x44, 0xBF, 0x43, 0xF0, 0x20, 0x03, 0x84, 0xF8, 0x36, 0x30, 0x70, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0xC3, 0x7E, 0x00, 0x93, 0x04, 0x46, 0xC3, 0x8B, ++0x0F, 0x46, 0x16, 0x46, 0x16, 0x49, 0x02, 0x8C, 0x20, 0x20, 0xF4, 0xF7, 0x29, 0xFF, 0xE3, 0x8B, 0xD9, 0x07, 0x1E, 0xD5, ++0x13, 0x48, 0xF4, 0xF7, 0xD3, 0xFE, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x10, 0x4D, 0x2B, 0x68, 0x3A, 0x46, 0x01, 0x33, 0x31, 0x46, 0x20, 0x46, 0x2B, 0x60, 0xDF, 0xF7, 0x4A, 0xFD, ++0x2B, 0x68, 0x33, 0xB1, 0x09, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x03, 0xB0, ++0xF0, 0xBD, 0xDF, 0xF7, 0x61, 0xF9, 0xE3, 0x8B, 0xDA, 0x07, 0xDB, 0xD4, 0xDD, 0xE7, 0x00, 0xBF, 0x3C, 0xC1, 0x15, 0x00, ++0x58, 0xC1, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x02, 0x8B, 0x53, 0xBA, 0x9B, 0xB2, 0xB3, 0xF5, ++0xC0, 0x6F, 0x10, 0xB5, 0x04, 0x46, 0x08, 0xD3, 0x4A, 0xF6, 0xAA, 0x23, 0x21, 0xF8, 0x08, 0x3D, 0x03, 0x20, 0x00, 0x23, ++0xCA, 0x80, 0x48, 0x80, 0x8B, 0x80, 0x20, 0x46, 0x01, 0x22, 0xFF, 0xF7, 0xBB, 0xFE, 0x04, 0x4B, 0x01, 0x46, 0xD3, 0xF8, ++0x20, 0x34, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xC5, 0x8B, 0xDF, 0xF8, 0x7C, 0x82, 0x07, 0x7F, 0x4F, 0xF4, 0xA4, 0x6A, 0x0E, 0x46, 0x29, 0x07, 0x83, 0xB0, 0x04, 0x46, ++0x0A, 0xFB, 0x07, 0x8A, 0x6B, 0xD4, 0x41, 0x7F, 0xDF, 0xF8, 0x64, 0xB2, 0x03, 0x8B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, ++0x01, 0xB1, 0x5B, 0xBA, 0x88, 0x8E, 0x91, 0xF8, 0x30, 0x20, 0x9B, 0xB2, 0x98, 0x42, 0x0F, 0xD0, 0x02, 0x2A, 0x16, 0xD0, ++0x8B, 0x49, 0x20, 0x20, 0xF4, 0xF7, 0xB4, 0xFE, 0x20, 0x46, 0x31, 0x46, 0x4F, 0xF0, 0x00, 0x42, 0xFF, 0xF7, 0x78, 0xFF, ++0x00, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x3A, 0x25, 0xF4, 0x80, 0x75, 0x01, 0x2A, 0xE5, 0x83, 0x02, 0xD9, ++0x91, 0xF8, 0x30, 0x20, 0xE8, 0xE7, 0xDF, 0xF8, 0x1C, 0x92, 0x20, 0x46, 0xD9, 0xF8, 0x2C, 0x34, 0x98, 0x47, 0x63, 0x7F, ++0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0xBB, 0x9B, 0xF8, 0x30, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xA2, 0x80, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x07, 0x87, 0x77, 0x4A, 0x3B, 0x6C, 0x77, 0x49, 0x1F, 0x79, 0x77, 0x4B, 0x00, 0x2F, 0x0C, 0xBF, ++0x0F, 0x46, 0x17, 0x46, 0xE7, 0x62, 0x7D, 0x69, 0x93, 0xF8, 0xBD, 0x20, 0xC5, 0xF3, 0xC2, 0x28, 0xED, 0xB2, 0x00, 0x2A, ++0x40, 0xF0, 0xB4, 0x80, 0xD9, 0xF8, 0x38, 0x33, 0x50, 0x46, 0x01, 0xAA, 0x0D, 0xF1, 0x03, 0x01, 0x98, 0x47, 0x05, 0xF0, ++0x7C, 0x03, 0x58, 0xEA, 0x03, 0x03, 0x0C, 0xBF, 0x9D, 0xF8, 0x03, 0x30, 0x9D, 0xF8, 0x04, 0x30, 0x43, 0xEA, 0x03, 0x23, ++0x7B, 0x62, 0xE3, 0x8B, 0xDB, 0x07, 0x4C, 0xD4, 0xA1, 0x6C, 0xD9, 0xF8, 0x1C, 0x34, 0xA8, 0x31, 0x20, 0x46, 0x98, 0x47, ++0x45, 0xE0, 0x00, 0x23, 0xEA, 0x06, 0x01, 0x93, 0x5B, 0xD5, 0x5D, 0x4B, 0xE3, 0x62, 0x15, 0xF0, 0x80, 0x05, 0x7D, 0xD1, ++0xA8, 0x46, 0xDF, 0xF8, 0x80, 0x91, 0x5B, 0x4F, 0xD9, 0xF8, 0x38, 0x33, 0x50, 0x46, 0x0D, 0xF1, 0x03, 0x02, 0x0D, 0xF1, ++0x02, 0x01, 0x98, 0x47, 0xE2, 0x6A, 0x4F, 0xF0, 0x00, 0x0A, 0xA3, 0x68, 0x02, 0xEB, 0x8A, 0x00, 0x23, 0xF0, 0x60, 0x41, ++0x13, 0xF0, 0x80, 0x4F, 0x41, 0xF0, 0x00, 0x51, 0x14, 0xBF, 0x41, 0x61, 0x43, 0x69, 0x97, 0xF8, 0xBD, 0x10, 0xC3, 0xF3, ++0xC2, 0x20, 0x03, 0xF0, 0x7F, 0x03, 0x51, 0xBB, 0x08, 0xBB, 0x03, 0x2B, 0x02, 0xEB, 0x8A, 0x01, 0x1D, 0xD8, 0x9D, 0xF8, ++0x02, 0x30, 0x43, 0xEA, 0x03, 0x23, 0x4B, 0x62, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x04, 0x0F, 0xDD, 0xD1, 0x00, 0x23, ++0xC4, 0xE9, 0x09, 0x33, 0x01, 0x9A, 0x84, 0xF8, 0x32, 0x80, 0x84, 0xF8, 0x33, 0x50, 0x84, 0xF8, 0x42, 0x50, 0x84, 0xF8, ++0x35, 0x20, 0xD9, 0xF8, 0x94, 0x33, 0x31, 0x46, 0x20, 0x46, 0x98, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x9D, 0xF8, ++0x03, 0x30, 0x02, 0xEB, 0x8A, 0x01, 0x43, 0xEA, 0x03, 0x23, 0x4B, 0x62, 0xDE, 0xE7, 0x19, 0x46, 0xD1, 0xF7, 0xF0, 0xFD, ++0xE2, 0x6A, 0x02, 0xEB, 0x8A, 0x03, 0x40, 0xEA, 0x00, 0x20, 0x58, 0x62, 0xD4, 0xE7, 0x9A, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0x9F, 0xD1, 0xDA, 0xF8, 0x40, 0x20, 0x2D, 0x4B, 0x11, 0x79, 0x2B, 0x4A, 0x00, 0x29, 0x18, 0xBF, 0x13, 0x46, 0xC3, 0x62, ++0x97, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x83, 0x93, 0xF8, 0x62, 0x20, 0x52, 0xB3, 0x02, 0x2A, 0x04, 0xD1, ++0x9B, 0xF8, 0x70, 0x32, 0x00, 0x2B, 0x7F, 0xF4, 0x50, 0xAF, 0x24, 0x4B, 0x1B, 0x78, 0x1B, 0xB9, 0xD9, 0xF8, 0x1C, 0x30, ++0x20, 0x46, 0x98, 0x47, 0x20, 0x46, 0xFF, 0xF7, 0x67, 0xFE, 0x6E, 0xE7, 0x00, 0x22, 0xC0, 0x21, 0x20, 0x46, 0x01, 0xF0, ++0x1D, 0xFB, 0x01, 0x28, 0x1C, 0xD0, 0x02, 0x28, 0x15, 0xD0, 0xE3, 0x8B, 0x00, 0x25, 0x23, 0xF0, 0x80, 0x03, 0xE3, 0x83, ++0xA8, 0x46, 0x72, 0xE7, 0x05, 0xF0, 0x7F, 0x01, 0x40, 0x46, 0xD1, 0xF7, 0xAD, 0xFD, 0x40, 0xEA, 0x00, 0x20, 0x78, 0x62, ++0x55, 0xE7, 0x93, 0xF8, 0xAC, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x27, 0xAF, 0xD5, 0xE7, 0x12, 0x23, 0x00, 0x25, 0x01, 0x93, ++0xA8, 0x46, 0x5E, 0xE7, 0x01, 0xA9, 0x20, 0x46, 0xFF, 0xF7, 0x46, 0xFB, 0xA3, 0x6C, 0x05, 0x46, 0x03, 0xF1, 0xA8, 0x01, ++0x03, 0xF1, 0xA0, 0x00, 0x18, 0x22, 0x07, 0xF0, 0x75, 0xFA, 0xED, 0xB2, 0x4F, 0xF0, 0x18, 0x08, 0x4D, 0xE7, 0x00, 0xBF, ++0x70, 0xC1, 0x15, 0x00, 0x84, 0x3C, 0x18, 0x00, 0xC4, 0x3C, 0x18, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xB8, 0x34, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x51, 0x4A, 0x43, 0x7F, ++0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x03, 0x23, 0x86, 0xB0, 0xD3, 0xF8, 0xB4, 0x30, 0x1E, 0x68, 0x8E, 0xB1, 0x90, 0xF8, ++0x35, 0x30, 0x04, 0x46, 0x6B, 0xB1, 0x90, 0xF8, 0x34, 0x30, 0x85, 0x6C, 0x96, 0xF8, 0x60, 0x20, 0xED, 0x1A, 0x01, 0x2A, ++0x05, 0xF1, 0xA8, 0x05, 0x06, 0xD0, 0x03, 0x2A, 0x51, 0xD0, 0x00, 0x2A, 0x4F, 0xD0, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, ++0x07, 0x8E, 0x42, 0x4A, 0x00, 0x91, 0x3B, 0x44, 0x06, 0xF1, 0x50, 0x01, 0xD2, 0xF8, 0x7C, 0x73, 0x2A, 0x46, 0xB8, 0x47, ++0x3E, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9A, 0x07, 0xED, 0xD5, 0x96, 0xF8, 0x60, 0x20, 0x01, 0x2A, 0x06, 0xF1, 0x64, 0x08, ++0x3E, 0xD1, 0x23, 0x8E, 0x94, 0xF8, 0x34, 0x70, 0x0C, 0x33, 0x1F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, 0x4F, 0xF0, 0xFF, 0x33, ++0x03, 0x22, 0x28, 0x46, 0xD6, 0xF7, 0xD8, 0xF8, 0xD6, 0xE9, 0x12, 0x03, 0x32, 0x49, 0x94, 0xF8, 0x1C, 0xC0, 0x88, 0x80, ++0x31, 0x4A, 0x00, 0x0C, 0x4F, 0xF4, 0xA4, 0x6E, 0x40, 0xEA, 0x03, 0x40, 0x0E, 0xFB, 0x0C, 0x22, 0x08, 0x60, 0x02, 0xAB, ++0x40, 0x46, 0xF2, 0xF7, 0x9F, 0xFA, 0x02, 0xA8, 0x10, 0x21, 0xF2, 0xF7, 0x5F, 0xFC, 0x96, 0xF8, 0x60, 0x20, 0xCA, 0xB1, ++0x03, 0x2A, 0x17, 0xD0, 0x03, 0x20, 0xD6, 0xF7, 0xF1, 0xF8, 0x39, 0x46, 0x02, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x84, 0xFA, ++0x39, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x7A, 0xFC, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, ++0x9B, 0x07, 0xAA, 0xD5, 0x06, 0xF1, 0x64, 0x08, 0x00, 0x27, 0xE4, 0xE7, 0x23, 0x8E, 0x94, 0xF8, 0x34, 0x70, 0x04, 0x33, ++0x1F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x28, 0x46, 0xD6, 0xF7, 0x97, 0xF8, 0x96, 0xF8, ++0x60, 0x30, 0xB6, 0xF8, 0x48, 0x10, 0xB6, 0xF8, 0x4A, 0x20, 0xAD, 0xF8, 0x08, 0x10, 0x8D, 0xF8, 0x0A, 0x20, 0x41, 0x46, ++0x4B, 0xB9, 0x05, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x07, 0xF0, 0xCA, 0xF9, 0x02, 0xA8, 0x08, 0x21, 0xF2, 0xF7, 0x20, 0xFC, ++0xC4, 0xE7, 0x0D, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x07, 0xF0, 0xC0, 0xF9, 0x02, 0xA8, 0x10, 0x21, 0xF2, 0xF7, 0x16, 0xFC, ++0xBA, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0xA0, 0x34, 0x17, 0x00, ++0x74, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xC5, 0x6C, 0xC3, 0x8B, 0x2F, 0x69, 0x02, 0x8C, 0x2A, 0x81, 0x00, 0x26, ++0x13, 0xF0, 0x08, 0x02, 0x2E, 0x61, 0x04, 0x46, 0x07, 0xF4, 0x00, 0x06, 0x88, 0x46, 0x07, 0xF0, 0x40, 0x47, 0x1C, 0xD0, ++0x99, 0x06, 0x01, 0xD5, 0x00, 0x2E, 0x6C, 0xD0, 0x9A, 0x05, 0x3E, 0xD4, 0xB7, 0xF1, 0x40, 0x4F, 0x20, 0xD0, 0xE3, 0x7E, ++0xFF, 0x2B, 0x22, 0xD1, 0x2B, 0x69, 0x62, 0x6A, 0x01, 0x20, 0x02, 0xF4, 0x00, 0x12, 0x16, 0xB1, 0x43, 0xF0, 0x08, 0x03, ++0x2B, 0x61, 0x00, 0x2A, 0x47, 0xD0, 0x43, 0xF0, 0x01, 0x03, 0x28, 0x73, 0x2B, 0x61, 0xBD, 0xE8, 0xF0, 0x81, 0x9B, 0x05, ++0xE6, 0xD5, 0x43, 0x7F, 0x2A, 0x49, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0xB7, 0xF1, 0x40, 0x4F, 0x83, 0xF8, ++0x32, 0x20, 0xDE, 0xD1, 0x2B, 0x69, 0x43, 0xF0, 0x04, 0x03, 0x2B, 0x61, 0xDD, 0xE7, 0x31, 0x1E, 0x42, 0x46, 0x18, 0xBF, ++0x01, 0x21, 0x20, 0x46, 0x01, 0xF0, 0x3A, 0xF8, 0x63, 0x6A, 0x13, 0xF4, 0x00, 0x12, 0x20, 0xD0, 0x03, 0xF4, 0x60, 0x13, ++0xB3, 0xF5, 0x60, 0x1F, 0x01, 0xD0, 0x00, 0x23, 0x6B, 0x73, 0x2B, 0x69, 0x00, 0x2E, 0xD2, 0xD0, 0xCC, 0xE7, 0x19, 0x4B, ++0x60, 0x7F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1A, 0xDB, 0x00, 0x23, 0x1A, 0x46, 0x17, 0x21, 0xE0, 0xF7, ++0x0D, 0xFA, 0x12, 0x4A, 0x63, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x00, 0x22, 0x83, 0xF8, 0x32, 0x20, ++0xAA, 0xE7, 0x2B, 0x69, 0x0E, 0xB1, 0x43, 0xF0, 0x08, 0x03, 0x01, 0x22, 0x43, 0xF0, 0x01, 0x03, 0x6A, 0x73, 0x28, 0x73, ++0x2B, 0x61, 0xBD, 0xE8, 0xF0, 0x81, 0xFF, 0x28, 0xE2, 0xD1, 0x08, 0x48, 0x08, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0xF4, 0xF7, ++0x89, 0xFE, 0x60, 0x7F, 0xDA, 0xE7, 0xFF, 0xF7, 0xC7, 0xF9, 0xE3, 0x8B, 0x8E, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x84, 0xC1, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x70, 0xB5, 0x90, 0xF8, 0x33, 0x30, 0x82, 0xB0, ++0x04, 0x46, 0x0D, 0x46, 0x16, 0x46, 0x7B, 0xB1, 0x90, 0xF8, 0x35, 0x20, 0x01, 0x92, 0x18, 0x46, 0x2B, 0x88, 0x2E, 0x44, ++0x43, 0xF4, 0x80, 0x43, 0x31, 0x18, 0x2B, 0x80, 0x20, 0x46, 0x00, 0x22, 0xFF, 0xF7, 0x12, 0xFC, 0x02, 0xB0, 0x70, 0xBD, ++0x01, 0xA9, 0xFF, 0xF7, 0xCD, 0xF9, 0x01, 0x9B, 0x84, 0xF8, 0x33, 0x00, 0x84, 0xF8, 0x35, 0x30, 0xEA, 0xE7, 0x00, 0xBF, ++0x10, 0xB4, 0x0C, 0x88, 0x0B, 0x46, 0x44, 0xF4, 0x80, 0x44, 0x11, 0x44, 0x1C, 0x80, 0x00, 0x22, 0x5D, 0xF8, 0x04, 0x4B, ++0xFF, 0xF7, 0xFA, 0xBB, 0xF0, 0xB5, 0x00, 0x22, 0x18, 0x4C, 0x85, 0xB0, 0x05, 0x46, 0x0F, 0x46, 0x02, 0xE0, 0x01, 0x32, ++0x20, 0x2A, 0x26, 0xD0, 0xA5, 0x42, 0x96, 0xB2, 0x04, 0xF1, 0x18, 0x04, 0xF7, 0xD1, 0x12, 0x02, 0x02, 0xF4, 0x7F, 0x42, ++0x42, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0xF6, 0xFF, 0x04, 0x28, 0x18, 0xD1, 0x17, 0xF4, 0x00, 0x03, 0x02, 0xD1, 0xEA, 0x7C, ++0x02, 0x2A, 0x06, 0xD9, 0x28, 0x7B, 0x31, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0x00, 0xF0, 0x65, 0xBC, 0x08, 0x49, ++0x01, 0x32, 0xEA, 0x74, 0x27, 0x22, 0xCD, 0xE9, 0x01, 0x21, 0x00, 0x93, 0x28, 0x7B, 0x02, 0x22, 0x29, 0x46, 0x00, 0xF0, ++0xBB, 0xFC, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, 0xF4, 0xE4, 0x17, 0x00, 0xE5, 0xFE, 0x14, 0x00, 0x2D, 0xE9, 0xF0, 0x43, ++0x10, 0x46, 0x85, 0xB0, 0x14, 0x46, 0x0F, 0x46, 0xF2, 0xF7, 0xCC, 0xFF, 0x03, 0x28, 0x09, 0xD0, 0x50, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x72, 0xDB, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x4C, 0x4E, 0x4F, 0xEA, ++0x14, 0x28, 0x08, 0xEB, 0x48, 0x03, 0x06, 0xEB, 0xC3, 0x06, 0x96, 0xF8, 0x0D, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x39, 0xD0, ++0xB9, 0xF1, 0x01, 0x0F, 0x29, 0xD1, 0xBB, 0x78, 0x00, 0x2B, 0x7C, 0xD1, 0x05, 0x46, 0x30, 0x46, 0x96, 0xF8, 0x0F, 0x90, ++0x00, 0xF0, 0xA0, 0xFF, 0x41, 0x4B, 0x1B, 0x69, 0x73, 0x60, 0x05, 0x22, 0x2B, 0x46, 0x0C, 0x21, 0x41, 0xF2, 0x0B, 0x40, ++0x3D, 0x78, 0x7F, 0x78, 0xF2, 0xF7, 0xFA, 0xFC, 0xA9, 0xF1, 0x04, 0x09, 0x4F, 0xFA, 0x89, 0xF9, 0x80, 0xF8, 0x02, 0x90, ++0x05, 0x70, 0x47, 0x70, 0xF2, 0xF7, 0x20, 0xFD, 0x73, 0x89, 0x00, 0x2B, 0x39, 0xD1, 0x20, 0x46, 0x01, 0x21, 0xF2, 0xF7, ++0xE3, 0xFE, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x2F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xBC, 0xDA, 0x2F, 0x49, 0x2F, 0x48, 0x40, 0xF2, 0x29, 0x12, 0xF4, 0xF7, 0xD3, 0xFD, 0xB5, 0xE7, 0xBA, 0x78, 0x33, 0x7C, ++0x72, 0xBB, 0xB0, 0x7B, 0xF1, 0x7B, 0x02, 0x92, 0x9B, 0x00, 0x43, 0xEA, 0x40, 0x03, 0x43, 0xEA, 0x81, 0x13, 0xCD, 0xE9, ++0x00, 0x32, 0x31, 0x46, 0x73, 0x7C, 0x30, 0x7B, 0x01, 0x22, 0x00, 0xF0, 0x47, 0xFC, 0x3B, 0x78, 0x7D, 0x78, 0x23, 0x4A, ++0x1F, 0x48, 0x71, 0x89, 0x03, 0xEB, 0x83, 0x07, 0xC3, 0xEB, 0x07, 0x13, 0x2B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x83, 0xF8, ++0xA4, 0x81, 0x03, 0x69, 0x73, 0x60, 0x00, 0x29, 0xC5, 0xD0, 0x40, 0x46, 0x00, 0xF0, 0x9A, 0xFB, 0xC1, 0xE7, 0x17, 0x49, ++0x17, 0x48, 0xC8, 0x22, 0xF4, 0xF7, 0xA4, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0xB1, 0x7B, 0xF2, 0x7B, ++0xCD, 0xF8, 0x08, 0x90, 0x9B, 0x00, 0x43, 0xEA, 0x41, 0x03, 0x43, 0xEA, 0x82, 0x13, 0x25, 0x22, 0xCD, 0xE9, 0x00, 0x32, ++0x31, 0x46, 0x30, 0x7B, 0x73, 0x7C, 0x01, 0x22, 0x00, 0xF0, 0x16, 0xFC, 0x49, 0x46, 0x20, 0x46, 0xF2, 0xF7, 0x8A, 0xFE, ++0x6C, 0xE7, 0x40, 0x46, 0x00, 0xF0, 0xF8, 0xFA, 0x20, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0x82, 0xFE, 0x64, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x8B, 0x78, 0x02, 0x2B, 0x01, 0xD0, 0x00, 0x20, 0xF8, 0xBD, 0x02, 0xF4, 0x7F, 0x40, ++0x40, 0xF0, 0x08, 0x00, 0x0C, 0x46, 0x15, 0x0A, 0xF2, 0xF7, 0x0E, 0xFF, 0x04, 0x28, 0xF3, 0xD1, 0x11, 0x4E, 0x05, 0xEB, ++0x45, 0x03, 0x06, 0xEB, 0xC3, 0x06, 0x73, 0x7B, 0x01, 0x2B, 0x04, 0xD0, 0x0E, 0x4B, 0x28, 0x46, 0x9B, 0x6A, 0x98, 0x47, ++0xE6, 0xE7, 0x70, 0x69, 0x00, 0xF0, 0x1E, 0xFF, 0xF3, 0x7B, 0x67, 0x78, 0x26, 0x78, 0xC3, 0xF1, 0x04, 0x03, 0x1C, 0x18, ++0x05, 0x22, 0x03, 0x23, 0x0C, 0x21, 0x41, 0xF2, 0x0B, 0x40, 0xF2, 0xF7, 0x4D, 0xFC, 0x64, 0xB2, 0x84, 0x70, 0x06, 0x70, ++0x47, 0x70, 0xF2, 0xF7, 0x77, 0xFC, 0xE3, 0xE7, 0xF4, 0xE4, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xB7, 0x4F, 0xCE, 0x79, 0xB7, 0x4A, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x06, 0x75, 0x0C, 0x46, 0x95, 0xF8, 0x22, 0x30, ++0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x85, 0xB0, 0x93, 0xF8, 0x64, 0x30, 0x1B, 0xB9, 0x00, 0x20, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x20, 0x94, 0xF8, 0x0D, 0x80, 0xF2, 0xF7, 0xC7, 0xFE, 0x09, 0x28, 0x04, 0xF1, 0x0C, 0x09, ++0xF2, 0xD0, 0xB8, 0xF1, 0x01, 0x0F, 0x5B, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0x1B, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0xE9, 0xD1, ++0xB9, 0xF8, 0x03, 0x80, 0x99, 0xF8, 0x02, 0xB0, 0xC8, 0xF3, 0x83, 0x0A, 0xBA, 0xF1, 0x08, 0x0F, 0x04, 0xD8, 0xA1, 0x4B, ++0x1B, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x87, 0x80, 0x25, 0x23, 0x00, 0x21, 0xCD, 0xE9, 0x00, 0x83, 0x30, 0x46, 0x5B, 0x46, ++0x02, 0x91, 0x01, 0x22, 0x00, 0xF0, 0x82, 0xFB, 0xD0, 0xE7, 0xB9, 0xF8, 0x02, 0x10, 0xB1, 0xF5, 0x10, 0x4F, 0x4F, 0xEA, ++0x11, 0x35, 0xC9, 0xD2, 0xE3, 0x79, 0xFF, 0x2B, 0xC6, 0xD0, 0x09, 0x05, 0x2A, 0x46, 0x40, 0xF1, 0xBA, 0x80, 0x93, 0x49, ++0x4F, 0xF4, 0x00, 0x60, 0xF4, 0xF7, 0xA4, 0xFA, 0xE3, 0x79, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x2B, 0x44, ++0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA4, 0x51, 0x21, 0x2D, 0xB1, 0xD0, 0x2E, 0x02, 0x46, 0xF0, 0x08, 0x06, 0x30, 0x46, ++0xF2, 0xF7, 0x7C, 0xFE, 0x04, 0x28, 0xA9, 0xD0, 0x31, 0x46, 0x42, 0xF2, 0x01, 0x00, 0xF2, 0xF7, 0xE1, 0xFA, 0x30, 0x46, ++0xF2, 0xF7, 0x72, 0xFE, 0x01, 0x28, 0x00, 0xF0, 0xD2, 0x80, 0x30, 0x46, 0xF2, 0xF7, 0x6C, 0xFE, 0x03, 0x28, 0x00, 0xF0, ++0xCC, 0x80, 0x7F, 0x4B, 0x28, 0x46, 0x9B, 0x6A, 0x98, 0x47, 0x93, 0xE7, 0xB9, 0xF8, 0x05, 0x50, 0xC5, 0xF3, 0x83, 0x06, ++0x08, 0x2E, 0x8D, 0xD8, 0xE3, 0x79, 0x7A, 0x49, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x33, 0x44, 0x07, 0xEB, ++0xC3, 0x07, 0x32, 0x46, 0x97, 0xF8, 0xA5, 0x71, 0x4F, 0xF4, 0x00, 0x60, 0x3B, 0x46, 0xF4, 0xF7, 0x63, 0xFA, 0x21, 0x2F, ++0x3F, 0xF4, 0x7A, 0xAF, 0x4F, 0xEA, 0x07, 0x28, 0x48, 0xF0, 0x08, 0x08, 0x40, 0x46, 0xF2, 0xF7, 0x43, 0xFE, 0x02, 0x28, ++0x7F, 0xF4, 0x70, 0xAF, 0x41, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0xF2, 0xF7, 0xA7, 0xFA, 0x6A, 0x4A, 0x99, 0xF8, 0x02, 0x10, ++0x07, 0xEB, 0x47, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x58, 0x7C, 0x88, 0x42, 0x03, 0xD1, 0x1B, 0x7C, 0xB3, 0x42, 0x00, 0xF0, ++0x9B, 0x80, 0x38, 0x46, 0x00, 0xF0, 0xF4, 0xF9, 0x40, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0x7E, 0xFD, 0x54, 0xE7, 0x60, 0x49, ++0x4F, 0xF4, 0x00, 0x60, 0x52, 0x46, 0xF4, 0xF7, 0x35, 0xFA, 0x51, 0x46, 0x30, 0x46, 0xE8, 0xF7, 0x85, 0xF9, 0x00, 0x28, ++0x4F, 0xD1, 0x95, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0x68, 0xAF, 0x00, 0xF0, 0x04, 0xFA, 0x21, 0x28, 0x04, 0x46, ++0x3F, 0xF4, 0x62, 0xAF, 0x53, 0x4D, 0x55, 0x4A, 0x00, 0xEB, 0x40, 0x01, 0x05, 0xEB, 0xC1, 0x03, 0xC8, 0xF3, 0x40, 0x00, ++0x12, 0x68, 0x83, 0xF8, 0x10, 0xA0, 0x00, 0x27, 0x1E, 0x73, 0x83, 0xF8, 0x11, 0xB0, 0x98, 0x73, 0x5F, 0x73, 0x90, 0x6B, ++0xB9, 0xF8, 0x05, 0x20, 0x5A, 0x81, 0x4F, 0xEA, 0x98, 0x18, 0x80, 0x45, 0x28, 0xBF, 0x80, 0x46, 0x83, 0xF8, 0x0F, 0x80, ++0xB9, 0xF8, 0x07, 0x00, 0xC9, 0x00, 0x00, 0x09, 0x92, 0xB2, 0x6F, 0x50, 0x18, 0x81, 0x1A, 0xB9, 0x44, 0x4A, 0x12, 0x68, ++0x52, 0x88, 0x5A, 0x81, 0x30, 0x46, 0x21, 0x46, 0x00, 0xF0, 0x3C, 0xFA, 0x20, 0x02, 0x00, 0xF4, 0x7F, 0x40, 0x40, 0xF0, ++0x08, 0x00, 0x03, 0x21, 0xF2, 0xF7, 0x32, 0xFD, 0x08, 0xE7, 0x3D, 0x49, 0x4F, 0xF4, 0x00, 0x60, 0xF4, 0xF7, 0xEA, 0xF9, ++0xE3, 0x79, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x2B, 0x44, 0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA5, 0x51, ++0x44, 0xE7, 0x06, 0xEB, 0x86, 0x03, 0xC6, 0xEB, 0x03, 0x13, 0x53, 0x44, 0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA4, 0x71, ++0x3D, 0x02, 0x45, 0xF0, 0x08, 0x05, 0x28, 0x46, 0xF2, 0xF7, 0xBA, 0xFD, 0x01, 0x28, 0x7F, 0xF4, 0x0B, 0xAF, 0x2A, 0x4B, ++0x27, 0x4A, 0x1B, 0x68, 0x07, 0xEB, 0x47, 0x01, 0x02, 0xEB, 0xC1, 0x02, 0x99, 0x6B, 0xD2, 0x7B, 0x4F, 0xEA, 0x98, 0x13, ++0x8B, 0x42, 0x28, 0xBF, 0x0B, 0x46, 0x9A, 0x42, 0x12, 0xD0, 0x28, 0x46, 0x04, 0x21, 0xF2, 0xF7, 0xFB, 0xFC, 0xE0, 0x79, ++0x39, 0x46, 0x00, 0xF0, 0x1D, 0xFA, 0x25, 0x23, 0xF1, 0xE6, 0x30, 0x46, 0x04, 0x21, 0xF2, 0xF7, 0xF1, 0xFC, 0xE0, 0x79, ++0x29, 0x46, 0x00, 0xF0, 0x13, 0xFA, 0xC3, 0xE6, 0x00, 0x23, 0xE6, 0xE6, 0xB9, 0xF8, 0x03, 0x30, 0x00, 0x2B, 0x7F, 0xF4, ++0x60, 0xAF, 0x18, 0x23, 0x03, 0xFB, 0x07, 0x23, 0xA9, 0x09, 0xDB, 0x7B, 0xB3, 0xEB, 0x95, 0x1F, 0x03, 0xD9, 0x18, 0x23, ++0x03, 0xFB, 0x07, 0x23, 0xD9, 0x73, 0x18, 0x23, 0x03, 0xFB, 0x07, 0x22, 0x05, 0xF0, 0x01, 0x05, 0x95, 0x74, 0xE0, 0x79, ++0x39, 0x46, 0x00, 0xF0, 0xD1, 0xF9, 0x40, 0x46, 0x03, 0x21, 0xF2, 0xF7, 0xCB, 0xFC, 0xA1, 0xE6, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0xB9, 0x34, 0x17, 0x00, 0xE4, 0xC1, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC0, 0xC1, 0x15, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0xA4, 0xC1, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x08, 0xC2, 0x15, 0x00, ++0x10, 0xB5, 0x10, 0x46, 0x14, 0x46, 0xF2, 0xF7, 0x57, 0xFD, 0x02, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x20, 0x0A, ++0x00, 0xF0, 0x1A, 0xF9, 0x20, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0xA4, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x10, 0x46, ++0x84, 0xB0, 0x14, 0x46, 0xF2, 0xF7, 0x44, 0xFD, 0x01, 0x28, 0x02, 0xD0, 0x00, 0x20, 0x04, 0xB0, 0x70, 0xBD, 0x20, 0x0A, ++0x13, 0x4A, 0x00, 0xEB, 0x40, 0x05, 0x52, 0xF8, 0x35, 0x60, 0x02, 0xEB, 0xC5, 0x05, 0x3E, 0xB9, 0x10, 0x4B, 0x6A, 0x68, ++0x19, 0x69, 0x6B, 0x89, 0x52, 0x1A, 0x12, 0xEB, 0x83, 0x23, 0x04, 0xD4, 0x00, 0xF0, 0x74, 0xF9, 0x00, 0x20, 0x04, 0xB0, ++0x70, 0xBD, 0x20, 0x46, 0x04, 0x21, 0x2C, 0x7B, 0xF2, 0xF7, 0x7C, 0xFC, 0x08, 0x4B, 0x02, 0x93, 0x27, 0x22, 0x01, 0x92, ++0x00, 0x96, 0x20, 0x46, 0x33, 0x46, 0x29, 0x46, 0x02, 0x22, 0xEE, 0x74, 0x00, 0xF0, 0xF8, 0xF9, 0xD4, 0xE7, 0x00, 0xBF, ++0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0xE5, 0xFE, 0x14, 0x00, 0x90, 0xF8, 0x46, 0x30, 0x90, 0xF8, 0x47, 0x20, ++0x19, 0x44, 0xB1, 0xFB, 0xF2, 0xF0, 0x02, 0xFB, 0x10, 0x10, 0x70, 0x47, 0x90, 0xF8, 0x46, 0x30, 0x90, 0xF8, 0x48, 0x00, ++0x19, 0x44, 0x08, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x03, 0x4B, 0x1B, 0x69, 0xA0, 0xEB, 0x93, 0x20, 0xC0, 0xF3, 0xC0, 0x30, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x70, 0xB5, 0x90, 0xF8, 0x46, 0x30, 0x03, 0x44, 0x9A, 0x79, 0x02, 0x2A, ++0x17, 0xD1, 0x00, 0x26, 0x04, 0x46, 0x35, 0x46, 0x9D, 0x71, 0xA3, 0x88, 0x22, 0x68, 0x01, 0x33, 0xC3, 0xF3, 0x0B, 0x03, ++0xA3, 0x80, 0x01, 0x21, 0x20, 0x46, 0x90, 0x47, 0x54, 0xFA, 0x80, 0xF3, 0x84, 0xF8, 0x46, 0x00, 0x9A, 0x79, 0x01, 0x36, ++0x02, 0x2A, 0x76, 0xB2, 0xEC, 0xD0, 0x30, 0x46, 0x70, 0xBD, 0x00, 0x26, 0x30, 0x46, 0x70, 0xBD, 0x38, 0xB5, 0x85, 0x88, ++0x03, 0x68, 0x49, 0x1B, 0xC1, 0xF3, 0x0B, 0x01, 0x04, 0x46, 0x15, 0x46, 0x98, 0x47, 0x20, 0x44, 0x85, 0x71, 0x38, 0xBD, ++0xF8, 0xB5, 0x05, 0x46, 0x33, 0x48, 0x6F, 0x6A, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0xC1, 0x00, 0xBF, 0x02, 0x44, 0x69, ++0x03, 0xD5, 0x11, 0x46, 0x4B, 0xB3, 0x00, 0x2A, 0x49, 0xD0, 0xA2, 0x88, 0x29, 0x8C, 0x23, 0x68, 0x89, 0x1A, 0xC1, 0xF3, ++0x0B, 0x01, 0x20, 0x46, 0x98, 0x47, 0x20, 0x44, 0x02, 0x23, 0x83, 0x71, 0x94, 0xF8, 0x46, 0x30, 0x23, 0x44, 0x00, 0x26, ++0x9A, 0x79, 0x02, 0x2A, 0x13, 0xD1, 0x35, 0x46, 0x9D, 0x71, 0xA3, 0x88, 0x22, 0x68, 0x01, 0x33, 0xC3, 0xF3, 0x0B, 0x03, ++0xA3, 0x80, 0x01, 0x21, 0x20, 0x46, 0x90, 0x47, 0x54, 0xFA, 0x80, 0xF3, 0x84, 0xF8, 0x46, 0x00, 0x9A, 0x79, 0x01, 0x36, ++0x02, 0x2A, 0x76, 0xB2, 0xEC, 0xD0, 0x30, 0x46, 0xF8, 0xBD, 0x00, 0x2A, 0xD5, 0xD1, 0x19, 0x4B, 0xB5, 0xF8, 0x40, 0x00, ++0x1B, 0x69, 0xA0, 0xEB, 0x93, 0x23, 0x1B, 0x04, 0xCD, 0xD4, 0xEA, 0x8B, 0xEB, 0x6C, 0x6F, 0xEA, 0x42, 0x42, 0x1C, 0x69, ++0x6F, 0xEA, 0x52, 0x42, 0xEA, 0x83, 0x44, 0xF0, 0x02, 0x04, 0x6A, 0x8F, 0x0E, 0x46, 0x29, 0x8F, 0x19, 0x80, 0x1C, 0x61, ++0xE9, 0x8F, 0xAC, 0x8F, 0x5A, 0x80, 0x2A, 0x8C, 0x1A, 0x81, 0x9C, 0x80, 0xD9, 0x80, 0x58, 0x81, 0xDB, 0xE7, 0x09, 0x48, ++0xB5, 0xF8, 0x40, 0x20, 0x03, 0x69, 0xA2, 0xEB, 0x93, 0x23, 0x1E, 0x04, 0xAD, 0xD4, 0x03, 0x69, 0x05, 0x48, 0xA2, 0xEB, ++0x93, 0x22, 0xC2, 0xF3, 0xC0, 0x32, 0xF4, 0xF7, 0x23, 0xF8, 0xA4, 0xE7, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x34, 0xC2, 0x15, 0x00, 0xF8, 0xB5, 0x0D, 0x4D, 0x0D, 0x4E, 0xFF, 0x27, 0x2F, 0x73, 0x00, 0x24, 0x08, 0xE0, 0x0F, 0x2C, ++0x85, 0xF8, 0x24, 0x70, 0x03, 0xDD, 0x4C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0xEB, 0x62, 0x18, 0x35, 0x20, 0x02, 0x00, 0xF4, ++0x7F, 0x40, 0x40, 0xF0, 0x08, 0x00, 0x01, 0x34, 0x00, 0x21, 0xF2, 0xF7, 0x95, 0xFB, 0x20, 0x2C, 0xEB, 0xD1, 0xF8, 0xBD, ++0xF4, 0xE4, 0x17, 0x00, 0x74, 0xDB, 0x17, 0x00, 0x11, 0x4B, 0x00, 0xEB, 0x40, 0x00, 0x03, 0xEB, 0xC0, 0x00, 0x42, 0x7B, ++0x03, 0x7B, 0x01, 0x7C, 0x72, 0xB1, 0x01, 0x2A, 0x0B, 0xD1, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x0B, 0x4A, ++0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA5, 0x21, 0x70, 0x47, 0x70, 0x47, 0x03, 0xEB, 0x83, 0x02, ++0xC3, 0xEB, 0x02, 0x13, 0x04, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA4, 0x21, 0x70, 0x47, ++0xF4, 0xE4, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x00, 0x28, 0x09, 0x4B, 0x14, 0xBF, 0x10, 0x20, 0x00, 0x20, 0x03, 0xEB, ++0x40, 0x03, 0x14, 0xBF, 0x20, 0x21, 0x10, 0x21, 0x33, 0xF8, 0x02, 0x2F, 0x22, 0xB1, 0x01, 0x30, 0x88, 0x42, 0xF9, 0xDB, ++0x21, 0x20, 0x70, 0x47, 0x80, 0xB2, 0x70, 0x47, 0xF2, 0xDF, 0x17, 0x00, 0x38, 0xB5, 0x05, 0x02, 0x45, 0xF0, 0x08, 0x05, ++0x04, 0x46, 0x29, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0xF2, 0xF7, 0x5A, 0xF8, 0x29, 0x46, 0x42, 0xF2, 0x01, 0x00, 0xF2, 0xF7, ++0x55, 0xF8, 0x16, 0x48, 0x04, 0xEB, 0x44, 0x04, 0x00, 0xEB, 0xC4, 0x04, 0x62, 0x7B, 0x23, 0x7B, 0x21, 0x7C, 0x92, 0xB1, ++0x01, 0x2A, 0x0A, 0xD1, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x0F, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, ++0x21, 0x22, 0x83, 0xF8, 0xA5, 0x21, 0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x38, 0x40, 0xF2, 0xF7, 0x25, 0xBB, 0x03, 0xEB, ++0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x07, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA4, 0x21, ++0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x38, 0x40, 0xF2, 0xF7, 0x14, 0xBB, 0xF4, 0xE4, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x07, 0x4B, 0x00, 0xEB, 0x40, 0x02, 0x03, 0xEB, 0xC2, 0x03, 0x00, 0x02, 0x5A, 0x89, 0x00, 0xF4, 0x7F, 0x41, 0x41, 0xF0, ++0x08, 0x01, 0x92, 0x02, 0x42, 0xF2, 0x01, 0x00, 0xF1, 0xF7, 0x64, 0xBF, 0xF4, 0xE4, 0x17, 0x00, 0x0A, 0x02, 0x02, 0xF4, ++0x7F, 0x42, 0x38, 0xB5, 0x42, 0xF0, 0x08, 0x02, 0x05, 0x46, 0x0C, 0x46, 0x06, 0x23, 0x00, 0x21, 0x28, 0x20, 0xF2, 0xF7, ++0xF7, 0xF8, 0x0A, 0x49, 0x04, 0xEB, 0x44, 0x04, 0x01, 0xEB, 0xC4, 0x04, 0x62, 0x7B, 0x45, 0x70, 0x01, 0x3A, 0x18, 0xBF, ++0x01, 0x22, 0x02, 0x70, 0x22, 0x7C, 0x82, 0x70, 0xE2, 0x7B, 0xC2, 0x70, 0x22, 0x89, 0x82, 0x80, 0xBD, 0xE8, 0x38, 0x40, ++0xF2, 0xF7, 0x12, 0xB9, 0xF4, 0xE4, 0x17, 0x00, 0xF8, 0xB5, 0x0D, 0x02, 0x45, 0xF0, 0x08, 0x05, 0xAD, 0xB2, 0x03, 0x23, ++0x0C, 0x46, 0x07, 0x46, 0x2A, 0x46, 0x00, 0x21, 0x2A, 0x20, 0xF2, 0xF7, 0xD3, 0xF8, 0x12, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x06, 0x46, 0x11, 0xDB, 0x0F, 0x49, 0x04, 0xEB, 0x44, 0x04, 0x01, 0xEB, 0xC4, 0x04, 0x30, 0x46, ++0x63, 0x7B, 0x77, 0x70, 0x01, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0x33, 0x70, 0x23, 0x7C, 0xB3, 0x70, 0xBD, 0xE8, 0xF8, 0x40, ++0xF2, 0xF7, 0xEA, 0xB8, 0x28, 0x46, 0xF2, 0xF7, 0x59, 0xFB, 0x04, 0x28, 0xE8, 0xD0, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, ++0x05, 0x22, 0xF4, 0xF7, 0x91, 0xF9, 0xE1, 0xE7, 0x38, 0x36, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x60, 0xC2, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x10, 0x4E, 0x11, 0x4D, 0x80, 0x46, 0x87, 0xB2, 0x00, 0x24, 0x36, 0xF8, ++0x02, 0x3F, 0x8B, 0xB1, 0x2B, 0x7B, 0x43, 0x45, 0x0E, 0xD1, 0x1F, 0xFA, 0x84, 0xF9, 0x4F, 0xEA, 0x09, 0x23, 0x03, 0xF4, ++0x7F, 0x43, 0x43, 0xF0, 0x08, 0x00, 0x04, 0x21, 0xF2, 0xF7, 0x88, 0xFA, 0x49, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xAA, 0xFF, ++0x01, 0x34, 0x20, 0x2C, 0x05, 0xF1, 0x18, 0x05, 0xE5, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0xF2, 0xDF, 0x17, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0xB0, 0xDF, 0xF8, 0x50, 0x92, 0xBD, 0xF8, 0x50, 0x40, 0x09, 0x94, ++0xBD, 0xF8, 0x54, 0x40, 0x07, 0x94, 0x16, 0x9C, 0x04, 0x94, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x94, 0x87, 0x4F, ++0x94, 0xF8, 0x22, 0x80, 0xDF, 0xF8, 0x30, 0xA2, 0x03, 0x91, 0x06, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x08, 0x70, ++0x93, 0x46, 0x00, 0x6C, 0x08, 0x93, 0x00, 0x28, 0x00, 0xF0, 0xC4, 0x80, 0xDA, 0xF8, 0x00, 0x30, 0x02, 0x79, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9B, 0x80, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x73, 0x4F, 0xF4, 0xC0, 0x71, ++0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xDF, 0xF7, 0x14, 0xFB, 0x04, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0x9B, 0x80, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x08, 0xF5, 0x78, 0x19, 0x21, 0x46, 0x05, 0x90, 0xF1, 0xF7, ++0x05, 0xFC, 0x4F, 0xF4, 0x1E, 0x72, 0xA3, 0x6C, 0x02, 0xFB, 0x06, 0xF2, 0x00, 0x21, 0x26, 0x32, 0x6F, 0xF0, 0x2F, 0x0C, ++0x83, 0xF8, 0x68, 0xC0, 0x83, 0xF8, 0x69, 0x10, 0x83, 0xF8, 0x6A, 0x10, 0x83, 0xF8, 0x6B, 0x10, 0x39, 0xF8, 0x02, 0x10, ++0xA3, 0xF8, 0x6C, 0x10, 0x09, 0xEB, 0x02, 0x01, 0x5C, 0x35, 0xB1, 0xF8, 0x02, 0xC0, 0xA3, 0xF8, 0x6E, 0xC0, 0xB1, 0xF8, ++0x04, 0xC0, 0xA3, 0xF8, 0x70, 0xC0, 0x37, 0xF8, 0x05, 0xC0, 0xA3, 0xF8, 0x72, 0xC0, 0x07, 0xEB, 0x05, 0x0C, 0x03, 0xF1, ++0x68, 0x00, 0xBC, 0xF8, 0x02, 0xE0, 0xA3, 0xF8, 0x74, 0xE0, 0xBC, 0xF8, 0x04, 0xE0, 0x06, 0x90, 0x05, 0x98, 0xA3, 0xF8, ++0x76, 0xE0, 0x90, 0xF8, 0x62, 0x00, 0x02, 0x28, 0x5E, 0xD0, 0x39, 0xF8, 0x02, 0x20, 0xA3, 0xF8, 0x78, 0x20, 0x4A, 0x88, ++0xA3, 0xF8, 0x7A, 0x20, 0x8A, 0x88, 0xA3, 0xF8, 0x7C, 0x20, 0x4E, 0x49, 0xB1, 0xF8, 0xFC, 0x21, 0x01, 0x32, 0x92, 0xB2, ++0xA1, 0xF8, 0xFC, 0x21, 0x10, 0x01, 0x00, 0x21, 0xA3, 0xF8, 0x7E, 0x00, 0x03, 0x22, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, ++0x35, 0x10, 0x84, 0xF8, 0x1C, 0x80, 0x66, 0x77, 0xD0, 0x21, 0x20, 0x46, 0x00, 0xF0, 0xE6, 0xFB, 0x01, 0x28, 0x70, 0xD0, ++0x18, 0x25, 0xBB, 0xF1, 0x01, 0x0F, 0x4A, 0xD0, 0xBB, 0xF1, 0x02, 0x0F, 0x54, 0xD0, 0xBB, 0xF1, 0x00, 0x0F, 0x5C, 0xD0, ++0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x69, 0xDB, 0x03, 0x26, 0xE1, 0x6C, 0x94, 0xF8, 0x35, 0x30, ++0x4A, 0x6A, 0x1D, 0x44, 0x01, 0x3A, 0x04, 0x9B, 0x2A, 0x44, 0x04, 0x35, 0xC1, 0xE9, 0x0A, 0x25, 0x13, 0xB1, 0x63, 0x65, ++0x03, 0x9B, 0xA3, 0x65, 0x31, 0x46, 0x20, 0x46, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xDF, 0xF7, 0x97, 0xBA, 0x02, 0x2A, ++0x7F, 0xF4, 0x62, 0xAF, 0x2D, 0x49, 0x2E, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0xF4, 0xF7, 0x92, 0xF8, 0x01, 0x20, 0x4F, 0xF4, ++0xC0, 0x71, 0xDF, 0xF7, 0x79, 0xFA, 0x04, 0x46, 0x00, 0x28, 0x7F, 0xF4, 0x65, 0xAF, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x7A, 0x5B, 0xA3, 0xF8, 0x78, 0x20, 0xBC, 0xF8, 0x02, 0x20, 0xA3, 0xF8, 0x7A, 0x20, 0xBC, 0xF8, 0x04, 0x20, 0xA3, 0xF8, ++0x7C, 0x20, 0x9E, 0xE7, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE1, 0xDA, 0xDA, 0xE7, 0x06, 0x99, ++0x07, 0x9B, 0x00, 0x93, 0x29, 0x44, 0x08, 0x46, 0xDD, 0xE9, 0x08, 0x32, 0x03, 0x99, 0xF5, 0xF7, 0x4D, 0xFA, 0x03, 0x26, ++0x05, 0x44, 0xB4, 0xE7, 0xDD, 0xE9, 0x06, 0x02, 0x03, 0x99, 0x15, 0x4E, 0x0B, 0x7C, 0x28, 0x44, 0xF6, 0x5C, 0xF5, 0xF7, ++0x5D, 0xFA, 0x05, 0x44, 0xA9, 0xE7, 0x03, 0x99, 0x06, 0x98, 0x10, 0x4A, 0x0B, 0x7C, 0x28, 0x44, 0xD6, 0x5C, 0xF5, 0xF7, ++0x1B, 0xFA, 0x05, 0x44, 0x9F, 0xE7, 0x06, 0x99, 0x18, 0x22, 0x20, 0x46, 0xFF, 0xF7, 0xD2, 0xF9, 0x94, 0xF8, 0x33, 0x50, ++0x18, 0x35, 0x86, 0xE7, 0x05, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x6E, 0x22, 0xF4, 0xF7, 0x5A, 0xF8, 0x03, 0x26, 0x8E, 0xE7, ++0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0xC0, 0xB2, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x35, 0x4B, 0x87, 0xB0, ++0x81, 0x46, 0x8A, 0x46, 0x93, 0x46, 0x10, 0x24, 0x33, 0xF8, 0x02, 0x5F, 0x35, 0xB1, 0x01, 0x34, 0x20, 0x2C, 0xF9, 0xD1, ++0x03, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2E, 0x4A, 0xDF, 0xF8, 0xCC, 0x80, 0x04, 0xEB, 0x44, 0x03, 0x02, 0xEB, ++0xC3, 0x06, 0xDB, 0x00, 0x86, 0xF8, 0x0C, 0x90, 0x86, 0xF8, 0x10, 0xA0, 0x05, 0x93, 0x06, 0xF0, 0xBB, 0xFB, 0x28, 0x49, ++0x70, 0x74, 0x09, 0x68, 0x27, 0x48, 0xB1, 0xF8, 0x02, 0xC0, 0x10, 0xF8, 0x0A, 0x00, 0x05, 0x9B, 0x25, 0x49, 0x22, 0x4A, ++0x02, 0x95, 0x09, 0xEB, 0x89, 0x07, 0xC9, 0xEB, 0x07, 0x17, 0x57, 0x44, 0x00, 0x95, 0x34, 0x37, 0x51, 0xF8, 0x20, 0xE0, ++0xD5, 0x50, 0x08, 0xEB, 0xC7, 0x00, 0x27, 0x23, 0x01, 0x93, 0xA6, 0xF8, 0x0A, 0xC0, 0x4F, 0xF0, 0x01, 0x0C, 0x86, 0xF8, ++0x0F, 0xE0, 0x86, 0xF8, 0x0E, 0xC0, 0x86, 0xF8, 0x0D, 0xC0, 0x31, 0x46, 0x2B, 0x46, 0x44, 0x71, 0xA6, 0xF8, 0x08, 0xB0, ++0x48, 0x46, 0x02, 0x22, 0xFF, 0xF7, 0x82, 0xFE, 0x24, 0x02, 0x31, 0x46, 0x48, 0x46, 0x2B, 0x46, 0x2A, 0x46, 0xCD, 0xE9, ++0x01, 0x55, 0x00, 0x95, 0xFF, 0xF7, 0x78, 0xFE, 0x44, 0xF0, 0x08, 0x04, 0x0E, 0x4B, 0xA4, 0xB2, 0x1B, 0x69, 0x48, 0xF8, ++0x37, 0x30, 0x21, 0x46, 0x4F, 0xF4, 0xFA, 0x22, 0x4F, 0xF4, 0x00, 0x50, 0xF1, 0xF7, 0x46, 0xFD, 0x20, 0x46, 0x02, 0x21, ++0xF2, 0xF7, 0xDE, 0xF8, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0xE0, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, ++0xC8, 0x35, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0x7C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x19, 0x4C, 0x1A, 0x4D, 0xDF, 0xF8, 0x68, 0xA0, 0xC4, 0xEB, 0x44, 0x29, 0x4F, 0xEA, 0xC9, 0x19, ++0x84, 0xB0, 0x07, 0x46, 0x1F, 0xFA, 0x89, 0xF9, 0x04, 0xF1, 0x40, 0x06, 0x4F, 0xF0, 0x00, 0x08, 0x34, 0xF8, 0x02, 0x3F, ++0xCB, 0xB1, 0x2B, 0x7B, 0xBB, 0x42, 0x16, 0xD1, 0x09, 0xEB, 0xC4, 0x10, 0xA0, 0xF5, 0x80, 0x70, 0x40, 0xF0, 0x08, 0x00, ++0x80, 0xB2, 0x04, 0x21, 0xF2, 0xF7, 0xAA, 0xF8, 0x27, 0x23, 0xCD, 0xE9, 0x00, 0x83, 0xCD, 0xF8, 0x08, 0xA0, 0x00, 0x23, ++0x02, 0x22, 0x29, 0x46, 0x38, 0x46, 0x85, 0xF8, 0x13, 0x80, 0xFF, 0xF7, 0x25, 0xFE, 0xB4, 0x42, 0x05, 0xF1, 0x18, 0x05, ++0xDE, 0xD1, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xF2, 0xDF, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0xE5, 0xFE, 0x14, 0x00, ++0xFF, 0x29, 0x2F, 0xD0, 0xF8, 0xB5, 0xC3, 0xB2, 0x03, 0xEB, 0x83, 0x02, 0x16, 0x4F, 0xC3, 0xEB, 0x02, 0x13, 0x53, 0xFA, ++0x81, 0xF3, 0x07, 0xEB, 0xC3, 0x03, 0x0C, 0x46, 0x93, 0xF8, 0xA5, 0x61, 0x21, 0x2E, 0x05, 0x46, 0x1C, 0xD0, 0x30, 0x02, ++0x40, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0x20, 0xF9, 0x01, 0x28, 0x15, 0xD1, 0x0D, 0x4B, 0x06, 0xEB, 0x46, 0x06, 0x03, 0xEB, ++0xC6, 0x06, 0x4F, 0xF4, 0x9E, 0x71, 0x01, 0xFB, 0x05, 0x44, 0x73, 0x69, 0x07, 0xEB, 0x44, 0x04, 0x9A, 0x88, 0xB4, 0xF8, ++0x34, 0x31, 0x9B, 0x1A, 0x13, 0xF4, 0x7C, 0x6F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xF8, 0xBD, 0x01, 0x20, 0xF8, 0xBD, ++0x02, 0x20, 0x70, 0x47, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x04, 0x46, 0x50, 0x48, ++0xE1, 0x7E, 0xD0, 0xF8, 0x10, 0x90, 0xFF, 0x29, 0x23, 0xD0, 0x65, 0x7F, 0x4D, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x05, 0x63, 0x5A, 0x68, 0x97, 0x07, 0x1A, 0xD5, 0x05, 0xEB, 0x85, 0x07, 0xC5, 0xEB, 0x07, 0x17, 0x7A, 0x18, 0x34, 0x32, ++0x06, 0xEB, 0xC2, 0x0C, 0x9C, 0xF8, 0x07, 0xE0, 0x9C, 0xF8, 0x05, 0x80, 0x0E, 0xF1, 0x01, 0x0E, 0xB8, 0xF1, 0x21, 0x0F, ++0x8C, 0xF8, 0x07, 0xE0, 0x09, 0xD1, 0x00, 0x69, 0x56, 0xF8, 0x32, 0x20, 0xDF, 0xF8, 0x14, 0xC1, 0x82, 0x1A, 0x62, 0x45, ++0x48, 0xD8, 0xBD, 0xE8, 0xF0, 0x87, 0xDF, 0xF8, 0x0C, 0xA1, 0x08, 0xEB, 0x48, 0x07, 0x0A, 0xEB, 0xC7, 0x07, 0x4F, 0xEA, ++0x08, 0x20, 0xC7, 0xF8, 0x04, 0x90, 0x40, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0xC3, 0xF8, 0x01, 0x28, 0x4F, 0xEA, 0x48, 0x09, ++0xEB, 0xD1, 0x7F, 0x69, 0xE3, 0x8B, 0xB8, 0x88, 0x60, 0x84, 0xD9, 0x07, 0x57, 0xD4, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, ++0x05, 0x65, 0xD5, 0xF8, 0x4C, 0x21, 0x92, 0xF8, 0xA2, 0x20, 0x52, 0x07, 0x03, 0xD5, 0x62, 0x6A, 0x42, 0xF4, 0x00, 0x12, ++0x62, 0x62, 0x21, 0x8C, 0x3A, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x09, 0x1A, 0xE3, 0x83, 0xC1, 0xF3, 0x0B, 0x01, 0x38, 0x46, ++0x90, 0x47, 0x38, 0x44, 0x01, 0x23, 0x83, 0x71, 0xE3, 0x8B, 0xDB, 0x07, 0x07, 0xD4, 0x1F, 0x4A, 0x20, 0x4B, 0x12, 0x69, ++0x9B, 0x8D, 0x03, 0xEB, 0x92, 0x23, 0xA4, 0xF8, 0x40, 0x30, 0xC8, 0x44, 0x4F, 0xEA, 0xC8, 0x08, 0x5A, 0xF8, 0x08, 0x30, ++0x01, 0x33, 0x4A, 0xF8, 0x08, 0x30, 0xB6, 0xE7, 0x93, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0xB2, 0xD0, 0x17, 0x4B, 0x18, 0x48, ++0x5A, 0x5C, 0x54, 0x23, 0x03, 0xFB, 0x02, 0xF3, 0xC3, 0x58, 0x00, 0x2B, 0xA9, 0xD1, 0x15, 0x4B, 0x53, 0xF8, 0x32, 0x30, ++0x00, 0x2B, 0xA4, 0xD1, 0xBB, 0x18, 0x46, 0x33, 0x56, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x9E, 0xD1, 0x23, 0x7F, 0x10, 0x48, ++0xA4, 0x26, 0x06, 0xFB, 0x03, 0x23, 0x9E, 0x33, 0x50, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x94, 0xD1, 0x0C, 0x4B, 0x22, 0x8C, ++0x1B, 0x6A, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x03, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0x89, 0xD1, 0xA2, 0xE7, ++0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x24, 0x64, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x40, 0x42, 0x0F, 0x00, 0xF4, 0xE4, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x1C, 0x48, 0x6C, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x03, 0x5E, 0x68, ++0xB6, 0x07, 0x0E, 0xD5, 0xEB, 0x7E, 0x04, 0xEB, 0x84, 0x06, 0xC4, 0xEB, 0x06, 0x14, 0x1C, 0x44, 0x34, 0x34, 0x00, 0xEB, ++0xC4, 0x04, 0xE3, 0x79, 0x01, 0x3B, 0xE3, 0x71, 0xEB, 0x8B, 0x9B, 0x07, 0x02, 0xD4, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, ++0x66, 0x79, 0x21, 0x2E, 0xF9, 0xD0, 0x30, 0x02, 0x40, 0xF0, 0x08, 0x00, 0x88, 0x46, 0x91, 0x46, 0xF2, 0xF7, 0x20, 0xF8, ++0x01, 0x28, 0xF0, 0xD1, 0x06, 0xEB, 0x46, 0x07, 0xFF, 0x00, 0xDF, 0xF8, 0x20, 0xC0, 0x5C, 0xF8, 0x07, 0x40, 0x01, 0x3C, ++0x4C, 0xF8, 0x07, 0x40, 0x4B, 0x46, 0x42, 0x46, 0x28, 0x46, 0x31, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x46, 0xBB, ++0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x38, 0xB5, 0x45, 0x69, 0x04, 0x46, 0x40, 0x22, 0x00, 0x21, 0xA8, 0x1D, ++0xCF, 0xF7, 0x58, 0xF9, 0x22, 0x7B, 0x21, 0x7C, 0x0C, 0x4B, 0x4F, 0xF4, 0x9E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x03, 0xEB, ++0x42, 0x03, 0x00, 0x22, 0xB3, 0xF8, 0x34, 0x31, 0xAB, 0x80, 0x85, 0xF8, 0x46, 0x20, 0xE3, 0x7B, 0x85, 0xF8, 0x47, 0x30, ++0x5A, 0x1E, 0x1A, 0x42, 0x12, 0xBF, 0x04, 0x4B, 0x04, 0x4B, 0x85, 0xF8, 0x48, 0x20, 0x2B, 0x60, 0x38, 0xBD, 0x00, 0xBF, ++0x68, 0x65, 0x17, 0x00, 0xDD, 0x04, 0x15, 0x00, 0xF1, 0x04, 0x15, 0x00, 0x90, 0xF8, 0x47, 0x10, 0x59, 0xB1, 0x43, 0x1D, ++0x19, 0x44, 0x00, 0x20, 0x13, 0xF8, 0x01, 0x2F, 0x02, 0x2A, 0x04, 0xBF, 0x01, 0x30, 0x40, 0xB2, 0x8B, 0x42, 0xF7, 0xD1, ++0x70, 0x47, 0x08, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x11, 0x4A, 0x12, 0x4B, 0x12, 0x68, 0x10, 0xB5, 0x00, 0xEB, 0x80, 0x04, ++0xC0, 0xEB, 0x04, 0x10, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x90, 0xF8, 0xA4, 0x41, 0x00, 0x2B, ++0x08, 0xDB, 0x0B, 0x4B, 0x0B, 0x4A, 0x04, 0xEB, 0x44, 0x04, 0x03, 0xEB, 0xC4, 0x04, 0x13, 0x69, 0x63, 0x60, 0x10, 0xBD, ++0x20, 0x2C, 0xF4, 0xD9, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x52, 0x32, 0xF3, 0xF7, 0xEA, 0xFD, 0xED, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x9C, 0xC2, 0x15, 0x00, 0x10, 0xF0, 0x0C, 0x0F, 0x11, 0xD1, 0x00, 0xF0, 0xF0, 0x03, 0xC0, 0x2B, 0x0B, 0xD0, 0xD0, 0x2B, ++0x05, 0xD0, 0xA3, 0xF1, 0xA0, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x0F, 0x29, 0x24, 0xD8, 0x03, 0x29, ++0x03, 0xD8, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x04, 0x39, 0x0B, 0x29, 0xF8, 0xD8, 0x01, 0xA3, 0x53, 0xF8, ++0x21, 0xF0, 0x00, 0xBF, 0xEF, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, ++0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, ++0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, 0xB1, 0xF1, 0x7F, 0x00, 0x18, 0xBF, 0x01, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x08, 0xB0, 0xB0, 0xF8, 0x00, 0x90, 0x1B, 0xF8, 0x01, 0xA0, ++0x0C, 0x46, 0x85, 0xB0, 0x80, 0x46, 0x51, 0x46, 0x48, 0x46, 0x1D, 0x46, 0xFF, 0xF7, 0xB4, 0xFF, 0x0B, 0xEB, 0x04, 0x0C, ++0x00, 0x28, 0x00, 0xF0, 0x81, 0x80, 0x98, 0xF8, 0x09, 0x30, 0xFF, 0x2B, 0x24, 0xD0, 0x98, 0xF8, 0x0A, 0x70, 0xFF, 0x2F, ++0x20, 0xD0, 0x50, 0x49, 0x16, 0x46, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x12, 0xD2, 0xF8, 0xA8, 0x24, 0x00, 0x2A, ++0x6E, 0xD0, 0x98, 0xF8, 0x30, 0x20, 0x12, 0x07, 0x6E, 0xD5, 0x09, 0xF0, 0xFC, 0x03, 0xD0, 0x2B, 0x00, 0xF0, 0x84, 0x80, ++0x46, 0x4B, 0x4F, 0xF4, 0xA4, 0x68, 0x08, 0xFB, 0x07, 0xF8, 0x43, 0x44, 0xD3, 0xF8, 0xAC, 0x34, 0x00, 0x2B, 0x5B, 0xD0, ++0x0B, 0xF1, 0x13, 0x03, 0xB3, 0x42, 0x05, 0xDB, 0x00, 0x23, 0x01, 0x20, 0x2B, 0x70, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0xB1, 0x1E, 0xA1, 0xEB, 0x0B, 0x01, 0x0C, 0xF1, 0x02, 0x00, 0x89, 0xB2, 0xF2, 0xF7, 0x3A, 0xFC, 0x1F, 0xFA, 0x8B, 0xF3, ++0x00, 0x28, 0xED, 0xD0, 0xB0, 0xF8, 0x02, 0xC0, 0xAC, 0xF1, 0x04, 0x02, 0x01, 0x2A, 0xE7, 0xD8, 0x33, 0x4A, 0xCC, 0xEB, ++0x0C, 0x11, 0x08, 0xEB, 0xC1, 0x01, 0x11, 0x44, 0x4F, 0xEA, 0x0C, 0x12, 0x03, 0x92, 0x91, 0xF8, 0x3B, 0x22, 0x00, 0x2A, ++0xDA, 0xD0, 0xD1, 0xE9, 0x76, 0xAB, 0x42, 0x68, 0x4F, 0xF0, 0x00, 0x0E, 0x22, 0xF0, 0x7F, 0x48, 0xF3, 0x45, 0x08, 0xBF, ++0xC2, 0x45, 0xF1, 0x46, 0xCE, 0xD2, 0x82, 0x46, 0xDD, 0xF8, 0x0C, 0xB0, 0x5A, 0xF8, 0x0A, 0x2F, 0x00, 0x92, 0xDA, 0xF8, ++0x04, 0x20, 0x01, 0x92, 0xC1, 0xE9, 0x76, 0x89, 0x12, 0x30, 0x52, 0x46, 0x02, 0xF8, 0x01, 0xEB, 0x82, 0x42, 0xFB, 0xD1, ++0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x07, 0xF0, 0xAB, 0xEB, 0x0C, 0x0C, 0x21, 0x46, 0x00, 0xF5, 0xEC, 0x70, 0x1A, 0x4C, ++0x00, 0xEB, 0xCC, 0x00, 0x20, 0x44, 0x32, 0x46, 0x00, 0xF0, 0xD2, 0xFA, 0xDD, 0xE9, 0x00, 0x34, 0x8C, 0x42, 0x08, 0xBF, ++0x83, 0x42, 0xA7, 0xD1, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x4A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x03, 0x23, 0x5B, 0x68, 0x1B, 0x07, 0xF3, 0xD5, 0x19, 0xF4, 0x80, 0x4F, 0xF0, 0xD1, 0x09, 0xF0, 0xFC, 0x09, 0xB9, 0xF1, ++0xC0, 0x0F, 0x02, 0xD0, 0xB9, 0xF1, 0xA0, 0x0F, 0x90, 0xD1, 0xAA, 0xF1, 0x06, 0x01, 0x01, 0x29, 0x8C, 0xD8, 0x01, 0x20, ++0x28, 0x70, 0xE2, 0xE7, 0xAA, 0xF1, 0x0D, 0x01, 0x01, 0x29, 0x3F, 0xF6, 0x77, 0xAF, 0x89, 0xF4, 0x80, 0x40, 0xC0, 0xF3, ++0x80, 0x30, 0xD8, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x45, 0x7F, 0x06, 0x7F, 0xFF, 0x2D, ++0x2B, 0xD0, 0x19, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x06, 0x73, 0xD3, 0xF8, 0xA8, 0x04, 0xE0, 0xB1, 0x0C, 0x46, ++0x20, 0x46, 0x11, 0x46, 0xFF, 0xF7, 0xF0, 0xFE, 0xB0, 0xB1, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0xF5, 0x11, 0x4B, ++0xE8, 0x5C, 0x10, 0xF0, 0x01, 0x00, 0x0E, 0xD0, 0x04, 0xF0, 0xFC, 0x04, 0xD0, 0x2C, 0x12, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x06, 0x76, 0xD6, 0xF8, 0xAC, 0x34, 0x00, 0x2B, 0x0C, 0xBF, 0x00, 0x20, 0x02, 0x20, 0xF8, 0xBD, 0x1D, 0x44, ++0x55, 0xF8, 0x22, 0x0C, 0xC0, 0xF3, 0xC0, 0x00, 0xF8, 0xBD, 0x00, 0x20, 0xF8, 0xBD, 0x0D, 0x3A, 0x01, 0x2A, 0xE9, 0xD8, ++0xF2, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x8E, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x2A, 0x4C, 0x03, 0x7F, 0x4F, 0xF4, ++0xA4, 0x60, 0x00, 0xFB, 0x03, 0x43, 0x02, 0xEB, 0x01, 0x0C, 0xD3, 0xF8, 0xAC, 0x04, 0x00, 0x28, 0x47, 0xD0, 0x4C, 0x23, ++0x53, 0x54, 0x10, 0x23, 0x8C, 0xF8, 0x01, 0x30, 0xD0, 0xE9, 0x12, 0x37, 0x01, 0x33, 0x90, 0xF8, 0x61, 0x40, 0xAC, 0xF8, ++0x02, 0x40, 0x47, 0xF1, 0x00, 0x07, 0xC0, 0xE9, 0x12, 0x37, 0x0C, 0xF1, 0x04, 0x0E, 0x00, 0x24, 0x01, 0xE0, 0xD0, 0xE9, ++0x12, 0x37, 0xC4, 0xF1, 0x20, 0x06, 0xE3, 0x40, 0xA4, 0xF1, 0x20, 0x05, 0x07, 0xFA, 0x06, 0xF6, 0x33, 0x43, 0x27, 0xFA, ++0x05, 0xF5, 0x08, 0x34, 0x2B, 0x43, 0x30, 0x2C, 0x0E, 0xF8, 0x01, 0x3B, 0xED, 0xD1, 0x0C, 0xF1, 0x0A, 0x06, 0x0C, 0xF1, ++0x12, 0x04, 0x33, 0x46, 0x00, 0x25, 0x03, 0xF8, 0x01, 0x5B, 0xA3, 0x42, 0xFB, 0xD1, 0x12, 0x32, 0x18, 0x23, 0x92, 0xB2, ++0x00, 0xF0, 0x22, 0xFA, 0x00, 0x23, 0xC3, 0xF1, 0x20, 0x05, 0x20, 0xFA, 0x03, 0xF2, 0xA3, 0xF1, 0x20, 0x04, 0x01, 0xFA, ++0x05, 0xF5, 0x2A, 0x43, 0x21, 0xFA, 0x04, 0xF4, 0x08, 0x33, 0x22, 0x43, 0x40, 0x2B, 0x06, 0xF8, 0x01, 0x2B, 0xEE, 0xD1, ++0x12, 0x20, 0xF8, 0xBD, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x0A, 0x68, 0x05, 0x68, 0x4B, 0x68, 0xAE, 0x4C, ++0xDF, 0xF8, 0xBC, 0x82, 0x8F, 0xB0, 0x0E, 0x46, 0x6A, 0x40, 0x01, 0x92, 0x32, 0x46, 0x07, 0x46, 0x0D, 0x90, 0xF0, 0x68, ++0x01, 0x9E, 0x04, 0x91, 0x89, 0x68, 0x16, 0x60, 0x7E, 0x68, 0x07, 0x97, 0x83, 0xEA, 0x06, 0x05, 0x55, 0x60, 0x13, 0x46, ++0xBA, 0x68, 0x00, 0x95, 0x81, 0xEA, 0x02, 0x09, 0xC3, 0xF8, 0x08, 0x90, 0xFB, 0x68, 0xCD, 0xF8, 0x0C, 0x90, 0x43, 0x40, ++0x02, 0x93, 0x07, 0xF1, 0x90, 0x03, 0x0C, 0x93, 0x00, 0x9E, 0x01, 0x98, 0x02, 0x99, 0x03, 0x9D, 0xF3, 0xB2, 0x5F, 0xFA, ++0x80, 0xFC, 0xC6, 0xF3, 0x07, 0x2A, 0x4F, 0xEA, 0x10, 0x69, 0xE0, 0x5C, 0x06, 0x90, 0x0A, 0x0E, 0x96, 0x48, 0x08, 0x93, ++0x14, 0xF8, 0x0A, 0x30, 0x87, 0x5C, 0x18, 0xF8, 0x02, 0x10, 0x05, 0x93, 0xC5, 0xF3, 0x07, 0x26, 0xA3, 0x5C, 0x03, 0x9A, ++0x0A, 0x97, 0xC2, 0xF3, 0x07, 0x4E, 0xA7, 0x5D, 0x10, 0xF8, 0x0E, 0x20, 0x18, 0xF8, 0x09, 0xB0, 0x14, 0xF8, 0x0C, 0x50, ++0x38, 0x46, 0x06, 0x9F, 0x09, 0x90, 0x87, 0xEA, 0x0B, 0x0B, 0x05, 0x9F, 0x80, 0xEA, 0x0B, 0x0B, 0x69, 0x40, 0x87, 0x48, ++0x79, 0x40, 0x51, 0x40, 0x10, 0xF8, 0x0A, 0x20, 0x5D, 0x40, 0x6A, 0x40, 0x18, 0xF8, 0x0E, 0x50, 0x14, 0xF8, 0x0E, 0xE0, ++0x6A, 0x40, 0x09, 0x04, 0x41, 0xEA, 0x02, 0x21, 0x7F, 0x4A, 0x02, 0x9D, 0x12, 0xF8, 0x0C, 0x20, 0x5F, 0x46, 0x18, 0xF8, ++0x0A, 0xB0, 0x14, 0xF8, 0x09, 0xA0, 0x10, 0xF8, 0x09, 0x90, 0xCD, 0xF8, 0x2C, 0x90, 0x53, 0x40, 0xC5, 0xF3, 0x07, 0x49, ++0x06, 0x98, 0x18, 0xF8, 0x0C, 0x50, 0x76, 0x4A, 0x83, 0xEA, 0x0B, 0x0B, 0x0A, 0x9B, 0x18, 0xF8, 0x06, 0xC0, 0x5D, 0x40, ++0x12, 0xF8, 0x09, 0x30, 0x92, 0x5D, 0x71, 0x4E, 0x8A, 0xEA, 0x00, 0x00, 0x50, 0x40, 0x08, 0x9A, 0xB6, 0x5C, 0x18, 0xF8, ++0x02, 0x20, 0x8A, 0xEA, 0x06, 0x0A, 0x7B, 0x40, 0x0B, 0x9E, 0x05, 0x9F, 0x8A, 0xEA, 0x0C, 0x0A, 0x18, 0xF8, 0x09, 0xC0, ++0x14, 0xF8, 0x09, 0x90, 0x8E, 0xEA, 0x05, 0x05, 0x56, 0x40, 0x7D, 0x40, 0x1B, 0x04, 0x09, 0x9F, 0x80, 0xEA, 0x0C, 0x00, ++0x8E, 0xEA, 0x0B, 0x0B, 0x43, 0xEA, 0x00, 0x20, 0x89, 0xEA, 0x06, 0x03, 0x41, 0xEA, 0x0B, 0x02, 0x02, 0x99, 0x00, 0x9E, ++0x83, 0xEA, 0x07, 0x0B, 0x03, 0x9B, 0x89, 0xEA, 0x0A, 0x0A, 0x40, 0xEA, 0x0A, 0x0C, 0x5F, 0xFA, 0x83, 0xFE, 0x4F, 0xEA, ++0x13, 0x69, 0xC1, 0xF3, 0x07, 0x20, 0xCB, 0xB2, 0x01, 0x99, 0x02, 0x93, 0x42, 0xEA, 0x05, 0x67, 0x04, 0x9A, 0x03, 0x97, ++0xC1, 0xF3, 0x07, 0x4A, 0x4C, 0xEA, 0x0B, 0x65, 0x17, 0x60, 0x27, 0x5C, 0x55, 0x60, 0x36, 0x0E, 0x05, 0x95, 0x01, 0x97, ++0x4F, 0x4D, 0x14, 0xF8, 0x0A, 0x70, 0x06, 0x97, 0x18, 0xF8, 0x0A, 0x70, 0x15, 0xF8, 0x00, 0xB0, 0xA2, 0x5D, 0x18, 0xF8, ++0x06, 0x30, 0x08, 0x97, 0xC1, 0xF3, 0x07, 0x2C, 0x14, 0xF8, 0x0E, 0x10, 0x15, 0xF8, 0x0A, 0xA0, 0x18, 0xF8, 0x00, 0x00, ++0x01, 0x9F, 0x09, 0x90, 0xA8, 0x5D, 0x0A, 0x90, 0x4B, 0x40, 0x02, 0x98, 0x00, 0x9E, 0x25, 0x5C, 0x18, 0xF8, 0x09, 0x00, ++0x7B, 0x40, 0x83, 0xEA, 0x0A, 0x03, 0x14, 0xF8, 0x0C, 0xA0, 0x51, 0x40, 0x57, 0x46, 0x68, 0x40, 0x8B, 0xEA, 0x01, 0x0B, ++0x00, 0x97, 0x3B, 0x49, 0x14, 0xF8, 0x09, 0xA0, 0x11, 0xF8, 0x09, 0x90, 0xCD, 0xF8, 0x2C, 0x90, 0x78, 0x40, 0x08, 0x9F, ++0x8B, 0xEA, 0x07, 0x01, 0x35, 0x4F, 0x08, 0x91, 0x17, 0xF8, 0x0E, 0x90, 0x09, 0x99, 0x18, 0xF8, 0x0E, 0xE0, 0xC6, 0xF3, ++0x07, 0x46, 0x82, 0xEA, 0x09, 0x02, 0x17, 0xF8, 0x06, 0xB0, 0x17, 0xF8, 0x0C, 0x90, 0x02, 0x9F, 0x18, 0xF8, 0x0C, 0xC0, ++0x4A, 0x40, 0x2C, 0x49, 0x80, 0xEA, 0x0B, 0x00, 0x11, 0xF8, 0x07, 0xB0, 0x0A, 0x99, 0x8A, 0xEA, 0x05, 0x05, 0x89, 0xEA, ++0x05, 0x05, 0x8E, 0xEA, 0x01, 0x0E, 0x18, 0xF8, 0x07, 0x90, 0x0B, 0x99, 0x89, 0xEA, 0x01, 0x09, 0x08, 0x99, 0x1B, 0x04, ++0x43, 0xEA, 0x01, 0x21, 0x06, 0x9B, 0x8A, 0xEA, 0x0B, 0x0A, 0x18, 0xF8, 0x06, 0xB0, 0xA6, 0x5D, 0x01, 0x9F, 0x83, 0xEA, ++0x0E, 0x0E, 0x85, 0xEA, 0x0B, 0x05, 0x87, 0xEA, 0x0E, 0x0E, 0x00, 0x04, 0x00, 0x9F, 0x8A, 0xEA, 0x0C, 0x0A, 0x5A, 0x40, ++0x40, 0xEA, 0x05, 0x20, 0x86, 0xEA, 0x0A, 0x0A, 0x86, 0xEA, 0x09, 0x09, 0x11, 0x43, 0x87, 0xEA, 0x09, 0x09, 0x04, 0x9A, ++0x07, 0x9E, 0x03, 0x9F, 0x05, 0x9B, 0x40, 0xEA, 0x0A, 0x00, 0x41, 0xEA, 0x0E, 0x61, 0x40, 0xEA, 0x09, 0x60, 0xC2, 0xE9, ++0x02, 0x10, 0x35, 0x69, 0x6F, 0x40, 0x17, 0x60, 0x35, 0x46, 0x76, 0x69, 0x01, 0x97, 0x5E, 0x40, 0x56, 0x60, 0x00, 0x96, ++0x2E, 0x46, 0xAD, 0x69, 0x69, 0x40, 0x91, 0x60, 0xF3, 0x69, 0x03, 0x91, 0x43, 0x40, 0x02, 0x93, 0xD3, 0x60, 0x0C, 0x9B, ++0x06, 0xF1, 0x10, 0x01, 0x8B, 0x42, 0x07, 0x91, 0x7F, 0xF4, 0xC8, 0xAE, 0x06, 0xE0, 0x00, 0xBF, 0xE4, 0xC2, 0x15, 0x00, ++0xE4, 0xC3, 0x15, 0x00, 0xE4, 0xC4, 0x15, 0x00, 0xDD, 0xF8, 0x00, 0xE0, 0x3E, 0x0E, 0x5F, 0xFA, 0x8E, 0xF2, 0xDD, 0xE9, ++0x02, 0x39, 0x14, 0xF8, 0x06, 0xC0, 0xA2, 0x5C, 0x70, 0x46, 0x42, 0xEA, 0x0C, 0x62, 0x00, 0x92, 0x1D, 0x0E, 0x02, 0x9A, ++0x65, 0x5D, 0xF9, 0xB2, 0x5F, 0xFA, 0x89, 0xF3, 0x00, 0x0E, 0x61, 0x5C, 0x20, 0x5C, 0xE3, 0x5C, 0xB8, 0x46, 0x5F, 0xFA, ++0x82, 0xFC, 0x4F, 0xEA, 0x19, 0x67, 0x43, 0xEA, 0x00, 0x63, 0xE7, 0x5D, 0x14, 0xF8, 0x0C, 0x00, 0x41, 0xEA, 0x05, 0x61, ++0xCE, 0xF3, 0x07, 0x25, 0x40, 0xEA, 0x07, 0x67, 0x65, 0x5D, 0xC9, 0xF3, 0x07, 0x20, 0x41, 0xEA, 0x05, 0x21, 0x14, 0xF8, ++0x00, 0xB0, 0xC8, 0xF3, 0x07, 0x25, 0xC2, 0xF3, 0x07, 0x20, 0xCE, 0xF3, 0x07, 0x46, 0xC9, 0xF3, 0x07, 0x4A, 0xC2, 0xF3, ++0x07, 0x4C, 0xC8, 0xF3, 0x07, 0x48, 0x65, 0x5D, 0x00, 0x9A, 0x20, 0x5C, 0x14, 0xF8, 0x0A, 0xE0, 0x14, 0xF8, 0x0C, 0xC0, ++0x14, 0xF8, 0x08, 0x80, 0xA6, 0x5D, 0x47, 0xEA, 0x05, 0x27, 0x42, 0xEA, 0x0B, 0x24, 0x43, 0xEA, 0x00, 0x20, 0x04, 0x9A, ++0x0D, 0x9D, 0x41, 0xEA, 0x0E, 0x41, 0x44, 0xEA, 0x0C, 0x44, 0x40, 0xEA, 0x08, 0x40, 0x47, 0xEA, 0x06, 0x46, 0xC2, 0xE9, ++0x00, 0x14, 0xC2, 0xE9, 0x02, 0x06, 0xD5, 0xF8, 0xA0, 0x30, 0x59, 0x40, 0x11, 0x60, 0xD5, 0xF8, 0xA4, 0x30, 0x5C, 0x40, ++0x54, 0x60, 0xD5, 0xF8, 0xA8, 0x30, 0x58, 0x40, 0x90, 0x60, 0xD5, 0xF8, 0xAC, 0x30, 0x5E, 0x40, 0xD6, 0x60, 0x0F, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xD0, 0xE9, 0x01, 0x23, 0xF0, 0xB5, 0x19, 0x49, 0x05, 0x68, 0xC7, 0x68, 0x54, 0x04, 0x04, 0xF0, ++0x80, 0x76, 0x01, 0xEA, 0xD5, 0x34, 0x34, 0x43, 0x6E, 0x00, 0x06, 0xF0, 0xFE, 0x36, 0x34, 0x43, 0x4F, 0xEA, 0x43, 0x4E, ++0x7E, 0x04, 0x0E, 0xF0, 0x80, 0x7E, 0x04, 0x60, 0x01, 0xEA, 0xD2, 0x34, 0x52, 0x00, 0x06, 0xF0, 0x80, 0x7C, 0x44, 0xEA, ++0x0E, 0x04, 0x01, 0xEA, 0xD3, 0x36, 0x02, 0xF0, 0xFE, 0x32, 0x5B, 0x00, 0x22, 0x43, 0x46, 0xEA, 0x0C, 0x06, 0x03, 0xF0, ++0xFE, 0x33, 0x7C, 0x00, 0x33, 0x43, 0x01, 0xEA, 0xD7, 0x31, 0x04, 0xF0, 0xFE, 0x34, 0x21, 0x43, 0xC0, 0xE9, 0x01, 0x23, ++0x2B, 0x06, 0x48, 0xBF, 0x81, 0xF0, 0x07, 0x41, 0xC1, 0x60, 0xF0, 0xBD, 0x01, 0x01, 0x01, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x29, 0x2A, 0xBD, 0xB0, 0x0B, 0xD8, 0x8B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x00, 0x81, ++0x00, 0x20, 0x01, 0x46, 0x3D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x88, 0x46, 0x1D, 0x46, 0x31, 0xF8, 0x04, 0x3B, 0x06, 0x46, ++0x23, 0xF4, 0x60, 0x53, 0x14, 0x46, 0x0D, 0xF1, 0x2E, 0x00, 0x12, 0x22, 0xAD, 0xF8, 0x2C, 0x30, 0x05, 0xF0, 0xC4, 0xFC, ++0xD6, 0xE9, 0x14, 0x13, 0xD6, 0xE9, 0x16, 0x72, 0xC5, 0xF5, 0x7F, 0x40, 0xF4, 0x30, 0x80, 0xB2, 0x01, 0x90, 0xCD, 0xE9, ++0x11, 0x37, 0xDF, 0xF8, 0xEC, 0xE1, 0xDF, 0xF8, 0xEC, 0xC1, 0x10, 0x91, 0x13, 0x92, 0x10, 0xAE, 0x0D, 0xF1, 0xD0, 0x0A, ++0x01, 0x20, 0x02, 0xE0, 0x5E, 0xF8, 0x04, 0x0F, 0x10, 0x36, 0xC2, 0xF3, 0x07, 0x2B, 0x5F, 0xFA, 0x82, 0xF9, 0x1C, 0xF8, ++0x0B, 0xB0, 0x1C, 0xF8, 0x09, 0x90, 0x8B, 0xEA, 0x00, 0x00, 0x4F, 0xEA, 0x12, 0x6B, 0x40, 0xEA, 0x09, 0x60, 0xC2, 0xF3, ++0x07, 0x49, 0x1C, 0xF8, 0x0B, 0xB0, 0x1C, 0xF8, 0x09, 0x90, 0x40, 0xEA, 0x0B, 0x40, 0x40, 0xEA, 0x09, 0x20, 0x41, 0x40, ++0x4B, 0x40, 0x5F, 0x40, 0x7A, 0x40, 0x56, 0x45, 0xC6, 0xE9, 0x06, 0x72, 0xC6, 0xE9, 0x04, 0x13, 0xDA, 0xD1, 0x10, 0x22, ++0x00, 0x21, 0x03, 0xA8, 0xCE, 0xF7, 0xF6, 0xFC, 0x0D, 0xF1, 0x0A, 0x06, 0x00, 0x21, 0x07, 0xA8, 0x10, 0x22, 0xCE, 0xF7, ++0xEF, 0xFC, 0x0D, 0xF1, 0x1A, 0x07, 0x33, 0x46, 0x0D, 0xF1, 0x2A, 0x01, 0x33, 0xF8, 0x02, 0x2F, 0x31, 0xF8, 0x02, 0x0F, ++0x9F, 0x42, 0x82, 0xEA, 0x00, 0x02, 0x1A, 0x80, 0xF6, 0xD1, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x7B, 0xFD, 0x03, 0x9B, ++0x0F, 0x9A, 0x6D, 0x08, 0x08, 0xEB, 0x45, 0x08, 0x53, 0x40, 0xA8, 0xF1, 0x02, 0x01, 0x08, 0xF1, 0x0A, 0x05, 0x03, 0x93, ++0x0D, 0xF1, 0x0E, 0x02, 0x32, 0xF8, 0x02, 0x3F, 0x31, 0xF8, 0x02, 0x0F, 0x43, 0x40, 0x8D, 0x42, 0x13, 0x80, 0xF7, 0xD1, ++0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x62, 0xFD, 0x01, 0x9B, 0x1C, 0x44, 0xA4, 0xB2, 0x10, 0x2C, 0x08, 0xF1, 0x0C, 0x09, ++0x26, 0xD9, 0xA4, 0xF1, 0x11, 0x0A, 0xCA, 0xF3, 0x0B, 0x1A, 0x08, 0xEB, 0x0A, 0x18, 0x08, 0xF1, 0x1C, 0x08, 0x4D, 0x46, ++0xAA, 0x1E, 0x33, 0x46, 0x05, 0xF1, 0x0E, 0x00, 0x33, 0xF8, 0x02, 0x1F, 0x32, 0xF8, 0x02, 0xCF, 0x81, 0xEA, 0x0C, 0x01, ++0x90, 0x42, 0x19, 0x80, 0xF6, 0xD1, 0x10, 0x35, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x40, 0xFD, 0x45, 0x45, 0xEB, 0xD1, ++0xCA, 0xEB, 0x0A, 0x33, 0x10, 0x3C, 0x04, 0xEB, 0x03, 0x14, 0x0A, 0xF1, 0x01, 0x0A, 0xA4, 0xB2, 0x09, 0xEB, 0x0A, 0x19, ++0x07, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x30, 0xFD, 0x07, 0xA8, 0xFF, 0xF7, 0x01, 0xFF, 0x10, 0x2C, 0x34, 0xD0, 0x65, 0x08, ++0x07, 0xA8, 0xFF, 0xF7, 0xFB, 0xFE, 0x65, 0xB1, 0xA9, 0xF1, 0x02, 0x02, 0x02, 0xEB, 0x45, 0x0C, 0x39, 0x46, 0x31, 0xF8, ++0x02, 0x3F, 0x32, 0xF8, 0x02, 0x0F, 0x43, 0x40, 0x94, 0x45, 0x0B, 0x80, 0xF7, 0xD1, 0xE3, 0x07, 0x39, 0xD4, 0x80, 0x23, ++0xA4, 0x08, 0x05, 0xF0, 0x01, 0x05, 0x3C, 0xAA, 0x05, 0xEB, 0x44, 0x04, 0x02, 0xEB, 0x44, 0x04, 0x34, 0xF8, 0xD4, 0x2C, ++0x53, 0x40, 0x24, 0xF8, 0xD4, 0x3C, 0x3A, 0x46, 0x36, 0xF8, 0x02, 0x3F, 0x32, 0xF8, 0x02, 0x1F, 0xB7, 0x42, 0x83, 0xEA, ++0x01, 0x03, 0x33, 0x80, 0xF6, 0xD1, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0xFB, 0xFC, 0xDD, 0xE9, 0x03, 0x01, 0x3D, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xA9, 0xF1, 0x02, 0x02, 0x39, 0x46, 0x09, 0xF1, 0x0E, 0x09, 0x31, 0xF8, 0x02, 0x3F, 0x32, 0xF8, ++0x02, 0x0F, 0x43, 0x40, 0x91, 0x45, 0x0B, 0x80, 0xF7, 0xD1, 0xDE, 0xE7, 0x08, 0x49, 0x09, 0x48, 0x4F, 0xF4, 0xD6, 0x72, ++0xF3, 0xF7, 0x44, 0xF9, 0x00, 0x20, 0x01, 0x46, 0x3D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x19, 0xF8, 0x15, 0x30, 0x43, 0xF4, ++0x00, 0x43, 0xC1, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xBC, 0xC2, 0x15, 0x00, ++0xE4, 0xC2, 0x15, 0x00, 0x81, 0x04, 0x4F, 0xEA, 0xD0, 0x23, 0xC0, 0xF3, 0xC2, 0x22, 0x0C, 0xD4, 0x13, 0xF0, 0x06, 0x0F, ++0x03, 0xF0, 0x06, 0x02, 0x11, 0xD1, 0x00, 0xF0, 0x7F, 0x00, 0x62, 0xB9, 0x03, 0x28, 0x8C, 0xBF, 0x00, 0x20, 0x01, 0x20, ++0x70, 0x47, 0x07, 0x2A, 0x0C, 0xD0, 0x03, 0xF0, 0x06, 0x02, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x2A, 0xF2, 0xD0, 0x00, 0x20, ++0x70, 0x47, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x2A, 0xF9, 0xD1, 0xEB, 0xE7, 0x13, 0xF0, 0x06, 0x0F, 0x0C, 0xBF, 0x01, 0x20, ++0x00, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x40, 0x7F, 0x87, 0xB0, 0x4F, 0xF0, 0xFF, 0x34, 0x09, 0x28, ++0x05, 0x94, 0x02, 0xD9, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x89, 0x46, 0xF9, 0x6C, 0xC9, 0x4E, 0x8C, 0x6C, 0x0D, 0x6D, ++0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x00, 0x60, 0x90, 0x46, 0x90, 0xF8, 0x22, 0x10, 0xFA, 0x8B, 0x14, 0xF4, 0x00, 0x5F, ++0x08, 0xBF, 0x01, 0x23, 0x22, 0xF4, 0x00, 0x54, 0x05, 0xF4, 0x80, 0x05, 0x02, 0xF4, 0x00, 0x52, 0xFF, 0x29, 0x01, 0x95, ++0xFC, 0x83, 0x02, 0x92, 0xE0, 0xD0, 0xBD, 0x4A, 0xD0, 0xF8, 0x4C, 0xA1, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, ++0x50, 0xDB, 0xBA, 0xF8, 0xB4, 0x10, 0xBA, 0x6C, 0x48, 0x1E, 0x05, 0xAC, 0xC0, 0xB2, 0x01, 0xEB, 0x41, 0x0E, 0x00, 0x90, ++0x03, 0x94, 0x0A, 0xEB, 0x8E, 0x0E, 0x02, 0xF1, 0x3C, 0x00, 0x02, 0xF1, 0x4C, 0x0B, 0xA4, 0x46, 0x50, 0xF8, 0x04, 0x6B, ++0xC6, 0xF3, 0x0D, 0x06, 0x79, 0xB1, 0x74, 0x46, 0x00, 0x22, 0x02, 0xE0, 0x01, 0x32, 0x8A, 0x42, 0x09, 0xD0, 0x34, 0xF8, ++0x02, 0x5C, 0xB5, 0x42, 0xA4, 0xF1, 0x0C, 0x04, 0xF6, 0xD1, 0x00, 0x9C, 0xA2, 0x1A, 0x8C, 0xF8, 0x00, 0x20, 0x00, 0x2B, ++0x40, 0xF0, 0xAD, 0x80, 0x83, 0x45, 0x0C, 0xF1, 0x01, 0x0C, 0xE3, 0xD1, 0x97, 0xF8, 0x36, 0x30, 0x9A, 0xF8, 0xA3, 0x20, ++0xC3, 0xF3, 0x82, 0x03, 0x93, 0x42, 0x27, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x64, 0xD0, 0xBA, 0xF8, 0x92, 0x20, 0xBA, 0xF8, ++0x90, 0x30, 0x01, 0x32, 0x01, 0x33, 0xAA, 0xF8, 0x92, 0x20, 0xAA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x7E, 0x10, 0xBA, 0xF8, ++0x7C, 0x20, 0x1F, 0xFA, 0x89, 0xF9, 0xA9, 0xEB, 0x08, 0x03, 0x0B, 0x44, 0x91, 0x44, 0xAA, 0xF8, 0x7E, 0x30, 0xAA, 0xF8, ++0x7C, 0x90, 0x87, 0xE7, 0xBA, 0xF1, 0x00, 0x0F, 0xAB, 0xD1, 0x90, 0x49, 0x90, 0x48, 0x00, 0x93, 0x4F, 0xF4, 0x18, 0x62, ++0xF3, 0xF7, 0x64, 0xF8, 0x00, 0x9B, 0xA2, 0xE7, 0xBA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x92, 0x20, 0x01, 0x33, 0xAA, 0xF8, ++0x90, 0x30, 0x01, 0x9B, 0x01, 0x32, 0xAA, 0xF8, 0x92, 0x20, 0x00, 0x2B, 0xD7, 0xD1, 0x02, 0x9B, 0x00, 0x2B, 0x3A, 0xD0, ++0x83, 0x4E, 0x85, 0x4D, 0x03, 0x9F, 0x00, 0x24, 0xB9, 0xF1, 0x00, 0x0F, 0x24, 0xD0, 0x17, 0xF8, 0x01, 0x3B, 0xFF, 0x2B, ++0x00, 0xF0, 0xEC, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0x41, 0x81, 0x03, 0xEB, 0x43, 0x02, 0xB8, 0xF1, 0x01, 0x0F, 0x0A, 0xEB, ++0x82, 0x02, 0x40, 0xF2, 0x7A, 0x81, 0x92, 0x88, 0x59, 0x00, 0x19, 0x44, 0x0A, 0xEB, 0x81, 0x01, 0x02, 0x32, 0x8A, 0x80, ++0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x71, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, ++0x02, 0x81, 0x01, 0x34, 0x04, 0x2C, 0xD7, 0xD1, 0x00, 0x23, 0x8A, 0xF8, 0x9B, 0x30, 0x3B, 0xE7, 0xBA, 0xF8, 0x92, 0x20, ++0xBA, 0xF8, 0x90, 0x30, 0x01, 0x32, 0x01, 0x33, 0xAA, 0xF8, 0x92, 0x20, 0xAA, 0xF8, 0x90, 0x30, 0xC1, 0xE7, 0x66, 0x4E, ++0x67, 0x4D, 0x03, 0x9F, 0x1C, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x29, 0xAF, 0x17, 0xF8, 0x01, 0x3B, 0xFF, 0x2B, ++0x00, 0xF0, 0xA5, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0xF0, 0x80, 0x03, 0xEB, 0x43, 0x02, 0xB8, 0xF1, 0x01, 0x0F, 0x0A, 0xEB, ++0x82, 0x02, 0x40, 0xF2, 0x43, 0x81, 0x92, 0x88, 0x59, 0x00, 0x19, 0x44, 0x0A, 0xEB, 0x81, 0x01, 0x02, 0x32, 0x8A, 0x80, ++0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x53, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, ++0xB6, 0x80, 0x01, 0x34, 0x04, 0x2C, 0xD6, 0xD1, 0x02, 0xE7, 0x97, 0xF8, 0x36, 0x30, 0x9A, 0xF8, 0xA3, 0x20, 0xC3, 0xF3, ++0x82, 0x03, 0x93, 0x42, 0x38, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x69, 0xD1, 0xBA, 0xF8, 0x92, 0x30, 0xBA, 0xF8, 0x90, 0x20, ++0x01, 0x33, 0x1F, 0xFA, 0x89, 0xF0, 0xAA, 0xF8, 0x92, 0x30, 0x02, 0x9B, 0x02, 0x44, 0xAA, 0xF8, 0x90, 0x20, 0x00, 0x2B, ++0x40, 0xF0, 0x8A, 0x80, 0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0xE3, 0xAE, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, ++0x04, 0x33, 0x3C, 0x4A, 0x5D, 0x88, 0x19, 0x88, 0x14, 0x68, 0xA0, 0xEB, 0x08, 0x02, 0x2A, 0x44, 0x01, 0x44, 0x92, 0xB2, ++0x89, 0xB2, 0x5A, 0x80, 0x19, 0x80, 0xB4, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xCE, 0xAE, 0x91, 0x42, 0xBF, 0xF4, ++0xCB, 0xAE, 0x33, 0x49, 0x34, 0x48, 0x4F, 0xF4, 0x1F, 0x62, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xF2, 0xF7, 0xA8, 0xBF, ++0xBA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x92, 0x20, 0x1F, 0xFA, 0x89, 0xF0, 0x03, 0x44, 0xAA, 0xF8, 0x90, 0x30, 0x01, 0x9B, ++0x01, 0x32, 0xAA, 0xF8, 0x92, 0x20, 0x8B, 0xBB, 0x02, 0x9B, 0x00, 0x2B, 0x52, 0xD1, 0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, ++0x00, 0xF0, 0xFD, 0x80, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, 0x04, 0x33, 0xB9, 0xEB, 0x48, 0x0F, 0x9A, 0xF8, 0xA4, 0x20, ++0x80, 0xF0, 0xE9, 0x80, 0x01, 0x2A, 0x40, 0xF2, 0xF8, 0x80, 0x02, 0x2A, 0x03, 0xD0, 0x00, 0x2B, 0x3F, 0xF4, 0x9A, 0xAE, ++0xB9, 0xE7, 0xDA, 0xF8, 0x00, 0x20, 0xA2, 0xF5, 0x92, 0x32, 0xF8, 0x3A, 0xCA, 0xF8, 0x00, 0x20, 0x00, 0x2B, 0x3F, 0xF4, ++0x8F, 0xAE, 0xAE, 0xE7, 0xBA, 0xF8, 0x90, 0x20, 0xBA, 0xF8, 0x92, 0x30, 0x1F, 0xFA, 0x89, 0xF0, 0x02, 0x44, 0x01, 0x33, ++0xAA, 0xF8, 0x90, 0x20, 0xAA, 0xF8, 0x92, 0x30, 0x0A, 0xF1, 0x7C, 0x03, 0x9F, 0xE7, 0x00, 0x2C, 0x75, 0xD0, 0xB8, 0xF1, ++0x01, 0x0F, 0x7F, 0xF6, 0x79, 0xAE, 0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x6C, 0xE7, 0x00, 0x2C, 0x00, 0xF0, ++0x8C, 0x80, 0xB8, 0xF1, 0x01, 0x0F, 0x7F, 0xF6, 0x2D, 0xAF, 0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x24, 0xE7, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0xE4, 0xC5, 0x15, 0x00, ++0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0x19, 0xAF, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, 0x00, 0x22, 0x04, 0x33, ++0x8A, 0xF8, 0x9B, 0x20, 0x71, 0xE7, 0x03, 0xEB, 0x43, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x9A, 0x88, 0xDB, 0x88, 0x9A, 0x42, ++0xBF, 0xF4, 0x41, 0xAF, 0x40, 0xF6, 0x61, 0x22, 0x31, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x28, 0xFF, 0x39, 0xE7, 0x03, 0xEB, ++0x43, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x9A, 0x88, 0xDB, 0x88, 0x9A, 0x42, 0xBF, 0xF4, 0xF5, 0xAE, 0x40, 0xF6, 0x33, 0x22, ++0x31, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x18, 0xFF, 0xED, 0xE6, 0xB8, 0xF1, 0x00, 0x0F, 0x6C, 0xD0, 0x03, 0xEB, 0x43, 0x01, ++0x0A, 0xEB, 0x81, 0x01, 0x08, 0xF1, 0xFF, 0x38, 0x8A, 0x88, 0x01, 0x32, 0x92, 0xB2, 0xB8, 0xF1, 0x01, 0x0F, 0x8A, 0x80, ++0x09, 0xF1, 0xFF, 0x39, 0x19, 0xB2, 0x73, 0xD9, 0x59, 0x00, 0x04, 0xE7, 0xB8, 0xF1, 0x00, 0x0F, 0x1B, 0xD0, 0x03, 0xEB, ++0x43, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x08, 0xF1, 0xFF, 0x38, 0x8A, 0x88, 0x01, 0x32, 0x92, 0xB2, 0xB8, 0xF1, 0x01, 0x0F, ++0x8A, 0x80, 0x09, 0xF1, 0xFF, 0x39, 0x19, 0xB2, 0x5B, 0xD9, 0x59, 0x00, 0xB3, 0xE6, 0xB8, 0xF1, 0x02, 0x0F, 0x7F, 0xF6, ++0x03, 0xAE, 0xA9, 0xF1, 0x03, 0x09, 0xA8, 0xF1, 0x03, 0x08, 0x01, 0x24, 0xCF, 0xE6, 0x03, 0xEB, 0x43, 0x02, 0x0A, 0xEB, ++0x82, 0x02, 0xA0, 0x46, 0x92, 0x88, 0x19, 0xB2, 0x01, 0xEB, 0x41, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x1F, 0xFA, 0x89, 0xF9, ++0xC8, 0x88, 0xA9, 0xEB, 0x08, 0x08, 0x4A, 0x44, 0x40, 0x44, 0x4F, 0xF0, 0x00, 0x09, 0x8A, 0x80, 0xC8, 0x80, 0xC8, 0x46, ++0x9A, 0xE6, 0xB8, 0xF1, 0x02, 0x0F, 0x7F, 0xF6, 0xA1, 0xAE, 0xA9, 0xF1, 0x03, 0x09, 0xA8, 0xF1, 0x03, 0x08, 0x01, 0x24, ++0x72, 0xE6, 0x92, 0x88, 0x1F, 0xFA, 0x88, 0xF8, 0x19, 0xB2, 0xDF, 0xE7, 0x92, 0x88, 0x1F, 0xFA, 0x88, 0xF8, 0x19, 0xB2, ++0x01, 0xEB, 0x41, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x1F, 0xFA, 0x89, 0xF9, 0xC8, 0x88, 0xA9, 0xEB, 0x08, 0x08, 0x4A, 0x44, ++0x40, 0x44, 0x4F, 0xF0, 0x00, 0x09, 0x8A, 0x80, 0xC8, 0x80, 0xC8, 0x46, 0xB2, 0xE6, 0x03, 0xEB, 0x43, 0x02, 0x0A, 0xEB, ++0x82, 0x02, 0xA0, 0x46, 0x92, 0x88, 0x19, 0xB2, 0xE6, 0xE7, 0x00, 0x2A, 0x3F, 0xF4, 0x19, 0xAF, 0x01, 0x3A, 0x8A, 0xF8, ++0xA4, 0x20, 0x00, 0x2B, 0x3F, 0xF4, 0xB0, 0xAD, 0xCF, 0xE6, 0x02, 0x9B, 0x04, 0xE7, 0x1F, 0xFA, 0x88, 0xF8, 0xB3, 0xE7, ++0x1F, 0xFA, 0x88, 0xF8, 0xD4, 0xE7, 0x01, 0x32, 0x8A, 0xF8, 0xA4, 0x20, 0x00, 0x2B, 0x3F, 0xF4, 0xA1, 0xAD, 0xC0, 0xE6, ++0x03, 0x88, 0xA3, 0xB1, 0x10, 0xB4, 0x42, 0x88, 0x44, 0x7A, 0x00, 0x21, 0x12, 0x04, 0x01, 0x72, 0xB2, 0xFB, 0xF3, 0xF1, ++0x8C, 0xB1, 0x83, 0x88, 0x5D, 0xF8, 0x04, 0x4B, 0x03, 0xEB, 0x43, 0x03, 0x0B, 0x44, 0xC3, 0xF3, 0x98, 0x03, 0x83, 0x80, ++0x01, 0x23, 0x43, 0x72, 0x70, 0x47, 0x03, 0x7A, 0xFF, 0x2B, 0x1C, 0xBF, 0x01, 0x33, 0x03, 0x72, 0x70, 0x47, 0x9A, 0x42, ++0x24, 0xBF, 0x01, 0xF1, 0xFF, 0x33, 0x83, 0x80, 0x4F, 0xF0, 0x01, 0x03, 0x38, 0xBF, 0x84, 0x80, 0x43, 0x72, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0xF8, 0xB5, 0x06, 0x46, 0x88, 0x04, 0x0C, 0x46, 0xC1, 0xF3, 0xC2, 0x25, 0x19, 0xD4, 0xCB, 0x0A, ++0x13, 0xF0, 0x06, 0x0F, 0x40, 0xD1, 0xCF, 0xB2, 0x01, 0xF0, 0x7F, 0x05, 0x05, 0xF0, 0xF8, 0xF9, 0x17, 0xF0, 0x7C, 0x0F, ++0x5B, 0xD1, 0x96, 0xF8, 0xAD, 0x20, 0x04, 0xE0, 0xB6, 0xF8, 0xAA, 0x30, 0xEB, 0x40, 0xD9, 0x07, 0x59, 0xD4, 0x6B, 0x1E, ++0x95, 0x42, 0xDD, 0xB2, 0xF6, 0xD8, 0x20, 0x46, 0xF8, 0xBD, 0x07, 0x2D, 0x47, 0xD0, 0x04, 0x3D, 0x05, 0xF0, 0xE2, 0xF9, ++0x04, 0xF0, 0x0F, 0x02, 0x01, 0x2D, 0xF4, 0xD8, 0xDF, 0xE8, 0x05, 0xF0, 0x01, 0x0E, 0x72, 0xB3, 0x53, 0x1E, 0x24, 0xF0, ++0x0F, 0x04, 0x96, 0xF8, 0xB1, 0x20, 0x23, 0x43, 0x98, 0xB2, 0x00, 0x2A, 0xE8, 0xD0, 0x40, 0xF4, 0x00, 0x70, 0xF8, 0xBD, ++0x0A, 0xB3, 0x24, 0xF0, 0x0F, 0x03, 0x51, 0x1E, 0x0B, 0x43, 0x98, 0xB2, 0x63, 0x04, 0xDD, 0xD5, 0x03, 0x2A, 0x03, 0xD0, ++0x96, 0xF8, 0xBD, 0x30, 0x99, 0x42, 0xD7, 0xDD, 0x20, 0xF4, 0x80, 0x43, 0x98, 0xB2, 0xF8, 0xBD, 0xC4, 0xF3, 0xC1, 0x05, ++0x05, 0xF0, 0xB8, 0xF9, 0x35, 0x44, 0x04, 0xF0, 0x07, 0x03, 0x05, 0xE0, 0x95, 0xF8, 0xA6, 0x20, 0xCB, 0xB2, 0xDA, 0x40, ++0xD2, 0x07, 0x24, 0xD4, 0x59, 0x1E, 0x00, 0x2B, 0xF6, 0xD1, 0x96, 0xF8, 0xAE, 0x30, 0x03, 0x2B, 0xBD, 0xD8, 0x43, 0xB3, ++0x96, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x60, 0x43, 0xEA, 0x82, 0x23, 0x03, 0x43, 0x98, 0xB2, 0xF8, 0xBD, 0x05, 0xF0, ++0x9B, 0xF9, 0x20, 0x46, 0xB0, 0xE7, 0x96, 0xF8, 0xAD, 0x20, 0x04, 0x2A, 0x38, 0xBF, 0x04, 0x22, 0xA5, 0xE7, 0x24, 0xF0, ++0x7F, 0x04, 0x44, 0xEA, 0x05, 0x00, 0x00, 0x2D, 0xA4, 0xD1, 0x40, 0xF4, 0x80, 0x63, 0x98, 0xB2, 0xF8, 0xBD, 0x96, 0xF8, ++0xB1, 0x20, 0x24, 0xF0, 0x07, 0x04, 0x44, 0xEA, 0x03, 0x00, 0x00, 0x2A, 0x98, 0xD0, 0x40, 0xF4, 0x00, 0x73, 0x98, 0xB2, ++0xF8, 0xBD, 0x4F, 0xF4, 0x80, 0x60, 0xF8, 0xBD, 0x8A, 0x04, 0x30, 0xB4, 0xC1, 0xF3, 0xC2, 0x23, 0x20, 0xD4, 0xCA, 0x0A, ++0x12, 0xF0, 0x06, 0x0F, 0x26, 0xD1, 0x11, 0xF0, 0x7C, 0x0F, 0x01, 0xF0, 0x7F, 0x03, 0x71, 0xD1, 0x90, 0xF8, 0xAE, 0x40, ++0x03, 0x2C, 0x28, 0xBF, 0x03, 0x24, 0x04, 0xE0, 0xB0, 0xF8, 0xAA, 0x20, 0xDA, 0x40, 0xD5, 0x07, 0x74, 0xD4, 0x5A, 0x1C, ++0xA3, 0x42, 0xD3, 0xB2, 0xF6, 0xD3, 0x90, 0xF8, 0xA5, 0x30, 0x01, 0x2B, 0x01, 0xD9, 0xD9, 0x02, 0x89, 0xB2, 0x08, 0x46, ++0x30, 0xBC, 0x70, 0x47, 0x07, 0x2B, 0xFA, 0xD0, 0x04, 0x3B, 0x01, 0xF0, 0x0F, 0x02, 0x01, 0x2B, 0xF5, 0xD8, 0xDF, 0xE8, ++0x03, 0xF0, 0x15, 0x30, 0xC1, 0xF3, 0xC1, 0x04, 0x90, 0xF8, 0xAC, 0x50, 0x04, 0x44, 0x01, 0xF0, 0x07, 0x03, 0x04, 0xE0, ++0x94, 0xF8, 0xA6, 0x20, 0xDA, 0x40, 0xD2, 0x07, 0x45, 0xD4, 0x5A, 0x1C, 0x9D, 0x42, 0xD3, 0xB2, 0xF6, 0xD8, 0x08, 0x46, ++0x30, 0xBC, 0x70, 0x47, 0x90, 0xF8, 0xAC, 0x30, 0x93, 0x42, 0xDA, 0xD9, 0xB0, 0xF8, 0xA6, 0x30, 0xC1, 0xF3, 0x02, 0x14, ++0x64, 0x00, 0x23, 0x41, 0x03, 0xF0, 0x03, 0x03, 0x07, 0x33, 0x93, 0x42, 0xCF, 0xD9, 0x21, 0xF0, 0x0F, 0x01, 0x01, 0x32, ++0x90, 0xF8, 0xB1, 0x30, 0x11, 0x43, 0x89, 0xB2, 0x00, 0x2B, 0xC6, 0xD0, 0x41, 0xF4, 0x00, 0x71, 0xC3, 0xE7, 0x90, 0xF8, ++0xAC, 0x30, 0x93, 0x42, 0xBF, 0xD9, 0xB0, 0xF8, 0xA6, 0x30, 0xC1, 0xF3, 0x02, 0x14, 0x64, 0x00, 0x23, 0x41, 0x03, 0xF0, ++0x03, 0x03, 0x5B, 0x00, 0x07, 0x33, 0x93, 0x42, 0xB3, 0xD9, 0x21, 0xF0, 0x0F, 0x01, 0x53, 0x1C, 0x0B, 0x43, 0x99, 0xB2, ++0x5B, 0x04, 0xAC, 0xD5, 0x01, 0x2A, 0x03, 0xD0, 0x90, 0xF8, 0xBD, 0x30, 0x93, 0x42, 0xA6, 0xD8, 0x21, 0xF4, 0x80, 0x41, ++0x89, 0xB2, 0xA2, 0xE7, 0x90, 0xF8, 0xAE, 0x40, 0x95, 0xE7, 0x90, 0xF8, 0xB1, 0x20, 0x21, 0xF0, 0x07, 0x01, 0x19, 0x43, ++0x00, 0x2A, 0x98, 0xD0, 0x41, 0xF4, 0x00, 0x71, 0x89, 0xB2, 0x94, 0xE7, 0x21, 0xF0, 0x7F, 0x01, 0x19, 0x43, 0x90, 0xE7, ++0x2D, 0xE9, 0xF0, 0x4F, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x85, 0xB0, 0x4C, 0x89, 0xE6, 0x0A, 0xC4, 0xF3, ++0x80, 0x22, 0x01, 0x92, 0x71, 0x07, 0x4F, 0xEA, 0x54, 0x22, 0x05, 0x46, 0x06, 0xF0, 0x04, 0x03, 0xC4, 0xF3, 0xC2, 0x27, ++0x02, 0x92, 0xC4, 0xF3, 0x40, 0x2B, 0xC4, 0xF3, 0xC1, 0x1A, 0x23, 0xD5, 0x07, 0x2F, 0x50, 0xD0, 0xC4, 0xF3, 0x02, 0x19, ++0x04, 0xF0, 0x0F, 0x04, 0xDF, 0xF8, 0x70, 0x83, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x22, 0xDA, ++0x05, 0x2F, 0x27, 0xD9, 0x40, 0xF2, 0xB5, 0x22, 0xCA, 0x49, 0xCB, 0x48, 0x03, 0x93, 0xF2, 0xF7, 0x0B, 0xFD, 0x95, 0xF8, ++0xA5, 0x20, 0x03, 0x9B, 0x05, 0x2A, 0x14, 0xD8, 0xDF, 0xE8, 0x12, 0xF0, 0xD6, 0x00, 0xD6, 0x00, 0x31, 0x01, 0x31, 0x01, ++0xF4, 0x00, 0x45, 0x01, 0x16, 0xF0, 0x06, 0x09, 0x26, 0xD1, 0x04, 0xF0, 0x7F, 0x04, 0xDF, 0xF8, 0x2C, 0x83, 0xD8, 0xF8, ++0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x06, 0xDB, 0x05, 0x2F, 0x17, 0xD8, 0xDF, 0xE8, 0x07, 0xF0, 0x22, 0x22, ++0x0F, 0x0F, 0x50, 0x91, 0x95, 0xF8, 0xA5, 0x10, 0x05, 0x29, 0xF4, 0xD8, 0xDF, 0xE8, 0x11, 0xF0, 0xBD, 0x00, 0xBD, 0x00, ++0x15, 0x01, 0x15, 0x01, 0xD8, 0x00, 0x29, 0x01, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, ++0xDF, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC4, 0xF3, 0xC1, 0x09, 0x04, 0xF0, 0x07, 0x04, 0xD5, 0xE7, 0x4F, 0xF0, ++0x00, 0x09, 0x4C, 0x46, 0xAE, 0xE7, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x03, 0x2C, 0x04, 0xD8, 0x95, 0xF8, ++0xB2, 0x10, 0x01, 0x29, 0x00, 0xF0, 0x7B, 0x81, 0x00, 0x2A, 0xE6, 0xDA, 0xBB, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x2E, 0x81, ++0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x1C, 0x81, 0xB9, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0xDC, 0x81, 0x95, 0xF8, 0xAD, 0x30, ++0xA3, 0x42, 0x00, 0xF2, 0xC9, 0x81, 0x95, 0xF8, 0xAE, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0xEE, 0x81, 0xB5, 0xF8, 0xAA, 0x30, ++0x23, 0xFA, 0x04, 0xF4, 0xE2, 0x07, 0xCA, 0xD4, 0x93, 0x49, 0x95, 0x48, 0x40, 0xF2, 0x06, 0x32, 0x3B, 0xE0, 0xD8, 0xF8, ++0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xBF, 0xDA, 0x01, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0xCB, 0x81, 0x95, 0xF8, ++0xB1, 0x30, 0x5B, 0x45, 0xC0, 0xF0, 0x52, 0x82, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, 0xC0, 0xF0, 0x3F, 0x82, 0x95, 0xF8, ++0xB0, 0x30, 0x4B, 0x45, 0xC0, 0xF0, 0x2C, 0x82, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0x19, 0x82, 0xB5, 0xF8, ++0xA6, 0x30, 0x4F, 0xEA, 0x49, 0x02, 0x13, 0x41, 0x03, 0xF0, 0x03, 0x03, 0x07, 0x33, 0x9C, 0x42, 0x00, 0xF3, 0x82, 0x81, ++0x06, 0x2C, 0x00, 0xF0, 0x3E, 0x81, 0x09, 0x2C, 0x97, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x4B, 0x82, 0xB9, 0xF1, ++0x02, 0x0F, 0x90, 0xD0, 0xB9, 0xF1, 0x05, 0x0F, 0x8D, 0xD0, 0x75, 0x49, 0x77, 0x48, 0x4F, 0xF4, 0x48, 0x72, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0xF2, 0xF7, 0x5C, 0xBC, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0x7E, 0xAF, 0x02, 0x9B, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF0, 0x21, 0x82, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, ++0xC0, 0xF0, 0x9E, 0x81, 0x95, 0xF8, 0xB0, 0x30, 0x4B, 0x45, 0xC0, 0xF0, 0xD1, 0x81, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, ++0xC0, 0xF0, 0xBE, 0x81, 0xB5, 0xF8, 0xA6, 0x30, 0x4F, 0xEA, 0x49, 0x09, 0x43, 0xFA, 0x09, 0xF3, 0x03, 0xF0, 0x03, 0x03, ++0x5B, 0x00, 0x07, 0x33, 0x9C, 0x42, 0x7F, 0xF7, 0x5C, 0xAF, 0x5C, 0x49, 0x5F, 0x48, 0x40, 0xF2, 0x2F, 0x32, 0xCC, 0xE7, ++0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xBF, 0xF6, 0x36, 0xAF, 0x16, 0xF0, 0x06, 0x0F, 0x40, 0xF0, ++0x2A, 0x81, 0x05, 0x2F, 0x3F, 0xF6, 0x49, 0xAF, 0x01, 0xA3, 0x53, 0xF8, 0x27, 0xF0, 0x00, 0xBF, 0xE7, 0x21, 0x15, 0x00, ++0xE7, 0x21, 0x15, 0x00, 0x8D, 0x23, 0x15, 0x00, 0x8D, 0x23, 0x15, 0x00, 0x43, 0x22, 0x15, 0x00, 0xC5, 0x22, 0x15, 0x00, ++0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x60, 0xD8, 0x00, 0x2A, 0xBF, 0xF6, ++0x14, 0xAF, 0x04, 0x2F, 0x3F, 0xF4, 0x6B, 0xAF, 0x00, 0x2F, 0x3F, 0xF4, 0x38, 0xAF, 0x42, 0x49, 0x46, 0x48, 0x4F, 0xF4, ++0x36, 0x72, 0xF2, 0xF7, 0xF9, 0xFB, 0x06, 0xE7, 0x01, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0x64, 0x81, 0x95, 0xF8, 0xB1, 0x30, ++0x5B, 0x45, 0xC0, 0xF0, 0x51, 0x81, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, 0xC0, 0xF0, 0xD5, 0x80, 0x95, 0xF8, 0xB0, 0x30, ++0x4B, 0x45, 0xC0, 0xF0, 0xC2, 0x80, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0xD9, 0x80, 0x4D, 0x44, 0x95, 0xF8, ++0xA6, 0x30, 0x23, 0xFA, 0x04, 0xF4, 0xE3, 0x07, 0x3F, 0xF5, 0x01, 0xAF, 0x2E, 0x49, 0x34, 0x48, 0x40, 0xF2, 0x12, 0x32, ++0x71, 0xE7, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x77, 0xD8, 0x00, 0x2A, ++0xBF, 0xF6, 0xD7, 0xAE, 0x00, 0x2B, 0xA2, 0xD0, 0x25, 0x49, 0x2C, 0x48, 0x40, 0xF2, 0xCA, 0x22, 0xF2, 0xF7, 0xC0, 0xFB, ++0xCD, 0xE6, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x56, 0xD8, 0x00, 0x2A, ++0xBF, 0xF6, 0xC3, 0xAE, 0x05, 0x2F, 0x3F, 0xF4, 0x5C, 0xAF, 0x00, 0x2F, 0x3F, 0xF4, 0xE7, 0xAE, 0x19, 0x49, 0x21, 0x48, ++0x40, 0xF2, 0xE7, 0x22, 0xF2, 0xF7, 0xA8, 0xFB, 0xB5, 0xE6, 0x00, 0x2A, 0xBF, 0xF6, 0xB3, 0xAE, 0x04, 0x2F, 0x3F, 0xF4, ++0x0A, 0xAF, 0x13, 0x49, 0x1B, 0x48, 0x4F, 0xF4, 0x37, 0x72, 0xF2, 0xF7, 0x9B, 0xFB, 0xA8, 0xE6, 0x0F, 0x49, 0x19, 0x48, ++0x40, 0xF2, 0x02, 0x32, 0xF2, 0xF7, 0x94, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0xD7, 0xAE, 0xB4, 0xE6, 0x08, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x01, 0x32, 0xF2, 0xF7, 0x86, 0xFB, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xA8, 0xAE, 0xBA, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0xC5, 0xAE, 0xDF, 0xE7, ++0x70, 0x79, 0x15, 0x00, 0x08, 0xC6, 0x15, 0x00, 0xB0, 0xC7, 0x15, 0x00, 0xF0, 0xC8, 0x15, 0x00, 0xA8, 0xC9, 0x15, 0x00, ++0xA8, 0xC6, 0x15, 0x00, 0x3C, 0xC8, 0x15, 0x00, 0x48, 0xC6, 0x15, 0x00, 0x04, 0xC7, 0x15, 0x00, 0xE8, 0xC6, 0x15, 0x00, ++0x64, 0xC7, 0x15, 0x00, 0x58, 0xC7, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x2A, 0xBF, 0xF6, 0x6C, 0xAE, 0x05, 0x2F, ++0x3F, 0xF4, 0x05, 0xAF, 0xA9, 0x49, 0xAA, 0x48, 0x40, 0xF2, 0xEB, 0x22, 0xF2, 0xF7, 0x54, 0xFB, 0x61, 0xE6, 0x00, 0x2A, ++0xBF, 0xF6, 0x5F, 0xAE, 0xBA, 0x1E, 0x01, 0x2A, 0x7F, 0xF6, 0x54, 0xAF, 0xA2, 0x49, 0xA4, 0x48, 0x40, 0xF2, 0xCE, 0x22, ++0xF2, 0xF7, 0x46, 0xFB, 0x53, 0xE6, 0x00, 0x2A, 0xBF, 0xF6, 0x6B, 0xAE, 0x01, 0x9B, 0x00, 0x2B, 0x7F, 0xF4, 0x80, 0xAE, ++0x40, 0xF2, 0xFB, 0x22, 0x9A, 0x49, 0x9D, 0x48, 0xF2, 0xF7, 0x38, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x20, ++0x72, 0xE6, 0xBA, 0xF1, 0x02, 0x0F, 0x7F, 0xF4, 0x58, 0xAE, 0xB9, 0xF1, 0x03, 0x0F, 0x03, 0xD0, 0xB9, 0xF1, 0x06, 0x0F, ++0x7F, 0xF4, 0x51, 0xAE, 0x90, 0x49, 0x94, 0x48, 0x40, 0xF2, 0x1F, 0x32, 0xC1, 0xE6, 0x8E, 0x49, 0x92, 0x48, 0x4F, 0xF4, ++0x44, 0x72, 0xF2, 0xF7, 0x1D, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x31, 0xAF, ++0x3D, 0xE6, 0x87, 0x49, 0x8C, 0x48, 0x40, 0xF2, 0x0F, 0x32, 0xF2, 0xF7, 0x0F, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x1E, 0xAF, 0x2F, 0xE6, 0x80, 0x49, 0x86, 0x48, 0x40, 0xF2, 0x11, 0x32, 0xF2, 0xF7, ++0x01, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x1A, 0xAF, 0x21, 0xE6, 0x79, 0x49, ++0x80, 0x48, 0x40, 0xF2, 0xC2, 0x22, 0xF2, 0xF7, 0xF3, 0xFA, 0x00, 0xE6, 0x75, 0x49, 0x7E, 0x48, 0x40, 0xF2, 0x1E, 0x32, ++0xF2, 0xF7, 0xEC, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x71, 0xAE, 0x0C, 0xE6, ++0x6E, 0x49, 0x78, 0x48, 0x4F, 0xF4, 0x41, 0x72, 0xF2, 0xF7, 0xDE, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xFF, 0xF6, 0x2A, 0xAE, 0xFE, 0xE5, 0x67, 0x49, 0x72, 0x48, 0x40, 0xF2, 0x03, 0x32, 0xF2, 0xF7, 0xD0, 0xFA, ++0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x17, 0xAE, 0xF0, 0xE5, 0x60, 0x49, 0x6C, 0x48, ++0x40, 0xF2, 0x19, 0x32, 0xF2, 0xF7, 0xC2, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0x28, 0xAE, 0xE2, 0xE5, 0x59, 0x49, 0x66, 0x48, 0x40, 0xF2, 0x05, 0x32, 0xF2, 0xF7, 0xB4, 0xFA, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x05, 0xAE, 0xD4, 0xE5, 0x52, 0x49, 0x58, 0x48, 0x4F, 0xF4, 0x4B, 0x72, ++0xF2, 0xF7, 0xA6, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x55, 0xAE, 0xC6, 0xE5, ++0x4B, 0x49, 0x59, 0x48, 0x40, 0xF2, 0x0E, 0x32, 0xF2, 0xF7, 0x98, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xFF, 0xF6, 0xA2, 0xAE, 0xB8, 0xE5, 0x44, 0x49, 0x50, 0x48, 0x40, 0xF2, 0x0D, 0x32, 0xF2, 0xF7, 0x8A, 0xFA, ++0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x8F, 0xAE, 0xAA, 0xE5, 0x3D, 0x49, 0x44, 0x48, ++0x40, 0xF2, 0x2E, 0x32, 0xF2, 0xF7, 0x7C, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0x35, 0xAE, 0x9C, 0xE5, 0x36, 0x49, 0x3B, 0x48, 0x40, 0xF2, 0x2D, 0x32, 0xF2, 0xF7, 0x6E, 0xFA, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x22, 0xAE, 0x8E, 0xE5, 0x2F, 0x49, 0x36, 0x48, 0x40, 0xF2, 0x1D, 0x32, ++0xF2, 0xF7, 0x60, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xDA, 0xAD, 0x80, 0xE5, ++0x28, 0x49, 0x2D, 0x48, 0x4F, 0xF4, 0x47, 0x72, 0xF2, 0xF7, 0x52, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xFF, 0xF6, 0xC7, 0xAD, 0x72, 0xE5, 0x21, 0x49, 0x27, 0x48, 0x40, 0xF2, 0x1B, 0x32, 0xF2, 0xF7, 0x44, 0xFA, ++0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xB4, 0xAD, 0x64, 0xE5, 0x1A, 0x49, 0x28, 0x48, ++0x40, 0xF2, 0x1A, 0x32, 0xF2, 0xF7, 0x36, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0xA1, 0xAD, 0x56, 0xE5, 0x13, 0x49, 0x22, 0x48, 0x40, 0xF2, 0x2B, 0x32, 0xF2, 0xF7, 0x28, 0xFA, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xD2, 0xAD, 0x48, 0xE5, 0xBA, 0xF1, 0x02, 0x0F, 0x08, 0xD1, 0xB9, 0xF1, ++0x05, 0x0F, 0x7F, 0xF4, 0x42, 0xAD, 0x09, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x21, 0x32, 0xB2, 0xE5, 0xBA, 0xF1, 0x03, 0x0F, ++0x7F, 0xF4, 0x39, 0xAD, 0xB9, 0xF1, 0x02, 0x0F, 0x7F, 0xF4, 0x35, 0xAD, 0x02, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x22, 0x32, ++0xA5, 0xE5, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0xD8, 0x93, 0x15, 0x00, 0x64, 0xC6, 0x15, 0x00, 0x48, 0xC7, 0x15, 0x00, ++0xAC, 0xC8, 0x15, 0x00, 0x10, 0xC8, 0x15, 0x00, 0xFC, 0xC7, 0x15, 0x00, 0x24, 0xC8, 0x15, 0x00, 0x28, 0xC6, 0x15, 0x00, ++0x64, 0xC8, 0x15, 0x00, 0x80, 0xC7, 0x15, 0x00, 0x74, 0xC7, 0x15, 0x00, 0xD4, 0xC7, 0x15, 0x00, 0x98, 0xC7, 0x15, 0x00, ++0xE4, 0xC7, 0x15, 0x00, 0xA0, 0xC9, 0x15, 0x00, 0x34, 0xC9, 0x15, 0x00, 0x68, 0xC9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x04, 0x46, 0x04, 0xF0, 0x89, 0xFD, 0x94, 0xF8, 0xA5, 0x10, 0x94, 0xF8, 0xAF, 0x20, 0xCB, 0x02, 0x9B, 0xB2, 0x92, 0xB3, ++0x55, 0x1E, 0xED, 0xB2, 0x05, 0x29, 0x2B, 0xD8, 0xDF, 0xE8, 0x01, 0xF0, 0x6D, 0x6D, 0x2F, 0x2F, 0x94, 0x03, 0x94, 0xF8, ++0xAD, 0x10, 0x03, 0x29, 0x00, 0xF2, 0xD1, 0x80, 0x06, 0x05, 0x40, 0xF1, 0xCE, 0x80, 0x94, 0xF8, 0xAE, 0x60, 0xB4, 0xF8, ++0xAA, 0x20, 0x73, 0x1A, 0x01, 0x33, 0x00, 0xF0, 0x7F, 0x07, 0x97, 0xFB, 0xF3, 0xF5, 0x03, 0xFB, 0x15, 0x73, 0x19, 0x44, ++0xC9, 0xB2, 0x22, 0xFA, 0x01, 0xF3, 0x13, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x31, 0x46, 0x00, 0x29, 0x00, 0xF0, 0x3F, 0x81, ++0x94, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x63, 0x43, 0xEA, 0x82, 0x23, 0x0B, 0x43, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, ++0xF0, 0x81, 0x15, 0x46, 0xCC, 0xE7, 0x94, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x01, 0xD8, 0x06, 0x05, 0xD5, 0xD4, 0x94, 0xF8, ++0xB0, 0x70, 0x94, 0xF8, 0xAC, 0x60, 0x94, 0xF8, 0xB1, 0xC0, 0x01, 0x37, 0xC0, 0xF3, 0xC1, 0x01, 0xB1, 0xFB, 0xF7, 0xFE, ++0x07, 0xFB, 0x1E, 0x11, 0x0C, 0x44, 0x06, 0xF1, 0x01, 0x0E, 0x00, 0xF0, 0x07, 0x08, 0x94, 0xF8, 0xA6, 0x70, 0xB8, 0xFB, ++0xFE, 0xF4, 0x0E, 0xFB, 0x14, 0x84, 0xE7, 0x40, 0xFF, 0x07, 0x48, 0xBF, 0xE6, 0xB2, 0x52, 0x1B, 0x0C, 0xF1, 0x01, 0x04, ++0xC0, 0xF3, 0x40, 0x2C, 0x01, 0x32, 0xC0, 0xF3, 0xC1, 0x10, 0xBC, 0xFB, 0xF4, 0xF7, 0xC9, 0x00, 0x04, 0xFB, 0x17, 0xC4, ++0x41, 0xEA, 0x44, 0x21, 0x90, 0xFB, 0xF2, 0xF4, 0x02, 0xFB, 0x14, 0x00, 0x05, 0x44, 0x0B, 0x43, 0x43, 0xEA, 0xC5, 0x13, ++0x9B, 0xB2, 0x33, 0x43, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x94, 0xF8, 0xAE, 0x70, 0x94, 0xF8, 0xAD, 0x20, 0xB4, 0xF8, ++0xAA, 0x50, 0xB9, 0x1A, 0x01, 0x31, 0x00, 0xF0, 0x7F, 0x0C, 0x9C, 0xFB, 0xF1, 0xF6, 0x01, 0xFB, 0x16, 0xC1, 0x0A, 0x44, ++0xD2, 0xB2, 0x25, 0xFA, 0x02, 0xF1, 0x11, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x3A, 0x46, 0x13, 0x43, 0x00, 0x2A, 0x00, 0xF0, ++0xA2, 0x80, 0x01, 0x3A, 0xD2, 0xB2, 0x02, 0x2A, 0x9E, 0xD8, 0x94, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x60, 0x40, 0xEA, ++0x82, 0x20, 0x03, 0x43, 0x9B, 0xB2, 0x95, 0xE7, 0x94, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x40, 0xF2, 0x8C, 0x80, 0x94, 0xF8, ++0xB0, 0x10, 0xB4, 0xF8, 0xA6, 0x70, 0x94, 0xF8, 0xAC, 0xC0, 0x94, 0xF8, 0xB1, 0x40, 0x4E, 0x1C, 0xC0, 0xF3, 0x02, 0x11, ++0xB1, 0xFB, 0xF6, 0xFE, 0x06, 0xFB, 0x1E, 0x11, 0x4E, 0x00, 0x37, 0x41, 0x07, 0xF0, 0x03, 0x07, 0x0C, 0xF1, 0x01, 0x06, ++0x00, 0xF0, 0x0F, 0x0C, 0x07, 0x37, 0xBC, 0xFB, 0xF6, 0xFE, 0x06, 0xFB, 0x1E, 0xCC, 0xBC, 0x45, 0xCE, 0xB2, 0xA2, 0xEB, ++0x05, 0x02, 0x40, 0xF3, 0x81, 0x80, 0x02, 0xF1, 0x01, 0x0C, 0xC0, 0xF3, 0xC1, 0x1E, 0x9E, 0xFB, 0xFC, 0xF2, 0x0C, 0xFB, ++0x12, 0xE2, 0x15, 0x44, 0xFF, 0xB2, 0xED, 0xB2, 0x09, 0x2F, 0x40, 0xF0, 0xAE, 0x80, 0x00, 0x2D, 0x40, 0xF0, 0x98, 0x80, ++0x02, 0x29, 0x00, 0xF0, 0xC0, 0x80, 0x05, 0x2E, 0x14, 0xBF, 0x4F, 0xF0, 0x08, 0x0C, 0x4F, 0xF0, 0x09, 0x0C, 0x09, 0x01, ++0x09, 0xB2, 0x00, 0x25, 0x76, 0xE0, 0x94, 0xF8, 0xB0, 0x70, 0xB4, 0xF8, 0xA6, 0x60, 0x94, 0xF8, 0xAC, 0xC0, 0x79, 0x1C, ++0xC0, 0xF3, 0x02, 0x17, 0xB7, 0xFB, 0xF1, 0xFE, 0x01, 0xFB, 0x1E, 0x77, 0x79, 0x00, 0x0E, 0x41, 0x06, 0xF0, 0x03, 0x06, ++0x0C, 0xF1, 0x01, 0x0C, 0x00, 0xF0, 0x0F, 0x01, 0x76, 0x00, 0x07, 0x36, 0xB1, 0xFB, 0xFC, 0xFE, 0x0C, 0xFB, 0x1E, 0x11, ++0xB1, 0x42, 0xC0, 0xF3, 0x41, 0x2C, 0xA2, 0xEB, 0x05, 0x02, 0xC8, 0xBF, 0xF1, 0xB2, 0x02, 0xF1, 0x01, 0x02, 0xC0, 0xF3, ++0xC1, 0x1E, 0xD8, 0xBF, 0xC9, 0xB2, 0xBC, 0xF1, 0x03, 0x0F, 0x18, 0xBF, 0x4F, 0xEA, 0x4C, 0x26, 0x9E, 0xFB, 0xF2, 0xFC, ++0x02, 0xFB, 0x1C, 0xEC, 0x94, 0xF8, 0xBC, 0x20, 0x65, 0x44, 0x08, 0xBF, 0x4F, 0xF4, 0x80, 0x66, 0xED, 0xB2, 0xEA, 0xB1, ++0x02, 0x29, 0x1A, 0xD0, 0x94, 0xF8, 0xBD, 0x20, 0x8A, 0x42, 0x16, 0xD3, 0x94, 0xF8, 0xBE, 0xC0, 0xFA, 0xB2, 0x94, 0x45, ++0x11, 0xD3, 0x94, 0xF8, 0xBF, 0x20, 0xAA, 0x42, 0x0D, 0xD3, 0x00, 0xF4, 0x80, 0x42, 0x12, 0xB2, 0x0A, 0xE0, 0x07, 0x05, ++0x7F, 0xF5, 0x71, 0xAF, 0xE1, 0xE6, 0x43, 0xF4, 0x80, 0x63, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x22, ++0x43, 0xEA, 0x07, 0x13, 0x43, 0xEA, 0xC5, 0x15, 0x29, 0x43, 0x31, 0x43, 0x42, 0xEA, 0x01, 0x03, 0x9B, 0xB2, 0x18, 0x46, ++0xBD, 0xE8, 0xF0, 0x81, 0x57, 0x1C, 0xC0, 0xF3, 0xC1, 0x1E, 0x9E, 0xFB, 0xF7, 0xF2, 0x07, 0xFB, 0x12, 0xE2, 0x15, 0x44, ++0xBC, 0xF1, 0x06, 0x0F, 0xED, 0xB2, 0x5F, 0xFA, 0x8C, 0xF7, 0x7F, 0xF4, 0x7B, 0xAF, 0x02, 0x2D, 0x20, 0xD0, 0x09, 0x01, ++0x09, 0xB2, 0xED, 0x01, 0x01, 0x34, 0xC0, 0xF3, 0x40, 0x20, 0xB0, 0xFB, 0xF4, 0xF2, 0x04, 0xFB, 0x12, 0x00, 0x43, 0xEA, ++0x40, 0x23, 0x2B, 0x43, 0x0B, 0x43, 0x4C, 0xEA, 0x03, 0x03, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, ++0x80, 0x63, 0xC5, 0xE6, 0x02, 0x2D, 0x16, 0xD1, 0x05, 0x29, 0x2D, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0xBC, 0x46, 0x4F, 0xF4, ++0x80, 0x75, 0xE1, 0xE7, 0x03, 0x29, 0x16, 0xD0, 0x06, 0x29, 0x14, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0x4F, 0xF4, 0x80, 0x75, ++0xD8, 0xE7, 0x09, 0x01, 0x09, 0xB2, 0xED, 0x01, 0x0F, 0xFA, 0x87, 0xFC, 0xD2, 0xE7, 0x03, 0x2D, 0x1B, 0xD1, 0x02, 0x29, ++0x0F, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0xBC, 0x46, 0x4F, 0xF4, 0xC0, 0x75, 0xC8, 0xE7, 0x71, 0x1E, 0xC9, 0xB2, 0x09, 0x01, ++0x4F, 0xF0, 0x06, 0x0C, 0x4F, 0xF4, 0x80, 0x75, 0xC0, 0xE7, 0xBC, 0x46, 0x43, 0xE7, 0xBC, 0x46, 0x10, 0x21, 0x4F, 0xF4, ++0xC0, 0x75, 0xB9, 0xE7, 0xBC, 0x46, 0x40, 0x21, 0x4F, 0xF4, 0x80, 0x75, 0xB4, 0xE7, 0x09, 0x01, 0x09, 0xB2, 0xED, 0x01, ++0xBC, 0x46, 0xAF, 0xE7, 0xB0, 0xF8, 0xB4, 0x30, 0x00, 0x2B, 0x4A, 0xD0, 0x2D, 0xE9, 0xF0, 0x4F, 0x03, 0xF1, 0xFF, 0x3B, ++0x1F, 0xFA, 0x8B, 0xFB, 0xBB, 0xF1, 0x01, 0x0F, 0x85, 0xB0, 0x8A, 0x46, 0x00, 0xF1, 0x10, 0x09, 0x3A, 0xD9, 0x01, 0x25, ++0x2F, 0x46, 0x0A, 0xF1, 0x04, 0x04, 0x4E, 0x46, 0x00, 0x21, 0x0D, 0xE0, 0x13, 0x43, 0x04, 0xD1, 0x73, 0x7A, 0x13, 0xB9, ++0x73, 0x7D, 0x01, 0x2B, 0x0B, 0xD0, 0x01, 0x35, 0xAF, 0xB2, 0x06, 0xF1, 0x0C, 0x08, 0x5F, 0x45, 0x46, 0x46, 0x20, 0xD2, ++0x22, 0x68, 0x54, 0xF8, 0x04, 0x3F, 0x9A, 0x42, 0xEC, 0xD9, 0x0C, 0x22, 0x06, 0xEB, 0x02, 0x08, 0x31, 0x46, 0x01, 0xA8, ++0x04, 0xF0, 0x3E, 0xFB, 0x30, 0x46, 0x41, 0x46, 0x0C, 0x22, 0x04, 0xF0, 0x39, 0xFB, 0x0C, 0x22, 0x01, 0xA9, 0x40, 0x46, ++0x04, 0xF0, 0x34, 0xFB, 0x01, 0x35, 0x54, 0xE9, 0x01, 0x32, 0x39, 0x46, 0xAF, 0xB2, 0x5F, 0x45, 0x44, 0xF8, 0x04, 0x2C, ++0x23, 0x60, 0x46, 0x46, 0xDE, 0xD3, 0x19, 0xB1, 0x8B, 0x46, 0xBB, 0xF1, 0x01, 0x0F, 0xC4, 0xD8, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0xB0, 0xF8, 0xB4, 0x50, 0x83, 0xB0, 0x06, 0x46, 0x89, 0x46, 0x00, 0x2D, ++0x00, 0xF0, 0xE2, 0x80, 0x6F, 0x1E, 0x1F, 0xFA, 0x87, 0xF8, 0x08, 0xEB, 0x48, 0x08, 0x00, 0xF1, 0x0C, 0x03, 0x03, 0xEB, ++0x88, 0x08, 0x04, 0x46, 0x4F, 0xF0, 0x00, 0x0A, 0x41, 0xF6, 0x98, 0x1B, 0x60, 0x89, 0xFE, 0xF7, 0xAD, 0xFE, 0x30, 0xB9, ++0x63, 0x7B, 0x23, 0xB1, 0x23, 0x89, 0x5B, 0x45, 0x07, 0xD8, 0x4F, 0xF0, 0x01, 0x0A, 0x0C, 0x34, 0x44, 0x45, 0xF1, 0xD1, ++0x4F, 0xEA, 0xCA, 0x00, 0x40, 0xB2, 0x96, 0xF8, 0xA2, 0x40, 0x24, 0xF0, 0x08, 0x04, 0x04, 0x43, 0xE4, 0xB2, 0x86, 0xF8, ++0xA2, 0x40, 0x14, 0xF0, 0x02, 0x04, 0x09, 0xD1, 0x05, 0xF1, 0x80, 0x43, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x59, 0xF8, ++0x23, 0x30, 0x9A, 0x42, 0x00, 0xF2, 0x9C, 0x80, 0x1F, 0xFA, 0x87, 0xFB, 0xCD, 0xF8, 0x00, 0xB0, 0x4F, 0xF0, 0x02, 0x08, ++0x00, 0x9C, 0xA6, 0xF8, 0x88, 0xB0, 0x04, 0xEB, 0x44, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x58, 0x89, 0xFE, 0xF7, 0x7A, 0xFE, ++0x63, 0x00, 0x01, 0x93, 0xE0, 0xB9, 0x00, 0x2F, 0x13, 0xDD, 0x82, 0x46, 0x84, 0x46, 0x0C, 0xEB, 0x4C, 0x0C, 0x06, 0xEB, ++0x8C, 0x04, 0x60, 0x89, 0xFE, 0xF7, 0x6C, 0xFE, 0x0A, 0xF1, 0x01, 0x03, 0x1F, 0xFA, 0x83, 0xFA, 0xD4, 0x46, 0x10, 0xB1, ++0x4F, 0xF0, 0x00, 0x03, 0xA3, 0x73, 0xBA, 0x45, 0xED, 0xDB, 0xDD, 0xE9, 0x00, 0x23, 0x13, 0x44, 0x06, 0xEB, 0x83, 0x04, ++0x01, 0x23, 0xA3, 0x73, 0xA8, 0x45, 0xA6, 0xF8, 0x8A, 0xB0, 0x76, 0xD2, 0xA5, 0xEB, 0x08, 0x03, 0x03, 0xEB, 0x43, 0x03, ++0x06, 0xEB, 0x83, 0x03, 0x03, 0xE0, 0x1F, 0xFA, 0x80, 0xF8, 0xA8, 0x45, 0x6B, 0xD0, 0x99, 0x7B, 0x08, 0xF1, 0x01, 0x00, ++0x0C, 0x3B, 0x00, 0x29, 0xF5, 0xD0, 0xA5, 0xEB, 0x08, 0x00, 0x08, 0xF1, 0x01, 0x08, 0x1F, 0xFA, 0x88, 0xF8, 0x80, 0xB2, ++0x45, 0x45, 0xA6, 0xF8, 0x8A, 0x00, 0x58, 0xD9, 0xA5, 0xEB, 0x08, 0x05, 0xA7, 0xEB, 0x08, 0x08, 0x4F, 0xEA, 0x18, 0x48, ++0x05, 0xEB, 0x45, 0x03, 0x4F, 0xEA, 0x08, 0x48, 0x06, 0xEB, 0x83, 0x03, 0x02, 0xE0, 0x01, 0x3D, 0x45, 0x45, 0x48, 0xD0, ++0x99, 0x7B, 0x0C, 0x3B, 0x00, 0x29, 0xF8, 0xD0, 0x05, 0xEB, 0x45, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x59, 0xF8, 0x25, 0x20, ++0xB3, 0xF8, 0x08, 0xE0, 0x30, 0xB3, 0x31, 0x46, 0x00, 0x23, 0x4F, 0xF2, 0x32, 0x38, 0x0C, 0xE0, 0x59, 0xF8, 0x23, 0x70, ++0x97, 0x42, 0x02, 0xD3, 0xA6, 0x46, 0x3A, 0x46, 0x1D, 0x46, 0x01, 0x33, 0x9C, 0xB2, 0xA0, 0x42, 0x01, 0xF1, 0x0C, 0x01, ++0x14, 0xD9, 0x8C, 0x7B, 0x9F, 0xB2, 0x00, 0x2C, 0xF5, 0xD0, 0x5F, 0x45, 0xF3, 0xD0, 0x0C, 0x89, 0x44, 0x45, 0xE9, 0xD8, ++0x74, 0x45, 0xEE, 0xD3, 0x59, 0xF8, 0x23, 0x20, 0x1D, 0x46, 0x01, 0x33, 0xA6, 0x46, 0x9C, 0xB2, 0xA0, 0x42, 0x01, 0xF1, ++0x0C, 0x01, 0xEA, 0xD8, 0x00, 0x23, 0xA6, 0xF8, 0x8C, 0x50, 0xA6, 0xF8, 0x8E, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x07, 0xEB, 0x47, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x5B, 0x7B, 0x00, 0x2B, 0x3F, 0xF4, 0x5C, 0xAF, 0x00, 0x94, 0xA3, 0x46, ++0x4F, 0xF0, 0x01, 0x08, 0x5C, 0xE7, 0x05, 0x46, 0xB8, 0xE7, 0x5D, 0x46, 0x58, 0x46, 0xB5, 0xE7, 0x28, 0x46, 0x4F, 0xF0, ++0xFF, 0x37, 0x38, 0xE7, 0xC1, 0xF3, 0xC2, 0x23, 0x05, 0x2B, 0x5B, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x03, 0x27, 0x27, ++0x0B, 0x32, 0xB0, 0xF8, 0xAA, 0x00, 0x01, 0xF0, 0x7F, 0x01, 0xC8, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x70, 0x47, 0xC1, 0xF3, ++0x02, 0x12, 0xB0, 0xF8, 0xA6, 0x00, 0x53, 0x00, 0x18, 0x41, 0x00, 0xF0, 0x03, 0x00, 0x07, 0x30, 0x01, 0xF0, 0x0F, 0x03, ++0x83, 0x42, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x06, 0x2B, 0xC1, 0xF3, 0xC1, 0x11, 0x24, 0xD0, 0x09, 0x2B, 0x24, 0xD1, ++0x21, 0xBB, 0x02, 0x2A, 0x21, 0xD0, 0x05, 0x2A, 0x18, 0xBF, 0x00, 0x20, 0x70, 0x47, 0xC1, 0xF3, 0xC1, 0x03, 0x18, 0x44, ++0x01, 0xF0, 0x07, 0x01, 0x90, 0xF8, 0xA6, 0x00, 0xC8, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x70, 0x47, 0xB0, 0xF8, 0xA6, 0x00, ++0xC1, 0xF3, 0x02, 0x13, 0x5B, 0x00, 0x18, 0x41, 0x00, 0xF0, 0x03, 0x00, 0x40, 0x00, 0x07, 0x30, 0x01, 0xF0, 0x0F, 0x01, ++0x81, 0x42, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x02, 0x29, 0x06, 0xD0, 0x70, 0x47, 0x02, 0x29, 0x09, 0xD1, ++0x05, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, 0x03, 0x2A, 0x09, 0xD0, 0x06, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, ++0x03, 0x29, 0xF0, 0xD1, 0x02, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0xEA, 0xE7, 0x01, 0x20, 0x70, 0x47, ++0x2D, 0xE9, 0xF0, 0x4F, 0x82, 0x46, 0xB0, 0xF8, 0x88, 0x70, 0xB0, 0xF8, 0x8A, 0x00, 0x9A, 0xF8, 0xAD, 0x30, 0x9A, 0xF8, ++0xAE, 0x60, 0x00, 0xEB, 0x40, 0x00, 0x07, 0xEB, 0x47, 0x07, 0x83, 0xB0, 0x0A, 0xEB, 0x80, 0x0C, 0x0A, 0xEB, 0x87, 0x07, ++0x14, 0x46, 0x0D, 0x46, 0x08, 0x46, 0x52, 0x00, 0x4F, 0xF0, 0xFF, 0x31, 0x7F, 0x89, 0xBC, 0xF8, 0x0A, 0x80, 0x00, 0x93, ++0xCD, 0xF7, 0x86, 0xF9, 0x00, 0x2C, 0x7E, 0xD0, 0x00, 0x9B, 0xA6, 0xEB, 0x03, 0x09, 0x01, 0x3C, 0x09, 0xF1, 0x01, 0x03, ++0xE4, 0xB2, 0x01, 0x93, 0x4F, 0xF0, 0x00, 0x0B, 0x5F, 0xFA, 0x8B, 0xF3, 0x05, 0x2B, 0x5E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, ++0x59, 0x41, 0x32, 0x23, 0x13, 0x03, 0x41, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xF9, 0xFF, 0x80, 0x45, 0x81, 0x46, 0x52, 0xD0, ++0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x5E, 0xFF, 0x00, 0x28, 0x4C, 0xD0, 0xA5, 0xF8, 0x0A, 0x90, 0x49, 0xE0, 0x41, 0x46, ++0x50, 0x46, 0xFF, 0xF7, 0x77, 0xF8, 0x80, 0x45, 0x81, 0x46, 0x42, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x4E, 0xFF, ++0x00, 0x28, 0x3C, 0xD0, 0xA5, 0xF8, 0x08, 0x90, 0x39, 0xE0, 0x39, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xD9, 0xFF, 0xB8, 0x42, ++0x81, 0x46, 0x32, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x3E, 0xFF, 0x68, 0xB3, 0xA5, 0xF8, 0x06, 0x90, 0x2A, 0xE0, ++0x39, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x58, 0xF8, 0xB8, 0x42, 0x81, 0x46, 0x23, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, ++0x2F, 0xFF, 0xF0, 0xB1, 0xA5, 0xF8, 0x04, 0x90, 0x1B, 0xE0, 0x00, 0x9B, 0x03, 0x2B, 0x03, 0xD8, 0x9A, 0xF8, 0xA2, 0x30, ++0x19, 0x07, 0x3B, 0xD4, 0xC7, 0xF3, 0xC2, 0x23, 0x05, 0x2B, 0x4F, 0xEA, 0xD7, 0x22, 0x23, 0xD0, 0x12, 0xF0, 0x06, 0x0F, ++0x0B, 0xD0, 0x9A, 0xF8, 0xB1, 0x30, 0x01, 0x2B, 0x07, 0xD1, 0x87, 0xF4, 0x00, 0x73, 0x6B, 0x80, 0x03, 0xE0, 0x50, 0x46, ++0xFF, 0xF7, 0x1E, 0xFC, 0x28, 0x80, 0x03, 0x2E, 0x09, 0xD8, 0x35, 0xF8, 0x1B, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, ++0x04, 0xBF, 0x46, 0xF4, 0x80, 0x63, 0x25, 0xF8, 0x1B, 0x30, 0x5C, 0x45, 0x0B, 0xF1, 0x01, 0x03, 0x01, 0xD0, 0x9B, 0x46, ++0x8A, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0x4A, 0xC7, 0xF3, 0x41, 0x23, 0x01, 0x33, 0xA2, 0xFB, 0x03, 0x21, ++0x21, 0xF0, 0x01, 0x02, 0x02, 0xEB, 0x51, 0x02, 0x27, 0xF4, 0xC0, 0x67, 0x9B, 0x1A, 0x47, 0xEA, 0x43, 0x23, 0x6B, 0x80, ++0xBF, 0xB2, 0xD8, 0xE7, 0x04, 0xF0, 0x82, 0xF9, 0x01, 0x99, 0x00, 0xF0, 0x7F, 0x02, 0x92, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, ++0x13, 0x23, 0x00, 0x9A, 0x13, 0x44, 0xBA, 0xF8, 0xAA, 0x20, 0xDB, 0xB2, 0xDA, 0x40, 0xD2, 0x07, 0x0F, 0xD5, 0x00, 0x2B, ++0x08, 0xBF, 0x33, 0x46, 0x5A, 0x1E, 0x02, 0x2A, 0x6B, 0x80, 0xCC, 0xD8, 0x9A, 0xF8, 0xB2, 0x10, 0x00, 0xF4, 0x80, 0x62, ++0x42, 0xEA, 0x81, 0x22, 0x13, 0x43, 0x6B, 0x80, 0xC3, 0xE7, 0x33, 0x46, 0xF0, 0xE7, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, ++0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x84, 0xB0, 0x01, 0xA9, 0x06, 0x22, 0xFF, 0xF7, 0x1C, 0xFF, 0xB5, 0xF8, 0xB4, 0x10, ++0x01, 0x29, 0x30, 0xD9, 0x00, 0x26, 0x01, 0x24, 0xB0, 0x46, 0xA1, 0x46, 0x4F, 0xF6, 0xFF, 0x77, 0x18, 0xE0, 0xB5, 0xF8, ++0x88, 0x20, 0xA2, 0x42, 0x21, 0xD0, 0xB5, 0xF8, 0x8A, 0x20, 0xA2, 0x42, 0x1D, 0xD0, 0xB5, 0xF8, 0x8C, 0x20, 0xA2, 0x42, ++0x19, 0xD0, 0x05, 0x2E, 0x17, 0xD8, 0x04, 0xAA, 0x02, 0xEB, 0x46, 0x02, 0x32, 0xF8, 0x0C, 0xEC, 0xBE, 0x45, 0x17, 0xD1, ++0xA1, 0x42, 0x06, 0xF1, 0x01, 0x06, 0x10, 0xD9, 0x04, 0xEB, 0x44, 0x03, 0x05, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0x44, 0x0C, ++0xB3, 0xF9, 0x08, 0x20, 0x00, 0x2A, 0xDC, 0xDA, 0x1A, 0x7B, 0x0A, 0x2A, 0xD9, 0xD8, 0x01, 0x34, 0xA4, 0xB2, 0xA1, 0x42, ++0xEE, 0xD8, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x59, 0xB1, 0x2A, 0x46, 0x00, 0x20, 0xB2, 0xF8, 0x0A, 0xA0, 0xF2, 0x45, ++0x00, 0xF1, 0x01, 0x00, 0x02, 0xF1, 0x0C, 0x02, 0xDC, 0xD0, 0x88, 0x42, 0xF5, 0xD1, 0x0C, 0xEB, 0x04, 0x02, 0x05, 0xEB, ++0x82, 0x02, 0xA3, 0xF8, 0x0A, 0xE0, 0xA3, 0xF8, 0x08, 0x80, 0x21, 0x46, 0x82, 0xF8, 0x0D, 0x80, 0x28, 0x46, 0xA3, 0xF8, ++0x04, 0x80, 0xA3, 0xF8, 0x06, 0x80, 0x01, 0x34, 0x82, 0xF8, 0x0C, 0x80, 0x82, 0xF8, 0x0E, 0x90, 0xFF, 0xF7, 0x12, 0xF8, ++0xA4, 0xB2, 0xB5, 0xF8, 0xB4, 0x10, 0xBF, 0xE7, 0x30, 0xB4, 0x90, 0xF8, 0xA5, 0x30, 0x05, 0x2B, 0x00, 0xF2, 0x8C, 0x80, ++0xDF, 0xE8, 0x03, 0xF0, 0x36, 0x36, 0x03, 0x03, 0x70, 0x57, 0x90, 0xF8, 0xAF, 0x50, 0x90, 0xF8, 0xB1, 0x20, 0x90, 0xF8, ++0xB0, 0x30, 0x90, 0xF8, 0xA6, 0x40, 0x01, 0x35, 0x95, 0x40, 0x03, 0xFB, 0x05, 0x55, 0xAD, 0xB2, 0x08, 0x21, 0x00, 0x23, ++0x04, 0xF0, 0x01, 0x02, 0x12, 0xFB, 0x05, 0xF2, 0x13, 0x44, 0x01, 0x39, 0x9B, 0xB2, 0x4F, 0xEA, 0x54, 0x04, 0xF5, 0xD1, ++0xB0, 0xF8, 0xAA, 0x20, 0x90, 0xF8, 0xB2, 0x10, 0xC2, 0xF3, 0x80, 0x04, 0xC2, 0xF3, 0x40, 0x00, 0xC1, 0xF1, 0x01, 0x01, ++0x20, 0x44, 0x88, 0x40, 0x02, 0xF0, 0x01, 0x04, 0xC2, 0xF3, 0xC0, 0x02, 0x20, 0x44, 0x8A, 0x40, 0x10, 0x44, 0x18, 0x44, ++0x80, 0xB2, 0x0A, 0x28, 0x28, 0xBF, 0x0A, 0x20, 0x30, 0xBC, 0x70, 0x47, 0xB0, 0xF8, 0xAA, 0x10, 0x90, 0xF8, 0xB2, 0x30, ++0xC1, 0xF3, 0x80, 0x02, 0xC1, 0xF3, 0x40, 0x00, 0xC3, 0xF1, 0x01, 0x03, 0x10, 0x44, 0x98, 0x40, 0x01, 0xF0, 0x01, 0x04, ++0xC1, 0xF3, 0xC0, 0x02, 0x02, 0xFA, 0x03, 0xF3, 0x20, 0x44, 0x13, 0xFA, 0x80, 0xF0, 0x80, 0xB2, 0x04, 0x23, 0x41, 0xFA, ++0x03, 0xF2, 0x02, 0xF0, 0x01, 0x02, 0x01, 0x33, 0x10, 0x44, 0x0C, 0x2B, 0x80, 0xB2, 0xF6, 0xD1, 0xD9, 0xE7, 0x90, 0xF8, ++0xB1, 0x30, 0xB0, 0xF8, 0xA6, 0x20, 0x90, 0xF8, 0xAF, 0x40, 0x90, 0xF8, 0xB0, 0x10, 0x58, 0x1C, 0x02, 0xF0, 0x03, 0x03, ++0x04, 0xFB, 0x00, 0x00, 0x01, 0x2B, 0x01, 0xFB, 0x00, 0x00, 0x1F, 0xD0, 0x02, 0x2B, 0x14, 0xBF, 0x08, 0x23, 0x0A, 0x23, ++0x10, 0xFB, 0x03, 0xF0, 0x80, 0xB2, 0xC0, 0xE7, 0xB0, 0xF8, 0xA6, 0x20, 0x90, 0xF8, 0xAF, 0x30, 0x90, 0xF8, 0xB1, 0x40, ++0x90, 0xF8, 0xB0, 0x10, 0x02, 0xF0, 0x03, 0x02, 0x01, 0x33, 0x01, 0x3A, 0x03, 0xFA, 0x04, 0xF0, 0x01, 0x2A, 0x8C, 0xBF, ++0x08, 0x23, 0x09, 0x23, 0x01, 0xFB, 0x00, 0x00, 0x10, 0xFB, 0x03, 0xF0, 0x80, 0xB2, 0xA8, 0xE7, 0x09, 0x23, 0xE1, 0xE7, ++0x00, 0x20, 0xA7, 0xE7, 0x2D, 0xE9, 0xF8, 0x4F, 0xB0, 0xF8, 0xB4, 0x40, 0x05, 0x46, 0x00, 0x2C, 0x00, 0xF0, 0xF4, 0x80, ++0x04, 0xF1, 0xFF, 0x38, 0x1F, 0xFA, 0x88, 0xF1, 0x01, 0xEB, 0x41, 0x03, 0x00, 0xF1, 0x0C, 0x01, 0x01, 0xEB, 0x83, 0x01, ++0x4F, 0xF6, 0xFF, 0x76, 0x03, 0x46, 0x00, 0x22, 0x01, 0x20, 0x5E, 0x81, 0x9A, 0x80, 0xDA, 0x80, 0x1A, 0x81, 0x1A, 0x73, ++0x5A, 0x73, 0x98, 0x73, 0x0C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0xC1, 0x46, 0x95, 0xF8, 0xA5, 0x30, 0x05, 0x2B, 0x00, 0xF2, ++0xD9, 0x80, 0xDF, 0xE8, 0x03, 0xF0, 0x4E, 0x4E, 0x03, 0x03, 0x8A, 0x5E, 0x95, 0xF8, 0xAD, 0x20, 0xDB, 0x02, 0x00, 0x2A, ++0x00, 0xF0, 0xC7, 0x80, 0x99, 0xB2, 0x95, 0xF8, 0xB0, 0x20, 0x69, 0x81, 0xA9, 0x18, 0x95, 0xF8, 0xB1, 0x60, 0x91, 0xF8, ++0xA6, 0x70, 0x95, 0xF8, 0xAF, 0x00, 0x43, 0xEA, 0x46, 0x23, 0xB7, 0xFA, 0x87, 0xF7, 0xC7, 0xF1, 0x1F, 0x07, 0x43, 0xEA, ++0xC0, 0x13, 0xFF, 0xB2, 0x43, 0xEA, 0xC2, 0x03, 0x3B, 0x43, 0x9F, 0xB2, 0x09, 0xEB, 0x49, 0x09, 0x05, 0xEB, 0x89, 0x03, ++0x01, 0x26, 0x46, 0x45, 0x5F, 0x81, 0x80, 0xF2, 0x9B, 0x80, 0x28, 0x46, 0xFF, 0xF7, 0x7E, 0xFA, 0xB5, 0xF8, 0xB4, 0x40, ++0x00, 0x2C, 0x00, 0xF0, 0x87, 0x80, 0x2B, 0x46, 0x00, 0x22, 0x02, 0xE0, 0xA2, 0x42, 0x00, 0xF0, 0x81, 0x80, 0x59, 0x89, ++0x81, 0x42, 0x02, 0xF1, 0x01, 0x02, 0x03, 0xF1, 0x0C, 0x03, 0xF5, 0xD1, 0x01, 0x3C, 0xA6, 0x42, 0xE7, 0xDB, 0x00, 0x24, ++0xA1, 0xB2, 0x28, 0x46, 0xFE, 0xF7, 0x0A, 0xFF, 0xB5, 0xF8, 0xB4, 0x30, 0x01, 0x34, 0x9C, 0x42, 0xF6, 0xD3, 0xBD, 0xE8, ++0xF8, 0x8F, 0x95, 0xF8, 0xAD, 0x20, 0x00, 0x2A, 0x7A, 0xD0, 0x92, 0xB2, 0x95, 0xF8, 0xB2, 0x10, 0x95, 0xF8, 0xAE, 0x70, ++0x6A, 0x81, 0xDB, 0x02, 0x43, 0xEA, 0x81, 0x23, 0x3B, 0x43, 0x9F, 0xB2, 0xC2, 0xE7, 0x95, 0xF8, 0xAD, 0x30, 0x00, 0x2B, ++0x67, 0xD0, 0x95, 0xF8, 0xBC, 0x30, 0x00, 0x2B, 0x0C, 0xBF, 0x4F, 0xF4, 0x28, 0x52, 0x4F, 0xF4, 0xD4, 0x42, 0x95, 0xF8, ++0xB0, 0x30, 0xB5, 0xF8, 0xA6, 0x60, 0x6A, 0x81, 0x5A, 0x00, 0x16, 0x41, 0x95, 0xF8, 0xAF, 0xA0, 0x06, 0xF0, 0x03, 0x06, ++0x1B, 0x01, 0x76, 0x00, 0x07, 0x36, 0x43, 0xEA, 0xCA, 0x1A, 0x4A, 0xEA, 0x06, 0x07, 0x47, 0xF4, 0x20, 0x57, 0x39, 0x46, ++0x28, 0x46, 0xFF, 0xF7, 0x1B, 0xFD, 0x01, 0x3E, 0xF3, 0xB2, 0xB6, 0xB2, 0x00, 0x28, 0x99, 0xD1, 0x06, 0x2B, 0xF0, 0xD1, ++0x96, 0xE7, 0x95, 0xF8, 0xB0, 0xA0, 0xB5, 0xF8, 0xA6, 0xB0, 0x95, 0xF8, 0xAF, 0x60, 0x95, 0xF8, 0xB1, 0x30, 0x4F, 0xEA, ++0x4A, 0x02, 0x4B, 0xFA, 0x02, 0xFB, 0xF6, 0x01, 0x46, 0xEA, 0x43, 0x26, 0x0B, 0xF0, 0x03, 0x0B, 0x4F, 0xF4, 0x00, 0x53, ++0x4F, 0xEA, 0x0A, 0x1A, 0x0B, 0xF1, 0x07, 0x0B, 0x36, 0xB2, 0x6B, 0x81, 0x4A, 0xEA, 0x0B, 0x07, 0x37, 0x43, 0x47, 0xF4, ++0x00, 0x57, 0xBF, 0xB2, 0x39, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0xF0, 0xFC, 0x0B, 0xF1, 0xFF, 0x3B, 0x5F, 0xFA, 0x8B, 0xF3, ++0x1F, 0xFA, 0x8B, 0xFB, 0x00, 0x28, 0x7F, 0xF4, 0x6B, 0xAF, 0x06, 0x2B, 0xEA, 0xD1, 0x67, 0xE7, 0x06, 0xEB, 0x46, 0x03, ++0x01, 0x36, 0x05, 0xEB, 0x83, 0x03, 0xB6, 0xB2, 0x04, 0xF1, 0xFF, 0x38, 0x46, 0x45, 0x58, 0x81, 0xFF, 0xF6, 0x65, 0xAF, ++0x00, 0x2C, 0x7F, 0xF4, 0x7A, 0xAF, 0xBD, 0xE8, 0xF8, 0x8F, 0x4F, 0xF4, 0x80, 0x62, 0x9C, 0xE7, 0x4F, 0xF4, 0x80, 0x62, ++0x82, 0xE7, 0x4F, 0xF4, 0x80, 0x61, 0x36, 0xE7, 0x4F, 0xF0, 0xFF, 0x39, 0xC8, 0x46, 0x21, 0xE7, 0x00, 0x27, 0x6F, 0x81, ++0x46, 0xE7, 0x00, 0xBF, 0x90, 0xF8, 0xAD, 0x30, 0x0B, 0x2B, 0xF0, 0xB4, 0x0C, 0xD9, 0x90, 0xF8, 0xA2, 0x20, 0x04, 0x23, ++0x01, 0x24, 0x22, 0xF0, 0x04, 0x02, 0x13, 0x43, 0x80, 0xF8, 0xA2, 0x30, 0x01, 0xB1, 0x0C, 0x70, 0xF0, 0xBC, 0x70, 0x47, ++0xB0, 0xF8, 0x88, 0x30, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, ++0x04, 0xD1, 0x00, 0x23, 0x90, 0xF8, 0xA2, 0x20, 0x1C, 0x46, 0xE6, 0xE7, 0xB0, 0xF8, 0x8A, 0x30, 0x03, 0xEB, 0x43, 0x03, ++0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, 0xEF, 0xD0, 0xB0, 0xF8, 0x8C, 0x30, 0x03, 0xEB, ++0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, 0xE4, 0xD0, 0x90, 0xF8, 0xA2, 0x20, ++0x12, 0xF0, 0x20, 0x04, 0x20, 0xD1, 0x90, 0xF8, 0xA4, 0x30, 0x44, 0x33, 0x30, 0xF8, 0x13, 0x30, 0x03, 0xEB, 0x43, 0x03, ++0x00, 0xEB, 0x83, 0x05, 0x6B, 0x89, 0x13, 0xF4, 0x00, 0x5F, 0x4F, 0xEA, 0xD3, 0x27, 0xC3, 0xF3, 0xC2, 0x26, 0x12, 0xD1, ++0x17, 0xF0, 0x06, 0x0F, 0x1D, 0xD1, 0x03, 0xF0, 0x7F, 0x03, 0x02, 0x2B, 0x15, 0xD9, 0x2D, 0x89, 0x40, 0xF2, 0x8E, 0x23, ++0x9D, 0x42, 0x86, 0xBF, 0x01, 0x24, 0x04, 0x23, 0x00, 0x23, 0xAA, 0xE7, 0x04, 0x23, 0x01, 0x24, 0xA7, 0xE7, 0x07, 0x2E, ++0x07, 0xD0, 0x03, 0xF0, 0x0F, 0x06, 0xC3, 0xF3, 0x02, 0x13, 0x02, 0x2E, 0xEB, 0xD8, 0x00, 0x2B, 0xE9, 0xD1, 0x2D, 0x89, ++0x41, 0xF6, 0x98, 0x13, 0xE8, 0xE7, 0x03, 0xF0, 0x07, 0x06, 0xC3, 0xF3, 0xC1, 0x03, 0xF2, 0xE7, 0xF8, 0xB5, 0x90, 0xF8, ++0xA2, 0x60, 0x16, 0xF0, 0x10, 0x05, 0x04, 0x46, 0x35, 0xD0, 0xB0, 0xF8, 0xB4, 0x00, 0x00, 0x28, 0x5F, 0xD0, 0xB4, 0xF8, ++0xBA, 0x70, 0x00, 0x23, 0x02, 0xE0, 0x82, 0x42, 0xCB, 0xB2, 0x46, 0xD2, 0x03, 0xEB, 0x43, 0x02, 0x04, 0xEB, 0x82, 0x02, ++0x59, 0x1C, 0x55, 0x89, 0xBD, 0x42, 0xCA, 0xB2, 0xF3, 0xD1, 0x9A, 0xB2, 0xA4, 0xF8, 0x88, 0x20, 0xA4, 0xF8, 0x8A, 0x20, ++0xA4, 0xF8, 0x8C, 0x20, 0x01, 0x38, 0x80, 0xB2, 0x04, 0xF1, 0x0C, 0x03, 0x00, 0xEB, 0x40, 0x00, 0x03, 0xEB, 0x80, 0x00, ++0x00, 0x22, 0x23, 0x46, 0x9A, 0x80, 0xDA, 0x80, 0x0C, 0x33, 0x98, 0x42, 0xFA, 0xD1, 0x26, 0xF0, 0x30, 0x06, 0x46, 0xF0, ++0x20, 0x06, 0x00, 0x23, 0x84, 0xF8, 0xA2, 0x60, 0x84, 0xF8, 0x9B, 0x30, 0x01, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x90, 0xF8, ++0x88, 0x00, 0x0C, 0x23, 0x03, 0xFB, 0x00, 0x40, 0x04, 0x30, 0xFE, 0xF7, 0x73, 0xFC, 0xB4, 0xF8, 0xB4, 0x30, 0x00, 0x2B, ++0xF1, 0xD0, 0x01, 0x3B, 0x9A, 0xB2, 0x02, 0xEB, 0x42, 0x03, 0x04, 0xF1, 0x0C, 0x02, 0x02, 0xEB, 0x83, 0x02, 0x2B, 0x46, ++0xA3, 0x80, 0xE3, 0x80, 0x0C, 0x34, 0x94, 0x42, 0xFA, 0xD1, 0x28, 0x46, 0xF8, 0xBD, 0xC1, 0xD1, 0x01, 0x38, 0xC3, 0xB2, ++0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0xC2, 0xB2, 0x00, 0x21, 0x5F, 0x81, 0x19, 0x81, 0xA4, 0xF8, 0x88, 0x20, ++0xA4, 0xF8, 0x8A, 0x20, 0xA4, 0xF8, 0x8C, 0x20, 0xB7, 0xE7, 0xB4, 0xF8, 0xBA, 0x20, 0xA4, 0xF8, 0xFE, 0x2B, 0x4F, 0xF0, ++0xFF, 0x11, 0xFF, 0x22, 0xA4, 0xF8, 0xFC, 0x0B, 0xC4, 0xF8, 0x88, 0x10, 0xA4, 0xF8, 0x8C, 0x20, 0xB7, 0xE7, 0x00, 0xBF, ++0xC2, 0x6C, 0x12, 0x69, 0xC2, 0xF3, 0x07, 0x21, 0xC2, 0xF3, 0x00, 0x42, 0x0A, 0x44, 0x00, 0x23, 0x01, 0x31, 0xFE, 0xF7, ++0xC9, 0xB9, 0x00, 0xBF, 0x8A, 0x1A, 0x01, 0x23, 0xFE, 0xF7, 0xC4, 0xB9, 0xC3, 0x88, 0x99, 0x04, 0x30, 0xB4, 0xC3, 0xF3, ++0xC2, 0x22, 0x11, 0xD4, 0xD9, 0x0A, 0x11, 0xF0, 0x06, 0x0F, 0x4A, 0xD1, 0x13, 0xF0, 0x7C, 0x0F, 0x03, 0xF0, 0x7F, 0x02, ++0x5D, 0xD1, 0xC3, 0xF3, 0x80, 0x23, 0x43, 0xEA, 0x42, 0x02, 0x3D, 0x4B, 0x30, 0xBC, 0x53, 0xF8, 0x22, 0x00, 0x70, 0x47, ++0x07, 0x2A, 0x37, 0xD0, 0x51, 0x1F, 0x03, 0xF0, 0x0F, 0x04, 0x01, 0x29, 0x37, 0xD8, 0xDF, 0xE8, 0x01, 0xF0, 0x01, 0x1B, ++0xC3, 0xF3, 0x00, 0x21, 0x4A, 0x00, 0x11, 0x44, 0x06, 0x22, 0x12, 0xFB, 0x04, 0x12, 0xC3, 0xF3, 0x41, 0x21, 0x0A, 0x44, ++0x31, 0x49, 0x51, 0xF8, 0x22, 0x00, 0xC3, 0xF3, 0xC0, 0x11, 0xC3, 0xF3, 0x02, 0x12, 0xC3, 0xF3, 0x80, 0x33, 0xC8, 0x40, ++0x01, 0x32, 0x30, 0xBC, 0xB0, 0xFB, 0xF2, 0xF0, 0x98, 0x40, 0x70, 0x47, 0x00, 0x7A, 0x00, 0xF0, 0x07, 0x00, 0x02, 0x28, ++0x31, 0xD8, 0x28, 0x49, 0xC3, 0xF3, 0x41, 0x25, 0x03, 0x22, 0x51, 0xF8, 0x20, 0x10, 0x12, 0xFB, 0x04, 0x52, 0xC3, 0xF3, ++0x02, 0x10, 0x01, 0x30, 0x51, 0xF8, 0x22, 0x30, 0xB3, 0xFB, 0xF0, 0xF0, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x30, 0xBC, ++0x70, 0x47, 0x03, 0xF0, 0x07, 0x04, 0xC3, 0xF3, 0x40, 0x20, 0xC3, 0xF3, 0xC1, 0x11, 0x40, 0xEA, 0x41, 0x01, 0x41, 0xEA, ++0xC4, 0x04, 0x04, 0x2A, 0x19, 0x49, 0x14, 0xBF, 0xC3, 0xF3, 0xC1, 0x03, 0xC3, 0xF3, 0x02, 0x13, 0x51, 0xF8, 0x24, 0x00, ++0x01, 0x33, 0x30, 0xBC, 0xB0, 0xFB, 0xF3, 0xF0, 0x70, 0x47, 0x14, 0x4B, 0x04, 0x3A, 0x30, 0xBC, 0x53, 0xF8, 0x22, 0x00, ++0x70, 0x47, 0xC2, 0x1E, 0xC2, 0xF3, 0x46, 0x01, 0x02, 0xF0, 0xFE, 0x00, 0x08, 0x44, 0x06, 0x21, 0x11, 0xFB, 0x04, 0x04, ++0xC3, 0xF3, 0x41, 0x21, 0x0C, 0x44, 0x08, 0x49, 0x51, 0xF8, 0x24, 0x00, 0xC3, 0xF3, 0x02, 0x13, 0x02, 0xF0, 0x01, 0x02, ++0x59, 0x1C, 0x30, 0xBC, 0x20, 0xFA, 0x02, 0xF3, 0xB3, 0xFB, 0xF1, 0xF0, 0x70, 0x47, 0x00, 0xBF, 0x54, 0xCC, 0x15, 0x00, ++0x74, 0xCC, 0x15, 0x00, 0xA4, 0xD0, 0x15, 0x00, 0x44, 0xCF, 0x15, 0x00, 0x84, 0xD0, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0xB0, 0xF8, 0x96, 0x30, 0x90, 0xF8, 0xA2, 0x80, 0x90, 0xF8, 0xA5, 0x60, 0x03, 0xEB, 0x83, 0x03, 0x5B, 0x00, 0xA0, 0xF8, ++0x98, 0x30, 0x07, 0x46, 0x03, 0xF0, 0xB8, 0xFD, 0xB7, 0xF8, 0xB4, 0x10, 0x80, 0xB2, 0xB0, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, ++0x13, 0x00, 0x00, 0x29, 0x77, 0xD0, 0xB7, 0xF8, 0x88, 0xC0, 0x83, 0xB2, 0x08, 0xF0, 0x02, 0x08, 0x00, 0x20, 0x4F, 0xF2, ++0x33, 0x3E, 0x03, 0x44, 0xB3, 0xFB, 0xF1, 0xF5, 0x01, 0xFB, 0x15, 0x35, 0x05, 0xEB, 0x45, 0x02, 0x92, 0x00, 0xAB, 0xB2, ++0x07, 0xEB, 0x02, 0x0A, 0x9C, 0x45, 0x02, 0xF1, 0x04, 0x02, 0x00, 0xF1, 0x01, 0x00, 0x07, 0xEB, 0x02, 0x04, 0x4F, 0xEA, ++0x45, 0x09, 0x58, 0xD0, 0xBA, 0xF8, 0x08, 0x20, 0x72, 0x45, 0x54, 0xD8, 0xB8, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0xBA, 0xF8, ++0x0A, 0x20, 0xD2, 0x12, 0x12, 0xF0, 0x06, 0x0F, 0x4B, 0xD0, 0x01, 0x2E, 0x42, 0xD9, 0x0C, 0xEB, 0x4C, 0x0C, 0x07, 0xEB, ++0x8C, 0x0C, 0xBC, 0xF8, 0x0A, 0x30, 0x98, 0x04, 0x4F, 0xEA, 0xD3, 0x26, 0xC3, 0xF3, 0xC2, 0x22, 0x47, 0xD4, 0x16, 0xF0, ++0x06, 0x06, 0x01, 0xD0, 0xC3, 0xF3, 0xC1, 0x06, 0xE3, 0x88, 0x99, 0x04, 0x4F, 0xEA, 0xD3, 0x28, 0xC3, 0xF3, 0xC2, 0x22, ++0x36, 0xD4, 0x18, 0xF0, 0x06, 0x08, 0x01, 0xD0, 0xC3, 0xF3, 0xC1, 0x08, 0xB7, 0xF8, 0x8A, 0x00, 0x00, 0xEB, 0x40, 0x00, ++0x07, 0xEB, 0x80, 0x00, 0xA9, 0x44, 0x04, 0x30, 0x07, 0xEB, 0x89, 0x09, 0xFF, 0xF7, 0xFA, 0xFE, 0x99, 0xF8, 0x0D, 0x30, ++0x82, 0x46, 0x5B, 0xBB, 0xB7, 0xF8, 0x96, 0xB0, 0x20, 0x46, 0xFF, 0xF7, 0xF1, 0xFE, 0x50, 0x45, 0x81, 0x46, 0x0D, 0xD3, ++0x01, 0x3E, 0x46, 0x45, 0x23, 0xD2, 0x23, 0x7A, 0x5B, 0x45, 0x10, 0xD3, 0x97, 0xF8, 0x9A, 0x30, 0x01, 0x33, 0xDB, 0xB2, ++0x02, 0x2B, 0x87, 0xF8, 0x9A, 0x30, 0x29, 0xD8, 0x01, 0x20, 0x87, 0xF8, 0xA0, 0x50, 0x87, 0xF8, 0x9B, 0x00, 0xBD, 0xE8, ++0xF8, 0x8F, 0x88, 0x42, 0x8F, 0xD1, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x07, 0x2A, 0x18, 0xD0, 0xC3, 0xF3, 0x02, 0x18, ++0xC8, 0xE7, 0x07, 0x2A, 0x11, 0xD0, 0xC3, 0xF3, 0x02, 0x16, 0xB7, 0xE7, 0x4F, 0xF0, 0x20, 0x0B, 0xD2, 0xE7, 0xB7, 0xF8, ++0x8C, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x07, 0xEB, 0x80, 0x00, 0x04, 0x30, 0xFF, 0xF7, 0xBE, 0xFE, 0x81, 0x45, 0xDB, 0xD3, ++0xCF, 0xE7, 0x00, 0x26, 0xA6, 0xE7, 0x4F, 0xF0, 0x00, 0x08, 0xAF, 0xE7, 0x0F, 0x2B, 0x84, 0xBF, 0x0F, 0x23, 0x87, 0xF8, ++0x9A, 0x30, 0xD8, 0xE7, 0x90, 0xF8, 0xA2, 0x30, 0x99, 0x06, 0x1F, 0xD4, 0x10, 0xB5, 0x90, 0xF8, 0x9B, 0x20, 0x04, 0x46, ++0xC2, 0xB9, 0xB0, 0xF8, 0x98, 0x20, 0x92, 0xB9, 0x5A, 0x06, 0x0B, 0xD5, 0xB0, 0xF8, 0xB4, 0x20, 0x09, 0x2A, 0x03, 0xD9, ++0xFF, 0xF7, 0x9E, 0xFB, 0x94, 0xF8, 0xA2, 0x30, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0xA2, 0x30, 0x20, 0x46, 0xBD, 0xE8, ++0x10, 0x40, 0xFF, 0xF7, 0x29, 0xBF, 0x01, 0x3A, 0xA0, 0xF8, 0x98, 0x20, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x70, 0x47, ++0x2D, 0xE9, 0xF0, 0x41, 0x29, 0x4F, 0x2A, 0x4E, 0xD7, 0xF8, 0x00, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0xB8, 0xF9, 0x00, 0x20, ++0x03, 0xFB, 0x00, 0x63, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x8A, 0xB0, 0x04, 0x46, 0x20, 0xDB, 0x28, 0x46, 0xFF, 0xF7, ++0xDF, 0xFB, 0xA5, 0xF8, 0xB4, 0x00, 0xB8, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x22, 0xDB, 0x28, 0x46, 0xFF, 0xF7, 0x6A, 0xFC, ++0x69, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x3C, 0xF9, 0x28, 0x46, 0x00, 0x21, 0xFF, 0xF7, 0x66, 0xFD, 0x4F, 0xF4, 0x1E, 0x70, ++0x00, 0xFB, 0x04, 0x64, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x01, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x0A, 0xB0, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0x2D, 0xDC, 0xD1, 0x12, 0x49, 0x12, 0x48, 0x40, 0xF6, 0xAF, 0x42, 0xF1, 0xF7, 0x03, 0xF9, 0xD7, 0xF8, ++0x00, 0x80, 0xD3, 0xE7, 0x40, 0xB1, 0x0A, 0x28, 0xD9, 0xD9, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF6, 0xB4, 0x42, 0xF1, 0xF7, ++0xF7, 0xF8, 0xD2, 0xE7, 0x08, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0xB3, 0x42, 0xF1, 0xF7, 0xF0, 0xF8, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC7, 0xDA, 0xB5, 0xF8, 0xB4, 0x00, 0xE8, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x0C, 0xCA, 0x15, 0x00, 0xF4, 0xC9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0xDF, 0xF8, 0xBC, 0x80, 0x29, 0x4D, 0xD8, 0xF8, 0x00, 0x40, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x00, 0x53, 0x07, 0x46, ++0xB4, 0xF9, 0x00, 0x00, 0xD3, 0xF8, 0x4C, 0x41, 0x00, 0x28, 0x0D, 0x46, 0x16, 0x46, 0x20, 0xDB, 0x94, 0xF8, 0xAF, 0x30, ++0xAB, 0x42, 0x39, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0x84, 0xF8, 0xAF, 0x50, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x26, 0xDB, ++0x84, 0xF8, 0xB0, 0x60, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x17, 0xDB, 0x94, 0xF8, 0xA2, 0x30, 0x9A, 0x06, 0x05, 0xD5, ++0x63, 0xF0, 0x7F, 0x03, 0x84, 0xF8, 0xA2, 0x30, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7, ++0x69, 0xBF, 0x00, 0x2C, 0xDC, 0xD1, 0x11, 0x49, 0x11, 0x48, 0x40, 0xF6, 0xCC, 0x42, 0xF1, 0xF7, 0x9F, 0xF8, 0xD5, 0xE7, ++0x07, 0x2E, 0xE5, 0xD9, 0x0C, 0x49, 0x0E, 0x48, 0x40, 0xF6, 0xD4, 0x42, 0xF1, 0xF7, 0x96, 0xF8, 0xDE, 0xE7, 0x03, 0x2D, ++0xD6, 0xD9, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0xD2, 0x42, 0xF1, 0xF7, 0x8D, 0xF8, 0xD8, 0xF8, 0x00, 0x30, 0xCD, 0xE7, ++0x94, 0xF8, 0xB0, 0x30, 0xB3, 0x42, 0xC1, 0xD1, 0xD6, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0x50, 0xCA, 0x15, 0x00, 0x34, 0xCA, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x4D, 0x4B, 0x8D, 0xB0, 0x1A, 0x68, 0x01, 0x90, 0x04, 0x46, 0x4C, 0x48, 0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x04, 0x03, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0xB1, 0x0C, 0x46, 0x79, 0xDB, 0x9B, 0xF8, 0xB2, 0x20, 0xA2, 0x42, ++0x72, 0xD0, 0x8B, 0xF8, 0xB2, 0x40, 0x00, 0x2C, 0x6E, 0xD0, 0x9B, 0xF8, 0xA2, 0x20, 0x12, 0xF0, 0x20, 0x07, 0x76, 0xD1, ++0xBB, 0xF8, 0xB4, 0x90, 0xB8, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x15, 0xD1, 0x4D, 0xE0, 0x25, 0x44, 0x0C, 0xAB, 0x01, 0x37, ++0x0B, 0xEB, 0x85, 0x05, 0x03, 0xEB, 0x84, 0x04, 0xB8, 0xB2, 0x4F, 0xF0, 0x01, 0x03, 0x81, 0x45, 0xAB, 0x73, 0xA6, 0xF8, ++0x0A, 0xA0, 0xA6, 0xF8, 0x08, 0x80, 0x85, 0xF8, 0x0D, 0x80, 0x44, 0xF8, 0x28, 0x8C, 0x38, 0xD9, 0xBC, 0xB2, 0x04, 0xEB, ++0x44, 0x06, 0x0B, 0xEB, 0x86, 0x06, 0x65, 0x00, 0xB6, 0xF8, 0x0A, 0xA0, 0x50, 0x46, 0xFD, 0xF7, 0x19, 0xFF, 0x00, 0x28, ++0xDD, 0xD0, 0x4A, 0xF4, 0x80, 0x6A, 0xB9, 0xF1, 0x00, 0x0F, 0x16, 0xD0, 0x58, 0x46, 0x4F, 0xF0, 0x00, 0x0C, 0x01, 0xE0, ++0xCC, 0x45, 0xD2, 0xD0, 0xB0, 0xF8, 0x0A, 0xE0, 0xD6, 0x45, 0x0C, 0xF1, 0x01, 0x0C, 0x00, 0xF1, 0x0C, 0x00, 0xF5, 0xD1, ++0x58, 0x46, 0xFE, 0xF7, 0x37, 0xFE, 0xBB, 0xF8, 0xB4, 0x90, 0x82, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0xE8, 0xD1, 0x28, 0x19, ++0x0C, 0xAB, 0x0B, 0xEB, 0x80, 0x00, 0x03, 0xEB, 0x84, 0x04, 0x01, 0x25, 0x85, 0x73, 0xA6, 0xF8, 0x0A, 0xA0, 0xA6, 0xF8, ++0x08, 0x90, 0x80, 0xF8, 0x0D, 0x90, 0x44, 0xF8, 0x28, 0x9C, 0x02, 0xA9, 0x58, 0x46, 0xFE, 0xF7, 0xCF, 0xFF, 0x02, 0xA9, ++0x58, 0x46, 0xFF, 0xF7, 0x1B, 0xF8, 0x01, 0x9A, 0x11, 0x46, 0x10, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x29, ++0x99, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x01, 0x03, 0x89, 0xF8, 0x56, 0x31, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xBB, 0xF1, ++0x00, 0x0F, 0x82, 0xD1, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF6, 0xEA, 0x42, 0xF0, 0xF7, 0xE2, 0xFF, 0x7B, 0xE7, 0x62, 0xF0, ++0x7F, 0x02, 0x8B, 0xF8, 0xA2, 0x20, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0xB0, 0xF8, 0x54, 0x21, 0x03, 0x29, 0x9A, 0xBF, 0x02, 0xF4, 0x80, 0x62, ++0x12, 0xB2, 0x00, 0x22, 0x10, 0xB4, 0x42, 0xEA, 0x01, 0x03, 0xD0, 0xF8, 0x48, 0x41, 0x43, 0xF0, 0x00, 0x53, 0xC4, 0xE9, ++0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x90, 0xF8, 0xA5, 0x30, 0xC1, 0xF3, 0xC2, 0x22, ++0x93, 0x42, 0x13, 0xD3, 0x05, 0x2B, 0x70, 0xB5, 0x4F, 0xEA, 0xD1, 0x24, 0x11, 0xD0, 0x04, 0x2B, 0x29, 0xD0, 0x02, 0x3B, ++0x01, 0x2B, 0x12, 0xD8, 0x14, 0xF0, 0x06, 0x03, 0x04, 0xF0, 0x06, 0x05, 0x26, 0xD1, 0x90, 0xF8, 0xAD, 0x20, 0x03, 0x2A, ++0x1B, 0xD8, 0x0D, 0xE0, 0x00, 0x23, 0x18, 0x46, 0x70, 0x47, 0x05, 0x2A, 0x03, 0xD0, 0x90, 0xF8, 0xAD, 0x30, 0x03, 0x2B, ++0x15, 0xD8, 0x14, 0xF0, 0x06, 0x0F, 0x04, 0xF0, 0x06, 0x05, 0x13, 0xD1, 0x4A, 0x05, 0xC1, 0xF3, 0x80, 0x23, 0x03, 0xD4, ++0x90, 0xF8, 0xB2, 0x20, 0x01, 0x2A, 0x04, 0xD0, 0xFF, 0xF7, 0x9A, 0xF8, 0x03, 0x1E, 0x18, 0xBF, 0x01, 0x23, 0x18, 0x46, ++0x70, 0xBD, 0x04, 0x2A, 0x1A, 0xD0, 0x00, 0x23, 0x18, 0x46, 0x70, 0xBD, 0x04, 0x2A, 0x1A, 0xD9, 0x90, 0xF8, 0xAF, 0x60, ++0xC1, 0xF3, 0xC1, 0x13, 0x9E, 0x42, 0xF4, 0xD3, 0x63, 0x07, 0x08, 0xD5, 0x07, 0x2A, 0xE7, 0xD0, 0xC1, 0xF3, 0x02, 0x13, ++0x90, 0xF8, 0xB0, 0x20, 0x9A, 0x42, 0xEA, 0xD3, 0xE0, 0xE7, 0x00, 0x2D, 0xDE, 0xD0, 0xC1, 0xF3, 0xC1, 0x03, 0xF5, 0xE7, ++0x14, 0xF0, 0x06, 0x0F, 0x04, 0xF0, 0x06, 0x05, 0xCE, 0xD0, 0x8E, 0x05, 0xE2, 0xD5, 0x90, 0xF8, 0xB1, 0x30, 0x00, 0x2B, ++0xD5, 0xD0, 0xDD, 0xE7, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0x81, 0x03, 0x2D, 0xE9, 0xF0, 0x47, 0x1F, 0x89, 0x80, 0x46, ++0x41, 0xF6, 0x98, 0x10, 0x87, 0x42, 0x38, 0xD9, 0xB3, 0xF8, 0x0A, 0x90, 0xD8, 0xF8, 0x94, 0xA0, 0x48, 0x46, 0x15, 0x46, ++0x8C, 0x00, 0xFD, 0xF7, 0x2F, 0xFE, 0x08, 0xB3, 0x00, 0x26, 0x20, 0x1D, 0x40, 0x44, 0xFF, 0xF7, 0x8D, 0xFC, 0x2D, 0x4A, ++0x4F, 0xF4, 0x7A, 0x73, 0x30, 0x44, 0x03, 0xFB, 0x07, 0xF3, 0xB3, 0xFB, 0xF0, 0xF3, 0x02, 0xFB, 0x03, 0xF3, 0x18, 0x0C, ++0x75, 0xB1, 0x43, 0xF2, 0x32, 0x33, 0x9F, 0x42, 0x1C, 0xD9, 0x44, 0xF6, 0xCB, 0x43, 0x9F, 0x42, 0x21, 0xD8, 0x24, 0x4B, ++0x5A, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xBD, 0xE8, 0xF0, 0x87, 0x20, 0x4E, 0x21, 0x4B, ++0xC9, 0xF3, 0xC2, 0x29, 0x4F, 0xEA, 0x1A, 0x4A, 0xB9, 0xF1, 0x06, 0x0F, 0x08, 0xBF, 0x1E, 0x46, 0xB6, 0xFB, 0xFA, 0xF6, ++0xD1, 0xE7, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x17, 0x4B, 0x1A, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, ++0x44, 0x60, 0xBD, 0xE8, 0xF0, 0x87, 0x46, 0xF2, 0x65, 0x63, 0x9F, 0x42, 0x0A, 0xD9, 0xB7, 0xF5, 0x00, 0x4F, 0x0F, 0xD2, ++0x0F, 0x4B, 0xDA, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xD5, 0xE7, 0x0B, 0x4B, 0x9A, 0x78, ++0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xCD, 0xE7, 0x49, 0xF6, 0x98, 0x13, 0x9F, 0x42, 0x06, 0x4B, ++0x94, 0xBF, 0x1A, 0x79, 0x5A, 0x79, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xC0, 0xE7, 0x00, 0xBF, ++0xB0, 0xE2, 0x0D, 0x00, 0x54, 0x25, 0x17, 0x00, 0x90, 0x53, 0x03, 0x00, 0x10, 0x09, 0x05, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x8F, 0xB0, 0x00, 0xF1, 0x88, 0x09, 0x02, 0xAD, 0x01, 0x91, 0x04, 0x46, 0x4A, 0x46, 0x07, 0x46, 0x00, 0xF1, 0x90, 0x06, ++0x29, 0x46, 0x32, 0xF8, 0x02, 0x3B, 0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0xB2, 0x42, 0x5B, 0x89, 0x21, 0xF8, ++0x02, 0x3B, 0xF4, 0xD1, 0xB4, 0xF8, 0x92, 0x10, 0x71, 0xB1, 0xD4, 0xF8, 0x94, 0x20, 0xB4, 0xF8, 0x90, 0x30, 0x02, 0xEB, ++0x42, 0x02, 0x1B, 0x04, 0x93, 0xFB, 0xF1, 0xF3, 0x13, 0x44, 0xC3, 0xF3, 0x98, 0x03, 0x00, 0x22, 0xC4, 0xE9, 0x24, 0x23, ++0x04, 0xF1, 0x7C, 0x00, 0xFE, 0xF7, 0x2A, 0xF8, 0xB4, 0xF8, 0xB4, 0x00, 0x00, 0x21, 0xA4, 0xF8, 0x7C, 0x10, 0xA4, 0xF8, ++0x7E, 0x10, 0x84, 0xF8, 0x9A, 0x10, 0x00, 0x28, 0x74, 0xD0, 0x01, 0x38, 0x05, 0xAB, 0x80, 0xB2, 0x0D, 0xF1, 0x10, 0x0A, ++0x03, 0xEB, 0x80, 0x00, 0x52, 0x46, 0x23, 0x46, 0x4F, 0xF0, 0x01, 0x0C, 0x42, 0xF8, 0x04, 0x1B, 0x82, 0x42, 0x83, 0xF8, ++0x0E, 0xC0, 0x03, 0xF1, 0x0C, 0x03, 0xF7, 0xD1, 0xB4, 0xF8, 0xBA, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, 0x14, 0xD0, ++0x32, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x6C, 0x32, 0x98, 0x47, 0x39, 0xF8, 0x02, 0x3B, 0x35, 0xF8, 0x02, 0x2B, 0x03, 0xEB, ++0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0x93, 0x42, 0x47, 0xD1, 0xB1, 0x45, 0xF2, 0xD1, 0x0F, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x4F, 0xF0, 0x00, 0x08, 0x1F, 0xFA, 0x88, 0xFB, 0x0B, 0xEB, 0x4B, 0x00, 0x04, 0xEB, 0x80, 0x00, 0x04, 0x30, ++0xFD, 0xF7, 0xE6, 0xFF, 0x01, 0x22, 0x5F, 0xFA, 0x88, 0xF1, 0x20, 0x46, 0x90, 0x44, 0xFF, 0xF7, 0x09, 0xFF, 0xB4, 0xF8, ++0xB4, 0x10, 0x0E, 0xAB, 0x03, 0xEB, 0x8B, 0x0B, 0x1F, 0xFA, 0x88, 0xF2, 0x91, 0x42, 0x4B, 0xF8, 0x28, 0x0C, 0xE4, 0xD8, ++0x51, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0x26, 0xFE, 0x51, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0x72, 0xFE, 0x01, 0x9B, 0xCB, 0xB9, ++0x94, 0xF8, 0xA2, 0x20, 0xB4, 0xF8, 0xB4, 0x30, 0x42, 0xF0, 0x40, 0x02, 0x84, 0xF8, 0xA2, 0x20, 0x83, 0xB1, 0x01, 0x3B, ++0x9B, 0xB2, 0x03, 0xEB, 0x43, 0x02, 0xDD, 0xF8, 0x04, 0x80, 0x04, 0xF1, 0x0C, 0x03, 0x03, 0xEB, 0x82, 0x03, 0xA7, 0xF8, ++0x04, 0x80, 0xA7, 0xF8, 0x06, 0x80, 0x0C, 0x37, 0x9F, 0x42, 0xF8, 0xD1, 0x00, 0x20, 0xAC, 0xE7, 0x01, 0x20, 0x0F, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xB4, 0xF8, 0xBA, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, 0x9D, 0xD1, 0x0D, 0xF1, 0x10, 0x0A, ++0xCC, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x23, 0x4B, 0x23, 0x4A, 0x1B, 0x68, 0x4F, 0xF4, 0x1E, 0x71, ++0xB3, 0xF9, 0x00, 0x30, 0x01, 0xFB, 0x00, 0x20, 0x00, 0x2B, 0xD0, 0xF8, 0x4C, 0x41, 0x2F, 0xDB, 0x20, 0x46, 0xFF, 0xF7, ++0x5D, 0xF9, 0xB4, 0xF8, 0xB4, 0x30, 0x59, 0x1E, 0x9A, 0x1E, 0x21, 0xEA, 0xE1, 0x71, 0x03, 0x3B, 0x22, 0xEA, 0xE2, 0x72, ++0x23, 0xEA, 0xE3, 0x73, 0x00, 0x25, 0x4F, 0xF4, 0x80, 0x30, 0xA4, 0xF8, 0x88, 0x10, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xF8, ++0x8A, 0x20, 0xA4, 0xF8, 0x8C, 0x30, 0xC4, 0xF8, 0x94, 0x00, 0xA4, 0xF8, 0xBA, 0x10, 0xA4, 0xF8, 0x8E, 0x50, 0x84, 0xF8, ++0xA2, 0x50, 0x01, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x13, 0xFF, 0x94, 0xF8, 0xB4, 0x30, 0x84, 0xF8, 0x9B, 0x50, 0x04, 0x3B, ++0x05, 0x22, 0x84, 0xF8, 0xA0, 0x30, 0xA4, 0xF8, 0x98, 0x20, 0x38, 0xBD, 0x00, 0x2C, 0xCD, 0xD1, 0x05, 0x49, 0x06, 0x48, ++0x40, 0xF6, 0x76, 0x02, 0xF0, 0xF7, 0xDE, 0xFD, 0xC6, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xC4, 0xA3, 0x90, 0xF8, 0x23, 0x70, ++0xDA, 0xF8, 0x00, 0x30, 0xD0, 0xF8, 0x48, 0x81, 0xB3, 0xF9, 0x00, 0x30, 0x8B, 0xB0, 0x07, 0xF1, 0x10, 0x02, 0xD2, 0xB2, ++0x00, 0x2B, 0x04, 0x46, 0x06, 0x92, 0xC0, 0xF2, 0xA9, 0x81, 0xDA, 0x4D, 0x07, 0xEB, 0x47, 0x03, 0x05, 0xEB, 0x83, 0x1B, ++0xC4, 0xF8, 0x4C, 0xB1, 0x9B, 0x01, 0x04, 0x93, 0xCD, 0xF7, 0xB4, 0xF9, 0x83, 0x03, 0x05, 0x93, 0xCD, 0xF7, 0xB0, 0xF9, ++0x4F, 0xF0, 0x01, 0x09, 0x01, 0x30, 0x09, 0xFA, 0x00, 0xF9, 0x00, 0x21, 0x58, 0x46, 0xC0, 0x22, 0xCC, 0xF7, 0xBE, 0xF8, ++0x61, 0x68, 0x11, 0xF0, 0x02, 0x01, 0x09, 0xF1, 0xFF, 0x39, 0x00, 0xF0, 0x9D, 0x80, 0x00, 0x21, 0x04, 0xF1, 0xB8, 0x00, ++0xF3, 0xF7, 0xB4, 0xFB, 0x63, 0x68, 0xAB, 0xF8, 0xAA, 0x00, 0x98, 0x06, 0x4F, 0xEA, 0x47, 0x06, 0x00, 0xF1, 0x30, 0x82, ++0x58, 0x07, 0x40, 0xF1, 0xA3, 0x81, 0xC3, 0x4B, 0x07, 0x93, 0x04, 0x23, 0xB4, 0xF8, 0xEC, 0x00, 0x8B, 0xF8, 0xA5, 0x30, ++0xCD, 0xF8, 0x24, 0xB0, 0xF3, 0xF7, 0xBA, 0xFA, 0x07, 0x9A, 0x03, 0x46, 0x10, 0x8F, 0x08, 0x93, 0xF3, 0xF7, 0xB4, 0xFA, ++0x08, 0x9B, 0x09, 0x9A, 0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xB0, 0x00, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xC0, 0x83, 0x07, 0x9B, 0xB4, 0xF8, 0xEC, 0x00, 0x19, 0x8F, 0xF3, 0xF7, 0xCA, 0xFB, ++0xF2, 0x19, 0x05, 0xEB, 0x82, 0x12, 0x03, 0x46, 0xB4, 0xF8, 0xEC, 0x00, 0xA2, 0xF8, 0xA6, 0x30, 0x09, 0x92, 0xF3, 0xF7, ++0x7D, 0xFA, 0x07, 0x9A, 0x03, 0x46, 0x10, 0x8F, 0x08, 0x93, 0xF3, 0xF7, 0x77, 0xFA, 0x08, 0x9B, 0x09, 0x9A, 0x98, 0x42, ++0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xAC, 0x00, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, ++0x91, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0x20, 0xF4, 0x7F, 0x60, 0x80, 0xB2, ++0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x96, 0xFA, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x6D, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, ++0xF3, 0xF7, 0x92, 0xFA, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x4E, 0x83, 0xB4, 0xF8, 0x54, 0x21, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, 0x83, 0xF8, ++0xB2, 0x20, 0xCD, 0xF7, 0xD1, 0xF8, 0x00, 0x28, 0x40, 0xF0, 0x04, 0x83, 0xD4, 0xF8, 0xE8, 0x30, 0x03, 0xF0, 0x03, 0x03, ++0x01, 0x2B, 0x00, 0xF0, 0xD4, 0x83, 0x02, 0x2B, 0x00, 0xF0, 0xD9, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x40, 0xF6, ++0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x88, 0xE1, 0x04, 0xF1, 0xB8, 0x00, 0xF3, 0xF7, 0x18, 0xFB, 0x07, 0xEB, 0x47, 0x03, ++0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x4D, 0xFA, 0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, ++0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x4F, 0xEA, 0x47, 0x06, 0xC0, 0xF2, 0xBC, 0x80, 0xF3, 0x19, ++0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x47, 0xFA, 0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, ++0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9E, 0x80, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, ++0xFF, 0x21, 0x83, 0xF8, 0xAC, 0x10, 0x94, 0xF8, 0x2D, 0x11, 0x83, 0xF8, 0xAF, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x83, 0x80, 0xB4, 0xF8, 0x54, 0x11, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC1, 0xF3, 0x80, 0x21, 0x83, 0xF8, ++0xB2, 0x10, 0x58, 0x46, 0x07, 0x92, 0xFE, 0xF7, 0x71, 0xFF, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x07, 0x9A, 0xA3, 0xF8, ++0xB4, 0x00, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x8D, 0x80, 0x3E, 0x44, 0x05, 0xEB, 0x86, 0x1A, 0x94, 0xF8, ++0x23, 0x30, 0x9A, 0xF8, 0xAF, 0x70, 0x9A, 0xF8, 0xB1, 0x00, 0x9A, 0xF8, 0xB2, 0x10, 0x9A, 0xF8, 0xA5, 0x20, 0xCD, 0xE9, ++0x02, 0x07, 0xCD, 0xE9, 0x00, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0x4B, 0x4A, 0x4B, 0x49, 0xF0, 0xF7, 0x6F, 0xFA, 0xBA, 0xF8, ++0xB4, 0x00, 0x9A, 0xF8, 0xAE, 0x10, 0x9A, 0xF8, 0xAD, 0x20, 0x9A, 0xF8, 0xAC, 0x30, 0xCD, 0xE9, 0x02, 0x10, 0xCD, 0xE9, ++0x00, 0x32, 0x45, 0x49, 0x42, 0x4A, 0x9A, 0xF8, 0xB0, 0x30, 0x4F, 0xF4, 0x80, 0x50, 0xF0, 0xF7, 0x5B, 0xFA, 0x94, 0xF8, ++0x23, 0x00, 0xFF, 0xF7, 0x5D, 0xFE, 0x04, 0x99, 0x88, 0x31, 0xB0, 0x01, 0x29, 0x44, 0x08, 0xF1, 0x14, 0x02, 0x08, 0xF1, ++0x24, 0x07, 0x31, 0xF8, 0x02, 0x3B, 0xDB, 0xB2, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x2B, 0x44, 0x5B, 0x89, ++0x43, 0xF0, 0x80, 0x43, 0x42, 0xF8, 0x04, 0x3B, 0x97, 0x42, 0xF0, 0xD1, 0x58, 0x46, 0x00, 0x21, 0xFF, 0xF7, 0xB4, 0xF8, ++0x32, 0x4A, 0x06, 0x99, 0x12, 0x69, 0xD4, 0xF8, 0x48, 0x31, 0x31, 0x4F, 0x31, 0x48, 0xB6, 0x01, 0x89, 0x02, 0xAA, 0x51, ++0xA2, 0x69, 0x05, 0x9D, 0xC8, 0xF8, 0x0C, 0x10, 0x4F, 0xF4, 0x08, 0x51, 0xC8, 0xE9, 0x01, 0x59, 0xC8, 0xF8, 0x00, 0x70, ++0xC8, 0xF8, 0x10, 0x00, 0xC3, 0xE9, 0x0D, 0x12, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x11, 0x03, 0x84, 0xF8, 0x56, 0x31, ++0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x29, 0x3F, 0xF4, 0x7A, 0xAF, 0x40, 0xF6, 0x21, 0x42, 0x22, 0x49, 0x23, 0x48, ++0xF0, 0xF7, 0x3C, 0xFC, 0xDA, 0xF8, 0x00, 0x20, 0x70, 0xE7, 0x0B, 0x28, 0x7F, 0xF6, 0x5F, 0xAF, 0x40, 0xF6, 0x1E, 0x42, ++0x1C, 0x49, 0x1E, 0x48, 0xF0, 0xF7, 0x30, 0xFC, 0xDA, 0xF8, 0x00, 0x20, 0x55, 0xE7, 0x0B, 0x28, 0x7F, 0xF6, 0x41, 0xAF, ++0x17, 0x49, 0x1A, 0x48, 0x40, 0xF6, 0x1C, 0x42, 0xF0, 0xF7, 0x24, 0xFC, 0x39, 0xE7, 0x00, 0x28, 0x00, 0xF0, 0xFE, 0x81, ++0x0A, 0x28, 0x7F, 0xF6, 0x6D, 0xAF, 0x11, 0x49, 0x14, 0x48, 0x40, 0xF6, 0x28, 0x42, 0xF0, 0xF7, 0x17, 0xFC, 0x65, 0xE7, ++0x09, 0x2F, 0x7F, 0xF6, 0x54, 0xAE, 0x0C, 0x49, 0x10, 0x48, 0x40, 0xF6, 0xEB, 0x22, 0xF0, 0xF7, 0x0D, 0xFC, 0x94, 0xF8, ++0x23, 0x70, 0x4A, 0xE6, 0xF4, 0xE7, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x4C, 0xCC, 0x15, 0x00, 0xC4, 0xCB, 0x15, 0x00, ++0x08, 0xCC, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1E, 0xAB, 0xDC, 0xBA, 0x04, 0x07, 0xFF, 0xFF, 0x70, 0x79, 0x15, 0x00, ++0xA8, 0xCB, 0x15, 0x00, 0x84, 0xCB, 0x15, 0x00, 0x60, 0xCB, 0x15, 0x00, 0x0C, 0xCA, 0x15, 0x00, 0x64, 0xCA, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x04, 0xF1, 0xCB, 0x03, 0x02, 0x21, 0x18, 0x46, 0x8B, 0xF8, 0xA5, 0x10, 0x09, 0x93, 0xCD, 0xF8, ++0x20, 0xB0, 0xF3, 0xF7, 0x2B, 0xF9, 0x01, 0x46, 0xD9, 0x48, 0x07, 0x91, 0xF3, 0xF7, 0x26, 0xF9, 0x07, 0x99, 0x08, 0x9A, ++0x09, 0x9B, 0x88, 0x42, 0x28, 0xBF, 0x08, 0x46, 0xDA, 0xF8, 0x00, 0x10, 0x82, 0xF8, 0xB0, 0x00, 0xB1, 0xF9, 0x00, 0x20, ++0x00, 0x2A, 0xC0, 0xF2, 0x41, 0x82, 0x04, 0x9A, 0x02, 0xF1, 0xA6, 0x00, 0x19, 0x46, 0x04, 0x22, 0x28, 0x44, 0x02, 0xF0, ++0x6B, 0xFE, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xFF, 0x22, 0xB3, 0xF8, 0xAA, 0x00, 0x83, 0xF8, 0xA6, 0x20, 0x20, 0xF4, ++0x7F, 0x60, 0x07, 0x22, 0x80, 0xB2, 0x83, 0xF8, 0xAC, 0x20, 0xA3, 0xF8, 0xAA, 0x00, 0x07, 0x93, 0xF3, 0xF7, 0x0A, 0xF9, ++0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x0F, 0x82, ++0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x06, 0xF9, 0x07, 0x9B, 0xDA, 0xF8, ++0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xF0, 0x81, 0xB4, 0xF8, 0x54, 0x21, ++0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, 0x83, 0xF8, 0xB2, 0x20, 0xCC, 0xF7, 0x45, 0xFF, 0x00, 0x28, ++0x40, 0xF0, 0x88, 0x81, 0xB4, 0xF8, 0xC8, 0x30, 0x13, 0xF4, 0x00, 0x6F, 0x06, 0xEB, 0x07, 0x03, 0x05, 0xEB, 0x83, 0x13, ++0x14, 0xBF, 0x40, 0xF6, 0xB5, 0x72, 0x40, 0xF6, 0xFF, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0xF1, 0x19, 0x05, 0xEB, 0x81, 0x11, ++0x94, 0xF8, 0x2D, 0x31, 0xDA, 0xF8, 0x00, 0x20, 0x81, 0xF8, 0xAF, 0x30, 0xB2, 0xF9, 0x00, 0x10, 0x00, 0x29, 0xC0, 0xF2, ++0x31, 0x81, 0x03, 0x2B, 0x3F, 0xF6, 0xA9, 0xAE, 0xDF, 0xE8, 0x13, 0xF0, 0x26, 0x01, 0x20, 0x01, 0x15, 0x01, 0x04, 0x01, ++0x05, 0x23, 0x94, 0xF8, 0x22, 0x10, 0xB4, 0xF8, 0x06, 0x01, 0x8B, 0xF8, 0xA5, 0x30, 0x07, 0x91, 0xCD, 0xF8, 0x24, 0xB0, ++0xF3, 0xF7, 0x8C, 0xF8, 0x95, 0x4A, 0x03, 0x46, 0xB2, 0xF8, 0x50, 0x00, 0x08, 0x93, 0xF3, 0xF7, 0x85, 0xF8, 0x08, 0x9B, ++0x09, 0x9A, 0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xB0, 0x00, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC0, 0xF2, 0xE5, 0x81, 0x8B, 0x4B, 0xB4, 0xF8, 0x06, 0x01, 0xB3, 0xF8, 0x50, 0x10, 0xF3, 0xF7, 0x9A, 0xF9, ++0xF2, 0x19, 0x05, 0xEB, 0x82, 0x12, 0x03, 0x46, 0xB4, 0xF8, 0x06, 0x01, 0xA2, 0xF8, 0xA6, 0x30, 0x09, 0x92, 0xF3, 0xF7, ++0x59, 0xF8, 0x82, 0x4A, 0x03, 0x46, 0xB2, 0xF8, 0x50, 0x00, 0x08, 0x93, 0xF3, 0xF7, 0x52, 0xF8, 0x08, 0x9B, 0x09, 0x9A, ++0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xAC, 0x00, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0xB4, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0x20, 0xF4, 0x7F, 0x60, ++0x80, 0xB2, 0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x65, 0xF8, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, ++0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x90, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, ++0xAA, 0x00, 0xF3, 0xF7, 0x61, 0xF8, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC0, 0xF2, 0x71, 0x81, 0xB4, 0xF8, 0x54, 0x21, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, ++0x83, 0xF8, 0xB2, 0x20, 0xCC, 0xF7, 0xA0, 0xFE, 0x28, 0xB1, 0x5D, 0x4B, 0x93, 0xF8, 0x43, 0x30, 0x99, 0x06, 0x00, 0xF1, ++0x99, 0x81, 0x63, 0x68, 0x5B, 0x07, 0x40, 0xF1, 0xEB, 0x80, 0xD4, 0xF8, 0xE8, 0x30, 0x03, 0xF0, 0x03, 0x03, 0x01, 0x2B, ++0x00, 0xF0, 0xBD, 0x81, 0x02, 0x2B, 0x00, 0xF0, 0xB2, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x40, 0xF6, 0xED, 0x62, ++0xA3, 0xF8, 0xB6, 0x20, 0x50, 0x4B, 0x07, 0x99, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x33, 0x93, 0xF8, 0x62, 0x20, ++0x00, 0x2A, 0x40, 0xF0, 0xDF, 0x80, 0xD3, 0xF8, 0xC8, 0x31, 0xD4, 0xF8, 0x48, 0x01, 0x13, 0xF4, 0x80, 0x3F, 0xC1, 0x6B, ++0x40, 0xF0, 0x69, 0x81, 0x41, 0xF0, 0x20, 0x01, 0x00, 0x2B, 0xC1, 0x63, 0x06, 0xDB, 0xC3, 0xF3, 0x05, 0x63, 0x49, 0xEA, ++0x03, 0x59, 0x02, 0x2A, 0x00, 0xF0, 0x58, 0x81, 0x49, 0xF0, 0x80, 0x59, 0x49, 0xF4, 0xC0, 0x29, 0x3D, 0x4B, 0x93, 0xF8, ++0x45, 0x10, 0x94, 0xF8, 0xFD, 0x30, 0x01, 0xF0, 0x03, 0x00, 0xC3, 0xF3, 0xC1, 0x03, 0x83, 0x42, 0x06, 0xEB, 0x07, 0x02, ++0x28, 0xBF, 0x03, 0x46, 0x05, 0xEB, 0x82, 0x12, 0x01, 0x20, 0x83, 0x42, 0x82, 0xF8, 0xBC, 0x00, 0x00, 0xF0, 0x6A, 0x81, ++0x02, 0x2B, 0x00, 0xF0, 0x64, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0x68, 0x81, 0x04, 0x23, 0x82, 0xF8, 0xBD, 0x30, 0x2E, 0x4B, ++0x94, 0xF8, 0xFD, 0xC0, 0x93, 0xF8, 0x4B, 0x00, 0x93, 0xF8, 0x4A, 0x20, 0x8B, 0x08, 0xF1, 0x19, 0x03, 0xEA, 0x5C, 0x13, ++0x05, 0xEB, 0x81, 0x11, 0x03, 0xF0, 0x01, 0x03, 0x81, 0xF8, 0xBE, 0x30, 0x94, 0xF8, 0x03, 0xC1, 0x94, 0xF8, 0x02, 0x31, ++0x0C, 0xF0, 0x01, 0x0C, 0x9B, 0x11, 0x00, 0xF0, 0x01, 0x00, 0x92, 0x11, 0x43, 0xEA, 0x8C, 0x03, 0x42, 0xEA, 0x80, 0x02, ++0x93, 0x42, 0x28, 0xBF, 0x13, 0x46, 0x81, 0xF8, 0xBF, 0x30, 0xE8, 0xE6, 0xD4, 0xF8, 0xE8, 0x30, 0x59, 0x06, 0x7F, 0xF5, ++0x9E, 0xAD, 0x19, 0x4B, 0x9B, 0x89, 0x5B, 0x06, 0x7F, 0xF5, 0x99, 0xAD, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x01, 0x21, ++0x83, 0xF8, 0xB1, 0x10, 0x91, 0xE5, 0xD4, 0xF8, 0xE8, 0x30, 0x9B, 0x06, 0x7F, 0xF5, 0x8D, 0xAD, 0x10, 0x4B, 0x9B, 0x89, ++0x98, 0x06, 0x7F, 0xF5, 0x88, 0xAD, 0xED, 0xE7, 0xB4, 0xF8, 0xC8, 0x30, 0x59, 0x06, 0x7F, 0xF5, 0x82, 0xAD, 0xE2, 0xE7, ++0xB4, 0xF8, 0xC8, 0x30, 0x98, 0x06, 0x7F, 0xF5, 0x7C, 0xAD, 0xED, 0xE7, 0x03, 0x2B, 0x7F, 0xF6, 0xCC, 0xAE, 0x40, 0xF6, ++0xF9, 0x32, 0x07, 0x49, 0x07, 0x48, 0xF0, 0xF7, 0x31, 0xFA, 0x94, 0xF8, 0x2D, 0x31, 0xDA, 0xF8, 0x00, 0x20, 0xC0, 0xE6, ++0xF3, 0xB8, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x34, 0xCA, 0x15, 0x00, ++0x40, 0xF6, 0x27, 0x42, 0x88, 0x49, 0x89, 0x48, 0x07, 0x93, 0xF0, 0xF7, 0x1B, 0xFA, 0xDA, 0xF8, 0x00, 0x20, 0xB2, 0xF9, ++0x00, 0x20, 0x00, 0x2A, 0xBF, 0xF6, 0x64, 0xAD, 0x07, 0x9B, 0xB3, 0xF8, 0xB4, 0x00, 0xEF, 0xE5, 0x07, 0x9B, 0x1B, 0x6B, ++0x13, 0xF0, 0x10, 0x0F, 0xD4, 0xF8, 0xE8, 0x30, 0x3F, 0xF4, 0xF6, 0xAC, 0xD9, 0x06, 0x7F, 0xF5, 0xF3, 0xAC, 0x05, 0x9A, ++0x42, 0xF0, 0x40, 0x02, 0x05, 0x92, 0xED, 0xE4, 0x7A, 0x4B, 0x9B, 0x89, 0x13, 0xF0, 0x01, 0x0F, 0xB4, 0xF8, 0xC8, 0x30, ++0x3F, 0xF4, 0x72, 0xAE, 0xDA, 0x07, 0x7F, 0xF5, 0x6F, 0xAE, 0x05, 0x9A, 0x42, 0xF0, 0x40, 0x02, 0x05, 0x92, 0x69, 0xE6, ++0xB4, 0xF8, 0xC8, 0x30, 0x13, 0xF4, 0x00, 0x6F, 0x06, 0xEB, 0x07, 0x03, 0x05, 0xEB, 0x83, 0x13, 0x14, 0xBF, 0x41, 0xF6, ++0xFF, 0x62, 0x40, 0xF6, 0xFF, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x15, 0xE7, 0xD4, 0xF8, 0x48, 0x01, 0xD3, 0xF8, 0xC8, 0x31, ++0xC1, 0x6B, 0x00, 0x2B, 0x21, 0xF0, 0x20, 0x01, 0xC1, 0x63, 0xBF, 0xF6, 0x24, 0xAF, 0x26, 0xE7, 0x03, 0x28, 0x7F, 0xF6, ++0xAF, 0xAC, 0x0C, 0x28, 0x3F, 0xF4, 0xAC, 0xAC, 0x5F, 0x49, 0x62, 0x48, 0x40, 0xF6, 0xA2, 0x32, 0xF0, 0xF7, 0xC8, 0xF9, ++0xA4, 0xE4, 0x03, 0x28, 0x7F, 0xF6, 0x90, 0xAC, 0x0C, 0x28, 0x3F, 0xF4, 0x8D, 0xAC, 0x59, 0x49, 0x5C, 0x48, 0x4F, 0xF4, ++0x3A, 0x62, 0xF0, 0xF7, 0xBB, 0xF9, 0x85, 0xE4, 0x09, 0x28, 0x7F, 0xF6, 0x6C, 0xAC, 0x54, 0x49, 0x58, 0x48, 0x40, 0xF6, ++0x94, 0x32, 0xF0, 0xF7, 0xB1, 0xF9, 0x64, 0xE4, 0x07, 0x28, 0x7F, 0xF6, 0x3D, 0xAC, 0x4F, 0x49, 0x54, 0x48, 0x40, 0xF6, ++0x8E, 0x32, 0xF0, 0xF7, 0xA7, 0xF9, 0x35, 0xE4, 0x03, 0x28, 0x7F, 0xF6, 0x0D, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, 0x0A, 0xAE, ++0x48, 0x49, 0x4B, 0x48, 0x40, 0xF6, 0xD9, 0x32, 0xF0, 0xF7, 0x9A, 0xF9, 0x02, 0xE6, 0x03, 0x28, 0x7F, 0xF6, 0xEE, 0xAD, ++0x0C, 0x28, 0x3F, 0xF4, 0xEB, 0xAD, 0x42, 0x49, 0x45, 0x48, 0x40, 0xF6, 0xD7, 0x32, 0xF0, 0xF7, 0x8D, 0xF9, 0xE3, 0xE5, ++0x03, 0x28, 0x7F, 0xF6, 0xBC, 0xAD, 0x3D, 0x49, 0x43, 0x48, 0x07, 0x93, 0x40, 0xF6, 0xCC, 0x32, 0xF0, 0xF7, 0x82, 0xF9, ++0x07, 0x9B, 0xB2, 0xE5, 0x03, 0x28, 0x7F, 0xF6, 0x8C, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, 0x89, 0xAE, 0x35, 0x49, 0x38, 0x48, ++0x40, 0xF6, 0x22, 0x32, 0xF0, 0xF7, 0x74, 0xF9, 0x81, 0xE6, 0x03, 0x28, 0x7F, 0xF6, 0x6D, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, ++0x6A, 0xAE, 0x2F, 0x49, 0x32, 0x48, 0x4F, 0xF4, 0x32, 0x62, 0xF0, 0xF7, 0x67, 0xF9, 0x62, 0xE6, 0x0B, 0x28, 0x7F, 0xF6, ++0x49, 0xAE, 0x2A, 0x49, 0x31, 0x48, 0x40, 0xF6, 0x1C, 0x32, 0xF0, 0xF7, 0x5D, 0xF9, 0x41, 0xE6, 0x07, 0x28, 0x7F, 0xF6, ++0x18, 0xAE, 0x25, 0x49, 0x2A, 0x48, 0x40, 0xF6, 0x16, 0x32, 0xF0, 0xF7, 0x53, 0xF9, 0x10, 0xE6, 0x49, 0xF0, 0x80, 0x59, ++0x49, 0xF4, 0x00, 0x39, 0xA6, 0xE6, 0x21, 0xF0, 0x20, 0x01, 0x00, 0x2B, 0xC1, 0x63, 0xBF, 0xF6, 0x96, 0xAE, 0x9B, 0xE6, ++0x94, 0xF8, 0x2D, 0x31, 0x23, 0xB9, 0x94, 0xF8, 0xFB, 0x30, 0x9A, 0x06, 0x7F, 0xF5, 0x5F, 0xAE, 0x05, 0x9B, 0x43, 0xF0, ++0x40, 0x03, 0x05, 0x93, 0x59, 0xE6, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x41, 0xF6, 0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, ++0xB7, 0xE5, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x42, 0xF6, 0x74, 0x42, 0xA3, 0xF8, 0xB6, 0x20, 0xAF, 0xE5, 0x82, 0xF8, ++0xBD, 0x00, 0x9E, 0xE6, 0x00, 0x23, 0x82, 0xF8, 0xBD, 0x30, 0x9A, 0xE6, 0x82, 0xF8, 0xBC, 0x30, 0xA5, 0xE5, 0xF3, 0x19, ++0x05, 0xEB, 0x83, 0x13, 0x42, 0xF6, 0x74, 0x42, 0xA3, 0xF8, 0xB6, 0x20, 0x4C, 0xE6, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, ++0x41, 0xF6, 0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x44, 0xE6, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0xF4, 0xC9, 0x15, 0x00, ++0xE4, 0xB8, 0x17, 0x00, 0xE8, 0xCA, 0x15, 0x00, 0x98, 0xCA, 0x15, 0x00, 0x38, 0xCB, 0x15, 0x00, 0x50, 0xCA, 0x15, 0x00, ++0x4C, 0xCB, 0x15, 0x00, 0x84, 0xCA, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x46, 0x7F, 0x09, 0x2E, 0x83, 0xB0, 0x04, 0x46, ++0x00, 0xF2, 0x8D, 0x80, 0x4B, 0x4B, 0x4C, 0x4F, 0x1A, 0x68, 0x4F, 0xF4, 0x1E, 0x73, 0xB2, 0xF9, 0x00, 0x20, 0x03, 0xFB, ++0x06, 0x73, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x40, 0xDB, 0x95, 0xF8, 0xA2, 0x30, 0x59, 0x07, 0x34, 0xD4, 0x03, 0xF0, ++0xFD, 0x03, 0x4F, 0xF0, 0x00, 0x08, 0xDF, 0xF8, 0x18, 0x91, 0x85, 0xF8, 0xA2, 0x30, 0xD9, 0xF8, 0x10, 0x30, 0x2A, 0x68, ++0x3F, 0x49, 0x9B, 0x1A, 0x8B, 0x42, 0x36, 0xD8, 0x95, 0xF8, 0xA3, 0x20, 0x95, 0xF8, 0xA4, 0x30, 0x43, 0xEA, 0x82, 0x03, ++0x84, 0xF8, 0x36, 0x30, 0x28, 0x46, 0xFE, 0xF7, 0x65, 0xFF, 0xB0, 0xB1, 0xE2, 0x8B, 0x94, 0xF8, 0x36, 0x30, 0x42, 0xF4, ++0x00, 0x52, 0x23, 0xF0, 0x03, 0x03, 0xE2, 0x83, 0x84, 0xF8, 0x36, 0x30, 0xB8, 0xF1, 0x00, 0x0F, 0x59, 0xD1, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x06, 0x76, 0x96, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x20, 0x03, 0x86, 0xF8, 0x56, 0x31, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0x62, 0x6A, 0x92, 0x02, 0xC7, 0xD5, 0x43, 0xF0, 0x02, 0x03, 0x4F, 0xF0, 0x01, 0x08, 0xC6, 0xE7, ++0x00, 0x2D, 0xBC, 0xD1, 0x26, 0x49, 0x27, 0x48, 0x40, 0xF6, 0x9A, 0x22, 0xF0, 0xF7, 0x9E, 0xF8, 0xB5, 0xE7, 0x00, 0x21, ++0x28, 0x46, 0xFF, 0xF7, 0xBB, 0xF9, 0x95, 0xF8, 0xA3, 0x30, 0x01, 0x33, 0x00, 0x22, 0x03, 0xF0, 0x07, 0x03, 0x85, 0xF8, ++0xA3, 0x30, 0x85, 0xF8, 0x9B, 0x20, 0x85, 0xF8, 0xA4, 0x20, 0xD9, 0xF8, 0x10, 0x20, 0x2A, 0x60, 0x9B, 0x00, 0x84, 0xF8, ++0x36, 0x30, 0x00, 0x28, 0xB8, 0xD0, 0x0D, 0xF1, 0x07, 0x01, 0x28, 0x46, 0xFE, 0xF7, 0xCE, 0xFC, 0x9D, 0xF8, 0x07, 0x30, ++0x53, 0xB9, 0x62, 0x6A, 0x22, 0xF4, 0x00, 0x12, 0x62, 0x62, 0x95, 0xF8, 0xA2, 0x20, 0x22, 0xF0, 0x02, 0x02, 0x98, 0x46, ++0x85, 0xF8, 0xA2, 0x20, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0x73, 0x93, 0xF8, 0x56, 0x21, 0x42, 0xF0, 0x11, 0x02, ++0x83, 0xF8, 0x56, 0x21, 0x9A, 0xE7, 0x00, 0x23, 0x80, 0xF8, 0x36, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x63, 0x6A, ++0x43, 0xF4, 0x20, 0x13, 0x63, 0x62, 0xA0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xA0, 0x86, 0x01, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0xB4, 0xCA, 0x0A, 0x12, 0xF0, 0x06, 0x0F, ++0x9D, 0xF8, 0x08, 0x50, 0x9D, 0xF8, 0x14, 0x40, 0x20, 0xD0, 0x02, 0xF0, 0x07, 0x02, 0x01, 0xF0, 0x7F, 0x01, 0x04, 0x2A, ++0x0C, 0xBF, 0x09, 0x09, 0xC1, 0xF3, 0xC1, 0x01, 0x4B, 0xB9, 0xC3, 0x6B, 0x23, 0xF0, 0x04, 0x03, 0xC3, 0x63, 0x64, 0xB1, ++0x43, 0xF0, 0x10, 0x03, 0x30, 0xBC, 0xC3, 0x63, 0x70, 0x47, 0xA9, 0x42, 0xF3, 0xD1, 0xC3, 0x6B, 0x43, 0xF0, 0x04, 0x03, ++0xC3, 0x63, 0x00, 0x2C, 0xF2, 0xD1, 0x23, 0xF0, 0x10, 0x03, 0x30, 0xBC, 0xC3, 0x63, 0x70, 0x47, 0xC3, 0x6B, 0x23, 0xF0, ++0x10, 0x03, 0xF8, 0xE7, 0x0B, 0x7B, 0x05, 0x2B, 0x0E, 0xD1, 0x2D, 0xE9, 0xF0, 0x41, 0x4B, 0x7B, 0x84, 0xB0, 0x0C, 0x46, ++0x01, 0xF1, 0x0C, 0x07, 0x13, 0xB9, 0x0D, 0x88, 0x09, 0x2D, 0x05, 0xDC, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, ++0x00, 0x20, 0x70, 0x47, 0x0B, 0x20, 0x97, 0xF8, 0x02, 0x80, 0x7E, 0x7A, 0xEE, 0xF7, 0xC8, 0xF9, 0x08, 0xBB, 0xFB, 0x78, ++0x3B, 0xBB, 0x69, 0x1F, 0x04, 0xF1, 0x11, 0x00, 0x1D, 0x46, 0x01, 0x22, 0x07, 0x78, 0x43, 0x78, 0x26, 0x2F, 0x03, 0xF1, ++0x02, 0x03, 0x14, 0xD1, 0x8B, 0x42, 0xA1, 0xEB, 0x03, 0x01, 0x10, 0xDC, 0x05, 0xB9, 0x03, 0x90, 0x02, 0x29, 0x18, 0x44, ++0x4F, 0xF0, 0x01, 0x05, 0xEE, 0xDC, 0x00, 0x92, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x03, 0xAB, 0x00, 0xF0, 0x1A, 0xFD, ++0x01, 0xF0, 0x52, 0xF8, 0xD0, 0xE7, 0x00, 0x96, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x04, 0x23, 0x00, 0xF0, 0xF4, 0xFC, ++0xC8, 0xE7, 0x00, 0x96, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x02, 0x23, 0x00, 0xF0, 0xEC, 0xFC, 0xC0, 0xE7, 0x00, 0xBF, ++0x08, 0xB5, 0x0B, 0x20, 0xEE, 0xF7, 0x90, 0xF9, 0x01, 0x28, 0x07, 0xD0, 0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x05, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x01, 0xF0, 0xEA, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x04, 0x49, 0x05, 0x48, ++0x9D, 0x22, 0xEF, 0xF7, 0xD5, 0xFF, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x08, 0xB5, 0x0B, 0x20, 0xEE, 0xF7, 0x70, 0xF9, 0x04, 0x28, 0x07, 0xD0, 0x09, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x01, 0xF0, 0x3E, 0xF8, 0x00, 0x20, 0x08, 0xBD, ++0x04, 0x49, 0x05, 0x48, 0x81, 0x22, 0xEF, 0xF7, 0xB5, 0xFF, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x3A, 0xB3, 0x93, 0x68, 0x10, 0xB4, 0x93, 0xB9, 0x54, 0x69, 0x64, 0xB1, ++0xFF, 0x28, 0x22, 0xD1, 0x00, 0x2C, 0x1A, 0xDD, 0x18, 0x32, 0x10, 0x19, 0x01, 0xE0, 0x82, 0x42, 0x15, 0xD0, 0x12, 0xF8, ++0x01, 0x3B, 0x99, 0x42, 0xF9, 0xD1, 0x01, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xFF, 0x28, 0x13, 0xD0, 0x00, 0x2B, ++0x09, 0xDD, 0x0C, 0x32, 0x13, 0x44, 0x01, 0xE0, 0x9A, 0x42, 0x04, 0xD0, 0x12, 0xF8, 0x01, 0x1B, 0x81, 0x42, 0xF9, 0xD1, ++0xED, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x18, 0x46, 0xE6, 0xE7, 0x54, 0x69, ++0xD8, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x0A, 0x4D, 0x41, 0xF2, 0x98, 0x74, 0x2B, 0x59, 0x63, 0xB1, 0x0B, 0x20, 0xEE, 0xF7, ++0x1B, 0xF9, 0x03, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x38, 0xBD, 0x2B, 0x59, 0x18, 0x68, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, ++0x38, 0xBD, 0x01, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x78, 0xEF, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0x46, 0x80, 0x6C, ++0x89, 0xB0, 0x14, 0x46, 0x99, 0x46, 0x00, 0xF1, 0x68, 0x05, 0x00, 0x29, 0x3B, 0xD1, 0xB0, 0xF8, 0x68, 0x10, 0xBE, 0x4A, ++0xB2, 0xF8, 0xFC, 0x31, 0x01, 0x33, 0x9B, 0xB2, 0x1E, 0x01, 0xA2, 0xF8, 0xFC, 0x31, 0xA0, 0xF8, 0x7E, 0x60, 0x05, 0x22, ++0x58, 0x46, 0xFC, 0xF7, 0x53, 0xFA, 0x01, 0x28, 0x00, 0xF0, 0xC8, 0x80, 0x1B, 0x23, 0x03, 0x93, 0x18, 0x23, 0xE9, 0x18, ++0x05, 0x22, 0xEA, 0x54, 0x01, 0x22, 0x4A, 0x70, 0x99, 0xF8, 0x00, 0x20, 0x8A, 0x70, 0x01, 0xF1, 0x03, 0x0A, 0x00, 0x2C, ++0x7B, 0xD0, 0x03, 0x22, 0x27, 0x20, 0xC8, 0x70, 0x0A, 0x71, 0x99, 0xF8, 0x01, 0x20, 0x4A, 0x71, 0x8C, 0x71, 0x99, 0xF8, ++0x02, 0x20, 0xCA, 0x71, 0x08, 0x33, 0xDB, 0xF8, 0x4C, 0x00, 0x9B, 0xF8, 0x35, 0x20, 0x41, 0x6A, 0x13, 0x44, 0x01, 0x39, ++0x19, 0x44, 0x04, 0x33, 0xC0, 0xE9, 0x0A, 0x13, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA2, 0x4B, 0xA2, 0x4E, 0x00, 0x22, ++0x41, 0xF2, 0xA8, 0x7C, 0x6F, 0xF0, 0x2F, 0x01, 0x80, 0xF8, 0x69, 0x20, 0x80, 0xF8, 0x6A, 0x20, 0x80, 0xF8, 0x6B, 0x20, ++0x80, 0xF8, 0x68, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x9B, 0x4A, 0x4F, 0xF4, 0x1E, 0x77, 0x07, 0xFB, 0x01, 0xF1, 0x41, 0xF2, ++0xA9, 0x78, 0x89, 0x5B, 0xA0, 0xF8, 0x6C, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x07, 0xFB, 0x01, 0x61, 0x4F, 0xF4, 0xA4, 0x6E, ++0x49, 0x88, 0xA0, 0xF8, 0x6E, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x07, 0xFB, 0x01, 0x61, 0x89, 0x88, 0xA0, 0xF8, 0x70, 0x10, ++0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0xF1, 0x89, 0x5A, 0xA0, 0xF8, 0x72, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, ++0x01, 0x21, 0x49, 0x88, 0xA0, 0xF8, 0x74, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0x21, 0x89, 0x88, 0xA0, 0xF8, ++0x76, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0xF1, 0x02, 0xEB, 0x01, 0x0A, 0x9A, 0xF8, 0x06, 0xA0, 0xBA, 0xF1, ++0x02, 0x0F, 0x5F, 0xD0, 0x13, 0xF8, 0x0C, 0x20, 0x07, 0xFB, 0x02, 0xF2, 0xD0, 0x21, 0x92, 0x5B, 0xA0, 0xF8, 0x78, 0x20, ++0x13, 0xF8, 0x0C, 0x20, 0x07, 0xFB, 0x02, 0x62, 0x52, 0x88, 0xA0, 0xF8, 0x7A, 0x20, 0x13, 0xF8, 0x0C, 0x30, 0x07, 0xFB, ++0x03, 0x66, 0xB3, 0x88, 0xA0, 0xF8, 0x7C, 0x30, 0x63, 0xE7, 0x03, 0x9B, 0x01, 0x94, 0xC3, 0xF5, 0xC0, 0x73, 0x9B, 0xB2, ++0x02, 0x93, 0xCD, 0xF8, 0x14, 0xB0, 0x99, 0xF8, 0x02, 0x30, 0x02, 0x9A, 0x05, 0x2B, 0xA2, 0xF1, 0x05, 0x04, 0xA4, 0xB2, ++0x00, 0xF0, 0xE2, 0x80, 0x27, 0x23, 0x8A, 0xF8, 0x00, 0x30, 0x99, 0xF8, 0x01, 0x30, 0x8A, 0xF8, 0x02, 0x30, 0x00, 0x23, ++0x8A, 0xF8, 0x03, 0x30, 0x99, 0xF8, 0x02, 0x30, 0x8A, 0xF8, 0x04, 0x30, 0x05, 0x2B, 0x3A, 0xD0, 0x03, 0x23, 0x8A, 0xF8, ++0x01, 0x30, 0x02, 0x94, 0x0A, 0xF1, 0x05, 0x0A, 0x05, 0x25, 0xFF, 0xF7, 0x15, 0xFF, 0x01, 0x9B, 0x2B, 0x44, 0x01, 0x93, ++0x08, 0xB9, 0x04, 0x2C, 0xD7, 0xD8, 0x5C, 0x4B, 0xDD, 0xF8, 0x14, 0xB0, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x9D, 0x80, 0x01, 0x9B, 0x03, 0x9A, 0x13, 0x44, 0x52, 0xE7, 0x18, 0x22, 0x29, 0x46, 0x58, 0x46, 0xFA, 0xF7, ++0xE7, 0xFF, 0x9B, 0xF8, 0x33, 0x20, 0x02, 0xF1, 0x18, 0x03, 0x1B, 0x32, 0x03, 0x92, 0x2E, 0xE7, 0x89, 0x5A, 0xA0, 0xF8, ++0x78, 0x10, 0x13, 0xF8, 0x08, 0x60, 0x0E, 0xFB, 0x06, 0x26, 0xD0, 0x21, 0x76, 0x88, 0xA0, 0xF8, 0x7A, 0x60, 0x13, 0xF8, ++0x08, 0x30, 0x0E, 0xFB, 0x03, 0x22, 0x93, 0x88, 0xA0, 0xF8, 0x7C, 0x30, 0x07, 0xE7, 0xD9, 0xF8, 0x5C, 0x20, 0x46, 0x49, ++0x01, 0x32, 0x0D, 0x68, 0xC9, 0xF8, 0x5C, 0x20, 0x0A, 0xF1, 0x05, 0x02, 0x04, 0x92, 0x00, 0x2D, 0x00, 0xF0, 0x45, 0x81, ++0xEB, 0x7C, 0x8A, 0xF8, 0x05, 0x30, 0x2B, 0x7C, 0x8A, 0xF8, 0x06, 0x30, 0xD9, 0xE9, 0x0A, 0x12, 0xB9, 0xF8, 0x30, 0x30, ++0xAA, 0xF8, 0x0F, 0x30, 0xCA, 0xF8, 0x07, 0x10, 0xCA, 0xF8, 0x0B, 0x20, 0xAB, 0x7C, 0x8A, 0xF8, 0x11, 0x30, 0x95, 0xF9, ++0x14, 0x00, 0xEE, 0xF7, 0x21, 0xFF, 0xFF, 0x23, 0x8A, 0xF8, 0x12, 0x00, 0x8A, 0xF8, 0x13, 0x30, 0x05, 0xF1, 0x0C, 0x00, ++0xAB, 0x1D, 0x13, 0xF8, 0x01, 0x1B, 0x03, 0xF1, 0x0D, 0x02, 0x52, 0x1B, 0x83, 0x42, 0x02, 0xF8, 0x0A, 0x10, 0xF6, 0xD1, ++0x6B, 0x7C, 0x8A, 0xF8, 0x1A, 0x30, 0x02, 0x9A, 0xEB, 0x68, 0xCA, 0xF8, 0x1B, 0x30, 0x40, 0xF2, 0x01, 0x14, 0x94, 0x42, ++0x99, 0xF8, 0x20, 0x30, 0x28, 0xBF, 0x14, 0x46, 0x0A, 0xF1, 0x1F, 0x02, 0xA4, 0xB2, 0x04, 0x92, 0x00, 0x2B, 0x40, 0xF0, ++0x05, 0x81, 0x1F, 0x3C, 0xA4, 0xB2, 0x99, 0xF8, 0x04, 0x30, 0x00, 0x2B, 0x6D, 0xD1, 0x6B, 0x8B, 0x2B, 0x83, 0x03, 0x23, ++0x1D, 0x48, 0xAB, 0x80, 0x29, 0x46, 0xEE, 0xF7, 0xEB, 0xF9, 0x99, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x12, 0x81, ++0x04, 0x9B, 0x02, 0x9A, 0xA3, 0xEB, 0x0A, 0x05, 0xAB, 0x1E, 0x8A, 0xF8, 0x01, 0x30, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x54, 0x1B, 0x00, 0x2B, 0xA4, 0xB2, 0x80, 0xF2, 0xF9, 0x80, 0xAA, 0x42, 0x80, 0xF0, 0xF6, 0x80, 0x10, 0x49, ++0x10, 0x48, 0xDD, 0xF8, 0x10, 0xA0, 0x40, 0xF2, 0x07, 0x52, 0xEF, 0xF7, 0xCF, 0xFD, 0x02, 0x94, 0x51, 0xE7, 0x01, 0x9B, ++0x00, 0x2B, 0x7F, 0xF4, 0x5F, 0xAF, 0x09, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0x12, 0x52, 0xEF, 0xF7, 0xDB, 0xFD, 0x57, 0xE7, ++0x20, 0x62, 0x17, 0x00, 0x78, 0xEF, 0x17, 0x00, 0x8E, 0x65, 0x17, 0x00, 0x74, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x10, 0x07, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF4, 0xD0, 0x15, 0x00, 0x0C, 0xD1, 0x15, 0x00, 0x94, 0x4B, 0x1A, 0x68, ++0x00, 0x2A, 0x3F, 0xF4, 0x19, 0xAF, 0x19, 0x2C, 0x7F, 0xF6, 0x35, 0xAF, 0x02, 0x98, 0x99, 0xF8, 0x20, 0x10, 0xA0, 0xF1, ++0x1F, 0x03, 0x9B, 0xB2, 0x29, 0xB1, 0x02, 0x2B, 0x7F, 0xF6, 0x2B, 0xAF, 0xA0, 0xF1, 0x22, 0x03, 0x9B, 0xB2, 0x99, 0xF8, ++0x04, 0x10, 0x00, 0x29, 0x3F, 0xF4, 0x04, 0xAF, 0x03, 0x2B, 0x7F, 0xF6, 0x20, 0xAF, 0x10, 0x8B, 0x04, 0x3B, 0x9D, 0xB2, ++0x00, 0x28, 0x40, 0xF0, 0xCF, 0x80, 0x0D, 0x2D, 0x3F, 0xF6, 0xF8, 0xAE, 0x15, 0xE7, 0x04, 0x9A, 0x01, 0x23, 0x13, 0x70, ++0x2B, 0x8B, 0xA2, 0x1F, 0x92, 0xB2, 0x0A, 0xF1, 0x21, 0x01, 0x0B, 0x2B, 0x06, 0x92, 0x8C, 0x46, 0x1B, 0xD8, 0x7C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xAE, 0x80, 0x05, 0xF1, 0x1C, 0x02, 0x05, 0xF1, 0x28, 0x00, ++0x13, 0x46, 0x05, 0x33, 0x12, 0xF8, 0x01, 0x1B, 0x5B, 0x1B, 0x82, 0x42, 0x03, 0xF8, 0x0A, 0x10, 0xF6, 0xD1, 0x0C, 0x23, ++0x12, 0x3C, 0xA2, 0xB2, 0x2B, 0x83, 0x0A, 0xF1, 0x2D, 0x03, 0x06, 0x92, 0x9C, 0x46, 0x99, 0xF8, 0x04, 0x30, 0x01, 0x2B, ++0x3A, 0xD0, 0x2B, 0x8B, 0x6E, 0x8B, 0xF6, 0x1A, 0x05, 0xF1, 0x1C, 0x07, 0xB6, 0xB2, 0x1F, 0x44, 0x00, 0x2E, 0x3B, 0xD0, ++0xCD, 0xF8, 0x1C, 0xA0, 0xE3, 0x46, 0xAA, 0x46, 0x09, 0xE0, 0xBA, 0xF8, 0x18, 0x10, 0x36, 0x1B, 0xB6, 0xB2, 0x0C, 0x44, ++0x2F, 0x44, 0xAA, 0xF8, 0x18, 0x40, 0x00, 0x2E, 0x5D, 0xD0, 0x97, 0xF8, 0x00, 0x80, 0xB9, 0x78, 0x7C, 0x78, 0x40, 0x46, ++0x4A, 0x46, 0xFF, 0xF7, 0xA9, 0xFD, 0xA5, 0x1C, 0x02, 0x34, 0xED, 0xB2, 0xE4, 0xB2, 0x00, 0x28, 0xE7, 0xD0, 0xD9, 0x2D, ++0xE5, 0xD8, 0x06, 0x9B, 0x9C, 0x42, 0x4A, 0xD8, 0x4D, 0xB1, 0x59, 0x46, 0x78, 0x1A, 0xAB, 0x44, 0x01, 0xE0, 0x10, 0xF8, ++0x01, 0x80, 0x01, 0xF8, 0x01, 0x8B, 0x8B, 0x45, 0xF9, 0xD1, 0x06, 0x9B, 0x1B, 0x1B, 0x9B, 0xB2, 0x06, 0x93, 0xD2, 0xE7, ++0xD9, 0xF8, 0x08, 0x30, 0x00, 0x2B, 0xC0, 0xD1, 0xD9, 0xF8, 0x14, 0x30, 0x00, 0x2B, 0xBC, 0xD1, 0x6B, 0x8B, 0x2B, 0x83, ++0x04, 0x9B, 0xC3, 0xF1, 0xFE, 0x0B, 0xE3, 0x44, 0x02, 0x23, 0x8A, 0xF8, 0x20, 0xB0, 0x8C, 0xF8, 0x00, 0x30, 0x8C, 0xF8, ++0x01, 0x30, 0xEA, 0x7D, 0x28, 0x8B, 0x69, 0x8B, 0x99, 0xF8, 0x01, 0x30, 0x54, 0x1C, 0x88, 0x42, 0x66, 0x46, 0xEC, 0x75, ++0x43, 0xEA, 0x02, 0x23, 0x23, 0xD2, 0x6F, 0xEA, 0x43, 0x43, 0x6F, 0xEA, 0x53, 0x43, 0xAC, 0xF8, 0x02, 0x30, 0x33, 0x1D, ++0x04, 0x93, 0x08, 0xE7, 0x22, 0x3C, 0xA4, 0xB2, 0xF9, 0xE6, 0x03, 0x22, 0x8A, 0xF8, 0x01, 0x20, 0x36, 0x4A, 0x12, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x09, 0xDB, 0xDD, 0xF8, 0x10, 0xA0, 0x02, 0x94, 0x1D, 0x46, 0x6B, 0xE6, 0x55, 0x46, ++0xDC, 0x46, 0xDD, 0xF8, 0x1C, 0xA0, 0xC9, 0xE7, 0x1D, 0x46, 0xDD, 0xF8, 0x10, 0xA0, 0x02, 0x94, 0x61, 0xE6, 0xAC, 0xF8, ++0x02, 0x30, 0x33, 0x1D, 0x04, 0x93, 0xE2, 0xE6, 0x04, 0x9D, 0xA4, 0x23, 0x01, 0x24, 0x2B, 0x70, 0x6C, 0x70, 0xFF, 0xF7, ++0x6D, 0xFD, 0x20, 0xB1, 0xAC, 0x70, 0x04, 0x9B, 0x03, 0x33, 0x04, 0x93, 0xE0, 0xE6, 0x04, 0x9B, 0x98, 0x70, 0xF8, 0xE7, ++0x0B, 0x2A, 0x3F, 0xF6, 0x4F, 0xAF, 0x21, 0x49, 0x21, 0x48, 0x40, 0xF2, 0x7D, 0x42, 0xEF, 0xF7, 0xBF, 0xFC, 0x47, 0xE7, ++0xB2, 0xF8, 0x1A, 0x80, 0x01, 0x29, 0x02, 0xF1, 0x1C, 0x02, 0xA8, 0xEB, 0x00, 0x08, 0x02, 0xEB, 0x00, 0x07, 0x08, 0xD0, ++0xB8, 0xF1, 0x00, 0x0F, 0x1B, 0xD0, 0x7B, 0x78, 0x03, 0x33, 0xAB, 0x42, 0xFF, 0xF6, 0x1A, 0xAE, 0x37, 0xE6, 0x7E, 0x78, ++0x10, 0x5C, 0x97, 0xF8, 0x02, 0xB0, 0x02, 0x36, 0xF6, 0xB2, 0x03, 0xE0, 0x7E, 0x78, 0x38, 0x78, 0x02, 0x36, 0xF6, 0xB2, ++0x4A, 0x46, 0x59, 0x46, 0xFF, 0xF7, 0x08, 0xFD, 0x08, 0xB1, 0xD9, 0x2E, 0xE4, 0xD9, 0xB8, 0xEB, 0x06, 0x08, 0x37, 0x44, ++0xF0, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xFC, 0xAD, 0x05, 0x49, 0x07, 0x48, ++0x40, 0xF2, 0x13, 0x42, 0xEF, 0xF7, 0xA0, 0xFC, 0xF4, 0xE5, 0x00, 0xBF, 0x10, 0x07, 0x18, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xD0, 0xD0, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x2D, 0x4E, 0x41, 0xF2, 0xA9, 0x73, ++0xF2, 0x5C, 0x03, 0x2A, 0x42, 0xD8, 0x41, 0xF2, 0xA8, 0x73, 0xF3, 0x5C, 0x09, 0x2B, 0x3D, 0xD8, 0x0D, 0x46, 0x28, 0x49, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x13, 0x07, 0x46, 0x1B, 0x6C, 0x00, 0x2B, 0x3E, 0xD0, 0x24, 0x48, 0x1B, 0x79, ++0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x2D, 0xDB, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x12, 0x92, 0xF8, ++0xC0, 0x24, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xDA, 0xF7, 0x3D, 0xFE, 0x04, 0x46, ++0xE0, 0xB1, 0x41, 0xF2, 0xA9, 0x72, 0x41, 0xF2, 0xA8, 0x73, 0xB2, 0x5C, 0x02, 0x77, 0xF3, 0x5C, 0x43, 0x77, 0x00, 0x23, ++0x80, 0xF8, 0x33, 0x30, 0x80, 0xF8, 0x35, 0x30, 0x15, 0xB9, 0x13, 0x4B, 0xC0, 0xE9, 0x15, 0x30, 0x20, 0x46, 0x3B, 0x46, ++0x2A, 0x46, 0x01, 0x21, 0xFF, 0xF7, 0xEC, 0xFC, 0x20, 0x46, 0x03, 0x21, 0xBD, 0xE8, 0xF8, 0x40, 0xDA, 0xF7, 0x2E, 0xBE, ++0xF8, 0xBD, 0x02, 0x2B, 0xCF, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0xEF, 0xF7, 0x29, 0xFC, 0x01, 0x20, ++0xD1, 0xE7, 0x05, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xF7, 0xDA, 0xF0, 0xE7, 0x78, 0xEF, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xA1, 0x5E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, ++0x00, 0x2A, 0x35, 0xD0, 0x70, 0xB5, 0x04, 0x46, 0x92, 0xF8, 0x32, 0x00, 0x8A, 0xB0, 0x13, 0x46, 0x58, 0xB9, 0x95, 0x8E, ++0x22, 0x88, 0x95, 0x42, 0x28, 0xD1, 0xDD, 0x8E, 0x62, 0x88, 0x95, 0x42, 0x24, 0xD1, 0xA2, 0x88, 0x1C, 0x8F, 0x94, 0x42, ++0x20, 0xD1, 0x93, 0xF8, 0x3A, 0x20, 0xE2, 0xB1, 0xD9, 0xB1, 0x4D, 0x78, 0x8D, 0xF8, 0x04, 0x50, 0x6D, 0xB1, 0x01, 0xA8, ++0x05, 0x44, 0xC0, 0xF1, 0x02, 0x06, 0x44, 0x18, 0xA4, 0x5D, 0x00, 0xF8, 0x01, 0x4F, 0xA8, 0x42, 0xF9, 0xD1, 0x9D, 0xF8, ++0x04, 0x10, 0x91, 0x42, 0x01, 0xD0, 0x00, 0x20, 0x08, 0xE0, 0x03, 0xF1, 0x3B, 0x00, 0x0D, 0xF1, 0x05, 0x01, 0x01, 0xF0, ++0x57, 0xFE, 0x00, 0x28, 0xF5, 0xD1, 0x01, 0x20, 0x0A, 0xB0, 0x70, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, ++0x04, 0x46, 0xB1, 0xB1, 0x64, 0x48, 0x65, 0x4D, 0xA0, 0xF1, 0x82, 0x07, 0xED, 0xF7, 0x78, 0xFF, 0x00, 0x26, 0x25, 0xF8, ++0x02, 0x6C, 0x28, 0x46, 0x06, 0x22, 0x00, 0x21, 0x05, 0xF5, 0xF6, 0x75, 0xCA, 0xF7, 0xDE, 0xFE, 0xBD, 0x42, 0xF4, 0xD1, ++0xEC, 0xF7, 0x56, 0xFC, 0xC4, 0xE9, 0x0A, 0x01, 0x26, 0x66, 0x5B, 0x4E, 0xDF, 0xF8, 0x6C, 0x81, 0x06, 0xF1, 0x88, 0x07, ++0x0B, 0x20, 0xED, 0xF7, 0x77, 0xFD, 0x01, 0x28, 0x39, 0xD1, 0x57, 0x4D, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x02, 0x0A, ++0x03, 0xE0, 0x05, 0xF5, 0xF6, 0x75, 0xB5, 0x42, 0x1A, 0xD0, 0xAB, 0x88, 0x01, 0x2B, 0xF8, 0xD1, 0x6B, 0x7D, 0x05, 0xF1, ++0x1C, 0x01, 0x19, 0x44, 0x22, 0x46, 0xA8, 0x1D, 0xFF, 0xF7, 0x8C, 0xFF, 0x00, 0x28, 0xEE, 0xD0, 0x29, 0x46, 0xA5, 0xF8, ++0x18, 0x90, 0x85, 0xF8, 0x17, 0x90, 0xA5, 0xF8, 0x04, 0xA0, 0x38, 0x46, 0x05, 0xF5, 0xF6, 0x75, 0xED, 0xF7, 0x3E, 0xFF, ++0xB5, 0x42, 0xE4, 0xD1, 0x23, 0x6E, 0x94, 0xF8, 0x65, 0x20, 0x01, 0x33, 0x93, 0x42, 0x23, 0x66, 0x5D, 0xDA, 0x03, 0x21, ++0x0B, 0x20, 0xED, 0xF7, 0x9D, 0xFC, 0xFF, 0xF7, 0x1F, 0xFC, 0x00, 0x28, 0xC6, 0xD1, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, ++0xF0, 0x47, 0xFF, 0xF7, 0xFF, 0xBE, 0x01, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x8F, 0xFC, 0x23, 0x6E, 0x06, 0xE0, 0x23, 0x6E, ++0x94, 0xF8, 0x65, 0x20, 0x01, 0x33, 0x93, 0x42, 0x23, 0x66, 0xB3, 0xDA, 0x23, 0x44, 0x94, 0xF8, 0x64, 0x00, 0x93, 0xF8, ++0x66, 0x10, 0xF1, 0xF7, 0xBB, 0xFF, 0x05, 0x46, 0x00, 0x28, 0xEE, 0xD0, 0xC3, 0x78, 0x9B, 0x07, 0xEB, 0xD4, 0x4F, 0xF4, ++0xBA, 0x73, 0x0B, 0x22, 0x04, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xED, 0xF7, 0x77, 0xFA, 0x06, 0x46, 0x28, 0x68, 0x30, 0x60, ++0xAB, 0x88, 0xB3, 0x80, 0xE3, 0x78, 0x1B, 0xB9, 0xF3, 0x78, 0x43, 0xF0, 0x01, 0x03, 0xF3, 0x70, 0x01, 0x25, 0x86, 0xF8, ++0x6F, 0x51, 0x94, 0xF8, 0x3A, 0x20, 0x86, 0xF8, 0xFC, 0x20, 0x04, 0xF1, 0x3B, 0x01, 0x06, 0xF1, 0xFD, 0x00, 0x01, 0xF0, ++0xE7, 0xFD, 0x86, 0xF8, 0x70, 0x51, 0xA3, 0x8E, 0xA6, 0xF8, 0x60, 0x31, 0xE3, 0x8E, 0xA6, 0xF8, 0x62, 0x31, 0x23, 0x8F, ++0xA6, 0xF8, 0x64, 0x31, 0x41, 0xF2, 0xA9, 0x73, 0x30, 0x46, 0x18, 0xF8, 0x03, 0x30, 0x86, 0xF8, 0x6E, 0x31, 0xBD, 0xE8, ++0xF0, 0x47, 0xED, 0xF7, 0x79, 0xBA, 0x13, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x09, 0xDB, 0x02, 0x21, ++0x0B, 0x20, 0xED, 0xF7, 0x39, 0xFC, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x9F, 0xBE, 0xFF, 0xF7, ++0xB5, 0xFB, 0x00, 0x28, 0xF1, 0xD0, 0xE3, 0x6D, 0x00, 0x2B, 0xEE, 0xD0, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF2, 0x22, 0x62, ++0xEF, 0xF7, 0x0E, 0xFB, 0xE7, 0xE7, 0x00, 0xBF, 0x10, 0x07, 0x18, 0x00, 0x7E, 0xEF, 0x17, 0x00, 0x88, 0x06, 0x18, 0x00, ++0x78, 0xEF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x1C, 0xD1, 0x15, 0x00, 0x10, 0xB5, 0x08, 0x4C, ++0x00, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x10, 0xFC, 0x20, 0x46, 0x41, 0xF2, 0xB0, 0x72, 0x00, 0x21, 0x04, 0xF5, 0xBD, 0x54, ++0xCA, 0xF7, 0x08, 0xFE, 0x4F, 0xF0, 0xFF, 0x33, 0x23, 0x60, 0x10, 0xBD, 0x78, 0xEF, 0x17, 0x00, 0xF0, 0xB5, 0xA3, 0xB0, ++0x0B, 0x4C, 0x9D, 0xF8, 0xA0, 0x50, 0x8D, 0xF8, 0x02, 0x50, 0x41, 0xF2, 0xA8, 0x75, 0x84, 0x46, 0x41, 0xF2, 0xA9, 0x77, ++0x08, 0x46, 0x66, 0x5B, 0x60, 0x55, 0x19, 0x46, 0x68, 0x46, 0x04, 0xF8, 0x07, 0xC0, 0x8D, 0xF8, 0x00, 0x20, 0xFF, 0xF7, ++0x57, 0xFE, 0x66, 0x53, 0x23, 0xB0, 0xF0, 0xBD, 0x78, 0xEF, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAB, 0xB0, 0x41, 0xF2, ++0xA8, 0x76, 0x00, 0x92, 0xC4, 0x4A, 0x41, 0xF2, 0xA9, 0x75, 0x91, 0x55, 0xCD, 0xE9, 0x01, 0x01, 0x02, 0xF5, 0xBD, 0x51, ++0x50, 0x55, 0x4F, 0xF0, 0xFF, 0x30, 0x08, 0x60, 0x34, 0x99, 0x16, 0x46, 0x41, 0xF2, 0xA4, 0x74, 0x00, 0x22, 0x91, 0x42, ++0x32, 0x51, 0x34, 0xDD, 0xDF, 0xF8, 0xF0, 0x82, 0x1F, 0x46, 0x91, 0x46, 0xBA, 0x46, 0x57, 0xF8, 0x04, 0x4B, 0x65, 0x78, ++0xAB, 0x1C, 0x04, 0x2B, 0x37, 0xD9, 0x88, 0x22, 0x00, 0x21, 0x40, 0x46, 0xCA, 0xF7, 0xBC, 0xFD, 0xA3, 0x78, 0x88, 0xF8, ++0x01, 0x30, 0xE3, 0x78, 0x22, 0x79, 0x88, 0xF8, 0x02, 0x20, 0xD9, 0x07, 0x03, 0xD4, 0x9B, 0x07, 0x1C, 0xD4, 0x05, 0x2A, ++0x73, 0xD0, 0xDA, 0xF8, 0x00, 0x40, 0x02, 0x21, 0x00, 0x9A, 0x23, 0x79, 0x8D, 0xF8, 0x20, 0x20, 0xA8, 0x4A, 0x02, 0x98, ++0x8D, 0xF8, 0x22, 0x30, 0x41, 0xF2, 0xA8, 0x75, 0x41, 0xF2, 0xA9, 0x73, 0x16, 0x46, 0x54, 0x5B, 0x01, 0x9F, 0x50, 0x55, ++0x08, 0xA8, 0xD7, 0x54, 0xFF, 0xF7, 0x04, 0xFE, 0x74, 0x53, 0x2B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x98, 0xF8, 0x00, 0x30, ++0x00, 0x9A, 0x93, 0x42, 0x4C, 0xD0, 0x34, 0x9B, 0x09, 0xF1, 0x01, 0x09, 0x4B, 0x45, 0xC1, 0xD1, 0xF1, 0xE7, 0x04, 0x21, ++0xDA, 0xE7, 0xA3, 0x2C, 0x00, 0xF0, 0x25, 0x81, 0xA4, 0x2C, 0x40, 0xF0, 0x18, 0x81, 0x98, 0x78, 0x88, 0xF8, 0x20, 0x00, ++0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0x0B, 0x44, 0x00, 0xF2, 0x82, 0x80, 0x98, 0xF8, 0x03, 0x30, 0x01, 0x2B, 0x3E, 0x46, ++0x03, 0x9F, 0x2C, 0xD8, 0x04, 0x9C, 0x72, 0x2C, 0x23, 0x46, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x30, ++0x00, 0x2E, 0x00, 0xF0, 0x2B, 0x81, 0xB6, 0xF8, 0x03, 0x20, 0xB1, 0x78, 0xB0, 0x88, 0x88, 0xF8, 0x66, 0x40, 0x41, 0xF2, ++0x88, 0x33, 0x9A, 0x42, 0x94, 0xBF, 0x00, 0x22, 0x01, 0x22, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x20, 0x88, 0xF8, 0x65, 0x30, ++0x00, 0x29, 0x40, 0xF0, 0x03, 0x81, 0x05, 0x9A, 0x88, 0xF8, 0x64, 0x10, 0x94, 0x42, 0x06, 0xD0, 0x80, 0xF0, 0x59, 0x81, ++0x04, 0x9B, 0x04, 0x33, 0x88, 0xF8, 0x67, 0x30, 0x02, 0x23, 0x88, 0xF8, 0x65, 0x30, 0x00, 0x9B, 0x88, 0xF8, 0x00, 0x30, ++0x76, 0x4A, 0x13, 0x68, 0x01, 0x33, 0x08, 0xF1, 0x88, 0x08, 0x13, 0x60, 0xAB, 0xE7, 0xEB, 0x1E, 0x0C, 0x2B, 0x40, 0xF2, ++0xDD, 0x80, 0xE3, 0x7A, 0x88, 0xF8, 0x03, 0x30, 0x02, 0x2B, 0x82, 0xD8, 0x62, 0x79, 0x63, 0x7A, 0x04, 0x92, 0xA2, 0x79, ++0x05, 0x92, 0xA8, 0xF8, 0x30, 0x30, 0x08, 0xF1, 0x3A, 0x0E, 0x08, 0xF1, 0x34, 0x03, 0xA4, 0xEB, 0x08, 0x01, 0x5A, 0x18, ++0x12, 0xF8, 0x28, 0x2C, 0x03, 0xF8, 0x01, 0x2B, 0x73, 0x45, 0xF8, 0xD1, 0xB8, 0xF8, 0x34, 0x20, 0x4F, 0xF6, 0xFF, 0x73, ++0x9A, 0x42, 0xA5, 0xF1, 0x10, 0x02, 0x08, 0xBF, 0x01, 0x23, 0x4F, 0xF0, 0x02, 0x01, 0x92, 0xB2, 0x08, 0xBF, 0x88, 0xF8, ++0x32, 0x30, 0x8A, 0x42, 0x04, 0xF1, 0x12, 0x03, 0x88, 0xF8, 0x04, 0x10, 0x40, 0xF2, 0x47, 0x81, 0x00, 0x21, 0x6F, 0xF0, ++0x13, 0x00, 0x0C, 0x46, 0x6F, 0xF0, 0x08, 0x06, 0x6F, 0xF0, 0x37, 0x0C, 0x0D, 0x46, 0xA0, 0xEB, 0x08, 0x01, 0x03, 0x97, ++0x06, 0x91, 0xA6, 0xEB, 0x08, 0x06, 0xAC, 0xEB, 0x08, 0x0C, 0x27, 0x46, 0x58, 0x78, 0x1C, 0x78, 0x81, 0x1C, 0x91, 0x42, ++0x00, 0xF2, 0x96, 0x80, 0x0B, 0x2C, 0x3F, 0xF6, 0x66, 0xAF, 0x0B, 0x2C, 0x3F, 0xF6, 0x6C, 0xAF, 0x0F, 0xF2, 0x04, 0x0B, ++0x5B, 0xF8, 0x24, 0xF0, 0xA9, 0x58, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0x97, 0x58, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, ++0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, ++0xB1, 0x56, 0x15, 0x00, 0x65, 0x58, 0x15, 0x00, 0x11, 0x58, 0x15, 0x00, 0x02, 0x29, 0x71, 0xD0, 0x9C, 0x78, 0xFF, 0x2C, ++0x7F, 0xF4, 0x4A, 0xAF, 0x00, 0xF1, 0xFF, 0x3B, 0x5F, 0xFA, 0x8B, 0xFB, 0xBB, 0xF1, 0x08, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, ++0x08, 0x0B, 0x01, 0x28, 0xC8, 0xF8, 0x14, 0xB0, 0x3F, 0xF4, 0x3C, 0xAF, 0x08, 0xF1, 0x17, 0x00, 0xCD, 0xF8, 0x1C, 0xA0, ++0xDD, 0xF8, 0x18, 0xA0, 0x83, 0x44, 0x1C, 0x18, 0x14, 0xF8, 0x0A, 0x40, 0x00, 0xF8, 0x01, 0x4F, 0x58, 0x45, 0xF8, 0xD1, ++0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0xDD, 0xF8, 0x1C, 0xA0, 0x0B, 0x44, 0xAE, 0xD8, 0x2B, 0xE7, 0x8C, 0x1E, 0x08, 0x2C, ++0xA8, 0xBF, 0x08, 0x24, 0x02, 0x29, 0xC8, 0xF8, 0x08, 0x40, 0x3F, 0xF4, 0x1D, 0xAF, 0x08, 0xF1, 0x0B, 0x00, 0x00, 0xEB, ++0x04, 0x0B, 0x1C, 0x18, 0xA4, 0x5D, 0x00, 0xF8, 0x01, 0x4F, 0x83, 0x45, 0xF9, 0xD1, 0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, ++0x0B, 0x44, 0x95, 0xD8, 0x12, 0xE7, 0x52, 0x1A, 0x92, 0xB2, 0x98, 0x78, 0x88, 0xF8, 0x04, 0x00, 0x02, 0x2A, 0x0B, 0x44, ++0x8C, 0xD8, 0x09, 0xE7, 0x22, 0x29, 0x25, 0xD8, 0x88, 0xF8, 0x3A, 0x00, 0x00, 0x28, 0x3F, 0xF4, 0xFD, 0xAE, 0x00, 0xEB, ++0x0E, 0x04, 0x70, 0x46, 0x00, 0xEB, 0x03, 0x0B, 0x1B, 0xF8, 0x0C, 0xB0, 0x00, 0xF8, 0x01, 0xBF, 0xA0, 0x42, 0xF7, 0xD1, ++0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0x0B, 0x44, 0x3F, 0xF6, 0x74, 0xAF, 0xF0, 0xE6, 0x52, 0x1A, 0x92, 0xB2, 0x33, 0x2C, ++0x08, 0xBF, 0x1D, 0x46, 0x02, 0x2A, 0x0B, 0x44, 0x3F, 0xF6, 0x6A, 0xAF, 0xE6, 0xE6, 0x1F, 0x46, 0xDE, 0xE6, 0x00, 0x23, ++0x88, 0xF8, 0x65, 0x30, 0xDA, 0xF8, 0x00, 0x40, 0x04, 0x21, 0xA9, 0xE6, 0x78, 0xEF, 0x17, 0x00, 0x1C, 0x07, 0x18, 0x00, ++0x88, 0x06, 0x18, 0x00, 0x01, 0x29, 0x08, 0xF1, 0x66, 0x03, 0x00, 0xF0, 0x47, 0x81, 0x04, 0x9A, 0x41, 0x2A, 0x35, 0xBF, ++0x40, 0x20, 0x80, 0x20, 0x24, 0x22, 0x64, 0x22, 0x11, 0x1D, 0x03, 0xF8, 0x01, 0x2B, 0xCA, 0xB2, 0x90, 0x42, 0xF9, 0xD2, ++0x08, 0x23, 0xF4, 0xE6, 0x05, 0x9B, 0xFF, 0x2B, 0x4E, 0xD0, 0x05, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0x85, 0x80, 0x05, 0x9A, ++0x88, 0xF8, 0x66, 0x20, 0x01, 0x23, 0x88, 0xF8, 0x65, 0x30, 0x04, 0x9B, 0xA3, 0xF1, 0x53, 0x02, 0x08, 0xF1, 0x66, 0x03, ++0x2E, 0x2A, 0x30, 0xD8, 0xDF, 0xE8, 0x12, 0xF0, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, ++0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, ++0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, ++0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, ++0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x71, 0x01, ++0x6E, 0x01, 0x01, 0x23, 0xAD, 0xE6, 0x05, 0x9B, 0x04, 0x93, 0x04, 0x9B, 0x04, 0x3B, 0x88, 0xF8, 0x67, 0x30, 0x02, 0x23, ++0xA5, 0xE6, 0x05, 0x9B, 0x04, 0x93, 0x9D, 0xE6, 0x00, 0x2D, 0x8D, 0xD0, 0xAB, 0x78, 0x04, 0x9A, 0x93, 0x42, 0x89, 0xD1, ++0x68, 0x78, 0x43, 0x1E, 0xDB, 0xB2, 0x1C, 0x2B, 0x28, 0xBF, 0x1C, 0x23, 0x59, 0x1E, 0x01, 0x28, 0x05, 0xF1, 0x03, 0x05, ++0xC9, 0xB2, 0x3F, 0xF4, 0x7D, 0xAF, 0x32, 0x46, 0x08, 0xEB, 0x02, 0x04, 0xAE, 0x5C, 0x84, 0xF8, 0x66, 0x60, 0x91, 0x42, ++0x02, 0xF1, 0x01, 0x02, 0xF6, 0xD1, 0x01, 0x28, 0x3F, 0xF4, 0x70, 0xAF, 0x88, 0xF8, 0x65, 0x30, 0x01, 0x2B, 0x7F, 0xF4, ++0x80, 0xAE, 0x98, 0xF8, 0x66, 0x30, 0x05, 0x93, 0x91, 0xE7, 0x98, 0xF8, 0x03, 0x30, 0x01, 0x2B, 0x3F, 0xF6, 0x77, 0xAE, ++0x04, 0x9B, 0x72, 0x2B, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x30, 0x05, 0x9B, 0xFF, 0x2B, 0x7F, 0xF4, ++0x78, 0xAF, 0x55, 0xE7, 0x04, 0x9A, 0x08, 0xF1, 0x66, 0x03, 0x51, 0x3A, 0x1E, 0x46, 0x30, 0x2A, 0x3F, 0xF6, 0x4B, 0xAF, ++0x01, 0xA1, 0x51, 0xF8, 0x22, 0xF0, 0x00, 0xBF, 0x9B, 0x5B, 0x15, 0x00, 0x27, 0x5C, 0x15, 0x00, 0x9B, 0x5B, 0x15, 0x00, ++0x9B, 0x5B, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x87, 0x5B, 0x15, 0x00, ++0x87, 0x5B, 0x15, 0x00, 0x87, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, ++0x29, 0x5B, 0x15, 0x00, 0x03, 0x5C, 0x15, 0x00, 0x29, 0x5B, 0x15, 0x00, 0x29, 0x5B, 0x15, 0x00, 0xE9, 0x5B, 0x15, 0x00, ++0x0D, 0x5C, 0x15, 0x00, 0x00, 0x25, 0x04, 0x20, 0xA2, 0x24, 0x95, 0x22, 0x71, 0x1E, 0x0B, 0x46, 0x02, 0x33, 0x01, 0xF8, ++0x01, 0x2F, 0x02, 0x44, 0x2B, 0x44, 0x94, 0x42, 0xA3, 0xEB, 0x06, 0x03, 0xF5, 0xDC, 0x40, 0x4A, 0xDB, 0xB2, 0x12, 0x68, ++0x88, 0xF8, 0x65, 0x30, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xDB, 0x00, 0x2B, 0x7F, 0xF4, 0x5F, 0xAF, 0xCB, 0xE6, ++0x1C, 0x2B, 0xF9, 0xD9, 0x39, 0x49, 0x3A, 0x48, 0x40, 0xF2, 0x01, 0x32, 0xEF, 0xF7, 0x06, 0xF8, 0x98, 0xF8, 0x65, 0x30, ++0x00, 0x2B, 0x7F, 0xF4, 0x51, 0xAF, 0xBD, 0xE6, 0x00, 0x25, 0x04, 0x20, 0x91, 0x24, 0x64, 0x22, 0xD4, 0xE7, 0x00, 0x25, ++0x04, 0x20, 0x41, 0x24, 0x34, 0x22, 0xCF, 0xE7, 0x00, 0x25, 0x04, 0x20, 0x31, 0x24, 0x24, 0x22, 0xCA, 0xE7, 0x01, 0x20, ++0x02, 0x46, 0x00, 0x25, 0x0E, 0x24, 0xC5, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0xB6, 0xAE, 0x04, 0x9A, 0x23, 0x2A, 0x7F, 0xF6, ++0x06, 0xAF, 0x30, 0x2A, 0x15, 0xD9, 0x40, 0x2A, 0x10, 0xD9, 0x70, 0x2A, 0x3B, 0xD9, 0x80, 0x2A, 0x36, 0xD9, 0x90, 0x2A, ++0x3F, 0xF6, 0xFB, 0xAE, 0x90, 0x21, 0x84, 0x22, 0x10, 0x1D, 0x03, 0xF8, 0x01, 0x2B, 0xC2, 0xB2, 0x91, 0x42, 0xF9, 0xD2, ++0x04, 0x23, 0xA0, 0xE5, 0x40, 0x21, 0x34, 0x22, 0xF4, 0xE7, 0x30, 0x21, 0x24, 0x22, 0xF1, 0xE7, 0x24, 0x22, 0x03, 0xF8, ++0x01, 0x2B, 0x04, 0x32, 0x44, 0x2A, 0xFA, 0xD1, 0x08, 0xF1, 0x6E, 0x06, 0x08, 0x25, 0x04, 0x20, 0x91, 0x24, 0x64, 0x22, ++0x96, 0xE7, 0x00, 0x25, 0x04, 0x20, 0xAA, 0x24, 0x95, 0x22, 0x91, 0xE7, 0x24, 0x22, 0x03, 0xF8, 0x01, 0x2B, 0x04, 0x32, ++0x44, 0x2A, 0xFA, 0xD1, 0x08, 0xF1, 0x6E, 0x06, 0x08, 0x25, 0x04, 0x20, 0x81, 0x24, 0x64, 0x22, 0x84, 0xE7, 0x0F, 0x24, ++0x01, 0x20, 0x00, 0x25, 0x0E, 0x22, 0x7F, 0xE7, 0x80, 0x21, 0x74, 0x22, 0xCA, 0xE7, 0x70, 0x21, 0x64, 0x22, 0xC7, 0xE7, ++0x05, 0x9A, 0x04, 0x92, 0x69, 0xE6, 0x05, 0x9A, 0x04, 0x92, 0xB0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x5C, 0xD1, 0x15, 0x00, 0x70, 0xB5, 0x15, 0x4D, 0x2C, 0x68, 0xA5, 0xF5, 0xBD, 0x56, 0x01, 0x34, 0xA5, 0xF1, 0x90, 0x01, ++0x2C, 0x60, 0x33, 0x46, 0x01, 0x20, 0x9A, 0x88, 0x01, 0x2A, 0x88, 0xBF, 0x98, 0x80, 0x03, 0xF5, 0xF6, 0x73, 0x8B, 0x42, ++0xF7, 0xD1, 0x41, 0xF2, 0xA4, 0x73, 0xF3, 0x58, 0x9C, 0x42, 0x0B, 0xDA, 0x04, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x90, 0xF8, ++0x0B, 0x22, 0xBD, 0xE8, 0x70, 0x40, 0x11, 0x46, 0x4F, 0xF4, 0x30, 0x50, 0xEC, 0xF7, 0xF6, 0xBE, 0x00, 0x21, 0x0B, 0x20, ++0xED, 0xF7, 0x84, 0xF8, 0x4F, 0xF0, 0xFF, 0x33, 0x2B, 0x60, 0x70, 0xBD, 0x18, 0x07, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0x3E, 0x4C, 0x3F, 0x4E, 0x04, 0xF5, 0xBD, 0x53, 0x31, 0x68, 0x1B, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x03, 0xEB, 0x03, 0x13, ++0x04, 0xEB, 0xC3, 0x05, 0x05, 0xF5, 0xB8, 0x55, 0x00, 0x29, 0x05, 0xF1, 0x10, 0x05, 0x4F, 0xEA, 0xC3, 0x03, 0x3A, 0xDB, ++0x23, 0x44, 0x41, 0xF2, 0x13, 0x72, 0x9B, 0x5C, 0x01, 0x2B, 0x45, 0xD9, 0x02, 0x2B, 0x50, 0xD1, 0x02, 0x21, 0x0B, 0x20, ++0xED, 0xF7, 0x5C, 0xF8, 0x30, 0x48, 0x2E, 0x4C, 0xA0, 0xF1, 0x88, 0x06, 0x06, 0xF1, 0x88, 0x09, 0xED, 0xF7, 0xE4, 0xFA, ++0x00, 0x27, 0x4F, 0xF0, 0x02, 0x08, 0x03, 0xE0, 0x04, 0xF5, 0xF6, 0x74, 0xB4, 0x42, 0x18, 0xD0, 0xA3, 0x88, 0x01, 0x2B, ++0xF8, 0xD1, 0x63, 0x7D, 0x04, 0xF1, 0x1C, 0x01, 0x19, 0x44, 0x2A, 0x46, 0xA0, 0x1D, 0xFF, 0xF7, 0x15, 0xFB, 0x00, 0x28, ++0xEE, 0xD0, 0x21, 0x46, 0x27, 0x83, 0xE7, 0x75, 0xA4, 0xF8, 0x04, 0x80, 0x48, 0x46, 0x04, 0xF5, 0xF6, 0x74, 0xED, 0xF7, ++0xC9, 0xFA, 0xB4, 0x42, 0xE6, 0xD1, 0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0x99, 0xBA, 0x1C, 0x44, ++0x41, 0xF2, 0x12, 0x73, 0xE3, 0x5C, 0x05, 0x2B, 0x19, 0xD0, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0xA3, 0x62, 0xEE, 0xF7, ++0x09, 0xFF, 0x41, 0xF2, 0x13, 0x73, 0xE3, 0x5C, 0x01, 0x2B, 0x05, 0xD8, 0x28, 0x46, 0x01, 0x21, 0xBD, 0xE8, 0xF8, 0x43, ++0xFF, 0xF7, 0x24, 0xBB, 0x02, 0x2B, 0xB3, 0xD0, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x08, 0xDB, 0xBD, 0xE8, ++0xF8, 0x83, 0x41, 0xF2, 0x13, 0x73, 0xE3, 0x5C, 0x01, 0x2B, 0xEB, 0xD9, 0x02, 0x2B, 0xA5, 0xD0, 0xBD, 0xE8, 0xF8, 0x43, ++0x05, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xAF, 0x62, 0xEE, 0xF7, 0xE6, 0xBE, 0x78, 0xEF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x10, 0x07, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xD1, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0xDF, 0xF8, 0xCC, 0x80, 0x2C, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x14, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0C, 0xDB, ++0x29, 0x4F, 0x04, 0xEB, 0x04, 0x13, 0x07, 0xEB, 0xC3, 0x03, 0x41, 0xF2, 0x13, 0x72, 0x25, 0x01, 0x9B, 0x5C, 0x01, 0x2B, ++0x19, 0xD9, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x2C, 0x35, 0xDB, 0x22, 0x4F, 0x04, 0xEB, 0x04, 0x16, 0x07, 0xEB, 0xC6, 0x06, ++0x41, 0xF2, 0x12, 0x73, 0x25, 0x01, 0xF3, 0x5C, 0x05, 0x2B, 0x15, 0xD0, 0x1D, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0xD7, 0x62, ++0xEE, 0xF7, 0xAE, 0xFE, 0x41, 0xF2, 0x13, 0x73, 0xF3, 0x5C, 0x01, 0x2B, 0x17, 0xD8, 0x2C, 0x44, 0x07, 0xEB, 0xC4, 0x00, ++0x00, 0xF5, 0xB8, 0x50, 0xBD, 0xE8, 0xF0, 0x41, 0x10, 0x30, 0x00, 0x21, 0xFF, 0xF7, 0xC4, 0xBA, 0x41, 0xF2, 0x13, 0x73, ++0xF3, 0x5C, 0x01, 0x2B, 0xEF, 0xD9, 0xBD, 0xE8, 0xF0, 0x41, 0x0F, 0x49, 0x10, 0x48, 0x40, 0xF2, 0xC1, 0x62, 0xEE, 0xF7, ++0x91, 0xBE, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xF1, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, 0x08, 0x49, ++0x0A, 0x48, 0x40, 0xF2, 0xB7, 0x62, 0xEE, 0xF7, 0x83, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xBD, 0xDB, 0xAD, 0xE7, 0x18, 0x07, 0x18, 0x00, 0x78, 0xEF, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xD1, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0xC0, 0xD1, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0xB5, 0x29, 0xB3, 0x18, 0x4C, 0x04, 0xF5, ++0xBD, 0x53, 0x05, 0x46, 0x1E, 0x68, 0xFE, 0xF7, 0x01, 0xFF, 0x02, 0x46, 0x40, 0xB1, 0x0B, 0x20, 0xED, 0xF7, 0x20, 0xF8, ++0x03, 0x28, 0x1F, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xC6, 0xBE, 0x06, 0xEB, 0x06, 0x16, 0x04, 0xEB, 0xC6, 0x03, ++0x01, 0x21, 0x03, 0xF5, 0xB8, 0x53, 0x85, 0xF8, 0x5E, 0x10, 0x10, 0x33, 0x01, 0x46, 0x28, 0x46, 0xFE, 0xF7, 0x00, 0xFF, ++0x28, 0x46, 0x03, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0xDA, 0xF7, 0x42, 0xB8, 0x0B, 0x20, 0xEC, 0xF7, 0x5B, 0xFF, 0x05, 0x4B, ++0x4F, 0xF0, 0xFF, 0x32, 0x1A, 0x60, 0x70, 0xBD, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0x60, 0xBF, 0x78, 0xEF, 0x17, 0x00, ++0x18, 0x07, 0x18, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0xB0, 0xB6, 0x4F, 0x9D, 0xF8, 0x50, 0x40, 0x03, 0x94, 0x9D, 0xF9, ++0x54, 0x40, 0x04, 0x94, 0x07, 0xF5, 0xBD, 0x55, 0x04, 0x46, 0x28, 0x68, 0x25, 0x7C, 0x8D, 0xF8, 0x20, 0x50, 0x65, 0x7C, ++0x8D, 0xF8, 0x21, 0x50, 0xA5, 0x7C, 0x8D, 0xF8, 0x22, 0x50, 0xE5, 0x7C, 0x8D, 0xF8, 0x23, 0x50, 0x25, 0x7D, 0x8D, 0xF8, ++0x24, 0x50, 0x00, 0x28, 0x65, 0x7D, 0x9D, 0xF8, 0x58, 0x90, 0x8D, 0xF8, 0x25, 0x50, 0x0E, 0x46, 0x90, 0x46, 0x05, 0x93, ++0xC0, 0xF2, 0x1A, 0x81, 0x00, 0xEB, 0x00, 0x10, 0x07, 0xEB, 0xC0, 0x00, 0x00, 0xF5, 0xB8, 0x57, 0x10, 0x37, 0x3A, 0x46, ++0x00, 0x21, 0x08, 0xA8, 0xFF, 0xF7, 0xEE, 0xF9, 0x10, 0xB9, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xBD, 0xF8, 0x20, 0x00, ++0xBD, 0xF8, 0x24, 0x30, 0x01, 0x93, 0x00, 0x21, 0xBD, 0xF8, 0x22, 0xE0, 0x97, 0x4B, 0x98, 0x4A, 0x02, 0x94, 0x8C, 0x46, ++0x0D, 0x46, 0x83, 0x46, 0x0B, 0xE0, 0x98, 0x88, 0x01, 0x28, 0x00, 0xF0, 0xC1, 0x80, 0x03, 0x28, 0x00, 0xF0, 0xB4, 0x80, ++0x88, 0xB1, 0x03, 0xF5, 0xF6, 0x73, 0x93, 0x42, 0x14, 0xD0, 0xB3, 0xF8, 0x06, 0xA0, 0xDA, 0x45, 0xEF, 0xD1, 0x18, 0x89, ++0x70, 0x45, 0xEC, 0xD1, 0x58, 0x89, 0x01, 0x9C, 0xA0, 0x42, 0xE8, 0xD1, 0x02, 0x9C, 0x1D, 0x46, 0x10, 0xE0, 0x00, 0x2D, ++0x08, 0xBF, 0x1D, 0x46, 0x03, 0xF5, 0xF6, 0x73, 0x93, 0x42, 0xEA, 0xD1, 0x02, 0x9C, 0x00, 0x2D, 0x00, 0xF0, 0x42, 0x81, ++0x4F, 0xF4, 0xF6, 0x72, 0x00, 0x21, 0x28, 0x46, 0xCA, 0xF7, 0xDC, 0xF8, 0xAB, 0x88, 0x03, 0x2B, 0xBF, 0xD0, 0x03, 0x9B, ++0xBD, 0xF8, 0x20, 0x10, 0xBD, 0xF8, 0x22, 0x20, 0xC5, 0xF8, 0x0C, 0x80, 0x00, 0x2B, 0xBD, 0xF8, 0x24, 0x30, 0x6B, 0x81, ++0x08, 0xBF, 0x05, 0x20, 0x05, 0xF1, 0x1C, 0x03, 0x18, 0xBF, 0x04, 0x20, 0x02, 0x93, 0x04, 0xF1, 0x24, 0x08, 0x85, 0xF8, ++0x11, 0x90, 0xA8, 0x74, 0xE9, 0x80, 0x2A, 0x81, 0x18, 0x34, 0x05, 0xF1, 0x1B, 0x03, 0x14, 0xF8, 0x01, 0x2B, 0x03, 0xF8, ++0x01, 0x2F, 0x44, 0x45, 0xF9, 0xD1, 0x02, 0x9B, 0xA6, 0xF1, 0x24, 0x09, 0x03, 0xF1, 0x0C, 0x0B, 0xB9, 0xF1, 0x02, 0x0F, ++0x4F, 0xF0, 0x00, 0x03, 0xCD, 0xE9, 0x06, 0x33, 0x40, 0xF3, 0x56, 0x81, 0x4F, 0xF4, 0xE2, 0x7A, 0x3A, 0x46, 0x98, 0xF8, ++0x01, 0x40, 0x98, 0xF8, 0x00, 0x60, 0x98, 0xF8, 0x02, 0x70, 0x02, 0x34, 0x08, 0xF1, 0x02, 0x00, 0x00, 0x2E, 0x71, 0xD0, ++0x03, 0x2E, 0x7D, 0xD0, 0xA9, 0x7C, 0x05, 0x29, 0x00, 0xF2, 0x81, 0x80, 0x2A, 0x2E, 0x00, 0xF0, 0x8D, 0x80, 0x3D, 0x2E, ++0x00, 0xF0, 0x8D, 0x80, 0xC0, 0x2E, 0x00, 0xF0, 0x9A, 0x80, 0xFF, 0x2E, 0x02, 0xD1, 0x08, 0x2C, 0x00, 0xF2, 0xCD, 0x80, ++0x54, 0x45, 0x07, 0xDC, 0x39, 0x46, 0x30, 0x46, 0x01, 0x92, 0xFE, 0xF7, 0xD5, 0xFD, 0x01, 0x9A, 0x00, 0x28, 0x46, 0xD1, ++0xA0, 0x44, 0xA9, 0xEB, 0x04, 0x09, 0xB9, 0xF1, 0x02, 0x0F, 0xD0, 0xDC, 0xCA, 0xF5, 0xE8, 0x7A, 0x1F, 0xFA, 0x8A, 0xFA, ++0xAB, 0x7D, 0xA5, 0xF8, 0x1A, 0xA0, 0x00, 0x2B, 0x00, 0xF0, 0x94, 0x80, 0x04, 0x9B, 0x2B, 0x75, 0x2B, 0x7C, 0x06, 0x9A, ++0x04, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x03, 0x2A, 0x00, 0xF0, 0x05, 0x81, 0x02, 0x2A, 0x00, 0xF0, 0x04, 0x81, 0x03, 0x99, ++0x00, 0x29, 0x40, 0xF0, 0xC0, 0x80, 0x0E, 0x2B, 0x00, 0xF0, 0x14, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x07, 0x9B, ++0x01, 0x2B, 0x0C, 0xBF, 0x54, 0x23, 0x53, 0x23, 0x01, 0x22, 0xEB, 0x74, 0xAA, 0x80, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x00, 0x29, 0x41, 0xD0, 0x93, 0xF9, 0x14, 0xA0, 0x91, 0xF9, 0x14, 0x00, 0x82, 0x45, 0xB8, 0xBF, 0x19, 0x46, 0x42, 0xE7, ++0xBC, 0xF1, 0x00, 0x0F, 0x34, 0xD0, 0x93, 0xF9, 0x14, 0xA0, 0x9C, 0xF9, 0x14, 0x00, 0x82, 0x45, 0xB8, 0xBF, 0x9C, 0x46, ++0x37, 0xE7, 0x43, 0x46, 0xAB, 0xEB, 0x03, 0x00, 0xA0, 0x44, 0x19, 0x78, 0xC1, 0x54, 0x01, 0x33, 0x98, 0x45, 0xFA, 0xD1, ++0xA3, 0x44, 0xAA, 0xEB, 0x04, 0x0A, 0xAC, 0xE7, 0x02, 0x9B, 0x01, 0x92, 0xAB, 0xEB, 0x03, 0x01, 0x69, 0x75, 0xA8, 0x1D, ++0x41, 0x46, 0xFF, 0xF7, 0xF5, 0xF8, 0x01, 0x9A, 0x00, 0x28, 0x95, 0xD1, 0xA8, 0x80, 0x02, 0xE7, 0x02, 0x9B, 0xAB, 0xEB, ++0x03, 0x01, 0xA9, 0x75, 0x01, 0x78, 0x29, 0x74, 0x8C, 0xE7, 0x06, 0x29, 0x3F, 0xF4, 0x7F, 0xAF, 0x08, 0x29, 0x7F, 0xF6, ++0x7F, 0xAF, 0x0D, 0x29, 0x84, 0xD8, 0x7E, 0xE7, 0x00, 0x27, 0xEA, 0xE6, 0x9C, 0x46, 0x08, 0xE7, 0x19, 0x46, 0x06, 0xE7, ++0x06, 0x21, 0xA9, 0x74, 0x7A, 0xE7, 0x18, 0x2C, 0x7F, 0xF4, 0x78, 0xAF, 0x4F, 0xF0, 0x07, 0x03, 0xAB, 0x74, 0x98, 0xF8, ++0x03, 0x10, 0x11, 0xF0, 0x03, 0x03, 0x07, 0x93, 0x06, 0x9B, 0x18, 0xBF, 0x01, 0x23, 0x06, 0x93, 0x6A, 0xE7, 0x07, 0x2C, ++0x7F, 0xF4, 0x68, 0xAF, 0x4F, 0xF0, 0x09, 0x03, 0xAB, 0x74, 0x01, 0x78, 0x00, 0x29, 0x3F, 0xF4, 0x61, 0xAF, 0x01, 0x29, ++0x76, 0xD0, 0x02, 0x29, 0x00, 0xF0, 0x97, 0x80, 0x03, 0x29, 0x06, 0x9B, 0x08, 0xBF, 0x04, 0x23, 0x06, 0x93, 0x55, 0xE7, ++0x78, 0xEF, 0x17, 0x00, 0x88, 0x06, 0x18, 0x00, 0xAA, 0x88, 0x22, 0xB1, 0x95, 0xF9, 0x14, 0x20, 0x04, 0x99, 0x8A, 0x42, ++0x60, 0xDA, 0x04, 0x9A, 0x2A, 0x75, 0x03, 0x9A, 0x00, 0x2A, 0x42, 0xD1, 0x05, 0x99, 0xA1, 0xF6, 0x6C, 0x13, 0x48, 0x2B, ++0x6D, 0xD8, 0x40, 0xF6, 0xB4, 0x13, 0x99, 0x42, 0x00, 0xF0, 0x82, 0x80, 0x48, 0x4A, 0xA1, 0xF6, 0x67, 0x13, 0xA2, 0xFB, ++0x03, 0x23, 0xC3, 0xF3, 0x87, 0x03, 0x2B, 0x74, 0x4F, 0xE7, 0x24, 0x2F, 0x7F, 0xF4, 0x30, 0xAF, 0x09, 0x29, 0x11, 0xD0, ++0x0B, 0x2C, 0x0F, 0xD9, 0xD8, 0xF8, 0x03, 0x10, 0x4B, 0x04, 0x0B, 0xD5, 0x98, 0xF8, 0x09, 0x10, 0x41, 0xB1, 0x01, 0x29, ++0x71, 0xD0, 0x02, 0x29, 0x72, 0xD0, 0x03, 0x29, 0x06, 0x9B, 0x08, 0xBF, 0x04, 0x23, 0x06, 0x93, 0x4F, 0xF0, 0x0E, 0x03, ++0xAB, 0x74, 0x17, 0xE7, 0x89, 0xB3, 0x0D, 0x46, 0xBA, 0xE6, 0x30, 0x2B, 0x24, 0xD9, 0x40, 0x2B, 0x40, 0xD9, 0x90, 0x2B, ++0x4C, 0xD9, 0xA4, 0x2B, 0x59, 0xD8, 0x06, 0x9B, 0x00, 0x2B, 0x54, 0xD0, 0x0A, 0x23, 0x07, 0x9A, 0x01, 0x2A, 0x0C, 0xBF, ++0x74, 0x33, 0x75, 0x33, 0x38, 0xE7, 0x03, 0x9A, 0x01, 0x2A, 0xCA, 0xD1, 0x05, 0x9A, 0xA2, 0xF5, 0x9C, 0x51, 0xA1, 0xF1, ++0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, 0x4D, 0x7F, 0xC1, 0xD8, 0x26, 0x4A, 0xA1, 0xF1, 0x08, 0x03, 0xA2, 0xFB, 0x03, 0x23, ++0xC3, 0xF3, 0x87, 0x03, 0x2B, 0x74, 0x0A, 0xE7, 0x06, 0x9B, 0x23, 0xB3, 0x00, 0x23, 0xE0, 0xE7, 0x2B, 0x7C, 0x04, 0xE7, ++0x02, 0x23, 0x06, 0x93, 0xE4, 0xE6, 0xBC, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x50, 0xAE, 0x9C, 0xF9, 0x14, 0x30, 0x04, 0x9A, ++0x93, 0x42, 0xBF, 0xF6, 0x4A, 0xAE, 0x65, 0x46, 0x7E, 0xE6, 0x82, 0x23, 0x0C, 0xE7, 0x81, 0x23, 0x0A, 0xE7, 0x80, 0x23, ++0x08, 0xE7, 0x03, 0x9B, 0x2B, 0x74, 0xEC, 0xE6, 0x06, 0x9B, 0x8B, 0xB1, 0x03, 0x23, 0xC2, 0xE7, 0x4F, 0xF0, 0x0C, 0x0A, ++0xDC, 0xE6, 0x51, 0x23, 0xFC, 0xE6, 0x73, 0x23, 0xFA, 0xE6, 0x03, 0x23, 0x06, 0x93, 0xC1, 0xE6, 0x06, 0x9B, 0x43, 0xB1, ++0x06, 0x23, 0xB4, 0xE7, 0x52, 0x23, 0xF1, 0xE6, 0x76, 0x23, 0xEF, 0xE6, 0x0E, 0x23, 0x2B, 0x74, 0xD3, 0xE6, 0x79, 0x23, ++0xEA, 0xE6, 0x7C, 0x23, 0xE8, 0xE6, 0x7D, 0x23, 0xE6, 0xE6, 0x02, 0x23, 0x06, 0x93, 0x91, 0xE7, 0x03, 0x23, 0x06, 0x93, ++0x8E, 0xE7, 0x00, 0xBF, 0xCD, 0xCC, 0xCC, 0xCC, 0x2D, 0xE9, 0xF0, 0x48, 0xC1, 0xF3, 0x0A, 0x57, 0xA7, 0xF2, 0xFF, 0x34, ++0x13, 0x2C, 0x0B, 0x46, 0x0D, 0x46, 0x02, 0x46, 0x0F, 0xDC, 0x00, 0x2C, 0x2A, 0xDB, 0x1D, 0x49, 0x21, 0x41, 0x03, 0xEA, ++0x01, 0x00, 0x10, 0x43, 0x2F, 0xD0, 0x4F, 0xF4, 0x00, 0x23, 0x23, 0x41, 0x1D, 0x44, 0x25, 0xEA, 0x01, 0x05, 0x00, 0x23, ++0x25, 0xE0, 0x33, 0x2C, 0x07, 0xDD, 0xB4, 0xF5, 0x80, 0x6F, 0x22, 0xD1, 0x00, 0xF0, 0x2E, 0xF8, 0x02, 0x46, 0x0B, 0x46, ++0x1D, 0xE0, 0xA7, 0xF2, 0x13, 0x47, 0x4F, 0xF0, 0xFF, 0x31, 0x21, 0xFA, 0x07, 0xF7, 0x38, 0x42, 0x15, 0xD0, 0x01, 0x22, ++0xC4, 0xF1, 0x33, 0x03, 0x02, 0xFA, 0x03, 0xF3, 0xC3, 0x18, 0x28, 0xBF, 0xAD, 0x18, 0x23, 0xEA, 0x07, 0x03, 0x08, 0xE0, ++0x01, 0xF0, 0x00, 0x45, 0x01, 0x34, 0x04, 0xBF, 0x45, 0xF0, 0x7F, 0x55, 0x45, 0xF4, 0x40, 0x15, 0x00, 0x23, 0x1A, 0x46, ++0x2B, 0x46, 0x10, 0x46, 0x19, 0x46, 0xBD, 0xE8, 0xF0, 0x88, 0x00, 0xBF, 0xFF, 0xFF, 0x0F, 0x00, 0x81, 0xF0, 0x00, 0x41, ++0x02, 0xE0, 0x00, 0xBF, 0x83, 0xF0, 0x00, 0x43, 0x30, 0xB5, 0x4F, 0xEA, 0x41, 0x04, 0x4F, 0xEA, 0x43, 0x05, 0x94, 0xEA, ++0x05, 0x0F, 0x08, 0xBF, 0x90, 0xEA, 0x02, 0x0F, 0x1F, 0xBF, 0x54, 0xEA, 0x00, 0x0C, 0x55, 0xEA, 0x02, 0x0C, 0x7F, 0xEA, ++0x64, 0x5C, 0x7F, 0xEA, 0x65, 0x5C, 0x00, 0xF0, 0xE2, 0x80, 0x4F, 0xEA, 0x54, 0x54, 0xD4, 0xEB, 0x55, 0x55, 0xB8, 0xBF, ++0x6D, 0x42, 0x0C, 0xDD, 0x2C, 0x44, 0x80, 0xEA, 0x02, 0x02, 0x81, 0xEA, 0x03, 0x03, 0x82, 0xEA, 0x00, 0x00, 0x83, 0xEA, ++0x01, 0x01, 0x80, 0xEA, 0x02, 0x02, 0x81, 0xEA, 0x03, 0x03, 0x36, 0x2D, 0x88, 0xBF, 0x30, 0xBD, 0x11, 0xF0, 0x00, 0x4F, ++0x4F, 0xEA, 0x01, 0x31, 0x4F, 0xF4, 0x80, 0x1C, 0x4C, 0xEA, 0x11, 0x31, 0x02, 0xD0, 0x40, 0x42, 0x61, 0xEB, 0x41, 0x01, ++0x13, 0xF0, 0x00, 0x4F, 0x4F, 0xEA, 0x03, 0x33, 0x4C, 0xEA, 0x13, 0x33, 0x02, 0xD0, 0x52, 0x42, 0x63, 0xEB, 0x43, 0x03, ++0x94, 0xEA, 0x05, 0x0F, 0x00, 0xF0, 0xA7, 0x80, 0xA4, 0xF1, 0x01, 0x04, 0xD5, 0xF1, 0x20, 0x0E, 0x0D, 0xDB, 0x02, 0xFA, ++0x0E, 0xFC, 0x22, 0xFA, 0x05, 0xF2, 0x80, 0x18, 0x41, 0xF1, 0x00, 0x01, 0x03, 0xFA, 0x0E, 0xF2, 0x80, 0x18, 0x43, 0xFA, ++0x05, 0xF3, 0x59, 0x41, 0x0E, 0xE0, 0xA5, 0xF1, 0x20, 0x05, 0x0E, 0xF1, 0x20, 0x0E, 0x01, 0x2A, 0x03, 0xFA, 0x0E, 0xFC, ++0x28, 0xBF, 0x4C, 0xF0, 0x02, 0x0C, 0x43, 0xFA, 0x05, 0xF3, 0xC0, 0x18, 0x51, 0xEB, 0xE3, 0x71, 0x01, 0xF0, 0x00, 0x45, ++0x07, 0xD5, 0x4F, 0xF0, 0x00, 0x0E, 0xDC, 0xF1, 0x00, 0x0C, 0x7E, 0xEB, 0x00, 0x00, 0x6E, 0xEB, 0x01, 0x01, 0xB1, 0xF5, ++0x80, 0x1F, 0x1B, 0xD3, 0xB1, 0xF5, 0x00, 0x1F, 0x0C, 0xD3, 0x49, 0x08, 0x5F, 0xEA, 0x30, 0x00, 0x4F, 0xEA, 0x3C, 0x0C, ++0x04, 0xF1, 0x01, 0x04, 0x4F, 0xEA, 0x44, 0x52, 0x12, 0xF5, 0x80, 0x0F, 0x80, 0xF0, 0x9A, 0x80, 0xBC, 0xF1, 0x00, 0x4F, ++0x08, 0xBF, 0x5F, 0xEA, 0x50, 0x0C, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, 0x04, 0x51, 0x41, 0xEA, 0x05, 0x01, 0x30, 0xBD, ++0x5F, 0xEA, 0x4C, 0x0C, 0x40, 0x41, 0x41, 0xEB, 0x01, 0x01, 0x01, 0x3C, 0x28, 0xBF, 0xB1, 0xF5, 0x80, 0x1F, 0xE9, 0xD2, ++0x91, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x01, 0x46, 0x00, 0x20, 0xB1, 0xFA, 0x81, 0xF3, 0x08, 0xBF, 0x20, 0x33, 0xA3, 0xF1, ++0x0B, 0x03, 0xB3, 0xF1, 0x20, 0x02, 0x0C, 0xDA, 0x0C, 0x32, 0x08, 0xDD, 0x02, 0xF1, 0x14, 0x0C, 0xC2, 0xF1, 0x0C, 0x02, ++0x01, 0xFA, 0x0C, 0xF0, 0x21, 0xFA, 0x02, 0xF1, 0x0C, 0xE0, 0x02, 0xF1, 0x14, 0x02, 0xD8, 0xBF, 0xC2, 0xF1, 0x20, 0x0C, ++0x01, 0xFA, 0x02, 0xF1, 0x20, 0xFA, 0x0C, 0xFC, 0xDC, 0xBF, 0x41, 0xEA, 0x0C, 0x01, 0x90, 0x40, 0xE4, 0x1A, 0xA2, 0xBF, ++0x01, 0xEB, 0x04, 0x51, 0x29, 0x43, 0x30, 0xBD, 0x6F, 0xEA, 0x04, 0x04, 0x1F, 0x3C, 0x1C, 0xDA, 0x0C, 0x34, 0x0E, 0xDC, ++0x04, 0xF1, 0x14, 0x04, 0xC4, 0xF1, 0x20, 0x02, 0x20, 0xFA, 0x04, 0xF0, 0x01, 0xFA, 0x02, 0xF3, 0x40, 0xEA, 0x03, 0x00, ++0x21, 0xFA, 0x04, 0xF3, 0x45, 0xEA, 0x03, 0x01, 0x30, 0xBD, 0xC4, 0xF1, 0x0C, 0x04, 0xC4, 0xF1, 0x20, 0x02, 0x20, 0xFA, ++0x02, 0xF0, 0x01, 0xFA, 0x04, 0xF3, 0x40, 0xEA, 0x03, 0x00, 0x29, 0x46, 0x30, 0xBD, 0x21, 0xFA, 0x04, 0xF0, 0x29, 0x46, ++0x30, 0xBD, 0x94, 0xF0, 0x00, 0x0F, 0x83, 0xF4, 0x80, 0x13, 0x06, 0xBF, 0x81, 0xF4, 0x80, 0x11, 0x01, 0x34, 0x01, 0x3D, ++0x4E, 0xE7, 0x7F, 0xEA, 0x64, 0x5C, 0x18, 0xBF, 0x7F, 0xEA, 0x65, 0x5C, 0x29, 0xD0, 0x94, 0xEA, 0x05, 0x0F, 0x08, 0xBF, ++0x90, 0xEA, 0x02, 0x0F, 0x05, 0xD0, 0x54, 0xEA, 0x00, 0x0C, 0x04, 0xBF, 0x19, 0x46, 0x10, 0x46, 0x30, 0xBD, 0x91, 0xEA, ++0x03, 0x0F, 0x1E, 0xBF, 0x00, 0x21, 0x00, 0x20, 0x30, 0xBD, 0x5F, 0xEA, 0x54, 0x5C, 0x05, 0xD1, 0x40, 0x00, 0x49, 0x41, ++0x28, 0xBF, 0x41, 0xF0, 0x00, 0x41, 0x30, 0xBD, 0x14, 0xF5, 0x80, 0x04, 0x3C, 0xBF, 0x01, 0xF5, 0x80, 0x11, 0x30, 0xBD, ++0x01, 0xF0, 0x00, 0x45, 0x45, 0xF0, 0xFE, 0x41, 0x41, 0xF4, 0x70, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x30, 0xBD, 0x7F, 0xEA, ++0x64, 0x5C, 0x1A, 0xBF, 0x19, 0x46, 0x10, 0x46, 0x7F, 0xEA, 0x65, 0x5C, 0x1C, 0xBF, 0x0B, 0x46, 0x02, 0x46, 0x50, 0xEA, ++0x01, 0x34, 0x06, 0xBF, 0x52, 0xEA, 0x03, 0x35, 0x91, 0xEA, 0x03, 0x0F, 0x41, 0xF4, 0x00, 0x21, 0x30, 0xBD, 0x00, 0xBF, ++0x90, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x00, 0x21, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, 0x32, 0x04, ++0x4F, 0xF0, 0x00, 0x05, 0x4F, 0xF0, 0x00, 0x01, 0x50, 0xE7, 0x00, 0xBF, 0x90, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x00, 0x21, ++0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, 0x32, 0x04, 0x10, 0xF0, 0x00, 0x45, 0x48, 0xBF, 0x40, 0x42, ++0x4F, 0xF0, 0x00, 0x01, 0x3E, 0xE7, 0x00, 0xBF, 0x42, 0x00, 0x4F, 0xEA, 0xE2, 0x01, 0x4F, 0xEA, 0x31, 0x01, 0x4F, 0xEA, ++0x02, 0x70, 0x1F, 0xBF, 0x12, 0xF0, 0x7F, 0x43, 0x93, 0xF0, 0x7F, 0x4F, 0x81, 0xF0, 0x60, 0x51, 0x70, 0x47, 0x32, 0xF0, ++0x7F, 0x42, 0x08, 0xBF, 0x70, 0x47, 0x93, 0xF0, 0x7F, 0x4F, 0x04, 0xBF, 0x41, 0xF4, 0x00, 0x21, 0x70, 0x47, 0x30, 0xB5, ++0x4F, 0xF4, 0x60, 0x74, 0x01, 0xF0, 0x00, 0x45, 0x21, 0xF0, 0x00, 0x41, 0x1C, 0xE7, 0x00, 0xBF, 0x50, 0xEA, 0x01, 0x02, ++0x08, 0xBF, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF0, 0x00, 0x05, 0x0A, 0xE0, 0x50, 0xEA, 0x01, 0x02, 0x08, 0xBF, 0x70, 0x47, ++0x30, 0xB5, 0x11, 0xF0, 0x00, 0x45, 0x02, 0xD5, 0x40, 0x42, 0x61, 0xEB, 0x41, 0x01, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, ++0x32, 0x04, 0x5F, 0xEA, 0x91, 0x5C, 0x3F, 0xF4, 0xD8, 0xAE, 0x4F, 0xF0, 0x03, 0x02, 0x5F, 0xEA, 0xDC, 0x0C, 0x18, 0xBF, ++0x03, 0x32, 0x5F, 0xEA, 0xDC, 0x0C, 0x18, 0xBF, 0x03, 0x32, 0x02, 0xEB, 0xDC, 0x02, 0xC2, 0xF1, 0x20, 0x03, 0x00, 0xFA, ++0x03, 0xFC, 0x20, 0xFA, 0x02, 0xF0, 0x01, 0xFA, 0x03, 0xFE, 0x40, 0xEA, 0x0E, 0x00, 0x21, 0xFA, 0x02, 0xF1, 0x14, 0x44, ++0xBD, 0xE6, 0x00, 0xBF, 0x70, 0xB5, 0x4F, 0xF0, 0xFF, 0x0C, 0x4C, 0xF4, 0xE0, 0x6C, 0x1C, 0xEA, 0x11, 0x54, 0x1D, 0xBF, ++0x1C, 0xEA, 0x13, 0x55, 0x94, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, 0x0F, 0x00, 0xF0, 0xDE, 0xF8, 0x2C, 0x44, 0x81, 0xEA, ++0x03, 0x06, 0x21, 0xEA, 0x4C, 0x51, 0x23, 0xEA, 0x4C, 0x53, 0x50, 0xEA, 0x01, 0x35, 0x18, 0xBF, 0x52, 0xEA, 0x03, 0x35, ++0x41, 0xF4, 0x80, 0x11, 0x43, 0xF4, 0x80, 0x13, 0x38, 0xD0, 0xA0, 0xFB, 0x02, 0xCE, 0x4F, 0xF0, 0x00, 0x05, 0xE1, 0xFB, ++0x02, 0xE5, 0x06, 0xF0, 0x00, 0x42, 0xE0, 0xFB, 0x03, 0xE5, 0x4F, 0xF0, 0x00, 0x06, 0xE1, 0xFB, 0x03, 0x56, 0x9C, 0xF0, ++0x00, 0x0F, 0x18, 0xBF, 0x4E, 0xF0, 0x01, 0x0E, 0xA4, 0xF1, 0xFF, 0x04, 0xB6, 0xF5, 0x00, 0x7F, 0x64, 0xF5, 0x40, 0x74, ++0x04, 0xD2, 0x5F, 0xEA, 0x4E, 0x0E, 0x6D, 0x41, 0x46, 0xEB, 0x06, 0x06, 0x42, 0xEA, 0xC6, 0x21, 0x41, 0xEA, 0x55, 0x51, ++0x4F, 0xEA, 0xC5, 0x20, 0x40, 0xEA, 0x5E, 0x50, 0x4F, 0xEA, 0xCE, 0x2E, 0xB4, 0xF1, 0xFD, 0x0C, 0x88, 0xBF, 0xBC, 0xF5, ++0xE0, 0x6F, 0x1E, 0xD8, 0xBE, 0xF1, 0x00, 0x4F, 0x08, 0xBF, 0x5F, 0xEA, 0x50, 0x0E, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, ++0x04, 0x51, 0x70, 0xBD, 0x06, 0xF0, 0x00, 0x46, 0x46, 0xEA, 0x01, 0x01, 0x40, 0xEA, 0x02, 0x00, 0x81, 0xEA, 0x03, 0x01, ++0xB4, 0xEB, 0x5C, 0x04, 0xC2, 0xBF, 0xD4, 0xEB, 0x0C, 0x05, 0x41, 0xEA, 0x04, 0x51, 0x70, 0xBD, 0x41, 0xF4, 0x80, 0x11, ++0x4F, 0xF0, 0x00, 0x0E, 0x01, 0x3C, 0x00, 0xF3, 0xAB, 0x80, 0x14, 0xF1, 0x36, 0x0F, 0xDE, 0xBF, 0x00, 0x20, 0x01, 0xF0, ++0x00, 0x41, 0x70, 0xBD, 0xC4, 0xF1, 0x00, 0x04, 0x20, 0x3C, 0x35, 0xDA, 0x0C, 0x34, 0x1B, 0xDC, 0x04, 0xF1, 0x14, 0x04, ++0xC4, 0xF1, 0x20, 0x05, 0x00, 0xFA, 0x05, 0xF3, 0x20, 0xFA, 0x04, 0xF0, 0x01, 0xFA, 0x05, 0xF2, 0x40, 0xEA, 0x02, 0x00, ++0x01, 0xF0, 0x00, 0x42, 0x21, 0xF0, 0x00, 0x41, 0x10, 0xEB, 0xD3, 0x70, 0x21, 0xFA, 0x04, 0xF6, 0x42, 0xEB, 0x06, 0x01, ++0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, 0xC4, 0xF1, 0x0C, 0x04, 0xC4, 0xF1, 0x20, 0x05, ++0x00, 0xFA, 0x04, 0xF3, 0x20, 0xFA, 0x05, 0xF0, 0x01, 0xFA, 0x04, 0xF2, 0x40, 0xEA, 0x02, 0x00, 0x01, 0xF0, 0x00, 0x41, ++0x10, 0xEB, 0xD3, 0x70, 0x41, 0xF1, 0x00, 0x01, 0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, ++0xC4, 0xF1, 0x20, 0x05, 0x00, 0xFA, 0x05, 0xF2, 0x4E, 0xEA, 0x02, 0x0E, 0x20, 0xFA, 0x04, 0xF3, 0x01, 0xFA, 0x05, 0xF2, ++0x43, 0xEA, 0x02, 0x03, 0x21, 0xFA, 0x04, 0xF0, 0x01, 0xF0, 0x00, 0x41, 0x21, 0xFA, 0x04, 0xF2, 0x20, 0xEA, 0x02, 0x00, ++0x00, 0xEB, 0xD3, 0x70, 0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, 0x94, 0xF0, 0x00, 0x0F, ++0x0F, 0xD1, 0x01, 0xF0, 0x00, 0x46, 0x40, 0x00, 0x41, 0xEB, 0x01, 0x01, 0x11, 0xF4, 0x80, 0x1F, 0x08, 0xBF, 0x01, 0x3C, ++0xF7, 0xD0, 0x41, 0xEA, 0x06, 0x01, 0x95, 0xF0, 0x00, 0x0F, 0x18, 0xBF, 0x70, 0x47, 0x03, 0xF0, 0x00, 0x46, 0x52, 0x00, ++0x43, 0xEB, 0x03, 0x03, 0x13, 0xF4, 0x80, 0x1F, 0x08, 0xBF, 0x01, 0x3D, 0xF7, 0xD0, 0x43, 0xEA, 0x06, 0x03, 0x70, 0x47, ++0x94, 0xEA, 0x0C, 0x0F, 0x0C, 0xEA, 0x13, 0x55, 0x18, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, 0x0C, 0xD0, 0x50, 0xEA, 0x41, 0x06, ++0x18, 0xBF, 0x52, 0xEA, 0x43, 0x06, 0xD1, 0xD1, 0x81, 0xEA, 0x03, 0x01, 0x01, 0xF0, 0x00, 0x41, 0x4F, 0xF0, 0x00, 0x00, ++0x70, 0xBD, 0x50, 0xEA, 0x41, 0x06, 0x06, 0xBF, 0x10, 0x46, 0x19, 0x46, 0x52, 0xEA, 0x43, 0x06, 0x19, 0xD0, 0x94, 0xEA, ++0x0C, 0x0F, 0x02, 0xD1, 0x50, 0xEA, 0x01, 0x36, 0x13, 0xD1, 0x95, 0xEA, 0x0C, 0x0F, 0x05, 0xD1, 0x52, 0xEA, 0x03, 0x36, ++0x1C, 0xBF, 0x10, 0x46, 0x19, 0x46, 0x0A, 0xD1, 0x81, 0xEA, 0x03, 0x01, 0x01, 0xF0, 0x00, 0x41, 0x41, 0xF0, 0xFE, 0x41, ++0x41, 0xF4, 0x70, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0xBD, 0x41, 0xF0, 0xFE, 0x41, 0x41, 0xF4, 0x78, 0x01, 0x70, 0xBD, ++0x70, 0xB5, 0x4F, 0xF0, 0xFF, 0x0C, 0x4C, 0xF4, 0xE0, 0x6C, 0x1C, 0xEA, 0x11, 0x54, 0x1D, 0xBF, 0x1C, 0xEA, 0x13, 0x55, ++0x94, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, 0x0F, 0x00, 0xF0, 0xA7, 0xF8, 0xA4, 0xEB, 0x05, 0x04, 0x81, 0xEA, 0x03, 0x0E, ++0x52, 0xEA, 0x03, 0x35, 0x4F, 0xEA, 0x01, 0x31, 0x00, 0xF0, 0x88, 0x80, 0x4F, 0xEA, 0x03, 0x33, 0x4F, 0xF0, 0x80, 0x55, ++0x45, 0xEA, 0x13, 0x13, 0x43, 0xEA, 0x12, 0x63, 0x4F, 0xEA, 0x02, 0x22, 0x45, 0xEA, 0x11, 0x15, 0x45, 0xEA, 0x10, 0x65, ++0x4F, 0xEA, 0x00, 0x26, 0x0E, 0xF0, 0x00, 0x41, 0x9D, 0x42, 0x08, 0xBF, 0x96, 0x42, 0x44, 0xF1, 0xFD, 0x04, 0x04, 0xF5, ++0x40, 0x74, 0x02, 0xD2, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0x1A, 0x65, 0xEB, 0x03, 0x05, 0x5B, 0x08, 0x4F, 0xEA, ++0x32, 0x02, 0x4F, 0xF4, 0x80, 0x10, 0x4F, 0xF4, 0x00, 0x2C, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, ++0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x0C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, ++0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x5C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0xEB, ++0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x9C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, ++0x32, 0x02, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0xDC, 0x00, ++0x55, 0xEA, 0x06, 0x0E, 0x18, 0xD0, 0x4F, 0xEA, 0x05, 0x15, 0x45, 0xEA, 0x16, 0x75, 0x4F, 0xEA, 0x06, 0x16, 0x4F, 0xEA, ++0xC3, 0x03, 0x43, 0xEA, 0x52, 0x73, 0x4F, 0xEA, 0xC2, 0x02, 0x5F, 0xEA, 0x1C, 0x1C, 0xC0, 0xD1, 0x11, 0xF4, 0x80, 0x1F, ++0x0B, 0xD1, 0x41, 0xEA, 0x00, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x4F, 0xF0, 0x00, 0x4C, 0xB6, 0xE7, 0x11, 0xF4, 0x80, 0x1F, ++0x04, 0xBF, 0x01, 0x43, 0x00, 0x20, 0xB4, 0xF1, 0xFD, 0x0C, 0x88, 0xBF, 0xBC, 0xF5, 0xE0, 0x6F, 0x3F, 0xF6, 0xAF, 0xAE, ++0xB5, 0xEB, 0x03, 0x0C, 0x04, 0xBF, 0xB6, 0xEB, 0x02, 0x0C, 0x5F, 0xEA, 0x50, 0x0C, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, ++0x04, 0x51, 0x70, 0xBD, 0x0E, 0xF0, 0x00, 0x4E, 0x4E, 0xEA, 0x11, 0x31, 0x14, 0xEB, 0x5C, 0x04, 0xC2, 0xBF, 0xD4, 0xEB, ++0x0C, 0x05, 0x41, 0xEA, 0x04, 0x51, 0x70, 0xBD, 0x41, 0xF4, 0x80, 0x11, 0x4F, 0xF0, 0x00, 0x0E, 0x01, 0x3C, 0x90, 0xE6, ++0x45, 0xEA, 0x06, 0x0E, 0x8D, 0xE6, 0x0C, 0xEA, 0x13, 0x55, 0x94, 0xEA, 0x0C, 0x0F, 0x08, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, ++0x3F, 0xF4, 0x3B, 0xAF, 0x94, 0xEA, 0x0C, 0x0F, 0x0A, 0xD1, 0x50, 0xEA, 0x01, 0x34, 0x7F, 0xF4, 0x34, 0xAF, 0x95, 0xEA, ++0x0C, 0x0F, 0x7F, 0xF4, 0x25, 0xAF, 0x10, 0x46, 0x19, 0x46, 0x2C, 0xE7, 0x95, 0xEA, 0x0C, 0x0F, 0x06, 0xD1, 0x52, 0xEA, ++0x03, 0x35, 0x3F, 0xF4, 0xFD, 0xAE, 0x10, 0x46, 0x19, 0x46, 0x22, 0xE7, 0x50, 0xEA, 0x41, 0x06, 0x18, 0xBF, 0x52, 0xEA, ++0x43, 0x06, 0x7F, 0xF4, 0xC5, 0xAE, 0x50, 0xEA, 0x41, 0x04, 0x7F, 0xF4, 0x0D, 0xAF, 0x52, 0xEA, 0x43, 0x05, 0x7F, 0xF4, ++0xEB, 0xAE, 0x12, 0xE7, 0x4F, 0xF0, 0xFF, 0x3C, 0x06, 0xE0, 0x00, 0xBF, 0x4F, 0xF0, 0x01, 0x0C, 0x02, 0xE0, 0x00, 0xBF, ++0x4F, 0xF0, 0x01, 0x0C, 0x4D, 0xF8, 0x04, 0xCD, 0x4F, 0xEA, 0x41, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0x4F, 0xEA, 0x43, 0x0C, ++0x18, 0xBF, 0x7F, 0xEA, 0x6C, 0x5C, 0x1B, 0xD0, 0x01, 0xB0, 0x50, 0xEA, 0x41, 0x0C, 0x0C, 0xBF, 0x52, 0xEA, 0x43, 0x0C, ++0x91, 0xEA, 0x03, 0x0F, 0x02, 0xBF, 0x90, 0xEA, 0x02, 0x0F, 0x00, 0x20, 0x70, 0x47, 0x10, 0xF1, 0x00, 0x0F, 0x91, 0xEA, ++0x03, 0x0F, 0x58, 0xBF, 0x99, 0x42, 0x08, 0xBF, 0x90, 0x42, 0x2C, 0xBF, 0xD8, 0x17, 0x6F, 0xEA, 0xE3, 0x70, 0x40, 0xF0, ++0x01, 0x00, 0x70, 0x47, 0x4F, 0xEA, 0x41, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0x02, 0xD1, 0x50, 0xEA, 0x01, 0x3C, 0x07, 0xD1, ++0x4F, 0xEA, 0x43, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0xD6, 0xD1, 0x52, 0xEA, 0x03, 0x3C, 0xD3, 0xD0, 0x5D, 0xF8, 0x04, 0x0B, ++0x70, 0x47, 0x00, 0xBF, 0x84, 0x46, 0x10, 0x46, 0x62, 0x46, 0x8C, 0x46, 0x19, 0x46, 0x63, 0x46, 0x00, 0xE0, 0x00, 0xBF, ++0x01, 0xB5, 0xFF, 0xF7, 0xB7, 0xFF, 0x00, 0x28, 0x48, 0xBF, 0x10, 0xF1, 0x00, 0x0F, 0x01, 0xBD, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xF4, 0xFF, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xEA, 0xFF, 0x34, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xE0, 0xFF, 0x94, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xCE, 0xFF, 0x94, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xC4, 0xFF, 0x34, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4A, 0x00, 0x11, 0xD2, ++0x12, 0xF5, 0x00, 0x12, 0x11, 0xD2, 0x0D, 0xD5, 0x6F, 0xF4, 0x78, 0x73, 0xB3, 0xEB, 0x62, 0x52, 0x0E, 0xD4, 0x4F, 0xEA, ++0xC1, 0x23, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xEA, 0x50, 0x53, 0x23, 0xFA, 0x02, 0xF0, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, ++0x70, 0x47, 0x50, 0xEA, 0x01, 0x30, 0x02, 0xD1, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, ++0x4F, 0xEA, 0x41, 0x02, 0xB2, 0xF1, 0xE0, 0x43, 0x24, 0xBF, 0xB3, 0xF5, 0x00, 0x1C, 0xDC, 0xF1, 0xFE, 0x5C, 0x0D, 0xD9, ++0x01, 0xF0, 0x00, 0x4C, 0x4F, 0xEA, 0xC0, 0x02, 0x4C, 0xEA, 0x50, 0x70, 0xB2, 0xF1, 0x00, 0x4F, 0x40, 0xEB, 0x83, 0x00, ++0x08, 0xBF, 0x20, 0xF0, 0x01, 0x00, 0x70, 0x47, 0x11, 0xF0, 0x80, 0x4F, 0x21, 0xD1, 0x13, 0xF1, 0x38, 0x72, 0xBC, 0xBF, ++0x01, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x41, 0xF4, 0x80, 0x11, 0x4F, 0xEA, 0x52, 0x52, 0xC2, 0xF1, 0x18, 0x02, 0xC2, 0xF1, ++0x20, 0x0C, 0x10, 0xFA, 0x0C, 0xF3, 0x20, 0xFA, 0x02, 0xF0, 0x18, 0xBF, 0x40, 0xF0, 0x01, 0x00, 0x4F, 0xEA, 0xC1, 0x23, ++0x4F, 0xEA, 0xD3, 0x23, 0x03, 0xFA, 0x0C, 0xFC, 0x40, 0xEA, 0x0C, 0x00, 0x23, 0xFA, 0x02, 0xF3, 0x4F, 0xEA, 0x43, 0x03, ++0xCC, 0xE7, 0x7F, 0xEA, 0x62, 0x53, 0x07, 0xD1, 0x50, 0xEA, 0x01, 0x33, 0x1E, 0xBF, 0x4F, 0xF0, 0xFE, 0x40, 0x40, 0xF4, ++0x40, 0x00, 0x70, 0x47, 0x01, 0xF0, 0x00, 0x40, 0x40, 0xF0, 0xFE, 0x40, 0x40, 0xF4, 0x00, 0x00, 0x70, 0x47, 0x00, 0xBF, ++0x53, 0xB9, 0x4A, 0xB9, 0x00, 0x29, 0x08, 0xBF, 0x00, 0x28, 0x1C, 0xBF, 0x4F, 0xF0, 0xFF, 0x31, 0x4F, 0xF0, 0xFF, 0x30, ++0x00, 0xF0, 0x6C, 0xB9, 0xAD, 0xF1, 0x08, 0x0C, 0x6D, 0xE9, 0x04, 0xCE, 0x00, 0xF0, 0x06, 0xF8, 0xDD, 0xF8, 0x04, 0xE0, ++0xDD, 0xE9, 0x02, 0x23, 0x04, 0xB0, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, 0x08, 0x9E, 0x0D, 0x46, 0x04, 0x46, 0x8E, 0x46, ++0x00, 0x2B, 0x40, 0xF0, 0x82, 0x80, 0x8A, 0x42, 0x17, 0x46, 0x46, 0xD9, 0xB2, 0xFA, 0x82, 0xF2, 0x4A, 0xB1, 0xC2, 0xF1, ++0x20, 0x01, 0x05, 0xFA, 0x02, 0xF3, 0x20, 0xFA, 0x01, 0xF1, 0x97, 0x40, 0x41, 0xEA, 0x03, 0x0E, 0x94, 0x40, 0x4F, 0xEA, ++0x17, 0x48, 0x23, 0x0C, 0xBE, 0xFB, 0xF8, 0xFC, 0xB9, 0xB2, 0x08, 0xFB, 0x1C, 0xEE, 0x43, 0xEA, 0x0E, 0x43, 0x0C, 0xFB, ++0x01, 0xF0, 0x98, 0x42, 0x0A, 0xD9, 0xFB, 0x18, 0x0C, 0xF1, 0xFF, 0x35, 0x80, 0xF0, 0x16, 0x81, 0x98, 0x42, 0x40, 0xF2, ++0x13, 0x81, 0xAC, 0xF1, 0x02, 0x0C, 0x3B, 0x44, 0x1B, 0x1A, 0xA4, 0xB2, 0xB3, 0xFB, 0xF8, 0xF0, 0x08, 0xFB, 0x10, 0x33, ++0x44, 0xEA, 0x03, 0x44, 0x00, 0xFB, 0x01, 0xF1, 0xA1, 0x42, 0x09, 0xD9, 0x3C, 0x19, 0x00, 0xF1, 0xFF, 0x33, 0x80, 0xF0, ++0x01, 0x81, 0xA1, 0x42, 0x40, 0xF2, 0xFE, 0x80, 0x02, 0x38, 0x3C, 0x44, 0x64, 0x1A, 0x40, 0xEA, 0x0C, 0x40, 0x00, 0x21, ++0x1E, 0xB1, 0xD4, 0x40, 0x00, 0x23, 0xC6, 0xE9, 0x00, 0x43, 0xBD, 0xE8, 0xF0, 0x87, 0x02, 0xB9, 0xFF, 0xDE, 0xB2, 0xFA, ++0x82, 0xF2, 0x00, 0x2A, 0x4F, 0xD1, 0xCB, 0x1B, 0x4F, 0xEA, 0x17, 0x4E, 0x1F, 0xFA, 0x87, 0xF8, 0x01, 0x21, 0xB3, 0xFB, ++0xFE, 0xFC, 0x25, 0x0C, 0x0E, 0xFB, 0x1C, 0x33, 0x45, 0xEA, 0x03, 0x45, 0x08, 0xFB, 0x0C, 0xF3, 0xAB, 0x42, 0x07, 0xD9, ++0x7D, 0x19, 0x0C, 0xF1, 0xFF, 0x30, 0x02, 0xD2, 0xAB, 0x42, 0x00, 0xF2, 0xE7, 0x80, 0x84, 0x46, 0xED, 0x1A, 0xA3, 0xB2, ++0xB5, 0xFB, 0xFE, 0xF0, 0x0E, 0xFB, 0x10, 0x55, 0x43, 0xEA, 0x05, 0x44, 0x08, 0xFB, 0x00, 0xF8, 0xA0, 0x45, 0x07, 0xD9, ++0x3C, 0x19, 0x00, 0xF1, 0xFF, 0x33, 0x02, 0xD2, 0xA0, 0x45, 0x00, 0xF2, 0xD7, 0x80, 0x18, 0x46, 0xA4, 0xEB, 0x08, 0x04, ++0x40, 0xEA, 0x0C, 0x40, 0xC0, 0xE7, 0x8B, 0x42, 0x08, 0xD9, 0x00, 0x2E, 0x00, 0xF0, 0xAF, 0x80, 0x00, 0x21, 0xC6, 0xE9, ++0x00, 0x05, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xB3, 0xFA, 0x83, 0xF1, 0x00, 0x29, 0x4B, 0xD1, 0xAB, 0x42, 0x02, 0xD3, ++0x82, 0x42, 0x00, 0xF2, 0xB7, 0x80, 0x84, 0x1A, 0x65, 0xEB, 0x03, 0x03, 0x01, 0x20, 0x9E, 0x46, 0x00, 0x2E, 0xAA, 0xD0, ++0xC6, 0xE9, 0x00, 0x4E, 0xA7, 0xE7, 0xC2, 0xF1, 0x20, 0x0C, 0x01, 0xFA, 0x02, 0xF3, 0x97, 0x40, 0x20, 0xFA, 0x0C, 0xF0, ++0x4F, 0xEA, 0x17, 0x4E, 0x21, 0xFA, 0x0C, 0xFC, 0x18, 0x43, 0xBC, 0xFB, 0xFE, 0xF1, 0x05, 0x0C, 0x0E, 0xFB, 0x11, 0xCC, ++0x1F, 0xFA, 0x87, 0xF8, 0x45, 0xEA, 0x0C, 0x45, 0x01, 0xFB, 0x08, 0xF3, 0xAB, 0x42, 0x04, 0xFA, 0x02, 0xF4, 0x09, 0xD9, ++0x7D, 0x19, 0x01, 0xF1, 0xFF, 0x3C, 0x80, 0xF0, 0x8B, 0x80, 0xAB, 0x42, 0x40, 0xF2, 0x88, 0x80, 0x02, 0x39, 0x3D, 0x44, ++0xEB, 0x1A, 0x85, 0xB2, 0xB3, 0xFB, 0xFE, 0xF0, 0x0E, 0xFB, 0x10, 0x33, 0x45, 0xEA, 0x03, 0x45, 0x00, 0xFB, 0x08, 0xF3, ++0xAB, 0x42, 0x07, 0xD9, 0x7D, 0x19, 0x00, 0xF1, 0xFF, 0x3C, 0x71, 0xD2, 0xAB, 0x42, 0x6F, 0xD9, 0x02, 0x38, 0x3D, 0x44, ++0xEB, 0x1A, 0x40, 0xEA, 0x01, 0x41, 0x78, 0xE7, 0xC1, 0xF1, 0x20, 0x0C, 0x8B, 0x40, 0x22, 0xFA, 0x0C, 0xF7, 0x1F, 0x43, ++0x20, 0xFA, 0x0C, 0xF4, 0x05, 0xFA, 0x01, 0xF3, 0x4F, 0xEA, 0x17, 0x4E, 0x25, 0xFA, 0x0C, 0xF5, 0x1C, 0x43, 0x23, 0x0C, ++0xB5, 0xFB, 0xFE, 0xF9, 0x1F, 0xFA, 0x87, 0xF8, 0x0E, 0xFB, 0x19, 0x55, 0x43, 0xEA, 0x05, 0x45, 0x09, 0xFB, 0x08, 0xFA, ++0xAA, 0x45, 0x02, 0xFA, 0x01, 0xF2, 0x00, 0xFA, 0x01, 0xF3, 0x08, 0xD9, 0x7D, 0x19, 0x09, 0xF1, 0xFF, 0x30, 0x47, 0xD2, ++0xAA, 0x45, 0x45, 0xD9, 0xA9, 0xF1, 0x02, 0x09, 0x3D, 0x44, 0xA5, 0xEB, 0x0A, 0x05, 0xA4, 0xB2, 0xB5, 0xFB, 0xFE, 0xF0, ++0x0E, 0xFB, 0x10, 0x55, 0x44, 0xEA, 0x05, 0x44, 0x00, 0xFB, 0x08, 0xF8, 0xA0, 0x45, 0x07, 0xD9, 0x3C, 0x19, 0x00, 0xF1, ++0xFF, 0x35, 0x2D, 0xD2, 0xA0, 0x45, 0x2B, 0xD9, 0x02, 0x38, 0x3C, 0x44, 0x40, 0xEA, 0x09, 0x40, 0xA4, 0xEB, 0x08, 0x04, ++0xA0, 0xFB, 0x02, 0x89, 0x4C, 0x45, 0xC6, 0x46, 0x4D, 0x46, 0x19, 0xD3, 0x16, 0xD0, 0x5E, 0xB1, 0xB3, 0xEB, 0x0E, 0x02, ++0x64, 0xEB, 0x05, 0x04, 0x04, 0xFA, 0x0C, 0xFC, 0xCA, 0x40, 0x4C, 0xEA, 0x02, 0x02, 0xCC, 0x40, 0xC6, 0xE9, 0x00, 0x24, ++0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x87, 0x31, 0x46, 0x30, 0x46, 0x0E, 0xE7, 0xAC, 0x46, 0xED, 0xE6, 0x18, 0x46, 0x01, 0xE7, ++0x43, 0x45, 0xE6, 0xD2, 0xB8, 0xEB, 0x02, 0x0E, 0x69, 0xEB, 0x07, 0x05, 0x01, 0x38, 0xE0, 0xE7, 0x28, 0x46, 0xD3, 0xE7, ++0x60, 0x46, 0x8F, 0xE7, 0x81, 0x46, 0xBA, 0xE7, 0x61, 0x46, 0x77, 0xE7, 0x08, 0x46, 0x4B, 0xE7, 0xAC, 0xF1, 0x02, 0x0C, ++0x3D, 0x44, 0x15, 0xE7, 0x02, 0x38, 0x3C, 0x44, 0x26, 0xE7, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x28, 0xB8, 0xBF, ++0x40, 0x42, 0x70, 0x47, 0x03, 0x2A, 0x70, 0xB4, 0x12, 0xD9, 0x40, 0xEA, 0x01, 0x05, 0xAD, 0x07, 0x04, 0x46, 0x0B, 0x46, ++0x1E, 0xD1, 0x19, 0x46, 0x20, 0x46, 0x53, 0xF8, 0x04, 0x5B, 0x54, 0xF8, 0x04, 0x6B, 0xAE, 0x42, 0x16, 0xD1, 0x04, 0x3A, ++0x03, 0x2A, 0x20, 0x46, 0x19, 0x46, 0xF2, 0xD8, 0x56, 0x1E, 0xA2, 0xB1, 0x01, 0x39, 0x44, 0x1E, 0x01, 0xE0, 0xC3, 0x18, ++0x0C, 0xD0, 0x14, 0xF8, 0x01, 0x5F, 0x11, 0xF8, 0x01, 0x2F, 0x95, 0x42, 0xA6, 0xEB, 0x04, 0x03, 0xF5, 0xD0, 0xA8, 0x1A, ++0x70, 0xBC, 0x70, 0x47, 0x56, 0x1E, 0xED, 0xE7, 0x18, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x10, 0x46, 0xF6, 0xE7, 0x00, 0xBF, ++0x84, 0x46, 0x41, 0xEA, 0x00, 0x03, 0x13, 0xF0, 0x03, 0x03, 0x6D, 0xD1, 0x40, 0x3A, 0x41, 0xD3, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x40, 0x3A, 0xBD, 0xD2, 0x30, 0x32, 0x11, 0xD3, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x10, 0x3A, 0xED, 0xD2, 0x0C, 0x32, 0x05, 0xD3, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x04, 0x3A, 0xF9, 0xD2, 0x04, 0x32, 0x08, 0xD0, 0xD2, 0x07, 0x1C, 0xBF, 0x11, 0xF8, 0x01, 0x3B, 0x00, 0xF8, 0x01, 0x3B, ++0x01, 0xD3, 0x0B, 0x88, 0x03, 0x80, 0x60, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x08, 0x2A, 0x13, 0xD3, 0x8B, 0x07, 0x8D, 0xD0, ++0x10, 0xF0, 0x03, 0x03, 0x8A, 0xD0, 0xC3, 0xF1, 0x04, 0x03, 0xD2, 0x1A, 0xDB, 0x07, 0x1C, 0xBF, 0x11, 0xF8, 0x01, 0x3B, ++0x00, 0xF8, 0x01, 0x3B, 0x80, 0xD3, 0x31, 0xF8, 0x02, 0x3B, 0x20, 0xF8, 0x02, 0x3B, 0x7B, 0xE7, 0x04, 0x3A, 0xD9, 0xD3, ++0x01, 0x3A, 0x11, 0xF8, 0x01, 0x3B, 0x00, 0xF8, 0x01, 0x3B, 0xF9, 0xD2, 0x0B, 0x78, 0x03, 0x70, 0x4B, 0x78, 0x43, 0x70, ++0x8B, 0x78, 0x83, 0x70, 0x60, 0x46, 0x70, 0x47, 0x88, 0x42, 0xF0, 0xB4, 0x0D, 0xD9, 0x8B, 0x18, 0x83, 0x42, 0x0A, 0xD9, ++0x84, 0x18, 0x32, 0xB1, 0x22, 0x46, 0x13, 0xF8, 0x01, 0x4D, 0x02, 0xF8, 0x01, 0x4D, 0x99, 0x42, 0xF9, 0xD1, 0xF0, 0xBC, ++0x70, 0x47, 0x0F, 0x2A, 0x0E, 0xD8, 0x03, 0x46, 0x54, 0x1E, 0x00, 0x2A, 0xF7, 0xD0, 0x01, 0x34, 0x0C, 0x44, 0x01, 0x3B, ++0x11, 0xF8, 0x01, 0x2B, 0x03, 0xF8, 0x01, 0x2F, 0xA1, 0x42, 0xF9, 0xD1, 0xF0, 0xBC, 0x70, 0x47, 0x40, 0xEA, 0x01, 0x03, ++0x9B, 0x07, 0x3F, 0xD1, 0xA2, 0xF1, 0x10, 0x03, 0x23, 0xF0, 0x0F, 0x04, 0x01, 0xF1, 0x20, 0x07, 0x27, 0x44, 0x1B, 0x09, ++0x01, 0xF1, 0x10, 0x04, 0x00, 0xF1, 0x10, 0x05, 0x54, 0xF8, 0x10, 0x6C, 0x45, 0xF8, 0x10, 0x6C, 0x54, 0xF8, 0x0C, 0x6C, ++0x45, 0xF8, 0x0C, 0x6C, 0x54, 0xF8, 0x08, 0x6C, 0x45, 0xF8, 0x08, 0x6C, 0x54, 0xF8, 0x04, 0x6C, 0x45, 0xF8, 0x04, 0x6C, ++0x10, 0x34, 0xBC, 0x42, 0x05, 0xF1, 0x10, 0x05, 0xEA, 0xD1, 0x01, 0x33, 0x12, 0xF0, 0x0C, 0x0F, 0x01, 0xEB, 0x03, 0x11, ++0x02, 0xF0, 0x0F, 0x04, 0x00, 0xEB, 0x03, 0x13, 0x17, 0xD0, 0x04, 0x3C, 0x24, 0xF0, 0x03, 0x0C, 0xA5, 0x08, 0x9C, 0x44, ++0x1C, 0x1F, 0x0E, 0x46, 0x56, 0xF8, 0x04, 0x7B, 0x44, 0xF8, 0x04, 0x7F, 0x64, 0x45, 0xF9, 0xD1, 0x6C, 0x1C, 0x03, 0xEB, ++0x84, 0x03, 0x01, 0xEB, 0x84, 0x01, 0x02, 0xF0, 0x03, 0x02, 0xAD, 0xE7, 0x54, 0x1E, 0x03, 0x46, 0xAD, 0xE7, 0x22, 0x46, ++0xA8, 0xE7, 0x00, 0xBF, 0x0B, 0x4B, 0x0C, 0x48, 0x19, 0x68, 0xD1, 0xE9, 0x2A, 0x23, 0x10, 0xB4, 0x0A, 0x4C, 0x00, 0xFB, ++0x02, 0xF0, 0x04, 0xFB, 0x03, 0x00, 0xA2, 0xFB, 0x04, 0x34, 0x04, 0x44, 0x5A, 0x1C, 0x44, 0xF1, 0x00, 0x00, 0xC1, 0xE9, ++0x2A, 0x20, 0x10, 0xBC, 0x20, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x80, 0x01, 0x17, 0x00, 0x2D, 0xF4, 0x51, 0x58, ++0x2D, 0x7F, 0x95, 0x4C, 0x11, 0xF0, 0xFF, 0x01, 0x03, 0x46, 0x44, 0xD0, 0x82, 0x07, 0x32, 0xD1, 0x70, 0xB4, 0x04, 0x68, ++0x41, 0xEA, 0x01, 0x26, 0x46, 0xEA, 0x06, 0x46, 0x86, 0xEA, 0x04, 0x05, 0xA5, 0xF1, 0x01, 0x33, 0xA4, 0xF1, 0x01, 0x32, ++0x23, 0xEA, 0x05, 0x03, 0x22, 0xEA, 0x04, 0x02, 0x13, 0x43, 0x13, 0xF0, 0x80, 0x3F, 0x0F, 0xD1, 0x50, 0xF8, 0x04, 0x4F, ++0x84, 0xEA, 0x06, 0x05, 0xA5, 0xF1, 0x01, 0x32, 0xA4, 0xF1, 0x01, 0x33, 0x22, 0xEA, 0x05, 0x02, 0x23, 0xEA, 0x04, 0x03, ++0x13, 0x43, 0x13, 0xF0, 0x80, 0x3F, 0xEF, 0xD0, 0x03, 0x78, 0x23, 0xB9, 0x36, 0xE0, 0x10, 0xF8, 0x01, 0x3F, 0x00, 0x2B, ++0x32, 0xD0, 0x99, 0x42, 0xF9, 0xD1, 0x30, 0xE0, 0x8A, 0x42, 0x11, 0xD0, 0x9A, 0x07, 0x18, 0x46, 0xCC, 0xD0, 0x18, 0x46, ++0x13, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0xF5, 0xD1, 0x10, 0x46, 0x70, 0x47, 0x99, 0x07, 0x18, 0x46, 0x07, 0xD0, 0x18, 0x46, ++0x01, 0x33, 0x02, 0x78, 0x00, 0x2A, 0xF7, 0xD1, 0x70, 0x47, 0x82, 0x07, 0xF7, 0xD1, 0x02, 0x68, 0xA2, 0xF1, 0x01, 0x33, ++0x23, 0xEA, 0x02, 0x03, 0x13, 0xF0, 0x80, 0x3F, 0x08, 0xD1, 0x50, 0xF8, 0x04, 0x2F, 0xA2, 0xF1, 0x01, 0x33, 0x23, 0xEA, ++0x02, 0x03, 0x13, 0xF0, 0x80, 0x3F, 0xF6, 0xD0, 0x03, 0x78, 0x00, 0x2B, 0xE8, 0xD0, 0x10, 0xF8, 0x01, 0x3F, 0x00, 0x2B, ++0xFB, 0xD1, 0x70, 0x47, 0x18, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x80, 0xEA, 0x01, 0x02, 0x84, 0x46, 0x12, 0xF0, ++0x03, 0x0F, 0x4F, 0xD1, 0x11, 0xF0, 0x03, 0x0F, 0x32, 0xD1, 0x4D, 0xF8, 0x04, 0x4D, 0x11, 0xF0, 0x04, 0x0F, 0x51, 0xF8, ++0x04, 0x3B, 0x0B, 0xD0, 0xA3, 0xF1, 0x01, 0x32, 0x9A, 0x43, 0x12, 0xF0, 0x80, 0x3F, 0x04, 0xBF, 0x4C, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x16, 0xD1, 0x00, 0xBF, 0x51, 0xF8, 0x04, 0x4B, 0xA3, 0xF1, 0x01, 0x32, 0x9A, 0x43, 0x12, 0xF0, ++0x80, 0x3F, 0xA4, 0xF1, 0x01, 0x32, 0x0B, 0xD1, 0x4C, 0xF8, 0x04, 0x3B, 0xA2, 0x43, 0x12, 0xF0, 0x80, 0x3F, 0x04, 0xBF, ++0x51, 0xF8, 0x04, 0x3B, 0x4C, 0xF8, 0x04, 0x4B, 0xEA, 0xD0, 0x23, 0x46, 0x0C, 0xF8, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x0F, ++0x4F, 0xEA, 0x33, 0x23, 0xF8, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x11, 0xF0, 0x01, 0x0F, 0x06, 0xD0, 0x11, 0xF8, ++0x01, 0x2B, 0x0C, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0x08, 0xBF, 0x70, 0x47, 0x11, 0xF0, 0x02, 0x0F, 0xBF, 0xD0, 0x31, 0xF8, ++0x02, 0x2B, 0x12, 0xF0, 0xFF, 0x0F, 0x16, 0xBF, 0x2C, 0xF8, 0x02, 0x2B, 0x8C, 0xF8, 0x00, 0x20, 0x12, 0xF4, 0x7F, 0x4F, ++0xB3, 0xD1, 0x70, 0x47, 0x11, 0xF8, 0x01, 0x2B, 0x0C, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0xF9, 0xD1, 0x70, 0x47, 0x00, 0xBF, ++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, 0x00, 0x00, 0x00, 0x00, 0x90, 0xF8, 0x00, 0xF0, ++0x6D, 0xE9, 0x02, 0x45, 0x20, 0xF0, 0x07, 0x01, 0x6F, 0xF0, 0x00, 0x0C, 0x10, 0xF0, 0x07, 0x04, 0x91, 0xF8, 0x20, 0xF0, ++0x40, 0xF0, 0x49, 0x80, 0x4F, 0xF0, 0x00, 0x04, 0x6F, 0xF0, 0x07, 0x00, 0xD1, 0xE9, 0x00, 0x23, 0x91, 0xF8, 0x40, 0xF0, ++0x00, 0xF1, 0x08, 0x00, 0x82, 0xFA, 0x4C, 0xF2, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, ++0x4B, 0xBB, 0xD1, 0xE9, 0x02, 0x23, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, ++0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, 0xE3, 0xB9, 0xD1, 0xE9, 0x04, 0x23, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, ++0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, 0x7B, 0xB9, 0xD1, 0xE9, 0x06, 0x23, 0x01, 0xF1, ++0x20, 0x01, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, ++0x8C, 0xF3, 0x00, 0x2B, 0xC6, 0xD0, 0x00, 0x2A, 0x04, 0xBF, 0x04, 0x30, 0x1A, 0x46, 0x12, 0xBA, 0xB2, 0xFA, 0x82, 0xF2, ++0xFD, 0xE8, 0x02, 0x45, 0x00, 0xEB, 0xD2, 0x00, 0x70, 0x47, 0xD1, 0xE9, 0x00, 0x23, 0x04, 0xF0, 0x03, 0x05, 0xC4, 0xF1, ++0x00, 0x00, 0x4F, 0xEA, 0xC5, 0x05, 0x14, 0xF0, 0x04, 0x0F, 0x91, 0xF8, 0x40, 0xF0, 0x0C, 0xFA, 0x05, 0xF5, 0x62, 0xEA, ++0x05, 0x02, 0x1C, 0xBF, 0x63, 0xEA, 0x05, 0x03, 0x62, 0x46, 0x4F, 0xF0, 0x00, 0x04, 0xA9, 0xE7, 0x9A, 0xB3, 0xF0, 0xB4, ++0x40, 0xEA, 0x01, 0x05, 0xAD, 0x07, 0x04, 0x46, 0x03, 0x46, 0x08, 0x46, 0x28, 0xD0, 0x20, 0x78, 0x0E, 0x78, 0x86, 0x42, ++0x29, 0xD1, 0x01, 0x2A, 0x2A, 0xD0, 0x25, 0x46, 0x50, 0xB1, 0x15, 0xF8, 0x01, 0x0F, 0x11, 0xF8, 0x01, 0x6F, 0xEB, 0x43, ++0xB0, 0x42, 0x13, 0x44, 0x1D, 0xD1, 0xE3, 0x18, 0xF4, 0xD1, 0x18, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0x07, 0x68, 0x1C, 0x46, ++0x53, 0xF8, 0x04, 0x5B, 0xA5, 0xF1, 0x01, 0x36, 0xBD, 0x42, 0x01, 0x46, 0x26, 0xEA, 0x05, 0x06, 0x00, 0xF1, 0x04, 0x00, ++0xDD, 0xD1, 0x04, 0x3A, 0x1C, 0x46, 0x01, 0x46, 0x0A, 0xD0, 0x16, 0xF0, 0x80, 0x3F, 0x07, 0xD1, 0x03, 0x2A, 0xE9, 0xD8, ++0xD3, 0xE7, 0x10, 0x46, 0x70, 0x47, 0x80, 0x1B, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0x20, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0xBF, ++0x6D, 0x65, 0x6D, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x6C, 0x61, 0x70, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x6B, 0x5F, 0x73, 0x74, ++0x61, 0x72, 0x74, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x5F, 0x65, 0x6E, 0x64, 0x3D, 0x25, 0x78, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x6D, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x6C, 0x61, 0x70, 0x73, 0x3A, 0x20, 0x73, 0x74, ++0x6B, 0x5F, 0x65, 0x6E, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x3D, ++0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, ++0x6D, 0x61, 0x69, 0x6E, 0x21, 0x0D, 0x0A, 0x00, 0x10, 0x14, 0x08, 0x12, 0x3C, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, ++0x08, 0x12, 0xC7, 0x11, 0x10, 0x14, 0x08, 0x12, 0x3C, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, 0x08, 0x12, 0x45, 0x11, ++0x08, 0x12, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0x03, 0x11, 0x08, 0x12, 0x04, 0x11, ++0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0xC2, 0x10, 0x08, 0x12, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, ++0x07, 0x12, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x86, 0x11, 0xC3, 0x10, ++0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x86, 0x11, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, ++0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, 0x08, 0x12, 0x04, 0x11, ++0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, 0x08, 0x12, 0x03, 0x11, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, ++0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x8A, 0x12, 0x0C, 0x13, ++0x04, 0x11, 0x03, 0x11, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x8A, 0x12, 0x86, 0x11, 0x04, 0x11, 0x03, 0x11, ++0x9D, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x62, 0x61, 0x6E, 0x64, 0x3D, 0x25, 0x64, 0x20, 0x66, 0x72, 0x65, 0x71, 0x3D, 0x25, ++0x64, 0x20, 0x66, 0x72, 0x65, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x74, 0x79, 0x70, 0x65, 0x3D, ++0x25, 0x64, 0x20, 0x73, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x63, 0x68, 0x61, 0x6E, 0x3A, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x62, 0x61, 0x6E, 0x64, 0x20, ++0x25, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x62, 0x61, 0x6E, 0x64, 0x20, 0x3C, 0x20, 0x50, ++0x48, 0x59, 0x5F, 0x42, 0x41, 0x4E, 0x44, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x28, 0x6D, 0x64, 0x6D, 0x5F, 0x6D, 0x61, 0x6A, ++0x6F, 0x72, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x2B, 0x20, ++0x32, 0x29, 0x20, 0x2A, 0x20, 0x31, 0x30, 0x20, 0x2B, 0x20, 0x6D, 0x64, 0x6D, 0x5F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x5F, ++0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x58, ++0x5F, 0x4D, 0x44, 0x4D, 0x5F, 0x56, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x72, 0x61, ++0x64, 0x69, 0x6F, 0x20, 0x25, 0x64, 0x20, 0x64, 0x6F, 0x65, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, ++0x74, 0x0A, 0x00, 0x00, 0x9D, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x61, ++0x6D, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x2C, 0x20, 0x64, 0x6F, 0x20, 0x6E, 0x6F, 0x74, 0x68, 0x69, ++0x6E, 0x67, 0x0A, 0x00, 0x9B, 0x25, 0x73, 0x20, 0x4D, 0x41, 0x43, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x21, 0x3D, ++0x20, 0x49, 0x44, 0x4C, 0x45, 0x0A, 0x00, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x68, 0x77, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x63, ++0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x00, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x63, 0x68, 0x61, 0x6E, ++0x6E, 0x65, 0x6C, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x67, 0x65, 0x74, 0x5F, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x00, ++0x70, 0x68, 0x79, 0x5F, 0x73, 0x74, 0x6F, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x0D, 0xFE, 0x11, 0xFE, 0x0D, 0x02, ++0x0E, 0xFF, 0x13, 0xFE, 0x0B, 0x02, 0x0C, 0xFD, 0x12, 0xFD, 0x0C, 0x03, 0x0D, 0xFE, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, ++0x14, 0xFD, 0x0A, 0x03, 0x0B, 0xFC, 0x11, 0xFF, 0x0D, 0x01, 0x0E, 0xFF, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x12, 0xFE, ++0x0C, 0x02, 0x0D, 0xFE, 0x12, 0xFE, 0x0C, 0x02, 0x0D, 0xFE, 0x12, 0xFE, 0x0C, 0x02, 0x0D, 0xFE, 0x13, 0xFE, 0x0B, 0x02, ++0x0C, 0xFD, 0x1F, 0x00, 0x0C, 0x02, 0x0D, 0xFE, 0x11, 0x00, 0x0D, 0x00, 0x0E, 0xFF, 0x13, 0x03, 0x0B, 0x03, 0x0C, 0xFD, ++0x14, 0xFC, 0x0A, 0x04, 0x0B, 0xFC, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x11, 0xFE, 0x0D, 0x02, 0x0E, 0xFF, 0x13, 0xFE, ++0x0B, 0x02, 0x0C, 0xFD, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x12, 0xFD, 0x0C, 0x03, ++0x0D, 0xFE, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x13, 0xFE, 0x0B, 0x02, 0x0C, 0xFD, ++0x1F, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x74, 0x63, 0x5F, 0x73, 0x70, 0x75, 0x72, 0x69, 0x6F, 0x75, 0x73, 0x00, 0x00, 0x00, ++0x18, 0x10, 0x0C, 0x08, 0x07, 0x06, 0x8B, 0x05, 0x89, 0x04, 0x87, 0x03, 0x85, 0x02, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x65, 0x74, 0x20, 0x74, 0x78, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x32, 0x2E, 0x34, ++0x67, 0x28, 0x70, 0x61, 0x5F, 0x64, 0x72, 0x76, 0x5F, 0x69, 0x62, 0x69, 0x74, 0x29, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x77, 0x66, 0x20, 0x64, 0x66, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x66, 0x69, 0x6E, 0x74, 0x66, 0x20, 0x52, 0x58, ++0x4F, 0x4E, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, 0x66, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, ++0x66, 0x69, 0x6E, 0x74, 0x66, 0x20, 0x52, 0x58, 0x4F, 0x46, 0x46, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x64, 0x65, 0x74, 0x65, ++0x63, 0x74, 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x62, 0x79, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, ++0x69, 0x6E, 0x20, 0x63, 0x61, 0x6C, 0x5F, 0x6C, 0x73, 0x20, 0x64, 0x65, 0x74, 0x20, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x6C, 0x6F, 0x70, 0x65, 0x20, 0x74, 0x6F, 0x6F, 0x20, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x66, 0x69, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, ++0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x66, 0x69, ++0x74, 0x5F, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x21, 0x0D, 0x0A, 0x00, 0x63, 0x6F, 0x65, 0x66, 0x5F, 0x49, 0x51, 0x20, ++0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2E, 0x00, 0x25, 0x30, 0x33, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, ++0x73, 0x64, 0x6D, 0x20, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, ++0x66, 0x72, 0x65, 0x71, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, ++0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x66, 0x65, 0x6E, ++0x20, 0x72, 0x65, 0x67, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, ++0x63, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x21, 0x0D, 0x0A, 0x00, 0x66, 0x69, 0x74, 0x2D, ++0x69, 0x6E, 0x2D, 0x49, 0x20, 0x25, 0x78, 0x3A, 0x20, 0x5B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, ++0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x5D, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x66, 0x69, 0x74, 0x2D, 0x69, 0x6E, 0x2D, 0x51, 0x20, 0x25, 0x78, 0x3A, 0x20, 0x5B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x5D, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x63, 0x61, 0x6C, 0x49, 0x20, 0x25, ++0x78, 0x2C, 0x20, 0x63, 0x61, 0x6C, 0x51, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, ++0x63, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x20, 0x65, 0x6E, 0x64, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x5F, ++0x63, 0x66, 0x67, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, ++0x70, 0x6C, 0x6C, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x63, 0x6B, 0x3A, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x77, 0x66, 0x72, 0x66, 0x20, 0x6F, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x66, 0x72, 0x66, 0x20, 0x6F, 0x66, 0x66, ++0x0D, 0x0A, 0x00, 0x00, 0x20, 0x2A, 0x20, 0x63, 0x61, 0x6C, 0x20, 0x74, 0x69, 0x61, 0x5F, 0x69, 0x71, 0x3A, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x49, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x30, 0x3D, 0x25, 0x64, ++0x2C, 0x20, 0x56, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x30, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, ++0x20, 0x20, 0x49, 0x69, 0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x69, ++0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x20, 0x61, 0x64, 0x6A, ++0x49, 0x69, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x61, 0x64, 0x6A, 0x49, 0x71, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x2D, 0x3E, 0x20, 0x49, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x30, 0x3D, 0x25, ++0x64, 0x2C, 0x20, 0x56, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x30, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x2A, 0x6C, 0x6E, 0x61, 0x5F, 0x76, 0x63, 0x6D, 0x70, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6C, 0x6E, ++0x61, 0x5F, 0x76, 0x63, 0x6D, 0x6E, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, ++0x67, 0x61, 0x69, 0x6E, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x72, 0x66, ++0x20, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, ++0x3C, 0x3D, 0x20, 0x33, 0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x69, ++0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x00, 0x73, 0x66, 0x74, 0x20, 0x64, 0x69, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x66, 0x74, 0x72, 0x73, 0x74, 0x20, 0x64, 0x6F, 0x6E, 0x65, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x6F, 0x61, 0x64, ++0x5F, 0x76, 0x61, 0x6C, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x75, 0x73, ++0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x68, 0x6F, 0x73, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x5F, 0x64, 0x6D, 0x61, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x20, 0x21, 0x3D, ++0x20, 0x30, 0x00, 0x00, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x64, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, ++0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x20, 0x3C, 0x3D, 0x20, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, ++0x6B, 0x65, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x28, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x64, ++0x73, 0x74, 0x2D, 0x3E, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, ++0x6D, 0x73, 0x67, 0x62, 0x75, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x5F, 0x6D, 0x73, 0x67, ++0x5F, 0x62, 0x75, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x69, 0x70, 0x63, 0x5F, 0x65, 0x6D, 0x62, 0x5F, ++0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x66, 0x77, 0x64, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, ++0x6D, 0x73, 0x67, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x73, 0x72, 0x63, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x64, 0x73, ++0x74, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x69, ++0x70, 0x63, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x72, ++0x20, 0x75, 0x73, 0x62, 0x20, 0x69, 0x6E, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x25, 0x64, 0x2C, ++0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x73, 0x72, 0x63, 0x2D, 0x3E, 0x70, 0x61, ++0x72, 0x61, 0x6D, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x73, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x6D, 0x73, ++0x67, 0x2D, 0x3E, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x29, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6D, 0x73, 0x67, ++0x20, 0x63, 0x66, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6E, 0x6F, 0x20, ++0x64, 0x73, 0x63, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x6E, 0x6F, 0x74, 0x69, 0x66, 0x79, 0x3A, ++0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x42, 0x54, 0x20, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x20, 0x68, 0x6F, ++0x73, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x70, 0x6D, 0x69, 0x63, 0x20, 0x67, 0x70, 0x69, 0x6F, 0x0A, 0x00, 0x00, ++0x77, 0x6B, 0x62, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x50, 0x4D, 0x49, 0x43, 0x5F, 0x45, 0x52, 0x52, ++0x49, 0x52, 0x51, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x5F, ++0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x49, 0x50, 0x43, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x43, 0x48, 0x41, 0x4E, 0x4E, 0x45, ++0x4C, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x23, 0x20, 0x3D, 0x25, 0x64, 0x20, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x75, 0x2E, 0x73, 0x74, 0x61, 0x2E, 0x6C, ++0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x3D, 0x3D, ++0x20, 0x31, 0x00, 0x00, 0x73, 0x74, 0x61, 0x2D, 0x3E, 0x6C, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x63, 0x6F, 0x6E, ++0x6E, 0x5F, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x00, 0x00, 0x61, 0x70, 0x6D, 0x20, ++0x73, 0x74, 0x61, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x74, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x72, 0x3A, 0x25, 0x64, 0x2C, 0x20, ++0x72, 0x72, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x31, 0x0A, 0x00, ++0x63, 0x6C, 0x65, 0x61, 0x72, 0x0A, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x0A, 0x00, 0x00, ++0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x74, 0x6D, 0x70, 0x2D, 0x3E, 0x68, 0x6F, 0x73, 0x74, 0x2E, 0x73, 0x74, 0x61, ++0x69, 0x64, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, 0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, ++0x41, 0x58, 0x00, 0x00, 0x73, 0x74, 0x61, 0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x25, 0x64, 0x0A, 0x00, ++0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x74, 0x6D, 0x70, 0x2D, 0x3E, 0x68, 0x6F, 0x73, 0x74, 0x2E, 0x66, 0x6C, 0x61, ++0x67, 0x73, 0x20, 0x26, 0x20, 0x54, 0x58, 0x55, 0x5F, 0x43, 0x4E, 0x54, 0x52, 0x4C, 0x5F, 0x52, 0x45, 0x54, 0x52, 0x59, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xD9, 0x67, 0x12, 0x00, 0xF9, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x70, 0x6F, 0x6F, 0x6C, 0x5F, ++0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, ++0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x74, 0x74, ++0x65, 0x72, 0x6E, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, ++0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x6E, 0x75, 0x6D, 0x5F, ++0x75, 0x73, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, ++0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, ++0x6E, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x20, 0x49, 0x6E, ++0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, ++0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x65, 0x6D, 0x4D, 0x67, 0x72, 0x45, 0x72, 0x72, 0x3A, 0x20, 0x53, ++0x75, 0x62, 0x70, 0x6F, 0x6F, 0x6C, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x53, 0x77, 0x45, 0x72, ++0x3A, 0x4E, 0x6F, 0x53, 0x69, 0x7A, 0x65, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x0D, 0x00, ++0x67, 0x65, 0x74, 0x5F, 0x6E, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x61, 0x64, 0x64, 0x72, ++0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, ++0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x74, 0x74, ++0x65, 0x72, 0x6E, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, ++0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x53, 0x77, 0x45, 0x72, 0x3A, 0x41, 0x6C, 0x6C, ++0x63, 0x45, 0x72, 0x72, 0x50, 0x74, 0x72, 0x6E, 0x20, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, ++0x72, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x74, 0x69, ++0x76, 0x65, 0x5F, 0x70, 0x6F, 0x6F, 0x6C, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, ++0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x64, 0x65, 0x63, 0x72, 0x5F, 0x6E, 0x75, 0x6D, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, ++0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, ++0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, ++0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, ++0x25, 0x78, 0x0A, 0x00, 0x6E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x69, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x32, 0x00, 0x00, ++0x67, 0x65, 0x74, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, ++0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, ++0x72, 0x65, 0x70, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x2C, 0x20, 0x25, 0x64, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x64, 0x65, 0x73, 0x63, 0x0D, 0x0A, 0x00, 0x00, ++0x70, 0x61, 0x72, 0x61, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6E, 0x74, 0x20, ++0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x69, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6E, 0x75, 0x6D, 0x3D, 0x25, 0x64, ++0x2C, 0x20, 0x72, 0x78, 0x64, 0x65, 0x73, 0x63, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x61, 0x63, 0x3E, 0x3D, 0x4E, 0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x20, ++0x2B, 0x20, 0x31, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, 0x65, 0x77, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, ++0x4C, 0x4C, 0x00, 0x00, 0x6D, 0x73, 0x67, 0x20, 0x63, 0x72, 0x63, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x69, 0x6E, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x73, 0x6F, 0x66, 0x74, ++0x77, 0x6B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x61, 0x20, 0x69, 0x6E, 0x74, 0x20, 0x25, 0x78, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x20, 0x73, 0x74, ++0x61, 0x74, 0x75, 0x73, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x68, 0x6F, 0x73, ++0x74, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x61, 0x68, 0x62, 0x32, 0x73, 0x64, 0x69, 0x6F, ++0x20, 0x74, 0x78, 0x20, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x53, 0x44, 0x49, 0x4F, 0x32, 0x41, 0x48, 0x42, ++0x5F, 0x4C, 0x4C, 0x53, 0x54, 0x5F, 0x48, 0x44, 0x52, 0x5F, 0x45, 0x52, 0x52, 0x0D, 0x0A, 0x00, 0x73, 0x64, 0x69, 0x6F, ++0x20, 0x65, 0x72, 0x72, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3D, 0x25, 0x78, 0x2C, 0x30, 0x78, 0x34, 0x35, 0x3D, ++0x25, 0x78, 0x0A, 0x00, 0x6D, 0x73, 0x67, 0x72, 0x78, 0x75, 0x73, 0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, ++0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x63, 0x75, 0x73, 0x65, 0x64, 0x3D, ++0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x74, 0x78, 0x63, 0x6D, ++0x73, 0x67, 0x75, 0x73, 0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6D, 0x73, 0x67, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x61, 0x69, 0x74, 0x20, 0x69, 0x6F, 0x20, 0x65, 0x6E, 0x61, 0x62, ++0x6C, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6F, 0x20, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x0D, 0x0A, 0x00, ++0x65, 0x72, 0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x70, 0x6B, 0x74, 0x21, 0x0D, 0x0A, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x64, 0x73, 0x63, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x6F, 0x70, 0x65, 0x6E, ++0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x55, 0x4C, 0x50, 0x49, 0x20, 0x63, 0x6C, 0x6B, 0x20, 0x64, 0x65, 0x74, ++0x65, 0x63, 0x74, 0x65, 0x64, 0x0D, 0x0A, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x20, 0x6E, 0x6F, 0x20, 0x75, 0x73, 0x62, ++0x20, 0x75, 0x6C, 0x70, 0x69, 0x20, 0x63, 0x6C, 0x6B, 0x0D, 0x0A, 0x00, 0x77, 0x61, 0x69, 0x74, 0x20, 0x63, 0x66, 0x67, ++0x0A, 0x00, 0x00, 0x00, 0x46, 0x49, 0x46, 0x4F, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x3A, 0x20, 0x6F, 0x76, 0x65, 0x72, ++0x66, 0x6C, 0x6F, 0x77, 0x2C, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x69, ++0x7A, 0x65, 0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x20, 0x52, 0x41, 0x4D, 0x20, ++0x69, 0x73, 0x20, 0x25, 0x64, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E, ++0x6D, 0x65, 0x6E, 0x74, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x45, 0x50, 0x30, 0x20, 0x53, 0x45, 0x54, 0x55, ++0x50, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x2C, 0x20, 0x64, 0x69, 0x72, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x00, ++0x45, 0x50, 0x30, 0x20, 0x53, 0x45, 0x54, 0x55, 0x50, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x2C, 0x20, 0x77, 0x4C, 0x65, ++0x6E, 0x67, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6E, 0x6B, 0x6E, ++0x6F, 0x77, 0x6E, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6F, 0x72, 0x3A, 0x20, 0x25, 0x64, 0x00, 0x00, ++0x45, 0x70, 0x30, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x65, 0x72, 0x72, 0x20, ++0x25, 0x75, 0x2D, 0x25, 0x75, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x72, 0x65, 0x62, 0x6F, 0x6F, 0x74, ++0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x65, 0x74, 0x0D, 0x0A, 0x00, 0x65, 0x78, 0x69, 0x74, ++0x0D, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x0A, 0x00, 0x77, 0x61, 0x6B, 0x65, ++0x75, 0x70, 0x20, 0x75, 0x73, 0x62, 0x0A, 0x00, 0x69, 0x72, 0x71, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x77, 0x6C, 0x61, 0x6E, 0x5F, 0x75, 0x73, 0x62, 0x5F, 0x73, 0x75, 0x73, 0x70, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x00, ++0x52, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x64, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, ++0x64, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x6D, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, ++0x64, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x6E, 0x6F, 0x20, 0x72, 0x78, ++0x20, 0x6D, 0x73, 0x67, 0x20, 0x65, 0x6C, 0x65, 0x6D, 0x0D, 0x0A, 0x00, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, ++0x20, 0x25, 0x58, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x65, 0x6E, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, ++0x64, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x72, 0x65, 0x63, 0x76, 0x20, 0x65, 0x72, ++0x72, 0x21, 0x21, 0x21, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x23, 0x65, ++0x72, 0x72, 0x23, 0x23, 0x23, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x6C, 0x61, 0x6E, ++0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6F, 0x70, 0x65, 0x6E, 0x20, 0x72, 0x65, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x21, 0x21, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x64, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x74, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x20, 0x00, ++0x01, 0x01, 0x00, 0xA0, 0xFA, 0x09, 0x04, 0x00, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, ++0x00, 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00, 0x05, 0x0F, 0x0C, 0x00, 0x01, 0x07, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, ++0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x9C, 0xA6, 0x00, 0x88, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00, ++0x0A, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, ++0x0A, 0x03, 0x77, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x10, 0x03, 0x61, 0x00, 0x69, 0x00, 0x63, 0x00, ++0x73, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x12, 0x03, 0x41, 0x00, 0x49, 0x00, 0x43, 0x00, 0x20, 0x00, 0x57, 0x00, ++0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x12, 0x03, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x39, 0x00, 0x30, 0x00, ++0x32, 0x00, 0x32, 0x00, 0x37, 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x75, 0x73, 0x62, 0x5F, 0x77, 0x6C, 0x61, 0x6E, ++0x5F, 0x72, 0x78, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x6E, ++0x69, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, ++0x77, 0x66, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x75, 0x73, 0x62, 0x20, 0x73, 0x74, 0x61, ++0x72, 0x74, 0x20, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x68, 0x6F, 0x73, ++0x74, 0x5F, 0x69, 0x66, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x73, 0x69, 0x7A, ++0x65, 0x00, 0x00, 0x00, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x72, 0x78, 0x3A, 0x20, 0x64, 0x73, 0x63, 0x72, 0x20, 0x75, ++0x73, 0x65, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x23, 0x77, 0x66, 0x3A, 0x25, 0x58, 0x0A, 0x00, ++0x23, 0x77, 0x65, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x64, 0x20, 0x72, 0x78, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x21, 0x20, 0x77, 0x64, 0x20, 0x6E, 0x6F, 0x20, 0x72, 0x78, 0x20, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, ++0x77, 0x64, 0x20, 0x72, 0x78, 0x20, 0x6D, 0x61, 0x78, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, ++0x68, 0x6F, 0x73, 0x74, 0x5F, 0x72, 0x65, 0x61, 0x64, 0x79, 0x0A, 0x00, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x64, 0x61, 0x74, ++0x61, 0x20, 0x72, 0x65, 0x63, 0x76, 0x20, 0x72, 0x65, 0x74, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, ++0x20, 0x6E, 0x6F, 0x20, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x69, 0x70, 0x63, ++0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x69, 0x70, 0x63, 0x20, 0x68, 0x6F, 0x73, ++0x74, 0x20, 0x72, 0x78, 0x3A, 0x20, 0x6E, 0x6F, 0x62, 0x75, 0x66, 0x66, 0x2C, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x3D, ++0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x4D, 0x4D, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x54, 0x4F, 0x5F, 0x4B, 0x45, ++0x59, 0x28, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, 0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x20, ++0x2D, 0x20, 0x31, 0x29, 0x20, 0x3C, 0x3D, 0x20, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x6B, 0x65, ++0x79, 0x5F, 0x6D, 0x61, 0x78, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x00, 0x00, ++0x6C, 0x70, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x61, 0x63, 0x74, 0x73, 0x6C, 0x70, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x69, ++0x6D, 0x65, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x69, 0x64, 0x78, 0x20, 0x21, 0x3D, ++0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x43, 0x54, 0x58, 0x54, 0x5F, 0x55, 0x4E, 0x55, 0x53, 0x45, 0x44, 0x00, 0x00, 0x00, ++0x73, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, ++0x67, 0x3A, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x0D, 0x0A, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, ++0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x6C, 0x61, 0x73, 0x74, 0x20, 0x3C, 0x20, 0x31, 0x30, 0x6D, 0x73, 0x2C, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, ++0x6F, 0x77, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x0D, 0x0A, 0x00, ++0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x0A, 0x43, 0x4F, 0x4E, 0x54, 0x52, 0x4F, 0x4C, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x78, ++0x50, 0x53, 0x52, 0x20, 0x20, 0x20, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x50, 0x53, 0x50, 0x20, 0x20, 0x20, 0x20, 0x3D, ++0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x4D, 0x53, 0x50, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x50, ++0x52, 0x49, 0x4D, 0x41, 0x53, 0x4B, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x4C, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, ++0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x00, 0x0A, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x20, 0x50, 0x53, 0x50, 0x21, 0x00, ++0x0A, 0x44, 0x75, 0x6D, 0x70, 0x4D, 0x53, 0x50, 0x3A, 0x00, 0x00, 0x00, 0x0A, 0x5B, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x3A, ++0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x0A, 0x52, 0x25, 0x2D, 0x34, 0x64, 0x3A, 0x20, ++0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x53, 0x50, 0x20, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x4C, 0x52, 0x20, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x43, 0x20, 0x20, 0x20, 0x3A, 0x20, ++0x25, 0x30, 0x38, 0x58, 0x0A, 0x78, 0x50, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x53, 0x50, ++0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x4D, 0x53, 0x50, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x00, 0x00, 0x00, 0x00, 0x0A, 0x43, 0x50, 0x55, 0x49, 0x44, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x49, 0x43, 0x53, ++0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x56, 0x54, 0x4F, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x41, 0x49, 0x52, 0x43, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x53, 0x48, 0x43, ++0x53, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x43, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x48, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x44, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, ++0x25, 0x30, 0x38, 0x58, 0x0A, 0x41, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, ++0x0A, 0x4D, 0x4D, 0x46, 0x53, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x20, 0x20, 0x49, 0x41, 0x43, 0x43, 0x56, ++0x49, 0x4F, 0x4C, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x44, 0x41, 0x43, 0x43, 0x56, 0x49, 0x4F, 0x4C, 0x20, 0x3A, 0x25, 0x64, ++0x0A, 0x20, 0x20, 0x4D, 0x55, 0x4E, 0x53, 0x54, 0x4B, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x09, 0x4D, 0x53, 0x54, 0x4B, ++0x45, 0x52, 0x52, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x4D, 0x4C, 0x53, 0x50, 0x45, 0x52, 0x52, 0x20, 0x20, ++0x3A, 0x25, 0x64, 0x09, 0x4D, 0x4D, 0x41, 0x52, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x3A, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, ++0x0A, 0x4D, 0x4D, 0x46, 0x41, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x42, 0x46, 0x53, ++0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x20, 0x20, 0x49, 0x42, 0x55, 0x53, 0x45, 0x52, 0x52, 0x20, 0x20, ++0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x0A, 0x20, ++0x20, 0x49, 0x4D, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x09, 0x55, 0x4E, 0x53, 0x54, ++0x4B, 0x45, 0x52, 0x52, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x53, 0x54, 0x4B, 0x45, 0x52, 0x52, 0x20, 0x20, 0x20, ++0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x4C, 0x53, 0x50, 0x45, 0x52, 0x52, 0x20, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, ++0x20, 0x42, 0x46, 0x41, 0x52, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x00, 0x0A, 0x42, 0x46, 0x41, ++0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x55, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, ++0x25, 0x30, 0x34, 0x58, 0x0A, 0x20, 0x20, 0x55, 0x4E, 0x44, 0x45, 0x46, 0x49, 0x4E, 0x53, 0x54, 0x52, 0x3A, 0x25, 0x64, ++0x09, 0x49, 0x4E, 0x56, 0x53, 0x54, 0x41, 0x54, 0x45, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x49, 0x4E, 0x56, 0x50, ++0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x4E, 0x4F, 0x43, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, ++0x25, 0x64, 0x0A, 0x20, 0x20, 0x55, 0x4E, 0x41, 0x4C, 0x49, 0x47, 0x4E, 0x45, 0x44, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x44, ++0x49, 0x56, 0x42, 0x59, 0x5A, 0x45, 0x52, 0x4F, 0x3A, 0x25, 0x64, 0x00, 0x0A, 0x4D, 0x6F, 0x64, 0x65, 0x20, 0x3A, 0x20, ++0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x0A, 0x50, 0x72, 0x69, 0x76, 0x20, 0x3A, 0x20, 0x55, 0x73, 0x65, 0x72, ++0x00, 0x00, 0x00, 0x00, 0x0A, 0x50, 0x72, 0x69, 0x76, 0x20, 0x3A, 0x20, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6C, 0x65, 0x67, ++0x65, 0x64, 0x00, 0x00, 0x0A, 0x4D, 0x6F, 0x64, 0x65, 0x20, 0x3A, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, ++0x0A, 0x53, 0x74, 0x61, 0x63, 0x6B, 0x3A, 0x20, 0x50, 0x53, 0x50, 0x00, 0x0A, 0x53, 0x74, 0x61, 0x63, 0x6B, 0x3A, 0x20, ++0x4D, 0x53, 0x50, 0x00, 0x0A, 0x43, 0x4E, 0x54, 0x52, 0x4C, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x4D, 0x41, ++0x53, 0x4B, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x46, 0x4D, 0x41, 0x53, 0x4B, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x42, 0x41, 0x53, 0x45, 0x50, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x44, 0x75, 0x6D, ++0x70, 0x50, 0x53, 0x50, 0x3A, 0x00, 0x00, 0x00, 0x50, 0x61, 0x6E, 0x69, 0x63, 0x2E, 0x2E, 0x2E, 0x0A, 0x00, 0x00, 0x00, ++0x0A, 0x2B, 0x2B, 0x20, 0x43, 0x4D, 0x34, 0x20, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, ++0x72, 0x20, 0x2B, 0x2B, 0x0A, 0x0A, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x54, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x00, 0x00, 0x00, ++0x4D, 0x65, 0x6D, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x42, 0x75, 0x73, 0x46, ++0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, ++0x48, 0x61, 0x72, 0x64, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, ++0x74, 0x3A, 0x00, 0x00, 0x0A, 0x0A, 0x2D, 0x2D, 0x20, 0x43, 0x4D, 0x34, 0x20, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x48, ++0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x2D, 0x2D, 0x0A, 0x0A, 0x00, 0x9A, 0x25, 0x73, 0x20, 0x2D, 0x20, 0x62, 0x75, ++0x69, 0x6C, 0x64, 0x3A, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x25, ++0x64, 0x2C, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x64, 0x6F, 0x6E, 0x65, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x64, 0x2C, 0x00, 0x00, 0x74, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x6E, 0x6F, 0x74, 0x20, ++0x70, 0x61, 0x73, 0x74, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x70, 0x61, 0x73, 0x73, ++0x3A, 0x20, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, ++0x68, 0x77, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x2D, 0x3E, ++0x74, 0x69, 0x6D, 0x65, 0x20, 0x2D, 0x20, 0x67, 0x5F, 0x77, 0x69, 0x66, 0x69, 0x5F, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6E, ++0x67, 0x73, 0x2E, 0x70, 0x77, 0x72, 0x5F, 0x6F, 0x70, 0x65, 0x6E, 0x5F, 0x73, 0x79, 0x73, 0x64, 0x65, 0x6C, 0x61, 0x79, ++0x29, 0x00, 0x00, 0x00, 0x73, 0x6C, 0x70, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x62, 0x74, 0x0A, 0x00, ++0x6C, 0x70, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x69, 0x67, 0x6E, 0x6F, 0x72, 0x65, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, ++0x77, 0x2C, 0x20, 0x00, 0x72, 0x77, 0x6E, 0x78, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x70, 0x72, 0x65, 0x76, 0x5F, 0x68, 0x77, ++0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, ++0x65, 0x6E, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x00, 0x00, 0x00, 0x00, ++0x77, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x77, 0x6E, 0x78, 0x6C, 0x5F, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5F, ++0x65, 0x76, 0x74, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5B, 0x30, 0x5D, 0x20, ++0x26, 0x26, 0x20, 0x74, 0x78, 0x5F, 0x68, 0x77, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5B, ++0x30, 0x5D, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, ++0x74, 0x78, 0x6C, 0x20, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x6C, 0x65, 0x6E, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x74, 0x78, 0x6C, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, ++0x63, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x74, 0x68, 0x64, 0x2D, 0x3E, 0x66, 0x69, 0x72, ++0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x00, 0x00, 0x6E, 0x65, 0x78, 0x74, 0x64, 0x65, 0x73, 0x63, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, ++0x2D, 0x3E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x41, 0x47, 0x47, 0x5F, 0x42, 0x41, 0x5F, 0x52, 0x45, ++0x43, 0x45, 0x49, 0x56, 0x45, 0x44, 0x00, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x62, 0x63, 0x6E, ++0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x00, ++0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x33, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, ++0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, ++0x5F, 0x61, 0x63, 0x5F, 0x32, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, ++0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x31, 0x5F, 0x73, 0x74, ++0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, ++0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x30, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, ++0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x68, 0x69, 0x5F, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x00, 0x00, ++0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5F, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6F, 0x72, 0x79, 0x20, 0x3C, 0x20, 0x28, 0x4E, ++0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x2B, 0x32, 0x29, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, ++0x21, 0x21, 0x20, 0x74, 0x78, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, ++0x20, 0x66, 0x6F, 0x72, 0x20, 0x75, 0x73, 0x62, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x66, 0x6D, 0x20, 0x66, 0x6C, 0x75, 0x73, ++0x68, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x73, 0x6E, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x63, 0x66, 0x6D, 0x73, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x73, 0x6E, 0x3D, 0x25, 0x64, 0x2C, ++0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x79, 0x5F, 0x69, 0x64, 0x78, 0x5F, ++0x68, 0x77, 0x20, 0x3E, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x53, 0x45, 0x43, 0x5F, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4C, 0x54, ++0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x4F, 0x55, 0x4E, 0x54, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x65, 0x76, 0x74, 0x5F, 0x67, ++0x65, 0x74, 0x28, 0x29, 0x20, 0x26, 0x20, 0x65, 0x76, 0x74, 0x5F, 0x62, 0x69, 0x74, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, ++0x73, 0x63, 0x5F, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, ++0x62, 0x75, 0x67, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x74, 0x61, 0x69, 0x6C, 0x20, 0x65, 0x72, ++0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, ++0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x28, 0x74, 0x68, 0x64, 0x2D, 0x3E, 0x64, 0x61, ++0x74, 0x61, 0x73, 0x74, 0x61, 0x72, 0x74, 0x70, 0x74, 0x72, 0x20, 0x26, 0x20, 0x30, 0x78, 0x30, 0x31, 0x29, 0x20, 0x3D, ++0x3D, 0x20, 0x30, 0x00, 0x62, 0x61, 0x6E, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x50, 0x48, 0x59, 0x5F, 0x42, 0x41, 0x4E, 0x44, ++0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, ++0x6F, 0x72, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x6E, 0x6F, 0x20, 0x70, 0x72, 0x6F, 0x62, 0x65, 0x20, 0x62, 0x75, 0x66, ++0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, ++0x4C, 0x4C, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, 0x65, 0x77, 0x20, 0x21, 0x3D, 0x20, ++0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x70, 0x69, 0x63, 0x6B, ++0x28, 0x26, 0x74, 0x78, 0x6C, 0x69, 0x73, 0x74, 0x2D, 0x3E, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, ++0x29, 0x20, 0x3D, 0x3D, 0x20, 0x26, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6F, 0x6C, 0x64, 0x2D, 0x3E, ++0x6C, 0x69, 0x73, 0x74, 0x5F, 0x68, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, ++0x6F, 0x64, 0x20, 0x3E, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, 0x4F, 0x4E, 0x5F, 0x48, ++0x54, 0x5F, 0x44, 0x55, 0x50, 0x5F, 0x4F, 0x46, 0x44, 0x4D, 0x00, 0x00, 0x28, 0x2A, 0x6E, 0x73, 0x73, 0x20, 0x3E, 0x20, ++0x30, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x2A, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x34, 0x29, 0x00, 0x00, 0x00, ++0x6D, 0x63, 0x73, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x39, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x63, 0x73, 0x5F, ++0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x33, 0x31, 0x00, 0x00, 0x00, 0x69, 0x73, 0x5F, 0x6D, 0x70, 0x64, 0x75, 0x5F, ++0x66, 0x69, 0x72, 0x73, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x29, 0x00, 0x00, 0x00, 0x21, 0x69, 0x73, 0x5F, ++0x6D, 0x70, 0x64, 0x75, 0x5F, 0x6C, 0x61, 0x73, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x29, 0x00, 0x00, 0x00, ++0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x70, 0x72, 0x65, 0x76, 0x20, 0x3D, 0x3D, 0x20, 0x61, 0x67, 0x67, 0x5F, 0x64, ++0x65, 0x73, 0x63, 0x5F, 0x6F, 0x6C, 0x64, 0x2D, 0x3E, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6C, 0x61, 0x73, 0x74, ++0x00, 0x00, 0x00, 0x00, 0x61, 0x5F, 0x74, 0x68, 0x64, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x52, ++0x45, 0x54, 0x52, 0x59, 0x5F, 0x4C, 0x49, 0x4D, 0x49, 0x54, 0x5F, 0x52, 0x45, 0x41, 0x43, 0x48, 0x45, 0x44, 0x5F, 0x42, ++0x49, 0x54, 0x00, 0x00, 0x1A, 0x00, 0x1C, 0x00, 0x36, 0x00, 0x3C, 0x00, 0x75, 0x00, 0x82, 0x00, 0xEA, 0x00, 0x04, 0x01, ++0x34, 0x00, 0x39, 0x00, 0x6C, 0x00, 0x78, 0x00, 0xEA, 0x00, 0x04, 0x01, 0xD4, 0x01, 0x08, 0x02, 0x4E, 0x00, 0x56, 0x00, ++0xA2, 0x00, 0xB4, 0x00, 0x5F, 0x01, 0x86, 0x01, 0xBE, 0x02, 0x0C, 0x03, 0x68, 0x00, 0x73, 0x00, 0xD8, 0x00, 0xF0, 0x00, ++0xD4, 0x01, 0x08, 0x02, 0xA8, 0x03, 0x10, 0x04, 0x9C, 0x00, 0xAD, 0x00, 0x44, 0x01, 0x68, 0x01, 0xBE, 0x02, 0x0C, 0x03, ++0x7C, 0x05, 0x18, 0x06, 0xD0, 0x00, 0xE7, 0x00, 0xB0, 0x01, 0xE0, 0x01, 0xA8, 0x03, 0x10, 0x04, 0x50, 0x07, 0x20, 0x08, ++0xEA, 0x00, 0x04, 0x01, 0xE6, 0x01, 0x1C, 0x02, 0x1D, 0x04, 0x92, 0x04, 0x3A, 0x08, 0x24, 0x09, 0x04, 0x01, 0x20, 0x01, ++0x1C, 0x02, 0x58, 0x02, 0x92, 0x04, 0x14, 0x05, 0x24, 0x09, 0x28, 0x0A, 0x38, 0x01, 0x5A, 0x01, 0x88, 0x02, 0xD0, 0x02, ++0x7C, 0x05, 0x18, 0x06, 0xF8, 0x0A, 0x30, 0x0C, 0x5A, 0x01, 0x81, 0x01, 0xD0, 0x02, 0x20, 0x03, 0x18, 0x06, 0xC5, 0x06, ++0x30, 0x0C, 0x8A, 0x0D, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x08, 0x09, 0x02, 0x02, 0x04, 0x04, 0x08, 0x09, 0x0F, 0x11, ++0x03, 0x03, 0x06, 0x06, 0x0B, 0x0D, 0x16, 0x19, 0x04, 0x04, 0x07, 0x08, 0x0F, 0x11, 0x1E, 0x21, 0x05, 0x06, 0x0B, 0x0C, ++0x16, 0x19, 0x2C, 0x31, 0x07, 0x08, 0x0E, 0x0F, 0x1E, 0x21, 0x3B, 0x41, 0x08, 0x09, 0x10, 0x11, 0x21, 0x25, 0x42, 0x4A, ++0x09, 0x0A, 0x11, 0x13, 0x25, 0x29, 0x4A, 0x52, 0x0A, 0x0B, 0x15, 0x17, 0x2C, 0x31, 0x58, 0x62, 0x0B, 0x0D, 0x17, 0x19, ++0x31, 0x37, 0x62, 0x6D, 0x74, 0x78, 0x6C, 0x5F, 0x68, 0x65, 0x5F, 0x65, 0x64, 0x63, 0x61, 0x5F, 0x71, 0x75, 0x65, 0x75, ++0x65, 0x5F, 0x68, 0x61, 0x6C, 0x74, 0x65, 0x64, 0x28, 0x61, 0x63, 0x29, 0x00, 0x00, 0x00, 0x00, 0x68, 0x64, 0x72, 0x64, ++0x65, 0x73, 0x63, 0x2D, 0x3E, 0x66, 0x72, 0x6D, 0x6C, 0x65, 0x6E, 0x20, 0x3E, 0x3D, 0x20, 0x48, 0x45, 0x5F, 0x54, 0x52, ++0x49, 0x47, 0x5F, 0x46, 0x52, 0x4D, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, ++0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, ++0x48, 0x45, 0x5F, 0x53, 0x55, 0x00, 0x00, 0x00, 0x6D, 0x63, 0x73, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x31, ++0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, ++0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x07, 0x00, ++0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, ++0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, ++0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, ++0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, ++0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, ++0x22, 0x00, 0x20, 0x00, 0x1D, 0x00, 0x90, 0x00, 0x88, 0x00, 0x7A, 0x00, 0x44, 0x00, 0x41, 0x00, 0x3A, 0x00, 0x20, 0x01, ++0x10, 0x01, 0xF5, 0x00, 0x67, 0x00, 0x61, 0x00, 0x57, 0x00, 0xB0, 0x01, 0x98, 0x01, 0x6F, 0x01, 0x89, 0x00, 0x82, 0x00, ++0x75, 0x00, 0x40, 0x02, 0x20, 0x02, 0xEA, 0x01, 0xCE, 0x00, 0xC3, 0x00, 0xAF, 0x00, 0x60, 0x03, 0x30, 0x03, 0xDF, 0x02, ++0x13, 0x01, 0x04, 0x01, 0xEA, 0x00, 0x80, 0x04, 0x40, 0x04, 0xD4, 0x03, 0x35, 0x01, 0x24, 0x01, 0x07, 0x01, 0x11, 0x05, ++0xC9, 0x04, 0x4E, 0x04, 0x58, 0x01, 0x45, 0x01, 0x24, 0x01, 0xA1, 0x05, 0x51, 0x05, 0xC9, 0x04, 0x9C, 0x01, 0x86, 0x01, ++0x5F, 0x01, 0xC1, 0x06, 0x61, 0x06, 0xBE, 0x05, 0xCA, 0x01, 0xB1, 0x01, 0x86, 0x01, 0x81, 0x07, 0x16, 0x07, 0x61, 0x06, ++0x04, 0x02, 0xE7, 0x01, 0xB6, 0x01, 0x71, 0x08, 0xF9, 0x07, 0x2D, 0x07, 0x3D, 0x02, 0x1D, 0x02, 0xE7, 0x01, 0x61, 0x09, ++0xDC, 0x08, 0xF9, 0x07, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, ++0x02, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x0D, 0x00, 0x0C, 0x00, ++0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x13, 0x00, 0x12, 0x00, 0x10, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x1C, 0x00, ++0x1A, 0x00, 0x17, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x25, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x0A, 0x00, 0x0A, 0x00, ++0x09, 0x00, 0x29, 0x00, 0x27, 0x00, 0x23, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x2E, 0x00, 0x2B, 0x00, 0x27, 0x00, ++0x0D, 0x00, 0x0D, 0x00, 0x0B, 0x00, 0x37, 0x00, 0x34, 0x00, 0x2E, 0x00, 0x0F, 0x00, 0x0E, 0x00, 0x0D, 0x00, 0x3D, 0x00, ++0x39, 0x00, 0x34, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x44, 0x00, 0x40, 0x00, 0x3A, 0x00, 0x12, 0x00, 0x11, 0x00, ++0x10, 0x00, 0x4C, 0x00, 0x47, 0x00, 0x40, 0x00, 0x08, 0x10, 0x20, 0x04, 0x50, 0x94, 0x15, 0x00, 0x98, 0x94, 0x15, 0x00, ++0x08, 0x94, 0x15, 0x00, 0x72, 0x68, 0x64, 0x2D, 0x3E, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, ++0x74, 0x72, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x6E, 0x6F, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, ++0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x72, 0x78, 0x62, 0x75, 0x66, 0x31, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, ++0x25, 0x30, 0x38, 0x78, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x65, 0x6E, ++0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x77, ++0x72, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x64, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, ++0x78, 0x0D, 0x0A, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x72, 0x65, 0x63, 0x6F, ++0x76, 0x65, 0x72, 0x79, 0x0D, 0x0A, 0x00, 0x00, 0x70, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, ++0x70, 0x64, 0x2D, 0x3E, 0x70, 0x62, 0x64, 0x2E, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x61, 0x72, 0x74, 0x70, 0x74, 0x72, ++0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x61, 0x5F, 0x68, 0x64, 0x72, 0x64, 0x65, 0x73, 0x63, 0x2D, ++0x3E, 0x68, 0x64, 0x2E, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x20, 0x3D, 0x3D, ++0x20, 0x30, 0x00, 0x00, 0x70, 0x62, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x72, 0x78, 0x6C, 0x20, ++0x65, 0x72, 0x72, 0x2C, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x6E, 0x6F, 0x20, 0x74, ++0x78, 0x5F, 0x64, 0x73, 0x63, 0x72, 0x5F, 0x68, 0x64, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x20, 0x74, ++0x78, 0x5F, 0x64, 0x73, 0x63, 0x72, 0x5F, 0x68, 0x64, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6D, 0x70, 0x64, 0x75, ++0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x6D, 0x70, 0x64, 0x75, 0x5F, 0x6C, 0x65, 0x6E, ++0x20, 0x3C, 0x3D, 0x20, 0x52, 0x57, 0x4E, 0x58, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x41, 0x4D, 0x53, 0x44, 0x55, 0x5F, 0x52, ++0x58, 0x00, 0x00, 0x00, 0x72, 0x68, 0x64, 0x2D, 0x3E, 0x75, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6E, 0x72, 0x78, 0x20, ++0x3D, 0x3D, 0x20, 0x52, 0x58, 0x5F, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5F, 0x44, 0x45, 0x53, 0x43, 0x5F, 0x50, 0x41, ++0x54, 0x54, 0x45, 0x52, 0x4E, 0x00, 0x00, 0x00, 0x72, 0x78, 0x62, 0x75, 0x66, 0x32, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, ++0x25, 0x30, 0x38, 0x78, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x65, 0x6E, ++0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x77, ++0x72, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x64, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, ++0x78, 0x0D, 0x0A, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, ++0x73, 0x74, 0x61, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, ++0x73, 0x74, 0x61, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, ++0x6D, 0x61, 0x63, 0x20, 0x69, 0x73, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x70, 0x32, 0x70, 0x3D, 0x25, ++0x64, 0x0D, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x20, 0x6D, 0x61, 0x63, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x20, 0x6D, ++0x61, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x70, 0x32, 0x70, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x21, 0x3D, 0x20, 0x50, 0x32, ++0x50, 0x5F, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x25, ++0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x76, 0x69, 0x66, 0x20, ++0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x20, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6D, 0x67, 0x6D, 0x74, 0x3A, ++0x25, 0x64, 0x0A, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, ++0x73, 0x6C, 0x65, 0x65, 0x70, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, 0x6C, 0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x6F, 0x6E, 0x5F, 0x61, 0x69, 0x72, 0x5F, 0x76, 0x61, ++0x6C, 0x69, 0x64, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x64, 0x74, 0x69, 0x6D, ++0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x2A, 0x28, 0x76, 0x6F, ++0x6C, 0x61, 0x74, 0x69, 0x6C, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x5F, 0x74, 0x20, 0x2A, 0x29, 0x26, 0x67, 0x5F, ++0x61, 0x6F, 0x6E, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2E, 0x64, 0x74, 0x69, 0x6D, 0x5F, 0x63, 0x6E, 0x74, 0x5F, ++0x61, 0x6F, 0x6E, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x3C, 0x20, 0x2A, 0x28, 0x76, 0x6F, 0x6C, 0x61, 0x74, 0x69, ++0x6C, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x5F, 0x74, 0x20, 0x2A, 0x29, 0x26, 0x67, 0x5F, 0x61, 0x6F, 0x6E, 0x5F, ++0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2E, 0x64, 0x74, 0x69, 0x6D, 0x5F, 0x70, 0x65, 0x72, 0x69, 0x6F, 0x64, 0x5F, 0x61, ++0x6F, 0x6E, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x6E, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, ++0x6C, 0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x4C, 0x2C, 0x00, 0x00, 0x9B, 0x84, 0x4B, 0x65, 0x79, 0x69, 0x64, 0x78, ++0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x2C, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x00, 0x00, 0x9B, 0x84, 0x49, 0x6E, ++0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x6B, 0x65, 0x79, 0x69, 0x64, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x9B, 0x84, 0x49, 0x6E, ++0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x53, 0x54, 0x41, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x5F, ++0x73, 0x74, 0x61, 0x20, 0x3D, 0x3D, 0x20, 0x76, 0x69, 0x66, 0x00, 0x00, 0x54, 0x3D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x42, 0x43, 0x4E, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x6E, 0x20, ++0x64, 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x66, 0x63, 0x73, 0x20, ++0x6F, 0x6B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x66, 0x63, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x6F, 0x6B, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x69, 0x64, 0x6C, 0x65, ++0x20, 0x69, 0x6E, 0x74, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x65, 0x76, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4D, ++0x4D, 0x5F, 0x54, 0x42, 0x54, 0x54, 0x5F, 0x45, 0x56, 0x54, 0x5F, 0x4D, 0x41, 0x53, 0x4B, 0x00, 0x61, 0x64, 0x64, 0x20, ++0x67, 0x74, 0x6B, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x20, ++0x3C, 0x20, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x20, 0x70, 0x74, 0x6B, 0x3A, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x48, 0x4F, 0x53, 0x54, ++0x5F, 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, ++0x4E, 0x4F, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x00, 0x66, 0x6F, 0x72, 0x63, 0x65, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x72, ++0x65, 0x71, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x63, 0x65, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x65, ++0x78, 0x69, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, ++0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x48, 0x4F, 0x53, ++0x54, 0x5F, 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, ++0x20, 0x4D, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x6B, ++0x65, 0x79, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4C, 0x54, ++0x5F, 0x4D, 0x46, 0x50, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x4F, 0x55, 0x4E, 0x54, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, ++0x6D, 0x2D, 0x3E, 0x6B, 0x65, 0x79, 0x2E, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x3C, 0x3D, 0x20, 0x4D, 0x41, 0x43, ++0x5F, 0x53, 0x45, 0x43, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, ++0x6D, 0x2D, 0x3E, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5F, 0x73, 0x75, 0x69, 0x74, 0x65, 0x20, 0x3C, 0x3D, 0x20, 0x4D, ++0x41, 0x43, 0x5F, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x50, 0x5F, 0x43, 0x4D, 0x41, 0x43, 0x5F, 0x31, ++0x32, 0x38, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x68, 0x77, 0x5F, 0x6B, 0x65, 0x79, 0x5F, 0x69, 0x64, ++0x78, 0x20, 0x3C, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x53, 0x45, 0x43, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x4D, 0x46, 0x50, 0x5F, ++0x4B, 0x45, 0x59, 0x5F, 0x4E, 0x42, 0x52, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, ++0x20, 0x56, 0x49, 0x46, 0x5F, 0x53, 0x54, 0x41, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, ++0x49, 0x44, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x6D, 0x75, 0x20, 0x65, 0x64, 0x63, 0x61, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x44, 0x48, 0x43, 0x50, 0x65, 0x64, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x78, 0x2E, 0x0D, 0x0A, 0x00, ++0x73, 0x65, 0x74, 0x20, 0x61, 0x67, 0x67, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x25, 0x64, 0x2C, 0x20, ++0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x72, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x20, ++0x6D, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x73, 0x65, 0x74, 0x20, 0x74, 0x78, 0x6F, 0x70, 0x20, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x62, 0x6B, 0x3A, 0x25, 0x78, 0x2C, ++0x20, 0x62, 0x65, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x76, 0x69, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x76, 0x6F, 0x3A, 0x25, 0x78, ++0x2C, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x6E, 0x61, 0x76, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x63, 0x66, 0x65, 0x3D, 0x25, 0x64, ++0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x20, 0x74, 0x72, 0x78, 0x3A, 0x20, ++0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, ++0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x73, ++0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x73, 0x74, 0x6F, 0x70, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x69, 0x73, 0x20, 0x35, 0x67, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x77, 0x5F, 0x65, 0x6E, 0x3D, ++0x25, 0x64, 0x2C, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x5F, 0x69, 0x6E, 0x66, 0x6F, 0x3D, 0x30, 0x78, 0x25, 0x78, ++0x0D, 0x0A, 0x00, 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, 0x20, 0x65, 0x66, ++0x75, 0x73, 0x65, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x61, 0x70, ++0x3A, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x61, 0x70, 0x5F, 0x66, 0x69, 0x6E, ++0x65, 0x3A, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, ++0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, ++0x5F, 0x66, 0x69, 0x6E, 0x65, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x32, 0x2E, 0x34, 0x67, 0x3A, 0x62, 0x65, 0x66, ++0x6F, 0x72, 0x65, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, ++0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x32, 0x2E, 0x34, 0x67, 0x3A, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x20, ++0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x35, 0x67, 0x3A, 0x62, 0x65, 0x66, 0x6F, 0x72, 0x65, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, ++0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x35, 0x67, 0x3A, 0x61, ++0x66, 0x74, 0x65, 0x72, 0x20, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, ++0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, ++0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x48, 0x57, ++0x5F, 0x49, 0x44, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x4E, 0x4F, 0x5F, 0x49, ++0x44, 0x4C, 0x45, 0x00, 0x76, 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, ++0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x68, 0x65, 0x20, 0x65, ++0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x74, ++0x65, 0x20, 0x69, 0x6E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0xA8, 0x1F, 0x17, 0x00, 0x35, 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, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x74, 0x3A, 0x20, ++0x63, 0x62, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x63, 0x75, 0x72, 0x72, ++0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, 0x68, 0x77, 0x5F, 0x74, ++0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x29, 0x00, 0x74, 0x69, 0x6D, 0x65, ++0x72, 0x2D, 0x3E, 0x63, 0x62, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x20, 0x70, 0x72, 0x6F, 0x62, ++0x65, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x20, ++0x70, 0x72, 0x6F, 0x62, 0x65, 0x20, 0x73, 0x75, 0x63, 0x63, 0x0A, 0x00, 0x6D, 0x6D, 0x5F, 0x62, 0x63, 0x6E, 0x5F, 0x65, ++0x6E, 0x76, 0x2E, 0x74, 0x78, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x6C, ++0x6C, 0x65, 0x20, 0x6E, 0x65, 0x76, 0x65, 0x72, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x61, 0x70, 0x6D, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6E, 0x75, 0x6C, 0x6C, 0x20, 0x74, 0x6F, 0x20, 0x70, 0x72, 0x6F, ++0x62, 0x65, 0x20, 0x73, 0x74, 0x61, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, ++0x21, 0x6D, 0x6D, 0x5F, 0x62, 0x63, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x74, 0x78, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, ++0x61, 0x70, 0x6D, 0x5F, 0x70, 0x72, 0x6F, 0x62, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, ++0x28, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, ++0x74, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3D, ++0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x29, 0x20, 0x7C, ++0x7C, 0x20, 0x28, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, ++0x74, 0x78, 0x74, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, ++0x20, 0x3D, 0x3D, 0x20, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x69, 0x6E, 0x64, 0x65, 0x78, ++0x29, 0x00, 0x00, 0x00, 0x6F, 0x74, 0x68, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x62, 0x5F, 0x76, ++0x69, 0x66, 0x5F, 0x6F, 0x74, 0x68, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3E, 0x20, 0x31, 0x00, 0x6E, 0x6F, 0x61, 0x5F, ++0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x50, 0x32, 0x50, 0x5F, 0x4E, 0x4F, 0x41, 0x5F, 0x4E, 0x42, 0x5F, 0x4D, 0x41, 0x58, ++0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x20, 0x33, 0x32, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x74, 0x62, 0x74, 0x74, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2E, 0x70, 0x32, 0x70, ++0x5F, 0x6E, 0x6F, 0x61, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3D, 0x3D, 0x20, 0x49, 0x4E, ++0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, 0x00, 0x63, 0x68, 0x5F, 0x73, ++0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x52, ++0x4F, 0x43, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x50, 0x45, 0x4E, 0x44, 0x49, 0x4E, 0x47, 0x5F, 0x4D, 0x41, 0x53, 0x4B, ++0x00, 0x00, 0x00, 0x00, 0x28, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, ++0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, 0x54, 0x28, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x45, 0x4E, 0x56, 0x5F, 0x52, ++0x4F, 0x43, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x28, 0x63, 0x68, 0x61, ++0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, ++0x54, 0x28, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x45, 0x4E, 0x56, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x42, 0x49, 0x54, 0x29, ++0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x28, 0x76, 0x6F, 0x69, 0x64, 0x20, 0x2A, 0x29, 0x63, 0x68, 0x5F, 0x73, ++0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6E, 0x76, 0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, ++0x4E, 0x6F, 0x20, 0x63, 0x74, 0x78, 0x74, 0x20, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x64, 0x20, 0x70, 0x72, ++0x65, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x69, 0x64, ++0x78, 0x20, 0x3D, 0x3D, 0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x43, 0x54, 0x58, 0x54, 0x5F, 0x55, 0x4E, 0x55, 0x53, 0x45, ++0x44, 0x00, 0x00, 0x00, 0x72, 0x6F, 0x63, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x64, 0x75, 0x72, 0x3D, 0x25, 0x64, 0x2C, ++0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x6E, 0x62, ++0x5F, 0x6C, 0x69, 0x6E, 0x6B, 0x65, 0x64, 0x5F, 0x76, 0x69, 0x66, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x55, ++0x4C, 0x4C, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x6E, 0x62, 0x5F, 0x73, 0x63, 0x68, 0x65, ++0x64, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3C, 0x3D, 0x20, 0x32, 0x00, 0x63, 0x68, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, ++0x68, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x6C, 0x69, 0x6E, 0x6B, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x63, 0x74, 0x78, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, ++0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x6C, 0x69, 0x6E, 0x6B, 0x3A, 0x20, 0x25, 0x64, 0x2C, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x6E, 0x62, 0x5F, 0x73, 0x63, 0x68, 0x65, 0x64, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3C, ++0x3D, 0x20, 0x31, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x70, 0x73, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, 0x6C, ++0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x70, 0x73, 0x5F, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x64, ++0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x75, 0x70, 0x6D, 0x5F, 0x65, ++0x6E, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x75, 0x70, 0x6D, 0x5F, 0x65, 0x78, 0x69, 0x74, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, ++0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x6F, 0x61, 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x20, 0x3C, 0x20, 0x50, 0x32, 0x50, 0x5F, ++0x4E, 0x4F, 0x41, 0x5F, 0x4E, 0x42, 0x5F, 0x4D, 0x41, 0x58, 0x29, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, ++0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x50, 0x32, 0x50, 0x5F, 0x56, 0x49, 0x46, 0x5F, ++0x4D, 0x41, 0x58, 0x00, 0x74, 0x64, 0x73, 0x5F, 0x65, 0x6E, 0x76, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, ++0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x6E, 0x74, 0x20, 0x3E, 0x20, 0x30, 0x00, ++0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x43, ++0x41, 0x4E, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x57, 0x41, 0x49, 0x54, 0x5F, 0x43, 0x48, 0x41, ++0x4E, 0x4E, 0x45, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, ++0x57, 0x41, 0x49, 0x54, 0x5F, 0x42, 0x45, 0x41, 0x43, 0x4F, 0x4E, 0x5F, 0x50, 0x52, 0x4F, 0x42, 0x45, 0x5F, 0x52, 0x53, ++0x50, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5F, 0x72, 0x65, 0x71, 0x5F, 0x68, ++0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x5F, ++0x72, 0x65, 0x71, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x50, 0x21, 0x17, 0x00, 0x04, 0x00, 0x00, 0x00, ++0x73, 0x63, 0x61, 0x6E, 0x5F, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x5F, 0x63, 0x66, 0x6D, ++0x00, 0x00, 0x00, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x5F, 0x73, 0x74, ++0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x49, 0x44, 0x4C, ++0x45, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x61, 0x6F, 0x6E, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, 0x74, 0x69, ++0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x2D, 0x3E, 0x74, 0x69, 0x6D, 0x65, 0x20, ++0x2B, 0x20, 0x35, 0x30, 0x30, 0x30, 0x29, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, ++0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x6B, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x67, ++0x65, 0x6E, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x79, 0x6D, 0x6F, 0x72, 0x65, 0x0D, 0x0A, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x6D, ++0x6D, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x67, 0x65, 0x6E, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, ++0x20, 0x61, 0x6E, 0x79, 0x6D, 0x6F, 0x72, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x30, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x31, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x32, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x33, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x5F, 0x54, ++0x49, 0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x48, 0x45, 0x5F, 0x54, 0x42, 0x5F, ++0x54, 0x49, 0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x48, 0x49, 0x51, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x5F, 0x46, 0x49, 0x46, 0x4F, 0x5F, ++0x4F, 0x56, 0x45, 0x52, 0x5F, 0x46, 0x4C, 0x4F, 0x57, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x2C, 0x20, 0x68, 0x77, ++0x20, 0x72, 0x65, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6C, 0x66, 0x0D, 0x0A, 0x00, 0x00, ++0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, ++0x58, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x48, 0x59, 0x5F, 0x45, 0x52, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, ++0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, ++0x58, 0x4D, 0x41, 0x43, 0x5F, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x48, 0x59, 0x49, 0x46, 0x5F, 0x55, 0x4E, 0x44, 0x45, 0x52, ++0x5F, 0x52, 0x55, 0x4E, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, ++0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x4D, 0x41, 0x43, ++0x5F, 0x50, 0x48, 0x59, 0x49, 0x46, 0x5F, 0x4F, 0x56, 0x45, 0x52, 0x46, 0x4C, 0x4F, 0x57, 0x5F, 0x42, 0x49, 0x54, 0x29, ++0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, ++0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x54, 0x5F, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x5F, 0x42, 0x49, ++0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, ++0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x30, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, ++0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, ++0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, ++0x31, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, ++0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, ++0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x32, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, ++0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, ++0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x33, 0x5F, 0x54, 0x58, ++0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, ++0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, ++0x5F, 0x42, 0x43, 0x4E, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, ++0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, ++0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x58, 0x5F, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5F, 0x44, ++0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, ++0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, ++0x5F, 0x52, 0x58, 0x5F, 0x50, 0x41, 0x59, 0x4C, 0x4F, 0x41, 0x44, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, ++0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, ++0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x57, 0x5F, 0x45, 0x52, 0x52, 0x5F, ++0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, ++0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x49, 0x5F, 0x54, 0x58, 0x5F, 0x44, ++0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, ++0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x08, 0x06, 0x04, 0x0B, 0x09, 0x07, 0x05, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, 0x8D, 0xF6, ++0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, ++0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, ++0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, ++0xAE, 0x3D, 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, 0x08, 0xF9, ++0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, ++0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, ++0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, ++0x61, 0xB7, 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, 0x2C, 0xC1, ++0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, ++0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, ++0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, ++0xC0, 0x80, 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, 0x63, 0x42, ++0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, ++0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, ++0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, ++0xD3, 0x6B, 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, 0x1E, 0x14, ++0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, ++0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, ++0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, ++0x6F, 0x4A, 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, 0x21, 0x3E, ++0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, ++0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, ++0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, ++0x92, 0x15, 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, 0x17, 0x1A, ++0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, ++0xD6, 0x6D, 0x3A, 0x2C, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x20, 0x3E, 0x20, 0x30, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6C, 0x61, ++0x79, 0x20, 0x3C, 0x20, 0x4B, 0x45, 0x5F, 0x54, 0x49, 0x4D, 0x45, 0x52, 0x5F, 0x44, 0x45, 0x4C, 0x41, 0x59, 0x5F, 0x4D, ++0x41, 0x58, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0x21, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x7C, ++0x7C, 0x20, 0x21, 0x6B, 0x65, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x66, 0x69, 0x72, 0x73, ++0x74, 0x2D, 0x3E, 0x74, 0x69, 0x6D, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x73, 0x67, 0x20, 0x21, 0x3D, 0x20, 0x4E, ++0x55, 0x4C, 0x4C, 0x00, 0x9D, 0x80, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x73, ++0x67, 0x3A, 0x25, 0x78, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x20, 0x74, 0x6F, 0x20, ++0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x73, 0x69, 0x7A, 0x65, 0x20, 0x3E, 0x3D, ++0x20, 0x73, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6D, 0x62, 0x6C, 0x6F, 0x63, ++0x6B, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x29, 0x00, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, ++0x4C, 0x00, 0x00, 0x00, 0x28, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x5F, 0x74, 0x29, 0x6D, 0x65, 0x6D, 0x5F, 0x70, 0x74, ++0x72, 0x20, 0x3E, 0x20, 0x28, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x5F, 0x74, 0x29, 0x6E, 0x6F, 0x64, 0x65, 0x00, 0x00, ++0x70, 0x72, 0x65, 0x76, 0x5F, 0x6E, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x2D, 0x3E, 0x6D, 0x73, 0x67, 0x5F, 0x74, ++0x61, 0x62, 0x6C, 0x65, 0x5B, 0x69, 0x5D, 0x2E, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, ++0x20, 0x3C, 0x20, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x6B, 0x65, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x5F, ++0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x28, 0x74, 0x79, 0x70, 0x65, 0x29, 0x00, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x54, 0x41, ++0x53, 0x4B, 0x5F, 0x44, 0x45, 0x53, 0x43, 0x5B, 0x74, 0x79, 0x70, 0x65, 0x5D, 0x2E, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, ++0x78, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x69, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x00, 0x00, ++0x80, 0x9D, 0x73, 0x65, 0x74, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x9A, 0x80, 0x4E, 0x6F, 0x20, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x66, ++0x6F, 0x72, 0x20, 0x6D, 0x73, 0x67, 0x3A, 0x25, 0x78, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, ++0x78, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x24, 0x9F, 0x15, 0x00, ++0x1C, 0x9F, 0x15, 0x00, 0xCC, 0x9C, 0x17, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xB5, 0x15, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xA4, 0x15, 0x00, 0xF0, 0x9F, 0x17, 0x00, ++0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x20, 0xBF, 0x15, 0x00, 0x18, 0xBF, 0x15, 0x00, 0xA4, 0xBA, 0x17, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x8C, 0xB8, 0x15, 0x00, 0xE0, 0xB8, 0x17, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xBB, 0x15, 0x00, ++0x60, 0xBA, 0x17, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xBE, 0x15, 0x00, 0x90, 0xBA, 0x17, 0x00, ++0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xC2, 0x15, 0x00, 0xF4, 0xDF, 0x17, 0x00, 0x05, 0x00, 0x20, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xD0, 0x15, 0x00, ++0x74, 0xEF, 0x17, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x28, 0x65, 0x76, 0x65, 0x6E, 0x74, 0x20, 0x3C, 0x20, 0x4B, 0x45, 0x5F, 0x45, 0x56, 0x54, 0x5F, ++0x4D, 0x41, 0x58, 0x29, 0x20, 0x26, 0x26, 0x20, 0x6B, 0x65, 0x5F, 0x65, 0x76, 0x74, 0x5F, 0x68, 0x64, 0x6C, 0x72, 0x5B, ++0x65, 0x76, 0x65, 0x6E, 0x74, 0x5D, 0x2E, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x68, 0x64, 0x72, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, ++0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x28, 0x70, 0x72, 0x65, 0x76, 0x5F, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, ++0x74, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x70, 0x72, 0x65, 0x76, 0x5F, ++0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x2D, 0x3E, 0x6E, 0x65, 0x78, 0x74, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6C, 0x65, ++0x6D, 0x65, 0x6E, 0x74, 0x29, 0x00, 0x00, 0x00, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, ++0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x30, 0x07, 0x77, 0x2C, 0x61, 0x0E, 0xEE, 0xBA, 0x51, 0x09, 0x99, ++0x19, 0xC4, 0x6D, 0x07, 0x8F, 0xF4, 0x6A, 0x70, 0x35, 0xA5, 0x63, 0xE9, 0xA3, 0x95, 0x64, 0x9E, 0x32, 0x88, 0xDB, 0x0E, ++0xA4, 0xB8, 0xDC, 0x79, 0x1E, 0xE9, 0xD5, 0xE0, 0x88, 0xD9, 0xD2, 0x97, 0x2B, 0x4C, 0xB6, 0x09, 0xBD, 0x7C, 0xB1, 0x7E, ++0x07, 0x2D, 0xB8, 0xE7, 0x91, 0x1D, 0xBF, 0x90, 0x64, 0x10, 0xB7, 0x1D, 0xF2, 0x20, 0xB0, 0x6A, 0x48, 0x71, 0xB9, 0xF3, ++0xDE, 0x41, 0xBE, 0x84, 0x7D, 0xD4, 0xDA, 0x1A, 0xEB, 0xE4, 0xDD, 0x6D, 0x51, 0xB5, 0xD4, 0xF4, 0xC7, 0x85, 0xD3, 0x83, ++0x56, 0x98, 0x6C, 0x13, 0xC0, 0xA8, 0x6B, 0x64, 0x7A, 0xF9, 0x62, 0xFD, 0xEC, 0xC9, 0x65, 0x8A, 0x4F, 0x5C, 0x01, 0x14, ++0xD9, 0x6C, 0x06, 0x63, 0x63, 0x3D, 0x0F, 0xFA, 0xF5, 0x0D, 0x08, 0x8D, 0xC8, 0x20, 0x6E, 0x3B, 0x5E, 0x10, 0x69, 0x4C, ++0xE4, 0x41, 0x60, 0xD5, 0x72, 0x71, 0x67, 0xA2, 0xD1, 0xE4, 0x03, 0x3C, 0x47, 0xD4, 0x04, 0x4B, 0xFD, 0x85, 0x0D, 0xD2, ++0x6B, 0xB5, 0x0A, 0xA5, 0xFA, 0xA8, 0xB5, 0x35, 0x6C, 0x98, 0xB2, 0x42, 0xD6, 0xC9, 0xBB, 0xDB, 0x40, 0xF9, 0xBC, 0xAC, ++0xE3, 0x6C, 0xD8, 0x32, 0x75, 0x5C, 0xDF, 0x45, 0xCF, 0x0D, 0xD6, 0xDC, 0x59, 0x3D, 0xD1, 0xAB, 0xAC, 0x30, 0xD9, 0x26, ++0x3A, 0x00, 0xDE, 0x51, 0x80, 0x51, 0xD7, 0xC8, 0x16, 0x61, 0xD0, 0xBF, 0xB5, 0xF4, 0xB4, 0x21, 0x23, 0xC4, 0xB3, 0x56, ++0x99, 0x95, 0xBA, 0xCF, 0x0F, 0xA5, 0xBD, 0xB8, 0x9E, 0xB8, 0x02, 0x28, 0x08, 0x88, 0x05, 0x5F, 0xB2, 0xD9, 0x0C, 0xC6, ++0x24, 0xE9, 0x0B, 0xB1, 0x87, 0x7C, 0x6F, 0x2F, 0x11, 0x4C, 0x68, 0x58, 0xAB, 0x1D, 0x61, 0xC1, 0x3D, 0x2D, 0x66, 0xB6, ++0x90, 0x41, 0xDC, 0x76, 0x06, 0x71, 0xDB, 0x01, 0xBC, 0x20, 0xD2, 0x98, 0x2A, 0x10, 0xD5, 0xEF, 0x89, 0x85, 0xB1, 0x71, ++0x1F, 0xB5, 0xB6, 0x06, 0xA5, 0xE4, 0xBF, 0x9F, 0x33, 0xD4, 0xB8, 0xE8, 0xA2, 0xC9, 0x07, 0x78, 0x34, 0xF9, 0x00, 0x0F, ++0x8E, 0xA8, 0x09, 0x96, 0x18, 0x98, 0x0E, 0xE1, 0xBB, 0x0D, 0x6A, 0x7F, 0x2D, 0x3D, 0x6D, 0x08, 0x97, 0x6C, 0x64, 0x91, ++0x01, 0x5C, 0x63, 0xE6, 0xF4, 0x51, 0x6B, 0x6B, 0x62, 0x61, 0x6C, 0x1C, 0xD8, 0x30, 0x65, 0x85, 0x4E, 0x00, 0x62, 0xF2, ++0xED, 0x95, 0x06, 0x6C, 0x7B, 0xA5, 0x01, 0x1B, 0xC1, 0xF4, 0x08, 0x82, 0x57, 0xC4, 0x0F, 0xF5, 0xC6, 0xD9, 0xB0, 0x65, ++0x50, 0xE9, 0xB7, 0x12, 0xEA, 0xB8, 0xBE, 0x8B, 0x7C, 0x88, 0xB9, 0xFC, 0xDF, 0x1D, 0xDD, 0x62, 0x49, 0x2D, 0xDA, 0x15, ++0xF3, 0x7C, 0xD3, 0x8C, 0x65, 0x4C, 0xD4, 0xFB, 0x58, 0x61, 0xB2, 0x4D, 0xCE, 0x51, 0xB5, 0x3A, 0x74, 0x00, 0xBC, 0xA3, ++0xE2, 0x30, 0xBB, 0xD4, 0x41, 0xA5, 0xDF, 0x4A, 0xD7, 0x95, 0xD8, 0x3D, 0x6D, 0xC4, 0xD1, 0xA4, 0xFB, 0xF4, 0xD6, 0xD3, ++0x6A, 0xE9, 0x69, 0x43, 0xFC, 0xD9, 0x6E, 0x34, 0x46, 0x88, 0x67, 0xAD, 0xD0, 0xB8, 0x60, 0xDA, 0x73, 0x2D, 0x04, 0x44, ++0xE5, 0x1D, 0x03, 0x33, 0x5F, 0x4C, 0x0A, 0xAA, 0xC9, 0x7C, 0x0D, 0xDD, 0x3C, 0x71, 0x05, 0x50, 0xAA, 0x41, 0x02, 0x27, ++0x10, 0x10, 0x0B, 0xBE, 0x86, 0x20, 0x0C, 0xC9, 0x25, 0xB5, 0x68, 0x57, 0xB3, 0x85, 0x6F, 0x20, 0x09, 0xD4, 0x66, 0xB9, ++0x9F, 0xE4, 0x61, 0xCE, 0x0E, 0xF9, 0xDE, 0x5E, 0x98, 0xC9, 0xD9, 0x29, 0x22, 0x98, 0xD0, 0xB0, 0xB4, 0xA8, 0xD7, 0xC7, ++0x17, 0x3D, 0xB3, 0x59, 0x81, 0x0D, 0xB4, 0x2E, 0x3B, 0x5C, 0xBD, 0xB7, 0xAD, 0x6C, 0xBA, 0xC0, 0x20, 0x83, 0xB8, 0xED, ++0xB6, 0xB3, 0xBF, 0x9A, 0x0C, 0xE2, 0xB6, 0x03, 0x9A, 0xD2, 0xB1, 0x74, 0x39, 0x47, 0xD5, 0xEA, 0xAF, 0x77, 0xD2, 0x9D, ++0x15, 0x26, 0xDB, 0x04, 0x83, 0x16, 0xDC, 0x73, 0x12, 0x0B, 0x63, 0xE3, 0x84, 0x3B, 0x64, 0x94, 0x3E, 0x6A, 0x6D, 0x0D, ++0xA8, 0x5A, 0x6A, 0x7A, 0x0B, 0xCF, 0x0E, 0xE4, 0x9D, 0xFF, 0x09, 0x93, 0x27, 0xAE, 0x00, 0x0A, 0xB1, 0x9E, 0x07, 0x7D, ++0x44, 0x93, 0x0F, 0xF0, 0xD2, 0xA3, 0x08, 0x87, 0x68, 0xF2, 0x01, 0x1E, 0xFE, 0xC2, 0x06, 0x69, 0x5D, 0x57, 0x62, 0xF7, ++0xCB, 0x67, 0x65, 0x80, 0x71, 0x36, 0x6C, 0x19, 0xE7, 0x06, 0x6B, 0x6E, 0x76, 0x1B, 0xD4, 0xFE, 0xE0, 0x2B, 0xD3, 0x89, ++0x5A, 0x7A, 0xDA, 0x10, 0xCC, 0x4A, 0xDD, 0x67, 0x6F, 0xDF, 0xB9, 0xF9, 0xF9, 0xEF, 0xBE, 0x8E, 0x43, 0xBE, 0xB7, 0x17, ++0xD5, 0x8E, 0xB0, 0x60, 0xE8, 0xA3, 0xD6, 0xD6, 0x7E, 0x93, 0xD1, 0xA1, 0xC4, 0xC2, 0xD8, 0x38, 0x52, 0xF2, 0xDF, 0x4F, ++0xF1, 0x67, 0xBB, 0xD1, 0x67, 0x57, 0xBC, 0xA6, 0xDD, 0x06, 0xB5, 0x3F, 0x4B, 0x36, 0xB2, 0x48, 0xDA, 0x2B, 0x0D, 0xD8, ++0x4C, 0x1B, 0x0A, 0xAF, 0xF6, 0x4A, 0x03, 0x36, 0x60, 0x7A, 0x04, 0x41, 0xC3, 0xEF, 0x60, 0xDF, 0x55, 0xDF, 0x67, 0xA8, ++0xEF, 0x8E, 0x6E, 0x31, 0x79, 0xBE, 0x69, 0x46, 0x8C, 0xB3, 0x61, 0xCB, 0x1A, 0x83, 0x66, 0xBC, 0xA0, 0xD2, 0x6F, 0x25, ++0x36, 0xE2, 0x68, 0x52, 0x95, 0x77, 0x0C, 0xCC, 0x03, 0x47, 0x0B, 0xBB, 0xB9, 0x16, 0x02, 0x22, 0x2F, 0x26, 0x05, 0x55, ++0xBE, 0x3B, 0xBA, 0xC5, 0x28, 0x0B, 0xBD, 0xB2, 0x92, 0x5A, 0xB4, 0x2B, 0x04, 0x6A, 0xB3, 0x5C, 0xA7, 0xFF, 0xD7, 0xC2, ++0x31, 0xCF, 0xD0, 0xB5, 0x8B, 0x9E, 0xD9, 0x2C, 0x1D, 0xAE, 0xDE, 0x5B, 0xB0, 0xC2, 0x64, 0x9B, 0x26, 0xF2, 0x63, 0xEC, ++0x9C, 0xA3, 0x6A, 0x75, 0x0A, 0x93, 0x6D, 0x02, 0xA9, 0x06, 0x09, 0x9C, 0x3F, 0x36, 0x0E, 0xEB, 0x85, 0x67, 0x07, 0x72, ++0x13, 0x57, 0x00, 0x05, 0x82, 0x4A, 0xBF, 0x95, 0x14, 0x7A, 0xB8, 0xE2, 0xAE, 0x2B, 0xB1, 0x7B, 0x38, 0x1B, 0xB6, 0x0C, ++0x9B, 0x8E, 0xD2, 0x92, 0x0D, 0xBE, 0xD5, 0xE5, 0xB7, 0xEF, 0xDC, 0x7C, 0x21, 0xDF, 0xDB, 0x0B, 0xD4, 0xD2, 0xD3, 0x86, ++0x42, 0xE2, 0xD4, 0xF1, 0xF8, 0xB3, 0xDD, 0x68, 0x6E, 0x83, 0xDA, 0x1F, 0xCD, 0x16, 0xBE, 0x81, 0x5B, 0x26, 0xB9, 0xF6, ++0xE1, 0x77, 0xB0, 0x6F, 0x77, 0x47, 0xB7, 0x18, 0xE6, 0x5A, 0x08, 0x88, 0x70, 0x6A, 0x0F, 0xFF, 0xCA, 0x3B, 0x06, 0x66, ++0x5C, 0x0B, 0x01, 0x11, 0xFF, 0x9E, 0x65, 0x8F, 0x69, 0xAE, 0x62, 0xF8, 0xD3, 0xFF, 0x6B, 0x61, 0x45, 0xCF, 0x6C, 0x16, ++0x78, 0xE2, 0x0A, 0xA0, 0xEE, 0xD2, 0x0D, 0xD7, 0x54, 0x83, 0x04, 0x4E, 0xC2, 0xB3, 0x03, 0x39, 0x61, 0x26, 0x67, 0xA7, ++0xF7, 0x16, 0x60, 0xD0, 0x4D, 0x47, 0x69, 0x49, 0xDB, 0x77, 0x6E, 0x3E, 0x4A, 0x6A, 0xD1, 0xAE, 0xDC, 0x5A, 0xD6, 0xD9, ++0x66, 0x0B, 0xDF, 0x40, 0xF0, 0x3B, 0xD8, 0x37, 0x53, 0xAE, 0xBC, 0xA9, 0xC5, 0x9E, 0xBB, 0xDE, 0x7F, 0xCF, 0xB2, 0x47, ++0xE9, 0xFF, 0xB5, 0x30, 0x1C, 0xF2, 0xBD, 0xBD, 0x8A, 0xC2, 0xBA, 0xCA, 0x30, 0x93, 0xB3, 0x53, 0xA6, 0xA3, 0xB4, 0x24, ++0x05, 0x36, 0xD0, 0xBA, 0x93, 0x06, 0xD7, 0xCD, 0x29, 0x57, 0xDE, 0x54, 0xBF, 0x67, 0xD9, 0x23, 0x2E, 0x7A, 0x66, 0xB3, ++0xB8, 0x4A, 0x61, 0xC4, 0x02, 0x1B, 0x68, 0x5D, 0x94, 0x2B, 0x6F, 0x2A, 0x37, 0xBE, 0x0B, 0xB4, 0xA1, 0x8E, 0x0C, 0xC3, ++0x1B, 0xDF, 0x05, 0x5A, 0x8D, 0xEF, 0x02, 0x2D, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6E, 0x64, 0x00, ++0x00, 0x50, 0xF2, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x03, ++0x04, 0x08, 0x02, 0x01, 0x01, 0x00, 0x02, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x02, 0x04, 0x0B, 0x16, ++0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, ++0x44, 0x42, 0x47, 0x5F, 0x53, 0x45, 0x56, 0x5F, 0x4D, 0x49, 0x4E, 0x20, 0x3C, 0x3D, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, ++0x78, 0x20, 0x26, 0x26, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3C, 0x20, 0x44, 0x42, 0x47, 0x5F, 0x53, 0x45, ++0x56, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, ++0x63, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, ++0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, ++0x03, 0x02, 0x06, 0x07, 0x00, 0x00, 0x04, 0x02, 0x03, 0x02, 0x06, 0x07, 0x00, 0x00, 0x04, 0x03, 0x03, 0x00, 0x06, 0x07, ++0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x2C, 0x20, 0x77, 0x6C, 0x61, ++0x6E, 0x20, 0x66, 0x63, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x62, 0x6F, ++0x6F, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x70, 0x69, 0x6F, 0x77, 0x72, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, ++0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x53, ++0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x20, 0x66, 0x69, 0x6C, 0x74, ++0x65, 0x72, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x53, ++0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x20, 0x66, 0x69, 0x6C, 0x74, 0x65, 0x72, ++0x3A, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x42, ++0x6F, 0x6F, 0x74, 0x20, 0x4E, 0x50, 0x43, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x57, ++0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6D, ++0x61, 0x73, 0x6B, 0x3A, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x3A, 0x30, 0x78, 0x25, ++0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, ++0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, ++0x47, 0x3A, 0x20, 0x57, 0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x77, 0x69, ++0x74, 0x68, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, ++0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, ++0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x52, 0x65, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, ++0x79, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, ++0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x42, 0x6F, 0x6F, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, ++0x25, 0x78, 0x2C, 0x20, 0x61, 0x64, 0x64, 0x72, 0x3D, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x64, 0x65, 0x6C, 0x61, 0x79, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, ++0x62, 0x6F, 0x6F, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0D, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x46, ++0x57, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x57, ++0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x7E, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x77, 0x69, ++0x74, 0x68, 0x20, 0x7B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x2E, 0x2E, 0x2E, 0x7D, 0x2C, 0x20, 0x77, 0x73, ++0x74, 0x61, 0x74, 0x75, 0x73, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x70, 0x22, 0x17, 0x00, ++0x0C, 0x00, 0x00, 0x00, 0x9B, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x20, 0x28, 0x25, 0x73, 0x29, 0x20, 0x61, 0x74, 0x20, ++0x25, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x9B, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x20, 0x28, 0x25, 0x73, ++0x29, 0x20, 0x61, 0x74, 0x20, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x45, 0x72, 0x72, 0x3A, 0x20, 0x55, 0x46, 0x20, ++0x68, 0x6F, 0x73, 0x74, 0x20, 0x72, 0x78, 0x20, 0x62, 0x75, 0x66, 0x66, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x0D, 0x0A, 0x00, ++0x09, 0x2D, 0x20, 0x00, 0x25, 0x73, 0x25, 0x73, 0x25, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, ++0x25, 0x30, 0x32, 0x78, 0x20, 0x00, 0x00, 0x00, 0x25, 0x30, 0x38, 0x78, 0x3A, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x34, ++0x58, 0x20, 0x25, 0x30, 0x34, 0x58, 0x00, 0x00, 0x20, 0x25, 0x30, 0x32, 0x58, 0x20, 0x25, 0x30, 0x32, 0x58, 0x20, 0x25, ++0x30, 0x32, 0x58, 0x20, 0x25, 0x30, 0x32, 0x58, 0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x34, 0x58, 0x00, 0x00, 0x00, ++0x20, 0x25, 0x30, 0x32, 0x58, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x68, 0x65, 0x6C, ++0x70, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0x00, 0x68, 0x65, 0x6C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x20, 0x72, 0x20, 0x61, ++0x64, 0x64, 0x72, 0x20, 0x3C, 0x63, 0x6E, 0x74, 0x3E, 0x20, 0x3C, 0x73, 0x7A, 0x3E, 0x00, 0x00, 0x20, 0x77, 0x20, 0x61, ++0x64, 0x64, 0x72, 0x20, 0x76, 0x61, 0x6C, 0x00, 0x77, 0x00, 0x00, 0x00, 0x20, 0x64, 0x62, 0x67, 0x20, 0x6D, 0x73, 0x6B, ++0x00, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x00, 0x00, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x76, 0x61, 0x6C, 0x28, 0x69, 0x6E, ++0x20, 0x73, 0x29, 0x00, 0x77, 0x66, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, 0x20, 0x63, 0x6D, 0x64, ++0x5F, 0x66, 0x72, 0x65, 0x65, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x20, 0x65, 0x6D, 0x70, 0x74, 0x79, 0x0D, 0x0A, 0x00, 0x00, ++0x61, 0x69, 0x63, 0x3E, 0x20, 0x00, 0x00, 0x00, 0x4E, 0x6F, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x63, 0x6D, 0x64, 0x73, ++0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x64, 0x2E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x2A, 0x20, 0x54, ++0x6F, 0x6F, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, 0x28, 0x6D, 0x61, 0x78, 0x2E, 0x20, 0x25, ++0x64, 0x29, 0x20, 0x2A, 0x2A, 0x0A, 0x00, 0x00, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x20, 0x63, 0x6F, 0x6D, 0x6D, ++0x61, 0x6E, 0x64, 0x20, 0x27, 0x25, 0x73, 0x27, 0x0A, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x25, ++0x73, 0x0A, 0x00, 0x00, 0x63, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x0D, 0x0A, 0x00, 0x00, ++0x63, 0x75, 0x72, 0x20, 0x64, 0x62, 0x67, 0x5F, 0x6D, 0x73, 0x6B, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x63, 0x66, 0x67, 0x20, 0x64, 0x62, 0x67, 0x5F, 0x6D, 0x73, 0x6B, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x76, 0x61, ++0x6C, 0x69, 0x64, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, ++0x65, 0x3A, 0x0A, 0x20, 0x20, 0x72, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3C, 0x63, 0x6E, 0x74, 0x3E, 0x0A, 0x00, 0x00, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x0D, 0x0A, 0x00, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x32, 0x58, 0x0D, 0x0A, 0x00, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x34, 0x58, 0x0D, 0x0A, 0x00, ++0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x20, 0x20, 0x77, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x76, 0x61, 0x6C, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x76, 0x61, 0x6C, ++0x28, 0x69, 0x6E, 0x20, 0x73, 0x29, 0x0A, 0x00, 0x63, 0x75, 0x72, 0x20, 0x77, 0x66, 0x63, 0x74, 0x3A, 0x20, 0x25, 0x75, ++0x73, 0x0A, 0x00, 0x00, 0x63, 0x66, 0x67, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x25, 0x75, 0x73, 0x0A, 0x00, 0x00, 0x00, ++0x77, 0x66, 0x63, 0x74, 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x0A, 0x00, 0x00, ++0x08, 0x20, 0x08, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x07, 0x00, 0x50, ++0xF2, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x45, 0x5F, ++0x42, 0x55, 0x53, 0x59, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x65, 0x6E, 0x76, ++0x2E, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x5F, 0x76, 0x69, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, ++0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x00, 0xD8, 0x22, 0x17, 0x00, 0x18, 0x00, 0x00, 0x00, ++0x62, 0x69, 0x74, 0x5F, 0x70, 0x6F, 0x73, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, 0x45, ++0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2D, 0x3E, 0x6C, 0x65, 0x6E, 0x67, 0x74, ++0x68, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x48, ++0x45, 0x29, 0x00, 0x00, 0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x56, 0x48, 0x54, 0x29, 0x00, ++0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x48, 0x54, 0x29, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, ++0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, ++0x63, 0x75, 0x72, 0x72, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x6D, 0x69, 0x63, 0x5F, 0x63, 0x61, 0x6C, 0x63, 0x5F, 0x70, 0x74, 0x72, 0x2D, 0x3E, 0x6C, 0x61, 0x73, 0x74, 0x5F, 0x6D, ++0x5F, 0x69, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x20, 0x34, 0x00, 0x00, 0x72, 0x65, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x75, 0x2E, 0x73, 0x74, 0x61, 0x2E, 0x61, 0x70, 0x5F, 0x69, 0x64, ++0x20, 0x3D, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x49, 0x44, 0x58, 0x00, ++0x63, 0x6F, 0x6E, 0x6E, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x20, 0x69, 0x6E, 0x64, 0x0D, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, ++0x20, 0x53, 0x4D, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x4E, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, ++0x20, 0x53, 0x4D, 0x5F, 0x4A, 0x4F, 0x49, 0x4E, 0x49, 0x4E, 0x47, 0x00, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x3A, 0x20, 0x25, ++0x34, 0x78, 0x3A, 0x25, 0x34, 0x78, 0x3A, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x28, 0x6B, 0x65, 0x5F, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, ++0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, ++0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, ++0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, ++0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, ++0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, ++0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, ++0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, ++0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, ++0x47, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, ++0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, ++0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, ++0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x00, 0x00, ++0x73, 0x6D, 0x20, 0x63, 0x6F, 0x65, 0x78, 0x20, 0x74, 0x73, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, ++0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x41, 0x44, 0x44, 0x49, ++0x4E, 0x47, 0x00, 0x00, 0x98, 0x23, 0x17, 0x00, 0x15, 0x00, 0x00, 0x00, 0x74, 0x78, 0x20, 0x63, 0x66, 0x6D, 0x3A, 0x25, ++0x64, 0x2C, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x73, 0x5F, 0x65, ++0x6D, 0x70, 0x74, 0x79, 0x28, 0x26, 0x73, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x62, 0x73, 0x73, 0x5F, 0x63, 0x6F, 0x6E, ++0x66, 0x69, 0x67, 0x29, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x20, 0x72, 0x65, 0x6F, 0x75, 0x72, ++0x63, 0x65, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x2F, 0x64, 0x69, 0x73, 0x61, 0x73, ++0x73, 0x6F, 0x63, 0x3A, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x63, ++0x74, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x3A, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x61, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x61, 0x75, 0x74, 0x68, ++0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x61, 0x73, 0x73, 0x6F, ++0x63, 0x5F, 0x72, 0x73, 0x70, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x20, ++0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x61, 0x75, ++0x74, 0x68, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x20, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x20, 0x63, ++0x6F, 0x64, 0x65, 0x20, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x42, 0x53, 0x53, 0x5F, 0x43, 0x41, 0x50, 0x41, ++0x28, 0x62, 0x73, 0x73, 0x2C, 0x20, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x29, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x03, 0x00, ++0x00, 0x00, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x73, 0x6D, 0x5F, 0x61, 0x75, 0x74, 0x68, 0x5F, ++0x73, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6D, 0x5F, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x5F, 0x72, 0x65, 0x71, ++0x5F, 0x73, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, 0x43, ++0x4E, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, 0x61, 0x70, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, ++0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, ++0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, ++0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, ++0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, ++0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x20, 0x7C, 0x7C, ++0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, ++0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, ++0x29, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, ++0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, ++0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, ++0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, ++0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, ++0x50, 0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, ++0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x00, 0x00, 0x00, 0x00, 0x61, 0x70, 0x20, 0x73, ++0x74, 0x6F, 0x70, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x73, 0x5F, 0x65, ++0x6D, 0x70, 0x74, 0x79, 0x28, 0x26, 0x61, 0x70, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x62, 0x73, 0x73, 0x5F, 0x63, 0x6F, ++0x6E, 0x66, 0x69, 0x67, 0x29, 0x00, 0x00, 0x00, 0x40, 0x24, 0x17, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, ++0x75, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, ++0x75, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x0D, 0x0A, 0x00, ++0x73, 0x63, 0x61, 0x6E, 0x75, 0x20, 0x73, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x76, 0x6E, 0x64, 0x72, 0x20, ++0x69, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x63, 0x61, ++0x6E, 0x75, 0x20, 0x72, 0x65, 0x71, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x4D, 0x41, 0x43, ++0x5F, 0x41, 0x44, 0x44, 0x52, 0x5F, 0x47, 0x52, 0x4F, 0x55, 0x50, 0x28, 0x26, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, ++0x62, 0x73, 0x73, 0x69, 0x64, 0x29, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x20, 0x76, 0x6E, 0x64, 0x72, 0x20, 0x69, ++0x65, 0x0D, 0x0A, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x20, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x24, 0x17, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC8, 0x24, 0x17, 0x00, ++0x05, 0x00, 0x00, 0x00, 0xF0, 0x24, 0x17, 0x00, 0x07, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x5F, 0x63, 0x6F, ++0x6E, 0x66, 0x69, 0x72, 0x6D, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x5B, 0x48, 0x49, 0x44, ++0x44, 0x45, 0x4E, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x2D, 0x00, 0x6A, 0x6F, 0x69, 0x6E, ++0x3A, 0x25, 0x73, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x66, 0x69, 0x78, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x6E, 0x6F, 0x5F, 0x73, ++0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x64, 0x20, ++0x25, 0x64, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x20, 0x25, 0x78, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00, 0x00, ++0x28, 0x69, 0x65, 0x5F, 0x62, 0x75, 0x66, 0x20, 0x2D, 0x20, 0x43, 0x50, 0x55, 0x32, 0x48, 0x57, 0x28, 0x69, 0x65, 0x2D, ++0x3E, 0x62, 0x75, 0x66, 0x29, 0x29, 0x20, 0x3C, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x49, ++0x45, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3A, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x20, 0x61, ++0x72, 0x70, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x69, 0x70, 0x3D, 0x25, 0x78, 0x2E, 0x20, 0x76, 0x69, 0x66, 0x20, 0x69, 0x70, ++0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x78, 0x20, 0x61, 0x72, 0x70, 0x72, 0x65, 0x73, 0x70, 0x0A, 0x00, ++0x72, 0x78, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x2D, 0x3E, 0x76, 0x61, 0x6C, 0x2E, 0x73, 0x74, ++0x61, 0x74, 0x75, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x75, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x20, 0x73, ++0x74, 0x61, 0x74, 0x3A, 0x25, 0x64, 0x00, 0x00, 0x54, 0x4B, 0x49, 0x50, 0x20, 0x49, 0x43, 0x56, 0x20, 0x45, 0x52, 0x52, ++0x0A, 0x00, 0x00, 0x00, 0x64, 0x65, 0x66, 0x72, 0x61, 0x67, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, ++0x72, 0x78, 0x5F, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x2D, 0x3E, 0x6F, 0x6F, 0x6F, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x63, 0x6E, ++0x74, 0x00, 0x00, 0x00, 0x6F, 0x6C, 0x64, 0x5F, 0x77, 0x69, 0x6E, 0x5F, 0x62, 0x61, 0x72, 0x20, 0x64, 0x65, 0x74, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x2D, 0x3E, 0x6F, 0x6F, 0x6F, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x63, ++0x6E, 0x74, 0x3C, 0x3D, 0x36, 0x34, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x64, 0x65, 0x61, ++0x75, 0x74, 0x68, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x21, 0x3D, 0x20, ++0x30, 0x78, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6D, 0x61, 0x63, 0x68, 0x64, 0x72, 0x5F, 0x6C, 0x65, 0x6E, 0x67, ++0x74, 0x68, 0x20, 0x26, 0x20, 0x30, 0x78, 0x33, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x72, 0x78, 0x20, 0x65, ++0x61, 0x70, 0x6F, 0x6C, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x57, 0x45, 0x50, 0x20, ++0x49, 0x43, 0x56, 0x20, 0x45, 0x52, 0x52, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x20, 0x21, 0x3D, ++0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x72, 0x78, 0x75, 0x5F, 0x63, 0x6E, 0x74, 0x72, 0x6C, 0x5F, 0x73, 0x70, ++0x75, 0x72, 0x69, 0x6F, 0x75, 0x73, 0x5F, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x75, 0x20, ++0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x6D, 0x69, 0x74, 0x20, 0x74, 0x78, 0x75, 0x20, 0x64, ++0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x0A, 0x00, 0x70, 0x6F, 0x72, 0x74, 0x20, 0x66, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3A, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x2D, 0x3E, 0x73, 0x74, 0x61, 0x69, 0x64, 0x20, ++0x21, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, ++0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x61, 0x64, 0x64, 0x62, 0x61, 0x5F, 0x72, 0x65, 0x71, 0x3A, 0x74, 0x69, 0x64, ++0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x61, 0x64, 0x64, 0x62, 0x61, ++0x5F, 0x72, 0x73, 0x70, 0x3A, 0x74, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x72, 0x78, 0x5F, 0x64, 0x65, 0x6C, 0x62, 0x61, 0x3A, ++0x74, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, ++0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x74, 0x78, 0x5F, 0x64, 0x65, 0x6C, 0x62, 0x61, 0x3A, 0x74, 0x69, 0x64, 0x3D, ++0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x2C, 0x25, 0x17, 0x00, ++0x05, 0x00, 0x00, 0x00, 0x6D, 0x6F, 0x76, 0x65, 0x20, 0x77, 0x69, 0x6E, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x66, ++0x6C, 0x75, 0x73, 0x68, 0x3A, 0x20, 0x73, 0x75, 0x63, 0x63, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x70, ++0x61, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x4B, 0x45, 0x5F, 0x42, 0x55, 0x49, 0x4C, 0x44, 0x5F, 0x49, 0x44, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x42, 0x41, ++0x4D, 0x2C, 0x20, 0x62, 0x61, 0x6D, 0x5F, 0x69, 0x64, 0x78, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x41, 0x4D, 0x5F, ++0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x00, 0x00, 0x62, 0x61, 0x6D, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x42, 0x41, ++0x4D, 0x5F, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, ++0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, ++0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, ++0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, ++0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, ++0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, ++0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, ++0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, ++0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, ++0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, ++0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, ++0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, ++0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, ++0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, ++0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, ++0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, 0xC6, 0xF8, 0xEE, 0xF6, ++0xFF, 0xD6, 0xDE, 0x91, 0x60, 0x02, 0xCE, 0x56, 0xE7, 0xB5, 0x4D, 0xEC, 0x8F, 0x1F, 0x89, 0xFA, 0xEF, 0xB2, 0x8E, 0xFB, ++0x41, 0xB3, 0x5F, 0x45, 0x23, 0x53, 0xE4, 0x9B, 0x75, 0xE1, 0x3D, 0x4C, 0x6C, 0x7E, 0xF5, 0x83, 0x68, 0x51, 0xD1, 0xF9, ++0xE2, 0xAB, 0x62, 0x2A, 0x08, 0x95, 0x46, 0x9D, 0x30, 0x37, 0x0A, 0x2F, 0x0E, 0x24, 0x1B, 0xDF, 0xCD, 0x4E, 0x7F, 0xEA, ++0x12, 0x1D, 0x58, 0x34, 0x36, 0xDC, 0xB4, 0x5B, 0xA4, 0x76, 0xB7, 0x7D, 0x52, 0xDD, 0x5E, 0x13, 0xA6, 0xB9, 0x00, 0xC1, ++0x40, 0xE3, 0x79, 0xB6, 0xD4, 0x8D, 0x67, 0x72, 0x94, 0x98, 0xB0, 0x85, 0xBB, 0xC5, 0x4F, 0xED, 0x86, 0x9A, 0x66, 0x11, ++0x8A, 0xE9, 0x04, 0xFE, 0xA0, 0x78, 0x25, 0x4B, 0xA2, 0x5D, 0x80, 0x05, 0x3F, 0x21, 0x70, 0xF1, 0x63, 0x77, 0xAF, 0x42, ++0x20, 0xE5, 0xFD, 0xBF, 0x81, 0x18, 0x26, 0xC3, 0xBE, 0x35, 0x88, 0x2E, 0x93, 0x55, 0xFC, 0x7A, 0xC8, 0xBA, 0x32, 0xE6, ++0xC0, 0x19, 0x9E, 0xA3, 0x44, 0x54, 0x3B, 0x0B, 0x8C, 0xC7, 0x6B, 0x28, 0xA7, 0xBC, 0x16, 0xAD, 0xDB, 0x64, 0x74, 0x14, ++0x92, 0x0C, 0x48, 0xB8, 0x9F, 0xBD, 0x43, 0xC4, 0x39, 0x31, 0xD3, 0xF2, 0xD5, 0x8B, 0x6E, 0xDA, 0x01, 0xB1, 0x9C, 0x49, ++0xD8, 0xAC, 0xF3, 0xCF, 0xCA, 0xF4, 0x47, 0x10, 0x6F, 0xF0, 0x4A, 0x5C, 0x38, 0x57, 0x73, 0x97, 0xCB, 0xA1, 0xE8, 0x3E, ++0x96, 0x61, 0x0D, 0x0F, 0xE0, 0x7C, 0x71, 0xCC, 0x90, 0x06, 0xF7, 0x1C, 0xC2, 0x6A, 0xAE, 0x69, 0x17, 0x99, 0x3A, 0x27, ++0xD9, 0xEB, 0x2B, 0x22, 0xD2, 0xA9, 0x07, 0x33, 0x2D, 0x3C, 0x15, 0xC9, 0x87, 0xAA, 0x50, 0xA5, 0x03, 0x59, 0x09, 0x1A, ++0x65, 0xD7, 0x84, 0xD0, 0x82, 0x29, 0x5A, 0x1E, 0x7B, 0xA8, 0x6D, 0x2C, 0xA5, 0x84, 0x99, 0x8D, 0x0D, 0xBD, 0xB1, 0x54, ++0x50, 0x03, 0xA9, 0x7D, 0x19, 0x62, 0xE6, 0x9A, 0x45, 0x9D, 0x40, 0x87, 0x15, 0xEB, 0xC9, 0x0B, 0xEC, 0x67, 0xFD, 0xEA, ++0xBF, 0xF7, 0x96, 0x5B, 0xC2, 0x1C, 0xAE, 0x6A, 0x5A, 0x41, 0x02, 0x4F, 0x5C, 0xF4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3F, ++0x0C, 0x52, 0x65, 0x5E, 0x28, 0xA1, 0x0F, 0xB5, 0x09, 0x36, 0x9B, 0x3D, 0x26, 0x69, 0xCD, 0x9F, 0x1B, 0x9E, 0x74, 0x2E, ++0x2D, 0xB2, 0xEE, 0xFB, 0xF6, 0x4D, 0x61, 0xCE, 0x7B, 0x3E, 0x71, 0x97, 0xF5, 0x68, 0x00, 0x2C, 0x60, 0x1F, 0xC8, 0xED, ++0xBE, 0x46, 0xD9, 0x4B, 0xDE, 0xD4, 0xE8, 0x4A, 0x6B, 0x2A, 0xE5, 0x16, 0xC5, 0xD7, 0x55, 0x94, 0xCF, 0x10, 0x06, 0x81, ++0xF0, 0x44, 0xBA, 0xE3, 0xF3, 0xFE, 0xC0, 0x8A, 0xAD, 0xBC, 0x48, 0x04, 0xDF, 0xC1, 0x75, 0x63, 0x30, 0x1A, 0x0E, 0x6D, ++0x4C, 0x14, 0x35, 0x2F, 0xE1, 0xA2, 0xCC, 0x39, 0x57, 0xF2, 0x82, 0x47, 0xAC, 0xE7, 0x2B, 0x95, 0xA0, 0x98, 0xD1, 0x7F, ++0x66, 0x7E, 0xAB, 0x83, 0xCA, 0x29, 0xD3, 0x3C, 0x79, 0xE2, 0x1D, 0x76, 0x3B, 0x56, 0x4E, 0x1E, 0xDB, 0x0A, 0x6C, 0xE4, ++0x5D, 0x6E, 0xEF, 0xA6, 0xA8, 0xA4, 0x37, 0x8B, 0x32, 0x43, 0x59, 0xB7, 0x8C, 0x64, 0xD2, 0xE0, 0xB4, 0xFA, 0x07, 0x25, ++0xAF, 0x8E, 0xE9, 0x18, 0xD5, 0x88, 0x6F, 0x72, 0x24, 0xF1, 0xC7, 0x51, 0x23, 0x7C, 0x9C, 0x21, 0xDD, 0xDC, 0x86, 0x85, ++0x90, 0x42, 0xC4, 0xAA, 0xD8, 0x05, 0x01, 0x12, 0xA3, 0x5F, 0xF9, 0xD0, 0x91, 0x58, 0x27, 0xB9, 0x38, 0x13, 0xB3, 0x33, ++0xBB, 0x70, 0x89, 0xA7, 0xB6, 0x22, 0x92, 0x20, 0x49, 0xFF, 0x78, 0x7A, 0x8F, 0xF8, 0x80, 0x17, 0xDA, 0x31, 0xC6, 0xB8, ++0xC3, 0xB0, 0x77, 0x11, 0xCB, 0xFC, 0xD6, 0x3A, 0x72, 0x63, 0x5F, 0x72, 0x73, 0x2D, 0x3E, 0x61, 0x74, 0x74, 0x65, 0x6D, ++0x70, 0x74, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x72, 0x73, 0x2D, 0x3E, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, ++0x73, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, 0x3D, 0x20, 0x46, 0x4F, ++0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, 0x45, 0x5F, 0x53, 0x55, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, ++0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, ++0x54, 0x5F, 0x4D, 0x46, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, ++0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x00, 0x00, 0x28, 0x66, 0x6F, 0x72, ++0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, ++0x5F, 0x48, 0x54, 0x5F, 0x4D, 0x46, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, ++0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, 0x54, 0x5F, 0x47, ++0x46, 0x29, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, ++0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x20, 0x7C, 0x7C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, ++0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, ++0x4F, 0x4E, 0x5F, 0x48, 0x54, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, ++0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x00, 0x28, 0x66, 0x6F, 0x72, ++0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, ++0x5F, 0x48, 0x45, 0x5F, 0x53, 0x55, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, ++0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, 0x4F, 0x4E, 0x5F, ++0x48, 0x54, 0x29, 0x00, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x00, ++0x73, 0x67, 0x69, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, ++0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, ++0x6D, 0x63, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, ++0x6D, 0x69, 0x6E, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, ++0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, ++0x5F, 0x6D, 0x61, 0x70, 0x5F, 0x6C, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, 0x54, 0x28, 0x6D, 0x63, 0x73, 0x29, ++0x29, 0x00, 0x00, 0x00, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, ++0x73, 0x67, 0x69, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x73, 0x68, 0x6F, 0x72, 0x74, 0x5F, ++0x67, 0x69, 0x00, 0x00, 0x62, 0x77, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, 0x77, 0x5F, ++0x6D, 0x61, 0x78, 0x00, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, ++0x5F, 0x73, 0x73, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, 0x63, ++0x73, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x00, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, ++0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x68, 0x74, 0x5B, 0x6E, 0x73, 0x73, 0x5D, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, ++0x54, 0x28, 0x6D, 0x63, 0x73, 0x29, 0x29, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x28, 0x37, 0x20, 0x2B, 0x20, ++0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, 0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x76, 0x68, 0x74, ++0x20, 0x3E, 0x3E, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3C, 0x20, 0x31, 0x29, 0x20, 0x26, 0x20, 0x4D, 0x41, 0x43, ++0x5F, 0x56, 0x48, 0x54, 0x5F, 0x4D, 0x43, 0x53, 0x5F, 0x4D, 0x41, 0x50, 0x5F, 0x4D, 0x53, 0x4B, 0x29, 0x29, 0x00, 0x00, ++0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x36, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, ++0x3D, 0x20, 0x42, 0x57, 0x5F, 0x38, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x28, 0x6E, 0x73, 0x73, ++0x20, 0x3D, 0x3D, 0x20, 0x33, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x36, 0x29, ++0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, ++0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, ++0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, ++0x73, 0x20, 0x21, 0x3D, 0x20, 0x35, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x28, 0x28, 0x6D, 0x63, ++0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, ++0x5F, 0x38, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x35, ++0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, ++0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x31, 0x36, 0x30, 0x4D, 0x48, 0x5A, 0x29, ++0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x32, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, ++0x00, 0x00, 0x00, 0x00, 0x67, 0x69, 0x20, 0x3C, 0x3D, 0x20, 0x32, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x28, ++0x37, 0x20, 0x2B, 0x20, 0x32, 0x20, 0x2A, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, ++0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x68, 0x65, 0x20, 0x3E, 0x3E, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3C, 0x20, 0x31, ++0x29, 0x20, 0x26, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x45, 0x5F, 0x4D, 0x43, 0x53, 0x5F, 0x4D, 0x41, 0x50, 0x5F, 0x4D, ++0x53, 0x4B, 0x29, 0x29, 0x00, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, 0x5F, 0x73, 0x61, ++0x6D, 0x70, 0x6C, 0x65, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, ++0x6F, 0x5F, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x52, 0x43, 0x5F, 0x4D, 0x41, 0x58, 0x5F, ++0x4E, 0x5F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, ++0x77, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x31, 0x36, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, ++0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, 0x5F, 0x73, 0x73, 0x20, 0x3C, 0x20, 0x38, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x74, 0x61, 0x2D, 0x3E, 0x73, 0x74, 0x61, 0x69, 0x64, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, ++0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, ++0x63, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x31, 0x32, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x52, 0x41, 0x54, 0x45, ++0x5F, 0x31, 0x31, 0x4D, 0x42, 0x50, 0x53, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, ++0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x29, 0x00, 0x00, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x52, 0x41, 0x54, 0x45, ++0x5F, 0x31, 0x31, 0x4D, 0x42, 0x50, 0x53, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, ++0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x29, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, ++0x63, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x31, 0x30, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, ++0x6F, 0x5F, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x33, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, ++0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, ++0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, 0x69, 0x64, 0x78, ++0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, ++0x45, 0x4E, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, 0x77, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3D, 0x3D, ++0x20, 0x42, 0x57, 0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x74, ++0x69, 0x6F, 0x6E, 0x5F, 0x69, 0x64, 0x3D, 0x25, 0x69, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, ++0x3D, 0x25, 0x69, 0x20, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x25, 0x69, 0x20, 0x73, 0x68, 0x6F, 0x72, ++0x74, 0x5F, 0x67, 0x69, 0x3D, 0x25, 0x69, 0x20, 0x6D, 0x61, 0x78, 0x5F, 0x62, 0x77, 0x3D, 0x25, 0x69, 0x0A, 0x00, 0x00, ++0x25, 0x73, 0x3A, 0x20, 0x6E, 0x73, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x6D, 0x63, 0x73, 0x5F, 0x6D, ++0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x3D, 0x25, 0x69, 0x20, 0x72, ++0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x6E, 0x6F, 0x5F, 0x73, 0x61, 0x6D, 0x70, 0x6C, ++0x65, 0x73, 0x3D, 0x25, 0x69, 0x0A, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x20, 0x7C, 0x9F, 0x00, ++0x20, 0xF3, 0xA0, 0x00, 0xA0, 0x17, 0x52, 0x00, 0xA0, 0x8E, 0x53, 0x00, 0xF8, 0x52, 0x23, 0x00, 0xF8, 0xC9, 0x24, 0x00, ++0x18, 0xF5, 0x15, 0x00, 0x18, 0x6C, 0x17, 0x00, 0xF9, 0x06, 0x11, 0x00, 0x62, 0x07, 0x12, 0x00, 0x35, 0x08, 0x14, 0x00, ++0xD1, 0x10, 0x04, 0x00, 0x0A, 0x4E, 0x04, 0x00, 0x7D, 0xC8, 0x04, 0x00, 0x7D, 0x83, 0x08, 0x00, 0xB1, 0x03, 0x09, 0x00, ++0x1A, 0x04, 0x0A, 0x00, 0x68, 0x08, 0x02, 0x00, 0x05, 0x27, 0x02, 0x00, 0x3F, 0x64, 0x02, 0x00, 0xFE, 0xAC, 0x05, 0x00, ++0x76, 0x02, 0x06, 0x00, 0x67, 0xAD, 0x06, 0x00, 0xF0, 0x5A, 0x01, 0x00, 0x59, 0x6F, 0x01, 0x00, 0x2A, 0x98, 0x01, 0x00, ++0xBE, 0x41, 0x04, 0x00, 0xD9, 0x81, 0x04, 0x00, 0x0D, 0x02, 0x05, 0x00, 0x34, 0x04, 0x01, 0x00, 0x83, 0x13, 0x01, 0x00, ++0x1F, 0x32, 0x01, 0x00, 0x7F, 0xD6, 0x02, 0x00, 0x3B, 0x01, 0x03, 0x00, 0xB3, 0x56, 0x03, 0x00, 0x78, 0xAD, 0x00, 0x00, ++0xAC, 0xB7, 0x00, 0x00, 0x15, 0xCC, 0x00, 0x00, 0xDF, 0x20, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, 0x07, 0x81, 0x02, 0x00, ++0x1A, 0x82, 0x00, 0x00, 0xC1, 0x89, 0x00, 0x00, 0x10, 0x99, 0x00, 0x00, 0x55, 0xE4, 0x01, 0x00, 0xD2, 0x00, 0x02, 0x00, ++0xCD, 0x39, 0x02, 0x00, 0xA5, 0x73, 0x00, 0x00, 0x73, 0x7A, 0x00, 0x00, 0x0E, 0x88, 0x00, 0x00, 0xE6, 0xB3, 0x01, 0x00, ++0x8A, 0xCD, 0x01, 0x00, 0xD2, 0x00, 0x02, 0x00, 0x15, 0x68, 0x00, 0x00, 0x34, 0x6E, 0x00, 0x00, 0x73, 0x7A, 0x00, 0x00, ++0x3F, 0x6B, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0x5A, 0xAB, 0x01, 0x00, 0xBC, 0x56, 0x00, 0x00, 0xD6, 0x5B, 0x00, 0x00, ++0x0A, 0x66, 0x00, 0x00, 0xEC, 0x46, 0x01, 0x00, 0x27, 0x5A, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0x11, 0x4E, 0x00, 0x00, ++0xA8, 0x52, 0x00, 0x00, 0xD7, 0x5B, 0x00, 0x00, 0x99, 0x22, 0x01, 0x00, 0xB1, 0x33, 0x01, 0x00, 0xE1, 0x55, 0x01, 0x00, ++0x63, 0x45, 0x00, 0x00, 0x78, 0x49, 0x00, 0x00, 0xA2, 0x51, 0x00, 0x00, 0x8A, 0x05, 0x01, 0x00, 0xEC, 0x14, 0x01, 0x00, ++0xB1, 0x33, 0x01, 0x00, 0x74, 0x3E, 0x00, 0x00, 0x21, 0x42, 0x00, 0x00, 0x7A, 0x49, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, ++0x3C, 0x5C, 0x29, 0x00, 0xB4, 0xF4, 0x2D, 0x00, 0x00, 0x88, 0x13, 0x00, 0x1E, 0xAE, 0x14, 0x00, 0x5A, 0xFA, 0x16, 0x00, ++0x55, 0x05, 0x0D, 0x00, 0x69, 0xC9, 0x0D, 0x00, 0x91, 0x51, 0x0F, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x0F, 0x57, 0x0A, 0x00, ++0x2D, 0x7D, 0x0B, 0x00, 0xAA, 0x82, 0x06, 0x00, 0xB4, 0xE4, 0x06, 0x00, 0xC8, 0xA8, 0x07, 0x00, 0x00, 0xE2, 0x04, 0x00, ++0x87, 0x2B, 0x05, 0x00, 0x96, 0xBE, 0x05, 0x00, 0x1C, 0x57, 0x04, 0x00, 0x78, 0x98, 0x04, 0x00, 0x30, 0x1B, 0x05, 0x00, ++0x00, 0xE8, 0x03, 0x00, 0xD2, 0x22, 0x04, 0x00, 0x78, 0x98, 0x04, 0x00, 0x55, 0x41, 0x03, 0x00, 0x5A, 0x72, 0x03, 0x00, ++0x64, 0xD4, 0x03, 0x00, 0x00, 0xEE, 0x02, 0x00, 0x1E, 0x1A, 0x03, 0x00, 0x5A, 0x72, 0x03, 0x00, 0xAA, 0x9A, 0x02, 0x00, ++0xE1, 0xC1, 0x02, 0x00, 0x50, 0x10, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x4B, 0x7B, 0x02, 0x00, 0xE1, 0xC1, 0x02, 0x00, ++0x00, 0x04, 0xA6, 0x00, 0x00, 0xC8, 0xAF, 0x00, 0x00, 0x50, 0xC3, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0xE4, 0x57, 0x00, ++0x00, 0xA8, 0x61, 0x00, 0xAA, 0x56, 0x37, 0x00, 0x00, 0x98, 0x3A, 0x00, 0xAA, 0x1A, 0x41, 0x00, 0x00, 0x81, 0x29, 0x00, ++0x00, 0xF2, 0x2B, 0x00, 0x00, 0xD4, 0x30, 0x00, 0x55, 0xAB, 0x1B, 0x00, 0x00, 0x4C, 0x1D, 0x00, 0x55, 0x8D, 0x20, 0x00, ++0x80, 0xC0, 0x14, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x38, 0x72, 0x12, 0x00, 0x00, 0x88, 0x13, 0x00, ++0x8E, 0xB3, 0x15, 0x00, 0x00, 0x9A, 0x10, 0x00, 0x00, 0x94, 0x11, 0x00, 0x00, 0x88, 0x13, 0x00, 0xAA, 0xD5, 0x0D, 0x00, ++0x00, 0xA6, 0x0E, 0x00, 0xAA, 0x46, 0x10, 0x00, 0x80, 0x73, 0x0C, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, 0xA6, 0x0E, 0x00, ++0x55, 0x11, 0x0B, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x55, 0x05, 0x0D, 0x00, 0x00, 0xF6, 0x09, 0x00, 0x00, 0x8C, 0x0A, 0x00, ++0x00, 0xB8, 0x0B, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, 0xA8, 0x61, 0x00, 0x00, 0x81, 0x29, 0x00, ++0x00, 0xF2, 0x2B, 0x00, 0x00, 0xD4, 0x30, 0x00, 0x55, 0xAB, 0x1B, 0x00, 0x00, 0x4C, 0x1D, 0x00, 0x55, 0x8D, 0x20, 0x00, ++0x80, 0xC0, 0x14, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x6A, 0x18, 0x00, 0xAA, 0xD5, 0x0D, 0x00, 0x00, 0xA6, 0x0E, 0x00, ++0xAA, 0x46, 0x10, 0x00, 0x40, 0x60, 0x0A, 0x00, 0x80, 0xFC, 0x0A, 0x00, 0x00, 0x35, 0x0C, 0x00, 0x1C, 0x39, 0x09, 0x00, ++0x00, 0xC4, 0x09, 0x00, 0xC7, 0xD9, 0x0A, 0x00, 0x00, 0x4D, 0x08, 0x00, 0x00, 0xCA, 0x08, 0x00, 0x00, 0xC4, 0x09, 0x00, ++0xD5, 0xEA, 0x06, 0x00, 0x00, 0x53, 0x07, 0x00, 0x55, 0x23, 0x08, 0x00, 0xC0, 0x39, 0x06, 0x00, 0x80, 0x97, 0x06, 0x00, ++0x00, 0x53, 0x07, 0x00, 0xAA, 0x88, 0x05, 0x00, 0x00, 0xDC, 0x05, 0x00, 0xAA, 0x82, 0x06, 0x00, 0x00, 0xFB, 0x04, 0x00, ++0x00, 0x46, 0x05, 0x00, 0x00, 0xDC, 0x05, 0x00, 0x3B, 0x89, 0x16, 0x00, 0x4F, 0x48, 0x14, 0x00, 0xC7, 0xD9, 0x0A, 0x00, ++0x00, 0xC4, 0x09, 0x00, 0x0D, 0x02, 0x05, 0x00, 0xD9, 0x81, 0x04, 0x00, 0x07, 0x81, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, ++0x9E, 0x44, 0x0B, 0x00, 0x27, 0x24, 0x0A, 0x00, 0xE4, 0x6C, 0x05, 0x00, 0x00, 0xE2, 0x04, 0x00, 0x07, 0x81, 0x02, 0x00, ++0xEC, 0x40, 0x02, 0x00, 0x83, 0x40, 0x01, 0x00, 0x76, 0x20, 0x01, 0x00, 0x14, 0x83, 0x07, 0x00, 0xC5, 0xC2, 0x06, 0x00, ++0xED, 0x9D, 0x03, 0x00, 0x55, 0x41, 0x03, 0x00, 0x5A, 0xAB, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0xAD, 0xD5, 0x00, 0x00, ++0x4F, 0xC0, 0x00, 0x00, 0x4F, 0xA2, 0x05, 0x00, 0x14, 0x12, 0x05, 0x00, 0x72, 0xB6, 0x02, 0x00, 0x00, 0x71, 0x02, 0x00, ++0x83, 0x40, 0x01, 0x00, 0x76, 0x20, 0x01, 0x00, 0x42, 0xA0, 0x00, 0x00, 0x3B, 0x90, 0x00, 0x00, 0x8A, 0xC1, 0x03, 0x00, ++0x62, 0x61, 0x03, 0x00, 0xF7, 0xCE, 0x01, 0x00, 0xAB, 0xA0, 0x01, 0x00, 0xAD, 0xD5, 0x00, 0x00, 0x4F, 0xC0, 0x00, 0x00, ++0xD6, 0x6A, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x27, 0xD1, 0x02, 0x00, 0x0A, 0x89, 0x02, 0x00, 0x39, 0x5B, 0x01, 0x00, ++0x80, 0x38, 0x01, 0x00, 0x42, 0xA0, 0x00, 0x00, 0x3B, 0x90, 0x00, 0x00, 0x21, 0x50, 0x00, 0x00, 0x1E, 0x48, 0x00, 0x00, ++0x07, 0x81, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, 0xA4, 0x34, 0x01, 0x00, 0xC7, 0x15, 0x01, 0x00, 0x73, 0x8E, 0x00, 0x00, ++0x35, 0x80, 0x00, 0x00, 0x3A, 0x47, 0x00, 0x00, 0x1A, 0x40, 0x00, 0x00, 0xEC, 0x40, 0x02, 0x00, 0x3B, 0x07, 0x02, 0x00, ++0xC7, 0x15, 0x01, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x35, 0x80, 0x00, 0x00, 0x62, 0x73, 0x00, 0x00, 0x1A, 0x40, 0x00, 0x00, ++0xB1, 0x39, 0x00, 0x00, 0xC5, 0xE0, 0x01, 0x00, 0xB1, 0xB0, 0x01, 0x00, 0x7B, 0xE7, 0x00, 0x00, 0x55, 0xD0, 0x00, 0x00, ++0xD6, 0x6A, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x6B, 0x35, 0x00, 0x00, 0x14, 0x30, 0x00, 0x00, 0xB1, 0xB0, 0x01, 0x00, ++0x6C, 0x85, 0x01, 0x00, 0x55, 0xD0, 0x00, 0x00, 0x80, 0xBB, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x8A, 0x56, 0x00, 0x00, ++0x14, 0x30, 0x00, 0x00, 0x45, 0x2B, 0x00, 0x00, 0x00, 0x6A, 0x18, 0x00, 0xE0, 0x4B, 0x10, 0x00, 0x00, 0x35, 0x0C, 0x00, ++0xC0, 0x2D, 0x08, 0x00, 0x80, 0x1A, 0x06, 0x00, 0xE0, 0x16, 0x04, 0x00, 0x40, 0x0D, 0x03, 0x00, 0x20, 0xBF, 0x02, 0x00, ++0x24, 0xCE, 0x15, 0x00, 0xB4, 0xCE, 0x15, 0x00, 0x94, 0xCD, 0x15, 0x00, 0xB8, 0xD0, 0x15, 0x00, 0x03, 0x00, 0x00, 0x00, ++0x00, 0x28, 0x00, 0x00, 0x39, 0x4B, 0x15, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x15, 0x4C, 0x15, 0x00, 0x01, 0x10, 0x00, 0x00, ++0xD5, 0x4B, 0x15, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x20, 0x3E, 0x3D, 0x20, 0x42, 0x43, 0x4E, 0x5F, 0x46, 0x49, 0x58, ++0x45, 0x44, 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x5F, 0x46, 0x49, 0x45, 0x4C, 0x44, 0x53, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, ++0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x62, 0x75, 0x66, 0x5F, 0x6C, 0x65, ++0x6E, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x73, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3E, 0x20, 0x30, 0x00, ++0x21, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x5F, 0x6D, 0x6F, 0x72, 0x65, 0x5F, 0x6D, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x5F, ++0x74, 0x6F, 0x5F, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x28, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x65, 0x71, 0x75, ++0x65, 0x73, 0x74, 0x2D, 0x3E, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x73, 0x65, 0x6E, 0x74, 0x20, 0x3D, 0x3D, 0x20, ++0x30, 0x29, 0x00, 0x00, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x6E, ++0x74, 0x20, 0x3C, 0x3D, 0x20, 0x43, 0x4F, 0x5F, 0x41, 0x52, 0x52, 0x41, 0x59, 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x28, 0x72, ++0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x29, 0x00, 0x00, ++0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, ++0x5F, 0x4D, 0x45, 0x41, 0x53, 0x5F, 0x52, 0x45, 0x51, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x45, 0x41, 0x43, 0x4F, ++0x4E, 0x00, 0x00, 0x00, 0x72, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x72, 0x65, ++0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x3E, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x64, 0x69, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, ++0x33, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x34, 0x37, 0x3A, 0x31, 0x34, 0x20, 0x2D, 0x20, 0x67, 0x37, ++0x34, 0x32, 0x30, 0x33, 0x31, 0x37, 0x31, 0x00, 0x76, 0x36, 0x2E, 0x34, 0x2E, 0x33, 0x2E, 0x31, 0x00, 0x00, 0x00, 0x00, ++0xF8, 0xB5, 0x00, 0xBF, 0xF8, 0xBC, 0x08, 0xBC, 0x9E, 0x46, 0x70, 0x47, 0xF8, 0xB5, 0x00, 0xBF, 0xF8, 0xBC, 0x08, 0xBC, ++0x9E, 0x46, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x74, 0x04, 0x17, 0x00, 0xDC, 0x04, 0x17, 0x00, 0x44, 0x05, 0x17, 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, 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, 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, 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, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x33, 0xCD, 0xAB, ++0x34, 0x12, 0x6D, 0xE6, 0xEC, 0xDE, 0x05, 0x00, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0E, 0x00, 0x00, 0x04, 0x0E, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x5B, ++0x4B, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x32, 0x7B, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, ++0x26, 0x00, 0x00, 0xF8, 0x11, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x19, 0x48, 0x20, 0x00, 0x00, 0x9C, 0x91, 0x01, 0x00, 0x08, ++0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x44, 0x10, 0x08, 0x00, 0x80, 0x01, 0x38, 0x41, 0x46, 0x00, 0x0C, ++0x14, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x3C, 0x1A, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x38, 0x01, 0x00, 0x00, 0x40, 0x1D, 0x00, 0x00, 0x08, ++0x8E, 0x00, 0x08, 0x38, 0x50, 0x00, 0x00, 0x14, 0x20, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x00, 0x40, 0x7B, 0x00, 0x00, 0xA4, ++0x01, 0x01, 0x00, 0x00, 0x9F, 0x33, 0x00, 0x30, 0x00, 0x07, 0x00, 0x41, 0x20, 0x44, 0x10, 0x04, 0x00, 0x00, 0x00, 0x90, ++0x00, 0x00, 0x00, 0x49, 0x2F, 0x84, 0x0E, 0xF0, 0x2C, 0x84, 0x0E, 0xEC, 0x2C, 0x84, 0x0E, 0xEC, 0x32, 0x00, 0x00, 0x04, ++0x00, 0x00, 0x00, 0x30, 0x01, 0x01, 0x00, 0x48, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x02, 0x02, 0x00, 0x48, ++0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x46, 0x11, 0x00, 0x00, 0x04, 0x06, 0x00, 0x01, 0x58, ++0x72, 0x04, 0x04, 0x3D, 0x39, 0x44, 0x20, 0xDC, 0xD2, 0xD4, 0x1D, 0x08, 0x06, 0x00, 0x0A, 0x48, 0xDC, 0x44, 0x20, 0xDC, ++0x3C, 0xD4, 0x1D, 0x08, 0x04, 0x00, 0x05, 0x38, 0xC3, 0xF1, 0xF1, 0x0E, 0xDC, 0x44, 0x20, 0x34, 0x00, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, 0x45, 0x44, 0x10, 0x04, ++0x00, 0x80, 0x00, 0x38, 0x9C, 0x10, 0x00, 0x22, 0x48, 0x44, 0x10, 0x08, 0x00, 0x80, 0x00, 0x38, 0x9C, 0x50, 0xD4, 0x23, ++0x17, 0x44, 0x10, 0x08, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x00, 0x00, 0x32, 0x63, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x14, ++0x51, 0x00, 0x00, 0x1C, 0x57, 0x00, 0x00, 0x10, 0x00, 0x80, 0x02, 0x38, 0x01, 0x00, 0x00, 0x0C, 0x66, 0x44, 0xD0, 0x08, ++0x0F, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x38, 0x01, 0x26, 0x00, 0x0C, ++0x5A, 0x44, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x30, 0x30, 0x02, 0x02, 0x3D, 0x5D, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, ++0x00, 0x01, 0x00, 0x3E, 0x66, 0x00, 0x00, 0x04, 0x00, 0x80, 0x02, 0x38, 0x01, 0x16, 0x00, 0x0C, 0x66, 0x44, 0x20, 0x34, ++0x00, 0x80, 0x02, 0x38, 0x01, 0x0A, 0x00, 0x0C, 0x66, 0x44, 0x20, 0x34, 0x04, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, ++0x7B, 0x00, 0x00, 0x08, 0x2F, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0x26, 0x6C, 0x00, 0x00, 0x08, 0xAF, 0x04, 0x04, 0x38, ++0x10, 0x10, 0x19, 0x1F, 0x6F, 0x00, 0x00, 0x08, 0xAF, 0x0C, 0x00, 0x20, 0x71, 0x00, 0x00, 0x04, 0xAF, 0x0C, 0x00, 0x60, ++0x79, 0x00, 0x70, 0x18, 0x77, 0x00, 0x00, 0x14, 0x75, 0x00, 0x00, 0x10, 0xAF, 0x0C, 0x14, 0x28, 0x84, 0x00, 0xB0, 0x09, ++0xAF, 0x0C, 0x0A, 0x28, 0x84, 0x00, 0xB0, 0x09, 0xAF, 0x0C, 0x06, 0x28, 0x84, 0x00, 0xB0, 0x09, 0x86, 0x80, 0x04, 0x28, ++0x7D, 0x00, 0x00, 0x08, 0x86, 0x00, 0x00, 0x38, 0x00, 0x00, 0x80, 0x22, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, ++0x01, 0xF1, 0xF1, 0x0E, 0x83, 0x48, 0x00, 0x36, 0x00, 0x00, 0x02, 0x28, 0x85, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x02, 0x38, ++0x31, 0x04, 0x04, 0x3D, 0x88, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x05, 0x38, 0x21, 0x18, 0x24, 0x1F, 0x8B, 0x00, 0x00, 0x08, ++0x8E, 0x00, 0x00, 0x30, 0x21, 0x30, 0x16, 0xA0, 0x8E, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x12, 0x00, 0xF1, 0x0E, ++0x91, 0x00, 0x00, 0x34, 0xCC, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x50, 0x94, 0x00, 0x00, 0x04, 0xFE, 0x95, 0x00, 0x38, ++0x00, 0x00, 0x01, 0x32, 0x97, 0x00, 0x00, 0x04, 0xFE, 0x1F, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5A, 0x9B, 0x98, 0xC9, 0x6D, ++0xB9, 0xD4, 0x19, 0xFC, 0x86, 0x01, 0x00, 0x30, 0x73, 0x03, 0x84, 0x3D, 0x9E, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x0A, 0xA1, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x00, 0xC0, 0x22, 0xA4, 0x00, 0x00, 0x04, ++0x8E, 0x02, 0x00, 0x90, 0x01, 0x00, 0x01, 0x32, 0xAA, 0x00, 0x40, 0x8E, 0xB0, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x30, 0x01, 0x00, 0x01, 0x32, 0xCB, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x01, 0x32, 0xB3, 0x00, 0x00, 0x04, ++0xB6, 0x19, 0x00, 0x30, 0x31, 0x04, 0x04, 0x3D, 0xB6, 0x00, 0x00, 0x04, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x80, 0x22, ++0x97, 0x00, 0x00, 0x04, 0x86, 0x01, 0x00, 0x30, 0x73, 0x04, 0x84, 0x3D, 0xBC, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x03, 0x29, 0xBF, 0x00, 0x00, 0x04, 0x8E, 0x02, 0xEE, 0x9A, 0x00, 0x01, 0x01, 0x32, 0xC5, 0x00, 0x00, 0x7C, ++0xB0, 0x00, 0x00, 0xCC, 0xB0, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x01, 0x01, 0x32, ++0xC8, 0x00, 0x00, 0x04, 0x8E, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x8E, 0x03, 0x00, 0x50, ++0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x35, 0x00, 0x00, 0xC0, 0x06, 0x00, 0x01, 0x38, 0x72, 0x04, 0x04, 0x3D, ++0xD2, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x30, 0x41, 0xF1, 0xF1, 0x0E, 0xD5, 0x00, 0x00, 0x34, 0x04, 0x00, 0x04, 0x28, ++0xD7, 0x00, 0x00, 0x08, 0x0E, 0x00, 0x08, 0x28, 0xD9, 0x00, 0x00, 0x08, 0x8E, 0x01, 0x00, 0x30, 0x52, 0x00, 0xF1, 0x0E, ++0xDC, 0x00, 0x00, 0x34, 0x8E, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x00, 0x00, 0x02, 0x38, ++0x00, 0x00, 0x00, 0x32, 0xE2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x60, 0xE6, 0x00, 0x00, 0xD8, 0xE9, 0x00, 0x00, 0xD4, ++0xEC, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x21, 0xF1, 0xF1, 0x0E, 0xEF, 0x48, 0x00, 0x36, 0x00, 0x00, 0x00, 0x30, ++0x21, 0x24, 0x00, 0x0C, 0xEF, 0x48, 0x00, 0x36, 0x00, 0x00, 0x00, 0x30, 0x21, 0x00, 0x00, 0x0C, 0xEF, 0x48, 0x00, 0x36, ++0x00, 0x00, 0x02, 0x28, 0x7B, 0x00, 0x00, 0x08, 0xFE, 0x1E, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5A, 0xF5, 0x98, 0xC9, 0x6D, ++0xF8, 0xD4, 0x19, 0xFC, 0x8E, 0x02, 0x00, 0x30, 0x40, 0x00, 0x00, 0x32, 0xFB, 0x00, 0x00, 0x04, 0x8E, 0x02, 0xEE, 0x3A, ++0x80, 0x00, 0x00, 0x32, 0xFB, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x01, 0xF1, 0xF1, 0x0E, 0xFE, 0x48, 0x00, 0x36, ++0x00, 0x00, 0x02, 0x28, 0x00, 0x01, 0x00, 0x08, 0x8E, 0x00, 0x02, 0x38, 0x31, 0x04, 0x04, 0x3D, 0x03, 0x01, 0x00, 0x08, ++0x8E, 0x00, 0x05, 0x38, 0x21, 0x18, 0x24, 0x1F, 0x06, 0x01, 0x00, 0x08, 0x8E, 0x00, 0x00, 0x30, 0x21, 0x30, 0x16, 0xA0, ++0x09, 0x01, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x12, 0x00, 0xF1, 0x0E, 0x0C, 0x01, 0x00, 0x34, 0xF6, 0x14, 0x00, 0x30, ++0x00, 0x00, 0x01, 0x32, 0x14, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x11, 0x01, 0x00, 0x04, 0xEC, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x50, 0xF1, 0x00, 0x00, 0x04, 0xF6, 0x14, 0x00, 0x30, 0x00, 0x00, 0x03, 0x32, 0x17, 0x01, 0x00, 0x04, ++0x86, 0x10, 0x00, 0x30, 0x73, 0x04, 0x84, 0x3D, 0x1A, 0x01, 0x00, 0x04, 0x8E, 0x10, 0x00, 0x50, 0x00, 0x00, 0xC0, 0x22, ++0xCB, 0xC0, 0x47, 0x8E, 0x1E, 0x01, 0x30, 0xCB, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x04, 0x32, 0x21, 0x01, 0x00, 0x04, ++0xB6, 0x19, 0x00, 0x30, 0x31, 0x04, 0x04, 0x3D, 0x24, 0x01, 0x00, 0x04, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x80, 0x22, ++0x11, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, 0x30, ++0x73, 0x04, 0x84, 0x3D, 0x2D, 0x01, 0x00, 0x04, 0x8E, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, ++0x31, 0x01, 0x00, 0xC0, 0x0E, 0x80, 0x0C, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x34, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x30, ++0x03, 0xF1, 0xF1, 0x0F, 0x37, 0x01, 0x00, 0x34, 0x00, 0x00, 0x02, 0x28, 0x39, 0x01, 0x00, 0x08, 0x8E, 0x03, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x06, 0x00, 0x01, 0x58, 0x72, 0x04, 0x04, 0x3D, 0x43, 0x45, 0x20, 0xDC, 0xD2, 0xD4, 0x1D, 0x08, 0x06, 0x00, 0x0A, 0x48, ++0xDC, 0x44, 0x20, 0xDC, 0x46, 0xD5, 0x1D, 0x08, 0x04, 0x00, 0x05, 0x38, 0x41, 0xF1, 0xF1, 0x0E, 0xDC, 0x44, 0x20, 0x34, ++0x0E, 0x80, 0x02, 0x28, 0xDC, 0x00, 0x00, 0x08, 0x35, 0x00, 0x00, 0x48, 0x4A, 0x01, 0x00, 0x04, 0x8F, 0x63, 0x96, 0x78, ++0x0F, 0x00, 0x00, 0x41, 0x4F, 0x01, 0x00, 0x8C, 0xC4, 0x50, 0x04, 0x08, 0x74, 0x45, 0x10, 0x90, 0x0F, 0x62, 0xC8, 0x88, ++0x5A, 0x01, 0x00, 0xC0, 0x74, 0x45, 0x10, 0x90, 0x54, 0x45, 0x10, 0x08, 0x57, 0x45, 0x10, 0x94, 0x8F, 0x62, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x29, 0x7A, 0x51, 0x04, 0x94, 0x8F, 0x63, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x7A, 0x45, 0x10, 0x04, ++0x05, 0xE0, 0x00, 0x38, 0x31, 0x01, 0x01, 0x3D, 0x5D, 0x45, 0x10, 0x08, 0x0F, 0x60, 0x32, 0xA8, 0x74, 0x45, 0x10, 0x90, ++0x54, 0x01, 0x00, 0x08, 0x57, 0x45, 0x10, 0x94, 0x67, 0x45, 0x10, 0xC6, 0x63, 0x55, 0x18, 0xC4, 0x0F, 0xE0, 0x02, 0x58, ++0x07, 0xEA, 0xEE, 0x0F, 0x74, 0x01, 0x00, 0x80, 0x6B, 0x45, 0x20, 0x34, 0x0F, 0xE0, 0x02, 0x58, 0x07, 0xEA, 0xEE, 0x0E, ++0x74, 0x01, 0x00, 0x80, 0x6B, 0x45, 0x20, 0x34, 0x00, 0x40, 0x00, 0x30, 0x01, 0x00, 0x00, 0x33, 0x6E, 0x01, 0x00, 0x04, ++0x05, 0x40, 0x03, 0x38, 0x73, 0x03, 0x03, 0x3D, 0x71, 0x01, 0x00, 0x08, 0x07, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, ++0x74, 0x01, 0x00, 0x04, 0x8F, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x77, 0x51, 0x04, 0x94, 0x8F, 0x60, 0x00, 0x40, ++0x7D, 0x45, 0x10, 0xA0, 0x7A, 0x45, 0x10, 0x04, 0x8F, 0x60, 0x00, 0x30, 0x01, 0x01, 0x00, 0x64, 0x11, 0x44, 0x10, 0x04, ++0x8F, 0x60, 0x00, 0x30, 0x01, 0x01, 0x00, 0x64, 0x80, 0x45, 0x10, 0x04, 0x8F, 0x61, 0x00, 0x30, 0x01, 0x00, 0x00, 0x42, ++0x83, 0x01, 0x00, 0x04, 0x00, 0x80, 0x02, 0x38, 0x00, 0x00, 0x00, 0x32, 0x86, 0x45, 0x10, 0x08, 0x8F, 0x61, 0x0A, 0x28, ++0x88, 0x01, 0x00, 0x08, 0x8F, 0x61, 0x0A, 0x48, 0x8B, 0x01, 0x00, 0xBC, 0x8E, 0x01, 0x00, 0x08, 0x8F, 0x61, 0x00, 0x30, ++0x01, 0x00, 0x00, 0x34, 0x05, 0x00, 0x00, 0x04, 0x8F, 0x61, 0x00, 0x30, 0x00, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00, 0x04, ++0x8F, 0x00, 0x00, 0x30, 0x0F, 0xED, 0xEA, 0x0E, 0x94, 0x01, 0x00, 0x36, 0x00, 0x80, 0x03, 0x38, 0x00, 0x00, 0x00, 0x34, ++0x97, 0x01, 0x00, 0x08, 0x05, 0x80, 0x02, 0x38, 0x02, 0x00, 0x01, 0x29, 0x9A, 0x01, 0x00, 0x08, 0x8F, 0x02, 0x00, 0x30, ++0x9C, 0x20, 0x00, 0x22, 0x9D, 0x01, 0x00, 0x04, 0x8F, 0x02, 0x00, 0x30, 0x9C, 0x50, 0xD4, 0x23, 0xA0, 0x01, 0x00, 0x04, ++0x8F, 0x02, 0x14, 0x28, 0xA2, 0x01, 0x00, 0x08, 0x8F, 0x02, 0x00, 0x30, 0x01, 0x02, 0x01, 0x43, 0xA5, 0x01, 0x00, 0x04, ++0x8F, 0x12, 0x00, 0x30, 0x00, 0x01, 0x00, 0x32, 0xA8, 0x01, 0x00, 0x04, 0x8F, 0x13, 0xEE, 0x5A, 0x0F, 0x00, 0x00, 0x41, ++0xAC, 0x01, 0x00, 0x7C, 0xF9, 0x00, 0x00, 0x08, 0x8F, 0x13, 0x2C, 0x59, 0x00, 0x00, 0x00, 0x29, 0xB0, 0x01, 0x00, 0x8C, ++0xF9, 0x00, 0x00, 0x08, 0x8F, 0x13, 0x00, 0x20, 0x11, 0x50, 0x04, 0x94, 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, 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, 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, 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, ++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, 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, 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, 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, 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, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x76, 0x76, 0x00, 0x70, 0xF8, 0xF8, 0x1D, ++0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x72, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xF8, 0x1D, ++0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x7B, 0x76, 0x76, 0x00, 0x70, 0xF8, 0xF8, 0x1D, ++0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x85, 0x7E, 0x7E, 0x00, 0x76, 0xF8, 0xF4, 0x1D, ++0x76, 0xF8, 0xF4, 0x1D, 0x76, 0xF8, 0xF4, 0x1D, 0x76, 0xF8, 0xF8, 0x1D, 0x8A, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x8D, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x8A, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7C, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x40, 0x7E, 0x7E, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x92, 0x8B, 0x8B, 0x00, 0x87, 0xF8, 0xF8, 0x1D, ++0x89, 0xF8, 0xF8, 0x1D, 0x87, 0xF8, 0xF8, 0x1D, 0x87, 0xF8, 0xF8, 0x1D, 0x55, 0x51, 0x51, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x89, 0xF8, 0xF8, 0x1D, 0x89, 0xF8, 0xF8, 0x1D, 0x54, 0x51, 0x51, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x88, 0xF8, 0xF8, 0x1D, 0x88, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4E, 0x4E, 0x00, 0x49, 0xF8, 0xF8, 0x1D, ++0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x52, 0x4D, 0x4D, 0x00, 0x47, 0xF8, 0xF8, 0x1D, ++0x47, 0xF8, 0xF8, 0x1D, 0x47, 0xF8, 0xF8, 0x1D, 0x47, 0xF8, 0xF8, 0x1D, 0x55, 0x4F, 0x4F, 0x00, 0x4B, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4E, 0x4E, 0x00, 0x49, 0xF8, 0xF8, 0x1D, ++0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x4D, 0x49, 0x49, 0x00, 0x44, 0xF8, 0xF8, 0x1D, ++0x44, 0xF8, 0xF8, 0x1D, 0x44, 0xF8, 0xF8, 0x1D, 0x44, 0xF8, 0xF8, 0x1D, 0x8F, 0x51, 0x51, 0x00, 0x49, 0xF8, 0xF8, 0x1D, ++0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x77, 0x42, 0x42, 0x00, 0x3F, 0xF8, 0xF8, 0x1D, ++0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x75, 0x42, 0x42, 0x00, 0x9E, 0xF8, 0xF8, 0x1D, ++0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x5C, 0x55, 0x55, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x5C, 0x53, 0x53, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4B, 0xF8, 0xF8, 0x1D, 0x4B, 0xF8, 0xF8, 0x1D, 0x4B, 0xF8, 0xF8, 0x1D, 0x9E, 0xF8, 0xF8, 0x00, 0x8C, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x40, 0x89, 0x89, 0x00, 0x46, 0xF8, 0xF8, 0x18, ++0x45, 0xF8, 0xCF, 0x18, 0x44, 0xF8, 0xCF, 0x18, 0x44, 0xF8, 0xCF, 0x18, 0x5F, 0x56, 0x56, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, ++0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x5E, 0x55, 0x55, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x5F, 0x56, 0x56, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, ++0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x61, 0x55, 0x55, 0x00, 0x50, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x5F, 0x53, 0x53, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x5F, 0x55, 0x55, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0xAA, 0x55, 0x55, 0x00, 0x54, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0xA6, 0x59, 0x59, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x9B, 0x4F, 0x4F, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, ++0x46, 0xF8, 0xF8, 0x1D, 0x46, 0xF8, 0xF8, 0x1D, 0x46, 0xF8, 0xF8, 0x1D, 0xA5, 0xF8, 0xF8, 0x00, 0x94, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0xA4, 0x98, 0x98, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x86, 0x46, 0x46, 0x00, 0xB3, 0xF8, 0xF8, 0x1D, ++0x3D, 0xF8, 0xF8, 0x1D, 0x3D, 0xF8, 0xF8, 0x1D, 0x3D, 0xF8, 0xF8, 0x1D, 0x40, 0x8E, 0x8E, 0x00, 0x48, 0xF8, 0xF8, 0x1A, ++0x48, 0xF8, 0xDF, 0x1A, 0x46, 0xF8, 0xDF, 0x1A, 0x46, 0xF8, 0xDF, 0x1A, 0x40, 0x7F, 0x7F, 0x00, 0x75, 0xD2, 0xD2, 0x18, ++0x3A, 0xD2, 0xD2, 0x18, 0x3A, 0xD2, 0xD2, 0x18, 0x39, 0xD2, 0xD2, 0x18, 0x40, 0x45, 0x45, 0x00, 0x64, 0x86, 0x86, 0x0F, ++0x3E, 0x86, 0x86, 0x0F, 0x3D, 0x86, 0x86, 0x0F, 0x3D, 0x86, 0x86, 0x0F, 0x64, 0x5C, 0x5C, 0x00, 0x56, 0xF8, 0xF8, 0x1D, ++0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x68, 0x5B, 0x5B, 0x00, 0x58, 0xF8, 0xF8, 0x1D, ++0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x64, 0x5A, 0x5A, 0x00, 0x55, 0xF8, 0xF8, 0x1D, ++0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0xB5, 0x5A, 0x5A, 0x00, 0x5B, 0xF8, 0xF8, 0x1D, ++0x55, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0xB0, 0xF8, 0xF8, 0x00, 0xA3, 0xF8, 0xF8, 0x1D, ++0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0xAE, 0xA4, 0xA4, 0x00, 0x54, 0xF8, 0xF8, 0x1D, ++0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x40, 0x9A, 0x9A, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, ++0x4D, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x40, 0x9C, 0x9C, 0x00, 0x95, 0xF8, 0xF8, 0x1D, ++0x49, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x40, 0x49, 0x49, 0x00, 0x6F, 0x97, 0x97, 0x11, ++0x42, 0x97, 0x97, 0x11, 0x41, 0x97, 0x97, 0x11, 0x41, 0x97, 0x97, 0x11, 0x74, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xF8, 0x1D, ++0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x40, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xDE, 0x1A, ++0x69, 0xF8, 0xDE, 0x1A, 0x69, 0xF8, 0xDE, 0x1A, 0x69, 0xF8, 0xDE, 0x1A, 0x40, 0x75, 0x75, 0x00, 0x6E, 0xF8, 0x78, 0x0D, ++0x6E, 0xF8, 0x78, 0x0D, 0x6E, 0xF8, 0x78, 0x0D, 0x6E, 0xF8, 0x79, 0x0D, 0x85, 0x78, 0x78, 0x00, 0x73, 0xF8, 0xF8, 0x1D, ++0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x40, 0x78, 0x78, 0x00, 0x73, 0xF8, 0xF8, 0x1D, ++0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x40, 0x78, 0x78, 0x00, 0x73, 0xF8, 0x81, 0x0E, ++0x73, 0xF8, 0x81, 0x0E, 0x73, 0xF8, 0x81, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x40, 0x40, 0x40, 0x00, 0x73, 0xF8, 0x82, 0x0E, ++0x73, 0xF8, 0x82, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x40, 0x81, 0x81, 0x00, 0x7E, 0xF8, 0x92, 0x10, ++0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x40, 0x40, 0x40, 0x00, 0x7E, 0xF8, 0x92, 0x10, ++0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x40, 0x73, 0x73, 0x00, 0x6B, 0xB2, 0xB2, 0x14, ++0x35, 0xB2, 0xB2, 0x14, 0x35, 0xB2, 0xB2, 0x14, 0x35, 0xB2, 0xB2, 0x14, 0x40, 0x40, 0x40, 0x00, 0x60, 0x82, 0x82, 0x0E, ++0x3D, 0x82, 0x82, 0x0E, 0x3C, 0x82, 0x82, 0x0E, 0x3C, 0x82, 0x82, 0x0E, 0x40, 0x40, 0x40, 0x00, 0x66, 0x8B, 0x8B, 0x0F, ++0x3F, 0x8B, 0x8B, 0x0F, 0x3D, 0x8B, 0x8B, 0x0F, 0x3D, 0x8B, 0x8B, 0x0F, 0x40, 0x40, 0x40, 0x00, 0x3D, 0x68, 0x68, 0x0B, ++0x1E, 0x68, 0x68, 0x0B, 0x1E, 0x68, 0x68, 0x0B, 0x1E, 0x68, 0x68, 0x0B, 0x40, 0x22, 0x22, 0x00, 0x18, 0x43, 0x43, 0x06, ++0x29, 0x43, 0x43, 0x06, 0x18, 0x43, 0x43, 0x06, 0x18, 0x43, 0x43, 0x06, 0x40, 0x40, 0x40, 0x00, 0x72, 0x9D, 0x9D, 0x12, ++0x43, 0x9D, 0x9D, 0x12, 0x41, 0x9D, 0x9D, 0x12, 0x41, 0x9D, 0x9D, 0x12, 0x40, 0x40, 0x40, 0x00, 0x42, 0x75, 0x75, 0x0D, ++0x20, 0x75, 0x75, 0x0D, 0x20, 0x75, 0x75, 0x0D, 0x20, 0x75, 0x75, 0x0D, 0x40, 0x23, 0x23, 0x00, 0x19, 0x4C, 0x4C, 0x08, ++0x2C, 0x4C, 0x4C, 0x08, 0x19, 0x4C, 0x4C, 0x08, 0x19, 0x4C, 0x4C, 0x08, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, ++0xB8, 0xC8, 0xD8, 0xF8, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0x08, 0x58, 0x68, 0x78, 0x88, ++0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, 0x09, 0x01, 0x03, 0x1E, 0x00, 0x00, 0x75, 0x19, 0x03, 0x00, 0x75, 0x19, 0x03, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x04, 0x62, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, ++0x61, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x60, 0x23, 0x8D, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x60, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0xB4, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xE3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x84, 0x60, 0xC3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, ++0x60, 0xCB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xB3, 0x0C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0x1B, 0x0F, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xA2, 0x3E, 0x2A, 0x00, ++0xB5, 0x5A, 0x3F, 0x04, 0x60, 0x9B, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, ++0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3F, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0xD8, 0x3F, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, ++0x62, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x61, 0x03, 0x8D, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x60, 0x23, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x58, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x60, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0xB4, 0x2E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x44, 0x60, 0xE3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, ++0x60, 0xC3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x60, 0xCB, 0x0C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xB3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x2A, 0x00, ++0xB5, 0x5A, 0x2F, 0x44, 0x60, 0x1B, 0x0F, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xA2, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x04, ++0x60, 0x9B, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x58, 0x2F, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0xD8, 0x2F, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, ++0x6C, 0x00, 0x0F, 0x03, 0x60, 0xE7, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0x2F, 0x03, ++0x60, 0xD7, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0xEF, 0x03, 0x60, 0x9F, 0x0D, 0xE8, ++0x80, 0x80, 0x80, 0x80, 0x6D, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0xEF, 0x83, 0x60, 0x9F, 0x0D, 0xE8, 0x80, 0x80, 0x80, 0x80, ++0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, ++0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x2F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, ++0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x44, ++0x70, 0xE3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x63, 0x8C, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0x03, 0x11, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x43, 0x8D, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, ++0xB4, 0x00, 0x19, 0x44, 0x70, 0xE3, 0x10, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0xC4, ++0x70, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0xB4, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0xC3, 0x8C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x03, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0xEB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xB9, 0x00, ++0xB4, 0x00, 0x19, 0x84, 0x70, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x84, ++0x70, 0xF3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x84, 0x70, 0x3B, 0x0D, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0xB4, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x44, 0x70, 0xBB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0xEB, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0xAA, 0x00, ++0xB5, 0x5A, 0x39, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3F, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x04, ++0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0xE3, 0xAC, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x70, 0x63, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0x03, 0x11, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x84, 0x70, 0x43, 0x8D, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, ++0x70, 0xE3, 0x10, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x70, 0xE3, 0x0C, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0xB4, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0xC3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x46, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x70, 0x03, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0xB9, 0x00, ++0xB4, 0x00, 0x0F, 0x44, 0x70, 0xEB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x84, ++0x70, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x84, 0x70, 0xF3, 0x0C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x84, 0x70, 0x3B, 0x0D, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0xB4, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x70, 0xBB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x2E, 0xAA, 0x00, ++0xB5, 0x5A, 0x2F, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x2F, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x04, ++0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x2F, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x04, 0x70, 0xFB, 0x11, 0x0E, ++0x7F, 0xC1, 0x9F, 0x00, 0x0A, 0x01, 0x82, 0x00, 0x0C, 0x81, 0x82, 0x00, 0x10, 0x81, 0x82, 0x00, 0x10, 0x01, 0x83, 0x00, ++0x16, 0x01, 0x83, 0x00, 0x16, 0x01, 0x84, 0x00, 0x60, 0x01, 0x84, 0x00, 0x67, 0x01, 0x93, 0x00, 0x67, 0x41, 0x99, 0x00, ++0x7F, 0x41, 0x99, 0x00, 0x7F, 0xC1, 0x99, 0x00, 0x7F, 0x81, 0x9A, 0x00, 0x7F, 0x81, 0x9B, 0x00, 0x3F, 0xC1, 0x9C, 0x00, ++0x3F, 0xC1, 0x8F, 0x00, 0x08, 0x01, 0x82, 0x00, 0x0A, 0x01, 0x82, 0x00, 0x0C, 0x81, 0x82, 0x00, 0x10, 0x81, 0x82, 0x00, ++0x10, 0x01, 0x83, 0x00, 0x16, 0x01, 0x83, 0x00, 0x16, 0x01, 0x84, 0x00, 0x20, 0x01, 0x84, 0x00, 0x20, 0x01, 0x85, 0x00, ++0x20, 0x01, 0x8C, 0x00, 0x27, 0x81, 0x8C, 0x00, 0x27, 0x01, 0x8E, 0x00, 0x27, 0x01, 0x9B, 0x00, 0x3F, 0x01, 0x9B, 0x00, ++0x3F, 0xC1, 0x9C, 0x00, 0x3F, 0xC1, 0x8F, 0x00, 0x00, 0xC6, 0xFF, 0x00, 0x00, 0xC6, 0x40, 0x00, 0x00, 0x06, 0x41, 0x00, ++0x00, 0x46, 0x41, 0x00, 0x00, 0x86, 0x90, 0x00, 0x00, 0xC6, 0x90, 0x00, 0x00, 0x06, 0xB1, 0x00, 0x00, 0x46, 0xB1, 0x00, ++0x00, 0x86, 0xB1, 0x00, 0x00, 0x06, 0xB2, 0x00, 0x00, 0xC6, 0xB2, 0x00, 0x00, 0x46, 0xB9, 0x00, 0x00, 0xC6, 0xB9, 0x00, ++0x00, 0x46, 0xBA, 0x00, 0x00, 0x46, 0xBB, 0x00, 0x00, 0xC6, 0xBC, 0x00, 0x82, 0x01, 0x83, 0x01, 0x40, 0x02, 0x41, 0x02, ++0x80, 0x02, 0x81, 0x02, 0x82, 0x02, 0x83, 0x02, 0x40, 0x03, 0x41, 0x03, 0x80, 0x03, 0x81, 0x03, 0x00, 0x04, 0x01, 0x04, ++0x40, 0x04, 0x41, 0x04, 0x60, 0x60, 0x00, 0x00, 0x3B, 0x18, 0xB3, 0x03, 0x68, 0x51, 0x2E, 0x1A, 0x48, 0x51, 0x2E, 0x1A, ++0x00, 0x00, 0x00, 0x00, 0x84, 0x18, 0x20, 0x56, 0x84, 0x18, 0x20, 0x56, 0x00, 0x00, 0x00, 0x00, 0x08, 0x50, 0x2A, 0x7A, ++0xC8, 0x50, 0x1B, 0x79, 0xC8, 0xD0, 0x2A, 0x7A, 0x40, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x64, 0x32, 0x00, 0x00, ++0x00, 0x87, 0x93, 0x03, 0x00, 0x20, 0x03, 0x00, 0x00, 0x20, 0x03, 0x00, 0x30, 0x75, 0x00, 0x00, 0xB0, 0xAD, 0x01, 0x00, ++0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x10, 0x27, 0x00, 0x00, ++0x40, 0x0D, 0x03, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x27, 0x50, 0xC3, 0xA0, 0x0F, 0x40, 0x1F, 0x84, 0x03, 0x05, 0x08, ++0x01, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x1A, 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x1A, 0x00, 0xE0, 0x57, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, ++0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x19, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x19, 0x00, 0xF4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0xE0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x71, 0x04, 0x00, 0x10, 0x0E, 0x00, ++0x03, 0x01, 0x08, 0x8F, 0x03, 0xE6, 0xE0, 0xD0, 0xD6, 0x06, 0xD6, 0x06, 0x00, 0x00, 0x01, 0xF3, 0x01, 0x0A, 0x00, 0x0F, ++0x08, 0x01, 0x09, 0x08, 0x08, 0x08, 0x08, 0x0A, 0x09, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ++0x03, 0x01, 0x00, 0x00, 0xBC, 0x06, 0x04, 0x04, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, 0x0A, 0x02, 0x04, ++0x01, 0x00, 0xF0, 0x00, 0x08, 0x04, 0x00, 0x04, 0x04, 0x04, 0x09, 0x06, 0x04, 0x01, 0x04, 0x01, 0x05, 0x14, 0x38, 0x01, ++0x38, 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, ++0x7D, 0xA6, 0x12, 0x00, 0x91, 0xA1, 0x12, 0x00, 0xA5, 0xA6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x99, 0xA1, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xA1, 0x12, 0x00, 0xD1, 0xA1, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xA3, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x6D, 0x12, 0x00, 0x88, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, ++0x05, 0xC7, 0x12, 0x00, 0xE1, 0xB8, 0x14, 0x00, 0x75, 0xBB, 0x14, 0x00, 0x2D, 0xBE, 0x14, 0x00, 0xE9, 0xBC, 0x14, 0x00, ++0x81, 0xBC, 0x14, 0x00, 0x29, 0xAC, 0x14, 0x00, 0xFD, 0x0C, 0x15, 0x00, 0x1D, 0x0B, 0x15, 0x00, 0x6D, 0x08, 0x15, 0x00, ++0x0D, 0x07, 0x15, 0x00, 0x59, 0xC8, 0x13, 0x00, 0xF5, 0xE7, 0x13, 0x00, 0xA1, 0xCE, 0x13, 0x00, 0x3D, 0xD1, 0x13, 0x00, ++0x4D, 0xD0, 0x13, 0x00, 0xF9, 0xD0, 0x13, 0x00, 0x05, 0xDD, 0x13, 0x00, 0xF1, 0xDD, 0x13, 0x00, 0x95, 0xDE, 0x13, 0x00, ++0x85, 0xE4, 0x13, 0x00, 0xF5, 0xE0, 0x13, 0x00, 0xC1, 0xE3, 0x13, 0x00, 0xED, 0xCE, 0x13, 0x00, 0x59, 0xD6, 0x13, 0x00, ++0xF5, 0xD9, 0x13, 0x00, 0x3D, 0xD5, 0x13, 0x00, 0xA9, 0xD4, 0x13, 0x00, 0x91, 0xD8, 0x13, 0x00, 0x31, 0xD9, 0x13, 0x00, ++0xC1, 0xD8, 0x13, 0x00, 0x21, 0xD4, 0x13, 0x00, 0x4D, 0xDB, 0x13, 0x00, 0x71, 0xCA, 0x13, 0x00, 0xE5, 0xC9, 0x13, 0x00, ++0xAD, 0xC0, 0x13, 0x00, 0xCD, 0xC6, 0x13, 0x00, 0x39, 0xC0, 0x13, 0x00, 0x79, 0xD6, 0x13, 0x00, 0xE5, 0xD7, 0x13, 0x00, ++0xF1, 0xC7, 0x13, 0x00, 0xDD, 0xE4, 0x13, 0x00, 0xA1, 0xE6, 0x13, 0x00, 0x21, 0xD2, 0x13, 0x00, 0x6D, 0xD4, 0x13, 0x00, ++0x99, 0xEA, 0x13, 0x00, 0x71, 0x50, 0x14, 0x00, 0x71, 0x58, 0x14, 0x00, 0x25, 0x06, 0x12, 0x00, 0x7D, 0x4B, 0x14, 0x00, ++0x19, 0x4B, 0x14, 0x00, 0xF9, 0x5E, 0x12, 0x00, 0xD1, 0x5E, 0x12, 0x00, 0xF1, 0x1C, 0x14, 0x00, 0x19, 0x1E, 0x14, 0x00, ++0xE9, 0x14, 0x14, 0x00, 0xD9, 0x16, 0x14, 0x00, 0x91, 0x17, 0x14, 0x00, 0xC9, 0x1A, 0x14, 0x00, 0xF1, 0x19, 0x14, 0x00, ++0x3D, 0x15, 0x14, 0x00, 0xA5, 0x1B, 0x14, 0x00, 0x25, 0x1B, 0x14, 0x00, 0x1D, 0x90, 0x12, 0x00, 0x7D, 0x93, 0x12, 0x00, ++0xD1, 0x9E, 0x12, 0x00, 0x71, 0x8E, 0x12, 0x00, 0xF5, 0xAA, 0x12, 0x00, 0xC5, 0x78, 0x12, 0x00, 0x05, 0x69, 0x12, 0x00, ++0x39, 0x69, 0x12, 0x00, 0x8D, 0x52, 0x12, 0x00, 0x7D, 0x50, 0x12, 0x00, 0xD9, 0x55, 0x12, 0x00, 0xC1, 0x51, 0x12, 0x00, ++0x79, 0x51, 0x12, 0x00, 0x5D, 0xB2, 0x12, 0x00, 0x8D, 0x0C, 0x15, 0x00, 0x61, 0x4C, 0x14, 0x00, 0xF9, 0x0E, 0x12, 0x00, ++0x49, 0x07, 0x12, 0x00, 0x55, 0x59, 0x14, 0x00, 0xD5, 0x58, 0x14, 0x00, 0x49, 0x5A, 0x14, 0x00, 0x05, 0x5A, 0x14, 0x00, ++0xD9, 0x80, 0x14, 0x00, 0xD9, 0x5A, 0x14, 0x00, 0x45, 0x79, 0x14, 0x00, 0x7D, 0x7D, 0x13, 0x00, 0xA1, 0x78, 0x13, 0x00, ++0xB5, 0x7E, 0x13, 0x00, 0xF1, 0x85, 0x13, 0x00, 0xD5, 0xB6, 0x13, 0x00, 0x91, 0xBC, 0x13, 0x00, 0xF1, 0xB5, 0x13, 0x00, ++0x19, 0xBB, 0x13, 0x00, 0x5D, 0xBB, 0x13, 0x00, 0xD5, 0xBC, 0x13, 0x00, 0xDD, 0xB8, 0x13, 0x00, 0x8D, 0xB8, 0x13, 0x00, ++0xFD, 0xBD, 0x13, 0x00, 0x21, 0xB8, 0x13, 0x00, 0xC5, 0x8C, 0x13, 0x00, 0x09, 0x8C, 0x13, 0x00, 0xE9, 0x72, 0x13, 0x00, ++0x59, 0x87, 0x13, 0x00, 0xCD, 0x73, 0x13, 0x00, 0x31, 0x84, 0x13, 0x00, 0x25, 0x80, 0x13, 0x00, 0x35, 0x83, 0x13, 0x00, ++0xFD, 0x80, 0x13, 0x00, 0xE9, 0x8B, 0x13, 0x00, 0x01, 0x8E, 0x13, 0x00, 0x55, 0x89, 0x13, 0x00, 0xD9, 0x89, 0x13, 0x00, ++0x91, 0x7D, 0x13, 0x00, 0x4D, 0x75, 0x13, 0x00, 0xA5, 0xB3, 0x13, 0x00, 0x19, 0xB0, 0x13, 0x00, 0x01, 0xAF, 0x13, 0x00, ++0x21, 0xAF, 0x13, 0x00, 0x25, 0x05, 0x14, 0x00, 0xA9, 0xFF, 0x13, 0x00, 0xB1, 0xFE, 0x13, 0x00, 0xC5, 0xFF, 0x13, 0x00, ++0x81, 0xFF, 0x13, 0x00, 0x69, 0x06, 0x14, 0x00, 0x49, 0x03, 0x14, 0x00, 0x2D, 0x0A, 0x14, 0x00, 0x25, 0x08, 0x14, 0x00, ++0x3D, 0x09, 0x14, 0x00, 0xF9, 0x07, 0x14, 0x00, 0x59, 0xFB, 0x13, 0x00, 0x35, 0x04, 0x14, 0x00, 0xF5, 0xF6, 0x13, 0x00, ++0x89, 0xF4, 0x13, 0x00, 0xA5, 0x13, 0x12, 0x00, 0x5D, 0x10, 0x12, 0x00, 0xC1, 0x0B, 0x12, 0x00, 0x49, 0x11, 0x12, 0x00, ++0x4D, 0x02, 0x12, 0x00, 0xDD, 0xEA, 0x13, 0x00, 0x01, 0xEE, 0x13, 0x00, 0xA9, 0xF0, 0x13, 0x00, 0x79, 0xEF, 0x13, 0x00, ++0x49, 0xF1, 0x13, 0x00, 0xE5, 0xF1, 0x13, 0x00, 0x85, 0xEC, 0x13, 0x00, 0x45, 0xED, 0x13, 0x00, 0xA5, 0xED, 0x13, 0x00, ++0x3D, 0xEB, 0x13, 0x00, 0x45, 0xEF, 0x13, 0x00, 0xA1, 0xF2, 0x13, 0x00, 0xC5, 0xF3, 0x13, 0x00, 0x85, 0x49, 0x15, 0x00, ++0x01, 0x35, 0x15, 0x00, 0xCD, 0x42, 0x12, 0x00, 0x71, 0xCB, 0x12, 0x00, 0x35, 0xCF, 0x12, 0x00, 0xAD, 0xD3, 0x12, 0x00, ++0x9D, 0xCB, 0x12, 0x00, 0xFD, 0xD4, 0x12, 0x00, 0xFD, 0x48, 0x13, 0x00, 0x69, 0x4B, 0x13, 0x00, 0x21, 0x4C, 0x13, 0x00, ++0x15, 0x46, 0x13, 0x00, 0x99, 0x50, 0x13, 0x00, 0x9D, 0x5C, 0x13, 0x00, 0x79, 0x5C, 0x13, 0x00, 0xED, 0x53, 0x13, 0x00, ++0xE5, 0x56, 0x13, 0x00, 0x81, 0x4F, 0x13, 0x00, 0x61, 0x4E, 0x13, 0x00, 0x29, 0x4D, 0x13, 0x00, 0x01, 0x40, 0x13, 0x00, ++0xED, 0x4C, 0x13, 0x00, 0x1D, 0x52, 0x13, 0x00, 0xDD, 0xDB, 0x14, 0x00, 0xB5, 0xEB, 0x14, 0x00, 0x19, 0xD9, 0x14, 0x00, ++0xA5, 0xDF, 0x14, 0x00, 0xB5, 0xE0, 0x14, 0x00, 0xE9, 0xDE, 0x14, 0x00, 0x15, 0xE3, 0x14, 0x00, 0xD9, 0xE5, 0x14, 0x00, ++0x5D, 0xD7, 0x14, 0x00, 0xED, 0xD6, 0x14, 0x00, 0x21, 0x13, 0x14, 0x00, 0x85, 0x14, 0x14, 0x00, 0x05, 0xD1, 0x14, 0x00, ++0x8D, 0x85, 0x12, 0x00, 0xD1, 0x80, 0x12, 0x00, 0xCD, 0x7D, 0x12, 0x00, 0xED, 0x7F, 0x12, 0x00, 0x45, 0x7A, 0x12, 0x00, ++0x01, 0x7F, 0x12, 0x00, 0xD5, 0x99, 0x14, 0x00, 0xED, 0x9A, 0x14, 0x00, 0x31, 0x62, 0x13, 0x00, 0x29, 0x5F, 0x13, 0x00, ++0x65, 0x63, 0x13, 0x00, 0x41, 0x61, 0x13, 0x00, 0x71, 0x5F, 0x12, 0x00, 0xB9, 0x24, 0x12, 0x00, 0xD9, 0x0D, 0x14, 0x00, ++0x61, 0x0C, 0x14, 0x00, 0x79, 0x20, 0x14, 0x00, 0x05, 0x20, 0x14, 0x00, 0xC1, 0x20, 0x14, 0x00, 0x55, 0xD6, 0x12, 0x00, ++0x4D, 0x1B, 0x13, 0x00, 0x99, 0x0E, 0x13, 0x00, 0x11, 0x0C, 0x13, 0x00, 0x65, 0x0D, 0x13, 0x00, 0xD1, 0x19, 0x13, 0x00, ++0x5D, 0x13, 0x13, 0x00, 0x79, 0x0A, 0x13, 0x00, 0x8D, 0x21, 0x13, 0x00, 0x2D, 0x15, 0x13, 0x00, 0x19, 0x21, 0x13, 0x00, ++0x79, 0x07, 0x13, 0x00, 0xCD, 0xF3, 0x12, 0x00, 0x31, 0xD7, 0x12, 0x00, 0x41, 0xD8, 0x12, 0x00, 0xA1, 0xD8, 0x12, 0x00, ++0x69, 0xFC, 0x12, 0x00, 0x15, 0xFD, 0x12, 0x00, 0xF5, 0xE7, 0x12, 0x00, 0xB5, 0xE2, 0x12, 0x00, 0xE5, 0xEA, 0x12, 0x00, ++0xF5, 0xEB, 0x12, 0x00, 0xED, 0xE6, 0x12, 0x00, 0xF9, 0xDD, 0x12, 0x00, 0x89, 0xE2, 0x12, 0x00, 0xD1, 0xFD, 0x12, 0x00, ++0xD5, 0xE7, 0x12, 0x00, 0xD5, 0x30, 0x13, 0x00, 0x91, 0x36, 0x13, 0x00, 0xD5, 0x3A, 0x13, 0x00, 0x7D, 0x3C, 0x13, 0x00, ++0xDD, 0x26, 0x13, 0x00, 0x49, 0x27, 0x13, 0x00, 0xA9, 0x25, 0x13, 0x00, 0xCD, 0x35, 0x13, 0x00, 0x71, 0x25, 0x13, 0x00, ++0x89, 0x2C, 0x13, 0x00, 0x75, 0x30, 0x13, 0x00, 0x81, 0x3A, 0x13, 0x00, 0x05, 0x3A, 0x13, 0x00, 0x49, 0x3D, 0x13, 0x00, ++0xB1, 0x2B, 0x13, 0x00, 0x21, 0x2F, 0x13, 0x00, 0xBD, 0x39, 0x13, 0x00, 0x59, 0x28, 0x13, 0x00, 0xCD, 0x2A, 0x13, 0x00, ++0x61, 0x37, 0x13, 0x00, 0x01, 0xDB, 0x12, 0x00, 0xF1, 0xE2, 0x12, 0x00, 0x81, 0xD9, 0x12, 0x00, 0x35, 0xEE, 0x12, 0x00, ++0xC5, 0xEF, 0x12, 0x00, 0x49, 0xED, 0x12, 0x00, 0x69, 0xFD, 0x14, 0x00, 0x39, 0xF9, 0x14, 0x00, 0x71, 0xF4, 0x14, 0x00, ++0x79, 0xF9, 0x14, 0x00, 0x09, 0xFC, 0x14, 0x00, 0xC5, 0xF3, 0x14, 0x00, 0xDD, 0x60, 0x12, 0x00, 0xB1, 0xAD, 0x12, 0x00, ++0xBD, 0xAE, 0x12, 0x00, 0x29, 0xAF, 0x12, 0x00, 0xA5, 0xA4, 0x12, 0x00, 0xD1, 0xA5, 0x12, 0x00, 0xD9, 0x6C, 0x13, 0x00, ++0xF5, 0x6E, 0x13, 0x00, 0x1D, 0x64, 0x13, 0x00, 0x2D, 0x6E, 0x13, 0x00, 0x51, 0x65, 0x13, 0x00, 0xB5, 0x6E, 0x13, 0x00, ++0x2D, 0x6F, 0x13, 0x00, 0xC1, 0x68, 0x13, 0x00, 0x91, 0xBE, 0x12, 0x00, 0x29, 0xC4, 0x12, 0x00, 0x95, 0xBB, 0x12, 0x00, ++0xDD, 0x03, 0x12, 0x00, 0x19, 0xC5, 0x12, 0x00, 0xCD, 0xC6, 0x12, 0x00, 0x2D, 0x1E, 0x12, 0x00, 0x61, 0x1B, 0x12, 0x00, ++0x69, 0x1D, 0x12, 0x00, 0x7D, 0x9D, 0x12, 0x00, 0xA9, 0x9D, 0x12, 0x00, 0x39, 0x12, 0x14, 0x00, 0x99, 0x71, 0x13, 0x00, ++0xC1, 0x21, 0x12, 0x00, 0x51, 0x09, 0x12, 0x00, 0x9D, 0x0A, 0x12, 0x00, 0xA1, 0x0A, 0x12, 0x00, 0xBD, 0x0B, 0x12, 0x00, ++0x41, 0x1C, 0x12, 0x00, 0xD5, 0xCF, 0x12, 0x00, 0x21, 0xD1, 0x12, 0x00, 0xD1, 0x3C, 0x12, 0x00, 0xC5, 0x4B, 0x12, 0x00, ++0xA1, 0x4D, 0x12, 0x00, 0x6D, 0x4C, 0x12, 0x00, 0xAD, 0x4A, 0x12, 0x00, 0x71, 0xC0, 0x12, 0x00, 0x19, 0xC2, 0x12, 0x00, ++0x79, 0xB8, 0x12, 0x00, 0x29, 0x9A, 0x12, 0x00, 0x39, 0x93, 0x12, 0x00, 0xA1, 0x65, 0x12, 0x00, 0xCD, 0xB1, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x58, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC2, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x75, 0x95, 0x13, 0x00, ++0x04, 0x00, 0x00, 0x00, 0xFD, 0x8F, 0x13, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x08, 0x00, 0x00, 0x00, ++0xF1, 0xA9, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x93, 0x13, 0x00, 0x10, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, ++0x16, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x12, 0x00, 0x00, 0x00, ++0xF1, 0xA9, 0x13, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, ++0x1A, 0x00, 0x00, 0x00, 0xCD, 0x90, 0x13, 0x00, 0x6B, 0x00, 0x00, 0x00, 0xF5, 0x96, 0x13, 0x00, 0x6D, 0x00, 0x00, 0x00, ++0xD1, 0x97, 0x13, 0x00, 0x71, 0x00, 0x00, 0x00, 0x19, 0x93, 0x13, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x79, 0x91, 0x13, 0x00, ++0x20, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x1E, 0x00, 0x00, 0x00, ++0xF1, 0xA9, 0x13, 0x00, 0x30, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x22, 0x00, 0x00, 0x00, 0x09, 0xA0, 0x13, 0x00, ++0x84, 0x00, 0x00, 0x00, 0xAD, 0xA0, 0x13, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x4D, 0x8E, 0x13, 0x00, 0x24, 0x00, 0x00, 0x00, ++0xA9, 0x93, 0x13, 0x00, 0x26, 0x00, 0x00, 0x00, 0x4D, 0x94, 0x13, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x8E, 0x13, 0x00, ++0x0C, 0x00, 0x00, 0x00, 0x9D, 0x91, 0x13, 0x00, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x2A, 0x00, 0x00, 0x00, ++0xF1, 0x97, 0x13, 0x00, 0x39, 0x00, 0x00, 0x00, 0xC5, 0x91, 0x13, 0x00, 0x3B, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, ++0x46, 0x00, 0x00, 0x00, 0xCD, 0x8E, 0x13, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x21, 0x8E, 0x13, 0x00, 0x41, 0x00, 0x00, 0x00, ++0x91, 0x98, 0x13, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x8E, 0x13, 0x00, 0x4B, 0x00, 0x00, 0x00, 0xA9, 0x94, 0x13, 0x00, ++0x51, 0x00, 0x00, 0x00, 0x59, 0x8F, 0x13, 0x00, 0x52, 0x00, 0x00, 0x00, 0xB5, 0x9F, 0x13, 0x00, 0x56, 0x00, 0x00, 0x00, ++0x15, 0x95, 0x13, 0x00, 0x87, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x61, 0x00, 0x00, 0x00, 0x21, 0x97, 0x13, 0x00, ++0x63, 0x00, 0x00, 0x00, 0x9D, 0x98, 0x13, 0x00, 0x65, 0x00, 0x00, 0x00, 0xE9, 0x91, 0x13, 0x00, 0x67, 0x00, 0x00, 0x00, ++0x0D, 0x96, 0x13, 0x00, 0x69, 0x00, 0x00, 0x00, 0xF1, 0x9C, 0x13, 0x00, 0x73, 0x00, 0x00, 0x00, 0xE9, 0x98, 0x13, 0x00, ++0x75, 0x00, 0x00, 0x00, 0x0D, 0x8F, 0x13, 0x00, 0x77, 0x00, 0x00, 0x00, 0xA5, 0x92, 0x13, 0x00, 0x79, 0x00, 0x00, 0x00, ++0xCD, 0x92, 0x13, 0x00, 0x7B, 0x00, 0x00, 0x00, 0xE1, 0x9B, 0x13, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x59, 0x99, 0x13, 0x00, ++0x80, 0x00, 0x00, 0x00, 0xBD, 0x96, 0x13, 0x00, 0x82, 0x00, 0x00, 0x00, 0x11, 0x9B, 0x13, 0x00, 0x00, 0x08, 0x00, 0x00, ++0xB9, 0x0E, 0x14, 0x00, 0x85, 0x00, 0x00, 0x00, 0x4D, 0x0F, 0x14, 0x00, 0x86, 0x00, 0x00, 0x00, 0xC9, 0x0F, 0x14, 0x00, ++0x03, 0x08, 0x00, 0x00, 0x71, 0x10, 0x14, 0x00, 0x0D, 0xCD, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xB0, 0x13, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xA1, 0x28, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x4C, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x9D, 0x2F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x84, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x7F, 0x13, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xB5, 0x7F, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x85, 0x4A, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xF2, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x48, 0x13, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xD1, 0x78, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xD1, 0xF4, 0x12, 0x00, 0x04, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, ++0x02, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xF9, 0x4C, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x05, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, ++0x03, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, ++0xF9, 0x4C, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x69, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x6D, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x69, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xBD, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x15, 0x4A, 0x14, 0x00, 0x02, 0x04, 0x00, 0x00, 0xB5, 0x49, 0x14, 0x00, ++0x04, 0x04, 0x00, 0x00, 0x2D, 0x48, 0x14, 0x00, 0x06, 0x04, 0x00, 0x00, 0xF9, 0x47, 0x14, 0x00, 0x09, 0x04, 0x00, 0x00, ++0x95, 0x49, 0x14, 0x00, 0x11, 0x04, 0x00, 0x00, 0x11, 0x49, 0x14, 0x00, 0x0B, 0x04, 0x00, 0x00, 0xC1, 0x4A, 0x14, 0x00, ++0x0D, 0x04, 0x00, 0x00, 0x45, 0x4A, 0x14, 0x00, 0x0F, 0x04, 0x00, 0x00, 0x61, 0x48, 0x14, 0x00, 0x1B, 0x04, 0x00, 0x00, ++0x91, 0x47, 0x14, 0x00, 0x1E, 0x04, 0x00, 0x00, 0x75, 0x47, 0x14, 0x00, 0x1F, 0x04, 0x00, 0x00, 0x59, 0x47, 0x14, 0x00, ++0x01, 0x00, 0x00, 0x00, 0x28, 0x34, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0xBD, 0x68, 0x14, 0x00, 0x02, 0x14, 0x00, 0x00, ++0xED, 0x65, 0x14, 0x00, 0x04, 0x14, 0x00, 0x00, 0x01, 0x67, 0x14, 0x00, 0x07, 0x14, 0x00, 0x00, 0x01, 0x6A, 0x14, 0x00, ++0x09, 0x14, 0x00, 0x00, 0x75, 0x67, 0x14, 0x00, 0x17, 0x14, 0x00, 0x00, 0xB1, 0x72, 0x14, 0x00, 0x19, 0x14, 0x00, 0x00, ++0xB5, 0x6E, 0x14, 0x00, 0x0C, 0x14, 0x00, 0x00, 0x01, 0x68, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, ++0x23, 0x00, 0x00, 0x00, 0x45, 0x6F, 0x14, 0x00, 0x13, 0x14, 0x00, 0x00, 0x45, 0x73, 0x14, 0x00, 0x32, 0x00, 0x00, 0x00, ++0x9D, 0x6F, 0x14, 0x00, 0x15, 0x14, 0x00, 0x00, 0x11, 0x66, 0x14, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, ++0x3C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x42, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x1B, 0x00, 0x00, 0x00, ++0x89, 0x31, 0x14, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, ++0x70, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x72, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x0E, 0x14, 0x00, 0x00, ++0xF5, 0x6F, 0x14, 0x00, 0x10, 0x14, 0x00, 0x00, 0xF1, 0x70, 0x14, 0x00, 0x11, 0x14, 0x00, 0x00, 0x91, 0x71, 0x14, 0x00, ++0x00, 0x18, 0x00, 0x00, 0x1D, 0x8A, 0x14, 0x00, 0x03, 0x18, 0x00, 0x00, 0x6D, 0x92, 0x14, 0x00, 0x01, 0x10, 0x00, 0x00, ++0xA1, 0x8C, 0x14, 0x00, 0x03, 0x10, 0x00, 0x00, 0x09, 0x8D, 0x14, 0x00, 0x08, 0x18, 0x00, 0x00, 0x71, 0x8C, 0x14, 0x00, ++0x43, 0x00, 0x00, 0x00, 0x21, 0x8C, 0x14, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x8D, 0x92, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, ++0xA5, 0x90, 0x14, 0x00, 0x19, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x17, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, ++0x15, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x72, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x1B, 0x00, 0x00, 0x00, ++0xE5, 0x8F, 0x14, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xD9, 0x94, 0x14, 0x00, 0x1A, 0x14, 0x00, 0x00, 0x7D, 0x8F, 0x14, 0x00, ++0x4C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x90, 0x14, 0x00, 0x3A, 0x00, 0x00, 0x00, ++0x65, 0x90, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, 0x99, 0x91, 0x14, 0x00, 0x07, 0x18, 0x00, 0x00, 0xFD, 0x91, 0x14, 0x00, ++0x09, 0x18, 0x00, 0x00, 0x19, 0x92, 0x14, 0x00, 0x00, 0x1C, 0x00, 0x00, 0xF5, 0xB3, 0x14, 0x00, 0x02, 0x1C, 0x00, 0x00, ++0xD5, 0xB6, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, 0xD9, 0xB7, 0x14, 0x00, 0x40, 0x00, 0x00, 0x00, 0xBD, 0xB2, 0x14, 0x00, ++0x19, 0x00, 0x00, 0x00, 0x01, 0xB6, 0x14, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0xB6, 0x14, 0x00, 0x15, 0x00, 0x00, 0x00, ++0x01, 0xB6, 0x14, 0x00, 0x1A, 0x14, 0x00, 0x00, 0x9D, 0xB5, 0x14, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x81, 0xB6, 0x14, 0x00, ++0x3A, 0x00, 0x00, 0x00, 0x41, 0xB6, 0x14, 0x00, 0x04, 0x1C, 0x00, 0x00, 0x01, 0xB3, 0x14, 0x00, 0x06, 0x1C, 0x00, 0x00, ++0x39, 0xB7, 0x14, 0x00, 0x08, 0x1C, 0x00, 0x00, 0x59, 0xB5, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, ++0x02, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, 0x05, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, ++0x89, 0x31, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0x95, 0xBF, 0x14, 0x00, 0x02, 0x10, 0x00, 0x00, 0xF5, 0xC0, 0x14, 0x00, ++0x05, 0x10, 0x00, 0x00, 0xF5, 0xBF, 0x14, 0x00, 0x07, 0x10, 0x00, 0x00, 0xF1, 0xC1, 0x14, 0x00, 0x0A, 0x10, 0x00, 0x00, ++0x7D, 0xC0, 0x14, 0x00, 0x01, 0x08, 0x00, 0x00, 0x39, 0xC2, 0x14, 0x00, 0x02, 0x08, 0x00, 0x00, 0x85, 0xC2, 0x14, 0x00, ++0x00, 0x28, 0x00, 0x00, 0xA1, 0xC2, 0x14, 0x00, 0x0A, 0x10, 0x00, 0x00, 0x51, 0xC0, 0x14, 0x00, 0x04, 0x08, 0x00, 0x00, ++0x4D, 0xC2, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0xD5, 0xC0, 0x14, 0x00, 0x07, 0x10, 0x00, 0x00, 0xA1, 0xC0, 0x14, 0x00, ++0xDC, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x45, 0x04, 0x15, 0x00, 0x01, 0x20, 0x00, 0x00, 0x69, 0x04, 0x15, 0x00, ++0x2B, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x15, 0x00, 0x29, 0x00, 0x00, 0x00, 0x55, 0xFF, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, ++0x35, 0x01, 0x15, 0x00, 0x0D, 0x26, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, ++}; ++ ++char fw_adid_u03[1208] = { ++0x61, 0xBD, 0x08, 0x00, 0xFD, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0x03, 0x08, 0x00, ++0x71, 0x02, 0x08, 0x00, 0x21, 0x04, 0x08, 0x00, 0xD9, 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x0F, 0x08, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x15, 0x08, 0x00, ++0x6D, 0x18, 0x08, 0x00, 0xD1, 0x18, 0x08, 0x00, 0x15, 0x19, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x1D, 0x08, 0x00, ++0xA1, 0x24, 0x08, 0x00, 0x05, 0x26, 0x08, 0x00, 0x3D, 0x2A, 0x08, 0x00, 0x9D, 0x55, 0x08, 0x00, 0x39, 0x76, 0x08, 0x00, ++0x91, 0x76, 0x08, 0x00, 0x9D, 0x7C, 0x08, 0x00, 0xE5, 0x7C, 0x08, 0x00, 0x5D, 0x80, 0x08, 0x00, 0x75, 0xA9, 0x08, 0x00, ++0x9D, 0xBE, 0x08, 0x00, 0xD5, 0xBE, 0x08, 0x00, 0x39, 0xC0, 0x08, 0x00, 0x6D, 0xC2, 0x08, 0x00, 0x3D, 0x05, 0x09, 0x00, ++0xF1, 0x3B, 0x09, 0x00, 0x31, 0x3E, 0x09, 0x00, 0xFD, 0x40, 0x09, 0x00, 0x65, 0x9D, 0x09, 0x00, 0x25, 0xC0, 0x09, 0x00, ++0xF9, 0xBB, 0x09, 0x00, 0x05, 0xA2, 0x09, 0x00, 0x91, 0xD7, 0x09, 0x00, 0x4D, 0xB2, 0x0A, 0x00, 0x25, 0xB6, 0x0A, 0x00, ++0x75, 0xB8, 0x0A, 0x00, 0x2D, 0xB9, 0x0A, 0x00, 0x8D, 0xBB, 0x0A, 0x00, 0x99, 0xBC, 0x0A, 0x00, 0xA1, 0xC5, 0x0A, 0x00, ++0x31, 0xCD, 0x0A, 0x00, 0x09, 0xDE, 0x0A, 0x00, 0xB9, 0xEE, 0x0A, 0x00, 0x35, 0x58, 0x09, 0x00, 0xB1, 0x58, 0x09, 0x00, ++0x15, 0x54, 0x09, 0x00, 0xBD, 0x56, 0x09, 0x00, 0x11, 0x5B, 0x09, 0x00, 0xED, 0x5C, 0x09, 0x00, 0x15, 0x6C, 0x09, 0x00, ++0xB9, 0x60, 0x09, 0x00, 0xDD, 0x29, 0x0B, 0x00, 0x05, 0x76, 0x09, 0x00, 0x75, 0x76, 0x09, 0x00, 0x3D, 0x7A, 0x09, 0x00, ++0x5D, 0x7E, 0x09, 0x00, 0x69, 0x78, 0x09, 0x00, 0x61, 0x79, 0x09, 0x00, 0xD9, 0x7E, 0x09, 0x00, 0x35, 0x41, 0x0B, 0x00, ++0xB5, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x0C, 0x0B, 0x00, 0x85, 0x6F, 0x09, 0x00, 0xD5, 0x7B, 0x0B, 0x00, ++0x75, 0x7C, 0x0B, 0x00, 0xDD, 0x6C, 0x09, 0x00, 0xA9, 0x6D, 0x09, 0x00, 0x75, 0x6E, 0x09, 0x00, 0xE9, 0x1F, 0x0B, 0x00, ++0x35, 0x23, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x1B, 0x0B, 0x00, 0x45, 0x27, 0x0B, 0x00, 0x85, 0x1A, 0x0B, 0x00, ++0x69, 0x17, 0x0B, 0x00, 0xDD, 0x27, 0x0B, 0x00, 0x31, 0x2B, 0x0B, 0x00, 0x25, 0x78, 0x0B, 0x00, 0x15, 0x65, 0x0B, 0x00, ++0x3D, 0x6B, 0x0B, 0x00, 0x9D, 0x67, 0x0B, 0x00, 0x99, 0x6B, 0x0B, 0x00, 0xC5, 0x6C, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x2D, 0xAF, 0x0B, 0x00, 0x3D, 0x99, 0x0C, 0x00, 0xC5, 0xD9, 0x0C, 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, 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, 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, 0x00, 0x61, 0x95, 0x0C, 0x00, 0x3D, 0xD5, 0x0C, 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, 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, 0x00, ++0xF5, 0xA4, 0x08, 0x00, 0xB5, 0xA5, 0x08, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0xFD, 0x50, 0x08, 0x00, 0x9D, 0x7D, 0x08, 0x00, 0xBD, 0x7D, 0x08, 0x00, 0xDD, 0x7D, 0x08, 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, 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, 0xA9, 0x91, 0x08, 0x00, ++0xAB, 0x91, 0x08, 0x00, 0xAD, 0x91, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x71, 0xD5, 0x09, 0x00, 0x6D, 0x0E, 0x08, 0x00, ++}; ++ ++char fw_patch_table_u03[1256] = { ++0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x50, 0x54, 0x5F, 0x54, 0x41, 0x47, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, ++0x54, 0x5F, 0x54, 0x52, 0x41, 0x50, 0x5F, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, ++0x00, 0xF0, 0x16, 0x00, 0x04, 0x23, 0xA3, 0x55, 0x00, 0x10, 0x08, 0x40, 0x88, 0x48, 0x0C, 0x00, 0x04, 0xF0, 0x16, 0x00, ++0x00, 0x2B, 0x05, 0xE0, 0x04, 0x10, 0x08, 0x40, 0x58, 0x58, 0x0B, 0x00, 0x08, 0xF0, 0x16, 0x00, 0x00, 0x2B, 0xB1, 0xE7, ++0x08, 0x10, 0x08, 0x40, 0x30, 0x5A, 0x0B, 0x00, 0x14, 0xEA, 0x16, 0x00, 0x02, 0x49, 0x8E, 0x46, 0x18, 0xEA, 0x16, 0x00, ++0x00, 0xB5, 0x02, 0x4B, 0x1C, 0xEA, 0x16, 0x00, 0xDB, 0x6E, 0x00, 0xBD, 0x20, 0xEA, 0x16, 0x00, 0xD7, 0xCB, 0x0A, 0x00, ++0x24, 0xEA, 0x16, 0x00, 0xAC, 0x2B, 0x16, 0x00, 0x0C, 0xF0, 0x16, 0x00, 0xC1, 0xF0, 0x1F, 0xFF, 0x0C, 0x10, 0x08, 0x40, ++0xD2, 0xCB, 0x0A, 0x00, 0x00, 0xEA, 0x16, 0x00, 0x02, 0x49, 0x8E, 0x46, 0x04, 0xEA, 0x16, 0x00, 0x00, 0xB5, 0x02, 0x4B, ++0x08, 0xEA, 0x16, 0x00, 0xDA, 0x6E, 0x00, 0xBD, 0x0C, 0xEA, 0x16, 0x00, 0xC1, 0xE6, 0x0A, 0x00, 0x10, 0xEA, 0x16, 0x00, ++0xAC, 0x2B, 0x16, 0x00, 0x10, 0xF0, 0x16, 0x00, 0xC0, 0xF0, 0xA0, 0xF9, 0x10, 0x10, 0x08, 0x40, 0xBC, 0xE6, 0x0A, 0x00, ++0x14, 0xF0, 0x16, 0x00, 0x43, 0x1C, 0x05, 0xE0, 0x14, 0x10, 0x08, 0x40, 0x1C, 0xFD, 0x0C, 0x00, 0x30, 0xEA, 0x16, 0x00, ++0x01, 0x4B, 0x98, 0x47, 0x34, 0xEA, 0x16, 0x00, 0x01, 0x4B, 0x9F, 0x46, 0x38, 0xEA, 0x16, 0x00, 0xD9, 0x97, 0x10, 0x00, ++0x3C, 0xEA, 0x16, 0x00, 0x59, 0x1E, 0x0D, 0x00, 0x18, 0xF0, 0x16, 0x00, 0x9C, 0xF0, 0x92, 0xFF, 0x18, 0x10, 0x08, 0x40, ++0x08, 0x1B, 0x0D, 0x00, 0x1C, 0xF0, 0x16, 0x00, 0xEC, 0xE1, 0x10, 0x00, 0x1C, 0x10, 0x08, 0x40, 0x30, 0xB8, 0x0B, 0x00, ++0x84, 0x10, 0x08, 0x40, 0x00, 0xF0, 0x16, 0x00, 0x80, 0x10, 0x08, 0x40, 0xFF, 0x00, 0x00, 0x00, 0x58, 0x00, 0x10, 0x40, ++0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x50, 0x41, 0x54, 0x43, 0x48, 0x5F, 0x54, 0x42, 0x34, 0x00, ++0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x38, 0x1B, 0x16, 0x00, 0x99, 0x12, 0x10, 0x00, 0x98, 0x19, 0x16, 0x00, ++0xA9, 0x23, 0x10, 0x00, 0x18, 0x1B, 0x16, 0x00, 0x81, 0x07, 0x10, 0x00, 0x20, 0x1B, 0x16, 0x00, 0xCD, 0x09, 0x10, 0x00, ++0x28, 0x1B, 0x16, 0x00, 0xF1, 0x0B, 0x10, 0x00, 0xB0, 0x19, 0x16, 0x00, 0x21, 0x25, 0x10, 0x00, 0x70, 0x1A, 0x16, 0x00, ++0xB9, 0x30, 0x10, 0x00, 0x6C, 0x1A, 0x16, 0x00, 0x19, 0x64, 0x10, 0x00, 0xE0, 0x1A, 0x16, 0x00, 0xB9, 0x69, 0x10, 0x00, ++0xE0, 0x19, 0x16, 0x00, 0xCB, 0x09, 0x10, 0x00, 0xDC, 0x19, 0x16, 0x00, 0xC9, 0x09, 0x10, 0x00, 0x38, 0x19, 0x16, 0x00, ++0x89, 0x54, 0x10, 0x00, 0x1C, 0x1B, 0x16, 0x00, 0x69, 0x56, 0x10, 0x00, 0x24, 0x1B, 0x16, 0x00, 0x75, 0x58, 0x10, 0x00, ++0x7C, 0x1D, 0x16, 0x00, 0xDD, 0x5B, 0x10, 0x00, 0xB0, 0x1A, 0x16, 0x00, 0xB9, 0x5A, 0x10, 0x00, 0xB0, 0x1D, 0x16, 0x00, ++0x31, 0x6D, 0x10, 0x00, 0x8C, 0x1D, 0x16, 0x00, 0x19, 0x6E, 0x10, 0x00, 0x88, 0x1D, 0x16, 0x00, 0x49, 0x6E, 0x10, 0x00, ++0x40, 0x19, 0x16, 0x00, 0xF5, 0x6E, 0x10, 0x00, 0x2C, 0x1B, 0x16, 0x00, 0x51, 0x6F, 0x10, 0x00, 0x80, 0x1D, 0x16, 0x00, ++0xC1, 0x5F, 0x10, 0x00, 0xF4, 0x19, 0x16, 0x00, 0x89, 0x6F, 0x10, 0x00, 0xEC, 0x19, 0x16, 0x00, 0x0D, 0x70, 0x10, 0x00, ++0x54, 0x19, 0x16, 0x00, 0x31, 0x93, 0x10, 0x00, 0x14, 0x1B, 0x16, 0x00, 0x35, 0x94, 0x10, 0x00, 0x8C, 0x19, 0x16, 0x00, ++0xE9, 0x71, 0x10, 0x00, 0x88, 0x19, 0x16, 0x00, 0xB9, 0x7A, 0x10, 0x00, 0x04, 0x1B, 0x16, 0x00, 0x35, 0x97, 0x10, 0x00, ++0x90, 0x19, 0x16, 0x00, 0xFD, 0x9E, 0x10, 0x00, 0x94, 0x19, 0x16, 0x00, 0x5D, 0x9F, 0x10, 0x00, 0xE8, 0x19, 0x16, 0x00, ++0x3D, 0xA2, 0x10, 0x00, 0xE4, 0x1A, 0x16, 0x00, 0x35, 0x02, 0x10, 0x00, 0xD4, 0x1A, 0x16, 0x00, 0x69, 0xA2, 0x10, 0x00, ++0x64, 0x1A, 0x16, 0x00, 0x29, 0x33, 0x10, 0x00, 0x08, 0x1B, 0x16, 0x00, 0x55, 0x91, 0x10, 0x00, 0xBC, 0x19, 0x16, 0x00, ++0x31, 0x38, 0x10, 0x00, 0x68, 0x1A, 0x16, 0x00, 0x79, 0x61, 0x10, 0x00, 0x40, 0x1A, 0x16, 0x00, 0x8D, 0x40, 0x10, 0x00, ++0x3C, 0x1A, 0x16, 0x00, 0x41, 0x07, 0x10, 0x00, 0x4C, 0x1A, 0x16, 0x00, 0x85, 0x54, 0x10, 0x00, 0xB8, 0x19, 0x16, 0x00, ++0x9D, 0x3B, 0x10, 0x00, 0x7C, 0x1A, 0x16, 0x00, 0x41, 0x2A, 0x10, 0x00, 0x68, 0xAD, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x4D, 0x4F, 0x44, 0x45, 0x5F, 0x54, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ++0x09, 0x00, 0x00, 0x00, 0xA4, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x54, 0xE0, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xA8, 0xE5, 0x10, 0x00, ++0x02, 0x00, 0x00, 0x00, 0xB8, 0xE5, 0x10, 0x00, 0x60, 0xE3, 0x16, 0x00, 0xBC, 0xE5, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, ++0xAC, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xE5, 0x10, 0x00, 0x20, 0x60, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, ++0x54, 0x5F, 0x50, 0x4F, 0x57, 0x45, 0x52, 0x5F, 0x4F, 0x4E, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, ++0x3C, 0x00, 0x50, 0x40, 0x00, 0x00, 0x08, 0x00, 0x24, 0x01, 0x50, 0x40, 0x40, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, ++0x54, 0x5F, 0x50, 0x41, 0x54, 0x43, 0x48, 0x5F, 0x54, 0x41, 0x46, 0x00, 0x05, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, ++0x24, 0x0A, 0x16, 0x00, 0x65, 0x7E, 0x10, 0x00, 0xA4, 0x12, 0x16, 0x00, 0x1D, 0x84, 0x10, 0x00, 0xBC, 0x12, 0x16, 0x00, ++0xFD, 0xA3, 0x10, 0x00, 0xC4, 0x12, 0x16, 0x00, 0xE9, 0xB2, 0x10, 0x00, 0x0C, 0x08, 0x16, 0x00, 0x1D, 0xA3, 0x10, 0x00, ++0x5C, 0x07, 0x16, 0x00, 0x45, 0xA3, 0x10, 0x00, 0x84, 0x15, 0x16, 0x00, 0xB9, 0x89, 0x10, 0x00, 0x4C, 0x18, 0x16, 0x00, ++0x65, 0x8B, 0x10, 0x00, 0x6C, 0x18, 0x16, 0x00, 0xE9, 0x8B, 0x10, 0x00, 0xDC, 0x18, 0x16, 0x00, 0x35, 0x8C, 0x10, 0x00, ++0xF4, 0x1A, 0x16, 0x00, 0x99, 0x05, 0x10, 0x00, 0xAC, 0x12, 0x16, 0x00, 0x35, 0x76, 0x10, 0x00, 0x04, 0x10, 0x16, 0x00, ++0xD1, 0x8E, 0x10, 0x00, 0x0C, 0x10, 0x16, 0x00, 0x25, 0x90, 0x10, 0x00, 0x84, 0x10, 0x16, 0x00, 0x41, 0xAA, 0x10, 0x00, ++0x9C, 0x10, 0x16, 0x00, 0xB1, 0xAA, 0x10, 0x00, 0xA4, 0x10, 0x16, 0x00, 0x71, 0xAB, 0x10, 0x00, 0x4C, 0x10, 0x16, 0x00, ++0x5D, 0xAC, 0x10, 0x00, 0xE4, 0x0F, 0x16, 0x00, 0x65, 0x90, 0x10, 0x00, 0xEC, 0x13, 0x16, 0x00, 0xC5, 0xA7, 0x10, 0x00, ++0x0C, 0x13, 0x16, 0x00, 0x55, 0xB3, 0x10, 0x00, 0xFC, 0x12, 0x16, 0x00, 0x1D, 0x26, 0x10, 0x00, 0x74, 0x0A, 0x16, 0x00, ++0xED, 0x27, 0x10, 0x00, 0x74, 0x13, 0x16, 0x00, 0x35, 0xA8, 0x10, 0x00, 0x04, 0x14, 0x16, 0x00, 0xD9, 0xA8, 0x10, 0x00, ++0x4C, 0x14, 0x16, 0x00, 0xB1, 0xAE, 0x10, 0x00, 0x3C, 0x0A, 0x16, 0x00, 0x05, 0xAF, 0x10, 0x00, 0x44, 0x0A, 0x16, 0x00, ++0xF1, 0xAF, 0x10, 0x00, 0x04, 0x15, 0x16, 0x00, 0x51, 0x91, 0x10, 0x00, 0x2C, 0x13, 0x16, 0x00, 0xA1, 0x42, 0x10, 0x00, ++0xD4, 0x0A, 0x16, 0x00, 0xED, 0xAD, 0x10, 0x00, 0x44, 0x11, 0x16, 0x00, 0x51, 0xAD, 0x10, 0x00, 0xE4, 0x12, 0x16, 0x00, ++0x09, 0xA7, 0x10, 0x00, 0x7C, 0x09, 0x16, 0x00, 0x15, 0xCD, 0x10, 0x00, 0x8C, 0x09, 0x16, 0x00, 0x4D, 0xCD, 0x10, 0x00, ++0x94, 0x09, 0x16, 0x00, 0xC1, 0xCD, 0x10, 0x00, 0x6C, 0x14, 0x16, 0x00, 0x71, 0xCD, 0x10, 0x00, 0x70, 0x30, 0x50, 0x40, ++0x00, 0x00, 0x00, 0x00, 0x74, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x78, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, ++0x7C, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x56, 0x45, 0x52, 0x5F, 0x49, 0x4E, ++0x46, 0x4F, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2D, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, 0x33, ++0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x33, 0x38, 0x3A, 0x33, 0x39, 0x20, 0x2D, 0x20, 0x67, 0x69, 0x74, ++0x20, 0x30, 0x61, 0x61, 0x62, 0x66, 0x62, 0x66, 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, ++}; ++ ++char fw_patch_u03[59704] = { ++0x10, 0xB5, 0x15, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0x13, 0x4B, 0x1B, 0x68, ++0x3F, 0x22, 0x9A, 0x5C, 0x00, 0x2A, 0xF6, 0xD1, 0x3D, 0x32, 0x9C, 0x5C, 0x10, 0x4B, 0x1A, 0x78, 0x01, 0x32, 0xD2, 0xB2, ++0x10, 0x2A, 0x10, 0xD8, 0x1A, 0x70, 0x0D, 0x49, 0x0A, 0x78, 0x12, 0x03, 0x92, 0xB2, 0x62, 0x23, 0x63, 0x43, 0x0B, 0x4C, ++0x1C, 0x19, 0x22, 0x80, 0x0A, 0x78, 0x12, 0x09, 0x09, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x1A, 0x80, 0xDD, 0xE7, 0x05, 0x4B, ++0x00, 0x22, 0x1A, 0x70, 0xEB, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0xC1, 0xE9, 0x0A, 0x00, 0x28, 0x27, 0x16, 0x00, ++0xB0, 0xE6, 0x10, 0x00, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x0B, 0x4B, 0x1B, 0x68, ++0x00, 0x2B, 0x03, 0xD0, 0x3A, 0x22, 0x9B, 0x5C, 0x01, 0x2B, 0x06, 0xD0, 0x20, 0x00, 0x08, 0x4B, 0x98, 0x47, 0x62, 0x68, ++0x07, 0x4B, 0x1A, 0x60, 0x10, 0xBD, 0x07, 0x49, 0x0B, 0x68, 0x07, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, ++0x0B, 0x60, 0xEF, 0xE7, 0x18, 0x27, 0x16, 0x00, 0x25, 0xC3, 0x0C, 0x00, 0x30, 0xE6, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, ++0xFF, 0xFF, 0xDF, 0xFF, 0x10, 0xB5, 0x18, 0x4A, 0x00, 0x23, 0x00, 0x24, 0x14, 0x57, 0x84, 0x42, 0x04, 0xDA, 0x01, 0x33, ++0xDB, 0xB2, 0x01, 0x32, 0x08, 0x2B, 0xF6, 0xD1, 0x12, 0x4A, 0xD2, 0x56, 0x82, 0x42, 0x05, 0xD0, 0x00, 0x29, 0x03, 0xD1, ++0x00, 0x2B, 0x01, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x1A, 0x1C, 0x07, 0x2B, 0x00, 0xD9, 0x07, 0x22, 0xD2, 0xB2, 0x0C, 0x4B, ++0x99, 0x5C, 0x0C, 0x4A, 0x95, 0x23, 0x9B, 0x00, 0xD3, 0x5C, 0x1A, 0x1C, 0xDB, 0xB2, 0x8B, 0x42, 0x00, 0xD9, 0x0A, 0x1C, ++0x07, 0x49, 0x08, 0x4B, 0xCB, 0x5C, 0x18, 0x1C, 0xDB, 0xB2, 0xD1, 0xB2, 0x8B, 0x42, 0x00, 0xD2, 0x10, 0x1C, 0xC0, 0xB2, ++0x10, 0xBD, 0xC0, 0x46, 0x28, 0xE0, 0x10, 0x00, 0xBC, 0xDF, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x55, 0x02, 0x00, 0x00, ++0x10, 0xB5, 0x62, 0x22, 0x42, 0x43, 0x0F, 0x4B, 0x9C, 0x46, 0x62, 0x44, 0x13, 0x88, 0xDB, 0xB2, 0x1E, 0x2B, 0x13, 0xD0, ++0x0C, 0x49, 0x0D, 0x48, 0x0C, 0x5C, 0x0D, 0x48, 0x09, 0x5C, 0x09, 0x19, 0x01, 0x20, 0x8B, 0x42, 0x09, 0xDB, 0x1B, 0x1B, ++0xDB, 0xB2, 0x10, 0x2B, 0x08, 0xD0, 0x11, 0x88, 0xFF, 0x20, 0x81, 0x43, 0x0B, 0x43, 0x13, 0x80, 0x00, 0x20, 0x10, 0xBD, ++0x0E, 0x3B, 0xE9, 0xE7, 0x0E, 0x33, 0xF4, 0xE7, 0x0C, 0x65, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, 0x57, 0x02, 0x00, 0x00, ++0x55, 0x02, 0x00, 0x00, 0x30, 0xB5, 0x62, 0x22, 0x42, 0x43, 0x0F, 0x4B, 0x9C, 0x46, 0x62, 0x44, 0x13, 0x88, 0xDB, 0xB2, ++0x1E, 0x2B, 0x12, 0xD0, 0x0C, 0x49, 0x0D, 0x48, 0x0C, 0x5C, 0x1D, 0x19, 0x03, 0x38, 0x09, 0x5C, 0x01, 0x20, 0x8D, 0x42, ++0x08, 0xDC, 0xEB, 0xB2, 0x10, 0x2B, 0x08, 0xD0, 0x11, 0x88, 0xFF, 0x20, 0x81, 0x43, 0x0B, 0x43, 0x13, 0x80, 0x00, 0x20, ++0x30, 0xBD, 0x0E, 0x3B, 0xEA, 0xE7, 0x0E, 0x33, 0xF4, 0xE7, 0xC0, 0x46, 0x0C, 0x65, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, ++0x57, 0x02, 0x00, 0x00, 0x70, 0x47, 0x70, 0x47, 0x70, 0xB5, 0x00, 0x28, 0x1C, 0xD0, 0x12, 0x4B, 0x1D, 0x68, 0x00, 0x2D, ++0x18, 0xD0, 0xE9, 0x78, 0x09, 0x02, 0x01, 0x23, 0x19, 0x43, 0x03, 0x33, 0xFF, 0x22, 0x0E, 0x48, 0x81, 0xF7, 0xFA, 0xFE, ++0x04, 0x1E, 0x0E, 0xD0, 0x20, 0x00, 0x81, 0xF7, 0x1F, 0xFF, 0xAB, 0xF7, 0x23, 0xFB, 0x03, 0x00, 0x09, 0x48, 0x6A, 0x68, ++0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x43, 0x60, 0xD6, 0xF7, 0x9E, 0xFE, 0x70, 0xBD, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xE9, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x3F, 0x06, 0x00, 0x00, 0xFC, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x05, 0x00, 0x22, 0x4B, 0x23, 0x4A, 0x13, 0x60, 0x02, 0x22, 0xFF, 0x32, 0x9C, 0x5C, ++0x21, 0x4B, 0xE2, 0x18, 0x12, 0x01, 0x13, 0x88, 0x9B, 0x06, 0x5B, 0x0F, 0x01, 0x2B, 0x04, 0xD0, 0x13, 0x88, 0x9B, 0x06, ++0x5B, 0x0F, 0x02, 0x2B, 0x0F, 0xD1, 0x23, 0x01, 0x18, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x1B, 0x7B, 0x00, 0x2B, 0x05, 0xD1, ++0x13, 0x88, 0x38, 0x21, 0x8B, 0x43, 0x20, 0x39, 0x0B, 0x43, 0x13, 0x80, 0x15, 0x48, 0x83, 0xF7, 0xB9, 0xFF, 0x15, 0x4B, ++0x2A, 0x68, 0x9A, 0x42, 0x0F, 0xD0, 0x14, 0x4F, 0xDE, 0x26, 0x76, 0x00, 0x00, 0x23, 0xBB, 0x51, 0x28, 0x00, 0xD7, 0xF7, ++0x4B, 0xF9, 0x11, 0x4B, 0xBB, 0x51, 0xAB, 0xF7, 0xD5, 0xFA, 0xA4, 0x00, 0x0F, 0x4B, 0x18, 0x51, 0xF8, 0xBD, 0x0F, 0x4B, ++0x1B, 0x68, 0x02, 0x2B, 0xEB, 0xD1, 0x2B, 0x7C, 0x9B, 0x00, 0x0D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x68, 0x0C, 0x4A, ++0x12, 0x68, 0x1A, 0x66, 0x1A, 0x61, 0xE0, 0xE7, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0x00, 0x10, 0x06, 0x04, ++0xF8, 0xCD, 0x10, 0x00, 0xD1, 0x1F, 0x0D, 0x00, 0x28, 0x19, 0x16, 0x00, 0x35, 0x02, 0x10, 0x00, 0xE0, 0xE5, 0x10, 0x00, ++0x50, 0xE0, 0x10, 0x00, 0xF4, 0x29, 0x16, 0x00, 0xE8, 0xE1, 0x10, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x04, 0x1E, 0x32, 0xD0, ++0x9E, 0x23, 0xC5, 0x5C, 0x1B, 0x4B, 0x00, 0x93, 0x43, 0x68, 0x01, 0x93, 0x83, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1D, 0x76, ++0x04, 0x95, 0x18, 0x4B, 0x03, 0x93, 0x83, 0x7D, 0x6A, 0x46, 0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, 0x93, 0x75, ++0xB0, 0x22, 0x82, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, 0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, 0xD7, 0xF7, ++0xFB, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x47, 0x3A, 0x6A, 0x43, 0x0C, 0x4B, 0x9C, 0x46, 0x62, 0x44, ++0x13, 0x88, 0xFF, 0x21, 0x8B, 0x43, 0x01, 0x21, 0x0B, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0xA0, 0x23, 0xE1, 0x54, 0x09, 0xB0, ++0x30, 0xBD, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xF6, 0xE7, 0xD1, 0xBD, 0x10, 0x00, ++0xDE, 0x05, 0x00, 0x00, 0x1E, 0x65, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x03, 0x00, 0x0D, 0x00, ++0x89, 0x00, 0x2B, 0x4A, 0x8C, 0x58, 0x00, 0x2C, 0x36, 0xD0, 0xA6, 0x22, 0xA2, 0x5C, 0x12, 0x1A, 0x03, 0x20, 0x10, 0x40, ++0xC0, 0x18, 0x00, 0x01, 0x00, 0x09, 0x63, 0x68, 0xC3, 0x1A, 0x1A, 0x01, 0x12, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8A, 0x42, ++0x26, 0xD8, 0x1B, 0x01, 0x20, 0x2B, 0x23, 0xD9, 0x20, 0x4B, 0x00, 0x93, 0x01, 0x90, 0xA3, 0x68, 0x02, 0x93, 0x6B, 0x46, ++0x1D, 0x76, 0x04, 0x95, 0x1D, 0x4B, 0x03, 0x93, 0xA3, 0x7D, 0x6A, 0x46, 0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, ++0x93, 0x75, 0xB0, 0x22, 0xA2, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, 0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, ++0xD7, 0xF7, 0xA0, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x9F, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x01, 0xD0, ++0x09, 0xB0, 0x30, 0xBD, 0xA3, 0x6F, 0x9B, 0xB2, 0x62, 0x21, 0x4D, 0x43, 0x0D, 0x4A, 0xAA, 0x18, 0x13, 0x80, 0xA3, 0x6F, ++0x1B, 0x0C, 0x0C, 0x4A, 0xAA, 0x18, 0x13, 0x80, 0x0B, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x0B, 0x4B, 0x1B, 0x68, 0xDB, 0x03, ++0xFF, 0x22, 0xD2, 0x03, 0x1A, 0x40, 0x23, 0x6D, 0x13, 0x43, 0x9B, 0xB2, 0x2B, 0x80, 0xE3, 0xE7, 0x38, 0xE6, 0x10, 0x00, ++0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, ++0xC8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x00, 0x28, 0x08, 0xD0, 0x08, 0x4B, 0x98, 0x47, 0x08, 0x4B, 0x1B, 0x68, 0xD9, 0x6A, ++0x05, 0x20, 0xD7, 0xF7, 0x5B, 0xFF, 0x10, 0xBD, 0x05, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0xF7, 0xE7, 0xC0, 0x46, 0x85, 0xC0, 0x0A, 0x00, 0x18, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x04, 0x4B, ++0x98, 0x47, 0x04, 0x4B, 0x1B, 0x68, 0x59, 0x6B, 0x06, 0x20, 0xD7, 0xF7, 0x43, 0xFF, 0x10, 0xBD, 0xA5, 0xD7, 0x0A, 0x00, ++0x24, 0x27, 0x16, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x04, 0x1E, 0x5A, 0xD0, 0x9F, 0x23, 0xC3, 0x5C, 0x01, 0x2B, 0x04, 0xD0, ++0xA0, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x09, 0xB0, 0x30, 0xBD, 0x9D, 0x33, 0xC5, 0x5C, 0x2B, 0x4B, 0x00, 0x93, 0x43, 0x68, ++0x01, 0x93, 0x83, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1D, 0x76, 0x04, 0x95, 0x27, 0x4B, 0x03, 0x93, 0x83, 0x7D, 0x6A, 0x46, ++0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, 0x93, 0x75, 0xB0, 0x22, 0x82, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, ++0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, 0xD7, 0xF7, 0x1A, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, ++0x9F, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0xD3, 0xD1, 0x23, 0x6D, 0x01, 0x33, 0x5B, 0x08, 0xA2, 0x6F, 0x91, 0xB2, 0x62, 0x22, ++0x55, 0x43, 0x17, 0x4A, 0xAA, 0x18, 0x11, 0x80, 0xA2, 0x6F, 0x12, 0x0C, 0x15, 0x49, 0x69, 0x18, 0x0A, 0x80, 0x15, 0x4A, ++0x94, 0x46, 0x65, 0x44, 0x01, 0x33, 0x5B, 0x08, 0x13, 0x4A, 0x13, 0x43, 0x9B, 0xB2, 0x2B, 0x80, 0x9F, 0x23, 0xE3, 0x5C, ++0x01, 0x2B, 0xB7, 0xD1, 0xA5, 0x33, 0xE2, 0x5C, 0x01, 0x32, 0xA3, 0x3B, 0x13, 0x40, 0x9E, 0x22, 0xA1, 0x5C, 0x9C, 0x3A, ++0x0C, 0x48, 0xD7, 0xF7, 0x3D, 0xF9, 0xAA, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xA8, 0xE7, 0x0A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA4, 0xE7, 0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, 0xFA, 0x64, 0x61, 0x40, ++0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0x7D, 0x03, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x00, 0x09, 0x01, 0x4B, 0x18, 0x56, 0x70, 0x47, 0x28, 0xE0, 0x10, 0x00, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, ++0xC0, 0xB5, 0x8A, 0x46, 0x5B, 0x49, 0x09, 0x78, 0x06, 0x29, 0x23, 0xD0, 0x5A, 0x49, 0x0C, 0x78, 0x01, 0x2C, 0x07, 0xD0, ++0x20, 0x21, 0x55, 0x46, 0x69, 0x5C, 0x1E, 0x29, 0x08, 0xD8, 0x56, 0x49, 0x01, 0x25, 0x0D, 0x70, 0x20, 0x21, 0x55, 0x46, ++0x69, 0x5C, 0x1F, 0x29, 0x00, 0xD9, 0x9B, 0xE0, 0x52, 0x4F, 0xE6, 0x25, 0x6D, 0x00, 0x00, 0x21, 0x79, 0x51, 0x51, 0x46, ++0x50, 0x4E, 0xB0, 0x47, 0x50, 0x4B, 0x7B, 0x51, 0x4C, 0x4B, 0x1C, 0x70, 0x00, 0x20, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xF0, 0xBD, 0x00, 0x21, 0xE5, 0x20, 0x81, 0xF7, 0xC8, 0xFD, 0x80, 0x46, 0x00, 0x28, 0x14, 0xD0, 0x20, 0x23, ++0x52, 0x46, 0xD7, 0x5C, 0x04, 0x33, 0xD1, 0x5C, 0x53, 0x8C, 0xC9, 0x18, 0x89, 0xB2, 0x45, 0x4B, 0x9C, 0x46, 0x61, 0x44, ++0x3A, 0x00, 0x40, 0x46, 0xD8, 0xF7, 0xDC, 0xFB, 0x00, 0x2F, 0x64, 0xD0, 0x45, 0x46, 0x41, 0x4B, 0x99, 0x46, 0x14, 0xE0, ++0x3B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xE3, 0xE7, 0x05, 0x2C, 0x27, 0xD0, 0x4B, 0x46, ++0x1A, 0x88, 0x3B, 0x4B, 0x9A, 0x42, 0x36, 0xD0, 0xE2, 0x43, 0xBF, 0x18, 0xFF, 0xB2, 0x01, 0x34, 0x2D, 0x19, 0x00, 0x2F, ++0x4B, 0xD0, 0x2C, 0x78, 0x6E, 0x78, 0x16, 0x2E, 0xED, 0xD0, 0xFF, 0x2E, 0xED, 0xD1, 0x0D, 0x2C, 0xEB, 0xD1, 0xAB, 0x78, ++0x5D, 0x2B, 0xE8, 0xD1, 0xEB, 0x78, 0x00, 0x2B, 0xE5, 0xD1, 0x2B, 0x79, 0x03, 0x2B, 0xE2, 0xD1, 0x6B, 0x79, 0x00, 0x2B, ++0xDF, 0xD1, 0x2D, 0x48, 0x83, 0xF7, 0xB6, 0xFD, 0x2C, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xD7, 0xE7, 0xAB, 0x78, ++0x01, 0x2B, 0xD4, 0xD1, 0xEB, 0x78, 0xFD, 0x2B, 0xD1, 0xD1, 0x2B, 0x79, 0x00, 0x2B, 0xCE, 0xD1, 0x6B, 0x79, 0x01, 0x2B, ++0xCB, 0xD1, 0x25, 0x48, 0x83, 0xF7, 0xA2, 0xFD, 0x22, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xC3, 0xE7, 0x1D, 0x4B, ++0x5B, 0x88, 0xB3, 0x42, 0xC4, 0xD1, 0x1B, 0x4B, 0x9B, 0x68, 0x00, 0x2B, 0x0C, 0xD0, 0x19, 0x4B, 0x9A, 0x79, 0xA9, 0x1C, ++0x98, 0x68, 0xD8, 0xF7, 0x5F, 0xFB, 0x00, 0x28, 0xB8, 0xD1, 0x18, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xB3, 0xE7, ++0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEB, 0xE7, 0x20, 0x23, 0x52, 0x46, 0xD3, 0x5C, ++0x00, 0x2B, 0x03, 0xD1, 0x40, 0x46, 0x81, 0xF7, 0xEB, 0xFD, 0x73, 0xE7, 0x50, 0x8C, 0xBA, 0xF7, 0xAD, 0xFD, 0xF7, 0xE7, ++0x53, 0x46, 0x58, 0x8C, 0xBA, 0xF7, 0xA8, 0xFD, 0x6A, 0xE7, 0xC0, 0x46, 0xD0, 0xE5, 0x10, 0x00, 0x59, 0xA9, 0x16, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x45, 0xF8, 0x0B, 0x00, 0x99, 0x05, 0x10, 0x00, 0x00, 0x00, 0x61, 0x40, 0xC4, 0xE5, 0x10, 0x00, ++0x88, 0xAC, 0x00, 0x00, 0x10, 0xCE, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x00, 0xCE, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, ++0x07, 0x4E, 0x8A, 0x25, 0x6D, 0x00, 0x00, 0x21, 0x71, 0x51, 0x21, 0x00, 0xB3, 0xF7, 0xF0, 0xFC, 0xA4, 0x00, 0x04, 0x4B, ++0xE3, 0x58, 0x04, 0x4A, 0xDA, 0x61, 0x04, 0x4B, 0x73, 0x51, 0x70, 0xBD, 0x28, 0x19, 0x16, 0x00, 0x54, 0x27, 0x16, 0x00, ++0x21, 0x61, 0x10, 0x00, 0x41, 0x07, 0x10, 0x00, 0x10, 0xB5, 0xD2, 0x23, 0x5B, 0x00, 0x1B, 0x68, 0x98, 0x47, 0x10, 0xBD, ++0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0xE3, 0xB0, 0x01, 0xAC, 0xC2, 0x25, 0x6D, 0x00, 0x2A, 0x00, 0x00, 0x21, ++0x20, 0x00, 0x7F, 0xF7, 0xAB, 0xFC, 0x7A, 0x4E, 0x2A, 0x00, 0x00, 0x21, 0x30, 0x68, 0x7F, 0xF7, 0xA5, 0xFC, 0x31, 0x68, ++0x2A, 0x00, 0x01, 0xA8, 0xD8, 0xF7, 0x14, 0xFB, 0x75, 0x48, 0x83, 0xF7, 0x1D, 0xFD, 0x50, 0x22, 0x00, 0x21, 0x4E, 0xA8, ++0x7F, 0xF7, 0x98, 0xFC, 0x00, 0x26, 0x9A, 0x23, 0x5B, 0x00, 0xE6, 0x54, 0x4E, 0xA9, 0x00, 0x20, 0x8B, 0xF7, 0x3A, 0xF8, ++0x86, 0x3D, 0xC0, 0x23, 0x5B, 0x00, 0xE5, 0x54, 0x80, 0x3B, 0xFF, 0x3B, 0x98, 0x46, 0x82, 0x33, 0xFF, 0x33, 0x42, 0x46, ++0xE2, 0x54, 0x03, 0x27, 0x82, 0x23, 0xFF, 0x33, 0xE7, 0x54, 0x0D, 0x3B, 0xE7, 0x54, 0x36, 0x23, 0xFF, 0x33, 0x99, 0x46, ++0xE6, 0x54, 0x4E, 0xA9, 0x00, 0x20, 0x87, 0xF7, 0x6B, 0xFE, 0x4B, 0x46, 0xE0, 0x5C, 0x4E, 0xA9, 0x8B, 0xF7, 0x6A, 0xF8, ++0x50, 0x22, 0x00, 0x21, 0x3A, 0xA8, 0x7F, 0xF7, 0x6D, 0xFC, 0xE4, 0x23, 0xE6, 0x54, 0x3A, 0xA9, 0x00, 0x20, 0x8B, 0xF7, ++0x11, 0xF8, 0x32, 0x23, 0xFF, 0x33, 0xE5, 0x54, 0x30, 0x3B, 0xFF, 0x3B, 0x99, 0x22, 0x52, 0x00, 0xA3, 0x54, 0x02, 0x3A, ++0xA3, 0x54, 0x0C, 0x3A, 0xA3, 0x54, 0x19, 0x3D, 0x43, 0x46, 0x63, 0x55, 0x3A, 0xA9, 0x01, 0x20, 0x87, 0xF7, 0x48, 0xFE, ++0x60, 0x5D, 0x3A, 0xA9, 0x8B, 0xF7, 0x48, 0xF8, 0x4E, 0x4B, 0x1E, 0x60, 0x4E, 0x4D, 0x2E, 0x60, 0x4E, 0x4B, 0x42, 0x46, ++0x1A, 0x60, 0x4E, 0x49, 0x0B, 0x68, 0x4E, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x4C, 0x4C, ++0x27, 0x60, 0x4C, 0x4B, 0x19, 0x68, 0x4C, 0x48, 0xD7, 0xF7, 0x60, 0xFE, 0x0F, 0x23, 0x03, 0x40, 0x22, 0x68, 0x80, 0x21, ++0x8A, 0x43, 0x0A, 0x43, 0x22, 0x60, 0x06, 0x09, 0xFF, 0x22, 0x16, 0x40, 0x46, 0x4F, 0x3E, 0x60, 0x00, 0x0B, 0x10, 0x40, ++0x28, 0x60, 0x5A, 0x08, 0x9B, 0x1A, 0x1B, 0x01, 0x9B, 0x18, 0x43, 0x4A, 0x13, 0x60, 0x23, 0x68, 0x8B, 0x43, 0x23, 0x60, ++0x41, 0x4B, 0x1B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x3F, 0x4A, 0x13, 0x6F, 0x71, 0x39, 0x8B, 0x43, 0x0D, 0x39, 0x0B, 0x43, ++0x13, 0x67, 0x3C, 0x4B, 0x5B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x3A, 0x4A, 0x53, 0x6F, 0x0F, 0x21, 0x8B, 0x43, 0x0D, 0x39, ++0x0B, 0x43, 0x53, 0x67, 0x36, 0x4B, 0x9B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x34, 0x4A, 0x93, 0x6F, 0x0F, 0x21, 0x8B, 0x43, ++0x0D, 0x39, 0x0B, 0x43, 0x93, 0x67, 0x31, 0x4B, 0xDB, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x2F, 0x4A, 0xD3, 0x6F, 0x0F, 0x21, ++0x8B, 0x43, 0x0D, 0x39, 0x0B, 0x43, 0xD3, 0x67, 0x2B, 0x4B, 0x19, 0x69, 0x0F, 0x24, 0xA1, 0x43, 0x03, 0x20, 0x01, 0x43, ++0x19, 0x61, 0x59, 0x69, 0xA1, 0x43, 0x01, 0x43, 0x59, 0x61, 0x99, 0x69, 0xA1, 0x43, 0x01, 0x43, 0x99, 0x61, 0xDA, 0x69, ++0xA2, 0x43, 0x02, 0x43, 0xDA, 0x61, 0x18, 0x4B, 0x07, 0x22, 0x1A, 0x60, 0x01, 0xAA, 0x00, 0x23, 0x20, 0x21, 0x53, 0x54, ++0x06, 0x93, 0x05, 0x93, 0x02, 0x93, 0x01, 0x93, 0x15, 0x4A, 0x13, 0x68, 0x1E, 0x39, 0x0B, 0x43, 0x13, 0x60, 0x1B, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x03, 0xD0, 0x13, 0x68, 0x1E, 0x31, 0x0B, 0x43, 0x13, 0x60, 0x18, 0x4B, 0x9A, 0x68, 0x84, 0x23, ++0x17, 0x49, 0xD1, 0x50, 0x17, 0x4B, 0x80, 0x22, 0x92, 0x01, 0x1A, 0x60, 0xC2, 0x22, 0x05, 0x4B, 0x18, 0x68, 0x52, 0x00, ++0x01, 0xA9, 0xD8, 0xF7, 0x2F, 0xFA, 0x63, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0xFC, 0xE1, 0x10, 0x00, ++0x20, 0xCE, 0x10, 0x00, 0x08, 0x20, 0x04, 0x40, 0x04, 0x20, 0x04, 0x40, 0x24, 0x20, 0x04, 0x40, 0x10, 0x20, 0x04, 0x40, ++0xFF, 0xFE, 0xFF, 0xFF, 0x0C, 0x20, 0x04, 0x40, 0xB8, 0xE5, 0x10, 0x00, 0x00, 0x75, 0x19, 0x03, 0x00, 0x20, 0x04, 0x40, ++0x28, 0x20, 0x04, 0x40, 0x00, 0x30, 0x50, 0x40, 0xBC, 0xE5, 0x10, 0x00, 0x00, 0xED, 0x00, 0xE0, 0xC5, 0x88, 0x08, 0x00, ++0x00, 0xE1, 0x00, 0xE0, 0x70, 0x47, 0x70, 0x47, 0x3D, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, 0x3E, 0x4B, 0x8D, 0x22, 0x12, 0x03, ++0x1A, 0x60, 0x3D, 0x4B, 0x3D, 0x4A, 0x1A, 0x60, 0x3D, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, 0x3E, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, ++0x3E, 0x4B, 0x3F, 0x4A, 0x1A, 0x60, 0x3F, 0x4B, 0x3F, 0x4A, 0x1A, 0x60, 0x3F, 0x4B, 0x40, 0x4A, 0x1A, 0x60, 0x40, 0x4B, ++0x40, 0x4A, 0x1A, 0x60, 0x40, 0x4B, 0x41, 0x4A, 0x1A, 0x60, 0x41, 0x4B, 0x41, 0x4A, 0x1A, 0x60, 0x41, 0x4B, 0x42, 0x4A, ++0x1A, 0x60, 0x42, 0x4B, 0x42, 0x4A, 0x1A, 0x60, 0x42, 0x4B, 0x43, 0x4A, 0x1A, 0x60, 0x43, 0x4B, 0x43, 0x4A, 0x1A, 0x60, ++0x43, 0x4B, 0x44, 0x4A, 0x1A, 0x60, 0x44, 0x4B, 0x44, 0x4A, 0x1A, 0x60, 0x44, 0x4B, 0x45, 0x4A, 0x1A, 0x60, 0x45, 0x4B, ++0x45, 0x4A, 0x1A, 0x60, 0x45, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x88, 0x22, ++0x52, 0x01, 0x1A, 0x60, 0x45, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x46, 0x4A, 0x13, 0x60, 0x46, 0x4A, 0x47, 0x49, ++0x11, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4B, 0x47, 0x4A, 0x1A, 0x60, ++0x47, 0x4B, 0x48, 0x4A, 0x1A, 0x60, 0x48, 0x4B, 0x48, 0x4A, 0x1A, 0x60, 0x48, 0x4B, 0x49, 0x4A, 0x1A, 0x60, 0x49, 0x4B, ++0x49, 0x4A, 0x1A, 0x60, 0x49, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0xFF, 0x22, ++0x12, 0x02, 0x1A, 0x60, 0x49, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x74, 0x22, ++0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4B, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0x04, 0x01, 0x58, 0x40, ++0xFB, 0x33, 0x09, 0x00, 0x1C, 0x20, 0x62, 0x40, 0x28, 0x20, 0x62, 0x40, 0x20, 0x20, 0x91, 0x48, 0x14, 0x20, 0x62, 0x40, ++0x83, 0x89, 0x01, 0x00, 0x54, 0x20, 0x62, 0x40, 0x34, 0x8F, 0x00, 0x00, 0x48, 0x07, 0x62, 0x40, 0xA0, 0x01, 0x1A, 0x02, ++0x28, 0x07, 0x62, 0x40, 0x20, 0x00, 0x01, 0x00, 0x38, 0x07, 0x62, 0x40, 0xD4, 0x0F, 0x80, 0x04, 0x3C, 0x07, 0x62, 0x40, ++0x64, 0x00, 0xC8, 0x00, 0x2C, 0x20, 0x62, 0x40, 0x20, 0xB2, 0x0C, 0x00, 0x0C, 0x20, 0x62, 0x40, 0x45, 0x2B, 0xAD, 0xE9, ++0x30, 0x20, 0x62, 0x40, 0xD2, 0x30, 0x0C, 0x14, 0x34, 0x20, 0x62, 0x40, 0x02, 0x16, 0x00, 0x00, 0x54, 0x07, 0x62, 0x40, ++0xFD, 0x20, 0x42, 0x21, 0x58, 0x07, 0x62, 0x40, 0x1E, 0xF0, 0x07, 0x00, 0x1C, 0x07, 0x62, 0x40, 0x33, 0x0A, 0x00, 0x00, ++0x18, 0x20, 0x62, 0x40, 0x24, 0x41, 0x12, 0x00, 0x0C, 0x00, 0x62, 0x40, 0x00, 0x00, 0x04, 0x04, 0x90, 0x00, 0x62, 0x40, ++0x82, 0x90, 0x06, 0x00, 0x34, 0x10, 0x62, 0x40, 0x80, 0x30, 0x00, 0x02, 0x14, 0x10, 0x62, 0x40, 0x7A, 0x11, 0x45, 0x04, ++0x24, 0x20, 0x62, 0x40, 0x04, 0x20, 0x62, 0x40, 0xC0, 0xA9, 0x01, 0x00, 0x34, 0x08, 0x50, 0x00, 0x8C, 0x04, 0x60, 0x40, ++0x10, 0x01, 0x60, 0x40, 0x58, 0x00, 0x7E, 0x02, 0x80, 0x08, 0x60, 0x40, 0x84, 0x08, 0x60, 0x40, 0x88, 0x08, 0x60, 0x40, ++0x8C, 0x08, 0x60, 0x40, 0x34, 0x08, 0x00, 0x00, 0x18, 0x05, 0x62, 0x40, 0x0A, 0x88, 0x92, 0x36, 0x14, 0x05, 0x62, 0x40, ++0x10, 0x1A, 0x0C, 0xA8, 0x2C, 0x05, 0x62, 0x40, 0x03, 0x14, 0x0C, 0x9C, 0x0C, 0x05, 0x62, 0x40, 0x13, 0x20, 0x20, 0x20, ++0xA0, 0x05, 0x62, 0x40, 0x00, 0x0C, 0x15, 0x14, 0xA4, 0x05, 0x62, 0x40, 0x24, 0x36, 0x2D, 0x36, 0xF0, 0x05, 0x62, 0x40, ++0x08, 0x05, 0x62, 0x40, 0x32, 0x31, 0x55, 0x54, 0x30, 0x05, 0x62, 0x40, 0x00, 0x12, 0x17, 0x13, 0x34, 0x05, 0x62, 0x40, ++0xB0, 0x05, 0x62, 0x40, 0x55, 0x53, 0x00, 0x00, 0x1C, 0x05, 0x62, 0x40, 0x66, 0x57, 0x4B, 0x96, 0x2A, 0x49, 0x0B, 0x68, ++0x2A, 0x4A, 0x1A, 0x40, 0xFC, 0x23, 0x9B, 0x05, 0x13, 0x43, 0x0B, 0x60, 0x28, 0x4B, 0x29, 0x4A, 0x1A, 0x60, 0x29, 0x4B, ++0x29, 0x4A, 0x1A, 0x60, 0x29, 0x4B, 0x2A, 0x4A, 0x1A, 0x60, 0x2A, 0x4B, 0x2A, 0x4A, 0x1A, 0x60, 0x2A, 0x4B, 0x2B, 0x4A, ++0x1A, 0x60, 0x2B, 0x4B, 0x2B, 0x4A, 0x1A, 0x60, 0x2B, 0x4B, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x2C, 0x49, 0x11, 0x60, ++0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4B, 0x2D, 0x4A, 0x1A, 0x60, 0x2D, 0x4B, ++0x2D, 0x4A, 0x1A, 0x60, 0x2D, 0x4B, 0x2E, 0x4A, 0x1A, 0x60, 0x2E, 0x4B, 0x2E, 0x4A, 0x1A, 0x60, 0x2E, 0x4B, 0x2F, 0x4A, ++0x1A, 0x60, 0x2F, 0x4B, 0x2F, 0x4A, 0x1A, 0x60, 0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x30, 0x4A, 0x1A, 0x60, ++0x30, 0x4B, 0xFF, 0x22, 0x12, 0x02, 0x1A, 0x60, 0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x76, 0x22, 0x1A, 0x60, ++0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x31, 0x4A, 0x1A, 0x60, 0x31, 0x4B, ++0x31, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x0C, 0x00, 0x58, 0x40, 0xFF, 0xFF, 0xFF, 0xC0, 0x04, 0x01, 0x58, 0x40, ++0xFB, 0x33, 0x09, 0x00, 0x20, 0x40, 0x34, 0x40, 0x77, 0x0B, 0x00, 0x00, 0x24, 0x40, 0x34, 0x40, 0x94, 0xC5, 0x6E, 0x00, ++0x28, 0x40, 0x34, 0x40, 0x02, 0x94, 0x00, 0x00, 0x2C, 0x40, 0x34, 0x40, 0x84, 0x18, 0x20, 0x56, 0x30, 0x40, 0x34, 0x40, ++0x68, 0x51, 0x2E, 0x1A, 0x34, 0x08, 0x50, 0x00, 0x8C, 0x04, 0x60, 0x40, 0x10, 0x01, 0x60, 0x40, 0x58, 0x00, 0x7E, 0x02, ++0x80, 0x08, 0x60, 0x40, 0x84, 0x08, 0x60, 0x40, 0x88, 0x08, 0x60, 0x40, 0x8C, 0x08, 0x60, 0x40, 0x34, 0x08, 0x00, 0x00, ++0x18, 0x05, 0x62, 0x40, 0x0A, 0x88, 0x92, 0x36, 0x14, 0x05, 0x62, 0x40, 0x10, 0x1A, 0x0C, 0xA8, 0x2C, 0x05, 0x62, 0x40, ++0x03, 0x14, 0x0C, 0x9C, 0x0C, 0x05, 0x62, 0x40, 0x13, 0x20, 0x20, 0x20, 0x08, 0x05, 0x62, 0x40, 0x32, 0x31, 0x55, 0x54, ++0xA0, 0x05, 0x62, 0x40, 0x00, 0x16, 0x17, 0x0F, 0xA4, 0x05, 0x62, 0x40, 0x36, 0x36, 0x28, 0x36, 0xF0, 0x05, 0x62, 0x40, ++0x30, 0x05, 0x62, 0x40, 0x00, 0x1A, 0x17, 0x13, 0x34, 0x05, 0x62, 0x40, 0xB0, 0x05, 0x62, 0x40, 0x55, 0x53, 0x00, 0x00, ++0x1C, 0x05, 0x62, 0x40, 0x66, 0x57, 0x4B, 0x96, 0x90, 0x00, 0x62, 0x40, 0x32, 0x00, 0x05, 0x00, 0x10, 0x10, 0x62, 0x40, ++0x43, 0x01, 0x00, 0x12, 0x10, 0xB5, 0x01, 0x28, 0x03, 0xD0, 0x02, 0x38, 0x01, 0x28, 0x05, 0xD9, 0x10, 0xBD, 0x87, 0xF7, ++0x99, 0xFF, 0xFF, 0xF7, 0x2B, 0xFE, 0xF9, 0xE7, 0x88, 0xF7, 0x96, 0xF8, 0x0A, 0x4A, 0x11, 0x68, 0x80, 0x23, 0xDB, 0x05, ++0x0B, 0x43, 0x13, 0x60, 0xFF, 0xF7, 0x32, 0xFF, 0x07, 0x4B, 0x1B, 0x68, 0x9B, 0x02, 0xEB, 0xD4, 0x05, 0x49, 0x0B, 0x68, ++0x05, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0xE2, 0xE7, 0xC0, 0x46, 0x1C, 0x20, 0x34, 0x40, ++0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0x7F, 0xFF, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, ++0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x00, 0x24, 0x25, 0x4A, 0x26, 0x4B, 0x9B, 0x46, 0xE0, 0x23, 0xDB, 0x04, 0x9A, 0x46, ++0xC0, 0x23, 0x9B, 0x05, 0x99, 0x46, 0x23, 0x4B, 0x98, 0x46, 0x23, 0x4B, 0x00, 0x93, 0x23, 0x4F, 0x23, 0x4E, 0x13, 0x68, ++0x58, 0x46, 0x03, 0x40, 0x50, 0x46, 0x20, 0x40, 0x03, 0x43, 0x13, 0x60, 0x13, 0x68, 0x48, 0x46, 0x03, 0x43, 0x13, 0x60, ++0x43, 0x46, 0x1B, 0x68, 0x00, 0x98, 0x00, 0x68, 0x1B, 0x04, 0x3B, 0x40, 0x40, 0x04, 0x40, 0x0C, 0x03, 0x43, 0x08, 0xC5, ++0x13, 0x68, 0x33, 0x40, 0x13, 0x60, 0x80, 0x23, 0x5B, 0x04, 0x9C, 0x46, 0x64, 0x44, 0x80, 0x23, 0xDB, 0x04, 0x9C, 0x42, ++0xDF, 0xD1, 0x04, 0x20, 0x01, 0x9B, 0x01, 0x2B, 0x06, 0xD0, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, ++0xAB, 0x46, 0xF0, 0xBD, 0x0E, 0x4B, 0x1B, 0x68, 0x0B, 0x61, 0x0E, 0x4B, 0x1B, 0x68, 0x4B, 0x61, 0x0D, 0x4B, 0x1B, 0x68, ++0x8B, 0x61, 0x0D, 0x4B, 0x1B, 0x68, 0xCB, 0x61, 0x0C, 0x4B, 0x1B, 0x68, 0x0B, 0x62, 0x05, 0x30, 0xE7, 0xE7, 0xC0, 0x46, ++0x28, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0xFF, 0xF8, 0x8C, 0x08, 0x62, 0x40, 0x90, 0x08, 0x62, 0x40, 0x00, 0x00, 0xFF, 0x7F, ++0xFF, 0xFF, 0xFF, 0xCF, 0x30, 0x07, 0x62, 0x40, 0x34, 0x07, 0x62, 0x40, 0x5C, 0x07, 0x62, 0x40, 0x60, 0x07, 0x62, 0x40, ++0x20, 0x20, 0x62, 0x40, 0x12, 0x04, 0x12, 0x4B, 0x1A, 0x40, 0x49, 0x04, 0x49, 0x0C, 0x0A, 0x43, 0x10, 0x4B, 0x1A, 0x60, ++0x10, 0x4B, 0x1A, 0x68, 0x00, 0x06, 0xE0, 0x21, 0xC9, 0x04, 0x08, 0x40, 0x0E, 0x49, 0x0A, 0x40, 0x10, 0x43, 0x18, 0x60, ++0x19, 0x68, 0x80, 0x22, 0x12, 0x06, 0x0A, 0x43, 0x1A, 0x60, 0x19, 0x68, 0x80, 0x22, 0xD2, 0x05, 0x0A, 0x43, 0x1A, 0x60, ++0x1A, 0x68, 0x08, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x52, 0x00, 0x52, 0x08, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, ++0x00, 0x00, 0xFF, 0x7F, 0x44, 0x05, 0x62, 0x40, 0x28, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x1C, 0x49, 0x0B, 0x68, 0x99, 0x46, 0x1C, 0x4A, ++0x1A, 0x40, 0x1C, 0x4B, 0x13, 0x43, 0x0B, 0x60, 0x1B, 0x4B, 0x1B, 0x68, 0x98, 0x46, 0x1B, 0x4B, 0x1B, 0x68, 0x9A, 0x46, ++0x00, 0x24, 0xF0, 0x23, 0x47, 0x46, 0x9F, 0x43, 0x16, 0x4E, 0xE5, 0xB2, 0x00, 0x22, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, ++0xB1, 0xFF, 0x23, 0x01, 0x3B, 0x43, 0x33, 0x60, 0x88, 0xF7, 0x3D, 0xF9, 0x69, 0x46, 0x01, 0xA8, 0x88, 0xF7, 0x4A, 0xF9, ++0x00, 0x9A, 0x01, 0x99, 0x28, 0x00, 0xFF, 0xF7, 0xA3, 0xFF, 0x01, 0x34, 0x04, 0x2C, 0xE8, 0xD1, 0x07, 0x4B, 0x4A, 0x46, ++0x1A, 0x60, 0x09, 0x4B, 0x42, 0x46, 0x1A, 0x60, 0x08, 0x4B, 0x52, 0x46, 0x1A, 0x60, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x1C, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0x8F, 0x7F, 0x0A, 0x00, 0x20, 0x00, ++0x08, 0x05, 0x62, 0x40, 0x04, 0x00, 0x62, 0x40, 0x70, 0xB5, 0x0C, 0x4D, 0x2C, 0x68, 0x2A, 0x68, 0x0B, 0x4E, 0x32, 0x40, ++0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x2B, 0x60, 0x26, 0x20, 0x88, 0xF7, 0x3F, 0xFF, 0xFF, 0xF7, 0xA7, 0xFF, 0x88, 0xF7, ++0x81, 0xFF, 0x2B, 0x68, 0xE4, 0x05, 0xE4, 0x0F, 0x24, 0x02, 0x33, 0x40, 0x1C, 0x43, 0x2C, 0x60, 0x70, 0xBD, 0xC0, 0x46, ++0x00, 0x04, 0x60, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0x10, 0xB5, 0x26, 0x20, 0x88, 0xF7, 0x62, 0xF9, 0xFF, 0xF7, 0x92, 0xFF, ++0x88, 0xF7, 0xBA, 0xF9, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, ++0x8B, 0xB0, 0x82, 0x46, 0x0C, 0x00, 0x03, 0x68, 0x7F, 0x22, 0x1A, 0x40, 0x93, 0x46, 0x1E, 0x09, 0x0F, 0x25, 0x2E, 0x40, ++0x1D, 0x40, 0x01, 0x95, 0x0C, 0x22, 0x13, 0x42, 0x05, 0xD0, 0x35, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0x01, 0x9B, 0x9E, 0x42, 0x05, 0xD9, 0x30, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x2E, 0x4B, 0x98, 0x46, 0x1F, 0x68, 0x1A, 0x68, 0x2D, 0x4B, 0x99, 0x46, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, ++0x42, 0x46, 0x13, 0x60, 0x58, 0x46, 0x88, 0xF7, 0xF1, 0xFE, 0x53, 0x46, 0x19, 0x68, 0x03, 0xA8, 0x89, 0xF7, 0x0E, 0xF9, ++0x88, 0xF7, 0x30, 0xFF, 0x43, 0x46, 0x1B, 0x68, 0xFF, 0x05, 0xFF, 0x0F, 0x3F, 0x02, 0x4A, 0x46, 0x13, 0x40, 0x1F, 0x43, ++0x43, 0x46, 0x1F, 0x60, 0x01, 0x9B, 0x9E, 0x42, 0x30, 0xD8, 0x37, 0x00, 0x20, 0x36, 0x36, 0x01, 0x1D, 0x4B, 0xF6, 0x18, ++0x03, 0xA9, 0x1D, 0x4B, 0x98, 0x46, 0xF0, 0x23, 0x1B, 0x05, 0x9C, 0x46, 0x23, 0x1D, 0x99, 0x46, 0x05, 0xE0, 0x01, 0x37, ++0x10, 0x36, 0xFB, 0xB2, 0x01, 0x9A, 0x9A, 0x42, 0x1C, 0xD3, 0x7B, 0x18, 0x1A, 0x7D, 0x12, 0x02, 0xDB, 0x7B, 0x1A, 0x43, ++0x43, 0x46, 0x1A, 0x43, 0x32, 0x60, 0x7B, 0x5C, 0x18, 0x05, 0x65, 0x46, 0x28, 0x40, 0x1B, 0x07, 0x5B, 0x0F, 0x5B, 0x07, ++0x03, 0x43, 0x70, 0x68, 0x00, 0x02, 0x00, 0x0A, 0x03, 0x43, 0x73, 0x60, 0x00, 0x2C, 0xE2, 0xD0, 0xFB, 0x00, 0xE2, 0x50, ++0x4A, 0x46, 0x70, 0x68, 0xD0, 0x50, 0xDC, 0xE7, 0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0x00, 0x04, 0x60, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xD8, 0x99, 0x16, 0x00, ++0x00, 0x00, 0x80, 0x80, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x05, 0x00, ++0x01, 0x91, 0x03, 0x68, 0x5A, 0x02, 0x52, 0x0E, 0x90, 0x46, 0x1C, 0x09, 0x0F, 0x26, 0x34, 0x40, 0x1E, 0x40, 0x0C, 0x22, ++0x13, 0x42, 0x05, 0xD0, 0x38, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xB4, 0x42, 0x2F, 0xD9, ++0x34, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x40, 0x46, 0x88, 0xF7, 0xAD, 0xF8, 0x29, 0x68, ++0x02, 0xA8, 0x88, 0xF7, 0x09, 0xFB, 0x88, 0xF7, 0x03, 0xF9, 0x80, 0x22, 0x52, 0x00, 0x2D, 0x49, 0x2D, 0x48, 0xD7, 0xF7, ++0x49, 0xFE, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x01, 0x35, 0xEB, 0xB2, ++0x9E, 0x42, 0xEE, 0xD3, 0x2B, 0x01, 0xA8, 0x00, 0x63, 0x44, 0x1A, 0x68, 0x22, 0x40, 0x02, 0xA9, 0x41, 0x58, 0x00, 0x91, ++0xC9, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x01, 0x9B, 0x00, 0x2B, 0xED, 0xD0, 0x1A, 0x50, 0xEB, 0xE7, 0x40, 0x46, 0x88, 0xF7, ++0x83, 0xF8, 0x29, 0x68, 0x02, 0xA8, 0x88, 0xF7, 0xDF, 0xFA, 0x25, 0x00, 0xA2, 0x00, 0x02, 0xAB, 0x9C, 0x46, 0x62, 0x44, ++0xFC, 0x23, 0x1B, 0x01, 0x98, 0x46, 0xF8, 0x23, 0x5B, 0x02, 0x9C, 0x46, 0x3F, 0x20, 0xF8, 0x23, 0x9B, 0x03, 0x9B, 0x46, ++0x13, 0x68, 0x1F, 0x0A, 0x41, 0x46, 0x0F, 0x40, 0xB9, 0x46, 0xD9, 0x00, 0x0F, 0x00, 0x61, 0x46, 0x0F, 0x40, 0xBA, 0x46, ++0x4F, 0x46, 0x51, 0x46, 0x0F, 0x43, 0xB9, 0x46, 0x19, 0x0D, 0x0F, 0x00, 0x07, 0x40, 0xBA, 0x46, 0x4F, 0x46, 0x51, 0x46, ++0x0F, 0x43, 0x5B, 0x03, 0x59, 0x46, 0x0B, 0x40, 0x3B, 0x43, 0x08, 0xC2, 0x01, 0x34, 0xE4, 0xB2, 0xA6, 0x42, 0xE1, 0xD2, ++0x88, 0xF7, 0xAC, 0xF8, 0x02, 0x4B, 0x9C, 0x46, 0x03, 0x4C, 0xB5, 0xE7, 0x28, 0x19, 0x16, 0x00, 0xD8, 0x97, 0x16, 0x00, ++0x00, 0x50, 0x1E, 0x00, 0x7F, 0x00, 0x00, 0xE0, 0x70, 0xB5, 0x8E, 0xB0, 0x87, 0xF7, 0x76, 0xFF, 0x04, 0x00, 0x01, 0x28, ++0x05, 0xD0, 0x83, 0x1E, 0xDB, 0xB2, 0x01, 0x2B, 0x24, 0xD9, 0x0E, 0xB0, 0x70, 0xBD, 0x1C, 0x4B, 0x00, 0x93, 0x1C, 0x4C, ++0x25, 0x68, 0xF0, 0x23, 0x2A, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x70, 0x22, 0x13, 0x43, 0x23, 0x60, 0x01, 0xA9, 0x68, 0x46, ++0xFF, 0xF7, 0x56, 0xFF, 0x25, 0x60, 0x16, 0x4B, 0x00, 0x93, 0x00, 0x21, 0x68, 0x46, 0x88, 0xF7, 0xE9, 0xFC, 0x00, 0x20, ++0x88, 0xF7, 0xD0, 0xFB, 0x05, 0xA9, 0x01, 0x20, 0xFF, 0xF7, 0xB0, 0xFD, 0x01, 0x20, 0x89, 0xF7, 0x43, 0xFA, 0xFF, 0xF7, ++0xAF, 0xFE, 0xDA, 0xE7, 0x0A, 0x4B, 0x00, 0x93, 0x0A, 0x4D, 0x2E, 0x68, 0xF0, 0x23, 0x32, 0x00, 0x9A, 0x43, 0x13, 0x00, ++0x70, 0x22, 0x13, 0x43, 0x2B, 0x60, 0x01, 0xA9, 0x68, 0x46, 0xFF, 0xF7, 0xA9, 0xFE, 0x2E, 0x60, 0x20, 0x00, 0x89, 0xF7, ++0x2D, 0xFA, 0xFF, 0xF7, 0x7B, 0xFE, 0xC4, 0xE7, 0x03, 0x42, 0x26, 0x00, 0x08, 0x05, 0x62, 0x40, 0x0F, 0x30, 0x02, 0x00, ++0x30, 0xB5, 0x83, 0xB0, 0x41, 0x4B, 0x18, 0x78, 0x87, 0xF7, 0x12, 0xFF, 0x40, 0x4A, 0x80, 0x23, 0x5B, 0x00, 0x06, 0x21, ++0xD1, 0x50, 0x3F, 0x4B, 0x5A, 0x68, 0x3F, 0x49, 0x0A, 0x40, 0x5A, 0x60, 0x59, 0x68, 0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, ++0x5A, 0x60, 0x19, 0x00, 0x44, 0x22, 0x0B, 0x6B, 0x13, 0x40, 0x04, 0x2B, 0xFB, 0xD1, 0x39, 0x4B, 0x18, 0x68, 0x39, 0x49, ++0xD7, 0xF7, 0x32, 0xF9, 0xA0, 0x23, 0x5B, 0x03, 0x03, 0x43, 0x37, 0x4A, 0x13, 0x60, 0x37, 0x49, 0x08, 0x43, 0x10, 0x60, ++0x13, 0x60, 0x30, 0x4B, 0x59, 0x68, 0x35, 0x4A, 0x0A, 0x43, 0x5A, 0x60, 0x2C, 0x49, 0x9A, 0x22, 0x52, 0x00, 0x80, 0x20, ++0x40, 0x01, 0x88, 0x50, 0x1A, 0x68, 0x40, 0x20, 0x02, 0x43, 0x1A, 0x60, 0x18, 0x68, 0x02, 0x24, 0x20, 0x43, 0x18, 0x60, ++0x48, 0x6F, 0x01, 0x22, 0x10, 0x43, 0x48, 0x67, 0x59, 0x6D, 0x2B, 0x4A, 0x11, 0x40, 0x59, 0x65, 0x5A, 0x6D, 0x22, 0x43, ++0x5A, 0x65, 0x5A, 0x6D, 0x28, 0x49, 0x0A, 0x40, 0x5A, 0x65, 0x87, 0xF7, 0xE1, 0xFE, 0x04, 0x00, 0x80, 0x22, 0x52, 0x00, ++0x25, 0x49, 0x26, 0x48, 0xD7, 0xF7, 0x4C, 0xFD, 0x80, 0x22, 0x25, 0x49, 0x25, 0x48, 0xD7, 0xF7, 0x47, 0xFD, 0x01, 0x2C, ++0x05, 0xD1, 0x17, 0x4B, 0xDB, 0x6D, 0x9B, 0x07, 0x0D, 0xD5, 0x03, 0xB0, 0x30, 0xBD, 0xC0, 0x22, 0x92, 0x00, 0x20, 0x49, ++0x20, 0x48, 0xD7, 0xF7, 0x39, 0xFD, 0x80, 0x22, 0x1F, 0x49, 0x20, 0x48, 0xD7, 0xF7, 0x34, 0xFD, 0xED, 0xE7, 0x20, 0x00, ++0x87, 0xF7, 0xD2, 0xFE, 0x20, 0x00, 0xFF, 0xF7, 0xF1, 0xFC, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0xFF, 0xF7, 0x39, 0xFF, 0x05, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0xDF, 0xD1, 0x16, 0x4A, 0x13, 0x68, 0x01, 0x21, ++0x8B, 0x43, 0x13, 0x60, 0xD9, 0xE7, 0xC0, 0x46, 0xB4, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, ++0xFF, 0xFF, 0xFB, 0xFF, 0xB0, 0x06, 0x16, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x08, 0x00, 0x58, 0x40, 0x00, 0x00, 0x14, 0x80, ++0x02, 0x88, 0x01, 0x00, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x58, 0xE0, 0x10, 0x00, 0xD8, 0x97, 0x16, 0x00, ++0x58, 0xE1, 0x10, 0x00, 0xD8, 0x98, 0x16, 0x00, 0x18, 0xE2, 0x10, 0x00, 0xD8, 0x99, 0x16, 0x00, 0x18, 0xE5, 0x10, 0x00, ++0x58, 0x99, 0x16, 0x00, 0x04, 0x30, 0x34, 0x40, 0x80, 0x00, 0x01, 0x4B, 0xC0, 0x58, 0x70, 0x47, 0x38, 0x27, 0x16, 0x00, ++0x80, 0x00, 0x01, 0x4B, 0xC0, 0x58, 0x70, 0x47, 0x54, 0x27, 0x16, 0x00, 0x80, 0x00, 0x01, 0x4B, 0x19, 0x50, 0x70, 0x47, ++0x54, 0x27, 0x16, 0x00, 0x03, 0x23, 0x03, 0x40, 0x8B, 0x42, 0x05, 0xD8, 0x03, 0x23, 0x98, 0x43, 0x40, 0x18, 0x00, 0x01, ++0x00, 0x09, 0x70, 0x47, 0x03, 0x30, 0x03, 0x23, 0x98, 0x43, 0x40, 0x18, 0xF7, 0xE7, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x05, 0x00, 0x0F, 0x00, 0x14, 0x00, 0x06, 0xAB, 0x04, 0xCB, 0x90, 0x46, 0x1A, 0x78, 0x1B, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x01, 0xD0, 0x00, 0x2A, 0x06, 0xD0, 0x18, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x00, 0x21, 0x99, 0x70, 0xD9, 0x70, ++0x5A, 0x70, 0xAB, 0x68, 0x2A, 0x69, 0x94, 0x46, 0x63, 0x44, 0x18, 0x00, 0x13, 0x49, 0xD7, 0xF7, 0x63, 0xF8, 0x06, 0x00, ++0x10, 0x4B, 0x5D, 0x60, 0x9F, 0x60, 0xDC, 0x60, 0x18, 0x61, 0x00, 0x2C, 0x05, 0xD1, 0x0F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0A, 0x4D, 0x21, 0x00, 0x38, 0x00, 0xD7, 0xF7, 0xD6, 0xF8, 0x29, 0x77, 0x43, 0x46, ++0x6B, 0x61, 0xA4, 0x1B, 0x62, 0x01, 0x12, 0x1B, 0x92, 0x00, 0x12, 0x19, 0x90, 0x00, 0x12, 0x18, 0x78, 0x3A, 0xAA, 0x61, ++0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x74, 0xE6, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x80, 0x46, 0x00, 0x91, 0x01, 0x92, 0x99, 0x46, ++0x40, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA3, 0x46, 0xF0, 0xBD, ++0x3C, 0x4B, 0x1E, 0x68, 0xB4, 0x68, 0x00, 0x2C, 0xF4, 0xD0, 0x00, 0x25, 0x1F, 0x23, 0x9B, 0x46, 0x01, 0x27, 0x03, 0xE0, ++0x3B, 0x00, 0x83, 0x40, 0x9C, 0x43, 0x0D, 0xD0, 0x20, 0x00, 0xD7, 0xF7, 0x8B, 0xF9, 0x5B, 0x46, 0x18, 0x1A, 0x43, 0x1C, ++0xDB, 0x00, 0xF3, 0x18, 0x5B, 0x68, 0x00, 0x2B, 0xF0, 0xD0, 0x01, 0x35, 0xED, 0xB2, 0xED, 0xE7, 0x01, 0x2D, 0xDB, 0xD1, ++0x2C, 0x4B, 0x5C, 0x68, 0xA3, 0x68, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1E, 0x00, 0x2B, 0x49, 0x18, 0x00, 0xD6, 0xF7, ++0xFD, 0xFF, 0x05, 0x00, 0x64, 0x68, 0x04, 0x19, 0x27, 0x49, 0x30, 0x00, 0xD7, 0xF7, 0x7C, 0xF8, 0x4B, 0x46, 0x9B, 0x68, ++0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x64, 0x18, 0x4B, 0x46, 0x99, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, ++0x03, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x54, 0xFF, 0x04, 0x00, 0x43, 0x46, 0x1B, 0x68, 0xE1, 0x1A, 0x0A, 0x01, 0x12, 0x09, ++0x80, 0x20, 0x00, 0x05, 0x82, 0x42, 0x11, 0xD8, 0x09, 0x01, 0x0F, 0xD0, 0x15, 0x4A, 0xD1, 0x68, 0xCB, 0x18, 0xE2, 0x1A, ++0x12, 0x01, 0x12, 0x09, 0x82, 0x42, 0x07, 0xD8, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x1A, 0x1B, 0x01, 0x02, 0xD0, 0x64, 0x1A, ++0x24, 0x01, 0x24, 0x09, 0x43, 0x46, 0x1C, 0x60, 0x0C, 0x4B, 0xDA, 0x68, 0x55, 0x1B, 0x68, 0x01, 0x40, 0x1B, 0x80, 0x00, ++0x40, 0x19, 0x82, 0x00, 0x80, 0x18, 0x0B, 0x4A, 0x94, 0x46, 0x60, 0x44, 0x00, 0x9A, 0x10, 0x60, 0xD8, 0x68, 0x60, 0x28, ++0x02, 0xD8, 0x01, 0x9B, 0x18, 0x60, 0x87, 0xE7, 0x24, 0x21, 0xD6, 0xF7, 0xB1, 0xFF, 0x01, 0x9B, 0x18, 0x60, 0x81, 0xE7, ++0x74, 0xE6, 0x10, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x1E, 0xFB, 0xFF, 0xFF, 0x03, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x02, 0xD0, 0x01, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x70, 0x47, 0x74, 0xE6, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x06, 0x00, 0x01, 0x92, 0x38, 0x4B, 0x38, 0x4A, 0x13, 0x60, ++0x9C, 0x68, 0x00, 0x2C, 0x08, 0xD0, 0x43, 0x68, 0x9B, 0x46, 0x36, 0x4B, 0x99, 0x46, 0x36, 0x4B, 0x98, 0x46, 0x33, 0x4B, ++0x9A, 0x46, 0x0F, 0xE0, 0xD5, 0xF7, 0x8C, 0xF9, 0x04, 0x1E, 0x5B, 0xD0, 0x73, 0x68, 0x9B, 0x46, 0xF1, 0xE7, 0x75, 0x60, ++0x53, 0x46, 0x1B, 0x68, 0x9B, 0x68, 0xA3, 0x42, 0x46, 0xD0, 0x24, 0x68, 0x00, 0x2C, 0x47, 0xD0, 0x21, 0x00, 0x30, 0x00, ++0xC8, 0x47, 0x00, 0x28, 0x43, 0xD0, 0x05, 0x28, 0xF0, 0xD0, 0xA3, 0x68, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x00, ++0x41, 0x46, 0x18, 0x00, 0xD6, 0xF7, 0x64, 0xFF, 0x63, 0x68, 0xC5, 0x18, 0x41, 0x46, 0x38, 0x00, 0xD6, 0xF7, 0xE4, 0xFF, ++0xB3, 0x68, 0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x6D, 0x18, 0xB1, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, ++0x03, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0xBE, 0xFE, 0x05, 0x00, 0x5B, 0x46, 0xEB, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x22, ++0x12, 0x05, 0x93, 0x42, 0x04, 0xD9, 0x5B, 0x46, 0x5B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0x01, 0x9A, 0x93, 0x42, ++0xC1, 0xD9, 0x63, 0x7E, 0x0B, 0x2B, 0x03, 0xD8, 0x10, 0x4A, 0xDA, 0x40, 0xD3, 0x07, 0xBA, 0xD4, 0xA3, 0x7D, 0xB2, 0x7D, ++0x01, 0x20, 0x9A, 0x42, 0x07, 0xD8, 0x01, 0x33, 0xB3, 0x75, 0x04, 0xE0, 0xD5, 0xF7, 0x38, 0xF9, 0x04, 0x00, 0xB5, 0xE7, ++0x00, 0x20, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x00, 0x20, 0xF6, 0xE7, ++0x64, 0x2A, 0x16, 0x00, 0x10, 0xE7, 0x10, 0x00, 0x51, 0x62, 0x0D, 0x00, 0x71, 0x02, 0x00, 0x00, 0x6A, 0x0C, 0x00, 0x00, ++0x01, 0x4B, 0x18, 0x68, 0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x1B, 0x68, 0x01, 0x20, 0x18, 0x40, ++0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0x80, 0x07, 0xC0, 0x0F, 0x70, 0x47, 0xC0, 0x46, ++0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0xC0, 0x07, 0x70, 0x47, 0xC0, 0x46, 0x48, 0x30, 0x34, 0x40, ++0x01, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0x70, 0x47, 0x48, 0x30, 0x34, 0x40, 0x02, 0x4B, 0x18, 0x68, 0x40, 0x07, 0xC0, 0x0F, ++0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x03, 0x4B, 0x1B, 0x68, 0x14, 0x20, 0x18, 0x40, 0x43, 0x1E, 0x98, 0x41, ++0xC0, 0xB2, 0x70, 0x47, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0x06, 0xC0, 0x0F, 0x70, 0x47, 0xC0, 0x46, ++0x94, 0x40, 0x04, 0x40, 0x01, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0x70, 0x47, 0x98, 0x40, 0x04, 0x40, 0x10, 0xB5, 0x10, 0x4B, ++0x1A, 0x68, 0x00, 0x23, 0x01, 0x2A, 0x02, 0xD9, 0x01, 0x20, 0x18, 0x40, 0x10, 0xBD, 0xFF, 0xF7, 0xCF, 0xFF, 0x00, 0x23, ++0x00, 0x28, 0xF7, 0xD0, 0xFF, 0xF7, 0xE2, 0xFF, 0x00, 0x28, 0x03, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x05, 0xDA, ++0xFF, 0xF7, 0xB2, 0xFF, 0x01, 0x23, 0x43, 0x40, 0xDB, 0xB2, 0xE9, 0xE7, 0xFF, 0xF7, 0xC2, 0xFF, 0x00, 0x23, 0x00, 0x28, ++0xE4, 0xD0, 0xF3, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0x98, 0x40, 0x04, 0x40, 0x10, 0xB5, 0xFF, 0xF7, 0xB7, 0xFF, 0x00, 0x23, ++0x00, 0x28, 0x02, 0xD1, 0x01, 0x20, 0x18, 0x40, 0x10, 0xBD, 0xFF, 0xF7, 0x99, 0xFF, 0x01, 0x23, 0x43, 0x40, 0xDB, 0xB2, ++0xF6, 0xE7, 0x00, 0x00, 0x05, 0x4B, 0x1B, 0x68, 0x00, 0x28, 0x04, 0xD0, 0x08, 0x22, 0x13, 0x43, 0x02, 0x4A, 0x13, 0x60, ++0x70, 0x47, 0x08, 0x22, 0x93, 0x43, 0xF9, 0xE7, 0x94, 0x40, 0x04, 0x40, 0x04, 0x4A, 0x13, 0x68, 0x40, 0x01, 0x04, 0x49, ++0x0B, 0x40, 0x04, 0x49, 0x08, 0x40, 0x18, 0x43, 0x10, 0x60, 0x70, 0x47, 0x94, 0x40, 0x04, 0x40, 0x1F, 0x00, 0xFE, 0xFF, ++0xE0, 0xFF, 0x01, 0x00, 0x03, 0x4B, 0x1B, 0x68, 0x00, 0x20, 0x01, 0x22, 0x9A, 0x42, 0x40, 0x41, 0xC0, 0xB2, 0x70, 0x47, ++0x50, 0xE0, 0x10, 0x00, 0x02, 0x4B, 0x18, 0x68, 0x43, 0x42, 0x58, 0x41, 0xC0, 0xB2, 0x70, 0x47, 0x50, 0xE0, 0x10, 0x00, ++0x70, 0xB5, 0x01, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x0F, 0xD0, 0x70, 0xBD, 0x0E, 0x4C, 0xEA, 0x25, 0x6D, 0x00, 0x02, 0x22, ++0x02, 0x21, 0x20, 0x00, 0x2B, 0x68, 0x98, 0x47, 0x80, 0x22, 0x2B, 0x68, 0x92, 0x01, 0x00, 0x21, 0x20, 0x00, 0x98, 0x47, ++0xEF, 0xE7, 0x80, 0x21, 0x89, 0x01, 0x06, 0x4C, 0xEA, 0x25, 0x6D, 0x00, 0x0A, 0x00, 0x20, 0x00, 0x2B, 0x68, 0x98, 0x47, ++0x2B, 0x68, 0x02, 0x22, 0x00, 0x21, 0x20, 0x00, 0x98, 0x47, 0xE0, 0xE7, 0x00, 0x10, 0x01, 0x50, 0x70, 0xB5, 0x05, 0x00, ++0x0C, 0x00, 0x39, 0x4B, 0x1B, 0x68, 0x01, 0x20, 0x00, 0x2B, 0x45, 0xD1, 0x00, 0x29, 0x43, 0xD0, 0x00, 0x2D, 0x1A, 0xD0, ++0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x16, 0x00, 0x1E, 0x40, 0x1A, 0x42, 0x4E, 0xD1, 0x72, 0xB6, 0x31, 0x4B, 0x1B, 0x68, ++0x00, 0x2B, 0x41, 0xD1, 0x00, 0x20, 0x00, 0x2E, 0x4A, 0xD1, 0x62, 0xB6, 0x27, 0xE0, 0x20, 0x00, 0xFF, 0xF7, 0xBA, 0xFF, ++0x2B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x28, 0x00, 0x00, 0x2E, 0x20, 0xD1, 0xF3, 0xE7, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, ++0x16, 0x00, 0x1E, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x24, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x1B, 0xD1, 0x01, 0x20, ++0x87, 0xF7, 0x51, 0xFC, 0x20, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x14, 0xD1, 0x01, 0x20, 0x87, 0xF7, 0x4A, 0xFC, 0x28, 0x00, ++0x00, 0x2E, 0x00, 0xD1, 0x62, 0xB6, 0x1C, 0x4A, 0x13, 0x68, 0x01, 0x33, 0x13, 0x60, 0x00, 0x28, 0x1E, 0xD0, 0x00, 0x23, ++0x19, 0x4A, 0x13, 0x60, 0x19, 0x4A, 0x13, 0x60, 0x16, 0x4A, 0x13, 0x60, 0x70, 0xBD, 0x20, 0x00, 0xFF, 0xF7, 0x88, 0xFF, ++0x12, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x01, 0x20, 0x87, 0xF7, 0x2F, 0xFC, 0x01, 0x20, 0xE3, 0xE7, 0x08, 0x00, 0xFF, 0xF7, ++0x7D, 0xFF, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x28, 0x00, 0xB8, 0xE7, 0x0A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xB6, 0xD1, ++0x09, 0x4B, 0x1B, 0x68, 0x00, 0x20, 0x05, 0x2B, 0xDB, 0xD8, 0x08, 0x4B, 0x1C, 0x60, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x07, 0x48, 0x82, 0xF7, 0x2F, 0xFC, 0x00, 0x20, 0xD8, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x54, 0xE6, 0x10, 0x00, 0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x2C, 0xCE, 0x10, 0x00, 0xF0, 0xB5, 0xCE, 0x46, ++0x00, 0xB5, 0x86, 0xB0, 0x2A, 0x4B, 0x1C, 0x68, 0x21, 0x00, 0x2A, 0x48, 0x82, 0xF7, 0x16, 0xFC, 0x03, 0xAA, 0x29, 0x4B, ++0x03, 0xCB, 0x03, 0xC2, 0x1B, 0x88, 0x13, 0x80, 0x00, 0x2C, 0x0D, 0xDB, 0x0A, 0x22, 0x03, 0xA9, 0x25, 0x48, 0xD7, 0xF7, ++0xFD, 0xF9, 0x0A, 0x22, 0x03, 0xA9, 0x24, 0x48, 0xD7, 0xF7, 0xF8, 0xF9, 0x06, 0xB0, 0x04, 0xBC, 0x91, 0x46, 0xF0, 0xBD, ++0xFF, 0x23, 0x1B, 0x04, 0x23, 0x40, 0x80, 0x22, 0x52, 0x02, 0x93, 0x42, 0x11, 0xD0, 0x24, 0x04, 0x24, 0x0C, 0x1D, 0x4B, ++0xE7, 0x18, 0x1D, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0xFB, 0x43, 0xDB, 0x17, 0x1F, 0x40, 0x4E, 0x2C, 0x00, 0xDD, 0x4E, 0x24, ++0x03, 0xAD, 0x00, 0x26, 0x00, 0x23, 0x01, 0x93, 0x1B, 0xE0, 0x24, 0x04, 0x24, 0x0C, 0x16, 0x4B, 0xE7, 0x18, 0x16, 0x4B, ++0x9C, 0x46, 0x64, 0x44, 0xEC, 0xE7, 0x8B, 0x40, 0x1A, 0x43, 0xD2, 0xB2, 0x01, 0x31, 0x08, 0x29, 0x07, 0xD0, 0x88, 0x19, ++0x01, 0x23, 0xB8, 0x42, 0xF5, 0xDB, 0xA0, 0x42, 0xF3, 0xDC, 0x01, 0x9B, 0xF1, 0xE7, 0x4B, 0x46, 0x1A, 0x70, 0x01, 0x35, ++0x08, 0x36, 0x50, 0x2E, 0xBC, 0xD0, 0xA9, 0x46, 0x00, 0x22, 0x00, 0x21, 0xED, 0xE7, 0xC0, 0x46, 0x98, 0x40, 0x04, 0x40, ++0x34, 0xCE, 0x10, 0x00, 0x48, 0xCE, 0x10, 0x00, 0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x94, 0xF6, 0xFF, 0xFF, ++0xA7, 0xF6, 0xFF, 0xFF, 0x8A, 0xF6, 0xFF, 0xFF, 0xB1, 0xF6, 0xFF, 0xFF, 0x10, 0xB5, 0x84, 0xB0, 0x98, 0x4B, 0x1C, 0x68, ++0x21, 0x00, 0x98, 0x48, 0x82, 0xF7, 0xAC, 0xFB, 0x01, 0xAA, 0x97, 0x4B, 0x03, 0xCB, 0x03, 0xC2, 0x1B, 0x88, 0x13, 0x80, ++0x00, 0x2C, 0x0B, 0xDB, 0x0A, 0x22, 0x01, 0xA9, 0x93, 0x48, 0xD7, 0xF7, 0x93, 0xF9, 0x0A, 0x22, 0x01, 0xA9, 0x92, 0x48, ++0xD7, 0xF7, 0x8E, 0xF9, 0x04, 0xB0, 0x10, 0xBD, 0xFF, 0x23, 0x1B, 0x04, 0x23, 0x40, 0x80, 0x22, 0x52, 0x02, 0x93, 0x42, ++0x00, 0xD1, 0x02, 0xE1, 0x24, 0x04, 0x24, 0x0C, 0x8B, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x3C, 0x2C, 0xE4, 0xD8, 0xA4, 0x00, ++0x89, 0x4B, 0x1B, 0x59, 0x9F, 0x46, 0x01, 0xAB, 0x00, 0x22, 0x1A, 0x70, 0x5A, 0x70, 0x9A, 0x70, 0xFC, 0x32, 0xDA, 0x70, ++0xD8, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, 0x1A, 0x70, 0x00, 0x22, 0x5A, 0x70, 0x9A, 0x70, 0xFC, 0x32, 0xDA, 0x70, ++0x14, 0x29, 0xCD, 0xD1, 0x00, 0x22, 0x1A, 0x70, 0xDA, 0x70, 0x1A, 0x71, 0xC8, 0xE7, 0x14, 0x21, 0xEE, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x03, 0x22, 0x5A, 0x70, 0x00, 0x22, 0x9A, 0x70, 0xC0, 0x32, 0xDA, 0x70, 0x14, 0x29, 0xBC, 0xD1, 0x00, 0x22, ++0x1A, 0x70, 0x5A, 0x70, 0xDA, 0x70, 0x1A, 0x71, 0xF0, 0x32, 0x5A, 0x71, 0xB4, 0xE7, 0x14, 0x21, 0xEC, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x00, 0x22, 0x9A, 0x70, 0xDA, 0x70, 0xF0, 0x32, 0x1A, 0x71, 0x14, 0x29, 0xA9, 0xD1, 0xED, 0x3A, 0x1A, 0x70, ++0x00, 0x22, 0x5A, 0x70, 0x1A, 0x71, 0x5A, 0x71, 0xA2, 0xE7, 0x14, 0x21, 0xEE, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, ++0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x1A, 0x71, 0xFC, 0x32, 0x5A, 0x71, 0x14, 0x29, 0x95, 0xD1, 0x00, 0x22, 0x5A, 0x70, ++0x9A, 0x70, 0x5A, 0x71, 0xF0, 0x32, 0x9A, 0x71, 0x8E, 0xE7, 0x14, 0x21, 0xEC, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x03, 0x22, ++0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0xC0, 0x32, 0x5A, 0x71, 0x14, 0x29, 0x00, 0xD0, 0x81, 0xE7, 0x81, 0x3A, 0x5A, 0x70, ++0x00, 0x22, 0x9A, 0x70, 0xDA, 0x70, 0x5A, 0x71, 0xFC, 0x32, 0x9A, 0x71, 0x78, 0xE7, 0x14, 0x21, 0xEA, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x3F, 0x22, 0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0x5A, 0x71, 0xFC, 0x32, 0x9A, 0x71, 0x14, 0x29, 0x00, 0xD0, ++0x6A, 0xE7, 0xF9, 0x3A, 0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x9A, 0x71, 0xC0, 0x32, 0xDA, 0x71, 0x62, 0xE7, 0x14, 0x21, ++0xEA, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x0F, 0x22, 0x1A, 0x71, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0x14, 0x29, 0x00, 0xD0, ++0x56, 0xE7, 0x3F, 0x32, 0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x1A, 0x71, 0xDA, 0x71, 0x4F, 0xE7, 0x14, 0x21, 0xED, 0xE7, ++0x0A, 0x21, 0x01, 0xAB, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0xF0, 0x32, 0xDA, 0x71, 0x14, 0x29, 0x00, 0xD0, 0x43, 0xE7, ++0xE1, 0x3A, 0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0xDA, 0x71, 0x1A, 0x72, 0x3C, 0xE7, 0x14, 0x21, 0xED, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x3F, 0x22, 0x5A, 0x71, 0x00, 0x22, 0x9A, 0x71, 0xDA, 0x71, 0xFC, 0x32, 0x1A, 0x72, 0x14, 0x29, 0x00, 0xD0, ++0x2E, 0xE7, 0xED, 0x3A, 0x1A, 0x71, 0x00, 0x22, 0x5A, 0x71, 0x1A, 0x72, 0x5A, 0x72, 0x27, 0xE7, 0x14, 0x21, 0xEB, 0xE7, ++0x0A, 0x21, 0x01, 0xAB, 0x03, 0x22, 0x9A, 0x71, 0x00, 0x22, 0xDA, 0x71, 0xC0, 0x32, 0x1A, 0x72, 0x14, 0x29, 0x00, 0xD0, ++0x1A, 0xE7, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0x1A, 0x72, 0x5A, 0x72, 0x14, 0xE7, 0x14, 0x21, 0xED, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x00, 0x22, 0xDA, 0x71, 0x1A, 0x72, 0xF0, 0x32, 0x5A, 0x72, 0x14, 0x29, 0x00, 0xD0, 0x08, 0xE7, 0x00, 0x22, ++0x9A, 0x71, 0x5A, 0x72, 0x04, 0xE7, 0x14, 0x21, 0xF0, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, 0xDA, 0x71, 0x00, 0x22, ++0x1A, 0x72, 0x5A, 0x72, 0x14, 0x29, 0x00, 0xD0, 0xF8, 0xE6, 0x0F, 0x32, 0x9A, 0x71, 0x00, 0x22, 0xDA, 0x71, 0xF3, 0xE6, ++0x14, 0x21, 0xEF, 0xE7, 0x01, 0xAB, 0x00, 0x22, 0x1A, 0x70, 0x5A, 0x70, 0x9A, 0x70, 0xDA, 0x70, 0xFC, 0x32, 0x1A, 0x71, ++0xE8, 0xE6, 0x24, 0x04, 0x24, 0x0C, 0x0A, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x3C, 0x2C, 0x00, 0xD9, 0xE0, 0xE6, 0xA4, 0x00, ++0x08, 0x4B, 0x1B, 0x59, 0x9F, 0x46, 0xC0, 0x46, 0x98, 0x40, 0x04, 0x40, 0x34, 0xCE, 0x10, 0x00, 0x48, 0xCE, 0x10, 0x00, ++0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x94, 0xF6, 0xFF, 0xFF, 0x54, 0xCE, 0x10, 0x00, 0x48, 0xCF, 0x10, 0x00, ++0x10, 0xB5, 0x08, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0x06, 0x4B, 0x1A, 0x6B, 0x06, 0x4B, 0x19, 0x68, ++0x01, 0x20, 0x81, 0x43, 0x19, 0x60, 0x19, 0x68, 0x04, 0x48, 0x82, 0xF7, 0x5F, 0xFA, 0xF2, 0xE7, 0xB4, 0xE5, 0x10, 0x00, ++0x00, 0x60, 0x50, 0x40, 0x04, 0x30, 0x34, 0x40, 0x3C, 0xD0, 0x10, 0x00, 0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x4C, 0x4B, ++0x1B, 0x68, 0x01, 0x2B, 0x02, 0xD0, 0x4B, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x4A, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, ++0x13, 0x60, 0xA9, 0xF7, 0x71, 0xFD, 0x48, 0x4B, 0x18, 0x60, 0x5C, 0x60, 0x0C, 0x2D, 0x38, 0xD8, 0xAD, 0x00, 0x46, 0x4B, ++0x5B, 0x59, 0x9F, 0x46, 0x80, 0x23, 0xDB, 0x01, 0x00, 0x21, 0x9C, 0x42, 0x1B, 0xD3, 0x43, 0x4A, 0x13, 0x68, 0x43, 0x49, ++0x19, 0x40, 0x80, 0x23, 0x9B, 0x02, 0x0B, 0x43, 0x13, 0x60, 0x11, 0x68, 0xE3, 0x08, 0xC0, 0x20, 0x40, 0x01, 0x03, 0x40, ++0x76, 0x20, 0x03, 0x43, 0x09, 0x0C, 0x09, 0x04, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x3B, 0x49, 0x19, 0x40, 0x80, 0x23, ++0x1B, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x80, 0x21, 0xC9, 0x01, 0x35, 0x4B, 0x1A, 0x68, 0x35, 0x48, 0x02, 0x40, 0x1A, 0x60, ++0x1A, 0x68, 0xA4, 0x04, 0xA4, 0x0C, 0x0C, 0x43, 0x12, 0x0C, 0x12, 0x04, 0x14, 0x43, 0x1C, 0x60, 0x1A, 0x68, 0x30, 0x49, ++0x11, 0x40, 0x80, 0x22, 0x12, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x70, 0xBD, 0x2D, 0x4B, 0x1B, 0x68, 0x9A, 0x6A, 0x5B, 0x6B, ++0xD2, 0x1A, 0xD5, 0x00, 0x55, 0x19, 0x6D, 0x00, 0x55, 0x19, 0xAD, 0xB2, 0x2A, 0x00, 0x21, 0x00, 0x28, 0x48, 0x82, 0xF7, ++0xF7, 0xF9, 0x23, 0x4B, 0x19, 0x68, 0x23, 0x4E, 0x31, 0x40, 0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, ++0x12, 0x0C, 0x12, 0x04, 0x6D, 0x05, 0x6D, 0x0D, 0x2A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x1D, 0x48, 0x02, 0x40, 0x80, 0x21, ++0x09, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x16, 0x40, 0x1E, 0x60, 0x1A, 0x68, 0xA4, 0x04, 0xA4, 0x0C, 0x80, 0x25, ++0x2D, 0x02, 0x2C, 0x43, 0x12, 0x0C, 0x12, 0x04, 0x14, 0x43, 0x1C, 0x60, 0x1A, 0x68, 0x10, 0x40, 0x01, 0x43, 0x19, 0x60, ++0xC7, 0xE7, 0x0F, 0x4A, 0x13, 0x68, 0x0F, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x10, 0x49, ++0x0C, 0x43, 0xA4, 0xB2, 0x1C, 0x43, 0x14, 0x60, 0x13, 0x68, 0x0A, 0x49, 0x19, 0x40, 0x80, 0x23, 0x1B, 0x03, 0x0B, 0x43, ++0x13, 0x60, 0xB2, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, 0xFC, 0x00, 0x60, 0x40, 0x6C, 0xE6, 0x10, 0x00, ++0x5C, 0xD0, 0x10, 0x00, 0xF8, 0x00, 0x60, 0x40, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xF8, 0xE6, 0x10, 0x00, ++0x50, 0xD0, 0x10, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, ++0x07, 0x00, 0xD4, 0xF7, 0x4B, 0xFD, 0x04, 0x00, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0x3B, 0x4A, 0x13, 0x70, 0x01, 0x21, ++0x01, 0x20, 0xFF, 0xF7, 0xEF, 0xFC, 0x80, 0x46, 0x38, 0x4B, 0x1E, 0x78, 0x02, 0x3E, 0x73, 0x1E, 0x9E, 0x41, 0x76, 0x42, ++0x19, 0x23, 0x1E, 0x40, 0x02, 0x36, 0x00, 0x2C, 0x21, 0xD0, 0x65, 0x68, 0xFB, 0x7D, 0x9A, 0x46, 0xA3, 0x68, 0x99, 0x46, ++0x69, 0x46, 0x01, 0xA8, 0xA9, 0xF7, 0xB0, 0xFC, 0x01, 0x9B, 0x53, 0x44, 0xEB, 0x1A, 0x1B, 0x01, 0x1A, 0x09, 0x5B, 0x00, ++0x9C, 0x1A, 0xA4, 0x00, 0xA4, 0x18, 0xA3, 0x00, 0xE4, 0x18, 0x4B, 0x46, 0x00, 0x9A, 0x9B, 0x1A, 0xE4, 0x18, 0xA4, 0x09, ++0xA6, 0x42, 0x00, 0xD8, 0xA4, 0x1B, 0x80, 0x23, 0x5B, 0x02, 0x9C, 0x42, 0x02, 0xD9, 0x24, 0x4C, 0x00, 0xE0, 0x23, 0x4C, ++0xFF, 0xF7, 0xFC, 0xFB, 0x05, 0x00, 0x43, 0x46, 0x00, 0x2B, 0x12, 0xD0, 0x20, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, ++0x1F, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x0F, 0xD0, 0x0A, 0x2C, 0x16, 0xD8, 0x4F, 0x23, 0x00, 0x22, 0xFA, 0x54, 0x02, 0xB0, ++0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0x01, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xA3, 0xFC, 0xE7, 0xE7, ++0x16, 0x4B, 0x80, 0x22, 0x12, 0x05, 0x1A, 0x60, 0x13, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0x00, 0x25, 0xE6, 0xE7, 0xFF, 0xF7, ++0x0B, 0xFC, 0x00, 0x28, 0xE4, 0xD0, 0xB2, 0xF7, 0xC9, 0xFD, 0x06, 0x23, 0x00, 0x28, 0x05, 0xD1, 0x4A, 0x33, 0xFB, 0x5C, ++0x01, 0x3B, 0x58, 0x42, 0x43, 0x41, 0x05, 0x33, 0x00, 0x2D, 0xD7, 0xD1, 0xCF, 0x2C, 0x01, 0xD8, 0x06, 0x2B, 0xD3, 0xD1, ++0x21, 0x00, 0x18, 0x00, 0xFF, 0xF7, 0xCC, 0xFE, 0xCE, 0xE7, 0xC0, 0x46, 0xB2, 0xE6, 0x10, 0x00, 0xB4, 0xE5, 0x10, 0x00, ++0xFF, 0xFF, 0x00, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x4E, 0x23, ++0x01, 0x22, 0xC2, 0x54, 0x2A, 0x4B, 0x1D, 0x68, 0x2A, 0x4B, 0x1C, 0x68, 0x2A, 0x4B, 0x19, 0x68, 0x2A, 0x4B, 0x1A, 0x68, ++0x2A, 0x4B, 0x00, 0x26, 0x1E, 0x70, 0x00, 0x23, 0x00, 0x2D, 0x05, 0xD0, 0x42, 0x33, 0xEB, 0x5C, 0x01, 0x3B, 0x5D, 0x42, ++0x6B, 0x41, 0xDB, 0xB2, 0x00, 0x2C, 0x03, 0xD0, 0x3A, 0x25, 0x64, 0x5D, 0x01, 0x2C, 0x23, 0xD0, 0x00, 0x24, 0x00, 0x29, ++0x04, 0xD0, 0x3E, 0x34, 0x0D, 0x5D, 0x00, 0x24, 0x01, 0x2D, 0x1D, 0xD0, 0x00, 0x2A, 0x03, 0xD0, 0x2F, 0x21, 0x51, 0x5C, ++0x01, 0x29, 0x1A, 0xD0, 0x00, 0x2B, 0x1D, 0xD0, 0x1A, 0x49, 0x0B, 0x68, 0x1A, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, ++0x13, 0x43, 0x0B, 0x60, 0x18, 0x4B, 0x19, 0x4A, 0x13, 0x60, 0x81, 0x22, 0x52, 0x00, 0x9B, 0x5C, 0x00, 0x2B, 0x18, 0xD0, ++0x4F, 0x23, 0x01, 0x22, 0xC2, 0x54, 0x70, 0xBD, 0x01, 0x23, 0xD9, 0xE7, 0x8C, 0x62, 0x01, 0x34, 0xDE, 0xE7, 0x00, 0x21, ++0x91, 0x62, 0x00, 0x2B, 0xE2, 0xD1, 0x01, 0xE0, 0x00, 0x2C, 0xE7, 0xD0, 0x0A, 0x49, 0x0B, 0x68, 0x0D, 0x4A, 0x1A, 0x40, ++0x80, 0x23, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0xDE, 0xE7, 0xFF, 0xF7, 0x17, 0xFF, 0xE6, 0xE7, 0x24, 0x27, 0x16, 0x00, ++0x18, 0x27, 0x16, 0x00, 0x28, 0x27, 0x16, 0x00, 0x20, 0x27, 0x16, 0x00, 0xB1, 0xE6, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, ++0xFF, 0xFF, 0xDF, 0xFF, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0xFF, 0xFF, 0x7F, 0xFF, 0x02, 0x4B, 0x1B, 0x68, ++0x04, 0x20, 0x18, 0x40, 0x70, 0x47, 0xC0, 0x46, 0x80, 0x40, 0x34, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x01, 0x00, 0x12, 0x48, ++0x82, 0xF7, 0x98, 0xF8, 0x00, 0x2C, 0x1E, 0xD0, 0x10, 0x4B, 0x1A, 0x68, 0x10, 0x48, 0x02, 0x40, 0xD0, 0x21, 0x89, 0x03, ++0x0A, 0x43, 0x1A, 0x60, 0x1C, 0x68, 0x04, 0x40, 0xA0, 0x22, 0x52, 0x03, 0x22, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x02, 0x40, ++0x11, 0x43, 0x19, 0x60, 0x09, 0x49, 0x04, 0x22, 0x0B, 0x68, 0x1A, 0x42, 0xFC, 0xD0, 0x05, 0x49, 0x0B, 0x68, 0x05, 0x4A, ++0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x10, 0xBD, 0x90, 0xD0, 0x10, 0x00, 0x58, 0x40, 0x34, 0x40, ++0xFF, 0xFF, 0xC1, 0xFF, 0x80, 0x40, 0x34, 0x40, 0xF8, 0xB5, 0x04, 0x00, 0x83, 0x7D, 0x02, 0x33, 0x83, 0x75, 0x03, 0x6C, ++0x03, 0x61, 0xB2, 0xF7, 0xF9, 0xFC, 0x00, 0x28, 0x24, 0xD1, 0x20, 0x4E, 0x4C, 0x25, 0x20, 0x4F, 0x20, 0x00, 0xD4, 0xF7, ++0x19, 0xFA, 0x00, 0x28, 0x33, 0xD0, 0x31, 0x00, 0x20, 0x69, 0xD6, 0xF7, 0xFD, 0xF9, 0x63, 0x68, 0x9C, 0x46, 0x60, 0x44, ++0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x63, 0x5B, 0x5B, 0x00, 0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, ++0xE3, 0x60, 0xA3, 0x7D, 0x14, 0x4A, 0x52, 0x78, 0x9B, 0x18, 0xA3, 0x75, 0x10, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0xBE, 0x42, ++0xDE, 0xD1, 0xF8, 0xBD, 0x63, 0x68, 0x18, 0x33, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x18, 0x26, 0x65, 0x68, 0x00, 0x22, ++0x21, 0x69, 0x20, 0x00, 0xFF, 0xF7, 0x3C, 0xFA, 0x63, 0x68, 0xAB, 0x42, 0xCB, 0xD0, 0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, ++0x65, 0x60, 0x18, 0x36, 0x90, 0x2E, 0xEF, 0xD1, 0xC3, 0xE7, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xE3, 0xE7, 0xC0, 0x46, ++0xE2, 0x04, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x10, 0xB5, 0xFF, 0xF7, 0xAB, 0xFF, 0x10, 0xBD, ++0xF8, 0xB5, 0x04, 0x00, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xF8, 0xBD, 0x00, 0x21, 0xD4, 0xF7, 0x6E, 0xFB, ++0xA9, 0xF7, 0x38, 0xFB, 0x23, 0x6C, 0x23, 0x61, 0x60, 0x60, 0x04, 0x26, 0x4C, 0x27, 0x10, 0x4D, 0x20, 0x00, 0xD4, 0xF7, ++0xBF, 0xF9, 0x00, 0x28, 0x15, 0xD0, 0x63, 0x68, 0x04, 0x33, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0xE3, 0x5B, 0x5B, 0x00, ++0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x60, 0xA3, 0x7D, 0x6A, 0x78, 0x9B, 0x18, 0xA3, 0x75, ++0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xE5, 0xD1, 0xD8, 0xE7, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xD4, 0xE7, 0xC0, 0x46, ++0x7C, 0x91, 0x0D, 0x00, 0x70, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x1C, 0xD1, ++0x72, 0xB6, 0x10, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x07, 0xD0, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x05, 0xD0, 0x01, 0x2B, ++0x0D, 0xD0, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, 0x70, 0xBD, 0x00, 0x21, 0xD4, 0xF7, 0x2A, 0xFB, 0x07, 0x4D, 0x28, 0x68, ++0x80, 0xF7, 0x38, 0xF8, 0x00, 0x23, 0x2B, 0x60, 0xF1, 0xE7, 0x4E, 0x23, 0x02, 0x22, 0xC2, 0x54, 0xED, 0xE7, 0x02, 0x4B, ++0x18, 0x68, 0x00, 0x28, 0xE3, 0xD1, 0xEB, 0xE7, 0xF8, 0xE6, 0x10, 0x00, 0xF8, 0xB5, 0x05, 0x00, 0x36, 0x4B, 0x1B, 0x68, ++0x0C, 0x20, 0x00, 0x2B, 0x00, 0xD0, 0xF8, 0xBD, 0x00, 0x21, 0x48, 0x30, 0x7F, 0xF7, 0x7A, 0xFF, 0x31, 0x4B, 0x18, 0x60, ++0x00, 0x28, 0x56, 0xD0, 0xA9, 0xF7, 0xD2, 0xFA, 0x06, 0x00, 0x00, 0x27, 0x2E, 0x4B, 0x1F, 0x60, 0x2E, 0x4B, 0x1F, 0x60, ++0x2B, 0x4B, 0x1C, 0x68, 0x54, 0x22, 0x00, 0x21, 0x20, 0x00, 0x7D, 0xF7, 0x19, 0xFF, 0x2B, 0x68, 0xA3, 0x62, 0x6A, 0x68, ++0x22, 0x63, 0xEA, 0x68, 0xE2, 0x63, 0x2A, 0x68, 0xE2, 0x62, 0xAA, 0x68, 0xA2, 0x63, 0x62, 0x63, 0x1B, 0x01, 0x4C, 0x22, ++0xA3, 0x52, 0x24, 0x4A, 0x22, 0x64, 0x24, 0x4B, 0x63, 0x62, 0x24, 0x4B, 0xE3, 0x61, 0x24, 0x4B, 0x23, 0x62, 0x03, 0x23, ++0x23, 0x76, 0x23, 0x4B, 0x9B, 0x78, 0x02, 0x33, 0xA3, 0x75, 0x22, 0x61, 0xE7, 0x75, 0x05, 0x23, 0x63, 0x76, 0xEF, 0xF3, ++0x10, 0x83, 0x01, 0x22, 0x15, 0x00, 0x1D, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x66, 0x60, 0x00, 0x23, 0xA3, 0x60, ++0x1A, 0x4B, 0xA3, 0x82, 0x4C, 0x23, 0xE0, 0x5A, 0x40, 0x00, 0x80, 0x19, 0x00, 0x01, 0x00, 0x09, 0xE0, 0x60, 0x20, 0x00, ++0xD4, 0xF7, 0x1E, 0xF9, 0x00, 0x28, 0x06, 0xD1, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x00, 0x2D, 0xA9, 0xD1, 0x62, 0xB6, ++0xA7, 0xE7, 0x11, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0C, 0x20, 0xF3, 0xE7, 0x0D, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0C, 0x20, 0x97, 0xE7, 0xC0, 0x46, 0xF8, 0xE6, 0x10, 0x00, ++0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0xE8, 0xFD, 0x00, 0x00, 0xB9, 0x21, 0x10, 0x00, 0xC9, 0x1F, 0x10, 0x00, ++0x05, 0x4B, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x00, 0xA0, 0xFF, 0xFF, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x06, 0x4B, ++0x18, 0x68, 0x00, 0x28, 0x03, 0xD0, 0x4F, 0x23, 0xC3, 0x5C, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0xFF, 0xF7, 0x84, 0xFD, ++0xFB, 0xE7, 0xC0, 0x46, 0xF8, 0xE6, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x85, 0xF7, 0x55, 0xFE, 0x4C, 0x4B, ++0x1B, 0x68, 0x01, 0x2B, 0x02, 0xD0, 0x4A, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x49, 0x4A, 0x48, 0x4B, 0x19, 0x68, 0x49, 0x4B, ++0xD1, 0x54, 0x00, 0x21, 0x42, 0x3B, 0xD1, 0x54, 0x0B, 0x23, 0x47, 0x48, 0x13, 0x54, 0x01, 0x30, 0x13, 0x54, 0x46, 0x4B, ++0x1B, 0x68, 0x1C, 0x0A, 0x50, 0x38, 0x14, 0x54, 0x44, 0x48, 0x13, 0x54, 0x44, 0x4B, 0x20, 0x20, 0xD0, 0x54, 0x44, 0x4B, ++0x10, 0x38, 0xD0, 0x54, 0x43, 0x4B, 0x19, 0x60, 0x00, 0x24, 0x00, 0x23, 0x98, 0x46, 0x00, 0x27, 0x01, 0x34, 0xE4, 0xB2, ++0x01, 0x2C, 0x0B, 0xD0, 0x02, 0x2C, 0x3E, 0xD0, 0x03, 0x2C, 0x4C, 0xD0, 0x3D, 0x4A, 0x13, 0x78, 0x20, 0x21, 0x8B, 0x43, ++0x13, 0x70, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0C, 0x20, 0xFE, 0xF7, 0xA7, 0xF9, 0x06, 0x00, 0x0D, 0x20, 0xFE, 0xF7, ++0xA3, 0xF9, 0x05, 0x04, 0x2D, 0x0C, 0x2A, 0x00, 0x31, 0x00, 0x35, 0x48, 0x81, 0xF7, 0xDA, 0xFE, 0x2B, 0x00, 0x33, 0x43, ++0xDE, 0xD0, 0x43, 0x46, 0x00, 0x2B, 0x41, 0xD0, 0x27, 0x4B, 0x2A, 0x0A, 0x1A, 0x70, 0x5D, 0x70, 0x32, 0x0E, 0x9A, 0x70, ++0x32, 0x0C, 0xDA, 0x70, 0x32, 0x0A, 0x1A, 0x71, 0x5E, 0x71, 0x00, 0x2F, 0x0A, 0xD0, 0x21, 0x4A, 0x11, 0x1D, 0x13, 0x78, ++0x01, 0x33, 0xDB, 0xB2, 0x13, 0x70, 0x00, 0x2B, 0x02, 0xD1, 0x01, 0x32, 0x8A, 0x42, 0xF6, 0xD1, 0x1B, 0x4C, 0x20, 0x68, ++0x61, 0x68, 0xA9, 0xF7, 0xD1, 0xFC, 0x20, 0x00, 0xB9, 0xF7, 0x0E, 0xFB, 0xC2, 0xE7, 0x07, 0x20, 0xFE, 0xF7, 0x72, 0xF9, ++0x06, 0x00, 0x08, 0x20, 0xFE, 0xF7, 0x6E, 0xF9, 0x05, 0x04, 0x2D, 0x0C, 0x2A, 0x00, 0x31, 0x00, 0x1B, 0x48, 0x81, 0xF7, ++0xA5, 0xFE, 0x01, 0x27, 0xC8, 0xE7, 0x1A, 0x4B, 0x1E, 0x88, 0x58, 0x88, 0x00, 0x04, 0x06, 0x43, 0x18, 0x4B, 0x1D, 0x88, ++0x5B, 0x88, 0x2A, 0x00, 0x31, 0x00, 0x17, 0x48, 0x81, 0xF7, 0x96, 0xFE, 0x01, 0x23, 0x98, 0x46, 0x00, 0x27, 0xB7, 0xE7, ++0x06, 0x4B, 0x2A, 0x0A, 0x5A, 0x71, 0x1D, 0x71, 0x32, 0x0E, 0xDA, 0x70, 0x32, 0x0C, 0x9A, 0x70, 0x32, 0x0A, 0x5A, 0x70, ++0x1E, 0x70, 0xBC, 0xE7, 0xA8, 0xE5, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x9A, 0x02, 0x00, 0x00, 0xA3, 0x02, 0x00, 0x00, ++0xB0, 0xE5, 0x10, 0x00, 0x55, 0x02, 0x00, 0x00, 0x56, 0x02, 0x00, 0x00, 0x57, 0x02, 0x00, 0x00, 0xF8, 0xE6, 0x10, 0x00, ++0xEC, 0xE1, 0x10, 0x00, 0xA0, 0xD0, 0x10, 0x00, 0xB0, 0xD0, 0x10, 0x00, 0x12, 0xC0, 0x1F, 0x08, 0x16, 0xC0, 0x1F, 0x08, ++0xC4, 0xD0, 0x10, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x05, 0x00, 0x14, 0x00, 0x00, 0x28, 0x14, 0xD1, 0x1F, 0x4B, 0x20, 0x48, ++0x1A, 0x5C, 0x04, 0x35, 0xAA, 0x43, 0x1A, 0x54, 0x02, 0x30, 0x1A, 0x5C, 0x3E, 0x35, 0xAA, 0x43, 0x1A, 0x54, 0x22, 0x00, ++0x00, 0x20, 0x8D, 0xF7, 0xF9, 0xFF, 0x1A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x0E, 0xD0, 0x09, 0xB0, 0x30, 0xBD, 0x8D, 0xF7, ++0xF1, 0xFF, 0x02, 0x2D, 0xF5, 0xD1, 0x23, 0x78, 0x0C, 0x22, 0x93, 0x43, 0x23, 0x70, 0x63, 0x78, 0x0B, 0x3A, 0x93, 0x43, ++0x63, 0x70, 0xEC, 0xE7, 0x11, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0xEC, 0xD8, 0x00, 0x23, 0x07, 0x93, 0x0F, 0x4B, 0x1B, 0x68, ++0x03, 0x93, 0x0F, 0x4B, 0x1B, 0x68, 0x01, 0x93, 0x04, 0x93, 0x0E, 0x4B, 0x18, 0x68, 0x0E, 0x49, 0xD5, 0xF7, 0xD4, 0xFF, ++0x05, 0x90, 0x0D, 0x4B, 0x18, 0x68, 0x0B, 0x49, 0xD5, 0xF7, 0xCE, 0xFF, 0x06, 0x90, 0x03, 0xA8, 0xFF, 0xF7, 0x6C, 0xFE, ++0xD3, 0xE7, 0xC0, 0x46, 0x7C, 0x1E, 0x16, 0x00, 0x9E, 0x02, 0x00, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, ++0x0C, 0xE2, 0x10, 0x00, 0x10, 0xE2, 0x10, 0x00, 0x04, 0xE2, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x08, 0xE2, 0x10, 0x00, ++0x80, 0x00, 0x08, 0x4B, 0xC3, 0x58, 0x88, 0x22, 0xFF, 0x32, 0x9A, 0x5C, 0x00, 0x20, 0x01, 0x2A, 0x00, 0xD0, 0x70, 0x47, ++0x8A, 0x22, 0xFF, 0x32, 0x98, 0x5C, 0x01, 0x38, 0x43, 0x42, 0x58, 0x41, 0xF7, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x00, 0x23, 0x00, 0x20, 0x06, 0x49, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, 0x06, 0xD0, 0x9A, 0x00, 0x52, 0x58, 0x00, 0x2A, ++0xF8, 0xD0, 0x01, 0x30, 0xC0, 0xB2, 0xF5, 0xE7, 0x70, 0x47, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x70, 0xB5, 0x82, 0xB0, ++0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x30, 0x4B, 0xD6, 0x58, 0x20, 0x00, 0x80, 0xF7, 0xB2, 0xF8, 0x03, 0x00, 0x02, 0x00, ++0x01, 0x28, 0x12, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x05, 0xD9, 0x19, 0x2B, 0x05, 0xD8, 0x15, 0x23, 0x93, 0x42, 0x40, 0x41, ++0x40, 0x00, 0x02, 0xB0, 0x70, 0xBD, 0x58, 0x3B, 0xDB, 0xB2, 0x01, 0x20, 0x98, 0x42, 0x80, 0x41, 0x40, 0x42, 0x40, 0x00, ++0xF5, 0xE7, 0x4C, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x3A, 0xD1, 0x4B, 0x33, 0xF3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x4B, 0x23, ++0x00, 0x22, 0xF2, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x16, 0xD1, 0x36, 0x33, 0xF2, 0x5C, 0x35, 0x3B, 0x13, 0x40, ++0x3E, 0x22, 0x13, 0x43, 0x6A, 0x46, 0x13, 0x71, 0x00, 0x23, 0x53, 0x71, 0xE8, 0xB2, 0x01, 0xA9, 0xA7, 0xF7, 0x98, 0xF9, ++0x14, 0x48, 0x81, 0xF7, 0xA9, 0xFD, 0x59, 0x21, 0x20, 0x00, 0x80, 0xF7, 0x17, 0xF8, 0x00, 0x20, 0xCF, 0xE7, 0x01, 0xA9, ++0x36, 0x23, 0xF2, 0x5C, 0x38, 0x3B, 0x13, 0x43, 0x0B, 0x70, 0x1F, 0x23, 0x4B, 0x70, 0x1E, 0x3B, 0x8B, 0x70, 0xE8, 0xB2, ++0xA7, 0xF7, 0x82, 0xF9, 0x0A, 0x48, 0x81, 0xF7, 0x93, 0xFD, 0x20, 0x00, 0x97, 0xF7, 0x72, 0xFD, 0x58, 0x21, 0x20, 0x00, ++0x7F, 0xF7, 0xFE, 0xFF, 0x00, 0x20, 0xB6, 0xE7, 0x05, 0x48, 0x81, 0xF7, 0x87, 0xFD, 0x00, 0x20, 0xB1, 0xE7, 0xC0, 0x46, ++0x64, 0xA2, 0x16, 0x00, 0xDC, 0xD0, 0x10, 0x00, 0xEC, 0xD0, 0x10, 0x00, 0xFC, 0xD0, 0x10, 0x00, 0xF0, 0xB5, 0x05, 0xAC, ++0x24, 0x78, 0x4E, 0x28, 0x3C, 0xD8, 0xFF, 0x2C, 0x08, 0xD0, 0x10, 0x2C, 0x0B, 0xD9, 0x18, 0x2C, 0x37, 0xD9, 0x20, 0x2C, ++0x38, 0xD9, 0x03, 0x26, 0x00, 0x25, 0x06, 0xE0, 0x32, 0x4C, 0x24, 0x18, 0xED, 0x34, 0x24, 0x78, 0xF1, 0xE7, 0x00, 0x26, ++0x03, 0x25, 0x00, 0x29, 0x36, 0xD0, 0x2E, 0x4F, 0x39, 0x18, 0x0E, 0x00, 0x4F, 0x36, 0x33, 0x70, 0x3E, 0x56, 0xF3, 0x18, ++0x5B, 0x10, 0x3B, 0x54, 0x0B, 0x00, 0xED, 0x33, 0x1C, 0x70, 0x0E, 0x00, 0x9E, 0x36, 0x33, 0x78, 0x1C, 0x19, 0x64, 0x10, ++0x34, 0x70, 0x8C, 0x31, 0xFF, 0x31, 0x00, 0x23, 0x0B, 0x70, 0x24, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x1B, 0x78, ++0xED, 0x18, 0x6D, 0xB2, 0x06, 0x2D, 0x10, 0xDC, 0x1F, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x1D, 0x70, 0x02, 0x30, ++0x80, 0x00, 0x1C, 0x4B, 0x18, 0x18, 0x42, 0x60, 0xF0, 0xBD, 0x01, 0x26, 0x02, 0x25, 0xD0, 0xE7, 0x02, 0x26, 0x01, 0x25, ++0xCD, 0xE7, 0x17, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x06, 0x21, 0x19, 0x70, 0xEC, 0xE7, 0x12, 0x4B, 0x1B, 0x18, ++0x8C, 0x33, 0xFF, 0x33, 0x1B, 0x78, 0x01, 0x2B, 0x14, 0xD0, 0x0F, 0x49, 0x09, 0x18, 0x8C, 0x31, 0xFF, 0x31, 0x01, 0x23, ++0x0B, 0x70, 0x0D, 0x49, 0x09, 0x18, 0x49, 0x31, 0xFF, 0x31, 0x0B, 0x78, 0x9B, 0x1B, 0x5B, 0xB2, 0x99, 0x1D, 0x08, 0xDB, ++0x08, 0x49, 0x09, 0x18, 0x49, 0x31, 0xFF, 0x31, 0x0B, 0x70, 0xD0, 0xE7, 0x02, 0x36, 0xF6, 0xB2, 0xE7, 0xE7, 0x04, 0x4B, ++0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0xFA, 0x21, 0x19, 0x70, 0xC6, 0xE7, 0x1C, 0xE7, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, ++0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0x4C, 0x00, 0x25, 0x00, 0x22, 0x01, 0x26, ++0xC1, 0x27, 0xFF, 0x00, 0x03, 0xE0, 0x01, 0x35, 0x09, 0x34, 0x07, 0x2D, 0x0E, 0xD0, 0x23, 0x78, 0x03, 0x2B, 0xF8, 0xD1, ++0x63, 0x78, 0x00, 0x2B, 0xF5, 0xD1, 0x29, 0x02, 0x31, 0x43, 0x89, 0xB2, 0x00, 0x22, 0x38, 0x00, 0x7F, 0xF7, 0x20, 0xFC, ++0x01, 0x22, 0xEC, 0xE7, 0x00, 0x2A, 0x0B, 0xD1, 0x7E, 0x4A, 0xD9, 0x23, 0x5B, 0x00, 0x00, 0x21, 0xD1, 0x54, 0x00, 0x20, ++0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, 0xA8, 0xF7, 0xFE, 0xFF, 0x82, 0x46, 0x8E, 0xF7, ++0x09, 0xF8, 0x80, 0x46, 0xA9, 0xF7, 0x18, 0xFB, 0x81, 0x46, 0x00, 0x24, 0x73, 0x4B, 0x9B, 0x46, 0x63, 0xE0, 0x8D, 0xF7, ++0xF3, 0xFF, 0x00, 0x28, 0x19, 0xD0, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, ++0xC8, 0x22, 0x92, 0x01, 0x93, 0x42, 0x3D, 0xD2, 0x4B, 0x46, 0x3D, 0x33, 0xFF, 0x33, 0x1B, 0x57, 0x01, 0x33, 0x2D, 0xDB, ++0xD4, 0x20, 0x40, 0x00, 0x66, 0x4B, 0x5B, 0x19, 0x01, 0x21, 0xB1, 0x40, 0x1A, 0x5C, 0x0A, 0x43, 0x1A, 0x54, 0x2A, 0x00, ++0x63, 0x32, 0xFF, 0x32, 0x5A, 0x44, 0x00, 0x21, 0x06, 0x20, 0x38, 0x40, 0x03, 0x27, 0x13, 0x78, 0x03, 0x41, 0x3B, 0x40, ++0x03, 0x2B, 0x27, 0xD0, 0x01, 0x31, 0x0A, 0x32, 0x07, 0x29, 0xF6, 0xD1, 0xB3, 0x1E, 0x01, 0x2B, 0x00, 0xD8, 0x98, 0xE0, ++0x73, 0x1F, 0x01, 0x2B, 0x00, 0xD8, 0x94, 0xE0, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0xFA, 0x22, 0x12, 0x02, 0x93, 0x42, 0x1E, 0xD9, 0x93, 0xE0, 0xD4, 0x21, 0x49, 0x00, 0x4F, 0x4B, 0x5D, 0x19, ++0x01, 0x22, 0xB2, 0x40, 0x6B, 0x5C, 0x93, 0x43, 0x6B, 0x54, 0x13, 0xE0, 0x4B, 0x46, 0x3D, 0x33, 0xFF, 0x33, 0x00, 0x22, ++0x1A, 0x55, 0xCA, 0xE7, 0xD4, 0x20, 0x40, 0x00, 0x47, 0x4B, 0x9C, 0x46, 0xAC, 0x44, 0x01, 0x22, 0xB2, 0x40, 0x63, 0x46, ++0x1B, 0x5C, 0x93, 0x43, 0x62, 0x46, 0x13, 0x54, 0x07, 0x29, 0xCD, 0xD0, 0x01, 0x34, 0x4F, 0x2C, 0x13, 0xD0, 0xE7, 0xB2, ++0x07, 0x26, 0x26, 0x40, 0x65, 0x05, 0x2D, 0x0E, 0x43, 0x46, 0x5B, 0x5D, 0x33, 0x41, 0xDB, 0x07, 0x91, 0xD4, 0xD4, 0x21, ++0x49, 0x00, 0x3A, 0x4B, 0x5D, 0x19, 0x01, 0x22, 0xB2, 0x40, 0x6B, 0x5C, 0x93, 0x43, 0x6B, 0x54, 0xE8, 0xE7, 0x37, 0x48, ++0x81, 0xF7, 0xB0, 0xFC, 0x13, 0x28, 0x41, 0xD8, 0x14, 0x23, 0x1B, 0x1A, 0xDB, 0xB2, 0x9B, 0x46, 0x14, 0x25, 0x2D, 0x1A, ++0x00, 0x23, 0x99, 0x46, 0x00, 0x24, 0x2F, 0x4E, 0x0E, 0xE0, 0x48, 0x46, 0x13, 0x28, 0x09, 0xD9, 0x2C, 0x48, 0x84, 0x46, ++0x62, 0x44, 0x01, 0x20, 0x98, 0x40, 0x01, 0x43, 0xD4, 0x23, 0x5B, 0x00, 0xD1, 0x54, 0x01, 0x34, 0xAC, 0x42, 0x27, 0xDA, ++0xD6, 0xF7, 0xDA, 0xFA, 0x7F, 0x23, 0x18, 0x40, 0x4E, 0x28, 0x00, 0xD9, 0x4F, 0x38, 0xC2, 0x08, 0xB1, 0x18, 0xD4, 0x23, ++0x5B, 0x00, 0xC9, 0x5C, 0xA2, 0x3B, 0xFF, 0x3B, 0x03, 0x40, 0x0F, 0x00, 0x1F, 0x41, 0xFF, 0x07, 0xEA, 0xD4, 0x47, 0x46, ++0xBF, 0x5C, 0x1F, 0x41, 0xFF, 0x07, 0xE5, 0xD5, 0x4F, 0x46, 0x01, 0x37, 0xFF, 0xB2, 0xB9, 0x46, 0x1A, 0x4F, 0xBC, 0x46, ++0x60, 0x44, 0x9E, 0x30, 0x00, 0x78, 0x18, 0x28, 0xD0, 0xD9, 0xCB, 0x45, 0xCB, 0xD8, 0x20, 0x28, 0xCC, 0xD9, 0xC8, 0xE7, ++0x13, 0x48, 0x81, 0xF7, 0x69, 0xFC, 0x01, 0x00, 0x13, 0x48, 0x81, 0xF7, 0x01, 0xFC, 0xC8, 0x22, 0x00, 0x21, 0x12, 0x48, ++0x7F, 0xF7, 0x38, 0xFA, 0x1F, 0xE7, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, ++0xFA, 0x22, 0xD2, 0x01, 0x93, 0x42, 0x89, 0xD9, 0xD4, 0x21, 0x49, 0x00, 0x05, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x01, 0x22, ++0xB2, 0x40, 0x6B, 0x5C, 0x13, 0x43, 0x6B, 0x54, 0x7E, 0xE7, 0xC0, 0x46, 0xA4, 0x9E, 0x16, 0x00, 0x68, 0x9E, 0x16, 0x00, ++0x10, 0xA0, 0x16, 0x00, 0x1C, 0xE7, 0x10, 0x00, 0x0C, 0xD1, 0x10, 0x00, 0x0A, 0x05, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x07, 0x00, 0x08, 0x00, 0x00, 0x91, 0xBA, 0x00, 0xA4, 0x4B, ++0xD5, 0x58, 0xA6, 0x23, 0xEB, 0x5C, 0x9B, 0x46, 0x2B, 0x6D, 0x98, 0x46, 0x62, 0x23, 0x7B, 0x43, 0xA0, 0x4A, 0x9A, 0x18, ++0x16, 0x88, 0xA0, 0x4A, 0x9A, 0x18, 0x14, 0x88, 0x36, 0x04, 0x26, 0x43, 0x9E, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x92, 0x05, ++0x92, 0x0D, 0x91, 0x46, 0x9C, 0x4A, 0x9A, 0x18, 0x14, 0x88, 0x9C, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x24, 0x04, ++0x1C, 0x19, 0x9A, 0x4B, 0x98, 0x45, 0x1A, 0xD8, 0x73, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x80, 0x22, 0x12, 0x05, 0x91, 0x42, ++0x4A, 0xD9, 0x83, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0x49, 0xD0, 0x00, 0x2B, ++0x09, 0xDB, 0x89, 0x08, 0x00, 0x29, 0x06, 0xDD, 0x89, 0x00, 0x00, 0x9B, 0x9C, 0x46, 0x61, 0x44, 0x09, 0x01, 0x0B, 0x09, ++0x00, 0x93, 0xA4, 0x1B, 0x00, 0x9B, 0x9C, 0x46, 0x64, 0x44, 0x24, 0x01, 0x24, 0x09, 0xF4, 0x26, 0x76, 0x00, 0x4B, 0x46, ++0xF6, 0x1A, 0x3B, 0xD4, 0xAC, 0x67, 0x82, 0x23, 0xEE, 0x52, 0x62, 0x42, 0x7F, 0x3B, 0x13, 0x40, 0xA6, 0x22, 0xAB, 0x54, ++0x72, 0x3A, 0x2A, 0x65, 0x01, 0x96, 0xAE, 0x60, 0x42, 0x46, 0x34, 0x2A, 0x09, 0xD9, 0xEA, 0x7D, 0x00, 0x2A, 0x06, 0xD0, ++0xC8, 0x22, 0x52, 0x00, 0xB2, 0x42, 0x92, 0x41, 0x52, 0x42, 0x05, 0x32, 0xEA, 0x75, 0x5B, 0x45, 0x00, 0xD1, 0x9F, 0xE0, ++0xA1, 0x23, 0xEB, 0x5C, 0x03, 0x2B, 0x21, 0xD0, 0x3B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x02, 0x93, 0x01, 0x23, 0x98, 0x46, ++0xFE, 0x33, 0x9A, 0x46, 0xA9, 0x46, 0x45, 0x46, 0xA0, 0x46, 0x4D, 0xE0, 0x1B, 0x01, 0x1B, 0x09, 0xA1, 0x22, 0xAA, 0x5C, ++0x00, 0x2A, 0xB8, 0xD0, 0xB5, 0xE7, 0x00, 0x2B, 0xB5, 0xDA, 0x6C, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0xB8, 0xE7, 0x69, 0x4E, 0xF6, 0x1A, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0xBD, 0xE7, 0xC1, 0x33, 0x99, 0x46, ++0xEB, 0x58, 0x6A, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x4A, 0x46, 0xAB, 0x50, 0x3B, 0x02, ++0x01, 0x21, 0x19, 0x43, 0x02, 0x23, 0x3B, 0x32, 0x5F, 0x48, 0x7F, 0xF7, 0x2B, 0xFA, 0x80, 0x46, 0x4B, 0x46, 0xEB, 0x58, ++0x5B, 0x08, 0x99, 0x46, 0xCC, 0x23, 0xEB, 0x5A, 0x9A, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x57, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x51, 0x46, 0x48, 0x46, 0xD5, 0xF7, 0x47, 0xFD, 0x43, 0x46, 0x19, 0x80, 0x40, 0x46, ++0x7F, 0xF7, 0x3C, 0xFA, 0xB0, 0xE7, 0x21, 0x00, 0x03, 0x98, 0xD5, 0xF7, 0x3D, 0xFD, 0x04, 0x9B, 0x59, 0x80, 0x18, 0x00, ++0x7F, 0xF7, 0x32, 0xFA, 0x01, 0x3D, 0x3F, 0xD3, 0x53, 0x46, 0x2B, 0x40, 0x9B, 0x00, 0x4B, 0x4A, 0x9C, 0x58, 0x00, 0x2C, ++0xF6, 0xD0, 0x46, 0x23, 0xE3, 0x5C, 0xBB, 0x42, 0xF2, 0xD1, 0x63, 0x6B, 0x42, 0x46, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, ++0x63, 0x63, 0x4A, 0x46, 0x52, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x63, 0x63, 0x68, 0x42, 0x46, ++0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x4A, 0x46, 0x52, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, ++0x63, 0x60, 0x01, 0x9B, 0xA3, 0x60, 0x04, 0x23, 0x52, 0x46, 0x02, 0x99, 0x38, 0x48, 0x7F, 0xF7, 0xD9, 0xF9, 0x04, 0x90, ++0x47, 0x23, 0xE3, 0x5C, 0x03, 0x70, 0x63, 0x6B, 0x5B, 0x08, 0x03, 0x93, 0x42, 0x23, 0xE4, 0x5C, 0x00, 0x2C, 0xBC, 0xD1, ++0x2D, 0x4B, 0x9B, 0x6E, 0x05, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xB4, 0xE7, 0x44, 0x46, 0x4D, 0x46, ++0x6C, 0x67, 0x84, 0x23, 0xEE, 0x52, 0x1D, 0x33, 0xEB, 0x5C, 0x04, 0x2B, 0x0D, 0xD0, 0xA6, 0x23, 0xE8, 0x5C, 0x5B, 0x46, ++0xC0, 0x1A, 0x43, 0x1E, 0x98, 0x41, 0xC0, 0xB2, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, ++0xF0, 0xBD, 0x7C, 0x33, 0xEB, 0x5A, 0x9E, 0x1B, 0xF3, 0x17, 0xF6, 0x18, 0x5E, 0x40, 0x33, 0xB2, 0x9D, 0x22, 0x52, 0x00, ++0x93, 0x42, 0x02, 0xDB, 0x1D, 0x4B, 0x9B, 0x1B, 0x1B, 0xB2, 0x03, 0x2B, 0xE1, 0xDD, 0xE8, 0x23, 0xEB, 0x58, 0x1A, 0x68, ++0x00, 0x9B, 0xA8, 0x6F, 0x84, 0x46, 0x63, 0x44, 0x19, 0x00, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x20, 0x00, 0x05, ++0x83, 0x42, 0xD2, 0xD8, 0x09, 0x01, 0x09, 0x09, 0x51, 0x1A, 0x09, 0x01, 0x09, 0x09, 0x64, 0x29, 0xCB, 0xDD, 0x3F, 0x02, ++0x01, 0x21, 0x39, 0x43, 0xFF, 0x22, 0x0F, 0x48, 0x7F, 0xF7, 0xC2, 0xF9, 0xC3, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, ++0x4C, 0x65, 0x61, 0x40, 0x4A, 0x65, 0x61, 0x40, 0x4E, 0x65, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, ++0xE1, 0x04, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0x59, 0x04, 0x00, 0x00, 0x33, 0x06, 0x00, 0x00, 0x54, 0x27, 0x16, 0x00, ++0x34, 0x06, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x2E, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x89, 0xB0, 0x03, 0x90, 0x89, 0x46, 0x81, 0x00, 0xC9, 0x4B, 0xCF, 0x58, 0x53, 0x1E, 0xDB, 0xB2, ++0x9B, 0x46, 0x00, 0x2A, 0x00, 0xD1, 0x26, 0xE1, 0x03, 0x02, 0x01, 0x22, 0x13, 0x43, 0x07, 0x93, 0xC4, 0x4B, 0x98, 0x46, ++0x9A, 0x46, 0x5C, 0x46, 0x83, 0xE0, 0x6B, 0x46, 0x10, 0x21, 0x5B, 0x5E, 0x00, 0x2B, 0x06, 0xDB, 0xA7, 0x21, 0x79, 0x5C, ++0x77, 0x29, 0x02, 0xD8, 0x01, 0x31, 0xA7, 0x20, 0x39, 0x54, 0xE9, 0x06, 0x00, 0xD5, 0xD7, 0xE0, 0xA4, 0x21, 0x29, 0x42, ++0x5B, 0xD1, 0x29, 0x07, 0x54, 0xD4, 0x00, 0x2B, 0x00, 0xDA, 0xCF, 0xE0, 0xA7, 0x23, 0xFB, 0x5C, 0x77, 0x2B, 0x02, 0xD8, ++0xA7, 0x23, 0x02, 0x21, 0xF9, 0x54, 0x0F, 0x23, 0x1A, 0x40, 0x03, 0x25, 0x05, 0x9B, 0x1D, 0x40, 0x03, 0x2A, 0x01, 0xD0, ++0x08, 0x2A, 0x02, 0xD1, 0x03, 0x2D, 0x00, 0xD1, 0xCE, 0xE0, 0xEC, 0x23, 0xFB, 0x58, 0x00, 0x2B, 0x00, 0xD0, 0xB7, 0xE0, ++0x6B, 0x1E, 0x01, 0x2B, 0x00, 0xD9, 0xB3, 0xE0, 0x05, 0x9B, 0xDE, 0x04, 0xB6, 0x0D, 0x00, 0xD1, 0xAE, 0xE0, 0x04, 0x23, ++0xFF, 0x22, 0x07, 0x99, 0xA5, 0x48, 0x7F, 0xF7, 0x0B, 0xF9, 0xA5, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, ++0x9B, 0x1A, 0x5B, 0x00, 0xA2, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x03, 0x80, 0x43, 0x88, 0x9B, 0x0A, 0x9B, 0x02, ++0x33, 0x43, 0x9F, 0x4E, 0x33, 0x40, 0x2D, 0x03, 0x1D, 0x43, 0xAA, 0x04, 0x92, 0x0C, 0x06, 0x9B, 0x59, 0x42, 0x4B, 0x41, ++0x9B, 0x03, 0x13, 0x43, 0x43, 0x80, 0x7F, 0xF7, 0x17, 0xF9, 0x96, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, ++0x9B, 0x1A, 0x5B, 0x00, 0x93, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x00, 0x22, 0x1A, 0x80, 0x7D, 0xE0, 0xFF, 0x22, 0x07, 0x99, ++0x91, 0x48, 0x7F, 0xF7, 0x1B, 0xF9, 0xA8, 0xF7, 0x3F, 0xFA, 0x90, 0x4B, 0x1D, 0x68, 0x58, 0x46, 0x43, 0x46, 0xDB, 0x69, ++0x98, 0x47, 0x03, 0x00, 0x2D, 0x0A, 0xED, 0xB2, 0x00, 0x95, 0x4A, 0x46, 0x00, 0x21, 0x02, 0x98, 0xFF, 0xF7, 0x52, 0xFC, ++0x01, 0x3C, 0xE4, 0xB2, 0xFF, 0x2C, 0x00, 0xD1, 0x99, 0xE0, 0x03, 0x98, 0xA8, 0xF7, 0x54, 0xFA, 0x00, 0x28, 0x00, 0xD1, ++0x93, 0xE0, 0xD5, 0x23, 0x5B, 0x00, 0x7E, 0x4A, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x80, 0x4A, 0x9A, 0x18, ++0x15, 0x88, 0xAD, 0xB2, 0x7F, 0x4A, 0x9A, 0x18, 0x16, 0x88, 0xB6, 0xB2, 0x7E, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x92, 0xB2, ++0x05, 0x92, 0x7D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9A, 0xB2, 0x04, 0x92, 0xDA, 0xB2, 0x93, 0x46, 0x5B, 0x04, ++0x5B, 0x0E, 0x02, 0x93, 0x4B, 0x46, 0xFA, 0x6E, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xC8, 0x2B, 0x0A, 0xD9, 0xA7, 0x23, ++0xFB, 0x5C, 0x77, 0x2B, 0x06, 0xD8, 0xA1, 0x22, 0xBA, 0x5C, 0x00, 0x2A, 0x02, 0xD1, 0x01, 0x33, 0xA7, 0x32, 0xBB, 0x54, ++0xEB, 0x07, 0xB0, 0xD4, 0x07, 0x23, 0x1A, 0x00, 0x32, 0x40, 0x06, 0x92, 0x4A, 0x46, 0xFA, 0x66, 0x33, 0x42, 0x0B, 0xD0, ++0x5F, 0x4B, 0xDB, 0x69, 0x58, 0x46, 0x98, 0x47, 0x98, 0x22, 0xBB, 0x5A, 0x1B, 0x18, 0xBB, 0x52, 0x02, 0x32, 0xBB, 0x5C, ++0x01, 0x33, 0xBB, 0x54, 0xAB, 0x07, 0x9A, 0xD4, 0x4B, 0x46, 0x3B, 0x67, 0x6B, 0x06, 0x02, 0xD5, 0x06, 0x9B, 0x00, 0x2B, ++0x0C, 0xD1, 0xF6, 0x10, 0xF2, 0xB2, 0x0E, 0x23, 0x1E, 0x42, 0x00, 0xD0, 0x1F, 0xE7, 0x99, 0x33, 0xFB, 0x5C, 0x00, 0x2B, ++0x02, 0xD0, 0x01, 0x3B, 0xA7, 0x22, 0xBB, 0x54, 0xA8, 0xF7, 0xC6, 0xF9, 0x53, 0x4B, 0x1D, 0x68, 0x58, 0x46, 0x53, 0x46, ++0xDB, 0x69, 0x98, 0x47, 0x03, 0x00, 0x2D, 0x0A, 0xED, 0xB2, 0x00, 0x95, 0x4A, 0x46, 0x01, 0x21, 0x02, 0x98, 0xFF, 0xF7, ++0xD9, 0xFB, 0x85, 0xE7, 0x47, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x4D, 0x4A, ++0x94, 0x46, 0x63, 0x44, 0x19, 0x88, 0x8B, 0xB2, 0x04, 0x93, 0x05, 0x9A, 0xD5, 0x04, 0xAD, 0x0D, 0x6B, 0x1C, 0xFF, 0x22, ++0x07, 0x99, 0x48, 0x48, 0x7F, 0xF7, 0x3A, 0xF8, 0x06, 0x00, 0x05, 0x70, 0x04, 0x9B, 0x46, 0x4A, 0x94, 0x46, 0x63, 0x44, ++0x19, 0x00, 0x01, 0x30, 0x2A, 0x00, 0xD5, 0xF7, 0x27, 0xFF, 0x30, 0x00, 0x7F, 0xF7, 0x56, 0xF8, 0xC8, 0xE7, 0x62, 0x24, ++0x03, 0x9B, 0x5C, 0x43, 0x3F, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x80, 0x22, 0x93, 0x43, 0x23, 0x80, 0x89, 0xF7, ++0x59, 0xF9, 0x00, 0x28, 0x18, 0xD0, 0x2F, 0x4B, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x13, 0xD1, 0x38, 0x4B, 0x1B, 0x88, ++0x9B, 0xB2, 0x00, 0x2B, 0x0E, 0xD1, 0x37, 0x4B, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x09, 0xD1, 0x35, 0x4B, 0x1B, 0x88, ++0x9B, 0xB2, 0x00, 0x2B, 0x04, 0xD1, 0x23, 0x88, 0x80, 0x22, 0x93, 0x43, 0x13, 0x43, 0x23, 0x80, 0x9A, 0x23, 0xFB, 0x5C, ++0x96, 0x2B, 0x03, 0xD9, 0xEC, 0x23, 0xFB, 0x58, 0x00, 0x2B, 0x06, 0xD0, 0x09, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xAC, 0x33, 0xFB, 0x5C, 0x00, 0x2B, 0xF4, 0xD0, 0x9B, 0x23, 0x00, 0x22, 0xFA, 0x54, ++0x26, 0x4A, 0x27, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0x03, 0xD5, 0x26, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x05, 0xD1, 0x00, 0x23, ++0x9A, 0x22, 0xBB, 0x54, 0x02, 0x3A, 0xBB, 0x52, 0xE2, 0xE7, 0x03, 0x9B, 0x19, 0x02, 0x01, 0x23, 0x19, 0x43, 0xFF, 0x22, ++0x1F, 0x48, 0x7F, 0xF7, 0x17, 0xF8, 0x98, 0x23, 0xF8, 0x5E, 0x9A, 0x23, 0xF9, 0x5C, 0xD5, 0xF7, 0x05, 0xFB, 0x06, 0x4A, ++0x2F, 0x23, 0xD3, 0x5C, 0xC0, 0x1A, 0x9B, 0x23, 0xF8, 0x54, 0x17, 0x4A, 0x13, 0x78, 0x01, 0x3B, 0x13, 0x70, 0xE0, 0xE7, ++0x38, 0x27, 0x16, 0x00, 0x60, 0x92, 0x16, 0x00, 0x29, 0x06, 0x00, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x9A, 0x69, 0x61, 0x40, ++0xFF, 0xCF, 0xFF, 0xFF, 0x2A, 0x06, 0x00, 0x00, 0x0C, 0x01, 0x60, 0x40, 0x92, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, ++0x96, 0x69, 0x61, 0x40, 0x98, 0x69, 0x61, 0x40, 0x9C, 0x69, 0x61, 0x40, 0x27, 0x06, 0x00, 0x00, 0x00, 0x00, 0x61, 0x40, ++0x0E, 0x65, 0x61, 0x40, 0xA8, 0x69, 0x61, 0x40, 0xB6, 0x69, 0x61, 0x40, 0xC4, 0x69, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, ++0x9D, 0x02, 0x00, 0x00, 0x24, 0xE6, 0x10, 0x00, 0x2F, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x04, 0x00, ++0x88, 0x46, 0x16, 0x00, 0xFF, 0xF7, 0x84, 0xFA, 0x00, 0x28, 0x3F, 0xD1, 0x22, 0x4D, 0x23, 0x4F, 0xEB, 0x5D, 0x04, 0x22, ++0x93, 0x43, 0xEB, 0x55, 0x32, 0x00, 0x41, 0x46, 0x20, 0x00, 0xFF, 0xF7, 0x1F, 0xFE, 0xEB, 0x5D, 0x04, 0x22, 0x13, 0x43, ++0xEB, 0x55, 0xA4, 0x00, 0x1C, 0x4B, 0xE4, 0x58, 0xA7, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x02, 0xD9, 0xA7, 0x23, 0x04, 0x22, ++0xE2, 0x54, 0xFE, 0xF7, 0x49, 0xFB, 0x00, 0x28, 0x02, 0xD1, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xB1, 0xF7, 0x04, 0xFD, ++0x00, 0x28, 0xF8, 0xD1, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x0A, 0xD1, 0xA7, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x06, 0xD1, ++0xAA, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0xA7, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xA8, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x03, 0xD1, 0x62, 0x68, 0x09, 0x4B, 0x1A, 0x60, 0xE1, 0xE7, 0xA8, 0xF7, 0x81, 0xFB, 0x08, 0x4B, 0x18, 0x60, 0xF6, 0xE7, ++0x32, 0x00, 0x41, 0x46, 0x20, 0x00, 0xFF, 0xF7, 0xE5, 0xFD, 0xC8, 0xE7, 0x7C, 0x1E, 0x16, 0x00, 0x9D, 0x02, 0x00, 0x00, ++0x38, 0x27, 0x16, 0x00, 0x28, 0xE6, 0x10, 0x00, 0x2C, 0xE6, 0x10, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x1A, 0x60, 0x04, 0x4B, ++0x04, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x04, 0x30, 0x34, 0x40, 0xC1, 0x00, 0xA0, 0x00, 0x0C, 0x00, 0x58, 0x40, ++0x14, 0x00, 0x7F, 0x30, 0x01, 0x4B, 0x02, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0x04, 0x30, 0x34, 0x40, 0xC0, 0x00, 0xA0, 0x00, ++0x10, 0xB5, 0x30, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x09, 0xD0, 0x01, 0x28, 0x08, 0xD0, 0x02, 0x28, 0x47, 0xD0, 0x2D, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x10, 0xBD, 0xA8, 0xF7, 0x44, 0xFB, 0x27, 0x4B, 0x5B, 0x78, ++0x00, 0x2B, 0x11, 0xD1, 0x25, 0x4B, 0x01, 0x22, 0x5A, 0x70, 0x58, 0x60, 0x9B, 0x78, 0x01, 0x2B, 0xF1, 0xD0, 0xFE, 0xF7, ++0xA7, 0xFA, 0x00, 0x28, 0xED, 0xD1, 0xFE, 0xF7, 0xC1, 0xFA, 0x00, 0x28, 0xE9, 0xD1, 0xFF, 0xF7, 0xC1, 0xFF, 0xE6, 0xE7, ++0x1C, 0x4A, 0x53, 0x68, 0xC3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x92, 0x78, 0x00, 0x2A, 0x0B, 0xD1, 0x23, 0x2B, 0xDC, 0xD9, ++0x17, 0x4B, 0x01, 0x32, 0x9A, 0x70, 0x00, 0x22, 0x5A, 0x70, 0x58, 0x60, 0x16, 0x4B, 0x17, 0x4A, 0x1A, 0x60, 0xD2, 0xE7, ++0x01, 0x2A, 0xD0, 0xD1, 0x3B, 0x2B, 0xCE, 0xD9, 0x10, 0x4B, 0x00, 0x22, 0x9A, 0x70, 0x01, 0x32, 0x5A, 0x70, 0x58, 0x60, ++0xFE, 0xF7, 0x7E, 0xFA, 0x00, 0x28, 0xC4, 0xD1, 0xFE, 0xF7, 0x98, 0xFA, 0x00, 0x28, 0xC0, 0xD1, 0xFF, 0xF7, 0x98, 0xFF, ++0xBD, 0xE7, 0x08, 0x4B, 0x5B, 0x78, 0x01, 0x2B, 0x01, 0xD0, 0x00, 0x29, 0xB7, 0xD0, 0x05, 0x4B, 0x00, 0x22, 0x5A, 0x70, ++0x9A, 0x70, 0x01, 0x3A, 0x5A, 0x60, 0x04, 0x4B, 0x04, 0x4A, 0x1A, 0x60, 0xAD, 0xE7, 0xC0, 0x46, 0xDC, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x04, 0x30, 0x34, 0x40, 0xC0, 0x00, 0xA0, 0x00, 0xF0, 0xB5, 0x80, 0x00, 0x26, 0x4B, 0xC3, 0x58, ++0xAB, 0x20, 0x18, 0x5C, 0x00, 0x28, 0x27, 0xD0, 0x0D, 0x1C, 0xAA, 0x20, 0x80, 0x00, 0x81, 0x42, 0x01, 0xD3, 0x22, 0x49, ++0x0D, 0x1C, 0xAD, 0xB2, 0x9D, 0x21, 0x5F, 0x5C, 0x00, 0x23, 0x00, 0x24, 0x01, 0x26, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, ++0x0C, 0xD0, 0xD8, 0xB2, 0x39, 0x00, 0x19, 0x41, 0x0E, 0x42, 0xF7, 0xD0, 0x59, 0x00, 0x1A, 0x4C, 0x61, 0x5A, 0xA9, 0x42, ++0x01, 0xD2, 0x04, 0x00, 0xF0, 0xE7, 0x04, 0x00, 0x17, 0x4B, 0x18, 0x5D, 0x64, 0x00, 0x15, 0x4B, 0xE3, 0x5A, 0xAB, 0x42, ++0x00, 0xD9, 0x2B, 0x00, 0x13, 0x80, 0xF0, 0xBD, 0x9C, 0x20, 0x1F, 0x5C, 0x00, 0x23, 0x00, 0x25, 0x01, 0x26, 0x02, 0xE0, ++0x01, 0x33, 0x06, 0x2B, 0x0C, 0xD0, 0xDC, 0xB2, 0x38, 0x00, 0x18, 0x41, 0x06, 0x42, 0xF7, 0xD0, 0x58, 0x00, 0x0C, 0x4D, ++0x28, 0x5A, 0x88, 0x42, 0x01, 0xD2, 0x25, 0x00, 0xF0, 0xE7, 0x25, 0x00, 0x09, 0x4B, 0x58, 0x5D, 0x6D, 0x00, 0x07, 0x4B, ++0xEB, 0x5A, 0x8B, 0x42, 0x00, 0xD9, 0x0B, 0x00, 0x13, 0x80, 0xDE, 0xE7, 0x38, 0x27, 0x16, 0x00, 0xA7, 0x02, 0x00, 0x00, ++0x40, 0xC9, 0x0D, 0x00, 0x50, 0xC9, 0x0D, 0x00, 0x2C, 0xC9, 0x0D, 0x00, 0x38, 0xC9, 0x0D, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x85, 0xB0, 0x00, 0x90, 0x88, 0x46, 0x82, 0x00, 0x95, 0x4B, 0xD4, 0x58, ++0xAF, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD9, 0x0D, 0xE1, 0x03, 0x02, 0x01, 0x27, 0x1F, 0x43, 0x88, 0x23, 0x99, 0x46, ++0xBB, 0x46, 0x2A, 0xE0, 0xAB, 0x00, 0x5D, 0x19, 0x6D, 0x00, 0x8E, 0x4B, 0xEA, 0x18, 0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, ++0x60, 0x39, 0x0B, 0x43, 0x13, 0x80, 0x8B, 0x4B, 0xEA, 0x18, 0x83, 0x79, 0xDB, 0x00, 0x11, 0x39, 0x0B, 0x43, 0x13, 0x80, ++0x82, 0x88, 0x88, 0x4B, 0xEB, 0x18, 0x1A, 0x80, 0x87, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, ++0x2B, 0x80, 0xAE, 0x22, 0xA3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, ++0xAF, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD9, 0xDB, 0xE0, 0x9E, 0x23, 0xE5, 0x5C, 0x6D, 0x00, 0x10, 0x33, 0xE3, 0x5C, ++0xED, 0x18, 0xED, 0xB2, 0x20, 0x00, 0x40, 0x30, 0x81, 0xF7, 0x84, 0xFA, 0x00, 0x28, 0xC7, 0xD1, 0xEC, 0x23, 0xE3, 0x58, ++0x00, 0x2B, 0x39, 0xD0, 0x9A, 0x7A, 0x00, 0x2A, 0x36, 0xD1, 0xAC, 0x32, 0xA2, 0x5C, 0x00, 0x2A, 0x00, 0xD1, 0xC2, 0xE0, ++0x9A, 0x78, 0x05, 0x3A, 0x03, 0x2A, 0x00, 0xD8, 0xBD, 0xE0, 0x1A, 0x88, 0xA9, 0x00, 0x4D, 0x19, 0x6D, 0x00, 0x69, 0x49, ++0x68, 0x18, 0x01, 0x88, 0xDE, 0x79, 0x0F, 0x23, 0x33, 0x40, 0xDB, 0x00, 0x78, 0x26, 0xB1, 0x43, 0x0B, 0x43, 0x03, 0x80, ++0x64, 0x4B, 0xE9, 0x18, 0xD3, 0x00, 0x05, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x0B, 0x80, 0xEC, 0x23, 0xE3, 0x58, 0x1A, 0x89, ++0x62, 0x4B, 0xEB, 0x18, 0x1A, 0x80, 0x60, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x2B, 0x80, ++0xAE, 0x22, 0xA3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0xAF, 0xE7, ++0xAC, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x8B, 0xE0, 0x96, 0x23, 0xE1, 0x5A, 0x01, 0x27, 0x00, 0x29, 0x39, 0xD0, ++0x02, 0xAB, 0x9A, 0x1D, 0x00, 0x98, 0xFF, 0xF7, 0x07, 0xFF, 0xAB, 0x00, 0x5D, 0x19, 0x6D, 0x00, 0x4B, 0x4B, 0xEA, 0x18, ++0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, 0xC0, 0x00, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x48, 0x4B, 0xEA, 0x18, 0x02, 0xAB, ++0xDB, 0x88, 0xDB, 0x00, 0x1F, 0x43, 0x04, 0x23, 0x1F, 0x43, 0xBF, 0xB2, 0x17, 0x80, 0x94, 0x22, 0xA1, 0x5A, 0x45, 0x4B, ++0xEB, 0x18, 0x19, 0x80, 0x42, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x2B, 0x80, 0x02, 0xAB, ++0xDB, 0x88, 0x96, 0x20, 0x21, 0x5A, 0xC9, 0x1A, 0x21, 0x52, 0xA1, 0x5A, 0x5B, 0x18, 0xA3, 0x52, 0x1A, 0x32, 0xA3, 0x5C, ++0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x6B, 0xE7, 0x27, 0x00, 0x48, 0x37, ++0x80, 0x23, 0x1B, 0x05, 0x9A, 0x46, 0x0F, 0xE0, 0x52, 0x00, 0x8A, 0x42, 0x1E, 0xDA, 0x01, 0x23, 0xFF, 0x22, 0x59, 0x46, ++0x31, 0x48, 0x7E, 0xF7, 0x7F, 0xFD, 0x01, 0x23, 0x03, 0x70, 0x7E, 0xF7, 0xA5, 0xFD, 0x30, 0x89, 0x88, 0xF7, 0x98, 0xFE, ++0x38, 0x00, 0x81, 0xF7, 0xE7, 0xF9, 0x06, 0x1E, 0x46, 0xD0, 0x4B, 0x46, 0xE2, 0x5A, 0x00, 0x2A, 0x08, 0xD0, 0x43, 0x68, ++0x59, 0x1C, 0x05, 0xD0, 0x41, 0x46, 0xCB, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x51, 0x45, 0xDD, 0xD9, 0x73, 0x89, 0x9F, 0x04, ++0xBF, 0x0F, 0x9B, 0x05, 0x9B, 0x0D, 0x9A, 0x46, 0x90, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0x2C, 0xD0, 0x8C, 0x23, 0xE3, 0x58, ++0x00, 0x2B, 0x06, 0xD0, 0x1D, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x8C, 0x23, ++0xE6, 0x50, 0x96, 0x23, 0x52, 0x46, 0xE2, 0x52, 0x32, 0x89, 0x02, 0x3B, 0xE2, 0x52, 0x01, 0x2F, 0x00, 0xD0, 0x02, 0x27, ++0x96, 0x23, 0xE1, 0x5A, 0x00, 0x29, 0x00, 0xD0, 0x78, 0xE7, 0xAF, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x06, 0xD0, 0xA8, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x02, 0xD1, 0xA8, 0x33, 0x01, 0x22, 0xE2, 0x54, 0x05, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x90, 0x33, 0xE6, 0x50, 0xDC, 0xE7, 0x01, 0x27, 0xE3, 0xE7, 0x38, 0x27, 0x16, 0x00, ++0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xD0, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0xCE, 0x69, 0x61, 0x40, ++0x2B, 0x06, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, ++0x83, 0xB0, 0x82, 0x00, 0x4B, 0x4B, 0xD4, 0x58, 0x90, 0x23, 0xE2, 0x58, 0x00, 0x2A, 0x00, 0xD1, 0x84, 0xE0, 0x49, 0x4B, ++0x59, 0x88, 0x49, 0x4B, 0x1B, 0x78, 0x99, 0x42, 0x73, 0xD9, 0x9E, 0x23, 0xE3, 0x5C, 0x5B, 0x00, 0xAD, 0x21, 0x61, 0x5C, ++0x5B, 0x18, 0xDB, 0xB2, 0x56, 0x89, 0xB6, 0x05, 0xB2, 0x0D, 0x90, 0x46, 0x02, 0x22, 0x90, 0x26, 0x41, 0x49, 0x01, 0x91, ++0xAF, 0x21, 0x8A, 0x46, 0x01, 0x39, 0x89, 0x46, 0x10, 0x39, 0x8C, 0x46, 0x00, 0x90, 0x0C, 0xE0, 0x63, 0x46, 0xE5, 0x5C, ++0x6D, 0x00, 0xAD, 0x23, 0xE1, 0x5C, 0x4B, 0x42, 0x4B, 0x41, 0x5B, 0x19, 0xDB, 0xB2, 0x01, 0x3A, 0xD2, 0xB2, 0x00, 0x2A, ++0x31, 0xD0, 0x99, 0x00, 0xCB, 0x18, 0x5B, 0x00, 0x35, 0x49, 0x5F, 0x18, 0x39, 0x88, 0x89, 0xB2, 0xA5, 0x59, 0x2D, 0x89, ++0x8D, 0x42, 0xE7, 0xD8, 0x45, 0x44, 0xA9, 0x42, 0xE4, 0xDA, 0x31, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x01, 0x98, 0x01, 0x40, ++0x29, 0x80, 0x2F, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x2D, 0x48, 0x01, 0x43, 0x89, 0xB2, 0x29, 0x80, ++0x2C, 0x49, 0x8B, 0x46, 0x5B, 0x44, 0x19, 0x88, 0x78, 0x20, 0x81, 0x43, 0x19, 0x80, 0x00, 0x23, 0x3B, 0x80, 0x53, 0x46, ++0xE3, 0x5C, 0x01, 0x3B, 0x51, 0x46, 0x63, 0x54, 0x4B, 0x46, 0xE3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0x49, 0x46, 0x63, 0x54, ++0xC0, 0xE7, 0x00, 0x98, 0x00, 0x02, 0x01, 0x25, 0x28, 0x43, 0x81, 0xB2, 0x01, 0x23, 0xFF, 0x32, 0x1F, 0x48, 0x7E, 0xF7, ++0xA5, 0xFC, 0x05, 0x70, 0x7E, 0xF7, 0xCC, 0xFC, 0x1D, 0x48, 0x80, 0xF7, 0xA3, 0xFD, 0x90, 0x23, 0xE3, 0x58, 0x18, 0x89, ++0x88, 0xF7, 0xBA, 0xFD, 0x8C, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0x0B, 0xD0, 0x90, 0x22, 0xA3, 0x50, 0x8C, 0x23, 0x00, 0x22, ++0xE2, 0x50, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x96, 0x22, 0x00, 0x21, ++0xA1, 0x52, 0xEF, 0xE7, 0x8C, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0xF0, 0xD0, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0xE9, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x9C, 0xE5, 0x10, 0x00, 0xF8, 0xE1, 0x10, 0x00, ++0x07, 0xE0, 0xFF, 0xFF, 0xCE, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, ++0xCA, 0x69, 0x61, 0x40, 0x2B, 0x06, 0x00, 0x00, 0x18, 0xD1, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x03, 0x00, 0x00, 0x20, ++0x9A, 0x6C, 0x00, 0x2A, 0x00, 0xD0, 0x70, 0x47, 0xA7, 0x32, 0x9A, 0x5C, 0x00, 0x2A, 0xFA, 0xD1, 0xA8, 0x32, 0x98, 0x5C, ++0x43, 0x42, 0x58, 0x41, 0xC0, 0xB2, 0xF4, 0xE7, 0x04, 0x4B, 0x18, 0x68, 0x04, 0x4B, 0x1B, 0x68, 0x18, 0x43, 0x43, 0x1E, ++0x98, 0x41, 0xC0, 0xB2, 0x70, 0x47, 0xC0, 0x46, 0x24, 0x27, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0x70, 0xB5, 0x84, 0xB0, ++0x82, 0x00, 0x12, 0x4B, 0xD5, 0x58, 0x01, 0xA9, 0x11, 0x4C, 0x02, 0x01, 0x13, 0x1A, 0x9B, 0x00, 0xE3, 0x18, 0xDE, 0x88, ++0x4E, 0x80, 0x1E, 0x7B, 0x4E, 0x70, 0x1E, 0x89, 0xCE, 0x80, 0x5E, 0x89, 0x0E, 0x81, 0x9B, 0x88, 0x8B, 0x80, 0x12, 0x1A, ++0x92, 0x00, 0xA2, 0x18, 0x53, 0x7B, 0x01, 0x22, 0x53, 0x40, 0x36, 0x22, 0xAA, 0x5C, 0x5A, 0x40, 0x01, 0x23, 0x13, 0x40, ++0x2E, 0x22, 0x13, 0x43, 0x0B, 0x70, 0xA6, 0xF7, 0x0F, 0xF9, 0x04, 0xB0, 0x70, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0xC0, 0xA0, 0x16, 0x00, 0xF8, 0xB5, 0x06, 0x00, 0x0C, 0x00, 0x05, 0x0A, 0xAA, 0x00, 0x18, 0x4B, 0xD7, 0x58, 0x36, 0x23, ++0xFB, 0x5C, 0x00, 0x2B, 0x0C, 0xD0, 0x2B, 0x01, 0x5B, 0x1B, 0x9B, 0x00, 0x14, 0x4A, 0xD3, 0x18, 0x5B, 0x7B, 0x00, 0x2B, ++0x08, 0xD1, 0x01, 0x21, 0x30, 0x00, 0x7E, 0xF7, 0x77, 0xFF, 0xF8, 0xBD, 0xE8, 0xB2, 0xB2, 0xF7, 0x73, 0xF9, 0xEE, 0xE7, ++0x08, 0x23, 0x14, 0x22, 0x00, 0x21, 0x0D, 0x48, 0x7E, 0xF7, 0xF6, 0xFB, 0x04, 0x70, 0x2B, 0x00, 0x80, 0x33, 0x43, 0x80, ++0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, 0xFB, 0x5C, 0x03, 0x71, 0xD0, 0xF7, 0x4B, 0xFA, 0x2B, 0x01, 0x5D, 0x1B, 0xAD, 0x00, ++0x03, 0x4B, 0x5D, 0x19, 0x00, 0x23, 0x6B, 0x73, 0xDD, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xC0, 0xA0, 0x16, 0x00, ++0x03, 0x11, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x93, 0xB0, 0x05, 0x00, ++0x03, 0x91, 0x93, 0x46, 0x1E, 0x00, 0x1C, 0xAB, 0x1B, 0x88, 0x99, 0x46, 0x1D, 0xAB, 0x1B, 0x88, 0x9A, 0x46, 0x04, 0x0A, ++0xA2, 0x00, 0xCB, 0x4B, 0xD7, 0x58, 0x01, 0x00, 0xCA, 0x48, 0x7E, 0xF7, 0x7B, 0xFB, 0xB3, 0x1F, 0xC9, 0x4A, 0x9B, 0xB2, ++0x93, 0x42, 0x03, 0xD8, 0x5B, 0x46, 0x33, 0x43, 0xDB, 0x07, 0x0D, 0xD5, 0x39, 0x23, 0xFB, 0x5C, 0xE0, 0xB2, 0x12, 0x22, ++0x17, 0x21, 0xA6, 0xF7, 0xF6, 0xF8, 0x13, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, ++0x5E, 0x45, 0xEF, 0xD9, 0x4B, 0x46, 0x00, 0x2B, 0xEC, 0xD0, 0x73, 0x08, 0x4B, 0x45, 0xE9, 0xD3, 0x53, 0x46, 0x28, 0x2B, ++0xE6, 0xD8, 0x4B, 0x44, 0x5B, 0x00, 0xB3, 0x42, 0xE2, 0xD2, 0x28, 0x00, 0x7E, 0xF7, 0x70, 0xFF, 0x01, 0x28, 0x00, 0xD1, ++0x85, 0xE0, 0xB5, 0x4B, 0x22, 0x01, 0x11, 0x1B, 0x89, 0x00, 0xCE, 0x52, 0x5B, 0x18, 0x5E, 0x80, 0x4A, 0x46, 0x1A, 0x81, ++0x9E, 0x80, 0x5A, 0x46, 0xDA, 0x80, 0x52, 0x46, 0x5A, 0x81, 0x03, 0x9A, 0x1A, 0x73, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x22, ++0x04, 0x92, 0x01, 0x2B, 0x77, 0xD0, 0x0A, 0x96, 0x0B, 0x96, 0x36, 0x23, 0xF8, 0x5C, 0x4A, 0x46, 0x02, 0x2A, 0x00, 0xD9, ++0x02, 0x22, 0x90, 0x46, 0x80, 0x44, 0x0A, 0xAB, 0x42, 0x46, 0x0C, 0x92, 0x49, 0x46, 0x49, 0x00, 0x0D, 0x91, 0x00, 0x21, ++0x99, 0x74, 0x80, 0x31, 0x8C, 0x46, 0xA4, 0x44, 0x61, 0x46, 0x19, 0x82, 0x01, 0x21, 0x04, 0x9A, 0x11, 0x40, 0xD9, 0x74, ++0x06, 0xAB, 0x06, 0x96, 0x42, 0x46, 0x07, 0x92, 0x62, 0x46, 0x9A, 0x81, 0x00, 0x28, 0x5A, 0xD1, 0x58, 0x46, 0x08, 0x90, ++0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, 0x5A, 0xD0, 0x08, 0x9B, 0x10, 0x93, 0x11, 0x93, 0x06, 0x9B, 0x0F, 0x93, 0x06, 0xA8, ++0xD4, 0xF7, 0x5A, 0xFA, 0x80, 0x46, 0x00, 0x28, 0x72, 0xD1, 0x0A, 0xAA, 0x10, 0x98, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, ++0x8D, 0x49, 0xCB, 0x18, 0x98, 0x62, 0x0F, 0x99, 0x8C, 0x46, 0x59, 0x62, 0x0C, 0x99, 0xD9, 0x62, 0x0D, 0x99, 0x19, 0x63, ++0x12, 0x8A, 0x9A, 0x86, 0x00, 0x22, 0x9A, 0x63, 0x36, 0x33, 0x1A, 0x70, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x6B, 0xD1, ++0x80, 0xB2, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x81, 0x4A, 0xD3, 0x18, 0xD8, 0x80, 0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, ++0x67, 0xD0, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, 0x7D, 0x4B, 0x9A, 0x42, 0x79, 0xD1, 0x43, 0x46, 0x01, 0x2B, ++0x00, 0xD1, 0xDF, 0xE0, 0x02, 0x2B, 0x00, 0xD1, 0xBC, 0xE0, 0x00, 0x2B, 0x00, 0xD1, 0xAE, 0xE0, 0x77, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x5D, 0xE7, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x70, 0x4A, 0xD3, 0x18, ++0x00, 0x22, 0x5A, 0x73, 0x71, 0xE7, 0xE0, 0xB2, 0xAF, 0xF7, 0xAE, 0xFE, 0x43, 0x08, 0x04, 0x93, 0x81, 0xE7, 0x04, 0x9A, ++0x31, 0x00, 0x58, 0x46, 0xA5, 0xF7, 0x2E, 0xFD, 0x9F, 0xE7, 0x06, 0x9B, 0x9B, 0x46, 0x01, 0x3B, 0x98, 0x46, 0x80, 0x44, ++0x5B, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x66, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x59, 0x46, ++0x40, 0x46, 0xD4, 0xF7, 0x1B, 0xFE, 0x08, 0x91, 0x0A, 0xAB, 0xDA, 0x7C, 0x01, 0x21, 0x4A, 0x40, 0xDA, 0x74, 0x0C, 0x9A, ++0x03, 0x32, 0x0C, 0x92, 0x0D, 0x9A, 0x03, 0x32, 0x0D, 0x92, 0x07, 0x9B, 0x05, 0x93, 0x03, 0x33, 0x07, 0x93, 0x81, 0xE7, ++0x28, 0x00, 0x7E, 0xF7, 0xAD, 0xFE, 0x80, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x01, 0x23, 0x98, 0x46, 0x83, 0xE7, 0x0A, 0xA8, ++0xD4, 0xF7, 0x6A, 0xF9, 0x00, 0x28, 0x00, 0xD0, 0x7D, 0xE7, 0x02, 0x23, 0x98, 0x46, 0x7A, 0xE7, 0x63, 0x46, 0x99, 0xB2, ++0x80, 0xB2, 0x04, 0x9A, 0xA5, 0xF7, 0x0A, 0xFD, 0x8D, 0xE7, 0x43, 0x1C, 0x04, 0x93, 0x0F, 0x9B, 0x9B, 0x46, 0x00, 0x2B, ++0x05, 0xD1, 0x49, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, ++0x42, 0x4A, 0xD3, 0x18, 0x05, 0x93, 0x59, 0x46, 0x04, 0x98, 0xD4, 0xF7, 0xDB, 0xFD, 0x05, 0x9B, 0xD9, 0x80, 0x7E, 0xE7, ++0xE3, 0xB2, 0x9B, 0x46, 0x18, 0x00, 0x95, 0xF7, 0x71, 0xFF, 0x05, 0x90, 0x0F, 0x9B, 0x04, 0x93, 0x00, 0x28, 0x05, 0xD1, ++0x3A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x05, 0x99, 0x04, 0x98, 0xD4, 0xF7, 0xC4, 0xFD, ++0x00, 0x29, 0x00, 0xD0, 0x6E, 0xE7, 0x3C, 0x22, 0x62, 0x43, 0x31, 0x4B, 0x9B, 0x18, 0xD9, 0x88, 0x11, 0x9B, 0x04, 0x93, ++0x10, 0x9B, 0x05, 0x93, 0x04, 0x9B, 0x05, 0x9A, 0x9A, 0x1A, 0x8A, 0x18, 0x92, 0xB2, 0x58, 0x46, 0x95, 0xF7, 0x9C, 0xFF, ++0x04, 0x90, 0x0F, 0x9B, 0x9B, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x29, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, ++0x98, 0x47, 0x3C, 0x23, 0x63, 0x43, 0x23, 0x4A, 0xD3, 0x18, 0x05, 0x93, 0x59, 0x46, 0x04, 0x98, 0xD4, 0xF7, 0x9C, 0xFD, ++0x05, 0x9B, 0xD9, 0x80, 0x46, 0xE7, 0x39, 0x33, 0xFA, 0x5C, 0xE0, 0xB2, 0x17, 0x21, 0xA5, 0xF7, 0x87, 0xFF, 0x2F, 0x21, ++0x28, 0x00, 0x7E, 0xF7, 0xD5, 0xFD, 0xAA, 0xE6, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x0A, 0xD0, 0xE0, 0xB2, 0xFF, 0xF7, ++0x13, 0xFE, 0x28, 0x00, 0x96, 0xF7, 0x3A, 0xFB, 0x2E, 0x21, 0x28, 0x00, 0x7E, 0xF7, 0xC6, 0xFD, 0x9B, 0xE6, 0x3C, 0x22, ++0x62, 0x43, 0x10, 0x4B, 0x9B, 0x18, 0xD9, 0x88, 0xE0, 0xB2, 0x03, 0x9B, 0x9F, 0x07, 0xFF, 0x0F, 0x01, 0x97, 0x53, 0x46, ++0x00, 0x93, 0x4B, 0x46, 0x32, 0x00, 0xAF, 0xF7, 0x5F, 0xFC, 0xE3, 0xE7, 0x39, 0x23, 0xFB, 0x5C, 0xE0, 0xB2, 0x20, 0x22, ++0x17, 0x21, 0xA5, 0xF7, 0x7A, 0xFF, 0x20, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x1B, 0xFE, 0x7E, 0xE6, 0x64, 0xA2, 0x16, 0x00, ++0x05, 0x06, 0x00, 0x00, 0x3A, 0x05, 0x00, 0x00, 0xC0, 0xA0, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x8A, 0xB0, 0x06, 0x00, 0x88, 0x46, 0x91, 0x46, 0x1D, 0x00, ++0x12, 0xAB, 0x1B, 0x88, 0x9C, 0x46, 0x04, 0x0A, 0xA2, 0x00, 0x9C, 0x4B, 0xD7, 0x58, 0x9C, 0x4B, 0x22, 0x01, 0x11, 0x1B, ++0x89, 0x00, 0x40, 0x46, 0xC8, 0x52, 0x5B, 0x18, 0x4A, 0x46, 0x5A, 0x80, 0x1D, 0x81, 0x62, 0x46, 0x5A, 0x81, 0x36, 0x23, ++0xFB, 0x5C, 0x00, 0x22, 0x92, 0x46, 0x01, 0x2B, 0x00, 0xD1, 0x87, 0xE0, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x91, 0x4A, ++0xD3, 0x18, 0x00, 0x22, 0x1A, 0x73, 0xA7, 0xF7, 0x29, 0xFE, 0x50, 0x44, 0x03, 0x01, 0x06, 0xD5, 0x23, 0x01, 0x1B, 0x1B, ++0x9B, 0x00, 0x8B, 0x4A, 0xD3, 0x18, 0x02, 0x22, 0x1A, 0x73, 0x02, 0xAB, 0x4A, 0x46, 0x02, 0x92, 0x42, 0x46, 0x5A, 0x60, ++0x2A, 0x00, 0x02, 0x2D, 0x00, 0xD9, 0x02, 0x22, 0x9A, 0x60, 0x6D, 0x00, 0x05, 0x95, 0x00, 0x23, 0x02, 0xAA, 0x93, 0x74, ++0x25, 0x00, 0x80, 0x35, 0x15, 0x82, 0x53, 0x46, 0x5B, 0x08, 0x9A, 0x46, 0x01, 0x23, 0x52, 0x46, 0x13, 0x40, 0x02, 0xAA, ++0xD3, 0x74, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, 0x7B, 0x4B, 0x9A, 0x42, 0x58, 0xD1, 0x36, 0x23, 0xFB, 0x5C, ++0x01, 0x2B, 0x6A, 0xD0, 0x02, 0xA8, 0xD4, 0xF7, 0x63, 0xF8, 0x00, 0x28, 0x00, 0xD0, 0x72, 0xE0, 0x08, 0x98, 0x22, 0x01, ++0x12, 0x1B, 0x92, 0x00, 0x71, 0x4B, 0x9B, 0x18, 0x98, 0x62, 0x07, 0x99, 0x59, 0x62, 0x04, 0x9A, 0xDA, 0x62, 0x05, 0x9A, ++0x00, 0x92, 0x1A, 0x63, 0x02, 0xAA, 0x12, 0x8A, 0x9A, 0x86, 0x00, 0x22, 0x9A, 0x63, 0x36, 0x33, 0x1A, 0x70, 0x36, 0x23, ++0xFB, 0x5C, 0x00, 0x2B, 0x6A, 0xD1, 0x80, 0xB2, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x65, 0x4A, 0xD3, 0x18, 0xD8, 0x80, ++0x07, 0x9D, 0x9D, 0x80, 0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, 0x63, 0xD0, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, ++0x5F, 0x4B, 0x9A, 0x42, 0x00, 0xD0, 0x72, 0xE0, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x5B, 0x4A, 0xD3, 0x18, 0x01, 0x22, ++0x5A, 0x73, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0xA4, 0xE0, 0xE0, 0xB2, 0xFF, 0xF7, 0x43, 0xFD, 0x30, 0x00, ++0x96, 0xF7, 0x6A, 0xFA, 0x2E, 0x21, 0x30, 0x00, 0x7E, 0xF7, 0xF6, 0xFC, 0x0A, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xF0, 0xBD, 0xE0, 0xB2, 0xAF, 0xF7, 0x1F, 0xFD, 0x82, 0x46, 0x72, 0xE7, 0xE0, 0xB2, 0x95, 0xF7, 0x40, 0xFE, ++0x02, 0x00, 0x03, 0x00, 0x02, 0x98, 0x82, 0x42, 0x07, 0xD2, 0x00, 0x92, 0x11, 0x00, 0xD4, 0xF7, 0x13, 0xFC, 0x43, 0x1C, ++0x00, 0x9A, 0x5A, 0x43, 0x93, 0xB2, 0x03, 0x9A, 0x93, 0x42, 0x93, 0xD8, 0x02, 0x93, 0x03, 0x93, 0x90, 0xE7, 0x02, 0xAB, ++0xDB, 0x7C, 0x01, 0x22, 0x53, 0x40, 0x02, 0xAA, 0xD3, 0x74, 0x04, 0x9B, 0x03, 0x33, 0x04, 0x93, 0x05, 0x9B, 0x00, 0x93, ++0x03, 0x33, 0x05, 0x93, 0x86, 0xE7, 0x08, 0x23, 0x14, 0x22, 0x00, 0x21, 0x3A, 0x48, 0x7E, 0xF7, 0x4B, 0xF9, 0x20, 0x23, ++0x03, 0x70, 0x45, 0x80, 0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, 0xFB, 0x5C, 0x03, 0x71, 0xCF, 0xF7, 0xA1, 0xFF, 0xBF, 0xE7, ++0x89, 0xB2, 0x80, 0xB2, 0x52, 0x46, 0xA5, 0xF7, 0x83, 0xFB, 0x8F, 0xE7, 0x43, 0x1C, 0x98, 0x46, 0x00, 0x2D, 0x05, 0xD1, ++0x2F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x28, 0x4A, ++0x91, 0x46, 0x99, 0x44, 0x29, 0x00, 0x40, 0x46, 0xD4, 0xF7, 0x56, 0xFC, 0x4B, 0x46, 0xD9, 0x80, 0x84, 0xE7, 0xE3, 0xB2, ++0x98, 0x46, 0x18, 0x00, 0x95, 0xF7, 0xEC, 0xFD, 0x05, 0x1E, 0x07, 0x9B, 0x99, 0x46, 0x05, 0xD1, 0x21, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x29, 0x00, 0x48, 0x46, 0xD4, 0xF7, 0x40, 0xFC, 0x00, 0x29, 0x00, 0xD0, ++0x76, 0xE7, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x16, 0x4A, 0xD3, 0x18, 0xD9, 0x88, 0x09, 0x9B, 0x00, 0x93, 0x08, 0x9B, ++0x01, 0x93, 0x00, 0x9B, 0x01, 0x9A, 0x9A, 0x1A, 0x8A, 0x18, 0x92, 0xB2, 0x40, 0x46, 0x95, 0xF7, 0x17, 0xFE, 0x81, 0x46, ++0x07, 0x9B, 0x98, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x0F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x08, 0x4D, 0xED, 0x18, 0x41, 0x46, 0x48, 0x46, 0xD4, 0xF7, 0x17, 0xFC, 0xE9, 0x80, ++0x4E, 0xE7, 0xE0, 0xB2, 0x01, 0x33, 0x00, 0x22, 0x17, 0x21, 0x95, 0xF7, 0x89, 0xFC, 0x53, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0xC0, 0xA0, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x00, 0x24, 0x00, 0x20, 0x0E, 0x4E, 0xA1, 0x27, 0xAF, 0x23, 0x98, 0x46, 0x0C, 0xE0, 0x42, 0x46, 0x9D, 0x5C, ++0x45, 0x19, 0xED, 0xB2, 0x48, 0x33, 0x18, 0x00, 0x80, 0xF7, 0x18, 0xFE, 0x28, 0x18, 0xC0, 0xB2, 0x01, 0x34, 0x07, 0x2C, ++0x07, 0xD0, 0xA3, 0x00, 0x9B, 0x59, 0x00, 0x2B, 0xF8, 0xD0, 0xDA, 0x5D, 0x00, 0x2A, 0xF5, 0xD1, 0xEA, 0xE7, 0x04, 0xBC, ++0x90, 0x46, 0xF0, 0xBD, 0x38, 0x27, 0x16, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x40, 0x4B, 0x1A, 0x78, 0x01, 0x2A, 0x01, 0xD0, ++0x05, 0xB0, 0xF0, 0xBD, 0x3E, 0x4B, 0x1D, 0x78, 0x3E, 0x4B, 0x1B, 0x68, 0x00, 0x24, 0x5B, 0x05, 0x08, 0xD5, 0x3C, 0x48, ++0x03, 0x68, 0x3C, 0x49, 0x19, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x0B, 0x43, 0x03, 0x60, 0x80, 0x34, 0x39, 0x4B, 0x1B, 0x68, ++0x9B, 0x05, 0x09, 0xD4, 0x37, 0x48, 0x03, 0x68, 0x37, 0x49, 0x19, 0x40, 0x80, 0x23, 0x9B, 0x00, 0x0B, 0x43, 0x03, 0x60, ++0x40, 0x23, 0x1C, 0x43, 0x34, 0x4B, 0x18, 0x68, 0x34, 0x4B, 0x19, 0x68, 0x34, 0x4B, 0x1E, 0x68, 0x8B, 0x07, 0x31, 0xD4, ++0xF0, 0x23, 0x03, 0x40, 0x30, 0x2B, 0x0E, 0xD0, 0x20, 0x2B, 0x1F, 0xD0, 0x10, 0x2B, 0x29, 0xD1, 0x2F, 0x4B, 0xDB, 0x69, ++0xB3, 0x42, 0x25, 0xD0, 0xF0, 0x23, 0x07, 0x00, 0x9F, 0x43, 0x3B, 0x00, 0x20, 0x27, 0x3B, 0x43, 0x0A, 0xE0, 0x2A, 0x4B, ++0xDB, 0x6B, 0xB3, 0x42, 0x1A, 0xD0, 0xF0, 0x23, 0x02, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x20, 0x22, 0x13, 0x43, 0x1D, 0x3A, ++0x22, 0x4F, 0x3F, 0x68, 0xBF, 0x07, 0x1F, 0xD4, 0x1F, 0x4F, 0x3B, 0x60, 0x14, 0x43, 0x1D, 0xE0, 0x20, 0x4B, 0xDB, 0x6A, ++0xB3, 0x42, 0x07, 0xD0, 0xF0, 0x23, 0x02, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x10, 0x22, 0x13, 0x43, 0x0E, 0x3A, 0xEB, 0xE7, ++0x01, 0x2D, 0xA3, 0xD1, 0x17, 0x4B, 0x1B, 0x68, 0x02, 0x93, 0x00, 0x23, 0x01, 0x93, 0x00, 0x90, 0x33, 0x00, 0x00, 0x22, ++0x16, 0x48, 0x80, 0xF7, 0x47, 0xF9, 0x00, 0x2C, 0x96, 0xD0, 0x0D, 0xE0, 0x04, 0x27, 0x3C, 0x43, 0x01, 0x2D, 0x00, 0xD0, ++0x90, 0xE7, 0x0E, 0x4D, 0x2D, 0x68, 0x02, 0x95, 0x01, 0x93, 0x00, 0x90, 0x33, 0x00, 0x0E, 0x48, 0x80, 0xF7, 0x36, 0xF9, ++0x32, 0x00, 0x21, 0x00, 0x0C, 0x48, 0x80, 0xF7, 0x31, 0xF9, 0x81, 0xE7, 0xB4, 0xE5, 0x10, 0x00, 0xBC, 0xE6, 0x10, 0x00, ++0x4C, 0x20, 0x62, 0x40, 0xFF, 0xF3, 0xFF, 0xFF, 0x58, 0x20, 0x62, 0x40, 0xFF, 0xFD, 0xFF, 0xFF, 0x08, 0x05, 0x62, 0x40, ++0x74, 0x20, 0x62, 0x40, 0x78, 0x20, 0x62, 0x40, 0xD8, 0x97, 0x16, 0x00, 0x24, 0xD1, 0x10, 0x00, 0x3C, 0xD1, 0x10, 0x00, ++0x70, 0x47, 0x00, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x13, 0x60, 0x81, 0x22, 0x52, 0x00, 0x98, 0x5C, 0x70, 0x47, 0xC0, 0x46, ++0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x17, 0x4B, 0x17, 0x4A, 0x1A, 0x60, ++0x17, 0x48, 0x80, 0xF7, 0x53, 0xFD, 0x45, 0x1E, 0x6D, 0xB2, 0x40, 0xB2, 0x00, 0x28, 0x1F, 0xDD, 0x11, 0x4F, 0x14, 0x4B, ++0x98, 0x46, 0x14, 0x4E, 0x0A, 0xE0, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x43, 0x46, 0x9B, 0x6E, 0x98, 0x47, 0x09, 0xE0, ++0x01, 0x3D, 0x6D, 0xB2, 0x6B, 0x1C, 0x0F, 0xD0, 0x38, 0x68, 0x0C, 0x30, 0x80, 0xF7, 0x56, 0xFC, 0x04, 0x1E, 0xEE, 0xD0, ++0x61, 0x6A, 0x30, 0x00, 0x80, 0xF7, 0xE2, 0xF8, 0x63, 0x6A, 0x00, 0x2B, 0xEE, 0xD0, 0x20, 0x00, 0x98, 0x47, 0xEB, 0xE7, ++0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x10, 0xE7, 0x10, 0x00, 0x64, 0x2A, 0x16, 0x00, 0x70, 0x2A, 0x16, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xC0, 0xD3, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x78, 0x21, 0x88, 0xF7, 0xAB, 0xF9, 0x05, 0x00, ++0x08, 0x4B, 0xC0, 0x18, 0x78, 0x22, 0x55, 0x21, 0x7C, 0xF7, 0x42, 0xF8, 0x29, 0x00, 0x20, 0x00, 0x88, 0xF7, 0xBA, 0xF9, ++0x01, 0x00, 0x20, 0x00, 0xB0, 0xF7, 0x1E, 0xFD, 0x02, 0x48, 0x80, 0xF7, 0xB7, 0xF8, 0x70, 0xBD, 0x00, 0x00, 0x61, 0x40, ++0x4C, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x04, 0x00, ++0x83, 0x00, 0x76, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1D, 0x68, 0x00, 0x2D, 0x00, 0xD1, 0xDE, 0xE0, 0x4B, 0x23, 0xEB, 0x5C, ++0x00, 0x2B, 0x05, 0xD0, 0x71, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x28, 0x00, 0x50, 0x30, ++0x80, 0xF7, 0x02, 0xFC, 0x07, 0x00, 0x00, 0x21, 0x20, 0x00, 0x88, 0xF7, 0xDF, 0xF9, 0x63, 0x01, 0x6A, 0x4A, 0x9A, 0x18, ++0x12, 0x68, 0xD2, 0x0F, 0x49, 0x21, 0x69, 0x5C, 0x01, 0x26, 0x71, 0x40, 0x91, 0x42, 0x4F, 0xD0, 0x66, 0x49, 0x8A, 0x46, ++0x9A, 0x44, 0x51, 0x46, 0x09, 0x68, 0x89, 0xB2, 0x8B, 0x46, 0x64, 0x4E, 0xB1, 0x46, 0x99, 0x44, 0x4E, 0x46, 0x36, 0x68, ++0xB6, 0xB2, 0xB0, 0x46, 0x61, 0x4E, 0x9E, 0x19, 0x36, 0x68, 0xB6, 0x03, 0xB1, 0x0F, 0x01, 0x91, 0x56, 0x46, 0x36, 0x68, ++0x36, 0x0C, 0x36, 0x04, 0xB4, 0x46, 0x56, 0x46, 0x61, 0x46, 0x31, 0x60, 0x49, 0x46, 0x09, 0x68, 0x09, 0x0C, 0x09, 0x04, ++0x8C, 0x46, 0x49, 0x46, 0x66, 0x46, 0x0E, 0x60, 0x00, 0x2F, 0x67, 0xD0, 0x00, 0x2A, 0x4C, 0xD1, 0x52, 0x4A, 0x94, 0x46, ++0x9C, 0x44, 0x62, 0x46, 0x12, 0x68, 0x91, 0x46, 0xBA, 0x88, 0x12, 0x04, 0x49, 0x46, 0x0F, 0x04, 0x3F, 0x0C, 0x3A, 0x43, ++0x61, 0x46, 0x0A, 0x60, 0x00, 0x28, 0x0A, 0xD0, 0x4B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x68, 0x82, 0x88, 0x04, 0x32, ++0x12, 0x04, 0x38, 0x04, 0x00, 0x0C, 0x02, 0x43, 0x1A, 0x60, 0x5B, 0x46, 0x00, 0x2B, 0x4C, 0xD1, 0x43, 0x46, 0x00, 0x2B, ++0x4E, 0xD1, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x3E, 0x49, 0x8A, 0x46, ++0x9A, 0x44, 0x51, 0x46, 0x09, 0x68, 0x09, 0x0C, 0x8B, 0x46, 0x3C, 0x49, 0x89, 0x46, 0x99, 0x44, 0x49, 0x46, 0x0E, 0x68, ++0x31, 0x0C, 0x88, 0x46, 0x39, 0x49, 0x5E, 0x18, 0x36, 0x68, 0x36, 0x03, 0xB1, 0x0F, 0x01, 0x91, 0x51, 0x46, 0x09, 0x68, ++0x09, 0x04, 0x09, 0x0C, 0x8C, 0x46, 0x51, 0x46, 0x66, 0x46, 0x0E, 0x60, 0x49, 0x46, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0C, ++0x8C, 0x46, 0x49, 0x46, 0x66, 0x46, 0x0E, 0x60, 0xAE, 0xE7, 0x2C, 0x4A, 0x94, 0x46, 0x9C, 0x44, 0x62, 0x46, 0x12, 0x68, ++0x12, 0x0C, 0x12, 0x04, 0xBF, 0x88, 0x3A, 0x43, 0x61, 0x46, 0x0A, 0x60, 0x00, 0x28, 0xC0, 0xD0, 0x26, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1F, 0x68, 0x82, 0x88, 0x04, 0x32, 0x92, 0xB2, 0x38, 0x0C, 0x00, 0x04, 0x02, 0x43, 0x1A, 0x60, 0xB4, 0xE7, ++0x00, 0x28, 0xB2, 0xD0, 0x00, 0x2A, 0xEF, 0xD1, 0xA4, 0xE7, 0x59, 0x46, 0x20, 0x00, 0x88, 0xF7, 0x17, 0xF9, 0xAD, 0xE7, ++0x46, 0x23, 0xE9, 0x5C, 0x09, 0x02, 0x45, 0x3B, 0x19, 0x43, 0x05, 0x33, 0xFF, 0x22, 0x1A, 0x48, 0x7D, 0xF7, 0xDE, 0xFE, ++0x07, 0x00, 0x43, 0x46, 0x03, 0x80, 0x58, 0x23, 0xEA, 0x5C, 0x01, 0x32, 0x2B, 0x8F, 0x53, 0x43, 0x83, 0x70, 0x01, 0x99, ++0xC1, 0x70, 0x14, 0x4B, 0x1A, 0x68, 0x01, 0x32, 0x1A, 0x60, 0x00, 0x29, 0x04, 0xD1, 0x3C, 0x71, 0x38, 0x00, 0x7D, 0xF7, ++0xF3, 0xFE, 0x90, 0xE7, 0x0F, 0x49, 0x0B, 0x68, 0x01, 0x33, 0x0B, 0x60, 0x01, 0x99, 0x0E, 0x48, 0x7F, 0xF7, 0xC4, 0xFF, ++0xF1, 0xE7, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x80, 0xE7, 0x54, 0x27, 0x16, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xD0, 0x05, 0x60, 0x40, 0xD8, 0x05, 0x60, 0x40, 0xDC, 0x05, 0x60, 0x40, 0xD4, 0x05, 0x60, 0x40, ++0x35, 0x06, 0x00, 0x00, 0xC4, 0xE6, 0x10, 0x00, 0xC0, 0xE6, 0x10, 0x00, 0x54, 0xD1, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, ++0x15, 0x00, 0x10, 0x00, 0x7E, 0xF7, 0x74, 0xFA, 0x00, 0x28, 0x03, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x07, 0xD8, ++0x21, 0x88, 0x04, 0x39, 0x89, 0xB2, 0x20, 0x79, 0x88, 0xF7, 0xFA, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0x2E, 0x0A, 0x06, 0x23, ++0x2A, 0x00, 0x31, 0x00, 0x1B, 0x48, 0x7D, 0xF7, 0x89, 0xFE, 0x05, 0x00, 0x23, 0x88, 0x83, 0x80, 0xA3, 0x78, 0x83, 0x70, ++0x21, 0x79, 0x01, 0x31, 0x09, 0x02, 0x80, 0x36, 0x89, 0x19, 0x01, 0x80, 0xE1, 0x78, 0x0A, 0x03, 0x14, 0x4B, 0x1A, 0x42, ++0x06, 0xD0, 0xC0, 0x20, 0x13, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x80, 0x01, 0xB0, 0x47, 0x2B, 0x88, 0x0F, 0x4A, ++0x13, 0x40, 0xE2, 0x78, 0x12, 0x03, 0x13, 0x43, 0x2B, 0x80, 0xE3, 0x78, 0x00, 0x2B, 0x03, 0xD1, 0x28, 0x00, 0xCF, 0xF7, ++0xC5, 0xFC, 0xD1, 0xE7, 0xA2, 0x78, 0x20, 0x88, 0x09, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x7B, 0xF7, 0xE0, 0xFE, ++0xE1, 0x78, 0x00, 0x29, 0xF0, 0xD0, 0x06, 0x48, 0x7F, 0xF7, 0x5A, 0xFF, 0xEC, 0xE7, 0xC0, 0x46, 0x07, 0x11, 0x00, 0x00, ++0xFF, 0xCF, 0xFF, 0xFF, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0x6C, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0x89, 0xB0, ++0x04, 0x1E, 0x00, 0xD1, 0xAB, 0xE0, 0x46, 0x23, 0xC6, 0x5C, 0xB2, 0x00, 0x5A, 0x4B, 0xD5, 0x58, 0x00, 0x2D, 0x00, 0xD1, ++0xA9, 0xE0, 0x43, 0x68, 0x02, 0x3B, 0x1B, 0x01, 0x1B, 0x09, 0xC3, 0x62, 0x28, 0x30, 0xD2, 0xF7, 0xE9, 0xFD, 0x62, 0x68, ++0x61, 0x6B, 0x8A, 0x42, 0x13, 0xD0, 0x45, 0x23, 0xE3, 0x5C, 0x5B, 0x00, 0x5B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x9A, 0x42, ++0x0B, 0xD0, 0x4F, 0x4B, 0x9B, 0x7A, 0xA3, 0x75, 0x4A, 0x23, 0xE3, 0x5C, 0x03, 0x2B, 0x00, 0xD0, 0x8D, 0xE0, 0x47, 0x33, ++0x00, 0x22, 0xE2, 0x54, 0x89, 0xE0, 0x4A, 0x4B, 0x00, 0x93, 0x01, 0x92, 0xA3, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1E, 0x76, ++0x47, 0x23, 0xE0, 0x5C, 0x03, 0x01, 0x33, 0x43, 0x04, 0x93, 0x00, 0x23, 0x9C, 0x46, 0x03, 0x93, 0xA7, 0x7D, 0x6B, 0x46, ++0x1F, 0x75, 0x67, 0x46, 0x5F, 0x75, 0x9F, 0x75, 0x8A, 0x42, 0x00, 0xD1, 0x73, 0xE0, 0x10, 0x23, 0x6A, 0x46, 0xD3, 0x75, ++0x0C, 0x3B, 0x6A, 0x46, 0x93, 0x76, 0xD0, 0x76, 0x01, 0x23, 0x53, 0x76, 0x68, 0x46, 0xD3, 0xF7, 0x9B, 0xF8, 0x48, 0x22, ++0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x01, 0x21, 0x63, 0x68, 0x62, 0x6B, 0x93, 0x42, 0x35, 0xD0, 0x47, 0x23, 0xE3, 0x5C, ++0x33, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x5B, 0x01, 0x1A, 0x68, 0x32, 0x48, 0x02, 0x40, 0x09, 0x04, 0x0A, 0x43, 0x1A, 0x60, ++0x9F, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0xB6, 0xD1, 0x2B, 0x6D, 0x5F, 0x1C, 0x7F, 0x08, 0xAB, 0x6F, 0x9B, 0xB2, 0x62, 0x22, ++0x56, 0x43, 0x2B, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0xAB, 0x6F, 0x1B, 0x0C, 0x29, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0x80, 0x23, ++0x9B, 0x01, 0x9F, 0x42, 0x2B, 0xD3, 0x27, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0xF9, 0xF8, 0x00, 0x29, 0x19, 0xD0, 0x25, 0x4B, ++0x9C, 0x46, 0x66, 0x44, 0x22, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0x6A, 0xF8, 0x01, 0x30, 0x22, 0x4B, 0x03, 0x43, 0x9B, 0xB2, ++0x33, 0x80, 0x90, 0xE7, 0x20, 0x4B, 0x2A, 0x6D, 0x9A, 0x42, 0xC5, 0xD8, 0x4A, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0xC1, 0xD1, ++0x44, 0x33, 0xE1, 0x5C, 0x01, 0x31, 0xC9, 0xB2, 0xBC, 0xE7, 0x18, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0x15, 0x49, 0x38, 0x00, ++0xD4, 0xF7, 0x50, 0xF8, 0x15, 0x4B, 0x03, 0x43, 0x9B, 0xB2, 0x33, 0x80, 0x77, 0xE7, 0x01, 0x37, 0x7F, 0x08, 0xBF, 0xB2, ++0x10, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0x37, 0x80, 0x6F, 0xE7, 0x11, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0x09, 0xB0, 0xF0, 0xBD, 0x0F, 0x23, 0x6A, 0x46, 0xD3, 0x75, 0x0D, 0x3B, 0x8A, 0xE7, 0x38, 0x27, 0x16, 0x00, ++0x7C, 0x91, 0x0D, 0x00, 0x5D, 0x74, 0x0B, 0x00, 0x2F, 0x00, 0x03, 0x02, 0xFF, 0xFF, 0x00, 0xFF, 0xFA, 0x64, 0x61, 0x40, ++0xFC, 0x64, 0x61, 0x40, 0x71, 0x02, 0x00, 0x00, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0xE1, 0x04, 0x00, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x06, 0x00, 0x14, 0x4B, 0x1D, 0x68, 0x00, 0x2D, 0x05, 0xD1, 0x5D, 0x68, 0x00, 0x2D, ++0x02, 0xD1, 0x00, 0x24, 0x20, 0x00, 0xF8, 0xBD, 0xAB, 0x68, 0x2A, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x00, 0x0E, 0x49, ++0x18, 0x00, 0xD4, 0xF7, 0x09, 0xF8, 0x6C, 0x6B, 0x04, 0x19, 0x0B, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0x89, 0xF8, 0xB3, 0x68, ++0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x64, 0x18, 0xB1, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, 0xE3, 0xD0, ++0x20, 0x00, 0xFC, 0xF7, 0x63, 0xFF, 0x04, 0x00, 0xDE, 0xE7, 0xC0, 0x46, 0x54, 0x27, 0x16, 0x00, 0x71, 0x02, 0x00, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0xB0, 0xBD, 0x4B, 0x1C, 0x68, 0xA1, 0x46, ++0xBC, 0x4B, 0xA3, 0x82, 0x4C, 0x23, 0xE3, 0x5A, 0x5B, 0x00, 0x62, 0x6C, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, ++0xE3, 0x60, 0xA7, 0xF7, 0x5D, 0xF9, 0x04, 0x90, 0xB6, 0x4B, 0x1B, 0x68, 0x01, 0x93, 0xB6, 0x4B, 0x1B, 0x68, 0x02, 0x93, ++0xB5, 0x4B, 0x1B, 0x68, 0x07, 0x93, 0xB5, 0x4B, 0x1B, 0x68, 0x06, 0x93, 0x00, 0x25, 0x00, 0x20, 0x00, 0x27, 0x00, 0x23, ++0x03, 0x93, 0x00, 0x26, 0xB1, 0x4B, 0x98, 0x46, 0xA1, 0x23, 0x9A, 0x46, 0x02, 0x3B, 0x9B, 0x46, 0x0F, 0xE0, 0x01, 0x37, ++0xFF, 0xB2, 0xAF, 0x22, 0x9E, 0x5C, 0x86, 0x19, 0xF6, 0xB2, 0x48, 0x33, 0x18, 0x00, 0x80, 0xF7, 0x5F, 0xFA, 0x30, 0x18, ++0xC0, 0xB2, 0x01, 0x26, 0x01, 0x35, 0x07, 0x2D, 0x0E, 0xD0, 0xAB, 0x00, 0x42, 0x46, 0x9B, 0x58, 0x00, 0x2B, 0xF7, 0xD0, ++0x52, 0x46, 0x9A, 0x5C, 0x00, 0x2A, 0xF3, 0xD1, 0x5A, 0x46, 0x9A, 0x5C, 0x01, 0x2A, 0xE2, 0xD1, 0x03, 0x92, 0xE0, 0xE7, ++0x9F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x00, 0x23, 0x01, 0x32, 0xBA, 0x42, 0x5B, 0x41, 0x02, 0x33, 0x9C, 0x4A, 0x13, 0x70, ++0x83, 0x42, 0x08, 0xD8, 0x00, 0x22, 0x03, 0x28, 0x01, 0xD9, 0xC2, 0x1E, 0xD2, 0xB2, 0xC0, 0x1A, 0x10, 0x18, 0x96, 0x4B, ++0x18, 0x70, 0x50, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x95, 0x4B, 0x19, 0x00, 0x41, 0x31, 0xFF, 0x31, 0x00, 0x25, 0x04, 0xE0, ++0x01, 0x35, 0xED, 0xB2, 0x40, 0x33, 0x8B, 0x42, 0x07, 0xD0, 0x1A, 0x78, 0x09, 0x2A, 0xF9, 0xD1, 0x00, 0x2F, 0xF5, 0xD0, ++0x01, 0x37, 0xFF, 0xB2, 0xF2, 0xE7, 0xB0, 0xF7, 0x5F, 0xFA, 0x05, 0x90, 0x80, 0x46, 0x02, 0x9B, 0x01, 0x9A, 0x13, 0x43, ++0x5A, 0x1E, 0x93, 0x41, 0xDB, 0xB2, 0x9B, 0x46, 0x87, 0x4B, 0x1B, 0x78, 0x9A, 0x46, 0x00, 0x2B, 0x00, 0xD1, 0x79, 0xE0, ++0x85, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x28, 0xD9, 0x02, 0x2B, 0x64, 0xD0, 0x8C, 0xF7, 0xDC, 0xF8, 0x82, 0x46, 0x00, 0x28, ++0x00, 0xD1, 0x1B, 0xE2, 0x00, 0x23, 0x9A, 0x46, 0x7F, 0x4B, 0x23, 0x64, 0x02, 0x22, 0x62, 0x63, 0xFA, 0x22, 0x92, 0x01, ++0xA2, 0x62, 0x19, 0x00, 0x23, 0x61, 0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x77, 0xE0, 0xA3, 0x6A, 0x62, 0x6B, 0x98, 0x1A, ++0x40, 0x00, 0x04, 0x9B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x01, 0x2D, 0x00, 0xD1, 0x84, 0xE1, ++0x00, 0x22, 0x20, 0x00, 0xFC, 0xF7, 0x9A, 0xFF, 0x11, 0xE0, 0x71, 0x4B, 0x23, 0x64, 0x80, 0x22, 0x62, 0x63, 0xA2, 0x62, ++0x6C, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x16, 0x22, 0xA2, 0x75, 0x23, 0x61, 0x04, 0x98, 0x2C, 0x30, 0x00, 0x01, 0x00, 0x09, ++0x60, 0x60, 0x00, 0x23, 0x9A, 0x46, 0x69, 0x4E, 0x4C, 0x25, 0x69, 0x4F, 0x48, 0x46, 0xD1, 0xF7, 0x33, 0xFF, 0x00, 0x28, ++0x00, 0xD1, 0xB0, 0xE1, 0x31, 0x00, 0x20, 0x69, 0xD3, 0xF7, 0x16, 0xFF, 0x63, 0x68, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x01, ++0x00, 0x09, 0x60, 0x60, 0x63, 0x5B, 0x5B, 0x00, 0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x60, ++0xA3, 0x7D, 0x5D, 0x4A, 0xD2, 0x78, 0x9B, 0x18, 0xA3, 0x75, 0x59, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0xBE, 0x42, 0xDD, 0xD1, ++0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x56, 0x4B, 0x1B, 0x68, 0x5B, 0x00, ++0x23, 0x64, 0x02, 0x23, 0x63, 0x63, 0x4E, 0x33, 0xA3, 0x62, 0x4C, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0x49, 0x4B, 0x00, 0x22, ++0x1A, 0x70, 0x8B, 0xE7, 0xFD, 0xF7, 0x12, 0xF8, 0x00, 0x28, 0x04, 0xD1, 0x4D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x00, 0xD1, ++0x11, 0xE1, 0x43, 0x46, 0x00, 0x2B, 0x2C, 0xD0, 0x4A, 0x4B, 0x23, 0x64, 0x04, 0x23, 0x63, 0x63, 0x08, 0x33, 0xA3, 0x62, ++0x8C, 0xF7, 0x56, 0xF8, 0x00, 0x28, 0x00, 0xD0, 0x7C, 0xE7, 0x23, 0x6C, 0x23, 0x61, 0x20, 0x00, 0xFF, 0xF7, 0xAE, 0xFE, ++0x53, 0x46, 0x00, 0x2B, 0x00, 0xD1, 0x95, 0xE1, 0xC0, 0x30, 0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x18, 0x26, 0x4F, 0x46, ++0x65, 0x68, 0x00, 0x22, 0x21, 0x69, 0x38, 0x00, 0xFC, 0xF7, 0x20, 0xFF, 0x63, 0x68, 0xAB, 0x42, 0x00, 0xD1, 0x4A, 0xE1, ++0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x18, 0x36, 0x90, 0x2E, 0xEE, 0xD1, 0xB9, 0x46, 0x8B, 0xE7, 0x5B, 0x46, ++0x00, 0x2B, 0x21, 0xD0, 0x33, 0x4B, 0x1B, 0x68, 0x5B, 0x00, 0x23, 0x64, 0xE3, 0x6B, 0x63, 0x63, 0x23, 0x6B, 0xA3, 0x62, ++0x03, 0x9B, 0x00, 0x2B, 0x05, 0xD0, 0x2F, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0x46, 0x33, 0xA3, 0x62, 0xB2, 0x46, ++0x00, 0x2E, 0x00, 0xD1, 0xD4, 0xE0, 0x05, 0x9A, 0x92, 0x46, 0x01, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0xCE, 0xE0, 0x28, 0x4B, ++0x1B, 0x68, 0xA1, 0x6A, 0x8C, 0x46, 0x63, 0x44, 0xA3, 0x62, 0xC7, 0xE0, 0x15, 0x4B, 0x1B, 0x78, 0x5A, 0x00, 0x9B, 0x18, ++0x5B, 0x00, 0xDB, 0xB2, 0x01, 0x2F, 0x49, 0xD9, 0x21, 0x4A, 0x22, 0x64, 0x1A, 0x22, 0x62, 0x63, 0x2C, 0x32, 0xA2, 0x62, ++0x00, 0x2B, 0x03, 0xD0, 0x1E, 0x4B, 0x23, 0x64, 0x14, 0x23, 0x63, 0x63, 0x00, 0x2D, 0x03, 0xD0, 0x1C, 0x4B, 0x23, 0x64, ++0x10, 0x23, 0x63, 0x63, 0x63, 0x6B, 0xA3, 0x62, 0xDA, 0x46, 0xA9, 0xE0, 0xF8, 0xE6, 0x10, 0x00, 0x00, 0xA0, 0xFF, 0xFF, ++0x24, 0x27, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0x28, 0x27, 0x16, 0x00, 0x20, 0x27, 0x16, 0x00, 0x38, 0x27, 0x16, 0x00, ++0xB1, 0xE6, 0x10, 0x00, 0xD1, 0xE6, 0x10, 0x00, 0x70, 0xA6, 0x16, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, ++0xC4, 0x09, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, ++0x04, 0xE2, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x08, 0xE2, 0x10, 0x00, 0xDC, 0x82, 0x00, 0x00, ++0x14, 0xE2, 0x10, 0x00, 0xE8, 0x80, 0x00, 0x00, 0xF6, 0x54, 0x00, 0x00, 0xF2, 0x2B, 0x00, 0x00, 0x85, 0x4A, 0x5A, 0x43, ++0x03, 0x99, 0x00, 0x29, 0x33, 0xD0, 0x84, 0x49, 0x09, 0x68, 0x49, 0x00, 0x8A, 0x42, 0x29, 0xD8, 0x8A, 0x1A, 0x22, 0x64, ++0x28, 0x22, 0xD3, 0x1A, 0x63, 0x63, 0xE3, 0x6A, 0xA3, 0x62, 0x7F, 0x4B, 0x22, 0x6C, 0x9A, 0x42, 0x4B, 0xD9, 0xDA, 0x46, ++0x00, 0x2F, 0x5D, 0xD0, 0x07, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0xC4, 0xE0, 0x59, 0x68, 0x06, 0x9A, 0x00, 0x2A, 0x00, 0xD1, ++0xC4, 0xE0, 0x78, 0x4B, 0x99, 0x42, 0x00, 0xD1, 0xBE, 0xE0, 0x52, 0x68, 0x53, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x20, ++0x00, 0x05, 0x83, 0x42, 0x00, 0xD8, 0xBA, 0xE0, 0x8B, 0x1A, 0x1B, 0x01, 0x00, 0xD1, 0xB6, 0xE0, 0x11, 0x00, 0xB1, 0xE0, ++0x6F, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0xD5, 0xE7, 0x00, 0x2D, 0x0D, 0xD0, 0x6D, 0x4B, 0x23, 0x64, 0x10, 0x23, ++0x63, 0x63, 0xA3, 0x62, 0x01, 0x2D, 0x02, 0xD0, 0x01, 0x23, 0x9A, 0x46, 0xD0, 0xE7, 0x40, 0x33, 0x01, 0x22, 0xE2, 0x54, ++0xF8, 0xE7, 0x67, 0x49, 0x09, 0x68, 0x49, 0x00, 0x8A, 0x42, 0x0D, 0xD8, 0x8A, 0x1A, 0x22, 0x64, 0xA2, 0x6B, 0xD3, 0x1A, ++0x63, 0x63, 0xE3, 0x6A, 0xA3, 0x62, 0x5D, 0x4B, 0x22, 0x6C, 0x9A, 0x42, 0x09, 0xD9, 0x03, 0x9B, 0x9A, 0x46, 0xB9, 0xE7, ++0x5B, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0xF1, 0xE7, 0x00, 0x2D, 0x05, 0xD1, 0x58, 0x4B, 0x23, 0x64, 0x1A, 0x23, ++0x63, 0x63, 0xDA, 0x46, 0xAC, 0xE7, 0xDA, 0x46, 0xAA, 0xE7, 0x50, 0x4B, 0x23, 0x64, 0x02, 0x23, 0x63, 0x63, 0x43, 0x46, ++0x00, 0x2B, 0x0B, 0xD1, 0x30, 0x33, 0xA3, 0x62, 0x2F, 0x3B, 0x9A, 0x46, 0x8B, 0xF7, 0x42, 0xFF, 0x00, 0x28, 0x00, 0xD0, ++0x68, 0xE6, 0x21, 0x6C, 0x21, 0x61, 0x72, 0xE6, 0xC0, 0x23, 0xA3, 0x62, 0x05, 0x9B, 0x9A, 0x46, 0xDE, 0xE6, 0x00, 0x23, ++0x08, 0x93, 0x09, 0x93, 0x20, 0x1D, 0x23, 0x00, 0x08, 0xAA, 0x09, 0xA9, 0xFC, 0xF7, 0x72, 0xFD, 0x09, 0x9B, 0x00, 0x2B, ++0x04, 0xD0, 0x22, 0x69, 0x9A, 0x42, 0x00, 0xD9, 0x1A, 0x00, 0x22, 0x61, 0x00, 0x2F, 0x07, 0xD0, 0x08, 0x9B, 0x5B, 0x00, ++0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x63, 0x6B, 0x02, 0x2B, 0x1E, 0xD0, 0x53, 0x46, ++0x00, 0x2B, 0x04, 0xD1, 0x3A, 0x4B, 0x08, 0x9A, 0x53, 0x43, 0x23, 0x61, 0x23, 0x64, 0x03, 0x26, 0x4F, 0x46, 0x65, 0x68, ++0x00, 0x22, 0x21, 0x69, 0x38, 0x00, 0xFC, 0xF7, 0xEB, 0xFD, 0x63, 0x68, 0xAB, 0x42, 0x18, 0xD0, 0x08, 0x9B, 0x9C, 0x46, ++0x65, 0x44, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xEC, 0xD1, 0xB9, 0x46, 0x54, 0xE6, ++0x08, 0x9A, 0x53, 0x00, 0x9B, 0x18, 0x5B, 0x00, 0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, ++0xD5, 0xE7, 0xB9, 0x46, 0x47, 0xE6, 0xB9, 0x46, 0x45, 0xE6, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xA3, 0x7D, 0x10, 0x2B, ++0x00, 0xD9, 0x63, 0xE6, 0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x5F, 0xE6, 0x53, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x5B, 0xE6, ++0x11, 0x33, 0xA3, 0x75, 0x58, 0xE6, 0x06, 0x9B, 0x00, 0x2B, 0x91, 0xD0, 0x06, 0x9B, 0x59, 0x68, 0x15, 0x4B, 0x99, 0x42, ++0x8C, 0xD0, 0x63, 0x6B, 0x1A, 0x00, 0x28, 0x32, 0x52, 0x00, 0xA0, 0x6A, 0xC3, 0x1A, 0x5B, 0x00, 0x04, 0x98, 0x84, 0x46, ++0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x9A, 0x42, 0x00, 0xD2, 0x7A, 0xE7, 0x0C, 0x4B, ++0x23, 0x64, 0x77, 0xE7, 0x21, 0x6C, 0x21, 0x61, 0x43, 0x46, 0x00, 0x2B, 0x04, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x14, 0xFD, ++0x60, 0x60, 0x6B, 0xE6, 0x05, 0x9B, 0x9A, 0x46, 0xE5, 0xE5, 0xC0, 0x46, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xE2, 0x10, 0x00, ++0xE7, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xE8, 0x80, 0x00, 0x00, 0xF2, 0x2B, 0x00, 0x00, 0x04, 0xE2, 0x10, 0x00, ++0xA9, 0x03, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x1A, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x19, 0x4B, ++0x9B, 0x78, 0x83, 0x75, 0xFC, 0xF7, 0x06, 0xFE, 0x05, 0x00, 0x02, 0x21, 0x01, 0x20, 0xFC, 0xF7, 0xC3, 0xFE, 0x06, 0x00, ++0x00, 0x2D, 0x04, 0xD0, 0x11, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x4E, 0x23, 0xE3, 0x5C, 0x02, 0x2B, ++0x0E, 0xD0, 0xA6, 0xF7, 0x83, 0xFE, 0x60, 0x64, 0xFF, 0xF7, 0x0C, 0xFD, 0x00, 0x2E, 0x0E, 0xD0, 0x00, 0x2D, 0x04, 0xD0, ++0x08, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x70, 0xBD, 0x07, 0x4C, 0x20, 0x68, 0x7D, 0xF7, 0xB8, 0xFB, ++0x00, 0x23, 0x23, 0x60, 0xEE, 0xE7, 0x02, 0x21, 0x00, 0x20, 0xFC, 0xF7, 0x9D, 0xFE, 0xEB, 0xE7, 0xFC, 0x00, 0x60, 0x40, ++0x7C, 0x91, 0x0D, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x10, 0xBD, ++0x00, 0x21, 0xD1, 0xF7, 0x8F, 0xFE, 0xFF, 0xF7, 0xE5, 0xFC, 0xF8, 0xE7, 0x10, 0xB5, 0xA6, 0xF7, 0x55, 0xFE, 0x22, 0x4B, ++0x5A, 0x68, 0x92, 0x01, 0x1B, 0x68, 0xC0, 0x1A, 0x00, 0x01, 0x01, 0x09, 0x40, 0x00, 0x43, 0x1A, 0x9B, 0x00, 0x5B, 0x18, ++0x99, 0x00, 0x5B, 0x18, 0x9A, 0x42, 0x20, 0xD3, 0xD3, 0x1A, 0x1B, 0x4C, 0x9C, 0x42, 0xA4, 0x41, 0x64, 0x42, 0x1A, 0x4B, ++0x1A, 0x4A, 0x1A, 0x60, 0xD1, 0xF7, 0xC0, 0xFE, 0x00, 0x28, 0x0A, 0xD0, 0x00, 0x2C, 0x19, 0xD0, 0x17, 0x4B, 0x80, 0x22, ++0x12, 0x05, 0x1A, 0x60, 0x16, 0x48, 0x7F, 0xF7, 0x05, 0xFB, 0x10, 0xBD, 0x00, 0x24, 0x11, 0x4B, 0x1B, 0x68, 0x9B, 0x68, ++0x00, 0x2B, 0xF1, 0xD0, 0x12, 0x4A, 0xDB, 0x69, 0x93, 0x42, 0xEB, 0xD1, 0xEC, 0xE7, 0x0C, 0x4B, 0x0C, 0x4A, 0x1A, 0x60, ++0xD1, 0xF7, 0xA4, 0xFE, 0x00, 0x28, 0xED, 0xD0, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x0D, 0x4B, 0x00, 0x22, 0x1A, 0x70, ++0x0C, 0x4B, 0x18, 0x68, 0x00, 0x28, 0xE2, 0xD0, 0xFF, 0xF7, 0xAE, 0xFF, 0xDF, 0xE7, 0xC0, 0x46, 0x6C, 0xE6, 0x10, 0x00, ++0xFF, 0x70, 0x02, 0x00, 0x10, 0xE7, 0x10, 0x00, 0x64, 0x2A, 0x16, 0x00, 0x00, 0x41, 0x04, 0x40, 0x74, 0xD1, 0x10, 0x00, ++0xC9, 0x1F, 0x10, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0xF8, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x49, 0x4B, 0x1C, 0x68, 0xA4, 0x04, ++0xA4, 0x0E, 0x20, 0x00, 0x50, 0x43, 0x43, 0x01, 0x1B, 0x1A, 0x9B, 0x00, 0x1B, 0x18, 0x98, 0x00, 0x18, 0x18, 0x00, 0x02, ++0xD3, 0xF7, 0x5E, 0xFC, 0x81, 0x46, 0x03, 0x0A, 0x9B, 0x46, 0x29, 0x00, 0x80, 0x20, 0xC0, 0x00, 0xD3, 0xF7, 0x56, 0xFC, ++0x03, 0x00, 0x6B, 0x43, 0x9A, 0x46, 0xFF, 0x21, 0x4B, 0x46, 0x19, 0x40, 0x69, 0x43, 0x09, 0x0A, 0x48, 0x43, 0x53, 0x46, ++0x1B, 0x1A, 0x98, 0x46, 0x23, 0x01, 0x1B, 0x19, 0x9B, 0x00, 0x99, 0x46, 0xA1, 0x44, 0x53, 0x46, 0x00, 0x2B, 0x05, 0xD1, ++0x34, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x78, 0x01, 0xC0, 0x1B, 0x80, 0x00, 0xC7, 0x19, ++0xB8, 0x00, 0x38, 0x18, 0x29, 0x00, 0xD3, 0xF7, 0x33, 0xFC, 0x44, 0x43, 0x27, 0x00, 0x65, 0x09, 0x73, 0x01, 0x2C, 0x4A, ++0x9A, 0x18, 0x11, 0x68, 0x2B, 0x4A, 0x11, 0x60, 0x2B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x68, 0x2A, 0x4B, 0x1A, 0x60, ++0x2A, 0x4B, 0x5A, 0x46, 0x1A, 0x60, 0x51, 0x46, 0x48, 0x46, 0xD3, 0xF7, 0xA3, 0xFC, 0x09, 0x05, 0x43, 0x46, 0x19, 0x43, ++0x26, 0x4B, 0x19, 0x60, 0x26, 0x4B, 0x52, 0x46, 0x1A, 0x60, 0x26, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x25, 0x4B, 0x9E, 0x22, ++0xFF, 0x32, 0x99, 0x5C, 0x09, 0x02, 0x01, 0x3A, 0x9A, 0x5C, 0x0A, 0x43, 0x12, 0x04, 0x9C, 0x21, 0xFF, 0x31, 0x58, 0x5C, ++0x00, 0x02, 0x01, 0x39, 0x59, 0x5C, 0x01, 0x43, 0x0A, 0x43, 0x1E, 0x49, 0x0A, 0x60, 0xA0, 0x22, 0xFF, 0x32, 0x98, 0x5C, ++0x00, 0x02, 0x01, 0x3A, 0x9C, 0x5C, 0x04, 0x43, 0x24, 0x04, 0x20, 0x00, 0x28, 0x43, 0x01, 0x35, 0x6D, 0x01, 0xEC, 0x1B, ++0x24, 0x04, 0x04, 0x43, 0x16, 0x4A, 0x14, 0x60, 0x9A, 0x22, 0xFF, 0x32, 0x98, 0x5C, 0x00, 0x02, 0x01, 0x3A, 0x9B, 0x5C, ++0x03, 0x43, 0x36, 0x02, 0x1E, 0x43, 0x01, 0x20, 0x06, 0x43, 0x11, 0x4B, 0x1E, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, 0xC0, 0x46, 0x08, 0x04, 0x60, 0x40, 0x28, 0x19, 0x16, 0x00, 0xDC, 0x05, 0x60, 0x40, ++0x5C, 0x06, 0x60, 0x40, 0xD8, 0x05, 0x60, 0x40, 0x60, 0x06, 0x60, 0x40, 0x50, 0x06, 0x60, 0x40, 0x54, 0x06, 0x60, 0x40, ++0x58, 0x06, 0x60, 0x40, 0x4C, 0x06, 0x60, 0x40, 0x20, 0xA3, 0x16, 0x00, 0x44, 0x06, 0x60, 0x40, 0x48, 0x06, 0x60, 0x40, ++0x40, 0x06, 0x60, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8F, 0xB0, 0x80, 0x46, ++0x0E, 0x00, 0x15, 0x00, 0x03, 0x93, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x17, 0x00, 0x1F, 0x40, 0x1A, 0x42, 0x00, 0xD0, ++0xF6, 0xE2, 0x72, 0xB6, 0x00, 0x21, 0x5C, 0x20, 0x7D, 0xF7, 0xCE, 0xF9, 0x04, 0x1E, 0x00, 0xD1, 0x25, 0xE3, 0x00, 0x20, ++0x00, 0x2F, 0x00, 0xD0, 0xF1, 0xE2, 0x62, 0xB6, 0x00, 0x28, 0x00, 0xD1, 0xED, 0xE2, 0x0F, 0xB0, 0x3C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xDE, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x0C, 0x20, 0x00, 0x2F, 0xEF, 0xD1, 0xEA, 0xE7, 0x00, 0x23, 0x06, 0x93, 0xEC, 0xE2, 0x01, 0x23, 0x06, 0x93, 0xE9, 0xE2, ++0x00, 0x23, 0x5B, 0x00, 0xD6, 0x4A, 0xD3, 0x18, 0x5F, 0x78, 0xBA, 0x46, 0xBF, 0xE0, 0x2F, 0x7B, 0xD4, 0x4B, 0x19, 0x00, ++0x00, 0x22, 0x08, 0x78, 0xB8, 0x42, 0x00, 0xD1, 0xAD, 0xE0, 0x01, 0x32, 0x02, 0x31, 0x08, 0x2A, 0xF7, 0xD1, 0x02, 0x27, ++0x68, 0x7B, 0x00, 0x22, 0x19, 0x78, 0x81, 0x42, 0x00, 0xD1, 0xA7, 0xE0, 0x01, 0x32, 0x02, 0x33, 0x08, 0x2A, 0xF7, 0xD1, ++0x02, 0x23, 0x9A, 0x46, 0x09, 0x2F, 0x05, 0xD9, 0xC5, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x07, 0x97, 0xD3, 0x46, 0xC4, 0x4A, 0x7B, 0x00, 0xDF, 0x19, 0xD7, 0x19, 0x53, 0x46, 0x5B, 0x00, 0x53, 0x44, 0xD2, 0x18, ++0xBF, 0x78, 0x93, 0x78, 0xFF, 0x18, 0xFB, 0xB2, 0x1F, 0x00, 0x05, 0x93, 0x28, 0x7C, 0x19, 0x00, 0xD3, 0xF7, 0x48, 0xFB, ++0xC0, 0xB2, 0xBC, 0x4B, 0x63, 0x62, 0xBC, 0x4B, 0xE3, 0x61, 0xBC, 0x4B, 0x23, 0x62, 0x03, 0x23, 0x23, 0x76, 0xBB, 0x4B, ++0x9B, 0x7A, 0xA3, 0x75, 0xBA, 0x4A, 0x9F, 0x23, 0x9B, 0x00, 0xD2, 0x5C, 0x00, 0x23, 0x00, 0x2A, 0x02, 0xD1, 0x7B, 0x00, ++0x03, 0x33, 0xDB, 0xB2, 0xE3, 0x75, 0x00, 0x23, 0xA3, 0x82, 0x06, 0x33, 0x63, 0x76, 0x40, 0x33, 0x42, 0x46, 0xE2, 0x54, ++0x01, 0x33, 0xE6, 0x54, 0xEB, 0x88, 0x23, 0x87, 0x2B, 0x89, 0x63, 0x87, 0xAA, 0x7A, 0x3D, 0x23, 0xE2, 0x54, 0xEA, 0x7A, ++0x01, 0x33, 0xE2, 0x54, 0x2A, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0x6A, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0xAA, 0x7B, 0x01, 0x33, ++0xE2, 0x54, 0xEA, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0x6A, 0x7C, 0x01, 0x33, 0xE2, 0x54, 0x01, 0x33, 0xE0, 0x54, 0x9B, 0x4A, ++0xB0, 0x33, 0xD3, 0x58, 0x23, 0x63, 0xAA, 0x78, 0x4B, 0x23, 0xE2, 0x54, 0x2B, 0x7C, 0x05, 0x99, 0x8C, 0x46, 0x63, 0x44, ++0xEA, 0x7B, 0x9B, 0x1A, 0x5A, 0x42, 0x53, 0x41, 0x49, 0x22, 0xA3, 0x54, 0x45, 0x23, 0xE1, 0x54, 0x13, 0x33, 0x08, 0x9A, ++0xE2, 0x54, 0x01, 0x22, 0x31, 0x00, 0x01, 0x20, 0xA6, 0xF7, 0xF8, 0xF9, 0x03, 0x9B, 0x00, 0x2B, 0x00, 0xD0, 0x98, 0xE1, ++0x06, 0x99, 0x01, 0x31, 0x2A, 0x89, 0x4A, 0x43, 0xD3, 0xB2, 0x0C, 0x93, 0xEB, 0x88, 0x4B, 0x43, 0xDB, 0xB2, 0x0D, 0x93, ++0x2B, 0x79, 0x00, 0x22, 0x92, 0x46, 0x00, 0x2B, 0x02, 0xD0, 0xEA, 0x78, 0x04, 0x2A, 0x26, 0xD0, 0x68, 0x78, 0x03, 0x28, ++0x33, 0xD8, 0x2B, 0x78, 0x04, 0x2B, 0x30, 0xD8, 0x9B, 0x00, 0x88, 0x4A, 0xD3, 0x18, 0x1A, 0x5C, 0x0F, 0x23, 0x13, 0x40, ++0x0A, 0x93, 0x53, 0x11, 0x01, 0x21, 0x0B, 0x40, 0x03, 0x93, 0x12, 0x11, 0x11, 0x40, 0x0B, 0x91, 0x2C, 0xE0, 0x52, 0x00, ++0x79, 0x49, 0x8A, 0x18, 0x57, 0x78, 0x51, 0xE7, 0x52, 0x00, 0x77, 0x4B, 0x9A, 0x18, 0x53, 0x78, 0x9A, 0x46, 0x09, 0x2F, ++0x00, 0xD9, 0x57, 0xE7, 0x53, 0x46, 0x09, 0x2B, 0x00, 0xD9, 0x53, 0xE7, 0x58, 0xE7, 0x01, 0x2B, 0x0A, 0xD0, 0x02, 0x3B, ++0x5A, 0x42, 0x53, 0x41, 0x5B, 0x42, 0x76, 0x4A, 0x13, 0x40, 0x9A, 0x46, 0x75, 0x4B, 0x9C, 0x46, 0xE2, 0x44, 0xCB, 0xE7, ++0x74, 0x4B, 0x9A, 0x46, 0xC8, 0xE7, 0x29, 0x78, 0x66, 0x4B, 0xDB, 0x6E, 0x98, 0x46, 0x00, 0x23, 0x00, 0x22, 0xC0, 0x47, ++0x03, 0x9B, 0x0B, 0x93, 0x00, 0x23, 0x0A, 0x93, 0x2B, 0x79, 0x0E, 0x2B, 0x00, 0xD1, 0xBC, 0xE0, 0x00, 0xD9, 0xAC, 0xE0, ++0x00, 0x22, 0x06, 0x92, 0x08, 0x2B, 0x04, 0xD0, 0x01, 0x32, 0x06, 0x92, 0x0D, 0x2B, 0x00, 0xD0, 0xA8, 0xE0, 0xEB, 0x78, ++0x5A, 0x1E, 0x03, 0x2A, 0x00, 0xD9, 0xE3, 0xE0, 0xD3, 0xB2, 0x08, 0x93, 0x63, 0x4A, 0x13, 0x68, 0x63, 0x49, 0x19, 0x40, ++0x80, 0x23, 0x9B, 0x02, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x61, 0x49, 0x0B, 0x40, 0x80, 0x21, 0x49, 0x02, 0x8C, 0x46, ++0x0B, 0x43, 0x13, 0x60, 0x73, 0x01, 0x98, 0x46, 0x5D, 0x4A, 0x42, 0x44, 0x85, 0x23, 0x1B, 0x04, 0x51, 0x46, 0x0B, 0x43, ++0x13, 0x60, 0x5B, 0x4B, 0x43, 0x44, 0x9A, 0x46, 0x4B, 0x4A, 0x5B, 0x46, 0x59, 0x00, 0x59, 0x44, 0x53, 0x18, 0x5B, 0x78, ++0x1B, 0x01, 0xA8, 0x7A, 0x03, 0x43, 0xE8, 0x7A, 0x02, 0x38, 0x07, 0x00, 0x78, 0x42, 0x78, 0x41, 0xC0, 0x00, 0x03, 0x43, ++0x07, 0x9F, 0x78, 0x00, 0xBB, 0x46, 0x58, 0x44, 0x17, 0x18, 0x7F, 0x78, 0x7F, 0x01, 0x3B, 0x43, 0x67, 0x46, 0x3B, 0x43, ++0x57, 0x46, 0x3B, 0x60, 0x4C, 0x4B, 0x43, 0x44, 0x9A, 0x46, 0x2B, 0x89, 0x1B, 0x05, 0x9C, 0x46, 0xEB, 0x88, 0x1B, 0x01, ++0x67, 0x46, 0x3B, 0x43, 0x80, 0x5C, 0x03, 0x43, 0x88, 0x5C, 0x00, 0x04, 0x03, 0x43, 0x52, 0x46, 0x13, 0x60, 0x03, 0x9B, ++0xDB, 0x03, 0x0A, 0x9A, 0x12, 0x02, 0x13, 0x43, 0x0B, 0x9A, 0xD2, 0x01, 0x13, 0x43, 0x06, 0x9A, 0x12, 0x05, 0x13, 0x43, ++0x08, 0x9A, 0x12, 0x04, 0x13, 0x43, 0x3E, 0x4A, 0xB2, 0x18, 0x92, 0x00, 0x13, 0x60, 0xB3, 0x00, 0x3C, 0x4A, 0x9C, 0x50, ++0x4B, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x87, 0xE0, 0x32, 0x01, 0xB2, 0x18, 0xD3, 0x01, 0x9B, 0x1A, 0xF3, 0x18, ++0x37, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x9B, 0xB2, 0x36, 0x49, 0x41, 0x44, 0x0C, 0x98, 0xC2, 0x18, 0x12, 0x04, 0x13, 0x43, ++0x0B, 0x60, 0x87, 0x23, 0xDB, 0x00, 0x73, 0x43, 0x84, 0x46, 0x63, 0x44, 0x31, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x5B, 0x00, ++0x9B, 0xB2, 0x30, 0x49, 0x41, 0x44, 0x0D, 0x9A, 0x9A, 0x18, 0x92, 0xB2, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0x2D, 0x4B, ++0x43, 0x44, 0xE9, 0x7B, 0x80, 0x22, 0xD2, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x29, 0x89, 0x00, 0x29, 0x04, 0xD1, 0xEB, 0x88, ++0x01, 0x31, 0x00, 0x2B, 0x00, 0xD0, 0x19, 0x00, 0x00, 0x2E, 0x00, 0xD0, 0xDA, 0xE0, 0xEA, 0x7B, 0x89, 0xB2, 0x00, 0x20, ++0xFF, 0xF7, 0x72, 0xFD, 0xD4, 0xE0, 0x03, 0x22, 0x06, 0x92, 0x10, 0x2B, 0x00, 0xD1, 0x56, 0xE7, 0x05, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0x06, 0x93, 0x4D, 0xE7, 0x02, 0x23, 0x06, 0x93, 0x4A, 0xE7, ++0x28, 0x19, 0x16, 0x00, 0xE4, 0xDF, 0x10, 0x00, 0xD4, 0xDF, 0x10, 0x00, 0xE8, 0xDF, 0x10, 0x00, 0x69, 0xF5, 0x0A, 0x00, ++0x21, 0x61, 0x10, 0x00, 0x4D, 0xF3, 0x0A, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x08, 0xE0, 0x10, 0x00, ++0x00, 0xA0, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0xD0, 0x04, 0x60, 0x40, 0xFF, 0xFF, 0xFD, 0xFF, ++0xFF, 0xFF, 0xFE, 0xFF, 0xD4, 0x05, 0x60, 0x40, 0xE0, 0x05, 0x60, 0x40, 0xE4, 0x05, 0x60, 0x40, 0x8C, 0x01, 0x18, 0x10, ++0x54, 0x27, 0x16, 0x00, 0x5C, 0xAB, 0xFF, 0xFF, 0xD8, 0x05, 0x60, 0x40, 0xAE, 0x55, 0x00, 0x00, 0xDC, 0x05, 0x60, 0x40, ++0xD0, 0x05, 0x60, 0x40, 0x96, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0x08, 0x93, ++0x14, 0xE7, 0x42, 0x33, 0xE3, 0x5C, 0x5F, 0x1E, 0x20, 0x00, 0x50, 0x30, 0x7F, 0xF7, 0xF0, 0xFA, 0x49, 0x23, 0xE1, 0x5C, ++0xCB, 0x1C, 0xDB, 0xB2, 0x04, 0x31, 0xC9, 0xB2, 0x8B, 0x4A, 0x92, 0x46, 0x0D, 0x9A, 0x04, 0x32, 0xD2, 0xB2, 0x00, 0x92, ++0x84, 0x22, 0x50, 0x46, 0x82, 0x58, 0x93, 0x46, 0x0C, 0x9A, 0x30, 0x00, 0xD8, 0x47, 0x86, 0x4A, 0x42, 0x44, 0x00, 0x23, ++0x13, 0x60, 0x85, 0x4A, 0x42, 0x44, 0x13, 0x60, 0x19, 0x33, 0xFF, 0x33, 0x52, 0x46, 0xD0, 0x58, 0x31, 0x00, 0xD2, 0xF7, ++0x47, 0xFB, 0x81, 0x4A, 0x11, 0x68, 0x80, 0x23, 0x9B, 0x01, 0xB3, 0x40, 0x0B, 0x43, 0x13, 0x60, 0x7E, 0x4A, 0x42, 0x44, ++0xFF, 0x23, 0x3B, 0x40, 0x1F, 0x2B, 0x00, 0xD9, 0x1F, 0x23, 0x1B, 0x02, 0xE9, 0x7B, 0x0B, 0x43, 0x09, 0x99, 0x03, 0x39, ++0x48, 0x42, 0x41, 0x41, 0xC9, 0x03, 0x0B, 0x43, 0xC0, 0x21, 0xC9, 0x01, 0x0B, 0x43, 0x13, 0x60, 0x42, 0xE0, 0x75, 0x4B, ++0xF2, 0x18, 0x52, 0x01, 0x74, 0x49, 0x5B, 0x46, 0x58, 0x00, 0x58, 0x44, 0x0B, 0x18, 0x5B, 0x78, 0x1B, 0x01, 0xAF, 0x7A, ++0x1F, 0x43, 0xBC, 0x46, 0xEB, 0x7A, 0x02, 0x3B, 0x1F, 0x00, 0x7B, 0x42, 0x7B, 0x41, 0xDB, 0x00, 0x67, 0x46, 0x3B, 0x43, ++0x9A, 0x46, 0x07, 0x9F, 0x7B, 0x00, 0x98, 0x46, 0xBC, 0x46, 0xE0, 0x44, 0x8C, 0x46, 0xC4, 0x44, 0x63, 0x46, 0x5B, 0x78, ++0x5B, 0x01, 0x1F, 0x00, 0x53, 0x46, 0x1F, 0x43, 0x80, 0x23, 0x5B, 0x02, 0x3B, 0x43, 0x13, 0x60, 0x2B, 0x89, 0x1B, 0x05, ++0xED, 0x88, 0x2D, 0x01, 0x2B, 0x43, 0x45, 0x46, 0x6D, 0x5C, 0x2B, 0x43, 0x41, 0x5C, 0x09, 0x04, 0x0B, 0x43, 0x53, 0x60, ++0x31, 0x01, 0x71, 0x18, 0xCB, 0x01, 0x5B, 0x1A, 0xF3, 0x18, 0x5B, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x98, 0xB2, 0x11, 0x00, ++0x08, 0x39, 0x1B, 0x04, 0x03, 0x43, 0x0B, 0x60, 0x04, 0x3A, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x11, 0x00, ++0x19, 0x40, 0x88, 0x46, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x52, 0x4B, 0x05, 0x9A, 0x53, 0x43, 0x9B, 0xB2, 0x42, 0x22, ++0xA2, 0x5C, 0x52, 0x00, 0x44, 0x21, 0x61, 0x5C, 0x48, 0x1E, 0x81, 0x41, 0x00, 0x91, 0x31, 0x00, 0x0B, 0x20, 0xD3, 0xF7, ++0x41, 0xF8, 0x4B, 0x46, 0xDB, 0x07, 0x33, 0xD4, 0x4B, 0x46, 0x1F, 0x01, 0x3F, 0x09, 0x41, 0x23, 0xE5, 0x5C, 0x02, 0x33, ++0xE3, 0x5C, 0x9B, 0x06, 0x7F, 0x08, 0x5F, 0x40, 0x42, 0x23, 0xE3, 0x5C, 0x99, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x39, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x49, 0x46, 0x38, 0x00, 0xD3, 0xF7, 0x63, 0xF9, 0x69, 0x1A, ++0x00, 0x29, 0x21, 0xDD, 0x42, 0x23, 0xE3, 0x5C, 0xC9, 0x1A, 0x49, 0x00, 0x58, 0x00, 0x04, 0x9A, 0x94, 0x46, 0x60, 0x44, ++0x09, 0x18, 0x09, 0x01, 0x09, 0x09, 0x61, 0x63, 0x02, 0x2B, 0x02, 0xD9, 0x30, 0x00, 0x34, 0x4B, 0x98, 0x47, 0x00, 0x20, ++0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x28, 0xE5, 0x62, 0xB6, 0x26, 0xE5, 0x30, 0x4F, 0x4B, 0x46, 0x3B, 0x40, 0x1F, 0x00, ++0x04, 0x98, 0x01, 0x38, 0x00, 0x01, 0x03, 0x09, 0x04, 0x93, 0xC4, 0xE7, 0x42, 0x23, 0xE3, 0x5C, 0xC9, 0x18, 0xD9, 0xE7, ++0x00, 0x21, 0x5C, 0x20, 0x7C, 0xF7, 0xD8, 0xFE, 0x04, 0x1E, 0x00, 0xD1, 0x18, 0xE5, 0x43, 0x46, 0x9B, 0x00, 0x26, 0x4A, ++0x9F, 0x58, 0x6B, 0x78, 0x09, 0x93, 0x03, 0x2B, 0x00, 0xD1, 0x19, 0xE5, 0xAB, 0x78, 0x01, 0x2B, 0x00, 0xD1, 0x18, 0xE5, ++0x2A, 0x79, 0x08, 0x23, 0x93, 0x42, 0x9B, 0x41, 0x5B, 0x42, 0x06, 0x93, 0x06, 0x9B, 0x08, 0x93, 0xA6, 0xF7, 0x1C, 0xFA, ++0x04, 0x90, 0xBB, 0x6F, 0x81, 0x46, 0x99, 0x44, 0x5C, 0x22, 0x00, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0x67, 0xFE, 0xEB, 0x7A, ++0x00, 0x2B, 0x00, 0xD0, 0x0B, 0xE5, 0x2B, 0x7B, 0x00, 0x2B, 0x00, 0xD1, 0x00, 0xE5, 0x02, 0x22, 0x92, 0x46, 0x02, 0x27, ++0x02, 0x2B, 0x00, 0xD0, 0x22, 0xE5, 0x01, 0x3B, 0xF9, 0xE4, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0x0C, 0x20, 0xD5, 0xE4, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0xD8, 0x05, 0x60, 0x40, 0xDC, 0x05, 0x60, 0x40, ++0x0C, 0x04, 0x60, 0x40, 0xD0, 0x05, 0x60, 0x40, 0x2F, 0x00, 0x03, 0x02, 0xE8, 0xDF, 0x10, 0x00, 0x5C, 0xAB, 0xFF, 0xFF, ++0xE2, 0x04, 0x00, 0x00, 0x3D, 0xF4, 0x0A, 0x00, 0xFE, 0xFF, 0xFF, 0x0F, 0x38, 0x27, 0x16, 0x00, 0x00, 0x20, 0x70, 0x47, ++0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x5A, 0x4B, ++0x1B, 0x68, 0xDB, 0x05, 0x0B, 0xD5, 0x58, 0x49, 0x0B, 0x68, 0x5B, 0x00, 0x5B, 0x08, 0x80, 0x22, 0x12, 0x06, 0x13, 0x43, ++0x0B, 0x60, 0x0A, 0x00, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xDB, 0x53, 0x4B, 0x1B, 0x68, 0xDB, 0x05, 0x0B, 0xD5, 0x51, 0x49, ++0x0B, 0x68, 0x5B, 0x00, 0x5B, 0x08, 0x80, 0x22, 0x12, 0x06, 0x13, 0x43, 0x0B, 0x60, 0x0A, 0x00, 0x13, 0x68, 0x00, 0x2B, ++0xFC, 0xDB, 0x7A, 0xF7, 0x4F, 0xFF, 0x4B, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x09, 0xD0, 0x7C, 0xF7, 0xF5, 0xFE, 0x48, 0x4B, ++0x00, 0x22, 0x1A, 0x60, 0x47, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x46, 0x4B, 0x11, 0x22, 0x44, 0x21, ++0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x10, 0x3A, ++0x40, 0x49, 0x5A, 0x54, 0x40, 0x49, 0x5A, 0x54, 0x40, 0x4A, 0x00, 0x21, 0x99, 0x54, 0x40, 0x4B, 0x1B, 0x68, 0x01, 0x2B, ++0x47, 0xD9, 0x39, 0x4B, 0x1A, 0x68, 0x08, 0x21, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x01, 0x20, 0x82, 0x43, 0x1A, 0x60, ++0x1A, 0x68, 0x06, 0x39, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x38, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x12, 0x04, ++0x12, 0x0C, 0xB0, 0x21, 0x49, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x34, 0x4A, 0xA0, 0x23, 0x9B, 0x00, 0xD0, 0x54, 0x29, 0x4A, ++0x13, 0x68, 0x0F, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x30, 0x4A, 0x13, 0x68, 0x30, 0x49, 0x19, 0x40, 0xA0, 0x23, 0xDB, 0x03, ++0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0xFF, 0x21, 0x8B, 0x43, 0xAF, 0x39, 0x0B, 0x43, 0x13, 0x60, 0x2B, 0x4B, 0x2C, 0x4A, ++0x9A, 0x60, 0x2C, 0x4A, 0xDA, 0x60, 0x2C, 0x4A, 0x5A, 0x61, 0x2C, 0x4A, 0x9A, 0x61, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, ++0x00, 0x23, 0x2A, 0x4A, 0x13, 0x60, 0x2A, 0x4A, 0x13, 0x60, 0x2A, 0x4A, 0x13, 0x60, 0x0A, 0x22, 0x29, 0x49, 0x2A, 0x48, ++0xD3, 0xF7, 0x10, 0xFC, 0x10, 0xBD, 0x15, 0x4B, 0x1A, 0x68, 0x08, 0x31, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x07, 0x39, ++0x8A, 0x43, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x02, 0x20, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x13, 0x48, 0x10, 0x40, ++0x80, 0x22, 0x92, 0x01, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x12, 0x04, 0x12, 0x0C, 0xB0, 0x20, 0x40, 0x03, 0x02, 0x43, ++0x1A, 0x60, 0x0E, 0x4A, 0xA0, 0x23, 0x9B, 0x00, 0xD1, 0x54, 0x19, 0x4B, 0x19, 0x4A, 0x1A, 0x60, 0xAF, 0xE7, 0xC0, 0x46, ++0x00, 0x04, 0x60, 0x40, 0x00, 0x08, 0x60, 0x40, 0xF8, 0xE6, 0x10, 0x00, 0xFC, 0x00, 0x60, 0x40, 0xEC, 0xA4, 0x16, 0x00, ++0x1E, 0x03, 0x00, 0x00, 0x6F, 0x04, 0x00, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xFF, 0xDF, 0xFF, 0xFF, ++0x7C, 0x1E, 0x16, 0x00, 0x8C, 0x04, 0x60, 0x40, 0xFF, 0xFF, 0x00, 0xFF, 0x60, 0x92, 0x16, 0x00, 0x2D, 0x01, 0x10, 0x00, ++0x81, 0x01, 0x10, 0x00, 0x8D, 0x05, 0x10, 0x00, 0xB9, 0x00, 0x10, 0x00, 0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, ++0x54, 0xE6, 0x10, 0x00, 0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x30, 0x10, 0x62, 0x40, 0x15, 0x1C, 0x20, 0x00, ++0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x70, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x0B, 0xD5, ++0x6F, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x6C, 0x4A, 0x13, 0x68, 0x08, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x6B, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x6A, 0x4C, 0x23, 0x68, 0x6A, 0x4E, 0x33, 0x40, 0x23, 0x60, 0x6A, 0x4D, 0x2B, 0x68, 0x6A, 0x4F, ++0x3B, 0x40, 0x2B, 0x60, 0x83, 0xF7, 0xEE, 0xFA, 0x23, 0x68, 0x68, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x2B, 0x68, 0x33, 0x40, ++0x2B, 0x60, 0x23, 0x68, 0x1F, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x3B, 0x43, 0x23, 0x60, 0x23, 0x68, 0x1E, 0x40, 0x80, 0x23, ++0x9B, 0x00, 0x33, 0x43, 0x23, 0x60, 0x60, 0x4B, 0x99, 0x46, 0xFF, 0x23, 0x9B, 0x46, 0x22, 0x00, 0xC0, 0x3B, 0x98, 0x46, ++0x5D, 0x4B, 0x9C, 0x46, 0x40, 0x25, 0x80, 0x21, 0x09, 0x01, 0x5F, 0x46, 0x5E, 0x46, 0x04, 0x36, 0xF3, 0xB2, 0x9B, 0x46, ++0x4C, 0x46, 0x18, 0x00, 0x13, 0x68, 0x46, 0x46, 0xB3, 0x43, 0x03, 0x43, 0x13, 0x60, 0x63, 0x46, 0x26, 0x68, 0x1E, 0x60, ++0x13, 0x68, 0xAB, 0x43, 0x2B, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, ++0xFC, 0xD0, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0x34, 0xB8, 0x42, 0xE7, 0xD1, 0x10, 0x23, 0x9A, 0x46, 0xD1, 0x44, 0x5B, 0x46, ++0x0F, 0x2B, 0xDA, 0xD1, 0x42, 0x4C, 0x23, 0x68, 0x44, 0x4D, 0x2B, 0x40, 0x23, 0x60, 0x83, 0xF7, 0xAA, 0xFA, 0x23, 0x68, ++0x3F, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x3F, 0x4B, 0x1A, 0x68, 0x80, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x15, 0x40, ++0x80, 0x22, 0x52, 0x00, 0x2A, 0x43, 0x1A, 0x60, 0x3E, 0x4B, 0x9A, 0x46, 0xFF, 0x24, 0x38, 0x4A, 0x1F, 0x23, 0x99, 0x46, ++0x3C, 0x4B, 0x98, 0x46, 0x20, 0x26, 0x80, 0x21, 0xC9, 0x00, 0x04, 0xE0, 0x08, 0x23, 0x9C, 0x46, 0xE2, 0x44, 0x1F, 0x2C, ++0x1D, 0xD0, 0xA4, 0x46, 0x02, 0x34, 0xE4, 0xB2, 0x55, 0x46, 0x20, 0x00, 0x13, 0x68, 0x4F, 0x46, 0xBB, 0x43, 0x03, 0x43, ++0x13, 0x60, 0x43, 0x46, 0x2F, 0x68, 0x1F, 0x60, 0x13, 0x68, 0xB3, 0x43, 0x33, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, ++0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0x35, 0x60, 0x45, 0xE7, 0xD1, ++0xDC, 0xE7, 0x22, 0x4C, 0x23, 0x68, 0x80, 0x22, 0x93, 0x43, 0x23, 0x60, 0x83, 0xF7, 0x65, 0xFA, 0x23, 0x68, 0x1F, 0x4D, ++0x2B, 0x40, 0x23, 0x60, 0x23, 0x49, 0x0B, 0x68, 0x23, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x02, 0x13, 0x43, 0x0B, 0x60, ++0x83, 0xF7, 0x50, 0xFA, 0x15, 0x49, 0x0B, 0x68, 0x18, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x0B, 0x60, ++0x0B, 0x68, 0x12, 0x48, 0x03, 0x40, 0x80, 0x22, 0x92, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x23, 0x68, 0x03, 0x40, 0x1A, 0x43, ++0x22, 0x60, 0x23, 0x68, 0x1D, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x2B, 0x43, 0x23, 0x60, 0x14, 0x49, 0x0B, 0x68, 0x14, 0x4A, ++0x1A, 0x40, 0x80, 0x23, 0x5B, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, ++0xF8, 0xBD, 0xC0, 0x46, 0x18, 0x00, 0x58, 0x40, 0x40, 0x42, 0x04, 0x40, 0x58, 0x20, 0x62, 0x40, 0xFF, 0xFD, 0xFF, 0xFF, ++0x64, 0x20, 0x62, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xD8, 0x97, 0x16, 0x00, 0x5C, 0x20, 0x62, 0x40, ++0xD8, 0x98, 0x16, 0x00, 0x68, 0x20, 0x62, 0x40, 0x4C, 0x20, 0x62, 0x40, 0xFF, 0xFF, 0xFE, 0xFF, 0x30, 0x20, 0x62, 0x40, ++0xFF, 0xFF, 0xEF, 0xFF, 0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x6E, 0x4C, 0x23, 0x68, ++0x6E, 0x4E, 0x33, 0x40, 0x23, 0x60, 0x6E, 0x4D, 0x2B, 0x68, 0x6E, 0x4A, 0x13, 0x40, 0x2B, 0x60, 0x83, 0xF7, 0xF8, 0xF9, ++0x23, 0x68, 0x6C, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x2B, 0x68, 0x6B, 0x4A, 0x13, 0x40, 0x2B, 0x60, 0x23, 0x68, 0x6A, 0x4A, ++0x1A, 0x40, 0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x23, 0x60, 0x23, 0x68, 0x1E, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x33, 0x43, ++0x23, 0x60, 0x65, 0x4B, 0x9A, 0x46, 0x7F, 0x25, 0x22, 0x00, 0xFF, 0x23, 0x99, 0x46, 0x63, 0x4B, 0x98, 0x46, 0x5D, 0x4B, ++0x9C, 0x46, 0x80, 0x21, 0x89, 0x01, 0x2E, 0x00, 0x04, 0x35, 0xED, 0xB2, 0x54, 0x46, 0x28, 0x00, 0x13, 0x68, 0x4F, 0x46, ++0xBB, 0x43, 0x03, 0x43, 0x13, 0x60, 0x43, 0x46, 0x27, 0x68, 0x1F, 0x60, 0x13, 0x68, 0x67, 0x46, 0x3B, 0x40, 0x80, 0x27, ++0x7F, 0x00, 0x3B, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, ++0x01, 0x38, 0xC0, 0xB2, 0x04, 0x34, 0x86, 0x42, 0xE4, 0xD1, 0x10, 0x23, 0x9B, 0x46, 0xDA, 0x44, 0x8F, 0x2D, 0xDA, 0xD1, ++0x45, 0x4C, 0x23, 0x68, 0x4A, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x83, 0xF7, 0xB2, 0xF9, 0x23, 0x68, 0x42, 0x4A, 0x13, 0x40, ++0x23, 0x60, 0x42, 0x4B, 0x1A, 0x68, 0x80, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x40, 0x49, 0x11, 0x40, 0x80, 0x22, ++0x52, 0x00, 0x0A, 0x43, 0x1A, 0x60, 0x10, 0x20, 0x1A, 0x00, 0x1F, 0x27, 0x41, 0x4E, 0x42, 0x4D, 0x20, 0x24, 0x80, 0x21, ++0xC9, 0x00, 0x13, 0x68, 0xBB, 0x43, 0x03, 0x43, 0x13, 0x60, 0x83, 0x00, 0xF3, 0x58, 0x2B, 0x60, 0x13, 0x68, 0xA3, 0x43, ++0x23, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, 0x01, 0x30, ++0x20, 0x28, 0xEA, 0xD1, 0x2D, 0x4C, 0x23, 0x68, 0x80, 0x22, 0x93, 0x43, 0x23, 0x60, 0x83, 0xF7, 0x7E, 0xF9, 0x23, 0x68, ++0x2A, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x31, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x30, 0x4A, 0x13, 0x68, 0x02, 0x21, ++0x8B, 0x43, 0x13, 0x60, 0x2C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2D, 0x4A, 0x13, 0x68, 0x2D, 0x49, 0x0B, 0x40, 0x13, 0x60, ++0x2C, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x83, 0xF7, 0x5D, 0xF9, 0x1B, 0x49, 0x0B, 0x68, 0x1E, 0x4A, 0x13, 0x40, 0x80, 0x22, ++0x52, 0x01, 0x13, 0x43, 0x0B, 0x60, 0x0B, 0x68, 0x17, 0x48, 0x18, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x03, 0x43, 0x0B, 0x60, ++0x15, 0x4B, 0x19, 0x68, 0x17, 0x48, 0x08, 0x40, 0x80, 0x21, 0x89, 0x00, 0x01, 0x43, 0x19, 0x60, 0x19, 0x68, 0x12, 0x48, ++0x08, 0x40, 0x80, 0x21, 0x49, 0x00, 0x01, 0x43, 0x19, 0x60, 0x1C, 0x4B, 0x19, 0x68, 0x0A, 0x43, 0x1A, 0x60, 0x1B, 0x4A, ++0x13, 0x68, 0x1B, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x1A, 0x4B, 0x1A, 0x68, 0x1A, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x19, 0x68, ++0x80, 0x22, 0xD2, 0x05, 0x0A, 0x43, 0x1A, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, ++0x60, 0x40, 0x34, 0x40, 0xFF, 0xF7, 0xFF, 0xFF, 0x6C, 0x40, 0x34, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, ++0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xD8, 0x9B, 0x16, 0x00, 0x64, 0x40, 0x34, 0x40, 0x58, 0x99, 0x16, 0x00, ++0x70, 0x40, 0x34, 0x40, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xFF, 0xFB, ++0x08, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, 0xFF, 0xFF, 0xFB, 0xFF, 0x1C, 0x20, 0x34, 0x40, ++0xFF, 0xFF, 0xFF, 0xDF, 0x10, 0xB5, 0x07, 0x49, 0x0A, 0x69, 0x0F, 0x24, 0xA2, 0x43, 0x03, 0x20, 0x02, 0x43, 0x0A, 0x61, ++0xCB, 0x69, 0xA3, 0x43, 0x03, 0x43, 0xCB, 0x61, 0x02, 0x48, 0x7E, 0xF7, 0xA1, 0xFB, 0x10, 0xBD, 0x00, 0x30, 0x50, 0x40, ++0x94, 0xD1, 0x10, 0x00, 0x70, 0xB5, 0x1B, 0x4B, 0x9B, 0x69, 0xDB, 0x05, 0x1F, 0xD4, 0x0C, 0x38, 0xEF, 0xF3, 0x10, 0x83, ++0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x15, 0x4B, 0x1B, 0x7F, 0x01, 0x2B, 0x1C, 0xD0, ++0xCF, 0xF7, 0x62, 0xF8, 0x12, 0x4B, 0x1B, 0x7F, 0xFF, 0x2B, 0x1A, 0xD0, 0x02, 0x20, 0x7B, 0xF7, 0xCB, 0xF9, 0xFF, 0xF7, ++0xCF, 0xFF, 0x0F, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, 0x70, 0xBD, 0x0C, 0x4D, ++0xC4, 0x24, 0x64, 0x00, 0x00, 0x23, 0x2B, 0x51, 0xCE, 0xF7, 0xCC, 0xF8, 0x09, 0x4B, 0x2B, 0x51, 0xF4, 0xE7, 0x05, 0x4B, ++0xFF, 0x22, 0x1A, 0x77, 0xDE, 0xE7, 0x03, 0x4B, 0x01, 0x22, 0x1A, 0x77, 0xE0, 0xE7, 0xC0, 0x46, 0x3C, 0x95, 0x16, 0x00, ++0x24, 0x2A, 0x16, 0x00, 0x00, 0x41, 0x04, 0x40, 0x28, 0x19, 0x16, 0x00, 0xB9, 0x5A, 0x10, 0x00, 0x01, 0x28, 0x02, 0xD0, ++0x02, 0x28, 0x05, 0xD0, 0x70, 0x47, 0x05, 0x4B, 0x80, 0x22, 0x92, 0x04, 0x1A, 0x60, 0xF9, 0xE7, 0x02, 0x4B, 0x80, 0x22, ++0x52, 0x04, 0x1A, 0x60, 0xF4, 0xE7, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, 0x15, 0x4B, 0x16, 0x4A, 0x13, 0x60, 0x16, 0x4A, ++0x13, 0x60, 0x16, 0x4B, 0x1A, 0x68, 0x30, 0x21, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x90, 0x31, 0x8A, 0x43, 0x1A, 0x60, ++0x1A, 0x68, 0x12, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x11, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x10, 0x49, ++0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x0F, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x0E, 0x4A, 0xC4, 0x20, 0x80, 0x00, 0x13, 0x58, ++0x1B, 0x02, 0x1B, 0x0A, 0xC0, 0x21, 0x09, 0x06, 0x0B, 0x43, 0x13, 0x50, 0x80, 0x23, 0x1B, 0x03, 0x13, 0x60, 0x70, 0x47, ++0x00, 0x00, 0x7C, 0x07, 0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x18, 0x41, 0x04, 0x40, 0xFF, 0xFC, 0xFF, 0xFF, ++0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0x00, 0xE1, 0x00, 0xE0, 0x70, 0xB5, 0x82, 0xB0, ++0x04, 0x00, 0x64, 0x4B, 0x18, 0x68, 0x04, 0x28, 0x04, 0xD8, 0x49, 0xD8, 0x80, 0x00, 0x62, 0x4B, 0x1B, 0x58, 0x9F, 0x46, ++0xFF, 0x28, 0x43, 0xD1, 0x60, 0x4B, 0x80, 0x22, 0xD2, 0x00, 0x1A, 0x60, 0x5F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x5F, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x40, 0xD1, 0x5E, 0x4B, 0x19, 0x68, 0x41, 0x29, 0x57, 0xD0, 0x43, 0xD8, 0x01, 0x29, 0x49, 0xD0, ++0x21, 0x29, 0x00, 0xD0, 0x81, 0xE0, 0x5A, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x52, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x58, 0x4B, ++0x1B, 0x68, 0x01, 0x2B, 0x54, 0xD1, 0x50, 0xE0, 0x54, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x4F, 0x4B, 0x80, 0x22, 0xD2, 0x00, ++0x1A, 0x60, 0x4E, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x50, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x00, 0xD1, 0x7D, 0xE0, 0x47, 0x4B, ++0x1B, 0x68, 0x02, 0x2B, 0x40, 0xD1, 0x00, 0x25, 0x4C, 0x4B, 0x1D, 0x70, 0x01, 0x20, 0xFB, 0xF7, 0xCB, 0xFD, 0x4B, 0x4B, ++0x1D, 0x70, 0x3D, 0xE0, 0x46, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0xE2, 0xE7, 0x44, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xDE, 0xE7, ++0x42, 0x4B, 0x19, 0x78, 0x45, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA8, 0x47, 0xD6, 0xE7, 0x0F, 0x20, 0xFA, 0xF7, ++0x6F, 0xFD, 0xFF, 0x23, 0x03, 0x40, 0x3B, 0x4A, 0x13, 0x60, 0xB6, 0xE7, 0x61, 0x29, 0x10, 0xD0, 0xFF, 0x29, 0x3E, 0xD1, ++0x3D, 0x48, 0x7E, 0xF7, 0xA1, 0xFA, 0xCD, 0xE7, 0x36, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0x2F, 0x4B, 0x01, 0x3A, 0x1A, 0x60, ++0x34, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x0D, 0xD1, 0x4C, 0xE0, 0x31, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x29, 0x4B, 0x01, 0x32, ++0x1A, 0x60, 0x2F, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0xC1, 0xD1, 0x26, 0x4B, 0x03, 0x22, 0x1A, 0x60, 0x2D, 0x4B, 0x01, 0x22, ++0x1A, 0x70, 0x00, 0x20, 0xFB, 0xF7, 0x8A, 0xFD, 0x2D, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0xFF, 0xF7, 0x35, 0xFF, 0x2C, 0x4B, ++0x1B, 0x68, 0x24, 0x4A, 0x12, 0x78, 0x1D, 0x49, 0x09, 0x68, 0x2A, 0x48, 0x00, 0x68, 0x01, 0x90, 0x1E, 0x48, 0x00, 0x68, ++0x00, 0x90, 0x28, 0x48, 0x7E, 0xF7, 0x6E, 0xFA, 0x00, 0x2C, 0x27, 0xD0, 0x26, 0x4A, 0x13, 0x68, 0x20, 0x21, 0x0B, 0x43, ++0x13, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x24, 0x48, 0x7E, 0xF7, 0x62, 0xFA, 0x17, 0x4E, 0x31, 0x78, 0x10, 0x4D, 0x00, 0x23, ++0x00, 0x22, 0x28, 0x68, 0x81, 0xF7, 0xFE, 0xFF, 0x02, 0x23, 0x33, 0x70, 0x01, 0x3B, 0x2B, 0x60, 0x12, 0x4B, 0x1B, 0x68, ++0x01, 0x2B, 0xC9, 0xD1, 0x0F, 0x4B, 0x1B, 0x78, 0x03, 0xE0, 0x0E, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0xBF, 0xD0, 0x02, 0x2B, ++0x00, 0xD0, 0x7A, 0xE7, 0x04, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0xBB, 0xE7, 0x12, 0x4A, 0x13, 0x68, 0x20, 0x21, 0x8B, 0x43, ++0x13, 0x60, 0xD6, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0xE0, 0xD1, 0x10, 0x00, 0xE4, 0xE1, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, ++0xA4, 0xE5, 0x10, 0x00, 0xC0, 0xE5, 0x10, 0x00, 0xB4, 0xE5, 0x10, 0x00, 0x54, 0xE0, 0x10, 0x00, 0x60, 0xE6, 0x10, 0x00, ++0xDC, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x9C, 0xD1, 0x10, 0x00, 0xD1, 0xE6, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, ++0xBC, 0xE5, 0x10, 0x00, 0xC8, 0xD1, 0x10, 0x00, 0x84, 0x40, 0x04, 0x40, 0xB0, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x38, 0x4B, 0x38, 0x4A, 0x1A, 0x60, 0x38, 0x4B, 0x39, 0x4A, 0x1A, 0x60, 0x40, 0x23, 0x38, 0x4A, 0x13, 0x60, ++0x28, 0x22, 0x38, 0x49, 0x0A, 0x80, 0xC8, 0x21, 0x49, 0x00, 0x37, 0x48, 0x01, 0x80, 0x37, 0x48, 0x01, 0x80, 0x03, 0x20, ++0x36, 0x49, 0x08, 0x80, 0x02, 0x21, 0x36, 0x4C, 0x21, 0x80, 0x36, 0x4C, 0x20, 0x80, 0x36, 0x48, 0x01, 0x80, 0x36, 0x49, ++0x0A, 0x80, 0x80, 0x25, 0xAD, 0x00, 0x35, 0x49, 0x0D, 0x80, 0x14, 0x21, 0x34, 0x48, 0x01, 0x80, 0x34, 0x48, 0x15, 0x24, ++0x04, 0x80, 0x34, 0x48, 0x01, 0x80, 0x20, 0x26, 0x33, 0x49, 0x0E, 0x60, 0x0D, 0x3C, 0x33, 0x49, 0x0C, 0x60, 0x33, 0x49, ++0x01, 0x20, 0x40, 0x42, 0x08, 0x60, 0x00, 0x20, 0x31, 0x49, 0x08, 0x60, 0x31, 0x49, 0x88, 0x46, 0x31, 0x4F, 0x39, 0x60, ++0x31, 0x4F, 0x14, 0x21, 0xFF, 0x31, 0x39, 0x60, 0x30, 0x4F, 0x31, 0x49, 0x39, 0x60, 0x31, 0x4F, 0x07, 0x21, 0x39, 0x80, ++0x30, 0x4F, 0x3B, 0x80, 0x30, 0x4F, 0x41, 0x31, 0x39, 0x80, 0x30, 0x4F, 0x01, 0x39, 0x39, 0x80, 0x2F, 0x4F, 0x3E, 0x80, ++0x2F, 0x4E, 0x35, 0x80, 0x2F, 0x4D, 0xD2, 0x26, 0x76, 0x00, 0x2E, 0x80, 0x64, 0x25, 0x2E, 0x4E, 0x35, 0x80, 0x2E, 0x4E, ++0x35, 0x80, 0x2E, 0x4D, 0x2C, 0x80, 0x2E, 0x4C, 0x18, 0x25, 0x25, 0x80, 0x2D, 0x4C, 0x22, 0x80, 0x2D, 0x4A, 0x8C, 0x24, ++0x14, 0x80, 0x2D, 0x4A, 0x10, 0x80, 0x2D, 0x4A, 0x13, 0x60, 0x2D, 0x4B, 0x42, 0x46, 0x1A, 0x60, 0x2C, 0x4B, 0x32, 0x22, ++0x1A, 0x80, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xA0, 0x06, 0x16, 0x00, 0x00, 0xD7, 0x18, 0x00, 0x9C, 0x06, 0x16, 0x00, ++0x00, 0xF7, 0x18, 0x00, 0x78, 0x06, 0x16, 0x00, 0x5C, 0x06, 0x16, 0x00, 0x8E, 0x06, 0x16, 0x00, 0x8C, 0x06, 0x16, 0x00, ++0x5A, 0x06, 0x16, 0x00, 0x4A, 0x06, 0x16, 0x00, 0x56, 0x06, 0x16, 0x00, 0x54, 0x06, 0x16, 0x00, 0x5E, 0x06, 0x16, 0x00, ++0x58, 0x06, 0x16, 0x00, 0x64, 0x06, 0x16, 0x00, 0x66, 0x06, 0x16, 0x00, 0x62, 0x06, 0x16, 0x00, 0x68, 0x06, 0x16, 0x00, ++0x6C, 0x06, 0x16, 0x00, 0x44, 0x1E, 0x16, 0x00, 0x40, 0x1E, 0x16, 0x00, 0x20, 0x4E, 0x00, 0x00, 0x7C, 0x06, 0x16, 0x00, ++0x38, 0x1E, 0x16, 0x00, 0x3C, 0x1E, 0x16, 0x00, 0x02, 0x73, 0x06, 0x20, 0x4C, 0x06, 0x16, 0x00, 0x4E, 0x06, 0x16, 0x00, ++0x50, 0x06, 0x16, 0x00, 0x52, 0x06, 0x16, 0x00, 0x90, 0x06, 0x16, 0x00, 0x94, 0x06, 0x16, 0x00, 0x92, 0x06, 0x16, 0x00, ++0x8A, 0x06, 0x16, 0x00, 0x88, 0x06, 0x16, 0x00, 0x82, 0x06, 0x16, 0x00, 0x80, 0x06, 0x16, 0x00, 0x86, 0x06, 0x16, 0x00, ++0x84, 0x06, 0x16, 0x00, 0x48, 0x1E, 0x16, 0x00, 0x70, 0x06, 0x16, 0x00, 0x74, 0x06, 0x16, 0x00, 0x60, 0x06, 0x16, 0x00, ++0x0F, 0x4B, 0x02, 0x22, 0x9A, 0x77, 0x0F, 0x4A, 0x11, 0x6D, 0x80, 0x23, 0xDB, 0x01, 0x0B, 0x43, 0x13, 0x65, 0x0D, 0x4B, ++0x1B, 0x78, 0x02, 0x2B, 0x0B, 0xD0, 0x0A, 0x4B, 0x19, 0x6D, 0x80, 0x22, 0x12, 0x02, 0x0A, 0x43, 0x1A, 0x65, 0x19, 0x6D, ++0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, 0x1A, 0x65, 0x70, 0x47, 0x11, 0x6D, 0x80, 0x23, 0xDB, 0x02, 0x0B, 0x43, 0x13, 0x65, ++0xED, 0xE7, 0xC0, 0x46, 0x3C, 0x95, 0x16, 0x00, 0x00, 0x60, 0x50, 0x40, 0xB4, 0xE5, 0x10, 0x00, 0x01, 0x4B, 0x01, 0x22, ++0xDA, 0x77, 0x70, 0x47, 0x3C, 0x95, 0x16, 0x00, 0x10, 0xB5, 0x01, 0x20, 0x7F, 0xF7, 0x48, 0xF9, 0x10, 0xBD, 0x10, 0xB5, ++0x80, 0x20, 0x40, 0x00, 0x7B, 0xF7, 0x3A, 0xFC, 0x10, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x20, 0x4B, 0x1B, 0x68, ++0x01, 0x2B, 0x03, 0xD0, 0x1F, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x22, 0xD1, 0x00, 0x2C, 0x2C, 0xD0, 0x1D, 0x4A, 0x13, 0x68, ++0x08, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x00, 0x23, 0x1B, 0x4A, 0x13, 0x60, 0x1B, 0x4A, 0x13, 0x60, 0x1B, 0x4A, 0x13, 0x60, ++0x1B, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x22, 0xD9, 0x1A, 0x4A, 0x0F, 0x21, 0x11, 0x70, 0x03, 0x3B, 0x01, 0x2B, 0x05, 0xD8, ++0x18, 0x4A, 0x80, 0x23, 0x1B, 0x02, 0x91, 0x69, 0x0B, 0x43, 0x93, 0x61, 0x16, 0x49, 0x17, 0x48, 0x7E, 0xF7, 0xEC, 0xF8, ++0x10, 0xBD, 0xFF, 0xF7, 0xCF, 0xFE, 0xFF, 0xF7, 0x97, 0xFF, 0x11, 0x4B, 0x01, 0x22, 0xDA, 0x77, 0xFF, 0xF7, 0xBE, 0xFF, ++0xFF, 0xF7, 0xC1, 0xFF, 0xD0, 0xE7, 0x07, 0x4A, 0x13, 0x68, 0x08, 0x21, 0x8B, 0x43, 0x13, 0x60, 0xD1, 0xE7, 0x09, 0x4B, ++0x0B, 0x22, 0x1A, 0x70, 0xE4, 0xE7, 0xC0, 0x46, 0xA8, 0xE5, 0x10, 0x00, 0xAC, 0xE5, 0x10, 0x00, 0x84, 0x40, 0x04, 0x40, ++0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x54, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xE2, 0xE1, 0x10, 0x00, ++0x3C, 0x95, 0x16, 0x00, 0xF8, 0xE8, 0x10, 0x00, 0xF4, 0xD1, 0x10, 0x00, 0x02, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, ++0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0x12, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, ++0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0xD2, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, ++0x04, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, 0x03, 0x4B, 0x80, 0x22, 0x52, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, ++0xD0, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x13, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x07, 0xD0, ++0x11, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x16, 0xD9, 0x20, 0x00, 0x10, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0xAD, 0x33, 0xC3, 0x5C, ++0x00, 0x2B, 0xF7, 0xD0, 0x0D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, 0xFD, 0xF7, 0x54, 0xF8, ++0xEA, 0xE7, 0xFF, 0xF7, 0xD5, 0xFF, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xAE, 0xF7, 0x09, 0xFD, 0x00, 0x28, ++0xE4, 0xD1, 0xA7, 0x23, 0x04, 0x22, 0xE2, 0x54, 0xE0, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0xD5, 0x0D, 0x0B, 0x00, ++0xD8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x0B, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x03, 0xD0, 0x20, 0x00, 0xFE, 0xF7, ++0x11, 0xF9, 0x10, 0xBD, 0x08, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, 0xFD, 0xF7, 0x2C, 0xF8, ++0xF2, 0xE7, 0xFF, 0xF7, 0xAD, 0xFF, 0x03, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, ++0xD8, 0xE6, 0x10, 0x00, 0x04, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, 0x03, 0x4B, 0x80, 0x22, 0x92, 0x05, 0x1A, 0x60, ++0x70, 0x47, 0xC0, 0x46, 0xD2, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x80, 0x46, 0x00, 0x91, 0x82, 0x00, 0x93, 0x4B, 0xD5, 0x58, 0x9E, 0x23, 0xEC, 0x5C, ++0x64, 0x00, 0x0F, 0x33, 0xEB, 0x5C, 0xE4, 0x18, 0xE4, 0xB2, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0xAF, 0xE0, ++0xA8, 0x23, 0xEB, 0x5C, 0x77, 0x2B, 0x02, 0xD8, 0x01, 0x33, 0xA8, 0x22, 0xAB, 0x54, 0x43, 0x46, 0x1B, 0x02, 0x01, 0x27, ++0x3B, 0x43, 0x9B, 0x46, 0x87, 0x4B, 0x99, 0x46, 0x47, 0xE0, 0xC5, 0x20, 0x02, 0x23, 0xFF, 0x22, 0x59, 0x46, 0xC0, 0x00, ++0x7B, 0xF7, 0x0A, 0xFF, 0x06, 0x00, 0x3B, 0x88, 0x03, 0x80, 0x7B, 0xF7, 0x2F, 0xFF, 0x30, 0x88, 0x43, 0x1C, 0x9B, 0xB2, ++0x7F, 0x49, 0x5A, 0x5C, 0x41, 0x5C, 0x49, 0x10, 0x7E, 0x48, 0x7D, 0xF7, 0xFF, 0xFF, 0x00, 0x23, 0x3B, 0x80, 0x7D, 0x4B, ++0xE2, 0x18, 0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, 0x13, 0x80, 0x7B, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x7A, 0x4A, ++0x13, 0x40, 0x23, 0x80, 0xAF, 0x22, 0xAB, 0x5C, 0x01, 0x3B, 0xDB, 0xB2, 0xAB, 0x54, 0x35, 0x31, 0x6A, 0x5C, 0x50, 0x42, ++0x42, 0x41, 0x6A, 0x54, 0x5A, 0x1E, 0x93, 0x41, 0xA8, 0x22, 0xAB, 0x54, 0x8C, 0x23, 0xEB, 0x58, 0x00, 0x2B, 0x05, 0xD0, ++0x6A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x9E, 0x23, 0xEC, 0x5C, 0x64, 0x00, 0x0F, 0x33, ++0xEB, 0x5C, 0xE4, 0x18, 0xE4, 0xB2, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x58, 0xD0, 0xA3, 0x00, 0x1C, 0x19, 0x64, 0x00, ++0x66, 0x4B, 0xE3, 0x18, 0x1B, 0x88, 0xDB, 0x0B, 0x50, 0xD0, 0x65, 0x4B, 0xE7, 0x18, 0x3B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, ++0xA9, 0xD1, 0x63, 0x4B, 0xE7, 0x18, 0x3B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x38, 0xD0, 0xEC, 0x23, 0xEB, 0x58, 0x00, 0x2B, ++0xB7, 0xD1, 0x5A, 0x4B, 0xE3, 0x18, 0x1B, 0x88, 0xDB, 0x04, 0x9B, 0x0D, 0x0A, 0xD0, 0x3A, 0x88, 0x90, 0x21, 0x69, 0x58, ++0xD3, 0x18, 0x4A, 0x89, 0x92, 0x05, 0x92, 0x0D, 0x09, 0x89, 0x52, 0x18, 0x93, 0x42, 0x0D, 0xDA, 0x8C, 0x23, 0xEB, 0x58, ++0x00, 0x2B, 0x06, 0xD0, 0x4B, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, ++0x3B, 0x80, 0x98, 0xE7, 0x01, 0x23, 0xFF, 0x22, 0x59, 0x46, 0x4E, 0x48, 0x7B, 0xF7, 0x8C, 0xFE, 0x00, 0x23, 0x9A, 0x46, ++0x03, 0x70, 0x7B, 0xF7, 0xB1, 0xFE, 0x90, 0x26, 0xAB, 0x59, 0x18, 0x89, 0x85, 0xF7, 0xA2, 0xFF, 0x8C, 0x23, 0xEA, 0x58, ++0xAA, 0x51, 0x52, 0x46, 0xEA, 0x50, 0xE6, 0xE7, 0xEC, 0x23, 0xEB, 0x58, 0x00, 0x2B, 0x00, 0xD0, 0x7D, 0xE7, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x4B, 0x46, 0x9B, 0x6E, 0x98, 0x47, 0x76, 0xE7, 0x00, 0x99, 0x40, 0x46, 0xFD, 0xF7, 0x0C, 0xF8, ++0x3D, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x0A, 0xD0, 0xFC, 0xF7, 0x6E, 0xF9, 0x01, 0x28, 0x28, 0xD0, 0x03, 0xB0, 0x3C, 0xBC, ++0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xAD, 0x33, 0xEB, 0x5C, 0x00, 0x2B, 0x0E, 0xD1, 0x35, 0x4B, ++0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0x2B, 0xFF, 0xE7, 0xE7, 0xFF, 0xF7, 0x08, 0xFF, ++0x2F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0x2D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, ++0xFC, 0xF7, 0x1C, 0xFF, 0xD8, 0xE7, 0xFF, 0xF7, 0x9D, 0xFE, 0x28, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xFB, 0xF7, ++0x0F, 0xFA, 0x00, 0x28, 0xD2, 0xD0, 0xAE, 0xF7, 0xCD, 0xFB, 0x00, 0x28, 0xCE, 0xD1, 0x8A, 0xF7, 0x5D, 0xFA, 0x00, 0x28, ++0xCA, 0xD1, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0xC6, 0xD1, 0xA7, 0x33, 0xEB, 0x5C, 0x01, 0x2B, 0xC2, 0xD8, 0xD0, 0xF7, ++0xD9, 0xFA, 0x04, 0x1E, 0xBE, 0xD0, 0x1B, 0x4B, 0xC2, 0x69, 0x9A, 0x42, 0xBA, 0xD1, 0xA5, 0xF7, 0x4D, 0xFA, 0x63, 0x68, ++0x05, 0x3B, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xAA, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0xAF, 0xD0, 0x0B, 0x2B, 0xAD, 0xD9, ++0x13, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x9E, 0x23, 0xE8, 0x5C, 0xD1, 0xF7, 0x35, 0xFA, 0xAA, 0x23, 0x00, 0x22, 0xEA, 0x54, ++0xA2, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0xFC, 0xD1, 0x10, 0x00, ++0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0x07, 0xE0, 0xFF, 0xFF, 0xC8, 0x69, 0x61, 0x40, 0xD0, 0x69, 0x61, 0x40, ++0xCE, 0x69, 0x61, 0x40, 0x2B, 0x06, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0xC9, 0x1F, 0x10, 0x00, ++0x98, 0xE5, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x81, 0x46, ++0x82, 0x00, 0xBA, 0x4B, 0xD4, 0x58, 0x01, 0x94, 0xB0, 0x23, 0x15, 0x22, 0xE2, 0x54, 0x2A, 0x3B, 0xFA, 0x22, 0x52, 0x01, ++0xE2, 0x52, 0xB6, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x15, 0xD0, 0xB4, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x26, 0xD9, 0xB3, 0x4B, ++0x00, 0x22, 0x1A, 0x70, 0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x2C, 0xD0, 0x86, 0x23, 0xE3, 0x5A, 0x00, 0x2B, 0x6B, 0xD0, ++0x5B, 0x00, 0x22, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1F, 0x09, 0x29, 0xE0, 0xAB, 0x4B, 0xE3, 0x61, 0xAF, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x03, 0xD1, 0xA9, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD0, 0x01, 0x21, 0x02, 0x20, 0xFC, 0xF7, ++0x87, 0xFE, 0xDA, 0xE7, 0xFF, 0xF7, 0x64, 0xFE, 0xA3, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xA0, 0x4B, 0xE3, 0x61, ++0x9E, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xD2, 0xD0, 0x9F, 0x4B, 0x18, 0x68, 0x00, 0x28, 0xCE, 0xD0, 0xFB, 0xF7, 0x86, 0xFE, ++0xCB, 0xE7, 0xE4, 0x33, 0xE3, 0x58, 0x19, 0x68, 0xA3, 0x6F, 0xC9, 0x1A, 0x14, 0x39, 0x09, 0x01, 0x0F, 0x09, 0xA6, 0x23, ++0xE3, 0x5C, 0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x1A, 0x40, 0x96, 0x4B, 0x59, 0x78, 0x0F, 0x23, 0x0B, 0x40, 0x13, 0x43, ++0x94, 0x4A, 0x13, 0x43, 0xA3, 0x82, 0xE7, 0x60, 0xFB, 0xF7, 0x56, 0xF9, 0x02, 0x90, 0xFD, 0xF7, 0x2B, 0xF9, 0x03, 0x90, ++0xAE, 0xF7, 0x12, 0xFB, 0x06, 0x00, 0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x00, 0xD1, 0x38, 0xE2, 0x00, 0x25, 0x00, 0x28, ++0x2B, 0xD0, 0x8B, 0x4B, 0xA2, 0x6F, 0x1A, 0x60, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x5C, 0xE1, 0x88, 0x4A, ++0xD2, 0x88, 0x22, 0x61, 0x01, 0x2B, 0x00, 0xD0, 0xDA, 0xE1, 0xA7, 0x33, 0xE3, 0x5C, 0xA7, 0x21, 0x61, 0x5C, 0x5B, 0x18, ++0x1B, 0x11, 0x83, 0x49, 0x4B, 0x43, 0x93, 0x42, 0x00, 0xD2, 0x13, 0x00, 0x23, 0x61, 0xCD, 0xE1, 0xA6, 0x23, 0xE3, 0x5C, ++0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x1A, 0x40, 0x78, 0x4B, 0x59, 0x78, 0x0F, 0x23, 0x0B, 0x40, 0x13, 0x43, 0x7B, 0x4A, ++0x13, 0x43, 0xA3, 0x82, 0x01, 0x27, 0x7F, 0x42, 0xC2, 0xE7, 0xA5, 0xF7, 0x73, 0xF9, 0x60, 0x60, 0x03, 0x9B, 0x00, 0x2B, ++0x52, 0xD0, 0x76, 0x4B, 0x23, 0x61, 0x11, 0x23, 0xA3, 0x75, 0x8E, 0x33, 0xE3, 0x5C, 0x01, 0x2B, 0x47, 0xD0, 0x00, 0x25, ++0x48, 0x23, 0x9B, 0x46, 0xAF, 0x23, 0xE3, 0x5C, 0x98, 0x46, 0x20, 0x00, 0x48, 0x30, 0x7E, 0xF7, 0x83, 0xFA, 0x6E, 0x4A, ++0x12, 0x68, 0x92, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0xE0, 0xE0, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x01, 0xD1, 0x6A, 0x4B, ++0x23, 0x61, 0x40, 0x44, 0xC3, 0xB2, 0xA7, 0x22, 0xA2, 0x5C, 0x11, 0x00, 0x19, 0x43, 0x06, 0xD0, 0xD3, 0x18, 0x65, 0x4A, ++0x53, 0x43, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x23, 0x61, 0x23, 0x69, 0x62, 0x4A, 0x93, 0x42, 0x00, 0xD9, 0x13, 0x00, ++0x23, 0x61, 0x5A, 0x46, 0x21, 0x69, 0x20, 0x00, 0xFB, 0xF7, 0x16, 0xF8, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x04, 0xD1, ++0x63, 0x68, 0x03, 0x33, 0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0xA7, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x50, 0x4B, 0xA2, 0x6F, ++0x1A, 0x60, 0x20, 0x00, 0xCF, 0xF7, 0xB6, 0xFF, 0x00, 0x28, 0x00, 0xD0, 0xAE, 0xE1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, ++0x49, 0xE1, 0x37, 0x33, 0x9B, 0x46, 0xB7, 0xE7, 0x02, 0x9B, 0x00, 0x2B, 0x6B, 0xD0, 0x00, 0x23, 0x00, 0x25, 0x3E, 0x4A, ++0x90, 0x46, 0xA1, 0x22, 0x94, 0x46, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, 0x0B, 0xD0, 0x9A, 0x00, 0x41, 0x46, 0x52, 0x58, ++0x00, 0x2A, 0xF7, 0xD0, 0x61, 0x46, 0x52, 0x5C, 0x00, 0x2A, 0xF3, 0xD1, 0x01, 0x35, 0xED, 0xB2, 0xF0, 0xE7, 0x01, 0x2D, ++0x08, 0xD9, 0xA0, 0x33, 0x00, 0x22, 0xE2, 0x54, 0x41, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x28, 0x23, 0x9B, 0x46, 0x93, 0xE7, ++0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x23, 0xD1, 0xA7, 0x33, 0x00, 0x22, 0xE2, 0x54, 0x01, 0x33, 0xE2, 0x5C, 0x53, 0x42, ++0x5A, 0x41, 0x53, 0x42, 0x08, 0x22, 0x1A, 0x40, 0x68, 0x32, 0x38, 0x4B, 0x1B, 0x68, 0x98, 0x46, 0xC3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8B, 0x42, 0x04, 0xD9, 0x43, 0x46, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, ++0x00, 0x21, 0x8B, 0x46, 0x9A, 0x42, 0x01, 0xD3, 0xD3, 0x1A, 0x9B, 0x46, 0x2C, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x6B, 0xE7, ++0x01, 0x2B, 0x00, 0xD0, 0x65, 0xE1, 0xA7, 0x33, 0xE2, 0x5C, 0x53, 0x42, 0x5A, 0x41, 0x53, 0x42, 0x0C, 0x22, 0x1A, 0x40, ++0x44, 0x32, 0xE3, 0x6E, 0x98, 0x46, 0xC3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8B, 0x42, 0x04, 0xD9, ++0x43, 0x46, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0x00, 0x21, 0x8B, 0x46, 0x9A, 0x42, 0x01, 0xD3, 0xD3, 0x1A, ++0x9B, 0x46, 0x1B, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x48, 0xE7, 0x0A, 0x4B, 0x1B, 0x68, 0x00, 0x25, 0x01, 0x2B, 0x00, 0xD9, ++0x05, 0xE7, 0x13, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0x00, 0xD1, 0x37, 0xE1, 0x13, 0x4B, 0x1B, 0x68, 0x23, 0x61, ++0x00, 0x23, 0x9B, 0x46, 0x36, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x98, 0xE5, 0x10, 0x00, ++0xC1, 0x60, 0x10, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x40, 0x80, 0xFF, 0xFF, ++0xCC, 0xE6, 0x10, 0x00, 0x5C, 0xAB, 0x16, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, ++0xF4, 0xE1, 0x10, 0x00, 0x5C, 0x1C, 0x00, 0x00, 0x70, 0x71, 0x00, 0x00, 0x40, 0xE0, 0x10, 0x00, 0x2C, 0xE6, 0x10, 0x00, ++0x00, 0x23, 0x04, 0x93, 0x05, 0x93, 0x20, 0x1D, 0x23, 0x00, 0x05, 0xAA, 0x04, 0xA9, 0xFA, 0xF7, 0xAD, 0xFE, 0x04, 0x9B, ++0x00, 0x2B, 0x28, 0xD0, 0x22, 0x69, 0x9A, 0x42, 0x00, 0xD9, 0x1A, 0x00, 0x22, 0x61, 0x03, 0x26, 0x63, 0x68, 0x9A, 0x46, ++0x5A, 0x46, 0x21, 0x69, 0x01, 0x98, 0xFA, 0xF7, 0x3B, 0xFF, 0x63, 0x68, 0x53, 0x45, 0x08, 0xD0, 0x05, 0x9B, 0x53, 0x44, ++0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xEC, 0xD1, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x00, 0xD0, 0x0E, 0xE7, 0x63, 0x68, 0x03, 0x33, 0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0x23, 0x69, 0x70, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x23, 0x61, 0x03, 0xE7, 0x02, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0x9B, 0xE6, 0xEA, 0xE7, 0xA7, 0x23, 0xE3, 0x5C, ++0x00, 0x2B, 0x00, 0xD0, 0x7B, 0xE0, 0xA8, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x76, 0xE0, 0xB3, 0x33, 0xE3, 0x5C, ++0x00, 0x2B, 0x00, 0xD0, 0x71, 0xE0, 0x65, 0x4B, 0x23, 0x61, 0x73, 0x42, 0x73, 0x41, 0x5B, 0x42, 0x4B, 0x22, 0x93, 0x43, ++0x60, 0x33, 0x5B, 0x00, 0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x60, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xB0, 0x23, 0x09, 0x22, ++0xE2, 0x54, 0x20, 0x00, 0xCF, 0xF7, 0xA8, 0xFE, 0x00, 0x28, 0x00, 0xD0, 0xA0, 0xE0, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, ++0x00, 0x2E, 0x3A, 0xD0, 0xA5, 0xF7, 0x0E, 0xF8, 0x57, 0x4B, 0x18, 0x60, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x66, 0x60, 0x80, 0xE0, 0x00, 0x2E, 0x00, 0xD1, 0x86, 0xE0, 0x51, 0x4B, 0x23, 0x61, ++0x20, 0x00, 0xFD, 0xF7, 0x57, 0xFE, 0x60, 0x60, 0x18, 0x26, 0x65, 0x68, 0x00, 0x22, 0x21, 0x69, 0x01, 0x98, 0xFA, 0xF7, ++0xD1, 0xFE, 0x63, 0x68, 0xAB, 0x42, 0x06, 0xD0, 0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x18, 0x36, 0x60, 0x2E, ++0xEF, 0xD1, 0x20, 0x00, 0xCF, 0xF7, 0x76, 0xFE, 0x00, 0x28, 0x6F, 0xD1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xCF, 0xE7, ++0x39, 0x00, 0x14, 0x31, 0x09, 0x01, 0x09, 0x09, 0x48, 0x46, 0x40, 0x4B, 0x98, 0x47, 0xCB, 0xE7, 0xA0, 0x23, 0x00, 0x22, ++0xE2, 0x54, 0xA3, 0x7D, 0x10, 0x2B, 0x01, 0xD8, 0x11, 0x23, 0xA3, 0x75, 0x02, 0x9B, 0x00, 0x2B, 0xBC, 0xD0, 0x01, 0x2D, ++0xBA, 0xD1, 0x39, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0xB5, 0xD1, 0x37, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x9F, 0x23, ++0xE3, 0x5C, 0x01, 0x2B, 0xAE, 0xD1, 0x35, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0xAA, 0xE7, 0x34, 0x4B, 0xDB, 0x88, 0x23, 0x61, ++0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0xB0, 0xD0, 0x00, 0x2E, 0xB1, 0xD1, 0x30, 0x4B, 0x23, 0x61, 0xA7, 0x23, 0xE3, 0x5C, ++0x00, 0x2B, 0x03, 0xD1, 0xA8, 0x22, 0xA2, 0x5C, 0x00, 0x2A, 0x2E, 0xD0, 0xA8, 0x22, 0xA1, 0x5C, 0xCB, 0x18, 0x2A, 0x49, ++0x59, 0x43, 0x29, 0x4B, 0x9C, 0x46, 0x61, 0x44, 0x21, 0x61, 0x23, 0x4B, 0x1A, 0x68, 0x53, 0x6F, 0x58, 0x42, 0x43, 0x41, ++0x5B, 0x42, 0x1B, 0x48, 0x03, 0x40, 0x24, 0x48, 0x84, 0x46, 0x63, 0x44, 0x92, 0x68, 0x00, 0x2A, 0x02, 0xD0, 0x22, 0x4A, ++0x12, 0x68, 0x9B, 0x1A, 0x99, 0x42, 0x00, 0xD9, 0x19, 0x00, 0x21, 0x61, 0x66, 0x68, 0x28, 0x22, 0x20, 0x00, 0xFA, 0xF7, ++0x63, 0xFE, 0x01, 0x28, 0x00, 0xD1, 0x7C, 0xE7, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x04, 0xD1, 0x63, 0x68, 0x03, 0x33, ++0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0x20, 0x00, 0xCF, 0xF7, 0x06, 0xFE, 0x00, 0x28, 0x9B, 0xD0, 0xA1, 0x23, 0xE3, 0x5C, ++0x04, 0x2B, 0x8F, 0xD0, 0x08, 0x21, 0x48, 0x46, 0x11, 0x4B, 0x98, 0x47, 0x5E, 0xE7, 0x00, 0x25, 0xC7, 0xE5, 0x00, 0x25, ++0xC5, 0xE5, 0x00, 0x23, 0x9B, 0x46, 0xFF, 0xE5, 0xAA, 0xF8, 0xFF, 0xFF, 0x98, 0x12, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, ++0x34, 0xE6, 0x10, 0x00, 0x88, 0x13, 0x00, 0x00, 0xB9, 0x4C, 0x0B, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x40, 0xE0, 0x10, 0x00, ++0x44, 0xE0, 0x10, 0x00, 0x5C, 0xAB, 0x16, 0x00, 0x5C, 0x1C, 0x00, 0x00, 0x7C, 0x42, 0x00, 0x00, 0xE8, 0xE1, 0x10, 0x00, ++0x95, 0x0F, 0x0B, 0x00, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0xB7, 0x4B, 0xB8, 0x4A, ++0x13, 0x60, 0x80, 0x22, 0x52, 0x00, 0x9C, 0x5C, 0xFD, 0xF7, 0x5A, 0xFA, 0xB5, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, ++0x09, 0xD0, 0xB2, 0x4B, 0x1D, 0x68, 0x02, 0x23, 0xFF, 0x33, 0xEB, 0x5C, 0xA3, 0x42, 0x00, 0xD1, 0x42, 0xE1, 0xB0, 0x4F, ++0x84, 0xE0, 0xFA, 0xF7, 0xFD, 0xFD, 0xF2, 0xE7, 0xAE, 0x4A, 0x93, 0x42, 0x46, 0xD1, 0xAE, 0x4B, 0x4B, 0x60, 0x43, 0xE0, ++0xAD, 0x49, 0x8B, 0x42, 0x00, 0xD1, 0xE5, 0xE0, 0xAC, 0x49, 0x8B, 0x42, 0x16, 0xD1, 0xAC, 0x4B, 0x1A, 0x68, 0x00, 0x2A, ++0x38, 0xD0, 0x23, 0x01, 0xED, 0x18, 0xA9, 0x68, 0x8B, 0x00, 0x9B, 0x58, 0x00, 0x9A, 0x48, 0x46, 0x02, 0x43, 0xD2, 0xB2, ++0x00, 0x2A, 0x04, 0xD0, 0x00, 0x29, 0x00, 0xD0, 0xCC, 0xE0, 0xD8, 0x22, 0x1A, 0x86, 0x00, 0x22, 0x9A, 0x62, 0x25, 0xE0, ++0xA1, 0x49, 0x8B, 0x42, 0x22, 0xD1, 0x02, 0x2A, 0x20, 0xD1, 0x00, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0xA5, 0xFB, 0x1B, 0xE0, ++0x9D, 0x4B, 0x1D, 0x68, 0x00, 0x9B, 0x4A, 0x46, 0x13, 0x43, 0xDB, 0xB2, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x23, 0xAB, 0x62, ++0x34, 0x33, 0x01, 0x22, 0xEA, 0x54, 0xAE, 0xF7, 0x53, 0xF8, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0xC0, 0x22, 0x92, 0x01, ++0x13, 0x40, 0x80, 0x22, 0x52, 0x01, 0x94, 0x46, 0x63, 0x44, 0x2B, 0x86, 0x12, 0x23, 0x6B, 0x86, 0x86, 0x4B, 0x1B, 0x68, ++0x52, 0x46, 0x98, 0x18, 0x45, 0x68, 0x00, 0x2D, 0x00, 0xD1, 0xD1, 0xE0, 0x42, 0x46, 0x04, 0x3A, 0x51, 0x42, 0x4A, 0x41, ++0xD2, 0xB2, 0x31, 0x01, 0x5B, 0x18, 0x99, 0x68, 0x00, 0x68, 0xA8, 0x47, 0x7D, 0x4B, 0x1D, 0x68, 0x33, 0x01, 0xEB, 0x18, ++0x85, 0x4A, 0x5B, 0x68, 0x93, 0x42, 0x00, 0xD1, 0xC5, 0xE0, 0x33, 0x01, 0xEB, 0x18, 0x00, 0x22, 0x1A, 0x73, 0x03, 0x32, ++0xFF, 0x32, 0xAB, 0x5C, 0x01, 0x3B, 0xAB, 0x54, 0x02, 0x23, 0xFF, 0x33, 0xEA, 0x5C, 0x0F, 0x21, 0xA2, 0x42, 0x00, 0xD1, ++0xC5, 0xE0, 0x01, 0x34, 0x0C, 0x40, 0x23, 0x01, 0xEB, 0x18, 0x1B, 0x7B, 0x00, 0x2B, 0xF5, 0xD0, 0x80, 0x23, 0x5B, 0x00, ++0xEC, 0x54, 0xA2, 0x42, 0x00, 0xD1, 0xBB, 0xE0, 0x26, 0x00, 0x75, 0x4B, 0xE3, 0x18, 0x1B, 0x01, 0x1B, 0x88, 0x9B, 0x06, ++0x5B, 0x0F, 0x98, 0x46, 0x03, 0x3B, 0x02, 0x2B, 0x00, 0xD9, 0xAF, 0xE0, 0xFB, 0xF7, 0x70, 0xFD, 0x00, 0x90, 0x01, 0x90, ++0x3A, 0x68, 0x00, 0x23, 0x01, 0x21, 0x91, 0x42, 0x5B, 0x41, 0xDB, 0xB2, 0x99, 0x46, 0x23, 0x01, 0x9A, 0x46, 0xE9, 0x18, ++0x4B, 0x68, 0x69, 0x48, 0x83, 0x42, 0x62, 0xD0, 0x00, 0xD9, 0x63, 0xE7, 0x67, 0x4A, 0x93, 0x42, 0x88, 0xD0, 0x63, 0x4A, ++0x93, 0x42, 0x00, 0xD0, 0x56, 0xE7, 0x65, 0x4B, 0x1D, 0x68, 0x00, 0x23, 0xAB, 0x62, 0x51, 0x33, 0x01, 0x22, 0xEA, 0x54, ++0xAD, 0xF7, 0xDE, 0xFF, 0x00, 0x28, 0x05, 0xD0, 0x80, 0x23, 0x9B, 0x01, 0xAB, 0x85, 0x06, 0x23, 0xEB, 0x85, 0x8F, 0xE7, ++0x50, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x0B, 0xD0, 0x00, 0x9B, 0x4A, 0x46, 0x13, 0x43, 0xDB, 0xB2, 0x00, 0x2B, 0x1C, 0xD1, ++0x80, 0x23, 0x1B, 0x01, 0xAB, 0x85, 0x12, 0x23, 0xEB, 0x85, 0x7F, 0xE7, 0x55, 0x4B, 0xEB, 0x61, 0x01, 0x9B, 0x00, 0x2B, ++0x03, 0xD1, 0xFD, 0xF7, 0x13, 0xFA, 0x01, 0x28, 0x07, 0xD9, 0x00, 0x9A, 0xD3, 0x02, 0xAB, 0x85, 0x09, 0x23, 0x9B, 0x1A, ++0x5B, 0x00, 0xEB, 0x85, 0x6E, 0xE7, 0x80, 0x23, 0x5B, 0x00, 0xAB, 0x85, 0xEE, 0x3B, 0xEB, 0x85, 0x68, 0xE7, 0xFD, 0xF7, ++0x41, 0xF9, 0x01, 0x28, 0x00, 0xD8, 0x63, 0xE7, 0x80, 0x23, 0xDB, 0x01, 0xAB, 0x85, 0x08, 0x23, 0xEB, 0x85, 0x5D, 0xE7, ++0xC8, 0x22, 0x92, 0x00, 0x1A, 0x86, 0x30, 0xE7, 0x01, 0x2A, 0x00, 0xD9, 0x56, 0xE7, 0x01, 0x9B, 0x00, 0x2B, 0x00, 0xD1, ++0x52, 0xE7, 0x23, 0x01, 0xED, 0x18, 0xAB, 0x68, 0x9B, 0x00, 0x3E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x68, 0xC0, 0x22, ++0x12, 0x01, 0xDA, 0x66, 0x46, 0xE7, 0x02, 0x2A, 0x00, 0xD0, 0x43, 0xE7, 0x23, 0x01, 0xED, 0x18, 0x2B, 0x7A, 0x9B, 0x00, ++0x37, 0x4A, 0x9D, 0x58, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x03, 0xD1, 0x35, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x09, 0xD0, ++0xA0, 0x23, 0xEB, 0x5C, 0x02, 0x2B, 0x00, 0xD0, 0x30, 0xE7, 0x01, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0xB5, 0xFA, 0x2B, 0xE7, ++0xFF, 0xF7, 0x92, 0xFA, 0x00, 0x23, 0x2D, 0x4A, 0x13, 0x70, 0xEF, 0xE7, 0x2C, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x30, 0xE7, 0x24, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x00, 0xD1, 0x34, 0xE7, 0x11, 0x22, 0x9A, 0x75, ++0x31, 0xE7, 0xFB, 0xF7, 0x93, 0xFB, 0x11, 0xE0, 0x80, 0x20, 0x80, 0x00, 0x7A, 0xF7, 0xE2, 0xFD, 0x13, 0xE0, 0x80, 0x23, ++0x5B, 0x00, 0xEC, 0x54, 0x81, 0x23, 0x5B, 0x00, 0xEB, 0x5C, 0x00, 0x2B, 0x04, 0xD1, 0x05, 0x33, 0xFF, 0x33, 0xEB, 0x58, ++0x00, 0x2B, 0xEA, 0xD0, 0x07, 0x4B, 0x1A, 0x68, 0x81, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0x00, 0x2B, 0xE6, 0xD0, 0x02, 0xB0, ++0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, ++0xF4, 0xE1, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x31, 0xC3, 0x0A, 0x00, 0xE1, 0xA1, 0x10, 0x00, 0xE9, 0x8F, 0x0C, 0x00, ++0xCD, 0x05, 0x0D, 0x00, 0xF0, 0x29, 0x16, 0x00, 0x5D, 0x74, 0x0B, 0x00, 0x20, 0x27, 0x16, 0x00, 0xD9, 0xEA, 0x0A, 0x00, ++0x00, 0x10, 0x06, 0x04, 0x11, 0x6F, 0x0B, 0x00, 0x99, 0xCA, 0x0A, 0x00, 0x28, 0x27, 0x16, 0x00, 0x01, 0x00, 0x10, 0x00, ++0x84, 0x29, 0x16, 0x00, 0x38, 0x27, 0x16, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x04, 0x4B, ++0x1B, 0x7F, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0x02, 0x4B, 0x98, 0x47, 0xFB, 0xE7, 0xC0, 0x46, 0x24, 0x2A, 0x16, 0x00, ++0x69, 0x44, 0x0D, 0x00, 0x10, 0xB5, 0x05, 0x4B, 0x80, 0x22, 0xD2, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, ++0xAF, 0xF8, 0xFF, 0xF7, 0xE7, 0xFF, 0x10, 0xBD, 0x08, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x2D, 0x4B, 0x1B, 0x68, 0xC0, 0x22, ++0x92, 0x02, 0x13, 0x42, 0x16, 0xD1, 0x5A, 0x03, 0x1E, 0xD4, 0x1A, 0x03, 0x2D, 0xD4, 0xDA, 0x02, 0x34, 0xD4, 0x9A, 0x02, ++0x36, 0xD4, 0x5A, 0x02, 0x38, 0xD4, 0xDA, 0x01, 0x39, 0xD4, 0x9A, 0x01, 0x3E, 0xD4, 0x5B, 0x01, 0x0F, 0xD5, 0xFD, 0xF7, ++0x1B, 0xFF, 0x22, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0x08, 0xE0, 0x20, 0x4D, 0x91, 0x24, 0xE4, 0x00, 0x00, 0x23, ++0x2B, 0x51, 0x84, 0xF7, 0x7F, 0xFB, 0x1E, 0x4B, 0x2B, 0x51, 0x70, 0xBD, 0x1D, 0x4B, 0x1C, 0x78, 0xFE, 0xF7, 0x84, 0xFE, ++0x02, 0x2C, 0x04, 0xD0, 0x17, 0x4B, 0x80, 0x22, 0xD2, 0x02, 0x1A, 0x60, 0xF3, 0xE7, 0x19, 0x4B, 0x01, 0x22, 0x1A, 0x70, ++0x84, 0xF7, 0x32, 0xFB, 0xED, 0xE7, 0x12, 0x4B, 0x80, 0x22, 0x12, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, ++0x3F, 0xFD, 0xE4, 0xE7, 0x01, 0x20, 0x84, 0xF7, 0x3D, 0xFB, 0xE0, 0xE7, 0x02, 0x20, 0x84, 0xF7, 0x39, 0xFB, 0xDC, 0xE7, ++0xFF, 0xF7, 0xA6, 0xFF, 0xD9, 0xE7, 0xFA, 0xF7, 0xF1, 0xFD, 0x07, 0x4B, 0x80, 0x22, 0x52, 0x04, 0x1A, 0x60, 0xD2, 0xE7, ++0xFA, 0xF7, 0x9A, 0xFF, 0x03, 0x4B, 0x80, 0x22, 0x92, 0x04, 0x1A, 0x60, 0xCB, 0xE7, 0xC0, 0x46, 0x1C, 0x41, 0x04, 0x40, ++0x08, 0x41, 0x04, 0x40, 0x28, 0x19, 0x16, 0x00, 0x31, 0x6D, 0x10, 0x00, 0xE0, 0x1D, 0x16, 0x00, 0xE1, 0x1D, 0x16, 0x00, ++0x10, 0xB5, 0x04, 0x4B, 0x80, 0x22, 0x12, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, 0x0F, 0xFD, 0x10, 0xBD, ++0x08, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x09, 0x4B, 0xDB, 0x7F, 0x00, 0x2B, 0x08, 0xD0, 0x00, 0x28, 0x01, 0xD1, 0x00, 0x29, ++0x04, 0xD0, 0x01, 0x20, 0x80, 0xF7, 0xD6, 0xFF, 0x84, 0xF7, 0x00, 0xFD, 0x03, 0x49, 0x40, 0x22, 0x0B, 0x6B, 0x1A, 0x42, ++0xFC, 0xD0, 0x10, 0xBD, 0x3C, 0x95, 0x16, 0x00, 0x00, 0x60, 0x50, 0x40, 0x70, 0xB5, 0x82, 0xB0, 0x27, 0x4A, 0xD3, 0x69, ++0x0F, 0x24, 0xA3, 0x43, 0xD3, 0x61, 0x26, 0x4B, 0x99, 0x68, 0x80, 0x20, 0x01, 0x43, 0x99, 0x60, 0x59, 0x68, 0x01, 0x43, ++0x59, 0x60, 0x19, 0x68, 0x01, 0x43, 0x19, 0x60, 0x13, 0x69, 0xA3, 0x43, 0x13, 0x61, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, ++0xEF, 0xFC, 0x01, 0x9C, 0x00, 0x9B, 0x1E, 0x00, 0x7A, 0x36, 0x9C, 0x22, 0x92, 0x00, 0x96, 0x42, 0x19, 0xD9, 0xF8, 0x3B, ++0xFF, 0x3B, 0x1E, 0x00, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0x80, 0x25, 0x2D, 0x05, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, ++0xDB, 0xFC, 0x01, 0x9A, 0xA3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xAB, 0x42, 0xF5, 0xD9, 0x12, 0x1B, 0x12, 0x01, 0xF2, 0xD0, ++0x00, 0x9B, 0xB3, 0x42, 0xEF, 0xD3, 0x02, 0xB0, 0x70, 0xBD, 0xB3, 0x42, 0xE9, 0xD2, 0x80, 0x25, 0x2D, 0x05, 0x02, 0xE0, ++0x00, 0x9B, 0xB3, 0x42, 0xF5, 0xD2, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, 0xC1, 0xFC, 0x01, 0x9A, 0xA3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0xAB, 0x42, 0xF2, 0xD9, 0x12, 0x1B, 0x12, 0x01, 0xEF, 0xD0, 0xE7, 0xE7, 0xC0, 0x46, 0x00, 0x30, 0x50, 0x40, ++0x00, 0x40, 0x50, 0x40, 0x70, 0xB5, 0x10, 0x4B, 0x9A, 0x69, 0x10, 0x4B, 0x1A, 0x42, 0x0A, 0xD1, 0x0F, 0x4D, 0x10, 0x4C, ++0x29, 0x68, 0x00, 0x20, 0xFA, 0xF7, 0xD0, 0xFC, 0x7B, 0xF7, 0x96, 0xFD, 0x23, 0x68, 0x01, 0x2B, 0xF6, 0xD0, 0x0C, 0x4A, ++0x13, 0x68, 0x01, 0x33, 0x13, 0x60, 0x0B, 0x4B, 0x1B, 0x68, 0x03, 0x3B, 0x01, 0x2B, 0x00, 0xD9, 0x70, 0xBD, 0x03, 0x4A, ++0x80, 0x23, 0x1B, 0x02, 0x91, 0x69, 0x0B, 0x43, 0x93, 0x61, 0xF7, 0xE7, 0x3C, 0x95, 0x16, 0x00, 0x01, 0x20, 0x00, 0x00, ++0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x20, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x02, 0x38, 0x01, 0x28, ++0x11, 0xD8, 0x09, 0x4A, 0x80, 0x23, 0x5B, 0x00, 0x08, 0x21, 0xD1, 0x50, 0x07, 0x49, 0x8B, 0x68, 0x07, 0x4A, 0x1A, 0x40, ++0x80, 0x23, 0x9B, 0x02, 0x13, 0x43, 0x8B, 0x60, 0x22, 0x22, 0x0B, 0x6B, 0x13, 0x40, 0x02, 0x2B, 0xFB, 0xD1, 0x70, 0x47, ++0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, 0xFF, 0xFF, 0xFB, 0xFF, 0x70, 0xB5, 0xA6, 0xF7, 0x3D, 0xFF, 0x04, 0x1E, ++0x0D, 0xD1, 0x1A, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x09, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x17, 0xD4, 0x72, 0xB6, ++0x3E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x62, 0xB6, 0x20, 0x00, 0x70, 0xBD, 0x13, 0x4B, 0x1D, 0x68, 0x00, 0x21, ++0xCF, 0xF7, 0x7A, 0xFC, 0x2B, 0x6B, 0x5B, 0x00, 0x6A, 0x68, 0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x0E, 0x4A, 0x13, 0x60, ++0x0E, 0x4B, 0x98, 0x47, 0xEC, 0xE7, 0x3E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0xE9, 0xD1, 0x09, 0x4B, 0x1D, 0x68, 0x00, 0x21, ++0xCF, 0xF7, 0x66, 0xFC, 0x2B, 0x6B, 0x5B, 0x00, 0x6A, 0x68, 0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x04, 0x4A, 0x13, 0x60, ++0x04, 0x4B, 0x98, 0x47, 0xD9, 0xE7, 0xC0, 0x46, 0x28, 0x27, 0x16, 0x00, 0x24, 0x27, 0x16, 0x00, 0x18, 0x2C, 0x16, 0x00, ++0x15, 0xE6, 0x0A, 0x00, 0x10, 0xB5, 0xA5, 0xF7, 0xC7, 0xFA, 0x00, 0x28, 0x0F, 0xD1, 0x0B, 0x4B, 0x19, 0x68, 0x00, 0x29, ++0x0B, 0xD0, 0x0A, 0x4B, 0xCB, 0x61, 0x0A, 0x4B, 0x1C, 0x00, 0x41, 0x34, 0xFF, 0x34, 0x1A, 0x78, 0x09, 0x2A, 0x03, 0xD0, ++0x40, 0x33, 0xA3, 0x42, 0xF9, 0xD1, 0x10, 0xBD, 0x0B, 0x69, 0x05, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x0B, 0x61, 0xF8, 0xE7, ++0x18, 0x27, 0x16, 0x00, 0x51, 0x04, 0x10, 0x00, 0x70, 0xA6, 0x16, 0x00, 0x78, 0xEC, 0xFF, 0xFF, 0x10, 0xB5, 0x02, 0x00, ++0x0C, 0x00, 0x01, 0x23, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0xC2, 0xFF, 0x04, 0x70, 0xCC, 0xF7, 0x1F, 0xFE, 0x10, 0xBD, ++0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x02, 0x00, 0x0C, 0x00, 0x01, 0x23, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0xB4, 0xFF, ++0x04, 0x70, 0xCC, 0xF7, 0x11, 0xFE, 0x10, 0xBD, 0x02, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x06, 0x23, 0x13, 0x4A, 0x00, 0x21, ++0x13, 0x48, 0x7A, 0xF7, 0xA7, 0xFF, 0x13, 0x4A, 0x2D, 0x23, 0xD3, 0x5C, 0x1B, 0x09, 0x12, 0x4A, 0x12, 0x78, 0x02, 0x2A, ++0x0B, 0xD0, 0x01, 0x2A, 0x10, 0xD0, 0x0E, 0x4A, 0x2D, 0x23, 0xD3, 0x5C, 0x03, 0x71, 0x00, 0x23, 0x03, 0x70, 0xCC, 0xF7, ++0xF5, 0xFD, 0x00, 0x20, 0x10, 0xBD, 0x0B, 0x4A, 0xD2, 0x5C, 0x80, 0x23, 0x9B, 0x00, 0x13, 0x43, 0x43, 0x80, 0xEE, 0xE7, ++0x08, 0x4A, 0xD2, 0x5C, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x43, 0x80, 0xE7, 0xE7, 0xC0, 0x46, 0x2D, 0x0C, 0x00, 0x00, ++0x01, 0x11, 0x00, 0x00, 0x60, 0x92, 0x16, 0x00, 0xB4, 0xE5, 0x10, 0x00, 0x30, 0xE0, 0x10, 0x00, 0x28, 0xE0, 0x10, 0x00, ++0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x19, 0x78, 0x03, 0x4A, 0x2D, 0x23, 0xD1, 0x54, 0x00, 0x21, 0xFF, 0xF7, 0xB2, 0xFF, ++0x00, 0x20, 0x10, 0xBD, 0x60, 0x92, 0x16, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0xD1, 0xF7, 0x96, 0xFF, ++0x06, 0x00, 0x2C, 0x4B, 0x99, 0x6F, 0x00, 0x29, 0x15, 0xD0, 0xF8, 0x22, 0x20, 0x00, 0xD1, 0xF7, 0xBB, 0xFF, 0x00, 0x21, ++0x00, 0x28, 0x0A, 0xD1, 0x26, 0x4A, 0x30, 0x23, 0xD3, 0x5C, 0x01, 0x2B, 0x21, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0x86, 0xFF, ++0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x21, 0x4B, 0x98, 0x6F, 0x7B, 0xF7, 0xBF, 0xF8, 0xFF, 0x20, 0x06, 0x40, 0xF8, 0x2E, ++0x00, 0xD9, 0xF8, 0x26, 0x70, 0x1C, 0x00, 0x21, 0x7B, 0xF7, 0x12, 0xF8, 0x1A, 0x4B, 0x98, 0x67, 0x07, 0x21, 0x00, 0x28, ++0xE2, 0xD0, 0x32, 0x00, 0x21, 0x00, 0xD1, 0xF7, 0x2F, 0xFE, 0x16, 0x4B, 0x9B, 0x6F, 0x00, 0x22, 0x9A, 0x55, 0x00, 0x21, ++0xD8, 0xE7, 0x7F, 0x33, 0x5B, 0x00, 0x2F, 0x22, 0x00, 0x21, 0x12, 0x48, 0x7A, 0xF7, 0x2A, 0xFF, 0x06, 0x00, 0x01, 0xA9, ++0x0D, 0x70, 0x2D, 0x0A, 0x4D, 0x70, 0xF8, 0x23, 0x8B, 0x70, 0x03, 0x22, 0xD1, 0xF7, 0x18, 0xFE, 0xF0, 0x1C, 0xF8, 0x22, ++0x21, 0x00, 0xD1, 0xF7, 0x13, 0xFE, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x30, 0x00, 0x0C, 0x38, 0x08, 0x4B, 0x98, 0x47, ++0x08, 0x4B, 0x5B, 0x7F, 0x5B, 0xB2, 0x04, 0x2B, 0xBE, 0xDC, 0x01, 0x33, 0x05, 0x4A, 0x53, 0x77, 0xBA, 0xE7, 0xC0, 0x46, ++0x68, 0x9E, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, 0x68, 0xE6, 0x10, 0x00, 0xA5, 0x4B, 0x0D, 0x00, 0x24, 0x2A, 0x16, 0x00, ++0xF8, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x16, 0x00, 0x1F, 0x00, 0x02, 0x20, 0x79, 0xF7, 0x46, 0xFE, 0x6B, 0x1E, 0x1C, 0x70, ++0x63, 0x1E, 0x03, 0x2B, 0x22, 0xD8, 0x04, 0x2C, 0x10, 0xD0, 0x68, 0x1E, 0x16, 0x4B, 0x18, 0x61, 0x1E, 0x83, 0x5F, 0x61, ++0x1B, 0x7F, 0xFF, 0x2B, 0x25, 0xD1, 0x13, 0x4B, 0x00, 0x22, 0x1A, 0x77, 0x71, 0x1C, 0x1A, 0x68, 0x54, 0x68, 0x11, 0x4A, ++0xA0, 0x47, 0x1C, 0xE0, 0x2B, 0x78, 0x2F, 0x2B, 0xEB, 0xD1, 0x0F, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xE7, 0xD0, 0x19, 0x23, ++0x2B, 0x70, 0xE2, 0x33, 0x6B, 0x70, 0x0B, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xFD, 0x26, 0xDE, 0xE7, 0x09, 0x4D, 0x00, 0x23, ++0x00, 0x22, 0x01, 0x21, 0x20, 0x00, 0xEE, 0x6E, 0xB0, 0x47, 0xED, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x01, 0x21, 0x20, 0x00, ++0xA8, 0x47, 0xF8, 0xBD, 0x58, 0x1E, 0x16, 0x00, 0x19, 0x74, 0x08, 0x00, 0x68, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0xC0, 0xB5, 0x86, 0xB0, 0x04, 0x00, 0x0E, 0x00, 0x03, 0x92, 0xCE, 0xF7, ++0x93, 0xFE, 0x07, 0x00, 0xB8, 0x4B, 0x1D, 0x25, 0x5D, 0x57, 0x2B, 0x00, 0x80, 0x33, 0x00, 0xD1, 0x61, 0xE1, 0x01, 0x3D, ++0x6D, 0xB2, 0xB4, 0x4B, 0x5D, 0x77, 0x00, 0x28, 0x00, 0xD1, 0x18, 0xE1, 0x00, 0x2D, 0x00, 0xDA, 0x59, 0xE1, 0x80, 0x78, ++0x0F, 0x23, 0x18, 0x40, 0x08, 0x28, 0x5F, 0xD8, 0x83, 0x00, 0xAE, 0x4A, 0xD3, 0x58, 0x9F, 0x46, 0x05, 0x23, 0x99, 0x46, ++0x67, 0xE0, 0x06, 0x28, 0x1E, 0xD0, 0x01, 0x2E, 0x00, 0xD8, 0x3B, 0xE1, 0x03, 0x9A, 0x53, 0x78, 0x1B, 0x02, 0x12, 0x78, ++0x13, 0x43, 0x0B, 0x2B, 0x00, 0xD9, 0x22, 0xE1, 0xA5, 0x4A, 0xD2, 0x18, 0x12, 0x7E, 0x00, 0x2A, 0x00, 0xD1, 0x2D, 0xE1, ++0xA2, 0x04, 0x37, 0xD4, 0xA2, 0x4A, 0x94, 0x42, 0x34, 0xD0, 0x27, 0xD8, 0xA1, 0x4A, 0x94, 0x42, 0x30, 0xD0, 0xA1, 0x4A, ++0x94, 0x42, 0x00, 0xD0, 0x20, 0xE1, 0x2B, 0xE0, 0x05, 0x2E, 0x00, 0xD8, 0x1C, 0xE1, 0x9E, 0x4D, 0x00, 0x23, 0x99, 0x46, ++0x07, 0xE0, 0x01, 0x23, 0x9C, 0x46, 0xE1, 0x44, 0x07, 0x35, 0x4B, 0x46, 0x07, 0x2B, 0x00, 0xD1, 0x10, 0xE1, 0x2B, 0x78, ++0x00, 0x2B, 0xF4, 0xD0, 0x69, 0x1C, 0x06, 0x22, 0x03, 0x98, 0xD1, 0xF7, 0x2D, 0xFD, 0x00, 0x28, 0xED, 0xD1, 0x4B, 0x46, ++0x1B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x26, 0xE0, 0x90, 0x4A, 0x94, 0x42, 0x04, 0xD8, 0x90, 0x4A, ++0x94, 0x42, 0x00, 0xD8, 0xF8, 0xE0, 0x03, 0xE0, 0x8E, 0x4A, 0x94, 0x42, 0x00, 0xD0, 0xF3, 0xE0, 0x1B, 0x02, 0x04, 0x22, ++0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x14, 0xE0, 0x1B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x0E, 0xE0, ++0x87, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xA8, 0x47, 0xAF, 0xE0, 0x03, 0x23, 0x99, 0x46, 0x04, 0xE0, ++0x02, 0x23, 0x99, 0x46, 0x01, 0xE0, 0x00, 0x23, 0x99, 0x46, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x00, 0x22, ++0x1A, 0x80, 0x7E, 0x4B, 0x92, 0x46, 0x9C, 0x42, 0x59, 0xD0, 0x00, 0x2E, 0x00, 0xD1, 0xAD, 0xE0, 0x7D, 0x68, 0x00, 0x2D, ++0x00, 0xD1, 0x9C, 0xE0, 0xBB, 0x78, 0x5B, 0x06, 0x65, 0xD5, 0xB3, 0xB2, 0x0E, 0x22, 0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, ++0x03, 0x99, 0x00, 0x20, 0xA8, 0x47, 0xC5, 0xB2, 0x01, 0x2D, 0x66, 0xD0, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, ++0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x6F, 0x48, 0x7A, 0xF7, 0x00, 0xFE, 0x81, 0x46, 0x00, 0x2D, 0x07, 0xD0, 0x6A, 0x4B, ++0xDB, 0x6E, 0x9B, 0x46, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0x28, 0x00, 0xD8, 0x47, 0x4B, 0x46, 0x00, 0x2B, 0x59, 0xD0, ++0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x00, 0x2B, 0x0F, 0xD0, 0x7B, 0x68, 0x9B, 0x46, 0x00, 0x2B, ++0x0B, 0xD0, 0xBB, 0x78, 0x5B, 0x06, 0x51, 0xD5, 0xB3, 0xB2, 0x0E, 0x22, 0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, 0x03, 0x99, ++0x48, 0x46, 0xD8, 0x47, 0xC5, 0xB2, 0x00, 0x2D, 0x06, 0xD0, 0x58, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, ++0x28, 0x00, 0xB0, 0x47, 0x48, 0x46, 0x7A, 0xF7, 0xF9, 0xFD, 0x54, 0x4B, 0x9C, 0x42, 0x4A, 0xD1, 0x53, 0x46, 0x00, 0x2B, ++0x47, 0xD0, 0x50, 0x46, 0x7A, 0xF7, 0x3C, 0xFF, 0x43, 0xE0, 0x75, 0x1C, 0x01, 0x21, 0x28, 0x00, 0x7A, 0xF7, 0x92, 0xFE, ++0x82, 0x46, 0x03, 0x99, 0x0B, 0x78, 0x03, 0x70, 0x72, 0x1E, 0x42, 0x70, 0x01, 0x31, 0x02, 0x30, 0xD1, 0xF7, 0xAE, 0xFC, ++0xEE, 0xB2, 0x49, 0x48, 0x7C, 0xF7, 0xB6, 0xFE, 0x53, 0x46, 0x03, 0x93, 0x8F, 0xE7, 0xB3, 0xB2, 0x00, 0x95, 0x0E, 0x22, ++0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, 0x03, 0x99, 0x00, 0x20, 0x7D, 0xF7, 0x57, 0xF8, 0x05, 0x00, 0x96, 0xE7, 0x21, 0x00, ++0x40, 0x48, 0x7C, 0xF7, 0xA3, 0xFE, 0x00, 0x23, 0x12, 0x22, 0x21, 0x00, 0x38, 0x00, 0x3E, 0x4D, 0xA8, 0x47, 0xC8, 0xE7, ++0x07, 0x22, 0x21, 0x00, 0x38, 0x00, 0x3B, 0x4D, 0xA8, 0x47, 0xC2, 0xE7, 0xB3, 0xB2, 0x5A, 0x46, 0x00, 0x92, 0x0E, 0x22, ++0x62, 0x44, 0x03, 0x99, 0x48, 0x46, 0x7D, 0xF7, 0x3B, 0xF8, 0x05, 0x00, 0xAB, 0xE7, 0x00, 0x23, 0x01, 0x22, 0x21, 0x00, ++0x00, 0x20, 0x32, 0x4C, 0xA0, 0x47, 0x06, 0xB0, 0x1C, 0xBC, 0x91, 0x46, 0x9A, 0x46, 0xA3, 0x46, 0xF0, 0xBD, 0x0E, 0x23, ++0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x27, 0x48, 0x7A, 0xF7, 0x71, 0xFD, 0x81, 0x46, ++0x04, 0x25, 0x70, 0xE7, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x21, 0x48, ++0x7A, 0xF7, 0x64, 0xFD, 0x81, 0x46, 0x35, 0x00, 0x6B, 0xE7, 0x22, 0x4A, 0x13, 0x40, 0x1A, 0x00, 0x80, 0x3A, 0x92, 0xB2, ++0x06, 0x2A, 0x09, 0xD8, 0x80, 0x3B, 0xD9, 0x00, 0xC9, 0x1A, 0x0F, 0x4A, 0x52, 0x18, 0x24, 0x32, 0x12, 0x78, 0x02, 0x2A, ++0x00, 0xD1, 0x11, 0xE7, 0x21, 0x00, 0x1A, 0x48, 0x7C, 0xF7, 0x50, 0xFE, 0x03, 0x9B, 0x02, 0x22, 0x21, 0x00, 0x38, 0x00, ++0x14, 0x4C, 0xA0, 0x47, 0xC3, 0xE7, 0x00, 0x28, 0xBB, 0xD0, 0x00, 0x23, 0x07, 0x22, 0x21, 0x00, 0x38, 0x00, 0x10, 0x4C, ++0xA0, 0x47, 0xBA, 0xE7, 0x24, 0x2A, 0x16, 0x00, 0x2C, 0xD2, 0x10, 0x00, 0xCC, 0xAA, 0x16, 0x00, 0x2D, 0x0C, 0x00, 0x00, ++0x06, 0x04, 0x00, 0x00, 0x1D, 0x04, 0x00, 0x00, 0xF0, 0xAA, 0x16, 0x00, 0x7C, 0x0C, 0x00, 0x00, 0x7A, 0x0C, 0x00, 0x00, ++0x05, 0x14, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0x57, 0xFD, 0x00, 0x00, 0x05, 0x11, 0x00, 0x00, 0x14, 0xD2, 0x10, 0x00, ++0x20, 0xD2, 0x10, 0x00, 0x7D, 0x4A, 0x0D, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0x08, 0xD2, 0x10, 0x00, 0x10, 0xB5, 0x07, 0x20, ++0x7B, 0xF7, 0x10, 0xFA, 0x08, 0x4C, 0xA1, 0x7A, 0x20, 0x89, 0x62, 0x68, 0xFF, 0xF7, 0x54, 0xFE, 0x60, 0x68, 0x00, 0x28, ++0x03, 0xD0, 0x7A, 0xF7, 0x7F, 0xFE, 0x00, 0x22, 0x62, 0x60, 0x02, 0x48, 0x02, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0xC0, 0x46, ++0x58, 0x1E, 0x16, 0x00, 0xA5, 0x73, 0x08, 0x00, 0x30, 0xB5, 0x0C, 0x4C, 0x25, 0x68, 0x29, 0x60, 0x24, 0x68, 0x60, 0x60, ++0xA2, 0x60, 0xE3, 0x60, 0x09, 0x4B, 0x0A, 0x4A, 0x98, 0x50, 0x0A, 0x48, 0x1A, 0x58, 0x0A, 0x43, 0x1A, 0x50, 0x04, 0x30, ++0x1A, 0x58, 0x11, 0x43, 0x19, 0x50, 0x07, 0x49, 0x5A, 0x58, 0x01, 0x20, 0x02, 0x43, 0x5A, 0x50, 0x30, 0xBD, 0xC0, 0x46, ++0xFC, 0xE1, 0x10, 0x00, 0x00, 0x00, 0x07, 0x40, 0x10, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, ++0x70, 0xB5, 0x0D, 0x00, 0x1A, 0x4C, 0x30, 0x21, 0x61, 0x5C, 0x01, 0x29, 0x04, 0xD0, 0x29, 0x00, 0x18, 0x4C, 0xA0, 0x47, ++0x00, 0x20, 0x70, 0xBD, 0x14, 0x0A, 0x84, 0xF7, 0x99, 0xFD, 0x06, 0x1E, 0x1F, 0xD0, 0x6A, 0x88, 0xA9, 0x88, 0x14, 0x4B, ++0x9C, 0x46, 0x61, 0x44, 0x00, 0x89, 0x60, 0x44, 0xD1, 0xF7, 0xB8, 0xFB, 0x08, 0x23, 0x00, 0x22, 0x21, 0x00, 0x10, 0x48, ++0x7A, 0xF7, 0xBA, 0xFC, 0x33, 0x89, 0x43, 0x60, 0x2B, 0x88, 0x03, 0x80, 0x6B, 0x88, 0x43, 0x80, 0xCC, 0xF7, 0x12, 0xFB, ++0x20, 0x00, 0x80, 0x30, 0x01, 0x21, 0x0A, 0x4B, 0x98, 0x47, 0xA8, 0x88, 0x84, 0xF7, 0xCA, 0xFD, 0xD8, 0xE7, 0x08, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEF, 0xE7, 0x68, 0x9E, 0x16, 0x00, 0x49, 0x86, 0x0A, 0x00, ++0x00, 0x00, 0x61, 0x40, 0x06, 0x11, 0x00, 0x00, 0xC1, 0xDC, 0x09, 0x00, 0x28, 0x19, 0x16, 0x00, 0x42, 0x7A, 0x12, 0x02, ++0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x83, 0x7A, 0x8B, 0x70, 0x70, 0x47, 0xC2, 0x7A, 0x12, 0x02, 0x83, 0x7A, 0x13, 0x43, ++0x4B, 0x80, 0x42, 0x7A, 0x12, 0x02, 0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x70, 0x47, 0x83, 0x7A, 0x8B, 0x70, 0x42, 0x7A, ++0x12, 0x02, 0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x70, 0x47, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x00, 0x22, 0x02, 0x73, ++0x0B, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x03, 0x4A, 0x01, 0x21, 0xA0, 0x47, 0x04, 0x20, 0x7A, 0xF7, 0x91, 0xF8, 0x10, 0xBD, ++0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x01, 0x22, 0x02, 0x73, 0x08, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x03, 0x4A, ++0xA0, 0x47, 0x04, 0x20, 0x79, 0xF7, 0xAC, 0xFB, 0x10, 0xBD, 0xC0, 0x46, 0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, ++0x02, 0x22, 0x02, 0x73, 0x40, 0x68, 0x1A, 0x68, 0x14, 0x68, 0x01, 0x4A, 0xA0, 0x47, 0x10, 0xBD, 0x59, 0x78, 0x10, 0x00, ++0x10, 0xB5, 0x03, 0x00, 0x03, 0x22, 0x02, 0x73, 0x0B, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x02, 0x4A, 0x01, 0x21, 0xA0, 0x47, ++0x10, 0xBD, 0xC0, 0x46, 0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x01, 0x23, 0x10, 0x22, 0x00, 0x21, 0x0B, 0x48, ++0x7A, 0xF7, 0x38, 0xFC, 0x00, 0x23, 0x03, 0x70, 0xCC, 0xF7, 0x94, 0xFA, 0x20, 0x00, 0x08, 0x30, 0x02, 0x22, 0x00, 0x21, ++0x78, 0xF7, 0xB2, 0xFC, 0xE3, 0x7A, 0xA3, 0x72, 0x20, 0x00, 0xFF, 0xF7, 0xDB, 0xFF, 0x04, 0x20, 0x7A, 0xF7, 0x4A, 0xF8, ++0x10, 0xBD, 0xC0, 0x46, 0x03, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x06, 0x20, 0x7B, 0xF7, 0x1A, 0xF9, 0x16, 0x4C, 0x17, 0x49, ++0x20, 0x00, 0xFF, 0xF7, 0x83, 0xFF, 0xA4, 0x7A, 0x00, 0x2C, 0x09, 0xD1, 0x12, 0x4C, 0x20, 0x89, 0x00, 0x22, 0x00, 0x21, ++0xFF, 0xF7, 0x56, 0xFD, 0x20, 0x00, 0xFF, 0xF7, 0x93, 0xFF, 0x10, 0xBD, 0x0D, 0x4B, 0x18, 0x89, 0xCD, 0xF7, 0x9C, 0xFA, ++0x84, 0x42, 0x03, 0xD9, 0x0A, 0x48, 0xFF, 0xF7, 0xC3, 0xFF, 0xF4, 0xE7, 0x08, 0x4C, 0xA0, 0x7A, 0x01, 0x21, 0x7A, 0xF7, ++0xCF, 0xFC, 0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0x20, 0x00, 0xA1, 0x7A, 0xFF, 0xF7, 0x9C, 0xFF, 0xE7, 0xE7, 0x02, 0x48, ++0xFF, 0xF7, 0xB2, 0xFF, 0xE3, 0xE7, 0xC0, 0x46, 0x58, 0x1E, 0x16, 0x00, 0x60, 0x1E, 0x16, 0x00, 0x10, 0xB5, 0x82, 0xB0, ++0x04, 0x00, 0x0E, 0x4B, 0x01, 0x93, 0x01, 0x00, 0x08, 0x31, 0x04, 0x22, 0x01, 0xA8, 0xD1, 0xF7, 0xB5, 0xFA, 0x00, 0x28, ++0x0B, 0xD0, 0x04, 0x20, 0x79, 0xF7, 0x2A, 0xFB, 0x63, 0x7A, 0x23, 0x72, 0xA3, 0x7A, 0x63, 0x72, 0xE3, 0x7A, 0xA3, 0x72, ++0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0x22, 0x00, 0x21, 0x03, 0x48, 0xCD, 0xF7, 0x6C, 0xFA, 0x01, 0x20, 0xF6, 0xE7, ++0x01, 0x03, 0x0C, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x00, 0x29, 0x0B, 0xD0, 0x01, 0x29, 0x02, 0xD0, ++0x03, 0x7B, 0x00, 0x2B, 0x03, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x7C, 0xFF, 0x10, 0xBD, 0xFF, 0xF7, 0x3F, 0xFF, 0xFB, 0xE7, ++0x03, 0x7B, 0x02, 0x2B, 0x44, 0xD0, 0x0F, 0xD8, 0x00, 0x2B, 0x17, 0xD0, 0x40, 0x7B, 0x02, 0x28, 0x25, 0xD0, 0x03, 0x28, ++0x27, 0xD0, 0x01, 0x28, 0x1D, 0xD0, 0xA1, 0x7B, 0x34, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA0, 0x47, 0xE7, 0xE7, ++0x03, 0x2B, 0x59, 0xD1, 0xFF, 0xF7, 0xB4, 0xFF, 0x00, 0x28, 0x51, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x21, 0xFF, 0xDD, 0xE7, ++0xC3, 0x7A, 0x43, 0x73, 0x5A, 0x1E, 0x02, 0x2A, 0x04, 0xD8, 0x2B, 0x4A, 0xD1, 0x5C, 0xFF, 0xF7, 0x27, 0xFF, 0xD3, 0xE7, ++0xFF, 0xF7, 0x4E, 0xFF, 0xD0, 0xE7, 0x05, 0x30, 0x7B, 0xF7, 0x5E, 0xF8, 0xCC, 0xE7, 0x08, 0x20, 0x7B, 0xF7, 0x5A, 0xF8, ++0xC8, 0xE7, 0x21, 0x00, 0x08, 0x31, 0x20, 0x00, 0xFF, 0xF7, 0xFD, 0xFE, 0xA1, 0x7A, 0x20, 0x89, 0xCD, 0xF7, 0x2E, 0xFC, ++0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0xA1, 0x7A, 0x20, 0x00, 0xFF, 0xF7, 0x1B, 0xFF, 0xB7, 0xE7, 0x20, 0x00, 0xFF, 0xF7, ++0x31, 0xFF, 0xB3, 0xE7, 0x40, 0x7B, 0x02, 0x28, 0x0E, 0xD0, 0x03, 0x28, 0x15, 0xD0, 0x01, 0x28, 0x06, 0xD0, 0xA1, 0x7B, ++0x13, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA0, 0x47, 0xA5, 0xE7, 0x06, 0x30, 0x7B, 0xF7, 0x33, 0xF8, 0xA1, 0xE7, ++0x61, 0x89, 0x20, 0x89, 0x62, 0x68, 0xCD, 0xF7, 0xB9, 0xFB, 0x20, 0x00, 0xFF, 0xF7, 0xDC, 0xFE, 0x98, 0xE7, 0xA1, 0x7A, ++0x20, 0x89, 0x62, 0x68, 0xCD, 0xF7, 0x2E, 0xFC, 0x20, 0x00, 0xFF, 0xF7, 0xD3, 0xFE, 0x8F, 0xE7, 0x20, 0x00, 0xFF, 0xF7, ++0xFB, 0xFE, 0x8B, 0xE7, 0x03, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x84, 0xE7, 0xC0, 0x46, ++0x28, 0x19, 0x16, 0x00, 0xC8, 0xDF, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, 0x03, 0x05, 0x1B, 0x0D, 0x82, 0x0B, 0x0B, 0x2B, ++0x1C, 0xD8, 0x00, 0x2A, 0x4C, 0xD1, 0x19, 0x02, 0x04, 0x22, 0x0A, 0x43, 0x92, 0xB2, 0xF8, 0x21, 0x09, 0x01, 0x08, 0x42, ++0x1F, 0xD1, 0xFB, 0x21, 0xFF, 0x2A, 0x46, 0xD0, 0x8C, 0x42, 0x44, 0xD8, 0xFF, 0x23, 0x13, 0x40, 0x02, 0x2B, 0x26, 0xD9, ++0x04, 0x2B, 0x26, 0xD1, 0xB3, 0xF7, 0x8A, 0xFC, 0x00, 0x28, 0x3A, 0xD0, 0x25, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x46, 0xE0, ++0x01, 0x2A, 0x31, 0xD0, 0x00, 0x2A, 0x32, 0xD1, 0xF8, 0x22, 0x12, 0x01, 0x10, 0x42, 0x2E, 0xD0, 0x00, 0x21, 0xFF, 0x22, ++0x86, 0x2B, 0xE1, 0xD8, 0x00, 0xE0, 0xFB, 0x21, 0x80, 0x3B, 0xDD, 0x00, 0xED, 0x1A, 0x1C, 0x48, 0x40, 0x19, 0x24, 0x30, ++0x00, 0x78, 0x02, 0x28, 0xD6, 0xD1, 0x1B, 0x02, 0x01, 0x22, 0x1A, 0x43, 0x92, 0xB2, 0x18, 0x49, 0xD2, 0xE7, 0x00, 0x2B, ++0x06, 0xD1, 0x17, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x10, 0xE0, 0x84, 0xF7, 0xE0, 0xFB, ++0x00, 0x28, 0x03, 0xD0, 0x0E, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x18, 0xE0, 0x10, 0x48, 0x7C, 0xF7, 0xEB, 0xFB, 0x04, 0xE0, ++0x01, 0x2A, 0x02, 0xD1, 0x0B, 0x4B, 0x9C, 0x42, 0xEE, 0xD9, 0x01, 0x23, 0x1A, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x7A, 0xF7, ++0xDB, 0xFA, 0x01, 0x25, 0x05, 0x70, 0xCC, 0xF7, 0x37, 0xF9, 0x01, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0xA5, 0xFB, 0x07, 0x4B, ++0x9D, 0x77, 0x70, 0xBD, 0x00, 0x00, 0x61, 0x40, 0xCC, 0xAA, 0x16, 0x00, 0xFD, 0x03, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x50, 0xD2, 0x10, 0x00, 0x03, 0x11, 0x00, 0x00, 0x24, 0x2A, 0x16, 0x00, 0x10, 0xB5, 0x08, 0x20, 0x7A, 0xF7, 0xBA, 0xFF, ++0x10, 0x4C, 0x11, 0x49, 0x20, 0x00, 0xFF, 0xF7, 0x2B, 0xFE, 0x61, 0x89, 0x00, 0x29, 0x0E, 0xD0, 0x20, 0x89, 0xFF, 0xF7, ++0x77, 0xFF, 0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0x09, 0x48, 0x41, 0x89, 0xFF, 0xF7, 0x52, 0xFE, 0x0C, 0xE0, 0x20, 0x00, ++0xFF, 0xF7, 0x68, 0xFE, 0x08, 0xE0, 0x05, 0x4C, 0x20, 0x89, 0x00, 0x22, 0x00, 0x21, 0xCD, 0xF7, 0x01, 0xFB, 0x20, 0x00, ++0xFF, 0xF7, 0x24, 0xFE, 0x10, 0xBD, 0xC0, 0x46, 0x58, 0x1E, 0x16, 0x00, 0x60, 0x1E, 0x16, 0x00, 0x10, 0xB5, 0x7F, 0xF7, ++0xBD, 0xFD, 0x06, 0x49, 0x06, 0x20, 0x7A, 0xF7, 0x47, 0xFF, 0x05, 0x49, 0x07, 0x20, 0x7A, 0xF7, 0x43, 0xFF, 0x04, 0x49, ++0x08, 0x20, 0x7A, 0xF7, 0x3F, 0xFF, 0x10, 0xBD, 0xA5, 0x77, 0x10, 0x00, 0xB9, 0x75, 0x10, 0x00, 0x65, 0x7A, 0x10, 0x00, ++0x10, 0xB5, 0x0A, 0x00, 0x41, 0x23, 0x00, 0x21, 0x0C, 0x48, 0x7A, 0xF7, 0x7B, 0xFA, 0x04, 0x00, 0x01, 0x30, 0x28, 0x22, ++0x0A, 0x49, 0xD1, 0xF7, 0x6D, 0xF9, 0xE2, 0x79, 0x2F, 0x23, 0x13, 0x40, 0xE3, 0x71, 0x20, 0x00, 0x29, 0x30, 0x18, 0x22, ++0x00, 0x21, 0x78, 0xF7, 0xEF, 0xFA, 0x00, 0x23, 0x23, 0x70, 0x20, 0x00, 0xCC, 0xF7, 0xC6, 0xF8, 0x00, 0x20, 0x10, 0xBD, ++0x01, 0x11, 0x00, 0x00, 0xA4, 0xB5, 0x0D, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x0D, 0x00, 0x90, 0x46, 0x06, 0x0A, ++0xB2, 0x00, 0x11, 0x4B, 0xD7, 0x58, 0x0C, 0x23, 0x03, 0x22, 0x00, 0x21, 0x0F, 0x48, 0x7A, 0xF7, 0x51, 0xFA, 0x04, 0x00, ++0x43, 0x46, 0x03, 0x70, 0x2D, 0x02, 0x81, 0x35, 0xFF, 0x35, 0x75, 0x19, 0x45, 0x80, 0x00, 0x23, 0x83, 0x72, 0x88, 0x23, ++0xFF, 0x33, 0xFB, 0x5C, 0xC3, 0x72, 0x39, 0x00, 0x72, 0x31, 0x04, 0x30, 0x06, 0x22, 0xD1, 0xF7, 0x35, 0xF9, 0x20, 0x00, ++0xCC, 0xF7, 0x9A, 0xF8, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, ++0x70, 0xB5, 0x05, 0x00, 0x0E, 0x00, 0x04, 0x78, 0x02, 0x2C, 0x21, 0xD8, 0x00, 0x2C, 0x04, 0xD1, 0x14, 0x4A, 0x30, 0x23, ++0x00, 0x21, 0xD1, 0x54, 0x1B, 0xE0, 0x03, 0x20, 0x88, 0xF7, 0x2E, 0xFC, 0x04, 0x1E, 0x1C, 0xD1, 0x2B, 0x78, 0x0F, 0x49, ++0x30, 0x22, 0x8B, 0x54, 0x01, 0x2B, 0x10, 0xD1, 0xDF, 0x20, 0x00, 0x21, 0x80, 0x00, 0x7A, 0xF7, 0xE7, 0xFA, 0x0B, 0x4B, ++0x18, 0x60, 0x0B, 0x4A, 0x24, 0x23, 0x01, 0x21, 0xD1, 0x54, 0x00, 0x21, 0x00, 0x20, 0x92, 0xF7, 0xA1, 0xF8, 0x00, 0xE0, ++0x12, 0x24, 0x21, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x3B, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x0C, 0x24, 0xF7, 0xE7, 0xC0, 0x46, ++0x68, 0x9E, 0x16, 0x00, 0x64, 0xA2, 0x16, 0x00, 0xCC, 0xAA, 0x16, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0F, 0x4B, ++0x5B, 0x68, 0x02, 0x00, 0x06, 0x21, 0x01, 0x20, 0x98, 0x47, 0x20, 0x78, 0x63, 0x78, 0x1B, 0x02, 0x03, 0x43, 0xA0, 0x78, ++0x00, 0x04, 0x03, 0x43, 0xE0, 0x78, 0x00, 0x06, 0x18, 0x43, 0x23, 0x79, 0x61, 0x79, 0x09, 0x02, 0x19, 0x43, 0xA4, 0xF7, ++0xFF, 0xF8, 0x20, 0x00, 0xB3, 0xF7, 0x3C, 0xFF, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x10, 0xFA, 0x00, 0x20, 0x70, 0xBD, ++0x94, 0x92, 0x16, 0x00, 0x10, 0x4A, 0xFF, 0x21, 0x13, 0x68, 0x8B, 0x43, 0x0F, 0x48, 0x00, 0x78, 0x03, 0x43, 0x80, 0x20, ++0x03, 0x43, 0x0E, 0x48, 0x03, 0x60, 0x0E, 0x4B, 0x1B, 0x78, 0x1B, 0x01, 0x0B, 0x40, 0xD0, 0x68, 0x88, 0x43, 0x03, 0x43, ++0x0B, 0x49, 0x0B, 0x60, 0x0B, 0x4B, 0x00, 0x21, 0x19, 0x60, 0x13, 0x69, 0x0A, 0x4A, 0x13, 0x40, 0x0A, 0x4A, 0x13, 0x60, ++0x0A, 0x4B, 0x0B, 0x4A, 0x1A, 0x60, 0x0B, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xE4, 0xE6, 0x10, 0x00, 0x14, 0xE7, 0x10, 0x00, ++0x08, 0x01, 0x60, 0x40, 0xF7, 0xE8, 0x10, 0x00, 0x28, 0x10, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, 0xFF, 0x0F, 0xF0, 0xFF, ++0x34, 0x08, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, 0x00, 0x01, 0x0A, 0x01, 0x00, 0x01, 0x0F, 0x01, 0x0B, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x11, 0xD1, 0x0A, 0x4B, 0x1B, 0x68, 0x03, 0x60, 0x0A, 0x4B, 0x1B, 0x68, 0x43, 0x60, 0x09, 0x4B, 0x1B, 0x68, ++0x83, 0x60, 0x09, 0x4B, 0x1B, 0x68, 0xC3, 0x60, 0x08, 0x4B, 0x1B, 0x68, 0x03, 0x61, 0x02, 0x4B, 0x01, 0x22, 0x1A, 0x70, ++0x70, 0x47, 0xC0, 0x46, 0xD3, 0xE6, 0x10, 0x00, 0x08, 0x01, 0x60, 0x40, 0x00, 0x00, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, ++0x28, 0x10, 0x62, 0x40, 0x34, 0x08, 0x62, 0x40, 0x09, 0x4B, 0x02, 0x68, 0x1A, 0x60, 0x09, 0x4B, 0x42, 0x68, 0x1A, 0x60, ++0x08, 0x4B, 0x82, 0x68, 0x1A, 0x60, 0x08, 0x4B, 0xC2, 0x68, 0x1A, 0x60, 0x02, 0x69, 0x07, 0x4B, 0x1A, 0x60, 0x07, 0x4B, ++0x00, 0x22, 0x1A, 0x70, 0x70, 0x47, 0xC0, 0x46, 0x08, 0x01, 0x60, 0x40, 0x00, 0x00, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, ++0x28, 0x10, 0x62, 0x40, 0x34, 0x08, 0x62, 0x40, 0xD3, 0xE6, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x03, 0x78, ++0x00, 0x2B, 0x17, 0xD0, 0x02, 0x20, 0xF9, 0xF7, 0x8D, 0xFD, 0x0E, 0x48, 0xFF, 0xF7, 0xB0, 0xFF, 0x62, 0x78, 0x0D, 0x4B, ++0x1A, 0x70, 0xA2, 0x78, 0x0C, 0x4B, 0x1A, 0x70, 0xFF, 0xF7, 0x70, 0xFF, 0x21, 0x78, 0x0B, 0x48, 0x7C, 0xF7, 0x46, 0xFA, ++0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x82, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0x03, 0x48, 0xFF, 0xF7, 0xBF, 0xFF, 0x01, 0x20, ++0xF9, 0xF7, 0x72, 0xFD, 0xEE, 0xE7, 0xC0, 0x46, 0xE4, 0xE6, 0x10, 0x00, 0x14, 0xE7, 0x10, 0x00, 0xF7, 0xE8, 0x10, 0x00, ++0x5C, 0xD2, 0x10, 0x00, 0x00, 0x23, 0x03, 0x73, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x88, ++0x12, 0x21, 0x15, 0x2B, 0x04, 0xD9, 0x04, 0x4B, 0x80, 0x22, 0xD2, 0x01, 0x9A, 0x82, 0x00, 0x21, 0xFF, 0xF7, 0x50, 0xF9, ++0x00, 0x20, 0x10, 0xBD, 0x68, 0x9E, 0x16, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0F, 0x4B, 0x1B, 0x68, 0x02, 0x2B, ++0x0B, 0xD0, 0x29, 0x00, 0x20, 0x00, 0x0D, 0x4B, 0x98, 0x47, 0x0D, 0x4B, 0x80, 0x22, 0x12, 0x01, 0x1A, 0x83, 0x12, 0x22, ++0x5A, 0x83, 0x00, 0x20, 0x70, 0xBD, 0xFA, 0xF7, 0x09, 0xFC, 0x00, 0x28, 0xEF, 0xD1, 0x23, 0x78, 0x9B, 0x07, 0xEC, 0xD5, ++0x05, 0x4B, 0x80, 0x22, 0x92, 0x00, 0x1A, 0x83, 0xEF, 0x3A, 0xFF, 0x3A, 0x5A, 0x83, 0xE4, 0xE7, 0x50, 0xE0, 0x10, 0x00, ++0x15, 0x28, 0x09, 0x00, 0x68, 0x9E, 0x16, 0x00, 0x70, 0xB5, 0x0C, 0x00, 0x0B, 0x4A, 0x8C, 0x23, 0xD3, 0x5C, 0x0C, 0x25, ++0x01, 0x2B, 0x05, 0xD0, 0x29, 0x00, 0x20, 0x00, 0xFF, 0xF7, 0x18, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xA4, 0xF7, 0xB8, 0xFC, ++0x05, 0x1E, 0xF5, 0xD0, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEE, 0xE7, 0xC0, 0x46, ++0x68, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x78, 0x01, 0x21, 0x99, 0x42, ++0x9B, 0x41, 0x11, 0x31, 0x19, 0x40, 0xFF, 0xF7, 0xFB, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0x70, 0xB5, 0x05, 0x00, ++0x08, 0x00, 0x1C, 0x00, 0x47, 0x4B, 0x9C, 0x42, 0x43, 0xD0, 0x23, 0xD8, 0x46, 0x4B, 0x9C, 0x42, 0x51, 0xD0, 0x13, 0xD8, ++0x45, 0x4B, 0x9C, 0x42, 0x45, 0xD0, 0x45, 0x4B, 0x9C, 0x42, 0x04, 0xD1, 0x43, 0x49, 0xFF, 0xF7, 0x43, 0xF9, 0x00, 0x25, ++0x6A, 0xE0, 0x42, 0x4B, 0x9C, 0x42, 0x00, 0xD0, 0x70, 0xE0, 0x40, 0x49, 0xFF, 0xF7, 0xB6, 0xFF, 0x00, 0x25, 0x61, 0xE0, ++0x3E, 0x4B, 0x9C, 0x42, 0x3E, 0xD0, 0x3E, 0x4B, 0x9C, 0x42, 0x65, 0xD1, 0x3C, 0x49, 0x00, 0x20, 0xFF, 0xF7, 0x16, 0xFE, ++0x00, 0x25, 0x55, 0xE0, 0x3A, 0x4B, 0x9C, 0x42, 0x20, 0xD0, 0x0A, 0xD9, 0x39, 0x4B, 0x9C, 0x42, 0x12, 0xD0, 0x39, 0x4B, ++0x9C, 0x42, 0x55, 0xD1, 0x19, 0x00, 0xFF, 0xF7, 0xDB, 0xF8, 0x00, 0x25, 0x46, 0xE0, 0x36, 0x4B, 0x9C, 0x42, 0x28, 0xD0, ++0x35, 0x4B, 0x9C, 0x42, 0x2A, 0xD1, 0x34, 0x49, 0xFF, 0xF7, 0x84, 0xFE, 0x00, 0x25, 0x3B, 0xE0, 0x2E, 0x49, 0xFF, 0xF7, ++0x01, 0xF9, 0x00, 0x25, 0x36, 0xE0, 0x24, 0x49, 0xFF, 0xF7, 0x42, 0xFE, 0x00, 0x25, 0x31, 0xE0, 0x28, 0x49, 0xFF, 0xF7, ++0x15, 0xFF, 0x00, 0x25, 0x2C, 0xE0, 0x00, 0x23, 0x0B, 0x73, 0x20, 0x4B, 0x28, 0x00, 0x29, 0x4D, 0xA8, 0x47, 0x05, 0x00, ++0x24, 0xE0, 0x1C, 0x49, 0xFF, 0xF7, 0x3A, 0xFF, 0x00, 0x25, 0x1F, 0xE0, 0x1D, 0x49, 0xFF, 0xF7, 0x47, 0xFF, 0x00, 0x25, ++0x1A, 0xE0, 0x20, 0x49, 0xFF, 0xF7, 0x88, 0xFF, 0x00, 0x25, 0x15, 0xE0, 0x23, 0x00, 0x28, 0x00, 0x1E, 0x4D, 0xA8, 0x47, ++0x05, 0x00, 0x1E, 0x4B, 0x9C, 0x42, 0x05, 0xD0, 0x1D, 0x4B, 0x08, 0x22, 0x21, 0x00, 0x91, 0x43, 0x99, 0x42, 0x04, 0xD1, ++0x02, 0x20, 0xF9, 0xF7, 0x81, 0xFC, 0xFA, 0xF7, 0x63, 0xF9, 0x19, 0x4B, 0x9C, 0x42, 0x05, 0xD0, 0x21, 0x00, 0x18, 0x48, ++0x7C, 0xF7, 0x40, 0xF9, 0x28, 0x00, 0x70, 0xBD, 0x01, 0x20, 0xF9, 0xF7, 0x73, 0xFC, 0xF5, 0xE7, 0x23, 0x00, 0x01, 0x00, ++0x28, 0x00, 0x0E, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xE0, 0xE7, 0xC0, 0x46, 0x02, 0x18, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, ++0x05, 0x04, 0x00, 0x00, 0x13, 0x0C, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x1A, 0x0C, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, ++0xC6, 0xFC, 0x00, 0x00, 0xC7, 0xFC, 0x00, 0x00, 0xC9, 0xFC, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x70, 0xFC, 0x00, 0x00, ++0x1D, 0x0C, 0x09, 0x00, 0x06, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x0C, 0x18, 0x00, 0x00, 0x6C, 0xD2, 0x10, 0x00, ++0x70, 0xB5, 0x0D, 0x00, 0x14, 0x00, 0x04, 0x23, 0x02, 0x00, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0x03, 0xF8, 0x05, 0x70, ++0x44, 0x80, 0xCB, 0xF7, 0x5F, 0xFE, 0x70, 0xBD, 0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x10, 0x00, 0x1A, 0x88, ++0x0C, 0x21, 0xFF, 0xF7, 0xE9, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x80, 0x46, 0x0C, 0x00, 0x91, 0x46, 0x0F, 0x0A, 0xBA, 0x00, 0x2E, 0x4B, 0xD5, 0x58, ++0x08, 0x00, 0x7A, 0xF7, 0xB7, 0xFB, 0x02, 0x26, 0x00, 0x28, 0x19, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x4F, 0xD0, ++0x3C, 0x23, 0xEE, 0x5C, 0x02, 0x2E, 0x03, 0xD1, 0x43, 0x46, 0x5B, 0x88, 0x00, 0x2B, 0x1B, 0xD1, 0xFA, 0x21, 0x49, 0x01, ++0xA9, 0x83, 0xFF, 0xB2, 0x36, 0x23, 0xEA, 0x5C, 0x38, 0x00, 0xA1, 0xF7, 0x6D, 0xFE, 0xA9, 0x8B, 0x38, 0x00, 0xAB, 0xF7, ++0x31, 0xFC, 0x00, 0x26, 0x43, 0x46, 0x1A, 0x88, 0x31, 0x00, 0x48, 0x46, 0xFF, 0xF7, 0xB2, 0xFF, 0x00, 0x20, 0x03, 0xB0, ++0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xFB, 0xB2, 0x9B, 0x46, 0x06, 0x23, 0x6B, 0x44, ++0x9A, 0x46, 0x6B, 0x46, 0x5A, 0x1D, 0x51, 0x46, 0x58, 0x46, 0x8B, 0xF7, 0x65, 0xFE, 0x43, 0x46, 0x5A, 0x88, 0x53, 0x46, ++0x19, 0x88, 0x8A, 0x42, 0x13, 0xD9, 0x6B, 0x46, 0x05, 0x33, 0x1B, 0x78, 0x00, 0x2B, 0xCD, 0xD0, 0x4B, 0x43, 0x9A, 0x42, ++0xCA, 0xD8, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0x58, 0x46, 0xAB, 0xF7, 0x73, 0xFA, 0x22, 0x00, 0x21, 0x00, 0x07, 0x48, ++0x79, 0xF7, 0xD2, 0xFF, 0xBE, 0xE7, 0x43, 0x46, 0x1A, 0x88, 0x12, 0x21, 0x48, 0x46, 0xFF, 0xF7, 0x7F, 0xFF, 0xC5, 0xE7, ++0x0C, 0x26, 0xC3, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x22, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0x93, 0xB0, 0x01, 0x90, 0x0C, 0x00, ++0x16, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x37, 0x4B, 0xD5, 0x58, 0x08, 0x00, 0x7A, 0xF7, 0x4E, 0xFB, 0x04, 0x28, 0x06, 0xD0, ++0x09, 0x28, 0x18, 0xD0, 0x0C, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x42, 0xFB, 0x10, 0xE0, 0x3C, 0x22, 0x30, 0x49, 0x03, 0xA8, ++0xD0, 0xF7, 0x62, 0xFE, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x38, 0xFB, 0x2D, 0x4A, 0xE8, 0x23, 0xD5, 0x58, 0x03, 0xAB, ++0x01, 0x22, 0x01, 0x21, 0x20, 0x00, 0xA8, 0x47, 0x00, 0x20, 0x13, 0xB0, 0xF0, 0xBD, 0x21, 0x00, 0x28, 0x48, 0x79, 0xF7, ++0x0F, 0xFF, 0x01, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0xC9, 0xFA, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x21, 0xFB, 0xBC, 0x23, ++0x5B, 0x00, 0xEB, 0x5C, 0xDB, 0x43, 0x9B, 0x07, 0x21, 0xD1, 0x00, 0x23, 0x01, 0x9A, 0x93, 0x71, 0xFF, 0xB2, 0x29, 0x00, ++0x38, 0x31, 0x38, 0x00, 0x88, 0xF7, 0x70, 0xF9, 0x00, 0x28, 0x1C, 0xD0, 0x1B, 0x48, 0x7C, 0xF7, 0x3F, 0xF8, 0x01, 0x23, ++0xAF, 0x22, 0x92, 0x00, 0xAB, 0x54, 0x43, 0x22, 0xAB, 0x54, 0x20, 0x00, 0x93, 0xF7, 0xA0, 0xF9, 0x88, 0xF7, 0x64, 0xFA, ++0x00, 0x28, 0x19, 0xD1, 0xC4, 0x20, 0x22, 0x00, 0x21, 0x00, 0xC0, 0x00, 0x79, 0xF7, 0x68, 0xFF, 0xC8, 0xE7, 0x22, 0x00, ++0x21, 0x00, 0x10, 0x48, 0x79, 0xF7, 0x62, 0xFF, 0xD7, 0xE7, 0x0F, 0x48, 0x7C, 0xF7, 0x22, 0xF8, 0x44, 0x23, 0x01, 0x22, ++0xEA, 0x54, 0x0B, 0x3B, 0xEA, 0x5C, 0x33, 0x21, 0x38, 0x00, 0xA1, 0xF7, 0x39, 0xFC, 0xE1, 0xE7, 0x22, 0x00, 0x21, 0x00, ++0x08, 0x48, 0x79, 0xF7, 0x4F, 0xFF, 0xDF, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x80, 0xD6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x06, 0x06, 0x00, 0x00, 0x74, 0xD2, 0x10, 0x00, 0x14, 0x06, 0x00, 0x00, 0x7C, 0xD2, 0x10, 0x00, 0x1D, 0x06, 0x00, 0x00, ++0x70, 0xB5, 0x04, 0x00, 0x0E, 0x00, 0x15, 0x00, 0x41, 0x88, 0x80, 0x23, 0x1B, 0x01, 0x99, 0x42, 0x06, 0xD3, 0x22, 0x88, ++0x0C, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0xE4, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x03, 0x48, 0x7B, 0xF7, 0xEF, 0xFF, 0x30, 0x0A, ++0x00, 0x21, 0xAB, 0xF7, 0xA7, 0xF8, 0xF0, 0xE7, 0x84, 0xD2, 0x10, 0x00, 0x70, 0xB5, 0x0E, 0x00, 0x15, 0x00, 0x07, 0x23, ++0x02, 0x00, 0x00, 0x21, 0x06, 0x48, 0x79, 0xF7, 0xDB, 0xFE, 0x04, 0x00, 0x06, 0x70, 0x01, 0x30, 0x06, 0x22, 0x29, 0x00, ++0xD0, 0xF7, 0xCC, 0xFD, 0x20, 0x00, 0xCB, 0xF7, 0x31, 0xFD, 0x70, 0xBD, 0x01, 0x11, 0x00, 0x00, 0xF0, 0xB5, 0x83, 0xB0, ++0x01, 0x90, 0x0D, 0x00, 0x16, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x22, 0x4B, 0xD4, 0x58, 0x08, 0x00, 0x7A, 0xF7, 0x98, 0xFA, ++0x00, 0x28, 0x1A, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x16, 0xD9, 0x88, 0x23, 0xFF, 0x33, 0xE3, 0x5C, 0x00, 0x2B, ++0x03, 0xD1, 0x36, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x14, 0xD0, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x81, 0xFA, 0x36, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x11, 0xD1, 0x2A, 0x00, 0x29, 0x00, 0x14, 0x48, 0x79, 0xF7, 0xE6, 0xFE, 0x03, 0xE0, 0x02, 0x21, ++0x30, 0x00, 0x91, 0xF7, 0x73, 0xFA, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x0C, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x6C, 0xFA, ++0xF7, 0xE7, 0x06, 0x23, 0x1C, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x79, 0xF7, 0x93, 0xFE, 0x05, 0x00, 0x00, 0x23, 0x03, 0x70, ++0x01, 0x9B, 0x1B, 0x88, 0x43, 0x80, 0xF8, 0xB2, 0xAB, 0xF7, 0x32, 0xFA, 0xC0, 0x03, 0x40, 0x0C, 0xA8, 0x80, 0x28, 0x00, ++0xCB, 0xF7, 0xE4, 0xFC, 0xE1, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x16, 0x06, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, ++0xF0, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x16, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x31, 0x4A, 0x9F, 0x58, 0x08, 0x00, ++0x7A, 0xF7, 0x46, 0xFA, 0x00, 0x28, 0x53, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x02, 0x24, 0x03, 0x28, 0x4F, 0xD9, 0x01, 0x99, ++0x4B, 0x88, 0xA8, 0x22, 0xD2, 0x00, 0x10, 0x34, 0x93, 0x42, 0x48, 0xD8, 0xDA, 0x07, 0x46, 0xD4, 0x8A, 0x88, 0x05, 0x2A, ++0x43, 0xD9, 0xD0, 0x07, 0x41, 0xD4, 0x08, 0x00, 0xC9, 0x88, 0x00, 0x29, 0x3D, 0xD0, 0x00, 0x89, 0x84, 0x46, 0x28, 0x28, ++0x39, 0xD8, 0x58, 0x08, 0x81, 0x42, 0x36, 0xD8, 0x93, 0x42, 0x34, 0xD3, 0x61, 0x44, 0x49, 0x00, 0x99, 0x42, 0x30, 0xD2, ++0x7B, 0x8C, 0x06, 0x3C, 0x5B, 0x07, 0x2C, 0xD5, 0x3C, 0x23, 0xFC, 0x5C, 0x00, 0x2C, 0x01, 0xD0, 0x0C, 0x24, 0x26, 0xE0, ++0x38, 0x00, 0x54, 0x30, 0x07, 0x21, 0xA1, 0xF7, 0x47, 0xFA, 0x00, 0x28, 0x01, 0xD1, 0x1A, 0x24, 0x1D, 0xE0, 0x08, 0x23, ++0x2A, 0x00, 0x29, 0x00, 0x11, 0x48, 0x79, 0xF7, 0x31, 0xFE, 0x01, 0x9B, 0x5A, 0x88, 0x02, 0x80, 0x9B, 0x88, 0x43, 0x80, ++0xC0, 0x21, 0x49, 0x00, 0x8A, 0x42, 0x00, 0xD9, 0x01, 0x80, 0xC0, 0x22, 0x52, 0x00, 0x93, 0x42, 0x00, 0xD9, 0x42, 0x80, ++0x01, 0x9A, 0xD3, 0x88, 0x83, 0x80, 0x13, 0x89, 0xC3, 0x80, 0x79, 0xF7, 0x45, 0xFE, 0x00, 0xE0, 0x02, 0x24, 0x21, 0x00, ++0x30, 0x00, 0x91, 0xF7, 0xE7, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x64, 0xA2, 0x16, 0x00, 0x0D, 0x06, 0x00, 0x00, ++0x70, 0xB5, 0x04, 0x00, 0x08, 0x00, 0x15, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x0F, 0x4A, 0x9E, 0x58, 0x7A, 0xF7, 0xDA, 0xF9, ++0x02, 0x21, 0x00, 0x28, 0x10, 0xD0, 0x63, 0x88, 0xF0, 0x22, 0x10, 0x31, 0x1A, 0x42, 0x0B, 0xD1, 0xE6, 0x3A, 0x01, 0x39, ++0x1A, 0x42, 0x07, 0xD1, 0x73, 0x84, 0x2C, 0x32, 0xB1, 0x5C, 0x00, 0x29, 0x08, 0xD1, 0x35, 0x3A, 0x93, 0x43, 0x73, 0x84, ++0x22, 0x88, 0x28, 0x00, 0xFF, 0xF7, 0xE0, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x00, 0x21, 0xF7, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0E, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x4B, 0x4B, ++0x9C, 0x42, 0x5D, 0xD0, 0x0E, 0xD9, 0x4A, 0x4B, 0x9C, 0x42, 0x67, 0xD0, 0x42, 0xD9, 0x49, 0x4B, 0x9C, 0x42, 0x00, 0xD0, ++0x81, 0xE0, 0x47, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0xDA, 0xFD, 0x00, 0x25, 0x43, 0xE0, 0x44, 0x4B, 0x9C, 0x42, ++0x69, 0xD0, 0x01, 0x33, 0x9C, 0x42, 0x13, 0xD3, 0x42, 0x4B, 0xE3, 0x18, 0x9B, 0xB2, 0x03, 0x2B, 0x00, 0xD9, 0x6E, 0xE0, ++0x10, 0x00, 0x7A, 0xF7, 0x91, 0xF9, 0x43, 0x28, 0x51, 0xD8, 0x41, 0x28, 0x51, 0xD8, 0x32, 0x00, 0x0C, 0x21, 0x20, 0x00, ++0xFF, 0xF7, 0xCE, 0xFE, 0x00, 0x25, 0x29, 0xE0, 0x39, 0x4B, 0x9C, 0x42, 0x37, 0xD0, 0x39, 0x4B, 0x9C, 0x42, 0x5A, 0xD1, ++0x38, 0x48, 0x7B, 0xF7, 0xAB, 0xFE, 0xB5, 0x1D, 0x16, 0x23, 0x9A, 0x46, 0xB2, 0x44, 0x36, 0x4B, 0x99, 0x46, 0x29, 0x78, ++0x48, 0x46, 0x7B, 0xF7, 0xA1, 0xFE, 0x01, 0x35, 0x55, 0x45, 0xF8, 0xD1, 0x2F, 0x4B, 0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, ++0x30, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0x0B, 0xE0, 0x2F, 0x4B, 0x9C, 0x42, 0x38, 0xD0, 0x2F, 0x4B, 0x9C, 0x42, 0x3C, 0xD1, ++0x2D, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x8B, 0xFD, 0x00, 0x25, 0x21, 0x00, 0x2B, 0x48, 0x7B, 0xF7, 0x86, 0xFE, ++0x28, 0x00, 0x03, 0xB0, 0x0C, 0xBC, 0x91, 0x46, 0x9A, 0x46, 0xF0, 0xBD, 0x1A, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, ++0xFB, 0xFE, 0x00, 0x25, 0xEE, 0xE7, 0x1C, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0xEC, 0xFD, 0x05, 0x00, 0xE7, 0xE7, ++0x14, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x6B, 0xFE, 0x05, 0x00, 0xE0, 0xE7, 0x4A, 0x28, 0xAD, 0xD1, 0x23, 0x00, ++0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, 0x16, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xD6, 0xE7, 0x0E, 0x4A, 0x39, 0x00, 0x30, 0x00, ++0xFF, 0xF7, 0x8A, 0xFE, 0x05, 0x00, 0xCF, 0xE7, 0x11, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x43, 0xFF, 0x05, 0x00, ++0xC8, 0xE7, 0x23, 0x00, 0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, 0x0B, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xC0, 0xE7, 0xC0, 0x46, ++0x03, 0x08, 0x00, 0x00, 0x28, 0x0C, 0x00, 0x00, 0x37, 0x0C, 0x00, 0x00, 0x1F, 0x04, 0x00, 0x00, 0xD4, 0xFB, 0xFF, 0xFF, ++0x09, 0x04, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x90, 0xD2, 0x10, 0x00, 0x98, 0xD2, 0x10, 0x00, 0xC1, 0xDB, 0x09, 0x00, ++0x0D, 0x08, 0x00, 0x00, 0x11, 0x08, 0x00, 0x00, 0x9C, 0xD2, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x78, ++0x00, 0x21, 0x01, 0x2B, 0x00, 0xD9, 0x12, 0x31, 0xB2, 0xF7, 0x7C, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x08, 0x00, ++0x00, 0x21, 0xB2, 0xF7, 0x75, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0xAD, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0x02, 0xAB, 0x00, 0x22, 0xDA, 0x71, 0x60, 0x32, 0x00, 0x21, ++0x14, 0xA8, 0x77, 0xF7, 0x8B, 0xFD, 0x9B, 0x4A, 0x9B, 0x4B, 0xD3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0xC8, 0xE1, 0x99, 0x4B, ++0x02, 0x21, 0xD1, 0x54, 0x02, 0xAB, 0x00, 0x21, 0xD9, 0x71, 0x44, 0x32, 0x00, 0x20, 0x00, 0x23, 0x01, 0x26, 0x11, 0x78, ++0x05, 0x29, 0x26, 0xD0, 0x01, 0x33, 0xDB, 0xB2, 0x40, 0x32, 0x30, 0x00, 0x0C, 0x2B, 0xF6, 0xD1, 0x02, 0xAB, 0x0C, 0x22, ++0xDA, 0x71, 0x27, 0x78, 0x00, 0x2F, 0x24, 0xD0, 0x60, 0x7A, 0x07, 0x23, 0x07, 0x00, 0x9F, 0x43, 0x00, 0x97, 0x00, 0xD0, ++0xB5, 0xE1, 0x8A, 0x49, 0x0F, 0x22, 0x02, 0x40, 0x03, 0x09, 0x8E, 0x5C, 0xCB, 0x5C, 0xF6, 0x18, 0xF6, 0xB2, 0x00, 0x2E, ++0x61, 0xDD, 0x23, 0x00, 0x0A, 0x33, 0x3A, 0x00, 0x02, 0x37, 0x07, 0x40, 0x01, 0x21, 0x01, 0x40, 0xA4, 0x46, 0x0C, 0x00, ++0x1E, 0xE0, 0x00, 0x28, 0x01, 0xD0, 0x02, 0xAA, 0xD3, 0x71, 0x0C, 0x21, 0x00, 0x27, 0x0B, 0x2B, 0x00, 0xD8, 0x8D, 0xE1, ++0xD7, 0xE7, 0xA1, 0x78, 0xE0, 0x1C, 0xB2, 0xF7, 0x35, 0xFF, 0x0B, 0x21, 0x00, 0x28, 0x00, 0xD0, 0x84, 0xE1, 0xD1, 0xE7, ++0x59, 0x88, 0x18, 0x88, 0x81, 0x42, 0x46, 0xD8, 0x03, 0x29, 0x44, 0xD9, 0x03, 0x28, 0x42, 0xD9, 0x01, 0x32, 0x10, 0x33, ++0xB2, 0x42, 0x04, 0xDA, 0x00, 0x2F, 0xF1, 0xD0, 0x94, 0x42, 0xEF, 0xD1, 0xF6, 0xE7, 0x64, 0x46, 0x23, 0x00, 0x0E, 0x33, ++0x00, 0x98, 0xC8, 0x22, 0x12, 0x01, 0x91, 0x46, 0x6B, 0x4A, 0x92, 0x46, 0xFA, 0x22, 0x52, 0x00, 0x93, 0x46, 0xA4, 0x46, ++0xA8, 0x46, 0x1F, 0x88, 0x5A, 0x88, 0x97, 0x42, 0x2D, 0xD8, 0x1D, 0x89, 0x59, 0x89, 0x8D, 0x42, 0x29, 0xD8, 0xD9, 0x88, ++0x05, 0x2F, 0x26, 0xD9, 0x4A, 0x45, 0x24, 0xD8, 0x0F, 0x00, 0x0A, 0x3F, 0xBF, 0xB2, 0x57, 0x45, 0x1F, 0xD8, 0x9F, 0x88, ++0x5F, 0x45, 0x1C, 0xD2, 0x8C, 0x00, 0x61, 0x18, 0x49, 0x00, 0x01, 0x37, 0x57, 0x43, 0xBA, 0x00, 0xD2, 0x19, 0x01, 0x32, ++0x52, 0x10, 0x91, 0x42, 0x11, 0xDB, 0x01, 0x30, 0x10, 0x33, 0xB0, 0x42, 0xDB, 0xDB, 0x64, 0x46, 0x45, 0x46, 0xA3, 0x78, ++0x01, 0x2B, 0x0F, 0xD9, 0x12, 0x21, 0x00, 0x27, 0x38, 0xE1, 0x64, 0x46, 0x96, 0x42, 0xC3, 0xDD, 0x12, 0x21, 0x00, 0x27, ++0x32, 0xE1, 0x64, 0x46, 0x45, 0x46, 0x86, 0x42, 0xEF, 0xDD, 0x12, 0x21, 0x00, 0x27, 0x2B, 0xE1, 0x63, 0x78, 0x03, 0x2B, ++0x00, 0xD9, 0x35, 0xE1, 0xDB, 0x07, 0x06, 0xD5, 0x49, 0x49, 0x4A, 0x48, 0x7B, 0xF7, 0x98, 0xFD, 0x00, 0x28, 0x00, 0xD0, ++0x2F, 0xE1, 0x02, 0xAB, 0xD8, 0x1D, 0xB3, 0xF7, 0x71, 0xF9, 0x01, 0x00, 0x01, 0x90, 0x00, 0x27, 0x00, 0x28, 0x00, 0xD0, ++0x14, 0xE1, 0x00, 0x2E, 0x00, 0xDC, 0x25, 0xE1, 0x0E, 0x23, 0x99, 0x46, 0xA1, 0x44, 0x14, 0xAF, 0x00, 0x9B, 0x9A, 0x46, ++0x00, 0x23, 0x9B, 0x46, 0xA0, 0x46, 0x4C, 0x46, 0xA9, 0x46, 0x55, 0x46, 0x13, 0xE0, 0x78, 0x60, 0x39, 0x60, 0xBA, 0x60, ++0xFB, 0x60, 0x5B, 0x46, 0xBB, 0x74, 0xFB, 0x74, 0x02, 0xAB, 0xDB, 0x79, 0x3B, 0x82, 0x38, 0x00, 0xCF, 0xF7, 0xCA, 0xFA, ++0x00, 0x28, 0x18, 0xD1, 0x01, 0x35, 0x10, 0x34, 0x20, 0x37, 0xB5, 0x42, 0x24, 0xDA, 0x23, 0x00, 0x21, 0x88, 0x49, 0x00, ++0x22, 0x89, 0x8A, 0x42, 0x00, 0xD9, 0x0A, 0x00, 0x02, 0x2A, 0x00, 0xD2, 0x02, 0x22, 0x58, 0x88, 0x40, 0x00, 0x5B, 0x89, ++0x83, 0x42, 0x00, 0xD9, 0x03, 0x00, 0x93, 0x42, 0xD9, 0xD2, 0x13, 0x00, 0xD7, 0xE7, 0xAA, 0x46, 0x44, 0x46, 0x4D, 0x46, ++0x51, 0x46, 0x25, 0x48, 0x7B, 0xF7, 0x10, 0xFD, 0x51, 0x46, 0x24, 0x48, 0x7B, 0xF7, 0x0C, 0xFD, 0x01, 0x9F, 0x3B, 0x21, ++0x56, 0x45, 0x00, 0xDD, 0xCC, 0xE0, 0x06, 0xE0, 0xAA, 0x46, 0x44, 0x46, 0x4D, 0x46, 0x51, 0x46, 0x1D, 0x48, 0x7B, 0xF7, ++0xFF, 0xFC, 0x02, 0xAB, 0xDA, 0x79, 0x92, 0x01, 0x13, 0x4B, 0x9B, 0x18, 0x9B, 0x68, 0x00, 0x2B, 0x05, 0xD0, 0x19, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x60, 0x78, 0x02, 0x28, 0x2D, 0xD0, 0x0E, 0xD8, 0x00, 0x28, ++0x2A, 0xD0, 0x0B, 0x49, 0x02, 0xAB, 0xD8, 0x79, 0x80, 0x01, 0x08, 0x18, 0x0C, 0x30, 0x11, 0x4B, 0x9C, 0x46, 0x61, 0x44, ++0x06, 0x22, 0xD0, 0xF7, 0xD3, 0xFA, 0x2B, 0xE0, 0x03, 0x28, 0xF0, 0xD0, 0x0B, 0x4B, 0xDF, 0x6E, 0x00, 0x23, 0x1A, 0x00, ++0x19, 0x00, 0xB8, 0x47, 0x22, 0xE0, 0xC0, 0x46, 0xEC, 0xA4, 0x16, 0x00, 0x6D, 0x04, 0x00, 0x00, 0xE4, 0x98, 0x0D, 0x00, ++0x76, 0x0C, 0x00, 0x00, 0xB4, 0x98, 0x0D, 0x00, 0xFA, 0xA7, 0x16, 0x00, 0xA4, 0xD2, 0x10, 0x00, 0xB0, 0xD2, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x0E, 0x03, 0x00, 0x00, 0x4E, 0x4A, 0x02, 0xAB, 0x07, 0x33, 0x1B, 0x78, 0x9B, 0x01, 0xD3, 0x18, ++0xC2, 0x21, 0x89, 0x00, 0x8C, 0x46, 0x62, 0x44, 0x11, 0x68, 0xD9, 0x60, 0x92, 0x88, 0x1A, 0x82, 0x02, 0xAB, 0x07, 0x33, ++0x1B, 0x78, 0x46, 0x4F, 0x9A, 0x01, 0xBA, 0x18, 0x94, 0x60, 0x01, 0x33, 0x9B, 0x01, 0xFB, 0x18, 0x05, 0x22, 0x1A, 0x71, ++0xE1, 0x1C, 0x01, 0x32, 0x0E, 0x20, 0x02, 0xAB, 0x9C, 0x46, 0x60, 0x44, 0xD0, 0xF7, 0x92, 0xFA, 0x3E, 0x4B, 0xF9, 0x18, ++0x05, 0x22, 0x07, 0xA8, 0xD0, 0xF7, 0x8C, 0xFA, 0x67, 0x7A, 0x04, 0xAB, 0x9F, 0x74, 0x00, 0x2E, 0x17, 0xDD, 0x22, 0x00, ++0x0A, 0x32, 0x14, 0xA9, 0x10, 0x88, 0x18, 0x83, 0x50, 0x88, 0x58, 0x83, 0x48, 0x69, 0x40, 0x08, 0x98, 0x83, 0x88, 0x69, ++0xD8, 0x83, 0x10, 0x89, 0x18, 0x84, 0x50, 0x89, 0x58, 0x84, 0x00, 0x98, 0x01, 0x30, 0x00, 0x90, 0x10, 0x32, 0x0C, 0x33, ++0x20, 0x31, 0xB0, 0x42, 0xEA, 0xDB, 0x05, 0x23, 0x3B, 0x40, 0x05, 0x2B, 0x20, 0xD0, 0x02, 0xAB, 0x07, 0x33, 0x1B, 0x78, ++0x04, 0xA8, 0xC3, 0x74, 0x62, 0x78, 0x02, 0x75, 0xA2, 0x78, 0x42, 0x75, 0x22, 0x78, 0x82, 0x75, 0x24, 0x4A, 0x9B, 0x01, ++0xD3, 0x18, 0xD9, 0x68, 0x04, 0x91, 0x1B, 0x8A, 0x83, 0x80, 0x01, 0x23, 0x43, 0x74, 0x22, 0x4B, 0xD2, 0x5C, 0x3C, 0x23, ++0xC2, 0x54, 0xC7, 0xF7, 0x29, 0xFF, 0x01, 0x00, 0x01, 0x27, 0x00, 0x28, 0x1E, 0xD0, 0x03, 0x21, 0x01, 0x27, 0x1B, 0xE0, ++0x01, 0x3E, 0x04, 0xA8, 0x43, 0x8B, 0x0C, 0x22, 0x72, 0x43, 0x82, 0x18, 0x51, 0x8B, 0x5F, 0x18, 0x02, 0x8B, 0xBA, 0x42, ++0x00, 0xD2, 0x07, 0x83, 0x0C, 0x22, 0x72, 0x43, 0x04, 0xA8, 0x84, 0x46, 0x62, 0x44, 0x12, 0x8B, 0xBA, 0x42, 0xCA, 0xD2, ++0x0C, 0x22, 0x72, 0x43, 0x62, 0x44, 0x5B, 0x18, 0x13, 0x83, 0xC4, 0xE7, 0x0C, 0x21, 0x00, 0x27, 0x28, 0x00, 0xB2, 0xF7, ++0x9B, 0xFD, 0x38, 0x00, 0x2D, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x12, 0x21, ++0x00, 0x27, 0xF1, 0xE7, 0x12, 0x21, 0x00, 0x27, 0xEE, 0xE7, 0x12, 0x21, 0x00, 0x27, 0xEB, 0xE7, 0x00, 0x9B, 0x9A, 0x46, ++0x1F, 0xE7, 0xC0, 0x46, 0xEC, 0xA4, 0x16, 0x00, 0x19, 0x03, 0x00, 0x00, 0xD6, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x80, 0x46, 0x0D, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x58, 0x4B, 0xE3, 0x18, 0x9A, 0xB2, 0x39, 0x2A, 0x00, 0xD9, ++0x90, 0xE0, 0x93, 0x00, 0x55, 0x4A, 0xD3, 0x58, 0x9F, 0x46, 0x02, 0x20, 0xF8, 0xF7, 0x40, 0xFF, 0x53, 0x4B, 0x00, 0x22, ++0x44, 0x21, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, ++0x00, 0x26, 0x7C, 0xE0, 0x01, 0x20, 0xF8, 0xF7, 0x2F, 0xFF, 0x4B, 0x4B, 0x11, 0x22, 0x44, 0x21, 0x5A, 0x54, 0x40, 0x31, ++0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x00, 0x26, 0x6B, 0xE0, 0x45, 0x4B, ++0x1B, 0x78, 0x00, 0x26, 0x00, 0x2B, 0x66, 0xD0, 0x43, 0x49, 0x28, 0x00, 0xFF, 0xF7, 0xB0, 0xFD, 0x05, 0x00, 0x21, 0x00, ++0x41, 0x48, 0x7B, 0xF7, 0xDB, 0xFB, 0x41, 0x4B, 0x9C, 0x42, 0x6E, 0xD1, 0x00, 0x26, 0x3B, 0x4A, 0x3F, 0x4B, 0x00, 0x21, ++0xD1, 0x54, 0x62, 0xE0, 0x39, 0x4B, 0x1B, 0x78, 0x00, 0x26, 0x00, 0x2B, 0x4F, 0xD0, 0x00, 0x21, 0x3B, 0x48, 0xB2, 0xF7, ++0x1F, 0xFD, 0x00, 0x25, 0xE7, 0xE7, 0x4B, 0x78, 0x02, 0x2B, 0x27, 0xD0, 0x38, 0x4E, 0x05, 0x22, 0xFF, 0x21, 0x30, 0x00, ++0x77, 0xF7, 0x3E, 0xFB, 0x36, 0x4B, 0xF3, 0x18, 0x36, 0x49, 0x58, 0x5C, 0x1F, 0x22, 0x02, 0x40, 0x5A, 0x54, 0x35, 0x4B, ++0x1B, 0x78, 0xEB, 0x81, 0x2B, 0x82, 0x12, 0x23, 0xAB, 0x81, 0x6B, 0x7A, 0x9A, 0x07, 0x07, 0xD5, 0x02, 0x22, 0x93, 0x43, ++0x6B, 0x72, 0x12, 0x23, 0xAB, 0x83, 0x6B, 0x8B, 0x9B, 0x00, 0x6B, 0x83, 0x6B, 0x7A, 0x00, 0x26, 0x5B, 0x07, 0x24, 0xD5, ++0x12, 0x23, 0xAB, 0x85, 0x6B, 0x8D, 0x5B, 0x00, 0x6B, 0x85, 0x1E, 0xE0, 0x00, 0x23, 0x4B, 0x70, 0xD4, 0xE7, 0x23, 0x4E, ++0x05, 0x22, 0xFF, 0x21, 0x30, 0x00, 0x77, 0xF7, 0x13, 0xFB, 0x21, 0x4B, 0xF0, 0x18, 0x21, 0x4A, 0x81, 0x5C, 0x1F, 0x23, ++0x0B, 0x40, 0x83, 0x54, 0x20, 0x4B, 0xC6, 0x5C, 0x00, 0x2E, 0x0A, 0xD0, 0x13, 0x4A, 0x00, 0x21, 0xD1, 0x54, 0x06, 0xE0, ++0x11, 0x4A, 0x16, 0x4B, 0x00, 0x21, 0xD1, 0x54, 0x00, 0x26, 0x00, 0xE0, 0x00, 0x26, 0x23, 0x00, 0x3A, 0x00, 0x29, 0x00, ++0x40, 0x46, 0x18, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0x21, 0x00, 0x0D, 0x48, 0x7B, 0xF7, 0x72, 0xFB, 0x0C, 0x4B, 0x9C, 0x42, ++0x97, 0xD0, 0x00, 0x2E, 0x03, 0xD0, 0x06, 0x4A, 0x10, 0x4B, 0x01, 0x21, 0xD1, 0x54, 0x28, 0x00, 0x04, 0xBC, 0x90, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0xF6, 0xDF, 0xFF, 0xFF, 0xC4, 0xD2, 0x10, 0x00, 0xEC, 0xA4, 0x16, 0x00, 0x60, 0xE6, 0x10, 0x00, ++0x0A, 0x20, 0x00, 0x00, 0xB8, 0xD2, 0x10, 0x00, 0x3B, 0x20, 0x00, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x39, 0x20, 0x00, 0x00, ++0x05, 0xA8, 0x16, 0x00, 0xE7, 0xFC, 0xFF, 0xFF, 0x1D, 0x03, 0x00, 0x00, 0xE2, 0xE1, 0x10, 0x00, 0xD6, 0x03, 0x00, 0x00, ++0x15, 0xC9, 0x0B, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x06, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x17, 0x4B, 0x9C, 0x42, ++0x24, 0xD0, 0x17, 0x4B, 0x9C, 0x42, 0x13, 0xD1, 0xCB, 0x88, 0x10, 0x2B, 0x01, 0xD9, 0x10, 0x23, 0xCB, 0x80, 0x14, 0x4B, ++0x1B, 0x78, 0x6A, 0x88, 0x9A, 0x42, 0x01, 0xD8, 0x6B, 0x80, 0xAB, 0x80, 0xEB, 0x88, 0xAA, 0x88, 0x69, 0x88, 0x28, 0x89, ++0x00, 0x90, 0x0F, 0x48, 0x7B, 0xF7, 0x26, 0xFB, 0x23, 0x00, 0x3A, 0x00, 0x29, 0x00, 0x30, 0x00, 0x0C, 0x4D, 0xA8, 0x47, ++0x05, 0x00, 0x21, 0x00, 0x0B, 0x48, 0x7B, 0xF7, 0x1B, 0xFB, 0x28, 0x00, 0x03, 0xB0, 0xF0, 0xBD, 0x0A, 0x88, 0x00, 0x21, ++0x02, 0x48, 0xFF, 0xF7, 0x03, 0xFA, 0x00, 0x25, 0xF1, 0xE7, 0xC0, 0x46, 0x0D, 0x08, 0x00, 0x00, 0x13, 0x20, 0x00, 0x00, ++0xE2, 0xE1, 0x10, 0x00, 0xAC, 0xD3, 0x10, 0x00, 0x09, 0x1C, 0x0C, 0x00, 0xBC, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0xCE, 0x46, ++0x47, 0x46, 0x80, 0xB5, 0x14, 0x0A, 0xA4, 0x00, 0x0E, 0x4D, 0x65, 0x59, 0x44, 0x24, 0x2C, 0x5D, 0x03, 0x27, 0x3E, 0x00, ++0x26, 0x40, 0x27, 0x42, 0x11, 0xD0, 0xB9, 0x46, 0xBC, 0x43, 0xA4, 0x46, 0x44, 0x24, 0x67, 0x46, 0x2F, 0x55, 0xB9, 0xF7, ++0x7F, 0xF8, 0x2B, 0x5D, 0x4A, 0x46, 0x93, 0x43, 0x1E, 0x43, 0x2E, 0x55, 0x00, 0x20, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xF8, 0xBD, 0xB9, 0xF7, 0x73, 0xF8, 0xF7, 0xE7, 0x5C, 0xA9, 0x16, 0x00, 0x70, 0xB5, 0x0D, 0x00, 0x14, 0x0A, 0xA2, 0x00, ++0x29, 0x4B, 0xD6, 0x58, 0x0B, 0x2C, 0x06, 0xD8, 0x00, 0x2E, 0x04, 0xD0, 0x44, 0x23, 0xF3, 0x5C, 0xDB, 0x43, 0x9B, 0x07, ++0x11, 0xD1, 0x2D, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x06, 0xD0, 0x2A, 0x00, 0x16, 0x21, 0x20, 0x00, 0x21, 0x4B, 0x98, 0x47, ++0x00, 0x20, 0x70, 0xBD, 0x45, 0x22, 0xB1, 0x5C, 0x7F, 0x23, 0x0B, 0x40, 0xB3, 0x54, 0x00, 0x20, 0xF7, 0xE7, 0x00, 0x21, ++0x20, 0x00, 0xB8, 0xF7, 0x83, 0xFC, 0x00, 0x28, 0x2C, 0xD1, 0x42, 0x23, 0xF3, 0x5A, 0xDB, 0x06, 0x04, 0xD5, 0x28, 0x00, ++0xB8, 0xF7, 0x92, 0xFC, 0x00, 0x28, 0x25, 0xD0, 0x28, 0x00, 0xB8, 0xF7, 0x8D, 0xFC, 0x00, 0x28, 0x0E, 0xD1, 0x2A, 0x00, ++0x00, 0x21, 0x20, 0x00, 0xB8, 0xF7, 0x20, 0xFC, 0x28, 0x00, 0xB8, 0xF7, 0x83, 0xFC, 0x01, 0x00, 0x00, 0x22, 0x20, 0x00, ++0x0D, 0x4B, 0x98, 0x47, 0x01, 0x20, 0xD4, 0xE7, 0x28, 0x00, 0xB8, 0xF7, 0x79, 0xFC, 0x01, 0x28, 0xEB, 0xD0, 0x0A, 0x4B, ++0xDE, 0x6E, 0x28, 0x00, 0xB8, 0xF7, 0x72, 0xFC, 0x01, 0x00, 0x00, 0x23, 0x00, 0x22, 0x20, 0x00, 0xB0, 0x47, 0xE0, 0xE7, ++0x02, 0x20, 0xC2, 0xE7, 0x02, 0x20, 0xC0, 0xE7, 0x5C, 0xA9, 0x16, 0x00, 0x81, 0x45, 0x0C, 0x00, 0xF5, 0x46, 0x0C, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x82, 0xB0, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0x1F, 0x00, ++0x13, 0x0A, 0x9B, 0x00, 0x0E, 0x4A, 0x9B, 0x58, 0x00, 0x2B, 0x0E, 0xD0, 0x89, 0x88, 0x0D, 0x4B, 0x9C, 0x46, 0x61, 0x44, ++0x01, 0xAB, 0x98, 0x46, 0x01, 0x22, 0x18, 0x00, 0xD0, 0xF7, 0x5A, 0xF8, 0x43, 0x46, 0x19, 0x78, 0x08, 0x48, 0x7B, 0xF7, ++0x61, 0xFA, 0x3B, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0xB9, 0xF7, 0x91, 0xF9, 0x02, 0xB0, 0x04, 0xBC, 0x90, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0x5C, 0xA9, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0xC8, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0x05, 0x00, ++0x0E, 0x00, 0x14, 0x00, 0x1F, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x08, 0x4A, 0x9B, 0x58, 0x9B, 0x6A, 0x00, 0x2B, 0x03, 0xD0, ++0x59, 0x7A, 0x06, 0x48, 0x7B, 0xF7, 0x40, 0xFA, 0x3B, 0x00, 0x22, 0x00, 0x31, 0x00, 0x28, 0x00, 0xB9, 0xF7, 0x50, 0xFA, ++0xF8, 0xBD, 0xC0, 0x46, 0x5C, 0xA9, 0x16, 0x00, 0xD4, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0x04, 0x00, 0x06, 0x0A, 0xB2, 0x00, ++0x28, 0x4B, 0xD5, 0x58, 0x28, 0x00, 0x54, 0x30, 0x2A, 0x21, 0xA0, 0xF7, 0x31, 0xFD, 0x00, 0x28, 0x3C, 0xD0, 0xF6, 0xB2, ++0x30, 0x00, 0xAA, 0xF7, 0xB5, 0xF8, 0x20, 0x00, 0x91, 0xF7, 0x02, 0xFA, 0x43, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x23, 0xD0, ++0x1F, 0x4B, 0xEB, 0x5C, 0x00, 0x2B, 0x14, 0xD0, 0x95, 0x23, 0x9B, 0x00, 0xEF, 0x18, 0x38, 0x00, 0x86, 0xF7, 0x80, 0xFA, ++0x36, 0x23, 0xE9, 0x5C, 0x3A, 0x00, 0x30, 0x00, 0xA1, 0xF7, 0x42, 0xF8, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x0A, 0xD0, ++0x2D, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x76, 0xFC, 0x22, 0xE0, 0x36, 0x23, 0xE9, 0x5C, 0x30, 0x00, 0xA1, 0xF7, 0x4B, 0xF8, ++0xF0, 0xE7, 0x2B, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x6B, 0xFC, 0x17, 0xE0, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x04, 0xD0, ++0x60, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x62, 0xFC, 0x0E, 0xE0, 0x61, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x5D, 0xFC, 0x09, 0xE0, ++0x00, 0x23, 0xAC, 0x22, 0x92, 0x00, 0xAB, 0x54, 0x05, 0x4A, 0xAB, 0x54, 0x00, 0x21, 0x20, 0x00, 0x93, 0xF7, 0xA6, 0xFB, ++0xF8, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xAF, 0x02, 0x00, 0x00, 0xB3, 0x02, 0x00, 0x00, 0xF8, 0xB5, 0x05, 0x00, ++0x0E, 0x00, 0x07, 0x0A, 0xBA, 0x00, 0x1D, 0x4B, 0xD4, 0x58, 0x1D, 0x4B, 0xE3, 0x5C, 0x00, 0x2B, 0x0A, 0xD1, 0x1B, 0x4B, ++0x00, 0x22, 0xE2, 0x54, 0x09, 0x3B, 0xE3, 0x5C, 0x00, 0x2B, 0x27, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0x8F, 0xFF, 0xF8, 0xBD, ++0x93, 0xF7, 0xCC, 0xF8, 0x00, 0x28, 0x03, 0xD0, 0x14, 0x4B, 0xE3, 0x5C, 0x00, 0x2B, 0x0C, 0xD0, 0x11, 0x4B, 0xE3, 0x5C, ++0x00, 0x2B, 0xE8, 0xD0, 0x88, 0x23, 0xFF, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0xE3, 0xD0, 0x43, 0x23, 0x01, 0x22, 0xE2, 0x54, ++0xDF, 0xE7, 0x04, 0x33, 0x06, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x79, 0xF7, 0xA3, 0xF8, 0x06, 0x70, 0x80, 0x37, 0x47, 0x80, ++0xCA, 0xF7, 0xFE, 0xFE, 0x43, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xE3, 0xE7, 0x31, 0x00, 0x28, 0x00, 0x93, 0xF7, 0x60, 0xFB, ++0xD5, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xB9, 0x02, 0x00, 0x00, 0xC5, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, ++0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x8C, 0xB0, 0x05, 0x00, 0x0C, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x4A, 0x4B, 0xD6, 0x58, ++0x08, 0x00, 0x79, 0xF7, 0x55, 0xFC, 0x20, 0x28, 0x07, 0xD0, 0x21, 0x00, 0x28, 0x00, 0x47, 0x4B, 0x98, 0x47, 0x0C, 0xB0, ++0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2A, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x69, 0x1C, 0x29, 0x3A, ++0x30, 0x00, 0xCB, 0x30, 0xFF, 0x30, 0xCF, 0xF7, 0x61, 0xFF, 0xFD, 0x23, 0x5B, 0x00, 0x98, 0x46, 0xB0, 0x44, 0x09, 0xAB, ++0x07, 0x93, 0x43, 0x46, 0x06, 0x93, 0x02, 0xA8, 0x10, 0x22, 0x31, 0x00, 0xCB, 0x31, 0xFF, 0x31, 0xCF, 0xF7, 0x52, 0xFF, ++0x6A, 0x46, 0x33, 0x00, 0x6C, 0x33, 0xF1, 0x6E, 0x00, 0x91, 0x9B, 0x88, 0x93, 0x80, 0xCD, 0x23, 0x5B, 0x00, 0xF3, 0x5A, ++0x35, 0x00, 0x9B, 0x35, 0xFF, 0x35, 0x68, 0x88, 0x00, 0x04, 0x18, 0x43, 0xAB, 0x88, 0xE9, 0x88, 0x09, 0x04, 0x19, 0x43, ++0x2B, 0x89, 0x6A, 0x89, 0x12, 0x04, 0x1A, 0x43, 0xAB, 0x89, 0x9C, 0x46, 0xEB, 0x89, 0x1B, 0x04, 0x65, 0x46, 0x2B, 0x43, ++0x83, 0xF7, 0xDA, 0xFD, 0x27, 0x4B, 0xF3, 0x5C, 0x00, 0x2B, 0x1F, 0xD0, 0x39, 0x23, 0xF2, 0x5C, 0xF8, 0xB2, 0x41, 0x46, ++0xA0, 0xF7, 0x93, 0xFE, 0xBE, 0x23, 0x5B, 0x00, 0xF3, 0x5C, 0x00, 0x2B, 0x1B, 0xD0, 0x88, 0x23, 0xFF, 0x33, 0xF3, 0x5C, ++0x00, 0x2B, 0x05, 0xD0, 0x01, 0x23, 0xAC, 0x22, 0x92, 0x00, 0xB3, 0x54, 0x1C, 0x4A, 0xB3, 0x54, 0x37, 0x23, 0xF3, 0x5C, ++0x05, 0x2B, 0x27, 0xD0, 0x00, 0x21, 0x20, 0x00, 0xFF, 0xF7, 0x44, 0xFF, 0x00, 0x20, 0x9C, 0xE7, 0x0C, 0x22, 0x09, 0xA9, ++0x16, 0x4B, 0xF0, 0x18, 0xCF, 0xF7, 0x08, 0xFF, 0xD8, 0xE7, 0x17, 0x33, 0x18, 0x22, 0x00, 0x21, 0x13, 0x48, 0x79, 0xF7, ++0x09, 0xF8, 0x05, 0x00, 0xC0, 0x23, 0x5B, 0x00, 0xF3, 0x5C, 0x83, 0x75, 0x06, 0x22, 0x31, 0x00, 0x72, 0x31, 0xCF, 0xF7, ++0xF7, 0xFE, 0xA8, 0x1D, 0x10, 0x22, 0x31, 0x00, 0x9B, 0x31, 0xFF, 0x31, 0xCF, 0xF7, 0xF0, 0xFE, 0x28, 0x00, 0xCA, 0xF7, ++0x55, 0xFE, 0xC8, 0xE7, 0x05, 0x21, 0x20, 0x00, 0x93, 0xF7, 0x2E, 0xFB, 0x00, 0x20, 0x74, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0x01, 0x4A, 0x0A, 0x00, 0xC5, 0x02, 0x00, 0x00, 0xB3, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, ++0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x0B, 0x4A, 0x9E, 0x58, 0x08, 0x00, 0x79, 0xF7, 0xAE, 0xFB, ++0x24, 0x28, 0x04, 0xD0, 0x21, 0x00, 0x28, 0x00, 0x07, 0x4B, 0x98, 0x47, 0x70, 0xBD, 0xBE, 0x23, 0x5B, 0x00, 0xF3, 0x5C, ++0x00, 0x2B, 0xF5, 0xD1, 0x7D, 0x33, 0xFF, 0x33, 0x01, 0x22, 0xF2, 0x54, 0xF0, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x55, 0x45, 0x0A, 0x00, 0xF8, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x0F, 0x0A, 0xBA, 0x00, ++0x2F, 0x4B, 0xD6, 0x58, 0x02, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x42, 0x78, 0x37, 0x23, 0xF2, 0x54, ++0x08, 0x00, 0x79, 0xF7, 0x83, 0xFB, 0x18, 0x28, 0x04, 0xD8, 0x01, 0x23, 0x83, 0x40, 0x28, 0x4A, 0x13, 0x42, 0x2B, 0xD1, ++0xFB, 0xB2, 0x99, 0x46, 0x18, 0x00, 0xAA, 0xF7, 0x81, 0xF9, 0x80, 0x46, 0x24, 0x4B, 0x01, 0x22, 0xF2, 0x54, 0x21, 0x00, ++0x23, 0x48, 0x78, 0xF7, 0x51, 0xFF, 0x23, 0x4B, 0xF3, 0x5C, 0x00, 0x2B, 0x1F, 0xD1, 0x3C, 0x23, 0xF3, 0x5C, 0x02, 0x2B, ++0x2D, 0xD0, 0x48, 0x46, 0xA9, 0xF7, 0x24, 0xFF, 0x36, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x2A, 0xD1, 0x43, 0x46, 0x58, 0x00, ++0x40, 0x44, 0x40, 0x00, 0x80, 0xB2, 0x7B, 0xF7, 0xE7, 0xF8, 0x02, 0x00, 0x21, 0x00, 0x16, 0x48, 0x78, 0xF7, 0xBE, 0xFE, ++0x19, 0x21, 0x20, 0x00, 0x79, 0xF7, 0xF0, 0xFA, 0x00, 0x20, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF8, 0xBD, 0x04, 0x23, ++0x06, 0x22, 0x00, 0x21, 0x10, 0x48, 0x78, 0xF7, 0x6F, 0xFF, 0x6B, 0x78, 0x03, 0x70, 0x80, 0x37, 0x47, 0x80, 0xCA, 0xF7, ++0xC9, 0xFD, 0x00, 0x23, 0x0A, 0x4A, 0xB3, 0x54, 0x43, 0x22, 0xB3, 0x54, 0xCD, 0xE7, 0x20, 0x00, 0x09, 0x4B, 0x98, 0x47, ++0xCD, 0xE7, 0x43, 0x46, 0x58, 0x00, 0x40, 0x44, 0x80, 0xB2, 0xD4, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x01, 0x00, 0x40, 0x01, ++0xC2, 0x02, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0xB9, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0xF5, 0x3A, 0x09, 0x00, ++0x00, 0x20, 0x70, 0x47, 0xF0, 0xB5, 0x83, 0xB0, 0x0C, 0x00, 0x04, 0x23, 0x5B, 0x4A, 0x00, 0x21, 0x5B, 0x48, 0x78, 0xF7, ++0x41, 0xFF, 0x05, 0x00, 0x21, 0x78, 0x5A, 0x48, 0x7B, 0xF7, 0x40, 0xF8, 0x23, 0x78, 0x01, 0x2B, 0x65, 0xD0, 0x06, 0x2B, ++0x00, 0xD1, 0x80, 0xE0, 0x00, 0x2B, 0x05, 0xD0, 0x28, 0x00, 0xCA, 0xF7, 0x91, 0xFD, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, ++0xA2, 0x78, 0x52, 0x4B, 0x1A, 0x70, 0x00, 0x23, 0x2B, 0x70, 0x6B, 0x70, 0xA3, 0x78, 0xAB, 0x70, 0x4F, 0x4B, 0x1B, 0x78, ++0xEB, 0x70, 0x63, 0x78, 0x01, 0x2B, 0xEB, 0xD1, 0x4D, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0xE7, 0xD1, 0x49, 0x4B, 0x1B, 0x78, ++0x06, 0x2B, 0xE3, 0xD1, 0xFC, 0xF7, 0x66, 0xF9, 0x49, 0x4C, 0x4A, 0x4B, 0x02, 0x22, 0xE2, 0x54, 0x6B, 0x46, 0xDF, 0x1D, ++0x38, 0x00, 0xB2, 0xF7, 0x2D, 0xFC, 0x3E, 0x78, 0x10, 0x23, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x78, 0xF7, 0x06, 0xFF, ++0xB6, 0x01, 0xA6, 0x19, 0xB0, 0x60, 0x3B, 0x78, 0x9B, 0x01, 0xE3, 0x18, 0x9B, 0x68, 0x01, 0x22, 0x9A, 0x70, 0x00, 0x26, ++0x1E, 0x71, 0x80, 0x22, 0x92, 0x01, 0xDA, 0x80, 0x1A, 0x81, 0x1E, 0x70, 0x5E, 0x70, 0x38, 0x78, 0x43, 0x1C, 0x9B, 0x01, ++0xE3, 0x18, 0x06, 0x22, 0x1A, 0x71, 0x38, 0x4A, 0xA3, 0x5C, 0x03, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x83, 0x01, 0xE3, 0x18, ++0x1E, 0x86, 0x5E, 0x86, 0x34, 0x4B, 0x98, 0x47, 0x3B, 0x78, 0x5A, 0x1C, 0x92, 0x01, 0xA2, 0x18, 0x07, 0x21, 0x11, 0x71, ++0x9B, 0x01, 0xE3, 0x18, 0x98, 0x68, 0x0C, 0x38, 0x78, 0xF7, 0x27, 0xFF, 0x3B, 0x78, 0x9B, 0x01, 0xE4, 0x18, 0xA6, 0x60, ++0x9E, 0xE7, 0xA3, 0x78, 0x00, 0x2B, 0x0C, 0xD1, 0x24, 0x4B, 0x1B, 0x78, 0x01, 0x33, 0xDB, 0xB2, 0x10, 0x2B, 0x02, 0xD8, ++0x21, 0x4A, 0x13, 0x70, 0x07, 0xE0, 0x20, 0x4B, 0x10, 0x22, 0x1A, 0x70, 0x03, 0xE0, 0x1E, 0x4A, 0x13, 0x78, 0x01, 0x3B, ++0x13, 0x70, 0x00, 0x23, 0x2B, 0x70, 0x01, 0x33, 0x6B, 0x70, 0xA3, 0x78, 0xAB, 0x70, 0x19, 0x4B, 0x1B, 0x78, 0xEB, 0x70, ++0x80, 0xE7, 0xE2, 0x78, 0x12, 0x02, 0xA3, 0x78, 0x13, 0x43, 0x1B, 0x4A, 0x1B, 0xB2, 0x93, 0x42, 0x00, 0xD0, 0x77, 0xE7, ++0x19, 0x4B, 0x1A, 0x80, 0x61, 0x79, 0x09, 0x02, 0x22, 0x79, 0x0A, 0x43, 0x5A, 0x80, 0xE1, 0x79, 0x09, 0x02, 0xA2, 0x79, ++0x0A, 0x43, 0x9A, 0x80, 0x98, 0x68, 0x00, 0x28, 0x01, 0xD0, 0x79, 0xF7, 0x11, 0xF8, 0x20, 0x7A, 0x10, 0x4E, 0xB0, 0x71, ++0x01, 0x21, 0x78, 0xF7, 0x67, 0xFF, 0xB0, 0x60, 0xB2, 0x79, 0x21, 0x00, 0x09, 0x31, 0xCF, 0xF7, 0x87, 0xFD, 0x59, 0xE7, ++0x57, 0xFD, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0xE0, 0xD3, 0x10, 0x00, 0xD0, 0xE5, 0x10, 0x00, 0x48, 0x06, 0x16, 0x00, ++0xA8, 0xE5, 0x10, 0x00, 0xEC, 0xA4, 0x16, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x6A, 0x04, 0x00, 0x00, 0xE1, 0xEA, 0x0B, 0x00, ++0x88, 0xAC, 0xFF, 0xFF, 0xC4, 0xE5, 0x10, 0x00, 0x09, 0x4B, 0x1B, 0x68, 0xDA, 0x6E, 0x53, 0x1C, 0x0C, 0xD0, 0x08, 0x4B, ++0x19, 0x68, 0x4B, 0x68, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x06, 0x48, 0x83, 0x42, 0x03, 0xD9, 0x04, 0x32, 0x12, 0x01, ++0x12, 0x09, 0x4A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0xF4, 0xE1, 0x10, 0x00, 0x28, 0x27, 0x16, 0x00, 0xFE, 0xFF, 0xFF, 0x07, ++0x30, 0xB5, 0x83, 0xB0, 0x68, 0x46, 0x77, 0xF7, 0xE5, 0xFC, 0x00, 0x9D, 0x34, 0x4C, 0x23, 0x68, 0x01, 0x22, 0x93, 0x43, ++0x23, 0x60, 0x82, 0xF7, 0x51, 0xFE, 0xB1, 0xF7, 0x69, 0xFE, 0x22, 0x68, 0x8C, 0x23, 0x5B, 0x01, 0x13, 0x43, 0x23, 0x60, ++0x2E, 0x4B, 0x1B, 0x68, 0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x41, 0xD0, 0x2A, 0x49, 0x0B, 0x68, 0x2B, 0x4A, 0x1A, 0x40, ++0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x27, 0x4B, 0x5B, 0x68, 0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x36, 0xD0, ++0x23, 0x49, 0x0B, 0x68, 0x25, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x13, 0x43, 0x0B, 0x60, 0x20, 0x4B, 0x9B, 0x68, ++0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x2B, 0xD0, 0x1C, 0x49, 0x0B, 0x68, 0x1F, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x00, ++0x13, 0x43, 0x0B, 0x60, 0x1D, 0x48, 0x78, 0xF7, 0x3F, 0xFA, 0x18, 0x4B, 0x5B, 0x7F, 0x00, 0x2B, 0x1F, 0xD1, 0x7F, 0xF7, ++0x9B, 0xFE, 0x02, 0x28, 0x21, 0xD1, 0x19, 0x49, 0x0B, 0x68, 0x19, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, ++0x0B, 0x60, 0x17, 0x4B, 0x1A, 0x68, 0x01, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x01, 0x31, 0x8A, 0x43, 0x1A, 0x60, ++0x03, 0xB0, 0x30, 0xBD, 0x77, 0xF7, 0x4E, 0xFB, 0xC2, 0xE7, 0x77, 0xF7, 0x5F, 0xFB, 0xCD, 0xE7, 0x77, 0xF7, 0x70, 0xFB, ++0xD8, 0xE7, 0xFC, 0xF7, 0x49, 0xFB, 0x05, 0x4B, 0x00, 0x22, 0x5A, 0x77, 0xD9, 0xE7, 0x7F, 0xF7, 0x75, 0xFE, 0x03, 0x28, ++0xEA, 0xD1, 0xD8, 0xE7, 0x0C, 0x00, 0x60, 0x40, 0x3C, 0x95, 0x16, 0x00, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, ++0xFF, 0xFD, 0xFF, 0xFF, 0x01, 0x20, 0x00, 0x00, 0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xDF, 0xFF, 0x18, 0x00, 0x58, 0x40, ++0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x91, 0x46, 0x9C, 0x4B, 0x1E, 0x68, 0x80, 0x00, 0x84, 0x59, ++0x3C, 0x23, 0xE3, 0x5C, 0x98, 0x46, 0x9A, 0x4B, 0xE3, 0x61, 0xBD, 0xF7, 0x4D, 0xFA, 0x01, 0x90, 0x00, 0x23, 0xA3, 0x62, ++0x00, 0x20, 0xCE, 0xF7, 0x51, 0xFF, 0x96, 0x4B, 0x1D, 0x68, 0xEB, 0x6E, 0x5A, 0x1C, 0x16, 0xD0, 0x63, 0x60, 0x00, 0x23, ++0xA3, 0x60, 0xE7, 0x8E, 0xA7, 0x62, 0x92, 0x49, 0x9A, 0x00, 0x52, 0x58, 0x00, 0x2A, 0x25, 0xD1, 0x01, 0x33, 0x07, 0x2B, ++0xF8, 0xD1, 0x00, 0x23, 0x9C, 0x46, 0x8E, 0x4B, 0x18, 0x00, 0x41, 0x30, 0xFF, 0x30, 0x00, 0x22, 0x00, 0x21, 0x00, 0x91, ++0x1E, 0xE0, 0x8B, 0x4B, 0x1B, 0x68, 0x01, 0x33, 0x09, 0xD0, 0x8A, 0x4B, 0x1B, 0x68, 0x5B, 0x00, 0x01, 0x9A, 0x94, 0x46, ++0x63, 0x44, 0x88, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xDB, 0xE7, 0xA3, 0x8E, 0xE2, 0x8E, 0x9B, 0x1A, 0x5B, 0x00, 0x01, 0x9A, ++0x94, 0x46, 0x63, 0x44, 0x82, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xD0, 0xE7, 0x01, 0x23, 0x9C, 0x46, 0xDB, 0xE7, 0x40, 0x33, ++0x83, 0x42, 0x07, 0xD0, 0x19, 0x78, 0x09, 0x29, 0xF9, 0xD1, 0x01, 0x32, 0xD2, 0xB2, 0x08, 0x39, 0x00, 0x91, 0xF4, 0xE7, ++0xEB, 0x6E, 0x59, 0x1C, 0x21, 0xD0, 0x63, 0x60, 0x75, 0x4B, 0x9A, 0x88, 0x77, 0x4B, 0x9A, 0x42, 0x02, 0xD9, 0x77, 0x4B, ++0x9C, 0x46, 0x62, 0x44, 0x76, 0x4B, 0x7B, 0x43, 0x93, 0x42, 0x00, 0xD9, 0x13, 0x00, 0x75, 0x4A, 0x93, 0x42, 0x00, 0xD2, ++0x13, 0x00, 0x23, 0x61, 0xB3, 0x68, 0x80, 0x22, 0x52, 0x05, 0x93, 0x42, 0x3B, 0xD2, 0x62, 0x68, 0xD3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0x6F, 0x4A, 0x93, 0x42, 0x34, 0xD8, 0x6E, 0x4B, 0x98, 0x47, 0xAF, 0xE0, 0x65, 0x4B, 0x1B, 0x68, 0x01, 0x33, ++0x07, 0xD0, 0x64, 0x4B, 0x18, 0x68, 0x01, 0x9B, 0x1D, 0x18, 0x63, 0x48, 0x05, 0x40, 0x65, 0x60, 0xD2, 0xE7, 0x63, 0x46, ++0x00, 0x2B, 0x03, 0xD1, 0x66, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x08, 0xD0, 0x5C, 0x4B, 0x18, 0x68, 0x80, 0x00, 0x01, 0x9B, ++0xC5, 0x18, 0x5B, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xC2, 0xE7, 0x00, 0x9B, 0x00, 0x2B, 0xBF, 0xD0, 0x5F, 0x4B, 0x1B, 0x68, ++0x01, 0x2B, 0x06, 0xD9, 0xD3, 0x01, 0x01, 0x9A, 0x9D, 0x18, 0x54, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xB4, 0xE7, 0x51, 0x4B, ++0x1B, 0x68, 0x01, 0x9A, 0xD5, 0x18, 0x50, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xAC, 0xE7, 0x4B, 0x46, 0x00, 0x2B, 0x05, 0xD1, ++0x55, 0x4A, 0x26, 0x33, 0xD3, 0x5C, 0xA3, 0x75, 0x63, 0x68, 0xE3, 0x62, 0x52, 0x4A, 0x27, 0x23, 0xD2, 0x5C, 0x18, 0x3B, ++0x1A, 0x40, 0xC0, 0x23, 0xDB, 0x01, 0x13, 0x43, 0xA3, 0x82, 0x3F, 0x23, 0xE1, 0x5C, 0x1B, 0x33, 0x42, 0x46, 0x53, 0x43, ++0x4C, 0x4A, 0x98, 0x18, 0x8A, 0x00, 0x11, 0x43, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x02, 0x80, 0x21, 0x8D, 0x49, 0x4A, ++0x9A, 0x18, 0x11, 0x80, 0x3E, 0x22, 0xA2, 0x5C, 0x0A, 0x3A, 0x01, 0x2A, 0x5A, 0xD9, 0x46, 0x4A, 0x98, 0x18, 0xA1, 0x6A, ++0x80, 0x22, 0xD2, 0x01, 0x91, 0x42, 0x00, 0xD3, 0x43, 0x49, 0x44, 0x4A, 0x0A, 0x43, 0x92, 0xB2, 0x02, 0x80, 0x00, 0x21, ++0x42, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x32, 0x7D, 0x92, 0x07, 0x14, 0xD5, 0xF1, 0x7B, 0x09, 0x02, 0xB2, 0x7B, 0x0A, 0x43, ++0x3E, 0x49, 0x59, 0x18, 0x0A, 0x80, 0x71, 0x7C, 0x09, 0x02, 0x32, 0x7C, 0x0A, 0x43, 0x3C, 0x49, 0x59, 0x18, 0x0A, 0x80, ++0xF1, 0x7C, 0x09, 0x02, 0xB2, 0x7C, 0x0A, 0x43, 0x39, 0x49, 0x59, 0x18, 0x0A, 0x80, 0x71, 0x7D, 0xB5, 0x7D, 0x38, 0x4A, ++0x97, 0x78, 0x7A, 0x1E, 0x97, 0x41, 0x30, 0x7D, 0x80, 0x07, 0xC0, 0x0F, 0x01, 0x22, 0x94, 0x46, 0x00, 0x2D, 0x00, 0xD1, ++0x84, 0x46, 0x33, 0x4A, 0x9E, 0x18, 0x09, 0x02, 0xAA, 0x01, 0x0A, 0x43, 0xFF, 0x00, 0x3A, 0x43, 0x80, 0x00, 0x02, 0x43, ++0x61, 0x46, 0x0A, 0x43, 0x32, 0x80, 0x2E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x1F, 0x21, 0x8A, 0x43, 0x11, 0x00, ++0x3E, 0x22, 0xA2, 0x5C, 0x0A, 0x43, 0x1A, 0x80, 0x20, 0x00, 0xCC, 0xF7, 0x71, 0xFF, 0x00, 0x28, 0x0D, 0xD1, 0x00, 0x23, ++0x47, 0x22, 0xA3, 0x54, 0x63, 0x87, 0x03, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x22, 0x49, 0x23, 0x4A, ++0x9A, 0x18, 0x11, 0x80, 0x9F, 0xE7, 0x22, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEE, 0xE7, ++0xE4, 0x29, 0x16, 0x00, 0x71, 0x00, 0x10, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x38, 0x27, 0x16, 0x00, 0x70, 0xA6, 0x16, 0x00, ++0x5C, 0xAB, 0x16, 0x00, 0xE4, 0xE1, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x0F, 0xC4, 0x09, 0x00, 0x00, 0x3C, 0xF6, 0xFF, 0xFF, ++0xE2, 0x04, 0x00, 0x00, 0xA6, 0x0E, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x39, 0xC2, 0x0C, 0x00, 0xF0, 0x29, 0x16, 0x00, ++0x50, 0xE0, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x7A, 0x01, 0x61, 0x40, 0x96, 0x01, 0x61, 0x40, 0x90, 0x01, 0x61, 0x40, ++0xFF, 0x3F, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xBC, 0x01, 0x61, 0x40, 0x7C, 0x01, 0x61, 0x40, 0x7E, 0x01, 0x61, 0x40, ++0x80, 0x01, 0x61, 0x40, 0xE8, 0x29, 0x16, 0x00, 0x8A, 0x01, 0x61, 0x40, 0x76, 0x01, 0x61, 0x40, 0x72, 0x3E, 0x00, 0x00, ++0x9E, 0x01, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x10, 0x23, 0x0F, 0x4A, 0x00, 0x21, 0x0F, 0x48, 0x78, 0xF7, ++0x53, 0xFC, 0x00, 0x22, 0x02, 0x70, 0x05, 0x23, 0x43, 0x70, 0x04, 0x3B, 0x83, 0x70, 0x80, 0x21, 0x89, 0x00, 0x81, 0x80, ++0xFE, 0x39, 0xFF, 0x39, 0x81, 0x71, 0xC3, 0x71, 0x0B, 0x31, 0x01, 0x72, 0x43, 0x72, 0x53, 0x31, 0x41, 0x81, 0x57, 0x39, ++0x81, 0x81, 0x83, 0x73, 0xC2, 0x73, 0xCA, 0xF7, 0x9B, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0xC0, 0x46, 0x53, 0xFD, 0x00, 0x00, ++0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x10, 0x4A, 0x11, 0x68, 0xA0, 0x23, 0x5B, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x0E, 0x4C, ++0x01, 0x23, 0x23, 0x60, 0x05, 0x20, 0x7F, 0xF7, 0x10, 0xFD, 0x00, 0x23, 0x23, 0x60, 0x0B, 0x49, 0x04, 0x22, 0x0B, 0x68, ++0x1A, 0x42, 0xFC, 0xD0, 0x06, 0x4A, 0x13, 0x68, 0x08, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x08, 0x4C, 0x01, 0x23, 0x23, 0x60, ++0x05, 0x20, 0x7F, 0xF7, 0xFE, 0xFC, 0x00, 0x23, 0x23, 0x60, 0x10, 0xBD, 0x58, 0x40, 0x34, 0x40, 0x54, 0x40, 0x34, 0x40, ++0x80, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xEB, 0xFF, 0x48, 0x20, 0x62, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x04, 0x90, 0x0F, 0x00, 0x16, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x11, 0x00, ++0x19, 0x40, 0x05, 0x91, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x04, 0x9A, 0x93, 0x00, 0xA3, 0x49, 0x8C, 0x46, 0x63, 0x44, ++0x1C, 0x68, 0xA2, 0x46, 0xA1, 0x4B, 0x63, 0x62, 0xE5, 0x6C, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD5, 0x4F, 0xE2, ++0x93, 0x00, 0x9E, 0x4A, 0x9B, 0x58, 0x1A, 0x8A, 0x00, 0x2A, 0x0E, 0xD0, 0x84, 0x23, 0xE3, 0x5A, 0x5B, 0x07, 0x00, 0xD5, ++0x36, 0xE2, 0x9A, 0x4B, 0x23, 0x61, 0xA2, 0x6E, 0x99, 0x4B, 0x1B, 0x68, 0x9A, 0x42, 0x00, 0xD1, 0x3C, 0xE2, 0x96, 0x4B, ++0x2F, 0xE2, 0x06, 0x32, 0x1A, 0x82, 0x96, 0x48, 0x7A, 0xF7, 0xD0, 0xFC, 0xEA, 0xE7, 0x96, 0x23, 0x00, 0x22, 0xE2, 0x54, ++0x00, 0x2E, 0x00, 0xD1, 0x34, 0xE2, 0x20, 0x3B, 0xE3, 0x5A, 0x00, 0x2B, 0x00, 0xD1, 0x2F, 0xE2, 0x80, 0x21, 0xC9, 0x00, ++0x8E, 0x4A, 0x02, 0x40, 0x8A, 0x42, 0x00, 0xD0, 0x28, 0xE2, 0x02, 0x07, 0x00, 0xD5, 0x25, 0xE2, 0x4A, 0x22, 0xA2, 0x5C, ++0x00, 0x2A, 0x00, 0xD0, 0x20, 0xE2, 0xA2, 0x6E, 0x5A, 0x43, 0x55, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x22, 0xA1, 0x5A, ++0x5B, 0x18, 0xA3, 0x52, 0x96, 0x23, 0x7D, 0x3A, 0xE2, 0x54, 0x7B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x81, 0x4A, 0x93, 0x42, ++0x00, 0xD8, 0x13, 0xE2, 0xE7, 0x6D, 0x2B, 0xE2, 0x46, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x26, 0xE2, 0x7C, 0x33, ++0xE3, 0x5A, 0x7E, 0x22, 0xA2, 0x5A, 0x9B, 0x18, 0x48, 0x22, 0xA2, 0x5A, 0x9B, 0x1A, 0x79, 0x4A, 0x9B, 0xB2, 0x93, 0x42, ++0x00, 0xD9, 0x19, 0xE2, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x21, 0xD1, 0x40, 0x33, 0xE3, 0x5A, 0x5D, 0x19, 0x2D, 0x01, ++0x2D, 0x09, 0xC3, 0x07, 0x00, 0xD4, 0xCA, 0xE1, 0x44, 0x23, 0xE3, 0x5A, 0x5B, 0x08, 0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, ++0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, 0xE3, 0x66, 0x46, 0x23, 0x01, 0x22, ++0xE2, 0x54, 0x48, 0x33, 0xE0, 0x5C, 0x68, 0x4B, 0x98, 0x47, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD4, 0xBB, 0xE1, ++0x7C, 0x23, 0xE2, 0x5A, 0x02, 0x33, 0xE3, 0x5A, 0xD2, 0x18, 0x48, 0x23, 0xE3, 0x5A, 0xD2, 0x1A, 0x92, 0xB2, 0x53, 0x1E, ++0x9B, 0xB2, 0x00, 0x2A, 0x0A, 0xD0, 0xA1, 0x6E, 0x2F, 0x00, 0x5E, 0x4A, 0x7F, 0x1A, 0x3F, 0x01, 0x3F, 0x09, 0x01, 0x3B, ++0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD1, 0xDB, 0xE1, 0x2F, 0x00, 0xD9, 0xE1, 0x00, 0x2B, 0x00, 0xD1, 0x5F, 0xE1, 0x68, 0xE1, ++0x01, 0x3B, 0x1B, 0x01, 0x1B, 0x09, 0x56, 0x4A, 0x94, 0x46, 0xE0, 0x44, 0x78, 0xE1, 0x2B, 0x00, 0x63, 0x60, 0x50, 0x46, ++0xCC, 0xF7, 0xFA, 0xFD, 0x00, 0x28, 0x00, 0xD1, 0x2E, 0xE1, 0xA3, 0x7D, 0x50, 0x49, 0x2F, 0x22, 0x8A, 0x5C, 0x9B, 0x18, ++0xA3, 0x75, 0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0x02, 0xD5, 0x03, 0x9B, 0x00, 0x2B, 0x4C, 0xD0, 0xA3, 0x6E, 0x9C, 0x46, ++0x65, 0x44, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x22, 0xA3, 0x5A, 0x01, 0x33, 0xA3, 0x52, 0xA3, 0x7D, 0x01, 0x33, 0xA3, 0x75, ++0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0x8C, 0xE0, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x99, 0x45, 0x00, 0xD8, ++0xF5, 0xE0, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0xCF, 0xD5, 0x72, 0x23, 0xE3, 0x5E, 0x98, 0x46, 0x63, 0x6D, 0xEE, 0x1A, ++0x36, 0x01, 0x36, 0x09, 0x77, 0xF7, 0x3C, 0xFF, 0x14, 0x23, 0x00, 0x28, 0x02, 0xD1, 0xC4, 0x33, 0x37, 0x4A, 0xD3, 0x5A, ++0x7A, 0x22, 0xA0, 0x5A, 0xC0, 0x18, 0x70, 0x43, 0xC8, 0x21, 0xC9, 0x00, 0xCE, 0xF7, 0xA2, 0xFD, 0x20, 0x30, 0x46, 0x00, ++0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0x00, 0xD5, 0x04, 0xE1, 0x74, 0x23, 0xE2, 0x5A, 0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, ++0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0xF6, 0x18, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD0, 0x05, 0xE1, 0x46, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x8E, 0xE1, 0xFF, 0xE0, 0xF7, 0xF7, 0xB1, 0xFE, 0x00, 0x28, 0xAE, 0xD0, 0x24, 0x4B, ++0x1A, 0x78, 0x01, 0x23, 0x00, 0x2A, 0x08, 0xD0, 0x22, 0x4B, 0x1B, 0x78, 0x01, 0x3B, 0x5A, 0x1E, 0x93, 0x41, 0x5B, 0x42, ++0x06, 0x22, 0x93, 0x43, 0x08, 0x33, 0xA0, 0x6E, 0x02, 0x00, 0x5A, 0x43, 0x80, 0x21, 0x49, 0x00, 0x8A, 0x42, 0x0C, 0xD9, ++0x5A, 0x1E, 0xD2, 0xB2, 0x42, 0x43, 0x8C, 0x46, 0x00, 0xE0, 0x0A, 0x00, 0x01, 0x3B, 0xDB, 0xB2, 0x62, 0x45, 0x02, 0xD9, ++0x11, 0x1A, 0x00, 0x2B, 0xF7, 0xD1, 0x55, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x21, 0x62, 0x5A, 0xD3, 0x18, 0x63, 0x52, ++0x01, 0x23, 0x03, 0x93, 0x8B, 0xE7, 0xC0, 0x46, 0xF4, 0x29, 0x16, 0x00, 0x95, 0x9D, 0x10, 0x00, 0x5C, 0xA9, 0x16, 0x00, ++0xDE, 0x0D, 0x00, 0x00, 0x64, 0xE6, 0x10, 0x00, 0xEC, 0xD3, 0x10, 0x00, 0x04, 0x04, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, ++0xFE, 0x7F, 0x00, 0x00, 0xF1, 0x12, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, ++0x8C, 0xA9, 0x16, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0x46, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, ++0x6D, 0xE7, 0x7C, 0x33, 0xE3, 0x5A, 0x7E, 0x22, 0xA2, 0x5A, 0x9B, 0x18, 0x48, 0x22, 0xA2, 0x5A, 0x9B, 0x1A, 0x9F, 0x4A, ++0x9B, 0xB2, 0x93, 0x42, 0x00, 0xD9, 0x60, 0xE7, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x26, 0xD1, 0x40, 0x33, 0xE3, 0x5A, ++0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD4, 0x76, 0xE0, 0x44, 0x23, 0xE3, 0x5A, ++0x5B, 0x08, 0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, ++0xE3, 0x6B, 0xE3, 0x66, 0x8E, 0x23, 0xE0, 0x5C, 0x8E, 0x4B, 0x98, 0x47, 0x46, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xE3, 0x6E, ++0x99, 0x46, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x01, 0xD4, 0x47, 0x23, 0xE2, 0x54, 0x7C, 0x23, 0xE2, 0x5A, 0x02, 0x33, ++0xE3, 0x5A, 0xD2, 0x18, 0x48, 0x23, 0xE3, 0x5A, 0xD2, 0x1A, 0x92, 0xB2, 0x53, 0x1E, 0x9B, 0xB2, 0x00, 0x2A, 0x0A, 0xD0, ++0xA1, 0x6E, 0x2F, 0x00, 0x81, 0x4A, 0x7F, 0x1A, 0x3F, 0x01, 0x3F, 0x09, 0x01, 0x3B, 0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD1, ++0x1D, 0xE7, 0x2F, 0x00, 0x1B, 0xE7, 0x7D, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x7C, 0x4B, 0x1B, 0x68, 0x00, 0x21, 0x1B, 0x02, ++0x0A, 0xD5, 0x7B, 0x48, 0x7A, 0xF7, 0x2E, 0xFB, 0x84, 0x23, 0xE2, 0x5A, 0x92, 0x07, 0xD2, 0x17, 0x4F, 0x3B, 0x9A, 0x43, ++0x3E, 0x32, 0x0A, 0xE0, 0x01, 0x20, 0xF8, 0xF7, 0x85, 0xFA, 0x01, 0x21, 0xEF, 0xE7, 0x84, 0x23, 0xE3, 0x5A, 0x08, 0x22, ++0x9B, 0x07, 0x00, 0xD4, 0xB6, 0xE0, 0x01, 0x21, 0x04, 0x98, 0x70, 0x4B, 0x98, 0x47, 0x05, 0x9B, 0x00, 0x2B, 0x00, 0xD1, ++0x62, 0xB6, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x8F, 0x23, 0x00, 0x22, ++0xE2, 0x54, 0xE5, 0x64, 0x0B, 0x3B, 0xE3, 0x5A, 0x9A, 0x07, 0x02, 0xD5, 0x62, 0x4A, 0x00, 0x21, 0x11, 0x70, 0xDB, 0x07, ++0xE7, 0xD5, 0x70, 0x23, 0x42, 0x46, 0xE2, 0x52, 0x1C, 0x36, 0x26, 0x65, 0xE1, 0xE7, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, ++0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, 0xE3, 0x66, 0x91, 0xE7, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, ++0x91, 0xE0, 0xA2, 0x6E, 0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, 0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0x5B, 0x08, 0xB3, 0x42, ++0xBF, 0xD9, 0x73, 0x08, 0x9B, 0x46, 0x54, 0x49, 0x18, 0x00, 0xCE, 0xF7, 0x81, 0xFC, 0x01, 0x00, 0x2B, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0x40, 0x01, 0x40, 0x1A, 0x80, 0x00, 0x40, 0x18, 0x82, 0x00, 0x80, 0x18, 0x42, 0x46, 0x59, 0x46, 0x52, 0x1A, ++0x82, 0x18, 0x90, 0x46, 0x00, 0xD5, 0x7F, 0xE6, 0x42, 0x46, 0xA2, 0x60, 0x22, 0x6E, 0x92, 0x19, 0x22, 0x61, 0x81, 0xE6, ++0xE3, 0x6E, 0x99, 0x46, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x08, 0x22, 0x99, 0x45, 0xA0, 0xD9, 0x00, 0x23, 0x03, 0x93, ++0x1C, 0x26, 0x98, 0x46, 0x9F, 0xE6, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, ++0xE3, 0x66, 0x46, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x47, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x3F, 0xE6, 0x39, 0x4B, 0x23, 0x61, ++0xA2, 0x6E, 0xA1, 0x6D, 0x00, 0x20, 0x01, 0x90, 0x00, 0x93, 0x00, 0x23, 0x20, 0x00, 0xF7, 0xF7, 0xC1, 0xFB, 0x35, 0x4B, ++0xA2, 0x6E, 0x1A, 0x60, 0x84, 0x23, 0xE0, 0x5A, 0xC3, 0x43, 0x9B, 0x07, 0x00, 0xD1, 0xC4, 0xE5, 0x7B, 0x1B, 0x1B, 0x01, ++0x1B, 0x09, 0x30, 0x4A, 0x93, 0x42, 0x13, 0xD8, 0xA1, 0x6E, 0x7E, 0x23, 0xE2, 0x5A, 0x01, 0x32, 0x92, 0xB2, 0x2C, 0x4E, ++0x4D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x03, 0x92, 0x01, 0x32, 0x92, 0xB2, 0x7B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0xB3, 0x42, ++0xF4, 0xD9, 0x7E, 0x23, 0x03, 0x9A, 0xE2, 0x52, 0xE7, 0x6D, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0xD3, 0xE5, ++0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0xAB, 0xD4, 0x14, 0x23, 0xA3, 0x75, 0xA2, 0x6E, 0x53, 0x00, 0x9B, 0x18, 0x5B, 0x00, ++0x99, 0x46, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x4B, 0x45, 0xA7, 0xD3, 0x12, 0x4B, 0x1B, 0x78, 0x01, 0x33, 0xDB, 0xB2, ++0x03, 0x2B, 0x00, 0xD9, 0x23, 0xE7, 0x0F, 0x4A, 0x13, 0x70, 0x3E, 0x22, 0x3D, 0xE7, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x00, 0xD1, 0x68, 0xE7, 0x00, 0x23, 0x47, 0x22, 0xA2, 0x5C, 0x00, 0x2A, 0x00, 0xD0, 0xFF, 0xE5, 0x44, 0x23, 0xE2, 0x5A, ++0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, 0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0xF6, 0x18, 0x62, 0xE7, 0xFE, 0x7F, 0x00, 0x00, ++0xF1, 0x12, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xE6, 0x10, 0x00, 0x58, 0x40, 0x34, 0x40, 0xF8, 0xD3, 0x10, 0x00, ++0x65, 0x17, 0x0D, 0x00, 0x71, 0x02, 0x00, 0x00, 0x42, 0x0E, 0x00, 0x00, 0x64, 0xE6, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x07, ++0xF8, 0xB5, 0x04, 0x1E, 0x32, 0xD0, 0xA1, 0xF7, 0x55, 0xFD, 0x05, 0x00, 0x8F, 0x23, 0xE6, 0x5C, 0x00, 0x2E, 0x17, 0xD1, ++0xE3, 0x6C, 0xA2, 0x6E, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x64, 0x7E, 0x22, 0xA3, 0x5A, 0x01, 0x33, ++0xA3, 0x52, 0xA3, 0x7D, 0x13, 0x49, 0x4F, 0x3A, 0x8A, 0x5C, 0x9B, 0x18, 0xA3, 0x75, 0x8E, 0x23, 0xE0, 0x5C, 0x00, 0x22, ++0x29, 0x00, 0xFF, 0xF7, 0x01, 0xFD, 0xF8, 0xBD, 0x67, 0x68, 0xA1, 0xF7, 0x35, 0xFD, 0x03, 0x00, 0x3A, 0x00, 0x31, 0x00, ++0x0B, 0x48, 0x7A, 0xF7, 0x03, 0xFA, 0x8F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0xDA, 0xD0, 0x09, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD3, 0xE7, 0x05, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0xE3, 0xE7, 0xC0, 0x46, 0x7C, 0x91, 0x0D, 0x00, 0x08, 0xD4, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x80, 0x46, 0x0F, 0x00, 0x16, 0x00, 0x1D, 0x00, 0x02, 0x21, 0x10, 0x20, 0x78, 0xF7, 0xAD, 0xF9, 0x04, 0x00, ++0x04, 0x23, 0x03, 0x70, 0xFB, 0x33, 0x43, 0x70, 0xF2, 0x3B, 0x83, 0x70, 0x43, 0x46, 0xC3, 0x70, 0x47, 0x60, 0x86, 0x60, ++0xC5, 0x60, 0x1F, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x1A, 0xD0, 0x01, 0x2B, 0x30, 0xD1, 0x1D, 0x4B, 0x1B, 0x68, 0x00, 0x2B, ++0x0D, 0xD0, 0x0A, 0x25, 0x1B, 0x4F, 0x80, 0x26, 0xB6, 0x02, 0xE8, 0x20, 0x7F, 0xF7, 0xA7, 0xF9, 0x3B, 0x68, 0x33, 0x42, ++0x25, 0xD1, 0x01, 0x3D, 0xED, 0xB2, 0x00, 0x2D, 0xF5, 0xD1, 0x00, 0x23, 0x15, 0x4A, 0x10, 0x21, 0x20, 0x00, 0x81, 0xF7, ++0x6D, 0xFC, 0x17, 0xE0, 0x13, 0x48, 0x14, 0x49, 0x01, 0x22, 0x43, 0x58, 0x1A, 0x42, 0xFC, 0xD1, 0x10, 0x4B, 0x12, 0x4A, ++0x9C, 0x50, 0x12, 0x4A, 0x99, 0x58, 0x10, 0x20, 0x01, 0x43, 0x99, 0x50, 0x81, 0x21, 0x49, 0x01, 0x5A, 0x58, 0x02, 0x43, ++0x5A, 0x50, 0x0B, 0x49, 0x5A, 0x58, 0x0F, 0x38, 0x02, 0x43, 0x5A, 0x50, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0A, 0x4B, ++0x80, 0x22, 0x92, 0x02, 0x1A, 0x60, 0xD8, 0xE7, 0xA8, 0xE5, 0x10, 0x00, 0x28, 0x25, 0x16, 0x00, 0x1C, 0x41, 0x04, 0x40, ++0x19, 0x74, 0x08, 0x00, 0x00, 0x00, 0x07, 0x40, 0x08, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, ++0x10, 0xB5, 0x01, 0x00, 0x13, 0x00, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x00, 0xD4, 0x72, 0xB6, 0x74, 0x46, 0x0E, 0x4A, ++0x94, 0x42, 0x0F, 0xD0, 0x22, 0x00, 0x0D, 0x48, 0x7A, 0xF7, 0x6A, 0xF9, 0x23, 0x00, 0x00, 0x22, 0x00, 0x21, 0x57, 0x20, ++0xFF, 0xF7, 0x7A, 0xFF, 0x09, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x05, 0xD0, 0x72, 0xB6, 0xFE, 0xE7, 0x07, 0x48, 0x7A, 0xF7, ++0x5B, 0xF9, 0x10, 0xBD, 0x06, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0xF4, 0xE7, 0xC0, 0x46, 0xB9, 0x25, 0x0D, 0x00, ++0x40, 0xD4, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, 0x18, 0xD4, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x82, 0xB0, ++0x04, 0x00, 0x0D, 0x00, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x00, 0xD4, 0x72, 0xB6, 0x76, 0x46, 0x00, 0x93, 0x33, 0x00, ++0x2A, 0x00, 0x21, 0x00, 0x09, 0x48, 0x7A, 0xF7, 0x39, 0xF9, 0x33, 0x00, 0x2A, 0x00, 0x21, 0x00, 0x57, 0x20, 0xFF, 0xF7, ++0x49, 0xFF, 0x06, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x01, 0xD0, 0x72, 0xB6, 0xFE, 0xE7, 0x04, 0x4B, 0x80, 0x22, 0xD2, 0x04, ++0x1A, 0x60, 0xF8, 0xE7, 0x64, 0xD4, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x65, 0x4B, 0x1E, 0x68, 0x07, 0x20, 0xA1, 0xF7, 0xA4, 0xF9, ++0x00, 0x28, 0x06, 0xD1, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x5F, 0x4A, ++0xD5, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0xDC, 0x00, 0xE4, 0x1A, 0x64, 0x00, 0x5C, 0x4B, 0xE3, 0x18, 0x1D, 0x88, 0xAD, 0xB2, ++0xA1, 0xF7, 0x62, 0xF9, 0x6B, 0x07, 0xE9, 0xD1, 0x3A, 0x23, 0xF3, 0x5C, 0x02, 0x2B, 0x52, 0xD0, 0x57, 0x4B, 0xE3, 0x18, ++0x1B, 0x88, 0x9B, 0xB2, 0x98, 0x46, 0x56, 0x4B, 0xE2, 0x18, 0x13, 0x88, 0x5B, 0x06, 0x1B, 0x0F, 0x02, 0x2B, 0x08, 0xD0, ++0x10, 0x88, 0x40, 0x06, 0x00, 0x0F, 0x52, 0x4B, 0xDF, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xB8, 0x47, 0x39, 0x23, ++0xF3, 0x5C, 0x00, 0x2B, 0x01, 0xD0, 0xEB, 0x05, 0x53, 0xD4, 0x10, 0x23, 0xFF, 0x22, 0x00, 0x21, 0x4B, 0x48, 0x77, 0xF7, ++0xD5, 0xFF, 0x07, 0x00, 0x00, 0x23, 0x83, 0x73, 0xFB, 0x1D, 0xBA, 0x1D, 0x02, 0x92, 0x05, 0xAA, 0x01, 0x92, 0x00, 0x22, ++0x00, 0x92, 0x3A, 0x00, 0x00, 0x21, 0x40, 0x46, 0xB0, 0xF7, 0x7C, 0xFC, 0x43, 0x4B, 0x19, 0x88, 0x43, 0x4B, 0x1B, 0x88, ++0x05, 0x9A, 0x92, 0x00, 0x09, 0x04, 0x0B, 0x43, 0xD3, 0x1A, 0x6A, 0xD4, 0xDB, 0x03, 0x5B, 0x0C, 0x7B, 0x81, 0x3F, 0x4B, ++0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x3B, 0x73, 0xED, 0x05, 0xED, 0x0F, 0x7D, 0x73, 0x38, 0x00, 0x77, 0xF7, 0xD8, 0xFF, ++0x3C, 0x23, 0xF3, 0x5C, 0x3B, 0x22, 0xB2, 0x5C, 0x9A, 0x42, 0x00, 0xD8, 0x96, 0xE7, 0x01, 0x33, 0x3C, 0x22, 0xB3, 0x54, ++0x92, 0xE7, 0x37, 0x33, 0xF3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x8D, 0xE7, 0xEB, 0x05, 0x00, 0xD4, 0x8A, 0xE7, 0x07, 0x20, ++0xA1, 0xF7, 0x2A, 0xF9, 0x00, 0x28, 0x00, 0xD1, 0x84, 0xE7, 0x25, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, ++0x9B, 0x1A, 0x5B, 0x00, 0x22, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0xA1, 0xF7, 0xEE, 0xF8, 0x76, 0xE7, 0x07, 0x20, ++0xA1, 0xF7, 0x16, 0xF9, 0x00, 0x28, 0xA6, 0xD0, 0x1B, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, ++0x5B, 0x00, 0x19, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x52, 0x07, 0x02, 0xD0, 0xA1, 0xF7, 0xDA, 0xF8, 0x97, 0xE7, 0x1D, 0x4A, ++0x9A, 0x18, 0x11, 0x88, 0x8A, 0xB2, 0x91, 0x46, 0x1B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0xDB, 0x08, 0x9B, 0x46, ++0xFF, 0x23, 0x5A, 0x46, 0x1A, 0x40, 0x92, 0x46, 0x13, 0x00, 0x10, 0x33, 0xFF, 0x22, 0x00, 0x21, 0x0F, 0x48, 0x77, 0xF7, ++0x5D, 0xFF, 0x07, 0x00, 0x5B, 0x46, 0x83, 0x73, 0x12, 0x49, 0x49, 0x44, 0x0F, 0x30, 0x52, 0x46, 0xCE, 0xF7, 0x4C, 0xFE, ++0xA1, 0xF7, 0xB8, 0xF8, 0x7E, 0xE7, 0x80, 0x22, 0x52, 0x05, 0x94, 0x46, 0x63, 0x44, 0x8F, 0xE7, 0x18, 0x27, 0x16, 0x00, ++0x20, 0xA3, 0x16, 0x00, 0x92, 0x69, 0x61, 0x40, 0x9C, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, ++0x01, 0x05, 0x00, 0x00, 0xFA, 0x67, 0x61, 0x40, 0xF8, 0x67, 0x61, 0x40, 0x98, 0x69, 0x61, 0x40, 0x9A, 0x69, 0x61, 0x40, ++0x96, 0x69, 0x61, 0x40, 0x00, 0x00, 0x61, 0x40, 0x70, 0xB5, 0xA1, 0xF7, 0x5F, 0xFB, 0x05, 0x00, 0x0F, 0x4B, 0x1C, 0x68, ++0x00, 0x2C, 0x06, 0xD1, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x70, 0xBD, 0xFF, 0xF7, ++0x03, 0xFF, 0x01, 0x21, 0x20, 0x00, 0xCC, 0xF7, 0x81, 0xFB, 0x3A, 0x23, 0xE3, 0x5C, 0x02, 0x2B, 0x06, 0xD0, 0x07, 0x4B, ++0x1B, 0x7D, 0xA3, 0x75, 0x65, 0x60, 0x06, 0x4B, 0x98, 0x47, 0xED, 0xE7, 0x05, 0x4B, 0x98, 0x47, 0xEA, 0xE7, 0xC0, 0x46, ++0x18, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0xE5, 0xC1, 0x0A, 0x00, 0x99, 0xC1, 0x0A, 0x00, ++0x70, 0xB5, 0x0D, 0x00, 0x14, 0x00, 0x07, 0x29, 0x06, 0xD0, 0x11, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, ++0x28, 0x00, 0xB0, 0x47, 0x01, 0x2C, 0x0E, 0xD9, 0x04, 0x2C, 0x0F, 0xD1, 0x0C, 0x4B, 0x1C, 0x68, 0x01, 0x21, 0x20, 0x00, ++0xCC, 0xF7, 0x52, 0xFB, 0x3A, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x20, 0x00, 0x08, 0x4B, 0x98, 0x47, 0x01, 0xE0, 0xFF, 0xF7, ++0xB3, 0xFF, 0x70, 0xBD, 0x03, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0x28, 0x00, 0xB0, 0x47, 0xF6, 0xE7, ++0x28, 0x19, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0xD1, 0xC2, 0x0A, 0x00, 0x10, 0xB5, 0x01, 0x28, 0x00, 0xD0, 0x10, 0xBD, ++0x00, 0x29, 0xFC, 0xD0, 0x04, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xF8, 0xD0, 0x03, 0x4A, 0xDA, 0x61, 0x03, 0x48, 0x79, 0xF7, ++0xCB, 0xFF, 0xF2, 0xE7, 0x24, 0x27, 0x16, 0x00, 0x85, 0x04, 0x10, 0x00, 0x94, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x1E, 0x4B, ++0x1E, 0x4A, 0x13, 0x60, 0x80, 0x22, 0x52, 0x00, 0x9C, 0x5C, 0x1D, 0x4B, 0xE3, 0x18, 0x1B, 0x01, 0x1A, 0x88, 0xD2, 0x08, ++0x06, 0x21, 0x11, 0x42, 0x08, 0xD1, 0x19, 0x88, 0x89, 0x06, 0x49, 0x0F, 0x18, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x20, 0x00, 0xA8, 0x47, 0x13, 0x4B, 0x1A, 0x68, 0x81, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, 0x12, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0D, 0x4B, 0x1B, 0x68, 0x22, 0x01, 0x9B, 0x18, 0x1B, 0x7B, ++0x00, 0x2B, 0x05, 0xD1, 0x0B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x06, 0x4B, 0x1A, 0x68, ++0x23, 0x01, 0xD3, 0x18, 0x5D, 0x68, 0x00, 0x2D, 0x03, 0xD0, 0x99, 0x68, 0x18, 0x68, 0x02, 0x22, 0xA8, 0x47, 0x70, 0xBD, ++0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0x00, 0x10, 0x06, 0x04, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0xFF, 0x23, ++0x9B, 0x00, 0x98, 0x42, 0x08, 0xD9, 0x05, 0x4B, 0x59, 0x80, 0x00, 0x24, 0x21, 0x00, 0x04, 0x48, 0x79, 0xF7, 0x72, 0xFF, ++0x20, 0x00, 0x10, 0xBD, 0x11, 0x24, 0xF7, 0xE7, 0x54, 0x2A, 0x16, 0x00, 0xA0, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, ++0x0D, 0x00, 0x81, 0x88, 0x00, 0x88, 0xFF, 0xF7, 0xE5, 0xFF, 0x01, 0x1E, 0x04, 0xD0, 0x28, 0x00, 0xFC, 0xF7, 0x90, 0xFE, ++0x00, 0x20, 0x70, 0xBD, 0xE1, 0x88, 0xA0, 0x78, 0xCB, 0xF7, 0xB6, 0xFE, 0x01, 0x00, 0xF4, 0xE7, 0xF0, 0xB5, 0xCE, 0x46, ++0x47, 0x46, 0x80, 0xB5, 0x89, 0xB0, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x23, 0x00, 0x21, 0x26, 0x48, 0x77, 0xF7, 0x46, 0xFE, ++0x80, 0x46, 0x00, 0x23, 0x43, 0x80, 0xB1, 0x79, 0x23, 0x48, 0x79, 0xF7, 0x43, 0xFF, 0xB3, 0x79, 0x00, 0x2B, 0x2A, 0xD1, ++0x60, 0x24, 0x6B, 0x46, 0xDD, 0x1D, 0x16, 0x23, 0x99, 0x46, 0x1F, 0x4F, 0x07, 0xE0, 0x03, 0x23, 0x42, 0x46, 0x13, 0x70, ++0x24, 0xE0, 0x01, 0x34, 0xE4, 0xB2, 0x68, 0x2C, 0x20, 0xD0, 0x4B, 0x46, 0x2B, 0x70, 0x02, 0xAA, 0x29, 0x00, 0x20, 0x00, ++0x3B, 0x68, 0x98, 0x47, 0x00, 0x28, 0xF2, 0xD1, 0x06, 0x22, 0x02, 0xA9, 0x30, 0x00, 0xCE, 0xF7, 0xF3, 0xFC, 0x00, 0x28, ++0xEB, 0xD1, 0x12, 0x4B, 0x9B, 0x68, 0x20, 0x00, 0x98, 0x47, 0x00, 0x28, 0xE1, 0xD1, 0x43, 0x46, 0x5B, 0x88, 0x01, 0x33, ++0x42, 0x46, 0x53, 0x80, 0x04, 0xE0, 0x01, 0x2B, 0x0B, 0xD0, 0x12, 0x23, 0x42, 0x46, 0x13, 0x70, 0x40, 0x46, 0xC9, 0xF7, ++0x69, 0xFC, 0x00, 0x20, 0x09, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x43, 0x46, 0x5B, 0x88, 0x08, 0x33, ++0x42, 0x46, 0x53, 0x80, 0xF0, 0xE7, 0xC0, 0x46, 0x01, 0x11, 0x00, 0x00, 0xAC, 0xD4, 0x10, 0x00, 0x94, 0x92, 0x16, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x85, 0xB0, 0x0C, 0x00, 0x16, 0x00, 0x17, 0x0A, ++0xBA, 0x00, 0x91, 0x4B, 0xD5, 0x58, 0x50, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xD6, 0xE0, 0x4B, 0x78, 0x5B, 0x08, ++0x98, 0x46, 0x7F, 0x2B, 0x11, 0xD0, 0x01, 0x93, 0x00, 0x22, 0x19, 0x00, 0x8A, 0x48, 0x79, 0xF7, 0xDD, 0xFE, 0x43, 0x46, ++0x7E, 0x2B, 0x56, 0xD1, 0x36, 0x3B, 0xEB, 0x5C, 0x00, 0x2B, 0x43, 0xD0, 0x00, 0x23, 0x9B, 0x46, 0x7E, 0x33, 0x01, 0x93, ++0x0C, 0xE0, 0x8B, 0x78, 0x9B, 0x46, 0x1A, 0x00, 0x7F, 0x21, 0x81, 0x48, 0x79, 0xF7, 0xCA, 0xFE, 0x7F, 0x23, 0x01, 0x93, ++0x48, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x43, 0xD0, 0xFB, 0xB2, 0x99, 0x46, 0x61, 0x78, 0x4F, 0x08, 0x59, 0x29, 0x00, 0xD8, ++0xE0, 0xE0, 0x7F, 0x2F, 0x05, 0xD1, 0xA3, 0x78, 0x9A, 0x46, 0x0D, 0x2B, 0x55, 0xD8, 0x0B, 0x2B, 0x55, 0xD8, 0x07, 0x23, ++0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x9A, 0x46, 0x23, 0x78, 0x52, 0x46, 0x13, 0x70, 0x14, 0x23, 0x32, 0x00, 0x31, 0x00, ++0x70, 0x48, 0x77, 0xF7, 0xA3, 0xFD, 0x07, 0x00, 0x61, 0x1C, 0x52, 0x46, 0x82, 0xF7, 0x30, 0xF9, 0x02, 0x28, 0x75, 0xD0, ++0x00, 0x28, 0x00, 0xD1, 0xA9, 0xE0, 0x04, 0x28, 0x00, 0xD0, 0x99, 0xE0, 0xFB, 0x22, 0x43, 0x46, 0x15, 0x3B, 0x13, 0x42, ++0x00, 0xD1, 0xB1, 0xE0, 0x19, 0x24, 0x6F, 0xE0, 0x36, 0x33, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, ++0x0C, 0x22, 0x7E, 0x21, 0x9F, 0xF7, 0xC7, 0xFA, 0x00, 0x23, 0x9B, 0x46, 0x7E, 0x33, 0x01, 0x93, 0xBE, 0xE7, 0x00, 0x23, ++0x9B, 0x46, 0xB7, 0xE7, 0x59, 0x46, 0x40, 0x46, 0x82, 0xF7, 0x96, 0xF8, 0x00, 0x28, 0xB5, 0xD1, 0x43, 0x46, 0x7F, 0x2B, ++0x0A, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, 0x0C, 0x22, 0x41, 0x46, 0x9F, 0xF7, ++0xAC, 0xFA, 0x5A, 0xE0, 0x49, 0x3B, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, 0x0C, 0x22, 0x59, 0x46, ++0x9F, 0xF7, 0xB0, 0xFA, 0x4F, 0xE0, 0x15, 0x2B, 0xA9, 0xD1, 0x4B, 0x46, 0x9B, 0x00, 0x48, 0x4A, 0x9B, 0x58, 0xB2, 0x22, ++0x92, 0x00, 0x9A, 0x5C, 0x00, 0x2A, 0xA0, 0xD0, 0xCA, 0x07, 0x9E, 0xD5, 0x46, 0x4A, 0x9A, 0x5C, 0xBA, 0x42, 0x14, 0xD1, ++0x7F, 0x2F, 0x98, 0xD1, 0x44, 0x4A, 0x9B, 0x5C, 0x53, 0x45, 0x94, 0xD0, 0x4B, 0x46, 0x1B, 0x02, 0x01, 0x20, 0x18, 0x43, ++0x78, 0xF7, 0x16, 0xF9, 0x00, 0x28, 0x30, 0xD0, 0x01, 0x23, 0x2A, 0x22, 0x51, 0x46, 0x48, 0x46, 0x9F, 0xF7, 0x8A, 0xFA, ++0x29, 0xE0, 0x4B, 0x46, 0x1B, 0x02, 0x01, 0x20, 0x18, 0x43, 0x78, 0xF7, 0x07, 0xF9, 0x00, 0x28, 0x21, 0xD0, 0x7F, 0x2F, ++0xEE, 0xD0, 0x01, 0x23, 0x2A, 0x22, 0x39, 0x00, 0x48, 0x46, 0x9F, 0xF7, 0x6A, 0xFA, 0x18, 0xE0, 0x33, 0x4B, 0xDC, 0x6E, ++0x00, 0x23, 0x00, 0x22, 0x01, 0x99, 0x08, 0x00, 0xA0, 0x47, 0x1E, 0x24, 0x38, 0x00, 0x0C, 0x38, 0x77, 0xF7, 0x69, 0xFD, ++0x43, 0x46, 0x7F, 0x2B, 0x1C, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0x22, 0x00, 0x41, 0x46, ++0x48, 0x46, 0x9F, 0xF7, 0x50, 0xFA, 0x8A, 0x23, 0xFF, 0x33, 0xEB, 0x5C, 0x00, 0x2B, 0x03, 0xD0, 0x25, 0x4B, 0xEB, 0x5C, ++0x00, 0x2B, 0x18, 0xD1, 0x00, 0x20, 0x05, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, ++0x1E, 0x24, 0xDB, 0xE7, 0x49, 0x3B, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0x22, 0x00, 0x59, 0x46, 0x48, 0x46, ++0x9F, 0xF7, 0x42, 0xFA, 0xE1, 0xE7, 0x38, 0x00, 0x77, 0xF7, 0x16, 0xFD, 0xDD, 0xE7, 0xAA, 0x8D, 0xEB, 0x8D, 0xD2, 0x1A, ++0x31, 0x00, 0x16, 0x48, 0x77, 0xF7, 0x24, 0xFC, 0xAA, 0x8D, 0x31, 0x00, 0x14, 0x48, 0x77, 0xF7, 0x1F, 0xFC, 0xD9, 0xE7, ++0x38, 0x00, 0x0C, 0x38, 0x77, 0xF7, 0x29, 0xFD, 0x1A, 0x24, 0xC0, 0xE7, 0x12, 0x2F, 0x00, 0xD8, 0x23, 0xE7, 0x3A, 0x00, ++0x13, 0x3A, 0xD2, 0xB2, 0x01, 0x23, 0x93, 0x40, 0x0C, 0x4A, 0x13, 0x42, 0x00, 0xD1, 0x1A, 0xE7, 0x00, 0x23, 0x9A, 0x46, ++0x6D, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xBC, 0xD4, 0x10, 0x00, 0x01, 0x06, 0x00, 0x00, 0xC6, 0x02, 0x00, 0x00, ++0xC7, 0x02, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xAF, 0x02, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x0A, 0x06, 0x00, 0x00, ++0x31, 0x00, 0x00, 0x03, 0x30, 0xB5, 0x87, 0xB0, 0x1E, 0x4C, 0x23, 0x7B, 0x03, 0x22, 0x13, 0x43, 0x23, 0x73, 0x03, 0xAD, ++0x21, 0x00, 0x27, 0x31, 0x03, 0x22, 0x28, 0x00, 0xCE, 0xF7, 0x9E, 0xFB, 0xE3, 0x89, 0xAB, 0x80, 0x23, 0x8A, 0xEB, 0x80, ++0xA3, 0x7C, 0x2B, 0x72, 0x23, 0x7F, 0x6B, 0x72, 0x28, 0x00, 0xA2, 0xF7, 0x3F, 0xFB, 0x23, 0x00, 0x3C, 0x33, 0x00, 0x24, ++0x1A, 0x78, 0x00, 0x2A, 0x06, 0xD0, 0x01, 0x34, 0xE4, 0xB2, 0x09, 0x33, 0x07, 0x2C, 0xF7, 0xD1, 0x07, 0xB0, 0x30, 0xBD, ++0x06, 0x2C, 0xFB, 0xD8, 0x01, 0xA8, 0x0B, 0x4B, 0x1A, 0x8B, 0x02, 0x80, 0x5A, 0x8B, 0x42, 0x80, 0x5B, 0x7F, 0x03, 0x71, ++0x44, 0x71, 0x08, 0x4A, 0xD0, 0x23, 0xD3, 0x58, 0x98, 0x47, 0x00, 0x28, 0xEC, 0xD1, 0xE3, 0x00, 0x1B, 0x19, 0x03, 0x4C, ++0xE4, 0x18, 0x3C, 0x34, 0x02, 0x23, 0x23, 0x70, 0xE4, 0xE7, 0xC0, 0x46, 0x68, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x10, 0xB5, 0x07, 0x4C, 0xA0, 0x47, 0x86, 0xF7, 0x97, 0xF8, 0x00, 0x28, 0x01, 0xD1, 0x00, 0x20, 0x10, 0xBD, 0xFF, 0xF7, ++0xB1, 0xFF, 0x03, 0x48, 0x79, 0xF7, 0x66, 0xFD, 0xF7, 0xE7, 0xC0, 0x46, 0xDD, 0x90, 0x0A, 0x00, 0xCC, 0xD4, 0x10, 0x00, ++0x00, 0xB5, 0x83, 0xB0, 0x01, 0xAA, 0x01, 0x23, 0x0B, 0x40, 0x30, 0x21, 0x0B, 0x43, 0x13, 0x70, 0x11, 0x00, 0x9F, 0xF7, ++0x41, 0xF9, 0x03, 0xB0, 0x00, 0xBD, 0x00, 0x00, 0x30, 0xB5, 0x83, 0xB0, 0x04, 0x00, 0x00, 0x0A, 0x82, 0x00, 0x0E, 0x4B, ++0xD2, 0x58, 0x3C, 0x23, 0xD3, 0x5C, 0x02, 0x2B, 0x07, 0xD0, 0x96, 0x22, 0x52, 0x00, 0x21, 0x00, 0x0A, 0x48, 0x77, 0xF7, ++0x7D, 0xFB, 0x03, 0xB0, 0x30, 0xBD, 0x6B, 0x46, 0x9D, 0x1D, 0xC0, 0xB2, 0x00, 0x22, 0x29, 0x00, 0x89, 0xF7, 0xEE, 0xFA, ++0x28, 0x88, 0x79, 0xF7, 0x95, 0xFD, 0x40, 0x00, 0x02, 0x00, 0x2D, 0x32, 0xFF, 0x32, 0xEA, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0x05, 0x06, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x00, 0x0A, 0x82, 0x00, 0x07, 0x4B, 0xD2, 0x58, 0x36, 0x23, 0xD1, 0x5C, ++0xC0, 0xB2, 0xFF, 0xF7, 0xC1, 0xFF, 0x20, 0x00, 0xFF, 0xF7, 0xCC, 0xFF, 0x32, 0x21, 0x20, 0x00, 0x77, 0xF7, 0x8C, 0xFF, ++0x10, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x70, 0xB5, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x17, 0x4B, 0xD6, 0x58, ++0x20, 0x00, 0x77, 0xF7, 0xDF, 0xFF, 0x03, 0x00, 0x19, 0x28, 0x1D, 0xD8, 0x01, 0x38, 0xC0, 0xB2, 0x14, 0x28, 0x06, 0xD8, ++0x02, 0x20, 0x01, 0x2B, 0x15, 0xD1, 0x3C, 0x23, 0xF3, 0x5C, 0x02, 0x2B, 0x16, 0xD0, 0x08, 0x23, 0x14, 0x22, 0x00, 0x21, ++0x0D, 0x48, 0x77, 0xF7, 0xF5, 0xFB, 0x0C, 0x23, 0x03, 0x70, 0x80, 0x35, 0x45, 0x80, 0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, ++0xF3, 0x5C, 0x03, 0x71, 0xC9, 0xF7, 0x4A, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x02, 0x20, 0x66, 0x2B, 0xFB, 0xD1, 0xE4, 0xE7, ++0x20, 0x00, 0xFF, 0xF7, 0xB9, 0xFF, 0x00, 0x20, 0xF5, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, ++0x70, 0xB5, 0x82, 0xB0, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x24, 0x4B, 0xD6, 0x58, 0x20, 0x00, 0x77, 0xF7, 0xA6, 0xFF, ++0x01, 0x28, 0x16, 0xD0, 0x04, 0xD9, 0x16, 0x38, 0xC3, 0xB2, 0x02, 0x20, 0x03, 0x2B, 0x0E, 0xD8, 0x06, 0x23, 0x1C, 0x22, ++0x00, 0x21, 0x1D, 0x48, 0x77, 0xF7, 0xC2, 0xFB, 0x02, 0x23, 0x03, 0x70, 0x80, 0x35, 0x45, 0x80, 0x00, 0x23, 0x83, 0x80, ++0xC9, 0xF7, 0x1A, 0xFA, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x36, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x0E, 0xD1, 0x01, 0xA9, ++0x0A, 0x33, 0x0B, 0x70, 0xE8, 0xB2, 0x9F, 0xF7, 0x9D, 0xF8, 0x20, 0x00, 0xFF, 0xF7, 0x5C, 0xFF, 0x06, 0x21, 0x20, 0x00, ++0x77, 0xF7, 0x1C, 0xFF, 0x00, 0x20, 0xEA, 0xE7, 0x06, 0x23, 0x1C, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x77, 0xF7, 0x9E, 0xFB, ++0x04, 0x00, 0x00, 0x23, 0x03, 0x70, 0x2B, 0x00, 0x80, 0x33, 0x43, 0x80, 0xE8, 0xB2, 0xA8, 0xF7, 0x3D, 0xFF, 0x00, 0x04, ++0x40, 0x0C, 0xA0, 0x80, 0x20, 0x00, 0xC9, 0xF7, 0xEF, 0xF9, 0x00, 0x20, 0xD3, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x03, 0x11, 0x00, 0x00, 0x70, 0xB5, 0x14, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x14, 0x4A, 0x9D, 0x58, 0x20, 0x00, 0x77, 0xF7, ++0x55, 0xFF, 0x00, 0x28, 0x1E, 0xD0, 0x16, 0x38, 0xC3, 0xB2, 0x00, 0x20, 0x03, 0x2B, 0x13, 0xD9, 0x43, 0x23, 0x01, 0x22, ++0xEA, 0x54, 0x07, 0x3B, 0xEB, 0x5C, 0x02, 0x2B, 0x0D, 0xD0, 0x37, 0x23, 0xE9, 0x5C, 0x20, 0x00, 0x8B, 0xF7, 0x32, 0xF8, ++0x00, 0x28, 0x0D, 0xD0, 0x37, 0x23, 0xE9, 0x5C, 0x20, 0x00, 0x90, 0xF7, 0x57, 0xFF, 0x00, 0x20, 0x70, 0xBD, 0x20, 0x00, ++0x89, 0xF7, 0xFE, 0xFD, 0x02, 0x20, 0xF9, 0xE7, 0x00, 0x20, 0xF7, 0xE7, 0x02, 0x20, 0xF5, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0x10, 0xB5, 0x80, 0x00, 0x0F, 0x4B, 0xC4, 0x58, 0x8E, 0xF7, 0xD4, 0xFC, 0x03, 0x00, 0x01, 0x20, 0x0B, 0x2B, 0x13, 0xD9, ++0x11, 0x2B, 0x06, 0xD8, 0x20, 0x00, 0x54, 0x30, 0x00, 0x21, 0x9E, 0xF7, 0x53, 0xFF, 0x00, 0x28, 0x0B, 0xD1, 0x20, 0x00, ++0x54, 0x30, 0x01, 0x21, 0x9E, 0xF7, 0x4C, 0xFF, 0x43, 0x42, 0x58, 0x41, 0x40, 0x42, 0x03, 0x23, 0x98, 0x43, 0x05, 0x30, ++0x10, 0xBD, 0x03, 0x20, 0xFC, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x02, 0x00, 0x00, 0x29, 0x16, 0xD1, 0x01, 0x23, ++0x03, 0x40, 0x58, 0x42, 0x43, 0x41, 0x58, 0x42, 0x20, 0x4B, 0x18, 0x40, 0x20, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x06, 0x23, ++0x1A, 0x40, 0x04, 0x2A, 0x02, 0xD0, 0x02, 0x2A, 0x03, 0xD0, 0x70, 0x47, 0x80, 0x04, 0x80, 0x0C, 0xFB, 0xE7, 0x1B, 0x4B, ++0x18, 0x40, 0xF8, 0xE7, 0x18, 0x23, 0x19, 0x00, 0x01, 0x40, 0x03, 0x42, 0x21, 0xD0, 0x08, 0x29, 0x0E, 0xD0, 0x60, 0x23, ++0x03, 0x40, 0x40, 0x2B, 0x21, 0xD0, 0x20, 0x3B, 0x18, 0x00, 0x43, 0x1E, 0x98, 0x41, 0x40, 0x42, 0x12, 0x4B, 0x18, 0x40, ++0x12, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xE2, 0xE7, 0x48, 0x33, 0x03, 0x40, 0x60, 0x2B, 0x0E, 0xD0, 0x40, 0x2B, 0x0E, 0xD0, ++0x20, 0x3B, 0x18, 0x00, 0x43, 0x1E, 0x98, 0x41, 0x40, 0x42, 0x0C, 0x4B, 0x18, 0x40, 0x0C, 0x4B, 0x9C, 0x46, 0x60, 0x44, ++0xD1, 0xE7, 0x0B, 0x48, 0xCF, 0xE7, 0x0B, 0x48, 0xCD, 0xE7, 0x0B, 0x48, 0xCB, 0xE7, 0x0B, 0x48, 0xC9, 0xE7, 0xC0, 0x46, ++0xF0, 0x77, 0xFF, 0xFF, 0x1E, 0xFF, 0x00, 0x00, 0xFF, 0x33, 0x00, 0x00, 0x00, 0xCD, 0xFF, 0xFF, 0x08, 0x33, 0x00, 0x00, ++0x00, 0xEF, 0xFF, 0xFF, 0x0C, 0x33, 0x00, 0x00, 0x0E, 0x33, 0x00, 0x00, 0x0C, 0x22, 0x00, 0x00, 0x0C, 0x32, 0x00, 0x00, ++0x08, 0x30, 0x00, 0x00, 0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x77, 0xF7, 0xA4, 0xFE, 0x03, 0x00, 0x01, 0x28, ++0x0A, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x06, 0xD9, 0x16, 0x3B, 0xDB, 0xB2, 0x03, 0x30, 0x98, 0x42, 0x80, 0x41, 0x40, 0x42, ++0x40, 0x00, 0x70, 0xBD, 0x24, 0x0A, 0xA2, 0x00, 0x0F, 0x4B, 0xD6, 0x58, 0x3F, 0x23, 0xF1, 0x5C, 0x68, 0x78, 0xFF, 0xF7, ++0x83, 0xFF, 0x70, 0x85, 0xE4, 0xB2, 0x20, 0x00, 0xFF, 0xF7, 0x5A, 0xFF, 0x9E, 0xF7, 0x5C, 0xFF, 0x71, 0x8D, 0x01, 0x22, ++0x9E, 0xF7, 0x08, 0xFD, 0x31, 0x8C, 0x01, 0x22, 0x9E, 0xF7, 0x04, 0xFD, 0x01, 0x00, 0x33, 0x8C, 0x00, 0x20, 0x8B, 0x42, ++0xE1, 0xD0, 0x20, 0x00, 0xA8, 0xF7, 0xA2, 0xFF, 0x00, 0x20, 0xDC, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x05, 0x00, 0x08, 0x00, 0x0E, 0x0A, 0xB2, 0x00, 0x29, 0x4B, 0xD4, 0x58, 0x77, 0xF7, 0x67, 0xFE, 0x00, 0x28, ++0x03, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x03, 0xD8, 0x00, 0x20, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2B, 0x78, ++0x01, 0x27, 0x3B, 0x40, 0x39, 0x22, 0xA3, 0x54, 0x54, 0x23, 0x98, 0x46, 0xA0, 0x44, 0x69, 0x1C, 0x31, 0x3A, 0x40, 0x46, ++0xCE, 0xF7, 0x72, 0xF9, 0x57, 0x22, 0xA3, 0x5C, 0x04, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x02, 0x32, 0xA3, 0x5C, 0x3E, 0x31, ++0x8B, 0x43, 0xA3, 0x54, 0x29, 0x78, 0x39, 0x40, 0xF0, 0xB2, 0x9F, 0xF7, 0x2D, 0xF9, 0x09, 0x21, 0x40, 0x46, 0x9E, 0xF7, ++0x73, 0xFE, 0x00, 0x28, 0x0D, 0xD1, 0x85, 0xF7, 0x8F, 0xFE, 0x00, 0x28, 0x02, 0xD0, 0x4F, 0x23, 0x01, 0x22, 0xE2, 0x54, ++0xBC, 0x22, 0x52, 0x00, 0xA3, 0x5C, 0x01, 0x21, 0x0B, 0x43, 0xA3, 0x54, 0xCB, 0xE7, 0x3A, 0x21, 0x40, 0x46, 0x9E, 0xF7, ++0x5F, 0xFE, 0x02, 0x00, 0x53, 0x1E, 0x9A, 0x41, 0x4F, 0x23, 0xE2, 0x54, 0x00, 0x23, 0x00, 0x28, 0x04, 0xD0, 0x05, 0x4A, ++0x05, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0xDB, 0x0F, 0x4F, 0x22, 0xA3, 0x54, 0xDD, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x7C, 0x1E, 0x16, 0x00, 0xA2, 0x02, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x0B, 0x0A, ++0x98, 0x46, 0x9A, 0x00, 0x32, 0x4B, 0xD4, 0x58, 0x27, 0x00, 0x54, 0x37, 0x41, 0x1C, 0x08, 0x22, 0x38, 0x00, 0xCE, 0xF7, ++0x23, 0xF9, 0x57, 0x22, 0xA3, 0x5C, 0x04, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x02, 0x32, 0xA3, 0x5C, 0x3E, 0x31, 0x8B, 0x43, ++0xA3, 0x54, 0x28, 0x00, 0x77, 0xF7, 0xF4, 0xFD, 0x14, 0x28, 0x13, 0xD0, 0x07, 0xD9, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, ++0x05, 0xD8, 0x00, 0x20, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x00, 0x28, 0xF9, 0xD0, 0x28, 0x00, 0x77, 0xF7, 0xE4, 0xFD, ++0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0x7D, 0xF7, 0xB1, 0xF8, 0xF0, 0xE7, 0x29, 0x00, 0x1D, 0x48, 0x77, 0xF7, 0xBC, 0xF9, ++0x32, 0x78, 0x01, 0x23, 0x13, 0x40, 0x3A, 0x22, 0xA3, 0x54, 0x09, 0x21, 0x38, 0x00, 0x9E, 0xF7, 0x07, 0xFE, 0x00, 0x28, ++0x11, 0xD1, 0xBC, 0x22, 0x52, 0x00, 0xA3, 0x5C, 0x01, 0x21, 0x0B, 0x43, 0xA3, 0x54, 0x3F, 0x21, 0x38, 0x00, 0x9E, 0xF7, ++0xFB, 0xFD, 0x00, 0x28, 0x19, 0xD0, 0x01, 0x22, 0x41, 0x46, 0x28, 0x00, 0x91, 0xF7, 0xE6, 0xF8, 0xCF, 0xE7, 0x3A, 0x21, ++0x38, 0x00, 0x9E, 0xF7, 0xEF, 0xFD, 0x02, 0x00, 0x53, 0x1E, 0x9A, 0x41, 0x4F, 0x23, 0xE2, 0x54, 0x00, 0x23, 0x00, 0x28, ++0x04, 0xD0, 0x08, 0x4A, 0x08, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0xDB, 0x0F, 0x4F, 0x22, 0xA3, 0x54, 0xD9, 0xE7, 0x01, 0x21, ++0x28, 0x00, 0x77, 0xF7, 0x45, 0xFD, 0xB6, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x05, 0x06, 0x00, 0x00, 0x7C, 0x1E, 0x16, 0x00, ++0xA2, 0x02, 0x00, 0x00, 0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0x0E, 0x0A, ++0xB2, 0x00, 0x35, 0x4B, 0xD7, 0x58, 0x02, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xBB, 0x54, 0x36, 0x23, 0xFB, 0x5C, ++0x98, 0x46, 0x33, 0x01, 0x9B, 0x1B, 0x9B, 0x00, 0x2F, 0x4A, 0xD3, 0x18, 0x5B, 0x7B, 0x99, 0x46, 0x08, 0x00, 0x77, 0xF7, ++0x7F, 0xFD, 0x02, 0x00, 0x19, 0x28, 0x1B, 0xD8, 0x01, 0x38, 0xC0, 0xB2, 0x14, 0x28, 0x47, 0xD8, 0x02, 0x20, 0x01, 0x2A, ++0x47, 0xD1, 0x3C, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x36, 0xD1, 0x7B, 0x8C, 0x5B, 0x07, 0x33, 0xD5, 0xA3, 0x88, 0x62, 0x88, ++0x61, 0x78, 0x20, 0x89, 0x01, 0x90, 0xE0, 0x88, 0x00, 0x90, 0x21, 0x4C, 0x94, 0x20, 0x24, 0x58, 0x28, 0x00, 0xA0, 0x47, ++0x00, 0x20, 0x32, 0xE0, 0x2E, 0x28, 0x2F, 0xD1, 0x01, 0x23, 0x4A, 0x46, 0x5A, 0x40, 0x13, 0x00, 0x42, 0x46, 0x5A, 0x40, ++0x13, 0x00, 0x39, 0x22, 0xBA, 0x5C, 0xDB, 0xB2, 0x9A, 0x42, 0x0D, 0xD1, 0xA3, 0x88, 0x62, 0x88, 0x61, 0x78, 0x20, 0x89, ++0x01, 0x90, 0xE0, 0x88, 0x00, 0x90, 0x13, 0x4C, 0x94, 0x20, 0x24, 0x58, 0x28, 0x00, 0xA0, 0x47, 0x00, 0x20, 0x16, 0xE0, ++0x22, 0x78, 0x01, 0x23, 0x13, 0x40, 0xF0, 0xB2, 0x23, 0x22, 0x17, 0x21, 0x9E, 0xF7, 0xA9, 0xFE, 0x00, 0x20, 0x0C, 0xE0, ++0x22, 0x78, 0x01, 0x23, 0x13, 0x40, 0xF0, 0xB2, 0x24, 0x22, 0x17, 0x21, 0x9E, 0xF7, 0x9F, 0xFE, 0x00, 0x20, 0x02, 0xE0, ++0x00, 0x20, 0x00, 0xE0, 0x02, 0x20, 0x03, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x64, 0xA2, 0x16, 0x00, ++0xC0, 0xA0, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x04, 0x00, 0x08, 0x00, 0x0D, 0x0A, 0xAA, 0x00, 0x22, 0x4B, ++0xD6, 0x58, 0x77, 0xF7, 0x19, 0xFD, 0x00, 0x28, 0x3B, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x37, 0xD9, 0x22, 0x78, ++0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x36, 0x23, 0xF3, 0x5C, 0x01, 0x2B, 0x27, 0xD1, 0x23, 0x7A, 0x1B, 0x3A, ++0x01, 0x2B, 0x24, 0xD8, 0x27, 0x00, 0x09, 0x37, 0x38, 0x00, 0x79, 0xF7, 0x93, 0xFA, 0x01, 0x00, 0x13, 0x28, 0x16, 0xD9, ++0x8B, 0x23, 0x9B, 0x00, 0xF0, 0x18, 0x0A, 0x22, 0x39, 0x00, 0xCE, 0xF7, 0x19, 0xF8, 0x22, 0x7A, 0x53, 0x1E, 0x9A, 0x41, ++0xD2, 0xB2, 0xE8, 0xB2, 0x3B, 0x00, 0x61, 0x68, 0xA9, 0xF7, 0x2E, 0xF8, 0x23, 0x7A, 0x5A, 0x1E, 0x93, 0x41, 0x91, 0x22, ++0x92, 0x00, 0xB3, 0x54, 0x0B, 0xE0, 0x08, 0x48, 0x79, 0xF7, 0x12, 0xFA, 0x1E, 0x22, 0x00, 0xE0, 0x24, 0x22, 0x39, 0x23, ++0xF3, 0x5C, 0xE8, 0xB2, 0x3C, 0x21, 0x9E, 0xF7, 0x48, 0xFE, 0x00, 0x20, 0xF8, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0xD8, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x04, 0x00, 0x08, 0x00, 0x0D, 0x0A, 0xAA, 0x00, 0x2B, 0x4B, 0xD6, 0x58, ++0x77, 0xF7, 0xCA, 0xFC, 0x00, 0x28, 0x20, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x1C, 0xD9, 0x22, 0x78, 0x01, 0x23, ++0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x16, 0xD0, 0xA3, 0x78, 0x01, 0x2B, 0x31, 0xD0, ++0x02, 0x2B, 0x39, 0xD0, 0x00, 0x20, 0x00, 0x2B, 0x22, 0xD0, 0x01, 0xA9, 0x39, 0x23, 0xF2, 0x5C, 0x3B, 0x3B, 0x13, 0x43, ++0x0B, 0x70, 0x20, 0x23, 0x4B, 0x70, 0x88, 0x70, 0xE8, 0xB2, 0x9E, 0xF7, 0xC1, 0xFD, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, ++0x85, 0xF7, 0xF8, 0xFC, 0x00, 0x28, 0x03, 0xD0, 0x4F, 0x23, 0x01, 0x22, 0xF2, 0x54, 0xE0, 0xE7, 0x4F, 0x23, 0xF3, 0x5C, ++0x00, 0x2B, 0xDC, 0xD1, 0x39, 0x23, 0xF3, 0x5C, 0xE8, 0xB2, 0x1A, 0x22, 0x1F, 0x21, 0x9E, 0xF7, 0x0D, 0xFE, 0xE8, 0xE7, ++0xE8, 0xB2, 0xF5, 0xF7, 0x59, 0xF9, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0x2A, 0x20, 0x18, 0x40, 0x15, 0x30, 0xD2, 0xE7, ++0xE8, 0xB2, 0xF5, 0xF7, 0x79, 0xF9, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0x15, 0x20, 0x18, 0x40, 0x15, 0x30, 0xC8, 0xE7, ++0xE8, 0xB2, 0x03, 0x4B, 0x1B, 0x69, 0x98, 0x47, 0x2A, 0x20, 0xC2, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x60, 0x92, 0x16, 0x00, ++0x70, 0xB5, 0x14, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x11, 0x4A, 0x9D, 0x58, 0x20, 0x00, 0x77, 0xF7, 0x69, 0xFC, 0x03, 0x00, ++0x01, 0x28, 0x0A, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x06, 0xD9, 0x16, 0x3B, 0xDB, 0xB2, 0x03, 0x30, 0x98, 0x42, 0x80, 0x41, ++0x40, 0x42, 0x40, 0x00, 0x70, 0xBD, 0x36, 0x23, 0xEB, 0x5C, 0x00, 0x20, 0x00, 0x2B, 0xF9, 0xD1, 0x91, 0x23, 0x9B, 0x00, ++0xEB, 0x5C, 0x00, 0x2B, 0xF4, 0xD0, 0x00, 0x21, 0x20, 0x00, 0x8E, 0xF7, 0xDB, 0xFC, 0x00, 0x20, 0xEE, 0xE7, 0xC0, 0x46, ++0x64, 0xA2, 0x16, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x00, 0x90, 0x0F, 0x00, 0x16, 0x00, 0x01, 0x93, 0x0B, 0x78, 0xDC, 0x00, ++0xE3, 0x18, 0x32, 0x4C, 0xE4, 0x18, 0x3C, 0x34, 0x23, 0x78, 0x01, 0x2B, 0x02, 0xD0, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, ++0x4B, 0x78, 0x00, 0x2B, 0x4B, 0xD1, 0x2C, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x4D, 0xD0, 0x2B, 0x4D, 0x2C, 0x00, 0x3F, 0x34, ++0x02, 0xE0, 0x09, 0x35, 0xA5, 0x42, 0x43, 0xD0, 0xAB, 0x79, 0x02, 0x2B, 0xF9, 0xD9, 0x3B, 0x78, 0xD9, 0x00, 0xC9, 0x18, ++0x36, 0x31, 0x23, 0x4B, 0x9C, 0x46, 0x61, 0x44, 0x06, 0x22, 0x28, 0x00, 0xCD, 0xF7, 0x18, 0xFF, 0x00, 0x28, 0xEC, 0xD1, ++0x0C, 0x23, 0x03, 0x22, 0x00, 0x21, 0x1F, 0x48, 0x77, 0xF7, 0x3C, 0xF8, 0x04, 0x00, 0x0B, 0x23, 0x03, 0x70, 0x3B, 0x78, ++0xD9, 0x00, 0xC9, 0x18, 0x36, 0x31, 0x18, 0x4D, 0x49, 0x19, 0x04, 0x30, 0x06, 0x22, 0xCD, 0xF7, 0x27, 0xFF, 0x01, 0x23, ++0x5B, 0x42, 0x63, 0x80, 0x02, 0x33, 0xA3, 0x72, 0x00, 0x26, 0xE6, 0x72, 0x20, 0x00, 0xC8, 0xF7, 0x85, 0xFE, 0x3A, 0x78, ++0xD3, 0x00, 0x9B, 0x18, 0xEB, 0x18, 0x3E, 0x33, 0x18, 0x78, 0x85, 0xF7, 0x0F, 0xFA, 0x3A, 0x78, 0xD3, 0x00, 0x9B, 0x18, ++0xEB, 0x18, 0x3C, 0x33, 0x1E, 0x70, 0x28, 0x68, 0x0C, 0x38, 0x77, 0xF7, 0x62, 0xF8, 0x2E, 0x60, 0xAD, 0xE7, 0x16, 0x2B, ++0xAB, 0xD0, 0x02, 0xE0, 0x7B, 0x78, 0x16, 0x2B, 0xA7, 0xD0, 0x01, 0x9B, 0x32, 0x00, 0x39, 0x00, 0x00, 0x98, 0x04, 0x4C, ++0xA0, 0x47, 0xA0, 0xE7, 0x68, 0x9E, 0x16, 0x00, 0x9E, 0x9E, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, 0xED, 0x33, 0x09, 0x00, ++0xF0, 0xB5, 0x87, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x02, 0x92, 0x03, 0x93, 0x0A, 0x78, 0xD3, 0x00, 0x9A, 0x18, 0x29, 0x4B, ++0x9B, 0x18, 0x3C, 0x33, 0x1B, 0x78, 0x02, 0x2B, 0x02, 0xD0, 0x00, 0x20, 0x07, 0xB0, 0xF0, 0xBD, 0x25, 0x4C, 0x27, 0x00, ++0x3F, 0x37, 0x4E, 0x1C, 0x02, 0xE0, 0x09, 0x34, 0xBC, 0x42, 0x39, 0xD0, 0xA3, 0x79, 0x02, 0x2B, 0xF9, 0xD9, 0x06, 0x22, ++0x31, 0x00, 0x20, 0x00, 0xCD, 0xF7, 0xAE, 0xFE, 0x00, 0x28, 0xF2, 0xD1, 0x1B, 0x4A, 0x29, 0x78, 0xCB, 0x00, 0x5B, 0x18, ++0xD3, 0x18, 0x3C, 0x33, 0x00, 0x21, 0x19, 0x70, 0x13, 0x7B, 0x9B, 0x07, 0xDF, 0xD5, 0x18, 0x4B, 0x00, 0x24, 0x1A, 0x78, ++0x00, 0x2A, 0x05, 0xD0, 0x01, 0x34, 0xE4, 0xB2, 0x09, 0x33, 0x07, 0x2C, 0xF7, 0xD1, 0xD4, 0xE7, 0x06, 0x2C, 0xD2, 0xD8, ++0x0F, 0x4B, 0x1A, 0x8B, 0x04, 0xA9, 0x0A, 0x80, 0x5A, 0x8B, 0x4A, 0x80, 0x5B, 0x7F, 0x0B, 0x71, 0x4C, 0x71, 0x0E, 0x4A, ++0xD0, 0x23, 0xD3, 0x58, 0x08, 0x00, 0x98, 0x47, 0x00, 0x28, 0xC2, 0xD1, 0xE3, 0x00, 0x1C, 0x19, 0x06, 0x4B, 0x1C, 0x19, ++0x3C, 0x34, 0x02, 0x22, 0x22, 0x70, 0xBA, 0xE7, 0x03, 0x9B, 0x02, 0x9A, 0x29, 0x00, 0x01, 0x98, 0x05, 0x4C, 0xA0, 0x47, ++0xB3, 0xE7, 0xC0, 0x46, 0x68, 0x9E, 0x16, 0x00, 0x9E, 0x9E, 0x16, 0x00, 0xA4, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xDD, 0x32, 0x09, 0x00, 0x00, 0x09, 0x70, 0x47, 0x00, 0x28, 0x14, 0xD0, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x03, 0xD0, ++0x0D, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x06, 0xD1, 0x0C, 0x4B, 0x0A, 0x4A, 0x99, 0x68, 0x11, 0x60, 0xDA, 0x68, 0x09, 0x4B, ++0x1A, 0x60, 0x09, 0x4B, 0x09, 0x4A, 0x9A, 0x60, 0x09, 0x4A, 0xDA, 0x60, 0x70, 0x47, 0x06, 0x4B, 0x03, 0x4A, 0x12, 0x68, ++0x9A, 0x60, 0x03, 0x4A, 0x12, 0x68, 0xDA, 0x60, 0xF6, 0xE7, 0xC0, 0x46, 0xB8, 0xE6, 0x10, 0x00, 0xD4, 0xE6, 0x10, 0x00, ++0x60, 0x92, 0x16, 0x00, 0x2D, 0x01, 0x10, 0x00, 0x81, 0x01, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x01, 0x00, 0x2F, 0x48, ++0x79, 0xF7, 0x68, 0xF8, 0x7D, 0xF7, 0xE8, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x70, 0xBD, 0xFF, 0xF7, 0xC9, 0xFF, 0x2B, 0x4A, ++0x95, 0x23, 0x9B, 0x00, 0xD2, 0x5C, 0x2A, 0x4B, 0x1A, 0x70, 0x2A, 0x4B, 0x1A, 0x68, 0x2A, 0x4B, 0x1A, 0x60, 0xE6, 0x23, ++0x5B, 0x00, 0x1B, 0x68, 0x28, 0x48, 0x98, 0x47, 0x28, 0x4B, 0x18, 0x60, 0x01, 0x2C, 0x27, 0xD0, 0x02, 0x23, 0x22, 0x00, ++0x9A, 0x43, 0x05, 0xD0, 0x25, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x1C, 0x4E, 0x95, 0x25, ++0xAD, 0x00, 0x40, 0x23, 0x73, 0x55, 0x1C, 0x4B, 0x20, 0x4A, 0x1A, 0x60, 0x8C, 0x21, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, ++0x49, 0x00, 0x1A, 0x48, 0x98, 0x47, 0x73, 0x5D, 0x1C, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x01, 0x2C, 0x1B, 0xD9, 0x02, 0x2C, ++0xC8, 0xD1, 0x1A, 0x49, 0x0A, 0x88, 0xFF, 0x20, 0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xC1, 0xE7, 0x0D, 0x4D, 0x95, 0x24, ++0xA4, 0x00, 0x30, 0x23, 0x2B, 0x55, 0x0D, 0x4B, 0x11, 0x4A, 0x1A, 0x60, 0x8C, 0x21, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, ++0x49, 0x00, 0x0B, 0x48, 0x98, 0x47, 0x2B, 0x5D, 0x0D, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x0E, 0x49, 0x0A, 0x88, 0xFF, 0x20, ++0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xA7, 0xE7, 0xE4, 0xD4, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0xF6, 0xE8, 0x10, 0x00, ++0x54, 0x07, 0x62, 0x40, 0x08, 0xE7, 0x10, 0x00, 0x58, 0x00, 0x01, 0x50, 0x18, 0xE7, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xFD, 0x20, 0x22, 0x21, 0x60, 0x92, 0x16, 0x00, 0x8E, 0x01, 0x61, 0x40, 0x0C, 0x65, 0x61, 0x40, 0x70, 0xB5, 0x04, 0x00, ++0x01, 0x00, 0x1A, 0x48, 0x78, 0xF7, 0xEE, 0xFF, 0x7D, 0xF7, 0x6E, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x70, 0xBD, 0x00, 0x20, ++0xFF, 0xF7, 0x4E, 0xFF, 0x15, 0x4E, 0x95, 0x25, 0xAD, 0x00, 0x15, 0x4B, 0x1B, 0x78, 0x73, 0x55, 0x14, 0x4B, 0x1A, 0x68, ++0x14, 0x4B, 0x1A, 0x60, 0x14, 0x4B, 0x1B, 0x68, 0x80, 0x21, 0x49, 0x00, 0x19, 0x43, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, ++0x11, 0x48, 0x98, 0x47, 0x73, 0x5D, 0x11, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x01, 0x2C, 0x08, 0xD9, 0x02, 0x2C, 0xDF, 0xD1, ++0x0E, 0x49, 0x0A, 0x88, 0xFF, 0x20, 0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xD8, 0xE7, 0x0C, 0x49, 0x0A, 0x88, 0xFF, 0x20, ++0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xD1, 0xE7, 0xF8, 0xD4, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0xF6, 0xE8, 0x10, 0x00, ++0x08, 0xE7, 0x10, 0x00, 0x54, 0x07, 0x62, 0x40, 0x18, 0xE7, 0x10, 0x00, 0x58, 0x00, 0x01, 0x50, 0x60, 0x92, 0x16, 0x00, ++0x8E, 0x01, 0x61, 0x40, 0x0C, 0x65, 0x61, 0x40, 0x10, 0xB5, 0x09, 0x28, 0x0B, 0xD9, 0xFF, 0x28, 0x0B, 0xD1, 0x0B, 0x09, ++0x1F, 0x29, 0x0D, 0xD9, 0x02, 0x3B, 0x01, 0x2B, 0x05, 0xD8, 0x01, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, 0x01, 0xE0, 0x00, 0x28, ++0x08, 0xD1, 0x10, 0xBD, 0x00, 0x20, 0xFF, 0xF7, 0x25, 0xFF, 0xFA, 0xE7, 0x00, 0x20, 0xFF, 0xF7, 0x9B, 0xFF, 0xF6, 0xE7, ++0x0B, 0x09, 0x1F, 0x29, 0xF4, 0xD9, 0x02, 0x3B, 0x01, 0x2B, 0xF0, 0xD8, 0x01, 0x20, 0xFF, 0xF7, 0x17, 0xFF, 0xEC, 0xE7, ++0xF8, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0x1F, 0x00, 0x13, 0x0A, 0x9B, 0x00, ++0x11, 0x4A, 0x9B, 0x58, 0x99, 0x46, 0x0A, 0x88, 0x10, 0x4B, 0xD3, 0x5C, 0x98, 0x46, 0x20, 0x00, 0x77, 0xF7, 0x42, 0xFA, ++0x0A, 0x28, 0x0A, 0xD0, 0x3B, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0x0B, 0x4C, 0xA0, 0x47, 0x00, 0x20, 0x0C, 0xBC, ++0x90, 0x46, 0x99, 0x46, 0xF8, 0xBD, 0x43, 0x46, 0x5B, 0x08, 0x03, 0x2B, 0xF0, 0xD1, 0x07, 0x4B, 0x4A, 0x46, 0xD1, 0x5C, ++0x06, 0x3B, 0xD0, 0x5C, 0xFF, 0xF7, 0xB0, 0xFF, 0xE8, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, ++0x05, 0x87, 0x0A, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x20, 0x4B, ++0xD6, 0x58, 0x20, 0x00, 0x77, 0xF7, 0x16, 0xFA, 0x03, 0x00, 0x01, 0x28, 0x10, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x05, 0xD9, ++0x19, 0x2B, 0x05, 0xD8, 0x15, 0x22, 0x9A, 0x42, 0x40, 0x41, 0x40, 0x00, 0x02, 0xB0, 0x70, 0xBD, 0x58, 0x3B, 0x18, 0x00, ++0x43, 0x1E, 0x98, 0x41, 0x40, 0x00, 0xF7, 0xE7, 0x4C, 0x23, 0xF3, 0x5C, 0x00, 0x20, 0x00, 0x2B, 0xF2, 0xD1, 0x4B, 0x33, ++0xF3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x4B, 0x23, 0x00, 0x22, 0xF2, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x20, 0x00, 0x2B, ++0xE6, 0xD0, 0x01, 0xA9, 0x36, 0x23, 0xF2, 0x5C, 0x38, 0x3B, 0x13, 0x43, 0x0B, 0x70, 0x1F, 0x23, 0x4B, 0x70, 0x1D, 0x3B, ++0x8B, 0x70, 0xE8, 0xB2, 0x9E, 0xF7, 0xFE, 0xFA, 0x20, 0x00, 0x8E, 0xF7, 0xF1, 0xFE, 0x58, 0x21, 0x20, 0x00, 0x77, 0xF7, ++0x7D, 0xF9, 0x00, 0x20, 0xD0, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x05, 0x4B, 0x00, 0x20, 0x1A, 0x78, 0x00, 0x2A, ++0x04, 0xD0, 0x01, 0x30, 0xC0, 0xB2, 0x09, 0x33, 0x07, 0x28, 0xF7, 0xD1, 0x70, 0x47, 0xC0, 0x46, 0xA4, 0x9E, 0x16, 0x00, ++0x70, 0xB5, 0x80, 0x00, 0x28, 0x4B, 0xC2, 0x58, 0x28, 0x49, 0xD5, 0x23, 0x5B, 0x00, 0xC9, 0x5C, 0xCB, 0x00, 0x5B, 0x1A, ++0x5B, 0x00, 0x26, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x19, 0x88, 0xC9, 0x0B, 0x0B, 0xD0, 0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, ++0x19, 0x80, 0x20, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x0B, 0x40, 0x23, 0x54, 0x9E, 0x23, ++0xD3, 0x5C, 0x5B, 0x00, 0xAE, 0x21, 0x51, 0x5C, 0x5B, 0x18, 0xDB, 0xB2, 0x99, 0x00, 0xCB, 0x18, 0x5B, 0x00, 0x19, 0x49, ++0x5C, 0x18, 0x21, 0x88, 0x89, 0xB2, 0x00, 0x29, 0x19, 0xD1, 0x9C, 0x31, 0x50, 0x5C, 0x00, 0x28, 0x01, 0xD1, 0x01, 0x31, ++0x50, 0x5C, 0x14, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x78, 0x26, 0xB1, 0x43, 0xC0, 0x00, 0x01, 0x43, 0x29, 0x80, 0x96, 0x21, ++0x51, 0x5A, 0xC9, 0x00, 0x06, 0x20, 0x01, 0x43, 0x89, 0xB2, 0x0E, 0x48, 0x18, 0x18, 0x01, 0x80, 0x94, 0x21, 0x51, 0x5A, ++0x21, 0x80, 0x0C, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x19, 0x80, 0xAE, 0x21, 0x53, 0x5C, ++0x58, 0x42, 0x43, 0x41, 0x53, 0x54, 0x70, 0xBD, 0x38, 0xE6, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, ++0xCE, 0x69, 0x61, 0x40, 0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0x70, 0xB5, 0x35, 0x4B, ++0x1C, 0x68, 0x00, 0x2C, 0x14, 0xD0, 0xE3, 0x78, 0x9B, 0x00, 0x33, 0x4A, 0x9D, 0x58, 0xA0, 0x23, 0xEB, 0x5C, 0x02, 0x2B, ++0x0E, 0xD0, 0x31, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x05, 0xD0, 0x30, 0x4A, 0x11, 0x68, 0x80, 0x23, 0xDB, 0x03, 0x0B, 0x43, ++0x13, 0x60, 0xA0, 0x23, 0x02, 0x22, 0xEA, 0x54, 0x00, 0x20, 0x70, 0xBD, 0x94, 0x23, 0xE8, 0x5A, 0x00, 0x28, 0x07, 0xD0, ++0x63, 0x78, 0x00, 0x2B, 0x42, 0xD0, 0x01, 0x2B, 0x43, 0xD0, 0x94, 0x23, 0x00, 0x22, 0xEA, 0x52, 0xE2, 0x78, 0x62, 0x23, ++0x53, 0x43, 0x24, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x40, 0x05, 0x40, 0x0F, 0x84, 0xF7, 0x51, 0xFF, 0x1D, 0x4D, ++0xE3, 0x78, 0x9B, 0x00, 0x58, 0x59, 0x76, 0xF7, 0xCF, 0xFE, 0xE3, 0x78, 0x9B, 0x00, 0x00, 0x24, 0x5C, 0x51, 0x1C, 0x48, ++0xCB, 0xF7, 0x56, 0xFD, 0x1B, 0x48, 0x78, 0xF7, 0x53, 0xFE, 0x14, 0x4D, 0x2B, 0x68, 0xD8, 0x68, 0x76, 0xF7, 0xC0, 0xFE, ++0x2B, 0x68, 0xDC, 0x60, 0x98, 0x68, 0x00, 0x28, 0x05, 0xD0, 0x76, 0xF7, 0xB9, 0xFE, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x22, ++0x9A, 0x60, 0x0C, 0x4C, 0x20, 0x68, 0x76, 0xF7, 0xB1, 0xFE, 0x00, 0x23, 0x23, 0x60, 0x0B, 0x4B, 0x1B, 0x78, 0x00, 0x2B, ++0xBC, 0xD0, 0x0E, 0x4A, 0x13, 0x68, 0x0E, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x06, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xB3, 0xE7, ++0x80, 0xF7, 0x4A, 0xFE, 0xBB, 0xE7, 0x80, 0xF7, 0xFD, 0xFD, 0xB8, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, ++0xDC, 0xE5, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, 0xFE, 0x64, 0x61, 0x40, 0xFC, 0xE6, 0x10, 0x00, 0x0C, 0xD5, 0x10, 0x00, ++0xD0, 0x04, 0x60, 0x40, 0xFF, 0x7F, 0xFF, 0xFF, 0x70, 0xB5, 0x13, 0x4B, 0x1C, 0x68, 0xA5, 0x78, 0x00, 0x2D, 0x1D, 0xD1, ++0x23, 0x78, 0x03, 0x2B, 0x1C, 0xD0, 0x63, 0x78, 0x00, 0x2B, 0x08, 0xD0, 0x01, 0x2B, 0x0F, 0xD0, 0x0D, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x04, 0xE0, 0x0E, 0x22, 0x01, 0x00, 0xE0, 0x68, 0xCD, 0xF7, 0xF2, 0xFB, ++0x01, 0x23, 0xA3, 0x70, 0x28, 0x00, 0x70, 0xBD, 0x0E, 0x22, 0x01, 0x00, 0xE0, 0x68, 0xCD, 0xF7, 0xE9, 0xFB, 0xF5, 0xE7, ++0x0C, 0x25, 0xF5, 0xE7, 0x0C, 0x25, 0xF3, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0xB0, 0x05, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x01, 0x93, 0x00, 0x23, ++0x08, 0x93, 0x09, 0x93, 0x06, 0x93, 0x06, 0xAA, 0x93, 0x80, 0x82, 0x00, 0xBB, 0x4B, 0xD3, 0x58, 0x00, 0x2B, 0x00, 0xD1, ++0x10, 0xE1, 0xAB, 0x00, 0xB8, 0x4A, 0x9F, 0x58, 0x21, 0x00, 0xB8, 0x48, 0x78, 0xF7, 0xCE, 0xFD, 0x00, 0x2C, 0x00, 0xD1, ++0x0D, 0xE1, 0x01, 0x2C, 0x00, 0xD1, 0x6D, 0xE2, 0xB4, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x00, 0x23, 0x00, 0x93, 0x98, 0x46, 0x99, 0x46, 0x02, 0x93, 0x00, 0x21, 0x00, 0x26, 0x01, 0x9B, 0x00, 0x2B, 0x63, 0xD0, ++0x62, 0x23, 0x6B, 0x43, 0xAC, 0x4A, 0x98, 0x18, 0x02, 0x88, 0x1F, 0x24, 0xA2, 0x43, 0x32, 0x43, 0x02, 0x80, 0xAA, 0x4A, ++0x9A, 0x18, 0x10, 0x88, 0xA9, 0x4E, 0x06, 0x40, 0x80, 0x20, 0x40, 0x00, 0x30, 0x43, 0x10, 0x80, 0x10, 0x88, 0x40, 0x04, ++0x40, 0x0C, 0x10, 0x80, 0x10, 0x88, 0xA5, 0x4E, 0x30, 0x40, 0x10, 0x80, 0xA4, 0x4A, 0x94, 0x46, 0x9C, 0x44, 0x62, 0x46, ++0x16, 0x88, 0xFF, 0x20, 0x86, 0x43, 0xA2, 0x4A, 0x93, 0x46, 0x2D, 0x22, 0x5C, 0x46, 0xA2, 0x5C, 0x32, 0x43, 0x64, 0x46, ++0x22, 0x80, 0x9F, 0x4A, 0x9E, 0x18, 0x00, 0x22, 0x94, 0x46, 0x32, 0x80, 0x9D, 0x4A, 0x93, 0x46, 0x9B, 0x44, 0x5A, 0x46, ++0x12, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x5C, 0x46, 0x22, 0x80, 0x9A, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x99, 0x4A, 0x9A, 0x18, ++0x61, 0x46, 0x11, 0x80, 0x98, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x98, 0x4A, 0x99, 0x18, 0x02, 0x22, 0xFF, 0x32, 0x0A, 0x80, ++0x32, 0x88, 0x40, 0x24, 0xA2, 0x43, 0x22, 0x43, 0x32, 0x80, 0x0A, 0x88, 0x82, 0x43, 0xFE, 0x38, 0x02, 0x43, 0x0A, 0x80, ++0x9E, 0x22, 0xBA, 0x5C, 0x14, 0x21, 0x4A, 0x43, 0x8F, 0x49, 0x8C, 0x46, 0x62, 0x44, 0x92, 0xB2, 0x8E, 0x49, 0x59, 0x18, ++0x0A, 0x80, 0x8E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x3F, 0x21, 0x0A, 0x40, 0x8C, 0x49, 0x0A, 0x43, 0x1A, 0x80, ++0x08, 0xAE, 0x31, 0x00, 0x06, 0xA8, 0xAF, 0xF7, 0x9D, 0xF9, 0x06, 0xAB, 0x5A, 0x78, 0x12, 0x02, 0x1B, 0x78, 0x13, 0x43, ++0x62, 0x27, 0x6F, 0x43, 0x85, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x06, 0xAB, 0xDA, 0x78, 0x12, 0x02, 0x9B, 0x78, 0x13, 0x43, ++0x82, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x06, 0xAB, 0x5A, 0x79, 0x12, 0x02, 0x1B, 0x79, 0x13, 0x43, 0x7F, 0x4A, 0xBA, 0x18, ++0x13, 0x80, 0x72, 0x78, 0x12, 0x02, 0x33, 0x78, 0x13, 0x43, 0x7D, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0xF2, 0x78, 0x12, 0x02, ++0xB3, 0x78, 0x13, 0x43, 0x7A, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x00, 0x22, 0x06, 0x2D, 0x01, 0xD8, 0x6A, 0x1C, 0xD2, 0xB2, ++0x08, 0xAB, 0x19, 0x79, 0x03, 0x23, 0x0B, 0x40, 0x92, 0x00, 0x13, 0x43, 0x6E, 0x4A, 0x13, 0x43, 0x6C, 0x4A, 0xBA, 0x18, ++0x13, 0x80, 0x72, 0x48, 0x03, 0x68, 0x72, 0x49, 0x0B, 0x40, 0x80, 0x22, 0x52, 0x01, 0x1A, 0x43, 0x02, 0x60, 0x5A, 0x4B, ++0xFE, 0x18, 0x33, 0x88, 0x02, 0x9A, 0x14, 0x03, 0x24, 0xB2, 0x0B, 0x40, 0x23, 0x43, 0x9B, 0xB2, 0x33, 0x80, 0x4B, 0x46, ++0x00, 0x2B, 0x00, 0xD1, 0xDE, 0xE1, 0x56, 0x4B, 0xFA, 0x18, 0x13, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x80, 0x21, 0x09, 0x02, ++0x0B, 0x43, 0x13, 0x80, 0x33, 0x88, 0x64, 0x4A, 0x13, 0x40, 0x00, 0x9A, 0xD2, 0x02, 0x13, 0x43, 0x9B, 0xB2, 0x33, 0x80, ++0x61, 0x49, 0x0B, 0x68, 0x61, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, 0x13, 0x43, 0x0B, 0x60, 0x4C, 0x4B, 0xFB, 0x18, ++0x00, 0x22, 0x1A, 0x80, 0x49, 0x4B, 0xFB, 0x18, 0x1A, 0x88, 0x08, 0x21, 0x8A, 0x43, 0x1A, 0x80, 0x30, 0x88, 0x31, 0x88, ++0x33, 0x88, 0x80, 0x0B, 0x01, 0x22, 0x10, 0x40, 0x80, 0x03, 0xC9, 0x0A, 0x0A, 0x40, 0xD2, 0x02, 0x10, 0x43, 0x05, 0x43, ++0x58, 0x05, 0x40, 0x0F, 0x00, 0x02, 0x05, 0x43, 0x25, 0x43, 0xAD, 0xB2, 0x35, 0x80, 0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x32, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0xE7, 0xE6, 0xB3, 0x78, 0x99, 0x46, 0xF3, 0x78, 0x98, 0x46, 0x33, 0x79, 0x00, 0x93, 0x72, 0x79, 0x02, 0x92, 0x00, 0x2B, ++0x10, 0xD1, 0x9D, 0x23, 0x00, 0x22, 0xFA, 0x54, 0x32, 0x78, 0x01, 0x3B, 0xFA, 0x54, 0xF2, 0x88, 0x96, 0x23, 0xFA, 0x52, ++0x73, 0x78, 0x07, 0x2B, 0x00, 0xD9, 0x3D, 0xE1, 0x9B, 0x00, 0x3E, 0x49, 0xCB, 0x58, 0x9F, 0x46, 0x31, 0x78, 0x9D, 0x23, ++0xF9, 0x54, 0x3C, 0x48, 0x78, 0xF7, 0x9C, 0xFC, 0x9C, 0x23, 0x00, 0x22, 0xFA, 0x54, 0xEA, 0xE7, 0x39, 0x4B, 0x1A, 0x68, ++0x39, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x30, 0x49, 0x11, 0x40, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x1A, 0x60, ++0x35, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x76, 0xD0, 0x31, 0x49, 0x0B, 0x68, 0x2D, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, ++0x13, 0x43, 0x0B, 0x60, 0x6D, 0xE0, 0x2D, 0x4B, 0x1A, 0x68, 0x2D, 0x49, 0x11, 0x40, 0x80, 0x22, 0x92, 0x01, 0x0A, 0x43, ++0x1A, 0x60, 0x1A, 0x68, 0x22, 0x49, 0x11, 0x40, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x27, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x5A, 0xD0, 0x23, 0x49, 0x0B, 0x68, 0x1F, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, 0x13, 0x43, 0x0B, 0x60, ++0x51, 0xE0, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0x18, 0xD5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF8, 0x64, 0x61, 0x40, ++0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0x0C, 0x65, 0x61, 0x40, 0x60, 0x92, 0x16, 0x00, ++0x0E, 0x65, 0x61, 0x40, 0x56, 0x65, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, ++0x1E, 0x65, 0x61, 0x40, 0xC8, 0x69, 0x00, 0x00, 0x12, 0x65, 0x61, 0x40, 0x0A, 0x65, 0x61, 0x40, 0x40, 0xFF, 0x00, 0x00, ++0x00, 0x65, 0x61, 0x40, 0x02, 0x65, 0x61, 0x40, 0x04, 0x65, 0x61, 0x40, 0x06, 0x65, 0x61, 0x40, 0x08, 0x65, 0x61, 0x40, ++0x00, 0x04, 0x60, 0x40, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x28, 0x04, 0x60, 0x40, 0xFF, 0x7F, 0xFF, 0xFF, ++0x48, 0xD5, 0x10, 0x00, 0x30, 0xD5, 0x10, 0x00, 0xD0, 0x04, 0x60, 0x40, 0xFF, 0xDF, 0xFF, 0xFF, 0xDC, 0xE5, 0x10, 0x00, ++0x94, 0x23, 0xF8, 0x5A, 0x8E, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xF0, 0x21, 0x74, 0xF7, 0x96, 0xFB, 0x8C, 0x4A, 0x13, 0x68, ++0x8C, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x9E, 0x23, 0xFA, 0x5C, 0x52, 0x00, 0x10, 0x33, 0xFB, 0x5C, 0xD2, 0x18, 0xD2, 0xB2, ++0x62, 0x23, 0x6B, 0x43, 0x87, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x03, 0x93, 0x02, 0x20, 0x07, 0x23, 0x9A, 0x46, 0x04, 0x95, ++0x05, 0x96, 0x91, 0x00, 0x89, 0x18, 0x49, 0x00, 0x82, 0x4B, 0xCC, 0x18, 0x23, 0x88, 0x78, 0x25, 0xAB, 0x43, 0x70, 0x3D, ++0x2B, 0x43, 0x9B, 0xB2, 0x23, 0x80, 0x03, 0x9B, 0x1B, 0x88, 0x25, 0x88, 0xAB, 0x46, 0x1B, 0x0A, 0x55, 0x46, 0x2B, 0x40, ++0x5D, 0x46, 0x56, 0x46, 0xB5, 0x43, 0x2B, 0x43, 0x23, 0x80, 0x79, 0x4B, 0x9C, 0x46, 0x8C, 0x44, 0x63, 0x46, 0x1B, 0x88, ++0x77, 0x4C, 0x23, 0x40, 0x64, 0x46, 0x23, 0x80, 0x76, 0x4B, 0xCB, 0x18, 0x00, 0x24, 0x1C, 0x80, 0x75, 0x4B, 0x9C, 0x46, ++0x61, 0x44, 0x9E, 0x23, 0xFB, 0x5C, 0x5B, 0x00, 0x01, 0x34, 0x54, 0x40, 0xE4, 0xB2, 0xA4, 0x46, 0x63, 0x44, 0x9C, 0x00, ++0xA4, 0x46, 0x63, 0x44, 0x5B, 0x00, 0x6F, 0x4C, 0xA4, 0x46, 0x63, 0x44, 0x6E, 0x4C, 0x23, 0x43, 0x9B, 0xB2, 0x0B, 0x80, ++0x0B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x0B, 0x80, 0x53, 0x42, 0x5A, 0x41, 0xD2, 0xB2, 0x01, 0x38, 0xC0, 0xB2, 0x00, 0x28, ++0xB9, 0xD1, 0x04, 0x9D, 0x05, 0x9E, 0x31, 0x00, 0x08, 0x31, 0x06, 0x22, 0x06, 0xA8, 0xCD, 0xF7, 0xA5, 0xF9, 0x00, 0x21, ++0x02, 0x26, 0xF2, 0xE5, 0x94, 0x23, 0xF8, 0x5A, 0x56, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xAA, 0x21, 0x74, 0xF7, 0x26, 0xFB, ++0x54, 0x4A, 0x13, 0x68, 0x54, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x8E, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x4F, 0x4B, 0x9C, 0x46, ++0x60, 0x44, 0xFF, 0x21, 0x74, 0xF7, 0x18, 0xFB, 0x4D, 0x4A, 0x13, 0x68, 0x4D, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x80, 0xE7, ++0x94, 0x23, 0xF8, 0x5A, 0x48, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x74, 0xF7, 0x0A, 0xFB, 0x46, 0x4A, 0x13, 0x68, ++0x46, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x72, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x41, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x0F, 0x21, ++0x74, 0xF7, 0xFC, 0xFA, 0x3F, 0x4A, 0x13, 0x68, 0x3F, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x64, 0xE7, 0x94, 0x23, 0xF8, 0x5A, ++0x3A, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x55, 0x21, 0x74, 0xF7, 0xEE, 0xFA, 0x38, 0x4A, 0x13, 0x68, 0x38, 0x49, 0x0B, 0x40, ++0x13, 0x60, 0x56, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x33, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x74, 0xF7, 0xE0, 0xFA, ++0x31, 0x4A, 0x13, 0x68, 0x31, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x48, 0xE7, 0xB3, 0x78, 0x98, 0x46, 0xF3, 0x78, 0x00, 0x93, ++0xB4, 0x79, 0xF1, 0x1D, 0x06, 0x22, 0x06, 0xA8, 0xCD, 0xF7, 0x44, 0xF9, 0x00, 0x22, 0x33, 0x4B, 0x99, 0x46, 0xD5, 0x23, ++0x5B, 0x00, 0x9C, 0x46, 0x03, 0x26, 0x17, 0x3B, 0xFF, 0x3B, 0x9B, 0x46, 0x0A, 0xE0, 0x2F, 0x49, 0x8A, 0x46, 0x53, 0x44, ++0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x19, 0x80, 0x01, 0x32, 0xD2, 0xB2, 0x04, 0x2A, 0x11, 0xD0, 0x4B, 0x46, 0x61, 0x46, ++0x5B, 0x5C, 0xD3, 0x18, 0x33, 0x40, 0xD9, 0x00, 0xCB, 0x1A, 0x5B, 0x00, 0x26, 0x49, 0x58, 0x18, 0x01, 0x88, 0x89, 0xB2, ++0x00, 0x29, 0xE6, 0xD1, 0x59, 0x46, 0x79, 0x5A, 0x01, 0x80, 0xE2, 0xE7, 0x02, 0x94, 0x00, 0x23, 0x99, 0x46, 0x21, 0x49, ++0x03, 0x26, 0x66, 0xE5, 0x20, 0x4B, 0xFA, 0x18, 0x13, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x13, 0x80, 0x43, 0x46, 0xDB, 0x07, ++0x0F, 0xD4, 0x11, 0x88, 0x43, 0x46, 0x5B, 0x08, 0x1B, 0x02, 0x1B, 0x48, 0x01, 0x40, 0x0B, 0x43, 0x13, 0x80, 0x43, 0x46, ++0x5B, 0x08, 0x28, 0x33, 0x19, 0x00, 0x18, 0x48, 0x78, 0xF7, 0x0A, 0xFB, 0x10, 0xE6, 0x10, 0x88, 0x43, 0x46, 0x5B, 0x08, ++0x28, 0x33, 0x1B, 0x02, 0x12, 0x49, 0x01, 0x40, 0x0B, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0xEC, 0xE7, 0x00, 0x00, 0x61, 0x40, ++0xD0, 0x04, 0x60, 0x40, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0x64, 0x61, 0x40, 0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, ++0x07, 0xE0, 0xFF, 0xFF, 0xCE, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, ++0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, 0x9A, 0x69, 0x61, 0x40, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x65, 0x61, 0x40, ++0xFF, 0x80, 0xFF, 0xFF, 0x3C, 0xD5, 0x10, 0x00, 0x10, 0xB5, 0x07, 0x4B, 0x1C, 0x68, 0xA3, 0x78, 0x00, 0x2B, 0x00, 0xD1, ++0x10, 0xBD, 0x00, 0x23, 0x0A, 0x00, 0xE1, 0x68, 0xFF, 0xF7, 0xE2, 0xFC, 0x00, 0x23, 0xA3, 0x70, 0xF6, 0xE7, 0xC0, 0x46, ++0xD8, 0xE5, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x05, 0x00, 0x82, 0x00, 0x52, 0x4B, 0xD4, 0x58, 0x00, 0x2C, ++0x00, 0xD1, 0x98, 0xE0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, 0x4E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, 0xDB, 0xB2, 0xA3, 0x54, 0x09, 0x3A, 0xA2, 0x5C, 0x02, 0x3A, ++0x01, 0x2A, 0x01, 0xD8, 0x00, 0x2B, 0x14, 0xD0, 0x9F, 0xF7, 0xD2, 0xFD, 0x06, 0x00, 0x01, 0x00, 0x28, 0x00, 0xFF, 0xF7, ++0xA9, 0xFB, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x68, 0xE0, 0x3F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x01, 0x21, 0x20, 0x00, 0xCA, 0xF7, 0xEF, 0xFD, 0xA0, 0x23, ++0x02, 0x22, 0xE2, 0x54, 0xFF, 0xF7, 0xF4, 0xFB, 0x37, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, ++0x5B, 0x00, 0x35, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0xD2, 0x0B, 0xE7, 0xD0, 0x33, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, ++0xD2, 0x0A, 0xAA, 0x42, 0x07, 0xD0, 0x19, 0x88, 0xC9, 0x0A, 0x2C, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x28, 0x00, ++0xA0, 0x47, 0x2A, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x22, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x27, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x19, 0x40, 0x21, 0x54, ++0x23, 0x4B, 0x1A, 0x68, 0xCB, 0x00, 0x5B, 0x1A, 0x5B, 0x00, 0x22, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x52, 0x04, 0x52, 0x0C, ++0x93, 0x42, 0x05, 0xD0, 0x19, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x18, 0x4E, 0x00, 0x24, ++0xD5, 0x23, 0x5B, 0x00, 0x98, 0x46, 0x14, 0x4F, 0x03, 0xE0, 0x01, 0x34, 0x0E, 0x36, 0x04, 0x2C, 0xA8, 0xD0, 0x33, 0x88, ++0xDB, 0x0B, 0xF8, 0xD0, 0x10, 0x4B, 0x42, 0x46, 0x98, 0x5C, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xFD, 0x6E, 0xA8, 0x47, ++0xEF, 0xE7, 0x01, 0x21, 0x20, 0x00, 0xCA, 0xF7, 0x8F, 0xFD, 0x02, 0x36, 0x66, 0x60, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, ++0x4F, 0xFF, 0x20, 0x00, 0xF4, 0xF7, 0xA6, 0xFA, 0x8E, 0xE7, 0x04, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, ++0xA0, 0x47, 0x87, 0xE7, 0x38, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, ++0x92, 0x69, 0x61, 0x40, 0x2C, 0x04, 0x60, 0x40, 0x90, 0x69, 0x00, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, ++0x14, 0x00, 0xCF, 0xB2, 0x06, 0x2F, 0x07, 0xD9, 0xFF, 0x20, 0x08, 0x40, 0x0B, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x21, 0x00, 0xB0, 0x47, 0x00, 0x2C, 0x09, 0xD0, 0xFF, 0x20, 0x28, 0x40, 0x06, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x21, 0x00, 0xA8, 0x47, 0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x99, 0x38, 0x00, 0xFF, 0xF7, 0x28, 0xFF, 0xF8, 0xE7, 0xC0, 0x46, ++0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x96, 0xB0, 0x2F, 0x4B, 0x1B, 0x68, 0xD9, 0x68, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x51, 0xD4, 0x72, 0xB6, 0x10, 0x31, 0x24, 0x22, 0x0D, 0xA8, 0xCC, 0xF7, 0xCF, 0xFF, 0x62, 0xB6, ++0x0D, 0x9C, 0x00, 0x26, 0x00, 0x2C, 0x07, 0xD0, 0x0E, 0x9B, 0xE3, 0x1A, 0x64, 0x20, 0x58, 0x43, 0x21, 0x00, 0xCC, 0xF7, ++0x75, 0xFB, 0x06, 0x00, 0x13, 0x9D, 0x00, 0x20, 0x00, 0x2D, 0x05, 0xD0, 0x21, 0x48, 0x14, 0x9B, 0x58, 0x43, 0x29, 0x00, ++0xCC, 0xF7, 0x6A, 0xFB, 0x11, 0x9A, 0x12, 0x9F, 0x15, 0x99, 0x13, 0x00, 0x3B, 0x43, 0x0B, 0x43, 0x1B, 0xD0, 0x0F, 0x9B, ++0x98, 0x46, 0x0E, 0x9B, 0x9C, 0x46, 0x00, 0x23, 0x09, 0x93, 0x08, 0x90, 0x07, 0x93, 0x06, 0x96, 0x14, 0x9B, 0x0B, 0x93, ++0x05, 0x93, 0x04, 0x95, 0x03, 0x91, 0x02, 0x97, 0x01, 0x92, 0x10, 0x9B, 0x00, 0x93, 0x43, 0x46, 0x22, 0x00, 0x61, 0x46, ++0x11, 0x48, 0x78, 0xF7, 0xA5, 0xF9, 0x16, 0xB0, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0F, 0x9B, 0x0E, 0x99, 0x00, 0x22, ++0x06, 0x92, 0x05, 0x90, 0x04, 0x92, 0x03, 0x96, 0x14, 0x9A, 0x0B, 0x92, 0x02, 0x92, 0x01, 0x95, 0x10, 0x9A, 0x00, 0x92, ++0x22, 0x00, 0x08, 0x48, 0x78, 0xF7, 0x90, 0xF9, 0xE9, 0xE7, 0x10, 0x31, 0x24, 0x22, 0x0D, 0xA8, 0xCC, 0xF7, 0x7E, 0xFF, ++0xAE, 0xE7, 0xC0, 0x46, 0xD8, 0xE5, 0x10, 0x00, 0x10, 0x27, 0x00, 0x00, 0x68, 0xD5, 0x10, 0x00, 0xC8, 0xD5, 0x10, 0x00, ++0x70, 0x47, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x05, 0x00, 0x0F, 0x00, 0x16, 0x00, 0x1C, 0x00, 0x4B, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x05, 0xD0, 0x4A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x21, ++0x10, 0x20, 0x76, 0xF7, 0x37, 0xF9, 0x44, 0x4B, 0x18, 0x60, 0x00, 0x28, 0x10, 0xD0, 0x42, 0x4B, 0x18, 0x68, 0x10, 0x22, ++0x00, 0x21, 0x74, 0xF7, 0xDF, 0xF8, 0x00, 0x2D, 0x0E, 0xD0, 0x01, 0x2D, 0x2C, 0xD0, 0x3E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x1B, 0xE0, 0x3A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x98, 0x47, 0xE8, 0xE7, ++0x36, 0x4C, 0x25, 0x68, 0x00, 0x21, 0x0E, 0x20, 0x76, 0xF7, 0x16, 0xF9, 0xE8, 0x60, 0x23, 0x68, 0xDB, 0x68, 0x00, 0x2B, ++0x0D, 0xD0, 0x31, 0x4C, 0x23, 0x68, 0xD8, 0x68, 0x0E, 0x22, 0x00, 0x21, 0x74, 0xF7, 0xBC, 0xF8, 0x23, 0x68, 0x00, 0x22, ++0x5A, 0x70, 0xDE, 0x70, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0xEA, 0xE7, 0x26, 0x4D, 0x2B, 0x68, 0x98, 0x46, 0x00, 0x21, 0x38, 0x20, 0x76, 0xF7, 0xF5, 0xF8, 0x43, 0x46, ++0xD8, 0x60, 0x2B, 0x68, 0xDB, 0x68, 0x00, 0x2B, 0x31, 0xD0, 0x20, 0x4D, 0x2B, 0x68, 0xD8, 0x68, 0x38, 0x22, 0x00, 0x21, ++0x74, 0xF7, 0x9A, 0xF8, 0x2B, 0x68, 0x98, 0x46, 0x00, 0x21, 0x28, 0x20, 0x76, 0xF7, 0xE2, 0xF8, 0x43, 0x46, 0x98, 0x60, ++0x2B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0x25, 0xD0, 0x16, 0x4D, 0x2B, 0x68, 0x98, 0x68, 0x28, 0x22, 0x00, 0x21, 0x74, 0xF7, ++0x87, 0xF8, 0x2B, 0x68, 0xD8, 0x68, 0x0E, 0x22, 0x39, 0x00, 0xCC, 0xF7, 0xF5, 0xFE, 0x2B, 0x68, 0x01, 0x22, 0x5A, 0x70, ++0xC8, 0x22, 0x52, 0x01, 0x5A, 0x60, 0xDE, 0x70, 0x0E, 0x48, 0x0F, 0x4A, 0x82, 0x60, 0x5B, 0x68, 0xE4, 0x18, 0x24, 0x01, ++0x24, 0x09, 0x44, 0x60, 0xCA, 0xF7, 0xA0, 0xFF, 0xB6, 0xE7, 0x08, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0xC6, 0xE7, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD2, 0xE7, 0xC0, 0x46, ++0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xFC, 0xE6, 0x10, 0x00, 0xD5, 0x01, 0x10, 0x00, 0xF8, 0xB5, 0x04, 0x00, ++0x4E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0xF7, 0xB8, 0xFA, 0x05, 0x00, 0x28, 0x00, 0xF8, 0xBD, 0x4B, 0x48, ++0x78, 0xF7, 0xCA, 0xF8, 0x4A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x07, 0xD0, 0x49, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0xEE, 0xE7, 0x00, 0x21, 0xF8, 0x20, 0x76, 0xF7, 0x88, 0xF8, 0x42, 0x4B, 0x18, 0x60, ++0x00, 0x28, 0x75, 0xD0, 0x9F, 0xF7, 0xE0, 0xFB, 0x07, 0x00, 0x84, 0xF7, 0x81, 0xF9, 0x40, 0x4A, 0x13, 0x88, 0x40, 0x49, ++0x0B, 0x40, 0x00, 0x02, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x3A, 0x4B, 0x1E, 0x68, 0xF8, 0x22, 0x00, 0x21, 0x30, 0x00, ++0x74, 0xF7, 0x22, 0xF8, 0x00, 0x23, 0x73, 0x62, 0x39, 0x4A, 0xF2, 0x61, 0x39, 0x4A, 0x32, 0x62, 0x03, 0x22, 0x32, 0x76, ++0x38, 0x4A, 0x12, 0x78, 0xB2, 0x75, 0x38, 0x4A, 0x32, 0x61, 0x05, 0x22, 0xF2, 0x75, 0x99, 0x32, 0xB3, 0x54, 0x01, 0x32, ++0xB3, 0x54, 0x02, 0x32, 0xB3, 0x54, 0x03, 0x32, 0x28, 0x21, 0xB1, 0x52, 0x1C, 0x3A, 0xB3, 0x52, 0x80, 0xF7, 0x72, 0xF8, ++0x05, 0x1E, 0x05, 0xD1, 0x28, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x94, 0x23, 0xF5, 0x52, ++0x93, 0x3B, 0x00, 0x22, 0x21, 0x00, 0x00, 0x20, 0xFF, 0xF7, 0x8A, 0xFA, 0x28, 0x4A, 0x13, 0x88, 0x1F, 0x21, 0x0B, 0x40, ++0x13, 0x80, 0x77, 0x60, 0x00, 0x23, 0x82, 0x22, 0xB3, 0x52, 0xB3, 0x60, 0x00, 0x22, 0xA6, 0x33, 0xF2, 0x54, 0x20, 0x3B, ++0xFA, 0x22, 0xD2, 0x01, 0xF2, 0x52, 0x37, 0x67, 0x20, 0x4B, 0xB3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0xFB, 0x18, 0x1B, 0x01, ++0x1B, 0x09, 0xF3, 0x60, 0x30, 0x00, 0xCA, 0xF7, 0x15, 0xFA, 0x05, 0x1E, 0x07, 0xD0, 0x12, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0x7F, 0xE7, 0xA0, 0x23, 0x00, 0x22, 0xF2, 0x54, 0x01, 0x32, 0x00, 0x21, ++0x00, 0x20, 0x9F, 0xF7, 0xF3, 0xF8, 0x3B, 0x00, 0x00, 0x22, 0x21, 0x00, 0x00, 0x20, 0xFF, 0xF7, 0xC3, 0xFE, 0x70, 0xE7, ++0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0x68, 0xE7, 0xD8, 0xE5, 0x10, 0x00, ++0x10, 0xD6, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, ++0xF1, 0x02, 0x10, 0x00, 0xD1, 0x01, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x6A, 0x04, 0x00, 0x00, 0xF8, 0x64, 0x61, 0x40, ++0x00, 0x80, 0xFF, 0xFF, 0x10, 0xB5, 0x00, 0x29, 0x12, 0xD1, 0x03, 0x78, 0xFF, 0x2B, 0x0A, 0xD1, 0x43, 0x78, 0xC1, 0x2B, ++0x2F, 0xD1, 0x83, 0x78, 0xFB, 0x2B, 0x2E, 0xD1, 0xC1, 0x78, 0xE8, 0x39, 0x4B, 0x42, 0x59, 0x41, 0x03, 0x31, 0x04, 0x39, ++0x48, 0x42, 0x48, 0x41, 0xC0, 0xB2, 0x10, 0xBD, 0x03, 0x29, 0x0C, 0xD0, 0x12, 0x4B, 0x5C, 0x5C, 0x00, 0x23, 0xD9, 0xB2, ++0xC2, 0x5C, 0xA2, 0x42, 0xF1, 0xD1, 0x01, 0x31, 0xC9, 0xB2, 0x01, 0x33, 0x04, 0x2B, 0xF6, 0xD1, 0xEB, 0xE7, 0x03, 0x78, ++0xFF, 0x2B, 0x0A, 0xD1, 0x43, 0x78, 0xC1, 0x2B, 0x09, 0xD1, 0x83, 0x78, 0xFB, 0x2B, 0x08, 0xD1, 0xC3, 0x78, 0xE8, 0x2B, ++0xDF, 0xD1, 0x04, 0x21, 0xDD, 0xE7, 0x00, 0x21, 0xDB, 0xE7, 0x01, 0x21, 0xD9, 0xE7, 0x02, 0x21, 0xD7, 0xE7, 0x01, 0x21, ++0xD5, 0xE7, 0x02, 0x21, 0xD3, 0xE7, 0xC0, 0x46, 0x1C, 0xE0, 0x10, 0x00, 0xF8, 0xB5, 0x23, 0x4B, 0x1B, 0x68, 0x00, 0x2B, ++0x3A, 0xD0, 0xDA, 0x68, 0x53, 0x78, 0x00, 0x2B, 0x10, 0xD1, 0x95, 0x88, 0x00, 0x2D, 0x0C, 0xD0, 0x1E, 0x4F, 0x1F, 0x4E, ++0xF1, 0x5C, 0xC4, 0x5C, 0x61, 0x40, 0x79, 0x5C, 0xD4, 0x6A, 0xA4, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xAB, 0x42, ++0xF4, 0xD3, 0xF8, 0xBD, 0x03, 0x2B, 0x11, 0xD0, 0x18, 0x49, 0xCD, 0x5C, 0x94, 0x88, 0x00, 0x2C, 0xF7, 0xD0, 0x00, 0x23, ++0x13, 0x4E, 0xC1, 0x5C, 0x69, 0x40, 0x71, 0x5C, 0xD7, 0x6A, 0xBC, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xA3, 0x42, ++0xF5, 0xD3, 0xEA, 0xE7, 0x95, 0x88, 0x00, 0x2D, 0xE7, 0xD0, 0x00, 0x23, 0x0B, 0x4F, 0x0E, 0x4E, 0xF1, 0x5C, 0xC4, 0x5C, ++0x61, 0x40, 0x79, 0x5C, 0xD4, 0x6A, 0xA4, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xAB, 0x42, 0xF4, 0xD3, 0xD8, 0xE7, ++0x08, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD1, 0xE7, 0xC0, 0x46, 0xD8, 0xE5, 0x10, 0x00, ++0xBC, 0xDE, 0x10, 0x00, 0xBC, 0xDA, 0x10, 0x00, 0x1C, 0xE0, 0x10, 0x00, 0xBC, 0xD6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x06, 0x00, 0x74, 0x4B, 0x1B, 0x68, 0xDD, 0x68, ++0x54, 0x1E, 0xE4, 0xB2, 0x00, 0x2A, 0x00, 0xD1, 0xDA, 0xE0, 0x71, 0x4F, 0xAB, 0xE0, 0x04, 0x21, 0x08, 0x00, 0x10, 0x40, ++0x11, 0x42, 0x2F, 0xD0, 0xE9, 0x69, 0x01, 0x31, 0xE9, 0x61, 0xDB, 0x04, 0x9B, 0x0D, 0x99, 0x46, 0xB8, 0x23, 0x13, 0x42, ++0x5B, 0xD1, 0xAB, 0x88, 0xDB, 0x00, 0xAA, 0x6A, 0x94, 0x46, 0x63, 0x44, 0xAB, 0x62, 0xD5, 0x23, 0x5B, 0x00, 0x65, 0x4A, ++0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x63, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x83, 0xB2, 0x9A, 0x46, ++0x00, 0x2B, 0x06, 0xD1, 0x60, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x4B, 0x46, ++0x00, 0x2B, 0x53, 0xD0, 0x43, 0x46, 0x59, 0x06, 0x09, 0x0F, 0x5B, 0x48, 0x50, 0x44, 0xFF, 0xF7, 0x67, 0xFF, 0x4B, 0xE0, ++0x69, 0x69, 0x01, 0x31, 0x69, 0x61, 0xDB, 0x04, 0x9B, 0x0D, 0x99, 0x46, 0xB8, 0x23, 0x13, 0x42, 0x00, 0xD0, 0x95, 0xE0, ++0x00, 0x28, 0xCC, 0xD1, 0xAB, 0x88, 0x4B, 0x45, 0x2B, 0xD0, 0x6B, 0x6A, 0x01, 0x33, 0x6B, 0x62, 0x4C, 0x4A, 0xD5, 0x23, ++0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x4A, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x83, 0xB2, ++0x98, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x47, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x4B, 0x46, ++0x00, 0x2B, 0x21, 0xD0, 0x69, 0x78, 0x43, 0x48, 0x40, 0x44, 0xFF, 0xF7, 0xF7, 0xFE, 0x00, 0x28, 0x1A, 0xD1, 0x2B, 0x6B, ++0x01, 0x33, 0x2B, 0x63, 0x16, 0xE0, 0x2B, 0x6A, 0x01, 0x33, 0x2B, 0x62, 0x00, 0x28, 0x11, 0xD1, 0xD0, 0xE7, 0xDB, 0x00, ++0xAA, 0x6A, 0x94, 0x46, 0x63, 0x44, 0xAB, 0x62, 0xD0, 0xE7, 0x35, 0x23, 0xEB, 0x5C, 0x01, 0x33, 0xDB, 0xB2, 0x64, 0x2B, ++0x54, 0xD8, 0x35, 0x22, 0xAB, 0x54, 0x34, 0x23, 0x00, 0x22, 0xEA, 0x54, 0x2F, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, ++0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x2D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x05, 0xD1, ++0x2A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x25, 0x48, 0xD5, 0x21, 0x49, 0x00, 0x42, 0x5C, ++0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x26, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, ++0x42, 0x5C, 0x01, 0x32, 0x03, 0x23, 0x13, 0x40, 0x43, 0x54, 0x01, 0x3C, 0xE4, 0xB2, 0xFF, 0x2C, 0x2C, 0xD0, 0x30, 0x00, ++0x9E, 0xF7, 0x5A, 0xFF, 0x00, 0x28, 0x27, 0xD0, 0xD5, 0x23, 0x5B, 0x00, 0xFA, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, ++0x19, 0x4A, 0x9A, 0x18, 0x10, 0x88, 0x82, 0xB2, 0x18, 0x49, 0x59, 0x18, 0x09, 0x88, 0x89, 0xB2, 0x88, 0x46, 0x17, 0x49, ++0x8C, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9B, 0xB2, 0xC1, 0x07, 0xAE, 0xD4, 0x29, 0x69, 0x01, 0x31, 0x29, 0x61, 0x91, 0x07, ++0x00, 0xD4, 0x32, 0xE7, 0xAB, 0x69, 0x01, 0x33, 0xAB, 0x61, 0xAF, 0xE7, 0x35, 0x23, 0x64, 0x22, 0xEA, 0x54, 0xA8, 0xE7, ++0x2B, 0x6A, 0x01, 0x33, 0x2B, 0x62, 0x67, 0xE7, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, ++0xD8, 0xE5, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x9A, 0x69, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, ++0x90, 0x69, 0x61, 0x40, 0x92, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, 0x96, 0x69, 0x61, 0x40, 0xF0, 0xB5, 0xD6, 0x46, ++0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x89, 0x46, 0x82, 0x00, 0x41, 0x4B, 0xD5, 0x58, 0xA6, 0x23, 0xEF, 0x5C, 0x2E, 0x6D, ++0x44, 0x3B, 0x58, 0x43, 0x3E, 0x4B, 0xC3, 0x18, 0x1B, 0x88, 0x3E, 0x4A, 0x82, 0x18, 0x14, 0x88, 0x1B, 0x04, 0x1C, 0x43, ++0xA2, 0x46, 0x3C, 0x4B, 0xC3, 0x18, 0x1B, 0x88, 0x9B, 0x05, 0x9B, 0x0D, 0x98, 0x46, 0x3A, 0x4B, 0xC3, 0x18, 0x1C, 0x88, ++0x39, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x01, 0x88, 0x24, 0x04, 0x0C, 0x19, 0x37, 0x4B, 0x9E, 0x42, 0x1C, 0xD8, 0x53, 0x46, ++0x4A, 0x46, 0x9B, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x80, 0x22, 0x12, 0x05, 0x91, 0x42, 0x40, 0xD9, 0x4B, 0x46, 0x52, 0x46, ++0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0x3D, 0xD0, 0x00, 0x2B, 0x07, 0xDB, ++0x89, 0x08, 0x00, 0x29, 0x04, 0xDD, 0x89, 0x00, 0x49, 0x44, 0x09, 0x01, 0x0B, 0x09, 0x99, 0x46, 0x53, 0x46, 0xE1, 0x1A, ++0x49, 0x44, 0x09, 0x01, 0x09, 0x09, 0xF4, 0x23, 0x5B, 0x00, 0x42, 0x46, 0x9B, 0x1A, 0x32, 0xD4, 0xA9, 0x67, 0x82, 0x22, ++0xAB, 0x52, 0x4A, 0x42, 0x03, 0x20, 0x10, 0x40, 0xA6, 0x22, 0xA8, 0x54, 0x72, 0x3A, 0x2A, 0x65, 0xAB, 0x60, 0x34, 0x2E, ++0x09, 0xD9, 0xEA, 0x7D, 0x00, 0x2A, 0x06, 0xD0, 0xC8, 0x22, 0x52, 0x00, 0x9A, 0x42, 0x92, 0x41, 0x52, 0x42, 0x05, 0x32, ++0xEA, 0x75, 0x69, 0x67, 0x84, 0x22, 0xAB, 0x52, 0xC0, 0x1B, 0x43, 0x1E, 0x98, 0x41, 0xC0, 0xB2, 0x1C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0x1B, 0x01, 0x1B, 0x09, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0xC4, 0xD0, 0xC1, 0xE7, ++0x00, 0x2B, 0xC1, 0xDA, 0x0D, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xC2, 0xE7, 0x0B, 0x4B, ++0x9B, 0x1A, 0x01, 0x31, 0x09, 0x01, 0x09, 0x09, 0xC6, 0xE7, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0x4C, 0x65, 0x61, 0x40, ++0x4A, 0x65, 0x61, 0x40, 0x4E, 0x65, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, 0xE1, 0x04, 0x00, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x59, 0x04, 0x00, 0x00, 0xF8, 0xB5, 0x80, 0x00, 0x25, 0x4B, 0xC5, 0x58, 0xA6, 0x23, 0xEE, 0x5C, ++0x6C, 0x6F, 0xEB, 0x6E, 0xC8, 0x1A, 0x00, 0x01, 0x00, 0x09, 0x22, 0x49, 0x48, 0x43, 0x22, 0x49, 0xCB, 0xF7, 0x84, 0xFF, ++0x1A, 0x30, 0x40, 0x00, 0x02, 0x00, 0x34, 0x3A, 0x52, 0x08, 0x84, 0x23, 0xEB, 0x5A, 0x9B, 0x1A, 0x19, 0xB2, 0x1B, 0x04, ++0x27, 0xD5, 0x00, 0x23, 0x1B, 0x4A, 0x8A, 0x18, 0x11, 0xB2, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0x1F, 0x00, 0x01, 0x33, ++0xDB, 0xB2, 0x12, 0x04, 0xF4, 0xD4, 0xAC, 0x67, 0x82, 0x22, 0xA9, 0x52, 0x64, 0x42, 0x7F, 0x3A, 0x14, 0x40, 0xA3, 0x32, ++0xAC, 0x54, 0x28, 0x65, 0xA9, 0x60, 0x00, 0x2B, 0x0A, 0xD0, 0xEB, 0x7D, 0x00, 0x2B, 0x07, 0xD0, 0xC8, 0x23, 0x5B, 0x00, ++0x8B, 0x42, 0x9B, 0x41, 0x5B, 0x42, 0x06, 0x37, 0xDF, 0x19, 0xEF, 0x75, 0x34, 0x1B, 0x66, 0x1E, 0xB4, 0x41, 0xE0, 0xB2, ++0xF8, 0xBD, 0xAC, 0x67, 0x82, 0x23, 0xE9, 0x52, 0x64, 0x42, 0x7F, 0x3B, 0x1C, 0x40, 0xA3, 0x33, 0xEC, 0x54, 0x28, 0x65, ++0xA9, 0x60, 0xEF, 0xE7, 0x38, 0xE6, 0x10, 0x00, 0xA8, 0x61, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x71, 0x02, 0x00, 0x00, ++0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x8A, 0xB0, 0x0E, 0x00, 0x8A, 0x00, 0x52, 0x4B, 0xD5, 0x58, 0x00, 0x2D, 0x00, 0xD1, ++0x9B, 0xE0, 0xA6, 0x23, 0x98, 0x46, 0xEB, 0x5C, 0x01, 0x33, 0x03, 0x24, 0x23, 0x40, 0x1F, 0x00, 0x9F, 0xF7, 0xB0, 0xF8, ++0x00, 0x90, 0x03, 0x00, 0xA3, 0x43, 0x3B, 0x43, 0x42, 0x46, 0xAA, 0x5C, 0xD2, 0x1A, 0x14, 0x40, 0x04, 0x3B, 0xE4, 0x18, ++0x24, 0x01, 0x24, 0x09, 0x23, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x22, 0x12, 0x05, 0x93, 0x42, 0x02, 0xD9, 0x03, 0x1B, ++0x1B, 0x01, 0x59, 0xD1, 0x00, 0x23, 0x01, 0x93, 0x01, 0xA9, 0x68, 0x46, 0x9F, 0xF7, 0x9C, 0xF8, 0x01, 0x9B, 0x1A, 0x00, ++0x0F, 0x32, 0xFF, 0x32, 0x9C, 0x21, 0x89, 0x00, 0x8A, 0x42, 0x57, 0xD8, 0x01, 0x92, 0x00, 0x9A, 0x13, 0x1B, 0x1B, 0x01, ++0x1B, 0x09, 0x38, 0x49, 0x8B, 0x42, 0x05, 0xD8, 0xA2, 0x42, 0x61, 0xD1, 0xAB, 0x68, 0x01, 0x9A, 0x93, 0x42, 0x5D, 0xD9, ++0x02, 0xA8, 0x34, 0x4B, 0x02, 0x93, 0x44, 0x60, 0xAB, 0x68, 0x83, 0x60, 0x06, 0x76, 0x06, 0x61, 0x31, 0x4B, 0xC3, 0x60, ++0xAB, 0x7D, 0x03, 0x75, 0x01, 0x33, 0x43, 0x75, 0x00, 0x23, 0x83, 0x75, 0xB0, 0x22, 0xAA, 0x5C, 0xC2, 0x75, 0x83, 0x76, ++0xC3, 0x76, 0x01, 0x33, 0x43, 0x76, 0xCA, 0xF7, 0xD7, 0xFE, 0xA9, 0x22, 0xAB, 0x5C, 0x01, 0x33, 0xAB, 0x54, 0xAA, 0x23, ++0xEB, 0x5C, 0x00, 0x2B, 0x31, 0xD1, 0x9F, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x3B, 0xD1, 0xAB, 0x6F, 0x9B, 0xB2, 0x62, 0x21, ++0x4E, 0x43, 0x22, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0xAB, 0x6F, 0x1B, 0x0C, 0x20, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0x20, 0x4B, ++0x9C, 0x46, 0x66, 0x44, 0x2B, 0x6D, 0x01, 0x33, 0x5B, 0x08, 0x01, 0x33, 0x5B, 0x08, 0x1D, 0x4A, 0x13, 0x43, 0x9B, 0xB2, ++0x33, 0x80, 0x22, 0xE0, 0x04, 0x34, 0x24, 0x01, 0x24, 0x09, 0x23, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x93, 0x42, 0x9D, 0xD9, ++0x03, 0x1B, 0x1B, 0x01, 0x9A, 0xD0, 0xF3, 0xE7, 0x64, 0x3B, 0xFF, 0x3B, 0x01, 0x93, 0x00, 0x9B, 0x01, 0x33, 0x1B, 0x01, ++0x1B, 0x09, 0x00, 0x93, 0x9F, 0xE7, 0x9E, 0x23, 0xE8, 0x5C, 0xCB, 0xF7, 0x21, 0xF8, 0x0F, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xAA, 0x23, 0x00, 0x22, 0xEA, 0x54, 0xC2, 0xE7, 0x0C, 0x48, 0x77, 0xF7, 0xF1, 0xFC, 0x0A, 0xB0, 0x04, 0xBC, 0x90, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, ++0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0x18, 0x00, 0x60, 0x40, ++0x28, 0xD6, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x82, 0xB0, 0x05, 0x00, 0x0E, 0x00, 0x82, 0x00, 0x9D, 0x4B, ++0xD4, 0x58, 0x00, 0x2C, 0x00, 0xD1, 0x2B, 0xE1, 0x9B, 0x4B, 0x1B, 0x68, 0xDF, 0x68, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x05, 0xD1, 0x99, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, ++0xDB, 0xB2, 0xA3, 0x54, 0x09, 0x3A, 0xA2, 0x5C, 0x02, 0x2A, 0x01, 0xD1, 0x00, 0x2B, 0x51, 0xD0, 0x9E, 0xF7, 0xDE, 0xFF, ++0x01, 0x90, 0x01, 0x22, 0x31, 0x00, 0x28, 0x00, 0xFF, 0xF7, 0x20, 0xFD, 0x62, 0x23, 0x6B, 0x43, 0x8C, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1B, 0x88, 0xDB, 0x0B, 0x00, 0xD1, 0xAC, 0xE0, 0x31, 0x00, 0x28, 0x00, 0xFF, 0xF7, 0x15, 0xFE, 0xB4, 0x23, ++0xE0, 0x54, 0xA0, 0x23, 0xE3, 0x5C, 0x02, 0x2B, 0x00, 0xD1, 0xEA, 0xE0, 0x01, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0xBA, 0xF9, ++0x82, 0x23, 0xE3, 0x5E, 0xA3, 0x60, 0x81, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x0C, 0xD0, 0x34, 0x23, 0xFB, 0x5C, 0x00, 0x2B, ++0x00, 0xD1, 0x9D, 0xE0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x93, 0xE0, 0x7A, 0x4B, 0x00, 0x22, 0x1A, 0x60, ++0x34, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x90, 0xE0, 0xB4, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xBE, 0xE0, ++0xAA, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xD6, 0xE0, 0xA6, 0x33, 0xE2, 0x5C, 0x01, 0x32, 0xA3, 0x3B, 0x13, 0x40, ++0x9E, 0x22, 0xA1, 0x5C, 0x9C, 0x3A, 0x6E, 0x48, 0xCA, 0xF7, 0x56, 0xFF, 0xAA, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xC7, 0xE0, ++0x01, 0x21, 0x20, 0x00, 0xC9, 0xF7, 0xBE, 0xFF, 0xA0, 0x23, 0x02, 0x22, 0xE2, 0x54, 0x0A, 0x33, 0xE3, 0x5C, 0x00, 0x2B, ++0x49, 0xD1, 0xFE, 0xF7, 0xBF, 0xFD, 0x65, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, ++0x62, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0xD2, 0x0B, 0x00, 0xD1, 0xAD, 0xE0, 0x60, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, ++0xD2, 0x0A, 0xAA, 0x42, 0x07, 0xD0, 0x19, 0x88, 0xC9, 0x0A, 0x56, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x28, 0x00, ++0xA0, 0x47, 0x57, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x22, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x54, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x19, 0x40, 0x21, 0x54, ++0x50, 0x4B, 0x1A, 0x68, 0xCB, 0x00, 0x5B, 0x1A, 0x5B, 0x00, 0x4F, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x52, 0x04, 0x52, 0x0C, ++0x93, 0x42, 0x05, 0xD0, 0x43, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x45, 0x4E, 0x00, 0x24, ++0xD5, 0x23, 0x5B, 0x00, 0x98, 0x46, 0x3E, 0x4F, 0x0A, 0xE0, 0x28, 0x00, 0xCA, 0xF7, 0x30, 0xFF, 0xAA, 0x23, 0x00, 0x22, ++0xE2, 0x54, 0xAE, 0xE7, 0x01, 0x34, 0x0E, 0x36, 0x04, 0x2C, 0x67, 0xD0, 0x33, 0x88, 0xDB, 0x0B, 0xF8, 0xD0, 0x3A, 0x4B, ++0x42, 0x46, 0x98, 0x5C, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xFD, 0x6E, 0xA8, 0x47, 0xEF, 0xE7, 0x31, 0x00, 0x28, 0x00, ++0xFF, 0xF7, 0x04, 0xFE, 0xB4, 0x23, 0xE0, 0x54, 0x51, 0xE7, 0x29, 0x00, 0x01, 0x98, 0xFF, 0xF7, 0x53, 0xFE, 0x66, 0xE7, ++0xB4, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x2E, 0xD1, 0xAA, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x47, 0xD1, 0xA9, 0x33, 0xE3, 0x5C, ++0x00, 0x2B, 0x43, 0xD1, 0x01, 0x21, 0x20, 0x00, 0xC9, 0xF7, 0x3A, 0xFF, 0x01, 0x99, 0x61, 0x60, 0x86, 0x23, 0xFA, 0x22, ++0xD2, 0x01, 0xE2, 0x52, 0x21, 0x67, 0x20, 0x33, 0xE3, 0x5C, 0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x13, 0x40, 0x26, 0x4A, ++0x13, 0x43, 0xA3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0x9C, 0x46, 0x61, 0x44, 0x0F, 0x01, 0x3F, 0x09, 0xE7, 0x60, 0x20, 0x00, ++0xC9, 0xF7, 0x7C, 0xFD, 0x00, 0x28, 0x23, 0xD0, 0x15, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x1C, 0xE0, 0x9E, 0x23, 0xE0, 0x5C, 0xCA, 0xF7, 0xD9, 0xFE, 0x00, 0x23, 0xAA, 0x22, 0xA3, 0x54, 0x75, 0x3A, 0xBB, 0x54, ++0xC6, 0xE7, 0x9E, 0x23, 0xE0, 0x5C, 0xCA, 0xF7, 0xCF, 0xFE, 0xAA, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x01, 0x3B, 0xE1, 0x5C, ++0x12, 0x48, 0x77, 0xF7, 0xA1, 0xFB, 0x05, 0xE0, 0x06, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xA0, 0x47, ++0x02, 0xB0, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x38, 0xE6, 0x10, 0x00, 0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x4E, 0x65, 0x61, 0x40, 0xC8, 0xE6, 0x10, 0x00, 0x7D, 0x03, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, ++0x92, 0x69, 0x61, 0x40, 0x2C, 0x04, 0x60, 0x40, 0x90, 0x69, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x34, 0xD6, 0x10, 0x00, ++0x10, 0xB5, 0x82, 0x00, 0x0C, 0x4B, 0xD4, 0x58, 0x00, 0x2C, 0x0E, 0xD0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, ++0x09, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, 0xA3, 0x54, ++0x10, 0xBD, 0x04, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xA0, 0x47, 0xF7, 0xE7, 0x38, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0xCF, 0xB2, 0x06, 0x2F, ++0x08, 0xD9, 0xFF, 0x20, 0x08, 0x40, 0x10, 0x4B, 0xDB, 0x6E, 0x98, 0x46, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xC0, 0x47, ++0x00, 0x2C, 0x0A, 0xD0, 0x04, 0x2C, 0x0F, 0xD0, 0xFF, 0x20, 0x28, 0x40, 0x09, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x21, 0x00, 0xA8, 0x47, 0x03, 0xE0, 0x31, 0x00, 0x38, 0x00, 0xFF, 0xF7, 0x61, 0xFE, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, ++0x31, 0x00, 0x38, 0x00, 0xFF, 0xF7, 0xB6, 0xFF, 0xF7, 0xE7, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x05, 0x00, ++0x51, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x02, 0xD0, 0xFE, 0xF7, 0x0E, 0xFD, 0xF8, 0xBD, 0x4F, 0x48, 0x77, 0xF7, 0x22, 0xFB, ++0x4E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x07, 0xD0, 0x4D, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x12, 0x20, 0xEF, 0xE7, 0x00, 0x21, 0xF8, 0x20, 0x75, 0xF7, 0xE0, 0xFA, 0x46, 0x4B, 0x18, 0x60, 0x00, 0x28, 0x00, 0xD1, ++0x7C, 0xE0, 0x9E, 0xF7, 0x37, 0xFE, 0x06, 0x00, 0x83, 0xF7, 0xD8, 0xFB, 0x43, 0x4A, 0x13, 0x88, 0x43, 0x49, 0x0B, 0x40, ++0x00, 0x02, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x3D, 0x4B, 0x1C, 0x68, 0xF8, 0x22, 0x00, 0x21, 0x20, 0x00, 0x73, 0xF7, ++0x79, 0xFA, 0x00, 0x23, 0x63, 0x62, 0x3D, 0x4A, 0xE2, 0x61, 0x3D, 0x4A, 0x22, 0x62, 0x03, 0x22, 0x22, 0x76, 0x3C, 0x4A, ++0x12, 0x78, 0xA2, 0x75, 0x3B, 0x4A, 0x22, 0x61, 0x05, 0x22, 0xE2, 0x75, 0x99, 0x32, 0xA3, 0x54, 0x01, 0x32, 0x01, 0x21, ++0xA1, 0x54, 0x6B, 0x3A, 0x22, 0x65, 0x6D, 0x32, 0xA3, 0x54, 0x7F, 0xF7, 0xA9, 0xFA, 0x07, 0x1E, 0x3D, 0xD0, 0x3A, 0x89, ++0x94, 0x23, 0xE2, 0x52, 0x93, 0x3B, 0x01, 0x22, 0x29, 0x00, 0x00, 0x20, 0xFE, 0xF7, 0xE8, 0xFC, 0x33, 0x00, 0x00, 0x22, ++0x29, 0x00, 0x01, 0x20, 0xFF, 0xF7, 0x50, 0xF9, 0x9E, 0xF7, 0xF8, 0xFD, 0x60, 0x60, 0x00, 0x23, 0x82, 0x22, 0xA3, 0x52, ++0xA3, 0x60, 0x04, 0x32, 0xFA, 0x21, 0xC9, 0x01, 0xA1, 0x52, 0xE6, 0x66, 0x26, 0x67, 0x63, 0x67, 0xA3, 0x67, 0x00, 0x22, ++0xA6, 0x33, 0xE2, 0x54, 0x23, 0x4B, 0xA3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0x9C, 0x46, 0x66, 0x44, 0x36, 0x01, 0x36, 0x09, ++0xE6, 0x60, 0x20, 0x00, 0xC9, 0xF7, 0x6C, 0xFC, 0x00, 0x28, 0x15, 0xD1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x1C, 0x49, ++0xA1, 0x32, 0xFF, 0x32, 0x8B, 0x5A, 0x01, 0x24, 0x23, 0x43, 0x8B, 0x52, 0xA0, 0x3A, 0xFF, 0x3A, 0x18, 0x4B, 0x1A, 0x60, ++0x78, 0xE7, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xBA, 0xE7, 0x0A, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x20, 0x69, 0xE7, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x12, 0x20, 0x61, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x4C, 0xD6, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, 0xA1, 0x04, 0x10, 0x00, 0xD3, 0x01, 0x10, 0x00, ++0x7C, 0x91, 0x0D, 0x00, 0x6A, 0x04, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x20, 0xA3, 0x16, 0x00, 0xC8, 0xE6, 0x10, 0x00, ++0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0A, 0x48, 0x77, 0xF7, 0x68, 0xFA, 0xA1, 0x78, 0x4A, 0x10, 0x01, 0x23, 0x1A, 0x40, ++0x07, 0x48, 0x02, 0x70, 0x0B, 0x40, 0xA3, 0x70, 0x20, 0x00, 0xFF, 0xF7, 0x85, 0xF9, 0x01, 0x00, 0x28, 0x00, 0xFA, 0xF7, ++0x8B, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xC0, 0x46, 0x60, 0xD6, 0x10, 0x00, 0xDC, 0xE5, 0x10, 0x00, 0x70, 0xB5, 0x05, 0x00, ++0x0C, 0x00, 0x06, 0x48, 0x77, 0xF7, 0x4C, 0xFA, 0x28, 0x00, 0xFF, 0xF7, 0x1B, 0xFF, 0x01, 0x00, 0x20, 0x00, 0xFA, 0xF7, ++0x77, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xC0, 0x46, 0x68, 0xD6, 0x10, 0x00, 0x10, 0xB5, 0xFF, 0xF7, 0x51, 0xF8, 0x00, 0x20, ++0x10, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x17, 0xD0, 0xDC, 0x68, 0x18, 0x23, 0x0D, 0x22, ++0x00, 0x21, 0x0B, 0x48, 0x75, 0xF7, 0x2A, 0xF9, 0xFF, 0x23, 0x03, 0x70, 0xA3, 0x88, 0x43, 0x80, 0x00, 0x23, 0x03, 0x71, ++0x43, 0x71, 0x23, 0x69, 0x83, 0x60, 0x63, 0x69, 0xC3, 0x60, 0xE3, 0x69, 0x03, 0x61, 0xE3, 0x6A, 0x43, 0x61, 0xC6, 0xF7, ++0x79, 0xFF, 0x10, 0xBD, 0xD8, 0xE5, 0x10, 0x00, 0x03, 0x11, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x01, 0x78, ++0x0A, 0x48, 0x77, 0xF7, 0x11, 0xFA, 0x23, 0x78, 0x00, 0x2B, 0x07, 0xD0, 0x01, 0x2B, 0x08, 0xD0, 0x00, 0x21, 0x28, 0x00, ++0xFA, 0xF7, 0x3A, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xFE, 0xF7, 0x6E, 0xFB, 0xF6, 0xE7, 0xFF, 0xF7, 0xC7, 0xFF, 0xFE, 0xF7, ++0x69, 0xFB, 0xF1, 0xE7, 0x70, 0xD6, 0x10, 0x00, 0x45, 0x54, 0x45, 0x52, 0x52, 0x3A, 0x0A, 0x00, 0x77, 0x61, 0x6B, 0x65, ++0x75, 0x70, 0x5F, 0x68, 0x6F, 0x73, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x5F, 0x75, 0x70, ++0x5F, 0x68, 0x6F, 0x73, 0x74, 0x0A, 0x00, 0x00, 0x75, 0x61, 0x72, 0x74, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x0A, 0x00, 0x00, ++0x70, 0x5F, 0x73, 0x5F, 0x70, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x5F, 0x63, 0x68, 0x5F, 0x75, 0x70, 0x64, 0x61, ++0x74, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, ++0xE6, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xF6, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x1A, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x42, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x66, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x8E, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xBA, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xE6, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x0C, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x32, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x5C, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x82, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA2, 0x1C, 0x10, 0x00, 0xC4, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x16, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x3E, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x62, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x8A, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0xB6, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0xE2, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x08, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x2E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x58, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x7E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x9E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0xC0, 0x1C, 0x10, 0x00, 0x30, 0x78, 0x34, 0x30, 0x33, 0x34, 0x33, 0x30, 0x30, 0x34, 0x3A, 0x25, ++0x78, 0x2C, 0x25, 0x78, 0x00, 0x00, 0x00, 0x00, 0x43, 0x54, 0x53, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x20, 0x0A, 0x00, ++0xE2, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, ++0x78, 0x1D, 0x10, 0x00, 0x52, 0x1E, 0x10, 0x00, 0xE4, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, ++0xE2, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x6D, 0x64, 0x6C, 0x6C, 0x5F, 0x72, 0x65, 0x63, ++0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x62, 0x64, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, 0x2C, 0x25, ++0x78, 0x0A, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x6D, 0x61, 0x63, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, 0x2C, ++0x25, 0x78, 0x0A, 0x00, 0x66, 0x6C, 0x61, 0x73, 0x68, 0x6D, 0x61, 0x63, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, ++0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x43, 0x52, 0x5F, 0x50, 0x57, 0x52, 0x5F, 0x52, 0x45, 0x51, ++0x0A, 0x00, 0x00, 0x00, 0x50, 0x57, 0x52, 0x5F, 0x43, 0x54, 0x52, 0x4C, 0x5F, 0x52, 0x45, 0x51, 0x0A, 0x00, 0x00, 0x00, ++0x72, 0x65, 0x6D, 0x6F, 0x74, 0x65, 0x5F, 0x6D, 0x61, 0x78, 0x5F, 0x70, 0x77, 0x72, 0x0A, 0x00, 0x61, 0x66, 0x68, 0x74, ++0x6F, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x74, 0x78, 0x5F, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x00, ++0x72, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x73, 0x73, 0x69, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, ++0x73, 0x6D, 0x75, 0x74, 0x65, 0x0A, 0x00, 0x00, 0x72, 0x78, 0x5F, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x25, ++0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, ++0x64, 0x75, 0x20, 0x65, 0x6E, 0x6F, 0x75, 0x67, 0x68, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x77, 0x69, 0x66, 0x69, 0x20, 0x63, ++0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x69, 0x6F, 0x6E, 0x0A, 0x00, 0x00, 0x00, 0x75, 0x6D, 0x72, 0x65, 0x0A, 0x00, 0x00, 0x00, ++0x55, 0x4E, 0x44, 0x45, 0x46, 0x20, 0x56, 0x45, 0x4E, 0x44, 0x4F, 0x52, 0x5F, 0x49, 0x4E, 0x46, 0x4F, 0x0A, 0x00, 0x00, ++0x55, 0x4E, 0x4B, 0x4E, 0x4F, 0x57, 0x20, 0x56, 0x45, 0x4E, 0x44, 0x4F, 0x52, 0x5F, 0x49, 0x4E, 0x46, 0x4F, 0x3A, 0x25, ++0x78, 0x0A, 0x00, 0x00, 0x69, 0x6E, 0x69, 0x74, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, ++0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x38, 0x5C, 0x10, 0x00, 0x70, 0x5C, 0x10, 0x00, 0x78, 0x5C, 0x10, 0x00, ++0x38, 0x5C, 0x10, 0x00, 0x70, 0x5C, 0x10, 0x00, 0x76, 0x65, 0x72, 0x3A, 0x25, 0x73, 0x0A, 0x00, 0x6C, 0x6D, 0x74, 0x3A, ++0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x72, 0x65, 0x6A, 0x65, 0x63, 0x74, 0x3A, 0x25, 0x78, 0x00, 0x00, 0x00, ++0x76, 0x73, 0x5F, 0x61, 0x70, 0x63, 0x66, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x6A, 0x65, 0x63, 0x74, 0x32, 0x3A, ++0x25, 0x78, 0x00, 0x00, 0x92, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0x86, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, ++0x92, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0x8C, 0x73, 0x10, 0x00, 0xC0, 0x72, 0x10, 0x00, ++0x6E, 0x6F, 0x61, 0x6C, 0x63, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, 0x00, 0x62, 0x62, 0x5F, 0x74, 0x78, 0x5F, 0x74, 0x6F, ++0x6E, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x6F, 0x70, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x6D, 0x73, 0x73, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6D, 0x73, 0x73, 0x65, 0x72, 0x72, 0x0A, 0x00, 0x46, 0x4C, 0x55, 0x53, 0x48, 0x3A, 0x25, 0x78, ++0x0A, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x4B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x25, 0x78, 0x20, 0x00, 0x6F, 0x70, 0x63, 0x3A, ++0x25, 0x78, 0x0A, 0x00, 0x69, 0x20, 0x3D, 0x20, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x3A, 0x25, 0x78, ++0x0A, 0x00, 0x00, 0x00, 0x6F, 0x70, 0x6C, 0x6C, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x1E, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xBE, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, ++0xFC, 0x89, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xDA, 0x89, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0x4C, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xE8, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0x62, 0x8A, 0x10, 0x00, 0x55, 0x50, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, ++0x25, 0x78, 0x0A, 0x00, 0x6F, 0x70, 0x6C, 0x6C, 0x63, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x63, 0x72, ++0x78, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x63, 0x74, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, ++0x61, 0x70, 0x63, 0x66, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x61, 0x74, 0x65, 0x6E, 0x63, 0x79, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x66, 0x5F, 0x72, 0x65, 0x73, 0x65, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x45, 0x52, 0x52, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x41, 0x53, 0x53, 0x45, ++0x52, 0x54, 0x5F, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x28, 0x25, 0x73, 0x29, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x25, ++0x78, 0x20, 0x61, 0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x41, 0x53, 0x53, 0x45, ++0x52, 0x54, 0x5F, 0x45, 0x52, 0x52, 0x7A, 0x28, 0x25, 0x73, 0x29, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x61, ++0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x5F, 0x50, ++0x41, 0x52, 0x41, 0x4D, 0x7A, 0x28, 0x30, 0x78, 0x25, 0x58, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x58, 0x29, 0x2C, 0x20, 0x69, ++0x6E, 0x20, 0x25, 0x78, 0x20, 0x61, 0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x70, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0A, 0x00, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x25, ++0x78, 0x0D, 0x0A, 0x00, 0x64, 0x65, 0x6C, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x6F, 0x70, 0x3A, 0x30, 0x78, 0x25, 0x78, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x65, 0x72, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, ++0x74, 0x65, 0x73, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x5F, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, ++0x74, 0x65, 0x73, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x5F, 0x65, 0x78, 0x69, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x74, 0x73, 0x74, 0x5F, 0x65, 0x6E, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x74, 0x73, ++0x74, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x64, 0x72, 0x5F, ++0x70, 0x6B, 0x74, 0x3D, 0x25, 0x78, 0x00, 0x00, 0x66, 0x72, 0x65, 0x71, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0xC0, 0xB8, 0x10, 0x00, 0xB4, 0xB9, 0x10, 0x00, 0x94, 0xBA, 0x10, 0x00, 0xF2, 0xB8, 0x10, 0x00, 0xB0, 0xBA, 0x10, 0x00, ++0xCC, 0xBA, 0x10, 0x00, 0xE8, 0xBA, 0x10, 0x00, 0x04, 0xBB, 0x10, 0x00, 0x70, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, ++0x73, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x68, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x65, 0x3A, 0x25, ++0x34, 0x64, 0x2C, 0x20, 0x6F, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x6F, 0x6C, 0x65, 0x3A, 0x25, 0x34, 0x64, ++0x2C, 0x20, 0x70, 0x6E, 0x3A, 0x25, 0x34, 0x64, 0x20, 0x62, 0x63, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x3A, ++0x25, 0x37, 0x64, 0x2C, 0x20, 0x70, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2E, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x72, 0x3A, ++0x25, 0x64, 0x2E, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x70, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x73, 0x6F, 0x3A, 0x25, ++0x34, 0x64, 0x2C, 0x20, 0x68, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, ++0x62, 0x63, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x70, 0x65, 0x72, 0x3A, ++0x25, 0x64, 0x2E, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2E, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x62, 0x75, 0x72, 0x73, 0x74, 0x5F, 0x74, 0x78, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, ++0x0A, 0x00, 0x00, 0x00, 0x72, 0x78, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x63, 0x68, 0x5F, ++0x70, 0x72, 0x6F, 0x67, 0x5F, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x72, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0A, 0x00, ++0x74, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x0A, 0x00, 0x72, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x0A, 0x00, 0x62, 0x62, 0x5F, 0x74, ++0x73, 0x74, 0x5F, 0x73, 0x74, 0x6F, 0x70, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x02, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC7, 0x03, 0x00, 0x00, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, ++0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, ++0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, ++0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, ++0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, ++0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, ++0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, ++0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, ++0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, ++0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, ++0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, ++0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, ++0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, ++0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, ++0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, ++0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, ++0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, ++0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, ++0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, ++0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, ++0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, ++0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, ++0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, ++0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, ++0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, ++0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, ++0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, ++0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, ++0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, ++0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, ++0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, ++0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, ++0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, ++0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, ++0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, ++0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, ++0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, ++0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, ++0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, ++0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, ++0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, ++0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, ++0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, ++0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, ++0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, ++0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, ++0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, ++0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, ++0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, ++0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, ++0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, ++0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFF, 0xC1, 0xFB, 0xE8, ++0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, ++0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, ++0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, ++0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, ++0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, ++0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, ++0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, ++0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, ++0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, ++0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, ++0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, ++0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, ++0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, ++0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, ++0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, ++0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, ++0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, ++0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, ++0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, ++0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, ++0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, ++0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, ++0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, ++0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, ++0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, ++0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, ++0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, ++0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, ++0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, ++0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, ++0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, ++0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, ++0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, ++0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, ++0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, ++0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, ++0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, ++0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, ++0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, ++0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, ++0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, ++0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, ++0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, ++0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, ++0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, ++0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, ++0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, ++0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, ++0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, ++0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, ++0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, ++0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x01, 0x02, 0x02, 0x03, ++0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, ++0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, ++0x04, 0x05, 0x05, 0x06, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, ++0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, ++0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, ++0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, ++0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, ++0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, ++0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, ++0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, ++0x05, 0x06, 0x06, 0x07, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, ++0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08, 0x00, 0x10, 0x20, 0x30, ++0x40, 0x50, 0x60, 0x70, 0x00, 0x00, 0x01, 0x50, 0x00, 0x03, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x50, ++0x00, 0x02, 0x07, 0x03, 0x0C, 0x04, 0x0D, 0x05, 0x26, 0x06, 0x37, 0x07, 0x2C, 0x08, 0x3D, 0x09, 0x00, 0x00, 0x02, 0x01, ++0x05, 0x00, 0x01, 0x07, 0x00, 0x01, 0x00, 0x00, 0x01, 0x07, 0x00, 0x01, 0x0C, 0x00, 0x03, 0x0D, 0x00, 0x03, 0x06, 0x01, ++0x01, 0x07, 0x01, 0x01, 0x0C, 0x01, 0x03, 0x0D, 0x01, 0x03, 0x00, 0x00, 0x00, 0x27, 0x35, 0x00, 0x2B, 0x00, 0x31, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x22, 0x10, 0x00, 0xFF, 0xF0, 0xAA, 0xFF, 0xFF, 0x00, 0x0F, 0x55, ++0x80, 0x01, 0x00, 0x00, 0xF6, 0xFC, 0xFE, 0x00, 0x03, 0x06, 0x09, 0x0A, 0xF9, 0xFC, 0xFF, 0x02, 0x05, 0x07, 0x09, 0x0C, ++0x0F, 0x11, 0x15, 0x17, 0x50, 0x00, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, 0x50, 0xC3, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, ++0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x24, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x25, ++0x00, 0x80, 0xDE, 0xA9, 0x91, 0x06, 0x7B, 0x00, 0x04, 0x10, 0x04, 0x00, 0x04, 0x00, 0x00, 0x26, 0x00, 0x80, 0xDE, 0xA9, ++0x65, 0x06, 0x7C, 0x00, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x48, ++0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0x7F, 0x24, 0x17, 0x42, 0x40, 0x40, 0x8D, 0x08, 0x7B, 0xB0, 0x14, 0x10, 0x04, 0x00, ++0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, 0x04, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x26, ++0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, ++0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, 0x17, 0x42, 0x40, 0x40, 0xFD, 0x08, 0x7A, 0xB0, ++0x14, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, 0x04, 0x10, 0x04, 0x00, ++0x0C, 0x21, 0x04, 0x26, 0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, ++0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, 0x17, 0x42, 0x40, 0x40, ++0xFD, 0x08, 0x7A, 0xB0, 0x14, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, ++0x04, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x26, 0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, ++0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, ++0x17, 0x42, 0x40, 0x40, 0xFD, 0x08, 0x7A, 0xB0, 0xD0, 0x9E, 0x21, 0x00, 0x1C, 0x1C, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, ++0x1C, 0x1C, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x61, ++0xD6, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x65, 0xD7, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x75, 0xD7, 0x9E, 0x21, 0x00, ++0x70, 0x70, 0xFB, 0xFD, 0xD7, 0x9E, 0x21, 0x00, 0xF0, 0xF0, 0xFB, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, ++0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, ++0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, ++0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, ++0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0B, 0x00, 0x00, 0x04, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0xFF, 0xF9, 0x01, 0x08, ++0x00, 0x00, 0x00, 0x00, 0xAC, 0x2B, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x28, 0x21, 0x16, 0x00, 0xA8, 0x61, 0x00, 0x00, ++0xB8, 0x88, 0x00, 0x00, 0x74, 0x40, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0xED, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xCD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, ++0x60, 0x07, 0x8D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x0D, 0x79, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x6B, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0xDB, 0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, ++0x60, 0xD7, 0x0C, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x58, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x55, 0x00, ++0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, ++0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0xEB, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0xED, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xCD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, ++0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x79, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0xDB, ++0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0xD7, 0x0C, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, ++0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0xDB, ++0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, ++0xEB, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, ++0x6C, 0x00, 0x00, 0x03, 0x60, 0x07, 0xAC, 0xE9, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0x00, 0x03, ++0x60, 0x07, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0x20, 0x03, 0x60, 0xD7, 0x0C, 0xE8, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0xE0, 0x03, 0x60, 0x9F, 0x0D, 0xE8, 0x80, 0x80, 0x80, 0x80, ++0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0xE7, 0x8C, 0x69, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, ++0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x2F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, ++0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, 0x03, 0xC7, 0x8E, 0x00, 0x07, 0xC7, 0x8E, 0x00, 0x0B, 0xC7, 0x8E, 0x00, ++0x0F, 0xC7, 0x8E, 0x00, 0x13, 0xC7, 0x8E, 0x00, 0x17, 0xC7, 0x8E, 0x00, 0x1B, 0xC7, 0x8E, 0x00, 0x1F, 0xC7, 0x8E, 0x00, ++0x23, 0xC7, 0x8E, 0x00, 0x27, 0xC7, 0x8E, 0x00, 0x2B, 0xC7, 0x8E, 0x00, 0x2F, 0xC7, 0x8E, 0x00, 0x33, 0xC7, 0x8E, 0x00, ++0x37, 0xC7, 0x8E, 0x00, 0x3B, 0xC7, 0x8E, 0x00, 0x3F, 0xC7, 0x8E, 0x00, 0x06, 0x81, 0x88, 0x00, 0x0A, 0x81, 0x88, 0x00, ++0x0C, 0xC1, 0x88, 0x00, 0x14, 0xC1, 0x90, 0x00, 0x14, 0x41, 0x91, 0x00, 0x15, 0xC1, 0x91, 0x00, 0x23, 0xC1, 0x91, 0x00, ++0x3F, 0xC1, 0x91, 0x00, 0x3F, 0xC1, 0x92, 0x00, 0x3F, 0x01, 0x94, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, ++0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, ++0x2D, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, 0x33, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x33, 0x38, 0x3A, ++0x33, 0x39, 0x20, 0x2D, 0x20, 0x67, 0x69, 0x74, 0x20, 0x30, 0x61, 0x61, 0x62, 0x66, 0x62, 0x66, 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, ++}; ++ ++struct firmware_info{ ++ char fw_name[30]; ++ char* fw_array; ++ int fw_size; ++}; ++ ++struct firmware_info firmware[]={ ++ {"fmacfw.bin", fmacfw, sizeof(fmacfw)}, ++ {"fw_adid_u03.bin", fw_adid_u03, sizeof(fw_adid_u03)}, ++ {"fw_patch_table_u03.bin", fw_patch_table_u03, sizeof(fw_patch_table_u03)}, ++ {"fw_patch_u03.bin", fw_patch_u03, sizeof(fw_patch_u03)} ++}; ++ ++int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf){ ++ int firmware_number = 0; ++ int index = 0; ++ int fw_size = 0; ++ ++ firmware_number = sizeof(firmware)/sizeof(struct firmware_info); ++ printk("%s search:%s \r\n", __func__ , fw_name); ++ ++ for(index = 0; index < firmware_number; index++){ ++ if(!strcmp(firmware[index].fw_name, fw_name)){ ++ fw_size = firmware[index].fw_size; ++ printk("%s find %s len:%d\r\n", __func__, fw_name, fw_size); ++ *fw_buf = (u32*)firmware[index].fw_array; ++ return fw_size; ++ } ++ } ++ ++ printk("%s %s not found \r\n", __func__, fw_name); ++ ++ return 0; ++} +\ No newline at end of file +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h +new file mode 100644 +index 000000000000..dcf38e9ba302 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h +@@ -0,0 +1,3 @@ ++int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf); ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c +new file mode 100644 +index 000000000000..9514c416b5d6 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c +@@ -0,0 +1,62 @@ ++#include ++#include "aicsdio_txrxif.h" ++#include "aic_bsp_driver.h" ++ ++struct prealloc_txq{ ++ int prealloced; ++ void *txq; ++ size_t size; ++}; ++ ++struct prealloc_txq prealloc_txq; ++#define MAX_TXQ_SIZE 100 * 1024 ++ ++void *aicwf_prealloc_txq_alloc(size_t size) ++{ ++ ++ BUG_ON(size > MAX_TXQ_SIZE); ++ ++ //check prealloc_txq.size ++ if((int)prealloc_txq.size != (int)size) ++ { ++ AICWFDBG(LOGINFO, "%s size is diff will to be kzalloc \r\n", __func__); ++ ++ if(prealloc_txq.txq != NULL) ++ { ++ AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__); ++ kfree(prealloc_txq.txq); ++ prealloc_txq.txq = NULL; ++ } ++ ++ prealloc_txq.size = size; ++ prealloc_txq.prealloced = 0; ++ } ++ ++ //check prealloc or not ++ if(!prealloc_txq.prealloced) ++ { ++ prealloc_txq.txq = kzalloc(size, GFP_KERNEL); ++ if(!prealloc_txq.txq){ ++ AICWFDBG(LOGERROR, "%s txq kzalloc fail \r\n", __func__); ++ }else{ ++ AICWFDBG(LOGINFO, "%s txq kzalloc successful \r\n", __func__); ++ prealloc_txq.prealloced = 1; ++ } ++ }else{ ++ AICWFDBG(LOGINFO, "%s txq not need to kzalloc \r\n", __func__); ++ } ++ ++ return prealloc_txq.txq; ++} ++void aicwf_prealloc_txq_free(void) ++{ ++ if(prealloc_txq.txq != NULL) ++ { ++ AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__); ++ kfree(prealloc_txq.txq); ++ prealloc_txq.txq = NULL; ++ } ++} ++ ++EXPORT_SYMBOL(aicwf_prealloc_txq_alloc); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h +new file mode 100644 +index 000000000000..ce4ee07473b3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h +@@ -0,0 +1,4 @@ ++ ++ ++void aicwf_prealloc_txq_free(void); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c +new file mode 100644 +index 000000000000..3d7b65375adb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c +@@ -0,0 +1,161 @@ ++#include ++#include "md5.h" ++ ++unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; ++ ++void MD5Init(MD5_CTX *context) ++{ ++ context->count[0] = 0; ++ context->count[1] = 0; ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xEFCDAB89; ++ context->state[2] = 0x98BADCFE; ++ context->state[3] = 0x10325476; ++} ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) ++{ ++ unsigned int i = 0,index = 0,partlen = 0; ++ index = (context->count[0] >> 3) & 0x3F; ++ partlen = 64 - index; ++ context->count[0] += inputlen << 3; ++ if(context->count[0] < (inputlen << 3)) ++ context->count[1]++; ++ context->count[1] += inputlen >> 29; ++ ++ if(inputlen >= partlen) ++ { ++ memcpy(&context->buffer[index],input,partlen); ++ MD5Transform(context->state,context->buffer); ++ for(i = partlen;i+64 <= inputlen;i+=64) ++ MD5Transform(context->state,&input[i]); ++ index = 0; ++ } ++ else ++ { ++ i = 0; ++ } ++ memcpy(&context->buffer[index],&input[i],inputlen-i); ++} ++void MD5Final(MD5_CTX *context,unsigned char digest[16]) ++{ ++ unsigned int index = 0,padlen = 0; ++ unsigned char bits[8]; ++ index = (context->count[0] >> 3) & 0x3F; ++ padlen = (index < 56)?(56-index):(120-index); ++ MD5Encode(bits,context->count,8); ++ MD5Update(context,PADDING,padlen); ++ MD5Update(context,bits,8); ++ MD5Encode(digest,context->state,16); ++} ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[j] = input[i] & 0xFF; ++ output[j+1] = (input[i] >> 8) & 0xFF; ++ output[j+2] = (input[i] >> 16) & 0xFF; ++ output[j+3] = (input[i] >> 24) & 0xFF; ++ i++; ++ j+=4; ++ } ++} ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[i] = (input[j]) | ++ (input[j+1] << 8) | ++ (input[j+2] << 16) | ++ (input[j+3] << 24); ++ i++; ++ j+=4; ++ } ++} ++void MD5Transform(unsigned int state[4],unsigned char block[64]) ++{ ++ unsigned int a = state[0]; ++ unsigned int b = state[1]; ++ unsigned int c = state[2]; ++ unsigned int d = state[3]; ++ unsigned int x[64]; ++ MD5Decode(x,block,64); ++ FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ ++ FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ ++ FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ ++ FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ ++ FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ ++ FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ ++ FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ ++ FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ ++ FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ ++ FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ ++ FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ ++ FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ ++ FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ ++ FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ ++ FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ ++ FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ ++ ++ /* Round 2 */ ++ GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ ++ GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ ++ GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ ++ GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ ++ GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ ++ GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ ++ GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ ++ GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ ++ GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ ++ GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ ++ GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ ++ GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ ++ GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ ++ GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ ++ GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ ++ GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ ++ ++ /* Round 3 */ ++ HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ ++ HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ ++ HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ ++ HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ ++ HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ ++ HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ ++ HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ ++ HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ ++ HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ ++ HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ ++ HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ ++ HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ ++ HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ ++ HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ ++ HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ ++ HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ ++ ++ /* Round 4 */ ++ II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ ++ II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ ++ II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ ++ II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ ++ II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ ++ II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ ++ II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ ++ II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ ++ II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ ++ II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ ++ II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ ++ II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ ++ II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ ++ II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ ++ II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ ++ II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h +new file mode 100644 +index 000000000000..6ed5c0f8e886 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h +@@ -0,0 +1,48 @@ ++#ifndef MD5_H ++#define MD5_H ++ ++typedef struct ++{ ++ unsigned int count[2]; ++ unsigned int state[4]; ++ unsigned char buffer[64]; ++}MD5_CTX; ++ ++ ++#define F(x,y,z) ((x & y) | (~x & z)) ++#define G(x,y,z) ((x & z) | (y & ~z)) ++#define H(x,y,z) (x^y^z) ++#define I(x,y,z) (y ^ (x | ~z)) ++#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) ++#define FF(a,b,c,d,x,s,ac) \ ++ { \ ++ a += F(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define GG(a,b,c,d,x,s,ac) \ ++ { \ ++ a += G(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define HH(a,b,c,d,x,s,ac) \ ++ { \ ++ a += H(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define II(a,b,c,d,x,s,ac) \ ++ { \ ++ a += I(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++void MD5Init(MD5_CTX *context); ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); ++void MD5Final(MD5_CTX *context,unsigned char digest[16]); ++void MD5Transform(unsigned int state[4],unsigned char block[64]); ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h +new file mode 100644 +index 000000000000..6fcb679c8934 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h +@@ -0,0 +1,4 @@ ++#define RWNX_VERS_REV "241c091M (master)" ++#define RWNX_VERS_MOD "6.4.3.0" ++#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" ++#define RELEASE_DATE "2025_0410_b99ca8b6" +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore +new file mode 100644 +index 000000000000..c3c2d151e157 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig +new file mode 100644 +index 000000000000..ff7aaa649f83 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig +@@ -0,0 +1,5 @@ ++config AIC8800_BTLPM_SUPPORT ++ tristate "AIC8800 bluetooth Support" ++ help ++ This is support for aic bluetooh driver. ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile +new file mode 100644 +index 000000000000..6d59301f9741 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile +@@ -0,0 +1,83 @@ ++CONFIG_AIC8800_BTLPM_SUPPORT = m ++ ++obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) := aic8800_btlpm.o ++ ++ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp ++ ++# Platform support list ++CONFIG_PLATFORM_ROCKCHIP ?= n ++CONFIG_PLATFORM_ROCKCHIP2 ?= n ++CONFIG_PLATFORM_ALLWINNER ?= n ++CONFIG_PLATFORM_AMLOGIC ?= n ++CONFIG_PLATFORM_UBUNTU ?= y ++ ++ ++CONFIG_SUPPORT_LPM ?= n ++CONFIG_AUTO_PM ?= n ++ ++aic8800_btlpm-y := \ ++ aic_bluetooth_main.o \ ++ rfkill.o \ ++ ++aic8800_btlpm-$(CONFIG_SUPPORT_LPM) += lpm.o ++ ++ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) ++ ++ccflags-$(CONFIG_AUTO_PM) += -DCONFIG_AUTO_PM ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ARCH = arm64 ++KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++ARCH = arm64 ++KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++KDIR ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9/ ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ccflags-$(CONFIG_PLATFORM_NANOPI) += -DCONFIG_PLATFORM_NANOPI ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++KDIR ?= /lib/modules/$(shell uname -r)/build ++PWD ?= $(shell pwd) ++KVER ?= $(shell uname -r) ++MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ++ARCH ?= x86_64 ++CROSS_COMPILE ?= ++endif ++ ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c +new file mode 100644 +index 000000000000..52d768d83da8 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c +@@ -0,0 +1,1167 @@ ++/* ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++#include ++#endif ++ ++#include "aic_bsp_export.h" ++ ++/* ++ * #define BT_SLEEP_DBG ++ */ ++#define BT_SLEEP_DBG ++#undef BT_DBG ++#undef BT_ERR ++#ifdef BT_SLEEP_DBG ++#define BT_DBG(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++#else ++#define BT_DBG(fmt, arg...) ++#endif ++#define BT_ERR(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++ ++/* ++ * Defines ++ */ ++ ++#define VERSION "1.3.3" ++#define PROC_DIR "bluetooth/sleep" ++ ++#define DEFAULT_UART_INDEX 1 ++#define BT_BLUEDROID_SUPPORT 1 ++static int bluesleep_start(void); ++static void bluesleep_stop(void); ++ ++struct bluesleep_info { ++ unsigned int wakeup_enable; ++ unsigned host_wake; ++ unsigned ext_wake; ++ unsigned host_wake_irq; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ struct wakeup_source *ws; ++#else ++ struct wake_lock wake_lock; ++#endif ++ struct uart_port *uport; ++ unsigned host_wake_assert:1; ++ unsigned ext_wake_assert:1; ++ struct platform_device *pdev; ++}; ++ ++/* work function */ ++static void bluesleep_sleep_work(struct work_struct *work); ++static void bluesleep_tx_allow_sleep(void); ++ ++/* work queue */ ++DECLARE_DELAYED_WORK(sleep_workqueue, bluesleep_sleep_work); ++ ++/* Macros for handling sleep work */ ++#define bluesleep_rx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_rx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++ ++/* 1 second timeout */ ++#define RX_TIMER_INTERVAL 1 ++ ++/* state variable names and bit positions */ ++#define BT_PROTO 0x01 ++#define BT_TXDATA 0x02 ++#define BT_ASLEEP 0x04 ++#define BT_TXIDLE 0x08 ++#define BT_PAUSE 0x09 ++#define BT_RXTIMER 0x0a ++ ++#if BT_BLUEDROID_SUPPORT ++static bool has_lpm_enabled; ++#else ++/* global pointer to a single hci device. */ ++static struct hci_dev *bluesleep_hdev; ++#endif ++ ++#if BT_BLUEDROID_SUPPORT ++static struct platform_device *bluesleep_uart_dev; ++#endif ++static struct bluesleep_info *bsi; ++ ++/* module usage */ ++static atomic_t open_count = ATOMIC_INIT(1); ++ ++/* ++ * Local function prototypes ++ */ ++ ++#if !BT_BLUEDROID_SUPPORT ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data); ++#endif ++ ++/* ++ * Global variables ++ */ ++ ++/** Global state flags */ ++static unsigned long flags; ++ ++/** Tasklet to respond to change in hostwake line */ ++static struct tasklet_struct hostwake_task; ++ ++/** Reception timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t); ++#else ++static void bluesleep_rx_timer_expire(unsigned long data); ++#endif ++static struct timer_list rx_timer; ++ ++/** Lock for state transitions */ ++static spinlock_t rw_lock; ++ ++#if !BT_BLUEDROID_SUPPORT ++/** Notifier block for HCI events */ ++struct notifier_block hci_event_nblock = { ++ .notifier_call = bluesleep_hci_event, ++}; ++#endif ++ ++struct proc_dir_entry *bluetooth_dir, *sleep_dir; ++ ++/* ++ * Local functions ++ */ ++ ++/* ++ * bt go to sleep will call this function tell uart stop data interactive ++ */ ++static void hsuart_power(int on) ++{ ++ if (bsi->uport != NULL) { ++ if (on) ++ bsi->uport->ops->set_mctrl(bsi->uport, TIOCM_RTS); ++ else ++ bsi->uport->ops->set_mctrl(bsi->uport, 0); ++ } else { ++ BT_ERR("bsi->uport = NULL, has_lpm_enabled = %d", has_lpm_enabled); ++ } ++} ++ ++/** ++ * @return 1 if the Host can go to sleep, 0 otherwise. ++ */ ++static inline int bluesleep_can_sleep(void) ++{ ++ /* check if HOST_WAKE_BT_GPIO and BT_WAKE_HOST_GPIO ++ * are both deasserted ++ */ ++ return (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) && ++ (gpio_get_value(bsi->host_wake) != bsi->host_wake_assert) && ++ (!test_bit(BT_RXTIMER, &flags)) && (bsi->uport != NULL); ++} ++ ++/** ++ * @brief@ main sleep work handling function which update the flags ++ * and activate and deactivate UART ,check FIFO. ++ */ ++static void bluesleep_sleep_work(struct work_struct *work) ++{ ++ if (!has_lpm_enabled) ++ return; ++ ++ if (bluesleep_can_sleep()) { ++ /* already asleep, this is an error case */ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("already asleep"); ++ return; ++ } ++ if (bsi->uport->ops->tx_empty(bsi->uport)) { ++ BT_DBG("going to sleep..."); ++ set_bit(BT_ASLEEP, &flags); ++ /*Deactivating UART */ ++ hsuart_power(0); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++ } else { ++ BT_DBG("This should never happen.\n"); ++ return; ++ } ++ } else if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("hold wake locks for rx_task."); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ clear_bit(BT_ASLEEP, &flags); ++ ++ /* Add a timer to make sure that UART ++ * would not be turned on&off very frequentently ++ */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ ++ set_bit(BT_RXTIMER, &flags); ++ hsuart_power(1); ++ } else { ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ set_bit(BT_RXTIMER, &flags); ++ ++ if(test_bit(BT_PAUSE, &flags)){ ++ BT_DBG("rx wake du BT_PAUSE:%lx", flags); ++ ///enable bt sleep immediately ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } else if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert ++ && !test_bit(BT_TXIDLE, &flags)) { ++ BT_DBG("force retrigger bt wake:%lx", flags); ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ msleep(20); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } ++ } ++} ++ ++/** ++ * A tasklet function that runs in tasklet context and reads the value ++ * of the HOST_WAKE GPIO pin and further defer the work. ++ * @param data Not used. ++ */ ++static void bluesleep_hostwake_task(unsigned long data) ++{ ++ BT_DBG("hostwake line change"); ++ spin_lock(&rw_lock); ++ ++ if (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert) ++ bluesleep_rx_busy(); ++ else ++ bluesleep_rx_idle(); ++ ++ spin_unlock(&rw_lock); ++} ++ ++/** ++ * Handles proper timer action when outgoing data is delivered to the ++ * HCI line discipline. Sets BT_TXDATA. ++ */ ++static void bluesleep_outgoing_data(void) ++{ ++ unsigned long irq_flags; ++ int power_on_uart = 0; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ /* if the tx side is sleeping... */ ++ if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) { ++ BT_DBG("tx was sleeping, wakeup it"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ clear_bit(BT_ASLEEP, &flags); ++ clear_bit(BT_TXIDLE, &flags); ++ power_on_uart = 1; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ if (power_on_uart == 1) ++ hsuart_power(1); ++} ++ ++#if BT_BLUEDROID_SUPPORT ++static struct uart_port *bluesleep_get_uart_port(void) ++{ ++ struct uart_port *uport = NULL; ++ ++ if (bluesleep_uart_dev) { ++ uport = platform_get_drvdata(bluesleep_uart_dev); ++ if (uport) ++ BT_DBG( ++ "%s get uart_port from blusleep_uart_dev: %s, port irq: %d", ++ __func__, bluesleep_uart_dev->name, uport->irq); ++ } ++ return uport; ++} ++ ++static int bluesleep_lpm_proc_show(struct seq_file *m, void *v) ++{ ++ seq_printf(m, "lpm enable: %d\n", has_lpm_enabled); ++ return 0; ++} ++ ++static int bluesleep_lpm_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_lpm_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_lpm(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ if (b == '0') { ++#if 1 ++ set_bit(BT_PAUSE, &flags); ++ set_bit(BT_TXIDLE, &flags); ++ clear_bit(BT_TXDATA, &flags); ++ /* deassert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++#else ++ /* HCI_DEV_UNREG */ ++ bluesleep_stop(); ++ has_lpm_enabled = false; ++ bsi->uport = NULL; ++#endif ++ } else { ++ clear_bit(BT_PAUSE, &flags); ++ /* HCI_DEV_REG */ ++ if (!has_lpm_enabled) { ++ has_lpm_enabled = true; ++ if (bluesleep_uart_dev) ++ bsi->uport = bluesleep_get_uart_port(); ++ ++ /* if bluetooth started, start bluesleep*/ ++ bluesleep_start(); ++ } ++ } ++ ++ return count; ++} ++ ++static int bluesleep_btwrite_proc_show(struct seq_file *m, void *v) ++{ ++ seq_puts(m, "it's not support\n"); ++ return 0; ++} ++ ++static int bluesleep_btwrite_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_btwrite_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_btwrite(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ /* HCI_DEV_WRITE */ ++ if (b != '0') ++ bluesleep_outgoing_data(); ++ else ++ bluesleep_tx_allow_sleep(); ++ ++ return count; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops lpm_fops = { ++ .proc_open = bluesleep_lpm_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_lpm, ++}; ++static const struct proc_ops btwrite_fops = { ++ .proc_open = bluesleep_btwrite_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_btwrite, ++}; ++ ++#else ++ ++static const struct file_operations lpm_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_lpm_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_lpm, ++}; ++static const struct file_operations btwrite_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_btwrite_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_btwrite, ++}; ++#endif ++ ++#else ++/** ++ * Handles HCI device events. ++ * @param this Not used. ++ * @param event The event that occurred. ++ * @param data The HCI device associated with the event. ++ * @return NOTIFY_DONE. ++ */ ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data) ++{ ++ struct hci_dev *hdev = (struct hci_dev *) data; ++ struct hci_uart *hu; ++ struct uart_state *state; ++ ++ if (!hdev) ++ return NOTIFY_DONE; ++ ++ switch (event) { ++ case HCI_DEV_REG: ++ if (!bluesleep_hdev) { ++ bluesleep_hdev = hdev; ++ hu = (struct hci_uart *) hdev->driver_data; ++ state = (struct uart_state *) hu->tty->driver_data; ++ bsi->uport = state->uart_port; ++ } ++ break; ++ case HCI_DEV_UNREG: ++ bluesleep_hdev = NULL; ++ bsi->uport = NULL; ++ break; ++ case HCI_DEV_WRITE: ++ bluesleep_outgoing_data(); ++ break; ++ } ++ ++ return NOTIFY_DONE; ++} ++#endif ++ ++/** ++ * Function to check wheather bluetooth can sleep when btwrite was deasserted ++ * by bluedroid. ++ */ ++static void bluesleep_tx_allow_sleep(void) ++{ ++ unsigned long irq_flags; ++ BT_DBG("Tx has been idle\n"); ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ set_bit(BT_TXIDLE, &flags); ++ clear_bit(BT_TXDATA, &flags); ++ bluesleep_tx_idle(); ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++} ++ ++ ++/* Handles reception timer expiration. ++ * Clear BT_RXTIMER. ++ * @param data Not used. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t) ++#else ++static void bluesleep_rx_timer_expire(unsigned long data) ++#endif ++{ ++ BT_DBG("bluesleep_rx_timer_expire"); ++ clear_bit(BT_RXTIMER, &flags); ++ bluesleep_rx_idle(); ++} ++ ++/** ++ * Schedules a tasklet to run when receiving an interrupt on the ++ * HOST_WAKE GPIO pin. ++ * @param irq Not used. ++ * @param dev_id Not used. ++ */ ++static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id) ++{ ++ /* schedule a tasklet to handle the change in the host wake line */ ++ tasklet_schedule(&hostwake_task); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * Starts the Sleep-Mode Protocol on the Host. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++static int bluesleep_start(void) ++{ ++ int retval; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return 0; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ ++ if (!atomic_dec_and_test(&open_count)) { ++ atomic_inc(&open_count); ++ return -EBUSY; ++ } ++ ++ /* start the timer */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL*HZ)); ++ /*deassert BT_WAKE first*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ msleep(20); ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ retval = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr, ++ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, ++ "bluetooth hostwake", &bsi->pdev->dev); ++ if (retval < 0) { ++ BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ"); ++ goto fail; ++ } ++ ++ set_bit(BT_PROTO, &flags); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ ++ return 0; ++fail: ++ del_timer(&rx_timer); ++ atomic_inc(&open_count); ++ ++ return retval; ++} ++ ++/** ++ * Stops the Sleep-Mode Protocol on the Host. ++ */ ++static void bluesleep_stop(void) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (!test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return; ++ } ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ ++ del_timer(&rx_timer); ++ clear_bit(BT_PROTO, &flags); ++ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ clear_bit(BT_ASLEEP, &flags); ++ hsuart_power(1); ++ } ++ ++ atomic_inc(&open_count); ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++} ++#if 0 ++/** ++ * Read the BT_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the ++ * pin is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_btwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "btwake:%u\n", ++ (gpio_get_value(bsi->ext_wake) == bsi->ext_wake_assert)); ++} ++ ++/** ++ * Write the BT_WAKE GPIO pin value via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluepower_write_proc_btwake(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char *buf; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ buf = kmalloc(count, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ if (copy_from_user(buf, buffer, count)) { ++ kfree(buf); ++ return -EFAULT; ++ } ++ ++ if (buf[0] == '0') { ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } else if (buf[0] == '1') { ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ } else { ++ kfree(buf); ++ return -EINVAL; ++ } ++ ++ kfree(buf); ++ return count; ++} ++ ++/** ++ * Read the BT_HOST_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the pin ++ * is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_hostwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "hostwake: %u\n", ++ (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert)); ++} ++ ++ ++/** ++ * Read the low-power status of the Host via the proc interface. ++ * When this function returns, page contains a 1 if the Host ++ * is asleep, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_asleep(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int asleep; ++ ++ asleep = test_bit(BT_ASLEEP, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "asleep: %u\n", asleep); ++} ++ ++/** ++ * Read the low-power protocol being used by the Host via the proc interface. ++ * When this function returns, page will contain a 1 if the Host ++ * is using the Sleep Mode Protocol, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_proto(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int proto; ++ ++ proto = test_bit(BT_PROTO, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "proto: %u\n", proto); ++} ++ ++/** ++ * Modify the low-power protocol used by the Host via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluesleep_write_proc_proto(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char proto; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&proto, buffer, 1)) ++ return -EFAULT; ++ ++ if (proto == '0') ++ bluesleep_stop(); ++ else ++ bluesleep_start(); ++ ++ /* claim that we wrote everything */ ++ return count; ++} ++#endif ++ ++static int assert_level = -1; ++module_param(assert_level, int, S_IRUGO); ++MODULE_PARM_DESC(assert_level, "BT_LPM hostwake/btwake assert level"); ++ ++static struct platform_device *sw_uart_get_pdev(int id) ++{ ++ struct device_node *np; ++ char match[20]; ++ sprintf(match, "uart%d", id); ++ np = of_find_node_by_type(NULL, match); ++ return of_find_device_by_node(np); ++} ++ ++static int __init bluesleep_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device *dev = &pdev->dev; ++ enum of_gpio_flags config; ++ int ret, uart_index; ++ u32 val; ++ struct aicbsp_feature_t bsp_feature_lpm; ++ ++ bsi = devm_kzalloc(&pdev->dev, sizeof(struct bluesleep_info), ++ GFP_KERNEL); ++ if (!bsi) ++ return -ENOMEM; ++ ++ bsi->host_wake = of_get_named_gpio_flags(np, "bt_hostwake", 0, &config); ++ if (!gpio_is_valid(bsi->host_wake)) { ++ BT_ERR("get gpio bt_hostwake failed\n"); ++ ret = -EINVAL; ++ goto err0; ++ } ++ ++ /* set host_wake_assert */ ++ aicbsp_get_feature(&bsp_feature_lpm); ++ if (bsp_feature_lpm.irqf == 0) ++ bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ else ++ bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 1 : 0; ++ ++ BT_DBG("bt_hostwake gpio=%d assert=%d\n", bsi->host_wake, bsi->host_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->host_wake_assert = (assert_level & 0x02) > 0; ++ BT_DBG("override host_wake assert to %d", bsi->host_wake_assert); ++ } ++ ++ ret = devm_gpio_request(dev, bsi->host_wake, "bt_hostwake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_hostwake gpio %d\n", ++ bsi->host_wake); ++ goto err0; ++ } ++ ret = gpio_direction_input(bsi->host_wake); ++ if (ret < 0) { ++ BT_ERR("can't request input direction bt_wake gpio %d\n", ++ bsi->host_wake); ++ goto err1; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (!of_property_read_bool(np, "wakeup-source")) { ++#else ++ if (!of_property_read_u32(np, "wakeup-source", &bsi->wakeup_enable) && ++ (bsi->wakeup_enable == 0)) { ++#endif ++ BT_DBG("wakeup source is disabled!\n"); ++ } else { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ ret = device_init_wakeup(dev, true); ++ if (ret < 0) { ++ BT_ERR("device init wakeup failed!\n"); ++ goto err1; ++ } ++ ret = dev_pm_set_wake_irq(dev, gpio_to_irq(bsi->host_wake)); ++ if (ret < 0) { ++ BT_ERR("can't enable wakeup src for bt_hostwake %d\n", ++ bsi->host_wake); ++ goto err2; ++ } ++ bsi->wakeup_enable = 1; ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ } ++ ++ bsi->ext_wake = of_get_named_gpio_flags(np, "bt_wake", 0, &config); ++ if (!gpio_is_valid(bsi->ext_wake)) { ++ BT_ERR("get gpio bt_wake failed\n"); ++ ret = -EINVAL; ++ goto err2; ++ } ++ ++ ret = devm_gpio_request(dev, bsi->ext_wake, "bt_wake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err2; ++ } ++ ++ /* set ext_wake_assert */ ++ bsi->ext_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ BT_DBG("bt_wake gpio=%d assert=%d\n", bsi->ext_wake, bsi->ext_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->ext_wake_assert = (assert_level & 0x01) > 0; ++ BT_DBG("override ext_wake assert to %d", bsi->ext_wake_assert); ++ } ++ ++ /* 1.set bt_wake as output and the level is assert, assert bt wake */ ++ ret = gpio_direction_output(bsi->ext_wake, bsi->ext_wake_assert); ++ if (ret < 0) { ++ BT_ERR("can't request output direction bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err3; ++ } ++ /*set ext_wake deassert as default*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ ++ /* 2.get bt_host_wake gpio irq */ ++ bsi->host_wake_irq = gpio_to_irq(bsi->host_wake); ++ if (bsi->host_wake_irq < 0) { ++ BT_ERR("map gpio [%d] to virq failed, errno = %d\n", ++ bsi->host_wake, bsi->host_wake_irq); ++ ret = -ENODEV; ++ goto err3; ++ } ++ ++ uart_index = DEFAULT_UART_INDEX; ++ if (!of_property_read_u32(np, "uart_index", &val)) { ++ switch (val) { ++ case 0: ++ case 1: ++ case 2: ++ uart_index = val; ++ break; ++ default: ++ BT_ERR("unsupported uart_index (%u)\n", val); ++ } ++ } ++ BT_DBG("uart_index (%u)\n", uart_index); ++ bluesleep_uart_dev = sw_uart_get_pdev(uart_index); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ bsi->ws = wakeup_source_register(dev, "bluesleep"); ++#else ++ wake_lock_init(&bsi->wake_lock, WAKE_LOCK_SUSPEND, "bluesleep"); ++#endif ++ bsi->pdev = pdev; ++ ++ return 0; ++ ++err3: ++ devm_gpio_free(dev, bsi->ext_wake); ++err2: ++ device_init_wakeup(dev, false); ++err1: ++ devm_gpio_free(dev, bsi->host_wake); ++err0: ++ devm_kfree(dev, bsi); ++ ++ BT_ERR("probe fail, err: %d", ret); ++ return ret; ++} ++ ++static int bluesleep_remove(struct platform_device *pdev) ++{ ++ /* assert bt wake */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ if (test_bit(BT_PROTO, &flags)) { ++ if (disable_irq_wake(bsi->host_wake_irq)) ++ BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n"); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++ del_timer(&rx_timer); ++ if (test_bit(BT_ASLEEP, &flags)) ++ hsuart_power(1); ++ } ++ gpio_free(bsi->host_wake); ++ gpio_free(bsi->ext_wake); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ wakeup_source_unregister(bsi->ws); ++#else ++ wake_lock_destroy(&bsi->wake_lock); ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ if (bsi->wakeup_enable) { ++ BT_DBG("Deinit wakeup source"); ++ device_init_wakeup(&pdev->dev, false); ++ dev_pm_clear_wake_irq(&pdev->dev); ++ } ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ return 0; ++} ++ ++#ifdef CONFIG_AUTO_PM ++static int bluesleep_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ printk("%s\n", __func__); ++ ++ bluesleep_tx_allow_sleep(); ++ return 0; ++} ++ ++static int bluesleep_resume(struct platform_device *pdev) ++{ ++ printk("%s\n", __func__); ++ ++ bluesleep_outgoing_data(); ++ return 0; ++} ++#endif ++ ++static const struct of_device_id sunxi_btlpm_ids[] = { ++ { .compatible = "allwinner,sunxi-btlpm" }, ++ { /* Sentinel */ } ++}; ++ ++static struct platform_driver bluesleep_driver = { ++ .remove = bluesleep_remove, ++#ifdef CONFIG_AUTO_PM ++ .suspend = bluesleep_suspend, ++ .resume = bluesleep_resume, ++#endif ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "sunxi-btlpm", ++ .of_match_table = sunxi_btlpm_ids, ++ }, ++}; ++ ++/** ++ * Initializes the module. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++static int __init bluesleep_init(void) ++{ ++ int retval; ++ struct proc_dir_entry *ent; ++ ++ BT_DBG("BlueSleep Mode Driver Ver %s", VERSION); ++ ++ retval = platform_driver_probe(&bluesleep_driver, bluesleep_probe); ++ if (retval) ++ return retval; ++ ++#if !BT_BLUEDROID_SUPPORT ++ bluesleep_hdev = NULL; ++#endif ++ ++ bluetooth_dir = proc_mkdir("bluetooth", NULL); ++ if (bluetooth_dir == NULL) { ++ BT_ERR("Unable to create /proc/bluetooth directory"); ++ return -ENOMEM; ++ } ++ ++ sleep_dir = proc_mkdir("sleep", bluetooth_dir); ++ if (sleep_dir == NULL) { ++ BT_ERR("Unable to create /proc/%s directory", PROC_DIR); ++ return -ENOMEM; ++ } ++#if 0 ++ /* Creating read/write "btwake" entry */ ++ ent = create_proc_entry("btwake", 0, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluepower_read_proc_btwake; ++ ent->write_proc = bluepower_write_proc_btwake; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("hostwake", 0, sleep_dir, ++ bluepower_read_proc_hostwake, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* read/write proc entries */ ++ ent = create_proc_entry("proto", 0666, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluesleep_read_proc_proto; ++ ent->write_proc = bluesleep_write_proc_proto; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("asleep", 0, ++ sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++#if BT_BLUEDROID_SUPPORT ++ /* read/write proc entries */ ++ ent = proc_create("lpm", 0660, sleep_dir, &lpm_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/lpm entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ ent = proc_create("btwrite", 0660, sleep_dir, &btwrite_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwrite entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++ ++ flags = 0; /* clear all status bits */ ++ ++ /* Initialize spinlock. */ ++ spin_lock_init(&rw_lock); ++ ++ /* Initialize timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ timer_setup(&rx_timer, bluesleep_rx_timer_expire, 0); ++#else ++ init_timer(&rx_timer); ++ rx_timer.function = bluesleep_rx_timer_expire; ++ rx_timer.data = 0; ++#endif ++ ++ /* initialize host wake tasklet */ ++ tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); ++ ++#if !BT_BLUEDROID_SUPPORT ++ hci_register_notifier(&hci_event_nblock); ++#endif ++ ++ return 0; ++ ++fail: ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++ return retval; ++} ++ ++/** ++ * Cleans up the module. ++ */ ++static void __exit bluesleep_exit(void) ++{ ++#if !BT_BLUEDROID_SUPPORT ++ hci_unregister_notifier(&hci_event_nblock); ++#endif ++ platform_driver_unregister(&bluesleep_driver); ++ ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++} ++ ++module_init(bluesleep_init); ++module_exit(bluesleep_exit); ++ ++MODULE_DESCRIPTION("Bluetooth Sleep Mode Driver ver %s " VERSION); ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c +new file mode 100644 +index 000000000000..122d867f0ed6 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c +@@ -0,0 +1,88 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "lpm.h" ++#include "rfkill.h" ++ ++#define DRV_CONFIG_FW_NAME "fw.bin" ++#define DRV_DESCRIPTION "AIC BLUETOOTH" ++#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi" ++#define DRV_AUTHOR "AICSemi" ++#define DRV_VERS_MOD "1.0" ++ ++static struct platform_device *aicbt_pdev; ++ ++static struct platform_driver aicbt_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "aic_bt", ++ }, ++ //.probe = aicbt_probe, ++ //.remove = aicbt_remove, ++}; ++ ++static int __init aic_bluetooth_mod_init(void) ++{ ++ int ret; ++ printk("%s\n", __func__); ++ ret = platform_driver_register(&aicbt_driver); ++ if (ret) { ++ pr_err("register platform driver failed: %d\n", ret); ++ return ret; ++ } ++ ++ aicbt_pdev = platform_device_alloc("aic-bt", -1); ++ ret = platform_device_add(aicbt_pdev); ++ if (ret) { ++ pr_err("register platform device failed: %d\n", ret); ++ goto err0; ++ } ++ ++ ret = rfkill_bluetooth_init(aicbt_pdev); ++ if (ret) { ++ pr_err("rfkill init fail\n"); ++ goto err1; ++ } ++#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) ++ ret = bluesleep_init(aicbt_pdev); ++ if (ret) { ++ pr_err("bluesleep init fail\n"); ++ goto err2; ++ } ++#endif ++ ++ return 0; ++ ++#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) ++err2: ++#endif ++ rfkill_bluetooth_remove(aicbt_pdev); ++err1: ++ platform_device_del(aicbt_pdev); ++err0: ++ platform_driver_unregister(&aicbt_driver); ++ return ret; ++} ++ ++static void __exit aic_bluetooth_mod_exit(void) ++{ ++ printk("%s\n", __func__); ++#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) ++ bluesleep_exit(aicbt_pdev); ++#endif ++ rfkill_bluetooth_remove(aicbt_pdev); ++ platform_device_del(aicbt_pdev); ++ platform_driver_unregister(&aicbt_driver); ++} ++ ++module_init(aic_bluetooth_mod_init); ++module_exit(aic_bluetooth_mod_exit); ++ ++MODULE_DESCRIPTION(DRV_DESCRIPTION); ++MODULE_VERSION(DRV_VERS_MOD); ++MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h +new file mode 100644 +index 000000000000..88f6b565cd5f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h +@@ -0,0 +1,19 @@ ++#ifndef __AIC_BSP_EXPORT_H ++#define __AIC_BSP_EXPORT_H ++ ++#define AIC_BLUETOOTH 0 ++#define AIC_WIFI 1 ++#define AIC_PWR_OFF 0 ++#define AIC_PWR_ON 1 ++ ++struct aicbsp_feature_t { ++ bool band_5g_support; ++ uint32_t sdio_clock; ++ uint8_t sdio_phase; ++ uint8_t irqf; ++}; ++ ++int aicbsp_set_subsys(int, int); ++int aicbsp_get_feature(struct aicbsp_feature_t *feature); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c +new file mode 100644 +index 000000000000..6e9b71564f19 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c +@@ -0,0 +1,1111 @@ ++/* ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#endif ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++#include ++#endif ++ ++/* ++ * #define BT_SLEEP_DBG ++ */ ++#define BT_SLEEP_DBG ++#undef BT_DBG ++#undef BT_ERR ++#ifdef BT_SLEEP_DBG ++#define BT_DBG(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++#else ++#define BT_DBG(fmt, arg...) ++#endif ++#define BT_ERR(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++ ++/* ++ * Defines ++ */ ++ ++#define VERSION "1.3.3" ++#define PROC_DIR "bluetooth/sleep" ++ ++#define DEFAULT_UART_INDEX 1 ++#define BT_BLUEDROID_SUPPORT 1 ++static int bluesleep_start(void); ++static void bluesleep_stop(void); ++ ++struct bluesleep_info { ++ unsigned int wakeup_enable; ++ unsigned host_wake; ++ unsigned ext_wake; ++ unsigned host_wake_irq; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ struct wakeup_source *ws; ++#else ++ struct wake_lock wake_lock; ++#endif ++ struct uart_port *uport; ++ unsigned host_wake_assert:1; ++ unsigned ext_wake_assert:1; ++ struct platform_device *pdev; ++}; ++ ++/* work function */ ++static void bluesleep_sleep_work(struct work_struct *work); ++static void bluesleep_tx_allow_sleep(void); ++ ++/* work queue */ ++DECLARE_DELAYED_WORK(sleep_workqueue, bluesleep_sleep_work); ++ ++/* Macros for handling sleep work */ ++#define bluesleep_rx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_rx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++ ++/* 1 second timeout */ ++#define RX_TIMER_INTERVAL 1 ++ ++/* state variable names and bit positions */ ++#define BT_PROTO 0x01 ++#define BT_TXDATA 0x02 ++#define BT_ASLEEP 0x04 ++#define BT_RXTIMER 0x20 ++#define BT_TXIDLE 0x08 ++ ++#if BT_BLUEDROID_SUPPORT ++static bool has_lpm_enabled; ++#else ++/* global pointer to a single hci device. */ ++static struct hci_dev *bluesleep_hdev; ++#endif ++ ++#if BT_BLUEDROID_SUPPORT ++static struct platform_device *bluesleep_uart_dev; ++#endif ++static struct bluesleep_info *bsi; ++ ++/* module usage */ ++static atomic_t open_count = ATOMIC_INIT(1); ++ ++/* ++ * Local function prototypes ++ */ ++ ++#if !BT_BLUEDROID_SUPPORT ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data); ++#endif ++ ++/* ++ * Global variables ++ */ ++ ++/** Global state flags */ ++static unsigned long flags; ++ ++/** Tasklet to respond to change in hostwake line */ ++static struct tasklet_struct hostwake_task; ++ ++/** Reception timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t); ++#else ++static void bluesleep_rx_timer_expire(unsigned long data); ++#endif ++static struct timer_list rx_timer; ++ ++/** Lock for state transitions */ ++static spinlock_t rw_lock; ++ ++#if !BT_BLUEDROID_SUPPORT ++/** Notifier block for HCI events */ ++struct notifier_block hci_event_nblock = { ++ .notifier_call = bluesleep_hci_event, ++}; ++#endif ++ ++struct proc_dir_entry *bluetooth_dir, *sleep_dir; ++ ++/* ++ * Local functions ++ */ ++ ++/* ++ * bt go to sleep will call this function tell uart stop data interactive ++ */ ++static void hsuart_power(int on) ++{ ++ if (bsi->uport != NULL) { ++ if (on) ++ bsi->uport->ops->set_mctrl(bsi->uport, TIOCM_RTS); ++ else ++ bsi->uport->ops->set_mctrl(bsi->uport, 0); ++ } else { ++ BT_ERR("bsi->uport = NULL, has_lpm_enabled = %d", has_lpm_enabled); ++ } ++} ++ ++/** ++ * @return 1 if the Host can go to sleep, 0 otherwise. ++ */ ++static inline int bluesleep_can_sleep(void) ++{ ++ /* check if HOST_WAKE_BT_GPIO and BT_WAKE_HOST_GPIO ++ * are both deasserted ++ */ ++ return (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) && ++ (gpio_get_value(bsi->host_wake) != bsi->host_wake_assert) && ++ (!test_bit(BT_RXTIMER, &flags)) && (bsi->uport != NULL); ++} ++ ++/** ++ * @brief@ main sleep work handling function which update the flags ++ * and activate and deactivate UART ,check FIFO. ++ */ ++static void bluesleep_sleep_work(struct work_struct *work) ++{ ++ if (!has_lpm_enabled) ++ return; ++ ++ if (bluesleep_can_sleep()) { ++ /* already asleep, this is an error case */ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("already asleep"); ++ return; ++ } ++ if (bsi->uport->ops->tx_empty(bsi->uport)) { ++ BT_DBG("going to sleep..."); ++ set_bit(BT_ASLEEP, &flags); ++ /*Deactivating UART */ ++ hsuart_power(0); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++ } else { ++ BT_DBG("This should never happen.\n"); ++ return; ++ } ++ } else if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("hold wake locks for rx_task."); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ clear_bit(BT_ASLEEP, &flags); ++ ++ /* Add a timer to make sure that UART ++ * would not be turned on&off very frequentently ++ */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ ++ set_bit(BT_RXTIMER, &flags); ++ hsuart_power(1); ++ } else { ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert ++ && !test_bit(BT_TXIDLE, &flags)) { ++ BT_DBG("force retrigger bt wake:%lx", flags); ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ msleep(20); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } ++ } ++} ++ ++/** ++ * A tasklet function that runs in tasklet context and reads the value ++ * of the HOST_WAKE GPIO pin and further defer the work. ++ * @param data Not used. ++ */ ++static void bluesleep_hostwake_task(unsigned long data) ++{ ++ BT_DBG("hostwake line change"); ++ spin_lock(&rw_lock); ++ ++ if (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert) ++ bluesleep_rx_busy(); ++ else ++ bluesleep_rx_idle(); ++ ++ spin_unlock(&rw_lock); ++} ++ ++/** ++ * Handles proper timer action when outgoing data is delivered to the ++ * HCI line discipline. Sets BT_TXDATA. ++ */ ++static void bluesleep_outgoing_data(void) ++{ ++ unsigned long irq_flags; ++ int power_on_uart = 0; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ /* if the tx side is sleeping... */ ++ if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) { ++ BT_DBG("tx was sleeping, wakeup it"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ clear_bit(BT_ASLEEP, &flags); ++ clear_bit(BT_TXIDLE, &flags); ++ power_on_uart = 1; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ if (power_on_uart == 1) ++ hsuart_power(1); ++} ++ ++#if BT_BLUEDROID_SUPPORT ++static struct uart_port *bluesleep_get_uart_port(void) ++{ ++ struct uart_port *uport = NULL; ++ ++ if (bluesleep_uart_dev) { ++ uport = platform_get_drvdata(bluesleep_uart_dev); ++ if (uport) ++ BT_DBG( ++ "%s get uart_port from blusleep_uart_dev: %s, port irq: %d", ++ __func__, bluesleep_uart_dev->name, uport->irq); ++ } ++ return uport; ++} ++ ++static int bluesleep_lpm_proc_show(struct seq_file *m, void *v) ++{ ++ seq_printf(m, "lpm enable: %d\n", has_lpm_enabled); ++ return 0; ++} ++ ++static int bluesleep_lpm_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_lpm_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_lpm(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ if (b == '0') { ++ /* HCI_DEV_UNREG */ ++ bluesleep_stop(); ++ has_lpm_enabled = false; ++ bsi->uport = NULL; ++ } else { ++ /* HCI_DEV_REG */ ++ if (!has_lpm_enabled) { ++ has_lpm_enabled = true; ++ if (bluesleep_uart_dev) ++ bsi->uport = bluesleep_get_uart_port(); ++ ++ /* if bluetooth started, start bluesleep*/ ++ bluesleep_start(); ++ } ++ } ++ ++ return count; ++} ++ ++static int bluesleep_btwrite_proc_show(struct seq_file *m, void *v) ++{ ++ seq_puts(m, "it's not support\n"); ++ return 0; ++} ++ ++static int bluesleep_btwrite_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_btwrite_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_btwrite(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ /* HCI_DEV_WRITE */ ++ if (b != '0') ++ bluesleep_outgoing_data(); ++ else ++ bluesleep_tx_allow_sleep(); ++ ++ return count; ++} ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0) ++static const struct proc_ops lpm_fops = { ++ .proc_open = bluesleep_lpm_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_lpm, ++}; ++static const struct proc_ops btwrite_fops = { ++ .proc_open = bluesleep_btwrite_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_btwrite, ++}; ++#else ++static const struct file_operations lpm_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_lpm_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_lpm, ++}; ++static const struct file_operations btwrite_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_btwrite_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_btwrite, ++}; ++#endif ++#else ++/** ++ * Handles HCI device events. ++ * @param this Not used. ++ * @param event The event that occurred. ++ * @param data The HCI device associated with the event. ++ * @return NOTIFY_DONE. ++ */ ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data) ++{ ++ struct hci_dev *hdev = (struct hci_dev *) data; ++ struct hci_uart *hu; ++ struct uart_state *state; ++ ++ if (!hdev) ++ return NOTIFY_DONE; ++ ++ switch (event) { ++ case HCI_DEV_REG: ++ if (!bluesleep_hdev) { ++ bluesleep_hdev = hdev; ++ hu = (struct hci_uart *) hdev->driver_data; ++ state = (struct uart_state *) hu->tty->driver_data; ++ bsi->uport = state->uart_port; ++ } ++ break; ++ case HCI_DEV_UNREG: ++ bluesleep_hdev = NULL; ++ bsi->uport = NULL; ++ break; ++ case HCI_DEV_WRITE: ++ bluesleep_outgoing_data(); ++ break; ++ } ++ ++ return NOTIFY_DONE; ++} ++#endif ++ ++/** ++ * Function to check wheather bluetooth can sleep when btwrite was deasserted ++ * by bluedroid. ++ */ ++static void bluesleep_tx_allow_sleep(void) ++{ ++ unsigned long irq_flags; ++ BT_DBG("Tx has been idle\n"); ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ set_bit(BT_TXIDLE, &flags); ++ bluesleep_tx_idle(); ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++} ++ ++ ++/* Handles reception timer expiration. ++ * Clear BT_RXTIMER. ++ * @param data Not used. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t) ++#else ++static void bluesleep_rx_timer_expire(unsigned long data) ++#endif ++{ ++ BT_DBG("bluesleep_rx_timer_expire"); ++ clear_bit(BT_RXTIMER, &flags); ++ bluesleep_rx_idle(); ++} ++ ++/** ++ * Schedules a tasklet to run when receiving an interrupt on the ++ * HOST_WAKE GPIO pin. ++ * @param irq Not used. ++ * @param dev_id Not used. ++ */ ++static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id) ++{ ++ /* schedule a tasklet to handle the change in the host wake line */ ++ tasklet_schedule(&hostwake_task); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * Starts the Sleep-Mode Protocol on the Host. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++static int bluesleep_start(void) ++{ ++ int retval; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return 0; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ ++ if (!atomic_dec_and_test(&open_count)) { ++ atomic_inc(&open_count); ++ return -EBUSY; ++ } ++ ++ /* start the timer */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL*HZ)); ++ /*deassert BT_WAKE first*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ msleep(20); ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ retval = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr, ++ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, ++ "bluetooth hostwake", &bsi->pdev->dev); ++ if (retval < 0) { ++ BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ"); ++ goto fail; ++ } ++ ++ set_bit(BT_PROTO, &flags); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ ++ return 0; ++fail: ++ del_timer(&rx_timer); ++ atomic_inc(&open_count); ++ ++ return retval; ++} ++ ++/** ++ * Stops the Sleep-Mode Protocol on the Host. ++ */ ++static void bluesleep_stop(void) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (!test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return; ++ } ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ ++ del_timer(&rx_timer); ++ clear_bit(BT_PROTO, &flags); ++ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ clear_bit(BT_ASLEEP, &flags); ++ hsuart_power(1); ++ } ++ ++ atomic_inc(&open_count); ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++} ++#if 0 ++/** ++ * Read the BT_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the ++ * pin is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_btwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "btwake:%u\n", ++ (gpio_get_value(bsi->ext_wake) == bsi->ext_wake_assert)); ++} ++ ++/** ++ * Write the BT_WAKE GPIO pin value via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluepower_write_proc_btwake(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char *buf; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ buf = kmalloc(count, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ if (copy_from_user(buf, buffer, count)) { ++ kfree(buf); ++ return -EFAULT; ++ } ++ ++ if (buf[0] == '0') { ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } else if (buf[0] == '1') { ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ } else { ++ kfree(buf); ++ return -EINVAL; ++ } ++ ++ kfree(buf); ++ return count; ++} ++ ++/** ++ * Read the BT_HOST_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the pin ++ * is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_hostwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "hostwake: %u\n", ++ (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert)); ++} ++ ++ ++/** ++ * Read the low-power status of the Host via the proc interface. ++ * When this function returns, page contains a 1 if the Host ++ * is asleep, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_asleep(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int asleep; ++ ++ asleep = test_bit(BT_ASLEEP, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "asleep: %u\n", asleep); ++} ++ ++/** ++ * Read the low-power protocol being used by the Host via the proc interface. ++ * When this function returns, page will contain a 1 if the Host ++ * is using the Sleep Mode Protocol, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_proto(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int proto; ++ ++ proto = test_bit(BT_PROTO, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "proto: %u\n", proto); ++} ++ ++/** ++ * Modify the low-power protocol used by the Host via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluesleep_write_proc_proto(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char proto; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&proto, buffer, 1)) ++ return -EFAULT; ++ ++ if (proto == '0') ++ bluesleep_stop(); ++ else ++ bluesleep_start(); ++ ++ /* claim that we wrote everything */ ++ return count; ++} ++#endif ++ ++static int assert_level = -1; ++module_param(assert_level, int, S_IRUGO); ++MODULE_PARM_DESC(assert_level, "BT_LPM hostwake/btwake assert level"); ++ ++#if 1 ++static struct platform_device *sw_uart_get_pdev(int id) ++{ ++ struct device_node *np; ++ char match[20]; ++ sprintf(match, "uart%d", id); ++ np = of_find_node_by_type(NULL, match); ++ return of_find_device_by_node(np); ++} ++#endif ++ ++static int bluesleep_probe(struct platform_device *pdev) ++{ ++#if 1 ++ struct device_node *np = of_find_compatible_node(NULL, NULL, "allwinner,sunxi-btlpm"); ++ struct device *dev = &pdev->dev; ++ enum of_gpio_flags config; ++ int ret, uart_index; ++ u32 val; ++ ++ bsi = devm_kzalloc(&pdev->dev, sizeof(struct bluesleep_info), ++ GFP_KERNEL); ++ if (!bsi) ++ return -ENOMEM; ++ ++ bsi->host_wake = of_get_named_gpio_flags(np, "bt_hostwake", 0, &config); ++ if (!gpio_is_valid(bsi->host_wake)) { ++ BT_ERR("get gpio bt_hostwake failed\n"); ++ ret = -EINVAL; ++ goto err0; ++ } ++ ++ /* set host_wake_assert */ ++ bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ BT_DBG("bt_hostwake gpio=%d assert=%d\n", bsi->host_wake, bsi->host_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->host_wake_assert = (assert_level & 0x02) > 0; ++ BT_DBG("override host_wake assert to %d", bsi->host_wake_assert); ++ } ++ ++ ret = devm_gpio_request(dev, bsi->host_wake, "bt_hostwake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_hostwake gpio %d\n", ++ bsi->host_wake); ++ goto err0; ++ } ++ ret = gpio_direction_input(bsi->host_wake); ++ if (ret < 0) { ++ BT_ERR("can't request input direction bt_wake gpio %d\n", ++ bsi->host_wake); ++ goto err1; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (!of_property_read_bool(np, "wakeup-source")) { ++#else ++ if (!of_property_read_u32(np, "wakeup-source", &bsi->wakeup_enable) && ++ (bsi->wakeup_enable == 0)) { ++#endif ++ BT_DBG("wakeup source is disabled!\n"); ++ } else { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ ret = device_init_wakeup(dev, true); ++ if (ret < 0) { ++ BT_ERR("device init wakeup failed!\n"); ++ goto err1; ++ } ++ ret = dev_pm_set_wake_irq(dev, gpio_to_irq(bsi->host_wake)); ++ if (ret < 0) { ++ BT_ERR("can't enable wakeup src for bt_hostwake %d\n", ++ bsi->host_wake); ++ goto err2; ++ } ++ bsi->wakeup_enable = 1; ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ } ++ ++ bsi->ext_wake = of_get_named_gpio_flags(np, "bt_wake", 0, &config); ++ if (!gpio_is_valid(bsi->ext_wake)) { ++ BT_ERR("get gpio bt_wake failed\n"); ++ ret = -EINVAL; ++ goto err2; ++ } ++ ++ ret = devm_gpio_request(dev, bsi->ext_wake, "bt_wake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err2; ++ } ++ ++ /* set ext_wake_assert */ ++ bsi->ext_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ BT_DBG("bt_wake gpio=%d assert=%d\n", bsi->ext_wake, bsi->ext_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->ext_wake_assert = (assert_level & 0x01) > 0; ++ BT_DBG("override ext_wake assert to %d", bsi->ext_wake_assert); ++ } ++ ++ /* 1.set bt_wake as output and the level is assert, assert bt wake */ ++ ret = gpio_direction_output(bsi->ext_wake, bsi->ext_wake_assert); ++ if (ret < 0) { ++ BT_ERR("can't request output direction bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err3; ++ } ++ /*set ext_wake deassert as default*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ ++ /* 2.get bt_host_wake gpio irq */ ++ bsi->host_wake_irq = gpio_to_irq(bsi->host_wake); ++ if (bsi->host_wake_irq < 0) { ++ BT_ERR("map gpio [%d] to virq failed, errno = %d\n", ++ bsi->host_wake, bsi->host_wake_irq); ++ ret = -ENODEV; ++ goto err3; ++ } ++ ++ uart_index = DEFAULT_UART_INDEX; ++ if (!of_property_read_u32(np, "uart_index", &val)) { ++ switch (val) { ++ case 0: ++ case 1: ++ case 2: ++ uart_index = val; ++ break; ++ default: ++ BT_ERR("unsupported uart_index (%u)\n", val); ++ } ++ } ++ BT_DBG("uart_index (%u)\n", uart_index); ++ bluesleep_uart_dev = sw_uart_get_pdev(uart_index); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ bsi->ws = wakeup_source_register(dev, "bluesleep"); ++#else ++ bsi->ws = wakeup_source_register("bluesleep"); ++#endif ++ ++#else ++ wake_lock_init(&bsi->wake_lock, WAKE_LOCK_SUSPEND, "bluesleep"); ++#endif ++ bsi->pdev = pdev; ++ ++ return 0; ++ ++err3: ++ devm_gpio_free(dev, bsi->ext_wake); ++err2: ++ device_init_wakeup(dev, false); ++err1: ++ devm_gpio_free(dev, bsi->host_wake); ++err0: ++ devm_kfree(dev, bsi); ++ ++ BT_ERR("probe fail, err: %d", ret); ++ return ret; ++#endif ++ return 0; ++} ++ ++static int bluesleep_remove(struct platform_device *pdev) ++{ ++ /* assert bt wake */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ if (test_bit(BT_PROTO, &flags)) { ++ if (disable_irq_wake(bsi->host_wake_irq)) ++ BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n"); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++ del_timer(&rx_timer); ++ if (test_bit(BT_ASLEEP, &flags)) ++ hsuart_power(1); ++ } ++ gpio_free(bsi->host_wake); ++ gpio_free(bsi->ext_wake); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ wakeup_source_unregister(bsi->ws); ++#else ++ wake_lock_destroy(&bsi->wake_lock); ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ if (bsi->wakeup_enable) { ++ BT_DBG("Deinit wakeup source"); ++ device_init_wakeup(&pdev->dev, false); ++ dev_pm_clear_wake_irq(&pdev->dev); ++ } ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ return 0; ++} ++ ++/** ++ * Initializes the module. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++int bluesleep_init(struct platform_device *pdev) ++{ ++ int retval; ++ struct proc_dir_entry *ent; ++ ++ BT_DBG("BlueSleep Mode Driver Ver %s", VERSION); ++ ++#if 1 ++ retval = bluesleep_probe(pdev); ++ if (retval) ++ return retval; ++#endif ++ ++#if !BT_BLUEDROID_SUPPORT ++ bluesleep_hdev = NULL; ++#endif ++ ++ bluetooth_dir = proc_mkdir("bluetooth", NULL); ++ if (bluetooth_dir == NULL) { ++ BT_ERR("Unable to create /proc/bluetooth directory"); ++ return -ENOMEM; ++ } ++ ++ sleep_dir = proc_mkdir("sleep", bluetooth_dir); ++ if (sleep_dir == NULL) { ++ BT_ERR("Unable to create /proc/%s directory", PROC_DIR); ++ return -ENOMEM; ++ } ++#if 0 ++ /* Creating read/write "btwake" entry */ ++ ent = create_proc_entry("btwake", 0, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluepower_read_proc_btwake; ++ ent->write_proc = bluepower_write_proc_btwake; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("hostwake", 0, sleep_dir, ++ bluepower_read_proc_hostwake, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* read/write proc entries */ ++ ent = create_proc_entry("proto", 0666, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluesleep_read_proc_proto; ++ ent->write_proc = bluesleep_write_proc_proto; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("asleep", 0, ++ sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++#if BT_BLUEDROID_SUPPORT ++ /* read/write proc entries */ ++ ent = proc_create("lpm", 0660, sleep_dir, &lpm_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/lpm entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ ent = proc_create("btwrite", 0660, sleep_dir, &btwrite_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwrite entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++ ++ flags = 0; /* clear all status bits */ ++ ++ /* Initialize spinlock. */ ++ spin_lock_init(&rw_lock); ++ ++ /* Initialize timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ timer_setup(&rx_timer, bluesleep_rx_timer_expire, 0); ++#else ++ init_timer(&rx_timer); ++ rx_timer.function = bluesleep_rx_timer_expire; ++ rx_timer.data = 0; ++#endif ++ ++ /* initialize host wake tasklet */ ++ tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); ++ ++#if !BT_BLUEDROID_SUPPORT ++ hci_register_notifier(&hci_event_nblock); ++#endif ++ ++ return 0; ++ ++fail: ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++ return retval; ++} ++ ++/** ++ * Cleans up the module. ++ */ ++int bluesleep_exit(struct platform_device *dev) ++{ ++#if !BT_BLUEDROID_SUPPORT ++ hci_unregister_notifier(&hci_event_nblock); ++#endif ++ ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++ bluesleep_remove(dev); ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h +new file mode 100644 +index 000000000000..0ff9dca14c0b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2015 Spreadtrum Communications Inc. ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __LPM_H ++#define __LPM_H ++ ++int bluesleep_init(struct platform_device *pdev); ++int bluesleep_exit(struct platform_device *dev); ++ ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c +new file mode 100644 +index 000000000000..5caf3f83a03a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c +@@ -0,0 +1,81 @@ ++/* ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aic_bsp_export.h" ++ ++static struct rfkill *bt_rfk; ++static const char bt_name[] = "bluetooth"; ++ ++static int bluetooth_set_power(void *data, bool blocked) ++{ ++ pr_info("%s: start_block=%d\n", __func__, blocked); ++ if (!blocked) { ++ aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON); ++ } else { ++ aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_OFF); ++ } ++ ++ pr_info("%s: end_block=%d\n", __func__, blocked); ++ return 0; ++} ++ ++static struct rfkill_ops rfkill_bluetooth_ops = { ++ .set_block = bluetooth_set_power, ++}; ++ ++int rfkill_bluetooth_init(struct platform_device *pdev) ++{ ++ ++ int rc = 0; ++ ++ pr_info("-->%s\n", __func__); ++ bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH, ++ &rfkill_bluetooth_ops, NULL); ++ if (!bt_rfk) { ++ rc = -ENOMEM; ++ goto err_rfkill_alloc; ++ } ++ /* userspace cannot take exclusive control */ ++ rfkill_init_sw_state(bt_rfk, true); ++ rc = rfkill_register(bt_rfk); ++ if (rc) ++ goto err_rfkill_reg; ++ ++ pr_info("<--%s\n", __func__); ++ ++ return 0; ++ ++err_rfkill_reg: ++ rfkill_destroy(bt_rfk); ++err_rfkill_alloc: ++ return rc; ++} ++ ++int rfkill_bluetooth_remove(struct platform_device *dev) ++{ ++ pr_info("-->%s\n", __func__); ++ rfkill_unregister(bt_rfk); ++ rfkill_destroy(bt_rfk); ++ pr_info("<--%s\n", __func__); ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h +new file mode 100644 +index 000000000000..ce0d5761a960 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h +@@ -0,0 +1,17 @@ ++/* ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef __RFKILL_H__ ++#define __RFKILL_H__ ++ ++int rfkill_bluetooth_init(struct platform_device *pdev); ++int rfkill_bluetooth_remove(struct platform_device *pdev); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore +new file mode 100644 +index 000000000000..c3c2d151e157 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig +new file mode 100644 +index 000000000000..c26f2b4af23c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig +@@ -0,0 +1,5 @@ ++config AIC8800_WLAN_SUPPORT ++ tristate "AIC8800 wlan Support" ++ help ++ This is support for aic wifi driver. ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile +new file mode 100644 +index 000000000000..558f3818b8e2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile +@@ -0,0 +1,424 @@ ++EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) ++EXTRA_CFLAGS += -Wno-implicit-fallthrough ++#EXTRA_CFLAGS += -Wno-unused-function ++#EXTRA_CFLAGS += -Wno-maybe-uninitialized ++#EXTRA_CFLAGS += -Wno-unused-variable ++ ++RWNX_VERS_NUM := 6.4.3.0 ++ ++CONFIG_COUNTRY_CODE = "00" ++ ++MODULE_NAME = aic8800_fdrv ++CONFIG_AIC8800_WLAN_SUPPORT = m ++ ++# Support of bootrom start ++CONFIG_START_FROM_BOOTROM = y ++ ++# Support of pmic setting, new version bootrom avaliable ++CONFIG_PMIC_SETTING ?=y ++ ++# Select 8800DC/DW DCDC_VRF mode, check your board ++CONFIG_VRF_DCDC_MODE = y ++ ++ ++# ROM patch enabled option ++CONFIG_ROM_PATCH_EN ?=y ++# Support chip with mcu ++CONFIG_MCU_INTEGRATED ?= n ++CONFIG_MCU_MESSAGE ?= n ++ifeq ($(CONFIG_MCU_INTEGRATED), y) ++CONFIG_PMIC_SETTING = n ++else ++CONFIG_MCU_MESSAGE ?= n ++endif ++ ++# ++# WAITING FOR KCONFIG { ++# ++CONFIG_RWNX_FULLMAC ?= y ++CONFIG_RWNX_FHOST ?= n ++ ++# ++# DEBUG OPTIONS ++CONFIG_RWNX_UM_HELPER_DFLT ?= "/dini/dini_bin/rwnx_umh.sh" ++ ++# ++# FW ARCH: ++CONFIG_RWNX_SDM ?= n ++CONFIG_RWNX_TL4 ?= n ++ ++# IPC version ++CONFIG_RWNX_OLD_IPC ?= n ++ ++# Support of P2P DebugFS for enabling/disabling NoA and OppPS ++CONFIG_RWNX_P2P_DEBUGFS := n ++# ++# } // WAITING FOR KCONFIG ++# ++ ++# Enable A-MSDU support (need FW support) ++## Select this if FW is compiled with AMSDU support ++CONFIG_RWNX_SPLIT_TX_BUF ?= n ++## Select this TO send AMSDU ++CONFIG_RWNX_AMSDUS_TX ?= n ++ ++# Enable BFMER support (need FW support) ++CONFIG_RWNX_BFMER ?= n ++ ++CONFIG_SDIO_SUPPORT =y ++CONFIG_USB_SUPPORT =n ++CONFIG_RX_REORDER ?=y ++CONFIG_ARP_OFFLOAD =y ++CONFIG_RADAR_OR_IR_DETECT =n ++CONFIG_DOWNLOAD_FW =n ++CONFIG_RFTEST=y ++CONFIG_USB_BT =y ++CONFIG_SDIO_BT=n ++CONFIG_USE_5G ?= y ++CONFIG_CREATE_TRACE_POINTS = n ++CONFIG_TXRX_THREAD_PRIO = y ++# CONFIG_COEX = n for BT_ONLY, CONFIG_COEX =y for combo and sw ++CONFIG_COEX = y ++CONFIG_RX_NETIF_RECV_SKB = y ++CONFIG_SET_VENDOR_EXTENSION_IE = n ++CONFIG_SUPPORT_REALTIME_CHANGE_MAC = y ++CONFIG_WPA3_FOR_OLD_KERNEL ?= n ++CONFIG_VHT_FOR_OLD_KERNEL ?= n ++CONFIG_HE_FOR_OLD_KERNEL ?= n ++CONFIG_PREALLOC_RX_SKB ?= n ++CONFIG_WIFI_SUSPEND_FOR_LINUX = n ++# Need to set fw path in BOARD_KERNEL_CMDLINE ++CONFIG_USE_FW_REQUEST ?= n ++CONFIG_USE_P2P0=n ++CONFIG_TX_NETIF_FLOWCTRL = n ++CONFIG_ONE_TXQ = n ++CONFIG_BR_SUPPORT =n ++BR_NAME = br0 ++CONFIG_FDRV_NO_REG_SDIO=n ++CONFIG_SCHED_SCAN = n ++CONFIG_OOB ?= n ++CONFIG_USE_CUSTOMER_MAC = n ++CONFIG_PREALLOC_TXQ ?= y ++CONFIG_DPD = y ++CONFIG_FORCE_DPD_CALIB = y ++CONFIG_LOFT_CALIB = n ++CONFIG_FILTER_TCP_ACK =y ++CONFIG_RESV_MEM_SUPPORT ?= y ++CONFIG_GKI = n ++CONFIG_TEMP_COMP = n ++CONFIG_TEMP_CONTROL = n ++CONFIG_EXT_FEM_8800DCDW = n ++CONFIG_SHUTDOWN_CALLBACK = y ++CONFIG_FOR_IPCAM = n ++CONFIG_SDIO_ADMA = n ++# CONFIG_MCC = n for sta and p2p concurrent in same channel. ++CONFIG_MCC = y ++CONFIG_APF = n ++CONFIG_POWER_LIMIT = n ++ ++#CONFIG FOR LOW POWER MODE ++CONFIG_SDIO_PWRCTRL ?= y ++CONFIG_GPIO_WAKEUP ?= n ++CONFIG_AUTO_POWERSAVE = n ++ ++# Enable wifi-hal Latency Mode ++CONFIG_AICWF_LATENCY_MODE = n ++ ++ifneq ($(CONFIG_WIRELESS_EXT), y) ++CONFIG_USE_WIRELESS_EXT = n ++endif ++ ++ifeq ($(CONFIG_EXT_FEM_8800DCDW), y) ++CONFIG_DPD = n ++CONFIG_FORCE_DPD_CALIB = n ++CONFIG_LOFT_CALIB = y ++endif ++ ++# Support of MU-MIMO transmission (need FW support) ++ifeq ($(CONFIG_RWNX_BFMER), y) ++CONFIG_RWNX_MUMIMO_TX ?= n ++else ++CONFIG_RWNX_MUMIMO_TX = n ++endif ++ ++# Enable handling of radar event ++CONFIG_RWNX_RADAR ?= y ++ ++# Enable HW queue for Broadcast/Multicast traffic (need FW support) ++CONFIG_RWNX_BCMC ?= y ++ ++# Enable Monitor+Data interface support (need FW support) ++CONFIG_RWNX_MON_DATA = n ++CONFIG_RWNX_MON_XMIT = n ++CONFIG_RWNX_MON_RXFILTER = n ++ ++ ++# extra DEBUG config ++CONFIG_RWNX_SW_PROFILING ?= n ++CONFIG_RWNX_DBG ?= y ++CONFIG_DEBUG_FS ?= n ++ ++obj-$(CONFIG_AIC8800_WLAN_SUPPORT) := $(MODULE_NAME).o ++$(MODULE_NAME)-y := \ ++ rwnx_msg_tx.o \ ++ rwnx_msg_rx.o \ ++ rwnx_utils.o \ ++ rwnx_cmds.o \ ++ rwnx_irqs.o \ ++ rwnx_cfgfile.o \ ++ rwnx_strs.o \ ++ rwnx_rx.o \ ++ rwnx_tx.o \ ++ rwnx_txq.o \ ++ rwnx_main.o \ ++ rwnx_mod_params.o \ ++ rwnx_mesh.o \ ++ rwnx_platform.o \ ++ rwnx_pci.o \ ++ rwnx_dini.o \ ++ rwnx_v7.o \ ++ ipc_host.o \ ++ rwnx_tdls.o \ ++ aic_vendor.o \ ++ md5.o \ ++ aicwf_compat_8800dc.o \ ++ aicwf_compat_8800d80.o \ ++ rwnx_wakelock.o \ ++ regdb.o \ ++ aic_priv_cmd.o \ ++ aicwf_rx_prealloc.o ++ ++$(MODULE_NAME)-$(CONFIG_BR_SUPPORT) += aic_br_ext.o ++$(MODULE_NAME)-$(CONFIG_RWNX_RADAR) += rwnx_radar.o ++$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_debugfs.o ++$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_fw_trace.o ++$(MODULE_NAME)-$(CONFIG_NL80211_TESTMODE) += rwnx_testmode.o ++$(MODULE_NAME)-$(CONFIG_RWNX_BFMER) += rwnx_bfmer.o ++$(MODULE_NAME)-$(CONFIG_RWNX_MUMIMO_TX) += rwnx_mu_group.o ++$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += sdio_host.o ++$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_txrxif.o ++$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_sdio.o ++$(MODULE_NAME)-$(CONFIG_FILTER_TCP_ACK) += aicwf_tcp_ack.o ++$(MODULE_NAME)-$(CONFIG_SDIO_BT) += aic_btsdio.o ++$(MODULE_NAME)-$(CONFIG_SDIO_BT) += btsdio.o ++ ++$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += usb_host.o ++$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_txrxif.o ++$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_usb.o ++$(MODULE_NAME)-$(CONFIG_GKI) += rwnx_gki.o ++ ++ ++ ++ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_DEBUGFS ++ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_UM_HELPER_DFLT=\"$(CONFIG_RWNX_UM_HELPER_DFLT)\" ++ccflags-$(CONFIG_RWNX_P2P_DEBUGFS) += -DCONFIG_RWNX_P2P_DEBUGFS ++ ++# FW VARS ++ccflags-y += -DNX_VIRT_DEV_MAX=4 ++ ++#for 8800D and DCDW u01 ++#ccflags-y += -DNX_REMOTE_STA_MAX=10 ++ ++#for 8800DCDW u02 ++ccflags-y += -DNX_REMOTE_STA_MAX_FOR_OLD_IC=10 ++ccflags-y += -DNX_REMOTE_STA_MAX=32 ++ ++ccflags-y += -DNX_MU_GROUP_MAX=62 ++ccflags-y += -DNX_TXDESC_CNT=64 ++ccflags-y += -DNX_TX_MAX_RATES=4 ++ccflags-y += -DNX_CHAN_CTXT_CNT=3 ++ ++# FW ARCH: ++ccflags-$(CONFIG_RWNX_SDM) += -DCONFIG_RWNX_SDM ++ccflags-$(CONFIG_RWNX_TL4) += -DCONFIG_RWNX_TL4 ++ccflags-$(CONFIG_RWNX_OLD_IPC) += -DCONFIG_RWNX_OLD_IPC ++ccflags-$(CONFIG_PLATFORM_NANOPI_M4) += -DCONFIG_NANOPI_M4 ++ccflags-$(CONFIG_PLATFORM_INGENIC_T20) += -DCONFIG_INGENIC_T20 ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++ccflags-$(CONFIG_START_FROM_BOOTROM) += -DCONFIG_START_FROM_BOOTROM ++ccflags-$(CONFIG_PMIC_SETTING) += -DCONFIG_PMIC_SETTING ++ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE ++ccflags-$(CONFIG_ROM_PATCH_EN) += -DCONFIG_ROM_PATCH_EN ++ccflags-$(CONFIG_HE_FOR_OLD_KERNEL) += -DCONFIG_HE_FOR_OLD_KERNEL ++ccflags-$(CONFIG_MCU_INTEGRATED) += -DCONFIG_MCU_INTEGRATED ++ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE ++ccflags-$(CONFIG_COEX) += -DCONFIG_COEX ++ ++ccflags-y += -DCONFIG_RWNX_FULLMAC ++ccflags-y += -I$(srctree) ++ccflags-y += -I$(srctree)/$(src) ++ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp ++ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\" ++ccflags-$(CONFIG_RWNX_RADAR) += -DCONFIG_RWNX_RADAR ++ccflags-$(CONFIG_RWNX_MON_DATA) += -DCONFIG_RWNX_MON_DATA ++ccflags-$(CONFIG_RWNX_MON_XMIT) += -DCONFIG_RWNX_MON_XMIT ++ccflags-$(CONFIG_RWNX_MON_RXFILTER) += -DCONFIG_RWNX_MON_RXFILTER ++ ++ccflags-$(CONFIG_RWNX_BFMER) += -DCONFIG_RWNX_BFMER ++ccflags-$(CONFIG_RWNX_SPLIT_TX_BUF) += -DCONFIG_RWNX_SPLIT_TX_BUF ++ifeq ($(CONFIG_RWNX_SPLIT_TX_BUF), y) ++ccflags-$(CONFIG_RWNX_AMSDUS_TX) += -DCONFIG_RWNX_AMSDUS_TX ++endif ++ccflags-$(CONFIG_RWNX_DBG) += -DCONFIG_RWNX_DBG ++ccflags-$(CONFIG_RWNX_SW_PROFILING) += -DCONFIG_RWNX_SW_PROFILING ++ccflags-$(CONFIG_RWNX_MUMIMO_TX) += -DCONFIG_RWNX_MUMIMO_TX ++ccflags-$(CONFIG_RFTEST) += -DCONFIG_RFTEST ++ccflags-y += -DDEFAULT_COUNTRY_CODE=""\$(CONFIG_COUNTRY_CODE)"\" ++ccflags-$(CONFIG_USE_5G) += -DUSE_5G ++ccflags-$(CONFIG_CREATE_TRACE_POINTS) += -DCREATE_TRACE_POINTS ++ccflags-$(CONFIG_TXRX_THREAD_PRIO) += -DCONFIG_TXRX_THREAD_PRIO ++ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP ++ccflags-$(CONFIG_SET_VENDOR_EXTENSION_IE) += -DCONFIG_SET_VENDOR_EXTENSION_IE ++ccflags-$(CONFIG_SUPPORT_REALTIME_CHANGE_MAC) += -DCONFIG_SUPPORT_REALTIME_CHANGE_MAC ++ccflags-$(CONFIG_WPA3_FOR_OLD_KERNEL) += -DCONFIG_WPA3_FOR_OLD_KERNEL ++ccflags-$(CONFIG_VHT_FOR_OLD_KERNEL) += -DCONFIG_VHT_FOR_OLD_KERNEL ++ccflags-$(CONFIG_PREALLOC_RX_SKB) += -DCONFIG_PREALLOC_RX_SKB ++ccflags-$(CONFIG_WIFI_SUSPEND_FOR_LINUX) += -DCONFIG_WIFI_SUSPEND_FOR_LINUX ++ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST ++ccflags-$(CONFIG_USE_P2P0) += -DCONFIG_USE_P2P0 ++ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO ++ccflags-$(CONFIG_SCHED_SCAN) += -DCONFIG_SCHED_SCAN ++ccflags-$(CONFIG_OOB) += -DCONFIG_OOB ++ccflags-$(CONFIG_AICWF_LATENCY_MODE) += -DAICWF_LATENCY_MODE ++ccflags-$(CONFIG_USE_CUSTOMER_MAC) += -DCONFIG_USE_CUSTOMER_MAC ++ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ ++ccflags-$(CONFIG_DPD) += -DCONFIG_DPD ++ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD ++ccflags-$(CONFIG_LOFT_CALIB) += -DCONFIG_LOFT_CALIB ++ccflags-$(CONFIG_FILTER_TCP_ACK) += -DCONFIG_FILTER_TCP_ACK ++ccflags-$(CONFIG_SDIO_BT) += -DCONFIG_SDIO_BT ++ccflags-$(CONFIG_RESV_MEM_SUPPORT) += -DCONFIG_RESV_MEM_SUPPORT ++ccflags-$(CONFIG_GKI) += -DCONFIG_GKI ++ccflags-$(CONFIG_TEMP_COMP) += -DCONFIG_TEMP_COMP ++ccflags-$(CONFIG_TEMP_CONTROL) += -DCONFIG_TEMP_CONTROL ++ccflags-$(CONFIG_POWER_LIMIT) += -DCONFIG_POWER_LIMIT ++ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW ++ccflags-$(CONFIG_MCC) += -DCONFIG_MCC ++ccflags-$(CONFIG_SHUTDOWN_CALLBACK) += -DCONFIG_SHUTDOWN_CALLBACK ++ccflags-$(CONFIG_FOR_IPCAM) += -DCONFIG_FOR_IPCAM ++ccflags-$(CONFIG_SDIO_ADMA) += -DCONFIG_SDIO_ADMA ++ ++ ++ifeq ($(CONFIG_SDIO_SUPPORT), y) ++ccflags-y += -DAICWF_SDIO_SUPPORT ++ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL ++endif ++ ++ifeq ($(CONFIG_USB_SUPPORT), y) ++ccflags-y += -DAICWF_USB_SUPPORT ++endif ++ ++ifeq ($(CONFIG_BR_SUPPORT), y) ++ccflags-y += -DCONFIG_BR_SUPPORT ++ccflags-y += '-DCONFIG_BR_SUPPORT_BRNAME="'$(BR_NAME)'"' ++endif ++ ++ifeq ($(CONFIG_RWNX_MUMIMO_TX), y) ++ccflags-y += -DCONFIG_USER_MAX=2 ++else ++ccflags-y += -DCONFIG_USER_MAX=1 ++endif ++ ++ifeq ($(CONFIG_RWNX_BCMC), y) ++ccflags-y += -DNX_TXQ_CNT=5 ++else ++ccflags-y += -DNX_TXQ_CNT=4 ++endif ++ ++# For old kernel (<=3.19) ++ifeq ($(shell test $(VERSION) -lt 4 -a "$(CONFIG_VENDOR_RWNX)" = y ; echo $$?),0) ++ccflags-y += -DCONFIG_VENDOR_RWNX_VHT_NO80 ++endif ++ ++ccflags-$(CONFIG_RX_REORDER) += -DAICWF_RX_REORDER ++ccflags-$(CONFIG_ARP_OFFLOAD) += -DAICWF_ARP_OFFLOAD ++ccflags-$(CONFIG_RADAR_OR_IR_DETECT) += -DCONFIG_RADAR_OR_IR_DETECT ++ccflags-$(CONFIG_DOWNLOAD_FW) += -DCONFIG_DOWNLOAD_FW ++ccflags-$(CONFIG_RX_NETIF_RECV_SKB) += -DCONFIG_RX_NETIF_RECV_SKB ++ccflags-$(CONFIG_ONE_TXQ) += -DCONFIG_ONE_TXQ ++ccflags-$(CONFIG_TX_NETIF_FLOWCTRL) += -DCONFIG_TX_NETIF_FLOWCTRL ++ccflags-$(CONFIG_APF) += -DCONFIG_APF ++ccflags-$(CONFIG_AUTO_POWERSAVE) += -DCONFIG_AUTO_POWERSAVE ++ ++ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) ++MAKEFLAGS +=-j$(shell nproc) ++ ++########## Platform support list ########## ++CONFIG_PLATFORM_ROCKCHIP ?= n ++CONFIG_PLATFORM_ROCKCHIP2 ?= n ++CONFIG_PLATFORM_ALLWINNER ?= n ++CONFIG_PLATFORM_INGENIC_T20 ?= n ++CONFIG_PLATFORM_AMLOGIC ?= n ++CONFIG_PLATFORM_UBUNTU ?= y ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ARCH := arm64 ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE := /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++ARCH := arm64 ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE := /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++ccflags-y += -DANDROID_PLATFORM ++KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/ ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y) ++KDIR ?= /home/yaya/E/T40/kernel ++ARCH ?= mips ++CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++ccflags-$(CONFIG_PLATFORM_UBUNTU) += -DCONFIG_PLATFORM_UBUNTU ++KDIR ?= /lib/modules/$(shell uname -r)/build ++PWD ?= $(shell pwd) ++KVER ?= $(shell uname -r) ++MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ++ARCH ?= x86_64 ++CROSS_COMPILE ?= ++ ++ifeq ($(CONFIG_AW_BSP), y) ++ccflags-y += -DCONFIG_PLATFORM_ALLWINNER ++endif ++ ++endif ++########################################### ++ ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c +new file mode 100644 +index 000000000000..dd038e39f3fe +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c +@@ -0,0 +1,1569 @@ ++/****************************************************************************** ++ * ++ * Copyright(c) 2007 - 2017 Realtek Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ *****************************************************************************/ ++#define _AIC_BR_EXT_C_ ++ ++#ifdef __KERNEL__ ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include "rwnx_defs.h" ++#endif ++ ++#ifdef CL_IPV6_PASS ++ #ifdef __KERNEL__ ++ #include ++ #include ++ #include ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)) ++ #include ++ #else ++ #include ++ #endif ++ #endif ++#endif ++ ++#ifdef CONFIG_BR_SUPPORT ++ ++/* #define BR_SUPPORT_DEBUG */ ++ ++#define NAT25_IPV4 01 ++#define NAT25_IPV6 02 ++#define NAT25_IPX 03 ++#define NAT25_APPLE 04 ++#define NAT25_PPPOE 05 ++ ++#define RTL_RELAY_TAG_LEN (ETH_ALEN) ++#define TAG_HDR_LEN 4 ++ ++#define MAGIC_CODE 0x8186 ++#define MAGIC_CODE_LEN 2 ++#define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */ ++ ++/*----------------------------------------------------------------- ++ How database records network address: ++ 0 1 2 3 4 5 6 7 8 9 10 ++ |----|----|----|----|----|----|----|----|----|----|----| ++ IPv4 |type| | IP addr | ++ IPX |type| Net addr | Node addr | ++ IPX |type| Net addr |Sckt addr| ++ Apple |type| Network |node| ++ PPPoE |type| SID | AC MAC | ++-----------------------------------------------------------------*/ ++ ++ ++/* Find a tag in pppoe frame and return the pointer */ ++static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type) ++{ ++ unsigned char *cur_ptr, *start_ptr; ++ unsigned short tagLen, tagType; ++ ++ start_ptr = cur_ptr = (unsigned char *)ph->tag; ++ while ((cur_ptr - start_ptr) < ntohs(ph->length)) { ++ /* prevent un-alignment access */ ++ tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]); ++ tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]); ++ if (tagType == type) ++ return cur_ptr; ++ cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen; ++ } ++ return 0; ++} ++ ++ ++static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag) ++{ ++ struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); ++ int data_len; ++ ++ data_len = tag->tag_len + TAG_HDR_LEN; ++ if (skb_tailroom(skb) < data_len) { ++ printk("skb_tailroom() failed in add SID tag!\n"); ++ return -1; ++ } ++ ++ skb_put(skb, data_len); ++ /* have a room for new tag */ ++ memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length)); ++ ph->length = htons(ntohs(ph->length) + data_len); ++ memcpy((unsigned char *)ph->tag, tag, data_len); ++ return data_len; ++} ++ ++static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len) ++{ ++ int tail_len; ++ unsigned long end, tail; ++ ++ if ((src + len) > skb_tail_pointer(skb) || skb->len < len) ++ return -1; ++ ++ tail = (unsigned long)skb_tail_pointer(skb); ++ end = (unsigned long)src + len; ++ if (tail < end) ++ return -1; ++ ++ tail_len = (int)(tail - end); ++ if (tail_len > 0) ++ memmove(src, src + len, tail_len); ++ ++ skb_trim(skb, skb->len - len); ++ return 0; ++} ++ ++static __inline__ unsigned long __nat25_timeout(struct rwnx_vif *vif) ++{ ++ unsigned long timeout; ++ ++ timeout = jiffies - NAT25_AGEING_TIME * HZ; ++ ++ return timeout; ++} ++ ++ ++static __inline__ int __nat25_has_expired(struct rwnx_vif *vif, ++ struct nat25_network_db_entry *fdb) ++{ ++ if (time_before_eq(fdb->ageing_timer, __nat25_timeout(vif))) ++ return 1; ++ ++ return 0; ++} ++ ++ ++static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr, ++ unsigned int *ipAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPV4; ++ memcpy(networkAddr + 7, (unsigned char *)ipAddr, 4); ++} ++ ++ ++static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr, ++ unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPX; ++ memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); ++ memcpy(networkAddr + 5, ipxNodeAddr, 6); ++} ++ ++ ++static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr, ++ unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPX; ++ memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); ++ memcpy(networkAddr + 5, (unsigned char *)ipxSocketAddr, 2); ++} ++ ++ ++static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr, ++ unsigned short *network, unsigned char *node) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_APPLE; ++ memcpy(networkAddr + 1, (unsigned char *)network, 2); ++ networkAddr[3] = *node; ++} ++ ++ ++static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr, ++ unsigned char *ac_mac, unsigned short *sid) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_PPPOE; ++ memcpy(networkAddr + 1, (unsigned char *)sid, 2); ++ memcpy(networkAddr + 3, (unsigned char *)ac_mac, 6); ++} ++ ++ ++#ifdef CL_IPV6_PASS ++static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr, ++ unsigned int *ipAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPV6; ++ memcpy(networkAddr + 1, (unsigned char *)ipAddr, 16); ++} ++ ++ ++static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b) ++{ ++ while (len > 0) { ++ if (*data == tag && *(data + 1) == len8b && len >= len8b * 8) ++ return data + 2; ++ ++ len -= (*(data + 1)) * 8; ++ data += (*(data + 1)) * 8; ++ } ++ return NULL; ++} ++ ++ ++static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac) ++{ ++ struct icmp6hdr *icmphdr = (struct icmp6hdr *)data; ++ unsigned char *mac; ++ ++ if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { ++ if (len >= 8) { ++ mac = scan_tlv(&data[8], len - 8, 1, 1); ++ if (mac) { ++ printk("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) { ++ if (len >= 16) { ++ mac = scan_tlv(&data[16], len - 16, 1, 1); ++ if (mac) { ++ printk("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { ++ if (len >= 24) { ++ mac = scan_tlv(&data[24], len - 24, 1, 1); ++ if (mac) { ++ printk("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { ++ if (len >= 24) { ++ mac = scan_tlv(&data[24], len - 24, 2, 1); ++ if (mac) { ++ printk("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_REDIRECT) { ++ if (len >= 40) { ++ mac = scan_tlv(&data[40], len - 40, 2, 1); ++ if (mac) { ++ printk("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } ++ return 0; ++} ++ ++#ifdef SUPPORT_RX_UNI2MCAST ++static void convert_ipv6_mac_to_mc(struct sk_buff *skb) ++{ ++ struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); ++ unsigned char *dst_mac = skb->data; ++ ++ /* dst_mac[0] = 0xff; */ ++ /* dst_mac[1] = 0xff; */ ++ /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/ ++ dst_mac[0] = 0x33; ++ dst_mac[1] = 0x33; ++ memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4); ++#if defined(__LINUX_2_6__) ++ /*modified by qinjunjie,warning:should not remove next line*/ ++ skb->pkt_type = PACKET_MULTICAST; ++#endif ++} ++#endif /* CL_IPV6_PASS */ ++#endif /* SUPPORT_RX_UNI2MCAST */ ++ ++ ++static __inline__ int __nat25_network_hash(unsigned char *networkAddr) ++{ ++ if (networkAddr[0] == NAT25_IPV4) { ++ unsigned long x; ++ ++ x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } else if (networkAddr[0] == NAT25_IPX) { ++ unsigned long x; ++ ++ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ ++ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } else if (networkAddr[0] == NAT25_APPLE) { ++ unsigned long x; ++ ++ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } else if (networkAddr[0] == NAT25_PPPOE) { ++ unsigned long x; ++ ++ x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } ++#ifdef CL_IPV6_PASS ++ else if (networkAddr[0] == NAT25_IPV6) { ++ unsigned long x; ++ ++ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ ++ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^ ++ networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^ ++ networkAddr[16]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } ++#endif ++ else { ++ unsigned long x = 0; ++ int i; ++ ++ for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++) ++ x ^= networkAddr[i]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } ++} ++ ++ ++static __inline__ void __network_hash_link(struct rwnx_vif *vif, ++ struct nat25_network_db_entry *ent, int hash) ++{ ++ /* Caller must _enter_critical_bh already! */ ++ /* _irqL irqL; */ ++ /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ ++ ++ ent->next_hash = vif->nethash[hash]; ++ if (ent->next_hash != NULL) ++ ent->next_hash->pprev_hash = &ent->next_hash; ++ vif->nethash[hash] = ent; ++ ent->pprev_hash = &vif->nethash[hash]; ++ ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++} ++ ++ ++static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent) ++{ ++ /* Caller must _enter_critical_bh already! */ ++ /* _irqL irqL; */ ++ /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ ++ ++ *(ent->pprev_hash) = ent->next_hash; ++ if (ent->next_hash != NULL) ++ ent->next_hash->pprev_hash = ent->pprev_hash; ++ ent->next_hash = NULL; ++ ent->pprev_hash = NULL; ++ ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++} ++ ++ ++static int __nat25_db_network_lookup_and_replace(struct rwnx_vif *vif, ++ struct sk_buff *skb, unsigned char *networkAddr) ++{ ++ struct nat25_network_db_entry *db; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ db = vif->nethash[__nat25_network_hash(networkAddr)]; ++ while (db != NULL) { ++ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { ++ if (!__nat25_has_expired(vif, db)) { ++ /* replace the destination mac address */ ++ memcpy(skb->data, db->macAddr, ETH_ALEN); ++ atomic_inc(&db->use_count); ++ ++#ifdef CL_IPV6_PASS ++ printk("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ++ "%02x%02x%02x%02x%02x%02x\n", ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10], ++ db->networkAddr[11], ++ db->networkAddr[12], ++ db->networkAddr[13], ++ db->networkAddr[14], ++ db->networkAddr[15], ++ db->networkAddr[16]); ++#else ++ printk("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10]); ++#endif ++ } ++ spin_unlock_bh(&vif->br_ext_lock); ++ return 1; ++ } ++ ++ db = db->next_hash; ++ } ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++ return 0; ++} ++ ++ ++static void __nat25_db_network_insert(struct rwnx_vif *vif, ++ unsigned char *macAddr, unsigned char *networkAddr) ++{ ++ struct nat25_network_db_entry *db; ++ int hash; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ hash = __nat25_network_hash(networkAddr); ++ db = vif->nethash[hash]; ++ ++ while (db != NULL) { ++ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { ++ memcpy(db->macAddr, macAddr, ETH_ALEN); ++ db->ageing_timer = jiffies; ++ spin_unlock_bh(&vif->br_ext_lock); ++ return; ++ } ++ ++ db = db->next_hash; ++ } ++ ++ db = (struct nat25_network_db_entry *)kmalloc(sizeof(*db), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); ++ if (db == NULL) { ++ spin_unlock_bh(&vif->br_ext_lock); ++ return; ++ } ++ ++ memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN); ++ memcpy(db->macAddr, macAddr, ETH_ALEN); ++ atomic_set(&db->use_count, 1); ++ db->ageing_timer = jiffies; ++ ++ __network_hash_link(vif, db, hash); ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++static void __nat25_db_print(struct rwnx_vif *vif) ++{ ++ spin_lock_bh(&vif->br_ext_lock); ++ ++#ifdef BR_SUPPORT_DEBUG ++ static int counter = 0; ++ int i, j; ++ struct nat25_network_db_entry *db; ++ ++ counter++; ++ if ((counter % 16) != 0) ++ return; ++ ++ for (i = 0, j = 0; i < NAT25_HASH_SIZE; i++) { ++ db = vif->nethash[i]; ++ ++ while (db != NULL) { ++#ifdef CL_IPV6_PASS ++ printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ++ "%02x%02x%02x%02x%02x%02x\n", ++ j, ++ i, ++ atomic_read(&db->use_count), ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10], ++ db->networkAddr[11], ++ db->networkAddr[12], ++ db->networkAddr[13], ++ db->networkAddr[14], ++ db->networkAddr[15], ++ db->networkAddr[16]); ++#else ++ printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ j, ++ i, ++ atomic_read(&db->use_count), ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10]); ++#endif ++ j++; ++ ++ db = db->next_hash; ++ } ++ } ++#endif ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++ ++ ++/* ++ * NAT2.5 interface ++ */ ++ ++void nat25_db_cleanup(struct rwnx_vif *vif) ++{ ++ int i; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ for (i = 0; i < NAT25_HASH_SIZE; i++) { ++ struct nat25_network_db_entry *f; ++ f = vif->nethash[i]; ++ while (f != NULL) { ++ struct nat25_network_db_entry *g; ++ ++ g = f->next_hash; ++ if (vif->scdb_entry == f) { ++ memset(vif->scdb_mac, 0, ETH_ALEN); ++ memset(vif->scdb_ip, 0, 4); ++ vif->scdb_entry = NULL; ++ } ++ __network_hash_unlink(f); ++ kfree(f); ++ ++ f = g; ++ } ++ } ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++void nat25_db_expire(struct rwnx_vif *vif) ++{ ++ int i; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ /* if(!priv->ethBrExtInfo.nat25_disable) */ ++ { ++ for (i = 0; i < NAT25_HASH_SIZE; i++) { ++ struct nat25_network_db_entry *f; ++ f = vif->nethash[i]; ++ ++ while (f != NULL) { ++ struct nat25_network_db_entry *g; ++ g = f->next_hash; ++ ++ if (__nat25_has_expired(vif, f)) { ++ if (atomic_dec_and_test(&f->use_count)) { ++#ifdef BR_SUPPORT_DEBUG ++#ifdef CL_IPV6_PASS ++ panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ++ "%02x%02x%02x%02x%02x%02x\n", ++ i, ++ f->macAddr[0], ++ f->macAddr[1], ++ f->macAddr[2], ++ f->macAddr[3], ++ f->macAddr[4], ++ f->macAddr[5], ++ f->networkAddr[0], ++ f->networkAddr[1], ++ f->networkAddr[2], ++ f->networkAddr[3], ++ f->networkAddr[4], ++ f->networkAddr[5], ++ f->networkAddr[6], ++ f->networkAddr[7], ++ f->networkAddr[8], ++ f->networkAddr[9], ++ f->networkAddr[10], ++ f->networkAddr[11], ++ f->networkAddr[12], ++ f->networkAddr[13], ++ f->networkAddr[14], ++ f->networkAddr[15], ++ f->networkAddr[16]); ++#else ++ ++ panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ i, ++ f->macAddr[0], ++ f->macAddr[1], ++ f->macAddr[2], ++ f->macAddr[3], ++ f->macAddr[4], ++ f->macAddr[5], ++ f->networkAddr[0], ++ f->networkAddr[1], ++ f->networkAddr[2], ++ f->networkAddr[3], ++ f->networkAddr[4], ++ f->networkAddr[5], ++ f->networkAddr[6], ++ f->networkAddr[7], ++ f->networkAddr[8], ++ f->networkAddr[9], ++ f->networkAddr[10]); ++#endif ++#endif ++ if (vif->scdb_entry == f) { ++ memset(vif->scdb_mac, 0, ETH_ALEN); ++ memset(vif->scdb_ip, 0, 4); ++ vif->scdb_entry = NULL; ++ } ++ __network_hash_unlink(f); ++ kfree(f); ++ } ++ } ++ ++ f = g; ++ } ++ } ++ } ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++#ifdef SUPPORT_TX_MCAST2UNI ++static int checkIPMcAndReplace(struct rwnx_vif *vif, struct sk_buff *skb, unsigned int *dst_ip) ++{ ++ struct stat_info *pstat; ++ struct list_head *phead, *plist; ++ int i; ++ ++ phead = &vif->asoc_list; ++ plist = phead->next; ++ ++ while (plist != phead) { ++ pstat = list_entry(plist, struct stat_info, asoc_list); ++ plist = plist->next; ++ ++ if (pstat->ipmc_num == 0) ++ continue; ++ ++ for (i = 0; i < MAX_IP_MC_ENTRY; i++) { ++ if (pstat->ipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip) + 1, 3)) { ++ memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN); ++ return 1; ++ } ++ } ++ } ++ return 0; ++} ++#endif ++ ++int nat25_db_handle(struct rwnx_vif *vif, struct sk_buff *skb, int method) ++{ ++ unsigned short protocol; ++ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; ++ ++ if (skb == NULL) ++ return -1; ++ ++ if ((method <= NAT25_MIN) || (method >= NAT25_MAX)) ++ return -1; ++ ++ protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); ++ ++ /*---------------------------------------------------*/ ++ /* Handle IP frame */ ++ /*---------------------------------------------------*/ ++ if (protocol == __constant_htons(ETH_P_IP)) { ++ struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); ++ ++ if (((unsigned char *)(iph) + (iph->ihl << 2)) >= (skb->data + ETH_HLEN + skb->len)) { ++ printk("NAT25: malformed IP packet !\n"); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: { ++ /* some muticast with source IP is all zero, maybe other case is illegal */ ++ /* in class A, B, C, host address is all zero or all one is illegal */ ++ if (iph->saddr == 0) ++ return 0; ++ printk("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); ++ __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr); ++ /* record source IP address and , source mac address into db */ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); ++#ifdef SUPPORT_TX_MCAST2UNI ++ if (vif->pshare->rf_ft_var.mc2u_disable || ++ ((((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) ++ == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) && ++ !checkIPMcAndReplace(vif, skb, &iph->daddr)) || ++ (OPMODE & WIFI_ADHOC_STATE))) ++#endif ++ { ++ __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr); ++ ++ if (!__nat25_db_network_lookup_and_replace(vif, skb, networkAddr)) { ++ if (*((unsigned char *)&iph->daddr + 3) == 0xff) { ++ /* L2 is unicast but L3 is broadcast, make L2 bacome broadcast */ ++ printk("NAT25: Set DA as boardcast\n"); ++ memset(skb->data, 0xff, ETH_ALEN); ++ } else { ++ /* forward unknow IP packet to upper TCP/IP */ ++ printk("NAT25: Replace DA with BR's MAC\n"); ++ if ((*(u32 *)vif->br_mac) == 0 && (*(u16 *)(vif->br_mac + 4)) == 0) { ++ void netdev_br_init(struct net_device *netdev); ++ printk("Re-init netdev_br_init() due to br_mac==0!\n"); ++ netdev_br_init(vif->ndev); ++ } ++ memcpy(skb->data, vif->br_mac, ETH_ALEN); ++ } ++ } ++ } ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle ARP frame */ ++ /*---------------------------------------------------*/ ++ else if (protocol == __constant_htons(ETH_P_ARP)) { ++ struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); ++ unsigned char *arp_ptr = (unsigned char *)(arp + 1); ++ unsigned int *sender, *target; ++ ++ if (arp->ar_pro != __constant_htons(ETH_P_IP)) { ++ printk("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro)); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ return 0; /* skb_copy for all ARP frame */ ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0], ++ arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]); ++ ++ /* change to ARP sender mac address to wlan STA address */ ++ memcpy(arp_ptr, vif->ndev->dev_addr, ETH_ALEN); ++ ++ arp_ptr += arp->ar_hln; ++ sender = (unsigned int *)arp_ptr; ++ ++ __nat25_generate_ipv4_network_addr(networkAddr, sender); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup ARP\n"); ++ ++ arp_ptr += arp->ar_hln; ++ sender = (unsigned int *)arp_ptr; ++ arp_ptr += (arp->ar_hln + arp->ar_pln); ++ target = (unsigned int *)arp_ptr; ++ ++ __nat25_generate_ipv4_network_addr(networkAddr, target); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ /* change to ARP target mac address to Lookup result */ ++ arp_ptr = (unsigned char *)(arp + 1); ++ arp_ptr += (arp->ar_hln + arp->ar_pln); ++ memcpy(arp_ptr, skb->data, ETH_ALEN); ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle IPX and Apple Talk frame */ ++ /*---------------------------------------------------*/ ++ else if ((protocol == __constant_htons(ETH_P_IPX)) || ++ (protocol == __constant_htons(ETH_P_ATALK)) || ++ (protocol == __constant_htons(ETH_P_AARP))) { ++ unsigned char ipx_header[2] = {0xFF, 0xFF}; ++ struct ipxhdr *ipx = NULL; ++ struct elapaarp *ea = NULL; ++ struct ddpehdr *ddp = NULL; ++ unsigned char *framePtr = skb->data + ETH_HLEN; ++ ++ if (protocol == __constant_htons(ETH_P_IPX)) { ++ printk("NAT25: Protocol=IPX (Ethernet II)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else { /* if(protocol <= __constant_htons(ETH_FRAME_LEN)) */ ++ if (!memcmp(ipx_header, framePtr, 2)) { ++ printk("NAT25: Protocol=IPX (Ethernet 802.3)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else { ++ unsigned char ipx_8022_type = 0xE0; ++ unsigned char snap_8022_type = 0xAA; ++ ++ if (*framePtr == snap_8022_type) { ++ unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; /* IPX SNAP ID */ ++ unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; /* Apple Talk AARP SNAP ID */ ++ unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; /* Apple Talk DDP SNAP ID */ ++ ++ framePtr += 3; /* eliminate the 802.2 header */ ++ ++ if (!memcmp(ipx_snap_id, framePtr, 5)) { ++ framePtr += 5; /* eliminate the SNAP header */ ++ ++ printk("NAT25: Protocol=IPX (Ethernet SNAP)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else if (!memcmp(aarp_snap_id, framePtr, 5)) { ++ framePtr += 5; /* eliminate the SNAP header */ ++ ++ ea = (struct elapaarp *)framePtr; ++ } else if (!memcmp(ddp_snap_id, framePtr, 5)) { ++ framePtr += 5; /* eliminate the SNAP header */ ++ ++ ddp = (struct ddpehdr *)framePtr; ++ } else { ++ printk("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0], ++ framePtr[1], framePtr[2], framePtr[3], framePtr[4]); ++ return -1; ++ } ++ } else if (*framePtr == ipx_8022_type) { ++ framePtr += 3; /* eliminate the 802.2 header */ ++ ++ if (!memcmp(ipx_header, framePtr, 2)) { ++ printk("NAT25: Protocol=IPX (Ethernet 802.2)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else ++ return -1; ++ } ++ } ++ } ++ ++ /* IPX */ ++ if (ipx != NULL) { ++ switch (method) { ++ case NAT25_CHECK: ++ if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { ++ printk("NAT25: Check IPX skb_copy\n"); ++ return 0; ++ } ++ return -1; ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n", ++ ipx->ipx_dest.net, ++ ipx->ipx_dest.node[0], ++ ipx->ipx_dest.node[1], ++ ipx->ipx_dest.node[2], ++ ipx->ipx_dest.node[3], ++ ipx->ipx_dest.node[4], ++ ipx->ipx_dest.node[5], ++ ipx->ipx_dest.sock, ++ ipx->ipx_source.net, ++ ipx->ipx_source.node[0], ++ ipx->ipx_source.node[1], ++ ipx->ipx_source.node[2], ++ ipx->ipx_source.node[3], ++ ipx->ipx_source.node[4], ++ ipx->ipx_source.node[5], ++ ipx->ipx_source.sock); ++ ++ if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { ++ printk("NAT25: Use IPX Net, and Socket as network addr\n"); ++ ++ __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock); ++ ++ /* change IPX source node addr to wlan STA address */ ++ memcpy(ipx->ipx_source.node, vif->ndev->dev_addr, ETH_ALEN); ++ } else ++ __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ if (!memcmp(vif->ndev->dev_addr, ipx->ipx_dest.node, ETH_ALEN)) { ++ printk("NAT25: Lookup IPX, Modify Destination IPX Node addr\n"); ++ ++ __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ /* replace IPX destination node addr with Lookup destination MAC addr */ ++ memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN); ++ } else { ++ __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ } ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /* AARP */ ++ else if (ea != NULL) { ++ /* Sanity check fields. */ ++ if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) { ++ printk("NAT25: Appletalk AARP Sanity check fail!\n"); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ return 0; ++ ++ case NAT25_INSERT: { ++ /* change to AARP source mac address to wlan STA address */ ++ memcpy(ea->hw_src, vif->ndev->dev_addr, ETH_ALEN); ++ ++ printk("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n", ++ ea->pa_src_net, ++ ea->pa_src_node, ++ ea->pa_dst_net, ++ ea->pa_dst_node); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n", ++ ea->pa_src_net, ++ ea->pa_src_node, ++ ea->pa_dst_net, ++ ea->pa_dst_node); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ /* change to AARP destination mac address to Lookup result */ ++ memcpy(ea->hw_dst, skb->data, ETH_ALEN); ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /* DDP */ ++ else if (ddp != NULL) { ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n", ++ ddp->deh_snet, ++ ddp->deh_snode, ++ ddp->deh_dnet, ++ ddp->deh_dnode); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n", ++ ddp->deh_snet, ++ ddp->deh_snode, ++ ddp->deh_dnet, ++ ddp->deh_dnode); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ return -1; ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle PPPoE frame */ ++ /*---------------------------------------------------*/ ++ else if ((protocol == __constant_htons(ETH_P_PPP_DISC)) || ++ (protocol == __constant_htons(ETH_P_PPP_SES))) { ++ struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); ++ unsigned short *pMagic; ++ ++ switch (method) { ++ case NAT25_CHECK: ++ if (ph->sid == 0) ++ return 0; ++ return 1; ++ ++ case NAT25_INSERT: ++ if (ph->sid == 0) { /* Discovery phase according to tag */ ++ if (ph->code == PADI_CODE || ph->code == PADR_CODE) { ++ if (vif->ethBrExtInfo.addPPPoETag) { ++ struct pppoe_tag *tag, *pOldTag; ++ unsigned char tag_buf[40]; ++ int old_tag_len = 0; ++ ++ tag = (struct pppoe_tag *)tag_buf; ++ pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); ++ if (pOldTag) { /* if SID existed, copy old value and delete it */ ++ old_tag_len = ntohs(pOldTag->tag_len); ++ if (old_tag_len + TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN > sizeof(tag_buf)) { ++ printk("SID tag length too long!\n"); ++ return -1; ++ } ++ ++ memcpy(tag->tag_data + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN, ++ pOldTag->tag_data, old_tag_len); ++ ++ if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN + old_tag_len) < 0) { ++ printk("call skb_pull_and_merge() failed in PADI/R packet!\n"); ++ return -1; ++ } ++ ph->length = htons(ntohs(ph->length) - TAG_HDR_LEN - old_tag_len); ++ } ++ ++ tag->tag_type = PTT_RELAY_SID; ++ tag->tag_len = htons(MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN + old_tag_len); ++ ++ /* insert the magic_code+client mac in relay tag */ ++ pMagic = (unsigned short *)tag->tag_data; ++ *pMagic = htons(MAGIC_CODE); ++ memcpy(tag->tag_data + MAGIC_CODE_LEN, skb->data + ETH_ALEN, ETH_ALEN); ++ ++ /* Add relay tag */ ++ if (__nat25_add_pppoe_tag(skb, tag) < 0) ++ return -1; ++ ++ printk("NAT25: Insert PPPoE, forward %s packet\n", ++ (ph->code == PADI_CODE ? "PADI" : "PADR")); ++ } else { /* not add relay tag */ ++ if (vif->pppoe_connection_in_progress && ++ memcmp(skb->data + ETH_ALEN, vif->pppoe_addr, ETH_ALEN)) { ++ printk("Discard PPPoE packet due to another PPPoE connection is in progress!\n"); ++ return -2; ++ } ++ ++ if (vif->pppoe_connection_in_progress == 0) ++ memcpy(vif->pppoe_addr, skb->data + ETH_ALEN, ETH_ALEN); ++ ++ vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE; ++ } ++ } else ++ return -1; ++ } else { /* session phase */ ++ printk("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name); ++ ++ __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid)); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ ++ if (!vif->ethBrExtInfo.addPPPoETag && ++ vif->pppoe_connection_in_progress && ++ !memcmp(skb->data + ETH_ALEN, vif->pppoe_addr, ETH_ALEN)) ++ vif->pppoe_connection_in_progress = 0; ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: ++ if (ph->code == PADO_CODE || ph->code == PADS_CODE) { ++ if (vif->ethBrExtInfo.addPPPoETag) { ++ struct pppoe_tag *tag; ++ unsigned char *ptr; ++ unsigned short tagType, tagLen; ++ int offset = 0; ++ ++ ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); ++ if (ptr == 0) { ++ printk("Fail to find PTT_RELAY_SID in FADO!\n"); ++ return -1; ++ } ++ ++ tag = (struct pppoe_tag *)ptr; ++ tagType = (unsigned short)((ptr[0] << 8) + ptr[1]); ++ tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]); ++ ++ if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN))) { ++ printk("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen); ++ return -1; ++ } ++ ++ pMagic = (unsigned short *)tag->tag_data; ++ if (ntohs(*pMagic) != MAGIC_CODE) { ++ printk("Can't find MAGIC_CODE in %s packet!\n", ++ (ph->code == PADO_CODE ? "PADO" : "PADS")); ++ return -1; ++ } ++ ++ memcpy(skb->data, tag->tag_data + MAGIC_CODE_LEN, ETH_ALEN); ++ ++ if (tagLen > MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN) ++ offset = TAG_HDR_LEN; ++ ++ if (skb_pull_and_merge(skb, ptr + offset, TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset) < 0) { ++ printk("call skb_pull_and_merge() failed in PADO packet!\n"); ++ return -1; ++ } ++ ph->length = htons(ntohs(ph->length) - (TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset)); ++ if (offset > 0) ++ tag->tag_len = htons(tagLen - MAGIC_CODE_LEN - RTL_RELAY_TAG_LEN); ++ ++ printk("NAT25: Lookup PPPoE, forward %s Packet from %s\n", ++ (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name); ++ } else { /* not add relay tag */ ++ if (!vif->pppoe_connection_in_progress) { ++ printk("Discard PPPoE packet due to no connection in progresss!\n"); ++ return -1; ++ } ++ memcpy(skb->data, vif->pppoe_addr, ETH_ALEN); ++ vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE; ++ } ++ } else { ++ if (ph->sid != 0) { ++ printk("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name); ++ __nat25_generate_pppoe_network_addr(networkAddr, skb->data + ETH_ALEN, &(ph->sid)); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ __nat25_db_print(vif); ++ } else ++ return -1; ++ ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle EAP frame */ ++ /*---------------------------------------------------*/ ++ else if (protocol == __constant_htons(0x888e)) { ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: ++ return 0; ++ ++ case NAT25_LOOKUP: ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle C-Media proprietary frame */ ++ /*---------------------------------------------------*/ ++ else if ((protocol == __constant_htons(0xe2ae)) || ++ (protocol == __constant_htons(0xe2af))) { ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: ++ return 0; ++ ++ case NAT25_LOOKUP: ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle IPV6 frame */ ++ /*---------------------------------------------------*/ ++#ifdef CL_IPV6_PASS ++ else if (protocol == __constant_htons(ETH_P_IPV6)) { ++ struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); ++ ++ if (sizeof(*iph) >= (skb->len - ETH_HLEN)) { ++ printk("NAT25: malformed IPv6 packet !\n"); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ if (skb->data[0] & 1) ++ return 0; ++ return -1; ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," ++ " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", ++ iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], ++ iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], ++ iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], ++ iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); ++ ++ if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) { ++ __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr); ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ __nat25_db_print(vif); ++ ++ if (iph->nexthdr == IPPROTO_ICMPV6 && ++ skb->len > (ETH_HLEN + sizeof(*iph) + 4)) { ++ if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), ++ skb->len - ETH_HLEN - sizeof(*iph), vif->ndev->dev_addr)) { ++ struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); ++ hdr->icmp6_cksum = 0; ++ hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr, ++ iph->payload_len, ++ IPPROTO_ICMPV6, ++ csum_partial((__u8 *)hdr, iph->payload_len, 0)); ++ } ++ } ++ } ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: ++ printk("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," ++ " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", ++ iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], ++ iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], ++ iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], ++ iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); ++ ++ ++ __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr); ++ if (!__nat25_db_network_lookup_and_replace(vif, skb, networkAddr)) { ++#ifdef SUPPORT_RX_UNI2MCAST ++ if (iph->daddr.s6_addr[0] == 0xff) ++ convert_ipv6_mac_to_mc(skb); ++#endif ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++#endif /* CL_IPV6_PASS */ ++ ++ return -1; ++} ++ ++ ++int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb) ++{ ++ //printk("%s : vif_type=%d \n",__func__,RWNX_VIF_TYPE(vif)); ++#ifdef BR_SUPPORT_DEBUG ++ if ((!vif->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1))) { ++ printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n", ++ skb->data[0], ++ skb->data[1], ++ skb->data[2], ++ skb->data[3], ++ skb->data[4], ++ skb->data[5], ++ skb->data[6], ++ skb->data[7], ++ skb->data[8], ++ skb->data[9], ++ skb->data[10], ++ skb->data[11]); ++ } ++#endif ++ ++ if (!(skb->data[0] & 1)) { ++ int is_vlan_tag = 0, i, retval = 0; ++ unsigned short vlan_hdr = 0; ++ ++ if (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_8021Q)) { ++ is_vlan_tag = 1; ++ vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2)); ++ skb_pull(skb, 4); ++ } ++ ++ if (!vif->ethBrExtInfo.nat25_disable) { ++ unsigned long irqL; ++ spin_lock_bh(&vif->br_ext_lock); ++ /* ++ * This function look up the destination network address from ++ * the NAT2.5 database. Return value = -1 means that the ++ * corresponding network protocol is NOT support. ++ */ ++ if (!vif->ethBrExtInfo.nat25sc_disable && ++ (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && ++ !memcmp(vif->scdb_ip, skb->data + ETH_HLEN + 16, 4)) { ++ memcpy(skb->data, vif->scdb_mac, ETH_ALEN); ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++ } else { ++ spin_unlock_bh(&vif->br_ext_lock); ++ ++ retval = nat25_db_handle(vif, skb, NAT25_LOOKUP); ++ } ++ } else { ++ if (((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && ++ !memcmp(vif->br_ip, skb->data + ETH_HLEN + 16, 4)) || ++ ((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_ARP)) && ++ !memcmp(vif->br_ip, skb->data + ETH_HLEN + 24, 4))) { ++ /* for traffic to upper TCP/IP */ ++ retval = nat25_db_handle(vif, skb, NAT25_LOOKUP); ++ } ++ } ++ ++ if (is_vlan_tag) { ++ skb_push(skb, 4); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); ++ *((unsigned short *)(skb->data + ETH_ALEN * 2)) = __constant_htons(ETH_P_8021Q); ++ *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr; ++ } ++ ++ if (retval == -1) { ++ /* DEBUG_ERR("NAT25: Lookup fail!\n"); */ ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++#if 0 ++void mac_clone(_adapter *priv, unsigned char *addr) ++{ ++ struct sockaddr sa; ++ ++ memcpy(sa.sa_data, addr, ETH_ALEN); ++ RTW_INFO("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); ++ rtl8192cd_set_hwaddr(priv->dev, &sa); ++} ++ ++ ++int mac_clone_handle_frame(_adapter *priv, struct sk_buff *skb) ++{ ++ if (priv->ethBrExtInfo.macclone_enable && !priv->macclone_completed) { ++ if (!(skb->data[ETH_ALEN] & 1)) { /* check any other particular MAC add */ ++ if (memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(priv), ETH_ALEN) && ++ ((priv->dev->br_port) && ++ memcmp(skb->data + ETH_ALEN, priv->br_mac, ETH_ALEN))) { ++ mac_clone(priv, skb->data + ETH_ALEN); ++ priv->macclone_completed = 1; ++ } ++ } ++ } ++ ++ return 0; ++} ++#endif /* 0 */ ++ ++#define SERVER_PORT 67 ++#define CLIENT_PORT 68 ++#define DHCP_MAGIC 0x63825363 ++#define BROADCAST_FLAG 0x8000 ++ ++struct dhcpMessage { ++ u_int8_t op; ++ u_int8_t htype; ++ u_int8_t hlen; ++ u_int8_t hops; ++ u_int32_t xid; ++ u_int16_t secs; ++ u_int16_t flags; ++ u_int32_t ciaddr; ++ u_int32_t yiaddr; ++ u_int32_t siaddr; ++ u_int32_t giaddr; ++ u_int8_t chaddr[16]; ++ u_int8_t sname[64]; ++ u_int8_t file[128]; ++ u_int32_t cookie; ++ u_int8_t options[308]; /* 312 - cookie */ ++}; ++ ++void dhcp_flag_bcast(struct rwnx_vif *vif, struct sk_buff *skb) ++{ ++ if (skb == NULL) ++ return; ++ //print_hex_dump(KERN_ERR, "SKB DUMP: SKB->DATA== ", DUMP_PREFIX_NONE, 32, 1, skb->data, 64,false); ++ if (!vif->ethBrExtInfo.dhcp_bcst_disable) { ++ unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); ++ printk("%s protocol: %04x\n", __func__, protocol); ++ ++ if (protocol == __constant_htons(ETH_P_IP)) { /* IP */ ++ struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); ++ ++ if (iph->protocol == IPPROTO_UDP) { /* UDP */ ++ struct udphdr *udph = (struct udphdr *)((u8 *)iph + (iph->ihl << 2)); ++ ++ if ((udph->source == __constant_htons(CLIENT_PORT)) ++ && (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */ ++ struct dhcpMessage *dhcph = ++ (struct dhcpMessage *)((u8 *)udph + sizeof(struct udphdr)); ++ ++ if (dhcph->cookie == __constant_htonl(DHCP_MAGIC)) { /* match magic word */ ++ if (!(dhcph->flags & htons(BROADCAST_FLAG))) { /* if not broadcast */ ++ register int sum = 0; ++ ++ printk("DHCP: change flag of DHCP request to broadcast.\n"); ++ ++ #if 1 ++ /* or BROADCAST flag */ ++ dhcph->flags |= htons(BROADCAST_FLAG); ++ /* recalculate checksum */ ++ sum = ~(udph->check) & 0xffff; ++ sum += dhcph->flags; ++ while (sum >> 16) ++ sum = (sum & 0xffff) + (sum >> 16); ++ udph->check = ~sum; ++ #endif ++ } ++ } ++ } ++ } ++ } ++ } ++} ++ ++ ++void *scdb_findEntry(struct rwnx_vif *vif, unsigned char *macAddr, ++ unsigned char *ipAddr) ++{ ++ printk("%s()\n",__func__); ++ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; ++ struct nat25_network_db_entry *db; ++ int hash; ++ /* _irqL irqL; */ ++ /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ ++ ++ __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr); ++ hash = __nat25_network_hash(networkAddr); ++ db = vif->nethash[hash]; ++ while (db != NULL) { ++ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++ return (void *)db; ++ } ++ ++ db = db->next_hash; ++ } ++ ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++ return NULL; ++} ++ ++#endif /* CONFIG_BR_SUPPORT */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h +new file mode 100644 +index 000000000000..71ebeb293b8e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h +@@ -0,0 +1,73 @@ ++/****************************************************************************** ++ * ++ * Copyright(c) 2007 - 2017 Realtek Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * 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 _AIC_BR_EXT_H_ ++#define _AIC_BR_EXT_H_ ++ ++#define CL_IPV6_PASS 1 ++#define MACADDRLEN 6 ++#define WLAN_ETHHDR_LEN 14 ++ ++#define NAT25_HASH_BITS 4 ++#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS) ++#define NAT25_AGEING_TIME 300 ++ ++#define NDEV_FMT "%s" ++#define NDEV_ARG(ndev) ndev->name ++#define ADPT_FMT "%s" ++//#define ADPT_ARG(adapter) (adapter->pnetdev ? adapter->pnetdev->name : NULL) ++#define FUNC_NDEV_FMT "%s(%s)" ++#define FUNC_NDEV_ARG(ndev) __func__, ndev->name ++#define FUNC_ADPT_FMT "%s(%s)" ++//#define FUNC_ADPT_ARG(adapter) __func__, (adapter->pnetdev ? adapter->pnetdev->name : NULL) ++#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" ++#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5] ++ ++ ++#ifdef CL_IPV6_PASS ++ #define MAX_NETWORK_ADDR_LEN 17 ++#else ++ #define MAX_NETWORK_ADDR_LEN 11 ++#endif ++ ++struct nat25_network_db_entry { ++ struct nat25_network_db_entry *next_hash; ++ struct nat25_network_db_entry **pprev_hash; ++ atomic_t use_count; ++ unsigned char macAddr[6]; ++ unsigned long ageing_timer; ++ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; ++}; ++ ++enum NAT25_METHOD { ++ NAT25_MIN, ++ NAT25_CHECK, ++ NAT25_INSERT, ++ NAT25_LOOKUP, ++ NAT25_PARSE, ++ NAT25_MAX ++}; ++ ++struct br_ext_info { ++ unsigned int nat25_disable; ++ unsigned int macclone_enable; ++ unsigned int dhcp_bcst_disable; ++ int addPPPoETag; /* 1: Add PPPoE relay-SID, 0: disable */ ++ unsigned char nat25_dmzMac[MACADDRLEN]; ++ unsigned int nat25sc_disable; ++}; ++ ++void nat25_db_cleanup(struct rwnx_vif *vif); ++ ++#endif /* _AIC_BR_EXT_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h +new file mode 100644 +index 000000000000..d3d020533a84 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h +@@ -0,0 +1,64 @@ ++#ifndef __AIC_BSP_EXPORT_H ++#define __AIC_BSP_EXPORT_H ++ ++enum aicbsp_subsys { ++ AIC_BLUETOOTH, ++ AIC_WIFI, ++}; ++ ++enum aicbsp_pwr_state { ++ AIC_PWR_OFF, ++ AIC_PWR_ON, ++}; ++ ++struct aicbsp_feature_t { ++ int hwinfo; ++ uint32_t sdio_clock; ++ uint8_t sdio_phase; ++ int fwlog_en; ++ uint8_t irqf; ++}; ++ ++enum skb_buff_id { ++ AIC_RESV_MEM_TXDATA, ++}; ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++typedef struct { ++ uint32_t bit_mask[3]; ++ uint32_t reserved; ++ uint32_t dpd_high[96]; ++ uint32_t dpd_11b[96]; ++ uint32_t dpd_low[96]; ++ uint32_t idac_11b[48]; ++ uint32_t idac_high[48]; ++ uint32_t idac_low[48]; ++ uint32_t loft_res[18]; ++ uint32_t rx_iqim_res[16]; ++} rf_misc_ram_t; ++ ++typedef struct { ++ uint32_t bit_mask[4]; ++ uint32_t dpd_high[96]; ++ uint32_t loft_res[18]; ++} rf_misc_ram_lite_t; ++ ++#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) ++#define DPD_RESULT_SIZE_8800DC sizeof(rf_misc_ram_lite_t) ++#endif ++ ++#ifdef CONFIG_DPD ++extern rf_misc_ram_lite_t dpd_res; ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++extern rf_misc_ram_lite_t loft_res_local; ++#endif ++ ++int aicbsp_set_subsys(int, int); ++int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path); ++bool aicbsp_get_load_fw_in_fdrv(void); ++struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id); ++void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c +new file mode 100644 +index 000000000000..ba26a37ef6e7 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c +@@ -0,0 +1,1299 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aic_btsdio.h" ++#include "rwnx_msg_tx.h" ++ ++#if CONFIG_BLUEDROID == 1 ++static spinlock_t queue_lock; ++static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how) ++{ ++ struct sk_buff *skb; ++ ++ if ((skb = alloc_skb(len + BT_SKB_RESERVE, how))) { ++ skb_reserve(skb, BT_SKB_RESERVE); ++ bt_cb(skb)->incoming = 0; ++ } ++ return skb; ++} ++ ++static spinlock_t queue_lock; ++static spinlock_t dlfw_lock; ++static volatile uint16_t dlfw_dis_state = 0; ++ ++/* Global parameters for bt usb char driver */ ++#define BT_CHAR_DEVICE_NAME "aicbt_dev" ++struct mutex btchr_mutex; ++static struct sk_buff_head btchr_readq; ++static wait_queue_head_t btchr_read_wait; ++static wait_queue_head_t bt_dlfw_wait; ++static int bt_char_dev_registered; ++static dev_t bt_devid; /* bt char device number */ ++static struct cdev bt_char_dev; /* bt character device structure */ ++static struct class *bt_char_class; /* device class for usb char driver */ ++static int bt_reset = 0; ++//int aic_queue_cnt(void); ++/* HCI device & lock */ ++DEFINE_RWLOCK(hci_dev_lock); ++ ++struct hci_dev *ghdev = NULL; ++ ++static struct sk_buff *aic_skb_queue[QUEUE_SIZE]; ++static int aic_skb_queue_front = 0; ++static int aic_skb_queue_rear = 0; ++ ++static inline int check_set_dlfw_state_value(uint16_t change_value) ++{ ++ spin_lock(&dlfw_lock); ++ if(!dlfw_dis_state) { ++ dlfw_dis_state = change_value; ++ } ++ spin_unlock(&dlfw_lock); ++ return dlfw_dis_state; ++} ++ ++static inline void set_dlfw_state_value(uint16_t change_value) ++{ ++ spin_lock(&dlfw_lock); ++ dlfw_dis_state = change_value; ++ spin_unlock(&dlfw_lock); ++} ++ ++static void print_acl(struct sk_buff *skb, int direction) ++{ ++#if PRINT_ACL_DATA ++ //uint wlength = skb->len; ++ u16 *handle = (u16 *)(skb->data); ++ u16 len = *(handle+1); ++ //u8 *acl_data = (u8 *)(skb->data); ++ ++ AICBT_INFO("aic %s: direction %d, handle %04x, len %d", ++ __func__, direction, *handle, len); ++#endif ++} ++ ++static void print_sco(struct sk_buff *skb, int direction) ++{ ++#if PRINT_SCO_DATA ++ uint wlength = skb->len; ++ u16 *handle = (u16 *)(skb->data); ++ u8 len = *(u8 *)(handle+1); ++ //u8 *sco_data =(u8 *)(skb->data); ++ ++ AICBT_INFO("aic %s: direction %d, handle %04x, len %d,wlength %d", ++ __func__, direction, *handle, len,wlength); ++#endif ++} ++ ++int bt_bypass_event(struct sk_buff *skb) ++{ ++ int ret = 0; ++ u8 *opcode = (u8*)(skb->data); ++ //u8 len = *(opcode+1); ++ //printk("bypass_event %x,%x,%x,%x,%x\r\n",opcode[0],opcode[1],opcode[2],opcode[3],opcode[4]); ++ ++ switch(opcode[1]) { ++ case HCI_EV_LE_Meta: ++ { ++ u8 subevent_code; ++ subevent_code = opcode[3]; ++ switch(subevent_code){ ++ case HCI_BLE_ADV_PKT_RPT_EVT: ++ case HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT: ++ { ++ if(aic_queue_cnt() > (QUEUE_SIZE-490)){ ++ printk("more adv report bypass\r\n"); ++ ret = 1; ++ } ++ } ++ break; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++ ++int bt_sdio_recv(u8 *data,u32 data_len) ++{ ++ struct sk_buff *skb; ++ int type= data[0]; ++ struct hci_dev *hdev; ++ u32 len = data_len; ++ //int ret=0; ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICWFDBG(LOGERROR,"%s: Failed to get hci dev[NULL]", __func__); ++ return -ENODEV; ++ } ++ ++ skb = alloc_skb(len,GFP_ATOMIC); ++ if(!skb){ ++ AICWFDBG(LOGERROR, "alloc skb fail %s \n",__func__); ++ } ++ memcpy(skb_put(skb,len) ,data, len); ++ if(bt_bypass_event(skb)){ ++ kfree_skb(skb); ++ return 0; ++ } ++ //bt_data_dump("bt_skb", skb, skb->len); ++ ++ if(aic_enqueue(skb)<0){ ++ kfree_skb(skb); ++ }else{ ++ //printk("wake up \n"); ++ wake_up_interruptible(&btchr_read_wait); ++ } ++ return 0; ++} ++ ++ ++static int bypass_event(struct sk_buff *skb) ++{ ++ int ret = 0; ++ u8 *opcode = (u8*)(skb->data); ++ //u8 len = *(opcode+1); ++ //printk("bypass_event %x,%x,%x,%x,%x\r\n",opcode[0],opcode[1],opcode[2],opcode[3],opcode[4]); ++ ++ switch(*opcode) { ++#ifdef CONFIG_SUPPORT_VENDOR_APCF ++ case HCI_EV_CMD_COMPLETE: ++ { ++ u16 sub_opcpde; ++ sub_opcpde = ((u16)opcode[3]|(u16)(opcode[4])<<8); ++ if(sub_opcpde == 0xfd57){ ++ if(vendor_apcf_sent_done){ ++ vendor_apcf_sent_done--; ++ printk("apcf bypass\r\n"); ++ ret = 1; ++ } ++ } ++ } ++ break; ++#endif//CONFIG_SUPPORT_VENDOR_APCF ++ case HCI_EV_LE_Meta: ++ { ++ u8 subevent_code; ++ subevent_code = opcode[2]; ++ switch(subevent_code){ ++ case HCI_BLE_ADV_PKT_RPT_EVT: ++ case HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT: ++ { ++ if(aic_queue_cnt() > (QUEUE_SIZE-100)){ ++ printk("more adv report bypass\r\n"); ++ ret = 1; ++ } ++ } ++ break; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++static void print_event(struct sk_buff *skb) ++{ ++#if PRINT_CMD_EVENT ++ //uint wlength = skb->len; ++ //uint icount = 0; ++ u8 *opcode = (u8*)(skb->data); ++ //u8 len = *(opcode+1); ++ ++ printk("aic %s ", __func__); ++ switch (*opcode) { ++ case HCI_EV_INQUIRY_COMPLETE: ++ printk("HCI_EV_INQUIRY_COMPLETE"); ++ break; ++ case HCI_EV_INQUIRY_RESULT: ++ printk("HCI_EV_INQUIRY_RESULT"); ++ break; ++ case HCI_EV_CONN_COMPLETE: ++ printk("HCI_EV_CONN_COMPLETE"); ++ break; ++ case HCI_EV_CONN_REQUEST: ++ printk("HCI_EV_CONN_REQUEST"); ++ break; ++ case HCI_EV_DISCONN_COMPLETE: ++ printk("HCI_EV_DISCONN_COMPLETE"); ++ break; ++ case HCI_EV_AUTH_COMPLETE: ++ printk("HCI_EV_AUTH_COMPLETE"); ++ break; ++ case HCI_EV_REMOTE_NAME: ++ printk("HCI_EV_REMOTE_NAME"); ++ break; ++ case HCI_EV_ENCRYPT_CHANGE: ++ printk("HCI_EV_ENCRYPT_CHANGE"); ++ break; ++ case HCI_EV_CHANGE_LINK_KEY_COMPLETE: ++ printk("HCI_EV_CHANGE_LINK_KEY_COMPLETE"); ++ break; ++ case HCI_EV_REMOTE_FEATURES: ++ printk("HCI_EV_REMOTE_FEATURES"); ++ break; ++ case HCI_EV_REMOTE_VERSION: ++ printk("HCI_EV_REMOTE_VERSION"); ++ break; ++ case HCI_EV_QOS_SETUP_COMPLETE: ++ printk("HCI_EV_QOS_SETUP_COMPLETE"); ++ break; ++ case HCI_EV_CMD_COMPLETE: ++ printk("HCI_EV_CMD_COMPLETE"); ++ break; ++ case HCI_EV_CMD_STATUS: ++ printk("HCI_EV_CMD_STATUS"); ++ break; ++ case HCI_EV_ROLE_CHANGE: ++ printk("HCI_EV_ROLE_CHANGE"); ++ break; ++ case HCI_EV_NUM_COMP_PKTS: ++ printk("HCI_EV_NUM_COMP_PKTS"); ++ break; ++ case HCI_EV_MODE_CHANGE: ++ printk("HCI_EV_MODE_CHANGE"); ++ break; ++ case HCI_EV_PIN_CODE_REQ: ++ printk("HCI_EV_PIN_CODE_REQ"); ++ break; ++ case HCI_EV_LINK_KEY_REQ: ++ printk("HCI_EV_LINK_KEY_REQ"); ++ break; ++ case HCI_EV_LINK_KEY_NOTIFY: ++ printk("HCI_EV_LINK_KEY_NOTIFY"); ++ break; ++ case HCI_EV_CLOCK_OFFSET: ++ printk("HCI_EV_CLOCK_OFFSET"); ++ break; ++ case HCI_EV_PKT_TYPE_CHANGE: ++ printk("HCI_EV_PKT_TYPE_CHANGE"); ++ break; ++ case HCI_EV_PSCAN_REP_MODE: ++ printk("HCI_EV_PSCAN_REP_MODE"); ++ break; ++ case HCI_EV_INQUIRY_RESULT_WITH_RSSI: ++ printk("HCI_EV_INQUIRY_RESULT_WITH_RSSI"); ++ break; ++ case HCI_EV_REMOTE_EXT_FEATURES: ++ printk("HCI_EV_REMOTE_EXT_FEATURES"); ++ break; ++ case HCI_EV_SYNC_CONN_COMPLETE: ++ printk("HCI_EV_SYNC_CONN_COMPLETE"); ++ break; ++ case HCI_EV_SYNC_CONN_CHANGED: ++ printk("HCI_EV_SYNC_CONN_CHANGED"); ++ break; ++ case HCI_EV_SNIFF_SUBRATE: ++ printk("HCI_EV_SNIFF_SUBRATE"); ++ break; ++ case HCI_EV_EXTENDED_INQUIRY_RESULT: ++ printk("HCI_EV_EXTENDED_INQUIRY_RESULT"); ++ break; ++ case HCI_EV_IO_CAPA_REQUEST: ++ printk("HCI_EV_IO_CAPA_REQUEST"); ++ break; ++ case HCI_EV_SIMPLE_PAIR_COMPLETE: ++ printk("HCI_EV_SIMPLE_PAIR_COMPLETE"); ++ break; ++ case HCI_EV_REMOTE_HOST_FEATURES: ++ printk("HCI_EV_REMOTE_HOST_FEATURES"); ++ break; ++ default: ++ printk("unknow event"); ++ break; ++ } ++ printk("\n"); ++#if 0 ++ printk("%02x,len:%d,", *opcode,len); ++ for (icount = 2; (icount < wlength) && (icount < 24); icount++) ++ printk("%02x ", *(opcode+icount)); ++ printk("\n"); ++#endif ++#endif ++} ++ ++ ++static inline ssize_t sdio_put_user(struct sk_buff *skb, ++ char __user *buf, int count) ++{ ++ char __user *ptr = buf; ++ int len = min_t(unsigned int, skb->len, count); ++ ++ if (copy_to_user(ptr, skb->data, len)) ++ return -EFAULT; ++ ++ return len; ++} ++ ++int aic_enqueue(struct sk_buff *skb) ++{ ++ unsigned long flags = 0; ++ int ret = 0; ++ spin_lock_irqsave(&queue_lock, flags); ++ if (aic_skb_queue_front == (aic_skb_queue_rear + 1) % QUEUE_SIZE) { ++ /* ++ * If queue is full, current solution is to drop ++ * the following entries. ++ */ ++ AICBT_WARN("%s: Queue is full, entry will be dropped", __func__); ++ ret = -1; ++ } else { ++ aic_skb_queue[aic_skb_queue_rear] = skb; ++ ++ aic_skb_queue_rear++; ++ aic_skb_queue_rear %= QUEUE_SIZE; ++ ++ } ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return ret; ++} ++ ++static struct sk_buff *aic_dequeue_try(unsigned int deq_len) ++{ ++ struct sk_buff *skb; ++ struct sk_buff *skb_copy; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&queue_lock, flags); ++ if (aic_skb_queue_front == aic_skb_queue_rear) { ++ AICBT_WARN("%s: Queue is empty", __func__); ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return NULL; ++ } ++ ++ skb = aic_skb_queue[aic_skb_queue_front]; ++ if (deq_len >= skb->len) { ++ ++ aic_skb_queue_front++; ++ aic_skb_queue_front %= QUEUE_SIZE; ++ ++ /* ++ * Return skb addr to be dequeued, and the caller ++ * should free the skb eventually. ++ */ ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return skb; ++ } else { ++ skb_copy = pskb_copy(skb, GFP_ATOMIC); ++ skb_pull(skb, deq_len); ++ /* Return its copy to be freed */ ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return skb_copy; ++ } ++} ++ ++static inline int is_queue_empty(void) ++{ ++ return (aic_skb_queue_front == aic_skb_queue_rear) ? 1 : 0; ++} ++ ++void aic_clear_queue(void) ++{ ++ struct sk_buff *skb; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&queue_lock, flags); ++ while(!is_queue_empty()) { ++ skb = aic_skb_queue[aic_skb_queue_front]; ++ aic_skb_queue[aic_skb_queue_front] = NULL; ++ aic_skb_queue_front++; ++ aic_skb_queue_front %= QUEUE_SIZE; ++ if (skb) { ++ kfree_skb(skb); ++ } ++ } ++ spin_unlock_irqrestore(&queue_lock, flags); ++} ++ ++int aic_queue_cnt(void) ++{ ++ int ret_cnt = 0; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&queue_lock, flags); ++ if(is_queue_empty()) { ++ ret_cnt = 0; ++ }else{ ++ if(aic_skb_queue_rear > aic_skb_queue_front){ ++ ret_cnt = aic_skb_queue_rear-aic_skb_queue_front; ++ }else{ ++ ret_cnt = aic_skb_queue_rear+QUEUE_SIZE-aic_skb_queue_front; ++ } ++ } ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return ret_cnt; ++} ++ ++/* ++ * AicSemi - Integrate from hci_core.c ++ */ ++ ++/* Get HCI device by index. ++ * Device is held on return. */ ++struct hci_dev *hci_dev_get(int index) ++{ ++ if (index != 0) ++ return NULL; ++ ++ return ghdev; ++} ++ ++/* ---- HCI ioctl helpers ---- */ ++static int hci_dev_open(__u16 dev) ++{ ++ struct hci_dev *hdev; ++ int ret = 0; ++ ++ AICBT_DBG("%s: dev %d", __func__, dev); ++ ++ hdev = hci_dev_get(dev); ++ if (!hdev) { ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ return -ENODEV; ++ } ++ ++ /*if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) { ++ ret = -ENODEV; ++ goto done; ++ } ++ ++ if (test_bit(HCI_UP, &hdev->flags)) { ++ ret = -EALREADY; ++ goto done; ++ }*/ ++ ++done: ++ return ret; ++} ++ ++static int hci_dev_do_close(struct hci_dev *hdev) ++{ ++ //if (hdev->flush) ++ // hdev->flush(hdev); ++ /* After this point our queues are empty ++ * and no tasks are scheduled. */ ++ //hdev->close(hdev); ++ /* Clear flags */ ++ hdev->flags = 0; ++ return 0; ++} ++ ++static int hci_dev_close(__u16 dev) ++{ ++ struct hci_dev *hdev; ++ int err; ++ hdev = hci_dev_get(dev); ++ if (!hdev) { ++ AICBT_ERR("%s: failed to get hci dev[Null]", __func__); ++ return -ENODEV; ++ } ++ ++ err = hci_dev_do_close(hdev); ++ ++ return err; ++} ++ ++#if CONFIG_BLUEDROID ++static struct hci_dev *hci_alloc_dev(void) ++{ ++ struct hci_dev *hdev; ++ ++ hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL); ++ if (!hdev) ++ return NULL; ++ ++ return hdev; ++} ++ ++/* Free HCI device */ ++static void hci_free_dev(struct hci_dev *hdev) ++{ ++ kfree(hdev); ++} ++ ++/* Register HCI device */ ++static int hci_register_dev(struct hci_dev *hdev) ++{ ++ int i, id; ++ ++ AICBT_DBG("%s: %p name %s bus %d", __func__, hdev, hdev->name, hdev->bus); ++ /* Do not allow HCI_AMP devices to register at index 0, ++ * so the index can be used as the AMP controller ID. ++ */ ++ id = (hdev->dev_type == HCI_BREDR) ? 0 : 1; ++ ++ write_lock(&hci_dev_lock); ++ ++ sprintf(hdev->name, "hci%d", id); ++ hdev->id = id; ++ hdev->flags = 0; ++ hdev->dev_flags = 0; ++ mutex_init(&hdev->lock); ++ ++ AICBT_DBG("%s: id %d, name %s", __func__, hdev->id, hdev->name); ++ ++ ++ for (i = 0; i < NUM_REASSEMBLY; i++) ++ hdev->reassembly[i] = NULL; ++ ++ memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); ++ atomic_set(&hdev->promisc, 0); ++ ++ if (ghdev) { ++ write_unlock(&hci_dev_lock); ++ AICBT_ERR("%s: Hci device has been registered already", __func__); ++ return -1; ++ } else ++ ghdev = hdev; ++ ++ write_unlock(&hci_dev_lock); ++ ++ return id; ++} ++ ++/* Unregister HCI device */ ++static void hci_unregister_dev(struct hci_dev *hdev) ++{ ++ int i; ++ ++ AICBT_DBG("%s: hdev %p name %s bus %d", __func__, hdev, hdev->name, hdev->bus); ++ set_bit(HCI_UNREGISTER, &hdev->dev_flags); ++ ++ write_lock(&hci_dev_lock); ++ ghdev = NULL; ++ write_unlock(&hci_dev_lock); ++ ++ hci_dev_do_close(hdev); ++ for (i = 0; i < NUM_REASSEMBLY; i++) ++ kfree_skb(hdev->reassembly[i]); ++} ++ ++static void hci_send_to_stack(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ struct sk_buff *aic_skb_copy = NULL; ++ ++ //AICBT_DBG("%s", __func__); ++ ++ if (!hdev) { ++ AICBT_ERR("%s: Frame for unknown HCI device", __func__); ++ return; ++ } ++ ++ if (!test_bit(HCI_RUNNING, &hdev->flags)) { ++ AICBT_ERR("%s: HCI not running", __func__); ++ return; ++ } ++ ++ aic_skb_copy = pskb_copy(skb, GFP_ATOMIC); ++ if (!aic_skb_copy) { ++ AICBT_ERR("%s: Copy skb error", __func__); ++ return; ++ } ++ ++ memcpy(skb_push(aic_skb_copy, 1), &bt_cb(skb)->pkt_type, 1); ++ aic_enqueue(aic_skb_copy); ++ ++ /* Make sure bt char device existing before wakeup read queue */ ++ hdev = hci_dev_get(0); ++ if (hdev) { ++ //AICBT_DBG("%s: Try to wakeup read queue", __func__); ++ AICBT_DBG("%s", __func__); ++ wake_up_interruptible(&btchr_read_wait); ++ } ++ ++ ++ return; ++} ++ ++/* Receive frame from HCI drivers */ ++static int hci_recv_frame(struct sk_buff *skb) ++{ ++ struct hci_dev *hdev = (struct hci_dev *) skb->dev; ++ ++ if (!hdev || ++ (!test_bit(HCI_UP, &hdev->flags) && !test_bit(HCI_INIT, &hdev->flags))) { ++ kfree_skb(skb); ++ return -ENXIO; ++ } ++ ++ /* Incomming skb */ ++ bt_cb(skb)->incoming = 1; ++ ++ /* Time stamp */ ++ __net_timestamp(skb); ++ ++ if (atomic_read(&hdev->promisc)) { ++#ifdef CONFIG_SCO_OVER_HCI ++ if(bt_cb(skb)->pkt_type == HCI_SCODATA_PKT){ ++ hci_send_to_alsa_ringbuffer(hdev, skb); ++ }else{ ++ if(bt_cb(skb)->pkt_type == HCI_EVENT_PKT){ ++ if(bypass_event(skb)){ ++ kfree_skb(skb); ++ return 0; ++ } ++ } ++ hci_send_to_stack(hdev, skb); ++ } ++#else ++ if(bt_cb(skb)->pkt_type == HCI_EVENT_PKT){ ++ if(bypass_event(skb)){ ++ kfree_skb(skb); ++ return 0; ++ } ++ } ++ /* Send copy to the sockets */ ++ hci_send_to_stack(hdev, skb); ++#endif ++ ++ } ++ ++ kfree_skb(skb); ++ return 0; ++} ++ ++ ++ ++static int hci_reassembly(struct hci_dev *hdev, int type, void *data, ++ int count, __u8 index) ++{ ++ int len = 0; ++ int hlen = 0; ++ int remain = count; ++ struct sk_buff *skb; ++ struct bt_skb_cb *scb; ++ ++ //AICBT_DBG("%s", __func__); ++ ++ if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) || ++ index >= NUM_REASSEMBLY) ++ return -EILSEQ; ++ ++ skb = hdev->reassembly[index]; ++ ++ if (!skb) { ++ switch (type) { ++ case HCI_ACLDATA_PKT: ++ len = HCI_MAX_FRAME_SIZE; ++ hlen = HCI_ACL_HDR_SIZE; ++ break; ++ case HCI_EVENT_PKT: ++ len = HCI_MAX_EVENT_SIZE; ++ hlen = HCI_EVENT_HDR_SIZE; ++ break; ++ case HCI_SCODATA_PKT: ++ len = HCI_MAX_SCO_SIZE; ++ hlen = HCI_SCO_HDR_SIZE; ++ break; ++ } ++ ++ skb = bt_skb_alloc(len, GFP_ATOMIC); ++ if (!skb) ++ return -ENOMEM; ++ ++ scb = (void *) skb->cb; ++ scb->expect = hlen; ++ scb->pkt_type = type; ++ ++ skb->dev = (void *) hdev; ++ hdev->reassembly[index] = skb; ++ } ++ ++ while (count) { ++ scb = (void *) skb->cb; ++ len = min_t(uint, scb->expect, count); ++ ++ memcpy(skb_put(skb, len), data, len); ++ ++ count -= len; ++ data += len; ++ scb->expect -= len; ++ remain = count; ++ ++ switch (type) { ++ case HCI_EVENT_PKT: ++ if (skb->len == HCI_EVENT_HDR_SIZE) { ++ struct hci_event_hdr *h = hci_event_hdr(skb); ++ scb->expect = h->plen; ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ hdev->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ ++ case HCI_ACLDATA_PKT: ++ if (skb->len == HCI_ACL_HDR_SIZE) { ++ struct hci_acl_hdr *h = hci_acl_hdr(skb); ++ scb->expect = __le16_to_cpu(h->dlen); ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ hdev->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ ++ case HCI_SCODATA_PKT: ++ if (skb->len == HCI_SCO_HDR_SIZE) { ++ struct hci_sco_hdr *h = hci_sco_hdr(skb); ++ scb->expect = h->dlen; ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ hdev->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ } ++ ++ if (scb->expect == 0) { ++ /* Complete frame */ ++ if(HCI_ACLDATA_PKT == type) ++ print_acl(skb,0); ++ if(HCI_SCODATA_PKT == type) ++ print_sco(skb,0); ++ if(HCI_EVENT_PKT == type) ++ print_event(skb); ++ ++ bt_cb(skb)->pkt_type = type; ++ hci_recv_frame(skb); ++ ++ hdev->reassembly[index] = NULL; ++ return remain; ++ } ++ } ++ ++ return remain; ++} ++ ++int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) ++{ ++ int rem = 0; ++ ++ if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ++ return -EILSEQ; ++ ++ while (count) { ++ rem = hci_reassembly(hdev, type, data, count, type - 1); ++ if (rem < 0) ++ return rem; ++ ++ data += (count - rem); ++ count = rem; ++ } ++ ++ return rem; ++} ++#endif //CONFIG_BLUEDROID ++ ++static int btchr_open(struct inode *inode_p, struct file *file_p) ++{ ++ struct btusb_data *data; ++ struct hci_dev *hdev; ++ ++ AICBT_DBG("%s: BT sdio char device is opening", __func__); ++ /* Not open unless wanna tracing log */ ++ /* trace_printk("%s: open....\n", __func__); */ ++ ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_DBG("%s: Failed to get hci dev[NULL]", __func__); ++ return -ENODEV; ++ } ++ data = GET_DRV_DATA(hdev); ++ ++ atomic_inc(&hdev->promisc); ++ /* ++ * As bt device is not re-opened when hotplugged out, we cannot ++ * trust on file's private data(may be null) when other file ops ++ * are invoked. ++ */ ++ file_p->private_data = data; ++ ++ mutex_lock(&btchr_mutex); ++ hci_dev_open(0); ++ mutex_unlock(&btchr_mutex); ++ ++ aic_clear_queue(); ++ return nonseekable_open(inode_p, file_p); ++} ++ ++static int btchr_close(struct inode *inode_p, struct file *file_p) ++{ ++ struct btusb_data *data; ++ struct hci_dev *hdev; ++ ++ AICBT_INFO("%s: BT sdio char device is closing", __func__); ++ /* Not open unless wanna tracing log */ ++ /* trace_printk("%s: close....\n", __func__); */ ++ ++ data = file_p->private_data; ++ file_p->private_data = NULL; ++ ++#if CONFIG_BLUEDROID ++ /* ++ * If the upper layer closes bt char interfaces, no reset ++ * action required even bt device hotplugged out. ++ */ ++ bt_reset = 0; ++#endif ++ ++ hdev = hci_dev_get(0); ++ if (hdev) { ++ atomic_set(&hdev->promisc, 0); ++ mutex_lock(&btchr_mutex); ++ hci_dev_close(0); ++ mutex_unlock(&btchr_mutex); ++ } ++ ++ return 0; ++} ++ ++void bt_data_dump(char* tag, void* data, unsigned long len){ ++ unsigned long i = 0; ++ uint8_t* data_ = (uint8_t* )data; ++ ++ printk("%s %s len:(%lu)\r\n", __func__, tag, len); ++ ++ for (i = 0; i < len; i += 16){ ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", ++ data_[0 + i], ++ data_[1 + i], ++ data_[2 + i], ++ data_[3 + i], ++ data_[4 + i], ++ data_[5 + i], ++ data_[6 + i], ++ data_[7 + i], ++ data_[8 + i], ++ data_[9 + i], ++ data_[10 + i], ++ data_[11 + i], ++ data_[12 + i], ++ data_[13 + i], ++ data_[14 + i], ++ data_[15 + i]); ++ } ++ ++} ++ ++static ssize_t btchr_read(struct file *file_p, ++ char __user *buf_p, ++ size_t count, ++ loff_t *pos_p) ++{ ++ struct hci_dev *hdev; ++ struct sk_buff *skb; ++ ssize_t ret = 0; ++ ++ while (count) { ++#if 1 ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ /* ++ * Note: Only when BT device hotplugged out, we wil get ++ * into such situation. In order to keep the upper layer ++ * stack alive (blocking the read), we should never return ++ * EFAULT or break the loop. ++ */ ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ } ++#endif ++ ret = wait_event_interruptible(btchr_read_wait, !is_queue_empty()); ++ if (ret < 0) { ++ AICBT_ERR("%s: wait event is signaled %d", __func__, (int)ret); ++ break; ++ } ++ ++ skb = aic_dequeue_try(count); ++ //bt_data_dump("btchr_read", skb->data, skb->len); ++ //printk("btchr_read \n"); ++ if (skb) { ++ ret = sdio_put_user(skb, buf_p, count); ++ if (ret < 0) ++ AICBT_ERR("%s: Failed to put data to user space", __func__); ++ kfree_skb(skb); ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++#ifdef CONFIG_SUPPORT_VENDOR_APCF ++void btchr_external_write(char* buff, int len){ ++ struct hci_dev *hdev; ++ struct sk_buff *skb; ++ int i; ++ struct btusb_data *data; ++ ++ AICBT_INFO("%s \r\n", __func__); ++ for(i=0;idev = (void *)hdev; ++ memcpy((__u8 *)skb->data,(__u8 *)buff,len); ++ skb_put(skb, len); ++ bt_cb(skb)->pkt_type = *((__u8 *)skb->data); ++ skb_pull(skb, 1); ++ data->hdev->send(skb); ++} ++ ++EXPORT_SYMBOL(btchr_external_write); ++#endif //CONFIG_SUPPORT_VENDOR_APCF ++ ++//extern struct rwnx_plat *g_rwnx_plat; ++static ssize_t btchr_write(struct file *file_p, ++ const char __user *buf_p, ++ size_t count, ++ loff_t *pos_p) ++{ ++ struct btusb_data *data = file_p->private_data; ++ struct hci_dev *hdev; ++ struct sk_buff *skb; ++ int err=0; ++ ++ AICBT_DBG("%s", __func__); ++ ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_WARN("%s: Failed to get hci dev[Null]", __func__); ++ /* ++ * Note: we bypass the data from the upper layer if bt device ++ * is hotplugged out. Fortunatelly, H4 or H5 HCI stack does ++ * NOT check btchr_write's return value. However, returning ++ * count instead of EFAULT is preferable. ++ */ ++ /* return -EFAULT; */ ++ return count; ++ } ++ ++#if 0 ++ /* Never trust on btusb_data, as bt device may be hotplugged out */ ++ data = GET_DRV_DATA(hdev); ++ if (!data) { ++ AICBT_WARN("%s: Failed to get bt usb driver data[Null]", __func__); ++ return count; ++ } ++#endif ++ ++ if (count > HCI_MAX_FRAME_SIZE) ++ return -EINVAL; ++ ++ skb = bt_skb_alloc(count, GFP_ATOMIC); ++ if (!skb) ++ return -ENOMEM; ++ skb_reserve(skb, -1); // Add this line ++ ++ if (copy_from_user(skb_put(skb, count), buf_p, count)) { ++ AICBT_ERR("%s: Failed to get data from user space", __func__); ++ kfree_skb(skb); ++ return -EFAULT; ++ } ++ ++ skb->dev = (void *)hdev; ++ bt_cb(skb)->pkt_type = *((__u8 *)skb->data); ++ //skb_pull(skb, 1); ++ //data->hdev->send(skb); ++ ++ //bt_data_dump("btwrite", skb->data, skb->len); ++ err = rwnx_sdio_bt_send_req(g_rwnx_plat->sdiodev->rwnx_hw, skb->len, skb); ++ if(err<0){ ++ printk("%s rwnx_sdio_bt_send_req error %d",__func__,err); ++ } ++ ++ kfree_skb(skb); ++ return count; ++} ++ ++static unsigned int btchr_poll(struct file *file_p, poll_table *wait) ++{ ++ struct btusb_data *data = file_p->private_data; ++ struct hci_dev *hdev; ++ ++ //AICBT_DBG("%s: BT sdio char device is polling", __func__); ++ ++ /*if(!bt_char_dev_registered) { ++ AICBT_ERR("%s: char device has not registered!", __func__); ++ return POLLERR | POLLHUP; ++ }*/ ++ //printk("poll wait\n"); ++ poll_wait(file_p, &btchr_read_wait, wait); ++ //printk("poll out\n"); ++ ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ //mdelay(URB_CANCELING_DELAY_MS); ++ return POLLERR | POLLHUP; ++ return POLLOUT | POLLWRNORM; ++ } ++ ++#if 0 ++ /* Never trust on btusb_data, as bt device may be hotplugged out */ ++ data = GET_DRV_DATA(hdev); ++ if (!data) { ++ /* ++ * When bt device is hotplugged out, btusb_data will ++ * be freed in disconnect. ++ */ ++ AICBT_ERR("%s: Failed to get bt sdio driver data[Null]", __func__); ++ mdelay(URB_CANCELING_DELAY_MS); ++ return POLLOUT | POLLWRNORM; ++ } ++#endif ++ ++ if (!is_queue_empty()) ++ return POLLIN | POLLRDNORM; ++ ++ return POLLOUT | POLLWRNORM; ++} ++static long btchr_ioctl(struct file *file_p,unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ struct hci_dev *hdev; ++ struct btusb_data *data; ++ //firmware_info *fw_info; ++ ++ /*if(!bt_char_dev_registered) { ++ return -ENODEV; ++ }*/ ++ ++ printk("%s cmd support %d \n",__func__,cmd); ++ ++#if 1 ++ if(check_set_dlfw_state_value(1) != 1) { ++ AICBT_ERR("%s bt controller is disconnecting!", __func__); ++ return 0; ++ } ++ ++ hdev = hci_dev_get(0); ++ if(!hdev) { ++ AICBT_ERR("%s device is NULL!", __func__); ++ set_dlfw_state_value(0); ++ return 0; ++ } ++ //data = GET_DRV_DATA(hdev); ++ //fw_info = data->fw_info; ++ ++ AICBT_INFO(" btchr_ioctl DOWN_FW_CFG with Cmd:%d",cmd); ++ switch (cmd) { ++ case DOWN_FW_CFG: ++ AICBT_INFO(" btchr_ioctl DOWN_FW_CFG"); ++ /*ret = usb_autopm_get_interface(data->intf); ++ if (ret < 0){ ++ goto failed; ++ }*/ ++ ++ //ret = download_patch(fw_info,1); ++ /*usb_autopm_put_interface(data->intf); ++ if(ret < 0){ ++ AICBT_ERR("%s:Failed in download_patch with ret:%d",__func__,ret); ++ goto failed; ++ } ++ ++ ret = hdev->open(hdev); ++ if(ret < 0){ ++ AICBT_ERR("%s:Failed in hdev->open(hdev):%d",__func__,ret); ++ goto failed; ++ }*/ ++ set_bit(HCI_UP, &hdev->flags); ++ set_dlfw_state_value(0); ++ wake_up_interruptible(&bt_dlfw_wait); ++ return 1; ++ case DWFW_CMPLT: ++ AICBT_INFO(" btchr_ioctl DWFW_CMPLT"); ++#if 1 ++ case SET_ISO_CFG: ++ AICBT_INFO("btchr_ioctl SET_ISO_CFG"); ++ if(copy_from_user(&(hdev->voice_setting), (__u16*)arg, sizeof(__u16))){ ++ AICBT_INFO(" voice settings err"); ++ } ++ //hdev->voice_setting = *(uint16_t*)arg; ++ AICBT_INFO(" voice settings = %d", hdev->voice_setting); ++ //return 1; ++#endif ++ case GET_USB_INFO: ++ //ret = download_patch(fw_info,1); ++ AICBT_INFO(" btchr_ioctl GET_USB_INFO"); ++ /*ret = hdev->open(hdev); ++ if(ret < 0){ ++ AICBT_ERR("%s:Failed in hdev->open(hdev):%d",__func__,ret); ++ //goto done; ++ }*/ ++ set_bit(HCI_UP, &hdev->flags); ++ set_dlfw_state_value(0); ++ wake_up_interruptible(&bt_dlfw_wait); ++ return 1; ++ case RESET_CONTROLLER: ++ AICBT_INFO(" btchr_ioctl RESET_CONTROLLER"); ++ //reset_controller(fw_info); ++ return 1; ++ default: ++ AICBT_ERR("%s:Failed with wrong Cmd:%d",__func__,cmd); ++ goto failed; ++ } ++ failed: ++ set_dlfw_state_value(0); ++ wake_up_interruptible(&bt_dlfw_wait); ++ return ret; ++#endif ++} ++ ++#ifdef CONFIG_PLATFORM_UBUNTU//AIDEN ++typedef u32 compat_uptr_t; ++static inline void __user *compat_ptr(compat_uptr_t uptr) ++{ ++ return (void __user *)(unsigned long)uptr; ++} ++#endif ++ ++#ifdef CONFIG_COMPAT ++static long compat_btchr_ioctl (struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ AICBT_DBG("%s: enter",__func__); ++ return btchr_ioctl(filp, cmd, (unsigned long) compat_ptr(arg)); ++} ++#endif ++static struct file_operations bt_chrdev_ops = { ++ open : btchr_open, ++ release : btchr_close, ++ read : btchr_read, ++ write : btchr_write, ++ poll : btchr_poll, ++ unlocked_ioctl : btchr_ioctl, ++#ifdef CONFIG_COMPAT ++ compat_ioctl : compat_btchr_ioctl, ++#endif ++}; ++ ++int btchr_init() ++{ ++ int res = 0; ++ struct device *dev; ++ ++ AICBT_INFO("Register sdio char device interface for BT driver"); ++ /* ++ * btchr mutex is used to sync between ++ * 1) downloading patch and opening bt char driver ++ * 2) the file operations of bt char driver ++ */ ++ mutex_init(&btchr_mutex); ++ ++ skb_queue_head_init(&btchr_readq); ++ init_waitqueue_head(&btchr_read_wait); ++ init_waitqueue_head(&bt_dlfw_wait); ++ ++ bt_char_class = class_create(THIS_MODULE, BT_CHAR_DEVICE_NAME); ++ if (IS_ERR(bt_char_class)) { ++ AICBT_ERR("Failed to create bt char class"); ++ return PTR_ERR(bt_char_class); ++ } ++ ++ res = alloc_chrdev_region(&bt_devid, 0, 1, BT_CHAR_DEVICE_NAME); ++ if (res < 0) { ++ AICBT_ERR("Failed to allocate bt char device"); ++ goto err_alloc; ++ } ++ ++ dev = device_create(bt_char_class, NULL, bt_devid, NULL, BT_CHAR_DEVICE_NAME); ++ if (IS_ERR(dev)) { ++ AICBT_ERR("Failed to create bt char device"); ++ res = PTR_ERR(dev); ++ goto err_create; ++ } ++ ++ cdev_init(&bt_char_dev, &bt_chrdev_ops); ++ res = cdev_add(&bt_char_dev, bt_devid, 1); ++ if (res < 0) { ++ AICBT_ERR("Failed to add bt char device"); ++ goto err_add; ++ } ++ ++ return 0; ++ ++err_add: ++ device_destroy(bt_char_class, bt_devid); ++err_create: ++ unregister_chrdev_region(bt_devid, 1); ++err_alloc: ++ class_destroy(bt_char_class); ++ return res; ++} ++ ++void btchr_exit(void) ++{ ++ AICBT_INFO("Unregister sdio char device interface for BT driver"); ++ ++ device_destroy(bt_char_class, bt_devid); ++ cdev_del(&bt_char_dev); ++ unregister_chrdev_region(bt_devid, 1); ++ class_destroy(bt_char_class); ++ ++ return; ++} ++ ++int hdev_init(void) ++{ ++ struct hci_dev *hdev; ++ int err=0; ++ hdev = hci_alloc_dev(); ++ ++ err = hci_register_dev(hdev); ++ if (err < 0) { ++ hci_free_dev(hdev); ++ hdev = NULL; ++ return err; ++ } ++ ++ spin_lock_init(&queue_lock); ++ ++ return 0; ++} ++ ++void hdev_exit(void) ++{ ++ struct hci_dev *hdev; ++ hdev = ghdev; ++ hci_unregister_dev(hdev); ++ hci_free_dev(hdev); ++} ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h +new file mode 100644 +index 000000000000..153ba49d7c55 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h +@@ -0,0 +1,554 @@ ++#ifndef _AICWF_SDIO_BT_H_ ++#define _AICWF_SDIO_BT_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++ ++#ifdef CONFIG_PLATFORM_UBUNTU ++#define CONFIG_BLUEDROID 0 /* bleuz 0, bluedroid 1 */ ++#else ++#define CONFIG_BLUEDROID 1 /* bleuz 0, bluedroid 1 */ ++#endif ++/* #define HCI_VERSION_CODE KERNEL_VERSION(3, 14, 41) */ ++#define HCI_VERSION_CODE LINUX_VERSION_CODE ++ ++ ++#define PRINT_CMD_EVENT 1 ++#define PRINT_ACL_DATA 1 ++#define PRINT_SCO_DATA 1 ++ ++#define AICBT_DBG_FLAG 1 ++ ++#if AICBT_DBG_FLAG ++#define AICBT_DBG(fmt, arg...) printk( "aic_btsdio: " fmt "\n" , ## arg) ++#else ++#define AICBT_DBG(fmt, arg...) ++#endif ++ ++#define AICBT_INFO(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) ++#define AICBT_WARN(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) ++#define AICBT_ERR(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 0) ++#define GET_DRV_DATA(x) hci_get_drvdata(x) ++#else ++#define GET_DRV_DATA(x) x->driver_data ++#endif ++ ++#if CONFIG_BLUEDROID ++struct btusb_data { ++ struct hci_dev *hdev; ++ //struct usb_device *udev; ++ //struct usb_interface *intf; ++ //struct usb_interface *isoc; ++ ++ spinlock_t lock; ++ ++ unsigned long flags; ++ ++ struct work_struct work; ++ struct work_struct waker; ++ ++ /*struct usb_anchor tx_anchor; ++ struct usb_anchor intr_anchor; ++ struct usb_anchor bulk_anchor; ++ struct usb_anchor isoc_anchor; ++ struct usb_anchor deferred;*/ ++ int tx_in_flight; ++ spinlock_t txlock; ++ ++#if (CONFIG_BLUEDROID == 0) ++#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) ++ spinlock_t rxlock; ++ struct sk_buff *evt_skb; ++ struct sk_buff *acl_skb; ++ struct sk_buff *sco_skb; ++#endif ++#endif ++ ++ /*struct usb_endpoint_descriptor *intr_ep; ++ struct usb_endpoint_descriptor *bulk_tx_ep; ++ struct usb_endpoint_descriptor *bulk_rx_ep; ++ struct usb_endpoint_descriptor *isoc_tx_ep; ++ struct usb_endpoint_descriptor *isoc_rx_ep;*/ ++ ++ __u8 cmdreq_type; ++ ++ unsigned int sco_num; ++ int isoc_altsetting; ++ int suspend_count; ++ uint16_t sco_handle; ++ ++#if (CONFIG_BLUEDROID == 0) ++#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) ++ int (*recv_bulk) (struct btusb_data * data, void *buffer, int count); ++#endif ++#endif ++ ++//#ifdef CONFIG_HAS_EARLYSUSPEND ++#if 0 ++ struct early_suspend early_suspend; ++#else ++ struct notifier_block pm_notifier; ++ struct notifier_block reboot_notifier; ++#endif ++ //firmware_info *fw_info; ++ ++#ifdef CONFIG_SCO_OVER_HCI ++ AIC_sco_card_t *pSCOSnd; ++#endif ++}; ++ ++ ++ ++#define QUEUE_SIZE 500 ++ ++/*************************************** ++** AicSemi - Integrate from bluetooth.h ** ++*****************************************/ ++/* Reserv for core and drivers use */ ++#define BT_SKB_RESERVE 8 ++ ++/* BD Address */ ++typedef struct { ++ __u8 b[6]; ++} __packed bdaddr_t; ++ ++/* Skb helpers */ ++struct bt_skb_cb { ++ __u8 pkt_type; ++ __u8 incoming; ++ __u16 expect; ++ __u16 tx_seq; ++ __u8 retries; ++ __u8 sar; ++ __u8 force_active; ++}; ++ ++#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) ++ ++ ++/*********************************** ++** AicSemi - Integrate from hci.h ** ++***********************************/ ++#define HCI_MAX_ACL_SIZE 1024 ++#define HCI_MAX_SCO_SIZE 255 ++#define HCI_MAX_EVENT_SIZE 260 ++#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) ++ ++/* 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 ++ ++/* HCI controller types */ ++#define HCI_BREDR 0x00 ++#define HCI_AMP 0x01 ++ ++/* HCI device flags */ ++enum { ++ HCI_UP, ++ HCI_INIT, ++ HCI_RUNNING, ++ ++ HCI_PSCAN, ++ HCI_ISCAN, ++ HCI_AUTH, ++ HCI_ENCRYPT, ++ HCI_INQUIRY, ++ ++ HCI_RAW, ++ ++ HCI_RESET, ++}; ++ ++/* ++ * BR/EDR and/or LE controller flags: the flags defined here should represent ++ * states from the controller. ++ */ ++enum { ++ HCI_SETUP, ++ HCI_AUTO_OFF, ++ HCI_MGMT, ++ HCI_PAIRABLE, ++ HCI_SERVICE_CACHE, ++ HCI_LINK_KEYS, ++ HCI_DEBUG_KEYS, ++ HCI_UNREGISTER, ++ ++ HCI_LE_SCAN, ++ HCI_SSP_ENABLED, ++ HCI_HS_ENABLED, ++ HCI_LE_ENABLED, ++ HCI_CONNECTABLE, ++ HCI_DISCOVERABLE, ++ HCI_LINK_SECURITY, ++ HCI_PENDING_CLASS, ++}; ++ ++/* HCI data types */ ++#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 ++ ++#define HCI_MAX_NAME_LENGTH 248 ++#define HCI_MAX_EIR_LENGTH 240 ++ ++#define HCI_OP_READ_LOCAL_VERSION 0x1001 ++struct hci_rp_read_local_version { ++ __u8 status; ++ __u8 hci_ver; ++ __le16 hci_rev; ++ __u8 lmp_ver; ++ __le16 manufacturer; ++ __le16 lmp_subver; ++} __packed; ++ ++#define HCI_EV_CMD_COMPLETE 0x0e ++struct hci_ev_cmd_complete { ++ __u8 ncmd; ++ __le16 opcode; ++} __packed; ++ ++/* ---- HCI Packet structures ---- */ ++#define HCI_COMMAND_HDR_SIZE 3 ++#define HCI_EVENT_HDR_SIZE 2 ++#define HCI_ACL_HDR_SIZE 4 ++#define HCI_SCO_HDR_SIZE 3 ++ ++struct hci_command_hdr { ++ __le16 opcode; /* OCF & OGF */ ++ __u8 plen; ++} __packed; ++ ++struct hci_event_hdr { ++ __u8 evt; ++ __u8 plen; ++} __packed; ++ ++struct hci_acl_hdr { ++ __le16 handle; /* Handle & Flags(PB, BC) */ ++ __le16 dlen; ++} __packed; ++ ++struct hci_sco_hdr { ++ __le16 handle; ++ __u8 dlen; ++} __packed; ++ ++static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb) ++{ ++ return (struct hci_event_hdr *) skb->data; ++} ++ ++static inline struct hci_acl_hdr *hci_acl_hdr(const struct sk_buff *skb) ++{ ++ return (struct hci_acl_hdr *) skb->data; ++} ++ ++static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) ++{ ++ return (struct hci_sco_hdr *) skb->data; ++} ++ ++/* ---- HCI Ioctl requests structures ---- */ ++struct hci_dev_stats { ++ __u32 err_rx; ++ __u32 err_tx; ++ __u32 cmd_tx; ++ __u32 evt_rx; ++ __u32 acl_tx; ++ __u32 acl_rx; ++ __u32 sco_tx; ++ __u32 sco_rx; ++ __u32 byte_rx; ++ __u32 byte_tx; ++}; ++/* AicSemi - Integrate from hci.h end */ ++ ++/***************************************** ++** AicSemi - Integrate from hci_core.h ** ++*****************************************/ ++struct hci_conn_hash { ++ struct list_head list; ++ unsigned int acl_num; ++ unsigned int sco_num; ++ unsigned int le_num; ++}; ++ ++#define HCI_MAX_SHORT_NAME_LENGTH 10 ++ ++#define NUM_REASSEMBLY 4 ++struct hci_dev { ++ struct mutex lock; ++ ++ char name[8]; ++ unsigned long flags; ++ __u16 id; ++ __u8 bus; ++ __u8 dev_type; ++ ++ struct sk_buff *reassembly[NUM_REASSEMBLY]; ++ ++ struct hci_conn_hash conn_hash; ++ ++ struct hci_dev_stats stat; ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) ++ atomic_t refcnt; ++ struct module *owner; ++ void *driver_data; ++#endif ++ ++ atomic_t promisc; ++ ++ struct device *parent; ++ struct device dev; ++ ++ unsigned long dev_flags; ++ ++ int (*open)(struct hci_dev *hdev); ++ int (*close)(struct hci_dev *hdev); ++ int (*flush)(struct hci_dev *hdev); ++ int (*send)(struct sk_buff *skb); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) ++ void (*destruct)(struct hci_dev *hdev); ++#endif ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 1) ++ __u16 voice_setting; ++#endif ++ void (*notify)(struct hci_dev *hdev, unsigned int evt); ++ int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); ++ u8 *align_data; ++}; ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) ++static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d) ++{ ++ atomic_inc(&d->refcnt); ++ return d; ++} ++ ++static inline void __hci_dev_put(struct hci_dev *d) ++{ ++ if (atomic_dec_and_test(&d->refcnt)) ++ d->destruct(d); ++} ++#endif ++ ++static inline void *hci_get_drvdata(struct hci_dev *hdev) ++{ ++ return dev_get_drvdata(&hdev->dev); ++} ++ ++static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) ++{ ++ dev_set_drvdata(&hdev->dev, data); ++} ++ ++#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev)) ++ ++ ++/* ---- HCI Packet structures ---- */ ++#define HCI_COMMAND_HDR_SIZE 3 ++#define HCI_EVENT_HDR_SIZE 2 ++#define HCI_ACL_HDR_SIZE 4 ++#define HCI_SCO_HDR_SIZE 3 ++ ++/* ----- HCI Commands ---- */ ++#define HCI_OP_INQUIRY 0x0401 ++#define HCI_OP_INQUIRY_CANCEL 0x0402 ++#define HCI_OP_EXIT_PERIODIC_INQ 0x0404 ++#define HCI_OP_CREATE_CONN 0x0405 ++#define HCI_OP_DISCONNECT 0x0406 ++#define HCI_OP_ADD_SCO 0x0407 ++#define HCI_OP_CREATE_CONN_CANCEL 0x0408 ++#define HCI_OP_ACCEPT_CONN_REQ 0x0409 ++#define HCI_OP_REJECT_CONN_REQ 0x040a ++#define HCI_OP_LINK_KEY_REPLY 0x040b ++#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c ++#define HCI_OP_PIN_CODE_REPLY 0x040d ++#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e ++#define HCI_OP_CHANGE_CONN_PTYPE 0x040f ++#define HCI_OP_AUTH_REQUESTED 0x0411 ++#define HCI_OP_SET_CONN_ENCRYPT 0x0413 ++#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415 ++#define HCI_OP_REMOTE_NAME_REQ 0x0419 ++#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a ++#define HCI_OP_READ_REMOTE_FEATURES 0x041b ++#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c ++#define HCI_OP_READ_REMOTE_VERSION 0x041d ++#define HCI_OP_SETUP_SYNC_CONN 0x0428 ++#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429 ++#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a ++#define HCI_OP_SNIFF_MODE 0x0803 ++#define HCI_OP_EXIT_SNIFF_MODE 0x0804 ++#define HCI_OP_ROLE_DISCOVERY 0x0809 ++#define HCI_OP_SWITCH_ROLE 0x080b ++#define HCI_OP_READ_LINK_POLICY 0x080c ++#define HCI_OP_WRITE_LINK_POLICY 0x080d ++#define HCI_OP_READ_DEF_LINK_POLICY 0x080e ++#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f ++#define HCI_OP_SNIFF_SUBRATE 0x0811 ++#define HCI_OP_Write_Link_Policy_Settings 0x080d ++#define HCI_OP_SET_EVENT_MASK 0x0c01 ++#define HCI_OP_RESET 0x0c03 ++#define HCI_OP_SET_EVENT_FLT 0x0c05 ++#define HCI_OP_Write_Extended_Inquiry_Response 0x0c52 ++#define HCI_OP_Write_Simple_Pairing_Mode 0x0c56 ++#define HCI_OP_Read_Buffer_Size 0x1005 ++#define HCI_OP_Host_Buffer_Size 0x0c33 ++#define HCI_OP_Read_Local_Version_Information 0x1001 ++#define HCI_OP_Read_BD_ADDR 0x1009 ++#define HCI_OP_Read_Local_Supported_Commands 0x1002 ++#define HCI_OP_Write_Scan_Enable 0x0c1a ++#define HCI_OP_Write_Current_IAC_LAP 0x0c3a ++#define HCI_OP_Write_Inquiry_Scan_Activity 0x0c1e ++#define HCI_OP_Write_Class_of_Device 0x0c24 ++#define HCI_OP_LE_Rand 0x2018 ++#define HCI_OP_LE_Set_Random_Address 0x2005 ++#define HCI_OP_LE_Set_Extended_Scan_Enable 0x2042 ++#define HCI_OP_LE_Set_Extended_Scan_Parameters 0x2041 ++#define HCI_OP_Set_Event_Filter 0x0c05 ++#define HCI_OP_Write_Voice_Setting 0x0c26 ++#define HCI_OP_Change_Local_Name 0x0c13 ++#define HCI_OP_Read_Local_Name 0x0c14 ++#define HCI_OP_Wirte_Page_Timeout 0x0c18 ++#define HCI_OP_LE_Clear_Resolving_List 0x0c29 ++#define HCI_OP_LE_Set_Addres_Resolution_Enable_Command 0x0c2e ++#define HCI_OP_Write_Inquiry_mode 0x0c45 ++#define HCI_OP_Write_Page_Scan_Type 0x0c47 ++#define HCI_OP_Write_Inquiry_Scan_Type 0x0c43 ++ ++#define HCI_OP_Delete_Stored_Link_Key 0x0c12 ++#define HCI_OP_LE_Read_Local_Resolvable_Address 0x202d ++#define HCI_OP_LE_Extended_Create_Connection 0x2043 ++#define HCI_OP_Read_Remote_Version_Information 0x041d ++#define HCI_OP_LE_Start_Encryption 0x2019 ++#define HCI_OP_LE_Add_Device_to_Resolving_List 0x2027 ++#define HCI_OP_LE_Set_Privacy_Mode 0x204e ++#define HCI_OP_LE_Connection_Update 0x2013 ++ ++/* ----- HCI events---- */ ++#define HCI_OP_DISCONNECT 0x0406 ++#define HCI_EV_INQUIRY_COMPLETE 0x01 ++#define HCI_EV_INQUIRY_RESULT 0x02 ++#define HCI_EV_CONN_COMPLETE 0x03 ++#define HCI_EV_CONN_REQUEST 0x04 ++#define HCI_EV_DISCONN_COMPLETE 0x05 ++#define HCI_EV_AUTH_COMPLETE 0x06 ++#define HCI_EV_REMOTE_NAME 0x07 ++#define HCI_EV_ENCRYPT_CHANGE 0x08 ++#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09 ++ ++#define HCI_EV_REMOTE_FEATURES 0x0b ++#define HCI_EV_REMOTE_VERSION 0x0c ++#define HCI_EV_QOS_SETUP_COMPLETE 0x0d ++#define HCI_EV_CMD_COMPLETE 0x0e ++#define HCI_EV_CMD_STATUS 0x0f ++ ++#define HCI_EV_ROLE_CHANGE 0x12 ++#define HCI_EV_NUM_COMP_PKTS 0x13 ++#define HCI_EV_MODE_CHANGE 0x14 ++#define HCI_EV_PIN_CODE_REQ 0x16 ++#define HCI_EV_LINK_KEY_REQ 0x17 ++#define HCI_EV_LINK_KEY_NOTIFY 0x18 ++#define HCI_EV_CLOCK_OFFSET 0x1c ++#define HCI_EV_PKT_TYPE_CHANGE 0x1d ++#define HCI_EV_PSCAN_REP_MODE 0x20 ++ ++#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22 ++#define HCI_EV_REMOTE_EXT_FEATURES 0x23 ++#define HCI_EV_SYNC_CONN_COMPLETE 0x2c ++#define HCI_EV_SYNC_CONN_CHANGED 0x2d ++#define HCI_EV_SNIFF_SUBRATE 0x2e ++#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f ++#define HCI_EV_IO_CAPA_REQUEST 0x31 ++#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36 ++#define HCI_EV_REMOTE_HOST_FEATURES 0x3d ++#define HCI_EV_LE_Meta 0x3e ++ ++/* ULP Event sub code */ ++#define HCI_BLE_CONN_COMPLETE_EVT 0x01 ++#define HCI_BLE_ADV_PKT_RPT_EVT 0x02 ++#define HCI_BLE_LL_CONN_PARAM_UPD_EVT 0x03 ++#define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT 0x04 ++#define HCI_BLE_LTK_REQ_EVT 0x05 ++#define HCI_BLE_RC_PARAM_REQ_EVT 0x06 ++#define HCI_BLE_DATA_LENGTH_CHANGE_EVT 0x07 ++#define HCI_BLE_ENHANCED_CONN_COMPLETE_EVT 0x0a ++#define HCI_BLE_DIRECT_ADV_EVT 0x0b ++#define HCI_BLE_PHY_UPDATE_COMPLETE_EVT 0x0c ++#define HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT 0x0D ++#define HCI_BLE_PERIODIC_ADV_SYNC_EST_EVT 0x0E ++#define HCI_BLE_PERIODIC_ADV_REPORT_EVT 0x0F ++#define HCI_BLE_PERIODIC_ADV_SYNC_LOST_EVT 0x10 ++#define HCI_BLE_SCAN_TIMEOUT_EVT 0x11 ++#define HCI_LE_ADVERTISING_SET_TERMINATED_EVT 0x12 ++#define HCI_BLE_SCAN_REQ_RX_EVT 0x13 ++#define HCI_BLE_CIS_EST_EVT 0x19 ++#define HCI_BLE_CIS_REQ_EVT 0x1a ++#define HCI_BLE_CREATE_BIG_CPL_EVT 0x1b ++#define HCI_BLE_TERM_BIG_CPL_EVT 0x1c ++#define HCI_BLE_BIG_SYNC_EST_EVT 0x1d ++#define HCI_BLE_BIG_SYNC_LOST_EVT 0x1e ++#define HCI_BLE_REQ_PEER_SCA_CPL_EVT 0x1f ++ ++#define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */ ++ ++#define CONFIG_MAC_OFFSET_GEN_1_2 (0x3C) //MAC's OFFSET in config/efuse for aic generation 1~2 bluetooth chip ++#define CONFIG_MAC_OFFSET_GEN_3PLUS (0x44) //MAC's OFFSET in config/efuse for aic generation 3+ bluetooth chip ++ ++//Define ioctl cmd the same as HCIDEVUP in the kernel ++#define DOWN_FW_CFG _IOW('E', 176, int) ++//#ifdef CONFIG_SCO_OVER_HCI ++//#define SET_ISO_CFG _IOW('H', 202, int) ++//#else ++#define SET_ISO_CFG _IOW('E', 177, int) ++//#endif ++#define RESET_CONTROLLER _IOW('E', 178, int) ++#define DWFW_CMPLT _IOW('E', 179, int) ++ ++#define GET_USB_INFO _IOR('E', 180, int) ++ ++void bt_data_dump(char* tag, void* data, unsigned long len); ++int aic_enqueue(struct sk_buff *skb); ++int aic_queue_cnt(void); ++int bt_sdio_recv(u8 *data,u32 data_len); ++ ++ ++int btchr_init(void); ++void btchr_exit(void); ++int hdev_init(void); ++void hdev_exit(void); ++ ++ ++struct hci_dev *hci_dev_get(int index); ++int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); ++#else ++int btsdio_init(void); ++void btsdio_remove(void); ++int bt_sdio_recv(u8 *data,u32 data_len); ++#endif ++#endif//_AICWF_SDIO_BT_H_ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.c +new file mode 100644 +index 000000000000..4f3d5867dd04 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.c +@@ -0,0 +1,2023 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file aic_priv_cmd.c ++ * ++ * @brief Entry point of the AIC driver ++ * ++ * Copyright (C) Aicsemi 2018-2024 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include "rwnx_defs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_main.h" ++#include "aicwf_sdio.h" ++#include "aic_priv_cmd.h" ++#include "rwnx_mod_params.h" ++ ++ ++extern int testmode; ++static void print_help(const char *cmd); ++struct dbg_rftest_cmd_cfm cfm = {{0,}}; ++ ++#ifdef CONFIG_RFTEST ++enum { ++ SET_TX, ++ SET_TXSTOP, ++ SET_TXTONE, ++ SET_RX, ++ GET_RX_RESULT, ++ SET_RXSTOP, ++ SET_RX_METER, ++ SET_POWER, ++ SET_XTAL_CAP, ++ SET_XTAL_CAP_FINE, ++ GET_EFUSE_BLOCK, ++ SET_FREQ_CAL, ++ SET_FREQ_CAL_FINE, ++ GET_FREQ_CAL, ++ SET_MAC_ADDR, ++ GET_MAC_ADDR, ++ SET_BT_MAC_ADDR, ++ GET_BT_MAC_ADDR, ++ SET_VENDOR_INFO, ++ GET_VENDOR_INFO, ++ RDWR_PWRMM, ++ RDWR_PWRIDX, ++ RDWR_PWRLVL = RDWR_PWRIDX, ++ RDWR_PWROFST, ++ RDWR_DRVIBIT, ++ RDWR_EFUSE_PWROFST, ++ RDWR_EFUSE_DRVIBIT, ++ SET_PAPR, ++ SET_CAL_XTAL, ++ GET_CAL_XTAL_RES, ++ SET_COB_CAL, ++ GET_COB_CAL_RES, ++ RDWR_EFUSE_USRDATA, ++ SET_NOTCH, ++ RDWR_PWROFSTFINE, ++ RDWR_EFUSE_PWROFSTFINE, ++ RDWR_EFUSE_SDIOCFG, ++ RDWR_EFUSE_USBVIDPID, ++ SET_SRRC, ++ SET_FSS, ++ RDWR_EFUSE_HE_OFF, ++ SET_USB_OFF, ++ SET_PLL_TEST, ++ SET_ANT_MODE, ++ RDWR_BT_EFUSE_PWROFST, ++}; ++ ++typedef struct { ++ u8_l chan; ++ u8_l bw; ++ u8_l mode; ++ u8_l rate; ++ u16_l length; ++ u16_l tx_intv_us; ++ s8_l max_pwr; ++} cmd_rf_settx_t; ++ ++typedef struct { ++ u8_l val; ++} cmd_rf_setfreq_t; ++ ++typedef struct { ++ u8_l chan; ++ u8_l bw; ++} cmd_rf_rx_t; ++ ++typedef struct { ++ u8_l block; ++} cmd_rf_getefuse_t; ++ ++typedef struct { ++ u8_l dutid; ++ u8_l chip_num; ++ u8_l dis_xtal; ++} cmd_rf_setcobcal_t; ++ ++typedef struct { ++ u16_l dut_rcv_golden_num; ++ u8_l golden_rcv_dut_num; ++ s8_l rssi_static; ++ s8_l snr_static; ++ s8_l dut_rssi_static; ++ u16_l reserved; ++} cob_result_ptr_t; ++#endif ++ ++typedef struct ++{ ++ u8_l func; ++ u8_l cnt; ++ u8_l reserved[2]; ++ u32_l usrdata[3]; // 3 words totally ++} cmd_ef_usrdata_t; ++ ++#define CMD_MAXARGS 10 ++#define POWER_LEVEL_INVALID_VAL (127) ++ ++extern char country_code[]; ++ ++#if 0//#include ++#define isblank(c) ((c) == ' ' || (c) == '\t') ++#define isascii(c) (((unsigned char)(c)) <= 0x7F) ++ ++static int isdigit(unsigned char c) ++{ ++ return ((c >= '0') && (c <='9')); ++} ++ ++static int isxdigit(unsigned char c) ++{ ++ if ((c >= '0') && (c <='9')) ++ return 1; ++ if ((c >= 'a') && (c <='f')) ++ return 1; ++ if ((c >= 'A') && (c <='F')) ++ return 1; ++ return 0; ++} ++ ++static int islower(unsigned char c) ++{ ++ return ((c >= 'a') && (c <='z')); ++} ++ ++static unsigned char toupper(unsigned char c) ++{ ++ if (islower(c)) ++ c -= 'a'-'A'; ++ return c; ++} ++#endif ++ ++static int parse_line (char *line, char *argv[]) ++{ ++ int nargs = 0; ++ ++ while (nargs < CMD_MAXARGS) { ++ /* skip any white space */ ++ while ((*line == ' ') || (*line == '\t')) { ++ ++line; ++ } ++ ++ if (*line == '\0') { /* end of line, no more args */ ++ argv[nargs] = 0; ++ return nargs; ++ } ++ ++ /* Argument include space should be bracketed by quotation mark */ ++ if (*line == '\"') { ++ /* Skip quotation mark */ ++ line++; ++ ++ /* Begin of argument string */ ++ argv[nargs++] = line; ++ ++ /* Until end of argument */ ++ while (*line && (*line != '\"')) { ++ ++line; ++ } ++ } else { ++ argv[nargs++] = line; /* begin of argument string */ ++ ++ /* find end of string */ ++ while (*line && (*line != ' ') && (*line != '\t')) { ++ ++line; ++ } ++ } ++ ++ if (*line == '\0') { /* end of line, no more args */ ++ argv[nargs] = 0; ++ return nargs; ++ } ++ ++ *line++ = '\0'; /* terminate current arg */ ++ } ++ ++ printk("** Too many args (max. %d) **\n", CMD_MAXARGS); ++ ++ return nargs; ++} ++ ++unsigned int command_strtoul(const char *cp, char **endp, unsigned int base) ++{ ++ unsigned int result = 0, value, is_neg = 0; ++ ++ if (*cp == '0') { ++ cp++; ++ if ((*cp == 'x') && isxdigit(cp[1])) { ++ base = 16; ++ cp++; ++ } ++ if (!base) { ++ base = 8; ++ } ++ } ++ if (!base) { ++ base = 10; ++ } ++ if (*cp == '-') { ++ is_neg = 1; ++ cp++; ++ } ++ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0' : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) { ++ result = result * base + value; ++ cp++; ++ } ++ if (is_neg) ++ result = (unsigned int)((int)result * (-1)); ++ ++ if (endp) ++ *endp = (char *)cp; ++ return result; ++} ++ ++/* ++ * aic_priv_cmd handers. ++ */ ++static int aic_priv_cmd_set_tx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_settx_t settx_param; ++ u8_l set_p = 0; ++ u8_l lvl_band, lvl_mod, lvl_idx, lvl_pwr = 0; ++ u8_l buf[10]; ++#ifdef CONFIG_POWER_LIMIT ++ int8_t max_pwr; ++ uint8_t r_idx; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++ txpwr_loss = &txpwr_loss_tmp; ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (argc < 6) ++ return -EINVAL; ++ ++ settx_param.chan = command_strtoul(argv[1], NULL, 10); ++ settx_param.bw = command_strtoul(argv[2], NULL, 10); ++ settx_param.mode = command_strtoul(argv[3], NULL, 10); ++ settx_param.rate = command_strtoul(argv[4], NULL, 10); ++ settx_param.length = command_strtoul(argv[5], NULL, 10); ++ if (argc > 6) { ++ settx_param.tx_intv_us = command_strtoul(argv[6], NULL, 10); ++ } else { ++ settx_param.tx_intv_us = 10000; // set default val 10ms ++ } ++ if (argc > 7) { ++ if (dev->chipid == PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ return -EINVAL; ++ } ++ lvl_pwr = command_strtoul(argv[7], NULL, 10); ++ AICWFDBG(LOGINFO, "lvl_pwr: %d\n", lvl_pwr); ++ ++ if (settx_param.chan >= 36) ++ lvl_band = 2; ++ else ++ lvl_band = 1; ++ if (settx_param.mode == 0) ++ lvl_mod = 0; ++ else if (settx_param.mode == 2 || settx_param.mode == 4) ++ lvl_mod = 1; ++ else if (settx_param.mode == 5) ++ lvl_mod = 2; ++ if (settx_param.mode >= 4) ++ lvl_idx = settx_param.rate & 0xF; ++ else if (settx_param.mode >= 2) ++ lvl_idx = settx_param.rate & 0x7; ++ else ++ lvl_idx = settx_param.rate; ++ ++ buf[0] = lvl_band; ++ buf[1] = lvl_mod; ++ buf[2] = lvl_idx; ++ buf[3] = lvl_pwr; ++ ++ set_p = 1; ++ } ++ settx_param.max_pwr = POWER_LEVEL_INVALID_VAL; ++ AICWFDBG(LOGINFO, "txparam:%d,%d,%d,%d,%d,%d\n", settx_param.chan, settx_param.bw, ++ settx_param.mode, settx_param.rate, settx_param.length, settx_param.tx_intv_us); ++ ++#ifdef CONFIG_POWER_LIMIT ++ r_idx = get_ccode_region(country_code); ++ txpwr_loss = &txpwr_loss_tmp; ++ get_userconfig_txpwr_loss(txpwr_loss); ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ if (txpwr_loss->loss_enable_5g == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ max_pwr = get_powerlimit_by_chnum(settx_param.chan, r_idx, settx_param.bw); ++ if (settx_param.chan >= 36) { ++ if (txpwr_loss->loss_enable_5g == 1) ++ max_pwr -= txpwr_loss->loss_value_5g; ++ } else { ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ max_pwr -= txpwr_loss->loss_value_2g4; ++ } ++ ++ if (!set_p || (lvl_pwr == 255)) { ++ settx_param.max_pwr = max_pwr; ++ AICWFDBG(LOGINFO, "max_pwr:%d\n", settx_param.max_pwr); ++ } else ++ AICWFDBG(LOGINFO, "the specified power is input without power limit\n"); ++#endif ++ ++ if (set_p && (lvl_pwr != 255)) ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, 4, buf, &cfm); ++ ++ rwnx_send_rftest_req(rwnx_hw, SET_TX, sizeof(cmd_rf_settx_t), (u8_l *)&settx_param, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_txstop (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_TXSTOP, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_rx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_rx_t setrx_param; ++ ++ if (argc < 3) { ++ return -EINVAL; ++ } ++ setrx_param.chan = command_strtoul(argv[1], NULL, 10); ++ setrx_param.bw = command_strtoul(argv[2], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_RX, sizeof(cmd_rf_rx_t), (u8_l *)&setrx_param, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_rx_result (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, GET_RX_RESULT, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ return 8; ++} ++ ++static int aic_priv_cmd_set_rxstop (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_RXSTOP, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_tx_tone (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ u8_l buf[2]; ++ s8_l freq_ = 0; ++ ++ AICWFDBG(LOGINFO, "%s argc:%d\n", argv[0], argc); ++ if ((argc == 2) || (argc == 3)) { ++ AICWFDBG(LOGINFO, "argv 1:%s\n",argv[1]); ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ if (argc == 3) { ++ AICWFDBG(LOGINFO, "argv 2:%s\n",argv[2]); ++ freq_ = (u8_l)command_strtoul(argv[2], NULL, 10); ++ } else { ++ freq_ = 0; ++ }; ++ buf[0] = func; ++ buf[1] = (u8_l)freq_; ++ rwnx_send_rftest_req(rwnx_hw, SET_TXTONE, argc - 1, buf, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_rx_meter (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ s8_l freq = 0; ++ ++ freq = (int)command_strtoul(argv[1], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_RX_METER, sizeof(freq), (u8_l *)&freq, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_set_power (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l ana_pwr; ++ u8_l dig_pwr; ++ u8_l pwr; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (dev->chipid == PRODUCT_ID_AIC8801) { ++ ana_pwr = command_strtoul(argv[1], NULL, 16); ++ dig_pwr = command_strtoul(argv[2], NULL, 16); ++ pwr = (ana_pwr << 4 | dig_pwr); ++ if (ana_pwr > 0xf || dig_pwr > 0xf) ++ return -EINVAL; ++ } else { ++ ana_pwr = command_strtoul(argv[1], NULL, 10); ++ pwr = ana_pwr; ++ if (ana_pwr > 0x1e) ++ return -EINVAL; ++ } ++ AICWFDBG(LOGINFO, "pwr =%x\r\n", pwr); ++ rwnx_send_rftest_req(rwnx_hw, SET_POWER, sizeof(pwr), (u8_l *)&pwr, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_xtal_cap (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l xtal_cap; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ xtal_cap = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "xtal_cap =%x\r\n", xtal_cap); ++ rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap), (u8_l *)&xtal_cap, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_xtal_cap_fine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l xtal_cap_fine; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ xtal_cap_fine = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "xtal_cap_fine =%x\r\n", xtal_cap_fine); ++ rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP_FINE, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_get_efuse_block (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_getefuse_t getefuse_param; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ getefuse_param.block = command_strtoul(argv[1], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, GET_EFUSE_BLOCK, sizeof(cmd_rf_getefuse_t), (u8_l *)&getefuse_param, &cfm); ++ AICWFDBG(LOGINFO, "get val=%x\r\n", cfm.rftest_result[0]); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_setfreq_t cmd_setfreq; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); ++ rwnx_send_rftest_req(rwnx_hw, SET_FREQ_CAL, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_freq_cal_fine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_setfreq_t cmd_setfreq; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); ++ rwnx_send_rftest_req(rwnx_hw, SET_FREQ_CAL_FINE, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_get_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u32_l val; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_FREQ_CAL, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ val = cfm.rftest_result[0]; ++ if (dev->chipid != PRODUCT_ID_AIC8801) { ++ AICWFDBG(LOGINFO, "cap=0x%x (remain:%x), cap_fine=%x (remain:%x)\n", ++ val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff); ++ } else { ++ AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", val & 0xff, (val >> 8) & 0xff); ++ } ++ return 4; ++} ++ ++static int aic_priv_cmd_set_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l mac_addr[6]; ++ ++ if (argc < 7) ++ return -EINVAL; ++ ++ mac_addr[5] = command_strtoul(argv[1], NULL, 16); ++ mac_addr[4] = command_strtoul(argv[2], NULL, 16); ++ mac_addr[3] = command_strtoul(argv[3], NULL, 16); ++ mac_addr[2] = command_strtoul(argv[4], NULL, 16); ++ mac_addr[1] = command_strtoul(argv[5], NULL, 16); ++ mac_addr[0] = command_strtoul(argv[6], NULL, 16); ++ AICWFDBG(LOGINFO, "set macaddr:%x,%x,%x,%x,%x,%x\n", mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); ++ rwnx_send_rftest_req(rwnx_hw, SET_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u32_l addr0, addr1; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_MAC_ADDR, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ addr0 = cfm.rftest_result[0]; ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ int rem_cnt = (cfm.rftest_result[1] >> 16) & 0x00FF; ++ addr1 = cfm.rftest_result[1] & 0x0000FFFF; ++ AICWFDBG(LOGINFO, "0x%x,0x%x (remain:%x)\n", addr0, addr1, rem_cnt); ++ } else { ++ addr1 = cfm.rftest_result[1]; ++ AICWFDBG(LOGINFO, "0x%x,0x%x\n", addr0, addr1); ++ } ++ return 8; ++} ++ ++static int aic_priv_cmd_set_bt_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l mac_addr[6]; ++ ++ if (argc < 7) ++ return -EINVAL; ++ ++ mac_addr[5] = command_strtoul(argv[1], NULL, 16); ++ mac_addr[4] = command_strtoul(argv[2], NULL, 16); ++ mac_addr[3] = command_strtoul(argv[3], NULL, 16); ++ mac_addr[2] = command_strtoul(argv[4], NULL, 16); ++ mac_addr[1] = command_strtoul(argv[5], NULL, 16); ++ mac_addr[0] = command_strtoul(argv[6], NULL, 16); ++ AICWFDBG(LOGINFO, "set bt macaddr:%x,%x,%x,%x,%x,%x\n", mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); ++ rwnx_send_rftest_req(rwnx_hw, SET_BT_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_bt_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u32_l addr0, addr1; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_BT_MAC_ADDR, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ addr0 = cfm.rftest_result[0]; ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ int rem_cnt = (cfm.rftest_result[1] >> 16) & 0x00FF; ++ addr1 = cfm.rftest_result[1] & 0x0000FFFF; ++ AICWFDBG(LOGINFO, "0x%x,0x%x (remain:%x)\n", addr0, addr1, rem_cnt); ++ } else { ++ addr1 = cfm.rftest_result[1]; ++ AICWFDBG(LOGINFO, "0x%x,0x%x\n", addr0, addr1); ++ } ++ return 8; ++} ++ ++static int aic_priv_cmd_set_vendor_info (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l vendor_info; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ vendor_info = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "set vendor info:%x\n", vendor_info); ++ rwnx_send_rftest_req(rwnx_hw, SET_VENDOR_INFO, 1, &vendor_info, &cfm); ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ memcpy(command, &cfm.rftest_result[0], 2); ++ return 2; ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 1); ++ return 1; ++ } ++ AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); ++} ++ ++static int aic_priv_cmd_get_vendor_info (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_VENDOR_INFO, 0, NULL, &cfm); ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ memcpy(command, &cfm.rftest_result[0], 2); ++ return 2; ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 1); ++ return 1; ++ } ++ AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); ++} ++ ++static int aic_priv_cmd_rdwr_pwrmm (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ if (argc <= 1) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRMM, 0, NULL, &cfm); ++ } else { // write ++ u8_l pwrmm = (u8_l)command_strtoul(argv[1], NULL, 16); ++ pwrmm = (pwrmm) ? 1 : 0; ++ AICWFDBG(LOGINFO, "set pwrmm = %x\r\n", pwrmm); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRMM, sizeof(pwrmm), (u8_l *)&pwrmm, &cfm); ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_pwridx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (dev->chipid != PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ return -EINVAL; ++ } ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRIDX, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr idx ++ if (argc > 3) { ++ u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l pwridx = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, type, pwridx}; ++ AICWFDBG(LOGINFO, "set pwridx:[%x][%x]=%x\r\n", func, type, pwridx); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRIDX, sizeof(buf), buf, &cfm); ++ } else { ++ return -EINVAL; ++ } ++ } else { ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 9); ++ return 9; ++} ++ ++static int aic_priv_cmd_rdwr_pwrlvl (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (dev->chipid == PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ return -EINVAL; ++ } ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr lvl ++ if (argc > 4) { ++ u8_l grp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l idx, size; ++ u8_l buf[14] = {func, grp,}; ++ if (argc > 12) { // set all grp ++ AICWFDBG(LOGINFO, "set pwrlvl %s:\n" ++ " [%x] =", (func == 1) ? "2.4g" : "5g", grp); ++ if (grp == 1) { // TXPWR_LVL_GRP_11N_11AC ++ size = 10; ++ } else { ++ size = 12; ++ } ++ for (idx = 0; idx < size; idx++) { ++ s8_l pwrlvl = (s8_l)command_strtoul(argv[3 + idx], NULL, 10); ++ buf[2 + idx] = (u8_l)pwrlvl; ++ if (idx && !(idx & 0x3)) { ++ AICWFDBG(LOGINFO, " "); ++ } ++ AICWFDBG(LOGINFO, " %2d", pwrlvl); ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ size += 2; ++ } else { // set grp[idx] ++ u8_l idx = (u8_l)command_strtoul(argv[3], NULL, 10); ++ s8_l pwrlvl = (s8_l)command_strtoul(argv[4], NULL, 10); ++ buf[2] = idx; ++ buf[3] = (u8_l)pwrlvl; ++ size = 4; ++ AICWFDBG(LOGINFO, "set pwrlvl %s:\n" ++ " [%x][%d] = %d\n", (func == 1) ? "2.4g" : "5g", grp, idx, pwrlvl); ++ } ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, size, buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ if(dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ memcpy(command, &cfm.rftest_result[0], 6 * 12); ++ return (6 * 12); ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 3 * 12); ++ return (3 * 12); ++ } ++} ++ ++static int aic_priv_cmd_rdwr_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ int res_len = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, 0, NULL, &cfm); ++ } else if (func <= 4) { // write 2.4g/5g pwr ofst and ant0/1 ++ if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); ++ u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); ++ } else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D80) && (dev->chipid != PRODUCT_ID_AIC8800D80X2)) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); ++ } else { ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { // 3 = 3 (2.4g) ++ res_len = 3; ++ } else if (dev->chipid == PRODUCT_ID_AIC8800D80) { // 3 * 2 (2.4g) + 3 * 6 (5g) ++ res_len = 3 * 3 + 3 * 6; ++ } else if (dev->chipid == PRODUCT_ID_AIC8800D80X2) { // ant0/1 ++ res_len = ( 3 * 3 + 3 * 6 ) * 2; ++ } else { ++ res_len = 3 + 4; ++ } ++ memcpy(command, &cfm.rftest_result[0], res_len); ++ return res_len; ++} ++ ++static int aic_priv_cmd_rdwr_pwrofstfine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr ofst ++ if (argc > 3) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ ++ } ++ memcpy(command, &cfm.rftest_result[0], 7); ++ return 7; ++} ++ ++static int aic_priv_cmd_rdwr_drvibit (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_DRVIBIT, 0, NULL, &cfm); ++ } else if (func == 1) { // write 2.4g pa drv_ibit ++ if (argc > 2) { ++ u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[2] = {func, ibit}; ++ AICWFDBG(LOGINFO, "set drvibit:[%x]=%x\r\n", func, ibit); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_DRVIBIT, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 16); ++ return 16; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ int res_len = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, 0, NULL, &cfm); ++ } else if (func <= 4) { // write 2.4g/5g pwr ofst and ant0/1 ++ if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); ++ u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set efuse pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); ++ } else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D80) && (dev->chipid != PRODUCT_ID_AIC8800D80X2)) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set efuse pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { // 6 = 3 (2.4g) * 2 ++ res_len = 3 * 2; ++ } else if (dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2) { // 3 * 2 (2.4g) + 3 * 6 (5g) ++ res_len = (3 * 3 + 3 * 6) * 2; ++ } else { // 7 = 3(2.4g) + 4(5g) ++ res_len = 3 + 4; ++ } ++ memcpy(command, &cfm.rftest_result[0], res_len); ++ return res_len; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_pwrofstfine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr ofst ++ if (argc > 3) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 7); ++ return 7; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_drvibit (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_DRVIBIT, 0, NULL, &cfm); ++ } else if (func == 1) { // write 2.4g pa drv_ibit ++ if (argc > 2) { ++ u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[2] = {func, ibit}; ++ AICWFDBG(LOGINFO, "set efuse drvibit:[%x]=%x\r\n", func, ibit); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_DRVIBIT, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_usrdata (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_ef_usrdata_t cmd_ef_usrdata; ++ ++ if (argc <= 1) { // read all ++ cmd_ef_usrdata.func = 0; ++ cmd_ef_usrdata.cnt = 3; ++ } else if (argc >= 2) { // read/write ++ cmd_ef_usrdata.func = (u8_l)command_strtoul(argv[1], NULL, 10); ++ cmd_ef_usrdata.cnt = (u8_l)command_strtoul(argv[2], NULL, 10); ++ if (cmd_ef_usrdata.func == 1) { ++ int idx; ++ for (idx = 0; idx < cmd_ef_usrdata.cnt; idx++) { ++ cmd_ef_usrdata.usrdata[idx] = (u32_l)command_strtoul(argv[3 + idx], NULL, 16); ++ } ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong argc: %x\n", argc); ++ return -EINVAL; ++ } ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USRDATA, sizeof(cmd_ef_usrdata), (u8_l *)&cmd_ef_usrdata, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 12); ++ return 12; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_sdiocfg (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_SDIOCFG, 0, NULL, &cfm); ++ } else if (func == 1) { // write sdiocfg ++ if (argc > 2) { ++ u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[2] = {func, ibit}; ++ AICWFDBG(LOGINFO, "set efuse sdiocfg:[%x]=%x\r\n", func, ibit); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_SDIOCFG, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_usbvidpid (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ AICWFDBG(LOGINFO, "read/write usb vid/pid into efuse\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USBVIDPID, 0, NULL, &cfm); ++ } else if (func == 1) { // write USB vid+pid ++ if (argc > 2) { ++ u32_l usb_id = (u32_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[5] = {func, (u8_l)usb_id, (u8_l)(usb_id >> 8), (u8_l)(usb_id >> 16), (u8_l)(usb_id >> 24)}; ++ AICWFDBG(LOGINFO, "set efuse usb vid/pid:[%x]=%x\r\n", func, usb_id); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USBVIDPID, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_he_off (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set he off: %d\n", func); ++ if(func == 1 || func == 0) { ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_HE_OFF, sizeof(func), (u8_l *)&func, &cfm); ++ AICWFDBG(LOGINFO, "he_off cfm: %d\n", cfm.rftest_result[0]); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_cal_xtal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_CAL_XTAL, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_cal_xtal_res (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, GET_CAL_XTAL_RES, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", cfm.rftest_result[0] & 0x0000ffff, (cfm.rftest_result[0] >> 16) & 0x0000ffff); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_cob_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_setcobcal_t setcob_cal; ++ ++ if (argc < 3) ++ return -EINVAL; ++ setcob_cal.dutid = command_strtoul(argv[1], NULL, 10); ++ setcob_cal.chip_num = command_strtoul(argv[2], NULL, 10); ++ setcob_cal.dis_xtal = command_strtoul(argv[3], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_cob_cal_res (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l state; ++ cob_result_ptr_t *cob_result_ptr; ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); ++ state = (cfm.rftest_result[0] >> 16) & 0x000000ff; ++ if (!state){ ++ AICWFDBG(LOGINFO, "cap= 0x%x, cap_fine= 0x%x, freq_ofst= %d Hz\n", ++ cfm.rftest_result[0] & 0x000000ff, (cfm.rftest_result[0] >> 8) & 0x000000ff, cfm.rftest_result[1]); ++ cob_result_ptr = (cob_result_ptr_t *) & (cfm.rftest_result[2]); ++ AICWFDBG(LOGINFO, "golden_rcv_dut= %d , tx_rssi= %d dBm, snr = %d dB\ndut_rcv_godlden= %d , rx_rssi= %d dBm", ++ cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, ++ cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static); ++ memcpy(command, &cfm.rftest_result, 16); ++ return 16; ++ } else { ++ AICWFDBG(LOGERROR, "cob not idle\n"); ++ return -EINVAL; ++ } ++} ++ ++static int aic_priv_cmd_do_cob_test (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l state; ++ cmd_rf_setcobcal_t setcob_cal; ++ cob_result_ptr_t *cob_result_ptr; ++ ++ setcob_cal.dutid = 1; ++ setcob_cal.chip_num = 1; ++ setcob_cal.dis_xtal = 0; ++ if (argc > 1) ++ setcob_cal.dis_xtal = command_strtoul(argv[1], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); ++ msleep(2000); ++ rwnx_send_rftest_req(rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); ++ state = (cfm.rftest_result[0] >> 16) & 0x000000ff; ++ if (!state){ ++ AICWFDBG(LOGINFO, "cap= 0x%x, cap_fine= 0x%x, freq_ofst= %d Hz\n", ++ cfm.rftest_result[0] & 0x000000ff, (cfm.rftest_result[0] >> 8) & 0x000000ff, cfm.rftest_result[1]); ++ cob_result_ptr = (cob_result_ptr_t *) & (cfm.rftest_result[2]); ++ AICWFDBG(LOGINFO, "golden_rcv_dut= %d , tx_rssi= %d dBm, snr = %d dB\ndut_rcv_godlden= %d , rx_rssi= %d dBm", ++ cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, ++ cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static); ++ memcpy(command, &cfm.rftest_result, 16); ++ return 16; ++ } else { ++ AICWFDBG(LOGERROR, "cob not idle\n"); ++ return -EINVAL; ++ } ++} ++ ++static int aic_priv_cmd_set_papr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "papr %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_PAPR, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_notch (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "notch %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_NOTCH, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_srrc (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "srrc %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_SRRC, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_fss (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "fss %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_FSS, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_usb_off (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_USB_OFF, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_pll_test (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0, tx_pwr = 0xc; ++ s8_l freq = 0; ++ ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 16); ++ } ++ if (argc > 3) { ++ freq = (s8_l)command_strtoul(argv[2], NULL, 10); ++ tx_pwr = command_strtoul(argv[3], NULL, 16); ++ } ++ if (func <= 1) { ++ u8_l buf[3] = {func, (u8_l)freq, tx_pwr}; ++ AICWFDBG(LOGINFO, "set pll_test %d: freq=%d, tx_pwr=0x%x\n", func, freq, tx_pwr); ++ rwnx_send_rftest_req(rwnx_hw, SET_PLL_TEST, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_get_txpwr(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ s8_l power=0; ++ power = get_txpwr_max(power); ++ memcpy(command, &power, 1); ++ return 1; ++} ++ ++static int aic_priv_cmd_set_txpwr_loss(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ s8_l func; ++ if (argc > 1) { ++ func = (s8_l)command_strtoul(argv[1], NULL, 10); ++ printk("set txpwr loss: %d\n", func); ++ if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ set_txpwr_loss_ofst(func); ++ rwnx_send_txpwr_lvl_v3_req(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ set_txpwr_loss_ofst(func); ++ rwnx_send_txpwr_lvl_v4_req(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ set_txpwr_loss_ofst(func); ++ rwnx_send_txpwr_lvl_req(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else{ ++ AICWFDBG(LOGINFO,"error:don't support 8800D"); ++ } ++ } else { ++ printk("wrong args\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_ant_mode (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "ant %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_ANT_MODE, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_rdwr_bt_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc == 1) { ++ func = 0; ++ } else if (argc == 2) { ++ func = 1; ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_BT_EFUSE_PWROFST, 0, NULL, &cfm); ++ } else if (func == 1) { // write bt tx pwrofst ++ int8_t bt_txpwrofst = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set bt efuse pwrofst %d\r\n",bt_txpwrofst); ++ if (bt_txpwrofst < -7 || bt_txpwrofst > 7) { ++ AICWFDBG(LOGERROR, "wrong params %d, pwrofst limit -7 ~ 7\n", bt_txpwrofst); ++ return -EINVAL; ++ } else { ++ rwnx_send_rftest_req(rwnx_hw, RDWR_BT_EFUSE_PWROFST, sizeof(bt_txpwrofst), &bt_txpwrofst, &cfm); ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 2); ++ return 2; ++} ++ ++static int aic_priv_cmd_country_set(struct rwnx_hw *rwnx_hw, int argc, ++ char *argv[], char *command) ++{ ++ int ret = 0; ++ struct ieee80211_regdomain *regdomain; ++ ++ if (argc < 2) { ++ AICWFDBG(LOGINFO, "%s param err\n", __func__); ++ return -1; ++ } ++ ++ AICWFDBG(LOGINFO, "cmd country_set: %s\n", argv[1]); ++ ++ regdomain = getRegdomainFromRwnxDB(rwnx_hw->wiphy, argv[1]); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ ret = regulatory_set_wiphy_regd( ++ rwnx_hw->wiphy, regdomain); ++#else ++ ret = wiphy_apply_custom_regulatory( ++ rwnx_hw->wiphy, regdomain); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */ ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ rwnx_radar_set_domain(&rwnx_hw->radar, regdomain->dfs_region); ++#endif ++ ++#ifdef CONFIG_POWER_LIMIT ++ if (!testmode){ ++ rwnx_send_me_chan_config_req(rwnx_hw, argv[1]); ++ } ++#endif ++ ++ return ret; ++} ++ ++static int aic_priv_cmd_help (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ print_help(argc > 0 ? argv[0] : NULL); ++ return 0; ++} ++ ++struct aic_priv_cmd { ++ const char *cmd; ++ int (*handler)(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command); ++ const char *usage; ++}; ++ ++static const struct aic_priv_cmd aic_priv_commands[] = { ++ { "set_tx", aic_priv_cmd_set_tx, ++ " " }, ++ { "set_txstop", aic_priv_cmd_set_txstop, ++ "= stop tx " }, ++ { "set_rx", aic_priv_cmd_set_rx, ++ " " }, ++ { "get_rx_result", aic_priv_cmd_get_rx_result, ++ "= display rx fcsok/total pkt num" }, ++ { "set_rxstop", aic_priv_cmd_set_rxstop, ++ "= stop rx " }, ++ { "set_txtone", aic_priv_cmd_set_tx_tone, ++ " val = 0/off" }, ++ { "set_rx_meter", aic_priv_cmd_set_rx_meter, ++ "= set rx meter " }, ++ { "set_power", aic_priv_cmd_set_set_power, ++ " " }, ++ { "set_xtal_cap", aic_priv_cmd_set_xtal_cap, ++ " [0 ~ 31]" }, ++ { "set_xtal_cap_fine", aic_priv_cmd_set_xtal_cap_fine, ++ " [0 ~ 63]" }, ++ { "get_efuse_block", aic_priv_cmd_get_efuse_block, ++ "" }, ++ { "set_freq_cal", aic_priv_cmd_set_freq_cal, ++ "" }, ++ { "set_freq_cal_fine", aic_priv_cmd_set_freq_cal_fine, ++ "" }, ++ { "get_freq_cal", aic_priv_cmd_get_freq_cal, ++ "= display cap & cap fine" }, ++ { "set_mac_addr", aic_priv_cmd_set_mac_addr, ++ "= write WiFi MAC into efuse or flash is limited to a maximum of two times" }, ++ { "get_mac_addr", aic_priv_cmd_get_mac_addr, ++ "= display WiFi MAC stored in efuse or flash" }, ++ { "set_bt_mac_addr", aic_priv_cmd_set_bt_mac_addr, ++ "= write BT MAC into efuse or flash is limited to a maximum of two times" }, ++ { "get_bt_mac_addr", aic_priv_cmd_get_bt_mac_addr, ++ "= display BT MAC stored in efuse or flash" }, ++ { "set_vendor_info", aic_priv_cmd_set_vendor_info, ++ "= write vendor info into efuse or flash is allowed only once" }, ++ { "get_vendor_info", aic_priv_cmd_get_vendor_info, ++ "= display vendor info stored in efuse or flash" }, ++ { "rdwr_pwrmm", aic_priv_cmd_rdwr_pwrmm, ++ " = 0/rdwr_pwrlvl, 1/set_power = read/write txpwr manul mode" }, ++ { "rdwr_pwridx", aic_priv_cmd_rdwr_pwridx, ++ " " }, ++ { "rdwr_pwrlvl", aic_priv_cmd_rdwr_pwrlvl, ++ " " }, ++ { "rdwr_pwrofst", aic_priv_cmd_rdwr_pwrofst, ++ " " }, ++ { "rdwr_pwrofstfine", aic_priv_cmd_rdwr_pwrofstfine, ++ " " }, ++ { "rdwr_drvibit", aic_priv_cmd_rdwr_drvibit, ++ " read/write 8800D pa drvibit" }, ++ { "set_cal_xtal", aic_priv_cmd_set_cal_xtal, ++ "= set cal xtal" }, ++ { "get_cal_xtal_res", aic_priv_cmd_get_cal_xtal_res, ++ "= get cal xtal result cap & cap_fine" }, ++ { "set_cob_cal", aic_priv_cmd_set_cob_cal, ++ " = dut cob test" }, ++ { "get_cob_cal_res", aic_priv_cmd_get_cob_cal_res, ++ "= get cob cal result" }, ++ { "do_cob_test", aic_priv_cmd_do_cob_test, ++ " = 0/xtal, 1/dis_xtal, 2/only_xtal" }, ++ { "rdwr_efuse_pwrofst", aic_priv_cmd_rdwr_efuse_pwrofst, ++ " limited to a maximum of two times" }, ++ { "rdwr_efuse_pwrofstfine", aic_priv_cmd_rdwr_efuse_pwrofstfine, ++ " limited to a maximum of two times" }, ++ { "rdwr_efuse_drvibit", aic_priv_cmd_rdwr_efuse_drvibit, ++ " = read/write 8800D efuse pa drvibitis allowed only once" }, ++ { "rdwr_efuse_usrdata", aic_priv_cmd_rdwr_efuse_usrdata, ++ " = read/write efuse usrdata" }, ++ { "rdwr_efuse_sdiocfg", aic_priv_cmd_rdwr_efuse_sdiocfg, ++ " = read/write sdiocfg_bit into efuse" }, ++ { "rdwr_efuse_usbvidpid", aic_priv_cmd_rdwr_efuse_usbvidpid, ++ " = read/write usb vid/pid into efuse" }, ++ { "rdwr_efuse_he_off", aic_priv_cmd_rdwr_efuse_he_off, ++ " = read/write he_off into efuse" }, ++ { "set_papr", aic_priv_cmd_set_papr, ++ " = configure papr filter to optimize sideband suppression" }, ++ { "set_notch", aic_priv_cmd_set_notch, ++ " = configure filter to optimize sideband suppression" }, ++ { "set_srrc", aic_priv_cmd_set_srrc, ++ " = disable/enable sideband suppression for SRRC" }, ++ { "set_fss", aic_priv_cmd_set_fss, ++ " = disable/enable treatment of spurious emissions and burrs" }, ++ { "set_usb_off", aic_priv_cmd_set_usb_off, ++ "= off usb configure before usb disconnect" }, ++ { "set_pll_test", aic_priv_cmd_set_pll_test, ++ " = use pll test to measure saturation power" }, ++ { "get_txpwr", aic_priv_cmd_get_txpwr, ++ "= get userconfig max txpwr" }, ++ { "set_txpwr_loss",aic_priv_cmd_set_txpwr_loss, ++ " = txpwr will change ,val can be negative" }, ++ { "set_ant", aic_priv_cmd_set_ant_mode, ++ " = 0/ant0, 1/ant1, 2/both" }, ++ { "rdwr_bt_efuse_pwrofst", aic_priv_cmd_rdwr_bt_efuse_pwrofst, ++ " = read/write bt tx power offset into efuse" }, ++ {"country_set", aic_priv_cmd_country_set, ""}, ++//Reserve for new aic_priv_cmd. ++ { "help", aic_priv_cmd_help, ++ "= show usage help" }, ++ { NULL, NULL, NULL } ++ ++}; ++ ++ ++/* ++ * Prints command usage, lines are padded with the specified string. ++ */ ++static void print_help(const char *cmd) ++{ ++ int n; ++ printk("commands:\n"); ++ for (n = 0; aic_priv_commands[n].cmd; n++) { ++ if (cmd != NULL) ++ printk("%s %s\n", aic_priv_commands[n].cmd, aic_priv_commands[n].usage); ++ } ++} ++ ++int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len) ++{ ++ const struct aic_priv_cmd *cmd, *match = NULL; ++ int count; ++ int bytes_written = 0; ++ char *argv[CMD_MAXARGS + 1]; ++ int argc; ++ struct rwnx_vif *vif = container_of(net->ieee80211_ptr, struct rwnx_vif, wdev); ++ struct rwnx_hw *p_rwnx_hw = vif->rwnx_hw; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#if 1 ++ if(!testmode) { ++ AICWFDBG(LOGERROR, "not in testmdoe\n"); ++ return -1; ++ } ++#endif ++ argc = parse_line(command, argv); ++ if (argc == 0) { ++ return -1; ++ } ++ ++ count = 0; ++ cmd = aic_priv_commands; ++ while (cmd->cmd) { ++ if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0 && ++ strncasecmp(cmd->cmd, argv[0], strlen(cmd->cmd)) == 0) ++ { ++ match = cmd; ++ if (strcasecmp(cmd->cmd, argv[0]) == 0) { ++ /* we have an exact match */ ++ count = 1; ++ break; ++ } ++ count++; ++ } ++ cmd++; ++ } ++ ++ if (count > 1) { ++ AICWFDBG(LOGINFO, "Ambiguous command '%s'; possible commands:", argv[0]); ++ cmd = aic_priv_commands; ++ while (cmd->cmd) { ++ if (strncasecmp(cmd->cmd, argv[0], ++ strlen(argv[0])) == 0) { ++ AICWFDBG(LOGINFO, " %s", cmd->cmd); ++ } ++ cmd++; ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ } else if (count == 0) { ++ AICWFDBG(LOGERROR, "Unknown command '%s'\n", argv[0]); ++ } else { ++ AICWFDBG(LOGINFO, "match %s", match->cmd); ++ bytes_written = match->handler(p_rwnx_hw, argc, &argv[0], command); ++ } ++ ++ if (bytes_written < 0) ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ ++ return bytes_written; ++} ++ ++#define RWNX_COUNTRY_CODE_LEN 2 ++#define CMD_SET_COUNTRY "COUNTRY" ++#define CMD_SET_VENDOR_EX_IE "SET_VENDOR_EX_IE" ++#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" ++#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" ++#define CMD_SET_MON_FREQ "SET_MON_FREQ" ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2); ++struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, int index); ++extern int reg_regdb_size; ++ ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++extern u8_l vendor_extension_data[256]; ++extern int vendor_extension_len; ++extern int testmode = 0; ++ ++void set_vendor_extension_ie(char *command){ ++ ++ char databyte[3]={0x00, 0x00, 0x00}; ++ int skip = strlen(CMD_SET_VENDOR_EX_IE) + 1; ++ int command_index = skip; ++ int data_index = 0; ++ ++ memset(vendor_extension_data, 0, 256); ++ vendor_extension_len = 0; ++ memcpy(databyte, command + command_index, 2); ++ vendor_extension_len = command_strtoul(databyte, NULL, 16); ++ printk("%s len:%d \r\n", __func__, vendor_extension_len); ++ ++ //parser command and save data in vendor_extension_data ++ for(data_index = 0;data_index < vendor_extension_len; data_index++){ ++ command_index = command_index + 3; ++ memcpy(databyte, command + command_index, 2); ++ vendor_extension_data[data_index] = command_strtoul(databyte, NULL, 16); ++ } ++ ++} ++#endif//CONFIG_SET_VENDOR_EXTENSION_IE ++int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef); ++int rwnx_atoi2(char *value, int c_len); ++void set_mon_chan(struct rwnx_vif *vif, char *parameter){ ++ struct cfg80211_chan_def *chandef = NULL; ++ int freq = 0; ++ ++ ++ chandef = (struct cfg80211_chan_def *)vmalloc(sizeof(struct cfg80211_chan_def)); ++ memset(chandef, 0, sizeof(struct cfg80211_chan_def)); ++ chandef->chan = (struct ieee80211_channel *)vmalloc(sizeof(struct ieee80211_channel)); ++ memset(chandef->chan, 0, sizeof(struct ieee80211_channel)); ++ ++ freq = rwnx_atoi2(parameter, 4); ++ ++ if(freq <= 2484){ ++ chandef->chan->band = NL80211_BAND_2GHZ; ++ }else{ ++ chandef->chan->band = NL80211_BAND_5GHZ; ++ } ++ chandef->chan->center_freq = freq; ++ chandef->width = NL80211_CHAN_WIDTH_20; ++ chandef->center_freq1 = chandef->chan->center_freq; ++ chandef->center_freq2 = 0; ++ ++ rwnx_cfg80211_set_monitor_channel_(vif->rwnx_hw->wiphy, chandef); ++ ++ vfree(chandef->chan); ++ vfree(chandef); ++ ++} ++ ++ ++int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) ++{ ++#define PRIVATE_COMMAND_MAX_LEN 8192 ++#define PRIVATE_COMMAND_DEF_LEN 4096 ++ ++ struct rwnx_vif *vif = netdev_priv(net); ++ int ret = 0; ++ char *command = NULL; ++ int bytes_written = 0; ++ android_wifi_priv_cmd priv_cmd; ++ int buf_size = 0; ++ int skip = 0; ++ char *country = NULL; ++#ifdef CONFIG_GPIO_WAKEUP ++ int setsusp_mode; ++#endif ++ struct ieee80211_regdomain *regdomain; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ///todo: add our lock ++ //net_os_wake_lock(net); ++ ++ ++/* if (!capable(CAP_NET_ADMIN)) { ++ ret = -EPERM; ++ goto exit; ++ }*/ ++ if (!ifr->ifr_data) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++#ifdef CONFIG_COMPAT ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) ++ if (in_compat_syscall()) ++#else ++ if (is_compat_task()) ++#endif ++ { ++ compat_android_wifi_priv_cmd compat_priv_cmd; ++ if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ 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 /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ } ++ if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { ++ printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); ++ command = kmalloc((buf_size + 1), GFP_KERNEL); ++ ++ if (!command) { ++ printk("%s: failed to allocate memory\n", __FUNCTION__); ++ ret = -ENOMEM; ++ goto exit; ++ } ++ if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ command[priv_cmd.total_len] = '\0'; ++ ++ /* outputs */ ++ AICWFDBG(LOGINFO, "%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); ++ AICWFDBG(LOGINFO, "cmd = %d\n", cmd); ++ AICWFDBG(LOGINFO, "buf_size=%d\n", buf_size); ++ ++#if 1//Handle Android command ++ if(!strncasecmp(command, CMD_SET_COUNTRY, strlen(CMD_SET_COUNTRY)) && ++ strncasecmp(command, "country_set", strlen("country_set"))) { ++ skip = strlen(CMD_SET_COUNTRY) + 1; ++ country = command + skip; ++ if (!country || strlen(country) < RWNX_COUNTRY_CODE_LEN) { ++ printk("%s: invalid country code\n", __func__); ++ ret = -EINVAL; ++ goto exit; ++ } ++#if 0 ++ for(index = 0; index < reg_regdb_size; index++){ ++ regdomain = getRegdomainFromRwnxDBIndex(vif->rwnx_hw->wiphy, index); ++ if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ ++ printk("regulatory_set_wiphy_regd fail \r\n"); ++ }else{ ++ printk("regulatory_set_wiphy_regd ok \r\n"); ++ } ++ } ++#endif ++ AICWFDBG(LOGINFO, "%s country code:%c%c\n", __func__, toupper(country[0]), toupper(country[1])); ++ regdomain = getRegdomainFromRwnxDB(vif->rwnx_hw->wiphy, country); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ ++ printk("regulatory_set_wiphy_regd fail \r\n"); ++ } ++#else ++ wiphy_apply_custom_regulatory(vif->rwnx_hw->wiphy, regdomain); ++#endif ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ rwnx_radar_set_domain(&vif->rwnx_hw->radar, regdomain->dfs_region); ++#endif ++ ++#ifdef CONFIG_POWER_LIMIT ++ if (!testmode) ++ rwnx_send_me_chan_config_req(vif->rwnx_hw, country); ++#endif ++ ret = 0; ++ goto exit; ++ } ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++ else if(!strncasecmp(command, CMD_SET_VENDOR_EX_IE, strlen(CMD_SET_VENDOR_EX_IE))){ ++ set_vendor_extension_ie(command); ++ ret = 0; ++ goto exit; ++ } ++#endif//CONFIG_SET_VENDOR_EXTENSION_IE ++ else if(!strncasecmp(command, CMD_SET_AP_WPS_P2P_IE, strlen(CMD_SET_AP_WPS_P2P_IE))){ ++ ret = 0; ++ goto exit; ++ } ++ else if(!strncasecmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) && testmode == 0){ ++#ifdef AICWF_SDIO_SUPPORT ++#if defined(CONFIG_GPIO_WAKEUP) && !defined(CONFIG_AUTO_POWERSAVE) ++ skip = strlen(CMD_SETSUSPENDMODE) + 1; ++ setsusp_mode = command_strtoul((command + skip), NULL, 10); ++#ifdef AICWF_LATENCY_MODE ++ if (setsusp_mode) ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, setsusp_mode, 0); ++ else ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1, 1); ++#else ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, setsusp_mode, !setsusp_mode); ++#endif ++ #if 0 ++ if (setsusp_mode == 1) { ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); ++#endif ++ ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); ++ } ++ } ++ #endif ++ AICWFDBG(LOGINFO, "set suspend mode %d\n", setsusp_mode); ++#endif//CONFIG_GPIO_WAKEUP ++#endif ++ goto exit; ++ } ++#ifdef CONFIG_RWNX_MON_DATA ++ else if(!strncasecmp(command, CMD_SET_MON_FREQ, strlen(CMD_SET_MON_FREQ))){ ++ char *set_parameter; ++ skip = strlen(CMD_SET_MON_FREQ) + 1; ++ set_parameter = command + skip; ++ set_mon_chan(vif, set_parameter); ++ ret = 0; ++ goto exit; ++ } ++#endif ++ ++#endif//Handle Android command ++ ++ bytes_written = handle_private_cmd(net, command, priv_cmd.total_len); ++ if (bytes_written >= 0) { ++ if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { ++ command[0] = '\0'; ++ } ++ if (bytes_written >= priv_cmd.total_len) { ++ printk("%s: err. bytes_written:%d >= buf_size:%d \n", ++ __FUNCTION__, bytes_written, buf_size); ++ goto exit; ++ } ++ bytes_written++; ++ priv_cmd.used_len = bytes_written; ++ if (copy_to_user(priv_cmd.buf, command, bytes_written)) { ++ printk("%s: failed to copy data to user buffer\n", __FUNCTION__); ++ ret = -EFAULT; ++ } ++ } else { ++ /* Propagate the error */ ++ ret = bytes_written; ++ } ++ ++exit: ++ ///todo: add our unlock ++ //net_os_wake_unlock(net); ++ kfree(command); ++ return ret; ++} ++ ++#ifdef CONFIG_MCU_MESSAGE ++#define CMD_GET_VERSION_STR "GET_VERSION" ++#define CMD_GET_SSID_STR "GET_SSID" ++#define CMD_SET_SSID_STR "SET_SSID" ++#define CMD_GET_PASS_STR "GET_PASS" ++#define CMD_SET_PASS_STR "SET_PASS" ++#define CMD_GET_VAR_STR "GET_VAR" ++#define CMD_SET_VAR_STR "SET_VAR" ++ ++enum custmsg_cmd_tag ++{ ++ CUST_CMD_GET_VERSION = 0, ++ CUST_CMD_GET_SSID, ++ CUST_CMD_SET_SSID, ++ CUST_CMD_GET_PASS, ++ CUST_CMD_SET_PASS, ++ CUST_CMD_GET_VAR, ++ CUST_CMD_SET_VAR, ++ CUST_CMD_MAX ++}; ++ ++int handle_custom_msg(char *command, u32 cmd_len) ++{ ++ int bytes_read = 0, max_bytes_to_read = 0; ++ struct rwnx_hw *p_rwnx_hw = NULL; ++ u32 cmd, len = 0, flags = 0; ++ char *buf = NULL; ++ struct dbg_custom_msg_cfm *cust_msg_cfm; ++ printk("cmd,%s,%ld\n",command,strlen(command)); ++ if (strncasecmp(command, CMD_GET_VERSION_STR, strlen(CMD_GET_VERSION_STR)) == 0) { ++ cmd = CUST_CMD_GET_VERSION; ++ max_bytes_to_read = 32; // max str len for version ++ } else if (strncasecmp(command, CMD_GET_SSID_STR, strlen(CMD_GET_SSID_STR)) == 0) { ++ cmd = CUST_CMD_GET_SSID; ++ max_bytes_to_read = 48; // max str len for ssid ++ } else if (strncasecmp(command, CMD_SET_SSID_STR, strlen(CMD_SET_SSID_STR)) == 0) { ++ cmd = CUST_CMD_SET_SSID; ++ len = cmd_len - (strlen(CMD_SET_SSID_STR) + 1); ++ buf = command + (strlen(CMD_SET_SSID_STR) + 1); ++ max_bytes_to_read = 0; ++ } else if (strncasecmp(command, CMD_GET_PASS_STR, strlen(CMD_GET_PASS_STR)) == 0) { ++ cmd = CUST_CMD_GET_PASS; ++ max_bytes_to_read = 64; // max str len for PASS ++ } else if (strncasecmp(command, CMD_SET_PASS_STR, strlen(CMD_SET_PASS_STR)) == 0) { ++ cmd = CUST_CMD_SET_PASS; ++ len = cmd_len - (strlen(CMD_SET_PASS_STR) + 1); ++ buf = command + (strlen(CMD_SET_PASS_STR) + 1); ++ max_bytes_to_read = 0; ++ } else if (strncasecmp(command, CMD_GET_VAR_STR, strlen(CMD_GET_VAR_STR)) == 0) { ++ cmd = CUST_CMD_GET_VAR; ++ max_bytes_to_read = 64; // max str len for VAR ++ } else if (strncasecmp(command, CMD_SET_VAR_STR, strlen(CMD_SET_VAR_STR)) == 0) { ++ cmd = CUST_CMD_SET_VAR; ++ len = cmd_len - (strlen(CMD_SET_VAR_STR) + 1); ++ buf = command + (strlen(CMD_SET_VAR_STR) + 1); ++ max_bytes_to_read = 0; ++ } else { ++ printk("invalid cmd: %s\r\n", command); ++ return -1; ++ } ++ if (len < 0) { ++ printk("invalid len: %d\r\n", len); ++ return -3; ++ } ++ #ifdef AICWF_SDIO_SUPPORT ++ p_rwnx_hw = g_rwnx_plat->sdiodev->rwnx_hw; ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ p_rwnx_hw = g_rwnx_plat->usbdev->rwnx_hw; ++ #endif ++ cust_msg_cfm = (struct dbg_custom_msg_cfm *)kmalloc((offsetof(struct dbg_custom_msg_cfm, buf) + max_bytes_to_read), GFP_KERNEL); ++ if (cust_msg_cfm == NULL) { ++ printk("msg cfm alloc fail\r\n"); ++ return -2; ++ } ++ rwnx_send_dbg_custom_msg_req(p_rwnx_hw, cmd, buf, len, flags, cust_msg_cfm); ++ bytes_read = cust_msg_cfm->len; ++ printk("Custom msg cfm: cmd=%d, len=%d, status=%x\n", cust_msg_cfm->cmd, bytes_read, cust_msg_cfm->status); ++ if (bytes_read) { ++ memcpy(command, cust_msg_cfm->buf, bytes_read); ++ command[bytes_read] = '\0'; ++ } else { ++ command[0] = '\0'; ++ } ++ if (cust_msg_cfm->status) { ++ printk("cfm status: %x", cust_msg_cfm->status); ++ } ++ return bytes_read; ++} ++ ++int devipc_cust_msg(struct net_device *net, struct ifreq *ifr, int cmd) ++{ ++#ifdef PRIVATE_COMMAND_MAX_LEN ++#undef PRIVATE_COMMAND_MAX_LEN ++#undef PRIVATE_COMMAND_DEF_LEN ++#define PRIVATE_COMMAND_MAX_LEN 8192 ++#define PRIVATE_COMMAND_DEF_LEN 4096 ++#endif ++ int ret = 0; ++ char *command = NULL; ++ int bytes_written = 0; ++ android_wifi_priv_cmd priv_cmd; ++ int buf_size = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ///todo: add our lock ++ //net_os_wake_lock(net); ++ ++ ++/* if (!capable(CAP_NET_ADMIN)) { ++ ret = -EPERM; ++ goto exit; ++ }*/ ++ if (!ifr->ifr_data) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++#ifdef CONFIG_COMPAT ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) ++ if (in_compat_syscall()) ++#else ++ if (is_compat_task()) ++#endif ++ { ++ compat_android_wifi_priv_cmd compat_priv_cmd; ++ if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ 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 /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ } ++ if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { ++ printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); ++ command = kmalloc((buf_size + 1), GFP_KERNEL); ++ ++ if (!command) ++ { ++ printk("%s: failed to allocate memory\n", __FUNCTION__); ++ ret = -ENOMEM; ++ goto exit; ++ } ++ if (copy_from_user(command, priv_cmd.buf, priv_cmd.used_len)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ command[priv_cmd.used_len] = '\0'; ++ ++ /* outputs */ ++ printk("%s: Devipc custom msg \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); ++ printk("cmd = %x\n", cmd); ++ printk("buf_size=%d\n", buf_size); ++ ++ ++ bytes_written = handle_custom_msg(command, priv_cmd.used_len); ++ if (bytes_written >= 0) { ++ if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { ++ command[0] = '\0'; ++ } ++ if (bytes_written >= priv_cmd.total_len) { ++ printk("%s: err. bytes_written:%d >= buf_size:%d \n", ++ __FUNCTION__, bytes_written, buf_size); ++ goto exit; ++ } ++ bytes_written++; ++ priv_cmd.used_len = bytes_written; ++ if (copy_to_user(priv_cmd.buf, command, bytes_written)) { ++ printk("%s: failed to copy data to user buffer\n", __FUNCTION__); ++ ret = -EFAULT; ++ } ++ } ++ else { ++ /* Propagate the error */ ++ ret = bytes_written; ++ } ++ ++exit: ++ ///todo: add our unlock ++ //net_os_wake_unlock(net); ++ kfree(command); ++ Sreturn ret; ++} ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.h +new file mode 100644 +index 000000000000..265658ed1053 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.h +@@ -0,0 +1,33 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file private_cmd.h ++ * ++ * Copyright (C) Aicsemi 2018-2024 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _AIC_PRIV_CMD_H_ ++#define _AIC_PRIV_CMD_H_ ++ ++#include "rwnx_defs.h" ++ ++typedef struct _android_wifi_priv_cmd { ++ char *buf; ++ int used_len; ++ int total_len; ++} android_wifi_priv_cmd; ++ ++#ifdef CONFIG_COMPAT ++typedef struct _compat_android_wifi_priv_cmd { ++ compat_caddr_t buf; ++ int used_len; ++ int total_len; ++} compat_android_wifi_priv_cmd; ++#endif /* CONFIG_COMPAT */ ++ ++int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd); ++ ++#endif /* _AIC_PRIV_CMD_H_ */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c +new file mode 100644 +index 000000000000..004a1a3cfdc9 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c +@@ -0,0 +1,1247 @@ ++#include "aic_vendor.h" ++#include "rwnx_defs.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_version_gen.h" ++#include "rwnx_msg_tx.h" ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ ++static struct wifi_ring_buffer_status ring_buffer[] = { ++ { ++ .name = "aicwf_ring_buffer0", ++ .flags = 0, ++ .ring_id = 0, ++ .verbose_level = 0, ++ .written_bytes = 0, ++ .read_bytes = 0, ++ .written_records = 0, ++ }, ++}; ++ ++static struct wlan_driver_wake_reason_cnt_t wake_reason_cnt = { ++ .total_cmd_event_wake = 10, ++}; ++ ++#endif ++ ++#ifdef CONFIG_APF ++#define AIC_APF_MEM_SIZE 2048 ++#define AIC_APF_VERSION 4 ++ ++static char apfProgram[AIC_APF_MEM_SIZE]; ++#endif ++ ++int aic_dev_start_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 mkeep_alive_id, u8 *ip_pkt, u16 ip_pkt_len, u8 *src_mac, u8 *dst_mac, u32 period_msec) ++{ ++ u8 *data, *pos; ++ ++ data = kzalloc(ip_pkt_len + 14, GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ pos = data; ++ memcpy(pos, dst_mac, 6); ++ pos += 6; ++ memcpy(pos, src_mac, 6); ++ pos += 6; ++ /* Mapping Ethernet type (ETHERTYPE_IP: 0x0800) */ ++ *(pos++) = 0x08; ++ *(pos++) = 0x00; ++ ++ /* Mapping IP pkt */ ++ memcpy(pos, ip_pkt, ip_pkt_len); ++ pos += ip_pkt_len; ++ ++ //add send 802.3 pkt(raw data) ++ kfree(data); ++ ++ return 0; ++} ++ ++int aic_dev_stop_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, u8 mkeep_alive_id) ++{ ++ int res = -1; ++ ++ /* ++ * The mkeep_alive packet is for STA interface only; if the bss is configured as AP, ++ * dongle shall reject a mkeep_alive request. ++ */ ++ if (rwnx_vif->wdev.iftype != NL80211_IFTYPE_STATION) ++ return res; ++ ++ printk("%s execution\n", __func__); ++ ++ //add send stop keep alive ++ res = 0; ++ return res; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++static int aicwf_vendor_start_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* max size of IP packet for keep alive */ ++ const int MKEEP_ALIVE_IP_PKT_MAX = 256; ++ ++ int ret = 0, rem, type; ++ u8 mkeep_alive_id = 0; ++ u8 *ip_pkt = NULL; ++ u16 ip_pkt_len = 0; ++ u8 src_mac[6]; ++ u8 dst_mac[6]; ++ u32 period_msec = 0; ++ const struct nlattr *iter; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; ++ printk("%s\n", __func__); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case MKEEP_ALIVE_ATTRIBUTE_ID: ++ mkeep_alive_id = nla_get_u8(iter); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN: ++ ip_pkt_len = nla_get_u16(iter); ++ if (ip_pkt_len > MKEEP_ALIVE_IP_PKT_MAX) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_IP_PKT: ++ if (!ip_pkt_len) { ++ ret = -EINVAL; ++ printk("ip packet length is 0\n"); ++ goto exit; ++ } ++ ip_pkt = (u8 *)kzalloc(ip_pkt_len, kflags); ++ if (ip_pkt == NULL) { ++ ret = -ENOMEM; ++ printk("Failed to allocate mem for ip packet\n"); ++ goto exit; ++ } ++ memcpy(ip_pkt, (u8 *)nla_data(iter), ip_pkt_len); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR: ++ memcpy(src_mac, nla_data(iter), 6); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR: ++ memcpy(dst_mac, nla_data(iter), 6); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC: ++ period_msec = nla_get_u32(iter); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ ret = -EINVAL; ++ goto exit; ++ } ++ } ++ ++ if (ip_pkt == NULL) { ++ ret = -EINVAL; ++ printk("ip packet is NULL\n"); ++ goto exit; ++ } ++ ++ ret = aic_dev_start_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id, ip_pkt, ip_pkt_len, src_mac, ++ dst_mac, period_msec); ++ if (ret < 0) { ++ printk("start_mkeep_alive is failed ret: %d\n", ret); ++ } ++ ++exit: ++ if (ip_pkt) { ++ kfree(ip_pkt); ++ } ++ ++ return ret; ++} ++ ++static int aicwf_vendor_stop_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ u8 mkeep_alive_id = 0; ++ const struct nlattr *iter; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ ++ printk("%s\n", __func__); ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case MKEEP_ALIVE_ATTRIBUTE_ID: ++ mkeep_alive_id = nla_get_u8(iter); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ ++ ret = aic_dev_stop_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id); ++ if (ret < 0) { ++ printk("stop_mkeep_alive is failed ret: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++static int aicwf_vendor_get_ver(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ int payload = 0; ++ char version[128]; ++ int attr = -1; ++ struct sk_buff *reply; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_DRIVER_VER: ++ memcpy(version, RWNX_VERS_BANNER, sizeof(RWNX_VERS_BANNER)); ++ payload = strlen(version); ++ attr = LOGGER_ATTRIBUTE_DRIVER_VER; ++ break; ++ case LOGGER_ATTRIBUTE_FW_VER: ++ memcpy(version, wiphy->fw_version, sizeof(wiphy->fw_version)); ++ payload = strlen(version); ++ attr = LOGGER_ATTRIBUTE_FW_VER; ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ if (attr < 0) ++ return -EINVAL; ++ ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put(reply, attr, ++ payload, version)) { ++ wiphy_err(wiphy, "%s put version error\n", __func__); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "%s reply cmd error\n", __func__); ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_subcmd_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ struct sk_buff *reply; ++ int num_channels = 0; ++ int *channel_list = NULL; ++ int payload; ++ int i = 0; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ]; ++ ++ num_channels += rwnx_band_2GHz->n_channels; ++ num_channels += (rwnx_hw->band_5g_support) ? rwnx_band_5GHz->n_channels : 0; ++ ++ channel_list = (int *)kzalloc(sizeof(int) * num_channels, GFP_KERNEL); ++ if (!channel_list) ++ return -ENOMEM; ++ ++ for (i = 0; i < rwnx_band_2GHz->n_channels; i++) ++ channel_list[i] = rwnx_band_2GHz->channels[i].center_freq; ++ ++ for (; rwnx_hw->band_5g_support && i < num_channels; i++) ++ channel_list[i] = rwnx_band_5GHz->channels[i].center_freq; ++ ++ payload = sizeof(num_channels) + sizeof(int) * num_channels + 4; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case GSCAN_ATTRIBUTE_BAND: ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put_u32(reply, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels)) ++ goto out_put_fail; ++ ++ if (nla_put(reply, GSCAN_ATTRIBUTE_CHANNEL_LIST, sizeof(int) * num_channels, channel_list)) ++ goto out_put_fail; ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "%s reply cmd error\n", __func__); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ kfree(channel_list); ++ return ret; ++ ++out_put_fail: ++ kfree(channel_list); ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2); ++ ++static int aicwf_vendor_subcmd_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ struct ieee80211_regdomain *regdomain; ++ char *country = NULL; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case ANDR_WIFI_ATTRIBUTE_COUNTRY: ++ printk("%s(%d), ANDR_WIFI_ATTRIBUTE_COUNTRY: %s\n", __func__, __LINE__, (char *)nla_data(iter)); ++ country = (char *)nla_data(iter); ++ ++ AICWFDBG(LOGINFO, "%s country code:%c%c\n", __func__, ++ country[0], ++ country[1]); ++ ++ regdomain = getRegdomainFromRwnxDB(rwnx_hw->wiphy, country); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ if((ret = regulatory_set_wiphy_regd(rwnx_hw->wiphy, regdomain))){ ++ printk("regulatory_set_wiphy_regd fail \r\n"); ++ } ++#else ++ wiphy_apply_custom_regulatory(rwnx_hw->wiphy, regdomain); ++#endif ++ ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future! ++ */ ++ ++ return ret; ++} ++ ++static int aicwf_vendor_logger_trigger_memory_dump(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* TODO ++ * Add handle in the future! ++ */ ++ return 0; ++} ++ ++static int aicwf_vendor_subcmd_get_feature_set(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t feature = 0, payload; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ payload = sizeof(feature); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ /* TODO ++ * Add handle in the future! ++ */ ++ /*bit 1:Basic infrastructure mode*/ ++ if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) ++ feature |= WIFI_FEATURE_INFRA; ++ ++ /*bit 2:Support for 5 GHz Band*/ ++ if (rwnx_hw->band_5g_support) ++ feature |= WIFI_FEATURE_INFRA_5G; ++ ++ /*bit3:HOTSPOT is a supplicant feature, enable it by default*/ ++ feature |= WIFI_FEATURE_HOTSPOT; ++ ++ /*bit 4:P2P*/ ++ if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) && ++ (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) ++ feature |= WIFI_FEATURE_P2P; ++ ++ /*bit 5:soft AP feature supported*/ ++ if (wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) ++ feature |= WIFI_FEATURE_SOFT_AP; ++ ++ /*bit 18:WiFi Logger*/ ++ feature |= WIFI_FEATURE_LOGGER; ++ ++ /*bit 21:WiFi mkeep_alive*/ ++ feature |= WIFI_FEATURE_MKEEP_ALIVE; ++ ++#ifdef AICWF_LATENCY_MODE ++ feature |= WIFI_FEATURE_SET_LATENCY_MODE; ++#endif ++ if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) { ++ wiphy_err(wiphy, "%s put u32 error\n", __func__); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "%s reply cmd error\n", __func__); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_get_feature(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t feature = 0, payload; ++ ++ payload = sizeof(feature); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ feature |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED; ++ feature |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED; ++ ++ /*vts will test wake reason state function*/ ++ feature |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED; ++ ++ if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) { ++ wiphy_err(wiphy, "put skb u32 failed\n"); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_get_ring_status(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t payload; ++ uint32_t ring_buffer_nums = sizeof(ring_buffer) / sizeof(ring_buffer[0]); ++ ++ payload = sizeof(ring_buffer_nums) + sizeof(ring_buffer); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put_u32(reply, LOGGER_ATTRIBUTE_RING_NUM, ring_buffer_nums)) { ++ wiphy_err(wiphy, "put skb u32 failed\n"); ++ goto out_put_fail; ++ } ++ ++ if (nla_put(reply, LOGGER_ATTRIBUTE_RING_STATUS, sizeof(ring_buffer), ring_buffer)) { ++ wiphy_err(wiphy, "put skb failed\n"); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_start_logging(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type, intval, size, i; ++ const struct nlattr *iter; ++ struct wifi_ring_buffer_status rb; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_LOG_LEVEL: ++ rb.verbose_level = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_RING_FLAGS: ++ rb.flags = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_LOG_TIME_INTVAL: ++ intval = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE: ++ size = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_RING_NAME: ++ strcpy(rb.name, nla_data(iter)); ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ ret = -EINVAL; ++ for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) { ++ if (strcmp(rb.name, ring_buffer[i].name) == 0) { ++ ret = 0; ++ break; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ ++ return ret; ++} ++ ++static int aicwf_vendor_logger_get_ring_data(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type, i; ++ const struct nlattr *iter; ++ struct wifi_ring_buffer_status rb; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_RING_NAME: ++ strcpy(rb.name, nla_data(iter)); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ ret = -EINVAL; ++ for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) { ++ if (strcmp(rb.name, ring_buffer[i].name) == 0) { ++ ret = 0; ++ break; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ ++ return ret; ++} ++ ++static int aicwf_vendor_logger_get_wake_reason_stats(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t payload; ++ ++ payload = sizeof(wake_reason_cnt.total_cmd_event_wake); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ if (nla_put_u32(reply, WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT, wake_reason_cnt.total_cmd_event_wake)) ++ goto out_put_fail; ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_get_tx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++#if 0 ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ int fate_num; ++ int fate_data; ++ ++ AICWFDBG(LOGDEBUG, "%s Enter\r\n", __func__); ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_PKT_FATE_NUM: ++ fate_num = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_PKT_FATE_DATA: ++ fate_data = nla_get_u64(iter); ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++#endif ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++static int aicwf_vendor_logger_get_rx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++#if 0 ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ int fate_num; ++ int fate_data; ++ ++ AICWFDBG(LOGDEBUG, "%s Enter\r\n", __func__); ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_PKT_FATE_NUM: ++ fate_num = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_PKT_FATE_DATA: ++ fate_data = nla_get_u64(iter); ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++#endif ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++ ++#ifdef AICWF_LATENCY_MODE ++static int aicwf_vendor_subcmd_set_latency_mode(struct wiphy *wiphy, ++ struct wireless_dev *wdev, const void *data, int len) ++{ ++ int err = 0, rem, type; ++ u32 latency_mode; ++ const struct nlattr *iter; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case ANDR_WIFI_ATTRIBUTE_LATENCY_MODE: ++ latency_mode = nla_get_u32(iter); ++ printk("%s,Setting latency mode %d\n", __func__, latency_mode); ++ #ifdef AICWF_SDIO_SUPPORT ++ if (latency_mode) { ++ rwnx_send_me_set_lp_level(rwnx_hw, 0, 1); ++ } else { ++ rwnx_send_me_set_lp_level(rwnx_hw, 1, 0); ++ } ++ #endif ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return err; ++ } ++ } ++ ++ return err; ++} ++#endif ++ ++static int aicwf_vendor_logger_start_pkt_fate_monitoring(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++#ifdef CONFIG_APF ++static int aicwf_vendor_apf_subcmd_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t payload; ++ printk("%s\n", __func__); ++ ++ /* APF_ATTRIBUTE_VERSION + APF_ATTRIBUTE_MAX_LEN */ ++ payload = sizeof(u32) * 2; ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put_u32(reply, APF_ATTRIBUTE_VERSION, AIC_APF_VERSION)) ++ goto out_put_fail; ++ ++ if (nla_put_u32(reply, APF_ATTRIBUTE_MAX_LEN, AIC_APF_MEM_SIZE)) ++ goto out_put_fail; ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_apf_set_filter(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ unsigned int mProgramLen = 0; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ printk("%s\n", __func__); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case APF_ATTRIBUTE_PROGRAM_LEN: ++ memcpy(&mProgramLen, nla_data(iter), sizeof(unsigned int)); ++ ret = (mProgramLen > 0 && mProgramLen <= AIC_APF_MEM_SIZE) ? 0 : -EINVAL; ++ break; ++ case APF_ATTRIBUTE_PROGRAM: ++ if (mProgramLen > AIC_APF_MEM_SIZE || mProgramLen == 0) { ++ printk("%s: apf program size invalid: %d (should > 0 and <= %d)\n", ++ __func__, mProgramLen, AIC_APF_MEM_SIZE); ++ return -EINVAL; ++ } ++ ++ memcpy(apfProgram, nla_data(iter), mProgramLen); ++ ret = rwnx_send_set_apf_prog_req(rwnx_hw, apfProgram, mProgramLen); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ return ret; ++} ++ ++static int aicwf_vendor_apf_read_filter_data(struct wiphy *wiphy, ++ struct wireless_dev *wdev, const void *data, int len) ++{ ++ struct sk_buff *reply; ++ int ret, payload, apf_mem_size; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ printk("%s\n", __func__); ++ ++ apf_mem_size = AIC_APF_MEM_SIZE; ++ payload = sizeof(u32) + apf_mem_size; ++ ++ ret = rwnx_send_get_apf_prog_req(rwnx_hw, apfProgram, apf_mem_size); ++ if (ret != 0) { ++ pr_err("%s, Failed to read apf mem from firmware, ret = %d\n", __func__, ret); ++ return ret; ++ } ++ ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ if (!reply) ++ return -ENOMEM; ++ ++ ret = nla_put_u32(reply, APF_ATTRIBUTE_PROGRAM_LEN, apf_mem_size); ++ if (ret < 0) { ++ pr_err("%s, Failed to put APF_ATTRIBUTE_MAX_LEN, ret = %d\n", __func__, ret); ++ goto out_put_fail; ++ } ++ ++ /* copy the full apf mem */ ++ ret = nla_put(reply, APF_ATTRIBUTE_PROGRAM, apf_mem_size, &apfProgram[0]); ++ if (ret < 0) { ++ pr_err("%s, Failed to put APF_ATTRIBUTE_PROGRAM, ret = %d\n", __func__, ret); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++#endif ++ ++static int aicwf_vendor_sub_cmd_set_mac(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ u8 mac[ETH_ALEN]; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR: ++ memcpy(mac, nla_data(iter), ETH_ALEN); ++ printk("%s, %02X:%02X:%02X:%02X:%02X:%02X\n", __func__, ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ ++ return ret; ++} ++#endif ++ ++static const struct nla_policy ++aicwf_cfg80211_mkeep_alive_policy[MKEEP_ALIVE_ATTRIBUTE_MAX+1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [MKEEP_ALIVE_ATTRIBUTE_ID] = { .type = NLA_U8 }, ++ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = { .type = NLA_MSECS }, ++ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = { .type = NLA_U16 }, ++ [MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = { .type = NLA_MSECS, ++ .len = ETH_ALEN }, ++ [MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = { .type = NLA_MSECS, ++ .len = ETH_ALEN }, ++ [MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = { .type = NLA_U32 }, ++}; ++ ++static const struct nla_policy ++aicwf_cfg80211_logger_policy[LOGGER_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [LOGGER_ATTRIBUTE_DRIVER_VER] = { .type = NLA_BINARY }, ++ [LOGGER_ATTRIBUTE_FW_VER] = { .type = NLA_BINARY }, ++ [LOGGER_ATTRIBUTE_LOG_LEVEL] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_RING_FLAGS] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_LOG_TIME_INTVAL] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_RING_NAME] = { .type = NLA_STRING }, ++}; ++ ++#ifdef CONFIG_APF ++static const struct nla_policy ++aicwf_cfg80211_apf_policy[APF_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [APF_ATTRIBUTE_VERSION] = {.type = NLA_U32 }, ++ [APF_ATTRIBUTE_MAX_LEN] = {.type = NLA_U32 }, ++ [APF_ATTRIBUTE_PROGRAM] = { .type = NLA_BINARY }, ++ [APF_ATTRIBUTE_PROGRAM_LEN] = { .type = NLA_U32 }, ++}; ++#endif ++ ++static const struct nla_policy ++aicwf_cfg80211_subcmd_policy[GSCAN_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [GSCAN_ATTRIBUTE_BAND] = { .type = NLA_U32 }, ++}; ++ ++static const struct nla_policy ++aicwf_cfg80211_andr_wifi_policy[ANDR_WIFI_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [ANDR_WIFI_ATTRIBUTE_COUNTRY] = { .type = NLA_STRING }, ++}; ++ ++static const struct nla_policy ++aicwf_cfg80211_subcmd_set_mac_policy[WIFI_VENDOR_ATTR_DRIVER_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR] = { .type = NLA_MSECS, .len = ETH_ALEN }, ++}; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++static int aicwf_dump_interface(struct wiphy *wiphy, ++ struct wireless_dev *wdev, struct sk_buff *skb, ++ const void *data, int data_len, ++ unsigned long *storage) ++{ ++ return 0; ++} ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++const struct wiphy_vendor_command aicwf_vendor_cmd[] = { ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_start_mkeep_alive, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_mkeep_alive_policy, ++ .maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_stop_mkeep_alive, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_mkeep_alive_policy, ++ .maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_VER ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_get_ver, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_logger_policy, ++ .maxattr = LOGGER_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_get_channel_list, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_subcmd_policy, ++ .maxattr = GSCAN_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_set_country_code, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_andr_wifi_policy, ++ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_TRIGGER_MEM_DUMP ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_trigger_memory_dump, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_GET_FEATURE_SET ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_get_feature_set, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_FEATURE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_feature, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_RING_STATUS ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_ring_status, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_START_LOGGING ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_start_logging, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_logger_policy, ++ .maxattr = LOGGER_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_RING_DATA ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_ring_data, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_logger_policy, ++ .maxattr = LOGGER_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_WAKE_REASON_STATS ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_wake_reason_stats, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++#ifdef CONFIG_APF ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = APF_SUBCMD_GET_CAPABILITIES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_apf_subcmd_get_capabilities, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_apf_policy, ++ .maxattr = APF_ATTRIBUTE_MAX, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = APF_SUBCMD_SET_FILTER ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_apf_set_filter, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_apf_policy, ++ .maxattr = APF_ATTRIBUTE_MAX, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = APF_SUBCMD_READ_FILTER_DATA ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_apf_read_filter_data, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) ++ .policy = aicwf_cfg80211_apf_policy, ++ .maxattr = APF_ATTRIBUTE_MAX ++#endif /* LINUX_VERSION >= 5.3 */ ++ }, ++#endif ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_START_PKT_FATE_MONITORING ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_start_pkt_fate_monitoring, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_TX_PKT_FATES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_tx_pkt_fates, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_RX_PKT_FATES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_rx_pkt_fates, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = VENDOR_NL80211_SUBCMD_SET_MAC ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = aicwf_vendor_sub_cmd_set_mac, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_subcmd_set_mac_policy, ++ .maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX, ++#endif ++ }, ++ { ++ { ++ .vendor_id = BRCM_OUI, ++ .subcmd = VENDOR_NL80211_SUBCMD_SET_MAC ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = aicwf_vendor_sub_cmd_set_mac, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_subcmd_set_mac_policy, ++ .maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX, ++#endif ++ }, ++#ifdef AICWF_LATENCY_MODE ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_SET_LATENCY_MODE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_set_latency_mode, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) ++ .policy = aicwf_cfg80211_andr_wifi_policy, ++ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX ++#endif /* LINUX_VERSION >= 5.3 */ ++ }, ++#endif ++}; ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++static const struct nl80211_vendor_cmd_info aicwf_vendor_events[] = { ++}; ++#endif ++ ++int aicwf_vendor_init(struct wiphy *wiphy) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ wiphy->vendor_commands = aicwf_vendor_cmd; ++ wiphy->n_vendor_commands = ARRAY_SIZE(aicwf_vendor_cmd); ++ wiphy->vendor_events = aicwf_vendor_events; ++ wiphy->n_vendor_events = ARRAY_SIZE(aicwf_vendor_events); ++#endif ++ return 0; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h +new file mode 100644 +index 000000000000..996edefa812e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h +@@ -0,0 +1,363 @@ ++#ifndef _AIC_VENDOR_H ++#define _AIC_VENDOR_H ++ ++#include ++ ++#define GOOGLE_OUI 0x001A11 ++#define BRCM_OUI 0x001018 ++ ++typedef enum { ++ START_MKEEP_ALIVE, ++ STOP_MKEEP_ALIVE, ++} GetCmdType; ++ ++typedef enum { ++ /* don't use 0 as a valid subcommand */ ++ VENDOR_NL80211_SUBCMD_UNSPECIFIED, ++ ++ /* define all vendor startup commands between 0x0 and 0x0FFF */ ++ VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001, ++ VENDOR_NL80211_SUBCMD_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 NearbyDiscovery related commands between 0x1100 and 0x11FF */ ++ ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100, ++ ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x11FF, ++ ++ /* 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, ++ ++ /* define all NAN related commands between 0x1700 and 0x17FF */ ++ ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700, ++ ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF, ++ ++ /* define all Android Packet Filter related commands between 0x1800 and 0x18FF */ ++ ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800, ++ ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF, ++ ++ /* This is reserved for future usage */ ++ ++} ANDROID_VENDOR_SUB_COMMAND; ++ ++typedef enum { ++ WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, ++ WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE, ++} WIFI_OFFLOAD_SUB_COMMAND; ++ ++ ++enum mkeep_alive_attributes { ++ MKEEP_ALIVE_ATTRIBUTE_ID = 0x1, ++ MKEEP_ALIVE_ATTRIBUTE_IP_PKT, ++ MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, ++ MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, ++ MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, ++ MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, ++ MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST, ++ MKEEP_ALIVE_ATTRIBUTE_MAX = MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST - 1 ++}; ++ ++enum debug_sub_command { ++ LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, ++ LOGGER_TRIGGER_MEM_DUMP, ++ LOGGER_GET_MEM_DUMP, ++ LOGGER_GET_VER, ++ LOGGER_GET_RING_STATUS, ++ LOGGER_GET_RING_DATA, ++ LOGGER_GET_FEATURE, ++ LOGGER_RESET_LOGGING, ++ LOGGER_TRIGGER_DRIVER_MEM_DUMP, ++ LOGGER_GET_DRIVER_MEM_DUMP, ++ LOGGER_START_PKT_FATE_MONITORING, ++ LOGGER_GET_TX_PKT_FATES, ++ LOGGER_GET_RX_PKT_FATES, ++ LOGGER_GET_WAKE_REASON_STATS, ++ LOGGER_DEBUG_GET_DUMP, ++ LOGGER_FILE_DUMP_DONE_IND, ++ LOGGER_SET_HAL_START, ++ LOGGER_HAL_STOP, ++ LOGGER_SET_HAL_PID, ++}; ++ ++enum logger_attributes { ++ LOGGER_ATTRIBUTE_INVALID = 0, ++ LOGGER_ATTRIBUTE_DRIVER_VER, ++ LOGGER_ATTRIBUTE_FW_VER, ++ LOGGER_ATTRIBUTE_RING_ID, ++ LOGGER_ATTRIBUTE_RING_NAME, ++ LOGGER_ATTRIBUTE_RING_FLAGS, ++ LOGGER_ATTRIBUTE_LOG_LEVEL, ++ LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, ++ LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, ++ LOGGER_ATTRIBUTE_FW_DUMP_LEN, ++ LOGGER_ATTRIBUTE_FW_DUMP_DATA, ++ // LOGGER_ATTRIBUTE_FW_ERR_CODE, ++ LOGGER_ATTRIBUTE_RING_DATA, ++ LOGGER_ATTRIBUTE_RING_STATUS, ++ LOGGER_ATTRIBUTE_RING_NUM, ++ LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN, ++ LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA, ++ LOGGER_ATTRIBUTE_PKT_FATE_NUM, ++ LOGGER_ATTRIBUTE_PKT_FATE_DATA, ++ LOGGER_ATTRIBUTE_AFTER_LAST, ++ LOGGER_ATTRIBUTE_MAX = LOGGER_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++#ifdef CONFIG_APF ++enum wifi_apf_attr { ++ APF_ATTRIBUTE_VERSION, ++ APF_ATTRIBUTE_MAX_LEN, ++ APF_ATTRIBUTE_PROGRAM, ++ APF_ATTRIBUTE_PROGRAM_LEN, ++ APF_ATTRIBUTE_LAST, ++ APF_ATTRIBUTE_MAX = APF_ATTRIBUTE_LAST - 1, ++}; ++#endif ++ ++enum wifi_sub_command { ++ 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 */ ++ GSCAN_SUBCMD_GET_CHANNEL_LIST, /* 0x1009 */ ++ WIFI_SUBCMD_GET_FEATURE_SET, /* 0x100A */ ++ WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x100B */ ++ WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x100C */ ++ WIFI_SUBCMD_NODFS_SET, /* 0x100D */ ++ WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x100E */ ++ /* Add more sub commands here */ ++ GSCAN_SUBCMD_SET_EPNO_SSID, /* 0x100F */ ++ WIFI_SUBCMD_SET_SSID_WHITE_LIST, /* 0x1010 */ ++ WIFI_SUBCMD_SET_ROAM_PARAMS, /* 0x1011 */ ++ WIFI_SUBCMD_ENABLE_LAZY_ROAM, /* 0x1012 */ ++ WIFI_SUBCMD_SET_BSSID_PREF, /* 0x1013 */ ++ WIFI_SUBCMD_SET_BSSID_BLACKLIST, /* 0x1014 */ ++ GSCAN_SUBCMD_ANQPO_CONFIG, /* 0x1015 */ ++ WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x1016 */ ++ WIFI_SUBCMD_CONFIG_ND_OFFLOAD, /* 0x1017 */ ++ WIFI_SUBCMD_SET_LATENCY_MODE, /* 0x1018 */ ++ /* Add more sub commands here */ ++ GSCAN_SUBCMD_MAX, ++ APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START, ++ APF_SUBCMD_SET_FILTER, ++#ifdef CONFIG_APF ++ APF_SUBCMD_READ_FILTER_DATA, ++#endif ++}; ++ ++enum gscan_attributes { ++ 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_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, ++ ++ 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, ++ ++ /* remaining reserved for additional attributes */ ++ 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_NUM_CHANNELS, ++ GSCAN_ATTRIBUTE_CHANNEL_LIST, ++ GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, ++ ++ GSCAN_ATTRIBUTE_AFTER_LAST, ++ GSCAN_ATTRIBUTE_MAX = GSCAN_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++enum andr_wifi_attributes { ++ ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, ++ ANDR_WIFI_ATTRIBUTE_FEATURE_SET, ++ ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, ++ ANDR_WIFI_ATTRIBUTE_NODFS_SET, ++ ANDR_WIFI_ATTRIBUTE_COUNTRY, ++ ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE, ++ ANDR_WIFI_ATTRIBUTE_LATENCY_MODE, ++ // Add more attribute here ++ ANDR_WIFI_ATTRIBUTE_AFTER_LAST, ++ ANDR_WIFI_ATTRIBUTE_MAX = ANDR_WIFI_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++enum wifi_support_feature { ++ /* Feature enums */ ++ WIFI_FEATURE_INFRA = 0x0001, /* Basic infrastructure mode */ ++ WIFI_FEATURE_INFRA_5G = 0x0002, /* Support for 5, GHz Band */ ++ WIFI_FEATURE_HOTSPOT = 0x0004, /* Support for GAS/ANQP */ ++ WIFI_FEATURE_P2P = 0x0008, /* Wifi-Direct */ ++ WIFI_FEATURE_SOFT_AP = 0x0010, /* Soft AP */ ++ WIFI_FEATURE_GSCAN = 0x0020, /* Google-Scan APIs */ ++ WIFI_FEATURE_NAN = 0x0040, /* Neighbor Awareness Networking */ ++ WIFI_FEATURE_D2D_RTT = 0x0080, /* Device-to-device RTT */ ++ WIFI_FEATURE_D2AP_RTT = 0x0100, /* Device-to-AP RTT */ ++ WIFI_FEATURE_BATCH_SCAN = 0x0200, /* Batched Scan (legacy) */ ++ WIFI_FEATURE_PNO = 0x0400, /* Preferred network offload */ ++ WIFI_FEATURE_ADDITIONAL_STA = 0x0800, /* Support for two STAs */ ++ WIFI_FEATURE_TDLS = 0x1000, /* Tunnel directed link setup */ ++ WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000, /* Support for TDLS off channel */ ++ WIFI_FEATURE_EPR = 0x4000, /* Enhanced power reporting */ ++ WIFI_FEATURE_AP_STA = 0x8000, /* Support for AP STA Concurrency */ ++ WIFI_FEATURE_LINK_LAYER_STATS = 0x10000, /* Support for Linkstats */ ++ WIFI_FEATURE_LOGGER = 0x20000, /* WiFi Logger */ ++ WIFI_FEATURE_HAL_EPNO = 0x40000, /* WiFi PNO enhanced */ ++ WIFI_FEATURE_RSSI_MONITOR = 0x80000, /* RSSI Monitor */ ++ WIFI_FEATURE_MKEEP_ALIVE = 0x100000, /* WiFi mkeep_alive */ ++ WIFI_FEATURE_CONFIG_NDO = 0x200000, /* ND offload configure */ ++ WIFI_FEATURE_TX_TRANSMIT_POWER = 0x400000, /* Capture Tx transmit power levels */ ++ WIFI_FEATURE_CONTROL_ROAMING = 0x800000, /* Enable/Disable firmware roaming */ ++ WIFI_FEATURE_IE_WHITELIST = 0x1000000, /* Support Probe IE white listing */ ++ WIFI_FEATURE_SCAN_RAND = 0x2000000, /* Support MAC & Probe Sequence Number randomization */ ++ WIFI_FEATURE_SET_LATENCY_MODE = 0x40000000, /* Support Latency mode setting */ ++ WIFI_FEATURE_INVALID = 0xFFFFFFFF, /* Invalid Feature */ ++}; ++ ++enum wifi_logger_feature { ++ WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), // Memory dump of FW ++ WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), // PKT status ++ WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), // Connectivity event ++ WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), // POWER of Driver ++ WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), // WAKE LOCK of Driver ++ WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), // verbose log of FW ++ WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), // monitor the health of FW ++ WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), // dumps driver state ++ WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)), // tracks connection packets' fate ++}; ++ ++enum wake_stats_attributes { ++ WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT, ++ WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE, ++ WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT, ++ WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED, ++ WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW, ++ WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE, ++ WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT, ++ WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED, ++ WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE, ++ WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT, ++ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT, ++ WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS, ++ WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT, ++ WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT, ++ WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT, ++ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO, ++ WAKE_STAT_ATTRIBUTE_AFTER_LAST, ++ WAKE_STAT_ATTRIBUTE_MAX = WAKE_STAT_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++enum vendor_nl80211_subcmd { ++ /* copied from wpa_supplicant brcm definations */ ++ VENDOR_NL80211_SUBCMD_UNSPEC = 0, ++ VENDOR_NL80211_SUBCMD_SET_PMK = 4, ++ VENDOR_NL80211_SUBCMD_SET_MAC = 6, ++ VENDOR_NL80211_SCMD_ACS = 9, ++ VENDOR_NL80211_SCMD_MAX = 10, ++}; ++ ++enum nl80211_vendor_subcmd_attributes { ++ WIFI_VENDOR_ATTR_DRIVER_CMD = 0, ++ WIFI_VENDOR_ATTR_DRIVER_KEY_PMK = 1, ++ WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR = 3, ++ WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST = 5, ++ WIFI_VENDOR_ATTR_DRIVER_MAX = ++ WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST - 1, ++}; ++ ++typedef int wifi_ring_buffer_id; ++ ++struct wifi_ring_buffer_status { ++ u8 name[32]; ++ u32 flags; ++ wifi_ring_buffer_id ring_id; ++ u32 ring_buffer_byte_size; ++ u32 verbose_level; ++ u32 written_bytes; ++ u32 read_bytes; ++ u32 written_records; ++}; ++ ++struct rx_data_cnt_details_t { ++ int rx_unicast_cnt; /*Total rx unicast packet which woke up host */ ++ int rx_multicast_cnt; /*Total rx multicast packet which woke up host */ ++ int rx_broadcast_cnt; /*Total rx broadcast packet which woke up host */ ++}; ++ ++struct rx_wake_pkt_type_classification_t { ++ int icmp_pkt; /*wake icmp packet count */ ++ int icmp6_pkt; /*wake icmp6 packet count */ ++ int icmp6_ra; /*wake icmp6 RA packet count */ ++ int icmp6_na; /*wake icmp6 NA packet count */ ++ int icmp6_ns; /*wake icmp6 NS packet count */ ++ //ToDo: Any more interesting classification to add? ++}; ++ ++struct rx_multicast_cnt_t{ ++ int ipv4_rx_multicast_addr_cnt; /*Rx wake packet was ipv4 multicast */ ++ int ipv6_rx_multicast_addr_cnt; /*Rx wake packet was ipv6 multicast */ ++ int other_rx_multicast_addr_cnt;/*Rx wake packet was non-ipv4 and non-ipv6*/ ++}; ++ ++struct wlan_driver_wake_reason_cnt_t { ++ int total_cmd_event_wake; /* Total count of cmd event wakes */ ++ int *cmd_event_wake_cnt; /* Individual wake count array, each index a reason */ ++ int cmd_event_wake_cnt_sz; /* Max number of cmd event wake reasons */ ++ int cmd_event_wake_cnt_used; /* Number of cmd event wake reasons specific to the driver */ ++ ++ int total_driver_fw_local_wake; /* Total count of drive/fw wakes, for local reasons */ ++ int *driver_fw_local_wake_cnt; /* Individual wake count array, each index a reason */ ++ int driver_fw_local_wake_cnt_sz; /* Max number of local driver/fw wake reasons */ ++ int driver_fw_local_wake_cnt_used; /* Number of local driver/fw wake reasons specific to the driver */ ++ ++ int total_rx_data_wake; /* total data rx packets, that woke up host */ ++ struct rx_data_cnt_details_t rx_wake_details; ++ struct rx_wake_pkt_type_classification_t rx_wake_pkt_classification_info; ++ struct rx_multicast_cnt_t rx_multicast_wake_pkt_info; ++}; ++ ++typedef struct wl_mkeep_alive_pkt { ++ u16 version; /* Version for mkeep_alive */ ++ u16 length; /* length of fixed parameters in the structure */ ++ u32 period_msec; /* high bit on means immediate send */ ++ u16 len_bytes; ++ u8 keep_alive_id; /* 0 - 3 for N = 4 */ ++ u8 data[1]; ++} wl_mkeep_alive_pkt_t; ++ ++#endif /* _AIC_VENDOR_H */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c +new file mode 100644 +index 000000000000..8dee7597efad +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c +@@ -0,0 +1,166 @@ ++#include "rwnx_main.h" ++#include "rwnx_msg_tx.h" ++#include "reg_access.h" ++#include "aicwf_compat_8800d80.h" ++ ++#define FW_USERCONFIG_NAME_8800D80 "aic_userconfig_8800d80.txt" ++#define FW_USERCONFIG_NAME_8800D80X2 "aic_userconfig_8800d80x2.txt" ++#define FW_POWERLIMIT_NAME_8800D80 "aic_powerlimit_8800d80.txt" ++ ++ ++int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, ++ u32** buffer, const char *filename); ++void rwnx_plat_userconfig_parsing2(char *buffer, int size); ++void rwnx_plat_userconfig_parsing3(char *buffer, int size); ++void rwnx_plat_userconfig_parsing_8800d80x2(char *buffer, int size); ++ ++void rwnx_release_firmware_common(u32** buffer); ++ ++int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm) ++{ ++ int ret = 0; ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ if ((ret = rwnx_send_txpwr_lvl_v3_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst2x_req(rwnx_hw))) { ++ return -1; ++ } ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if ((ret = rwnx_send_txpwr_lvl_v4_req(rwnx_hw))) { ++ return -1; ++ } ++ if ((ret = rwnx_send_txpwr_ofst2x_v2_req(rwnx_hw))) { ++ return -1; ++ } ++ } ++ ++ if ((ret = rwnx_send_txpwr_lvl_adj_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) { ++ return -1; ++ } ++ ++ return 0 ; ++} ++ ++int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800D80; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing3((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ ++int rwnx_plat_userconfig_load_8800d80x2(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800D80X2; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing_8800d80x2((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ ++#ifdef CONFIG_POWER_LIMIT ++extern char country_code[4]; ++int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst = NULL; ++ char *filename = FW_POWERLIMIT_NAME_8800D80; ++ ++ AICWFDBG(LOGDEBUG, "powerlimit file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of cfg file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ AICWFDBG(LOGDEBUG, "### Load file done: %s, size=%d\n", filename, size); ++ ++ /* parsing the file */ ++ rwnx_plat_powerlimit_parsing((char *)dst, size, country_code); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGDEBUG, "powerlimit download complete\n\n"); ++ return 0; ++} ++ ++int rwnx_plat_powerlimit_load_8800d80x2(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst = NULL; ++ char *filename = FW_POWERLIMIT_NAME_8800D80; ++ ++ AICWFDBG(LOGDEBUG, "powerlimit file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of cfg file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ AICWFDBG(LOGDEBUG, "### Load file done: %s, size=%d\n", filename, size); ++ ++ /* parsing the file */ ++ rwnx_plat_powerlimit_parsing((char *)dst, size, country_code); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGDEBUG, "powerlimit download complete\n\n"); ++ return 0; ++} ++ ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h +new file mode 100644 +index 000000000000..e76577414834 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h +@@ -0,0 +1,15 @@ ++#ifndef _AICWF_COMPAT_8800D80_H_ ++#define _AICWF_COMPAT_8800D80_H_ ++#include ++ ++int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); ++int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw); ++int rwnx_plat_userconfig_load_8800d80x2(struct rwnx_hw *rwnx_hw); ++ ++#ifdef CONFIG_POWER_LIMIT ++int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw); ++int rwnx_plat_powerlimit_load_8800d80x2(struct rwnx_hw *rwnx_hw); ++#endif ++ ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c +new file mode 100644 +index 000000000000..3e68283f6dc7 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c +@@ -0,0 +1,685 @@ ++#include "rwnx_main.h" ++#include "rwnx_msg_tx.h" ++#include "reg_access.h" ++#include "aic_bsp_export.h" ++ ++#define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc" ++#define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin" ++#define FW_USERCONFIG_NAME_8800DC "aic_userconfig_8800dc.txt" ++#define FW_USERCONFIG_NAME_8800DW "aic_userconfig_8800dw.txt" ++ ++int rwnx_plat_bin_fw_upload_2(struct rwnx_hw *rwnx_hw, u32 fw_addr, ++ char *filename); ++int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, ++ u32** buffer, const char *filename); ++void rwnx_plat_userconfig_parsing2(char *buffer, int size); ++ ++void rwnx_release_firmware_common(u32** buffer); ++ ++#if !defined(CONFIG_EXT_FEM_8800DCDW) ++u32 wifi_txgain_table_24g_8800dcdw[32] = ++{ ++ 0xA4B22189, //index 0 ++ 0x00007825, ++ 0xA4B2214B, //index 1 ++ 0x00007825, ++ 0xA4B2214F, //index 2 ++ 0x00007825, ++ 0xA4B221D5, //index 3 ++ 0x00007825, ++ 0xA4B221DC, //index 4 ++ 0x00007825, ++ 0xA4B221E5, //index 5 ++ 0x00007825, ++ 0xAC9221E5, //index 6 ++ 0x00006825, ++ 0xAC9221EF, //index 7 ++ 0x00006825, ++ 0xBC9221EE, //index 8 ++ 0x00006825, ++ 0xBC9221FF, //index 9 ++ 0x00006825, ++ 0xBC9221FF, //index 10 ++ 0x00004025, ++ 0xB792203F, //index 11 ++ 0x00004026, ++ 0xDC92203F, //index 12 ++ 0x00004025, ++ 0xE692203F, //index 13 ++ 0x00004025, ++ 0xFF92203F, //index 14 ++ 0x00004035, ++ 0xFFFE203F, //index 15 ++ 0x00004832 ++}; ++ ++u32 wifi_txgain_table_24g_1_8800dcdw[32] = ++{ ++ 0x096E2011, //index 0 ++ 0x00004001, ++ 0x096E2015, //index 1 ++ 0x00004001, ++ 0x096E201B, //index 2 ++ 0x00004001, ++ 0x116E2018, //index 3 ++ 0x00004001, ++ 0x116E201E, //index 4 ++ 0x00004001, ++ 0x116E2023, //index 5 ++ 0x00004001, ++ 0x196E2021, //index 6 ++ 0x00004001, ++ 0x196E202B, //index 7 ++ 0x00004001, ++ 0x216E202B, //index 8 ++ 0x00004001, ++ 0x236E2027, //index 9 ++ 0x00004001, ++ 0x236E2031, //index 10 ++ 0x00004001, ++ 0x246E2039, //index 11 ++ 0x00004001, ++ 0x26922039, //index 12 ++ 0x00004001, ++ 0x2E92203F, //index 13 ++ 0x00004001, ++ 0x3692203F, //index 14 ++ 0x00004001, ++ 0x3FF2203F, //index 15 ++ 0x00004001, ++}; ++ ++u32 wifi_txgain_table_24g_8800dcdw_h[32] = ++{ ++ 0xA55629C9, //index 0 ++ 0x00005825, ++ 0xAE5629C9, //index 1 ++ 0x00005825, ++ 0xAD5629CD, //index 2 ++ 0x00005825, ++ 0xAD5629D1, //index 3 ++ 0x00005825, ++ 0xAD5629D7, //index 4 ++ 0x00005825, ++ 0xAD5629DE, //index 5 ++ 0x00005825, ++ 0xAD5629E6, //index 6 ++ 0x00005825, ++ 0xBD5629E6, //index 7 ++ 0x00005825, ++ 0xBD5629F0, //index 8 ++ 0x00005825, ++ 0xCD5629F0, //index 9 ++ 0x00005825, ++ 0xE55629F0, //index 10 ++ 0x00005825, ++ 0xE55629FF, //index 11 ++ 0x00005825, ++ 0xE55629FF, //index 12 ++ 0x00002825, ++ 0xE75629FF, //index 13 ++ 0x00002825, ++ 0xFF5629FF, //index 14 ++ 0x00001825, ++ 0xFF5628FF, //index 15 ++ 0x00001025, ++}; ++ ++u32 wifi_txgain_table_24g_1_8800dcdw_h[32] = ++{ ++ 0x941A2048, //index 0 ++ 0x00001825, ++ 0x961A2048, //index 1 ++ 0x00001825, ++ 0x9D1A2048, //index 2 ++ 0x00001825, ++ 0x9A1A204F, //index 3 ++ 0x00001825, ++ 0x961A204F, //index 4 ++ 0x00001825, ++ 0x9A1A2057, //index 5 ++ 0x00001825, ++ 0x9C1A2057, //index 6 ++ 0x00001825, ++ 0xA31A205B, //index 7 ++ 0x00001825, ++ 0xAB1A205B, //index 8 ++ 0x00001825, ++ 0xAD1A205B, //index 9 ++ 0x00001825, ++ 0xA71A2064, //index 10 ++ 0x00001825, ++ 0xAD1A2070, //index 11 ++ 0x00001825, ++ 0xAD72207F, //index 12 ++ 0x00001825, ++ 0xBCAE207F, //index 13 ++ 0x00001825, ++ 0xBFB2207F, //index 14 ++ 0x00001825, ++ 0xD73A207F, //index 15 ++ 0x00001825, ++}; ++ ++#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ ++// ofdm ++uint32_t wifi_txgain_table_24g_8800dcdw_femkct[32] = { ++ 0x919221C2, //index 0 ++ 0x00007825, ++ 0x899221C3, //index 1 ++ 0x00007825, ++ 0x8B9221C3, //index 2 ++ 0x00007825, ++ 0x929221C3, //index 3 ++ 0x00007825, ++ 0x949221C4, //index 4 ++ 0x00007825, ++ 0x969221C4, //index 5 ++ 0x00007825, ++ 0x949221C6, //index 6 ++ 0x00007825, ++ 0x949221C8, //index 7 ++ 0x00007825, ++ 0x9C9221C8, //index 8 ++ 0x00007825, ++ 0x9C9221CA, //index 9 ++ 0x00007825, ++ 0x9C9221CB, //index 10 ++ 0x00007825, ++ 0x939221D5, //index 11 ++ 0x00007825, ++ 0x9B9221D7, //index 12 ++ 0x00007825, ++ 0xA49221D7, //index 13 ++ 0x00007825, ++ 0xA79221D7, //index 14 ++ 0x00007825, ++ 0xBD9221D7, //index 15 ++ 0x00007825, ++}; ++ ++// 11b ++uint32_t wifi_txgain_table_24g_1_8800dcdw_femkct[32] = { ++ 0x836E20C2, //index 0 ++ 0x00003024, ++ 0x856E20C2, //index 1 ++ 0x00003024, ++ 0x826E20C3, //index 2 ++ 0x00003024, ++ 0x836E20C3, //index 3 ++ 0x00003024, ++ 0x856E20C3, //index 4 ++ 0x00003024, ++ 0x876E20C3, //index 5 ++ 0x00003024, ++ 0x8B6E20C3, //index 6 ++ 0x00003024, ++ 0x926E20C4, //index 7 ++ 0x00003024, ++ 0x9A6E20C4, //index 8 ++ 0x00003024, ++ 0x936E20C5, //index 9 ++ 0x00003024, ++ 0x936E20C7, //index 10 ++ 0x00003024, ++ 0xA16E20C8, //index 11 ++ 0x00003024, ++ 0xA16E20CA, //index 12 ++ 0x00003024, ++ 0xA26E20CB, //index 13 ++ 0x00003024, ++ 0xAA6E20CD, //index 14 ++ 0x00003024, ++ 0xAC7220CF, //index 15 ++ 0x00003024, ++}; ++#endif ++ ++u32 wifi_rxgain_table_24g_20m_8800dcdw[64] = { ++ 0x82f282d1,//index 0 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x42f282d1,//index 1 ++ 0x95923524, ++ 0x80808419, ++ 0x000000f0, ++ 0x22f282d1,//index 2 ++ 0x9592c724, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282d1,//index 3 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x06f282d1,//index 4 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ad1,//index 5 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ad3,//index 6 ++ 0x95923524, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ad7,//index 7 ++ 0x9595a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282d2,//index 8 ++ 0x95951124, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282f4,//index 9 ++ 0x95951124, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 10 ++ 0x9595a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 11 ++ 0x9599a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 12 ++ 0x959da324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 13 ++ 0x959f5924, ++ 0x80808419, ++ 0x000000f0, ++ 0x06f282e6,//index 14 ++ 0x959f5924, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ae6,//index 15 ++ 0x959f5924, //loft [35:34]=3 ++ 0x80808419, ++ 0x000000f0 ++}; ++ ++u32 wifi_rxgain_table_24g_40m_8800dcdw[64] = { ++ 0x83428151,//index 0 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x43428151,//index 1 ++ 0x96323528, ++ 0x80808419, ++ 0x000000f0, ++ 0x23428151,//index 2 ++ 0x9632c728, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428151,//index 3 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x07429951,//index 4 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d151,//index 5 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d153,//index 6 ++ 0x96323528, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d157,//index 7 ++ 0x9635a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428152,//index 8 ++ 0x96351128, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428174,//index 9 ++ 0x96351128, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 10 ++ 0x9635a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 11 ++ 0x9639a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 12 ++ 0x963da328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 13 ++ 0x963f5928, ++ 0x80808419, ++ 0x000000f0, ++ 0x07429966,//index 14 ++ 0x963f5928, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d166,//index 15 ++ 0x963f5928, ++ 0x80808419, ++ 0x000000f0 ++}; ++ ++#define RAM_LMAC_FW_ADDR 0x00150000 ++#ifdef CONFIG_DPD ++#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++extern int is_file_exist(char* name); ++#endif ++extern rf_misc_ram_lite_t dpd_res; ++ ++int aicwf_fdrv_dpd_result_apply_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", dpd_res->bit_mask[1]); ++ if (dpd_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void dpd_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == 1) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy dpd_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", dpd_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // dpd_high ++ AICWFDBG(LOGINFO, "dpd_high[0]=%x\n", dpd_res->dpd_high[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, dpd_high); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, dpd_high); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->dpd_high[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "dpd_high wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", dpd_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++ ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_fdrv_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_DPDRESULT_NAME_8800DC; ++ AICWFDBG(LOGINFO, "dpd_res file path:%s \r\n", filename); ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of dpd_res file\n"); ++ dst = NULL; ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d, dst[0]=%x\n", filename, size, dst[0]); ++ memcpy((u8 *)dpd_res, (u8 *)dst, sizeof(rf_misc_ram_lite_t)); ++ if (dst) { ++ rwnx_release_firmware_common(&dst); ++ } ++ return ret; ++} ++#endif ++#endif ++ ++#if defined(CONFIG_LOFT_CALIB) ++extern rf_misc_ram_lite_t loft_res_local; ++ ++int aicwf_fdrv_loft_result_apply_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *loft_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", loft_res->bit_mask[1]); ++ if (loft_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void loft_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == 1) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy loft_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", loft_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", loft_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++#endif ++ ++int aicwf_fdrv_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t misc_ram_size = 12; ++ int i; ++ ++ if (testmode == 1) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ // init misc ram ++ printk("%s\n", __func__); ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr); ++ for (i = 0; i < (misc_ram_size / 4); i++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, misc_ram_addr + i * 4, 0); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] wr fail: %d\n", misc_ram_addr + i * 4, ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++ ++ ++int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm){ ++ int ret = 0; ++ ++ if ((ret = rwnx_send_txpwr_lvl_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ ++ if (testmode == 0) { ++ #if !defined(CONFIG_EXT_FEM_8800DCDW) ++ if (IS_CHIP_ID_H()) { ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_h, 128))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw_h, 128))) ++ return -1; ++ } else { ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw, 128))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw, 128))) ++ return -1; ++ } ++ #else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ ++ { ++ ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_femkct, 128); ++ if (ret) { ++ return -1; ++ } ++ ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw_femkct, 128); ++ if (ret) { ++ return -1; ++ } ++ } ++ #endif ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 0, (u8_l *)wifi_rxgain_table_24g_20m_8800dcdw, 256))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 32, 0, (u8_l *)wifi_rxgain_table_24g_40m_8800dcdw, 256))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) { ++ return -1; ++ } ++ } else if (testmode == 1) { ++ if (chip_sub_id >= 1) { ++ #ifdef CONFIG_DPD ++ #ifndef CONFIG_FORCE_DPD_CALIB ++ if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 1) { ++ AICWFDBG(LOGINFO, "%s load dpd bin\n", __func__); ++ ret = aicwf_fdrv_dpd_result_load_8800dc(rwnx_hw, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ if (dpd_res.bit_mask[1]) { ++ ret = aicwf_fdrv_dpd_result_apply_8800dc(rwnx_hw, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "apply dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #elif defined(CONFIG_LOFT_CALIB) ++ if (loft_res_local.bit_mask[1]) { ++ ret = aicwf_fdrv_loft_result_apply_8800dc(rwnx_hw, &loft_res_local); ++ if (ret) { ++ AICWFDBG(LOGINFO, "apply loft res fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #else ++ { ++ ret = aicwf_fdrv_misc_ram_init_8800dc(rwnx_hw); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram init fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ ret = rwnx_send_rf_calib_req(rwnx_hw, cfm); ++ if (ret) { ++ AICWFDBG(LOGINFO, "rf calib req fail: %d\n", ret); ++ return ret; ++ } ++ } ++ } ++ ++ return 0 ; ++} ++ ++int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw){ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800DC; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing2((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ ++int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw){ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800DC; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing2((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h +new file mode 100644 +index 000000000000..249703b68389 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h +@@ -0,0 +1,15 @@ ++#include ++#include "aic_bsp_export.h" ++ ++#ifdef CONFIG_DPD ++int aicwf_fdrv_dpd_result_apply_8800dc(struct rwnx_hw * rwnx_hw, rf_misc_ram_lite_t * dpd_res); ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_fdrv_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res); ++#endif ++#endif ++int aicwf_fdrv_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw); ++int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); ++int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw); ++int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw); ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h +new file mode 100644 +index 000000000000..25a5766567eb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h +@@ -0,0 +1,56 @@ ++ ++ ++#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ ++ ++ ++ ++/* message levels */ ++#define LOGERROR 0x0001 ++#define LOGINFO 0x0002 ++#define LOGTRACE 0x0004 ++#define LOGDEBUG 0x0008 ++#define LOGDATA 0x0010 ++#define LOGIRQ 0x0020 ++#define LOGSDPWRC 0x0040 ++#define LOGWAKELOCK 0x0080 ++#define LOGRXPOLL 0x0100 ++ ++extern int aicwf_dbg_level; ++void rwnx_data_dump(char* tag, void* data, unsigned long len); ++ ++#define AICWF_LOG "AICWFDBG(" ++ ++#define AICWFDBG(level, args, arg...) \ ++do { \ ++ if (aicwf_dbg_level & level) { \ ++ printk(AICWF_LOG#level")\t" args, ##arg); \ ++ } \ ++} while (0) ++ ++#define RWNX_DBG(fmt, ...) \ ++do { \ ++ if (aicwf_dbg_level & LOGTRACE) { \ ++ printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \ ++ } \ ++} while (0) ++ ++ ++ ++#if 0 ++#define RWNX_DBG(fmt, ...) \ ++ do { \ ++ if (aicwf_dbg_level & LOGTRACE) { \ ++ printk(AICWF_LOG"LOGTRACE"")\t" fmt, ##__VA_ARGS__); \ ++ } \ ++ } while (0) ++#define AICWFDBG(args, level) \ ++do { \ ++ if (aicwf_dbg_level & level) { \ ++ printk(AICWF_LOG"(%s)\t" ,#level); \ ++ printf args; \ ++ } \ ++} while (0) ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c +new file mode 100644 +index 000000000000..59502b89a318 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c +@@ -0,0 +1,97 @@ ++#include ++#include ++#include ++#include ++#include ++#include "aicwf_rx_prealloc.h" ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct aicwf_rx_buff_list aic_rx_buff_list; ++ ++int aic_rxbuff_num_max = 30; ++ ++int aic_rxbuff_size = (64 * 512); ++ ++struct rx_buff *aicwf_prealloc_rxbuff_alloc(spinlock_t *lock) ++{ ++ unsigned long flags; ++ struct rx_buff *rxbuff = NULL; ++ ++ spin_lock_irqsave(lock, flags); ++ if (list_empty(&aic_rx_buff_list.rxbuff_list)) { ++ spin_unlock_irqrestore(lock, flags); ++ printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); ++ return NULL; ++ } else { ++ rxbuff = list_first_entry(&aic_rx_buff_list.rxbuff_list, ++ struct rx_buff, queue); ++ list_del_init(&rxbuff->queue); ++ atomic_dec(&aic_rx_buff_list.rxbuff_list_len); ++ } ++ spin_unlock_irqrestore(lock, flags); ++ //printk("len:%d\n", aic_rx_buff_list.rxbuff_list_len); ++ memset(rxbuff->data, 0, aic_rxbuff_size); ++ rxbuff->len = 0; ++ rxbuff->start = NULL; ++ rxbuff->read = NULL; ++ rxbuff->end = NULL; ++ ++ return rxbuff; ++} ++ ++void aicwf_prealloc_rxbuff_free(struct rx_buff *rxbuff, spinlock_t *lock) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(lock, flags); ++ list_add_tail(&rxbuff->queue, &aic_rx_buff_list.rxbuff_list); ++ atomic_inc(&aic_rx_buff_list.rxbuff_list_len); ++ spin_unlock_irqrestore(lock, flags); ++} ++ ++int aicwf_prealloc_init() ++{ ++ struct rx_buff *rxbuff; ++ int i = 0; ++ ++ printk("%s enter\n", __func__); ++ INIT_LIST_HEAD(&aic_rx_buff_list.rxbuff_list); ++ ++ for (i = 0 ; i < aic_rxbuff_num_max ; i++) { ++ rxbuff = kzalloc(sizeof(struct rx_buff), GFP_KERNEL); ++ if (rxbuff) { ++ rxbuff->data = kzalloc(aic_rxbuff_size, GFP_KERNEL); ++ if (rxbuff->data == NULL) { ++ printk("failed to alloc rxbuff data\n"); ++ kfree(rxbuff); ++ continue; ++ } ++ rxbuff->len = 0; ++ rxbuff->start = NULL; ++ rxbuff->read = NULL; ++ rxbuff->end = NULL; ++ list_add_tail(&rxbuff->queue, &aic_rx_buff_list.rxbuff_list); ++ atomic_inc(&aic_rx_buff_list.rxbuff_list_len); ++ } ++ } ++ ++ printk("pre alloc rxbuff list len: %d\n", (int)atomic_read(&aic_rx_buff_list.rxbuff_list_len)); ++ return 0; ++} ++ ++void aicwf_prealloc_exit() ++{ ++ struct rx_buff *rxbuff; ++ struct rx_buff *pos; ++ ++ printk("%s enter\n", __func__); ++ ++ printk("free pre alloc rxbuff list %d\n", (int)atomic_read(&aic_rx_buff_list.rxbuff_list_len)); ++ list_for_each_entry_safe(rxbuff, pos, &aic_rx_buff_list.rxbuff_list, queue) { ++ list_del_init(&rxbuff->queue); ++ kfree(rxbuff->data); ++ kfree(rxbuff); ++ } ++} ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h +new file mode 100644 +index 000000000000..64a494aeef16 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h +@@ -0,0 +1,24 @@ ++#ifndef _AICWF_RX_PREALLOC_H_ ++#define _AICWF_RX_PREALLOC_H_ ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct rx_buff { ++ struct list_head queue; ++ unsigned char *data; ++ u32 len; ++ uint8_t *start; ++ uint8_t *end; ++ uint8_t *read; ++}; ++ ++struct aicwf_rx_buff_list { ++ struct list_head rxbuff_list; ++ atomic_t rxbuff_list_len; ++}; ++ ++struct rx_buff *aicwf_prealloc_rxbuff_alloc(spinlock_t *lock); ++void aicwf_prealloc_rxbuff_free(struct rx_buff *rxbuff, spinlock_t *lock); ++int aicwf_prealloc_init(void); ++void aicwf_prealloc_exit(void); ++#endif ++#endif /* _AICWF_RX_PREALLOC_H_ */ +\ No newline at end of file +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c +new file mode 100644 +index 000000000000..0c0fa323b3de +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c +@@ -0,0 +1,3462 @@ ++/** ++ * aicwf_sdmmc.c ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aicwf_txrxif.h" ++#include "aicwf_sdio.h" ++#include "sdio_host.h" ++#include "rwnx_defs.h" ++#include "rwnx_platform.h" ++#include "aicwf_rx_prealloc.h" ++#include "rwnx_msg_tx.h" ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#else ++#include ++#endif ++#include "rwnx_wakelock.h" ++ ++#ifdef CONFIG_INGENIC_T20 ++#include "mach/jzmmc.h" ++#endif /* CONFIG_INGENIC_T20 */ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#include ++#endif ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#include ++#endif ++ ++#include "aic_bsp_export.h" ++extern uint8_t scanning; ++ ++#ifdef CONFIG_SDIO_ADMA ++unsigned char sdio_tx_buf_fill[512]; ++unsigned char sdio_tx_buf_dummy[SDIO_TX_SLIST_MAX][8]; ++#endif ++ ++#ifdef CONFIG_GPIO_WAKEUP ++extern int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter); ++ ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++#include ++void rwnx_init_wifi_suspend_node(void); ++void rwnx_deinit_wifi_suspend_node(void); ++void rwnx_set_wifi_suspend(char onoff); ++struct proc_dir_entry *wifi_suspend_node; ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ ++#endif//CONFIG_GPIO_WAKEUP ++ ++int tx_aggr_counter = 32; ++module_param_named(tx_aggr_counter, tx_aggr_counter, int, 0644); ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++int tx_fc_low_water = AICWF_SDIO_TX_LOW_WATER; ++module_param_named(tx_fc_low_water, tx_fc_low_water, int, 0644); ++ ++int tx_fc_high_water = AICWF_SDIO_TX_HIGH_WATER; ++module_param_named(tx_fc_high_water, tx_fc_high_water, int, 0644); ++#endif ++ ++#if 0 ++void rwnx_data_dump(char* tag, void* data, unsigned long len){ ++ if(dump){ ++ unsigned long i = 0; ++ uint8_t* data_ = (uint8_t* )data; ++ ++ printk("%s %s len:(%lu)\r\n", __func__, tag, len); ++ ++ for (i = 0; i < len; i += 16){ ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", ++ data_[0 + i], ++ data_[1 + i], ++ data_[2 + i], ++ data_[3 + i], ++ data_[4 + i], ++ data_[5 + i], ++ data_[6 + i], ++ data_[7 + i], ++ data_[8 + i], ++ data_[9 + i], ++ data_[10 + i], ++ data_[11 + i], ++ data_[12 + i], ++ data_[13 + i], ++ data_[14 + i], ++ data_[15 + i]); ++ } ++ } ++} ++#endif ++ ++int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ *val = sdio_readb(sdiodev->func, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ sdio_writeb(sdiodev->func, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_func2_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func2); ++ *val = sdio_readb(sdiodev->func2, regaddr, &ret); ++ sdio_release_host(sdiodev->func2); ++ return ret; ++} ++ ++int aicwf_sdio_func2_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func2); ++ sdio_writeb(sdiodev->func2, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func2); ++ return ret; ++} ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++void aicwf_sdio_tx_netif_flowctrl(struct rwnx_hw *rwnx_hw, bool state) ++{ ++ struct rwnx_vif *rwnx_vif; ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (! rwnx_vif->up) ++ continue; ++ if (state) ++ netif_tx_stop_all_queues(rwnx_vif->ndev);//netif_stop_queue(rwnx_vif->ndev); ++ else ++ netif_tx_wake_all_queues(rwnx_vif->ndev);//netif_wake_queue(rwnx_vif->ndev); ++ } ++} ++#endif ++ ++#ifdef CONFIG_TEMP_CONTROL ++//int interval = 30; ++//module_param(interval, int, 0660); ++static int update_state(s8_l value, u8_l current_state) ++{ ++ if (value > TEMP_THD_2) ++ return 2; ++ else if (value > (TEMP_THD_2 - BUFFERING_V2) && (current_state == 2)) ++ return 2; ++ else if (value > TEMP_THD_1 && current_state != 2) ++ return 1; ++ else if (value > (TEMP_THD_1 - BUFFERING_V1) && current_state == 1) ++ return 1; ++ else if (current_state == 0) ++ return 0; ++ else ++ return 1; ++} ++ ++void aicwf_netif_ctrl(struct aic_sdio_dev *sdiodev, int val) ++{ ++ unsigned long flags; ++ struct rwnx_vif *rwnx_vif; ++ ++ if (sdiodev->net_stop) ++ return; ++ ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ list_for_each_entry(rwnx_vif, &sdiodev->rwnx_hw->vifs, list) { ++ if (!rwnx_vif || !rwnx_vif->ndev || !rwnx_vif->up) ++ continue; ++ netif_tx_stop_all_queues(rwnx_vif->ndev);//netif_stop_queue(rwnx_vif->ndev); ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++ sdiodev->net_stop = true; ++ mod_timer(&sdiodev->netif_timer, jiffies + msecs_to_jiffies(val)); ++ ++ return; ++} ++ ++void aicwf_temp_ctrl(struct aic_sdio_dev *sdiodev) ++{ ++ if (sdiodev->set_level) { ++ if (sdiodev->set_level == 1) { ++ sdiodev->get_level = 1; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t1/*TMR_INTERVAL_1*/); ++ //mdelay(1); ++ } else if (sdiodev->set_level == 2) { ++ sdiodev->get_level = 2; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t2/*TMR_INTERVAL_2*/); ++ //mdelay(2); ++ } ++ return; ++ } else { ++ if (sdiodev->cur_temp > (TEMP_THD_1 - 8)) { ++ //if ((sdiodev->cur_temp > TEMP_THD_1 && sdiodev->cur_temp <= TEMP_THD_2) || (sdiodev->cur_stat == 1)) { ++ if (update_state(sdiodev->cur_temp, sdiodev->cur_stat) == 1) { ++ sdiodev->get_level = 1; ++ sdiodev->cur_stat = 1; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t1/*TMR_INTERVAL_1*/); ++ //mdelay(1); ++ //break; ++ //} else if ((sdiodev->cur_temp > TEMP_THD_2) || (sdiodev->cur_stat == 2)) { ++ } else if (update_state(sdiodev->cur_temp, sdiodev->cur_stat) == 2) { ++ sdiodev->get_level = 2; ++ sdiodev->cur_stat = 2; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t2/*TMR_INTERVAL_2*/); ++ //mdelay(2); ++ //break; ++ } ++ return; ++ } ++ ++ if (sdiodev->cur_stat) { ++ AICWFDBG(LOGINFO, "reset cur_stat"); ++ sdiodev->cur_stat = 0; ++ } ++ ++ return; ++ } ++} ++ ++void aicwf_netif_worker(struct work_struct *work) ++{ ++ struct aic_sdio_dev *sdiodev = container_of(work, struct aic_sdio_dev, netif_work); ++ unsigned long flags; ++ struct rwnx_vif *rwnx_vif; ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ list_for_each_entry(rwnx_vif, &sdiodev->rwnx_hw->vifs, list) { ++ if (!rwnx_vif || !rwnx_vif->ndev || !rwnx_vif->up) ++ continue; ++ netif_tx_wake_all_queues(rwnx_vif->ndev);//netif_wake_queue(rwnx_vif->ndev); ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++ sdiodev->net_stop = false; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++static void aicwf_netif_timer(ulong data) ++#else ++static void aicwf_netif_timer(struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, netif_timer); ++#endif ++ ++ if (!work_pending(&sdiodev->netif_work)) ++ schedule_work(&sdiodev->netif_work); ++ ++ return; ++} ++ ++void aicwf_temp_ctrl_worker(struct work_struct *work) ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct mm_set_vendor_swconfig_cfm cfm; ++ struct aic_sdio_dev *sdiodev = container_of(work, struct aic_sdio_dev, tp_ctrl_work); ++ rwnx_hw = sdiodev->rwnx_hw; ++ //AICWFDBG(LOGINFO, "%s\n", __func__); ++ ++ rwnx_hw->started_jiffies = jiffies; ++ ++ rwnx_send_get_temp_req(rwnx_hw, &cfm); ++ sdiodev->cur_temp = cfm.temp_comp_get_cfm.degree; ++ ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++ ++ return; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++static void aicwf_temp_ctrl_timer(ulong data) ++#else ++static void aicwf_temp_ctrl_timer(struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, tp_ctrl_timer); ++#endif ++ ++ if (!work_pending(&sdiodev->tp_ctrl_work)) ++ schedule_work(&sdiodev->tp_ctrl_work); ++ ++ return; ++} ++#endif ++ ++int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = -1; ++ u8 fc_reg = 0; ++ u32 count = 0; ++ ++ while (true) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.flow_ctrl_reg, &fc_reg); ++ if (ret) { ++ return -1; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ fc_reg = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; ++ } ++ ++ if (fc_reg != 0) { ++ ret = fc_reg; ++ if(ret > tx_aggr_counter){ ++ ret = tx_aggr_counter; ++ } ++ return ret; ++ } else { ++ if (count >= FLOW_CTRL_RETRY_COUNT) { ++ ret = -fc_reg; ++ break; ++ } ++ count++; ++ if (count < 30) ++ udelay(200); ++ else if(count < 40) ++ msleep(2); ++ else ++ msleep(10); ++ } ++ } ++ ++ return ret; ++} ++ ++ ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = -1; ++ u8 fc_reg = 0; ++ u32 count = 0; ++ ++ while (true) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.flow_ctrl_reg, &fc_reg); ++ if (ret) { ++ return -1; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ fc_reg = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; ++ } ++ ++ if (fc_reg > DATA_FLOW_CTRL_THRESH) { ++ ret = fc_reg; ++ if(ret > tx_aggr_counter){ ++ ret = tx_aggr_counter; ++ } ++ return ret; ++ } else { ++ if (count >= FLOW_CTRL_RETRY_COUNT) { ++ ret = -fc_reg; ++ break; ++ } ++ count++; ++ if (count < 30) ++ udelay(200); ++ else if(count < 40) ++ msleep(2); ++ else ++ msleep(10); ++ } ++ } ++ ++ return ret; ++} ++ ++ ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) ++{ ++ int ret = 0; ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, buf, count); ++ sdio_release_host(sdiodev->func); ++ ++ return ret; ++} ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct rx_buff *rxbuff, ++ u32 size) ++{ ++ int ret; ++ ++ if ((!rxbuff->data) || (!size)) { ++ return -EINVAL;; ++ } ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_readsb(sdiodev->func, rxbuff->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ rxbuff->len = size; ++ ++ return ret; ++} ++#else ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, ++ u32 size) ++{ ++ int ret; ++ ++ if ((!skbbuf) || (!size)) { ++ return -EINVAL;; ++ } ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_readsb(sdiodev->func, skbbuf->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ skbbuf->len = size; ++ ++ return ret; ++} ++#endif ++ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++static int wakeup_enable; ++static u32 hostwake_irq_num; ++#endif//CONFIG_GPIO_WAKEUP ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)//LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++//static struct wakeup_source *ws_rx_sdio; ++//static struct wakeup_source *ws_sdio_pwrctrl; ++//static struct wakeup_source *ws_tx_sdio; ++#ifdef CONFIG_GPIO_WAKEUP ++//static struct wakeup_source *ws; ++#endif ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++#include ++static struct wake_lock irq_wakelock; ++//struct wake_lock irq_wakelock; ++#endif//CONFIG_GPIO_WAKEUP ++#endif//ANDROID_PLATFORM ++#endif ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++extern int sunxi_wlan_get_oob_irq(int *, int *); ++#else ++extern int sunxi_wlan_get_oob_irq(void); ++extern int sunxi_wlan_get_oob_irq_flags(void); ++#endif ++#endif// CONFIG_PLATFORM_ALLWINNER ++ ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static struct wakeup_source *ws; ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++#include ++static struct wake_lock irq_wakelock; ++#endif//CONFIG_GPIO_WAKEUP ++#endif//ANDROID_PLATFORM ++#endif ++#endif ++ ++#if 0 ++void rwnx_pm_stay_awake(struct aic_sdio_dev *sdiodev){ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ spin_lock_bh(&sdiodev->wslock); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if(ws != NULL){ ++ __pm_stay_awake(ws); ++ AICWFDBG(LOGWAKELOCK, "%s active_count:%d relax_count:%d\r\n", __func__, (int)ws->active_count, (int)ws->relax_count); ++ } ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++ wake_lock(&irq_wakelock); ++#endif //CONFIG_GPIO_WAKEUP ++#endif //ANDROID_PLATFORM ++#endif ++ ++ spin_unlock_bh(&sdiodev->wslock); ++#endif ++} ++ ++void rwnx_pm_relax(struct aic_sdio_dev *sdiodev){ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ spin_lock_bh(&sdiodev->wslock); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if(ws != NULL){ ++ __pm_relax(ws); ++ AICWFDBG(LOGWAKELOCK, "%s active_count:%d relax_count:%d\r\n", __func__, (int)ws->active_count, (int)ws->relax_count); ++ } ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++ wake_unlock(&irq_wakelock); ++#endif //CONFIG_GPIO_WAKEUP ++#endif //ANDROID_PLATFORM ++#endif ++ spin_unlock_bh(&sdiodev->wslock); ++#endif ++ ++} ++#endif ++ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ ++void rwnx_set_wifi_suspend(char onoff); ++ ++ ++static irqreturn_t rwnx_hostwake_irq_handler(int irq, void *para) ++{ ++ static int wake_cnt; ++ wake_cnt++; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ rwnx_wakeup_lock_timeout(g_rwnx_plat->sdiodev->rwnx_hw->ws_rx, 1000); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_timeout(&irq_wakelock, HZ); ++#endif //ANDROID_PLATFORM ++#endif ++ ++ AICWFDBG(LOGIRQ, "%s(%d): wake_irq_cnt = %d\n", __func__, __LINE__, wake_cnt); ++ ++#ifdef CONFIG_OOB ++#if 0//old oob feature ++ complete(&g_rwnx_plat->sdiodev->bus_if->busrx_trgg); ++#else//new oob feature ++ if(g_rwnx_plat->sdiodev->oob_enable){ ++ complete(&g_rwnx_plat->sdiodev->bus_if->busirq_trgg); ++ } ++#endif//old oob feature ++#endif ++ ++ return IRQ_HANDLED; ++} ++#endif//CONFIG_GPIO_WAKEUP ++ ++#ifdef CONFIG_GPIO_WAKEUP ++static int rwnx_disable_hostwake_irq(void); ++static int rwnx_enable_hostwake_irq(void); ++#endif ++ ++static int rwnx_register_hostwake_irq(struct device *dev) ++{ ++ int ret = 0;//-1; ++#ifdef CONFIG_GPIO_WAKEUP ++ unsigned long flag_edge; ++ struct aicbsp_feature_t aicwf_feature; ++ int irq_flags; ++//TODO hostwake_irq_num hostwake_irq_num and wakeup_enable ++ ++ aicbsp_get_feature(&aicwf_feature, NULL); ++ if (aicwf_feature.irqf == 0) ++ flag_edge = IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND; ++ else ++ flag_edge = IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND; ++ ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ hostwake_irq_num = sunxi_wlan_get_oob_irq(&irq_flags, &wakeup_enable); ++#else ++ hostwake_irq_num = sunxi_wlan_get_oob_irq(); ++ irq_flags = sunxi_wlan_get_oob_irq_flags(); ++ wakeup_enable = 1; ++#endif ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++//For Rockchip ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ hostwake_irq_num = rockchip_wifi_get_oob_irq(); ++ printk("%s hostwake_irq_num:%d \r\n", __func__, hostwake_irq_num); ++ irq_flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE) & IRQF_TRIGGER_MASK; ++ printk("%s irq_flags:%d \r\n", __func__, irq_flags); ++ wakeup_enable = 1; ++#endif //CONFIG_PLATFORM_ROCKCHIP ++ //For Rockchip ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ hostwake_irq_num = rockchip_wifi_get_oob_irq(); ++ printk("%s hostwake_irq_num:%d \r\n", __func__, hostwake_irq_num); ++ irq_flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE) & IRQF_TRIGGER_MASK; ++ printk("%s irq_flags:%d \r\n", __func__, irq_flags); ++ wakeup_enable = 1; ++#endif //CONFIG_PLATFORM_ROCKCHIP ++ ++ ++ ++ if (wakeup_enable) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ //ws = wakeup_source_register(dev, "wifisleep"); ++ //ws_tx_sdio = wakeup_source_register(dev, "wifi_tx_sleep"); ++ //ws_rx_sdio = wakeup_source_register(dev, "wifi_rx_sleep"); ++ //ws_sdio_pwrctrl = wakeup_source_register(dev, "sdio_pwrctrl_sleep"); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_init(&irq_wakelock, WAKE_LOCK_SUSPEND, "wifisleep"); ++#endif ++#endif ++ ret = device_init_wakeup(dev, true); ++ if (ret < 0) { ++ pr_err("%s(%d): device init wakeup failed!\n", __func__, __LINE__); ++ return ret; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ ret = dev_pm_set_wake_irq(dev, hostwake_irq_num); ++#endif ++ if (ret < 0) { ++ pr_err("%s(%d): can't enable wakeup src!\n", __func__, __LINE__); ++ goto fail1; ++ } ++ ++ ret = request_irq(hostwake_irq_num, rwnx_hostwake_irq_handler, flag_edge, "rwnx_hostwake_irq", NULL); ++ ++ if (ret < 0) { ++ pr_err("%s(%d): request_irq fail! ret = %d\n", __func__, __LINE__, ret); ++ goto fail2; ++ } ++ } ++ //disable_irq(hostwake_irq_num); ++ rwnx_disable_hostwake_irq(); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ dev_pm_clear_wake_irq(dev); ++#endif ++ rwnx_enable_hostwake_irq(); ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++ return ret; ++ ++fail2: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ dev_pm_clear_wake_irq(dev); ++#endif ++fail1: ++ device_init_wakeup(dev, false); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ //wakeup_source_unregister(ws); ++ //wakeup_source_unregister(ws_tx_sdio); ++ //wakeup_source_unregister(ws_rx_sdio); ++ //wakeup_source_unregister(ws_sdio_pwrctrl); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_destroy(&irq_wakelock); ++#endif ++#endif ++#endif//CONFIG_GPIO_WAKEUP ++ return ret; ++} ++ ++static int rwnx_unregister_hostwake_irq(struct device *dev) ++{ ++#ifdef CONFIG_GPIO_WAKEUP ++ rwnx_disable_hostwake_irq(); ++ if (wakeup_enable) { ++ device_init_wakeup(dev, false); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ dev_pm_clear_wake_irq(dev); ++#else ++ AICWFDBG(LOGERROR, "%s kernel unsupport this feature!\r\n", __func__); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ //wakeup_source_unregister(ws); ++ //wakeup_source_unregister(ws_tx_sdio); ++ //wakeup_source_unregister(ws_rx_sdio); ++ //wakeup_source_unregister(ws_sdio_pwrctrl); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_destroy(&irq_wakelock); ++#endif //ANDROID_PLATFORM ++#endif ++ } ++ free_irq(hostwake_irq_num, NULL); ++#endif//CONFIG_GPIO_WAKEUP ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++ return 0; ++} ++ ++#ifdef CONFIG_GPIO_WAKEUP ++static int rwnx_enable_hostwake_irq(void) ++{ ++#ifdef CONFIG_GPIO_WAKEUP ++ enable_irq(hostwake_irq_num); ++ enable_irq_wake(hostwake_irq_num); ++#endif//CONFIG_GPIO_WAKEUP ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++ return 0; ++} ++ ++static int rwnx_disable_hostwake_irq(void) ++{ ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++#ifdef CONFIG_GPIO_WAKEUP ++ disable_irq_nosync(hostwake_irq_num); ++ //disable_irq_wake(hostwake_irq_num); ++ //disable_irq(hostwake_irq_num); ++#endif//CONFIG_GPIO_WAKEUP ++ return 0; ++} ++#endif ++ ++static int aicwf_sdio_chipmatch(struct aic_sdio_dev *sdio_dev, u16_l vid, u16_l did){ ++ ++ if(vid == SDIO_VENDOR_ID_AIC8801 && did == SDIO_DEVICE_ID_AIC8801){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8801; ++ AICWFDBG(LOGINFO, "%s USE AIC8801\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800DC && did == SDIO_DEVICE_ID_AIC8800DC){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800DC; ++ AICWFDBG(LOGINFO, "%s USE AIC8800DC\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80 && did == SDIO_DEVICE_ID_AIC8800D80){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80X2 && did == SDIO_DEVICE_ID_AIC8800D80X2){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80X2; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80X2\r\n", __func__); ++ return 0; ++ }else{ ++ return -1; ++ } ++} ++ ++ ++extern int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter); ++ ++static int aicwf_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ struct mmc_host *host; ++ struct aic_sdio_dev *sdiodev; ++ struct aicwf_bus *bus_if; ++ int err = -ENODEV; ++ ++ AICWFDBG(LOGDEBUG, "%s:%d\n", __func__, func->num); ++ AICWFDBG(LOGDEBUG, "Class=%x\n", func->class); ++ AICWFDBG(LOGDEBUG, "sdio vendor ID: 0x%04x\n", func->vendor); ++ AICWFDBG(LOGDEBUG, "sdio device ID: 0x%04x\n", func->device); ++ AICWFDBG(LOGDEBUG, "Function#: %d\n", func->num); ++ ++ host = func->card->host; ++ if (func->num != 1) { ++ return err; ++ } ++ ++ bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_KERNEL); ++ if (!bus_if) { ++ sdio_err("alloc bus fail\n"); ++ return -ENOMEM; ++ } ++ ++ sdiodev = kzalloc(sizeof(struct aic_sdio_dev), GFP_KERNEL); ++ if (!sdiodev) { ++ sdio_err("alloc sdiodev fail\n"); ++ kfree(bus_if); ++ return -ENOMEM; ++ } ++ ++ ++ err = aicwf_sdio_chipmatch(sdiodev, func->vendor, func->device); ++ ++ sdiodev->func = func; ++ sdiodev->bus_if = bus_if; ++ ++#ifdef CONFIG_OOB ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "%s ERROR!!! 8801 not support OOB \r\n", __func__); ++ sdiodev->oob_enable = false; ++ }else{ ++ sdiodev->oob_enable = true; ++ } ++#else ++ sdiodev->oob_enable = false; ++#endif ++ ++ atomic_set(&sdiodev->is_bus_suspend, 0); ++ bus_if->bus_priv.sdio = sdiodev; ++ ++ dev_set_drvdata(&func->dev, bus_if); ++ sdiodev->dev = &func->dev; ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ sdiodev->func2 = func->card->sdio_func[1]; ++ } ++ ++ //sdio func init start ++ if (sdiodev->chipid != PRODUCT_ID_AIC8800D80 && sdiodev->chipid != PRODUCT_ID_AIC8800D80X2) { ++ err = aicwf_sdio_func_init(sdiodev); ++ } else { ++ err = aicwf_sdiov3_func_init(sdiodev); ++ } ++ if (err < 0) { ++ sdio_err("sdio func init fail\n"); ++ goto fail; ++ } ++ //sdio func init end ++ ++ if (aicwf_sdio_bus_init(sdiodev) == NULL) { ++ sdio_err("sdio bus init fail\n"); ++ err = -1; ++ goto fail; ++ } ++ ++ host->caps |= MMC_CAP_NONREMOVABLE; ++ aicwf_rwnx_sdio_platform_init(sdiodev); ++ aicwf_hostif_ready(); ++ err = rwnx_register_hostwake_irq(sdiodev->dev); ++ if (err != 0) ++ return err; ++ ++#ifdef CONFIG_GPIO_WAKEUP ++#ifdef CONFIG_OOB ++ if(sdiodev->oob_enable){ ++ AICWFDBG(LOGINFO, "%s SDIOWIFI_INTR_CONFIG_REG Disable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ err = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x0); ++ if (err < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_INTR_CONFIG_REG); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++#if 0 ++#if 0//old oob feature ++ sdiodev->oob_enable = true; ++#else//new oob feature ++ sdiodev->oob_enable = true; ++#endif//old oob feature ++#endif ++ } ++#endif ++ ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++ rwnx_init_wifi_suspend_node(); ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++#endif//CONFIG_GPIO_WAKEUP ++ device_disable_async_suspend(sdiodev->dev); ++ ++ return 0; ++fail: ++ aicwf_sdio_func_deinit(sdiodev); ++ dev_set_drvdata(&func->dev, NULL); ++ kfree(sdiodev); ++ kfree(bus_if); ++ aicwf_hostif_fail(); ++ return err; ++} ++ ++void aicwf_sdio_probe_(struct sdio_func *func, ++ const struct sdio_device_id *id){ ++ aicwf_sdio_probe(func, NULL); ++} ++ ++ ++static void aicwf_sdio_remove(struct sdio_func *func) ++{ ++ struct mmc_host *host; ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_sdio_dev *sdiodev = NULL; ++ ++ AICWFDBG(LOGINFO, "%s Enter\n", __func__); ++ host = func->card->host; ++ host->caps &= ~MMC_CAP_NONREMOVABLE; ++ bus_if = dev_get_drvdata(&func->dev); ++ if (!bus_if) { ++ return; ++ } ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ if (!sdiodev) { ++ return; ++ } ++ ++ sdiodev->bus_if->state = BUS_DOWN_ST; ++ aicwf_sdio_release(sdiodev); ++ aicwf_sdio_func_deinit(sdiodev); ++ rwnx_unregister_hostwake_irq(sdiodev->dev); ++ dev_set_drvdata(&sdiodev->func->dev, NULL); ++ kfree(sdiodev); ++ kfree(bus_if); ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++ rwnx_deinit_wifi_suspend_node(); ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ AICWFDBG(LOGINFO, "%s done\n", __func__); ++} ++ ++void aicwf_sdio_remove_(struct sdio_func *func){ ++ aicwf_sdio_remove(func); ++} ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_SHUTDOWN_CALLBACK ++int rwnx_close_(struct net_device *dev); ++ ++void aicwf_sdio_shutdown(struct device *dev) ++{ ++ struct rwnx_vif *rwnx_vif, *tmp; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ AICWFDBG(LOGINFO, "%s Enter", __func__); ++ list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { ++ if (rwnx_vif->ndev && test_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags)){ ++ AICWFDBG(LOGINFO, "%s rwnx_close by shutdown", __func__); ++ rwnx_close_(rwnx_vif->ndev); ++ ++ }else{ ++ if(!rwnx_vif->ndev){ ++ AICWFDBG(LOGERROR, "%s rwnx_vif->ndev is NULL \r\n", __func__); ++ } ++ if(!test_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags)){ ++ AICWFDBG(LOGERROR, "%s rwnx_vif->drv_flags close\r\n", __func__); ++ } ++ } ++ ++ } ++ AICWFDBG(LOGINFO, "%s Exit", __func__); ++ ++} ++#endif ++#endif ++ ++#if defined(CONFIG_AUTO_POWERSAVE) ++static int aicwf_wakeup_lock_status(struct rwnx_hw *rwnx_hw) ++{ ++ if(rwnx_hw->ws_tx && rwnx_hw->ws_tx->active) ++ return -1; ++ ++ if(rwnx_hw->ws_rx && rwnx_hw->ws_rx->active) ++ return -1; ++ ++ if(rwnx_hw->ws_pwrctrl && rwnx_hw->ws_pwrctrl->active) ++ return -1; ++ ++ if(rwnx_hw->ws_irqrx && rwnx_hw->ws_irqrx->active) ++ return -1; ++ ++ return 0; ++} ++#endif ++ ++static int aicwf_sdio_suspend(struct device *dev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ mmc_pm_flag_t sdio_flags; ++ struct rwnx_vif *rwnx_vif, *tmp; ++ ++ sdio_dbg("%s enter\n", __func__); ++ ++ list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { ++ if (rwnx_vif->ndev) ++ netif_device_detach(rwnx_vif->ndev); ++ } ++ ++ sdio_flags = sdio_get_host_pm_caps(sdiodev->func); ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ return -EINVAL; ++ } ++ ret = sdio_set_host_pm_flags(sdiodev->func, MMC_PM_KEEP_POWER); ++ if (ret) { ++ return ret; ++ } ++ ++#ifdef CONFIG_TEMP_CONTROL ++ del_timer_sync(&sdiodev->tp_ctrl_timer); ++ cancel_work_sync(&sdiodev->tp_ctrl_work); ++ ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++ ++ del_timer_sync(&sdiodev->netif_timer); ++ cancel_work_sync(&sdiodev->netif_work); ++#endif ++ ++#if (defined(CONFIG_AUTO_POWERSAVE) && defined(CONFIG_SDIO_PWRCTRL)) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ ++ if((sdiodev->chipid == PRODUCT_ID_AIC8800D80) || (sdiodev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ sdio_dbg("autops set\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x8); ++ if(ret) { ++ sdio_err("sdio set autops fail\n"); ++ } ++ } ++#endif ++ ++ #if (!defined(CONFIG_AUTO_POWERSAVE)) ++ while (sdiodev->state == SDIO_ACTIVE_ST) { ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) ++ continue; ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ #endif ++ up(&sdiodev->tx_priv->txctl_sema); ++ break; ++ } ++ #else ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ #endif ++ #endif ++#ifdef CONFIG_GPIO_WAKEUP ++// rwnx_enable_hostwake_irq(); ++#endif ++ ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ sdio_dbg("%s SDIOWIFI_INTR_CONFIG_REG Disable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_INTR_CONFIG_REG); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++#endif ++ atomic_set(&sdiodev->is_bus_suspend, 1); ++// smp_mb(); ++ ++#if defined(CONFIG_AUTO_POWERSAVE) ++ if(aicwf_wakeup_lock_status(sdiodev->rwnx_hw)) { ++ printk("%s ws active dont suspend", __func__); ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ ++ if((sdiodev->chipid == PRODUCT_ID_AIC8800D80) || (sdiodev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ sdio_dbg("autops clear\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x8); ++ if(ret) { ++ sdio_err("sdio clear autops fail\n"); ++ } ++ } ++ ++ return -EBUSY; ++ } ++#endif ++ ++ sdio_dbg("%s exit\n", __func__); ++ ++ return 0; ++} ++ ++static int aicwf_sdio_resume(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ struct rwnx_vif *rwnx_vif, *tmp; ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_AUTO_POWERSAVE) ++ int ret; ++#endif ++ ++ sdio_dbg("%s enter \n", __func__); ++ ++#ifdef CONFIG_TEMP_CONTROL ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++#endif ++ ++//#ifdef CONFIG_GPIO_WAKEUP ++// rwnx_disable_hostwake_irq(); ++//#endif ++ //dev_pm_clear_wake_irq(dev); ++ list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { ++ if (rwnx_vif->ndev) ++ netif_device_attach(rwnx_vif->ndev); ++ } ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ #endif ++ ++#if defined(CONFIG_AUTO_POWERSAVE) && defined(CONFIG_SDIO_PWRCTRL) ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ sdio_dbg("autops clear\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x8); ++ if(ret) { ++ sdio_err("sdio clear autops fail\n"); ++ } ++ } ++#endif ++ ++// aicwf_sdio_hal_irqhandler(sdiodev->func); ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ sdio_dbg("%s SDIOWIFI_INTR_CONFIG_REG Enable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ sdio_release_host(sdiodev->func); ++ } ++#endif ++ atomic_set(&sdiodev->is_bus_suspend, 0); ++// smp_mb(); ++ #ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++ rwnx_set_wifi_suspend('0'); ++ #endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ ++ ++ sdio_dbg("%s exit\n", __func__); ++ return 0; ++} ++ ++static const struct sdio_device_id aicwf_sdmmc_ids[] = { ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8801, SDIO_DEVICE_ID_AIC8801)}, ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8800DC, SDIO_DEVICE_ID_AIC8800DC)}, ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8800D80, SDIO_DEVICE_ID_AIC8800D80)}, ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8800D80X2, SDIO_DEVICE_ID_AIC8800D80X2)}, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(sdio, aicwf_sdmmc_ids); ++ ++static const struct dev_pm_ops aicwf_sdio_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(aicwf_sdio_suspend, aicwf_sdio_resume) ++}; ++ ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++static struct sdio_driver aicwf_sdio_driver = { ++ .probe = aicwf_sdio_probe, ++ .remove = aicwf_sdio_remove, ++ .name = AICWF_SDIO_NAME, ++ .id_table = aicwf_sdmmc_ids, ++ .drv = { ++ .pm = &aicwf_sdio_pm_ops, ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_SHUTDOWN_CALLBACK ++ .shutdown = aicwf_sdio_shutdown, ++#endif ++#endif ++ }, ++}; ++#endif ++ ++#if 0 ++#ifdef CONFIG_NANOPI_M4 ++extern int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq); ++extern unsigned aic_max_freqs; ++extern struct mmc_host *aic_host_drv; ++extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); ++extern void mmc_release_host(struct mmc_host *host); ++#endif ++#endif ++ ++#ifdef CONFIG_FDRV_NO_REG_SDIO ++extern struct sdio_func *get_sdio_func(void); ++void aicwf_sdio_probe_(struct sdio_func *func, const struct sdio_device_id *id); ++void aicwf_sdio_remove_(struct sdio_func *func); ++#endif ++ ++void aicwf_sdio_register(void) ++{ ++#if 0 ++#ifdef CONFIG_PLATFORM_NANOPI ++ extern_wifi_set_enable(0); ++ mdelay(200); ++ extern_wifi_set_enable(1); ++ mdelay(200); ++ sdio_reinit(); ++#endif /*CONFIG_PLATFORM_NANOPI*/ ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ rockchip_wifi_power(0); ++ mdelay(200); ++ rockchip_wifi_power(1); ++ mdelay(200); ++ rockchip_wifi_set_carddetect(1); ++#endif /*CONFIG_PLATFORM_ROCKCHIP*/ ++ ++#ifdef CONFIG_INGENIC_T20 ++ jzmmc_manual_detect(1, 1); ++#endif /* CONFIG_INGENIC_T20 */ ++ ++ ++#ifdef CONFIG_NANOPI_M4 ++ if (aic_host_drv->card == NULL) { ++ __mmc_claim_host(aic_host_drv, NULL); ++ printk("aic: >>>mmc_rescan_try_freq\n"); ++ mmc_rescan_try_freq(aic_host_drv, aic_max_freqs); ++ mmc_release_host(aic_host_drv); ++ } ++#endif ++#endif ++ ++ ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ if (sdio_register_driver(&aicwf_sdio_driver)) { ++ ++ } else { ++ //may add mmc_rescan here ++ } ++#else ++ aicwf_sdio_probe_(get_sdio_func(), NULL); ++#endif ++} ++ ++void aicwf_sdio_exit(void) ++{ ++ if (g_rwnx_plat && g_rwnx_plat->enabled){ ++#ifdef CONFIG_TEMP_CONTROL ++ if (timer_pending(&g_rwnx_plat->sdiodev->tp_ctrl_timer)) { ++ AICWFDBG(LOGINFO, "%s del tp_ctrl_timer\n", __func__); ++ del_timer_sync(&g_rwnx_plat->sdiodev->tp_ctrl_timer); ++ } ++ cancel_work_sync(&g_rwnx_plat->sdiodev->tp_ctrl_work); ++ ++ if (timer_pending(&g_rwnx_plat->sdiodev->netif_timer)) { ++ AICWFDBG(LOGINFO, "%s del netif_timer\n", __func__); ++ del_timer_sync(&g_rwnx_plat->sdiodev->netif_timer); ++ } ++ cancel_work_sync(&g_rwnx_plat->sdiodev->netif_work); ++#endif ++ rwnx_platform_deinit(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else{ ++ AICWFDBG(LOGERROR, "%s g_rwnx_plat is not ready \r\n", __func__); ++ } ++ ++ udelay(500); ++ ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ sdio_unregister_driver(&aicwf_sdio_driver); ++#else ++ aicwf_sdio_remove_(get_sdio_func()); ++#endif ++ ++#if 0 ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++#endif /*CONFIG_PLATFORM_AMLOGIC*/ ++#endif ++ ++#if 0 ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ rockchip_wifi_set_carddetect(0); ++ mdelay(200); ++ rockchip_wifi_power(0); ++ mdelay(200); ++#endif /*CONFIG_PLATFORM_ROCKCHIP*/ ++#endif ++ ++ if(g_rwnx_plat){ ++ kfree(g_rwnx_plat); ++ } ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++int aicwf_sdio_wakeup(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ int read_retry; ++ int write_retry = 1; ++ int wakeup_reg_val = 0; ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ wakeup_reg_val = 1; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ wakeup_reg_val = 0x11; ++ } ++ ++ if (sdiodev->state == SDIO_SLEEP_ST) { ++ AICWFDBG(LOGSDPWRC, "%s w\n", __func__); ++ ++ //rwnx_pm_stay_awake(sdiodev); ++ ++ while (write_retry) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, wakeup_reg_val); ++ if (ret) { ++ txrx_err("sdio wakeup fail\n"); ++ ret = -1; ++ } else { ++ read_retry = 50; ++ while (read_retry) { ++ u8 val; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.wakeup_reg, &val); ++ if (ret < 0) ++ txrx_err("sdio wakeup read fail\n"); ++ else if ((val & 0x1) == 0) { ++ break; ++ } ++ read_retry--; ++ udelay(200); ++ } ++ if (read_retry != 0) ++ break; ++ } ++ sdio_dbg("write retry: %d \n", write_retry); ++ write_retry--; ++ udelay(100); ++ } ++ ++ sdiodev->state = SDIO_ACTIVE_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ return ret; ++} ++ ++int aicwf_sdio_sleep_allow(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = sdiodev->bus_if; ++ struct rwnx_hw *rwnx_hw = sdiodev->rwnx_hw; ++ u8 read_retry; ++ u8 val; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, 0x10); ++ if (ret) { ++ sdio_err("Write sleep fail!\n"); ++ } ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ return ret; ++ } ++ ++ sdio_info("sleep: %d, %d\n", sdiodev->state, scanning); ++ if (sdiodev->state == SDIO_ACTIVE_ST && !scanning && !rwnx_hw->is_p2p_alive \ ++ && !rwnx_hw->is_p2p_connected && (int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) <= 0) \ ++ && (sdiodev->tx_priv->cmd_txstate == false) && (int)(atomic_read(&sdiodev->rx_priv->rx_cnt) == 0)) { ++ AICWFDBG(LOGSDPWRC, "%s s\n", __func__); ++ if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ if (aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x02) < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ if (aicwf_sdio_func2_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x2) < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++ read_retry = 100; ++ while (read_retry) { ++ val = 0; ++ if (aicwf_sdio_func2_readb(sdiodev, sdiodev->sdio_reg.wakeup_reg, &val) < 0){ ++ sdio_err("reg %d read fail\n", sdiodev->sdio_reg.wakeup_reg); ++ }else if ((val & 0x2) == 0) { ++ break; ++ } else { ++ sdio_err("val:%d\n", val); ++ } ++ read_retry--; ++ if(read_retry < 90) ++ printk("warning: read cnt %d\n", read_retry); ++ udelay(500); ++ } ++ } ++ sdiodev->state = SDIO_SLEEP_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ //rwnx_pm_relax(sdiodev); ++ } else { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target) ++{ ++ int ret = 0; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ return -1; ++ } ++ ++ down(&sdiodev->pwrctl_wakeup_sema); ++ ++ if (sdiodev->state == target) { ++ if (target == SDIO_ACTIVE_ST) { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ up(&sdiodev->pwrctl_wakeup_sema); ++ return ret; ++ } ++ ++ switch (target) { ++ case SDIO_ACTIVE_ST: ++ aicwf_sdio_wakeup(sdiodev); ++ break; ++ case SDIO_SLEEP_ST: ++ aicwf_sdio_sleep_allow(sdiodev); ++ break; ++ } ++ ++ up(&sdiodev->pwrctl_wakeup_sema); ++ return ret; ++} ++#endif ++ ++#if 0 ++int align_param = 16; ++module_param(align_param, int, 0660); ++#endif ++ ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++{ ++ int ret = 0; ++ u8 *frame; ++ u32 len = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++#if 0 ++ int align = 0; ++#endif ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("tx bus is down!\n"); ++ return -EINVAL; ++ } ++ ++#if 0 ++ len = pkt->len; ++ len = (len + SDIOWIFI_FUNC_BLOCKSIZE - 1) / SDIOWIFI_FUNC_BLOCKSIZE * SDIOWIFI_FUNC_BLOCKSIZE; ++ ++ frame = (u8*)kmalloc(sizeof(u8) * len + align_param, GFP_ATOMIC); ++ align = ((unsigned long)(frame)) & (align_param - 1); ++ memcpy(frame + (align_param - align), (u8 *) (pkt->data), len); ++ ++ ret = aicwf_sdio_send_pkt(sdiodev, frame + (align_param - align), len); ++ if (ret) ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", ret); ++ ++ kfree(frame); ++#endif ++#if 1 ++ frame = (u8 *) (pkt->data); ++ len = pkt->len; ++ len = (len + SDIOWIFI_FUNC_BLOCKSIZE - 1) / SDIOWIFI_FUNC_BLOCKSIZE * SDIOWIFI_FUNC_BLOCKSIZE; ++ ++ ret = aicwf_sdio_send_pkt(sdiodev, pkt->data, len); ++ if (ret) ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", ret); ++#endif ++ return ret; ++} ++ ++#ifdef CONFIG_SDIO_ADMA ++int aicwf_sdio_txscatterpkt(struct aicwf_tx_priv *tx_priv) ++{ ++ int ret = 0; ++ u8 *frame; ++ u32 len = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(tx_priv->sdiodev->dev); ++ struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; ++ int nents = tx_priv->aggr_segcnt; ++ int i=0; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("tx bus is down!\n"); ++ return -EINVAL; ++ } ++ ++ //AICWFDBG(LOGTRACE,"%s aggr_segcnt %d len %d \n",__func__,tx_priv->aggr_segcnt, tx_priv->len); ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_write_sg(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, &(tx_priv->sg_list[0]), tx_priv->aggr_segcnt, tx_priv->len);//&(tx_priv->sg_list[0]) ++ //sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, tx_priv->sg_list[0].buf, tx_priv->sg_list[0].len); ++ /*for(i=0;i<1;i++){ ++ sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, tx_priv->sg_list[i].buf, tx_priv->sg_list[i].len); ++ }*/ ++ sdio_release_host(sdiodev->func); ++ ++ return ret; ++ ++} ++ ++void aicwf_adma_add(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt) ++{ ++ u8 adj_len = 0; ++ u8 *sdio_header = NULL; ++ u32 sdio_len = 0; ++ u32 curr_len = 0; ++ unsigned int align_len = 0; ++ u8 *start_ptr = NULL; ++ ++ adj_len = ALIGN4_ADJ_LEN((uint32_t)pkt->data); ++ start_ptr = skb_push(pkt,adj_len); //skb_push(pkt,adj_len) ++ //ASSERT((adj_len==0)||(adj_len==2)); // mgmt-pkt or data-pkt ++ //ASSERT((((uint32_t)start_ptr)&3) == 0); // start_ptr addr word align ++ if(!((adj_len==0)||(adj_len==2))) ++ AICWFDBG(LOGTRACE,"adj_len false %u \n",adj_len); ++ ++ if((((uint32_t)start_ptr)&3) != 0) ++ AICWFDBG(LOGTRACE,"start_ptr %x \n",(((uint32_t)start_ptr)&3)); ++ ++ //AICWFDBG(LOGTRACE,"start adj_len %d aggrcnt %d segcnt %d len %d \n",adj_len,atomic_read(&tx_priv->aggr_count),tx_priv->aggr_segcnt,tx_priv->len); ++ ++ if (adj_len==0) { ++ sdio_len = pkt->len + SDIO_MGMT_FAKE_LEN; ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ //AICWFDBG(LOGTRACE,"pkt_len %d \n",pkt->len); ++ start_ptr = skb_push(pkt, (SDIO_HEADER_LEN+SDIO_MGMT_FAKE_LEN)); ++ //AICWFDBG(LOGTRACE,"push_pkt_len %d \n",pkt->len); ++ sdio_header = start_ptr; ++ ++ sdio_header[0] =((sdio_len) & 0xff); ++ sdio_header[1] =(((sdio_len) >> 8)&0x0f); ++ sdio_header[2] = 0x01; //data ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80) ++ sdio_header[3] = crc8_ponl_107(&sdio_header[0], 3); // crc8 ++ else ++ sdio_header[3] = 0; //reserved ++ ++ // fill 4 byte 0x00, need to fasync with data-pkt. ++ sdio_header[4] = 0; ++ sdio_header[5] = 0; ++ sdio_header[6] = 0; ++ sdio_header[7] = 0; ++ ++ curr_len = sdio_len + SDIO_HEADER_LEN; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj0",pkt->data,((pkt->len>32) ? 32 : pkt->len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ tx_priv->len += curr_len; ++ }else if (adj_len==1) { ++ sdio_len = pkt->len + 3; ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][0] = ((sdio_len) & 0xff); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][1] = (((sdio_len) >> 8)&0x0f); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][2] = 0x01; // data ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][3] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][4] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][5] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][6] = 0; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_dummy[tx_priv->aggr_segcnt]; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = SDIO_HEADER_LEN + 3; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] =NULL; ++ ++ tx_priv->aggr_segcnt++; ++ ++ sdio_header = start_ptr; ++ sdio_header[0] = 0; ++ ++ curr_len = sdio_len - 3; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj1",start_ptr,((curr_len>32) ? 32 : curr_len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ ++ tx_priv->len += curr_len + SDIO_HEADER_LEN + 3; ++ ++ }else if (adj_len==2) { // adj_len==2 ++ sdio_len = pkt->len + SDIO_DATA_FAKE_LEN;//adj_len + ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][0] = ((sdio_len) & 0xff); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][1] = (((sdio_len) >> 8)&0x0f); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][2] = 0x01; // data ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][3] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][4] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][5] = 0; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_dummy[tx_priv->aggr_segcnt]; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = SDIO_HEADER_LEN + SDIO_DATA_FAKE_LEN; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] =NULL; ++ ++ tx_priv->aggr_segcnt++; ++ ++ sdio_header = start_ptr; ++ sdio_header[0] = 0; ++ sdio_header[1] = 0; ++ ++ curr_len = sdio_len - SDIO_DATA_FAKE_LEN; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj2",start_ptr,((curr_len>32) ? 32 : curr_len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ ++ tx_priv->len += curr_len + SDIO_HEADER_LEN + SDIO_DATA_FAKE_LEN; ++ }else if (adj_len==3) { ++ sdio_len = pkt->len + 1; ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][0] = ((sdio_len) & 0xff); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][1] = (((sdio_len) >> 8)&0x0f); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][2] = 0x01; // data ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][3] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][4] = 0; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_dummy[tx_priv->aggr_segcnt]; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = SDIO_HEADER_LEN + 1; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] =NULL; ++ ++ tx_priv->aggr_segcnt++; ++ ++ sdio_header = start_ptr; ++ sdio_header[0] = 0; ++ sdio_header[1] = 0; ++ sdio_header[2] = 0; ++ ++ curr_len = sdio_len - 1; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj3",start_ptr,((curr_len>32) ? 32 : curr_len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ ++ tx_priv->len += curr_len + SDIO_HEADER_LEN + 1; ++ } ++ ++ //AICWFDBG(LOGTRACE,"end aggrcnt %d segcnt %d len %d \n",atomic_read(&tx_priv->aggr_count),tx_priv->aggr_segcnt,tx_priv->len); ++ ++} ++ ++#endif ++ ++static int aicwf_sdio_intr_get_len_bytemode(struct aic_sdio_dev *sdiodev, u8 *byte_len) ++{ ++ int ret = 0; ++ ++ if (!byte_len) ++ return -EBADE; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ *byte_len = 0; ++ } else { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.bytemode_len_reg, byte_len); ++ sdiodev->rx_priv->data_len = (*byte_len)*4; ++ } ++ ++ return ret; ++} ++ ++static void aicwf_sdio_bus_stop(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ #endif ++ AICWFDBG(LOGINFO, "%s Enter\n", __func__); ++ ++ bus_if->state = BUS_DOWN_ST; ++ if (sdiodev->tx_priv) { ++ ret = down_interruptible(&sdiodev->tx_priv->txctl_sema); ++ if (ret) ++ AICWFDBG(LOGERROR, "down txctl_sema fail\n"); ++ } ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ #endif ++ ++ if (sdiodev->tx_priv) { ++ if (!ret) ++ up(&sdiodev->tx_priv->txctl_sema); ++ aicwf_frame_queue_flush(&sdiodev->tx_priv->txq); ++ } ++ AICWFDBG(LOGINFO, "%s Exit \n", __func__); ++} ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct rx_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ u32 size = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ struct rx_buff* rxbuff; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("bus down\n"); ++ return NULL; ++ } ++ ++ size = sdiodev->rx_priv->data_len; ++ rxbuff = aicwf_prealloc_rxbuff_alloc(&sdiodev->rx_priv->rxbuff_lock); ++ if (rxbuff == NULL) { ++ printk("failed to alloc rxbuff\n"); ++ return NULL; ++ } ++ rxbuff->len = 0; ++ rxbuff->start = rxbuff->data; ++ rxbuff->read = rxbuff->start; ++ rxbuff->end = rxbuff->data + size; ++ ++ ret = aicwf_sdio_recv_pkt(sdiodev, rxbuff, size); ++ if (ret) { ++ printk("%s %d, sdio recv pkt fail\n", __func__, __LINE__); ++ aicwf_prealloc_rxbuff_free(rxbuff, &sdiodev->rx_priv->rxbuff_lock); ++ return NULL; ++ } ++ ++ return rxbuff; ++} ++#else ++struct sk_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ u32 size = 0; ++ struct sk_buff *skb = NULL; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("bus down\n"); ++ return NULL; ++ } ++ ++ size = sdiodev->rx_priv->data_len; ++ skb = __dev_alloc_skb(size, GFP_KERNEL); ++ if (!skb) { ++ return NULL; ++ } ++ ++ ret = aicwf_sdio_recv_pkt(sdiodev, skb, size); ++ if (ret) { ++ dev_kfree_skb(skb); ++ skb = NULL; ++ } ++ ++ return skb; ++} ++#endif ++ ++static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++ u16 len; ++ u8 *payload = sdiodev->tx_priv->cmd_buf; ++ u16 payload_len = sdiodev->tx_priv->cmd_len; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ int adjust_len = 0; ++ int buffer_cnt = 0; ++ u8 retry = 0; ++ ++ len = payload_len; ++ if ((len % TX_ALIGNMENT) != 0) { ++ adjust_len = roundup(len, TX_ALIGNMENT); ++ memcpy(payload+payload_len, adjust_str, (adjust_len - len)); ++ payload_len += (adjust_len - len); ++ } ++ len = payload_len; ++ ++ //link tail is necessary ++ if ((len % SDIOWIFI_FUNC_BLOCKSIZE) != 0) { ++ memset(payload+payload_len, 0, TAIL_LEN); ++ payload_len += TAIL_LEN; ++ len = (payload_len/SDIOWIFI_FUNC_BLOCKSIZE + 1) * SDIOWIFI_FUNC_BLOCKSIZE; ++ } else ++ len = payload_len; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ buffer_cnt = aicwf_sdio_flow_ctrl_msg(sdiodev); ++ while ((buffer_cnt <= 0 || (buffer_cnt > 0 && len > (buffer_cnt * BUFFER_SIZE))) && retry < 10) { ++ retry++; ++ buffer_cnt = aicwf_sdio_flow_ctrl_msg(sdiodev); ++ printk("buffer_cnt = %d\n", buffer_cnt); ++ } ++ } ++ down(&sdiodev->tx_priv->cmd_txsema); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if (buffer_cnt > 0 && len < (buffer_cnt * BUFFER_SIZE)) { ++ err = aicwf_sdio_send_pkt(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC){ ++ err = aicwf_sdio_send_pkt(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ ++ sdiodev->tx_priv->cmd_txstate = false; ++ if (!err) ++ sdiodev->tx_priv->cmd_tx_succ = true; ++ else ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ return err; ++ ++} ++ ++static void aicwf_sdio_tx_process(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ unsigned long flags; ++#endif ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("Bus is down\n"); ++ return; ++ } ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ #endif ++ ++ //config ++ sdio_info("send cmd\n"); ++ if (sdiodev->tx_priv->cmd_txstate) { ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txctl down bus->txctl_sema fail\n"); ++ return; ++ } ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ txrx_err("txctl up bus->txctl_sema fail\n"); ++ return; ++ } ++ err = aicwf_sdio_tx_msg(sdiodev); ++ up(&sdiodev->tx_priv->txctl_sema); ++ if (waitqueue_active(&sdiodev->tx_priv->cmd_txdone_wait)) ++ wake_up(&sdiodev->tx_priv->cmd_txdone_wait); ++ } ++ ++ //data ++ sdio_info("send data\n"); ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txdata down bus->txctl_sema\n"); ++ return; ++ } ++ ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("sdio state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ return; ++ } ++ ++ if (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)){ ++ sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ } ++ while (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) { ++ if(sdiodev->bus_if->state == BUS_DOWN_ST) { ++ break; ++ } ++#ifdef CONFIG_TEMP_CONTROL ++ if (sdiodev->on_off) ++ aicwf_temp_ctrl(sdiodev); ++#endif ++ ++ if (sdiodev->tx_priv->fw_avail_bufcnt <= DATA_FLOW_CTRL_THRESH) { ++ if (sdiodev->tx_priv->cmd_txstate) ++ break; ++ sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ } else { ++ if (sdiodev->tx_priv->cmd_txstate) { ++ aicwf_sdio_send(sdiodev->tx_priv, 1); ++ break; ++ } else { ++ aicwf_sdio_send(sdiodev->tx_priv, 0); ++ } ++ } ++ } ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) < tx_fc_low_water) { ++ //printk("sdiodev->tx_priv->tx_pktcnt < tx_fc_low_water:%d %d\r\n", ++ // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_low_water); ++ if (sdiodev->flowctrl) { ++ sdiodev->flowctrl = 0; ++ aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, false); ++ } ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++#endif ++ ++ up(&sdiodev->tx_priv->txctl_sema); ++} ++ ++static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) ++{ ++ uint prio; ++ int ret = -EBADE; ++ struct rwnx_txhdr *txhdr = NULL; ++ int headroom = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ unsigned long flags; ++#endif ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus_if stopped\n"); ++ txhdr = (struct rwnx_txhdr *)pkt->data; ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ consume_skb(pkt); ++ return -1; ++ } ++ ++ prio = (pkt->priority & 0x7); ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ if (!aicwf_frame_enq(sdiodev->dev, &sdiodev->tx_priv->txq, pkt, prio)) { ++ txhdr = (struct rwnx_txhdr *)pkt->data; ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ consume_skb(pkt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return -ENOSR; ++ goto flowctrl; ++ } else { ++ ret = 0; ++ } ++ ++ atomic_inc(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ complete(&bus_if->bustx_trgg); ++ ++ flowctrl: ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) >= tx_fc_high_water) { ++ //printk("sdiodev->tx_priv->tx_pktcnt >= tx_fc_high_water:%d %d\r\n", ++ // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_high_water); ++ if (!sdiodev->flowctrl) { ++ sdiodev->flowctrl = 1; ++ aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, true); ++ } ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++#endif ++ ++ return ret; ++} ++ ++static int aicwf_sdio_bus_txmsg(struct device *dev, u8 *msg, uint msglen) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ down(&sdiodev->tx_priv->cmd_txsema); ++ sdiodev->tx_priv->cmd_txstate = true; ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ sdiodev->tx_priv->cmd_buf = msg; ++ sdiodev->tx_priv->cmd_len = msglen; ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ if (bus_if->state != BUS_UP_ST) { ++ sdio_err("bus has stop\n"); ++ return -1; ++ } ++ ++ complete(&bus_if->bustx_trgg); ++#if 0 ++ if (sdiodev->tx_priv->cmd_txstate) { ++ int timeout = msecs_to_jiffies(CMD_TX_TIMEOUT); ++ ret = wait_event_interruptible_timeout(sdiodev->tx_priv->cmd_txdone_wait, \ ++ !(sdiodev->tx_priv->cmd_txstate), timeout); ++ } ++ ++ if (!sdiodev->tx_priv->cmd_txstate && sdiodev->tx_priv->cmd_tx_succ) { ++ ret = 0; ++ } else { ++ sdio_err("send faild:%d, %d,%x\n", sdiodev->tx_priv->cmd_txstate, sdiodev->tx_priv->cmd_tx_succ, ret); ++ ret = -EIO; ++ } ++#endif ++ return 0; ++} ++ ++ ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv, u8 txnow) ++{ ++ struct sk_buff *pkt; ++ struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; ++ u32 aggr_len = 0; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ unsigned long flags; ++#endif ++ ++#ifdef CONFIG_SDIO_ADMA ++ aggr_len = tx_priv->len; ++#else ++ aggr_len = (tx_priv->tail - tx_priv->head); ++#endif ++ ++ if (((atomic_read(&tx_priv->aggr_count) == 0) && (aggr_len != 0)) ++ || ((atomic_read(&tx_priv->aggr_count) != 0) && (aggr_len == 0))) { ++ if (aggr_len > 0){ ++#ifdef CONFIG_SDIO_ADMA ++ printk("len %d seg_cnt %d aggr_cnt %d avail_cnt %d \n",aggr_len,tx_priv->aggr_segcnt,atomic_read(&tx_priv->aggr_count),tx_priv->fw_avail_bufcnt ); ++#endif ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++#ifdef CONFIG_SDIO_ADMA ++ printk("set len %d seg_cnt %d aggr_cnt %d avail_cnt %d \n",aggr_len,tx_priv->aggr_segcnt,atomic_read(&tx_priv->aggr_count),tx_priv->fw_avail_bufcnt ); ++#endif ++ } ++ ++ return 0; ++ } ++ ++ if (atomic_read(&tx_priv->aggr_count) == (tx_priv->fw_avail_bufcnt - DATA_FLOW_CTRL_THRESH)) { ++ if (atomic_read(&tx_priv->aggr_count) > 0) { ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); //send and check the next pkt; ++ } ++ return 0; ++ } else { ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ pkt = aicwf_frame_dequeue(&sdiodev->tx_priv->txq); ++ if (pkt == NULL) { ++ sdio_err("txq no pkt\n"); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return 0; ++ } ++ //atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) < tx_fc_low_water) { ++ //printk("sdiodev->tx_priv->tx_pktcnt < tx_fc_low_water:%d %d\r\n", ++ // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_low_water); ++ if (sdiodev->flowctrl) { ++ sdiodev->flowctrl = 0; ++ aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, false); ++ } ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++#endif ++ ++#ifndef CONFIG_SDIO_ADMA ++ if (tx_priv == NULL || tx_priv->tail == NULL || pkt == NULL) ++ txrx_err("null error\n"); ++#endif ++ if (aicwf_sdio_aggr(tx_priv, pkt)) { ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++ sdio_err("add aggr pkts failed!\n"); ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ return 0; ++ } ++ ++ //when aggr finish or there is cmd to send, just send this aggr pkt to fw ++ if ((int)atomic_read(&sdiodev->tx_priv->tx_pktcnt) == 1 || txnow || (atomic_read(&tx_priv->aggr_count) == (tx_priv->fw_avail_bufcnt - DATA_FLOW_CTRL_THRESH))) { ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ return 0; ++ } else { ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ return 0; ++ } ++ } ++} ++ ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt) ++{ ++#ifdef CONFIG_SDIO_ADMA ++ u8 adj_len = 0; ++ struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; ++ u8 *sdio_header = NULL; ++ u32 sdio_len = 0; ++ u32 curr_len = 0; ++ int align_len = 0; ++ int headroom; ++ u32 pkt_len = 0; ++ struct txdesc_api tmp_txdesc; ++ struct sk_buff *tmp_skb; ++ ++ //AICWFDBG(LOGTRACE,"%s \n",__func__); ++ //pkt (txhdr + data),aggr only need txhdr->sw_hdr->desc and data ++ memcpy(&tmp_txdesc, (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ ++ if(txhdr->sw_hdr->need_cfm){ ++ tmp_skb = skb_copy(pkt,GFP_ATOMIC);//save pkt when cfm get,then release,send skb is copy ++ if(!tmp_skb){ ++ AICWFDBG(LOGERROR,"skb copy fail"); ++ return -ENOMEM; ++ } ++ //AICWFDBG(LOGTRACE,"tmp_len %d pkt_len %d \n",tmp_skb->len,pkt->len); ++ ++ skb_pull(tmp_skb, txhdr->sw_hdr->headroom); ++ ++ //AICWFDBG(LOGTRACE,"pull_tmp_len %d \n",tmp_skb->len); ++ ++ skb_push(tmp_skb,sizeof(struct txdesc_api));//skb header is enough ++ ++ //AICWFDBG(LOGTRACE,"push_tmp_len %d \n",tmp_skb->len); ++ ++ memcpy(tmp_skb->data, (u8 *)(long)&tmp_txdesc,sizeof(struct txdesc_api)); ++ AICWFDBG(LOGTRACE,"need cfm len %d \n",tmp_skb->len); ++ ++ //printk("cfm alloc %p \n",tmp_skb); ++ //printk("delay free %p \n",pkt); ++ aicwf_adma_add(tx_priv, tmp_skb); ++ tx_priv->copyd[tx_priv->aggr_segcnt -1] = true; ++ }else{ ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ ++ //AICWFDBG(LOGTRACE,"pull_pkt_len %d \n",pkt->len); ++ ++ skb_push(pkt,sizeof(struct txdesc_api));//skb header is enough ++ ++ //AICWFDBG(LOGTRACE,"push_pkt_len %d \n",pkt->len); ++ ++ memcpy(pkt->data, (u8 *)(long)&tmp_txdesc,sizeof(struct txdesc_api)); ++ ++ //rwnx_data_dump("data",pkt->data,((pkt->len>64) ? 64 : pkt->len)); ++ ++ //printk("alloc %p \n",pkt); ++ ++ aicwf_adma_add(tx_priv, pkt); ++ tx_priv->copyd[tx_priv->aggr_segcnt -1] = false; ++ } ++ ++#else ++ ++ struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; ++ u8 *start_ptr = tx_priv->tail; ++ u8 sdio_header[4]; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ u32 curr_len = 0; ++ int allign_len = 0; ++ int headroom; ++ ++ sdio_header[0] = ((pkt->len - txhdr->sw_hdr->headroom + sizeof(struct txdesc_api)) & 0xff); ++ sdio_header[1] = (((pkt->len - txhdr->sw_hdr->headroom + sizeof(struct txdesc_api)) >> 8)&0x0f); ++ sdio_header[2] = 0x01; //data ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ sdio_header[3] = 0; //reserved ++ else if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ sdio_header[3] = crc8_ponl_107(&sdio_header[0], 3); // crc8 ++ ++ memcpy(tx_priv->tail, (u8 *)&sdio_header, sizeof(sdio_header)); ++ tx_priv->tail += sizeof(sdio_header); ++ //payload ++ memcpy(tx_priv->tail, (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ tx_priv->tail += sizeof(struct txdesc_api); //hostdesc ++ memcpy(tx_priv->tail, (u8 *)((u8 *)txhdr + txhdr->sw_hdr->headroom), pkt->len-txhdr->sw_hdr->headroom); ++ tx_priv->tail += (pkt->len - txhdr->sw_hdr->headroom); ++ ++ //word alignment ++ curr_len = tx_priv->tail - tx_priv->head; ++ if (curr_len & (TX_ALIGNMENT - 1)) { ++ allign_len = roundup(curr_len, TX_ALIGNMENT)-curr_len; ++ memcpy(tx_priv->tail, adjust_str, allign_len); ++ tx_priv->tail += allign_len; ++ } ++ ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ start_ptr[0] = ((tx_priv->tail - start_ptr - 4) & 0xff); ++ start_ptr[1] = (((tx_priv->tail - start_ptr - 4)>>8) & 0x0f); ++ } ++ tx_priv->aggr_buf->dev = pkt->dev; ++ ++ if (!txhdr->sw_hdr->need_cfm) { ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ consume_skb(pkt); ++ } ++ ++ atomic_inc(&tx_priv->aggr_count); ++#endif /* CONFIG_SDIO_ADMA */ ++ ++ return 0; ++} ++ ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv) ++{ ++#ifdef CONFIG_SDIO_ADMA ++ int ret = 0; ++ int i=0; ++ int nents = tx_priv->aggr_segcnt; ++ //struct sk_buff *scatter_buf; ++ ++ if(tx_priv->len & (TXPKT_BLOCKSIZE-1)) ++ { ++ uint16_t alen = TXPKT_BLOCKSIZE-(tx_priv->len & (TXPKT_BLOCKSIZE-1)); ++ ++ memset(sdio_tx_buf_fill, 0,32); ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_fill; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = alen; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = NULL; ++ tx_priv->aggr_segcnt += 1; ++ tx_priv->len += alen; ++ } ++ ++ //AICWFDBG(LOGTRACE,"nents %d \n",tx_priv->aggr_segcnt); ++ /*for(i=0;iaggr_segcnt;i++){ ++ if(tx_priv->sg_list[i].buf != NULL){ ++ rwnx_data_dump("send",tx_priv->sg_list[i].buf,((tx_priv->sg_list[i].len>64) ? 64 : tx_priv->sg_list[i].len)); ++ } ++ }*/ ++ ++ ret = aicwf_sdio_txscatterpkt(tx_priv); ++ if (ret < 0) { ++ sdio_err("fail to send scatter pkt %d !\n",ret); ++ } ++ ++#else ++ ++ struct sk_buff *tx_buf = tx_priv->aggr_buf; ++ int ret = 0; ++ int curr_len = 0; ++ ++ //link tail is necessary ++ curr_len = tx_priv->tail - tx_priv->head; ++ if ((curr_len % TXPKT_BLOCKSIZE) != 0) { ++ memset(tx_priv->tail, 0, TAIL_LEN); ++ tx_priv->tail += TAIL_LEN; ++ } ++ ++ tx_buf->len = tx_priv->tail - tx_priv->head; ++ ret = aicwf_sdio_txpkt(tx_priv->sdiodev, tx_buf); ++ if (ret < 0) { ++ sdio_err("fail to send aggr pkt!\n"); ++ } ++#endif/* CONFIG_SDIO_ADMA */ ++ ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++} ++ ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv) ++{ ++#ifdef CONFIG_SDIO_ADMA ++ struct sk_buff *scatter_buf; ++ int i = 0; ++ int nents = tx_priv->aggr_segcnt; ++ ++ for(i=0;ifree_buf[i]; ++ if(scatter_buf != NULL){ ++ //printk("free %p \n",scatter_buf); ++ if(tx_priv->copyd[i]){ ++ kfree_skb(scatter_buf); ++ tx_priv->copyd[i] = false; ++ } ++ else ++ consume_skb(scatter_buf); ++ } ++ } ++ ++ tx_priv->len = 0; ++ tx_priv->aggr_segcnt = 0; ++ atomic_set(&tx_priv->aggr_count, 0); ++ AICWFDBG(LOGTRACE,"reset len %d seg_cnt %d aggr_cnt %d \n",tx_priv->len,tx_priv->aggr_segcnt,atomic_read(&tx_priv->aggr_count)); ++#else ++ ++ struct sk_buff *aggr_buf = tx_priv->aggr_buf; ++ ++ tx_priv->tail = tx_priv->head; ++ aggr_buf->len = 0; ++ atomic_set(&tx_priv->aggr_count, 0); ++#endif/* CONFIG_SDIO_ADMA */ ++} ++ ++extern void set_irq_handler(void *fn); ++ ++static int aicwf_sdio_bus_start(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ ++ sdio_claim_host(sdiodev->func); ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++#else ++ set_irq_handler(aicwf_sdio_hal_irqhandler); ++#endif ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdio_f0_writeb(sdiodev->func, 0x07, 0x04, &ret); ++ if (ret) { ++ sdio_err("set func0 int en fail %d\n", ret); ++ } ++ } ++ sdio_release_host(sdiodev->func); ++ ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ ++ bus_if->state = BUS_UP_ST; ++ ++ return ret; ++} ++ ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) ++#include "uapi/linux/sched/types.h" ++#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) ++#include "linux/sched/types.h" ++#else ++#include "linux/sched/rt.h" ++#endif ++ ++int bustx_thread_prio = 1; ++module_param_named(bustx_thread_prio, bustx_thread_prio, int, 0644); ++//module_param(bustx_thread_prio, int, 0); ++int busrx_thread_prio = 1; ++module_param_named(busrx_thread_prio, busrx_thread_prio, int, 0644); ++//module_param(busrx_thread_prio, int, 0); ++#endif ++ ++ ++static inline void aic_thread_wait_stop(void) ++{ ++#if 1// PLATFORM_LINUX ++ #if 0 ++ while (!kthread_should_stop()){ ++ AICWFDBG(LOGINFO, "%s waiting for thread_stop notify \r\n", __func__); ++ msleep(100); ++ } ++ #else ++ set_current_state(TASK_INTERRUPTIBLE); ++ while (!kthread_should_stop()) { ++ AICWFDBG(LOGINFO, "%s waiting for thread_stop notify \r\n", __func__); ++ schedule(); ++ set_current_state(TASK_INTERRUPTIBLE); ++ } ++ __set_current_state(TASK_RUNNING); ++ #endif ++#endif ++} ++ ++#ifdef CONFIG_OOB ++int rx_thread_wait_to = 1000; ++module_param_named(rx_thread_wait_to, rx_thread_wait_to, int, 0644); ++ ++//new oob feature ++int sdio_busirq_thread(void *data){ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++#if 0 ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ int set_cpu_ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s the cpu is:%d\n", __func__, current->cpu); ++ set_cpu_ret = set_cpus_allowed_ptr(current, cpumask_of(0)); ++ AICWFDBG(LOGINFO, "%s set_cpu_ret is:%d\n", __func__, set_cpu_ret); ++ AICWFDBG(LOGINFO, "%s change cpu to:%d\n", __func__, current->cpu); ++#endif ++#endif ++ ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (busrx_thread_prio > 0) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) ++ sched_set_fifo_low(current); ++#else ++ struct sched_param param; ++ param.sched_priority = (busrx_thread_prio - 1 < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++#endif ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++ ++ while (1) { ++#if 0 ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busirq thread stop\n"); ++ break; ++ } ++#endif ++ if(!wait_for_completion_timeout(&bus_if->busirq_trgg, msecs_to_jiffies(rx_thread_wait_to))){ ++ AICWFDBG(LOGRXPOLL, "%s wait for completion timout \r\n", __func__); ++ } ++ ++ if (bus_if->state == BUS_DOWN_ST){ ++ AICWFDBG(LOGERROR, "%s bus down thread exit \r\n", __func__); ++ break; ++ } ++ //continue; ++#if 1 ++#ifdef CONFIG_SDIO_PWRCTRL ++ while(atomic_read(&bus_if->bus_priv.sdio->is_bus_suspend) == 1){ ++ AICWFDBG(LOGDEBUG, "%s waiting for sdio bus resume \r\n", __func__); ++ msleep(100); ++ } ++ aicwf_sdio_pwr_stctl(bus_if->bus_priv.sdio, SDIO_ACTIVE_ST); ++#endif//CONFIG_SDIO_PWRCTRL ++#endif ++ aicwf_sdio_hal_irqhandler(bus_if->bus_priv.sdio->func); ++ } ++ ++ aic_thread_wait_stop(); ++ ++ return 0; ++} ++ ++#endif//CONFIG_OOB ++ ++#if 0 ++#include ++#endif ++int sdio_bustx_thread(void *data) ++{ ++ struct aicwf_bus *bus = (struct aicwf_bus *) data; ++ struct aic_sdio_dev *sdiodev = bus->bus_priv.sdio; ++#if 0 ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ int set_cpu_ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s the cpu is:%d\n", __func__, current->cpu); ++ set_cpu_ret = set_cpus_allowed_ptr(current, cpumask_of(1)); ++ AICWFDBG(LOGINFO, "%s set_cpu_ret is:%d\n", __func__, set_cpu_ret); ++ AICWFDBG(LOGINFO, "%s change cpu to:%d\n", __func__, current->cpu); ++#endif ++#endif ++ ++#if 0 ++ struct cpumask cpumask; ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(1, &cpumask); ++ cpumask_set_cpu(2, &cpumask); ++ cpumask_set_cpu(3, &cpumask); ++ sched_setaffinity(0, &cpumask);//need to add EXPORT_SYMBOL_GPL(sched_setaffinity) in kernel/sched/core.c ++#endif ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (bustx_thread_prio > 0) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) ++ sched_set_fifo_low(current); ++#else ++ struct sched_param param; ++ param.sched_priority = (bustx_thread_prio < MAX_RT_PRIO)?bustx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++#endif ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++ while (1) { ++ #if 0 ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio bustx thread stop\n"); ++ break; ++ } ++ #endif ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) ++ break; ++ //continue; ++ ++ rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_tx); ++ if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) > 0) || (sdiodev->tx_priv->cmd_txstate == true)){ ++ aicwf_sdio_tx_process(sdiodev); ++ } ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_tx); ++ } ++ } ++ ++ aic_thread_wait_stop(); ++ AICWFDBG(LOGINFO, "%s Exit\r\n", __func__); ++ return 0; ++} ++ ++#if 0//old oob feature ++int sdio_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++#if 0 ++ struct cpumask cpumask; ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(1, &cpumask); ++ cpumask_set_cpu(2, &cpumask); ++ cpumask_set_cpu(3, &cpumask); ++ sched_setaffinity(0, &cpumask); ++#endif ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (busrx_thread_prio > 0) { ++ struct sched_param param; ++ param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++while (1) { ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busrx thread stop\n"); ++ break; ++ } ++#ifndef CONFIG_OOB ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++#else ++ if(!wait_for_completion_timeout(&bus_if->busrx_trgg, msecs_to_jiffies(rx_thread_wait_to))){ ++ AICWFDBG(LOGDEBUG, "%s wait for completion timout \r\n", __func__); ++ } ++#endif ++ if (bus_if->state == BUS_DOWN_ST) ++ continue; ++#ifdef CONFIG_OOB ++#ifdef CONFIG_SDIO_PWRCTRL ++ while(atomic_read(&bus_if->bus_priv.sdio->is_bus_suspend) == 1){ ++ AICWFDBG(LOGDEBUG, "%s waiting for sdio bus resume \r\n", __func__); ++ msleep(100); ++ } ++ aicwf_sdio_pwr_stctl(bus_if->bus_priv.sdio, SDIO_ACTIVE_ST); ++#endif//CONFIG_SDIO_PWRCTRL ++ aicwf_sdio_hal_irqhandler(bus_if->bus_priv.sdio->func); ++#endif//CONFIG_OOB ++ rwnx_wakeup_lock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++ aicwf_process_rxframes(rx_priv); ++ rwnx_wakeup_unlock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++#ifndef CONFIG_OOB ++ } ++#endif ++ } ++ ++ return 0; ++ ++} ++#else//new oob feature ++int sdio_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++ ++ ++#if 0 ++ struct cpumask cpumask; ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(1, &cpumask); ++ cpumask_set_cpu(2, &cpumask); ++ cpumask_set_cpu(3, &cpumask); ++ sched_setaffinity(0, &cpumask); ++#endif ++#if 0 ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ int set_cpu_ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s the cpu is:%d\n", __func__, current->cpu); ++ set_cpu_ret = set_cpus_allowed_ptr(current, cpumask_of(2)); ++ AICWFDBG(LOGINFO, "%s set_cpu_ret is:%d\n", __func__, set_cpu_ret); ++ AICWFDBG(LOGINFO, "%s change cpu to:%d\n", __func__, current->cpu); ++#endif ++#endif ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (busrx_thread_prio > 0) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) ++ sched_set_fifo_low(current); ++#else ++ struct sched_param param; ++ param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++#endif ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++ while (1) { ++ #if 0 ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busrx thread stop\n"); ++ break; ++ } ++ #endif ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ ++ if (bus_if->state == BUS_DOWN_ST) ++ break; ++ //continue; ++ rwnx_wakeup_lock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++ aicwf_process_rxframes(rx_priv); ++ rwnx_wakeup_unlock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++ } ++ } ++ aic_thread_wait_stop(); ++ AICWFDBG(LOGINFO, "%s Exit\r\n", __func__); ++ return 0; ++ ++} ++ ++#endif//old oob feature ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++static int aicwf_sdio_pwrctl_thread(void *data) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ sdio_err("sdio pwrctl thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&sdiodev->pwrctrl_trgg)) { ++ //printk("%s working\r\n", __func__); ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) ++ continue; ++ ++ rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_pwrctrl); ++ ++ if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) <= 0) && (sdiodev->tx_priv->cmd_txstate == false) && \ ++ atomic_read(&sdiodev->rx_priv->rx_cnt) == 0) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ else ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_pwrctrl); ++ } ++ } ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++static void aicwf_sdio_bus_pwrctl(ulong data) ++#else ++static void aicwf_sdio_bus_pwrctl(struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ struct aic_sdio_dev *sdiodev = timer_container_of(sdiodev, t, timer); ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, timer); ++#endif ++#endif ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus down\n"); ++ return; ++ } ++ ++ if (sdiodev->pwrctl_tsk) { ++ complete(&sdiodev->pwrctrl_trgg); ++ } ++} ++#endif ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++static void aicwf_sdio_enq_rxpkt(struct aic_sdio_dev *sdiodev, struct rx_buff *pkt) ++#else ++static void aicwf_sdio_enq_rxpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++#endif ++{ ++ struct aicwf_rx_priv *rx_priv = sdiodev->rx_priv; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ if (!aicwf_rxbuff_enqueue(sdiodev->dev, &rx_priv->rxq, pkt)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ printk("%s %d, enqueue rxq fail\n", __func__, __LINE__); ++ aicwf_prealloc_rxbuff_free(pkt, &rx_priv->rxbuff_lock); ++ return; ++ } ++ #else ++ if (!aicwf_rxframe_enqueue(sdiodev->dev, &rx_priv->rxq, pkt)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ aicwf_dev_skb_free(pkt); ++ return; ++ } ++ #endif ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ ++ atomic_inc(&rx_priv->rx_cnt); ++} ++ ++ ++#define SDIO_OTHER_INTERRUPT (0x1ul << 7) ++ ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(&func->dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ u8 intstatus = 0; ++ u8 byte_len = 0; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_buff *pkt = NULL; ++ #else ++ struct sk_buff *pkt = NULL; ++ #endif ++ int ret; ++ ++ ++ if ((sdiodev->rwnx_hw) == NULL) { ++ sdio_err("waiting for rwnx_hw->irq_enable is true\r\n"); ++ return; ++ } ++ ++ //AICWFDBG(LOGDEBUG, "fdrv %s enter \r\n", __func__); ++ rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_irqrx); ++ ++ ++ if (!bus_if || bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus err\n"); ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); ++ return; ++ } ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++ if (list_empty(&aic_rx_buff_list.rxbuff_list)) { ++ printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); ++ return; ++ } ++#endif ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ while (ret || (intstatus & SDIO_OTHER_INTERRUPT)) { ++ sdio_err("ret=%d, intstatus=%x\r\n", ret, intstatus); ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ if (!ret) { ++ return; ++ } ++ } ++ sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; ++ ++ if (intstatus > 0) { ++ if (intstatus < 64) { ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } else { ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ // sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ ++ if(atomic_read(&sdiodev->rx_priv->rx_cnt) == 1){ ++ complete(&bus_if->busrx_trgg); ++ } ++ ++ }else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ do { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.misc_int_status_reg, &intstatus); ++ if (!ret) { ++ break; ++ } ++ sdio_err("ret=%d, intstatus=%x\r\n",ret, intstatus); ++ return; ++ } while (1); ++ if (intstatus & SDIO_OTHER_INTERRUPT) { ++ u8 int_pending; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ int_pending &= ~0x01; // dev to host soft irq ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ } ++ ++ if (intstatus > 0) { ++ uint8_t intmaskf2 = intstatus | (0x1UL << 3); ++ if (intmaskf2 > 120U) { // func2 ++ if (intmaskf2 == 127U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 1);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ //pkt = aicwf_sdio_readframes(sdiodev, 1); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7U) * SDIOWIFI_FUNC_BLOCKSIZE; ++ //pkt = aicwf_sdio_readframes(sdiodev, 1); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } ++ } else { // func1 ++ if (intstatus == 120U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 0);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ //pkt = aicwf_sdio_readframes(sdiodev, 0); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7FU) * SDIOWIFI_FUNC_BLOCKSIZE; ++ //pkt = aicwf_sdio_readframes(sdiodev, 0); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ //sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ ++ if(atomic_read(&sdiodev->rx_priv->rx_cnt) == 1){ ++ complete(&bus_if->busrx_trgg); ++ } ++ } ++ ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration) ++{ ++ uint timeout; ++ ++ //printk("%s duration:%d\r\n", __func__, duration); ++ if (sdiodev->bus_if->state == BUS_DOWN_ST && duration) ++ return; ++ ++ spin_lock_bh(&sdiodev->pwrctl_lock); ++ if (!duration) { ++ if (timer_pending(&sdiodev->timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&sdiodev->timer); ++#else ++ del_timer_sync(&sdiodev->timer); ++#endif ++ } else { ++ sdiodev->active_duration = duration; ++ timeout = msecs_to_jiffies(sdiodev->active_duration); ++ mod_timer(&sdiodev->timer, jiffies + timeout); ++ } ++ spin_unlock_bh(&sdiodev->pwrctl_lock); ++} ++#endif ++ ++static struct aicwf_bus_ops aicwf_sdio_bus_ops = { ++ .stop = aicwf_sdio_bus_stop, ++ .start = aicwf_sdio_bus_start, ++ .txdata = aicwf_sdio_bus_txdata, ++ .txmsg = aicwf_sdio_bus_txmsg, ++}; ++ ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) ++{ ++ struct aicwf_bus *bus_if; ++ int ret = 0; ++ AICWFDBG(LOGINFO, "%s Enter\n", __func__); ++ ++ bus_if = dev_get_drvdata(sdiodev->dev); ++ bus_if->state = BUS_DOWN_ST; ++#ifdef CONFIG_OOB ++ if(sdiodev->oob_enable){ ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++#else ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++#endif ++ if (sdiodev->dev) ++ aicwf_bus_deinit(sdiodev->dev); ++ ++ if (sdiodev->tx_priv) ++ aicwf_tx_deinit(sdiodev->tx_priv); ++ ++ if (sdiodev->rx_priv) ++ aicwf_rx_deinit(sdiodev->rx_priv); ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ if (sdiodev->pwrctl_tsk) { ++ complete_all(&sdiodev->pwrctrl_trgg); ++ kthread_stop(sdiodev->pwrctl_tsk); ++ sdiodev->pwrctl_tsk = NULL; ++ } ++ ++ AICWFDBG(LOGINFO, "%s:pwrctl stopped\n", __func__); ++ #endif ++ ++ if (sdiodev->cmd_mgr.state == RWNX_CMD_MGR_STATE_INITED) ++ rwnx_cmd_mgr_deinit(&sdiodev->cmd_mgr); ++ AICWFDBG(LOGINFO, "%s Exit\n", __func__); ++} ++ ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev) ++{ ++ sdio_dbg("%s\n", __func__); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_CONFIG_REG; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_SLEEP_REG; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_WAKEUP_REG; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_REG; ++ sdiodev->sdio_reg.register_block = SDIOWIFI_REGISTER_BLOCK; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG; ++ sdiodev->sdio_reg.block_cnt_reg = SDIOWIFI_BLOCK_CNT_REG; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG_V3; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_ENABLE_REG_V3; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_INTR_PENDING_REG_V3; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_INTR_TO_DEVICE_REG_V3; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_Q1_REG_V3; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG_V3; ++ sdiodev->sdio_reg.misc_int_status_reg = SDIOWIFI_MISC_INT_STATUS_REG_V3; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR_V3; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR_V3; ++ } ++} ++ ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 block_bit0 = 0x1; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ struct aicbsp_feature_t feature; ++ //u8 val = 0; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++#if 0//SDIO PHASE SETTING ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ sdio_f0_writeb(sdiodev->func, feature.sdio_phase, 0x13, &ret); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "write func0 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#endif ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_release_host(sdiodev->func); ++ AICWFDBG(LOGERROR, "enable func fail %d.\n", ret); ++ return ret; ++ } ++ ++#if 1//SDIO CLOCK SETTING ++ if (feature.sdio_clock > 0) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ AICWFDBG(LOGINFO, "Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++ ++ sdio_release_host(sdiodev->func); ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ sdio_claim_host(sdiodev->func2); ++ //set sdio blocksize ++ ret = sdio_set_block_size(sdiodev->func2, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set func2 blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func2); ++ return ret; ++ } ++ ++ //set sdio enable func ++ ret = sdio_enable_func(sdiodev->func2); ++ if (ret < 0) { ++ sdio_release_host(sdiodev->func2); ++ AICWFDBG(LOGERROR, "enable func2 fail %d.\n", ret); ++ return ret; ++ } ++ ++ sdio_release_host(sdiodev->func2); ++ ++ ret = aicwf_sdio_func2_writeb(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_func2_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ } ++ ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++#if 0 ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 1); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ return ret; ++ } ++ ++ mdelay(5); ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ return ret; ++ } ++ ++ if(!(val & 0x10)){ ++ AICWFDBG(LOGERROR, "wakeup fail\n"); ++ }else{ ++ AICWFDBG(LOGINFO, "sdio ready\n"); ++ } ++#else ++ mdelay(10); ++#endif ++ return ret; ++} ++ ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ struct aicbsp_feature_t feature; ++ //u8 val = 0; ++ u8 val1 = 0; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_release_host(sdiodev->func); ++ AICWFDBG(LOGERROR, "enable func fail %d.\n", ret); ++ return ret; ++ } ++ ++ sdio_f0_writeb(sdiodev->func, 0x7F, 0xF2, &ret); ++ if (ret) { ++ sdio_err("set fn0 0xF2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#if 0 ++ if (host->ios.timing == MMC_TIMING_UHS_DDR50) { ++ val = 0x21;//0x1D;//0x5; ++ } else { ++ val = 0x01;//0x19;//0x1; ++ } ++ val |= SDIOCLK_FREE_RUNNING_BIT; ++ sdio_f0_writeb(sdiodev->func, val, 0xF0, &ret); ++ if (ret) { ++ sdio_err("set iopad ctrl fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x0, 0xF8, &ret); ++ if (ret) { ++ sdio_err("set iopad delay2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x20, 0xF1, &ret); ++ if (ret) { ++ sdio_err("set iopad delay1 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ msleep(1); ++#if 1//SDIO CLOCK SETTING ++ if ((feature.sdio_clock > 0) && (host->ios.timing != MMC_TIMING_UHS_DDR50)) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ AICWFDBG(LOGINFO, "Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++#endif ++ sdio_release_host(sdiodev->func); ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x11); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ return ret; ++ } ++ ++#if 1 ++ mdelay(5); ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val1); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ return ret; ++ } ++ ++ if(!(val1 & 0x10)){ ++ AICWFDBG(LOGERROR, "wakeup fail\n"); ++ }else{ ++ AICWFDBG(LOGINFO, "sdio ready\n"); ++ } ++#endif ++ return ret; ++} ++ ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev) ++{ ++ sdio_claim_host(sdiodev->func); ++ sdio_disable_func(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func2); ++ sdio_disable_func(sdiodev->func2); ++ sdio_release_host(sdiodev->func2); ++ } ++} ++ ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret; ++ struct aicwf_bus *bus_if; ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ spin_lock_init(&sdiodev->pwrctl_lock); ++ sema_init(&sdiodev->pwrctl_wakeup_sema, 1); ++ #endif ++ ++ bus_if = sdiodev->bus_if; ++ bus_if->dev = sdiodev->dev; ++ bus_if->ops = &aicwf_sdio_bus_ops; ++ bus_if->state = BUS_DOWN_ST; ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ sdiodev->state = SDIO_SLEEP_ST; ++ sdiodev->active_duration = SDIOWIFI_PWR_CTRL_INTERVAL; ++ #else ++ sdiodev->state = SDIO_ACTIVE_ST; ++ #endif ++ ++ rx_priv = aicwf_rx_init(sdiodev); ++ if (!rx_priv) { ++ sdio_err("rx init fail\n"); ++ goto fail; ++ } ++ sdiodev->rx_priv = rx_priv; ++ ++ tx_priv = aicwf_tx_init(sdiodev); ++ if (!tx_priv) { ++ sdio_err("tx init fail\n"); ++ goto fail; ++ } ++ sdiodev->tx_priv = tx_priv; ++ aicwf_frame_queue_init(&tx_priv->txq, 8, TXQLEN); ++ spin_lock_init(&tx_priv->txqlock); ++ sema_init(&tx_priv->txctl_sema, 1); ++ sema_init(&tx_priv->cmd_txsema, 1); ++ init_waitqueue_head(&tx_priv->cmd_txdone_wait); ++ atomic_set(&tx_priv->tx_pktcnt, 0); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ init_timer(&sdiodev->timer); ++ sdiodev->timer.data = (ulong) sdiodev; ++ sdiodev->timer.function = aicwf_sdio_bus_pwrctl; ++#else ++ timer_setup(&sdiodev->timer, aicwf_sdio_bus_pwrctl, 0); ++#endif ++ init_completion(&sdiodev->pwrctrl_trgg); ++#ifdef AICWF_SDIO_SUPPORT ++ sdiodev->pwrctl_tsk = kthread_run(aicwf_sdio_pwrctl_thread, sdiodev, "aicwf_pwrctl"); ++#endif ++ if (IS_ERR(sdiodev->pwrctl_tsk)) { ++ sdiodev->pwrctl_tsk = NULL; ++ } ++#endif ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ sdiodev->flowctrl = 0; ++ spin_lock_init(&sdiodev->tx_flow_lock); ++#endif ++ ++#ifdef CONFIG_TEMP_CONTROL ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ init_timer(&sdiodev->tp_ctrl_timer); ++ sdiodev->tp_ctrl_timer.data = (ulong) sdiodev; ++ sdiodev->tp_ctrl_timer.function = aicwf_temp_ctrl_timer; ++ init_timer(&sdiodev->netif_timer); ++ sdiodev->netif_timer.data = (ulong) sdiodev; ++ sdiodev->netif_timer.function = aicwf_netif_timer; ++#else ++ timer_setup(&sdiodev->tp_ctrl_timer, aicwf_temp_ctrl_timer, 0); ++ timer_setup(&sdiodev->netif_timer, aicwf_netif_timer, 0); ++#endif ++ INIT_WORK(&sdiodev->tp_ctrl_work, aicwf_temp_ctrl_worker); ++ INIT_WORK(&sdiodev->netif_work, aicwf_netif_worker); ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++ sdiodev->net_stop = false;; ++ sdiodev->on_off = true; ++ sdiodev->cur_temp = 0; ++ sdiodev->get_level = 0; ++ sdiodev->set_level = 0; ++ sdiodev->interval_t1 = TMR_INTERVAL_1; ++ sdiodev->interval_t2 = TMR_INTERVAL_2; ++ sdiodev->cur_stat = 0; ++#endif ++ ++ ret = aicwf_bus_init(0, sdiodev->dev); ++ if (ret < 0) { ++ sdio_err("bus init fail\n"); ++ goto fail; ++ } ++ ++ ret = aicwf_bus_start(bus_if); ++ if (ret != 0) { ++ sdio_err("bus start fail\n"); ++ goto fail; ++ } ++ ++ return sdiodev; ++ ++fail: ++ aicwf_sdio_release(sdiodev); ++ return NULL; ++} ++ ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size) ++{ ++ uint8_t i; ++ uint8_t crc = 0; ++ if (cal_size==0) { ++ return crc; ++ } ++ while (cal_size--) { ++ for (i = 0x80; i > 0; i /= 2) { ++ if (crc & 0x80) { ++ crc *= 2; ++ crc ^= 0x07; //polynomial X8 + X2 + X + 1,(0x107) ++ } else { ++ crc *= 2; ++ } ++ if ((*p_buffer) & i) { ++ crc ^= 0x07; ++ } ++ } ++ p_buffer++; ++ } ++ ++ return crc; ++} ++ ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++void rwnx_set_wifi_suspend(char onoff){ ++ int ret = 0; ++ if (onoff == '0') { ++ printk("%s resume \r\n", __func__); ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 0, 1); ++ }else{ ++ printk("%s suspend \r\n", __func__); ++ ret = rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1, 0); ++ if (!ret) { ++ aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); ++ ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); ++ } ++ } ++ } ++} ++ ++static ssize_t rwnx_wifi_suspend_write_proc(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos){ ++ char onoff; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&onoff, buffer, 1)) ++ return -EFAULT; ++ ++ rwnx_set_wifi_suspend(onoff); ++ ++ return count; ++} ++ ++static const struct file_operations wifi_suspend_fops = { ++ .owner = THIS_MODULE, ++ .write = rwnx_wifi_suspend_write_proc, ++}; ++ ++void rwnx_init_wifi_suspend_node(void){ ++ struct proc_dir_entry *ent; ++ ++ wifi_suspend_node = proc_mkdir("wifi_suspend", NULL); ++ if (wifi_suspend_node == NULL) { ++ printk("Unable to create /proc/wifi_suspend directory"); ++ } ++ ++ ent = proc_create("suspend", 0660, wifi_suspend_node, &wifi_suspend_fops); ++ if (ent == NULL) { ++ printk("Unable to create /proc/wifi_suspend/suspend"); ++ } ++} ++ ++void rwnx_deinit_wifi_suspend_node(void){ ++ remove_proc_entry("suspend", wifi_suspend_node); ++ remove_proc_entry("wifi_suspend", 0); ++} ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h +new file mode 100644 +index 000000000000..7e3e16fd405c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h +@@ -0,0 +1,226 @@ ++/** ++ * aicwf_sdio.h ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_SDMMC_H_ ++#define _AICWF_SDMMC_H_ ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include ++#include ++#include ++#include ++#include "rwnx_cmds.h" ++#include "aicwf_rx_prealloc.h" ++#define AICWF_SDIO_NAME "aicwf_sdio" ++#define SDIOWIFI_FUNC_BLOCKSIZE 512 ++ ++#define SDIOWIFI_BYTEMODE_LEN_REG 0x02 ++#define SDIOWIFI_INTR_CONFIG_REG 0x04 ++#define SDIOWIFI_SLEEP_REG 0x05 ++#define SDIOWIFI_WAKEUP_REG 0x09 ++#define SDIOWIFI_FLOW_CTRL_REG 0x0A ++#define SDIOWIFI_REGISTER_BLOCK 0x0B ++#define SDIOWIFI_BYTEMODE_ENABLE_REG 0x11 ++#define SDIOWIFI_BLOCK_CNT_REG 0x12 ++#define SDIOWIFI_FLOWCTRL_MASK_REG 0x7F ++#define SDIOWIFI_WR_FIFO_ADDR 0x07 ++#define SDIOWIFI_RD_FIFO_ADDR 0x08 ++ ++#define SDIOWIFI_INTR_ENABLE_REG_V3 0x00 ++#define SDIOWIFI_INTR_PENDING_REG_V3 0x01 ++#define SDIOWIFI_INTR_TO_DEVICE_REG_V3 0x02 ++#define SDIOWIFI_FLOW_CTRL_Q1_REG_V3 0x03 ++#define SDIOWIFI_MISC_INT_STATUS_REG_V3 0x04 ++#define SDIOWIFI_BYTEMODE_LEN_REG_V3 0x05 ++#define SDIOWIFI_BYTEMODE_LEN_MSB_REG_V3 0x06 ++#define SDIOWIFI_BYTEMODE_ENABLE_REG_V3 0x07 ++#define SDIOWIFI_MISC_CTRL_REG_V3 0x08 ++#define SDIOWIFI_FLOW_CTRL_Q2_REG_V3 0x09 ++#define SDIOWIFI_CLK_TEST_RESULT_REG_V3 0x0A ++#define SDIOWIFI_RD_FIFO_ADDR_V3 0x0F ++#define SDIOWIFI_WR_FIFO_ADDR_V3 0x10 ++ ++#define SDIOCLK_FREE_RUNNING_BIT (1 << 6) ++ ++#define SDIOWIFI_PWR_CTRL_INTERVAL 30 ++#define FLOW_CTRL_RETRY_COUNT 50 ++#define BUFFER_SIZE 1536 ++#define TAIL_LEN 4 ++#define TXQLEN (2048*4) ++ ++#define SDIO_SLEEP_ST 0 ++#define SDIO_ACTIVE_ST 1 ++ ++#define DATA_FLOW_CTRL_THRESH 2 ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++#define AICWF_SDIO_TX_LOW_WATER 100 ++#define AICWF_SDIO_TX_HIGH_WATER 500 ++#endif ++ ++#ifdef CONFIG_TEMP_CONTROL ++#define TEMP_GET_INTERVAL (60 * 1000) ++#define TEMP_THD_1 80 //temperature 1 (℃) ++#define TEMP_THD_2 95 //temperature 2 (℃) ++#define BUFFERING_V1 8 ++#define BUFFERING_V2 13 ++#define TMR_INTERVAL_1 60 //timer_1 60ms ++#define TMR_INTERVAL_2 180 //timer_2 130ms ++#endif ++ ++typedef enum { ++ SDIO_TYPE_DATA = 0X00, ++ SDIO_TYPE_CFG = 0X10, ++ SDIO_TYPE_CFG_CMD_RSP = 0X11, ++ SDIO_TYPE_CFG_DATA_CFM = 0X12, ++ SDIO_TYPE_CFG_PRINT = 0X13 ++} sdio_type; ++ ++/* SDIO Device ID */ ++#define SDIO_VENDOR_ID_AIC8801 0x5449 ++#define SDIO_VENDOR_ID_AIC8800DC 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80X2 0xc8a1 ++ ++#define SDIO_DEVICE_ID_AIC8801 0x0145 ++#define SDIO_DEVICE_ID_AIC8800DC 0xc08d ++#define SDIO_DEVICE_ID_AIC8800D80 0x0082 ++#define SDIO_DEVICE_ID_AIC8800D80X2 0x2082 ++ ++enum AICWF_IC{ ++ PRODUCT_ID_AIC8801 = 0, ++ PRODUCT_ID_AIC8800DC, ++ PRODUCT_ID_AIC8800DW, ++ PRODUCT_ID_AIC8800D80, ++ PRODUCT_ID_AIC8800D80X2 ++}; ++ ++ ++struct rwnx_hw; ++ ++struct aic_sdio_reg { ++ u8 bytemode_len_reg; ++ u8 intr_config_reg; ++ u8 sleep_reg; ++ u8 wakeup_reg; ++ u8 flow_ctrl_reg; ++ u8 flowctrl_mask_reg; ++ u8 register_block; ++ u8 bytemode_enable_reg; ++ u8 block_cnt_reg; ++ u8 misc_int_status_reg; ++ u8 rd_fifo_addr; ++ u8 wr_fifo_addr; ++}; ++ ++struct aic_sdio_dev { ++ struct rwnx_hw *rwnx_hw; ++ struct sdio_func *func; ++ struct sdio_func *func2; ++ struct device *dev; ++ struct aicwf_bus *bus_if; ++ struct rwnx_cmd_mgr cmd_mgr; ++ ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ u32 state; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ u8 flowctrl; ++ spinlock_t tx_flow_lock; ++#endif ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ //for sdio pwr ctrl ++ struct timer_list timer; ++ uint active_duration; ++ struct completion pwrctrl_trgg; ++ struct task_struct *pwrctl_tsk; ++ spinlock_t pwrctl_lock; ++ struct semaphore pwrctl_wakeup_sema; ++ #endif ++ u16 chipid; ++ struct aic_sdio_reg sdio_reg; ++ ++ spinlock_t wslock;//AIDEN test ++ bool oob_enable; ++ atomic_t is_bus_suspend; ++ ++#ifdef CONFIG_TEMP_CONTROL ++ spinlock_t tx_flow_lock; ++ struct timer_list netif_timer; ++ struct timer_list tp_ctrl_timer; ++ struct work_struct tp_ctrl_work; ++ struct work_struct netif_work; ++ s8_l cur_temp; ++ bool net_stop; ++ bool on_off; //for command, 0 - off, 1 - on ++ int8_t get_level; //for command, 0 - 100%, 1 - 12%, 2 - 3% ++ int8_t set_level; //for command, 0 - driver auto, 1 - 12%, 2 - 3% ++ int interval_t1; ++ int interval_t2; ++ u8_l cur_stat; //0--normal temp, 1/2--buffering temp ++#endif ++ ++}; ++ ++#ifdef CONFIG_TEMP_CONTROL ++void aicwf_netif_worker(struct work_struct *work); ++void aicwf_temp_ctrl_worker(struct work_struct *work); ++void aicwf_temp_ctrl(struct aic_sdio_dev *sdiodev); ++void aicwf_netif_ctrl(struct aic_sdio_dev *sdiodev, int val); ++#endif ++extern struct aicwf_rx_buff_list aic_rx_buff_list; ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++int aicwf_sdio_func2_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val); ++int aicwf_sdio_func2_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration); ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target); ++#endif ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev); ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++void aicwf_sdio_tx_netif_flowctrl(struct rwnx_hw *rwnx_hw, bool state); ++#endif ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev); ++#ifdef CONFIG_PREALLOC_RX_SKB ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct rx_buff *rxbbuf, u32 size); ++#else ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size); ++#endif ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count); ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_exit(void); ++void aicwf_sdio_register(void); ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt); ++int sdio_bustx_thread(void *data); ++int sdio_busrx_thread(void *data); ++#ifdef CONFIG_OOB ++//new oob feature ++int sdio_busirq_thread(void *data); ++#endif //CONFIG_OOB ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt); ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv, u8 txnow); ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv); ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv); ++extern void aicwf_hostif_ready(void); ++extern void aicwf_hostif_fail(void); ++#ifdef CONFIG_PLATFORM_AMLOGIC ++extern void extern_wifi_set_enable(int is_on); ++extern void sdio_reinit(void); ++#endif /*CONFIG_PLATFORM_AMLOGIC*/ ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size); ++ ++#endif /* AICWF_SDIO_SUPPORT */ ++ ++#endif /*_AICWF_SDMMC_H_*/ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c +new file mode 100644 +index 000000000000..d74bd8d1f420 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c +@@ -0,0 +1,646 @@ ++#include"aicwf_tcp_ack.h" ++//#include"rwnx_tx.h" ++//#include "aicwf_tcp_ack.h" ++#include"rwnx_defs.h" ++extern int intf_tx(struct rwnx_hw *priv,struct msg_buf *msg); ++struct msg_buf *intf_tcp_alloc_msg(struct msg_buf *msg) ++{ ++ //printk("%s \n",__func__); ++ int len=sizeof(struct msg_buf) ; ++ msg = kzalloc(len , /*GFP_KERNEL*/GFP_ATOMIC); ++ if(!msg) ++ printk("%s: alloc failed \n", __func__); ++ memset(msg,0,len); ++ return msg; ++} ++ ++void intf_tcp_drop_msg(struct rwnx_hw *priv, ++ struct msg_buf *msg) ++{ ++ //printk("%s \n",__func__); ++ if (msg->skb) ++ dev_kfree_skb_any(msg->skb); ++ ++ kfree(msg); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void tcp_ack_timeout(unsigned long data) ++#else ++void tcp_ack_timeout(struct timer_list *t) ++#endif ++{ ++ //printk("%s \n",__func__); ++ struct tcp_ack_info *ack_info; ++ struct msg_buf *msg; ++ struct tcp_ack_manage *ack_m = NULL; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ ack_info = (struct tcp_ack_info *)data; ++#else ++ ack_info = container_of(t,struct tcp_ack_info,timer); ++#endif ++ ++ ack_m = container_of(ack_info, struct tcp_ack_manage, ++ ack_info[ack_info->ack_info_num]); ++ ++ write_seqlock_bh(&ack_info->seqlock); ++ msg = ack_info->msgbuf; ++ if (ack_info->busy && msg && !ack_info->in_send_msg) { ++ ack_info->msgbuf = NULL; ++ ack_info->drop_cnt = 0; ++ ack_info->in_send_msg = msg; ++ write_sequnlock_bh(&ack_info->seqlock); ++ intf_tx(ack_m->priv, msg);//send skb ++ //ack_info->in_send_msg = NULL;//add by dwx ++ //write_sequnlock_bh(&ack_info->seqlock); ++ //intf_tx(ack_m->priv, msg); ++ return; ++ } ++ write_sequnlock_bh(&ack_info->seqlock); ++} ++ ++void tcp_ack_init(struct rwnx_hw *priv) ++{ ++ int i; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ ++ printk("%s \n",__func__); ++ memset(ack_m, 0, sizeof(struct tcp_ack_manage)); ++ ack_m->priv = priv; ++ spin_lock_init(&ack_m->lock); ++ atomic_set(&ack_m->max_drop_cnt, TCP_ACK_DROP_CNT); ++ ack_m->last_time = jiffies; ++ ack_m->timeout = msecs_to_jiffies(ACK_OLD_TIME); ++ ++ for (i = 0; i < TCP_ACK_NUM; i++) { ++ ack_info = &ack_m->ack_info[i]; ++ ack_info->ack_info_num = i; ++ seqlock_init(&ack_info->seqlock); ++ ack_info->last_time = jiffies; ++ ack_info->timeout = msecs_to_jiffies(ACK_OLD_TIME); ++ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ setup_timer(&ack_info->timer, tcp_ack_timeout, ++ (unsigned long)ack_info); ++ #else ++ timer_setup(&ack_info->timer,tcp_ack_timeout,0); ++ #endif ++ } ++ ++ atomic_set(&ack_m->enable, 1); ++ ack_m->ack_winsize = MIN_WIN; ++} ++ ++void tcp_ack_deinit(struct rwnx_hw *priv) ++{ ++ int i; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ struct msg_buf *drop_msg = NULL; ++ ++ printk("%s \n",__func__); ++ atomic_set(&ack_m->enable, 0); ++ ++ for (i = 0; i < TCP_ACK_NUM; i++) { ++ drop_msg = NULL; ++ ++ write_seqlock_bh(&ack_m->ack_info[i].seqlock); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_m->ack_info[i].timer); ++#else ++ del_timer(&ack_m->ack_info[i].timer); ++#endif ++ drop_msg = ack_m->ack_info[i].msgbuf; ++ ack_m->ack_info[i].msgbuf = NULL; ++ write_sequnlock_bh(&ack_m->ack_info[i].seqlock); ++ ++ if (drop_msg) ++ intf_tcp_drop_msg(priv, drop_msg);//drop skb ++ } ++} ++ ++int tcp_check_quick_ack(unsigned char *buf, ++ struct tcp_ack_msg *msg) ++{ ++ int ip_hdr_len; ++ unsigned char *temp; ++ struct ethhdr *ethhdr; ++ struct iphdr *iphdr; ++ struct tcphdr *tcphdr; ++ ++ ethhdr = (struct ethhdr *)buf; ++ if (ethhdr->h_proto != htons(ETH_P_IP)) ++ return 0; ++ iphdr = (struct iphdr *)(ethhdr + 1); ++ if (iphdr->version != 4 || iphdr->protocol != IPPROTO_TCP) ++ return 0; ++ ip_hdr_len = iphdr->ihl * 4; ++ temp = (unsigned char *)(iphdr) + ip_hdr_len; ++ tcphdr = (struct tcphdr *)temp; ++ /* TCP_FLAG_ACK */ ++ if (!(temp[13] & 0x10)) ++ return 0; ++ ++ if (temp[13] & 0x8) { ++ msg->saddr = iphdr->daddr; ++ msg->daddr = iphdr->saddr; ++ msg->source = tcphdr->dest; ++ msg->dest = tcphdr->source; ++ msg->seq = ntohl(tcphdr->seq); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int is_drop_tcp_ack(struct tcphdr *tcphdr, int tcp_tot_len, ++ unsigned short *win_scale) ++{ ++ //printk("%s \n",__func__); ++ int drop = 1; ++ int len = tcphdr->doff * 4; ++ unsigned char *ptr; ++ ++ if(tcp_tot_len > len) { ++ drop = 0; ++ } else { ++ len -= sizeof(struct tcphdr); ++ ptr = (unsigned char *)(tcphdr + 1); ++ ++ while ((len > 0) && drop) { ++ int opcode = *ptr++; ++ int opsize; ++ ++ switch (opcode) { ++ case TCPOPT_EOL: ++ break; ++ case TCPOPT_NOP: ++ len--; ++ continue; ++ default: ++ opsize = *ptr++; ++ if (opsize < 2) ++ break; ++ if (opsize > len) ++ break; ++ ++ switch (opcode) { ++ /* TODO: Add other ignore opt */ ++ case TCPOPT_TIMESTAMP: ++ break; ++ case TCPOPT_WINDOW: ++ if (*ptr < 15) ++ *win_scale = (1 << (*ptr)); ++ //printk("%d\n",*win_scale); ++ break; ++ default: ++ drop = 2; ++ } ++ ++ ptr += opsize - 2; ++ len -= opsize; ++ } ++ } ++ } ++ ++ return drop; ++} ++ ++ ++/* flag:0 for not tcp ack ++ * 1 for ack which can be drop ++ * 2 for other ack whith more info ++ */ ++ ++int tcp_check_ack(unsigned char *buf, ++ struct tcp_ack_msg *msg, ++ unsigned short *win_scale) ++{ ++ int ret; ++ int ip_hdr_len; ++ int tcp_tot_len; ++ unsigned char *temp; ++ struct ethhdr *ethhdr; ++ struct iphdr *iphdr; ++ struct tcphdr *tcphdr; ++ ++ ethhdr =(struct ethhdr *)buf; ++ if (ethhdr->h_proto != htons(ETH_P_IP)) ++ return 0; ++ ++ iphdr = (struct iphdr *)(ethhdr + 1); ++ if (iphdr->version != 4 || iphdr->protocol != IPPROTO_TCP) ++ return 0; ++ ++ ip_hdr_len = iphdr->ihl * 4; ++ temp = (unsigned char *)(iphdr) + ip_hdr_len; ++ tcphdr = (struct tcphdr *)temp; ++ /* TCP_FLAG_ACK */ ++ if (!(temp[13] & 0x10)) ++ return 0; ++ ++ tcp_tot_len = ntohs(iphdr->tot_len) - ip_hdr_len;// tcp total len ++ ret = is_drop_tcp_ack(tcphdr, tcp_tot_len, win_scale); ++ //printk("is drop:%d \n",ret); ++ ++ if (ret > 0) { ++ msg->saddr = iphdr->saddr; ++ msg->daddr = iphdr->daddr; ++ msg->source = tcphdr->source; ++ msg->dest = tcphdr->dest; ++ msg->seq = ntohl(tcphdr->ack_seq); ++ msg->win = ntohs(tcphdr->window); ++ } ++ ++ return ret; ++} ++ ++/* return val: -1 for not match, others for match */ ++int tcp_ack_match(struct tcp_ack_manage *ack_m, ++ struct tcp_ack_msg *ack_msg) ++{ ++ int i, ret = -1; ++ unsigned start; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_msg *ack; ++ ++ for (i = 0; ((ret < 0) && (i < TCP_ACK_NUM)); i++) { ++ ack_info = &ack_m->ack_info[i]; ++ do { ++ start = read_seqbegin(&ack_info->seqlock); ++ ret = -1; ++ ++ ack = &ack_info->ack_msg; ++ if (ack_info->busy && ++ ack->dest == ack_msg->dest && ++ ack->source == ack_msg->source && ++ ack->saddr == ack_msg->saddr && ++ ack->daddr == ack_msg->daddr) ++ ret = i; ++ } while(read_seqretry(&ack_info->seqlock, start)); ++ } ++ ++ return ret; ++} ++ ++ ++void tcp_ack_update(struct tcp_ack_manage *ack_m) ++{ ++ int i; ++ struct tcp_ack_info *ack_info; ++ ++ if (time_after(jiffies, ack_m->last_time + ack_m->timeout)) { ++ spin_lock_bh(&ack_m->lock); ++ ack_m->last_time = jiffies; ++ for (i = TCP_ACK_NUM - 1; i >= 0; i--) { ++ ack_info = &ack_m->ack_info[i]; ++ write_seqlock_bh(&ack_info->seqlock); ++ if (ack_info->busy && ++ time_after(jiffies, ack_info->last_time + ++ ack_info->timeout)) { ++ ack_m->free_index = i; ++ ack_m->max_num--; ++ ack_info->busy = 0; ++ } ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++ spin_unlock_bh(&ack_m->lock); ++ } ++} ++ ++/* return val: -1 for no index, others for index */ ++int tcp_ack_alloc_index(struct tcp_ack_manage *ack_m) ++{ ++ int i, ret = -1; ++ struct tcp_ack_info *ack_info; ++ unsigned start; ++ ++ spin_lock_bh(&ack_m->lock); ++ if (ack_m->max_num == TCP_ACK_NUM) { ++ spin_unlock_bh(&ack_m->lock); ++ return -1; ++ } ++ ++ if (ack_m->free_index >= 0) { ++ i = ack_m->free_index; ++ ack_m->free_index = -1; ++ ack_m->max_num++; ++ spin_unlock_bh(&ack_m->lock); ++ return i; ++ } ++ ++ for (i = 0; ((ret < 0) && (i < TCP_ACK_NUM)); i++) { ++ ack_info = &ack_m->ack_info[i]; ++ do { ++ start = read_seqbegin(&ack_info->seqlock); ++ ret = -1; ++ if (!ack_info->busy) { ++ ack_m->free_index = -1; ++ ack_m->max_num++; ++ ret = i; ++ } ++ } while(read_seqretry(&ack_info->seqlock, start)); ++ } ++ spin_unlock_bh(&ack_m->lock); ++ ++ return ret; ++} ++ ++ ++/* return val: 0 for not handle tx, 1 for handle tx */ ++int tcp_ack_handle(struct msg_buf *new_msgbuf, ++ struct tcp_ack_manage *ack_m, ++ struct tcp_ack_info *ack_info, ++ struct tcp_ack_msg *ack_msg, ++ int type) ++{ ++ int quick_ack = 0; ++ struct tcp_ack_msg *ack; ++ int ret = 0; ++ struct msg_buf *drop_msg = NULL; ++ ++ //printk("%s %d",__func__,type); ++ write_seqlock_bh(&ack_info->seqlock); ++ ++ ack_info->last_time = jiffies; ++ ack = &ack_info->ack_msg; ++ ++ if (type == 2) { ++ if (U32_BEFORE(ack->seq, ack_msg->seq)) { ++ ack->seq = ack_msg->seq; ++ if (ack_info->psh_flag && ++ !U32_BEFORE(ack_msg->seq, ++ ack_info->psh_seq)) { ++ ack_info->psh_flag = 0; ++ } ++ ++ if (ack_info->msgbuf) { ++ //printk("%lx \n",ack_info->msgbuf); ++ drop_msg = ack_info->msgbuf; ++ ack_info->msgbuf = NULL; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_info->timer); ++#else ++ del_timer(&ack_info->timer); ++#endif ++ }else{ ++ //printk("msgbuf is NULL \n"); ++ } ++ ++ ack_info->in_send_msg = NULL; ++ ack_info->drop_cnt = atomic_read(&ack_m->max_drop_cnt); ++ } else { ++ printk("%s before abnormal ack: %d, %d\n", ++ __func__, ack->seq, ack_msg->seq); ++ drop_msg = new_msgbuf; ++ ret = 1; ++ } ++ } else if (U32_BEFORE(ack->seq, ack_msg->seq)) { ++ if (ack_info->msgbuf) { ++ drop_msg = ack_info->msgbuf; ++ ack_info->msgbuf = NULL; ++ } ++ ++ if (ack_info->psh_flag && ++ !U32_BEFORE(ack_msg->seq, ack_info->psh_seq)) { ++ ack_info->psh_flag = 0; ++ quick_ack = 1; ++ } else { ++ ack_info->drop_cnt++; ++ } ++ ++ ack->seq = ack_msg->seq; ++ ++ if (quick_ack || (!ack_info->in_send_msg && ++ (ack_info->drop_cnt >= ++ atomic_read(&ack_m->max_drop_cnt)))) { ++ ack_info->drop_cnt = 0; ++ ack_info->in_send_msg = new_msgbuf; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_info->timer); ++#else ++ del_timer(&ack_info->timer); ++#endif ++ } else { ++ ret = 1; ++ ack_info->msgbuf = new_msgbuf; ++ if (!timer_pending(&ack_info->timer)) ++ mod_timer(&ack_info->timer, ++ (jiffies + msecs_to_jiffies(5))); ++ } ++ } else { ++ printk("%s before ack: %d, %d\n", ++ __func__, ack->seq, ack_msg->seq); ++ drop_msg = new_msgbuf; ++ ret = 1; ++ } ++ ++ write_sequnlock_bh(&ack_info->seqlock); ++ ++ if (drop_msg) ++ intf_tcp_drop_msg(ack_m->priv, drop_msg);// drop skb ++ ++ return ret; ++} ++ ++int tcp_ack_handle_new(struct msg_buf *new_msgbuf, ++ struct tcp_ack_manage *ack_m, ++ struct tcp_ack_info *ack_info, ++ struct tcp_ack_msg *ack_msg, ++ int type) ++{ ++ int quick_ack = 0; ++ struct tcp_ack_msg *ack; ++ int ret = 0; ++ struct msg_buf *drop_msg = NULL; ++ //struct msg_buf * send_msg = NULL; ++ //printk("",); ++ write_seqlock_bh(&ack_info->seqlock); ++ ++ ack_info->last_time = jiffies; ++ ack = &ack_info->ack_msg; ++ ++ if(U32_BEFORE(ack->seq, ack_msg->seq)){ ++ if (ack_info->msgbuf) { ++ drop_msg = ack_info->msgbuf; ++ ack_info->msgbuf = NULL; ++ //ack_info->drop_cnt++; ++ } ++ ++ if (ack_info->psh_flag && ++ !U32_BEFORE(ack_msg->seq, ack_info->psh_seq)) { ++ ack_info->psh_flag = 0; ++ quick_ack = 1; ++ } else { ++ ack_info->drop_cnt++; ++ } ++ ++ ack->seq = ack_msg->seq; ++ ++ if(quick_ack || (!ack_info->in_send_msg && ++ (ack_info->drop_cnt >= ++ atomic_read(&ack_m->max_drop_cnt)))){ ++ ack_info->drop_cnt = 0; ++ //send_msg = new_msgbuf; ++ ack_info->in_send_msg = new_msgbuf; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_info->timer); ++#else ++ del_timer(&ack_info->timer); ++#endif ++ }else{ ++ ret = 1; ++ ack_info->msgbuf = new_msgbuf; ++ if (!timer_pending(&ack_info->timer)) ++ mod_timer(&ack_info->timer, ++ (jiffies + msecs_to_jiffies(5))); ++ } ++ ++ //ret = 1; ++ }else { ++ printk("%s before ack: %d, %d\n", ++ __func__, ack->seq, ack_msg->seq); ++ drop_msg = new_msgbuf; ++ ret = 1; ++ } ++ ++ /*if(send_msg){ ++ intf_tx(ack_m->priv,send_msg); ++ ack_info->in_send_msg=NULL; ++ }*/ ++ ++ //ack_info->in_send_msg=NULL; ++ ++ write_sequnlock_bh(&ack_info->seqlock); ++ ++ /*if(send_msg){ ++ intf_tx(ack_m->priv,send_msg); ++ //ack_info->in_send_msg=NULL; ++ }*/ ++ ++ if (drop_msg) ++ intf_tcp_drop_msg(ack_m->priv, drop_msg);// drop skb ++ ++ return ret; ++ ++} ++ ++void filter_rx_tcp_ack(struct rwnx_hw *priv, ++ unsigned char *buf, unsigned plen) ++{ ++ int index; ++ struct tcp_ack_msg ack_msg; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ ++ if (!atomic_read(&ack_m->enable)) ++ return; ++ ++ if ((plen > MAX_TCP_ACK) || ++ !tcp_check_quick_ack(buf, &ack_msg)) ++ return; ++ ++ index = tcp_ack_match(ack_m, &ack_msg); ++ if (index >= 0) { ++ ack_info = ack_m->ack_info + index; ++ write_seqlock_bh(&ack_info->seqlock); ++ ack_info->psh_flag = 1; ++ ack_info->psh_seq = ack_msg.seq; ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++} ++ ++/* return val: 0 for not filter, 1 for filter */ ++int filter_send_tcp_ack(struct rwnx_hw *priv, ++ struct msg_buf *msgbuf, ++ unsigned char *buf, unsigned int plen) ++{ ++ //printk("%s \n",__func__); ++ int ret = 0; ++ int index, drop; ++ unsigned short win_scale = 0; ++ unsigned int win = 0; ++ struct tcp_ack_msg ack_msg; ++ struct tcp_ack_msg *ack; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ ++ tcp_ack_update(ack_m); ++ drop = tcp_check_ack(buf, &ack_msg, &win_scale); ++ //printk("drop:%d win_scale:%d",drop,win_scale); ++ if (!drop && (0 == win_scale)) ++ return 0; ++ ++ index = tcp_ack_match(ack_m, &ack_msg); ++ if (index >= 0) { ++ ack_info = ack_m->ack_info + index; ++ if ((0 != win_scale) && ++ (ack_info->win_scale != win_scale)) { ++ write_seqlock_bh(&ack_info->seqlock); ++ ack_info->win_scale = win_scale; ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++ ++ if (drop > 0 && atomic_read(&ack_m->enable)) { ++ win = ack_info->win_scale * ack_msg.win; ++ if ((win_scale!=0) && (win < (ack_m->ack_winsize * SIZE_KB))) ++ { ++ drop = 2; ++ printk("%d %d %d",win_scale,win,(ack_m->ack_winsize * SIZE_KB)); ++ } ++ ret = tcp_ack_handle_new(msgbuf, ack_m, ack_info, ++ &ack_msg, drop); ++ } ++ ++ goto out; ++ } ++ ++ index = tcp_ack_alloc_index(ack_m); ++ if (index >= 0) { ++ write_seqlock_bh(&ack_m->ack_info[index].seqlock); ++ ack_m->ack_info[index].busy = 1; ++ ack_m->ack_info[index].psh_flag = 0; ++ ack_m->ack_info[index].last_time = jiffies; ++ ack_m->ack_info[index].drop_cnt = ++ atomic_read(&ack_m->max_drop_cnt); ++ ack_m->ack_info[index].win_scale = ++ (win_scale != 0) ? win_scale : 1; ++ ++ //ack_m->ack_info[index].msgbuf = NULL; ++ //ack_m->ack_info[index].in_send_msg = NULL; ++ ack = &ack_m->ack_info[index].ack_msg; ++ ack->dest = ack_msg.dest; ++ ack->source = ack_msg.source; ++ ack->saddr = ack_msg.saddr; ++ ack->daddr = ack_msg.daddr; ++ ack->seq = ack_msg.seq; ++ write_sequnlock_bh(&ack_m->ack_info[index].seqlock); ++ } ++ ++out: ++ return ret; ++} ++ ++void move_tcpack_msg(struct rwnx_hw *priv, ++ struct msg_buf *msg) ++{ ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ int i = 0; ++ ++ if (!atomic_read(&ack_m->enable)) ++ return; ++ ++ //if (msg->len > MAX_TCP_ACK) ++ // return; ++ ++ for (i = 0; i < TCP_ACK_NUM; i++) { ++ ack_info = &ack_m->ack_info[i]; ++ write_seqlock_bh(&ack_info->seqlock); ++ if (ack_info->busy && (ack_info->in_send_msg == msg)) ++ ack_info->in_send_msg = NULL; ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h +new file mode 100644 +index 000000000000..542023fc577c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h +@@ -0,0 +1,92 @@ ++#ifndef _AICWF_TCP_ACK_H_ ++#define _AICWF_TCP_ACK_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define TCP_ACK_NUM 32 ++#define TCP_ACK_EXIT_VAL 0x800 ++#define TCP_ACK_DROP_CNT 10 ++ ++#define ACK_OLD_TIME 4000 ++#define U32_BEFORE(a, b) ((__s32)((__u32)a - (__u32)b) <= 0) ++ ++#define MAX_TCP_ACK 200 ++/*min window size in KB, it's 256KB*/ ++#define MIN_WIN 256 ++#define SIZE_KB 1024 ++ ++ ++struct msg_buf { ++ //struct list_head list; ++ struct sk_buff *skb; ++ struct rwnx_vif *rwnx_vif; ++ /* data just tx cmd use,not include the head */ ++}; ++ ++struct tcp_ack_msg { ++ u16 source; ++ u16 dest; ++ s32 saddr; ++ s32 daddr; ++ u32 seq; ++ u16 win; ++}; ++ ++ ++struct tcp_ack_info { ++ int ack_info_num; ++ int busy; ++ int drop_cnt; ++ int psh_flag; ++ u32 psh_seq; ++ u16 win_scale; ++ /* seqlock for ack info */ ++ seqlock_t seqlock; ++ unsigned long last_time; ++ unsigned long timeout; ++ struct timer_list timer; ++ struct msg_buf *msgbuf; ++ struct msg_buf *in_send_msg; ++ struct tcp_ack_msg ack_msg; ++}; ++ ++struct tcp_ack_manage { ++ /* 1 filter */ ++ atomic_t enable; ++ int max_num; ++ int free_index; ++ unsigned long last_time; ++ unsigned long timeout; ++ atomic_t max_drop_cnt; ++ /* lock for tcp ack alloc and free */ ++ spinlock_t lock; ++ struct rwnx_hw *priv; ++ struct tcp_ack_info ack_info[TCP_ACK_NUM]; ++ /*size in KB*/ ++ unsigned int ack_winsize; ++}; ++ ++struct msg_buf *intf_tcp_alloc_msg(struct msg_buf *msg); ++ ++void tcp_ack_init(struct rwnx_hw *priv); ++ ++void tcp_ack_deinit(struct rwnx_hw *priv); ++ ++ ++int is_drop_tcp_ack(struct tcphdr *tcphdr, int tcp_tot_len, unsigned short *win_scale); ++ ++int is_tcp_ack(struct sk_buff *skb, unsigned short *win_scale); ++ ++int filter_send_tcp_ack(struct rwnx_hw *priv, struct msg_buf *msgbuf,unsigned char *buf, unsigned int plen); ++ ++void filter_rx_tcp_ack(struct rwnx_hw *priv,unsigned char *buf, unsigned plen); ++ ++void move_tcpack_msg(struct rwnx_hw *priv, struct msg_buf * msg); ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c +new file mode 100644 +index 000000000000..555a8deadf54 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c +@@ -0,0 +1,891 @@ ++/** ++ * aicwf_bus.c ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "lmac_msg.h" ++#include "aicwf_txrxif.h" ++#include "rwnx_platform.h" ++#include "rwnx_defs.h" ++#include "rwnx_msg_rx.h" ++#include "rwnx_rx.h" ++#include "aicwf_rx_prealloc.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "sdio_host.h" ++#endif ++#include "aic_bsp_export.h" ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++void aicwf_rxframe_queue_init_2(struct rx_frame_queue *pq, int max_len) ++{ ++ //int prio; ++ ++ memset(pq, 0, offsetof(struct rx_frame_queue, queuelist) + (sizeof(struct list_head))); ++ pq->qmax = (u16)max_len; ++ INIT_LIST_HEAD(&pq->queuelist); ++#if 0 ++ memset(pq, 0, offsetof(struct rx_frame_queue, queuelist) + (sizeof(struct list_head) * num_prio)); ++ pq->num_prio = (u16)num_prio; ++ pq->qmax = (u16)max_len; ++ ++ for (prio = 0; prio < num_prio; prio++) { ++ INIT_LIST_HEAD(&pq->queuelist[prio]); ++ } ++#endif ++} ++ ++//extern struct aic_sdio_dev *g_sdiodev; ++void rxbuff_queue_flush(struct aicwf_rx_priv* rx_priv) ++{ ++ ++ //int prio; ++ struct rx_frame_queue *pq = &rx_priv->rxq; ++ struct list_head *pos; ++ struct list_head *n; ++ struct list_head *head; ++ struct rx_buff *tempbuf = NULL; ++ ++ head = &pq->queuelist; ++ list_for_each_safe(pos, n, head) { ++ tempbuf = list_entry(pos, struct rx_buff, queue); ++ list_del_init(&tempbuf->queue); ++#if 0 ++ rxbuff_free(tempbuf); ++#else ++ aicwf_prealloc_rxbuff_free(tempbuf, &rx_priv->rxbuff_lock); ++#endif ++ pq->qcnt--; ++ } ++} ++#endif ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if; ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return -1; ++ } ++ bus_if = dev_get_drvdata(dev); ++ bus_if->cmd_buf = kzalloc(CMD_BUF_MAX, GFP_KERNEL); ++ if (!bus_if->cmd_buf) { ++ ret = -ENOMEM; ++ txrx_err("proto_attach failed\n"); ++ goto fail; ++ } ++ memset(bus_if->cmd_buf, '\0', CMD_BUF_MAX); ++ ++ init_completion(&bus_if->bustx_trgg); ++ init_completion(&bus_if->busrx_trgg); ++ //new oob feature ++ init_completion(&bus_if->busirq_trgg); ++#ifdef AICWF_SDIO_SUPPORT ++ spin_lock_init(&bus_if->bus_priv.sdio->wslock);//AIDEN test ++ bus_if->bustx_thread = kthread_run(sdio_bustx_thread, (void *)bus_if, "aicwf_bustx_thread"); ++ bus_if->busrx_thread = kthread_run(sdio_busrx_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busrx_thread"); ++ //new oob feature ++#ifdef CONFIG_OOB ++ if(bus_if->bus_priv.sdio->oob_enable){ ++ bus_if->busirq_thread = kthread_run(sdio_busirq_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busirq_thread"); ++ } ++#endif //CONFIG_OOB ++#endif ++#ifdef AICWF_USB_SUPPORT ++ bus_if->bustx_thread = kthread_run(usb_bustx_thread, (void *)bus_if, "aicwf_bustx_thread"); ++ bus_if->busrx_thread = kthread_run(usb_busrx_thread, (void *)bus_if->bus_priv.usb->rx_priv, "aicwf_busrx_thread"); ++#endif ++ ++ if (IS_ERR(bus_if->bustx_thread)) { ++ bus_if->bustx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ goto fail; ++ } ++ ++ if (IS_ERR(bus_if->busrx_thread)) { ++ bus_if->busrx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ goto fail; ++ } ++ ++ return ret; ++fail: ++ aicwf_bus_deinit(dev); ++ ++ return ret; ++} ++ ++void aicwf_bus_deinit(struct device *dev) ++{ ++ struct aicwf_bus *bus_if; ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usb; ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return; ++ } ++ AICWFDBG(LOGINFO, "%s Enter\r\n", __func__); ++ bus_if = dev_get_drvdata(dev); ++ aicwf_bus_stop(bus_if); ++ ++#ifdef AICWF_USB_SUPPORT ++ usb = bus_if->bus_priv.usb; ++ if (g_rwnx_plat->enabled) ++ rwnx_platform_deinit(usb->rwnx_hw); ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ sdiodev = bus_if->bus_priv.sdio; ++ if (g_rwnx_plat && g_rwnx_plat->enabled) { ++ rwnx_platform_deinit(sdiodev->rwnx_hw); ++ } ++#endif ++ ++ if (bus_if->cmd_buf) { ++ kfree(bus_if->cmd_buf); ++ bus_if->cmd_buf = NULL; ++ } ++ ++ if (bus_if->bustx_thread) { ++ complete_all(&bus_if->bustx_trgg); ++ kthread_stop(bus_if->bustx_thread); ++ bus_if->bustx_thread = NULL; ++ } ++ AICWFDBG(LOGINFO, "%s Exit\r\n", __func__); ++} ++ ++void aicwf_frame_tx(void *dev, struct sk_buff *skb) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ aicwf_bus_txdata(sdiodev->bus_if, skb); ++#else ++ struct aic_usb_dev *usbdev = (struct aic_usb_dev *)dev; ++ ++ if (!usbdev->state) { ++ txrx_err("down\n"); ++ aicwf_usb_tx_flowctrl(usbdev->rwnx_hw, true); ++ dev_kfree_skb(skb); ++ return; ++ } ++ aicwf_bus_txdata(usbdev->bus_if, skb); ++#endif ++} ++ ++struct aicwf_tx_priv *aicwf_tx_init(void *arg) ++{ ++ struct aicwf_tx_priv *tx_priv; ++ ++ tx_priv = kzalloc(sizeof(struct aicwf_tx_priv), GFP_KERNEL); ++ if (!tx_priv) ++ return NULL; ++ ++#ifdef AICWF_SDIO_SUPPORT ++ tx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++#else ++ tx_priv->usbdev = (struct aic_usb_dev *)arg; ++#endif ++ ++ atomic_set(&tx_priv->aggr_count, 0); ++#ifdef CONFIG_RESV_MEM_SUPPORT ++ tx_priv->aggr_buf = aicbsp_resv_mem_alloc_skb(MAX_AGGR_TXPKT_LEN, AIC_RESV_MEM_TXDATA); ++#else ++ tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN); ++#endif ++ if (!tx_priv->aggr_buf) { ++ txrx_err("Alloc bus->txdata_buf failed!\n"); ++ kfree(tx_priv); ++ return NULL; ++ } ++ tx_priv->head = tx_priv->aggr_buf->data; ++ tx_priv->tail = tx_priv->aggr_buf->data; ++ ++#ifdef CONFIG_SDIO_ADMA ++ tx_priv->aggr_segcnt = 0; ++ tx_priv->len = 0; ++#endif ++ ++ return tx_priv; ++} ++ ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv) ++{ ++ if (tx_priv && tx_priv->aggr_buf) { ++#ifdef CONFIG_RESV_MEM_SUPPORT ++ aicbsp_resv_mem_kfree_skb(tx_priv->aggr_buf, AIC_RESV_MEM_TXDATA); ++#else ++ dev_kfree_skb(tx_priv->aggr_buf); ++#endif ++ kfree(tx_priv); ++ } ++#ifdef CONFIG_SDIO_ADMA ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++#endif ++} ++ ++#ifdef AICWF_SDIO_SUPPORT ++#ifdef CONFIG_PREALLOC_RX_SKB ++static bool aicwf_another_ptk_1(struct rx_buff *buffer) ++{ ++ u8 *read = buffer->read; ++ u16 aggr_len = 0; ++ ++ BUG_ON((read - buffer->start)%4 != 0); ++ ++ if(read == NULL || read >= buffer->end) { ++ return false; ++ } ++ ++ aggr_len = (*read | (*(read + 1) << 8)); ++ if(aggr_len == 0) { ++ return false; ++ } ++ ++ return true; ++} ++#else ++static bool aicwf_another_ptk(struct sk_buff *skb) ++{ ++ u8 *data; ++ u16 aggr_len = 0; ++ ++ if (skb->data == NULL || skb->len == 0) { ++ return false; ++ } ++ data = skb->data; ++ aggr_len = (*skb->data | (*(skb->data + 1) << 8)); ++ if (aggr_len == 0) { ++ return false; ++ } ++ ++ return true; ++} ++#endif ++#endif ++ ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ int ret = 0; ++ unsigned long flags = 0; ++#ifndef CONFIG_PREALLOC_RX_SKB ++ struct sk_buff *skb = NULL; ++#endif ++ u16 pkt_len = 0; ++ struct sk_buff *skb_inblock = NULL; ++ u16 aggr_len = 0, adjust_len = 0; ++ u8 *data = NULL; ++ u8_l *msg = NULL; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_buff *buffer = NULL; ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (!rx_priv->rxq.qcnt) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ buffer = rxbuff_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (buffer == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ while (aicwf_another_ptk_1(buffer)) { ++ data = buffer->read; ++ pkt_len = (*data | (*(data + 1) << 8)); ++ ++ if ((data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL); ++ if (skb_inblock == NULL) { ++ txrx_err("no more space! skip\n"); ++ buffer->read = buffer->read + adjust_len; ++ continue; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ buffer->read = buffer->read + adjust_len; ++ } else { ++ // type : config ++ aggr_len = pkt_len; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ msg = kmalloc(aggr_len+4, GFP_KERNEL); ++ if (msg == NULL) { ++ txrx_err("no more space for msg!\n"); ++ aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock); ++ return -EBADE; ++ } ++ ++ memcpy(msg, data, aggr_len + 4); ++ if (((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) && (rx_priv->sdiodev->bus_if->state != BUS_DOWN_ST)) ++ rwnx_rx_handle_msg(rx_priv->sdiodev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) ++ aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_PRINT) ++ rwnx_rx_handle_print(rx_priv->sdiodev->rwnx_hw, msg + 4, aggr_len); ++ ++ buffer->read = buffer->read + (adjust_len + 4); ++ kfree(msg); ++ } ++ } ++ ++ aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock); ++ ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ ++ #else ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ skb = aicwf_frame_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (skb == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ while (aicwf_another_ptk(skb)) { ++ data = skb->data; ++ pkt_len = (*skb->data | (*(skb->data + 1) << 8)); ++ ++ if ((skb->data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL); ++ if (skb_inblock == NULL) { ++ txrx_err("no more space! skip\n"); ++ skb_pull(skb, adjust_len); ++ continue; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ skb_pull(skb, adjust_len); ++ } else { ++ // type : config ++ aggr_len = pkt_len; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ msg = kmalloc(aggr_len+4, GFP_KERNEL); ++ if (msg == NULL) { ++ txrx_err("no more space for msg!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ ++ memcpy(msg, data, aggr_len + 4); ++ if (((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) && (rx_priv->sdiodev->bus_if->state != BUS_DOWN_ST)) ++ rwnx_rx_handle_msg(rx_priv->sdiodev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) ++ aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_PRINT) ++ rwnx_rx_handle_print(rx_priv->sdiodev->rwnx_hw, msg + 4, aggr_len); ++ ++ skb_pull(skb, adjust_len+4); ++ kfree(msg); ++ } ++ } ++ ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ #endif ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(rx_priv->sdiodev, SDIO_ACTIVE_ST); ++ #endif ++ ++ return ret; ++#else //AICWF_USB_SUPPORT ++ int ret = 0; ++ unsigned long flags = 0; ++ struct sk_buff *skb = NULL; /* Packet for event or data frames */ ++ u16 pkt_len = 0; ++ struct sk_buff *skb_inblock = NULL; ++ u16 aggr_len = 0, adjust_len = 0; ++ u8 *data = NULL; ++ u8_l *msg = NULL; ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { ++ usb_info("no more rxdata\n"); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ skb = aicwf_frame_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (skb == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ data = skb->data; ++ pkt_len = (*skb->data | (*(skb->data + 1) << 8)); ++ //printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]); ++ if (pkt_len > 1600) { ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ continue; ++ } ++ ++ if ((skb->data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv ++ if (skb_inblock == NULL) { ++ txrx_err("no more space! skip!\n"); ++ skb_pull(skb, adjust_len); ++ continue; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ ///TODO: here need to add rx data process ++ ++ skb_pull(skb, adjust_len); ++ } else { // type : config ++ aggr_len = pkt_len; ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ msg = kmalloc(aggr_len+4, GFP_KERNEL); ++ if (msg == NULL) { ++ txrx_err("no more space for msg!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ memcpy(msg, data, aggr_len + 4); ++ if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP) ++ rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM) ++ aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4)); ++ skb_pull(skb, adjust_len + 4); ++ kfree(msg); ++ } ++ ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ ++ return ret; ++#endif //AICWF_SDIO_SUPPORT ++} ++ ++static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize) ++{ ++ int i; ++ struct recv_msdu *req, *reqs; ++ ++ reqs = vmalloc(qsize*sizeof(struct recv_msdu)); ++ if (reqs == NULL) ++ return NULL; ++ ++ req = reqs; ++ for (i = 0; i < qsize; i++) { ++ INIT_LIST_HEAD(&req->rxframe_list); ++ list_add(&req->rxframe_list, q); ++ req++; ++ } ++ ++ return reqs; ++} ++ ++struct aicwf_rx_priv *aicwf_rx_init(void *arg) ++{ ++ struct aicwf_rx_priv *rx_priv; ++ rx_priv = kzalloc(sizeof(struct aicwf_rx_priv), GFP_KERNEL); ++ if (!rx_priv) ++ return NULL; ++ ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++#else ++ rx_priv->usbdev = (struct aic_usb_dev *)arg; ++#endif ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ aicwf_rxframe_queue_init_2(&rx_priv->rxq, MAX_RXQLEN); ++ #else ++ aicwf_frame_queue_init(&rx_priv->rxq, 1, MAX_RXQLEN); ++ #endif ++ spin_lock_init(&rx_priv->rxqlock); ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ spin_lock_init(&rx_priv->rxbuff_lock); ++ aicwf_prealloc_init(); ++ #endif ++ atomic_set(&rx_priv->rx_cnt, 0); ++ ++#ifdef AICWF_RX_REORDER ++ INIT_LIST_HEAD(&rx_priv->rxframes_freequeue); ++ spin_lock_init(&rx_priv->freeq_lock); ++ rx_priv->recv_frames = aicwf_rxframe_queue_init(&rx_priv->rxframes_freequeue, MAX_REORD_RXFRAME); ++ if (!rx_priv->recv_frames) { ++ txrx_err("no enough buffer for free recv frame queue!\n"); ++ kfree(rx_priv); ++ return NULL; ++ } ++ spin_lock_init(&rx_priv->stas_reord_lock); ++ INIT_LIST_HEAD(&rx_priv->stas_reord_list); ++#endif ++ ++ return rx_priv; ++} ++ ++ ++static void aicwf_recvframe_queue_deinit(struct list_head *q) ++{ ++ struct recv_msdu *req, *next; ++ ++ list_for_each_entry_safe(req, next, q, rxframe_list) { ++ list_del_init(&req->rxframe_list); ++ } ++} ++ ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv) ++{ ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *tmp; ++ ++ AICWFDBG(LOGINFO, "%s\n", __func__); ++ ++ list_for_each_entry_safe(reord_info, tmp, ++ &rx_priv->stas_reord_list, list) { ++ reord_deinit_sta(rx_priv, reord_info); ++ } ++#endif ++ ++#ifdef AICWF_SDIO_SUPPORT ++ AICWFDBG(LOGINFO, "sdio rx thread\n"); ++ if (rx_priv->sdiodev->bus_if->busrx_thread) { ++ complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg); ++ kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread); ++ rx_priv->sdiodev->bus_if->busrx_thread = NULL; ++ } ++#ifdef CONFIG_OOB ++ if(rx_priv->sdiodev->oob_enable){ ++ //new oob feature ++ if (rx_priv->sdiodev->bus_if->busirq_thread) { ++ complete_all(&rx_priv->sdiodev->bus_if->busirq_trgg); ++ kthread_stop(rx_priv->sdiodev->bus_if->busirq_thread); ++ rx_priv->sdiodev->bus_if->busirq_thread = NULL; ++ } ++ } ++#endif //CONFIG_OOB ++#endif ++#ifdef AICWF_USB_SUPPORT ++ if (rx_priv->usbdev->bus_if->busrx_thread) { ++ complete_all(&rx_priv->usbdev->bus_if->busrx_trgg); ++ kthread_stop(rx_priv->usbdev->bus_if->busrx_thread); ++ rx_priv->usbdev->bus_if->busrx_thread = NULL; ++ } ++#endif ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ rxbuff_queue_flush(rx_priv); ++ #else ++ aicwf_frame_queue_flush(&rx_priv->rxq); ++ #endif ++ ++#ifdef AICWF_RX_REORDER ++ aicwf_recvframe_queue_deinit(&rx_priv->rxframes_freequeue); ++ if (rx_priv->recv_frames) ++ vfree(rx_priv->recv_frames); ++#endif ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ aicwf_prealloc_exit(); ++ #endif ++ kfree(rx_priv); ++ ++ AICWFDBG(LOGINFO, "%s exit \n", __func__); ++} ++ ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt) ++{ ++ return aicwf_frame_enq(dev, q, pkt, 0); ++} ++ ++ ++void aicwf_dev_skb_free(struct sk_buff *skb) ++{ ++ if (!skb) ++ return; ++ ++ dev_kfree_skb_any(skb); ++} ++ ++static struct sk_buff *aicwf_frame_queue_penq(struct frame_queue *pq, int prio, struct sk_buff *p) ++{ ++ struct sk_buff_head *q; ++ ++ if (pq->queuelist[prio].qlen >= pq->qmax) ++ return NULL; ++ ++ q = &pq->queuelist[prio]; ++ __skb_queue_tail(q, p); ++ pq->qcnt++; ++ if (pq->hi_prio < prio) ++ pq->hi_prio = (u16)prio; ++ ++ return p; ++} ++ ++void aicwf_frame_queue_flush(struct frame_queue *pq) ++{ ++ int prio; ++ struct sk_buff_head *q; ++ struct sk_buff *p, *next; ++ ++ for (prio = 0; prio < pq->num_prio; prio++) { ++ q = &pq->queuelist[prio]; ++ skb_queue_walk_safe(q, p, next) { ++ skb_unlink(p, q); ++ aicwf_dev_skb_free(p); ++ pq->qcnt--; ++ } ++ } ++} ++ ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len) ++{ ++ int prio; ++ ++ memset(pq, 0, offsetof(struct frame_queue, queuelist) + (sizeof(struct sk_buff_head) * num_prio)); ++ pq->num_prio = (u16)num_prio; ++ pq->qmax = (u16)max_len; ++ ++ for (prio = 0; prio < num_prio; prio++) { ++ skb_queue_head_init(&pq->queuelist[prio]); ++ } ++} ++ ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out) ++{ ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ for (prio = 0; prio < pq->hi_prio; prio++) ++ if (!skb_queue_empty(&pq->queuelist[prio])) ++ break; ++ ++ if (prio_out) ++ *prio_out = prio; ++ ++ return skb_peek_tail(&pq->queuelist[prio]); ++} ++ ++bool aicwf_is_framequeue_empty(struct frame_queue *pq) ++{ ++ int prio, len = 0; ++ ++ for (prio = 0; prio <= pq->hi_prio; prio++) ++ len += pq->queuelist[prio].qlen; ++ ++ if (len > 0) ++ return false; ++ else ++ return true; ++} ++ ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq) ++{ ++ struct sk_buff_head *q; ++ struct sk_buff *p; ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ while ((prio = pq->hi_prio) > 0 && skb_queue_empty(&pq->queuelist[prio])) ++ pq->hi_prio--; ++ ++ q = &pq->queuelist[prio]; ++ p = __skb_dequeue(q); ++ if (p == NULL) ++ return NULL; ++ ++ pq->qcnt--; ++ ++ return p; ++} ++#if 0 ++static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio) ++{ ++ struct sk_buff_head *q = &pq->queuelist[prio]; ++ struct sk_buff *p = skb_dequeue_tail(q); ++ ++ if (!p) ++ return NULL; ++ ++ pq->qcnt--; ++ return p; ++} ++#endif ++ ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio) ++{ ++ #if 0 ++ struct sk_buff *p = NULL; ++ int prio_modified = -1; ++ ++ if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { ++ aicwf_frame_queue_penq(q, prio, pkt); ++ return true; ++ } ++ if (q->queuelist[prio].qlen >= q->qmax) { ++ prio_modified = prio; ++ } else if (q->qcnt >= q->qmax) { ++ p = aicwf_frame_queue_peek_tail(q, &prio_modified); ++ if (prio_modified > prio) ++ return false; ++ } ++ ++ if (prio_modified >= 0) { ++ if (prio_modified == prio) ++ return false; ++ ++ p = aicwf_skb_dequeue_tail(q, prio_modified); ++ aicwf_dev_skb_free(p); ++ ++ p = aicwf_frame_queue_penq(q, prio_modified, pkt); ++ if (p == NULL) ++ txrx_err("failed\n"); ++ } ++ ++ return p != NULL; ++ #else ++ if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { ++ aicwf_frame_queue_penq(q, prio, pkt); ++ return true; ++ } else ++ return false; ++ #endif ++} ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++void rxbuff_free(struct rx_buff *rxbuff) ++{ ++ kfree(rxbuff->data); ++ kfree(rxbuff); ++} ++ ++struct rx_buff *rxbuff_queue_penq(struct rx_frame_queue *pq, struct rx_buff *p) ++{ ++ ++ struct list_head *q; ++ if (pq->qcnt >= pq->qmax) ++ return NULL; ++ ++ q = &pq->queuelist; ++ list_add_tail(&p->queue,q); ++ ++ pq->qcnt++; ++ ++ return p; ++} ++ ++struct rx_buff *rxbuff_dequeue(struct rx_frame_queue *pq) ++{ ++ struct rx_buff *p = NULL; ++ ++ if (pq->qcnt == 0) { ++ printk("%s %d, rxq is empty\n", __func__, __LINE__); ++ return NULL; ++ } ++ ++ if(list_empty(&pq->queuelist)) { ++ printk("%s %d, rxq is empty\n", __func__, __LINE__); ++ return NULL; ++ } else { ++ p = list_first_entry(&pq->queuelist, struct rx_buff, queue); ++ list_del_init(&p->queue); ++ pq->qcnt--; ++ } ++ ++ return p; ++} ++ ++bool aicwf_rxbuff_enqueue(struct device *dev, struct rx_frame_queue *rxq, struct rx_buff *pkt) ++{ ++// struct rx_buff *p = NULL; ++ ++ if ((rxq == NULL) || (pkt == NULL)) { ++ printk("%s %d, rxq or pkt is NULL\n", __func__, __LINE__); ++ return false; ++ } ++ ++ if (rxq->qcnt < rxq->qmax) { ++ if (rxbuff_queue_penq(rxq, pkt)) { ++ return true; ++ } else { ++ printk("%s %d, rxbuff enqueue fail\n", __func__, __LINE__); ++ return false; ++ } ++ } else { ++ printk("%s %d, rxq or pkt is full\n", __func__, __LINE__); ++ return false; ++ } ++} ++#endif ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h +new file mode 100644 +index 000000000000..0774c1676235 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h +@@ -0,0 +1,284 @@ ++/** ++ * aicwf_txrxif.h ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_TXRXIF_H_ ++#define _AICWF_TXRXIF_H_ ++ ++#include ++#include ++#include "ipc_shared.h" ++#include "aicwf_rx_prealloc.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#else ++#include "aicwf_usb.h" ++#endif ++ ++#define CMD_BUF_MAX 1536 ++#define TXPKT_BLOCKSIZE 512 ++#define MAX_AGGR_TXPKT_LEN (1536*64) ++#define CMD_TX_TIMEOUT 5000 ++#define TX_ALIGNMENT 4 ++ ++#define RX_HWHRD_LEN 60 //58->60 word allined ++#define CCMP_OR_WEP_INFO 8 ++#define MAX_RXQLEN 2000 ++#define RX_ALIGNMENT 4 ++ ++#define DEBUG_ERROR_LEVEL 0 ++#define DEBUG_DEBUG_LEVEL 1 ++#define DEBUG_INFO_LEVEL 2 ++ ++#define DBG_LEVEL DEBUG_DEBUG_LEVEL ++ ++#define txrx_err(fmt, ...) pr_err("txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define sdio_err(fmt, ...) pr_err("sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define usb_err(fmt, ...) pr_err("usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL ++#define txrx_dbg(fmt, ...) printk("txrx: " fmt, ##__VA_ARGS__) ++#define sdio_dbg(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__) ++#define usb_dbg(fmt, ...) printk("aicusb: " fmt, ##__VA_ARGS__) ++#else ++#define txrx_dbg(fmt, ...) ++#define sdio_dbg(fmt, ...) ++#define usb_dbg(fmt, ...) ++#endif ++#if DBG_LEVEL >= DEBUG_INFO_LEVEL ++#define txrx_info(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__) ++#define sdio_info(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__) ++#define usb_info(fmt, ...) printk("aicusb: " fmt, ##__VA_ARGS__) ++#else ++#define txrx_info(fmt, ...) ++#define sdio_info(fmt, ...) ++#define usb_info(fmt, ...) ++#endif ++ ++enum aicwf_bus_state { ++ BUS_DOWN_ST, ++ BUS_UP_ST ++}; ++ ++struct aicwf_bus_ops { ++ int (*start) (struct device *dev); ++ void (*stop) (struct device *dev); ++ int (*txdata) (struct device *dev, struct sk_buff *skb); ++ int (*txmsg) (struct device *dev, u8 *msg, uint len); ++}; ++ ++struct frame_queue { ++ u16 num_prio; ++ u16 hi_prio; ++ u16 qmax; /* max number of queued frames */ ++ u16 qcnt; ++ struct sk_buff_head queuelist[8]; ++}; ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct rx_frame_queue { ++ u16 qmax; /* max number of queued frames */ ++ u16 qcnt; ++ struct list_head queuelist; ++}; ++#endif ++ ++struct aicwf_bus { ++ union { ++ struct aic_sdio_dev *sdio; ++ struct aic_usb_dev *usb; ++ } bus_priv; ++ struct device *dev; ++ struct aicwf_bus_ops *ops; ++ enum aicwf_bus_state state; ++ u8 *cmd_buf; ++ struct completion bustx_trgg; ++ struct completion busrx_trgg; ++ struct completion busirq_trgg;//new oob feature ++ struct task_struct *bustx_thread; ++ struct task_struct *busrx_thread; ++ struct task_struct *busirq_thread;//new oob feature ++}; ++ ++#ifdef CONFIG_SDIO_ADMA ++#define SDIO_HEADER_LEN 4 ++#define SDIO_DATA_FAKE_LEN 2 ++#define SDIO_MGMT_FAKE_LEN 4 ++#define ALIGN4_ADJ_LEN(x) ((4-(x&3))&3) ++ ++#define SDIO_TX_SLIST_MAX 136 ++ ++/*struct tx_scatterlist { ++ const void *buf; ++ unsigned int len; ++};*/ ++#endif ++ ++struct aicwf_tx_priv { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++ int fw_avail_bufcnt; ++ //for cmd tx ++ u8 *cmd_buf; ++ uint cmd_len; ++ bool cmd_txstate; ++ bool cmd_tx_succ; ++ struct semaphore cmd_txsema; ++ wait_queue_head_t cmd_txdone_wait; ++ //for data tx ++ atomic_t tx_pktcnt; ++ ++ struct frame_queue txq; ++ spinlock_t txqlock; ++ struct semaphore txctl_sema; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ struct sk_buff *aggr_buf; ++ atomic_t aggr_count; ++ u8 *head; ++ u8 *tail; ++ ++#ifdef CONFIG_SDIO_ADMA ++ struct tx_scatterlist sg_list[SDIO_TX_SLIST_MAX]; ++ void *free_buf[SDIO_TX_SLIST_MAX]; ++ bool copyd[SDIO_TX_SLIST_MAX]; ++ u32 aggr_segcnt; ++ u32 len; ++#endif ++}; ++ ++ ++#define DEFRAG_MAX_WAIT 40 //100 ++#ifdef AICWF_RX_REORDER ++#define MAX_REORD_RXFRAME 250 ++#define REORDER_UPDATE_TIME 50 ++#define AICWF_REORDER_WINSIZE 64 ++#define SN_LESS(a, b) (((a-b)&0x800) != 0) ++#define SN_EQUAL(a, b) (a == b) ++ ++struct reord_ctrl { ++ struct aicwf_rx_priv *rx_priv; ++ u8 enable; ++ u16 ind_sn; ++ u8 wsize_b; ++ spinlock_t reord_list_lock; ++ struct list_head reord_list; ++ struct timer_list reord_timer; ++ struct work_struct reord_timer_work; ++}; ++ ++struct reord_ctrl_info { ++ u8 mac_addr[6]; ++ struct reord_ctrl preorder_ctrl[8]; ++ struct list_head list; ++}; ++ ++struct recv_msdu { ++ struct sk_buff *pkt; ++ u8 tid; ++ u16 seq_num; ++ u8 forward; ++ //uint len; ++ u32 is_amsdu; ++ u8 *rx_data; ++ //for pending rx reorder list ++ struct list_head reord_pending_list; ++ //for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue ++ struct list_head rxframe_list; ++ struct reord_ctrl *preorder_ctrl; ++}; ++#endif ++ ++struct aicwf_rx_priv { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ ++ void *rwnx_vif; ++ atomic_t rx_cnt; ++ u32 data_len; ++ spinlock_t rxqlock; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_frame_queue rxq; ++ #else ++ struct frame_queue rxq; ++ #endif ++ ++#ifdef AICWF_RX_REORDER ++ spinlock_t freeq_lock; ++ struct list_head rxframes_freequeue; ++ struct list_head stas_reord_list; ++ spinlock_t stas_reord_lock; ++ struct recv_msdu *recv_frames; ++#endif ++#ifdef CONFIG_PREALLOC_RX_SKB ++ spinlock_t rxbuff_lock; ++#endif ++}; ++ ++static inline int aicwf_bus_start(struct aicwf_bus *bus) ++{ ++ return bus->ops->start(bus->dev); ++} ++ ++static inline void aicwf_bus_stop(struct aicwf_bus *bus) ++{ ++ bus->ops->stop(bus->dev); ++} ++ ++static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb) ++{ ++ return bus->ops->txdata(bus->dev, skb); ++} ++ ++static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len) ++{ ++ return bus->ops->txmsg(bus->dev, msg, len); ++} ++ ++static inline void aicwf_sched_timeout(u32 millisec) ++{ ++ ulong timeout = 0, expires = 0; ++ expires = jiffies + msecs_to_jiffies(millisec); ++ timeout = millisec; ++ ++ while (timeout) { ++ timeout = schedule_timeout(timeout); ++ if (time_after(jiffies, expires)) ++ break; ++ } ++} ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev); ++void aicwf_bus_deinit(struct device *dev); ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv); ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv); ++struct aicwf_tx_priv *aicwf_tx_init(void *arg); ++struct aicwf_rx_priv *aicwf_rx_init(void *arg); ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len); ++void aicwf_frame_queue_flush(struct frame_queue *pq); ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio); ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt); ++bool aicwf_is_framequeue_empty(struct frame_queue *pq); ++void aicwf_frame_tx(void *dev, struct sk_buff *skb); ++void aicwf_dev_skb_free(struct sk_buff *skb); ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq); ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out); ++#ifdef CONFIG_PREALLOC_RX_SKB ++void rxbuff_queue_flush(struct aicwf_rx_priv* rx_priv); ++void aicwf_rxframe_queue_init_2(struct rx_frame_queue *pq, int max_len); ++void rxbuff_free(struct rx_buff *rxbuff); ++struct rx_buff *rxbuff_dequeue(struct rx_frame_queue *pq); ++bool aicwf_rxbuff_enqueue(struct device *dev, struct rx_frame_queue *rxq, struct rx_buff *pkt); ++extern struct aicwf_rx_buff_list aic_rx_buff_list; ++#endif ++ ++#endif /* _AICWF_TXRXIF_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c +new file mode 100644 +index 000000000000..9344217c2256 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c +@@ -0,0 +1,957 @@ ++/** ++ * aicwf_usb.c ++ * ++ * USB function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#include ++#include ++#include "aicwf_txrxif.h" ++#include "aicwf_usb.h" ++#include "rwnx_tx.h" ++#include "rwnx_defs.h" ++#include "usb_host.h" ++#include "rwnx_platform.h" ++ ++void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state) ++{ ++ struct rwnx_vif *rwnx_vif; ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (!rwnx_vif->up) ++ continue; ++ if (!rwnx_vif->ndev) ++ continue; ++ if (state) ++ netif_stop_queue(rwnx_vif->ndev); ++ else ++ netif_wake_queue(rwnx_vif->ndev); ++ } ++} ++ ++static struct aicwf_usb_buf *aicwf_usb_tx_dequeue(struct aic_usb_dev *usb_dev, ++ struct list_head *q, int *counter, spinlock_t *qlock) ++{ ++ unsigned long flags; ++ struct aicwf_usb_buf *usb_buf; ++ ++ spin_lock_irqsave(qlock, flags); ++ if (list_empty(q)) { ++ usb_buf = NULL; ++ } else { ++ usb_buf = list_first_entry(q, struct aicwf_usb_buf, list); ++ list_del_init(&usb_buf->list); ++ if (counter) ++ (*counter)--; ++ } ++ spin_unlock_irqrestore(qlock, flags); ++ return usb_buf; ++} ++ ++static void aicwf_usb_tx_queue(struct aic_usb_dev *usb_dev, ++ struct list_head *q, struct aicwf_usb_buf *usb_buf, int *counter, ++ spinlock_t *qlock) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(qlock, flags); ++ list_add_tail(&usb_buf->list, q); ++ (*counter)++; ++ spin_unlock_irqrestore(qlock, flags); ++} ++ ++static struct aicwf_usb_buf *aicwf_usb_rx_buf_get(struct aic_usb_dev *usb_dev) ++{ ++ unsigned long flags; ++ struct aicwf_usb_buf *usb_buf; ++ ++ spin_lock_irqsave(&usb_dev->rx_free_lock, flags); ++ if (list_empty(&usb_dev->rx_free_list)) { ++ usb_buf = NULL; ++ } else { ++ usb_buf = list_first_entry(&usb_dev->rx_free_list, struct aicwf_usb_buf, list); ++ list_del_init(&usb_buf->list); ++ } ++ spin_unlock_irqrestore(&usb_dev->rx_free_lock, flags); ++ return usb_buf; ++} ++ ++static void aicwf_usb_rx_buf_put(struct aic_usb_dev *usb_dev, struct aicwf_usb_buf *usb_buf) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&usb_dev->rx_free_lock, flags); ++ list_add_tail(&usb_buf->list, &usb_dev->rx_free_list); ++ spin_unlock_irqrestore(&usb_dev->rx_free_lock, flags); ++} ++ ++static void aicwf_usb_tx_complete(struct urb *urb) ++{ ++ unsigned long flags; ++ struct aicwf_usb_buf *usb_buf = (struct aicwf_usb_buf *) urb->context; ++ struct aic_usb_dev *usb_dev = usb_buf->usbdev; ++ struct sk_buff *skb; ++ u8 *buf; ++ ++ if (usb_buf->cfm == false) { ++ skb = usb_buf->skb; ++ } else { ++ buf = (u8 *)usb_buf->skb; ++ } ++ ++ if (usb_buf->cfm == false) { ++ dev_kfree_skb_any(skb); ++ } else { ++ kfree(buf); ++ } ++ usb_buf->skb = NULL; ++ ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ ++ spin_lock_irqsave(&usb_dev->tx_flow_lock, flags); ++ if (usb_dev->tx_free_count > AICWF_USB_TX_HIGH_WATER) { ++ if (usb_dev->tbusy) { ++ usb_dev->tbusy = false; ++ aicwf_usb_tx_flowctrl(usb_dev->rwnx_hw, false); ++ } ++ } ++ spin_unlock_irqrestore(&usb_dev->tx_flow_lock, flags); ++ } ++ ++static void aicwf_usb_rx_complete(struct urb *urb) ++{ ++ struct aicwf_usb_buf *usb_buf = (struct aicwf_usb_buf *) urb->context; ++ struct aic_usb_dev *usb_dev = usb_buf->usbdev; ++ struct aicwf_rx_priv *rx_priv = usb_dev->rx_priv; ++ struct sk_buff *skb = NULL; ++ unsigned long flags = 0; ++ ++ skb = usb_buf->skb; ++ usb_buf->skb = NULL; ++ ++ if (urb->actual_length > urb->transfer_buffer_length) { ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ schedule_work(&usb_dev->rx_urb_work); ++ return; ++ } ++ ++ if (urb->status != 0 || !urb->actual_length) { ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ schedule_work(&usb_dev->rx_urb_work); ++ return; ++ } ++ ++ if (usb_dev->state == USB_UP_ST) { ++ skb_put(skb, urb->actual_length); ++ ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (!aicwf_rxframe_enqueue(usb_dev->dev, &rx_priv->rxq, skb)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ usb_err("rx_priv->rxq is over flow!!!\n"); ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ return; ++ } ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ atomic_inc(&rx_priv->rx_cnt); ++ complete(&rx_priv->usbdev->bus_if->busrx_trgg); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ ++ schedule_work(&usb_dev->rx_urb_work); ++ } else { ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ } ++} ++ ++static int aicwf_usb_submit_rx_urb(struct aic_usb_dev *usb_dev, ++ struct aicwf_usb_buf *usb_buf) ++{ ++ struct sk_buff *skb; ++ int ret; ++ ++ if (!usb_buf || !usb_dev) ++ return -1; ++ ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("usb state is not up!\n"); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ return -1; ++ } ++ ++ skb = __dev_alloc_skb(AICWF_USB_MAX_PKT_SIZE, GFP_KERNEL); ++ if (!skb) { ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ return -1; ++ } ++ ++ usb_buf->skb = skb; ++ ++ usb_fill_bulk_urb(usb_buf->urb, ++ usb_dev->udev, ++ usb_dev->bulk_in_pipe, ++ skb->data, skb_tailroom(skb), aicwf_usb_rx_complete, usb_buf); ++ ++ usb_buf->usbdev = usb_dev; ++ ++ usb_anchor_urb(usb_buf->urb, &usb_dev->rx_submitted); ++ ret = usb_submit_urb(usb_buf->urb, GFP_ATOMIC); ++ if (ret) { ++ usb_err("usb submit rx urb fail:%d\n", ret); ++ usb_unanchor_urb(usb_buf->urb); ++ aicwf_dev_skb_free(usb_buf->skb); ++ usb_buf->skb = NULL; ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ ++ msleep(100); ++ } ++ return 0; ++} ++ ++static void aicwf_usb_rx_submit_all_urb(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf; ++ ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("bus is not up=%d\n", usb_dev->state); ++ return; ++ } ++ ++ while ((usb_buf = aicwf_usb_rx_buf_get(usb_dev)) != NULL) { ++ if (aicwf_usb_submit_rx_urb(usb_dev, usb_buf)) { ++ usb_err("usb rx refill fail\n"); ++ if (usb_dev->state != USB_UP_ST) ++ return; ++ } ++ } ++} ++ ++static void aicwf_usb_rx_prepare(struct aic_usb_dev *usb_dev) ++{ ++ aicwf_usb_rx_submit_all_urb(usb_dev); ++} ++ ++static void aicwf_usb_tx_prepare(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf; ++ ++ while (!list_empty(&usb_dev->tx_post_list)) { ++ usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_post_list, ++ &usb_dev->tx_post_count, &usb_dev->tx_post_lock); ++ if (usb_buf->skb) { ++ dev_kfree_skb(usb_buf->skb); ++ usb_buf->skb = NULL; ++ } ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ } ++} ++static void aicwf_usb_tx_process(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf; ++ int ret = 0; ++ u8 *data = NULL; ++ ++ while (!list_empty(&usb_dev->tx_post_list)) { ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("usb state is not up!\n"); ++ return; ++ } ++ ++ usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_post_list, ++ &usb_dev->tx_post_count, &usb_dev->tx_post_lock); ++ if (!usb_buf) { ++ usb_err("can not get usb_buf from tx_post_list!\n"); ++ return; ++ } ++ data = usb_buf->skb->data; ++ ++ ret = usb_submit_urb(usb_buf->urb, GFP_ATOMIC); ++ if (ret) { ++ usb_err("aicwf_usb_bus_tx usb_submit_urb FAILED\n"); ++ goto fail; ++ } ++ ++ continue; ++fail: ++ dev_kfree_skb(usb_buf->skb); ++ usb_buf->skb = NULL; ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ } ++} ++ ++int usb_bustx_thread(void *data) ++{ ++ struct aicwf_bus *bus = (struct aicwf_bus *)data; ++ struct aic_usb_dev *usbdev = bus->bus_priv.usb; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ usb_err("usb bustx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if (usbdev->bus_if->state == BUS_DOWN_ST) ++ continue; ++ if (usbdev->tx_post_count > 0) ++ aicwf_usb_tx_process(usbdev); ++ } ++ } ++ ++ return 0; ++} ++ ++int usb_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->usbdev->bus_if; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ usb_err("usb busrx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ if (bus_if->state == BUS_DOWN_ST) ++ continue; ++ aicwf_process_rxframes(rx_priv); ++ } ++ } ++ ++ return 0; ++} ++ ++static void aicwf_usb_send_msg_complete(struct urb *urb) ++{ ++ struct aic_usb_dev *usb_dev = (struct aic_usb_dev *) urb->context; ++ ++ usb_dev->msg_finished = true; ++ if (waitqueue_active(&usb_dev->msg_wait)) ++ wake_up(&usb_dev->msg_wait); ++} ++ ++static int aicwf_usb_bus_txmsg(struct device *dev, u8 *buf, u32 len) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ ++ if (usb_dev->state != USB_UP_ST) ++ return -EIO; ++ ++ if (buf == NULL || len == 0 || usb_dev->msg_out_urb == NULL) ++ return -EINVAL; ++ ++ if (test_and_set_bit(0, &usb_dev->msg_busy)) { ++ usb_err("In a control frame option, can't tx!\n"); ++ return -EIO; ++ } ++ ++ usb_dev->msg_finished = false; ++ ++ usb_fill_bulk_urb(usb_dev->msg_out_urb, ++ usb_dev->udev, ++ usb_dev->bulk_out_pipe, ++ buf, len, (usb_complete_t) aicwf_usb_send_msg_complete, usb_dev); ++ usb_dev->msg_out_urb->transfer_flags |= URB_ZERO_PACKET; ++ ++ ret = usb_submit_urb(usb_dev->msg_out_urb, GFP_ATOMIC); ++ if (ret) { ++ usb_err("usb_submit_urb failed %d\n", ret); ++ goto exit; ++ } ++ ++ ret = wait_event_timeout(usb_dev->msg_wait, ++ usb_dev->msg_finished, msecs_to_jiffies(CMD_TX_TIMEOUT)); ++ if (!ret) { ++ if (usb_dev->msg_out_urb) ++ usb_kill_urb(usb_dev->msg_out_urb); ++ usb_err("Txmsg wait timed out\n"); ++ ret = -EIO; ++ goto exit; ++ } ++ ++ if (usb_dev->msg_finished == false) { ++ usb_err("Txmsg timed out\n"); ++ ret = -ETIMEDOUT; ++ goto exit; ++ } ++exit: ++ clear_bit(0, &usb_dev->msg_busy); ++ return ret; ++} ++ ++ ++static void aicwf_usb_free_urb(struct list_head *q, spinlock_t *qlock) ++{ ++ struct aicwf_usb_buf *usb_buf, *tmp; ++ unsigned long flags; ++ ++ spin_lock_irqsave(qlock, flags); ++ list_for_each_entry_safe(usb_buf, tmp, q, list) { ++ spin_unlock_irqrestore(qlock, flags); ++ if (!usb_buf->urb) { ++ usb_err("bad usb_buf\n"); ++ spin_lock_irqsave(qlock, flags); ++ break; ++ } ++ usb_free_urb(usb_buf->urb); ++ list_del_init(&usb_buf->list); ++ spin_lock_irqsave(qlock, flags); ++ } ++ spin_unlock_irqrestore(qlock, flags); ++} ++ ++static int aicwf_usb_alloc_rx_urb(struct aic_usb_dev *usb_dev) ++{ ++ int i; ++ ++ for (i = 0; i < AICWF_USB_RX_URBS; i++) { ++ struct aicwf_usb_buf *usb_buf = &usb_dev->usb_rx_buf[i]; ++ ++ usb_buf->usbdev = usb_dev; ++ usb_buf->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!usb_buf->urb) { ++ usb_err("could not allocate rx data urb\n"); ++ goto err; ++ } ++ list_add_tail(&usb_buf->list, &usb_dev->rx_free_list); ++ } ++ return 0; ++ ++err: ++ aicwf_usb_free_urb(&usb_dev->rx_free_list, &usb_dev->rx_free_lock); ++ return -ENOMEM; ++} ++ ++static int aicwf_usb_alloc_tx_urb(struct aic_usb_dev *usb_dev) ++{ ++ int i; ++ ++ for (i = 0; i < AICWF_USB_TX_URBS; i++) { ++ struct aicwf_usb_buf *usb_buf = &usb_dev->usb_tx_buf[i]; ++ ++ usb_buf->usbdev = usb_dev; ++ usb_buf->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!usb_buf->urb) { ++ usb_err("could not allocate tx data urb\n"); ++ goto err; ++ } ++ list_add_tail(&usb_buf->list, &usb_dev->tx_free_list); ++ (usb_dev->tx_free_count)++; ++ } ++ return 0; ++ ++err: ++ aicwf_usb_free_urb(&usb_dev->tx_free_list, &usb_dev->tx_free_lock); ++ return -ENOMEM; ++} ++ ++ ++static void aicwf_usb_state_change(struct aic_usb_dev *usb_dev, int state) ++{ ++ int old_state; ++ ++ if (usb_dev->state == state) ++ return; ++ ++ old_state = usb_dev->state; ++ usb_dev->state = state; ++ ++ if (state == USB_DOWN_ST) { ++ usb_dev->bus_if->state = BUS_DOWN_ST; ++ } ++ if (state == USB_UP_ST) { ++ usb_dev->bus_if->state = BUS_UP_ST; ++ } ++} ++ ++static int aicwf_usb_bus_txdata(struct device *dev, struct sk_buff *skb) ++{ ++ u8 *buf; ++ u16 buf_len = 0; ++ u16 adjust_len = 0; ++ struct aicwf_usb_buf *usb_buf; ++ int ret = 0; ++ unsigned long flags; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)skb->data; ++ struct rwnx_hw *rwnx_hw = usb_dev->rwnx_hw; ++ u8 usb_header[4]; ++ u8 adj_buf[4] = {0}; ++ u16 index = 0; ++ bool need_cfm = false; ++ ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("usb state is not up!\n"); ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ dev_kfree_skb_any(skb); ++ return -EIO; ++ } ++ ++ usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_free_list, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ if (!usb_buf) { ++ usb_err("free:%d, post:%d\n", usb_dev->tx_free_count, usb_dev->tx_post_count); ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ dev_kfree_skb_any(skb); ++ ret = -ENOMEM; ++ goto flow_ctrl; ++ } ++ ++ if (txhdr->sw_hdr->need_cfm) { ++ need_cfm = true; ++ buf = kmalloc(skb->len, GFP_KERNEL); ++ index += sizeof(usb_header); ++ memcpy(&buf[index], (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ index += sizeof(struct txdesc_api); ++ memcpy(&buf[index], &skb->data[txhdr->sw_hdr->headroom], skb->len - txhdr->sw_hdr->headroom); ++ index += skb->len - txhdr->sw_hdr->headroom; ++ buf_len = index; ++ if (buf_len & (TX_ALIGNMENT - 1)) { ++ adjust_len = roundup(buf_len, TX_ALIGNMENT)-buf_len; ++ memcpy(&buf[buf_len], adj_buf, adjust_len); ++ buf_len += adjust_len; ++ } ++ usb_header[0] = ((buf_len) & 0xff); ++ usb_header[1] = (((buf_len) >> 8)&0x0f); ++ usb_header[2] = 0x01; //data ++ usb_header[3] = 0; //reserved ++ memcpy(&buf[0], usb_header, sizeof(usb_header)); ++ usb_buf->skb = (struct sk_buff *)buf; ++ } else { ++ skb_pull(skb, txhdr->sw_hdr->headroom); ++ skb_push(skb, sizeof(struct txdesc_api)); ++ memcpy(&skb->data[0], (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ ++ skb_push(skb, sizeof(usb_header)); ++ usb_header[0] = ((skb->len) & 0xff); ++ usb_header[1] = (((skb->len) >> 8)&0x0f); ++ usb_header[2] = 0x01; //data ++ usb_header[3] = 0; //reserved ++ memcpy(&skb->data[0], usb_header, sizeof(usb_header)); ++ ++ buf = skb->data; ++ buf_len = skb->len; ++ ++ usb_buf->skb = skb; ++ } ++ usb_buf->usbdev = usb_dev; ++ if (need_cfm) ++ usb_buf->cfm = true; ++ else ++ usb_buf->cfm = false; ++ usb_fill_bulk_urb(usb_buf->urb, usb_dev->udev, usb_dev->bulk_out_pipe, ++ buf, buf_len, aicwf_usb_tx_complete, usb_buf); ++ usb_buf->urb->transfer_flags |= URB_ZERO_PACKET; ++ ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_post_list, usb_buf, ++ &usb_dev->tx_post_count, &usb_dev->tx_post_lock); ++ complete(&bus_if->bustx_trgg); ++ ret = 0; ++ ++ flow_ctrl: ++ spin_lock_irqsave(&usb_dev->tx_flow_lock, flags); ++ if (usb_dev->tx_free_count < AICWF_USB_TX_LOW_WATER) { ++ usb_dev->tbusy = true; ++ aicwf_usb_tx_flowctrl(usb_dev->rwnx_hw, true); ++ } ++ spin_unlock_irqrestore(&usb_dev->tx_flow_lock, flags); ++ ++ return ret; ++} ++ ++static int aicwf_usb_bus_start(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ ++ if (usb_dev->state == USB_UP_ST) ++ return 0; ++ ++ aicwf_usb_state_change(usb_dev, USB_UP_ST); ++ aicwf_usb_rx_prepare(usb_dev); ++ aicwf_usb_tx_prepare(usb_dev); ++ return 0; ++} ++ ++static void aicwf_usb_cancel_all_urbs(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf, *tmp; ++ unsigned long flags; ++ ++ if (usb_dev->msg_out_urb) ++ usb_kill_urb(usb_dev->msg_out_urb); ++ ++ spin_lock_irqsave(&usb_dev->tx_post_lock, flags); ++ list_for_each_entry_safe(usb_buf, tmp, &usb_dev->tx_post_list, list) { ++ spin_unlock_irqrestore(&usb_dev->tx_post_lock, flags); ++ if (!usb_buf->urb) { ++ usb_err("bad usb_buf\n"); ++ spin_lock_irqsave(&usb_dev->tx_post_lock, flags); ++ break; ++ } ++ usb_kill_urb(usb_buf->urb); ++ spin_lock_irqsave(&usb_dev->tx_post_lock, flags); ++ } ++ spin_unlock_irqrestore(&usb_dev->tx_post_lock, flags); ++ ++ usb_kill_anchored_urbs(&usb_dev->rx_submitted); ++} ++ ++static void aicwf_usb_bus_stop(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ ++ usb_dbg("%s\r\n", __func__); ++ if (usb_dev == NULL) ++ return; ++ ++ if (usb_dev->state == USB_DOWN_ST) ++ return; ++ ++ aicwf_usb_state_change(usb_dev, USB_DOWN_ST); ++ aicwf_usb_cancel_all_urbs(usb_dev); ++} ++ ++static void aicwf_usb_deinit(struct aic_usb_dev *usbdev) ++{ ++ cancel_work_sync(&usbdev->rx_urb_work); ++ aicwf_usb_free_urb(&usbdev->rx_free_list, &usbdev->rx_free_lock); ++ aicwf_usb_free_urb(&usbdev->tx_free_list, &usbdev->tx_free_lock); ++ usb_free_urb(usbdev->msg_out_urb); ++} ++ ++static void aicwf_usb_rx_urb_work(struct work_struct *work) ++{ ++ struct aic_usb_dev *usb_dev = container_of(work, struct aic_usb_dev, rx_urb_work); ++ ++ aicwf_usb_rx_submit_all_urb(usb_dev); ++} ++ ++static int aicwf_usb_init(struct aic_usb_dev *usb_dev) ++{ ++ int ret = 0; ++ ++ usb_dev->tbusy = false; ++ usb_dev->state = USB_DOWN_ST; ++ ++ init_waitqueue_head(&usb_dev->msg_wait); ++ init_usb_anchor(&usb_dev->rx_submitted); ++ ++ spin_lock_init(&usb_dev->tx_free_lock); ++ spin_lock_init(&usb_dev->tx_post_lock); ++ spin_lock_init(&usb_dev->rx_free_lock); ++ spin_lock_init(&usb_dev->tx_flow_lock); ++ ++ INIT_LIST_HEAD(&usb_dev->rx_free_list); ++ INIT_LIST_HEAD(&usb_dev->tx_free_list); ++ INIT_LIST_HEAD(&usb_dev->tx_post_list); ++ ++ usb_dev->tx_free_count = 0; ++ usb_dev->tx_post_count = 0; ++ ++ ret = aicwf_usb_alloc_rx_urb(usb_dev); ++ if (ret) { ++ goto error; ++ } ++ ret = aicwf_usb_alloc_tx_urb(usb_dev); ++ if (ret) { ++ goto error; ++ } ++ ++ ++ usb_dev->msg_out_urb = usb_alloc_urb(0, GFP_ATOMIC); ++ if (!usb_dev->msg_out_urb) { ++ usb_err("usb_alloc_urb (msg out) failed\n"); ++ ret = ENOMEM; ++ goto error; ++ } ++ ++ INIT_WORK(&usb_dev->rx_urb_work, aicwf_usb_rx_urb_work); ++ ++ return ret; ++ error: ++ usb_err("failed!\n"); ++ aicwf_usb_deinit(usb_dev); ++ return ret; ++} ++ ++ ++static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *interface) ++{ ++ struct usb_interface_descriptor *interface_desc; ++ struct usb_host_interface *host_interface; ++ struct usb_endpoint_descriptor *endpoint; ++ struct usb_device *usb = usb_dev->udev; ++ int i, endpoints; ++ u8 endpoint_num; ++ int ret = 0; ++ ++ usb_dev->bulk_in_pipe = 0; ++ usb_dev->bulk_out_pipe = 0; ++ ++ host_interface = &interface->altsetting[0]; ++ interface_desc = &host_interface->desc; ++ endpoints = interface_desc->bNumEndpoints; ++ ++ /* Check device configuration */ ++ if (usb->descriptor.bNumConfigurations != 1) { ++ usb_err("Number of configurations: %d not supported\n", ++ usb->descriptor.bNumConfigurations); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ /* Check deviceclass */ ++#ifndef CONFIG_USB_BT ++ if (usb->descriptor.bDeviceClass != 0x00) { ++ usb_err("DeviceClass %d not supported\n", ++ usb->descriptor.bDeviceClass); ++ ret = -ENODEV; ++ goto exit; ++ } ++#endif ++ ++ /* Check interface number */ ++#ifdef CONFIG_USB_BT ++ if (usb->actconfig->desc.bNumInterfaces != 3) { ++#else ++ if (usb->actconfig->desc.bNumInterfaces != 1) { ++#endif ++ usb_err("Number of interfaces: %d not supported\n", ++ usb->actconfig->desc.bNumInterfaces); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ if ((interface_desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || ++ (interface_desc->bInterfaceSubClass != 0xff) || ++ (interface_desc->bInterfaceProtocol != 0xff)) { ++ usb_err("non WLAN interface %d: 0x%x:0x%x:0x%x\n", ++ interface_desc->bInterfaceNumber, interface_desc->bInterfaceClass, ++ interface_desc->bInterfaceSubClass, interface_desc->bInterfaceProtocol); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ for (i = 0; i < endpoints; i++) { ++ endpoint = &host_interface->endpoint[i].desc; ++ endpoint_num = usb_endpoint_num(endpoint); ++ ++ if (usb_endpoint_dir_in(endpoint) && ++ usb_endpoint_xfer_bulk(endpoint)) { ++ if (!usb_dev->bulk_in_pipe) { ++ usb_dev->bulk_in_pipe = usb_rcvbulkpipe(usb, endpoint_num); ++ } ++ } ++ ++ if (usb_endpoint_dir_out(endpoint) && ++ usb_endpoint_xfer_bulk(endpoint)) { ++ if (!usb_dev->bulk_out_pipe) { ++ usb_dev->bulk_out_pipe = usb_sndbulkpipe(usb, endpoint_num); ++ } ++ } ++ } ++ ++ if (usb_dev->bulk_in_pipe == 0) { ++ usb_err("No RX (in) Bulk EP found\n"); ++ ret = -ENODEV; ++ goto exit; ++ } ++ if (usb_dev->bulk_out_pipe == 0) { ++ usb_err("No TX (out) Bulk EP found\n"); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ if (usb->speed == USB_SPEED_HIGH) ++ printk("Aic high speed USB device detected\n"); ++ else ++ printk("Aic full speed USB device detected\n"); ++ ++ exit: ++ return ret; ++} ++ ++ ++ ++static struct aicwf_bus_ops aicwf_usb_bus_ops = { ++ .start = aicwf_usb_bus_start, ++ .stop = aicwf_usb_bus_stop, ++ .txdata = aicwf_usb_bus_txdata, ++ .txmsg = aicwf_usb_bus_txmsg, ++}; ++ ++static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ++{ ++ int ret = 0; ++ struct usb_device *usb = interface_to_usbdev(intf); ++ struct aicwf_bus *bus_if ; ++ struct device *dev = NULL; ++ struct aicwf_rx_priv *rx_priv = NULL; ++ struct aic_usb_dev *usb_dev = NULL; ++ ++ usb_dev = kzalloc(sizeof(struct aic_usb_dev), GFP_ATOMIC); ++ if (!usb_dev) { ++ return -ENOMEM; ++ } ++ ++ usb_dev->udev = usb; ++ usb_dev->dev = &usb->dev; ++ usb_set_intfdata(intf, usb_dev); ++ ++ ret = aicwf_parse_usb(usb_dev, intf); ++ if (ret) { ++ usb_err("aicwf_parse_usb err %d\n", ret); ++ goto out_free; ++ } ++ ++ ret = aicwf_usb_init(usb_dev); ++ if (ret) { ++ usb_err("aicwf_usb_init err %d\n", ret); ++ goto out_free; ++ } ++ ++ bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_ATOMIC); ++ if (!bus_if) { ++ ret = -ENOMEM; ++ goto out_free_usb; ++ } ++ ++ dev = usb_dev->dev; ++ bus_if->dev = dev; ++ usb_dev->bus_if = bus_if; ++ bus_if->bus_priv.usb = usb_dev; ++ dev_set_drvdata(dev, bus_if); ++ ++ bus_if->ops = &aicwf_usb_bus_ops; ++ ++ rx_priv = aicwf_rx_init(usb_dev); ++ if (!rx_priv) { ++ txrx_err("rx init failed\n"); ++ ret = -1; ++ goto out_free_bus; ++ } ++ usb_dev->rx_priv = rx_priv; ++ ++ ret = aicwf_bus_init(0, dev); ++ if (ret < 0) { ++ usb_err("aicwf_bus_init err %d\n", ret); ++ goto out_free_bus; ++ } ++ ++ ret = aicwf_bus_start(bus_if); ++ if (ret < 0) { ++ usb_err("aicwf_bus_start err %d\n", ret); ++ goto out_free_bus; ++ } ++ ++ aicwf_rwnx_usb_platform_init(usb_dev); ++ aicwf_hostif_ready(); ++ return 0; ++ ++out_free_bus: ++ aicwf_bus_deinit(dev); ++ kfree(bus_if); ++out_free_usb: ++ aicwf_usb_deinit(usb_dev); ++out_free: ++ usb_err("failed with errno %d\n", ret); ++ kfree(usb_dev); ++ usb_set_intfdata(intf, NULL); ++ return ret; ++} ++ ++static void aicwf_usb_disconnect(struct usb_interface *intf) ++{ ++ struct aic_usb_dev *usb_dev = ++ (struct aic_usb_dev *) usb_get_intfdata(intf); ++ ++ if (!usb_dev) ++ return; ++ ++ aicwf_bus_deinit(usb_dev->dev); ++ aicwf_usb_deinit(usb_dev); ++ rwnx_cmd_mgr_deinit(&usb_dev->cmd_mgr); ++ ++ if (usb_dev->rx_priv) ++ aicwf_rx_deinit(usb_dev->rx_priv); ++ kfree(usb_dev->bus_if); ++ kfree(usb_dev); ++} ++ ++static int aicwf_usb_suspend(struct usb_interface *intf, pm_message_t state) ++{ ++ struct aic_usb_dev *usb_dev = ++ (struct aic_usb_dev *) usb_get_intfdata(intf); ++ ++ aicwf_usb_state_change(usb_dev, USB_SLEEP_ST); ++ aicwf_bus_stop(usb_dev->bus_if); ++ return 0; ++} ++ ++static int aicwf_usb_resume(struct usb_interface *intf) ++{ ++ struct aic_usb_dev *usb_dev = ++ (struct aic_usb_dev *) usb_get_intfdata(intf); ++ ++ if (usb_dev->state == USB_UP_ST) ++ return 0; ++ ++ aicwf_bus_start(usb_dev->bus_if); ++ return 0; ++} ++ ++static int aicwf_usb_reset_resume(struct usb_interface *intf) ++{ ++ return aicwf_usb_resume(intf); ++} ++ ++static struct usb_device_id aicwf_usb_id_table[] = { ++#ifndef CONFIG_USB_BT ++ {USB_DEVICE(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC)}, ++#else ++ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC, 0xff, 0xff, 0xff)}, ++#endif ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(usb, aicwf_usb_id_table); ++ ++static struct usb_driver aicwf_usbdrvr = { ++ .name = KBUILD_MODNAME, ++ .probe = aicwf_usb_probe, ++ .disconnect = aicwf_usb_disconnect, ++ .id_table = aicwf_usb_id_table, ++ .suspend = aicwf_usb_suspend, ++ .resume = aicwf_usb_resume, ++ .reset_resume = aicwf_usb_reset_resume, ++ .supports_autosuspend = 1, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) ++ .disable_hub_initiated_lpm = 1, ++#endif ++}; ++ ++void aicwf_usb_register(void) ++{ ++ if (usb_register(&aicwf_usbdrvr) < 0) { ++ usb_err("usb_register failed\n"); ++ } ++} ++ ++void aicwf_usb_exit(void) ++{ ++ if (g_rwnx_plat && g_rwnx_plat->enabled) ++ rwnx_platform_deinit(g_rwnx_plat->usbdev->rwnx_hw); ++ usb_deregister(&aicwf_usbdrvr); ++ kfree(g_rwnx_plat); ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h +new file mode 100644 +index 000000000000..cc3619b2dfe0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h +@@ -0,0 +1,99 @@ ++/** ++ * aicwf_usb.h ++ * ++ * USB function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_USB_H_ ++#define _AICWF_USB_H_ ++ ++#include ++#include "rwnx_cmds.h" ++ ++#ifdef AICWF_USB_SUPPORT ++ ++/* USB Device ID */ ++#define USB_VENDOR_ID_AIC 0xA69C ++ ++#ifndef CONFIG_USB_BT ++#define USB_PRODUCT_ID_AIC 0x8800 ++#else ++#define USB_PRODUCT_ID_AIC 0x8801 ++#endif ++ ++#define AICWF_USB_RX_URBS (200) ++#define AICWF_USB_TX_URBS (100) ++#define AICWF_USB_TX_LOW_WATER (AICWF_USB_TX_URBS/4) ++#define AICWF_USB_TX_HIGH_WATER (AICWF_USB_TX_LOW_WATER*3) ++#define AICWF_USB_MAX_PKT_SIZE (2048) ++ ++typedef enum { ++ USB_TYPE_DATA = 0X00, ++ USB_TYPE_CFG = 0X10, ++ USB_TYPE_CFG_CMD_RSP = 0X11, ++ USB_TYPE_CFG_DATA_CFM = 0X12 ++} usb_type; ++ ++enum aicwf_usb_state { ++ USB_DOWN_ST, ++ USB_UP_ST, ++ USB_SLEEP_ST ++}; ++ ++struct aicwf_usb_buf { ++ struct list_head list; ++ struct aic_usb_dev *usbdev; ++ struct urb *urb; ++ struct sk_buff *skb; ++ bool cfm; ++}; ++ ++struct aic_usb_dev { ++ struct rwnx_hw *rwnx_hw; ++ struct aicwf_bus *bus_if; ++ struct usb_device *udev; ++ struct device *dev; ++ struct aicwf_rx_priv *rx_priv; ++ enum aicwf_usb_state state; ++ struct rwnx_cmd_mgr cmd_mgr; ++ ++ struct usb_anchor rx_submitted; ++ struct work_struct rx_urb_work; ++ ++ spinlock_t rx_free_lock; ++ spinlock_t tx_free_lock; ++ spinlock_t tx_post_lock; ++ spinlock_t tx_flow_lock; ++ ++ struct list_head rx_free_list; ++ struct list_head tx_free_list; ++ struct list_head tx_post_list; ++ ++ uint bulk_in_pipe; ++ uint bulk_out_pipe; ++ ++ int tx_free_count; ++ int tx_post_count; ++ ++ struct aicwf_usb_buf usb_tx_buf[AICWF_USB_TX_URBS]; ++ struct aicwf_usb_buf usb_rx_buf[AICWF_USB_RX_URBS]; ++ ++ int msg_finished; ++ wait_queue_head_t msg_wait; ++ ulong msg_busy; ++ struct urb *msg_out_urb; ++ ++ bool tbusy; ++}; ++ ++extern void aicwf_usb_exit(void); ++extern void aicwf_usb_register(void); ++extern void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state); ++int usb_bustx_thread(void *data); ++int usb_busrx_thread(void *data); ++extern void aicwf_hostif_ready(void); ++ ++#endif /* AICWF_USB_SUPPORT */ ++#endif /* _AICWF_USB_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/btsdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/btsdio.c +new file mode 100644 +index 000000000000..81c5c1ae1e98 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/btsdio.c +@@ -0,0 +1,298 @@ ++/* ++ * ++ * Generic Bluetooth SDIO driver ++ * ++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd. ++ * Copyright (C) 2007 Marcel Holtmann ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++ ++#include "aic_btsdio.h" ++#include "rwnx_msg_tx.h" ++ ++#include ++ ++#define VERSION "0.1" ++#if CONFIG_BLUEDROID == 0 ++struct btsdio_data { ++ struct hci_dev *hdev; ++ ++ struct work_struct work; ++ ++ struct sk_buff_head txq; ++}; ++struct hci_dev *ghdev = NULL; ++ ++void bt_data_dump(char* tag, void* data, unsigned long len){ ++ unsigned long i = 0; ++ uint8_t* data_ = (uint8_t* )data; ++ ++ printk("%s %s len:(%lu)\r\n", __func__, tag, len); ++ ++ for (i = 0; i < len; i += 16){ ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", ++ data_[0 + i], ++ data_[1 + i], ++ data_[2 + i], ++ data_[3 + i], ++ data_[4 + i], ++ data_[5 + i], ++ data_[6 + i], ++ data_[7 + i], ++ data_[8 + i], ++ data_[9 + i], ++ data_[10 + i], ++ data_[11 + i], ++ data_[12 + i], ++ data_[13 + i], ++ data_[14 + i], ++ data_[15 + i]); ++ } ++ ++} ++ ++static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) ++{ ++ int err; ++ ++ AICBT_INFO("%s", data->hdev->name); ++ ++ /* Prepend Type-A header */ ++ skb_push(skb, 1); ++ skb->data[0] = hci_skb_pkt_type(skb); ++ ++ //bt_data_dump("btwrite", skb->data, skb->len); ++ err = rwnx_sdio_bt_send_req(g_rwnx_plat->sdiodev->rwnx_hw, skb->len, skb); ++ if(err<0){ ++ printk("%s rwnx_sdio_bt_send_req error %d",__func__,err); ++ return err; ++ } ++ ++ data->hdev->stat.byte_tx += skb->len; ++ ++ kfree_skb(skb); ++ ++ return 0; ++} ++ ++static void btsdio_work(struct work_struct *work) ++{ ++ struct btsdio_data *data = container_of(work, struct btsdio_data, work); ++ struct sk_buff *skb; ++ int err; ++ ++ AICBT_INFO("%s,%s", data->hdev->name,__func__); ++ ++ ++ while ((skb = skb_dequeue(&data->txq))) { ++ err = btsdio_tx_packet(data, skb); ++ if (err < 0) { ++ data->hdev->stat.err_tx++; ++ skb_queue_head(&data->txq, skb); ++ break; ++ } ++ } ++} ++ ++/* Get HCI device by index. ++ * Device is held on return. */ ++struct hci_dev *hci_dev_get(int index) ++{ ++ if (index != 0) ++ return NULL; ++ ++ return ghdev; ++} ++ ++int bt_sdio_recv(u8 *data,u32 data_len) ++{ ++ struct sk_buff *skb; ++ int type= data[0]; ++ struct hci_dev *hdev; ++ u32 len = data_len; ++ int ret=0; ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICWFDBG(LOGERROR,"%s: Failed to get hci dev[NULL]", __func__); ++ return -ENODEV; ++ } ++ ++ skb = alloc_skb(len-1,GFP_ATOMIC); ++ if(!skb){ ++ AICWFDBG(LOGERROR, "alloc skb fail %s \n",__func__); ++ } ++ memcpy(skb_put(skb,len-1) ,(data+1), len-1); ++ hdev->stat.byte_rx += len; ++ hci_skb_pkt_type(skb) = type; ++ //if(bt_bypass_event(skb)){ ++ //kfree_skb(skb); ++ ///return 0; ++ //} ++ AICBT_INFO("skb type %d",type); ++ //bt_data_dump("bt_skb", skb, skb->len); ++ ret = hci_recv_frame(hdev, skb); ++ if(ret < 0){ ++ AICWFDBG(LOGERROR, "hci_recv_frame fail %d\n",ret); ++ hdev->stat.err_rx++; ++ kfree_skb(skb); ++ } ++ return 0; ++} ++ ++static int btsdio_open(struct hci_dev *hdev) ++{ ++ //struct btsdio_data *data = hci_get_drvdata(hdev); ++ int err = 0; ++ ++ AICBT_INFO("%s", hdev->name); ++ ++ return err; ++} ++ ++static int btsdio_close(struct hci_dev *hdev) ++{ ++ //struct btsdio_data *data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("%s,%s", hdev->name,__func__); ++ ++ return 0; ++} ++ ++static int btsdio_flush(struct hci_dev *hdev) ++{ ++ struct btsdio_data *data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("%s,%s", hdev->name,__func__); ++ ++ skb_queue_purge(&data->txq); ++ ++ return 0; ++} ++ ++static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ struct btsdio_data *data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("%s,%s", hdev->name,__func__); ++ ++ switch (hci_skb_pkt_type(skb)) { ++ case HCI_COMMAND_PKT: ++ hdev->stat.cmd_tx++; ++ break; ++ ++ case HCI_ACLDATA_PKT: ++ hdev->stat.acl_tx++; ++ break; ++ ++ case HCI_SCODATA_PKT: ++ hdev->stat.sco_tx++; ++ break; ++ ++ default: ++ return -EILSEQ; ++ } ++ ++ skb_queue_tail(&data->txq, skb); ++ ++ schedule_work(&data->work); ++ ++ return 0; ++} ++ ++int btsdio_init(void) ++{ ++ struct btsdio_data *data; ++ struct hci_dev *hdev; ++ int err; ++ ++ AICBT_INFO("%s", __func__); ++ ++ ++ data = kzalloc(sizeof(struct btsdio_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ INIT_WORK(&data->work, btsdio_work); ++ ++ skb_queue_head_init(&data->txq); ++ ++ hdev = hci_alloc_dev(); ++ if (!hdev) ++ return -ENOMEM; ++ ++ hdev->bus = HCI_SDIO; ++ hci_set_drvdata(hdev, data); ++ ++ hdev->dev_type = HCI_PRIMARY; ++ ++ data->hdev = hdev; ++ ++ hdev->open = btsdio_open; ++ hdev->close = btsdio_close; ++ hdev->flush = btsdio_flush; ++ hdev->send = btsdio_send_frame; ++ ++ err = hci_register_dev(hdev); ++ if (err < 0) { ++ hci_free_dev(hdev); ++ return err; ++ } ++ ghdev = hdev; ++ ++ return 0; ++} ++ ++void btsdio_remove(void) ++{ ++ struct btsdio_data *data; ++ struct hci_dev *hdev; ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ return; ++ } ++ data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("btsdio_remove"); ++ ++ if (!data) ++ return; ++ ++ kfree(data); ++ ++ hci_unregister_dev(hdev); ++ ++ hci_free_dev(hdev); ++} ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h +new file mode 100644 +index 000000000000..e2429283314b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h +@@ -0,0 +1,383 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file hal_desc.h ++ * ++ * @brief File containing the definition of HW descriptors. ++ * ++ * Contains the definition and structures used by HW ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _HAL_DESC_H_ ++#define _HAL_DESC_H_ ++ ++#include "lmac_types.h" ++ ++/* Rate and policy table */ ++ ++#define N_CCK 8 ++#define N_OFDM 8 ++#define N_HT (8 * 2 * 2 * 4) ++#define N_VHT (10 * 4 * 2 * 8) ++#define N_HE_SU (12 * 4 * 3 * 8) ++#define N_HE_MU (12 * 6 * 3 * 8) ++#define N_HE_ER (3 * 3 + 3) //RU242 + RU106 ++ ++/* conversion table from NL80211 to MACHW enum */ ++extern const int chnl2bw[]; ++ ++/* conversion table from MACHW to NL80211 enum */ ++extern const int bw2chnl[]; ++ ++/* Rate cntrl info */ ++#define MCS_INDEX_TX_RCX_OFT 0 ++#define MCS_INDEX_TX_RCX_MASK (0x7F << MCS_INDEX_TX_RCX_OFT) ++#define BW_TX_RCX_OFT 7 ++#define BW_TX_RCX_MASK (0x3 << BW_TX_RCX_OFT) ++#define SHORT_GI_TX_RCX_OFT 9 ++#define SHORT_GI_TX_RCX_MASK (0x1 << SHORT_GI_TX_RCX_OFT) ++#define PRE_TYPE_TX_RCX_OFT 10 ++#define PRE_TYPE_TX_RCX_MASK (0x1 << PRE_TYPE_TX_RCX_OFT) ++#define FORMAT_MOD_TX_RCX_OFT 11 ++#define FORMAT_MOD_TX_RCX_MASK (0x7 << FORMAT_MOD_TX_RCX_OFT) ++ ++ ++/* Values for formatModTx */ ++#define FORMATMOD_NON_HT 0 ++#define FORMATMOD_NON_HT_DUP_OFDM 1 ++#define FORMATMOD_HT_MF 2 ++#define FORMATMOD_HT_GF 3 ++#define FORMATMOD_VHT 4 ++#define FORMATMOD_HE_SU 5 ++#define FORMATMOD_HE_MU 6 ++#define FORMATMOD_HE_ER 7 ++#define FORMATMOD_HE_TB 8 ++ ++/* Values for navProtFrmEx */ ++#define NAV_PROT_NO_PROT_BIT 0 ++#define NAV_PROT_SELF_CTS_BIT 1 ++#define NAV_PROT_RTS_CTS_BIT 2 ++#define NAV_PROT_RTS_CTS_WITH_QAP_BIT 3 ++#define NAV_PROT_STBC_BIT 4 ++ ++/* THD MACCTRLINFO2 fields, used in struct umacdesc umac.flags */ ++/// WhichDescriptor definition - contains aMPDU bit and position value ++/// Offset of WhichDescriptor field in the MAC CONTROL INFO 2 word ++#define WHICHDESC_OFT 19 ++/// Mask of the WhichDescriptor field ++#define WHICHDESC_MSK (0x07 << WHICHDESC_OFT) ++/// Only 1 THD possible, describing an unfragmented MSDU ++#define WHICHDESC_UNFRAGMENTED_MSDU (0x00 << WHICHDESC_OFT) ++/// THD describing the first MPDU of a fragmented MSDU ++#define WHICHDESC_FRAGMENTED_MSDU_FIRST (0x01 << WHICHDESC_OFT) ++/// THD describing intermediate MPDUs of a fragmented MSDU ++#define WHICHDESC_FRAGMENTED_MSDU_INT (0x02 << WHICHDESC_OFT) ++/// THD describing the last MPDU of a fragmented MSDU ++#define WHICHDESC_FRAGMENTED_MSDU_LAST (0x03 << WHICHDESC_OFT) ++/// THD for extra descriptor starting an AMPDU ++#define WHICHDESC_AMPDU_EXTRA (0x04 << WHICHDESC_OFT) ++/// THD describing the first MPDU of an A-MPDU ++#define WHICHDESC_AMPDU_FIRST (0x05 << WHICHDESC_OFT) ++/// THD describing intermediate MPDUs of an A-MPDU ++#define WHICHDESC_AMPDU_INT (0x06 << WHICHDESC_OFT) ++/// THD describing the last MPDU of an A-MPDU ++#define WHICHDESC_AMPDU_LAST (0x07 << WHICHDESC_OFT) ++ ++/// aMPDU bit offset ++#define AMPDU_OFT 21 ++/// aMPDU bit ++#define AMPDU_BIT CO_BIT(AMPDU_OFT) ++ ++union rwnx_mcs_index { ++ struct { ++ u32 mcs : 3; ++ u32 nss : 2; ++ } ht; ++ struct { ++ u32 mcs : 4; ++ u32 nss : 3; ++ } vht; ++ struct { ++ u32 mcs : 4; ++ u32 nss : 3; ++ } he; ++ u32 legacy : 7; ++}; ++ ++enum { ++ HW_RATE_1MBPS = 0, ++ HW_RATE_2MBPS = 1, ++ HW_RATE_5_5MBPS = 2, ++ HW_RATE_11MBPS = 3, ++ HW_RATE_6MBPS = 4, ++ HW_RATE_9MBPS = 5, ++ HW_RATE_12MBPS = 6, ++ HW_RATE_18MBPS = 7, ++ HW_RATE_24MBPS = 8, ++ HW_RATE_36MBPS = 9, ++ HW_RATE_48MBPS = 10, ++ HW_RATE_54MBPS = 11, ++ HW_RATE_MAX ++}; ++ ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_rate_ctrl_info { ++ struct { ++ u32 mcsIndexTx : 7; ++ u32 bwTx : 2; ++ u32 giAndPreTypeTx : 2; ++ u32 formatModTx : 3; ++ u32 navProtFrmEx : 3; ++ u32 mcsIndexProtTx : 7; ++ u32 bwProtTx : 2; ++ u32 formatModProtTx : 3; ++ u32 nRetry : 3; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++struct rwnx_power_ctrl_info { ++ u32 txPwrLevelPT : 8; ++ u32 txPwrLevelProtPT : 8; ++ u32 reserved :16; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_phy_ctrl_info_1 { ++ struct { ++ u32 rsvd1 : 3; ++ u32 bfFrmEx : 1; ++ u32 numExtnSS : 2; ++ u32 fecCoding : 1; ++ u32 stbc : 2; ++ u32 rsvd2 : 5; ++ u32 nTx : 3; ++ u32 nTxProt : 3; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_phy_ctrl_info_2 { ++ struct { ++ u32 antennaSet : 8; ++ u32 smmIndex : 8; ++ u32 beamFormed : 1; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_mac_ctrl_info_1 { ++ struct { ++ u32 keySRamIndex : 10; ++ u32 keySRamIndexRA : 10; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_mac_ctrl_info_2 { ++ struct { ++ u32 longRetryLimit : 8; ++ u32 shortRetryLimit : 8; ++ u32 rtsThreshold : 12; ++ }; ++ u32 value; ++}; ++ ++#define POLICY_TABLE_PATTERN 0xBADCAB1E ++ ++struct tx_policy_tbl { ++ /* Unique Pattern at the start of Policy Table */ ++ u32 upatterntx; ++ /* PHY Control 1 Information used by MAC HW */ ++ union rwnx_pol_phy_ctrl_info_1 phyctrlinfo_1; ++ /* PHY Control 2 Information used by MAC HW */ ++ union rwnx_pol_phy_ctrl_info_2 phyctrlinfo_2; ++ /* MAC Control 1 Information used by MAC HW */ ++ union rwnx_pol_mac_ctrl_info_1 macctrlinfo_1; ++ /* MAC Control 2 Information used by MAC HW */ ++ union rwnx_pol_mac_ctrl_info_2 macctrlinfo_2; ++ ++ union rwnx_rate_ctrl_info ratectrlinfos[NX_TX_MAX_RATES]; ++ struct rwnx_power_ctrl_info powerctrlinfos[NX_TX_MAX_RATES]; ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++/** ++ * struct rwnx_hw_txstatus - Bitfield of confirmation status ++ * ++ * @tx_done: packet has been processed by the firmware. ++ * @retry_required: packet has been transmitted but not acknoledged. ++ * Driver must repush it. ++ * @sw_retry_required: packet has not been transmitted (FW wasn't able to push ++ * it when it received it: not active channel ...). Driver must repush it. ++ * @acknowledged: packet has been acknowledged by peer ++ */ ++union rwnx_hw_txstatus { ++ struct { ++ u32 tx_done : 1; ++ u32 retry_required : 1; ++ u32 sw_retry_required : 1; ++ u32 acknowledged : 1; ++ u32 reserved :28; ++ }; ++ u32 value; ++}; ++ ++/** ++ * struct tx_cfm_tag - Structure indicating the status and other ++ * information about the transmission ++ * ++ * @pn: PN that was used for the transmission ++ * @sn: Sequence number of the packet ++ * @timestamp: Timestamp of first transmission of this MPDU ++ * @credits: Number of credits to be reallocated for the txq that push this ++ * buffer (can be 0 or 1) ++ * @ampdu_size: Size of the ampdu in which the frame has been transmitted if ++ * this was the last frame of the a-mpdu, and 0 if the frame is not the last ++ * frame on a a-mdpu. ++ * 1 means that the frame has been transmitted as a singleton. ++ * @amsdu_size: Size, in bytes, allowed to create a-msdu. ++ * @status: transmission status ++ */ ++struct tx_cfm_tag { ++/* ++ u16_l pn[4]; ++ u16_l sn; ++ u16_l timestamp; ++*/ ++ s8_l credits; ++ u8_l ampdu_size; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ u16_l amsdu_size; ++#endif ++ union rwnx_hw_txstatus status; ++ u32_l hostid; ++}; ++ ++/** ++ * struct rwnx_hw_txhdr - Hardware part of tx header ++ * ++ * @cfm: Information updated by fw/hardware after sending a frame ++ */ ++struct rwnx_hw_txhdr { ++ struct tx_cfm_tag cfm; ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/* Modem */ ++ ++#define MDM_PHY_CONFIG_TRIDENT 0 ++#define MDM_PHY_CONFIG_ELMA 1 ++#define MDM_PHY_CONFIG_KARST 2 ++ ++// MODEM features (from reg_mdm_stat.h) ++/// MUMIMOTX field bit ++#define MDM_MUMIMOTX_BIT ((u32)0x80000000) ++/// MUMIMOTX field position ++#define MDM_MUMIMOTX_POS 31 ++/// MUMIMORX field bit ++#define MDM_MUMIMORX_BIT ((u32)0x40000000) ++/// MUMIMORX field position ++#define MDM_MUMIMORX_POS 30 ++/// BFMER field bit ++#define MDM_BFMER_BIT ((u32)0x20000000) ++/// BFMER field position ++#define MDM_BFMER_POS 29 ++/// BFMEE field bit ++#define MDM_BFMEE_BIT ((u32)0x10000000) ++/// BFMEE field position ++#define MDM_BFMEE_POS 28 ++/// LDPCDEC field bit ++#define MDM_LDPCDEC_BIT ((u32)0x08000000) ++/// LDPCDEC field position ++#define MDM_LDPCDEC_POS 27 ++/// LDPCENC field bit ++#define MDM_LDPCENC_BIT ((u32)0x04000000) ++/// LDPCENC field position ++#define MDM_LDPCENC_POS 26 ++/// CHBW field mask ++#define MDM_CHBW_MASK ((u32)0x03000000) ++/// CHBW field LSB position ++#define MDM_CHBW_LSB 24 ++/// CHBW field width ++#define MDM_CHBW_WIDTH ((u32)0x00000002) ++/// DSSSCCK field bit ++#define MDM_DSSSCCK_BIT ((u32)0x00800000) ++/// DSSSCCK field position ++#define MDM_DSSSCCK_POS 23 ++/// VHT field bit ++#define MDM_VHT_BIT ((u32)0x00400000) ++/// VHT field position ++#define MDM_VHT_POS 22 ++/// HE field bit ++#define MDM_HE_BIT ((u32)0x00200000) ++/// HE field position ++#define MDM_HE_POS 21 ++/// ESS field bit ++#define MDM_ESS_BIT ((u32)0x00100000) ++/// ESS field position ++#define MDM_ESS_POS 20 ++/// RFMODE field mask ++#define MDM_RFMODE_MASK ((u32)0x000F0000) ++/// RFMODE field LSB position ++#define MDM_RFMODE_LSB 16 ++/// RFMODE field width ++#define MDM_RFMODE_WIDTH ((u32)0x00000004) ++/// NSTS field mask ++#define MDM_NSTS_MASK ((u32)0x0000F000) ++/// NSTS field LSB position ++#define MDM_NSTS_LSB 12 ++/// NSTS field width ++#define MDM_NSTS_WIDTH ((u32)0x00000004) ++/// NSS field mask ++#define MDM_NSS_MASK ((u32)0x00000F00) ++/// NSS field LSB position ++#define MDM_NSS_LSB 8 ++/// NSS field width ++#define MDM_NSS_WIDTH ((u32)0x00000004) ++/// NTX field mask ++#define MDM_NTX_MASK ((u32)0x000000F0) ++/// NTX field LSB position ++#define MDM_NTX_LSB 4 ++/// NTX field width ++#define MDM_NTX_WIDTH ((u32)0x00000004) ++/// NRX field mask ++#define MDM_NRX_MASK ((u32)0x0000000F) ++/// NRX field LSB position ++#define MDM_NRX_LSB 0 ++/// NRX field width ++#define MDM_NRX_WIDTH ((u32)0x00000004) ++ ++#define __MDM_PHYCFG_FROM_VERS(v) (((v) & MDM_RFMODE_MASK) >> MDM_RFMODE_LSB) ++ ++#define RIU_FCU_PRESENT_MASK ((u32)0xFF000000) ++#define RIU_FCU_PRESENT_LSB 24 ++ ++#define __RIU_FCU_PRESENT(v) (((v) & RIU_FCU_PRESENT_MASK) >> RIU_FCU_PRESENT_LSB == 5) ++ ++/// AGC load version field mask ++#define RIU_AGC_LOAD_MASK ((u32)0x00C00000) ++/// AGC load version field LSB position ++#define RIU_AGC_LOAD_LSB 22 ++ ++#define __RIU_AGCLOAD_FROM_VERS(v) (((v) & RIU_AGC_LOAD_MASK) >> RIU_AGC_LOAD_LSB) ++ ++#define __FPGA_TYPE(v) (((v) & 0xFFFF0000) >> 16) ++ ++#define __MDM_MAJOR_VERSION(v) (((v) & 0xFF000000) >> 24) ++#define __MDM_MINOR_VERSION(v) (((v) & 0x00FF0000) >> 16) ++#define __MDM_VERSION(v) ((__MDM_MAJOR_VERSION(v) + 2) * 10 + __MDM_MINOR_VERSION(v)) ++ ++ ++#endif // _HAL_DESC_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h +new file mode 100644 +index 000000000000..069f69ee5ee0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h +@@ -0,0 +1,25 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file ipc_compat.h ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _IPC_H_ ++#define _IPC_H_ ++ ++#define __INLINE inline ++ ++#define __ALIGN4 __aligned(4) ++ ++#define ASSERT_ERR(condition) \ ++ do { \ ++ if (unlikely(!(condition))) { \ ++ printk(KERN_ERR "%s:%d:ASSERT_ERR(" #condition ")\n", __FILE__, __LINE__); \ ++ } \ ++ } while (0) ++ ++#endif /* _IPC_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c +new file mode 100644 +index 000000000000..7746f4097976 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c +@@ -0,0 +1,52 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file ipc_host.c ++ * ++ * @brief IPC module. ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++/* ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++#ifndef __KERNEL__ ++#include ++#else ++#include ++#include "rwnx_defs.h" ++#include "rwnx_prof.h" ++#endif ++ ++#include "ipc_host.h" ++ ++/* ++ * TYPES DEFINITION ++ ****************************************************************************** ++ */ ++ ++const int nx_txdesc_cnt[] = { ++ NX_TXDESC_CNT0, ++ NX_TXDESC_CNT1, ++ NX_TXDESC_CNT2, ++ NX_TXDESC_CNT3, ++ #if NX_TXQ_CNT == 5 ++ NX_TXDESC_CNT4, ++ #endif ++}; ++ ++const int nx_txuser_cnt[] = { ++ CONFIG_USER_MAX, ++ CONFIG_USER_MAX, ++ CONFIG_USER_MAX, ++ CONFIG_USER_MAX, ++ #if NX_TXQ_CNT == 5 ++ 1, ++ #endif ++}; ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h +new file mode 100644 +index 000000000000..583b66889aa4 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h +@@ -0,0 +1,168 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file ipc_host.h ++ * ++ * @brief IPC module. ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _IPC_HOST_H_ ++#define _IPC_HOST_H_ ++ ++/* ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++#include "ipc_shared.h" ++#ifndef __KERNEL__ ++#include "arch.h" ++#else ++#include "ipc_compat.h" ++#endif ++ ++/** ++ ****************************************************************************** ++ * @brief This structure is used to initialize the MAC SW ++ * ++ * The WLAN device driver provides functions call-back with this structure ++ ****************************************************************************** ++ */ ++struct ipc_host_cb_tag { ++ /// WLAN driver call-back function: send_data_cfm ++ int (*send_data_cfm)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_data_ind ++ uint8_t (*recv_data_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_radar_ind ++ uint8_t (*recv_radar_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_unsup_rx_vec_ind ++ uint8_t (*recv_unsup_rx_vec_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_msg_ind ++ uint8_t (*recv_msg_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_msgack_ind ++ uint8_t (*recv_msgack_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_dbg_ind ++ uint8_t (*recv_dbg_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: prim_tbtt_ind ++ void (*prim_tbtt_ind)(void *pthis); ++ ++ /// WLAN driver call-back function: sec_tbtt_ind ++ void (*sec_tbtt_ind)(void *pthis); ++ ++}; ++ ++/* ++ * Struct used to store information about host buffers (DMA Address and local pointer) ++ */ ++struct ipc_hostbuf { ++ void *hostid; ///< ptr to hostbuf client (ipc_host client) structure ++ uint32_t dma_addr; ///< ptr to real hostbuf dma address ++}; ++ ++/// Definition of the IPC Host environment structure. ++struct ipc_host_env_tag { ++ /// Structure containing the callback pointers ++ struct ipc_host_cb_tag cb; ++ ++ /// Pointer to the shared environment ++ struct ipc_shared_env_tag *shared; ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ // Array used to store the descriptor addresses ++ struct ipc_hostbuf ipc_host_rxdesc_array[IPC_RXDESC_CNT]; ++ // Index of the host RX descriptor array (ipc_shared environment) ++ uint8_t ipc_host_rxdesc_idx; ++ /// Store the number of RX Descriptors ++ uint8_t rxdesc_nb; ++ #endif //(CONFIG_RWNX_FULLMAC) ++ ++ /// Fields for Data Rx handling ++ // Index used for ipc_host_rxbuf_array to point to current buffer ++ uint8_t ipc_host_rxbuf_idx; ++ // Store the number of Rx Data buffers ++ uint32_t rx_bufnb; ++ // Store the size of the Rx Data buffers ++ uint32_t rx_bufsz; ++ ++ /// Fields for Radar events handling ++ // Global array used to store the hostid and hostbuf addresses ++ struct ipc_hostbuf ipc_host_radarbuf_array[IPC_RADARBUF_CNT]; ++ // Index used for ipc_host_rxbuf_array to point to current buffer ++ uint8_t ipc_host_radarbuf_idx; ++ // Store the number of radar event buffers ++ uint32_t radar_bufnb; ++ // Store the size of the radar event buffers ++ uint32_t radar_bufsz; ++ ++ ///Fields for Unsupported frame handling ++ // Global array used to store the hostid and hostbuf addresses ++ struct ipc_hostbuf ipc_host_unsuprxvecbuf_array[IPC_UNSUPRXVECBUF_CNT]; ++ // Index used for ipc_host_unsuprxvecbuf_array to point to current buffer ++ uint8_t ipc_host_unsuprxvecbuf_idx; ++ // Store the number of unsupported rx vector buffers ++ uint32_t unsuprxvec_bufnb; ++ // Store the size of unsupported rx vector buffers ++ uint32_t unsuprxvec_bufsz; ++ ++ // Index used that points to the first free TX desc ++ uint32_t txdesc_free_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ // Index used that points to the first used TX desc ++ uint32_t txdesc_used_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ // Array storing the currently pushed host ids for the BK queue ++ void *tx_host_id0[CONFIG_USER_MAX][NX_TXDESC_CNT0]; ++ // Array storing the currently pushed host ids for the BE queue ++ void *tx_host_id1[CONFIG_USER_MAX][NX_TXDESC_CNT1]; ++ // Array storing the currently pushed host ids for the VI queue ++ void *tx_host_id2[CONFIG_USER_MAX][NX_TXDESC_CNT2]; ++ // Array storing the currently pushed host ids for the VO queue ++ void *tx_host_id3[CONFIG_USER_MAX][NX_TXDESC_CNT3]; ++ #if NX_TXQ_CNT == 5 ++ // Array storing the currently pushed host ids for the BCN queue ++ void *tx_host_id4[1][NX_TXDESC_CNT4]; ++ #endif ++ // Pointer to the different host ids arrays, per IPC queue ++ void **tx_host_id[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ // Pointer to the different TX descriptor arrays, per IPC queue ++ volatile struct txdesc_host *txdesc[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ ++ /// Fields for Emb->App MSGs handling ++ // Global array used to store the hostid and hostbuf addresses for msg/ind ++ struct ipc_hostbuf ipc_host_msgbuf_array[IPC_MSGE2A_BUF_CNT]; ++ // Index of the MSG E2A buffers array to point to current buffer ++ uint8_t ipc_host_msge2a_idx; ++ // Store the number of E2A MSG buffers ++ uint32_t ipc_e2amsg_bufnb; ++ // Store the size of the E2A MSG buffers ++ uint32_t ipc_e2amsg_bufsz; ++ ++ /// E2A ACKs of A2E MSGs ++ uint8_t msga2e_cnt; ++ void *msga2e_hostid; ++ ++ /// Fields for Debug MSGs handling ++ // Global array used to store the hostid and hostbuf addresses for Debug messages ++ struct ipc_hostbuf ipc_host_dbgbuf_array[IPC_DBGBUF_CNT]; ++ // Index of the Debug messages buffers array to point to current buffer ++ uint8_t ipc_host_dbg_idx; ++ // Store the number of Debug messages buffers ++ uint32_t ipc_dbg_bufnb; ++ // Store the size of the Debug messages buffers ++ uint32_t ipc_dbg_bufsz; ++ ++ /// Pointer to the attached object (used in callbacks and register accesses) ++ void *pthis; ++}; ++ ++extern const int nx_txdesc_cnt[]; ++extern const int nx_txuser_cnt[]; ++ ++#endif // _IPC_HOST_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h +new file mode 100644 +index 000000000000..7e2fedcb1b53 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h +@@ -0,0 +1,785 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file ipc_shared.h ++ * ++ * @brief Shared data between both IPC modules. ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _IPC_SHARED_H_ ++#define _IPC_SHARED_H_ ++ ++/* ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++#include "ipc_compat.h" ++#include "lmac_mac.h" ++ ++/* ++ * DEFINES AND MACROS ++ **************************************************************************************** ++ */ ++#define CO_BIT(pos) (1U<<(pos)) ++ ++#define IPC_TXQUEUE_CNT NX_TXQ_CNT ++#define NX_TXDESC_CNT0 8 ++#define NX_TXDESC_CNT1 64 ++#define NX_TXDESC_CNT2 64 ++#define NX_TXDESC_CNT3 32 ++#if NX_TXQ_CNT == 5 ++#define NX_TXDESC_CNT4 8 ++#endif ++ ++/* ++ * Number of Host buffers available for Data Rx handling (through DMA) ++ */ ++#define IPC_RXBUF_CNT 128 ++ ++/* ++ * Number of shared descriptors available for Data RX handling ++ */ ++#define IPC_RXDESC_CNT 128 ++ ++/* ++ * Number of Host buffers available for Radar events handling (through DMA) ++ */ ++#define IPC_RADARBUF_CNT 16 ++ ++/* ++ * Number of Host buffers available for unsupported Rx vectors handling (through DMA) ++ */ ++#define IPC_UNSUPRXVECBUF_CNT 8 ++ ++/* ++ * Size of RxVector ++ */ ++#define IPC_RXVEC_SIZE 16 ++ ++/* ++ * Number of Host buffers available for Emb->App MSGs sending (through DMA) ++ */ ++#ifdef CONFIG_RWNX_FULLMAC ++#define IPC_MSGE2A_BUF_CNT 64 ++#endif ++/* ++ * Number of Host buffers available for Debug Messages sending (through DMA) ++ */ ++#define IPC_DBGBUF_CNT 32 ++ ++/* ++ * Length used in MSGs structures ++ */ ++#define IPC_A2E_MSG_BUF_SIZE 127 // size in 4-byte words ++#ifdef CONFIG_RWNX_FULLMAC ++#define IPC_E2A_MSG_SIZE_BASE 256 // size in 4-byte words ++#endif ++ ++#ifdef CONFIG_RWNX_TL4 ++#define IPC_E2A_MSG_PARAM_SIZE (IPC_E2A_MSG_SIZE_BASE + (IPC_E2A_MSG_SIZE_BASE / 2)) ++#else ++#define IPC_E2A_MSG_PARAM_SIZE IPC_E2A_MSG_SIZE_BASE ++#endif ++ ++/* ++ * Debug messages buffers size (in bytes) ++ */ ++#define IPC_DBG_PARAM_SIZE 256 ++ ++/* ++ * Define used for Rx hostbuf validity. ++ * This value should appear only when hostbuf was used for a Reception. ++ */ ++#define RX_DMA_OVER_PATTERN 0xAAAAAA00 ++ ++/* ++ * Define used for MSG buffers validity. ++ * This value will be written only when a MSG buffer is used for sending from Emb to App. ++ */ ++#define IPC_MSGE2A_VALID_PATTERN 0xADDEDE2A ++ ++/* ++ * Define used for Debug messages buffers validity. ++ * This value will be written only when a DBG buffer is used for sending from Emb to App. ++ */ ++#define IPC_DBG_VALID_PATTERN 0x000CACA0 ++ ++/* ++ * Length of the receive vectors, in bytes ++ */ ++#define DMA_HDR_PHYVECT_LEN 36 ++ ++/* ++ * Maximum number of payload addresses and lengths present in the descriptor ++ */ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++#define NX_TX_PAYLOAD_MAX 6 ++#else ++#define NX_TX_PAYLOAD_MAX 1 ++#endif ++ ++/* ++ * Message struct/ID API version ++ */ ++#define MSG_API_VER 33 ++ ++/* ++ **************************************************************************************** ++ */ ++// c.f LMAC/src/tx/tx_swdesc.h ++/// Descriptor filled by the Host ++struct hostdesc { ++ /// Pointer to packet payload ++ //u32_l packet_addr; ++ /// Size of the payload ++ u16_l packet_len; ++ u16_l flags_ext; ++ ++ u32_l hostid; ++#ifdef CONFIG_RWNX_FULLMAC ++ /// Address of the status descriptor in host memory (used for confirmation upload) ++ //u32_l status_desc_addr; ++ /// Destination Address ++ struct mac_addr eth_dest_addr; ++ /// Source Address ++ struct mac_addr eth_src_addr; ++ /// Ethernet Type ++ u16_l ethertype; ++#else /* ! CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_AGG_TX ++ ///Sequence Number for AMPDU MPDUs - for quick check if it's allowed within window ++ u16_l sn; ++#endif /* CONFIG_RWNX_AGG_TX */ ++ /// Padding between the buffer control structure and the MPDU in host memory ++ u8_l padding; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ u8_l ac; ++ /// Packet TID (0xFF if not a QoS frame) ++ u8_l tid; ++ /// Interface Id ++ u8_l vif_idx; ++ /// Station Id (0xFF if station is unknown) ++ u8_l staid; ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ /// MU-MIMO information (GroupId and User Position in the group) - The GroupId ++ /// is located on bits 0-5 and the User Position on bits 6-7. The GroupId value is set ++ /// to 63 if MU-MIMO shall not be used ++ u8_l mumimo_info; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#ifdef CONFIG_RWNX_FULLMAC ++ /// TX flags ++ u16_l flags; ++#endif /* CONFIG_RWNX_FULLMAC */ ++}; ++ ++/// Descriptor filled by the UMAC ++struct umacdesc { ++#ifdef CONFIG_RWNX_AGG_TX ++ ///First Sequence Number of the BlockAck window ++ u16_l sn_win; ++ /// Flags from UMAC (match tx_hd.macctrlinfo2 format) ++ u32_l flags; ++ /// PHY related flags field - rate, GI type, BW type - filled by driver ++ u32_l phy_flags; ++#endif //(CONFIG_RWNX_AGG_TX) ++}; ++ ++struct txdesc_api { ++ /// Information provided by Host ++ struct hostdesc host; ++}; ++ ++ ++struct txdesc_host { ++ u32_l ready; ++ ++ /// API of the embedded part ++ struct txdesc_api api; ++}; ++ ++/// Comes from ipc_dma.h ++/// Element in the pool of TX DMA bridge descriptors. ++struct dma_desc { ++ /** Application subsystem address which is used as source address for DMA payload ++ * transfer*/ ++ u32_l src; ++ /** Points to the start of the embedded data buffer associated with this descriptor. ++ * This address acts as the destination address for the DMA payload transfer*/ ++ u32_l dest; ++ /// Complete length of the buffer in memory ++ u16_l length; ++ /// Control word for the DMA engine (e.g. for interrupt generation) ++ u16_l ctrl; ++ /// Pointer to the next element of the chained list ++ u32_l next; ++}; ++ ++// Comes from la.h ++/// Length of the configuration data of a logic analyzer ++#define LA_CONF_LEN 10 ++ ++/// Structure containing the configuration data of a logic analyzer ++struct la_conf_tag { ++ u32_l conf[LA_CONF_LEN]; ++ u32_l trace_len; ++ u32_l diag_conf; ++}; ++ ++/// Size of a logic analyzer memory ++#define LA_MEM_LEN (1024 * 1024) ++ ++/// Type of errors ++enum { ++ /// Recoverable error, not requiring any action from Upper MAC ++ DBG_ERROR_RECOVERABLE = 0, ++ /// Fatal error, requiring Upper MAC to reset Lower MAC and HW and restart operation ++ DBG_ERROR_FATAL ++}; ++ ++/// Maximum length of the SW diag trace ++#define DBG_SW_DIAG_MAX_LEN 1024 ++ ++/// Maximum length of the error trace ++#define DBG_ERROR_TRACE_SIZE 256 ++ ++/// Number of MAC diagnostic port banks ++#define DBG_DIAGS_MAC_MAX 48 ++ ++/// Number of PHY diagnostic port banks ++#define DBG_DIAGS_PHY_MAX 32 ++ ++/// Maximum size of the RX header descriptor information in the debug dump ++#define DBG_RHD_MEM_LEN (5 * 1024) ++ ++/// Maximum size of the RX buffer descriptor information in the debug dump ++#define DBG_RBD_MEM_LEN (5 * 1024) ++ ++/// Maximum size of the TX header descriptor information in the debug dump ++#define DBG_THD_MEM_LEN (10 * 1024) ++ ++/// Structure containing the information about the PHY channel that is used ++struct phy_channel_info { ++ /// PHY channel information 1 ++ u32_l info1; ++ /// PHY channel information 2 ++ u32_l info2; ++}; ++ ++/// Debug information forwarded to host when an error occurs ++struct dbg_debug_info_tag { ++ /// Type of error (0: recoverable, 1: fatal) ++ u32_l error_type; ++ /// Pointer to the first RX Header Descriptor chained to the MAC HW ++ u32_l rhd; ++ /// Size of the RX header descriptor buffer ++ u32_l rhd_len; ++ /// Pointer to the first RX Buffer Descriptor chained to the MAC HW ++ u32_l rbd; ++ /// Size of the RX buffer descriptor buffer ++ u32_l rbd_len; ++ /// Pointer to the first TX Header Descriptors chained to the MAC HW ++ u32_l thd[NX_TXQ_CNT]; ++ /// Size of the TX header descriptor buffer ++ u32_l thd_len[NX_TXQ_CNT]; ++ /// MAC HW diag configuration ++ u32_l hw_diag; ++ /// Error message ++ u32_l error[DBG_ERROR_TRACE_SIZE/4]; ++ /// SW diag configuration length ++ u32_l sw_diag_len; ++ /// SW diag configuration ++ u32_l sw_diag[DBG_SW_DIAG_MAX_LEN/4]; ++ /// PHY channel information ++ struct phy_channel_info chan_info; ++ /// Embedded LA configuration ++ struct la_conf_tag la_conf; ++ /// MAC diagnostic port state ++ u16_l diags_mac[DBG_DIAGS_MAC_MAX]; ++ /// PHY diagnostic port state ++ u16_l diags_phy[DBG_DIAGS_PHY_MAX]; ++ /// MAC HW RX Header descriptor pointer ++ u32_l rhd_hw_ptr; ++ /// MAC HW RX Buffer descriptor pointer ++ u32_l rbd_hw_ptr; ++}; ++ ++/// Full debug dump that is forwarded to host in case of error ++struct dbg_debug_dump_tag { ++ /// Debug information ++ struct dbg_debug_info_tag dbg_info; ++ ++ /// RX header descriptor memory ++ u32_l rhd_mem[DBG_RHD_MEM_LEN/4]; ++ ++ /// RX buffer descriptor memory ++ u32_l rbd_mem[DBG_RBD_MEM_LEN/4]; ++ ++ /// TX header descriptor memory ++ u32_l thd_mem[NX_TXQ_CNT][DBG_THD_MEM_LEN/4]; ++ ++ /// Logic analyzer memory ++ u32_l la_mem[LA_MEM_LEN/4]; ++}; ++ ++ ++/// Number of pulses in a radar event structure ++#define RADAR_PULSE_MAX 4 ++ ++/// Definition of an array of radar pulses ++struct radar_pulse_array_desc { ++ /// Buffer containing the radar pulses ++ u32_l pulse[RADAR_PULSE_MAX]; ++ /// Index of the radar detection chain that detected those pulses ++ u32_l idx; ++ /// Number of valid pulses in the buffer ++ u32_l cnt; ++}; ++ ++/// Bit mapping inside a radar pulse element ++struct radar_pulse { ++ s32_l freq:6; /** Freq (resolution is 2Mhz range is [-Fadc/4 .. Fadc/4]) */ ++ u32_l fom:4; /** Figure of Merit */ ++ u32_l len:6; /** Length of the current radar pulse (resolution is 2us) */ ++ u32_l rep:16; /** Time interval between the previous radar event ++ and the current one (in us) */ ++}; ++ ++/// Definition of a RX vector descriptor ++struct rx_vector_desc { ++ /// PHY channel information ++ struct phy_channel_info phy_info; ++ ++ /// RX vector 1 ++ u32_l rx_vect1[IPC_RXVEC_SIZE/4]; ++ ++ /// Used to print a valid rx vector ++ u32_l pattern; ++}; ++ ++/// ++struct rxdesc_tag { ++ /// Host Buffer Address ++ u32_l host_id; ++ /// Length ++ u32_l frame_len; ++ /// Status ++ u16_l status; ++}; ++ ++/** ++ **************************************************************************************** ++ * @defgroup IPC IPC ++ * @ingroup NXMAC ++ * @brief Inter Processor Communication module. ++ * ++ * The IPC module implements the protocol to communicate between the Host CPU ++ * and the Embedded CPU. ++ * ++ * @see http://en.wikipedia.org/wiki/Circular_buffer ++ * For more information about the ring buffer typical use and difficulties. ++ **************************************************************************************** ++ */ ++ ++ ++/** ++ **************************************************************************************** ++ * @addtogroup IPC_TX IPC Tx path ++ * @ingroup IPC ++ * @brief IPC Tx path structures and functions ++ * ++ * A typical use case of the IPC Tx path API: ++ * @msc ++ * hscale = "2"; ++ * ++ * a [label=Driver], ++ * b [label="IPC host"], ++ * c [label="IPC emb"], ++ * d [label=Firmware]; ++ * ++ * --- [label="Tx descriptor queue example"]; ++ * a=>a [label="Driver receives a Tx packet from OS"]; ++ * a=>b [label="ipc_host_txdesc_get()"]; ++ * a<a [label="Driver fill the descriptor"]; ++ * a=>b [label="ipc_host_txdesc_push()"]; ++ * ... [label="(several Tx desc can be pushed)"]; ++ * b:>c [label="Tx desc queue filled IRQ"]; ++ * c=>>d [label="EDCA sub-scheduler callback"]; ++ * c<>d [label="UMAC Tx desc callback"]; ++ * ... [label="(several Tx desc can be popped)"]; ++ * d=>d [label="Packets are sent or discarded"]; ++ * --- [label="Tx confirm queue example"]; ++ * c<=d [label="ipc_emb_txcfm_push()"]; ++ * c>>d [label="Request accepted"]; ++ * ... [label="(several Tx cfm can be pushed)"]; ++ * b<:c [label="Tx cfm queue filled IRQ"]; ++ * a<<=b [label="Driver's Tx Confirm callback"]; ++ * a=>b [label="ipc_host_txcfm_pop()"]; ++ * a<c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * ... [label="(several Rx buffer are pushed)"]; ++ * a=>a [label=" Frame is received\n from the medium"]; ++ * a<a [label=" Firmware fill the buffer\n with received frame"]; ++ * a<c [label="Rx desc queue filled IRQ"]; ++ * c=>>d [label="Driver Rx packet callback"]; ++ * c<=d [label="ipc_host_rxdesc_pop()"]; ++ * d=>d [label="Rx packet is handed \nover to the OS "]; ++ * ... [label="(several Rx desc can be poped)"]; ++ * --- [label="Rx buffer request exemple"]; ++ * b:>c [label="Low Rx buffer count IRQ"]; ++ * a<>d [label="Driver Rx buffer callback"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * ... [label="(several Rx buffer are pushed)"]; ++ * @endmsc ++ * ++ * @addtogroup IPC_RX ++ * @{ ++ **************************************************************************************** ++ */ ++ ++/// @} IPC_RX ++ ++ ++ ++/** ++ **************************************************************************************** ++ * @defgroup IPC_MISC IPC Misc ++ * @ingroup IPC ++ * @brief IPC miscellaneous functions ++ **************************************************************************************** ++ */ ++/** IPC header structure. This structure is stored at the beginning of every IPC message. ++ * @warning This structure's size must NOT exceed 4 bytes in length. ++ */ ++struct ipc_header { ++ /// IPC message type. ++ u16_l type; ++ /// IPC message size in number of bytes. ++ u16_l size; ++}; ++ ++struct ipc_msg_elt { ++ /// Message header (alignment forced on word size, see allocation in shared env). ++ struct ipc_header header __ALIGN4; ++}; ++ ++/// Message structure for MSGs from Emb to App ++struct ipc_e2a_msg { ++ u16_l id; ///< Message id. ++ u16_l dummy_dest_id; ++ u16_l dummy_src_id; ++ u16_l param_len; ///< Parameter embedded struct length. ++ u32_l pattern; ///< Used to stamp a valid MSG buffer ++ u32_l param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++/// Message structure for Debug messages from Emb to App ++struct ipc_dbg_msg { ++ u32_l string[IPC_DBG_PARAM_SIZE/4]; ///< Debug string ++ u32_l pattern; ///< Used to stamp a valid buffer ++}; ++ ++/// Message structure for MSGs from App to Emb. ++/// Actually a sub-structure will be used when filling the messages. ++struct ipc_a2e_msg { ++ u32_l dummy_word; // used to cope with kernel message structure ++ u32_l msg[IPC_A2E_MSG_BUF_SIZE]; // body of the msg ++}; ++ ++struct ipc_shared_rx_buf { ++ /// < ptr to hostbuf client (ipc_host client) structure ++ u32_l hostid; ++ /// < ptr to real hostbuf dma address ++ u32_l dma_addr; ++}; ++ ++struct ipc_shared_rx_desc { ++ /// DMA Address ++ u32_l dma_addr; ++}; ++ ++/// Structure containing FW characteristics for compatibility checking ++struct compatibility_tag { ++ /// Size of IPC shared memory ++ u16_l ipc_shared_size; ++ /// Message struct/ID API version ++ u16_l msg_api; ++ /// Version of IPC shared ++ u8_l ipc_shared_version; ++ /// Number of host buffers available for Emb->App MSGs sending ++ u8_l msge2a_buf_cnt; ++ /// Number of host buffers available for Debug Messages sending ++ u8_l dbgbuf_cnt; ++ /// Number of host buffers available for Radar events handling ++ u8_l radarbuf_cnt; ++ /// Number of host buffers available for unsupported Rx vectors handling ++ u8_l unsuprxvecbuf_cnt; ++ /// Number of shared descriptors available for Data RX handling ++ u8_l rxdesc_cnt; ++ /// Number of host buffers available for Data Rx handling ++ u8_l rxbuf_cnt; ++ /// Number of descriptors in BK TX queue (power of 2, min 4, max 64) ++ u8_l bk_txq; ++ /// Number of descriptors in BE TX queue (power of 2, min 4, max 64) ++ u8_l be_txq; ++ /// Number of descriptors in VI TX queue (power of 2, min 4, max 64) ++ u8_l vi_txq; ++ /// Number of descriptors in VO TX queue (power of 2, min 4, max 64) ++ u8_l vo_txq; ++ /// Number of descriptors in BCN TX queue (power of 2, min 4, max 64) ++ u8_l bcn_txq; ++}; ++ ++/* ++ * TYPE and STRUCT DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++ ++// Indexes are defined in the MIB shared structure ++struct ipc_shared_env_tag { ++ volatile struct compatibility_tag comp_info; //FW characteristics ++ ++ volatile struct ipc_a2e_msg msg_a2e_buf; // room for MSG to be sent from App to Emb ++ ++ // Fields for MSGs sending from Emb to App ++ volatile struct ipc_e2a_msg msg_e2a_buf; // room to build the MSG to be DMA Xferred ++ volatile struct dma_desc msg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers ++ volatile u32_l msg_e2a_hostbuf_addr[IPC_MSGE2A_BUF_CNT]; // buffers @ for DMA Xfers ++ ++ // Fields for Debug MSGs sending from Emb to App ++ volatile struct ipc_dbg_msg dbg_buf; // room to build the MSG to be DMA Xferred ++ volatile struct dma_desc dbg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers ++ volatile u32_l dbg_hostbuf_addr[IPC_DBGBUF_CNT]; // buffers @ for MSGs DMA Xfers ++ volatile u32_l la_dbginfo_addr; // Host buffer address for the debug information ++ volatile u32_l pattern_addr; ++ volatile u32_l radarbuf_hostbuf[IPC_RADARBUF_CNT]; // buffers @ for Radar Events ++ volatile u32_l unsuprxvecbuf_hostbuf[IPC_UNSUPRXVECBUF_CNT]; // buffers @ for unsupported Rx vectors ++ volatile struct txdesc_host txdesc0[CONFIG_USER_MAX][NX_TXDESC_CNT0]; ++ volatile struct txdesc_host txdesc1[CONFIG_USER_MAX][NX_TXDESC_CNT1]; ++ volatile struct txdesc_host txdesc2[CONFIG_USER_MAX][NX_TXDESC_CNT2]; ++ volatile struct txdesc_host txdesc3[CONFIG_USER_MAX][NX_TXDESC_CNT3]; ++ #if NX_TXQ_CNT == 5 ++ volatile struct txdesc_host txdesc4[1][NX_TXDESC_CNT4]; ++ #endif ++ #ifdef CONFIG_RWNX_FULLMAC ++ // RX Descriptors Array ++ volatile struct ipc_shared_rx_desc host_rxdesc[IPC_RXDESC_CNT]; ++ // RX Buffers Array ++ volatile struct ipc_shared_rx_buf host_rxbuf[IPC_RXBUF_CNT]; ++ #else ++ // buffers @ for Data Rx ++ volatile u32_l host_rxbuf[IPC_RXBUF_CNT]; ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ ++ u32_l buffered[NX_REMOTE_STA_MAX][TID_MAX]; ++ ++ volatile uint16_t trace_pattern; ++ volatile uint32_t trace_start; ++ volatile uint32_t trace_end; ++ volatile uint32_t trace_size; ++ volatile uint32_t trace_offset; ++ volatile uint32_t trace_nb_compo; ++ volatile uint32_t trace_offset_compo; ++}; ++ ++extern struct ipc_shared_env_tag ipc_shared_env; ++ ++ ++/* ++ * TYPE and STRUCT DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++// IRQs from app to emb ++/// Interrupts bits used for the TX descriptors of the AC queues ++#ifdef CONFIG_RWNX_MUMIMO_TX ++#ifdef CONFIG_RWNX_OLD_IPC ++#error "MU-MIMO cannot be compiled for old IPC" ++#endif ++/// Interrupts bits used ++#if CONFIG_USER_MAX > 3 ++#define IPC_IRQ_A2E_USER_MSK 0xF ++#elif CONFIG_USER_MAX > 2 ++#define IPC_IRQ_A2E_USER_MSK 0x7 ++#else ++#define IPC_IRQ_A2E_USER_MSK 0x3 ++#endif ++ ++/// Offset of the interrupts for AC0 ++#define IPC_IRQ_A2E_AC0_OFT 8 ++/// Mask of the interrupts for AC0 ++#define IPC_IRQ_A2E_AC0_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC0_OFT) ++/// Offset of the interrupts for AC1 ++#define IPC_IRQ_A2E_AC1_OFT (IPC_IRQ_A2E_AC0_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC1 ++#define IPC_IRQ_A2E_AC1_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC1_OFT) ++/// Offset of the interrupts for AC2 ++#define IPC_IRQ_A2E_AC2_OFT (IPC_IRQ_A2E_AC1_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC2 ++#define IPC_IRQ_A2E_AC2_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC2_OFT) ++/// Offset of the interrupts for AC3 ++#define IPC_IRQ_A2E_AC3_OFT (IPC_IRQ_A2E_AC2_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC3 ++#define IPC_IRQ_A2E_AC3_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC3_OFT) ++/// Offset of the interrupts for BCN ++#define IPC_IRQ_A2E_BCN_OFT (IPC_IRQ_A2E_AC3_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for BCN ++#define IPC_IRQ_A2E_BCN_MSK CO_BIT(IPC_IRQ_A2E_BCN_OFT) ++ ++#define IPC_IRQ_A2E_AC_TXDESC (IPC_IRQ_A2E_AC0_MSK | IPC_IRQ_A2E_AC1_MSK | \ ++ IPC_IRQ_A2E_AC2_MSK | IPC_IRQ_A2E_AC3_MSK) ++ ++/// Interrupts bits used for the TX descriptors of the BCN queue ++#if NX_TXQ_CNT < 5 ++#define IPC_IRQ_A2E_BCN_TXDESC 0 ++#else ++#define IPC_IRQ_A2E_BCN_TXDESC (0x01 << IPC_IRQ_A2E_BCN_OFT) ++#endif ++ ++/// IPC TX descriptor interrupt mask ++#define IPC_IRQ_A2E_TXDESC (IPC_IRQ_A2E_AC_TXDESC | IPC_IRQ_A2E_BCN_TXDESC) ++#else ++/// IPC TX descriptor interrupt mask ++#define IPC_IRQ_A2E_TXDESC 0xFF00 ++#endif ++ ++#define IPC_IRQ_A2E_TXDESC_FIRSTBIT (8) ++#define IPC_IRQ_A2E_RXBUF_BACK CO_BIT(5) ++#define IPC_IRQ_A2E_RXDESC_BACK CO_BIT(4) ++ ++#define IPC_IRQ_A2E_MSG CO_BIT(1) ++#define IPC_IRQ_A2E_DBG CO_BIT(0) ++ ++#define IPC_IRQ_A2E_ALL (IPC_IRQ_A2E_TXDESC|IPC_IRQ_A2E_MSG|IPC_IRQ_A2E_DBG) ++ ++// IRQs from emb to app ++#define IPC_IRQ_E2A_TXCFM_POS 7 ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++#ifdef CONFIG_RWNX_OLD_IPC ++#error "MU-MIMO cannot be compiled for old IPC" ++#endif ++/// Interrupts bits used ++#if CONFIG_USER_MAX > 3 ++#define IPC_IRQ_E2A_USER_MSK 0xF ++#elif CONFIG_USER_MAX > 2 ++#define IPC_IRQ_E2A_USER_MSK 0x7 ++#else ++#define IPC_IRQ_E2A_USER_MSK 0x3 ++#endif ++ ++/// Offset of the interrupts for AC0 ++#define IPC_IRQ_E2A_AC0_OFT IPC_IRQ_E2A_TXCFM_POS ++/// Mask of the interrupts for AC0 ++#define IPC_IRQ_E2A_AC0_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC0_OFT) ++/// Offset of the interrupts for AC1 ++#define IPC_IRQ_E2A_AC1_OFT (IPC_IRQ_E2A_AC0_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC1 ++#define IPC_IRQ_E2A_AC1_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC1_OFT) ++/// Offset of the interrupts for AC2 ++#define IPC_IRQ_E2A_AC2_OFT (IPC_IRQ_E2A_AC1_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC2 ++#define IPC_IRQ_E2A_AC2_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC2_OFT) ++/// Offset of the interrupts for AC3 ++#define IPC_IRQ_E2A_AC3_OFT (IPC_IRQ_E2A_AC2_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC3 ++#define IPC_IRQ_E2A_AC3_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC3_OFT) ++/// Offset of the interrupts for BCN ++#define IPC_IRQ_E2A_BCN_OFT (IPC_IRQ_E2A_AC3_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for BCN ++#define IPC_IRQ_E2A_BCN_MSK CO_BIT(IPC_IRQ_E2A_BCN_OFT) ++ ++#define IPC_IRQ_E2A_AC_TXCFM (IPC_IRQ_E2A_AC0_MSK | IPC_IRQ_E2A_AC1_MSK | \ ++ IPC_IRQ_E2A_AC2_MSK | IPC_IRQ_E2A_AC3_MSK) ++ ++/// Interrupts bits used for the TX descriptors of the BCN queue ++#if NX_TXQ_CNT < 5 ++#define IPC_IRQ_E2A_BCN_TXCFM 0 ++#else ++#define IPC_IRQ_E2A_BCN_TXCFM (0x01 << IPC_IRQ_E2A_BCN_OFT) ++#endif ++ ++/// IPC TX descriptor interrupt mask ++#define IPC_IRQ_E2A_TXCFM (IPC_IRQ_E2A_AC_TXCFM | IPC_IRQ_E2A_BCN_TXCFM) ++ ++#else ++ ++#define IPC_IRQ_E2A_TXCFM (((1 << NX_TXQ_CNT) - 1) << IPC_IRQ_E2A_TXCFM_POS) ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++#define IPC_IRQ_E2A_UNSUP_RX_VEC CO_BIT(7) ++#define IPC_IRQ_E2A_RADAR CO_BIT(6) ++#define IPC_IRQ_E2A_TBTT_SEC CO_BIT(5) ++#define IPC_IRQ_E2A_TBTT_PRIM CO_BIT(4) ++#define IPC_IRQ_E2A_RXDESC CO_BIT(3) ++#define IPC_IRQ_E2A_MSG_ACK CO_BIT(2) ++#define IPC_IRQ_E2A_MSG CO_BIT(1) ++#define IPC_IRQ_E2A_DBG CO_BIT(0) ++ ++#define IPC_IRQ_E2A_ALL (IPC_IRQ_E2A_TXCFM \ ++ | IPC_IRQ_E2A_RXDESC \ ++ | IPC_IRQ_E2A_MSG_ACK \ ++ | IPC_IRQ_E2A_MSG \ ++ | IPC_IRQ_E2A_DBG \ ++ | IPC_IRQ_E2A_TBTT_PRIM \ ++ | IPC_IRQ_E2A_TBTT_SEC \ ++ | IPC_IRQ_E2A_RADAR \ ++ | IPC_IRQ_E2A_UNSUP_RX_VEC) ++ ++// FLAGS for RX desc ++#define IPC_RX_FORWARD CO_BIT(1) ++#define IPC_RX_INTRABSS CO_BIT(0) ++ ++ ++// IPC message TYPE ++enum { ++ IPC_MSG_NONE = 0, ++ IPC_MSG_WRAP, ++ IPC_MSG_KMSG, ++ ++ IPC_DBG_STRING, ++ ++}; ++ ++#endif // _IPC_SHARED_H_ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h +new file mode 100644 +index 000000000000..2753d4d23253 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h +@@ -0,0 +1,564 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file lmac_mac_types.h ++ * ++ * @brief MAC related definitions. ++ * ++ * Adapted from mac_types.h to used lmac_types.h instead of standard types ++ * eg: perl -pi -e '$_ =~ s/uint(\d{1,2})_t/u$1_l/g; \ ++ * $_ =~ s/int(\d{1,2})_t/s$1_l/g; \ ++ * $_ =~ s/CO_BIT/BIT/g;' lmac_mac.h ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef LMAC_MAC_H_ ++#define LMAC_MAC_H_ ++ ++#include "lmac_types.h" ++ ++/// Interface types ++enum mac_vif_type { ++ /// ESS STA interface ++ VIF_STA, ++ /// IBSS STA interface ++ VIF_IBSS, ++ /// AP interface ++ VIF_AP, ++ /// Mesh Point interface ++ VIF_MESH_POINT, ++ /// Monitor interface ++ VIF_MONITOR, ++ /// Unknown type ++ VIF_UNKNOWN ++}; ++ ++/// MAC address length in bytes. ++#define MAC_ADDR_LEN 6 ++ ++/// MAC address structure. ++struct mac_addr { ++ /// Array of 16-bit words that make up the MAC address. ++ u16_l array[MAC_ADDR_LEN/2]; ++}; ++ ++/// SSID maximum length. ++#define MAC_SSID_LEN 32 ++ ++/// SSID. ++struct mac_ssid { ++ /// Actual length of the SSID. ++ u8_l length; ++ /// Array containing the SSID name. ++ u8_l array[MAC_SSID_LEN]; ++}; ++ ++/// BSS type ++enum mac_bss_type { ++ INFRASTRUCTURE_MODE = 1, ++ INDEPENDENT_BSS_MODE, ++ ANY_BSS_MODE ++}; ++ ++/// Channel Band ++enum mac_chan_band { ++ /// 2.4GHz Band ++ PHY_BAND_2G4, ++ /// 5GHz band ++ PHY_BAND_5G, ++ /// Number of bands ++ PHY_BAND_MAX, ++}; ++ ++/// Operating Channel Bandwidth ++enum mac_chan_bandwidth { ++ /// 20MHz BW ++ PHY_CHNL_BW_20, ++ /// 40MHz BW ++ PHY_CHNL_BW_40, ++ /// 80MHz BW ++ PHY_CHNL_BW_80, ++ /// 160MHz BW ++ PHY_CHNL_BW_160, ++ /// 80+80MHz BW ++ PHY_CHNL_BW_80P80, ++ /// Reserved BW ++ PHY_CHNL_BW_OTHER, ++}; ++ ++/// max number of channels in the 2.4 GHZ band ++#define MAC_DOMAINCHANNEL_24G_MAX 14 ++ ++/// max number of channels in the 5 GHZ band ++#define MAC_DOMAINCHANNEL_5G_MAX 28 ++ ++/// Channel Flag ++enum mac_chan_flags { ++ /// Cannot initiate radiation on this channel ++ CHAN_NO_IR = BIT(0), ++ /// Channel is not allowed ++ CHAN_DISABLED = BIT(1), ++ /// Radar detection required on this channel ++ CHAN_RADAR = BIT(2), ++}; ++ ++/// Primary Channel definition ++struct mac_chan_def { ++ /// Frequency of the channel (in MHz) ++ u16_l freq; ++ /// RF band (@ref mac_chan_band) ++ u8_l band; ++ /// Additional information (@ref mac_chan_flags) ++ u8_l flags; ++ /// Max transmit power allowed on this channel (dBm) ++ s8_l tx_power; ++}; ++ ++/// Operating Channel ++struct mac_chan_op { ++ /// Band (@ref mac_chan_band) ++ u8_l band; ++ /// Channel type (@ref mac_chan_bandwidth) ++ u8_l type; ++ /// Frequency for Primary 20MHz channel (in MHz) ++ u16_l prim20_freq; ++ /// Frequency center of the contiguous channel or center of Primary 80+80 (in MHz) ++ u16_l center1_freq; ++ /// Frequency center of the non-contiguous secondary 80+80 (in MHz) ++ u16_l center2_freq; ++ /// Max transmit power allowed on this channel (dBm) ++ s8_l tx_power; ++ /// Additional information (@ref mac_chan_flags) ++ u8_l flags; ++}; ++ ++/// Cipher suites (order is important as it is used by MACHW) ++enum mac_cipher_suite { ++ /// 00-0F-AC 1 ++ MAC_CIPHER_WEP40 = 0, ++ /// 00-0F-AC 2 ++ MAC_CIPHER_TKIP = 1, ++ /// 00-0F-AC 4 ++ MAC_CIPHER_CCMP = 2, ++ /// 00-0F-AC 5 ++ MAC_CIPHER_WEP104 = 3, ++ /// 00-14-72 1 ++ MAC_CIPHER_WPI_SMS4 = 4, ++ /// 00-0F-AC 6 (aka AES_CMAC) ++ MAC_CIPHER_BIP_CMAC_128 = 5, ++ ++ // following cipher are not supported by MACHW ++ /// 00-0F-AC 08 ++ MAC_CIPHER_GCMP_128, ++ /// 00-0F-AC 09 ++ MAC_CIPHER_GCMP_256, ++ /// 00-0F-AC 10 ++ MAC_CIPHER_CCMP_256, ++ /// 00-0F-AC 11 ++ MAC_CIPHER_BIP_GMAC_128, ++ /// 00-0F-AC 12 ++ MAC_CIPHER_BIP_GMAC_256, ++ /// 00-0F-AC 13 ++ MAC_CIPHER_BIP_CMAC_256, ++ ++ MAC_CIPHER_INVALID = 0xFF ++}; ++ ++/// Authentication and Key Management suite ++enum mac_akm_suite { ++ /// No security ++ MAC_AKM_NONE, ++ /// Pre RSN (WEP or WPA) ++ MAC_AKM_PRE_RSN, ++ /// 00-0F-AC 1 ++ MAC_AKM_8021X, ++ /// 00-0F-AC 2 ++ MAC_AKM_PSK, ++ /// 00-0F-AC 3 ++ MAC_AKM_FT_8021X, ++ /// 00-0F-AC 4 ++ MAC_AKM_FT_PSK, ++ /// 00-0F-AC 5 ++ MAC_AKM_8021X_SHA256, ++ /// 00-0F-AC 6 ++ MAC_AKM_PSK_SHA256, ++ /// 00-0F-AC 7 ++ MAC_AKM_TDLS, ++ /// 00-0F-AC 8 ++ MAC_AKM_SAE, ++ /// 00-0F-AC 9 ++ MAC_AKM_FT_OVER_SAE, ++ /// 00-0F-AC 11 ++ MAC_AKM_8021X_SUITE_B, ++ /// 00-0F-AC 12 ++ MAC_AKM_8021X_SUITE_B_192, ++ /// 00-0F-AC 14 ++ MAC_AKM_FILS_SHA256, ++ /// 00-0F-AC 15 ++ MAC_AKM_FILS_SHA384, ++ /// 00-0F-AC 16 ++ MAC_AKM_FT_FILS_SHA256, ++ /// 00-0F-AC 17 ++ MAC_AKM_FT_FILS_SHA384, ++ /// 00-0F-AC 18 ++ MAC_AKM_OWE, ++ ++ /// 00-14-72 1 ++ MAC_AKM_WAPI_CERT, ++ /// 00-14-72 2 ++ MAC_AKM_WAPI_PSK, ++}; ++ ++/// Scan result element, parsed from beacon or probe response frames. ++struct mac_scan_result { ++ /// Scan result is valid ++ bool valid_flag; ++ /// Network BSSID. ++ struct mac_addr bssid; ++ /// Network name. ++ struct mac_ssid ssid; ++ /// Network type (@ref mac_bss_type). ++ u16_l bsstype; ++ /// Network channel. ++ struct mac_chan_def *chan; ++ /// Network beacon period (in TU). ++ u16_l beacon_period; ++ /// Capability information ++ u16_l cap_info; ++ /// Supported AKM (bit-field of @ref mac_akm_suite) ++ u32_l akm; ++ /// Group cipher (bit-field of @ref mac_cipher_suite) ++ u16_l group_cipher; ++ /// Group cipher (bit-field of @ref mac_cipher_suite) ++ u16_l pairwise_cipher; ++ /// RSSI of the scanned BSS (in dBm) ++ s8_l rssi; ++}; ++ ++/// Legacy rate 802.11 definitions ++enum mac_legacy_rates { ++ /// DSSS/CCK 1Mbps ++ MAC_RATE_1MBPS = 2, ++ /// DSSS/CCK 2Mbps ++ MAC_RATE_2MBPS = 4, ++ /// DSSS/CCK 5.5Mbps ++ MAC_RATE_5_5MBPS = 11, ++ /// OFDM 6Mbps ++ MAC_RATE_6MBPS = 12, ++ /// OFDM 9Mbps ++ MAC_RATE_9MBPS = 18, ++ /// DSSS/CCK 11Mbps ++ MAC_RATE_11MBPS = 22, ++ /// OFDM 12Mbps ++ MAC_RATE_12MBPS = 24, ++ /// OFDM 18Mbps ++ MAC_RATE_18MBPS = 36, ++ /// OFDM 24Mbps ++ MAC_RATE_24MBPS = 48, ++ /// OFDM 36Mbps ++ MAC_RATE_36MBPS = 72, ++ /// OFDM 48Mbps ++ MAC_RATE_48MBPS = 96, ++ /// OFDM 54Mbps ++ MAC_RATE_54MBPS = 108 ++}; ++ ++/// BSS Membership Selector definitions ++enum mac_bss_membership { ++ /// HT PHY ++ MAC_BSS_MEMBERSHIP_HT_PHY = 127, ++ /// VHT PHY ++ MAC_BSS_MEMBERSHIP_VHT_PHY = 126, ++}; ++ ++/// MAC rateset maximum length ++#define MAC_RATESET_LEN 12 ++ ++/// Structure containing the legacy rateset of a station ++struct mac_rateset { ++ /// Number of legacy rates supported ++ u8_l length; ++ /// Array of legacy rates ++ u8_l array[MAC_RATESET_LEN]; ++}; ++ ++/// MAC Security Key maximum length ++#define MAC_SEC_KEY_LEN 32 // TKIP keys 256 bits (max length) with MIC keys ++ ++/// Structure defining a security key ++struct mac_sec_key { ++ /// Key material length ++ u8_l length; ++ /// Key material ++ u32_l array[MAC_SEC_KEY_LEN/4]; ++}; ++ ++/// Access Category enumeration ++enum mac_ac { ++ /// Background ++ AC_BK = 0, ++ /// Best-effort ++ AC_BE, ++ /// Video ++ AC_VI, ++ /// Voice ++ AC_VO, ++ /// Number of access categories ++ AC_MAX ++}; ++ ++/// Traffic ID enumeration ++enum mac_tid { ++ /// TID_0. Mapped to @ref AC_BE as per 802.11 standard. ++ TID_0, ++ /// TID_1. Mapped to @ref AC_BK as per 802.11 standard. ++ TID_1, ++ /// TID_2. Mapped to @ref AC_BK as per 802.11 standard. ++ TID_2, ++ /// TID_3. Mapped to @ref AC_BE as per 802.11 standard. ++ TID_3, ++ /// TID_4. Mapped to @ref AC_VI as per 802.11 standard. ++ TID_4, ++ /// TID_5. Mapped to @ref AC_VI as per 802.11 standard. ++ TID_5, ++ /// TID_6. Mapped to @ref AC_VO as per 802.11 standard. ++ TID_6, ++ /// TID_7. Mapped to @ref AC_VO as per 802.11 standard. ++ TID_7, ++ /// Non standard Management TID used internally ++ TID_MGT, ++ /// Number of TID supported ++ TID_MAX ++}; ++ ++/// MCS bitfield maximum size (in bytes) ++#define MAX_MCS_LEN 16 // 16 * 8 = 128 ++ ++/// MAC HT capability information element ++struct mac_htcapability { ++ /// HT capability information ++ u16_l ht_capa_info; ++ /// A-MPDU parameters ++ u8_l a_mpdu_param; ++ /// Supported MCS ++ u8_l mcs_rate[MAX_MCS_LEN]; ++ /// HT extended capability information ++ u16_l ht_extended_capa; ++ /// Beamforming capability information ++ u32_l tx_beamforming_capa; ++ /// Antenna selection capability information ++ u8_l asel_capa; ++}; ++ ++/// MAC VHT capability information element ++struct mac_vhtcapability { ++ /// VHT capability information ++ u32_l vht_capa_info; ++ /// RX MCS map ++ u16_l rx_mcs_map; ++ /// RX highest data rate ++ u16_l rx_highest; ++ /// TX MCS map ++ u16_l tx_mcs_map; ++ /// TX highest data rate ++ u16_l tx_highest; ++}; ++ ++/// Length (in bytes) of the MAC HE capability field ++#define MAC_HE_MAC_CAPA_LEN 6 ++/// Length (in bytes) of the PHY HE capability field ++#define MAC_HE_PHY_CAPA_LEN 11 ++/// Maximum length (in bytes) of the PPE threshold data ++#define MAC_HE_PPE_THRES_MAX_LEN 25 ++ ++/// Structure listing the per-NSS, per-BW supported MCS combinations ++struct mac_he_mcs_nss_supp { ++ /// per-NSS supported MCS in RX, for BW <= 80MHz ++ u16_l rx_mcs_80; ++ /// per-NSS supported MCS in TX, for BW <= 80MHz ++ u16_l tx_mcs_80; ++ /// per-NSS supported MCS in RX, for BW = 160MHz ++ u16_l rx_mcs_160; ++ /// per-NSS supported MCS in TX, for BW = 160MHz ++ u16_l tx_mcs_160; ++ /// per-NSS supported MCS in RX, for BW = 80+80MHz ++ u16_l rx_mcs_80p80; ++ /// per-NSS supported MCS in TX, for BW = 80+80MHz ++ u16_l tx_mcs_80p80; ++}; ++ ++/// MAC HE capability information element ++struct mac_hecapability { ++ /// MAC HE capabilities ++ u8_l mac_cap_info[MAC_HE_MAC_CAPA_LEN]; ++ /// PHY HE capabilities ++ u8_l phy_cap_info[MAC_HE_PHY_CAPA_LEN]; ++ /// Supported MCS combinations ++ struct mac_he_mcs_nss_supp mcs_supp; ++ /// PPE Thresholds data ++ u8_l ppe_thres[MAC_HE_PPE_THRES_MAX_LEN]; ++}; ++ ++/// Station flags ++enum mac_sta_flags { ++ /// Bit indicating that a STA has QoS (WMM) capability ++ STA_QOS_CAPA = BIT(0), ++ /// Bit indicating that a STA has HT capability ++ STA_HT_CAPA = BIT(1), ++ /// Bit indicating that a STA has VHT capability ++ STA_VHT_CAPA = BIT(2), ++ /// Bit indicating that a STA has MFP capability ++ STA_MFP_CAPA = BIT(3), ++ /// Bit indicating that the STA included the Operation Notification IE ++ STA_OPMOD_NOTIF = BIT(4), ++ /// Bit indicating that a STA has HE capability ++ STA_HE_CAPA = BIT(5), ++}; ++ ++/// Connection flags ++enum mac_connection_flags { ++ /// Flag indicating whether the control port is controlled by host or not ++ CONTROL_PORT_HOST = BIT(0), ++ /// Flag indicating whether the control port frame shall be sent unencrypted ++ CONTROL_PORT_NO_ENC = BIT(1), ++ /// Flag indicating whether HT and VHT shall be disabled or not ++ DISABLE_HT = BIT(2), ++ /// Flag indicating whether WPA or WPA2 authentication is in use ++ WPA_WPA2_IN_USE = BIT(3), ++ /// Flag indicating whether MFP is in use ++ MFP_IN_USE = BIT(4), ++ // Flag indicating Roam ++ REASSOCIATION = BIT(5), ++}; ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++#define IEEE80211_HE_MAC_CAP2_ALL_ACK 0x02 ++#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02 ++#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04 ++#define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD 0x20 ++#define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US 0x40 ++#define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS 0x80 ++#define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS 0x01 ++#define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US 0x02 ++#define IEEE80211_HE_PHY_CAP2_DOPPLER_RX 0x20 ++#define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ 0x08 ++#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM 0x18 ++#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 0x00 ++#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA 0x40 ++#define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE 0x01 ++#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 0x0c ++#define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK 0x40 ++#define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK 0x80 ++#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU 0x01 ++#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU 0x02 ++#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB 0x04 ++#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB 0x08 ++#define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT 0x80 ++#define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO 0x40 ++#define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI 0x04 ++#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G 0x02 ++#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB 0x10 ++#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB 0x20 ++ ++#define IEEE80211_HE_PPE_THRES_MAX_LEN 25 ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) ++#define WLAN_EID_EXTENSION 255 ++/* Element ID Extensions for Element ID 255 */ ++ ++enum ieee80211_eid_ext { ++ WLAN_EID_EXT_ASSOC_DELAY_INFO = 1, ++ WLAN_EID_EXT_FILS_REQ_PARAMS = 2, ++ WLAN_EID_EXT_FILS_KEY_CONFIRM = 3, ++ WLAN_EID_EXT_FILS_SESSION = 4, ++ WLAN_EID_EXT_FILS_HLP_CONTAINER = 5, ++ WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN = 6, ++ WLAN_EID_EXT_KEY_DELIVERY = 7, ++ WLAN_EID_EXT_FILS_WRAPPED_DATA = 8, ++ WLAN_EID_EXT_FILS_PUBLIC_KEY = 12, ++ WLAN_EID_EXT_FILS_NONCE = 13, ++ WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE = 14, ++ ++}; ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define WLAN_EID_EXT_HE_CAPABILITY 35 ++#define WLAN_EID_EXT_HE_OPERATION 36 ++#define WLAN_EID_EXT_UORA 37 ++#define WLAN_EID_EXT_HE_MU_EDCA 38 ++#define WLAN_EID_EXT_HE_SPR 39 ++#define WLAN_EID_EXT_NDP_FEEDBACK_REPORT_PARAMSET 41 ++#define WLAN_EID_EXT_BSS_COLOR_CHG_ANN 42 ++#define WLAN_EID_EXT_QUIET_TIME_PERIOD_SETUP 43 ++#define WLAN_EID_EXT_ESS_REPORT 45 ++#define WLAN_EID_EXT_OPS 46 ++#define WLAN_EID_EXT_HE_BSS_LOAD 47 ++#define WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME 52 ++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55 ++#define WLAN_EID_EXT_NON_INHERITANCE 56 ++#define WLAN_EID_EXT_KNOWN_BSSID 57 ++#define WLAN_EID_EXT_SHORT_SSID_LIST 58 ++#define WLAN_EID_EXT_HE_6GHZ_CAPA 59 ++#define WLAN_EID_EXT_UL_MU_POWER_CAPA 60 ++#define WLAN_EID_EXT_EHT_OPERATION 106 ++#define WLAN_EID_EXT_EHT_MULTI_LINK 107 ++#define WLAN_EID_EXT_EHT_CAPABILITY 108 ++#endif ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++#include ++#else ++struct ieee80211_he_cap_elem { ++ u8 mac_cap_info[6]; ++ u8 phy_cap_info[11]; ++} __packed; ++ ++struct ieee80211_he_mcs_nss_supp { ++ __le16 rx_mcs_80; ++ __le16 tx_mcs_80; ++ __le16 rx_mcs_160; ++ __le16 tx_mcs_160; ++ __le16 rx_mcs_80p80; ++ __le16 tx_mcs_80p80; ++} __packed; ++ ++struct ieee80211_sta_he_cap { ++ bool has_he; ++ struct ieee80211_he_cap_elem he_cap_elem; ++ struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; ++ u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; ++}; ++ ++struct ieee80211_sband_iftype_data { ++ u16 types_mask; ++ struct ieee80211_sta_he_cap he_cap; ++}; ++#endif ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++struct ieee80211_vht_mcs_info { ++ __le16 rx_mcs_map; ++ __le16 rx_highest; ++ __le16 tx_mcs_map; ++ __le16 tx_highest; ++} __packed; ++ ++struct ieee80211_vht_cap { ++ __le32 vht_cap_info; ++ struct ieee80211_vht_mcs_info supp_mcs; ++}; ++#define WLAN_EID_VHT_CAPABILITY 191 ++ ++struct ieee80211_sta_vht_cap { ++ bool vht_supported; ++ u32 cap; /* use IEEE80211_VHT_CAP_ */ ++ struct ieee80211_vht_mcs_info vht_mcs; ++}; ++#endif ++#endif // LMAC_MAC_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h +new file mode 100644 +index 000000000000..96f492bba754 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h +@@ -0,0 +1,3224 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file lmac_msg.h ++ * ++ * @brief Main definitions for message exchanges with LMAC ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef LMAC_MSG_H_ ++#define LMAC_MSG_H_ ++ ++/* ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++// for MAC related elements (mac_addr, mac_ssid...) ++#include "lmac_mac.h" ++ ++#define LMAC_MSG_MAX_LEN 1024 ++ ++/* ++ **************************************************************************************** ++ */ ++///////////////////////////////////////////////////////////////////////////////// ++// COMMUNICATION WITH LMAC LAYER ++///////////////////////////////////////////////////////////////////////////////// ++/* Task identifiers for communication between LMAC and DRIVER */ ++enum { ++ TASK_NONE = (u8_l) -1, ++ ++ // MAC Management task. ++ TASK_MM = 0, ++ // DEBUG task ++ TASK_DBG, ++ /// SCAN task ++ TASK_SCAN, ++ /// TDLS task ++ TASK_TDLS, ++ /// SCANU task ++ TASK_SCANU, ++ /// ME task ++ TASK_ME, ++ /// SM task ++ TASK_SM, ++ /// APM task ++ TASK_APM, ++ /// BAM task ++ TASK_BAM, ++ /// MESH task ++ TASK_MESH, ++ /// RXU task ++ TASK_RXU, ++ /// RM_task ++ TASK_RM, ++ /// TWT task ++ TASK_TWT, ++#if defined CONFIG_RWNX_FULLMAC || defined CONFIG_RWNX_FHOST ++ // This is used to define the last task that is running on the EMB processor ++ TASK_LAST_EMB = TASK_TWT, ++#else ++#error "Need to define SOFTMAC or FULLMAC" ++#endif ++ // nX API task ++ TASK_API, ++ TASK_MAX, ++}; ++ ++ ++/// For MAC HW States copied from "hal_machw.h" ++enum { ++ /// MAC HW IDLE State. ++ HW_IDLE = 0, ++ /// MAC HW RESERVED State. ++ HW_RESERVED, ++ /// MAC HW DOZE State. ++ HW_DOZE, ++ /// MAC HW ACTIVE State. ++ HW_ACTIVE ++}; ++ ++/// Power Save mode setting ++enum mm_ps_mode_state { ++ MM_PS_MODE_OFF, ++ MM_PS_MODE_ON, ++ MM_PS_MODE_ON_DYN, ++}; ++ ++/// Status/error codes used in the MAC software. ++enum { ++ CO_OK, ++ CO_FAIL, ++ CO_EMPTY, ++ CO_FULL, ++ CO_BAD_PARAM, ++ CO_NOT_FOUND, ++ CO_NO_MORE_ELT_AVAILABLE, ++ CO_NO_ELT_IN_USE, ++ CO_BUSY, ++ CO_OP_IN_PROGRESS, ++}; ++ ++/// Remain on channel operation codes ++enum mm_remain_on_channel_op { ++ MM_ROC_OP_START = 0, ++ MM_ROC_OP_CANCEL, ++}; ++ ++#define DRV_TASK_ID 100 ++ ++/// Message Identifier. The number of messages is limited to 0xFFFF. ++/// The message ID is divided in two parts: ++/// - bits[15..10] : task index (no more than 64 tasks supported). ++/// - bits[9..0] : message index (no more that 1024 messages per task). ++typedef u16 lmac_msg_id_t; ++ ++typedef u16 lmac_task_id_t; ++ ++/// Build the first message ID of a task. ++#define LMAC_FIRST_MSG(task) ((lmac_msg_id_t)((task) << 10)) ++ ++#define MSG_T(msg) ((lmac_task_id_t)((msg) >> 10)) ++#define MSG_I(msg) ((msg) & ((1<<10)-1)) ++ ++/// Message structure. ++struct lmac_msg { ++ lmac_msg_id_t id; ///< Message id. ++ lmac_task_id_t dest_id; ///< Destination kernel identifier. ++ lmac_task_id_t src_id; ///< Source kernel identifier. ++ u16 param_len; ///< Parameter embedded struct length. ++ u32 param[]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++/// List of messages related to the task. ++enum mm_msg_tag { ++ /// RESET Request. ++ MM_RESET_REQ = LMAC_FIRST_MSG(TASK_MM), ++ /// RESET Confirmation. ++ MM_RESET_CFM, ++ /// START Request. ++ MM_START_REQ, ++ /// START Confirmation. ++ MM_START_CFM, ++ /// Read Version Request. ++ MM_VERSION_REQ, ++ /// Read Version Confirmation. ++ MM_VERSION_CFM, ++ /// ADD INTERFACE Request. ++ MM_ADD_IF_REQ, ++ /// ADD INTERFACE Confirmation. ++ MM_ADD_IF_CFM, ++ /// REMOVE INTERFACE Request. ++ MM_REMOVE_IF_REQ, ++ /// REMOVE INTERFACE Confirmation. ++ MM_REMOVE_IF_CFM, ++ /// STA ADD Request. ++ MM_STA_ADD_REQ, ++ /// STA ADD Confirm. ++ MM_STA_ADD_CFM, ++ /// STA DEL Request. ++ MM_STA_DEL_REQ, ++ /// STA DEL Confirm. ++ MM_STA_DEL_CFM, ++ /// RX FILTER CONFIGURATION Request. ++ MM_SET_FILTER_REQ, ++ /// RX FILTER CONFIGURATION Confirmation. ++ MM_SET_FILTER_CFM, ++ /// CHANNEL CONFIGURATION Request. ++ MM_SET_CHANNEL_REQ, ++ /// CHANNEL CONFIGURATION Confirmation. ++ MM_SET_CHANNEL_CFM, ++ /// DTIM PERIOD CONFIGURATION Request. ++ MM_SET_DTIM_REQ, ++ /// DTIM PERIOD CONFIGURATION Confirmation. ++ MM_SET_DTIM_CFM, ++ /// BEACON INTERVAL CONFIGURATION Request. ++ MM_SET_BEACON_INT_REQ, ++ /// BEACON INTERVAL CONFIGURATION Confirmation. ++ MM_SET_BEACON_INT_CFM, ++ /// BASIC RATES CONFIGURATION Request. ++ MM_SET_BASIC_RATES_REQ, ++ /// BASIC RATES CONFIGURATION Confirmation. ++ MM_SET_BASIC_RATES_CFM, ++ /// BSSID CONFIGURATION Request. ++ MM_SET_BSSID_REQ, ++ /// BSSID CONFIGURATION Confirmation. ++ MM_SET_BSSID_CFM, ++ /// EDCA PARAMETERS CONFIGURATION Request. ++ MM_SET_EDCA_REQ, ++ /// EDCA PARAMETERS CONFIGURATION Confirmation. ++ MM_SET_EDCA_CFM, ++ /// ABGN MODE CONFIGURATION Request. ++ MM_SET_MODE_REQ, ++ /// ABGN MODE CONFIGURATION Confirmation. ++ MM_SET_MODE_CFM, ++ /// Request setting the VIF active state (i.e associated or AP started) ++ MM_SET_VIF_STATE_REQ, ++ /// Confirmation of the @ref MM_SET_VIF_STATE_REQ message. ++ MM_SET_VIF_STATE_CFM, ++ /// SLOT TIME PARAMETERS CONFIGURATION Request. ++ MM_SET_SLOTTIME_REQ, ++ /// SLOT TIME PARAMETERS CONFIGURATION Confirmation. ++ MM_SET_SLOTTIME_CFM, ++ /// Power Mode Change Request. ++ MM_SET_IDLE_REQ, ++ /// Power Mode Change Confirm. ++ MM_SET_IDLE_CFM, ++ /// KEY ADD Request. ++ MM_KEY_ADD_REQ, ++ /// KEY ADD Confirm. ++ MM_KEY_ADD_CFM, ++ /// KEY DEL Request. ++ MM_KEY_DEL_REQ, ++ /// KEY DEL Confirm. ++ MM_KEY_DEL_CFM, ++ /// Block Ack agreement info addition ++ MM_BA_ADD_REQ, ++ /// Block Ack agreement info addition confirmation ++ MM_BA_ADD_CFM, ++ /// Block Ack agreement info deletion ++ MM_BA_DEL_REQ, ++ /// Block Ack agreement info deletion confirmation ++ MM_BA_DEL_CFM, ++ /// Indication of the primary TBTT to the upper MAC. Upon the reception of this ++ // message the upper MAC has to push the beacon(s) to the beacon transmission queue. ++ MM_PRIMARY_TBTT_IND, ++ /// Indication of the secondary TBTT to the upper MAC. Upon the reception of this ++ // message the upper MAC has to push the beacon(s) to the beacon transmission queue. ++ MM_SECONDARY_TBTT_IND, ++ /// Request for changing the TX power ++ MM_SET_POWER_REQ, ++ /// Confirmation of the TX power change ++ MM_SET_POWER_CFM, ++ /// Request to the LMAC to trigger the embedded logic analyzer and forward the debug ++ /// dump. ++ MM_DBG_TRIGGER_REQ, ++ /// Set Power Save mode ++ MM_SET_PS_MODE_REQ, ++ /// Set Power Save mode confirmation ++ MM_SET_PS_MODE_CFM, ++ /// Request to add a channel context ++ MM_CHAN_CTXT_ADD_REQ, ++ /// Confirmation of the channel context addition ++ MM_CHAN_CTXT_ADD_CFM, ++ /// Request to delete a channel context ++ MM_CHAN_CTXT_DEL_REQ, ++ /// Confirmation of the channel context deletion ++ MM_CHAN_CTXT_DEL_CFM, ++ /// Request to link a channel context to a VIF ++ MM_CHAN_CTXT_LINK_REQ, ++ /// Confirmation of the channel context link ++ MM_CHAN_CTXT_LINK_CFM, ++ /// Request to unlink a channel context from a VIF ++ MM_CHAN_CTXT_UNLINK_REQ, ++ /// Confirmation of the channel context unlink ++ MM_CHAN_CTXT_UNLINK_CFM, ++ /// Request to update a channel context ++ MM_CHAN_CTXT_UPDATE_REQ, ++ /// Confirmation of the channel context update ++ MM_CHAN_CTXT_UPDATE_CFM, ++ /// Request to schedule a channel context ++ MM_CHAN_CTXT_SCHED_REQ, ++ /// Confirmation of the channel context scheduling ++ MM_CHAN_CTXT_SCHED_CFM, ++ /// Request to change the beacon template in LMAC ++ MM_BCN_CHANGE_REQ, ++ /// Confirmation of the beacon change ++ MM_BCN_CHANGE_CFM, ++ /// Request to update the TIM in the beacon (i.e to indicate traffic bufferized at AP) ++ MM_TIM_UPDATE_REQ, ++ /// Confirmation of the TIM update ++ MM_TIM_UPDATE_CFM, ++ /// Connection loss indication ++ MM_CONNECTION_LOSS_IND, ++ /// Channel context switch indication to the upper layers ++ MM_CHANNEL_SWITCH_IND, ++ /// Channel context pre-switch indication to the upper layers ++ MM_CHANNEL_PRE_SWITCH_IND, ++ /// Request to remain on channel or cancel remain on channel ++ MM_REMAIN_ON_CHANNEL_REQ, ++ /// Confirmation of the (cancel) remain on channel request ++ MM_REMAIN_ON_CHANNEL_CFM, ++ /// Remain on channel expired indication ++ MM_REMAIN_ON_CHANNEL_EXP_IND, ++ /// Indication of a PS state change of a peer device ++ MM_PS_CHANGE_IND, ++ /// Indication that some buffered traffic should be sent to the peer device ++ MM_TRAFFIC_REQ_IND, ++ /// Request to modify the STA Power-save mode options ++ MM_SET_PS_OPTIONS_REQ, ++ /// Confirmation of the PS options setting ++ MM_SET_PS_OPTIONS_CFM, ++ /// Indication of PS state change for a P2P VIF ++ MM_P2P_VIF_PS_CHANGE_IND, ++ /// Indication that CSA counter has been updated ++ MM_CSA_COUNTER_IND, ++ /// Channel occupation report indication ++ MM_CHANNEL_SURVEY_IND, ++ /// Message containing Beamformer Information ++ MM_BFMER_ENABLE_REQ, ++ /// Request to Start/Stop/Update NOA - GO Only ++ MM_SET_P2P_NOA_REQ, ++ /// Request to Start/Stop/Update Opportunistic PS - GO Only ++ MM_SET_P2P_OPPPS_REQ, ++ /// Start/Stop/Update NOA Confirmation ++ MM_SET_P2P_NOA_CFM, ++ /// Start/Stop/Update Opportunistic PS Confirmation ++ MM_SET_P2P_OPPPS_CFM, ++ /// P2P NoA Update Indication - GO Only ++ MM_P2P_NOA_UPD_IND, ++ /// Request to set RSSI threshold and RSSI hysteresis ++ MM_CFG_RSSI_REQ, ++ /// Indication that RSSI level is below or above the threshold ++ MM_RSSI_STATUS_IND, ++ /// Indication that CSA is done ++ MM_CSA_FINISH_IND, ++ /// Indication that CSA is in prorgess (resp. done) and traffic must be stopped (resp. restarted) ++ MM_CSA_TRAFFIC_IND, ++ /// Request to update the group information of a station ++ MM_MU_GROUP_UPDATE_REQ, ++ /// Confirmation of the @ref MM_MU_GROUP_UPDATE_REQ message ++ MM_MU_GROUP_UPDATE_CFM, ++ /// Request to initialize the antenna diversity algorithm ++ MM_ANT_DIV_INIT_REQ, ++ /// Request to stop the antenna diversity algorithm ++ MM_ANT_DIV_STOP_REQ, ++ /// Request to update the antenna switch status ++ MM_ANT_DIV_UPDATE_REQ, ++ /// Request to switch the antenna connected to path_0 ++ MM_SWITCH_ANTENNA_REQ, ++ /// Indication that a packet loss has occurred ++ MM_PKTLOSS_IND, ++ ++ MM_SET_ARPOFFLOAD_REQ, ++ MM_SET_ARPOFFLOAD_CFM, ++ MM_SET_AGG_DISABLE_REQ, ++ MM_SET_AGG_DISABLE_CFM, ++ MM_SET_COEX_REQ, ++ MM_SET_COEX_CFM, ++ MM_SET_RF_CONFIG_REQ, ++ MM_SET_RF_CONFIG_CFM, ++ MM_SET_RF_CALIB_REQ, ++ MM_SET_RF_CALIB_CFM, ++ ++ /// MU EDCA PARAMETERS Configuration Request. ++ MM_SET_MU_EDCA_REQ, ++ /// MU EDCA PARAMETERS Configuration Confirmation. ++ MM_SET_MU_EDCA_CFM, ++ /// UORA PARAMETERS Configuration Request. ++ MM_SET_UORA_REQ, ++ /// UORA PARAMETERS Configuration Confirmation. ++ MM_SET_UORA_CFM, ++ /// TXOP RTS THRESHOLD Configuration Request. ++ MM_SET_TXOP_RTS_THRES_REQ, ++ /// TXOP RTS THRESHOLD Configuration Confirmation. ++ MM_SET_TXOP_RTS_THRES_CFM, ++ /// HE BSS Color Configuration Request. ++ MM_SET_BSS_COLOR_REQ, ++ /// HE BSS Color Configuration Confirmation. ++ MM_SET_BSS_COLOR_CFM, ++ ++ MM_GET_MAC_ADDR_REQ, ++ MM_GET_MAC_ADDR_CFM, ++ ++ MM_GET_STA_INFO_REQ, ++ MM_GET_STA_INFO_CFM, ++ ++ MM_SET_TXPWR_IDX_LVL_REQ, ++ MM_SET_TXPWR_IDX_LVL_CFM, ++ ++ MM_SET_TXPWR_OFST_REQ, ++ MM_SET_TXPWR_OFST_CFM, ++ ++ MM_SET_STACK_START_REQ, ++ MM_SET_STACK_START_CFM, ++ ++ MM_APM_STALOSS_IND, ++ ++ MM_SET_VENDOR_HWCONFIG_REQ, ++ MM_SET_VENDOR_HWCONFIG_CFM, ++ ++ MM_GET_FW_VERSION_REQ, ++ MM_GET_FW_VERSION_CFM, ++ ++ MM_SET_RESUME_RESTORE_REQ, ++ MM_SET_RESUME_RESTORE_CFM, ++ ++ MM_GET_WIFI_DISABLE_REQ, ++ MM_GET_WIFI_DISABLE_CFM, ++ ++ MM_CFG_RSSI_CFM, ++ ++ MM_SET_VENDOR_SWCONFIG_REQ, ++ MM_SET_VENDOR_SWCONFIG_CFM, ++ ++ MM_SET_TXPWR_LVL_ADJ_REQ, ++ MM_SET_TXPWR_LVL_ADJ_CFM, ++ ++ MM_RADAR_DETECT_IND, ++ ++ MM_SET_APF_PROG_REQ, ++ MM_SET_APF_PROG_CFM, ++ ++ MM_GET_APF_PROG_REQ, ++ MM_GET_APF_PROG_CFM, ++ ++ /// MAX number of messages ++ MM_MAX, ++}; ++ ++/// Interface types ++enum { ++ /// ESS STA interface ++ MM_STA, ++ /// IBSS STA interface ++ MM_IBSS, ++ /// AP interface ++ MM_AP, ++ // Mesh Point interface ++ MM_MESH_POINT, ++ // Monitor interface ++ MM_MONITOR, ++}; ++ ++///BA agreement types ++enum { ++ ///BlockAck agreement for TX ++ BA_AGMT_TX, ++ ///BlockAck agreement for RX ++ BA_AGMT_RX, ++}; ++ ++///BA agreement related status ++enum { ++ ///Correct BA agreement establishment ++ BA_AGMT_ESTABLISHED, ++ ///BA agreement already exists for STA+TID requested, cannot override it (should have been deleted first) ++ BA_AGMT_ALREADY_EXISTS, ++ ///Correct BA agreement deletion ++ BA_AGMT_DELETED, ++ ///BA agreement for the (STA, TID) doesn't exist so nothing to delete ++ BA_AGMT_DOESNT_EXIST, ++}; ++ ++/// Features supported by LMAC - Positions ++enum mm_features { ++ /// Beaconing ++ MM_FEAT_BCN_BIT = 0, ++/* ++ /// Autonomous Beacon Transmission ++ MM_FEAT_AUTOBCN_BIT, ++ /// Scan in LMAC ++ MM_FEAT_HWSCAN_BIT, ++ /// Connection Monitoring ++ MM_FEAT_CMON_BIT, ++ /// Multi Role ++ MM_FEAT_MROLE_BIT, ++*/ ++ /// Radar Detection ++ MM_FEAT_RADAR_BIT, ++ /// Power Save ++ MM_FEAT_PS_BIT, ++ /// UAPSD ++ MM_FEAT_UAPSD_BIT, ++ /// DPSM ++// MM_FEAT_DPSM_BIT, ++ /// A-MPDU ++ MM_FEAT_AMPDU_BIT, ++ /// A-MSDU ++ MM_FEAT_AMSDU_BIT, ++ /// Channel Context ++// MM_FEAT_CHNL_CTXT_BIT, ++ /// Packet reordering ++// MM_FEAT_REORD_BIT, ++ /// P2P ++ MM_FEAT_P2P_BIT, ++ /// P2P Go ++ MM_FEAT_P2P_GO_BIT, ++ /// UMAC Present ++ MM_FEAT_UMAC_BIT, ++ /// VHT support ++ MM_FEAT_VHT_BIT, ++ /// Beamformee ++ MM_FEAT_BFMEE_BIT, ++ /// Beamformer ++ MM_FEAT_BFMER_BIT, ++ /// WAPI ++ MM_FEAT_WAPI_BIT, ++ /// MFP ++ MM_FEAT_MFP_BIT, ++ /// Mu-MIMO RX support ++ MM_FEAT_MU_MIMO_RX_BIT, ++ /// Mu-MIMO TX support ++ MM_FEAT_MU_MIMO_TX_BIT, ++ /// Wireless Mesh Networking ++ MM_FEAT_MESH_BIT, ++ /// TDLS support ++ MM_FEAT_TDLS_BIT, ++ /// Antenna Diversity support ++ MM_FEAT_ANT_DIV_BIT, ++ /// UF support ++ MM_FEAT_UF_BIT, ++ /// A-MSDU maximum size (bit0) ++ MM_AMSDU_MAX_SIZE_BIT0, ++ /// A-MSDU maximum size (bit1) ++ MM_AMSDU_MAX_SIZE_BIT1, ++ /// MON_DATA support ++ MM_FEAT_MON_DATA_BIT, ++ /// HE (802.11ax) support ++ MM_FEAT_HE_BIT, ++ /// TWT support ++ MM_FEAT_TWT_BIT, ++}; ++ ++/// Maximum number of words in the configuration buffer ++#define PHY_CFG_BUF_SIZE 16 ++ ++/// Structure containing the parameters of the PHY configuration ++struct phy_cfg_tag { ++ /// Buffer containing the parameters specific for the PHY used ++ u32_l parameters[PHY_CFG_BUF_SIZE]; ++}; ++ ++/// Structure containing the parameters of the Trident PHY configuration ++struct phy_trd_cfg_tag { ++ /// MDM type(nxm)(upper nibble) and MDM2RF path mapping(lower nibble) ++ u8_l path_mapping; ++ /// TX DC offset compensation ++ u32_l tx_dc_off_comp; ++}; ++ ++/// Structure containing the parameters of the Karst PHY configuration ++struct phy_karst_cfg_tag { ++ /// TX IQ mismatch compensation in 2.4GHz ++ u32_l tx_iq_comp_2_4G[2]; ++ /// RX IQ mismatch compensation in 2.4GHz ++ u32_l rx_iq_comp_2_4G[2]; ++ /// TX IQ mismatch compensation in 5GHz ++ u32_l tx_iq_comp_5G[2]; ++ /// RX IQ mismatch compensation in 5GHz ++ u32_l rx_iq_comp_5G[2]; ++ /// RF path used by default (0 or 1) ++ u8_l path_used; ++}; ++ ++/// Structure containing the parameters of the @ref MM_START_REQ message ++struct mm_start_req { ++ /// PHY configuration ++ struct phy_cfg_tag phy_cfg; ++ /// UAPSD timeout ++ u32_l uapsd_timeout; ++ /// Local LP clock accuracy (in ppm) ++ u16_l lp_clk_accuracy; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_CHANNEL_REQ message ++struct mm_set_channel_req { ++ /// Channel information ++ struct mac_chan_op chan; ++ /// Index of the RF for which the channel has to be set (0: operating (primary), 1: secondary ++ /// RF (used for additional radar detection). This parameter is reserved if no secondary RF ++ /// is available in the system ++ u8_l index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_CHANNEL_CFM message ++struct mm_set_channel_cfm { ++ /// Radio index to be used in policy table ++ u8_l radio_idx; ++ /// TX power configured (in dBm) ++ s8_l power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_DTIM_REQ message ++struct mm_set_dtim_req { ++ /// DTIM period ++ u8_l dtim_period; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_POWER_REQ message ++struct mm_set_power_req { ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++ /// TX power (in dBm) ++ s8_l power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_POWER_CFM message ++struct mm_set_power_cfm { ++ /// Radio index to be used in policy table ++ u8_l radio_idx; ++ /// TX power configured (in dBm) ++ s8_l power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BEACON_INT_REQ message ++struct mm_set_beacon_int_req { ++ /// Beacon interval ++ u16_l beacon_int; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BASIC_RATES_REQ message ++struct mm_set_basic_rates_req { ++ /// Basic rate set (as expected by bssBasicRateSet field of Rates MAC HW register) ++ u32_l rates; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++ /// Band on which the interface will operate ++ u8_l band; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BSSID_REQ message ++struct mm_set_bssid_req { ++ /// BSSID to be configured in HW ++ struct mac_addr bssid; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_FILTER_REQ message ++struct mm_set_filter_req { ++ /// RX filter to be put into rxCntrlReg HW register ++ u32_l filter; ++}; ++ ++/// Structure containing the parameters of the @ref MM_ADD_IF_REQ message. ++struct mm_add_if_req { ++ /// Type of the interface (AP, STA, ADHOC, ...) ++ u8_l type; ++ /// MAC ADDR of the interface to start ++ struct mac_addr addr; ++ /// P2P Interface ++ bool_l p2p; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_EDCA_REQ message ++struct mm_set_edca_req { ++ /// EDCA parameters of the queue (as expected by edcaACxReg HW register) ++ u32_l ac_param; ++ /// Flag indicating if UAPSD can be used on this queue ++ bool_l uapsd; ++ /// HW queue for which the parameters are configured ++ u8_l hw_queue; ++ /// Index of the interface for which the parameters are configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_MU_EDCA_REQ message ++struct mm_set_mu_edca_req { ++ /// MU EDCA parameters of the different HE queues ++ u32_l param[AC_MAX]; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_UORA_REQ message ++struct mm_set_uora_req { ++ /// Minimum exponent of OFDMA Contention Window. ++ u8_l eocw_min; ++ /// Maximum exponent of OFDMA Contention Window. ++ u8_l eocw_max; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_TXOP_RTS_THRES_REQ message ++struct mm_set_txop_rts_thres_req { ++ /// TXOP RTS threshold ++ u16_l txop_dur_rts_thres; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BSS_COLOR_REQ message ++struct mm_set_bss_color_req { ++ /// HE BSS color, formatted as per BSS_COLOR MAC HW register ++ u32_l bss_color; ++}; ++ ++struct mm_set_idle_req { ++ u8_l hw_idle; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_SLOTTIME_REQ message ++struct mm_set_slottime_req { ++ /// Slot time expressed in us ++ u8_l slottime; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_MODE_REQ message ++struct mm_set_mode_req { ++ /// abgnMode field of macCntrl1Reg register ++ u8_l abgnmode; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_VIF_STATE_REQ message ++struct mm_set_vif_state_req { ++ /// Association Id received from the AP (valid only if the VIF is of STA type) ++ u16_l aid; ++ /// Flag indicating if the VIF is active or not ++ bool_l active; ++ /// Interface index ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_ADD_IF_CFM message. ++struct mm_add_if_cfm { ++ /// Status of operation (different from 0 if unsuccessful) ++ u8_l status; ++ /// Interface index assigned by the LMAC ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMOVE_IF_REQ message. ++struct mm_remove_if_req { ++ /// Interface index assigned by the LMAC ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_VERSION_CFM message. ++struct mm_version_cfm { ++ /// Version of the LMAC FW ++ u32_l version_lmac; ++ /// Version1 of the MAC HW (as encoded in version1Reg MAC HW register) ++ u32_l version_machw_1; ++ /// Version2 of the MAC HW (as encoded in version2Reg MAC HW register) ++ u32_l version_machw_2; ++ /// Version1 of the PHY (depends on actual PHY) ++ u32_l version_phy_1; ++ /// Version2 of the PHY (depends on actual PHY) ++ u32_l version_phy_2; ++ /// Supported Features ++ u32_l features; ++ /// Maximum number of supported stations ++ u16_l max_sta_nb; ++ /// Maximum number of supported virtual interfaces ++ u8_l max_vif_nb; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_ADD_REQ message. ++struct mm_sta_add_req { ++ /// Bitfield showing some capabilities of the STA (@ref enum mac_sta_flags) ++ u32_l capa_flags; ++ /// Maximum A-MPDU size, in bytes, for HE frames ++ u32_l ampdu_size_max_he; ++ /// Maximum A-MPDU size, in bytes, for VHT frames ++ u32_l ampdu_size_max_vht; ++ /// PAID/GID ++ u32_l paid_gid; ++ /// Maximum A-MPDU size, in bytes, for HT frames ++ u16_l ampdu_size_max_ht; ++ /// MAC address of the station to be added ++ struct mac_addr mac_addr; ++ /// A-MPDU spacing, in us ++ u8_l ampdu_spacing_min; ++ /// Interface index ++ u8_l inst_nbr; ++ /// TDLS station ++ bool_l tdls_sta; ++ /// Indicate if the station is TDLS link initiator station ++ bool_l tdls_sta_initiator; ++ /// Indicate if the TDLS Channel Switch is allowed ++ bool_l tdls_chsw_allowed; ++ /// nonTransmitted BSSID index, set to the BSSID index in case the STA added is an AP ++ /// that is a nonTransmitted BSSID. Should be set to 0 otherwise ++ u8_l bssid_index; ++ /// Maximum BSSID indicator, valid if the STA added is an AP that is a nonTransmitted ++ /// BSSID ++ u8_l max_bssid_ind; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_ADD_CFM message. ++struct mm_sta_add_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++ /// Index assigned by the LMAC to the newly added station ++ u8_l sta_idx; ++ /// MAC HW index of the newly added station ++ u8_l hw_sta_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_DEL_REQ message. ++struct mm_sta_del_req { ++ /// Index of the station to be deleted ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_DEL_CFM message. ++struct mm_sta_del_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the SET_POWER_MODE REQ message. ++struct mm_setpowermode_req { ++ u8_l mode; ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the parameters of the SET_POWER_MODE CFM message. ++struct mm_setpowermode_cfm { ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_KEY_ADD REQ message. ++struct mm_key_add_req { ++ /// Key index (valid only for default keys) ++ u8_l key_idx; ++ /// STA index (valid only for pairwise or mesh group keys) ++ u8_l sta_idx; ++ /// Key material ++ struct mac_sec_key key; ++ /// Cipher suite (WEP64, WEP128, TKIP, CCMP) ++ u8_l cipher_suite; ++ /// Index of the interface for which the key is set (valid only for default keys or mesh group keys) ++ u8_l inst_nbr; ++ /// A-MSDU SPP parameter ++ u8_l spp; ++ /// Indicate if provided key is a pairwise key or not ++ bool_l pairwise; ++}; ++ ++/// Structure containing the parameters of the @ref MM_KEY_ADD_CFM message. ++struct mm_key_add_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++ /// HW index of the key just added ++ u8_l hw_key_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_KEY_DEL_REQ message. ++struct mm_key_del_req { ++ /// HW index of the key to be deleted ++ u8_l hw_key_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_ADD_REQ message. ++struct mm_ba_add_req { ++ ///Type of agreement (0: TX, 1: RX) ++ u8_l type; ++ ///Index of peer station with which the agreement is made ++ u8_l sta_idx; ++ ///TID for which the agreement is made with peer station ++ u8_l tid; ++ ///Buffer size - number of MPDUs that can be held in its buffer per TID ++ u8_l bufsz; ++ /// Start sequence number negotiated during BA setup - the one in first aggregated MPDU counts more ++ u16_l ssn; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_ADD_CFM message. ++struct mm_ba_add_cfm { ++ ///Index of peer station for which the agreement is being confirmed ++ u8_l sta_idx; ++ ///TID for which the agreement is being confirmed ++ u8_l tid; ++ /// Status of ba establishment ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_DEL_REQ message. ++struct mm_ba_del_req { ++ ///Type of agreement (0: TX, 1: RX) ++ u8_l type; ++ ///Index of peer station for which the agreement is being deleted ++ u8_l sta_idx; ++ ///TID for which the agreement is being deleted ++ u8_l tid; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_DEL_CFM message. ++struct mm_ba_del_cfm { ++ ///Index of peer station for which the agreement deletion is being confirmed ++ u8_l sta_idx; ++ ///TID for which the agreement deletion is being confirmed ++ u8_l tid; ++ /// Status of ba deletion ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_ADD_REQ message ++struct mm_chan_ctxt_add_req { ++ /// Operating channel ++ struct mac_chan_op chan; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_ADD_REQ message ++struct mm_chan_ctxt_add_cfm { ++ /// Status of the addition ++ u8_l status; ++ /// Index of the new channel context ++ u8_l index; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_DEL_REQ message ++struct mm_chan_ctxt_del_req { ++ /// Index of the new channel context to be deleted ++ u8_l index; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_LINK_REQ message ++struct mm_chan_ctxt_link_req { ++ /// VIF index ++ u8_l vif_index; ++ /// Channel context index ++ u8_l chan_index; ++ /// Indicate if this is a channel switch (unlink current ctx first if true) ++ u8_l chan_switch; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_UNLINK_REQ message ++struct mm_chan_ctxt_unlink_req { ++ /// VIF index ++ u8_l vif_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_UPDATE_REQ message ++struct mm_chan_ctxt_update_req { ++ /// Channel context index ++ u8_l chan_index; ++ /// New channel information ++ struct mac_chan_op chan; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_SCHED_REQ message ++struct mm_chan_ctxt_sched_req { ++ /// VIF index ++ u8_l vif_index; ++ /// Channel context index ++ u8_l chan_index; ++ /// Type of the scheduling request (0: normal scheduling, 1: derogatory ++ /// scheduling) ++ u8_l type; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHANNEL_SWITCH_IND message ++struct mm_channel_switch_ind { ++ /// Index of the channel context we will switch to ++ u8_l chan_index; ++ /// Indicate if the switch has been triggered by a Remain on channel request ++ bool_l roc; ++ /// VIF on which remain on channel operation has been started (if roc == 1) ++ u8_l vif_index; ++ /// Indicate if the switch has been triggered by a TDLS Remain on channel request ++ bool_l roc_tdls; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHANNEL_PRE_SWITCH_IND message ++struct mm_channel_pre_switch_ind { ++ /// Index of the channel context we will switch to ++ u8_l chan_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CONNECTION_LOSS_IND message. ++struct mm_connection_loss_ind { ++ /// VIF instance number ++ u8_l inst_nbr; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_DBG_TRIGGER_REQ message. ++struct mm_dbg_trigger_req { ++ /// Error trace to be reported by the LMAC ++ char error[64]; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_PS_MODE_REQ message. ++struct mm_set_ps_mode_req { ++ /// Power Save is activated or deactivated ++ u8_l new_state; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BCN_CHANGE_REQ message. ++#define BCN_MAX_CSA_CPT 2 ++struct mm_bcn_change_req { ++ /// Pointer, in host memory, to the new beacon template ++ u32_l bcn_ptr; ++ /// Length of the beacon template ++ u16_l bcn_len; ++ /// Offset of the TIM IE in the beacon ++ u16_l tim_oft; ++ /// Length of the TIM IE ++ u8_l tim_len; ++ /// Index of the VIF for which the beacon is updated ++ u8_l inst_nbr; ++ /// Offset of CSA (channel switch announcement) counters (0 means no counter) ++ u8_l csa_oft[BCN_MAX_CSA_CPT]; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_TIM_UPDATE_REQ message. ++struct mm_tim_update_req { ++ /// Association ID of the STA the bit of which has to be updated (0 for BC/MC traffic) ++ u16_l aid; ++ /// Flag indicating the availability of data packets for the given STA ++ u8_l tx_avail; ++ /// Index of the VIF for which the TIM is updated ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMAIN_ON_CHANNEL_REQ message. ++struct mm_remain_on_channel_req { ++ /// Operation Code ++ u8_l op_code; ++ /// VIF Index ++ u8_l vif_index; ++ /// Band (2.4GHz or 5GHz) ++ u8_l band; ++ /// Channel type: 20,40,80,160 or 80+80 MHz ++ u8_l type; ++ /// Frequency for Primary 20MHz channel (in MHz) ++ u16_l prim20_freq; ++ /// Frequency for Center of the contiguous channel or center of Primary 80+80 ++ u16_l center1_freq; ++ /// Frequency for Center of the non-contiguous secondary 80+80 ++ u16_l center2_freq; ++ /// Duration (in ms) ++ u32_l duration_ms; ++ /// TX power (in dBm) ++ s8_l tx_power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMAIN_ON_CHANNEL_CFM message ++struct mm_remain_on_channel_cfm { ++ /// Operation Code ++ u8_l op_code; ++ /// Status of the operation ++ u8_l status; ++ /// Channel Context index ++ u8_l chan_ctxt_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMAIN_ON_CHANNEL_EXP_IND message ++struct mm_remain_on_channel_exp_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// Channel Context index ++ u8_l chan_ctxt_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_UAPSD_TMR_REQ message. ++struct mm_set_uapsd_tmr_req { ++ /// action: Start or Stop the timer ++ u8_l action; ++ /// timeout value, in milliseconds ++ u32_l timeout; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_UAPSD_TMR_CFM message. ++struct mm_set_uapsd_tmr_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_PS_CHANGE_IND message ++struct mm_ps_change_ind { ++ /// Index of the peer device that is switching its PS state ++ u8_l sta_idx; ++ /// New PS state of the peer device (0: active, 1: sleeping) ++ u8_l ps_state; ++}; ++ ++/// Structure containing the parameters of the @ref MM_P2P_VIF_PS_CHANGE_IND message ++struct mm_p2p_vif_ps_change_ind { ++ /// Index of the P2P VIF that is switching its PS state ++ u8_l vif_index; ++ /// New PS state of the P2P VIF interface (0: active, 1: sleeping) ++ u8_l ps_state; ++}; ++ ++/// Structure containing the parameters of the @ref MM_TRAFFIC_REQ_IND message ++struct mm_traffic_req_ind { ++ /// Index of the peer device that needs traffic ++ u8_l sta_idx; ++ /// Number of packets that need to be sent (if 0, all buffered traffic shall be sent and ++ /// if set to @ref PS_SP_INTERRUPTED, it means that current service period has been interrupted) ++ u8_l pkt_cnt; ++ /// Flag indicating if the traffic request concerns U-APSD queues or not ++ bool_l uapsd; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_PS_OPTIONS_REQ message. ++struct mm_set_ps_options_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// Listen interval (0 if wake up shall be based on DTIM period) ++ u16_l listen_interval; ++ /// Flag indicating if we shall listen the BC/MC traffic or not ++ bool_l dont_listen_bc_mc; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CSA_COUNTER_IND message ++struct mm_csa_counter_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Updated CSA counter value ++ u8_l csa_count; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHANNEL_SURVEY_IND message ++struct mm_channel_survey_ind { ++ /// Frequency of the channel ++ u16_l freq; ++ /// Noise in dbm ++ s8_l noise_dbm; ++ /// Amount of time spent of the channel (in ms) ++ u32_l chan_time_ms; ++ /// Amount of time the primary channel was sensed busy ++ u32_l chan_time_busy_ms; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BFMER_ENABLE_REQ message. ++struct mm_bfmer_enable_req { ++ /** ++ * Address of the beamforming report space allocated in host memory ++ * (Valid only if vht_su_bfmee is true) ++ */ ++ u32_l host_bfr_addr; ++ /** ++ * Size of the beamforming report space allocated in host memory. This space should ++ * be twice the maximum size of the expected beamforming reports as the FW will ++ * divide it in two in order to be able to upload a new report while another one is ++ * used in transmission ++ */ ++ u16_l host_bfr_size; ++ /// AID ++ u16_l aid; ++ /// Station Index ++ u8_l sta_idx; ++ /// Maximum number of spatial streams the station can receive ++ u8_l rx_nss; ++ /** ++ * Indicate if peer STA is MU Beamformee (VHT) capable ++ * (Valid only if vht_su_bfmee is true) ++ */ ++ bool_l vht_mu_bfmee; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_NOA_REQ message. ++struct mm_set_p2p_noa_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// Allocated NOA Instance Number - Valid only if count = 0 ++ u8_l noa_inst_nb; ++ /// Count ++ u8_l count; ++ /// Indicate if NoA can be paused for traffic reason ++ bool_l dyn_noa; ++ /// Duration (in us) ++ u32_l duration_us; ++ /// Interval (in us) ++ u32_l interval_us; ++ /// Start Time offset from next TBTT (in us) ++ u32_l start_offset; ++}; ++ ++#ifdef AICWF_ARP_OFFLOAD ++struct mm_set_arpoffload_en_req { ++ u32_l ipaddr; ++ u8_l enable; ++ u8_l vif_idx; ++}; ++ ++struct mm_set_arpoffload_en_cfm { ++ u8_l status; ++}; ++#endif ++ ++struct mm_set_agg_disable_req { ++ u8_l disable; ++ u8_l staidx; ++ u8_l disable_rx; ++}; ++ ++struct mm_set_coex_req { ++ u8_l bt_on; ++ u8_l disable_coexnull; ++ u8_l enable_nullcts; ++ u8_l enable_periodic_timer; ++ u8_l coex_timeslot_set; ++ u32_l coex_timeslot[2]; ++}; ++#if 0 ++struct mm_set_rf_config_req { ++ u8_l def_band; ++ u8_l config_type; ++ u16_l offset; ++ u16_l len; ++ u16_l set; ++ u32_l rx_gain_24g[48][4]; ++ u32_l rx_gain_5g[32][4]; ++ u32_l tx_gain[32]; ++}; ++#endif ++struct mm_set_rf_config_req ++{ ++ u8_l table_sel; ++ u8_l table_ofst; ++ u8_l table_num; ++ u8_l deft_page; ++ u32_l data[64]; ++}; ++ ++struct mm_set_rf_calib_req { ++ u32_l cal_cfg_24g; ++ u32_l cal_cfg_5g; ++ u32_l param_alpha; ++ u32_l bt_calib_en; ++ u32_l bt_calib_param; ++ u8_l xtal_cap; ++ u8_l xtal_cap_fine; ++}; ++ ++struct mm_set_rf_calib_cfm { ++ u32_l rxgain_24g_addr; ++ u32_l rxgain_5g_addr; ++ u32_l txgain_24g_addr; ++ u32_l txgain_5g_addr; ++}; ++ ++struct mm_get_mac_addr_req { ++ u32_l get; ++}; ++ ++struct mm_get_mac_addr_cfm { ++ u8_l mac_addr[6]; ++}; ++ ++struct mm_get_sta_info_req { ++ u8_l sta_idx; ++}; ++ ++struct mm_get_sta_info_cfm { ++ u32_l rate_info; ++ u32_l txfailed; ++ u8 rssi; ++ u8 reserved[3]; ++ u32_l chan_busy_time; ++ u32_l ack_fail_stat; ++ u32_l ack_succ_stat; ++ u32_l chan_tx_busy_time; ++}; ++ ++typedef struct ++{ ++ u8_l enable; ++ u8_l dsss; ++ u8_l ofdmlowrate_2g4; ++ u8_l ofdm64qam_2g4; ++ u8_l ofdm256qam_2g4; ++ u8_l ofdm1024qam_2g4; ++ u8_l ofdmlowrate_5g; ++ u8_l ofdm64qam_5g; ++ u8_l ofdm256qam_5g; ++ u8_l ofdm1024qam_5g; ++} txpwr_lvl_conf_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_11b_11ag_2g4[12]; ++ s8_l pwrlvl_11n_11ac_2g4[10]; ++ s8_l pwrlvl_11ax_2g4[12]; ++} txpwr_lvl_conf_v2_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_11b_11ag_2g4[12]; ++ s8_l pwrlvl_11n_11ac_2g4[10]; ++ s8_l pwrlvl_11ax_2g4[12]; ++ s8_l pwrlvl_11a_5g[12]; ++ s8_l pwrlvl_11n_11ac_5g[10]; ++ s8_l pwrlvl_11ax_5g[12]; ++} txpwr_lvl_conf_v3_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_11b_11ag_2g4[12]; ++ s8_l pwrlvl_11n_11ac_2g4[10]; ++ s8_l pwrlvl_11ax_2g4[12]; ++ s8_l pwrlvl_11a_5g[8]; ++ s8_l pwrlvl_11n_11ac_5g[10]; ++ s8_l pwrlvl_11ax_5g[12]; ++ s8_l pwrlvl_11a_6g[8]; ++ s8_l pwrlvl_11n_11ac_6g[10]; ++ s8_l pwrlvl_11ax_6g[12]; ++} txpwr_lvl_conf_v4_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_adj_tbl_2g4[3]; ++ s8_l pwrlvl_adj_tbl_5g[6]; ++} txpwr_lvl_adj_conf_t; ++ ++typedef struct ++{ ++ u8_l loss_enable_2g4; ++ s8_l loss_value_2g4; ++ u8_l loss_enable_5g; ++ s8_l loss_value_5g; ++} txpwr_loss_conf_t; ++ ++struct mm_set_txpwr_lvl_req ++{ ++ union { ++ txpwr_lvl_conf_t txpwr_lvl; ++ txpwr_lvl_conf_v2_t txpwr_lvl_v2; ++ txpwr_lvl_conf_v3_t txpwr_lvl_v3; ++ txpwr_lvl_conf_v4_t txpwr_lvl_v4; ++ }; ++}; ++ ++struct mm_set_txpwr_lvl_adj_req ++{ ++ txpwr_lvl_adj_conf_t txpwr_lvl_adj; ++}; ++ ++typedef struct { ++ u8_l enable; ++ u8_l dsss; ++ u8_l ofdmlowrate_2g4; ++ u8_l ofdm64qam_2g4; ++ u8_l ofdm256qam_2g4; ++ u8_l ofdm1024qam_2g4; ++ u8_l ofdmlowrate_5g; ++ u8_l ofdm64qam_5g; ++ u8_l ofdm256qam_5g; ++ u8_l ofdm1024qam_5g; ++} txpwr_idx_conf_t; ++ ++struct mm_set_txpwr_idx_req { ++ txpwr_idx_conf_t txpwr_idx; ++}; ++ ++typedef struct { ++ u8_l enable; ++ s8_l chan_1_4; ++ s8_l chan_5_9; ++ s8_l chan_10_13; ++ s8_l chan_36_64; ++ s8_l chan_100_120; ++ s8_l chan_122_140; ++ s8_l chan_142_165; ++} txpwr_ofst_conf_t; ++ ++/* ++ * pwrofst2x_tbl_2g4[3][3]: ++ * +---------------+----------+----------+----------+ ++ * | RateTyp\ChGrp | CH_1_4 | CH_5_9 | CH_10_13 | ++ * +---------------+----------+----------+----------+ ++ * | DSSS | [0][0] | [0][1] | [0][2] | ++ * +---------------+----------+----------+----------+ ++ * | OFDM_HIGHRATE | [1][0] | [1][1] | [1][2] | ++ * +---------------+----------+----------+----------+ ++ * | OFDM_LOWRATE | [2][0] | [2][1] | [2][2] | ++ * +---------------+----------+----------+----------+ ++ * pwrofst2x_tbl_5g[3][6]: ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | RateTyp\ChGrp | CH_42(36~50) | CH_58(51~64) | CH_106(98~114) | CH_122(115~130)| CH_138(131~146)| CH_155(147~166)| ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | OFDM_LOWRATE | [0][0] | [0][1] | [0][2] | [0][3] | [0][4] | [0][5] | ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | OFDM_HIGHRATE | [1][0] | [1][1] | [1][2] | [1][3] | [1][4] | [1][5] | ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | OFDM_MIDRATE | [2][0] | [2][1] | [2][2] | [2][3] | [2][4] | [2][5] | ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ */ ++ ++typedef struct ++{ ++ int8_t enable; ++ int8_t pwrofst2x_tbl_2g4[3][3]; ++ int8_t pwrofst2x_tbl_5g[3][6]; ++} txpwr_ofst2x_conf_t; ++ ++/* ++ * pwrofst2x_v2_tbl_2g4_ant0/1[3][3]: ++ * +---------------+----------+---------------+--------------+ ++ * | ChGrp\RateTyp | DSSS | OFDM_HIGHRATE | OFDM_LOWRATE | ++ * +---------------+----------+---------------+--------------+ ++ * | CH_1_4 | [0][0] | [0][1] | Reserved | ++ * +---------------+----------+---------------+--------------+ ++ * | CH_5_9 | [1][0] | [1][1] | Reserved | ++ * +---------------+----------+---------------+--------------+ ++ * | CH_10_13 | [2][0] | [2][1] | Reserved | ++ * +---------------+----------+---------------+--------------+ ++ * pwrofst2x_v2_tbl_5g_ant0/1[6][3]: ++ * +-----------------+---------------+--------------+--------------+ ++ * | ChGrp\RateTyp | OFDM_HIGHRATE | OFDM_LOWRATE | OFDM_MIDRATE | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_42(36~50) | [0][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_58(51~64) | [1][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_106(98~114) | [2][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_122(115~130) | [3][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_138(131~146) | [4][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_155(147~166) | [5][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ */ ++ ++typedef struct ++{ ++ u8_l enable; ++ u8_l pwrofst_flags; ++ s8_l pwrofst2x_tbl_2g4_ant0[3][3]; ++ s8_l pwrofst2x_tbl_2g4_ant1[3][3]; ++ s8_l pwrofst2x_tbl_5g_ant0[6][3]; ++ s8_l pwrofst2x_tbl_5g_ant1[6][3]; ++ s8_l pwrofst2x_tbl_6g_ant0[15]; ++ s8_l pwrofst2x_tbl_6g_ant1[15]; ++} txpwr_ofst2x_conf_v2_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ u8_l xtal_cap; ++ u8_l xtal_cap_fine; ++} xtal_cap_conf_t; ++ ++ ++struct mm_set_txpwr_ofst_req { ++ union { ++ txpwr_ofst_conf_t txpwr_ofst; ++ txpwr_ofst2x_conf_t txpwr_ofst2x; ++ txpwr_ofst2x_conf_v2_t txpwr_ofst2x_v2; ++ }; ++}; ++ ++struct mm_set_stack_start_req { ++ u8_l is_stack_start; ++ u8_l efuse_valid; ++ u8_l set_vendor_info; ++ u8_l fwtrace_redir; ++}; ++ ++struct mm_set_stack_start_cfm { ++ u8_l is_5g_support; ++ u8_l vendor_info; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_OPPPS_REQ message. ++struct mm_set_p2p_oppps_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// CTWindow ++ u8_l ctwindow; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_NOA_CFM message. ++struct mm_set_p2p_noa_cfm { ++ /// Request status ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_OPPPS_CFM message. ++struct mm_set_p2p_oppps_cfm { ++ /// Request status ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_P2P_NOA_UPD_IND message. ++struct mm_p2p_noa_upd_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// NOA Instance Number ++ u8_l noa_inst_nb; ++ /// NoA Type ++ u8_l noa_type; ++ /// Count ++ u8_l count; ++ /// Duration (in us) ++ u32_l duration_us; ++ /// Interval (in us) ++ u32_l interval_us; ++ /// Start Time ++ u32_l start_time; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CFG_RSSI_REQ message ++struct mm_cfg_rssi_req { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// RSSI threshold ++ s8_l rssi_thold; ++ /// RSSI hysteresis ++ u8_l rssi_hyst; ++}; ++ ++/// Structure containing the parameters of the @ref MM_RSSI_STATUS_IND message ++struct mm_rssi_status_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Status of the RSSI ++ bool_l rssi_status; ++ /// Current RSSI ++ s8_l rssi; ++}; ++ ++/// Structure containing the parameters of the @ref MM_PKTLOSS_IND message ++struct mm_pktloss_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Address of the STA for which there is a packet loss ++ struct mac_addr mac_addr; ++ /// Number of packets lost ++ u32 num_packets; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CSA_FINISH_IND message ++struct mm_csa_finish_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Status of the operation ++ u8_l status; ++ /// New channel ctx index ++ u8_l chan_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CSA_TRAFFIC_IND message ++struct mm_csa_traffic_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Is tx traffic enable or disable ++ bool_l enable; ++}; ++ ++/// Structure containing the parameters of the @ref MM_MU_GROUP_UPDATE_REQ message. ++/// Size allocated for the structure depends of the number of group ++struct mm_mu_group_update_req { ++ /// Station index ++ u8_l sta_idx; ++ /// Number of groups the STA belongs to ++ u8_l group_cnt; ++ /// Group information ++ struct { ++ /// Group Id ++ u8_l group_id; ++ /// User position ++ u8_l user_pos; ++ } groups[0]; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For Scan messages ++/////////////////////////////////////////////////////////////////////////////// ++enum scan_msg_tag { ++ /// Scanning start Request. ++ SCAN_START_REQ = LMAC_FIRST_MSG(TASK_SCAN), ++ /// Scanning start Confirmation. ++ SCAN_START_CFM, ++ /// End of scanning indication. ++ SCAN_DONE_IND, ++ /// Cancel scan request ++ SCAN_CANCEL_REQ, ++ /// Cancel scan confirmation ++ SCAN_CANCEL_CFM, ++ ++ /// MAX number of messages ++ SCAN_MAX, ++}; ++ ++/// Maximum number of SSIDs in a scan request ++#define SCAN_SSID_MAX 3 ++ ++/// Maximum number of channels in a scan request ++#define SCAN_CHANNEL_MAX (MAC_DOMAINCHANNEL_24G_MAX + MAC_DOMAINCHANNEL_5G_MAX) ++ ++/// Maximum length of the ProbeReq IEs (SoftMAC mode) ++#define SCAN_MAX_IE_LEN 300 ++ ++/// Maximum number of PHY bands supported ++#define SCAN_BAND_MAX 2 ++ ++/// Structure containing the parameters of the @ref SCAN_START_REQ message ++struct scan_start_req { ++ /// List of channel to be scanned ++ struct mac_chan_def chan[SCAN_CHANNEL_MAX]; ++ /// List of SSIDs to be scanned ++ struct mac_ssid ssid[SCAN_SSID_MAX]; ++ /// BSSID to be scanned ++ struct mac_addr bssid; ++ /// Pointer (in host memory) to the additional IEs that need to be added to the ProbeReq ++ /// (following the SSID element) ++ u32_l add_ies; ++ /// Length of the additional IEs ++ u16_l add_ie_len; ++ /// Index of the VIF that is scanning ++ u8_l vif_idx; ++ /// Number of channels to scan ++ u8_l chan_cnt; ++ /// Number of SSIDs to scan for ++ u8_l ssid_cnt; ++ /// no CCK - For P2P frames not being sent at CCK rate in 2GHz band. ++ bool no_cck; ++ /// Scan duration, in us ++ u32_l duration; ++}; ++ ++/// Structure containing the parameters of the @ref SCAN_START_CFM message ++struct scan_start_cfm { ++ /// Status of the request ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref SCAN_CANCEL_REQ message ++struct scan_cancel_req { ++}; ++ ++/// Structure containing the parameters of the @ref SCAN_START_CFM message ++struct scan_cancel_cfm { ++ /// Status of the request ++ u8_l status; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For Scanu messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Messages that are logically related to the task. ++enum { ++ /// Scan request from host. ++ SCANU_START_REQ = LMAC_FIRST_MSG(TASK_SCANU), ++ /// Scanning start Confirmation. ++ SCANU_START_CFM, ++ /// Join request ++ SCANU_JOIN_REQ, ++ /// Join confirmation. ++ SCANU_JOIN_CFM, ++ /// Scan result indication. ++ SCANU_RESULT_IND, ++ /// Fast scan request from any other module. ++ SCANU_FAST_REQ, ++ /// Confirmation of fast scan request. ++ SCANU_FAST_CFM, ++ ++ SCANU_VENDOR_IE_REQ, ++ SCANU_VENDOR_IE_CFM, ++ SCANU_START_CFM_ADDTIONAL, ++ SCANU_CANCEL_REQ, ++ SCANU_CANCEL_CFM, ++ ++ /// MAX number of messages ++ SCANU_MAX, ++}; ++ ++/// Maximum length of the additional ProbeReq IEs (FullMAC mode) ++#define SCANU_MAX_IE_LEN 200 ++ ++/// Structure containing the parameters of the @ref SCANU_START_REQ message ++struct scanu_start_req { ++ /// List of channel to be scanned ++ struct mac_chan_def chan[SCAN_CHANNEL_MAX]; ++ /// List of SSIDs to be scanned ++ struct mac_ssid ssid[SCAN_SSID_MAX]; ++ /// BSSID to be scanned (or WILDCARD BSSID if no BSSID is searched in particular) ++ struct mac_addr bssid; ++ /// Address (in host memory) of the additional IEs that need to be added to the ProbeReq ++ /// (following the SSID element) ++ u32_l add_ies; ++ /// Length of the additional IEs ++ u16_l add_ie_len; ++ /// Index of the VIF that is scanning ++ u8_l vif_idx; ++ /// Number of channels to scan ++ u8_l chan_cnt; ++ /// Number of SSIDs to scan for ++ u8_l ssid_cnt; ++ /// no CCK - For P2P frames not being sent at CCK rate in 2GHz band. ++ bool no_cck; ++ /// Scan duration, in us ++ u32_l duration; ++}; ++ ++struct scanu_vendor_ie_req { ++ u16_l add_ie_len; ++ u8_l vif_idx; ++ u8_l ie[256]; ++}; ++ ++/// Structure containing the parameters of the @ref SCANU_START_CFM message ++struct scanu_start_cfm { ++ /// Index of the VIF that was scanning ++ u8_l vif_idx; ++ /// Status of the request ++ u8_l status; ++ /// Number of scan results available ++ u8_l result_cnt; ++}; ++ ++/// Parameters of the @SCANU_RESULT_IND message ++struct scanu_result_ind { ++ /// Length of the frame ++ u16_l length; ++ /// Frame control field of the frame. ++ u16_l framectrl; ++ /// Center frequency on which we received the packet ++ u16_l center_freq; ++ /// PHY band ++ u8_l band; ++ /// Index of the station that sent the frame. 0xFF if unknown. ++ u8_l sta_idx; ++ /// Index of the VIF that received the frame. 0xFF if unknown. ++ u8_l inst_nbr; ++ /// RSSI of the received frame. ++ s8_l rssi; ++ /// Frame payload. ++ u32_l payload[]; ++}; ++ ++/// Structure containing the parameters of the message. ++struct scanu_fast_req { ++ /// The SSID to scan in the channel. ++ struct mac_ssid ssid; ++ /// BSSID. ++ struct mac_addr bssid; ++ /// Probe delay. ++ u16_l probe_delay; ++ /// Minimum channel time. ++ u16_l minch_time; ++ /// Maximum channel time. ++ u16_l maxch_time; ++ /// The channel number to scan. ++ u16_l ch_nbr; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For ME messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Messages that are logically related to the task. ++enum { ++ /// Configuration request from host. ++ ME_CONFIG_REQ = LMAC_FIRST_MSG(TASK_ME), ++ /// Configuration confirmation. ++ ME_CONFIG_CFM, ++ /// Configuration request from host. ++ ME_CHAN_CONFIG_REQ, ++ /// Configuration confirmation. ++ ME_CHAN_CONFIG_CFM, ++ /// Set control port state for a station. ++ ME_SET_CONTROL_PORT_REQ, ++ /// Control port setting confirmation. ++ ME_SET_CONTROL_PORT_CFM, ++ /// TKIP MIC failure indication. ++ ME_TKIP_MIC_FAILURE_IND, ++ /// Add a station to the FW (AP mode) ++ ME_STA_ADD_REQ, ++ /// Confirmation of the STA addition ++ ME_STA_ADD_CFM, ++ /// Delete a station from the FW (AP mode) ++ ME_STA_DEL_REQ, ++ /// Confirmation of the STA deletion ++ ME_STA_DEL_CFM, ++ /// Indication of a TX RA/TID queue credit update ++ ME_TX_CREDITS_UPDATE_IND, ++ /// Request indicating to the FW that there is traffic buffered on host ++ ME_TRAFFIC_IND_REQ, ++ /// Confirmation that the @ref ME_TRAFFIC_IND_REQ has been executed ++ ME_TRAFFIC_IND_CFM, ++ /// Request of RC statistics to a station ++ ME_RC_STATS_REQ, ++ /// RC statistics confirmation ++ ME_RC_STATS_CFM, ++ /// RC fixed rate request ++ ME_RC_SET_RATE_REQ, ++ /// Configure monitor interface ++ ME_CONFIG_MONITOR_REQ, ++ /// Configure monitor interface response ++ ME_CONFIG_MONITOR_CFM, ++ /// Setting power Save mode request from host ++ ME_SET_PS_MODE_REQ, ++ /// Set power Save mode confirmation ++ ME_SET_PS_MODE_CFM, ++ /// Setting Low Power level request from host ++ ME_SET_LP_LEVEL_REQ, ++ /// Set Low Power level confirmation ++ ME_SET_LP_LEVEL_CFM, ++ /// MAX number of messages ++ ME_MAX, ++}; ++ ++/// Structure containing the parameters of the @ref ME_START_REQ message ++struct me_config_req { ++ /// HT Capabilities ++ struct mac_htcapability ht_cap; ++ /// VHT Capabilities ++ struct mac_vhtcapability vht_cap; ++ /// HE capabilities ++ struct mac_hecapability he_cap; ++ /// Lifetime of packets sent under a BlockAck agreement (expressed in TUs) ++ u16_l tx_lft; ++ /// Maximum supported BW ++ u8_l phy_bw_max; ++ /// Boolean indicating if HT is supported or not ++ bool_l ht_supp; ++ /// Boolean indicating if VHT is supported or not ++ bool_l vht_supp; ++ /// Boolean indicating if HE is supported or not ++ bool_l he_supp; ++ /// Boolean indicating if HE OFDMA UL is enabled or not ++ bool_l he_ul_on; ++ /// Boolean indicating if PS mode shall be enabled or not ++ bool_l ps_on; ++ /// Boolean indicating if Antenna Diversity shall be enabled or not ++ bool_l ant_div_on; ++ /// Boolean indicating if Dynamic PS mode shall be used or not ++ bool_l dpsm; ++}; ++ ++/// Structure containing the parameters of the @ref ME_CHAN_CONFIG_REQ message ++struct me_chan_config_req { ++ /// List of 2.4GHz supported channels ++ struct mac_chan_def chan2G4[MAC_DOMAINCHANNEL_24G_MAX]; ++ /// List of 5GHz supported channels ++ struct mac_chan_def chan5G[MAC_DOMAINCHANNEL_5G_MAX]; ++ /// Number of 2.4GHz channels in the list ++ u8_l chan2G4_cnt; ++ /// Number of 5GHz channels in the list ++ u8_l chan5G_cnt; ++}; ++ ++/// Structure containing the parameters of the @ref ME_SET_CONTROL_PORT_REQ message ++struct me_set_control_port_req { ++ /// Index of the station for which the control port is opened ++ u8_l sta_idx; ++ /// Control port state ++ bool_l control_port_open; ++}; ++ ++/// Structure containing the parameters of the @ref ME_TKIP_MIC_FAILURE_IND message ++struct me_tkip_mic_failure_ind { ++ /// Address of the sending STA ++ struct mac_addr addr; ++ /// TSC value ++ u64_l tsc; ++ /// Boolean indicating if the packet was a group or unicast one (true if group) ++ bool_l ga; ++ /// Key Id ++ u8_l keyid; ++ /// VIF index ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref ME_STA_ADD_REQ message ++struct me_sta_add_req { ++ /// MAC address of the station to be added ++ struct mac_addr mac_addr; ++ /// Supported legacy rates ++ struct mac_rateset rate_set; ++ /// HT Capabilities ++ struct mac_htcapability ht_cap; ++ /// VHT Capabilities ++ struct mac_vhtcapability vht_cap; ++ /// HE capabilities ++ struct mac_hecapability he_cap; ++ /// Flags giving additional information about the station (@ref mac_sta_flags) ++ u32_l flags; ++ /// Association ID of the station ++ u16_l aid; ++ /// Bit field indicating which queues have U-APSD enabled ++ u8_l uapsd_queues; ++ /// Maximum size, in frames, of a APSD service period ++ u8_l max_sp_len; ++ /// Operation mode information (valid if bit @ref STA_OPMOD_NOTIF is ++ /// set in the flags) ++ u8_l opmode; ++ /// Index of the VIF the station is attached to ++ u8_l vif_idx; ++ /// Whether the the station is TDLS station ++ bool_l tdls_sta; ++ /// Indicate if the station is TDLS link initiator station ++ bool_l tdls_sta_initiator; ++ /// Indicate if the TDLS Channel Switch is allowed ++ bool_l tdls_chsw_allowed; ++}; ++ ++/// Structure containing the parameters of the @ref ME_STA_ADD_CFM message ++struct me_sta_add_cfm { ++ /// Station index ++ u8_l sta_idx; ++ /// Status of the station addition ++ u8_l status; ++ /// PM state of the station ++ u8_l pm_state; ++}; ++ ++/// Structure containing the parameters of the @ref ME_STA_DEL_REQ message. ++struct me_sta_del_req { ++ /// Index of the station to be deleted ++ u8_l sta_idx; ++ /// Whether the the station is TDLS station ++ bool_l tdls_sta; ++}; ++ ++/// Structure containing the parameters of the @ref ME_TX_CREDITS_UPDATE_IND message. ++struct me_tx_credits_update_ind { ++ /// Index of the station for which the credits are updated ++ u8_l sta_idx; ++ /// TID for which the credits are updated ++ u8_l tid; ++ /// Offset to be applied on the credit count ++ s8_l credits; ++}; ++ ++/// Structure containing the parameters of the @ref ME_TRAFFIC_IND_REQ message. ++struct me_traffic_ind_req { ++ /// Index of the station for which UAPSD traffic is available on host ++ u8_l sta_idx; ++ /// Flag indicating the availability of UAPSD packets for the given STA ++ u8_l tx_avail; ++ /// Indicate if traffic is on uapsd-enabled queues ++ bool_l uapsd; ++}; ++ ++struct mm_apm_staloss_ind ++{ ++ u8_l sta_idx; ++ u8_l vif_idx; ++ u8_l mac_addr[6]; ++}; ++ ++#ifdef CONFIG_SDIO_BT ++struct mm_bt_recv_ind ++{ ++ u32_l data_len; ++ u8_l bt_data[1024]; ++}; ++#endif ++ ++enum vendor_hwconfig_tag{ ++ ACS_TXOP_REQ = 0, ++ CHANNEL_ACCESS_REQ, ++ MAC_TIMESCALE_REQ, ++ CCA_THRESHOLD_REQ, ++ BWMODE_REQ, ++ CHIP_TEMP_GET_REQ, ++ AP_PS_LEVEL_SET_REQ, ++ CUSTOMIZED_FREQ_REQ, ++ WAKEUP_INFO_REQ, ++ KEEPALIVE_PKT_REQ, ++}; ++ ++enum { ++ BWMODE20M = 0, ++ BWMODE10M, ++ BWMODE5M, ++}; ++ ++struct mm_set_acs_txop_req ++{ ++ u32_l hwconfig_id; ++ u16_l txop_bk; ++ u16_l txop_be; ++ u16_l txop_vi; ++ u16_l txop_vo; ++}; ++ ++struct mm_set_channel_access_req ++{ ++ u32_l hwconfig_id; ++ u32_l edca[4]; ++ u8_l vif_idx; ++ u8_l retry_cnt; ++ u8_l rts_en; ++ u8_l long_nav_en; ++ u8_l cfe_en; ++ u8_l rc_retry_cnt[3]; ++ s8_l ccademod_th; ++ u8_l remove_1m2m; ++}; ++ ++struct mm_set_mac_timescale_req ++{ ++ u32_l hwconfig_id; ++ u8_l sifsA_time; ++ u8_l sifsB_time; ++ u8_l slot_time; ++ u8_l rx_startdelay_ofdm; ++ u8_l rx_startdelay_long; ++ u8_l rx_startdelay_short; ++}; ++ ++struct mm_set_cca_threshold_req ++{ ++ u32_l hwconfig_id; ++ u8_l auto_cca_en; ++ s8_l cca20p_rise_th; ++ s8_l cca20s_rise_th; ++ s8_l cca20p_fall_th; ++ s8_l cca20s_fall_th; ++ ++}; ++ ++struct mm_set_bwmode_req ++{ ++ u32_l hwconfig_id; ++ u8_l bwmode; ++}; ++ ++struct mm_get_chip_temp_req ++{ ++ u32_l hwconfig_id; ++}; ++ ++struct mm_get_chip_temp_cfm ++{ ++ /// Temp degree val ++ s8_l degree; ++}; ++ ++struct mm_set_ap_ps_level_req ++{ ++ u32_l hwconfig_id; ++ u8 ap_ps_level; ++}; ++ ++struct mm_set_vendor_hwconfig_cfm ++{ ++ u32_l hwconfig_id; ++ union { ++ struct mm_get_chip_temp_cfm chip_temp_cfm; ++ }; ++}; ++ ++struct mm_set_customized_freq_req ++{ ++ u32_l hwconfig_id; ++ u16_l raw_freq[4]; ++ u16_l map_freq[4]; ++}; ++ ++struct mm_set_wakeup_info_req ++{ ++ u32_l hwconfig_id; ++ u16_l offset; ++ u8_l length; ++ u8_l mask_and_patten[]; ++ ++}; ++ ++struct mm_set_keepalive_req ++{ ++ u32_l hwconfig_id; ++ u16_l code; ++ u16_l length; ++ u32_l intv; ++ u8_l payload[]; ++}; ++ ++struct mm_set_txop_req ++{ ++ u16_l txop_bk; ++ u16_l txop_be; ++ u16_l txop_vi; ++ u16_l txop_vo; ++ u8_l long_nav_en; ++ u8_l cfe_en; ++}; ++ ++#ifdef CONFIG_APF ++struct mm_set_apf_prog_req { ++ u32_l program_len; ++ u32_l offset; ++ u8_l program[LMAC_MSG_MAX_LEN]; ++}; ++ ++struct mm_get_apf_prog_req { ++ u16_l offset; ++}; ++ ++struct mm_get_apf_prog_cfm { ++ u8_l program[LMAC_MSG_MAX_LEN]; ++}; ++#endif ++ ++struct mm_get_fw_version_cfm ++{ ++ u8_l fw_version_len; ++ u8_l fw_version[63]; ++}; ++ ++struct mm_get_wifi_disable_cfm ++{ ++ u8_l wifi_disable; ++}; ++ ++enum vendor_swconfig_tag ++{ ++ BCN_CFG_REQ = 0, ++ TEMP_COMP_SET_REQ, ++ TEMP_COMP_GET_REQ, ++ EXT_FLAGS_SET_REQ, ++ EXT_FLAGS_GET_REQ, ++ EXT_FLAGS_MASK_SET_REQ, ++}; ++ ++struct mm_set_bcn_cfg_req ++{ ++ /// Ignore or not bcn tim bcmc bit ++ bool_l tim_bcmc_ignored_enable; ++}; ++ ++struct mm_set_bcn_cfg_cfm ++{ ++ /// Request status ++ bool_l tim_bcmc_ignored_status; ++}; ++ ++struct mm_set_temp_comp_req ++{ ++ /// Enable or not temp comp ++ u8_l enable; ++ u8_l reserved[3]; ++ u32_l tmr_period_ms; ++}; ++ ++struct mm_set_temp_comp_cfm ++{ ++ /// Request status ++ u8_l status; ++}; ++ ++struct mm_get_temp_comp_cfm ++{ ++ /// Request status ++ u8_l status; ++ /// Temp degree val ++ s8_l degree; ++}; ++ ++struct mm_set_ext_flags_req ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_set_ext_flags_cfm ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_get_ext_flags_cfm ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_mask_set_ext_flags_req ++{ ++ u32_l user_flags_mask; ++ u32_l user_flags_val; ++}; ++ ++struct mm_mask_set_ext_flags_cfm ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_set_vendor_swconfig_req ++{ ++ u32_l swconfig_id; ++ union { ++ struct mm_set_bcn_cfg_req bcn_cfg_req; ++ struct mm_set_temp_comp_req temp_comp_set_req; ++ struct mm_set_ext_flags_req ext_flags_set_req; ++ struct mm_mask_set_ext_flags_req ext_flags_mask_set_req; ++ }; ++}; ++ ++struct mm_set_vendor_swconfig_cfm ++{ ++ u32_l swconfig_id; ++ union { ++ struct mm_set_bcn_cfg_cfm bcn_cfg_cfm; ++ struct mm_set_temp_comp_cfm temp_comp_set_cfm; ++ struct mm_get_temp_comp_cfm temp_comp_get_cfm; ++ struct mm_set_ext_flags_cfm ext_flags_set_cfm; ++ struct mm_get_ext_flags_cfm ext_flags_get_cfm; ++ struct mm_mask_set_ext_flags_cfm ext_flags_mask_set_cfm; ++ }; ++}; ++ ++#ifdef CONFIG_SDIO_BT ++struct mm_bt_send_req ++{ ++ u32_l data_len; ++ u8_l bt_data[1024]; ++}; ++ ++struct mm_bt_send_cfm ++{ ++ u8_l status; ++}; ++#endif ++ ++/// Structure containing the parameters of the @ref ME_RC_STATS_REQ message. ++struct me_rc_stats_req { ++ /// Index of the station for which the RC statistics are requested ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the rate control statistics ++struct rc_rate_stats { ++ /// Number of attempts (per sampling interval) ++ u16_l attempts; ++ /// Number of success (per sampling interval) ++ u16_l success; ++ /// Estimated probability of success (EWMA) ++ u16_l probability; ++ /// Rate configuration of the sample ++ u16_l rate_config; ++ union { ++ struct { ++ /// Number of times the sample has been skipped (per sampling interval) ++ u8_l sample_skipped; ++ /// Whether the old probability is available ++ bool_l old_prob_available; ++ /// Whether the rate can be used in the retry chain ++ bool_l rate_allowed; ++ }; ++ struct { ++ /// RU size and UL length received in the latest HE trigger frame ++ u16_l ru_and_length; ++ }; ++ }; ++}; ++ ++/// Number of RC samples ++#define RC_MAX_N_SAMPLE 10 ++/// Index of the HE statistics element in the table ++#define RC_HE_STATS_IDX RC_MAX_N_SAMPLE ++ ++/// Structure containing the parameters of the @ref ME_RC_STATS_CFM message. ++struct me_rc_stats_cfm { ++ /// Index of the station for which the RC statistics are provided ++ u8_l sta_idx; ++ /// Number of samples used in the RC algorithm ++ u16_l no_samples; ++ /// Number of MPDUs transmitted (per sampling interval) ++ u16_l ampdu_len; ++ /// Number of AMPDUs transmitted (per sampling interval) ++ u16_l ampdu_packets; ++ /// Average number of MPDUs in each AMPDU frame (EWMA) ++ u32_l avg_ampdu_len; ++ // Current step 0 of the retry chain ++ u8_l sw_retry_step; ++ /// Trial transmission period ++ u8_l sample_wait; ++ /// Retry chain steps ++ u16_l retry_step_idx[4]; ++ /// RC statistics - Max number of RC samples, plus one for the HE TB statistics ++ struct rc_rate_stats rate_stats[RC_MAX_N_SAMPLE + 1]; ++ /// Throughput - Max number of RC samples, plus one for the HE TB statistics ++ u32_l tp[RC_MAX_N_SAMPLE + 1]; ++}; ++ ++/// Structure containing the parameters of the @ref ME_RC_SET_RATE_REQ message. ++struct me_rc_set_rate_req { ++ /// Index of the station for which the fixed rate is set ++ u8_l sta_idx; ++ /// Rate configuration to be set ++ u16_l fixed_rate_cfg; ++}; ++ ++/// Structure containing the parameters of the @ref ME_CONFIG_MONITOR_REQ message. ++struct me_config_monitor_req { ++ /// Channel to configure ++ struct mac_chan_op chan; ++ /// Is channel data valid ++ bool_l chan_set; ++ /// Enable report of unsupported HT frames ++ bool_l uf; ++ /// Enable auto-reply as the mac_addr matches ++ bool_l auto_reply; ++}; ++ ++/// Structure containing the parameters of the @ref ME_CONFIG_MONITOR_CFM message. ++struct me_config_monitor_cfm { ++ /// Channel context index ++ u8_l chan_index; ++ /// Channel parameters ++ struct mac_chan_op chan; ++}; ++ ++/// Structure containing the parameters of the @ref ME_SET_PS_MODE_REQ message. ++struct me_set_ps_mode_req { ++ /// Power Save is activated or deactivated ++ u8_l ps_state; ++}; ++ ++/// Structure containing the parameters of the @ref ME_SET_LP_LEVEL_REQ message. ++struct me_set_lp_level_req { ++ /// Low Power level ++ u8_l lp_level; ++ u8_l disable_filter; ++}; ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For SM messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Message API of the SM task ++enum sm_msg_tag { ++ /// Request to connect to an AP ++ SM_CONNECT_REQ = LMAC_FIRST_MSG(TASK_SM), ++ /// Confirmation of connection ++ SM_CONNECT_CFM, ++ /// Indicates that the SM associated to the AP ++ SM_CONNECT_IND, ++ /// Request to disconnect ++ SM_DISCONNECT_REQ, ++ /// Confirmation of disconnection ++ SM_DISCONNECT_CFM, ++ /// Indicates that the SM disassociated the AP ++ SM_DISCONNECT_IND, ++ /// Request to start external authentication ++ SM_EXTERNAL_AUTH_REQUIRED_IND, ++ /// Response to external authentication request ++ SM_EXTERNAL_AUTH_REQUIRED_RSP, ++ /// Request to update assoc elements after FT over the air authentication ++ SM_FT_AUTH_IND, ++ /// Response to FT authentication with updated assoc elements ++ SM_FT_AUTH_RSP, ++ ++ SM_RSP_TIMEOUT_IND, ++ ++ SM_COEX_TS_TIMEOUT_IND, ++ ++ SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM, ++ /// MAX number of messages ++ SM_MAX, ++}; ++ ++/// Structure containing the parameters of @ref SM_CONNECT_REQ message. ++struct sm_connect_req { ++ /// SSID to connect to ++ struct mac_ssid ssid; ++ /// BSSID to connect to (if not specified, set this field to WILDCARD BSSID) ++ struct mac_addr bssid; ++ /// Channel on which we have to connect (if not specified, set -1 in the chan.freq field) ++ struct mac_chan_def chan; ++ /// Connection flags (see @ref mac_connection_flags) ++ u32_l flags; ++ /// Control port Ethertype (in network endianness) ++ u16_l ctrl_port_ethertype; ++ /// Length of the association request IEs ++ u16_l ie_len; ++ /// Listen interval to be used for this connection ++ u16_l listen_interval; ++ /// Flag indicating if the we have to wait for the BC/MC traffic after beacon or not ++ bool_l dont_wait_bcmc; ++ /// Authentication type ++ u8_l auth_type; ++ /// UAPSD queues (bit0: VO, bit1: VI, bit2: BE, bit3: BK) ++ u8_l uapsd_queues; ++ /// VIF index ++ u8_l vif_idx; ++ /// Buffer containing the additional information elements to be put in the ++ /// association request ++ u32_l ie_buf[64]; ++}; ++ ++/// Structure containing the parameters of the @ref SM_CONNECT_CFM message. ++struct sm_connect_cfm { ++ /// Status. If 0, it means that the connection procedure will be performed and that ++ /// a subsequent @ref SM_CONNECT_IND message will be forwarded once the procedure is ++ /// completed ++ u8_l status; ++}; ++ ++#define SM_ASSOC_IE_LEN 800 ++/// Structure containing the parameters of the @ref SM_CONNECT_IND message. ++struct sm_connect_ind { ++ /// Status code of the connection procedure ++ u16_l status_code; ++ /// BSSID ++ struct mac_addr bssid; ++ /// Flag indicating if the indication refers to an internal roaming or from a host request ++ bool_l roamed; ++ /// Index of the VIF for which the association process is complete ++ u8_l vif_idx; ++ /// Index of the STA entry allocated for the AP ++ u8_l ap_idx; ++ /// Index of the LMAC channel context the connection is attached to ++ u8_l ch_idx; ++ /// Flag indicating if the AP is supporting QoS ++ bool_l qos; ++ /// ACM bits set in the AP WMM parameter element ++ u8_l acm; ++ /// Length of the AssocReq IEs ++ u16_l assoc_req_ie_len; ++ /// Length of the AssocRsp IEs ++ u16_l assoc_rsp_ie_len; ++ /// IE buffer ++ u32_l assoc_ie_buf[SM_ASSOC_IE_LEN/4]; ++ ++ u16_l aid; ++ u8_l band; ++ u16_l center_freq; ++ u8_l width; ++ u32_l center_freq1; ++ u32_l center_freq2; ++ ++ /// EDCA parameters ++ u32_l ac_param[AC_MAX]; ++}; ++ ++/// Structure containing the parameters of the @ref SM_DISCONNECT_REQ message. ++struct sm_disconnect_req { ++ /// Reason of the deauthentication. ++ u16_l reason_code; ++ /// Index of the VIF. ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of SM_ASSOCIATION_IND the message ++struct sm_association_ind { ++ // MAC ADDR of the STA ++ struct mac_addr me_mac_addr; ++}; ++ ++ ++/// Structure containing the parameters of the @ref SM_DISCONNECT_IND message. ++struct sm_disconnect_ind { ++ /// Reason of the disconnection. ++ u16_l reason_code; ++ /// Index of the VIF. ++ u8_l vif_idx; ++ /// FT over DS is ongoing ++ bool_l ft_over_ds; ++ u8_l reassoc; ++}; ++ ++/// Structure containing the parameters of the @ref SM_EXTERNAL_AUTH_REQUIRED_IND ++struct sm_external_auth_required_ind { ++ /// Index of the VIF. ++ u8_l vif_idx; ++ /// SSID to authenticate to ++ struct mac_ssid ssid; ++ /// BSSID to authenticate to ++ struct mac_addr bssid; ++ /// AKM suite of the respective authentication ++ u32_l akm; ++}; ++ ++/// Structure containing the parameters of the @ref SM_EXTERNAL_AUTH_REQUIRED_RSP ++struct sm_external_auth_required_rsp { ++ /// Index of the VIF. ++ u8_l vif_idx; ++ /// Authentication status ++ u16_l status; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For APM messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Message API of the APM task ++enum apm_msg_tag { ++ /// Request to start the AP. ++ APM_START_REQ = LMAC_FIRST_MSG(TASK_APM), ++ /// Confirmation of the AP start. ++ APM_START_CFM, ++ /// Request to stop the AP. ++ APM_STOP_REQ, ++ /// Confirmation of the AP stop. ++ APM_STOP_CFM, ++ /// Request to start CAC ++ APM_START_CAC_REQ, ++ /// Confirmation of the CAC start ++ APM_START_CAC_CFM, ++ /// Request to stop CAC ++ APM_STOP_CAC_REQ, ++ /// Confirmation of the CAC stop ++ APM_STOP_CAC_CFM, ++ ++ APM_SET_BEACON_IE_REQ, ++ APM_SET_BEACON_IE_CFM, ++ ++ /// MAX number of messages ++ APM_MAX, ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_REQ message. ++struct apm_start_req { ++ /// Basic rate set ++ struct mac_rateset basic_rates; ++ /// Control channel on which we have to enable the AP ++ struct mac_chan_def chan; ++ /// Center frequency of the first segment ++ u32_l center_freq1; ++ /// Center frequency of the second segment (only in 80+80 configuration) ++ u32_l center_freq2; ++ /// Width of channel ++ u8_l ch_width; ++ /// Address, in host memory, to the beacon template ++ u32_l bcn_addr; ++ /// Length of the beacon template ++ u16_l bcn_len; ++ /// Offset of the TIM IE in the beacon ++ u16_l tim_oft; ++ /// Beacon interval ++ u16_l bcn_int; ++ /// Flags (@ref mac_connection_flags) ++ u32_l flags; ++ /// Control port Ethertype ++ u16_l ctrl_port_ethertype; ++ /// Length of the TIM IE ++ u8_l tim_len; ++ /// Index of the VIF for which the AP is started ++ u8_l vif_idx; ++}; ++ ++struct apm_set_bcn_ie_req { ++ u8_l vif_idx; ++ u16_l bcn_ie_len; ++ u8_l bcn_ie[512]; ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_CFM message. ++struct apm_start_cfm { ++ /// Status of the AP starting procedure ++ u8_l status; ++ /// Index of the VIF for which the AP is started ++ u8_l vif_idx; ++ /// Index of the channel context attached to the VIF ++ u8_l ch_idx; ++ /// Index of the STA used for BC/MC traffic ++ u8_l bcmc_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_STOP_REQ message. ++struct apm_stop_req { ++ /// Index of the VIF for which the AP has to be stopped ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_CAC_REQ message. ++struct apm_start_cac_req { ++ /// Control channel on which we have to start the CAC ++ struct mac_chan_op chan; ++ /// Center frequency of the first segment ++ //u32_l center_freq1; ++ /// Center frequency of the second segment (only in 80+80 configuration) ++ //u32_l center_freq2; ++ /// Width of channel ++ //u8_l ch_width; ++ /// Index of the VIF for which the CAC is started ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_CAC_CFM message. ++struct apm_start_cac_cfm { ++ /// Status of the CAC starting procedure ++ u8_l status; ++ /// Index of the channel context attached to the VIF for CAC ++ u8_l ch_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_STOP_CAC_REQ message. ++struct apm_stop_cac_req { ++ /// Index of the VIF for which the CAC has to be stopped ++ u8_l vif_idx; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For MESH messages ++/////////////////////////////////////////////////////////////////////////////// ++ ++/// Maximum length of the Mesh ID ++#define MESH_MESHID_MAX_LEN (32) ++ ++/// Message API of the MESH task ++enum mesh_msg_tag ++{ ++ /// Request to start the MP ++ MESH_START_REQ = LMAC_FIRST_MSG(TASK_MESH), ++ /// Confirmation of the MP start. ++ MESH_START_CFM, ++ ++ /// Request to stop the MP. ++ MESH_STOP_REQ, ++ /// Confirmation of the MP stop. ++ MESH_STOP_CFM, ++ ++ // Request to update the MP ++ MESH_UPDATE_REQ, ++ /// Confirmation of the MP update ++ MESH_UPDATE_CFM, ++ ++ /// Request information about a given link ++ MESH_PEER_INFO_REQ, ++ /// Response to the MESH_PEER_INFO_REQ message ++ MESH_PEER_INFO_CFM, ++ ++ /// Request automatic establishment of a path with a given mesh STA ++ MESH_PATH_CREATE_REQ, ++ /// Confirmation to the MESH_PATH_CREATE_REQ message ++ MESH_PATH_CREATE_CFM, ++ ++ /// Request a path update (delete path, modify next hop mesh STA) ++ MESH_PATH_UPDATE_REQ, ++ /// Confirmation to the MESH_PATH_UPDATE_REQ message ++ MESH_PATH_UPDATE_CFM, ++ ++ /// Indication from Host that the indicated Mesh Interface is a proxy for an external STA ++ MESH_PROXY_ADD_REQ, ++ ++ /// Indicate that a connection has been established or lost ++ MESH_PEER_UPDATE_IND, ++ /// Notification that a connection has been established or lost (when MPM handled by userspace) ++ MESH_PEER_UPDATE_NTF = MESH_PEER_UPDATE_IND, ++ ++ /// Indicate that a path is now active or inactive ++ MESH_PATH_UPDATE_IND, ++ /// Indicate that proxy information have been updated ++ MESH_PROXY_UPDATE_IND, ++ ++ /// MAX number of messages ++ MESH_MAX, ++}; ++ ++ ++/// Structure containing the parameters of the @ref MESH_START_REQ message. ++struct mesh_start_req { ++ /// Basic rate set ++ struct mac_rateset basic_rates; ++ /// Control channel on which we have to enable the AP ++ struct mac_chan_def chan; ++ /// Center frequency of the first segment ++ u32_l center_freq1; ++ /// Center frequency of the second segment (only in 80+80 configuration) ++ u32_l center_freq2; ++ /// Width of channel ++ u8_l ch_width; ++ /// DTIM Period ++ u8_l dtim_period; ++ /// Beacon Interval ++ u16_l bcn_int; ++ /// Index of the VIF for which the MP is started ++ u8_l vif_index; ++ /// Length of the Mesh ID ++ u8_l mesh_id_len; ++ /// Mesh ID ++ u8_l mesh_id[MESH_MESHID_MAX_LEN]; ++ /// Address of the IEs to download ++ u32_l ie_addr; ++ /// Length of the provided IEs ++ u8_l ie_len; ++ /// Indicate if Mesh Peering Management (MPM) protocol is handled in userspace ++ bool_l user_mpm; ++ /// Indicate if Mesh Point is using authentication ++ bool_l is_auth; ++ /// Indicate which authentication method is used ++ u8_l auth_id; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_START_CFM message. ++struct mesh_start_cfm { ++ /// Status of the MP starting procedure ++ u8_l status; ++ /// Index of the VIF for which the MP is started ++ u8_l vif_idx; ++ /// Index of the channel context attached to the VIF ++ u8_l ch_idx; ++ /// Index of the STA used for BC/MC traffic ++ u8_l bcmc_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_STOP_REQ message. ++struct mesh_stop_req { ++ /// Index of the VIF for which the MP has to be stopped ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_STOP_CFM message. ++struct mesh_stop_cfm { ++ /// Index of the VIF for which the MP has to be stopped ++ u8_l vif_idx; ++ /// Status ++ u8_l status; ++}; ++ ++/// Bit fields for mesh_update_req message's flags value ++enum mesh_update_flags_bit { ++ /// Root Mode ++ MESH_UPDATE_FLAGS_ROOT_MODE_BIT = 0, ++ /// Gate Mode ++ MESH_UPDATE_FLAGS_GATE_MODE_BIT, ++ /// Mesh Forwarding ++ MESH_UPDATE_FLAGS_MESH_FWD_BIT, ++ /// Local Power Save Mode ++ MESH_UPDATE_FLAGS_LOCAL_PSM_BIT, ++}; ++ ++/// Structure containing the parameters of the @ref MESH_UPDATE_REQ message. ++struct mesh_update_req { ++ /// Flags, indicate fields which have been updated ++ u8_l flags; ++ /// VIF Index ++ u8_l vif_idx; ++ /// Root Mode ++ u8_l root_mode; ++ /// Gate Announcement ++ bool_l gate_announ; ++ /// Mesh Forwarding ++ bool_l mesh_forward; ++ /// Local PS Mode ++ u8_l local_ps_mode; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_UPDATE_CFM message. ++struct mesh_update_cfm { ++ /// Status ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_INFO_REQ message. ++struct mesh_peer_info_req { ++ ///Index of the station allocated for the peer ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_INFO_CFM message. ++struct mesh_peer_info_cfm { ++ /// Response status ++ u8_l status; ++ /// Index of the station allocated for the peer ++ u8_l sta_idx; ++ /// Local Link ID ++ u16_l local_link_id; ++ /// Peer Link ID ++ u16_l peer_link_id; ++ /// Local PS Mode ++ u8_l local_ps_mode; ++ /// Peer PS Mode ++ u8_l peer_ps_mode; ++ /// Non-peer PS Mode ++ u8_l non_peer_ps_mode; ++ /// Link State ++ u8_l link_state; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_CREATE_REQ message. ++struct mesh_path_create_req { ++ /// Index of the interface on which path has to be created ++ u8_l vif_idx; ++ /// Indicate if originator MAC Address is provided ++ bool_l has_orig_addr; ++ /// Path Target MAC Address ++ struct mac_addr tgt_mac_addr; ++ /// Originator MAC Address ++ struct mac_addr orig_mac_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_CREATE_CFM message. ++struct mesh_path_create_cfm { ++ /// Confirmation status ++ u8_l status; ++ /// VIF Index ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_UPDATE_REQ message. ++struct mesh_path_update_req { ++ /// Indicate if path must be deleted ++ bool_l delete; ++ /// Index of the interface on which path has to be created ++ u8_l vif_idx; ++ /// Path Target MAC Address ++ struct mac_addr tgt_mac_addr; ++ /// Next Hop MAC Address ++ struct mac_addr nhop_mac_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_UPDATE_CFM message. ++struct mesh_path_update_cfm { ++ /// Confirmation status ++ u8_l status; ++ /// VIF Index ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PROXY_ADD_REQ message. ++struct mesh_proxy_add_req { ++ /// VIF Index ++ u8_l vif_idx; ++ /// MAC Address of the External STA ++ struct mac_addr ext_sta_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PROXY_UPDATE_IND ++struct mesh_proxy_update_ind { ++ /// Indicate if proxy information has been added or deleted ++ bool_l delete; ++ /// Indicate if we are a proxy for the external STA ++ bool_l local; ++ /// VIF Index ++ u8_l vif_idx; ++ /// MAC Address of the External STA ++ struct mac_addr ext_sta_addr; ++ /// MAC Address of the proxy (only valid if local is false) ++ struct mac_addr proxy_mac_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_UPDATE_IND message. ++struct mesh_peer_update_ind { ++ /// Indicate if connection has been established or lost ++ bool_l estab; ++ /// VIF Index ++ u8_l vif_idx; ++ /// STA Index ++ u8_l sta_idx; ++ /// Peer MAC Address ++ struct mac_addr peer_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_UPDATE_NTF message. ++struct mesh_peer_update_ntf { ++ /// VIF Index ++ u8_l vif_idx; ++ /// STA Index ++ u8_l sta_idx; ++ /// Mesh Link State ++ u8_l state; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_UPDATE_IND message. ++struct mesh_path_update_ind { ++ /// Indicate if path is deleted or not ++ bool_l delete; ++ /// Indicate if path is towards an external STA (not part of MBSS) ++ bool_l ext_sta; ++ /// VIF Index ++ u8_l vif_idx; ++ /// Path Index ++ u8_l path_idx; ++ /// Target MAC Address ++ struct mac_addr tgt_mac_addr; ++ /// External STA MAC Address (only if ext_sta is true) ++ struct mac_addr ext_sta_mac_addr; ++ /// Next Hop STA Index ++ u8_l nhop_sta_idx; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For Debug messages ++/////////////////////////////////////////////////////////////////////////////// ++ ++/// Messages related to Debug Task ++enum dbg_msg_tag { ++ /// Memory read request ++ DBG_MEM_READ_REQ = LMAC_FIRST_MSG(TASK_DBG), ++ /// Memory read confirm ++ DBG_MEM_READ_CFM, ++ /// Memory write request ++ DBG_MEM_WRITE_REQ, ++ /// Memory write confirm ++ DBG_MEM_WRITE_CFM, ++ /// Module filter request ++ DBG_SET_MOD_FILTER_REQ, ++ /// Module filter confirm ++ DBG_SET_MOD_FILTER_CFM, ++ /// Severity filter request ++ DBG_SET_SEV_FILTER_REQ, ++ /// Severity filter confirm ++ DBG_SET_SEV_FILTER_CFM, ++ /// LMAC/MAC HW fatal error indication ++ DBG_ERROR_IND, ++ /// Request to get system statistics ++ DBG_GET_SYS_STAT_REQ, ++ /// COnfirmation of system statistics ++ DBG_GET_SYS_STAT_CFM, ++ /// Memory block write request ++ DBG_MEM_BLOCK_WRITE_REQ, ++ /// Memory block write confirm ++ DBG_MEM_BLOCK_WRITE_CFM, ++ /// Start app request ++ DBG_START_APP_REQ, ++ /// Start app confirm ++ DBG_START_APP_CFM, ++ /// Start npc request ++ DBG_START_NPC_REQ, ++ /// Start npc confirm ++ DBG_START_NPC_CFM, ++ /// Memory mask write request ++ DBG_MEM_MASK_WRITE_REQ, ++ /// Memory mask write confirm ++ DBG_MEM_MASK_WRITE_CFM, ++ ++ DBG_RFTEST_CMD_REQ, ++ DBG_RFTEST_CMD_CFM, ++ DBG_BINDING_REQ, ++ DBG_BINDING_CFM, ++ DBG_BINDING_IND, ++ ++ DBG_CUSTOM_MSG_REQ, ++ DBG_CUSTOM_MSG_CFM, ++ DBG_CUSTOM_MSG_IND, ++ ++ DBG_GPIO_WRITE_REQ, ++ DBG_GPIO_WRITE_CFM, ++ DBG_GPIO_READ_REQ, ++ DBG_GPIO_READ_CFM, ++ DBG_GPIO_INIT_REQ, ++ DBG_GPIO_INIT_CFM, ++ ++ /// EF usrdata read request ++ DBG_EF_USRDATA_READ_REQ, ++ /// EF usrdata read confirm ++ DBG_EF_USRDATA_READ_CFM, ++ /// Memory block read request ++ DBG_MEM_BLOCK_READ_REQ, ++ /// Memory block read confirm ++ DBG_MEM_BLOCK_READ_CFM, ++ ++ DBG_PWM_INIT_REQ, ++ DBG_PWM_INIT_CFM, ++ DBG_PWM_DEINIT_REQ, ++ DBG_PWM_DEINIT_CFM, ++ ++ /// Max number of Debug messages ++ DBG_MAX, ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_REQ message. ++struct dbg_mem_read_req { ++ u32_l memaddr; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_CFM message. ++struct dbg_mem_read_cfm { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_REQ message. ++struct dbg_mem_write_req { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_CFM message. ++struct dbg_mem_write_cfm { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_REQ message. ++struct dbg_mem_mask_write_req { ++ u32_l memaddr; ++ u32_l memmask; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_CFM message. ++struct dbg_mem_mask_write_cfm { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++struct dbg_rftest_cmd_req { ++ u32_l cmd; ++ u32_l argc; ++ u8_l argv[10]; ++}; ++ ++struct dbg_rftest_cmd_cfm { ++ u32_l rftest_result[32]; ++}; ++ ++struct dbg_gpio_write_req { ++ uint8_t gpio_idx; ++ uint8_t gpio_val; ++}; ++ ++struct dbg_gpio_read_req { ++ uint8_t gpio_idx; ++}; ++ ++struct dbg_gpio_read_cfm { ++ uint8_t gpio_idx; ++ uint8_t gpio_val; ++}; ++ ++struct dbg_gpio_init_req { ++ uint8_t gpio_idx; ++ uint8_t gpio_dir; //1 output, 0 input; ++ uint8_t gpio_val; //for output, 1 high, 0 low; ++}; ++ ++#ifdef CONFIG_MCU_MESSAGE ++/// Structure containing the parameters of the @ref DBG_CUSTOM_MSG_REQ message. ++struct dbg_custom_msg_req ++{ ++ u32_l cmd; ++ u32_l len; ++ u32_l flags; ++ u32_l buf[1]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_CUSTOM_MSG_CFM message. ++struct dbg_custom_msg_cfm ++{ ++ u32_l cmd; ++ u32_l len; ++ u32_l status; ++ u32_l buf[1]; ++}; ++ ++typedef struct dbg_custom_msg_cfm dbg_custom_msg_ind_t; ++#endif ++ ++/// Structure containing the parameters of the @ref DBG_SET_MOD_FILTER_REQ message. ++struct dbg_set_mod_filter_req { ++ /// Bit field indicating for each module if the traces are enabled or not ++ u32_l mod_filter; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_SEV_MOD_FILTER_REQ message. ++struct dbg_set_sev_filter_req { ++ /// Bit field indicating the severity threshold for the traces ++ u32_l sev_filter; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_GET_SYS_STAT_CFM message. ++struct dbg_get_sys_stat_cfm { ++ /// Time spent in CPU sleep since last reset of the system statistics ++ u32_l cpu_sleep_time; ++ /// Time spent in DOZE since last reset of the system statistics ++ u32_l doze_time; ++ /// Total time spent since last reset of the system statistics ++ u32_l stats_time; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_REQ message. ++struct dbg_mem_block_write_req { ++ u32_l memaddr; ++ u32_l memsize; ++ u32_l memdata[1024 / sizeof(u32_l)]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_CFM message. ++struct dbg_mem_block_write_cfm { ++ u32_l wstatus; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_READ_REQ message. ++struct dbg_mem_block_read_req ++{ ++ u32_l memaddr; ++ u32_l memsize; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_READ_CFM message. ++struct dbg_mem_block_read_cfm ++{ ++ u32_l memaddr; ++ u32_l memsize; ++ u32_l memdata[1024 / sizeof(u32_l)]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_REQ message. ++struct dbg_start_app_req { ++ u32_l bootaddr; ++ u32_l boottype; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_CFM message. ++struct dbg_start_app_cfm { ++ u32_l bootstatus; ++}; ++ ++enum { ++ HOST_START_APP_AUTO = 1, ++ HOST_START_APP_CUSTOM, ++ HOST_START_APP_FNCALL = 4, ++ HOST_START_APP_DUMMY = 5, ++}; ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For TDLS messages ++/////////////////////////////////////////////////////////////////////////////// ++ ++/// List of messages related to the task. ++enum tdls_msg_tag { ++ /// TDLS channel Switch Request. ++ TDLS_CHAN_SWITCH_REQ = LMAC_FIRST_MSG(TASK_TDLS), ++ /// TDLS channel switch confirmation. ++ TDLS_CHAN_SWITCH_CFM, ++ /// TDLS channel switch indication. ++ TDLS_CHAN_SWITCH_IND, ++ /// TDLS channel switch to base channel indication. ++ TDLS_CHAN_SWITCH_BASE_IND, ++ /// TDLS cancel channel switch request. ++ TDLS_CANCEL_CHAN_SWITCH_REQ, ++ /// TDLS cancel channel switch confirmation. ++ TDLS_CANCEL_CHAN_SWITCH_CFM, ++ /// TDLS peer power save indication. ++ TDLS_PEER_PS_IND, ++ /// TDLS peer traffic indication request. ++ TDLS_PEER_TRAFFIC_IND_REQ, ++ /// TDLS peer traffic indication confirmation. ++ TDLS_PEER_TRAFFIC_IND_CFM, ++ ++#ifdef CONFIG_SDIO_BT ++ TDLS_SDIO_BT_SEND_REQ = LMAC_FIRST_MSG(TASK_TDLS)+16, ++ TDLS_SDIO_BT_SEND_CFM, ++ TDLS_SDIO_BT_RECV_IND, ++#endif ++ /// MAX number of messages ++ TDLS_MAX ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_REQ message ++struct tdls_chan_switch_req { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ /// MAC address of the TDLS station ++ struct mac_addr peer_mac_addr; ++ bool_l initiator; ++ /// Band (2.4GHz or 5GHz) ++ u8_l band; ++ /// Channel type: 20,40,80,160 or 80+80 MHz ++ u8_l type; ++ /// Frequency for Primary 20MHz channel (in MHz) ++ u16_l prim20_freq; ++ /// Frequency for Center of the contiguous channel or center of Primary 80+80 ++ u16_l center1_freq; ++ /// Frequency for Center of the non-contiguous secondary 80+80 ++ u16_l center2_freq; ++ /// TX power (in dBm) ++ s8_l tx_power; ++ /// Operating class ++ u8_l op_class; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CANCEL_CHAN_SWITCH_REQ message ++struct tdls_cancel_chan_switch_req { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ /// MAC address of the TDLS station ++ struct mac_addr peer_mac_addr; ++}; ++ ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_CFM message ++struct tdls_chan_switch_cfm { ++ /// Status of the operation ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CANCEL_CHAN_SWITCH_CFM message ++struct tdls_cancel_chan_switch_cfm { ++ /// Status of the operation ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_IND message ++struct tdls_chan_switch_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// Channel Context Index ++ u8_l chan_ctxt_index; ++ /// Status of the operation ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_BASE_IND message ++struct tdls_chan_switch_base_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// Channel Context index ++ u8_l chan_ctxt_index; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_PEER_PS_IND message ++struct tdls_peer_ps_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ /// MAC ADDR of the TDLS STA ++ struct mac_addr peer_mac_addr; ++ /// Flag to indicate if the TDLS peer is going to sleep ++ bool ps_on; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_PEER_TRAFFIC_IND_REQ message ++struct tdls_peer_traffic_ind_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ // MAC ADDR of the TDLS STA ++ struct mac_addr peer_mac_addr; ++ /// Dialog token ++ u8_l dialog_token; ++ /// TID of the latest MPDU transmitted over the TDLS direct link to the TDLS STA ++ u8_l last_tid; ++ /// Sequence number of the latest MPDU transmitted over the TDLS direct link ++ /// to the TDLS STA ++ u16_l last_sn; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_PEER_TRAFFIC_IND_CFM message ++struct tdls_peer_traffic_ind_cfm { ++ /// Status of the operation ++ u8_l status; ++}; ++ ++ ++#endif // LMAC_MSG_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h +new file mode 100644 +index 000000000000..83b112290409 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h +@@ -0,0 +1,62 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file co_types.h ++ * ++ * @brief This file replaces the need to include stdint or stdbool typical headers, ++ * which may not be available in all toolchains, and adds new types ++ * ++ * Copyright (C) RivieraWaves 2009-2019 ++ * ++ * $Rev: $ ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _LMAC_INT_H_ ++#define _LMAC_INT_H_ ++ ++ ++/** ++ **************************************************************************************** ++ * @addtogroup CO_INT ++ * @ingroup COMMON ++ * @brief Common integer standard types (removes use of stdint) ++ * ++ * @{ ++ **************************************************************************************** ++ */ ++ ++ ++/* ++ * DEFINES ++ **************************************************************************************** ++ */ ++ ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++#include ++#else ++#include ++#endif ++ ++#ifdef CONFIG_RWNX_TL4 ++typedef uint16_t u8_l; ++typedef int16_t s8_l; ++typedef uint16_t bool_l; ++#else ++typedef uint8_t u8_l; ++typedef int8_t s8_l; ++typedef bool bool_l; ++#endif ++typedef uint16_t u16_l; ++typedef int16_t s16_l; ++typedef uint32_t u32_l; ++typedef int32_t s32_l; ++typedef uint64_t u64_l; ++ ++ ++ ++/// @} CO_INT ++#endif // _LMAC_INT_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c +new file mode 100644 +index 000000000000..3d7b65375adb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c +@@ -0,0 +1,161 @@ ++#include ++#include "md5.h" ++ ++unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; ++ ++void MD5Init(MD5_CTX *context) ++{ ++ context->count[0] = 0; ++ context->count[1] = 0; ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xEFCDAB89; ++ context->state[2] = 0x98BADCFE; ++ context->state[3] = 0x10325476; ++} ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) ++{ ++ unsigned int i = 0,index = 0,partlen = 0; ++ index = (context->count[0] >> 3) & 0x3F; ++ partlen = 64 - index; ++ context->count[0] += inputlen << 3; ++ if(context->count[0] < (inputlen << 3)) ++ context->count[1]++; ++ context->count[1] += inputlen >> 29; ++ ++ if(inputlen >= partlen) ++ { ++ memcpy(&context->buffer[index],input,partlen); ++ MD5Transform(context->state,context->buffer); ++ for(i = partlen;i+64 <= inputlen;i+=64) ++ MD5Transform(context->state,&input[i]); ++ index = 0; ++ } ++ else ++ { ++ i = 0; ++ } ++ memcpy(&context->buffer[index],&input[i],inputlen-i); ++} ++void MD5Final(MD5_CTX *context,unsigned char digest[16]) ++{ ++ unsigned int index = 0,padlen = 0; ++ unsigned char bits[8]; ++ index = (context->count[0] >> 3) & 0x3F; ++ padlen = (index < 56)?(56-index):(120-index); ++ MD5Encode(bits,context->count,8); ++ MD5Update(context,PADDING,padlen); ++ MD5Update(context,bits,8); ++ MD5Encode(digest,context->state,16); ++} ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[j] = input[i] & 0xFF; ++ output[j+1] = (input[i] >> 8) & 0xFF; ++ output[j+2] = (input[i] >> 16) & 0xFF; ++ output[j+3] = (input[i] >> 24) & 0xFF; ++ i++; ++ j+=4; ++ } ++} ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[i] = (input[j]) | ++ (input[j+1] << 8) | ++ (input[j+2] << 16) | ++ (input[j+3] << 24); ++ i++; ++ j+=4; ++ } ++} ++void MD5Transform(unsigned int state[4],unsigned char block[64]) ++{ ++ unsigned int a = state[0]; ++ unsigned int b = state[1]; ++ unsigned int c = state[2]; ++ unsigned int d = state[3]; ++ unsigned int x[64]; ++ MD5Decode(x,block,64); ++ FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ ++ FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ ++ FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ ++ FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ ++ FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ ++ FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ ++ FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ ++ FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ ++ FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ ++ FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ ++ FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ ++ FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ ++ FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ ++ FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ ++ FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ ++ FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ ++ ++ /* Round 2 */ ++ GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ ++ GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ ++ GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ ++ GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ ++ GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ ++ GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ ++ GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ ++ GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ ++ GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ ++ GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ ++ GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ ++ GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ ++ GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ ++ GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ ++ GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ ++ GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ ++ ++ /* Round 3 */ ++ HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ ++ HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ ++ HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ ++ HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ ++ HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ ++ HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ ++ HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ ++ HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ ++ HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ ++ HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ ++ HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ ++ HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ ++ HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ ++ HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ ++ HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ ++ HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ ++ ++ /* Round 4 */ ++ II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ ++ II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ ++ II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ ++ II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ ++ II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ ++ II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ ++ II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ ++ II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ ++ II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ ++ II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ ++ II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ ++ II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ ++ II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ ++ II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ ++ II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ ++ II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h +new file mode 100644 +index 000000000000..6ed5c0f8e886 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h +@@ -0,0 +1,48 @@ ++#ifndef MD5_H ++#define MD5_H ++ ++typedef struct ++{ ++ unsigned int count[2]; ++ unsigned int state[4]; ++ unsigned char buffer[64]; ++}MD5_CTX; ++ ++ ++#define F(x,y,z) ((x & y) | (~x & z)) ++#define G(x,y,z) ((x & z) | (y & ~z)) ++#define H(x,y,z) (x^y^z) ++#define I(x,y,z) (y ^ (x | ~z)) ++#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) ++#define FF(a,b,c,d,x,s,ac) \ ++ { \ ++ a += F(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define GG(a,b,c,d,x,s,ac) \ ++ { \ ++ a += G(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define HH(a,b,c,d,x,s,ac) \ ++ { \ ++ a += H(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define II(a,b,c,d,x,s,ac) \ ++ { \ ++ a += I(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++void MD5Init(MD5_CTX *context); ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); ++void MD5Final(MD5_CTX *context,unsigned char digest[16]); ++void MD5Transform(unsigned int state[4],unsigned char block[64]); ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h +new file mode 100644 +index 000000000000..568146624cee +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h +@@ -0,0 +1,148 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file reg_access.h ++ * ++ * @brief Definitions and macros for MAC HW and platform register accesses ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef REG_ACCESS_H_ ++#define REG_ACCESS_H_ ++ ++/***************************************************************************** ++ * Addresses within RWNX_ADDR_SYSTEM ++ *****************************************************************************/ ++/* Shard RAM */ ++#define SHARED_RAM_START_ADDR 0x00000000 ++ ++/* IPC registers */ ++#define IPC_REG_BASE_ADDR 0x00800000 ++ ++/* System Controller Registers */ ++#define SYSCTRL_SIGNATURE_ADDR 0x00900000 ++// old diag register name ++#define SYSCTRL_DIAG_CONF_ADDR 0x00900068 ++#define SYSCTRL_PHYDIAG_CONF_ADDR 0x00900074 ++#define SYSCTRL_RIUDIAG_CONF_ADDR 0x00900078 ++// new diag register name ++#define SYSCTRL_DIAG_CONF0 0x00900064 ++#define SYSCTRL_DIAG_CONF1 0x00900068 ++#define SYSCTRL_DIAG_CONF2 0x00900074 ++#define SYSCTRL_DIAG_CONF3 0x00900078 ++#define SYSCTRL_MISC_CNTL_ADDR 0x009000E0 ++#define BOOTROM_ENABLE BIT(4) ++#define FPGA_B_RESET BIT(1) ++#define SOFT_RESET BIT(0) ++ ++/* MAC platform */ ++#define NXMAC_VERSION_1_ADDR 0x00B00004 ++#define NXMAC_MU_MIMO_TX_BIT BIT(19) ++#define NXMAC_BFMER_BIT BIT(18) ++#define NXMAC_BFMEE_BIT BIT(17) ++#define NXMAC_MAC_80211MH_FORMAT_BIT BIT(16) ++#define NXMAC_COEX_BIT BIT(14) ++#define NXMAC_WAPI_BIT BIT(13) ++#define NXMAC_TPC_BIT BIT(12) ++#define NXMAC_VHT_BIT BIT(11) ++#define NXMAC_HT_BIT BIT(10) ++#define NXMAC_RCE_BIT BIT(8) ++#define NXMAC_CCMP_BIT BIT(7) ++#define NXMAC_TKIP_BIT BIT(6) ++#define NXMAC_WEP_BIT BIT(5) ++#define NXMAC_SECURITY_BIT BIT(4) ++#define NXMAC_SME_BIT BIT(3) ++#define NXMAC_HCCA_BIT BIT(2) ++#define NXMAC_EDCA_BIT BIT(1) ++#define NXMAC_QOS_BIT BIT(0) ++ ++#define NXMAC_RX_CNTRL_ADDR 0x00B00060 ++#define NXMAC_EN_DUPLICATE_DETECTION_BIT BIT(31) ++#define NXMAC_ACCEPT_UNKNOWN_BIT BIT(30) ++#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT BIT(29) ++#define NXMAC_ACCEPT_QO_S_NULL_BIT BIT(28) ++#define NXMAC_ACCEPT_QCFWO_DATA_BIT BIT(27) ++#define NXMAC_ACCEPT_Q_DATA_BIT BIT(26) ++#define NXMAC_ACCEPT_CFWO_DATA_BIT BIT(25) ++#define NXMAC_ACCEPT_DATA_BIT BIT(24) ++#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT BIT(23) ++#define NXMAC_ACCEPT_CF_END_BIT BIT(22) ++#define NXMAC_ACCEPT_ACK_BIT BIT(21) ++#define NXMAC_ACCEPT_CTS_BIT BIT(20) ++#define NXMAC_ACCEPT_RTS_BIT BIT(19) ++#define NXMAC_ACCEPT_PS_POLL_BIT BIT(18) ++#define NXMAC_ACCEPT_BA_BIT BIT(17) ++#define NXMAC_ACCEPT_BAR_BIT BIT(16) ++#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT BIT(15) ++#define NXMAC_ACCEPT_BFMEE_FRAMES_BIT BIT(14) ++#define NXMAC_ACCEPT_ALL_BEACON_BIT BIT(13) ++#define NXMAC_ACCEPT_NOT_EXPECTED_BA_BIT BIT(12) ++#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_BIT BIT(11) ++#define NXMAC_ACCEPT_BEACON_BIT BIT(10) ++#define NXMAC_ACCEPT_PROBE_RESP_BIT BIT(9) ++#define NXMAC_ACCEPT_PROBE_REQ_BIT BIT(8) ++#define NXMAC_ACCEPT_MY_UNICAST_BIT BIT(7) ++#define NXMAC_ACCEPT_UNICAST_BIT BIT(6) ++#define NXMAC_ACCEPT_ERROR_FRAMES_BIT BIT(5) ++#define NXMAC_ACCEPT_OTHER_BSSID_BIT BIT(4) ++#define NXMAC_ACCEPT_BROADCAST_BIT BIT(3) ++#define NXMAC_ACCEPT_MULTICAST_BIT BIT(2) ++#define NXMAC_DONT_DECRYPT_BIT BIT(1) ++#define NXMAC_EXC_UNENCRYPTED_BIT BIT(0) ++ ++#define NXMAC_DEBUG_PORT_SEL_ADDR 0x00B00510 ++#define NXMAC_SW_SET_PROFILING_ADDR 0x00B08564 ++#define NXMAC_SW_CLEAR_PROFILING_ADDR 0x00B08568 ++ ++/* Modem Status */ ++#define MDM_HDMCONFIG_ADDR 0x00C00000 ++ ++/* Clock gating configuration */ ++#define MDM_MEMCLKCTRL0_ADDR 0x00C00848 ++#define MDM_CLKGATEFCTRL0_ADDR 0x00C00874 ++#define CRM_CLKGATEFCTRL0_ADDR 0x00940010 ++ ++/* AGC (trident) */ ++#define AGC_RWNXAGCCNTL_ADDR 0x00C02060 ++ ++/* LDPC RAM*/ ++#define PHY_LDPC_RAM_ADDR 0x00C09000 ++ ++/* FCU (elma )*/ ++#define FCU_RWNXFCAGCCNTL_ADDR 0x00C09034 ++ ++/* AGC RAM */ ++#define PHY_AGC_UCODE_ADDR 0x00C0A000 ++ ++/* RIU */ ++#define RIU_RWNXVERSION_ADDR 0x00C0B000 ++#define RIU_RWNXDYNAMICCONFIG_ADDR 0x00C0B008 ++#define RIU_AGCMEMBISTSTAT_ADDR 0x00C0B238 ++#define RIU_AGCMEMSIGNATURESTAT_ADDR 0x00C0B23C ++#define RIU_RWNXAGCCNTL_ADDR 0x00C0B390 ++ ++/* FCU RAM */ ++#define PHY_FCU_UCODE_ADDR 0x00C0E000 ++ ++/* RF ITF */ ++#define FPGAB_MPIF_SEL_ADDR 0x00C10030 ++#define RF_V6_DIAGPORT_CONF1_ADDR 0x00C10010 ++#define RF_v6_PHYDIAG_CONF1_ADDR 0x00C10018 ++ ++#define RF_V7_DIAGPORT_CONF1_ADDR 0x00F10010 ++#define RF_v7_PHYDIAG_CONF1_ADDR 0x00F10018 ++ ++/***************************************************************************** ++ * Macros for generated register files ++ *****************************************************************************/ ++/* Macros for IPC registers access (used in reg_ipc_app.h) */ ++#define REG_IPC_APP_RD(env, INDEX) \ ++ (*(volatile u32 *)((u8 *)env + IPC_REG_BASE_ADDR + 4 * (INDEX))) ++ ++#define REG_IPC_APP_WR(env, INDEX, value) \ ++ (*(volatile u32 *)((u8 *)env + IPC_REG_BASE_ADDR + 4 * (INDEX)) = value) ++ ++#endif /* REG_ACCESS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c +new file mode 100644 +index 000000000000..260a9d27468e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c +@@ -0,0 +1,2914 @@ ++#include ++#include ++#include ++ ++//#include "regdb.h" ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++#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_antenna_gain = DBI_TO_MBI(gain),\ ++ .power_rule.max_eirp = DBM_TO_MBM(eirp), \ ++ .flags = reg_flags, \ ++} ++#define NL80211_RRF_AUTO_BW 0 ++#endif ++ ++static const struct ieee80211_regdomain regdom_00 = { ++ .n_reg_rules = 2, ++ .alpha2 = "00", ++ .reg_rules = { ++ // 1...14 ++ REG_RULE(2390 - 10, 2510 + 10, 40, 0, 20, 0), ++ // 36...165 ++ REG_RULE(5150 - 10, 5970 + 10, 80, 0, 20, 0), ++ } ++ ++#if 0 ++ .alpha2 = "00", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 20, 0, 0), ++ //REG_RULE_EXT(2457, 2482, 40, 0, 20, 0, ++ // NL80211_RRF_NO_IR | 0), ++ REG_RULE_EXT(2474, 2494, 20, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_NO_OFDM | 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, ++ NL80211_RRF_NO_IR | 0), ++ }, ++ .n_reg_rules = 6 ++#endif ++}; ++ ++static const struct ieee80211_regdomain regdom_AD = { ++ .alpha2 = "AD", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5710, 80, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AE = { ++ .alpha2 = "AE", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ //REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AF = { ++ .alpha2 = "AF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AI = { ++ .alpha2 = "AI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AL = { ++ .alpha2 = "AL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AM = { ++ .alpha2 = "AM", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 18, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 18, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_AN = { ++ .alpha2 = "AN", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AR = { ++ .alpha2 = "AR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ //REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ // NL80211_RRF_AUTO_BW | 0), ++ //REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ // NL80211_RRF_DFS | ++ // NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5270, 5330, 40, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ //REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ // NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_AS = { ++ .alpha2 = "AS", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AT = { ++ .alpha2 = "AT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AU = { ++ .alpha2 = "AU", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AW = { ++ .alpha2 = "AW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AZ = { ++ .alpha2 = "AZ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 18, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 18, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_BA = { ++ .alpha2 = "BA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BB = { ++ .alpha2 = "BB", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BD = { ++ .alpha2 = "BD", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_BE = { ++ .alpha2 = "BE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BF = { ++ .alpha2 = "BF", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BG = { ++ .alpha2 = "BG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BH = { ++ .alpha2 = "BH", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BL = { ++ .alpha2 = "BL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BM = { ++ .alpha2 = "BM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BN = { ++ .alpha2 = "BN", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BO = { ++ .alpha2 = "BO", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_BR = { ++ .alpha2 = "BR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BS = { ++ .alpha2 = "BS", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BT = { ++ .alpha2 = "BT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BY = { ++ .alpha2 = "BY", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BZ = { ++ .alpha2 = "BZ", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_CA = { ++ .alpha2 = "CA", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CF = { ++ .alpha2 = "CF", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 40, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 40, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 40, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 40, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CH = { ++ .alpha2 = "CH", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CI = { ++ .alpha2 = "CI", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CL = { ++ .alpha2 = "CL", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_CN = { ++ .alpha2 = "CN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ REG_RULE_EXT(57240, 59400, 2160, 0, 28, 0, 0), ++ REG_RULE_EXT(59400, 63720, 2160, 0, 44, 0, 0), ++ REG_RULE_EXT(63720, 65880, 2160, 0, 28, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_CO = { ++ .alpha2 = "CO", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CR = { ++ .alpha2 = "CR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CX = { ++ .alpha2 = "CX", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CY = { ++ .alpha2 = "CY", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CZ = { ++ .alpha2 = "CZ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5470, 5725, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_DE = { ++ .alpha2 = "DE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 20, 0, NL80211_RRF_AUTO_BW| ++ NL80211_RRF_NO_OUTDOOR| ++ 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, NL80211_RRF_AUTO_BW| ++ NL80211_RRF_DFS| ++ NL80211_RRF_NO_OUTDOOR| ++ 0), ++ REG_RULE_EXT(5470, 5725, 160, 0, 20, 0, NL80211_RRF_DFS| ++ 0), ++ REG_RULE_EXT(5725, 5875, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5945, 6425, 160, 0, 20, 0, NL80211_RRF_NO_OUTDOOR| ++ 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++ ++static const struct ieee80211_regdomain regdom_DK = { ++ .alpha2 = "DK", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_DM = { ++ .alpha2 = "DM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_DO = { ++ .alpha2 = "DO", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_DZ = { ++ .alpha2 = "DZ", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5670, 160, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_EC = { ++ .alpha2 = "EC", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_EE = { ++ .alpha2 = "EE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_EG = { ++ .alpha2 = "EG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_ES = { ++ .alpha2 = "ES", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5470, 5725, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_ET = { ++ .alpha2 = "ET", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_FI = { ++ .alpha2 = "FI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_FM = { ++ .alpha2 = "FM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_FR = { ++ .alpha2 = "FR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5695, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GB = { ++ .alpha2 = "GB", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GD = { ++ .alpha2 = "GD", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GE = { ++ .alpha2 = "GE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 18, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 18, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GF = { ++ .alpha2 = "GF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GH = { ++ .alpha2 = "GH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GL = { ++ .alpha2 = "GL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5710, 80, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GP = { ++ .alpha2 = "GP", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GR = { ++ .alpha2 = "GR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GT = { ++ .alpha2 = "GT", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GU = { ++ .alpha2 = "GU", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GY = { ++ .alpha2 = "GY", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_HK = { ++ .alpha2 = "HK", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HN = { ++ .alpha2 = "HN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HR = { ++ .alpha2 = "HR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HT = { ++ .alpha2 = "HT", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HU = { ++ .alpha2 = "HU", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_ID = { ++ .alpha2 = "ID", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 23, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_IE = { ++ .alpha2 = "IE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_IL = { ++ .alpha2 = "IL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_IN = { ++ .alpha2 = "IN", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_IR = { ++ .alpha2 = "IR", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_IS = { ++ .alpha2 = "IS", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_IT = { ++ .alpha2 = "IT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_JM = { ++ .alpha2 = "JM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_JO = { ++ .alpha2 = "JO", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 23, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_JP = { ++ .alpha2 = "JP", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(2474, 2494, 20, 0, 20, 0, ++ NL80211_RRF_NO_OFDM | 0), ++ REG_RULE_EXT(4910, 4990, 40, 0, 23, 0, 0), ++ REG_RULE_EXT(5030, 5090, 40, 0, 23, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_KE = { ++ .alpha2 = "KE", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, 0), ++ REG_RULE_EXT(5490, 5570, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5775, 40, 0, 23, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_KH = { ++ .alpha2 = "KH", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_KN = { ++ .alpha2 = "KN", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KP = { ++ .alpha2 = "KP", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5630, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KR = { ++ .alpha2 = "KR", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KW = { ++ .alpha2 = "KW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_KY = { ++ .alpha2 = "KY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KZ = { ++ .alpha2 = "KZ", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 1 ++}; ++ ++static const struct ieee80211_regdomain regdom_LB = { ++ .alpha2 = "LB", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LC = { ++ .alpha2 = "LC", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LI = { ++ .alpha2 = "LI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_LK = { ++ .alpha2 = "LK", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LS = { ++ .alpha2 = "LS", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_LT = { ++ .alpha2 = "LT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LU = { ++ .alpha2 = "LU", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LV = { ++ .alpha2 = "LV", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MA = { ++ .alpha2 = "MA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_MC = { ++ .alpha2 = "MC", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MD = { ++ .alpha2 = "MD", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_ME = { ++ .alpha2 = "ME", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MF = { ++ .alpha2 = "MF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MH = { ++ .alpha2 = "MH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MK = { ++ .alpha2 = "MK", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MN = { ++ .alpha2 = "MN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MO = { ++ .alpha2 = "MO", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 40, 0, 23, 0, 0), ++ REG_RULE_EXT(5250, 5330, 40, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 40, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MP = { ++ .alpha2 = "MP", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MQ = { ++ .alpha2 = "MQ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MR = { ++ .alpha2 = "MR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MT = { ++ .alpha2 = "MT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MU = { ++ .alpha2 = "MU", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MW = { ++ .alpha2 = "MW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MX = { ++ .alpha2 = "MX", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MY = { ++ .alpha2 = "MY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_NG = { ++ .alpha2 = "NG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, NL80211_RRF_DFS| ++ 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_NI = { ++ .alpha2 = "NI", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_NL = { ++ .alpha2 = "NL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_NO = { ++ .alpha2 = "NO", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5470, 5795, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5815, 5850, 35, 0, 33, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(17100, 17300, 200, 0, 20, 0, 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_NP = { ++ .alpha2 = "NP", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_NZ = { ++ .alpha2 = "NZ", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_OM = { ++ .alpha2 = "OM", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PA = { ++ .alpha2 = "PA", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PE = { ++ .alpha2 = "PE", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PF = { ++ .alpha2 = "PF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PG = { ++ .alpha2 = "PG", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PH = { ++ .alpha2 = "PH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PK = { ++ .alpha2 = "PK", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_PL = { ++ .alpha2 = "PL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PM = { ++ .alpha2 = "PM", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PR = { ++ .alpha2 = "PR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PT = { ++ .alpha2 = "PT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PW = { ++ .alpha2 = "PW", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PY = { ++ .alpha2 = "PY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_QA = { ++ .alpha2 = "QA", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_RE = { ++ .alpha2 = "RE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_RO = { ++ .alpha2 = "RO", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_RS = { ++ .alpha2 = "RS", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5350, 40, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | 0), ++ REG_RULE_EXT(5470, 5725, 20, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_RU = { ++ .alpha2 = "RU", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5650, 5730, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_RW = { ++ .alpha2 = "RW", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SA = { ++ .alpha2 = "SA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_SE = { ++ .alpha2 = "SE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SG = { ++ .alpha2 = "SG", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SI = { ++ .alpha2 = "SI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SK = { ++ .alpha2 = "SK", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SN = { ++ .alpha2 = "SN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SR = { ++ .alpha2 = "SR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_SV = { ++ .alpha2 = "SV", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_SY = { ++ .alpha2 = "SY", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 1 ++}; ++ ++static const struct ieee80211_regdomain regdom_TC = { ++ .alpha2 = "TC", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TD = { ++ .alpha2 = "TD", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_TG = { ++ .alpha2 = "TG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 40, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5710, 40, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_TH = { ++ .alpha2 = "TH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TN = { ++ .alpha2 = "TN", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_TR = { ++ .alpha2 = "TR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TT = { ++ .alpha2 = "TT", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TW = { ++ .alpha2 = "TW", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5270, 5330, 40, 0, 17, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5590, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5650, 5710, 40, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_UA = { ++ .alpha2 = "UA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | 0), ++ REG_RULE_EXT(5150, 5350, 40, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | 0), ++ REG_RULE_EXT(5490, 5670, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_UG = { ++ .alpha2 = "UG", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_US = { ++ .alpha2 = "US", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ // 1...13 ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ // 36 40 44 48 ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ // 52 56 60 64 ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ // 100 104 108 112 116 120 124 ++ REG_RULE_EXT(5490, 5650, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ // 128 132 136 140 ++ REG_RULE_EXT(5650, 5710, 40, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ // 149 153 157 161 165 ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ REG_RULE_EXT(57240, 63720, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_UY = { ++ .alpha2 = "UY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_UZ = { ++ .alpha2 = "UZ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_VC = { ++ .alpha2 = "VC", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_VE = { ++ .alpha2 = "VE", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_VI = { ++ .alpha2 = "VI", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_VN = { ++ .alpha2 = "VN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_VU = { ++ .alpha2 = "VU", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_WF = { ++ .alpha2 = "WF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_YE = { ++ .alpha2 = "YE", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 1 ++}; ++ ++static const struct ieee80211_regdomain regdom_YT = { ++ .alpha2 = "YT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_ZA = { ++ .alpha2 = "ZA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5695, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ /*REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0),*/ ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_ZW = { ++ .alpha2 = "ZW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++const struct ieee80211_regdomain *reg_regdb[] = { ++ ®dom_00, ++ ®dom_AD, ++ ®dom_AE, ++ ®dom_AF, ++ ®dom_AI, ++ ®dom_AL, ++ ®dom_AM, ++ ®dom_AN, ++ ®dom_AR, ++ ®dom_AS, ++ ®dom_AT, ++ ®dom_AU, ++ ®dom_AW, ++ ®dom_AZ, ++ ®dom_BA, ++ ®dom_BB, ++ ®dom_BD, ++ ®dom_BE, ++ ®dom_BF, ++ ®dom_BG, ++ ®dom_BH, ++ ®dom_BL, ++ ®dom_BM, ++ ®dom_BN, ++ ®dom_BO, ++ ®dom_BR, ++ ®dom_BS, ++ ®dom_BT, ++ ®dom_BY, ++ ®dom_BZ, ++ ®dom_CA, ++ ®dom_CF, ++ ®dom_CH, ++ ®dom_CI, ++ ®dom_CL, ++ ®dom_CN, ++ ®dom_CO, ++ ®dom_CR, ++ ®dom_CX, ++ ®dom_CY, ++ ®dom_CZ, ++ ®dom_DE, ++ ®dom_DK, ++ ®dom_DM, ++ ®dom_DO, ++ ®dom_DZ, ++ ®dom_EC, ++ ®dom_EE, ++ ®dom_EG, ++ ®dom_ES, ++ ®dom_ET, ++ ®dom_FI, ++ ®dom_FM, ++ ®dom_FR, ++ ®dom_GB, ++ ®dom_GD, ++ ®dom_GE, ++ ®dom_GF, ++ ®dom_GH, ++ ®dom_GL, ++ ®dom_GP, ++ ®dom_GR, ++ ®dom_GT, ++ ®dom_GU, ++ ®dom_GY, ++ ®dom_HK, ++ ®dom_HN, ++ ®dom_HR, ++ ®dom_HT, ++ ®dom_HU, ++ ®dom_ID, ++ ®dom_IE, ++ ®dom_IL, ++ ®dom_IN, ++ ®dom_IR, ++ ®dom_IS, ++ ®dom_IT, ++ ®dom_JM, ++ ®dom_JO, ++ ®dom_JP, ++ ®dom_KE, ++ ®dom_KH, ++ ®dom_KN, ++ ®dom_KP, ++ ®dom_KR, ++ ®dom_KW, ++ ®dom_KY, ++ ®dom_KZ, ++ ®dom_LB, ++ ®dom_LC, ++ ®dom_LI, ++ ®dom_LK, ++ ®dom_LS, ++ ®dom_LT, ++ ®dom_LU, ++ ®dom_LV, ++ ®dom_MA, ++ ®dom_MC, ++ ®dom_MD, ++ ®dom_ME, ++ ®dom_MF, ++ ®dom_MH, ++ ®dom_MK, ++ ®dom_MN, ++ ®dom_MO, ++ ®dom_MP, ++ ®dom_MQ, ++ ®dom_MR, ++ ®dom_MT, ++ ®dom_MU, ++ ®dom_MW, ++ ®dom_MX, ++ ®dom_MY, ++ ®dom_NG, ++ ®dom_NI, ++ ®dom_NL, ++ ®dom_NO, ++ ®dom_NP, ++ ®dom_NZ, ++ ®dom_OM, ++ ®dom_PA, ++ ®dom_PE, ++ ®dom_PF, ++ ®dom_PG, ++ ®dom_PH, ++ ®dom_PK, ++ ®dom_PL, ++ ®dom_PM, ++ ®dom_PR, ++ ®dom_PT, ++ ®dom_PW, ++ ®dom_PY, ++ ®dom_QA, ++ ®dom_RE, ++ ®dom_RO, ++ ®dom_RS, ++ ®dom_RU, ++ ®dom_RW, ++ ®dom_SA, ++ ®dom_SE, ++ ®dom_SG, ++ ®dom_SI, ++ ®dom_SK, ++ ®dom_SN, ++ ®dom_SR, ++ ®dom_SV, ++ ®dom_SY, ++ ®dom_TC, ++ ®dom_TD, ++ ®dom_TG, ++ ®dom_TH, ++ ®dom_TN, ++ ®dom_TR, ++ ®dom_TT, ++ ®dom_TW, ++ ®dom_UA, ++ ®dom_UG, ++ ®dom_US, ++ ®dom_UY, ++ ®dom_UZ, ++ ®dom_VC, ++ ®dom_VE, ++ ®dom_VI, ++ ®dom_VN, ++ ®dom_VU, ++ ®dom_WF, ++ ®dom_YE, ++ ®dom_YT, ++ ®dom_ZA, ++ ®dom_ZW, ++ NULL, ++}; ++ ++int reg_regdb_size = ARRAY_SIZE(reg_regdb); ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c +new file mode 100644 +index 000000000000..b39cf0f205a3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c +@@ -0,0 +1,105 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_bfmer.c ++ * ++ * @brief VHT Beamformer function definitions ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++/** ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++ ++#include ++#include "rwnx_bfmer.h" ++ ++/** ++ * FUNCTION DEFINITIONS ++ ****************************************************************************** ++ */ ++ ++int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ unsigned int length) ++{ ++ gfp_t flags; ++ struct rwnx_bfmer_report *bfm_report ; ++ ++ if (in_softirq()) ++ flags = GFP_ATOMIC; ++ else ++ flags = GFP_KERNEL; ++ ++ /* Allocate a structure that will contain the beamforming report */ ++ bfm_report = kmalloc(sizeof(*bfm_report) + length, flags); ++ ++ ++ /* Check report allocation */ ++ if (!bfm_report) { ++ /* Do not use beamforming */ ++ return -1; ++ } ++ ++ /* Store report length */ ++ bfm_report->length = length; ++ ++ /* ++ * Need to provide a Virtual Address to the MAC so that it can ++ * upload the received Beamforming Report in driver memory ++ */ ++ bfm_report->dma_addr = dma_map_single(rwnx_hw->dev, &bfm_report->report[0], ++ length, DMA_FROM_DEVICE); ++ ++ /* Check DMA mapping result */ ++ if (dma_mapping_error(rwnx_hw->dev, bfm_report->dma_addr)) { ++ /* Free allocated report */ ++ kfree(bfm_report); ++ /* And leave */ ++ return -1; ++ } ++ ++ /* Store report structure */ ++ rwnx_sta->bfm_report = bfm_report; ++ ++ return 0; ++} ++ ++void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) ++{ ++ /* Verify if a report has been allocated */ ++ if (rwnx_sta->bfm_report) { ++ struct rwnx_bfmer_report *bfm_report = rwnx_sta->bfm_report; ++ ++ /* Unmap DMA region */ ++ dma_unmap_single(rwnx_hw->dev, bfm_report->dma_addr, ++ bfm_report->length, DMA_BIDIRECTIONAL); ++ ++ /* Free allocated report structure and clean the pointer */ ++ kfree(bfm_report); ++ rwnx_sta->bfm_report = NULL; ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa) ++{ ++ int i; ++ u8 rx_nss = 0; ++ u16 rx_mcs_map = le16_to_cpu(vht_capa->supp_mcs.rx_mcs_map); ++ ++ for (i = 7; i >= 0; i--) { ++ u8 mcs = (rx_mcs_map >> (2 * i)) & 3; ++ ++ if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) { ++ rx_nss = i + 1; ++ break; ++ } ++ } ++ ++ return rx_nss; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h +new file mode 100644 +index 000000000000..4ce16496ef2e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h +@@ -0,0 +1,100 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_bfmer.h ++ * ++ * @brief VHT Beamformer function declarations ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_BFMER_H_ ++#define _RWNX_BFMER_H_ ++ ++/** ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++ ++/** ++ * DEFINES ++ ****************************************************************************** ++ */ ++ ++/// Maximal supported report length (in bytes) ++#define RWNX_BFMER_REPORT_MAX_LEN 2048 ++ ++/// Size of the allocated report space (twice the maximum report length) ++#define RWNX_BFMER_REPORT_SPACE_SIZE (RWNX_BFMER_REPORT_MAX_LEN * 2) ++ ++/** ++ * TYPE DEFINITIONS ++ ****************************************************************************** ++ */ ++ ++/* ++ * Structure used to store a beamforming report. ++ */ ++struct rwnx_bfmer_report { ++ dma_addr_t dma_addr; /* Virtual address provided to MAC for ++ DMA transfer of the Beamforming Report */ ++ unsigned int length; /* Report Length */ ++ u8 report[1]; /* Report to be used for VHT TX Beamforming */ ++}; ++ ++/** ++ * FUNCTION DECLARATIONS ++ ****************************************************************************** ++ */ ++ ++/** ++ ****************************************************************************** ++ * @brief Allocate memory aiming to contains the Beamforming Report received ++ * from a Beamformee capable capable. ++ * The providing length shall be large enough to contain the VHT Compressed ++ * Beaforming Report and the MU Exclusive part. ++ * It also perform a DMA Mapping providing an address to be provided to the HW ++ * responsible for the DMA transfer of the report. ++ * If successful a struct rwnx_bfmer_report object is allocated, it's address ++ * is stored in rwnx_sta->bfm_report. ++ * ++ * @param[in] rwnx_hw PHY Information ++ * @param[in] rwnx_sta Peer STA Information ++ * @param[in] length Memory size to be allocated ++ * ++ * @return 0 if operation is successful, else -1. ++ ****************************************************************************** ++ */ ++int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ unsigned int length); ++ ++/** ++ ****************************************************************************** ++ * @brief Free a previously allocated memory intended to be used for ++ * Beamforming Reports. ++ * ++ * @param[in] rwnx_hw PHY Information ++ * @param[in] rwnx_sta Peer STA Information ++ * ++ ****************************************************************************** ++ */ ++void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/** ++ ****************************************************************************** ++ * @brief Parse a Rx VHT-MCS map in order to deduce the maximum number of ++ * Spatial Streams supported by a beamformee. ++ * ++ * @param[in] vht_capa Received VHT Capability field. ++ * ++ ****************************************************************************** ++ */ ++u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#endif /* _RWNX_BFMER_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c +new file mode 100644 +index 000000000000..39a5a251482a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c +@@ -0,0 +1,239 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_configparse.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_cfgfile.h" ++ ++/** ++ * ++ */ ++static const char *rwnx_find_tag(const u8 *file_data, unsigned int file_size, ++ const char *tag_name, unsigned int tag_len) ++{ ++ unsigned int curr, line_start = 0, line_size; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Walk through all the lines of the configuration file */ ++ while (line_start < file_size) { ++ /* Search the end of the current line (or the end of the file) */ ++ for (curr = line_start; curr < file_size; curr++) ++ if (file_data[curr] == '\n') ++ break; ++ ++ /* Compute the line size */ ++ line_size = curr - line_start; ++ ++ /* Check if this line contains the expected tag */ ++ if ((line_size == (strlen(tag_name) + tag_len)) && ++ (!strncmp(&file_data[line_start], tag_name, strlen(tag_name)))) ++ return &file_data[line_start + strlen(tag_name)]; ++ ++ /* Move to next line */ ++ line_start = curr + 1; ++ } ++ ++ /* Tag not found */ ++ return NULL; ++} ++ ++/** ++ * Parse the Config file used at init time ++ */ ++int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_conf_file *config) ++{ ++ const struct firmware *config_fw; ++ u8 dflt_mac[ETH_ALEN] = { 0, 111, 111, 111, 111, 0 }; ++ int ret; ++ const u8 *tag_ptr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ret = request_firmware(&config_fw, filename, rwnx_hw->dev); ++ if (ret) { ++ printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); ++ return ret; ++ } ++ ++ /* Get MAC Address */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "MAC_ADDR=", strlen("00:00:00:00:00:00")); ++ if (tag_ptr != NULL) { ++ u8 *addr = config->mac_addr; ++ if (sscanf(tag_ptr, ++ "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ addr + 0, addr + 1, addr + 2, ++ addr + 3, addr + 4, addr + 5) != ETH_ALEN) ++ memcpy(config->mac_addr, dflt_mac, ETH_ALEN); ++ } else ++ memcpy(config->mac_addr, dflt_mac, ETH_ALEN); ++ ++ RWNX_DBG("MAC Address is:\n%pM\n", config->mac_addr); ++ ++ /* Release the configuration file */ ++ release_firmware(config_fw); ++ ++ return 0; ++} ++ ++/** ++ * Parse the Config file used at init time ++ */ ++int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_phy_conf_file *config, int path) ++{ ++ const struct firmware *config_fw; ++ int ret; ++ const u8 *tag_ptr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ret = request_firmware(&config_fw, filename, rwnx_hw->dev); ++ if (ret) { ++ printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); ++ return ret; ++ } ++ ++ /* Get Trident path mapping */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "TRD_PATH_MAPPING=", strlen("00")); ++ if (tag_ptr != NULL) { ++ u8 val; ++ if (sscanf(tag_ptr, "%hhx", &val) == 1) ++ config->trd.path_mapping = val; ++ else ++ config->trd.path_mapping = path; ++ } else ++ config->trd.path_mapping = path; ++ ++ RWNX_DBG("Trident path mapping is: %d\n", config->trd.path_mapping); ++ ++ /* Get DC offset compensation */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "TX_DC_OFF_COMP=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->trd.tx_dc_off_comp) != 1) ++ config->trd.tx_dc_off_comp = 0; ++ } else ++ config->trd.tx_dc_off_comp = 0; ++ ++ RWNX_DBG("TX DC offset compensation is: %08X\n", config->trd.tx_dc_off_comp); ++ ++ /* Get Karst TX IQ compensation value for path0 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[0]) != 1) ++ config->karst.tx_iq_comp_2_4G[0] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_2_4G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[0]); ++ ++ /* Get Karst TX IQ compensation value for path1 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[1]) != 1) ++ config->karst.tx_iq_comp_2_4G[1] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_2_4G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[1]); ++ ++ /* Get Karst RX IQ compensation value for path0 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[0]) != 1) ++ config->karst.rx_iq_comp_2_4G[0] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_2_4G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[0]); ++ ++ /* Get Karst RX IQ compensation value for path1 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[1]) != 1) ++ config->karst.rx_iq_comp_2_4G[1] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_2_4G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[1]); ++ ++ /* Get Karst TX IQ compensation value for path0 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_5G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[0]) != 1) ++ config->karst.tx_iq_comp_5G[0] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_5G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[0]); ++ ++ /* Get Karst TX IQ compensation value for path1 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_5G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[1]) != 1) ++ config->karst.tx_iq_comp_5G[1] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_5G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[1]); ++ ++ /* Get Karst RX IQ compensation value for path0 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_5G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[0]) != 1) ++ config->karst.rx_iq_comp_5G[0] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_5G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[0]); ++ ++ /* Get Karst RX IQ compensation value for path1 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_5G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[1]) != 1) ++ config->karst.rx_iq_comp_5G[1] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_5G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[1]); ++ ++ /* Get Karst default path */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_DEFAULT_PATH=", strlen("00")); ++ if (tag_ptr != NULL) { ++ u8 val; ++ if (sscanf(tag_ptr, "%hhx", &val) == 1) ++ config->karst.path_used = val; ++ else ++ config->karst.path_used = path; ++ } else ++ config->karst.path_used = path; ++ ++ RWNX_DBG("Karst default path is: %d\n", config->karst.path_used); ++ ++ /* Release the configuration file */ ++ release_firmware(config_fw); ++ ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h +new file mode 100644 +index 000000000000..7dc96fe5862b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h +@@ -0,0 +1,35 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_cfgfile.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_CFGFILE_H_ ++#define _RWNX_CFGFILE_H_ ++ ++/* ++ * Structure used to retrieve information from the Config file used at Initialization time ++ */ ++struct rwnx_conf_file { ++ u8 mac_addr[ETH_ALEN]; ++}; ++ ++/* ++ * Structure used to retrieve information from the PHY Config file used at Initialization time ++ */ ++struct rwnx_phy_conf_file { ++ struct phy_trd_cfg_tag trd; ++ struct phy_karst_cfg_tag karst; ++}; ++ ++int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_conf_file *config); ++ ++int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_phy_conf_file *config, int path); ++ ++#endif /* _RWNX_CFGFILE_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c +new file mode 100644 +index 000000000000..cdbe42c3f14c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c +@@ -0,0 +1,586 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.c ++ * ++ * Handles queueing (push to IPC, ack/cfm from IPC) of commands issued to ++ * LMAC FW ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++ ++#include "rwnx_cmds.h" ++#include "rwnx_defs.h" ++#include "rwnx_strs.h" ++//#define CREATE_TRACE_POINTS ++#include "rwnx_events.h" ++#include "aicwf_txrxif.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#else ++#include "aicwf_usb.h" ++#endif ++/** ++ * ++ */ ++extern int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++ ++void rwnx_cmd_free(struct rwnx_cmd *cmd); ++ ++static void cmd_dump(const struct rwnx_cmd *cmd) ++{ ++ printk(KERN_CRIT "tkn[%d] flags:%04x result:%3d cmd:%4d-%-24s - reqcfm(%4d-%-s)\n", ++ cmd->tkn, cmd->flags, cmd->result, cmd->id, RWNX_ID2STR(cmd->id), ++ cmd->reqid, cmd->reqid != (lmac_msg_id_t)-1 ? RWNX_ID2STR(cmd->reqid) : "none"); ++} ++ ++/** ++ * ++ */ ++static void cmd_complete(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ lockdep_assert_held(&cmd_mgr->lock); ++ ++ //list_del(&cmd->list); ++ //cmd_mgr->queue_sz--; ++ ++ cmd->flags |= RWNX_CMD_FLAG_DONE; ++ if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) { ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ } else { ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) { ++ cmd->result = 0; ++ complete(&cmd->complete); ++ } ++ } ++} ++ ++int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ bool defer_push = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef CREATE_TRACE_POINTS ++ trace_msg_send(cmd->id); ++#endif ++ spin_lock_bh(&cmd_mgr->lock); ++ ++ if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { ++ printk(KERN_CRIT"cmd queue crashed\n"); ++ cmd->result = -EPIPE; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EPIPE; ++ } ++ ++ #ifndef CONFIG_RWNX_FHOST ++ if (!list_empty(&cmd_mgr->cmds)) { ++ if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) { ++ printk(KERN_CRIT"Too many cmds (%d) already queued\n", ++ cmd_mgr->max_queue_sz); ++ cmd->result = -ENOMEM; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -ENOMEM; ++ } ++ } ++ #endif ++ ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ defer_push = true; ++ ++ if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM) ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM; ++ ++ cmd->tkn = cmd_mgr->next_tkn++; ++ cmd->result = -EINTR; ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ init_completion(&cmd->complete); ++ ++ list_add_tail(&cmd->list, &cmd_mgr->cmds); ++ cmd_mgr->queue_sz++; ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ WAKE_CMD_WORK(cmd_mgr); ++ return 0; ++} ++ ++#if 1 ++static void aic8800_start_system_reset_flow(struct aic_sdio_dev *aic) ++{ ++ int ret = 0; ++ char *event_string = "DHDISDOWN=1"; ++ char *envp[] = { event_string, NULL }; ++ printk(KERN_ERR "wlan error reset flow.\n"); ++ printk(KERN_ERR "send event.\n"); ++ ret=kobject_uevent_env(&aic->dev->kobj, KOBJ_CHANGE,envp); ++ if(!ret) ++ printk(KERN_ERR "wlan error event send.\n"); ++} ++#endif ++ ++static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ int ret; ++ struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); ++#endif ++ bool defer_push = false; ++ u8_l empty = 0; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef CREATE_TRACE_POINTS ++ trace_msg_send(cmd->id); ++#endif ++ if(cmd->e2a_msg != NULL) { ++ do { ++ if(cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) ++ break; ++ spin_lock_bh(&cmd_mgr->lock); ++ empty = list_empty(&cmd_mgr->cmds); ++ if(!empty) { ++ spin_unlock_bh(&cmd_mgr->lock); ++ if(in_softirq()) { ++ printk("in_softirq:check cmdqueue empty\n"); ++ mdelay(10); ++ } else { ++ printk("check cmdqueue empty\n"); ++ msleep(50); ++ } ++ } ++ } while(!empty);//wait for cmd queue empty ++ } else { ++ spin_lock_bh(&cmd_mgr->lock); ++ } ++ ++ if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { ++ printk(KERN_CRIT"cmd queue crashed\n"); ++ cmd->result = -EPIPE; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EPIPE; ++ } ++ ++ #ifndef CONFIG_RWNX_FHOST ++ if (!list_empty(&cmd_mgr->cmds)) { ++ struct rwnx_cmd *last; ++ ++ if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) { ++ printk(KERN_CRIT"Too many cmds (%d) already queued\n", ++ cmd_mgr->max_queue_sz); ++ cmd->result = -ENOMEM; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -ENOMEM; ++ } ++ last = list_entry(cmd_mgr->cmds.prev, struct rwnx_cmd, list); ++ if (last->flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_PUSH | RWNX_CMD_FLAG_WAIT_CFM)) { ++#if 0 // queue even NONBLOCK command. ++ if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) { ++ printk(KERN_CRIT"cmd queue busy\n"); ++ cmd->result = -EBUSY; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EBUSY; ++ } ++#endif ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ defer_push = true; ++ } ++ } ++ #endif ++ ++#if 0 ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_ACK; ++#endif ++ if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM) ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM; ++ ++ cmd->tkn = cmd_mgr->next_tkn++; ++ cmd->result = -EINTR; ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ init_completion(&cmd->complete); ++ ++ list_add_tail(&cmd->list, &cmd_mgr->cmds); ++ cmd_mgr->queue_sz++; ++ ++ if (cmd->a2e_msg->id == ME_TRAFFIC_IND_REQ ++ #ifdef AICWF_ARP_OFFLOAD ++ || cmd->a2e_msg->id == MM_SET_ARPOFFLOAD_REQ ++ #endif ++ ) { ++ defer_push = true; ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ //printk("defer push: tkn=%d\r\n", cmd->tkn); ++ } ++ ++ spin_unlock_bh(&cmd_mgr->lock); ++ if (!defer_push) { ++ //printk("queue:id=%x, param_len=%u\n",cmd->a2e_msg->id, cmd->a2e_msg->param_len); ++ #ifdef AICWF_SDIO_SUPPORT ++ aicwf_set_cmd_tx((void *)(sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ #else ++ aicwf_set_cmd_tx((void *)(usbdev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ #endif ++ //rwnx_ipc_msg_push(rwnx_hw, cmd, RWNX_CMD_A2EMSG_LEN(cmd->a2e_msg)); ++ ++ kfree(cmd->a2e_msg); ++ } else { ++ if(cmd_mgr->queue_sz <= 1){ ++ WAKE_CMD_WORK(cmd_mgr); ++ } ++ return 0; ++ } ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) { ++ #ifdef CONFIG_RWNX_FHOST ++ if (wait_for_completion_killable(&cmd->complete)) { ++ cmd->result = -EINTR; ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_complete(cmd_mgr, cmd); ++ spin_unlock_bh(&cmd_mgr->lock); ++ /* TODO: kill the cmd at fw level */ ++ } ++ #else ++ unsigned long tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz); ++ if (!wait_for_completion_timeout(&cmd->complete, tout)) { ++ printk(KERN_CRIT"cmd timed-out\n"); ++ #ifdef AICWF_SDIO_SUPPORT ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++ #endif ++ ++ aic8800_start_system_reset_flow(sdiodev); ++ ++ cmd_dump(cmd); ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED; ++ if (!(cmd->flags & RWNX_CMD_FLAG_DONE)) { ++ cmd->result = -ETIMEDOUT; ++ cmd_complete(cmd_mgr, cmd); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ } else { ++ spin_lock_bh(&cmd_mgr->lock); ++ list_del(&cmd->list); ++ cmd_mgr->queue_sz--; ++ spin_unlock_bh(&cmd_mgr->lock); ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ if (!list_empty(&cmd_mgr->cmds)) ++ WAKE_CMD_WORK(cmd_mgr); ++ } ++ #endif ++ } else { ++ cmd->result = 0; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ++ */ ++static int cmd_mgr_llind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ struct rwnx_cmd *cur, *acked = NULL, *next = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ if (!acked) { ++ if (cur->tkn == cmd->tkn) { ++ if (WARN_ON_ONCE(cur != cmd)) { ++ cmd_dump(cmd); ++ } ++ acked = cur; ++ continue; ++ } ++ } ++ if (cur->flags & RWNX_CMD_FLAG_WAIT_PUSH) { ++ next = cur; ++ break; ++ } ++ } ++ if (!acked) { ++ printk(KERN_CRIT "Error: acked cmd not found\n"); ++ } else { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) ++ cmd_complete(cmd_mgr, cmd); ++ } ++ ++ if (next) { ++ #if 0 //there is no ack ++ struct rwnx_hw *rwnx_hw = container_of(cmd_mgr, struct rwnx_hw, cmd_mgr); ++ next->flags &= ~RWNX_CMD_FLAG_WAIT_PUSH; ++ rwnx_ipc_msg_push(rwnx_hw, next, RWNX_CMD_A2EMSG_LEN(next->a2e_msg)); ++ kfree(next->a2e_msg); ++ #endif ++ } ++ spin_unlock(&cmd_mgr->lock); ++ ++ return 0; ++} ++ ++void cmd_mgr_task_process(struct work_struct *work) ++{ ++ struct rwnx_cmd_mgr *cmd_mgr = container_of(work, struct rwnx_cmd_mgr, cmdWork); ++ struct rwnx_cmd *cur, *next = NULL; ++ unsigned long tout; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ while (1) { ++ next = NULL; ++ spin_lock_bh(&cmd_mgr->lock); ++ ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ if (cur->flags & RWNX_CMD_FLAG_WAIT_PUSH) { //just judge the first ++ next = cur; ++ } ++ break; ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ if (next == NULL) ++ break; ++ ++ if (next) { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); ++#endif ++ next->flags &= ~RWNX_CMD_FLAG_WAIT_PUSH; ++ ++ //printk("cmd_process, cmd->id=%d, tkn=%d\r\n",next->reqid, next->tkn); ++ //rwnx_ipc_msg_push(rwnx_hw, next, RWNX_CMD_A2EMSG_LEN(next->a2e_msg)); ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_set_cmd_tx((void *)(sdiodev), next->a2e_msg, sizeof(struct lmac_msg) + next->a2e_msg->param_len); ++#else ++ aicwf_set_cmd_tx((void *)(usbdev), next->a2e_msg, sizeof(struct lmac_msg) + next->a2e_msg->param_len); ++#endif ++ kfree(next->a2e_msg); ++ ++ tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz); ++ if (!wait_for_completion_timeout(&next->complete, tout)) { ++ printk(KERN_CRIT"cmd timed-out\n"); ++#ifdef AICWF_SDIO_SUPPORT ++ if (aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 2) < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++#endif ++ aic8800_start_system_reset_flow(sdiodev); ++ ++ cmd_dump(next); ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED; ++ if (!(next->flags & RWNX_CMD_FLAG_DONE)) { ++ next->result = -ETIMEDOUT; ++ cmd_complete(cmd_mgr, next); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ } else { ++ spin_lock_bh(&cmd_mgr->lock); ++ list_del(&next->list); ++ cmd_mgr->queue_sz--; ++ spin_unlock_bh(&cmd_mgr->lock); ++ rwnx_cmd_free(next);//kfree(next); ++ } ++ } ++ } ++ ++} ++ ++ ++static int cmd_mgr_run_callback(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd, ++ struct rwnx_cmd_e2amsg *msg, msg_cb_fct cb) ++{ ++ int res; ++ ++ if (!cb) { ++ return 0; ++ } ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ //spin_lock_bh(&rwnx_hw->cb_lock); ++ res = cb(rwnx_hw, cmd, msg); ++ //spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ return res; ++} ++ ++/** ++ * ++ ++ */ ++static int cmd_mgr_msgind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd_e2amsg *msg, ++ msg_cb_fct cb) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); ++ struct rwnx_hw *rwnx_hw = sdiodev->rwnx_hw; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); ++ struct rwnx_hw *rwnx_hw = usbdev->rwnx_hw; ++#endif ++ struct rwnx_cmd *cmd, *pos; ++ bool found = false; ++ ++ // RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef CREATE_TRACE_POINTS ++ trace_msg_recv(msg->id); ++#endif ++ //printk("cmd->id=%x\n", msg->id); ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry_safe(cmd, pos, &cmd_mgr->cmds, list) { ++ if (cmd->reqid == msg->id && ++ (cmd->flags & RWNX_CMD_FLAG_WAIT_CFM)) { ++ ++ if (!cmd_mgr_run_callback(rwnx_hw, cmd, msg, cb)) { ++ found = true; ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_CFM; ++ ++ if (WARN((msg->param_len > RWNX_CMD_E2AMSG_LEN_MAX), ++ "Unexpect E2A msg len %d > %d\n", msg->param_len, ++ RWNX_CMD_E2AMSG_LEN_MAX)) { ++ msg->param_len = RWNX_CMD_E2AMSG_LEN_MAX; ++ } ++ ++ if (cmd->e2a_msg && msg->param_len) ++ memcpy(cmd->e2a_msg, &msg->param, msg->param_len); ++ ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) ++ cmd_complete(cmd_mgr, cmd); ++ ++ break; ++ } ++ } ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ if (!found) ++ cmd_mgr_run_callback(rwnx_hw, NULL, msg, cb); ++ ++ return 0; ++} ++ ++/** ++ * ++ */ ++static void cmd_mgr_print(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ RWNX_DBG("q_sz/max: %2d / %2d - next tkn: %d\n", ++ cmd_mgr->queue_sz, cmd_mgr->max_queue_sz, ++ cmd_mgr->next_tkn); ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ cmd_dump(cur); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++static void cmd_mgr_drain(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur, *nxt; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry_safe(cur, nxt, &cmd_mgr->cmds, list) { ++ list_del(&cur->list); ++ cmd_mgr->queue_sz--; ++ if (!(cur->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ complete(&cur->complete); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ INIT_LIST_HEAD(&cmd_mgr->cmds); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_INITED; ++ spin_lock_init(&cmd_mgr->lock); ++ cmd_mgr->max_queue_sz = RWNX_CMD_MAX_QUEUED; ++ cmd_mgr->queue = &cmd_mgr_queue; ++ cmd_mgr->print = &cmd_mgr_print; ++ cmd_mgr->drain = &cmd_mgr_drain; ++ cmd_mgr->llind = &cmd_mgr_llind; ++ cmd_mgr->msgind = &cmd_mgr_msgind; ++ ++ INIT_WORK(&cmd_mgr->cmdWork, cmd_mgr_task_process); ++ cmd_mgr->cmd_wq = create_singlethread_workqueue("cmd_wq"); ++ if (!cmd_mgr->cmd_wq) { ++ txrx_err("insufficient memory to create cmd workqueue.\n"); ++ return; ++ } ++} ++ ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ cmd_mgr->print(cmd_mgr); ++ cmd_mgr->drain(cmd_mgr); ++ cmd_mgr->print(cmd_mgr); ++ flush_workqueue(cmd_mgr->cmd_wq); ++ destroy_workqueue(cmd_mgr->cmd_wq); ++ memset(cmd_mgr, 0, sizeof(*cmd_mgr)); ++} ++ ++void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len) ++{ ++ u8 *buffer = NULL; ++ u16 index = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ struct aicwf_bus *bus = sdiodev->bus_if; ++#else ++ struct aic_usb_dev *usbdev = (struct aic_usb_dev *)dev; ++ struct aicwf_bus *bus = NULL; ++ if (!usbdev->state) { ++ printk("down msg \n"); ++ return; ++ } ++ bus = usbdev->bus_if; ++#endif ++ buffer = bus->cmd_buf; ++ ++ memset(buffer, 0, CMD_BUF_MAX); ++ buffer[0] = (len+4) & 0x00ff; ++ buffer[1] = ((len+4) >> 8) &0x0f; ++ buffer[2] = 0x11; ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ buffer[3] = 0x0; ++ else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ buffer[3] = crc8_ponl_107(&buffer[0], 3); // crc8 ++ index += 4; ++ //there is a dummy word ++ index += 4; ++ ++ //make sure little endian ++ put_u16(&buffer[index], msg->id); ++ index += 2; ++ put_u16(&buffer[index], msg->dest_id); ++ index += 2; ++ put_u16(&buffer[index], msg->src_id); ++ index += 2; ++ put_u16(&buffer[index], msg->param_len); ++ index += 2; ++ memcpy(&buffer[index], (u8 *)msg->param, msg->param_len); ++ ++ aicwf_bus_txmsg(bus, buffer, len + 8); ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h +new file mode 100644 +index 000000000000..d1ba11994193 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h +@@ -0,0 +1,124 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.h ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_CMDS_H_ ++#define _RWNX_CMDS_H_ ++ ++#include ++#include ++#include ++#include "lmac_msg.h" ++ ++#ifdef CONFIG_RWNX_SDM ++#define RWNX_80211_CMD_TIMEOUT_MS (20 * 300) ++#elif defined(CONFIG_RWNX_FHOST) ++#define RWNX_80211_CMD_TIMEOUT_MS (10000) ++#else ++#ifdef AICWF_USB_SUPPORT ++#define RWNX_80211_CMD_TIMEOUT_MS 2000//300 ++#else ++#define RWNX_80211_CMD_TIMEOUT_MS 6000//500//300 ++#endif ++#endif ++ ++#define RWNX_CMD_FLAG_NONBLOCK BIT(0) ++#define RWNX_CMD_FLAG_REQ_CFM BIT(1) ++#define RWNX_CMD_FLAG_WAIT_PUSH BIT(2) ++#define RWNX_CMD_FLAG_WAIT_ACK BIT(3) ++#define RWNX_CMD_FLAG_WAIT_CFM BIT(4) ++#define RWNX_CMD_FLAG_DONE BIT(5) ++/* ATM IPC design makes it possible to get the CFM before the ACK, ++ * otherwise this could have simply been a state enum */ ++#define RWNX_CMD_WAIT_COMPLETE(flags) \ ++ (!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM))) ++ ++#define RWNX_CMD_MAX_QUEUED 16 ++ ++#ifdef CONFIG_RWNX_FHOST ++#include "ipc_fhost.h" ++#define rwnx_cmd_e2amsg ipc_fhost_msg ++#define rwnx_cmd_a2emsg ipc_fhost_msg ++#define RWNX_CMD_A2EMSG_LEN(m) (m->param_len) ++#define RWNX_CMD_E2AMSG_LEN_MAX IPC_FHOST_MSG_BUF_SIZE ++struct rwnx_term_stream; ++ ++#else /* !CONFIG_RWNX_FHOST*/ ++#include "ipc_shared.h" ++#define rwnx_cmd_e2amsg ipc_e2a_msg ++#define rwnx_cmd_a2emsg lmac_msg ++#define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len) ++#define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4) ++ ++#endif /* CONFIG_RWNX_FHOST*/ ++ ++struct rwnx_hw; ++struct rwnx_cmd; ++typedef int (*msg_cb_fct)(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd, ++ struct rwnx_cmd_e2amsg *msg); ++static inline void put_u16(u8 *buf, u16 data) ++{ ++ buf[0] = (u8)(data&0x00ff); ++ buf[1] = (u8)((data >> 8)&0x00ff); ++} ++ ++enum rwnx_cmd_mgr_state { ++ RWNX_CMD_MGR_STATE_DEINIT, ++ RWNX_CMD_MGR_STATE_INITED, ++ RWNX_CMD_MGR_STATE_CRASHED, ++}; ++ ++struct rwnx_cmd { ++ struct list_head list; ++ lmac_msg_id_t id; ++ lmac_msg_id_t reqid; ++ struct rwnx_cmd_a2emsg *a2e_msg; ++ char *e2a_msg; ++ u32 tkn; ++ u16 flags; ++ ++ struct completion complete; ++ u32 result; ++ u8 used; ++ int array_id; ++ #ifdef CONFIG_RWNX_FHOST ++ struct rwnx_term_stream *stream; ++ #endif ++}; ++ ++struct rwnx_cmd_mgr { ++ enum rwnx_cmd_mgr_state state; ++ spinlock_t lock; ++ u32 next_tkn; ++ u32 queue_sz; ++ u32 max_queue_sz; ++ ++ struct list_head cmds; ++ ++ int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct); ++ void (*print)(struct rwnx_cmd_mgr *); ++ void (*drain)(struct rwnx_cmd_mgr *); ++ ++ struct work_struct cmdWork; ++ struct workqueue_struct *cmd_wq; ++}; ++ ++#define WAKE_CMD_WORK(cmd_mgr) \ ++ do { \ ++ queue_work((cmd_mgr)->cmd_wq, &cmd_mgr->cmdWork); \ ++ } while (0) ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr); ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr); ++int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd); ++void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len); ++ ++#endif /* _RWNX_CMDS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h +new file mode 100644 +index 000000000000..49f5cdd032a2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h +@@ -0,0 +1,448 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_compat.h ++ * ++ * Ensure driver compilation for linux 3.16 to 3.19 ++ * ++ * To avoid too many #if LINUX_VERSION_CODE if the code, when prototype change ++ * between different kernel version: ++ * - For external function, define a macro whose name is the function name with ++ * _compat suffix and prototype (actually the number of parameter) of the ++ * latest version. Then latest version this macro simply call the function ++ * and for older kernel version it call the function adapting the api. ++ * - For internal function (e.g. cfg80211_ops) do the same but the macro name ++ * doesn't need to have the _compat suffix when the function is not used ++ * directly by the driver ++ * ++ * Copyright (C) RivieraWaves 2018 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_COMPAT_H_ ++#define _RWNX_COMPAT_H_ ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) ++#error "Minimum kernel version supported is 3.10" ++#endif ++ ++/* Generic */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) ++#define __bf_shf(x) (__builtin_ffsll(x) - 1) ++#define FIELD_PREP(_mask, _val) \ ++ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) ++#else ++#include ++#endif ++ ++/* CFG80211 */ ++ ++//because android kernel 5.15 uses kernel 6.0 or 6.1 kernel api ++#ifdef ANDROID_PLATFORM ++#define HIGH_KERNEL_VERSION KERNEL_VERSION(5, 15, 41) ++#define HIGH_KERNEL_VERSION2 KERNEL_VERSION(5, 15, 41) ++#define HIGH_KERNEL_VERSION3 KERNEL_VERSION(5, 15, 104) ++#define HIGH_KERNEL_VERSION4 KERNEL_VERSION(6, 1, 0) ++#else ++#define HIGH_KERNEL_VERSION KERNEL_VERSION(6, 0, 0) ++#define HIGH_KERNEL_VERSION2 KERNEL_VERSION(6, 1, 0) ++#define HIGH_KERNEL_VERSION3 KERNEL_VERSION(6, 3, 0) ++#define HIGH_KERNEL_VERSION4 KERNEL_VERSION(6, 3, 0) ++#endif ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 60) ++#define IEEE80211_MAX_AMPDU_BUF IEEE80211_MAX_AMPDU_BUF_HE ++#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB ++#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB ++#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU ++#endif ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) ++#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_MASK ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define IEEE80211_RADIOTAP_HE 23 ++#define IEEE80211_RADIOTAP_HE_MU 24 ++ ++struct ieee80211_radiotap_he { ++ __le16 data1, data2, data3, data4, data5, data6; ++}; ++ ++enum ieee80211_radiotap_he_bits { ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3, ++ ++ IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004, ++ IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008, ++ IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010, ++ IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020, ++ IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040, ++ IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080, ++ IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100, ++ IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000, ++ IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001, ++ IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002, ++ IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004, ++ IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008, ++ IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010, ++ IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020, ++ IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040, ++ IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080, ++ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00, ++ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f, ++ IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040, ++ IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080, ++ IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00, ++ IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000, ++ IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000, ++ IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000, ++ ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10, ++ ++ IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030, ++ IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0, ++ IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1, ++ IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2, ++ ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3, ++ IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700, ++ IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000, ++ IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010, ++ IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00, ++ IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000, ++}; ++ ++struct ieee80211_radiotap_he_mu { ++ __le16 flags1, flags2; ++ u8 ru_ch1[4]; ++ u8 ru_ch2[4]; ++}; ++ ++enum ieee80211_radiotap_he_mu_bits { ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS = 0x000f, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN = 0x0010, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM = 0x0020, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN = 0x0040, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN = 0x0080, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN = 0x0100, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN = 0x0200, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN = 0x1000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU = 0x2000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN = 0x4000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW = 0x0003, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_20MHZ = 0x0000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_40MHZ = 0x0001, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_80MHZ = 0x0002, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_160MHZ = 0x0003, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN = 0x0004, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP = 0x0008, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS = 0x00f0, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW = 0x0300, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN = 0x0400, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800, ++}; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) ++#define rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, params) \ ++ rwnx_cfg80211_add_iface(wiphy, name, type, u32 *flags, params) ++#else ++#define rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, params) \ ++ rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, u32 *flags, params) ++#endif ++ ++#define rwnx_cfg80211_change_iface(wiphy, dev, type, params) \ ++ rwnx_cfg80211_change_iface(wiphy, dev, type, u32 *flags, params) ++ ++#define CCFS0(vht) vht->center_freq_seg1_idx ++#define CCFS1(vht) vht->center_freq_seg2_idx ++ ++#else ++#define CCFS0(vht) vht->center_freq_seg0_idx ++#define CCFS1(vht) vht->center_freq_seg1_idx ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) ++#define cfg80211_cqm_rssi_notify(dev, event, level, gfp) \ ++ cfg80211_cqm_rssi_notify(dev, event, gfp) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) ++#define ieee80211_amsdu_to_8023s(skb, list, addr, iftype, extra_headroom, check_da, check_sa) \ ++ ieee80211_amsdu_to_8023s(skb, list, addr, iftype, extra_headroom, false) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) ++#define NUM_NL80211_BANDS IEEE80211_NUM_BANDS ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++#define cfg80211_disconnected(dev, reason, ie, len, local, gfp) \ ++ cfg80211_disconnected(dev, reason, ie, len, gfp) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !(defined CONFIG_VENDOR_RWNX) ++#define ieee80211_chandef_to_operating_class(chan_def, op_class) 0 ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++#define SURVEY_INFO_TIME SURVEY_INFO_CHANNEL_TIME ++#define SURVEY_INFO_TIME_BUSY SURVEY_INFO_CHANNEL_TIME_BUSY ++#define SURVEY_INFO_TIME_EXT_BUSY SURVEY_INFO_CHANNEL_TIME_EXT_BUSY ++#define SURVEY_INFO_TIME_RX SURVEY_INFO_CHANNEL_TIME_RX ++#define SURVEY_INFO_TIME_TX SURVEY_INFO_CHANNEL_TIME_TX ++ ++#define SURVEY_TIME(s) s->channel_time ++#define SURVEY_TIME_BUSY(s) s->channel_time_busy ++#else ++#define SURVEY_TIME(s) s->time ++#define SURVEY_TIME_BUSY(s) s->time_busy ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) ++#define cfg80211_ch_switch_started_notify(dev, chandef, count) ++ ++#define WLAN_BSS_COEX_INFORMATION_REQUEST BIT(0) ++#define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2) ++#define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4) ++#define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5) ++#define WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH BIT(6) ++#define WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED BIT(7) ++#define NL80211_FEATURE_TDLS_CHANNEL_SWITCH 0 ++ ++#define STA_TDLS_INITIATOR(sta) 0 ++ ++#else ++#define STA_TDLS_INITIATOR(sta) sta->tdls_initiator ++#endif ++ ++#ifndef REGULATORY_IGNORE_STALE_KICKOFF ++#define REGULATORY_IGNORE_STALE_KICKOFF 0 ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) ++#define cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags) \ ++ cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags, GFP_ATOMIC) ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) ++#define cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags) \ ++ cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, GFP_ATOMIC) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) ++#define rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, initiator, buf, len) \ ++ rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, buf, len) ++#else ++#define rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, initiator, buf, len) \ ++ rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, buf, len) ++#endif ++#endif ++ ++#include ++ ++struct ieee80211_wmm_ac_param { ++ u8 aci_aifsn; /* AIFSN, ACM, ACI */ ++ u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ ++ __le16 txop_limit; ++} __packed; ++ ++struct ieee80211_wmm_param_ie { ++ u8 element_id; /* Element ID: 221 (0xdd); */ ++ u8 len; /* Length: 24 */ ++ /* required fields for WMM version 1 */ ++ u8 oui[3]; /* 00:50:f2 */ ++ u8 oui_type; /* 2 */ ++ u8 oui_subtype; /* 1 */ ++ u8 version; /* 1 for WMM version 1.0 */ ++ u8 qos_info; /* AP/STA specific QoS info */ ++ u8 reserved; /* 0 */ ++ /* AC_BE, AC_BK, AC_VI, AC_VO */ ++ struct ieee80211_wmm_ac_param ac[4]; ++} __packed; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++enum { ++ IEEE80211_HE_MCS_SUPPORT_0_7 = 0, ++ IEEE80211_HE_MCS_SUPPORT_0_9 = 1, ++ IEEE80211_HE_MCS_SUPPORT_0_11 = 2, ++ IEEE80211_HE_MCS_NOT_SUPPORTED = 3, ++}; ++#endif ++ ++/* MAC80211 */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) ++#define rwnx_ops_mgd_prepare_tx(hw, vif, duration) \ ++ rwnx_ops_mgd_prepare_tx(hw, vif) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) ++ ++#define RX_ENC_HT(s) (s->flag |= RX_FLAG_HT) ++#define RX_ENC_HT_GF(s) (s->flag |= (RX_FLAG_HT | RX_FLAG_HT_GF)) ++#define RX_ENC_VHT(s) (s->flag |= RX_FLAG_HT) ++#define RX_ENC_HE(s) (s->flag |= RX_FLAG_HT) ++#define RX_ENC_FLAG_SHORT_GI(s) (s->flag |= RX_FLAG_SHORT_GI) ++#define RX_ENC_FLAG_SHORT_PRE(s) (s->flag |= RX_FLAG_SHORTPRE) ++#define RX_ENC_FLAG_LDPC(s) (s->flag |= RX_FLAG_LDPC) ++#define RX_BW_40MHZ(s) (s->flag |= RX_FLAG_40MHZ) ++#define RX_BW_80MHZ(s) (s->vht_flag |= RX_VHT_FLAG_80MHZ) ++#define RX_BW_160MHZ(s) (s->vht_flag |= RX_VHT_FLAG_160MHZ) ++#define RX_NSS(s) s->vht_nss ++ ++#else ++#define RX_ENC_HT(s) (s->encoding = RX_ENC_HT) ++#define RX_ENC_HT_GF(s) { s->encoding = RX_ENC_HT; \ ++ s->enc_flags |= RX_ENC_FLAG_HT_GF; } ++#define RX_ENC_VHT(s) (s->encoding = RX_ENC_VHT) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define RX_ENC_HE(s) (s->encoding = RX_ENC_VHT) ++#else ++#define RX_ENC_HE(s) (s->encoding = RX_ENC_HE) ++#endif ++#define RX_ENC_FLAG_SHORT_GI(s) (s->enc_flags |= RX_ENC_FLAG_SHORT_GI) ++#define RX_ENC_FLAG_SHORT_PRE(s) (s->enc_flags |= RX_ENC_FLAG_SHORTPRE) ++#define RX_ENC_FLAG_LDPC(s) (s->enc_flags |= RX_ENC_FLAG_LDPC) ++#define RX_BW_40MHZ(s) (s->bw = RATE_INFO_BW_40) ++#define RX_BW_80MHZ(s) (s->bw = RATE_INFO_BW_80) ++#define RX_BW_160MHZ(s) (s->bw = RATE_INFO_BW_160) ++#define RX_NSS(s) s->nss ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) ++#define ieee80211_cqm_rssi_notify(vif, event, level, gfp) \ ++ ieee80211_cqm_rssi_notify(vif, event, gfp) ++#endif ++ ++#ifndef CONFIG_VENDOR_RWNX_AMSDUS_TX ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) ++#define rwnx_ops_ampdu_action(hw, vif, params) \ ++ rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \ ++ struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) ++#define rwnx_ops_ampdu_action(hw, vif, params) \ ++ rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \ ++ struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, \ ++ bool amsdu) ++#endif ++#endif /* CONFIG_VENDOR_RWNX_AMSDUS_TX */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++#define IEEE80211_HW_SUPPORT_FAST_XMIT 0 ++#define ieee80211_hw_check(hw, feat) (hw->flags & IEEE80211_HW_##feat) ++#define ieee80211_hw_set(hw, feat) {hw->flags |= IEEE80211_HW_##feat; } ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) ++#define rwnx_ops_sw_scan_start(hw, vif, mac_addr) \ ++ rwnx_ops_sw_scan_start(hw) ++#define rwnx_ops_sw_scan_complete(hw, vif) \ ++ rwnx_ops_sw_scan_complete(hw) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define rwnx_ops_hw_scan(hw, vif, hw_req) \ ++ rwnx_ops_hw_scan(hw, vif, struct cfg80211_scan_request *req) ++#endif ++ ++/* NET */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb) ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb, void *accel_priv, select_queue_fallback_t fallback) ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb, sb_dev, select_queue_fallback_t fallback) ++#else ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb, sb_dev) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)) && !(defined CONFIG_VENDOR_RWNX) ++#define sk_pacing_shift_update(sk, shift) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define alloc_netdev_mqs(size, name, assign, setup, txqs, rxqs) \ ++ alloc_netdev_mqs(size, name, setup, txqs, rxqs) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define NET_NAME_UNKNOWN 0 ++#endif ++ ++/* TRACE */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++#define trace_print_symbols_seq ftrace_print_symbols_seq ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define trace_seq_buffer_ptr(p) (p->buffer + p->len) ++#endif ++ ++/* TIME */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) ++#define time64_to_tm(t, o, tm) time_to_tm((time_t)t, o, tm) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) ++#define ktime_get_real_seconds get_seconds ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++typedef __s64 time64_t; ++#endif ++ ++#endif /* _RWNX_COMPAT_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c +new file mode 100644 +index 000000000000..fdca110169b0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c +@@ -0,0 +1,2469 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_debugfs.c ++ * ++ * @brief Definition of debugfs entries ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rwnx_debugfs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_radar.h" ++#include "rwnx_tx.h" ++ ++#ifdef CONFIG_DEBUG_FS ++#ifdef CONFIG_RWNX_FULLMAC ++static ssize_t rwnx_dbgfs_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int ret; ++ int i, skipped; ++ ssize_t read; ++ int bufsz = (NX_TXQ_CNT) * 20 + (ARRAY_SIZE(priv->stats.amsdus_rx) + 1) * 40 ++ + (ARRAY_SIZE(priv->stats.ampdus_tx) * 30); ++ ++ if (*ppos) ++ return 0; ++ ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ ret = scnprintf(buf, bufsz, "TXQs CFM balances "); ++ for (i = 0; i < NX_TXQ_CNT; i++) ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%1d]:%3d", i, ++ priv->stats.cfm_balance[i]); ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, "\n"); ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "\nAMSDU[len] done failed received\n"); ++ for (i = skipped = 0; i < NX_TX_PAYLOAD_MAX; i++) { ++ if (priv->stats.amsdus[i].done) { ++ per = DIV_ROUND_UP((priv->stats.amsdus[i].failed) * ++ 100, priv->stats.amsdus[i].done); ++ } else if (priv->stats.amsdus_rx[i]) { ++ per = 0; ++ } else { ++ per = 0; ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %10d %8d(%3d%%) %10d\n", i ? i + 1 : i, ++ priv->stats.amsdus[i].done, ++ priv->stats.amsdus[i].failed, per, ++ priv->stats.amsdus_rx[i]); ++ } ++ ++ for (; i < ARRAY_SIZE(priv->stats.amsdus_rx); i++) { ++ if (!priv->stats.amsdus_rx[i]) { ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %10d\n", ++ i + 1, priv->stats.amsdus_rx[i]); ++ } ++#else ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "\nAMSDU[len] received\n"); ++ for (i = skipped = 0; i < ARRAY_SIZE(priv->stats.amsdus_rx); i++) { ++ if (!priv->stats.amsdus_rx[i]) { ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %10d\n", ++ i + 1, priv->stats.amsdus_rx[i]); ++ } ++ ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "\nAMPDU[len] done received\n"); ++ for (i = skipped = 0; i < ARRAY_SIZE(priv->stats.ampdus_tx); i++) { ++ if (!priv->stats.ampdus_tx[i] && !priv->stats.ampdus_rx[i]) { ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %9d %9d\n", i ? i + 1 : i, ++ priv->stats.ampdus_tx[i], priv->stats.ampdus_rx[i]); ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "#mpdu missed %9d\n", ++ priv->stats.ampdus_rx_miss); ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ kfree(buf); ++ ++ return read; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++static ssize_t rwnx_dbgfs_stats_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ ++ /* Prevent from interrupt preemption as these statistics are updated under ++ * interrupt */ ++ spin_lock_bh(&priv->tx_lock); ++ ++ memset(&priv->stats, 0, sizeof(priv->stats)); ++ ++ spin_unlock_bh(&priv->tx_lock); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(stats); ++ ++#define TXQ_STA_PREF "tid|" ++#define TXQ_STA_PREF_FMT "%3d|" ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define TXQ_VIF_PREF "type|" ++#define TXQ_VIF_PREF_FMT "%4s|" ++#else ++#define TXQ_VIF_PREF "AC|" ++#define TXQ_VIF_PREF_FMT "%2s|" ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#define TXQ_HDR "idx| status|credit|ready|retry" ++#define TXQ_HDR_FMT "%3d|%s%s%s%s%s%s%s|%6d|%5d|%5d" ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++#ifdef CONFIG_RWNX_FULLMAC ++#define TXQ_HDR_SUFF "|amsdu" ++#define TXQ_HDR_SUFF_FMT "|%5d" ++#else ++#define TXQ_HDR_SUFF "|amsdu-ht|amdsu-vht" ++#define TXQ_HDR_SUFF_FMT "|%8d|%9d" ++#endif /* CONFIG_RWNX_FULLMAC */ ++#else ++#define TXQ_HDR_SUFF "" ++#define TXQ_HDR_SUF_FMT "" ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++#define TXQ_HDR_MAX_LEN (sizeof(TXQ_STA_PREF) + sizeof(TXQ_HDR) + sizeof(TXQ_HDR_SUFF) + 1) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define PS_HDR "Legacy PS: ready=%d, sp=%d / UAPSD: ready=%d, sp=%d" ++#define PS_HDR_LEGACY "Legacy PS: ready=%d, sp=%d" ++#define PS_HDR_UAPSD "UAPSD: ready=%d, sp=%d" ++#define PS_HDR_MAX_LEN sizeof("Legacy PS: ready=xxx, sp=xxx / UAPSD: ready=xxx, sp=xxx\n") ++#else ++#define PS_HDR "" ++#define PS_HDR_MAX_LEN 0 ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#define STA_HDR "** STA %d (%pM)\n" ++#define STA_HDR_MAX_LEN (sizeof("- STA xx (xx:xx:xx:xx:xx:xx)\n") + PS_HDR_MAX_LEN) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define VIF_HDR "* VIF [%d] %s\n" ++#define VIF_HDR_MAX_LEN (sizeof(VIF_HDR) + IFNAMSIZ) ++#else ++#define VIF_HDR "* VIF [%d]\n" ++#define VIF_HDR_MAX_LEN sizeof(VIF_HDR) ++#endif ++ ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define VIF_SEP "---------------------------------------\n" ++#else ++#define VIF_SEP "----------------------------------------------------\n" ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#else /* ! CONFIG_RWNX_AMSDUS_TX */ ++#define VIF_SEP "---------------------------------\n" ++#endif /* CONFIG_RWNX_AMSDUS_TX*/ ++ ++#define VIF_SEP_LEN sizeof(VIF_SEP) ++ ++#define CAPTION "status: L=in hwq list, F=stop full, P=stop sta PS, V=stop vif PS, C=stop channel, S=stop CSA, M=stop MU" ++#define CAPTION_LEN sizeof(CAPTION) ++ ++#define STA_TXQ 0 ++#define VIF_TXQ 1 ++ ++static int rwnx_dbgfs_txq(char *buf, size_t size, struct rwnx_txq *txq, int type, int tid, char *name) ++{ ++ int res, idx = 0; ++ ++ if (type == STA_TXQ) { ++ res = scnprintf(&buf[idx], size, TXQ_STA_PREF_FMT, tid); ++ idx += res; ++ size -= res; ++ } else { ++ res = scnprintf(&buf[idx], size, TXQ_VIF_PREF_FMT, name); ++ idx += res; ++ size -= res; ++ } ++ ++ res = scnprintf(&buf[idx], size, TXQ_HDR_FMT, txq->idx, ++ (txq->status & RWNX_TXQ_IN_HWQ_LIST) ? "L" : " ", ++ (txq->status & RWNX_TXQ_STOP_FULL) ? "F" : " ", ++ (txq->status & RWNX_TXQ_STOP_STA_PS) ? "P" : " ", ++ (txq->status & RWNX_TXQ_STOP_VIF_PS) ? "V" : " ", ++ (txq->status & RWNX_TXQ_STOP_CHAN) ? "C" : " ", ++ (txq->status & RWNX_TXQ_STOP_CSA) ? "S" : " ", ++ (txq->status & RWNX_TXQ_STOP_MU_POS) ? "M" : " ", ++ txq->credits, skb_queue_len(&txq->sk_list), ++ txq->nb_retry); ++ idx += res; ++ size -= res; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (type == STA_TXQ) { ++ res = scnprintf(&buf[idx], size, TXQ_HDR_SUFF_FMT, ++#ifdef CONFIG_RWNX_FULLMAC ++ txq->amsdu_len ++#else ++ txq->amsdu_ht_len_cap, txq->amsdu_vht_len_cap ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ); ++ idx += res; ++ size -= res; ++ } ++#endif ++ ++ res = scnprintf(&buf[idx], size, "\n"); ++ idx += res; ++ size -= res; ++ ++ return idx; ++} ++ ++static int rwnx_dbgfs_txq_sta(char *buf, size_t size, struct rwnx_sta *rwnx_sta, ++ struct rwnx_hw *rwnx_hw) ++{ ++ int tid, res, idx = 0; ++ struct rwnx_txq *txq; ++ ++ res = scnprintf(&buf[idx], size, "\n" STA_HDR, ++ rwnx_sta->sta_idx, ++#ifdef CONFIG_RWNX_FULLMAC ++ rwnx_sta->mac_addr ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ); ++ idx += res; ++ size -= res; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (rwnx_sta->ps.active) { ++ if (rwnx_sta->uapsd_tids && ++ (rwnx_sta->uapsd_tids == ((1 << NX_NB_TXQ_PER_STA) - 1))) ++ res = scnprintf(&buf[idx], size, PS_HDR_UAPSD "\n", ++ rwnx_sta->ps.pkt_ready[UAPSD_ID], ++ rwnx_sta->ps.sp_cnt[UAPSD_ID]); ++ else if (rwnx_sta->uapsd_tids) ++ res = scnprintf(&buf[idx], size, PS_HDR "\n", ++ rwnx_sta->ps.pkt_ready[LEGACY_PS_ID], ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID], ++ rwnx_sta->ps.pkt_ready[UAPSD_ID], ++ rwnx_sta->ps.sp_cnt[UAPSD_ID]); ++ else ++ res = scnprintf(&buf[idx], size, PS_HDR_LEGACY "\n", ++ rwnx_sta->ps.pkt_ready[LEGACY_PS_ID], ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID]); ++ idx += res; ++ size -= res; ++ } else { ++ res = scnprintf(&buf[idx], size, "\n"); ++ idx += res; ++ size -= res; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ ++ res = scnprintf(&buf[idx], size, TXQ_STA_PREF TXQ_HDR TXQ_HDR_SUFF "\n"); ++ idx += res; ++ size -= res; ++ ++ ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, STA_TXQ, tid, NULL); ++ idx += res; ++ size -= res; ++ } ++ ++ return idx; ++} ++ ++static int rwnx_dbgfs_txq_vif(char *buf, size_t size, struct rwnx_vif *rwnx_vif, ++ struct rwnx_hw *rwnx_hw) ++{ ++ int res, idx = 0; ++ struct rwnx_txq *txq; ++ struct rwnx_sta *rwnx_sta; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ res = scnprintf(&buf[idx], size, VIF_HDR, rwnx_vif->vif_index, rwnx_vif->ndev->name); ++ idx += res; ++ size -= res; ++ if (!rwnx_vif->up || rwnx_vif->ndev == NULL) ++ return idx; ++ ++#else ++ int ac; ++ char ac_name[2] = {'0', '\0'}; ++ ++ res = scnprintf(&buf[idx], size, VIF_HDR, rwnx_vif->vif_index); ++ idx += res; ++ size -= res; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT) { ++ res = scnprintf(&buf[idx], size, TXQ_VIF_PREF TXQ_HDR "\n"); ++ idx += res; ++ size -= res; ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, VIF_TXQ, 0, "UNK"); ++ idx += res; ++ size -= res; ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, VIF_TXQ, 0, "BCMC"); ++ idx += res; ++ size -= res; ++ rwnx_sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ if (rwnx_sta->ps.active) { ++ res = scnprintf(&buf[idx], size, PS_HDR_LEGACY "\n", ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID], ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID]); ++ idx += res; ++ size -= res; ++ } else { ++ res = scnprintf(&buf[idx], size, "\n"); ++ idx += res; ++ size -= res; ++ } ++ ++ list_for_each_entry(rwnx_sta, &rwnx_vif->ap.sta_list, list) { ++ res = rwnx_dbgfs_txq_sta(&buf[idx], size, rwnx_sta, rwnx_hw); ++ idx += res; ++ size -= res; ++ } ++ } else if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ if (rwnx_vif->sta.ap) { ++ res = rwnx_dbgfs_txq_sta(&buf[idx], size, rwnx_vif->sta.ap, rwnx_hw); ++ idx += res; ++ size -= res; ++ } ++ } ++ ++#else ++ res = scnprintf(&buf[idx], size, TXQ_VIF_PREF TXQ_HDR "\n"); ++ idx += res; ++ size -= res; ++ ++ foreach_vif_txq(rwnx_vif, txq, ac) { ++ ac_name[0]++; ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, VIF_TXQ, 0, ac_name); ++ idx += res; ++ size -= res; ++ } ++ ++ list_for_each_entry(rwnx_sta, &rwnx_vif->stations, list) { ++ res = rwnx_dbgfs_txq_sta(&buf[idx], size, rwnx_sta, rwnx_hw); ++ idx += res; ++ size -= res; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ return idx; ++} ++ ++static ssize_t rwnx_dbgfs_txq_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rwnx_hw = file->private_data; ++ struct rwnx_vif *vif; ++ char *buf; ++ int idx, res; ++ ssize_t read; ++ size_t bufsz = ((NX_VIRT_DEV_MAX * (VIF_HDR_MAX_LEN + 2 * VIF_SEP_LEN)) + ++ (NX_REMOTE_STA_MAX * STA_HDR_MAX_LEN) + ++ ((NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX + NX_NB_TXQ) * ++ TXQ_HDR_MAX_LEN) + CAPTION_LEN); ++ ++ /* everything is read in one go */ ++ if (*ppos) ++ return 0; ++ ++ bufsz = min_t(size_t, bufsz, count); ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ bufsz--; ++ idx = 0; ++ ++ res = scnprintf(&buf[idx], bufsz, CAPTION); ++ idx += res; ++ bufsz -= res; ++ ++ //spin_lock_bh(&rwnx_hw->tx_lock); ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ res = scnprintf(&buf[idx], bufsz, "\n"VIF_SEP); ++ idx += res; ++ bufsz -= res; ++ res = rwnx_dbgfs_txq_vif(&buf[idx], bufsz, vif, rwnx_hw); ++ idx += res; ++ bufsz -= res; ++ res = scnprintf(&buf[idx], bufsz, VIF_SEP); ++ idx += res; ++ bufsz -= res; ++ } ++ //spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, idx); ++ kfree(buf); ++ ++ return read; ++} ++DEBUGFS_READ_FILE_OPS(txq); ++ ++static ssize_t rwnx_dbgfs_acsinfo_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++#ifdef CONFIG_RWNX_FULLMAC ++ struct wiphy *wiphy = priv->wiphy; ++#endif //CONFIG_RWNX_FULLMAC ++ int survey_cnt = 0; ++ int len = 0; ++ int band, chan_cnt; ++ int band_max = NL80211_BAND_5GHZ; ++ char *buf = (char *)vmalloc((SCAN_CHANNEL_MAX + 1) * 43); ++ ssize_t size; ++ ++ if (!buf) ++ return 0; ++ ++ if (priv->band_5g_support) ++ band_max = NL80211_BAND_5GHZ + 1; ++ ++ mutex_lock(&priv->dbgdump_elem.mutex); ++ ++ len += scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "FREQ TIME(ms) BUSY(ms) NOISE(dBm)\n"); ++ ++ for (band = NL80211_BAND_2GHZ; band < band_max; band++) { ++ for (chan_cnt = 0; chan_cnt < wiphy->bands[band]->n_channels; chan_cnt++) { ++ struct rwnx_survey_info *p_survey_info = &priv->survey[survey_cnt]; ++ struct ieee80211_channel *p_chan = &wiphy->bands[band]->channels[chan_cnt]; ++ ++ if (p_survey_info->filled) { ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - len - 1, count), ++ "%d %03d %03d %d\n", ++ p_chan->center_freq, ++ p_survey_info->chan_time_ms, ++ p_survey_info->chan_time_busy_ms, ++ p_survey_info->noise_dbm); ++ } else { ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) -len -1, count), ++ "%d NOT AVAILABLE\n", ++ p_chan->center_freq); ++ } ++ ++ survey_cnt++; ++ } ++ } ++ ++ mutex_unlock(&priv->dbgdump_elem.mutex); ++ ++ size = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ vfree(buf); ++ ++ return size; ++} ++ ++DEBUGFS_READ_FILE_OPS(acsinfo); ++ ++static ssize_t rwnx_dbgfs_fw_dbg_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ char help[] = "usage: [MOD:]* " ++ "[DBG:]\n"; ++ ++ return simple_read_from_buffer(user_buf, count, ppos, help, sizeof(help)); ++} ++ ++ ++static ssize_t rwnx_dbgfs_fw_dbg_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int idx = 0; ++ u32 mod = 0; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ ++#define RWNX_MOD_TOKEN(str, val) \ ++ do { \ ++ if (strncmp(&buf[idx], str, sizeof(str) - 1) == 0) { \ ++ idx += sizeof(str) - 1; \ ++ mod |= val; \ ++ continue; \ ++ } \ ++ } while (0) ++ ++#define RWNX_DBG_TOKEN(str, val) \ ++ do { \ ++ if (strncmp(&buf[idx], str, sizeof(str) - 1) == 0) { \ ++ idx += sizeof(str) - 1; \ ++ dbg = val; \ ++ goto dbg_done; \ ++ } \ ++ } while (0) ++ ++ while ((idx + 4) < len) { ++ if (strncmp(&buf[idx], "MOD:", 4) == 0) { ++ idx += 4; ++ RWNX_MOD_TOKEN("ALL", 0xffffffff); ++ RWNX_MOD_TOKEN("KE", BIT(0)); ++ RWNX_MOD_TOKEN("DBG", BIT(1)); ++ RWNX_MOD_TOKEN("IPC", BIT(2)); ++ RWNX_MOD_TOKEN("DMA", BIT(3)); ++ RWNX_MOD_TOKEN("MM", BIT(4)); ++ RWNX_MOD_TOKEN("TX", BIT(5)); ++ RWNX_MOD_TOKEN("RX", BIT(6)); ++ RWNX_MOD_TOKEN("PHY", BIT(7)); ++ idx++; ++ } else if (strncmp(&buf[idx], "DBG:", 4) == 0) { ++ u32 dbg = 0; ++ idx += 4; ++ RWNX_DBG_TOKEN("NONE", 0); ++ RWNX_DBG_TOKEN("CRT", 1); ++ RWNX_DBG_TOKEN("ERR", 2); ++ RWNX_DBG_TOKEN("WRN", 3); ++ RWNX_DBG_TOKEN("INF", 4); ++ RWNX_DBG_TOKEN("VRB", 5); ++ idx++; ++ continue; ++ dbg_done: ++ rwnx_send_dbg_set_sev_filter_req(priv, dbg); ++ } else { ++ idx++; ++ } ++ } ++ ++ if (mod) { ++ rwnx_send_dbg_set_mod_filter_req(priv, mod); ++ } ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg); ++ ++static ssize_t rwnx_dbgfs_sys_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[3*64]; ++ int len = 0; ++ ssize_t read; ++ int error = 0; ++ struct dbg_get_sys_stat_cfm cfm; ++ u32 sleep_int, sleep_frac, doze_int, doze_frac; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Get the information from the FW */ ++ error = rwnx_send_dbg_get_sys_stat_req(priv, &cfm); ++ if (error) ++ return error; ++ ++ if (cfm.stats_time == 0) ++ return 0; ++ ++ sleep_int = ((cfm.cpu_sleep_time * 100) / cfm.stats_time); ++ sleep_frac = (((cfm.cpu_sleep_time * 100) % cfm.stats_time) * 10) / cfm.stats_time; ++ doze_int = ((cfm.doze_time * 100) / cfm.stats_time); ++ doze_frac = (((cfm.doze_time * 100) % cfm.stats_time) * 10) / cfm.stats_time; ++ ++ len += scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "\nSystem statistics:\n"); ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - 1, count), ++ " CPU sleep [%%]: %d.%d\n", sleep_int, sleep_frac); ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - 1, count), ++ " Doze [%%]: %d.%d\n", doze_int, doze_frac); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ return read; ++} ++ ++DEBUGFS_READ_FILE_OPS(sys_stats); ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++static ssize_t rwnx_dbgfs_mu_group_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rwnx_hw = file->private_data; ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ struct rwnx_mu_group *group; ++ size_t bufsz = NX_MU_GROUP_MAX * sizeof("xx = (xx - xx - xx - xx)\n") + 50; ++ char *buf; ++ int j, res, idx = 0; ++ ++ if (*ppos) ++ return 0; ++ ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ res = scnprintf(&buf[idx], bufsz, "MU Group list (%d groups, %d users max)\n", ++ NX_MU_GROUP_MAX, CONFIG_USER_MAX); ++ idx += res; ++ bufsz -= res; ++ ++ list_for_each_entry(group, &mu->active_groups, list) { ++ if (group->user_cnt) { ++ res = scnprintf(&buf[idx], bufsz, "%2d = (", group->group_id); ++ idx += res; ++ bufsz -= res; ++ for (j = 0; j < (CONFIG_USER_MAX - 1) ; j++) { ++ if (group->users[j]) ++ res = scnprintf(&buf[idx], bufsz, "%2d - ", ++ group->users[j]->sta_idx); ++ else ++ res = scnprintf(&buf[idx], bufsz, ".. - "); ++ ++ idx += res; ++ bufsz -= res; ++ } ++ ++ if (group->users[j]) ++ res = scnprintf(&buf[idx], bufsz, "%2d)\n", ++ group->users[j]->sta_idx); ++ else ++ res = scnprintf(&buf[idx], bufsz, "..)\n"); ++ ++ idx += res; ++ bufsz -= res; ++ } ++ } ++ ++ res = simple_read_from_buffer(user_buf, count, ppos, buf, idx); ++ kfree(buf); ++ ++ return res; ++} ++ ++DEBUGFS_READ_FILE_OPS(mu_group); ++#endif ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++static ssize_t rwnx_dbgfs_oppps_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rw_hw = file->private_data; ++ struct rwnx_vif *rw_vif; ++ char buf[32]; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ctw; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ ++ /* Read the written CT Window (provided in ms) value */ ++ if (sscanf(buf, "ctw=%d", &ctw) > 0) { ++ /* Check if at least one VIF is configured as P2P GO */ ++ list_for_each_entry(rw_vif, &rw_hw->vifs, list) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (RWNX_VIF_TYPE(rw_vif) == NL80211_IFTYPE_P2P_GO) { ++#endif /* CONFIG_RWNX_FULLMAC */ ++ struct mm_set_p2p_oppps_cfm cfm; ++ ++ /* Forward request to the embedded and wait for confirmation */ ++ rwnx_send_p2p_oppps_req(rw_hw, rw_vif, (u8)ctw, &cfm); ++ ++ break; ++ } ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(oppps); ++ ++static ssize_t rwnx_dbgfs_noa_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rw_hw = file->private_data; ++ struct rwnx_vif *rw_vif; ++ char buf[64]; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int noa_count, interval, duration, dyn_noa; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ ++ /* Read the written NOA information */ ++ if (sscanf(buf, "count=%d interval=%d duration=%d dyn=%d", ++ &noa_count, &interval, &duration, &dyn_noa) > 0) { ++ /* Check if at least one VIF is configured as P2P GO */ ++ list_for_each_entry(rw_vif, &rw_hw->vifs, list) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (RWNX_VIF_TYPE(rw_vif) == NL80211_IFTYPE_P2P_GO) { ++#endif /* CONFIG_RWNX_FULLMAC */ ++ struct mm_set_p2p_noa_cfm cfm; ++ ++ /* Forward request to the embedded and wait for confirmation */ ++ rwnx_send_p2p_noa_req(rw_hw, rw_vif, noa_count, interval, ++ duration, (dyn_noa > 0), &cfm); ++ ++ break; ++ } ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(noa); ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++static char fw_log_buffer[FW_LOG_SIZE]; ++ ++static ssize_t rwnx_dbgfs_fw_log_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ size_t not_cpy; ++ size_t nb_cpy; ++ char *log = fw_log_buffer; ++ ++ printk("%s, %d, %p, %p\n", __func__, priv->debugfs.fw_log.buf.size, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.dataend); ++ //spin_lock_bh(&priv->debugfs.fw_log.lock); ++ ++ if ((priv->debugfs.fw_log.buf.start + priv->debugfs.fw_log.buf.size) >= priv->debugfs.fw_log.buf.dataend) { ++ memcpy(log, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.dataend - priv->debugfs.fw_log.buf.start); ++ not_cpy = copy_to_user(user_buf, log, priv->debugfs.fw_log.buf.dataend - priv->debugfs.fw_log.buf.start); ++ nb_cpy = priv->debugfs.fw_log.buf.dataend - priv->debugfs.fw_log.buf.start - not_cpy; ++ priv->debugfs.fw_log.buf.start = priv->debugfs.fw_log.buf.data; ++ } else { ++ memcpy(log, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.size); ++ not_cpy = copy_to_user(user_buf, log, priv->debugfs.fw_log.buf.size); ++ nb_cpy = priv->debugfs.fw_log.buf.size - not_cpy; ++ priv->debugfs.fw_log.buf.start = priv->debugfs.fw_log.buf.start + priv->debugfs.fw_log.buf.size - not_cpy; ++ } ++ ++ priv->debugfs.fw_log.buf.size -= nb_cpy; ++ //spin_unlock_bh(&priv->debugfs.fw_log.lock); ++ ++ printk("nb_cpy=%lu, not_cpy=%lu, start=%p, end=%p\n", (long unsigned int)nb_cpy, (long unsigned int)not_cpy, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.end); ++ return nb_cpy; ++} ++ ++static ssize_t rwnx_dbgfs_fw_log_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ //struct rwnx_hw *priv = file->private_data; ++ ++ printk("%s\n", __func__); ++ return count; ++} ++DEBUGFS_READ_WRITE_FILE_OPS(fw_log); ++ ++#ifdef CONFIG_RWNX_RADAR ++static ssize_t rwnx_dbgfs_pulses_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos, ++ int rd_idx) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int len = 0; ++ int bufsz; ++ int i; ++ int index; ++ struct rwnx_radar_pulses *p = &priv->radar.pulses[rd_idx]; ++ ssize_t read; ++ ++ if (*ppos != 0) ++ return 0; ++ ++ /* Prevent from interrupt preemption */ ++ spin_lock_bh(&priv->radar.lock); ++ bufsz = p->count * 34 + 51; ++ bufsz += rwnx_radar_dump_pattern_detector(NULL, 0, &priv->radar, rd_idx); ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) { ++ spin_unlock_bh(&priv->radar.lock); ++ return 0; ++ } ++ ++ if (p->count) { ++ len += scnprintf(&buf[len], bufsz - len, ++ " PRI WIDTH FOM FREQ\n"); ++ index = p->index; ++ for (i = 0; i < p->count; i++) { ++ struct radar_pulse *pulse; ++ ++ if (index > 0) ++ index--; ++ else ++ index = RWNX_RADAR_PULSE_MAX - 1; ++ ++ pulse = (struct radar_pulse *) &p->buffer[index]; ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ "%05dus %03dus %2d%% %+3dMHz\n", pulse->rep, ++ 2 * pulse->len, 6 * pulse->fom, 2*pulse->freq); ++ } ++ } ++ ++ len += rwnx_radar_dump_pattern_detector(&buf[len], bufsz - len, ++ &priv->radar, rd_idx); ++ ++ spin_unlock_bh(&priv->radar.lock); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_pulses_prim_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ return rwnx_dbgfs_pulses_read(file, user_buf, count, ppos, 0); ++} ++ ++DEBUGFS_READ_FILE_OPS(pulses_prim); ++ ++static ssize_t rwnx_dbgfs_pulses_sec_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ return rwnx_dbgfs_pulses_read(file, user_buf, count, ppos, 1); ++} ++ ++DEBUGFS_READ_FILE_OPS(pulses_sec); ++ ++static ssize_t rwnx_dbgfs_detected_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int bufsz, len = 0; ++ ssize_t read; ++ ++ if (*ppos != 0) ++ return 0; ++ ++ bufsz = 5; // RIU:\n ++ bufsz += rwnx_radar_dump_radar_detected(NULL, 0, &priv->radar, ++ RWNX_RADAR_RIU); ++ ++ if (priv->phy.cnt > 1) { ++ bufsz += 5; // FCU:\n ++ bufsz += rwnx_radar_dump_radar_detected(NULL, 0, &priv->radar, ++ RWNX_RADAR_FCU); ++ } ++ ++ buf = kmalloc(bufsz, GFP_KERNEL); ++ if (buf == NULL) { ++ return 0; ++ } ++ ++ len = scnprintf(&buf[len], bufsz, "RIU:\n"); ++ len += rwnx_radar_dump_radar_detected(&buf[len], bufsz - len, &priv->radar, ++ RWNX_RADAR_RIU); ++ ++ if (priv->phy.cnt > 1) { ++ len += scnprintf(&buf[len], bufsz - len, "FCU:\n"); ++ len += rwnx_radar_dump_radar_detected(&buf[len], bufsz - len, ++ &priv->radar, RWNX_RADAR_FCU); ++ } ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ ++ return read; ++} ++ ++DEBUGFS_READ_FILE_OPS(detected); ++ ++static ssize_t rwnx_dbgfs_enable_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "RIU=%d FCU=%d\n", priv->radar.dpd[RWNX_RADAR_RIU]->enabled, ++ priv->radar.dpd[RWNX_RADAR_FCU]->enabled); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_enable_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "RIU=%d", &val) > 0) ++ rwnx_radar_detection_enable(&priv->radar, val, RWNX_RADAR_RIU); ++ ++ if (sscanf(buf, "FCU=%d", &val) > 0) ++ rwnx_radar_detection_enable(&priv->radar, val, RWNX_RADAR_FCU); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(enable); ++ ++static ssize_t rwnx_dbgfs_band_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "BAND=%d\n", priv->phy.sec_chan.band); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_band_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int band_max = NL80211_BAND_5GHZ; ++ ++ if (priv->band_5g_support) ++ band_max = NL80211_BAND_5GHZ + 1; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if ((sscanf(buf, "%d", &val) > 0) && (val >= 0) && (val < band_max)) ++ priv->phy.sec_chan.band = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(band); ++ ++static ssize_t rwnx_dbgfs_type_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "TYPE=%d\n", priv->phy.sec_chan.type); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_type_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if ((sscanf(buf, "%d", &val) > 0) && (val >= PHY_CHNL_BW_20) && ++ (val <= PHY_CHNL_BW_80P80)) ++ priv->phy.sec_chan.type = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(type); ++ ++static ssize_t rwnx_dbgfs_prim20_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "PRIM20=%dMHz\n", priv->phy.sec_chan.prim20_freq); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_prim20_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%d", &val) > 0) ++ priv->phy.sec_chan.prim20_freq = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(prim20); ++ ++static ssize_t rwnx_dbgfs_center1_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "CENTER1=%dMHz\n", priv->phy.sec_chan.center_freq1); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_center1_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%d", &val) > 0) ++ priv->phy.sec_chan.center_freq1 = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(center1); ++ ++static ssize_t rwnx_dbgfs_center2_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "CENTER2=%dMHz\n", priv->phy.sec_chan.center_freq2); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_center2_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%d", &val) > 0) ++ priv->phy.sec_chan.center_freq2 = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(center2); ++ ++ ++static ssize_t rwnx_dbgfs_set_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ return 0; ++} ++ ++static ssize_t rwnx_dbgfs_set_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ ++ rwnx_send_set_channel(priv, 1, NULL); ++ rwnx_radar_detection_enable(&priv->radar, RWNX_RADAR_DETECT_ENABLE, ++ RWNX_RADAR_FCU); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(set); ++#endif /* CONFIG_RWNX_RADAR */ ++ ++static ssize_t rwnx_dbgfs_regdbg_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ u32 addr,val, oper; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ struct dbg_mem_read_cfm mem_read_cfm; ++ int ret; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%x %x %x" , &oper, &addr, &val ) > 0) ++ printk("addr=%x, val=%x,oper=%d\n", addr, val, oper); ++ ++ if(oper== 0) { ++ ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); ++ printk("[0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); ++ } else if (oper == 1) { ++ ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); ++ printk("before write : [0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); ++ ret = rwnx_send_dbg_mem_block_write_req(priv, addr, 4, &val); ++ ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); ++ printk("after write : [0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(regdbg); ++ ++static ssize_t rwnx_dbgfs_vendor_hwconfig_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[64]; ++ int32_t addr[14]; ++ int32_t addr_out[12]; ++ u32_l hwconfig_id; ++ size_t len = min_t(size_t,count,sizeof(buf)-1); ++ int ret; ++ printk("%s\n",__func__); ++ //choose the type of write info by struct ++ //struct mm_set_vendor_trx_param_req trx_param; ++ ++ if(copy_from_user(buf,user_buf,len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", ++ &hwconfig_id, &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5], &addr[6], &addr[7], &addr[8], &addr[9], &addr[10], &addr[11], &addr[12], &addr[13]); ++ if(ret > 15) { ++ printk("param error > 15\n"); ++ } else { ++ switch(hwconfig_id) ++ { ++ case 0: ++ if(ret != 5) { ++ printk("param error != 5\n"); ++ break;} ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("ACS_TXOP_REQ bk:0x%x be:0x%x vi:0x%x vo:0x%x\n",addr[0], addr[1], addr[2], addr[3]); ++ break; ++ case 1: ++ if(ret != 15) { ++ printk("param error != 15\n"); ++ break;} ++ addr[12] = ~addr[12] + 1; ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("CHANNEL_ACCESS_REQ edca:%x,%x,%x,%x, vif:%x, retry_cnt:%x, rts:%x, long_nav:%x, cfe:%x, rc_retry_cnt:%x:%x:%x ccademod_th %x, remove_1m2m %x\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13]); ++ break; ++ case 2: ++ if(ret != 7) { ++ printk("param error != 7\n"); ++ break;} ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("MAC_TIMESCALE_REQ sifsA:%x,sifsB:%x,slot:%x,ofdm_delay:%x,long_delay:%x,short_delay:%x\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); ++ break; ++ case 3: ++ if(ret != 6) { ++ printk("param error != 6\n"); ++ break;} ++ addr[1] = ~addr[1] + 1; ++ addr[2] = ~addr[2] + 1; ++ addr[3] = ~addr[3] + 1; ++ addr[4] = ~addr[4] + 1; ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("CCA_THRESHOLD_REQ auto_cca:%d, cca20p_rise:%d cca20s_rise:%d cca20p_fail:%d cca20s_fail:%d\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4]); ++ break; ++ case 4: // BWMODE_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("BWMODE_REQ md=%d\n", addr[0]); ++ } ++ break; ++ case 5: // CHIP_TEMP_GET_REQ ++ if (ret != 1) { ++ printk("param error != 1\n"); ++ } else { ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, addr_out); ++ printk("CHIP_TEMP_GET_REQ degree=%d\n", addr_out[0]); ++ } ++ break; ++ case 6://AP_PS_LEVEL_SET_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("AP_PS_LEVEL_SET_REQ lvl=%d\n", addr[0]); ++ } ++ break; ++ default: ++ printk("param error\n"); ++ break; ++ } ++ if(ret) { ++ printk("rwnx_send_vendor_hwconfig_req fail: %x\n", ret); ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(vendor_hwconfig); ++ ++static ssize_t rwnx_dbgfs_vendor_swconfig_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[64]; ++ int32_t addr[12]; ++ int32_t addr_out[12]; ++ u32_l swconfig_id; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ret; ++ printk("%s\n", __func__); ++ ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%x %x %x", &swconfig_id, &addr[0], &addr[1]); ++ if (ret > 3) { ++ printk("param error > 3\n"); ++ } else { ++ switch (swconfig_id) ++ { ++ case 0: // BCN_CFG_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("BCN_CFG_REQ set_en=%d, get_en=%d\n", addr[0], addr_out[0]); ++ } ++ break; ++ ++ case 1: // TEMP_COMP_SET_REQ ++ if (ret != 3) { ++ printk("param error != 3\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("TEMP_COMP_SET_REQ set_en=%d, tmr=%dms, get_st=%d\n", ++ addr[0], addr[1], addr_out[0]); ++ } ++ break; ++ ++ case 2: // TEMP_COMP_GET_REQ ++ if (ret != 1) { ++ printk("param error != 1\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("TEMP_COMP_GET_REQ get_st=%d, degree=%d\n", addr_out[0], addr_out[1]); ++ } ++ break; ++ ++ case 3: // EXT_FLAGS_SET_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("EXT_FLAGS_SET_REQ set ext_flags=0x%x, get ext_flags=0x%x\n", ++ addr[0], addr_out[0]); ++ } ++ break; ++ ++ case 4: // EXT_FLAGS_GET_REQ ++ if (ret != 1) { ++ printk("param error != 1\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("EXT_FLAGS_GET_REQ get ext_flags=0x%x\n", addr_out[0]); ++ } ++ break; ++ ++ case 5: // EXT_FLAGS_MASK_SET_REQ ++ if (ret != 3) { ++ printk("param error != 3\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("EXT_FLAGS_MASK_SET_REQ set ext_flags mask=0x%x, val=0x%x, get ext_flags=0x%x\n", ++ addr[0], addr[1], addr_out[0]); ++ } ++ break; ++ ++ default: ++ printk("param error\n"); ++ break; ++ } ++ ++ if (ret) { ++ printk("rwnx_send_vendor_swconfig_req fail: %x\n", ret); ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(vendor_swconfig); ++ ++static ssize_t rwnx_dbgfs_agg_disable_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[64]; ++ int agg_disable, agg_disable_rx, sta_idx; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ret; ++ printk("%s\n", __func__); ++ ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%d %d %d", &agg_disable, &agg_disable_rx, &sta_idx); ++ if ((ret > 3) || (ret < 2)) { ++ printk("param error: cnt=%d\n", ret); ++ } else { ++ if (ret < 3) { ++ sta_idx = RWNX_INVALID_STA; ++ } ++ printk("disable_agg: T=%d, R=%d, staidx=%d\n", agg_disable, agg_disable_rx, sta_idx); ++ ret = rwnx_send_disable_agg_req(priv, (u8_l)agg_disable, (u8_l)agg_disable_rx, (u8_l)sta_idx); ++ if (ret) { ++ printk("rwnx_send_disable_agg_req fail: %d\n", ret); ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(agg_disable); ++ ++static ssize_t rwnx_dbgfs_set_roc_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ struct rwnx_vif *vif = NULL; ++ char buf[64]; ++ int roc_start, chan_freq, duration; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ret; ++ int if_type = NL80211_IFTYPE_STATION; ++ printk("%s\n", __func__); ++ ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%d %d %d", &roc_start, &chan_freq, &duration); ++ ++ list_for_each_entry(vif, &priv->vifs, list) { ++ if (RWNX_VIF_TYPE(vif) == if_type) { ++ break; ++ } ++ } ++ if ((ret > 3) || (ret < 1)) { ++ printk("param error: cnt=%d\n", ret); ++ } else if (vif) { ++ struct ieee80211_channel chan_entry = {0,}; ++ struct ieee80211_channel *chan = &chan_entry; ++ struct mm_remain_on_channel_cfm roc_cfm; ++ if (ret < 3) { ++ duration = 2000; ++ if (ret < 2) { ++ chan_freq = 2412; ++ } ++ } ++ printk("set_roc: start=%d, freq=%d\n", roc_start, chan_freq); ++ if (roc_start) { ++ if (chan_freq <= 2484) { ++ chan->band = NL80211_BAND_2GHZ; ++ } else { ++ chan->band = NL80211_BAND_5GHZ; ++ } ++ chan->center_freq = chan_freq; ++ chan->max_power = 18; ++ ret = rwnx_send_roc(priv, vif, chan, duration, &roc_cfm); ++ if (ret) { ++ printk("rwnx_send_roc fail: %d\n", ret); ++ } else { ++ printk("roc_cfm: opcode=%x, st=%d, idx=%d\n", roc_cfm.op_code, roc_cfm.status, roc_cfm.chan_ctxt_index); ++ } ++ } else { ++ ret = rwnx_send_cancel_roc(priv); ++ if (ret) { ++ printk("rwnx_send_cancel_roc fail: %d\n", ret); ++ } ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(set_roc); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++#define LINE_MAX_SZ 150 ++ ++struct st { ++ char line[LINE_MAX_SZ + 1]; ++ unsigned int r_idx; ++}; ++ ++static int compare_idx(const void *st1, const void *st2) ++{ ++ int index1 = ((struct st *)st1)->r_idx; ++ int index2 = ((struct st *)st2)->r_idx; ++ ++ if (index1 > index2) ++ return 1; ++ if (index1 < index2) ++ return -1; ++ ++ return 0; ++} ++ ++static const int ru_size[] = { ++ 26, ++ 52, ++ 106, ++ 242, ++ 484, ++ 996 ++}; ++ ++static int print_rate(char *buf, int size, int format, int nss, int mcs, int bw, ++ int sgi, int pre, int *r_idx) ++{ ++ int res = 0; ++ int bitrates_cck[4] = { 10, 20, 55, 110 }; ++ int bitrates_ofdm[8] = { 6, 9, 12, 18, 24, 36, 48, 54}; ++ char he_gi[3][4] = {"0.8", "1.6", "3.2"}; ++ ++ if (format < FORMATMOD_HT_MF) { ++ if (mcs < 4) { ++ if (r_idx) { ++ *r_idx = (mcs * 2) + pre; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "L-CCK/%cP %2u.%1uM ", ++ pre > 0 ? 'L' : 'S', ++ bitrates_cck[mcs] / 10, ++ bitrates_cck[mcs] % 10); ++ } else { ++ mcs -= 4; ++ if (r_idx) { ++ *r_idx = N_CCK + mcs; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "L-OFDM %2u.0M ", ++ bitrates_ofdm[mcs]); ++ } ++ } else if (format < FORMATMOD_VHT) { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + nss * 32 + mcs * 4 + bw * 2 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ mcs += nss * 8; ++ res += scnprintf(&buf[res], size - res, "HT%d/%cGI MCS%-2d ", ++ 20 * (1 << bw), sgi ? 'S' : 'L', mcs); ++ } else if (format == FORMATMOD_VHT) { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + N_HT + nss * 80 + mcs * 8 + bw * 2 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "VHT%d/%cGI%*cMCS%d/%1d ", ++ 20 * (1 << bw), sgi ? 'S' : 'L', bw > 2 ? 5 : 6, ' ', ++ mcs, nss + 1); ++ } else if (format == FORMATMOD_HE_SU) { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + N_HT + N_VHT + nss * 144 + mcs * 12 + bw * 3 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "HE%d/GI%s%*cMCS%d/%1d%*c", ++ 20 * (1 << bw), he_gi[sgi], bw > 2 ? 4 : 5, ' ', ++ mcs, nss + 1, mcs > 9 ? 1 : 2, ' '); ++ } else { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU + nss * 216 + mcs * 18 + bw * 3 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "HEMU-%d/GI%s%*cMCS%d/%1d%*c", ++ ru_size[bw], he_gi[sgi], bw > 1 ? 1 : 2, ' ', ++ mcs, nss + 1, mcs > 9 ? 1 : 2, ' '); ++ ++ } ++ ++ return res; ++} ++ ++static int print_rate_from_cfg(char *buf, int size, u32 rate_config, int *r_idx, int ru_size) ++{ ++ union rwnx_rate_ctrl_info *r_cfg = (union rwnx_rate_ctrl_info *)&rate_config; ++ union rwnx_mcs_index *mcs_index = (union rwnx_mcs_index *)&rate_config; ++ unsigned int ft, pre, gi, bw, nss, mcs, len; ++ ++ ft = r_cfg->formatModTx; ++ pre = r_cfg->giAndPreTypeTx >> 1; ++ gi = r_cfg->giAndPreTypeTx; ++ bw = r_cfg->bwTx; ++ if (ft == FORMATMOD_HE_MU) { ++ mcs = mcs_index->he.mcs; ++ nss = mcs_index->he.nss; ++ bw = ru_size; ++ } else if (ft == FORMATMOD_HE_SU) { ++ mcs = mcs_index->he.mcs; ++ nss = mcs_index->he.nss; ++ } else if (ft == FORMATMOD_VHT) { ++ mcs = mcs_index->vht.mcs; ++ nss = mcs_index->vht.nss; ++ } else if (ft >= FORMATMOD_HT_MF) { ++ mcs = mcs_index->ht.mcs; ++ nss = mcs_index->ht.nss; ++ } else { ++ mcs = mcs_index->legacy; ++ nss = 0; ++ } ++ ++ len = print_rate(buf, size, ft, nss, mcs, bw, gi, pre, r_idx); ++ return len; ++} ++ ++static void idx_to_rate_cfg(int idx, union rwnx_rate_ctrl_info *r_cfg, int *ru_size) ++{ ++ r_cfg->value = 0; ++ if (idx < N_CCK) { ++ r_cfg->formatModTx = FORMATMOD_NON_HT; ++ r_cfg->giAndPreTypeTx = (idx & 1) << 1; ++ r_cfg->mcsIndexTx = idx / 2; ++ } else if (idx < (N_CCK + N_OFDM)) { ++ r_cfg->formatModTx = FORMATMOD_NON_HT; ++ r_cfg->mcsIndexTx = idx - N_CCK + 4; ++ } else if (idx < (N_CCK + N_OFDM + N_HT)) { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ idx -= (N_CCK + N_OFDM); ++ r_cfg->formatModTx = FORMATMOD_HT_MF; ++ r->ht.nss = idx / (8*2*2); ++ r->ht.mcs = (idx % (8*2*2)) / (2*2); ++ r_cfg->bwTx = ((idx % (8*2*2)) % (2*2)) / 2; ++ r_cfg->giAndPreTypeTx = idx & 1; ++ } else if (idx < (N_CCK + N_OFDM + N_HT + N_VHT)) { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ idx -= (N_CCK + N_OFDM + N_HT); ++ r_cfg->formatModTx = FORMATMOD_VHT; ++ r->vht.nss = idx / (10*4*2); ++ r->vht.mcs = (idx % (10*4*2)) / (4*2); ++ r_cfg->bwTx = ((idx % (10*4*2)) % (4*2)) / 2; ++ r_cfg->giAndPreTypeTx = idx & 1; ++ } else if (idx < (N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU)) { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ idx -= (N_CCK + N_OFDM + N_HT + N_VHT); ++ r_cfg->formatModTx = FORMATMOD_HE_SU; ++ r->vht.nss = idx / (12*4*3); ++ r->vht.mcs = (idx % (12*4*3)) / (4*3); ++ r_cfg->bwTx = ((idx % (12*4*3)) % (4*3)) / 3; ++ r_cfg->giAndPreTypeTx = idx % 3; ++ } else { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ BUG_ON(ru_size == NULL); ++ ++ idx -= (N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU); ++ r_cfg->formatModTx = FORMATMOD_HE_MU; ++ r->vht.nss = idx / (12*6*3); ++ r->vht.mcs = (idx % (12*6*3)) / (6*3); ++ *ru_size = ((idx % (12*6*3)) % (6*3)) / 3; ++ r_cfg->giAndPreTypeTx = idx % 3; ++ r_cfg->bwTx = 0; ++ } ++} ++ ++static void idx_to_rate_cfg1(unsigned int formatmod, ++ unsigned int mcs,unsigned int nss, ++ unsigned int bwTx,unsigned int gi, ++ union rwnx_rate_ctrl_info *r_cfg, int *ru_size) ++{ ++ r_cfg->value = 0; ++ ++ switch(formatmod){ ++ case FORMATMOD_NON_HT: ++ { ++ r_cfg->formatModTx = formatmod; ++ r_cfg->giAndPreTypeTx = 1; ++ r_cfg->mcsIndexTx = mcs; ++ break; ++ } ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ { ++ r_cfg->formatModTx = formatmod; ++ r_cfg->giAndPreTypeTx = gi; ++ r_cfg->mcsIndexTx = mcs; ++ break; ++ } ++ case FORMATMOD_HT_MF: ++ { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ r_cfg->formatModTx = formatmod; ++ r->ht.nss = nss; ++ r->ht.mcs = mcs; ++ r_cfg->bwTx = bwTx; ++ r_cfg->giAndPreTypeTx = gi; ++ break; ++ } ++ case FORMATMOD_VHT: ++ case FORMATMOD_HE_SU: ++ { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ r_cfg->formatModTx = formatmod; ++ r->vht.nss = nss; ++ r->vht.mcs = mcs; ++ r_cfg->bwTx = bwTx; ++ r_cfg->giAndPreTypeTx = gi; ++ break; ++ } ++ case FORMATMOD_HE_MU: ++ { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ r_cfg->formatModTx = formatmod; ++ r->he.nss = nss; ++ r->he.mcs = mcs; ++ r_cfg->bwTx = 0; ++ r_cfg->giAndPreTypeTx = gi; ++ break; ++ } ++ default: ++ printk("Don't have the formatmod"); ++ } ++} ++ ++static ssize_t rwnx_dbgfs_rc_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int bufsz, len = 0; ++ ssize_t read; ++ int i = 0; ++ int error = 0; ++ struct me_rc_stats_cfm me_rc_stats_cfm; ++ unsigned int no_samples; ++ struct st *st; ++ u8 mac[6]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* everything should fit in one call */ ++ if (*ppos) ++ return 0; ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ //if (mac == NULL) ++ // return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_me_rc_stats(priv, sta->sta_idx, &me_rc_stats_cfm); ++ if (error) ++ return error; ++ ++ no_samples = me_rc_stats_cfm.no_samples; ++ if (no_samples == 0) ++ return 0; ++ ++ bufsz = no_samples * LINE_MAX_SZ + 500; ++ ++ buf = kmalloc(bufsz + 1, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ st = kmalloc(sizeof(struct st) * no_samples, GFP_ATOMIC); ++ if (st == NULL) { ++ kfree(buf); ++ return 0; ++ } ++ ++ for (i = 0; i < no_samples; i++) { ++ unsigned int tp, eprob; ++ len = print_rate_from_cfg(st[i].line, LINE_MAX_SZ, ++ me_rc_stats_cfm.rate_stats[i].rate_config, ++ &st[i].r_idx, 0); ++ ++ if (me_rc_stats_cfm.sw_retry_step != 0) { ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c", ++ me_rc_stats_cfm.retry_step_idx[me_rc_stats_cfm.sw_retry_step] == i ? '*' : ' '); ++ } else { ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, " "); ++ } ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c", ++ me_rc_stats_cfm.retry_step_idx[0] == i ? 'T' : ' '); ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c", ++ me_rc_stats_cfm.retry_step_idx[1] == i ? 't' : ' '); ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c ", ++ me_rc_stats_cfm.retry_step_idx[2] == i ? 'P' : ' '); ++ ++ tp = me_rc_stats_cfm.tp[i] / 10; ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, " %4u.%1u", ++ tp / 10, tp % 10); ++ ++ eprob = ((me_rc_stats_cfm.rate_stats[i].probability * 1000) >> 16) + 1; ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, ++ " %4u.%1u %5u(%6u) %6u", ++ eprob / 10, eprob % 10, ++ me_rc_stats_cfm.rate_stats[i].success, ++ me_rc_stats_cfm.rate_stats[i].attempts, ++ me_rc_stats_cfm.rate_stats[i].sample_skipped); ++ } ++ len = scnprintf(buf, bufsz, ++ "\nTX rate info for %02X:%02X:%02X:%02X:%02X:%02X:\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ " # type rate tpt eprob ok( tot) skipped\n"); ++ ++ // add sorted statistics to the buffer ++ sort(st, no_samples, sizeof(st[0]), compare_idx, NULL); ++ for (i = 0; i < no_samples; i++) { ++ len += scnprintf(&buf[len], bufsz - len, "%s\n", st[i].line); ++ } ++ ++ // display HE TB statistics if any ++ if (me_rc_stats_cfm.rate_stats[RC_HE_STATS_IDX].rate_config != 0) { ++ unsigned int tp, eprob; ++ struct rc_rate_stats *rate_stats = &me_rc_stats_cfm.rate_stats[RC_HE_STATS_IDX]; ++ int ru_index = rate_stats->ru_and_length & 0x07; ++ int ul_length = rate_stats->ru_and_length >> 3; ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ "\nHE TB rate info:\n"); ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ " type rate tpt eprob ok( tot) ul_length\n "); ++ len += print_rate_from_cfg(&buf[len], bufsz - len, rate_stats->rate_config, ++ NULL, ru_index); ++ ++ tp = me_rc_stats_cfm.tp[RC_HE_STATS_IDX] / 10; ++ len += scnprintf(&buf[len], bufsz - len, " %4u.%1u", ++ tp / 10, tp % 10); ++ ++ eprob = ((rate_stats->probability * 1000) >> 16) + 1; ++ len += scnprintf(&buf[len], bufsz - len, ++ " %4u.%1u %5u(%6u) %6u\n", ++ eprob / 10, eprob % 10, ++ rate_stats->success, ++ rate_stats->attempts, ++ ul_length); ++ } ++ ++ len += scnprintf(&buf[len], bufsz - len, "\n MPDUs AMPDUs AvLen trialP"); ++ len += scnprintf(&buf[len], bufsz - len, "\n%6u %6u %3d.%1d %6u\n", ++ me_rc_stats_cfm.ampdu_len, ++ me_rc_stats_cfm.ampdu_packets, ++ me_rc_stats_cfm.avg_ampdu_len >> 16, ++ ((me_rc_stats_cfm.avg_ampdu_len * 10) >> 16) % 10, ++ me_rc_stats_cfm.sample_wait); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ kfree(st); ++ ++ return read; ++} ++ ++DEBUGFS_READ_FILE_OPS(rc_stats); ++ ++static ssize_t rwnx_dbgfs_rc_fixed_rate_idx_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ u8 mac[6]; ++ char buf[20]; ++ int fixed_rate_idx = 1; ++ unsigned int formatmod, mcs, nss, bwTx, gi; ++ union rwnx_rate_ctrl_info rate_config; ++ union rwnx_rate_ctrl_info *r_cfg=&rate_config; ++ int error = 0; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ //if (mac == NULL) ++ // return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ /* Get the content of the file */ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ //sscanf(buf, "%i\n", &fixed_rate_idx); ++ sscanf(buf, "%u %u %u %u %u",&formatmod, &mcs, &nss, &bwTx, &gi); ++ printk("%u %u %u %u %u\n",formatmod, mcs, nss, bwTx, gi); ++ ++ if((formatmod > 6) || (mcs > 11) || (nss > 8) || (bwTx > 6) || (gi > 3)){ ++ printk("error parameter"); ++ return len; ++ } ++ ++ /* Convert rate index into rate configuration */ ++ if ((fixed_rate_idx < 0) || (fixed_rate_idx >= (N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU))) ++ { ++ // disable fixed rate ++ rate_config.value = (u32)-1; ++ } ++ else ++ { ++ //idx_to_rate_cfg(fixed_rate_idx, &rate_config, NULL); ++ idx_to_rate_cfg1(formatmod, mcs, nss, bwTx, gi, &rate_config, NULL); ++ } ++ ++ printk("formatModTx=%u mcsIndexTx=%u bwTx=%u giAndPreTypeTx=%u\n",r_cfg->formatModTx,r_cfg->mcsIndexTx,r_cfg->bwTx,r_cfg->giAndPreTypeTx); ++ // Forward the request to the LMAC ++ if ((error = rwnx_send_me_rc_set_rate(priv, sta->sta_idx, ++ (u16)rate_config.value)) != 0) ++ { ++ return error; ++ } ++ ++ printk("send success \n"); ++ priv->debugfs.rc_config[sta->sta_idx] = (int)rate_config.value; ++ return len; ++ ++} ++ ++DEBUGFS_WRITE_FILE_OPS(rc_fixed_rate_idx); ++ ++static ssize_t rwnx_dbgfs_last_rx_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ struct rwnx_rx_rate_stats *rate_stats; ++ char *buf; ++ int bufsz, i, len = 0; ++ ssize_t read; ++ unsigned int fmt, pre, bw, nss, mcs, gi; ++ u8 mac[6]; ++ struct rx_vector_1 *last_rx; ++ char hist[] = "##################################################"; ++ int hist_len = sizeof(hist) - 1; ++ u8 nrx; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* everything should fit in one call */ ++ if (*ppos) ++ return 0; ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++// if (mac == NULL) ++// return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ rate_stats = &sta->stats.rx_rate; ++ bufsz = (rate_stats->rate_cnt * (50 + hist_len) + 200); ++ buf = kmalloc(bufsz + 1, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ // Get number of RX paths ++ nrx = (priv->version_cfm.version_phy_1 & MDM_NRX_MASK) >> MDM_NRX_LSB; ++ ++ len += scnprintf(buf, bufsz, ++ "\nRX rate info for %02X:%02X:%02X:%02X:%02X:%02X:\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ ++ // Display Statistics ++ for (i = 0; i < rate_stats->size; i++) { ++ if (rate_stats->table[i]) { ++ union rwnx_rate_ctrl_info rate_config; ++ int percent = (rate_stats->table[i] * 1000) / rate_stats->cpt; ++ int p = 0; ++ int ru_size = 0; ++ ++ idx_to_rate_cfg(i, &rate_config, &ru_size); ++ len += print_rate_from_cfg(&buf[len], bufsz - len, ++ rate_config.value, NULL, ru_size); ++ p = (percent * hist_len) / 1000; ++ len += scnprintf(&buf[len], bufsz - len, ": %6d(%3d.%1d%%)%.*s\n", ++ rate_stats->table[i], ++ percent / 10, percent % 10, p, hist); ++ } ++ } ++ ++ // Display detailed info of the last received rate ++ last_rx = &sta->stats.last_rx.rx_vect1; ++ ++ len += scnprintf(&buf[len], bufsz - len, "\nLast received rate\n" ++ " type rate LDPC STBC BEAMFM DCM DOPPLER %s\n", ++ (nrx > 1) ? "rssi1(dBm) rssi2(dBm)" : "rssi(dBm)"); ++ ++ fmt = last_rx->format_mod; ++ bw = last_rx->ch_bw; ++ pre = last_rx->pre_type; ++ if (fmt >= FORMATMOD_HE_SU) { ++ mcs = last_rx->he.mcs; ++ nss = last_rx->he.nss; ++ gi = last_rx->he.gi_type; ++ if (fmt == FORMATMOD_HE_MU) ++ bw = last_rx->he.ru_size; ++ } else if (fmt == FORMATMOD_VHT) { ++ mcs = last_rx->vht.mcs; ++ nss = last_rx->vht.nss; ++ gi = last_rx->vht.short_gi; ++ } else if (fmt >= FORMATMOD_HT_MF) { ++ mcs = last_rx->ht.mcs % 8; ++ nss = last_rx->ht.mcs / 8;; ++ gi = last_rx->ht.short_gi; ++ } else { ++ BUG_ON((mcs = legrates_lut[last_rx->leg_rate].idx) == -1); ++ nss = 0; ++ gi = 0; ++ } ++ ++ len += print_rate(&buf[len], bufsz - len, fmt, nss, mcs, bw, gi, pre, NULL); ++ ++ /* flags for HT/VHT/HE */ ++ if (fmt >= FORMATMOD_HE_SU) { ++ len += scnprintf(&buf[len], bufsz - len, " %c %c %c %c %c", ++ last_rx->he.fec ? 'L' : ' ', ++ last_rx->he.stbc ? 'S' : ' ', ++ last_rx->he.beamformed ? 'B' : ' ', ++ last_rx->he.dcm ? 'D' : ' ', ++ last_rx->he.doppler ? 'D' : ' '); ++ } else if (fmt == FORMATMOD_VHT) { ++ len += scnprintf(&buf[len], bufsz - len, " %c %c %c ", ++ last_rx->vht.fec ? 'L' : ' ', ++ last_rx->vht.stbc ? 'S' : ' ', ++ last_rx->vht.beamformed ? 'B' : ' '); ++ } else if (fmt >= FORMATMOD_HT_MF) { ++ len += scnprintf(&buf[len], bufsz - len, " %c %c ", ++ last_rx->ht.fec ? 'L' : ' ', ++ last_rx->ht.stbc ? 'S' : ' '); ++ } else { ++ len += scnprintf(&buf[len], bufsz - len, " "); ++ } ++ if (nrx > 1) { ++ len += scnprintf(&buf[len], bufsz - len, " %-4d %d\n", ++ last_rx->rssi1, last_rx->rssi1); ++ } else { ++ len += scnprintf(&buf[len], bufsz - len, " %d\n", last_rx->rssi1); ++ } ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_last_rx_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ u8 mac[6]; ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++// if (mac == NULL) ++// return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ /* Prevent from interrupt preemption as these statistics are updated under ++ * interrupt */ ++ spin_lock_bh(&priv->tx_lock); ++ memset(sta->stats.rx_rate.table, 0, ++ sta->stats.rx_rate.size * sizeof(sta->stats.rx_rate.table[0])); ++ sta->stats.rx_rate.cpt = 0; ++ sta->stats.rx_rate.rate_cnt = 0; ++ spin_unlock_bh(&priv->tx_lock); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(last_rx); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static void rwnx_rc_stat_work(struct work_struct *ws) ++{ ++ struct rwnx_debugfs *rwnx_debugfs = container_of(ws, struct rwnx_debugfs, ++ rc_stat_work); ++ struct rwnx_hw *rwnx_hw = container_of(rwnx_debugfs, struct rwnx_hw, ++ debugfs); ++ struct rwnx_sta *sta; ++ uint8_t ridx, sta_idx; ++ ++ ridx = rwnx_debugfs->rc_read; ++ sta_idx = rwnx_debugfs->rc_sta[ridx]; ++ if (sta_idx > (NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX)) { ++ WARN(1, "Invalid sta index %d", sta_idx); ++ return; ++ } ++ ++ rwnx_debugfs->rc_sta[ridx] = 0xFF; ++ ridx = (ridx + 1) % ARRAY_SIZE(rwnx_debugfs->rc_sta); ++ rwnx_debugfs->rc_read = ridx; ++ sta = &rwnx_hw->sta_table[sta_idx]; ++ if (!sta) { ++ WARN(1, "Invalid sta %d", sta_idx); ++ return; ++ } ++ ++ if (rwnx_debugfs->dir_sta[sta_idx] == NULL) { ++ /* register the sta */ ++ struct dentry *dir_rc = rwnx_debugfs->dir_rc; ++ struct dentry *dir_sta; ++ struct dentry *file; ++ char sta_name[18]; ++ struct rwnx_rx_rate_stats *rate_stats = &sta->stats.rx_rate; ++ int nb_rx_rate = N_CCK + N_OFDM; ++ struct rwnx_rc_config_save *rc_cfg, *next; ++ ++ if (sta->sta_idx >= NX_REMOTE_STA_MAX) { ++ scnprintf(sta_name, sizeof(sta_name), "bc_mc"); ++ } else { ++ scnprintf(sta_name, sizeof(sta_name), "%pM", sta->mac_addr); ++ } ++ ++ dir_sta = debugfs_create_dir(sta_name, dir_rc); ++ if (!dir_sta) ++ goto error; ++ ++ rwnx_debugfs->dir_sta[sta->sta_idx] = dir_sta; ++ ++ file = debugfs_create_file("stats", S_IRUSR, dir_sta, rwnx_hw, ++ &rwnx_dbgfs_rc_stats_ops); ++ if (IS_ERR_OR_NULL(file)) ++ goto error_after_dir; ++ ++ file = debugfs_create_file("fixed_rate_idx", S_IWUSR, dir_sta, rwnx_hw, ++ &rwnx_dbgfs_rc_fixed_rate_idx_ops); ++ if (IS_ERR_OR_NULL(file)) ++ goto error_after_dir; ++ ++ file = debugfs_create_file("rx_rate", S_IRUSR | S_IWUSR, dir_sta, rwnx_hw, ++ &rwnx_dbgfs_last_rx_ops); ++ if (IS_ERR_OR_NULL(file)) ++ goto error_after_dir; ++ ++ if (rwnx_hw->mod_params->ht_on) ++ nb_rx_rate += N_HT; ++ ++ if (rwnx_hw->mod_params->vht_on) ++ nb_rx_rate += N_VHT; ++ ++ if (rwnx_hw->mod_params->he_on) ++ nb_rx_rate += N_HE_SU + N_HE_MU; ++ ++ rate_stats->table = kzalloc(nb_rx_rate * sizeof(rate_stats->table[0]), ++ GFP_KERNEL); ++ if (!rate_stats->table) ++ goto error_after_dir; ++ ++ rate_stats->size = nb_rx_rate; ++ rate_stats->cpt = 0; ++ rate_stats->rate_cnt = 0; ++ ++ /* By default enable rate contoller */ ++ rwnx_debugfs->rc_config[sta_idx] = -1; ++ ++ /* Unless we already fix the rate for this station */ ++ list_for_each_entry_safe(rc_cfg, next, &rwnx_debugfs->rc_config_save, list) { ++ if (jiffies_to_msecs(jiffies - rc_cfg->timestamp) > RC_CONFIG_DUR) { ++ list_del(&rc_cfg->list); ++ kfree(rc_cfg); ++ } else if (!memcmp(rc_cfg->mac_addr, sta->mac_addr, ETH_ALEN)) { ++ rwnx_debugfs->rc_config[sta_idx] = rc_cfg->rate; ++ list_del(&rc_cfg->list); ++ kfree(rc_cfg); ++ break; ++ } ++ } ++ ++ if ((rwnx_debugfs->rc_config[sta_idx] >= 0) && ++ rwnx_send_me_rc_set_rate(rwnx_hw, sta_idx, ++ (u16)rwnx_debugfs->rc_config[sta_idx])) ++ rwnx_debugfs->rc_config[sta_idx] = -1; ++ ++ } else { ++ /* unregister the sta */ ++ if (sta->stats.rx_rate.table) { ++ kfree(sta->stats.rx_rate.table); ++ sta->stats.rx_rate.table = NULL; ++ } ++ sta->stats.rx_rate.size = 0; ++ sta->stats.rx_rate.cpt = 0; ++ sta->stats.rx_rate.rate_cnt = 0; ++ ++ /* If fix rate was set for this station, save the configuration in case ++ we reconnect to this station within RC_CONFIG_DUR msec */ ++ if (rwnx_debugfs->rc_config[sta_idx] >= 0) { ++ struct rwnx_rc_config_save *rc_cfg; ++ rc_cfg = kmalloc(sizeof(*rc_cfg), GFP_KERNEL); ++ if (rc_cfg) { ++ rc_cfg->rate = rwnx_debugfs->rc_config[sta_idx]; ++ rc_cfg->timestamp = jiffies; ++ memcpy(rc_cfg->mac_addr, sta->mac_addr, ETH_ALEN); ++ list_add_tail(&rc_cfg->list, &rwnx_debugfs->rc_config_save); ++ } ++ } ++ ++ debugfs_remove_recursive(rwnx_debugfs->dir_sta[sta_idx]); ++ rwnx_debugfs->dir_sta[sta->sta_idx] = NULL; ++ } ++ ++ return; ++ ++error_after_dir: ++ debugfs_remove_recursive(rwnx_debugfs->dir_sta[sta_idx]); ++ rwnx_debugfs->dir_sta[sta->sta_idx] = NULL; ++error: ++ dev_err(rwnx_hw->dev, ++ "Error while (un)registering debug entry for sta %d\n", sta_idx); ++} ++ ++void _rwnx_dbgfs_rc_stat_write(struct rwnx_debugfs *rwnx_debugfs, uint8_t sta_idx) ++{ ++ uint8_t widx = rwnx_debugfs->rc_write; ++ if (rwnx_debugfs->rc_sta[widx] != 0XFF) { ++ WARN(1, "Overlap in debugfs rc_sta table\n"); ++ } ++ ++ if (rwnx_debugfs->unregistering) ++ return; ++ ++ rwnx_debugfs->rc_sta[widx] = sta_idx; ++ widx = (widx + 1) % ARRAY_SIZE(rwnx_debugfs->rc_sta); ++ rwnx_debugfs->rc_write = widx; ++ ++ schedule_work(&rwnx_debugfs->rc_stat_work); ++} ++ ++void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{ ++ _rwnx_dbgfs_rc_stat_write(&rwnx_hw->debugfs, sta->sta_idx); ++} ++ ++void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{ ++ _rwnx_dbgfs_rc_stat_write(&rwnx_hw->debugfs, sta->sta_idx); ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct dentry *phyd = rwnx_hw->wiphy->debugfsdir; ++ struct dentry *dir_rc; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ struct rwnx_debugfs *rwnx_debugfs = &rwnx_hw->debugfs; ++ struct dentry *dir_drv, *dir_diags; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ dir_drv = debugfs_create_dir(name, phyd); ++ if (!dir_drv) ++ return -ENOMEM; ++ ++ rwnx_debugfs->dir = dir_drv; ++ rwnx_debugfs->unregistering = false; ++ ++ dir_diags = debugfs_create_dir("diags", dir_drv); ++ if (!dir_diags) ++ goto err; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ dir_rc = debugfs_create_dir("rc", dir_drv); ++ if (!dir_rc) ++ goto err; ++ rwnx_debugfs->dir_rc = dir_rc; ++ INIT_WORK(&rwnx_debugfs->rc_stat_work, rwnx_rc_stat_work); ++ INIT_LIST_HEAD(&rwnx_debugfs->rc_config_save); ++ rwnx_debugfs->rc_write = rwnx_debugfs->rc_read = 0; ++ memset(rwnx_debugfs->rc_sta, 0xFF, sizeof(rwnx_debugfs->rc_sta)); ++#endif ++ ++ DEBUGFS_ADD_U32(tcp_pacing_shift, dir_drv, &rwnx_hw->tcp_pacing_shift, ++ S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(stats, dir_drv, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(sys_stats, dir_drv, S_IRUSR); ++ DEBUGFS_ADD_FILE(txq, dir_drv, S_IRUSR); ++ DEBUGFS_ADD_FILE(acsinfo, dir_drv, S_IRUSR); ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ DEBUGFS_ADD_FILE(mu_group, dir_drv, S_IRUSR); ++#endif ++ DEBUGFS_ADD_FILE(regdbg, dir_drv, S_IWUSR); ++ DEBUGFS_ADD_FILE(vendor_hwconfig, dir_drv,S_IWUSR); ++ DEBUGFS_ADD_FILE(vendor_swconfig, dir_drv,S_IWUSR); ++ DEBUGFS_ADD_FILE(agg_disable, dir_drv,S_IWUSR); ++ DEBUGFS_ADD_FILE(set_roc, dir_drv,S_IWUSR); ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++ { ++ /* Create a p2p directory */ ++ struct dentry *dir_p2p; ++ dir_p2p = debugfs_create_dir("p2p", dir_drv); ++ if (!dir_p2p) ++ goto err; ++ ++ /* Add file allowing to control Opportunistic PS */ ++ DEBUGFS_ADD_FILE(oppps, dir_p2p, S_IRUSR); ++ /* Add file allowing to control Notice of Absence */ ++ DEBUGFS_ADD_FILE(noa, dir_p2p, S_IRUSR); ++ } ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++ if (rwnx_hw->fwlog_en) { ++ rwnx_fw_log_init(&rwnx_hw->debugfs.fw_log); ++ DEBUGFS_ADD_FILE(fw_log, dir_drv, S_IWUSR | S_IRUSR); ++ } ++#ifdef CONFIG_RWNX_RADAR ++ { ++ struct dentry *dir_radar, *dir_sec; ++ dir_radar = debugfs_create_dir("radar", dir_drv); ++ if (!dir_radar) ++ goto err; ++ ++ DEBUGFS_ADD_FILE(pulses_prim, dir_radar, S_IRUSR); ++ DEBUGFS_ADD_FILE(detected, dir_radar, S_IRUSR); ++ DEBUGFS_ADD_FILE(enable, dir_radar, S_IRUSR); ++ ++ if (rwnx_hw->phy.cnt == 2) { ++ DEBUGFS_ADD_FILE(pulses_sec, dir_radar, S_IRUSR); ++ ++ dir_sec = debugfs_create_dir("sec", dir_radar); ++ if (!dir_sec) ++ goto err; ++ ++ DEBUGFS_ADD_FILE(band, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(type, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(prim20, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(center1, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(center2, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(set, dir_sec, S_IWUSR | S_IRUSR); ++ } ++ } ++#endif /* CONFIG_RWNX_RADAR */ ++ return 0; ++ ++err: ++ rwnx_dbgfs_unregister(rwnx_hw); ++ return -ENOMEM; ++} ++ ++void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_debugfs *rwnx_debugfs = &rwnx_hw->debugfs; ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_rc_config_save *cfg, *next; ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ list_for_each_entry_safe(cfg, next, &rwnx_debugfs->rc_config_save, list) { ++ list_del(&cfg->list); ++ kfree(cfg); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (rwnx_hw->fwlog_en) ++ rwnx_fw_log_deinit(&rwnx_hw->debugfs.fw_log); ++ ++ if (!rwnx_hw->debugfs.dir) ++ return; ++ ++ rwnx_debugfs->unregistering = true; ++#ifdef CONFIG_RWNX_FULLMAC ++ flush_work(&rwnx_debugfs->rc_stat_work); ++#endif ++ debugfs_remove_recursive(rwnx_hw->debugfs.dir); ++ rwnx_hw->debugfs.dir = NULL; ++} ++ ++#endif /* CONFIG_DEBUG_FS */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h +new file mode 100644 +index 000000000000..7f5c7c9c575d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h +@@ -0,0 +1,202 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_debugfs.h ++ * ++ * @brief Miscellaneous utility function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++ ++#ifndef _RWNX_DEBUGFS_H_ ++#define _RWNX_DEBUGFS_H_ ++#include ++ ++#include ++#include ++#include "rwnx_fw_trace.h" ++ ++struct rwnx_hw; ++struct rwnx_sta; ++ ++/* some macros taken from iwlwifi */ ++/* TODO: replace with generic read and fill read buffer in open to avoid double ++ * reads */ ++#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ ++ if (!debugfs_create_file(#name, mode, parent, rwnx_hw, \ ++ &rwnx_dbgfs_##name##_ops)) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_X64(name, parent, ptr) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_x64(#name, S_IWUSR | S_IRUSR, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_U64(name, parent, ptr, mode) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_u64(#name, mode, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) ++#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ ++ debugfs_create_u32(#name, mode, \ ++ parent, ptr); \ ++} while (0) ++#else ++#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_u32(#name, mode, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++ } while (0) ++#endif ++ ++ ++ ++/* file operation */ ++#define DEBUGFS_READ_FUNC(name) \ ++ static ssize_t rwnx_dbgfs_##name##_read(struct file *file, \ ++ char __user *user_buf, \ ++ size_t count, loff_t *ppos); ++ ++#define DEBUGFS_WRITE_FUNC(name) \ ++ static ssize_t rwnx_dbgfs_##name##_write(struct file *file, \ ++ const char __user *user_buf,\ ++ size_t count, loff_t *ppos); ++ ++#define DEBUGFS_OPEN_FUNC(name) \ ++ static int rwnx_dbgfs_##name##_open(struct inode *inode, \ ++ struct file *file); ++ ++#define DEBUGFS_RELEASE_FUNC(name) \ ++ static int rwnx_dbgfs_##name##_release(struct inode *inode, \ ++ struct file *file); ++ ++#define DEBUGFS_READ_FILE_OPS(name) \ ++ DEBUGFS_READ_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .read = rwnx_dbgfs_##name##_read, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++#define DEBUGFS_WRITE_FILE_OPS(name) \ ++ DEBUGFS_WRITE_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .write = rwnx_dbgfs_##name##_write, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ ++ DEBUGFS_READ_FUNC(name); \ ++ DEBUGFS_WRITE_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .write = rwnx_dbgfs_##name##_write, \ ++ .read = rwnx_dbgfs_##name##_read, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++#define DEBUGFS_READ_WRITE_OPEN_RELEASE_FILE_OPS(name) \ ++ DEBUGFS_READ_FUNC(name); \ ++ DEBUGFS_WRITE_FUNC(name); \ ++ DEBUGFS_OPEN_FUNC(name); \ ++ DEBUGFS_RELEASE_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .write = rwnx_dbgfs_##name##_write, \ ++ .read = rwnx_dbgfs_##name##_read, \ ++ .open = rwnx_dbgfs_##name##_open, \ ++ .release = rwnx_dbgfs_##name##_release, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++ ++#ifdef CONFIG_RWNX_DEBUGFS ++ ++struct rwnx_debugfs { ++ unsigned long long rateidx; ++ struct dentry *dir; ++ bool trace_prst; ++ ++ char helper_cmd[64]; ++ //struct work_struct helper_work; ++ bool helper_scheduled; ++ spinlock_t umh_lock; ++ bool unregistering; ++ ++#ifndef CONFIG_RWNX_FHOST ++ struct rwnx_fw_log fw_log; ++#endif /* CONFIG_RWNX_FHOST */ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct work_struct rc_stat_work; ++ uint8_t rc_sta[NX_REMOTE_STA_MAX]; ++ uint8_t rc_write; ++ uint8_t rc_read; ++ struct dentry *dir_rc; ++ struct dentry *dir_sta[NX_REMOTE_STA_MAX]; ++ int rc_config[NX_REMOTE_STA_MAX]; ++ struct list_head rc_config_save; ++#endif ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++// Max duration in msecs to save rate config for a sta after disconnection ++#define RC_CONFIG_DUR 600000 ++ ++struct rwnx_rc_config_save { ++ struct list_head list; ++ unsigned long timestamp; ++ int rate; ++ u8 mac_addr[ETH_ALEN]; ++}; ++#endif ++ ++int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name); ++void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw); ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); ++void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); ++#endif ++#else ++struct rwnx_debugfs { ++}; ++static inline int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name) { return 0; } ++static inline void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw) {} ++#ifdef CONFIG_RWNX_FULLMAC ++static inline void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {} ++static inline void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {} ++#endif ++#endif /* CONFIG_RWNX_DEBUGFS */ ++ ++ ++#endif /* _RWNX_DEBUGFS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h +new file mode 100644 +index 000000000000..55e532bcbf8c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h +@@ -0,0 +1,769 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_defs.h ++ * ++ * @brief Main driver structure declarations for fullmac driver ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_DEFS_H_ ++#define _RWNX_DEFS_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rwnx_mod_params.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_tx.h" ++#include "rwnx_rx.h" ++#include "rwnx_radar.h" ++#include "rwnx_utils.h" ++#include "rwnx_mu_group.h" ++#include "rwnx_platform.h" ++#include "rwnx_cmds.h" ++#ifdef CONFIG_GKI ++#include "rwnx_gki.h" ++#endif ++#include "rwnx_compat.h" ++#ifdef CONFIG_FILTER_TCP_ACK ++#include "aicwf_tcp_ack.h" ++#endif ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#include "sdio_host.h" ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++#include "usb_host.h" ++#endif ++ ++#ifdef CONFIG_BR_SUPPORT ++#include "aic_br_ext.h" ++#endif /* CONFIG_BR_SUPPORT */ ++ ++#define WPI_HDR_LEN 18 ++#define WPI_PN_LEN 16 ++#define WPI_PN_OFST 2 ++#define WPI_MIC_LEN 16 ++#define WPI_KEY_LEN 32 ++#define WPI_SUBKEY_LEN 16 // WPI key is actually two 16bytes key ++ ++#define LEGACY_PS_ID 0 ++#define UAPSD_ID 1 ++ ++#define PS_SP_INTERRUPTED 255 ++#define MAC_ADDR_LEN 6 ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++enum nl80211_ac { ++ NL80211_AC_VO, ++ NL80211_AC_VI, ++ NL80211_AC_BE, ++ NL80211_AC_BK, ++ NL80211_NUM_ACS ++}; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++struct ieee80211_vht_operation { ++ u8 vht_op_info_chwidth; ++ u8 vht_op_info_chan_center_freq_seg1_idx; ++ u8 vht_op_info_chan_center_freq_seg2_idx; ++ __le16 vht_basic_mcs_set; ++} __packed; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++#define IEEE80211_RADIOTAP_VHT 21 ++#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004 ++#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040 ++ ++#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01 ++#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04 ++ ++#define NL80211_FEATURE_CELL_BASE_REG_HINTS 1 << 3 ++#define NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL 1 << 4 ++#define NL80211_FEATURE_SAE 1 << 5 ++#define NL80211_FEATURE_LOW_PRIORITY_SCAN 1 << 6 ++#define NL80211_FEATURE_SCAN_FLUSH 1 << 7 ++#define NL80211_FEATURE_AP_SCAN 1 << 8 ++#define NL80211_FEATURE_VIF_TXPOWER 1 << 9 ++#define NL80211_FEATURE_NEED_OBSS_SCAN 1 << 10 ++#define NL80211_FEATURE_P2P_GO_CTWIN 1 << 11 ++#define NL80211_FEATURE_P2P_GO_OPPPS 1 << 12 ++ ++/* 802.11ac VHT Capabilities */ ++#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 ++#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 ++#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 ++#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 ++#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 ++#define IEEE80211_VHT_CAP_RXLDPC 0x00000010 ++#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 ++#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 ++#define IEEE80211_VHT_CAP_TXSTBC 0x00000080 ++#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 ++#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 ++#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 ++#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 ++#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 ++#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 ++#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 ++#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000 ++#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 ++#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 ++#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 ++#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 ++#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23 ++#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \ ++ (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT) ++#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 ++#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 ++#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 ++#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 ++ ++enum ieee80211_vht_mcs_support { ++ IEEE80211_VHT_MCS_SUPPORT_0_7 = 0, ++ IEEE80211_VHT_MCS_SUPPORT_0_8 = 1, ++ IEEE80211_VHT_MCS_SUPPORT_0_9 = 2, ++ IEEE80211_VHT_MCS_NOT_SUPPORTED = 3, ++}; ++ ++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, ++}; ++ ++struct cfg80211_chan_def { ++ struct ieee80211_channel *chan; ++ enum nl80211_chan_width width; ++ u32 center_freq1; ++ u32 center_freq2; ++}; ++ ++enum nl80211_mesh_power_mode { ++ NL80211_MESH_POWER_UNKNOWN, ++ NL80211_MESH_POWER_ACTIVE, ++ NL80211_MESH_POWER_LIGHT_SLEEP, ++ NL80211_MESH_POWER_DEEP_SLEEP, ++ __NL80211_MESH_POWER_AFTER_LAST, ++ NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1 ++}; ++#endif ++ ++/** ++ * struct rwnx_bcn - Information of the beacon in used (AP mode) ++ * ++ * @head: head portion of beacon (before TIM IE) ++ * @tail: tail portion of beacon (after TIM IE) ++ * @ies: extra IEs (not used ?) ++ * @head_len: length of head data ++ * @tail_len: length of tail data ++ * @ies_len: length of extra IEs data ++ * @tim_len: length of TIM IE ++ * @len: Total beacon len (head + tim + tail + extra) ++ * @dtim: dtim period ++ */ ++struct rwnx_bcn { ++ u8 *head; ++ u8 *tail; ++ u8 *ies; ++ size_t head_len; ++ size_t tail_len; ++ size_t ies_len; ++ size_t tim_len; ++ size_t len; ++ u8 dtim; ++}; ++ ++/** ++ * struct rwnx_key - Key information ++ * ++ * @hw_idx: Idx of the key from hardware point of view ++ */ ++struct rwnx_key { ++ u8 hw_idx; ++}; ++ ++/** ++ * Structure containing information about a Mesh Path ++ */ ++struct rwnx_mesh_path { ++ struct list_head list; /* For rwnx_vif.mesh_paths */ ++ u8 path_idx; /* Path Index */ ++ struct mac_addr tgt_mac_addr; /* Target MAC Address */ ++ struct rwnx_sta *p_nhop_sta; /* Pointer to the Next Hop STA */ ++}; ++ ++struct rwnx_mesh_proxy { ++ struct list_head list; /* For rwnx_vif.mesh_proxy */ ++ struct mac_addr ext_sta_addr; /* Address of the External STA */ ++ struct mac_addr proxy_addr; /* Proxy MAC Address */ ++ bool local; /* Indicate if interface is a proxy for the device */ ++}; ++ ++/** ++ * struct rwnx_csa - Information for CSA (Channel Switch Announcement) ++ * ++ * @vif: Pointer to the vif doing the CSA ++ * @bcn: Beacon to use after CSA ++ * @elem: IPC buffer to send the new beacon to the fw ++ * @chandef: defines the channel to use after the switch ++ * @count: Current csa counter ++ * @status: Status of the CSA at fw level ++ * @ch_idx: Index of the new channel context ++ * @work: work scheduled at the end of CSA ++ */ ++struct rwnx_csa { ++ struct rwnx_vif *vif; ++ struct rwnx_bcn bcn; ++ struct rwnx_ipc_elem_var elem; ++ struct cfg80211_chan_def chandef; ++ int count; ++ int status; ++ int ch_idx; ++ struct work_struct work; ++}; ++ ++struct apm_probe_sta { ++ u8 sta_mac_addr[6]; ++ u8 vif_idx; ++ u64 probe_id; ++ struct work_struct apmprobestaWork; ++ struct workqueue_struct *apmprobesta_wq; ++}; ++/// Possible States of the TDLS link. ++enum tdls_status_tag { ++ /// TDLS link is not active (no TDLS peer connected) ++ TDLS_LINK_IDLE, ++ /// TDLS Setup Request transmitted ++ TDLS_SETUP_REQ_TX, ++ /// TDLS Setup Response transmitted ++ TDLS_SETUP_RSP_TX, ++ /// TDLS link is active (TDLS peer connected) ++ TDLS_LINK_ACTIVE, ++ /// TDLS Max Number of states. ++ TDLS_STATE_MAX ++}; ++ ++/* ++ * Structure used to save information relative to the TDLS peer. ++ * This is also linked within the rwnx_hw vifs list. ++ * ++ */ ++struct rwnx_tdls { ++ bool active; /* Indicate if TDLS link is active */ ++ bool initiator; /* Indicate if TDLS peer is the TDLS initiator */ ++ bool chsw_en; /* Indicate if channel switch is enabled */ ++ u8 last_tid; /* TID of the latest MPDU transmitted over the ++ TDLS direct link to the TDLS STA */ ++ u16 last_sn; /* Sequence number of the latest MPDU transmitted ++ over the TDLS direct link to the TDLS STA */ ++ bool ps_on; /* Indicate if the power save is enabled on the ++ TDLS STA */ ++ bool chsw_allowed; /* Indicate if TDLS channel switch is allowed */ ++}; ++ ++ ++/** ++ * enum rwnx_ap_flags - AP flags ++ * ++ * @RWNX_AP_ISOLATE Isolate clients (i.e. Don't brige packets transmitted by ++ * one client for another one) ++ */ ++enum rwnx_ap_flags { ++ RWNX_AP_ISOLATE = BIT(0), ++}; ++ ++/* ++ * Structure used to save information relative to the managed interfaces. ++ * This is also linked within the rwnx_hw vifs list. ++ * ++ */ ++struct rwnx_vif { ++ struct list_head list; ++ struct rwnx_hw *rwnx_hw; ++ struct wireless_dev wdev; ++ struct net_device *ndev; ++ struct net_device_stats net_stats; ++ struct rwnx_key key[6]; ++ unsigned long drv_flags; ++ atomic_t drv_conn_state; ++ u8 drv_vif_index; /* Identifier of the VIF in driver */ ++ u8 vif_index; /* Identifier of the station in FW */ ++ u8 ch_index; /* Channel context identifier */ ++ bool up; /* Indicate if associated netdev is up ++ (i.e. Interface is created at fw level) */ ++ bool use_4addr; /* Should we use 4addresses mode */ ++ bool is_resending; /* Indicate if a frame is being resent on this interface */ ++ bool user_mpm; /* In case of Mesh Point VIF, indicate if MPM is handled by userspace */ ++ bool roc_tdls; /* Indicate if the ROC has been called by a ++ TDLS station */ ++ u8 tdls_status; /* Status of the TDLS link */ ++ bool tdls_chsw_prohibited; /* Indicate if TDLS Channel Switch is prohibited */ ++ bool wep_enabled; /* 1 if WEP is enabled */ ++ bool wep_auth_err; /* 1 if auth status code is not supported auth alg when WEP enabled */ ++ enum nl80211_auth_type last_auth_type; /* Authentication type (algorithm) sent in the last connection ++ when WEP enabled */ ++ union { ++ struct { ++ struct rwnx_sta *ap; /* Pointer to the peer STA entry allocated for ++ the AP */ ++ struct rwnx_sta *tdls_sta; /* Pointer to the TDLS station */ ++ bool external_auth; /* Indicate if external authentication is in progress */ ++ u32 group_cipher_type; ++ u32 paired_cipher_type; ++ //connected network info start ++ char ssid[33];//ssid max is 32, but this has one spare for '\0' ++ int ssid_len; ++ u8 bssid[ETH_ALEN]; ++ u32 conn_owner_nlportid; ++ bool is_roam; ++ //connected network info end ++ } sta; ++ struct { ++ u16 flags; /* see rwnx_ap_flags */ ++ struct list_head sta_list; /* List of STA connected to the AP */ ++ struct rwnx_bcn bcn; /* beacon */ ++ u8 bcmc_index; /* Index of the BCMC sta to use */ ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ u8 aic_index; ++#endif ++ struct rwnx_csa *csa; ++ ++ struct list_head mpath_list; /* List of Mesh Paths used on this interface */ ++ struct list_head proxy_list; /* List of Proxies Information used on this interface */ ++ bool create_path; /* Indicate if we are waiting for a MESH_CREATE_PATH_CFM ++ message */ ++ int generation; /* Increased each time the list of Mesh Paths is updated */ ++ enum nl80211_mesh_power_mode mesh_pm; /* mesh power save mode currently set in firmware */ ++ enum nl80211_mesh_power_mode next_mesh_pm; /* mesh power save mode for next peer */ ++ } ap; ++ struct { ++ struct rwnx_vif *master; /* pointer on master interface */ ++ struct rwnx_sta *sta_4a; ++ } ap_vlan; ++ }; ++ ++ u8_l key_has_add; ++ u8_l is_p2p_vif; ++ struct apm_probe_sta sta_probe; ++ ++ #ifdef CONFIG_BR_SUPPORT ++ spinlock_t br_ext_lock; ++ /* unsigned int macclone_completed; */ ++ struct nat25_network_db_entry *nethash[NAT25_HASH_SIZE]; ++ int pppoe_connection_in_progress; ++ unsigned char pppoe_addr[MACADDRLEN]; ++ unsigned char scdb_mac[MACADDRLEN]; ++ unsigned char scdb_ip[4]; ++ struct nat25_network_db_entry *scdb_entry; ++ unsigned char br_mac[MACADDRLEN]; ++ unsigned char br_ip[4]; ++ ++ struct br_ext_info ethBrExtInfo; ++ #endif /* CONFIG_BR_SUPPORT */ ++}; ++ ++#define RWNX_VIF_TYPE(rwnx_vif) (rwnx_vif->wdev.iftype) ++ ++/** ++ * Structure used to store information relative to PS mode. ++ * ++ * @active: True when the sta is in PS mode. ++ * If false, other values should be ignored ++ * @pkt_ready: Number of packets buffered for the sta in drv's txq ++ * (1 counter for Legacy PS and 1 for U-APSD) ++ * @sp_cnt: Number of packets that remain to be pushed in the service period. ++ * 0 means that no service period is in progress ++ * (1 counter for Legacy PS and 1 for U-APSD) ++ */ ++struct rwnx_sta_ps { ++ bool active; ++ u16 pkt_ready[2]; ++ u16 sp_cnt[2]; ++}; ++ ++/** ++ * struct rwnx_rx_rate_stats - Store statistics for RX rates ++ * ++ * @table: Table indicating how many frame has been receive which each ++ * rate index. Rate index is the same as the one used by RC algo for TX ++ * @size: Size of the table array ++ * @cpt: number of frames received ++ */ ++struct rwnx_rx_rate_stats { ++ int *table; ++ int size; ++ int cpt; ++ int rate_cnt; ++}; ++ ++/** ++ * struct rwnx_sta_stats - Structure Used to store statistics specific to a STA ++ * ++ * @last_rx: Hardware vector of the last received frame ++ * @rx_rate: Statistics of the received rates ++ */ ++struct rwnx_sta_stats { ++ struct hw_vect last_rx; ++ struct rwnx_rx_rate_stats rx_rate; ++}; ++ ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++struct aic_sta { ++ u8 sta_idx; /* Identifier of the station */ ++ bool he; /* Flag indicating if the station supports HE */ ++ bool vht; /* Flag indicating if the station supports VHT */ ++ ++ struct ieee80211_he_cap_elem he_cap_elem; ++ struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ __le32 vht_cap_info; ++ struct ieee80211_vht_mcs_info supp_mcs; ++#endif ++}; ++#endif ++ ++/* ++ * Structure used to save information relative to the managed stations. ++ */ ++struct rwnx_sta { ++ struct list_head list; ++ u16 aid; /* association ID */ ++ u8 sta_idx; /* Identifier of the station */ ++ u8 vif_idx; /* Identifier of the VIF (fw id) the station ++ belongs to */ ++ u8 vlan_idx; /* Identifier of the VLAN VIF (fw id) the station ++ belongs to (= vif_idx if no vlan in used) */ ++ enum nl80211_band band; /* Band */ ++ enum nl80211_chan_width width; /* Channel width */ ++ u16 center_freq; /* Center frequency */ ++ u32 center_freq1; /* Center frequency 1 */ ++ u32 center_freq2; /* Center frequency 2 */ ++ u8 ch_idx; /* Identifier of the channel ++ context the station belongs to */ ++ bool qos; /* Flag indicating if the station ++ supports QoS */ ++ u8 acm; /* Bitfield indicating which queues ++ have AC mandatory */ ++ u16 uapsd_tids; /* Bitfield indicating which tids are subject to ++ UAPSD */ ++ u8 mac_addr[ETH_ALEN]; /* MAC address of the station */ ++ struct rwnx_key key; ++ bool valid; /* Flag indicating if the entry is valid */ ++ struct rwnx_sta_ps ps; /* Information when STA is in PS (AP only) */ ++#ifdef CONFIG_RWNX_BFMER ++ struct rwnx_bfmer_report *bfm_report; /* Beamforming report to be used for ++ VHT TX Beamforming */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ struct rwnx_sta_group_info group_info; /* MU grouping information for the STA */ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ bool ht; /* Flag indicating if the station ++ supports HT */ ++ bool vht; /* Flag indicating if the station ++ supports VHT */ ++ u32 ac_param[AC_MAX]; /* EDCA parameters */ ++ struct rwnx_tdls tdls; /* TDLS station information */ ++ struct rwnx_sta_stats stats; ++ enum nl80211_mesh_power_mode mesh_pm; /* link-specific mesh power save mode */ ++}; ++ ++static inline const u8 *rwnx_sta_addr(struct rwnx_sta *rwnx_sta) ++{ ++ return rwnx_sta->mac_addr; ++} ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++struct rwnx_amsdu_stats { ++ int done; ++ int failed; ++}; ++#endif ++ ++struct rwnx_stats { ++ int cfm_balance[NX_TXQ_CNT]; ++ unsigned long last_rx, last_tx; /* jiffies */ ++ int ampdus_tx[IEEE80211_MAX_AMPDU_BUF]; ++ int ampdus_rx[IEEE80211_MAX_AMPDU_BUF]; ++ int ampdus_rx_map[4]; ++ int ampdus_rx_miss; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ struct rwnx_amsdu_stats amsdus[NX_TX_PAYLOAD_MAX]; ++#endif ++ int amsdus_rx[64]; ++}; ++ ++struct rwnx_sec_phy_chan { ++ u16 prim20_freq; ++ u16 center_freq1; ++ u16 center_freq2; ++ enum nl80211_band band; ++ u8 type; ++}; ++ ++/* Structure that will contains all RoC information received from cfg80211 */ ++struct rwnx_roc_elem { ++ struct wireless_dev *wdev; ++ struct ieee80211_channel *chan; ++ unsigned int duration; ++ /* Used to avoid call of CFG80211 callback upon expiration of RoC */ ++ bool mgmt_roc; ++ /* Indicate if we have switch on the RoC channel */ ++ bool on_chan; ++}; ++ ++/* Structure containing channel survey information received from MAC */ ++struct rwnx_survey_info { ++ // Filled ++ u32 filled; ++ // Amount of time in ms the radio spent on the channel ++ u32 chan_time_ms; ++ // Amount of time the primary channel was sensed busy ++ u32 chan_time_busy_ms; ++ // Noise in dbm ++ s8 noise_dbm; ++}; ++ ++#define RWNX_CH_NOT_SET 0xFF ++#define RWNX_INVALID_VIF 0xFF ++#define RWNX_INVALID_STA 0xFF ++ ++/* Structure containing channel context information */ ++struct rwnx_chanctx { ++ struct cfg80211_chan_def chan_def; /* channel description */ ++ u8 count; /* number of vif using this ctxt */ ++}; ++ ++/** ++ * rwnx_phy_info - Phy information ++ * ++ * @phy_cnt: Number of phy interface ++ * @cfg: Configuration send to firmware ++ * @sec_chan: Channel configuration of the second phy interface (if phy_cnt > 1) ++ * @limit_bw: Set to true to limit BW on requested channel. Only set to use ++ * VHT with old radio that don't support 80MHz (deprecated) ++ */ ++struct rwnx_phy_info { ++ u8 cnt; ++ struct phy_cfg_tag cfg; ++ struct rwnx_sec_phy_chan sec_chan; ++ bool limit_bw; ++}; ++ ++ ++struct defrag_ctrl_info { ++ struct list_head list; ++ u8 sta_idx; ++ u8 tid; ++ u16 sn; ++ u8 next_fn; ++ u16 frm_len; ++ struct sk_buff *skb; ++ struct timer_list defrag_timer; ++ struct rwnx_hw *rwnx_hw; ++}; ++ ++struct amsdu_subframe_hdr { ++ u8 da[6]; ++ u8 sa[6]; ++ u16 sublen; ++}; ++ ++ ++/* rwnx driver status */ ++void rwnx_set_conn_state(atomic_t *drv_conn_state, int state); ++ ++enum rwnx_drv_connect_status { ++ RWNX_DRV_STATUS_DISCONNECTED = 0, ++ RWNX_DRV_STATUS_DISCONNECTING, ++ RWNX_DRV_STATUS_CONNECTING, ++ RWNX_DRV_STATUS_CONNECTED, ++ RWNX_DRV_STATUS_ROAMING, ++}; ++ ++static const char *const s_conn_state[] = { ++ "RWNX_DRV_STATUS_DISCONNECTED", ++ "RWNX_DRV_STATUS_DISCONNECTING", ++ "RWNX_DRV_STATUS_CONNECTING", ++ "RWNX_DRV_STATUS_CONNECTED", ++ "RWNX_DRV_STATUS_ROAMING", ++}; ++ ++ ++struct rwnx_hw { ++ struct rwnx_mod_params *mod_params; ++ struct device *dev; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ struct wiphy *wiphy; ++ struct list_head vifs; ++ struct rwnx_vif *vif_table[NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX]; /* indexed with fw id */ ++ struct rwnx_sta sta_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX]; ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ struct aic_sta aic_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX]; ++#endif ++ struct rwnx_survey_info survey[SCAN_CHANNEL_MAX]; ++ struct cfg80211_scan_request *scan_request; ++#ifdef CONFIG_SCHED_SCAN ++ struct cfg80211_sched_scan_request *sched_scan_req; ++#endif ++ struct rwnx_chanctx chanctx_table[NX_CHAN_CTXT_CNT]; ++ u8 cur_chanctx; ++ ++ u8 monitor_vif; /* FW id of the monitor interface, RWNX_INVALID_VIF if no monitor vif at fw level */ ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ /* tcp ack management */ ++ struct tcp_ack_manage ack_m; ++#endif ++ ++ /* RoC Management */ ++ struct rwnx_roc_elem *roc_elem; /* Information provided by cfg80211 in its remain on channel request */ ++ u32 roc_cookie_cnt; /* Counter used to identify RoC request sent by cfg80211 */ ++ ++ struct rwnx_cmd_mgr *cmd_mgr; ++ ++ struct rwnx_plat *plat; ++ ++ spinlock_t tx_lock; ++ spinlock_t cb_lock; ++ struct mutex mutex; /* per-device perimeter lock */ ++ ++ struct tasklet_struct task; ++ struct mm_version_cfm version_cfm; /* Lower layers versions - obtained via MM_VERSION_REQ */ ++ ++ u32 tcp_pacing_shift; ++ ++ /* IPC */ ++ struct ipc_host_env_tag *ipc_env; ++#ifdef AICWF_SDIO_SUPPORT ++ struct sdio_host_env_tag sdio_env; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct usb_host_env_tag usb_env; ++#endif ++ ++ struct rwnx_ipc_elem_pool e2amsgs_pool; ++ struct rwnx_ipc_elem_pool dbgmsgs_pool; ++ struct rwnx_ipc_elem_pool e2aradars_pool; ++ struct rwnx_ipc_elem_var pattern_elem; ++ struct rwnx_ipc_dbgdump_elem dbgdump_elem; ++ struct rwnx_ipc_elem_pool e2arxdesc_pool; ++ struct rwnx_ipc_skb_elem *e2aunsuprxvec_elems; ++ //struct rwnx_ipc_rxbuf_elems rxbuf_elems; ++ struct rwnx_ipc_elem_var scan_ie; ++ ++ struct kmem_cache *sw_txhdr_cache; ++ ++ struct rwnx_debugfs debugfs; ++ struct rwnx_stats stats; ++ ++#ifdef CONFIG_PREALLOC_TXQ ++ struct rwnx_txq *txq; ++#else ++ struct rwnx_txq txq[NX_NB_TXQ]; ++#endif ++ ++ struct rwnx_hwq hwq[NX_TXQ_CNT]; ++ ++ u64 avail_idx_map; ++ u8 vif_started; ++ bool adding_sta; ++ struct rwnx_phy_info phy; ++ ++ struct rwnx_radar radar; ++ ++ /* extended capabilities supported */ ++ u8 ext_capa[8]; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ struct rwnx_mu_info mu; ++#endif ++ u8 is_p2p_alive; ++ u8 is_p2p_connected; ++ struct timer_list p2p_alive_timer; ++ struct rwnx_vif *p2p_dev_vif; ++ atomic_t p2p_alive_timer_count; ++ bool band_5g_support; ++ u8_l vendor_info; ++ bool fwlog_en; ++ ++ struct list_head defrag_list; ++ spinlock_t defrag_lock; ++ ++ struct work_struct apmStalossWork; ++ struct workqueue_struct *apmStaloss_wq; ++ u8 apm_vif_idx; ++ u8 sta_mac_addr[6]; ++ ++ struct wakeup_source *ws_rx; ++ struct wakeup_source *ws_irqrx; ++ struct wakeup_source *ws_tx; ++ struct wakeup_source *ws_pwrctrl; ++ ++#ifdef CONFIG_SCHED_SCAN ++ bool is_sched_scan; ++#endif//CONFIG_SCHED_SCAN ++#ifdef CONFIG_TEMP_CONTROL ++ unsigned long started_jiffies; ++ s8_l temp; ++#endif ++ ++}; ++ ++u8 *rwnx_build_bcn(struct rwnx_bcn *bcn, struct cfg80211_beacon_data *new); ++ ++void rwnx_chanctx_link(struct rwnx_vif *vif, u8 idx, ++ struct cfg80211_chan_def *chandef); ++void rwnx_chanctx_unlink(struct rwnx_vif *vif); ++int rwnx_chanctx_valid(struct rwnx_hw *rwnx_hw, u8 idx); ++ ++extern u8 chip_id; ++ ++static inline bool is_multicast_sta(int sta_idx) ++{ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)) ++ { ++ return (sta_idx >= NX_REMOTE_STA_MAX_FOR_OLD_IC); ++ }else{ ++ return (sta_idx >= NX_REMOTE_STA_MAX); ++ } ++ ++} ++struct rwnx_sta *rwnx_get_sta(struct rwnx_hw *rwnx_hw, const u8 *mac_addr); ++ ++static inline uint8_t master_vif_idx(struct rwnx_vif *vif) ++{ ++ if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) { ++ return vif->ap_vlan.master->vif_index; ++ } else { ++ return vif->vif_index; ++ } ++} ++ ++void rwnx_external_auth_enable(struct rwnx_vif *vif); ++void rwnx_external_auth_disable(struct rwnx_vif *vif); ++ ++#endif /* _RWNX_DEFS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c +new file mode 100644 +index 000000000000..17d55da1156f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c +@@ -0,0 +1,297 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_dini.c - Add support for dini platform ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_dini.h" ++#include "rwnx_defs.h" ++#include "rwnx_irqs.h" ++#include "reg_access.h" ++ ++/* Config FPGA is accessed via bar0 */ ++#define CFPGA_DMA0_CTRL_REG 0x02C ++#define CFPGA_DMA1_CTRL_REG 0x04C ++#define CFPGA_DMA2_CTRL_REG 0x06C ++#define CFPGA_UINTR_SRC_REG 0x0E8 ++#define CFPGA_UINTR_MASK_REG 0x0EC ++#define CFPGA_BAR4_HIADDR_REG 0x100 ++#define CFPGA_BAR4_LOADDR_REG 0x104 ++#define CFPGA_BAR4_LOADDR_MASK_REG 0x110 ++#define CFPGA_BAR_TOUT 0x120 ++ ++#define CFPGA_DMA_CTRL_ENABLE 0x00001400 ++#define CFPGA_DMA_CTRL_DISABLE 0x00001000 ++#define CFPGA_DMA_CTRL_CLEAR 0x00001800 ++#define CFPGA_DMA_CTRL_REREAD_TIME_MASK (BIT(10) - 1) ++ ++#define CFPGA_BAR4_LOADDR_MASK_MAX 0xFF000000 ++ ++#define CFPGA_PCIEX_IT 0x00000001 ++#define CFPGA_ALL_ITS 0x0000000F ++ ++/* Programmable BAR4 Window start address */ ++#define CPU_RAM_WINDOW_HIGH 0x00000000 ++#define CPU_RAM_WINDOW_LOW 0x00000000 ++#define AHB_BRIDGE_WINDOW_HIGH 0x00000000 ++#define AHB_BRIDGE_WINDOW_LOW 0x60000000 ++ ++struct rwnx_dini { ++ u8 *pci_bar0_vaddr; ++ u8 *pci_bar4_vaddr; ++}; ++ ++static const u32 mv_cfg_fpga_dma_ctrl_regs[] = { ++ CFPGA_DMA0_CTRL_REG, ++ CFPGA_DMA1_CTRL_REG, ++ CFPGA_DMA2_CTRL_REG ++}; ++ ++/* This also clears running transactions */ ++static void dini_dma_on(struct rwnx_dini *rwnx_dini) ++{ ++ int i; ++ u32 reread_time; ++ volatile void *reg; ++ ++ for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) { ++ reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i]; ++ reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK; ++ ++ writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg); ++ writel(CFPGA_DMA_CTRL_ENABLE | reread_time, reg); ++ } ++} ++ ++/* This also clears running transactions */ ++static void dini_dma_off(struct rwnx_dini *rwnx_dini) ++{ ++ int i; ++ u32 reread_time; ++ volatile void *reg; ++ ++ for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) { ++ reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i]; ++ reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK; ++ ++ writel(CFPGA_DMA_CTRL_DISABLE | reread_time, reg); ++ writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg); ++ } ++} ++ ++ ++/* Configure address range for BAR4. ++ * By default BAR4_LOADDR_MASK value is 0xFF000000, then there is no need to ++ * change it because the addresses we need to access are covered by this mask ++ */ ++static void dini_set_bar4_win(u32 low, u32 high, struct rwnx_dini *rwnx_dini) ++{ ++ writel(low, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_REG); ++ writel(high, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_HIADDR_REG); ++ writel(CFPGA_BAR4_LOADDR_MASK_MAX, ++ rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_MASK_REG); ++} ++ ++ ++/** ++ * Enable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10 ++ * and request the corresponding IRQ line ++ */ ++int rwnx_cfpga_irq_enable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ unsigned int cfpga_uintr_mask; ++ volatile void *reg; ++ int ret; ++ ++ /* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */ ++ ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0, "rwnx", rwnx_hw); ++ if (ret) ++ return ret; ++ ++ reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG; ++ cfpga_uintr_mask = readl(reg); ++ writel(cfpga_uintr_mask | CFPGA_PCIEX_IT, reg); ++ ++ return ret; ++} ++ ++/** ++ * Disable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10 ++ * and free the corresponding IRQ line ++ */ ++int rwnx_cfpga_irq_disable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ unsigned int cfpga_uintr_mask; ++ volatile void *reg; ++ ++ reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG; ++ cfpga_uintr_mask = readl(reg); ++ writel(cfpga_uintr_mask & ~CFPGA_PCIEX_IT, reg); ++ ++ free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw); ++ ++ return 0; ++} ++ ++static int rwnx_dini_platform_enable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++#ifdef CONFIG_RWNX_SDM ++ writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT); ++#endif ++ ++ dini_dma_on(rwnx_dini); ++ return rwnx_cfpga_irq_enable(rwnx_hw); ++} ++ ++static int rwnx_dini_platform_disable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ int ret; ++ ++ ret = rwnx_cfpga_irq_disable(rwnx_hw); ++ dini_dma_off(rwnx_dini); ++ return ret; ++} ++ ++static void rwnx_dini_platform_deinit(struct rwnx_plat *rwnx_plat) ++{ ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++ pci_disable_device(rwnx_plat->pci_dev); ++ iounmap(rwnx_dini->pci_bar0_vaddr); ++ iounmap(rwnx_dini->pci_bar4_vaddr); ++ pci_release_regions(rwnx_plat->pci_dev); ++ ++ kfree(rwnx_plat); ++} ++ ++static u8 *rwnx_dini_get_address(struct rwnx_plat *rwnx_plat, int addr_name, ++ unsigned int offset) ++{ ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++ if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name)) ++ return NULL; ++ ++ if (addr_name == RWNX_ADDR_CPU) ++ dini_set_bar4_win(CPU_RAM_WINDOW_LOW, CPU_RAM_WINDOW_HIGH, rwnx_dini); ++ else ++ dini_set_bar4_win(AHB_BRIDGE_WINDOW_LOW, AHB_BRIDGE_WINDOW_HIGH, rwnx_dini); ++ ++ return rwnx_dini->pci_bar4_vaddr + offset; ++} ++ ++static void rwnx_dini_ack_irq(struct rwnx_plat *rwnx_plat) ++{ ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++ writel(CFPGA_ALL_ITS, rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_SRC_REG); ++} ++ ++static const u32 rwnx_dini_config_reg[] = { ++ NXMAC_DEBUG_PORT_SEL_ADDR, ++ SYSCTRL_DIAG_CONF_ADDR, ++ RF_V6_DIAGPORT_CONF1_ADDR, ++ RF_v6_PHYDIAG_CONF1_ADDR, ++}; ++ ++static int rwnx_dini_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list) ++{ ++ if (!list) ++ return 0; ++ ++ *list = rwnx_dini_config_reg; ++ return ARRAY_SIZE(rwnx_dini_config_reg); ++} ++ ++/** ++ * rwnx_dini_platform_init - Initialize the DINI platform ++ * ++ * @pci_dev PCI device ++ * @rwnx_plat Pointer on struct rwnx_stat * to be populated ++ * ++ * @return 0 on success, < 0 otherwise ++ * ++ * Allocate and initialize a rwnx_plat structure for the dini platform. ++ */ ++int rwnx_dini_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat) ++{ ++ struct rwnx_dini *rwnx_dini; ++ u16 pci_cmd; ++ int ret = 0; ++ ++ *rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_dini), ++ GFP_KERNEL); ++ if (!*rwnx_plat) ++ return -ENOMEM; ++ ++ rwnx_dini = (struct rwnx_dini *)(*rwnx_plat)->priv; ++ ++ /* Hotplug fixups */ ++ pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd); ++ pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; ++ pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd); ++ //pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2); ++ ++ ret = pci_enable_device(pci_dev); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_enable_device failed\n"); ++ goto out_enable; ++ } ++ ++ pci_set_master(pci_dev); ++#if 0 ++ ret = pci_request_regions(pci_dev, KBUILD_MODNAME); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_request_regions failed\n"); ++ goto out_request; ++ } ++#endif ++ rwnx_dini->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0); ++ if (!rwnx_dini->pci_bar0_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0); ++ ret = -ENOMEM; ++ goto out_bar0; ++ } ++ rwnx_dini->pci_bar4_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 4); ++ if (!rwnx_dini->pci_bar4_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 4); ++ ret = -ENOMEM; ++ goto out_bar4; ++ } ++ ++ (*rwnx_plat)->enable = rwnx_dini_platform_enable; ++ (*rwnx_plat)->disable = rwnx_dini_platform_disable; ++ (*rwnx_plat)->deinit = rwnx_dini_platform_deinit; ++ (*rwnx_plat)->get_address = rwnx_dini_get_address; ++ (*rwnx_plat)->ack_irq = rwnx_dini_ack_irq; ++ (*rwnx_plat)->get_config_reg = rwnx_dini_get_config_reg; ++ ++#ifdef CONFIG_RWNX_SDM ++ writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT); ++#endif ++ ++ return 0; ++ ++out_bar4: ++ iounmap(rwnx_dini->pci_bar0_vaddr); ++out_bar0: ++ pci_release_regions(pci_dev); ++//out_request: ++ pci_disable_device(pci_dev); ++out_enable: ++ kfree(*rwnx_plat); ++ return ret; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h +new file mode 100644 +index 000000000000..d9f57c10ed4f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h +@@ -0,0 +1,20 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_dini.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_DINI_H_ ++#define _RWNX_DINI_H_ ++ ++#include ++#include "rwnx_platform.h" ++ ++int rwnx_dini_platform_init(struct pci_dev *pci_dev, ++ struct rwnx_plat **rwnx_plat); ++ ++#endif /* _RWNX_DINI_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h +new file mode 100644 +index 000000000000..3bd59807f663 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h +@@ -0,0 +1,1326 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_events.h ++ * ++ * @brief Trace events definition ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM rwnx ++ ++#if !defined(_RWNX_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _RWNX_EVENTS_H ++ ++#include ++#ifndef CONFIG_RWNX_FHOST ++#include "rwnx_tx.h" ++#endif ++#include "rwnx_compat.h" ++ ++/***************************************************************************** ++ * TRACE function for MGMT TX (FULLMAC) ++ ****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++#include "linux/ieee80211.h" ++#if defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) ++#include ++ ++/* P2P Public Action Frames Definitions (see WiFi P2P Technical Specification, section 4.2.8) */ ++/* IEEE 802.11 Public Action Usage Category - Define P2P public action frames */ ++#define MGMT_ACTION_PUBLIC_CAT (0x04) ++/* Offset of OUI Subtype field in P2P Action Frame format */ ++#define MGMT_ACTION_OUI_SUBTYPE_OFFSET (6) ++/* P2P Public Action Frame Types */ ++enum p2p_action_type { ++ P2P_ACTION_GO_NEG_REQ = 0, /* GO Negociation Request */ ++ P2P_ACTION_GO_NEG_RSP, /* GO Negociation Response */ ++ P2P_ACTION_GO_NEG_CFM, /* GO Negociation Confirmation */ ++ P2P_ACTION_INVIT_REQ, /* P2P Invitation Request */ ++ P2P_ACTION_INVIT_RSP, /* P2P Invitation Response */ ++ P2P_ACTION_DEV_DISC_REQ, /* Device Discoverability Request */ ++ P2P_ACTION_DEV_DISC_RSP, /* Device Discoverability Response */ ++ P2P_ACTION_PROV_DISC_REQ, /* Provision Discovery Request */ ++ P2P_ACTION_PROV_DISC_RSP, /* Provision Discovery Response */ ++}; ++ ++const char *ftrace_print_mgmt_info(struct trace_seq *p, u16 frame_control, u8 cat, u8 type, u8 p2p) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ switch (frame_control & IEEE80211_FCTL_STYPE) { ++ case (IEEE80211_STYPE_ASSOC_REQ): ++ trace_seq_printf(p, "Association Request"); ++ break; ++ case (IEEE80211_STYPE_ASSOC_RESP): ++ trace_seq_printf(p, "Association Response"); ++ break; ++ case (IEEE80211_STYPE_REASSOC_REQ): ++ trace_seq_printf(p, "Reassociation Request"); ++ break; ++ case (IEEE80211_STYPE_REASSOC_RESP): ++ trace_seq_printf(p, "Reassociation Response"); ++ break; ++ case (IEEE80211_STYPE_PROBE_REQ): ++ trace_seq_printf(p, "Probe Request"); ++ break; ++ case (IEEE80211_STYPE_PROBE_RESP): ++ trace_seq_printf(p, "Probe Response"); ++ break; ++ case (IEEE80211_STYPE_BEACON): ++ trace_seq_printf(p, "Beacon"); ++ break; ++ case (IEEE80211_STYPE_ATIM): ++ trace_seq_printf(p, "ATIM"); ++ break; ++ case (IEEE80211_STYPE_DISASSOC): ++ trace_seq_printf(p, "Disassociation"); ++ break; ++ case (IEEE80211_STYPE_AUTH): ++ trace_seq_printf(p, "Authentication"); ++ break; ++ case (IEEE80211_STYPE_DEAUTH): ++ trace_seq_printf(p, "Deauthentication"); ++ break; ++ case (IEEE80211_STYPE_ACTION): ++ trace_seq_printf(p, "Action"); ++ if (cat == MGMT_ACTION_PUBLIC_CAT && type == 0x9) { ++ switch (p2p) { ++ case (P2P_ACTION_GO_NEG_REQ): ++ trace_seq_printf(p, ": GO Negociation Request"); ++ break; ++ case (P2P_ACTION_GO_NEG_RSP): ++ trace_seq_printf(p, ": GO Negociation Response"); ++ break; ++ case (P2P_ACTION_GO_NEG_CFM): ++ trace_seq_printf(p, ": GO Negociation Confirmation"); ++ break; ++ case (P2P_ACTION_INVIT_REQ): ++ trace_seq_printf(p, ": P2P Invitation Request"); ++ break; ++ case (P2P_ACTION_INVIT_RSP): ++ trace_seq_printf(p, ": P2P Invitation Response"); ++ break; ++ case (P2P_ACTION_DEV_DISC_REQ): ++ trace_seq_printf(p, ": Device Discoverability Request"); ++ break; ++ case (P2P_ACTION_DEV_DISC_RSP): ++ trace_seq_printf(p, ": Device Discoverability Response"); ++ break; ++ case (P2P_ACTION_PROV_DISC_REQ): ++ trace_seq_printf(p, ": Provision Discovery Request"); ++ break; ++ case (P2P_ACTION_PROV_DISC_RSP): ++ trace_seq_printf(p, ": Provision Discovery Response"); ++ break; ++ default: ++ trace_seq_printf(p, "Unknown p2p %d", p2p); ++ break; ++ } ++ } else { ++ switch (cat) { ++ case 0: ++ trace_seq_printf(p, ":Spectrum %d", type); ++ break; ++ case 1: ++ trace_seq_printf(p, ":QOS %d", type); break; ++ case 2: ++ trace_seq_printf(p, ":DLS %d", type); ++ break; ++ case 3: ++ trace_seq_printf(p, ":BA %d", type); ++ break; ++ case 4: ++ trace_seq_printf(p, ":Public %d", type); ++ break; ++ case 5: ++ trace_seq_printf(p, ":Radio Measure %d", type); ++ break; ++ case 6: ++ trace_seq_printf(p, ":Fast BSS %d", type); ++ break; ++ case 7: ++ trace_seq_printf(p, ":HT Action %d", type); ++ break; ++ case 8: ++ trace_seq_printf(p, ":SA Query %d", type); ++ break; ++ case 9: ++ trace_seq_printf(p, ":Protected Public %d", type); ++ break; ++ case 10: ++ trace_seq_printf(p, ":WNM %d", type); ++ break; ++ case 11: ++ trace_seq_printf(p, ":Unprotected WNM %d", type); ++ break; ++ case 12: ++ trace_seq_printf(p, ":TDLS %d", type); ++ break; ++ case 13: ++ trace_seq_printf(p, ":Mesh %d", type); ++ break; ++ case 14: ++ trace_seq_printf(p, ":MultiHop %d", type); ++ break; ++ case 15: ++ trace_seq_printf(p, ":Self Protected %d", type); ++ break; ++ case 126: ++ trace_seq_printf(p, ":Vendor protected"); ++ break; ++ case 127: ++ trace_seq_printf(p, ":Vendor"); ++ break; ++ default: ++ trace_seq_printf(p, ":Unknown category %d", cat); ++ break; ++ } ++ } ++ break; ++ default: ++ trace_seq_printf(p, "Unknown subtype %d", frame_control & IEEE80211_FCTL_STYPE); ++ break; ++ } ++ ++ trace_seq_putc(p, 0); ++ ++ return ret; ++} ++#endif /* defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) */ ++ ++#undef __print_mgmt_info ++#define __print_mgmt_info(frame_control, cat, type, p2p) ftrace_print_mgmt_info(p, frame_control, cat, type, p2p) ++ ++TRACE_EVENT( ++ roc, ++ TP_PROTO(u8 vif_idx, u16 freq, unsigned int duration), ++ TP_ARGS(vif_idx, freq, duration), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ __field(u16, freq) ++ __field(unsigned int, duration) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ __entry->freq = freq; ++ __entry->duration = duration; ++ ), ++ TP_printk("f=%d vif=%d dur=%d", ++ __entry->freq, __entry->vif_idx, __entry->duration) ++); ++ ++TRACE_EVENT( ++ cancel_roc, ++ TP_PROTO(u8 vif_idx), ++ TP_ARGS(vif_idx), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ ), ++ TP_printk("vif=%d", __entry->vif_idx) ++); ++ ++TRACE_EVENT( ++ roc_exp, ++ TP_PROTO(u8 vif_idx), ++ TP_ARGS(vif_idx), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ ), ++ TP_printk("vif=%d", __entry->vif_idx) ++); ++ ++TRACE_EVENT( ++ switch_roc, ++ TP_PROTO(u8 vif_idx), ++ TP_ARGS(vif_idx), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ ), ++ TP_printk("vif=%d", __entry->vif_idx) ++); ++ ++DECLARE_EVENT_CLASS( ++ mgmt_template, ++ TP_PROTO(u16 freq, u8 vif_idx, u8 sta_idx, struct ieee80211_mgmt *mgmt), ++ TP_ARGS(freq, vif_idx, sta_idx, mgmt), ++ TP_STRUCT__entry( ++ __field(u16, freq) ++ __field(u8, vif_idx) ++ __field(u8, sta_idx) ++ __field(u16, frame_control) ++ __field(u8, action_cat) ++ __field(u8, action_type) ++ __field(u8, action_p2p) ++ ), ++ TP_fast_assign( ++ __entry->freq = freq; ++ __entry->vif_idx = vif_idx; ++ __entry->sta_idx = sta_idx; ++ __entry->frame_control = mgmt->frame_control; ++ __entry->action_cat = mgmt->u.action.category; ++ __entry->action_type = mgmt->u.action.u.wme_action.action_code; ++ __entry->action_p2p = *((u8 *)&mgmt->u.action.category ++ + MGMT_ACTION_OUI_SUBTYPE_OFFSET); ++ ), ++ TP_printk("f=%d vif=%d sta=%d -> %s", ++ __entry->freq, __entry->vif_idx, __entry->sta_idx, ++ __print_mgmt_info(__entry->frame_control, __entry->action_cat, ++ __entry->action_type, __entry->action_p2p)) ++); ++ ++DEFINE_EVENT(mgmt_template, mgmt_tx, ++ TP_PROTO(u16 freq, u8 vif_idx, u8 sta_idx, struct ieee80211_mgmt *mgmt), ++ TP_ARGS(freq, vif_idx, sta_idx, mgmt)); ++ ++DEFINE_EVENT(mgmt_template, mgmt_rx, ++ TP_PROTO(u16 freq, u8 vif_idx, u8 sta_idx, struct ieee80211_mgmt *mgmt), ++ TP_ARGS(freq, vif_idx, sta_idx, mgmt)); ++ ++TRACE_EVENT( ++ mgmt_cfm, ++ TP_PROTO(u8 vif_idx, u8 sta_idx, bool acked), ++ TP_ARGS(vif_idx, sta_idx, acked), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ __field(u8, sta_idx) ++ __field(bool, acked) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ __entry->sta_idx = sta_idx; ++ __entry->acked = acked; ++ ), ++ TP_printk("vif=%d sta=%d ack=%d", ++ __entry->vif_idx, __entry->sta_idx, __entry->acked) ++); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/***************************************************************************** ++ * TRACE function for TXQ ++ ****************************************************************************/ ++#ifndef CONFIG_RWNX_FHOST ++#if defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) ++ ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#else ++#include ++#endif ++ ++const char * ++ftrace_print_txq(struct trace_seq *p, int txq_idx) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (txq_idx == TXQ_INACTIVE) { ++ trace_seq_printf(p, "[INACTIVE]"); ++ } else if (txq_idx < NX_FIRST_VIF_TXQ_IDX) { ++ trace_seq_printf(p, "[STA %d/%d]", ++ txq_idx / NX_NB_TXQ_PER_STA, ++ txq_idx % NX_NB_TXQ_PER_STA); ++#ifdef CONFIG_RWNX_FULLMAC ++ } else if (txq_idx < NX_FIRST_UNK_TXQ_IDX) { ++ trace_seq_printf(p, "[BC/MC %d]", ++ txq_idx - NX_FIRST_BCMC_TXQ_IDX); ++ } else if (txq_idx < NX_OFF_CHAN_TXQ_IDX) { ++ trace_seq_printf(p, "[UNKNOWN %d]", ++ txq_idx - NX_FIRST_UNK_TXQ_IDX); ++ } else if (txq_idx == NX_OFF_CHAN_TXQ_IDX) { ++ trace_seq_printf(p, "[OFFCHAN]"); ++#else ++ } else if (txq_idx < NX_NB_TXQ) { ++ txq_idx -= NX_FIRST_VIF_TXQ_IDX; ++ trace_seq_printf(p, "[VIF %d/%d]", ++ txq_idx / NX_NB_TXQ_PER_VIF, ++ txq_idx % NX_NB_TXQ_PER_VIF); ++#endif ++ } else { ++ trace_seq_printf(p, "[ERROR %d]", txq_idx); ++ } ++ ++ trace_seq_putc(p, 0); ++ ++ return ret; ++} ++ ++const char * ++ftrace_print_sta(struct trace_seq *p, int sta_idx) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (sta_idx < NX_REMOTE_STA_MAX) { ++ trace_seq_printf(p, "[STA %d]", sta_idx); ++ } else { ++ trace_seq_printf(p, "[BC/MC %d]", sta_idx - NX_REMOTE_STA_MAX); ++ } ++ ++ trace_seq_putc(p, 0); ++ ++ return ret; ++} ++ ++const char * ++ftrace_print_hwq(struct trace_seq *p, int hwq_idx) ++{ ++ ++ static const struct trace_print_flags symbols[] = { ++ {RWNX_HWQ_BK, "BK"}, ++ {RWNX_HWQ_BE, "BE"}, ++ {RWNX_HWQ_VI, "VI"}, ++ {RWNX_HWQ_VO, "VO"}, ++#ifdef CONFIG_RWNX_FULLMAC ++ {RWNX_HWQ_BCMC, "BCMC"}, ++#else ++ {RWNX_HWQ_BCN, "BCN"}, ++#endif ++ { -1, NULL } }; ++ return trace_print_symbols_seq(p, hwq_idx, symbols); ++} ++ ++const char * ++ftrace_print_hwq_cred(struct trace_seq *p, u8 *cred) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++#if CONFIG_USER_MAX == 1 ++ trace_seq_printf(p, "%d", cred[0]); ++#else ++ int i; ++ ++ for (i = 0; i < CONFIG_USER_MAX - 1; i++) ++ trace_seq_printf(p, "%d-", cred[i]); ++ trace_seq_printf(p, "%d", cred[i]); ++#endif ++ ++ trace_seq_putc(p, 0); ++ return ret; ++} ++ ++const char * ++ftrace_print_mu_info(struct trace_seq *p, u8 mu_info) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (mu_info) ++ trace_seq_printf(p, "MU: %d-%d", (mu_info & 0x3f), (mu_info >> 6)); ++ ++ trace_seq_putc(p, 0); ++ return ret; ++} ++ ++const char * ++ftrace_print_mu_group(struct trace_seq *p, int nb_user, u8 *users) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ int i; ++ ++ if (users[0] != 0xff) ++ trace_seq_printf(p, "(%d", users[0]); ++ else ++ trace_seq_printf(p, "(-"); ++ for (i = 1; i < CONFIG_USER_MAX ; i++) { ++ if (users[i] != 0xff) ++ trace_seq_printf(p, ",%d", users[i]); ++ else ++ trace_seq_printf(p, ",-"); ++ } ++ ++ trace_seq_printf(p, ")"); ++ trace_seq_putc(p, 0); ++ return ret; ++} ++ ++const char * ++ftrace_print_amsdu(struct trace_seq *p, u16 nb_pkt) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (nb_pkt > 1) ++ trace_seq_printf(p, "(AMSDU %d)", nb_pkt); ++ ++ trace_seq_putc(p, 0); ++ return ret; ++} ++#endif /* defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) */ ++ ++#undef __print_txq ++#define __print_txq(txq_idx) ftrace_print_txq(p, txq_idx) ++ ++#undef __print_sta ++#define __print_sta(sta_idx) ftrace_print_sta(p, sta_idx) ++ ++#undef __print_hwq ++#define __print_hwq(hwq) ftrace_print_hwq(p, hwq) ++ ++#undef __print_hwq_cred ++#define __print_hwq_cred(cred) ftrace_print_hwq_cred(p, cred) ++ ++#undef __print_mu_info ++#define __print_mu_info(mu_info) ftrace_print_mu_info(p, mu_info) ++ ++#undef __print_mu_group ++#define __print_mu_group(nb, users) ftrace_print_mu_group(p, nb, users) ++ ++#undef __print_amsdu ++#define __print_amsdu(nb_pkt) ftrace_print_amsdu(p, nb_pkt) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++TRACE_EVENT( ++ txq_select, ++ TP_PROTO(int txq_idx, u16 pkt_ready_up, struct sk_buff *skb), ++ TP_ARGS(txq_idx, pkt_ready_up, skb), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, pkt_ready) ++ __field(struct sk_buff *, skb) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq_idx; ++ __entry->pkt_ready = pkt_ready_up; ++ __entry->skb = skb; ++ ), ++ TP_printk("%s pkt_ready_up=%d skb=%p", __print_txq(__entry->txq_idx), ++ __entry->pkt_ready, __entry->skb) ++); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++DECLARE_EVENT_CLASS( ++ hwq_template, ++ TP_PROTO(u8 hwq_idx), ++ TP_ARGS(hwq_idx), ++ TP_STRUCT__entry( ++ __field(u8, hwq_idx) ++ ), ++ TP_fast_assign( ++ __entry->hwq_idx = hwq_idx; ++ ), ++ TP_printk("%s", __print_hwq(__entry->hwq_idx)) ++); ++ ++DEFINE_EVENT(hwq_template, hwq_flowctrl_stop, ++ TP_PROTO(u8 hwq_idx), ++ TP_ARGS(hwq_idx)); ++ ++DEFINE_EVENT(hwq_template, hwq_flowctrl_start, ++ TP_PROTO(u8 hwq_idx), ++ TP_ARGS(hwq_idx)); ++ ++ ++DECLARE_EVENT_CLASS( ++ txq_template, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ ), ++ TP_printk("%s", __print_txq(__entry->txq_idx)) ++); ++ ++DEFINE_EVENT(txq_template, txq_add_to_hw, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++DEFINE_EVENT(txq_template, txq_del_from_hw, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++DEFINE_EVENT(txq_template, txq_flowctrl_stop, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++DEFINE_EVENT(txq_template, txq_flowctrl_restart, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++TRACE_EVENT( ++ process_txq, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, len) ++ __field(u16, len_retry) ++ __field(s8, credit) ++ #ifdef CONFIG_RWNX_FULLMAC ++ __field(u16, limit) ++ #endif /* CONFIG_RWNX_FULLMAC*/ ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->len = skb_queue_len(&txq->sk_list); ++ #ifdef CONFIG_MAC80211_TXQ ++ __entry->len += txq->nb_ready_mac80211; ++ #endif ++ __entry->len_retry = txq->nb_retry; ++ __entry->credit = txq->credits; ++ #ifdef CONFIG_RWNX_FULLMAC ++ __entry->limit = txq->push_limit; ++ #endif /* CONFIG_RWNX_FULLMAC*/ ++ ), ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ TP_printk("%s txq_credits=%d, len=%d, retry_len=%d, push_limit=%d", ++ __print_txq(__entry->txq_idx), __entry->credit, ++ __entry->len, __entry->len_retry, __entry->limit) ++ #else ++ TP_printk("%s txq_credits=%d, len=%d, retry_len=%d", ++ __print_txq(__entry->txq_idx), __entry->credit, ++ __entry->len, __entry->len_retry) ++ #endif /* CONFIG_RWNX_FULLMAC*/ ++); ++ ++DECLARE_EVENT_CLASS( ++ txq_reason_template, ++ TP_PROTO(struct rwnx_txq *txq, u16 reason), ++ TP_ARGS(txq, reason), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, reason) ++ __field(u16, status) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->reason = reason; ++ __entry->status = txq->status; ++ ), ++ TP_printk("%s reason=%s status=%s", ++ __print_txq(__entry->txq_idx), ++ __print_symbolic(__entry->reason, ++ {RWNX_TXQ_STOP_FULL, "FULL"}, ++ {RWNX_TXQ_STOP_CSA, "CSA"}, ++ {RWNX_TXQ_STOP_STA_PS, "PS"}, ++ {RWNX_TXQ_STOP_VIF_PS, "VPS"}, ++ {RWNX_TXQ_STOP_CHAN, "CHAN"}, ++ {RWNX_TXQ_STOP_MU_POS, "MU"}), ++ __print_flags(__entry->status, "|", ++ {RWNX_TXQ_IN_HWQ_LIST, "IN LIST"}, ++ {RWNX_TXQ_STOP_FULL, "FULL"}, ++ {RWNX_TXQ_STOP_CSA, "CSA"}, ++ {RWNX_TXQ_STOP_STA_PS, "PS"}, ++ {RWNX_TXQ_STOP_VIF_PS, "VPS"}, ++ {RWNX_TXQ_STOP_CHAN, "CHAN"}, ++ {RWNX_TXQ_STOP_MU_POS, "MU"}, ++ {RWNX_TXQ_NDEV_FLOW_CTRL, "FLW_CTRL"})) ++); ++ ++DEFINE_EVENT(txq_reason_template, txq_start, ++ TP_PROTO(struct rwnx_txq *txq, u16 reason), ++ TP_ARGS(txq, reason)); ++ ++DEFINE_EVENT(txq_reason_template, txq_stop, ++ TP_PROTO(struct rwnx_txq *txq, u16 reason), ++ TP_ARGS(txq, reason)); ++ ++ ++TRACE_EVENT( ++ push_desc, ++ TP_PROTO(struct sk_buff *skb, struct rwnx_sw_txhdr *sw_txhdr, int push_flags), ++ ++ TP_ARGS(skb, sw_txhdr, push_flags), ++ ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(unsigned int, len) ++ __field(u16, tx_queue) ++ __field(u8, hw_queue) ++ __field(u8, push_flag) ++ __field(u32, flag) ++ __field(s8, txq_cred) ++ __field(u8, hwq_cred) ++ __field(u16, pkt_cnt) ++ __field(u8, mu_info) ++ ), ++ TP_fast_assign( ++ __entry->skb = skb; ++ __entry->tx_queue = sw_txhdr->txq->idx; ++ __entry->push_flag = push_flags; ++ __entry->hw_queue = sw_txhdr->txq->hwq->id; ++ __entry->txq_cred = sw_txhdr->txq->credits; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ __entry->pkt_cnt = sw_txhdr->desc.host.packet_cnt; ++#endif ++#ifdef CONFIG_RWNX_FULLMAC ++ __entry->flag = sw_txhdr->desc.host.flags; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->amsdu.len) ++ __entry->len = sw_txhdr->amsdu.len; ++ else ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ __entry->len = sw_txhdr->desc.host.packet_len[0]; ++#else ++ __entry->len = sw_txhdr->desc.host.packet_len; ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ ++#else /* !CONFIG_RWNX_FULLMAC */ ++ __entry->flag = sw_txhdr->desc.umac.flags; ++ __entry->len = sw_txhdr->frame_len; ++ __entry->sn = sw_txhdr->sn; ++#endif /* CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ __entry->mu_info = sw_txhdr->desc.host.mumimo_info; ++#else ++ __entry->mu_info = 0; ++#endif ++ ), ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ TP_printk("%s skb=%p (len=%d) hw_queue=%s cred_txq=%d cred_hwq=%d %s flag=%s %s%s%s", ++ __print_txq(__entry->tx_queue), __entry->skb, __entry->len, ++ __print_hwq(__entry->hw_queue), ++ __entry->txq_cred, __entry->hwq_cred, ++ __print_mu_info(__entry->mu_info), ++ __print_flags(__entry->flag, "|", ++ {TXU_CNTRL_RETRY, "RETRY"}, ++ {TXU_CNTRL_MORE_DATA, "MOREDATA"}, ++ {TXU_CNTRL_MGMT, "MGMT"}, ++ {TXU_CNTRL_MGMT_NO_CCK, "NO_CCK"}, ++ {TXU_CNTRL_MGMT_ROBUST, "ROBUST"}, ++ {TXU_CNTRL_AMSDU, "AMSDU"}, ++ {TXU_CNTRL_USE_4ADDR, "4ADDR"}, ++ {TXU_CNTRL_EOSP, "EOSP"}, ++ {TXU_CNTRL_MESH_FWD, "MESH_FWD"}, ++ {TXU_CNTRL_TDLS, "TDLS"}), ++ (__entry->push_flag & RWNX_PUSH_IMMEDIATE) ? "(IMMEDIATE)" : "", ++ (!(__entry->flag & TXU_CNTRL_RETRY) && ++ (__entry->push_flag & RWNX_PUSH_RETRY)) ? "(SW_RETRY)" : "", ++ __print_amsdu(__entry->pkt_cnt)) ++#else ++ TP_printk("%s skb=%p (len=%d) hw_queue=%s cred_txq=%d cred_hwq=%d %s flag=%x (%s) sn=%d %s", ++ __print_txq(__entry->tx_queue), __entry->skb, __entry->len, ++ __print_hwq(__entry->hw_queue), __entry->txq_cred, __entry->hwq_cred, ++ __print_mu_info(__entry->mu_info), ++ __entry->flag, ++ __print_flags(__entry->push_flag, "|", ++ {RWNX_PUSH_RETRY, "RETRY"}, ++ {RWNX_PUSH_IMMEDIATE, "IMMEDIATE"}), ++ __entry->sn, __print_amsdu(__entry->pkt_cnt)) ++#endif /* CONFIG_RWNX_FULLMAC */ ++); ++ ++ ++TRACE_EVENT( ++ txq_queue_skb, ++ TP_PROTO(struct sk_buff *skb, struct rwnx_txq *txq, bool retry), ++ TP_ARGS(skb, txq, retry), ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(s8, credit) ++ __field(u16, q_len) ++ __field(u16, q_len_retry) ++ __field(bool, retry) ++ ), ++ TP_fast_assign( ++ __entry->skb = skb; ++ __entry->txq_idx = txq->idx; ++ __entry->credit = txq->credits; ++ __entry->q_len = skb_queue_len(&txq->sk_list); ++ __entry->q_len_retry = txq->nb_retry; ++ __entry->retry = retry; ++ ), ++ ++ TP_printk("%s skb=%p retry=%d txq_credits=%d queue_len=%d (retry = %d)", ++ __print_txq(__entry->txq_idx), __entry->skb, __entry->retry, ++ __entry->credit, __entry->q_len, __entry->q_len_retry) ++); ++ ++#ifdef CONFIG_MAC80211_TXQ ++TRACE_EVENT( ++ txq_wake, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, q_len) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->q_len = txq->nb_ready_mac80211; ++ ), ++ ++ TP_printk("%s mac80211_queue_len=%d", __print_txq(__entry->txq_idx), __entry->q_len) ++); ++ ++TRACE_EVENT( ++ txq_drop, ++ TP_PROTO(struct rwnx_txq *txq, unsigned long nb_drop), ++ TP_ARGS(txq, nb_drop), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, nb_drop) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->nb_drop = nb_drop; ++ ), ++ ++ TP_printk("%s %u pkt have been dropped by codel in mac80211 txq", ++ __print_txq(__entry->txq_idx), __entry->nb_drop) ++); ++ ++#endif ++ ++ ++DECLARE_EVENT_CLASS( ++ idx_template, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ ), ++ TP_fast_assign( ++ __entry->idx = idx; ++ ), ++ TP_printk("idx=%d", __entry->idx) ++); ++ ++ ++DEFINE_EVENT(idx_template, txq_vif_start, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++DEFINE_EVENT(idx_template, txq_vif_stop, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++TRACE_EVENT( ++ process_hw_queue, ++ TP_PROTO(struct rwnx_hwq *hwq), ++ TP_ARGS(hwq), ++ TP_STRUCT__entry( ++ __field(u16, hwq) ++ __array(u8, credits, CONFIG_USER_MAX) ++ ), ++ TP_fast_assign( ++ __entry->hwq = hwq->id; ++ ), ++ TP_printk("hw_queue=%s hw_credits=%s", ++ __print_hwq(__entry->hwq), __print_hwq_cred(__entry->credits)) ++); ++ ++DECLARE_EVENT_CLASS( ++ sta_idx_template, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ ), ++ TP_fast_assign( ++ __entry->idx = idx; ++ ), ++ TP_printk("%s", __print_sta(__entry->idx)) ++); ++ ++DEFINE_EVENT(sta_idx_template, txq_sta_start, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++DEFINE_EVENT(sta_idx_template, txq_sta_stop, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++DEFINE_EVENT(sta_idx_template, ps_disable, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++TRACE_EVENT( ++ skb_confirm, ++ TP_PROTO(struct sk_buff *skb, struct rwnx_txq *txq, struct rwnx_hwq *hwq, ++#ifdef CONFIG_RWNX_FULLMAC ++ struct tx_cfm_tag *cfm ++#else ++ u8 cfm ++#endif ++ ), ++ ++ TP_ARGS(skb, txq, hwq, cfm), ++ ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(u8, hw_queue) ++ __array(u8, hw_credit, CONFIG_USER_MAX) ++ __field(s8, sw_credit) ++ __field(s8, sw_credit_up) ++#ifdef CONFIG_RWNX_FULLMAC ++ __field(u8, ampdu_size) ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ __field(u16, amsdu) ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ __field(u16, sn) ++#endif /* CONFIG_RWNX_FULLMAC*/ ++ ), ++ ++ TP_fast_assign( ++ __entry->skb = skb; ++ __entry->txq_idx = txq->idx; ++ __entry->hw_queue = hwq->id; ++ __entry->sw_credit = txq->credits; ++#if defined CONFIG_RWNX_FULLMAC ++ __entry->sw_credit_up = cfm->credits; ++ __entry->ampdu_size = cfm->ampdu_size; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ __entry->amsdu = cfm->amsdu_size; ++ __entry->sn = cfm->sn; ++#endif ++#else ++ __entry->sw_credit_up = cfm ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ), ++ ++ TP_printk("%s skb=%p hw_queue=%s, hw_credits=%s, txq_credits=%d (+%d)" ++#ifdef CONFIG_RWNX_FULLMAC ++ " sn=%u ampdu=%d" ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ " amsdu=%u" ++#endif ++#endif ++ , __print_txq(__entry->txq_idx), __entry->skb, ++ __print_hwq(__entry->hw_queue), ++ __print_hwq_cred(__entry->hw_credit), ++ __entry->sw_credit, __entry->sw_credit_up ++#ifdef CONFIG_RWNX_FULLMAC ++ , __entry->sn, __entry->ampdu_size ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ , __entry->amsdu ++#endif ++#endif ++ ) ++); ++ ++TRACE_EVENT( ++ credit_update, ++ TP_PROTO(struct rwnx_txq *txq, s8_l cred_up), ++ ++ TP_ARGS(txq, cred_up), ++ ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(s8, sw_credit) ++ __field(s8, sw_credit_up) ++ ), ++ ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->sw_credit = txq->credits; ++ __entry->sw_credit_up = cred_up; ++ ), ++ ++ TP_printk("%s txq_credits=%d (%+d)", __print_txq(__entry->txq_idx), ++ __entry->sw_credit, __entry->sw_credit_up) ++) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++DECLARE_EVENT_CLASS( ++ ps_template, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ __field(u16, ready_ps) ++ __field(u16, sp_ps) ++ __field(u16, ready_uapsd) ++ __field(u16, sp_uapsd) ++ ), ++ TP_fast_assign( ++ __entry->idx = sta->sta_idx; ++ __entry->ready_ps = sta->ps.pkt_ready[LEGACY_PS_ID]; ++ __entry->sp_ps = sta->ps.sp_cnt[LEGACY_PS_ID]; ++ __entry->ready_uapsd = sta->ps.pkt_ready[UAPSD_ID]; ++ __entry->sp_uapsd = sta->ps.sp_cnt[UAPSD_ID]; ++ ), ++ ++ TP_printk("%s [PS] ready=%d sp=%d [UAPSD] ready=%d sp=%d", ++ __print_sta(__entry->idx), __entry->ready_ps, __entry->sp_ps, ++ __entry->ready_uapsd, __entry->sp_uapsd) ++); ++ ++DEFINE_EVENT(ps_template, ps_queue, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta)); ++ ++DEFINE_EVENT(ps_template, ps_push, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta)); ++ ++DEFINE_EVENT(ps_template, ps_enable, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta)); ++ ++TRACE_EVENT( ++ ps_traffic_update, ++ TP_PROTO(u16 sta_idx, u8 traffic, bool uapsd), ++ ++ TP_ARGS(sta_idx, traffic, uapsd), ++ ++ TP_STRUCT__entry( ++ __field(u16, sta_idx) ++ __field(u8, traffic) ++ __field(bool, uapsd) ++ ), ++ ++ TP_fast_assign( ++ __entry->sta_idx = sta_idx; ++ __entry->traffic = traffic; ++ __entry->uapsd = uapsd; ++ ), ++ ++ TP_printk("%s %s%s traffic available ", __print_sta(__entry->sta_idx), ++ __entry->traffic ? "" : "no more ", ++ __entry->uapsd ? "U-APSD" : "legacy PS") ++); ++ ++TRACE_EVENT( ++ ps_traffic_req, ++ TP_PROTO(struct rwnx_sta *sta, u16 pkt_req, u8 ps_id), ++ TP_ARGS(sta, pkt_req, ps_id), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ __field(u16, pkt_req) ++ __field(u8, ps_id) ++ __field(u16, ready) ++ __field(u16, sp) ++ ), ++ TP_fast_assign( ++ __entry->idx = sta->sta_idx; ++ __entry->pkt_req = pkt_req; ++ __entry->ps_id = ps_id; ++ __entry->ready = sta->ps.pkt_ready[ps_id]; ++ __entry->sp = sta->ps.sp_cnt[ps_id]; ++ ), ++ ++ TP_printk("%s %s traffic request %d pkt (ready=%d, sp=%d)", ++ __print_sta(__entry->idx), ++ __entry->ps_id == UAPSD_ID ? "U-APSD" : "legacy PS", ++ __entry->pkt_req, __entry->ready, __entry->sp) ++); ++ ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++TRACE_EVENT( ++ amsdu_subframe, ++ TP_PROTO(struct rwnx_sw_txhdr *sw_txhdr), ++ TP_ARGS(sw_txhdr), ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(u8, nb) ++ __field(u32, len) ++ ), ++ TP_fast_assign( ++ __entry->skb = sw_txhdr->skb; ++ __entry->nb = sw_txhdr->amsdu.nb; ++ __entry->len = sw_txhdr->amsdu.len; ++ __entry->txq_idx = sw_txhdr->txq->idx; ++ ), ++ ++ TP_printk("%s skb=%p %s nb_subframe=%d, len=%u", ++ __print_txq(__entry->txq_idx), __entry->skb, ++ (__entry->nb == 2) ? "Start new AMSDU" : "Add subframe", ++ __entry->nb, __entry->len) ++); ++#endif ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++TRACE_EVENT( ++ mu_group_update, ++ TP_PROTO(struct rwnx_mu_group *group), ++ TP_ARGS(group), ++ TP_STRUCT__entry( ++ __field(u8, nb_user) ++ __field(u8, group_id) ++ __array(u8, users, CONFIG_USER_MAX) ++ ), ++ TP_fast_assign( ++ int i; ++ __entry->nb_user = group->user_cnt; ++ for (i = 0; i < CONFIG_USER_MAX ; i++) { ++ if (group->users[i]) { ++ __entry->users[i] = group->users[i]->sta_idx; ++ } else { ++ __entry->users[i] = 0xff; ++ } ++ } ++ ++ __entry->group_id = group->group_id; ++ ), ++ ++ TP_printk("Group-id = %d, Users = %s", ++ __entry->group_id, ++ __print_mu_group(__entry->nb_user, __entry->users)) ++); ++ ++TRACE_EVENT( ++ mu_group_delete, ++ TP_PROTO(int group_id), ++ TP_ARGS(group_id), ++ TP_STRUCT__entry( ++ __field(u8, group_id) ++ ), ++ TP_fast_assign( ++ __entry->group_id = group_id; ++ ), ++ ++ TP_printk("Group-id = %d", __entry->group_id) ++); ++ ++TRACE_EVENT( ++ mu_group_selection, ++ TP_PROTO(struct rwnx_sta *sta, int group_id), ++ TP_ARGS(sta, group_id), ++ TP_STRUCT__entry( ++ __field(u8, sta_idx) ++ __field(u8, group_id) ++ ), ++ TP_fast_assign( ++ __entry->sta_idx = sta->sta_idx; ++ __entry->group_id = group_id; ++ ), ++ ++ TP_printk("[Sta %d] Group-id = %d", __entry->sta_idx, __entry->group_id) ++); ++ ++TRACE_EVENT( ++ txq_select_mu_group, ++ TP_PROTO(struct rwnx_txq *txq, int group_id, int pos), ++ ++ TP_ARGS(txq, group_id, pos), ++ ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u8, group_id) ++ __field(u8, pos) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->group_id = group_id; ++ __entry->pos = pos; ++ ), ++ ++ TP_printk("%s: group=%d pos=%d", __print_txq(__entry->txq_idx), ++ __entry->group_id, __entry->pos) ++); ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* ! CONFIG_RWNX_FHOST */ ++ ++/***************************************************************************** ++ * TRACE functions for MESH ++ ****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++DECLARE_EVENT_CLASS( ++ mesh_path_template, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path), ++ TP_STRUCT__entry( ++ __field(u8, idx) ++ __field(u8, next_hop_sta) ++ __array(u8, tgt_mac, ETH_ALEN) ++ ), ++ ++ TP_fast_assign( ++ __entry->idx = mesh_path->path_idx; ++ memcpy(__entry->tgt_mac, &mesh_path->tgt_mac_addr, ETH_ALEN); ++ if (mesh_path->p_nhop_sta) ++ __entry->next_hop_sta = mesh_path->p_nhop_sta->sta_idx; ++ else ++ __entry->next_hop_sta = 0xff; ++ ), ++ ++ TP_printk("Mpath(%d): target=%pM next_hop=STA-%d", ++ __entry->idx, __entry->tgt_mac, __entry->next_hop_sta) ++); ++ ++DEFINE_EVENT(mesh_path_template, mesh_create_path, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path)); ++ ++DEFINE_EVENT(mesh_path_template, mesh_delete_path, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path)); ++ ++DEFINE_EVENT(mesh_path_template, mesh_update_path, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path)); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/***************************************************************************** ++ * TRACE functions for RADAR ++ ****************************************************************************/ ++#ifdef CONFIG_RWNX_RADAR ++TRACE_EVENT( ++ radar_pulse, ++ TP_PROTO(u8 chain, struct radar_pulse *pulse), ++ TP_ARGS(chain, pulse), ++ TP_STRUCT__entry( ++ __field(u8, chain) ++ __field(s16, freq) ++ __field(u16, pri) ++ __field(u8, len) ++ __field(u8, fom) ++ ), ++ TP_fast_assign( ++ __entry->freq = pulse->freq * 2; ++ __entry->len = pulse->len * 2; ++ __entry->fom = pulse->fom * 6; ++ __entry->pri = pulse->rep; ++ __entry->chain = chain; ++ ), ++ ++ TP_printk("%s: PRI=%.5d LEN=%.3d FOM=%.2d%% freq=%dMHz ", ++ __print_symbolic(__entry->chain, ++ {RWNX_RADAR_RIU, "RIU"}, ++ {RWNX_RADAR_FCU, "FCU"}), ++ __entry->pri, __entry->len, __entry->fom, __entry->freq) ++ ); ++ ++TRACE_EVENT( ++ radar_detected, ++ TP_PROTO(u8 chain, u8 region, s16 freq, u8 type, u16 pri), ++ TP_ARGS(chain, region, freq, type, pri), ++ TP_STRUCT__entry( ++ __field(u8, chain) ++ __field(u8, region) ++ __field(s16, freq) ++ __field(u8, type) ++ __field(u16, pri) ++ ), ++ TP_fast_assign( ++ __entry->chain = chain; ++ __entry->region = region; ++ __entry->freq = freq; ++ __entry->type = type; ++ __entry->pri = pri; ++ ), ++ TP_printk("%s: region=%s type=%d freq=%dMHz (pri=%dus)", ++ __print_symbolic(__entry->chain, ++ {RWNX_RADAR_RIU, "RIU"}, ++ {RWNX_RADAR_FCU, "FCU"}), ++ __print_symbolic(__entry->region, ++ {NL80211_DFS_UNSET, "UNSET"}, ++ {NL80211_DFS_FCC, "FCC"}, ++ {NL80211_DFS_ETSI, "ETSI"}, ++ {NL80211_DFS_JP, "JP"}), ++ __entry->type, __entry->freq, __entry->pri) ++); ++ ++TRACE_EVENT( ++ radar_set_region, ++ TP_PROTO(u8 region), ++ TP_ARGS(region), ++ TP_STRUCT__entry( ++ __field(u8, region) ++ ), ++ TP_fast_assign( ++ __entry->region = region; ++ ), ++ TP_printk("region=%s", ++ __print_symbolic(__entry->region, ++ {NL80211_DFS_UNSET, "UNSET"}, ++ {NL80211_DFS_FCC, "FCC"}, ++ {NL80211_DFS_ETSI, "ETSI"}, ++ {NL80211_DFS_JP, "JP"})) ++); ++ ++TRACE_EVENT( ++ radar_enable_detection, ++ TP_PROTO(u8 region, u8 enable, u8 chain), ++ TP_ARGS(region, enable, chain), ++ TP_STRUCT__entry( ++ __field(u8, region) ++ __field(u8, chain) ++ __field(u8, enable) ++ ), ++ TP_fast_assign( ++ __entry->chain = chain; ++ __entry->enable = enable; ++ __entry->region = region; ++ ), ++ TP_printk("%s: %s radar detection %s", ++ __print_symbolic(__entry->chain, ++ {RWNX_RADAR_RIU, "RIU"}, ++ {RWNX_RADAR_FCU, "FCU"}), ++ __print_symbolic(__entry->enable, ++ {RWNX_RADAR_DETECT_DISABLE, "Disable"}, ++ {RWNX_RADAR_DETECT_ENABLE, "Enable (no report)"}, ++ {RWNX_RADAR_DETECT_REPORT, "Enable"}), ++ __entry->enable == RWNX_RADAR_DETECT_DISABLE ? "" : ++ __print_symbolic(__entry->region, ++ {NL80211_DFS_UNSET, "UNSET"}, ++ {NL80211_DFS_FCC, "FCC"}, ++ {NL80211_DFS_ETSI, "ETSI"}, ++ {NL80211_DFS_JP, "JP"})) ++); ++#endif /* CONFIG_RWNX_RADAR */ ++ ++/***************************************************************************** ++ * TRACE functions for IPC message ++ ****************************************************************************/ ++#include "rwnx_strs.h" ++ ++DECLARE_EVENT_CLASS( ++ ipc_msg_template, ++ TP_PROTO(u16 id), ++ TP_ARGS(id), ++ TP_STRUCT__entry( ++ __field(u16, id) ++ ), ++ TP_fast_assign( ++ __entry->id = id; ++ ), ++ ++ TP_printk("%s (%d - %d)", RWNX_ID2STR(__entry->id), ++ MSG_T(__entry->id), MSG_I(__entry->id)) ++); ++ ++DEFINE_EVENT(ipc_msg_template, msg_send, ++ TP_PROTO(u16 id), ++ TP_ARGS(id)); ++ ++DEFINE_EVENT(ipc_msg_template, msg_recv, ++ TP_PROTO(u16 id), ++ TP_ARGS(id)); ++ ++ ++ ++#endif /* !defined(_RWNX_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ) */ ++ ++#undef TRACE_INCLUDE_PATH ++#undef TRACE_INCLUDE_FILE ++//#define TRACE_INCLUDE_PATH . ++#define TRACE_INCLUDE_PATH AIC_TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_FILE rwnx_events ++#include +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c +new file mode 100644 +index 000000000000..9151c8b81f59 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c +@@ -0,0 +1,48 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_fw_trace.c ++ * ++ * Copyright (C) RivieraWaves 2017-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_fw_trace.h" ++#include "aicwf_debug.h" ++ ++int rwnx_fw_log_init(struct rwnx_fw_log *fw_log) ++{ ++ u8 *buf = kmalloc(FW_LOG_SIZE, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ fw_log->buf.data = buf; ++ fw_log->buf.start = fw_log->buf.data; ++ fw_log->buf.size = 0; ++ fw_log->buf.end = fw_log->buf.data; ++ fw_log->buf.dataend = fw_log->buf.data + FW_LOG_SIZE; ++ spin_lock_init(&fw_log->lock); ++ ++ AICWFDBG(LOGINFO, "fw_log_init: %lx, %lx\n", (unsigned long)fw_log->buf.start, (unsigned long)(fw_log->buf.dataend)); ++ return 0; ++} ++ ++void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log) ++{ ++ if (!fw_log) ++ return; ++ ++ if (fw_log->buf.data) ++ kfree(fw_log->buf.data); ++ fw_log->buf.start = NULL; ++ fw_log->buf.end = NULL; ++ fw_log->buf.size = 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h +new file mode 100644 +index 000000000000..7956790957c3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h +@@ -0,0 +1,35 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_fw_trace.h ++ * ++ * Copyright (C) RivieraWaves 2017-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_FW_TRACE_H_ ++#define _RWNX_FW_TRACE_H_ ++ ++#include ++#include ++#include ++ ++#define FW_LOG_SIZE (10240) ++ ++struct rwnx_fw_log_buf { ++ uint8_t *data; ++ uint8_t *start; ++ uint8_t *end; ++ uint8_t *dataend; ++ uint32_t size; ++}; ++ ++struct rwnx_fw_log { ++ struct rwnx_fw_log_buf buf; ++ spinlock_t lock; ++}; ++ ++int rwnx_fw_log_init(struct rwnx_fw_log *fw_log); ++void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log); ++#endif /* _RWNX_FW_TRACE_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c +new file mode 100644 +index 000000000000..7f6333d91e59 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c +@@ -0,0 +1,408 @@ ++#include ++#ifdef ANDROID_PLATFORM ++#include "net/wireless/core.h" ++#endif ++#include ++ ++#undef NL80211_MCGRP_MLME ++#define NL80211_MCGRP_MLME 3 ++//#if IS_ENABLED(CONFIG_GKI_OPT_FEATURES) && IS_ENABLED(CONFIG_ANDROID) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++ ++static struct genl_family rwnx_nl80211_fam; ++ ++static bool __rwnx_cfg80211_unexpected_frame(struct net_device *dev, u8 cmd, ++ const u8 *addr, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid); ++ ++ if (!nlportid) ++ return false; ++ ++ msg = nlmsg_new(100, gfp); ++ if (!msg) ++ return true; ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, cmd); ++ if (!hdr) { ++ nlmsg_free(msg); ++ return true; ++ } ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || ++ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || ++ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); ++ return true; ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++ return true; ++} ++ ++bool rwnx_cfg80211_rx_spurious_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ bool ret; ++ ++ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && ++ wdev->iftype != NL80211_IFTYPE_P2P_GO)) { ++ return false; ++ } ++ ret = __rwnx_cfg80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, ++ addr, gfp); ++ return ret; ++} ++ ++bool rwnx_cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ bool ret; ++ ++ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && ++ wdev->iftype != NL80211_IFTYPE_P2P_GO && ++ wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { ++ return false; ++ } ++ ret = __rwnx_cfg80211_unexpected_frame(dev, ++ NL80211_CMD_UNEXPECTED_4ADDR_FRAME, ++ addr, gfp); ++ return ret; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) ++void rwnx_cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, ++ const u8 *ie, u8 ie_len, ++ int sig_dbm, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ ++ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) ++ return; ++ ++ msg = nlmsg_new(100 + ie_len, gfp); ++ if (!msg) ++ return; ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, NL80211_CMD_NEW_PEER_CANDIDATE); ++ if (!hdr) { ++ nlmsg_free(msg); ++ return; ++ } ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || ++ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || ++ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || ++ (ie_len && ie && ++ nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) || ++ (sig_dbm && ++ nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm))) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++#define NL80211_MCGRP_MLME 3 ++ genlmsg_multicast_netns(&rwnx_nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, ++ NL80211_MCGRP_MLME, gfp); ++ return; ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++} ++#endif ++ ++void rwnx_cfg80211_report_obss_beacon(struct wiphy *wiphy, ++ const u8 *frame, size_t len, ++ int freq, int sig_dbm) ++{ ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ struct cfg80211_beacon_registration *reg; ++ ++ spin_lock_bh(&rdev->beacon_registrations_lock); ++ list_for_each_entry(reg, &rdev->beacon_registrations, list) { ++ msg = nlmsg_new(len + 100, GFP_ATOMIC); ++ if (!msg) { ++ spin_unlock_bh(&rdev->beacon_registrations_lock); ++ return; ++ } ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, NL80211_CMD_FRAME); ++ if (!hdr) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || ++ (freq && ++ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || ++ (sig_dbm && ++ nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || ++ nla_put(msg, NL80211_ATTR_FRAME, len, frame)) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid); ++ } ++ spin_unlock_bh(&rdev->beacon_registrations_lock); ++ return; ++ ++ nla_put_failure: ++ spin_unlock_bh(&rdev->beacon_registrations_lock); ++ nlmsg_free(msg); ++} ++ ++static int rwnx_nl80211_send_chandef(struct sk_buff *msg, ++ const struct cfg80211_chan_def *chandef) ++{ ++ if (WARN_ON(!cfg80211_chandef_valid(chandef))) ++ return -EINVAL; ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, ++ chandef->chan->center_freq)) ++ return -ENOBUFS; ++ switch (chandef->width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ case NL80211_CHAN_WIDTH_40: ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ++ cfg80211_get_chandef_type(chandef))) ++ return -ENOBUFS; ++ break; ++ default: ++ break; ++ } ++ if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width)) ++ return -ENOBUFS; ++ if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1)) ++ return -ENOBUFS; ++ if (chandef->center_freq2 && ++ nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2)) ++ return -ENOBUFS; ++ return 0; ++} ++ ++void rwnx_cfg80211_ch_switch_notify(struct cfg80211_registered_device *rdev, ++ struct net_device *netdev, ++ struct cfg80211_chan_def *chandef, ++ gfp_t gfp, ++ enum nl80211_commands notif, ++ u8 count) ++{ ++ struct sk_buff *msg; ++ void *hdr; ++ ++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); ++ if (!msg) ++ return; ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, notif); ++ if (!hdr) { ++ nlmsg_free(msg); ++ return; ++ } ++ ++ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) ++ goto nla_put_failure; ++ ++ if (rwnx_nl80211_send_chandef(msg, chandef)) ++ goto nla_put_failure; ++ ++ if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) && ++ (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++ genlmsg_multicast_netns(&rwnx_nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, ++ NL80211_MCGRP_MLME, gfp); ++ return; ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++} ++ ++void rwnx_cfg80211_ch_switch_started_notify(struct net_device *dev, ++ struct cfg80211_chan_def *chandef, ++ u8 count ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ , bool quiet ++ #endif ++ ) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct wiphy *wiphy = wdev->wiphy; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ ++ rwnx_cfg80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL, ++ NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count); ++} ++ ++int rwnx_regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, ++ struct ieee80211_regdomain *rd) ++{ ++ wiphy_apply_custom_regulatory(wiphy, rd); ++ return 0; ++} ++ ++void rwnx_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list) ++{ ++ unsigned long flags; ++ struct sk_buff *prev = old; ++ struct sk_buff *next = prev->next; ++ spin_lock_irqsave(&list->lock, flags); ++ WRITE_ONCE(newsk->next, next); ++ WRITE_ONCE(newsk->prev, prev); ++ WRITE_ONCE(next->prev, newsk); ++ WRITE_ONCE(prev->next, newsk); ++ list->qlen++; ++ spin_unlock_irqrestore(&list->lock, flags); ++} ++ ++bool rwnx_ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, ++ u8 *op_class) ++{ ++ u8 vht_opclass; ++ u32 freq = chandef->center_freq1; ++ ++ if (freq >= 2412 && freq <= 2472) { ++ if (chandef->width > NL80211_CHAN_WIDTH_40) ++ return false; ++ ++ /* 2.407 GHz, channels 1..13 */ ++ if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 83; /* HT40+ */ ++ else ++ *op_class = 84; /* HT40- */ ++ } else { ++ *op_class = 81; ++ } ++ ++ return true; ++ } ++ ++ if (freq == 2484) { ++ /* channel 14 is only for IEEE 802.11b */ ++ if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT) ++ return false; ++ ++ *op_class = 82; /* channel 14 */ ++ return true; ++ } ++ ++ switch (chandef->width) { ++ case NL80211_CHAN_WIDTH_80: ++ vht_opclass = 128; ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ vht_opclass = 129; ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ vht_opclass = 130; ++ break; ++ case NL80211_CHAN_WIDTH_10: ++ case NL80211_CHAN_WIDTH_5: ++ return false; /* unsupported for now */ ++ default: ++ vht_opclass = 0; ++ break; ++ } ++ ++ /* 5 GHz, channels 36..48 */ ++ if (freq >= 5180 && freq <= 5240) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 116; ++ else ++ *op_class = 117; ++ } else { ++ *op_class = 115; ++ } ++ ++ return true; ++ } ++ ++ /* 5 GHz, channels 52..64 */ ++ if (freq >= 5260 && freq <= 5320) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 119; ++ else ++ *op_class = 120; ++ } else { ++ *op_class = 118; ++ } ++ ++ return true; ++ } ++ ++ /* 5 GHz, channels 100..144 */ ++ if (freq >= 5500 && freq <= 5720) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 122; ++ else ++ *op_class = 123; ++ } else { ++ *op_class = 121; ++ } ++ ++ return true; ++ } ++ ++ /* 5 GHz, channels 149..169 */ ++ if (freq >= 5745 && freq <= 5845) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 126; ++ else ++ *op_class = 127; ++ } else if (freq <= 5805) { ++ *op_class = 124; ++ } else { ++ *op_class = 125; ++ } ++ ++ return true; ++ } ++ ++ /* 56.16 GHz, channel 1..4 */ ++ if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) { ++ if (chandef->width >= NL80211_CHAN_WIDTH_40) ++ return false; ++ ++ *op_class = 180; ++ return true; ++ } ++ ++ /* not supported yet */ ++ return false; ++} ++ ++int rwnx_call_usermodehelper(const char *path, char **argv, char **envp, int wait) ++{ ++ return -1; ++} ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h +new file mode 100644 +index 000000000000..a41f57832279 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h +@@ -0,0 +1,72 @@ ++#ifndef __RWNX_GKI_H ++#define __RWNX_GKI_H ++ ++#ifdef ANDROID_PLATFORM ++#include "net/wireless/core.h" ++#endif ++ ++//#if IS_ENABLED(CONFIG_GKI_OPT_FEATURES) && IS_ENABLED(CONFIG_ANDROID) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++ ++ ++bool rwnx_cfg80211_rx_spurious_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp); ++ ++bool rwnx_cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) ++void rwnx_cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, ++ const u8 *ie, u8 ie_len, ++ int sig_dbm, gfp_t gfp); ++#endif ++ ++void rwnx_cfg80211_report_obss_beacon(struct wiphy *wiphy, ++ const u8 *frame, size_t len, ++ int freq, int sig_dbm); ++ ++void rwnx_cfg80211_ch_switch_notify(struct cfg80211_registered_device *rdev, ++ struct net_device *netdev, ++ struct cfg80211_chan_def *chandef, ++ gfp_t gfp, ++ enum nl80211_commands notif, ++ u8 count); ++ ++void rwnx_cfg80211_ch_switch_started_notify(struct net_device *dev, ++ struct cfg80211_chan_def *chandef, ++ u8 count ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ , bool quiet ++ #endif ++ ); ++ ++int rwnx_regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, ++ struct ieee80211_regdomain *rd); ++ ++void rwnx_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list); ++ ++bool rwnx_ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, ++ u8 *op_class); ++ ++int rwnx_call_usermodehelper(const char *path, char **argv, char **envp, int wait); ++ ++#else ++ ++#define rwnx_cfg80211_rx_spurious_frame cfg80211_rx_spurious_frame ++#define rwnx_cfg80211_rx_unexpected_4addr_frame cfg80211_rx_unexpected_4addr_frame ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) ++#define rwnx_cfg80211_notify_new_peer_candidate cfg80211_notify_new_peer_candidate ++#endif ++ ++#define rwnx_cfg80211_report_obss_beacon cfg80211_report_obss_beacon ++#define rwnx_cfg80211_ch_switch_notify cfg80211_ch_switch_notify ++#define rwnx_cfg80211_ch_switch_started_notify cfg80211_ch_switch_started_notify ++#define rwnx_regulatory_set_wiphy_regd_sync_rtnl regulatory_set_wiphy_regd_sync_rtnl ++#define rwnx_skb_append skb_append ++#define rwnx_ieee80211_chandef_to_operating_class ieee80211_chandef_to_operating_class ++#define rwnx_call_usermodehelper call_usermodehelper ++ ++#endif ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c +new file mode 100644 +index 000000000000..8ba95b703f17 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c +@@ -0,0 +1,65 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_irqs.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++ ++#include "rwnx_defs.h" ++#include "ipc_host.h" ++#include "rwnx_prof.h" ++ ++/** ++ * rwnx_irq_hdlr - IRQ handler ++ * ++ * Handler registerd by the platform driver ++ */ ++irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id) ++{ ++ struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)dev_id; ++ disable_irq_nosync(irq); ++ tasklet_schedule(&rwnx_hw->task); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * rwnx_task - Bottom half for IRQ handler ++ * ++ * Read irq status and process accordingly ++ */ ++void rwnx_task(unsigned long data) ++{ ++ struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)data; ++ ++#if 0 ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ u32 status, statuses = 0; ++ ++ /* Ack unconditionnally in case ipc_host_get_status does not see the irq */ ++ rwnx_plat->ack_irq(rwnx_plat); ++ ++ while ((status = ipc_host_get_status(rwnx_hw->ipc_env))) { ++ statuses |= status; ++ /* All kinds of IRQs will be handled in one shot (RX, MSG, DBG, ...) ++ * this will ack IPC irqs not the cfpga irqs */ ++ ipc_host_irq(rwnx_hw->ipc_env, status); ++ ++ rwnx_plat->ack_irq(rwnx_plat); ++ } ++#endif ++ //if (statuses & IPC_IRQ_E2A_RXDESC) ++ // rwnx_hw->stats.last_rx = now; ++ //if (statuses & IPC_IRQ_E2A_TXCFM) ++ // rwnx_hw->stats.last_tx = now; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ rwnx_hwq_process_all(rwnx_hw); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++#if 0 ++ enable_irq(rwnx_platform_get_irq(rwnx_plat)); ++#endif ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h +new file mode 100644 +index 000000000000..d3fb4519c615 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h +@@ -0,0 +1,20 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_irqs.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_IRQS_H_ ++#define _RWNX_IRQS_H_ ++ ++#include ++ ++/* IRQ handler to be registered by platform driver */ ++irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id); ++ ++void rwnx_task(unsigned long data); ++ ++#endif /* _RWNX_IRQS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c +new file mode 100644 +index 000000000000..4773735ffe64 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c +@@ -0,0 +1,6124 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_main.c ++ * ++ * @brief Entry point of the RWNX driver ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_defs.h" ++#include "rwnx_dini.h" ++#include "rwnx_msg_tx.h" ++#include "reg_access.h" ++#include "hal_desc.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_cfgfile.h" ++#include "rwnx_irqs.h" ++#include "rwnx_radar.h" ++#include "rwnx_version.h" ++#ifdef CONFIG_RWNX_BFMER ++#include "rwnx_bfmer.h" ++#endif //(CONFIG_RWNX_BFMER) ++#include "rwnx_tdls.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "rwnx_version.h" ++#include "rwnx_main.h" ++#include "aicwf_txrxif.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#endif ++#ifdef AICWF_USB_SUPPORT ++#include "aicwf_usb.h" ++#endif ++#include "aic_bsp_export.h" ++#include "aicwf_compat_8800dc.h" ++#include "aicwf_compat_8800d80.h" ++#include "rwnx_wakelock.h" ++#ifdef CONFIG_SDIO_BT ++#include "aic_btsdio.h" ++#endif ++#include "aic_priv_cmd.h" ++ ++#define RW_DRV_DESCRIPTION "RivieraWaves 11nac driver for Linux cfg80211" ++#define RW_DRV_COPYRIGHT "Copyright(c) 2015-2017 RivieraWaves" ++#define RW_DRV_AUTHOR "RivieraWaves S.A.S" ++ ++#define RWNX_PRINT_CFM_ERR(req) \ ++ printk(KERN_CRIT "%s: Status Error(%d)\n", #req, (&req##_cfm)->status) ++ ++extern char country_code[]; ++ ++#define RWNX_HT_CAPABILITIES \ ++{ \ ++ .ht_supported = true, \ ++ .cap = 0, \ ++ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, \ ++ .mcs = { \ ++ .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \ ++ .rx_highest = cpu_to_le16(65), \ ++ .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ ++ }, \ ++} ++ ++#define RWNX_VHT_CAPABILITIES \ ++{ \ ++ .vht_supported = false, \ ++ .cap = \ ++ (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT),\ ++ .vht_mcs = { \ ++ .rx_mcs_map = cpu_to_le16( \ ++ IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 14), \ ++ .tx_mcs_map = cpu_to_le16( \ ++ IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 14), \ ++ } \ ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) || defined(CONFIG_HE_FOR_OLD_KERNEL) ++#define RWNX_HE_CAPABILITIES \ ++{ \ ++ .has_he = false, \ ++ .he_cap_elem = { \ ++ .mac_cap_info[0] = 0, \ ++ .mac_cap_info[1] = 0, \ ++ .mac_cap_info[2] = 0, \ ++ .mac_cap_info[3] = 0, \ ++ .mac_cap_info[4] = 0, \ ++ .mac_cap_info[5] = 0, \ ++ .phy_cap_info[0] = 0, \ ++ .phy_cap_info[1] = 0, \ ++ .phy_cap_info[2] = 0, \ ++ .phy_cap_info[3] = 0, \ ++ .phy_cap_info[4] = 0, \ ++ .phy_cap_info[5] = 0, \ ++ .phy_cap_info[6] = 0, \ ++ .phy_cap_info[7] = 0, \ ++ .phy_cap_info[8] = 0, \ ++ .phy_cap_info[9] = 0, \ ++ .phy_cap_info[10] = 0, \ ++ }, \ ++ .he_mcs_nss_supp = { \ ++ .rx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .tx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .rx_mcs_160 = cpu_to_le16(0xffff), \ ++ .tx_mcs_160 = cpu_to_le16(0xffff), \ ++ .rx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ .tx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ }, \ ++ .ppe_thres = {0x08, 0x1c, 0x07}, \ ++} ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++#define RWNX_HE_CAPABILITIES \ ++{ \ ++ .has_he = false, \ ++ .he_cap_elem = { \ ++ .mac_cap_info[0] = 0, \ ++ .mac_cap_info[1] = 0, \ ++ .mac_cap_info[2] = 0, \ ++ .mac_cap_info[3] = 0, \ ++ .mac_cap_info[4] = 0, \ ++ .phy_cap_info[0] = 0, \ ++ .phy_cap_info[1] = 0, \ ++ .phy_cap_info[2] = 0, \ ++ .phy_cap_info[3] = 0, \ ++ .phy_cap_info[4] = 0, \ ++ .phy_cap_info[5] = 0, \ ++ .phy_cap_info[6] = 0, \ ++ .phy_cap_info[7] = 0, \ ++ .phy_cap_info[8] = 0, \ ++ }, \ ++ .he_mcs_nss_supp = { \ ++ .rx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .tx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .rx_mcs_160 = cpu_to_le16(0xffff), \ ++ .tx_mcs_160 = cpu_to_le16(0xffff), \ ++ .rx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ .tx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ }, \ ++ .ppe_thres = {0x08, 0x1c, 0x07}, \ ++} ++#endif ++#endif ++ ++#define RATE(_bitrate, _hw_rate, _flags) { \ ++ .bitrate = (_bitrate), \ ++ .flags = (_flags), \ ++ .hw_value = (_hw_rate), \ ++} ++ ++#define CHAN(_freq) { \ ++ .center_freq = (_freq), \ ++ .max_power = 30, /* FIXME */ \ ++} ++ ++static struct ieee80211_rate rwnx_ratetable[] = { ++ RATE(10, 0x00, 0), ++ RATE(20, 0x01, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(55, 0x02, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(110, 0x03, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(60, 0x04, 0), ++ RATE(90, 0x05, 0), ++ RATE(120, 0x06, 0), ++ RATE(180, 0x07, 0), ++ RATE(240, 0x08, 0), ++ RATE(360, 0x09, 0), ++ RATE(480, 0x0A, 0), ++ RATE(540, 0x0B, 0), ++}; ++ ++/* The channels indexes here are not used anymore */ ++static struct ieee80211_channel rwnx_2ghz_channels[] = { ++ CHAN(2412), ++ CHAN(2417), ++ CHAN(2422), ++ CHAN(2427), ++ CHAN(2432), ++ CHAN(2437), ++ CHAN(2442), ++ CHAN(2447), ++ CHAN(2452), ++ CHAN(2457), ++ CHAN(2462), ++ CHAN(2467), ++ CHAN(2472), ++ CHAN(2484), ++ // Extra channels defined only to be used for PHY measures. ++ // Enabled only if custregd and custchan parameters are set ++ CHAN(2390), ++ CHAN(2400), ++ CHAN(2410), ++ CHAN(2420), ++ CHAN(2430), ++ CHAN(2440), ++ CHAN(2450), ++ CHAN(2460), ++ CHAN(2470), ++ CHAN(2480), ++ CHAN(2490), ++ CHAN(2500), ++ CHAN(2510), ++}; ++ ++static struct ieee80211_channel rwnx_5ghz_channels[] = { ++ CHAN(5180), // 36 - 20MHz ++ CHAN(5200), // 40 - 20MHz ++ CHAN(5220), // 44 - 20MHz ++ CHAN(5240), // 48 - 20MHz ++ CHAN(5260), // 52 - 20MHz ++ CHAN(5280), // 56 - 20MHz ++ CHAN(5300), // 60 - 20MHz ++ CHAN(5320), // 64 - 20MHz ++ CHAN(5500), // 100 - 20MHz ++ CHAN(5520), // 104 - 20MHz ++ CHAN(5540), // 108 - 20MHz ++ CHAN(5560), // 112 - 20MHz ++ CHAN(5580), // 116 - 20MHz ++ CHAN(5600), // 120 - 20MHz ++ CHAN(5620), // 124 - 20MHz ++ CHAN(5640), // 128 - 20MHz ++ CHAN(5660), // 132 - 20MHz ++ CHAN(5680), // 136 - 20MHz ++ CHAN(5700), // 140 - 20MHz ++ CHAN(5720), // 144 - 20MHz ++ CHAN(5745), // 149 - 20MHz ++ CHAN(5765), // 153 - 20MHz ++ CHAN(5785), // 157 - 20MHz ++ CHAN(5805), // 161 - 20MHz ++ CHAN(5825), // 165 - 20MHz ++ // Extra channels defined only to be used for PHY measures. ++ // Enabled only if custregd and custchan parameters are set ++ CHAN(5190), ++ CHAN(5210), ++ CHAN(5230), ++ CHAN(5250), ++ CHAN(5270), ++ CHAN(5290), ++ CHAN(5310), ++ CHAN(5330), ++ CHAN(5340), ++ CHAN(5350), ++ CHAN(5360), ++ CHAN(5370), ++ CHAN(5380), ++ CHAN(5390), ++ CHAN(5400), ++ CHAN(5410), ++ CHAN(5420), ++ CHAN(5430), ++ CHAN(5440), ++ CHAN(5450), ++ CHAN(5460), ++ CHAN(5470), ++ CHAN(5480), ++ CHAN(5490), ++ CHAN(5510), ++ CHAN(5530), ++ CHAN(5550), ++ CHAN(5570), ++ CHAN(5590), ++ CHAN(5610), ++ CHAN(5630), ++ CHAN(5650), ++ CHAN(5670), ++ CHAN(5690), ++ CHAN(5710), ++ CHAN(5730), ++ CHAN(5750), ++ CHAN(5760), ++ CHAN(5770), ++ CHAN(5780), ++ CHAN(5790), ++ CHAN(5800), ++ CHAN(5810), ++ CHAN(5820), ++ CHAN(5830), ++ CHAN(5840), ++ CHAN(5850), ++ CHAN(5860), ++ CHAN(5870), ++ CHAN(5880), ++ CHAN(5890), ++ CHAN(5900), ++ CHAN(5910), ++ CHAN(5920), ++ CHAN(5930), ++ CHAN(5940), ++ CHAN(5950), ++ CHAN(5960), ++ CHAN(5970), ++}; ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) || defined(CONFIG_HE_FOR_OLD_KERNEL) ++struct ieee80211_sband_iftype_data rwnx_he_capa = { ++ .types_mask = BIT(NL80211_IFTYPE_STATION)|BIT(NL80211_IFTYPE_AP), ++ .he_cap = RWNX_HE_CAPABILITIES, ++}; ++#endif ++ ++static struct ieee80211_supported_band rwnx_band_2GHz = { ++ .channels = rwnx_2ghz_channels, ++ .n_channels = ARRAY_SIZE(rwnx_2ghz_channels) - 13, // -13 to exclude extra channels ++ .bitrates = rwnx_ratetable, ++ .n_bitrates = ARRAY_SIZE(rwnx_ratetable), ++ .ht_cap = RWNX_HT_CAPABILITIES, ++ .vht_cap = RWNX_VHT_CAPABILITIES, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ .iftype_data = &rwnx_he_capa, ++ .n_iftype_data = 1, ++#endif ++}; ++ ++static struct ieee80211_supported_band rwnx_band_5GHz = { ++ .channels = rwnx_5ghz_channels, ++ .n_channels = ARRAY_SIZE(rwnx_5ghz_channels) - 59, // -59 to exclude extra channels ++ .bitrates = &rwnx_ratetable[4], ++ .n_bitrates = ARRAY_SIZE(rwnx_ratetable) - 4, ++ .ht_cap = RWNX_HT_CAPABILITIES, ++ .vht_cap = RWNX_VHT_CAPABILITIES, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ .iftype_data = &rwnx_he_capa, ++ .n_iftype_data = 1, ++#endif ++}; ++ ++static struct ieee80211_iface_limit rwnx_limits[] = { ++ { .max = 1, ++ .types = BIT(NL80211_IFTYPE_STATION)}, ++ { .max = 1, ++ .types = BIT(NL80211_IFTYPE_AP)}, ++#ifdef CONFIG_USE_P2P0 ++ { .max = 2, ++#else ++ { .max = 1, ++#endif ++ .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)}, ++#ifndef CONFIG_USE_P2P0 ++ { .max = 1, ++ .types = BIT(NL80211_IFTYPE_P2P_DEVICE), ++ } ++#endif ++}; ++ ++static struct ieee80211_iface_limit rwnx_limits_dfs[] = { ++ { .max = NX_VIRT_DEV_MAX, .types = BIT(NL80211_IFTYPE_AP)} ++}; ++ ++static const struct ieee80211_iface_combination rwnx_combinations[] = { ++ { ++ .limits = rwnx_limits, ++ .n_limits = ARRAY_SIZE(rwnx_limits), ++#ifdef CONFIG_MCC ++ .num_different_channels = NX_CHAN_CTXT_CNT, ++#else ++ .num_different_channels = 1, ++#endif ++ .max_interfaces = NX_VIRT_DEV_MAX, ++ }, ++ /* Keep this combination as the last one */ ++ { ++ .limits = rwnx_limits_dfs, ++ .n_limits = ARRAY_SIZE(rwnx_limits_dfs), ++ .num_different_channels = 1, ++ .max_interfaces = NX_VIRT_DEV_MAX, ++ .radar_detect_widths = (BIT(NL80211_CHAN_WIDTH_20_NOHT) | ++ BIT(NL80211_CHAN_WIDTH_20) | ++ BIT(NL80211_CHAN_WIDTH_40) | ++ BIT(NL80211_CHAN_WIDTH_80)), ++ } ++}; ++ ++/* There isn't a lot of sense in it, but you can transmit anything you like */ ++static struct ieee80211_txrx_stypes ++rwnx_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { ++ [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_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_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_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_DEVICE] = { ++ .tx = 0xffff, ++ .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)), ++ }, ++ [NL80211_IFTYPE_MESH_POINT] = { ++ .tx = 0xffff, ++ .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) | ++ BIT(IEEE80211_STYPE_AUTH >> 4) | ++ BIT(IEEE80211_STYPE_DEAUTH >> 4)), ++ }, ++}; ++ ++ ++static u32 cipher_suites[] = { ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++ WLAN_CIPHER_SUITE_AES_CMAC, // reserved entries to enable AES-CMAC and/or SMS4 ++ WLAN_CIPHER_SUITE_SMS4, ++ 0, ++}; ++#define NB_RESERVED_CIPHER 1; ++ ++static const int rwnx_ac2hwq[1][NL80211_NUM_ACS] = { ++ { ++ [NL80211_TXQ_Q_VO] = RWNX_HWQ_VO, ++ [NL80211_TXQ_Q_VI] = RWNX_HWQ_VI, ++ [NL80211_TXQ_Q_BE] = RWNX_HWQ_BE, ++ [NL80211_TXQ_Q_BK] = RWNX_HWQ_BK ++ } ++}; ++ ++const int rwnx_tid2hwq[IEEE80211_NUM_TIDS] = { ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BK, ++ RWNX_HWQ_BK, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_VI, ++ RWNX_HWQ_VI, ++ RWNX_HWQ_VO, ++ RWNX_HWQ_VO, ++ /* TID_8 is used for management frames */ ++ RWNX_HWQ_VO, ++ /* At the moment, all others TID are mapped to BE */ ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++}; ++ ++static const int rwnx_hwq2uapsd[NL80211_NUM_ACS] = { ++ [RWNX_HWQ_VO] = IEEE80211_WMM_IE_STA_QOSINFO_AC_VO, ++ [RWNX_HWQ_VI] = IEEE80211_WMM_IE_STA_QOSINFO_AC_VI, ++ [RWNX_HWQ_BE] = IEEE80211_WMM_IE_STA_QOSINFO_AC_BE, ++ [RWNX_HWQ_BK] = IEEE80211_WMM_IE_STA_QOSINFO_AC_BK, ++}; ++ ++#define P2P_ALIVE_TIME_MS (1*1000) ++#define P2P_ALIVE_TIME_COUNT 200 ++ ++ ++extern uint8_t scanning; ++int aicwf_dbg_level = LOGERROR; ++module_param(aicwf_dbg_level, int, 0660); ++int testmode = 0; ++char aic_fw_path[200]; ++u8 chip_sub_id = 0; ++u8 chip_mcu_id = 0; ++u8 chip_id = 0; ++ ++int rwnx_init_cmd_array(void); ++void rwnx_free_cmd_array(void); ++ ++ ++/********************************************************************* ++ * helper ++ *********************************************************************/ ++struct rwnx_sta *rwnx_get_sta(struct rwnx_hw *rwnx_hw, const u8 *mac_addr) ++{ ++ int i; ++ ++ for (i = 0; i < NX_REMOTE_STA_MAX; i++) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[i]; ++ if (sta->valid && (memcmp(mac_addr, &sta->mac_addr, 6) == 0)) ++ return sta; ++ } ++ ++ return NULL; ++} ++ ++void rwnx_enable_wapi(struct rwnx_hw *rwnx_hw) ++{ ++ //cipher_suites[rwnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_SMS4; ++ rwnx_hw->wiphy->n_cipher_suites++; ++ rwnx_hw->wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; ++} ++ ++void rwnx_enable_mfp(struct rwnx_hw *rwnx_hw) ++{ ++ cipher_suites[rwnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC; ++ rwnx_hw->wiphy->n_cipher_suites++; ++} ++ ++u8 *rwnx_build_bcn(struct rwnx_bcn *bcn, struct cfg80211_beacon_data *new) ++{ ++ u8 *buf, *pos; ++ ++ if (new->head) { ++ u8 *head = kmalloc(new->head_len, GFP_KERNEL); ++ ++ if (!head) ++ return NULL; ++ ++ if (bcn->head) ++ kfree(bcn->head); ++ ++ bcn->head = head; ++ bcn->head_len = new->head_len; ++ memcpy(bcn->head, new->head, new->head_len); ++ } ++ if (new->tail) { ++ u8 *tail = kmalloc(new->tail_len, GFP_KERNEL); ++ ++ if (!tail) ++ return NULL; ++ ++ if (bcn->tail) ++ kfree(bcn->tail); ++ ++ bcn->tail = tail; ++ bcn->tail_len = new->tail_len; ++ memcpy(bcn->tail, new->tail, new->tail_len); ++ } ++ ++ if (!bcn->head) ++ return NULL; ++ ++ bcn->tim_len = 6; ++ bcn->len = bcn->head_len + bcn->tail_len + bcn->ies_len + bcn->tim_len; ++ ++ buf = kmalloc(bcn->len, GFP_KERNEL); ++ if (!buf) ++ return NULL; ++ ++ // Build the beacon buffer ++ pos = buf; ++ memcpy(pos, bcn->head, bcn->head_len); ++ pos += bcn->head_len; ++ *pos++ = WLAN_EID_TIM; ++ *pos++ = 4; ++ *pos++ = 0; ++ *pos++ = bcn->dtim; ++ *pos++ = 0; ++ *pos++ = 0; ++ if (bcn->tail) { ++ memcpy(pos, bcn->tail, bcn->tail_len); ++ pos += bcn->tail_len; ++ } ++ if (bcn->ies) { ++ memcpy(pos, bcn->ies, bcn->ies_len); ++ } ++ ++ return buf; ++} ++ ++ ++static void rwnx_del_bcn(struct rwnx_bcn *bcn) ++{ ++ if (bcn->head) { ++ kfree(bcn->head); ++ bcn->head = NULL; ++ } ++ bcn->head_len = 0; ++ ++ if (bcn->tail) { ++ kfree(bcn->tail); ++ bcn->tail = NULL; ++ } ++ bcn->tail_len = 0; ++ ++ if (bcn->ies) { ++ kfree(bcn->ies); ++ bcn->ies = NULL; ++ } ++ bcn->ies_len = 0; ++ bcn->tim_len = 0; ++ bcn->dtim = 0; ++ bcn->len = 0; ++} ++ ++/** ++ * Link channel ctxt to a vif and thus increments count for this context. ++ */ ++void rwnx_chanctx_link(struct rwnx_vif *vif, u8 ch_idx, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_chanctx *ctxt; ++ ++ if (ch_idx >= NX_CHAN_CTXT_CNT) { ++ WARN(1, "Invalid channel ctxt id %d", ch_idx); ++ return; ++ } ++ ++ vif->ch_index = ch_idx; ++ ctxt = &vif->rwnx_hw->chanctx_table[ch_idx]; ++ ctxt->count++; ++ ++ // For now chandef is NULL for STATION interface ++ if (chandef) { ++ if (!ctxt->chan_def.chan) ++ ctxt->chan_def = *chandef; ++ else { ++ // TODO. check that chandef is the same as the one already ++ // set for this ctxt ++ } ++ } ++} ++ ++/** ++ * Unlink channel ctxt from a vif and thus decrements count for this context ++ */ ++void rwnx_chanctx_unlink(struct rwnx_vif *vif) ++{ ++ struct rwnx_chanctx *ctxt; ++ ++ if (vif->ch_index == RWNX_CH_NOT_SET) ++ return; ++ ++ ctxt = &vif->rwnx_hw->chanctx_table[vif->ch_index]; ++ ++ if (ctxt->count == 0) { ++ WARN(1, "Chan ctxt ref count is already 0"); ++ } else { ++ ctxt->count--; ++ } ++ ++ if (ctxt->count == 0) { ++ if (vif->ch_index == vif->rwnx_hw->cur_chanctx) { ++ /* If current chan ctxt is no longer linked to a vif ++ disable radar detection (no need to check if it was activated) */ ++ rwnx_radar_detection_enable(&vif->rwnx_hw->radar, ++ RWNX_RADAR_DETECT_DISABLE, ++ RWNX_RADAR_RIU); ++ } ++ /* set chan to null, so that if this ctxt is relinked to a vif that ++ don't have channel information, don't use wrong information */ ++ ctxt->chan_def.chan = NULL; ++ } ++ vif->ch_index = RWNX_CH_NOT_SET; ++} ++ ++int rwnx_chanctx_valid(struct rwnx_hw *rwnx_hw, u8 ch_idx) ++{ ++ if (ch_idx >= NX_CHAN_CTXT_CNT || ++ rwnx_hw->chanctx_table[ch_idx].chan_def.chan == NULL) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static void rwnx_del_csa(struct rwnx_vif *vif) ++{ ++ struct rwnx_csa *csa = vif->ap.csa; ++ ++ if (!csa) ++ return; ++ ++ rwnx_del_bcn(&csa->bcn); ++ kfree(csa); ++ vif->ap.csa = NULL; ++} ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++static void rwnx_csa_finish(struct work_struct *ws) ++{ ++ struct rwnx_csa *csa = container_of(ws, struct rwnx_csa, work); ++ struct rwnx_vif *vif = csa->vif; ++ struct rwnx_hw *rwnx_hw = vif->rwnx_hw; ++ int error = csa->status; ++ u8 *buf, *pos; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ buf = kmalloc(csa->bcn.len, GFP_KERNEL); ++ if (!buf) { ++ printk ("%s buf fail\n", __func__); ++ return; ++ } ++ pos = buf; ++ ++ memcpy(pos, csa->bcn.head, csa->bcn.head_len); ++ pos += csa->bcn.head_len; ++ *pos++ = WLAN_EID_TIM; ++ *pos++ = 4; ++ *pos++ = 0; ++ *pos++ = csa->bcn.dtim; ++ *pos++ = 0; ++ *pos++ = 0; ++ if (csa->bcn.tail) { ++ memcpy(pos, csa->bcn.tail, csa->bcn.tail_len); ++ pos += csa->bcn.tail_len; ++ } ++ if (csa->bcn.ies) { ++ memcpy(pos, csa->bcn.ies, csa->bcn.ies_len); ++ } ++ ++ if (!error) { ++ error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, csa->bcn.len); ++ if (error) ++ return; ++ error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, ++ csa->bcn.len, csa->bcn.head_len, ++ csa->bcn.tim_len, NULL); ++ } ++ ++ if (error) { ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) ++ cfg80211_stop_iface(rwnx_hw->wiphy, &vif->wdev, GFP_KERNEL); ++ #else ++ cfg80211_disconnected(vif->ndev, 0, NULL, 0, 0, GFP_KERNEL); ++ #endif ++ } else { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) ++ wiphy_lock(rwnx_hw->wiphy); ++#else ++ mutex_lock(&vif->wdev.mtx); ++ __acquire(&vif->wdev.mtx); ++#endif ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_unlink(vif); ++ rwnx_chanctx_link(vif, csa->ch_idx, &csa->chandef); ++ if (rwnx_hw->cur_chanctx == csa->ch_idx) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ rwnx_txq_vif_start(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } else ++ rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 9, 0)) ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0); ++#elif (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION3) ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0, 0); ++#elif (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION) ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0); ++#else ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef); ++#endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) ++ wiphy_unlock(rwnx_hw->wiphy); ++#else ++ mutex_unlock(&vif->wdev.mtx); ++ __release(&vif->wdev.mtx); ++#endif ++ } ++ rwnx_del_csa(vif); ++} ++#endif ++ ++/** ++ * rwnx_external_auth_enable - Enable external authentication on a vif ++ * ++ * @vif: VIF on which external authentication must be enabled ++ * ++ * External authentication requires to start TXQ for unknown STA in ++ * order to send auth frame pusehd by user space. ++ * Note: It is assumed that fw is on the correct channel. ++ */ ++void rwnx_external_auth_enable(struct rwnx_vif *vif) ++{ ++ vif->sta.external_auth = true; ++ rwnx_txq_unk_vif_init(vif); ++ rwnx_txq_start(rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE), 0); ++} ++ ++/** ++ * rwnx_external_auth_disable - Disable external authentication on a vif ++ * ++ * @vif: VIF on which external authentication must be disabled ++ */ ++void rwnx_external_auth_disable(struct rwnx_vif *vif) ++{ ++ if (!vif->sta.external_auth) ++ return; ++ ++ vif->sta.external_auth = false; ++ rwnx_txq_unk_vif_deinit(vif); ++} ++ ++/** ++ * rwnx_update_mesh_power_mode - ++ * ++ * @vif: mesh VIF for which power mode is updated ++ * ++ * Does nothing if vif is not a mesh point interface. ++ * Since firmware doesn't support one power save mode per link select the ++ * most "active" power mode among all mesh links. ++ * Indeed as soon as we have to be active on one link we might as well be ++ * active on all links. ++ * ++ * If there is no link then the power mode for next peer is used; ++ */ ++void rwnx_update_mesh_power_mode(struct rwnx_vif *vif) ++{ ++ enum nl80211_mesh_power_mode mesh_pm; ++ struct rwnx_sta *sta; ++ struct mesh_config mesh_conf; ++ struct mesh_update_cfm cfm; ++ u32 mask; ++ ++ if (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_MESH_POINT) ++ return; ++ ++ if (list_empty(&vif->ap.sta_list)) { ++ mesh_pm = vif->ap.next_mesh_pm; ++ } else { ++ mesh_pm = NL80211_MESH_POWER_DEEP_SLEEP; ++ list_for_each_entry(sta, &vif->ap.sta_list, list) { ++ if (sta->valid && (sta->mesh_pm < mesh_pm)) { ++ mesh_pm = sta->mesh_pm; ++ } ++ } ++ } ++ ++ if (mesh_pm == vif->ap.mesh_pm) ++ return; ++ ++ mask = BIT(NL80211_MESHCONF_POWER_MODE - 1); ++ mesh_conf.power_mode = mesh_pm; ++ if (rwnx_send_mesh_update_req(vif->rwnx_hw, vif, mask, &mesh_conf, &cfm) || ++ cfm.status) ++ return; ++ ++ vif->ap.mesh_pm = mesh_pm; ++} ++ ++#ifdef CONFIG_BR_SUPPORT ++void netdev_br_init(struct net_device *netdev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(netdev); ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++ rcu_read_lock(); ++#endif ++ ++ /* if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) */ ++ { ++ /* struct net_bridge *br = netdev->br_port->br; */ /* ->dev->dev_addr; */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ if (netdev->br_port) ++ #else ++ if (rcu_dereference(rwnx_vif->ndev->rx_handler_data)) ++ #endif ++ { ++ struct net_device *br_netdev; ++ ++ br_netdev = dev_get_by_name(&init_net, CONFIG_BR_SUPPORT_BRNAME); ++ if (br_netdev) { ++ memcpy(rwnx_vif->br_mac, br_netdev->dev_addr, ETH_ALEN); ++ dev_put(br_netdev); ++ printk(FUNC_NDEV_FMT" bind bridge dev "NDEV_FMT"("MAC_FMT")\n" ++ , FUNC_NDEV_ARG(netdev), NDEV_ARG(br_netdev), MAC_ARG(br_netdev->dev_addr)); ++ } else { ++ printk(FUNC_NDEV_FMT" can't get bridge dev by name \"%s\"\n" ++ , FUNC_NDEV_ARG(netdev), CONFIG_BR_SUPPORT_BRNAME); ++ } ++ } ++ ++ rwnx_vif->ethBrExtInfo.addPPPoETag = 1; ++ } ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++ rcu_read_unlock(); ++#endif ++} ++#endif /* CONFIG_BR_SUPPORT */ ++ ++void rwnx_set_conn_state(atomic_t *drv_conn_state, int state){ ++ ++ if((int)atomic_read(drv_conn_state) != state){ ++ AICWFDBG(LOGDEBUG, "%s drv_conn_state:%p %s --> %s \r\n", __func__, ++ drv_conn_state, ++ s_conn_state[(int)atomic_read(drv_conn_state)], ++ s_conn_state[state]); ++ ++ atomic_set(drv_conn_state, state); ++ } ++} ++ ++/********************************************************************* ++ * netdev callbacks ++ ********************************************************************/ ++/** ++ * int (*ndo_open)(struct net_device *dev); ++ * This function is called when network device transistions to the up ++ * state. ++ * ++ * - Start FW if this is the first interface opened ++ * - Add interface at fw level ++ */ ++static int rwnx_open(struct net_device *dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct mm_add_if_cfm add_if_cfm; ++ int error = 0; ++ u8 rwnx_rx_gain = 0x0E; ++ int err = 0; ++ int waiting_counter = 10; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ while(test_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags)){ ++ msleep(100); ++ AICWFDBG(LOGDEBUG, "%s waiting for rwnx_close \r\n", __func__); ++ waiting_counter--; ++ if(waiting_counter == 0){ ++ AICWFDBG(LOGERROR, "%s error waiting for close time out \r\n", __func__); ++ break; ++ } ++ } ++ ++#ifdef AICWF_LATENCY_MODE ++ if ((testmode == 0) && (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT)) { ++ rwnx_send_me_set_lp_level(rwnx_hw, 1, 1); ++ } ++#endif ++ ++#ifdef CONFIG_GPIO_WAKEUP ++//close lp mode ++// rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 0); ++#endif//CONFIG_GPIO_WAKEUP ++ ++ // Check if it is the first opened VIF ++ if (rwnx_hw->vif_started == 0) { ++ // Start the FW ++ error = rwnx_send_start(rwnx_hw); ++ if (error) ++ return error; ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ error = rwnx_send_dbg_mem_mask_write_req(rwnx_hw, 0x4033b300, 0xFF, rwnx_rx_gain); ++ if(error){ ++ return error; ++ } ++ } ++ ++#ifdef CONFIG_COEX ++ if (testmode == 0) { ++ rwnx_send_coex_req(rwnx_hw, 0, 1); ++ } ++#endif ++ ++ /* Device is now started */ ++ } ++ ++ set_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif->drv_flags:%d\r\n", __func__, (int)rwnx_vif->drv_flags); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO) { ++ if (!rwnx_hw->is_p2p_alive) { ++ if (rwnx_hw->p2p_dev_vif && !rwnx_hw->p2p_dev_vif->up) { ++ err = rwnx_send_add_if (rwnx_hw, rwnx_hw->p2p_dev_vif->wdev.address, ++ RWNX_VIF_TYPE(rwnx_hw->p2p_dev_vif), false, &add_if_cfm); ++ if (err) { ++ return -EIO; ++ } ++ ++ if (add_if_cfm.status != 0) { ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->p2p_dev_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_hw->p2p_dev_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_hw->p2p_dev_vif; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++ rwnx_hw->is_p2p_alive = 1; ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ } ++ } ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN) { ++ /* For AP_vlan use same fw and drv indexes. We ensure that this index ++ will not be used by fw for another vif by taking index >= NX_VIRT_DEV_MAX */ ++ add_if_cfm.inst_nbr = rwnx_vif->drv_vif_index; ++ netif_tx_stop_all_queues(dev); ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ AICWFDBG(LOGDEBUG, "%s ap create vif in rwnx_hw->vif_table[%d] \r\n", ++ __func__, rwnx_vif->vif_index); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } else { ++ /* Forward the information to the LMAC, ++ * p2p value not used in FMAC configuration, iftype is sufficient */ ++ error = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); ++ if (error) { ++ printk("add if fail\n"); ++ return error; ++ } ++ ++ if (add_if_cfm.status != 0) { ++ RWNX_PRINT_CFM_ERR(add_if); ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ AICWFDBG(LOGDEBUG, "%s sta create vif in rwnx_hw->vif_table[%d] \r\n", ++ __func__, rwnx_vif->vif_index); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++#ifdef CONFIG_USE_P2P0 ++ if(rwnx_vif->is_p2p_vif){ ++ rwnx_hw->p2p_dev_vif = rwnx_vif; ++ rwnx_hw->is_p2p_alive = 1; ++ } ++#endif ++ } ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MONITOR) { ++ rwnx_hw->monitor_vif = rwnx_vif->vif_index; ++ if (rwnx_vif->ch_index != RWNX_CH_NOT_SET) { ++ //Configure the monitor channel ++ error = rwnx_send_config_monitor_req(rwnx_hw, &rwnx_hw->chanctx_table[rwnx_vif->ch_index].chan_def, NULL); ++ } ++#if defined(CONFIG_RWNX_MON_XMIT) ++ rwnx_txq_unk_vif_init(rwnx_vif); ++#endif ++#if defined(CONFIG_RWNX_MON_RXFILTER) ++ rwnx_send_set_filter(rwnx_hw, (FIF_BCN_PRBRESP_PROMISC | FIF_OTHER_BSS | FIF_PSPOLL | FIF_PROBE_REQ)); ++#endif ++ } ++ ++#if defined(CONFIG_RWNX_MON_XMIT) ++ netif_carrier_on(dev); ++ AICWFDBG(LOGINFO, "monitor xmit: netif_carrier_on\n"); ++#endif ++ ++ ++ #ifdef CONFIG_BR_SUPPORT ++ netdev_br_init(dev); ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ //netif_carrier_off(dev); ++ netif_start_queue(dev); ++ ++ return error; ++} ++ ++/** ++ * int (*ndo_stop)(struct net_device *dev); ++ * This function is called when network device transistions to the down ++ * state. ++ * ++ * - Remove interface at fw level ++ * - Reset FW if this is the last interface opened ++ */ ++static int rwnx_close(struct net_device *dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ int ret; ++#if defined(AICWF_USB_SUPPORT) ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_usb_dev *usbdev = NULL; ++ bus_if = dev_get_drvdata(rwnx_hw->dev); ++ usbdev = bus_if->bus_priv.usb; ++#elif defined(AICWF_SDIO_SUPPORT) ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_sdio_dev *sdiodev = NULL; ++#else ++#endif ++ int waiting_counter = 20; ++ int test_counter = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ test_counter = waiting_counter; ++ while(atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING|| ++ atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING){ ++ AICWFDBG(LOGDEBUG, "%s wifi is connecting or disconnecting, waiting 200ms for state to stable\r\n", __func__); ++ msleep(200); ++ test_counter--; ++ if(test_counter == 0){ ++ AICWFDBG(LOGERROR, "%s connecting or disconnecting, not finish\r\n", __func__); ++ WARN_ON(1); ++ break; ++ } ++ } ++ ++#if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) ++ if (scanning) { ++ scanning = false; ++ } ++#endif ++ ++ netdev_info(dev, "CLOSE"); ++ ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ ++ /* Abort scan request on the vif */ ++ if (rwnx_hw->scan_request && ++ rwnx_hw->scan_request->wdev == &rwnx_vif->wdev) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ cfg80211_scan_done(rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(rwnx_hw->scan_request, true); ++#endif ++ rwnx_hw->scan_request = NULL; ++ ++ ret = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ mdelay(35);//make sure firmware take affect ++ if (ret) { ++ printk("scanu_cancel fail\n"); ++ return ret; ++ } ++ } ++ ++ if (rwnx_hw->roc_elem && (rwnx_hw->roc_elem->wdev == &rwnx_vif->wdev)) { ++ printk(KERN_CRIT "%s clear roc\n", __func__); ++ /* Initialize RoC element pointer to NULL, indicate that RoC can be started */ ++ kfree(rwnx_hw->roc_elem); ++ rwnx_hw->roc_elem = NULL; ++ } ++ ++ rwnx_vif->up = false; ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif[%d] down \r\n", __func__, rwnx_vif->vif_index); ++ ++ if (netif_carrier_ok(dev)) { ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ cfg80211_disconnected(dev, WLAN_REASON_DEAUTH_LEAVING, ++ NULL, 0, true, GFP_ATOMIC); ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ udelay(1000); ++ } else if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN) { ++ netif_carrier_off(dev); ++ } else { ++ netdev_warn(dev, "AP not stopped when disabling interface"); ++ } ++ ++ #ifdef CONFIG_BR_SUPPORT ++ /* if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) */ ++ { ++ /* void nat25_db_cleanup(_adapter *priv); */ ++ nat25_db_cleanup(rwnx_vif); ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ } ++ ++#if defined(AICWF_USB_SUPPORT) ++ if (usbdev != NULL) { ++ if (usbdev->state != USB_DOWN_ST) ++ rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, false); ++ } ++#endif ++#if defined(AICWF_SDIO_SUPPORT) ++ bus_if = dev_get_drvdata(rwnx_hw->dev); ++ if (bus_if) { ++ sdiodev = bus_if->bus_priv.sdio; ++ } ++ if (sdiodev != NULL) { ++ if (sdiodev->bus_if->state != BUS_DOWN_ST){ ++ if(RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT){ ++ test_counter = waiting_counter; ++ if(atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTED){ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTING); ++ rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, 3); ++ while (atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING) { ++ AICWFDBG(LOGDEBUG, "%s wifi is disconnecting, waiting 100ms for state to stable\r\n", __func__); ++ msleep(100); ++ test_counter--; ++ if (test_counter ==0) ++ break; ++ } ++ } ++ } ++#ifdef CONFIG_USE_P2P0 ++ if(!rwnx_vif->is_p2p_vif || ( rwnx_vif->is_p2p_vif && rwnx_hw->is_p2p_alive)){ ++ if (rwnx_vif->is_p2p_vif) ++ rwnx_hw->is_p2p_alive = 0; ++#endif ++ rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, false); ++#ifdef CONFIG_USE_P2P0 ++ } ++#endif ++ } ++ } ++#endif ++ /* Ensure that we won't process disconnect ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ ++ rwnx_hw->vif_table[rwnx_vif->vif_index] = NULL; ++ ++ rwnx_chanctx_unlink(rwnx_vif); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MONITOR) ++ rwnx_hw->monitor_vif = RWNX_INVALID_VIF; ++ ++ rwnx_hw->vif_started--; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if (rwnx_hw->vif_started == 0) { ++ /* This also lets both ipc sides remain in sync before resetting */ ++#if 0 ++ rwnx_ipc_tx_drain(rwnx_hw); ++#else ++#ifdef AICWF_USB_SUPPORT ++ if (usbdev->bus_if->state != BUS_DOWN_ST) { ++#else ++ if (sdiodev->bus_if->state != BUS_DOWN_ST) { ++#endif ++ rwnx_send_reset(rwnx_hw); ++ // Set parameters to firmware ++ if (testmode == 0) { ++ rwnx_send_me_config_req(rwnx_hw); ++ // Set channel parameters to firmware ++ rwnx_send_me_chan_config_req(rwnx_hw, country_code); ++ } ++ } ++#endif ++ } ++ clear_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif->drv_flags:%d\r\n", __func__, (int)rwnx_vif->drv_flags); ++ ++ return 0; ++} ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_SHUTDOWN_CALLBACK ++int rwnx_close_(struct net_device *dev){ ++ return rwnx_close(dev); ++} ++#endif ++#endif ++ ++#define IOCTL_HOSTAPD (SIOCIWFIRSTPRIV+28) ++#define IOCTL_WPAS (SIOCIWFIRSTPRIV+30) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) ++static int rwnx_do_ioctl(struct net_device *net, struct ifreq *req, int cmd) ++#else ++static int rwnx_do_ioctl(struct net_device *net, struct ifreq *req, void __user *data, int cmd) ++#endif ++{ ++ int ret = 0; ++ ///TODO: add ioctl command handler later ++ switch (cmd) { ++ case IOCTL_HOSTAPD: ++ printk("IOCTL_HOSTAPD\n"); ++ break; ++ case IOCTL_WPAS: ++ AICWFDBG(LOGINFO, "IOCTL_WPAS\n"); ++ break; ++ case SIOCDEVPRIVATE: ++ AICWFDBG(LOGINFO, "IOCTL SIOCDEVPRIVATE\n"); ++ break; ++ case (SIOCDEVPRIVATE+1): ++ AICWFDBG(LOGINFO, "IOCTL PRIVATE\n"); ++ ret = android_priv_cmd(net, req, cmd); ++ break; ++ case (SIOCDEVPRIVATE+2): ++ AICWFDBG(LOGINFO, "IOCTL PRIVATE+2\n"); ++ #ifdef CONFIG_MCU_MESSAGE ++ devipc_cust_msg(net, req, cmd); ++ #endif ++ break; ++ default: ++ ret = -EOPNOTSUPP; ++ } ++ return ret; ++} ++ ++/** ++ * struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); ++ * Called when a user wants to get the network device usage ++ * statistics. Drivers must do one of the following: ++ * 1. Define @ndo_get_stats64 to fill in a zero-initialised ++ * rtnl_link_stats64 structure passed by the caller. ++ * 2. Define @ndo_get_stats to update a net_device_stats structure ++ * (which should normally be dev->stats) and return a pointer to ++ * it. The structure may be changed asynchronously only if each ++ * field is written atomically. ++ * 3. Update dev->stats asynchronously and atomically, and define ++ * neither operation. ++ */ ++static struct net_device_stats *rwnx_get_stats(struct net_device *dev) ++{ ++ struct rwnx_vif *vif = netdev_priv(dev); ++ ++ return &vif->net_stats; ++} ++ ++/** ++ * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, ++ * struct net_device *sb_dev); ++ * Called to decide which queue to when device supports multiple ++ * transmit queues. ++ */ ++u16 rwnx_select_queue(struct net_device *dev, struct sk_buff *skb, ++ struct net_device *sb_dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ return rwnx_select_txq(rwnx_vif, skb); ++} ++ ++/** ++ * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); ++ * This function is called when the Media Access Control address ++ * needs to be changed. If this interface is not defined, the ++ * mac address can not be changed. ++ */ ++static int rwnx_set_mac_address(struct net_device *dev, void *addr) ++{ ++ struct sockaddr *sa = addr; ++ int ret = 0; ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ AICWFDBG(LOGTRACE, "%s enter \r\n", __func__); ++ ++ ret = eth_mac_addr(dev, sa); ++ AICWFDBG(LOGINFO, "%s set %02X:%02X:%02X:%02X:%02X:%02X\r\n", __func__, ++ dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2], ++ dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]); ++ memcpy(rwnx_vif->wdev.address, dev->dev_addr, 6); ++ ++ return ret; ++} ++ ++static const struct net_device_ops rwnx_netdev_ops = { ++ .ndo_open = rwnx_open, ++ .ndo_stop = rwnx_close, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) ++ .ndo_do_ioctl = rwnx_do_ioctl, ++#else ++ .ndo_siocdevprivate = rwnx_do_ioctl, ++#endif ++ .ndo_start_xmit = rwnx_start_xmit, ++ .ndo_get_stats = rwnx_get_stats, ++#ifndef CONFIG_ONE_TXQ ++ .ndo_select_queue = rwnx_select_queue, ++#endif ++#ifdef CONFIG_SUPPORT_REALTIME_CHANGE_MAC ++ .ndo_set_mac_address = rwnx_set_mac_address ++#endif ++// .ndo_set_features = rwnx_set_features, ++// .ndo_set_rx_mode = rwnx_set_multicast_list, ++}; ++ ++static const struct net_device_ops rwnx_netdev_monitor_ops = { ++ .ndo_open = rwnx_open, ++ .ndo_stop = rwnx_close, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) ++ .ndo_siocdevprivate = rwnx_do_ioctl, ++#else ++ .ndo_do_ioctl = rwnx_do_ioctl, ++#endif ++#ifdef CONFIG_RWNX_MON_XMIT ++ .ndo_start_xmit = rwnx_start_monitor_if_xmit, ++ .ndo_select_queue = rwnx_select_queue, ++#endif ++ .ndo_get_stats = rwnx_get_stats, ++ .ndo_set_mac_address = rwnx_set_mac_address, ++}; ++ ++static void rwnx_netdev_setup(struct net_device *dev) ++{ ++ ether_setup(dev); ++ dev->priv_flags &= ~IFF_TX_SKB_SHARING; ++ dev->netdev_ops = &rwnx_netdev_ops; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) ++ dev->destructor = free_netdev; ++#else ++ dev->needs_free_netdev = true; ++#endif ++ dev->watchdog_timeo = RWNX_TX_LIFETIME_MS; ++ ++ dev->needed_headroom = sizeof(struct rwnx_txhdr) + RWNX_SWTXHDR_ALIGN_SZ; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ dev->needed_headroom = max(dev->needed_headroom, ++ (unsigned short)(sizeof(struct rwnx_amsdu_txhdr) ++ + sizeof(struct ethhdr) + 4 ++ + sizeof(rfc1042_header) + 2)); ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++ dev->hw_features = 0; ++} ++ ++/********************************************************************* ++ * Cfg80211 callbacks (and helper) ++ *********************************************************************/ ++static struct rwnx_vif *rwnx_interface_add(struct rwnx_hw *rwnx_hw, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ struct net_device *ndev; ++ struct rwnx_vif *vif; ++ int min_idx, max_idx; ++ int vif_idx = -1; ++ int i; ++ int nx_nb_ndev_txq = NX_NB_NDEV_TXQ; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_nb_ndev_txq = NX_NB_NDEV_TXQ_FOR_OLD_IC; ++ } ++ ++ AICWFDBG(LOGINFO, "rwnx_interface_add: %s, %d, %d\r\n", name, type, NL80211_IFTYPE_P2P_DEVICE); ++ // Look for an available VIF ++ if (type == NL80211_IFTYPE_AP_VLAN) { ++ min_idx = NX_VIRT_DEV_MAX; ++ max_idx = NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; ++ } else { ++ min_idx = 0; ++ max_idx = NX_VIRT_DEV_MAX; ++ } ++ ++ for (i = min_idx; i < max_idx; i++) { ++ if ((rwnx_hw->avail_idx_map) & BIT(i)) { ++ vif_idx = i; ++ break; ++ } ++ } ++ if (vif_idx < 0) ++ return NULL; ++ ++ #ifndef CONFIG_RWNX_MON_DATA ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ // Check if monitor interface already exists or type is monitor ++ if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR) || ++ (type == NL80211_IFTYPE_MONITOR)) { ++ wiphy_err(rwnx_hw->wiphy, ++ "Monitor+Data interface support (MON_DATA) disabled\n"); ++ return NULL; ++ } ++ } ++ #endif ++ ++#ifndef CONFIG_ONE_TXQ ++ ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type, ++ rwnx_netdev_setup, nx_nb_ndev_txq, 1); ++#else ++ ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type, ++ rwnx_netdev_setup, 1, 1); ++#endif ++ ++ if (!ndev) ++ return NULL; ++ ++ vif = netdev_priv(ndev); ++ vif->key_has_add = 0; ++ ndev->ieee80211_ptr = &vif->wdev; ++ vif->wdev.wiphy = rwnx_hw->wiphy; ++ vif->rwnx_hw = rwnx_hw; ++ vif->ndev = ndev; ++ vif->drv_vif_index = vif_idx; ++ SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy)); ++ vif->wdev.netdev = ndev; ++ vif->wdev.iftype = type; ++ vif->up = false; ++ vif->ch_index = RWNX_CH_NOT_SET; ++ memset(&vif->net_stats, 0, sizeof(vif->net_stats)); ++ vif->is_p2p_vif = 0; ++ ++ #ifdef CONFIG_BR_SUPPORT ++ spin_lock_init(&vif->br_ext_lock); ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ ++ switch (type) { ++ case NL80211_IFTYPE_STATION: ++ vif->sta.ap = NULL; ++ vif->sta.tdls_sta = NULL; ++ vif->sta.external_auth = false; ++ break; ++ case NL80211_IFTYPE_P2P_CLIENT: ++ vif->sta.ap = NULL; ++ vif->sta.tdls_sta = NULL; ++ vif->sta.external_auth = false; ++ vif->is_p2p_vif = 1; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ INIT_LIST_HEAD(&vif->ap.mpath_list); ++ INIT_LIST_HEAD(&vif->ap.proxy_list); ++ vif->ap.create_path = false; ++ vif->ap.generation = 0; ++ vif->ap.mesh_pm = NL80211_MESH_POWER_ACTIVE; ++ vif->ap.next_mesh_pm = NL80211_MESH_POWER_ACTIVE; ++ // no break ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ INIT_LIST_HEAD(&vif->ap.sta_list); ++ memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn)); ++ break; ++ case NL80211_IFTYPE_P2P_GO: ++ INIT_LIST_HEAD(&vif->ap.sta_list); ++ memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn)); ++ vif->is_p2p_vif = 1; ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ { ++ struct rwnx_vif *master_vif; ++ bool found = false; ++ list_for_each_entry(master_vif, &rwnx_hw->vifs, list) { ++ if ((RWNX_VIF_TYPE(master_vif) == NL80211_IFTYPE_AP) && ++ !(!memcmp(master_vif->ndev->dev_addr, params->macaddr, ++ ETH_ALEN))) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ goto err; ++ ++ vif->ap_vlan.master = master_vif; ++ vif->ap_vlan.sta_4a = NULL; ++ break; ++ } ++ case NL80211_IFTYPE_MONITOR: ++ ndev->type = ARPHRD_IEEE80211_RADIOTAP; ++ ndev->netdev_ops = &rwnx_netdev_monitor_ops; ++ break; ++ default: ++ break; ++ } ++ ++ if (type == NL80211_IFTYPE_AP_VLAN) { ++ memcpy((void *)ndev->dev_addr, (const void *)params->macaddr, ETH_ALEN); ++ memcpy((void *)vif->wdev.address, (const void *)params->macaddr, ETH_ALEN); ++ } else { ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 17, 0) ++ unsigned char mac_addr[6]; ++ memcpy(mac_addr, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ mac_addr[5] ^= vif_idx; ++ //memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); ++ eth_hw_addr_set(ndev, mac_addr); ++ memcpy(vif->wdev.address, mac_addr, ETH_ALEN); ++#else ++ memcpy(ndev->dev_addr, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ ndev->dev_addr[5] ^= vif_idx; ++ memcpy(vif->wdev.address, ndev->dev_addr, ETH_ALEN); ++#endif ++ ++ } ++ ++ AICWFDBG(LOGINFO, "interface add:%x %x %x %x %x %x\n", vif->wdev.address[0], vif->wdev.address[1], \ ++ vif->wdev.address[2], vif->wdev.address[3], vif->wdev.address[4], vif->wdev.address[5]); ++ ++ if (params) { ++ vif->use_4addr = params->use_4addr; ++ ndev->ieee80211_ptr->use_4addr = params->use_4addr; ++ } else ++ vif->use_4addr = false; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) ++ if (cfg80211_register_netdevice(ndev)) ++#else ++ if (register_netdevice(ndev)) ++#endif ++ goto err; ++ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_add_tail(&vif->list, &rwnx_hw->vifs); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->avail_idx_map &= ~BIT(vif_idx); ++ ++ return vif; ++ ++err: ++ free_netdev(ndev); ++ return NULL; ++} ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++void aicwf_p2p_alive_timeout(ulong data) ++#else ++void aicwf_p2p_alive_timeout(struct timer_list *t) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct rwnx_vif *rwnx_vif; ++ struct rwnx_vif *rwnx_vif1, *tmp; ++ u8_l p2p = 0; ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ rwnx_vif = (struct rwnx_vif *)data; ++ rwnx_hw = rwnx_vif->rwnx_hw; ++ #else ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ rwnx_hw = timer_container_of(rwnx_hw, t, p2p_alive_timer); ++ #else ++ rwnx_hw = from_timer(rwnx_hw, t, p2p_alive_timer); ++ #endif ++ rwnx_vif = rwnx_hw->p2p_dev_vif; ++ #endif ++ ++ list_for_each_entry_safe(rwnx_vif1, tmp, &rwnx_hw->vifs, list) { ++ if ((rwnx_hw->avail_idx_map & BIT(rwnx_vif1->drv_vif_index)) == 0) { ++ switch (RWNX_VIF_TYPE(rwnx_vif1)) { ++ case NL80211_IFTYPE_P2P_CLIENT: ++ case NL80211_IFTYPE_P2P_GO: ++ rwnx_hw->is_p2p_alive = 1; ++ p2p = 1; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ ++ if (p2p) ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++ else ++ atomic_inc(&rwnx_hw->p2p_alive_timer_count); ++ ++ if (atomic_read(&rwnx_hw->p2p_alive_timer_count) < P2P_ALIVE_TIME_COUNT) { ++ mod_timer(&rwnx_hw->p2p_alive_timer, ++ jiffies + msecs_to_jiffies(P2P_ALIVE_TIME_MS)); ++ return; ++ } else ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++ ++ rwnx_hw->is_p2p_alive = 0; ++ if (rwnx_vif->up) { ++ rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, true); ++ ++ /* Ensure that we won't process disconnect ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ ++ rwnx_vif->up = false; ++ rwnx_hw->vif_table[rwnx_vif->vif_index] = NULL; ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif[%d] down \r\n", __func__, rwnx_vif->vif_index); ++ rwnx_hw->vif_started--; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++} ++ ++ ++/********************************************************************* ++ * Cfg80211 callbacks (and helper) ++ *********************************************************************/ ++static struct wireless_dev *rwnx_virtual_interface_add(struct rwnx_hw *rwnx_hw, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ struct wireless_dev *wdev = NULL; ++ struct rwnx_vif *vif; ++ int min_idx, max_idx; ++ int vif_idx = -1; ++ int i; ++ ++ printk("rwnx_virtual_interface_add: %d, %s\n", type, name); ++ ++ if (type == NL80211_IFTYPE_AP_VLAN) { ++ min_idx = NX_VIRT_DEV_MAX; ++ max_idx = NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; ++ } else { ++ min_idx = 0; ++ max_idx = NX_VIRT_DEV_MAX; ++ } ++ ++ for (i = min_idx; i < max_idx; i++) { ++ if ((rwnx_hw->avail_idx_map) & BIT(i)) { ++ vif_idx = i; ++ break; ++ } ++ } ++ ++ if (vif_idx < 0) { ++ printk("virtual_interface_add %s fail\n", name); ++ return NULL; ++ } ++ ++ vif = kzalloc(sizeof(struct rwnx_vif), GFP_KERNEL); ++ if (unlikely(!vif)) { ++ printk("Could not allocate wireless device\n"); ++ return NULL; ++ } ++ wdev = &vif->wdev; ++ wdev->wiphy = rwnx_hw->wiphy; ++ wdev->iftype = type; ++ ++ printk("rwnx_virtual_interface_add, ifname=%s, wdev=%p, vif_idx=%d\n", name, wdev, vif_idx); ++ ++ #ifndef CONFIG_USE_P2P0 ++ vif->is_p2p_vif = 1; ++ vif->rwnx_hw = rwnx_hw; ++ vif->vif_index = vif_idx; ++ vif->wdev.wiphy = rwnx_hw->wiphy; ++ vif->drv_vif_index = vif_idx; ++ vif->up = false; ++ vif->ch_index = RWNX_CH_NOT_SET; ++ memset(&vif->net_stats, 0, sizeof(vif->net_stats)); ++ vif->use_4addr = false; ++ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_add_tail(&vif->list, &rwnx_hw->vifs); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if (rwnx_hw->is_p2p_alive == 0) { ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ init_timer(&rwnx_hw->p2p_alive_timer); ++ rwnx_hw->p2p_alive_timer.data = (unsigned long)vif; ++ rwnx_hw->p2p_alive_timer.function = aicwf_p2p_alive_timeout; ++ #else ++ timer_setup(&rwnx_hw->p2p_alive_timer, aicwf_p2p_alive_timeout, 0); ++ #endif ++ rwnx_hw->is_p2p_alive = 0; ++ rwnx_hw->is_p2p_connected = 0; ++ rwnx_hw->p2p_dev_vif = vif; ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++ } ++ #endif ++ rwnx_hw->avail_idx_map &= ~BIT(vif_idx); ++ ++ memcpy(vif->wdev.address, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ vif->wdev.address[5] ^= vif_idx; ++ printk("p2p dev addr=%x %x %x %x %x %x\n", vif->wdev.address[0], vif->wdev.address[1], \ ++ vif->wdev.address[2], vif->wdev.address[3], vif->wdev.address[4], vif->wdev.address[5]); ++ ++ return wdev; ++} ++ ++/* ++ * @brief Retrieve the rwnx_sta object allocated for a given MAC address ++ * and a given role. ++ */ ++static struct rwnx_sta *rwnx_retrieve_sta(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, u8 *addr, ++ __le16 fc, bool ap) ++{ ++ if (ap) { ++ /* only deauth, disassoc and action are bufferable MMPDUs */ ++ bool bufferable = ieee80211_is_deauth(fc) || ++ ieee80211_is_disassoc(fc) || ++ ieee80211_is_action(fc); ++ ++ /* Check if the packet is bufferable or not */ ++ if (bufferable) { ++ /* Check if address is a broadcast or a multicast address */ ++ if (is_broadcast_ether_addr(addr) || is_multicast_ether_addr(addr)) { ++ /* Returned STA pointer */ ++ struct rwnx_sta *rwnx_sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ ++ if (rwnx_sta->valid) ++ return rwnx_sta; ++ } else { ++ /* Returned STA pointer */ ++ struct rwnx_sta *rwnx_sta; ++ ++ /* Go through list of STAs linked with the provided VIF */ ++ spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ list_for_each_entry(rwnx_sta, &rwnx_vif->ap.sta_list, list) { ++ if (rwnx_sta->valid && ++ ether_addr_equal(rwnx_sta->mac_addr, addr)) { ++ /* Return the found STA */ ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ return rwnx_sta; ++ } ++ } ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ } ++ } ++ } else { ++ return rwnx_vif->sta.ap; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * @add_virtual_intf: create a new virtual interface with the given name, ++ * must set the struct wireless_dev's iftype. Beware: You must create ++ * the new netdev in the wiphy's network namespace! Returns the struct ++ * wireless_dev, or an ERR_PTR. For P2P device wdevs, the driver must ++ * also set the address member in the wdev. ++ */ ++static struct wireless_dev *rwnx_cfg80211_add_iface(struct wiphy *wiphy, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct wireless_dev *wdev; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) ++ unsigned char name_assign_type = NET_NAME_UNKNOWN; ++#endif ++ ++ if (type != NL80211_IFTYPE_P2P_DEVICE) { ++ struct rwnx_vif *vif = rwnx_interface_add(rwnx_hw, name, name_assign_type, type, params); ++ if (!vif) ++ return ERR_PTR(-EINVAL); ++ return &vif->wdev; ++ ++ } else { ++ wdev = rwnx_virtual_interface_add(rwnx_hw, name, name_assign_type, type, params); ++ if (!wdev) ++ return ERR_PTR(-EINVAL); ++ return wdev; ++ } ++} ++ ++/** ++ * @del_virtual_intf: remove the virtual interface ++ */ ++static int rwnx_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ struct net_device *dev = wdev->netdev; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ ++ AICWFDBG(LOGINFO, "del_iface: %p, %x\n", wdev, wdev->address[5]); ++ ++ if (!dev || !rwnx_vif->ndev) { ++ cfg80211_unregister_wdev(wdev); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_del(&rwnx_vif->list); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->avail_idx_map |= BIT(rwnx_vif->drv_vif_index); ++ rwnx_vif->ndev = NULL; ++ kfree(rwnx_vif); ++ return 0; ++ } ++ ++ netdev_info(dev, "Remove Interface"); ++ ++ if (dev->reg_state == NETREG_REGISTERED) { ++ /* Will call rwnx_close if interface is UP */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) ++ cfg80211_unregister_netdevice(dev); ++#else ++ unregister_netdevice(dev); ++#endif ++ ++ } ++ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_del(&rwnx_vif->list); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->avail_idx_map |= BIT(rwnx_vif->drv_vif_index); ++ rwnx_vif->ndev = NULL; ++ ++ /* Clear the priv in adapter */ ++ dev->ieee80211_ptr = NULL; ++ ++ return 0; ++} ++ ++/** ++ * @change_virtual_intf: change type/configuration of virtual interface, ++ * keep the struct wireless_dev's iftype updated. ++ */ ++static int rwnx_cfg80211_change_iface(struct wiphy *wiphy, ++ struct net_device *dev, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++#ifndef CONFIG_RWNX_MON_DATA ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++#endif ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct mm_add_if_cfm add_if_cfm; ++ bool_l p2p = false; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("change_if: %d to %d, %d, %d", vif->wdev.iftype, type, NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_STATION); ++ ++#ifndef CONFIG_RWNX_MON_DATA ++ if ((type == NL80211_IFTYPE_MONITOR) && ++ (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_MONITOR)) { ++ struct rwnx_vif *vif_el; ++ list_for_each_entry(vif_el, &rwnx_hw->vifs, list) { ++ // Check if data interface already exists ++ if ((vif_el != vif) && ++ (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_MONITOR)) { ++ wiphy_err(rwnx_hw->wiphy, ++ "Monitor+Data interface support (MON_DATA) disabled\n"); ++ return -EIO; ++ } ++ } ++ } ++#endif ++ ++ // Reset to default case (i.e. not monitor) ++ dev->type = ARPHRD_ETHER; ++ dev->netdev_ops = &rwnx_netdev_ops; ++ ++ switch (type) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ vif->sta.ap = NULL; ++ vif->sta.tdls_sta = NULL; ++ vif->sta.external_auth = false; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ INIT_LIST_HEAD(&vif->ap.mpath_list); ++ INIT_LIST_HEAD(&vif->ap.proxy_list); ++ vif->ap.create_path = false; ++ vif->ap.generation = 0; ++ // no break ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ INIT_LIST_HEAD(&vif->ap.sta_list); ++ memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn)); ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ return -EPERM; ++ case NL80211_IFTYPE_MONITOR: ++ dev->type = ARPHRD_IEEE80211_RADIOTAP; ++ dev->netdev_ops = &rwnx_netdev_monitor_ops; ++ break; ++ default: ++ break; ++ } ++ ++ vif->wdev.iftype = type; ++ if (params->use_4addr != -1) ++ vif->use_4addr = params->use_4addr; ++ if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO) ++ p2p = true; ++ ++ if (vif->up) { ++ /* Abort scan request on the vif */ ++ if (vif->rwnx_hw->scan_request && ++ vif->rwnx_hw->scan_request->wdev == &vif->wdev) { ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ cfg80211_scan_done(vif->rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(vif->rwnx_hw->scan_request, true); ++#endif ++ ret = rwnx_send_scanu_cancel_req(vif->rwnx_hw, NULL); ++ if (ret) { ++ printk("scanu_cancel fail\n"); ++ return ret; ++ } ++ vif->rwnx_hw->scan_request = NULL; ++#else ++ if ((ret = rwnx_send_scanu_cancel_req(vif->rwnx_hw, NULL))) { ++ AICWFDBG(LOGERROR, "scanu_cancel fail\n"); ++ return ret; ++ } ++#endif ++ } ++ ret = rwnx_send_remove_if(vif->rwnx_hw, vif->vif_index, false); ++ if (ret) { ++ printk("remove_if fail\n"); ++ return ret; ++ } ++ vif->rwnx_hw->vif_table[vif->vif_index] = NULL; ++ printk("change_if from %d \n", vif->vif_index); ++ ret = rwnx_send_add_if(vif->rwnx_hw, vif->wdev.address, RWNX_VIF_TYPE(vif), p2p, &add_if_cfm); ++ if (ret) { ++ printk("add if fail\n"); ++ return ret; ++ } ++ if (add_if_cfm.status != 0) { ++ printk("add if status fail\n"); ++ return -EIO; ++ } ++ ++ printk("change_if to %d \n", add_if_cfm.inst_nbr); ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&vif->rwnx_hw->cb_lock); ++ vif->vif_index = add_if_cfm.inst_nbr; ++ vif->rwnx_hw->vif_table[add_if_cfm.inst_nbr] = vif; ++ spin_unlock_bh(&vif->rwnx_hw->cb_lock); ++ } ++ ++ if (type == NL80211_IFTYPE_MONITOR) { ++ vif->rwnx_hw->monitor_vif = vif->vif_index; ++ #if defined(CONFIG_RWNX_MON_XMIT) ++ rwnx_txq_unk_vif_init(vif); ++ #endif ++ #if defined(CONFIG_RWNX_MON_RXFILTER) ++ rwnx_send_set_filter(vif->rwnx_hw, (FIF_BCN_PRBRESP_PROMISC | FIF_OTHER_BSS | FIF_PSPOLL | FIF_PROBE_REQ)); ++ #endif ++ } else { ++ vif->rwnx_hw->monitor_vif = RWNX_INVALID_VIF; ++ } ++ ++ return 0; ++} ++ ++static int rwnx_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ int ret = 0; ++ ++ //do nothing ++ printk("P2P interface started\n"); ++ ++ return ret; ++} ++ ++static void rwnx_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ int ret = 0; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ /* Abort scan request on the vif */ ++ if (rwnx_hw->scan_request && ++ rwnx_hw->scan_request->wdev == &rwnx_vif->wdev) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ cfg80211_scan_done(rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(rwnx_hw->scan_request, true); ++#endif ++ rwnx_hw->scan_request = NULL; ++ ret = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ if (ret) ++ printk("scanu_cancel fail\n"); ++ } ++ ++ if (rwnx_vif == rwnx_hw->p2p_dev_vif) { ++ rwnx_hw->is_p2p_alive = 0; ++ if (timer_pending(&rwnx_hw->p2p_alive_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&rwnx_hw->p2p_alive_timer); ++#else ++ del_timer_sync(&rwnx_hw->p2p_alive_timer); ++#endif ++ } ++ ++ if (rwnx_vif->up) { ++ rwnx_send_remove_if(rwnx_hw, rwnx_vif->vif_index, true); ++ /* Ensure that we won't process disconnect ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->up = false; ++ rwnx_hw->vif_table[rwnx_vif->vif_index] = NULL; ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif[%d] down \r\n", __func__, rwnx_vif->vif_index); ++ rwnx_hw->vif_started--; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++ ++ } ++ ++ printk("Exit. P2P interface stopped\n"); ++ ++ return; ++} ++ ++ ++/** ++ * @scan: Request to do a scan. If returning zero, the scan request is given ++ * the driver, and will be valid until passed to cfg80211_scan_done(). ++ * For scan results, call cfg80211_inform_bss(); you can call this outside ++ * the scan/scan_done bracket too. ++ */ ++static int rwnx_cfg80211_scan(struct wiphy *wiphy, ++ struct cfg80211_scan_request *request) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(request->wdev, struct rwnx_vif, wdev); ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if(testmode){ ++ return -EBUSY; ++ } ++ ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING){ ++ AICWFDBG(LOGERROR, "%s wifi is connecting, return it\r\n", __func__); ++ return -EBUSY; ++ } ++ ++ if (scanning) { ++ AICWFDBG(LOGERROR, "%s is scanning, abort\n", __func__); ++ #if 0 ++ error = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ if (error) ++ return error; ++ msleep(150); ++ #endif ++ return -EBUSY; ++ } ++ ++ if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) && ++ rwnx_vif->sta.external_auth) { ++ AICWFDBG(LOGERROR, "scan about: external auth\r\n"); ++ return -EBUSY; ++ } ++ ++ rwnx_hw->scan_request = request; ++ error = rwnx_send_scanu_req(rwnx_hw, rwnx_vif, request); ++ if (error) ++ return error; ++ ++ return 0; ++} ++ ++bool key_flag = false; ++/** ++ * @add_key: add a key with the given parameters. @mac_addr will be %NULL ++ * when adding a group key. ++ */ ++ static int rwnx_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool pairwise, const u8 *mac_addr, ++ struct key_params *params) ++ ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(netdev); ++ int i, error = 0; ++ struct mm_key_add_cfm key_add_cfm; ++ u8_l cipher = 0; ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_key *rwnx_key; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (mac_addr) { ++ sta = rwnx_get_sta(rwnx_hw, mac_addr); ++ if (!sta) ++ return -EINVAL; ++ rwnx_key = &sta->key; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.paired_cipher_type = params->cipher; ++ } else { ++ rwnx_key = &vif->key[key_index]; ++ vif->key_has_add = 1; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.group_cipher_type = params->cipher; ++ } ++ ++ /* Retrieve the cipher suite selector */ ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ cipher = MAC_CIPHER_WEP40; ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ cipher = MAC_CIPHER_WEP104; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ cipher = MAC_CIPHER_TKIP; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ cipher = MAC_CIPHER_CCMP; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ cipher = MAC_CIPHER_BIP_CMAC_128; ++ break; ++ case WLAN_CIPHER_SUITE_SMS4: ++ { ++ // Need to reverse key order ++ u8 tmp, *key = (u8 *)params->key; ++ cipher = MAC_CIPHER_WPI_SMS4; ++ for (i = 0; i < WPI_SUBKEY_LEN/2; i++) { ++ tmp = key[i]; ++ key[i] = key[WPI_SUBKEY_LEN - 1 - i]; ++ key[WPI_SUBKEY_LEN - 1 - i] = tmp; ++ } ++ for (i = 0; i < WPI_SUBKEY_LEN/2; i++) { ++ tmp = key[i + WPI_SUBKEY_LEN]; ++ key[i + WPI_SUBKEY_LEN] = key[WPI_KEY_LEN - 1 - i]; ++ key[WPI_KEY_LEN - 1 - i] = tmp; ++ } ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ key_flag = false; ++ error = rwnx_send_key_add(rwnx_hw, vif->vif_index, ++ (sta ? sta->sta_idx : 0xFF), pairwise, ++ (u8 *)params->key, params->key_len, ++ key_index, cipher, &key_add_cfm); ++ if (error) ++ return error; ++ ++ if (key_add_cfm.status != 0) { ++ RWNX_PRINT_CFM_ERR(key_add); ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ rwnx_key->hw_idx = key_add_cfm.hw_key_idx; ++ ++ return 0; ++} ++ ++/** ++ * @get_key: get information about the key with the given parameters. ++ * @mac_addr will be %NULL when requesting information for a group ++ * key. All pointers given to the @callback function need not be valid ++ * after it returns. This function should return an error if it is ++ * not possible to retrieve the key, -ENOENT if it doesn't exist. ++ * ++ */ ++static int rwnx_cfg80211_get_key(struct wiphy *wiphy, struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool pairwise, const u8 *mac_addr, ++ void *cookie, ++ void (*callback)(void *cookie, struct key_params*)) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ return -1; ++} ++ ++ ++/** ++ * @del_key: remove a key given the @mac_addr (%NULL for a group key) ++ * and @key_index, return -ENOENT if the key doesn't exist. ++ */ ++static int rwnx_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool pairwise, const u8 *mac_addr) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(netdev); ++ int error; ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_key *rwnx_key; ++ if (!key_flag && vif->wdev.iftype == NL80211_IFTYPE_STATION) ++ return 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ if (mac_addr) { ++ sta = rwnx_get_sta(rwnx_hw, mac_addr); ++ if (!sta) ++ return -EINVAL; ++ rwnx_key = &sta->key; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.paired_cipher_type = 0xff; ++ } else { ++ rwnx_key = &vif->key[key_index]; ++ vif->key_has_add = 0; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.group_cipher_type = 0xff; ++ } ++ ++ error = rwnx_send_key_del(rwnx_hw, rwnx_key->hw_idx); ++ ++ rwnx_key->hw_idx = 0; ++ return error; ++} ++ ++/** ++ * @set_default_key: set the default key on an interface ++ */ ++static int rwnx_cfg80211_set_default_key(struct wiphy *wiphy, ++ struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool unicast, bool multicast) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ return 0; ++} ++ ++/** ++ * @set_default_mgmt_key: set the default management frame key on an interface ++ */ ++static int rwnx_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, ++ struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index) ++{ ++ return 0; ++} ++ ++/** ++ * @connect: Connect to the ESS with the specified parameters. When connected, ++ * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. ++ * If the connection fails for some reason, call cfg80211_connect_result() ++ * with the status from the AP. ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_connect_params *sme) ++{ ++ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct sm_connect_cfm sm_connect_cfm; ++ int error = 0; ++ int is_wep = ((sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104)); ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#if 1 ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTED) { ++ AICWFDBG(LOGDEBUG, "%s this connection is roam \r\n", __func__); ++ rwnx_vif->sta.is_roam = true; ++ }else{ ++ rwnx_vif->sta.is_roam = false; ++ } ++ ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING|| ++ (int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING) { ++ AICWFDBG(LOGERROR, "%s driver is disconnecting or connecting ,return it \r\n", __func__); ++ return 0; ++ } ++#endif ++ ++ if(rwnx_vif->sta.is_roam){ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_ROAMING); ++ }else{ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTING); ++ } ++ ++ if (is_wep) { ++ if(sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { ++ if(rwnx_vif->wep_enabled && rwnx_vif->wep_auth_err) { ++ if(rwnx_vif->last_auth_type == NL80211_AUTHTYPE_SHARED_KEY) ++ sme->auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; ++ else ++ sme->auth_type = NL80211_AUTHTYPE_SHARED_KEY; ++ } else { ++ if((rwnx_vif->wep_enabled && !rwnx_vif->wep_auth_err)) ++ sme->auth_type = rwnx_vif->last_auth_type; ++ else ++ sme->auth_type = NL80211_AUTHTYPE_SHARED_KEY; ++ } ++ printk("auto: use sme->auth_type = %d\r\n", sme->auth_type); ++ } else { ++ if (rwnx_vif->wep_enabled && rwnx_vif->wep_auth_err && (sme->auth_type == rwnx_vif->last_auth_type)) { ++ if(sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { ++ sme->auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; ++ printk("start connect, auth_type changed, shared --> open\n"); ++ } else if(sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { ++ sme->auth_type = NL80211_AUTHTYPE_SHARED_KEY; ++ printk("start connect, auth_type changed, open --> shared\n"); ++ } ++ } ++ } ++ } ++ ++ /* For SHARED-KEY authentication, must install key first */ ++ if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY && sme->key) { ++ struct key_params key_params; ++ key_params.key = (u8*)sme->key; ++ key_params.seq = NULL; ++ key_params.key_len = sme->key_len; ++ key_params.seq_len = 0; ++ key_params.cipher = sme->crypto.cipher_group; ++ rwnx_cfg80211_add_key(wiphy, dev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ 0, ++#endif ++ sme->key_idx, false, NULL, &key_params); ++ } ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ else if ((sme->auth_type == NL80211_AUTHTYPE_SAE) && ++ !(sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) { ++ netdev_err(dev, "Doesn't support SAE without external authentication\n"); ++ return -EINVAL; ++ } ++#endif ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) { ++ rwnx_hw->is_p2p_connected = 1; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) { ++ rwnx_vif->sta.paired_cipher_type = 0xff; ++ rwnx_vif->sta.group_cipher_type = 0xff; ++ } ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_sm_connect_req(rwnx_hw, rwnx_vif, sme, &sm_connect_cfm); ++ if (error) ++ return error; ++ ++ // Check the status ++ switch (sm_connect_cfm.status) { ++ case CO_OK: ++ error = 0; ++ break; ++ case CO_BUSY: ++ error = -EINPROGRESS; ++ break; ++ case CO_OP_IN_PROGRESS: ++ error = -EALREADY; ++ break; ++ default: ++ error = -EIO; ++ break; ++ } ++ ++ return error; ++ ++} ++ ++/** ++ * @disconnect: Disconnect from the BSS/ESS. ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, ++ u16 reason_code) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int ret = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ AICWFDBG(LOGINFO, "%s drv_vif_index:%d disconnect reason:%d \r\n", ++ __func__, rwnx_vif->drv_vif_index, reason_code); ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTED) { ++ AICWFDBG(LOGERROR, "%s this\r\n",__func__); ++ WARN_ON(1); ++ return -EBUSY; ++ } ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTING) { ++ AICWFDBG(LOGERROR, "%s wifi is disconnecting, return it:%d \r\n", ++ __func__, reason_code); ++ return -EBUSY; ++ } ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTED|| ++ atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTING|| ++ atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_ROAMING) { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTING); ++ key_flag = true; ++ ret = rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, reason_code); ++#ifdef AICWF_SDIO_SUPPORT ++ if (rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { ++ AICWFDBG(LOGINFO, "%s bus is down %d\n", __func__, ret); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ } ++#endif ++ return ret; ++ } ++#if 0 ++ else { ++ cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, ++ reason_code?reason_code:WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ return 0; ++ } ++#endif ++ return 0; ++} ++ ++#ifdef CONFIG_SCHED_SCAN ++ ++static int rwnx_cfg80211_sched_scan_stop(struct wiphy *wiphy, ++ struct net_device *ndev ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ ,u64 reqid) ++#else ++ ) ++#endif ++{ ++ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ //struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ AICWFDBG(LOGINFO, "%s enter wiphy:%p\r\n", __func__, wiphy); ++ ++ if(rwnx_hw->scan_request){ ++ AICWFDBG(LOGINFO, "%s rwnx_send_scanu_cancel_req\r\n", __func__); ++ return rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ }else{ ++ return 0; ++ } ++} ++ ++ ++static int rwnx_cfg80211_sched_scan_start(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_sched_scan_request *request) ++ ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct cfg80211_scan_request *scan_request = NULL; ++ ++ int ret = 0; ++ int index = 0; ++ ++ AICWFDBG(LOGINFO, "%s enter wiphy:%p\r\n", __func__, wiphy); ++ ++ if(rwnx_hw->is_sched_scan || scanning){ ++ AICWFDBG(LOGERROR, "%s is_sched_scanning and scanning, busy", __func__); ++ return -EBUSY; ++ } ++ ++ scan_request = (struct cfg80211_scan_request *)kmalloc(sizeof(struct cfg80211_scan_request), GFP_KERNEL); ++ ++ scan_request->ssids = request->ssids; ++ scan_request->n_channels = request->n_channels; ++ scan_request->n_ssids = request->n_match_sets; ++ scan_request->no_cck = false; ++ scan_request->ie = request->ie; ++ scan_request->ie_len = request->ie_len; ++ scan_request->flags = request->flags; ++ ++ scan_request->wiphy = wiphy; ++ scan_request->scan_start = request->scan_start; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) ++ memcpy(scan_request->mac_addr, request->mac_addr, ETH_ALEN); ++ memcpy(scan_request->mac_addr_mask, request->mac_addr_mask, ETH_ALEN); ++#endif ++ rwnx_hw->sched_scan_req = request; ++ scan_request->wdev = &rwnx_vif->wdev; ++ AICWFDBG(LOGDEBUG, "%s scan_request->n_channels:%d \r\n", __func__, scan_request->n_channels); ++ AICWFDBG(LOGDEBUG, "%s scan_request->n_ssids:%d \r\n", __func__, scan_request->n_ssids); ++ ++ for(index = 0; index < scan_request->n_ssids; index++){ ++ memset(scan_request->ssids[index].ssid, 0, IEEE80211_MAX_SSID_LEN); ++ ++ memcpy(scan_request->ssids[index].ssid, ++ request->match_sets[index].ssid.ssid, ++ IEEE80211_MAX_SSID_LEN); ++ ++ scan_request->ssids[index].ssid_len = request->match_sets[index].ssid.ssid_len; ++ ++ AICWFDBG(LOGDEBUG, "%s request ssid:%s len:%d \r\n", __func__, ++ scan_request->ssids[index].ssid, scan_request->ssids[index].ssid_len); ++ } ++ ++ for(index = 0;index < scan_request->n_channels; index++){ ++ scan_request->channels[index] = request->channels[index]; ++ ++ AICWFDBG(LOGDEBUG, "%s scan_request->channels[%d]:%d \r\n", __func__, index, ++ scan_request->channels[index]->center_freq); ++ ++ if(scan_request->channels[index] == NULL){ ++ AICWFDBG(LOGERROR, "%s ERROR!!! channels is NULL", __func__); ++ continue; ++ } ++ } ++ ++ rwnx_hw->is_sched_scan = true; ++ ++ if(scanning){ ++ AICWFDBG(LOGERROR, "%s scanning, about it", __func__); ++ kfree(scan_request); ++ return -EBUSY; ++ }else{ ++ ret = rwnx_cfg80211_scan(wiphy, scan_request); ++ } ++ ++ return ret; ++} ++#endif //CONFIG_SCHED_SCAN ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++/** ++ * @external_auth: indicates result of offloaded authentication processing from ++ * user space ++ */ ++static int rwnx_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_external_auth_params *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ ++ if (!rwnx_vif->sta.external_auth) ++ return -EINVAL; ++ ++ rwnx_external_auth_disable(rwnx_vif); ++ return rwnx_send_sm_external_auth_required_rsp(rwnx_hw, rwnx_vif, ++ params->status); ++} ++#endif ++ ++/** ++ * @add_station: Add a new station. ++ */ ++static int rwnx_cfg80211_add_station(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac, ++#else ++ const u8 *mac, ++#endif ++ struct station_parameters *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct me_sta_add_cfm me_sta_add_cfm; ++ int error = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ WARN_ON(RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN); ++ ++ /* Do not add TDLS station */ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ++ return 0; ++ ++ /* Indicate we are in a STA addition process - This will allow handling ++ * potential PS mode change indications correctly ++ */ ++ rwnx_hw->adding_sta = true; ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_me_sta_add(rwnx_hw, params, mac, rwnx_vif->vif_index, &me_sta_add_cfm); ++ if (error) ++ return error; ++ ++ // Check the status ++ switch (me_sta_add_cfm.status) { ++ case CO_OK: ++ { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[me_sta_add_cfm.sta_idx]; ++ int tid; ++ sta->aid = params->aid; ++ ++ sta->sta_idx = me_sta_add_cfm.sta_idx; ++ sta->ch_idx = rwnx_vif->ch_index; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->vlan_idx = sta->vif_idx; ++ sta->qos = (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) != 0; ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ sta->ht = params->link_sta_params.ht_capa ? 1 : 0; ++ sta->vht = params->link_sta_params.vht_capa ? 1 : 0; ++#else ++ sta->ht = params->ht_capa ? 1 : 0; ++ sta->vht = params->vht_capa ? 1 : 0; ++#endif ++ sta->acm = 0; ++ sta->key.hw_idx = 0; ++ ++ if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) ++ sta->mesh_pm = params->local_pm; ++ else ++ sta->mesh_pm = rwnx_vif->ap.next_mesh_pm; ++ rwnx_update_mesh_power_mode(rwnx_vif); ++ ++ for (tid = 0; tid < NX_NB_TXQ_PER_STA; tid++) { ++ int uapsd_bit = rwnx_hwq2uapsd[rwnx_tid2hwq[tid]]; ++ if (params->uapsd_queues & uapsd_bit) ++ sta->uapsd_tids |= 1 << tid; ++ else ++ sta->uapsd_tids &= ~(1 << tid); ++ } ++ memcpy(sta->mac_addr, mac, ETH_ALEN); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, sta); ++#endif ++ ++ /* Ensure that we won't process PS change or channel switch ind*/ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_txq_sta_init(rwnx_hw, sta, rwnx_txq_vif_get_status(rwnx_vif)); ++ list_add_tail(&sta->list, &rwnx_vif->ap.sta_list); ++ sta->valid = true; ++ rwnx_ps_bh_enable(rwnx_hw, sta, sta->ps.active || me_sta_add_cfm.pm_state); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ error = 0; ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { ++ struct station_info sinfo; ++ memset(&sinfo, 0, sizeof(struct station_info)); ++ sinfo.assoc_req_ies = NULL; ++ sinfo.assoc_req_ies_len = 0; ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; ++ #endif ++ cfg80211_new_sta(rwnx_vif->ndev, sta->mac_addr, &sinfo, GFP_KERNEL); ++ } ++#ifdef CONFIG_RWNX_BFMER ++ if (rwnx_hw->mod_params->bfmer) ++ rwnx_send_bfmer_enable(rwnx_hw, sta, params->vht_capa); ++ ++ rwnx_mu_group_sta_init(sta, params->vht_capa); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ #define PRINT_STA_FLAG(f) \ ++ (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "") ++ ++ netdev_info(dev, "Add sta %d (%pM) flags=%s%s%s%s%s%s%s", ++ sta->sta_idx, mac, ++ PRINT_STA_FLAG(AUTHORIZED), ++ PRINT_STA_FLAG(SHORT_PREAMBLE), ++ PRINT_STA_FLAG(WME), ++ PRINT_STA_FLAG(MFP), ++ PRINT_STA_FLAG(AUTHENTICATED), ++ PRINT_STA_FLAG(TDLS_PEER), ++ PRINT_STA_FLAG(ASSOCIATED)); ++ #undef PRINT_STA_FLAG ++ break; ++ } ++ default: ++ error = -EBUSY; ++ break; ++ } ++ ++ rwnx_hw->adding_sta = false; ++ ++ return error; ++} ++ ++/** ++ * @del_station: Remove a station ++ */ ++static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)) ++ const u8 *mac ++#else ++ struct station_del_parameters *params ++#endif ++ ++) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_sta *cur, *tmp; ++ int error = 0, found = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ const u8 *mac = NULL; ++#endif ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *reord_tmp; ++ u8 *macaddr; ++ struct aicwf_rx_priv *rx_priv; ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ if (params) ++ mac = params->mac; ++#endif ++ printk("%s: %pM\n", __func__, mac); ++ ++ do { ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ if(list_empty(&rwnx_vif->ap.sta_list)) { ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ break; ++ } ++ ++ list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { ++ if ((!mac) || (!memcmp(cur->mac_addr, mac, ETH_ALEN))) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if(found) { ++ cur->ps.active = false; ++ cur->valid = false; ++ list_del(&cur->list); ++ } ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if(found) { ++ netdev_info(dev, "Del sta %d (%pM)", cur->sta_idx, cur->mac_addr); ++ if (cur->vif_idx != cur->vlan_idx) { ++ struct rwnx_vif *vlan_vif; ++ vlan_vif = rwnx_hw->vif_table[cur->vlan_idx]; ++ if (vlan_vif->up) { ++ if ((RWNX_VIF_TYPE(vlan_vif) == NL80211_IFTYPE_AP_VLAN) && ++ (vlan_vif->use_4addr)) { ++ vlan_vif->ap_vlan.sta_4a = NULL; ++ } else { ++ WARN(1, "Deleting sta belonging to VLAN other than AP_VLAN 4A"); ++ } ++ } ++ } ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { ++ cfg80211_del_sta(rwnx_vif->ndev, cur->mac_addr, GFP_KERNEL); ++ } ++ ++#ifdef AICWF_RX_REORDER ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv = rwnx_hw->sdiodev->rx_priv; ++#else ++ rx_priv = rwnx_hw->usbdev->rx_priv; ++#endif ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ BUG();//should be other function ++ } ++ else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)){ ++ macaddr = cur->mac_addr; ++ printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0],macaddr[1],macaddr[2], \ ++ macaddr[3],macaddr[4],macaddr[5]); ++ list_for_each_entry_safe(reord_info, reord_tmp, ++ &rx_priv->stas_reord_list, list) { ++ printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0],reord_info->mac_addr[1],reord_info->mac_addr[2], \ ++ reord_info->mac_addr[3],reord_info->mac_addr[4],reord_info->mac_addr[5]); ++ if (!memcmp(reord_info->mac_addr, macaddr, 6)) { ++ reord_deinit_sta(rx_priv, reord_info); ++ break; ++ } ++ } ++ } ++#endif ++ ++ rwnx_txq_sta_deinit(rwnx_hw, cur); ++ error = rwnx_send_me_sta_del(rwnx_hw, cur->sta_idx, false); ++ if ((error != 0) && (error != -EPIPE)) ++ return error; ++ ++#ifdef CONFIG_RWNX_BFMER ++ // Disable Beamformer if supported ++ rwnx_bfmer_report_del(rwnx_hw, cur); ++ rwnx_mu_group_sta_del(rwnx_hw, cur); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++#ifdef CONFIG_DEBUG_FS_AIC ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, cur); ++#endif ++ } ++ ++ if(mac) ++ break; ++ } while (1); ++ ++ rwnx_update_mesh_power_mode(rwnx_vif); ++ ++ if(!found && mac != NULL) ++ return -ENOENT; ++ else ++ return 0; ++} ++ ++ ++void apm_staloss_work_process(struct work_struct *work) ++{ ++ struct rwnx_hw *rwnx_hw = container_of(work, struct rwnx_hw, apmStalossWork); ++ struct rwnx_sta *cur, *tmp; ++ int error = 0; ++ ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *reord_tmp; ++ u8 *macaddr; ++ struct aicwf_rx_priv *rx_priv; ++#endif ++ struct rwnx_vif *rwnx_vif; ++ bool_l found = false; ++ const u8 *mac = rwnx_hw->sta_mac_addr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == rwnx_hw->apm_vif_idx) { ++ found = true; ++ break; ++ } ++ } ++ ++ printk("apm vif idx=%d, found=%d, mac addr=%pM\n", rwnx_hw->apm_vif_idx, found, mac); ++ if (!found || !rwnx_vif || (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_AP && RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_P2P_GO)) ++ { ++ return; ++ } ++ ++ found = false; ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { ++ if ((mac) && (!memcmp(cur->mac_addr, mac, ETH_ALEN))) { ++ found = true; ++ break; ++ } ++ } ++ if(found) { ++ cur->ps.active = false; ++ cur->valid = false; ++ list_del(&cur->list); ++ } ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if(found) { ++ netdev_info(rwnx_vif->ndev, "Del sta %d (%pM)", cur->sta_idx, cur->mac_addr); ++ if (cur->vif_idx != cur->vlan_idx) { ++ struct rwnx_vif *vlan_vif; ++ vlan_vif = rwnx_hw->vif_table[cur->vlan_idx]; ++ if (vlan_vif->up) { ++ if ((RWNX_VIF_TYPE(vlan_vif) == NL80211_IFTYPE_AP_VLAN) && ++ (vlan_vif->use_4addr)) { ++ vlan_vif->ap_vlan.sta_4a = NULL; ++ } else { ++ WARN(1, "Deleting sta belonging to VLAN other than AP_VLAN 4A"); ++ } ++ } ++ } ++ ++#ifdef AICWF_RX_REORDER ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv = rwnx_hw->sdiodev->rx_priv; ++#else ++ rx_priv = rwnx_hw->usbdev->rx_priv; ++#endif ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ BUG();//should be other function ++ } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { ++ macaddr = cur->mac_addr; ++ printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0], macaddr[1], macaddr[2], \ ++ macaddr[3], macaddr[4], macaddr[5]); ++ list_for_each_entry_safe(reord_info, reord_tmp, ++ &rx_priv->stas_reord_list, list) { ++ printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0], reord_info->mac_addr[1], reord_info->mac_addr[2], \ ++ reord_info->mac_addr[3], reord_info->mac_addr[4], reord_info->mac_addr[5]); ++ if (!memcmp(reord_info->mac_addr, macaddr, 6)) { ++ reord_deinit_sta(rx_priv, reord_info); ++ break; ++ } ++ } ++ } ++#endif ++ ++ rwnx_txq_sta_deinit(rwnx_hw, cur); ++ error = rwnx_send_me_sta_del(rwnx_hw, cur->sta_idx, false); ++ if ((error != 0) && (error != -EPIPE)) ++ return; ++ ++#ifdef CONFIG_RWNX_BFMER ++ // Disable Beamformer if supported ++ rwnx_bfmer_report_del(rwnx_hw, cur); ++ rwnx_mu_group_sta_del(rwnx_hw, cur); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++#ifdef CONFIG_DEBUG_FS_AIC ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, cur); ++#endif ++ }else { ++ printk("sta not found: %pM\n", mac); ++ return; ++ } ++ ++ rwnx_update_mesh_power_mode(rwnx_vif); ++} ++ ++ ++void apm_probe_sta_work_process(struct work_struct *work) ++{ ++ struct apm_probe_sta *probe_sta = container_of(work, struct apm_probe_sta, apmprobestaWork); ++ struct rwnx_vif *rwnx_vif = container_of(probe_sta, struct rwnx_vif, sta_probe); ++ bool found = false; ++ struct rwnx_sta *cur, *tmp; ++ ++ u8 *mac = rwnx_vif->sta_probe.sta_mac_addr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { ++ if (!memcmp(cur->mac_addr, mac, ETH_ALEN)) { ++ found = true; ++ break; ++ } ++ } ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ ++ printk("sta %pM found = %d\n", mac, found); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) ++ if(found) ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, 0, false, GFP_ATOMIC); ++ else ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 0, 0, false, GFP_ATOMIC); ++#else ++ if(found) ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, GFP_ATOMIC); ++ else ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 0, GFP_ATOMIC); ++ ++#endif ++ rwnx_vif->sta_probe.probe_id ++; ++} ++/** ++ * @change_station: Modify a given station. Note that flags changes are not much ++ * validated in cfg80211, in particular the auth/assoc/authorized flags ++ * might come to the driver in invalid combinations -- make sure to check ++ * them, also against the existing state! Drivers must call ++ * cfg80211_check_station_change() to validate the information. ++ */ ++static int rwnx_cfg80211_change_station(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac, ++#else ++ const u8 *mac, ++#endif ++ struct station_parameters *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_sta *sta; ++ ++ sta = rwnx_get_sta(rwnx_hw, mac); ++ if (!sta) { ++ /* Add the TDLS station */ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct me_sta_add_cfm me_sta_add_cfm; ++ int error = 0; ++ ++ /* Indicate we are in a STA addition process - This will allow handling ++ * potential PS mode change indications correctly ++ */ ++ rwnx_hw->adding_sta = true; ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_me_sta_add(rwnx_hw, params, mac, rwnx_vif->vif_index, &me_sta_add_cfm); ++ if (error) ++ return error; ++ ++ // Check the status ++ switch (me_sta_add_cfm.status) { ++ case CO_OK: ++ { ++ int tid; ++ sta = &rwnx_hw->sta_table[me_sta_add_cfm.sta_idx]; ++ sta->aid = params->aid; ++ sta->sta_idx = me_sta_add_cfm.sta_idx; ++ sta->ch_idx = rwnx_vif->ch_index; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->vlan_idx = sta->vif_idx; ++ sta->qos = (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) != 0; ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ sta->ht = params->link_sta_params.ht_capa ? 1 : 0; ++ sta->vht = params->link_sta_params.vht_capa ? 1 : 0; ++#else ++ sta->ht = params->ht_capa ? 1 : 0; ++ sta->vht = params->vht_capa ? 1 : 0; ++#endif ++ sta->acm = 0; ++ for (tid = 0; tid < NX_NB_TXQ_PER_STA; tid++) { ++ int uapsd_bit = rwnx_hwq2uapsd[rwnx_tid2hwq[tid]]; ++ if (params->uapsd_queues & uapsd_bit) ++ sta->uapsd_tids |= 1 << tid; ++ else ++ sta->uapsd_tids &= ~(1 << tid); ++ } ++ memcpy(sta->mac_addr, mac, ETH_ALEN); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, sta); ++#endif ++ /* Ensure that we won't process PS change or channel switch ind*/ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_txq_sta_init(rwnx_hw, sta, rwnx_txq_vif_get_status(rwnx_vif)); ++ if (rwnx_vif->tdls_status == TDLS_SETUP_RSP_TX) { ++ rwnx_vif->tdls_status = TDLS_LINK_ACTIVE; ++ sta->tdls.initiator = true; ++ sta->tdls.active = true; ++ } ++ /* Set TDLS channel switch capability */ ++ if ((params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) && ++ !rwnx_vif->tdls_chsw_prohibited) ++ sta->tdls.chsw_allowed = true; ++ rwnx_vif->sta.tdls_sta = sta; ++ sta->valid = true; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++#ifdef CONFIG_RWNX_BFMER ++ if (rwnx_hw->mod_params->bfmer) ++ rwnx_send_bfmer_enable(rwnx_hw, sta, params->vht_capa); ++ ++ rwnx_mu_group_sta_init(sta, NULL); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ #define PRINT_STA_FLAG(f) \ ++ (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "") ++ ++ netdev_info(dev, "Add %s TDLS sta %d (%pM) flags=%s%s%s%s%s%s%s", ++ sta->tdls.initiator ? "initiator" : "responder", ++ sta->sta_idx, mac, ++ PRINT_STA_FLAG(AUTHORIZED), ++ PRINT_STA_FLAG(SHORT_PREAMBLE), ++ PRINT_STA_FLAG(WME), ++ PRINT_STA_FLAG(MFP), ++ PRINT_STA_FLAG(AUTHENTICATED), ++ PRINT_STA_FLAG(TDLS_PEER), ++ PRINT_STA_FLAG(ASSOCIATED)); ++ #undef PRINT_STA_FLAG ++ ++ break; ++ } ++ default: ++ error = -EBUSY; ++ break; ++ } ++ ++ rwnx_hw->adding_sta = false; ++ } else { ++ return -EINVAL; ++ } ++ } ++ ++ if (params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) ++ rwnx_send_me_set_control_port_req(rwnx_hw, ++ (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) != 0, ++ sta->sta_idx); ++ ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MESH_POINT) { ++ if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) { ++ if (params->plink_state < NUM_NL80211_PLINK_STATES) { ++ rwnx_send_mesh_peer_update_ntf(rwnx_hw, vif, sta->sta_idx, params->plink_state); ++ } ++ } ++ ++ if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) { ++ sta->mesh_pm = params->local_pm; ++ rwnx_update_mesh_power_mode(vif); ++ } ++ } ++ ++ if (params->vlan) { ++ uint8_t vlan_idx; ++ ++ vif = netdev_priv(params->vlan); ++ vlan_idx = vif->vif_index; ++ ++ if (sta->vlan_idx != vlan_idx) { ++ struct rwnx_vif *old_vif; ++ old_vif = rwnx_hw->vif_table[sta->vlan_idx]; ++ rwnx_txq_sta_switch_vif(sta, old_vif, vif); ++ sta->vlan_idx = vlan_idx; ++ ++ if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP_VLAN) && ++ (vif->use_4addr)) { ++ WARN((vif->ap_vlan.sta_4a), ++ "4A AP_VLAN interface with more than one sta"); ++ vif->ap_vlan.sta_4a = sta; ++ } ++ ++ if ((RWNX_VIF_TYPE(old_vif) == NL80211_IFTYPE_AP_VLAN) && ++ (old_vif->use_4addr)) { ++ old_vif->ap_vlan.sta_4a = NULL; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * @start_ap: Start acting in AP mode defined by the parameters. ++ */ ++static int rwnx_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_ap_settings *settings) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct apm_start_cfm apm_start_cfm; ++ struct rwnx_ipc_elem_var elem; ++ struct rwnx_sta *sta; ++ int error = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ INIT_WORK(&rwnx_vif->sta_probe.apmprobestaWork, apm_probe_sta_work_process); ++ rwnx_vif->sta_probe.apmprobesta_wq = create_singlethread_workqueue("apmprobe_wq"); ++ if (!rwnx_vif->sta_probe.apmprobesta_wq) { ++ txrx_err("insufficient memory to create apmprobe_wq.\n"); ++ return -ENOBUFS; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ++ rwnx_hw->is_p2p_connected = 1; ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_apm_start_req(rwnx_hw, rwnx_vif, settings, &apm_start_cfm, &elem); ++ if (error) ++ goto end; ++ ++ // Check the status ++ switch (apm_start_cfm.status) { ++ case CO_OK: ++ { ++ u8 txq_status = 0; ++ rwnx_vif->ap.bcmc_index = apm_start_cfm.bcmc_idx; ++ rwnx_vif->ap.flags = 0; ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ rwnx_vif->ap.aic_index = 0; ++#endif ++ rwnx_vif->ap.csa = NULL; ++ sta = &rwnx_hw->sta_table[apm_start_cfm.bcmc_idx]; ++ sta->valid = true; ++ sta->aid = 0; ++ sta->sta_idx = apm_start_cfm.bcmc_idx; ++ sta->ch_idx = apm_start_cfm.ch_idx; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->qos = false; ++ sta->acm = 0; ++ sta->ps.active = false; ++ rwnx_mu_group_sta_init(sta, NULL); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_link(rwnx_vif, apm_start_cfm.ch_idx, ++ &settings->chandef); ++ if (rwnx_hw->cur_chanctx != apm_start_cfm.ch_idx) { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ rwnx_txq_vif_init(rwnx_hw, rwnx_vif, txq_status); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ error = 0; ++ /* If the AP channel is already the active, we probably skip radar ++ activation on MM_CHANNEL_SWITCH_IND (unless another vif use this ++ ctxt). In anycase retest if radar detection must be activated ++ */ ++ if (txq_status == 0) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ } ++ break; ++ } ++ case CO_BUSY: ++ error = -EINPROGRESS; ++ break; ++ case CO_OP_IN_PROGRESS: ++ error = -EALREADY; ++ break; ++ default: ++ error = -EIO; ++ break; ++ } ++ ++ if (error) { ++ netdev_info(dev, "Failed to start AP (%d)", error); ++ } else { ++ netdev_info(dev, "AP started: ch=%d, bcmc_idx=%d channel=%d bw=%d", ++ rwnx_vif->ch_index, rwnx_vif->ap.bcmc_index, ++ ((settings->chandef).chan)->center_freq, ++ ((settings->chandef).width)); ++ } ++ ++end: ++ //rwnx_ipc_elem_var_deallocs(rwnx_hw, &elem); ++ ++ return error; ++} ++ ++ ++/** ++ * @change_beacon: Change the beacon parameters for an access point mode ++ * interface. This should reject the call when AP mode wasn't started. ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)) ++static int rwnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_ap_update *params) ++#else ++static int rwnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_beacon_data *info) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_bcn *bcn = &vif->ap.bcn; ++ struct rwnx_ipc_elem_var elem; ++ u8 *buf; ++ int error = 0; ++ elem.dma_addr = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Build the beacon ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)) ++ buf = rwnx_build_bcn(bcn, ¶ms->beacon); ++#else ++ buf = rwnx_build_bcn(bcn, info); ++#endif ++ if (!buf) ++ return -ENOMEM; ++ ++ rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn->len); ++ ++ // Forward the information to the LMAC ++ error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, ++ bcn->len, bcn->head_len, bcn->tim_len, NULL); ++ ++ return error; ++} ++ ++/** ++ * * @stop_ap: Stop being an AP, including stopping beaconing. ++ */ ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION) ++static int rwnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, unsigned int link_id) ++#else ++static int rwnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_sta *sta; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ ++ /* delete any remaining STA*/ ++ while (!list_empty(&rwnx_vif->ap.sta_list)) { ++ rwnx_cfg80211_del_station_compat(wiphy, dev, NULL); ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ++ rwnx_hw->is_p2p_connected = 0; ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ rwnx_send_apm_stop_req(rwnx_hw, rwnx_vif); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_unlink(rwnx_vif); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ /* delete BC/MC STA */ ++ sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ rwnx_txq_vif_deinit(rwnx_hw, rwnx_vif); ++ rwnx_del_bcn(&rwnx_vif->ap.bcn); ++ rwnx_del_csa(rwnx_vif); ++ ++ flush_workqueue(rwnx_vif->sta_probe.apmprobesta_wq); ++ destroy_workqueue(rwnx_vif->sta_probe.apmprobesta_wq); ++ ++ netdev_info(dev, "AP Stopped"); ++ ++ return 0; ++} ++ ++/** ++ * @set_monitor_channel: Set the monitor mode channel for the device. If other ++ * interfaces are active this callback should reject the configuration. ++ * If no interfaces are active or the device is down, the channel should ++ * be stored for when a monitor interface becomes active. ++ * ++ * Also called internaly with chandef set to NULL simply to retrieve the channel ++ * configured at firmware level. ++ */ ++static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 13, 0) ++ struct net_device *, ++#endif ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif; ++ struct me_config_monitor_cfm cfm; ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (rwnx_hw->monitor_vif == RWNX_INVALID_VIF) ++ return -EINVAL; ++ ++ rwnx_vif = rwnx_hw->vif_table[rwnx_hw->monitor_vif]; ++ ++ // Do nothing if monitor interface is already configured with the requested channel ++ if (rwnx_chanctx_valid(rwnx_hw, rwnx_vif->ch_index)) { ++ struct rwnx_chanctx *ctxt; ++ ctxt = &rwnx_vif->rwnx_hw->chanctx_table[rwnx_vif->ch_index]; ++ if (chandef && cfg80211_chandef_identical(&ctxt->chan_def, chandef)) ++ return 0; ++ } ++ ++ // Always send command to firmware. It allows to retrieve channel context index ++ // and its configuration. ++ if (rwnx_send_config_monitor_req(rwnx_hw, chandef, &cfm)) ++ return -EIO; ++ ++ // Always re-set channel context info ++ rwnx_chanctx_unlink(rwnx_vif); ++ ++ ++ ++ // If there is also a STA interface not yet connected then monitor interface ++ // will only have a channel context after the connection of the STA interface. ++ if (cfm.chan_index != RWNX_CH_NOT_SET) { ++ struct cfg80211_chan_def mon_chandef; ++ ++ if (rwnx_hw->vif_started > 1) { ++ // In this case we just want to update the channel context index not ++ // the channel configuration ++ rwnx_chanctx_link(rwnx_vif, cfm.chan_index, NULL); ++ return -EBUSY; ++ } ++ ++ mon_chandef.chan = ieee80211_get_channel(wiphy, cfm.chan.prim20_freq); ++ mon_chandef.center_freq1 = cfm.chan.center1_freq; ++ mon_chandef.center_freq2 = cfm.chan.center2_freq; ++ mon_chandef.width = chnl2bw[cfm.chan.type]; ++ rwnx_chanctx_link(rwnx_vif, cfm.chan_index, &mon_chandef); ++ } ++ ++ return 0; ++} ++ ++int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef){ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 13, 0) ++ return rwnx_cfg80211_set_monitor_channel(wiphy, NULL, chandef); ++#else ++ return rwnx_cfg80211_set_monitor_channel(wiphy, chandef); ++#endif ++} ++ ++ ++/** ++ * @probe_client: probe an associated client, must return a cookie that it ++ * later passes to cfg80211_probe_status(). ++ */ ++int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, u64 *cookie) ++{ ++// struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_sta *sta = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if((RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP) && (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_P2P_GO) && ++ (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP_VLAN)) ++ return -EINVAL; ++ spin_lock_bh(&vif->rwnx_hw->cb_lock); ++ list_for_each_entry(sta, &vif->ap.sta_list, list){ ++ if (sta->valid && ether_addr_equal(sta->mac_addr, peer)) ++ break; ++ } ++ spin_unlock_bh(&vif->rwnx_hw->cb_lock); ++ ++ if (!sta) ++ return -ENOENT; ++ ++ ++ memcpy(vif->sta_probe.sta_mac_addr, peer, 6); ++ queue_work(vif->sta_probe.apmprobesta_wq, &vif->sta_probe.apmprobestaWork); ++ ++ *cookie = vif->sta_probe.probe_id; ++ ++ return 0; ++ ++} ++ ++/** ++ * @mgmt_frame_register: Notify driver that a management frame type was ++ * registered. Note that this callback may not sleep, and cannot run ++ * concurrently with itself. ++ */ ++void rwnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ u16 frame_type, bool reg) ++{ ++} ++ ++/** ++ * @set_wiphy_params: Notify that wiphy parameters have changed; ++ * @changed bitfield (see &enum wiphy_params_flags) describes which values ++ * have changed. The actual parameter values are available in ++ * struct wiphy. If returning an error, no value should be changed. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ++#else ++static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, int radio_idx, u32 changed) ++#endif ++{ ++ return 0; ++} ++ ++ ++/** ++ * @set_tx_power: set the transmit power according to the parameters, ++ * the power passed is in mBm, to get dBm use MBM_TO_DBM(). The ++ * wdev may be %NULL if power was set for the wiphy, and will ++ * always be %NULL unless the driver supports per-vif TX power ++ * (as advertised by the nl80211 feature flag.) ++ */ ++static int rwnx_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ enum nl80211_tx_power_setting type, int mbm) ++#else ++ int radio_idx, enum nl80211_tx_power_setting type, int mbm) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif; ++ s8 pwr; ++ int res = 0; ++ ++ if (type == NL80211_TX_POWER_AUTOMATIC) { ++ pwr = 0x7f; ++ } else { ++ pwr = MBM_TO_DBM(mbm); ++ } ++ ++ if (wdev) { ++ vif = container_of(wdev, struct rwnx_vif, wdev); ++ res = rwnx_send_set_power(rwnx_hw, vif->vif_index, pwr, NULL); ++ } else { ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ res = rwnx_send_set_power(rwnx_hw, vif->vif_index, pwr, NULL); ++ if (res) ++ break; ++ } ++ } ++ ++ return res; ++} ++ ++static int rwnx_cfg80211_get_tx_power(struct wiphy *wiphy, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) ++ struct wireless_dev *wdev, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 14, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ unsigned int link_id, ++#else ++ int radio_idx, unsigned int link_id, ++#endif ++#endif ++#endif ++ int *mbm) ++{ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) ++ struct wireless_dev *wdev = NULL; ++ #endif ++ //struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ //struct rwnx_vif *vif; ++ s8 pwr = 0; ++ int res = 0; ++ ++ *mbm = get_txpwr_max(pwr); ++ ++ return res; ++} ++ ++/** ++ * @set_power_mgmt: set the power save to one of those two modes: ++ * Power-save off ++ * Power-save on - Dynamic mode ++ */ ++static int rwnx_cfg80211_set_power_mgmt(struct wiphy *wiphy, ++ struct net_device *dev, ++ bool enabled, int timeout) ++{ ++#if 0 ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ u8 ps_mode; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ if (timeout >= 0) ++ netdev_info(dev, "Ignore timeout value %d", timeout); ++ ++ if (!(rwnx_hw->version_cfm.features & BIT(MM_FEAT_PS_BIT))) ++ enabled = false; ++ ++ if (enabled) { ++ /* Switch to Dynamic Power Save */ ++ ps_mode = MM_PS_MODE_ON_DYN; ++ } else { ++ /* Exit Power Save */ ++ ps_mode = MM_PS_MODE_OFF; ++ } ++ ++ return rwnx_send_me_set_ps_mode(rwnx_hw, ps_mode); ++#else ++ /* TODO ++ * Add handle in the feature! ++ */ ++ return 0; ++#endif ++} ++ ++static int rwnx_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev, ++ struct ieee80211_txq_params *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ u8 hw_queue, aifs, cwmin, cwmax; ++ u32 param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ hw_queue = rwnx_ac2hwq[0][params->ac]; ++ ++ aifs = params->aifs; ++ cwmin = fls(params->cwmin); ++ cwmax = fls(params->cwmax); ++ ++ /* Store queue information in general structure */ ++ param = (u32) (aifs << 0); ++ param |= (u32) (cwmin << 4); ++ param |= (u32) (cwmax << 8); ++ param |= (u32) (params->txop) << 12; ++ ++ /* Send the MM_SET_EDCA_REQ message to the FW */ ++ return rwnx_send_set_edca(rwnx_hw, hw_queue, param, false, rwnx_vif->vif_index); ++} ++ ++ ++/** ++ * @remain_on_channel: Request the driver to remain awake on the specified ++ * channel for the specified duration to complete an off-channel ++ * operation (e.g., public action frame exchange). When the driver is ++ * ready on the requested channel, it must indicate this with an event ++ * notification by calling cfg80211_ready_on_channel(). ++ */ ++static int ++rwnx_cfg80211_remain_on_channel_(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, ++ unsigned int duration, u64 *cookie, bool mgmt_roc_flag) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ //struct rwnx_vif *rwnx_vif = netdev_priv(wdev->netdev); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ struct rwnx_roc_elem *roc_elem; ++ struct mm_add_if_cfm add_if_cfm; ++ struct mm_remain_on_channel_cfm roc_cfm; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* For debug purpose (use ftrace kernel option) */ ++#ifdef CREATE_TRACE_POINTS ++ trace_roc(rwnx_vif->vif_index, chan->center_freq, duration); ++#endif ++ /* Check that no other RoC procedure has been launched */ ++ if (rwnx_hw->roc_elem) { ++ msleep(2); ++ if (rwnx_hw->roc_elem) { ++ printk("remain_on_channel fail\n"); ++ return -EBUSY; ++ } ++ } ++ ++ printk("remain:%d,%d,%d\n", rwnx_vif->vif_index, rwnx_vif->is_p2p_vif, rwnx_hw->is_p2p_alive); ++#ifdef CONFIG_USE_P2P0 ++ if (rwnx_vif->is_p2p_vif) { ++#else ++ if (rwnx_vif == rwnx_hw->p2p_dev_vif && !rwnx_vif->up) { ++#endif ++ if (!rwnx_hw->is_p2p_alive) { ++ error = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, //wdev->netdev->dev_addr, ++ RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); ++ if (error) ++ return -EIO; ++ ++ if (add_if_cfm.status != 0) { ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->is_p2p_alive = 1; ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ } else { ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ } ++ } ++ ++ /* Allocate a temporary RoC element */ ++ roc_elem = kmalloc(sizeof(struct rwnx_roc_elem), GFP_KERNEL); ++ ++ /* Verify that element has well been allocated */ ++ if (!roc_elem) { ++ return -ENOMEM; ++ } ++ ++ /* Initialize the RoC information element */ ++ roc_elem->wdev = wdev; ++ roc_elem->chan = chan; ++ roc_elem->duration = duration; ++ roc_elem->mgmt_roc = mgmt_roc_flag; ++ roc_elem->on_chan = false; ++ ++ /* Initialize the OFFCHAN TX queue to allow off-channel transmissions */ ++ rwnx_txq_offchan_init(rwnx_vif); ++ ++ /* Forward the information to the FMAC */ ++ rwnx_hw->roc_elem = roc_elem; ++ error = rwnx_send_roc(rwnx_hw, rwnx_vif, chan, duration, &roc_cfm); ++ ++ /* If no error, keep all the information for handling of end of procedure */ ++ if (error == 0) { ++ /* Set the cookie value */ ++ *cookie = (u64)(rwnx_hw->roc_cookie_cnt); ++ if (roc_cfm.status) { ++ // failed to roc ++ rwnx_hw->roc_elem = NULL; ++ kfree(roc_elem); ++ rwnx_txq_offchan_deinit(rwnx_vif); ++ return -EBUSY; ++ } ++ } else { ++ /* Free the allocated element */ ++ rwnx_hw->roc_elem = NULL; ++ kfree(roc_elem); ++ rwnx_txq_offchan_deinit(rwnx_vif); ++ } ++ ++ return error; ++} ++ ++ ++static int ++rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, ++ unsigned int duration, u64 *cookie) ++{ ++ return rwnx_cfg80211_remain_on_channel_(wiphy, wdev, chan, duration, cookie, false); ++} ++ ++/** ++ * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. ++ * This allows the operation to be terminated prior to timeout based on ++ * the duration value. ++ */ ++static int rwnx_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ u64 cookie) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++#ifdef CREATE_TRACE_POINTS ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);//netdev_priv(wdev->netdev); ++#endif ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* For debug purpose (use ftrace kernel option) */ ++#ifdef CREATE_TRACE_POINTS ++ trace_cancel_roc(rwnx_vif->vif_index); ++#endif ++ /* Check if a RoC procedure is pending */ ++ if (!rwnx_hw->roc_elem) { ++ return 0; ++ } ++ ++ /* Forward the information to the FMAC */ ++ return rwnx_send_cancel_roc(rwnx_hw); ++} ++ ++#define IS_2P4GHZ(n) (n >= 2412 && n <= 2484) ++#define IS_5GHZ(n) (n >= 4000 && n <= 5895) ++#define DEFAULT_NOISE_FLOOR_2GHZ (-89) ++#define DEFAULT_NOISE_FLOOR_5GHZ (-92) ++ ++/** ++ * @dump_survey: get site survey information. ++ */ ++static int rwnx_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *netdev, ++ int idx, struct survey_info *info) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct ieee80211_supported_band *sband; ++ struct rwnx_survey_info *rwnx_survey; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (idx >= ARRAY_SIZE(rwnx_hw->survey)) ++ return -ENOENT; ++ ++ rwnx_survey = &rwnx_hw->survey[idx]; ++ ++ // Check if provided index matches with a supported 2.4GHz channel ++ sband = wiphy->bands[NL80211_BAND_2GHZ]; ++ if (sband && idx >= sband->n_channels) { ++ idx -= sband->n_channels; ++ sband = NULL; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ if (!sband) { ++ // Check if provided index matches with a supported 5GHz channel ++ sband = wiphy->bands[NL80211_BAND_5GHZ]; ++ ++ if (!sband || idx >= sband->n_channels) ++ return -ENOENT; ++ } ++ } else { ++ if (!sband || idx >= sband->n_channels) ++ return -ENOENT; ++ } ++ ++ // Fill the survey ++ info->channel = &sband->channels[idx]; ++ info->filled = rwnx_survey->filled; ++ ++ if (rwnx_survey->filled != 0) { ++ SURVEY_TIME(info) = (u64)rwnx_survey->chan_time_ms; ++ SURVEY_TIME_BUSY(info) = (u64)rwnx_survey->chan_time_busy_ms; ++ //info->noise = rwnx_survey->noise_dbm; ++ info->noise = ((IS_2P4GHZ(info->channel->center_freq)) ? DEFAULT_NOISE_FLOOR_2GHZ : ++ (IS_5GHZ(info->channel->center_freq)) ? DEFAULT_NOISE_FLOOR_5GHZ : DEFAULT_NOISE_FLOOR_5GHZ); ++ ++ // Set the survey report as not used ++ if(info->noise == 0){ ++ rwnx_survey->filled = 0; ++ }else{ ++ rwnx_survey->filled |= SURVEY_INFO_NOISE_DBM; ++ } ++ ++ } ++ ++ return 0; ++} ++ ++/** ++ * @get_channel: Get the current operating channel for the virtual interface. ++ * For monitor interfaces, it should return %NULL unless there's a single ++ * current monitoring channel. ++ */ ++static int rwnx_cfg80211_get_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ unsigned int link_id, ++#endif ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ struct rwnx_chanctx *ctxt; ++ ++ if (!rwnx_vif->up) { ++ return -ENODATA; ++ } ++ ++ if (rwnx_vif->vif_index == rwnx_hw->monitor_vif) { ++ //retrieve channel from firmware ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 13, 0) ++ rwnx_cfg80211_set_monitor_channel(wiphy, NULL, NULL); ++#else ++ rwnx_cfg80211_set_monitor_channel(wiphy, NULL); ++#endif ++ } ++ ++ //Check if channel context is valid ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_vif->ch_index)) { ++ return -ENODATA; ++ } ++ ++ ctxt = &rwnx_hw->chanctx_table[rwnx_vif->ch_index]; ++ *chandef = ctxt->chan_def; ++ ++ return 0; ++} ++ ++/** ++ * @mgmt_tx: Transmit a management frame. ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct cfg80211_mgmt_tx_params *params, ++ u64 *cookie) ++#else ++static int rwnx_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, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ bool no_cck, ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) ++ bool dont_wait_for_ack, ++ #endif ++ u64 *cookie) ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);//netdev_priv(wdev->netdev); ++ struct rwnx_sta *rwnx_sta; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ struct ieee80211_channel *channel = params->chan; ++ const u8 *buf = params->buf; ++ //size_t len = params->len; ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ struct ieee80211_mgmt *mgmt = (void *)buf; ++ bool ap = false; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ bool offchan = false; ++ #endif ++ ++ /* Check if provided VIF is an AP or a STA one */ ++ switch (RWNX_VIF_TYPE(rwnx_vif)) { ++ case NL80211_IFTYPE_AP_VLAN: ++ rwnx_vif = rwnx_vif->ap_vlan.master; ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ case NL80211_IFTYPE_MESH_POINT: ++ ap = true; ++ break; ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ default: ++ break; ++ } ++ ++ /* Get STA on which management frame has to be sent */ ++ rwnx_sta = rwnx_retrieve_sta(rwnx_hw, rwnx_vif, mgmt->da, ++ mgmt->frame_control, ap); ++#ifdef CREATE_TRACE_POINTS ++ trace_mgmt_tx((channel) ? channel->center_freq : 0, ++ rwnx_vif->vif_index, (rwnx_sta) ? rwnx_sta->sta_idx : 0xFF, ++ mgmt); ++#endif ++ if (ap || rwnx_sta) ++ goto send_frame; ++ ++ /* Not an AP interface sending frame to unknown STA: ++ * This is allowed for external authetication */ ++ if (rwnx_vif->sta.external_auth && ieee80211_is_auth(mgmt->frame_control)) ++ goto send_frame; ++ ++ /* Otherwise ROC is needed */ ++ if (!channel) { ++ printk("mgmt_tx fail since channel\n"); ++ return -EINVAL; ++ } ++ ++ /* Check that a RoC is already pending */ ++ if (rwnx_hw->roc_elem) { ++ /* Get VIF used for current ROC */ ++ struct rwnx_vif *rwnx_roc_vif = container_of(rwnx_hw->roc_elem->wdev, struct rwnx_vif, wdev);//netdev_priv(rwnx_hw->roc_elem->wdev->netdev); ++ ++ /* Check if RoC channel is the same than the required one */ ++ if ((rwnx_hw->roc_elem->chan->center_freq != channel->center_freq) ++ || (rwnx_vif->vif_index != rwnx_roc_vif->vif_index)) { ++ printk("mgmt rx chan invalid: %d, %d", rwnx_hw->roc_elem->chan->center_freq, channel->center_freq); ++ return -EINVAL; ++ } ++ } else { ++ u64 cookie; ++ int error; ++ ++ printk("mgmt rx remain on chan\n"); ++ ++ /* Start a ROC procedure for 30ms */ ++ error = rwnx_cfg80211_remain_on_channel_(wiphy, wdev, channel, ++ 30, &cookie, true); ++ if (error) { ++ printk("mgmt rx chan err\n"); ++ return error; ++ } ++ /* Need to keep in mind that RoC has been launched internally in order to ++ * avoid to call the cfg80211 callback once expired */ ++ //rwnx_hw->roc_elem->mgmt_roc = true; ++ } ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ offchan = true; ++ #endif ++ ++send_frame: ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, params, offchan, cookie); ++ #else ++ return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, channel, offchan, wait, buf, len, no_cck, dont_wait_for_ack, cookie); ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++} ++ ++/** ++ * @start_radar_detection: Start radar detection in the driver. ++ */ ++static ++int rwnx_cfg80211_start_radar_detection(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_chan_def *chandef ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) ++ , u32 cac_time_ms ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)) ++ , int link_id ++ #endif ++ ) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct apm_start_cac_cfm cfm; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) ++ rwnx_radar_start_cac(&rwnx_hw->radar, cac_time_ms, rwnx_vif); ++ #endif ++ rwnx_send_apm_start_cac_req(rwnx_hw, rwnx_vif, chandef, &cfm); ++ ++ if (cfm.status == CO_OK) { ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_link(rwnx_vif, cfm.ch_idx, chandef); ++ if (rwnx_hw->cur_chanctx == rwnx_vif->ch_index) ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_REPORT, ++ RWNX_RADAR_RIU); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } else { ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++/** ++ * @update_ft_ies: Provide updated Fast BSS Transition information to the ++ * driver. If the SME is in the driver/firmware, this information can be ++ * used in building Authentication and Reassociation Request frames. ++ */ ++static ++int rwnx_cfg80211_update_ft_ies(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_update_ft_ies_params *ftie) ++{ ++ printk("%s\n", __func__); ++ return 0; ++} ++ ++/** ++ * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. ++ */ ++static ++int rwnx_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, ++ struct net_device *dev, ++ int32_t rssi_thold, uint32_t rssi_hyst) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ ++ return rwnx_send_cfg_rssi_req(rwnx_hw, rwnx_vif->vif_index, rssi_thold, rssi_hyst); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++/** ++ * ++ * @channel_switch: initiate channel-switch procedure (with CSA). Driver is ++ * responsible for veryfing if the switch is possible. Since this is ++ * inherently tricky driver may decide to disconnect an interface later ++ * with cfg80211_stop_iface(). This doesn't mean driver can accept ++ * everything. It should do it's best to verify requests and reject them ++ * as soon as possible. ++ */ ++int rwnx_cfg80211_channel_switch (struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_csa_settings *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_bcn *bcn, *bcn_after; ++ struct rwnx_csa *csa; ++ u16 csa_oft[BCN_MAX_CSA_CPT]; ++ u8 *buf; ++ int i, error = 0; ++ ++ ++ if (vif->ap.csa) ++ return -EBUSY; ++ ++ if (params->n_counter_offsets_beacon > BCN_MAX_CSA_CPT) ++ return -EINVAL; ++ ++ /* Build the new beacon with CSA IE */ ++ bcn = &vif->ap.bcn; ++ buf = rwnx_build_bcn(bcn, ¶ms->beacon_csa); ++ if (!buf) ++ return -ENOMEM; ++ ++ memset(csa_oft, 0, sizeof(csa_oft)); ++ for (i = 0; i < params->n_counter_offsets_beacon; i++) { ++ csa_oft[i] = params->counter_offsets_beacon[i] + bcn->head_len + ++ bcn->tim_len; ++ } ++ ++ /* If count is set to 0 (i.e anytime after this beacon) force it to 2 */ ++ if (params->count == 0) { ++ params->count = 2; ++ for (i = 0; i < params->n_counter_offsets_beacon; i++) { ++ buf[csa_oft[i]] = 2; ++ } ++ } ++ ++ error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn->len); ++ if (error) { ++ goto end; ++ } ++ ++ /* Build the beacon to use after CSA. It will only be sent to fw once ++ CSA is over, but do it before sending the beacon as it must be ready ++ when CSA is finished. */ ++ csa = kzalloc(sizeof(struct rwnx_csa), GFP_KERNEL); ++ if (!csa) { ++ error = -ENOMEM; ++ goto end; ++ } ++ ++ bcn_after = &csa->bcn; ++ buf = rwnx_build_bcn(bcn_after, ¶ms->beacon_after); ++ if (!buf) { ++ error = -ENOMEM; ++ rwnx_del_csa(vif); ++ goto end; ++ } ++ ++ vif->ap.csa = csa; ++ csa->vif = vif; ++ csa->chandef = params->chandef; ++ ++ /* Send new Beacon. FW will extract channel and count from the beacon */ ++ error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, ++ bcn->len, bcn->head_len, bcn->tim_len, csa_oft); ++ ++ if (error) { ++ rwnx_del_csa(vif); ++ goto end; ++ } else { ++ INIT_WORK(&csa->work, rwnx_csa_finish); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 9, 0)) ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false); ++#elif LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION4 ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false, 0); ++#elif LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2 ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count, params->block_tx); ++#else ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count); ++#endif ++ ++ } ++ ++end: ++ return error; ++} ++#endif ++ ++ ++/* ++ * @tdls_mgmt: prepare TDLS action frame packets and forward them to FW ++ */ ++static int ++rwnx_cfg80211_tdls_mgmt(struct wiphy *wiphy, ++ struct net_device *dev, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ const u8 *peer, ++#else ++ u8 *peer, ++#endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0)) ++ int link_id, ++#endif ++ u8 action_code, ++ u8 dialog_token, ++ u16 status_code, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) ++ u32 peer_capability, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) ++ bool initiator, ++#endif ++ const u8 *buf, ++ size_t len) ++ ++{ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++ u32 peer_capability = 0; ++ #endif ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ bool initiator = false; ++ #endif ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int ret = 0; ++ ++ /* make sure we support TDLS */ ++ if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return -ENOTSUPP; ++ ++ /* make sure we are in station mode (and connected) */ ++ if ((RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_STATION) || ++ (!rwnx_vif->up) || (!rwnx_vif->sta.ap)) ++ return -ENOTSUPP; ++ ++ /* only one TDLS link is supported */ ++ if ((action_code == WLAN_TDLS_SETUP_REQUEST) && ++ (rwnx_vif->sta.tdls_sta) && ++ (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE)) { ++ printk("%s: only one TDLS link is supported!\n", __func__); ++ return -ENOTSUPP; ++ } ++ ++ if ((action_code == WLAN_TDLS_DISCOVERY_REQUEST) && ++ (rwnx_hw->mod_params->ps_on)) { ++ printk("%s: discovery request is not supported when " ++ "power-save is enabled!\n", __func__); ++ return -ENOTSUPP; ++ } ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_RESPONSE: ++ /* only one TDLS link is supported */ ++ if ((status_code == 0) && ++ (rwnx_vif->sta.tdls_sta) && ++ (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE)) { ++ printk("%s: only one TDLS link is supported!\n", __func__); ++ status_code = WLAN_STATUS_REQUEST_DECLINED; ++ } ++ /* fall-through */ ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ ret = rwnx_tdls_send_mgmt_packet_data(rwnx_hw, rwnx_vif, peer, action_code, ++ dialog_token, status_code, peer_capability, initiator, buf, len, 0, NULL); ++ break; ++ ++ default: ++ printk("%s: Unknown TDLS mgmt/action frame %pM\n", ++ __func__, peer); ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ if (action_code == WLAN_TDLS_SETUP_REQUEST) { ++ rwnx_vif->tdls_status = TDLS_SETUP_REQ_TX; ++ } else if (action_code == WLAN_TDLS_SETUP_RESPONSE) { ++ rwnx_vif->tdls_status = TDLS_SETUP_RSP_TX; ++ } else if ((action_code == WLAN_TDLS_SETUP_CONFIRM) && (ret == CO_OK)) { ++ rwnx_vif->tdls_status = TDLS_LINK_ACTIVE; ++ /* Set TDLS active */ ++ rwnx_vif->sta.tdls_sta->tdls.active = true; ++ } ++ ++ return ret; ++} ++ ++/* ++ * @tdls_oper: execute TDLS operation ++ */ ++static int ++rwnx_cfg80211_tdls_oper(struct wiphy *wiphy, ++ struct net_device *dev, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ const u8 *peer, ++#else ++ u8 *peer, ++#endif ++ enum nl80211_tdls_operation oper) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int error; ++ ++ if (oper != NL80211_TDLS_DISABLE_LINK) ++ return 0; ++ ++ if (!rwnx_vif->sta.tdls_sta) { ++ printk("%s: TDLS station %pM does not exist\n", __func__, peer); ++ return -ENOLINK; ++ } ++ ++ if (memcmp(rwnx_vif->sta.tdls_sta->mac_addr, peer, ETH_ALEN) == 0) { ++ /* Disable Channel Switch */ ++ if (!rwnx_send_tdls_cancel_chan_switch_req(rwnx_hw, rwnx_vif, ++ rwnx_vif->sta.tdls_sta, ++ NULL)) ++ rwnx_vif->sta.tdls_sta->tdls.chsw_en = false; ++ ++ netdev_info(dev, "Del TDLS sta %d (%pM)", ++ rwnx_vif->sta.tdls_sta->sta_idx, ++ rwnx_vif->sta.tdls_sta->mac_addr); ++ /* Ensure that we won't process PS change ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->sta.tdls_sta->ps.active = false; ++ rwnx_vif->sta.tdls_sta->valid = false; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_vif->sta.tdls_sta); ++ error = rwnx_send_me_sta_del(rwnx_hw, rwnx_vif->sta.tdls_sta->sta_idx, true); ++ if ((error != 0) && (error != -EPIPE)) ++ return error; ++ ++#ifdef CONFIG_RWNX_BFMER ++ // Disable Beamformer if supported ++ rwnx_bfmer_report_del(rwnx_hw, rwnx_vif->sta.tdls_sta); ++ rwnx_mu_group_sta_del(rwnx_hw, rwnx_vif->sta.tdls_sta); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ /* Set TDLS not active */ ++ rwnx_vif->sta.tdls_sta->tdls.active = false; ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.tdls_sta); ++#endif ++ // Remove TDLS station ++ rwnx_vif->tdls_status = TDLS_LINK_IDLE; ++ rwnx_vif->sta.tdls_sta = NULL; ++ } ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++/* ++ * @tdls_channel_switch: enable TDLS channel switch ++ */ ++static int ++rwnx_cfg80211_tdls_channel_switch (struct wiphy *wiphy, ++ struct net_device *dev, ++ const u8 *addr, u8 oper_class, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_sta *rwnx_sta = rwnx_vif->sta.tdls_sta; ++ struct tdls_chan_switch_cfm cfm; ++ int error; ++ ++ if ((!rwnx_sta) || (memcmp(addr, rwnx_sta->mac_addr, ETH_ALEN))) { ++ printk("%s: TDLS station %pM doesn't exist\n", __func__, addr); ++ return -ENOLINK; ++ } ++ ++ if (!rwnx_sta->tdls.chsw_allowed) { ++ printk("%s: TDLS station %pM does not support TDLS channel switch\n", __func__, addr); ++ return -ENOTSUPP; ++ } ++ ++ error = rwnx_send_tdls_chan_switch_req(rwnx_hw, rwnx_vif, rwnx_sta, ++ rwnx_sta->tdls.initiator, ++ oper_class, chandef, &cfm); ++ if (error) ++ return error; ++ ++ if (!cfm.status) { ++ rwnx_sta->tdls.chsw_en = true; ++ return 0; ++ } else { ++ printk("%s: TDLS channel switch already enabled and only one is supported\n", __func__); ++ return -EALREADY; ++ } ++} ++ ++/* ++ * @tdls_cancel_channel_switch: disable TDLS channel switch ++ */ ++static void ++rwnx_cfg80211_tdls_cancel_channel_switch (struct wiphy *wiphy, ++ struct net_device *dev, ++ const u8 *addr) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_sta *rwnx_sta = rwnx_vif->sta.tdls_sta; ++ struct tdls_cancel_chan_switch_cfm cfm; ++ ++ if (!rwnx_sta) ++ return; ++ ++ if (!rwnx_send_tdls_cancel_chan_switch_req(rwnx_hw, rwnx_vif, ++ rwnx_sta, &cfm)) ++ rwnx_sta->tdls.chsw_en = false; ++} ++#endif /* version >= 3.19 */ ++ ++/** ++ * @change_bss: Modify parameters for a given BSS (mainly for AP mode). ++ */ ++int rwnx_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, ++ struct bss_parameters *params) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int res = -EOPNOTSUPP; ++ ++ if (((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP) || ++ (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO)) && ++ (params->ap_isolate > -1)) { ++ ++ if (params->ap_isolate) ++ rwnx_vif->ap.flags |= RWNX_AP_ISOLATE; ++ else ++ rwnx_vif->ap.flags &= ~RWNX_AP_ISOLATE; ++ ++ res = 0; ++ } ++ ++ return res; ++} ++ ++static int rwnx_fill_station_info(struct rwnx_sta *sta, struct rwnx_vif *vif, ++ struct station_info *sinfo) ++{ ++ struct rwnx_sta_stats *stats = &sta->stats; ++ struct rx_vector_1 *rx_vect1 = &stats->last_rx.rx_vect1; ++ union rwnx_rate_ctrl_info *rate_info; ++ struct mm_get_sta_info_cfm cfm; ++ ++ rwnx_send_get_sta_info_req(vif->rwnx_hw, sta->sta_idx, &cfm); ++ sinfo->tx_failed = cfm.txfailed; ++ rate_info = (union rwnx_rate_ctrl_info *)&cfm.rate_info; ++ ++ AICWFDBG(LOGDEBUG, "%s ModTx(%d):%d TxIndex:%d ModRx(%d):%d RxHTIndex:%d RxVHTIndex:%d RxHEIndex:%d RSSI:%d \r\n", __func__, ++ rate_info->bwTx, ++ rate_info->formatModTx, ++ rate_info->mcsIndexTx, ++ rx_vect1->ch_bw, ++ rx_vect1->format_mod, ++ rx_vect1->ht.mcs, ++ rx_vect1->vht.mcs, ++ rx_vect1->he.mcs, ++ (s8)cfm.rssi); ++ ++ ++ ++ switch (rate_info->formatModTx) { ++ case FORMATMOD_NON_HT: ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ sinfo->txrate.flags = 0; ++ sinfo->txrate.legacy = tx_legrates_lut_rate[rate_info->mcsIndexTx]; ++ sinfo->txrate.nss = 1; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx & 0x7; ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 3) & 0x7) + 1; ++ if (rate_info->giAndPreTypeTx) ++ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ break; ++ case FORMATMOD_VHT: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx & 0xF; ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 4) & 0x7) + 1; ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_HE_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx & 0xF; ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 4) & 0x7) + 1; ++ break; ++#else ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ sinfo->txrate.mcs = ((rate_info->mcsIndexTx & 0xF) > 9 ? 9 : (rate_info->mcsIndexTx & 0xF)); ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 4) & 0x7) + 1; ++ break; ++#endif ++ default: ++ return -EINVAL; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ switch (rate_info->bwTx) { ++ case PHY_CHNL_BW_20: ++ sinfo->txrate.bw = RATE_INFO_BW_20; ++ break; ++ case PHY_CHNL_BW_40: ++ sinfo->txrate.bw = RATE_INFO_BW_40; ++ break; ++ case PHY_CHNL_BW_80: ++ sinfo->txrate.bw = RATE_INFO_BW_80; ++ break; ++ case PHY_CHNL_BW_160: ++ sinfo->txrate.bw = RATE_INFO_BW_160; ++ break; ++ default: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ sinfo->txrate.bw = RATE_INFO_BW_HE_RU; ++#else ++ sinfo->txrate.bw = RATE_INFO_BW_20; ++#endif ++ break; ++ } ++#endif ++ ++ sinfo->filled |= (BIT(NL80211_STA_INFO_TX_BITRATE) | BIT(NL80211_STA_INFO_TX_FAILED)); ++ ++ sinfo->inactive_time = jiffies_to_msecs(jiffies - vif->rwnx_hw->stats.last_tx); ++ sinfo->rx_bytes = vif->net_stats.rx_bytes; ++ sinfo->tx_bytes = vif->net_stats.tx_bytes; ++ sinfo->tx_packets = vif->net_stats.tx_packets; ++ sinfo->rx_packets = vif->net_stats.rx_packets; ++ sinfo->signal = (s8)cfm.rssi; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ switch (rx_vect1->ch_bw) { ++ case PHY_CHNL_BW_20: ++ sinfo->rxrate.bw = RATE_INFO_BW_20; ++ break; ++ case PHY_CHNL_BW_40: ++ sinfo->rxrate.bw = RATE_INFO_BW_40; ++ break; ++ case PHY_CHNL_BW_80: ++ sinfo->rxrate.bw = RATE_INFO_BW_80; ++ break; ++ case PHY_CHNL_BW_160: ++ sinfo->rxrate.bw = RATE_INFO_BW_160; ++ break; ++ default: ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ sinfo->rxrate.bw = RATE_INFO_BW_HE_RU; ++ #else ++ sinfo->rxrate.bw = RATE_INFO_BW_20; ++ #endif ++ break; ++ } ++ #endif ++ ++ switch (rx_vect1->format_mod) { ++ case FORMATMOD_NON_HT: ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ sinfo->rxrate.flags = 0; ++ sinfo->rxrate.legacy = legrates_lut[rx_vect1->leg_rate].rate; ++ sinfo->rxrate.nss = 1; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS; ++ if (rx_vect1->ht.short_gi) ++ sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ sinfo->rxrate.mcs = rx_vect1->ht.mcs; ++ sinfo->rxrate.nss = rx_vect1->ht.num_extn_ss + 1; ++ break; ++ case FORMATMOD_VHT: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ if (rx_vect1->vht.short_gi) ++ sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ sinfo->rxrate.mcs = rx_vect1->vht.mcs; ++ sinfo->rxrate.nss = rx_vect1->vht.nss + 1; ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ case FORMATMOD_HE_MU: ++ sinfo->rxrate.he_ru_alloc = rx_vect1->he.ru_size; ++ __attribute__((__fallthrough__)); ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_HE_MCS; ++ sinfo->rxrate.mcs = rx_vect1->he.mcs; ++ sinfo->rxrate.he_gi = rx_vect1->he.gi_type; ++ sinfo->rxrate.he_dcm = rx_vect1->he.dcm; ++ sinfo->rxrate.nss = rx_vect1->he.nss + 1; ++ break; ++#else ++ //kernel not support he ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ if(rx_vect1->he.mcs > 9){ ++ sinfo->rxrate.mcs = 9; ++ }else{ ++ sinfo->rxrate.mcs = rx_vect1->he.mcs; ++ } ++ sinfo->rxrate.mcs = (rx_vect1->he.mcs > 9 ? 9 : rx_vect1->he.mcs); ++ sinfo->rxrate.nss = rx_vect1->he.nss + 1; ++ break; ++#endif ++ default: ++ return -EINVAL; ++ } ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ sinfo->filled |= (STATION_INFO_INACTIVE_TIME | ++ STATION_INFO_RX_BYTES64 | ++ STATION_INFO_TX_BYTES64 | ++ STATION_INFO_RX_PACKETS | ++ STATION_INFO_TX_PACKETS | ++ STATION_INFO_SIGNAL | ++ STATION_INFO_RX_BITRATE); ++#else ++ sinfo->filled |= (BIT(NL80211_STA_INFO_INACTIVE_TIME) | ++ BIT(NL80211_STA_INFO_RX_BYTES64) | ++ BIT(NL80211_STA_INFO_TX_BYTES64) | ++ BIT(NL80211_STA_INFO_RX_PACKETS) | ++ BIT(NL80211_STA_INFO_TX_PACKETS) | ++ BIT(NL80211_STA_INFO_SIGNAL) | ++ BIT(NL80211_STA_INFO_RX_BITRATE)); ++#endif ++ ++ return 0; ++} ++ ++ ++/** ++ * @get_station: get station information for the station identified by @mac ++ */ ++static int rwnx_cfg80211_get_station(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac, ++#else ++ const u8 *mac, ++#endif ++ struct station_info *sinfo) ++{ ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_sta *sta = NULL; ++ ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR) ++ return -EINVAL; ++ else if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_STATION) || ++ (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_CLIENT)) { ++ if (vif->sta.ap && ether_addr_equal(vif->sta.ap->mac_addr, mac)) ++ sta = vif->sta.ap; ++ } else { ++ struct rwnx_sta *sta_iter; ++ spin_lock_bh(&vif->rwnx_hw->cb_lock); ++ list_for_each_entry(sta_iter, &vif->ap.sta_list, list) { ++ if (sta_iter->valid && ether_addr_equal(sta_iter->mac_addr, mac)) { ++ sta = sta_iter; ++ break; ++ } ++ } ++ spin_unlock_bh(&vif->rwnx_hw->cb_lock); ++ } ++ ++ if (sta) ++ return rwnx_fill_station_info(sta, vif, sinfo); ++ ++ return -ENOENT; ++} ++ ++ ++/** ++ * @dump_station: dump station callback -- resume dump at index @idx ++ */ ++static int rwnx_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, ++ int idx, u8 *mac, struct station_info *sinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ //struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_sta *sta_iter, *sta = NULL; ++ //struct mesh_peer_info_cfm peer_info_cfm; ++ int i = 0; ++ ++#if 0 ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++#endif ++ ++ list_for_each_entry(sta_iter, &rwnx_vif->ap.sta_list, list) { ++ if (i < idx) { ++ i++; ++ continue; ++ } ++ ++ sta = sta_iter; ++ break; ++ } ++ ++ if (sta == NULL) ++ return -ENOENT; ++ ++ /* Copy peer MAC address */ ++ memcpy(mac, &sta->mac_addr, ETH_ALEN); ++ ++ ++#if 0 ++ /* Forward the information to the UMAC */ ++ if (rwnx_send_mesh_peer_info_req(rwnx_hw, rwnx_vif, sta->sta_idx, ++ &peer_info_cfm)) ++ return -ENOMEM; ++ ++ /* Copy peer MAC address */ ++ memcpy(mac, &sta->mac_addr, ETH_ALEN); ++ ++ /* Fill station information */ ++ sinfo->llid = peer_info_cfm.local_link_id; ++ sinfo->plid = peer_info_cfm.peer_link_id; ++ sinfo->plink_state = peer_info_cfm.link_state; ++ sinfo->local_pm = peer_info_cfm.local_ps_mode; ++ sinfo->peer_pm = peer_info_cfm.peer_ps_mode; ++ sinfo->nonpeer_pm = peer_info_cfm.non_peer_ps_mode; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ sinfo->filled = (STATION_INFO_LLID | ++ STATION_INFO_PLID | ++ STATION_INFO_PLINK_STATE | ++ STATION_INFO_LOCAL_PM | ++ STATION_INFO_PEER_PM | ++ STATION_INFO_NONPEER_PM); ++#else ++ sinfo->filled = (BIT(NL80211_STA_INFO_LLID) | ++ BIT(NL80211_STA_INFO_PLID) | ++ BIT(NL80211_STA_INFO_PLINK_STATE) | ++ BIT(NL80211_STA_INFO_LOCAL_PM) | ++ BIT(NL80211_STA_INFO_PEER_PM) | ++ BIT(NL80211_STA_INFO_NONPEER_PM)); ++#endif ++#endif ++ ++ if (sta){ ++ rwnx_fill_station_info(sta, rwnx_vif, sinfo); ++ } ++ ++ return 0; ++} ++ ++/** ++ * @add_mpath: add a fixed mesh path ++ */ ++static int rwnx_cfg80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *dst, ++ u8 *next_hop ++#else ++ const u8 *dst, ++ const u8 *next_hop ++#endif ++) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_path_update_cfm cfm; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return rwnx_send_mesh_path_update_req(rwnx_hw, rwnx_vif, dst, next_hop, &cfm); ++} ++ ++/** ++ * @del_mpath: delete a given mesh path ++ */ ++static int rwnx_cfg80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *dst ++#else ++ const u8 *dst ++#endif ++) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_path_update_cfm cfm; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return rwnx_send_mesh_path_update_req(rwnx_hw, rwnx_vif, dst, NULL, &cfm); ++} ++ ++/** ++ * @change_mpath: change a given mesh path ++ */ ++static int rwnx_cfg80211_change_mpath(struct wiphy *wiphy, struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *dst, ++ u8 *next_hop ++#else ++ const u8 *dst, ++ const u8 *next_hop ++#endif ++) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_path_update_cfm cfm; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return rwnx_send_mesh_path_update_req(rwnx_hw, rwnx_vif, dst, next_hop, &cfm); ++} ++ ++/** ++ * @get_mpath: get a mesh path for the given parameters ++ */ ++static int rwnx_cfg80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, ++ u8 *dst, u8 *next_hop, struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_path *mesh_path = NULL; ++ struct rwnx_mesh_path *cur; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.mpath_list, list) { ++ /* Compare the path target address and the provided destination address */ ++ if (memcmp(dst, &cur->tgt_mac_addr, ETH_ALEN)) { ++ continue; ++ } ++ ++ mesh_path = cur; ++ break; ++ } ++ ++ if (mesh_path == NULL) ++ return -ENOENT; ++ ++ /* Copy next HOP MAC address */ ++ if (mesh_path->p_nhop_sta) ++ memcpy(next_hop, &mesh_path->p_nhop_sta->mac_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++ ++/** ++ * @dump_mpath: dump mesh path callback -- resume dump at index @idx ++ */ ++static int rwnx_cfg80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, ++ int idx, u8 *dst, u8 *next_hop, ++ struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_path *mesh_path = NULL; ++ struct rwnx_mesh_path *cur; ++ int i = 0; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.mpath_list, list) { ++ if (i < idx) { ++ i++; ++ continue; ++ } ++ ++ mesh_path = cur; ++ break; ++ } ++ ++ if (mesh_path == NULL) ++ return -ENOENT; ++ ++ /* Copy target and next hop MAC address */ ++ memcpy(dst, &mesh_path->tgt_mac_addr, ETH_ALEN); ++ if (mesh_path->p_nhop_sta) ++ memcpy(next_hop, &mesh_path->p_nhop_sta->mac_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++/** ++ * @get_mpp: get a mesh proxy path for the given parameters ++ */ ++static int rwnx_cfg80211_get_mpp(struct wiphy *wiphy, struct net_device *dev, ++ u8 *dst, u8 *mpp, struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_proxy *mesh_proxy = NULL; ++ struct rwnx_mesh_proxy *cur; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.proxy_list, list) { ++ if (cur->local) { ++ continue; ++ } ++ ++ /* Compare the path target address and the provided destination address */ ++ if (memcmp(dst, &cur->ext_sta_addr, ETH_ALEN)) { ++ continue; ++ } ++ ++ mesh_proxy = cur; ++ break; ++ } ++ ++ if (mesh_proxy == NULL) ++ return -ENOENT; ++ ++ memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++ ++/** ++ * @dump_mpp: dump mesh proxy path callback -- resume dump at index @idx ++ */ ++static int rwnx_cfg80211_dump_mpp(struct wiphy *wiphy, struct net_device *dev, ++ int idx, u8 *dst, u8 *mpp, struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_proxy *mesh_proxy = NULL; ++ struct rwnx_mesh_proxy *cur; ++ int i = 0; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.proxy_list, list) { ++ if (cur->local) { ++ continue; ++ } ++ ++ if (i < idx) { ++ i++; ++ continue; ++ } ++ ++ mesh_proxy = cur; ++ break; ++ } ++ ++ if (mesh_proxy == NULL) ++ return -ENOENT; ++ ++ /* Copy target MAC address */ ++ memcpy(dst, &mesh_proxy->ext_sta_addr, ETH_ALEN); ++ memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++#endif /* version >= 3.19 */ ++ ++/** ++ * @get_mesh_config: Get the current mesh configuration ++ */ ++static int rwnx_cfg80211_get_mesh_config(struct wiphy *wiphy, struct net_device *dev, ++ struct mesh_config *conf) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return 0; ++} ++ ++/** ++ * @update_mesh_config: Update mesh parameters on a running mesh. ++ */ ++static int rwnx_cfg80211_update_mesh_config(struct wiphy *wiphy, struct net_device *dev, ++ u32 mask, const struct mesh_config *nconf) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_update_cfm cfm; ++ int status; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ if (mask & CO_BIT(NL80211_MESHCONF_POWER_MODE - 1)) { ++ rwnx_vif->ap.next_mesh_pm = nconf->power_mode; ++ ++ if (!list_empty(&rwnx_vif->ap.sta_list)) { ++ // If there are mesh links we don't want to update the power mode ++ // It will be updated with rwnx_update_mesh_power_mode() when the ++ // ps mode of a link is updated or when a new link is added/removed ++ mask &= ~BIT(NL80211_MESHCONF_POWER_MODE - 1); ++ ++ if (!mask) ++ return 0; ++ } ++ } ++ ++ status = rwnx_send_mesh_update_req(rwnx_hw, rwnx_vif, mask, nconf, &cfm); ++ ++ if (!status && (cfm.status != 0)) ++ status = -EINVAL; ++ ++ return status; ++} ++ ++/** ++ * @join_mesh: join the mesh network with the specified parameters ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, ++ const struct mesh_config *conf, const struct mesh_setup *setup) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct mesh_start_cfm mesh_start_cfm; ++ int error = 0; ++ u8 txq_status = 0; ++ /* STA for BC/MC traffic */ ++ struct rwnx_sta *sta; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ /* Forward the information to the UMAC */ ++ error = rwnx_send_mesh_start_req(rwnx_hw, rwnx_vif, conf, setup, &mesh_start_cfm); ++ if (error) { ++ return error; ++ } ++ ++ /* Check the status */ ++ switch (mesh_start_cfm.status) { ++ case CO_OK: ++ rwnx_vif->ap.bcmc_index = mesh_start_cfm.bcmc_idx; ++ rwnx_vif->ap.flags = 0; ++ rwnx_vif->use_4addr = true; ++ rwnx_vif->user_mpm = setup->user_mpm; ++ ++ sta = &rwnx_hw->sta_table[mesh_start_cfm.bcmc_idx]; ++ sta->valid = true; ++ sta->aid = 0; ++ sta->sta_idx = mesh_start_cfm.bcmc_idx; ++ sta->ch_idx = mesh_start_cfm.ch_idx; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->qos = true; ++ sta->acm = 0; ++ sta->ps.active = false; ++ rwnx_mu_group_sta_init(sta, NULL); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_link(rwnx_vif, mesh_start_cfm.ch_idx, ++ (struct cfg80211_chan_def *)(&setup->chandef)); ++ if (rwnx_hw->cur_chanctx != mesh_start_cfm.ch_idx) { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ rwnx_txq_vif_init(rwnx_hw, rwnx_vif, txq_status); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ ++ /* If the AP channel is already the active, we probably skip radar ++ activation on MM_CHANNEL_SWITCH_IND (unless another vif use this ++ ctxt). In anycase retest if radar detection must be activated ++ */ ++ if (rwnx_hw->cur_chanctx == mesh_start_cfm.ch_idx) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ } ++ break; ++ ++ case CO_BUSY: ++ error = -EINPROGRESS; ++ break; ++ ++ default: ++ error = -EIO; ++ break; ++ } ++ ++ /* Print information about the operation */ ++ if (error) { ++ netdev_info(dev, "Failed to start MP (%d)", error); ++ } else { ++ netdev_info(dev, "MP started: ch=%d, bcmc_idx=%d", ++ rwnx_vif->ch_index, rwnx_vif->ap.bcmc_index); ++ } ++ ++ return error; ++} ++ ++/** ++ * @leave_mesh: leave the current mesh network ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct mesh_stop_cfm mesh_stop_cfm; ++ int error = 0; ++ ++ error = rwnx_send_mesh_stop_req(rwnx_hw, rwnx_vif, &mesh_stop_cfm); ++ ++ if (error == 0) { ++ /* Check the status */ ++ switch (mesh_stop_cfm.status) { ++ case CO_OK: ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_unlink(rwnx_vif); ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ /* delete BC/MC STA */ ++ rwnx_txq_vif_deinit(rwnx_hw, rwnx_vif); ++ rwnx_del_bcn(&rwnx_vif->ap.bcn); ++ ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ ++ break; ++ ++ default: ++ error = -EIO; ++ break; ++ } ++ } ++ ++ if (error) { ++ netdev_info(dev, "Failed to stop MP"); ++ } else { ++ netdev_info(dev, "MP Stopped"); ++ } ++ ++ return 0; ++} ++ ++static struct cfg80211_ops rwnx_cfg80211_ops = { ++ .add_virtual_intf = rwnx_cfg80211_add_iface, ++ .del_virtual_intf = rwnx_cfg80211_del_iface, ++ .change_virtual_intf = rwnx_cfg80211_change_iface, ++ .start_p2p_device = rwnx_cfgp2p_start_p2p_device, ++ .stop_p2p_device = rwnx_cfgp2p_stop_p2p_device, ++ .scan = rwnx_cfg80211_scan, ++ .connect = rwnx_cfg80211_connect, ++ .disconnect = rwnx_cfg80211_disconnect, ++ .add_key = rwnx_cfg80211_add_key, ++ .get_key = rwnx_cfg80211_get_key, ++ .del_key = rwnx_cfg80211_del_key, ++ .set_default_key = rwnx_cfg80211_set_default_key, ++ .set_default_mgmt_key = rwnx_cfg80211_set_default_mgmt_key, ++ .add_station = rwnx_cfg80211_add_station, ++ .del_station = rwnx_cfg80211_del_station_compat, ++ .change_station = rwnx_cfg80211_change_station, ++ .mgmt_tx = rwnx_cfg80211_mgmt_tx, ++ .start_ap = rwnx_cfg80211_start_ap, ++ .change_beacon = rwnx_cfg80211_change_beacon, ++ .stop_ap = rwnx_cfg80211_stop_ap, ++ .set_monitor_channel = rwnx_cfg80211_set_monitor_channel, ++ .probe_client = rwnx_cfg80211_probe_client, ++// .mgmt_frame_register = rwnx_cfg80211_mgmt_frame_register, ++ .set_wiphy_params = rwnx_cfg80211_set_wiphy_params, ++ .set_txq_params = rwnx_cfg80211_set_txq_params, ++ .set_tx_power = rwnx_cfg80211_set_tx_power, ++ .get_tx_power = rwnx_cfg80211_get_tx_power, ++ .set_power_mgmt = rwnx_cfg80211_set_power_mgmt, ++ .get_station = rwnx_cfg80211_get_station, ++ .remain_on_channel = rwnx_cfg80211_remain_on_channel, ++ .cancel_remain_on_channel = rwnx_cfg80211_cancel_remain_on_channel, ++ .dump_survey = rwnx_cfg80211_dump_survey, ++ .get_channel = rwnx_cfg80211_get_channel, ++ .start_radar_detection = rwnx_cfg80211_start_radar_detection, ++ .update_ft_ies = rwnx_cfg80211_update_ft_ies, ++ .set_cqm_rssi_config = rwnx_cfg80211_set_cqm_rssi_config, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ .channel_switch = rwnx_cfg80211_channel_switch, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ .tdls_channel_switch = rwnx_cfg80211_tdls_channel_switch, ++ .tdls_cancel_channel_switch = rwnx_cfg80211_tdls_cancel_channel_switch, ++#endif ++ .tdls_mgmt = rwnx_cfg80211_tdls_mgmt, ++ .tdls_oper = rwnx_cfg80211_tdls_oper, ++ .change_bss = rwnx_cfg80211_change_bss, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ .external_auth = rwnx_cfg80211_external_auth, ++#endif ++#ifdef CONFIG_SCHED_SCAN ++ .sched_scan_start = rwnx_cfg80211_sched_scan_start, ++ .sched_scan_stop = rwnx_cfg80211_sched_scan_stop, ++#endif ++}; ++ ++ ++/********************************************************************* ++ * Init/Exit functions ++ *********************************************************************/ ++static void rwnx_wdev_unregister(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_vif *rwnx_vif, *tmp; ++ ++ rtnl_lock(); ++ list_for_each_entry_safe(rwnx_vif, tmp, &rwnx_hw->vifs, list) { ++ rwnx_cfg80211_del_iface(rwnx_hw->wiphy, &rwnx_vif->wdev); ++ } ++ rtnl_unlock(); ++} ++ ++static void rwnx_set_vers(struct rwnx_hw *rwnx_hw) ++{ ++ u32 vers = rwnx_hw->version_cfm.version_lmac; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ snprintf(rwnx_hw->wiphy->fw_version, ++ sizeof(rwnx_hw->wiphy->fw_version), "%d.%d.%d.%d", ++ (vers & (0xff << 24)) >> 24, (vers & (0xff << 16)) >> 16, ++ (vers & (0xff << 8)) >> 8, (vers & (0xff << 0)) >> 0); ++} ++ ++static void rwnx_reg_notifier(struct wiphy *wiphy, ++ struct regulatory_request *request) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ // For now trust all initiator ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ if(request->dfs_region != 0) ++ rwnx_radar_set_domain(&rwnx_hw->radar, request->dfs_region); ++#else ++ rwnx_radar_set_domain(&rwnx_hw->radar, request->dfs_region); ++#endif ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC|| ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) && testmode == 0)){ ++ rwnx_send_me_chan_config_req(rwnx_hw, &request->alpha2[0]); ++ } ++} ++ ++static void rwnx_enable_mesh(struct rwnx_hw *rwnx_hw) ++{ ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ ++ if (!rwnx_mod_params.mesh) ++ return; ++ ++ rwnx_cfg80211_ops.get_station = rwnx_cfg80211_get_station; ++ rwnx_cfg80211_ops.dump_station = rwnx_cfg80211_dump_station; ++ rwnx_cfg80211_ops.add_mpath = rwnx_cfg80211_add_mpath; ++ rwnx_cfg80211_ops.del_mpath = rwnx_cfg80211_del_mpath; ++ rwnx_cfg80211_ops.change_mpath = rwnx_cfg80211_change_mpath; ++ rwnx_cfg80211_ops.get_mpath = rwnx_cfg80211_get_mpath; ++ rwnx_cfg80211_ops.dump_mpath = rwnx_cfg80211_dump_mpath; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ rwnx_cfg80211_ops.get_mpp = rwnx_cfg80211_get_mpp; ++ rwnx_cfg80211_ops.dump_mpp = rwnx_cfg80211_dump_mpp; ++#endif ++ rwnx_cfg80211_ops.get_mesh_config = rwnx_cfg80211_get_mesh_config; ++ rwnx_cfg80211_ops.update_mesh_config = rwnx_cfg80211_update_mesh_config; ++ rwnx_cfg80211_ops.join_mesh = rwnx_cfg80211_join_mesh; ++ rwnx_cfg80211_ops.leave_mesh = rwnx_cfg80211_leave_mesh; ++ ++ wiphy->flags |= (WIPHY_FLAG_MESH_AUTH | WIPHY_FLAG_IBSS_RSN); ++ wiphy->features |= NL80211_FEATURE_USERSPACE_MPM; ++ wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT); ++ ++ rwnx_limits[0].types |= BIT(NL80211_IFTYPE_MESH_POINT); ++ rwnx_limits_dfs[0].types |= BIT(NL80211_IFTYPE_MESH_POINT); ++} ++ ++extern int rwnx_init_aic(struct rwnx_hw *rwnx_hw); ++ ++#if IS_ENABLED(CONFIG_SUNXI_ADDR_MGT) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++extern int get_custom_mac_address(int fmt, char *name, char *addr); ++#else ++extern int get_wifi_custom_mac_address(char *addr_str); ++#endif ++#endif ++#if IS_ENABLED(CONFIG_PM) ++static const struct wiphy_wowlan_support aic_wowlan_support = { ++ .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT, ++}; ++#endif ++/** ++ * ++ */ ++extern int aicwf_vendor_init(struct wiphy *wiphy); ++extern txpwr_idx_conf_t nvram_txpwr_idx; ++ ++ ++int rwnx_ic_system_init(struct rwnx_hw *rwnx_hw){ ++ u32 mem_addr; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ ++ mem_addr = 0x40500000; ++ ++// if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++// rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ if (rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &rd_mem_addr_cfm)){ ++ return -1; ++ } ++ ++ chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16); ++ ++ if (rwnx_send_dbg_mem_read_req(rwnx_hw, 0x00000020, &rd_mem_addr_cfm)) { ++ AICWFDBG(LOGERROR, "[0x00000020] rd fail\n"); ++ return -1; ++ } ++ chip_sub_id = (u8)(rd_mem_addr_cfm.memdata); ++ ++ AICWFDBG(LOGINFO, "FDRV chip_id=%x, chip_sub_id=%x!!\n", chip_id, chip_sub_id); ++ ++#ifdef CONFIG_OOB ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ u32 memdata_temp = 0x00000006; ++ int ret; ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, 0x40504084, 4, &memdata_temp); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x40504084] write fail: %d\n", ret); ++ return -1; ++ } ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40504084, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x40504084] rd fail\n"); ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "rd [0x40504084] = %x\n", rd_mem_addr_cfm.memdata); ++ } ++#endif ++ ++ if (rwnx_platform_on(rwnx_hw, NULL)) ++ return -1; ++#if defined(CONFIG_START_FROM_BOOTROM) ++ //if (start_from_bootrom(rwnx_hw)) ++ // return -1; ++#endif ++// } ++ return 0; ++} ++ ++int rwnx_ic_rf_init(struct rwnx_hw *rwnx_hw){ ++ struct mm_set_rf_calib_cfm cfm; ++ int ret = 0; ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ if ((ret = rwnx_send_txpwr_idx_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if (testmode == 0) { ++ if ((ret = rwnx_send_rf_calib_req(rwnx_hw, &cfm))) ++ return -1; ++ } ++ ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ ++ if ((ret = aicwf_set_rf_config_8800dc(rwnx_hw, &cfm))) ++ return -1; ++ ++ ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if ((ret = aicwf_set_rf_config_8800d80(rwnx_hw, &cfm))) ++ return -1; ++ } ++ return 0; ++} ++ ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#ifdef CONFIG_USE_CUSTOMER_MAC ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++extern int get_custom_mac_address(int fmt, char *name, char *addr); ++#else ++extern int get_wifi_custom_mac_address(char *addr_str); ++#endif ++#endif//CONFIG_USE_CUSTOMER_MAC ++#endif//CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#include ++#endif ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#include ++#endif ++ ++#ifdef CONFIG_USE_CUSTOMER_MAC ++int rwnx_get_custom_mac_addr(u8_l *mac_addr_efuse){ ++ int ret = 0; ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ ret = get_custom_mac_address(1, "wifi", mac_addr_efuse); ++#else ++ ret = get_wifi_custom_mac_address(addr_str); ++ if (ret >= 0) { ++ sscanf(addr_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &mac_addr_efuse[0], &mac_addr_efuse[1], &mac_addr_efuse[2], ++ &mac_addr_efuse[3], &mac_addr_efuse[4], &mac_addr_efuse[5]); ++ } ++#endif ++ ++#endif//CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ ret = rockchip_wifi_mac_addr(mac_addr_efuse); ++#endif//CONFIG_PLATFORM_ROCKCHIP ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ ret = rockchip_wifi_mac_addr(mac_addr_efuse); ++#endif//CONFIG_PLATFORM_ROCKCHIP ++ ++ if(ret == 0){ ++ AICWFDBG(LOGINFO, "%s %02x:%02x:%02x:%02x:%02x:%02x", __func__, ++ mac_addr_efuse[0], mac_addr_efuse[1], mac_addr_efuse[2], ++ mac_addr_efuse[3], mac_addr_efuse[4], mac_addr_efuse[5]); ++ } ++ ++ return ret; ++} ++#endif ++ ++#ifdef CONFIG_FOR_IPCAM ++void aic_ipc_setting(struct rwnx_vif *rwnx_vif){ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ uint32_t hw_edca = 1; ++ uint32_t hw_cca = 3; ++ int32_t param[14]; ++ int32_t cca[5]= {0x10, 0, 0, 0, 0}; ++ ++ param[0] = 0xFA522; param[1] = 0xFA522; param[2] = 0xFA522; param[3] = 0xFA522; ++ param[4] = rwnx_vif->vif_index; ++ param[5] = 0x1e; param[6] = 0; param[7] = 0; param[8] =0;param[9] = 0x2;param[10] = 0x2;param[11] = 0x7;param[12] = 0;param[13] = 1; ++ rwnx_send_vendor_hwconfig_req(rwnx_hw, hw_edca, param, NULL); ++ rwnx_send_vendor_hwconfig_req(rwnx_hw, hw_cca, cca, NULL); ++} ++#endif ++ ++extern void *aicwf_prealloc_txq_alloc(size_t size); ++#ifdef CONFIG_POWER_LIMIT ++extern char default_ccode[]; ++#endif ++int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data) ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct rwnx_conf_file init_conf; ++ int ret = 0; ++ struct wiphy *wiphy; ++ struct rwnx_vif *vif; ++ int i; ++ u8 dflt_mac[ETH_ALEN] = { 0x88, 0x00, 0x33, 0x77, 0x10, 0x99}; ++ u8 addr_str[20]; ++ //struct mm_set_rf_calib_cfm cfm; ++ struct mm_get_fw_version_cfm fw_version; ++ u8_l mac_addr_efuse[ETH_ALEN]; ++ struct aicbsp_feature_t feature; ++ struct mm_set_stack_start_cfm set_start_cfm; ++#ifdef CONFIG_TEMP_COMP ++ struct mm_set_vendor_swconfig_cfm swconfig_cfm; ++#endif ++ char fw_path[200]; ++ (void)addr_str; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ memset(fw_path, 0, 200); ++ aicbsp_get_feature(&feature, fw_path); ++ ++ get_random_bytes(&dflt_mac[4], 2); ++#ifdef CONFIG_POWER_LIMIT ++ memcpy(country_code, default_ccode, 4); ++#endif ++ ++ /* create a new wiphy for use with cfg80211 */ ++ AICWFDBG(LOGINFO, "%s sizeof(struct rwnx_hw):%d \r\n", __func__, (int)sizeof(struct rwnx_hw)); ++ wiphy = wiphy_new(&rwnx_cfg80211_ops, sizeof(struct rwnx_hw)); ++ ++ if (!wiphy) { ++ dev_err(rwnx_platform_get_dev(rwnx_plat), "Failed to create new wiphy\n"); ++ ret = -ENOMEM; ++ goto err_out; ++ } ++ ++ rwnx_hw = wiphy_priv(wiphy); ++ rwnx_hw->wiphy = wiphy; ++ rwnx_hw->plat = rwnx_plat; ++ rwnx_hw->dev = rwnx_platform_get_dev(rwnx_plat); ++#ifdef AICWF_SDIO_SUPPORT ++ rwnx_hw->sdiodev = rwnx_plat->sdiodev; ++ rwnx_plat->sdiodev->rwnx_hw = rwnx_hw; ++ rwnx_hw->cmd_mgr = &rwnx_plat->sdiodev->cmd_mgr; ++#else ++ rwnx_hw->usbdev = rwnx_plat->usbdev; ++ rwnx_plat->usbdev->rwnx_hw = rwnx_hw; ++ rwnx_hw->cmd_mgr = &rwnx_plat->usbdev->cmd_mgr; ++#endif ++ rwnx_hw->mod_params = &rwnx_mod_params; ++ rwnx_hw->tcp_pacing_shift = 7; ++ ++#ifdef CONFIG_SCHED_SCAN ++ rwnx_hw->is_sched_scan = false; ++#endif//CONFIG_SCHED_SCAN ++ ++ aicwf_wakeup_lock_init(rwnx_hw); ++ rwnx_init_aic(rwnx_hw); ++ /* set device pointer for wiphy */ ++ set_wiphy_dev(wiphy, rwnx_hw->dev); ++ ++ /* Create cache to allocate sw_txhdr */ ++ rwnx_hw->sw_txhdr_cache = KMEM_CACHE(rwnx_sw_txhdr, 0); ++ if (!rwnx_hw->sw_txhdr_cache) { ++ wiphy_err(wiphy, "Cannot allocate cache for sw TX header\n"); ++ ret = -ENOMEM; ++ goto err_cache; ++ } ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ tcp_ack_init(rwnx_hw); ++#endif ++ ++#if 0 ++ ret = rwnx_parse_configfile(rwnx_hw, RWNX_CONFIG_FW_NAME, &init_conf); ++ if (ret) { ++ wiphy_err(wiphy, "rwnx_parse_configfile failed\n"); ++ goto err_config; ++ } ++#else ++ memcpy(init_conf.mac_addr, dflt_mac, ETH_ALEN); ++#endif ++ ++ rwnx_hw->vif_started = 0; ++ rwnx_hw->monitor_vif = RWNX_INVALID_VIF; ++ rwnx_hw->adding_sta = false; ++ ++ rwnx_hw->scan_ie.addr = NULL; ++ ++ for (i = 0; i < NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; i++) ++ rwnx_hw->avail_idx_map |= BIT(i); ++ ++ rwnx_hwq_init(rwnx_hw); ++ ++#ifdef CONFIG_PREALLOC_TXQ ++ rwnx_hw->txq = (struct rwnx_txq*)aicwf_prealloc_txq_alloc(sizeof(struct rwnx_txq)*NX_NB_TXQ); ++#endif ++ ++ for (i = 0; i < NX_NB_TXQ; i++) { ++ rwnx_hw->txq[i].idx = TXQ_INACTIVE; ++ } ++ ++ rwnx_mu_group_init(rwnx_hw); ++ ++ /* Initialize RoC element pointer to NULL, indicate that RoC can be started */ ++ rwnx_hw->roc_elem = NULL; ++ /* Cookie can not be 0 */ ++ rwnx_hw->roc_cookie_cnt = 1; ++ ++ INIT_LIST_HEAD(&rwnx_hw->vifs); ++ INIT_LIST_HEAD(&rwnx_hw->defrag_list); ++ spin_lock_init(&rwnx_hw->defrag_lock); ++ mutex_init(&rwnx_hw->mutex); ++ mutex_init(&rwnx_hw->dbgdump_elem.mutex); ++ spin_lock_init(&rwnx_hw->tx_lock); ++ spin_lock_init(&rwnx_hw->cb_lock); ++ ++ INIT_WORK(&rwnx_hw->apmStalossWork, apm_staloss_work_process); ++ rwnx_hw->apmStaloss_wq = create_singlethread_workqueue("apmStaloss_wq"); ++ if (!rwnx_hw->apmStaloss_wq) { ++ txrx_err("insufficient memory to create apmStaloss workqueue.\n"); ++ goto err_cache; ++ } ++ ++ wiphy->mgmt_stypes = rwnx_default_mgmt_stypes; ++ rwnx_hw->fwlog_en = feature.fwlog_en; ++ ++ ++ //init ic system ++ if((ret = rwnx_ic_system_init(rwnx_hw))){ ++ goto err_lmac_reqs; ++ } ++ ++ //ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, feature.hwinfo < 0, feature.hwinfo, 0, &set_start_cfm); ++#ifdef USE_5G ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801) { ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, CO_BIT(5), 0, &set_start_cfm); ++ } ++#else ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801) { ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, 0, 0, &set_start_cfm); ++ } ++#endif ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, 0, 0, &set_start_cfm); ++ set_start_cfm.is_5g_support = false; ++ } else { ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, CO_BIT(5), 0, &set_start_cfm); ++ } ++ ++ if (ret) ++ goto err_lmac_reqs; ++ ++ AICWFDBG(LOGINFO, "is 5g support = %d, vendor_info = 0x%02X\n", set_start_cfm.is_5g_support, set_start_cfm.vendor_info); ++ rwnx_hw->band_5g_support = set_start_cfm.is_5g_support; ++ rwnx_hw->vendor_info = (feature.hwinfo < 0) ? set_start_cfm.vendor_info : feature.hwinfo; ++ ++ ret = rwnx_send_get_fw_version_req(rwnx_hw, &fw_version); ++ memcpy(wiphy->fw_version, fw_version.fw_version, fw_version.fw_version_len>32? 32 : fw_version.fw_version_len); ++ AICWFDBG(LOGINFO, "Firmware Version: %s\r\n", fw_version.fw_version); ++ ++ wiphy->bands[NL80211_BAND_2GHZ] = &rwnx_band_2GHz; ++ if (rwnx_hw->band_5g_support) ++ wiphy->bands[NL80211_BAND_5GHZ] = &rwnx_band_5GHz; ++ ++ wiphy->interface_modes = ++ BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_AP_VLAN) | ++ BIT(NL80211_IFTYPE_P2P_CLIENT) | ++ BIT(NL80211_IFTYPE_P2P_GO) | ++#ifndef CONFIG_USE_P2P0 ++ BIT(NL80211_IFTYPE_P2P_DEVICE) | ++#endif ++ BIT(NL80211_IFTYPE_MONITOR); ++ ++#if IS_ENABLED(CONFIG_PM) ++ /* Set WoWLAN flags */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) ++ wiphy->wowlan = &aic_wowlan_support; ++#else ++ wiphy->wowlan.flags = aic_wowlan_support.flags; ++#endif ++#endif ++ wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) ++ WIPHY_FLAG_HAS_CHANNEL_SWITCH | ++ #endif ++ WIPHY_FLAG_4ADDR_STATION | ++ WIPHY_FLAG_4ADDR_AP; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ wiphy->max_num_csa_counters = BCN_MAX_CSA_CPT; ++ #endif ++ ++ wiphy->max_remain_on_channel_duration = rwnx_hw->mod_params->roc_dur_max; ++ ++ wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN | ++ NL80211_FEATURE_SK_TX_STATUS | ++ NL80211_FEATURE_VIF_TXPOWER | ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) ++ NL80211_FEATURE_ACTIVE_MONITOR | ++ #endif ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | ++ #endif ++ 0; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ wiphy->features |= NL80211_FEATURE_SAE; ++#endif ++ ++ if (rwnx_mod_params.tdls) ++ /* TDLS support */ ++ wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH; ++ ++ wiphy->iface_combinations = rwnx_combinations; ++ /* -1 not to include combination with radar detection, will be re-added in ++ rwnx_handle_dynparams if supported */ ++ wiphy->n_iface_combinations = ARRAY_SIZE(rwnx_combinations) - 1; ++ wiphy->reg_notifier = rwnx_reg_notifier; ++ ++ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; ++ ++ rwnx_enable_wapi(rwnx_hw); ++ ++ wiphy->cipher_suites = cipher_suites; ++ wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites) - NB_RESERVED_CIPHER; ++ ++ rwnx_hw->ext_capa[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING; ++ rwnx_hw->ext_capa[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF; ++ ++ wiphy->extended_capabilities = rwnx_hw->ext_capa; ++ wiphy->extended_capabilities_mask = rwnx_hw->ext_capa; ++ wiphy->extended_capabilities_len = ARRAY_SIZE(rwnx_hw->ext_capa); ++ ++#ifdef CONFIG_SCHED_SCAN ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ wiphy->max_sched_scan_reqs = 1; ++#endif ++ wiphy->max_sched_scan_ssids = SCAN_SSID_MAX;//16; ++ wiphy->max_match_sets = SCAN_SSID_MAX;//16; ++ wiphy->max_sched_scan_ie_len = 2048; ++#endif//CONFIG_SCHED_SCAN ++ ++ tasklet_init(&rwnx_hw->task, rwnx_task, (unsigned long)rwnx_hw); ++ ++ //init ic rf ++ if((ret = rwnx_ic_rf_init(rwnx_hw))){ ++ goto err_lmac_reqs; ++ } ++ ++ ++#ifdef CONFIG_USE_CUSTOMER_MAC ++ ret = rwnx_get_custom_mac_addr(mac_addr_efuse); ++ if (ret){ ++ AICWFDBG(LOGERROR, "%s read mac fail use default mac\r\n", __func__); ++ memcpy(init_conf.mac_addr, dflt_mac, ETH_ALEN); ++ } ++#else ++ ret = rwnx_send_get_macaddr_req(rwnx_hw, (struct mm_get_mac_addr_cfm *)mac_addr_efuse); ++ if (ret) ++ goto err_lmac_reqs; ++#endif ++ ++ if (mac_addr_efuse[0] | mac_addr_efuse[1] | mac_addr_efuse[2] | mac_addr_efuse[3]) { ++ memcpy(init_conf.mac_addr, mac_addr_efuse, ETH_ALEN); ++ }else{ ++ memcpy(init_conf.mac_addr, dflt_mac, ETH_ALEN); ++ } ++ ++ ++ AICWFDBG(LOGINFO, "get macaddr: %02x:%02x:%02x:%02x:%02x:%02x\r\n", ++ mac_addr_efuse[0], mac_addr_efuse[1], mac_addr_efuse[2], ++ mac_addr_efuse[3], mac_addr_efuse[4], mac_addr_efuse[5]); ++ memcpy(wiphy->perm_addr, init_conf.mac_addr, ETH_ALEN); ++ ++ /* Reset FW */ ++ ret = rwnx_send_reset(rwnx_hw); ++ if (ret) ++ goto err_lmac_reqs; ++ ++#ifdef CONFIG_TEMP_COMP ++ rwnx_send_set_temp_comp_req(rwnx_hw, &swconfig_cfm); ++#endif ++ ++ ret = rwnx_send_version_req(rwnx_hw, &rwnx_hw->version_cfm); ++ if (ret) ++ goto err_lmac_reqs; ++ rwnx_set_vers(rwnx_hw); ++ ++ ret = rwnx_handle_dynparams(rwnx_hw, rwnx_hw->wiphy); ++ if (ret) ++ goto err_lmac_reqs; ++ ++ rwnx_enable_mesh(rwnx_hw); ++ rwnx_radar_detection_init(&rwnx_hw->radar); ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ rwnx_radar_set_domain(&rwnx_hw->radar, NL80211_DFS_FCC); ++#endif ++ ++ /* Set parameters to firmware */ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC|| ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) && testmode == 0)){ ++ rwnx_send_me_config_req(rwnx_hw); ++ } ++ ++ /* Only monitor mode supported when custom channels are enabled */ ++ if (rwnx_mod_params.custchan) { ++ rwnx_limits[0].types = BIT(NL80211_IFTYPE_MONITOR); ++ rwnx_limits_dfs[0].types = BIT(NL80211_IFTYPE_MONITOR); ++ } ++ ++ aicwf_vendor_init(wiphy); ++ ++ ret = wiphy_register(wiphy); ++ if (ret) { ++ wiphy_err(wiphy, "Could not register wiphy device\n"); ++ goto err_register_wiphy; ++ } ++ ++ /* Update regulatory (if needed) and set channel parameters to firmware ++ (must be done after WiPHY registration) */ ++ rwnx_custregd(rwnx_hw, wiphy); ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) && testmode == 0)) { ++ rwnx_send_me_chan_config_req(rwnx_hw, "00"); ++ } ++ ++ *platform_data = rwnx_hw; ++ ++#ifdef CONFIG_DEBUG_FS ++ ret = rwnx_dbgfs_register(rwnx_hw, "rwnx"); ++ if (ret) { ++ wiphy_err(wiphy, "Failed to register debugfs entries"); ++ goto err_debugfs; ++ } ++#endif ++ rtnl_lock(); ++ ++ /* Add an initial station interface */ ++ vif = rwnx_interface_add(rwnx_hw, "wlan%d", NET_NAME_UNKNOWN, ++ NL80211_IFTYPE_STATION, NULL); ++ ++#ifdef CONFIG_RWNX_MON_DATA ++ /* Add an initial station interface */ ++ vif = rwnx_interface_add(rwnx_hw, "wlan%d", 1, ++ NL80211_IFTYPE_MONITOR, NULL); ++#endif ++ ++ rtnl_unlock(); ++ ++ if (!vif) { ++ wiphy_err(wiphy, "Failed to instantiate a network device\n"); ++ ret = -ENOMEM; ++ goto err_add_interface; ++ } ++ ++ //wiphy_info(wiphy, "New interface create %s", vif->ndev->name); ++ AICWFDBG(LOGINFO, "New interface create %s \r\n", vif->ndev->name); ++ ++#ifdef CONFIG_SDIO_BT ++#if CONFIG_BLUEDROID ++ btchr_init(); ++ hdev_init(); ++#else ++ btsdio_init(); ++#endif ++#endif ++ ++#ifdef CONFIG_USE_P2P0 ++ ++ rtnl_lock(); ++ /* Add an initial p2p0 interface */ ++ vif = rwnx_interface_add(rwnx_hw, "p2p%d", NET_NAME_UNKNOWN, ++ NL80211_IFTYPE_STATION, NULL); ++ vif->is_p2p_vif = 1; ++ rtnl_unlock(); ++ ++ if (!vif) { ++ wiphy_err(wiphy, "Failed to instantiate a network device\n"); ++ ret = -ENOMEM; ++ goto err_add_interface; ++ } ++ ++ //wiphy_info(wiphy, "New interface create %s", vif->ndev->name); ++ AICWFDBG(LOGINFO, "New interface create %s \r\n", vif->ndev->name); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ init_timer(&rwnx_hw->p2p_alive_timer); ++ rwnx_hw->p2p_alive_timer.data = (unsigned long)vif; ++ rwnx_hw->p2p_alive_timer.function = aicwf_p2p_alive_timeout; ++#else ++ timer_setup(&rwnx_hw->p2p_alive_timer, aicwf_p2p_alive_timeout, 0); ++#endif ++ rwnx_hw->is_p2p_alive = 0; ++ rwnx_hw->is_p2p_connected = 0; ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ ++#ifdef CONFIG_FOR_IPCAM ++ if(!testmode && !adap_test) { ++ aic_ipc_setting(vif); ++ } ++#endif ++ ++ return 0; ++ ++err_add_interface: ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister(rwnx_hw); ++err_debugfs: ++#endif ++ wiphy_unregister(rwnx_hw->wiphy); ++err_register_wiphy: ++err_lmac_reqs: ++ printk("err_lmac_reqs\n"); ++ rwnx_platform_off(rwnx_hw, NULL); ++//err_platon: ++//err_config: ++ kmem_cache_destroy(rwnx_hw->sw_txhdr_cache); ++err_cache: ++ aicwf_wakeup_lock_deinit(rwnx_hw); ++ wiphy_free(wiphy); ++err_out: ++ return ret; ++} ++ ++/** ++ * ++ */ ++void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_stack_start_cfm set_start_cfm; ++ struct defrag_ctrl_info *defrag_ctrl = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef AICWF_USB_SUPPORT ++ if (rwnx_hw->usbdev->bus_if->state != BUS_DOWN_ST) ++#else ++ if (rwnx_hw->sdiodev->bus_if->state != BUS_DOWN_ST) ++#endif ++ rwnx_send_set_stack_start_req(rwnx_hw, 0, 0, 0, 0, &set_start_cfm); ++ ++ rwnx_hw->fwlog_en = 0; ++ spin_lock_bh(&rwnx_hw->defrag_lock); ++ if (!list_empty(&rwnx_hw->defrag_list)) { ++ list_for_each_entry(defrag_ctrl, &rwnx_hw->defrag_list, list) { ++ list_del_init(&defrag_ctrl->list); ++ if (timer_pending(&defrag_ctrl->defrag_timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&defrag_ctrl->defrag_timer); ++#else ++ del_timer_sync(&defrag_ctrl->defrag_timer); ++#endif ++ dev_kfree_skb(defrag_ctrl->skb); ++ kfree(defrag_ctrl); ++ } ++ } ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister(rwnx_hw); ++#endif ++ ++#ifdef CONFIG_SDIO_BT ++#if CONFIG_BLUEDROID ++ btchr_exit(); ++ hdev_exit(); ++#else ++ btsdio_remove(); ++#endif ++#endif ++ ++ flush_workqueue(rwnx_hw->apmStaloss_wq); ++ destroy_workqueue(rwnx_hw->apmStaloss_wq); ++ ++ rwnx_wdev_unregister(rwnx_hw); ++ wiphy_unregister(rwnx_hw->wiphy); ++ rwnx_radar_detection_deinit(&rwnx_hw->radar); ++ rwnx_platform_off(rwnx_hw, NULL); ++ kmem_cache_destroy(rwnx_hw->sw_txhdr_cache); ++#ifdef CONFIG_FILTER_TCP_ACK ++ tcp_ack_deinit(rwnx_hw); ++#endif ++ aicwf_wakeup_lock_deinit(rwnx_hw); ++ wiphy_free(rwnx_hw->wiphy); ++} ++ ++static void aicsmac_driver_register(void) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_register(); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ aicwf_usb_register(); ++#endif ++#ifdef AICWF_PCIE_SUPPORT ++ aicwf_pcie_register(); ++#endif ++} ++ ++//static DECLARE_WORK(aicsmac_driver_work, aicsmac_driver_register); ++ ++struct completion hostif_register_done; ++static int rwnx_driver_err = -1; ++ ++#define REGISTRATION_TIMEOUT 9000 ++ ++void aicwf_hostif_ready(void) ++{ ++ rwnx_driver_err = 0; ++ g_rwnx_plat->enabled = true; ++ complete(&hostif_register_done); ++} ++ ++void aicwf_hostif_fail(void) ++{ ++ rwnx_driver_err = 1; ++ complete(&hostif_register_done); ++} ++ ++static int __init rwnx_mod_init(void) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ rwnx_print_version(); ++ rwnx_init_cmd_array(); ++ ++//#ifndef CONFIG_PLATFORM_ROCKCHIP ++ if (aicbsp_set_subsys(AIC_WIFI, AIC_PWR_ON) < 0) { ++ AICWFDBG(LOGERROR, "%s, set power on fail!\n", __func__); ++ if(!aicbsp_get_load_fw_in_fdrv()){ ++ return -ENODEV; ++ } ++ } ++//#endif ++ ++ init_completion(&hostif_register_done); ++ aicsmac_driver_register(); ++ ++ if ((wait_for_completion_timeout(&hostif_register_done, msecs_to_jiffies(REGISTRATION_TIMEOUT)) == 0) || rwnx_driver_err) { ++ AICWFDBG(LOGERROR, "register_driver timeout or error\n"); ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_exit(); ++#endif /* AICWF_SDIO_SUPPORT */ ++#ifdef AICWF_USB_SUPPORT ++ aicwf_usb_exit(); ++#endif /*AICWF_USB_SUPPORT */ ++ aicbsp_set_subsys(AIC_WIFI, AIC_PWR_OFF); ++ return -ENODEV; ++ } ++ ++#ifdef AICWF_PCIE_SUPPORT ++ return rwnx_platform_register_drv(); ++#else ++ return 0; ++#endif ++} ++ ++/** ++ * ++ */ ++static void __exit rwnx_mod_exit(void) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef AICWF_PCIE_SUPPORT ++ rwnx_platform_unregister_drv(); ++#endif ++ ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_exit(); ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++ aicwf_usb_exit(); ++#endif ++//#ifndef CONFIG_PLATFORM_ROCKCHIP ++ aicbsp_set_subsys(AIC_WIFI, AIC_PWR_OFF); ++//#endif ++ rwnx_free_cmd_array(); ++ ++} ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) ++MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver"); ++#else ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#endif ++#endif ++ ++module_init(rwnx_mod_init); ++module_exit(rwnx_mod_exit); ++ ++MODULE_FIRMWARE(RWNX_CONFIG_FW_NAME); ++ ++MODULE_DESCRIPTION(RW_DRV_DESCRIPTION); ++MODULE_VERSION(RWNX_VERS_MOD); ++MODULE_AUTHOR(RW_DRV_COPYRIGHT " " RW_DRV_AUTHOR); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h +new file mode 100644 +index 000000000000..dfa89034706a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h +@@ -0,0 +1,26 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_main.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_MAIN_H_ ++#define _RWNX_MAIN_H_ ++ ++#include "rwnx_defs.h" ++ ++int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data); ++void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw); ++extern int testmode; ++extern u8 chip_sub_id; ++extern u8 chip_mcu_id; ++extern u8 chip_id; ++ ++#define CHIP_ID_H_MASK 0xC0 ++#define IS_CHIP_ID_H() ((chip_id & CHIP_ID_H_MASK) == CHIP_ID_H_MASK) ++ ++#endif /* _RWNX_MAIN_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c +new file mode 100644 +index 000000000000..8773db61a664 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c +@@ -0,0 +1,42 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_mesh.c ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++/** ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++ ++#include "rwnx_mesh.h" ++ ++/** ++ * FUNCTION DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local) ++{ ++ struct rwnx_mesh_proxy *p_mesh_proxy = NULL; ++ struct rwnx_mesh_proxy *p_cur_proxy; ++ ++ /* Look for proxied devices with provided address */ ++ list_for_each_entry(p_cur_proxy, &p_rwnx_vif->ap.proxy_list, list) { ++ if (p_cur_proxy->local != local) { ++ continue; ++ } ++ ++ if (!memcmp(&p_cur_proxy->ext_sta_addr, p_sta_addr, ETH_ALEN)) { ++ p_mesh_proxy = p_cur_proxy; ++ break; ++ } ++ } ++ ++ /* Return the found information */ ++ return p_mesh_proxy; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h +new file mode 100644 +index 000000000000..db8950f160de +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h +@@ -0,0 +1,45 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_mesh.h ++ * ++ * @brief VHT Beamformer function declarations ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_MESH_H_ ++#define _RWNX_MESH_H_ ++ ++/** ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++ ++/** ++ * DEFINES ++ **************************************************************************************** ++ */ ++ ++/** ++ * TYPE DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++/** ++ * FUNCTION DECLARATIONS ++ **************************************************************************************** ++ */ ++ ++/** ++ **************************************************************************************** ++ * @brief TODO [LT] ++ **************************************************************************************** ++ */ ++struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local); ++ ++#endif /* _RWNX_MESH_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c +new file mode 100644 +index 000000000000..965454201a8a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c +@@ -0,0 +1,1798 @@ ++/** ++****************************************************************************** ++* ++* @file rwnx_mod_params.c ++* ++* @brief Set configuration according to modules parameters ++* ++* Copyright (C) RivieraWaves 2012-2019 ++* ++****************************************************************************** ++*/ ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_tx.h" ++#include "hal_desc.h" ++#include "rwnx_cfgfile.h" ++#include "rwnx_dini.h" ++#include "reg_access.h" ++#include "rwnx_compat.h" ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define COMMON_PARAM(name, default_softmac, default_fullmac) \ ++ .name = default_fullmac, ++#define SOFTMAC_PARAM(name, default) ++#define FULLMAC_PARAM(name, default) .name = default, ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++struct rwnx_mod_params rwnx_mod_params = { ++ /* common parameters */ ++ COMMON_PARAM(ht_on, true, true) ++ COMMON_PARAM(vht_on, true, true) ++ COMMON_PARAM(he_on, true, true) ++ COMMON_PARAM(mcs_map, IEEE80211_VHT_MCS_SUPPORT_0_9, IEEE80211_VHT_MCS_SUPPORT_0_9) ++ COMMON_PARAM(he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_11, IEEE80211_HE_MCS_SUPPORT_0_11) ++ COMMON_PARAM(he_ul_on, false, false) ++ COMMON_PARAM(ldpc_on, true, true) ++ COMMON_PARAM(stbc_on, true, true) ++ COMMON_PARAM(gf_rx_on, false, false) ++ COMMON_PARAM(phy_cfg, 2, 2) ++ COMMON_PARAM(uapsd_timeout, 300, 300) ++ COMMON_PARAM(ap_uapsd_on, true, true) ++ COMMON_PARAM(sgi, true, true) ++ COMMON_PARAM(sgi80, false, false) ++ COMMON_PARAM(use_2040, 1, 1) ++ COMMON_PARAM(nss, 2, 2) ++ COMMON_PARAM(amsdu_rx_max, 1, 1) ++ COMMON_PARAM(bfmee, true, true) ++ COMMON_PARAM(bfmer, false, false) ++ COMMON_PARAM(mesh, true, true) ++ COMMON_PARAM(murx, true, true) ++ COMMON_PARAM(mutx, true, true) ++ COMMON_PARAM(mutx_on, true, true) ++ COMMON_PARAM(use_80, false, false) ++ COMMON_PARAM(custregd, true, true) ++ COMMON_PARAM(custchan, false, false) ++ COMMON_PARAM(roc_dur_max, 500, 500) ++ COMMON_PARAM(listen_itv, 0, 0) ++ COMMON_PARAM(listen_bcmc, true, true) ++ COMMON_PARAM(lp_clk_ppm, 20, 20) ++ COMMON_PARAM(ps_on, true, true) ++ COMMON_PARAM(tx_lft, RWNX_TX_LIFETIME_MS, RWNX_TX_LIFETIME_MS) ++ COMMON_PARAM(amsdu_maxnb, NX_TX_PAYLOAD_MAX, NX_TX_PAYLOAD_MAX) ++ // By default, only enable UAPSD for Voice queue (see IEEE80211_DEFAULT_UAPSD_QUEUE comment) ++ COMMON_PARAM(uapsd_queues, IEEE80211_WMM_IE_STA_QOSINFO_AC_VO, IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) ++ COMMON_PARAM(tdls, false, false) ++ COMMON_PARAM(uf, false, false) ++ COMMON_PARAM(auto_reply, false, false) ++ COMMON_PARAM(ftl, "", "") ++ COMMON_PARAM(dpsm, false, false) ++ ++ /* SOFTMAC only parameters */ ++ SOFTMAC_PARAM(mfp_on, false) ++ SOFTMAC_PARAM(gf_on, false) ++ SOFTMAC_PARAM(bwsig_on, true) ++ SOFTMAC_PARAM(dynbw_on, true) ++ SOFTMAC_PARAM(agg_tx, true) ++ SOFTMAC_PARAM(amsdu_force, 2) ++ SOFTMAC_PARAM(rc_probes_on, false) ++ SOFTMAC_PARAM(cmon, true) ++ SOFTMAC_PARAM(hwscan, true) ++ SOFTMAC_PARAM(autobcn, true) ++ SOFTMAC_PARAM(dpsm, true) ++ ++ /* FULLMAC only parameters */ ++ FULLMAC_PARAM(ant_div, true) ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/* FULLMAC specific parameters*/ ++module_param_named(ant_div, rwnx_mod_params.ant_div, bool, S_IRUGO); ++MODULE_PARM_DESC(ant_div, "Enable Antenna Diversity (Default: 1)"); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++module_param_named(ht_on, rwnx_mod_params.ht_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ht_on, "Enable HT (Default: 1)"); ++ ++module_param_named(vht_on, rwnx_mod_params.vht_on, bool, S_IRUGO); ++MODULE_PARM_DESC(vht_on, "Enable VHT (Default: 1)"); ++ ++module_param_named(he_on, rwnx_mod_params.he_on, bool, S_IRUGO); ++MODULE_PARM_DESC(he_on, "Enable HE (Default: 1)"); ++ ++module_param_named(mcs_map, rwnx_mod_params.mcs_map, int, S_IRUGO); ++MODULE_PARM_DESC(mcs_map, "VHT MCS map value 0: MCS0_7, 1: MCS0_8, 2: MCS0_9" ++ " (Default: 2)"); ++ ++module_param_named(he_mcs_map, rwnx_mod_params.he_mcs_map, int, S_IRUGO); ++MODULE_PARM_DESC(he_mcs_map, "HE MCS map value 0: MCS0_7, 1: MCS0_9, 2: MCS0_11" ++ " (Default: 2)"); ++ ++module_param_named(he_ul_on, rwnx_mod_params.he_ul_on, bool, S_IRUGO); ++MODULE_PARM_DESC(he_ul_on, "Enable HE OFDMA UL (Default: 0)"); ++ ++module_param_named(amsdu_maxnb, rwnx_mod_params.amsdu_maxnb, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(amsdu_maxnb, "Maximum number of MSDUs inside an A-MSDU in TX: (Default: NX_TX_PAYLOAD_MAX)"); ++ ++module_param_named(ps_on, rwnx_mod_params.ps_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ps_on, "Enable PowerSaving (Default: 1-Enabled)"); ++ ++module_param_named(tx_lft, rwnx_mod_params.tx_lft, int, 0644); ++MODULE_PARM_DESC(tx_lft, "Tx lifetime (ms) - setting it to 0 disables retries " ++ "(Default: "__stringify(RWNX_TX_LIFETIME_MS)")"); ++ ++module_param_named(ldpc_on, rwnx_mod_params.ldpc_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ldpc_on, "Enable LDPC (Default: 1)"); ++ ++module_param_named(stbc_on, rwnx_mod_params.stbc_on, bool, S_IRUGO); ++MODULE_PARM_DESC(stbc_on, "Enable STBC in RX (Default: 1)"); ++ ++module_param_named(gf_rx_on, rwnx_mod_params.gf_rx_on, bool, S_IRUGO); ++MODULE_PARM_DESC(gf_rx_on, "Enable HT greenfield in reception (Default: 1)"); ++ ++module_param_named(phycfg, rwnx_mod_params.phy_cfg, int, S_IRUGO); ++MODULE_PARM_DESC(phycfg, ++ "0 <= phycfg <= 5 : RF Channel Conf (Default: 2(C0-A1-B2))"); ++ ++module_param_named(uapsd_timeout, rwnx_mod_params.uapsd_timeout, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(uapsd_timeout, ++ "UAPSD Timer timeout, in ms (Default: 300). If 0, UAPSD is disabled"); ++ ++module_param_named(uapsd_queues, rwnx_mod_params.uapsd_queues, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(uapsd_queues, "UAPSD Queues, integer value, must be seen as a bitfield\n" ++ " Bit 0 = VO\n" ++ " Bit 1 = VI\n" ++ " Bit 2 = BK\n" ++ " Bit 3 = BE\n" ++ " -> uapsd_queues=7 will enable uapsd for VO, VI and BK queues"); ++ ++module_param_named(ap_uapsd_on, rwnx_mod_params.ap_uapsd_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ap_uapsd_on, "Enable UAPSD in AP mode (Default: 1)"); ++ ++module_param_named(sgi, rwnx_mod_params.sgi, bool, S_IRUGO); ++MODULE_PARM_DESC(sgi, "Advertise Short Guard Interval support (Default: 1)"); ++ ++module_param_named(sgi80, rwnx_mod_params.sgi80, bool, S_IRUGO); ++MODULE_PARM_DESC(sgi80, "Advertise Short Guard Interval support for 80MHz (Default: 1)"); ++ ++module_param_named(use_2040, rwnx_mod_params.use_2040, bool, S_IRUGO); ++MODULE_PARM_DESC(use_2040, "Use tweaked 20-40MHz mode (Default: 1)"); ++ ++module_param_named(use_80, rwnx_mod_params.use_80, bool, S_IRUGO); ++MODULE_PARM_DESC(use_80, "Enable 80MHz (Default: 1)"); ++ ++module_param_named(custregd, rwnx_mod_params.custregd, bool, S_IRUGO); ++MODULE_PARM_DESC(custregd, ++ "Use permissive custom regulatory rules (for testing ONLY) (Default: 0)"); ++ ++module_param_named(custchan, rwnx_mod_params.custchan, bool, S_IRUGO); ++MODULE_PARM_DESC(custchan, ++ "Extend channel set to non-standard channels (for testing ONLY) (Default: 0)"); ++ ++module_param_named(nss, rwnx_mod_params.nss, int, S_IRUGO); ++MODULE_PARM_DESC(nss, "1 <= nss <= 2 : Supported number of Spatial Streams (Default: 1)"); ++ ++module_param_named(amsdu_rx_max, rwnx_mod_params.amsdu_rx_max, int, S_IRUGO); ++MODULE_PARM_DESC(amsdu_rx_max, "0 <= amsdu_rx_max <= 2 : Maximum A-MSDU size supported in RX\n" ++ " 0: 3895 bytes\n" ++ " 1: 7991 bytes\n" ++ " 2: 11454 bytes\n" ++ " This value might be reduced according to the FW capabilities.\n" ++ " Default: 2"); ++ ++module_param_named(bfmee, rwnx_mod_params.bfmee, bool, S_IRUGO); ++MODULE_PARM_DESC(bfmee, "Enable Beamformee Capability (Default: 1-Enabled)"); ++ ++module_param_named(bfmer, rwnx_mod_params.bfmer, bool, S_IRUGO); ++MODULE_PARM_DESC(bfmer, "Enable Beamformer Capability (Default: 0-Disabled)"); ++ ++module_param_named(mesh, rwnx_mod_params.mesh, bool, S_IRUGO); ++MODULE_PARM_DESC(mesh, "Enable Meshing Capability (Default: 1-Enabled)"); ++ ++module_param_named(murx, rwnx_mod_params.murx, bool, S_IRUGO); ++MODULE_PARM_DESC(murx, "Enable MU-MIMO RX Capability (Default: 1-Enabled)"); ++ ++module_param_named(mutx, rwnx_mod_params.mutx, bool, S_IRUGO); ++MODULE_PARM_DESC(mutx, "Enable MU-MIMO TX Capability (Default: 1-Enabled)"); ++ ++module_param_named(mutx_on, rwnx_mod_params.mutx_on, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(mutx_on, "Enable MU-MIMO transmissions (Default: 1-Enabled)"); ++ ++module_param_named(roc_dur_max, rwnx_mod_params.roc_dur_max, int, S_IRUGO); ++MODULE_PARM_DESC(roc_dur_max, "Maximum Remain on Channel duration"); ++ ++module_param_named(listen_itv, rwnx_mod_params.listen_itv, int, S_IRUGO); ++MODULE_PARM_DESC(listen_itv, "Maximum listen interval"); ++ ++module_param_named(listen_bcmc, rwnx_mod_params.listen_bcmc, bool, S_IRUGO); ++MODULE_PARM_DESC(listen_bcmc, "Wait for BC/MC traffic following DTIM beacon"); ++ ++module_param_named(lp_clk_ppm, rwnx_mod_params.lp_clk_ppm, int, S_IRUGO); ++MODULE_PARM_DESC(lp_clk_ppm, "Low Power Clock accuracy of the local device"); ++ ++module_param_named(tdls, rwnx_mod_params.tdls, bool, S_IRUGO); ++MODULE_PARM_DESC(tdls, "Enable TDLS (Default: 1-Enabled)"); ++ ++module_param_named(uf, rwnx_mod_params.uf, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(uf, "Enable Unsupported HT Frame Logging (Default: 0-Disabled)"); ++ ++module_param_named(auto_reply, rwnx_mod_params.auto_reply, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(auto_reply, "Enable Monitor MacAddr Auto-Reply (Default: 0-Disabled)"); ++ ++module_param_named(ftl, rwnx_mod_params.ftl, charp, S_IRUGO); ++MODULE_PARM_DESC(ftl, "Firmware trace level (Default: \"\")"); ++ ++module_param_named(dpsm, rwnx_mod_params.dpsm, bool, S_IRUGO); ++MODULE_PARM_DESC(dpsm, "Enable Dynamic PowerSaving (Default: 1-Enabled)"); ++ ++ ++#ifdef DEFAULT_COUNTRY_CODE ++char default_ccode[4] = DEFAULT_COUNTRY_CODE; ++#else ++char default_ccode[4] = "00"; ++#endif ++ ++char country_code[4]; ++module_param_string(country_code, country_code, 4, 0600); ++ ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++/* Regulatory rules */ ++static struct ieee80211_regdomain rwnx_regdom = { ++ .n_reg_rules = 2, ++ .alpha2 = "99", ++ .reg_rules = { ++ REG_RULE(2390 - 10, 2510 + 10, 40, 0, 1000, 0), ++ REG_RULE(5150 - 10, 5970 + 10, 80, 0, 1000, 0), ++ } ++}; ++#endif ++#endif ++ ++static const int mcs_map_to_rate[4][3] = { ++ [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_7] = 65, ++ [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_8] = 78, ++ [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_9] = 78, ++ [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_7] = 135, ++ [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_8] = 162, ++ [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_9] = 180, ++ [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_7] = 292, ++ [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_8] = 351, ++ [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_9] = 390, ++ [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_7] = 585, ++ [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_8] = 702, ++ [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_9] = 780, ++}; ++ ++#define MAX_VHT_RATE(map, nss, bw) (mcs_map_to_rate[bw][map] * (nss)) ++ ++extern struct ieee80211_regdomain *reg_regdb[]; ++extern int reg_regdb_size; ++ ++char ccode_channels[200]; ++int index_for_channel_list = 0; ++module_param_string(ccode_channels, ccode_channels, 200, 0600); ++ ++void rwnx_get_countrycode_channels(struct wiphy *wiphy, ++ struct ieee80211_regdomain *regdomain){ ++ enum nl80211_band band; ++ struct ieee80211_supported_band *sband; ++ int channel_index; ++ int rule_index; ++ int band_num = 0; ++ int rule_num = regdomain->n_reg_rules; ++ int start_freq = 0; ++ int end_freq = 0; ++ int center_freq = 0; ++ char channel[4]; ++ ++ band_num = NUM_NL80211_BANDS; ++ ++ memset(ccode_channels, 0, 200); ++ index_for_channel_list = 0; ++ ++ for (band = 0; band < band_num; band++) { ++ sband = wiphy->bands[band];// bands: 0:2.4G 1:5G 2:60G ++ if (!sband) ++ continue; ++ ++ for (channel_index = 0; channel_index < sband->n_channels; channel_index++) { ++ for(rule_index = 0; rule_index < rule_num; rule_index++){ ++ start_freq = regdomain->reg_rules[rule_index].freq_range.start_freq_khz/1000; ++ end_freq = regdomain->reg_rules[rule_index].freq_range.end_freq_khz/1000; ++ center_freq = sband->channels[channel_index].center_freq; ++ if((center_freq - 10) >= start_freq && (center_freq + 10) <= end_freq){ ++ sprintf(channel, "%d",ieee80211_frequency_to_channel(center_freq)); ++ memcpy(ccode_channels + index_for_channel_list, channel, strlen(channel)); ++ index_for_channel_list += strlen(channel); ++ memcpy(ccode_channels + index_for_channel_list, " ", 1); ++ index_for_channel_list += 1; ++ break; ++ } ++ } ++ } ++ } ++ AICWFDBG(LOGINFO, "%s support channel:%s\r\n", __func__, ccode_channels); ++} ++ ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, ++ int index) ++{ ++ u8 idx; ++ ++ idx = index; ++ ++ memset(country_code, 0, 4); ++ country_code[0] = reg_regdb[idx]->alpha2[0]; ++ country_code[1] = reg_regdb[idx]->alpha2[1]; ++ ++ printk("%s set ccode:%s \r\n", __func__, country_code); ++ ++ rwnx_get_countrycode_channels(wiphy, reg_regdb[idx]); ++ ++ return reg_regdb[idx]; ++} ++ ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, ++ char *alpha2) ++{ ++ u8 idx; ++ ++ memset(country_code, 0, 4); ++ ++ AICWFDBG(LOGINFO, "%s set ccode:%s \r\n", __func__, alpha2); ++ idx = 0; ++ ++ while (reg_regdb[idx]){ ++ if((reg_regdb[idx]->alpha2[0] == alpha2[0]) && ++ (reg_regdb[idx]->alpha2[1] == alpha2[1])){ ++ memcpy(country_code, alpha2, 2); ++ rwnx_get_countrycode_channels(wiphy, reg_regdb[idx]); ++ return reg_regdb[idx]; ++ } ++ idx++; ++ } ++ ++ AICWFDBG(LOGERROR, "%s(): Error, wrong country = %s\n", ++ __func__, alpha2); ++ AICWFDBG(LOGINFO, "Set as default 00\n"); ++ memcpy(country_code, default_ccode, sizeof(default_ccode)); ++ rwnx_get_countrycode_channels(wiphy, reg_regdb[0]); ++ ++ return reg_regdb[0]; ++} ++ ++ ++ ++/** ++ * Do some sanity check ++ * ++ */ ++#if 0 ++static int rwnx_check_fw_hw_feature(struct rwnx_hw *rwnx_hw, ++ struct wiphy *wiphy) ++{ ++ u32_l sys_feat = rwnx_hw->version_cfm.features; ++ u32_l mac_feat = rwnx_hw->version_cfm.version_machw_1; ++ u32_l phy_feat = rwnx_hw->version_cfm.version_phy_1; ++ u32_l phy_vers = rwnx_hw->version_cfm.version_phy_2; ++ u16_l max_sta_nb = rwnx_hw->version_cfm.max_sta_nb; ++ u8_l max_vif_nb = rwnx_hw->version_cfm.max_vif_nb; ++ int bw, res = 0; ++ int amsdu_rx; ++ ++ if (!rwnx_hw->mod_params->custregd) ++ rwnx_hw->mod_params->custchan = false; ++ ++ if (rwnx_hw->mod_params->custchan) { ++ rwnx_hw->mod_params->mesh = false; ++ rwnx_hw->mod_params->tdls = false; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++ if (!(sys_feat & BIT(MM_FEAT_UMAC_BIT))) { ++ wiphy_err(wiphy, ++ "Loading softmac firmware with fullmac driver\n"); ++ res = -1; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_ANT_DIV_BIT))) { ++ rwnx_hw->mod_params->ant_div = false; ++ } ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (!(sys_feat & BIT(MM_FEAT_VHT_BIT))) { ++ rwnx_hw->mod_params->vht_on = false; ++ } ++ ++ // Check if HE is supported ++ if (!(sys_feat & BIT(MM_FEAT_HE_BIT))) { ++ rwnx_hw->mod_params->he_on = false; ++ rwnx_hw->mod_params->he_ul_on = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_PS_BIT))) { ++ rwnx_hw->mod_params->ps_on = false; ++ } ++ ++ /* AMSDU (non)support implies different shared structure definition ++ so insure that fw and drv have consistent compilation option */ ++ if (sys_feat & BIT(MM_FEAT_AMSDU_BIT)) { ++#ifndef CONFIG_RWNX_SPLIT_TX_BUF ++ wiphy_err(wiphy, ++ "AMSDU enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#else ++ if (rwnx_hw->mod_params->amsdu_maxnb > NX_TX_PAYLOAD_MAX) ++ rwnx_hw->mod_params->amsdu_maxnb = NX_TX_PAYLOAD_MAX; ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ } else { ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ wiphy_err(wiphy, ++ "AMSDU disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_UAPSD_BIT))) { ++ rwnx_hw->mod_params->uapsd_timeout = 0; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_BFMEE_BIT))) { ++ rwnx_hw->mod_params->bfmee = false; ++ } ++ ++ if ((sys_feat & BIT(MM_FEAT_BFMER_BIT))) { ++#ifndef CONFIG_RWNX_BFMER ++ wiphy_err(wiphy, ++ "BFMER enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_BFMER */ ++ // Check PHY and MAC HW BFMER support and update parameter accordingly ++ if (!(phy_feat & MDM_BFMER_BIT) || !(mac_feat & NXMAC_BFMER_BIT)) { ++ rwnx_hw->mod_params->bfmer = false; ++ // Disable the feature in the bitfield so that it won't be displayed ++ sys_feat &= ~BIT(MM_FEAT_BFMER_BIT); ++ } ++ } else { ++#ifdef CONFIG_RWNX_BFMER ++ wiphy_err(wiphy, ++ "BFMER disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#else ++ rwnx_hw->mod_params->bfmer = false; ++#endif /* CONFIG_RWNX_BFMER */ ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_MESH_BIT))) { ++ rwnx_hw->mod_params->mesh = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_TDLS_BIT))) { ++ rwnx_hw->mod_params->tdls = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_UF_BIT))) { ++ rwnx_hw->mod_params->uf = false; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if ((sys_feat & BIT(MM_FEAT_MON_DATA_BIT))) { ++#ifndef CONFIG_RWNX_MON_DATA ++ wiphy_err(wiphy, ++ "Monitor+Data interface support (MON_DATA) is enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_MON_DATA */ ++ } else { ++#ifdef CONFIG_RWNX_MON_DATA ++ wiphy_err(wiphy, ++ "Monitor+Data interface support (MON_DATA) disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_MON_DATA */ ++ } ++#endif ++ ++ // Check supported AMSDU RX size ++ amsdu_rx = (sys_feat >> MM_AMSDU_MAX_SIZE_BIT0) & 0x03; ++ if (amsdu_rx < rwnx_hw->mod_params->amsdu_rx_max) { ++ rwnx_hw->mod_params->amsdu_rx_max = amsdu_rx; ++ } ++ ++ // Check supported BW ++ bw = (phy_feat & MDM_CHBW_MASK) >> MDM_CHBW_LSB; ++ // Check if 80MHz BW is supported ++ if (bw < 2) { ++ rwnx_hw->mod_params->use_80 = false; ++ } ++ // Check if 40MHz BW is supported ++ if (bw < 1) ++ rwnx_hw->mod_params->use_2040 = false; ++ ++ // 80MHz BW shall be disabled if 40MHz is not enabled ++ if (!rwnx_hw->mod_params->use_2040) ++ rwnx_hw->mod_params->use_80 = false; ++ ++ // Check if HT is supposed to be supported. If not, disable VHT/HE too ++ if (!rwnx_hw->mod_params->ht_on) { ++ rwnx_hw->mod_params->vht_on = false; ++ rwnx_hw->mod_params->he_on = false; ++ rwnx_hw->mod_params->he_ul_on = false; ++ rwnx_hw->mod_params->use_80 = false; ++ rwnx_hw->mod_params->use_2040 = false; ++ } ++ ++ // LDPC is mandatory for HE40 and above, so if LDPC is not supported, then disable ++ // HE to use HT/VHT only ++ if (rwnx_hw->mod_params->use_2040 && !rwnx_hw->mod_params->ldpc_on) { ++ rwnx_hw->mod_params->he_on = false; ++ rwnx_hw->mod_params->he_ul_on = false; ++ } ++ ++ // HT greenfield is not supported in modem >= 3.0 ++ if (__MDM_MAJOR_VERSION(phy_vers) > 0) { ++ rwnx_hw->mod_params->gf_rx_on = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_MU_MIMO_RX_BIT)) || ++ !rwnx_hw->mod_params->bfmee) { ++ rwnx_hw->mod_params->murx = false; ++ } ++ ++ if ((sys_feat & BIT(MM_FEAT_MU_MIMO_TX_BIT))) { ++#ifndef CONFIG_RWNX_MUMIMO_TX ++ wiphy_err(wiphy, ++ "MU-MIMO TX enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ if (!rwnx_hw->mod_params->bfmer) ++ rwnx_hw->mod_params->mutx = false; ++ // Check PHY and MAC HW MU-MIMO TX support and update parameter accordingly ++ else if (!(phy_feat & MDM_MUMIMOTX_BIT) || !(mac_feat & NXMAC_MU_MIMO_TX_BIT)) { ++ rwnx_hw->mod_params->mutx = false; ++ // Disable the feature in the bitfield so that it won't be displayed ++ sys_feat &= ~BIT(MM_FEAT_MU_MIMO_TX_BIT); ++ } ++ } else { ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ wiphy_err(wiphy, ++ "MU-MIMO TX disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#else ++ rwnx_hw->mod_params->mutx = false; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ } ++ ++ if (sys_feat & BIT(MM_FEAT_WAPI_BIT)) { ++ rwnx_enable_wapi(rwnx_hw); ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (sys_feat & BIT(MM_FEAT_MFP_BIT)) { ++ rwnx_enable_mfp(rwnx_hw); ++ } ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define QUEUE_NAME "Broadcast/Multicast queue " ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (sys_feat & BIT(MM_FEAT_BCN_BIT)) { ++#if NX_TXQ_CNT == 4 ++ wiphy_err(wiphy, QUEUE_NAME ++ "enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* NX_TXQ_CNT == 4 */ ++ } else { ++#if NX_TXQ_CNT == 5 ++ wiphy_err(wiphy, QUEUE_NAME ++ "disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#endif /* NX_TXQ_CNT == 5 */ ++ } ++#undef QUEUE_NAME ++ ++#ifdef CONFIG_RWNX_RADAR ++ if (sys_feat & BIT(MM_FEAT_RADAR_BIT)) { ++ /* Enable combination with radar detection */ ++ wiphy->n_iface_combinations++; ++ } ++#endif /* CONFIG_RWNX_RADAR */ ++ ++#ifndef CONFIG_RWNX_SDM ++ switch (__MDM_PHYCFG_FROM_VERS(phy_feat)) { ++ case MDM_PHY_CONFIG_TRIDENT: ++ case MDM_PHY_CONFIG_ELMA: ++ rwnx_hw->mod_params->nss = 1; ++ break; ++ case MDM_PHY_CONFIG_KARST: ++ { ++ int nss_supp = (phy_feat & MDM_NSS_MASK) >> MDM_NSS_LSB; ++ if (rwnx_hw->mod_params->nss > nss_supp) ++ rwnx_hw->mod_params->nss = nss_supp; ++ } ++ break; ++ default: ++ WARN_ON(1); ++ break; ++ } ++#endif /* CONFIG_RWNX_SDM */ ++ ++ if (rwnx_hw->mod_params->nss < 1 || rwnx_hw->mod_params->nss > 2) ++ rwnx_hw->mod_params->nss = 1; ++ ++ if (rwnx_hw->mod_params->phy_cfg < 0 || rwnx_hw->mod_params->phy_cfg > 5) ++ rwnx_hw->mod_params->phy_cfg = 2; ++ ++ if (rwnx_hw->mod_params->mcs_map < 0 || rwnx_hw->mod_params->mcs_map > 2) ++ rwnx_hw->mod_params->mcs_map = 0; ++ ++ wiphy_info(wiphy, "PHY features: [NSS=%d][CHBW=%d]%s%s\n", ++ rwnx_hw->mod_params->nss, ++ 20 * (1 << ((phy_feat & MDM_CHBW_MASK) >> MDM_CHBW_LSB)), ++ rwnx_hw->mod_params->ldpc_on ? "[LDPC]" : "", ++ rwnx_hw->mod_params->he_on ? "[HE]" : ""); ++ ++#define PRINT_RWNX_FEAT(feat) \ ++ (sys_feat & BIT(MM_FEAT_##feat##_BIT) ? "["#feat"]" : "") ++ ++ wiphy_info(wiphy, "FW features: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", ++ PRINT_RWNX_FEAT(BCN), ++ PRINT_RWNX_FEAT(AUTOBCN), ++ PRINT_RWNX_FEAT(HWSCAN), ++ PRINT_RWNX_FEAT(CMON), ++ PRINT_RWNX_FEAT(MROLE), ++ PRINT_RWNX_FEAT(RADAR), ++ PRINT_RWNX_FEAT(PS), ++ PRINT_RWNX_FEAT(UAPSD), ++ PRINT_RWNX_FEAT(DPSM), ++ PRINT_RWNX_FEAT(AMPDU), ++ PRINT_RWNX_FEAT(AMSDU), ++ PRINT_RWNX_FEAT(CHNL_CTXT), ++ PRINT_RWNX_FEAT(REORD), ++ PRINT_RWNX_FEAT(P2P), ++ PRINT_RWNX_FEAT(P2P_GO), ++ PRINT_RWNX_FEAT(UMAC), ++ PRINT_RWNX_FEAT(VHT), ++ PRINT_RWNX_FEAT(HE), ++ PRINT_RWNX_FEAT(BFMEE), ++ PRINT_RWNX_FEAT(BFMER), ++ PRINT_RWNX_FEAT(WAPI), ++ PRINT_RWNX_FEAT(MFP), ++ PRINT_RWNX_FEAT(MU_MIMO_RX), ++ PRINT_RWNX_FEAT(MU_MIMO_TX), ++ PRINT_RWNX_FEAT(MESH), ++ PRINT_RWNX_FEAT(TDLS), ++ PRINT_RWNX_FEAT(ANT_DIV)); ++#undef PRINT_RWNX_FEAT ++ ++ if (max_sta_nb != NX_REMOTE_STA_MAX) { ++ wiphy_err(wiphy, "Different number of supported stations between driver and FW (%d != %d)\n", ++ NX_REMOTE_STA_MAX, max_sta_nb); ++ res = -1; ++ } ++ ++ if (max_vif_nb != NX_VIRT_DEV_MAX) { ++ wiphy_err(wiphy, "Different number of supported virtual interfaces between driver and FW (%d != %d)\n", ++ NX_VIRT_DEV_MAX, max_vif_nb); ++ res = -1; ++ } ++ ++ return res; ++} ++#endif ++ ++ ++static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#ifdef CONFIG_VHT_FOR_OLD_KERNEL ++ #ifdef USE_5G ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ #endif ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ int mcs_map; ++ int mcs_map_max; ++ int bw_max; ++ ++ if (!rwnx_hw->mod_params->vht_on) { ++ return; ++ } ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ rwnx_hw->vht_cap_2G.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_2G.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_2G.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ rwnx_hw->vht_cap_2G.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_2G.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_2G.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif//CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_2G.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; ++ printk("%s, vht_capa_info=0x%x\n", __func__, rwnx_hw->vht_cap_2G.cap); ++#ifdef USE_5G ++ if (rwnx_hw->band_5g_support) { ++ rwnx_hw->vht_cap_5G.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_5G.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_5G.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ rwnx_hw->vht_cap_5G.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_5G.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_5G.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif//CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_5G.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; ++ } ++#endif//USE_5G ++ return; ++#else ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ int mcs_map; ++ int mcs_map_max; ++ int bw_max; ++#endif//CONFIG_VHT_FOR_OLD_KERNEL ++ ++ if (!rwnx_hw->mod_params->vht_on) { ++ return; ++ } ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ band_2GHz->vht_cap.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_2GHz->vht_cap.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ band_2GHz->vht_cap.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ band_2GHz->vht_cap.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_2GHz->vht_cap.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ band_2GHz->vht_cap.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_2GHz->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_2GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_2GHz->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_2GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif ++ band_2GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ band_5GHz->vht_cap.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_5GHz->vht_cap.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ band_5GHz->vht_cap.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ band_5GHz->vht_cap.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_5GHz->vht_cap.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ band_5GHz->vht_cap.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_5GHz->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_5GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_5GHz->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_5GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif ++ band_5GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ } ++} ++ ++static void rwnx_set_ht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ ++ if (!rwnx_hw->mod_params->ht_on) { ++ band_2GHz->ht_cap.ht_supported = false; ++ if (rwnx_hw->band_5g_support) ++ band_5GHz->ht_cap.ht_supported = false; ++ return; ++ } ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ if (rwnx_hw->mod_params->stbc_on) ++ band_2GHz->ht_cap.cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; ++ if (rwnx_hw->mod_params->ldpc_on) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; ++ if (rwnx_hw->mod_params->use_2040) { ++ band_2GHz->ht_cap.mcs.rx_mask[4] = 0x1; /* MCS32 */ ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(135 * nss); ++ } else { ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(65 * nss); ++ } ++ if (nss > 1) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; ++ ++ // Update the AMSDU max RX size ++ if (rwnx_hw->mod_params->amsdu_rx_max) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; ++ ++ if (rwnx_hw->mod_params->sgi) { ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; ++ if (rwnx_hw->mod_params->use_2040) { ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(150 * nss); ++ } else ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(72 * nss); ++ } ++ if (rwnx_hw->mod_params->gf_rx_on) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; ++ ++ for (i = 0; i < nss; i++) { ++ band_2GHz->ht_cap.mcs.rx_mask[i] = 0xFF; ++ } ++ ++ if (rwnx_hw->band_5g_support) ++ band_5GHz->ht_cap = band_2GHz->ht_cap; ++} ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++extern struct ieee80211_sband_iftype_data rwnx_he_capa; ++#endif ++static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++ struct ieee80211_sta_he_cap *he_cap; ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ int mcs_map; ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ he_cap = (struct ieee80211_sta_he_cap *) &rwnx_he_capa.he_cap; ++ he_cap->has_he = true; ++ he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK; ++ if (rwnx_hw->mod_params->use_2040) { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; ++ he_cap->ppe_thres[0] |= 0x10; ++ } ++ if (rwnx_hw->mod_params->use_80) { ++ he_cap->ppe_thres[0] |= 0x20; ++ he_cap->ppe_thres[2] |= 0xc0; ++ he_cap->ppe_thres[3] |= 0x01; ++ } ++ if (nss == 2) { ++ he_cap->ppe_thres[0] |= 0x01; ++ he_cap->ppe_thres[3] |= 0x70; ++ he_cap->ppe_thres[4] |= 0x1c; ++ he_cap->ppe_thres[5] |= 0x07; ++ } ++ //if (rwnx_hw->mod_params->use_80) ++ { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; ++ } ++ if (rwnx_hw->mod_params->ldpc_on) { ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; ++ } else { ++ // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory ++ // for MCS 10 and 11 ++ rwnx_hw->mod_params->he_mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US ++ | IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS; ++ ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS | ++ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #endif ++ if (rwnx_hw->mod_params->stbc_on) ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; ++ if (rwnx_hw->mod_params->bfmee) { ++ he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ he_cap->he_cap_elem.phy_cap_info[4] |= ++ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; ++ } ++ he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | ++ IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ //he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; ++ he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; ++ he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | ++ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9); ++ memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp)); ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ } ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, ++ // IEEE80211_HE_MCS_SUPPORT_0_7); ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ } ++ ++ return ; ++ #endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ struct ieee80211_sta_he_cap *he_cap; ++ int mcs_map; ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ if (!rwnx_hw->mod_params->he_on) { ++ band_2GHz->iftype_data = NULL; ++ band_2GHz->n_iftype_data = 0; ++ if (rwnx_hw->band_5g_support) { ++ band_5GHz->iftype_data = NULL; ++ band_5GHz->n_iftype_data = 0; ++ } ++ return; ++ } ++ he_cap = (struct ieee80211_sta_he_cap *) &band_2GHz->iftype_data->he_cap; ++ he_cap->has_he = true; ++ he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK; ++ if (rwnx_hw->mod_params->use_2040) { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; ++ he_cap->ppe_thres[0] |= 0x10; ++ } ++ if (rwnx_hw->mod_params->use_80) { ++ he_cap->ppe_thres[0] |= 0x20; ++ he_cap->ppe_thres[2] |= 0xc0; ++ he_cap->ppe_thres[3] |= 0x01; ++ } ++ if (nss == 2) { ++ he_cap->ppe_thres[0] |= 0x01; ++ he_cap->ppe_thres[3] |= 0x70; ++ he_cap->ppe_thres[4] |= 0x1c; ++ he_cap->ppe_thres[5] |= 0x07; ++ } ++ //if (rwnx_hw->mod_params->use_80) ++ { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; ++ } ++ if (rwnx_hw->mod_params->ldpc_on) { ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; ++ } else { ++ // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory ++ // for MCS 10 and 11 ++ rwnx_hw->mod_params->he_mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US ++ | IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS; ++ ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS | ++ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #endif ++ if (rwnx_hw->mod_params->stbc_on) ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; ++ #endif ++ ++ ++ if (rwnx_hw->mod_params->bfmee) { ++ he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ he_cap->he_cap_elem.phy_cap_info[4] |= ++ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; ++ } ++ he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | ++ IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #endif ++ ++ //he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; ++ he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | ++ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; ++ #endif ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ } ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp)); ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ } ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, ++ // IEEE80211_HE_MCS_SUPPORT_0_7); ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ he_cap = (struct ieee80211_sta_he_cap *) &band_5GHz->iftype_data->he_cap; ++ he_cap->has_he = true; ++ he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK; ++ if (rwnx_hw->mod_params->use_2040) { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; ++ he_cap->ppe_thres[0] |= 0x10; ++ } ++ if (rwnx_hw->mod_params->use_80) { ++ he_cap->ppe_thres[0] |= 0x20; ++ he_cap->ppe_thres[2] |= 0xc0; ++ he_cap->ppe_thres[3] |= 0x01; ++ } ++ if (nss == 2) { ++ he_cap->ppe_thres[0] |= 0x01; ++ he_cap->ppe_thres[3] |= 0x70; ++ he_cap->ppe_thres[4] |= 0x1c; ++ he_cap->ppe_thres[5] |= 0x07; ++ } ++ //if (rwnx_hw->mod_params->use_80) ++ { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; ++ } ++ if (rwnx_hw->mod_params->ldpc_on) { ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; ++ } else { ++ // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory ++ // for MCS 10 and 11 ++ rwnx_hw->mod_params->he_mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US | ++ IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS | ++ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #endif ++ if (rwnx_hw->mod_params->stbc_on) ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; ++ #endif ++ ++ if (rwnx_hw->mod_params->bfmee) { ++ he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ he_cap->he_cap_elem.phy_cap_info[4] |= ++ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; ++ } ++ he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | ++ IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #endif ++ ++ //he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; ++ he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | ++ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; ++ #endif ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9); ++ memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp)); ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ } ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, ++ // IEEE80211_HE_MCS_SUPPORT_0_7); ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ } ++ } ++#endif ++} ++ ++static void rwnx_set_wiphy_params(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) ++ struct ieee80211_regdomain *regdomain; ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ /* FULLMAC specific parameters */ ++ wiphy->flags |= WIPHY_FLAG_REPORTS_OBSS; ++ wiphy->max_scan_ssids = SCAN_SSID_MAX; ++ wiphy->max_scan_ie_len = SCANU_MAX_IE_LEN; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (rwnx_hw->mod_params->tdls) { ++ /* TDLS support */ ++ wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; ++#ifdef CONFIG_RWNX_FULLMAC ++ /* TDLS external setup support */ ++ wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; ++#endif ++ } ++ ++ if (rwnx_hw->mod_params->ap_uapsd_on) ++ wiphy->flags |= WIPHY_FLAG_AP_UAPSD; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (rwnx_hw->mod_params->ps_on) ++ wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; ++ else ++ wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; ++#endif ++ ++if (rwnx_hw->mod_params->custregd) { ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ // Apply custom regulatory. Note that for recent kernel versions we use instead the ++ // REGULATORY_WIPHY_SELF_MANAGED flag, along with the regulatory_set_wiphy_regd() ++ // function, that needs to be called after wiphy registration ++ memcpy(country_code, default_ccode, sizeof(default_ccode)); ++ regdomain = getRegdomainFromRwnxDB(wiphy, default_ccode); ++ printk(KERN_CRIT ++ "\n\n%s: CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES\n\n", ++ __func__); ++ wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; ++ /* From kernel 6.5.0, this bit is removed and will be reused later */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 39) || LINUX_VERSION_CODE > KERNEL_VERSION(6, 2, 0)) ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) */ ++ wiphy_apply_custom_regulatory(wiphy, regdomain); ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) ++ memcpy(country_code, default_ccode, sizeof(default_ccode)); ++ regdomain = getRegdomainFromRwnxDB(wiphy, default_ccode); ++ printk(KERN_CRIT"%s: Registering custom regulatory\n", __func__); ++ wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; ++ wiphy_apply_custom_regulatory(wiphy, regdomain); ++#endif ++ // Check if custom channel set shall be enabled. In such case only monitor mode is ++ // supported ++ if (rwnx_hw->mod_params->custchan) { ++ wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR); ++ ++ // Enable "extra" channels ++ wiphy->bands[NL80211_BAND_2GHZ]->n_channels += 13; ++ //#ifdef USE_5G ++ if(rwnx_hw->band_5g_support){ ++ wiphy->bands[NL80211_BAND_5GHZ]->n_channels += 59; ++ } ++ //#endif ++ } ++ } ++ ++#if 0 ++ if (rwnx_hw->mod_params->custregd) { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ // Apply custom regulatory. Note that for recent kernel versions we use instead the ++ // REGULATORY_WIPHY_SELF_MANAGED flag, along with the regulatory_set_wiphy_regd() ++ // function, that needs to be called after wiphy registration ++ printk(KERN_CRIT ++ "\n\n%s: CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES\n\n", ++ __func__); ++ wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; ++ /* From kernel 6.5.0, this bit is removed and will be reused later */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 39) || LINUX_VERSION_CODE > KERNEL_VERSION(6, 2, 0)) ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) */ ++ wiphy_apply_custom_regulatory(wiphy, &rwnx_regdom); ++#endif ++ // Check if custom channel set shall be enabled. In such case only monitor mode is ++ // supported ++ if (rwnx_hw->mod_params->custchan) { ++ wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR); ++ ++ // Enable "extra" channels ++ wiphy->bands[NL80211_BAND_2GHZ]->n_channels += 13; ++ if (rwnx_hw->band_5g_support) ++ wiphy->bands[NL80211_BAND_5GHZ]->n_channels += 59; ++ } ++ } ++#endif ++} ++ ++#if 0 ++static void rwnx_set_rf_params(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#ifndef CONFIG_RWNX_SDM ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ u32 mdm_phy_cfg = __MDM_PHYCFG_FROM_VERS(rwnx_hw->version_cfm.version_phy_1); ++ ++ /* ++ * Get configuration file depending on the RF ++ */ ++ if (mdm_phy_cfg == MDM_PHY_CONFIG_TRIDENT) { ++ struct rwnx_phy_conf_file phy_conf; ++ // Retrieve the Trident configuration ++ rwnx_parse_phy_configfile(rwnx_hw, RWNX_PHY_CONFIG_TRD_NAME, ++ &phy_conf, rwnx_hw->mod_params->phy_cfg); ++ memcpy(&rwnx_hw->phy.cfg, &phy_conf.trd, sizeof(phy_conf.trd)); ++ } else if (mdm_phy_cfg == MDM_PHY_CONFIG_ELMA) { ++ } else if (mdm_phy_cfg == MDM_PHY_CONFIG_KARST) { ++ struct rwnx_phy_conf_file phy_conf; ++ // We use the NSS parameter as is ++ // Retrieve the Karst configuration ++ rwnx_parse_phy_configfile(rwnx_hw, RWNX_PHY_CONFIG_KARST_NAME, ++ &phy_conf, rwnx_hw->mod_params->phy_cfg); ++ ++ memcpy(&rwnx_hw->phy.cfg, &phy_conf.karst, sizeof(phy_conf.karst)); ++ } else { ++ WARN_ON(1); ++ } ++ ++ /* ++ * adjust caps depending on the RF ++ */ ++ switch (mdm_phy_cfg) { ++ case MDM_PHY_CONFIG_TRIDENT: ++ { ++ wiphy_dbg(wiphy, "found Trident phy .. limit BW to 40MHz\n"); ++ rwnx_hw->phy.limit_bw = true; ++ if (rwnx_hw->band_5g_support) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif ++ band_5GHz->vht_cap.cap &= ~(IEEE80211_VHT_CAP_SHORT_GI_80 | ++ IEEE80211_VHT_CAP_RXSTBC_MASK); ++ } ++ break; ++ } ++ case MDM_PHY_CONFIG_ELMA: ++ wiphy_dbg(wiphy, "found ELMA phy .. disabling 2.4GHz and greenfield rx\n"); ++ wiphy->bands[NL80211_BAND_2GHZ] = NULL; ++ band_2GHz->ht_cap.cap &= ~IEEE80211_HT_CAP_GRN_FLD; ++ if (rwnx_hw->band_5g_support) { ++ band_5GHz->ht_cap.cap &= ~IEEE80211_HT_CAP_GRN_FLD; ++ band_5GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_RXSTBC_MASK; ++ } ++ break; ++ case MDM_PHY_CONFIG_KARST: ++ { ++ wiphy_dbg(wiphy, "found KARST phy\n"); ++ break; ++ } ++ default: ++ WARN_ON(1); ++ break; ++ } ++#endif /* CONFIG_RWNX_SDM */ ++} ++#endif ++ ++int rwnx_handle_dynparams(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#if 0 ++ /* Check compatibility between requested parameters and HW/SW features */ ++ int ret; ++ ++ ret = rwnx_check_fw_hw_feature(rwnx_hw, wiphy); ++ if (ret) ++ return ret; ++ ++ /* Allocate the RX buffers according to the maximum AMSDU RX size */ ++ ret = rwnx_ipc_rxbuf_init(rwnx_hw, ++ (4 * (rwnx_hw->mod_params->amsdu_rx_max + 1) + 1) * 1024); ++ if (ret) { ++ wiphy_err(wiphy, "Cannot allocate the RX buffers\n"); ++ return ret; ++ } ++#endif ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rwnx_hw->mod_params->sgi80 = true; ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80 && rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80X2 && ++ rwnx_hw->mod_params->he_mcs_map == IEEE80211_HE_MCS_SUPPORT_0_11) { ++ AICWFDBG(LOGINFO,"%s unsupport mcs11 change to mcs9", __func__); ++ rwnx_hw->mod_params->he_mcs_map = IEEE80211_HE_MCS_SUPPORT_0_9; ++ } ++ ++ /* Set wiphy parameters */ ++ rwnx_set_wiphy_params(rwnx_hw, wiphy); ++ /* Set VHT capabilities */ ++ rwnx_set_vht_capa(rwnx_hw, wiphy); ++ /* Set HE capabilities */ ++ rwnx_set_he_capa(rwnx_hw, wiphy); ++ /* Set HT capabilities */ ++ rwnx_set_ht_capa(rwnx_hw, wiphy); ++ /* Set RF specific parameters (shall be done last as it might change some ++ capabilities previously set) */ ++#if 0 ++ rwnx_set_rf_params(rwnx_hw, wiphy); ++#endif ++ return 0; ++} ++ ++void rwnx_custregd(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++// For older kernel version, the custom regulatory is applied before the wiphy ++// registration (in rwnx_set_wiphy_params()), so nothing has to be done here ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ if (!rwnx_hw->mod_params->custregd) ++ return; ++ ++ /* From kernel 6.5.0, this bit is removed and will be reused later */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 39) || LINUX_VERSION_CODE > KERNEL_VERSION(6, 2, 0)) ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) */ ++ wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; ++ ++ rtnl_lock(); ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) ++ if (regulatory_set_wiphy_regd_sync(wiphy, getRegdomainFromRwnxDB(wiphy, default_ccode))){ ++ wiphy_err(wiphy, "Failed to set custom regdomain\n"); ++ } ++ #else ++ if (regulatory_set_wiphy_regd_sync_rtnl(wiphy, getRegdomainFromRwnxDB(wiphy, default_ccode))){ ++ wiphy_err(wiphy, "Failed to set custom regdomain\n"); ++ } ++ #endif ++ ++ else{ ++ wiphy_err(wiphy,"\n" ++ "*******************************************************\n" ++ "** CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES **\n" ++ "*******************************************************\n"); ++ } ++ rtnl_unlock(); ++#endif ++ ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h +new file mode 100644 +index 000000000000..ef31093fcadb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h +@@ -0,0 +1,76 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_mod_params.h ++ * ++ * @brief Declaration of module parameters ++ * ++ * Copyright (C) RivieraWaves 2012-2021 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_MOD_PARAM_H_ ++#define _RWNX_MOD_PARAM_H_ ++ ++struct rwnx_mod_params { ++ bool ht_on; ++ bool vht_on; ++ bool he_on; ++ int mcs_map; ++ int he_mcs_map; ++ bool he_ul_on; ++ bool ldpc_on; ++ bool stbc_on; ++ bool gf_rx_on; ++ int phy_cfg; ++ int uapsd_timeout; ++ bool ap_uapsd_on; ++ bool sgi; ++ bool sgi80; ++ bool use_2040; ++ bool use_80; ++ bool custregd; ++ bool custchan; ++ int nss; ++ int amsdu_rx_max; ++ bool bfmee; ++ bool bfmer; ++ bool mesh; ++ bool murx; ++ bool mutx; ++ bool mutx_on; ++ unsigned int roc_dur_max; ++ int listen_itv; ++ bool listen_bcmc; ++ int lp_clk_ppm; ++ bool ps_on; ++ int tx_lft; ++ int amsdu_maxnb; ++ int uapsd_queues; ++ bool tdls; ++ bool uf; ++ bool auto_reply; ++ char *ftl; ++ bool dpsm; ++#ifdef CONFIG_RWNX_FULLMAC ++ bool ant_div; ++#endif /* CONFIG_RWNX_FULLMAC */ ++}; ++ ++extern struct rwnx_mod_params rwnx_mod_params; ++ ++struct rwnx_hw; ++struct wiphy; ++int rwnx_handle_dynparams(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy); ++void rwnx_custregd(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy); ++void rwnx_enable_wapi(struct rwnx_hw *rwnx_hw); ++void rwnx_enable_mfp(struct rwnx_hw *rwnx_hw); ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, ++ char *alpha2); ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, ++ int index); ++ ++ ++#endif /* _RWNX_MOD_PARAM_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c +new file mode 100644 +index 000000000000..1799d7dde4cd +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c +@@ -0,0 +1,1557 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_msg_rx.c ++ * ++ * @brief RX function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2021 ++ * ++ **************************************************************************************** ++ */ ++#include ++#include "rwnx_defs.h" ++#include "rwnx_prof.h" ++#include "rwnx_tx.h" ++#ifdef CONFIG_RWNX_BFMER ++#include "rwnx_bfmer.h" ++#endif //(CONFIG_RWNX_BFMER) ++#ifdef CONFIG_RWNX_FULLMAC ++#include "rwnx_debugfs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_tdls.h" ++#endif /* CONFIG_RWNX_FULLMAC */ ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "aicwf_txrxif.h" ++#include "rwnx_msg_rx.h" ++#ifdef CONFIG_SDIO_BT ++#include "aic_btsdio.h" ++#endif ++void rwnx_cfg80211_unlink_bss(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif); ++ ++static int rwnx_freq_to_idx(struct rwnx_hw *rwnx_hw, int freq) ++{ ++ struct ieee80211_supported_band *sband = NULL; ++ int band, ch, idx = 0; ++ ++ for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { ++#ifdef CONFIG_RWNX_FULLMAC ++ sband = rwnx_hw->wiphy->bands[band]; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ if (!sband) { ++ continue; ++ } ++ ++ for (ch = 0; ch < sband->n_channels; ch++, idx++) { ++ if (sband->channels[ch].center_freq == freq) { ++ goto exit; ++ } ++ } ++ } ++ ++ BUG_ON(1); ++ ++exit: ++ // Channel has been found, return the index ++ return idx; ++} ++ ++/*************************************************************************** ++ * Messages from MM task ++ **************************************************************************/ ++static inline int rwnx_rx_chan_pre_switch_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ int chan_idx = ((struct mm_channel_pre_switch_ind *)msg->param)->chan_index; ++ ++ REG_SW_SET_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->up && rwnx_vif->ch_index == chan_idx) { ++ rwnx_txq_vif_stop(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ REG_SW_CLEAR_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT); ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_chan_switch_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ int chan_idx = ((struct mm_channel_switch_ind *)msg->param)->chan_index; ++ bool roc = ((struct mm_channel_switch_ind *)msg->param)->roc; ++ bool roc_tdls = ((struct mm_channel_switch_ind *)msg->param)->roc_tdls; ++ ++ REG_SW_SET_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (roc_tdls) { ++ u8 vif_index = ((struct mm_channel_switch_ind *)msg->param)->vif_index; ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == vif_index) { ++ rwnx_vif->roc_tdls = true; ++ rwnx_txq_tdls_sta_start(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ } else if (!roc) { ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->up && rwnx_vif->ch_index == chan_idx) { ++ rwnx_txq_vif_start(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ } else { ++ /* Retrieve the allocated RoC element */ ++ struct rwnx_roc_elem *roc_elem = rwnx_hw->roc_elem; ++ /* Get VIF on which RoC has been started */ ++ //rwnx_vif = netdev_priv(roc_elem->wdev->netdev); ++ ++ /* For debug purpose (use ftrace kernel option) */ ++ //trace_switch_roc(rwnx_vif->vif_index); ++ ++ if(roc_elem) { ++ /* If mgmt_roc is true, remain on channel has been started by ourself */ ++ if (!roc_elem->mgmt_roc) { ++ /* Inform the host that we have switch on the indicated off-channel */ ++ cfg80211_ready_on_channel(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), ++ roc_elem->chan, roc_elem->duration, GFP_ATOMIC); ++ } ++ ++ /* Keep in mind that we have switched on the channel */ ++ roc_elem->on_chan = true; ++ } else { ++ printk("roc_elem == null\n"); ++ } ++ // Enable traffic on OFF channel queue ++ rwnx_txq_offchan_start(rwnx_hw); ++ } ++ ++ tasklet_schedule(&rwnx_hw->task); ++ ++ rwnx_hw->cur_chanctx = chan_idx; ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ REG_SW_CLEAR_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT); ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_tdls_chan_switch_cfm(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ return 0; ++} ++ ++static inline int rwnx_rx_tdls_chan_switch_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ // Enable traffic on OFF channel queue ++ rwnx_txq_offchan_start(rwnx_hw); ++ ++ return 0; ++#endif ++} ++ ++static inline int rwnx_rx_tdls_chan_switch_base_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ u8 vif_index = ((struct tdls_chan_switch_base_ind *)msg->param)->vif_index; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == vif_index) { ++ rwnx_vif->roc_tdls = false; ++ rwnx_txq_tdls_sta_stop(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ return 0; ++#endif ++} ++ ++static inline int rwnx_rx_tdls_peer_ps_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ u8 vif_index = ((struct tdls_peer_ps_ind *)msg->param)->vif_index; ++ bool ps_on = ((struct tdls_peer_ps_ind *)msg->param)->ps_on; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == vif_index) { ++ rwnx_vif->sta.tdls_sta->tdls.ps_on = ps_on; ++ // Update PS status for the TDLS station ++ rwnx_ps_bh_enable(rwnx_hw, rwnx_vif->sta.tdls_sta, ps_on); ++ } ++ } ++ ++ return 0; ++#endif ++} ++ ++static inline int rwnx_rx_remain_on_channel_exp_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ /* Retrieve the allocated RoC element */ ++ struct rwnx_roc_elem *roc_elem = rwnx_hw->roc_elem; ++ /* Get VIF on which RoC has been started */ ++ struct rwnx_vif *rwnx_vif; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (!roc_elem) ++ return 0; ++ ++ rwnx_vif = container_of(roc_elem->wdev, struct rwnx_vif, wdev); ++ /* For debug purpose (use ftrace kernel option) */ ++#ifdef CREATE_TRACE_POINTS ++ trace_roc_exp(rwnx_vif->vif_index); ++#endif ++ /* If mgmt_roc is true, remain on channel has been started by ourself */ ++ /* If RoC has been cancelled before we switched on channel, do not call cfg80211 */ ++ if (!roc_elem->mgmt_roc && roc_elem->on_chan) { ++ /* Inform the host that off-channel period has expired */ ++ cfg80211_remain_on_channel_expired(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), ++ roc_elem->chan, GFP_ATOMIC); ++ } ++ ++ /* De-init offchannel TX queue */ ++ rwnx_txq_offchan_deinit(rwnx_vif); ++ ++ /* Increase the cookie counter cannot be zero */ ++ rwnx_hw->roc_cookie_cnt++; ++ ++ if (rwnx_hw->roc_cookie_cnt == 0) { ++ rwnx_hw->roc_cookie_cnt = 1; ++ } ++ ++ /* Free the allocated RoC element */ ++ kfree(roc_elem); ++ rwnx_hw->roc_elem = NULL; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ return 0; ++} ++ ++static inline int rwnx_rx_p2p_vif_ps_change_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ int vif_idx = ((struct mm_p2p_vif_ps_change_ind *)msg->param)->vif_index; ++ int ps_state = ((struct mm_p2p_vif_ps_change_ind *)msg->param)->ps_state; ++ struct rwnx_vif *vif_entry; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ vif_entry = rwnx_hw->vif_table[vif_idx]; ++ ++ if (vif_entry) { ++ goto found_vif; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ goto exit; ++ ++found_vif: ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (ps_state == MM_PS_MODE_OFF) { ++ // Start TX queues for provided VIF ++ rwnx_txq_vif_start(vif_entry, RWNX_TXQ_STOP_VIF_PS, rwnx_hw); ++ tasklet_schedule(&rwnx_hw->task); ++ } else { ++ // Stop TX queues for provided VIF ++ rwnx_txq_vif_stop(vif_entry, RWNX_TXQ_STOP_VIF_PS, rwnx_hw); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++exit: ++ return 0; ++} ++ ++static inline int rwnx_rx_channel_survey_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_channel_survey_ind *ind = (struct mm_channel_survey_ind *)msg->param; ++ // Get the channel index ++ int idx = rwnx_freq_to_idx(rwnx_hw, ind->freq); ++ // Get the survey ++ struct rwnx_survey_info *rwnx_survey; ++ ++ if (idx > ARRAY_SIZE(rwnx_hw->survey)) ++ return 0; ++ ++ rwnx_survey = &rwnx_hw->survey[idx]; ++ ++ // Store the received parameters ++ rwnx_survey->chan_time_ms = ind->chan_time_ms; ++ rwnx_survey->chan_time_busy_ms = ind->chan_time_busy_ms; ++ rwnx_survey->noise_dbm = ind->noise_dbm; ++ rwnx_survey->filled = (SURVEY_INFO_TIME | ++ SURVEY_INFO_TIME_BUSY); ++ ++ if (ind->noise_dbm != 0) { ++ rwnx_survey->filled |= SURVEY_INFO_NOISE_DBM; ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_p2p_noa_upd_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ return 0; ++} ++ ++static inline int rwnx_rx_rssi_status_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_rssi_status_ind *ind = (struct mm_rssi_status_ind *)msg->param; ++ int vif_idx = ind->vif_index; ++ bool rssi_status = ind->rssi_status; ++ ++ struct rwnx_vif *vif_entry; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++vif_entry = rwnx_hw->vif_table[vif_idx]; ++ if (vif_entry) { ++ cfg80211_cqm_rssi_notify(vif_entry->ndev, ++ rssi_status ? NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW : ++ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, ++ ind->rssi, GFP_ATOMIC); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_pktloss_notify_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct mm_pktloss_ind *ind = (struct mm_pktloss_ind *)msg->param; ++ struct rwnx_vif *vif_entry; ++ int vif_idx = ind->vif_index; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ vif_entry = rwnx_hw->vif_table[vif_idx]; ++ if (vif_entry) { ++ cfg80211_cqm_pktloss_notify(vif_entry->ndev, (const u8 *)ind->mac_addr.array, ++ ind->num_packets, GFP_ATOMIC); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ return 0; ++} ++ ++static inline int rwnx_radar_detect_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct radar_pulse_array_desc *pulses = (struct radar_pulse_array_desc *)msg->param; ++ int i; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ //printk("%s\n", __func__); ++ ++ if(pulses->cnt == 0) { ++ printk("cnt error\n"); ++ return -1; ++ } ++ ++ if(rwnx_radar_detection_is_enable(&rwnx_hw->radar, pulses->idx)) { ++ for(i=0; icnt; i++) { ++ struct rwnx_radar_pulses *p = &rwnx_hw->radar.pulses[pulses->idx]; ++ ++ p->buffer[p->index] = pulses->pulse[i]; ++ p->index = (p->index + 1)%RWNX_RADAR_PULSE_MAX; ++ if(p->count < RWNX_RADAR_PULSE_MAX) ++ p->count++; ++ //printk("pulse=%x\n", pulses->pulse[i]); ++ } ++ ++ if(!work_pending(&rwnx_hw->radar.detection_work)) ++ schedule_work(&rwnx_hw->radar.detection_work); ++ } else ++ printk("not enable\n"); ++ ++ return 0; ++} ++ ++static inline int rwnx_apm_staloss_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_apm_staloss_ind *ind = (struct mm_apm_staloss_ind *)msg->param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ memcpy(rwnx_hw->sta_mac_addr, ind->mac_addr, 6); ++ rwnx_hw->apm_vif_idx = ind->vif_idx; ++ ++ queue_work(rwnx_hw->apmStaloss_wq, &rwnx_hw->apmStalossWork); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SDIO_BT ++static inline int rwnx_bt_recv_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_bt_recv_ind *ind = (struct mm_bt_recv_ind *)msg->param; ++ ++ bt_sdio_recv(ind->bt_data,ind->data_len); ++ return 0; ++} ++#endif ++ ++static inline int rwnx_rx_csa_counter_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_csa_counter_ind *ind = (struct mm_csa_counter_ind *)msg->param; ++ struct rwnx_vif *vif; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ if (vif->vif_index == ind->vif_index) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (vif->ap.csa) ++ vif->ap.csa->count = ind->csa_count; ++ else ++ netdev_err(vif->ndev, "CSA counter update but no active CSA"); ++ ++#endif ++ } ++ ++ return 0; ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline int rwnx_rx_csa_finish_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_csa_finish_ind *ind = (struct mm_csa_finish_ind *)msg->param; ++ struct rwnx_vif *vif; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ if (vif->vif_index == ind->vif_index) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) { ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP || ++ RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_GO) { ++ if (vif->ap.csa) { ++ vif->ap.csa->status = ind->status; ++ vif->ap.csa->ch_idx = ind->chan_idx; ++ schedule_work(&vif->ap.csa->work); ++ } else ++ netdev_err(vif->ndev, "CSA finish indication but no active CSA"); ++ } else { ++ if (ind->status == 0) { ++ rwnx_chanctx_unlink(vif); ++ rwnx_chanctx_link(vif, ind->chan_idx, NULL); ++ if (rwnx_hw->cur_chanctx == ind->chan_idx) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ rwnx_txq_vif_start(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } else ++ rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_csa_traffic_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_csa_traffic_ind *ind = (struct mm_csa_traffic_ind *)msg->param; ++ struct rwnx_vif *vif; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ if (vif->vif_index == ind->vif_index) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) { ++ if (ind->enable) ++ rwnx_txq_vif_start(vif, RWNX_TXQ_STOP_CSA, rwnx_hw); ++ else ++ rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CSA, rwnx_hw); ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_ps_change_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_ps_change_ind *ind = (struct mm_ps_change_ind *)msg->param; ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[ind->sta_idx]; ++ ++ if (ind->sta_idx >= (NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX)) { ++ wiphy_err(rwnx_hw->wiphy, "Invalid sta index reported by fw %d\n", ++ ind->sta_idx); ++ return 1; ++ } ++ ++ netdev_dbg(rwnx_hw->vif_table[sta->vif_idx]->ndev, ++ "Sta %d, change PS mode to %s", sta->sta_idx, ++ ind->ps_state ? "ON" : "OFF"); ++ ++ if (sta->valid) { ++ rwnx_ps_bh_enable(rwnx_hw, sta, ind->ps_state); ++ } else if (rwnx_hw->adding_sta) { ++ sta->ps.active = ind->ps_state ? true : false; ++ } else { ++ if (rwnx_hw->vif_table[sta->vif_idx] && rwnx_hw->vif_table[sta->vif_idx]->ndev) ++ netdev_err(rwnx_hw->vif_table[sta->vif_idx]->ndev, ++ "Ignore PS mode change on invalid sta\n"); ++ } ++ ++ return 0; ++} ++ ++ ++static inline int rwnx_rx_traffic_req_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_traffic_req_ind *ind = (struct mm_traffic_req_ind *)msg->param; ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[ind->sta_idx]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ netdev_dbg(rwnx_hw->vif_table[sta->vif_idx]->ndev, ++ "Sta %d, asked for %d pkt", sta->sta_idx, ind->pkt_cnt); ++ ++ rwnx_ps_bh_traffic_req(rwnx_hw, sta, ind->pkt_cnt, ++ ind->uapsd ? UAPSD_ID : LEGACY_PS_ID); ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from SCAN task ++ **************************************************************************/ ++#if 0 ++static inline int rwnx_rx_scan_done_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = false, ++ }; ++#endif ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_ipc_elem_var_deallocs(rwnx_hw, &rwnx_hw->scan_ie); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ ieee80211_scan_completed(rwnx_hw->hw, &info); ++#else ++ ieee80211_scan_completed(rwnx_hw->hw, false); ++#endif ++ ++ return 0; ++} ++#endif ++ ++/*************************************************************************** ++ * Messages from SCANU task ++ **************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++extern uint8_t scanning; ++static inline int rwnx_rx_scanu_start_cfm(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (rwnx_hw->scan_request ++#ifdef CONFIG_SCHED_SCAN ++ && !rwnx_hw->is_sched_scan ++#endif//CONFIG_SCHED_SCAN ++ ) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = false, ++ }; ++ ++ cfg80211_scan_done(rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(rwnx_hw->scan_request, false); ++#endif ++ } ++ ++#ifdef CONFIG_SCHED_SCAN ++ if(rwnx_hw->is_sched_scan){ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ AICWFDBG(LOGINFO, "%s cfg80211_sched_scan_results \r\n", __func__); ++ cfg80211_sched_scan_results(rwnx_hw->scan_request->wiphy, ++ rwnx_hw->sched_scan_req->reqid); ++#else ++ cfg80211_sched_scan_results(rwnx_hw->sched_scan_req->wiphy); ++#endif ++ kfree(rwnx_hw->scan_request); ++ rwnx_hw->is_sched_scan = false; ++ } ++#endif//CONFIG_SCHED_SCAN ++ ++ rwnx_hw->scan_request = NULL; ++ scanning = 0; ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_scanu_result_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct cfg80211_bss *bss = NULL; ++ struct ieee80211_channel *chan; ++ struct scanu_result_ind *ind = (struct scanu_result_ind *)msg->param; ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)ind->payload; ++ u64 tsf; ++ u8 *ie; ++ size_t ielen; ++ u16 capability, beacon_interval; ++ u16 len = ind->length; ++ ++ chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq); ++ ++ if (chan != NULL) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ struct timespec ts; ++ get_monotonic_boottime(&ts); ++ tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000); ++ mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000) + ts.tv_nsec/1000; ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0) ++ struct timespec ts; ++ ts = ktime_to_timespec(ktime_get_boottime()); ++ tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000); ++ mgmt->u.probe_resp.timestamp = tsf; ++#else ++ struct timespec64 ts; ++ ts = ktime_to_timespec64(ktime_get_boottime()); ++ tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000); ++ mgmt->u.probe_resp.timestamp = tsf; ++#endif ++ ie = mgmt->u.probe_resp.variable; ++ ielen = len - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); ++ beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); ++ capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); ++ /* framework use system bootup time */ ++ bss = cfg80211_inform_bss(rwnx_hw->wiphy, chan, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) ++ CFG80211_BSS_FTYPE_UNKNOWN, ++#endif ++ mgmt->bssid, tsf, capability, beacon_interval, ++ ie, ielen, ind->rssi * 100, GFP_ATOMIC); ++ } ++ ++ if (bss != NULL) ++ cfg80211_put_bss(rwnx_hw->wiphy, bss); ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from ME task ++ **************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline int rwnx_rx_me_tkip_mic_failure_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct me_tkip_mic_failure_ind *ind = (struct me_tkip_mic_failure_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct net_device *dev = rwnx_vif->ndev; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ cfg80211_michael_mic_failure(dev, (u8 *)&ind->addr, (ind->ga ? NL80211_KEYTYPE_GROUP : ++ NL80211_KEYTYPE_PAIRWISE), ind->keyid, ++ (u8 *)&ind->tsc, GFP_ATOMIC); ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_me_tx_credits_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct me_tx_credits_update_ind *ind = (struct me_tx_credits_update_ind *)msg->param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_txq_credit_update(rwnx_hw, ind->sta_idx, ind->tid, ind->credits); ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from SM task ++ **************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct sm_connect_ind *ind = (struct sm_connect_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct net_device *dev = rwnx_vif->ndev; ++ const u8 *req_ie, *rsp_ie; ++ const u8 *extcap_ie; ++ const struct ieee_types_extcap *extcap; ++ struct ieee80211_channel *chan; ++ //struct cfg80211_bss *bss = NULL; ++ struct wireless_dev *wdev = NULL; ++ //int retry_counter = 10; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ wdev = dev->ieee80211_ptr; ++ ++ /* Retrieve IE addresses and lengths */ ++ req_ie = (const u8 *)ind->assoc_ie_buf; ++ rsp_ie = req_ie + ind->assoc_req_ie_len; ++ ++ // Fill-in the AP information ++ AICWFDBG(LOGINFO, "%s ind->status_code:%d \r\n", __func__, ind->status_code); ++ ++ if (ind->status_code == 0) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[ind->ap_idx]; ++ u8 txq_status; ++ struct cfg80211_chan_def chandef; ++ ++ sta->valid = true; ++ sta->sta_idx = ind->ap_idx; ++ sta->ch_idx = ind->ch_idx; ++ sta->vif_idx = ind->vif_idx; ++ sta->vlan_idx = sta->vif_idx; ++ sta->qos = ind->qos; ++ sta->acm = ind->acm; ++ sta->ps.active = false; ++ sta->aid = ind->aid; ++ sta->band = ind->band;//ind->chan.band; ++ sta->width = ind->width;//ind->chan.type; ++ sta->center_freq = ind->center_freq;//ind->chan.prim20_freq; ++ sta->center_freq1 = ind->center_freq1;//ind->chan.center1_freq; ++ sta->center_freq2 = ind->center_freq2;//ind->chan.center2_freq; ++ rwnx_vif->sta.ap = sta; ++ chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq);//ind->chan.prim20_freq); ++ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); ++ if (!rwnx_hw->mod_params->ht_on) ++ chandef.width = NL80211_CHAN_WIDTH_20_NOHT; ++ else ++ chandef.width = chnl2bw[ind->width];//[ind->chan.type]; ++ chandef.center_freq1 = ind->center_freq1;//ind->chan.center1_freq; ++ chandef.center_freq2 = ind->center_freq2;//ind->chan.center2_freq; ++ rwnx_chanctx_link(rwnx_vif, ind->ch_idx, &chandef); ++ memcpy(sta->mac_addr, ind->bssid.array, ETH_ALEN); ++ if (ind->ch_idx == rwnx_hw->cur_chanctx) { ++ txq_status = 0; ++ } else { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ memcpy(sta->ac_param, ind->ac_param, sizeof(sta->ac_param)); ++ rwnx_txq_sta_init(rwnx_hw, sta, txq_status); ++ rwnx_txq_tdls_vif_init(rwnx_vif); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, sta); ++#endif ++ rwnx_mu_group_sta_init(sta, NULL); ++ /* Look for TDLS Channel Switch Prohibited flag in the Extended Capability ++ * Information Element*/ ++ extcap_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, rsp_ie, ind->assoc_rsp_ie_len); ++ if (extcap_ie && extcap_ie[1] >= 5) { ++ extcap = (void *)(extcap_ie); ++ rwnx_vif->tdls_chsw_prohibited = extcap->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED; ++ } ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ if (chan->flags & IEEE80211_CHAN_RADAR) ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_REPORT, ++ RWNX_RADAR_RIU); ++#endif ++ ++ if (rwnx_vif->wep_enabled) ++ rwnx_vif->wep_auth_err = false; ++ ++#ifdef CONFIG_RWNX_BFMER ++ /* If Beamformer feature is activated, check if features can be used ++ * with the new peer device ++ */ ++ if (rwnx_hw->mod_params->bfmer) { ++ const u8 *vht_capa_ie; ++ const struct ieee80211_vht_cap *vht_cap; ++ ++ do { ++ /* Look for VHT Capability Information Element */ ++ vht_capa_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, rsp_ie, ++ ind->assoc_rsp_ie_len); ++ ++ /* Stop here if peer device does not support VHT */ ++ if (!vht_capa_ie) { ++ break; ++ } ++ ++ vht_cap = (const struct ieee80211_vht_cap *)(vht_capa_ie + 2); ++ ++ /* Send MM_BFMER_ENABLE_REQ message if needed */ ++ rwnx_send_bfmer_enable(rwnx_hw, sta, vht_cap); ++ } while (0); ++ } ++#endif //(CONFIG_RWNX_BFMER) ++ ++#ifdef CONFIG_RWNX_MON_DATA ++ // If there are 1 sta and 1 monitor interface active at the same time then ++ // monitor interface channel context is always the same as the STA interface. ++ // This doesn't work with 2 STA interfaces but we don't want to support it. ++ if (rwnx_hw->monitor_vif != RWNX_INVALID_VIF) { ++ struct rwnx_vif *rwnx_mon_vif = rwnx_hw->vif_table[rwnx_hw->monitor_vif]; ++ rwnx_chanctx_unlink(rwnx_mon_vif); ++ rwnx_chanctx_link(rwnx_mon_vif, ind->ch_idx, NULL); ++ } ++#endif ++ //atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ } else if (ind->status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { ++ if (rwnx_vif->wep_enabled) { ++ rwnx_vif->wep_auth_err = true; ++ AICWFDBG(LOGINFO, "con ind wep_auth_err %d\n", rwnx_vif->wep_auth_err); ++ } ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ }else{ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ } ++ ++ AICWFDBG(LOGINFO, "%s ind->roamed:%d ind->status_code:%d rwnx_vif->drv_conn_state:%d\r\n", ++ __func__, ++ ind->roamed, ++ ind->status_code, ++ (int)atomic_read(&rwnx_vif->drv_conn_state)); ++ ++ if(ind->status_code == 0 && (int)atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTING){ ++ AICWFDBG(LOGINFO, "%s the disconnection has been requested, return it\r\n", __func__); ++ goto exit; ++ } ++ ++ if (!ind->roamed){//not roaming ++ cfg80211_connect_result(dev, (const u8 *)ind->bssid.array, req_ie, ++ ind->assoc_req_ie_len, rsp_ie, ++ ind->assoc_rsp_ie_len, ind->status_code, ++ GFP_ATOMIC); ++ if (ind->status_code == 0) { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ AICWFDBG(LOGINFO, "%s cfg80211_connect_result pass, rwnx_vif->drv_conn_state:%d\r\n", ++ __func__, ++ (int)atomic_read(&rwnx_vif->drv_conn_state)); ++ } else { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ } ++ ++ }else {//roaming ++ if(ind->status_code != 0){ ++ AICWFDBG(LOGINFO, "%s roaming fail to notify disconnect \r\n", __func__); ++ cfg80211_disconnected(dev, 0, NULL, 0,1, GFP_ATOMIC); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ }else{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ struct cfg80211_roam_info info; ++ memset(&info, 0, sizeof(info)); ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ if (rwnx_vif->ch_index < NX_CHAN_CTXT_CNT) ++ info.links[0].channel = rwnx_hw->chanctx_table[rwnx_vif->ch_index].chan_def.chan; ++ info.links[0].bssid = (const u8 *)ind->bssid.array; ++#else ++ if (rwnx_vif->ch_index < NX_CHAN_CTXT_CNT) ++ info.channel = rwnx_hw->chanctx_table[rwnx_vif->ch_index].chan_def.chan; ++ info.bssid = (const u8 *)ind->bssid.array; ++#endif ++ info.req_ie = req_ie; ++ info.req_ie_len = ind->assoc_req_ie_len; ++ info.resp_ie = rsp_ie; ++ info.resp_ie_len = ind->assoc_rsp_ie_len; ++ cfg80211_roamed(dev, &info, GFP_ATOMIC); ++#else ++ chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq); ++ cfg80211_roamed(dev ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE) ++ , chan ++#endif ++ , (const u8 *)ind->bssid.array ++ , req_ie ++ , ind->assoc_req_ie_len ++ , rsp_ie ++ , ind->assoc_rsp_ie_len ++ , GFP_ATOMIC); ++ ++#endif /*LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)*/ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ } ++ rwnx_vif->sta.is_roam = false; ++ } ++ ++ if (ind->status_code == 0) { ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ } ++ ++exit: ++ rwnx_vif->sta.is_roam = false; ++ return 0; ++} ++ ++void rwnx_cfg80211_unlink_bss(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif){ ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ struct cfg80211_bss *bss = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/, ++ rwnx_vif->sta.bssid, rwnx_vif->sta.ssid, ++ rwnx_vif->sta.ssid_len, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) ++ IEEE80211_BSS_TYPE_ESS, ++ IEEE80211_PRIVACY(true));//temp set true ++#else ++ WLAN_CAPABILITY_ESS, ++ WLAN_CAPABILITY_ESS); ++#endif ++ ++ if (bss) { ++ cfg80211_unlink_bss(wiphy, bss); ++ AICWFDBG(LOGINFO, "%s(): cfg80211_unlink %s!!\n", __func__, rwnx_vif->sta.ssid); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) ++ cfg80211_put_bss(wiphy, bss); ++#else ++ cfg80211_put_bss(bss); ++#endif ++ }else{ ++ AICWFDBG(LOGINFO, "%s(): cfg80211_unlink error %s!!\n", __func__, rwnx_vif->sta.ssid); ++ } ++} ++ ++extern u8 dhcped; ++static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct sm_disconnect_ind *ind = (struct sm_disconnect_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct net_device *dev; ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *tmp; ++ u8 *macaddr; ++ struct aicwf_rx_priv *rx_priv; ++#endif ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ AICWFDBG(LOGINFO, "%s reason code:%d \r\n", __func__, ind->reason_code); ++ ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTED){ ++ AICWFDBG(LOGINFO, "%s, is already disconnected, drop disconnect ind", __func__); ++ return 0; ++ } ++ ++ dhcped = 0; ++ ++ if(!rwnx_vif) ++ return 0; ++ dev = rwnx_vif->ndev; ++ ++ if (rwnx_vif->sta.is_roam == false) { ++ rwnx_cfg80211_unlink_bss(rwnx_hw, rwnx_vif); ++ } else { ++ AICWFDBG(LOGINFO, "%s roaming no rwnx_cfg80211_unlink_bss \r\n", __func__); ++ } ++ ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.ap); ++#endif ++ ++ #ifdef CONFIG_BR_SUPPORT ++ struct rwnx_vif *vif = netdev_priv(dev); ++ /* clear bridge database */ ++ nat25_db_cleanup(rwnx_vif); ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ rwnx_hw->is_p2p_connected = 0; ++ /* if vif is not up, rwnx_close has already been called */ ++ if (rwnx_vif->up) { ++ if (!ind->ft_over_ds && !ind->reassoc) { ++ cfg80211_disconnected(dev, ind->reason_code, NULL, 0, ++ (ind->reason_code < 1), GFP_ATOMIC); ++ } ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ } ++ ++#ifdef CONFIG_RWNX_BFMER ++ /* Disable Beamformer if supported */ ++ rwnx_bfmer_report_del(rwnx_hw, rwnx_vif->sta.ap); ++#endif //(CONFIG_RWNX_BFMER) ++ ++#ifdef AICWF_RX_REORDER ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv = rwnx_hw->sdiodev->rx_priv; ++#else ++ rx_priv = rwnx_hw->usbdev->rx_priv; ++#endif ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ macaddr = (u8*)rwnx_vif->ndev->dev_addr; ++ printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0], macaddr[1], macaddr[2], \ ++ macaddr[3], macaddr[4], macaddr[5]); ++ ++ //spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry_safe(reord_info, tmp, &rx_priv->stas_reord_list, list) { ++ macaddr = (u8*)rwnx_vif->ndev->dev_addr; ++ printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0], reord_info->mac_addr[1], reord_info->mac_addr[2], \ ++ reord_info->mac_addr[3], reord_info->mac_addr[4], reord_info->mac_addr[5]); ++ if (!memcmp(reord_info->mac_addr, macaddr, 6)) { ++ reord_deinit_sta(rx_priv, reord_info); ++ break; ++ } ++ } ++ //spin_unlock_bh(&rx_priv->stas_reord_lock); ++ } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { ++ BUG();//should be not here: del_sta function ++ } ++#endif ++ ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_vif->sta.ap); ++ rwnx_txq_tdls_vif_deinit(rwnx_vif); ++ #if 0 ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.ap); ++ #endif ++ rwnx_vif->sta.ap->valid = false; ++ rwnx_vif->sta.ap = NULL; ++ rwnx_external_auth_disable(rwnx_vif); ++ rwnx_chanctx_unlink(rwnx_vif); ++ ++ //msleep(200); ++ if (rwnx_vif->sta.is_roam == false) { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_sm_external_auth_required_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct sm_external_auth_required_ind *ind = ++ (struct sm_external_auth_required_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ struct net_device *dev = rwnx_vif->ndev; ++ struct cfg80211_external_auth_params params; ++ int ret = 0; ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ int retry_counter = 10; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ memset((void*)¶ms, 0, sizeof(struct cfg80211_external_auth_params)); ++ ++ params.action = NL80211_EXTERNAL_AUTH_START; ++ memcpy(params.bssid, ind->bssid.array, ETH_ALEN); ++ params.ssid.ssid_len = ind->ssid.length; ++ memcpy(params.ssid.ssid, ind->ssid.array, ++ min_t(size_t, ind->ssid.length, sizeof(params.ssid.ssid))); ++ params.key_mgmt_suite = ind->akm; ++ ++ while (wdev->conn_owner_nlportid == 0) { ++ AICWFDBG(LOGINFO, "%s WARNING conn_owner_nlportid = 0, msleep 100ms.\r\n", __func__); ++ msleep(100); ++ retry_counter--; ++ if (retry_counter == 0) { ++ break; ++ } ++ } ++ AICWFDBG(LOGINFO, "%s wdev->conn_owner_nlportid:%d \r\n", __func__, (int)wdev->conn_owner_nlportid); ++ ++ if ((ind->vif_idx > NX_VIRT_DEV_MAX) || !rwnx_vif->up || ++ (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_STATION) || ++ (ret = cfg80211_external_auth_request(dev, ¶ms, GFP_ATOMIC))) { ++ wiphy_err(rwnx_hw->wiphy, "Failed to start external auth on vif %d, rwnx_vif->up %d, iftype:%d, ret %d", ++ ind->vif_idx, rwnx_vif->up, RWNX_VIF_TYPE(rwnx_vif), ret); ++ rwnx_send_sm_external_auth_required_rsp(rwnx_hw, rwnx_vif, ++ WLAN_STATUS_UNSPECIFIED_FAILURE); ++ return 0; ++ } ++ ++ rwnx_external_auth_enable(rwnx_vif); ++#else ++ rwnx_send_sm_external_auth_required_rsp(rwnx_hw, rwnx_vif, ++ WLAN_STATUS_UNSPECIFIED_FAILURE); ++#endif ++ return 0; ++} ++ ++ ++static inline int rwnx_rx_mesh_path_create_cfm(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_path_create_cfm *cfm = (struct mesh_path_create_cfm *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[cfm->vif_idx]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Check we well have a Mesh Point Interface */ ++ if (rwnx_vif && (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT)) { ++ rwnx_vif->ap.create_path = false; ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_mesh_peer_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_peer_update_ind *ind = (struct mesh_peer_update_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct rwnx_sta *rwnx_sta = &rwnx_hw->sta_table[ind->sta_idx]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if ((ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) || ++ (rwnx_vif && (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT)) || ++ (ind->sta_idx >= NX_REMOTE_STA_MAX)) ++ return 1; ++ ++ /* Check we well have a Mesh Point Interface */ ++ if (!rwnx_vif->user_mpm) { ++ /* Check if peer link has been established or lost */ ++ if (ind->estab) { ++ if (!rwnx_sta->valid) { ++ u8 txq_status; ++ ++ rwnx_sta->valid = true; ++ rwnx_sta->sta_idx = ind->sta_idx; ++ rwnx_sta->ch_idx = rwnx_vif->ch_index; ++ rwnx_sta->vif_idx = ind->vif_idx; ++ rwnx_sta->vlan_idx = rwnx_sta->vif_idx; ++ rwnx_sta->ps.active = false; ++ rwnx_sta->qos = true; ++ rwnx_sta->aid = ind->sta_idx + 1; ++ //rwnx_sta->acm = ind->acm; ++ memcpy(rwnx_sta->mac_addr, ind->peer_addr.array, ETH_ALEN); ++ ++ rwnx_chanctx_link(rwnx_vif, rwnx_sta->ch_idx, NULL); ++ ++ /* Add the station in the list of VIF's stations */ ++ INIT_LIST_HEAD(&rwnx_sta->list); ++ list_add_tail(&rwnx_sta->list, &rwnx_vif->ap.sta_list); ++ ++ /* Initialize the TX queues */ ++ if (rwnx_sta->ch_idx == rwnx_hw->cur_chanctx) { ++ txq_status = 0; ++ } else { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ ++ rwnx_txq_sta_init(rwnx_hw, rwnx_sta, txq_status); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, rwnx_sta); ++#endif ++#ifdef CONFIG_RWNX_BFMER ++ // TODO: update indication to contains vht capabilties ++ if (rwnx_hw->mod_params->bfmer) ++ rwnx_send_bfmer_enable(rwnx_hw, rwnx_sta, NULL); ++ ++ rwnx_mu_group_sta_init(rwnx_sta, NULL); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ } else { ++ WARN_ON(0); ++ } ++ } else { ++ if (rwnx_sta->valid) { ++ rwnx_sta->ps.active = false; ++ rwnx_sta->valid = false; ++ ++ /* Remove the station from the list of VIF's station */ ++ list_del_init(&rwnx_sta->list); ++ ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_sta); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_sta); ++#endif ++ } else { ++ WARN_ON(0); ++ } ++ } ++ } else { ++ if (!ind->estab && rwnx_sta->valid) { ++ /* There is no way to inform upper layer for lost of peer, still ++ clean everything in the driver */ ++ rwnx_sta->ps.active = false; ++ rwnx_sta->valid = false; ++ ++ /* Remove the station from the list of VIF's station */ ++ list_del_init(&rwnx_sta->list); ++ ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_sta); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_sta); ++#endif ++ } else { ++ WARN_ON(0); ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_mesh_path_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_path_update_ind *ind = (struct mesh_path_update_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct rwnx_mesh_path *mesh_path; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) ++ return 1; ++ ++ if (!rwnx_vif || (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT)) ++ return 0; ++ ++ /* Look for path with provided target address */ ++ list_for_each_entry(mesh_path, &rwnx_vif->ap.mpath_list, list) { ++ if (mesh_path->path_idx == ind->path_idx) { ++ found = true; ++ break; ++ } ++ } ++ ++ /* Check if element has been deleted */ ++ if (ind->delete) { ++ if (found) { ++#ifdef CREATE_TRACE_POINTS ++ trace_mesh_delete_path(mesh_path); ++#endif ++ /* Remove element from list */ ++ list_del_init(&mesh_path->list); ++ /* Free the element */ ++ kfree(mesh_path); ++ } ++ } else { ++ if (found) { ++ // Update the Next Hop STA ++ mesh_path->p_nhop_sta = &rwnx_hw->sta_table[ind->nhop_sta_idx]; ++#ifdef CREATE_TRACE_POINTS ++ trace_mesh_update_path(mesh_path); ++#endif ++ } else { ++ // Allocate a Mesh Path structure ++ mesh_path = (struct rwnx_mesh_path *)kmalloc(sizeof(struct rwnx_mesh_path), GFP_ATOMIC); ++ ++ if (mesh_path) { ++ INIT_LIST_HEAD(&mesh_path->list); ++ ++ mesh_path->path_idx = ind->path_idx; ++ mesh_path->p_nhop_sta = &rwnx_hw->sta_table[ind->nhop_sta_idx]; ++ memcpy(&mesh_path->tgt_mac_addr, &ind->tgt_mac_addr, MAC_ADDR_LEN); ++ ++ // Insert the path in the list of path ++ list_add_tail(&mesh_path->list, &rwnx_vif->ap.mpath_list); ++#ifdef CREATE_TRACE_POINTS ++ trace_mesh_create_path(mesh_path); ++#endif ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_mesh_proxy_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_proxy_update_ind *ind = (struct mesh_proxy_update_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct rwnx_mesh_proxy *mesh_proxy; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) ++ return 1; ++ ++ if (!rwnx_vif || (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT)) ++ return 0; ++ ++ /* Look for path with provided external STA address */ ++ list_for_each_entry(mesh_proxy, &rwnx_vif->ap.proxy_list, list) { ++ if (!memcmp(&ind->ext_sta_addr, &mesh_proxy->ext_sta_addr, ETH_ALEN)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (ind->delete && found) { ++ /* Delete mesh path */ ++ list_del_init(&mesh_proxy->list); ++ kfree(mesh_proxy); ++ } else if (!ind->delete && !found) { ++ /* Allocate a Mesh Path structure */ ++ mesh_proxy = (struct rwnx_mesh_proxy *)kmalloc(sizeof(*mesh_proxy), ++ GFP_ATOMIC); ++ ++ if (mesh_proxy) { ++ INIT_LIST_HEAD(&mesh_proxy->list); ++ ++ memcpy(&mesh_proxy->ext_sta_addr, &ind->ext_sta_addr, MAC_ADDR_LEN); ++ mesh_proxy->local = ind->local; ++ ++ if (!ind->local) { ++ memcpy(&mesh_proxy->proxy_addr, &ind->proxy_mac_addr, MAC_ADDR_LEN); ++ } ++ ++ /* Insert the path in the list of path */ ++ list_add_tail(&mesh_proxy->list, &rwnx_vif->ap.proxy_list); ++ } ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from APM task ++ **************************************************************************/ ++ ++ ++/*************************************************************************** ++ * Messages from DEBUG task ++ **************************************************************************/ ++static inline int rwnx_rx_dbg_error_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_MCU_MESSAGE ++static inline int rwnx_rx_dbg_custmsg_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ dbg_custom_msg_ind_t * ind; ++ char str_msg[32 + 1]; ++ int str_len; ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ind = (dbg_custom_msg_ind_t *)msg->param; ++ str_len = (ind->len < 32) ? ind->len : 32; ++ memcpy(str_msg, (char *)ind->buf, str_len); ++ str_msg[str_len] = '\0'; ++ printk("CustMsgInd: cmd=0x%x, len=%d, str=%s\r\n", ind->cmd, ind->len, str_msg); ++ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++static msg_cb_fct mm_hdlrs[MSG_I(MM_MAX)] = { ++ [MSG_I(MM_CHANNEL_SWITCH_IND)] = rwnx_rx_chan_switch_ind, ++ [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = rwnx_rx_chan_pre_switch_ind, ++ [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = rwnx_rx_remain_on_channel_exp_ind, ++ [MSG_I(MM_PS_CHANGE_IND)] = rwnx_rx_ps_change_ind, ++ [MSG_I(MM_TRAFFIC_REQ_IND)] = rwnx_rx_traffic_req_ind, ++ [MSG_I(MM_P2P_VIF_PS_CHANGE_IND)] = rwnx_rx_p2p_vif_ps_change_ind, ++ [MSG_I(MM_CSA_COUNTER_IND)] = rwnx_rx_csa_counter_ind, ++ [MSG_I(MM_CSA_FINISH_IND)] = rwnx_rx_csa_finish_ind, ++ [MSG_I(MM_CSA_TRAFFIC_IND)] = rwnx_rx_csa_traffic_ind, ++ [MSG_I(MM_CHANNEL_SURVEY_IND)] = rwnx_rx_channel_survey_ind, ++ [MSG_I(MM_P2P_NOA_UPD_IND)] = rwnx_rx_p2p_noa_upd_ind, ++ [MSG_I(MM_RSSI_STATUS_IND)] = rwnx_rx_rssi_status_ind, ++ [MSG_I(MM_PKTLOSS_IND)] = rwnx_rx_pktloss_notify_ind, ++ [MSG_I(MM_APM_STALOSS_IND)] = rwnx_apm_staloss_ind, ++ [MSG_I(MM_RADAR_DETECT_IND)] = rwnx_radar_detect_ind, ++}; ++ ++static msg_cb_fct scan_hdlrs[MSG_I(SCANU_MAX)] = { ++ [MSG_I(SCANU_START_CFM)] = rwnx_rx_scanu_start_cfm, ++ [MSG_I(SCANU_RESULT_IND)] = rwnx_rx_scanu_result_ind, ++}; ++ ++static msg_cb_fct me_hdlrs[MSG_I(ME_MAX)] = { ++ [MSG_I(ME_TKIP_MIC_FAILURE_IND)] = rwnx_rx_me_tkip_mic_failure_ind, ++ [MSG_I(ME_TX_CREDITS_UPDATE_IND)] = rwnx_rx_me_tx_credits_update_ind, ++}; ++ ++static msg_cb_fct sm_hdlrs[MSG_I(SM_MAX)] = { ++ [MSG_I(SM_CONNECT_IND)] = rwnx_rx_sm_connect_ind, ++ [MSG_I(SM_DISCONNECT_IND)] = rwnx_rx_sm_disconnect_ind, ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_IND)] = rwnx_rx_sm_external_auth_required_ind, ++}; ++ ++static msg_cb_fct apm_hdlrs[MSG_I(APM_MAX)] = { ++}; ++ ++static msg_cb_fct mesh_hdlrs[MSG_I(MESH_MAX)] = { ++ [MSG_I(MESH_PATH_CREATE_CFM)] = rwnx_rx_mesh_path_create_cfm, ++ [MSG_I(MESH_PEER_UPDATE_IND)] = rwnx_rx_mesh_peer_update_ind, ++ [MSG_I(MESH_PATH_UPDATE_IND)] = rwnx_rx_mesh_path_update_ind, ++ [MSG_I(MESH_PROXY_UPDATE_IND)] = rwnx_rx_mesh_proxy_update_ind, ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = { ++ [MSG_I(DBG_ERROR_IND)] = rwnx_rx_dbg_error_ind, ++#ifdef CONFIG_MCU_MESSAGE ++ [MSG_I(DBG_CUSTOM_MSG_IND)] = rwnx_rx_dbg_custmsg_ind, ++#endif ++}; ++ ++static msg_cb_fct tdls_hdlrs[MSG_I(TDLS_MAX)] = { ++ [MSG_I(TDLS_CHAN_SWITCH_CFM)] = rwnx_rx_tdls_chan_switch_cfm, ++ [MSG_I(TDLS_CHAN_SWITCH_IND)] = rwnx_rx_tdls_chan_switch_ind, ++ [MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = rwnx_rx_tdls_chan_switch_base_ind, ++ [MSG_I(TDLS_PEER_PS_IND)] = rwnx_rx_tdls_peer_ps_ind, ++#ifdef CONFIG_SDIO_BT ++ [MSG_I(TDLS_SDIO_BT_RECV_IND)] = rwnx_bt_recv_ind, ++#endif ++}; ++ ++static msg_cb_fct *msg_hdlrs[] = { ++ [TASK_MM] = mm_hdlrs, ++ [TASK_DBG] = dbg_hdlrs, ++#ifdef CONFIG_RWNX_FULLMAC ++ [TASK_TDLS] = tdls_hdlrs, ++ [TASK_SCANU] = scan_hdlrs, ++ [TASK_ME] = me_hdlrs, ++ [TASK_SM] = sm_hdlrs, ++ [TASK_APM] = apm_hdlrs, ++ [TASK_MESH] = mesh_hdlrs, ++#endif /* CONFIG_RWNX_FULLMAC */ ++}; ++ ++/** ++ * ++ */ ++void rwnx_rx_handle_msg(struct rwnx_hw *rwnx_hw, struct ipc_e2a_msg *msg) ++{ ++ AICWFDBG(LOGDEBUG, "%s msg->id:0x%x \r\n", __func__, msg->id); ++ ++ rwnx_hw->cmd_mgr->msgind(rwnx_hw->cmd_mgr, msg, ++ msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]); ++} ++ ++void rwnx_rx_handle_print(struct rwnx_hw *rwnx_hw, u8 *msg, u32 len) ++{ ++ u8 *data_end = NULL; ++ (void)data_end; ++ ++ if (!rwnx_hw || !rwnx_hw->fwlog_en) { ++ pr_err("FWLOG-OVFL: %s", msg); ++ return; ++ } ++ ++ printk("FWLOG: %s", msg); ++ ++#ifdef CONFIG_RWNX_DEBUGFS ++ data_end = rwnx_hw->debugfs.fw_log.buf.dataend; ++ ++ if (!rwnx_hw->debugfs.fw_log.buf.data) ++ return ; ++ ++ //printk("end=%lx, len=%d\n", (unsigned long)rwnx_hw->debugfs.fw_log.buf.end, len); ++ ++ spin_lock_bh(&rwnx_hw->debugfs.fw_log.lock); ++ ++ if (rwnx_hw->debugfs.fw_log.buf.end + len > data_end) { ++ int rem = data_end - rwnx_hw->debugfs.fw_log.buf.end; ++ memcpy(rwnx_hw->debugfs.fw_log.buf.end, msg, rem); ++ memcpy(rwnx_hw->debugfs.fw_log.buf.data, &msg[rem], len - rem); ++ rwnx_hw->debugfs.fw_log.buf.end = rwnx_hw->debugfs.fw_log.buf.data + (len - rem); ++ } else { ++ memcpy(rwnx_hw->debugfs.fw_log.buf.end, msg, len); ++ rwnx_hw->debugfs.fw_log.buf.end += len; ++ } ++ ++ rwnx_hw->debugfs.fw_log.buf.size += len; ++ if (rwnx_hw->debugfs.fw_log.buf.size > FW_LOG_SIZE) ++ rwnx_hw->debugfs.fw_log.buf.size = FW_LOG_SIZE; ++ ++ spin_unlock_bh(&rwnx_hw->debugfs.fw_log.lock); ++#endif ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h +new file mode 100644 +index 000000000000..b5556d160ff0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h +@@ -0,0 +1,19 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_msg_rx.h ++ * ++ * @brief RX function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_MSG_RX_H_ ++#define _RWNX_MSG_RX_H_ ++ ++void rwnx_rx_handle_msg(struct rwnx_hw *rwnx_hw, struct ipc_e2a_msg *msg); ++void rwnx_rx_handle_print(struct rwnx_hw *rwnx_hw, u8 *msg, u32 len); ++ ++#endif /* _RWNX_MSG_RX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c +new file mode 100644 +index 000000000000..849a8ea709e3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c +@@ -0,0 +1,4185 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_msg_tx.c ++ * ++ * @brief TX function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_msg_tx.h" ++#include "rwnx_mod_params.h" ++#include "reg_access.h" ++#ifdef CONFIG_RWNX_BFMER ++#include "rwnx_bfmer.h" ++#endif //(CONFIG_RWNX_BFMER) ++#include "rwnx_compat.h" ++#include "rwnx_cmds.h" ++#include "aicwf_txrxif.h" ++#include "rwnx_strs.h" ++#include "rwnx_main.h" ++#include "rwnx_wakelock.h" ++ ++const struct mac_addr mac_addr_bcst = {{0xFFFF, 0xFFFF, 0xFFFF}}; ++ ++/* Default MAC Rx filters that can be changed by mac80211 ++ * (via the configure_filter() callback) */ ++#define RWNX_MAC80211_CHANGEABLE ( \ ++ NXMAC_ACCEPT_BA_BIT | \ ++ NXMAC_ACCEPT_BAR_BIT | \ ++ NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT | \ ++ NXMAC_ACCEPT_PROBE_REQ_BIT | \ ++ NXMAC_ACCEPT_PS_POLL_BIT \ ++ ) ++ ++/* Default MAC Rx filters that cannot be changed by mac80211 */ ++#define RWNX_MAC80211_NOT_CHANGEABLE ( \ ++ NXMAC_ACCEPT_QO_S_NULL_BIT | \ ++ NXMAC_ACCEPT_Q_DATA_BIT | \ ++ NXMAC_ACCEPT_DATA_BIT | \ ++ NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT | \ ++ NXMAC_ACCEPT_MY_UNICAST_BIT | \ ++ NXMAC_ACCEPT_BROADCAST_BIT | \ ++ NXMAC_ACCEPT_BEACON_BIT | \ ++ NXMAC_ACCEPT_PROBE_RESP_BIT \ ++ ) ++ ++/* Default MAC Rx filter */ ++#define RWNX_DEFAULT_RX_FILTER (RWNX_MAC80211_CHANGEABLE | RWNX_MAC80211_NOT_CHANGEABLE) ++ ++const int bw2chnl[] = { ++ [NL80211_CHAN_WIDTH_20_NOHT] = PHY_CHNL_BW_20, ++ [NL80211_CHAN_WIDTH_20] = PHY_CHNL_BW_20, ++ [NL80211_CHAN_WIDTH_40] = PHY_CHNL_BW_40, ++ [NL80211_CHAN_WIDTH_80] = PHY_CHNL_BW_80, ++ [NL80211_CHAN_WIDTH_160] = PHY_CHNL_BW_160, ++ [NL80211_CHAN_WIDTH_80P80] = PHY_CHNL_BW_80P80, ++}; ++ ++const int chnl2bw[] = { ++ [PHY_CHNL_BW_20] = NL80211_CHAN_WIDTH_20, ++ [PHY_CHNL_BW_40] = NL80211_CHAN_WIDTH_40, ++ [PHY_CHNL_BW_80] = NL80211_CHAN_WIDTH_80, ++ [PHY_CHNL_BW_160] = NL80211_CHAN_WIDTH_160, ++ [PHY_CHNL_BW_80P80] = NL80211_CHAN_WIDTH_80P80, ++}; ++ ++#define RWNX_CMD_ARRAY_SIZE 40 ++#define RWNX_CMD_HIGH_WATER_SIZE RWNX_CMD_ARRAY_SIZE/2 ++ ++struct rwnx_cmd cmd_array[RWNX_CMD_ARRAY_SIZE]; ++static spinlock_t cmd_array_lock; ++int cmd_array_index = 0; ++ ++ ++ ++/*****************************************************************************/ ++/* ++ * Parse the ampdu density to retrieve the value in usec, according to the ++ * values defined in ieee80211.h ++ */ ++static inline u8 rwnx_ampdudensity2usec(u8 ampdudensity) ++{ ++ switch (ampdudensity) { ++ case IEEE80211_HT_MPDU_DENSITY_NONE: ++ return 0; ++ /* 1 microsecond is our granularity */ ++ case IEEE80211_HT_MPDU_DENSITY_0_25: ++ case IEEE80211_HT_MPDU_DENSITY_0_5: ++ case IEEE80211_HT_MPDU_DENSITY_1: ++ return 1; ++ case IEEE80211_HT_MPDU_DENSITY_2: ++ return 2; ++ case IEEE80211_HT_MPDU_DENSITY_4: ++ return 4; ++ case IEEE80211_HT_MPDU_DENSITY_8: ++ return 8; ++ case IEEE80211_HT_MPDU_DENSITY_16: ++ return 16; ++ default: ++ return 0; ++ } ++} ++ ++static inline bool use_pairwise_key(struct cfg80211_crypto_settings *crypto) ++{ ++ if ((crypto->cipher_group == WLAN_CIPHER_SUITE_WEP40) || ++ (crypto->cipher_group == WLAN_CIPHER_SUITE_WEP104)) ++ return false; ++ ++ return true; ++} ++ ++static inline bool is_non_blocking_msg(int id) ++{ ++ return ((id == MM_TIM_UPDATE_REQ) || (id == ME_RC_SET_RATE_REQ) || ++ (id == MM_BFMER_ENABLE_REQ) || (id == ME_TRAFFIC_IND_REQ) || ++ (id == TDLS_PEER_TRAFFIC_IND_REQ) || ++ (id == MESH_PATH_CREATE_REQ) || (id == MESH_PROXY_ADD_REQ) || ++ (id == SM_EXTERNAL_AUTH_REQUIRED_RSP)); ++} ++ ++static inline u8_l get_chan_flags(uint32_t flags) ++{ ++ u8_l chan_flags = 0; ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) ++ if (flags & IEEE80211_CHAN_PASSIVE_SCAN) ++ #else ++ if (flags & IEEE80211_CHAN_NO_IR) ++ #endif ++ chan_flags |= CHAN_NO_IR; ++ if (flags & IEEE80211_CHAN_RADAR) ++ chan_flags |= CHAN_RADAR; ++#endif ++ return chan_flags; ++} ++ ++static inline s8_l chan_to_fw_pwr(int power) ++{ ++ return power > 127 ? 127 : (s8_l)power; ++} ++ ++static inline void limit_chan_bw(u8_l *bw, u16_l primary, u16_l *center1) ++{ ++ int oft, new_oft = 10; ++ ++ if (*bw <= PHY_CHNL_BW_40) ++ return; ++ ++ oft = *center1 - primary; ++ *bw = PHY_CHNL_BW_40; ++ ++ if (oft < 0) ++ new_oft = new_oft * -1; ++ if (abs(oft) == 10 || abs(oft) == 50) ++ new_oft = new_oft * -1; ++ ++ *center1 = primary + new_oft; ++} ++ ++struct rwnx_cmd *rwnx_cmd_malloc(void){ ++ struct rwnx_cmd *cmd = NULL; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&cmd_array_lock, flags); ++ ++ for(cmd_array_index = 0; cmd_array_index < RWNX_CMD_ARRAY_SIZE; cmd_array_index++){ ++ if(cmd_array[cmd_array_index].used == 0){ ++ AICWFDBG(LOGTRACE, "%s get cmd_array[%d]:%p \r\n", __func__, cmd_array_index,&cmd_array[cmd_array_index]); ++ cmd = &cmd_array[cmd_array_index]; ++ cmd_array[cmd_array_index].used = 1; ++ break; ++ } ++ } ++ ++ if(cmd_array_index >= RWNX_CMD_HIGH_WATER_SIZE){ ++ AICWFDBG(LOGERROR, "%s cmd(%d) was pending...\r\n", __func__, cmd_array_index); ++ mdelay(100); ++ } ++ ++ if(!cmd){ ++ AICWFDBG(LOGERROR, "%s array is empty...\r\n", __func__); ++ } ++ ++ spin_unlock_irqrestore(&cmd_array_lock, flags); ++ ++ return cmd; ++} ++ ++void rwnx_cmd_free(struct rwnx_cmd *cmd){ ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&cmd_array_lock, flags); ++ cmd->used = 0; ++ AICWFDBG(LOGTRACE, "%s cmd_array[%d]:%p \r\n", __func__, cmd->array_id, cmd); ++ spin_unlock_irqrestore(&cmd_array_lock, flags); ++} ++ ++ ++int rwnx_init_cmd_array(void){ ++ ++ AICWFDBG(LOGTRACE, "%s Enter \r\n", __func__); ++ spin_lock_init(&cmd_array_lock); ++ ++ for(cmd_array_index = 0; cmd_array_index < RWNX_CMD_ARRAY_SIZE; cmd_array_index++){ ++ AICWFDBG(LOGTRACE, "%s cmd_queue[%d]:%p \r\n", __func__, cmd_array_index, &cmd_array[cmd_array_index]); ++ cmd_array[cmd_array_index].used = 0; ++ cmd_array[cmd_array_index].array_id = cmd_array_index; ++ } ++ AICWFDBG(LOGTRACE, "%s Exit \r\n", __func__); ++ ++ return 0; ++} ++ ++void rwnx_free_cmd_array(void){ ++ ++ AICWFDBG(LOGTRACE, "%s Enter \r\n", __func__); ++ ++ for(cmd_array_index = 0; cmd_array_index < RWNX_CMD_ARRAY_SIZE; cmd_array_index++){ ++ cmd_array[cmd_array_index].used = 0; ++ } ++ ++ AICWFDBG(LOGTRACE, "%s Exit \r\n", __func__); ++} ++ ++ ++/** ++ ****************************************************************************** ++ * @brief Allocate memory for a message ++ * ++ * This primitive allocates memory for a message that has to be sent. The memory ++ * is allocated dynamically on the heap and the length of the variable parameter ++ * structure has to be provided in order to allocate the correct size. ++ * ++ * Several additional parameters are provided which will be preset in the message ++ * and which may be used internally to choose the kind of memory to allocate. ++ * ++ * The memory allocated will be automatically freed by the kernel, after the ++ * pointer has been sent to ke_msg_send(). If the message is not sent, it must ++ * be freed explicitly with ke_msg_free(). ++ * ++ * Allocation failure is considered critical and should not happen. ++ * ++ * @param[in] id Message identifier ++ * @param[in] dest_id Destination Task Identifier ++ * @param[in] src_id Source Task Identifier ++ * @param[in] param_len Size of the message parameters to be allocated ++ * ++ * @return Pointer to the parameter member of the ke_msg. If the parameter ++ * structure is empty, the pointer will point to the end of the message ++ * and should not be used (except to retrieve the message pointer or to ++ * send the message) ++ ****************************************************************************** ++ */ ++static inline void *rwnx_msg_zalloc(lmac_msg_id_t const id, ++ lmac_task_id_t const dest_id, ++ lmac_task_id_t const src_id, ++ uint16_t const param_len) ++{ ++ struct lmac_msg *msg; ++ gfp_t flags; ++ ++// if (is_non_blocking_msg(id) && (in_softirq()||in_atomic())) ++ flags = GFP_ATOMIC; ++// else ++// flags = GFP_KERNEL; ++ ++ msg = (struct lmac_msg *)kzalloc(sizeof(struct lmac_msg) + param_len, ++ flags); ++ if (msg == NULL) { ++ AICWFDBG(LOGERROR, "%s: msg allocation failed\n", __func__); ++ return NULL; ++ } ++ msg->id = id; ++ msg->dest_id = dest_id; ++ msg->src_id = src_id; ++ msg->param_len = param_len; ++ //printk("rwnx_msg_zalloc size=%d id=%d\n",msg->param_len,msg->id); ++ ++ return msg->param; ++} ++ ++static void rwnx_msg_free(struct rwnx_hw *rwnx_hw, const void *msg_params) ++{ ++ struct lmac_msg *msg = container_of((void *)msg_params, ++ struct lmac_msg, param); ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Free the message */ ++ kfree(msg); ++} ++ ++//void rwnx_pm_relax(struct aic_sdio_dev *sdiodev); ++//void rwnx_pm_stay_awake(struct aic_sdio_dev *sdiodev); ++ ++static int rwnx_send_msg(struct rwnx_hw *rwnx_hw, const void *msg_params, ++ int reqcfm, lmac_msg_id_t reqid, void *cfm) ++{ ++ struct lmac_msg *msg; ++ struct rwnx_cmd *cmd; ++ bool nonblock; ++ int ret = 0; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ AICWFDBG(LOGTRACE, "%s (%d)%s reqcfm:%d in_irq:%d in_softirq:%d in_atomic:%d\r\n", ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(6, 18, 0)) ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_irq(), (int)in_softirq(), (int)in_atomic()); ++#else ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_hardirq(), (int)in_softirq(), (int)in_atomic()); ++#endif ++ ++ ++#ifdef AICWF_USB_SUPPORT ++ if (rwnx_hw->usbdev->state == USB_DOWN_ST) { ++ rwnx_msg_free(rwnx_hw, msg_params); ++ usb_err("bus is down\n"); ++ return 0; ++ } ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ rwnx_wakeup_lock(rwnx_hw->ws_tx); ++ if (rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { ++ rwnx_msg_free(rwnx_hw, msg_params); ++ sdio_err("bus is down\n"); ++ rwnx_wakeup_unlock(rwnx_hw->ws_tx); ++ return 0; ++ } ++#endif ++ ++ msg = container_of((void *)msg_params, struct lmac_msg, param); ++ ++ #if 0 ++ if (!test_bit(RWNX_DEV_STARTED, &rwnx_hw->drv_flags) && ++ reqid != DBG_MEM_READ_CFM && reqid != DBG_MEM_WRITE_CFM && ++ reqid != DBG_MEM_BLOCK_WRITE_CFM && reqid != DBG_START_APP_CFM && ++ reqid != MM_SET_RF_CALIB_CFM && reqid != MM_SET_RF_CONFIG_CFM && ++ reqid != MM_RESET_CFM && reqid != MM_VERSION_CFM && ++ reqid != MM_START_CFM && reqid != MM_SET_IDLE_CFM && ++ reqid != ME_CONFIG_CFM && reqid != MM_SET_PS_MODE_CFM && ++ reqid != ME_CHAN_CONFIG_CFM) { ++ printk(KERN_CRIT "%s: bypassing (RWNX_DEV_RESTARTING set) 0x%02x\n", ++ __func__, reqid); ++ kfree(msg); ++ return -EBUSY; ++ } ++ #endif ++#if 0 ++ else if (!rwnx_hw->ipc_env) { ++ printk(KERN_CRIT "%s: bypassing (restart must have failed)\n", __func__); ++ kfree(msg); ++ return -EBUSY; ++ } ++#endif ++ ++ //nonblock = is_non_blocking_msg(msg->id); ++ nonblock = 0; ++ cmd = rwnx_cmd_malloc();//kzalloc(sizeof(struct rwnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL); ++ cmd->result = -EINTR; ++ cmd->id = msg->id; ++ cmd->reqid = reqid; ++ cmd->a2e_msg = msg; ++ cmd->e2a_msg = cfm; ++ if (nonblock) ++ cmd->flags = RWNX_CMD_FLAG_NONBLOCK; ++ if (reqcfm) ++ cmd->flags |= RWNX_CMD_FLAG_REQ_CFM; ++ ++#if 0 ++ if (cfm != NULL) { ++ do { ++ if(rwnx_hw->cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) ++ break; ++ spin_lock_bh(&rwnx_hw->cmd_mgr->lock); ++ empty = list_empty(&rwnx_hw->cmd_mgr->cmds); ++ spin_unlock_bh(&rwnx_hw->cmd_mgr->lock); ++ if(!empty) { ++ if(in_softirq()) { ++ printk("in_softirq:check cmdqueue empty\n"); ++ mdelay(10); ++ } ++ else { ++ printk("check cmdqueue empty\n"); ++ msleep(50); ++ } ++ } ++ } while (!empty);//wait for cmd queue empty ++ } ++#endif ++ if (reqcfm) { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; // we don't need ack any more ++ ret = rwnx_hw->cmd_mgr->queue(rwnx_hw->cmd_mgr, cmd); ++ } else { ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_set_cmd_tx((void *)(rwnx_hw->sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++#else ++ aicwf_set_cmd_tx((void *)(rwnx_hw->usbdev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++#endif ++ } ++ ++ if (!reqcfm || ret) ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ ++ rwnx_wakeup_unlock(rwnx_hw->ws_tx); ++ return 0; ++} ++ ++ ++static int rwnx_send_msg1(struct rwnx_hw *rwnx_hw, const void *msg_params, ++ int reqcfm, lmac_msg_id_t reqid, void *cfm, bool defer) ++{ ++ struct lmac_msg *msg; ++ struct rwnx_cmd *cmd; ++ bool nonblock; ++ int ret = 0; ++ ++// RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("%s (%d)%s reqcfm:%d in_irq:%d in_softirq:%d in_atomic:%d\r\n", ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(6, 18, 0)) ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_irq(), (int)in_softirq(), (int)in_atomic()); ++#else ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_hardirq(), (int)in_softirq(), (int)in_atomic()); ++#endif ++ ++ rwnx_wakeup_lock(rwnx_hw->ws_tx); ++ msg = container_of((void *)msg_params, struct lmac_msg, param); ++ ++ //nonblock = is_non_blocking_msg(msg->id); ++ nonblock = 0; ++ cmd = rwnx_cmd_malloc();//kzalloc(sizeof(struct rwnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL); ++ cmd->result = -EINTR; ++ cmd->id = msg->id; ++ cmd->reqid = reqid; ++ cmd->a2e_msg = msg; ++ cmd->e2a_msg = cfm; ++ if (nonblock) ++ cmd->flags = RWNX_CMD_FLAG_NONBLOCK; ++ if (reqcfm) ++ cmd->flags |= RWNX_CMD_FLAG_REQ_CFM; ++ ++ if (reqcfm) { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; // we don't need ack any more ++ if (!defer) ++ ret = rwnx_hw->cmd_mgr->queue(rwnx_hw->cmd_mgr, cmd); ++ else ++ ret = cmd_mgr_queue_force_defer(rwnx_hw->cmd_mgr, cmd); ++ } ++ ++ if (!reqcfm || ret) ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ ++ if (!ret) ++ ret = cmd->result; ++ ++ rwnx_wakeup_unlock(rwnx_hw->ws_tx); ++ //return ret; ++ return 0; ++} ++ ++/****************************************************************************** ++ * Control messages handling functions (FULLMAC) ++ *****************************************************************************/ ++int rwnx_send_reset(struct rwnx_hw *rwnx_hw) ++{ ++ void *void_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* RESET REQ has no parameter */ ++ void_param = rwnx_msg_zalloc(MM_RESET_REQ, TASK_MM, DRV_TASK_ID, 0); ++ if (!void_param) ++ return -ENOMEM; ++ ++ return rwnx_send_msg(rwnx_hw, void_param, 1, MM_RESET_CFM, NULL); ++} ++ ++int rwnx_send_start(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_start_req *start_req_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the START REQ message */ ++ start_req_param = rwnx_msg_zalloc(MM_START_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_start_req)); ++ if (!start_req_param) ++ return -ENOMEM; ++ ++ /* Set parameters for the START message */ ++ memcpy(&start_req_param->phy_cfg, &rwnx_hw->phy.cfg, sizeof(rwnx_hw->phy.cfg)); ++ start_req_param->uapsd_timeout = (u32_l)rwnx_hw->mod_params->uapsd_timeout; ++ start_req_param->lp_clk_accuracy = (u16_l)rwnx_hw->mod_params->lp_clk_ppm; ++ ++ /* Send the START REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, start_req_param, 1, MM_START_CFM, NULL); ++} ++ ++int rwnx_send_version_req(struct rwnx_hw *rwnx_hw, struct mm_version_cfm *cfm) ++{ ++ void *void_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* VERSION REQ has no parameter */ ++ void_param = rwnx_msg_zalloc(MM_VERSION_REQ, TASK_MM, DRV_TASK_ID, 0); ++ if (!void_param) ++ return -ENOMEM; ++ ++ return rwnx_send_msg(rwnx_hw, void_param, 1, MM_VERSION_CFM, cfm); ++} ++ ++int rwnx_send_add_if (struct rwnx_hw *rwnx_hw, const unsigned char *mac, ++ enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm) ++{ ++ struct mm_add_if_req *add_if_req_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ADD_IF_REQ message */ ++ add_if_req_param = rwnx_msg_zalloc(MM_ADD_IF_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_add_if_req)); ++ if (!add_if_req_param) ++ return -ENOMEM; ++ ++ /* Set parameters for the ADD_IF_REQ message */ ++ memcpy(&(add_if_req_param->addr.array[0]), mac, ETH_ALEN); ++ switch (iftype) { ++ #ifdef CONFIG_RWNX_FULLMAC ++ //case NL80211_IFTYPE_P2P_DEVICE: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ add_if_req_param->p2p = true; ++ // no break ++ __attribute__((__fallthrough__)); ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ case NL80211_IFTYPE_STATION: ++ add_if_req_param->type = MM_STA; ++ break; ++ ++ case NL80211_IFTYPE_ADHOC: ++ add_if_req_param->type = MM_IBSS; ++ break; ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ case NL80211_IFTYPE_P2P_GO: ++ add_if_req_param->p2p = true; ++ // no break ++ __attribute__((__fallthrough__)); ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ case NL80211_IFTYPE_AP: ++ add_if_req_param->type = MM_AP; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ add_if_req_param->type = MM_MESH_POINT; ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ return -1; ++ case NL80211_IFTYPE_MONITOR: ++ add_if_req_param->type = MM_MONITOR; ++ break; ++ default: ++ add_if_req_param->type = MM_STA; ++ break; ++ } ++ ++ ++ /* Send the ADD_IF_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, add_if_req_param, 1, MM_ADD_IF_CFM, cfm); ++} ++ ++int rwnx_send_remove_if (struct rwnx_hw *rwnx_hw, u8 vif_index, bool defer) ++{ ++ struct mm_remove_if_req *remove_if_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_REMOVE_IF_REQ message */ ++ remove_if_req = rwnx_msg_zalloc(MM_REMOVE_IF_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_remove_if_req)); ++ if (!remove_if_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_REMOVE_IF_REQ message */ ++ remove_if_req->inst_nbr = vif_index; ++ ++ /* Send the MM_REMOVE_IF_REQ message to LMAC FW */ ++ return rwnx_send_msg1(rwnx_hw, remove_if_req, 1, MM_REMOVE_IF_CFM, NULL, defer); ++} ++ ++int rwnx_send_set_channel(struct rwnx_hw *rwnx_hw, int phy_idx, ++ struct mm_set_channel_cfm *cfm) ++{ ++ struct mm_set_channel_req *req; ++ enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT; ++ u16 center_freq = 2412, center_freq1 = 2412, center_freq2 = 2412; ++ s8 tx_power = 0; ++ u8 flags = 0; ++ enum nl80211_band band = NL80211_BAND_2GHZ; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (phy_idx >= rwnx_hw->phy.cnt) ++ return -ENOTSUPP; ++ ++ req = rwnx_msg_zalloc(MM_SET_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_channel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if (phy_idx == 0) { ++#ifdef CONFIG_RWNX_FULLMAC ++ /* On FULLMAC only setting channel of secondary chain */ ++ wiphy_err(rwnx_hw->wiphy, "Trying to set channel of primary chain"); ++ return 0; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } else { ++ struct rwnx_sec_phy_chan *chan = &rwnx_hw->phy.sec_chan; ++ width = chnl2bw[chan->type]; ++ band = chan->band; ++ center_freq = chan->prim20_freq; ++ center_freq1 = chan->center_freq1; ++ center_freq2 = chan->center_freq2; ++ flags = 0; ++ } ++ ++ req->chan.band = band; ++ req->chan.type = bw2chnl[width]; ++ req->chan.prim20_freq = center_freq; ++ req->chan.center1_freq = center_freq1; ++ req->chan.center2_freq = center_freq2; ++ req->chan.tx_power = tx_power; ++ req->chan.flags = flags; ++ req->index = phy_idx; ++ ++ if (rwnx_hw->phy.limit_bw) ++ limit_chan_bw(&req->chan.type, req->chan.prim20_freq, &req->chan.center1_freq); ++ ++ RWNX_DBG("mac80211: freq=%d(c1:%d - c2:%d)/width=%d - band=%d\n" ++ " hw(%d): prim20=%d(c1:%d - c2:%d)/ type=%d - band=%d\n", ++ center_freq, center_freq1, center_freq2, width, band, ++ phy_idx, req->chan.prim20_freq, req->chan.center1_freq, ++ req->chan.center2_freq, req->chan.type, req->chan.band); ++ ++ /* Send the MM_SET_CHANNEL_REQ REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_SET_CHANNEL_CFM, cfm); ++} ++ ++int rwnx_send_key_add(struct rwnx_hw *rwnx_hw, u8 vif_idx, u8 sta_idx, bool pairwise, ++ u8 *key, u8 key_len, u8 key_idx, u8 cipher_suite, ++ struct mm_key_add_cfm *cfm) ++{ ++ struct mm_key_add_req *key_add_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_KEY_ADD_REQ message */ ++ key_add_req = rwnx_msg_zalloc(MM_KEY_ADD_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_key_add_req)); ++ if (!key_add_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_KEY_ADD_REQ message */ ++ if (sta_idx != 0xFF) { ++ /* Pairwise key */ ++ key_add_req->sta_idx = sta_idx; ++ } else { ++ /* Default key */ ++ key_add_req->sta_idx = sta_idx; ++ key_add_req->key_idx = (u8_l)key_idx; /* only useful for default keys */ ++ } ++ key_add_req->pairwise = pairwise; ++ key_add_req->inst_nbr = vif_idx; ++ key_add_req->key.length = key_len; ++ memcpy(&(key_add_req->key.array[0]), key, key_len); ++ ++ key_add_req->cipher_suite = cipher_suite; ++ ++ RWNX_DBG("%s: sta_idx:%d key_idx:%d inst_nbr:%d cipher:%d key_len:%d\n", __func__, ++ key_add_req->sta_idx, key_add_req->key_idx, key_add_req->inst_nbr, ++ key_add_req->cipher_suite, key_add_req->key.length); ++#if defined(CONFIG_RWNX_DBG) || defined(CONFIG_DYNAMIC_DEBUG) ++ print_hex_dump_bytes("key: ", DUMP_PREFIX_OFFSET, key_add_req->key.array, key_add_req->key.length); ++#endif ++ ++ /* Send the MM_KEY_ADD_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, key_add_req, 1, MM_KEY_ADD_CFM, cfm); ++} ++ ++int rwnx_send_key_del(struct rwnx_hw *rwnx_hw, uint8_t hw_key_idx) ++{ ++ struct mm_key_del_req *key_del_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_KEY_DEL_REQ message */ ++ key_del_req = rwnx_msg_zalloc(MM_KEY_DEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_key_del_req)); ++ if (!key_del_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_KEY_DEL_REQ message */ ++ key_del_req->hw_key_idx = hw_key_idx; ++ ++ /* Send the MM_KEY_DEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, key_del_req, 1, MM_KEY_DEL_CFM, NULL); ++} ++ ++int rwnx_send_bcn(struct rwnx_hw *rwnx_hw, u8 *buf, u8 vif_idx, u16 bcn_len) ++{ ++ struct apm_set_bcn_ie_req *bcn_ie_req; ++ bcn_ie_req = rwnx_msg_zalloc(APM_SET_BEACON_IE_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_set_bcn_ie_req)); ++ if (!bcn_ie_req) ++ return -ENOMEM; ++ ++ bcn_ie_req->vif_idx = vif_idx; ++ bcn_ie_req->bcn_ie_len = bcn_len; ++ memcpy(bcn_ie_req->bcn_ie, (u8 *)buf, bcn_len); ++ kfree(buf); ++ ++ return rwnx_send_msg(rwnx_hw, bcn_ie_req, 1, APM_SET_BEACON_IE_CFM, NULL); ++} ++ ++int rwnx_send_bcn_change(struct rwnx_hw *rwnx_hw, u8 vif_idx, u32 bcn_addr, ++ u16 bcn_len, u16 tim_oft, u16 tim_len, u16 *csa_oft) ++{ ++ struct mm_bcn_change_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_BCN_CHANGE_REQ message */ ++ req = rwnx_msg_zalloc(MM_BCN_CHANGE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_bcn_change_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_BCN_CHANGE_REQ message */ ++ req->bcn_ptr = bcn_addr; ++ req->bcn_len = bcn_len; ++ req->tim_oft = tim_oft; ++ req->tim_len = tim_len; ++ req->inst_nbr = vif_idx; ++ ++ if (csa_oft) { ++ int i; ++ for (i = 0; i < BCN_MAX_CSA_CPT; i++) { ++ req->csa_oft[i] = csa_oft[i]; ++ } ++ } ++ ++ /* Send the MM_BCN_CHANGE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_BCN_CHANGE_CFM, NULL); ++} ++ ++int rwnx_send_roc(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct ieee80211_channel *chan, unsigned int duration, ++ struct mm_remain_on_channel_cfm *roc_cfm) ++{ ++ struct mm_remain_on_channel_req *req; ++ struct cfg80211_chan_def chandef; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Create channel definition structure */ ++ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); ++ ++ /* Build the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req = rwnx_msg_zalloc(MM_REMAIN_ON_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_remain_on_channel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req->op_code = MM_ROC_OP_START; ++ req->vif_index = vif->vif_index; ++ req->duration_ms = duration; ++ req->band = chan->band; ++ req->type = bw2chnl[chandef.width]; ++ req->prim20_freq = chan->center_freq; ++ req->center1_freq = chandef.center_freq1; ++ req->center2_freq = chandef.center_freq2; ++ req->tx_power = chan_to_fw_pwr(chan->max_power); ++ ++ /* Send the MM_REMAIN_ON_CHANNEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_REMAIN_ON_CHANNEL_CFM, roc_cfm); ++} ++ ++int rwnx_send_cancel_roc(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_remain_on_channel_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req = rwnx_msg_zalloc(MM_REMAIN_ON_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_remain_on_channel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req->op_code = MM_ROC_OP_CANCEL; ++ ++ /* Send the MM_REMAIN_ON_CHANNEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_REMAIN_ON_CHANNEL_CFM, NULL); ++} ++ ++int rwnx_send_set_power(struct rwnx_hw *rwnx_hw, u8 vif_idx, s8 pwr, ++ struct mm_set_power_cfm *cfm) ++{ ++ struct mm_set_power_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_POWER_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_POWER_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_power_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_SET_POWER_REQ message */ ++ req->inst_nbr = vif_idx; ++ req->power = pwr; ++ ++ /* Send the MM_SET_POWER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_SET_POWER_CFM, cfm); ++} ++ ++int rwnx_send_set_edca(struct rwnx_hw *rwnx_hw, u8 hw_queue, u32 param, ++ bool uapsd, u8 inst_nbr) ++{ ++ struct mm_set_edca_req *set_edca_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_EDCA_REQ message */ ++ set_edca_req = rwnx_msg_zalloc(MM_SET_EDCA_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_edca_req)); ++ if (!set_edca_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_SET_EDCA_REQ message */ ++ set_edca_req->ac_param = param; ++ set_edca_req->uapsd = uapsd; ++ set_edca_req->hw_queue = hw_queue; ++ set_edca_req->inst_nbr = inst_nbr; ++ ++ /* Send the MM_SET_EDCA_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_edca_req, 1, MM_SET_EDCA_CFM, NULL); ++} ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++int rwnx_send_p2p_oppps_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 ctw, struct mm_set_p2p_oppps_cfm *cfm) ++{ ++ struct mm_set_p2p_oppps_req *p2p_oppps_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_P2P_OPPPS_REQ message */ ++ p2p_oppps_req = rwnx_msg_zalloc(MM_SET_P2P_OPPPS_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_p2p_oppps_req)); ++ ++ if (!p2p_oppps_req) { ++ return -ENOMEM; ++ } ++ ++ /* Fill the message parameters */ ++ p2p_oppps_req->vif_index = rwnx_vif->vif_index; ++ p2p_oppps_req->ctwindow = ctw; ++ ++ /* Send the MM_P2P_OPPPS_REQ message to LMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, p2p_oppps_req, 1, MM_SET_P2P_OPPPS_CFM, cfm); ++ ++ return error; ++} ++ ++int rwnx_send_p2p_noa_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ int count, int interval, int duration, bool dyn_noa, ++ struct mm_set_p2p_noa_cfm *cfm) ++{ ++ struct mm_set_p2p_noa_req *p2p_noa_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Param check */ ++ if (count > 255) ++ count = 255; ++ ++ if (duration >= interval) { ++ dev_err(rwnx_hw->dev, "Invalid p2p NOA config: interval=%d <= duration=%d\n", ++ interval, duration); ++ return -EINVAL; ++ } ++ ++ /* Build the MM_SET_P2P_NOA_REQ message */ ++ p2p_noa_req = rwnx_msg_zalloc(MM_SET_P2P_NOA_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_p2p_noa_req)); ++ ++ if (!p2p_noa_req) { ++ return -ENOMEM; ++ } ++ ++ /* Fill the message parameters */ ++ p2p_noa_req->vif_index = rwnx_vif->vif_index; ++ p2p_noa_req->noa_inst_nb = 0; ++ p2p_noa_req->count = count; ++ ++ if (count) { ++ p2p_noa_req->duration_us = duration * 1024; ++ p2p_noa_req->interval_us = interval * 1024; ++ p2p_noa_req->start_offset = (interval - duration - 10) * 1024; ++ p2p_noa_req->dyn_noa = dyn_noa; ++ } ++ ++ /* Send the MM_SET_2P_NOA_REQ message to LMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, p2p_noa_req, 1, MM_SET_P2P_NOA_CFM, cfm); ++ ++ return error; ++} ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++#ifdef AICWF_ARP_OFFLOAD ++int rwnx_send_arpoffload_en_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u32_l ipaddr, u8_l enable) ++{ ++ struct mm_set_arpoffload_en_req *arp_offload_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_P2P_NOA_REQ message */ ++ arp_offload_req = rwnx_msg_zalloc(MM_SET_ARPOFFLOAD_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_arpoffload_en_req)); ++ ++ if (!arp_offload_req) { ++ return -ENOMEM; ++ } ++ ++ /* Fill the message parameters */ ++ arp_offload_req->enable = enable; ++ arp_offload_req->vif_idx = rwnx_vif->vif_index; ++ arp_offload_req->ipaddr = ipaddr; ++ ++ /* Send the MM_ARPOFFLOAD_EN_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, arp_offload_req, 1, MM_SET_ARPOFFLOAD_CFM, NULL); ++ ++ return error; ++} ++#endif ++ ++int rwnx_send_disable_agg_req(struct rwnx_hw *rwnx_hw, u8_l agg_disable, u8_l agg_disable_rx, u8_l sta_idx) ++{ ++ struct mm_set_agg_disable_req *req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_AGG_DISABLE_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_AGG_DISABLE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_agg_disable_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->disable = agg_disable; ++ req->staidx = sta_idx; ++ req->disable_rx = agg_disable_rx; ++ ++ /* Send the MM_SET_AGG_DISABLE_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_AGG_DISABLE_CFM, NULL); ++ ++ return (error); ++}; ++ ++int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enable_nullcts) ++{ ++ struct mm_set_coex_req *coex_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_COEX_REQ message */ ++ coex_req = rwnx_msg_zalloc(MM_SET_COEX_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_coex_req)); ++ ++ if (!coex_req) { ++ return -ENOMEM; ++ } ++ ++ coex_req->bt_on = 1; ++ coex_req->disable_coexnull = disable_coexnull; ++ coex_req->enable_nullcts = enable_nullcts; ++ coex_req->enable_periodic_timer = 0; ++ coex_req->coex_timeslot_set = 0; ++ ++ /* Send the MM_SET_COEX_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, coex_req, 1, MM_SET_COEX_CFM, NULL); ++ ++ return error; ++}; ++ ++ ++int rwnx_send_rf_config_req(struct rwnx_hw *rwnx_hw, u8_l ofst, u8_l sel, u8_l *tbl, u16_l len) ++{ ++ struct mm_set_rf_config_req *rf_config_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_RF_CONFIG_REQ message */ ++ rf_config_req = rwnx_msg_zalloc(MM_SET_RF_CONFIG_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_rf_config_req)); ++ ++ if (!rf_config_req) { ++ return -ENOMEM; ++ } ++ ++ rf_config_req->table_sel = sel; ++ rf_config_req->table_ofst = ofst; ++ rf_config_req->table_num = 16; ++ rf_config_req->deft_page = 0; ++ ++ memcpy(rf_config_req->data, tbl, len); ++ ++ /* Send the MM_SET_RF_CONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, rf_config_req, 1, MM_SET_RF_CONFIG_CFM, NULL); ++ ++ return (error); ++ ++} ++ ++int rwnx_send_rf_calib_req(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm) ++{ ++ struct mm_set_rf_calib_req *rf_calib_req; ++ xtal_cap_conf_t xtal_cap = {0,}; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_P2P_NOA_REQ message */ ++ rf_calib_req = rwnx_msg_zalloc(MM_SET_RF_CALIB_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_rf_calib_req)); ++ ++ if (!rf_calib_req) { ++ return -ENOMEM; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ rf_calib_req->cal_cfg_24g = 0xbf; ++ rf_calib_req->cal_cfg_5g = 0x3f; ++ } else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ rf_calib_req->cal_cfg_24g = 0x0f8f; ++ rf_calib_req->cal_cfg_5g = 0; ++ } else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rf_calib_req->cal_cfg_24g = 0x0f8f; ++ rf_calib_req->cal_cfg_5g = 0x0f0f; ++ } ++ ++ rf_calib_req->param_alpha = 0x0c34c008; ++ rf_calib_req->bt_calib_en = 0; ++ rf_calib_req->bt_calib_param = 0x264203; ++ ++ get_userconfig_xtal_cap(&xtal_cap); ++ ++ if (xtal_cap.enable) { ++ printk("user xtal cap: %d, cap_fine: %d\n", xtal_cap.xtal_cap, xtal_cap.xtal_cap_fine); ++ rf_calib_req->xtal_cap = xtal_cap.xtal_cap; ++ rf_calib_req->xtal_cap_fine = xtal_cap.xtal_cap_fine; ++ } else { ++ rf_calib_req->xtal_cap = 0; ++ rf_calib_req->xtal_cap_fine = 0; ++ } ++ ++ ++ /* Send the MM_SET_RF_CALIB_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, rf_calib_req, 1, MM_SET_RF_CALIB_CFM, cfm); ++ ++ return error; ++}; ++ ++int rwnx_send_get_macaddr_req(struct rwnx_hw *rwnx_hw, struct mm_get_mac_addr_cfm *cfm) ++{ ++ struct mm_get_mac_addr_req *get_macaddr_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_GET_MAC_ADDR_REQ message */ ++ get_macaddr_req = rwnx_msg_zalloc(MM_GET_MAC_ADDR_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_get_mac_addr_req)); ++ ++ if (!get_macaddr_req) { ++ return -ENOMEM; ++ } ++ ++ get_macaddr_req->get = 1; ++ ++ /* Send the MM_GET_MAC_ADDR_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, get_macaddr_req, 1, MM_GET_MAC_ADDR_CFM, cfm); ++ ++ return error; ++}; ++ ++int rwnx_send_get_sta_info_req(struct rwnx_hw *rwnx_hw, u8_l sta_idx, struct mm_get_sta_info_cfm *cfm) ++{ ++ struct mm_get_sta_info_req *get_info_req; ++ int error; ++ ++ ++ /* Build the MM_GET_STA_INFO_REQ message */ ++ get_info_req = rwnx_msg_zalloc(MM_GET_STA_INFO_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_get_sta_info_req)); ++ ++ if (!get_info_req) { ++ return -ENOMEM; ++ } ++ ++ get_info_req->sta_idx = sta_idx; ++ ++ /* Send the MM_GET_STA_INFO_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, get_info_req, 1, MM_GET_STA_INFO_CFM, cfm); ++ ++ return error; ++}; ++ ++int rwnx_send_set_stack_start_req(struct rwnx_hw *rwnx_hw, u8_l on, u8_l efuse_valid, u8_l set_vendor_info, ++ u8_l fwtrace_redir_en, struct mm_set_stack_start_cfm *cfm) ++{ ++ struct mm_set_stack_start_req *req; ++ int error; ++ ++ /* Build the MM_SET_STACK_START_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_STACK_START_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_stack_start_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->is_stack_start = on; ++ req->efuse_valid = efuse_valid; ++ req->set_vendor_info = set_vendor_info; ++ req->fwtrace_redir = fwtrace_redir_en; ++ /* Send the MM_SET_STACK_START_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_STACK_START_CFM, cfm); ++ ++ return error; ++} ++ ++#ifdef CONFIG_TEMP_COMP ++ ++int rwnx_send_get_temp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the TEMP_COMP_GET_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ AICWFDBG(LOGINFO, "%s msg_alloc fail\n", __func__); ++ return -ENOMEM; ++ } ++ req->swconfig_id = TEMP_COMP_GET_REQ; ++ ++ ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); ++ if (!ret) ++ AICWFDBG(LOGINFO, "status=%d, temp=%d\n", cfm->temp_comp_get_cfm.status, cfm->temp_comp_get_cfm.degree); ++ else { ++ AICWFDBG(LOGINFO, "%s msg_fail\n", __func__); ++ return ret; ++ } ++ //rwnx_hw->started_jiffies = jiffies; ++ rwnx_hw->temp = cfm->temp_comp_get_cfm.degree; ++ ++ return ret; ++} ++ ++ ++int rwnx_send_set_temp_comp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ /* Build the TEMP_COMP_SET_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ printk("%s msg_alloc fail\n", __func__); ++ return -ENOMEM; ++ } ++ req->swconfig_id = TEMP_COMP_SET_REQ; ++ req->temp_comp_set_req.enable = 1; ++ req->temp_comp_set_req.tmr_period_ms = 15 * 1000; ++ ++ ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); ++ if (!ret) ++ printk("temp_comp status: %d\n", cfm->temp_comp_set_cfm.status); ++ else { ++ printk("%s msg_fail\n", __func__); ++ return ret; ++ } ++ return ret; ++} ++#endif ++ ++int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, int32_t *param, int32_t *param_out) ++{ ++ struct mm_set_acs_txop_req *req0; ++ struct mm_set_channel_access_req *req1; ++ struct mm_set_mac_timescale_req *req2; ++ struct mm_set_cca_threshold_req *req3; ++ struct mm_set_bwmode_req *req4; ++ struct mm_set_ap_ps_level_req *req5 = NULL; ++ struct mm_set_customized_freq_req *req6; ++ ++ int error = 0; ++ int i; ++ ++ switch (hwconfig_id) ++ { ++ case ACS_TXOP_REQ: ++ /* Build the ACS_TXOP_REQ message */ ++ req0= rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_acs_txop_req) ); ++ if (!req0) ++ return -ENOMEM; ++ req0->hwconfig_id = hwconfig_id; ++ req0->txop_be = param[0]; ++ req0->txop_bk = param[1]; ++ req0->txop_vi = param[2]; ++ req0->txop_vo = param[3]; ++ printk("set_acs_txop_req: be: %x,bk: %x,vi: %x,vo: %x\n", ++ req0->txop_be, req0->txop_bk, req0->txop_vi, req0->txop_vo); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req0, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ ++ case CHANNEL_ACCESS_REQ: ++ /* Build the CHANNEL_ACCESS_REQ message */ ++ req1 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_channel_access_req)); ++ if (!req1) ++ return -ENOMEM; ++ req1->hwconfig_id = hwconfig_id; ++ req1->edca[0] = param[0]; ++ req1->edca[1] = param[1]; ++ req1->edca[2] = param[2]; ++ req1->edca[3] = param[3]; ++ req1->vif_idx = param[4]; ++ req1->retry_cnt = param[5]; ++ req1->rts_en = param[6]; ++ req1->long_nav_en = param[7]; ++ req1->cfe_en = param[8]; ++ req1->rc_retry_cnt[0] = param[9]; ++ req1->rc_retry_cnt[1] = param[10]; ++ req1->rc_retry_cnt[2] = param[11]; ++ req1->ccademod_th = param[12]; ++ req1->remove_1m2m = param[13]; ++ printk("set_channel_access_req:edca[]= %x %x %x %x\nvif_idx: %x, retry_cnt: %x, rts_en: %x, long_nav_en: %x, cfe_en: %x, rc_retry_cnt: %x:%x:%x, ccademod_th = %d remove_1m2m = %x\n", ++ req1->edca[0], req1->edca[1], req1->edca[2], req1->edca[3], req1->vif_idx, req1->retry_cnt, req1->rts_en, req1->long_nav_en, req1->cfe_en, req1->rc_retry_cnt[0],req1->rc_retry_cnt[1], req1->rc_retry_cnt[2], req1->ccademod_th, req1->remove_1m2m); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req1, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ ++ case MAC_TIMESCALE_REQ: ++ /* Build the MAC_TIMESCALE_REQ message */ ++ req2 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_mac_timescale_req)); ++ if (!req2) ++ return -ENOMEM; ++ req2->hwconfig_id = hwconfig_id; ++ req2->sifsA_time = param[0]; ++ req2->sifsB_time = param[1]; ++ req2->slot_time = param[2]; ++ req2->rx_startdelay_ofdm = param[3]; ++ req2->rx_startdelay_long = param[4]; ++ req2->rx_startdelay_short = param[5]; ++ printk("set_mac_timescale_req:sifsA_time: %x, sifsB_time: %x, slot_time: %x, rx_startdelay ofdm:%x long %x short %x\n", ++ req2->sifsA_time, req2->sifsB_time, req2->slot_time, req2->rx_startdelay_ofdm, req2->rx_startdelay_long, req2->rx_startdelay_short); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req2, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ ++ case CCA_THRESHOLD_REQ: ++ /* Build the CCA_THRESHOLD_REQ message */ ++ req3 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_cca_threshold_req)); ++ if (!req3) ++ return -ENOMEM; ++ req3->hwconfig_id = hwconfig_id; ++ req3->auto_cca_en = param[0]; ++ req3->cca20p_rise_th = param[1]; ++ req3->cca20s_rise_th = param[2]; ++ req3->cca20p_fall_th = param[3]; ++ req3->cca20s_fall_th = param[4]; ++ printk("cca_threshold_req: auto_cca_en:%d\ncca20p_rise_th = %d\ncca20s_rise_th = %d\ncca20p_fall_th = %d\ncca20s_fall_th = %d\n", ++ req3->auto_cca_en, req3->cca20p_rise_th, req3->cca20s_rise_th, req3->cca20p_fall_th, req3->cca20s_fall_th); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req3, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ case BWMODE_REQ: ++ /* Build the SET_BWMODE_REQ message */ ++ req4 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_bwmode_req)); ++ if (!req4) ++ return -ENOMEM; ++ req4->hwconfig_id = hwconfig_id; ++ req4->bwmode = param[0]; ++ printk("bwmode :%d\n", req4->bwmode); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req4, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ case CHIP_TEMP_GET_REQ: ++ if ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) ++ { ++ struct mm_get_chip_temp_req *req; ++ struct mm_set_vendor_hwconfig_cfm cfm = {0,}; ++ /* Build the CHIP_TEMP_GET_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_get_chip_temp_req)); ++ if (!req) ++ return -ENOMEM; ++ req->hwconfig_id = hwconfig_id; ++ /* Send the MM_SET_VENDOR_HWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_HWCONFIG_CFM, &cfm); ++ if (!error) { ++ if (param_out) { ++ param_out[0] = (int32_t)cfm.chip_temp_cfm.degree; ++ } ++ printk("get_chip_temp degree=%d\n", cfm.chip_temp_cfm.degree); ++ } else { ++ printk("get_chip_temp err=%d\n", error); ++ } ++ } ++ break; ++ case AP_PS_LEVEL_SET_REQ: ++ /* ++ AP_PS_CLK_1 = 1, // 3:7 -> active 3, doze 7 ++ AP_PS_CLK_2, // 5:5 -> active 5, doze 5 ++ AP_PS_CLK_3, // 7:3 -> active 7, doze 3 ++ AP_PS_CLK_4, // 8:2 -> active 8, doze 2 ++ AP_PS_CLK_5, // 9:1 -> active 9, doze 1 ++ */ ++ /* Build the MM_SET_VENDOR_HWCONFIG_REQ message */ ++ req5 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_ap_ps_level_req)); ++ if (!req5) { ++ return -ENOMEM; ++ } ++ req5->hwconfig_id = hwconfig_id; ++ req5->ap_ps_level = param[0]; ++ ++ /* Send the MM_GET_MAC_ADDR_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req5, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ if(!error) ++ printk("set ap_ps_level=%d \n",param[0]); ++ break; ++ ++ case CUSTOMIZED_FREQ_REQ: ++ /* Build the CUSTOMIZED_FREQ_REQ message */ ++ req6 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_customized_freq_req)); ++ if (!req6) ++ return -ENOMEM; ++ req5->hwconfig_id = hwconfig_id; ++ for (i = 0; i < 4; i++) { ++ req6->raw_freq[i] = param [i]; ++ req6->map_freq[i] = param [i + 4]; ++ } ++ printk("customized_freq_req: raw_freq[ %d %d %d %d ], map_freq[ %d %d %d %d]\n", ++ param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7]); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req5, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ ++ break; ++ default: ++ return -ENOMEM; ++ } ++ return error; ++} ++ ++int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, int32_t *param_in, int32_t *param_out) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ struct mm_set_vendor_swconfig_cfm cfm = {0,}; ++ int error; ++ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ req->swconfig_id = swconfig_id; ++ ++ switch (swconfig_id) ++ { ++ case BCN_CFG_REQ: ++ /* Build the BCN_CFG_REQ message */ ++ req->bcn_cfg_req.tim_bcmc_ignored_enable = (bool_l)param_in[0]; ++ printk("bcn_cfg_req: tim_bcmc_ignd=%d\n", req->bcn_cfg_req.tim_bcmc_ignored_enable); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (int32_t)cfm.bcn_cfg_cfm.tim_bcmc_ignored_status; ++ printk("status=%d\n", cfm.bcn_cfg_cfm.tim_bcmc_ignored_status); ++ } ++ break; ++ ++ case TEMP_COMP_SET_REQ: ++ /* Build the TEMP_COMP_SET_REQ message */ ++ req->temp_comp_set_req.enable = (u8_l)param_in[0]; ++ req->temp_comp_set_req.tmr_period_ms = (u32_l)param_in[1]; ++ printk("temp_comp_set_req: en=%d, tmr=%x\n", ++ req->temp_comp_set_req.enable, req->temp_comp_set_req.tmr_period_ms); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (int32_t)cfm.temp_comp_set_cfm.status; ++ printk("status=%d\n", cfm.temp_comp_set_cfm.status); ++ } ++ break; ++ ++ case TEMP_COMP_GET_REQ: ++ printk("temp_comp_get_req\n"); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (int32_t)cfm.temp_comp_get_cfm.status; ++ param_out[1] = (int32_t)cfm.temp_comp_get_cfm.degree; ++ printk("status=%d, degree=%d\n", ++ cfm.temp_comp_get_cfm.status, cfm.temp_comp_get_cfm.degree); ++ } ++ break; ++ ++ case EXT_FLAGS_SET_REQ: ++ /* Build the EXT_FLAGS_SET_REQ message */ ++ req->ext_flags_set_req.user_flags = (u32_l)param_in[0]; ++ printk("ext_flags_set_req: flags=%x\n", ++ req->ext_flags_set_req.user_flags); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (uint32_t)cfm.ext_flags_set_cfm.user_flags; ++ printk("cfm flags=%x\n", cfm.ext_flags_set_cfm.user_flags); ++ } ++ break; ++ ++ case EXT_FLAGS_GET_REQ: ++ /* Build the EXT_FLAGS_GET_REQ message */ ++ printk("ext_flags_get_req\n"); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (uint32_t)cfm.ext_flags_get_cfm.user_flags; ++ printk("cfm flags=%x\n", cfm.ext_flags_get_cfm.user_flags); ++ } ++ break; ++ ++ case EXT_FLAGS_MASK_SET_REQ: ++ /* Build the EXT_FLAGS_MASK_SET_REQ message */ ++ req->ext_flags_mask_set_req.user_flags_mask = (u32_l)param_in[0]; ++ req->ext_flags_mask_set_req.user_flags_val = (u32_l)param_in[1]; ++ printk("ext_flags_mask_set_req: flags mask=0x%x, val=0x%x\n", ++ req->ext_flags_mask_set_req.user_flags_mask, req->ext_flags_mask_set_req.user_flags_val); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (uint32_t)cfm.ext_flags_mask_set_cfm.user_flags; ++ printk("cfm flags=%x\n", cfm.ext_flags_mask_set_cfm.user_flags); ++ } ++ break; ++ ++ default: ++ error = -ENOMEM; ++ break; ++ } ++ ++ return error; ++} ++ ++int rwnx_send_mask_set_ext_flags_req(struct rwnx_hw *rwnx_hw, uint32_t flags_mask, uint32_t flags_val, struct mm_set_vendor_swconfig_cfm *cfm) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ /* Build the REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ AICWFDBG(LOGERROR, "%s msg_alloc fail\n", __func__); ++ return -ENOMEM; ++ } ++ req->swconfig_id = EXT_FLAGS_MASK_SET_REQ; ++ req->ext_flags_mask_set_req.user_flags_mask = (u32_l)flags_mask; ++ req->ext_flags_mask_set_req.user_flags_val = (u32_l)flags_val; ++ ++ ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); ++ if (!ret) { ++ AICWFDBG(LOGINFO, "curr ext_flags=%x\n", cfm->ext_flags_mask_set_cfm.user_flags); ++ } else { ++ AICWFDBG(LOGERROR, "%s send_msg_fail\n", __func__); ++ return ret; ++ } ++ return ret; ++} ++ ++#ifdef CONFIG_SDIO_BT ++int rwnx_sdio_bt_send_req(struct rwnx_hw *rwnx_hw,uint32_t len, struct sk_buff *skb) ++{ ++ struct mm_bt_send_req *req; ++ struct mm_bt_send_cfm cfm; ++ int error; ++ ++ if(testmode) { ++ AICWFDBG(LOGERROR, "%s testmode can not send\n", __func__); ++ return 0; ++ } ++ cfm.status = 0; ++ req = rwnx_msg_zalloc(TDLS_SDIO_BT_SEND_REQ, TASK_TDLS, DRV_TASK_ID, sizeof(struct mm_bt_send_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->data_len = len; ++ memcpy(req->bt_data,skb->data,len); ++ ++ error = rwnx_send_msg(rwnx_hw, req, 1, TDLS_SDIO_BT_SEND_CFM, &cfm); ++ if(!cfm.status){ ++ printk("bt send no cfm"); ++ } ++ ++ return error; ++} ++#endif ++ ++int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_version_cfm *cfm) ++{ ++ void *req; ++ int error; ++ ++ /* Build the MM_GET_FW_VERSION_REQ message */ ++ req = rwnx_msg_zalloc(MM_GET_FW_VERSION_REQ, TASK_MM, DRV_TASK_ID, sizeof(u8)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ /* Send the MM_GET_FW_VERSION_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_GET_FW_VERSION_CFM, cfm); ++ ++ return error; ++} ++ ++int rwnx_send_txpwr_lvl_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_req *txpwr_lvl_req; ++ txpwr_lvl_conf_v2_t txpwr_lvl_v2_tmp; ++ txpwr_lvl_conf_v2_t *txpwr_lvl_v2; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_req)); ++ ++ if (!txpwr_lvl_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_v2 = &txpwr_lvl_v2_tmp; ++ ++ get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_v2); ++ ++ if (txpwr_lvl_v2->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v2->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[11]); ++ ++ if ((testmode == 0) && (chip_sub_id == 0)) { ++ txpwr_lvl_req->txpwr_lvl.enable = txpwr_lvl_v2->enable; ++ txpwr_lvl_req->txpwr_lvl.dsss = txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]; // 11M ++ txpwr_lvl_req->txpwr_lvl.ofdmlowrate_2g4= txpwr_lvl_v2->pwrlvl_11ax_2g4[4]; // MCS4 ++ txpwr_lvl_req->txpwr_lvl.ofdm64qam_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[7]; // MCS7 ++ txpwr_lvl_req->txpwr_lvl.ofdm256qam_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[9]; // MCS9 ++ txpwr_lvl_req->txpwr_lvl.ofdm1024qam_2g4= txpwr_lvl_v2->pwrlvl_11ax_2g4[11]; // MCS11 ++ txpwr_lvl_req->txpwr_lvl.ofdmlowrate_5g = 13; // unused ++ txpwr_lvl_req->txpwr_lvl.ofdm64qam_5g = 13; // unused ++ txpwr_lvl_req->txpwr_lvl.ofdm256qam_5g = 13; // unused ++ txpwr_lvl_req->txpwr_lvl.ofdm1024qam_5g = 13; // unused ++ } else { ++ txpwr_lvl_req->txpwr_lvl_v2 = *txpwr_lvl_v2; ++ } ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_req *txpwr_lvl_req; ++ txpwr_lvl_conf_v3_t txpwr_lvl_v3_tmp; ++ txpwr_lvl_conf_v3_t *txpwr_lvl_v3; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++ int error; ++ int i; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_req)); ++ ++ if (!txpwr_lvl_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_v3 = &txpwr_lvl_v3_tmp; ++ txpwr_loss = &txpwr_loss_tmp; ++ txpwr_loss->loss_enable_2g4 = 0; ++ txpwr_loss->loss_enable_5g = 0; ++ ++ get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_v3); ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable_2g4 == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11ax_2g4[i] -= txpwr_loss->loss_value_2g4; ++ } ++ ++ if (txpwr_loss->loss_enable_5g == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11a_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v3->pwrlvl_11n_11ac_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11ax_5g[i] -= txpwr_loss->loss_value_5g; ++ } ++ ++ if (txpwr_lvl_v3->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v3->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_1m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_2m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_5m5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_11m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[11]); ++ ++ txpwr_lvl_req->txpwr_lvl_v3 = *txpwr_lvl_v3; ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_lvl_v4_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_req *txpwr_lvl_req; ++ txpwr_lvl_conf_v4_t txpwr_lvl_v4_tmp; ++ txpwr_lvl_conf_v4_t *txpwr_lvl_v4; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++ int error; ++ int i; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_req)); ++ ++ if (!txpwr_lvl_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_v4 = &txpwr_lvl_v4_tmp; ++ txpwr_loss = &txpwr_loss_tmp; ++ txpwr_loss->loss_enable_2g4 = 0; ++ txpwr_loss->loss_enable_5g = 0; ++ ++ get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_v4); ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable_2g4 == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v4->pwrlvl_11ax_2g4[i] -= txpwr_loss->loss_value_2g4; ++ } ++ ++ if (txpwr_loss->loss_enable_5g == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ ++ for (i = 0; i <= 7; i++) ++ txpwr_lvl_v4->pwrlvl_11a_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v4->pwrlvl_11n_11ac_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v4->pwrlvl_11ax_5g[i] -= txpwr_loss->loss_value_5g; ++ } ++ ++ ++ if (txpwr_lvl_v4->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v4->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[11]); ++ ++ txpwr_lvl_req->txpwr_lvl_v4 = *txpwr_lvl_v4; ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_adj_req *txpwr_lvl_adj_req; ++ txpwr_lvl_adj_conf_t txpwr_lvl_adj_tmp; ++ txpwr_lvl_adj_conf_t *txpwr_lvl_adj; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_adj_req = rwnx_msg_zalloc(MM_SET_TXPWR_LVL_ADJ_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_adj_req)); ++ ++ if (!txpwr_lvl_adj_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_adj = &txpwr_lvl_adj_tmp; ++ ++ get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj); ++ ++ if (txpwr_lvl_adj->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_adj_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_adj->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_1_4:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_5_9:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_10_13:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[2]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_42:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_58:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_106:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_122:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_138:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_155:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[5]); ++ ++ txpwr_lvl_adj_req->txpwr_lvl_adj = *txpwr_lvl_adj; ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_adj_req, 1, MM_SET_TXPWR_LVL_ADJ_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_idx_req *txpwr_idx_req; ++ txpwr_idx_conf_t *txpwr_idx; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_IDX_LVL_REQ message */ ++ txpwr_idx_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_idx_req)); ++ ++ if (!txpwr_idx_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_idx = &txpwr_idx_req->txpwr_idx; ++ txpwr_idx->enable = 1; ++ txpwr_idx->dsss = 9; ++ txpwr_idx->ofdmlowrate_2g4 = 8; ++ txpwr_idx->ofdm64qam_2g4 = 8; ++ txpwr_idx->ofdm256qam_2g4 = 8; ++ txpwr_idx->ofdm1024qam_2g4 = 8; ++ txpwr_idx->ofdmlowrate_5g = 11; ++ txpwr_idx->ofdm64qam_5g = 10; ++ txpwr_idx->ofdm256qam_5g = 9; ++ txpwr_idx->ofdm1024qam_5g = 9; ++ ++ get_userconfig_txpwr_idx(txpwr_idx); ++ ++ if (txpwr_idx->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_idx_req); ++ return 0; ++ } else { ++ /* Send the MM_SET_TXPWR_IDX_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_idx_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return error; ++ } ++}; ++ ++int rwnx_send_txpwr_ofst_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_ofst_req *txpwr_ofst_req; ++ txpwr_ofst_conf_t *txpwr_ofst; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_OFST_REQ message */ ++ txpwr_ofst_req = rwnx_msg_zalloc(MM_SET_TXPWR_OFST_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_ofst_req)); ++ ++ if (!txpwr_ofst_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_ofst = &txpwr_ofst_req->txpwr_ofst; ++ txpwr_ofst->enable = 1; ++ txpwr_ofst->chan_1_4 = 0; ++ txpwr_ofst->chan_5_9 = 0; ++ txpwr_ofst->chan_10_13 = 0; ++ txpwr_ofst->chan_36_64 = 0; ++ txpwr_ofst->chan_100_120 = 0; ++ txpwr_ofst->chan_122_140 = 0; ++ txpwr_ofst->chan_142_165 = 0; ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ get_userconfig_txpwr_ofst(txpwr_ofst); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst); ++ } ++ ++ if (txpwr_ofst->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_ofst_req); ++ return 0; ++ } else { ++ /* Send the MM_SET_TXPWR_OFST_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_ofst_req, 1, MM_SET_TXPWR_OFST_CFM, NULL); ++ ++ return error; ++ } ++}; ++ ++int rwnx_send_txpwr_ofst2x_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_ofst_req *txpwr_ofst_req; ++ txpwr_ofst2x_conf_t *txpwr_ofst2x; ++ int error = 0; ++ int type, ch_grp; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_OFST_REQ message */ ++ txpwr_ofst_req = rwnx_msg_zalloc(MM_SET_TXPWR_OFST_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_ofst_req)); ++ ++ if (!txpwr_ofst_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_ofst2x = &txpwr_ofst_req->txpwr_ofst2x; ++ txpwr_ofst2x->enable = 0; ++ for (type = 0; type < 3; type++) { ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ if (ch_grp < 3) { ++ txpwr_ofst2x->pwrofst2x_tbl_2g4[type][ch_grp] = 0; ++ } ++ txpwr_ofst2x->pwrofst2x_tbl_5g[type][ch_grp] = 0; ++ } ++ } ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x); ++ } ++ if (txpwr_ofst2x->enable){ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_ofst2x->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g: [0]:11b, [1]:ofdm_highrate, [2]:ofdm_lowrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_2g4[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g: [0]:ofdm_lowrate, [1]:ofdm_highrate, [2]:ofdm_midrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_5g[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ ++ /* Send the MM_SET_TXPWR_OFST_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_ofst_req, 1, MM_SET_TXPWR_OFST_CFM, NULL); ++ }else{ ++ AICWFDBG(LOGINFO, "%s:Do not use txpwr_ofst2x\r\n", __func__); ++ rwnx_msg_free(rwnx_hw, txpwr_ofst_req); ++ } ++ ++ return (error); ++} ++ ++int rwnx_send_txpwr_ofst2x_v2_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_ofst_req *txpwr_ofst_req; ++ txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2; ++ int error = 0; ++ int type, ch_grp; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_OFST_REQ message */ ++ txpwr_ofst_req = rwnx_msg_zalloc(MM_SET_TXPWR_OFST_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_ofst_req)); ++ ++ if (!txpwr_ofst_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_ofst2x_v2 = &txpwr_ofst_req->txpwr_ofst2x_v2; ++ txpwr_ofst2x_v2->enable = 0; ++ ++ get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_v2); ++ ++ if (txpwr_ofst2x_v2->enable){ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_ofst2x_v2->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g(ant0/ant1): [0]:11b, [1]:ofdm_highrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 2; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g(ant0/ant1): [0]:ofdm_highrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 1; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ ++ /* Send the MM_SET_TXPWR_OFST_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_ofst_req, 1, MM_SET_TXPWR_OFST_CFM, NULL); ++ }else{ ++ AICWFDBG(LOGINFO, "%s:Do not use txpwr_ofst2x_v2\r\n", __func__); ++ rwnx_msg_free(rwnx_hw, txpwr_ofst_req); ++ } ++ ++ return (error); ++} ++ ++#ifdef CONFIG_APF ++int rwnx_send_set_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len) ++{ ++ struct mm_set_apf_prog_req *req; ++ int error = 0; ++ int buffer_len, buffer_start = 0, buffer_end, page; ++ ++ /* current only 8800d80 support apf */ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80) { ++ return 0; ++ } ++ ++ if (!program) ++ return -ENOMEM; ++ ++ for (page = 0; buffer_start < program_len; page++) { ++ buffer_end = buffer_start + LMAC_MSG_MAX_LEN; ++ if (buffer_end > program_len) ++ buffer_end = program_len; ++ buffer_len = buffer_end - buffer_start; ++ ++ /* Build the MM_SET_TXOP_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_APF_PROG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_apf_prog_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ req->program_len = buffer_len; ++ req->offset = page; ++ memcpy(req->program, program + buffer_start, buffer_len); ++ buffer_start = buffer_end; ++ ++ /* Send the MM_SET_TXOP_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_APF_PROG_CFM, NULL); ++ if (error) ++ break; ++ } ++ return error; ++} ++ ++int rwnx_send_get_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len) ++{ ++ struct mm_get_apf_prog_req *req; ++ int error = 0; ++ struct mm_get_apf_prog_cfm cfm; ++ int buffer_len, buffer_start = 0, buffer_end, page; ++ ++ /* current only 8800d80 support apf */ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80) { ++ return 0; ++ } ++ ++ if (!program) ++ return -ENOMEM; ++ ++ for (page = 0; buffer_start < program_len; page++) { ++ buffer_end = buffer_start + LMAC_MSG_MAX_LEN; ++ if (buffer_end > program_len) ++ buffer_end = program_len; ++ buffer_len = buffer_end - buffer_start; ++ ++ /* Build the MM_SET_TXOP_REQ message */ ++ req = rwnx_msg_zalloc(MM_GET_APF_PROG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_get_apf_prog_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ req->offset = page; ++ /* Send the MM_GET_APF_PROG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_GET_APF_PROG_CFM, &cfm); ++ if (error) ++ break; ++ ++ memcpy(program + buffer_start, cfm.program, buffer_len); ++ buffer_start = buffer_end; ++ } ++ ++ return error; ++} ++#endif ++ ++int rwnx_send_set_filter(struct rwnx_hw *rwnx_hw, uint32_t filter) ++{ ++ struct mm_set_filter_req *set_filter_req_param; ++ uint32_t rx_filter = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_FILTER_REQ message */ ++ set_filter_req_param = ++ rwnx_msg_zalloc(MM_SET_FILTER_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_filter_req)); ++ if (!set_filter_req_param) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_SET_FILTER_REQ message */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++ if (filter & FIF_PROMISC_IN_BSS) ++ rx_filter |= NXMAC_ACCEPT_UNICAST_BIT; ++#endif ++ if (filter & FIF_ALLMULTI) ++ rx_filter |= NXMAC_ACCEPT_MULTICAST_BIT; ++ ++ if (filter & (FIF_FCSFAIL | FIF_PLCPFAIL)) ++ rx_filter |= NXMAC_ACCEPT_ERROR_FRAMES_BIT; ++ ++ if (filter & FIF_BCN_PRBRESP_PROMISC) ++ rx_filter |= NXMAC_ACCEPT_OTHER_BSSID_BIT; ++ ++ if (filter & FIF_CONTROL) ++ rx_filter |= NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT | ++ NXMAC_ACCEPT_CF_END_BIT | ++ NXMAC_ACCEPT_ACK_BIT | ++ NXMAC_ACCEPT_CTS_BIT | ++ NXMAC_ACCEPT_RTS_BIT | ++ NXMAC_ACCEPT_BA_BIT | NXMAC_ACCEPT_BAR_BIT; ++ ++ if (filter & FIF_OTHER_BSS) ++ rx_filter |= NXMAC_ACCEPT_OTHER_BSSID_BIT; ++ ++ if (filter & FIF_PSPOLL) { ++ /* TODO: check if the MAC filters apply to our BSSID or is general */ ++ rx_filter |= NXMAC_ACCEPT_PS_POLL_BIT; ++ } ++ ++ if (filter & FIF_PROBE_REQ) { ++ rx_filter |= NXMAC_ACCEPT_PROBE_REQ_BIT; ++ rx_filter |= NXMAC_ACCEPT_ALL_BEACON_BIT; ++ } ++ ++ /* Add the filter flags that are set by default and cannot be changed here */ ++ rx_filter |= RWNX_MAC80211_NOT_CHANGEABLE; ++ ++ /* XXX */ ++ //if (ieee80211_hw_check(rwnx_hw->hw, AMPDU_AGGREGATION)) ++ rx_filter |= NXMAC_ACCEPT_BA_BIT; ++ ++ /* Now copy all the flags into the message parameter */ ++ set_filter_req_param->filter = rx_filter; ++ ++ RWNX_DBG("new total_flags = 0x%08x rx filter set to 0x%08x\r\n", ++ filter, rx_filter); ++ ++ /* Send the MM_SET_FILTER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_filter_req_param, 1, MM_SET_FILTER_CFM, NULL); ++} ++ ++ ++/****************************************************************************** ++ * Control messages handling functions (FULLMAC only) ++ *****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++extern struct ieee80211_sband_iftype_data rwnx_he_capa; ++#endif ++#ifdef CONFIG_VHT_FOR_OLD_KERNEL ++static struct ieee80211_sta_vht_cap* rwnx_vht_capa; ++#endif ++int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct me_config_req *req; ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ ++ struct ieee80211_sta_ht_cap *ht_cap; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ struct ieee80211_sta_vht_cap *vht_cap; ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ struct ieee80211_sta_he_cap const *he_cap = NULL; ++#else ++ #ifdef CONFIG_HE_FOR_OLD_KERNEL ++ struct ieee80211_sta_he_cap const *he_cap; ++ #endif ++#endif ++ uint8_t *ht_mcs; ++ int i; ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ ht_cap = &wiphy->bands[NL80211_BAND_5GHZ]->ht_cap; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ vht_cap = &wiphy->bands[NL80211_BAND_5GHZ]->vht_cap; ++ #endif ++ } else { ++ ht_cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ vht_cap = &wiphy->bands[NL80211_BAND_2GHZ]->vht_cap; ++ #endif ++ } ++ #ifdef CONFIG_VHT_FOR_OLD_KERNEL ++ rwnx_vht_capa = vht_cap; ++ #endif ++ ++ ht_mcs = (uint8_t *)&ht_cap->mcs; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_CONFIG_REQ message */ ++ req = rwnx_msg_zalloc(ME_CONFIG_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_config_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_CONFIG_REQ message */ ++ req->ht_supp = ht_cap->ht_supported; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ req->vht_supp = vht_cap->vht_supported; ++ #endif ++ req->ht_cap.ht_capa_info = cpu_to_le16(ht_cap->cap | IEEE80211_HT_CAP_LDPC_CODING); ++ req->ht_cap.a_mpdu_param = ht_cap->ampdu_factor | ++ (ht_cap->ampdu_density << ++ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); ++ for (i = 0; i < sizeof(ht_cap->mcs); i++) ++ req->ht_cap.mcs_rate[i] = ht_mcs[i]; ++ req->ht_cap.ht_extended_capa = 0; ++ req->ht_cap.tx_beamforming_capa = 0; ++ req->ht_cap.asel_capa = 0; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ if (req->vht_supp) { ++ req->vht_cap.vht_capa_info = cpu_to_le32(vht_cap->cap); ++ req->vht_cap.rx_highest = cpu_to_le16(vht_cap->vht_mcs.rx_highest); ++ req->vht_cap.rx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.rx_mcs_map); ++ req->vht_cap.tx_highest = cpu_to_le16(vht_cap->vht_mcs.tx_highest); ++ req->vht_cap.tx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.tx_mcs_map); ++ } ++ #endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) || defined(CONFIG_HE_FOR_OLD_KERNEL) ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (wiphy->bands[NL80211_BAND_2GHZ]->iftype_data != NULL) { ++ he_cap = &wiphy->bands[NL80211_BAND_2GHZ]->iftype_data->he_cap; ++ //} ++ #endif ++ #if defined(CONFIG_HE_FOR_OLD_KERNEL) ++ if (1) { ++ he_cap = &rwnx_he_capa.he_cap; ++ #endif ++ req->he_supp = he_cap->has_he; ++ for (i = 0; i < ARRAY_SIZE(he_cap->he_cap_elem.mac_cap_info); i++) { ++ req->he_cap.mac_cap_info[i] = he_cap->he_cap_elem.mac_cap_info[i]; ++ } ++ for (i = 0; i < ARRAY_SIZE(he_cap->he_cap_elem.phy_cap_info); i++) { ++ req->he_cap.phy_cap_info[i] = he_cap->he_cap_elem.phy_cap_info[i]; ++ } ++ req->he_cap.mcs_supp.rx_mcs_80 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_80); ++ req->he_cap.mcs_supp.tx_mcs_80 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_80); ++ req->he_cap.mcs_supp.rx_mcs_160 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_160); ++ req->he_cap.mcs_supp.tx_mcs_160 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_160); ++ req->he_cap.mcs_supp.rx_mcs_80p80 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_80p80); ++ req->he_cap.mcs_supp.tx_mcs_80p80 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_80p80); ++ for (i = 0; i < MAC_HE_PPE_THRES_MAX_LEN; i++) { ++ req->he_cap.ppe_thres[i] = he_cap->ppe_thres[i]; ++ } ++ req->he_ul_on = rwnx_hw->mod_params->he_ul_on; ++ } ++#else ++ req->he_supp = false; ++ req->he_ul_on = false; ++#endif ++ req->ps_on = rwnx_hw->mod_params->ps_on; ++ req->dpsm = rwnx_hw->mod_params->dpsm; ++ req->tx_lft = rwnx_hw->mod_params->tx_lft; ++ req->ant_div_on = rwnx_hw->mod_params->ant_div; ++ if (rwnx_hw->mod_params->use_80) ++ req->phy_bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ req->phy_bw_max = PHY_CHNL_BW_40; ++ else ++ req->phy_bw_max = PHY_CHNL_BW_20; ++ ++ wiphy_info(wiphy, "HT supp %d, VHT supp %d, HE supp %d\n", req->ht_supp, ++ req->vht_supp, ++ req->he_supp); ++ /* Send the ME_CONFIG_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_CONFIG_CFM, NULL); ++} ++ ++int rwnx_send_me_chan_config_req(struct rwnx_hw *rwnx_hw, char *ccode) ++{ ++ struct me_chan_config_req *req; ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ int i; ++#ifdef CONFIG_POWER_LIMIT ++ int8_t max_pwr; ++ uint8_t r_idx; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++#endif ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_CHAN_CONFIG_REQ message */ ++ req = rwnx_msg_zalloc(ME_CHAN_CONFIG_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_chan_config_req)); ++ if (!req) ++ return -ENOMEM; ++ ++#ifdef CONFIG_POWER_LIMIT ++ txpwr_loss = &txpwr_loss_tmp; ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ if (txpwr_loss->loss_enable_5g == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ r_idx = get_ccode_region(ccode); ++#endif ++ ++ req->chan2G4_cnt = 0; ++ if (wiphy->bands[NL80211_BAND_2GHZ] != NULL) { ++ struct ieee80211_supported_band *b = wiphy->bands[NL80211_BAND_2GHZ]; ++ for (i = 0; i < b->n_channels; i++) { ++ req->chan2G4[req->chan2G4_cnt].flags = 0; ++ if (b->channels[i].flags & IEEE80211_CHAN_DISABLED) ++ req->chan2G4[req->chan2G4_cnt].flags |= CHAN_DISABLED; ++ req->chan2G4[req->chan2G4_cnt].flags |= get_chan_flags(b->channels[i].flags); ++ req->chan2G4[req->chan2G4_cnt].band = NL80211_BAND_2GHZ; ++ req->chan2G4[req->chan2G4_cnt].freq = b->channels[i].center_freq; ++ req->chan2G4[req->chan2G4_cnt].tx_power = chan_to_fw_pwr(b->channels[i].max_power); ++#ifdef CONFIG_POWER_LIMIT ++ { ++ max_pwr = get_powerlimit_by_freq(PHY_BAND_2G4, req->chan2G4[req->chan2G4_cnt].freq, r_idx); ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ max_pwr -= txpwr_loss->loss_value_2g4; ++ if (req->chan2G4[req->chan2G4_cnt].tx_power > max_pwr) ++ req->chan2G4[req->chan2G4_cnt].tx_power = max_pwr; ++ } ++#endif ++ req->chan2G4_cnt++; ++ if (req->chan2G4_cnt == MAC_DOMAINCHANNEL_24G_MAX) ++ break; ++ } ++ } ++ ++ req->chan5G_cnt = 0; ++ if (wiphy->bands[NL80211_BAND_5GHZ] != NULL) { ++ struct ieee80211_supported_band *b = wiphy->bands[NL80211_BAND_5GHZ]; ++ for (i = 0; i < b->n_channels; i++) { ++ req->chan5G[req->chan5G_cnt].flags = 0; ++ if (b->channels[i].flags & IEEE80211_CHAN_DISABLED) ++ req->chan5G[req->chan5G_cnt].flags |= CHAN_DISABLED; ++ req->chan5G[req->chan5G_cnt].flags |= get_chan_flags(b->channels[i].flags); ++ req->chan5G[req->chan5G_cnt].band = NL80211_BAND_5GHZ; ++ req->chan5G[req->chan5G_cnt].freq = b->channels[i].center_freq; ++ req->chan5G[req->chan5G_cnt].tx_power = chan_to_fw_pwr(b->channels[i].max_power); ++#ifdef CONFIG_POWER_LIMIT ++ { ++ max_pwr = get_powerlimit_by_freq( PHY_BAND_5G, req->chan5G[req->chan5G_cnt].freq, r_idx); ++ if (txpwr_loss->loss_enable_5g == 1) ++ max_pwr -= txpwr_loss->loss_value_5g; ++ if (req->chan5G[req->chan5G_cnt].tx_power > max_pwr) ++ req->chan5G[req->chan5G_cnt].tx_power = max_pwr; ++ } ++#endif ++ req->chan5G_cnt++; ++ if (req->chan5G_cnt == MAC_DOMAINCHANNEL_5G_MAX) ++ break; ++ } ++ } ++ ++ /* Send the ME_CHAN_CONFIG_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_CHAN_CONFIG_CFM, NULL); ++} ++ ++int rwnx_send_me_set_control_port_req(struct rwnx_hw *rwnx_hw, bool opened, u8 sta_idx) ++{ ++ struct me_set_control_port_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_SET_CONTROL_PORT_REQ message */ ++ req = rwnx_msg_zalloc(ME_SET_CONTROL_PORT_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_set_control_port_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_SET_CONTROL_PORT_REQ message */ ++ req->sta_idx = sta_idx; ++ req->control_port_open = opened; ++ ++ /* Send the ME_SET_CONTROL_PORT_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_CONTROL_PORT_CFM, NULL); ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)) ++struct ieee80211_he_cap_elem_4_19 { ++ u8 mac_cap_info[6]; ++ u8 phy_cap_info[11]; ++} __packed; ++#endif ++ ++int rwnx_send_me_sta_add(struct rwnx_hw *rwnx_hw, struct station_parameters *params, ++ const u8 *mac, u8 inst_nbr, struct me_sta_add_cfm *cfm) ++{ ++ struct me_sta_add_req *req; ++ ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ struct link_station_parameters *link_sta_params = ¶ms->link_sta_params; ++#else ++ struct station_parameters *link_sta_params = params; ++#endif ++ u8 *ht_mcs = (u8 *)&link_sta_params->ht_capa->mcs; ++ ++ int i; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[inst_nbr]; ++ #if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ struct aic_sta *sta = &rwnx_hw->aic_table[rwnx_vif->ap.aic_index]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("assoc_req idx %d, he: %d, vht: %d\n ", rwnx_vif->ap.aic_index, sta->he, sta->vht); ++ if (rwnx_vif->ap.aic_index < NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX) ++ rwnx_vif->ap.aic_index++; ++ else ++ rwnx_vif->ap.aic_index = 0; ++ #endif ++ ++ /* Build the MM_STA_ADD_REQ message */ ++ req = rwnx_msg_zalloc(ME_STA_ADD_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_sta_add_req)); ++ if (!req){ ++ return -ENOMEM; ++ } ++ ++ /* Set parameters for the MM_STA_ADD_REQ message */ ++ memcpy(&(req->mac_addr.array[0]), mac, ETH_ALEN); ++ ++ req->rate_set.length = link_sta_params->supported_rates_len; ++ for (i = 0; i < link_sta_params->supported_rates_len; i++) ++ req->rate_set.array[i] = link_sta_params->supported_rates[i]; ++ ++ req->flags = 0; ++ if (link_sta_params->ht_capa) { ++ const struct ieee80211_ht_cap *ht_capa = link_sta_params->ht_capa; ++ ++ req->flags |= STA_HT_CAPA; ++ req->ht_cap.ht_capa_info = cpu_to_le16(ht_capa->cap_info); ++ req->ht_cap.a_mpdu_param = ht_capa->ampdu_params_info; ++ for (i = 0; i < sizeof(ht_capa->mcs); i++) ++ req->ht_cap.mcs_rate[i] = ht_mcs[i]; ++ req->ht_cap.ht_extended_capa = cpu_to_le16(ht_capa->extended_ht_cap_info); ++ req->ht_cap.tx_beamforming_capa = cpu_to_le32(ht_capa->tx_BF_cap_info); ++ req->ht_cap.asel_capa = ht_capa->antenna_selection_info; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) ++ if (link_sta_params->vht_capa) { ++ const struct ieee80211_vht_cap *vht_capa = link_sta_params->vht_capa; ++ ++ req->flags |= STA_VHT_CAPA; ++ req->vht_cap.vht_capa_info = cpu_to_le32(vht_capa->vht_cap_info); ++ req->vht_cap.rx_highest = cpu_to_le16(vht_capa->supp_mcs.rx_highest); ++ req->vht_cap.rx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.rx_mcs_map); ++ req->vht_cap.tx_highest = cpu_to_le16(vht_capa->supp_mcs.tx_highest); ++ req->vht_cap.tx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.tx_mcs_map); ++ } ++#elif defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ if (sta->vht) { ++ //const struct ieee80211_vht_cap *vht_capa = rwnx_vht_capa; ++ ++ req->flags |= STA_VHT_CAPA; ++ req->vht_cap.vht_capa_info = cpu_to_le32(rwnx_vht_capa->cap); ++ req->vht_cap.rx_highest = sta->supp_mcs.rx_highest;//cpu_to_le16(rwnx_vht_capa->vht_mcs.rx_highest); ++ req->vht_cap.rx_mcs_map = sta->supp_mcs.rx_mcs_map;//cpu_to_le16(rwnx_vht_capa->vht_mcs.rx_mcs_map); ++ req->vht_cap.tx_highest = sta->supp_mcs.tx_highest;//cpu_to_le16(rwnx_vht_capa->vht_mcs.tx_highest); ++ req->vht_cap.tx_mcs_map = sta->supp_mcs.tx_mcs_map;//cpu_to_le16(rwnx_vht_capa->vht_mcs.tx_mcs_map); ++ } ++#endif ++ ++ AICWFDBG(LOGDEBUG,"rx map %x rx high %x tx map %x tx high %x \n",req->vht_cap.rx_mcs_map,req->vht_cap.rx_highest,req->vht_cap.tx_mcs_map,req->vht_cap.tx_highest); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (link_sta_params->he_capa) { ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) ++ const struct ieee80211_he_cap_elem_4_19 *he_capa = (const struct ieee80211_he_cap_elem_4_19 *) link_sta_params->he_capa; ++ #else ++ const struct ieee80211_he_cap_elem *he_capa = link_sta_params->he_capa; ++ #endif ++ struct ieee80211_he_mcs_nss_supp *mcs_nss_supp = ++ (struct ieee80211_he_mcs_nss_supp *)(he_capa + 1); ++ ++ req->flags |= STA_HE_CAPA; ++ for (i = 0; i < ARRAY_SIZE(he_capa->mac_cap_info); i++) { ++ req->he_cap.mac_cap_info[i] = he_capa->mac_cap_info[i]; ++ } ++ for (i = 0; i < ARRAY_SIZE(he_capa->phy_cap_info); i++) { ++ req->he_cap.phy_cap_info[i] = he_capa->phy_cap_info[i]; ++ } ++ req->he_cap.mcs_supp.rx_mcs_80 = mcs_nss_supp->rx_mcs_80; ++ req->he_cap.mcs_supp.tx_mcs_80 = mcs_nss_supp->tx_mcs_80; ++ req->he_cap.mcs_supp.rx_mcs_160 = mcs_nss_supp->rx_mcs_160; ++ req->he_cap.mcs_supp.tx_mcs_160 = mcs_nss_supp->tx_mcs_160; ++ req->he_cap.mcs_supp.rx_mcs_80p80 = mcs_nss_supp->rx_mcs_80p80; ++ req->he_cap.mcs_supp.tx_mcs_80p80 = mcs_nss_supp->tx_mcs_80p80; ++ } ++#else ++ #ifdef CONFIG_HE_FOR_OLD_KERNEL ++ if (sta->he) { ++ const struct ieee80211_he_cap_elem *he_capa = &rwnx_he_capa.he_cap.he_cap_elem; ++ struct ieee80211_he_mcs_nss_supp *mcs_nss_supp = ++ (struct ieee80211_he_mcs_nss_supp *)(he_capa + 1); ++ req->flags |= STA_HE_CAPA; ++ for (i = 0; i < ARRAY_SIZE(he_capa->mac_cap_info); i++) { ++ req->he_cap.mac_cap_info[i] = sta->he_cap_elem.mac_cap_info[i];//he_capa->mac_cap_info[i]; ++ } ++ for (i = 0; i < ARRAY_SIZE(he_capa->phy_cap_info); i++) { ++ req->he_cap.phy_cap_info[i] = sta->he_cap_elem.phy_cap_info[i];//he_capa->phy_cap_info[i]; ++ } ++ req->he_cap.mcs_supp.rx_mcs_80 = sta->he_mcs_nss_supp.rx_mcs_80;//mcs_nss_supp->rx_mcs_80; ++ req->he_cap.mcs_supp.tx_mcs_80 = sta->he_mcs_nss_supp.tx_mcs_80;//mcs_nss_supp->tx_mcs_80; ++ req->he_cap.mcs_supp.rx_mcs_160 = mcs_nss_supp->rx_mcs_160; ++ req->he_cap.mcs_supp.tx_mcs_160 = mcs_nss_supp->tx_mcs_160; ++ req->he_cap.mcs_supp.rx_mcs_80p80 = mcs_nss_supp->rx_mcs_80p80; ++ req->he_cap.mcs_supp.tx_mcs_80p80 = mcs_nss_supp->tx_mcs_80p80; ++ } ++ #endif ++#endif ++ ++ AICWFDBG(LOGDEBUG,"rwnx sta add he mcs/nss rx mcs 80 0x%04x \n",le16_to_cpu(req->he_cap.mcs_supp.rx_mcs_80)); ++ AICWFDBG(LOGDEBUG,"rwnx sta add he mcs/nss tx mcs 80 0x%04x \n",le16_to_cpu(req->he_cap.mcs_supp.tx_mcs_80)); ++ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) ++ req->flags |= STA_QOS_CAPA; ++ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_MFP)) ++ req->flags |= STA_MFP_CAPA; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ if (link_sta_params->opmode_notif_used) { ++ req->flags |= STA_OPMOD_NOTIF; ++ req->opmode = link_sta_params->opmode_notif_used; ++ } ++ #endif ++ ++ req->aid = cpu_to_le16(params->aid); ++ req->uapsd_queues = params->uapsd_queues; ++ req->max_sp_len = params->max_sp * 2; ++ req->vif_idx = inst_nbr; ++ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { ++ //struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[inst_nbr]; ++ req->tdls_sta = true; ++ if ((params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) && ++ !rwnx_vif->tdls_chsw_prohibited) ++ req->tdls_chsw_allowed = true; ++ if (rwnx_vif->tdls_status == TDLS_SETUP_RSP_TX) ++ req->tdls_sta_initiator = true; ++ } ++ ++ /* Send the ME_STA_ADD_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_STA_ADD_CFM, cfm); ++} ++ ++int rwnx_send_me_sta_del(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool tdls_sta) ++{ ++ struct me_sta_del_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_STA_DEL_REQ message */ ++ req = rwnx_msg_zalloc(ME_STA_DEL_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_sta_del_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_STA_DEL_REQ message */ ++ req->sta_idx = sta_idx; ++ req->tdls_sta = tdls_sta; ++ ++ /* Send the ME_STA_DEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_STA_DEL_CFM, NULL); ++} ++ ++int rwnx_send_me_traffic_ind(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool uapsd, u8 tx_status) ++{ ++ struct me_traffic_ind_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_UTRAFFIC_IND_REQ message */ ++ req = rwnx_msg_zalloc(ME_TRAFFIC_IND_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_traffic_ind_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_TRAFFIC_IND_REQ message */ ++ req->sta_idx = sta_idx; ++ req->tx_avail = tx_status; ++ req->uapsd = uapsd; ++ ++ /* Send the ME_TRAFFIC_IND_REQ to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_TRAFFIC_IND_CFM, NULL); ++} ++ ++int rwnx_send_me_rc_stats(struct rwnx_hw *rwnx_hw, ++ u8 sta_idx, ++ struct me_rc_stats_cfm *cfm) ++{ ++ struct me_rc_stats_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_RC_STATS_REQ message */ ++ req = rwnx_msg_zalloc(ME_RC_STATS_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_rc_stats_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_RC_STATS_REQ message */ ++ req->sta_idx = sta_idx; ++ ++ /* Send the ME_RC_STATS_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_RC_STATS_CFM, cfm); ++} ++ ++int rwnx_send_me_rc_set_rate(struct rwnx_hw *rwnx_hw, ++ u8 sta_idx, ++ u16 rate_cfg) ++{ ++ struct me_rc_set_rate_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_RC_SET_RATE_REQ message */ ++ req = rwnx_msg_zalloc(ME_RC_SET_RATE_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_rc_set_rate_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_RC_SET_RATE_REQ message */ ++ req->sta_idx = sta_idx; ++ req->fixed_rate_cfg = rate_cfg; ++ ++ /* Send the ME_RC_SET_RATE_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 0, 0, NULL); ++} ++ ++int rwnx_send_me_set_ps_mode(struct rwnx_hw *rwnx_hw, u8 ps_mode) ++{ ++ struct me_set_ps_mode_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_SET_PS_MODE_REQ message */ ++ req = rwnx_msg_zalloc(ME_SET_PS_MODE_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_set_ps_mode_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_SET_PS_MODE_REQ message */ ++ req->ps_state = ps_mode; ++ ++ /* Send the ME_SET_PS_MODE_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_PS_MODE_CFM, NULL); ++} ++ ++int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter) ++{ ++ struct me_set_lp_level_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ printk("%s %d %d \n", __func__, lp_level, disable_filter); ++ /* Build the ME_SET_LP_LEVEL_REQ message */ ++ req = rwnx_msg_zalloc(ME_SET_LP_LEVEL_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_set_lp_level_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_SET_LP_LEVEL_REQ message */ ++ req->lp_level = lp_level; ++ req->disable_filter = disable_filter; ++ /* Send the ME_SET_LP_LEVEL_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_LP_LEVEL_CFM, NULL); ++} ++ ++int rwnx_send_sm_connect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct cfg80211_connect_params *sme, ++ struct sm_connect_cfm *cfm) ++{ ++ struct sm_connect_req *req; ++ int i; ++ u32_l flags = 0; ++ bool gval = false; ++ bool pval = false; ++ rwnx_vif->wep_enabled = false; ++ rwnx_vif->wep_auth_err = false; ++ rwnx_vif->last_auth_type = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SM_CONNECT_REQ message */ ++ req = rwnx_msg_zalloc(SM_CONNECT_REQ, TASK_SM, DRV_TASK_ID, ++ sizeof(struct sm_connect_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if ((sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)) { ++ gval = true; ++ } ++ ++ if (sme->crypto.n_ciphers_pairwise && ++ ((sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104))) { ++ pval = true; ++ } ++ ++ /* Set parameters for the SM_CONNECT_REQ message */ ++ if (sme->crypto.n_ciphers_pairwise && ++ ((sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_TKIP) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104))) ++ flags |= DISABLE_HT; ++ ++ if (sme->crypto.control_port) ++ flags |= CONTROL_PORT_HOST; ++ ++ if (sme->crypto.control_port_no_encrypt) ++ flags |= CONTROL_PORT_NO_ENC; ++ ++ if (use_pairwise_key(&sme->crypto)) ++ flags |= WPA_WPA2_IN_USE; ++ ++ if (sme->mfp == NL80211_MFP_REQUIRED) ++ flags |= MFP_IN_USE; ++ ++ if (rwnx_vif->sta.ap) ++ flags |= REASSOCIATION; ++ ++ req->ctrl_port_ethertype = sme->crypto.control_port_ethertype; ++ ++ if (sme->bssid) ++ memcpy(&req->bssid, sme->bssid, ETH_ALEN); ++ else ++ req->bssid = mac_addr_bcst; ++ req->vif_idx = rwnx_vif->vif_index; ++ if (sme->channel) { ++ req->chan.band = sme->channel->band; ++ req->chan.freq = sme->channel->center_freq; ++ req->chan.flags = get_chan_flags(sme->channel->flags); ++ } else { ++ req->chan.freq = (u16_l)-1; ++ } ++ for (i = 0; i < sme->ssid_len; i++) ++ req->ssid.array[i] = sme->ssid[i]; ++ req->ssid.length = sme->ssid_len; ++ req->flags = flags; ++ if (WARN_ON(sme->ie_len > sizeof(req->ie_buf))) ++ goto invalid_param; ++ if (sme->ie_len) ++ memcpy(req->ie_buf, sme->ie, sme->ie_len); ++ req->ie_len = sme->ie_len; ++ req->listen_interval = rwnx_mod_params.listen_itv; ++ req->dont_wait_bcmc = !rwnx_mod_params.listen_bcmc; ++ ++ /* Set auth_type */ ++ if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) ++ req->auth_type = WLAN_AUTH_OPEN; ++ else if (sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ++ req->auth_type = WLAN_AUTH_OPEN; ++ else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ++ req->auth_type = WLAN_AUTH_SHARED_KEY; ++ else if (sme->auth_type == NL80211_AUTHTYPE_FT) { ++ req->auth_type = WLAN_AUTH_FT; ++ } else if (sme->auth_type == NL80211_AUTHTYPE_SAE) ++ req->auth_type = WLAN_AUTH_SAE; ++ else ++ goto invalid_param; ++ ++ /* Set UAPSD queues */ ++ req->uapsd_queues = rwnx_mod_params.uapsd_queues; ++ ++ rwnx_vif->wep_enabled = pval & gval; ++ ++ if (rwnx_vif->wep_enabled) { ++ rwnx_vif->last_auth_type = sme->auth_type; ++ } ++ ++ rwnx_vif->sta.ssid_len = (int)sme->ssid_len; ++ memset(rwnx_vif->sta.ssid, 0, rwnx_vif->sta.ssid_len + 1); ++ memcpy(rwnx_vif->sta.ssid, sme->ssid, rwnx_vif->sta.ssid_len); ++ if (sme->bssid) ++ memcpy(rwnx_vif->sta.bssid, sme->bssid, ETH_ALEN); ++ ++ printk("%s drv_vif_index:%d connect to %s(%d) channel:%d auth_type:%d\r\n", ++ __func__, ++ rwnx_vif->drv_vif_index, ++ rwnx_vif->sta.ssid, ++ rwnx_vif->sta.ssid_len, ++ req->chan.freq, ++ req->auth_type); ++ ++ /* Send the SM_CONNECT_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SM_CONNECT_CFM, cfm); ++ ++invalid_param: ++ rwnx_msg_free(rwnx_hw, req); ++ return -EINVAL; ++} ++ ++int rwnx_send_sm_disconnect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 reason) ++{ ++ struct sm_disconnect_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SM_DISCONNECT_REQ message */ ++ req = rwnx_msg_zalloc(SM_DISCONNECT_REQ, TASK_SM, DRV_TASK_ID, ++ sizeof(struct sm_disconnect_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the SM_DISCONNECT_REQ message */ ++ req->reason_code = reason; ++ req->vif_idx = rwnx_vif->vif_index; ++ ++ /* Send the SM_DISCONNECT_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SM_DISCONNECT_CFM, NULL); ++} ++ ++int rwnx_send_sm_external_auth_required_rsp(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 status) ++{ ++ struct sm_external_auth_required_rsp *rsp; ++ ++ /* Build the SM_EXTERNAL_AUTH_CFM message */ ++ rsp = rwnx_msg_zalloc(SM_EXTERNAL_AUTH_REQUIRED_RSP, TASK_SM, DRV_TASK_ID, ++ sizeof(struct sm_external_auth_required_rsp)); ++ if (!rsp) ++ return -ENOMEM; ++ ++ rsp->status = status; ++ rsp->vif_idx = rwnx_vif->vif_index; ++ ++ /* send the SM_EXTERNAL_AUTH_REQUIRED_RSP message UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, rsp, 1, SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM, NULL); ++} ++ ++int rwnx_send_apm_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_ap_settings *settings, ++ struct apm_start_cfm *cfm, ++ struct rwnx_ipc_elem_var *elem) ++{ ++ struct apm_start_req *req; ++ struct rwnx_bcn *bcn = &vif->ap.bcn; ++ u8 *buf; ++ u32 flags = 0; ++ const u8 *rate_ie; ++ u8 rate_len = 0; ++ int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); ++ const u8 *var_pos; ++ int len, i; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_START_REQ message */ ++ req = rwnx_msg_zalloc(APM_START_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_start_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ // Build the beacon ++ bcn->dtim = (u8)settings->dtim_period; ++ buf = rwnx_build_bcn(bcn, &settings->beacon); ++ if (!buf) { ++ rwnx_msg_free(rwnx_hw, req); ++ return -ENOMEM; ++ } ++ ++ // Retrieve the basic rate set from the beacon buffer ++ len = bcn->len - var_offset; ++ var_pos = buf + var_offset; ++ ++// Assume that rate higher that 54 Mbps are BSS membership ++#define IS_BASIC_RATE(r) ((r & 0x80) && ((r & ~0x80) <= (54 * 2))) ++ ++ rate_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); ++ if (rate_ie) { ++ const u8 *rates = rate_ie + 2; ++ for (i = 0; (i < rate_ie[1]) && (rate_len < MAC_RATESET_LEN); i++) { ++ if (IS_BASIC_RATE(rates[i])) ++ req->basic_rates.array[rate_len++] = rates[i]; ++ } ++ } ++ rate_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, var_pos, len); ++ if (rate_ie) { ++ const u8 *rates = rate_ie + 2; ++ for (i = 0; (i < rate_ie[1]) && (rate_len < MAC_RATESET_LEN); i++) { ++ if (IS_BASIC_RATE(rates[i])) ++ req->basic_rates.array[rate_len++] = rates[i]; ++ } ++ } ++ req->basic_rates.length = rate_len; ++#undef IS_BASIC_RATE ++ ++#if 0 ++ // Sync buffer for FW ++ error = rwnx_ipc_elem_var_allocs(rwnx_hw, elem, bcn->len, DMA_TO_DEVICE, buf, NULL, NULL); ++ if (error) { ++ return error; ++ } ++#else ++ rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn->len); ++#endif ++ ++ /* Set parameters for the APM_START_REQ message */ ++ req->vif_idx = vif->vif_index; ++ req->bcn_addr = elem->dma_addr; ++ req->bcn_len = bcn->len; ++ req->tim_oft = bcn->head_len; ++ req->tim_len = bcn->tim_len; ++ req->chan.band = settings->chandef.chan->band; ++ req->chan.freq = settings->chandef.chan->center_freq; ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ req->chan.flags = get_chan_flags(settings->chandef.chan->flags); ++#else ++ req->chan.flags = 0; ++#endif ++ printk("chan.flags %u \n",req->chan.flags); ++ req->chan.tx_power = chan_to_fw_pwr(settings->chandef.chan->max_power); ++ req->center_freq1 = settings->chandef.center_freq1; ++ req->center_freq2 = settings->chandef.center_freq2; ++ req->ch_width = bw2chnl[settings->chandef.width]; ++ req->bcn_int = settings->beacon_interval; ++ if (settings->crypto.control_port) ++ flags |= CONTROL_PORT_HOST; ++ ++ if (settings->crypto.control_port_no_encrypt) ++ flags |= CONTROL_PORT_NO_ENC; ++ ++ if (use_pairwise_key(&settings->crypto)) ++ flags |= WPA_WPA2_IN_USE; ++ ++ if (settings->crypto.control_port_ethertype) ++ req->ctrl_port_ethertype = settings->crypto.control_port_ethertype; ++ else ++ req->ctrl_port_ethertype = ETH_P_PAE; ++ req->flags = flags; ++ ++ /* Send the APM_START_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_START_CFM, cfm); ++} ++ ++int rwnx_send_apm_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif) ++{ ++ struct apm_stop_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_STOP_REQ message */ ++ req = rwnx_msg_zalloc(APM_STOP_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_stop_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the APM_STOP_REQ message */ ++ req->vif_idx = vif->vif_index; ++ ++ /* Send the APM_STOP_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_STOP_CFM, NULL); ++} ++ ++uint8_t scanning;// = 0; ++ ++#define P2P_WILDCARD_SSID "DIRECT-" ++#define P2P_WILDCARD_SSID_LEN (sizeof(P2P_WILDCARD_SSID) - 1) ++ ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++u8_l vendor_extension_data[256]; ++u8_l vendor_extension_len = 0; ++#if 0 ++u8_l vendor_extension_data[]={ ++ 0x10,0x49,0x00,0x17,0x00,0x01,0x37,0x10, ++ 0x06,0x00,0x10,0xc5,0xc9,0x91,0xeb,0x1f, ++ 0xce,0x4d,0x00,0xa1,0x2a,0xdf,0xa1,0xe9, ++ 0xc3,0x44,0xe6,0x10,0x49,0x00,0x21,0x00, ++ 0x01,0x37,0x20,0x01,0x00,0x01,0x05,0x20, ++ 0x02,0x00,0x04,0x43,0x56,0x54,0x45,0x20, ++ 0x05,0x00,0x0d,0x31,0x39,0x32,0x2e,0x31, ++ 0x36,0x38,0x2e,0x31,0x35,0x34,0x2e,0x31}; ++#endif ++ ++void rwnx_insert_vendor_extension_data(struct scanu_vendor_ie_req *ie_req){ ++ u8_l temp_ie[256]; ++ u8_l vendor_extension_subelement[3] = {0x00,0x37,0x2A}; ++ u8_l vendor_extension_id[2] = {0x10,0x49}; ++ int index = 0; ++ int vendor_extension_subelement_len = 0; ++ ++ memset(temp_ie, 0, 256); ++ ++ //find vendor_extension_subelement ++ for(index = 0; index < ie_req->add_ie_len; index++){ ++ if(ie_req->ie[index] == vendor_extension_id[0]){ ++ index++; ++ if(index == ie_req->add_ie_len){ ++ return; ++ } ++ if(ie_req->ie[index] == vendor_extension_id[1] && ++ ie_req->ie[index + 3] == vendor_extension_subelement[0]&& ++ ie_req->ie[index + 4] == vendor_extension_subelement[1]&& ++ ie_req->ie[index + 5] == vendor_extension_subelement[2]){ ++ index = index + 2; ++ vendor_extension_subelement_len = ie_req->ie[index]; ++ printk("%s find vendor_extension_subelement,index:%d len:%d\r\n", __func__, index, ie_req->ie[index]); ++ break; ++ } ++ } ++ } ++ index = index + vendor_extension_subelement_len; ++ ++ //insert vendor extension ++ memcpy(&temp_ie[0], ie_req->ie, index + 1); ++ memcpy(&temp_ie[index + 1], vendor_extension_data, vendor_extension_len/*sizeof(vendor_extension_data)*/);//insert vendor extension data ++ memcpy(&temp_ie[index + 1 + vendor_extension_len/*sizeof(vendor_extension_data)*/], &ie_req->ie[index + 1], ie_req->add_ie_len - index); ++ ++ memcpy(ie_req->ie, temp_ie, ie_req->add_ie_len + vendor_extension_len/*sizeof(vendor_extension_data)*/); ++ ie_req->add_ie_len = ie_req->add_ie_len + vendor_extension_len/*sizeof(vendor_extension_data)*/; ++ ie_req->ie[1] = ie_req->ie[1] + vendor_extension_len/*sizeof(vendor_extension_data)*/; ++ ++ //rwnx_data_dump((char*)__func__, (void*)ie_req->ie, ie_req->add_ie_len); ++} ++#endif//CONFIG_SET_VENDOR_EXTENSION_IE ++ ++ ++int rwnx_send_scanu_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct cfg80211_scan_request *param) ++{ ++ struct scanu_start_req *req = NULL; ++ struct scanu_vendor_ie_req *ie_req = NULL; ++ struct mm_add_if_cfm add_if_cfm; ++ int i; ++ uint8_t chan_flags = 0; ++ int err; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SCANU_START_REQ message */ ++ req = rwnx_msg_zalloc(SCANU_START_REQ, TASK_SCANU, DRV_TASK_ID, ++ sizeof(struct scanu_start_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ scanning = 1; ++ /* Set parameters */ ++ req->vif_idx = rwnx_vif->vif_index; ++ req->chan_cnt = (u8)min_t(int, SCAN_CHANNEL_MAX, param->n_channels); ++ req->ssid_cnt = (u8)min_t(int, SCAN_SSID_MAX, param->n_ssids); ++ req->bssid = mac_addr_bcst; ++ req->no_cck = param->no_cck; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ if (param->duration_mandatory) ++ //req->duration = ieee80211_tu_to_usec(param->duration); ++ req->duration = 0; ++#endif ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ if (req->ssid_cnt == 0) ++ chan_flags |= CHAN_NO_IR; ++#endif ++ for (i = 0; i < req->ssid_cnt; i++) { ++ int j; ++ for (j = 0; j < param->ssids[i].ssid_len; j++) ++ req->ssid[i].array[j] = param->ssids[i].ssid[j]; ++ req->ssid[i].length = param->ssids[i].ssid_len; ++ ++ if (!memcmp(P2P_WILDCARD_SSID, param->ssids[i].ssid, ++ P2P_WILDCARD_SSID_LEN)) { ++ AICWFDBG(LOGINFO, "p2p scanu:%d,%d,%d\n", rwnx_vif->vif_index, rwnx_vif->is_p2p_vif, rwnx_hw->is_p2p_alive); ++#ifdef CONFIG_USE_P2P0 ++ if (rwnx_vif->is_p2p_vif && !rwnx_hw->is_p2p_alive) { ++#else ++ if (rwnx_vif == rwnx_hw->p2p_dev_vif && !rwnx_vif->up) { ++#endif ++ err = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, ++ RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); ++ if (err) ++ goto error; ++ ++ if (add_if_cfm.status != 0) { ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++ rwnx_hw->is_p2p_alive = 1; ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ AICWFDBG(LOGINFO, "p2p scan start\n"); ++ } ++ } ++ ++#if 1 ++ if (param->ie) { ++ #if 0 ++ if (rwnx_ipc_elem_var_allocs(rwnx_hw, &rwnx_hw->scan_ie, ++ param->ie_len, DMA_TO_DEVICE, ++ NULL, param->ie, NULL)) ++ goto error; ++ ++ req->add_ie_len = param->ie_len; ++ req->add_ies = rwnx_hw->scan_ie.dma_addr; ++ #else ++ ie_req = rwnx_msg_zalloc(SCANU_VENDOR_IE_REQ, TASK_SCANU, DRV_TASK_ID, ++ sizeof(struct scanu_vendor_ie_req)); ++ if (!ie_req) ++ return -ENOMEM; ++ ++ ie_req->add_ie_len = param->ie_len; ++ ie_req->vif_idx = rwnx_vif->vif_index; ++ memcpy(ie_req->ie, param->ie, param->ie_len); ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++ rwnx_insert_vendor_extension_data(ie_req); ++#endif //CONFIG_SET_VENDOR_EXTENSION_IE ++ req->add_ie_len = 0; ++ req->add_ies = 0; ++ ++ err = rwnx_send_msg(rwnx_hw, ie_req, 1, SCANU_VENDOR_IE_CFM, NULL); ++ if (err) ++ goto error; ++ #endif ++ } ++ else { ++ req->add_ie_len = 0; ++ req->add_ies = 0; ++ } ++#else ++ req->add_ie_len = 0; ++ req->add_ies = 0; ++#endif ++ ++ for (i = 0; i < req->chan_cnt; i++) { ++ struct ieee80211_channel *chan = param->channels[i]; ++ AICWFDBG(LOGDEBUG, "scan channel:%d(%d) \r\n", ieee80211_frequency_to_channel(chan->center_freq), chan->center_freq); ++ req->chan[i].band = chan->band; ++ req->chan[i].freq = chan->center_freq; ++ req->chan[i].flags = chan_flags | get_chan_flags(chan->flags); ++ req->chan[i].tx_power = chan_to_fw_pwr(chan->max_reg_power); ++ } ++ ++ /* Send the SCANU_START_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SCANU_START_CFM_ADDTIONAL, NULL); ++error: ++ if (req != NULL) ++ rwnx_msg_free(rwnx_hw, req); ++ if (ie_req != NULL) ++ rwnx_msg_free(rwnx_hw, ie_req); ++ return -ENOMEM; ++} ++ ++int rwnx_send_scanu_cancel_req(struct rwnx_hw *rwnx_hw, struct scan_cancel_cfm *cfm) ++{ ++ struct scan_cancel_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SCAN_CANCEL_REQ message */ ++ req = rwnx_msg_zalloc(SCANU_CANCEL_REQ, TASK_SCANU, DRV_TASK_ID, ++ sizeof(struct scan_cancel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Send the SCAN_CANCEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SCANU_CANCEL_CFM, cfm); ++} ++ ++int rwnx_send_apm_start_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_chan_def *chandef, ++ struct apm_start_cac_cfm *cfm) ++{ ++ struct apm_start_cac_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_START_CAC_REQ message */ ++ req = rwnx_msg_zalloc(APM_START_CAC_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_start_cac_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the APM_START_CAC_REQ message */ ++ req->vif_idx = vif->vif_index; ++ req->chan.band = chandef->chan->band; ++ req->chan.type = bw2chnl[chandef->width]; ++ req->chan.prim20_freq = chandef->chan->center_freq; ++ req->chan.center1_freq = chandef->center_freq1; ++ req->chan.center2_freq = chandef->center_freq2; ++ req->chan.tx_power = 20; ++ req->chan.flags = get_chan_flags(chandef->chan->flags); ++ ++ /* Send the APM_START_CAC_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_START_CAC_CFM, cfm); ++} ++ ++int rwnx_send_apm_stop_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif) ++{ ++ struct apm_stop_cac_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_STOP_CAC_REQ message */ ++ req = rwnx_msg_zalloc(APM_STOP_CAC_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_stop_cac_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the APM_STOP_CAC_REQ message */ ++ req->vif_idx = vif->vif_index; ++ ++ /* Send the APM_STOP_CAC_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_STOP_CAC_CFM, NULL); ++} ++ ++int rwnx_send_mesh_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ const struct mesh_config *conf, const struct mesh_setup *setup, ++ struct mesh_start_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_start_req *req; ++ // Supported basic rates ++ struct ieee80211_supported_band *band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ /* Counter */ ++ int i; ++ /* Return status */ ++ int status; ++ /* DMA Address to be unmapped after confirmation reception */ ++ u32 dma_addr = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_START_REQ message */ ++ req = rwnx_msg_zalloc(MESH_START_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_start_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->vif_index = vif->vif_index; ++ req->bcn_int = setup->beacon_interval; ++ req->dtim_period = setup->dtim_period; ++ req->mesh_id_len = setup->mesh_id_len; ++ ++ for (i = 0; i < setup->mesh_id_len; i++) { ++ req->mesh_id[i] = *(setup->mesh_id + i); ++ } ++ ++ req->user_mpm = setup->user_mpm; ++ req->is_auth = setup->is_authenticated; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) ++ req->auth_id = setup->auth_id; ++ #endif ++ req->ie_len = setup->ie_len; ++ ++ if (setup->ie_len) { ++ /* ++ * Need to provide a Virtual Address to the MAC so that it can download the ++ * additional information elements. ++ */ ++ req->ie_addr = dma_map_single(rwnx_hw->dev, (void *)setup->ie, ++ setup->ie_len, DMA_FROM_DEVICE); ++ ++ /* Check DMA mapping result */ ++ if (dma_mapping_error(rwnx_hw->dev, req->ie_addr)) { ++ printk(KERN_CRIT "%s - DMA Mapping error on additional IEs\n", __func__); ++ ++ /* Consider there is no Additional IEs */ ++ req->ie_len = 0; ++ } else { ++ /* Store DMA Address so that we can unmap the memory section once MESH_START_CFM is received */ ++ dma_addr = req->ie_addr; ++ } ++ } ++ ++ /* Provide rate information */ ++ req->basic_rates.length = 0; ++ for (i = 0; i < band_2GHz->n_bitrates; i++) { ++ u16 rate = band_2GHz->bitrates[i].bitrate; ++ ++ /* Read value is in in units of 100 Kbps, provided value is in units ++ * of 1Mbps, and multiplied by 2 so that 5.5 becomes 11 */ ++ rate = (rate << 1) / 10; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) // TODO: check basic rates ++ if (setup->basic_rates & CO_BIT(i)) { ++ rate |= 0x80; ++ } ++ #endif ++ ++ req->basic_rates.array[i] = (u8)rate; ++ req->basic_rates.length++; ++ } ++ ++ /* Provide channel information */ ++ req->chan.band = setup->chandef.chan->band; ++ req->chan.freq = setup->chandef.chan->center_freq; ++ req->chan.flags = 0; ++ req->chan.tx_power = chan_to_fw_pwr(setup->chandef.chan->max_power); ++ req->center_freq1 = setup->chandef.center_freq1; ++ req->center_freq2 = setup->chandef.center_freq2; ++ req->ch_width = bw2chnl[setup->chandef.width]; ++ ++ /* Send the MESH_START_REQ message to UMAC FW */ ++ status = rwnx_send_msg(rwnx_hw, req, 1, MESH_START_CFM, cfm); ++ ++ /* Unmap DMA area */ ++ if (setup->ie_len) { ++ dma_unmap_single(rwnx_hw->dev, dma_addr, setup->ie_len, DMA_TO_DEVICE); ++ } ++ ++ /* Return the status */ ++ return status; ++} ++ ++int rwnx_send_mesh_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct mesh_stop_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_stop_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_STOP_REQ message */ ++ req = rwnx_msg_zalloc(MESH_STOP_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_stop_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->vif_idx = vif->vif_index; ++ ++ /* Send the MESH_STOP_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_STOP_CFM, cfm); ++} ++ ++int rwnx_send_mesh_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u32 mask, const struct mesh_config *p_mconf, struct mesh_update_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_update_req *req; ++ // Keep only bit for fields which can be updated ++ u32 supp_mask = (mask << 1) & (CO_BIT(NL80211_MESHCONF_GATE_ANNOUNCEMENTS) ++ | CO_BIT(NL80211_MESHCONF_HWMP_ROOTMODE) ++ | CO_BIT(NL80211_MESHCONF_FORWARDING) ++ | CO_BIT(NL80211_MESHCONF_POWER_MODE)); ++ ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (!supp_mask) { ++ return -ENOENT; ++ } ++ ++ /* Build the MESH_UPDATE_REQ message */ ++ req = rwnx_msg_zalloc(MESH_UPDATE_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_update_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->vif_idx = vif->vif_index; ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_GATE_ANNOUNCEMENTS)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_GATE_MODE_BIT); ++ req->gate_announ = p_mconf->dot11MeshGateAnnouncementProtocol; ++ } ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_HWMP_ROOTMODE)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_ROOT_MODE_BIT); ++ req->root_mode = p_mconf->dot11MeshHWMPRootMode; ++ } ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_FORWARDING)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_MESH_FWD_BIT); ++ req->mesh_forward = p_mconf->dot11MeshForwarding; ++ } ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_POWER_MODE)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_LOCAL_PSM_BIT); ++ req->local_ps_mode = p_mconf->power_mode; ++ } ++ ++ /* Send the MESH_UPDATE_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_UPDATE_CFM, cfm); ++} ++ ++int rwnx_send_mesh_peer_info_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, struct mesh_peer_info_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_peer_info_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PEER_INFO_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PEER_INFO_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_peer_info_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->sta_idx = sta_idx; ++ ++ /* Send the MESH_PEER_INFO_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_PEER_INFO_CFM, cfm); ++} ++ ++void rwnx_send_mesh_peer_update_ntf(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, u8 mlink_state) ++{ ++ // Message to send ++ struct mesh_peer_update_ntf *ntf; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PEER_UPDATE_NTF message */ ++ ntf = rwnx_msg_zalloc(MESH_PEER_UPDATE_NTF, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_peer_update_ntf)); ++ ++ if (ntf) { ++ ntf->vif_idx = vif->vif_index; ++ ntf->sta_idx = sta_idx; ++ ntf->state = mlink_state; ++ ++ /* Send the MESH_PEER_INFO_REQ message to UMAC FW */ ++ rwnx_send_msg(rwnx_hw, ntf, 0, 0, NULL); ++ } ++} ++ ++void rwnx_send_mesh_path_create_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *tgt_addr) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Check if we are already waiting for a confirmation */ ++ if (!vif->ap.create_path) { ++ // Message to send ++ struct mesh_path_create_req *req; ++ ++ /* Build the MESH_PATH_CREATE_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PATH_CREATE_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_path_create_req)); ++ ++ if (req) { ++ req->vif_idx = vif->vif_index; ++ memcpy(&req->tgt_mac_addr, tgt_addr, ETH_ALEN); ++ ++ vif->ap.create_path = true; ++ ++ /* Send the MESH_PATH_CREATE_REQ message to UMAC FW */ ++ rwnx_send_msg(rwnx_hw, req, 0, 0, NULL); ++ } ++ } ++} ++ ++int rwnx_send_mesh_path_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, const u8 *tgt_addr, ++ const u8 *p_nhop_addr, struct mesh_path_update_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_path_update_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PATH_UPDATE_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PATH_UPDATE_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_path_update_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->delete = (p_nhop_addr == NULL); ++ req->vif_idx = vif->vif_index; ++ memcpy(&req->tgt_mac_addr, tgt_addr, ETH_ALEN); ++ ++ if (p_nhop_addr) { ++ memcpy(&req->nhop_mac_addr, p_nhop_addr, ETH_ALEN); ++ } ++ ++ /* Send the MESH_PATH_UPDATE_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_PATH_UPDATE_CFM, cfm); ++} ++ ++void rwnx_send_mesh_proxy_add_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *ext_addr) ++{ ++ // Message to send ++ struct mesh_proxy_add_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PROXY_ADD_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PROXY_ADD_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_proxy_add_req)); ++ ++ if (req) { ++ req->vif_idx = vif->vif_index; ++ memcpy(&req->ext_sta_addr, ext_addr, ETH_ALEN); ++ ++ /* Send the MESH_PROXY_ADD_REQ message to UMAC FW */ ++ rwnx_send_msg(rwnx_hw, req, 0, 0, NULL); ++ } ++} ++ ++int rwnx_send_tdls_peer_traffic_ind_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif) ++{ ++ struct tdls_peer_traffic_ind_req *tdls_peer_traffic_ind_req; ++ ++ if (!rwnx_vif->sta.tdls_sta) ++ return -ENOLINK; ++ ++ /* Build the TDLS_PEER_TRAFFIC_IND_REQ message */ ++ tdls_peer_traffic_ind_req = rwnx_msg_zalloc(TDLS_PEER_TRAFFIC_IND_REQ, TASK_TDLS, DRV_TASK_ID, ++ sizeof(struct tdls_peer_traffic_ind_req)); ++ ++ if (!tdls_peer_traffic_ind_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the TDLS_PEER_TRAFFIC_IND_REQ message */ ++ tdls_peer_traffic_ind_req->vif_index = rwnx_vif->vif_index; ++ tdls_peer_traffic_ind_req->sta_idx = rwnx_vif->sta.tdls_sta->sta_idx; ++ memcpy(&(tdls_peer_traffic_ind_req->peer_mac_addr.array[0]), ++ rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN); ++ tdls_peer_traffic_ind_req->dialog_token = 0; // check dialog token value ++ tdls_peer_traffic_ind_req->last_tid = rwnx_vif->sta.tdls_sta->tdls.last_tid; ++ tdls_peer_traffic_ind_req->last_sn = rwnx_vif->sta.tdls_sta->tdls.last_sn; ++ ++ /* Send the TDLS_PEER_TRAFFIC_IND_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, tdls_peer_traffic_ind_req, 0, 0, NULL); ++} ++ ++int rwnx_send_config_monitor_req(struct rwnx_hw *rwnx_hw, ++ struct cfg80211_chan_def *chandef, ++ struct me_config_monitor_cfm *cfm) ++{ ++ struct me_config_monitor_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_CONFIG_MONITOR_REQ message */ ++ req = rwnx_msg_zalloc(ME_CONFIG_MONITOR_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_config_monitor_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if (chandef) { ++ req->chan_set = true; ++ ++ req->chan.band = chandef->chan->band; ++ req->chan.type = bw2chnl[chandef->width]; ++ req->chan.prim20_freq = chandef->chan->center_freq; ++ req->chan.center1_freq = chandef->center_freq1; ++ req->chan.center2_freq = chandef->center_freq2; ++ req->chan.tx_power = chan_to_fw_pwr(chandef->chan->max_power); ++ ++ if (rwnx_hw->phy.limit_bw) ++ limit_chan_bw(&req->chan.type, req->chan.prim20_freq, &req->chan.center1_freq); ++ } else { ++ req->chan_set = false; ++ } ++ ++ req->uf = rwnx_hw->mod_params->uf; ++ req->auto_reply = rwnx_hw->mod_params->auto_reply; ++ ++ /* Send the ME_CONFIG_MONITOR_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_CONFIG_MONITOR_CFM, cfm); ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++int rwnx_send_tdls_chan_switch_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, bool sta_initiator, ++ u8 oper_class, struct cfg80211_chan_def *chandef, ++ struct tdls_chan_switch_cfm *cfm) ++{ ++ struct tdls_chan_switch_req *tdls_chan_switch_req; ++ ++ ++ /* Build the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_chan_switch_req = rwnx_msg_zalloc(TDLS_CHAN_SWITCH_REQ, TASK_TDLS, DRV_TASK_ID, ++ sizeof(struct tdls_chan_switch_req)); ++ ++ if (!tdls_chan_switch_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_chan_switch_req->vif_index = rwnx_vif->vif_index; ++ tdls_chan_switch_req->sta_idx = rwnx_sta->sta_idx; ++ memcpy(&(tdls_chan_switch_req->peer_mac_addr.array[0]), ++ rwnx_sta_addr(rwnx_sta), ETH_ALEN); ++ tdls_chan_switch_req->initiator = sta_initiator; ++ tdls_chan_switch_req->band = chandef->chan->band; ++ tdls_chan_switch_req->type = bw2chnl[chandef->width]; ++ tdls_chan_switch_req->prim20_freq = chandef->chan->center_freq; ++ tdls_chan_switch_req->center1_freq = chandef->center_freq1; ++ tdls_chan_switch_req->center2_freq = chandef->center_freq2; ++ tdls_chan_switch_req->tx_power = chan_to_fw_pwr(chandef->chan->max_power); ++ tdls_chan_switch_req->op_class = oper_class; ++ ++ /* Send the TDLS_CHAN_SWITCH_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, tdls_chan_switch_req, 1, TDLS_CHAN_SWITCH_CFM, cfm); ++} ++ ++int rwnx_send_tdls_cancel_chan_switch_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, ++ struct tdls_cancel_chan_switch_cfm *cfm) ++{ ++ struct tdls_cancel_chan_switch_req *tdls_cancel_chan_switch_req; ++ ++ /* Build the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_cancel_chan_switch_req = rwnx_msg_zalloc(TDLS_CANCEL_CHAN_SWITCH_REQ, TASK_TDLS, DRV_TASK_ID, ++ sizeof(struct tdls_cancel_chan_switch_req)); ++ if (!tdls_cancel_chan_switch_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_cancel_chan_switch_req->vif_index = rwnx_vif->vif_index; ++ tdls_cancel_chan_switch_req->sta_idx = rwnx_sta->sta_idx; ++ memcpy(&(tdls_cancel_chan_switch_req->peer_mac_addr.array[0]), ++ rwnx_sta_addr(rwnx_sta), ETH_ALEN); ++ ++ /* Send the TDLS_CHAN_SWITCH_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, tdls_cancel_chan_switch_req, 1, TDLS_CANCEL_CHAN_SWITCH_CFM, cfm); ++} ++ ++#ifdef CONFIG_RWNX_BFMER ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_send_bfmer_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ const struct ieee80211_vht_cap *vht_cap) ++#endif /* CONFIG_RWNX_FULLMAC*/ ++{ ++ struct mm_bfmer_enable_req *bfmer_en_req; ++#ifdef CONFIG_RWNX_FULLMAC ++ __le32 vht_capability; ++ u8 rx_nss = 0; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (!vht_cap) { ++#endif /* CONFIG_RWNX_FULLMAC */ ++ goto end; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ vht_capability = vht_cap->vht_cap_info; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (!(vht_capability & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) { ++ goto end; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ rx_nss = rwnx_bfmer_get_rx_nss(vht_cap); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ /* Allocate a structure that will contain the beamforming report */ ++ if (rwnx_bfmer_report_add(rwnx_hw, rwnx_sta, RWNX_BFMER_REPORT_SPACE_SIZE)) { ++ goto end; ++ } ++ ++ /* Build the MM_BFMER_ENABLE_REQ message */ ++ bfmer_en_req = rwnx_msg_zalloc(MM_BFMER_ENABLE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_bfmer_enable_req)); ++ ++ /* Check message allocation */ ++ if (!bfmer_en_req) { ++ /* Free memory allocated for the report */ ++ rwnx_bfmer_report_del(rwnx_hw, rwnx_sta); ++ ++ /* Do not use beamforming */ ++ goto end; ++ } ++ ++ /* Provide DMA address to the MAC */ ++ bfmer_en_req->host_bfr_addr = rwnx_sta->bfm_report->dma_addr; ++ bfmer_en_req->host_bfr_size = RWNX_BFMER_REPORT_SPACE_SIZE; ++ bfmer_en_req->sta_idx = rwnx_sta->sta_idx; ++#ifdef CONFIG_RWNX_FULLMAC ++ bfmer_en_req->aid = rwnx_sta->aid; ++ bfmer_en_req->rx_nss = rx_nss; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (vht_capability & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) { ++ bfmer_en_req->vht_mu_bfmee = true; ++ } else { ++ bfmer_en_req->vht_mu_bfmee = false; ++ } ++ ++ /* Send the MM_BFMER_EN_REQ message to LMAC FW */ ++ rwnx_send_msg(rwnx_hw, bfmer_en_req, 0, 0, NULL); ++ ++end: ++ return; ++} ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++int rwnx_send_mu_group_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) ++{ ++ struct mm_mu_group_update_req *req; ++ int group_id, i = 0; ++ u64 map; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_MU_GROUP_UPDATE_REQ message */ ++ req = rwnx_msg_zalloc(MM_MU_GROUP_UPDATE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_mu_group_update_req) + ++ rwnx_sta->group_info.cnt * sizeof(req->groups[0])); ++ ++ /* Check message allocation */ ++ if (!req) ++ return -ENOMEM; ++ ++ /* Go through the groups the STA belongs to */ ++ group_sta_for_each(rwnx_sta, group_id, map) { ++ int user_pos = rwnx_mu_group_sta_get_pos(rwnx_hw, rwnx_sta, group_id); ++ ++ if (WARN((i >= rwnx_sta->group_info.cnt), ++ "STA%d: Too much group (%d)\n", ++ rwnx_sta->sta_idx, i + 1)) ++ break; ++ ++ req->groups[i].group_id = group_id; ++ req->groups[i].user_pos = user_pos; ++ ++ i++; ++ } ++ ++ req->group_cnt = rwnx_sta->group_info.cnt; ++ req->sta_idx = rwnx_sta->sta_idx; ++ ++ /* Send the MM_MU_GROUP_UPDATE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_MU_GROUP_UPDATE_CFM, NULL); ++} ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* CONFIG_RWNX_BFMER */ ++ ++/********************************************************************** ++ * Debug Messages ++ *********************************************************************/ ++int rwnx_send_dbg_trigger_req(struct rwnx_hw *rwnx_hw, char *msg) ++{ ++ struct mm_dbg_trigger_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_DBG_TRIGGER_REQ message */ ++ req = rwnx_msg_zalloc(MM_DBG_TRIGGER_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_dbg_trigger_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_DBG_TRIGGER_REQ message */ ++ strncpy(req->error, msg, sizeof(req->error)); ++ ++ /* Send the MM_DBG_TRIGGER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 0, -1, NULL); ++} ++ ++int rwnx_send_dbg_mem_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm) ++{ ++ struct dbg_mem_read_req *mem_read_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_READ_REQ message */ ++ mem_read_req = rwnx_msg_zalloc(DBG_MEM_READ_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_read_req)); ++ if (!mem_read_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_READ_REQ message */ ++ mem_read_req->memaddr = mem_addr; ++ ++ /* Send the DBG_MEM_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_read_req, 1, DBG_MEM_READ_CFM, cfm); ++} ++ ++int rwnx_send_dbg_mem_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_data) ++{ ++ struct dbg_mem_write_req *mem_write_req; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_WRITE_REQ message */ ++ mem_write_req = rwnx_msg_zalloc(DBG_MEM_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_write_req)); ++ if (!mem_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_WRITE_REQ message */ ++ mem_write_req->memaddr = mem_addr; ++ mem_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_write_req, 1, DBG_MEM_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_mask_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_mask, u32 mem_data) ++{ ++ struct dbg_mem_mask_write_req *mem_mask_write_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req = rwnx_msg_zalloc(DBG_MEM_MASK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_mask_write_req)); ++ if (!mem_mask_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req->memaddr = mem_addr; ++ mem_mask_write_req->memmask = mem_mask; ++ mem_mask_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_MASK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_mask_write_req, 1, DBG_MEM_MASK_WRITE_CFM, NULL); ++} ++ ++#ifdef CONFIG_RFTEST ++int rwnx_send_rftest_req(struct rwnx_hw *rwnx_hw, u32_l cmd, u32_l argc, u8_l *argv, struct dbg_rftest_cmd_cfm *cfm) ++{ ++ struct dbg_rftest_cmd_req *mem_rftest_cmd_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_RFTEST_CMD_REQ message */ ++ mem_rftest_cmd_req = rwnx_msg_zalloc(DBG_RFTEST_CMD_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_rftest_cmd_req)); ++ if (!mem_rftest_cmd_req) ++ return -ENOMEM; ++ ++ if (argc > 10) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_rftest_cmd_req->cmd = cmd; ++ mem_rftest_cmd_req->argc = argc; ++ if (argc != 0) ++ memcpy(mem_rftest_cmd_req->argv, argv, argc); ++ ++ /* Send the DBG_RFTEST_CMD_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_rftest_cmd_req, 1, DBG_RFTEST_CMD_CFM, cfm); ++} ++#endif ++ ++#ifdef CONFIG_MCU_MESSAGE ++int rwnx_send_dbg_custom_msg_req(struct rwnx_hw *rwnx_hw, ++ u32 cmd, void *buf, u32 len, u32 action, ++ struct dbg_custom_msg_cfm *cfm) ++{ ++ struct dbg_custom_msg_req *cust_msg_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_CUSTOM_MSG_REQ message */ ++ cust_msg_req = ++ rwnx_msg_zalloc(DBG_CUSTOM_MSG_REQ, TASK_DBG, DRV_TASK_ID, ++ offsetof(struct dbg_custom_msg_req, buf) + len); ++ if (!cust_msg_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_CUSTOM_MSG_REQ message */ ++ cust_msg_req->cmd = cmd; ++ cust_msg_req->len = len; ++ cust_msg_req->flags = action; ++ if (buf) { ++ memcpy(cust_msg_req->buf, buf, len); ++ } ++ ++ /* Send the DBG_CUSTOM_MSG_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, cust_msg_req, 1, DBG_CUSTOM_MSG_CFM, cfm); ++} ++#endif ++ ++int rwnx_send_dbg_set_mod_filter_req(struct rwnx_hw *rwnx_hw, u32 filter) ++{ ++ struct dbg_set_mod_filter_req *set_mod_filter_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_SET_MOD_FILTER_REQ message */ ++ set_mod_filter_req = ++ rwnx_msg_zalloc(DBG_SET_MOD_FILTER_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_set_mod_filter_req)); ++ if (!set_mod_filter_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_SET_MOD_FILTER_REQ message */ ++ set_mod_filter_req->mod_filter = filter; ++ ++ /* Send the DBG_SET_MOD_FILTER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_mod_filter_req, 1, DBG_SET_MOD_FILTER_CFM, NULL); ++} ++ ++int rwnx_send_dbg_set_sev_filter_req(struct rwnx_hw *rwnx_hw, u32 filter) ++{ ++ struct dbg_set_sev_filter_req *set_sev_filter_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_SET_SEV_FILTER_REQ message */ ++ set_sev_filter_req = ++ rwnx_msg_zalloc(DBG_SET_SEV_FILTER_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_set_sev_filter_req)); ++ if (!set_sev_filter_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_SET_SEV_FILTER_REQ message */ ++ set_sev_filter_req->sev_filter = filter; ++ ++ /* Send the DBG_SET_SEV_FILTER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_sev_filter_req, 1, DBG_SET_SEV_FILTER_CFM, NULL); ++} ++ ++int rwnx_send_dbg_get_sys_stat_req(struct rwnx_hw *rwnx_hw, ++ struct dbg_get_sys_stat_cfm *cfm) ++{ ++ void *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Allocate the message */ ++ req = rwnx_msg_zalloc(DBG_GET_SYS_STAT_REQ, TASK_DBG, DRV_TASK_ID, 0); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Send the DBG_MEM_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, DBG_GET_SYS_STAT_CFM, cfm); ++} ++ ++int rwnx_send_dbg_mem_block_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, u32 *mem_data) ++{ ++ struct dbg_mem_block_write_req *mem_blk_write_req; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req = rwnx_msg_zalloc(DBG_MEM_BLOCK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_block_write_req)); ++ if (!mem_blk_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req->memaddr = mem_addr; ++ mem_blk_write_req->memsize = mem_size; ++ memcpy(mem_blk_write_req->memdata, mem_data, mem_size); ++ ++ /* Send the DBG_MEM_BLOCK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_blk_write_req, 1, DBG_MEM_BLOCK_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_block_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, struct dbg_mem_block_read_cfm *cfm) ++{ ++ struct dbg_mem_block_read_req *mem_blk_read_req; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_BLOCK_READ_REQ message */ ++ mem_blk_read_req = rwnx_msg_zalloc(DBG_MEM_BLOCK_READ_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_block_read_req)); ++ if (!mem_blk_read_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_BLOCK_READ_REQ message */ ++ mem_blk_read_req->memaddr = mem_addr; ++ mem_blk_read_req->memsize = mem_size; ++ ++ /* Send the DBG_MEM_BLOCK_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_blk_read_req, 1, DBG_MEM_BLOCK_READ_CFM, cfm); ++} ++ ++int rwnx_send_dbg_start_app_req(struct rwnx_hw *rwnx_hw, u32 boot_addr, ++ u32 boot_type) ++{ ++ struct dbg_start_app_req *start_app_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_START_APP_REQ message */ ++ start_app_req = rwnx_msg_zalloc(DBG_START_APP_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_start_app_req)); ++ if (!start_app_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_START_APP_REQ message */ ++ start_app_req->bootaddr = boot_addr; ++ start_app_req->boottype = boot_type; ++ ++ /* Send the DBG_START_APP_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, start_app_req, 1, DBG_START_APP_CFM, NULL); ++} ++ ++int rwnx_send_cfg_rssi_req(struct rwnx_hw *rwnx_hw, u8 vif_index, int rssi_thold, u32 rssi_hyst) ++{ ++ struct mm_cfg_rssi_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_CFG_RSSI_REQ message */ ++ req = rwnx_msg_zalloc(MM_CFG_RSSI_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_cfg_rssi_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if (rwnx_hw->vif_table[vif_index] == NULL) ++ return 0; ++ ++ /* Set parameters for the MM_CFG_RSSI_REQ message */ ++ req->vif_index = vif_index; ++ req->rssi_thold = (s8)rssi_thold; ++ req->rssi_hyst = (u8)rssi_hyst; ++ ++ /* Send the MM_CFG_RSSI_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_CFG_RSSI_CFM, NULL); ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h +new file mode 100644 +index 000000000000..d44c66c4645a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h +@@ -0,0 +1,196 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_msg_tx.h ++ * ++ * @brief TX function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_MSG_TX_H_ ++#define _RWNX_MSG_TX_H_ ++ ++#include "rwnx_defs.h" ++ ++int rwnx_send_reset(struct rwnx_hw *rwnx_hw); ++int rwnx_send_start(struct rwnx_hw *rwnx_hw); ++int rwnx_send_version_req(struct rwnx_hw *rwnx_hw, struct mm_version_cfm *cfm); ++int rwnx_send_add_if (struct rwnx_hw *rwnx_hw, const unsigned char *mac, ++ enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm); ++int rwnx_send_remove_if (struct rwnx_hw *rwnx_hw, u8 vif_index, bool defer); ++int rwnx_send_set_channel(struct rwnx_hw *rwnx_hw, int phy_idx, ++ struct mm_set_channel_cfm *cfm); ++int rwnx_send_key_add(struct rwnx_hw *rwnx_hw, u8 vif_idx, u8 sta_idx, bool pairwise, ++ u8 *key, u8 key_len, u8 key_idx, u8 cipher_suite, ++ struct mm_key_add_cfm *cfm); ++int rwnx_send_key_del(struct rwnx_hw *rwnx_hw, uint8_t hw_key_idx); ++int rwnx_send_bcn(struct rwnx_hw *rwnx_hw, u8 *buf, u8 vif_idx, u16 bcn_len); ++ ++int rwnx_send_bcn_change(struct rwnx_hw *rwnx_hw, u8 vif_idx, u32 bcn_addr, ++ u16 bcn_len, u16 tim_oft, u16 tim_len, u16 *csa_oft); ++int rwnx_send_tim_update(struct rwnx_hw *rwnx_hw, u8 vif_idx, u16 aid, ++ u8 tx_status); ++int rwnx_send_roc(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct ieee80211_channel *chan, unsigned int duration, struct mm_remain_on_channel_cfm *roc_cfm); ++int rwnx_send_cancel_roc(struct rwnx_hw *rwnx_hw); ++int rwnx_send_set_power(struct rwnx_hw *rwnx_hw, u8 vif_idx, s8 pwr, ++ struct mm_set_power_cfm *cfm); ++int rwnx_send_set_edca(struct rwnx_hw *rwnx_hw, u8 hw_queue, u32 param, ++ bool uapsd, u8 inst_nbr); ++int rwnx_send_tdls_chan_switch_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, bool sta_initiator, ++ u8 oper_class, struct cfg80211_chan_def *chandef, ++ struct tdls_chan_switch_cfm *cfm); ++int rwnx_send_tdls_cancel_chan_switch_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, ++ struct tdls_cancel_chan_switch_cfm *cfm); ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++int rwnx_send_p2p_oppps_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 ctw, struct mm_set_p2p_oppps_cfm *cfm); ++int rwnx_send_p2p_noa_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ int count, int interval, int duration, ++ bool dyn_noa, struct mm_set_p2p_noa_cfm *cfm); ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++#ifdef AICWF_ARP_OFFLOAD ++int rwnx_send_arpoffload_en_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u32_l ipaddr, u8_l enable); ++#endif ++int rwnx_send_rf_config_req(struct rwnx_hw *rwnx_hw, u8_l ofst, u8_l sel, u8_l *tbl, u16_l len); ++int rwnx_send_rf_calib_req(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); ++int rwnx_send_get_macaddr_req(struct rwnx_hw *rwnx_hw, struct mm_get_mac_addr_cfm *cfm); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_me_chan_config_req(struct rwnx_hw *rwnx_hw, char *ccode); ++int rwnx_send_me_set_control_port_req(struct rwnx_hw *rwnx_hw, bool opened, ++ u8 sta_idx); ++int rwnx_send_me_sta_add(struct rwnx_hw *rwnx_hw, struct station_parameters *params, ++ const u8 *mac, u8 inst_nbr, struct me_sta_add_cfm *cfm); ++int rwnx_send_me_sta_del(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool tdls_sta); ++int rwnx_send_me_traffic_ind(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool uapsd, u8 tx_status); ++int rwnx_send_me_rc_stats(struct rwnx_hw *rwnx_hw, u8 sta_idx, ++ struct me_rc_stats_cfm *cfm); ++int rwnx_send_me_rc_set_rate(struct rwnx_hw *rwnx_hw, ++ u8 sta_idx, ++ u16 rate_idx); ++int rwnx_send_me_set_ps_mode(struct rwnx_hw *rwnx_hw, u8 ps_mode); ++int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter); ++int rwnx_send_sm_connect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct cfg80211_connect_params *sme, ++ struct sm_connect_cfm *cfm); ++int rwnx_send_sm_disconnect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 reason); ++int rwnx_send_sm_external_auth_required_rsp(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 status); ++int rwnx_send_apm_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_ap_settings *settings, ++ struct apm_start_cfm *cfm, ++ struct rwnx_ipc_elem_var *elem); ++int rwnx_send_apm_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); ++int rwnx_send_scanu_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct cfg80211_scan_request *param); ++int rwnx_send_scanu_cancel_req(struct rwnx_hw *rwnx_hw, ++ struct scan_cancel_cfm *cfm); ++ ++int rwnx_send_apm_start_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_chan_def *chandef, ++ struct apm_start_cac_cfm *cfm); ++int rwnx_send_apm_stop_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); ++int rwnx_send_tdls_peer_traffic_ind_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif); ++int rwnx_send_config_monitor_req(struct rwnx_hw *rwnx_hw, ++ struct cfg80211_chan_def *chandef, ++ struct me_config_monitor_cfm *cfm); ++int rwnx_send_mesh_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ const struct mesh_config *conf, const struct mesh_setup *setup, ++ struct mesh_start_cfm *cfm); ++int rwnx_send_mesh_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct mesh_stop_cfm *cfm); ++int rwnx_send_mesh_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u32 mask, const struct mesh_config *p_mconf, struct mesh_update_cfm *cfm); ++int rwnx_send_mesh_peer_info_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, struct mesh_peer_info_cfm *cfm); ++void rwnx_send_mesh_peer_update_ntf(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, u8 mlink_state); ++void rwnx_send_mesh_path_create_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *tgt_addr); ++int rwnx_send_mesh_path_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, const u8 *tgt_addr, ++ const u8 *p_nhop_addr, struct mesh_path_update_cfm *cfm); ++void rwnx_send_mesh_proxy_add_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *ext_addr); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_BFMER ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_send_bfmer_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ const struct ieee80211_vht_cap *vht_cap); ++#endif /* CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++int rwnx_send_mu_group_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* CONFIG_RWNX_BFMER */ ++ ++/* Debug messages */ ++int rwnx_send_dbg_trigger_req(struct rwnx_hw *rwnx_hw, char *msg); ++int rwnx_send_dbg_mem_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm); ++int rwnx_send_dbg_mem_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_data); ++int rwnx_send_dbg_mem_mask_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_mask, u32 mem_data); ++int rwnx_send_dbg_set_mod_filter_req(struct rwnx_hw *rwnx_hw, u32 filter); ++#ifdef CONFIG_RFTEST ++int rwnx_send_rftest_req(struct rwnx_hw *rwnx_hw, u32_l cmd, u32_l argc, u8_l *argv, struct dbg_rftest_cmd_cfm *cfm); ++#endif ++#ifdef CONFIG_MCU_MESSAGE ++int rwnx_send_dbg_custom_msg_req(struct rwnx_hw *rwnx_hw, ++ u32 cmd, void *buf, u32 len, u32 action, ++ struct dbg_custom_msg_cfm *cfm); ++#endif ++int rwnx_send_dbg_set_sev_filter_req(struct rwnx_hw *rwnx_hw, u32 filter); ++int rwnx_send_dbg_get_sys_stat_req(struct rwnx_hw *rwnx_hw, ++ struct dbg_get_sys_stat_cfm *cfm); ++int rwnx_send_dbg_mem_block_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, u32 *mem_data); ++int rwnx_send_dbg_mem_block_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, struct dbg_mem_block_read_cfm *cfm); ++int rwnx_send_dbg_start_app_req(struct rwnx_hw *rwnx_hw, u32 boot_addr, ++ u32 boot_type); ++int rwnx_send_cfg_rssi_req(struct rwnx_hw *rwnx_hw, u8 vif_index, int rssi_thold, u32 rssi_hyst); ++int rwnx_send_disable_agg_req(struct rwnx_hw *rwnx_hw, u8_l agg_disable, u8_l agg_disable_rx, u8_l sta_idx); ++int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enable_nullcts); ++int rwnx_send_get_sta_info_req(struct rwnx_hw *rwnx_hw, u8_l sta_idx, struct mm_get_sta_info_cfm *cfm); ++int rwnx_send_set_stack_start_req(struct rwnx_hw *rwnx_hw, u8_l on, u8_l efuse_valid, u8_l set_vendor_info, ++ u8_l fwtrace_redir_en, struct mm_set_stack_start_cfm *cfm); ++int rwnx_send_txop_req(struct rwnx_hw *rwnx_hw, uint16_t *txop, u8_l long_nav_en, u8_l cfe_en); ++int rwnx_send_get_temp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm); ++int rwnx_send_set_temp_comp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm); ++int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, int32_t *param, int32_t *param_out); ++int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, int32_t *param_in, int32_t *param_out); ++int rwnx_send_mask_set_ext_flags_req(struct rwnx_hw *rwnx_hw, uint32_t flags_mask, uint32_t flags_val, struct mm_set_vendor_swconfig_cfm *cfm); ++int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_version_cfm *cfm); ++int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_ofst_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_ofst2x_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_ofst2x_v2_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_set_filter(struct rwnx_hw *rwnx_hw, uint32_t filter); ++int rwnx_send_txpwr_lvl_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_v4_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw); ++#ifdef CONFIG_APF ++int rwnx_send_set_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len); ++int rwnx_send_get_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len); ++#endif ++ ++#ifdef CONFIG_SDIO_BT ++int rwnx_sdio_bt_send_req(struct rwnx_hw *rwnx_hw,uint32_t len, struct sk_buff *skb); ++#endif ++ ++#endif /* _RWNX_MSG_TX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c +new file mode 100644 +index 000000000000..538f14306afb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c +@@ -0,0 +1,659 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_mu_group.c ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_events.h" ++ ++ ++/** ++ * rwnx_mu_group_sta_init - Initialize group information for a STA ++ * ++ * @sta: Sta to initialize ++ */ ++void rwnx_mu_group_sta_init(struct rwnx_sta *sta, ++ const struct ieee80211_vht_cap *vht_cap) ++{ ++ sta->group_info.map = 0; ++ sta->group_info.cnt = 0; ++ sta->group_info.active.next = LIST_POISON1; ++ sta->group_info.update.next = LIST_POISON1; ++ sta->group_info.last_update = 0; ++ sta->group_info.traffic = 0; ++ sta->group_info.group = 0; ++ ++ if (!vht_cap || ++ !(vht_cap->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { ++ sta->group_info.map = RWNX_SU_GROUP; ++ } ++} ++ ++/** ++ * rwnx_mu_group_sta_del - Remove a sta from all MU group ++ * ++ * @rwnx_hw: main driver data ++ * @sta: STA to remove ++ * ++ * Remove one sta from all the MU groups it belongs to. ++ */ ++void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ int i, j, group_id; ++ bool lock_taken; ++ u64 map; ++ ++ lock_taken = (down_interruptible(&mu->lock) == 0); ++ ++ group_sta_for_each(sta, group_id, map) { ++ struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id); ++ ++ for (i = 0; i < CONFIG_USER_MAX; i++) { ++ if (group->users[i] == sta) { ++ group->users[i] = NULL; ++ group->user_cnt--; ++ /* Don't keep group with only one user */ ++ if (group->user_cnt == 1) { ++ for (j = 0; j < CONFIG_USER_MAX; j++) { ++ if (group->users[j]) { ++ group->users[j]->group_info.cnt--; ++ group->users[j]->group_info.map &= ~BIT_ULL(group->group_id); ++ if (group->users[j]->group_info.group == group_id) ++ group->users[j]->group_info.group = 0; ++ group->user_cnt--; ++ break; ++ } ++ } ++ mu->group_cnt--; ++ trace_mu_group_delete(group->group_id); ++ } else { ++ trace_mu_group_update(group); ++ } ++ break; ++ } ++ } ++ ++ WARN((i == CONFIG_USER_MAX), "sta %d doesn't belongs to group %d", ++ sta->sta_idx, group_id); ++ } ++ ++ sta->group_info.map = 0; ++ sta->group_info.cnt = 0; ++ sta->group_info.traffic = 0; ++ ++ if (sta->group_info.active.next != LIST_POISON1) ++ list_del(&sta->group_info.active); ++ ++ if (sta->group_info.update.next != LIST_POISON1) ++ list_del(&sta->group_info.update); ++ ++ if (lock_taken) ++ up(&mu->lock); ++} ++ ++/** ++ * rwnx_mu_group_sta_get_map - Get the list of group a STA belongs to ++ * ++ * @sta: pointer to the sta ++ * ++ * @return the list of group a STA belongs to as a bitfield ++ */ ++u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta) ++{ ++ if (sta) ++ return sta->group_info.map; ++ return 0; ++} ++ ++/** ++ * rwnx_mu_group_sta_get_pos - Get sta position in a group ++ * ++ * @rwnx_hw: main driver data ++ * @sta: pointer to the sta ++ * @group_id: Group id ++ * ++ * @return the positon of @sta in group @group_id or -1 if the sta ++ * doesn't belongs to the group (or group id is invalid) ++ */ ++int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int group_id) ++{ ++ struct rwnx_mu_group *group; ++ int i; ++ ++ group = rwnx_mu_group_from_id(&rwnx_hw->mu, group_id); ++ if (!group) ++ return -1; ++ ++ for (i = 0; i < CONFIG_USER_MAX; i++) { ++ if (group->users[i] == sta) ++ return i; ++ } ++ ++ WARN(1, "sta %d doesn't belongs to group %d", ++ sta->sta_idx, group_id); ++ return -1; ++} ++ ++/** ++ * rwnx_mu_group_move_head - Move (or add) one element at the top of a list ++ * ++ * @list: list pointer ++ * @elem: element to move (or add) at the top of @list ++ * ++ */ ++static inline ++void rwnx_mu_group_move_head(struct list_head *list, struct list_head *elem) ++{ ++ if (elem->next != LIST_POISON1) { ++ __list_del_entry(elem); ++ } ++ list_add(elem, list); ++} ++ ++/** ++ * rwnx_mu_group_remove_users - Remove all the users of a group ++ * ++ * @mu: pointer on MU info ++ * @group: pointer on group to remove users from ++ * ++ * Loop over all users one one group and remove this group from their ++ * map (and count). ++ * Each users is also added to the update_sta list, so that group info ++ * will be resent to fw for this user. ++ */ ++static inline ++void rwnx_mu_group_remove_users(struct rwnx_mu_info *mu, ++ struct rwnx_mu_group *group) ++{ ++ struct rwnx_sta *sta; ++ int i, group_id = group->group_id; ++ ++ for (i = 0; i < CONFIG_USER_MAX; i++) { ++ if (group->users[i]) { ++ sta = group->users[i]; ++ group->users[i] = NULL; ++ sta->group_info.cnt--; ++ sta->group_info.map &= ~BIT_ULL(group_id); ++ rwnx_mu_group_move_head(&mu->update_sta, ++ &sta->group_info.update); ++ } ++ } ++ ++ if (group->user_cnt) ++ mu->group_cnt--; ++ group->user_cnt = 0; ++ trace_mu_group_delete(group_id); ++} ++ ++/** ++ * rwnx_mu_group_add_users - Add users to a group ++ * ++ * @mu: pointer on MU info ++ * @group: pointer on group to add users in ++ * @nb_user: number of users to ad ++ * @users: table of user to add ++ * ++ * Add @nb_users to @group (which may already have users) ++ * Each new users is added to the first free position. ++ * It is assume that @group has at least @nb_user free position. If it is not ++ * case it only add the number of users needed to complete the group. ++ * Each users (effectively added to @group) is also added to the update_sta ++ * list, so that group info will be resent to fw for this user. ++ */ ++static inline ++void rwnx_mu_group_add_users(struct rwnx_mu_info *mu, ++ struct rwnx_mu_group *group, ++ int nb_user, struct rwnx_sta **users) ++{ ++ int i, j, group_id = group->group_id; ++ ++ if (!group->user_cnt) ++ mu->group_cnt++; ++ ++ j = 0; ++ for (i = 0; i < nb_user ; i++) { ++ for (; j < CONFIG_USER_MAX ; j++) { ++ if (group->users[j] == NULL) { ++ group->users[j] = users[i]; ++ users[i]->group_info.cnt++; ++ users[i]->group_info.map |= BIT_ULL(group_id); ++ ++ rwnx_mu_group_move_head(&(mu->update_sta), ++ &(users[i]->group_info.update)); ++ group->user_cnt++; ++ j++; ++ break; ++ } ++ ++ WARN(j == (CONFIG_USER_MAX - 1), ++ "Too many user for group %d (nb_user=%d)", ++ group_id, group->user_cnt + nb_user - i); ++ } ++ } ++ ++ trace_mu_group_update(group); ++} ++ ++ ++/** ++ * rwnx_mu_group_create_one - create on group with a specific group of user ++ * ++ * @mu: pointer on MU info ++ * @nb_user: number of user to include in the group (<= CONFIG_USER_MAX) ++ * @users: table of users ++ * ++ * Try to create a new group with a specific group of users. ++ * 1- First it checks if a group containing all this users already exists. ++ * ++ * 2- Then it checks if it is possible to complete a group which already ++ * contains at least one user. ++ * ++ * 3- Finally it create a new group. To do so, it take take the last group of ++ * the active_groups list, remove all its current users and add the new ones ++ * ++ * In all cases, the group selected is moved at the top of the active_groups ++ * list ++ * ++ * @return 1 if a new group has been created and 0 otherwise ++ */ ++static ++int rwnx_mu_group_create_one(struct rwnx_mu_info *mu, int nb_user, ++ struct rwnx_sta **users, int *nb_group_left) ++{ ++ int i, group_id; ++ struct rwnx_mu_group *group; ++ u64 group_match; ++ u64 group_avail; ++ ++ group_match = users[0]->group_info.map; ++ group_avail = users[0]->group_info.map; ++ for (i = 1; i < nb_user ; i++) { ++ group_match &= users[i]->group_info.map; ++ group_avail |= users[i]->group_info.map; ++ ++ } ++ ++ if (group_match) { ++ /* a group (or more) with all the users already exist */ ++ group_id = RWNX_GET_FIRST_GROUP_ID(group_match); ++ group = rwnx_mu_group_from_id(mu, group_id); ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++ return 0; ++ } ++ ++#if CONFIG_USER_MAX > 2 ++ if (group_avail) { ++ /* check if we can complete a group */ ++ struct rwnx_sta *users2[CONFIG_USER_MAX]; ++ int nb_user2; ++ ++ group_for_each(group_id, group_avail) { ++ group = rwnx_mu_group_from_id(mu, group_id); ++ if (group->user_cnt == CONFIG_USER_MAX) ++ continue; ++ ++ nb_user2 = 0; ++ for (i = 0; i < nb_user ; i++) { ++ if (!(users[i]->group_info.map & BIT_ULL(group_id))) { ++ users2[nb_user2] = users[i]; ++ nb_user2++; ++ } ++ } ++ ++ if ((group->user_cnt + nb_user2) <= CONFIG_USER_MAX) { ++ rwnx_mu_group_add_users(mu, group, nb_user2, users2); ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++ return 0; ++ } ++ } ++ } ++#endif /* CONFIG_USER_MAX > 2*/ ++ ++ /* create a new group */ ++ group = list_last_entry(&mu->active_groups, struct rwnx_mu_group, list); ++ rwnx_mu_group_remove_users(mu, group); ++ rwnx_mu_group_add_users(mu, group, nb_user, users); ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++ (*nb_group_left)--; ++ ++ return 1; ++} ++ ++/** ++ * rwnx_mu_group_create - Create new groups containing one specific sta ++ * ++ * @mu: pointer on MU info ++ * @sta: sta to add in each group ++ * @nb_group_left: maximum number to new group allowed. (updated on exit) ++ * ++ * This will try to create "all the possible" group with a specific sta being ++ * a member of all these group. ++ * The function simply loops over the @active_sta list (starting from @sta). ++ * When it has (CONFIG_USER_MAX - 1) users it try to create a new group with ++ * these users (plus @sta). ++ * Loops end when there is no more users, or no more new group is allowed ++ * ++ */ ++static ++void rwnx_mu_group_create(struct rwnx_mu_info *mu, struct rwnx_sta *sta, ++ int *nb_group_left) ++{ ++ struct rwnx_sta *user_sta = sta; ++ struct rwnx_sta *users[CONFIG_USER_MAX]; ++ int nb_user = 1; ++ ++ users[0] = sta; ++ while (*nb_group_left) { ++ ++ list_for_each_entry_continue(user_sta, &mu->active_sta, group_info.active) { ++ users[nb_user] = user_sta; ++ if (++nb_user == CONFIG_USER_MAX) { ++ break; ++ } ++ } ++ ++ if (nb_user > 1) { ++ if (rwnx_mu_group_create_one(mu, nb_user, users, nb_group_left)) ++ (*nb_group_left)--; ++ ++ if (nb_user < CONFIG_USER_MAX) ++ break; ++ else ++ nb_user = 1; ++ } else ++ break; ++ } ++} ++ ++/** ++ * rwnx_mu_group_work - process function of the "group_work" ++ * ++ * The work is scheduled when several sta (MU beamformee capable) are active. ++ * When called, the @active_sta contains the list of the active sta (starting ++ * from the most recent one), and @active_groups is the list of all possible ++ * groups ordered so that the first one is the most recently used. ++ * ++ * This function will create new groups, starting from group containing the ++ * most "active" sta. ++ * For example if the list of sta is : ++ * sta8 -> sta3 -> sta4 -> sta7 -> sta1 ++ * and the number of user per group is 3, it will create grooups : ++ * - sta8 / sta3 / sta4 ++ * - sta8 / sta7 / sta1 ++ * - sta3 / sta4 / sta7 ++ * - sta3 / sta1 ++ * - sta4 / sta7 / sta1 ++ * - sta7 / sta1 ++ * ++ * To create new group, the least used group are first selected. ++ * It is only allowed to create NX_MU_GROUP_MAX per iteration. ++ * ++ * Once groups have been updated, mu group information is update to the fw. ++ * To do so it use the @update_sta list to know which sta has been affected. ++ * As it is necessary to wait for fw confirmation before using this new group ++ * MU is temporarily disabled during group update ++ * ++ * Work is then rescheduled. ++ * ++ * At the end of the function, both @active_sta and @update_sta list are empty. ++ * ++ * Note: ++ * - This is still a WIP, and will require more tuning ++ * - not all combinations are created, to avoid to much processing. ++ * - reschedule delay should be adaptative ++ */ ++void rwnx_mu_group_work(struct work_struct *ws) ++{ ++ struct delayed_work *dw = container_of(ws, struct delayed_work, work); ++ struct rwnx_mu_info *mu = container_of(dw, struct rwnx_mu_info, group_work); ++ struct rwnx_hw *rwnx_hw = container_of(mu, struct rwnx_hw, mu); ++ struct rwnx_sta *sta, *next; ++ int nb_group_left = NX_MU_GROUP_MAX; ++ ++ if (WARN(!rwnx_hw->mod_params->mutx, ++ "In group formation work, but mutx disabled")) ++ return; ++ ++ if (down_interruptible(&mu->lock) != 0) ++ return; ++ ++ mu->update_count++; ++ if (!mu->update_count) ++ mu->update_count++; ++ ++ list_for_each_entry_safe(sta, next, &mu->active_sta, group_info.active) { ++ if (nb_group_left) ++ rwnx_mu_group_create(mu, sta, &nb_group_left); ++ ++ sta->group_info.last_update = mu->update_count; ++ list_del(&sta->group_info.active); ++ } ++ ++ if (!list_empty(&mu->update_sta)) { ++ list_for_each_entry_safe(sta, next, &mu->update_sta, group_info.update) { ++ rwnx_send_mu_group_update_req(rwnx_hw, sta); ++ list_del(&sta->group_info.update); ++ } ++ } ++ ++ mu->next_group_select = jiffies; ++ rwnx_mu_group_sta_select(rwnx_hw); ++ up(&mu->lock); ++ ++ return; ++} ++ ++/** ++ * rwnx_mu_group_init - Initialize MU groups ++ * ++ * @rwnx_hw: main driver data ++ * ++ * Initialize all MU group ++ */ ++void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ int i; ++ ++ INIT_LIST_HEAD(&mu->active_groups); ++ INIT_LIST_HEAD(&mu->active_sta); ++ INIT_LIST_HEAD(&mu->update_sta); ++ ++ for (i = 0; i < NX_MU_GROUP_MAX; i++) { ++ int j; ++ mu->groups[i].user_cnt = 0; ++ mu->groups[i].group_id = i + 1; ++ for (j = 0; j < CONFIG_USER_MAX; j++) { ++ mu->groups[i].users[j] = NULL; ++ } ++ list_add(&mu->groups[i].list, &mu->active_groups); ++ } ++ ++ mu->update_count = 1; ++ mu->group_cnt = 0; ++ mu->next_group_select = jiffies; ++ INIT_DELAYED_WORK(&mu->group_work, rwnx_mu_group_work); ++ sema_init(&mu->lock, 1); ++} ++ ++/** ++ * rwnx_mu_set_active_sta - mark a STA as active ++ * ++ * @rwnx_hw: main driver data ++ * @sta: pointer to the sta ++ * @traffic: Number of buffers to add in the sta's traffic counter ++ * ++ * If @sta is MU beamformee capable (and MU-MIMO tx is enabled) move the ++ * sta at the top of the @active_sta list. ++ * It also schedule the group_work if not already scheduled and the list ++ * contains more than one sta. ++ * ++ * If a STA was already in the list during the last group update ++ * (i.e. sta->group_info.last_update == mu->update_count) it is not added ++ * back to the list until a sta that wasn't active during the last update is ++ * added. This is to avoid scheduling group update with a list of sta that ++ * were all already in the list during previous update. ++ * ++ * It is called with mu->lock taken. ++ */ ++void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int traffic) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ ++ if (!sta || (sta->group_info.map & RWNX_SU_GROUP)) ++ return; ++ ++ sta->group_info.traffic += traffic; ++ ++ if ((sta->group_info.last_update != mu->update_count) || ++ !list_empty(&mu->active_sta)) { ++ ++ rwnx_mu_group_move_head(&mu->active_sta, &sta->group_info.active); ++ ++ if (!delayed_work_pending(&mu->group_work) && ++ !list_is_singular(&mu->active_sta)) { ++ schedule_delayed_work(&mu->group_work, ++ msecs_to_jiffies(RWNX_MU_GROUP_INTERVAL)); ++ } ++ } ++} ++ ++/** ++ * rwnx_mu_set_active_group - mark a MU group as active ++ * ++ * @rwnx_hw: main driver data ++ * @group_id: Group id ++ * ++ * move a group at the top of the @active_groups list ++ */ ++void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id); ++ ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++} ++ ++ ++/** ++ * rwnx_mu_group_sta_select - Select the best group for MU stas ++ * ++ * @rwnx_hw: main driver data ++ * ++ * For each MU capable client of AP interfaces this function tries to select ++ * the best group to use. ++ * ++ * In first pass, gather information from all stations to form statistics ++ * for each group for the previous @RWNX_MU_GROUP_SELECT_INTERVAL interval: ++ * - number of buffers transmitted ++ * - number of user ++ * ++ * Then groups with more than 2 active users, are assigned after being ordered ++ * by traffic : ++ * - group with highest traffic is selected: set this group for all its users ++ * - update nb_users for all others group (as one sta may be in several groups) ++ * - select the next group that have still mor than 2 users and assign it. ++ * - continue until all group are processed ++ * ++ */ ++void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ int nb_users[NX_MU_GROUP_MAX + 1]; ++ int traffic[NX_MU_GROUP_MAX + 1]; ++ int order[NX_MU_GROUP_MAX + 1]; ++ struct rwnx_sta *sta; ++ struct rwnx_vif *vif; ++ struct list_head *head; ++ u64 map; ++ int i, j, update, group_id, tmp, cnt = 0; ++ ++ if (!mu->group_cnt || time_before(jiffies, mu->next_group_select)) ++ return; ++ ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ ++ if (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP) ++ continue; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ head = &vif->ap.sta_list; ++#else ++ head = &vif->stations; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ memset(nb_users, 0, sizeof(nb_users)); ++ memset(traffic, 0, sizeof(traffic)); ++ list_for_each_entry(sta, head, list) { ++ int sta_traffic = sta->group_info.traffic; ++ ++ /* reset statistics for next selection */ ++ sta->group_info.traffic = 0; ++ if (sta->group_info.group) ++ trace_mu_group_selection(sta, 0); ++ sta->group_info.group = 0; ++ ++ if (sta->group_info.cnt == 0 || ++ sta_traffic < RWNX_MU_GROUP_MIN_TRAFFIC) ++ continue; ++ ++ group_sta_for_each(sta, group_id, map) { ++ nb_users[group_id]++; ++ traffic[group_id] += sta_traffic; ++ ++ /* list group with 2 users or more */ ++ if (nb_users[group_id] == 2) ++ order[cnt++] = group_id; ++ } ++ } ++ ++ /* reorder list of group with more that 2 users */ ++ update = 1; ++ while (update) { ++ update = 0; ++ for (i = 0; i < cnt - 1; i++) { ++ if (traffic[order[i]] < traffic[order[i + 1]]) { ++ tmp = order[i]; ++ order[i] = order[i + 1]; ++ order[i + 1] = tmp; ++ update = 1; ++ } ++ } ++ } ++ ++ /* now assign group in traffic order */ ++ for (i = 0; i < cnt; i++) { ++ struct rwnx_mu_group *group; ++ group_id = order[i]; ++ ++ if (nb_users[group_id] < 2) ++ continue; ++ ++ group = rwnx_mu_group_from_id(mu, group_id); ++ for (j = 0; j < CONFIG_USER_MAX; j++) { ++ if (group->users[j]) { ++ trace_mu_group_selection(group->users[j], group_id); ++ group->users[j]->group_info.group = group_id; ++ ++ group_sta_for_each(group->users[j], tmp, map) { ++ if (group_id != tmp) ++ nb_users[tmp]--; ++ } ++ } ++ } ++ } ++ } ++ ++ mu->next_group_select = jiffies + ++ msecs_to_jiffies(RWNX_MU_GROUP_SELECT_INTERVAL); ++ mu->next_group_select |= 1; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h +new file mode 100644 +index 000000000000..c24bb0396e9f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h +@@ -0,0 +1,181 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_mu_group.h ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_MU_GROUP_H_ ++#define _RWNX_MU_GROUP_H_ ++ ++#include ++#include ++ ++struct rwnx_hw; ++struct rwnx_sta; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ ++/** ++ * struct rwnx_sta_group_info - Group Information for a STA ++ * ++ * @active: node for @mu->active_sta list ++ * @update: node for @mu->update_sta list ++ * @cnt: Number of groups the STA belongs to ++ * @map: Bitfield of groups the sta belongs to ++ * @traffic: Number of buffers sent since previous group selection ++ * @group: Id of the group selected by previous group selection ++ * (cf @rwnx_mu_group_sta_select) ++ */ ++struct rwnx_sta_group_info { ++ struct list_head active; ++ struct list_head update; ++ u16 last_update; ++ int cnt; ++ u64 map; ++ int traffic; ++ u8 group; ++}; ++ ++/** ++ * struct mu_group_info - Information about the users of a group ++ * ++ * @list: node for mu->active_groups ++ * @group_id: Group identifier ++ * @user_cnt: Number of the users in the group ++ * @users: Pointer to the sta, ordered by user position ++ */ ++struct rwnx_mu_group { ++ struct list_head list; ++ int group_id; ++ int user_cnt; ++ struct rwnx_sta *users[CONFIG_USER_MAX]; ++}; ++ ++/** ++ * struct rwnx_mu_info - Information about all MU group ++ * ++ * @active_groups: List of all possible groups. Ordered from the most recently ++ * used one to the least one (and possibly never used) ++ * @active_sta: List of MU beamformee sta that have been active (since previous ++ * group update). Ordered from the most recently active. ++ * @update_sta: List of sta whose group information has changed and need to be ++ * updated at fw level ++ * @groups: Table of all groups ++ * @group_work: Work item used to schedule group update ++ * @update_count: Counter used to identify the last group formation update. ++ * (cf rwnx_sta_group_info.last_update) ++ * @lock: Lock taken during group update. If tx happens lock is taken, then tx ++ * will not used MU. ++ * @next_group_assign: Next time the group selection should be run ++ * (ref @rwnx_mu_group_sta_select) ++ * @group_cnt: Number of group created ++ */ ++struct rwnx_mu_info { ++ struct list_head active_groups; ++ struct list_head active_sta; ++ struct list_head update_sta; ++ struct rwnx_mu_group groups[NX_MU_GROUP_MAX]; ++ struct delayed_work group_work; ++ u16 update_count; ++ struct semaphore lock; ++ unsigned long next_group_select; ++ u8 group_cnt; ++}; ++ ++#define RWNX_SU_GROUP BIT_ULL(0) ++#define RWNX_MU_GROUP_MASK 0x7ffffffffffffffeULL ++#define RWNX_MU_GROUP_INTERVAL 200 /* in ms */ ++#define RWNX_MU_GROUP_SELECT_INTERVAL 100 /* in ms */ ++// minimum traffic in a RWNX_MU_GROUP_SELECT_INTERVAL to consider the sta ++#define RWNX_MU_GROUP_MIN_TRAFFIC 50 /* in number of packet */ ++ ++ ++#define RWNX_GET_FIRST_GROUP_ID(map) (fls64(map) - 1) ++ ++#define group_sta_for_each(sta, id, map) \ ++ do { \ ++ map = sta->group_info.map & RWNX_MU_GROUP_MASK; \ ++ for (id = (fls64(map) - 1) ; id > 0 ; \ ++ map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1)) \ ++ } while (0) ++ ++#define group_for_each(id, map) \ ++ for (id = (fls64(map) - 1) ; id > 0 ; \ ++ map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1)) ++ ++#define RWNX_MUMIMO_INFO_POS_ID(info) (((info) >> 6) & 0x3) ++#define RWNX_MUMIMO_INFO_GROUP_ID(info) ((info) & 0x3f) ++ ++static inline ++struct rwnx_mu_group *rwnx_mu_group_from_id(struct rwnx_mu_info *mu, int id) ++{ ++ if (id > NX_MU_GROUP_MAX) ++ return NULL; ++ ++ return &mu->groups[id - 1]; ++} ++ ++ ++void rwnx_mu_group_sta_init(struct rwnx_sta *sta, ++ const struct ieee80211_vht_cap *vht_cap); ++void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); ++u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta); ++int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int group_id); ++ ++void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw); ++ ++void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int traffic); ++void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id); ++void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw); ++ ++ ++#else /* ! CONFIG_RWNX_MUMIMO_TX */ ++ ++static inline ++void rwnx_mu_group_sta_init(struct rwnx_sta *sta, ++ const struct ieee80211_vht_cap *vht_cap) ++{} ++ ++static inline ++void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{} ++ ++static inline ++u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta) ++{ ++ return 0; ++} ++ ++static inline ++int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int group_id) ++{ ++ return 0; ++} ++ ++static inline ++void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw) ++{} ++ ++static inline ++void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int traffic) ++{} ++ ++static inline ++void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id) ++{} ++ ++static inline ++void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw) ++{} ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++#endif /* _RWNX_MU_GROUP_H_ */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c +new file mode 100644 +index 000000000000..40dac946536d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c +@@ -0,0 +1,94 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_pci.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_dini.h" ++#include "rwnx_v7.h" ++ ++#define PCI_VENDOR_ID_DINIGROUP 0x17DF ++#define PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE 0x1907 ++ ++#define PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7 0x7011 ++ ++static const struct pci_device_id rwnx_pci_ids[] = { ++ {PCI_DEVICE(PCI_VENDOR_ID_DINIGROUP, PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7)}, ++ {0,} ++}; ++ ++ ++/* Uncomment this for depmod to create module alias */ ++/* We don't want this on development platform */ ++//MODULE_DEVICE_TABLE(pci, rwnx_pci_ids); ++ ++static int rwnx_pci_probe(struct pci_dev *pci_dev, ++ const struct pci_device_id *pci_id) ++{ ++ struct rwnx_plat *rwnx_plat = NULL; ++ void *drvdata; ++ int ret = -ENODEV; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (pci_id->vendor == PCI_VENDOR_ID_DINIGROUP) { ++ ret = rwnx_dini_platform_init(pci_dev, &rwnx_plat); ++ } else if (pci_id->vendor == PCI_VENDOR_ID_XILINX) { ++ ret = rwnx_v7_platform_init(pci_dev, &rwnx_plat); ++ } ++ ++ if (ret) ++ return ret; ++ ++ rwnx_plat->pci_dev = pci_dev; ++ ++ ret = rwnx_platform_init(rwnx_plat, &drvdata); ++ pci_set_drvdata(pci_dev, drvdata); ++ ++ if (ret) ++ rwnx_plat->deinit(rwnx_plat); ++ ++ return ret; ++} ++ ++static void rwnx_pci_remove(struct pci_dev *pci_dev) ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct rwnx_plat *rwnx_plat; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_hw = pci_get_drvdata(pci_dev); ++ rwnx_plat = rwnx_hw->plat; ++ ++ rwnx_platform_deinit(rwnx_hw); ++ rwnx_plat->deinit(rwnx_plat); ++ ++ pci_set_drvdata(pci_dev, NULL); ++} ++ ++static struct pci_driver rwnx_pci_drv = { ++ .name = KBUILD_MODNAME, ++ .id_table = rwnx_pci_ids, ++ .probe = rwnx_pci_probe, ++ .remove = rwnx_pci_remove ++}; ++ ++int rwnx_pci_register_drv(void) ++{ ++ return pci_register_driver(&rwnx_pci_drv); ++} ++ ++void rwnx_pci_unregister_drv(void) ++{ ++ pci_unregister_driver(&rwnx_pci_drv); ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h +new file mode 100644 +index 000000000000..d81578cbef48 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h +@@ -0,0 +1,17 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_pci.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_PCI_H_ ++#define _RWNX_PCI_H_ ++ ++int rwnx_pci_register_drv(void); ++void rwnx_pci_unregister_drv(void); ++ ++#endif /* _RWNX_PCI_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c +new file mode 100644 +index 000000000000..33bc63bd4057 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c +@@ -0,0 +1,3417 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_platform.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "rwnx_platform.h" ++#include "reg_access.h" ++#include "hal_desc.h" ++#include "rwnx_main.h" ++#include "rwnx_pci.h" ++#ifndef CONFIG_RWNX_FHOST ++#include "ipc_host.h" ++#endif /* !CONFIG_RWNX_FHOST */ ++#include "rwnx_msg_tx.h" ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++#include "aicwf_usb.h" ++#endif ++#include "md5.h" ++#include "aicwf_compat_8800dc.h" ++#include "aicwf_compat_8800d80.h" ++ ++#ifdef CONFIG_USE_FW_REQUEST ++#include ++#endif ++ ++#define FW_PATH_MAX_LEN 200 ++extern char aic_fw_path[FW_PATH_MAX_LEN]; ++ ++//Parser state ++#define INIT 0 ++#define CMD 1 ++#define PRINT 2 ++#define GET_VALUE 3 ++ ++ ++struct rwnx_plat *g_rwnx_plat; ++ ++typedef struct ++{ ++ txpwr_lvl_conf_t txpwr_lvl; ++ txpwr_lvl_conf_v2_t txpwr_lvl_v2; ++ txpwr_lvl_conf_v3_t txpwr_lvl_v3; ++ txpwr_lvl_conf_v4_t txpwr_lvl_v4; ++ txpwr_lvl_adj_conf_t txpwr_lvl_adj; ++ txpwr_loss_conf_t txpwr_loss; ++ txpwr_ofst_conf_t txpwr_ofst; ++ txpwr_ofst2x_conf_t txpwr_ofst2x; ++ txpwr_ofst2x_conf_v2_t txpwr_ofst2x_v2; ++ xtal_cap_conf_t xtal_cap; ++} userconfig_info_t; ++ ++userconfig_info_t userconfig_info = { ++ .txpwr_lvl = { ++ .enable = 1, ++ .dsss = 9, ++ .ofdmlowrate_2g4 = 8, ++ .ofdm64qam_2g4 = 8, ++ .ofdm256qam_2g4 = 8, ++ .ofdm1024qam_2g4 = 8, ++ .ofdmlowrate_5g = 11, ++ .ofdm64qam_5g = 10, ++ .ofdm256qam_5g = 9, ++ .ofdm1024qam_5g = 9 ++ }, ++ .txpwr_lvl_v2 = { ++ .enable = 1, ++ .pwrlvl_11b_11ag_2g4 = ++ //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, ++ .pwrlvl_11ax_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, ++ }, ++ .txpwr_lvl_v3 = { ++ .enable = 1, ++ .pwrlvl_11b_11ag_2g4 = ++ //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, ++ .pwrlvl_11ax_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, ++ .pwrlvl_11a_5g = ++ //NA, NA, NA, NA, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 0x80, 0x80, 0x80, 0x80, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15}, ++ .pwrlvl_11ax_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15, 14, 14}, ++ }, ++ .txpwr_lvl_v4 = { ++ .enable = 1, ++ .pwrlvl_11b_11ag_2g4 = ++ //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, ++ .pwrlvl_11ax_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, ++ .pwrlvl_11a_5g = ++ //6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15}, ++ .pwrlvl_11ax_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15, 14, 14}, ++ }, ++ .txpwr_loss = { ++ .loss_enable_2g4 = 0, ++ .loss_value_2g4 = 0, ++ .loss_enable_5g = 0, ++ .loss_value_5g = 0, ++ }, ++ .txpwr_ofst = { ++ .enable = 1, ++ .chan_1_4 = 0, ++ .chan_5_9 = 0, ++ .chan_10_13 = 0, ++ .chan_36_64 = 0, ++ .chan_100_120 = 0, ++ .chan_122_140 = 0, ++ .chan_142_165 = 0, ++ }, ++ .txpwr_ofst2x = { ++ .enable = 0, ++ .pwrofst2x_tbl_2g4 = ++ { // ch1-4, ch5-9, ch10-13 ++ { 0, 0, 0 }, // 11b ++ { 0, 0, 0 }, // ofdm_highrate ++ { 0, 0, 0 }, // ofdm_lowrate ++ }, ++ .pwrofst2x_tbl_5g = ++ { // ch42, ch58, ch106,ch122,ch138,ch155 ++ { 0, 0, 0, 0, 0, 0 }, // ofdm_lowrate ++ { 0, 0, 0, 0, 0, 0 }, // ofdm_highrate ++ { 0, 0, 0, 0, 0, 0 }, // ofdm_midrate ++ }, ++ }, ++ .txpwr_ofst2x_v2 = { ++ .enable = 0, ++ .pwrofst_flags = 0, ++ .pwrofst2x_tbl_2g4_ant0 = ++ { // 11b, ofdm_highrate, ofdm_lowrate ++ { 0, 0, 0 }, // ch1-4 ++ { 0, 0, 0 }, // ch5-9 ++ { 0, 0, 0 }, // ch10-13 ++ }, ++ .pwrofst2x_tbl_2g4_ant1 = ++ { // 11b, ofdm_highrate, ofdm_lowrate ++ { 0, 0, 0 }, // ch1-4 ++ { 0, 0, 0 }, // ch5-9 ++ { 0, 0, 0 }, // ch10-13 ++ }, ++ .pwrofst2x_tbl_5g_ant0 = ++ { // ofdm_highrate, ofdm_lowrate, ofdm_midrate ++ { 0, 0, 0 }, // ch42 ++ { 0, 0, 0 }, // ch58 ++ { 0, 0, 0 }, // ch106 ++ { 0, 0, 0 }, // ch122 ++ { 0, 0, 0 }, // ch138 ++ { 0, 0, 0 }, // ch155 ++ }, ++ .pwrofst2x_tbl_5g_ant1 = ++ { // ofdm_highrate, ofdm_lowrate, ofdm_midrate ++ { 0, 0, 0 }, // ch42 ++ { 0, 0, 0 }, // ch58 ++ { 0, 0, 0 }, // ch106 ++ { 0, 0, 0 }, // ch122 ++ { 0, 0, 0 }, // ch138 ++ { 0, 0, 0 }, // ch155 ++ }, ++ .pwrofst2x_tbl_6g_ant0 = { 0, }, // ofdm_highrate: 6e_ch7 ~ 6e_ch229 ++ .pwrofst2x_tbl_6g_ant1 = { 0, }, // ofdm_highrate: 6e_ch7 ~ 6e_ch229 ++ }, ++ .xtal_cap = { ++ .enable = 0, ++ .xtal_cap = 24, ++ .xtal_cap_fine = 31, ++ }, ++}; ++ ++typedef struct { ++ char ccode[3]; ++ Regions_code region; ++} reg_table; ++ ++/* If the region conflicts with the kernel, the actual authentication standard prevails */ ++reg_table reg_tables[] = { ++ {.ccode = "CN", .region = REGIONS_SRRC}, ++ {.ccode = "US", .region = REGIONS_FCC}, ++ {.ccode = "DE", .region = REGIONS_ETSI}, ++ {.ccode = "00", .region = REGIONS_DEFAULT}, ++ {.ccode = "WW", .region = REGIONS_DEFAULT}, ++ {.ccode = "XX", .region = REGIONS_DEFAULT}, ++ {.ccode = "JP", .region = REGIONS_JP}, ++ {.ccode = "AD", .region = REGIONS_ETSI}, ++ {.ccode = "AE", .region = REGIONS_ETSI}, ++ {.ccode = "AF", .region = REGIONS_ETSI}, ++ {.ccode = "AI", .region = REGIONS_ETSI}, ++ {.ccode = "AL", .region = REGIONS_ETSI}, ++ {.ccode = "AM", .region = REGIONS_ETSI}, ++ {.ccode = "AN", .region = REGIONS_ETSI}, ++ {.ccode = "AR", .region = REGIONS_FCC}, ++ {.ccode = "AS", .region = REGIONS_FCC}, ++ {.ccode = "AT", .region = REGIONS_ETSI}, ++ {.ccode = "AU", .region = REGIONS_ETSI}, ++ {.ccode = "AW", .region = REGIONS_ETSI}, ++ {.ccode = "AZ", .region = REGIONS_ETSI}, ++ {.ccode = "BA", .region = REGIONS_ETSI}, ++ {.ccode = "BB", .region = REGIONS_FCC}, ++ {.ccode = "BD", .region = REGIONS_JP}, ++ {.ccode = "BE", .region = REGIONS_ETSI}, ++ {.ccode = "BF", .region = REGIONS_FCC}, ++ {.ccode = "BG", .region = REGIONS_ETSI}, ++ {.ccode = "BH", .region = REGIONS_ETSI}, ++ {.ccode = "BL", .region = REGIONS_ETSI}, ++ {.ccode = "BM", .region = REGIONS_FCC}, ++ {.ccode = "BN", .region = REGIONS_JP}, ++ {.ccode = "BO", .region = REGIONS_JP}, ++ {.ccode = "BR", .region = REGIONS_FCC}, ++ {.ccode = "BS", .region = REGIONS_FCC}, ++ {.ccode = "BT", .region = REGIONS_ETSI}, ++ {.ccode = "BW", .region = REGIONS_ETSI}, ++ {.ccode = "BY", .region = REGIONS_ETSI}, ++ {.ccode = "BZ", .region = REGIONS_JP}, ++ {.ccode = "CA", .region = REGIONS_FCC}, ++ {.ccode = "CF", .region = REGIONS_FCC}, ++ {.ccode = "CH", .region = REGIONS_ETSI}, ++ {.ccode = "CI", .region = REGIONS_FCC}, ++ {.ccode = "CL", .region = REGIONS_ETSI}, ++ {.ccode = "CO", .region = REGIONS_FCC}, ++ {.ccode = "CR", .region = REGIONS_FCC}, ++ {.ccode = "CX", .region = REGIONS_FCC}, ++ {.ccode = "CY", .region = REGIONS_ETSI}, ++ {.ccode = "CZ", .region = REGIONS_ETSI}, ++ {.ccode = "DK", .region = REGIONS_ETSI}, ++ {.ccode = "DM", .region = REGIONS_FCC}, ++ {.ccode = "DO", .region = REGIONS_FCC}, ++ {.ccode = "DZ", .region = REGIONS_JP}, ++ {.ccode = "EC", .region = REGIONS_FCC}, ++ {.ccode = "EE", .region = REGIONS_ETSI}, ++ {.ccode = "EG", .region = REGIONS_ETSI}, ++ {.ccode = "ES", .region = REGIONS_ETSI}, ++ {.ccode = "ET", .region = REGIONS_ETSI}, ++ {.ccode = "FI", .region = REGIONS_ETSI}, ++ {.ccode = "FM", .region = REGIONS_FCC}, ++ {.ccode = "FR", .region = REGIONS_ETSI}, ++ {.ccode = "GB", .region = REGIONS_ETSI}, ++ {.ccode = "GD", .region = REGIONS_FCC}, ++ {.ccode = "GE", .region = REGIONS_ETSI}, ++ {.ccode = "GF", .region = REGIONS_ETSI}, ++ {.ccode = "GH", .region = REGIONS_FCC}, ++ {.ccode = "GI", .region = REGIONS_ETSI}, ++ {.ccode = "GL", .region = REGIONS_ETSI}, ++ {.ccode = "GP", .region = REGIONS_ETSI}, ++ {.ccode = "GR", .region = REGIONS_ETSI}, ++ {.ccode = "GT", .region = REGIONS_FCC}, ++ {.ccode = "GU", .region = REGIONS_FCC}, ++ {.ccode = "GY", .region = REGIONS_DEFAULT}, ++ {.ccode = "HK", .region = REGIONS_ETSI}, ++ {.ccode = "HN", .region = REGIONS_FCC}, ++ {.ccode = "HR", .region = REGIONS_ETSI}, ++ {.ccode = "HT", .region = REGIONS_FCC}, ++ {.ccode = "HU", .region = REGIONS_ETSI}, ++ {.ccode = "ID", .region = REGIONS_ETSI}, ++ {.ccode = "IE", .region = REGIONS_ETSI}, ++ {.ccode = "IL", .region = REGIONS_ETSI}, ++ {.ccode = "IN", .region = REGIONS_ETSI}, ++ {.ccode = "IQ", .region = REGIONS_ETSI}, ++ {.ccode = "IR", .region = REGIONS_JP}, ++ {.ccode = "IS", .region = REGIONS_ETSI}, ++ {.ccode = "IT", .region = REGIONS_ETSI}, ++ {.ccode = "JM", .region = REGIONS_FCC}, ++ {.ccode = "JO", .region = REGIONS_ETSI}, ++ {.ccode = "KE", .region = REGIONS_ETSI}, ++ {.ccode = "KG", .region = REGIONS_ETSI}, ++ {.ccode = "KH", .region = REGIONS_ETSI}, ++ {.ccode = "KN", .region = REGIONS_ETSI}, ++ {.ccode = "KP", .region = REGIONS_JP}, ++ {.ccode = "KR", .region = REGIONS_ETSI}, ++ {.ccode = "KW", .region = REGIONS_ETSI}, ++ {.ccode = "KY", .region = REGIONS_FCC}, ++ {.ccode = "KZ", .region = REGIONS_DEFAULT}, ++ {.ccode = "LB", .region = REGIONS_ETSI}, ++ {.ccode = "LC", .region = REGIONS_ETSI}, ++ {.ccode = "LI", .region = REGIONS_ETSI}, ++ {.ccode = "LK", .region = REGIONS_FCC}, ++ {.ccode = "LS", .region = REGIONS_ETSI}, ++ {.ccode = "LT", .region = REGIONS_ETSI}, ++ {.ccode = "LU", .region = REGIONS_ETSI}, ++ {.ccode = "LV", .region = REGIONS_ETSI}, ++ {.ccode = "LY", .region = REGIONS_ETSI}, ++ {.ccode = "MA", .region = REGIONS_ETSI}, ++ {.ccode = "MC", .region = REGIONS_ETSI}, ++ {.ccode = "MD", .region = REGIONS_ETSI}, ++ {.ccode = "ME", .region = REGIONS_ETSI}, ++ {.ccode = "MF", .region = REGIONS_ETSI}, ++ {.ccode = "MH", .region = REGIONS_FCC}, ++ {.ccode = "MK", .region = REGIONS_ETSI}, ++ {.ccode = "MN", .region = REGIONS_ETSI}, ++ {.ccode = "MO", .region = REGIONS_ETSI}, ++ {.ccode = "MP", .region = REGIONS_FCC}, ++ {.ccode = "MQ", .region = REGIONS_ETSI}, ++ {.ccode = "MR", .region = REGIONS_ETSI}, ++ {.ccode = "MT", .region = REGIONS_ETSI}, ++ {.ccode = "MU", .region = REGIONS_FCC}, ++ {.ccode = "MV", .region = REGIONS_ETSI}, ++ {.ccode = "MW", .region = REGIONS_ETSI}, ++ {.ccode = "MX", .region = REGIONS_FCC}, ++ {.ccode = "MY", .region = REGIONS_FCC}, ++ {.ccode = "NA", .region = REGIONS_ETSI}, ++ {.ccode = "NG", .region = REGIONS_ETSI}, ++ {.ccode = "NI", .region = REGIONS_FCC}, ++ {.ccode = "NL", .region = REGIONS_ETSI}, ++ {.ccode = "NO", .region = REGIONS_ETSI}, ++ {.ccode = "NP", .region = REGIONS_JP}, ++ {.ccode = "NZ", .region = REGIONS_ETSI}, ++ {.ccode = "OM", .region = REGIONS_ETSI}, ++ {.ccode = "PA", .region = REGIONS_FCC}, ++ {.ccode = "PE", .region = REGIONS_FCC}, ++ {.ccode = "PF", .region = REGIONS_ETSI}, ++ {.ccode = "PG", .region = REGIONS_FCC}, ++ {.ccode = "PH", .region = REGIONS_FCC}, ++ {.ccode = "PK", .region = REGIONS_ETSI}, ++ {.ccode = "PL", .region = REGIONS_ETSI}, ++ {.ccode = "PM", .region = REGIONS_ETSI}, ++ {.ccode = "PR", .region = REGIONS_FCC}, ++ {.ccode = "PT", .region = REGIONS_ETSI}, ++ {.ccode = "PW", .region = REGIONS_FCC}, ++ {.ccode = "PY", .region = REGIONS_FCC}, ++ {.ccode = "QA", .region = REGIONS_ETSI}, ++ {.ccode = "RE", .region = REGIONS_ETSI}, ++ {.ccode = "RO", .region = REGIONS_ETSI}, ++ {.ccode = "RS", .region = REGIONS_ETSI}, ++ {.ccode = "RU", .region = REGIONS_ETSI}, ++ {.ccode = "RW", .region = REGIONS_FCC}, ++ {.ccode = "SA", .region = REGIONS_ETSI}, ++ {.ccode = "SE", .region = REGIONS_ETSI}, ++ {.ccode = "SG", .region = REGIONS_ETSI}, ++ {.ccode = "SI", .region = REGIONS_ETSI}, ++ {.ccode = "SK", .region = REGIONS_ETSI}, ++ {.ccode = "SM", .region = REGIONS_ETSI}, ++ {.ccode = "SN", .region = REGIONS_FCC}, ++ {.ccode = "SR", .region = REGIONS_ETSI}, ++ {.ccode = "SV", .region = REGIONS_FCC}, ++ {.ccode = "SY", .region = REGIONS_DEFAULT}, ++ {.ccode = "TC", .region = REGIONS_FCC}, ++ {.ccode = "TD", .region = REGIONS_ETSI}, ++ {.ccode = "TG", .region = REGIONS_ETSI}, ++ {.ccode = "TH", .region = REGIONS_FCC}, ++ {.ccode = "TJ", .region = REGIONS_ETSI}, ++ {.ccode = "TM", .region = REGIONS_ETSI}, ++ {.ccode = "TN", .region = REGIONS_ETSI}, ++ {.ccode = "TR", .region = REGIONS_ETSI}, ++ {.ccode = "TT", .region = REGIONS_FCC}, ++ {.ccode = "TW", .region = REGIONS_FCC}, ++ {.ccode = "UA", .region = REGIONS_ETSI}, ++ {.ccode = "UG", .region = REGIONS_FCC}, ++ {.ccode = "UY", .region = REGIONS_FCC}, ++ {.ccode = "UZ", .region = REGIONS_ETSI}, ++ {.ccode = "VC", .region = REGIONS_ETSI}, ++ {.ccode = "VE", .region = REGIONS_FCC}, ++ {.ccode = "VI", .region = REGIONS_FCC}, ++ {.ccode = "VN", .region = REGIONS_JP}, ++ {.ccode = "VU", .region = REGIONS_FCC}, ++ {.ccode = "WF", .region = REGIONS_ETSI}, ++ {.ccode = "YE", .region = REGIONS_DEFAULT}, ++ {.ccode = "YT", .region = REGIONS_ETSI}, ++ {.ccode = "ZA", .region = REGIONS_ETSI}, ++ {.ccode = "ZM", .region = REGIONS_ETSI}, ++ {.ccode = "ZW", .region = REGIONS_ETSI}, ++}; ++ ++uint8_t get_ccode_region(char * ccode) ++{ ++ int i, cnt; ++ AICWFDBG(LOGDEBUG, "%s ccode:%s\r\n", __func__, ccode); ++ ++ cnt = sizeof(reg_tables) / sizeof(reg_tables[0]); ++ ++ for (i = 0; i < cnt; i++) { ++ if (reg_tables[i].ccode[0] == ccode[0] && ++ reg_tables[i].ccode[1] == ccode[1]) { ++ AICWFDBG(LOGDEBUG, "region: %d\r\n", reg_tables[i].region); ++ return reg_tables[i].region; ++ } ++ } ++ AICWFDBG(LOGDEBUG, "use default region\r\n"); ++ return REGIONS_DEFAULT; ++} ++ ++u8 get_region_index(char * name) ++{ ++ if (strncmp(name, "SRRC", 4) == 0) ++ return REGIONS_SRRC; ++ else if (strncmp(name, "FCC", 3) == 0) ++ return REGIONS_FCC; ++ else if (strncmp(name, "ETSI", 4) == 0) ++ return REGIONS_ETSI; ++ else if (strncmp(name, "JP", 2) == 0) ++ return REGIONS_JP; ++ else if (strncmp(name, "UNSET", 5) == 0) ++ return REGIONS_DEFAULT; ++ ++ return REGIONS_DEFAULT; ++} ++ ++ ++#ifdef CONFIG_POWER_LIMIT ++#define POWER_LIMIT_INVALID_VAL POWER_LEVEL_INVALID_VAL ++ ++#define POWER_LIMIT_CC_MATCHED_BIT (0x1U << 0) ++ ++#define MAX_2_4G_BW_NUM 2 ++#define MAX_5G_BW_NUM 3 ++#define MAX_REGION_NUM 5 ++ ++typedef struct ++{ ++ u8_l ch_cnt_2g4[MAX_2_4G_BW_NUM]; ++ u8_l ch_cnt_5g[MAX_5G_BW_NUM]; ++ u8_l ch_num_2g4[MAX_2_4G_BW_NUM][MAC_DOMAINCHANNEL_24G_MAX]; ++ u8_l ch_num_5g[MAX_5G_BW_NUM][MAC_DOMAINCHANNEL_5G_MAX]; ++ s8_l max_pwr_2g4[MAX_2_4G_BW_NUM][MAC_DOMAINCHANNEL_24G_MAX]; ++ s8_l max_pwr_5g[MAX_5G_BW_NUM][MAC_DOMAINCHANNEL_5G_MAX]; ++} txpwr_lmt_info_t; ++ ++typedef struct ++{ ++ u32_l flags; ++ txpwr_lmt_info_t txpwr_lmt[MAX_REGION_NUM]; ++} powerlimit_info_t; ++ ++powerlimit_info_t powerlimit_info = {0,}; ++#endif ++ ++#ifdef CONFIG_RWNX_TL4 ++/** ++ * rwnx_plat_tl4_fw_upload() - Load the requested FW into embedded side. ++ * ++ * @rwnx_plat: pointer to platform structure ++ * @fw_addr: Virtual address where the fw must be loaded ++ * @filename: Name of the fw. ++ * ++ * Load a fw, stored as a hex file, into the specified address ++ */ ++static int rwnx_plat_tl4_fw_upload(struct rwnx_plat *rwnx_plat, u8 *fw_addr, ++ char *filename) ++{ ++ struct device *dev = rwnx_platform_get_dev(rwnx_plat); ++ const struct firmware *fw; ++ int err = 0; ++ u32 *dst; ++ u8 const *file_data; ++ char typ0, typ1; ++ u32 addr0, addr1; ++ u32 dat0, dat1; ++ int remain; ++ ++ err = request_firmware(&fw, filename, dev); ++ if (err) { ++ return err; ++ } ++ file_data = fw->data; ++ remain = fw->size; ++ ++ /* Copy the file on the Embedded side */ ++ dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr); ++ ++ /* Walk through all the lines of the configuration file */ ++ while (remain >= 16) { ++ u32 data, offset; ++ ++ if (sscanf(file_data, "%c:%08X %04X", &typ0, &addr0, &dat0) != 3) ++ break; ++ if ((addr0 & 0x01) != 0) { ++ addr0 = addr0 - 1; ++ dat0 = 0; ++ } else { ++ file_data += 16; ++ remain -= 16; ++ } ++ if ((remain < 16) || ++ (sscanf(file_data, "%c:%08X %04X", &typ1, &addr1, &dat1) != 3) || ++ (typ1 != typ0) || (addr1 != (addr0 + 1))) { ++ typ1 = typ0; ++ addr1 = addr0 + 1; ++ dat1 = 0; ++ } else { ++ file_data += 16; ++ remain -= 16; ++ } ++ ++ if (typ0 == 'C') { ++ offset = 0x00200000; ++ if ((addr1 % 4) == 3) ++ offset += 2*(addr1 - 3); ++ else ++ offset += 2*(addr1 + 1); ++ ++ data = dat1 | (dat0 << 16); ++ } else { ++ offset = 2*(addr1 - 1); ++ data = dat0 | (dat1 << 16); ++ } ++ dst = (u32 *)(fw_addr + offset); ++ *dst = data; ++ } ++ ++ release_firmware(fw); ++ ++ return err; ++} ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) ++MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver"); ++#else ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#endif ++#endif ++ ++#if 0 ++/** ++ * rwnx_plat_bin_fw_upload() - Load the requested binary FW into embedded side. ++ * ++ * @rwnx_plat: pointer to platform structure ++ * @fw_addr: Virtual address where the fw must be loaded ++ * @filename: Name of the fw. ++ * ++ * Load a fw, stored as a binary file, into the specified address ++ */ ++static int rwnx_plat_bin_fw_upload(struct rwnx_plat *rwnx_plat, u8 *fw_addr, ++ char *filename) ++{ ++ const struct firmware *fw; ++ struct device *dev = rwnx_platform_get_dev(rwnx_plat); ++ int err = 0; ++ unsigned int i, size; ++ u32 *src, *dst; ++ ++ err = request_firmware(&fw, filename, dev); ++ if (err) { ++ return err; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr); ++ ++ src = (u32 *)fw->data; ++ dst = (u32 *)fw_addr; ++ size = (unsigned int)fw->size; ++ ++ /* check potential platform bug on multiple stores vs memcpy */ ++ for (i = 0; i < size; i += 4) { ++ *dst++ = *src++; ++ } ++ ++ release_firmware(fw); ++ ++ return err; ++} ++#endif ++ ++#define MD5(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] ++#define MD5PINRT "file md5:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\r\n" ++ ++static int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device) ++{ ++#ifdef CONFIG_USE_FW_REQUEST ++ const struct firmware *fw = NULL; ++ u32 *dst = NULL; ++ void *buffer=NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ int size = 0; ++ int ret = 0; ++ ++ printk("%s: request firmware = %s \n", __func__ ,name); ++ ++ ret = request_firmware(&fw, name, NULL); ++ ++ if (ret < 0) { ++ printk("Load %s fail\n", name); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ size = fw->size; ++ dst = (u32 *)fw->data; ++ ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ memcpy(buffer, dst, size); ++ ++ *fw_buf = buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ release_firmware(fw); ++ ++ return size; ++#else ++ void *buffer = NULL; ++ char *path = NULL; ++ struct file *fp = NULL; ++ int size = 0, len = 0;// i = 0; ++ ssize_t rdlen = 0; ++ //u32 *src = NULL, *dst = NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ ++ /* get the firmware path */ ++ path = __getname(); ++ if (!path) { ++ *fw_buf = NULL; ++ return -1; ++ } ++ ++ len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", aic_fw_path, name); ++ ++ //len = snprintf(path, FW_PATH_MAX_LEN, "%s", name); ++ if (len >= FW_PATH_MAX_LEN) { ++ AICWFDBG(LOGERROR, "%s: %s file's path too long\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ return -1; ++ } ++ ++ AICWFDBG(LOGINFO, "%s :firmware path = %s \n", __func__, path); ++ ++ /* open the firmware file */ ++ fp = filp_open(path, O_RDONLY, 0); ++ if (IS_ERR_OR_NULL(fp)) { ++ AICWFDBG(LOGERROR, "%s: %s file failed to open\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ fp = NULL; ++ return -1; ++ } ++ ++ size = i_size_read(file_inode(fp)); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "%s: %s file size invalid %d\n", __func__, name, size); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ } ++ ++ /* start to read from firmware file */ ++ buffer = kzalloc(size, GFP_KERNEL); ++ if (!buffer) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ } ++ ++ #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) ++ rdlen = kernel_read(fp, buffer, size, &fp->f_pos); ++ #else ++ rdlen = kernel_read(fp, fp->f_pos, buffer, size); ++ #endif ++ ++ if (size != rdlen) { ++ AICWFDBG(LOGERROR, "%s: %s file rdlen invalid %d\n", __func__, name, (int)rdlen); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ kfree(buffer); ++ buffer = NULL; ++ return -1; ++ } ++ if (rdlen > 0) { ++ fp->f_pos += rdlen; ++ } ++ ++#if 0 ++ /*start to transform the data format*/ ++ src = (u32 *)buffer; ++ dst = (u32 *)kzalloc(size, GFP_KERNEL); ++ ++ if (!dst) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ kfree(buffer); ++ buffer = NULL; ++ return -1; ++ } ++ ++ for (i = 0; i < (size/4); i++) { ++ dst[i] = src[i]; ++ } ++#endif ++ ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ //kfree(buffer); ++ //buffer = NULL; ++ *fw_buf = (u32*)buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ ++ AICWFDBG(LOGINFO, MD5PINRT, MD5(decrypt)); ++ ++ return size; ++#endif ++} ++ ++ ++ ++/* buffer is allocated by kzalloc */ ++int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, u32** buffer, const char *filename) ++{ ++ int size; ++ ++ AICWFDBG(LOGINFO, "### Load file %s\n", filename); ++ ++ size = rwnx_load_firmware(buffer, filename, NULL); ++ ++ return size; ++} ++ ++static void rwnx_restore_firmware(u32 **fw_buf) ++{ ++#ifdef CONFIG_USE_FW_REQUEST ++ vfree(*fw_buf); ++#else ++ kfree(*fw_buf); ++#endif ++ *fw_buf = NULL; ++} ++ ++ ++void rwnx_release_firmware_common(u32** buffer) ++{ ++ rwnx_restore_firmware(buffer); ++} ++ ++ ++/** ++ * rwnx_plat_bin_fw_upload_2() - Load the requested binary FW into embedded side. ++ * ++ * @rwnx_hw: Main driver data ++ * @fw_addr: Address where the fw must be loaded ++ * @filename: Name of the fw. ++ * ++ * Load a fw, stored as a binary file, into the specified address ++ */ ++int rwnx_plat_bin_fw_upload_2(struct rwnx_hw *rwnx_hw, u32 fw_addr, ++ char *filename) ++{ ++ int err = 0; ++ unsigned int i = 0, size; ++// u32 *src; ++ u32 *dst=NULL; ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Upload %s firmware, @ = %x\n", filename, fw_addr); ++ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (!dst) { ++ AICWFDBG(LOGERROR, "No such file or directory\n"); ++ return -1; ++ } ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ err = -1; ++ } ++ ++ AICWFDBG(LOGINFO, "size=%d, dst[0]=%x\n", size, dst[0]); ++ if (size > 512) { ++ for (; i < (size - 512); i += 512) { ++ //printk("wr blk 0: %p -> %x\r\n", dst + i / 4, fw_addr + i); ++ err = rwnx_send_dbg_mem_block_write_req(rwnx_hw, fw_addr + i, 512, dst + i / 4); ++ if (err) { ++ AICWFDBG(LOGERROR, "bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ break; ++ } ++ } ++ } ++ if (!err && (i < size)) { ++ //printk("wr blk 1: %p -> %x\r\n", dst + i / 4, fw_addr + i); ++ err = rwnx_send_dbg_mem_block_write_req(rwnx_hw, fw_addr + i, size - i, dst + i / 4); ++ if (err) { ++ AICWFDBG(LOGERROR, "bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ } ++ } ++ ++ if (dst) { ++ rwnx_release_firmware_common(&dst); ++ } ++ ++ return err; ++} ++ ++ ++ ++typedef struct { ++ txpwr_idx_conf_t txpwr_idx; ++ txpwr_ofst_conf_t txpwr_ofst; ++ xtal_cap_conf_t xtal_cap; ++} nvram_info_t; ++ ++nvram_info_t nvram_info = { ++ .txpwr_idx = { ++ .enable = 1, ++ .dsss = 9, ++ .ofdmlowrate_2g4 = 8, ++ .ofdm64qam_2g4 = 8, ++ .ofdm256qam_2g4 = 8, ++ .ofdm1024qam_2g4 = 8, ++ .ofdmlowrate_5g = 11, ++ .ofdm64qam_5g = 10, ++ .ofdm256qam_5g = 9, ++ .ofdm1024qam_5g = 9 ++ }, ++ .txpwr_ofst = { ++ .enable = 1, ++ .chan_1_4 = 0, ++ .chan_5_9 = 0, ++ .chan_10_13 = 0, ++ .chan_36_64 = 0, ++ .chan_100_120 = 0, ++ .chan_122_140 = 0, ++ .chan_142_165 = 0, ++ }, ++ .xtal_cap = { ++ .enable = 0, ++ .xtal_cap = 24, ++ .xtal_cap_fine = 31, ++ }, ++}; ++ ++void get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst_conf_t *txpwr_ofst) ++{ ++ txpwr_ofst->enable = userconfig_info.txpwr_ofst.enable; ++ txpwr_ofst->chan_1_4 = userconfig_info.txpwr_ofst.chan_1_4; ++ txpwr_ofst->chan_5_9 = userconfig_info.txpwr_ofst.chan_5_9; ++ txpwr_ofst->chan_10_13 = userconfig_info.txpwr_ofst.chan_10_13; ++ txpwr_ofst->chan_36_64 = userconfig_info.txpwr_ofst.chan_36_64; ++ txpwr_ofst->chan_100_120 = userconfig_info.txpwr_ofst.chan_100_120; ++ txpwr_ofst->chan_122_140 = userconfig_info.txpwr_ofst.chan_122_140; ++ txpwr_ofst->chan_142_165 = userconfig_info.txpwr_ofst.chan_142_165; ++ ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst->enable); ++ AICWFDBG(LOGINFO, "%s:chan_1_4 :%d\r\n", __func__, txpwr_ofst->chan_1_4); ++ AICWFDBG(LOGINFO, "%s:chan_5_9 :%d\r\n", __func__, txpwr_ofst->chan_5_9); ++ AICWFDBG(LOGINFO, "%s:chan_10_13 :%d\r\n", __func__, txpwr_ofst->chan_10_13); ++ AICWFDBG(LOGINFO, "%s:chan_36_64 :%d\r\n", __func__, txpwr_ofst->chan_36_64); ++ AICWFDBG(LOGINFO, "%s:chan_100_120:%d\r\n", __func__, txpwr_ofst->chan_100_120); ++ AICWFDBG(LOGINFO, "%s:chan_122_140:%d\r\n", __func__, txpwr_ofst->chan_122_140); ++ AICWFDBG(LOGINFO, "%s:chan_142_165:%d\r\n", __func__, txpwr_ofst->chan_142_165); ++} ++ ++void get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x_conf_t *txpwr_ofst2x) ++{ ++ int type, ch_grp; ++ *txpwr_ofst2x = userconfig_info.txpwr_ofst2x; ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst2x->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g: [0]:11b, [1]:ofdm_highrate, [2]:ofdm_lowrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_2g4[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g: [0]:ofdm_lowrate, [1]:ofdm_highrate, [2]:ofdm_midrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_5g[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++} ++ ++void get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2) ++{ ++ int type, ch_grp; ++ *txpwr_ofst2x_v2 = userconfig_info.txpwr_ofst2x_v2; ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst2x_v2->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g(ant0/ant1): [0]:11b, [1]:ofdm_highrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 2; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g: [0]:ofdm_highrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 1; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++} ++ ++void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx) ++{ ++ memcpy(txpwr_idx, &(nvram_info.txpwr_idx), sizeof(txpwr_idx_conf_t)); ++} ++ ++void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst) ++{ ++ memcpy(txpwr_ofst, &(nvram_info.txpwr_ofst), sizeof(txpwr_ofst_conf_t)); ++} ++ ++void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap) ++{ ++ if(nvram_info.xtal_cap.enable){ ++ *xtal_cap = nvram_info.xtal_cap; ++ } ++ ++ if(userconfig_info.xtal_cap.enable){ ++ *xtal_cap = userconfig_info.xtal_cap; ++ } ++ ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, xtal_cap->enable); ++ AICWFDBG(LOGINFO, "%s:xtal_cap :%d\r\n", __func__, xtal_cap->xtal_cap); ++ AICWFDBG(LOGINFO, "%s:xtal_cap_fine:%d\r\n", __func__, xtal_cap->xtal_cap_fine); ++} ++ ++s8_l get_txpwr_max(s8_l power) ++{ ++ int i=0; ++ ++ if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i]; ++ } ++ for (i = 0; i <= 9; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i]; ++ } ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i]; ++ } ++ for (i = 4; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i]; ++ } ++ for (i = 0; i <= 9; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i]; ++ } ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i]; ++ } ++ ++ if ((userconfig_info.txpwr_loss.loss_enable_2g4 == 1) || ++ (userconfig_info.txpwr_loss.loss_enable_5g == 1)) { ++ if (userconfig_info.txpwr_loss.loss_value_2g4 < ++ userconfig_info.txpwr_loss.loss_value_5g) ++ power += userconfig_info.txpwr_loss.loss_value_5g; ++ else ++ power += userconfig_info.txpwr_loss.loss_value_2g4; ++ } ++ ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[i]; ++ } ++ for (i = 0; i <= 9; i++){ ++ if(power < userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[i]; ++ } ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[i]; ++ } ++ } ++ ++ printk("%s:txpwr_max:%d \r\n",__func__,power); ++ return power; ++} ++ ++ ++void set_txpwr_loss_ofst(s8_l value) ++{ ++ int i=0; ++ if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i] += value; ++ } ++ for (i = 4; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i] += value; ++ } ++ }else if( g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[i] += value; ++ } ++ for (i = 0; i <= 7; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[i] += value; ++ } ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[i] += value; ++ } ++ } ++ printk("%s:value:%d\r\n", __func__, value); ++} ++ ++ ++#define MATCH_NODE(type, node, cfg_key) {cfg_key, offsetof(type, node)} ++ ++struct parse_match_t { ++ char keyname[64]; ++ int offset; ++}; ++ ++static const char *parse_key_prefix[] = { ++ [0x01] = "module0_", ++ [0x21] = "module1_", ++}; ++ ++static const struct parse_match_t parse_match_tab[] = { ++ MATCH_NODE(nvram_info_t, txpwr_idx.enable, "enable"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.dsss, "dsss"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdmlowrate_2g4, "ofdmlowrate_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm64qam_2g4, "ofdm64qam_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm256qam_2g4, "ofdm256qam_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm1024qam_2g4, "ofdm1024qam_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdmlowrate_5g, "ofdmlowrate_5g"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm64qam_5g, "ofdm64qam_5g"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm256qam_5g, "ofdm256qam_5g"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm1024qam_5g, "ofdm1024qam_5g"), ++ ++ MATCH_NODE(nvram_info_t, txpwr_ofst.enable, "ofst_enable"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_1_4, "ofst_chan_1_4"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_5_9, "ofst_chan_5_9"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_10_13, "ofst_chan_10_13"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_36_64, "ofst_chan_36_64"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_100_120, "ofst_chan_100_120"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_122_140, "ofst_chan_122_140"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_142_165, "ofst_chan_142_165"), ++ ++ MATCH_NODE(nvram_info_t, xtal_cap.enable, "xtal_enable"), ++ MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap, "xtal_cap"), ++ MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap_fine, "xtal_cap_fine"), ++}; ++ ++static int parse_key_val(const char *str, const char *key, char *val) ++{ ++ const char *p = NULL; ++ const char *dst = NULL; ++ int keysize = 0; ++ int bufsize = 0; ++ ++ if (str == NULL || key == NULL || val == NULL) ++ return -1; ++ ++ keysize = strlen(key); ++ bufsize = strlen(str); ++ if (bufsize <= keysize) ++ return -1; ++ ++ p = str; ++ while (*p != 0 && *p == ' ') ++ p++; ++ ++ if (*p == '#') ++ return -1; ++ ++ if (str + bufsize - p <= keysize) ++ return -1; ++ ++ if (strncmp(p, key, keysize) != 0) ++ return -1; ++ ++ p += keysize; ++ ++ while (*p != 0 && *p == ' ') ++ p++; ++ ++ if (*p != '=') ++ return -1; ++ ++ p++; ++ while (*p != 0 && *p == ' ') ++ p++; ++ ++ if (*p == '"') ++ p++; ++ ++ dst = p; ++ while (*p != 0) ++ p++; ++ ++ p--; ++ while (*p == ' ') ++ p--; ++ ++ if (*p == '"') ++ p--; ++ ++ while (*p == '\r' || *p == '\n') ++ p--; ++ ++ p++; ++ strncpy(val, dst, p -dst); ++ val[p - dst] = 0; ++ return 0; ++} ++ ++int rwnx_atoi2(char *value, int c_len) ++{ ++ int len = 0; ++ int i = 0; ++ int result = 0; ++ int flag = 1; ++ ++ if (value[0] == '-') { ++ flag = -1; ++ value++; ++ } ++ len = c_len; ++ ++ for (i = 0;i < len ;i++) { ++ result = result * 10; ++ if (value[i] >= 48 && value[i] <= 57) { ++ result += value[i] - 48; ++ } else { ++ result = 0; ++ break; ++ } ++ } ++ ++ return result * flag; ++} ++ ++ ++int rwnx_atoi(char *value) ++{ ++ int len = 0; ++ int i = 0; ++ int result = 0; ++ int flag = 1; ++ ++ if (value[0] == '-') { ++ flag = -1; ++ value++; ++ } ++ len = strlen(value); ++ ++ for (i = 0;i < len ;i++) { ++ result = result * 10; ++ if (value[i] >= 48 && value[i] <= 57) { ++ result += value[i] - 48; ++ } else { ++ result = 0; ++ break; ++ } ++ } ++ ++ return result * flag; ++} ++ ++ ++void rwnx_plat_nvram_set_value(char *command, char *value) ++{ ++ //TODO send command ++ AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); ++ if (!strcmp(command, "enable")) { ++ userconfig_info.txpwr_lvl.enable = rwnx_atoi(value); ++ userconfig_info.txpwr_lvl_v2.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "dsss")) { ++ userconfig_info.txpwr_lvl.dsss = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_2g4")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_5g")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_enable")) { ++ userconfig_info.txpwr_ofst.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_1_4")) { ++ userconfig_info.txpwr_ofst.chan_1_4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_5_9")) { ++ userconfig_info.txpwr_ofst.chan_5_9 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_10_13")) { ++ userconfig_info.txpwr_ofst.chan_10_13 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_36_64")) { ++ userconfig_info.txpwr_ofst.chan_36_64 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_100_120")) { ++ userconfig_info.txpwr_ofst.chan_100_120 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_122_140")) { ++ userconfig_info.txpwr_ofst.chan_122_140 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_142_165")) { ++ userconfig_info.txpwr_ofst.chan_142_165 = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_enable")) { ++ userconfig_info.xtal_cap.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap")) { ++ userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap_fine")) { ++ userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); ++ } else { ++ AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); ++ } ++} ++ ++void rwnx_plat_nvram_set_value_v3(char *command, char *value) ++{ ++ //TODO send command ++ AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); ++ if (!strcmp(command, "enable")) { ++ userconfig_info.txpwr_lvl.enable = rwnx_atoi(value); ++ userconfig_info.txpwr_lvl_v3.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "dsss")) { ++ userconfig_info.txpwr_lvl.dsss = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_2g4")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_5g")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_1m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_2m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_5m5_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_11m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_6m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_9m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_12m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_18m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_24m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_36m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_48m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_54m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_enable")) { ++ userconfig_info.txpwr_lvl_adj.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_1_4")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_5_9")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_10_13")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_42")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_58")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_106")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_122")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_138")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_155")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_2g4")) { ++ userconfig_info.txpwr_loss.loss_enable_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_2g4")) { ++ userconfig_info.txpwr_loss.loss_value_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_5g")) { ++ userconfig_info.txpwr_loss.loss_enable_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_5g")) { ++ userconfig_info.txpwr_loss.loss_value_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_enable")) { ++ userconfig_info.txpwr_ofst.enable = rwnx_atoi(value); ++ userconfig_info.txpwr_ofst2x.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_1_4")) { ++ userconfig_info.txpwr_ofst.chan_1_4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_5_9")) { ++ userconfig_info.txpwr_ofst.chan_5_9 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_10_13")) { ++ userconfig_info.txpwr_ofst.chan_10_13 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_36_64")) { ++ userconfig_info.txpwr_ofst.chan_36_64 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_100_120")) { ++ userconfig_info.txpwr_ofst.chan_100_120 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_122_140")) { ++ userconfig_info.txpwr_ofst.chan_122_140 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_142_165")) { ++ userconfig_info.txpwr_ofst.chan_142_165 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_11b_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_11b_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_11b_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[0][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_highrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_highrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_highrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[1][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_lowrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_lowrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_lowrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[2][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_enable")) { ++ userconfig_info.xtal_cap.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap")) { ++ userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap_fine")) { ++ userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); ++ } else { ++ AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); ++ } ++} ++ ++void rwnx_plat_userconfig_parsing2(char *buffer, int size) ++{ ++ int i = 0; ++ int parse_state = 0; ++ char command[30]; ++ char value[100]; ++ int char_counter = 0; ++ ++ memset(command, 0, 30); ++ memset(value, 0, 100); ++ ++ for (i = 0; i < size; i++) { ++ //Send command or print nvram log when char is \r or \n ++ if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ if (command[0] != 0 && value[0] != 0) { ++ if (parse_state == PRINT) { ++ AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); ++ } else if (parse_state == GET_VALUE) { ++ rwnx_plat_nvram_set_value(command, value); ++ } ++ } ++ //Reset command value and char_counter ++ memset(command, 0, 30); ++ memset(value, 0, 100); ++ char_counter = 0; ++ parse_state = INIT; ++ continue; ++ } ++ ++ //Switch parser state ++ if (parse_state == INIT) { ++ if (buffer[i] == '#') { ++ parse_state = PRINT; ++ continue; ++ } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ parse_state = INIT; ++ continue; ++ } else { ++ parse_state = CMD; ++ } ++ } ++ ++ //Fill data to command and value ++ if (parse_state == PRINT) { ++ command[0] = 0x01; ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == CMD) { ++ if (command[0] != 0 && buffer[i] == '=') { ++ parse_state = GET_VALUE; ++ char_counter = 0; ++ continue; ++ } ++ command[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == GET_VALUE) { ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } ++ } ++} ++ ++void rwnx_plat_userconfig_parsing3(char *buffer, int size) ++{ ++ int i = 0; ++ int parse_state = 0; ++ char command[64]; ++ char value[100]; ++ int char_counter = 0; ++ ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ ++ for (i = 0; i < size; i++) { ++ //Send command or print nvram log when char is \r or \n ++ if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ if (command[0] != 0 && value[0] != 0) { ++ if (parse_state == PRINT) { ++ AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); ++ } else if (parse_state == GET_VALUE) { ++ rwnx_plat_nvram_set_value_v3(command, value); ++ } ++ } ++ //Reset command value and char_counter ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ char_counter = 0; ++ parse_state = INIT; ++ continue; ++ } ++ ++ //Switch parser state ++ if (parse_state == INIT) { ++ if (buffer[i] == '#') { ++ parse_state = PRINT; ++ continue; ++ } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ parse_state = INIT; ++ continue; ++ } else { ++ parse_state = CMD; ++ } ++ } ++ ++ //Fill data to command and value ++ if (parse_state == PRINT) { ++ command[0] = 0x01; ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == CMD) { ++ if (command[0] != 0 && buffer[i] == '=') { ++ parse_state = GET_VALUE; ++ char_counter = 0; ++ continue; ++ } ++ command[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == GET_VALUE) { ++ if(buffer[i] != 0x2D && (buffer[i] < 0x30 || buffer[i] > 0x39)) { ++ continue; ++ } ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } ++ } ++} ++ ++void rwnx_plat_userconfig_parsing(struct rwnx_hw *rwnx_hw, char *buffer, int size) ++{ ++ char conf[100], keyname[64]; ++ char *line; ++ char *data; ++ int i = 0, err, len = 0; ++ long val; ++ ++ if (size <= 0) { ++ pr_err("Config buffer size %d error\n", size); ++ return; ++ } ++ ++ printk("%s rwnx_hw->vendor_info:0x%02X \r\n", __func__, rwnx_hw->vendor_info); ++ if (rwnx_hw->vendor_info == 0x00 || ++ (rwnx_hw->vendor_info > (sizeof(parse_key_prefix) / sizeof(parse_key_prefix[0]) - 1))) { ++ printk("Unsuppor vendor info config\n"); ++ printk("Using module0 config\n"); ++ rwnx_hw->vendor_info = 0x01; ++ //return; ++ } ++ ++ data = vmalloc(size + 1); ++ if (!data) { ++ pr_err("vmalloc fail\n"); ++ return; ++ } ++ ++ memcpy(data, buffer, size); ++ buffer = data; ++ ++ while (1) { ++ line = buffer; ++ if (*line == 0) ++ break; ++ ++ while (*buffer != '\r' && *buffer != '\n' && *buffer != 0 && len++ < size) ++ buffer++; ++ ++ while ((*buffer == '\r' || *buffer == '\n') && len++ < size) ++ *buffer++ = 0; ++ ++ if (len >= size) ++ *buffer = 0; ++ ++ // store value to data struct ++ for (i = 0; i < sizeof(parse_match_tab) / sizeof(parse_match_tab[0]); i++) { ++ sprintf(&keyname[0], "%s%s", parse_key_prefix[rwnx_hw->vendor_info], parse_match_tab[i].keyname); ++ if (parse_key_val(line, keyname, conf) == 0) { ++ err = kstrtol(conf, 0, &val); ++ *(unsigned long *)((unsigned long)&nvram_info + parse_match_tab[i].offset) = val; ++ printk("%s, %s = %ld\n", __func__, parse_match_tab[i].keyname, val); ++ break; ++ } ++ } ++ ++ } ++ vfree(data); ++} ++ ++void rwnx_plat_nvram_set_value_8800d80x2(char *command, char *value) ++{ ++ //TODO send command ++ AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); ++ if (!strcmp(command, "enable")) { ++ userconfig_info.txpwr_lvl_v4.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_6m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_9m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_12m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_18m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_24m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_36m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_48m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_54m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_enable")) { ++ userconfig_info.txpwr_lvl_adj.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_1_4")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_5_9")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_10_13")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_42")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_58")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_106")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_122")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_138")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_155")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_2g4")) { ++ userconfig_info.txpwr_loss.loss_enable_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_2g4")) { ++ userconfig_info.txpwr_loss.loss_value_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_5g")) { ++ userconfig_info.txpwr_loss.loss_enable_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_5g")) { ++ userconfig_info.txpwr_loss.loss_value_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_enable")) { ++ userconfig_info.txpwr_ofst2x_v2.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_11b_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_11b_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_11b_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_ofdm_highrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_ofdm_highrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_ofdm_highrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_11b_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_11b_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_11b_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_ofdm_highrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_ofdm_highrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_ofdm_highrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[3][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[4][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[5][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[3][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[4][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[5][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_enable")) { ++ userconfig_info.xtal_cap.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap")) { ++ userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap_fine")) { ++ userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); ++ } else { ++ AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); ++ } ++} ++ ++void rwnx_plat_userconfig_parsing_8800d80x2(char *buffer, int size) ++{ ++ int i = 0; ++ int parse_state = 0; ++ char command[100]; ++ char value[100]; ++ int char_counter = 0; ++ ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ ++ for (i = 0; i < size; i++) { ++ //Send command or print nvram log when char is \r or \n ++ if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ if (command[0] != 0 && value[0] != 0) { ++ if (parse_state == PRINT) { ++ AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); ++ } else if (parse_state == GET_VALUE) { ++ rwnx_plat_nvram_set_value_8800d80x2(command, value); ++ } ++ } ++ //Reset command value and char_counter ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ char_counter = 0; ++ parse_state = INIT; ++ continue; ++ } ++ ++ //Switch parser state ++ if (parse_state == INIT) { ++ if (buffer[i] == '#') { ++ parse_state = PRINT; ++ continue; ++ } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ parse_state = INIT; ++ continue; ++ } else { ++ parse_state = CMD; ++ } ++ } ++ ++ //Fill data to command and value ++ if (parse_state == PRINT) { ++ command[0] = 0x01; ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == CMD) { ++ if (command[0] != 0 && buffer[i] == '=') { ++ parse_state = GET_VALUE; ++ char_counter = 0; ++ continue; ++ } ++ command[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == GET_VALUE) { ++ if(buffer[i] != 0x2D && (buffer[i] < 0x30 || buffer[i] > 0x39)) { ++ continue; ++ } ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } ++ } ++} ++ ++static int aic_load_firmware(u32 ** fw_buf, char *fw_path,const char *name, struct device *device) ++{ ++#ifdef CONFIG_USE_FW_REQUEST ++ const struct firmware *fw = NULL; ++ u32 *dst = NULL; ++ void *buffer=NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ int size = 0; ++ int ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s: request firmware = %s \n", __func__ ,name); ++ ++ ret = request_firmware(&fw, name, NULL); ++ ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "Load %s fail\n", name); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ size = fw->size; ++ dst = (u32 *)fw->data; ++ ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ memcpy(buffer, dst, size); ++ ++ *fw_buf = buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ AICWFDBG(LOGINFO, MD5PINRT, MD5(decrypt)); ++ ++ release_firmware(fw); ++ ++ return size; ++#else ++ void *buffer=NULL; ++ char *path=NULL; ++ struct file *fp=NULL; ++ int size = 0, len=0;//, i=0; ++ ssize_t rdlen=0; ++ //u32 *src=NULL, *dst = NULL; ++ ++ /* get the firmware path */ ++ path = __getname(); ++ if (!path){ ++ *fw_buf=NULL; ++ return -1; ++ } ++ ++ len = sprintf(path, "%s/%s",fw_path, name); ++ ++ AICWFDBG(LOGINFO, "%s :firmware path = %s \n", __func__ ,path); ++ ++ ++ /* open the firmware file */ ++ fp=filp_open(path, O_RDONLY, 0); ++ if(IS_ERR(fp) || (!fp)){ ++ printk("%s: %s file failed to open\n", __func__, name); ++ if(IS_ERR(fp)){ ++ printk("is_Err\n"); ++ } ++ if((!fp)){ ++ printk("null\n"); ++ } ++ *fw_buf=NULL; ++ __putname(path); ++ fp=NULL; ++ return -1; ++ } ++ ++ size = i_size_read(file_inode(fp)); ++ if(size<=0){ ++ printk("%s: %s file size invalid %d\n", __func__, name, size); ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ return -1; ++ } ++ ++ /* start to read from firmware file */ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ if(!buffer){ ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ return -1; ++ } ++ ++ ++ #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) ++ rdlen = kernel_read(fp, buffer, size, &fp->f_pos); ++ #else ++ rdlen = kernel_read(fp, fp->f_pos, buffer, size); ++ #endif ++ ++ if(size != rdlen){ ++ printk("%s: %s file rdlen invalid %d %d\n", __func__, name, (int)rdlen, size); ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ vfree(buffer); ++ buffer=NULL; ++ return -1; ++ } ++ if(rdlen > 0){ ++ fp->f_pos += rdlen; ++ //printk("f_pos=%d\n", (int)fp->f_pos); ++ } ++ ++#if 0 ++ /*start to transform the data format*/ ++ src = (u32*)buffer; ++ //printk("malloc dst\n"); ++ dst = (u32*)vmalloc(size); ++ memset(dst, 0, size); ++ ++ if(!dst){ ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ vfree(buffer); ++ buffer=NULL; ++ return -1; ++ } ++ ++ for(i=0;i<(size/4);i++){ ++ dst[i] = src[i]; ++ } ++#endif ++ ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ //vfree(buffer); ++ //buffer=NULL; ++ *fw_buf = (u32 *)buffer; ++ ++ return size; ++#endif ++} ++ ++ ++ ++#define FW_USERCONFIG_NAME "aic_userconfig.txt" ++ ++int rwnx_plat_userconfig_upload_android(struct rwnx_hw *rwnx_hw, char *fw_path, char *filename) ++{ ++ int size; ++ u32 *dst=NULL; ++ ++ printk("userconfig file path:%s \r\n", filename); ++ ++ /* load aic firmware */ ++ size = aic_load_firmware(&dst, fw_path ,filename, NULL); ++ if(size <= 0){ ++ printk("wrong size of firmware file\n"); ++ vfree(dst); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload %s userconfig, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing(rwnx_hw, (char *)dst, size); ++ ++ if (dst) { ++ vfree(dst); ++ dst = NULL; ++ } ++ ++ printk("userconfig download complete\n\n"); ++ ++ return 0; ++ ++} ++ ++/** ++ * rwnx_plat_fmac_load() - Load FW code ++ * ++ * @rwnx_hw: Main driver data ++ */ ++ #if 0 ++static int rwnx_plat_fmac_load(struct rwnx_hw *rwnx_hw, char *fw_path) ++{ ++ int ret = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ret = rwnx_plat_userconfig_upload_android(rwnx_hw, fw_path, FW_USERCONFIG_NAME); ++ return ret; ++} ++ #endif ++ ++/** ++ * rwnx_platform_reset() - Reset the platform ++ * ++ * @rwnx_plat: platform data ++ */ ++static int rwnx_platform_reset(struct rwnx_plat *rwnx_plat) ++{ ++ u32 regval; ++ ++#if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) ++ return 0; ++#endif ++ ++ /* the doc states that SOFT implies FPGA_B_RESET ++ * adding FPGA_B_RESET is clearer */ ++ RWNX_REG_WRITE(SOFT_RESET | FPGA_B_RESET, rwnx_plat, ++ RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); ++ msleep(100); ++ ++ regval = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); ++ ++ if (regval & SOFT_RESET) { ++ dev_err(rwnx_platform_get_dev(rwnx_plat), "reset: failed\n"); ++ return -EIO; ++ } ++ ++ RWNX_REG_WRITE(regval & ~FPGA_B_RESET, rwnx_plat, ++ RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); ++ msleep(100); ++ return 0; ++} ++ ++/** ++ * rwmx_platform_save_config() - Save hardware config before reload ++ * ++ * @rwnx_plat: Pointer to platform data ++ * ++ * Return configuration registers values. ++ */ ++static void *rwnx_term_save_config(struct rwnx_plat *rwnx_plat) ++{ ++ const u32 *reg_list; ++ u32 *reg_value, *res; ++ int i, size = 0; ++ ++ if (rwnx_plat->get_config_reg) { ++ size = rwnx_plat->get_config_reg(rwnx_plat, ®_list); ++ } ++ ++ if (size <= 0) ++ return NULL; ++ ++ res = kmalloc(sizeof(u32) * size, GFP_KERNEL); ++ if (!res) ++ return NULL; ++ ++ reg_value = res; ++ for (i = 0; i < size; i++) { ++ *reg_value++ = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, ++ *reg_list++); ++ } ++ ++ return res; ++} ++ ++#if 0 ++/** ++ * rwmx_platform_restore_config() - Restore hardware config after reload ++ * ++ * @rwnx_plat: Pointer to platform data ++ * @reg_value: Pointer of value to restore ++ * (obtained with rwmx_platform_save_config()) ++ * ++ * Restore configuration registers value. ++ */ ++static void rwnx_term_restore_config(struct rwnx_plat *rwnx_plat, ++ u32 *reg_value) ++{ ++ const u32 *reg_list; ++ int i, size = 0; ++ ++ if (!reg_value || !rwnx_plat->get_config_reg) ++ return; ++ ++ size = rwnx_plat->get_config_reg(rwnx_plat, ®_list); ++ ++ for (i = 0; i < size; i++) { ++ RWNX_REG_WRITE(*reg_value++, rwnx_plat, RWNX_ADDR_SYSTEM, ++ *reg_list++); ++ } ++} ++#endif ++ ++#ifndef CONFIG_RWNX_FHOST ++#if 0 ++static int rwnx_check_fw_compatibility(struct rwnx_hw *rwnx_hw) ++{ ++ struct ipc_shared_env_tag *shared = rwnx_hw->ipc_env->shared; ++ #ifdef CONFIG_RWNX_FULLMAC ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ #endif //CONFIG_RWNX_FULLMAC ++ #ifdef CONFIG_RWNX_OLD_IPC ++ int ipc_shared_version = 10; ++ #else //CONFIG_RWNX_OLD_IPC ++ int ipc_shared_version = 11; ++ #endif //CONFIG_RWNX_OLD_IPC ++ int res = 0; ++ ++ if (shared->comp_info.ipc_shared_version != ipc_shared_version) { ++ wiphy_err(wiphy, "Different versions of IPC shared version between driver and FW (%d != %d)\n ", ++ ipc_shared_version, shared->comp_info.ipc_shared_version); ++ res = -1; ++ } ++ ++ if (shared->comp_info.radarbuf_cnt != IPC_RADARBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for Radar events handling "\ ++ "between driver and FW (%d != %d)\n", IPC_RADARBUF_CNT, ++ shared->comp_info.radarbuf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.unsuprxvecbuf_cnt != IPC_UNSUPRXVECBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for unsupported Rx vectors "\ ++ "handling between driver and FW (%d != %d)\n", IPC_UNSUPRXVECBUF_CNT, ++ shared->comp_info.unsuprxvecbuf_cnt); ++ res = -1; ++ } ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ if (shared->comp_info.rxdesc_cnt != IPC_RXDESC_CNT) { ++ wiphy_err(wiphy, "Different number of shared descriptors available for Data RX handling "\ ++ "between driver and FW (%d != %d)\n", IPC_RXDESC_CNT, ++ shared->comp_info.rxdesc_cnt); ++ res = -1; ++ } ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (shared->comp_info.rxbuf_cnt != IPC_RXBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for Data Rx handling "\ ++ "between driver and FW (%d != %d)\n", IPC_RXBUF_CNT, ++ shared->comp_info.rxbuf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.msge2a_buf_cnt != IPC_MSGE2A_BUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for Emb->App MSGs "\ ++ "sending between driver and FW (%d != %d)\n", IPC_MSGE2A_BUF_CNT, ++ shared->comp_info.msge2a_buf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.dbgbuf_cnt != IPC_DBGBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for debug messages "\ ++ "sending between driver and FW (%d != %d)\n", IPC_DBGBUF_CNT, ++ shared->comp_info.dbgbuf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.bk_txq != NX_TXDESC_CNT0) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of BK TX queue (%d != %d)\n", ++ NX_TXDESC_CNT0, shared->comp_info.bk_txq); ++ res = -1; ++ } ++ ++ if (shared->comp_info.be_txq != NX_TXDESC_CNT1) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of BE TX queue (%d != %d)\n", ++ NX_TXDESC_CNT1, shared->comp_info.be_txq); ++ res = -1; ++ } ++ ++ if (shared->comp_info.vi_txq != NX_TXDESC_CNT2) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of VI TX queue (%d != %d)\n", ++ NX_TXDESC_CNT2, shared->comp_info.vi_txq); ++ res = -1; ++ } ++ ++ if (shared->comp_info.vo_txq != NX_TXDESC_CNT3) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of VO TX queue (%d != %d)\n", ++ NX_TXDESC_CNT3, shared->comp_info.vo_txq); ++ res = -1; ++ } ++ ++ #if NX_TXQ_CNT == 5 ++ if (shared->comp_info.bcn_txq != NX_TXDESC_CNT4) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of BCN TX queue (%d != %d)\n", ++ NX_TXDESC_CNT4, shared->comp_info.bcn_txq); ++ res = -1; ++ } ++ #else ++ if (shared->comp_info.bcn_txq > 0) { ++ wiphy_err(wiphy, "BCMC enabled in firmware but disabled in driver\n"); ++ res = -1; ++ } ++ #endif /* NX_TXQ_CNT == 5 */ ++ ++ if (shared->comp_info.ipc_shared_size != sizeof(ipc_shared_env)) { ++ wiphy_err(wiphy, "Different sizes of IPC shared between driver and FW (%zd != %d)\n", ++ sizeof(ipc_shared_env), shared->comp_info.ipc_shared_size); ++ res = -1; ++ } ++ ++ if (shared->comp_info.msg_api != MSG_API_VER) { ++ wiphy_warn(wiphy, "WARNING: Different supported message API versions between "\ ++ "driver and FW (%d != %d)\n", MSG_API_VER, shared->comp_info.msg_api); ++ } ++ ++ return res; ++} ++#endif ++#endif /* !CONFIG_RWNX_FHOST */ ++ ++ ++void get_userconfig_txpwr_lvl_in_fdrv(txpwr_lvl_conf_t *txpwr_lvl) ++{ ++ txpwr_lvl->enable = userconfig_info.txpwr_lvl.enable; ++ txpwr_lvl->dsss = userconfig_info.txpwr_lvl.dsss; ++ txpwr_lvl->ofdmlowrate_2g4 = userconfig_info.txpwr_lvl.ofdmlowrate_2g4; ++ txpwr_lvl->ofdm64qam_2g4 = userconfig_info.txpwr_lvl.ofdm64qam_2g4; ++ txpwr_lvl->ofdm256qam_2g4 = userconfig_info.txpwr_lvl.ofdm256qam_2g4; ++ txpwr_lvl->ofdm1024qam_2g4 = userconfig_info.txpwr_lvl.ofdm1024qam_2g4; ++ txpwr_lvl->ofdmlowrate_5g = userconfig_info.txpwr_lvl.ofdmlowrate_5g; ++ txpwr_lvl->ofdm64qam_5g = userconfig_info.txpwr_lvl.ofdm64qam_5g; ++ txpwr_lvl->ofdm256qam_5g = userconfig_info.txpwr_lvl.ofdm256qam_5g; ++ txpwr_lvl->ofdm1024qam_5g = userconfig_info.txpwr_lvl.ofdm1024qam_5g; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl->enable); ++ AICWFDBG(LOGINFO, "%s:dsss:%d\r\n", __func__, txpwr_lvl->dsss); ++ AICWFDBG(LOGINFO, "%s:ofdmlowrate_2g4:%d\r\n", __func__, txpwr_lvl->ofdmlowrate_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdm64qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm64qam_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdm256qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm256qam_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdm1024qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm1024qam_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdmlowrate_5g:%d\r\n", __func__, txpwr_lvl->ofdmlowrate_5g); ++ AICWFDBG(LOGINFO, "%s:ofdm64qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm64qam_5g); ++ AICWFDBG(LOGINFO, "%s:ofdm256qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm256qam_5g); ++ AICWFDBG(LOGINFO, "%s:ofdm1024qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm1024qam_5g); ++} ++ ++void get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_conf_v2_t *txpwr_lvl_v2) ++{ ++ *txpwr_lvl_v2 = userconfig_info.txpwr_lvl_v2; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v2->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[11]); ++} ++ ++void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3) ++{ ++ *txpwr_lvl_v3 = userconfig_info.txpwr_lvl_v3; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v3->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_1m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_2m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_5m5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_11m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[11]); ++} ++ ++void get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_conf_v4_t *txpwr_lvl_v4) ++{ ++ *txpwr_lvl_v4 = userconfig_info.txpwr_lvl_v4; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v4->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[11]); ++} ++ ++void get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj) ++{ ++ *txpwr_lvl_adj = userconfig_info.txpwr_lvl_adj; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_adj->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_1_4:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_5_9:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_10_13:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[2]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_42:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_58:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_106:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_122:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_138:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_155:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[5]); ++} ++ ++#ifdef CONFIG_POWER_LIMIT ++#define GetLineFromBuffer(buffer) strsep(&buffer, "\n") ++ ++int isAllSpaceOrTab(uint8_t *data, uint8_t size) ++{ ++ uint8_t cnt = 0, NumOfSpaceAndTab = 0; ++ while (size > cnt) { ++ if (data[cnt] == ' ' || data[cnt] == '\t' || data[cnt] == '\0') ++ ++NumOfSpaceAndTab; ++ ++cnt; ++ } ++ return size == NumOfSpaceAndTab; ++} ++ ++int IsCommentString(char *szStr) ++{ ++ if (*szStr == '#' && *(szStr + 1) == ' ') ++ return 1; ++ else ++ return 0; ++} ++ ++int ParseQualifiedString(char *In, u32 *Start, char *Out, char LeftQualifier, char RightQualifier) ++{ ++ u32 i = 0, j = 0; ++ char c = In[(*Start)++]; ++ if (c != LeftQualifier) ++ return 0; ++ i = (*Start); ++ c = In[(*Start)++]; ++ while (c != RightQualifier && c != '\0') ++ c = In[(*Start)++]; ++ if (c == '\0') ++ return 0; ++ j = (*Start) - 2; ++ strncpy((char *)Out, (const char *)(In + i), j - i + 1); ++ return 1; ++} ++ ++int GetU1ByteIntegerFromStringInDecimal(char *Str, u8 *pInt) ++{ ++ u16 i = 0; ++ *pInt = 0; ++ while (Str[i] != '\0') { ++ if (Str[i] >= '0' && Str[i] <= '9') { ++ *pInt *= 10; ++ *pInt += (Str[i] - '0'); ++ } else ++ return 0; ++ ++i; ++ } ++ return 1; ++} ++int GetS1ByteIntegerFromStringInDecimal(char *str, s8 *val) ++{ ++ u8 negative = 0; ++ u16 i = 0; ++ *val = 0; ++ while (str[i] != '\0') { ++ if (i == 0 && (str[i] == '+' || str[i] == '-')) { ++ if (str[i] == '-') ++ negative = 1; ++ } else if (str[i] >= '0' && str[i] <= '9') { ++ *val *= 10; ++ *val += (str[i] - '0'); ++ } else ++ return 0; ++ ++i; ++ } ++ if (negative) ++ *val = -*val; ++ return 1; ++} ++ ++int8_t rwnx_plat_powerlimit_save(u8_l band, char *channel, u8_l bw, char *limit, char *name) ++{ ++ u8 channel_num, powerLimit_val, reg_idx; ++ ++ if (GetU1ByteIntegerFromStringInDecimal((char *)channel, &channel_num) == 0 ++ || GetS1ByteIntegerFromStringInDecimal((char *)limit, &powerLimit_val) == 0) { ++ AICWFDBG(LOGERROR, "Illegal index of power limit table [ch %s][val %s]\n", channel, limit); ++ return -1; ++ } ++ ++ reg_idx = get_region_index(name); ++ ++ if (band == PHY_BAND_2G4) { ++ uint8_t cur_idx = powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_2g4[bw]; ++ AICWFDBG(LOGINFO, "reg_idx=%d, band=%d, bw=%d, cur_idx=%d, ch=%s, pwr=%s\n", ++ reg_idx, band, bw, cur_idx, channel, limit); ++ if (cur_idx < MAC_DOMAINCHANNEL_24G_MAX) { ++ powerlimit_info.txpwr_lmt[reg_idx].ch_num_2g4[bw][cur_idx] = channel_num; ++ powerlimit_info.txpwr_lmt[reg_idx].max_pwr_2g4[bw][cur_idx] = powerLimit_val; ++ powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_2g4[bw]++; ++ } else { ++ AICWFDBG(LOGERROR, "band %d chan_cnt reached %d\n", band, MAC_DOMAINCHANNEL_24G_MAX); ++ AICWFDBG(LOGERROR, "channel=%s(%d) powerLimit=%s(%d)\n", channel, channel_num, limit, powerLimit_val); ++ } ++ } else if (band == PHY_BAND_5G) { ++ uint8_t cur_idx = powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_5g[bw]; ++ AICWFDBG(LOGINFO, "reg_idx=%d, band=%d, bw=%d, cur_idx=%d, ch=%s, pwr=%s\n", ++ reg_idx, band, bw, cur_idx, channel, limit); ++ if (cur_idx < MAC_DOMAINCHANNEL_5G_MAX) { ++ powerlimit_info.txpwr_lmt[reg_idx].ch_num_5g[bw][cur_idx] = channel_num; ++ powerlimit_info.txpwr_lmt[reg_idx].max_pwr_5g[bw][cur_idx] = powerLimit_val; ++ powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_5g[bw]++; ++ } else { ++ AICWFDBG(LOGERROR, "band %d chan_cnt reached %d\n", band, MAC_DOMAINCHANNEL_5G_MAX); ++ AICWFDBG(LOGERROR, "channel=%s(%d) powerLimit=%s(%d)\n", channel, channel_num, limit, powerLimit_val); ++ } ++ } ++ ++ return 0; ++} ++ ++ ++void rwnx_plat_powerlimit_parsing(char *buffer, int size, char *cc) ++{ ++#define LD_STAGE_EXC_MAPPING 0 ++#define LD_STAGE_TAB_DEFINE 1 ++#define LD_STAGE_TAB_START 2 ++#define LD_STAGE_COLUMN_DEFINE 3 ++#define LD_STAGE_CH_ROW 4 ++ ++ uint8_t loadingStage = LD_STAGE_EXC_MAPPING; ++ uint32_t i = 0, forCnt = 0; ++ uint32_t i_cc; ++ char *szLine, *ptmp; ++ char band[10], colNumBuf[10], bandwidth[10]; ++ uint8_t colNum = 0, band_cc = 0, bw_cc = 0; ++ char **reg_name = NULL; ++ // clear powerlimit info at first ++ memset((void *)&powerlimit_info, 0, sizeof(powerlimit_info_t)); ++ ptmp = buffer; ++ for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { ++ if (isAllSpaceOrTab(szLine, sizeof(*szLine))) ++ continue; ++ if (IsCommentString(szLine)) ++ continue; ++ ++ if (loadingStage == LD_STAGE_EXC_MAPPING) { ++ if (szLine[0] == '#' || szLine[1] == '#') { ++ loadingStage = LD_STAGE_TAB_DEFINE; ++ } else { ++ continue; ++ } ++ } ++ ++ if (loadingStage == LD_STAGE_TAB_DEFINE) { ++ /* read "## 2.4G" */ ++ if (szLine[0] != '#' || szLine[1] != '#') ++ continue; ++ ++ /* skip the space */ ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ szLine[--i] = ' '; /* return the space in front of the regulation info */ ++ ++ /* Parse the label of the table */ ++ memset((void *)band, 0, 10); ++ memset((void *)bandwidth, 0, 10); ++ memset((void *)colNumBuf, 0, 10); ++ ++ if (!ParseQualifiedString(szLine, &i, band, ' ', ',')) { ++ AICWFDBG(LOGERROR, "Fail to parse band!\n"); ++ goto exit; ++ } ++ if (strncmp(band, "2.4G", 4) == 0) { ++ band_cc = PHY_BAND_2G4; ++ } else if (strncmp(band, "5G", 2) == 0) { ++ band_cc = PHY_BAND_5G; ++ } ++ ++ if (!ParseQualifiedString(szLine, &i, bandwidth, ' ', ',')) { ++ AICWFDBG(LOGERROR, "Fail to parse bandwidth!\n"); ++ goto exit; ++ } ++ if (strncmp(bandwidth, "20M", 3) == 0) ++ bw_cc = PHY_CHNL_BW_20; ++ else if (strncmp(bandwidth, "40M", 3) == 0) ++ bw_cc = PHY_CHNL_BW_40; ++ else if (strncmp(bandwidth, "80M", 3) == 0) ++ bw_cc = PHY_CHNL_BW_80; ++ ++ if (!ParseQualifiedString(szLine, &i, colNumBuf, '#', '#')) { ++ AICWFDBG(LOGERROR, "Fail to parse column number!\n"); ++ goto exit; ++ } ++ if (!GetU1ByteIntegerFromStringInDecimal(colNumBuf, &colNum)) { ++ AICWFDBG(LOGERROR, "Column number \"%s\" is not unsigned decimal\n", colNumBuf); ++ goto exit; ++ } ++ if (colNum == 0) { ++ AICWFDBG(LOGERROR, "Column number is 0\n"); ++ goto exit; ++ } ++ ++ AICWFDBG(LOGINFO, "band=%s, bandwidth=%s, colnum=%d\n", band, bandwidth, colNum); ++ loadingStage = LD_STAGE_TAB_START; ++ } else if (loadingStage == LD_STAGE_TAB_START) { ++ /* read "## START" */ ++ if (szLine[0] != '#' || szLine[1] != '#') ++ continue; ++ ++ /* skip the space */ ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ if (strncmp((u8 *)(szLine + i), "START", 5)) { ++ AICWFDBG(LOGERROR, "Missing \"## START\" label\n"); ++ goto exit; ++ } ++ ++ loadingStage = LD_STAGE_COLUMN_DEFINE; ++ } else if (loadingStage == LD_STAGE_COLUMN_DEFINE) { ++ /* read "## FCC ETSI" */ ++ if (szLine[0] != '#' || szLine[1] != '#') ++ continue; ++ ++ /* skip the space */ ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ reg_name = (char **)kmalloc(sizeof(char *) * colNum, GFP_KERNEL); ++ if (!reg_name) { ++ AICWFDBG(LOGERROR, "reg_name alloc fail\n"); ++ goto exit; ++ } ++ ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ /* skip the space */ ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ i++; ++ i_cc = i; ++ ++ while (szLine[i] != ' ' && szLine[i] != '\t' && szLine[i] != '\0') ++ i++; ++ ++ reg_name[forCnt] = (char *)kmalloc(i - i_cc + 1, GFP_KERNEL); ++ if (!reg_name[forCnt]) { ++ AICWFDBG(LOGERROR, "reg_name element alloc fail\n"); ++ goto exit; ++ } ++ ++ strncpy(reg_name[forCnt], szLine + i_cc, i - i_cc); ++ reg_name[forCnt][i - i_cc] = '\0'; ++ AICWFDBG(LOGINFO, "reg_name: %s\n", reg_name[forCnt]); ++ ++ } ++ ++ loadingStage = LD_STAGE_CH_ROW; ++ } else if (loadingStage == LD_STAGE_CH_ROW) { ++ char channel[10] = {0}, powerLimit[10] = {0}; ++ u8 cnt = 0; ++ ++ /* the table ends */ ++ if (szLine[0] == '#' && szLine[1] == '#') { ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ if (strncmp((u8 *)(szLine + i), "END", 3) == 0) { ++ loadingStage = LD_STAGE_TAB_DEFINE; ++ if (reg_name) { ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ if (reg_name[forCnt]) { ++ kfree(reg_name[forCnt]); ++ reg_name[forCnt] = NULL; ++ } ++ } ++ kfree(reg_name); ++ reg_name = NULL; ++ } ++ colNum = 0; ++ continue; ++ } else { ++ AICWFDBG(LOGERROR, "Missing \"## END\" label\n"); ++ goto exit; ++ } ++ } ++ ++ if ((szLine[0] != 'c' && szLine[0] != 'C') || ++ (szLine[1] != 'h' && szLine[1] != 'H')) { ++ AICWFDBG(LOGERROR, "Wrong channel prefix: '%c','%c'(%d,%d)\n", szLine[0], szLine[1], szLine[0], szLine[1]); ++ continue; ++ } ++ i = 2;/* move to the location behind 'h' */ ++ ++ /* load the channel number */ ++ cnt = 0; ++ while (szLine[i] >= '0' && szLine[i] <= '9') { ++ channel[cnt] = szLine[i]; ++ ++cnt; ++ ++i; ++ } ++ ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ /* skip the space between channel number and the power limit value */ ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ /* load the power limit value */ ++ memset((void *)powerLimit, 0, 10); ++ ++ if (szLine[i] == 'N' && szLine[i + 1] == 'A') { ++ /* ++ * means channel not available ++ */ ++ sprintf(powerLimit, "%d", POWER_LIMIT_INVALID_VAL); ++ i += 2; ++ } else if ((szLine[i] >= '0' && szLine[i] <= '9') ++ || szLine[i] == '+' || szLine[i] == '-') { ++ /* case of dBm value */ ++ cnt = 0; ++ while ((szLine[i] >= '0' && szLine[i] <= '9') ++ || szLine[i] == '+' || szLine[i] == '-' ++ ) { ++ powerLimit[cnt] = szLine[i]; ++ ++cnt; ++ ++i; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "Wrong limit expression \"%c%c\"(%d, %d)\n", ++ szLine[i], szLine[i + 1], szLine[i], szLine[i + 1]); ++ goto exit; ++ } ++ ++ if (rwnx_plat_powerlimit_save(band_cc, channel, bw_cc, powerLimit, reg_name[forCnt]) < 0) ++ goto exit; ++ } ++ } ++ } ++ ++ powerlimit_info.flags |= POWER_LIMIT_CC_MATCHED_BIT; ++exit: ++ if (reg_name) { ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ if (reg_name[forCnt]) { ++ kfree(reg_name[forCnt]); ++ reg_name[forCnt] = NULL; ++ } ++ } ++ kfree(reg_name); ++ reg_name = NULL; ++ } ++ ++ return; ++} ++ ++ ++/// 5G lower bound freq ++#define PHY_FREQ_5G 5000 ++ ++uint16_t phy_channel_to_freq(uint8_t band, int channel) ++{ ++ if ((band == PHY_BAND_2G4) && (channel >= 1) && (channel <= 14)) { ++ if (channel == 14) ++ return 2484; ++ else ++ return 2407 + channel * 5; ++ } else if ((band == PHY_BAND_5G) && (channel >= 1) && (channel <= 165)) { ++ return PHY_FREQ_5G + channel * 5; ++ } ++ return 0; ++} ++ ++int8_t get_powerlimit_by_freq(uint8_t band, uint16_t freq, uint8_t r_idx) ++{ ++ int8_t ret = POWER_LIMIT_INVALID_VAL; ++ uint8_t idx; ++ if (!(powerlimit_info.flags & POWER_LIMIT_CC_MATCHED_BIT)) { ++ AICWFDBG(LOGERROR, "powerlimit flag not set\n"); ++ return ret; ++ } ++ ++ if (band == PHY_BAND_2G4) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_2g4[0]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ int ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_2g4[0][idx]; ++ uint16_t freq_tmp = phy_channel_to_freq(PHY_BAND_2G4, ch_num); ++ if (freq == freq_tmp) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_2g4[0][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d(freq=%d), pwr=%d\n", idx, ch_num, freq, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "powerlimit search failed: band=%d freq=%d\n", band, freq); ++ } else if (band == PHY_BAND_5G) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_5g[0]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ int ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_5g[0][idx]; ++ uint16_t freq_tmp = phy_channel_to_freq(PHY_BAND_5G, ch_num); ++ if (freq == freq_tmp) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_5g[0][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d(freq=%d), pwr=%d\n", idx, ch_num, freq, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "powerlimit search failed: band=%d freq=%d\n", band, freq); ++ } ++ return ret; ++} ++ ++int8_t get_powerlimit_by_chnum(uint8_t chnum, uint8_t r_idx, uint8_t bw) ++{ ++ int8_t ret = POWER_LIMIT_INVALID_VAL; ++ uint8_t idx; ++ if (!(powerlimit_info.flags & POWER_LIMIT_CC_MATCHED_BIT)) { ++ AICWFDBG(LOGERROR, "powerlimit flag not set\n"); ++ return ret; ++ } ++ ++ if (chnum <= 14) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_2g4[bw]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ uint8_t ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_2g4[bw][idx]; ++ if (chnum == ch_num) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_2g4[bw][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d, pwr=%d\n", idx, ch_num, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "%s powerlimit search failed: chnum=%d, please confirm the center frequency\n", ++ __func__, chnum); ++ } else if (chnum <= 165) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_5g[bw]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ uint8_t ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_5g[bw][idx]; ++ if (chnum == ch_num) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_5g[bw][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d, pwr=%d\n", idx, ch_num, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "%s powerlimit search failed: chnum=%d, please confirm the center frequency\n", ++ __func__, chnum); ++ } ++ ++ return ret; ++} ++#endif ++ ++/** ++ * rwnx_plat_userconfig_load ---Load aic_userconfig.txt ++ *@filename name of config ++*/ ++static int rwnx_plat_userconfig_load(struct rwnx_hw *rwnx_hw) { ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ ++ rwnx_plat_userconfig_upload_android(rwnx_hw, aic_fw_path, FW_USERCONFIG_NAME); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC){ ++ rwnx_plat_userconfig_load_8800dc(rwnx_hw); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ rwnx_plat_userconfig_load_8800dw(rwnx_hw); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ rwnx_plat_userconfig_load_8800d80(rwnx_hw); ++#ifdef CONFIG_POWER_LIMIT ++ rwnx_plat_powerlimit_load_8800d80(rwnx_hw); ++#endif ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ rwnx_plat_userconfig_load_8800d80x2(rwnx_hw); ++#ifdef CONFIG_POWER_LIMIT ++ rwnx_plat_powerlimit_load_8800d80x2(rwnx_hw); ++#endif ++ } ++ return 0; ++} ++ ++void get_userconfig_txpwr_loss(txpwr_loss_conf_t *txpwr_loss) ++{ ++ txpwr_loss->loss_enable_2g4 = userconfig_info.txpwr_loss.loss_enable_2g4; ++ txpwr_loss->loss_value_2g4 = userconfig_info.txpwr_loss.loss_value_2g4; ++ txpwr_loss->loss_enable_5g = userconfig_info.txpwr_loss.loss_enable_5g; ++ txpwr_loss->loss_value_5g = userconfig_info.txpwr_loss.loss_value_5g; ++ ++ AICWFDBG(LOGDEBUG, "%s:loss_enable_2g4: %d, val_2g4: %d, loss_enable_5g: %d, val_5g: %d\r\n", __func__, ++ txpwr_loss->loss_enable_2g4, txpwr_loss->loss_value_2g4, ++ txpwr_loss->loss_enable_5g, txpwr_loss->loss_value_5g); ++ ++} ++ ++/** ++ * rwnx_platform_on() - Start the platform ++ * ++ * @rwnx_hw: Main driver data ++ * @config: Config to restore (NULL if nothing to restore) ++ * ++ * It starts the platform : ++ * - load fw and ucodes ++ * - initialize IPC ++ * - boot the fw ++ * - enable link communication/IRQ ++ * ++ * Called by 802.11 part ++ */ ++int rwnx_platform_on(struct rwnx_hw *rwnx_hw, void *config) ++{ ++ int ret; ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ (void)ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (rwnx_plat->enabled) ++ return 0; ++ ++ #ifndef CONFIG_ROM_PATCH_EN ++ #ifdef CONFIG_DOWNLOAD_FW ++ ret = rwnx_plat_fmac_load(rwnx_hw, (char*)config); ++ if (ret) ++ return ret; ++ #endif /* !CONFIG_ROM_PATCH_EN */ ++ #endif ++ ++#if 0 ++ ret = rwnx_plat_patch_load(rwnx_hw); ++ if (ret) { ++ return ret; ++ } ++#endif ++ ++ ++ rwnx_plat_userconfig_load(rwnx_hw); ++ ++ //rwnx_plat->enabled = true; ++ ++ return 0; ++} ++ ++/** ++ * rwnx_platform_off() - Stop the platform ++ * ++ * @rwnx_hw: Main driver data ++ * @config: Updated with pointer to config, to be able to restore it with ++ * rwnx_platform_on(). It's up to the caller to free the config. Set to NULL ++ * if configuration is not needed. ++ * ++ * Called by 802.11 part ++ */ ++void rwnx_platform_off(struct rwnx_hw *rwnx_hw, void **config) ++{ ++#if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) ++ tasklet_kill(&rwnx_hw->task); ++ rwnx_hw->plat->enabled = false; ++ return ; ++#endif ++ ++ if (!rwnx_hw->plat->enabled) { ++ if (config) ++ *config = NULL; ++ return; ++ } ++ ++ if (config) ++ *config = rwnx_term_save_config(rwnx_hw->plat); ++ ++ rwnx_hw->plat->disable(rwnx_hw); ++ ++ tasklet_kill(&rwnx_hw->task); ++ rwnx_platform_reset(rwnx_hw->plat); ++ ++ rwnx_hw->plat->enabled = false; ++} ++ ++/** ++ * rwnx_platform_init() - Initialize the platform ++ * ++ * @rwnx_plat: platform data (already updated by platform driver) ++ * @platform_data: Pointer to store the main driver data pointer (aka rwnx_hw) ++ * That will be set as driver data for the platform driver ++ * Return: 0 on success, < 0 otherwise ++ * ++ * Called by the platform driver after it has been probed ++ */ ++int rwnx_platform_init(struct rwnx_plat *rwnx_plat, void **platform_data) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_plat->enabled = false; ++ g_rwnx_plat = rwnx_plat; ++ ++#if defined CONFIG_RWNX_FULLMAC ++ return rwnx_cfg80211_init(rwnx_plat, platform_data); ++#elif defined CONFIG_RWNX_FHOST ++ return rwnx_fhost_init(rwnx_plat, platform_data); ++#endif ++} ++ ++/** ++ * rwnx_platform_deinit() - Deinitialize the platform ++ * ++ * @rwnx_hw: main driver data ++ * ++ * Called by the platform driver after it is removed ++ */ ++void rwnx_platform_deinit(struct rwnx_hw *rwnx_hw) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#if defined CONFIG_RWNX_FULLMAC ++ rwnx_cfg80211_deinit(rwnx_hw); ++#elif defined CONFIG_RWNX_FHOST ++ rwnx_fhost_deinit(rwnx_hw); ++#endif ++} ++ ++/** ++ * rwnx_platform_register_drv() - Register all possible platform drivers ++ */ ++int rwnx_platform_register_drv(void) ++{ ++ return rwnx_pci_register_drv(); ++} ++ ++ ++/** ++ * rwnx_platform_unregister_drv() - Unegister all platform drivers ++ */ ++void rwnx_platform_unregister_drv(void) ++{ ++ return rwnx_pci_unregister_drv(); ++} ++ ++struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ return rwnx_plat->sdiodev->dev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ return rwnx_plat->usbdev->dev; ++#endif ++ return &(rwnx_plat->pci_dev->dev); ++} ++ ++ ++#ifndef CONFIG_RWNX_SDM ++MODULE_FIRMWARE(RWNX_AGC_FW_NAME); ++MODULE_FIRMWARE(RWNX_FCU_FW_NAME); ++MODULE_FIRMWARE(RWNX_LDPC_RAM_NAME); ++#endif ++MODULE_FIRMWARE(RWNX_MAC_FW_NAME); ++#ifndef CONFIG_RWNX_TL4 ++MODULE_FIRMWARE(RWNX_MAC_FW_NAME2); ++#endif ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h +new file mode 100644 +index 000000000000..1ce300dbfed5 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h +@@ -0,0 +1,159 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_platorm.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_PLATFORM_H_ ++#define _RWNX_PLATFORM_H_ ++ ++#include ++#include "lmac_msg.h" ++ ++#define RWNX_CONFIG_FW_NAME "rwnx_settings.ini" ++#define RWNX_PHY_CONFIG_TRD_NAME "rwnx_trident.ini" ++#define RWNX_PHY_CONFIG_KARST_NAME "rwnx_karst.ini" ++#define RWNX_AGC_FW_NAME "agcram.bin" ++#define RWNX_LDPC_RAM_NAME "ldpcram.bin" ++#ifdef CONFIG_RWNX_FULLMAC ++#define RWNX_MAC_FW_BASE_NAME "fmacfw" ++#elif defined CONFIG_RWNX_FHOST ++#define RWNX_MAC_FW_BASE_NAME "fhostfw" ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_TL4 ++#define RWNX_MAC_FW_NAME RWNX_MAC_FW_BASE_NAME".hex" ++#else ++#define RWNX_MAC_FW_NAME RWNX_MAC_FW_BASE_NAME".ihex" ++#define RWNX_MAC_FW_NAME2 RWNX_MAC_FW_BASE_NAME".bin" ++#endif ++ ++#define RWNX_FCU_FW_NAME "fcuram.bin" ++#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++#define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_lite_8800dc.bin" ++#endif ++ ++/** ++ * Type of memory to access (cf rwnx_plat.get_address) ++ * ++ * @RWNX_ADDR_CPU To access memory of the embedded CPU ++ * @RWNX_ADDR_SYSTEM To access memory/registers of one subsystem of the ++ * embedded system ++ * ++ */ ++enum rwnx_platform_addr { ++ RWNX_ADDR_CPU, ++ RWNX_ADDR_SYSTEM, ++ RWNX_ADDR_MAX, ++}; ++ ++#define POWER_LEVEL_INVALID_VAL (127) ++ ++typedef enum { ++ REGIONS_SRRC, ++ REGIONS_FCC, ++ REGIONS_ETSI, ++ REGIONS_JP, ++ REGIONS_DEFAULT, ++} Regions_code; ++ ++struct rwnx_hw; ++ ++/** ++ * struct rwnx_plat - Operation pointers for RWNX PCI platform ++ * ++ * @pci_dev: pointer to pci dev ++ * @enabled: Set if embedded platform has been enabled (i.e. fw loaded and ++ * ipc started) ++ * @enable: Configure communication with the fw (i.e. configure the transfers ++ * enable and register interrupt) ++ * @disable: Stop communication with the fw ++ * @deinit: Free all ressources allocated for the embedded platform ++ * @get_address: Return the virtual address to access the requested address on ++ * the platform. ++ * @ack_irq: Acknowledge the irq at link level. ++ * @get_config_reg: Return the list (size + pointer) of registers to restore in ++ * order to reload the platform while keeping the current configuration. ++ * ++ * @priv Private data for the link driver ++ */ ++struct rwnx_plat { ++ struct pci_dev *pci_dev; ++ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ bool enabled; ++ ++ int (*enable)(struct rwnx_hw *rwnx_hw); ++ int (*disable)(struct rwnx_hw *rwnx_hw); ++ void (*deinit)(struct rwnx_plat *rwnx_plat); ++ u8* (*get_address)(struct rwnx_plat *rwnx_plat, int addr_name, ++ unsigned int offset); ++ void (*ack_irq)(struct rwnx_plat *rwnx_plat); ++ int (*get_config_reg)(struct rwnx_plat *rwnx_plat, const u32 **list); ++ ++ u8 priv[0] __aligned(sizeof(void *)); ++}; ++ ++#define RWNX_ADDR(plat, base, offset) \ ++ plat->get_address(plat, base, offset) ++ ++#define RWNX_REG_READ(plat, base, offset) \ ++ readl(plat->get_address(plat, base, offset)) ++ ++#define RWNX_REG_WRITE(val, plat, base, offset) \ ++ writel(val, plat->get_address(plat, base, offset)) ++ ++extern struct rwnx_plat *g_rwnx_plat; ++ ++int rwnx_platform_init(struct rwnx_plat *rwnx_plat, void **platform_data); ++void rwnx_platform_deinit(struct rwnx_hw *rwnx_hw); ++ ++int rwnx_platform_on(struct rwnx_hw *rwnx_hw, void *config); ++void rwnx_platform_off(struct rwnx_hw *rwnx_hw, void **config); ++ ++int rwnx_platform_register_drv(void); ++void rwnx_platform_unregister_drv(void); ++ ++void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx); ++void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst); ++void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap); ++s8_l get_txpwr_max(s8_l power); ++void set_txpwr_loss_ofst(s8_l value); ++ ++void get_userconfig_txpwr_lvl_in_fdrv(txpwr_lvl_conf_t *txpwr_lvl); ++void get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_conf_v2_t *txpwr_lvl_v2); ++void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3); ++void get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_conf_v4_t *txpwr_lvl_v4); ++void get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj); ++uint8_t get_ccode_region(char * ccode); ++u8 get_region_index(char * name); ++ ++#ifdef CONFIG_POWER_LIMIT ++int8_t rwnx_plat_powerlimit_save(u8_l band, char *channel, u8_l bw, char *limit, char *name); ++void rwnx_plat_powerlimit_parsing(char *buffer, int size, char *cc); ++int8_t get_powerlimit_by_freq(uint8_t band, uint16_t freq, uint8_t r_idx); ++int8_t get_powerlimit_by_chnum(uint8_t chnum, uint8_t r_idx, uint8_t bw); ++#endif ++ ++void get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst_conf_t *txpwr_ofst); ++void get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x_conf_t *txpwr_ofst2x); ++void get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2); ++void get_userconfig_txpwr_loss(txpwr_loss_conf_t *txpwr_loss); ++extern struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat); ++ ++static inline unsigned int rwnx_platform_get_irq(struct rwnx_plat *rwnx_plat) ++{ ++ return rwnx_plat->pci_dev->irq; ++} ++ ++#endif /* _RWNX_PLATFORM_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h +new file mode 100644 +index 000000000000..5442f588212f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h +@@ -0,0 +1,133 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_prof.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_PROF_H_ ++#define _RWNX_PROF_H_ ++ ++#include "reg_access.h" ++#include "rwnx_platform.h" ++ ++static inline void rwnx_prof_set(struct rwnx_hw *rwnx_hw, int val) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_SET_PROFILING_ADDR); ++} ++ ++static inline void rwnx_prof_clear(struct rwnx_hw *rwnx_hw, int val) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_CLEAR_PROFILING_ADDR); ++} ++ ++#if 0 ++/* Defines for SW Profiling registers values */ ++enum { ++ TX_IPC_IRQ, ++ TX_IPC_EVT, ++ TX_PREP_EVT, ++ TX_DMA_IRQ, ++ TX_MAC_IRQ, ++ TX_PAYL_HDL, ++ TX_CFM_EVT, ++ TX_IPC_CFM, ++ RX_MAC_IRQ, // 8 ++ RX_TRIGGER_EVT, ++ RX_DMA_IRQ, ++ RX_DMA_EVT, ++ RX_IPC_IND, ++ RX_MPDU_XFER, ++ DBG_PROF_MAX ++}; ++#endif ++ ++enum { ++ SW_PROF_HOSTBUF_IDX = 12, ++ /****** IPC IRQs related signals ******/ ++ /* E2A direction */ ++ SW_PROF_IRQ_E2A_RXDESC = 16, // to make sure we let 16 bits available for LMAC FW ++ SW_PROF_IRQ_E2A_TXCFM, ++ SW_PROF_IRQ_E2A_DBG, ++ SW_PROF_IRQ_E2A_MSG, ++ SW_PROF_IPC_MSGPUSH, ++ SW_PROF_MSGALLOC, ++ SW_PROF_MSGIND, ++ SW_PROF_DBGIND, ++ ++ /* A2E direction */ ++ SW_PROF_IRQ_A2E_TXCFM_BACK, ++ ++ /****** Driver functions related signals ******/ ++ SW_PROF_WAIT_QUEUE_STOP, ++ SW_PROF_WAIT_QUEUE_WAKEUP, ++ SW_PROF_RWNXDATAIND, ++ SW_PROF_RWNX_IPC_IRQ_HDLR, ++ SW_PROF_RWNX_IPC_THR_IRQ_HDLR, ++ SW_PROF_IEEE80211RX, ++ SW_PROF_RWNX_PATTERN, ++ SW_PROF_MAX ++}; ++ ++// [LT]For debug purpose only ++#if (0) ++#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (21) ++#define SW_PROF_CHAN_CTXT_CFM_BIT (22) ++#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (23) ++#define SW_PROF_CHAN_CTXT_PUSH_BIT (24) ++#define SW_PROF_CHAN_CTXT_QUEUE_BIT (25) ++#define SW_PROF_CHAN_CTXT_TX_BIT (26) ++#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (27) ++#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (28) ++#define SW_PROF_CHAN_CTXT_SWTCH_BIT (29) ++ ++// TO DO: update this ++ ++#define REG_SW_SET_PROFILING_CHAN(env, bit) \ ++ rwnx_prof_set((struct rwnx_hw *)env, BIT(bit)) ++ ++#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) \ ++ rwnx_prof_clear((struct rwnx_hw *)env, BIT(bit)) ++ ++#else ++#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (0) ++#define SW_PROF_CHAN_CTXT_CFM_BIT (0) ++#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (0) ++#define SW_PROF_CHAN_CTXT_PUSH_BIT (0) ++#define SW_PROF_CHAN_CTXT_QUEUE_BIT (0) ++#define SW_PROF_CHAN_CTXT_TX_BIT (0) ++#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (0) ++#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (0) ++#define SW_PROF_CHAN_CTXT_SWTCH_BIT (0) ++ ++#define REG_SW_SET_PROFILING_CHAN(env, bit) do {} while (0) ++#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) do {} while (0) ++#endif ++ ++#ifdef CONFIG_RWNX_SW_PROFILING ++/* Macros for SW PRofiling registers access */ ++#define REG_SW_SET_PROFILING(env, bit) \ ++ rwnx_prof_set((struct rwnx_hw *)env, BIT(bit)) ++ ++#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) \ ++ rwnx_prof_set((struct rwnx_hw *)env, val << (SW_PROF_HOSTBUF_IDX)) ++ ++#define REG_SW_CLEAR_PROFILING(env, bit) \ ++ rwnx_prof_clear((struct rwnx_hw *)env, BIT(bit)) ++ ++#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) \ ++ rwnx_prof_clear((struct rwnx_hw *)env, 0x0F << (SW_PROF_HOSTBUF_IDX)) ++ ++#else ++#define REG_SW_SET_PROFILING(env, value) do {} while (0) ++#define REG_SW_CLEAR_PROFILING(env, value) do {} while (0) ++#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) do {} while (0) ++#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) do {} while (0) ++#endif ++ ++#endif /* _RWNX_PROF_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c +new file mode 100644 +index 000000000000..5017fd36f3bf +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c +@@ -0,0 +1,1657 @@ ++/** ++****************************************************************************** ++ * ++ * @file rwnx_radar.c ++ * ++ * @brief Functions to handle radar detection ++ * Radar detection is copied (and adapted) from ath driver source code. ++ * ++ * Copyright (c) 2012 Neratec Solutions AG ++ * Copyright (C) RivieraWaves 2015-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++#include ++ ++#include "rwnx_radar.h" ++#include "rwnx_defs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++ ++/* ++ * tolerated deviation of radar time stamp in usecs on both sides ++ * TODO: this might need to be HW-dependent ++ */ ++#define PRI_TOLERANCE 16 ++ ++/** ++ * struct radar_types - contains array of patterns defined for one DFS domain ++ * @domain: DFS regulatory domain ++ * @num_radar_types: number of radar types to follow ++ * @radar_types: radar types array ++ */ ++struct radar_types { ++ enum nl80211_dfs_regions region; ++ u32 num_radar_types; ++ const struct radar_detector_specs *spec_riu; ++ const struct radar_detector_specs *spec_fcu; ++}; ++ ++/** ++ * Type of radar waveform: ++ * RADAR_WAVEFORM_SHORT : waveform defined by ++ * - pulse width ++ * - pulse interval in a burst (pri) ++ * - number of pulses in a burst (ppb) ++ * ++ * RADAR_WAVEFORM_WEATHER : ++ * same than SHORT except that ppb is dependent of pri ++ * ++ * RADAR_WAVEFORM_INTERLEAVED : ++ * same than SHORT except there are several value of pri (interleaved) ++ * ++ * RADAR_WAVEFORM_LONG : ++ * ++ */ ++enum radar_waveform_type { ++ RADAR_WAVEFORM_SHORT, ++ RADAR_WAVEFORM_WEATHER, ++ RADAR_WAVEFORM_INTERLEAVED, ++ RADAR_WAVEFORM_LONG ++}; ++ ++/** ++ * struct radar_detector_specs - detector specs for a radar pattern type ++ * @type_id: pattern type, as defined by regulatory ++ * @width_min: minimum radar pulse width in [us] ++ * @width_max: maximum radar pulse width in [us] ++ * @pri_min: minimum pulse repetition interval in [us] (including tolerance) ++ * @pri_max: minimum pri in [us] (including tolerance) ++ * @num_pri: maximum number of different pri for this type ++ * @ppb: pulses per bursts for this type ++ * @ppb_thresh: number of pulses required to trigger detection ++ * @max_pri_tolerance: pulse time stamp tolerance on both sides [us] ++ * @type: Type of radar waveform ++ */ ++struct radar_detector_specs { ++ u8 type_id; ++ u8 width_min; ++ u8 width_max; ++ u16 pri_min; ++ u16 pri_max; ++ u8 num_pri; ++ u8 ppb; ++ u8 ppb_thresh; ++ u8 max_pri_tolerance; ++ enum radar_waveform_type type; ++}; ++ ++ ++/* percentage on ppb threshold to trigger detection */ ++#define MIN_PPB_THRESH 50 ++#define PPB_THRESH(PPB) ((PPB * MIN_PPB_THRESH + 50) / 100) ++#define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF) ++ ++/* width tolerance */ ++#define WIDTH_TOLERANCE 2 ++#define WIDTH_LOWER(X) (X) ++#define WIDTH_UPPER(X) (X) ++ ++#define ETSI_PATTERN_SHORT(ID, WMIN, WMAX, PMIN, PMAX, PPB) \ ++ { \ ++ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ ++ (PRF2PRI(PMAX) - PRI_TOLERANCE), \ ++ (PRF2PRI(PMIN) + PRI_TOLERANCE), 1, PPB, \ ++ PPB_THRESH(PPB), PRI_TOLERANCE, RADAR_WAVEFORM_SHORT \ ++ } ++ ++#define ETSI_PATTERN_INTERLEAVED(ID, WMIN, WMAX, PMIN, PMAX, PRFMIN, PRFMAX, PPB) \ ++ { \ ++ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ ++ (PRF2PRI(PMAX) * PRFMIN- PRI_TOLERANCE), \ ++ (PRF2PRI(PMIN) * PRFMAX + PRI_TOLERANCE), \ ++ PRFMAX, PPB * PRFMAX, \ ++ PPB_THRESH(PPB), PRI_TOLERANCE, RADAR_WAVEFORM_INTERLEAVED \ ++ } ++ ++/* radar types as defined by ETSI EN-301-893 v1.7.1 */ ++static const struct radar_detector_specs etsi_radar_ref_types_v17_riu[] = { ++ ETSI_PATTERN_SHORT(0, 0, 8, 700, 700, 18), ++ ETSI_PATTERN_SHORT(1, 0, 10, 200, 1000, 10), ++ ETSI_PATTERN_SHORT(2, 0, 22, 200, 1600, 15), ++ ETSI_PATTERN_SHORT(3, 0, 22, 2300, 4000, 25), ++ ETSI_PATTERN_SHORT(4, 20, 38, 2000, 4000, 20), ++ ETSI_PATTERN_INTERLEAVED(5, 0, 8, 300, 400, 2, 3, 10), ++ ETSI_PATTERN_INTERLEAVED(6, 0, 8, 400, 1200, 2, 3, 15), ++}; ++ ++static const struct radar_detector_specs etsi_radar_ref_types_v17_fcu[] = { ++ ETSI_PATTERN_SHORT(0, 0, 8, 700, 700, 18), ++ ETSI_PATTERN_SHORT(1, 0, 8, 200, 1000, 10), ++ ETSI_PATTERN_SHORT(2, 0, 16, 200, 1600, 15), ++ ETSI_PATTERN_SHORT(3, 0, 16, 2300, 4000, 25), ++ ETSI_PATTERN_SHORT(4, 20, 34, 2000, 4000, 20), ++ ETSI_PATTERN_INTERLEAVED(5, 0, 8, 300, 400, 2, 3, 10), ++ ETSI_PATTERN_INTERLEAVED(6, 0, 8, 400, 1200, 2, 3, 15), ++}; ++ ++static const struct radar_types etsi_radar_types_v17 = { ++ .region = NL80211_DFS_ETSI, ++ .num_radar_types = ARRAY_SIZE(etsi_radar_ref_types_v17_riu), ++ .spec_riu = etsi_radar_ref_types_v17_riu, ++ .spec_fcu = etsi_radar_ref_types_v17_fcu, ++}; ++ ++#define FCC_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB, TYPE) \ ++ { \ ++ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ ++ PMIN - PRI_TOLERANCE, \ ++ PMAX * PRF + PRI_TOLERANCE, PRF, PPB * PRF, \ ++ PPB_THRESH(PPB), PRI_TOLERANCE, TYPE \ ++ } ++ ++static const struct radar_detector_specs fcc_radar_ref_types_riu[] = { ++ FCC_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(1, 0, 8, 518, 3066, 1, 102, RADAR_WAVEFORM_WEATHER), ++ FCC_PATTERN(2, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(3, 6, 20, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(4, 10, 28, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(5, 50, 110, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ FCC_PATTERN(6, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_detector_specs fcc_radar_ref_types_fcu[] = { ++ FCC_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(1, 0, 8, 518, 3066, 1, 102, RADAR_WAVEFORM_WEATHER), ++ FCC_PATTERN(2, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(3, 6, 12, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(4, 10, 22, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(5, 50, 104, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ FCC_PATTERN(6, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_types fcc_radar_types = { ++ .region = NL80211_DFS_FCC, ++ .num_radar_types = ARRAY_SIZE(fcc_radar_ref_types_riu), ++ .spec_riu = fcc_radar_ref_types_riu, ++ .spec_fcu = fcc_radar_ref_types_fcu, ++}; ++ ++#define JP_PATTERN FCC_PATTERN ++static const struct radar_detector_specs jp_radar_ref_types_riu[] = { ++ JP_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(1, 2, 8, 3846, 3846, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(2, 0, 8, 1388, 1388, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(3, 0, 8, 4000, 4000, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(4, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(5, 6, 20, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(6, 10, 28, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(7, 50, 110, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ JP_PATTERN(8, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_detector_specs jp_radar_ref_types_fcu[] = { ++ JP_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(1, 2, 6, 3846, 3846, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(2, 0, 8, 1388, 1388, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(3, 2, 2, 4000, 4000, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(4, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(5, 6, 12, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(6, 10, 22, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(7, 50, 104, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ JP_PATTERN(8, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_types jp_radar_types = { ++ .region = NL80211_DFS_JP, ++ .num_radar_types = ARRAY_SIZE(jp_radar_ref_types_riu), ++ .spec_riu = jp_radar_ref_types_riu, ++ .spec_fcu = jp_radar_ref_types_fcu, ++}; ++ ++static const struct radar_types *dfs_domains[] = { ++ &etsi_radar_types_v17, ++ &fcc_radar_types, ++ &jp_radar_types, ++}; ++ ++ ++/** ++ * struct pri_sequence - sequence of pulses matching one PRI ++ * @head: list_head ++ * @pri: pulse repetition interval (PRI) in usecs ++ * @dur: duration of sequence in usecs ++ * @count: number of pulses in this sequence ++ * @count_falses: number of not matching pulses in this sequence ++ * @first_ts: time stamp of first pulse in usecs ++ * @last_ts: time stamp of last pulse in usecs ++ * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur) ++ * @ppb_thresh: Number of pulses to validate detection ++ * (need for weather radar whose value depends of pri) ++ */ ++struct pri_sequence { ++ struct list_head head; ++ u32 pri; ++ u32 dur; ++ u32 count; ++ u32 count_falses; ++ u64 first_ts; ++ u64 last_ts; ++ u64 deadline_ts; ++ u8 ppb_thresh; ++}; ++ ++ ++/** ++ * struct pulse_elem - elements in pulse queue ++ * @ts: time stamp in usecs ++ */ ++struct pulse_elem { ++ struct list_head head; ++ u64 ts; ++}; ++ ++/** ++ * struct pri_detector - PRI detector element for a dedicated radar type ++ * @head: ++ * @rs: detector specs for this detector element ++ * @last_ts: last pulse time stamp considered for this element in usecs ++ * @sequences: list_head holding potential pulse sequences ++ * @pulses: list connecting pulse_elem objects ++ * @count: number of pulses in queue ++ * @max_count: maximum number of pulses to be queued ++ * @window_size: window size back from newest pulse time stamp in usecs ++ * @freq: ++ */ ++struct pri_detector { ++ struct list_head head; ++ const struct radar_detector_specs *rs; ++ u64 last_ts; ++ struct list_head sequences; ++ struct list_head pulses; ++ u32 count; ++ u32 max_count; ++ u32 window_size; ++ struct pri_detector_ops *ops; ++ u16 freq; ++}; ++ ++/** ++ * struct pri_detector_ops - PRI detector ops (dependent of waveform type) ++ * @init : Initialize pri_detector structure ++ * @add_pulse : Add a pulse to the pri-detector ++ * @reset_on_pri_overflow : Should the pri_detector be resetted when pri overflow ++ */ ++struct pri_detector_ops { ++ void (*init)(struct pri_detector *pde); ++ struct pri_sequence * (*add_pulse)(struct pri_detector *pde, u16 len, u64 ts, u16 pri); ++ int reset_on_pri_overflow; ++}; ++ ++ ++/****************************************************************************** ++ * PRI (pulse repetition interval) sequence detection ++ *****************************************************************************/ ++/** ++ * Singleton Pulse and Sequence Pools ++ * ++ * Instances of pri_sequence and pulse_elem are kept in singleton pools to ++ * reduce the number of dynamic allocations. They are shared between all ++ * instances and grow up to the peak number of simultaneously used objects. ++ * ++ * Memory is freed after all references to the pools are released. ++ */ ++static u32 singleton_pool_references; ++static LIST_HEAD(pulse_pool); ++static LIST_HEAD(pseq_pool); ++static DEFINE_SPINLOCK(pool_lock); ++ ++static void pool_register_ref(void) ++{ ++ spin_lock_bh(&pool_lock); ++ singleton_pool_references++; ++ spin_unlock_bh(&pool_lock); ++} ++ ++static void pool_deregister_ref(void) ++{ ++ spin_lock_bh(&pool_lock); ++ singleton_pool_references--; ++ if (singleton_pool_references == 0) { ++ /* free singleton pools with no references left */ ++ struct pri_sequence *ps, *ps0; ++ struct pulse_elem *p, *p0; ++ ++ list_for_each_entry_safe(p, p0, &pulse_pool, head) { ++ list_del(&p->head); ++ kfree(p); ++ } ++ list_for_each_entry_safe(ps, ps0, &pseq_pool, head) { ++ list_del(&ps->head); ++ kfree(ps); ++ } ++ } ++ spin_unlock_bh(&pool_lock); ++} ++ ++static void pool_put_pulse_elem(struct pulse_elem *pe) ++{ ++ spin_lock_bh(&pool_lock); ++ list_add(&pe->head, &pulse_pool); ++ spin_unlock_bh(&pool_lock); ++} ++ ++static void pool_put_pseq_elem(struct pri_sequence *pse) ++{ ++ spin_lock_bh(&pool_lock); ++ list_add(&pse->head, &pseq_pool); ++ spin_unlock_bh(&pool_lock); ++} ++ ++static struct pri_sequence *pool_get_pseq_elem(void) ++{ ++ struct pri_sequence *pse = NULL; ++ spin_lock_bh(&pool_lock); ++ if (!list_empty(&pseq_pool)) { ++ pse = list_first_entry(&pseq_pool, struct pri_sequence, head); ++ list_del(&pse->head); ++ } ++ spin_unlock_bh(&pool_lock); ++ ++ if (pse == NULL) { ++ pse = kmalloc(sizeof(*pse), GFP_ATOMIC); ++ } ++ ++ return pse; ++} ++ ++static struct pulse_elem *pool_get_pulse_elem(void) ++{ ++ struct pulse_elem *pe = NULL; ++ spin_lock_bh(&pool_lock); ++ if (!list_empty(&pulse_pool)) { ++ pe = list_first_entry(&pulse_pool, struct pulse_elem, head); ++ list_del(&pe->head); ++ } ++ spin_unlock_bh(&pool_lock); ++ return pe; ++} ++ ++static struct pulse_elem *pulse_queue_get_tail(struct pri_detector *pde) ++{ ++ struct list_head *l = &pde->pulses; ++ if (list_empty(l)) ++ return NULL; ++ return list_entry(l->prev, struct pulse_elem, head); ++} ++ ++static bool pulse_queue_dequeue(struct pri_detector *pde) ++{ ++ struct pulse_elem *p = pulse_queue_get_tail(pde); ++ if (p != NULL) { ++ list_del_init(&p->head); ++ pde->count--; ++ /* give it back to pool */ ++ pool_put_pulse_elem(p); ++ } ++ return (pde->count > 0); ++} ++ ++/** ++ * pulse_queue_check_window - remove pulses older than window ++ * @pde: pointer on pri_detector ++ * ++ * dequeue pulse that are too old. ++ */ ++static ++void pulse_queue_check_window(struct pri_detector *pde) ++{ ++ u64 min_valid_ts; ++ struct pulse_elem *p; ++ ++ /* there is no delta time with less than 2 pulses */ ++ if (pde->count < 2) ++ return; ++ ++ if (pde->last_ts <= pde->window_size) ++ return; ++ ++ min_valid_ts = pde->last_ts - pde->window_size; ++ while ((p = pulse_queue_get_tail(pde)) != NULL) { ++ if (p->ts >= min_valid_ts) ++ return; ++ pulse_queue_dequeue(pde); ++ } ++} ++ ++/** ++ * pulse_queue_enqueue - Queue one pulse ++ * @pde: pointer on pri_detector ++ * ++ * Add one pulse to the list. If the maximum number of pulses ++ * if reached, remove oldest one. ++ */ ++static ++bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts) ++{ ++ struct pulse_elem *p = pool_get_pulse_elem(); ++ if (p == NULL) { ++ p = kmalloc(sizeof(*p), GFP_ATOMIC); ++ if (p == NULL) { ++ return false; ++ } ++ } ++ INIT_LIST_HEAD(&p->head); ++ p->ts = ts; ++ list_add(&p->head, &pde->pulses); ++ pde->count++; ++ pde->last_ts = ts; ++ pulse_queue_check_window(pde); ++ if (pde->count >= pde->max_count) ++ pulse_queue_dequeue(pde); ++ ++ return true; ++} ++ ++ ++/*************************************************************************** ++ * Short waveform ++ **************************************************************************/ ++/** ++ * pde_get_multiple() - get number of multiples considering a given tolerance ++ * @return factor if abs(val - factor*fraction) <= tolerance, 0 otherwise ++ */ ++static ++u32 pde_get_multiple(u32 val, u32 fraction, u32 tolerance) ++{ ++ u32 remainder; ++ u32 factor; ++ u32 delta; ++ ++ if (fraction == 0) ++ return 0; ++ ++ delta = (val < fraction) ? (fraction - val) : (val - fraction); ++ ++ if (delta <= tolerance) ++ /* val and fraction are within tolerance */ ++ return 1; ++ ++ factor = val / fraction; ++ remainder = val % fraction; ++ if (remainder > tolerance) { ++ /* no exact match */ ++ if ((fraction - remainder) <= tolerance) ++ /* remainder is within tolerance */ ++ factor++; ++ else ++ factor = 0; ++ } ++ return factor; ++} ++ ++/** ++ * pde_short_create_sequences - create_sequences function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * @ts: timestamp of the pulse ++ * @min_count: Minimum number of pulse to be present in the sequence. ++ * (With this pulse there is already a sequence with @min_count ++ * pulse, so if we can't create a sequence with more pulse don't ++ * create it) ++ * @return: false if an error occured (memory allocation) true otherwise ++ * ++ * For each pulses queued check if we can create a sequence with ++ * pri = (ts - pulse_queued.ts) which contains more than @min_count pulses. ++ * ++ */ ++static ++bool pde_short_create_sequences(struct pri_detector *pde, ++ u64 ts, u32 min_count) ++{ ++ struct pulse_elem *p; ++ u16 pulse_idx = 0; ++ ++ list_for_each_entry(p, &pde->pulses, head) { ++ struct pri_sequence ps, *new_ps; ++ struct pulse_elem *p2; ++ u32 tmp_false_count; ++ u64 min_valid_ts; ++ u32 delta_ts = ts - p->ts; ++ pulse_idx++; ++ ++ if (delta_ts < pde->rs->pri_min) ++ /* ignore too small pri */ ++ continue; ++ ++ if (delta_ts > pde->rs->pri_max) ++ /* stop on too large pri (sorted list) */ ++ break; ++ ++ /* build a new sequence with new potential pri */ ++ ps.count = 2; ++ ps.count_falses = pulse_idx - 1; ++ ps.first_ts = p->ts; ++ ps.last_ts = ts; ++ ps.pri = ts - p->ts; ++ ps.dur = ps.pri * (pde->rs->ppb - 1) ++ + 2 * pde->rs->max_pri_tolerance; ++ ++ p2 = p; ++ tmp_false_count = 0; ++ if (ps.dur > ts) ++ min_valid_ts = 0; ++ else ++ min_valid_ts = ts - ps.dur; ++ /* check which past pulses are candidates for new sequence */ ++ list_for_each_entry_continue(p2, &pde->pulses, head) { ++ u32 factor; ++ if (p2->ts < min_valid_ts) ++ /* stop on crossing window border */ ++ break; ++ /* check if pulse match (multi)PRI */ ++ factor = pde_get_multiple(ps.last_ts - p2->ts, ps.pri, ++ pde->rs->max_pri_tolerance); ++ if (factor > 0) { ++ ps.count++; ++ ps.first_ts = p2->ts; ++ /* ++ * on match, add the intermediate falses ++ * and reset counter ++ */ ++ ps.count_falses += tmp_false_count; ++ tmp_false_count = 0; ++ } else { ++ /* this is a potential false one */ ++ tmp_false_count++; ++ } ++ } ++ if (ps.count <= min_count) { ++ /* did not reach minimum count, drop sequence */ ++ continue; ++ } ++ /* this is a valid one, add it */ ++ ps.deadline_ts = ps.first_ts + ps.dur; ++ if (pde->rs->type == RADAR_WAVEFORM_WEATHER) { ++ ps.ppb_thresh = 19000000 / (360 * ps.pri); ++ ps.ppb_thresh = PPB_THRESH(ps.ppb_thresh); ++ } else { ++ ps.ppb_thresh = pde->rs->ppb_thresh; ++ } ++ ++ new_ps = pool_get_pseq_elem(); ++ if (new_ps == NULL) { ++ return false; ++ } ++ memcpy(new_ps, &ps, sizeof(ps)); ++ INIT_LIST_HEAD(&new_ps->head); ++ list_add(&new_ps->head, &pde->sequences); ++ } ++ return true; ++} ++ ++/** ++ * pde_short_add_to_existing_seqs - add_to_existing_seqs function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * @ts: timestamp of the pulse ++ * ++ * Check all sequemces created for this pde. ++ * - If the sequence is too old delete it. ++ * - Else if the delta with the previous pulse match the pri of the sequence ++ * add the pulse to this sequence. If the pulse cannot be added it is added ++ * to the false pulses for this sequence ++ * ++ * @return the length of the longest sequence in which the pulse has been added ++ */ ++static ++u32 pde_short_add_to_existing_seqs(struct pri_detector *pde, u64 ts) ++{ ++ u32 max_count = 0; ++ struct pri_sequence *ps, *ps2; ++ list_for_each_entry_safe(ps, ps2, &pde->sequences, head) { ++ u32 delta_ts; ++ u32 factor; ++ ++ /* first ensure that sequence is within window */ ++ if (ts > ps->deadline_ts) { ++ list_del_init(&ps->head); ++ pool_put_pseq_elem(ps); ++ continue; ++ } ++ ++ delta_ts = ts - ps->last_ts; ++ factor = pde_get_multiple(delta_ts, ps->pri, ++ pde->rs->max_pri_tolerance); ++ ++ if (factor > 0) { ++ ps->last_ts = ts; ++ ps->count++; ++ ++ if (max_count < ps->count) ++ max_count = ps->count; ++ } else { ++ ps->count_falses++; ++ } ++ } ++ return max_count; ++} ++ ++ ++/** ++ * pde_short_check_detection - check_detection function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * ++ * Check all sequemces created for this pde. ++ * - If a sequence contains more pulses than the threshold and more matching ++ * that false pulses. ++ * ++ * @return The first complete sequence, and NULL if no sequence is complete. ++ */ ++static ++struct pri_sequence *pde_short_check_detection(struct pri_detector *pde) ++{ ++ struct pri_sequence *ps; ++ ++ if (list_empty(&pde->sequences)) ++ return NULL; ++ ++ list_for_each_entry(ps, &pde->sequences, head) { ++ /* ++ * we assume to have enough matching confidence if we ++ * 1) have enough pulses ++ * 2) have more matching than false pulses ++ */ ++ if ((ps->count >= ps->ppb_thresh) && ++ (ps->count * pde->rs->num_pri > ps->count_falses)) { ++ return ps; ++ } ++ } ++ return NULL; ++} ++ ++/** ++ * pde_short_init - init function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * ++ * Initialize pri_detector window size to the maximun size of one burst ++ * for the radar specification associated. ++ */ ++static ++void pde_short_init(struct pri_detector *pde) ++{ ++ pde->window_size = pde->rs->pri_max * pde->rs->ppb * pde->rs->num_pri; ++ pde->max_count = pde->rs->ppb * 2; ++} ++ ++static void pri_detector_reset(struct pri_detector *pde, u64 ts); ++/** ++ * pde_short_add_pulse - Add pulse to a pri_detector for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * ++ * @pde : pointer on pri_detector ++ * @len : width of the pulse ++ * @ts : timestamp of the pulse received ++ * @pri : Delta in us with the previous pulse. ++ * (0 means that delta in bigger than 65535 us) ++ * ++ * Process on pulse within this pri_detector ++ * - First try to add it to existing sequence ++ * - Then try to create a new and longest sequence ++ * - Check if this pulse complete a sequence ++ * - If not save this pulse in the list ++ */ ++static ++struct pri_sequence *pde_short_add_pulse(struct pri_detector *pde, ++ u16 len, u64 ts, u16 pri) ++{ ++ u32 max_updated_seq; ++ struct pri_sequence *ps; ++ const struct radar_detector_specs *rs = pde->rs; ++ ++ if (pde->count == 0) { ++ /* This is the first pulse after reset, no need to check sequences */ ++ pulse_queue_enqueue(pde, ts); ++ return NULL; ++ } ++ ++ if ((ts - pde->last_ts) < rs->max_pri_tolerance) { ++ /* if delta to last pulse is too short, don't use this pulse */ ++ return NULL; ++ } ++ ++ max_updated_seq = pde_short_add_to_existing_seqs(pde, ts); ++ ++ if (!pde_short_create_sequences(pde, ts, max_updated_seq)) { ++ pri_detector_reset(pde, ts); ++ return NULL; ++ } ++ ++ ps = pde_short_check_detection(pde); ++ ++ if (ps == NULL) ++ pulse_queue_enqueue(pde, ts); ++ ++ return ps; ++} ++ ++ ++ ++/** ++ * pri detector ops to detect short radar waveform ++ * A Short waveform is defined by : ++ * The width of pulses. ++ * The interval between two pulses inside a burst (called pri) ++ * (some waveform may have or 2/3 interleaved pri) ++ * The number of pulses per burst (ppb) ++ */ ++static struct pri_detector_ops pri_detector_short = { ++ .init = pde_short_init, ++ .add_pulse = pde_short_add_pulse, ++ .reset_on_pri_overflow = 1, ++}; ++ ++ ++/*************************************************************************** ++ * Long waveform ++ **************************************************************************/ ++#define LONG_RADAR_DURATION 12000000 ++#define LONG_RADAR_BURST_MIN_DURATION (12000000 / 20) ++#define LONG_RADAR_MAX_BURST 20 ++ ++/** ++ * pde_long_init - init function for LONG radar waveform ++ * @pde: pointer on pri_detector ++ * ++ * Initialize pri_detector window size to the long waveform radar ++ * waveform (ie. 12s) and max_count ++ */ ++static ++void pde_long_init(struct pri_detector *pde) ++{ ++ pde->window_size = LONG_RADAR_DURATION; ++ pde->max_count = LONG_RADAR_MAX_BURST; /* only count burst not pulses */ ++} ++ ++ ++/** ++ * pde_long_add_pulse - Add pulse to a pri_detector for ++ * LONG radar waveform ++ * ++ * @pde : pointer on pri_detector ++ * @len : width of the pulse ++ * @ts : timestamp of the pulse received ++ * @pri : Delta in us with the previous pulse. ++ * ++ * ++ * For long pulse we only handle one sequence. Since each burst ++ * have a different set of parameters (number of pulse, pri) than ++ * the previous one we only use pulse width to add the pulse in the ++ * sequence. ++ * We only queue one pulse per burst and valid the radar when enough burst ++ * has been detected. ++ */ ++static ++struct pri_sequence *pde_long_add_pulse(struct pri_detector *pde, ++ u16 len, u64 ts, u16 pri) ++{ ++ struct pri_sequence *ps; ++ const struct radar_detector_specs *rs = pde->rs; ++ ++ if (list_empty(&pde->sequences)) { ++ /* First pulse, create a new sequence */ ++ ps = pool_get_pseq_elem(); ++ if (ps == NULL) { ++ return NULL; ++ } ++ ++ /*For long waveform, "count" represents the number of burst detected */ ++ ps->count = 1; ++ /*"count_false" represents the number of pulse in the current burst */ ++ ps->count_falses = 1; ++ ps->first_ts = ts; ++ ps->last_ts = ts; ++ ps->deadline_ts = ts + pde->window_size; ++ ps->pri = 0; ++ INIT_LIST_HEAD(&ps->head); ++ list_add(&ps->head, &pde->sequences); ++ pulse_queue_enqueue(pde, ts); ++ } else { ++ u32 delta_ts; ++ ++ ps = (struct pri_sequence *)pde->sequences.next; ++ ++ delta_ts = ts - ps->last_ts; ++ ps->last_ts = ts; ++ ++ if (delta_ts < rs->pri_max) { ++ /* ignore pulse too close from previous one */ ++ } else if ((delta_ts >= rs->pri_min) && ++ (delta_ts <= rs->pri_max)) { ++ /* this is a new pulse in the current burst, ignore it ++ (i.e don't queue it) */ ++ ps->count_falses++; ++ } else if ((ps->count > 2) && ++ (ps->dur + delta_ts) < LONG_RADAR_BURST_MIN_DURATION) { ++ /* not enough time between burst, ignore pulse */ ++ } else { ++ /* a new burst */ ++ ps->count++; ++ ps->count_falses = 1; ++ ++ /* reset the start of the sequence if deadline reached */ ++ if (ts > ps->deadline_ts) { ++ struct pulse_elem *p; ++ u64 min_valid_ts; ++ ++ min_valid_ts = ts - pde->window_size; ++ while ((p = pulse_queue_get_tail(pde)) != NULL) { ++ if (p->ts >= min_valid_ts) { ++ ps->first_ts = p->ts; ++ ps->deadline_ts = p->ts + pde->window_size; ++ break; ++ } ++ pulse_queue_dequeue(pde); ++ ps->count--; ++ } ++ } ++ ++ /* valid radar if enough burst detected and delta with first burst ++ is at least duration/2 */ ++ if (ps->count > pde->rs->ppb_thresh && ++ (ts - ps->first_ts) > (pde->window_size / 2)) { ++ return ps; ++ } else { ++ pulse_queue_enqueue(pde, ts); ++ ps->dur = delta_ts; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++/** ++ * pri detector ops to detect long radar waveform ++ */ ++static struct pri_detector_ops pri_detector_long = { ++ .init = pde_long_init, ++ .add_pulse = pde_long_add_pulse, ++ .reset_on_pri_overflow = 0, ++}; ++ ++ ++/*************************************************************************** ++ * PRI detector init/reset/exit/get ++ **************************************************************************/ ++/** ++ * pri_detector_init- Create a new pri_detector ++ * ++ * @dpd: dfs_pattern_detector instance pointer ++ * @radar_type: index of radar pattern ++ * @freq: Frequency of the pri detector ++ */ ++struct pri_detector *pri_detector_init(struct dfs_pattern_detector *dpd, ++ u16 radar_type, u16 freq) ++{ ++ struct pri_detector *pde; ++ ++ pde = kzalloc(sizeof(*pde), GFP_ATOMIC); ++ if (pde == NULL) ++ return NULL; ++ ++ INIT_LIST_HEAD(&pde->sequences); ++ INIT_LIST_HEAD(&pde->pulses); ++ INIT_LIST_HEAD(&pde->head); ++ list_add(&pde->head, &dpd->detectors[radar_type]); ++ ++ pde->rs = &dpd->radar_spec[radar_type]; ++ pde->freq = freq; ++ ++ if (pde->rs->type == RADAR_WAVEFORM_LONG) { ++ /* for LONG WAVEFORM */ ++ pde->ops = &pri_detector_long; ++ } else { ++ /* for SHORT, WEATHER and INTERLEAVED */ ++ pde->ops = &pri_detector_short; ++ } ++ ++ /* Init dependent of specs */ ++ pde->ops->init(pde); ++ ++ pool_register_ref(); ++ return pde; ++} ++ ++/** ++ * pri_detector_reset - Reset pri_detector ++ * ++ * @pde: pointer on pri_detector ++ * @ts: New ts reference for the pri_detector ++ * ++ * free pulse queue and sequences list and give objects back to pools ++ */ ++static ++void pri_detector_reset(struct pri_detector *pde, u64 ts) ++{ ++ struct pri_sequence *ps, *ps0; ++ struct pulse_elem *p, *p0; ++ list_for_each_entry_safe(ps, ps0, &pde->sequences, head) { ++ list_del_init(&ps->head); ++ pool_put_pseq_elem(ps); ++ } ++ list_for_each_entry_safe(p, p0, &pde->pulses, head) { ++ list_del_init(&p->head); ++ pool_put_pulse_elem(p); ++ } ++ pde->count = 0; ++ pde->last_ts = ts; ++} ++ ++/** ++ * pri_detector_exit - Delete pri_detector ++ * ++ * @pde: pointer on pri_detector ++ */ ++static ++void pri_detector_exit(struct pri_detector *pde) ++{ ++ pri_detector_reset(pde, 0); ++ pool_deregister_ref(); ++ list_del(&pde->head); ++ kfree(pde); ++} ++ ++/** ++ * pri_detector_get() - get pri detector for a given frequency and type ++ * @dpd: dfs_pattern_detector instance pointer ++ * @freq: frequency in MHz ++ * @radar_type: index of radar pattern ++ * @return pointer to pri detector on success, NULL otherwise ++ * ++ * Return existing pri detector for the given frequency or return a ++ * newly create one. ++ * Pri detector are "merged" by frequency so that if a pri detector for a freq ++ * of +/- 2Mhz already exists don't create a new one. ++ * ++ * Maybe will need to adapt frequency merge for pattern with chirp. ++ */ ++static struct pri_detector * ++pri_detector_get(struct dfs_pattern_detector *dpd, u16 freq, u16 radar_type) ++{ ++ struct pri_detector *pde, *cur = NULL; ++ list_for_each_entry(pde, &dpd->detectors[radar_type], head) { ++ if (pde->freq == freq) { ++ if (pde->count) ++ return pde; ++ else ++ cur = pde; ++ } else if (pde->freq - 2 == freq && pde->count) { ++ return pde; ++ } else if (pde->freq + 2 == freq && pde->count) { ++ return pde; ++ } ++ } ++ ++ if (cur) ++ return cur; ++ else ++ return pri_detector_init(dpd, radar_type, freq); ++} ++ ++ ++/****************************************************************************** ++ * DFS Pattern Detector ++ *****************************************************************************/ ++/** ++ * dfs_pattern_detector_reset() - reset all channel detectors ++ * ++ * @dpd: dfs_pattern_detector ++ */ ++static void dfs_pattern_detector_reset(struct dfs_pattern_detector *dpd) ++{ ++ struct pri_detector *pde; ++ int i; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry(pde, &dpd->detectors[i], head) ++ pri_detector_reset(pde, dpd->last_pulse_ts); ++ } ++ ++ dpd->last_pulse_ts = 0; ++ dpd->prev_jiffies = jiffies; ++} ++ ++/** ++ * dfs_pattern_detector_reset() - delete all channel detectors ++ * ++ * @dpd: dfs_pattern_detector ++ */ ++static void dfs_pattern_detector_exit(struct dfs_pattern_detector *dpd) ++{ ++ struct pri_detector *pde, *pde0; ++ int i; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry_safe(pde, pde0, &dpd->detectors[i], head) ++ pri_detector_exit(pde); ++ } ++ ++ kfree(dpd); ++} ++ ++/** ++ * dfs_pattern_detector_pri_overflow - reset all channel detectors on pri ++ * overflow ++ * @dpd: dfs_pattern_detector ++ */ ++static void dfs_pattern_detector_pri_overflow(struct dfs_pattern_detector *dpd) ++{ ++ struct pri_detector *pde; ++ int i; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry(pde, &dpd->detectors[i], head) ++ if (pde->ops->reset_on_pri_overflow) ++ pri_detector_reset(pde, dpd->last_pulse_ts); ++ } ++} ++ ++/** ++ * dfs_pattern_detector_add_pulse - Process one pulse ++ * ++ * @dpd: dfs_pattern_detector ++ * @chain: Chain that correspond to this pattern_detector (only for debug) ++ * @freq: frequency of the pulse ++ * @pri: Delta with previous pulse. (0 if delta is too big for u16) ++ * @len: width of the pulse ++ * @now: jiffies value when pulse was received ++ * ++ * Get (or create) the channel_detector for this frequency. Then add the pulse ++ * in each pri_detector created in this channel_detector. ++ * ++ * ++ * @return True is the pulse complete a radar pattern, false otherwise ++ */ ++static bool dfs_pattern_detector_add_pulse(struct dfs_pattern_detector *dpd, ++ enum rwnx_radar_chain chain, ++ u16 freq, u16 pri, u16 len, u32 now) ++{ ++ u32 i; ++ ++ /* ++ * pulses received for a non-supported or un-initialized ++ * domain are treated as detected radars for fail-safety ++ */ ++ if (dpd->region == NL80211_DFS_UNSET) ++ return true; ++ ++ /* Compute pulse time stamp */ ++ if (pri == 0) { ++ u32 delta_jiffie; ++ if (unlikely(now < dpd->prev_jiffies)) { ++ delta_jiffie = 0xffffffff - dpd->prev_jiffies + now; ++ } else { ++ delta_jiffie = now - dpd->prev_jiffies; ++ } ++ dpd->last_pulse_ts += jiffies_to_usecs(delta_jiffie); ++ dpd->prev_jiffies = now; ++ dfs_pattern_detector_pri_overflow(dpd); ++ } else { ++ dpd->last_pulse_ts += pri; ++ } ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ struct pri_sequence *ps; ++ struct pri_detector *pde; ++ const struct radar_detector_specs *rs = &dpd->radar_spec[i]; ++ ++ /* no need to look up for pde if len is not within range */ ++ if ((rs->width_min > len) || ++ (rs->width_max < len)) { ++ continue; ++ } ++ ++ pde = pri_detector_get(dpd, freq, i); ++ ps = pde->ops->add_pulse(pde, len, dpd->last_pulse_ts, pri); ++ ++ if (ps != NULL) { ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_detected(chain, dpd->region, pde->freq, i, ps->pri); ++#endif ++ // reset everything instead of just the channel detector ++ dfs_pattern_detector_reset(dpd); ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++/** ++ * get_dfs_domain_radar_types() - get radar types for a given DFS domain ++ * @param domain DFS domain ++ * @return radar_types ptr on success, NULL if DFS domain is not supported ++ */ ++static const struct radar_types * ++get_dfs_domain_radar_types(enum nl80211_dfs_regions region) ++{ ++ u32 i; ++ for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) { ++ if (dfs_domains[i]->region == region) ++ return dfs_domains[i]; ++ } ++ return NULL; ++} ++ ++/** ++ * get_dfs_max_radar_types() - get maximum radar types for all supported domain ++ * @return the maximum number of radar pattern supported by on region ++ */ ++static u16 get_dfs_max_radar_types(void) ++{ ++ u32 i; ++ u16 max = 0; ++ for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) { ++ if (dfs_domains[i]->num_radar_types > max) ++ max = dfs_domains[i]->num_radar_types; ++ } ++ return max; ++} ++ ++/** ++ * dfs_pattern_detector_set_domain - set DFS domain ++ * ++ * @dpd: dfs_pattern_detector ++ * @region: DFS region ++ * ++ * set DFS domain, resets detector lines upon domain changes ++ */ ++static ++bool dfs_pattern_detector_set_domain(struct dfs_pattern_detector *dpd, ++ enum nl80211_dfs_regions region, u8 chain) ++{ ++ const struct radar_types *rt; ++ struct pri_detector *pde, *pde0; ++ int i; ++ ++ if (dpd->region == region) ++ return true; ++ ++ dpd->region = NL80211_DFS_UNSET; ++ ++ rt = get_dfs_domain_radar_types(region); ++ if (rt == NULL) ++ return false; ++ ++ /* delete all pri detectors for previous DFS domain */ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry_safe(pde, pde0, &dpd->detectors[i], head) ++ pri_detector_exit(pde); ++ } ++ ++ if (chain == RWNX_RADAR_RIU) ++ dpd->radar_spec = rt->spec_riu; ++ else ++ dpd->radar_spec = rt->spec_fcu; ++ dpd->num_radar_types = rt->num_radar_types; ++ ++ dpd->region = region; ++ ++ AICWFDBG(LOGINFO,"set_region %d \n",region); ++ return true; ++} ++ ++/** ++ * dfs_pattern_detector_init - Initialize dfs_pattern_detector ++ * ++ * @region: DFS region ++ * @return: pointer on dfs_pattern_detector ++ * ++ */ ++static struct dfs_pattern_detector * ++dfs_pattern_detector_init(enum nl80211_dfs_regions region, u8 chain) ++{ ++ struct dfs_pattern_detector *dpd; ++ u16 i, max_radar_type = get_dfs_max_radar_types(); ++ ++ dpd = kmalloc(sizeof(*dpd) + max_radar_type * sizeof(dpd->detectors[0]), ++ GFP_KERNEL); ++ if (dpd == NULL) ++ return NULL; ++ ++ dpd->region = NL80211_DFS_UNSET; ++ dpd->enabled = RWNX_RADAR_DETECT_DISABLE; ++ dpd->last_pulse_ts = 0; ++ dpd->prev_jiffies = jiffies; ++ dpd->num_radar_types = 0; ++ for (i = 0; i < max_radar_type; i++) ++ INIT_LIST_HEAD(&dpd->detectors[i]); ++ ++ if (dfs_pattern_detector_set_domain(dpd, region, chain)) ++ return dpd; ++ ++ kfree(dpd); ++ return NULL; ++} ++ ++ ++/****************************************************************************** ++ * driver interface ++ *****************************************************************************/ ++static u16 rwnx_radar_get_center_freq(struct rwnx_hw *rwnx_hw, u8 chain) ++{ ++ if (chain == RWNX_RADAR_FCU) ++ return rwnx_hw->phy.sec_chan.center_freq1; ++ ++ if (chain == RWNX_RADAR_RIU) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) { ++ WARN(1, "Radar pulse without channel information"); ++ } else ++ return rwnx_hw->chanctx_table[rwnx_hw->cur_chanctx].chan_def.center_freq1; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } ++ ++ return 0; ++} ++ ++static void rwnx_radar_detected(struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct cfg80211_chan_def chan_def; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) { ++ WARN(1, "Radar detected without channel information"); ++ return; ++ } ++ ++ /* ++ recopy chan_def in local variable because rwnx_radar_cancel_cac may ++ clean the variable (if in CAC and it's the only vif using this context) ++ and CAC should be aborted before reporting the radar. ++ */ ++ chan_def = rwnx_hw->chanctx_table[rwnx_hw->cur_chanctx].chan_def; ++ ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ cfg80211_radar_event(rwnx_hw->wiphy, &chan_def, GFP_KERNEL); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++static void rwnx_radar_process_pulse(struct work_struct *ws) ++{ ++ struct rwnx_radar *radar = container_of(ws, struct rwnx_radar, ++ detection_work); ++ struct rwnx_hw *rwnx_hw = container_of(radar, struct rwnx_hw, radar); ++ int chain; ++ u32 pulses[RWNX_RADAR_LAST][RWNX_RADAR_PULSE_MAX]; ++ u16 pulses_count[RWNX_RADAR_LAST]; ++ u32 now = jiffies; /* would be better to store jiffies value in IT handler */ ++ ++ /* recopy pulses locally to avoid too long spin_lock */ ++ spin_lock_bh(&radar->lock); ++ for (chain = RWNX_RADAR_RIU; chain < RWNX_RADAR_LAST; chain++) { ++ int start, count; ++ ++ count = radar->pulses[chain].count; ++ start = radar->pulses[chain].index - count; ++ if (start < 0) ++ start += RWNX_RADAR_PULSE_MAX; ++ ++ pulses_count[chain] = count; ++ if (count == 0) ++ continue; ++ ++ if ((start + count) > RWNX_RADAR_PULSE_MAX) { ++ u16 count1 = (RWNX_RADAR_PULSE_MAX - start); ++ memcpy(&(pulses[chain][0]), ++ &(radar->pulses[chain].buffer[start]), ++ count1 * sizeof(struct radar_pulse)); ++ memcpy(&(pulses[chain][count1]), ++ &(radar->pulses[chain].buffer[0]), ++ (count - count1) * sizeof(struct radar_pulse)); ++ } else { ++ memcpy(&(pulses[chain][0]), ++ &(radar->pulses[chain].buffer[start]), ++ count * sizeof(struct radar_pulse)); ++ } ++ radar->pulses[chain].count = 0; ++ } ++ spin_unlock_bh(&radar->lock); ++ ++ ++ /* now process pulses */ ++ for (chain = RWNX_RADAR_RIU; chain < RWNX_RADAR_LAST; chain++) { ++ int i; ++ u16 freq; ++ ++ if (pulses_count[chain] == 0) ++ continue; ++ ++ freq = rwnx_radar_get_center_freq(rwnx_hw, chain); ++ ++ for (i = 0; i < pulses_count[chain] ; i++) { ++ struct radar_pulse *p = (struct radar_pulse *)&pulses[chain][i]; ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_pulse(chain, p); ++#endif ++ if (dfs_pattern_detector_add_pulse(radar->dpd[chain], chain, ++ (s16)freq + (2 * p->freq), ++ p->rep, (p->len * 2), now)) { ++ ++ u16 idx = radar->detected[chain].index; ++ ++ if (chain == RWNX_RADAR_RIU) { ++ /* operating chain, inform upper layer to change channel */ ++ if (radar->dpd[chain]->enabled == RWNX_RADAR_DETECT_REPORT) { ++ rwnx_radar_detected(rwnx_hw); ++ /* no need to report new radar until upper layer set a ++ new channel. This prevent warning if a new radar is ++ detected while mac80211 is changing channel */ ++ rwnx_radar_detection_enable(radar, ++ RWNX_RADAR_DETECT_DISABLE, ++ chain); ++ /* purge any event received since the beginning of the ++ function (we are sure not to interfer with tasklet ++ as we disable detection just before) */ ++ radar->pulses[chain].count = 0; ++ } ++ } else { ++ /* secondary radar detection chain, simply report info in ++ debugfs for now */ ++ } ++ ++ radar->detected[chain].freq[idx] = (s16)freq + (2 * p->freq); ++ radar->detected[chain].time[idx] = ktime_get_real_seconds(); ++ radar->detected[chain].index = ((idx + 1) % ++ NX_NB_RADAR_DETECTED); ++ radar->detected[chain].count++; ++ /* no need to process next pulses for this chain */ ++ break; ++ } ++ } ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static void rwnx_radar_cac_work(struct work_struct *ws) ++{ ++ struct delayed_work *dw = container_of(ws, struct delayed_work, work); ++ struct rwnx_radar *radar = container_of(dw, struct rwnx_radar, cac_work); ++ struct rwnx_hw *rwnx_hw = container_of(radar, struct rwnx_hw, radar); ++ struct rwnx_chanctx *ctxt; ++ ++ if (radar->cac_vif == NULL) { ++ WARN(1, "CAC finished but no vif set"); ++ return; ++ } ++ ++ ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index]; ++ cfg80211_cac_event(radar->cac_vif->ndev, ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ &ctxt->chan_def, ++ #endif ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) ++ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0); ++ #else ++ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); ++ #endif ++ rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif); ++ rwnx_chanctx_unlink(radar->cac_vif); ++ ++ radar->cac_vif = NULL; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++bool rwnx_radar_detection_init(struct rwnx_radar *radar) ++{ ++ spin_lock_init(&radar->lock); ++ ++ radar->dpd[RWNX_RADAR_RIU] = dfs_pattern_detector_init(NL80211_DFS_UNSET, ++ RWNX_RADAR_RIU); ++ if (radar->dpd[RWNX_RADAR_RIU] == NULL) ++ return false; ++ ++ radar->dpd[RWNX_RADAR_FCU] = dfs_pattern_detector_init(NL80211_DFS_UNSET, ++ RWNX_RADAR_FCU); ++ if (radar->dpd[RWNX_RADAR_FCU] == NULL) { ++ rwnx_radar_detection_deinit(radar); ++ return false; ++ } ++ ++ INIT_WORK(&radar->detection_work, rwnx_radar_process_pulse); ++#ifdef CONFIG_RWNX_FULLMAC ++ INIT_DELAYED_WORK(&radar->cac_work, rwnx_radar_cac_work); ++ radar->cac_vif = NULL; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ return true; ++} ++ ++void rwnx_radar_detection_deinit(struct rwnx_radar *radar) ++{ ++ if (radar->dpd[RWNX_RADAR_RIU]) { ++ dfs_pattern_detector_exit(radar->dpd[RWNX_RADAR_RIU]); ++ radar->dpd[RWNX_RADAR_RIU] = NULL; ++ } ++ if (radar->dpd[RWNX_RADAR_FCU]) { ++ dfs_pattern_detector_exit(radar->dpd[RWNX_RADAR_FCU]); ++ radar->dpd[RWNX_RADAR_FCU] = NULL; ++ } ++} ++ ++bool rwnx_radar_set_domain(struct rwnx_radar *radar, ++ enum nl80211_dfs_regions region) ++{ ++ if (radar->dpd[0] == NULL) ++ return false; ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_set_region(region); ++#endif ++ return (dfs_pattern_detector_set_domain(radar->dpd[RWNX_RADAR_RIU], ++ region, RWNX_RADAR_RIU) && ++ dfs_pattern_detector_set_domain(radar->dpd[RWNX_RADAR_FCU], ++ region, RWNX_RADAR_FCU)); ++} ++ ++void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain) ++{ ++ if (chain < RWNX_RADAR_LAST) { ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_enable_detection(radar->dpd[chain]->region, enable, chain); ++#endif ++ spin_lock_bh(&radar->lock); ++ radar->dpd[chain]->enabled = enable; ++ spin_unlock_bh(&radar->lock); ++ } ++} ++ ++bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, u8 chain) ++{ ++ return radar->dpd[chain]->enabled != RWNX_RADAR_DETECT_DISABLE; ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_radar_start_cac(struct rwnx_radar *radar, u32 cac_time_ms, ++ struct rwnx_vif *vif) ++{ ++ WARN(radar->cac_vif != NULL, "CAC already in progress"); ++ radar->cac_vif = vif; ++ schedule_delayed_work(&radar->cac_work, msecs_to_jiffies(cac_time_ms)); ++} ++ ++void rwnx_radar_cancel_cac(struct rwnx_radar *radar) ++{ ++ struct rwnx_hw *rwnx_hw = container_of(radar, struct rwnx_hw, radar); ++ ++ if (radar->cac_vif == NULL) { ++ return; ++ } ++ ++ if (cancel_delayed_work(&radar->cac_work)) { ++ struct rwnx_chanctx *ctxt; ++ ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index]; ++ rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif); ++ cfg80211_cac_event(radar->cac_vif->ndev, ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ &ctxt->chan_def, ++ #endif ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) ++ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0); ++ #else ++ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); ++ #endif ++ rwnx_chanctx_unlink(radar->cac_vif); ++ } ++ ++ radar->cac_vif = NULL; ++} ++ ++void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_chanctx *ctxt; ++ ++ /* If no information on current channel do nothing */ ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) ++ return; ++ ++ ctxt = &rwnx_hw->chanctx_table[rwnx_hw->cur_chanctx]; ++ if (ctxt->chan_def.chan->flags & IEEE80211_CHAN_RADAR) { ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_REPORT, ++ RWNX_RADAR_RIU); ++ } else { ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_DISABLE, ++ RWNX_RADAR_RIU); ++ } ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/***************************************************************************** ++ * Debug functions ++ *****************************************************************************/ ++static ++int rwnx_radar_dump_pri_detector(char *buf, size_t len, ++ struct pri_detector *pde) ++{ ++ char freq_info[] = "Freq = %3.dMhz\n"; ++ char seq_info[] = " pri | count | false \n"; ++ struct pri_sequence *seq; ++ int res, write = 0; ++ ++ if (list_empty(&pde->sequences)) { ++ return 0; ++ } ++ ++ if (buf == NULL) { ++ int nb_seq = 1; ++ list_for_each_entry(seq, &pde->sequences, head) { ++ nb_seq++; ++ } ++ ++ return (sizeof(freq_info) + nb_seq * sizeof(seq_info)); ++ } ++ ++ res = scnprintf(buf, len, freq_info, pde->freq); ++ write += res; ++ len -= res; ++ ++ res = scnprintf(&buf[write], len, "%s", seq_info); ++ write += res; ++ len -= res; ++ ++ list_for_each_entry(seq, &pde->sequences, head) { ++ res = scnprintf(&buf[write], len, " %6.d | %2.d | %.2d \n", ++ seq->pri, seq->count, seq->count_falses); ++ write += res; ++ len -= res; ++ } ++ ++ return write; ++} ++ ++int rwnx_radar_dump_pattern_detector(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain) ++{ ++ struct dfs_pattern_detector *dpd = radar->dpd[chain]; ++ char info[] = "Type = %3.d\n"; ++ struct pri_detector *pde; ++ int i, res, write = 0; ++ ++ /* if buf is NULL return size needed for dump */ ++ if (buf == NULL) { ++ int size_needed = 0; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ list_for_each_entry(pde, &dpd->detectors[i], head) { ++ size_needed += rwnx_radar_dump_pri_detector(NULL, 0, pde); ++ } ++ size_needed += sizeof(info); ++ ++ return size_needed; ++ } ++ } ++ ++ /* */ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ res = scnprintf(&buf[write], len, info, i); ++ ++ write += res; ++ len -= res; ++ list_for_each_entry(pde, &dpd->detectors[i], head) { ++ res = rwnx_radar_dump_pri_detector(&buf[write], len, pde); ++ write += res; ++ len -= res; ++ } ++ } ++ ++ return write; ++} ++ ++ ++int rwnx_radar_dump_radar_detected(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain) ++{ ++ struct rwnx_radar_detected *detect = &(radar->detected[chain]); ++ char info[] = "2001/02/02 - 02:20 5126MHz\n"; ++ int idx, i, res, write = 0; ++ int count = detect->count; ++ ++ if (count > NX_NB_RADAR_DETECTED) ++ count = NX_NB_RADAR_DETECTED; ++ ++ if (buf == NULL) { ++ return (count * sizeof(info)) + 1; ++ } ++ ++ idx = (detect->index - detect->count) % NX_NB_RADAR_DETECTED; ++ ++ for (i = 0; i < count; i++) { ++ struct tm tm; ++ time64_to_tm(detect->time[idx], 0, &tm); ++ ++ res = scnprintf(&buf[write], len, ++ "%.4d/%.2d/%.2d - %.2d:%.2d %4.4dMHz\n", ++ (int)tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, ++ tm.tm_hour, tm.tm_min, detect->freq[idx]); ++ write += res; ++ len -= res; ++ ++ idx = (idx + 1) % NX_NB_RADAR_DETECTED; ++ } ++ ++ return write; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h +new file mode 100644 +index 000000000000..8bc36f527f62 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h +@@ -0,0 +1,160 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_radar.h ++ * ++ * @brief Functions to handle radar detection ++ * ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_RADAR_H_ ++#define _RWNX_RADAR_H_ ++ ++#include ++ ++struct rwnx_vif; ++struct rwnx_hw; ++ ++enum rwnx_radar_chain { ++ RWNX_RADAR_RIU = 0, ++ RWNX_RADAR_FCU, ++ RWNX_RADAR_LAST ++}; ++ ++enum rwnx_radar_detector { ++ RWNX_RADAR_DETECT_DISABLE = 0, /* Ignore radar pulses */ ++ RWNX_RADAR_DETECT_ENABLE = 1, /* Process pattern detection but do not ++ report radar to upper layer (for test) */ ++ RWNX_RADAR_DETECT_REPORT = 2 /* Process pattern detection and report ++ radar to upper layer. */ ++}; ++ ++#ifdef CONFIG_RWNX_RADAR ++#include ++#include ++ ++#define RWNX_RADAR_PULSE_MAX 32 ++ ++/** ++ * struct rwnx_radar_pulses - List of pulses reported by HW ++ * @index: write index ++ * @count: number of valid pulses ++ * @buffer: buffer of pulses ++ */ ++struct rwnx_radar_pulses { ++ /* Last radar pulses received */ ++ int index; ++ int count; ++ u32 buffer[RWNX_RADAR_PULSE_MAX]; ++}; ++ ++/** ++ * struct dfs_pattern_detector - DFS pattern detector ++ * @region: active DFS region, NL80211_DFS_UNSET until set ++ * @num_radar_types: number of different radar types ++ * @last_pulse_ts: time stamp of last valid pulse in usecs ++ * @prev_jiffies: ++ * @radar_detector_specs: array of radar detection specs ++ * @channel_detectors: list connecting channel_detector elements ++ */ ++struct dfs_pattern_detector { ++ u8 enabled; ++ enum nl80211_dfs_regions region; ++ u8 num_radar_types; ++ u64 last_pulse_ts; ++ u32 prev_jiffies; ++ const struct radar_detector_specs *radar_spec; ++ struct list_head detectors[]; ++}; ++ ++#define NX_NB_RADAR_DETECTED 4 ++ ++/** ++ * struct rwnx_radar_detected - List of radar detected ++ */ ++struct rwnx_radar_detected { ++ u16 index; ++ u16 count; ++ s64 time[NX_NB_RADAR_DETECTED]; ++ s16 freq[NX_NB_RADAR_DETECTED]; ++}; ++ ++ ++struct rwnx_radar { ++ struct rwnx_radar_pulses pulses[RWNX_RADAR_LAST]; ++ struct dfs_pattern_detector *dpd[RWNX_RADAR_LAST]; ++ struct rwnx_radar_detected detected[RWNX_RADAR_LAST]; ++ struct work_struct detection_work; /* Work used to process radar pulses */ ++ spinlock_t lock; /* lock for pulses processing */ ++ ++ /* In softmac cac is handled by mac80211 */ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct delayed_work cac_work; /* Work used to handle CAC */ ++ struct rwnx_vif *cac_vif; /* vif on which we started CAC */ ++#endif ++}; ++ ++bool rwnx_radar_detection_init(struct rwnx_radar *radar); ++void rwnx_radar_detection_deinit(struct rwnx_radar *radar); ++bool rwnx_radar_set_domain(struct rwnx_radar *radar, ++ enum nl80211_dfs_regions region); ++void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain); ++bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, u8 chain); ++void rwnx_radar_start_cac(struct rwnx_radar *radar, u32 cac_time_ms, ++ struct rwnx_vif *vif); ++void rwnx_radar_cancel_cac(struct rwnx_radar *radar); ++void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw); ++int rwnx_radar_dump_pattern_detector(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain); ++int rwnx_radar_dump_radar_detected(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain); ++ ++#else ++ ++struct rwnx_radar { ++}; ++ ++static inline bool rwnx_radar_detection_init(struct rwnx_radar *radar) ++{return true; } ++ ++static inline void rwnx_radar_detection_deinit(struct rwnx_radar *radar) ++{} ++ ++static inline bool rwnx_radar_set_domain(struct rwnx_radar *radar, ++ enum nl80211_dfs_regions region) ++{return true; } ++ ++static inline void rwnx_radar_detection_enable(struct rwnx_radar *radar, ++ u8 enable, u8 chain) ++{} ++ ++static inline bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, ++ u8 chain) ++{return false; } ++ ++static inline void rwnx_radar_start_cac(struct rwnx_radar *radar, ++ u32 cac_time_ms, struct rwnx_vif *vif) ++{} ++ ++static inline void rwnx_radar_cancel_cac(struct rwnx_radar *radar) ++{} ++ ++static inline void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw) ++{} ++ ++static inline int rwnx_radar_dump_pattern_detector(char *buf, size_t len, ++ struct rwnx_radar *radar, ++ u8 chain) ++{return 0; } ++ ++static inline int rwnx_radar_dump_radar_detected(char *buf, size_t len, ++ struct rwnx_radar *radar, ++ u8 chain) ++{return 0; } ++ ++#endif /* CONFIG_RWNX_RADAR */ ++ ++#endif // _RWNX_RADAR_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c +new file mode 100644 +index 000000000000..148dca51c1df +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c +@@ -0,0 +1,2531 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_rx.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_rx.h" ++#include "rwnx_tx.h" ++#include "rwnx_prof.h" ++#include "ipc_host.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "aicwf_txrxif.h" ++#ifdef AICWF_ARP_OFFLOAD ++#include ++#include ++#include "rwnx_msg_tx.h" ++#endif ++ ++#ifndef IEEE80211_MAX_CHAINS ++#define IEEE80211_MAX_CHAINS 4 ++#endif ++ ++u8 dhcped; // = 0; ++ ++u16 tx_legrates_lut_rate[] = { ++ 10, ++ 20, ++ 55, ++ 110, ++ 60, ++ 90, ++ 120, ++ 180, ++ 240, ++ 360, ++ 480, ++ 540 ++}; ++ ++struct rwnx_legrate legrates_lut[] = { ++ [0] = { .idx = 0, .rate = 10}, ++ [1] = { .idx = 1, .rate = 20}, ++ [2] = { .idx = 2, .rate = 55}, ++ [3] = { .idx = 3, .rate = 110}, ++ [4] = { .idx = -1, .rate = 0}, ++ [5] = { .idx = -1, .rate = 0}, ++ [6] = { .idx = -1, .rate = 0}, ++ [7] = { .idx = -1, .rate = 0}, ++ [8] = { .idx = 10, .rate = 480}, ++ [9] = { .idx = 8, .rate = 240}, ++ [10] = { .idx = 6, .rate = 120}, ++ [11] = { .idx = 4, .rate = 60}, ++ [12] = { .idx = 11, .rate = 540}, ++ [13] = { .idx = 9, .rate = 360}, ++ [14] = { .idx = 7, .rate = 180}, ++ [15] = { .idx = 5, .rate = 90}, ++}; ++ ++struct vendor_radiotap_hdr { ++ u8 oui[3]; ++ u8 subns; ++ u16 len; ++ u8 data[]; ++}; ++ ++/** ++ * rwnx_rx_get_vif - Return pointer to the destination vif ++ * ++ * @rwnx_hw: main driver data ++ * @vif_idx: vif index present in rx descriptor ++ * ++ * Select the vif that should receive this frame. Returns NULL if the destination ++ * vif is not active or vif is not specified in the descriptor. ++ */ ++static inline ++struct rwnx_vif *rwnx_rx_get_vif(struct rwnx_hw *rwnx_hw, int vif_idx) ++{ ++ struct rwnx_vif *rwnx_vif = NULL; ++ ++ if (vif_idx < NX_VIRT_DEV_MAX) { ++ rwnx_vif = rwnx_hw->vif_table[vif_idx]; ++ ++ if(!rwnx_vif){ ++ AICWFDBG(LOGERROR, "%s rwnx_hw->vif_table[%d] NULL\r\n", __func__, vif_idx); ++ return NULL; ++ }else if(!rwnx_vif->up){ ++ AICWFDBG(LOGERROR, "%s rwnx_hw->vif_table[%d] is down\r\n", __func__, vif_idx); ++ return NULL; ++ } ++ } ++ ++ return rwnx_vif; ++} ++ ++/** ++ * rwnx_rx_vector_convert - Convert a legacy RX vector into a new RX vector format ++ * ++ * @rwnx_hw: main driver data. ++ * @rx_vect1: Rx vector 1 descriptor of the received frame. ++ * @rx_vect2: Rx vector 2 descriptor of the received frame. ++ */ ++static void rwnx_rx_vector_convert(struct rwnx_hw *rwnx_hw, ++ struct rx_vector_1 *rx_vect1, ++ struct rx_vector_2 *rx_vect2) ++{ ++ struct rx_vector_1_old rx_vect1_leg; ++ struct rx_vector_2_old rx_vect2_leg; ++ u32_l phy_vers = rwnx_hw->version_cfm.version_phy_2; ++ ++ // Check if we need to do the conversion. Only if old modem is used ++ if (__MDM_MAJOR_VERSION(phy_vers) > 0) { ++ rx_vect1->rssi1 = rx_vect1->rssi_leg; ++ return; ++ } ++ ++ // Copy the received vector locally ++ memcpy(&rx_vect1_leg, rx_vect1, sizeof(struct rx_vector_1_old)); ++ ++ // Reset it ++ memset(rx_vect1, 0, sizeof(struct rx_vector_1)); ++ ++ // Perform the conversion ++ rx_vect1->format_mod = rx_vect1_leg.format_mod; ++ rx_vect1->ch_bw = rx_vect1_leg.ch_bw; ++ rx_vect1->antenna_set = rx_vect1_leg.antenna_set; ++ rx_vect1->leg_length = rx_vect1_leg.leg_length; ++ rx_vect1->leg_rate = rx_vect1_leg.leg_rate; ++ rx_vect1->rssi1 = rx_vect1_leg.rssi1; ++ ++ switch (rx_vect1->format_mod) { ++ case FORMATMOD_NON_HT: ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ rx_vect1->leg.lsig_valid = rx_vect1_leg.lsig_valid; ++ rx_vect1->leg.chn_bw_in_non_ht = rx_vect1_leg.num_extn_ss; ++ rx_vect1->leg.dyn_bw_in_non_ht = rx_vect1_leg.dyn_bw; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ rx_vect1->ht.aggregation = rx_vect1_leg.aggregation; ++ rx_vect1->ht.fec = rx_vect1_leg.fec_coding; ++ rx_vect1->ht.lsig_valid = rx_vect1_leg.lsig_valid; ++ rx_vect1->ht.length = rx_vect1_leg.ht_length; ++ rx_vect1->ht.mcs = rx_vect1_leg.mcs; ++ rx_vect1->ht.num_extn_ss = rx_vect1_leg.num_extn_ss; ++ rx_vect1->ht.short_gi = rx_vect1_leg.short_gi; ++ rx_vect1->ht.smoothing = rx_vect1_leg.smoothing; ++ rx_vect1->ht.sounding = rx_vect1_leg.sounding; ++ rx_vect1->ht.stbc = rx_vect1_leg.stbc; ++ break; ++ case FORMATMOD_VHT: ++ rx_vect1->vht.beamformed = !rx_vect1_leg.smoothing; ++ rx_vect1->vht.fec = rx_vect1_leg.fec_coding; ++ rx_vect1->vht.length = rx_vect1_leg.ht_length | rx_vect1_leg._ht_length << 8; ++ rx_vect1->vht.mcs = rx_vect1_leg.mcs & 0x0F; ++ rx_vect1->vht.nss = rx_vect1_leg.stbc ? rx_vect1_leg.n_sts/2 : rx_vect1_leg.n_sts; ++ rx_vect1->vht.doze_not_allowed = rx_vect1_leg.doze_not_allowed; ++ rx_vect1->vht.short_gi = rx_vect1_leg.short_gi; ++ rx_vect1->vht.sounding = rx_vect1_leg.sounding; ++ rx_vect1->vht.stbc = rx_vect1_leg.stbc; ++ rx_vect1->vht.group_id = rx_vect1_leg.group_id; ++ rx_vect1->vht.partial_aid = rx_vect1_leg.partial_aid; ++ rx_vect1->vht.first_user = rx_vect1_leg.first_user; ++ break; ++ } ++ ++ if (!rx_vect2) ++ return; ++ ++ // Copy the received vector 2 locally ++ memcpy(&rx_vect2_leg, rx_vect2, sizeof(struct rx_vector_2_old)); ++ ++ // Reset it ++ memset(rx_vect2, 0, sizeof(struct rx_vector_2)); ++ ++ rx_vect2->rcpi1 = rx_vect2_leg.rcpi; ++ rx_vect2->rcpi2 = rx_vect2_leg.rcpi; ++ rx_vect2->rcpi3 = rx_vect2_leg.rcpi; ++ rx_vect2->rcpi4 = rx_vect2_leg.rcpi; ++ ++ rx_vect2->evm1 = rx_vect2_leg.evm1; ++ rx_vect2->evm2 = rx_vect2_leg.evm2; ++ rx_vect2->evm3 = rx_vect2_leg.evm3; ++ rx_vect2->evm4 = rx_vect2_leg.evm4; ++} ++ ++/** ++ * rwnx_rx_statistic - save some statistics about received frames ++ * ++ * @rwnx_hw: main driver data. ++ * @hw_rxhdr: Rx Hardware descriptor of the received frame. ++ * @sta: STA that sent the frame. ++ */ ++static void rwnx_rx_statistic(struct rwnx_hw *rwnx_hw, struct hw_rxhdr *hw_rxhdr, ++ struct rwnx_sta *sta) ++{ ++#if 1//def CONFIG_RWNX_DEBUGFS ++ struct rwnx_stats *stats = &rwnx_hw->stats; ++ struct rwnx_rx_rate_stats *rate_stats = &sta->stats.rx_rate; ++ struct rx_vector_1 *rxvect = &hw_rxhdr->hwvect.rx_vect1; ++ int mpdu, ampdu, mpdu_prev, rate_idx; ++ ++ /* save complete hwvect */ ++ sta->stats.last_rx = hw_rxhdr->hwvect; ++ ++ /* update ampdu rx stats */ ++ mpdu = hw_rxhdr->hwvect.mpdu_cnt; ++ ampdu = hw_rxhdr->hwvect.ampdu_cnt; ++ mpdu_prev = stats->ampdus_rx_map[ampdu]; ++ ++ if (mpdu_prev < mpdu) { ++ stats->ampdus_rx_miss += mpdu - mpdu_prev - 1; ++ } else { ++ stats->ampdus_rx[mpdu_prev]++; ++ } ++ stats->ampdus_rx_map[ampdu] = mpdu; ++ ++ /* update rx rate statistic */ ++ if (!rate_stats->size) ++ return; ++ ++ if (rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) { ++ int mcs; ++ int bw = rxvect->ch_bw; ++ int sgi; ++ int nss; ++ switch (rxvect->format_mod) { ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ mcs = rxvect->ht.mcs % 8; ++ nss = rxvect->ht.mcs / 8; ++ sgi = rxvect->ht.short_gi; ++ rate_idx = N_CCK + N_OFDM + nss * 32 + mcs * 4 + bw * 2 + sgi; ++ break; ++ case FORMATMOD_VHT: ++ mcs = rxvect->vht.mcs; ++ nss = rxvect->vht.nss; ++ sgi = rxvect->vht.short_gi; ++ rate_idx = N_CCK + N_OFDM + N_HT + nss * 80 + mcs * 8 + bw * 2 + sgi; ++ break; ++ case FORMATMOD_HE_SU: ++ mcs = rxvect->he.mcs; ++ nss = rxvect->he.nss; ++ sgi = rxvect->he.gi_type; ++ rate_idx = N_CCK + N_OFDM + N_HT + N_VHT + nss * 144 + mcs * 12 + bw * 3 + sgi; ++ break; ++ default: ++ mcs = rxvect->he.mcs; ++ nss = rxvect->he.nss; ++ sgi = rxvect->he.gi_type; ++ rate_idx = N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU ++ + nss * 216 + mcs * 18 + rxvect->he.ru_size * 3 + sgi; ++ break; ++ } ++ } else { ++ int idx = legrates_lut[rxvect->leg_rate].idx; ++ if (idx < 4) { ++ rate_idx = idx * 2 + rxvect->pre_type; ++ } else { ++ rate_idx = N_CCK + idx - 4; ++ } ++ } ++ if (rate_idx < rate_stats->size) { ++ if (!rate_stats->table[rate_idx]) ++ rate_stats->rate_cnt++; ++ rate_stats->table[rate_idx]++; ++ rate_stats->cpt++; ++ } else { ++ wiphy_err(rwnx_hw->wiphy, "RX: Invalid index conversion => %d/%d\n", ++ rate_idx, rate_stats->size); ++ } ++#endif ++} ++ ++/** ++ * rwnx_rx_data_skb - Process one data frame ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: vif that received the buffer ++ * @skb: skb received ++ * @rxhdr: HW rx descriptor ++ * @return: true if buffer has been forwarded to upper layer ++ * ++ * If buffer is amsdu , it is first split into a list of skb. ++ * Then each skb may be: ++ * - forwarded to upper layer ++ * - resent on wireless interface ++ * ++ * When vif is a STA interface, every skb is only forwarded to upper layer. ++ * When vif is an AP interface, multicast skb are forwarded and resent, whereas ++ * skb for other BSS's STA are only resent. ++ */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#define RAISE_RX_SOFTIRQ() \ ++ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) ++#endif /* LINUX_VERSION_CODE */ ++ ++void rwnx_rx_data_skb_resend(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *rxhdr) ++{ ++ struct sk_buff *rx_skb = skb; ++ const struct ethhdr *eth; ++ struct sk_buff *skb_copy; ++ ++ rx_skb->dev = rwnx_vif->ndev; ++ skb_reset_mac_header(rx_skb); ++ eth = eth_hdr(rx_skb); ++ ++ //printk("resend\n"); ++ /* resend pkt on wireless interface */ ++ /* always need to copy buffer when forward=0 to get enough headrom for tsdesc */ ++ skb_copy = skb_copy_expand(rx_skb, sizeof(struct rwnx_txhdr) + ++ RWNX_SWTXHDR_ALIGN_SZ + 3 + 24 + 8, 0, GFP_ATOMIC); ++ ++ if (skb_copy) { ++ int res; ++ skb_copy->protocol = htons(ETH_P_802_3); ++ skb_reset_network_header(skb_copy); ++ skb_reset_mac_header(skb_copy); ++ ++ rwnx_vif->is_resending = true; ++ res = dev_queue_xmit(skb_copy); ++ rwnx_vif->is_resending = false; ++ /* note: buffer is always consummed by dev_queue_xmit */ ++ if (res == NET_XMIT_DROP) { ++ rwnx_vif->net_stats.rx_dropped++; ++ rwnx_vif->net_stats.tx_dropped++; ++ } else if (res != NET_XMIT_SUCCESS) { ++ netdev_err(rwnx_vif->ndev, ++ "Failed to re-send buffer to driver (res=%d)", ++ res); ++ rwnx_vif->net_stats.tx_errors++; ++ } ++ } else { ++ netdev_err(rwnx_vif->ndev, "Failed to copy skb"); ++ } ++} ++ ++static void rwnx_rx_data_skb_forward(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *rxhdr) ++{ ++ struct sk_buff *rx_skb; ++ ++ rx_skb = skb; ++ rx_skb->dev = rwnx_vif->ndev; ++ skb_reset_mac_header(rx_skb); ++ ++ #ifdef CONFIG_BR_SUPPORT ++ void *br_port = NULL; ++ ++ if (1) {//(check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ /* Insert NAT2.5 RX here! */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb); ++ ++ if (nat25_handle_frame(rwnx_vif, rx_skb) == -1) { ++ /* priv->ext_stats.rx_data_drops++; */ ++ /* DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); */ ++ /* return FAIL; */ ++ ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ /* Update statistics */ ++ rwnx_vif->net_stats.rx_packets++; ++ rwnx_vif->net_stats.rx_bytes += rx_skb->len; ++ ++ //printk("forward\n"); ++ ++ rx_skb->protocol = eth_type_trans(rx_skb, rwnx_vif->ndev); ++ memset(rx_skb->cb, 0, sizeof(rx_skb->cb)); ++ REG_SW_SET_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++ #ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_hw,rx_skb->data, cpu_to_le16(rx_skb->len)); ++ #endif ++ ++ #ifdef CONFIG_RX_NETIF_RECV_SKB //modify by aic ++ local_bh_disable(); ++ netif_receive_skb(rx_skb); ++ local_bh_enable(); ++ #else ++ if (in_interrupt()) { ++ netif_rx(rx_skb); ++ } else { ++ /* ++ * If the receive is not processed inside an ISR, the softirqd must be woken explicitly to service the NET_RX_SOFTIRQ. ++ * * In 2.6 kernels, this is handledby netif_rx_ni(), but in earlier kernels, we need to do it manually. ++ */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(rx_skb); ++ #else ++ ulong flags; ++ netif_rx(rx_skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++ #endif ++ } ++ #endif ++ REG_SW_CLEAR_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++ rwnx_hw->stats.last_rx = jiffies; ++} ++ ++ ++static bool rwnx_rx_data_skb(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *rxhdr) ++{ ++ struct sk_buff_head list; ++ struct sk_buff *rx_skb; ++ bool amsdu = rxhdr->flags_is_amsdu; ++ u8 flags_dst_idx = rxhdr->flags_dst_idx; ++ bool resend = false, forward = true; ++ ++ skb->dev = rwnx_vif->ndev; ++ ++ __skb_queue_head_init(&list); ++ ++ if (amsdu) { ++ #if 1 ++ rwnx_rxdata_process_amsdu(rwnx_hw, skb, rxhdr->flags_vif_idx, &list); //rxhdr not used below since skb free! ++ #else ++ int count; ++ ieee80211_amsdu_to_8023s(skb, &list, rwnx_vif->ndev->dev_addr, ++ RWNX_VIF_TYPE(rwnx_vif), 0, NULL, NULL); ++ ++ count = skb_queue_len(&list); ++ if (count > ARRAY_SIZE(rwnx_hw->stats.amsdus_rx)) ++ count = ARRAY_SIZE(rwnx_hw->stats.amsdus_rx); ++ rwnx_hw->stats.amsdus_rx[count - 1]++; ++ #endif ++ } else { ++ rwnx_hw->stats.amsdus_rx[0]++; ++ __skb_queue_head(&list, skb); ++ } ++ ++ if (((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP) || ++ (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN) || ++ (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO)) && ++ !(rwnx_vif->ap.flags & RWNX_AP_ISOLATE)) { ++ const struct ethhdr *eth; ++ rx_skb = skb_peek(&list); ++ skb_reset_mac_header(rx_skb); ++ eth = eth_hdr(rx_skb); ++ ++ if (unlikely(is_multicast_ether_addr(eth->h_dest))) { ++ /* broadcast pkt need to be forwared to upper layer and resent ++ on wireless interface */ ++ resend = true; ++ } else { ++ /* unicast pkt for STA inside the BSS, no need to forward to upper ++ layer simply resend on wireless interface */ ++ if (flags_dst_idx != RWNX_INVALID_STA) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[flags_dst_idx]; ++ if (sta->valid && (sta->vlan_idx == rwnx_vif->vif_index)) { ++ forward = false; ++ resend = true; ++ } ++ } ++ } ++ } else if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT) { ++ const struct ethhdr *eth; ++ rx_skb = skb_peek(&list); ++ skb_reset_mac_header(rx_skb); ++ eth = eth_hdr(rx_skb); ++ ++ if (!is_multicast_ether_addr(eth->h_dest)) { ++ /* unicast pkt for STA inside the BSS, no need to forward to upper ++ layer simply resend on wireless interface */ ++ if (flags_dst_idx != RWNX_INVALID_STA) { ++ forward = false; ++ resend = true; ++ } ++ } ++ } ++ ++ while (!skb_queue_empty(&list)) { ++ rx_skb = __skb_dequeue(&list); ++ ++ /* resend pkt on wireless interface */ ++ if (resend) { ++ struct sk_buff *skb_copy; ++ /* always need to copy buffer when forward=0 to get enough headrom for tsdesc */ ++ skb_copy = skb_copy_expand(rx_skb, sizeof(struct rwnx_txhdr) + ++ RWNX_SWTXHDR_ALIGN_SZ + 3 + 24 + 8, 0, GFP_ATOMIC); ++ ++ if (skb_copy) { ++ int res; ++ skb_copy->protocol = htons(ETH_P_802_3); ++ skb_reset_network_header(skb_copy); ++ skb_reset_mac_header(skb_copy); ++ ++ rwnx_vif->is_resending = true; ++ res = dev_queue_xmit(skb_copy); ++ rwnx_vif->is_resending = false; ++ /* note: buffer is always consummed by dev_queue_xmit */ ++ if (res == NET_XMIT_DROP) { ++ rwnx_vif->net_stats.rx_dropped++; ++ rwnx_vif->net_stats.tx_dropped++; ++ } else if (res != NET_XMIT_SUCCESS) { ++ netdev_err(rwnx_vif->ndev, ++ "Failed to re-send buffer to driver (res=%d)", ++ res); ++ rwnx_vif->net_stats.tx_errors++; ++ } ++ } else { ++ netdev_err(rwnx_vif->ndev, "Failed to copy skb"); ++ } ++ } ++ ++ /* forward pkt to upper layer */ ++ if (forward) { ++ #ifdef CONFIG_BR_SUPPORT ++ void *br_port = NULL; ++ ++ if (1) {//(check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ /* Insert NAT2.5 RX here! */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb); ++ ++ if (nat25_handle_frame(rwnx_vif, rx_skb) == -1) { ++ /* priv->ext_stats.rx_data_drops++; */ ++ /* DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); */ ++ /* return FAIL; */ ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ /* Update statistics */ ++ rwnx_vif->net_stats.rx_packets++; ++ rwnx_vif->net_stats.rx_bytes += rx_skb->len; ++ ++ rx_skb->protocol = eth_type_trans(rx_skb, rwnx_vif->ndev); ++#ifdef AICWF_ARP_OFFLOAD ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) ++ arpoffload_proc(rx_skb, rwnx_vif); ++#endif ++ memset(rx_skb->cb, 0, sizeof(rx_skb->cb)); ++ REG_SW_SET_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_hw,rx_skb->data, cpu_to_le16(rx_skb->len)); ++#endif ++ ++ #ifdef CONFIG_RX_NETIF_RECV_SKB //modify by aic ++ local_bh_disable(); ++ netif_receive_skb(rx_skb); ++ local_bh_enable(); ++ #else ++ if (in_interrupt()) { ++ netif_rx(rx_skb); ++ } else { ++ /* ++ * If the receive is not processed inside an ISR, the softirqd must be woken explicitly to service the NET_RX_SOFTIRQ. ++ * * In 2.6 kernels, this is handledby netif_rx_ni(), but in earlier kernels, we need to do it manually. ++ */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(rx_skb); ++ #else ++ ulong flags; ++ netif_rx(rx_skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++ #endif ++ } ++ #endif ++ REG_SW_CLEAR_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++ rwnx_hw->stats.last_rx = jiffies; ++ } ++ } ++ ++ return forward; ++} ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) ++const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len, ++ const u8 *match, int match_len, ++ int match_offset) ++{ ++ const struct element *elem; ++ ++ /* 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; ++ ++ for_each_element_id(elem, eid, ies, len) { ++ if (elem->datalen >= match_offset - 2 + match_len && ++ !memcmp(elem->data + match_offset - 2, match, match_len)) ++ return (void *)elem; ++ } ++ ++ return NULL; ++} ++#endif ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) ++static inline const u8 *cfg80211_find_ext_ie(u8 ext_eid, const u8* ies, int len) ++{ ++ return cfg80211_find_ie_match(WLAN_EID_EXTENSION, ies, len, ++ &ext_eid, 1, 2); ++} ++#endif ++#endif ++ ++ ++/** ++ * rwnx_rx_mgmt - Process one 802.11 management frame ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: vif to upload the buffer to ++ * @skb: skb received ++ * @rxhdr: HW rx descriptor ++ * ++ * Forward the management frame to a given interface. ++ */ ++static void rwnx_rx_mgmt(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *hw_rxhdr) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; ++ struct rx_vector_1 *rxvect = &hw_rxhdr->hwvect.rx_vect1; ++ ++ //printk("rwnx_rx_mgmt\n"); ++ ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ struct aic_sta *sta = &rwnx_hw->aic_table[rwnx_vif->ap.aic_index]; ++ const u8* ie; ++ u32 len; ++ ++ if(skb->data[0]!=0x80) ++ AICWFDBG(LOGDEBUG,"rxmgmt:%x,%x\n", skb->data[0], skb->data[1]); ++ ++ if (ieee80211_is_assoc_req(mgmt->frame_control) && rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) { ++ printk("ASSOC_REQ: sta_idx %d MAC %pM\n", rwnx_vif->ap.aic_index, mgmt->sa); ++ sta->sta_idx = rwnx_vif->ap.aic_index; ++ len = skb->len - (mgmt->u.assoc_req.variable - skb->data); ++ ++ #ifdef CONFIG_HE_FOR_OLD_KERNEL ++ struct ieee80211_he_cap_elem *he; ++ struct ieee80211_he_mcs_nss_supp *he_mcs; ++ ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, mgmt->u.assoc_req.variable, len); ++ if (ie && ie[1] >= sizeof(*he) + 1) { ++ printk("assoc_req: find he\n"); ++ he = (struct ieee80211_he_cap_elem *)(ie+3); ++ he_mcs = (struct ieee80211_he_mcs_nss_supp *)((u8 *)he + sizeof(*he)); ++ memcpy(&sta->he_cap_elem,ie+3,sizeof(struct ieee80211_he_cap_elem)); ++ ++ sta->he_mcs_nss_supp.rx_mcs_80 = he_mcs->rx_mcs_80; ++ sta->he_mcs_nss_supp.tx_mcs_80 = he_mcs->tx_mcs_80; ++ sta->he = true; ++ } ++ else { ++ printk("assoc_req: no find he\n"); ++ sta->he = false; ++ } ++ #endif ++ ++ #ifdef CONFIG_VHT_FOR_OLD_KERNEL ++ struct ieee80211_vht_cap *vht; ++ ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.assoc_req.variable, len); ++ if (ie && ie[1] >= sizeof(*vht)) { ++ printk("assoc_req: find vht\n"); ++ memcpy(&sta->vht_cap_info,ie+2,4); ++ memcpy(&sta->supp_mcs,ie+2+4,sizeof(struct ieee80211_vht_mcs_info)); ++ sta->vht = true; ++ } else { ++ printk("assoc_req: no find vht\n"); ++ sta->vht = false; ++ } ++ #endif ++ } ++#endif ++ ++ /*if (ieee80211_is_mgmt(mgmt->frame_control) && ++ (skb->len <= 24 || skb->len > 768)) { ++ printk("mgmt err\n"); ++ return; ++ }*/ ++ if (ieee80211_is_beacon(mgmt->frame_control)) { ++ if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT) && ++ hw_rxhdr->flags_new_peer) { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ GFP_ATOMIC); ++#else ++ cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ GFP_ATOMIC); ++#endif ++#else ++ ++#ifdef CONFIG_GKI ++ /* TODO: the value of parameter sig_dbm need to be confirmed */ ++ rwnx_cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ rxvect->rssi1, GFP_ATOMIC); ++#else ++ /* TODO: the value of parameter sig_dbm need to be confirmed */ ++ cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ rxvect->rssi1, GFP_ATOMIC); ++#endif ++ ++#endif ++ } else { ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_report_obss_beacon(rwnx_hw->wiphy, skb->data, skb->len, ++ hw_rxhdr->phy_info.phy_prim20_freq, ++ rxvect->rssi1); ++#else ++ cfg80211_report_obss_beacon(rwnx_hw->wiphy, skb->data, skb->len, ++ hw_rxhdr->phy_info.phy_prim20_freq, ++ rxvect->rssi1); ++#endif ++ } ++ } else if ((ieee80211_is_deauth(mgmt->frame_control) || ++ ieee80211_is_disassoc(mgmt->frame_control)) && ++ (mgmt->u.deauth.reason_code == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA || ++ mgmt->u.deauth.reason_code == WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)) { ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) // TODO: process unprot mgmt ++ cfg80211_rx_unprot_mlme_mgmt(rwnx_vif->ndev, skb->data, skb->len); ++ #endif ++ } else if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION) && ++ (ieee80211_is_action(mgmt->frame_control) && ++ (mgmt->u.action.category == 6))) { ++ struct cfg80211_ft_event_params ft_event; ++ ft_event.target_ap = (uint8_t *)&mgmt->u.action + ETH_ALEN + 2; ++ ft_event.ies = (uint8_t *)&mgmt->u.action + ETH_ALEN * 2 + 2; ++ ft_event.ies_len = skb->len - (ft_event.ies - (uint8_t *)mgmt); ++ ft_event.ric_ies = NULL; ++ ft_event.ric_ies_len = 0; ++ cfg80211_ft_event(rwnx_vif->ndev, &ft_event); ++ } else { ++ cfg80211_rx_mgmt(&rwnx_vif->wdev, hw_rxhdr->phy_info.phy_prim20_freq, ++ rxvect->rssi1, skb->data, skb->len, 0); ++ } ++} ++ ++/** ++ * rwnx_rx_mgmt_any - Process one 802.11 management frame ++ * ++ * @rwnx_hw: main driver data ++ * @skb: skb received ++ * @rxhdr: HW rx descriptor ++ * ++ * Process the management frame and free the corresponding skb. ++ * If vif is not specified in the rx descriptor, the the frame is uploaded ++ * on all active vifs. ++ */ ++static void rwnx_rx_mgmt_any(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, ++ struct hw_rxhdr *hw_rxhdr) ++{ ++ struct rwnx_vif *rwnx_vif; ++ int vif_idx = hw_rxhdr->flags_vif_idx; ++#ifdef CREATE_TRACE_POINTS ++ trace_mgmt_rx(hw_rxhdr->phy_info.phy_prim20_freq, vif_idx, ++ hw_rxhdr->flags_sta_idx, (struct ieee80211_mgmt *)skb->data); ++#endif ++ if (vif_idx == RWNX_INVALID_VIF) { ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (!rwnx_vif->up) ++ continue; ++ rwnx_rx_mgmt(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } ++ } else { ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, vif_idx); ++ if (rwnx_vif) ++ rwnx_rx_mgmt(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } ++ ++ dev_kfree_skb(skb); ++} ++ ++/** ++ * rwnx_rx_rtap_hdrlen - Return radiotap header length ++ * ++ * @rxvect: Rx vector used to fill the radiotap header ++ * @has_vend_rtap: boolean indicating if vendor specific data is present ++ * ++ * Compute the length of the radiotap header based on @rxvect and vendor ++ * specific data (if any). ++ */ ++static u8 rwnx_rx_rtap_hdrlen(struct rx_vector_1 *rxvect, ++ bool has_vend_rtap) ++{ ++ u8 rtap_len; ++ ++ /* Compute radiotap header length */ ++ rtap_len = sizeof(struct ieee80211_radiotap_header) + 8; ++ ++ // Check for multiple antennas ++ if (hweight32(rxvect->antenna_set) > 1) ++ // antenna and antenna signal fields ++ rtap_len += 4 * hweight8(rxvect->antenna_set); ++ ++ // TSFT ++ if (!has_vend_rtap) { ++ rtap_len = ALIGN(rtap_len, 8); ++ rtap_len += 8; ++ } ++ ++ // IEEE80211_HW_SIGNAL_DBM ++ rtap_len++; ++ ++ // Check if single antenna ++ if (hweight32(rxvect->antenna_set) == 1) ++ rtap_len++; //Single antenna ++ ++ // padding for RX FLAGS ++ rtap_len = ALIGN(rtap_len, 2); ++ ++ // Check for HT frames ++ if ((rxvect->format_mod == FORMATMOD_HT_MF) || ++ (rxvect->format_mod == FORMATMOD_HT_GF)) ++ rtap_len += 3; ++ ++ // Check for AMPDU ++ if (!(has_vend_rtap) && ((rxvect->format_mod >= FORMATMOD_VHT) || ++ ((rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) && ++ (rxvect->ht.aggregation)))) { ++ rtap_len = ALIGN(rtap_len, 4); ++ rtap_len += 8; ++ } ++ ++ // Check for VHT frames ++ if (rxvect->format_mod == FORMATMOD_VHT) { ++ rtap_len = ALIGN(rtap_len, 2); ++ rtap_len += 12; ++ } ++ ++ // Check for HE frames ++ if (rxvect->format_mod == FORMATMOD_HE_SU) { ++ rtap_len = ALIGN(rtap_len, 2); ++ rtap_len += sizeof(struct ieee80211_radiotap_he); ++ } ++ ++ // Check for multiple antennas ++ if (hweight32(rxvect->antenna_set) > 1) { ++ // antenna and antenna signal fields ++ rtap_len += 2 * hweight8(rxvect->antenna_set); ++ } ++ ++ // Check for vendor specific data ++ if (has_vend_rtap) { ++ /* vendor presence bitmap */ ++ rtap_len += 4; ++ /* alignment for fixed 6-byte vendor data header */ ++ rtap_len = ALIGN(rtap_len, 2); ++ } ++ ++ return rtap_len; ++} ++ ++/** ++ * rwnx_rx_add_rtap_hdr - Add radiotap header to sk_buff ++ * ++ * @rwnx_hw: main driver data ++ * @skb: skb received (will include the radiotap header) ++ * @rxvect: Rx vector ++ * @phy_info: Information regarding the phy ++ * @hwvect: HW Info (NULL if vendor specific data is available) ++ * @rtap_len: Length of the radiotap header ++ * @vend_rtap_len: radiotap vendor length (0 if not present) ++ * @vend_it_present: radiotap vendor present ++ * ++ * Builds a radiotap header and add it to @skb. ++ */ ++static void rwnx_rx_add_rtap_hdr(struct rwnx_hw *rwnx_hw, ++ struct sk_buff *skb, ++ struct rx_vector_1 *rxvect, ++ struct phy_channel_info_desc *phy_info, ++ struct hw_vect *hwvect, ++ int rtap_len, ++ u8 vend_rtap_len, ++ u32 vend_it_present) ++{ ++ struct ieee80211_radiotap_header *rtap; ++ u8 *pos, rate_idx; ++ __le32 *it_present; ++ u32 it_present_val = 0; ++ bool fec_coding = false; ++ bool short_gi = false; ++ bool stbc = false; ++ bool aggregation = false; ++ ++ rtap = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); ++ memset((u8 *) rtap, 0, rtap_len); ++ ++ rtap->it_version = 0; ++ rtap->it_pad = 0; ++ rtap->it_len = cpu_to_le16(rtap_len + vend_rtap_len); ++ ++ it_present = &rtap->it_present; ++ ++ // Check for multiple antennas ++ if (hweight32(rxvect->antenna_set) > 1) { ++ int chain; ++ unsigned long chains = rxvect->antenna_set; ++ ++ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { ++ it_present_val |= ++ BIT(IEEE80211_RADIOTAP_EXT) | ++ BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE); ++ put_unaligned_le32(it_present_val, it_present); ++ it_present++; ++ it_present_val = BIT(IEEE80211_RADIOTAP_ANTENNA) | ++ BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); ++ } ++ } ++ ++ // Check if vendor specific data is present ++ if (vend_rtap_len) { ++ it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | ++ BIT(IEEE80211_RADIOTAP_EXT); ++ put_unaligned_le32(it_present_val, it_present); ++ it_present++; ++ it_present_val = vend_it_present; ++ } ++ ++ put_unaligned_le32(it_present_val, it_present); ++ pos = (void *)(it_present + 1); ++ ++ // IEEE80211_RADIOTAP_TSFT ++ if (hwvect) { ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); ++ // padding ++ while ((pos - (u8 *)rtap) & 7) ++ *pos++ = 0; ++ put_unaligned_le64((((u64)le32_to_cpu(hwvect->tsf_hi) << 32) + ++ (u64)le32_to_cpu(hwvect->tsf_lo)), pos); ++ pos += 8; ++ } ++ ++ // IEEE80211_RADIOTAP_FLAGS ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_FLAGS); ++ if (hwvect && (!hwvect->frm_successful_rx)) ++ *pos |= IEEE80211_RADIOTAP_F_BADFCS; ++ if (!rxvect->pre_type ++ && (rxvect->format_mod <= FORMATMOD_NON_HT_DUP_OFDM)) ++ *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; ++ pos++; ++ ++ // IEEE80211_RADIOTAP_RATE ++ // check for HT, VHT or HE frames ++ if (rxvect->format_mod >= FORMATMOD_HE_SU) { ++ rate_idx = rxvect->he.mcs; ++ fec_coding = rxvect->he.fec; ++ stbc = rxvect->he.stbc; ++ aggregation = true; ++ *pos = 0; ++ } else if (rxvect->format_mod == FORMATMOD_VHT) { ++ rate_idx = rxvect->vht.mcs; ++ fec_coding = rxvect->vht.fec; ++ short_gi = rxvect->vht.short_gi; ++ stbc = rxvect->vht.stbc; ++ aggregation = true; ++ *pos = 0; ++ } else if (rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) { ++ rate_idx = rxvect->ht.mcs; ++ fec_coding = rxvect->ht.fec; ++ short_gi = rxvect->ht.short_gi; ++ stbc = rxvect->ht.stbc; ++ aggregation = rxvect->ht.aggregation; ++ *pos = 0; ++ } else { ++ struct ieee80211_supported_band *band = ++ rwnx_hw->wiphy->bands[phy_info->phy_band]; ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); ++ BUG_ON((rate_idx = legrates_lut[rxvect->leg_rate].idx) == -1); ++ if (phy_info->phy_band == NL80211_BAND_5GHZ) ++ rate_idx -= 4; /* rwnx_ratetable_5ghz[0].hw_value == 4 */ ++ *pos = DIV_ROUND_UP(band->bitrates[rate_idx].bitrate, 5); ++ } ++ pos++; ++ ++ // IEEE80211_RADIOTAP_CHANNEL ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CHANNEL); ++ put_unaligned_le16(phy_info->phy_prim20_freq, pos); ++ pos += 2; ++ ++ if (phy_info->phy_band == NL80211_BAND_5GHZ) ++ put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, pos); ++ else if (rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) ++ put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, pos); ++ else ++ put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, pos); ++ pos += 2; ++ ++ if (hweight32(rxvect->antenna_set) == 1) { ++ // IEEE80211_RADIOTAP_DBM_ANTSIGNAL ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); ++ *pos++ = rxvect->rssi1; ++ ++ // IEEE80211_RADIOTAP_ANTENNA ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_ANTENNA); ++ *pos++ = rxvect->antenna_set; ++ } ++ ++ // IEEE80211_RADIOTAP_LOCK_QUALITY is missing ++ // IEEE80211_RADIOTAP_DB_ANTNOISE is missing ++ ++ // IEEE80211_RADIOTAP_RX_FLAGS ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RX_FLAGS); ++ // 2 byte alignment ++ if ((pos - (u8 *)rtap) & 1) ++ *pos++ = 0; ++ put_unaligned_le16(0, pos); ++ //Right now, we only support fcs error (no RX_FLAG_FAILED_PLCP_CRC) ++ pos += 2; ++ ++ // Check if HT ++ if ((rxvect->format_mod == FORMATMOD_HT_MF) ++ || (rxvect->format_mod == FORMATMOD_HT_GF)) { ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); ++ *pos++ = IEEE80211_RADIOTAP_MCS_HAVE_MCS | ++ IEEE80211_RADIOTAP_MCS_HAVE_GI | ++ IEEE80211_RADIOTAP_MCS_HAVE_BW; ++ *pos = 0; ++ if (short_gi) ++ *pos |= IEEE80211_RADIOTAP_MCS_SGI; ++ if (rxvect->ch_bw == PHY_CHNL_BW_40) ++ *pos |= IEEE80211_RADIOTAP_MCS_BW_40; ++ if (rxvect->format_mod == FORMATMOD_HT_GF) ++ *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; ++ if (fec_coding) ++ *pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC; ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ *pos++ |= stbc << 5; ++ #else ++ *pos++ |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; ++ #endif ++ *pos++ = rate_idx; ++ } ++ ++ // check for HT or VHT frames ++ if (aggregation && hwvect) { ++ // 4 byte alignment ++ while ((pos - (u8 *)rtap) & 3) ++ pos++; ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); ++ put_unaligned_le32(hwvect->ampdu_cnt, pos); ++ pos += 4; ++ put_unaligned_le32(0, pos); ++ pos += 4; ++ } ++ ++ // Check for VHT frames ++ if (rxvect->format_mod == FORMATMOD_VHT) { ++ u16 vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | ++ IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; ++ u8 vht_nss = rxvect->vht.nss + 1; ++ ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); ++ ++ if ((rxvect->ch_bw == PHY_CHNL_BW_160) ++ && phy_info->phy_center2_freq) ++ vht_details &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; ++ put_unaligned_le16(vht_details, pos); ++ pos += 2; ++ ++ // flags ++ if (short_gi) ++ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; ++ if (stbc) ++ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; ++ pos++; ++ ++ // bandwidth ++ if (rxvect->ch_bw == PHY_CHNL_BW_40) ++ *pos++ = 1; ++ if (rxvect->ch_bw == PHY_CHNL_BW_80) ++ *pos++ = 4; ++ else if ((rxvect->ch_bw == PHY_CHNL_BW_160) ++ && phy_info->phy_center2_freq) ++ *pos++ = 0; //80P80 ++ else if (rxvect->ch_bw == PHY_CHNL_BW_160) ++ *pos++ = 11; ++ else // 20 MHz ++ *pos++ = 0; ++ ++ // MCS/NSS ++ *pos = (rate_idx << 4) | vht_nss; ++ pos += 4; ++ if (fec_coding) ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++ *pos |= 0x01; ++ #else ++ *pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0; ++ #endif ++ pos++; ++ // group ID ++ pos++; ++ // partial_aid ++ pos += 2; ++ } ++ ++ // Check for HE frames ++ if (rxvect->format_mod == FORMATMOD_HE_SU) { ++ struct ieee80211_radiotap_he he; ++ #define HE_PREP(f, val) cpu_to_le16(FIELD_PREP(IEEE80211_RADIOTAP_HE_##f, val)) ++ #define D1_KNOWN(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_##f##_KNOWN) ++ #define D2_KNOWN(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_##f##_KNOWN) ++ ++ he.data1 = D1_KNOWN(DATA_MCS) | D1_KNOWN(BSS_COLOR) | D1_KNOWN(BEAM_CHANGE) | ++ D1_KNOWN(UL_DL) | D1_KNOWN(CODING) | D1_KNOWN(STBC) | ++ D1_KNOWN(BW_RU_ALLOC) | D1_KNOWN(DOPPLER) | D1_KNOWN(DATA_DCM); ++ he.data2 = D2_KNOWN(GI) | D2_KNOWN(TXBF); ++ ++ if (stbc) { ++ he.data6 |= HE_PREP(DATA6_NSTS, 2); ++ he.data3 |= HE_PREP(DATA3_STBC, 1); ++ } else { ++ he.data6 |= HE_PREP(DATA6_NSTS, rxvect->he.nss); ++ } ++ ++ he.data3 |= HE_PREP(DATA3_BSS_COLOR, rxvect->he.bss_color); ++ he.data3 |= HE_PREP(DATA3_BEAM_CHANGE, rxvect->he.beam_change); ++ he.data3 |= HE_PREP(DATA3_UL_DL, rxvect->he.uplink_flag); ++ he.data3 |= HE_PREP(DATA3_BSS_COLOR, rxvect->he.bss_color); ++ he.data3 |= HE_PREP(DATA3_DATA_MCS, rxvect->he.mcs); ++ he.data3 |= HE_PREP(DATA3_DATA_DCM, rxvect->he.dcm); ++ he.data3 |= HE_PREP(DATA3_CODING, rxvect->he.fec); ++ ++ he.data5 |= HE_PREP(DATA5_GI, rxvect->he.gi_type); ++ he.data5 |= HE_PREP(DATA5_TXBF, rxvect->he.beamformed); ++ he.data5 |= HE_PREP(DATA5_LTF_SIZE, rxvect->he.he_ltf_type + 1); ++ ++ switch (rxvect->ch_bw) { ++ case PHY_CHNL_BW_20: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ); ++ break; ++ case PHY_CHNL_BW_40: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ); ++ break; ++ case PHY_CHNL_BW_80: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ); ++ break; ++ case PHY_CHNL_BW_160: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ); ++ break; ++ default: ++ WARN_ONCE(1, "Invalid SU BW %d\n", rxvect->ch_bw); ++ } ++ ++ he.data6 |= HE_PREP(DATA6_DOPPLER, rxvect->he.doppler); ++ ++ /* ensure 2 byte alignment */ ++ while ((pos - (u8 *)rtap) & 1) ++ pos++; ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE); ++ memcpy(pos, &he, sizeof(he)); ++ pos += sizeof(he); ++ } ++ ++ // Rx Chains ++ if (hweight32(rxvect->antenna_set) > 1) { ++ int chain; ++ unsigned long chains = rxvect->antenna_set; ++ u8 rssis[4] = {rxvect->rssi1, rxvect->rssi1, rxvect->rssi1, rxvect->rssi1}; ++ ++ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { ++ *pos++ = rssis[chain]; ++ *pos++ = chain; ++ } ++ } ++} ++ ++/** ++ * rwnx_rx_monitor - Build radiotap header for skb an send it to netdev ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: vif that received the buffer ++ * @skb: sk_buff received ++ * @hw_rxhdr_ptr: Pointer to HW RX header ++ * @rtap_len: Radiotap Header length ++ * ++ * Add radiotap header to the receved skb and send it to netdev ++ */ ++static int rwnx_rx_monitor(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *hw_rxhdr_ptr, ++ u8 rtap_len) ++{ ++ skb->dev = rwnx_vif->ndev; ++ ++ if (rwnx_vif->wdev.iftype != NL80211_IFTYPE_MONITOR) { ++ netdev_err(rwnx_vif->ndev, "not a monitor vif\n"); ++ return -1; ++ } ++ ++ /* Add RadioTap Header */ ++ rwnx_rx_add_rtap_hdr(rwnx_hw, skb, &hw_rxhdr_ptr->hwvect.rx_vect1, ++ &hw_rxhdr_ptr->phy_info, &hw_rxhdr_ptr->hwvect, ++ rtap_len, 0, 0); ++ ++ skb_reset_mac_header(skb); ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ skb->pkt_type = PACKET_OTHERHOST; ++ skb->protocol = htons(ETH_P_802_2); ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_hw,skb->data, cpu_to_le16(skb->len)); ++#endif ++ ++ local_bh_disable(); ++ netif_receive_skb(skb); ++ local_bh_enable(); ++ ++ return 0; ++} ++ ++#ifdef AICWF_ARP_OFFLOAD ++void arpoffload_proc(struct sk_buff *skb, struct rwnx_vif *rwnx_vif) ++{ ++ struct iphdr *iphead = (struct iphdr *)(skb->data); ++ struct udphdr *udph; ++ struct DHCPInfo *dhcph; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { // IP ++ if (iphead->protocol == IPPROTO_UDP) { // UDP ++ udph = (struct udphdr *)((u8 *)iphead + (iphead->ihl << 2)); ++ if ((udph->source == __constant_htons(SERVER_PORT)) ++ && (udph->dest == __constant_htons(CLIENT_PORT))) { // DHCP offset/ack ++ dhcph = (struct DHCPInfo *)((u8 *)udph + sizeof(struct udphdr)); ++ if (dhcph->cookie == htonl(DHCP_MAGIC) && dhcph->op == 2 && ++ !memcmp(dhcph->chaddr, rwnx_vif->ndev->dev_addr, 6)) { // match magic word ++ u32 length = ntohs(udph->len) - sizeof(struct udphdr) - offsetof(struct DHCPInfo, options); ++ u16 offset = 0; ++ u8 *option = dhcph->options; ++ while (option[offset] != DHCP_OPTION_END && offset < length) { ++ if (option[offset] == DHCP_OPTION_MESSAGE_TYPE) { ++ if (option[offset+2] == DHCP_ACK) { ++ dhcped = 1; ++ AICWFDBG(LOGINFO, "paired=%x, should=%x\n", rwnx_vif->sta.paired_cipher_type, WLAN_CIPHER_SUITE_CCMP); ++ if (rwnx_vif->sta.paired_cipher_type == WLAN_CIPHER_SUITE_CCMP || \ ++ rwnx_vif->sta.paired_cipher_type == WLAN_CIPHER_SUITE_AES_CMAC || \ ++ ((rwnx_vif->sta.group_cipher_type == 0xff) && \ ++ (rwnx_vif->sta.paired_cipher_type == 0xff))) ++ rwnx_send_arpoffload_en_req(rwnx_vif->rwnx_hw, rwnx_vif, dhcph->yiaddr, 1); ++ else ++ rwnx_send_arpoffload_en_req(rwnx_vif->rwnx_hw, rwnx_vif, dhcph->yiaddr, 0); ++ } ++ } ++ offset += 2 + option[offset+1]; ++ } ++ } ++ } ++ } ++ } ++} ++#endif ++ ++#ifdef AICWF_RX_REORDER ++void reord_rxframe_free(spinlock_t *lock, struct list_head *q, struct list_head *list) ++{ ++ spin_lock_bh(lock); ++ list_add(list, q); ++ spin_unlock_bh(lock); ++} ++ ++struct recv_msdu *reord_rxframe_alloc(spinlock_t *lock, struct list_head *q) ++{ ++ struct recv_msdu *rxframe; ++ ++ spin_lock_bh(lock); ++ if (list_empty(q)) { ++ spin_unlock_bh(lock); ++ return NULL; ++ } ++ rxframe = list_entry(q->next, struct recv_msdu, rxframe_list); ++ list_del_init(q->next); ++ spin_unlock_bh(lock); ++ return rxframe; ++} ++ ++struct reord_ctrl_info *reord_init_sta(struct aicwf_rx_priv *rx_priv, const u8 *mac_addr) ++{ ++ u8 i = 0; ++ struct reord_ctrl *preorder_ctrl = NULL; ++ struct reord_ctrl_info *reord_info; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++#else ++ struct aicwf_bus *bus_if = rx_priv->usbdev->bus_if; ++#endif ++ ++ if (bus_if->state == BUS_DOWN_ST || rx_priv == NULL) { ++ AICWFDBG(LOGERROR, "bad stat!\n"); ++ return NULL; ++ } ++ ++ AICWFDBG(LOGINFO, "reord_init_sta:%pM\n", mac_addr); ++ reord_info = kmalloc(sizeof(struct reord_ctrl_info), GFP_ATOMIC); ++ if (!reord_info) ++ return NULL; ++ ++ memcpy(reord_info->mac_addr, mac_addr, ETH_ALEN); ++ for (i = 0; i < 8; i++) { ++ preorder_ctrl = &reord_info->preorder_ctrl[i]; ++ preorder_ctrl->enable = true; ++ preorder_ctrl->ind_sn = 0xffff; ++ preorder_ctrl->wsize_b = AICWF_REORDER_WINSIZE; ++ preorder_ctrl->rx_priv = rx_priv; ++ INIT_LIST_HEAD(&preorder_ctrl->reord_list); ++ spin_lock_init(&preorder_ctrl->reord_list_lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ init_timer(&preorder_ctrl->reord_timer); ++ preorder_ctrl->reord_timer.data = (ulong) preorder_ctrl; ++ preorder_ctrl->reord_timer.function = reord_timeout_handler; ++#else ++ timer_setup(&preorder_ctrl->reord_timer, reord_timeout_handler, 0); ++#endif ++ INIT_WORK(&preorder_ctrl->reord_timer_work, reord_timeout_worker); ++ } ++ ++ return reord_info; ++} ++ ++int reord_flush_tid(struct aicwf_rx_priv *rx_priv, struct sk_buff *skb, u8 tid) ++{ ++ struct reord_ctrl_info *reord_info; ++ struct reord_ctrl *preorder_ctrl; ++ struct rwnx_vif *rwnx_vif = (struct rwnx_vif *)rx_priv->rwnx_vif; ++ struct ethhdr *eh = (struct ethhdr *)(skb->data); ++ u8 *mac; ++ unsigned long flags; ++ u8 found = 0; ++ struct list_head *phead, *plist; ++ struct recv_msdu *prframe; ++ int ret; ++ ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) ++ mac = eh->h_dest; ++ else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) ++ mac = eh->h_source; ++ else { ++ AICWFDBG(LOGERROR, "error mode:%d!\n", rwnx_vif->wdev.iftype); ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry(reord_info, &rx_priv->stas_reord_list, list) { ++ if (!memcmp(mac, reord_info->mac_addr, ETH_ALEN)) { ++ found = 1; ++ preorder_ctrl = &reord_info->preorder_ctrl[tid]; ++ break; ++ } ++ } ++ if (!found) { ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ return 0; ++ } ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ ++ if (preorder_ctrl->enable == false) ++ return 0; ++ spin_lock_irqsave(&preorder_ctrl->reord_list_lock, flags); ++ phead = &preorder_ctrl->reord_list; ++ while (1) { ++ if (list_empty(phead)) { ++ break; ++ } ++ plist = phead->next; ++ prframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ reord_single_frame_ind(rx_priv, prframe); ++ list_del_init(&(prframe->reord_pending_list)); ++ } ++ ++ AICWFDBG(LOGINFO, "flush:tid=%d", tid); ++ preorder_ctrl->enable = false; ++ spin_unlock_irqrestore(&preorder_ctrl->reord_list_lock, flags); ++ if (timer_pending(&preorder_ctrl->reord_timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete_sync(&preorder_ctrl->reord_timer); ++#else ++ ret = del_timer_sync(&preorder_ctrl->reord_timer); ++#endif ++ cancel_work_sync(&preorder_ctrl->reord_timer_work); ++ ++ return 0; ++} ++ ++ ++void reord_deinit_sta(struct aicwf_rx_priv *rx_priv, struct reord_ctrl_info *reord_info) ++{ ++ u8 i = 0; ++ unsigned long flags; ++ struct reord_ctrl *preorder_ctrl = NULL; ++ int ret; ++ ++ if (rx_priv == NULL) { ++ txrx_err("bad rx_priv!\n"); ++ return; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ struct recv_msdu *req, *next; ++ preorder_ctrl = &reord_info->preorder_ctrl[i]; ++ if(preorder_ctrl->enable){ ++ preorder_ctrl->enable = false; ++ if (timer_pending(&preorder_ctrl->reord_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete_sync(&preorder_ctrl->reord_timer); ++#else ++ ret = del_timer_sync(&preorder_ctrl->reord_timer); ++#endif ++ } ++ cancel_work_sync(&preorder_ctrl->reord_timer_work); ++ } ++ spin_lock_irqsave(&preorder_ctrl->reord_list_lock, flags); ++ list_for_each_entry_safe(req, next, &preorder_ctrl->reord_list, reord_pending_list) { ++ list_del_init(&req->reord_pending_list); ++ if (req->pkt != NULL) ++ dev_kfree_skb(req->pkt); ++ req->pkt = NULL; ++ reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &req->rxframe_list); ++ } ++ spin_unlock_irqrestore(&preorder_ctrl->reord_list_lock, flags); ++ ++ } ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_del(&reord_info->list); ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ kfree(reord_info); ++} ++ ++int reord_single_frame_ind(struct aicwf_rx_priv *rx_priv, struct recv_msdu *prframe) ++{ ++ struct list_head *rxframes_freequeue = NULL; ++ struct sk_buff *skb = NULL; ++ struct rwnx_vif *rwnx_vif = (struct rwnx_vif *)rx_priv->rwnx_vif; ++ struct sk_buff_head list; ++ struct sk_buff *rx_skb; ++ ++ rxframes_freequeue = &rx_priv->rxframes_freequeue; ++ skb = prframe->pkt; ++ ++ #ifdef CONFIG_BR_SUPPORT ++ void *br_port = NULL; ++ ++ if (1) {//(check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ /* Insert NAT2.5 RX here! */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb); ++ ++ if (nat25_handle_frame(rwnx_vif, skb) == -1) { ++ /* priv->ext_stats.rx_data_drops++; */ ++ /* DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); */ ++ /* return FAIL; */ ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ if (skb == NULL) { ++ txrx_err("skb is NULL\n"); ++ return -1; ++ } ++ ++ if(!prframe->forward) { ++ //printk("single: %d not forward: drop\n", prframe->seq_num); ++ dev_kfree_skb(skb); ++ prframe->pkt = NULL; ++ reord_rxframe_free(&rx_priv->freeq_lock, rxframes_freequeue, &prframe->rxframe_list); ++ return 0; ++ } ++ ++ //skb->data = prframe->rx_data; ++ //skb_set_tail_pointer(skb, prframe->len); ++ //skb->len = prframe->len; ++ __skb_queue_head_init(&list); ++ //printk("sg:%d\n", prframe->is_amsdu); ++ if(prframe->is_amsdu) { ++ rwnx_rxdata_process_amsdu(rwnx_vif->rwnx_hw, skb, rwnx_vif->vif_index, &list); //rxhdr not used below since skb free! ++ } else { ++ __skb_queue_head(&list, skb); ++ } ++ ++ ++ while (!skb_queue_empty(&list)) { ++ rx_skb = __skb_dequeue(&list); ++ ++ rwnx_vif->net_stats.rx_packets++; ++ rwnx_vif->net_stats.rx_bytes += rx_skb->len; ++ //printk("netif sn=%d, len=%d\n", precv_frame->attrib.seq_num, skb->len); ++ ++ rx_skb->dev = rwnx_vif->ndev; ++ rx_skb->protocol = eth_type_trans(rx_skb, rwnx_vif->ndev); ++ ++#ifdef AICWF_ARP_OFFLOAD ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ arpoffload_proc(rx_skb, rwnx_vif); ++ } ++#endif ++ memset(rx_skb->cb, 0, sizeof(rx_skb->cb)); ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_vif->rwnx_hw,rx_skb->data, cpu_to_le16(rx_skb->len)); ++#endif ++ ++#ifdef CONFIG_RX_NETIF_RECV_SKB//AIDEN test ++ local_bh_disable(); ++ netif_receive_skb(rx_skb); ++ local_bh_enable(); ++#else ++ if (in_interrupt()) { ++ netif_rx(rx_skb); ++ } else { ++ /* ++ * If the receive is not processed inside an ISR, the softirqd must be woken explicitly to service the NET_RX_SOFTIRQ. ++ * * In 2.6 kernels, this is handledby netif_rx_ni(), but in earlier kernels, we need to do it manually. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(rx_skb); ++#else ++ ulong flags; ++ netif_rx(rx_skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++#endif ++ } ++#endif /* CONFIG_RX_NETIF_RECV_SKB */ ++ } ++ ++ prframe->pkt = NULL; ++ reord_rxframe_free(&rx_priv->freeq_lock, rxframes_freequeue, &prframe->rxframe_list); ++ ++ return 0; ++} ++ ++bool reord_rxframes_process(struct aicwf_rx_priv *rx_priv, struct reord_ctrl *preorder_ctrl, int bforced) ++{ ++ struct list_head *phead, *plist; ++ struct recv_msdu *prframe; ++ bool bPktInBuf = false; ++ ++ if (bforced == true) { ++ phead = &preorder_ctrl->reord_list; ++ if (list_empty(phead)) { ++ return false; ++ } ++ ++ plist = phead->next; ++ prframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ preorder_ctrl->ind_sn = prframe->seq_num; ++ } ++ ++ phead = &preorder_ctrl->reord_list; ++ if (list_empty(phead)) { ++ return bPktInBuf; ++ } ++ ++ list_for_each_entry(prframe, phead, reord_pending_list) { ++ if (!SN_LESS(preorder_ctrl->ind_sn, prframe->seq_num)) { ++ if (SN_EQUAL(preorder_ctrl->ind_sn, prframe->seq_num)) { ++ preorder_ctrl->ind_sn = (preorder_ctrl->ind_sn + 1) & 0xFFF; ++ } ++ } else { ++ bPktInBuf = true; ++ break; ++ } ++ } ++ ++ return bPktInBuf; ++} ++ ++void reord_rxframes_ind(struct aicwf_rx_priv *rx_priv, ++ struct reord_ctrl *preorder_ctrl) ++{ ++ struct list_head *phead, *plist; ++ struct recv_msdu *prframe; ++ ++ phead = &preorder_ctrl->reord_list; ++ while (1) { ++ //spin_lock_bh(&preorder_ctrl->reord_list_lock); ++ if (list_empty(phead)) { ++ // spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ break; ++ } ++ ++ plist = phead->next; ++ prframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ ++ if (!SN_LESS(preorder_ctrl->ind_sn, prframe->seq_num)) { ++ list_del_init(&(prframe->reord_pending_list)); ++ // spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ reord_single_frame_ind(rx_priv, prframe); ++ } else { ++ // spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ break; ++ } ++ } ++} ++ ++int reorder_timeout = REORDER_UPDATE_TIME; ++module_param(reorder_timeout, int, 0660); ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void reord_timeout_handler (ulong data) ++#else ++void reord_timeout_handler (struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct reord_ctrl *preorder_ctrl = (struct reord_ctrl *)data; ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ struct reord_ctrl *preorder_ctrl = timer_container_of(preorder_ctrl, t, reord_timer); ++#else ++ struct reord_ctrl *preorder_ctrl = from_timer(preorder_ctrl, t, reord_timer); ++#endif ++#endif ++ ++#if 0 //AIDEN ++ struct aicwf_rx_priv *rx_priv = preorder_ctrl->rx_priv; ++ ++ if (reord_rxframes_process(rx_priv, preorder_ctrl, true) == true) { ++ mod_timer(&preorder_ctrl->reord_timer, jiffies + msecs_to_jiffies(REORDER_UPDATE_TIME)); ++ } ++#endif ++ ++ if (!work_pending(&preorder_ctrl->reord_timer_work)) ++ schedule_work(&preorder_ctrl->reord_timer_work); ++} ++ ++void reord_timeout_worker(struct work_struct *work) ++{ ++ struct reord_ctrl *preorder_ctrl = container_of(work, struct reord_ctrl, reord_timer_work); ++ struct aicwf_rx_priv *rx_priv = preorder_ctrl->rx_priv; ++ ++ spin_lock_bh(&preorder_ctrl->reord_list_lock); ++#if 1//AIDEN ++ if (reord_rxframes_process(rx_priv, preorder_ctrl, true)==true) { ++ mod_timer(&preorder_ctrl->reord_timer, jiffies + msecs_to_jiffies(reorder_timeout/*REORDER_UPDATE_TIME*/)); ++ } ++#endif ++ ++ reord_rxframes_ind(rx_priv, preorder_ctrl); ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ ++ return ; ++} ++ ++int reord_process_unit(struct aicwf_rx_priv *rx_priv, struct sk_buff *skb, u16 seq_num, u8 tid, u8 forward, u8 is_amsdu) ++{ ++ int ret = 0; ++ u8 *mac; ++ struct recv_msdu *pframe; ++ struct reord_ctrl *preorder_ctrl; ++ struct reord_ctrl_info *reord_info; ++ struct rwnx_vif *rwnx_vif = (struct rwnx_vif *)rx_priv->rwnx_vif; ++ struct ethhdr *eh = (struct ethhdr *)(skb->data); ++ u8 *da = eh->h_dest; ++ u8 is_mcast = ((*da) & 0x01) ? 1 : 0; ++ ++ if (rwnx_vif == NULL || skb->len <= 14) { ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ pframe = reord_rxframe_alloc(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue); ++ if (!pframe) { ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ INIT_LIST_HEAD(&pframe->reord_pending_list); ++ pframe->seq_num = seq_num; ++ pframe->tid = tid; ++ pframe->rx_data = skb->data; ++ //pframe->len = skb->len; ++ pframe->pkt = skb; ++ pframe->forward = forward; ++ preorder_ctrl = pframe->preorder_ctrl; ++ pframe->is_amsdu = is_amsdu; ++ ++ if ((ntohs(eh->h_proto) == ETH_P_PAE) || is_mcast) ++ return reord_single_frame_ind(rx_priv, pframe); ++ ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) ++ mac = eh->h_dest; ++ else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) ++ mac = eh->h_source; ++ else { ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry(reord_info, &rx_priv->stas_reord_list, list) { ++ if (!memcmp(mac, reord_info->mac_addr, ETH_ALEN)) { ++ preorder_ctrl = &reord_info->preorder_ctrl[pframe->tid]; ++ break; ++ } ++ } ++ ++ if (&reord_info->list == &rx_priv->stas_reord_list) { ++ reord_info = reord_init_sta(rx_priv, mac); ++ if (!reord_info) { ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ list_add_tail(&reord_info->list, &rx_priv->stas_reord_list); ++ preorder_ctrl = &reord_info->preorder_ctrl[pframe->tid]; ++ } else { ++ if (preorder_ctrl->enable == false) { ++ preorder_ctrl->enable = true; ++ preorder_ctrl->ind_sn = 0xffff; ++ preorder_ctrl->wsize_b = AICWF_REORDER_WINSIZE; ++ preorder_ctrl->rx_priv = rx_priv; ++ } ++ } ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ ++ if (preorder_ctrl->enable == false) { ++ spin_lock_bh(&preorder_ctrl->reord_list_lock); ++ preorder_ctrl->ind_sn = pframe->seq_num; ++ reord_single_frame_ind(rx_priv, pframe); ++ preorder_ctrl->ind_sn = (preorder_ctrl->ind_sn + 1)%4096; ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ return 0; ++ } ++ ++ spin_lock_bh(&preorder_ctrl->reord_list_lock); ++ if (reord_need_check(preorder_ctrl, pframe->seq_num)) { ++#if 1 ++ if(pframe->rx_data[42] == 0x80){//this is rtp package ++ if(pframe->seq_num == preorder_ctrl->ind_sn){ ++ printk("%s pframe->seq_num1:%d \r\n", __func__, pframe->seq_num); ++ reord_single_frame_ind(rx_priv, pframe);//not need to reorder ++ }else{ ++ printk("%s free pframe->seq_num:%d \r\n", __func__, pframe->seq_num); ++ if (pframe->pkt){ ++ dev_kfree_skb(pframe->pkt); ++ pframe->pkt = NULL; ++ } ++ reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &pframe->rxframe_list); ++ } ++ }else{ ++ //printk("%s pframe->seq_num2:%d \r\n", __func__, pframe->seq_num); ++ reord_single_frame_ind(rx_priv, pframe);//not need to reorder ++ } ++#else ++ reord_single_frame_ind(rx_priv, pframe);//not need to reor ++#endif ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ return 0; ++ } ++ ++ if (reord_rxframe_enqueue(preorder_ctrl, pframe)) { ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ goto fail; ++ } ++ ++ if (reord_rxframes_process(rx_priv, preorder_ctrl, false) == true) { ++ if (!timer_pending(&preorder_ctrl->reord_timer)) { ++ ret = mod_timer(&preorder_ctrl->reord_timer, jiffies + msecs_to_jiffies(reorder_timeout/*REORDER_UPDATE_TIME*/)); ++ } ++ } else { ++ if (timer_pending(&preorder_ctrl->reord_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete(&preorder_ctrl->reord_timer); ++#else ++ ret = del_timer(&preorder_ctrl->reord_timer); ++#endif ++ } ++ } ++ ++ reord_rxframes_ind(rx_priv, preorder_ctrl); ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ ++ return 0; ++ ++fail: ++ if (pframe->pkt) { ++ dev_kfree_skb(pframe->pkt); ++ pframe->pkt = NULL; ++ } ++ reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &pframe->rxframe_list); ++ return ret; ++} ++ ++int reord_need_check(struct reord_ctrl *preorder_ctrl, u16 seq_num) ++{ ++ u8 wsize = preorder_ctrl->wsize_b; ++ u16 wend = (preorder_ctrl->ind_sn + wsize -1) & 0xFFF; ++ ++ if (preorder_ctrl->ind_sn == 0xFFFF) { ++ preorder_ctrl->ind_sn = seq_num; ++ } ++ ++ if (SN_LESS(seq_num, preorder_ctrl->ind_sn)) { ++ return -1; ++ } ++ ++ if (SN_EQUAL(seq_num, preorder_ctrl->ind_sn)) { ++ preorder_ctrl->ind_sn = (preorder_ctrl->ind_sn + 1) & 0xFFF; ++ } else if (SN_LESS(wend, seq_num)) { ++ if (seq_num >= (wsize-1)) ++ preorder_ctrl->ind_sn = seq_num-(wsize-1); ++ else ++ preorder_ctrl->ind_sn = 0xFFF - (wsize - (seq_num + 1)) + 1; ++ } ++ ++ return 0; ++} ++ ++int reord_rxframe_enqueue(struct reord_ctrl *preorder_ctrl, struct recv_msdu *prframe) ++{ ++ struct list_head *preord_list = &preorder_ctrl->reord_list; ++ struct list_head *phead, *plist; ++ struct recv_msdu *pnextrframe; ++ ++ phead = preord_list; ++ plist = phead->next; ++ ++ while (phead != plist) { ++ pnextrframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ if (SN_LESS(pnextrframe->seq_num, prframe->seq_num)) { ++ plist = plist->next; ++ continue; ++ } else if (SN_EQUAL(pnextrframe->seq_num, prframe->seq_num)) { ++ return -1; ++ } else { ++ break; ++ } ++ } ++ list_add_tail(&(prframe->reord_pending_list), plist); ++ ++ return 0; ++} ++#endif /* AICWF_RX_REORDER */ ++ ++void remove_sec_hdr_mgmt_frame(struct hw_rxhdr *hw_rxhdr, struct sk_buff *skb) ++{ ++ u8 hdr_len = 24; ++ u8 mgmt_header[24] = {0}; ++ ++ if (!hw_rxhdr->hwvect.ga_frame) { ++ if (((skb->data[0] & 0x0C) == 0) && (skb->data[1] & 0x40) == 0x40) { //protect management frame ++ printk("frame type %x\n", skb->data[0]); ++ if (hw_rxhdr->hwvect.decr_status == RWNX_RX_HD_DECR_CCMP128) { ++ memcpy(mgmt_header, skb->data, hdr_len); ++ skb_pull(skb, 8); ++ memcpy(skb->data, mgmt_header, hdr_len); ++ hw_rxhdr->hwvect.len -= 8; ++ } else { ++ printk("unsupport decr_status:%d\n", hw_rxhdr->hwvect.decr_status); ++ } ++ } ++ } ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++void defrag_timeout_cb(ulong data) ++#else ++void defrag_timeout_cb(struct timer_list *t) ++#endif ++{ ++ struct defrag_ctrl_info *defrag_ctrl = NULL; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ defrag_ctrl = (struct defrag_ctrl_info *)data; ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ defrag_ctrl = timer_container_of(defrag_ctrl, t, defrag_timer); ++#else ++ defrag_ctrl = from_timer(defrag_ctrl, t, defrag_timer); ++#endif ++#endif ++ ++ printk("%s:%p\r\n", __func__, defrag_ctrl); ++ spin_lock_bh(&defrag_ctrl->rwnx_hw->defrag_lock); ++ list_del_init(&defrag_ctrl->list); ++ dev_kfree_skb(defrag_ctrl->skb); ++ kfree(defrag_ctrl); ++ spin_unlock_bh(&defrag_ctrl->rwnx_hw->defrag_lock); ++} ++ ++void rwnx_rxdata_process_amsdu(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, u8 vif_idx, ++ struct sk_buff_head *list) ++{ ++ u16 len_alligned = 0; ++ u16 sublen = 0; ++ struct sk_buff *sub_skb = NULL; ++ struct rwnx_vif *rwnx_vif; ++ ++ //if (is_amsdu) ++ { ++ //skb_pull(skb, pull_len-8); ++ /* |amsdu sub1 | amsdu sub2 | ... */ ++ len_alligned = 0; ++ sublen = 0; ++ sub_skb = NULL; ++ while (skb->len > 16) { ++ sublen = (skb->data[12]<<8)|(skb->data[13]); ++ if (skb->len > (sublen+14)) ++ len_alligned = roundup(sublen + 14, 4); ++ else if (skb->len == (sublen+14)) ++ len_alligned = sublen+14; ++ else { ++ printk("accroding to amsdu: this will not happen\n"); ++ break; ++ } ++ //printk("sublen = %d, %x, %x, %x, %x\r\n", sublen,skb->data[0], skb->data[1], skb->data[12], skb->data[13]); ++#if 1 ++ sub_skb = __dev_alloc_skb(sublen - 6 + 12, GFP_ATOMIC); ++ if(!sub_skb){ ++ printk("sub_skb alloc fail:%d\n", sublen); ++ break; ++ } ++ skb_put(sub_skb, sublen - 6 + 12); ++ memcpy(sub_skb->data, skb->data, MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[6], &skb->data[6], MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[12], &skb->data[14 + 6], sublen - 6); ++ ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, vif_idx); ++ if (!rwnx_vif) { ++ printk("Frame received but no active vif (%d)", vif_idx); ++ //dev_kfree_skb(sub_skb); ++ break; ++ } ++ ++ __skb_queue_tail(list, sub_skb); ++ ++ //printk("a:%p\n", sub_skb); ++ //if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, sub_skb, hw_rxhdr)) ++ // dev_kfree_skb(sub_skb); ++#endif ++ skb_pull(skb, len_alligned); ++ } ++ //printk("af:%p\n", skb); ++ ++ dev_kfree_skb(skb); ++ //return 0; ++ } ++} ++ ++u8 rwnx_rxdataind_aicwf(struct rwnx_hw *rwnx_hw, void *hostid, void *rx_priv) ++{ ++ struct hw_rxhdr *hw_rxhdr; ++ struct rxdesc_tag *rxdesc = NULL; ++ struct rwnx_vif *rwnx_vif; ++ struct sk_buff *skb = hostid; ++ int msdu_offset = sizeof(struct hw_rxhdr) + 2; ++ u16_l status = 0; ++ struct aicwf_rx_priv *rx_priv_tmp; ++ u8 hdr_len = 24; ++ u8 ra[MAC_ADDR_LEN] = {0}; ++ u8 ta[MAC_ADDR_LEN] = {0}; ++ u8 ether_type[2] = {0}; ++ u8 pull_len = 0; ++ u16 seq_num = 0; ++ u8_l frag_num = 0; ++ u8 tid = 0; ++ u8 is_qos = 0; ++ u8 is_frag = 0; ++ struct defrag_ctrl_info *defrag_info = NULL; ++ struct defrag_ctrl_info *defrag_info_tmp = NULL; ++ struct sk_buff *skb_tmp = NULL; ++ int ret; ++ u8 sta_idx = 0; ++ u16_l frame_ctrl; ++ u8 is_amsdu = 0; ++ bool resend = false, forward = true; ++ const struct ethhdr *eth; ++ ++ hw_rxhdr = (struct hw_rxhdr *)skb->data; ++ ++#ifdef AICWF_RX_REORDER ++ if (hw_rxhdr->is_monitor_vif) { ++ status = RX_STAT_MONITOR; ++ //printk("monitor rx\n"); ++ } ++#endif ++ ++ if (hw_rxhdr->flags_upload) ++ status |= RX_STAT_FORWARD; ++ ++ /* Check if we need to delete the buffer */ ++ if (status & RX_STAT_DELETE) { ++ /* Remove the SK buffer from the rxbuf_elems table */ ++ #if 0 ++ rwnx_ipc_rxbuf_elem_pull(rwnx_hw, skb); ++ #endif ++ /* Free the buffer */ ++ dev_kfree_skb(skb); ++ goto end; ++ } ++ ++ /* Check if we need to forward the buffer coming from a monitor interface */ ++ if (status & RX_STAT_MONITOR) { ++ struct sk_buff *skb_monitor = NULL; ++ struct hw_rxhdr hw_rxhdr_copy; ++ u8 rtap_len; ++ u16 frm_len = 0; ++ ++ //Check if monitor interface exists and is open ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, rwnx_hw->monitor_vif); ++ if (!rwnx_vif) { ++ dev_err(rwnx_hw->dev, "Received monitor frame but there is no monitor interface open\n"); ++ goto check_len_update; ++ } ++ ++ rwnx_rx_vector_convert(rwnx_hw, ++ &hw_rxhdr->hwvect.rx_vect1, ++ &hw_rxhdr->hwvect.rx_vect2); ++ rtap_len = rwnx_rx_rtap_hdrlen(&hw_rxhdr->hwvect.rx_vect1, false); ++ ++ if (status == RX_STAT_MONITOR) ++ { ++ /* Remove the SK buffer from the rxbuf_elems table. It will also ++ unmap the buffer and then sync the buffer for the cpu */ ++ //rwnx_ipc_rxbuf_elem_pull(rwnx_hw, skb); ++ skb->data += (msdu_offset + 2); //sdio/usb word allign ++ ++ //Save frame length ++ frm_len = le32_to_cpu(hw_rxhdr->hwvect.len); ++ ++ // Reserve space for frame ++ skb->len = frm_len; ++ ++ //Check if there is enough space to add the radiotap header ++ if (skb_headroom(skb) > rtap_len) { ++ ++ skb_monitor = skb; ++ ++ //Duplicate the HW Rx Header to override with the radiotap header ++ memcpy(&hw_rxhdr_copy, hw_rxhdr, sizeof(hw_rxhdr_copy)); ++ ++ hw_rxhdr = &hw_rxhdr_copy; ++ } else { ++ //Duplicate the skb and extend the headroom ++ skb_monitor = skb_copy_expand(skb, rtap_len, 0, GFP_ATOMIC); ++ ++ //Reset original skb->data pointer ++ skb->data = (void*) hw_rxhdr; ++ } ++ } else { ++ #ifdef CONFIG_RWNX_MON_DATA ++ skb_monitor = skb_copy_expand(skb, rtap_len, 0, GFP_ATOMIC); ++ skb_monitor->data += (msdu_offset + 2); //sdio/usb word allign ++ ++ //Save frame length ++ frm_len = le32_to_cpu(hw_rxhdr->hwvect.len); ++ #endif ++ } ++ ++ skb_reset_tail_pointer(skb_monitor); ++ skb_monitor->len = 0; ++ skb_put(skb_monitor, frm_len); ++ ++ if (rwnx_rx_monitor(rwnx_hw, rwnx_vif, skb_monitor, hw_rxhdr, rtap_len)) ++ dev_kfree_skb(skb_monitor); ++ ++ if (status == RX_STAT_MONITOR) { ++ if (skb_monitor != skb) { ++ dev_kfree_skb(skb); ++ } ++ } ++ } ++ ++ ++check_len_update: ++ /* Check if we need to update the length */ ++ if (status & RX_STAT_LEN_UPDATE) { ++ if (rxdesc) ++ hw_rxhdr->hwvect.len = rxdesc->frame_len; ++ ++ if (status & RX_STAT_ETH_LEN_UPDATE) { ++ /* Update Length Field inside the Ethernet Header */ ++ struct ethhdr *hdr = (struct ethhdr *)((u8 *)hw_rxhdr + msdu_offset); ++ ++ if (rxdesc) ++ hdr->h_proto = htons(rxdesc->frame_len - sizeof(struct ethhdr)); ++ } ++ ++ goto end; ++ } ++ ++ /* Check if it must be discarded after informing upper layer */ ++ if (status & RX_STAT_SPURIOUS) { ++ struct ieee80211_hdr *hdr; ++ ++ hdr = (struct ieee80211_hdr *)(skb->data + msdu_offset); ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ if (rwnx_vif) { ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, GFP_ATOMIC); ++#else ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, GFP_ATOMIC); ++#else ++ cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, -1, GFP_ATOMIC); ++#endif ++#endif ++ } ++ goto end; ++ } ++ ++ /* Check if we need to forward the buffer */ ++ if (status & RX_STAT_FORWARD) { ++ rwnx_rx_vector_convert(rwnx_hw, ++ &hw_rxhdr->hwvect.rx_vect1, ++ &hw_rxhdr->hwvect.rx_vect2); ++ skb_pull(skb, msdu_offset + 2); //+2 since sdio allign 58->60 ++ ++#define MAC_FCTRL_MOREFRAG 0x0400 ++ frame_ctrl = (skb->data[1] << 8) | skb->data[0]; ++ seq_num = ((skb->data[22] & 0xf0) >> 4) | (skb->data[23] << 4); ++ frag_num = (skb->data[22] & 0x0f); ++ is_amsdu = 0; ++ ++ if ((skb->data[0] & 0x0f) == 0x08) { ++ if ((skb->data[0] & 0x80) == 0x80) {//qos data ++ hdr_len = 26; ++ tid = skb->data[24] & 0x0F; ++ is_qos = 1; ++ if (skb->data[24] & 0x80) ++ is_amsdu = 1; ++ } ++ ++ if(skb->data[1] & 0x80)// htc ++ hdr_len += 4; ++ ++ if ((skb->data[1] & 0x3) == 0x1) {// to ds ++ memcpy(ra, &skb->data[16], MAC_ADDR_LEN); ++ memcpy(ta, &skb->data[10], MAC_ADDR_LEN); ++ } else if ((skb->data[1] & 0x3) == 0x2) { //from ds ++ memcpy(ta, &skb->data[16], MAC_ADDR_LEN); ++ memcpy(ra, &skb->data[4], MAC_ADDR_LEN); ++ } ++ ++ pull_len += (hdr_len + 8); ++ ++ switch (hw_rxhdr->hwvect.decr_status) { ++ case RWNX_RX_HD_DECR_CCMP128: ++ pull_len += 8;//ccmp_header ++ //skb_pull(&skb->data[skb->len-8], 8); //ccmp_mic_len ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 8], 2); ++ break; ++ case RWNX_RX_HD_DECR_TKIP: ++ pull_len += 8;//tkip_header ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 8], 2); ++ break; ++ case RWNX_RX_HD_DECR_WEP: ++ pull_len += 4;//wep_header ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 4], 2); ++ break; ++ case RWNX_RX_HD_DECR_WAPI: ++ pull_len += 18;//wapi_header ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 18], 2); ++ break; ++ ++ default: ++ memcpy(ether_type, &skb->data[hdr_len + 6], 2); ++ break; ++ } ++ if(is_amsdu) ++ hw_rxhdr->flags_is_amsdu = 1; ++ else ++ hw_rxhdr->flags_is_amsdu = 0; ++ ++ if (is_amsdu) { ++ #if 1 ++ skb_pull(skb, pull_len-8); ++ #else ++ skb_pull(skb, pull_len-8); ++ /* |amsdu sub1 | amsdu sub2 | ... */ ++ len_alligned = 0; ++ sublen = 0; ++ sub_skb = NULL; ++ //printk("is_len:%d, pull:%d\n", skb->len, pull_len); ++ while (skb->len > 16) { ++ sublen = (skb->data[12]<<8)|(skb->data[13]); ++ if (skb->len > (sublen+14)) ++ len_alligned = roundup(sublen + 14, 4); ++ else if (skb->len == (sublen+14)) ++ len_alligned = sublen+14; ++ else { ++ printk("accroding to amsdu: this will not happen\n"); ++ break; ++ } ++ //printk("sublen = %d, %x, %x, %x, %x\r\n", sublen,skb->data[0], skb->data[1], skb->data[12], skb->data[13]); ++#if 1 ++ sub_skb = __dev_alloc_skb(sublen - 6 + 12, GFP_KERNEL); ++ skb_put(sub_skb, sublen - 6 + 12); ++ memcpy(sub_skb->data, skb->data, MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[6], &skb->data[6], MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[12], &skb->data[14 + 6], sublen - 6); ++ ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ if (!rwnx_vif) { ++ printk("Frame received but no active vif (%d)", hw_rxhdr->flags_vif_idx); ++ dev_kfree_skb(sub_skb); ++ break; ++ } ++ ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, sub_skb, hw_rxhdr)) ++ dev_kfree_skb(sub_skb); ++#endif ++ skb_pull(skb, len_alligned); ++ } ++ dev_kfree_skb(skb); ++ return 0; ++ #endif ++ } ++ ++ if (hw_rxhdr->flags_dst_idx != RWNX_INVALID_STA) ++ sta_idx = hw_rxhdr->flags_dst_idx; ++ ++ if (!hw_rxhdr->flags_need_reord && ((frame_ctrl & MAC_FCTRL_MOREFRAG) || frag_num)) { ++ printk("rxfrag:%d,%d,%d,sn=%d,%d\r\n", (frame_ctrl & MAC_FCTRL_MOREFRAG), frag_num, skb->len, seq_num,pull_len); ++ if (frame_ctrl & MAC_FCTRL_MOREFRAG) { ++ spin_lock_bh(&rwnx_hw->defrag_lock); ++ if (!list_empty(&rwnx_hw->defrag_list)) { ++ list_for_each_entry(defrag_info_tmp, &rwnx_hw->defrag_list, list) { ++ if ((defrag_info_tmp->sn == seq_num) && (defrag_info_tmp->tid == tid) && \ ++ defrag_info_tmp->sta_idx == sta_idx) { ++ defrag_info = defrag_info_tmp; ++ break; ++ } ++ } ++ } ++ ++ //printk("rx frag: sn=%d, fn=%d, skb->len=%d\r\n", seq_num, frag_num, skb->len); ++ if (defrag_info) { ++ is_frag = 1; ++ if (defrag_info->next_fn != frag_num) { ++ printk("discard:%d:%d\n", defrag_info->next_fn, frag_num); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ ++ skb_put(defrag_info->skb, skb->len-(pull_len-8)); ++ memcpy(&defrag_info->skb->data[defrag_info->frm_len], \ ++ &skb->data[pull_len-8], skb->len - (pull_len-8)); ++ //printk("middle:%d,%d\n", skb->len-(pull_len-8), skb->len); ++ defrag_info->frm_len += (skb->len - (pull_len - 8)); ++ defrag_info->next_fn++; ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } else { ++ defrag_info = kzalloc(sizeof(struct defrag_ctrl_info), GFP_KERNEL); ++ if (defrag_info == NULL) { ++ printk("no defrag_ctrl_info\r\n"); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ defrag_info->skb = __dev_alloc_skb(2000, GFP_KERNEL); ++ if (defrag_info->skb == NULL) { ++ printk("no fragment skb\r\n"); ++ dev_kfree_skb(skb); ++ kfree(defrag_info); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ is_frag = 1; ++ skb_pull(skb, pull_len); ++ skb_push(skb, 14); ++ memcpy(skb->data, ra, MAC_ADDR_LEN); ++ memcpy(&skb->data[6], ta, MAC_ADDR_LEN); ++ memcpy(&skb->data[12], ether_type, 2); ++ defrag_info->sn = seq_num; ++ defrag_info->next_fn = 1; ++ defrag_info->tid = tid; ++ defrag_info->sta_idx = sta_idx; ++ ++ skb_put(defrag_info->skb, skb->len); ++ memcpy(defrag_info->skb->data, skb->data, skb->len); ++ defrag_info->frm_len = skb->len; ++ defrag_info->rwnx_hw = rwnx_hw; ++ //printk("first:%p,%p,%p,%p,%p, %d,%d\r\n", defrag_info, defrag_info->skb, defrag_info->skb->head, defrag_info->skb->tail, defrag_info->skb->end, defrag_info->frm_len, skb->len); ++ list_add_tail(&defrag_info->list, &rwnx_hw->defrag_list); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ init_timer(&defrag_info->defrag_timer); ++ defrag_info->defrag_timer.data = (unsigned long)defrag_info; ++ defrag_info->defrag_timer.function = defrag_timeout_cb; ++#else ++ timer_setup(&defrag_info->defrag_timer, defrag_timeout_cb, 0); ++#endif ++ ret = mod_timer(&defrag_info->defrag_timer, jiffies + msecs_to_jiffies(DEFRAG_MAX_WAIT)); ++ dev_kfree_skb(skb); ++ return 0; ++ } ++ } else { ++ //check whether the last fragment ++ if (!list_empty(&rwnx_hw->defrag_list)) { ++ spin_lock_bh(&rwnx_hw->defrag_lock); ++ list_for_each_entry(defrag_info_tmp, &rwnx_hw->defrag_list, list) { ++ if (((defrag_info_tmp->sn == seq_num) && (defrag_info_tmp->tid == tid) && \ ++ defrag_info_tmp->sta_idx == sta_idx)) { ++ defrag_info = defrag_info_tmp; ++ break; ++ } ++ } ++ ++ if (!defrag_info) ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ else { ++ if (defrag_info->next_fn != frag_num) { ++ printk("discard:%d:%d\n", defrag_info->next_fn, frag_num); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ ++ skb_put(defrag_info->skb, skb->len - (pull_len-8)); ++ memcpy(&defrag_info->skb->data[defrag_info->frm_len], \ ++ &skb->data[pull_len-8], skb->len - (pull_len-8)); ++ defrag_info->frm_len += (skb->len - (pull_len-8)); ++ is_frag = 1; ++ //printk("last: sn=%d, fn=%d, %d, %d\r\n", seq_num, frag_num, defrag_info->frm_len, skb->len); ++ ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ if (!rwnx_vif) { ++ printk("Frame received but no active vif (%d)", hw_rxhdr->flags_vif_idx); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ dev_kfree_skb(skb); ++ ++ skb_tmp = defrag_info->skb; ++ list_del_init(&defrag_info->list); ++ if (timer_pending(&defrag_info->defrag_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete(&defrag_info->defrag_timer); ++#else ++ ret = del_timer(&defrag_info->defrag_timer); ++#endif ++ } ++ kfree(defrag_info); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb_tmp, hw_rxhdr)) ++ dev_kfree_skb(skb_tmp); ++ ++ return 0; ++ } ++ } ++ } ++ } ++ ++ if (!is_frag && !is_amsdu) { ++ skb_pull(skb, pull_len); ++ skb_push(skb, 14); ++ memcpy(skb->data, ra, MAC_ADDR_LEN); ++ memcpy(&skb->data[6], ta, MAC_ADDR_LEN); ++ memcpy(&skb->data[12], ether_type, 2); ++ } ++ } ++ ++ if (hw_rxhdr->flags_is_80211_mpdu) { ++ remove_sec_hdr_mgmt_frame(hw_rxhdr, skb); ++ rwnx_rx_mgmt_any(rwnx_hw, skb, hw_rxhdr); ++ } else { ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ ++ if (!rwnx_vif) { ++ dev_err(rwnx_hw->dev, "Frame received but no active vif(%d)", ++ hw_rxhdr->flags_vif_idx); ++ dev_kfree_skb(skb); ++ goto end; ++ } ++ ++ if (hw_rxhdr->flags_sta_idx != RWNX_INVALID_STA) { ++ struct rwnx_sta *sta; ++ ++ sta = &rwnx_hw->sta_table[hw_rxhdr->flags_sta_idx]; ++ rwnx_rx_statistic(rwnx_hw, hw_rxhdr, sta); ++ ++ if (sta->vlan_idx != rwnx_vif->vif_index) { ++ rwnx_vif = rwnx_hw->vif_table[sta->vlan_idx]; ++ if (!rwnx_vif) { ++ dev_kfree_skb(skb); ++ goto end; ++ } ++ } ++ ++ if (hw_rxhdr->flags_is_4addr && !rwnx_vif->use_4addr) { ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev, ++ sta->mac_addr, GFP_ATOMIC); ++#else ++ cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ sta->mac_addr, GFP_ATOMIC); ++#else ++ sta->mac_addr, -1, GFP_ATOMIC); ++#endif ++#endif ++ } ++ } ++ ++ skb->priority = 256 + tid;//hw_rxhdr->flags_user_prio; ++ ++#ifdef AICWF_RX_REORDER ++ rx_priv_tmp = rx_priv; ++ rx_priv_tmp->rwnx_vif = (void *)rwnx_vif; ++ ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ if (is_qos && hw_rxhdr->flags_need_reord) ++ reord_process_unit((struct aicwf_rx_priv *)rx_priv, skb, seq_num, tid, 1, hw_rxhdr->flags_is_amsdu); ++ else if (is_qos && !hw_rxhdr->flags_need_reord) { ++ reord_flush_tid((struct aicwf_rx_priv *)rx_priv, skb, tid); ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr) && !hw_rxhdr->flags_is_amsdu) ++ dev_kfree_skb(skb); ++ } else { ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr) && !hw_rxhdr->flags_is_amsdu) ++ dev_kfree_skb(skb); ++ } ++ } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { ++#if 1 ++ skb_reset_mac_header(skb); ++ eth = eth_hdr(skb); ++ //printk("da:%pM, %x,%x, len=%d\n", eth->h_dest, skb->data[12], skb->data[13], skb->len); ++ ++ if (unlikely(is_multicast_ether_addr(eth->h_dest))) { ++ /* broadcast pkt need to be forwared to upper layer and resent ++ on wireless interface */ ++ resend = true; ++ } else { ++ /* unicast pkt for STA inside the BSS, no need to forward to upper ++ layer simply resend on wireless interface */ ++ if (hw_rxhdr->flags_dst_idx != RWNX_INVALID_STA) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[hw_rxhdr->flags_dst_idx]; ++ if (sta->valid && (sta->vlan_idx == rwnx_vif->vif_index)) { ++ resend = true; ++ forward = false; ++ } ++ } ++ } ++ ++ if (resend) ++ rwnx_rx_data_skb_resend(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ ++ if (forward) { ++ if (is_qos && hw_rxhdr->flags_need_reord) ++ reord_process_unit((struct aicwf_rx_priv *)rx_priv, skb, seq_num, tid, 1, hw_rxhdr->flags_is_amsdu); ++ else if (is_qos && !hw_rxhdr->flags_need_reord) { ++ reord_flush_tid((struct aicwf_rx_priv *)rx_priv, skb, tid); ++ rwnx_rx_data_skb_forward(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } else ++ rwnx_rx_data_skb_forward(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } else if(resend) { ++ if (is_qos && hw_rxhdr->flags_need_reord) ++ reord_process_unit((struct aicwf_rx_priv *)rx_priv, skb, seq_num, tid, 0, hw_rxhdr->flags_is_amsdu); ++ else if (is_qos && !hw_rxhdr->flags_need_reord) { ++ reord_flush_tid((struct aicwf_rx_priv *)rx_priv, skb, tid); ++ dev_kfree_skb(skb); ++ } ++ }else ++ dev_kfree_skb(skb); ++#else ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr)) ++ dev_kfree_skb(skb); ++#endif ++ } ++#else ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr)) ++ dev_kfree_skb(skb); ++#endif ++ } ++ } ++ ++end: ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h +new file mode 100644 +index 000000000000..b831bc8e4012 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h +@@ -0,0 +1,396 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_rx.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_RX_H_ ++#define _RWNX_RX_H_ ++ ++#include "aicwf_txrxif.h" ++ ++#define SERVER_PORT 67 ++#define CLIENT_PORT 68 ++#define DHCP_MAGIC 0x63825363 ++#define DHCP_ACK 5 ++#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ ++#define DHCP_OPTION_END 255 ++ ++enum rx_status_bits { ++ /// The buffer can be forwarded to the networking stack ++ RX_STAT_FORWARD = 1 << 0, ++ /// A new buffer has to be allocated ++ RX_STAT_ALLOC = 1 << 1, ++ /// The buffer has to be deleted ++ RX_STAT_DELETE = 1 << 2, ++ /// The length of the buffer has to be updated ++ RX_STAT_LEN_UPDATE = 1 << 3, ++ /// The length in the Ethernet header has to be updated ++ RX_STAT_ETH_LEN_UPDATE = 1 << 4, ++ /// Simple copy ++ RX_STAT_COPY = 1 << 5, ++ /// Spurious frame (inform upper layer and discard) ++ RX_STAT_SPURIOUS = 1 << 6, ++ /// packet for monitor interface ++ RX_STAT_MONITOR = 1 << 7, ++}; ++ ++ ++/* ++ * Decryption status subfields. ++ * { ++ */ ++#define RWNX_RX_HD_DECR_UNENC 0 // ENCRYPTION TYPE NONE ++#define RWNX_RX_HD_DECR_WEP 1 // ENCRYPTION TYPE WEP ++#define RWNX_RX_HD_DECR_TKIP 2 // ENCRYPTION TYPE TKIP ++#define RWNX_RX_HD_DECR_CCMP128 3 // ENCRYPTION TYPE CCMP128 ++#define RWNX_RX_HD_DECR_CCMP256 4 // ENCRYPTION TYPE CCMP256 ++#define RWNX_RX_HD_DECR_GCMP128 5 // ENCRYPTION TYPE GCMP128 ++#define RWNX_RX_HD_DECR_GCMP256 6 // ENCRYPTION TYPE GCMP256 ++#define RWNX_RX_HD_DECR_WAPI 7 // ENCRYPTION TYPE WAPI ++// @} ++ ++//#ifdef CONFIG_RWNX_MON_DATA ++#if 0 ++#define RX_MACHDR_BACKUP_LEN 64 ++#endif ++ ++struct rx_vector_1_old { ++ /** Receive Vector 1a */ ++ u32 leg_length :12; ++ u32 leg_rate : 4; ++ u32 ht_length :16; ++ ++ /** Receive Vector 1b */ ++ u32 _ht_length : 4; // FIXME ++ u32 short_gi : 1; ++ u32 stbc : 2; ++ u32 smoothing : 1; ++ u32 mcs : 7; ++ u32 pre_type : 1; ++ u32 format_mod : 3; ++ u32 ch_bw : 2; ++ u32 n_sts : 3; ++ u32 lsig_valid : 1; ++ u32 sounding : 1; ++ u32 num_extn_ss : 2; ++ u32 aggregation : 1; ++ u32 fec_coding : 1; ++ u32 dyn_bw : 1; ++ u32 doze_not_allowed : 1; ++ ++ /** Receive Vector 1c */ ++ u32 antenna_set : 8; ++ u32 partial_aid : 9; ++ u32 group_id : 6; ++ u32 first_user : 1; ++ s32 rssi1 : 8; ++ ++ /** Receive Vector 1d */ ++ s32 rssi2 : 8; ++ s32 rssi3 : 8; ++ s32 rssi4 : 8; ++ u32 reserved_1d : 8; ++}; ++ ++struct rx_leg_vect { ++ u8 dyn_bw_in_non_ht : 1; ++ u8 chn_bw_in_non_ht : 2; ++ u8 rsvd_nht : 4; ++ u8 lsig_valid : 1; ++} __packed; ++ ++struct rx_ht_vect { ++ u16 sounding : 1; ++ u16 smoothing : 1; ++ u16 short_gi : 1; ++ u16 aggregation : 1; ++ u16 stbc : 1; ++ u16 num_extn_ss : 2; ++ u16 lsig_valid : 1; ++ u16 mcs : 7; ++ u16 fec : 1; ++ u16 length :16; ++} __packed; ++ ++struct rx_vht_vect { ++ u8 sounding : 1; ++ u8 beamformed : 1; ++ u8 short_gi : 1; ++ u8 rsvd_vht1 : 1; ++ u8 stbc : 1; ++ u8 doze_not_allowed : 1; ++ u8 first_user : 1; ++ u8 rsvd_vht2 : 1; ++ u16 partial_aid : 9; ++ u16 group_id : 6; ++ u16 rsvd_vht3 : 1; ++ u32 mcs : 4; ++ u32 nss : 3; ++ u32 fec : 1; ++ u32 length :20; ++ u32 rsvd_vht4 : 4; ++} __packed; ++ ++struct rx_he_vect { ++ u8 sounding : 1; ++ u8 beamformed : 1; ++ u8 gi_type : 2; ++ u8 stbc : 1; ++ u8 rsvd_he1 : 3; ++ ++ u8 uplink_flag : 1; ++ u8 beam_change : 1; ++ u8 dcm : 1; ++ u8 he_ltf_type : 2; ++ u8 doppler : 1; ++ u8 rsvd_he2 : 2; ++ ++ u8 bss_color : 6; ++ u8 rsvd_he3 : 2; ++ ++ u8 txop_duration : 7; ++ u8 rsvd_he4 : 1; ++ ++ u8 pe_duration : 4; ++ u8 spatial_reuse : 4; ++ ++ u8 sig_b_comp_mode : 1; ++ u8 dcm_sig_b : 1; ++ u8 mcs_sig_b : 3; ++ u8 ru_size : 3; ++ ++ u32 mcs : 4; ++ u32 nss : 3; ++ u32 fec : 1; ++ u32 length :20; ++ u32 rsvd_he6 : 4; ++} __packed; ++ ++struct rx_vector_1 { ++ u8 format_mod : 4; ++ u8 ch_bw : 3; ++ u8 pre_type : 1; ++ u8 antenna_set : 8; ++ s32 rssi_leg : 8; ++ u32 leg_length :12; ++ u32 leg_rate : 4; ++ s32 rssi1 : 8; ++ ++ union { ++ struct rx_leg_vect leg; ++ struct rx_ht_vect ht; ++ struct rx_vht_vect vht; ++ struct rx_he_vect he; ++ }; ++} __packed; ++ ++struct rx_vector_2_old { ++ /** Receive Vector 2a */ ++ u32 rcpi : 8; ++ u32 evm1 : 8; ++ u32 evm2 : 8; ++ u32 evm3 : 8; ++ ++ /** Receive Vector 2b */ ++ u32 evm4 : 8; ++ u32 reserved2b_1 : 8; ++ u32 reserved2b_2 : 8; ++ u32 reserved2b_3 : 8; ++ ++}; ++ ++struct rx_vector_2 { ++ /** Receive Vector 2a */ ++ u32 rcpi1 : 8; ++ u32 rcpi2 : 8; ++ u32 rcpi3 : 8; ++ u32 rcpi4 : 8; ++ ++ /** Receive Vector 2b */ ++ u32 evm1 : 8; ++ u32 evm2 : 8; ++ u32 evm3 : 8; ++ u32 evm4 : 8; ++}; ++ ++struct phy_channel_info_desc { ++ /** PHY channel information 1 */ ++ u32 phy_band : 8; ++ u32 phy_channel_type : 8; ++ u32 phy_prim20_freq : 16; ++ /** PHY channel information 2 */ ++ u32 phy_center1_freq : 16; ++ u32 phy_center2_freq : 16; ++}; ++ ++struct hw_vect { ++ /** Total length for the MPDU transfer */ ++ u32 len :16; ++ ++ u32 reserved : 8;//data type is included ++ /** AMPDU Status Information */ ++ u32 mpdu_cnt : 6; ++ u32 ampdu_cnt : 2; ++ ++ /** TSF Low */ ++ __le32 tsf_lo; ++ /** TSF High */ ++ __le32 tsf_hi; ++ ++ /** Receive Vector 1 */ ++ struct rx_vector_1 rx_vect1; ++ /** Receive Vector 2 */ ++ struct rx_vector_2 rx_vect2; ++ ++ /** Status **/ ++ u32 rx_vect2_valid : 1; ++ u32 resp_frame : 1; ++ /** Decryption Status */ ++ u32 decr_status : 3; ++ u32 rx_fifo_oflow : 1; ++ ++ /** Frame Unsuccessful */ ++ u32 undef_err : 1; ++ u32 phy_err : 1; ++ u32 fcs_err : 1; ++ u32 addr_mismatch : 1; ++ u32 ga_frame : 1; ++ u32 current_ac : 2; ++ ++ u32 frm_successful_rx : 1; ++ /** Descriptor Done */ ++ u32 desc_done_rx : 1; ++ /** Key Storage RAM Index */ ++ u32 key_sram_index : 10; ++ /** Key Storage RAM Index Valid */ ++ u32 key_sram_v : 1; ++ u32 type : 2; ++ u32 subtype : 4; ++}; ++ ++//#ifdef CONFIG_RWNX_MON_DATA ++#if 0 ++/// MAC header backup descriptor ++struct mon_machdrdesc { ++ /// Length of the buffer ++ u32 buf_len; ++ /// Buffer containing mac header, LLC and SNAP ++ u8 buffer[RX_MACHDR_BACKUP_LEN]; ++}; ++#endif ++ ++struct hw_rxhdr { ++ /** RX vector */ ++ struct hw_vect hwvect; ++ ++ /** PHY channel information */ ++ struct phy_channel_info_desc phy_info; ++ ++ /** RX flags */ ++ u32 flags_is_amsdu : 1; ++ u32 flags_is_80211_mpdu: 1; ++ u32 flags_is_4addr : 1; ++ u32 flags_new_peer : 1; ++#if defined(AICWF_SDIO_SUPPORT) || defined(AICWF_USB_SUPPORT) ++ u32 flags_user_prio : 1; // aic: fw not fill any more ++ u32 flags_need_reord : 1; ++ u32 flags_upload : 1; ++#else ++ u32 flags_user_prio : 3; ++#endif ++#ifndef AICWF_RX_REORDER ++ u32 flags_rsvd0 : 1; ++#else ++ u32 is_monitor_vif : 1; ++#endif ++ u32 flags_vif_idx : 8; // 0xFF if invalid VIF index ++ u32 flags_sta_idx : 8; // 0xFF if invalid STA index ++ u32 flags_dst_idx : 8; // 0xFF if unknown destination STA ++//#ifdef CONFIG_RWNX_MON_DATA ++#if 0 ++ /// MAC header backup descriptor (used only for MSDU when there is a monitor and a data interface) ++ struct mon_machdrdesc mac_hdr_backup; ++#endif ++ /** Pattern indicating if the buffer is available for the driver */ ++ u32 pattern; ++}; ++ ++struct rwnx_legrate { ++ int idx; ++ int rate; ++}; ++ ++extern struct rwnx_legrate legrates_lut[]; ++extern u16 tx_legrates_lut_rate[]; ++ ++struct DHCPInfo { ++ u8 op; ++ u8 htype; ++ u8 hlen; ++ u8 hops; ++ u32 xid; ++ u16 secs; ++ u16 flags; ++ u32 ciaddr; ++ u32 yiaddr; ++ u32 siaddr; ++ u32 giaddr; ++ u8 chaddr[16]; ++ u8 sname[64]; ++ u8 file[128]; ++ u32 cookie; ++ u8 options[308]; /* 312 - cookie */ ++}; ++ ++u8 rwnx_rxdataind_aicwf(struct rwnx_hw *rwnx_hw, void *hostid, void *rx_priv); ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv); ++ ++#ifdef AICWF_ARP_OFFLOAD ++void arpoffload_proc(struct sk_buff *skb, struct rwnx_vif *rwnx_vif); ++#endif ++#ifdef AICWF_RX_REORDER ++struct recv_msdu *reord_rxframe_alloc(spinlock_t *lock, struct list_head *q); ++void reord_rxframe_free(spinlock_t *lock, struct list_head *q, struct list_head *list); ++struct reord_ctrl_info *reord_init_sta(struct aicwf_rx_priv *rx_priv, const u8 *mac_addr); ++void reord_deinit_sta(struct aicwf_rx_priv *rx_priv, struct reord_ctrl_info *reord_info); ++int reord_need_check(struct reord_ctrl *preorder_ctrl, u16 seq_num); ++int reord_rxframe_enqueue(struct reord_ctrl *preorder_ctrl, struct recv_msdu *prframe); ++void reord_timeout_worker(struct work_struct *work); ++int reord_single_frame_ind(struct aicwf_rx_priv *rx_priv, struct recv_msdu *prframe); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void reord_timeout_handler (ulong data); ++#else ++void reord_timeout_handler (struct timer_list *t); ++#endif ++ ++#endif ++void rwnx_rxdata_process_amsdu(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, u8 vif_idx, ++ struct sk_buff_head *list); ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 197) ++struct element { ++ u8 id; ++ u8 datalen; ++ u8 data[]; ++}; ++/* element iteration helpers */ ++#define for_each_element(_elem, _data, _datalen) \ ++ for (_elem = (const struct element *)(_data); \ ++ (const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \ ++ (int)sizeof(*_elem) && \ ++ (const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \ ++ (int)sizeof(*_elem) + _elem->datalen; \ ++ _elem = (const struct element *)(_elem->data + _elem->datalen)) ++ ++#define for_each_element_id(element, _id, data, datalen) \ ++ for_each_element(element, data, datalen) \ ++ if (element->id == (_id)) ++#endif ++#endif ++ ++#endif /* _RWNX_RX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c +new file mode 100644 +index 000000000000..52ffbf64c6fb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c +@@ -0,0 +1,266 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_strs.c ++ * ++ * @brief Miscellaneous debug strings ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "lmac_msg.h" ++static const char *const rwnx_mmid2str[MSG_I(MM_MAX)] = { ++ [MSG_I(MM_RESET_REQ)] = "MM_RESET_REQ", ++ [MSG_I(MM_RESET_CFM)] = "MM_RESET_CFM", ++ [MSG_I(MM_START_REQ)] = "MM_START_REQ", ++ [MSG_I(MM_START_CFM)] = "MM_START_CFM", ++ [MSG_I(MM_VERSION_REQ)] = "MM_VERSION_REQ", ++ [MSG_I(MM_VERSION_CFM)] = "MM_VERSION_CFM", ++ [MSG_I(MM_ADD_IF_REQ)] = "MM_ADD_IF_REQ", ++ [MSG_I(MM_ADD_IF_CFM)] = "MM_ADD_IF_CFM", ++ [MSG_I(MM_REMOVE_IF_REQ)] = "MM_REMOVE_IF_REQ", ++ [MSG_I(MM_REMOVE_IF_CFM)] = "MM_REMOVE_IF_CFM", ++ [MSG_I(MM_STA_ADD_REQ)] = "MM_STA_ADD_REQ", ++ [MSG_I(MM_STA_ADD_CFM)] = "MM_STA_ADD_CFM", ++ [MSG_I(MM_STA_DEL_REQ)] = "MM_STA_DEL_REQ", ++ [MSG_I(MM_STA_DEL_CFM)] = "MM_STA_DEL_CFM", ++ [MSG_I(MM_SET_FILTER_REQ)] = "MM_SET_FILTER_REQ", ++ [MSG_I(MM_SET_FILTER_CFM)] = "MM_SET_FILTER_CFM", ++ [MSG_I(MM_SET_CHANNEL_REQ)] = "MM_SET_CHANNEL_REQ", ++ [MSG_I(MM_SET_CHANNEL_CFM)] = "MM_SET_CHANNEL_CFM", ++ [MSG_I(MM_SET_DTIM_REQ)] = "MM_SET_DTIM_REQ", ++ [MSG_I(MM_SET_DTIM_CFM)] = "MM_SET_DTIM_CFM", ++ [MSG_I(MM_SET_BEACON_INT_REQ)] = "MM_SET_BEACON_INT_REQ", ++ [MSG_I(MM_SET_BEACON_INT_CFM)] = "MM_SET_BEACON_INT_CFM", ++ [MSG_I(MM_SET_BASIC_RATES_REQ)] = "MM_SET_BASIC_RATES_REQ", ++ [MSG_I(MM_SET_BASIC_RATES_CFM)] = "MM_SET_BASIC_RATES_CFM", ++ [MSG_I(MM_SET_BSSID_REQ)] = "MM_SET_BSSID_REQ", ++ [MSG_I(MM_SET_BSSID_CFM)] = "MM_SET_BSSID_CFM", ++ [MSG_I(MM_SET_EDCA_REQ)] = "MM_SET_EDCA_REQ", ++ [MSG_I(MM_SET_EDCA_CFM)] = "MM_SET_EDCA_CFM", ++ [MSG_I(MM_SET_MODE_REQ)] = "MM_SET_MODE_REQ", ++ [MSG_I(MM_SET_MODE_CFM)] = "MM_SET_MODE_CFM", ++ [MSG_I(MM_SET_VIF_STATE_REQ)] = "MM_SET_VIF_STATE_REQ", ++ [MSG_I(MM_SET_VIF_STATE_CFM)] = "MM_SET_VIF_STATE_CFM", ++ [MSG_I(MM_SET_SLOTTIME_REQ)] = "MM_SET_SLOTTIME_REQ", ++ [MSG_I(MM_SET_SLOTTIME_CFM)] = "MM_SET_SLOTTIME_CFM", ++ [MSG_I(MM_SET_IDLE_REQ)] = "MM_SET_IDLE_REQ", ++ [MSG_I(MM_SET_IDLE_CFM)] = "MM_SET_IDLE_CFM", ++ [MSG_I(MM_KEY_ADD_REQ)] = "MM_KEY_ADD_REQ", ++ [MSG_I(MM_KEY_ADD_CFM)] = "MM_KEY_ADD_CFM", ++ [MSG_I(MM_KEY_DEL_REQ)] = "MM_KEY_DEL_REQ", ++ [MSG_I(MM_KEY_DEL_CFM)] = "MM_KEY_DEL_CFM", ++ [MSG_I(MM_BA_ADD_REQ)] = "MM_BA_ADD_REQ", ++ [MSG_I(MM_BA_ADD_CFM)] = "MM_BA_ADD_CFM", ++ [MSG_I(MM_BA_DEL_REQ)] = "MM_BA_DEL_REQ", ++ [MSG_I(MM_BA_DEL_CFM)] = "MM_BA_DEL_CFM", ++ [MSG_I(MM_PRIMARY_TBTT_IND)] = "MM_PRIMARY_TBTT_IND", ++ [MSG_I(MM_SECONDARY_TBTT_IND)] = "MM_SECONDARY_TBTT_IND", ++ [MSG_I(MM_SET_POWER_REQ)] = "MM_SET_POWER_REQ", ++ [MSG_I(MM_SET_POWER_CFM)] = "MM_SET_POWER_CFM", ++ [MSG_I(MM_DBG_TRIGGER_REQ)] = "MM_DBG_TRIGGER_REQ", ++ [MSG_I(MM_SET_PS_MODE_REQ)] = "MM_SET_PS_MODE_REQ", ++ [MSG_I(MM_SET_PS_MODE_CFM)] = "MM_SET_PS_MODE_CFM", ++ [MSG_I(MM_CHAN_CTXT_ADD_REQ)] = "MM_CHAN_CTXT_ADD_REQ", ++ [MSG_I(MM_CHAN_CTXT_ADD_CFM)] = "MM_CHAN_CTXT_ADD_CFM", ++ [MSG_I(MM_CHAN_CTXT_DEL_REQ)] = "MM_CHAN_CTXT_DEL_REQ", ++ [MSG_I(MM_CHAN_CTXT_DEL_CFM)] = "MM_CHAN_CTXT_DEL_CFM", ++ [MSG_I(MM_CHAN_CTXT_LINK_REQ)] = "MM_CHAN_CTXT_LINK_REQ", ++ [MSG_I(MM_CHAN_CTXT_LINK_CFM)] = "MM_CHAN_CTXT_LINK_CFM", ++ [MSG_I(MM_CHAN_CTXT_UNLINK_REQ)] = "MM_CHAN_CTXT_UNLINK_REQ", ++ [MSG_I(MM_CHAN_CTXT_UNLINK_CFM)] = "MM_CHAN_CTXT_UNLINK_CFM", ++ [MSG_I(MM_CHAN_CTXT_UPDATE_REQ)] = "MM_CHAN_CTXT_UPDATE_REQ", ++ [MSG_I(MM_CHAN_CTXT_UPDATE_CFM)] = "MM_CHAN_CTXT_UPDATE_CFM", ++ [MSG_I(MM_CHAN_CTXT_SCHED_REQ)] = "MM_CHAN_CTXT_SCHED_REQ", ++ [MSG_I(MM_CHAN_CTXT_SCHED_CFM)] = "MM_CHAN_CTXT_SCHED_CFM", ++ [MSG_I(MM_BCN_CHANGE_REQ)] = "MM_BCN_CHANGE_REQ", ++ [MSG_I(MM_BCN_CHANGE_CFM)] = "MM_BCN_CHANGE_CFM", ++ [MSG_I(MM_TIM_UPDATE_REQ)] = "MM_TIM_UPDATE_REQ", ++ [MSG_I(MM_TIM_UPDATE_CFM)] = "MM_TIM_UPDATE_CFM", ++ [MSG_I(MM_CONNECTION_LOSS_IND)] = "MM_CONNECTION_LOSS_IND", ++ [MSG_I(MM_CHANNEL_SWITCH_IND)] = "MM_CHANNEL_SWITCH_IND", ++ [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = "MM_CHANNEL_PRE_SWITCH_IND", ++ [MSG_I(MM_REMAIN_ON_CHANNEL_REQ)] = "MM_REMAIN_ON_CHANNEL_REQ", ++ [MSG_I(MM_REMAIN_ON_CHANNEL_CFM)] = "MM_REMAIN_ON_CHANNEL_CFM", ++ [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = "MM_REMAIN_ON_CHANNEL_EXP_IND", ++ [MSG_I(MM_PS_CHANGE_IND)] = "MM_PS_CHANGE_IND", ++ [MSG_I(MM_TRAFFIC_REQ_IND)] = "MM_TRAFFIC_REQ_IND", ++ [MSG_I(MM_SET_PS_OPTIONS_REQ)] = "MM_SET_PS_OPTIONS_REQ", ++ [MSG_I(MM_SET_PS_OPTIONS_CFM)] = "MM_SET_PS_OPTIONS_CFM", ++ [MSG_I(MM_P2P_VIF_PS_CHANGE_IND)] = "MM_P2P_VIF_PS_CHANGE_IND", ++ [MSG_I(MM_CSA_COUNTER_IND)] = "MM_CSA_COUNTER_IND", ++ [MSG_I(MM_CHANNEL_SURVEY_IND)] = "MM_CHANNEL_SURVEY_IND", ++ [MSG_I(MM_SET_P2P_NOA_REQ)] = "MM_SET_P2P_NOA_REQ", ++ [MSG_I(MM_SET_P2P_OPPPS_REQ)] = "MM_SET_P2P_OPPPS_REQ", ++ [MSG_I(MM_SET_P2P_NOA_CFM)] = "MM_SET_P2P_NOA_CFM", ++ [MSG_I(MM_SET_P2P_OPPPS_CFM)] = "MM_SET_P2P_OPPPS_CFM", ++ [MSG_I(MM_CFG_RSSI_REQ)] = "MM_CFG_RSSI_REQ", ++ [MSG_I(MM_RSSI_STATUS_IND)] = "MM_RSSI_STATUS_IND", ++ [MSG_I(MM_CSA_FINISH_IND)] = "MM_CSA_FINISH_IND", ++ [MSG_I(MM_CSA_TRAFFIC_IND)] = "MM_CSA_TRAFFIC_IND", ++ [MSG_I(MM_MU_GROUP_UPDATE_REQ)] = "MM_MU_GROUP_UPDATE_REQ", ++ [MSG_I(MM_MU_GROUP_UPDATE_CFM)] = "MM_MU_GROUP_UPDATE_CFM", ++ ++ [MSG_I(MM_SET_ARPOFFLOAD_REQ)] = "MM_SET_ARPOFFLOAD_REQ", ++ [MSG_I(MM_SET_ARPOFFLOAD_CFM)] = "MM_SET_ARPOFFLOAD_CFM", ++ [MSG_I(MM_SET_AGG_DISABLE_REQ)] = "MM_SET_AGG_DISABLE_REQ", ++ [MSG_I(MM_SET_AGG_DISABLE_CFM)] = "MM_SET_AGG_DISABLE_CFM", ++ [MSG_I(MM_SET_COEX_REQ)] = "MM_SET_COEX_REQ", ++ [MSG_I(MM_SET_COEX_CFM)] = "MM_SET_COEX_CFM", ++ [MSG_I(MM_SET_RF_CONFIG_REQ)] = "MM_SET_RF_CONFIG_REQ", ++ [MSG_I(MM_SET_RF_CONFIG_CFM)] = "MM_SET_RF_CONFIG_CFM", ++ [MSG_I(MM_SET_RF_CALIB_REQ)] = "MM_SET_RF_CALIB_REQ", ++ [MSG_I(MM_SET_RF_CALIB_CFM)] = "MM_SET_RF_CALIB_CFM", ++ ++ [MSG_I(MM_GET_MAC_ADDR_REQ)] = "MM_GET_MAC_ADDR_REQ", ++ [MSG_I(MM_GET_MAC_ADDR_CFM)] = "MM_GET_MAC_ADDR_CFM", ++ [MSG_I(MM_GET_STA_INFO_REQ)] = "MM_GET_STA_INFO_REQ", ++ [MSG_I(MM_GET_STA_INFO_CFM)] = "MM_GET_STA_INFO_CFM", ++ [MSG_I(MM_SET_TXPWR_IDX_LVL_REQ)] = "MM_SET_TXPWR_IDX_LVL_REQ", ++ [MSG_I(MM_SET_TXPWR_IDX_LVL_CFM)] = "MM_SET_TXPWR_IDX_LVL_CFM", ++ [MSG_I(MM_SET_TXPWR_OFST_REQ)] = "MM_SET_TXPWR_OFST_REQ", ++ [MSG_I(MM_SET_TXPWR_OFST_CFM)] = "MM_SET_TXPWR_OFST_CFM", ++ [MSG_I(MM_SET_STACK_START_REQ)] = "MM_SET_STACK_START_REQ", ++ [MSG_I(MM_SET_STACK_START_CFM)] = "MM_SET_STACK_START_CFM", ++ [MSG_I(MM_APM_STALOSS_IND)] = "MM_APM_STALOSS_IND", ++ [MSG_I(MM_SET_VENDOR_HWCONFIG_REQ)] = "MM_SET_VENDOR_HWCONFIG_REQ", ++ [MSG_I(MM_SET_VENDOR_HWCONFIG_CFM)] = "MM_SET_VENDOR_HWCONFIG_CFM", ++ [MSG_I(MM_GET_FW_VERSION_REQ)] = "MM_GET_FW_VERSION_REQ", ++ [MSG_I(MM_GET_FW_VERSION_CFM)] = "MM_GET_FW_VERSION_CFM", ++ [MSG_I(MM_SET_RESUME_RESTORE_REQ)] = "MM_SET_RESUME_RESTORE_REQ", ++ [MSG_I(MM_SET_RESUME_RESTORE_CFM)] = "MM_SET_RESUME_RESTORE_CFM", ++ [MSG_I(MM_GET_WIFI_DISABLE_REQ)] = "MM_GET_WIFI_DISABLE_REQ", ++ [MSG_I(MM_GET_WIFI_DISABLE_CFM)] = "MM_GET_WIFI_DISABLE_CFM", ++ [MSG_I(MM_CFG_RSSI_CFM)] = "MM_CFG_RSSI_CFM", ++}; ++ ++static const char *const rwnx_dbgid2str[MSG_I(DBG_MAX)] = { ++ [MSG_I(DBG_MEM_READ_REQ)] = "DBG_MEM_READ_REQ", ++ [MSG_I(DBG_MEM_READ_CFM)] = "DBG_MEM_READ_CFM", ++ [MSG_I(DBG_MEM_WRITE_REQ)] = "DBG_MEM_WRITE_REQ", ++ [MSG_I(DBG_MEM_WRITE_CFM)] = "DBG_MEM_WRITE_CFM", ++ [MSG_I(DBG_SET_MOD_FILTER_REQ)] = "DBG_SET_MOD_FILTER_REQ", ++ [MSG_I(DBG_SET_MOD_FILTER_CFM)] = "DBG_SET_MOD_FILTER_CFM", ++ [MSG_I(DBG_SET_SEV_FILTER_REQ)] = "DBG_SET_SEV_FILTER_REQ", ++ [MSG_I(DBG_SET_SEV_FILTER_CFM)] = "DBG_SET_SEV_FILTER_CFM", ++ [MSG_I(DBG_ERROR_IND)] = "DBG_ERROR_IND", ++ [MSG_I(DBG_GET_SYS_STAT_REQ)] = "DBG_GET_SYS_STAT_REQ", ++ [MSG_I(DBG_GET_SYS_STAT_CFM)] = "DBG_GET_SYS_STAT_CFM", ++}; ++ ++static const char *const rwnx_scanid2str[MSG_I(SCAN_MAX)] = { ++ [MSG_I(SCAN_START_REQ)] = "SCAN_START_REQ", ++ [MSG_I(SCAN_START_CFM)] = "SCAN_START_CFM", ++ [MSG_I(SCAN_DONE_IND)] = "SCAN_DONE_IND", ++}; ++ ++static const char *const rwnx_tdlsid2str[MSG_I(TDLS_MAX)] = { ++ [MSG_I(TDLS_CHAN_SWITCH_CFM)] = "TDLS_CHAN_SWITCH_CFM", ++ [MSG_I(TDLS_CHAN_SWITCH_REQ)] = "TDLS_CHAN_SWITCH_REQ", ++ [MSG_I(TDLS_CHAN_SWITCH_IND)] = "TDLS_CHAN_SWITCH_IND", ++ [MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = "TDLS_CHAN_SWITCH_BASE_IND", ++ [MSG_I(TDLS_CANCEL_CHAN_SWITCH_REQ)] = "TDLS_CANCEL_CHAN_SWITCH_REQ", ++ [MSG_I(TDLS_CANCEL_CHAN_SWITCH_CFM)] = "TDLS_CANCEL_CHAN_SWITCH_CFM", ++ [MSG_I(TDLS_PEER_PS_IND)] = "TDLS_PEER_PS_IND", ++ [MSG_I(TDLS_PEER_TRAFFIC_IND_REQ)] = "TDLS_PEER_TRAFFIC_IND_REQ", ++ [MSG_I(TDLS_PEER_TRAFFIC_IND_CFM)] = "TDLS_PEER_TRAFFIC_IND_CFM", ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++static const char *const rwnx_scanuid2str[MSG_I(SCANU_MAX)] = { ++ [MSG_I(SCANU_START_REQ)] = "SCANU_START_REQ", ++ [MSG_I(SCANU_START_CFM)] = "SCANU_START_CFM", ++ [MSG_I(SCANU_JOIN_REQ)] = "SCANU_JOIN_REQ", ++ [MSG_I(SCANU_JOIN_CFM)] = "SCANU_JOIN_CFM", ++ [MSG_I(SCANU_RESULT_IND)] = "SCANU_RESULT_IND", ++ [MSG_I(SCANU_FAST_REQ)] = "SCANU_FAST_REQ", ++ [MSG_I(SCANU_FAST_CFM)] = "SCANU_FAST_CFM", ++ [MSG_I(SCANU_VENDOR_IE_REQ)] = "SCANU_VENDOR_IE_REQ", ++ [MSG_I(SCANU_VENDOR_IE_CFM)] = "SCANU_VENDOR_IE_CFM", ++ [MSG_I(SCANU_START_CFM_ADDTIONAL)] = "SCANU_START_CFM_ADDTIONAL", ++ [MSG_I(SCANU_CANCEL_REQ)] = "SCANU_CANCEL_REQ", ++ [MSG_I(SCANU_CANCEL_CFM)] = "SCANU_CANCEL_CFM", ++}; ++ ++static const char *const rwnx_meid2str[MSG_I(ME_MAX)] = { ++ [MSG_I(ME_CONFIG_REQ)] = "ME_CONFIG_REQ", ++ [MSG_I(ME_CONFIG_CFM)] = "ME_CONFIG_CFM", ++ [MSG_I(ME_CHAN_CONFIG_REQ)] = "ME_CHAN_CONFIG_REQ", ++ [MSG_I(ME_CHAN_CONFIG_CFM)] = "ME_CHAN_CONFIG_CFM", ++ [MSG_I(ME_SET_CONTROL_PORT_REQ)] = "ME_SET_CONTROL_PORT_REQ", ++ [MSG_I(ME_SET_CONTROL_PORT_CFM)] = "ME_SET_CONTROL_PORT_CFM", ++ [MSG_I(ME_TKIP_MIC_FAILURE_IND)] = "ME_TKIP_MIC_FAILURE_IND", ++ [MSG_I(ME_STA_ADD_REQ)] = "ME_STA_ADD_REQ", ++ [MSG_I(ME_STA_ADD_CFM)] = "ME_STA_ADD_CFM", ++ [MSG_I(ME_STA_DEL_REQ)] = "ME_STA_DEL_REQ", ++ [MSG_I(ME_STA_DEL_CFM)] = "ME_STA_DEL_CFM", ++ [MSG_I(ME_TX_CREDITS_UPDATE_IND)]= "ME_TX_CREDITS_UPDATE_IND", ++ [MSG_I(ME_RC_STATS_REQ)] = "ME_RC_STATS_REQ", ++ [MSG_I(ME_RC_STATS_CFM)] = "ME_RC_STATS_CFM", ++ [MSG_I(ME_RC_SET_RATE_REQ)] = "ME_RC_SET_RATE_REQ", ++ [MSG_I(ME_TRAFFIC_IND_REQ)] = "ME_TRAFFIC_IND_REQ", ++ [MSG_I(ME_TRAFFIC_IND_CFM)] = "ME_TRAFFIC_IND_CFM", ++ [MSG_I(ME_SET_PS_MODE_REQ)] = "ME_SET_PS_MODE_REQ", ++ [MSG_I(ME_SET_PS_MODE_CFM)] = "ME_SET_PS_MODE_CFM", ++}; ++ ++static const char *const rwnx_smid2str[MSG_I(SM_MAX)] = { ++ [MSG_I(SM_CONNECT_REQ)] = "SM_CONNECT_REQ", ++ [MSG_I(SM_CONNECT_CFM)] = "SM_CONNECT_CFM", ++ [MSG_I(SM_CONNECT_IND)] = "SM_CONNECT_IND", ++ [MSG_I(SM_DISCONNECT_REQ)] = "SM_DISCONNECT_REQ", ++ [MSG_I(SM_DISCONNECT_CFM)] = "SM_DISCONNECT_CFM", ++ [MSG_I(SM_DISCONNECT_IND)] = "SM_DISCONNECT_IND", ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_IND)] = "SM_EXTERNAL_AUTH_REQUIRED_IND", ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP", ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM", ++}; ++ ++static const char *const rwnx_apmid2str[MSG_I(APM_MAX)] = { ++ [MSG_I(APM_START_REQ)] = "APM_START_REQ", ++ [MSG_I(APM_START_CFM)] = "APM_START_CFM", ++ [MSG_I(APM_STOP_REQ)] = "APM_STOP_REQ", ++ [MSG_I(APM_STOP_CFM)] = "APM_STOP_CFM", ++ [MSG_I(APM_START_CAC_REQ)] = "APM_START_CAC_REQ", ++ [MSG_I(APM_START_CAC_CFM)] = "APM_START_CAC_CFM", ++ [MSG_I(APM_STOP_CAC_REQ)] = "APM_STOP_CAC_REQ", ++ [MSG_I(APM_STOP_CAC_CFM)] = "APM_STOP_CAC_CFM", ++ [MSG_I(APM_SET_BEACON_IE_REQ)] = "APM_SET_BEACON_IE_REQ", ++ [MSG_I(APM_SET_BEACON_IE_CFM)] = "APM_SET_BEACON_IE_CFM", ++}; ++ ++static const char *const rwnx_meshid2str[MSG_I(MESH_MAX)] = { ++ [MSG_I(MESH_START_REQ)] = "MESH_START_REQ", ++ [MSG_I(MESH_START_CFM)] = "MESH_START_CFM", ++ [MSG_I(MESH_STOP_REQ)] = "MESH_STOP_REQ", ++ [MSG_I(MESH_STOP_CFM)] = "MESH_STOP_CFM", ++ [MSG_I(MESH_UPDATE_REQ)] = "MESH_UPDATE_REQ", ++ [MSG_I(MESH_UPDATE_CFM)] = "MESH_UPDATE_CFM", ++ [MSG_I(MESH_PATH_CREATE_REQ)] = "MESH_PATH_CREATE_REQ", ++ [MSG_I(MESH_PATH_CREATE_CFM)] = "MESH_PATH_CREATE_CFM", ++ [MSG_I(MESH_PATH_UPDATE_REQ)] = "MESH_PATH_UPDATE_REQ", ++ [MSG_I(MESH_PATH_UPDATE_CFM)] = "MESH_PATH_UPDATE_CFM", ++ [MSG_I(MESH_PROXY_ADD_REQ)] = "MESH_PROXY_ADD_REQ", ++ [MSG_I(MESH_PEER_UPDATE_IND)] = "MESH_PEER_UPDATE_IND", ++ [MSG_I(MESH_PATH_UPDATE_IND)] = "MESH_PATH_UPDATE_IND", ++ [MSG_I(MESH_PROXY_UPDATE_IND)] = "MESH_PROXY_UPDATE_IND", ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++const char *const *rwnx_id2str[TASK_LAST_EMB + 1] = { ++ [TASK_MM] = rwnx_mmid2str, ++ [TASK_DBG] = rwnx_dbgid2str, ++ [TASK_SCAN] = rwnx_scanid2str, ++ [TASK_TDLS] = rwnx_tdlsid2str, ++#ifdef CONFIG_RWNX_FULLMAC ++ [TASK_SCANU] = rwnx_scanuid2str, ++ [TASK_ME] = rwnx_meid2str, ++ [TASK_SM] = rwnx_smid2str, ++ [TASK_APM] = rwnx_apmid2str, ++ [TASK_MESH] = rwnx_meshid2str, ++#endif ++}; +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h +new file mode 100644 +index 000000000000..7dc83aba8bea +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h +@@ -0,0 +1,31 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_strs.h ++ * ++ * @brief Miscellaneous debug strings ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_STRS_H_ ++#define _RWNX_STRS_H_ ++ ++#ifdef CONFIG_RWNX_FHOST ++ ++#define RWNX_ID2STR(tag) "Cmd" ++ ++#else ++#include "lmac_msg.h" ++ ++#define RWNX_ID2STR(tag) (((MSG_T(tag) < ARRAY_SIZE(rwnx_id2str)) && \ ++ (rwnx_id2str[MSG_T(tag)]) && \ ++ ((rwnx_id2str[MSG_T(tag)])[MSG_I(tag)])) ? \ ++ (rwnx_id2str[MSG_T(tag)])[MSG_I(tag)] : "unknown") ++ ++extern const char *const *rwnx_id2str[TASK_LAST_EMB + 1]; ++#endif /* CONFIG_RWNX_FHOST */ ++ ++#endif /* _RWNX_STRS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c +new file mode 100644 +index 000000000000..7d9afb935ac7 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c +@@ -0,0 +1,786 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tx.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++/** ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_tdls.h" ++#include "rwnx_compat.h" ++ ++/** ++ * FUNCTION DEFINITIONS ++ ****************************************************************************** ++ */ ++ ++static u16 ++rwnx_get_tdls_sta_capab(struct rwnx_vif *rwnx_vif, u16 status_code) ++{ ++ u16 capab = 0; ++ ++ /* The capability will be 0 when sending a failure code */ ++ if (status_code != 0) ++ return capab; ++ ++ if (rwnx_vif->sta.ap->band != NL80211_BAND_2GHZ) ++ return capab; ++ ++ capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; ++ capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; ++ ++ return capab; ++} ++ ++static int ++rwnx_tdls_prepare_encap_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, struct sk_buff *skb) ++{ ++ struct ieee80211_tdls_data *tf; ++ tf = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_data) - sizeof(tf->u)); ++ ++ // set eth header ++ memcpy(tf->da, peer, ETH_ALEN); ++ memcpy(tf->sa, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ tf->ether_type = cpu_to_be16(ETH_P_TDLS); ++ ++ // set common TDLS info ++ tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; ++ tf->category = WLAN_CATEGORY_TDLS; ++ tf->action_code = action_code; ++ ++ // set action specific TDLS info ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ skb_put(skb, sizeof(tf->u.setup_req)); ++ tf->u.setup_req.dialog_token = dialog_token; ++ tf->u.setup_req.capability = ++ cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code)); ++ break; ++ ++ case WLAN_TDLS_SETUP_RESPONSE: ++ skb_put(skb, sizeof(tf->u.setup_resp)); ++ tf->u.setup_resp.status_code = cpu_to_le16(status_code); ++ tf->u.setup_resp.dialog_token = dialog_token; ++ tf->u.setup_resp.capability = ++ cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code)); ++ break; ++ ++ case WLAN_TDLS_SETUP_CONFIRM: ++ skb_put(skb, sizeof(tf->u.setup_cfm)); ++ tf->u.setup_cfm.status_code = cpu_to_le16(status_code); ++ tf->u.setup_cfm.dialog_token = dialog_token; ++ break; ++ ++ case WLAN_TDLS_TEARDOWN: ++ skb_put(skb, sizeof(tf->u.teardown)); ++ tf->u.teardown.reason_code = cpu_to_le16(status_code); ++ break; ++ ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ skb_put(skb, sizeof(tf->u.discover_req)); ++ tf->u.discover_req.dialog_token = dialog_token; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++rwnx_prep_tdls_direct(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt; ++ ++ mgmt = (void *)skb_put(skb, 24); ++ memset(mgmt, 0, 24); ++ memcpy(mgmt->da, peer, ETH_ALEN); ++ memcpy(mgmt->sa, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ memcpy(mgmt->bssid, rwnx_vif->sta.ap->mac_addr, ETH_ALEN); ++ ++ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | ++ IEEE80211_STYPE_ACTION); ++ ++ switch (action_code) { ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); ++ mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; ++ mgmt->u.action.u.tdls_discover_resp.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES; ++ mgmt->u.action.u.tdls_discover_resp.dialog_token = dialog_token; ++ mgmt->u.action.u.tdls_discover_resp.capability = ++ cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++rwnx_add_srates_ie(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ u8 i, rates, *pos; ++ int rate; ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ rates = 8; ++ ++ if (skb_tailroom(skb) < rates + 2) ++ return -ENOMEM; ++ ++ pos = skb_put(skb, rates + 2); ++ *pos++ = WLAN_EID_SUPP_RATES; ++ *pos++ = rates; ++ for (i = 0; i < rates; i++) { ++ rate = rwnx_band_2GHz->bitrates[i].bitrate; ++ rate = DIV_ROUND_UP(rate, 5); ++ *pos++ = (u8)rate; ++ } ++ ++ return 0; ++} ++ ++static int ++rwnx_add_ext_srates_ie(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ u8 i, exrates, *pos; ++ int rate; ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ exrates = rwnx_band_2GHz->n_bitrates - 8; ++ ++ if (skb_tailroom(skb) < exrates + 2) ++ return -ENOMEM; ++ ++ pos = skb_put(skb, exrates + 2); ++ *pos++ = WLAN_EID_EXT_SUPP_RATES; ++ *pos++ = exrates; ++ for (i = 8; i < (8+exrates); i++) { ++ rate = rwnx_band_2GHz->bitrates[i].bitrate; ++ rate = DIV_ROUND_UP(rate, 5); ++ *pos++ = (u8)rate; ++ } ++ ++ return 0; ++} ++ ++static void ++rwnx_tdls_add_supp_channels(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ /* ++ * Add possible channels for TDLS. These are channels that are allowed ++ * to be active. ++ */ ++ u8 subband_cnt = 0; ++ u8 *pos_subband; ++ u8 *pos = skb_put(skb, 2); ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ]; ++ ++ *pos++ = WLAN_EID_SUPPORTED_CHANNELS; ++ ++ /* ++ * 5GHz and 2GHz channels numbers can overlap. Ignore this for now, as ++ * this doesn't happen in real world scenarios. ++ */ ++ ++ /* 2GHz, with 5MHz spacing */ ++ pos_subband = skb_put(skb, 2); ++ if (rwnx_band_2GHz->n_channels > 0) { ++ *pos_subband++ = ieee80211_frequency_to_channel(rwnx_band_2GHz->channels[0].center_freq); ++ *pos_subband++ = rwnx_band_2GHz->n_channels; ++ subband_cnt++; ++ } ++ ++ /* 5GHz, with 20MHz spacing */ ++ pos_subband = skb_put(skb, 2); ++ if (rwnx_hw->band_5g_support) { ++ if (rwnx_band_5GHz->n_channels > 0) { ++ *pos_subband++ = ieee80211_frequency_to_channel(rwnx_band_5GHz->channels[0].center_freq); ++ *pos_subband++ = rwnx_band_5GHz->n_channels; ++ subband_cnt++; ++ } ++ } ++ /* length */ ++ *pos = 2 * subband_cnt; ++} ++ ++static void ++rwnx_tdls_add_ext_capab(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 7); ++ bool chan_switch = rwnx_hw->wiphy->features & ++ NL80211_FEATURE_TDLS_CHANNEL_SWITCH; ++ ++ *pos++ = WLAN_EID_EXT_CAPABILITY; ++ *pos++ = 5; /* len */ ++ *pos++ = 0x0; ++ *pos++ = 0x0; ++ *pos++ = 0x0; ++ *pos++ = WLAN_EXT_CAPA4_TDLS_BUFFER_STA | ++ (chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0); ++ *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; ++} ++ ++static void ++rwnx_add_wmm_info_ie(struct sk_buff *skb, u8 qosinfo) ++{ ++ u8 *pos = (void *)skb_put(skb, 9); ++ ++ *pos++ = WLAN_EID_VENDOR_SPECIFIC; ++ *pos++ = 7; /* len */ ++ *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ ++ *pos++ = 0x50; ++ *pos++ = 0xf2; ++ *pos++ = 2; /* WME */ ++ *pos++ = 0; /* WME info */ ++ *pos++ = 1; /* WME ver */ ++ *pos++ = qosinfo; /* U-APSD no in use */ ++} ++ ++/* translate numbering in the WMM parameter IE to the mac80211 notation */ ++static u8 rwnx_ac_from_wmm(int ac) ++{ ++ switch (ac) { ++ default: ++ WARN_ON_ONCE(1); ++ __attribute__((__fallthrough__)); ++ case 0: ++ return AC_BE; ++ case 1: ++ return AC_BK; ++ case 2: ++ return AC_VI; ++ case 3: ++ return AC_VO; ++ } ++} ++ ++static void ++rwnx_add_wmm_param_ie(struct sk_buff *skb, u8 acm_bits, u32 *ac_params) ++{ ++ struct ieee80211_wmm_param_ie *wmm; ++ int i, j; ++ u8 cw_min, cw_max; ++ bool acm; ++ ++ wmm = (void *)skb_put(skb, sizeof(struct ieee80211_wmm_param_ie)); ++ memset(wmm, 0, sizeof(*wmm)); ++ ++ wmm->element_id = WLAN_EID_VENDOR_SPECIFIC; ++ wmm->len = sizeof(*wmm) - 2; ++ ++ wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */ ++ wmm->oui[1] = 0x50; ++ wmm->oui[2] = 0xf2; ++ wmm->oui_type = 2; /* WME */ ++ wmm->oui_subtype = 1; /* WME param */ ++ wmm->version = 1; /* WME ver */ ++ wmm->qos_info = 0; /* U-APSD not in use */ ++ ++ /* ++ * Use the EDCA parameters defined for the BSS, or default if the AP ++ * doesn't support it, as mandated by 802.11-2012 section 10.22.4 ++ */ ++ for (i = 0; i < AC_MAX; i++) { ++ j = rwnx_ac_from_wmm(i); ++ cw_min = (ac_params[j] & 0xF0) >> 4; ++ cw_max = (ac_params[j] & 0xF00) >> 8; ++ acm = (acm_bits & (1 << j)) != 0; ++ ++ wmm->ac[i].aci_aifsn = (i << 5) | (acm << 4) | (ac_params[j] & 0xF); ++ wmm->ac[i].cw = (cw_max << 4) | cw_min; ++ wmm->ac[i].txop_limit = (ac_params[j] & 0x0FFFF000) >> 12; ++ } ++} ++ ++static void ++rwnx_tdls_add_oper_classes(struct rwnx_vif *rwnx_vif, struct sk_buff *skb) ++{ ++ u8 *pos; ++ u8 op_class; ++ struct cfg80211_chan_def chan_def; ++ struct ieee80211_channel chan; ++ ++ chan.band = rwnx_vif->sta.ap->band; ++ chan.center_freq = rwnx_vif->sta.ap->center_freq; ++ chan_def.chan = &chan; ++ chan_def.width = rwnx_vif->sta.ap->width; ++ chan_def.center_freq1 = rwnx_vif->sta.ap->center_freq1; ++ chan_def.center_freq2 = rwnx_vif->sta.ap->center_freq2; ++#ifdef CONFIG_GKI ++ if (!rwnx_ieee80211_chandef_to_operating_class(&chan_def, &op_class)) ++#else ++ if (!ieee80211_chandef_to_operating_class(&chan_def, &op_class)) ++#endif ++ return; ++ ++ pos = skb_put(skb, 4); ++ *pos++ = WLAN_EID_SUPPORTED_REGULATORY_CLASSES; ++ *pos++ = 2; /* len */ ++ ++ // current op class ++ *pos++ = op_class; ++ *pos++ = op_class; /* give current operating class as alternate too */ ++ ++ // need to add 5GHz classes? ++} ++ ++static void ++rwnx_ie_build_ht_cap(struct sk_buff *skb, struct ieee80211_sta_ht_cap *ht_cap, ++ u16 cap) ++{ ++ u8 *pos; ++ __le16 tmp; ++ ++ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); ++ *pos++ = WLAN_EID_HT_CAPABILITY; ++ *pos++ = sizeof(struct ieee80211_ht_cap); ++ memset(pos, 0, sizeof(struct ieee80211_ht_cap)); ++ ++ /* capability flags */ ++ tmp = cpu_to_le16(cap); ++ memcpy(pos, &tmp, sizeof(u16)); ++ pos += sizeof(u16); ++ ++ /* AMPDU parameters */ ++ *pos++ = ht_cap->ampdu_factor | ++ (ht_cap->ampdu_density << ++ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); ++ ++ /* MCS set */ ++ memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs)); ++ pos += sizeof(ht_cap->mcs); ++ ++ /* extended capabilities */ ++ pos += sizeof(__le16); ++ ++ /* BF capabilities */ ++ pos += sizeof(__le32); ++ ++ /* antenna selection */ ++ pos += sizeof(u8); ++} ++ ++static void ++rwnx_ie_build_vht_cap(struct sk_buff *skb, struct ieee80211_sta_vht_cap *vht_cap, ++ u32 cap) ++{ ++ u8 *pos; ++ __le32 tmp; ++ ++ pos = skb_put(skb, 14); ++ ++ *pos++ = WLAN_EID_VHT_CAPABILITY; ++ *pos++ = sizeof(struct ieee80211_vht_cap); ++ memset(pos, 0, sizeof(struct ieee80211_vht_cap)); ++ ++ /* capability flags */ ++ tmp = cpu_to_le32(cap); ++ memcpy(pos, &tmp, sizeof(u32)); ++ pos += sizeof(u32); ++ ++ /* VHT MCS set */ ++ memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs)); ++ pos += sizeof(vht_cap->vht_mcs); ++} ++ ++static void ++rwnx_tdls_add_bss_coex_ie(struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 3); ++ ++ *pos++ = WLAN_EID_BSS_COEX_2040; ++ *pos++ = 1; /* len */ ++ ++ *pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST; ++} ++ ++static void ++rwnx_tdls_add_link_ie(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, ++ bool initiator) ++{ ++ struct ieee80211_tdls_lnkie *lnkid; ++ const u8 *init_addr, *rsp_addr; ++ ++ if (initiator) { ++ init_addr = rwnx_hw->wiphy->perm_addr; ++ rsp_addr = peer; ++ } else { ++ init_addr = peer; ++ rsp_addr = rwnx_hw->wiphy->perm_addr; ++ } ++ ++ lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); ++ ++ lnkid->ie_type = WLAN_EID_LINK_ID; ++ lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; ++ ++ memcpy(lnkid->bssid, rwnx_vif->sta.ap->mac_addr, ETH_ALEN); ++ memcpy(lnkid->init_sta, init_addr, ETH_ALEN); ++ memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN); ++} ++ ++static void ++rwnx_tdls_add_aid_ie(struct rwnx_vif *rwnx_vif, struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 4); ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) ++ *pos++ = WLAN_EID_AID; ++ #else ++ *pos++ = 197; ++ #endif ++ *pos++ = 2; /* len */ ++ *pos++ = rwnx_vif->sta.ap->aid; ++} ++ ++static u8 * ++rwnx_ie_build_ht_oper(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, ++ u16 prot_mode) ++{ ++ struct ieee80211_ht_operation *ht_oper; ++ /* Build HT Information */ ++ *pos++ = WLAN_EID_HT_OPERATION; ++ *pos++ = sizeof(struct ieee80211_ht_operation); ++ ht_oper = (struct ieee80211_ht_operation *)pos; ++ ht_oper->primary_chan = ieee80211_frequency_to_channel( ++ rwnx_vif->sta.ap->center_freq); ++ switch (rwnx_vif->sta.ap->width) { ++ case NL80211_CHAN_WIDTH_160: ++ case NL80211_CHAN_WIDTH_80P80: ++ case NL80211_CHAN_WIDTH_80: ++ case NL80211_CHAN_WIDTH_40: ++ if (rwnx_vif->sta.ap->center_freq1 > rwnx_vif->sta.ap->center_freq) ++ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; ++ else ++ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; ++ break; ++ default: ++ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; ++ break; ++ } ++ if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && ++ rwnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20_NOHT && ++ rwnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20) ++ ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; ++ ++ ht_oper->operation_mode = cpu_to_le16(prot_mode); ++ ht_oper->stbc_param = 0x0000; ++ ++ /* It seems that Basic MCS set and Supported MCS set ++ are identical for the first 10 bytes */ ++ memset(&ht_oper->basic_set, 0, 16); ++ memcpy(&ht_oper->basic_set, &ht_cap->mcs, 10); ++ ++ return pos + sizeof(struct ieee80211_ht_operation); ++} ++ ++static u8 * ++rwnx_ie_build_vht_oper(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, ++ u16 prot_mode) ++{ ++ struct ieee80211_vht_operation *vht_oper; ++ /* Build HT Information */ ++ *pos++ = WLAN_EID_VHT_OPERATION; ++ *pos++ = sizeof(struct ieee80211_vht_operation); ++ vht_oper = (struct ieee80211_vht_operation *)pos; ++ ++ switch (rwnx_vif->sta.ap->width) { ++ case NL80211_CHAN_WIDTH_80: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; // Channel Width ++ CCFS0(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0 ++ CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.) ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ; // Channel Width ++ CCFS0(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0 ++ CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.) ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ; // Channel Width ++ CCFS0(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq1); // Channel Center Frequency Segment 0 ++ CCFS1(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq2); // Channel Center Frequency Segment 1 ++ break; ++ default: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT; ++ CCFS0(vht_oper) = 0; ++ CCFS1(vht_oper) = 0; ++ break; ++ } ++ ++ vht_oper->basic_mcs_set = cpu_to_le16(rwnx_hw->mod_params->mcs_map); ++ ++ return pos + sizeof(struct ieee80211_vht_operation); ++ ++} ++ ++static void ++rwnx_tdls_add_setup_start_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, ++ u8 action_code, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len) ++{ ++ enum nl80211_band band = rwnx_vif->sta.ap->band; ++ struct ieee80211_supported_band *sband; ++ struct ieee80211_sta_ht_cap ht_cap; ++ struct ieee80211_sta_vht_cap vht_cap; ++ size_t offset = 0, noffset; ++ u8 *pos; ++ ++ rcu_read_lock(); ++ ++ rwnx_add_srates_ie(rwnx_hw, skb); ++ rwnx_add_ext_srates_ie(rwnx_hw, skb); ++ rwnx_tdls_add_supp_channels(rwnx_hw, skb); ++ rwnx_tdls_add_ext_capab(rwnx_hw, skb); ++ ++ /* add the QoS element if we support it */ ++ if (/*local->hw.queues >= IEEE80211_NUM_ACS &&*/ ++ action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES) ++ rwnx_add_wmm_info_ie(skb, 0); /* no U-APSD */ ++ ++ rwnx_tdls_add_oper_classes(rwnx_vif, skb); ++ ++ /* ++ * with TDLS we can switch channels, and HT-caps are not necessarily ++ * the same on all bands. The specification limits the setup to a ++ * single HT-cap, so use the current band for now. ++ */ ++ sband = rwnx_hw->wiphy->bands[band]; ++ memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); ++ if (((action_code == WLAN_TDLS_SETUP_REQUEST) || ++ (action_code == WLAN_TDLS_SETUP_RESPONSE) || ++ (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES)) && ++ ht_cap.ht_supported /* (!sta || sta->sta.ht_cap.ht_supported)*/) { ++ rwnx_ie_build_ht_cap(skb, &ht_cap, ht_cap.cap); ++ } ++ ++ if (ht_cap.ht_supported && ++ (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) ++ rwnx_tdls_add_bss_coex_ie(skb); ++ ++ rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator); ++ ++ memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); ++ if (vht_cap.vht_supported) { ++ rwnx_tdls_add_aid_ie(rwnx_vif, skb); ++ rwnx_ie_build_vht_cap(skb, &vht_cap, vht_cap.cap); ++ // Operating mode Notification (optional) ++ } ++ ++ /* add any remaining IEs */ ++ if (extra_ies_len) { ++ noffset = extra_ies_len; ++ pos = skb_put(skb, noffset - offset); ++ memcpy(pos, extra_ies + offset, noffset - offset); ++ } ++ ++ rcu_read_unlock(); ++} ++ ++ ++static void ++rwnx_tdls_add_setup_cfm_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len) ++{ ++ struct ieee80211_supported_band *sband; ++ enum nl80211_band band = rwnx_vif->sta.ap->band; ++ struct ieee80211_sta_ht_cap ht_cap; ++ struct ieee80211_sta_vht_cap vht_cap; ++ ++ size_t offset = 0, noffset; ++ struct rwnx_sta *sta, *ap_sta; ++ u8 *pos; ++ ++ rcu_read_lock(); ++ ++ sta = rwnx_get_sta(rwnx_hw, peer); ++ ap_sta = rwnx_vif->sta.ap; ++ if (WARN_ON_ONCE(!sta || !ap_sta)) { ++ rcu_read_unlock(); ++ return; ++ } ++ ++ /* add the QoS param IE if both the peer and we support it */ ++ if (sta->qos) ++ rwnx_add_wmm_param_ie(skb, ap_sta->acm, ap_sta->ac_param); ++ ++ /* if HT support is only added in TDLS, we need an HT-operation IE */ ++ sband = rwnx_hw->wiphy->bands[band]; ++ memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); ++ if (ht_cap.ht_supported && !ap_sta->ht && sta->ht) { ++ pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); ++ /* send an empty HT operation IE */ ++ rwnx_ie_build_ht_oper(rwnx_hw, rwnx_vif, pos, &ht_cap, 0); ++ } ++ ++ rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator); ++ ++ memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); ++ if (vht_cap.vht_supported && !ap_sta->vht && sta->vht) { ++ pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_operation)); ++ rwnx_ie_build_vht_oper(rwnx_hw, rwnx_vif, pos, &ht_cap, 0); ++ // Operating mode Notification (optional) ++ } ++ ++ /* add any remaining IEs */ ++ if (extra_ies_len) { ++ noffset = extra_ies_len; ++ pos = skb_put(skb, noffset - offset); ++ memcpy(pos, extra_ies + offset, noffset - offset); ++ } ++ ++ rcu_read_unlock(); ++} ++ ++static void ++rwnx_tdls_add_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, ++ u8 action_code, u16 status_code, ++ bool initiator, const u8 *extra_ies, ++ size_t extra_ies_len, u8 oper_class, ++ struct cfg80211_chan_def *chandef) ++{ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ if (status_code == 0) ++ rwnx_tdls_add_setup_start_ies(rwnx_hw, rwnx_vif, skb, peer, action_code, ++ initiator, extra_ies, extra_ies_len); ++ break; ++ case WLAN_TDLS_SETUP_CONFIRM: ++ if (status_code == 0) ++ rwnx_tdls_add_setup_cfm_ies(rwnx_hw, rwnx_vif, skb, peer, initiator, ++ extra_ies, extra_ies_len); ++ break; ++ ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ if (extra_ies_len) ++ memcpy(skb_put(skb, extra_ies_len), extra_ies, ++ extra_ies_len); ++ if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN) ++ rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator); ++ break; ++ } ++} ++ ++int ++rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len, u8 oper_class, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct sk_buff *skb; ++ int ret = 0; ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ]; ++ int channels = rwnx_band_2GHz->n_channels; ++ ++ if (rwnx_hw->band_5g_support) ++ channels += rwnx_band_5GHz->n_channels; ++ ++ skb = netdev_alloc_skb(rwnx_vif->ndev, ++ sizeof(struct ieee80211_tdls_data) + // ethhdr + TDLS info ++ 10 + /* supported rates */ ++ 6 + /* extended supported rates */ ++ (2 + channels) + /* supported channels */ ++ sizeof(struct ieee_types_extcap) + ++ sizeof(struct ieee80211_wmm_param_ie) + ++ 4 + /* oper classes */ ++ 28 + //sizeof(struct ieee80211_ht_cap) + ++ sizeof(struct ieee_types_bss_co_2040) + ++ sizeof(struct ieee80211_tdls_lnkie) + ++ (2 + sizeof(struct ieee80211_vht_cap)) + ++ 4 + /*AID*/ ++ (2 + sizeof(struct ieee80211_ht_operation)) + ++ extra_ies_len); ++ ++ if (!skb) ++ return 0; ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ ret = rwnx_tdls_prepare_encap_data(rwnx_hw, rwnx_vif, peer, action_code, ++ dialog_token, status_code, skb); ++ break; ++ ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ ret = rwnx_prep_tdls_direct(rwnx_hw, rwnx_vif, peer, action_code, ++ dialog_token, status_code, skb); ++ break; ++ ++ default: ++ ret = -ENOTSUPP; ++ break; ++ } ++ ++ if (ret < 0) ++ goto fail; ++ ++ rwnx_tdls_add_ies(rwnx_hw, rwnx_vif, skb, peer, action_code, status_code, ++ initiator, extra_ies, extra_ies_len, oper_class, chandef); ++ ++ if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) { ++ u64 cookie; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ struct cfg80211_mgmt_tx_params params; ++ ++ params.len = skb->len; ++ params.buf = skb->data; ++ ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, ¶ms, false, &cookie); ++ #else ++ ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, NULL, false, 0, skb->data, skb->len, false, false, &cookie); ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ ++ return ret; ++ } ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ skb->priority = 2; ++ break; ++ default: ++ skb->priority = 5; ++ break; ++ } ++ ++ ret = rwnx_select_txq(rwnx_vif, skb); ++ ret = rwnx_start_xmit(skb, rwnx_vif->ndev); ++ ++ return ret; ++ ++fail: ++ dev_kfree_skb(skb); ++ return ret; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h +new file mode 100644 +index 000000000000..590b420f6ec6 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h +@@ -0,0 +1,54 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tdls.h ++ * ++ * @brief TDLS function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef RWNX_TDLS_H_ ++#define RWNX_TDLS_H_ ++ ++#include "rwnx_defs.h" ++ ++struct ieee_types_header { ++ u8 element_id; ++ u8 len; ++} __packed; ++ ++struct ieee_types_bss_co_2040 { ++ struct ieee_types_header ieee_hdr; ++ u8 bss_2040co; ++} __packed; ++ ++struct ieee_types_extcap { ++ struct ieee_types_header ieee_hdr; ++ u8 ext_capab[8]; ++} __packed; ++ ++struct ieee_types_vht_cap { ++ struct ieee_types_header ieee_hdr; ++ struct ieee80211_vht_cap vhtcap; ++} __packed; ++ ++struct ieee_types_vht_oper { ++ struct ieee_types_header ieee_hdr; ++ struct ieee80211_vht_operation vhtoper; ++} __packed; ++ ++struct ieee_types_aid { ++ struct ieee_types_header ieee_hdr; ++ u16 aid; ++} __packed; ++ ++int rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len, u8 oper_class, ++ struct cfg80211_chan_def *chandef); ++ ++#endif /* RWNX_TDLS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c +new file mode 100644 +index 000000000000..ef97354d08df +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c +@@ -0,0 +1,230 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_testmode.c ++ * ++ * @brief Test mode function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#include ++#include ++ ++#include "rwnx_testmode.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_dini.h" ++#include "reg_access.h" ++ ++/* ++ * This function handles the user application commands for register access. ++ * ++ * It retrieves command ID carried with RWNX_TM_ATTR_COMMAND and calls to the ++ * handlers respectively. ++ * ++ * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the ++ * mandatory fields(RWNX_TM_ATTR_REG_OFFSET,RWNX_TM_ATTR_REG_VALUE32) ++ * are missing; Otherwise 0 is replied indicating the success of the command execution. ++ * ++ * If RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_READ, the register read ++ * value is returned with RWNX_TM_ATTR_REG_VALUE32. ++ * ++ * @hw: ieee80211_hw object that represents the device ++ * @tb: general message fields from the user space ++ */ ++int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) ++{ ++ struct rwnx_hw *rwnx_hw = hw->priv; ++ u32 mem_addr, val32; ++ struct sk_buff *skb; ++ int status = 0; ++ ++ /* First check if register address is there */ ++ if (!tb[RWNX_TM_ATTR_REG_OFFSET]) { ++ printk("Error finding register offset\n"); ++ return -ENOMSG; ++ } ++ ++ mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]); ++ ++ switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { ++ case RWNX_TM_CMD_APP2DEV_REG_READ: ++ { ++ struct dbg_mem_read_cfm mem_read_cfm; ++ ++ /*** Send the command to the LMAC ***/ ++ status = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &mem_read_cfm); ++ if (status) ++ return status; ++ ++ /* Allocate the answer message */ ++ skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); ++ if (!skb) { ++ printk("Error allocating memory\n"); ++ return -ENOMEM; ++ } ++ ++ val32 = mem_read_cfm.memdata; ++ if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, val32)) ++ goto nla_put_failure; ++ ++ /* Send the answer to upper layer */ ++ status = cfg80211_testmode_reply(skb); ++ if (status < 0) ++ printk("Error sending msg : %d\n", status); ++ } ++ break; ++ ++ case RWNX_TM_CMD_APP2DEV_REG_WRITE: ++ { ++ if (!tb[RWNX_TM_ATTR_REG_VALUE32]) { ++ printk("Error finding value to write\n"); ++ return -ENOMSG; ++ } else { ++ val32 = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]); ++ /* Send the command to the LMAC */ ++ status = rwnx_send_dbg_mem_write_req(rwnx_hw, mem_addr, val32); ++ if (status) ++ return status; ++ } ++ } ++ break; ++ ++ default: ++ printk("Unknown testmode register command ID\n"); ++ return -ENOSYS; ++ } ++ ++ return status; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -EMSGSIZE; ++} ++ ++/* ++ * This function handles the user application commands for Debug filter settings. ++ * ++ * @hw: ieee80211_hw object that represents the device ++ * @tb: general message fields from the user space ++ */ ++int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb) ++{ ++ struct rwnx_hw *rwnx_hw = hw->priv; ++ u32 filter; ++ int status = 0; ++ ++ /* First check if the filter is there */ ++ if (!tb[RWNX_TM_ATTR_REG_FILTER]) { ++ printk("Error finding filter value\n"); ++ return -ENOMSG; ++ } ++ ++ filter = nla_get_u32(tb[RWNX_TM_ATTR_REG_FILTER]); ++ RWNX_DBG("testmode debug filter, setting: 0x%x\n", filter); ++ ++ switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { ++ case RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER: ++ { ++ /* Send the command to the LMAC */ ++ status = rwnx_send_dbg_set_mod_filter_req(rwnx_hw, filter); ++ if (status) ++ return status; ++ } ++ break; ++ case RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER: ++ { ++ /* Send the command to the LMAC */ ++ status = rwnx_send_dbg_set_sev_filter_req(rwnx_hw, filter); ++ if (status) ++ return status; ++ } ++ break; ++ ++ default: ++ printk("Unknown testmode register command ID\n"); ++ return -ENOSYS; ++ } ++ ++ return status; ++} ++ ++/* ++ * This function handles the user application commands for register access without using ++ * the normal LMAC messaging way. ++ * This time register access will be done through direct PCI BAR windows. This can be used ++ * to access registers even when the :AMC FW is stuck. ++ * ++ * @hw: ieee80211_hw object that represents the device ++ * @tb: general message fields from the user space ++ */ ++int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb) ++{ ++ struct rwnx_hw *rwnx_hw = hw->priv; ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ u32 mem_addr; ++ struct sk_buff *skb; ++ int status = 0; ++ volatile unsigned int reg_value = 0; ++ unsigned int offset; ++ ++ /* First check if register address is there */ ++ if (!tb[RWNX_TM_ATTR_REG_OFFSET]) { ++ printk("Error finding register offset\n"); ++ return -ENOMSG; ++ } ++ ++ mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]); ++ offset = mem_addr & 0x00FFFFFF; ++ ++ switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { ++ case RWNX_TM_CMD_APP2DEV_REG_READ_DBG: ++ { ++ /*** Send the command to the LMAC ***/ ++ reg_value = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, offset); ++ ++ /* Allocate the answer message */ ++ skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); ++ if (!skb) { ++ printk("Error allocating memory\n"); ++ return -ENOMEM; ++ } ++ ++ if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, reg_value)) ++ goto nla_put_failure; ++ ++ /* Send the answer to upper layer */ ++ status = cfg80211_testmode_reply(skb); ++ if (status < 0) ++ printk("Error sending msg : %d\n", status); ++ } ++ break; ++ ++ case RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG: ++ { ++ if (!tb[RWNX_TM_ATTR_REG_VALUE32]) { ++ printk("Error finding value to write\n"); ++ return -ENOMSG; ++ } else { ++ reg_value = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]); ++ ++ /* Send the command to the LMAC */ ++ RWNX_REG_WRITE(reg_value, rwnx_plat, RWNX_ADDR_SYSTEM, ++ offset); ++ } ++ } ++ break; ++ ++ default: ++ printk("Unknown testmode register command ID\n"); ++ return -ENOSYS; ++ } ++ ++ return status; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -EMSGSIZE; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h +new file mode 100644 +index 000000000000..9d1bca47eb50 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h +@@ -0,0 +1,64 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_testmode.h ++ * ++ * @brief Test mode function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef RWNX_TESTMODE_H_ ++#define RWNX_TESTMODE_H_ ++ ++#include ++#include ++ ++/* Commands from user space to kernel space(RWNX_TM_CMD_APP2DEV_XX) and ++ * from and kernel space to user space(RWNX_TM_CMD_DEV2APP_XX). ++ * The command ID is carried with RWNX_TM_ATTR_COMMAND. ++ */ ++enum rwnx_tm_cmd_t { ++ /* commands from user application to access register */ ++ RWNX_TM_CMD_APP2DEV_REG_READ = 1, ++ RWNX_TM_CMD_APP2DEV_REG_WRITE, ++ ++ /* commands from user application to select the Debug levels */ ++ RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER, ++ RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER, ++ ++ /* commands to access registers without sending messages to LMAC layer, ++ * this must be used when LMAC FW is stuck. */ ++ RWNX_TM_CMD_APP2DEV_REG_READ_DBG, ++ RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG, ++ ++ RWNX_TM_CMD_MAX, ++}; ++ ++enum rwnx_tm_attr_t { ++ RWNX_TM_ATTR_NOT_APPLICABLE = 0, ++ ++ RWNX_TM_ATTR_COMMAND, ++ ++ /* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_XXX, ++ * The mandatory fields are: ++ * RWNX_TM_ATTR_REG_OFFSET for the offset of the target register; ++ * RWNX_TM_ATTR_REG_VALUE32 for value */ ++ RWNX_TM_ATTR_REG_OFFSET, ++ RWNX_TM_ATTR_REG_VALUE32, ++ ++ /* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_SET_DBGXXXFILTER, ++ * The mandatory field is RWNX_TM_ATTR_REG_FILTER. */ ++ RWNX_TM_ATTR_REG_FILTER, ++ ++ RWNX_TM_ATTR_MAX, ++}; ++ ++/***********************************************************************/ ++int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb); ++int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb); ++int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb); ++ ++#endif /* RWNX_TESTMODE_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c +new file mode 100644 +index 000000000000..5a57acc20c71 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c +@@ -0,0 +1,2344 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tx.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_tx.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_mesh.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "aicwf_txrxif.h" ++#ifdef CONFIG_RWNX_MON_XMIT ++#include ++#endif ++ ++/****************************************************************************** ++ * Power Save functions ++ *****************************************************************************/ ++/** ++ * rwnx_set_traffic_status - Inform FW if traffic is available for STA in PS ++ * ++ * @rwnx_hw: Driver main data ++ * @sta: Sta in PS mode ++ * @available: whether traffic is buffered for the STA ++ * @ps_id: type of PS data requested (@LEGACY_PS_ID or @UAPSD_ID) ++ */ ++void rwnx_set_traffic_status(struct rwnx_hw *rwnx_hw, ++ struct rwnx_sta *sta, ++ bool available, ++ u8 ps_id) ++{ ++ if (sta->tdls.active) { ++ rwnx_send_tdls_peer_traffic_ind_req(rwnx_hw, ++ rwnx_hw->vif_table[sta->vif_idx]); ++ } else { ++ bool uapsd = (ps_id != LEGACY_PS_ID); ++ rwnx_send_me_traffic_ind(rwnx_hw, sta->sta_idx, uapsd, available); ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_traffic_update(sta->sta_idx, available, uapsd); ++#endif ++ } ++} ++ ++/** ++ * rwnx_ps_bh_enable - Enable/disable PS mode for one STA ++ * ++ * @rwnx_hw: Driver main data ++ * @sta: Sta which enters/leaves PS mode ++ * @enable: PS mode status ++ * ++ * This function will enable/disable PS mode for one STA. ++ * When enabling PS mode: ++ * - Stop all STA's txq for RWNX_TXQ_STOP_STA_PS reason ++ * - Count how many buffers are already ready for this STA ++ * - For BC/MC sta, update all queued SKB to use hw_queue BCMC ++ * - Update TIM if some packet are ready ++ * ++ * When disabling PS mode: ++ * - Start all STA's txq for RWNX_TXQ_STOP_STA_PS reason ++ * - For BC/MC sta, update all queued SKB to use hw_queue AC_BE ++ * - Update TIM if some packet are ready (otherwise fw will not update TIM ++ * in beacon for this STA) ++ * ++ * All counter/skb updates are protected from TX path by taking tx_lock ++ * ++ * NOTE: _bh_ in function name indicates that this function is called ++ * from a bottom_half tasklet. ++ */ ++void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ bool enable) ++{ ++ struct rwnx_txq *txq; ++ ++ if (enable) { ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_enable(sta); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ sta->ps.active = true; ++ sta->ps.sp_cnt[LEGACY_PS_ID] = 0; ++ sta->ps.sp_cnt[UAPSD_ID] = 0; ++ rwnx_txq_sta_stop(sta, RWNX_TXQ_STOP_STA_PS, rwnx_hw); ++ ++ if (is_multicast_sta(sta->sta_idx)) { ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ sta->ps.pkt_ready[LEGACY_PS_ID] = skb_queue_len(&txq->sk_list); ++ sta->ps.pkt_ready[UAPSD_ID] = 0; ++ //txq->hwq = &rwnx_hw->hwq[RWNX_HWQ_BCMC]; ++ } else { ++ int i; ++ sta->ps.pkt_ready[LEGACY_PS_ID] = 0; ++ sta->ps.pkt_ready[UAPSD_ID] = 0; ++ foreach_sta_txq(sta, txq, i, rwnx_hw) { ++ sta->ps.pkt_ready[txq->ps_id] += skb_queue_len(&txq->sk_list); ++ } ++ } ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ //if (sta->ps.pkt_ready[LEGACY_PS_ID]) ++ //srwnx_set_traffic_status(rwnx_hw, sta, true, LEGACY_PS_ID); ++ ++ //if (sta->ps.pkt_ready[UAPSD_ID]) ++ // rwnx_set_traffic_status(rwnx_hw, sta, true, UAPSD_ID); ++ } else { ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_disable(sta->sta_idx); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ sta->ps.active = false; ++ ++ if (is_multicast_sta(sta->sta_idx)) { ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ txq->hwq = &rwnx_hw->hwq[RWNX_HWQ_BE]; ++ txq->push_limit = 0; ++ } else { ++ int i; ++ foreach_sta_txq(sta, txq, i, rwnx_hw) { ++ txq->push_limit = 0; ++ } ++ } ++ ++ rwnx_txq_sta_start(sta, RWNX_TXQ_STOP_STA_PS, rwnx_hw); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ if (sta->ps.pkt_ready[LEGACY_PS_ID]) ++ rwnx_set_traffic_status(rwnx_hw, sta, false, LEGACY_PS_ID); ++ ++ //if (sta->ps.pkt_ready[UAPSD_ID]) ++ // rwnx_set_traffic_status(rwnx_hw, sta, false, UAPSD_ID); ++ ++ tasklet_schedule(&rwnx_hw->task); ++ } ++} ++ ++/** ++ * rwnx_ps_bh_traffic_req - Handle traffic request for STA in PS mode ++ * ++ * @rwnx_hw: Driver main data ++ * @sta: Sta which enters/leaves PS mode ++ * @pkt_req: number of pkt to push ++ * @ps_id: type of PS data requested (@LEGACY_PS_ID or @UAPSD_ID) ++ * ++ * This function will make sure that @pkt_req are pushed to fw ++ * whereas the STA is in PS mode. ++ * If request is 0, send all traffic ++ * If request is greater than available pkt, reduce request ++ * Note: request will also be reduce if txq credits are not available ++ * ++ * All counter updates are protected from TX path by taking tx_lock ++ * ++ * NOTE: _bh_ in function name indicates that this function is called ++ * from the bottom_half tasklet. ++ */ ++void rwnx_ps_bh_traffic_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ u16 pkt_req, u8 ps_id) ++{ ++ int pkt_ready_all; ++ struct rwnx_txq *txq; ++ int schedule = 0; ++ ++ //if (WARN(!sta->ps.active, "sta %pM is not in Power Save mode", ++ // sta->mac_addr)) ++ // return; ++ if (!sta->ps.active) { ++ AICWFDBG(LOGTRACE,"sta %pM is not in Power Save mode", sta->mac_addr); ++ return; ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_traffic_req(sta, pkt_req, ps_id); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ /* Fw may ask to stop a service period with PS_SP_INTERRUPTED. This only ++ happens for p2p-go interface if NOA starts during a service period */ ++ if ((pkt_req == PS_SP_INTERRUPTED) && (ps_id == UAPSD_ID)) { ++ int tid; ++ sta->ps.sp_cnt[ps_id] = 0; ++ foreach_sta_txq(sta, txq, tid, rwnx_hw) { ++ txq->push_limit = 0; ++ } ++ goto done; ++ } ++ ++ pkt_ready_all = (sta->ps.pkt_ready[ps_id] - sta->ps.sp_cnt[ps_id]); ++ ++ /* Don't start SP until previous one is finished or we don't have ++ packet ready (which must not happen for U-APSD) */ ++ if (sta->ps.sp_cnt[ps_id] || pkt_ready_all <= 0) { ++ goto done; ++ } ++ ++ /* Adapt request to what is available. */ ++ if (pkt_req == 0 || pkt_req > pkt_ready_all) { ++ pkt_req = pkt_ready_all; ++ } ++ ++ /* Reset the SP counter */ ++ sta->ps.sp_cnt[ps_id] = 0; ++ schedule = 1; ++ ++ /* "dispatch" the request between txq */ ++ if (is_multicast_sta(sta->sta_idx)) { ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ //if (txq->credits <= 0) ++ // goto done; ++ if (pkt_req > txq->credits) ++ pkt_req = txq->credits; ++ txq->push_limit = pkt_req; ++ sta->ps.sp_cnt[ps_id] = pkt_req; ++ rwnx_txq_add_to_hw_list(txq); ++ } else { ++ int i, tid; ++ ++ //foreach_sta_txq_prio(sta, txq, tid, i, rwnx_hw) { ++ for (i = 0; i < NX_NB_TID_PER_STA; i++) { ++ u16 txq_len; ++ tid = nx_tid_prio[i]; ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ txq_len = skb_queue_len(&txq->sk_list); ++ ++ if (txq->ps_id != ps_id) ++ continue; ++ ++ if (txq_len > txq->credits) ++ txq_len = txq->credits; ++ ++ if (txq_len == 0) ++ continue; ++ ++ if (txq_len < pkt_req) { ++ /* Not enough pkt queued in this txq, add this ++ txq to hwq list and process next txq */ ++ pkt_req -= txq_len; ++ txq->push_limit = txq_len; ++ sta->ps.sp_cnt[ps_id] += txq_len; ++ rwnx_txq_add_to_hw_list(txq); ++ } else { ++ /* Enough pkt in this txq to comlete the request ++ add this txq to hwq list and stop processing txq */ ++ txq->push_limit = pkt_req; ++ sta->ps.sp_cnt[ps_id] += pkt_req; ++ rwnx_txq_add_to_hw_list(txq); ++ break; ++ } ++ } ++ } ++ ++done: ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ if (schedule) ++ tasklet_schedule(&rwnx_hw->task); ++} ++ ++/****************************************************************************** ++ * TX functions ++ *****************************************************************************/ ++#define PRIO_STA_NULL 0xAA ++ ++static const int rwnx_down_hwq2tid[3] = { ++ [RWNX_HWQ_BK] = 2, ++ [RWNX_HWQ_BE] = 3, ++ [RWNX_HWQ_VI] = 5, ++}; ++ ++static void rwnx_downgrade_ac(struct rwnx_sta *sta, struct sk_buff *skb) ++{ ++ int8_t ac = rwnx_tid2hwq[skb->priority]; ++ ++ if (WARN((ac > RWNX_HWQ_VO), ++ "Unexepcted ac %d for skb before downgrade", ac)) ++ ac = RWNX_HWQ_VO; ++ ++ while (sta->acm & BIT(ac)) { ++ if (ac == RWNX_HWQ_BK) { ++ skb->priority = 1; ++ return; ++ } ++ ac--; ++ skb->priority = rwnx_down_hwq2tid[ac]; ++ } ++} ++ ++u16 rwnx_select_txq(struct rwnx_vif *rwnx_vif, struct sk_buff *skb) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct wireless_dev *wdev = &rwnx_vif->wdev; ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_txq *txq; ++ u16 netdev_queue; ++ bool tdls_mgmgt_frame = false; ++ int nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC; ++ } ++ ++ switch (wdev->iftype) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ { ++ struct ethhdr *eth; ++ eth = (struct ethhdr *)skb->data; ++ if (eth->h_proto == cpu_to_be16(ETH_P_TDLS)) { ++ tdls_mgmgt_frame = true; ++ } ++ if ((rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) && ++ (rwnx_vif->sta.tdls_sta != NULL) && ++ (memcmp(eth->h_dest, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) ++ sta = rwnx_vif->sta.tdls_sta; ++ else ++ sta = rwnx_vif->sta.ap; ++ break; ++ } ++ case NL80211_IFTYPE_AP_VLAN: ++ if (rwnx_vif->ap_vlan.sta_4a) { ++ sta = rwnx_vif->ap_vlan.sta_4a; ++ break; ++ } ++ ++ /* AP_VLAN interface is not used for a 4A STA, ++ fallback searching sta amongs all AP's clients */ ++ rwnx_vif = rwnx_vif->ap_vlan.master; ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ { ++ struct rwnx_sta *cur; ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ ++ if (is_multicast_ether_addr(eth->h_dest)) { ++ sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ } else { ++ spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ list_for_each_entry(cur, &rwnx_vif->ap.sta_list, list) { ++ if (!memcmp(cur->mac_addr, eth->h_dest, ETH_ALEN)) { ++ sta = cur; ++ break; ++ } ++ } ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ } ++ ++ break; ++ } ++ case NL80211_IFTYPE_MESH_POINT: ++ { ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ ++ if (!rwnx_vif->is_resending) { ++ /* ++ * If ethernet source address is not the address of a mesh wireless interface, we are proxy for ++ * this address and have to inform the HW ++ */ ++ if (memcmp(ð->h_source[0], &rwnx_vif->ndev->perm_addr[0], ETH_ALEN)) { ++ /* Check if LMAC is already informed */ ++ if (!rwnx_get_mesh_proxy_info(rwnx_vif, (u8 *)ð->h_source, true)) { ++ rwnx_send_mesh_proxy_add_req(rwnx_hw, rwnx_vif, (u8 *)ð->h_source); ++ } ++ } ++ } ++ ++ if (is_multicast_ether_addr(eth->h_dest)) { ++ sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ } else { ++ /* Path to be used */ ++ struct rwnx_mesh_path *p_mesh_path = NULL; ++ struct rwnx_mesh_path *p_cur_path; ++ /* Check if destination is proxied by a peer Mesh STA */ ++ struct rwnx_mesh_proxy *p_mesh_proxy = rwnx_get_mesh_proxy_info(rwnx_vif, (u8 *)ð->h_dest, false); ++ /* Mesh Target address */ ++ struct mac_addr *p_tgt_mac_addr; ++ ++ if (p_mesh_proxy) { ++ p_tgt_mac_addr = &p_mesh_proxy->proxy_addr; ++ } else { ++ p_tgt_mac_addr = (struct mac_addr *)ð->h_dest; ++ } ++ ++ /* Look for path with provided target address */ ++ list_for_each_entry(p_cur_path, &rwnx_vif->ap.mpath_list, list) { ++ if (!memcmp(&p_cur_path->tgt_mac_addr, p_tgt_mac_addr, ETH_ALEN)) { ++ p_mesh_path = p_cur_path; ++ break; ++ } ++ } ++ ++ if (p_mesh_path) { ++ sta = p_mesh_path->p_nhop_sta; ++ } else { ++ rwnx_send_mesh_path_create_req(rwnx_hw, rwnx_vif, (u8 *)p_tgt_mac_addr); ++ } ++ } ++ ++ break; ++ } ++ default: ++ break; ++ } ++ ++ if (sta && sta->qos) { ++ if (tdls_mgmgt_frame) { ++ skb_set_queue_mapping(skb, NX_STA_NDEV_IDX(skb->priority, sta->sta_idx)); ++ } else { ++ /* use the data classifier to determine what 802.1d tag the ++ * data frame has */ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) ++ skb->priority = cfg80211_classify8021d(skb) & IEEE80211_QOS_CTL_TAG1D_MASK; ++ #else ++ skb->priority = cfg80211_classify8021d(skb, NULL) & IEEE80211_QOS_CTL_TAG1D_MASK; ++ #endif ++ } ++ if (sta->acm) ++ rwnx_downgrade_ac(sta, skb); ++ ++ txq = rwnx_txq_sta_get(sta, skb->priority, rwnx_hw); ++ netdev_queue = txq->ndev_idx; ++ } else if (sta) { ++ skb->priority = 0xFF; ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ netdev_queue = txq->ndev_idx; ++ } else { ++ /* This packet will be dropped in xmit function, still need to select ++ an active queue for xmit to be called. As it most likely to happen ++ for AP interface, select BCMC queue ++ (TODO: select another queue if BCMC queue is stopped) */ ++ skb->priority = PRIO_STA_NULL; ++ netdev_queue = nx_bcmc_txq_ndev_idx; ++ } ++ ++#ifndef CONFIG_ONE_TXQ ++ BUG_ON(netdev_queue >= NX_NB_NDEV_TXQ); ++#endif ++ ++ return netdev_queue; ++} ++ ++/** ++ * rwnx_set_more_data_flag - Update MORE_DATA flag in tx sw desc ++ * ++ * @rwnx_hw: Driver main data ++ * @sw_txhdr: Header for pkt to be pushed ++ * ++ * If STA is in PS mode ++ * - Set EOSP in case the packet is the last of the UAPSD service period ++ * - Set MORE_DATA flag if more pkt are ready for this sta ++ * - Update TIM if this is the last pkt buffered for this sta ++ * ++ * note: tx_lock already taken. ++ */ ++static inline void rwnx_set_more_data_flag(struct rwnx_hw *rwnx_hw, ++ struct rwnx_sw_txhdr *sw_txhdr) ++{ ++ struct rwnx_sta *sta = sw_txhdr->rwnx_sta; ++ struct rwnx_vif *vif = sw_txhdr->rwnx_vif; ++ struct rwnx_txq *txq = sw_txhdr->txq; ++ ++ if (unlikely(sta->ps.active)) { ++ sta->ps.pkt_ready[txq->ps_id]--; ++ sta->ps.sp_cnt[txq->ps_id]--; ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_push(sta); ++#endif ++ if (((txq->ps_id == UAPSD_ID) || (vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) || (sta->tdls.active)) ++ && !sta->ps.sp_cnt[txq->ps_id]) { ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_EOSP; ++ } ++ ++ if (sta->ps.pkt_ready[txq->ps_id]) { ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_MORE_DATA; ++ } else { ++ rwnx_set_traffic_status(rwnx_hw, sta, false, txq->ps_id); ++ } ++ } ++} ++ ++/** ++ * rwnx_get_tx_priv - Get STA and tid for one skb ++ * ++ * @rwnx_vif: vif ptr ++ * @skb: skb ++ * @tid: pointer updated with the tid to use for this skb ++ * ++ * @return: pointer on the destination STA (may be NULL) ++ * ++ * skb has already been parsed in rwnx_select_queue function ++ * simply re-read information form skb. ++ */ ++static struct rwnx_sta *rwnx_get_tx_priv(struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, ++ u8 *tid) ++{ ++ static struct rwnx_hw *rwnx_hw; ++ struct rwnx_sta *sta; ++ int sta_idx; ++ int nx_remote_sta_max = NX_REMOTE_STA_MAX; ++ int nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX; ++ ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_remote_sta_max = NX_REMOTE_STA_MAX_FOR_OLD_IC; ++ nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC; ++ } ++ ++ ++ rwnx_hw = rwnx_vif->rwnx_hw; ++ *tid = skb->priority; ++ if (unlikely(skb->priority == PRIO_STA_NULL)) { ++ return NULL; ++ } else { ++ int ndev_idx = skb_get_queue_mapping(skb); ++ ++ if (ndev_idx == nx_bcmc_txq_ndev_idx) ++ sta_idx = nx_remote_sta_max + master_vif_idx(rwnx_vif); ++ else ++ sta_idx = ndev_idx / NX_NB_TID_PER_STA; ++ ++ sta = &rwnx_hw->sta_table[sta_idx]; ++ } ++ ++ return sta; ++} ++ ++/** ++ * rwnx_prep_tx - Prepare buffer for DMA transmission ++ * ++ * @rwnx_hw: Driver main data ++ * @txhdr: Tx descriptor ++ * ++ * Maps hw_txhdr and buffer data for transmission via DMA. ++ * - Data buffer with be downloaded by embebded side. ++ * - hw_txhdr will be uploaded by embedded side when buffer has been ++ * transmitted over the air. ++ */ ++static int rwnx_prep_tx(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr) ++{ ++#if 0 ++ struct rwnx_sw_txhdr *sw_txhdr = txhdr->sw_hdr; ++ struct rwnx_hw_txhdr *hw_txhdr = &txhdr->hw_hdr; ++ dma_addr_t dma_addr; ++ ++ /* MAP (and sync) memory for DMA */ ++ dma_addr = dma_map_single(rwnx_hw->dev, hw_txhdr, ++ sw_txhdr->map_len, DMA_BIDIRECTIONAL); ++ if (WARN_ON(dma_mapping_error(rwnx_hw->dev, dma_addr))) ++ return -1; ++ ++ sw_txhdr->dma_addr = dma_addr; ++#endif ++ return 0; ++} ++ ++/** ++ * rwnx_tx_push - Push one packet to fw ++ * ++ * @rwnx_hw: Driver main data ++ * @txhdr: tx desc of the buffer to push ++ * @flags: push flags (see @rwnx_push_flags) ++ * ++ * Push one packet to fw. Sw desc of the packet has already been updated. ++ * Only MORE_DATA flag will be set if needed. ++ */ ++void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags) ++{ ++ struct rwnx_sw_txhdr *sw_txhdr = txhdr->sw_hdr; ++ struct sk_buff *skb = sw_txhdr->skb; ++ struct rwnx_txq *txq = sw_txhdr->txq; ++ u16 hw_queue = txq->hwq->id; ++ int user = 0; ++ ++ lockdep_assert_held(&rwnx_hw->tx_lock); ++ ++ //printk("rwnx_tx_push\n"); ++ /* RETRY flag is not always set so retest here */ ++ if (txq->nb_retry) { ++ flags |= RWNX_PUSH_RETRY; ++ txq->nb_retry--; ++ if (txq->nb_retry == 0) { ++ WARN(skb != txq->last_retry_skb, ++ "last retry buffer is not the expected one"); ++ txq->last_retry_skb = NULL; ++ } ++ } else if (!(flags & RWNX_PUSH_RETRY)) { ++ txq->pkt_sent++; ++ } ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (txq->amsdu == sw_txhdr) { ++ WARN((flags & RWNX_PUSH_RETRY), "End A-MSDU on a retry"); ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].done++; ++ txq->amsdu = NULL; ++ } else if (!(flags & RWNX_PUSH_RETRY) && ++ !(sw_txhdr->desc.host.flags & TXU_CNTRL_AMSDU)) { ++ rwnx_hw->stats.amsdus[0].done++; ++ } ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++ /* Wait here to update hw_queue, as for multicast STA hwq may change ++ between queue and push (because of PS) */ ++ sw_txhdr->hw_queue = hw_queue; ++ ++ //sw_txhdr->desc.host.packet_addr = hw_queue; //use packet_addr field for hw_txq ++ sw_txhdr->desc.host.ac = hw_queue; //use ac field for hw_txq ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ /* MU group is only selected during hwq processing */ ++ sw_txhdr->desc.host.mumimo_info = txq->mumimo_info; ++ user = RWNX_TXQ_POS_ID(txq); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++ if (sw_txhdr->rwnx_sta) { ++ /* only for AP mode */ ++ rwnx_set_more_data_flag(rwnx_hw, sw_txhdr); ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_push_desc(skb, sw_txhdr, flags); ++#endif ++ #if 0 ++ txq->credits--; ++ #endif ++ txq->pkt_pushed[user]++; ++ //printk("txq->credits=%d\n",txq->credits); ++ #if 0 ++ if (txq->credits <= 0) ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); ++ #endif ++ ++ if (txq->push_limit) ++ txq->push_limit--; ++#if 0 ++ rwnx_ipc_txdesc_push(rwnx_hw, &sw_txhdr->desc, skb, hw_queue, user); ++#else ++#ifdef AICWF_SDIO_SUPPORT ++ if (((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT) && \ ++ ((*(skb->data+sw_txhdr->headroom) == 0xd0) || (*(skb->data+sw_txhdr->headroom) == 0x10) || (*(skb->data+sw_txhdr->headroom) == 0x30))) || \ ++ (sw_txhdr->desc.host.ethertype == 0x8e88) || (sw_txhdr->desc.host.ethertype == 0xb488)) { ++ sw_txhdr->need_cfm = 1; ++ sw_txhdr->desc.host.hostid = ((1<<31) | rwnx_hw->sdio_env.txdesc_free_idx[0]); ++ aicwf_sdio_host_txdesc_push(&(rwnx_hw->sdio_env), 0, (long)skb); ++ if((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT)) ++ AICWFDBG(LOGINFO, "need cfm mgmt:%x,user_idx=%d, skb=%p\n", *(skb->data+sw_txhdr->headroom), rwnx_hw->sdio_env.txdesc_free_idx[0], skb); ++ else ++ AICWFDBG(LOGINFO, "need cfm ethertype:%8x,user_idx=%d, skb=%p\n", sw_txhdr->desc.host.ethertype, rwnx_hw->sdio_env.txdesc_free_idx[0], skb); ++ } else { ++ sw_txhdr->need_cfm = 0; ++ sw_txhdr->desc.host.hostid = 0; ++ if (sw_txhdr->raw_frame) { ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_MGMT; ++ AICWFDBG(LOGDEBUG, "%s TXU_CNTRL_MGMT sw_txhdr->desc.host.flags:%x\r\n", __func__, ++ sw_txhdr->desc.host.flags); ++ } ++ if (sw_txhdr->fixed_rate) { ++ sw_txhdr->desc.host.hostid = (0x01UL << 30) | sw_txhdr->rate_config; ++ AICWFDBG(LOGDEBUG, "%s TXU_CNTRL_MGMT hostid:%x\r\n", __func__, ++ sw_txhdr->desc.host.hostid); ++ } else { ++ sw_txhdr->desc.host.hostid = 0; ++ } ++ ++ sw_txhdr->rwnx_vif->net_stats.tx_packets++; ++ sw_txhdr->rwnx_vif->net_stats.tx_bytes += sw_txhdr->frame_len; ++ rwnx_hw->stats.last_tx = jiffies; ++ } ++ aicwf_frame_tx((void *)(rwnx_hw->sdiodev), skb); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ if (((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT) && \ ++ ((*(skb->data+sw_txhdr->headroom) == 0xd0) || (*(skb->data+sw_txhdr->headroom) == 0x10) || (*(skb->data+sw_txhdr->headroom) == 0x30))) || \ ++ (sw_txhdr->desc.host.ethertype == 0x8e88)) { ++ printk("push need cfm flags 0x%x\n", sw_txhdr->desc.host.flags); ++ sw_txhdr->need_cfm = 1; ++ sw_txhdr->desc.host.hostid = ((1<<31) | rwnx_hw->usb_env.txdesc_free_idx[0]); ++ aicwf_usb_host_txdesc_push(&(rwnx_hw->usb_env), 0, (long)(skb)); ++ } else { ++ sw_txhdr->need_cfm = 0; ++ sw_txhdr->desc.host.hostid = 0; ++ ++ sw_txhdr->rwnx_vif->net_stats.tx_packets++; ++ sw_txhdr->rwnx_vif->net_stats.tx_bytes += sw_txhdr->frame_len; ++ rwnx_hw->stats.last_tx = jiffies; ++ } ++ aicwf_frame_tx((void *)(rwnx_hw->usbdev), skb); ++#endif ++#endif ++#if 0 ++ txq->hwq->credits[user]--; ++#endif ++ rwnx_hw->stats.cfm_balance[hw_queue]++; ++} ++ ++ ++ ++/** ++ * rwnx_tx_retry - Push an AMPDU pkt that need to be retried ++ * ++ * @rwnx_hw: Driver main data ++ * @skb: pkt to re-push ++ * @txhdr: tx desc of the pkt to re-push ++ * @sw_retry: Indicates if fw decide to retry this buffer ++ * (i.e. it has never been transmitted over the air) ++ * ++ * Called when a packet needs to be repushed to the firmware. ++ * First update sw descriptor and then queue it in the retry list. ++ */ ++static void rwnx_tx_retry(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, ++ struct rwnx_txhdr *txhdr, bool sw_retry) ++{ ++ struct rwnx_sw_txhdr *sw_txhdr = txhdr->sw_hdr; ++ struct tx_cfm_tag *cfm = &txhdr->hw_hdr.cfm; ++ struct rwnx_txq *txq = sw_txhdr->txq; ++ int peek_off = offsetof(struct rwnx_hw_txhdr, cfm); ++ int peek_len = sizeof(((struct rwnx_hw_txhdr *)0)->cfm); ++ ++ if (!sw_retry) { ++ /* update sw desc */ ++ #if 0 ++ sw_txhdr->desc.host.sn = cfm->sn; ++ sw_txhdr->desc.host.pn[0] = cfm->pn[0]; ++ sw_txhdr->desc.host.pn[1] = cfm->pn[1]; ++ sw_txhdr->desc.host.pn[2] = cfm->pn[2]; ++ sw_txhdr->desc.host.pn[3] = cfm->pn[3]; ++ sw_txhdr->desc.host.timestamp = cfm->timestamp; ++ #endif ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_RETRY; ++ ++ #ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->desc.host.flags & TXU_CNTRL_AMSDU) ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].failed++; ++ #endif ++ } ++ ++ /* MORE_DATA will be re-set if needed when pkt will be repushed */ ++ sw_txhdr->desc.host.flags &= ~TXU_CNTRL_MORE_DATA; ++ ++ cfm->status.value = 0; ++ dma_sync_single_for_device(rwnx_hw->dev, sw_txhdr->dma_addr + peek_off, ++ peek_len, DMA_BIDIRECTIONAL); ++ ++ txq->credits++; ++ if (txq->credits > 0) ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_FULL); ++ ++ /* Queue the buffer */ ++ rwnx_txq_queue_skb(skb, txq, rwnx_hw, true); ++} ++ ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++/* return size of subframe (including header) */ ++static inline int rwnx_amsdu_subframe_length(struct ethhdr *eth, int eth_len) ++{ ++ /* ethernet header is replaced with amdsu header that have the same size ++ Only need to check if LLC/SNAP header will be added */ ++ int len = eth_len; ++ ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ len += sizeof(rfc1042_header) + 2; ++ } ++ ++ return len; ++} ++ ++static inline bool rwnx_amsdu_is_aggregable(struct sk_buff *skb) ++{ ++ /* need to add some check on buffer to see if it can be aggregated ? */ ++ return true; ++} ++ ++ ++/** ++ * rwnx_amsdu_del_subframe_header - remove AMSDU header ++ * ++ * amsdu_txhdr: amsdu tx descriptor ++ * ++ * Move back the ethernet header at the "beginning" of the data buffer. ++ * (which has been moved in @rwnx_amsdu_add_subframe_header) ++ */ ++static void rwnx_amsdu_del_subframe_header(struct rwnx_amsdu_txhdr *amsdu_txhdr) ++{ ++ struct sk_buff *skb = amsdu_txhdr->skb; ++ struct ethhdr *eth; ++ u8 *pos; ++ ++ pos = skb->data; ++ pos += sizeof(struct rwnx_amsdu_txhdr); ++ eth = (struct ethhdr *)pos; ++ pos += amsdu_txhdr->pad + sizeof(struct ethhdr); ++ ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ pos += sizeof(rfc1042_header) + 2; ++ } ++ ++ memmove(pos, eth, sizeof(*eth)); ++ skb_pull(skb, (pos - skb->data)); ++} ++ ++/** ++ * rwnx_amsdu_add_subframe_header - Add AMSDU header and link subframe ++ * ++ * @rwnx_hw Driver main data ++ * @skb Buffer to aggregate ++ * @sw_txhdr Tx descriptor for the first A-MSDU subframe ++ * ++ * return 0 on sucess, -1 otherwise ++ * ++ * This functions Add A-MSDU header and LLC/SNAP header in the buffer ++ * and update sw_txhdr of the first subframe to link this buffer. ++ * If an error happens, the buffer will be queued as a normal buffer. ++ * ++ * ++ * Before After ++ * +-------------+ +-------------+ ++ * | HEADROOM | | HEADROOM | ++ * | | +-------------+ <- data ++ * | | | amsdu_txhdr | ++ * | | | * pad size | ++ * | | +-------------+ ++ * | | | ETH hdr | keep original eth hdr ++ * | | | | to restore it once transmitted ++ * | | +-------------+ <- packet_addr[x] ++ * | | | Pad | ++ * | | +-------------+ ++ * data -> +-------------+ | AMSDU HDR | ++ * | ETH hdr | +-------------+ ++ * | | | LLC/SNAP | ++ * +-------------+ +-------------+ ++ * | DATA | | DATA | ++ * | | | | ++ * +-------------+ +-------------+ ++ * ++ * Called with tx_lock hold ++ */ ++static int rwnx_amsdu_add_subframe_header(struct rwnx_hw *rwnx_hw, ++ struct sk_buff *skb, ++ struct rwnx_sw_txhdr *sw_txhdr) ++{ ++ struct rwnx_amsdu *amsdu = &sw_txhdr->amsdu; ++ struct rwnx_amsdu_txhdr *amsdu_txhdr; ++ struct ethhdr *amsdu_hdr, *eth = (struct ethhdr *)skb->data; ++ int headroom_need, map_len, msdu_len; ++ dma_addr_t dma_addr; ++ u8 *pos, *map_start; ++ ++ msdu_len = skb->len - sizeof(*eth); ++ headroom_need = sizeof(*amsdu_txhdr) + amsdu->pad + ++ sizeof(*amsdu_hdr); ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ headroom_need += sizeof(rfc1042_header) + 2; ++ msdu_len += sizeof(rfc1042_header) + 2; ++ } ++ ++ /* we should have enough headroom (checked in xmit) */ ++ if (WARN_ON(skb_headroom(skb) < headroom_need)) { ++ return -1; ++ } ++ ++ /* allocate headroom */ ++ pos = skb_push(skb, headroom_need); ++ amsdu_txhdr = (struct rwnx_amsdu_txhdr *)pos; ++ pos += sizeof(*amsdu_txhdr); ++ ++ /* move eth header */ ++ memmove(pos, eth, sizeof(*eth)); ++ eth = (struct ethhdr *)pos; ++ pos += sizeof(*eth); ++ ++ /* Add padding from previous subframe */ ++ map_start = pos; ++ memset(pos, 0, amsdu->pad); ++ pos += amsdu->pad; ++ ++ /* Add AMSDU hdr */ ++ amsdu_hdr = (struct ethhdr *)pos; ++ memcpy(amsdu_hdr->h_dest, eth->h_dest, ETH_ALEN); ++ memcpy(amsdu_hdr->h_source, eth->h_source, ETH_ALEN); ++ amsdu_hdr->h_proto = htons(msdu_len); ++ pos += sizeof(*amsdu_hdr); ++ ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); ++ pos += sizeof(rfc1042_header); ++ } ++ ++ /* MAP (and sync) memory for DMA */ ++ map_len = msdu_len + amsdu->pad + sizeof(*amsdu_hdr); ++ dma_addr = dma_map_single(rwnx_hw->dev, map_start, map_len, ++ DMA_BIDIRECTIONAL); ++ if (WARN_ON(dma_mapping_error(rwnx_hw->dev, dma_addr))) { ++ pos -= sizeof(*eth); ++ memmove(pos, eth, sizeof(*eth)); ++ skb_pull(skb, headroom_need); ++ return -1; ++ } ++ ++ /* update amdsu_txhdr */ ++ amsdu_txhdr->map_len = map_len; ++ amsdu_txhdr->dma_addr = dma_addr; ++ amsdu_txhdr->skb = skb; ++ amsdu_txhdr->pad = amsdu->pad; ++ amsdu_txhdr->msdu_len = msdu_len; ++ ++ /* update rwnx_sw_txhdr (of the first subframe) */ ++ BUG_ON(amsdu->nb != sw_txhdr->desc.host.packet_cnt); ++ sw_txhdr->desc.host.packet_addr[amsdu->nb] = dma_addr; ++ sw_txhdr->desc.host.packet_len[amsdu->nb] = map_len; ++ sw_txhdr->desc.host.packet_cnt++; ++ amsdu->nb++; ++ ++ amsdu->pad = AMSDU_PADDING(map_len - amsdu->pad); ++ list_add_tail(&amsdu_txhdr->list, &amsdu->hdrs); ++ amsdu->len += map_len; ++ ++ trace_amsdu_subframe(sw_txhdr); ++ return 0; ++} ++ ++/** ++ * rwnx_amsdu_add_subframe - Add this buffer as an A-MSDU subframe if possible ++ * ++ * @rwnx_hw Driver main data ++ * @skb Buffer to aggregate if possible ++ * @sta Destination STA ++ * @txq sta's txq used for this buffer ++ * ++ * Tyr to aggregate the buffer in an A-MSDU. If it succeed then the ++ * buffer is added as a new A-MSDU subframe with AMSDU and LLC/SNAP ++ * headers added (so FW won't have to modify this subframe). ++ * ++ * To be added as subframe : ++ * - sta must allow amsdu ++ * - buffer must be aggregable (to be defined) ++ * - at least one other aggregable buffer is pending in the queue ++ * or an a-msdu (with enough free space) is currently in progress ++ * ++ * returns true if buffer has been added as A-MDSP subframe, false otherwise ++ * ++ */ ++static bool rwnx_amsdu_add_subframe(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, ++ struct rwnx_sta *sta, struct rwnx_txq *txq) ++{ ++ bool res = false; ++ struct ethhdr *eth; ++ ++ /* immediately return if amsdu are not allowed for this sta */ ++ if (!txq->amsdu_len || rwnx_hw->mod_params->amsdu_maxnb < 2 || ++ !rwnx_amsdu_is_aggregable(skb) ++ ) ++ return false; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (txq->amsdu) { ++ /* aggreagation already in progress, add this buffer if enough space ++ available, otherwise end the current amsdu */ ++ struct rwnx_sw_txhdr *sw_txhdr = txq->amsdu; ++ eth = (struct ethhdr *)(skb->data); ++ ++ if (((sw_txhdr->amsdu.len + sw_txhdr->amsdu.pad + ++ rwnx_amsdu_subframe_length(eth, skb->len)) > txq->amsdu_len) || ++ rwnx_amsdu_add_subframe_header(rwnx_hw, skb, sw_txhdr)) { ++ txq->amsdu = NULL; ++ goto end; ++ } ++ ++ if (sw_txhdr->amsdu.nb >= rwnx_hw->mod_params->amsdu_maxnb) { ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].done++; ++ /* max number of subframes reached */ ++ txq->amsdu = NULL; ++ } ++ } else { ++ /* Check if a new amsdu can be started with the previous buffer ++ (if any) and this one */ ++ struct sk_buff *skb_prev = skb_peek_tail(&txq->sk_list); ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ int len1, len2; ++ ++ if (!skb_prev || !rwnx_amsdu_is_aggregable(skb_prev)) ++ goto end; ++ ++ txhdr = (struct rwnx_txhdr *)skb_prev->data; ++ sw_txhdr = txhdr->sw_hdr; ++ if ((sw_txhdr->amsdu.len) || ++ (sw_txhdr->desc.host.flags & TXU_CNTRL_RETRY)) ++ /* previous buffer is already a complete amsdu or a retry */ ++ goto end; ++ ++ eth = (struct ethhdr *)(skb_prev->data + sw_txhdr->headroom); ++ len1 = rwnx_amsdu_subframe_length(eth, (sw_txhdr->frame_len + ++ sizeof(struct ethhdr))); ++ ++ eth = (struct ethhdr *)(skb->data); ++ len2 = rwnx_amsdu_subframe_length(eth, skb->len); ++ ++ if (len1 + AMSDU_PADDING(len1) + len2 > txq->amsdu_len) ++ /* not enough space to aggregate those two buffers */ ++ goto end; ++ ++ /* Add subframe header. ++ Note: Fw will take care of adding AMDSU header for the first ++ subframe while generating 802.11 MAC header */ ++ INIT_LIST_HEAD(&sw_txhdr->amsdu.hdrs); ++ sw_txhdr->amsdu.len = len1; ++ sw_txhdr->amsdu.nb = 1; ++ sw_txhdr->amsdu.pad = AMSDU_PADDING(len1); ++ if (rwnx_amsdu_add_subframe_header(rwnx_hw, skb, sw_txhdr)) ++ goto end; ++ ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_AMSDU; ++ ++ if (sw_txhdr->amsdu.nb < rwnx_hw->mod_params->amsdu_maxnb) ++ txq->amsdu = sw_txhdr; ++ else ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].done++; ++ } ++ ++ res = true; ++ ++end: ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ return res; ++} ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++#ifdef CONFIG_BR_SUPPORT ++int aic_br_client_tx(struct rwnx_vif *vif, struct sk_buff **pskb) ++{ ++ struct sk_buff *skb = *pskb; ++ ++ /* if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) */ ++ { ++ void dhcp_flag_bcast(struct rwnx_vif *vif, struct sk_buff *skb); ++ int res, is_vlan_tag = 0, i, do_nat25 = 1; ++ unsigned short vlan_hdr = 0; ++ void *br_port = NULL; ++ ++ /* mac_clone_handle_frame(priv, skb); */ ++ ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = vif->ndev->br_port; ++#else /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) */ ++ rcu_read_lock(); ++ br_port = rcu_dereference(vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) */ ++#ifdef BR_SUPPORT_DEBUG ++ printk("SA=%pM, br_mac=%pM, type=0x%x, da[0]=%x, scdb=%pM, vif_type=%d\n", skb->data + MACADDRLEN, vif->br_mac, *((unsigned short *)(skb->data + MACADDRLEN * 2)), ++ skb->data[0], vif->scdb_mac,RWNX_VIF_TYPE(vif)); ++#endif ++ spin_lock_bh(&vif->br_ext_lock); ++ if (!(skb->data[0] & 1) && ++ br_port && ++ memcmp(skb->data + MACADDRLEN, vif->br_mac, MACADDRLEN) && ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) != __constant_htons(ETH_P_8021Q) && ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP) && ++ !memcmp(vif->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN) && vif->scdb_entry) { ++ memcpy(skb->data + MACADDRLEN, vif->ndev->dev_addr, MACADDRLEN); ++ vif->scdb_entry->ageing_timer = jiffies; ++ spin_unlock_bh(&vif->br_ext_lock); ++ } else ++ /* if (!priv->pmib->ethBrExtInfo.nat25_disable) */ ++ { ++ /* if (priv->dev->br_port && ++ * !memcmp(skb->data+MACADDRLEN, priv->br_mac, MACADDRLEN)) { */ ++#if 1 ++ if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_8021Q)) { ++ is_vlan_tag = 1; ++ vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2)); ++ skb_pull(skb, 4); ++ } ++ /* if SA == br_mac && skb== IP => copy SIP to br_ip ?? why */ ++ if (!memcmp(skb->data + MACADDRLEN, vif->br_mac, MACADDRLEN) && ++ (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP))) ++ memcpy(vif->br_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4); ++ ++ if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP)) { ++ if (memcmp(vif->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN)) { ++ #if 1 ++ void *scdb_findEntry(struct rwnx_vif *vif, unsigned char *macAddr, unsigned char *ipAddr); ++ ++ vif->scdb_entry = (struct nat25_network_db_entry *)scdb_findEntry(vif, ++ skb->data + MACADDRLEN, skb->data + WLAN_ETHHDR_LEN + 12); ++ if (vif->scdb_entry != NULL) { ++ memcpy(vif->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN); ++ memcpy(vif->scdb_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4); ++ vif->scdb_entry->ageing_timer = jiffies; ++ do_nat25 = 0; ++ } ++ #endif ++ } else { ++ if (vif->scdb_entry) { ++ vif->scdb_entry->ageing_timer = jiffies; ++ do_nat25 = 0; ++ } else { ++ memset(vif->scdb_mac, 0, MACADDRLEN); ++ memset(vif->scdb_ip, 0, 4); ++ } ++ } ++ } ++ spin_unlock_bh(&vif->br_ext_lock); ++#endif /* 1 */ ++ if (do_nat25) { ++ #if 1 ++ int nat25_db_handle(struct rwnx_vif *vif, struct sk_buff *skb, int method); ++ if (nat25_db_handle(vif, skb, NAT25_CHECK) == 0) { ++ struct sk_buff *newskb; ++ ++ if (is_vlan_tag) { ++ skb_push(skb, 4); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr; ++ } ++ ++ newskb = skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); ++ if (newskb == NULL) { ++ /* priv->ext_stats.tx_drops++; */ ++ printk("TX DROP: skb_copy fail!\n"); ++ /* goto stop_proc; */ ++ return -1; ++ } ++ dev_kfree_skb_any(skb); ++ ++ *pskb = skb = newskb; ++ if (is_vlan_tag) { ++ vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2)); ++ skb_pull(skb, 4); ++ } ++ } ++ ++ if (skb_is_nonlinear(skb)) ++ printk("%s(): skb_is_nonlinear!!\n", __FUNCTION__); ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) ++ res = skb_linearize(skb, GFP_ATOMIC); ++#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) */ ++ res = skb_linearize(skb); ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) */ ++ if (res < 0) { ++ printk("TX DROP: skb_linearize fail!\n"); ++ /* goto free_and_stop; */ ++ return -1; ++ } ++ ++ res = nat25_db_handle(vif, skb, NAT25_INSERT); ++ if (res < 0) { ++ if (res == -2) { ++ /* priv->ext_stats.tx_drops++; */ ++ printk("TX DROP: nat25_db_handle fail!\n"); ++ /* goto free_and_stop; */ ++ return -1; ++ ++ } ++ /* we just print warning message and let it go */ ++ /* DEBUG_WARN("%s()-%d: nat25_db_handle INSERT Warning!\n", __FUNCTION__, __LINE__); */ ++ /* return -1; */ /* return -1 will cause system crash on 2011/08/30! */ ++ return 0; ++ } ++ #endif ++ } ++ ++ memcpy(skb->data + MACADDRLEN, vif->ndev->dev_addr, MACADDRLEN); ++ ++ dhcp_flag_bcast(vif, skb); ++ ++ if (is_vlan_tag) { ++ skb_push(skb, 4); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr; ++ } ++ } ++#if 0 ++ else { ++ if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_8021Q)) ++ is_vlan_tag = 1; ++ ++ if (is_vlan_tag) { ++ if (ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A_VALN(skb->data)) ++ memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN); ++ } else { ++ if (ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A(skb->data)) ++ memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN); ++ } ++ } ++#endif /* 0 */ ++ ++ /* check if SA is equal to our MAC */ ++ if (memcmp(skb->data + MACADDRLEN, vif->ndev->dev_addr, MACADDRLEN)) { ++ /* priv->ext_stats.tx_drops++; */ ++ printk("TX DROP: untransformed frame SA:%02X%02X%02X%02X%02X%02X!\n", ++ skb->data[6], skb->data[7], skb->data[8], skb->data[9], skb->data[10], skb->data[11]); ++ /* goto free_and_stop; */ ++ return -1; ++ } ++ } ++ printk("%s:exit\n",__func__); ++ return 0; ++} ++#endif /* CONFIG_BR_SUPPORT */ ++ ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++/* return: ++ * 0, msg buf freed by the real driver ++ * others, skb need free by the caller,remember not use msg->skb! ++ */ ++ ++int intf_tx(struct rwnx_hw *priv,struct msg_buf *msg) ++{ ++ struct rwnx_vif *rwnx_vif = msg->rwnx_vif; ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct rwnx_sta *sta; ++ struct rwnx_txq *txq; ++ int headroom; ++ //int max_headroom; ++ int hdr_pads; ++ ++ u16 frame_len; ++ u16 frame_oft; ++ u8 tid; ++ struct sk_buff *skb=msg->skb; ++ struct ethhdr eth_t; ++ ++ move_tcpack_msg(rwnx_hw,msg); ++ kfree(msg); ++ ++ memcpy(ð_t, skb->data, sizeof(struct ethhdr)); ++ ++ /* Get the STA id and TID information */ ++ sta = rwnx_get_tx_priv(rwnx_vif, skb, &tid); ++ if (!sta) ++ goto free; ++ ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ if (txq->idx == TXQ_INACTIVE) ++ goto free; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (rwnx_amsdu_add_subframe(rwnx_hw, skb, sta, txq)) ++ return NETDEV_TX_OK; ++#endif ++ ++#ifdef CONFIG_BR_SUPPORT ++ if (1) {//(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ void *br_port = NULL; ++ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ s32 res = aic_br_client_tx(rwnx_vif, &skb); ++ if (res == -1) { ++ goto free; ++ } ++ } ++ } ++#endif /* CONFIG_BR_SUPPORT */ ++ ++ ++ /* Retrieve the pointer to the Ethernet data */ ++ // eth = (struct ethhdr *)skb->data; ++ ++ skb_pull(skb, 14); ++ //hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)eth); ++ hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)skb->data); ++ headroom = sizeof(struct rwnx_txhdr) + hdr_pads; ++ ++ skb_push(skb, headroom); ++ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) ++ goto free; ++ txhdr->sw_hdr = sw_txhdr; ++ desc = &sw_txhdr->desc; ++ ++ frame_len = (u16)skb->len - headroom;// - sizeof(*eth); ++ ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = rwnx_vif; ++ sw_txhdr->skb = skb; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ sw_txhdr->amsdu.len = 0; ++ sw_txhdr->amsdu.nb = 0; ++#endif ++ sw_txhdr->raw_frame = 0; ++ sw_txhdr->fixed_rate = 0; ++ ++ // Fill-in the descriptor ++ memcpy(&desc->host.eth_dest_addr, eth_t.h_dest, ETH_ALEN); ++ memcpy(&desc->host.eth_src_addr, eth_t.h_source, ETH_ALEN); ++ desc->host.ethertype = eth_t.h_proto; ++ desc->host.staid = sta->sta_idx; ++ desc->host.tid = tid; ++ if (unlikely(rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) ++ desc->host.vif_idx = rwnx_vif->ap_vlan.master->vif_index; ++ else ++ desc->host.vif_idx = rwnx_vif->vif_index; ++ ++ if (rwnx_vif->use_4addr && (sta->sta_idx < NX_REMOTE_STA_MAX)) ++ desc->host.flags = TXU_CNTRL_USE_4ADDR; ++ else ++ desc->host.flags = 0; ++ ++ if ((rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) && ++ rwnx_vif->sta.tdls_sta && ++ (memcmp(desc->host.eth_dest_addr.array, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) { ++ desc->host.flags |= TXU_CNTRL_TDLS; ++ rwnx_vif->sta.tdls_sta->tdls.last_tid = desc->host.tid; ++ //rwnx_vif->sta.tdls_sta->tdls.last_sn = desc->host.sn; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) { ++ if (rwnx_vif->is_resending) { ++ desc->host.flags |= TXU_CNTRL_MESH_FWD; ++ } ++ } ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_len[0] = frame_len; ++#else ++ desc->host.packet_len = frame_len; ++#endif ++ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ if (unlikely(rwnx_prep_tx(rwnx_hw, txhdr))) { ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_BUSY; ++ } ++ ++ /* Fill-in TX descriptor */ ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr) ++ + hdr_pads;// + sizeof(*eth); ++#if 0 ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_cnt = 1; ++#else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++#endif ++#endif ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ return 0;//NETDEV_TX_OK ++ ++free: ++ dev_kfree_skb_any(skb); ++ ++ return 0;//NETDEV_TX_OK ++} ++#endif ++ ++/** ++ * netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, ++ * struct net_device *dev); ++ * Called when a packet needs to be transmitted. ++ * Must return NETDEV_TX_OK , NETDEV_TX_BUSY. ++ * (can also return NETDEV_TX_LOCKED if NETIF_F_LLTX) ++ * ++ * - Initialize the desciptor for this pkt (stored in skb before data) ++ * - Push the pkt in the corresponding Txq ++ * - If possible (i.e. credit available and not in PS) the pkt is pushed ++ * to fw ++ */ ++netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct rwnx_sta *sta; ++ struct rwnx_txq *txq; ++ int headroom; ++ int max_headroom; ++ int hdr_pads; ++ ++ u16 frame_len; ++ u16 frame_oft; ++ u8 tid; ++ ++ struct ethhdr eth_t; ++#ifdef CONFIG_FILTER_TCP_ACK ++ struct msg_buf *msgbuf = NULL; ++#endif ++ ++#ifdef CONFIG_ONE_TXQ ++ skb->queue_mapping = rwnx_select_txq(rwnx_vif, skb); ++#endif ++ ++ sk_pacing_shift_update(skb->sk, rwnx_hw->tcp_pacing_shift); ++ max_headroom = sizeof(struct rwnx_txhdr); ++ ++ /* check whether the current skb can be used */ ++ if (skb_shared(skb) || (skb_headroom(skb) < max_headroom) || ++ (skb_cloned(skb) && (dev->priv_flags & IFF_BRIDGE_PORT))) { ++ struct sk_buff *newskb = skb_copy_expand(skb, max_headroom, 0, ++ GFP_ATOMIC); ++ if (unlikely(newskb == NULL)) ++ goto free; ++ ++ dev_kfree_skb_any(skb); ++ ++ skb = newskb; ++ } ++ ++ if(skb->priority < 3) ++ skb->priority = 0; ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ if(cpu_to_le16(skb->len) <= MAX_TCP_ACK){ ++ msgbuf=intf_tcp_alloc_msg(msgbuf); ++ msgbuf->rwnx_vif=rwnx_vif; ++ msgbuf->skb=skb; ++ if(filter_send_tcp_ack(rwnx_hw,msgbuf,skb->data,cpu_to_le16(skb->len))){ ++ return NETDEV_TX_OK; ++ }else{ ++ move_tcpack_msg(rwnx_hw,msgbuf); ++ kfree(msgbuf); ++ } ++ } ++#endif ++ ++ memcpy(ð_t, skb->data, sizeof(struct ethhdr)); ++ ++ /* Get the STA id and TID information */ ++ sta = rwnx_get_tx_priv(rwnx_vif, skb, &tid); ++ if (!sta) ++ goto free; ++ ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ if (txq->idx == TXQ_INACTIVE) ++ goto free; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (rwnx_amsdu_add_subframe(rwnx_hw, skb, sta, txq)) ++ return NETDEV_TX_OK; ++#endif ++ ++ #ifdef CONFIG_BR_SUPPORT ++ if (1) {//(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ void *br_port = NULL; ++ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ s32 res = aic_br_client_tx(rwnx_vif, &skb); ++ if (res == -1) { ++ goto free; ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ ++ /* Retrieve the pointer to the Ethernet data */ ++ // eth = (struct ethhdr *)skb->data; ++ ++ skb_pull(skb, 14); ++ //hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)eth); ++ hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)skb->data); ++ headroom = sizeof(struct rwnx_txhdr) + hdr_pads; ++ ++ skb_push(skb, headroom); ++ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) ++ goto free; ++ txhdr->sw_hdr = sw_txhdr; ++ desc = &sw_txhdr->desc; ++ ++ frame_len = (u16)skb->len - headroom;// - sizeof(*eth); ++ ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = rwnx_vif; ++ sw_txhdr->skb = skb; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ sw_txhdr->amsdu.len = 0; ++ sw_txhdr->amsdu.nb = 0; ++#endif ++ sw_txhdr->raw_frame = 0; ++ sw_txhdr->fixed_rate = 0; ++ ++ // Fill-in the descriptor ++ memcpy(&desc->host.eth_dest_addr, eth_t.h_dest, ETH_ALEN); ++ memcpy(&desc->host.eth_src_addr, eth_t.h_source, ETH_ALEN); ++ desc->host.ethertype = eth_t.h_proto; ++ desc->host.staid = sta->sta_idx; ++ desc->host.tid = tid; ++ if (unlikely(rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) ++ desc->host.vif_idx = rwnx_vif->ap_vlan.master->vif_index; ++ else ++ desc->host.vif_idx = rwnx_vif->vif_index; ++ ++ if (rwnx_vif->use_4addr && (sta->sta_idx < NX_REMOTE_STA_MAX)) ++ desc->host.flags = TXU_CNTRL_USE_4ADDR; ++ else ++ desc->host.flags = 0; ++ ++ if ((rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) && ++ rwnx_vif->sta.tdls_sta && ++ (memcmp(desc->host.eth_dest_addr.array, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) { ++ desc->host.flags |= TXU_CNTRL_TDLS; ++ rwnx_vif->sta.tdls_sta->tdls.last_tid = desc->host.tid; ++ //rwnx_vif->sta.tdls_sta->tdls.last_sn = desc->host.sn; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) { ++ if (rwnx_vif->is_resending) { ++ desc->host.flags |= TXU_CNTRL_MESH_FWD; ++ } ++ } ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_len[0] = frame_len; ++#else ++ desc->host.packet_len = frame_len; ++#endif ++ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ if (unlikely(rwnx_prep_tx(rwnx_hw, txhdr))) { ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_BUSY; ++ } ++ ++ /* Fill-in TX descriptor */ ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr) ++ + hdr_pads;// + sizeof(*eth); ++#if 0 ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_cnt = 1; ++#else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++#endif ++#endif ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ return NETDEV_TX_OK; ++ ++free: ++ dev_kfree_skb_any(skb); ++ ++ return NETDEV_TX_OK; ++} ++ ++#ifdef CONFIG_RWNX_MON_XMIT ++/** ++ * netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, ++ * struct net_device *dev); ++ * Called when a packet needs to be transmitted. ++ * Must return NETDEV_TX_OK , NETDEV_TX_BUSY. ++ * (can also return NETDEV_TX_LOCKED if NETIF_F_LLTX) ++ * ++ * - Initialize the desciptor for this pkt (stored in skb before data) ++ * - Push the pkt in the corresponding Txq ++ * - If possible (i.e. credit available and not in PS) the pkt is pushed ++ * to fw ++ */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)) ++#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20 ++#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 ++#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 ++#endif ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)) ++#define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01 ++#endif ++ ++char bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; ++netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ int rtap_len, ret, idx; ++ struct ieee80211_radiotap_header *rtap_hdr; // net/ieee80211_radiotap.h ++ struct ieee80211_radiotap_iterator iterator; // net/cfg80211.h ++ u8_l *rtap_buf = (u8_l *)skb->data; ++ u8_l rate; ++ ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct rwnx_sta *sta; ++ struct rwnx_txq *txq; ++ u16_l frame_len, headroom, frame_oft; ++ u8_l tid, rate_fmt = FORMATMOD_NON_HT, rate_idx = 0, txsig_bw = PHY_CHNL_BW_20; ++ u8_l *pframe, *data; ++ bool robust; ++ struct sk_buff *skb_mgmt; ++ bool offchan = false; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ rtap_hdr = (struct ieee80211_radiotap_header*)(rtap_buf); ++ rtap_len = ieee80211_get_radiotap_len(rtap_buf);//max_length ++ frame_len = skb->len; ++ ++ AICWFDBG(LOGINFO, "rwnx_start_monitor_if_xmit, skb_len=%d, rtap_len=%d\n", skb->len, rtap_len); ++//rwnx_data_dump((char*)__func__, skb->data, skb->len); ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ if (unlikely(rtap_hdr->it_version)){ ++ AICWFDBG(LOGERROR, "%s itv \r\n", __func__); ++ goto free_tag; ++ } ++ ++ if (unlikely(skb->len < rtap_len)){ ++ AICWFDBG(LOGERROR, "%s skb->len < rtap_len \r\n", __func__); ++ goto free_tag; ++ } ++ ++ if (unlikely(rtap_len < sizeof(struct ieee80211_radiotap_header))){ ++ AICWFDBG(LOGERROR, "%s rtap_len < sizeof(struct ieee80211_radiotap_header) \r\n", __func__); ++ goto free_tag; ++ } ++ ++ frame_len -= rtap_len; ++ pframe = rtap_buf + rtap_len; ++ ++ // Parse radiotap for injection items and overwrite attribs as needed ++ ret = ieee80211_radiotap_iterator_init(&iterator, rtap_hdr, rtap_len, NULL); ++ while (!ret) { ++ ret = ieee80211_radiotap_iterator_next(&iterator); ++ if (ret) { ++ continue; ++ } ++ AICWFDBG(LOGDEBUG, "%s iterator.this_arg_index:%d iterator.this_arg:%x\r\n", __func__, ++ iterator.this_arg_index, *iterator.this_arg); ++ switch (iterator.this_arg_index) { ++ case IEEE80211_RADIOTAP_RATE: ++ // This is basic 802.11b/g rate; use MCS/VHT for higher rates ++ rate = *iterator.this_arg; ++ AICWFDBG(LOGDEBUG, "rate=0x%x\n", rate); ++ for (idx = 0; idx < HW_RATE_MAX; idx++) { ++ if ((rate * 5) == tx_legrates_lut_rate[idx]) { ++ AICWFDBG(LOGDEBUG, "%s datarate:%d \r\n", __func__, tx_legrates_lut_rate[idx]); ++ break; ++ } ++ } ++ ++ if (idx < HW_RATE_MAX) { ++ rate_idx = idx; ++ AICWFDBG(LOGDEBUG, "rate_idx = %d \r\n", rate_idx); ++ } else { ++ AICWFDBG(LOGERROR, "invalid radiotap rate: %d\n", rate); ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_TX_FLAGS: { ++ u16_l txflags = get_unaligned_le16(iterator.this_arg); ++ AICWFDBG(LOGDEBUG, "txflags=0x%x\n", txflags); ++ if ((txflags & IEEE80211_RADIOTAP_F_TX_NOACK) == 0) { ++ AICWFDBG(LOGDEBUG, " TX_NOACK\n"); ++ } ++ if (txflags & 0x0010) { // Use preconfigured seq num ++ // NOTE: this is currently ignored due to qos_en=_FALSE and HW seq num override ++ AICWFDBG(LOGDEBUG, " GetSequence\n"); ++ } ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_MCS: { ++ u8_l mcs_have = iterator.this_arg[0]; ++ AICWFDBG(LOGDEBUG, "mcs_have=0x%x\n", mcs_have); ++ rate_fmt = FORMATMOD_HT_MF; ++ if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_BW) { ++ u8_l bw = (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_BW_MASK); ++ u8_l ch_offset = 0; ++ if (bw == IEEE80211_RADIOTAP_MCS_BW_40) { ++ txsig_bw = PHY_CHNL_BW_40; ++ } else if (bw == IEEE80211_RADIOTAP_MCS_BW_20L) { ++ bw = IEEE80211_RADIOTAP_MCS_BW_20; ++ ch_offset = 1; // CHNL_OFFSET_LOWER; ++ } else if (bw == IEEE80211_RADIOTAP_MCS_BW_20U) { ++ bw = IEEE80211_RADIOTAP_MCS_BW_20; ++ ch_offset = 2; // CHNL_OFFSET_UPPER; ++ } ++ AICWFDBG(LOGDEBUG, " bw=%d, ch_offset=%d\n", bw, ch_offset); ++ } ++ if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_MCS) { ++ u8_l fixed_rate = iterator.this_arg[2] & 0x7f; ++ if (fixed_rate > 31) { ++ fixed_rate = 0; ++ } ++ rate_idx = fixed_rate; ++ AICWFDBG(LOGDEBUG, " fixed_rate=0x%x\n", fixed_rate); ++ } ++ if ((mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_GI) && (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_SGI)) { ++ AICWFDBG(LOGDEBUG, " sgi\n"); ++ } ++ if ((mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_FEC) && (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_FEC_LDPC)) { ++ AICWFDBG(LOGDEBUG, " ldpc\n"); ++ } ++ if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_STBC) { ++ u8 stbc = (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT; ++ AICWFDBG(LOGDEBUG, " stbc=0x%x\n", stbc); ++ } ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_VHT: { ++ unsigned int mcs, nss; ++ u8 known = iterator.this_arg[0]; ++ u8 flags = iterator.this_arg[2]; ++ rate_fmt = FORMATMOD_VHT; ++ AICWFDBG(LOGDEBUG, "known=0x%x, flags=0x%x\n", known, flags); ++ // NOTE: this code currently only supports 1SS for radiotap defined rates ++ if ((known & IEEE80211_RADIOTAP_VHT_KNOWN_STBC) && (flags & IEEE80211_RADIOTAP_VHT_FLAG_STBC)) { ++ AICWFDBG(LOGDEBUG, " stbc\n"); ++ } ++ if ((known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) && (flags & IEEE80211_RADIOTAP_VHT_FLAG_SGI)) { ++ AICWFDBG(LOGDEBUG, " sgi\n"); ++ } ++ if (known & IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) { ++ u8_l bw = iterator.this_arg[3] & 0x1F; ++ AICWFDBG(LOGDEBUG, " bw=0x%x\n",bw); ++ // NOTE: there are various L and U, but we just use straight 20/40/80 ++ // since it's not clear how to set CHNL_OFFSET_LOWER/_UPPER with different ++ // sideband sizes/configurations. TODO. ++ // Also, any 160 is treated as 80 due to lack of WIDTH_160. ++ txsig_bw = PHY_CHNL_BW_40; ++ if (bw == 0) { ++ txsig_bw = PHY_CHNL_BW_20; ++ AICWFDBG(LOGDEBUG, " 20M\n"); ++ } else if (bw >=1 && bw <= 3) { ++ AICWFDBG(LOGDEBUG, " 40M\n"); ++ } else if (bw >=4 && bw <= 10) { ++ AICWFDBG(LOGDEBUG, " 80M\n"); ++ } else if (bw >= 11 && bw <= 25) { ++ AICWFDBG(LOGDEBUG, " 160M\n"); ++ } ++ } ++ // User 0 ++ nss = iterator.this_arg[4] & 0x0F; // Number of spatial streams ++ AICWFDBG(LOGDEBUG, " nss=0x%x\n", nss); ++ if (nss > 0) { ++ if (nss > 4) nss = 4; ++ mcs = (iterator.this_arg[4]>>4) & 0x0F; // MCS rate index ++ if (mcs > 8) mcs = 9; ++ rate_idx = mcs; ++ AICWFDBG(LOGDEBUG, " mcs=0x%x\n", mcs); ++ if (iterator.this_arg[8] & IEEE80211_RADIOTAP_CODING_LDPC_USER0) { ++ AICWFDBG(LOGDEBUG, " ldpc\n"); ++ } ++ } ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_HE: { ++ u16 data1 = ((u16)iterator.this_arg[1] << 8) | iterator.this_arg[0]; ++ u16 data2 = ((u16)iterator.this_arg[3] << 8) | iterator.this_arg[2]; ++ u16 data3 = ((u16)iterator.this_arg[5] << 8) | iterator.this_arg[4]; ++ u16 data5 = ((u16)iterator.this_arg[9] << 8) | iterator.this_arg[8]; ++ u8 fmt_he = data1 & IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK; ++ if (fmt_he == IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU) { ++ rate_fmt = FORMATMOD_HE_MU; ++ } else if (fmt_he == IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU) { ++ rate_fmt = FORMATMOD_HE_ER; ++ } else { ++ rate_fmt = FORMATMOD_HE_SU; ++ } ++ if (data1 & IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN) { ++ u8 mcs = (data3 & IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS) >> 8; ++ if (mcs > 11) mcs = 11; ++ rate_idx = mcs; ++ } ++ if (data1 & IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN) { ++ u8 bw = data5 & IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC; ++ txsig_bw = (bw == IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ) ? PHY_CHNL_BW_20 : PHY_CHNL_BW_40; ++ } ++ if (data2 & IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN) { ++ u8 gi = (data5 & IEEE80211_RADIOTAP_HE_DATA5_GI) >> 4; ++ AICWFDBG(LOGDEBUG, " gi: %d\n", gi); ++ } ++ } ++ break; ++ ++ default: ++ AICWFDBG(LOGERROR, "unparsed arg: 0x%x\n",iterator.this_arg_index); ++ break; ++ } ++ } ++ ++ #if 0 ++ // dump buffer ++ tmp_len = 128; ++ if (skb->len < 128) { ++ tmp_len = skb->len; ++ } ++ for (idx = 0; idx < tmp_len; idx+=16) { ++ printk("[%04X] %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", idx, ++ rtap_buf[idx+0],rtap_buf[idx+1],rtap_buf[idx+2],rtap_buf[idx+3], ++ rtap_buf[idx+4],rtap_buf[idx+5],rtap_buf[idx+6],rtap_buf[idx+7], ++ rtap_buf[idx+8],rtap_buf[idx+9],rtap_buf[idx+10],rtap_buf[idx+11], ++ rtap_buf[idx+12],rtap_buf[idx+13],rtap_buf[idx+14],rtap_buf[idx+15]); ++ } ++ #endif ++ //rwnx_data_dump((char*)__func__, pframe, frame_len); ++ ++ /* Get the STA id and TID information */ ++ sta = rwnx_get_tx_priv(vif, skb, &tid); ++ //if (!sta) { ++ // printk("sta=null, tid=0x%x\n", tid); ++ //} ++ /* Set TID and Queues indexes */ ++ if (sta) { ++ txq = rwnx_txq_sta_get(sta, 8, rwnx_hw); ++ } else { ++ if (offchan) ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ else ++ txq = rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE); ++ } ++ if (txq->idx == TXQ_INACTIVE) { ++ AICWFDBG(LOGERROR, "TXQ_INACTIVE\n"); ++ goto free_tag; ++ } ++ // prepare to xmit ++ headroom = sizeof(struct rwnx_txhdr); ++ skb_mgmt = dev_alloc_skb(headroom + frame_len); ++ if (!skb_mgmt) { ++ AICWFDBG(LOGERROR, "skb_mgmt alloc fail\n"); ++ goto free_tag; ++ } ++ skb_reserve(skb_mgmt, headroom); ++ data = skb_put(skb_mgmt, frame_len); ++ /* Copy the provided data */ ++ memcpy(data, pframe, frame_len); ++ robust = ieee80211_is_robust_mgmt_frame( ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)) ++ (void*)skb_mgmt ++#else ++ skb_mgmt ++#endif ++ ); ++ skb_push(skb_mgmt, headroom); ++ /* Fill the TX Header */ ++ txhdr = (struct rwnx_txhdr *)skb_mgmt->data; ++ txhdr->hw_hdr.cfm.status.value = 0; ++ /* Fill the SW TX Header */ ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) { ++ dev_kfree_skb(skb_mgmt); ++ AICWFDBG(LOGERROR, "sw_txhdr alloc fail\n"); ++ goto free_tag; ++ } ++ txhdr->sw_hdr = sw_txhdr; ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = vif; ++ sw_txhdr->skb = skb_mgmt; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb_mgmt->len - offsetof(struct rwnx_txhdr, hw_hdr); ++ sw_txhdr->raw_frame = 1; ++ sw_txhdr->fixed_rate = 1; ++ sw_txhdr->rate_config = ((rate_fmt << FORMAT_MOD_TX_RCX_OFT) & FORMAT_MOD_TX_RCX_MASK) | ++ ((txsig_bw << BW_TX_RCX_OFT) & BW_TX_RCX_MASK) | ++ ((rate_idx << MCS_INDEX_TX_RCX_OFT) & MCS_INDEX_TX_RCX_MASK); // from radiotap ++ /* Fill the Descriptor to be provided to the MAC SW */ ++ desc = &sw_txhdr->desc; ++ desc->host.staid = (sta) ? sta->sta_idx : 0xFF; ++ desc->host.vif_idx = vif->vif_index; ++ desc->host.tid = 0xFF; ++ desc->host.flags = TXU_CNTRL_MGMT; ++ if (robust) { ++ desc->host.flags |= TXU_CNTRL_MGMT_ROBUST; ++ } ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr); ++ #if 0 ++ #ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_len[0] = frame_len; ++ desc->host.packet_cnt = 1; ++ #else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_len = frame_len; ++ #endif ++ #else ++ desc->host.packet_len = frame_len; ++ #endif ++ ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ memcpy(desc->host.eth_dest_addr.array, bcast, ETH_ALEN); ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ AICWFDBG(LOGTRACE, "%s send data\r\n", __func__); ++ if (rwnx_txq_queue_skb(skb_mgmt, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++free_tag: ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++} ++#endif ++ ++ ++/** ++ * rwnx_start_mgmt_xmit - Transmit a management frame ++ * ++ * @vif: Vif that send the frame ++ * @sta: Destination of the frame. May be NULL if the destiantion is unknown ++ * to the AP. ++ * @params: Mgmt frame parameters ++ * @offchan: Indicate whether the frame must be send via the offchan TXQ. ++ * (is is redundant with params->offchan ?) ++ * @cookie: updated with a unique value to identify the frame with upper layer ++ * ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct cfg80211_mgmt_tx_params *params, bool offchan, ++ u64 *cookie) ++#else ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct ieee80211_channel *channel, bool offchan, ++ unsigned int wait, const u8 *buf, size_t len, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ bool no_cck, ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) ++ bool dont_wait_for_ack, ++ #endif ++ u64 *cookie) ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++{ ++ struct rwnx_hw *rwnx_hw = vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct sk_buff *skb; ++ u16 frame_len, headroom, frame_oft; ++ u8 *data; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ struct rwnx_txq *txq; ++ bool robust; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ const u8 *buf = params->buf; ++ size_t len = params->len; ++ bool no_cck = params->no_cck; ++ #endif ++ ++ AICWFDBG(LOGDEBUG,"mgmt xmit %x %x ",buf[0],buf[1]); ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ headroom = sizeof(struct rwnx_txhdr); ++ frame_len = len; ++ ++ //---------------------------------------------------------------------- ++ ++ /* Set TID and Queues indexes */ ++ if (sta) { ++ txq = rwnx_txq_sta_get(sta, 8, rwnx_hw); ++ } else { ++ if (offchan) ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ else ++ txq = rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE); ++ } ++ ++ /* Ensure that TXQ is active */ ++ if (txq->idx == TXQ_INACTIVE) { ++ netdev_dbg(vif->ndev, "TXQ inactive\n"); ++ return -EBUSY; ++ } ++ ++ /* ++ * Create a SK Buff object that will contain the provided data ++ */ ++ skb = dev_alloc_skb(headroom + frame_len); ++ ++ if (!skb) { ++ return -ENOMEM; ++ } ++ ++ *cookie = (unsigned long)skb; ++ ++ /* ++ * Move skb->data pointer in order to reserve room for rwnx_txhdr ++ * headroom value will be equal to sizeof(struct rwnx_txhdr) ++ */ ++ skb_reserve(skb, headroom); ++ ++ /* ++ * Extend the buffer data area in order to contain the provided packet ++ * len value (for skb) will be equal to param->len ++ */ ++ data = skb_put(skb, frame_len); ++ /* Copy the provided data */ ++ memcpy(data, buf, frame_len); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) ++ robust = ieee80211_is_robust_mgmt_frame(skb); ++#else ++ if (skb->len < 25){ ++ robust = false; ++ } ++ robust = ieee80211_is_robust_mgmt_frame((void *)skb->data); ++#endif ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) ++ /* Update CSA counter if present */ ++ if (unlikely(params->n_csa_offsets) && ++ vif->wdev.iftype == NL80211_IFTYPE_AP && ++ vif->ap.csa) { ++ int i; ++ ++ data = skb->data; ++ for (i = 0; i < params->n_csa_offsets ; i++) { ++ data[params->csa_offsets[i]] = vif->ap.csa->count; ++ } ++ } ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ ++ /* ++ * Go back to the beginning of the allocated data area ++ * skb->data pointer will move backward ++ */ ++ skb_push(skb, headroom); ++ ++ //---------------------------------------------------------------------- ++ ++ /* Fill the TX Header */ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ //---------------------------------------------------------------------- ++ ++ /* Fill the SW TX Header */ ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) { ++ dev_kfree_skb(skb); ++ return -ENOMEM; ++ } ++ txhdr->sw_hdr = sw_txhdr; ++ ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = vif; ++ sw_txhdr->skb = skb; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ sw_txhdr->amsdu.len = 0; ++ sw_txhdr->amsdu.nb = 0; ++#endif ++ sw_txhdr->raw_frame = 0; ++ sw_txhdr->fixed_rate = 0; ++ ++ //---------------------------------------------------------------------- ++ ++ /* Fill the Descriptor to be provided to the MAC SW */ ++ desc = &sw_txhdr->desc; ++ ++ desc->host.ethertype = 0; ++ desc->host.staid = (sta) ? sta->sta_idx : 0xFF; ++ desc->host.vif_idx = vif->vif_index; ++ desc->host.tid = 0xFF; ++ desc->host.flags = TXU_CNTRL_MGMT; ++ if (robust) ++ desc->host.flags |= TXU_CNTRL_MGMT_ROBUST; ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_len[0] = frame_len; ++#else ++ desc->host.packet_len = frame_len; ++#endif ++ ++ if (no_cck) { ++ desc->host.flags |= TXU_CNTRL_MGMT_NO_CCK; ++ } ++ ++ /* Get DMA Address */ ++ if (unlikely(rwnx_prep_tx(rwnx_hw, txhdr))) { ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ dev_kfree_skb(skb); ++ return -EBUSY; ++ } ++ ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr); ++#if 0 ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_cnt = 1; ++#else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++#endif ++#endif ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ //---------------------------------------------------------------------- ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ return 0; ++} ++ ++/** ++ * rwnx_txdatacfm - FW callback for TX confirmation ++ * ++ * called with tx_lock hold ++ */ ++int rwnx_txdatacfm(void *pthis, void *host_id) ++{ ++ struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)pthis; ++ struct sk_buff *skb = host_id; ++ struct rwnx_txhdr *txhdr; ++ union rwnx_hw_txstatus rwnx_txst; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct rwnx_hwq *hwq; ++ struct rwnx_txq *txq; ++ int headroom; ++ //int peek_off = offsetof(struct rwnx_hw_txhdr, cfm); ++ //int peek_len = sizeof(((struct rwnx_hw_txhdr *)0)->cfm); ++ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ sw_txhdr = txhdr->sw_hdr; ++ ++ /* Read status in the TX control header */ ++ rwnx_txst = txhdr->hw_hdr.cfm.status; ++ ++ /* Check status in the header. If status is null, it means that the buffer ++ * was not transmitted and we have to return immediately */ ++ if (rwnx_txst.value == 0) { ++ return -1; ++ } ++ ++#ifdef AICWF_USB_SUPPORT ++ if (rwnx_hw->usbdev->state == USB_DOWN_ST) { ++ headroom = sw_txhdr->headroom; ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ consume_skb(skb); ++ return 0; ++ } ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ if(rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { ++ headroom = sw_txhdr->headroom; ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ consume_skb(skb); ++ return 0; ++ } ++#endif ++ ++ txq = sw_txhdr->txq; ++ /* don't use txq->hwq as it may have changed between push and confirm */ ++ hwq = &rwnx_hw->hwq[sw_txhdr->hw_queue]; ++ rwnx_txq_confirm_any(rwnx_hw, txq, hwq, sw_txhdr); ++ ++ /* Update txq and HW queue credits */ ++ if (sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT) { ++ printk("done=%d retry_required=%d sw_retry_required=%d acknowledged=%d\n", ++ rwnx_txst.tx_done, rwnx_txst.retry_required, ++ rwnx_txst.sw_retry_required, rwnx_txst.acknowledged); ++#ifdef CREATE_TRACE_POINTS ++ trace_mgmt_cfm(sw_txhdr->rwnx_vif->vif_index, ++ (sw_txhdr->rwnx_sta) ? sw_txhdr->rwnx_sta->sta_idx : 0xFF, ++ rwnx_txst.acknowledged); ++#endif ++ /* Confirm transmission to CFG80211 */ ++ cfg80211_mgmt_tx_status(&sw_txhdr->rwnx_vif->wdev, ++ (unsigned long)skb, ++ (skb->data + sw_txhdr->headroom), ++ sw_txhdr->frame_len, ++ rwnx_txst.acknowledged, ++ GFP_ATOMIC); ++ } else if ((txq->idx != TXQ_INACTIVE) && ++ (rwnx_txst.retry_required || rwnx_txst.sw_retry_required)) { ++ bool sw_retry = (rwnx_txst.sw_retry_required) ? true : false; ++ ++ /* Reset the status */ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ /* The confirmed packet was part of an AMPDU and not acked ++ * correctly, so reinject it in the TX path to be retried */ ++ rwnx_tx_retry(rwnx_hw, skb, txhdr, sw_retry); ++ return 0; ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_skb_confirm(skb, txq, hwq, &txhdr->hw_hdr.cfm); ++#endif ++ /* STA may have disconnect (and txq stopped) when buffers were stored ++ in fw. In this case do nothing when they're returned */ ++ if (txq->idx != TXQ_INACTIVE) { ++ #if 0 ++ if (txhdr->hw_hdr.cfm.credits) { ++ txq->credits += txhdr->hw_hdr.cfm.credits; ++ if (txq->credits <= 0) ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); ++ else if (txq->credits > 0) ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_FULL); ++ } ++ #endif ++ ++ /* continue service period */ ++ if (unlikely(txq->push_limit && !rwnx_txq_is_full(txq))) { ++ rwnx_txq_add_to_hw_list(txq); ++ } ++ } ++ ++ if (txhdr->hw_hdr.cfm.ampdu_size && ++ txhdr->hw_hdr.cfm.ampdu_size < IEEE80211_MAX_AMPDU_BUF) ++ rwnx_hw->stats.ampdus_tx[txhdr->hw_hdr.cfm.ampdu_size - 1]++; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ txq->amsdu_len = txhdr->hw_hdr.cfm.amsdu_size; ++#endif ++ ++ /* Update statistics */ ++ sw_txhdr->rwnx_vif->net_stats.tx_packets++; ++ sw_txhdr->rwnx_vif->net_stats.tx_bytes += sw_txhdr->frame_len; ++ ++ /* Release SKBs */ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->desc.host.flags & TXU_CNTRL_AMSDU) { ++ struct rwnx_amsdu_txhdr *amsdu_txhdr; ++ list_for_each_entry(amsdu_txhdr, &sw_txhdr->amsdu.hdrs, list) { ++ rwnx_amsdu_del_subframe_header(amsdu_txhdr); ++ consume_skb(amsdu_txhdr->skb); ++ } ++ } ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++ headroom = sw_txhdr->headroom; ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ consume_skb(skb); ++ ++ return 0; ++} ++ ++/** ++ * rwnx_txq_credit_update - Update credit for one txq ++ * ++ * @rwnx_hw: Driver main data ++ * @sta_idx: STA idx ++ * @tid: TID ++ * @update: offset to apply in txq credits ++ * ++ * Called when fw send ME_TX_CREDITS_UPDATE_IND message. ++ * Apply @update to txq credits, and stop/start the txq if needed ++ */ ++void rwnx_txq_credit_update(struct rwnx_hw *rwnx_hw, int sta_idx, u8 tid, ++ s8 update) ++{ ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[sta_idx]; ++ struct rwnx_txq *txq; ++ ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ if (txq->idx != TXQ_INACTIVE) { ++ //txq->credits += update; ++#ifdef CREATE_TRACE_POINTS ++ trace_credit_update(txq, update); ++#endif ++ if (txq->credits <= 0) ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); ++ else ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_FULL); ++ } ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h +new file mode 100644 +index 000000000000..b7c863ff3284 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h +@@ -0,0 +1,196 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tx.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_TX_H_ ++#define _RWNX_TX_H_ ++ ++#include ++#include ++#include ++#include "lmac_types.h" ++#include "ipc_shared.h" ++#include "rwnx_txq.h" ++#include "hal_desc.h" ++ ++#define RWNX_HWQ_BK 0 ++#define RWNX_HWQ_BE 1 ++#define RWNX_HWQ_VI 2 ++#define RWNX_HWQ_VO 3 ++#define RWNX_HWQ_BCMC 4 ++#define RWNX_HWQ_NB NX_TXQ_CNT ++#define RWNX_HWQ_ALL_ACS (RWNX_HWQ_BK | RWNX_HWQ_BE | RWNX_HWQ_VI | RWNX_HWQ_VO) ++#define RWNX_HWQ_ALL_ACS_BIT (BIT(RWNX_HWQ_BK) | BIT(RWNX_HWQ_BE) | \ ++ BIT(RWNX_HWQ_VI) | BIT(RWNX_HWQ_VO)) ++ ++#define RWNX_TX_LIFETIME_MS 1000 ++#define RWNX_TX_MAX_RATES NX_TX_MAX_RATES ++ ++#define RWNX_SWTXHDR_ALIGN_SZ 4 ++#define RWNX_SWTXHDR_ALIGN_MSK (RWNX_SWTXHDR_ALIGN_SZ - 1) ++#define RWNX_SWTXHDR_ALIGN_PADS(x) \ ++ ((RWNX_SWTXHDR_ALIGN_SZ - ((x) & RWNX_SWTXHDR_ALIGN_MSK)) \ ++ & RWNX_SWTXHDR_ALIGN_MSK) ++#if RWNX_SWTXHDR_ALIGN_SZ & RWNX_SWTXHDR_ALIGN_MSK ++#error bad RWNX_SWTXHDR_ALIGN_SZ ++#endif ++ ++#define AMSDU_PADDING(x) ((4 - ((x) & 0x3)) & 0x3) ++ ++#define TXU_CNTRL_RETRY BIT(0) ++#define TXU_CNTRL_MORE_DATA BIT(2) ++#define TXU_CNTRL_MGMT BIT(3) ++#define TXU_CNTRL_MGMT_NO_CCK BIT(4) ++#define TXU_CNTRL_AMSDU BIT(6) ++#define TXU_CNTRL_MGMT_ROBUST BIT(7) ++#define TXU_CNTRL_USE_4ADDR BIT(8) ++#define TXU_CNTRL_EOSP BIT(9) ++#define TXU_CNTRL_MESH_FWD BIT(10) ++#define TXU_CNTRL_TDLS BIT(11) ++ ++extern const int rwnx_tid2hwq[IEEE80211_NUM_TIDS]; ++ ++/** ++ * struct rwnx_amsdu_txhdr - Structure added in skb headroom (instead of ++ * rwnx_txhdr) for amsdu subframe buffer (except for the first subframe ++ * that has a normal rwnx_txhdr) ++ * ++ * @list List of other amsdu subframe (rwnx_sw_txhdr.amsdu.hdrs) ++ * @map_len Length to be downloaded for this subframe ++ * @dma_addr Buffer address form embedded point of view ++ * @skb skb ++ * @pad padding added before this subframe ++ * (only use when amsdu must be dismantled) ++ * @msdu_len Size, in bytes, of the MSDU (without padding nor amsdu header) ++ */ ++struct rwnx_amsdu_txhdr { ++ struct list_head list; ++ size_t map_len; ++ dma_addr_t dma_addr; ++ struct sk_buff *skb; ++ u16 pad; ++ u16 msdu_len; ++}; ++ ++/** ++ * struct rwnx_amsdu - Structure to manage creation of an A-MSDU, updated ++ * only In the first subframe of an A-MSDU ++ * ++ * @hdrs List of subframe of rwnx_amsdu_txhdr ++ * @len Current size for this A-MDSU (doesn't take padding into account) ++ * 0 means that no amsdu is in progress ++ * @nb Number of subframe in the amsdu ++ * @pad Padding to add before adding a new subframe ++ */ ++struct rwnx_amsdu { ++ struct list_head hdrs; ++ u16 len; ++ u8 nb; ++ u8 pad; ++}; ++ ++/** ++ * struct rwnx_sw_txhdr - Software part of tx header ++ * ++ * @rwnx_sta sta to which this buffer is addressed ++ * @rwnx_vif vif that send the buffer ++ * @txq pointer to TXQ used to send the buffer ++ * @hw_queue Index of the HWQ used to push the buffer. ++ * May be different than txq->hwq->id on confirmation. ++ * @frame_len Size of the frame (doesn't not include mac header) ++ * (Only used to update stat, can't we use skb->len instead ?) ++ * @headroom Headroom added in skb to add rwnx_txhdr ++ * (Only used to remove it before freeing skb, is it needed ?) ++ * @amsdu Description of amsdu whose first subframe is this buffer ++ * (amsdu.nb = 0 means this buffer is not part of amsdu) ++ * @skb skb received from transmission ++ * @map_len Length mapped for DMA (only rwnx_hw_txhdr and data are mapped) ++ * @dma_addr DMA address after mapping ++ * @desc Buffer description that will be copied in shared mem for FW ++ */ ++struct rwnx_sw_txhdr { ++ struct rwnx_sta *rwnx_sta; ++ struct rwnx_vif *rwnx_vif; ++ struct rwnx_txq *txq; ++ u8 hw_queue; ++ u16 frame_len; ++ u16 headroom; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ struct rwnx_amsdu amsdu; ++#endif ++ u32 need_cfm; ++ struct sk_buff *skb; ++ ++ size_t map_len; ++ dma_addr_t dma_addr; ++ struct txdesc_api desc; ++ ++ u8 raw_frame; ++ u8 fixed_rate; ++ u16 rate_config; ++}; ++ ++/** ++ * struct rwnx_txhdr - Stucture to control transimission of packet ++ * (Added in skb headroom) ++ * ++ * @sw_hdr: Information from driver ++ * @cache_guard: ++ * @hw_hdr: Information for/from hardware ++ */ ++struct rwnx_txhdr { ++ struct rwnx_sw_txhdr *sw_hdr; ++ char cache_guard[L1_CACHE_BYTES]; ++ struct rwnx_hw_txhdr hw_hdr; ++}; ++ ++u16 rwnx_select_txq(struct rwnx_vif *rwnx_vif, struct sk_buff *skb); ++netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct cfg80211_mgmt_tx_params *params, bool offchan, ++ u64 *cookie); ++#else ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct ieee80211_channel *channel, bool offchan, ++ unsigned int wait, const u8 *buf, size_t len, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ bool no_cck, ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) ++ bool dont_wait_for_ack, ++ #endif ++ u64 *cookie); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ ++#ifdef CONFIG_RWNX_MON_XMIT ++int rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *dev); ++#endif ++int rwnx_txdatacfm(void *pthis, void *host_id); ++ ++struct rwnx_hw; ++struct rwnx_sta; ++void rwnx_set_traffic_status(struct rwnx_hw *rwnx_hw, ++ struct rwnx_sta *sta, ++ bool available, ++ u8 ps_id); ++void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ bool enable); ++void rwnx_ps_bh_traffic_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ u16 pkt_req, u8 ps_id); ++ ++void rwnx_switch_vif_sta_txq(struct rwnx_sta *sta, struct rwnx_vif *old_vif, ++ struct rwnx_vif *new_vif); ++ ++int rwnx_dbgfs_print_sta(char *buf, size_t size, struct rwnx_sta *sta, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_credit_update(struct rwnx_hw *rwnx_hw, int sta_idx, u8 tid, ++ s8 update); ++void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags); ++ ++#endif /* _RWNX_TX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c +new file mode 100644 +index 000000000000..9bdc07268407 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c +@@ -0,0 +1,1371 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_txq.c ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++#include "rwnx_tx.h" ++#include "ipc_host.h" ++#include "rwnx_events.h" ++ ++/****************************************************************************** ++ * Utils functions ++ *****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++const int nx_tid_prio[NX_NB_TID_PER_STA] = {7, 6, 5, 4, 3, 0, 2, 1}; ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++extern int tx_fc_low_water; ++extern int tx_fc_high_water; ++#endif ++ ++static inline int rwnx_txq_sta_idx(struct rwnx_sta *sta, u8 tid) ++{ ++ if (is_multicast_sta(sta->sta_idx)){ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ return NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + sta->vif_idx; ++ }else{ ++ return NX_FIRST_VIF_TXQ_IDX + sta->vif_idx; ++ } ++ }else{ ++ return (sta->sta_idx * NX_NB_TXQ_PER_STA) + tid; ++ } ++} ++ ++static inline int rwnx_txq_vif_idx(struct rwnx_vif *vif, u8 type) ++{ ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ return NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + master_vif_idx(vif) + (type * NX_VIRT_DEV_MAX); ++ }else{ ++ return NX_FIRST_VIF_TXQ_IDX + master_vif_idx(vif) + (type * NX_VIRT_DEV_MAX); ++ } ++ ++} ++ ++struct rwnx_txq *rwnx_txq_sta_get(struct rwnx_sta *sta, u8 tid, ++ struct rwnx_hw *rwnx_hw) ++{ ++ if (tid >= NX_NB_TXQ_PER_STA) ++ tid = 0; ++ ++ return &rwnx_hw->txq[rwnx_txq_sta_idx(sta, tid)]; ++} ++ ++struct rwnx_txq *rwnx_txq_vif_get(struct rwnx_vif *vif, u8 type) ++{ ++ if (type > NX_UNK_TXQ_TYPE) ++ type = NX_BCMC_TXQ_TYPE; ++ ++ return &vif->rwnx_hw->txq[rwnx_txq_vif_idx(vif, type)]; ++} ++ ++static inline struct rwnx_sta *rwnx_txq_2_sta(struct rwnx_txq *txq) ++{ ++ return txq->sta; ++} ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ ++/****************************************************************************** ++ * Init/Deinit functions ++ *****************************************************************************/ ++/** ++ * rwnx_txq_init - Initialize a TX queue ++ * ++ * @txq: TX queue to be initialized ++ * @idx: TX queue index ++ * @status: TX queue initial status ++ * @hwq: Associated HW queue ++ * @ndev: Net device this queue belongs to ++ * (may be null for non netdev txq) ++ * ++ * Each queue is initialized with the credit of @NX_TXQ_INITIAL_CREDITS. ++ */ ++static void rwnx_txq_init(struct rwnx_txq *txq, int idx, u8 status, ++ struct rwnx_hwq *hwq, int tid, ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_sta *sta, struct net_device *ndev ++#endif ++ ) ++{ ++ int i; ++ int nx_first_unk_txq_idx = NX_FIRST_UNK_TXQ_IDX; ++ int nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX; ++ int nx_first_vif_txq_idx = NX_FIRST_VIF_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_first_unk_txq_idx = NX_FIRST_UNK_TXQ_IDX_FOR_OLD_IC; ++ nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC; ++ nx_first_vif_txq_idx = NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ ++ txq->idx = idx; ++ txq->status = status; ++ txq->credits = NX_TXQ_INITIAL_CREDITS; ++ txq->pkt_sent = 0; ++ skb_queue_head_init(&txq->sk_list); ++ txq->last_retry_skb = NULL; ++ txq->nb_retry = 0; ++ txq->hwq = hwq; ++ txq->sta = sta; ++ for (i = 0; i < CONFIG_USER_MAX ; i++) ++ txq->pkt_pushed[i] = 0; ++ txq->push_limit = 0; ++ txq->tid = tid; ++#ifdef CONFIG_MAC80211_TXQ ++ txq->nb_ready_mac80211 = 0; ++#endif ++#ifdef CONFIG_RWNX_FULLMAC ++ txq->ps_id = LEGACY_PS_ID; ++ if (idx < nx_first_vif_txq_idx) { ++ int sta_idx = sta->sta_idx; ++ int tid = idx - (sta_idx * NX_NB_TXQ_PER_STA); ++ if (tid < NX_NB_TID_PER_STA) ++ txq->ndev_idx = NX_STA_NDEV_IDX(tid, sta_idx); ++ else ++ txq->ndev_idx = NDEV_NO_TXQ; ++ } else if (idx < nx_first_unk_txq_idx) { ++ txq->ndev_idx = nx_bcmc_txq_ndev_idx; ++ } else { ++ txq->ndev_idx = NDEV_NO_TXQ; ++ } ++ txq->ndev = ndev; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ txq->amsdu = NULL; ++ txq->amsdu_len = 0; ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++/** ++ * rwnx_txq_flush - Flush all buffers queued for a TXQ ++ * ++ * @rwnx_hw: main driver data ++ * @txq: txq to flush ++ */ ++void rwnx_txq_flush(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq) ++{ ++ struct sk_buff *skb; ++ ++ ++ while ((skb = skb_dequeue(&txq->sk_list)) != NULL) { ++ struct rwnx_sw_txhdr *sw_txhdr = ((struct rwnx_txhdr *)skb->data)->sw_hdr; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->desc.host.packet_cnt > 1) { ++ struct rwnx_amsdu_txhdr *amsdu_txhdr; ++ list_for_each_entry(amsdu_txhdr, &sw_txhdr->amsdu.hdrs, list) { ++ //dma_unmap_single(rwnx_hw->dev, amsdu_txhdr->dma_addr, ++ // amsdu_txhdr->map_len, DMA_TO_DEVICE); ++ dev_kfree_skb_any(amsdu_txhdr->skb); ++ } ++ } ++#endif ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ //dma_unmap_single(rwnx_hw->dev, sw_txhdr->dma_addr, sw_txhdr->map_len, ++ // DMA_TO_DEVICE); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ dev_kfree_skb_any(skb); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } ++} ++ ++/** ++ * rwnx_txq_deinit - De-initialize a TX queue ++ * ++ * @rwnx_hw: Driver main data ++ * @txq: TX queue to be de-initialized ++ * Any buffer stuck in a queue will be freed. ++ */ ++static void rwnx_txq_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq) ++{ ++ if (txq->idx == TXQ_INACTIVE) ++ return; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ rwnx_txq_del_from_hw_list(txq); ++ txq->idx = TXQ_INACTIVE; ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ rwnx_txq_flush(rwnx_hw, txq); ++} ++ ++/** ++ * rwnx_txq_vif_init - Initialize all TXQ linked to a vif ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: Pointer on VIF ++ * @status: Intial txq status ++ * ++ * Softmac : 1 VIF TXQ per HWQ ++ * ++ * Fullmac : 1 VIF TXQ for BC/MC ++ * 1 VIF TXQ for MGMT to unknown STA ++ */ ++void rwnx_txq_vif_init(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 status) ++{ ++ struct rwnx_txq *txq; ++ int idx; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ idx = rwnx_txq_vif_idx(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_init(txq, idx, status, &rwnx_hw->hwq[RWNX_HWQ_BE], 0, ++ &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index], rwnx_vif->ndev); ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ idx = rwnx_txq_vif_idx(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_init(txq, idx, status, &rwnx_hw->hwq[RWNX_HWQ_VO], TID_MGT, ++ NULL, rwnx_vif->ndev); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++/** ++ * rwnx_txq_vif_deinit - Deinitialize all TXQ linked to a vif ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_vif_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_deinit(rwnx_hw, txq); ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_deinit(rwnx_hw, txq); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++ ++/** ++ * rwnx_txq_sta_init - Initialize TX queues for a STA ++ * ++ * @rwnx_hw: Main driver data ++ * @rwnx_sta: STA for which tx queues need to be initialized ++ * @status: Intial txq status ++ * ++ * This function initialize all the TXQ associated to a STA. ++ * Softmac : 1 TXQ per TID ++ * ++ * Fullmac : 1 TXQ per TID (limited to 8) ++ * 1 TXQ for MGMT ++ */ ++void rwnx_txq_sta_init(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ u8 status) ++{ ++ struct rwnx_txq *txq; ++ int tid, idx; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[rwnx_sta->vif_idx]; ++ idx = rwnx_txq_sta_idx(rwnx_sta, 0); ++ ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_init(txq, idx, status, &rwnx_hw->hwq[rwnx_tid2hwq[tid]], tid, ++ rwnx_sta, rwnx_vif->ndev); ++ txq->ps_id = rwnx_sta->uapsd_tids & (1 << tid) ? UAPSD_ID : LEGACY_PS_ID; ++ idx++; ++ } ++ ++#endif /* CONFIG_RWNX_FULLMAC*/ ++} ++ ++/** ++ * rwnx_txq_sta_deinit - Deinitialize TX queues for a STA ++ * ++ * @rwnx_hw: Main driver data ++ * @rwnx_sta: STA for which tx queues need to be deinitialized ++ */ ++void rwnx_txq_sta_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) ++{ ++ struct rwnx_txq *txq; ++ int tid; ++ ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_deinit(rwnx_hw, txq); ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/** ++ * rwnx_txq_unk_vif_init - Initialize TXQ for unknown STA linked to a vif ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_unk_vif_init(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txq *txq; ++ int idx; ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ idx = rwnx_txq_vif_idx(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_init(txq, idx, 0, &rwnx_hw->hwq[RWNX_HWQ_VO], TID_MGT, NULL, rwnx_vif->ndev); ++} ++ ++/** ++ * rwnx_txq_tdls_vif_deinit - Deinitialize TXQ for unknown STA linked to a vif ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_unk_vif_deinit(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq; ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_deinit(rwnx_vif->rwnx_hw, txq); ++} ++ ++/** ++ * rwnx_init_unk_txq - Initialize TX queue for the transmission on a offchannel ++ * ++ * @vif: Interface for which the queue has to be initialized ++ * ++ * NOTE: Offchannel txq is only active for the duration of the ROC ++ */ ++void rwnx_txq_offchan_init(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txq *txq; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ rwnx_txq_init(txq, nx_off_chan_txq_idx, RWNX_TXQ_STOP_CHAN, ++ &rwnx_hw->hwq[RWNX_HWQ_VO], TID_MGT, NULL, rwnx_vif->ndev); ++} ++ ++/** ++ * rwnx_deinit_offchan_txq - Deinitialize TX queue for offchannel ++ * ++ * @vif: Interface that manages the STA ++ * ++ * This function deintialize txq for one STA. ++ * Any buffer stuck in a queue will be freed. ++ */ ++void rwnx_txq_offchan_deinit(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq; ++ ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ txq = &rwnx_vif->rwnx_hw->txq[nx_off_chan_txq_idx]; ++ rwnx_txq_deinit(rwnx_vif->rwnx_hw, txq); ++} ++ ++ ++/** ++ * rwnx_txq_tdls_vif_init - Initialize TXQ vif for TDLS ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_tdls_vif_init(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ ++ if (!(rwnx_hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return; ++ ++ rwnx_txq_unk_vif_init(rwnx_vif); ++} ++ ++/** ++ * rwnx_txq_tdls_vif_deinit - Deinitialize TXQ vif for TDLS ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_tdls_vif_deinit(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ ++ if (!(rwnx_hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return; ++ ++ rwnx_txq_unk_vif_deinit(rwnx_vif); ++} ++#endif ++ ++/****************************************************************************** ++ * Start/Stop functions ++ *****************************************************************************/ ++/** ++ * rwnx_txq_add_to_hw_list - Add TX queue to a HW queue schedule list. ++ * ++ * @txq: TX queue to add ++ * ++ * Add the TX queue if not already present in the HW queue list. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq) ++{ ++ if (!(txq->status & RWNX_TXQ_IN_HWQ_LIST)) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_add_to_hw(txq); ++#endif ++ txq->status |= RWNX_TXQ_IN_HWQ_LIST; ++ list_add_tail(&txq->sched_list, &txq->hwq->list); ++ txq->hwq->need_processing = true; ++ } ++} ++ ++/** ++ * rwnx_txq_del_from_hw_list - Delete TX queue from a HW queue schedule list. ++ * ++ * @txq: TX queue to delete ++ * ++ * Remove the TX queue from the HW queue list if present. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_del_from_hw_list(struct rwnx_txq *txq) ++{ ++ if (txq->status & RWNX_TXQ_IN_HWQ_LIST) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_del_from_hw(txq); ++#endif ++ txq->status &= ~RWNX_TXQ_IN_HWQ_LIST; ++ list_del(&txq->sched_list); ++ } ++} ++ ++/** ++ * rwnx_txq_skb_ready - Check if skb are available for the txq ++ * ++ * @txq: Pointer on txq ++ * @return True if there are buffer ready to be pushed on this txq, ++ * false otherwise ++ */ ++static inline bool rwnx_txq_skb_ready(struct rwnx_txq *txq) ++{ ++#ifdef CONFIG_MAC80211_TXQ ++ if (txq->nb_ready_mac80211 != NOT_MAC80211_TXQ) ++ return ((txq->nb_ready_mac80211 > 0) || !skb_queue_empty(&txq->sk_list)); ++ else ++#endif ++ return !skb_queue_empty(&txq->sk_list); ++} ++ ++/** ++ * rwnx_txq_start - Try to Start one TX queue ++ * ++ * @txq: TX queue to start ++ * @reason: reason why the TX queue is started (among RWNX_TXQ_STOP_xxx) ++ * ++ * Re-start the TX queue for one reason. ++ * If after this the txq is no longer stopped and some buffers are ready, ++ * the TX queue is also added to HW queue list. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_start(struct rwnx_txq *txq, u16 reason) ++{ ++ BUG_ON(txq == NULL); ++ if (txq->idx != TXQ_INACTIVE && (txq->status & reason)) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_start(txq, reason); ++#endif ++ txq->status &= ~reason; ++ if (!rwnx_txq_is_stopped(txq) && rwnx_txq_skb_ready(txq)) ++ rwnx_txq_add_to_hw_list(txq); ++ } ++} ++ ++/** ++ * rwnx_txq_stop - Stop one TX queue ++ * ++ * @txq: TX queue to stop ++ * @reason: reason why the TX queue is stopped (among RWNX_TXQ_STOP_xxx) ++ * ++ * Stop the TX queue. It will remove the TX queue from HW queue list ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_stop(struct rwnx_txq *txq, u16 reason) ++{ ++ BUG_ON(txq == NULL); ++ if (txq->idx != TXQ_INACTIVE) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_stop(txq, reason); ++#endif ++ txq->status |= reason; ++ rwnx_txq_del_from_hw_list(txq); ++ } ++} ++ ++ ++/** ++ * rwnx_txq_sta_start - Start all the TX queue linked to a STA ++ * ++ * @sta: STA whose TX queues must be re-started ++ * @reason: Reason why the TX queue are restarted (among RWNX_TXQ_STOP_xxx) ++ * @rwnx_hw: Driver main data ++ * ++ * This function will re-start all the TX queues of the STA for the reason ++ * specified. It can be : ++ * - RWNX_TXQ_STOP_STA_PS: the STA is no longer in power save mode ++ * - RWNX_TXQ_STOP_VIF_PS: the VIF is in power save mode (p2p absence) ++ * - RWNX_TXQ_STOP_CHAN: the STA's VIF is now on the current active channel ++ * ++ * Any TX queue with buffer ready and not Stopped for other reasons, will be ++ * added to the HW queue list ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_sta_start(struct rwnx_sta *rwnx_sta, u16 reason ++#ifdef CONFIG_RWNX_FULLMAC ++ , struct rwnx_hw *rwnx_hw ++#endif ++ ) ++{ ++ struct rwnx_txq *txq; ++ int tid; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_sta_start(rwnx_sta->sta_idx); ++#endif ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_start(txq, reason); ++ } ++} ++ ++ ++/** ++ * rwnx_stop_sta_txq - Stop all the TX queue linked to a STA ++ * ++ * @sta: STA whose TX queues must be stopped ++ * @reason: Reason why the TX queue are stopped (among RWNX_TX_STOP_xxx) ++ * @rwnx_hw: Driver main data ++ * ++ * This function will stop all the TX queues of the STA for the reason ++ * specified. It can be : ++ * - RWNX_TXQ_STOP_STA_PS: the STA is in power save mode ++ * - RWNX_TXQ_STOP_VIF_PS: the VIF is in power save mode (p2p absence) ++ * - RWNX_TXQ_STOP_CHAN: the STA's VIF is not on the current active channel ++ * ++ * Any TX queue present in a HW queue list will be removed from this list. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_sta_stop(struct rwnx_sta *rwnx_sta, u16 reason ++#ifdef CONFIG_RWNX_FULLMAC ++ , struct rwnx_hw *rwnx_hw ++#endif ++ ) ++{ ++ struct rwnx_txq *txq; ++ int tid; ++ ++ if (!rwnx_sta) ++ return; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_sta_stop(rwnx_sta->sta_idx); ++#endif ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_stop(txq, reason); ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_start(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ if (rwnx_vif->sta.tdls_sta) ++ rwnx_txq_sta_start(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_tdls_sta_stop(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_stop(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ if (rwnx_vif->sta.tdls_sta) ++ rwnx_txq_sta_stop(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline void rwnx_txq_vif_for_each_sta(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ void (*f)(struct rwnx_sta *, u16, struct rwnx_hw *), u16 reason) { ++ ++ switch (RWNX_VIF_TYPE(rwnx_vif)) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ { ++ if (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) ++ f(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ if (!WARN_ON(rwnx_vif->sta.ap == NULL)) ++ f(rwnx_vif->sta.ap, reason, rwnx_hw); ++ break; ++ } ++ case NL80211_IFTYPE_AP_VLAN: ++ rwnx_vif = rwnx_vif->ap_vlan.master; ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_MESH_POINT: ++ case NL80211_IFTYPE_P2P_GO: ++ { ++ struct rwnx_sta *sta; ++ list_for_each_entry(sta, &rwnx_vif->ap.sta_list, list) { ++ f(sta, reason, rwnx_hw); ++ } ++ break; ++ } ++ default: ++ BUG(); ++ break; ++ } ++} ++#endif ++ ++/** ++ * rwnx_txq_vif_start - START TX queues of all STA associated to the vif ++ * and vif's TXQ ++ * ++ * @vif: Interface to start ++ * @reason: Start reason (RWNX_TXQ_STOP_CHAN or RWNX_TXQ_STOP_VIF_PS) ++ * @rwnx_hw: Driver main data ++ * ++ * Iterate over all the STA associated to the vif and re-start them for the ++ * reason @reason ++ * Take tx_lock ++ */ ++void rwnx_txq_vif_start(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_txq *txq; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_start(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ //Reject if monitor interface ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MONITOR) ++ goto end; ++ ++ if (rwnx_vif->roc_tdls && rwnx_vif->sta.tdls_sta && rwnx_vif->sta.tdls_sta->tdls.chsw_en) { ++ rwnx_txq_sta_start(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ } ++ if (!rwnx_vif->roc_tdls) { ++ rwnx_txq_vif_for_each_sta(rwnx_hw, rwnx_vif, rwnx_txq_sta_start, reason); ++ } ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_start(txq, reason); ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_start(txq, reason); ++ ++end: ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++ ++ ++/** ++ * rwnx_txq_vif_stop - STOP TX queues of all STA associated to the vif ++ * ++ * @vif: Interface to stop ++ * @arg: Stop reason (RWNX_TXQ_STOP_CHAN or RWNX_TXQ_STOP_VIF_PS) ++ * @rwnx_hw: Driver main data ++ * ++ * Iterate over all the STA associated to the vif and stop them for the ++ * reason RWNX_TXQ_STOP_CHAN or RWNX_TXQ_STOP_VIF_PS ++ * Take tx_lock ++ */ ++void rwnx_txq_vif_stop(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_txq *txq; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_stop(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ //Reject if monitor interface ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MONITOR) ++ goto end; ++ ++ rwnx_txq_vif_for_each_sta(rwnx_hw, rwnx_vif, rwnx_txq_sta_stop, reason); ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_stop(txq, reason); ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_stop(txq, reason); ++ ++end: ++#endif /* CONFIG_RWNX_FULLMAC*/ ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++/** ++ * rwnx_start_offchan_txq - START TX queue for offchannel frame ++ * ++ * @rwnx_hw: Driver main data ++ */ ++void rwnx_txq_offchan_start(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_txq *txq; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_CHAN); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++ ++/** ++ * rwnx_switch_vif_sta_txq - Associate TXQ linked to a STA to a new vif ++ * ++ * @sta: STA whose txq must be switched ++ * @old_vif: Vif currently associated to the STA (may no longer be active) ++ * @new_vif: vif which should be associated to the STA for now on ++ * ++ * This function will switch the vif (i.e. the netdev) associated to all STA's ++ * TXQ. This is used when AP_VLAN interface are created. ++ * If one STA is associated to an AP_vlan vif, it will be moved from the master ++ * AP vif to the AP_vlan vif. ++ * If an AP_vlan vif is removed, then STA will be moved back to mastert AP vif. ++ * ++ */ ++void rwnx_txq_sta_switch_vif(struct rwnx_sta *sta, struct rwnx_vif *old_vif, ++ struct rwnx_vif *new_vif) ++{ ++ struct rwnx_hw *rwnx_hw = new_vif->rwnx_hw; ++ struct rwnx_txq *txq; ++ int i; ++ ++ /* start TXQ on the new interface, and update ndev field in txq */ ++ if (!netif_carrier_ok(new_vif->ndev)) ++ netif_carrier_on(new_vif->ndev); ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ for (i = 0; i < NX_NB_TID_PER_STA; i++, txq++) { ++ txq->ndev = new_vif->ndev; ++ netif_wake_subqueue(txq->ndev, txq->ndev_idx); ++ } ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/****************************************************************************** ++ * TXQ queue/schedule functions ++ *****************************************************************************/ ++/** ++ * rwnx_txq_queue_skb - Queue a buffer in a TX queue ++ * ++ * @skb: Buffer to queue ++ * @txq: TX Queue in which the buffer must be added ++ * @rwnx_hw: Driver main data ++ * @retry: Should it be queued in the retry list ++ * ++ * @return: Retrun 1 if txq has been added to hwq list, 0 otherwise ++ * ++ * Add a buffer in the buffer list of the TX queue ++ * and add this TX queue in the HW queue list if the txq is not stopped. ++ * If this is a retry packet it is added after the last retry packet or at the ++ * beginning if there is no retry packet queued. ++ * ++ * If the STA is in PS mode and this is the first packet queued for this txq ++ * update TIM. ++ * ++ * To be called with tx_lock hold ++ */ ++int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, ++ struct rwnx_hw *rwnx_hw, bool retry) ++{ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (unlikely(txq->sta && txq->sta->ps.active)) { ++ txq->sta->ps.pkt_ready[txq->ps_id]++; ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_queue(txq->sta); ++#endif ++ if (txq->sta->ps.pkt_ready[txq->ps_id] == 1) { ++ rwnx_set_traffic_status(rwnx_hw, txq->sta, true, txq->ps_id); ++ } ++ } ++#endif ++ ++ if (!retry) { ++ /* add buffer in the sk_list */ ++ skb_queue_tail(&txq->sk_list, skb); ++ } else { ++ if (txq->last_retry_skb) ++#ifdef CONFIG_GKI ++ rwnx_skb_append(txq->last_retry_skb, skb, &txq->sk_list); ++#else ++ skb_append(txq->last_retry_skb, skb, &txq->sk_list); ++#endif ++ else ++ skb_queue_head(&txq->sk_list, skb); ++ ++ txq->last_retry_skb = skb; ++ txq->nb_retry++; ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_queue_skb(skb, txq, retry); ++#endif ++ /* Flowctrl corresponding netdev queue if needed */ ++#ifdef CONFIG_RWNX_FULLMAC ++#ifndef CONFIG_ONE_TXQ ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ if ((txq->ndev_idx != NDEV_NO_TXQ) && ((skb_queue_len(&txq->sk_list) > RWNX_NDEV_FLOW_CTRL_STOP) && ++ !rwnx_hw->sdiodev->flowctrl)) { ++// (atomic_read(&rwnx_hw->sdiodev->tx_priv->tx_pktcnt) >= tx_fc_high_water))) { ++#else ++ /* If too many buffer are queued for this TXQ stop netdev queue */ ++ if ((txq->ndev_idx != NDEV_NO_TXQ) && ++ (skb_queue_len(&txq->sk_list) > RWNX_NDEV_FLOW_CTRL_STOP)) { ++#endif ++ ++ txq->status |= RWNX_TXQ_NDEV_FLOW_CTRL; ++ netif_stop_subqueue(txq->ndev, txq->ndev_idx); ++#ifdef CREATE_TRACE_POINT ++ trace_txq_flowctrl_stop(txq); ++#endif ++ } ++#endif /* CONFIG_ONE_TXQ */ ++#else /* ! CONFIG_RWNX_FULLMAC */ ++ ++ if (!retry && ++txq->hwq->len == txq->hwq->len_stop) { ++ trace_hwq_flowctrl_stop(txq->hwq->id); ++ ieee80211_stop_queue(rwnx_hw->hw, txq->hwq->id); ++ rwnx_hw->stats.queues_stops++; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ /* add it in the hwq list if not stopped and not yet present */ ++ if (!rwnx_txq_is_stopped(txq)) { ++ rwnx_txq_add_to_hw_list(txq); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * rwnx_txq_confirm_any - Process buffer confirmed by fw ++ * ++ * @rwnx_hw: Driver main data ++ * @txq: TX Queue ++ * @hwq: HW Queue ++ * @sw_txhdr: software descriptor of the confirmed packet ++ * ++ * Process a buffer returned by the fw. It doesn't check buffer status ++ * and only does systematic counter update: ++ * - hw credit ++ * - buffer pushed to fw ++ * ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_confirm_any(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, ++ struct rwnx_hwq *hwq, struct rwnx_sw_txhdr *sw_txhdr) ++{ ++ int user = 0; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ int group_id; ++ ++ user = RWNX_MUMIMO_INFO_POS_ID(sw_txhdr->desc.host.mumimo_info); ++ group_id = RWNX_MUMIMO_INFO_GROUP_ID(sw_txhdr->desc.host.mumimo_info); ++ ++ if ((txq->idx != TXQ_INACTIVE) && ++ (txq->pkt_pushed[user] == 1) && ++ (txq->status & RWNX_TXQ_STOP_MU_POS)) ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_MU_POS); ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++ if (txq->pkt_pushed[user]) ++ txq->pkt_pushed[user]--; ++ ++ hwq->need_processing = true; ++ rwnx_hw->stats.cfm_balance[hwq->id]--; ++} ++ ++/****************************************************************************** ++ * HWQ processing ++ *****************************************************************************/ ++static inline ++bool rwnx_txq_take_mu_lock(struct rwnx_hw *rwnx_hw) ++{ ++ bool res = false; ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ if (rwnx_hw->mod_params->mutx) ++ res = (down_trylock(&rwnx_hw->mu.lock) == 0); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ return res; ++} ++ ++static inline ++void rwnx_txq_release_mu_lock(struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ up(&rwnx_hw->mu.lock); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++} ++ ++static inline ++void rwnx_txq_set_mu_info(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, ++ int group_id, int pos) ++{ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ trace_txq_select_mu_group(txq, group_id, pos); ++ if (group_id) { ++ txq->mumimo_info = group_id | (pos << 6); ++ rwnx_mu_set_active_group(rwnx_hw, group_id); ++ } else ++ txq->mumimo_info = 0; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++} ++ ++static inline ++s8 rwnx_txq_get_credits(struct rwnx_txq *txq) ++{ ++ s8 cred = txq->credits; ++ /* if destination is in PS mode, push_limit indicates the maximum ++ number of packet that can be pushed on this txq. */ ++ if (txq->push_limit && (cred > txq->push_limit)) { ++ cred = txq->push_limit; ++ } ++ return cred; ++} ++ ++/** ++ * skb_queue_extract - Extract buffer from skb list ++ * ++ * @list: List of skb to extract from ++ * @head: List of skb to append to ++ * @nb_elt: Number of skb to extract ++ * ++ * extract the first @nb_elt of @list and append them to @head ++ * It is assume that: ++ * - @list contains more that @nb_elt ++ * - There is no need to take @list nor @head lock to modify them ++ */ ++static inline void skb_queue_extract(struct sk_buff_head *list, ++ struct sk_buff_head *head, int nb_elt) ++{ ++ int i; ++ struct sk_buff *first, *last, *ptr; ++ ++ first = ptr = list->next; ++ for (i = 0; i < nb_elt; i++) { ++ ptr = ptr->next; ++ } ++ last = ptr->prev; ++ ++ /* unlink nb_elt in list */ ++ list->qlen -= nb_elt; ++ list->next = ptr; ++ ptr->prev = (struct sk_buff *)list; ++ ++ /* append nb_elt at end of head */ ++ head->qlen += nb_elt; ++ last->next = (struct sk_buff *)head; ++ head->prev->next = first; ++ first->prev = head->prev; ++ head->prev = last; ++} ++ ++ ++#ifdef CONFIG_MAC80211_TXQ ++/** ++ * rwnx_txq_mac80211_dequeue - Dequeue buffer from mac80211 txq and ++ * add them to push list ++ * ++ * @rwnx_hw: Main driver data ++ * @sk_list: List of buffer to push (initialized without lock) ++ * @txq: TXQ to dequeue buffers from ++ * @max: Max number of buffer to dequeue ++ * ++ * Dequeue buffer from mac80211 txq, prepare them for transmission and chain them ++ * to the list of buffer to push. ++ * ++ * @return true if no more buffer are queued in mac80211 txq and false otherwise. ++ */ ++static bool rwnx_txq_mac80211_dequeue(struct rwnx_hw *rwnx_hw, ++ struct sk_buff_head *sk_list, ++ struct rwnx_txq *txq, int max) ++{ ++ struct ieee80211_txq *mac_txq; ++ struct sk_buff *skb; ++ unsigned long mac_txq_len; ++ ++ if (txq->nb_ready_mac80211 == NOT_MAC80211_TXQ) ++ return true; ++ ++ mac_txq = container_of((void *)txq, struct ieee80211_txq, drv_priv); ++ ++ for (; max > 0; max--) { ++ skb = rwnx_tx_dequeue_prep(rwnx_hw, mac_txq); ++ if (skb == NULL) ++ return true; ++ ++ __skb_queue_tail(sk_list, skb); ++ } ++ ++ /* re-read mac80211 txq current length. ++ It is mainly for debug purpose to trace dropped packet. There is no ++ problems to have nb_ready_mac80211 != actual mac80211 txq length */ ++ ieee80211_txq_get_depth(mac_txq, &mac_txq_len, NULL); ++ if (txq->nb_ready_mac80211 > mac_txq_len) ++ trace_txq_drop(txq, txq->nb_ready_mac80211 - mac_txq_len); ++ txq->nb_ready_mac80211 = mac_txq_len; ++ ++ return (txq->nb_ready_mac80211 == 0); ++} ++#endif ++ ++/** ++ * rwnx_txq_get_skb_to_push - Get list of buffer to push for one txq ++ * ++ * @rwnx_hw: main driver data ++ * @hwq: HWQ on wich buffers will be pushed ++ * @txq: TXQ to get buffers from ++ * @user: user postion to use ++ * @sk_list_push: list to update ++ * ++ * ++ * This function will returned a list of buffer to push for one txq. ++ * It will take into account the number of credit of the HWQ for this user ++ * position and TXQ (and push_limit). ++ * This allow to get a list that can be pushed without having to test for ++ * hwq/txq status after each push ++ * ++ * If a MU group has been selected for this txq, it will also update the ++ * counter for the group ++ * ++ * @return true if txq no longer have buffer ready after the ones returned. ++ * false otherwise ++ */ ++static ++bool rwnx_txq_get_skb_to_push(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq, ++ struct rwnx_txq *txq, int user, ++ struct sk_buff_head *sk_list_push) ++{ ++ int nb_ready = skb_queue_len(&txq->sk_list); ++ int credits = rwnx_txq_get_credits(txq); ++ bool res = false; ++ ++ __skb_queue_head_init(sk_list_push); ++ ++ if (credits >= nb_ready) { ++ skb_queue_splice_init(&txq->sk_list, sk_list_push); ++#ifdef CONFIG_MAC80211_TXQ ++ res = rwnx_txq_mac80211_dequeue(rwnx_hw, sk_list_push, txq, credits - nb_ready); ++ credits = skb_queue_len(sk_list_push); ++#else ++ res = true; ++ credits = nb_ready; ++#endif ++ } else { ++ skb_queue_extract(&txq->sk_list, sk_list_push, credits); ++ ++ /* When processing PS service period (i.e. push_limit != 0), no longer ++ process this txq if the buffers extracted will complete the SP for ++ this txq */ ++ if (txq->push_limit && (credits == txq->push_limit)) ++ res = true; ++ } ++ ++ rwnx_mu_set_active_sta(rwnx_hw, rwnx_txq_2_sta(txq), credits); ++ ++ return res; ++} ++ ++/** ++ * rwnx_txq_select_user - Select User queue for a txq ++ * ++ * @rwnx_hw: main driver data ++ * @mu_lock: true is MU lock is taken ++ * @txq: TXQ to select MU group for ++ * @hwq: HWQ for the TXQ ++ * @user: Updated with user position selected ++ * ++ * @return false if it is no possible to process this txq. ++ * true otherwise ++ * ++ * This function selects the MU group to use for a TXQ. ++ * The selection is done as follow: ++ * ++ * - return immediately for STA that don't belongs to any group and select ++ * group 0 / user 0 ++ * ++ * - If MU tx is disabled (by user mutx_on, or because mu group are being ++ * updated !mu_lock), select group 0 / user 0 ++ * ++ * - Use the best group selected by @rwnx_mu_group_sta_select. ++ * ++ * Each time a group is selected (except for the first case where sta ++ * doesn't belongs to a MU group), the function checks that no buffer is ++ * pending for this txq on another user position. If this is the case stop ++ * the txq (RWNX_TXQ_STOP_MU_POS) and return false. ++ * ++ */ ++static ++bool rwnx_txq_select_user(struct rwnx_hw *rwnx_hw, bool mu_lock, ++ struct rwnx_txq *txq, struct rwnx_hwq *hwq, int *user) ++{ ++ int pos = 0; ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ int id, group_id = 0; ++ struct rwnx_sta *sta = rwnx_txq_2_sta(txq); ++ ++ /* for sta that belong to no group return immediately */ ++ if (!sta || !sta->group_info.cnt) ++ goto end; ++ ++ /* If MU is disabled, need to check user */ ++ if (!rwnx_hw->mod_params->mutx_on || !mu_lock) ++ goto check_user; ++ ++ /* Use the "best" group selected */ ++ group_id = sta->group_info.group; ++ ++ if (group_id > 0) ++ pos = rwnx_mu_group_sta_get_pos(rwnx_hw, sta, group_id); ++ ++check_user: ++ /* check that we can push on this user position */ ++#if CONFIG_USER_MAX == 2 ++ id = (pos + 1) & 0x1; ++ if (txq->pkt_pushed[id]) { ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_MU_POS); ++ return false; ++ } ++ ++#else ++ for (id = 0 ; id < CONFIG_USER_MAX ; id++) { ++ if (id != pos && txq->pkt_pushed[id]) { ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_MU_POS); ++ return false; ++ } ++ } ++#endif ++ ++end: ++ rwnx_txq_set_mu_info(rwnx_hw, txq, group_id, pos); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++ *user = pos; ++ return true; ++} ++ ++ ++/** ++ * rwnx_hwq_process - Process one HW queue list ++ * ++ * @rwnx_hw: Driver main data ++ * @hw_queue: HW queue index to process ++ * ++ * The function will iterate over all the TX queues linked in this HW queue ++ * list. For each TX queue, push as many buffers as possible in the HW queue. ++ * (NB: TX queue have at least 1 buffer, otherwise it wouldn't be in the list) ++ * - If TX queue no longer have buffer, remove it from the list and check next ++ * TX queue ++ * - If TX queue no longer have credits or has a push_limit (PS mode) and it ++ * is reached , remove it from the list and check next TX queue ++ * - If HW queue is full, update list head to start with the next TX queue on ++ * next call if current TX queue already pushed "too many" pkt in a row, and ++ * return ++ * ++ * To be called when HW queue list is modified: ++ * - when a buffer is pushed on a TX queue ++ * - when new credits are received ++ * - when a STA returns from Power Save mode or receives traffic request. ++ * - when Channel context change ++ * ++ * To be called with tx_lock hold ++ */ ++#define ALL_HWQ_MASK ((1 << CONFIG_USER_MAX) - 1) ++ ++void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq) ++{ ++ struct rwnx_txq *txq, *next; ++ int user, credit_map = 0; ++ bool mu_enable; ++#ifdef CREATE_TRACE_POINTS ++ trace_process_hw_queue(hwq); ++#endif ++ hwq->need_processing = false; ++ ++ mu_enable = rwnx_txq_take_mu_lock(rwnx_hw); ++ if (!mu_enable) ++ credit_map = ALL_HWQ_MASK - 1; ++ ++ list_for_each_entry_safe(txq, next, &hwq->list, sched_list) { ++ struct rwnx_txhdr *txhdr = NULL; ++ struct sk_buff_head sk_list_push; ++ struct sk_buff *skb; ++ bool txq_empty; ++#ifdef CREATE_TRACE_POINTS ++ trace_process_txq(txq); ++#endif ++ /* sanity check for debug */ ++ BUG_ON(!(txq->status & RWNX_TXQ_IN_HWQ_LIST)); ++ if(txq->idx == TXQ_INACTIVE){ ++ printk("%s txq->idx == TXQ_INACTIVE \r\n", __func__); ++ rwnx_txq_del_from_hw_list(txq); ++ rwnx_txq_flush(rwnx_hw, txq); ++ continue; ++ } ++ BUG_ON(txq->idx == TXQ_INACTIVE); ++ BUG_ON(txq->credits <= 0); ++ BUG_ON(!rwnx_txq_skb_ready(txq)); ++ ++ if (!rwnx_txq_select_user(rwnx_hw, mu_enable, txq, hwq, &user)) { ++ printk("select user:%d\n", user); ++ continue; ++ } ++ ++ txq_empty = rwnx_txq_get_skb_to_push(rwnx_hw, hwq, txq, user, ++ &sk_list_push); ++ while ((skb = __skb_dequeue(&sk_list_push)) != NULL) { ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ rwnx_tx_push(rwnx_hw, txhdr, 0); ++ } ++ ++ if (txq_empty) { ++ rwnx_txq_del_from_hw_list(txq); ++ txq->pkt_sent = 0; ++ } else if (rwnx_txq_is_scheduled(txq)) { ++ /* txq not empty, ++ - To avoid starving need to process other txq in the list ++ - For better aggregation, need to send "as many consecutive ++ pkt as possible" for he same txq ++ ==> Add counter to trigger txq switch ++ */ ++ if (txq->pkt_sent > hwq->size) { ++ txq->pkt_sent = 0; ++ list_rotate_left(&hwq->list); ++ } ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ /* Unable to complete PS traffic request because of hwq credit */ ++ if (txq->push_limit && txq->sta) { ++ if (txq->ps_id == LEGACY_PS_ID) { ++ /* for legacy PS abort SP and wait next ps-poll */ ++ txq->sta->ps.sp_cnt[txq->ps_id] -= txq->push_limit; ++ txq->push_limit = 0; ++ } ++ /* for u-apsd need to complete the SP to send EOSP frame */ ++ } ++#ifndef CONFIG_ONE_TXQ ++ /* restart netdev queue if number of queued buffer is below threshold */ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && ++ (skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART)) { ++#else ++ if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && ++ skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART) { ++#endif ++ ++ txq->status &= ~RWNX_TXQ_NDEV_FLOW_CTRL; ++ netif_wake_subqueue(txq->ndev, txq->ndev_idx); ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_flowctrl_restart(txq); ++#endif ++ } ++#endif /* CONFIG_ONE_TXQ */ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } ++ ++ ++ if (mu_enable) ++ rwnx_txq_release_mu_lock(rwnx_hw); ++} ++ ++/** ++ * rwnx_hwq_process_all - Process all HW queue list ++ * ++ * @rwnx_hw: Driver main data ++ * ++ * Loop over all HWQ, and process them if needed ++ * To be called with tx_lock hold ++ */ ++void rwnx_hwq_process_all(struct rwnx_hw *rwnx_hw) ++{ ++ int id; ++ ++ rwnx_mu_group_sta_select(rwnx_hw); ++ ++ for (id = ARRAY_SIZE(rwnx_hw->hwq) - 1; id >= 0 ; id--) { ++ if (rwnx_hw->hwq[id].need_processing) { ++ rwnx_hwq_process(rwnx_hw, &rwnx_hw->hwq[id]); ++ } ++ } ++} ++ ++/** ++ * rwnx_hwq_init - Initialize all hwq structures ++ * ++ * @rwnx_hw: Driver main data ++ * ++ */ ++void rwnx_hwq_init(struct rwnx_hw *rwnx_hw) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(rwnx_hw->hwq); i++) { ++ struct rwnx_hwq *hwq = &rwnx_hw->hwq[i]; ++ ++ hwq->id = i; ++ hwq->size = nx_txdesc_cnt[i]; ++ INIT_LIST_HEAD(&hwq->list); ++ ++ } ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h +new file mode 100644 +index 000000000000..9653d014bf70 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h +@@ -0,0 +1,404 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_txq.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++#ifndef _RWNX_TXQ_H_ ++#define _RWNX_TXQ_H_ ++ ++#include ++#include ++#include ++ ++#include ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/** ++ * Fullmac TXQ configuration: ++ * - STA: 1 TXQ per TID (limited to 8) ++ * 1 TXQ for bufferable MGT frames ++ * - VIF: 1 TXQ for Multi/Broadcast + ++ * 1 TXQ for MGT for unknown STAs or non-bufferable MGT frames ++ * - 1 TXQ for offchannel transmissions ++ * ++ * ++ * Txq mapping looks like ++ * for NX_REMOTE_STA_MAX=10 and NX_VIRT_DEV_MAX=4 ++ * ++ * | TXQ | NDEV_ID | VIF | STA | TID | HWQ | ++ * |-----+---------+-----+-------+------+-----|- ++ * | 0 | 0 | | 0 | 0 | 1 | 9 TXQ per STA ++ * | 1 | 1 | | 0 | 1 | 0 | (8 data + 1 mgmt) ++ * | 2 | 2 | | 0 | 2 | 0 | ++ * | 3 | 3 | | 0 | 3 | 1 | ++ * | 4 | 4 | | 0 | 4 | 2 | ++ * | 5 | 5 | | 0 | 5 | 2 | ++ * | 6 | 6 | | 0 | 6 | 3 | ++ * | 7 | 7 | | 0 | 7 | 3 | ++ * | 8 | N/A | | 0 | MGMT | 3 | ++ * |-----+---------+-----+-------+------+-----|- ++ * | ... | | | | | | Same for all STAs ++ * |-----+---------+-----+-------+------+-----|- ++ * | 90 | 80 | 0 | BC/MC | 0 | 1/4 | 1 TXQ for BC/MC per VIF ++ * | ... | | | | | | ++ * | 93 | 80 | 3 | BC/MC | 0 | 1/4 | ++ * |-----+---------+-----+-------+------+-----|- ++ * | 94 | N/A | 0 | N/A | MGMT | 3 | 1 TXQ for unknown STA per VIF ++ * | ... | | | | | | ++ * | 97 | N/A | 3 | N/A | MGMT | 3 | ++ * |-----+---------+-----+-------+------+-----|- ++ * | 98 | N/A | | N/A | MGMT | 3 | 1 TXQ for offchannel frame ++ */ ++#define NX_NB_TID_PER_STA 8 ++#define NX_NB_TXQ_PER_STA (NX_NB_TID_PER_STA + 1) ++#define NX_NB_TXQ_PER_VIF 2 ++#define NX_NB_TXQ ((NX_NB_TXQ_PER_STA * NX_REMOTE_STA_MAX) + \ ++ (NX_NB_TXQ_PER_VIF * NX_VIRT_DEV_MAX) + 1) ++ ++#define NX_FIRST_VIF_TXQ_IDX (NX_REMOTE_STA_MAX * NX_NB_TXQ_PER_STA) ++#define NX_FIRST_BCMC_TXQ_IDX NX_FIRST_VIF_TXQ_IDX ++#define NX_FIRST_UNK_TXQ_IDX (NX_FIRST_BCMC_TXQ_IDX + NX_VIRT_DEV_MAX) ++ ++#define NX_OFF_CHAN_TXQ_IDX (NX_FIRST_VIF_TXQ_IDX + \ ++ (NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF)) ++ ++#define NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC (NX_REMOTE_STA_MAX_FOR_OLD_IC * NX_NB_TXQ_PER_STA) ++#define NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC ++#define NX_FIRST_UNK_TXQ_IDX_FOR_OLD_IC (NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC + NX_VIRT_DEV_MAX) ++ ++#define NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC (NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + \ ++ (NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF)) ++ ++ ++#define NX_BCMC_TXQ_TYPE 0 ++#define NX_UNK_TXQ_TYPE 1 ++ ++/** ++ * Each data TXQ is a netdev queue. TXQ to send MGT are not data TXQ as ++ * they did not recieved buffer from netdev interface. ++ * Need to allocate the maximum case. ++ * AP : all STAs + 1 BC/MC ++ */ ++#define NX_NB_NDEV_TXQ ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX) + 1) ++#define NX_NB_NDEV_TXQ_FOR_OLD_IC ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC) + 1) ++ ++#define NX_BCMC_TXQ_NDEV_IDX (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX) ++#define NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC) ++#define NX_STA_NDEV_IDX(tid, sta_idx) ((tid) + (sta_idx) * NX_NB_TID_PER_STA) ++#define NDEV_NO_TXQ 0xffff ++#if (NX_NB_NDEV_TXQ >= NDEV_NO_TXQ) ++#error("Need to increase struct rwnx_txq->ndev_idx size") ++#endif ++ ++/* stop netdev queue when number of queued buffers if greater than this */ ++#define RWNX_NDEV_FLOW_CTRL_STOP 64 ++/* restart netdev queue when number of queued buffers is lower than this */ ++#define RWNX_NDEV_FLOW_CTRL_RESTART 64 ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#define TXQ_INACTIVE 0xffff ++#if (NX_NB_TXQ >= TXQ_INACTIVE) ++#error("Need to increase struct rwnx_txq->idx size") ++#endif ++ ++#define NX_TXQ_INITIAL_CREDITS 64 ++ ++/** ++ * TXQ tid sorted by decreasing priority ++ */ ++extern const int nx_tid_prio[NX_NB_TID_PER_STA]; ++ ++/** ++ * struct rwnx_hwq - Structure used to save information relative to ++ * an AC TX queue (aka HW queue) ++ * @list: List of TXQ, that have buffers ready for this HWQ ++ * @credits: available credit for the queue (i.e. nb of buffers that ++ * can be pushed to FW ) ++ * @id Id of the HWQ among RWNX_HWQ_.... ++ * @size size of the queue ++ * @need_processing Indicate if hwq should be processed ++ * @len number of packet ready to be pushed to fw for this HW queue ++ * @len_stop threshold to stop mac80211(i.e. netdev) queues. Stop queue when ++ * driver has more than @len_stop packets ready. ++ * @len_start threshold to wake mac8011 queues. Wake queue when driver has ++ * less than @len_start packets ready. ++ */ ++struct rwnx_hwq { ++ struct list_head list; ++ u8 size; ++ u8 id; ++ bool need_processing; ++}; ++ ++/** ++ * enum rwnx_push_flags - Flags of pushed buffer ++ * ++ * @RWNX_PUSH_RETRY Pushing a buffer for retry ++ * @RWNX_PUSH_IMMEDIATE Pushing a buffer without queuing it first ++ */ ++enum rwnx_push_flags { ++ RWNX_PUSH_RETRY = BIT(0), ++ RWNX_PUSH_IMMEDIATE = BIT(1), ++}; ++ ++/** ++ * enum rwnx_txq_flags - TXQ status flag ++ * ++ * @RWNX_TXQ_IN_HWQ_LIST: The queue is scheduled for transmission ++ * @RWNX_TXQ_STOP_FULL: No more credits for the queue ++ * @RWNX_TXQ_STOP_CSA: CSA is in progress ++ * @RWNX_TXQ_STOP_STA_PS: Destiniation sta is currently in power save mode ++ * @RWNX_TXQ_STOP_VIF_PS: Vif owning this queue is currently in power save mode ++ * @RWNX_TXQ_STOP_CHAN: Channel of this queue is not the current active channel ++ * @RWNX_TXQ_STOP_MU_POS: TXQ is stopped waiting for all the buffers pushed to ++ * fw to be confirmed ++ * @RWNX_TXQ_STOP: All possible reason to have a txq stopped ++ * @RWNX_TXQ_NDEV_FLOW_CTRL: associated netdev queue is currently stopped. ++ * Note: when a TXQ is flowctrl it is NOT stopped ++ */ ++enum rwnx_txq_flags { ++ RWNX_TXQ_IN_HWQ_LIST = BIT(0), ++ RWNX_TXQ_STOP_FULL = BIT(1), ++ RWNX_TXQ_STOP_CSA = BIT(2), ++ RWNX_TXQ_STOP_STA_PS = BIT(3), ++ RWNX_TXQ_STOP_VIF_PS = BIT(4), ++ RWNX_TXQ_STOP_CHAN = BIT(5), ++ RWNX_TXQ_STOP_MU_POS = BIT(6), ++ RWNX_TXQ_STOP = (RWNX_TXQ_STOP_FULL | RWNX_TXQ_STOP_CSA | ++ RWNX_TXQ_STOP_STA_PS | RWNX_TXQ_STOP_VIF_PS | ++ RWNX_TXQ_STOP_CHAN), ++ RWNX_TXQ_NDEV_FLOW_CTRL = BIT(7), ++}; ++ ++ ++/** ++ * struct rwnx_txq - Structure used to save information relative to ++ * a RA/TID TX queue ++ * ++ * @idx: Unique txq idx. Set to TXQ_INACTIVE if txq is not used. ++ * @status: bitfield of @rwnx_txq_flags. ++ * @credits: available credit for the queue (i.e. nb of buffers that ++ * can be pushed to FW). ++ * @pkt_sent: number of consecutive pkt sent without leaving HW queue list ++ * @pkt_pushed: number of pkt currently pending for transmission confirmation ++ * @sched_list: list node for HW queue schedule list (rwnx_hwq.list) ++ * @sk_list: list of buffers to push to fw ++ * @last_retry_skb: pointer on the last skb in @sk_list that is a retry. ++ * (retry skb are stored at the beginning of the list) ++ * NULL if no retry skb is queued in @sk_list ++ * @nb_retry: Number of retry packet queued. ++ * @hwq: Pointer on the associated HW queue. ++ * @push_limit: number of packet to push before removing the txq from hwq list. ++ * (we always have push_limit < skb_queue_len(sk_list)) ++ * @tid: TID ++ * ++ * SOFTMAC specific: ++ * @baw: Block Ack window information ++ * @amsdu_anchor: pointer to rwnx_sw_txhdr of the first subframe of the A-MSDU. ++ * NULL if no A-MSDU frame is in construction ++ * @amsdu_ht_len_cap: ++ * @amsdu_vht_len_cap: ++ * @nb_ready_mac80211: Number of buffer ready in mac80211 txq ++ * ++ * FULLMAC specific ++ * @ps_id: Index to use for Power save mode (LEGACY or UAPSD) ++ * @ndev_idx: txq idx from netdev point of view (0xFF for non netdev queue) ++ * @ndev: pointer to ndev of the corresponding vif ++ * @amsdu: pointer to rwnx_sw_txhdr of the first subframe of the A-MSDU. ++ * NULL if no A-MSDU frame is in construction ++ * @amsdu_len: Maximum size allowed for an A-MSDU. 0 means A-MSDU not allowed ++ */ ++struct rwnx_txq { ++ u16 idx; ++ u8 status; ++ s8 credits; ++ u8 pkt_sent; ++ u8 pkt_pushed[CONFIG_USER_MAX]; ++ struct list_head sched_list; ++ struct sk_buff_head sk_list; ++ struct sk_buff *last_retry_skb; ++ struct rwnx_hwq *hwq; ++ int nb_retry; ++ u8 push_limit; ++ u8 tid; ++#ifdef CONFIG_MAC80211_TXQ ++ unsigned long nb_ready_mac80211; ++#endif ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_sta *sta; ++ u8 ps_id; ++ u16 ndev_idx; ++ struct net_device *ndev; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ struct rwnx_sw_txhdr *amsdu; ++ u16 amsdu_len; ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++#endif /* CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ u8 mumimo_info; ++#endif ++}; ++ ++struct rwnx_sta; ++struct rwnx_vif; ++struct rwnx_hw; ++struct rwnx_sw_txhdr; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++#define RWNX_TXQ_GROUP_ID(txq) ((txq)->mumimo_info & 0x3f) ++#define RWNX_TXQ_POS_ID(txq) (((txq)->mumimo_info >> 6) & 0x3) ++#else ++#define RWNX_TXQ_GROUP_ID(txq) 0 ++#define RWNX_TXQ_POS_ID(txq) 0 ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++static inline bool rwnx_txq_is_stopped(struct rwnx_txq *txq) ++{ ++ return (txq->status & RWNX_TXQ_STOP); ++} ++ ++static inline bool rwnx_txq_is_full(struct rwnx_txq *txq) ++{ ++ return (txq->status & RWNX_TXQ_STOP_FULL); ++} ++ ++static inline bool rwnx_txq_is_scheduled(struct rwnx_txq *txq) ++{ ++ return (txq->status & RWNX_TXQ_IN_HWQ_LIST); ++} ++ ++/** ++ * foreach_sta_txq - Macro to iterate over all TXQ of a STA in increasing ++ * TID order ++ * ++ * @sta: pointer to rwnx_sta ++ * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration ++ * @tid: int updated with the TXQ tid at each iteration ++ * @rwnx_hw: main driver data ++ */ ++#ifdef CONFIG_MAC80211_TXQ ++#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \ ++ for (tid = 0, txq = rwnx_txq_sta_get(sta, 0); \ ++ tid < NX_NB_TXQ_PER_STA; \ ++ tid++, txq = rwnx_txq_sta_get(sta, tid)) ++ ++#elif defined(CONFIG_RWNX_FULLMAC) /* CONFIG_RWNX_FULLMAC */ ++#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \ ++ for (tid = 0, txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); \ ++ tid < (is_multicast_sta(sta->sta_idx) ? 1 : NX_NB_TXQ_PER_STA); \ ++ tid++, txq++) ++ ++#endif ++ ++/** ++ * foreach_sta_txq_prio - Macro to iterate over all TXQ of a STA in ++ * decreasing priority order ++ * ++ * @sta: pointer to rwnx_sta ++ * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration ++ * @tid: int updated with the TXQ tid at each iteration ++ * @i: int updated with ieration count ++ * @rwnx_hw: main driver data ++ * ++ * Note: For fullmac txq for mgmt frame is skipped ++ */ ++#ifdef CONFIG_RWNX_FULLMAC ++#define foreach_sta_txq_prio(sta, txq, tid, i, rwnx_hw) \ ++ for (i = 0, tid = nx_tid_prio[0], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); \ ++ i < NX_NB_TID_PER_STA; \ ++ i++, tid = nx_tid_prio[i], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw)) ++#endif ++ ++/** ++ * foreach_vif_txq - Macro to iterate over all TXQ of a VIF (in AC order) ++ * ++ * @vif: pointer to rwnx_vif ++ * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration ++ * @ac: int updated with the TXQ ac at each iteration ++ */ ++#ifdef CONFIG_MAC80211_TXQ ++#define foreach_vif_txq(vif, txq, ac) \ ++ for (ac = RWNX_HWQ_BK, txq = rwnx_txq_vif_get(vif, ac); \ ++ ac < NX_NB_TXQ_PER_VIF; \ ++ ac++, txq = rwnx_txq_vif_get(vif, ac)) ++ ++#else ++#define foreach_vif_txq(vif, txq, ac) \ ++ for (ac = RWNX_HWQ_BK, txq = &vif->txqs[0]; \ ++ ac < NX_NB_TXQ_PER_VIF; \ ++ ac++, txq++) ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++struct rwnx_txq *rwnx_txq_sta_get(struct rwnx_sta *sta, u8 tid, ++ struct rwnx_hw *rwnx_hw); ++struct rwnx_txq *rwnx_txq_vif_get(struct rwnx_vif *vif, u8 type); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/** ++ * rwnx_txq_vif_get_status - return status bits related to the vif ++ * ++ * @rwnx_vif: Pointer to vif structure ++ */ ++static inline u8 rwnx_txq_vif_get_status(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq = rwnx_txq_vif_get(rwnx_vif, 0); ++ return (txq->status & (RWNX_TXQ_STOP_CHAN | RWNX_TXQ_STOP_VIF_PS)); ++} ++ ++void rwnx_txq_vif_init(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 status); ++void rwnx_txq_vif_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); ++void rwnx_txq_sta_init(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ u8 status); ++void rwnx_txq_sta_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_unk_vif_init(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_unk_vif_deinit(struct rwnx_vif *vif); ++void rwnx_txq_offchan_init(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_offchan_deinit(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_tdls_vif_init(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_tdls_vif_deinit(struct rwnx_vif *vif); ++void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_tdls_sta_stop(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++#endif ++ ++ ++void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq); ++void rwnx_txq_del_from_hw_list(struct rwnx_txq *txq); ++void rwnx_txq_stop(struct rwnx_txq *txq, u16 reason); ++void rwnx_txq_start(struct rwnx_txq *txq, u16 reason); ++void rwnx_txq_vif_start(struct rwnx_vif *vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_vif_stop(struct rwnx_vif *vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_sta_start(struct rwnx_sta *sta, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_sta_stop(struct rwnx_sta *sta, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_offchan_start(struct rwnx_hw *rwnx_hw); ++void rwnx_txq_sta_switch_vif(struct rwnx_sta *sta, struct rwnx_vif *old_vif, ++ struct rwnx_vif *new_vif); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, ++ struct rwnx_hw *rwnx_hw, bool retry); ++void rwnx_txq_confirm_any(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, ++ struct rwnx_hwq *hwq, struct rwnx_sw_txhdr *sw_txhdr); ++ ++ ++void rwnx_hwq_init(struct rwnx_hw *rwnx_hw); ++void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq); ++void rwnx_hwq_process_all(struct rwnx_hw *rwnx_hw); ++ ++#endif /* _RWNX_TXQ_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c +new file mode 100644 +index 000000000000..6b3c6f29bf10 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c +@@ -0,0 +1,39 @@ ++/** ++ * rwnx_utils.c ++ * ++ * IPC utility function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ */ ++#include "rwnx_utils.h" ++#include "rwnx_defs.h" ++#include "rwnx_rx.h" ++#include "rwnx_tx.h" ++#include "rwnx_msg_rx.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_prof.h" ++#include "ipc_host.h" ++ ++extern int get_testmode(void); ++extern void get_fw_path(char* fw_path); ++extern int testmode; ++extern char aic_fw_path[200]; ++ ++ ++int rwnx_init_aic(struct rwnx_hw *rwnx_hw) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_host_init(&(rwnx_hw->sdio_env), NULL, NULL, rwnx_hw); ++#else ++ aicwf_usb_host_init(&(rwnx_hw->usb_env), NULL, NULL, rwnx_hw); ++#endif ++ rwnx_cmd_mgr_init(rwnx_hw->cmd_mgr); ++ ++ testmode = get_testmode(); ++ memset(aic_fw_path, 0, 200); ++ get_fw_path(aic_fw_path); ++ ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h +new file mode 100644 +index 000000000000..f71a601c2af3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h +@@ -0,0 +1,133 @@ ++/** ++ * rwnx_ipc_utils.h ++ * ++ * IPC utility function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ */ ++#ifndef _RWNX_IPC_UTILS_H_ ++#define _RWNX_IPC_UTILS_H_ ++ ++#include ++#include ++#include ++#include "aicwf_debug.h" ++ ++ ++#include "lmac_msg.h" ++#if 0 ++#ifdef CONFIG_RWNX_DBG ++/* #define RWNX_DBG(format, arg...) pr_warn(format, ## arg) */ ++#define RWNX_DBG printk ++#else ++#define RWNX_DBG(a...) do {} while (0) ++#endif ++ ++#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ ++#endif ++enum rwnx_dev_flag { ++ RWNX_DEV_RESTARTING, ++ RWNX_DEV_STACK_RESTARTING, ++ RWNX_DEV_STARTED, ++}; ++ ++struct rwnx_hw; ++struct rwnx_sta; ++ ++/** ++ * struct rwnx_ipc_elem - Generic IPC buffer of fixed size ++ * ++ * @addr: Host address of the buffer. ++ * @dma_addr: DMA address of the buffer. ++ */ ++struct rwnx_ipc_elem { ++ void *addr; ++ dma_addr_t dma_addr; ++}; ++ ++/** ++ * struct rwnx_ipc_elem_pool - Generic pool of IPC buffers of fixed size ++ * ++ * @nb: Number of buffers currenlty allocated in the pool ++ * @buf: Array of buffers (size of array is @nb) ++ * @pool: DMA pool in which buffers have been allocated ++ */ ++struct rwnx_ipc_elem_pool { ++ int nb; ++ struct rwnx_ipc_elem *buf; ++ struct dma_pool *pool; ++}; ++ ++/** ++ * struct rwnx_ipc_elem - Generic IPC buffer of variable size ++ * ++ * @addr: Host address of the buffer. ++ * @dma_addr: DMA address of the buffer. ++ * @size: Size, in bytes, of the buffer ++ */ ++struct rwnx_ipc_elem_var { ++ void *addr; ++ dma_addr_t dma_addr; ++ size_t size; ++}; ++ ++/** ++ * struct rwnx_ipc_dbgdump_elem - IPC buffer for debug dump ++ * ++ * @mutex: Mutex to protect access to debug dump ++ * @buf: IPC buffer ++ */ ++struct rwnx_ipc_dbgdump_elem { ++ struct mutex mutex; ++ struct rwnx_ipc_elem_var buf; ++}; ++ ++static const u32 rwnx_rxbuff_pattern = 0xCAFEFADE; ++ ++/* ++ * Maximum Length of Radiotap header vendor specific data(in bytes) ++ */ ++#define RADIOTAP_HDR_VEND_MAX_LEN 16 ++ ++/* ++ * Maximum Radiotap Header Length without vendor specific data (in bytes) ++ */ ++#define RADIOTAP_HDR_MAX_LEN 80 ++ ++/* ++ * Unsupported HT Frame data length (in bytes) ++ */ ++#define UNSUP_RX_VEC_DATA_LEN 2 ++ ++/** ++ * struct rwnx_ipc_skb_elem - IPC buffer for SKB element ++ * ++ * @skb: Pointer to the skb buffer allocated ++ * @dma_addr: DMA address of the data buffer fo skb ++ * ++ */ ++struct rwnx_ipc_skb_elem { ++ struct sk_buff *skb; ++ dma_addr_t dma_addr; ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++/* Maximum number of rx buffer the fw may use at the same time */ ++#define RWNX_RXBUFF_MAX (64 * NX_REMOTE_STA_MAX) ++ ++/** ++ * struct rwnx_ipc_rxbuf_elems - IPC buffers for RX ++ * ++ * @skb: Array of buffer push to FW. ++ * @idx: Index of the last pushed skb.(Use to find the next free entry quicker) ++ * ++ * Note: contrary to softmac version, dma_addr are stored inside skb->cb. ++ */ ++struct rwnx_ipc_rxbuf_elems { ++ struct sk_buff *skb[RWNX_RXBUFF_MAX]; ++ int idx; ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++#endif /* _RWNX_IPC_UTILS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c +new file mode 100644 +index 000000000000..72e3c850b48e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c +@@ -0,0 +1,195 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_v7.c - Support for v7 platform ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_v7.h" ++#include "rwnx_defs.h" ++#include "rwnx_irqs.h" ++#include "reg_access.h" ++#include "hal_desc.h" ++ ++struct rwnx_v7 { ++ u8 *pci_bar0_vaddr; ++ u8 *pci_bar1_vaddr; ++}; ++ ++static int rwnx_v7_platform_enable(struct rwnx_hw *rwnx_hw) ++{ ++ int ret; ++ ++ /* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */ ++ ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0, ++ "rwnx", rwnx_hw); ++ return ret; ++} ++ ++static int rwnx_v7_platform_disable(struct rwnx_hw *rwnx_hw) ++{ ++ free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw); ++ return 0; ++} ++ ++static void rwnx_v7_platform_deinit(struct rwnx_plat *rwnx_plat) ++{ ++ #ifdef CONFIG_PCI ++ struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; ++ ++ pci_disable_device(rwnx_plat->pci_dev); ++ iounmap(rwnx_v7->pci_bar0_vaddr); ++ iounmap(rwnx_v7->pci_bar1_vaddr); ++ pci_release_regions(rwnx_plat->pci_dev); ++ pci_clear_master(rwnx_plat->pci_dev); ++ pci_disable_msi(rwnx_plat->pci_dev); ++ #endif ++ kfree(rwnx_plat); ++} ++ ++static u8 *rwnx_v7_get_address(struct rwnx_plat *rwnx_plat, int addr_name, ++ unsigned int offset) ++{ ++ struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; ++ ++ if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name)) ++ return NULL; ++ ++ if (addr_name == RWNX_ADDR_CPU) ++ return rwnx_v7->pci_bar0_vaddr + offset; ++ else ++ return rwnx_v7->pci_bar1_vaddr + offset; ++} ++ ++static void rwnx_v7_ack_irq(struct rwnx_plat *rwnx_plat) ++{ ++ ++} ++ ++static const u32 rwnx_v7_config_reg[] = { ++ NXMAC_DEBUG_PORT_SEL_ADDR, ++ SYSCTRL_DIAG_CONF_ADDR, ++ SYSCTRL_PHYDIAG_CONF_ADDR, ++ SYSCTRL_RIUDIAG_CONF_ADDR, ++ RF_V7_DIAGPORT_CONF1_ADDR, ++}; ++ ++static const u32 rwnx_v7_he_config_reg[] = { ++ SYSCTRL_DIAG_CONF0, ++ SYSCTRL_DIAG_CONF1, ++ SYSCTRL_DIAG_CONF2, ++ SYSCTRL_DIAG_CONF3, ++}; ++ ++static int rwnx_v7_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list) ++{ ++ u32 fpga_sign; ++ ++ if (!list) ++ return 0; ++ ++ fpga_sign = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_SIGNATURE_ADDR); ++ if (__FPGA_TYPE(fpga_sign) == 0xc0ca) { ++ *list = rwnx_v7_he_config_reg; ++ return ARRAY_SIZE(rwnx_v7_he_config_reg); ++ } else { ++ *list = rwnx_v7_config_reg; ++ return ARRAY_SIZE(rwnx_v7_config_reg); ++ } ++} ++ ++ ++/** ++ * rwnx_v7_platform_init - Initialize the DINI platform ++ * ++ * @pci_dev PCI device ++ * @rwnx_plat Pointer on struct rwnx_stat * to be populated ++ * ++ * @return 0 on success, < 0 otherwise ++ * ++ * Allocate and initialize a rwnx_plat structure for the dini platform. ++ */ ++int rwnx_v7_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat) ++{ ++ struct rwnx_v7 *rwnx_v7; ++ u16 pci_cmd; ++ int ret = 0; ++ ++ *rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_v7), ++ GFP_KERNEL); ++ if (!*rwnx_plat) ++ return -ENOMEM; ++ ++ rwnx_v7 = (struct rwnx_v7 *)(*rwnx_plat)->priv; ++ ++ /* Hotplug fixups */ ++ pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd); ++ pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; ++ pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd); ++ //pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2); ++ ++ ret = pci_enable_device(pci_dev); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_enable_device failed\n"); ++ goto out_enable; ++ } ++ ++ pci_set_master(pci_dev); ++ ++#if 0 ++ ret = pci_request_regions(pci_dev, KBUILD_MODNAME); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_request_regions failed\n"); ++ goto out_request; ++ } ++#endif ++ #ifdef CONFIG_PCI ++ if (pci_enable_msi(pci_dev)) { ++ dev_err(&(pci_dev->dev), "pci_enable_msi failed\n"); ++ goto out_msi; ++ ++ } ++ #endif ++ ++ rwnx_v7->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0); ++ if (!rwnx_v7->pci_bar0_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0); ++ ret = -ENOMEM; ++ goto out_bar0; ++ } ++ rwnx_v7->pci_bar1_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 1); ++ if (!rwnx_v7->pci_bar1_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 1); ++ ret = -ENOMEM; ++ goto out_bar1; ++ } ++ ++ (*rwnx_plat)->enable = rwnx_v7_platform_enable; ++ (*rwnx_plat)->disable = rwnx_v7_platform_disable; ++ (*rwnx_plat)->deinit = rwnx_v7_platform_deinit; ++ (*rwnx_plat)->get_address = rwnx_v7_get_address; ++ (*rwnx_plat)->ack_irq = rwnx_v7_ack_irq; ++ (*rwnx_plat)->get_config_reg = rwnx_v7_get_config_reg; ++ ++ return 0; ++ ++out_bar1: ++ iounmap(rwnx_v7->pci_bar0_vaddr); ++out_bar0: ++#ifdef CONFIG_PCI ++ pci_disable_msi(pci_dev); ++out_msi: ++#endif ++ pci_release_regions(pci_dev); ++//out_request: ++#ifdef CONFIG_PCI ++ pci_clear_master(pci_dev); ++#endif ++ pci_disable_device(pci_dev); ++out_enable: ++ kfree(*rwnx_plat); ++ return ret; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h +new file mode 100644 +index 000000000000..c2e39765ae1c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h +@@ -0,0 +1,20 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_v7.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_V7_H_ ++#define _RWNX_V7_H_ ++ ++#include ++#include "rwnx_platform.h" ++ ++int rwnx_v7_platform_init(struct pci_dev *pci_dev, ++ struct rwnx_plat **rwnx_plat); ++ ++#endif /* _RWNX_V7_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h +new file mode 100644 +index 000000000000..46ecb5de1ca5 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h +@@ -0,0 +1,12 @@ ++#ifndef _RWNX_VERSION_H_ ++#define _RWNX_VERSION_H_ ++ ++#include "rwnx_version_gen.h" ++ ++static inline void rwnx_print_version(void) ++{ ++ AICWFDBG(LOGINFO, RWNX_VERS_BANNER"\n"); ++ AICWFDBG(LOGINFO, "RELEASE_DATE:%s \r\n", RELEASE_DATE); ++} ++ ++#endif /* _RWNX_VERSION_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h +new file mode 100644 +index 000000000000..6fcb679c8934 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h +@@ -0,0 +1,4 @@ ++#define RWNX_VERS_REV "241c091M (master)" ++#define RWNX_VERS_MOD "6.4.3.0" ++#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" ++#define RELEASE_DATE "2025_0410_b99ca8b6" +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c +new file mode 100644 +index 000000000000..7c785e952c3d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c +@@ -0,0 +1,96 @@ ++#include ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#else ++#include ++#endif ++#include "rwnx_defs.h" ++#include "rwnx_wakelock.h" ++ ++struct wakeup_source *rwnx_wakeup_init(const char *name) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0) ++ struct wakeup_source *ws; ++ ws = wakeup_source_create(name); ++ wakeup_source_add(ws); ++ return ws; ++#else ++ return NULL; ++#endif ++} ++ ++void rwnx_wakeup_deinit(struct wakeup_source *ws) ++{ ++ if (ws && ws->active) ++ __pm_relax(ws); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0) ++ wakeup_source_remove(ws); ++ wakeup_source_destroy(ws); ++#endif ++} ++ ++struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name) ++{ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ return wakeup_source_register(dev, name); ++#else ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_PLATFORM_ROCKCHIP) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) ++ return wakeup_source_register(dev, name); ++#else ++ return wakeup_source_register(name); ++#endif ++ ++#else ++ return wakeup_source_register(name); ++#endif//#if defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_PLATFORM_ROCKCHIP) ++ ++#endif//LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++} ++ ++void rwnx_wakeup_unregister(struct wakeup_source *ws) ++{ ++ if (ws && ws->active) ++ __pm_relax(ws); ++ wakeup_source_unregister(ws); ++} ++ ++void rwnx_wakeup_lock(struct wakeup_source *ws) ++{ ++ __pm_stay_awake(ws); ++} ++ ++void rwnx_wakeup_unlock(struct wakeup_source *ws) ++{ ++ __pm_relax(ws); ++} ++ ++void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec) ++{ ++ __pm_wakeup_event(ws, msec); ++} ++ ++void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw) ++{ ++ rwnx_hw->ws_tx = rwnx_wakeup_init("rwnx_tx_wakelock"); ++ rwnx_hw->ws_rx = rwnx_wakeup_init("rwnx_rx_wakelock"); ++ rwnx_hw->ws_irqrx = rwnx_wakeup_init("rwnx_irqrx_wakelock"); ++ rwnx_hw->ws_pwrctrl = rwnx_wakeup_init("rwnx_pwrcrl_wakelock"); ++} ++ ++void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw) ++{ ++ rwnx_wakeup_deinit(rwnx_hw->ws_tx); ++ rwnx_wakeup_deinit(rwnx_hw->ws_rx); ++ rwnx_wakeup_deinit(rwnx_hw->ws_irqrx); ++ rwnx_wakeup_deinit(rwnx_hw->ws_pwrctrl); ++ rwnx_hw->ws_tx = NULL; ++ rwnx_hw->ws_rx = NULL; ++ rwnx_hw->ws_irqrx = NULL; ++ rwnx_hw->ws_pwrctrl = NULL; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h +new file mode 100644 +index 000000000000..9c9655a46be2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h +@@ -0,0 +1,21 @@ ++#ifndef __RWNX_WAKELOCK_H ++#define __RWNX_WAKELOCK_H ++ ++#include ++#include ++#include ++ ++struct wakeup_source *rwnx_wakeup_init(const char *name); ++void rwnx_wakeup_deinit(struct wakeup_source *ws); ++ ++struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name); ++void rwnx_wakeup_unregister(struct wakeup_source *ws); ++ ++void rwnx_wakeup_lock(struct wakeup_source *ws); ++void rwnx_wakeup_unlock(struct wakeup_source *ws); ++void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec); ++ ++void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw); ++void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c +new file mode 100644 +index 000000000000..f59409946e39 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c +@@ -0,0 +1,137 @@ ++/** ++ * sdio_host.c ++ * ++ * SDIO host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#include "sdio_host.h" ++//#include "ipc_compat.h" ++#include "rwnx_tx.h" ++#include "rwnx_platform.h" ++#include "aicwf_debug.h" ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_sdio_host_init(struct sdio_host_env_tag *env, ++ void *cb, ++ void *shared_env_ptr, ++ void *pthis) ++{ ++ // Reset the environments ++ ++ // Reset the Host environment ++ memset(env, 0, sizeof(struct sdio_host_env_tag)); ++ // Save the pointer to the register base ++ env->pthis = pthis; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++volatile struct txdesc_host *aicwf_sdio_host_txdesc_get(struct sdio_host_env_tag *env, const int queue_idx) ++{ ++ // struct ipc_shared_env_tag *shared_env_ptr = env->shared; ++ volatile struct txdesc_host *txdesc_free = NULL; ++ uint32_t used_idx = env->txdesc_used_idx[queue_idx]; ++ uint32_t free_idx = env->txdesc_free_idx[queue_idx]; ++ ++ // ASSERT_ERR(queue_idx < SDIO_TXQUEUE_CNT); ++ // ASSERT_ERR((free_idx - used_idx) <= SDIO_TXDESC_CNT); ++ ++ // Check if a free descriptor is available ++ if (free_idx != (used_idx + SDIO_TXDESC_CNT)) { ++ // Get the pointer to the first free descriptor ++ // txdesc_free = shared_env_ptr->txdesc[queue_idx] + (free_idx % IPC_TXDESC_CNT); ++ } else { ++ txdesc_free = NULL; ++ } ++ ++ return txdesc_free; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_sdio_host_txdesc_push(struct sdio_host_env_tag *env, const int queue_idx, const uint64_t host_id) ++{ ++ //printk("push, %d, %d, 0x%llx \r\n", queue_idx, env->txdesc_free_idx[queue_idx], host_id); ++ // Save the host id in the environment ++ env->tx_host_id[queue_idx][env->txdesc_free_idx[queue_idx] % SDIO_TXDESC_CNT] = host_id; ++ ++ // Increment the index ++ env->txdesc_free_idx[queue_idx]++; ++ if (env->txdesc_free_idx[queue_idx] == 0x80000000) ++ env->txdesc_free_idx[queue_idx] = 0; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_sdio_host_tx_cfm_handler(struct sdio_host_env_tag *env, u32 *data) ++{ ++ u32 queue_idx = 0;// data[0]; ++ //struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)env->pthis; ++ struct sk_buff *skb = NULL; ++ struct rwnx_txhdr *txhdr; ++ ++ // TX confirmation descriptors have been received ++ // REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM); ++ //while (1) ++ { ++ // Get the used index and increase it. We do the increase before knowing if the ++ // current buffer is confirmed because the callback function may call the ++ // ipc_host_txdesc_get() in case flow control was enabled and the index has to be ++ // already at the good value to ensure that the test of FIFO full is correct ++ //uint32_t used_idx = env->txdesc_used_idx[queue_idx]++; ++ uint32_t used_idx = data[1]; ++ unsigned long host_id = env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT]; ++ ++ // Reset the host id in the array ++ env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = 0; ++ ++ // call the external function to indicate that a TX packet is freed ++ if (host_id == 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ AICWFDBG(LOGERROR, "ERROR:No more confirmations\r\n"); ++ //break; ++ } ++ // set the cfm status ++ skb = (struct sk_buff *)host_id; ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ txhdr->hw_hdr.cfm.status = (union rwnx_hw_txstatus)data[0]; ++ AICWFDBG(LOGINFO, "sdio_host_tx_cfm_handler:used_idx=%d, 0x%p, status=%x\r\n", used_idx, env->pthis, txhdr->hw_hdr.cfm.status.value); ++ //if (env->cb.send_data_cfm(env->pthis, host_id) != 0) ++ if (rwnx_txdatacfm(env->pthis, (void *)host_id) != 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = host_id; ++ // and exit the loop ++ AICWFDBG(LOGERROR, "ERROR:rwnx_txdatacfm,\r\n"); ++ // break; ++ } ++ } ++} ++ ++int aicwf_rwnx_sdio_platform_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct rwnx_plat *rwnx_plat = NULL; ++ void *drvdata; ++ int ret = -ENODEV; ++ ++ rwnx_plat = kzalloc(sizeof(struct rwnx_plat), GFP_KERNEL); ++ ++ if (!rwnx_plat) { ++ return -ENOMEM; ++ } ++ ++ rwnx_plat->sdiodev = sdiodev; ++ ret = rwnx_platform_init(rwnx_plat, &drvdata); ++ ++ return ret; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h +new file mode 100644 +index 000000000000..670e9e08663d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h +@@ -0,0 +1,41 @@ ++/** ++ * sdio_host.h ++ * ++ * SDIO host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#ifndef _SDIO_HOST_H_ ++#define _SDIO_HOST_H_ ++ ++#include "lmac_types.h" ++#include "aicwf_sdio.h" ++ ++#define SDIO_TXQUEUE_CNT NX_TXQ_CNT ++#define SDIO_TXDESC_CNT NX_TXDESC_CNT ++ ++ ++/// Definition of the IPC Host environment structure. ++struct sdio_host_env_tag { ++ // Index used that points to the first free TX desc ++ uint32_t txdesc_free_idx[SDIO_TXQUEUE_CNT]; ++ // Index used that points to the first used TX desc ++ uint32_t txdesc_used_idx[SDIO_TXQUEUE_CNT]; ++ // Array storing the currently pushed host ids, per IPC queue ++ uint64_t tx_host_id[SDIO_TXQUEUE_CNT][SDIO_TXDESC_CNT]; ++ ++ /// Pointer to the attached object (used in callbacks and register accesses) ++ void *pthis; ++}; ++ ++extern void aicwf_sdio_host_init(struct sdio_host_env_tag *env, ++ void *cb, void *shared_env_ptr, void *pthis); ++ ++extern void aicwf_sdio_host_txdesc_push(struct sdio_host_env_tag *env, const int queue_idx, const uint64_t host_id); ++ ++extern void aicwf_sdio_host_tx_cfm_handler(struct sdio_host_env_tag *env, u32 *data); ++extern int aicwf_rwnx_sdio_platform_init(struct aic_sdio_dev *sdiodev); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c +new file mode 100644 +index 000000000000..c5c86d0de27b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c +@@ -0,0 +1,146 @@ ++/** ++ * usb_host.c ++ * ++ * USB host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#include "usb_host.h" ++//#include "ipc_compat.h" ++#include "rwnx_tx.h" ++#include "rwnx_platform.h" ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_usb_host_init(struct usb_host_env_tag *env, ++ void *cb, ++ void *shared_env_ptr, ++ void *pthis) ++{ ++ // Reset the environments ++ ++ // Reset the Host environment ++ memset(env, 0, sizeof(struct usb_host_env_tag)); ++ //printk("[Gaofx]rwnx_init_aic pthis %p !\n", pthis); ++ // Save the pointer to the register base ++ env->pthis = pthis; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++volatile struct txdesc_host *aicwf_usb_host_txdesc_get(struct usb_host_env_tag *env, const int queue_idx) ++{ ++ // struct ipc_shared_env_tag *shared_env_ptr = env->shared; ++ volatile struct txdesc_host *txdesc_free = NULL; ++ uint32_t used_idx = env->txdesc_used_idx[queue_idx]; ++ uint32_t free_idx = env->txdesc_free_idx[queue_idx]; ++ ++ // ASSERT_ERR(queue_idx < SDIO_TXQUEUE_CNT); ++ // ASSERT_ERR((free_idx - used_idx) <= USB_TXDESC_CNT); ++ ++ // Check if a free descriptor is available ++ if (free_idx != (used_idx + USB_TXDESC_CNT)) { ++ // Get the pointer to the first free descriptor ++ // txdesc_free = shared_env_ptr->txdesc[queue_idx] + (free_idx % IPC_TXDESC_CNT); ++ } else { ++ txdesc_free = NULL; ++ } ++ ++ return txdesc_free; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_usb_host_txdesc_push(struct usb_host_env_tag *env, const int queue_idx, const uint64_t host_id) ++{ ++ //printk("push, %d, %d, 0x%llx \r\n", queue_idx, env->txdesc_free_idx[queue_idx], host_id); ++ // Save the host id in the environment ++ env->tx_host_id[queue_idx][env->txdesc_free_idx[queue_idx] % USB_TXDESC_CNT] = host_id; ++ ++ // Increment the index ++ env->txdesc_free_idx[queue_idx]++; ++ if (env->txdesc_free_idx[queue_idx] == 0x80000000) ++ env->txdesc_free_idx[queue_idx] = 0; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_usb_host_tx_cfm_handler(struct usb_host_env_tag *env, u32 *data) ++{ ++ u32 queue_idx = 0;//data[0]; ++ //struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)env->pthis; ++ struct sk_buff *skb = NULL; ++ struct rwnx_txhdr *txhdr; ++ printk("%s enter \n", __func__); ++ //printk("sdio_host_tx_cfm_handler, %d, 0x%08x\r\n", queue_idx, data[1]); ++ // TX confirmation descriptors have been received ++ // REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM); ++ //while (1) ++ { ++ // Get the used index and increase it. We do the increase before knowing if the ++ // current buffer is confirmed because the callback function may call the ++ // ipc_host_txdesc_get() in case flow control was enabled and the index has to be ++ // already at the good value to ensure that the test of FIFO full is correct ++ //uint32_t used_idx = env->txdesc_used_idx[queue_idx]++; ++ uint32_t used_idx = data[1]; ++ uint64_t host_id = env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT]; ++ ++ // Reset the host id in the array ++ env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT] = 0; ++ ++ // call the external function to indicate that a TX packet is freed ++ if (host_id == 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ printk("ERROR:No more confirmations\r\n"); ++ return; ++ //break; ++ } ++ // set the cfm status ++ skb = (struct sk_buff *)(uint64_t)host_id; ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ txhdr->hw_hdr.cfm.status = (union rwnx_hw_txstatus)data[0]; ++ //txhdr->hw_hdr.status = data[1]; ++ //printk("sdio_host_tx_cfm_handler, 0x%p\r\n", env->pthis); ++ //if (env->cb.send_data_cfm(env->pthis, host_id) != 0) ++ if (rwnx_txdatacfm(env->pthis, (void *)host_id) != 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT] = host_id; ++ // and exit the loop ++ printk("ERROR:rwnx_txdatacfm,\r\n"); ++ // break; ++ } ++ } ++} ++ ++int aicwf_rwnx_usb_platform_init(struct aic_usb_dev *usbdev) ++{ ++ struct rwnx_plat *rwnx_plat = NULL; ++ void *drvdata; ++ int ret = -ENODEV; ++ ++ rwnx_plat = kzalloc(sizeof(struct rwnx_plat), GFP_KERNEL); ++ ++ if (!rwnx_plat) ++ return -ENOMEM; ++ ++// rwnx_plat->pci_dev = pci_dev; ++ rwnx_plat->usbdev = usbdev; ++ ++ ret = rwnx_platform_init(rwnx_plat, &drvdata); ++#if 0 ++ pci_set_drvdata(pci_dev, drvdata); ++ ++ if (ret) ++ rwnx_plat->deinit(rwnx_plat); ++#endif ++ return ret; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h +new file mode 100644 +index 000000000000..012b90c9770a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h +@@ -0,0 +1,41 @@ ++/** ++ * usb_host.h ++ * ++ * USB host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#ifndef _USB_HOST_H_ ++#define _USB_HOST_H_ ++ ++#include "lmac_types.h" ++#include "aicwf_usb.h" ++ ++#define USB_TXQUEUE_CNT NX_TXQ_CNT ++#define USB_TXDESC_CNT NX_TXDESC_CNT ++ ++ ++/// Definition of the IPC Host environment structure. ++struct usb_host_env_tag { ++ // Index used that points to the first free TX desc ++ uint32_t txdesc_free_idx[USB_TXQUEUE_CNT]; ++ // Index used that points to the first used TX desc ++ uint32_t txdesc_used_idx[USB_TXQUEUE_CNT]; ++ // Array storing the currently pushed host ids, per IPC queue ++ uint64_t tx_host_id[USB_TXQUEUE_CNT][USB_TXDESC_CNT]; ++ ++ /// Pointer to the attached object (used in callbacks and register accesses) ++ void *pthis; ++}; ++ ++extern void aicwf_usb_host_init(struct usb_host_env_tag *env, ++ void *cb, void *shared_env_ptr, void *pthis); ++ ++extern void aicwf_usb_host_txdesc_push(struct usb_host_env_tag *env, const int queue_idx, const uint64_t host_id); ++ ++extern void aicwf_usb_host_tx_cfm_handler(struct usb_host_env_tag *env, u32 *data); ++extern int aicwf_rwnx_usb_platform_init(struct aic_usb_dev *usbdev); ++ ++#endif diff --git a/patch/kernel/archive/rockchip64-7.0/drv-add-aic8800-sdio.patch b/patch/kernel/archive/rockchip64-7.0/drv-add-aic8800-sdio.patch new file mode 100644 index 000000000000..77a7028765e9 --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/drv-add-aic8800-sdio.patch @@ -0,0 +1,90985 @@ +diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig +index c6599594dc99..81a95a3a4e9a 100644 +--- a/drivers/net/wireless/Kconfig ++++ b/drivers/net/wireless/Kconfig +@@ -19,6 +19,7 @@ menuconfig WLAN + if WLAN + + source "drivers/net/wireless/admtek/Kconfig" ++source "drivers/net/wireless/aic8800_sdio/Kconfig" + source "drivers/net/wireless/ath/Kconfig" + source "drivers/net/wireless/atmel/Kconfig" + source "drivers/net/wireless/broadcom/Kconfig" +diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile +index e1c4141c6004..6837a10805ff 100644 +--- a/drivers/net/wireless/Makefile ++++ b/drivers/net/wireless/Makefile +@@ -4,6 +4,7 @@ + # + + obj-$(CONFIG_WLAN_VENDOR_ADMTEK) += admtek/ ++obj-$(CONFIG_SPARD_WLAN_SUPPORT) += aic8800_sdio/ + obj-$(CONFIG_WLAN_VENDOR_ATH) += ath/ + obj-$(CONFIG_WLAN_VENDOR_ATMEL) += atmel/ + obj-$(CONFIG_WLAN_VENDOR_BROADCOM) += broadcom/ +diff --git a/drivers/net/wireless/aic8800_sdio/Kconfig b/drivers/net/wireless/aic8800_sdio/Kconfig +new file mode 100644 +index 000000000000..e12a89df7899 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/Kconfig +@@ -0,0 +1,17 @@ ++config AIC_WLAN_SUPPORT ++ bool "AIC wireless Support" ++ default y ++ help ++ This is support for aic wireless chip. ++ ++config AIC_FW_PATH ++ depends on AIC_WLAN_SUPPORT ++ string "Firmware & config file path" ++ default "/lib/firmware/aic8800/SDIO/aic8800D80" ++ help ++ Path to the firmware & config file. ++ ++if AIC_WLAN_SUPPORT ++source "drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig" ++source "drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig" ++endif +diff --git a/drivers/net/wireless/aic8800_sdio/Makefile b/drivers/net/wireless/aic8800_sdio/Makefile +new file mode 100644 +index 000000000000..6f02ee9570cd +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/Makefile +@@ -0,0 +1,92 @@ ++CONFIG_AIC8800_BTLPM_SUPPORT := m ++CONFIG_AIC8800_WLAN_SUPPORT := m ++CONFIG_AIC_WLAN_SUPPORT := m ++ ++obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) += aic8800_btlpm/ ++obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/ ++obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800_bsp/ ++ ++MAKEFLAGS +=-j$(shell nproc) ++ ++########## config option ########## ++export CONFIG_USE_FW_REQUEST = n ++export CONFIG_PREALLOC_RX_SKB = y ++export CONFIG_PREALLOC_TXQ = y ++export CONFIG_OOB = n ++export CONFIG_GPIO_WAKEUP = n ++export CONFIG_RESV_MEM_SUPPORT = y ++################################### ++ ++########## Platform support list ########## ++export CONFIG_PLATFORM_ROCKCHIP = n ++export CONFIG_PLATFORM_ROCKCHIP2 = n ++export CONFIG_PLATFORM_ALLWINNER = n ++export CONFIG_PLATFORM_AMLOGIC = n ++export CONFIG_PLATFORM_UBUNTU = y ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ARCH = arm64 ++KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-y += -DANDROID_PLATFORM ++ccflags-y += -DCONFIG_PLATFORM_ROCKCHIP ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++KDIR := /home/yaya/E/Rockchip/3126/Android6/kernel ++ARCH ?= arm ++CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android5/rk3288_JHY/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- ++ccflags-y += -DANDROID_PLATFORM ++ccflags-y += -DCONFIG_PLATFORM_ROCKCHIP2 ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++KDIR = /home/yaya/E/Allwinner/A133/Android10/linux-4.9 ++ARCH = arm64 ++CROSS_COMPILE = /home/yaya/E/Allwinner/r818/Android10/lichee/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++export CONFIG_SUPPORT_LPM = y ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ARCH = arm ++CROSS_COMPILE = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel- ++KDIR = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/out/target/product/u202/obj/KERNEL_OBJ/ ++ccflags-y += -DANDROID_PLATFORM ++export CONFIG_SUPPORT_LPM = y ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++KDIR = /lib/modules/$(shell uname -r)/build ++PWD = $(shell pwd) ++KVER = $(shell uname -r) ++MODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800 ++SUBARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/armv.l/arm/ -e s/aarch64/arm64/) ++ARCH ?= $(SUBARCH) ++CROSS_COMPILE ?= ++endif ++########################################### ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 aic8800_bsp/aic8800_bsp.ko $(MODDESTDIR)/ ++ install -p -m 644 aic8800_fdrv/aic8800_fdrv.ko $(MODDESTDIR)/ ++ install -p -m 644 aic8800_btlpm/aic8800_btlpm.ko $(MODDESTDIR)/ ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/aic8800_bsp.ko ++ rm -rfv $(MODDESTDIR)/aic8800_fdrv.ko ++ rm -rfv $(MODDESTDIR)/aic8800_btlpm.ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ cd aic8800_bsp/;make clean;cd .. ++ cd aic8800_fdrv/;make clean;cd .. ++ cd aic8800_btlpm/;make clean;cd .. ++ rm -rf modules.order Module.symvers .modules.order.cmd .Module.symvers.cmd .tmp_versions/ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore +new file mode 100644 +index 000000000000..c3c2d151e157 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile +new file mode 100644 +index 000000000000..3e3849d0652a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile +@@ -0,0 +1,155 @@ ++CONFIG_SDIO_SUPPORT := y ++CONFIG_SDIO_PWRCTRL := y ++CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800/SDIO/aic8800D80" ++export CONFIG_AIC_FW_PATH ++ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\" ++ ++MODULE_NAME := aic8800_bsp ++ifeq ($(CONFIG_SDIO_SUPPORT), y) ++ccflags-y += -DAICWF_SDIO_SUPPORT ++ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL ++endif ++ ++CONFIG_GPIO_WAKEUP ?= n ++CONFIG_M2D_OTA_AUTO_SUPPORT = n ++CONFIG_M2D_OTA_LZMA_SUPPORT = n ++CONFIG_LINK_DET_5G = y ++CONFIG_MCU_MESSAGE = n ++CONFIG_FIRMWARE_ARRAY = n ++# Need to set fw path in BOARD_KERNEL_CMDLINE ++CONFIG_USE_FW_REQUEST ?= n ++CONFIG_FDRV_NO_REG_SDIO = n ++CONFIG_VRF_DCDC_MODE = y ++CONFIG_OOB ?= n ++CONFIG_PREALLOC_TXQ = y ++CONFIG_DPD = y ++CONFIG_FORCE_DPD_CALIB = y ++CONFIG_LOFT_CALIB = n ++CONFIG_EXT_FEM_8800DCDW = n ++CONFIG_RESV_MEM_SUPPORT ?= y ++CONFIG_AMSDU_RX = y ++CONFIG_IRQ_FALL ?= n ++CONFIG_SDIO_BT = n ++CONFIG_RADAR_OR_IR_DETECT =n ++CONFIG_FOR_IPCAM = n ++ ++ifeq ($(CONFIG_EXT_FEM_8800DCDW), y) ++CONFIG_DPD = n ++CONFIG_FORCE_DPD_CALIB = n ++CONFIG_LOFT_CALIB = y ++endif ++ ++ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP ++ccflags-$(CONFIG_M2D_OTA_AUTO_SUPPORT) += -DCONFIG_M2D_OTA_AUTO_SUPPORT ++ccflags-$(CONFIG_M2D_OTA_LZMA_SUPPORT) += -DCONFIG_M2D_OTA_LZMA_SUPPORT ++ccflags-$(CONFIG_LINK_DET_5G) += -DCONFIG_LINK_DET_5G ++ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE ++ccflags-$(CONFIG_FIRMWARE_ARRAY) += -DCONFIG_FIRMWARE_ARRAY ++ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST ++ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO ++ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE ++ccflags-$(CONFIG_OOB) += -DCONFIG_OOB ++ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ ++ccflags-$(CONFIG_DPD) += -DCONFIG_DPD ++ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD ++ccflags-$(CONFIG_LOFT_CALIB) += -DCONFIG_LOFT_CALIB ++ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW ++ccflags-$(CONFIG_RESV_MEM_SUPPORT) += -DCONFIG_RESV_MEM_SUPPORT ++ccflags-$(CONFIG_AMSDU_RX) += -DCONFIG_AMSDU_RX ++ccflags-$(CONFIG_IRQ_FALL) += -DCONFIG_IRQ_FALL ++ccflags-$(CONFIG_SDIO_BT) += -DCONFIG_SDIO_BT ++ccflags-$(CONFIG_RADAR_OR_IR_DETECT) += -DCONFIG_RADAR_OR_IR_DETECT ++ccflags-$(CONFIG_FOR_IPCAM) += -DCONFIG_FOR_IPCAM ++ ++ ++obj-m := $(MODULE_NAME).o ++$(MODULE_NAME)-y := \ ++ aic8800dc_compat.o \ ++ aic8800d80_compat.o \ ++ aic_bsp_main.o \ ++ aic_bsp_driver.o \ ++ aicsdio.o \ ++ aicsdio_txrxif.o \ ++ md5.o ++ ++$(MODULE_NAME)-$(CONFIG_PREALLOC_TXQ) += aicwf_txq_prealloc.o ++ ++ifeq ($(CONFIG_FIRMWARE_ARRAY),y) ++$(MODULE_NAME)-y += aicwf_firmware_array.o ++endif ++ ++########## Platform support list ########## ++CONFIG_PLATFORM_ROCKCHIP ?= n ++CONFIG_PLATFORM_ROCKCHIP2 ?= n ++CONFIG_PLATFORM_ALLWINNER ?=n ++CONFIG_PLATFORM_INGENIC_T20 ?= n ++CONFIG_PLATFORM_AMLOGIC ?= n ++CONFIG_PLATFORM_UBUNTU ?= y ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 ++ARCH ?= arm64 ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/ ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ++ ++endif ++ ++ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y) ++KDIR ?= /home/yaya/E/T40/kernel ++ARCH ?= mips ++CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC ++KDIR ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/out/target/product/u202/obj/KERNEL_OBJ/ ++ARCH ?= arm ++CROSS_COMPILE ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++ccflags-$(CONFIG_PLATFORM_UBUNTU) += -DCONFIG_PLATFORM_UBUNTU ++KDIR ?= /lib/modules/$(shell uname -r)/build ++PWD ?= $(shell pwd) ++KVER ?= $(shell uname -r) ++MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ++ARCH ?= x86_64 ++CROSS_COMPILE ?= ++ ++ifeq ($(CONFIG_AW_BSP), y) ++ccflags-y += -DCONFIG_PLATFORM_ALLWINNER ++endif ++ ++endif ++########################################### ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk built-in.a ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c +new file mode 100644 +index 000000000000..847da05ad75c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c +@@ -0,0 +1,267 @@ ++#include "aic8800d80_compat.h" ++#include "aic_bsp_driver.h" ++ ++extern struct aicbsp_info_t aicbsp_info; ++extern int adap_test; ++ ++typedef u32 (*array2_tbl_t)[2]; ++ ++#define AIC_PATCH_MAGIG_NUM 0x48435450 // "PTCH" ++#define AIC_PATCH_MAGIG_NUM_2 0x50544348 // "HCTP" ++#define AIC_PATCH_BLOCK_MAX 4 ++ ++typedef struct { ++ uint32_t magic_num; ++ uint32_t pair_start; ++ uint32_t magic_num_2; ++ uint32_t pair_count; ++ uint32_t block_dst[AIC_PATCH_BLOCK_MAX]; ++ uint32_t block_src[AIC_PATCH_BLOCK_MAX]; ++ uint32_t block_size[AIC_PATCH_BLOCK_MAX]; // word count ++} aic_patch_t; ++ ++#define AIC_PATCH_OFST(mem) ((size_t) &((aic_patch_t *)0)->mem) ++#define AIC_PATCH_ADDR(mem) ((u32)(aic_patch_str_base + AIC_PATCH_OFST(mem))) ++ ++u32 aicbsp_syscfg_tbl_8800d80[][2] = { ++}; ++ ++int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev) ++{ ++ int syscfg_num = sizeof(aicbsp_syscfg_tbl_8800d80) / sizeof(u32) / 2; ++ int ret, cnt; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl_8800d80[cnt][0], aicbsp_syscfg_tbl_8800d80[cnt][1]); ++ if (ret) { ++ printk("%x write fail: %d\n", aicbsp_syscfg_tbl_8800d80[cnt][0], ret); ++ return ret; ++ } ++ } ++ return 0; ++} ++ ++ ++u32 adaptivity_patch_tbl_8800d80[][2] = { ++ {0x000C, 0x0000320A}, //linkloss_thd ++ {0x009C, 0x00000000}, //ac_param_conf ++ {0x0168, 0x00010000}, //tx_adaptivity_en ++}; ++ ++#define USER_PWROFST_COVER_CALIB_FLAG 0x01U ++#define USER_CHAN_MAX_TXPWR_EN_FLAG (0x01U << 1) ++#define USER_TX_USE_ANA_F_FLAG (0x01U << 2) ++#define USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG (0x01U << 3) ++ ++#define CFG_PWROFST_COVER_CALIB 1 ++#define CFG_USER_CHAN_MAX_TXPWR_EN 1 ++#define CFG_USER_TX_USE_ANA_F 0 ++#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE 0 ++ ++ ++#define CFG_USER_EXT_FLAGS_EN (CFG_PWROFST_COVER_CALIB || CFG_USER_CHAN_MAX_TXPWR_EN || CFG_USER_TX_USE_ANA_F || CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE) ++ ++u32 patch_tbl_8800d80[][2] = { ++ #ifdef USE_5G ++ {0x00b4, 0xf3010001}, ++ #else ++ {0x00b4, 0xf3010000}, ++ #endif ++#if defined(CONFIG_AMSDU_RX) ++ {0x170, 0x0100000a}, ++#endif ++#ifdef CONFIG_IRQ_FALL ++ {0x00000170, 0x0000010a}, //irqf ++#endif ++ ++ #if CFG_USER_EXT_FLAGS_EN ++ {0x0188, 0x00000000 ++ #if CFG_PWROFST_COVER_CALIB ++ | USER_PWROFST_COVER_CALIB_FLAG ++ #endif ++ #if CFG_USER_CHAN_MAX_TXPWR_EN ++ | USER_CHAN_MAX_TXPWR_EN_FLAG ++ #endif ++ #if CFG_USER_TX_USE_ANA_F ++ | USER_TX_USE_ANA_F_FLAG ++ #endif ++ #if CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE ++ | USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG ++ #endif ++ }, // user_ext_flags ++ #endif ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ {0x019c, 0x00000100}, //enable radar detect ++#endif ++}; ++ ++#ifdef CONFIG_OOB ++// for 8800d40/d80 map data1 isr to gpiob1 ++u32 gpio_cfg_tbl_8800d40d80[][2] = { ++ {0x40504084, 0x00000006}, ++ {0x40500040, 0x00000000}, ++ {0x40100030, 0x00000001}, ++ {0x40241020, 0x00000001}, ++ {0x40240030, 0x00000004}, ++ {0x40240020, 0x03020700}, ++}; ++#endif ++ ++int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev) ++{ ++#ifdef CONFIG_OOB ++ int ret, cnt; ++ int gpiocfg_num = sizeof(gpio_cfg_tbl_8800d40d80) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < gpiocfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, gpio_cfg_tbl_8800d40d80[cnt][0], gpio_cfg_tbl_8800d40d80[cnt][1]); ++ if (ret) { ++ printk("%x write fail: %d\n", gpio_cfg_tbl_8800d40d80[cnt][0], ret); ++ return ret; ++ } ++ } ++#endif ++ ++ return 0; ++} ++ ++#define NEW_PATCH_BUFFER_MAP 1 ++ ++int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev) ++{ ++ const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0198; ++ u32 aic_patch_addr; ++ u32 config_base, aic_patch_str_base; ++ #if (NEW_PATCH_BUFFER_MAP) ++ u32 patch_buff_addr, patch_buff_base, rd_version_addr, rd_version_val; ++ #endif ++ uint32_t start_addr = 0x0016F800; ++ u32 patch_addr = start_addr; ++ u32 patch_cnt = sizeof(patch_tbl_8800d80)/sizeof(u32)/2; ++ struct dbg_mem_read_cfm rd_patch_addr_cfm; ++ int ret = 0; ++ int cnt = 0; ++ //adap test ++ int adap_patch_cnt = 0; ++ ++ if (adap_test) { ++ printk("%s for adaptivity test \r\n", __func__); ++ adap_patch_cnt = sizeof(adaptivity_patch_tbl_8800d80)/sizeof(u32)/2; ++ } ++ ++ aic_patch_addr = rd_patch_addr + 8; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch rd fail\n"); ++ return ret; ++ } ++ ++ config_base = rd_patch_addr_cfm.memdata; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, aic_patch_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch str rd fail\n"); ++ return ret; ++ } ++ aic_patch_str_base = rd_patch_addr_cfm.memdata; ++ ++ #if (NEW_PATCH_BUFFER_MAP) ++ rd_version_addr = RAM_FMAC_FW_ADDR + 0x01C; ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_version_addr, &rd_patch_addr_cfm))) { ++ printk("version val[0x%x] rd fail: %d\n", rd_version_addr, ret); ++ return ret; ++ } ++ rd_version_val = rd_patch_addr_cfm.memdata; ++ printk("rd_version_val=%08X\n", rd_version_val); ++ sdiodev->fw_version_uint = rd_version_val; ++ if (rd_version_val > 0x06090100) { ++ patch_buff_addr = rd_patch_addr + 12; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, patch_buff_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch buf rd fail\n"); ++ return ret; ++ } ++ patch_buff_base = rd_patch_addr_cfm.memdata; ++ patch_addr = start_addr = patch_buff_base; ++ } ++ #endif ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num)); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num_2), AIC_PATCH_MAGIG_NUM_2); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num_2)); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_start), patch_addr); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_start)); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_count), patch_cnt + adap_patch_cnt); ++ if (ret) { ++ printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_count)); ++ return ret; ++ } ++ ++ for (cnt = 0; cnt < patch_cnt; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl_8800d80[cnt][0]+config_base); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl_8800d80[cnt][1]); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ return ret; ++ } ++ } ++ ++ if (adap_test){ ++ int tmp_cnt = patch_cnt + adap_patch_cnt; ++ for (cnt = patch_cnt; cnt < tmp_cnt; cnt++) { ++ int tbl_idx = cnt - patch_cnt; ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, adaptivity_patch_tbl_8800d80[tbl_idx][0]+config_base); ++ if(ret) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, adaptivity_patch_tbl_8800d80[tbl_idx][1]); ++ if(ret) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ return ret; ++ } ++ } ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[0]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[0]), ret); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[1]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[1]), ret); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[2]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[2]), ret); ++ return ret; ++ } ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[3]), 0); ++ if (ret) { ++ printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[3]), ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h +new file mode 100644 +index 000000000000..20956582620f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h +@@ -0,0 +1,24 @@ ++#ifndef _AIC8800D80_COMPAT_H_ ++#define _AIC8800D80_COMPAT_H_ ++ ++#include "aicsdio.h" ++/*typedef u32 (*array2_tbl_t)[2]; ++ ++typedef uint8_t u8_l; ++typedef int8_t s8_l; ++typedef bool bool_l; ++typedef uint16_t u16_l; ++typedef int16_t s16_l; ++typedef uint32_t u32_l; ++typedef int32_t s32_l; ++typedef uint64_t u64_l;*/ ++ ++int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev); ++int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev); ++int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev); ++ ++ ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c +new file mode 100644 +index 000000000000..8efd2b81e194 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c +@@ -0,0 +1,2633 @@ ++#include ++#include "aic8800dc_compat.h" ++#include "aic_bsp_driver.h" ++ ++u8 chip_sub_id = 0; ++u8 chip_mcu_id = 0; ++extern int testmode; ++ ++u32 syscfg_tbl_8800dc[][2] = { ++ {0x40500010, 0x00000004}, ++ {0x40500010, 0x00000006},//160m clk ++}; ++ ++u32 syscfg_tbl_8800dc_sdio_u01[][2] = { ++ {0x40030000, 0x00036724}, // loop forever after assert_err ++ {0x0011E800, 0xE7FE4070}, ++ {0x40030084, 0x0011E800}, ++ {0x40030080, 0x00000001}, ++ {0x4010001C, 0x00000000}, ++}; ++ ++u32 syscfg_tbl_8800dc_sdio_u02[][2] = { ++ {0x40030000, 0x00036DA4}, // loop forever after assert_err ++ {0x0011E800, 0xE7FE4070}, ++ {0x40030084, 0x0011E800}, ++ {0x40030080, 0x00000001}, ++ {0x4010001C, 0x00000000}, ++}; ++#ifdef CONFIG_OOB ++u32 oobcfg_tbl_8800dc_sdio_u02[][2] = { ++ {0x40504044, 0x2},//oob_enable ++ {0x40500060, 0x03020700}, ++ {0x40500040, 0}, ++ {0x40100030, 1}, ++ {0x40241020, 1}, ++ {0x402400f0, 0x340022}, ++}; ++#endif //CONFIG_OOB ++ ++ ++u32 syscfg_tbl_masked_8800dc[][3] = { ++ //#ifdef CONFIG_PMIC_SETTING ++ #if defined(CONFIG_VRF_DCDC_MODE) ++ {0x7000216C, (0x3 << 2), (0x1 << 2)}, // pmic_pmu_init ++ {0x700021BC, (0x3 << 2), (0x1 << 2)}, ++ {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, ++ {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x70002170, (0xF << 0), (0x1 << 0)}, ++ {0x70002190, (0x3F << 0), (24 << 0)}, ++ {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, ++ {0x700010A0, (0x1 << 11), (0x1 << 11)}, ++ {0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))}, ++ {0x70001038, (0x1 << 8), (0x1 << 8)}, ++ {0x70001094, (0x3 << 2), (0x0 << 2)}, ++ {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x1 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ {0x70001028, (0xf << 2), (0x1 << 2)}, ++ #else ++ {0x7000216C, (0x3 << 2), (0x1 << 2)}, // pmic_pmu_init ++ {0x700021BC, (0x3 << 2), (0x1 << 2)}, ++ {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, ++ {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x70002170, (0xF << 0), (0x1 << 0)}, ++ {0x70002190, (0x3F << 0), (24 << 0)}, ++ {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, ++ {0x700010A0, (0x1 << 11), (0x1 << 11)}, ++ {0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))}, ++ {0x70001038, (0x1 << 8), (0x1 << 8)}, ++ {0x70001094, (0x3 << 2), (0x0 << 2)}, ++ {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x0 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ {0x70001028, (0xf << 2), (0x1 << 2)}, ++ #endif ++ //#endif /* CONFIG_PMIC_SETTING */ ++ {0x00000000, 0x00000000, 0x00000000}, // last one ++}; ++ ++u32 syscfg_tbl_masked_8800dc_h[][3] = { ++ {0x7000216C, ((0x3 << 2) | (0x3 << 4)), ((0x2 << 2) | (0x2 << 4))}, // pmic_pmu_init ++ {0x70002138, (0xFF << 0), (0xFF << 0)}, ++ {0x7000213C, (0xFF << 0), (0xFF << 0)}, ++ {0x70002144, (0xFF << 0), (0xFF << 0)}, ++ {0x700021BC, (0x3 << 2), (0x1 << 2)}, ++ {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, ++ {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, ++ {0x70002170, (0xF << 0), (0x1 << 0)}, ++ {0x70002190, (0x3F << 0), (24 << 0)}, ++ {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, ++ {0x700010A0, (0x1 << 11), (0x1 << 11)}, ++ //{0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))}, ++ {0x70001038, (0x1 << 8), (0x1 << 8)}, ++ {0x70001094, (0x3 << 2), (0x0 << 2)}, ++ {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, ++ #if defined(CONFIG_VRF_DCDC_MODE) ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x1 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ #else ++ {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), ++ ((0x0 << 0) | (0x1 << 20) | (0x0 << 22))}, ++ #endif ++ {0x70001028, (0xf << 2), (0x1 << 2)}, ++ ++ {0x00000000, 0x00000000, 0x00000000}, // last one ++}; ++ ++u32 syscfg_tbl_masked_8800dc_u01[][3] = { ++ //#ifdef CONFIG_PMIC_SETTING ++ {0x70001000, (0x1 << 16), (0x1 << 16)}, // for low temperature ++ {0x70001028, (0x1 << 6), (0x1 << 6)}, ++ {0x70001000, (0x1 << 16), (0x0 << 16)}, ++ //#endif /* CONFIG_PMIC_SETTING */ ++}; ++ ++u32 patch_tbl_wifisetting_8800dc_u01[][2] = ++{ ++ {0x010c,0x01001E01} ++}; ++ ++u32 patch_tbl_wifisetting_8800dc_u02[][2] = ++{ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ {0x0124,0x01011E01} ++#else ++ {0x0124,0x01001E01} ++#endif ++}; ++ ++ ++ ++uint32_t ldpc_cfg_ram[] = { ++#if 0//def CONFIG_FPGA_VERIFICATION ++ 0x00363638, ++ 0x1DF8F834, ++ 0x1DF8F834, ++ 0x1DF8F834, ++ 0x1DF8F834, ++ 0x002F2F31, ++ 0x1DF8F82C, ++ 0x1DF8F82C, ++ 0x1DF8F82C, ++ 0x1DF8F82C, ++ 0x00363639, ++ 0x1AA5F834, ++ 0x1AA5F834, ++ 0x1ADEF834, ++ 0x1ADEF834, ++ 0x003A3A3E, ++ 0x1578F436, ++ 0x1578F436, ++ 0x1578F436, ++ 0x15B6F436, ++ 0x003B3B40, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x003B3B41, ++ 0x1DC4F838, ++ 0x1DC4F838, ++ 0x1DF8F838, ++ 0x1DF8F838, ++ 0x003B3B40, ++ 0x1781F838, ++ 0x1781F838, ++ 0x1781F838, ++ 0x17C4F838, ++ 0x003B3B40, ++ 0x0E81F838, ++ 0x0E81F838, ++ 0x0E81F838, ++ 0x0E82F838, ++ 0x003F3F43, ++ 0x1A92F83D, ++ 0x1A92F83E, ++ 0x1A92F83D, ++ 0x1ADDF83D, ++ 0x00272729, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F843, ++ 0x1DF8F843, ++ 0x00272729, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F842, ++ 0x1DF8F842, ++ 0x00262628, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00252528, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00262628, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00242427, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x00232326, ++ 0x1DF8F821, ++ 0x1DF8F820, ++ 0x1DF8F820, ++ 0x1DF8F820, ++ 0x00262628, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x00242427, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x001F1F21, ++ 0x1DF8F81D, ++ 0x1DF8F81D, ++ 0x1DF8F81D, ++ 0x1DF8F81D, ++ 0x00262643, ++ 0x1DF8F822, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x1DF8F821, ++ 0x0018182B, ++ 0x1DF8F816, ++ 0x1DBDF815, ++ 0x1DF8F815, ++ 0x1DF8F815, ++ 0x0018182A, ++ 0x1195F836, ++ 0x1195F815, ++ 0x1195F815, ++ 0x1196F815, ++ 0x0028282C, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0027272C, ++ 0x1DF8F824, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x1DF8F823, ++ 0x0082824A, ++ 0x1ADFF841, ++ 0x1ADDF822, ++ 0x1ADEF822, ++ 0x1ADFF822, ++ 0x003E3E40, ++ 0x09D1F81D, ++ 0x095BF81D, ++ 0x095BF81D, ++ 0x095BF81D, ++ 0x0029292D, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x0028282C, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0029292D, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x0028282E, ++ 0x1DF8F825, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0026262C, ++ 0x1DF8F823, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x0028282D, ++ 0x1DF8F825, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x00282852, ++ 0x1DF8F827, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x1DF8F824, ++ 0x0029294E, ++ 0x1DF8F823, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x1DF8F822, ++ 0x00212143, ++ 0x1DF8F821, ++ 0x1DECF81D, ++ 0x1DF4F81D, ++ 0x1DF8F81D, ++ 0x0086864D, ++ 0x1CF0F844, ++ 0x1CEDF823, ++ 0x1CEFF822, ++ 0x1CF0F822, ++ 0x0047474D, ++ 0x1BE8F823, ++ 0x1BE8F823, ++ 0x1BE9F822, ++ 0x1BEAF822, ++ 0x0018182F, ++ 0x14B0F83C, ++ 0x14B0F814, ++ 0x14B0F814, ++ 0x14B0F814, ++ 0x00404040, ++ 0x0AE1F81E, ++ 0x0A61F81D, ++ 0x0A61F81D, ++ 0x0A61F81D, ++ 0x002C2C40, ++ 0x09555526, ++ 0x09555512, ++ 0x09555513, ++ 0x09555512, ++ 0x00181840, ++ 0x06333329, ++ 0x06333314, ++ 0x06333314, ++ 0x06333314, ++ 0x002B2B2F, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x002B2B32, ++ 0x1DF8F829, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x1DF8F828, ++ 0x002A2A2F, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x002A2A57, ++ 0x1DF8F82B, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x1DF8F827, ++ 0x00919152, ++ 0x1DF8F84B, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x004C4C51, ++ 0x1DF8F826, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x1DF8F825, ++ 0x00444440, ++ 0x0CF8F820, ++ 0x0C6EF81F, ++ 0x0C6EF81F, ++ 0x0C6EF81F, ++ 0x00424240, ++ 0x0D75753E, ++ 0x0D75751E, ++ 0x0D75751E, ++ 0x0D75751E, ++ 0x00191940, ++ 0x0539392E, ++ 0x05393914, ++ 0x05393914, ++ 0x05393914, ++ 0x002F2F32, ++ 0x1AA5F82C, ++ 0x1AA5F82C, ++ 0x1ADEF82C, ++ 0x1ADEF82C, ++ 0x002F2F40, ++ 0x0C6EDE2C, ++ 0x0C6EDE2C, ++ 0x0C6EDE2C, ++ 0x0C6EDE2C, ++ 0x00323240, ++ 0x053BB62E, ++ 0x053BB62E, ++ 0x053BB62E, ++ 0x053BB62E, ++ 0x00333339, ++ 0x1DC4F82F, ++ 0x1DC4F82F, ++ 0x1DF8F82F, ++ 0x1DF8F82F, ++ 0x00333340, ++ 0x0E81F82F, ++ 0x0E81F82F, ++ 0x0E81F82F, ++ 0x0E82F82F, ++ 0x00333340, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x00404040, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x063FC42F, ++ 0x00363640, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x00404040, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x0747DD33, ++ 0x00292940, ++ 0x07484825, ++ 0x07484812, ++ 0x07484812, ++ 0x07484812, ++ 0x00404040, ++ 0x07343428, ++ 0x07343414, ++ 0x07343414, ++ 0x07343414, ++ 0x00404040, ++ 0x0538382A, ++ 0x05383814, ++ 0x05383814, ++ 0x05383814, ++ 0x00404040, ++ 0x05292914, ++ 0x05292909, ++ 0x05292909, ++ 0x05292909, ++ 0x000B0B40, ++ 0x02111108, ++ 0x0211110E, ++ 0x02111108, ++ 0x02111108, ++ 0x00404040, ++ 0x063E3E2E, ++ 0x063E3E15, ++ 0x063E3E14, ++ 0x063E3E14, ++ 0x00404040, ++ 0x062E2E14, ++ 0x062E2E09, ++ 0x062E2E09, ++ 0x062E2E09, ++ 0x000B0B40, ++ 0x02131308, ++ 0x0213130F, ++ 0x02131308, ++ 0x02131308 ++#else ++ 0x00767679, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x006E6E72, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x0076767B, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x1DF8F870, ++ 0x007E7E85, ++ 0x1DF4F876, ++ 0x1DF4F876, ++ 0x1DF4F876, ++ 0x1DF8F876, ++ 0x0081818A, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x0081818D, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x0081818A, ++ 0x1DF8F87B, ++ 0x1DF8F87C, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x007E7E40, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x1DF8F87B, ++ 0x008B8B92, ++ 0x1DF8F887, ++ 0x1DF8F889, ++ 0x1DF8F887, ++ 0x1DF8F887, ++ 0x00515155, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F889, ++ 0x1DF8F889, ++ 0x00515154, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F888, ++ 0x1DF8F888, ++ 0x004F4F53, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004F4F53, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004F4F53, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004E4E53, ++ 0x1DF8F849, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x004D4D52, ++ 0x1DF8F847, ++ 0x1DF8F847, ++ 0x1DF8F847, ++ 0x1DF8F847, ++ 0x004F4F55, ++ 0x1DF8F84B, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x004E4E53, ++ 0x1DF8F849, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x0049494D, ++ 0x1DF8F844, ++ 0x1DF8F844, ++ 0x1DF8F844, ++ 0x1DF8F844, ++ 0x0051518F, ++ 0x1DF8F849, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x1DF8F848, ++ 0x00424277, ++ 0x1DF8F83F, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x00424275, ++ 0x1DF8F89E, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x1DF8F83C, ++ 0x0055555C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x0053535C, ++ 0x1DF8F84C, ++ 0x1DF8F84B, ++ 0x1DF8F84B, ++ 0x1DF8F84B, ++ 0x00F8F89E, ++ 0x1DF8F88C, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x00898940, ++ 0x18F8F846, ++ 0x18CFF845, ++ 0x18CFF844, ++ 0x18CFF844, ++ 0x0056565F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x0055555E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x0056565F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x1DF8F84F, ++ 0x00555561, ++ 0x1DF8F850, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x0053535F, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x0055555F, ++ 0x1DF8F84F, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x005555AA, ++ 0x1DF8F854, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x1DF8F84E, ++ 0x005959A6, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x004F4F9B, ++ 0x1DF8F84E, ++ 0x1DF8F846, ++ 0x1DF8F846, ++ 0x1DF8F846, ++ 0x00F8F8A5, ++ 0x1DF8F894, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x009898A4, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x00464686, ++ 0x1DF8F8B3, ++ 0x1DF8F83D, ++ 0x1DF8F83D, ++ 0x1DF8F83D, ++ 0x008E8E40, ++ 0x1AF8F848, ++ 0x1ADFF848, ++ 0x1ADFF846, ++ 0x1ADFF846, ++ 0x007F7F40, ++ 0x18D2D275, ++ 0x18D2D23A, ++ 0x18D2D23A, ++ 0x18D2D239, ++ 0x00454540, ++ 0x0F868664, ++ 0x0F86863E, ++ 0x0F86863D, ++ 0x0F86863D, ++ 0x005C5C64, ++ 0x1DF8F856, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x005B5B68, ++ 0x1DF8F858, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x1DF8F855, ++ 0x005A5A64, ++ 0x1DF8F855, ++ 0x1DF8F854, ++ 0x1DF8F854, ++ 0x1DF8F854, ++ 0x005A5AB5, ++ 0x1DF8F85B, ++ 0x1DF8F855, ++ 0x1DF8F854, ++ 0x1DF8F854, ++ 0x00F8F8B0, ++ 0x1DF8F8A3, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x00A4A4AE, ++ 0x1DF8F854, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x1DF8F852, ++ 0x009A9A40, ++ 0x1DF8F84E, ++ 0x1DF8F84D, ++ 0x1DF8F84C, ++ 0x1DF8F84C, ++ 0x009C9C40, ++ 0x1DF8F895, ++ 0x1DF8F849, ++ 0x1DF8F84A, ++ 0x1DF8F84A, ++ 0x00494940, ++ 0x1197976F, ++ 0x11979742, ++ 0x11979741, ++ 0x11979741, ++ 0x006E6E74, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x1DF8F869, ++ 0x006E6E40, ++ 0x1ADEF869, ++ 0x1ADEF869, ++ 0x1ADEF869, ++ 0x1ADEF869, ++ 0x00757540, ++ 0x0D78F86E, ++ 0x0D78F86E, ++ 0x0D78F86E, ++ 0x0D79F86E, ++ 0x00787885, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x00787840, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x1DF8F873, ++ 0x00787840, ++ 0x0E81F873, ++ 0x0E81F873, ++ 0x0E81F873, ++ 0x0E82F873, ++ 0x00404040, ++ 0x0E82F873, ++ 0x0E82F873, ++ 0x0E82F873, ++ 0x0E82F873, ++ 0x00818140, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x00404040, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x1092F87E, ++ 0x00737340, ++ 0x14B2B26B, ++ 0x14B2B235, ++ 0x14B2B235, ++ 0x14B2B235, ++ 0x00404040, ++ 0x0E828260, ++ 0x0E82823D, ++ 0x0E82823C, ++ 0x0E82823C, ++ 0x00404040, ++ 0x0F8B8B66, ++ 0x0F8B8B3F, ++ 0x0F8B8B3D, ++ 0x0F8B8B3D, ++ 0x00404040, ++ 0x0B68683D, ++ 0x0B68681E, ++ 0x0B68681E, ++ 0x0B68681E, ++ 0x00222240, ++ 0x06434318, ++ 0x06434329, ++ 0x06434318, ++ 0x06434318, ++ 0x00404040, ++ 0x129D9D72, ++ 0x129D9D43, ++ 0x129D9D41, ++ 0x129D9D41, ++ 0x00404040, ++ 0x0D757542, ++ 0x0D757520, ++ 0x0D757520, ++ 0x0D757520, ++ 0x00232340, ++ 0x084C4C19, ++ 0x084C4C2C, ++ 0x084C4C19, ++ 0x084C4C19 ++#endif ++}; ++ ++uint32_t agc_cfg_ram[] = { ++ 0x20000000, ++ 0x0400000E, ++ 0x3000200E, ++ 0x5B000000, ++ 0x0400004B, ++ 0x3000008E, ++ 0x32000000, ++ 0x0400007B, ++ 0x40000000, ++ 0xF8000026, ++ 0x04000011, ++ 0x4819008E, ++ 0x9C000020, ++ 0x08000191, ++ 0x38008000, ++ 0x0A000000, ++ 0x08104411, ++ 0x38018000, ++ 0x0C004641, ++ 0x08D00014, ++ 0x30000000, ++ 0x01000000, ++ 0x04000017, ++ 0x30000000, ++ 0x3C000000, ++ 0x0400001A, ++ 0x38020000, ++ 0x40000001, ++ 0x0800001D, ++ 0x3808008E, ++ 0x14000050, ++ 0x08000020, ++ 0x4000008E, ++ 0xA400007B, ++ 0x00000101, ++ 0x3000339F, ++ 0x41000700, ++ 0x04104420, ++ 0x90000000, ++ 0x49000000, ++ 0xF00E842F, ++ 0xEC0E842C, ++ 0xEC0E842C, ++ 0x04000032, ++ 0x30000000, ++ 0x48000101, ++ 0x04000032, ++ 0x30000000, ++ 0x48000202, ++ 0x04000032, ++ 0x30000000, ++ 0x46000000, ++ 0x04000011, ++ 0x58010006, ++ 0x3D040472, ++ 0xDC204439, ++ 0x081DD4D2, ++ 0x480A0006, ++ 0xDC2044DC, ++ 0x081DD43C, ++ 0x38050004, ++ 0x0EF1F1C3, ++ 0x342044DC, ++ 0x30000000, ++ 0x01000000, ++ 0x04000042, ++ 0x30000000, ++ 0x33000000, ++ 0x04104445, ++ 0x38008000, ++ 0x2200109C, ++ 0x08104448, ++ 0x38008000, ++ 0x23D4509C, ++ 0x08104417, ++ 0x9000A000, ++ 0x32000000, ++ 0x18000063, ++ 0x14000060, ++ 0x1C000051, ++ 0x10000057, ++ 0x38028000, ++ 0x0C000001, ++ 0x08D04466, ++ 0x3000200F, ++ 0x00000000, ++ 0x00000000, ++ 0x38030000, ++ 0x0C002601, ++ 0x08D0445A, ++ 0x30000000, ++ 0x3D020230, ++ 0x0400005D, ++ 0x30000000, ++ 0x3E000100, ++ 0x04000066, ++ 0x38028000, ++ 0x0C001601, ++ 0x34204466, ++ 0x38028000, ++ 0x0C000A01, ++ 0x34204466, ++ 0x38008004, ++ 0xFF000000, ++ 0x0800007B, ++ 0x3800802F, ++ 0x26000000, ++ 0x0800006C, ++ 0x380404AF, ++ 0x1F191010, ++ 0x0800006F, ++ 0x20000CAF, ++ 0x04000071, ++ 0x60000CAF, ++ 0x18700079, ++ 0x14000077, ++ 0x10000075, ++ 0x28140CAF, ++ 0x09B00084, ++ 0x280A0CAF, ++ 0x09B00084, ++ 0x28060CAF, ++ 0x09B00084, ++ 0x28048086, ++ 0x0800007D, ++ 0x38000086, ++ 0x22800000, ++ 0x04000080, ++ 0x30000000, ++ 0x0EF1F101, ++ 0x36004883, ++ 0x28020000, ++ 0x08000085, ++ 0x3802008E, ++ 0x3D040431, ++ 0x08000088, ++ 0x3805008E, ++ 0x1F241821, ++ 0x0800008B, ++ 0x3000008E, ++ 0xA0163021, ++ 0x0400008E, ++ 0x3000008E, ++ 0x0EF10012, ++ 0x34000091, ++ 0x300000CC, ++ 0x50000000, ++ 0x04000094, ++ 0x380095FE, ++ 0x32010000, ++ 0x04000097, ++ 0x50001FFE, ++ 0x5A010000, ++ 0x6DC9989B, ++ 0xFC19D4B9, ++ 0x30000186, ++ 0x3D840373, ++ 0x0400009E, ++ 0x3000008E, ++ 0x0A000000, ++ 0x040000A1, ++ 0x3000008E, ++ 0x22C00000, ++ 0x040000A4, ++ 0x9000028E, ++ 0x32010001, ++ 0x8E4000AA, ++ 0xC80000B0, ++ 0x00000000, ++ 0x00000000, ++ 0x3000008E, ++ 0x32010001, ++ 0x040000CB, ++ 0x3000008E, ++ 0x29000000, ++ 0x94045011, ++ 0x300019B6, ++ 0x32010000, ++ 0x040000B3, ++ 0x300019B6, ++ 0x3D040431, ++ 0x040000B6, ++ 0x300019B6, ++ 0x22800000, ++ 0x04000097, ++ 0x30000186, ++ 0x3D840473, ++ 0x040000BC, ++ 0x3000008E, ++ 0x29030000, ++ 0x040000BF, ++ 0x9AEE028E, ++ 0x32010100, ++ 0x7C0000C5, ++ 0xCC0000B0, ++ 0x080000B0, ++ 0x00000000, ++ 0x3000008E, ++ 0x32010100, ++ 0x040000C8, ++ 0x3000028E, ++ 0x29000000, ++ 0x94045011, ++ 0x5000038E, ++ 0x29000000, ++ 0x94045011, ++ 0xC0000035, ++ 0x38010006, ++ 0x3D040472, ++ 0x080000D2, ++ 0x30000004, ++ 0x0EF1F141, ++ 0x340000D5, ++ 0x28040004, ++ 0x080000D7, ++ 0x2808000E, ++ 0x080000D9, ++ 0x3000018E, ++ 0x0EF10052, ++ 0x340000DC, ++ 0x3000038E, ++ 0x29000000, ++ 0x94045011, ++ 0x38020000, ++ 0x32000000, ++ 0x080000E2, ++ 0x60000000, ++ 0xD80000E6, ++ 0xD40000E9, ++ 0x040000EC, ++ 0x30000000, ++ 0x0EF1F121, ++ 0x360048EF, ++ 0x30000000, ++ 0x0C002421, ++ 0x360048EF, ++ 0x30000000, ++ 0x0C000021, ++ 0x360048EF, ++ 0x28020000, ++ 0x0800007B, ++ 0x50001EFE, ++ 0x5A010000, ++ 0x6DC998F5, ++ 0xFC19D4F8, ++ 0x3000028E, ++ 0x32000040, ++ 0x040000FB, ++ 0x3AEE028E, ++ 0x32000080, ++ 0x040000FB, ++ 0x30000000, ++ 0x0EF1F101, ++ 0x360048FE, ++ 0x28020000, ++ 0x08000100, ++ 0x3802008E, ++ 0x3D040431, ++ 0x08000103, ++ 0x3805008E, ++ 0x1F241821, ++ 0x08000106, ++ 0x3000008E, ++ 0xA0163021, ++ 0x04000109, ++ 0x3000008E, ++ 0x0EF10012, ++ 0x3400010C, ++ 0x300014F6, ++ 0x32010000, ++ 0x04000114, ++ 0x20000000, ++ 0x04000111, ++ 0x300000EC, ++ 0x50000000, ++ 0x040000F1, ++ 0x300014F6, ++ 0x32030000, ++ 0x04000117, ++ 0x30001086, ++ 0x3D840473, ++ 0x0400011A, ++ 0x5000108E, ++ 0x22C00000, ++ 0x8E47C0CB, ++ 0xCB30011E, ++ 0x300019B6, ++ 0x32040000, ++ 0x04000121, ++ 0x300019B6, ++ 0x3D040431, ++ 0x04000124, ++ 0x300019B6, ++ 0x22800000, ++ 0x04000111, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x30000186, ++ 0x3D840473, ++ 0x0400012D, ++ 0x5000038E, ++ 0x29000000, ++ 0x94045011, ++ 0xC0000131, ++ 0x380C800E, ++ 0xFF000000, ++ 0x08000134, ++ 0x30000004, ++ 0x0FF1F103, ++ 0x34000137, ++ 0x28020000, ++ 0x08000139, ++ 0x3000038E, ++ 0x29000000, ++ 0x94045011, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x58010006, ++ 0x3D040472, ++ 0xDC204543, ++ 0x081DD4D2, ++ 0x480A0006, ++ 0xDC2044DC, ++ 0x081DD546, ++ 0x38050004, ++ 0x0EF1F141, ++ 0x342044DC, ++ 0x2802800E, ++ 0x080000DC, ++ 0x48000035, ++ 0x0400014A, ++ 0x7896638F, ++ 0x4100000F, ++ 0x8C00014F, ++ 0x080450C4, ++ 0x90104574, ++ 0x88C8620F, ++ 0xC000015A, ++ 0x90104574, ++ 0x08104554, ++ 0x94104557, ++ 0x3000628F, ++ 0x29000000, ++ 0x9404517A, ++ 0x3000638F, ++ 0x29000000, ++ 0x0410457A, ++ 0x3800E005, ++ 0x3D010131, ++ 0x0810455D, ++ 0xA832600F, ++ 0x90104574, ++ 0x08000154, ++ 0x94104557, ++ 0xC6104567, ++ 0xC4185563, ++ 0x5802E00F, ++ 0x0FEEEA07, ++ 0x80000174, ++ 0x3420456B, ++ 0x5802E00F, ++ 0x0EEEEA07, ++ 0x80000174, ++ 0x3420456B, ++ 0x30004000, ++ 0x33000001, ++ 0x0400016E, ++ 0x38034005, ++ 0x3D030373, ++ 0x08000171, ++ 0x30006007, ++ 0x33000000, ++ 0x04000174, ++ 0x3000608F, ++ 0x29000000, ++ 0x94045177, ++ 0x4000608F, ++ 0xA010457D, ++ 0x0410457A, ++ 0x3000608F, ++ 0x64000101, ++ 0x04104411, ++ 0x3000608F, ++ 0x64000101, ++ 0x04104580, ++ 0x3000618F, ++ 0x42000001, ++ 0x04000183, ++ 0x38028000, ++ 0x32000000, ++ 0x08104586, ++ 0x280A618F, ++ 0x08000188, ++ 0x480A618F, ++ 0xBC00018B, ++ 0x0800018E, ++ 0x3000618F, ++ 0x34000001, ++ 0x04000005, ++ 0x3000618F, ++ 0x34000000, ++ 0x04000008, ++ 0x3000008F, ++ 0x0EEAED0F, ++ 0x36000194, ++ 0x38038000, ++ 0x34000000, ++ 0x08000197, ++ 0x38028005, ++ 0x29010002, ++ 0x0800019A, ++ 0x3000028F, ++ 0x2200209C, ++ 0x0400019D, ++ 0x3000028F, ++ 0x23D4509C, ++ 0x040001A0, ++ 0x2814028F, ++ 0x080001A2, ++ 0x3000028F, ++ 0x43010201, ++ 0x040001A5, ++ 0x3000128F, ++ 0x32000100, ++ 0x040001A8, ++ 0x5AEE138F, ++ 0x4100000F, ++ 0x7C0001AC, ++ 0x080000F9, ++ 0x592C138F, ++ 0x29000000, ++ 0x8C0001B0, ++ 0x080000F9, ++ 0x2000138F, ++ 0x94045011, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++#if !defined(CONFIG_EXT_FEM_8800DCDW) ++uint32_t txgain_map[96] = { ++#ifdef CONFIG_FPGA_VERIFICATION ++ 0x20c0c971, ++ 0x20c0c980, ++ 0x20c0c992, ++ 0x20c0c9a6, ++ 0x20c0c9bf, ++ 0x20c0caa5, ++ 0x20c0cabd, ++ 0x20c0cba0, ++ 0x20c0cbb6, ++ 0x20c0cbea, ++ 0x20c0ccc5, ++ 0x20c0cdac, ++ 0x20c0cdd0, ++ 0x20c0ceb2, ++ 0x20c0ceff, ++ 0x20c0cfff, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c922, ++ 0x20c0c927, ++ 0x20c0c92c, ++ 0x20c0c931, ++ 0x20c0c937, ++ 0x20c0c93f, ++ 0x20c0c946, ++ 0x20c0c94f, ++ 0x20c0c959, ++ 0x20c0c964, ++ 0x20c0cbee, ++ 0x20c0cce0, ++ 0x20c0ccff, ++ 0x20c0cde2, ++ 0x20c0cdfe, ++ 0x20c0cede, ++ 0x20c0cefc, ++ 0x20c0cfd9, ++ 0x20c0cff8, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c98c, ++ 0x20c0ca79, ++ 0x20c0ca89, ++ 0x20c0cb74, ++ 0x20c0cb84, ++ 0x20c0cb94, ++ 0x20c0cba8, ++ 0x20c0cbbb, ++ 0x20c0cbd2, ++ 0x20c0cbee, ++ 0x20c0cce0, ++ 0x20c0ccff, ++ 0x20c0cde2, ++ 0x20c0cdfe, ++ 0x20c0cede, ++ 0x20c0cefc, ++ 0x20c0cfd9, ++ 0x20c0cff8, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0cfff, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c97c, ++ 0x20c0c98c, ++ 0x20c0ca79, ++ 0x20c0ca89, ++ 0x20c0cb74, ++ 0x20c0cb84, ++ 0x20c0cb94, ++ 0x20c0cba8, ++ 0x20c0cbbb, ++ 0x20c0cbd2, ++#else ++ //11b ++ 0x00ffd780, ++ 0x00ffd872, ++ 0x00ffd880, ++ 0x00ffd972, ++ 0x00ffd980, ++ 0x00ffda75, ++ 0x00ffda86, ++ 0x00ffdb77, ++ 0x00ffdb86, ++ 0x00ffdc78, ++ 0x00ffdc89, ++ 0x00ffdd79, ++ 0x00ffdd89, ++ 0x00ffde83, ++ 0x00ffdf79, ++ 0x00ffdf8b, ++ 0x00ffd072, ++ 0x00ffd072, ++ 0x00ffd080, ++ 0x00ffd172, ++ 0x00ffd180, ++ 0x00ffd272, ++ 0x00ffd280, ++ 0x00ffd36d, ++ 0x00ffd379, ++ 0x00ffd46d, ++ 0x00ffd479, ++ 0x00ffd572, ++ 0x00ffd580, ++ 0x00ffd672, ++ 0x00ffd680, ++ 0x00ffd772, ++ //high ++ 0x00ffc87d, ++ 0x00ffc88b, ++ 0x00ffc979, ++ 0x00ffc989, ++ 0x00ffcc4b, ++ 0x00ffcc54, ++ 0x00ffcc5e, ++ 0x00ffcc69, ++ 0x00ffcc78, ++ 0x00ffcc85, ++ 0x00ffcd70, ++ 0x00ffcd80, ++ 0x00ffce70, ++ 0x00ffce80, ++ 0x00ffcf7d, ++ 0x00ffcf90, ++ 0x00ffc080, ++ 0x00ffc090, ++ 0x00ffc180, ++ 0x00ffc190, ++ 0x00ffc27b, ++ 0x00ffc28b, ++ 0x00ffc37b, ++ 0x00ffc390, ++ 0x00ffc485, ++ 0x00ffc495, ++ 0x00ffc579, ++ 0x00ffc589, ++ 0x00ffc679, ++ 0x00ffc689, ++ 0x00ffc780, ++ 0x00ffc790, ++ //low ++ 0x00ffc87d, ++ 0x00ffc88b, ++ 0x00ffc979, ++ 0x00ffc989, ++ 0x00ffcc4b, ++ 0x00ffcc54, ++ 0x00ffcc5e, ++ 0x00ffcc69, ++ 0x00ffcc78, ++ 0x00ffcc85, ++ 0x00ffcd70, ++ 0x00ffcd80, ++ 0x00ffcd90, ++ 0x00ffcf68, ++ 0x00ffcf75, ++ 0x00ffcf83, ++ 0x00ffc080, ++ 0x00ffc090, ++ 0x00ffc180, ++ 0x00ffc190, ++ 0x00ffc27b, ++ 0x00ffc28b, ++ 0x00ffc37b, ++ 0x00ffc390, ++ 0x00ffc485, ++ 0x00ffc495, ++ 0x00ffc579, ++ 0x00ffc589, ++ 0x00ffc679, ++ 0x00ffc689, ++ 0x00ffc780, ++ 0x00ffc790, ++#endif ++}; ++ ++const uint32_t txgain_map_h[96] = ++{ ++ //11b ++ 0xffd888, //11 ++ 0xffd979, //12 ++ 0xffd988, //13 ++ 0xffda79, //14 ++ 0xffda88, //15 ++ 0xffdb79, //16 ++ 0xffdb88, //17 ++ 0xffdc72, //18 ++ 0xffdc80, //19 ++ 0xffdd80, //20 ++ 0xffde66, //21 ++ 0xffde72, //22 ++ 0xffde80, //23 ++ 0xffdf79, //24 ++ 0xffdf88, //25 ++ 0xffdf98, //26 ++ 0xffd079, //-5 ++ 0xffd088, //-4 ++ 0xffd179, //-3 ++ 0xffd188, //-2 ++ 0xffd288, //-1 ++ 0xffd36c, //0 ++ 0xffd379, //1 ++ 0xffd388, //2 ++ 0xffd479, //3 ++ 0xffd488, //4 ++ 0xffd579, //5 ++ 0xffd588, //6 ++ 0xffd679, //7 ++ 0xffd688, //8 ++ 0xffd779, //9 ++ 0xffd879, //10 ++ //high ++ 0xffc879, //8 ++ 0xffc96b, //9 ++ 0xffc979, //10 ++ 0xffcc45, //11 ++ 0xffcc4d, //12 ++ 0xffcc56, //13 ++ 0xffcc60, //14 ++ 0xffcc6b, //15 ++ 0xffcc79, //16 ++ 0xffcd72, //17 ++ 0xffce60, //18 ++ 0xffce72, //19 ++ 0xffcf72, //20 ++ 0xffcf80, //21 ++ 0xffcf90, //22 ++ 0xffcf90, //23 ++ 0xffc079, //-8 ++ 0xffc16b, //-7 ++ 0xffc179, //-6 ++ 0xffc26b, //-5 ++ 0xffc279, //-4 ++ 0xffc36b, //-3 ++ 0xffc379, //-2 ++ 0xffc46b, //-1 ++ 0xffc479, //0 ++ 0xffc56b, //1 ++ 0xffc579, //2 ++ 0xffc66b, //3 ++ 0xffc679, //4 ++ 0xffc76b, //5 ++ 0xffc779, //6 ++ 0xffc86b, //7 ++ //low ++ 0xffc879, //8 ++ 0xffc96b, //9 ++ 0xffc979, //10 ++ 0xffcc45, //11 ++ 0xffcc4d, //12 ++ 0xffcc56, //13 ++ 0xffcc60, //14 ++ 0xffcc6b, //15 ++ 0xffcc79, //16 ++ 0xffcd72, //17 ++ 0xffcf5b, //18 ++ 0xffcf66, //19 ++ 0xffcf72, //20 ++ 0xffcf80, //21 ++ 0xffcf90, //22 ++ 0xffcf90, //23 ++ 0xffc079, //-8 ++ 0xffc16b, //-7 ++ 0xffc179, //-6 ++ 0xffc26b, //-5 ++ 0xffc279, //-4 ++ 0xffc36b, //-3 ++ 0xffc379, //-2 ++ 0xffc46b, //-1 ++ 0xffc479, //0 ++ 0xffc56b, //1 ++ 0xffc579, //2 ++ 0xffc66b, //3 ++ 0xffc679, //4 ++ 0xffc76b, //5 ++ 0xffc779, //6 ++ 0xffc86b, //7 ++}; ++ ++#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ ++const uint32_t txgain_map_femkct[96] = ++{ ++ //11b ++ 0x00ffd780,//15 ++ 0x00ffd872,//16 ++ 0x00ffd880,//17 ++ 0x00ffd972,//18 ++ 0x00ffd980,//19 ++ 0x00ffda72,//20 ++ 0x00ffda80,//21 ++ 0x00ffdb72,//22 ++ 0x00ffdb80,//23 ++ 0x00ffdc72,//24 ++ 0x00ffdc80,//25 ++ 0x00ffdd72,//26 ++ 0x00ffdd80,//27 ++ 0x00ffde72,//28 ++ 0x00ffde80,//29 ++ 0x00ffdf72,//30 ++ 0x00ffd072,//-1 ++ 0x00ffd072,//0 ++ 0x00ffd080,//1 ++ 0x00ffd172,//2 ++ 0x00ffd180,//3 ++ 0x00ffd272,//4 ++ 0x00ffd280,//5 ++ 0x00ffd36d,//6 ++ 0x00ffd379,//7 ++ 0x00ffd46d,//8 ++ 0x00ffd479,//9 ++ 0x00ffd572,//10 ++ 0x00ffd580,//11 ++ 0x00ffd672,//12 ++ 0x00ffd680,//13 ++ 0x00ffd772,//14 ++ //high ++ 0x00ffc872,//11 ++ 0x00ffc880,//12 ++ 0x00ffc972,//13 ++ 0x00ffc980,//14 ++ 0x00ffca72,//15 ++ 0x00ffca80,//16 ++ 0x00ffcb72,//17 ++ 0x00ffcb80,//18 ++ 0x00ffcc72,//19 ++ 0x00ffcc80,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//25 ++ 0x00ffcf80,//26 ++ 0x00ffc072,//-5 ++ 0x00ffc080,//-4 ++ 0x00ffc172,//-3 ++ 0x00ffc180,//-2 ++ 0x00ffc272,//-1 ++ 0x00ffc280,//0 ++ 0x00ffc372,//1 ++ 0x00ffc380,//2 ++ 0x00ffc472,//3 ++ 0x00ffc480,//4 ++ 0x00ffc572,//5 ++ 0x00ffc580,//6 ++ 0x00ffc672,//7 ++ 0x00ffc680,//8 ++ 0x00ffc772,//9 ++ 0x00ffc780,//10 ++ //low ++ 0x00ffc872,//11 ++ 0x00ffc880,//12 ++ 0x00ffc972,//13 ++ 0x00ffc980,//14 ++ 0x00ffca72,//15 ++ 0x00ffca80,//16 ++ 0x00ffcb72,//17 ++ 0x00ffcb80,//18 ++ 0x00ffcc72,//19 ++ 0x00ffcc80,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//26 ++ 0x00ffcf80,//27 ++ 0x00ffc072,//-5 ++ 0x00ffc080,//-4 ++ 0x00ffc172,//-3 ++ 0x00ffc180,//-2 ++ 0x00ffc272,//-1 ++ 0x00ffc280,//0 ++ 0x00ffc372,//1 ++ 0x00ffc380,//2 ++ 0x00ffc472,//3 ++ 0x00ffc480,//4 ++ 0x00ffc572,//5 ++ 0x00ffc580,//6 ++ 0x00ffc672,//7 ++ 0x00ffc680,//8 ++ 0x00ffc772,//9 ++ 0x00ffc780,//10 ++}; ++ ++const uint32_t txgain_map_femkct_h[96] = ++{ ++ //11b ++ 0x00ffd872,//15 ++ 0x00ffd880,//16 ++ 0x00ffd972,//17 ++ 0x00ffd980,//18 ++ 0x00ffd990,//19 ++ 0x00ffda72,//20 ++ 0x00ffda80,//21 ++ 0x00ffdb72,//22 ++ 0x00ffdb80,//23 ++ 0x00ffdc72,//24 ++ 0x00ffdc80,//25 ++ 0x00ffdd72,//26 ++ 0x00ffdd80,//27 ++ 0x00ffde72,//28 ++ 0x00ffde80,//29 ++ 0x00ffdf72,//30 ++ 0x00ffd072,//-1 ++ 0x00ffd072,//0 ++ 0x00ffd080,//1 ++ 0x00ffd172,//2 ++ 0x00ffd180,//3 ++ 0x00ffd272,//4 ++ 0x00ffd280,//5 ++ 0x00ffd379,//6 ++ 0x00ffd46d,//7 ++ 0x00ffd479,//8 ++ 0x00ffd572,//9 ++ 0x00ffd580,//10 ++ 0x00ffd672,//11 ++ 0x00ffd680,//12 ++ 0x00ffd772,//13 ++ 0x00ffd780,//14 ++ //high ++ 0x00ffc880,//11 ++ 0x00ffc972,//12 ++ 0x00ffc980,//13 ++ 0x00ffca72,//14 ++ 0x00ffca80,//15 ++ 0x00ffcb72,//16 ++ 0x00ffcb80,//17 ++ 0x00ffcc72,//18 ++ 0x00ffcc80,//19 ++ 0x00ffcc90,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//25 ++ 0x00ffcf80,//26 ++ 0x00ffc080,//-5 ++ 0x00ffc172,//-4 ++ 0x00ffc180,//-3 ++ 0x00ffc272,//-2 ++ 0x00ffc280,//-1 ++ 0x00ffc372,//0 ++ 0x00ffc380,//1 ++ 0x00ffc472,//2 ++ 0x00ffc480,//3 ++ 0x00ffc572,//4 ++ 0x00ffc580,//5 ++ 0x00ffc672,//6 ++ 0x00ffc680,//7 ++ 0x00ffc772,//8 ++ 0x00ffc780,//9 ++ 0x00ffc872,//10 ++ //low ++ 0x00ffc880,//11 ++ 0x00ffc972,//12 ++ 0x00ffc980,//13 ++ 0x00ffca72,//14 ++ 0x00ffca80,//15 ++ 0x00ffcb72,//16 ++ 0x00ffcb80,//17 ++ 0x00ffcc72,//18 ++ 0x00ffcc80,//19 ++ 0x00ffcc90,//20 ++ 0x00ffcd72,//21 ++ 0x00ffcd80,//22 ++ 0x00ffce72,//23 ++ 0x00ffce80,//24 ++ 0x00ffcf72,//25 ++ 0x00ffcf80,//26 ++ 0x00ffc080,//-5 ++ 0x00ffc172,//-4 ++ 0x00ffc180,//-3 ++ 0x00ffc272,//-2 ++ 0x00ffc280,//-1 ++ 0x00ffc372,//0 ++ 0x00ffc380,//1 ++ 0x00ffc472,//2 ++ 0x00ffc480,//3 ++ 0x00ffc572,//4 ++ 0x00ffc580,//5 ++ 0x00ffc672,//6 ++ 0x00ffc680,//7 ++ 0x00ffc772,//8 ++ 0x00ffc780,//9 ++ 0x00ffc872,//10 ++}; ++#endif ++ ++u32 jump_tbl[][2] = ++{ ++#ifndef CONFIG_FOR_IPCOM ++ {296, 0x180001}, ++ {137, 0x180011}, ++ {303, 0x1810f9}, ++ {168, 0x18186d}, ++ {308, 0x181bbd}, ++ {288, 0x1820c1}, ++#else ++ {308, 0x181001}, ++ {288, 0x181031}, ++ {296, 0x18120d}, ++ {137, 0x18121d}, ++ {303, 0x182305}, ++ {168, 0x182a79}, ++ {258, 0x182ae1}, ++#endif ++}; ++ ++u32 jump_tbl_u02[][2] = ++{ ++ {303, 0x00180d25}, ++ {168, 0x001814a5}, ++ {265, 0x001816b1}, ++ {266, 0x00181849}, ++ {256, 0x001818ad}, ++ {288, 0x00181bf9}, ++ {333, 0x00182d0d}, ++ { 26, 0x00182d45} ++}; ++ ++ ++u32 patch_tbl_func[][2] = ++{ ++#ifndef CONFIG_FOR_IPCOM ++ {0x00110054, 0x0018186D}, // same as jump_tbl idx 168 ++ {0x0011005C, 0x0018186D}, // same as jump_tbl idx 168 ++#else ++ {0x00110054, 0x00182A79}, // same as jump_tbl idx 168 ++ {0x0011005C, 0x00182A79}, // same as jump_tbl idx 168 ++ {0x001118D4, 0x00000011}, ++#endif ++}; ++ ++u32 patch_tbl_func_u02[][2] = ++{ ++ {0x00110054, 0x001814a5}, // same as jump_tbl idx 168 ++ {0x0011005C, 0x001814a5}, // same as jump_tbl idx 168 ++ {0x001109c0, 0x00181e3d}, ++ {0x00110bb4, 0x001824e1}, ++ {0x00110f08, 0x00182d25}, ++}; ++ ++ ++u32 patch_tbl_rf_func[][2] = ++{ ++ {0x00110bf0, 0x00180001}, ++}; ++ ++ ++//adap test ++u32 adaptivity_patch_tbl_8800dc[][2] = { ++ {0x000C, 0x0000320A}, //linkloss_thd ++ {0x009C, 0x00000000}, //ac_param_conf ++ {0x0128, 0xF6140001}, //tx_adaptivity_en ++}; ++//adap test ++ ++ ++static u8 chip_id = 0; ++#define CHIP_ID_H_MASK 0xC0 ++#define IS_CHIP_ID_H() ((chip_id & CHIP_ID_H_MASK) == CHIP_ID_H_MASK) ++ ++//Crystal provided by CPU (start) ++int set_bbpll_config(struct aic_sdio_dev *rwnx_hw){ ++// {0x40505010, 0x7C301010},//bbpll ++ int ret = 0; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ ++ //Read crystal provided by CPU or not. ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40500148, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x rd fail: %d\n", 0x40500148, ret); ++ return -1; ++ } ++ ++ AICWFDBG(LOGDEBUG, "%s rd_mem_addr_cfm.memdata:%x \r\n", __func__, rd_mem_addr_cfm.memdata); ++ ++ if(!(rd_mem_addr_cfm.memdata & 0x01)){ ++ AICWFDBG(LOGINFO, "%s Crystal not provided by CPU \r\n", __func__); ++ return 0; ++ }else{ ++ AICWFDBG(LOGINFO, "%s Crystal provided by CPU \r\n", __func__); ++ //Read 0x40505010 value to check bbpll set or not. ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40505010, &rd_mem_addr_cfm); ++ if(ret < 0){ ++ AICWFDBG(LOGERROR, "%s error ret_val:%d\r\n", __func__, ret); ++ return -1; ++ } ++ ++ if((rd_mem_addr_cfm.memdata >> 29) == 3){ ++ AICWFDBG(LOGERROR, "%s Not need to set \r\n", __func__); ++ return 0; ++ }else{ ++ rd_mem_addr_cfm.memdata |= ((0x1 << 29) | (0x1 << 30)); ++ rd_mem_addr_cfm.memdata &= (~(0x1 << 31)); ++ rwnx_send_dbg_mem_write_req(rwnx_hw, 0x40505010, rd_mem_addr_cfm.memdata); ++ } ++ } ++ return 0; ++} ++//Crystal provided by CPU (end) ++ ++ ++void system_config_8800dc(struct aic_sdio_dev *rwnx_hw) ++{ ++ int syscfg_num; ++ array3_tbl_t p_syscfg_msk_tbl; ++ int ret, cnt; ++ const u32 mem_addr = 0x40500000; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++#ifdef CONFIG_OOB ++ int oobcfg_num; ++#endif ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x rd fail: %d\n", mem_addr, ret); ++ return; ++ } ++ chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16); ++ //printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ if (((rd_mem_addr_cfm.memdata >> 25) & 0x01UL) == 0x00UL) { ++ chip_mcu_id = 1; ++ } ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x00000020, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x00000020] rd fail: %d\n", ret); ++ return; ++ } ++ chip_sub_id = (u8)(rd_mem_addr_cfm.memdata); ++ //printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ AICWFDBG(LOGINFO, "chip_id=%x, chip_sub_id=%x!!\n", chip_id, chip_sub_id); ++ ++ //Crystal provided by CPU (start) ++ ret = set_bbpll_config(rwnx_hw); ++ if (ret) { ++ AICWFDBG(LOGERROR, "set_bbpll_config fail: %d\n", ret); ++ return; ++ } ++ //Crystal provided by CPU (end) ++ ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40500010, &rd_mem_addr_cfm); ++ AICWFDBG(LOGDEBUG, "[0x40500010]=%x\n", rd_mem_addr_cfm.memdata); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x40500010] rd fail: %d\n", ret); ++ return; ++ } ++ ++ syscfg_num = sizeof(syscfg_tbl_8800dc) / sizeof(uint32_t) / 2; ++ ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc[cnt][0], syscfg_tbl_8800dc[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", syscfg_tbl_8800dc[cnt][0], ret); ++ return; ++ } ++ } ++ ++ if (chip_mcu_id == 0) { ++ if (chip_sub_id == 0) { ++ syscfg_num = sizeof(syscfg_tbl_8800dc_sdio_u01) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc_sdio_u01[cnt][0], syscfg_tbl_8800dc_sdio_u01[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", syscfg_tbl_8800dc_sdio_u01[cnt][0], ret); ++ return; ++ } ++ } ++ } else if ((chip_sub_id == 1) || (chip_sub_id == 2)) { ++ syscfg_num = sizeof(syscfg_tbl_8800dc_sdio_u02) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc_sdio_u02[cnt][0], syscfg_tbl_8800dc_sdio_u02[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", syscfg_tbl_8800dc_sdio_u02[cnt][0], ret); ++ return; ++ } ++ } ++ } ++ } ++#ifdef CONFIG_OOB ++ if ((chip_sub_id == 1) || (chip_sub_id == 2)) { ++ oobcfg_num = sizeof(oobcfg_tbl_8800dc_sdio_u02) / sizeof(u32) / 2; ++ for (cnt = 0; cnt < oobcfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, oobcfg_tbl_8800dc_sdio_u02[cnt][0], oobcfg_tbl_8800dc_sdio_u02[cnt][1]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x write fail: %d\n", oobcfg_tbl_8800dc_sdio_u02[cnt][0], ret); ++ return; ++ } ++ } ++ } ++#endif ++ if (IS_CHIP_ID_H()) { ++ syscfg_num = sizeof(syscfg_tbl_masked_8800dc_h) / sizeof(u32) / 3; ++ p_syscfg_msk_tbl = syscfg_tbl_masked_8800dc_h; ++ } else { ++ syscfg_num = sizeof(syscfg_tbl_masked_8800dc) / sizeof(u32) / 3; ++ p_syscfg_msk_tbl = syscfg_tbl_masked_8800dc; ++ } ++ ++ ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ if (p_syscfg_msk_tbl[cnt][0] == 0x00000000) { ++ break; ++ } else if (p_syscfg_msk_tbl[cnt][0] == 0x70001000) { ++ if (chip_mcu_id == 0) { ++ p_syscfg_msk_tbl[cnt][1] |= ((0x1 << 8) | (0x1 << 15)); // mask ++ p_syscfg_msk_tbl[cnt][2] |= ((0x1 << 8) | (0x1 << 15)); ++ } ++ } ++ ++ ret = rwnx_send_dbg_mem_mask_write_req(rwnx_hw, ++ p_syscfg_msk_tbl[cnt][0], p_syscfg_msk_tbl[cnt][1], p_syscfg_msk_tbl[cnt][2]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x mask write fail: %d\n", p_syscfg_msk_tbl[cnt][0], ret); ++ return; ++ } ++ } ++ ++ if (chip_sub_id == 0) { ++ syscfg_num = sizeof(syscfg_tbl_masked_8800dc_u01) / sizeof(u32) / 3; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_mask_write_req(rwnx_hw, ++ syscfg_tbl_masked_8800dc_u01[cnt][0], syscfg_tbl_masked_8800dc_u01[cnt][1], syscfg_tbl_masked_8800dc_u01[cnt][2]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "%x mask write fail: %d\n", syscfg_tbl_masked_8800dc_u01[cnt][0], ret); ++ return; ++ } ++ } ++ } ++ ++} ++ ++extern int adap_test; ++ ++void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw) ++{ ++ int ret = 0; ++ int cnt = 0; ++ if (testmode == 0) { ++ const u32 cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ int i; ++ u32 wifisetting_cfg_addr; ++ u32 ldpc_cfg_addr; ++ u32 agc_cfg_addr; ++ u32 txgain_cfg_addr; ++ u32 jump_tbl_addr = 0; ++ ++ u32 patch_tbl_wifisetting_num;// = sizeof(patch_tbl_wifisetting_8800dc_u02)/sizeof(u32)/2; ++ u32 ldpc_cfg_size = sizeof(ldpc_cfg_ram); ++ u32 agc_cfg_size = sizeof(agc_cfg_ram); ++ u32 txgain_cfg_size, *txgain_cfg_array; ++ u32 jump_tbl_size = 0; ++ u32 patch_tbl_func_num = 0; ++ ++ //adap test ++ int adap_patch_num = 0; ++ //adap test ++ ++ ++ array2_tbl_t jump_tbl_base = NULL; ++ array2_tbl_t patch_tbl_func_base = NULL; ++ array2_tbl_t patch_tbl_wifisetting_8800dc_base = NULL; ++ ++ if (chip_sub_id == 0) { ++ jump_tbl_base = jump_tbl; ++ jump_tbl_size = sizeof(jump_tbl)/2; ++ patch_tbl_func_base = patch_tbl_func; ++ patch_tbl_func_num = sizeof(patch_tbl_func)/sizeof(u32)/2; ++ patch_tbl_wifisetting_num = sizeof(patch_tbl_wifisetting_8800dc_u01)/sizeof(u32)/2; ++ patch_tbl_wifisetting_8800dc_base = patch_tbl_wifisetting_8800dc_u01; ++ } else if ((chip_sub_id == 1) || (chip_sub_id == 2)) { ++ patch_tbl_wifisetting_num = sizeof(patch_tbl_wifisetting_8800dc_u02)/sizeof(u32)/2; ++ patch_tbl_wifisetting_8800dc_base = patch_tbl_wifisetting_8800dc_u02; ++ } else { ++ printk("unsupported id: %d", chip_sub_id); ++ return; ++ } ++ ++ //struct dbg_mem_read_cfm cfm; ++ //int i; ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base, ret); ++ } ++ wifisetting_cfg_addr = cfm.memdata; ++ ++ if(chip_sub_id == 0){ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 4, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 4, ret); ++ } ++ jump_tbl_addr = cfm.memdata; ++ } ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 8, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 8, ret); ++ } ++ ldpc_cfg_addr = cfm.memdata; ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0xc, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 0xc, ret); ++ } ++ agc_cfg_addr = cfm.memdata; ++ ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x10, &cfm))) { ++ AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", cfg_base + 0x10, ret); ++ } ++ txgain_cfg_addr = cfm.memdata; ++ ++ AICWFDBG(LOGINFO, "wifisetting_cfg_addr=%x, ldpc_cfg_addr=%x, agc_cfg_addr=%x, txgain_cfg_addr=%x\n", wifisetting_cfg_addr, ldpc_cfg_addr, agc_cfg_addr, txgain_cfg_addr); ++ ++ for (cnt = 0; cnt < patch_tbl_wifisetting_num; cnt++) { ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, wifisetting_cfg_addr + patch_tbl_wifisetting_8800dc_base[cnt][0], patch_tbl_wifisetting_8800dc_base[cnt][1]))) { ++ AICWFDBG(LOGERROR, "wifisetting %x write fail\n", patch_tbl_wifisetting_8800dc_base[cnt][0]); ++ } ++ } ++ ++//adap test ++ if(adap_test){ ++ AICWFDBG(LOGINFO, "%s for adaptivity test \r\n", __func__); ++ adap_patch_num = sizeof(adaptivity_patch_tbl_8800dc)/sizeof(u32)/2; ++ for(cnt = 0; cnt < adap_patch_num; cnt++) ++ { ++ if((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, wifisetting_cfg_addr + adaptivity_patch_tbl_8800dc[cnt][0], adaptivity_patch_tbl_8800dc[cnt][1]))) { ++ AICWFDBG(LOGERROR, "%x write fail\n", wifisetting_cfg_addr + adaptivity_patch_tbl_8800dc[cnt][0]); ++ } ++ } ++ } ++//adap test ++ ++ if (ldpc_cfg_size > 512) {// > 0.5KB data ++ for (i = 0; i < (ldpc_cfg_size - 512); i += 512) {//each time write 0.5KB ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ldpc_cfg_addr + i, 512, ldpc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "ldpc upload fail: %x, err:%d\r\n", ldpc_cfg_addr + i, ret); ++ break; ++ } ++ } ++ } ++ ++ if (!ret && (i < ldpc_cfg_size)) {// < 0.5KB data ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ldpc_cfg_addr + i, ldpc_cfg_size - i, ldpc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "ldpc upload fail: %x, err:%d\r\n", ldpc_cfg_addr + i, ret); ++ } ++ } ++ ++ if (agc_cfg_size > 512) {// > 0.5KB data ++ for (i = 0; i < (agc_cfg_size - 512); i += 512) {//each time write 0.5KB ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, agc_cfg_addr + i, 512, agc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "agc upload fail: %x, err:%d\r\n", agc_cfg_addr + i, ret); ++ break; ++ } ++ } ++ } ++ ++ if (!ret && (i < agc_cfg_size)) {// < 0.5KB data ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, agc_cfg_addr + i, agc_cfg_size - i, agc_cfg_ram + i / 4); ++ if (ret) { ++ AICWFDBG(LOGERROR, "agc upload fail: %x, err:%d\r\n", agc_cfg_addr + i, ret); ++ } ++ } ++ ++ #if !defined(CONFIG_FPGA_VERIFICATION) ++ if ((IS_CHIP_ID_H())) { ++ #if defined(CONFIG_EXT_FEM_8800DCDW) ++ txgain_cfg_size = sizeof(txgain_map_femkct_h); ++ txgain_cfg_array = (u32 *)txgain_map_femkct_h; ++ #else ++ txgain_cfg_size = sizeof(txgain_map_h); ++ txgain_cfg_array = (u32 *)txgain_map_h; ++ #endif ++ } else { ++ #if defined(CONFIG_EXT_FEM_8800DCDW) ++ txgain_cfg_size = sizeof(txgain_map_femkct); ++ txgain_cfg_array = (u32 *)txgain_map_femkct; ++ #else ++ txgain_cfg_size = sizeof(txgain_map); ++ txgain_cfg_array = (u32 *)txgain_map; ++ #endif ++ } ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, txgain_cfg_addr, txgain_cfg_size, txgain_cfg_array); ++ if (ret) { ++ AICWFDBG(LOGERROR, "txgain upload fail: %x, err:%d\r\n", txgain_cfg_addr, ret); ++ } ++ ++ if (chip_sub_id == 0) { ++ for (cnt = 0; cnt < jump_tbl_size/4; cnt+=1) { ++ AICWFDBG(LOGDEBUG, "%x = %x\n", jump_tbl_base[cnt][0]*4+jump_tbl_addr, jump_tbl_base[cnt][1]); ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, jump_tbl_base[cnt][0]*4+jump_tbl_addr, jump_tbl_base[cnt][1]))) { ++ AICWFDBG(LOGERROR, "%x write fail\n", jump_tbl_addr+8*cnt); ++ } ++ } ++ for (cnt = 0; cnt < patch_tbl_func_num; cnt++) { ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, patch_tbl_func_base[cnt][0], patch_tbl_func_base[cnt][1]))) { ++ AICWFDBG(LOGERROR, "patch_tbl_func %x write fail\n", patch_tbl_func_base[cnt][0]); ++ } ++ } ++ } else if (chip_sub_id == 1) { ++ ret = aicwf_patch_table_load(rwnx_hw, RWNX_MAC_PATCH_TABLE_8800DC_U02); ++ if(ret){ ++ printk("patch_tbl upload fail: err:%d\r\n", ret); ++ } ++ } else if (chip_sub_id == 2) { ++ ret = aicwf_patch_table_load(rwnx_hw, RWNX_MAC_PATCH_TABLE_8800DC_H_U02); ++ if(ret){ ++ printk("patch_tbl upload fail: err:%d\r\n", ret); ++ } ++ } else { ++ printk("unsupported id: %d\n", chip_sub_id); ++ } ++ ++ #endif ++ } else { ++ if (chip_sub_id == 0) { ++ u32 patch_tbl_rf_func_num = sizeof(patch_tbl_rf_func)/sizeof(u32)/2; ++ for (cnt = 0; cnt < patch_tbl_rf_func_num; cnt++) { ++ if ((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, patch_tbl_rf_func[cnt][0], patch_tbl_rf_func[cnt][1]))) { ++ AICWFDBG(LOGERROR, "patch_tbl_rf_func %x write fail\n", patch_tbl_rf_func[cnt][0]); ++ } ++ } ++ } ++ } ++} ++ ++int aicwf_misc_ram_init_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t misc_ram_size = 12; ++ int i; ++ ++ if (testmode == FW_RFTEST_MODE) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ // init misc ram ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr); ++ for (i = 0; i < (misc_ram_size / 4); i++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, misc_ram_addr + i * 4, 0); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] wr fail: %d\n", misc_ram_addr + i * 4, ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++ ++#ifdef CONFIG_DPD ++int aicwf_dpd_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ uint32_t fw_addr, boot_type; ++ int valid_flag; ++ ++ printk("%s\n", __func__); ++ ++ ret = aicwf_misc_ram_valid_check_8800dc(sdiodev, &valid_flag); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram check fail: %d\n", ret); ++ return ret; ++ } ++ if (valid_flag) { ++ AICWFDBG(LOGINFO, "misc ram valid, skip calib process\n"); ++ return ret; ++ } ++ ret = aicwf_plat_calib_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ /* fw start */ ++ fw_addr = 0x00130009; ++ boot_type = HOST_START_APP_FNCALL; ++ AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); ++ ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type, NULL); ++ if (ret) { ++ AICWFDBG(LOGINFO, "start app fail: %d\n", ret); ++ return ret; ++ } ++ { // read dpd res ++ const uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_word_cnt; ++ int i; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ // bit_mask ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ dpd_res->bit_mask[i] = cfm.memdata; ++ } ++ // dpd_high ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, dpd_high); ++ ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, dpd_high) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ dpd_res->dpd_high[i] = cfm.memdata; ++ } ++ // loft_res ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ dpd_res->loft_res[i] = cfm.memdata; ++ } ++ } ++ return ret; ++} ++ ++int aicwf_dpd_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", dpd_res->bit_mask[1]); ++ if (dpd_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void dpd_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == FW_RFTEST_MODE) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy dpd_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", dpd_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // dpd_high ++ AICWFDBG(LOGINFO, "dpd_high[0]=%x\n", dpd_res->dpd_high[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, dpd_high); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, dpd_high); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->dpd_high[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "dpd_high wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", dpd_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++ ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_DPDRESULT_NAME_8800DC; ++ struct device *dev = sdiodev->dev; ++ AICWFDBG(LOGINFO, "%s: dpd_res file path:%s \r\n", __func__, filename); ++ /* load file */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of dpd_res file\n"); ++ if (dst) { ++ #ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++ #endif ++ dst = NULL; ++ } ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d, dst[0]=%x\n", filename, size, dst[0]); ++ memcpy((u8 *)dpd_res, (u8 *)dst, sizeof(rf_misc_ram_lite_t)); ++ if (dst) { ++ #ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++ #endif ++ dst = NULL; ++ } ++ return ret; ++} ++ ++int aicwf_dpd_result_write_8800dc(void *buf, int buf_len) ++{ ++ int sum = 0, len = 0; ++ char *path = NULL; ++ struct file *fp = NULL; ++ loff_t pos = 0; ++ mm_segment_t fs; ++ ++ AICWFDBG(LOGINFO, "%s\n", __func__); ++ ++ path = __getname(); ++ if (!path) { ++ AICWFDBG(LOGINFO, "get path fail\n"); ++ return -1; ++ } ++ ++ len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", AICBSP_FW_PATH, FW_DPDRESULT_NAME_8800DC); ++ printk("%s\n", path); ++ ++ fp = filp_open(path, O_RDWR | O_CREAT, 0644); ++ if (IS_ERR(fp)) { ++ AICWFDBG(LOGINFO, "fp open fial\n"); ++ __putname(path); ++ fp = NULL; ++ return -1; ++ } ++ ++ fs = get_fs(); ++ set_fs(KERNEL_DS); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ sum = kernel_write(fp, buf, buf_len, &pos); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) ++ sum = kernel_write(fp, (char *)buf, buf_len, pos); ++#else ++ sum = vfs_write(fp, (char *)buf, buf_len, &pos); ++#endif ++ ++ set_fs(fs); ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ ++ return 0; ++} ++#endif /* !CONFIG_FORCE_DPD_CALIB */ ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++int aicwf_loft_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res) ++{ ++ int ret = 0; ++ uint32_t fw_addr, boot_type; ++ int valid_flag; ++ ++ printk("%s\n", __func__); ++ ++ ret = aicwf_misc_ram_valid_check_8800dc(sdiodev, &valid_flag); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram check fail: %d\n", ret); ++ return ret; ++ } ++ if (valid_flag) { ++ AICWFDBG(LOGINFO, "misc ram valid, skip calib process\n"); ++ return ret; ++ } ++ ret = aicwf_plat_calib_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ /* fw start */ ++ fw_addr = 0x00130009; ++ boot_type = HOST_START_APP_FNCALL; ++ AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); ++ ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type, NULL); ++ if (ret) { ++ AICWFDBG(LOGINFO, "start app fail: %d\n", ret); ++ return ret; ++ } ++ { // read loft res ++ const uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_word_cnt; ++ int i; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ // bit_mask ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ loft_res->bit_mask[i] = cfm.memdata; ++ } ++ // loft_res ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ loft_res->loft_res[i] = cfm.memdata; ++ } ++ } ++ return ret; ++} ++ ++int aicwf_loft_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", loft_res->bit_mask[1]); ++ if (loft_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void loft_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == FW_RFTEST_MODE) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy loft_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", loft_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", loft_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h +new file mode 100644 +index 000000000000..23b8185761eb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h +@@ -0,0 +1,41 @@ ++#ifndef _AIC8800DC_COMPAT_H_ ++#define _AIC8800DC_COMPAT_H_ ++ ++#include "aicsdio.h" ++typedef u32 (*array2_tbl_t)[2]; ++typedef u32 (*array3_tbl_t)[3]; ++ ++typedef uint8_t u8_l; ++typedef int8_t s8_l; ++typedef bool bool_l; ++typedef uint16_t u16_l; ++typedef int16_t s16_l; ++typedef uint32_t u32_l; ++typedef int32_t s32_l; ++typedef uint64_t u64_l; ++ ++extern u8 chip_sub_id; ++extern u8 chip_mcu_id; ++#define FW_PATH_MAX_LEN 200 ++ ++void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw); ++void system_config_8800dc(struct aic_sdio_dev *rwnx_hw); ++int aicwf_misc_ram_init_8800dc(struct aic_sdio_dev *sdiodev); ++ ++#ifdef CONFIG_DPD ++int aicwf_dpd_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res); ++int aicwf_dpd_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res); ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *dpd_res); ++int aicwf_dpd_result_write_8800dc(void *buf, int buf_len); ++#endif/* !CONFIG_FORCE_DPD_CALIB */ ++#endif ++#ifdef CONFIG_LOFT_CALIB ++int aicwf_loft_calib_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res); ++int aicwf_loft_result_apply_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_t *loft_res); ++#endif ++ ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c +new file mode 100644 +index 000000000000..658979c535a2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c +@@ -0,0 +1,2214 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.c ++ * ++ * Handles queueing (push to IPC, ack/cfm from IPC) of commands issued to ++ * LMAC FW ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) ++#include ++#endif ++#include ++#include "aicsdio_txrxif.h" ++#include "aicsdio.h" ++#include "aic_bsp_driver.h" ++#include "md5.h" ++#include "aic8800dc_compat.h" ++#include "aic8800d80_compat.h" ++#include "aicwf_firmware_array.h" ++#define FW_PATH_MAX 200 ++ ++extern int adap_test; ++extern char aic_fw_path[FW_PATH_MAX]; ++extern struct aic_sdio_dev *aicbsp_sdiodev; ++ ++static void cmd_dump(const struct rwnx_cmd *cmd) ++{ ++ printk(KERN_CRIT "tkn[%d] flags:%04x result:%3d cmd:%4d - reqcfm(%4d)\n", ++ cmd->tkn, cmd->flags, cmd->result, cmd->id, cmd->reqid); ++} ++ ++static void cmd_complete(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ //printk("cmdcmp\n"); ++ lockdep_assert_held(&cmd_mgr->lock); ++ ++ list_del(&cmd->list); ++ cmd_mgr->queue_sz--; ++ ++ cmd->flags |= RWNX_CMD_FLAG_DONE; ++ if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) { ++ kfree(cmd); ++ } else { ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) { ++ cmd->result = 0; ++ complete(&cmd->complete); ++ } ++ } ++} ++ ++static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ bool defer_push = false; ++ int err = 0; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ ++ if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { ++ printk(KERN_CRIT"cmd queue crashed\n"); ++ cmd->result = -EPIPE; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EPIPE; ++ } ++ ++ if (!list_empty(&cmd_mgr->cmds)) { ++ struct rwnx_cmd *last; ++ ++ if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) { ++ printk(KERN_CRIT"Too many cmds (%d) already queued\n", ++ cmd_mgr->max_queue_sz); ++ cmd->result = -ENOMEM; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -ENOMEM; ++ } ++ last = list_entry(cmd_mgr->cmds.prev, struct rwnx_cmd, list); ++ if (last->flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_PUSH)) { ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ defer_push = true; ++ } ++ } ++ ++ if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM) ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM; ++ ++ cmd->tkn = cmd_mgr->next_tkn++; ++ cmd->result = -EINTR; ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ init_completion(&cmd->complete); ++ ++ list_add_tail(&cmd->list, &cmd_mgr->cmds); ++ cmd_mgr->queue_sz++; ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ if (!defer_push) { ++ //printk("queue:id=%x, param_len=%u\n", cmd->a2e_msg->id, cmd->a2e_msg->param_len); ++ rwnx_set_cmd_tx((void *)(cmd_mgr->sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ //rwnx_ipc_msg_push(rwnx_hw, cmd, RWNX_CMD_A2EMSG_LEN(cmd->a2e_msg)); ++ kfree(cmd->a2e_msg); ++ } else { ++ //WAKE_CMD_WORK(cmd_mgr); ++ printk("ERR: never defer push!!!!"); ++ return 0; ++ } ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) { ++ unsigned long tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz); ++ if (!wait_for_completion_killable_timeout(&cmd->complete, tout)) { ++ printk(KERN_CRIT"cmd timed-out\n"); ++ cmd_dump(cmd); ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED; ++ if (!(cmd->flags & RWNX_CMD_FLAG_DONE)) { ++ cmd->result = -ETIMEDOUT; ++ cmd_complete(cmd_mgr, cmd); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ err = -ETIMEDOUT; ++ } else { ++ kfree(cmd); ++ } ++ } else { ++ cmd->result = 0; ++ } ++ ++ return err; ++} ++ ++static int cmd_mgr_run_callback(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd, ++ struct rwnx_cmd_e2amsg *msg, msg_cb_fct cb) ++{ ++ int res; ++ ++ if (!cb) { ++ return 0; ++ } ++ spin_lock(&cmd_mgr->cb_lock); ++ res = cb(cmd, msg); ++ spin_unlock(&cmd_mgr->cb_lock); ++ ++ return res; ++} ++ ++static int cmd_mgr_msgind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd_e2amsg *msg, ++ msg_cb_fct cb) ++{ ++ struct rwnx_cmd *cmd; ++ bool found = false; ++ ++ //printk("cmd->id=%x\n", msg->id); ++ spin_lock(&cmd_mgr->lock); ++ list_for_each_entry(cmd, &cmd_mgr->cmds, list) { ++ if (cmd->reqid == msg->id && ++ (cmd->flags & RWNX_CMD_FLAG_WAIT_CFM)) { ++ ++ if (!cmd_mgr_run_callback(cmd_mgr, cmd, msg, cb)) { ++ found = true; ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_CFM; ++ ++ if (WARN((msg->param_len > RWNX_CMD_E2AMSG_LEN_MAX), ++ "Unexpect E2A msg len %d > %d\n", msg->param_len, ++ RWNX_CMD_E2AMSG_LEN_MAX)) { ++ msg->param_len = RWNX_CMD_E2AMSG_LEN_MAX; ++ } ++ ++ if (cmd->e2a_msg && msg->param_len) ++ memcpy(cmd->e2a_msg, &msg->param, msg->param_len); ++ ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) ++ cmd_complete(cmd_mgr, cmd); ++ ++ break; ++ } ++ } ++ } ++ spin_unlock(&cmd_mgr->lock); ++ ++ if (!found) ++ cmd_mgr_run_callback(cmd_mgr, NULL, msg, cb); ++ ++ return 0; ++} ++ ++static void cmd_mgr_print(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ cmd_dump(cur); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++static void cmd_mgr_drain(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur, *nxt; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry_safe(cur, nxt, &cmd_mgr->cmds, list) { ++ list_del(&cur->list); ++ cmd_mgr->queue_sz--; ++ if (!(cur->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ complete(&cur->complete); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ cmd_mgr->max_queue_sz = RWNX_CMD_MAX_QUEUED; ++ INIT_LIST_HEAD(&cmd_mgr->cmds); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_INITED; ++ spin_lock_init(&cmd_mgr->lock); ++ spin_lock_init(&cmd_mgr->cb_lock); ++ cmd_mgr->queue = &cmd_mgr_queue; ++ cmd_mgr->print = &cmd_mgr_print; ++ cmd_mgr->drain = &cmd_mgr_drain; ++ cmd_mgr->llind = NULL;//&cmd_mgr_llind; ++ cmd_mgr->msgind = &cmd_mgr_msgind; ++ ++#if 0 ++ INIT_WORK(&cmd_mgr->cmdWork, cmd_mgr_task_process); ++ cmd_mgr->cmd_wq = create_singlethread_workqueue("cmd_wq"); ++ if (!cmd_mgr->cmd_wq) { ++ txrx_err("insufficient memory to create cmd workqueue.\n"); ++ return; ++ } ++#endif ++} ++ ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ if(cmd_mgr->print) ++ cmd_mgr->print(cmd_mgr); ++ if(cmd_mgr->drain) ++ cmd_mgr->drain(cmd_mgr); ++ if(cmd_mgr->print) ++ cmd_mgr->print(cmd_mgr); ++ memset(cmd_mgr, 0, sizeof(*cmd_mgr)); ++} ++ ++void rwnx_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ struct aicwf_bus *bus = sdiodev->bus_if; ++ u8 *buffer = bus->cmd_buf; ++ u16 index = 0; ++ ++ memset(buffer, 0, CMD_BUF_MAX); ++ buffer[0] = (len+4) & 0x00ff; ++ buffer[1] = ((len+4) >> 8) &0x0f; ++ buffer[2] = 0x11; ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ buffer[3] = 0x0; ++ else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ buffer[3] = crc8_ponl_107(&buffer[0], 3); // crc8 ++ index += 4; ++ //there is a dummy word ++ index += 4; ++ ++ //make sure little endian ++ put_u16(&buffer[index], msg->id); ++ index += 2; ++ put_u16(&buffer[index], msg->dest_id); ++ index += 2; ++ put_u16(&buffer[index], msg->src_id); ++ index += 2; ++ put_u16(&buffer[index], msg->param_len); ++ index += 2; ++ memcpy(&buffer[index], (u8 *)msg->param, msg->param_len); ++ ++ aicwf_bus_txmsg(bus, buffer, len + 8); ++} ++ ++static inline void *rwnx_msg_zalloc(lmac_msg_id_t const id, ++ lmac_task_id_t const dest_id, ++ lmac_task_id_t const src_id, ++ uint16_t const param_len) ++{ ++ struct lmac_msg *msg; ++ gfp_t flags; ++ ++ if (in_softirq()) ++ flags = GFP_ATOMIC; ++ else ++ flags = GFP_KERNEL; ++ ++ msg = (struct lmac_msg *)kzalloc(sizeof(struct lmac_msg) + param_len, ++ flags); ++ if (msg == NULL) { ++ printk(KERN_CRIT "%s: msg allocation failed\n", __func__); ++ return NULL; ++ } ++ msg->id = id; ++ msg->dest_id = dest_id; ++ msg->src_id = src_id; ++ msg->param_len = param_len; ++ ++ return msg->param; ++} ++ ++static void rwnx_msg_free(struct lmac_msg *msg, const void *msg_params) ++{ ++ kfree(msg); ++} ++ ++ ++static int rwnx_send_msg(struct aic_sdio_dev *sdiodev, const void *msg_params, ++ int reqcfm, lmac_msg_id_t reqid, void *cfm) ++{ ++ struct lmac_msg *msg; ++ struct rwnx_cmd *cmd; ++ bool nonblock; ++ int ret = 0; ++ ++ msg = container_of((void *)msg_params, struct lmac_msg, param); ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ rwnx_msg_free(msg, msg_params); ++ printk("bus is down\n"); ++ return 0; ++ } ++ ++ nonblock = 0; ++ cmd = kzalloc(sizeof(struct rwnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL); ++ cmd->result = -EINTR; ++ cmd->id = msg->id; ++ cmd->reqid = reqid; ++ cmd->a2e_msg = msg; ++ cmd->e2a_msg = cfm; ++ if (nonblock) ++ cmd->flags = RWNX_CMD_FLAG_NONBLOCK; ++ if (reqcfm) ++ cmd->flags |= RWNX_CMD_FLAG_REQ_CFM; ++ ++ if (reqcfm) { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; // we don't need ack any more ++ ret = sdiodev->cmd_mgr.queue(&sdiodev->cmd_mgr, cmd); ++ } else { ++ rwnx_set_cmd_tx((void *)(sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ } ++ ++ if (!reqcfm) ++ kfree(cmd); ++ ++ return ret; ++} ++ ++ ++int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_size, u32 *mem_data) ++{ ++ struct dbg_mem_block_write_req *mem_blk_write_req; ++ ++ /* Build the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req = rwnx_msg_zalloc(DBG_MEM_BLOCK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_block_write_req)); ++ if (!mem_blk_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req->memaddr = mem_addr; ++ mem_blk_write_req->memsize = mem_size; ++ memcpy(mem_blk_write_req->memdata, mem_data, mem_size); ++ ++ /* Send the DBG_MEM_BLOCK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_blk_write_req, 1, DBG_MEM_BLOCK_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm) ++{ ++ struct dbg_mem_read_req *mem_read_req; ++ ++ /* Build the DBG_MEM_READ_REQ message */ ++ mem_read_req = rwnx_msg_zalloc(DBG_MEM_READ_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_read_req)); ++ if (!mem_read_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_READ_REQ message */ ++ mem_read_req->memaddr = mem_addr; ++ ++ /* Send the DBG_MEM_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_read_req, 1, DBG_MEM_READ_CFM, cfm); ++} ++ ++ ++int rwnx_send_dbg_mem_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_data) ++{ ++ struct dbg_mem_write_req *mem_write_req; ++ ++ /* Build the DBG_MEM_WRITE_REQ message */ ++ mem_write_req = rwnx_msg_zalloc(DBG_MEM_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_write_req)); ++ if (!mem_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_WRITE_REQ message */ ++ mem_write_req->memaddr = mem_addr; ++ mem_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_write_req, 1, DBG_MEM_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_mask_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_mask, u32 mem_data) ++{ ++ struct dbg_mem_mask_write_req *mem_mask_write_req; ++ ++ /* Build the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req = rwnx_msg_zalloc(DBG_MEM_MASK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_mask_write_req)); ++ if (!mem_mask_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req->memaddr = mem_addr; ++ mem_mask_write_req->memmask = mem_mask; ++ mem_mask_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_MASK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, mem_mask_write_req, 1, DBG_MEM_MASK_WRITE_CFM, NULL); ++} ++ ++ ++int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm) ++{ ++ struct dbg_start_app_req *start_app_req; ++ ++ /* Build the DBG_START_APP_REQ message */ ++ start_app_req = rwnx_msg_zalloc(DBG_START_APP_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_start_app_req)); ++ if (!start_app_req) { ++ printk("start app nomen\n"); ++ return -ENOMEM; ++ } ++ ++ /* Set parameters for the DBG_START_APP_REQ message */ ++ start_app_req->bootaddr = boot_addr; ++ start_app_req->boottype = boot_type; ++ ++ /* Send the DBG_START_APP_REQ message to LMAC FW */ ++ return rwnx_send_msg(sdiodev, start_app_req, 1, DBG_START_APP_CFM, start_app_cfm); ++} ++ ++static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = { ++}; ++ ++static msg_cb_fct *msg_hdlrs[] = { ++ [TASK_DBG] = dbg_hdlrs, ++}; ++ ++void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg) ++{ ++ sdiodev->cmd_mgr.msgind(&sdiodev->cmd_mgr, msg, ++ msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) ++MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver"); ++#else ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#endif ++#endif ++ ++#define MD5(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] ++#define MD5PINRT "file md5:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\r\n" ++ ++int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device) ++{ ++ ++#ifdef CONFIG_USE_FW_REQUEST ++ const struct firmware *fw = NULL; ++ u32 *dst = NULL; ++ void *buffer=NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ int size = 0; ++ int ret = 0; ++ ++ printk("%s: request firmware = %s \n", __func__ ,name); ++ ++ ++ ret = request_firmware(&fw, name, NULL); ++ ++ if (ret < 0) { ++ printk("Load %s fail\n", name); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ size = fw->size; ++ dst = (u32 *)fw->data; ++ ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ memcpy(buffer, dst, size); ++ ++ *fw_buf = buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ release_firmware(fw); ++ ++ return size; ++#else ++ void *buffer = NULL; ++ char *path = NULL; ++ struct file *fp = NULL; ++ int size = 0, len = 0;// i = 0; ++ ssize_t rdlen = 0; ++ //u32 *src = NULL, *dst = NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ ++ #ifdef CONFIG_FIRMWARE_ARRAY ++ size = aicwf_get_firmware_array((char*)name, fw_buf); ++ printk("%s size:%d \r\n", __func__, size); ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)*fw_buf, size); ++ MD5Final(&md5, decrypt); ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ return size; ++ #endif ++ ++ /* get the firmware path */ ++ path = __getname(); ++ if (!path) { ++ *fw_buf = NULL; ++ return -1; ++ } ++ ++ if(strlen(aic_fw_path) > 0){ ++ len = snprintf(path, AICBSP_FW_PATH_MAX, "%s/%s", aic_fw_path, name); ++ }else{ ++ len = snprintf(path, AICBSP_FW_PATH_MAX, "%s/%s", AICBSP_FW_PATH, name); ++ } ++ if (len >= AICBSP_FW_PATH_MAX) { ++ printk("%s: %s file's path too long\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ return -1; ++ } ++ ++ printk("%s :firmware path = %s \n", __func__, path); ++ ++ /* open the firmware file */ ++ fp = filp_open(path, O_RDONLY, 0); ++ if (IS_ERR_OR_NULL(fp)) { ++ printk("%s: %s file failed to open\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ fp = NULL; ++ return -1; ++ } ++ ++ size = i_size_read(file_inode(fp)); ++ if (size <= 0) { ++ printk("%s: %s file size invalid %d\n", __func__, name, size); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ } ++ ++ /* start to read from firmware file */ ++ buffer = vmalloc(size); ++ ++ if (!buffer) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ }else{ ++ memset(buffer, 0, size); ++ } ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) ++ rdlen = kernel_read(fp, buffer, size, &fp->f_pos); ++#else ++ rdlen = kernel_read(fp, fp->f_pos, buffer, size); ++#endif ++ ++ if (size != rdlen) { ++ printk("%s: %s file rdlen invalid %ld\n", __func__, name, (long int)rdlen); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ vfree(buffer); ++ buffer = NULL; ++ return -1; ++ } ++ if (rdlen > 0) { ++ fp->f_pos += rdlen; ++ } ++ ++#if 0 ++ /*start to transform the data format*/ ++ src = (u32 *)buffer; ++ dst = (u32 *)vmalloc(size); ++ ++ if (!dst) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ vfree(buffer); ++ buffer = NULL; ++ return -1; ++ }else{ ++ memset(dst, 0, size); ++ } ++ ++ for (i = 0; i < (size/4); i++) { ++ dst[i] = src[i]; ++ } ++#endif ++ ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ //vfree(buffer); ++ //buffer = NULL; ++ *fw_buf = (u32*)buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ return size; ++#endif ++} ++ ++extern int testmode; ++ ++#ifdef CONFIG_M2D_OTA_AUTO_SUPPORT ++extern char saved_sdk_ver[64]; ++ ++int rwnx_plat_m2d_flash_ota_android(struct aic_sdio_dev *sdiodev, char *filename) ++{ ++ struct device *dev = sdiodev->dev; ++ unsigned int i=0; ++ int size; ++ u32 *dst=NULL; ++ int err=0; ++ int ret; ++ u8 bond_id; ++ const u32 mem_addr = 0x40500000; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm); ++ if (ret) { ++ printk("m2d %x rd fail: %d\n", mem_addr, ret); ++ return ret; ++ } ++ bond_id = (u8)(rd_mem_addr_cfm.memdata >> 24); ++ printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ if (bond_id & (1<<1)) { ++ //flash is invalid ++ printk("m2d flash is invalid\n"); ++ return -1; ++ } ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if(size<=0){ ++ printk("wrong size of m2d file\n"); ++ vfree(dst); ++ dst = NULL; ++ return -1; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload m2d %s flash, size=%d\n", filename, size); ++ ++ /*send info first*/ ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_INFO_ADDR, 4, (u32 *)&size); ++ ++ /*send data first*/ ++ if (size > 1024) {// > 1KB data ++ for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, 1024, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ break; ++ } ++ } ++ } ++ ++ if (!err && (i < size)) {// <1KB data ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, size - i, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ } ++ } ++ ++ if (dst) { ++ vfree(dst); ++ dst = NULL; ++ } ++ testmode = FW_NORMAL_MODE; ++ aicbsp_info.cpmode = testmode; ++ ++ printk("m2d flash update complete\n\n"); ++ ++ return err; ++} ++ ++int rwnx_plat_m2d_flash_ota_check(struct aic_sdio_dev *sdiodev, char *filename) ++{ ++ struct device *dev = sdiodev->dev; ++ unsigned int i=0,j=0; ++ int size; ++ u32 *dst=NULL; ++ int err=0; ++ int ret=0; ++ u8 bond_id; ++ const u32 mem_addr = 0x40500000; ++ const u32 mem_addr_code_start = AIC_M2D_OTA_CODE_START_ADDR; ++ const u32 mem_addr_sdk_ver = AIC_M2D_OTA_VER_ADDR; ++ const u32 driver_code_start_idx = (AIC_M2D_OTA_CODE_START_ADDR-AIC_M2D_OTA_FLASH_ADDR)/4; ++ const u32 driver_sdk_ver_idx = (AIC_M2D_OTA_VER_ADDR-AIC_M2D_OTA_FLASH_ADDR)/4; ++ u32 driver_sdk_ver_addr_idx = 0; ++ u32 code_start_addr = 0xffffffff; ++ u32 sdk_ver_addr = 0xffffffff; ++ u32 drv_code_start_addr = 0xffffffff; ++ u32 drv_sdk_ver_addr = 0xffffffff; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ char m2d_sdk_ver[64]; ++ char flash_sdk_ver[64]; ++ u32 flash_ver[16]; ++ u32 ota_ver[16]; ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm); ++ if (ret) { ++ printk("m2d %x rd fail: %d\n", mem_addr, ret); ++ return ret; ++ } ++ bond_id = (u8)(rd_mem_addr_cfm.memdata >> 24); ++ printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); ++ if (bond_id & (1<<1)) { ++ //flash is invalid ++ printk("m2d flash is invalid\n"); ++ return -1; ++ } ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr_code_start, &rd_mem_addr_cfm); ++ if (ret){ ++ printk("mem_addr_code_start %x rd fail: %d\n", mem_addr_code_start, ret); ++ return ret; ++ } ++ code_start_addr = rd_mem_addr_cfm.memdata; ++ ++ #if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, mem_addr_sdk_ver, &rd_mem_addr_cfm); ++ if (ret){ ++ printk("mem_addr_sdk_ver %x rd fail: %d\n", mem_addr_code_start, ret); ++ return ret; ++ } ++ sdk_ver_addr = rd_mem_addr_cfm.memdata; ++ #else ++ sdk_ver_addr = mem_addr_sdk_ver; ++ #endif ++ printk("code_start_addr: 0x%x, sdk_ver_addr: 0x%x\n", code_start_addr,sdk_ver_addr); ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if(size<=0){ ++ printk("wrong size of m2d file\n"); ++ vfree(dst); ++ dst = NULL; ++ return -1; ++ } ++ if(code_start_addr == 0xffffffff && sdk_ver_addr == 0xffffffff) { ++ printk("########m2d flash old version , must be upgrade\n"); ++ drv_code_start_addr = dst[driver_code_start_idx]; ++ drv_sdk_ver_addr = dst[driver_sdk_ver_idx]; ++ ++ printk("drv_code_start_addr: 0x%x, drv_sdk_ver_addr: 0x%x\n", drv_code_start_addr,drv_sdk_ver_addr); ++ ++ if(drv_sdk_ver_addr == 0xffffffff){ ++ printk("########driver m2d_ota.bin is old ,not need upgrade\n"); ++ return -1; ++ } ++ ++ } else { ++ for(i=0;i<16;i++){ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, (sdk_ver_addr+i*4), &rd_mem_addr_cfm); ++ if (ret){ ++ printk("mem_addr_sdk_ver %x rd fail: %d\n", mem_addr_code_start, ret); ++ return ret; ++ } ++ flash_ver[i] = rd_mem_addr_cfm.memdata; ++ } ++ memcpy((u8 *)flash_sdk_ver,(u8 *)flash_ver,64); ++ memcpy((u8 *)saved_sdk_ver,(u8 *)flash_sdk_ver,64); ++ printk("flash SDK Version: %s\r\n\r\n", flash_sdk_ver); ++ ++ drv_code_start_addr = dst[driver_code_start_idx]; ++ drv_sdk_ver_addr = dst[driver_sdk_ver_idx]; ++ ++ printk("drv_code_start_addr: 0x%x, drv_sdk_ver_addr: 0x%x\n", drv_code_start_addr,drv_sdk_ver_addr); ++ ++ if(drv_sdk_ver_addr == 0xffffffff){ ++ printk("########driver m2d_ota.bin is old ,not need upgrade\n"); ++ return -1; ++ } ++ ++ #if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++ driver_sdk_ver_addr_idx = (drv_sdk_ver_addr-drv_code_start_addr)/4; ++ #else ++ driver_sdk_ver_addr_idx = driver_sdk_ver_idx; ++ #endif ++ printk("driver_sdk_ver_addr_idx %d\n",driver_sdk_ver_addr_idx); ++ ++ if (driver_sdk_ver_addr_idx){ ++ for(j = 0; j < 16; j++){ ++ ota_ver[j] = dst[driver_sdk_ver_addr_idx+j]; ++ } ++ memcpy((u8 *)m2d_sdk_ver,(u8 *)ota_ver,64); ++ printk("m2d_ota SDK Version: %s\r\n\r\n", m2d_sdk_ver); ++ } else { ++ return -1; ++ } ++ ++ if(!strcmp(m2d_sdk_ver,flash_sdk_ver)){ ++ printk("######## m2d %s flash is not need upgrade\r\n", filename); ++ return -1; ++ } ++ } ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload m2d %s flash, size=%d\n", filename, size); ++ ++ /*send info first*/ ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_INFO_ADDR, 4, (u32 *)&size); ++ ++ /*send data first*/ ++ if (size > 1024) {// > 1KB data ++ for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, 1024, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ break; ++ } ++ } ++ } ++ ++ if (!err && (i < size)) {// <1KB data ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, AIC_M2D_OTA_DATA_ADDR, size - i, dst + i / 4); ++ if (err) { ++ printk("m2d upload fail: %x, err:%d\r\n", AIC_M2D_OTA_DATA_ADDR, err); ++ } ++ } ++ ++ if (dst) { ++ vfree(dst); ++ dst = NULL; ++ } ++ testmode = FW_NORMAL_MODE; ++ ++ printk("m2d flash update complete\n\n"); ++ ++ return err; ++} ++#endif//CONFIG_M2D_OTA_AUTO_SUPPORT ++ ++int aicwf_patch_table_load(struct aic_sdio_dev *rwnx_hw, char *filename) ++{ ++ struct device *dev = rwnx_hw->dev; ++ int err = 0; ++ unsigned int i = 0, size; ++ u32 *dst = NULL; ++ u8 *describle; ++ u32 fmacfw_patch_tbl_8800dc_u02_describe_size = 124; ++ u32 fmacfw_patch_tbl_8800dc_u02_describe_base;//read from patch_tbl ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload %s \n", filename); ++ ++ size = rwnx_load_firmware(&dst, filename,dev); ++ if (!dst) { ++ printk("No such file or directory\n"); ++ return -1; ++ } ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ dst = NULL; ++ err = -1; ++ } ++ ++ printk("tbl size = %d \n",size); ++ ++ fmacfw_patch_tbl_8800dc_u02_describe_base = dst[0]; ++ AICWFDBG(LOGINFO, "FMACFW_PATCH_TBL_8800DC_U02_DESCRIBE_BASE = %x \n",fmacfw_patch_tbl_8800dc_u02_describe_base); ++ ++ if (!err && (i < size)) { ++ err=rwnx_send_dbg_mem_block_write_req(rwnx_hw, fmacfw_patch_tbl_8800dc_u02_describe_base, fmacfw_patch_tbl_8800dc_u02_describe_size + 4, dst); ++ if(err){ ++ printk("write describe information fail \n"); ++ } ++ ++ describle=kzalloc(fmacfw_patch_tbl_8800dc_u02_describe_size,GFP_KERNEL); ++ memcpy(describle,&dst[1],fmacfw_patch_tbl_8800dc_u02_describe_size); ++ printk("%s",describle); ++ kfree(describle); ++ describle=NULL; ++ } ++ ++ if (!err && (i < size)) { ++ for (i =(128/4); i < (size/4); i +=2) { ++ printk("patch_tbl: %x %x\n", dst[i], dst[i+1]); ++ err = rwnx_send_dbg_mem_write_req(rwnx_hw, dst[i], dst[i+1]); ++ } ++ if (err) { ++ printk("bin upload fail: %x, err:%d\r\n", dst[i], err); ++ } ++ } ++ ++ if (dst) { ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++#endif ++ dst = NULL; ++ } ++ ++ ++ return err; ++ ++} ++ ++extern char aic_fw_path[200]; ++int aicwf_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ #if !defined(CONFIG_FPGA_VERIFICATION) ++ if (chip_sub_id == 0) { ++ printk("u01 is loaing ###############\n"); ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_8800DC); ++ } else if (chip_sub_id == 1) { ++ printk("u02 is loaing ###############\n"); ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_8800DC_U02); ++ } else if (chip_sub_id == 2) { ++ printk("h_u02 is loaing ###############\n"); ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_8800DC_H_U02); ++ } else { ++ printk("unsupported id: %d\n", chip_sub_id); ++ } ++ #endif ++ return ret; ++} ++ ++int aicwf_plat_rftest_load_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, RAM_LMAC_FW_ADDR, RWNX_MAC_FW_RF_BASE_NAME_8800DC); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ return ret; ++} ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++int aicwf_misc_ram_valid_check_8800dc(struct aic_sdio_dev *sdiodev, int *valid_out) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_word_cnt; ++ uint32_t bit_mask[4]; ++ int i; ++ if (valid_out) { ++ *valid_out = 0; ++ } ++ if (testmode == FW_RFTEST_MODE) { ++ ++ uint32_t vect1 = 0; ++ uint32_t vect2 = 0; ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0004; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "cfg_base:%x vcet1 rd fail: %d\n", cfg_base, ret); ++ return ret; ++ } ++ vect1 = cfm.memdata; ++ if ((vect1 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) { ++ AICWFDBG(LOGERROR, "vect1 invalid: %x\n", vect1); ++ return ret; ++ } ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0008; ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "cfg_base:%x vcet2 rd fail: %d\n", cfg_base, ret); ++ return ret; ++ } ++ vect2 = cfm.memdata; ++ if ((vect2 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) { ++ AICWFDBG(LOGERROR, "vect2 invalid: %x\n", vect2); ++ return ret; ++ } ++ ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ // init misc ram ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr); ++ // bit_mask ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4; ++ for (i = 0; i < ram_word_cnt; i++) { ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, ram_base_addr + i * 4, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret); ++ return ret; ++ } ++ bit_mask[i] = cfm.memdata; ++ } ++ AICWFDBG(LOGTRACE, "bit_mask:%x,%x,%x,%x\n",bit_mask[0],bit_mask[1],bit_mask[2],bit_mask[3]); ++ if ((bit_mask[0] == 0) && ((bit_mask[1] & 0xFFF00000) == 0x80000000) && ++ (bit_mask[2] == 0) && ((bit_mask[3] & 0xFFFFFF00) == 0x00000000)) { ++ if (valid_out) { ++ *valid_out = 1; ++ } ++ } ++ return ret; ++} ++ ++int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ if (chip_sub_id == 1) { ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_CALIB_ADDR, RWNX_MAC_CALIB_NAME_8800DC_U02); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ } else if (chip_sub_id == 2) { ++ ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_CALIB_ADDR, RWNX_MAC_CALIB_NAME_8800DC_H_U02); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++#endif ++ ++#ifdef CONFIG_DPD ++#ifndef CONFIG_FORCE_DPD_CALIB ++int is_file_exist(char* name) ++{ ++ char *path = NULL; ++ struct file *fp = NULL; ++ int len; ++ ++ path = __getname(); ++ if (!path) { ++ AICWFDBG(LOGINFO, "%s getname fail\n", __func__); ++ return -1; ++ } ++ ++ len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", AICBSP_FW_PATH, name); ++ ++ fp = filp_open(path, O_RDONLY, 0); ++ if (IS_ERR(fp)) { ++ __putname(path); ++ fp = NULL; ++ return 0; ++ } else { ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return 1; ++ } ++} ++ ++EXPORT_SYMBOL(is_file_exist); ++#endif ++#endif ++ ++#ifdef CONFIG_DPD ++rf_misc_ram_lite_t dpd_res = {{0},}; ++EXPORT_SYMBOL(dpd_res); ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++rf_misc_ram_lite_t loft_res_local = {{0},}; ++EXPORT_SYMBOL(loft_res_local); ++#endif ++ ++static int rwnx_plat_patch_load(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ AICWFDBG(LOGINFO, "testmode=%d\n", testmode); ++ if (chip_sub_id == 0) { ++ if (testmode == FW_NORMAL_MODE) { ++ AICWFDBG(LOGINFO, "rwnx_plat_patch_loading\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ } else if (testmode == FW_RFTEST_MODE) { ++ ret = aicwf_plat_rftest_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ } else if (chip_sub_id >= 1) { ++ if (testmode == FW_NORMAL_MODE) { ++ AICWFDBG(LOGINFO, "rwnx_plat_patch_loading\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ #ifdef CONFIG_DPD ++ #ifdef CONFIG_FORCE_DPD_CALIB ++ if (1) { ++ AICWFDBG(LOGINFO, "dpd calib & write\n"); ++ ret = aicwf_dpd_calib_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "dpd calib fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #else ++ if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 1) { ++ AICWFDBG(LOGINFO, "dpd bin load\n"); ++ ret = aicwf_dpd_result_load_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ ret = aicwf_dpd_result_apply_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "apply dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ else ++ #elif defined(CONFIG_LOFT_CALIB) ++ if (1) { ++ AICWFDBG(LOGINFO, "loft calib\n"); ++ ret = aicwf_loft_calib_8800dc(sdiodev, &loft_res_local); ++ if (ret) { ++ AICWFDBG(LOGINFO, "loft calib fail: %d\n", ret); ++ return ret; ++ } ++ } else ++ #endif ++ { ++ ret = aicwf_misc_ram_init_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram init fail: %d\n", ret); ++ return ret; ++ } ++ } ++ } else if (testmode == FW_RFTEST_MODE) { ++ #ifdef CONFIG_DPD ++ #ifdef CONFIG_FORCE_DPD_CALIB ++ if (1) { ++ AICWFDBG(LOGINFO, "patch load\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ AICWFDBG(LOGINFO, "dpd calib & write\n"); ++ ret = aicwf_dpd_calib_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "dpd calib fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif/*CONFIG_FORCE_DPD_CALIB*/ ++ #elif defined(CONFIG_LOFT_CALIB) ++ { ++ AICWFDBG(LOGINFO, "patch load\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ AICWFDBG(LOGINFO, "loft calib\n"); ++ ret = aicwf_loft_calib_8800dc(sdiodev, &loft_res_local); ++ if (ret) { ++ AICWFDBG(LOGINFO, "loft calib fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif/*CONFIG_DPD*/ ++ ret = aicwf_plat_rftest_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ } else if (testmode == FW_DPDCALIB_MODE) { ++ #if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++ if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 0) { ++ AICWFDBG(LOGINFO, "patch load\n"); ++ ret = aicwf_plat_patch_load_8800dc(sdiodev); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load patch bin fail: %d\n", ret); ++ return ret; ++ } ++ AICWFDBG(LOGINFO, "dpd calib & write\n"); ++ ret = aicwf_dpd_calib_8800dc(sdiodev, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "dpd calib fail: %d\n", ret); ++ return ret; ++ } ++ ret = aicwf_dpd_result_write_8800dc((void *)&dpd_res, DPD_RESULT_SIZE_8800DC); ++ if (ret) { ++ AICWFDBG(LOGINFO, "file write fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ return 1; // exit calib mode ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, ++ const char *filename) ++{ ++ struct device *dev = sdiodev->dev; ++ unsigned int i = 0; ++ int size; ++ u32 *dst = NULL; ++ int err = 0; ++ ++ printk("%s\n",__func__); ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware(&dst, filename, dev); ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++#endif ++ dst = NULL; ++ return -1; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ if (size > 1024) {// > 1KB data ++ for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, fw_addr + i, 1024, dst + i / 4); ++ if (err) { ++ printk("bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ break; ++ } ++ } ++ } ++ ++ if (!err && (i < size)) {// <1KB data ++ err = rwnx_send_dbg_mem_block_write_req(sdiodev, fw_addr + i, size - i, dst + i / 4); ++ if (err) { ++ printk("bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ } ++ } ++ ++ if (dst) { ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(dst); ++#endif ++ dst = NULL; ++ } ++ ++ return err; ++} ++ ++int aicbt_patch_table_free(struct aicbt_patch_table **head) ++{ ++ struct aicbt_patch_table *p = *head, *n = NULL; ++ while (p) { ++ n = p->next; ++ vfree(p->name); ++ vfree(p->data); ++ vfree(p); ++ p = n; ++ } ++ *head = NULL; ++ return 0; ++} ++ ++struct aicbt_patch_table *aicbt_patch_table_alloc(const char *filename) ++{ ++ uint8_t *rawdata = NULL, *p; ++ int size; ++ struct aicbt_patch_table *head = NULL, *new = NULL, *cur = NULL; ++ ++ /* load aic firmware */ ++ size = rwnx_load_firmware((u32 **)&rawdata, filename, NULL); ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ goto err; ++ } ++ ++ p = rawdata; ++ if (memcmp(p, AICBT_PT_TAG, sizeof(AICBT_PT_TAG) < 16 ? sizeof(AICBT_PT_TAG) : 16)) { ++ printk("TAG err\n"); ++ goto err; ++ } ++ p += 16; ++ ++ while (p - rawdata < size) { ++ new = (struct aicbt_patch_table *)vmalloc(sizeof(struct aicbt_patch_table)); ++ memset(new, 0, sizeof(struct aicbt_patch_table)); ++ if (head == NULL) { ++ head = new; ++ cur = new; ++ } else { ++ cur->next = new; ++ cur = cur->next; ++ } ++ ++ cur->name = (char *)vmalloc(sizeof(char) * 16); ++ memset(cur->name, 0, sizeof(char) * 16); ++ memcpy(cur->name, p, 16); ++ p += 16; ++ ++ cur->type = *(uint32_t *)p; ++ p += 4; ++ ++ cur->len = *(uint32_t *)p; ++ p += 4; ++ ++ if((cur->type ) >= 1000 ) {//Temp Workaround ++ cur->len = 0; ++ }else{ ++ if(cur->len > 0){ ++ cur->data = (uint32_t *)vmalloc(sizeof(uint8_t) * cur->len * 8); ++ memset(cur->data, 0, sizeof(uint8_t) * cur->len * 8); ++ memcpy(cur->data, p, cur->len * 8); ++ p += cur->len * 8; ++ } ++ } ++ } ++#ifndef CONFIG_FIRMWARE_ARRAY ++ vfree(rawdata); ++#endif ++ return head; ++ ++err: ++ aicbt_patch_table_free(&head); ++ if (rawdata) ++ vfree(rawdata); ++ return NULL; ++} ++int aicbt_patch_info_unpack(struct aicbt_patch_info_t *patch_info, struct aicbt_patch_table *head_t) ++{ ++ uint8_t *patch_info_array = (uint8_t*)patch_info; ++ int base_len = 0; ++ int memcpy_len = 0; ++ ++ if (AICBT_PT_INF == head_t->type) { ++ base_len = ((offsetof(struct aicbt_patch_info_t, ext_patch_nb_addr) - offsetof(struct aicbt_patch_info_t, adid_addrinf) )/sizeof(uint32_t))/2; ++ AICWFDBG(LOGDEBUG, "%s head_t->len:%d base_len:%d \r\n", __func__, head_t->len, base_len); ++ ++ if (head_t->len > base_len){ ++ patch_info->info_len = base_len; ++ memcpy_len = patch_info->info_len + 1;//include ext patch nb ++ } else{ ++ patch_info->info_len = head_t->len; ++ memcpy_len = patch_info->info_len; ++ } ++ AICWFDBG(LOGDEBUG, "%s memcpy_len:%d \r\n", __func__, memcpy_len); ++ ++ if (patch_info->info_len == 0) ++ return 0; ++ ++ memcpy(((patch_info_array) + sizeof(patch_info->info_len)), ++ head_t->data, ++ memcpy_len * sizeof(uint32_t) * 2); ++ AICWFDBG(LOGDEBUG, "%s adid_addrinf:%x addr_adid:%x \r\n", __func__, ++ ((struct aicbt_patch_info_t *)patch_info_array)->adid_addrinf, ++ ((struct aicbt_patch_info_t *)patch_info_array)->addr_adid); ++ ++ if (patch_info->ext_patch_nb > 0){ ++ int index = 0; ++ patch_info->ext_patch_param = (uint32_t *)(head_t->data + ((memcpy_len) * 2)); ++ ++ for(index = 0; index < patch_info->ext_patch_nb; index++){ ++ AICWFDBG(LOGDEBUG, "%s id:%x addr:%x \r\n", __func__, ++ *(patch_info->ext_patch_param + (index * 2)), ++ *(patch_info->ext_patch_param + (index * 2) + 1)); ++ } ++ } ++ ++ } ++ return 0; ++} ++ ++int aicbt_ext_patch_data_load(struct aic_sdio_dev *sdiodev, struct aicbt_patch_info_t *patch_info) ++{ ++ int ret = 0; ++ uint32_t ext_patch_nb = patch_info->ext_patch_nb; ++ char ext_patch_file_name[50]; ++ int index = 0; ++ uint32_t id = 0; ++ uint32_t addr = 0; ++ ++ ++ if (ext_patch_nb > 0){ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8800DC) { ++ AICWFDBG(LOGDEBUG, "[0x40506004]: 0x04318000\n"); ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, 0x40506004, 0x04318000); ++ AICWFDBG(LOGDEBUG, "[0x40506004]: 0x04338000\n"); ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, 0x40506004, 0x04338000); ++ } ++ for (index = 0; index < patch_info->ext_patch_nb; index++){ ++ id = *(patch_info->ext_patch_param + (index * 2)); ++ addr = *(patch_info->ext_patch_param + (index * 2) + 1); ++ memset(ext_patch_file_name, 0, sizeof(ext_patch_file_name)); ++ sprintf(ext_patch_file_name,"%s%d.bin", ++ aicbsp_firmware_list[aicbsp_info.cpmode].bt_ext_patch, ++ id); ++ AICWFDBG(LOGDEBUG, "%s ext_patch_file_name:%s ext_patch_id:%x ext_patch_addr:%x \r\n", ++ __func__,ext_patch_file_name, id, addr); ++ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, addr, ext_patch_file_name)) { ++ ret = -1; ++ break; ++ } ++ } ++ } ++ return ret; ++} ++ ++ ++int aicbt_patch_trap_data_load(struct aic_sdio_dev *sdiodev, struct aicbt_patch_table *head) ++{ ++ struct aicbt_patch_info_t patch_info = { ++ .info_len = 0, ++ .adid_addrinf = 0, ++ .addr_adid = 0, ++ .patch_addrinf = 0, ++ .addr_patch = 0, ++ .reset_addr = 0, ++ .reset_val = 0, ++ .adid_flag_addr = 0, ++ .adid_flag = 0, ++ .ext_patch_nb_addr = 0, ++ .ext_patch_nb = 0, ++ }; ++ if(head == NULL){ ++ return -1; ++ } ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR; ++ patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR; ++ } ++ else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC){ ++ if(aicbsp_info.chip_rev == CHIP_REV_U01){ ++ patch_info.addr_adid = RAM_8800DC_U01_ADID_ADDR; ++ }else if(aicbsp_info.chip_rev == CHIP_REV_U02){ ++ patch_info.addr_adid = RAM_8800DC_U02_ADID_ADDR; ++ } ++ patch_info.addr_patch = RAM_8800DC_FW_PATCH_ADDR; ++ aicbt_patch_info_unpack(&patch_info, head); ++ if(patch_info.reset_addr == 0) { ++ patch_info.reset_addr = FW_RESET_START_ADDR; ++ patch_info.reset_val = FW_RESET_START_VAL; ++ patch_info.adid_flag_addr = FW_ADID_FLAG_ADDR; ++ patch_info.adid_flag = FW_ADID_FLAG_VAL; ++ if (rwnx_send_dbg_mem_write_req(sdiodev, patch_info.reset_addr, patch_info.reset_val)) ++ return -1; ++ if (rwnx_send_dbg_mem_write_req(sdiodev, patch_info.adid_flag_addr, patch_info.adid_flag)) ++ return -1; ++ } ++ } else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ if (aicbsp_info.chip_rev == CHIP_REV_U01) { ++ patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80; ++ patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80; ++ } else if (aicbsp_info.chip_rev == CHIP_REV_U02 || aicbsp_info.chip_rev == CHIP_REV_U03) { ++ patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80_U02; ++ patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80_U02; ++ } ++ aicbt_patch_info_unpack(&patch_info, head); ++ if(patch_info.info_len == 0) { ++ printk("%s, aicbt_patch_info_unpack fail\n", __func__); ++ return -1; ++ } ++ } else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ aicbt_patch_info_unpack(&patch_info, head); ++ if(patch_info.info_len == 0) { ++ printk("%s, aicbt_patch_info_unpack fail\n", __func__); ++ return -1; ++ } ++ } ++ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, patch_info.addr_adid, aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid)) ++ return -1; ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, patch_info.addr_patch, aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch)) ++ return -1; ++ if (aicbt_ext_patch_data_load(sdiodev, &patch_info)) ++ return -1; ++ return 0; ++ ++} ++ ++static struct aicbt_info_t aicbt_info[]={ ++ { ++ .btmode = AICBT_BTMODE_DEFAULT, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT, ++ },//PRODUCT_ID_AIC8801 ++ { ++ .btmode = AICBT_BTMODE_BT_WIFI_COMBO, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800dc, ++ },//PRODUCT_ID_AIC8800DC ++ { ++ .btmode = AICBT_BTMODE_BT_WIFI_COMBO, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800dc, ++ },//PRODUCT_ID_AIC8800DW ++ { ++ .btmode = AICBT_BTMODE_DEFAULT_8800d80, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800d80, ++ },//PRODUCT_ID_AIC8800D80 ++ { ++ .btmode = AICBT_BTMODE_DEFAULT_8800d80x2, ++ .btport = AICBT_BTPORT_DEFAULT, ++ .uart_baud = AICBT_UART_BAUD_DEFAULT, ++ .uart_flowctrl = AICBT_UART_FC_DEFAULT, ++ .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, ++ .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800d80x2, ++ }//PRODUCT_ID_AIC8800D80x2 ++ ++}; ++ ++ ++int aicbt_patch_table_load(struct aic_sdio_dev *sdiodev, struct aicbt_patch_table *head) ++{ ++ struct aicbt_patch_table *p; ++ int ret = 0, i; ++ uint32_t *data = NULL; ++ if(head == NULL){ ++ return -1; ++ } ++ ++ for (p = head; p != NULL; p = p->next) { ++ data = p->data; ++ if (AICBT_PT_BTMODE == p->type) { ++ *(data + 1) = aicbsp_info.hwinfo < 0; ++ *(data + 3) = aicbsp_info.hwinfo; ++ *(data + 5) = (sdiodev->chipid == PRODUCT_ID_AIC8800DC?aicbsp_info.cpmode:0);//0;//aicbsp_info.cpmode; ++ ++ *(data + 7) = aicbt_info[sdiodev->chipid].btmode; ++ *(data + 9) = aicbt_info[sdiodev->chipid].btport; ++ *(data + 11) = aicbt_info[sdiodev->chipid].uart_baud; ++ *(data + 13) = aicbt_info[sdiodev->chipid].uart_flowctrl; ++ *(data + 15) = aicbt_info[sdiodev->chipid].lpm_enable; ++ *(data + 17) = aicbt_info[sdiodev->chipid].txpwr_lvl; ++ ++ printk("%s bt btmode[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].btmode); ++ printk("%s bt uart_baud[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].uart_baud); ++ printk("%s bt uart_flowctrl[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].uart_flowctrl); ++ printk("%s bt lpm_enable[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].lpm_enable); ++ printk("%s bt tx_pwr[%d]:%d \r\n", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].txpwr_lvl); ++ } ++ ++ if (AICBT_PT_VER == p->type) { ++ printk("aicbsp: bt patch version: %s\n", (char *)p->data); ++ continue; ++ } ++ ++ for (i = 0; i < p->len; i++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, *data, *(data + 1)); ++ if (ret != 0) ++ return ret; ++ data += 2; ++ } ++ if (p->type == AICBT_PT_PWRON) ++ udelay(500); ++ } ++ ++ ++ ///aicbt_patch_table_free(&head); ++ return 0; ++} ++ ++ ++int aicbt_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ struct aicbt_patch_table *head = aicbt_patch_table_alloc(aicbsp_firmware_list[aicbsp_info.cpmode].bt_table); ++ if (head == NULL){ ++ printk("aicbt_patch_table_alloc fail\n"); ++ return -1; ++ } ++ ++ if (aicbt_patch_trap_data_load(sdiodev, head)) { ++ printk("aicbt_patch_trap_data_load fail\n"); ++ ret = -1; ++ goto err; ++ } ++ ++ if (aicbt_patch_table_load(sdiodev, head)) { ++ printk("aicbt_patch_table_load fail\n"); ++ ret = -1; ++ goto err; ++ } ++ ++err: ++ aicbt_patch_table_free(&head); ++ return ret; ++} ++ ++static int aicwifi_start_from_bootrom(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ ++ /* memory access */ ++ const u32 fw_addr = RAM_FMAC_FW_ADDR; ++ struct dbg_start_app_cfm start_app_cfm; ++ ++ /* fw start */ ++ ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, HOST_START_APP_AUTO, &start_app_cfm); ++ if (ret) { ++ return -1; ++ } ++ aicbsp_info.hwinfo_r = start_app_cfm.bootstatus & 0xFF; ++ ++ return 0; ++} ++ ++static int start_from_bootrom_8800DC(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ u32 rd_addr; ++ u32 fw_addr; ++ u32 boot_type; ++ struct dbg_mem_read_cfm rd_cfm; ++ ++ /* memory access */ ++ if(testmode == 1){ ++ rd_addr = RAM_LMAC_FW_ADDR; ++ fw_addr = RAM_LMAC_FW_ADDR; ++ } ++ else{ ++ rd_addr = RAM_FMAC_FW_ADDR; ++ fw_addr = RAM_FMAC_FW_ADDR; ++ } ++ ++ AICWFDBG(LOGINFO, "Read FW mem: %08x\n", rd_addr); ++ if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_addr, &rd_cfm))) { ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "cfm: [%08x] = %08x\n", rd_cfm.memaddr, rd_cfm.memdata); ++ ++ if (testmode == 0) { ++ boot_type = HOST_START_APP_DUMMY; ++ } else { ++ boot_type = HOST_START_APP_AUTO; ++ } ++ /* fw start */ ++ AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); ++ if ((ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type ,NULL))) { ++ return -1; ++ } ++ return 0; ++} ++ ++u32 adaptivity_patch_tbl[][2] = { ++ {0x0004, 0x0000320A}, //linkloss_thd ++ {0x0094, 0x00000000}, //ac_param_conf ++ {0x00F8, 0x00010138}, //tx_adaptivity_en ++}; ++ ++u32 patch_tbl[][2] = { ++#if !defined(CONFIG_LINK_DET_5G) ++ {0x0104, 0x00000000}, //link_det_5g ++#endif ++#if defined(CONFIG_MCU_MESSAGE) ++ {0x004c, 0x0000004B}, //pkt_cnt_1724=0x4B ++ {0x0050, 0x0011FC00}, //ipc_base_addr ++#endif ++}; ++ ++u32 syscfg_tbl_masked[][3] = { ++ {0x40506024, 0x000000FF, 0x000000DF}, // for clk gate lp_level ++}; ++ ++u32 rf_tbl_masked[][3] = { ++ {0x40344058, 0x00800000, 0x00000000},// pll trx ++}; ++ ++static int aicwifi_sys_config(struct aic_sdio_dev *sdiodev) ++{ ++ int ret, cnt; ++ int syscfg_num = sizeof(syscfg_tbl_masked) / sizeof(u32) / 3; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, ++ syscfg_tbl_masked[cnt][0], syscfg_tbl_masked[cnt][1], syscfg_tbl_masked[cnt][2]); ++ if (ret) { ++ printk("%x mask write fail: %d\n", syscfg_tbl_masked[cnt][0], ret); ++ return ret; ++ } ++ } ++ ++ ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, ++ rf_tbl_masked[0][0], rf_tbl_masked[0][1], rf_tbl_masked[0][2]); ++ if (ret) { ++ printk("rf config %x write fail: %d\n", rf_tbl_masked[0][0], ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int aicwifi_patch_config(struct aic_sdio_dev *sdiodev) ++{ ++ const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0180; ++ u32 config_base; ++ uint32_t start_addr = 0x1e6000; ++ u32 patch_addr = start_addr; ++ u32 patch_num = sizeof(patch_tbl)/4; ++ struct dbg_mem_read_cfm rd_patch_addr_cfm; ++ u32 patch_addr_reg = 0x1e5318; ++ u32 patch_num_reg = 0x1e531c; ++ int ret = 0; ++ u16 cnt = 0; ++ int tmp_cnt = 0; ++ int adap_patch_num = 0; ++ ++ if (aicbsp_info.cpmode == AICBSP_CPMODE_TEST) { ++ patch_addr_reg = 0x1e5304; ++ patch_num_reg = 0x1e5308; ++ } ++ ++ ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm); ++ if (ret) { ++ printk("patch rd fail\n"); ++ return ret; ++ } ++ ++ config_base = rd_patch_addr_cfm.memdata; ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_addr_reg, patch_addr); ++ if (ret) { ++ printk("0x%x write fail\n", patch_addr_reg); ++ return ret; ++ } ++ ++ if(adap_test){ ++ printk("%s for adaptivity test \r\n", __func__); ++ adap_patch_num = sizeof(adaptivity_patch_tbl)/4; ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_num_reg, patch_num + adap_patch_num); ++ }else{ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_num_reg, patch_num); ++ } ++ if (ret) { ++ printk("0x%x write fail\n", patch_num_reg); ++ return ret; ++ } ++ ++ for (cnt = 0; cnt < patch_num/2; cnt += 1) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl[cnt][0]+config_base); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ return ret; ++ } ++ ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl[cnt][1]); ++ if (ret) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ return ret; ++ } ++ } ++ ++ tmp_cnt = cnt; ++ ++ if(adap_test){ ++ for(cnt = 0; cnt < adap_patch_num/2; cnt+=1) ++ { ++ if((ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*(cnt+tmp_cnt), adaptivity_patch_tbl[cnt][0]+config_base))) { ++ printk("%x write fail\n", start_addr+8*cnt); ++ } ++ ++ if((ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*(cnt+tmp_cnt)+4, adaptivity_patch_tbl[cnt][1]))) { ++ printk("%x write fail\n", start_addr+8*cnt+4); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int aicwifi_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ #ifdef CONFIG_M2D_OTA_AUTO_SUPPORT ++ if (testmode == FW_M2D_OTA_MODE) { ++ rwnx_plat_m2d_flash_ota_android(sdiodev, FW_M2D_OTA_NAME); ++ } else if (testmode == FW_NORMAL_MODE) { ++ rwnx_plat_m2d_flash_ota_check(sdiodev, FW_M2D_OTA_NAME); ++ } ++ #endif ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { ++ printk("download wifi fw fail\n"); ++ return -1; ++ } ++ if (testmode == FW_NORMAL_MODE) { ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_PATCH_ADDR, RAM_FMAC_FW_PATCH_NAME)) { ++ printk("download wifi fw patch fail\n"); ++ return -1; ++ } ++ } ++ ++ if (aicwifi_patch_config(sdiodev)) { ++ printk("aicwifi_patch_config fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_sys_config(sdiodev)) { ++ printk("aicwifi_sys_config fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_start_from_bootrom(sdiodev)) { ++ printk("wifi start fail\n"); ++ return -1; ++ } ++ }else if (sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ printk("############ aicwifi_init begin \n"); ++ ++ system_config_8800dc(sdiodev); ++ printk("############ system_config_8800dc done\n"); ++ ++ ret = rwnx_plat_patch_load(sdiodev); ++ if (ret) { ++ printk("patch load return %d\n", ret); ++ return ret; ++ } ++ printk("############ rwnx_plat_patch_load done\n"); ++ ++ //rwnx_plat_userconfig_load(sdiodev); ++ ++ aicwf_patch_config_8800dc(sdiodev); ++ printk("############ aicwf_patch_config_8800dc done\n"); ++ ++ start_from_bootrom_8800DC(sdiodev); ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { ++ printk("8800d80 download wifi fw fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_patch_config_8800d80(sdiodev)) { ++ printk("aicwifi_patch_config_8800d80 fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_sys_config_8800d80(sdiodev)) { ++ printk("aicwifi_patch_config_8800d80 fail\n"); ++ return -1; ++ } ++ ++ if (aicwifi_start_from_bootrom(sdiodev)) { ++ printk("8800d80 wifi start fail\n"); ++ return -1; ++ } ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { ++ printk("8800d80x2 download wifi fw fail\n"); ++ return -1; ++ } ++ if (aicwifi_start_from_bootrom(sdiodev)) { ++ printk("8800d80x2 wifi start fail\n"); ++ return -1; ++ } ++ } ++ ++#if (defined(CONFIG_GPIO_WAKEUP) || defined(CONFIG_SDIO_PWRCTRL)) ++ if (aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 4)) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ return -1; ++ } ++#endif ++ return 0; ++} ++ ++u32 aicbsp_syscfg_tbl[][2] = { ++ {0x40500014, 0x00000101}, // 1) ++ {0x40500018, 0x00000109}, // 2) ++ {0x40500004, 0x00000010}, // 3) the order should not be changed ++ ++ // def CONFIG_PMIC_SETTING ++ // U02 bootrom only ++ {0x40040000, 0x00001AC8}, // 1) fix panic ++ {0x40040084, 0x00011580}, ++ {0x40040080, 0x00000001}, ++ {0x40100058, 0x00000000}, ++ ++ {0x50000000, 0x03220204}, // 2) pmic interface init ++ {0x50019150, 0x00000002}, // 3) for 26m xtal, set div1 ++ {0x50017008, 0x00000000}, // 4) stop wdg ++}; ++ ++static int aicbsp_system_config(struct aic_sdio_dev *sdiodev) ++{ ++ int syscfg_num = sizeof(aicbsp_syscfg_tbl) / sizeof(u32) / 2; ++ int ret, cnt; ++ for (cnt = 0; cnt < syscfg_num; cnt++) { ++ ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl[cnt][0], aicbsp_syscfg_tbl[cnt][1]); ++ if (ret) { ++ sdio_err("%x write fail: %d\n", aicbsp_syscfg_tbl[cnt][0], ret); ++ return ret; ++ } ++ } ++ return 0; ++} ++ ++ ++ ++int aicbsp_platform_init(struct aic_sdio_dev *sdiodev) ++{ ++ rwnx_cmd_mgr_init(&sdiodev->cmd_mgr); ++ sdiodev->cmd_mgr.sdiodev = (void *)sdiodev; ++ ++ return 0; ++} ++ ++void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev) ++{ ++ (void)sdiodev; ++} ++ ++int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev) ++{ ++ u32 mem_addr; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ u32 btenable = 0; ++ u8 is_chip_id_h = 0; ++ int ret = 0; ++ ++ mem_addr = 0x40500000; ++ ++ testmode = aicbsp_info.cpmode; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)(rd_mem_addr_cfm.memdata >> 16); ++ btenable = 1; ++ ++ if (aicbsp_info.chip_rev != CHIP_REV_U02 && ++ aicbsp_info.chip_rev != CHIP_REV_U03 && ++ aicbsp_info.chip_rev != CHIP_REV_U04) { ++ pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ return -1; ++ } ++ ++ if (aicbsp_info.chip_rev != CHIP_REV_U02) ++ aicbsp_firmware_list = fw_u03; ++ ++ if (aicbsp_system_config(sdiodev)) ++ return -1; ++ } ++ else if (sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); ++ is_chip_id_h = (u8)(((rd_mem_addr_cfm.memdata >> 16) & 0xC0) == 0xC0); ++ ++ btenable = ((rd_mem_addr_cfm.memdata >> 26) & 0x1); ++ AICWFDBG(LOGINFO, "btenable = %d \n",btenable); ++ ++ if(btenable == 0){ ++ sdiodev->chipid = PRODUCT_ID_AIC8800DW; ++ AICWFDBG(LOGINFO, "AIC8800DC change to AIC8800DW \n"); ++ } ++ ++ if (aicbsp_info.chip_rev != CHIP_REV_U01 && ++ aicbsp_info.chip_rev != CHIP_REV_U02 && ++ aicbsp_info.chip_rev != CHIP_REV_U03 && ++ aicbsp_info.chip_rev != CHIP_REV_U04) { ++ pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ return -1; ++ } ++ if (is_chip_id_h) { ++ AICWFDBG(LOGINFO, "IS_CHIP_ID_H \n"); ++ aicbsp_firmware_list = fw_8800dc_h_u02; ++ } else { ++ if(aicbsp_info.chip_rev == CHIP_REV_U01){ ++ aicbsp_firmware_list = fw_8800dc_u01; ++ }else{ ++ aicbsp_firmware_list = fw_8800dc_u02; ++ } ++ } ++ } ++ else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); ++ is_chip_id_h = (u8)(((rd_mem_addr_cfm.memdata >> 16) & 0xC0) == 0xC0); ++ btenable = 1; ++ if (is_chip_id_h) { ++ AICWFDBG(LOGINFO, "IS_CHIP_ID_H \n"); ++ aicbsp_firmware_list = fw_8800d80_h_u02; ++ } else { ++ if (aicbsp_info.chip_rev == CHIP_REV_U01) ++ aicbsp_firmware_list = fw_8800d80_u01; ++ if (aicbsp_info.chip_rev == CHIP_REV_U02 || aicbsp_info.chip_rev == CHIP_REV_U03) ++ aicbsp_firmware_list = fw_8800d80_u02; ++ } ++ if (aicbsp_system_config_8800d80(sdiodev)) ++ return -1; ++ } ++ else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ btenable = 1; ++ if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) ++ return -1; ++ ++ aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); ++ if (aicbsp_info.chip_rev >= (CHIP_REV_U04 + 8)) ++ aicbsp_firmware_list = fw_8800d80x2; ++ else{ ++ pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ return -1; ++ } ++ } ++ ++ AICWFDBG(LOGINFO, "aicbsp: %s, chip rev: %d\n", __func__, aicbsp_info.chip_rev); ++ ++ #ifndef CONFIG_MCU_MESSAGE ++ if (testmode != 4) { ++ if(btenable == 1){ ++ if (aicbt_init(sdiodev)) ++ return -1; ++ } ++ } ++ #endif ++ ++ ret = aicwifi_init(sdiodev); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path) ++{ ++ if (aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ feature->sdio_clock = FEATURE_SDIO_CLOCK; ++ }else if (aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800D80 || aicbsp_sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ feature->sdio_clock = FEATURE_SDIO_CLOCK_V3; ++ } ++ feature->sdio_phase = FEATURE_SDIO_PHASE; ++ feature->hwinfo = aicbsp_info.hwinfo; ++ feature->fwlog_en = aicbsp_info.fwlog_en; ++ feature->irqf = aicbsp_info.irqf; ++ if(fw_path != NULL){ ++ sprintf(fw_path,"%s", AICBSP_FW_PATH); ++ } ++ ++ sdio_dbg("%s, set FEATURE_SDIO_CLOCK %d MHz\n", __func__, feature->sdio_clock/1000000); ++ return 0; ++} ++ ++EXPORT_SYMBOL_GPL(aicbsp_get_feature); ++ ++#ifdef CONFIG_RESV_MEM_SUPPORT ++static struct skb_buff_pool resv_skb[] = { ++ {AIC_RESV_MEM_TXDATA, 1536*64, "resv_mem_txdata", 0, NULL}, ++}; ++ ++int aicbsp_resv_mem_init(void) ++{ ++ int i = 0; ++ printk("%s \n",__func__); ++ for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) { ++ resv_skb[i].skb = dev_alloc_skb(resv_skb[i].size); ++ } ++ return 0; ++} ++ ++int aicbsp_resv_mem_deinit(void) ++{ ++ int i = 0; ++ printk("%s \n",__func__); ++ for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) { ++ if (resv_skb[i].used == 0 && resv_skb[i].skb) ++ dev_kfree_skb(resv_skb[i].skb); ++ } ++ return 0; ++} ++ ++struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id) ++{ ++ if (resv_skb[id].size < length) { ++ pr_err("aicbsp: %s, no enough mem\n", __func__); ++ goto fail; ++ } ++ ++ if (resv_skb[id].used) { ++ pr_err("aicbsp: %s, mem in use\n", __func__); ++ goto fail; ++ } ++ ++ if (resv_skb[id].skb == NULL) { ++ pr_err("aicbsp: %s, mem not initialazed\n", __func__); ++ resv_skb[id].skb = dev_alloc_skb(resv_skb[id].size); ++ if (resv_skb[id].skb == NULL) { ++ pr_err("aicbsp: %s, mem reinitial still fail\n", __func__); ++ goto fail; ++ } ++ } ++ ++ printk("aicbsp: %s, alloc %s succuss, id: %d, size: %d\n", __func__, ++ resv_skb[id].name, resv_skb[id].id, resv_skb[id].size); ++ ++ resv_skb[id].used = 1; ++ return resv_skb[id].skb; ++ ++fail: ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(aicbsp_resv_mem_alloc_skb); ++ ++void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id) ++{ ++ resv_skb[id].used = 0; ++ printk("aicbsp: %s, free %s succuss, id: %d, size: %d\n", __func__, ++ resv_skb[id].name, resv_skb[id].id, resv_skb[id].size); ++} ++EXPORT_SYMBOL_GPL(aicbsp_resv_mem_kfree_skb); ++ ++#else ++ ++int aicbsp_resv_mem_init(void) ++{ ++ return 0; ++} ++ ++int aicbsp_resv_mem_deinit(void) ++{ ++ return 0; ++} ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h +new file mode 100644 +index 000000000000..f18253d168a3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h +@@ -0,0 +1,598 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.h ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _AIC_BSP_DRIVER_H ++#define _AIC_BSP_DRIVER_H ++ ++#include ++#include ++#include ++#include "aic_bsp_export.h" ++ ++#define RWNX_80211_CMD_TIMEOUT_MS 6000//500//300 ++ ++#define RWNX_CMD_FLAG_NONBLOCK BIT(0) ++#define RWNX_CMD_FLAG_REQ_CFM BIT(1) ++#define RWNX_CMD_FLAG_WAIT_PUSH BIT(2) ++#define RWNX_CMD_FLAG_WAIT_ACK BIT(3) ++#define RWNX_CMD_FLAG_WAIT_CFM BIT(4) ++#define RWNX_CMD_FLAG_DONE BIT(5) ++/* ATM IPC design makes it possible to get the CFM before the ACK, ++ * otherwise this could have simply been a state enum */ ++#define RWNX_CMD_WAIT_COMPLETE(flags) \ ++ (!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM))) ++ ++#define RWNX_CMD_MAX_QUEUED 8 ++ ++#define IPC_E2A_MSG_PARAM_SIZE 256 ++ ++#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ ++ ++/* message levels */ ++#define LOGERROR 0x0001 ++#define LOGINFO 0x0002 ++#define LOGTRACE 0x0004 ++#define LOGDEBUG 0x0008 ++#define LOGDATA 0x0010 ++ ++extern int aicwf_dbg_level_bsp; ++ ++#define AICWF_LOG "AICWFDBG(" ++ ++#define AICWFDBG(level, args, arg...) \ ++do { \ ++ if (aicwf_dbg_level_bsp & level) { \ ++ printk(AICWF_LOG#level")\t" args, ##arg); \ ++ } \ ++} while (0) ++ ++#define RWNX_DBG(fmt, ...) \ ++do { \ ++ if (aicwf_dbg_level_bsp & LOGTRACE) { \ ++ printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \ ++ } \ ++} while (0) ++ ++/// Message structure for MSGs from Emb to App ++struct ipc_e2a_msg { ++ u16 id; ///< Message id. ++ u16 dummy_dest_id; ++ u16 dummy_src_id; ++ u16 param_len; ///< Parameter embedded struct length. ++ u32 pattern; ///< Used to stamp a valid MSG buffer ++ u32 param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++typedef u16 lmac_msg_id_t; ++typedef u16 lmac_task_id_t; ++ ++struct lmac_msg { ++ lmac_msg_id_t id; ///< Message id. ++ lmac_task_id_t dest_id; ///< Destination kernel identifier. ++ lmac_task_id_t src_id; ///< Source kernel identifier. ++ u16 param_len; ///< Parameter embedded struct length. ++ u32 param[]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++#define rwnx_cmd_e2amsg ipc_e2a_msg ++#define rwnx_cmd_a2emsg lmac_msg ++#define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len) ++#define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4) ++ ++static inline void put_u16(u8 *buf, u16 data) ++{ ++ buf[0] = (u8)(data&0x00ff); ++ buf[1] = (u8)((data >> 8)&0x00ff); ++} ++ ++enum rwnx_cmd_mgr_state { ++ RWNX_CMD_MGR_STATE_DEINIT, ++ RWNX_CMD_MGR_STATE_INITED, ++ RWNX_CMD_MGR_STATE_CRASHED, ++}; ++ ++struct rwnx_cmd { ++ struct list_head list; ++ lmac_msg_id_t id; ++ lmac_msg_id_t reqid; ++ struct rwnx_cmd_a2emsg *a2e_msg; ++ char *e2a_msg; ++ u32 tkn; ++ u16 flags; ++ struct completion complete; ++ u32 result; ++}; ++ ++struct aic_sdio_dev; ++struct rwnx_cmd; ++typedef int (*msg_cb_fct)(struct rwnx_cmd *cmd, struct rwnx_cmd_e2amsg *msg); ++ ++struct rwnx_cmd_mgr { ++ enum rwnx_cmd_mgr_state state; ++ spinlock_t lock; ++ u32 next_tkn; ++ u32 queue_sz; ++ u32 max_queue_sz; ++ spinlock_t cb_lock; ++ void *sdiodev; ++ ++ struct list_head cmds; ++ ++ int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct); ++ void (*print)(struct rwnx_cmd_mgr *); ++ void (*drain)(struct rwnx_cmd_mgr *); ++ ++ struct work_struct cmdWork; ++ struct workqueue_struct *cmd_wq; ++}; ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr); ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr); ++int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd); ++void rwnx_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len); ++ ++enum { ++ TASK_NONE = (u8) -1, ++ ++ // MAC Management task. ++ TASK_MM = 0, ++ // DEBUG task ++ TASK_DBG, ++ /// SCAN task ++ TASK_SCAN, ++ /// TDLS task ++ TASK_TDLS, ++ /// SCANU task ++ TASK_SCANU, ++ /// ME task ++ TASK_ME, ++ /// SM task ++ TASK_SM, ++ /// APM task ++ TASK_APM, ++ /// BAM task ++ TASK_BAM, ++ /// MESH task ++ TASK_MESH, ++ /// RXU task ++ TASK_RXU, ++ // This is used to define the last task that is running on the EMB processor ++ TASK_LAST_EMB = TASK_RXU, ++ ++ // nX API task ++ TASK_API, ++ TASK_MAX, ++}; ++ ++#define LMAC_FIRST_MSG(task) ((lmac_msg_id_t)((task) << 10)) ++#define DRV_TASK_ID 100 ++#define MSG_I(msg) ((msg) & ((1<<10)-1)) ++#define MSG_T(msg) ((lmac_task_id_t)((msg) >> 10)) ++ ++enum dbg_msg_tag { ++ /// Memory read request ++ DBG_MEM_READ_REQ = LMAC_FIRST_MSG(TASK_DBG), ++ /// Memory read confirm ++ DBG_MEM_READ_CFM, ++ /// Memory write request ++ DBG_MEM_WRITE_REQ, ++ /// Memory write confirm ++ DBG_MEM_WRITE_CFM, ++ /// Module filter request ++ DBG_SET_MOD_FILTER_REQ, ++ /// Module filter confirm ++ DBG_SET_MOD_FILTER_CFM, ++ /// Severity filter request ++ DBG_SET_SEV_FILTER_REQ, ++ /// Severity filter confirm ++ DBG_SET_SEV_FILTER_CFM, ++ /// LMAC/MAC HW fatal error indication ++ DBG_ERROR_IND, ++ /// Request to get system statistics ++ DBG_GET_SYS_STAT_REQ, ++ /// COnfirmation of system statistics ++ DBG_GET_SYS_STAT_CFM, ++ /// Memory block write request ++ DBG_MEM_BLOCK_WRITE_REQ, ++ /// Memory block write confirm ++ DBG_MEM_BLOCK_WRITE_CFM, ++ /// Start app request ++ DBG_START_APP_REQ, ++ /// Start app confirm ++ DBG_START_APP_CFM, ++ /// Start npc request ++ DBG_START_NPC_REQ, ++ /// Start npc confirm ++ DBG_START_NPC_CFM, ++ /// Memory mask write request ++ DBG_MEM_MASK_WRITE_REQ, ++ /// Memory mask write confirm ++ DBG_MEM_MASK_WRITE_CFM, ++ ++ DBG_RFTEST_CMD_REQ, ++ DBG_RFTEST_CMD_CFM, ++ DBG_BINDING_REQ, ++ DBG_BINDING_CFM, ++ DBG_BINDING_IND, ++ ++ DBG_CUSTOM_MSG_REQ, ++ DBG_CUSTOM_MSG_CFM, ++ DBG_CUSTOM_MSG_IND, ++ ++ DBG_GPIO_WRITE_REQ, ++ DBG_GPIO_WRITE_CFM, ++ ++ ++ /// Max number of Debug messages ++ DBG_MAX, ++}; ++ ++#if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++#define FW_M2D_OTA_NAME "m2d_ota.bin" ++#else ++#define FW_M2D_OTA_NAME "m2d_ota_lzma.bin" ++#endif ++ ++enum { ++ HOST_START_APP_AUTO = 1, ++ HOST_START_APP_CUSTOM, ++ HOST_START_APP_FNCALL = 4, ++ HOST_START_APP_DUMMY = 5, ++}; ++ ++ ++struct dbg_mem_block_write_req { ++ u32 memaddr; ++ u32 memsize; ++ u32 memdata[1024 / sizeof(u32)]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_CFM message. ++struct dbg_mem_block_write_cfm { ++ u32 wstatus; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_REQ message. ++struct dbg_mem_write_req { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_CFM message. ++struct dbg_mem_write_cfm { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_REQ message. ++struct dbg_mem_read_req { ++ u32 memaddr; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_CFM message. ++struct dbg_mem_read_cfm { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_REQ message. ++struct dbg_mem_mask_write_req { ++ u32 memaddr; ++ u32 memmask; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_CFM message. ++struct dbg_mem_mask_write_cfm { ++ u32 memaddr; ++ u32 memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_REQ message. ++struct dbg_start_app_req { ++ u32 bootaddr; ++ u32 boottype; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_CFM message. ++struct dbg_start_app_cfm { ++ u32 bootstatus; ++}; ++ ++int aicwf_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev); ++int aicwf_plat_rftest_load_8800dc(struct aic_sdio_dev *sdiodev); ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++int aicwf_misc_ram_valid_check_8800dc(struct aic_sdio_dev *sdiodev, int *valid_out); ++int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev); ++#endif ++ ++int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device); ++int aicwf_patch_table_load(struct aic_sdio_dev *rwnx_hw, char *filename); ++ ++int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm); ++int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_size, u32 *mem_data); ++int rwnx_send_dbg_mem_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_data); ++int rwnx_send_dbg_mem_mask_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, ++ u32 mem_mask, u32 mem_data); ++int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm); ++ ++int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, const char *filename); ++ ++void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg); ++int aicbsp_platform_init(struct aic_sdio_dev *sdiodev); ++void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev); ++int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev); ++#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++int is_file_exist(char* name); ++#endif ++int aicbsp_resv_mem_init(void); ++int aicbsp_resv_mem_deinit(void); ++ ++#define AICBSP_FW_PATH CONFIG_AIC_FW_PATH ++#define AICBSP_FW_PATH_MAX 200 ++ ++#define RAM_FMAC_FW_ADDR 0x00120000 ++#define RAM_FMAC_FW_PATCH_ADDR 0x00190000 ++#define FW_RAM_ADID_BASE_ADDR 0x00161928 ++#define FW_RAM_ADID_BASE_ADDR_U03 0x00161928 ++#define FW_RAM_PATCH_BASE_ADDR 0x00100000 ++#define RAM_8800DC_U01_ADID_ADDR 0x00101788 ++#define RAM_8800DC_U02_ADID_ADDR 0x001017d8 ++#define RAM_8800DC_FW_PATCH_ADDR 0x00184000 ++#define FW_RESET_START_ADDR 0x40500128 ++#define FW_RESET_START_VAL 0x40 ++#define FW_ADID_FLAG_ADDR 0x40500150 ++#define FW_ADID_FLAG_VAL 0x01 ++#define FW_RAM_ADID_BASE_ADDR_8800D80 0x002017E0 ++#define FW_RAM_PATCH_BASE_ADDR_8800D80 0x0020B2B0 ++#define FW_RAM_ADID_BASE_ADDR_8800D80_U02 0x00201940 ++#define FW_RAM_PATCH_BASE_ADDR_8800D80_U02 0x0020b43c ++ ++#define AICBT_PT_TAG "AICBT_PT_TAG" ++ ++ ++/***************************************************************************** ++ * Addresses within RWNX_ADDR_CPU ++ *****************************************************************************/ ++#define RAM_LMAC_FW_ADDR 0x00150000 ++ ++#define ROM_FMAC_FW_ADDR 0x00010000 ++#define ROM_FMAC_PATCH_ADDR 0x00180000 ++ ++#define RAM_FMAC_FW_PATCH_NAME "fmacfw_patch.bin" ++#define RWNX_MAC_CALIB_BASE_NAME_8800DC "fmacfw_calib_8800dc" ++#define RWNX_MAC_CALIB_NAME_8800DC_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_u02.bin" ++#ifdef CONFIG_SDIO_BT ++#define RWNX_MAC_CALIB_NAME_8800DC_H_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_hbt_u02.bin" ++#else ++#define RWNX_MAC_CALIB_NAME_8800DC_H_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_h_u02.bin" ++#endif ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++#define ROM_FMAC_CALIB_ADDR 0x00130000 ++#endif ++#ifdef CONFIG_DPD ++#ifndef CONFIG_FORCE_DPD_CALIB ++#define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_lite_8800dc.bin" ++#endif ++#endif ++ ++#define RWNX_MAC_FW_RF_BASE_NAME_8800DC "lmacfw_rf_8800dc.bin" ++ ++#ifdef CONFIG_FOR_IPCOM ++#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc_ipc" ++#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin" ++#else ++#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc" ++#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin" ++#define RWNX_MAC_PATCH_NAME2_8800DC_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_u02.bin" ++#ifdef CONFIG_SDIO_BT ++#define RWNX_MAC_PATCH_NAME2_8800DC_H_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_hbt_u02.bin" ++#else ++#define RWNX_MAC_PATCH_NAME2_8800DC_H_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_h_u02.bin" ++#endif ++#endif ++ ++#define RWNX_MAC_PATCH_TABLE_NAME_8800DC "fmacfw_patch_tbl_8800dc" ++#define RWNX_MAC_PATCH_TABLE_8800DC RWNX_MAC_PATCH_TABLE_NAME_8800DC ".bin" ++#define RWNX_MAC_PATCH_TABLE_8800DC_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_u02.bin" ++#ifdef CONFIG_SDIO_BT ++#define RWNX_MAC_PATCH_TABLE_8800DC_H_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_hbt_u02.bin" ++#else ++#define RWNX_MAC_PATCH_TABLE_8800DC_H_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_h_u02.bin" ++#endif ++ ++#define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc" ++#define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin" ++#define FW_USERCONFIG_NAME_8800DC "aic_userconfig_8800dc.txt" ++ ++enum { ++ FW_NORMAL_MODE = 0, ++ FW_RFTEST_MODE = 1, ++ FW_BLE_SCAN_WAKEUP_MODE = 2, ++ FW_M2D_OTA_MODE = 3, ++ FW_DPDCALIB_MODE = 4, ++ FW_BLE_SCAN_AD_FILTER_MODE = 5, ++}; ++ ++enum aicbt_patch_table_type { ++ AICBT_PT_INF = 0x00, ++ AICBT_PT_TRAP = 0x1, ++ AICBT_PT_B4, ++ AICBT_PT_BTMODE, ++ AICBT_PT_PWRON, ++ AICBT_PT_AF, ++ AICBT_PT_VER, ++}; ++ ++enum aicbt_btport_type { ++ AICBT_BTPORT_NULL, ++ AICBT_BTPORT_MB, ++ AICBT_BTPORT_UART, ++}; ++ ++/* btmode ++ * used for force bt mode,if not AICBSP_MODE_NULL ++ * efuse valid and vendor_info will be invalid, even has beed set valid ++*/ ++enum aicbt_btmode_type { ++ AICBT_BTMODE_BT_ONLY_SW = 0x0, // bt only mode with switch ++ AICBT_BTMODE_BT_WIFI_COMBO, // wifi/bt combo mode ++ AICBT_BTMODE_BT_ONLY, // bt only mode without switch ++ AICBT_BTMODE_BT_ONLY_TEST, // bt only test mode ++ AICBT_BTMODE_BT_WIFI_COMBO_TEST, // wifi/bt combo test mode ++ AICBT_BTMODE_BT_ONLY_COANT, // bt only mode with no external switch ++ AICBT_MODE_NULL = 0xFF, // invalid value ++}; ++ ++/* uart_baud ++ * used for config uart baud when btport set to uart, ++ * otherwise meaningless ++*/ ++enum aicbt_uart_baud_type { ++ AICBT_UART_BAUD_115200 = 115200, ++ AICBT_UART_BAUD_921600 = 921600, ++ AICBT_UART_BAUD_1_5M = 1500000, ++ AICBT_UART_BAUD_3_25M = 3250000, ++}; ++ ++enum aicbt_uart_flowctrl_type { ++ AICBT_UART_FLOWCTRL_DISABLE = 0x0, // uart without flow ctrl ++ AICBT_UART_FLOWCTRL_ENABLE, // uart with flow ctrl ++}; ++ ++enum aicbsp_cpmode_type { ++ AICBSP_CPMODE_WORK, ++ AICBSP_CPMODE_TEST, ++ AICBSP_CPMODE_MAX, ++}; ++ ++enum chip_rev { ++ CHIP_REV_U01 = 1, ++ CHIP_REV_U02 = 3, ++ CHIP_REV_U03 = 7, ++ CHIP_REV_U04 = 7, ++}; ++ ++#define AIC_M2D_OTA_INFO_ADDR 0x88000020 ++#define AIC_M2D_OTA_DATA_ADDR 0x88000040 ++#if !defined(CONFIG_M2D_OTA_LZMA_SUPPORT) ++#define AIC_M2D_OTA_FLASH_ADDR 0x08004000 ++#define AIC_M2D_OTA_CODE_START_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x0188) ++#define AIC_M2D_OTA_VER_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x018C) ++#else ++#define AIC_M2D_OTA_FLASH_ADDR 0x08005000 ++#define AIC_M2D_OTA_CODE_START_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x1188) ++#define AIC_M2D_OTA_VER_ADDR (AIC_M2D_OTA_FLASH_ADDR + 0x0010) ++#endif ++///aic bt tx pwr lvl :lsb->msb: first byte, min pwr lvl; second byte, max pwr lvl; ++///pwr lvl:20(min), 30 , 40 , 50 , 60(max) ++#define AICBT_TXPWR_LVL 0x00006020 ++#define AICBT_TXPWR_LVL_8800dc 0x00006f2f ++#define AICBT_TXPWR_LVL_8800d80 0x00006f2f ++#define AICBT_TXPWR_LVL_8800d80x2 0x00006f2f ++ ++ ++#define AICBSP_HWINFO_DEFAULT (-1) ++#define AICBSP_CPMODE_DEFAULT AICBSP_CPMODE_WORK ++#define AICBSP_FWLOG_EN_DEFAULT 0 ++ ++#define AICBT_BTMODE_DEFAULT_8800d80x2 AICBT_BTMODE_BT_ONLY_COANT ++#define AICBT_BTMODE_DEFAULT_8800d80 AICBT_BTMODE_BT_ONLY_COANT ++#define AICBT_BTMODE_DEFAULT AICBT_BTMODE_BT_ONLY_SW ++#ifdef CONFIG_SDIO_BT ++#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_MB ++#else ++#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_UART ++#endif ++#define AICBT_UART_BAUD_DEFAULT AICBT_UART_BAUD_1_5M ++#define AICBT_UART_FC_DEFAULT AICBT_UART_FLOWCTRL_ENABLE ++#define AICBT_LPM_ENABLE_DEFAULT 0 ++#define AICBT_TXPWR_LVL_DEFAULT AICBT_TXPWR_LVL ++#define AICBT_TXPWR_LVL_DEFAULT_8800dc AICBT_TXPWR_LVL_8800dc ++#define AICBT_TXPWR_LVL_DEFAULT_8800d80 AICBT_TXPWR_LVL_8800d80 ++#define AICBT_TXPWR_LVL_DEFAULT_8800d80x2 AICBT_TXPWR_LVL_8800d80x2 ++ ++ ++#define FEATURE_SDIO_CLOCK 50000000 // 0: default, other: target clock rate ++#define FEATURE_SDIO_CLOCK_V3 150000000 // 0: default, other: target clock rate ++#define FEATURE_SDIO_PHASE 2 // 0: default, 2: 180° ++ ++struct aicbt_patch_table { ++ char *name; ++ uint32_t type; ++ uint32_t *data; ++ uint32_t len; ++ struct aicbt_patch_table *next; ++}; ++ ++struct aicbt_info_t { ++ uint32_t btmode; ++ uint32_t btport; ++ uint32_t uart_baud; ++ uint32_t uart_flowctrl; ++ uint32_t lpm_enable; ++ uint32_t txpwr_lvl; ++}; ++ ++struct aicbt_patch_info_t { ++ uint32_t info_len; ++//base len start ++ uint32_t adid_addrinf; ++ uint32_t addr_adid; ++ uint32_t patch_addrinf; ++ uint32_t addr_patch; ++ uint32_t reset_addr; ++ uint32_t reset_val; ++ uint32_t adid_flag_addr; ++ uint32_t adid_flag; ++//base len end ++//ext patch nb ++ uint32_t ext_patch_nb_addr; ++ uint32_t ext_patch_nb; ++ uint32_t *ext_patch_param; ++}; ++ ++struct aicbsp_firmware { ++ const char *desc; ++ const char *bt_adid; ++ const char *bt_patch; ++ const char *bt_table; ++ const char *wl_fw; ++ const char *bt_ext_patch; ++}; ++ ++struct aicbsp_info_t { ++ int hwinfo; ++ int hwinfo_r; ++ uint32_t cpmode; ++ uint32_t chip_rev; ++ bool fwlog_en; ++ uint8_t irqf; ++}; ++ ++extern struct aicbsp_info_t aicbsp_info; ++extern struct mutex aicbsp_power_lock; ++extern const struct aicbsp_firmware *aicbsp_firmware_list; ++extern const struct aicbsp_firmware fw_u02[]; ++extern const struct aicbsp_firmware fw_u03[]; ++extern const struct aicbsp_firmware fw_8800dc_u01[]; ++extern const struct aicbsp_firmware fw_8800dc_u02[]; ++extern const struct aicbsp_firmware fw_8800dc_h_u02[]; ++extern const struct aicbsp_firmware fw_8800d80_u01[]; ++extern const struct aicbsp_firmware fw_8800d80_u02[]; ++extern const struct aicbsp_firmware fw_8800d80_h_u02[]; ++extern const struct aicbsp_firmware fw_8800d80x2[]; ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h +new file mode 100644 +index 000000000000..5535df6e0d14 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h +@@ -0,0 +1,71 @@ ++#ifndef __AIC_BSP_EXPORT_H ++#define __AIC_BSP_EXPORT_H ++ ++enum aicbsp_subsys { ++ AIC_BLUETOOTH, ++ AIC_WIFI, ++}; ++ ++enum aicbsp_pwr_state { ++ AIC_PWR_OFF, ++ AIC_PWR_ON, ++}; ++ ++enum skb_buff_id { ++ AIC_RESV_MEM_TXDATA, ++}; ++ ++struct skb_buff_pool { ++ uint32_t id; ++ uint32_t size; ++ const char *name; ++ uint8_t used; ++ struct sk_buff *skb; ++}; ++ ++struct aicbsp_feature_t { ++ int hwinfo; ++ uint32_t sdio_clock; ++ uint8_t sdio_phase; ++ bool fwlog_en; ++ uint8_t irqf; ++}; ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++typedef struct { ++ uint32_t bit_mask[3]; ++ uint32_t reserved; ++ uint32_t dpd_high[96]; ++ uint32_t dpd_11b[96]; ++ uint32_t dpd_low[96]; ++ uint32_t idac_11b[48]; ++ uint32_t idac_high[48]; ++ uint32_t idac_low[48]; ++ uint32_t loft_res[18]; ++ uint32_t rx_iqim_res[16]; ++} rf_misc_ram_t; ++ ++typedef struct { ++ uint32_t bit_mask[4]; ++ uint32_t dpd_high[96]; ++ uint32_t loft_res[18]; ++} rf_misc_ram_lite_t; ++ ++#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) ++#define DPD_RESULT_SIZE_8800DC sizeof(rf_misc_ram_lite_t) ++#endif ++ ++#ifdef CONFIG_DPD ++extern rf_misc_ram_lite_t dpd_res; ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++extern rf_misc_ram_lite_t loft_res_local; ++#endif ++ ++int aicbsp_set_subsys(int, int); ++int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path); ++struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id); ++void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c +new file mode 100644 +index 000000000000..406781997f6f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c +@@ -0,0 +1,456 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aic_bsp_driver.h" ++#include "rwnx_version_gen.h" ++#include "aicwf_txq_prealloc.h" ++ ++ ++#define DRV_DESCRIPTION "AIC BSP" ++#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi" ++#define DRV_AUTHOR "AICSemi" ++#define DRV_VERS_MOD "1.0" ++ ++int aicwf_dbg_level_bsp = LOGERROR; ++ ++struct semaphore aicbsp_probe_semaphore; ++ ++static struct platform_device *aicbsp_pdev; ++ ++const struct aicbsp_firmware *aicbsp_firmware_list = fw_u02; ++ ++const struct aicbsp_firmware fw_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(sdio u02)", ++ .bt_adid = "fw_adid.bin", ++ .bt_patch = "fw_patch.bin", ++ .bt_table = "fw_patch_table.bin", ++ #ifdef CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt.bin" ++ #else ++ .wl_fw = "fmacfw.bin" ++ #endif ++ }, ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(sdio u02)", ++ .bt_adid = "fw_adid.bin", ++ .bt_patch = "fw_patch.bin", ++ .bt_table = "fw_patch_table.bin", ++ .wl_fw = "fmacfw_rf.bin" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_u03[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(sdio u03/u04)", ++ .bt_adid = "fw_adid_u03.bin", ++ .bt_patch = "fw_patch_u03.bin", ++ .bt_table = "fw_patch_table_u03.bin", ++ #ifdef CONFIG_MCU_MESSAGE ++ .wl_fw = "fmacfw_8800m_custmsg.bin" ++ #elif defined(CONFIG_SDIO_BT) ++ .wl_fw = "fmacfwbt.bin" ++ #else ++ .wl_fw = "fmacfw.bin" ++ #endif ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(sdio u03/u04)", ++ .bt_adid = "fw_adid_u03.bin", ++ .bt_patch = "fw_patch_u03.bin", ++ .bt_table = "fw_patch_table_u03.bin", ++ .wl_fw = "fmacfw_rf.bin" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800dc_u01[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(sdio u01)", ++ .bt_adid = "fw_adid_8800dc.bin", ++ .bt_patch = "fw_patch_8800dc.bin", ++ .bt_table = "fw_patch_table_8800dc.bin", ++ .wl_fw = "fmacfw_8800dc.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(sdio u01)", ++ .bt_adid = "fw_adid_8800dc.bin", ++ .bt_patch = "fw_patch_8800dc.bin", ++ .bt_table = "fw_patch_table_8800dc.bin", ++ .wl_fw = "fmacfw_rf_8800dc.bin" ++ }, ++}; ++ ++ ++const struct aicbsp_firmware fw_8800dc_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800dc sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02.bin", ++ .bt_patch = "fw_patch_8800dc_u02.bin", ++ .bt_table = "fw_patch_table_8800dc_u02.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02_ext", ++ .wl_fw = "fmacfw_patch_8800dc_u02.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800dc sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02.bin", ++ .bt_patch = "fw_patch_8800dc_u02.bin", ++ .bt_table = "fw_patch_table_8800dc_u02.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02_ext", ++ .wl_fw = "lmacfw_rf_8800dc.bin" //u01,u02 lmacfw load same bin ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800dc_h_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800dc_h sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02h.bin", ++ .bt_patch = "fw_patch_8800dc_u02h.bin", ++ .bt_table = "fw_patch_table_8800dc_u02h.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02h_ext", ++ .wl_fw = "fmacfw_patch_8800dc_h_u02.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800dc_h sdio u02)", ++ .bt_adid = "fw_adid_8800dc_u02h.bin", ++ .bt_patch = "fw_patch_8800dc_u02h.bin", ++ .bt_table = "fw_patch_table_8800dc_u02h.bin", ++ .bt_ext_patch = "fw_patch_8800dc_u02h_ext", ++ .wl_fw = "lmacfw_rf_8800dc.bin" //u01,u02 lmacfw load same bin ++ }, ++}; ++ ++ ++const struct aicbsp_firmware fw_8800d80_u01[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80 sdio u01)", ++ .bt_adid = "fw_adid_8800d80.bin", ++ .bt_patch = "fw_patch_8800d80.bin", ++ .bt_table = "fw_patch_table_8800d80.bin", ++ .wl_fw = "fmacfw_8800d80.bin" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80 sdio u01)", ++ .bt_adid = "fw_adid_8800d80.bin", ++ .bt_patch = "fw_patch_8800d80.bin", ++ .bt_table = "fw_patch_table_8800d80.bin", ++ .wl_fw = "lmacfw_rf_8800d80.bin" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800d80_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80 sdio u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ #if defined CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_u02.bin", ++ #elif defined CONFIG_FOR_IPCAM ++ .wl_fw = "fmacfw_8800d80_u02_ipc.bin", ++ #else ++ .wl_fw = "fmacfw_8800d80_u02.bin", ++ #endif ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80 sdio u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ .wl_fw = "lmacfw_rf_8800d80_u02.bin", ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800d80_h_u02[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80 sdio h_u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ #if defined CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_h_u02.bin", ++ #elif defined CONFIG_FOR_IPCAM ++ .wl_fw = "fmacfw_8800d80_h_u02_ipc.bin", ++ #else ++ .wl_fw = "fmacfw_8800d80_h_u02.bin", ++ #endif ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80 sdio u02)", ++ .bt_adid = "fw_adid_8800d80_u02.bin", ++ .bt_patch = "fw_patch_8800d80_u02.bin", ++ .bt_table = "fw_patch_table_8800d80_u02.bin", ++ .wl_fw = "lmacfw_rf_8800d80_u02.bin", ++ .bt_ext_patch = "fw_patch_8800d80_u02_ext" ++ }, ++}; ++ ++const struct aicbsp_firmware fw_8800d80x2[] = { ++ [AICBSP_CPMODE_WORK] = { ++ .desc = "normal work mode(8800d80x2 sdio)", ++ .bt_adid = "fw_adid_8800d80x2_u05.bin", ++ .bt_patch = "fw_patch_8800d80x2_u05.bin", ++ .bt_table = "fw_patch_table_8800d80x2_u05.bin", ++ #ifdef CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_h_u02.bin", ++ #else ++ .wl_fw = "fmacfw_8800d80x2.bin", ++ #endif ++ .bt_ext_patch = "fw_patch_8800d80x2_u05_ext" ++ }, ++ ++ [AICBSP_CPMODE_TEST] = { ++ .desc = "rf test mode(8800d80x2 sdio)", ++ .bt_adid = "fw_adid_8800d80x2_u05.bin", ++ .bt_patch = "fw_patch_8800d80x2_u05.bin", ++ .bt_table = "fw_patch_table_8800d80x2_u05.bin", ++ .wl_fw = "lmacfw_rf_8800d80x2.bin", ++ .bt_ext_patch = "fw_patch_8800d80x2_u05_ext" ++ }, ++}; ++ ++struct aicbsp_info_t aicbsp_info = { ++ .hwinfo_r = AICBSP_HWINFO_DEFAULT, ++ .hwinfo = AICBSP_HWINFO_DEFAULT, ++ .cpmode = AICBSP_CPMODE_DEFAULT, ++ .fwlog_en = AICBSP_FWLOG_EN_DEFAULT, ++#ifdef CONFIG_IRQ_FALL ++ .irqf = 1, ++#else ++ .irqf = 0, ++#endif ++}; ++ ++struct mutex aicbsp_power_lock; ++ ++static struct platform_driver aicbsp_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "aic_bsp", ++ }, ++ //.probe = aicbsp_probe, ++ //.remove = aicbsp_remove, ++}; ++ ++static ssize_t cpmode_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t count = 0; ++ uint8_t i = 0; ++ ++ count += sprintf(&buf[count], "Support mode value:\n"); ++ ++ for (i = 0; i < AICBSP_CPMODE_MAX; i++) { ++ if (aicbsp_firmware_list[i].desc) ++ count += sprintf(&buf[count], " %2d: %s\n", i, aicbsp_firmware_list[i].desc); ++ } ++ ++ count += sprintf(&buf[count], "Current: %d, firmware info:\n", aicbsp_info.cpmode); ++ count += sprintf(&buf[count], " BT ADID : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid); ++ count += sprintf(&buf[count], " BT PATCH: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch); ++ count += sprintf(&buf[count], " BT TABLE: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_table); ++ count += sprintf(&buf[count], " WIFI FW : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw); ++ return count; ++} ++ ++static ssize_t cpmode_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ int err = kstrtoul(buf, 0, &val); ++ if (err) ++ return err; ++ ++ if (val >= AICBSP_CPMODE_MAX) { ++ pr_err("mode value must less than %d\n", AICBSP_CPMODE_MAX); ++ return -EINVAL; ++ } ++ ++ aicbsp_info.cpmode = val; ++ printk("%s, set mode to: %lu[%s] done\n", __func__, val, aicbsp_firmware_list[val].desc); ++ ++ return count; ++} ++ ++static ssize_t hwinfo_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t count = 0; ++ ++ count += sprintf(&buf[count], "chip hw rev: "); ++ if (aicbsp_info.hwinfo_r < 0) ++ count += sprintf(&buf[count], "-1(not avalible)\n"); ++ else ++ count += sprintf(&buf[count], "0x%02X\n", aicbsp_info.chip_rev); ++ ++ count += sprintf(&buf[count], "hwinfo read: "); ++ if (aicbsp_info.hwinfo_r < 0) ++ count += sprintf(&buf[count], "%d(not avalible), ", aicbsp_info.hwinfo_r); ++ else ++ count += sprintf(&buf[count], "0x%02X, ", aicbsp_info.hwinfo_r); ++ ++ if (aicbsp_info.hwinfo < 0) ++ count += sprintf(&buf[count], "set: %d(not avalible)\n", aicbsp_info.hwinfo); ++ else ++ count += sprintf(&buf[count], "set: 0x%02X\n", aicbsp_info.hwinfo); ++ ++ return count; ++} ++ ++static ssize_t hwinfo_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ long val; ++ int err = kstrtol(buf, 0, &val); ++ ++ if (err) { ++ pr_err("invalid input\n"); ++ return err; ++ } ++ ++ if ((val == -1) || (val >= 0 && val <= 0xFF)) { ++ aicbsp_info.hwinfo = val; ++ } else { ++ pr_err("invalid values\n"); ++ return -EINVAL; ++ } ++ return count; ++} ++ ++static ssize_t fwdebug_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t count = 0; ++ ++ count += sprintf(&buf[count], "fw log status: %s\n", ++ aicbsp_info.fwlog_en ? "on" : "off"); ++ ++ return count; ++} ++ ++static ssize_t fwdebug_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ long val; ++ int err = kstrtol(buf, 0, &val); ++ ++ if (err) { ++ pr_err("invalid input\n"); ++ return err; ++ } ++ ++ if (val > 1 || val < 0) { ++ pr_err("must be 0 or 1\n"); ++ return -EINVAL; ++ } ++ ++ aicbsp_info.fwlog_en = val; ++ return count; ++} ++ ++static DEVICE_ATTR(cpmode, S_IRUGO | S_IWUSR, ++ cpmode_show, cpmode_store); ++ ++static DEVICE_ATTR(hwinfo, S_IRUGO | S_IWUSR, ++ hwinfo_show, hwinfo_store); ++ ++static DEVICE_ATTR(fwdebug, S_IRUGO | S_IWUSR, ++ fwdebug_show, fwdebug_store); ++ ++static struct attribute *aicbsp_attributes[] = { ++ &dev_attr_cpmode.attr, ++ &dev_attr_hwinfo.attr, ++ &dev_attr_fwdebug.attr, ++ NULL, ++}; ++ ++static struct attribute_group aicbsp_attribute_group = { ++ .name = "aicbsp_info", ++ .attrs = aicbsp_attributes, ++}; ++ ++int testmode = AICBSP_CPMODE_DEFAULT; ++int adap_test = 0; ++module_param(testmode, int, 0660); ++module_param(adap_test, int, 0660); ++ ++ ++static int __init aicbsp_init(void) ++{ ++ int ret; ++ printk("%s\n", __func__); ++ printk("RELEASE_DATE:%s\r\n", RELEASE_DATE); ++ ++ aicbsp_info.cpmode = testmode; ++ ++ aicbsp_resv_mem_init(); ++ ++ sema_init(&aicbsp_probe_semaphore, 0); ++ ++ ret = platform_driver_register(&aicbsp_driver); ++ if (ret) { ++ pr_err("register platform driver failed: %d\n", ret); ++ return ret; ++ } ++ ++ aicbsp_pdev = platform_device_alloc("aic-bsp", -1); ++ ret = platform_device_add(aicbsp_pdev); ++ if (ret) { ++ pr_err("register platform device failed: %d\n", ret); ++ return ret; ++ } ++ ++ ret = sysfs_create_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group); ++ if (ret) { ++ pr_err("register sysfs create group failed!\n"); ++ return ret; ++ } ++ ++ mutex_init(&aicbsp_power_lock); ++#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 ++ aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON); ++#endif ++ return 0; ++} ++ ++void aicbsp_sdio_exit(void); ++extern struct aic_sdio_dev *aicbsp_sdiodev; ++ ++static void __exit aicbsp_exit(void) ++{ ++#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 ++ if(aicbsp_sdiodev){ ++ aicbsp_sdio_exit(); ++ } ++#endif ++ sysfs_remove_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group); ++ platform_device_del(aicbsp_pdev); ++ platform_driver_unregister(&aicbsp_driver); ++ mutex_destroy(&aicbsp_power_lock); ++ aicbsp_resv_mem_deinit(); ++#ifdef CONFIG_PREALLOC_TXQ ++ aicwf_prealloc_txq_free(); ++#endif ++ printk("%s\n", __func__); ++} ++ ++module_init(aicbsp_init); ++module_exit(aicbsp_exit); ++ ++MODULE_DESCRIPTION(DRV_DESCRIPTION); ++MODULE_VERSION(DRV_VERS_MOD); ++MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c +new file mode 100644 +index 000000000000..9ed440f912eb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c +@@ -0,0 +1,2040 @@ ++/** ++ * aicwf_sdmmc.c ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aicsdio_txrxif.h" ++#include "aicsdio.h" ++#include "aic_bsp_driver.h" ++#include ++#include ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#include ++#endif /* CONFIG_PLATFORM_ROCKCHIP */ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#include ++#endif /* CONFIG_PLATFORM_ROCKCHIP */ ++ ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++extern void sunxi_mmc_rescan_card(unsigned ids); ++extern void sunxi_wlan_set_power(int on); ++extern int sunxi_wlan_get_bus_index(void); ++static int aicbsp_bus_index = -1; ++#endif ++ ++#ifdef CONFIG_PLATFORM_AMLOGIC//for AML ++#include ++extern void sdio_reinit(void); ++extern void extern_wifi_set_enable(int is_on); ++extern void set_power_control_lock(int lock); ++#endif//for AML ++ ++ ++static int aicbsp_platform_power_on(void); ++static void aicbsp_platform_power_off(void); ++ ++struct aic_sdio_dev *aicbsp_sdiodev = NULL; ++static struct semaphore *aicbsp_notify_semaphore; ++extern struct semaphore aicbsp_probe_semaphore; ++ ++static const struct sdio_device_id aicbsp_sdmmc_ids[]; ++static bool aicbsp_load_fw_in_fdrv = false; ++ ++#define FW_PATH_MAX 200 ++ ++//#ifdef CONFIG_PLATFORM_UBUNTU ++//static const char* aic_default_fw_path = "/lib/firmware/aic8800_sdio"; ++//#else ++static const char* aic_default_fw_path = CONFIG_AIC_FW_PATH; ++//#endif ++char aic_fw_path[FW_PATH_MAX]; ++module_param_string(aic_fw_path, aic_fw_path, FW_PATH_MAX, 0660); ++#ifdef CONFIG_M2D_OTA_AUTO_SUPPORT ++char saved_sdk_ver[64]; ++module_param_string(saved_sdk_ver, saved_sdk_ver,64, 0660); ++#endif ++ ++extern int testmode; ++ ++ ++#define SDIO_DEVICE_ID_AIC8801_FUNC2 0x0146 ++#define SDIO_DEVICE_ID_AIC8800D80_FUNC2 0x0182 ++ ++/* SDIO Device ID */ ++#define SDIO_VENDOR_ID_AIC8801 0x5449 ++#define SDIO_VENDOR_ID_AIC8800DC 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80X2 0xc8a1 ++ ++#define SDIO_DEVICE_ID_AIC8801 0x0145 ++#define SDIO_DEVICE_ID_AIC8800DC 0xc08d ++#define SDIO_DEVICE_ID_AIC8800D80 0x0082 ++#define SDIO_DEVICE_ID_AIC8800D80X2 0x2082 ++ ++ ++static int aicbsp_dummy_probe(struct sdio_func *func, const struct sdio_device_id *id) ++{ ++ if (func && (func->num != 2)) ++ return 0; ++ ++ if(func->vendor != SDIO_VENDOR_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801_FUNC2 && ++ func->vendor != SDIO_VENDOR_ID_AIC8800DC && ++ func->device != SDIO_DEVICE_ID_AIC8800DC && ++ func->vendor != SDIO_VENDOR_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80_FUNC2){ ++ printk("VID:%x DID:%X \r\n", func->vendor, func->device); ++ aicbsp_load_fw_in_fdrv = true; ++ } ++ ++ if (aicbsp_notify_semaphore) ++ up(aicbsp_notify_semaphore); ++ return 0; ++} ++ ++static void aicbsp_dummy_remove(struct sdio_func *func) ++{ ++} ++ ++static struct sdio_driver aicbsp_dummy_sdmmc_driver = { ++ .probe = aicbsp_dummy_probe, ++ .remove = aicbsp_dummy_remove, ++ .name = "aicbsp_dummy_sdmmc", ++ .id_table = aicbsp_sdmmc_ids, ++}; ++ ++static int aicbsp_reg_sdio_notify(void *semaphore) ++{ ++ aicbsp_notify_semaphore = semaphore; ++ return sdio_register_driver(&aicbsp_dummy_sdmmc_driver); ++} ++ ++static void aicbsp_unreg_sdio_notify(void) ++{ ++ mdelay(15); ++ sdio_unregister_driver(&aicbsp_dummy_sdmmc_driver); ++} ++ ++static const char *aicbsp_subsys_name(int subsys) ++{ ++ switch (subsys) { ++ case AIC_BLUETOOTH: ++ return "AIC_BLUETOOTH"; ++ case AIC_WIFI: ++ return "AIC_WIFI"; ++ default: ++ return "unknown subsys"; ++ } ++} ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#if 1//FOR RK SUSPEND ++void rfkill_rk_sleep_bt(bool sleep); ++#endif ++#endif ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#if 1//FOR RK SUSPEND ++void rfkill_rk_sleep_bt(bool sleep); ++#endif ++#endif ++ ++int aicbsp_set_subsys(int subsys, int state) ++{ ++ static int pre_power_map; ++ int cur_power_map; ++ int pre_power_state; ++ int cur_power_state; ++ ++ mutex_lock(&aicbsp_power_lock); ++ aicbsp_load_fw_in_fdrv = false; ++ cur_power_map = pre_power_map; ++ if (state) ++ cur_power_map |= (1 << subsys); ++ else ++ cur_power_map &= ~(1 << subsys); ++ ++ pre_power_state = pre_power_map > 0; ++ cur_power_state = cur_power_map > 0; ++ ++ sdio_dbg("%s, subsys: %s, state to: %d\n", __func__, aicbsp_subsys_name(subsys), state); ++ ++ if (cur_power_state != pre_power_state) { ++ sdio_dbg("%s, power state change to %d dure to %s\n", __func__, cur_power_state, aicbsp_subsys_name(subsys)); ++ if (cur_power_state) { ++ if (aicbsp_platform_power_on() < 0) ++ goto err0; ++ if (aicbsp_sdio_init()) ++ goto err1; ++ if (aicbsp_driver_fw_init(aicbsp_sdiodev)) ++ goto err2; ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ aicbsp_sdio_release(aicbsp_sdiodev); ++#endif ++ ++#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(true); ++ printk("%s BT wake default to SLEEP\r\n", __func__); ++#endif ++#endif ++ ++//#ifndef CONFIG_PLATFORM_ROCKCHIP ++// aicbsp_sdio_exit(); ++//#endif ++ } else { ++ #ifndef CONFIG_PLATFORM_ROCKCHIP ++ aicbsp_sdio_exit(); ++ #endif ++ aicbsp_platform_power_off(); ++ } ++ } else { ++ sdio_dbg("%s, power state no need to change, current: %d\n", __func__, cur_power_state); ++ } ++ pre_power_map = cur_power_map; ++ mutex_unlock(&aicbsp_power_lock); ++ ++ return cur_power_state; ++ ++err2: ++ aicbsp_sdio_release(aicbsp_sdiodev); ++ aicbsp_sdio_exit(); ++ ++err1: ++ aicbsp_platform_power_off(); ++ ++err0: ++ sdio_dbg("%s, fail to set %s power state to %d\n", __func__, aicbsp_subsys_name(subsys), state); ++ mutex_unlock(&aicbsp_power_lock); ++ return -1; ++} ++EXPORT_SYMBOL_GPL(aicbsp_set_subsys); ++ ++bool aicbsp_get_load_fw_in_fdrv(void){ ++ return aicbsp_load_fw_in_fdrv; ++} ++ ++EXPORT_SYMBOL_GPL(aicbsp_get_load_fw_in_fdrv); ++ ++static int aicwf_sdio_chipmatch(struct aic_sdio_dev *sdio_dev, uint16_t vid, uint16_t did){ ++ ++ if(vid == SDIO_VENDOR_ID_AIC8801 && did == SDIO_DEVICE_ID_AIC8801){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8801; ++ AICWFDBG(LOGINFO, "%s USE AIC8801\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800DC && did == SDIO_DEVICE_ID_AIC8800DC){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800DC; ++ AICWFDBG(LOGINFO, "%s USE AIC8800DC\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80 && did == SDIO_DEVICE_ID_AIC8800D80){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80X2 && did == SDIO_DEVICE_ID_AIC8800D80X2){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80X2; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80X2\r\n", __func__); ++ return 0; ++ }else{ ++ return -1; ++ } ++} ++ ++void *aicbsp_get_drvdata(void *args) ++{ ++ (void)args; ++ if (aicbsp_sdiodev) ++ return aicbsp_sdiodev->bus_if; ++ return dev_get_drvdata((const struct device *)args); ++} ++ ++ ++static int aicbsp_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ struct mmc_host *host; ++ struct aic_sdio_dev *sdiodev; ++ struct aicwf_bus *bus_if; ++ int err = -ENODEV; ++ ++ if (func == NULL) { ++ sdio_err("%s func is null\n", __func__); ++ return err; ++ } ++ ++ sdio_dbg("%s:%d vid:0x%04X did:0x%04X\n", __func__, func->num, ++ func->vendor, func->device); ++ ++ if(func->vendor != SDIO_VENDOR_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801 && ++ func->device != SDIO_DEVICE_ID_AIC8801_FUNC2 && ++ func->vendor != SDIO_VENDOR_ID_AIC8800DC && ++ func->device != SDIO_DEVICE_ID_AIC8800DC && ++ func->vendor != SDIO_VENDOR_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80 && ++ func->device != SDIO_DEVICE_ID_AIC8800D80_FUNC2){ ++ aicbsp_load_fw_in_fdrv = true; ++ return err; ++ } ++ ++ if (func->num != 2) { ++ return err; ++ } ++ ++ host = func->card->host; ++ host->caps |= MMC_CAP_NONREMOVABLE; ++ ++ func = func->card->sdio_func[1 - 1]; //replace 2 with 1 ++ ++ sdio_dbg("%s after replace:%d\n", __func__, func->num); ++ ++ bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_KERNEL); ++ if (!bus_if) { ++ sdio_err("alloc bus fail\n"); ++ return -ENOMEM; ++ } ++ ++ ++ sdiodev = kzalloc(sizeof(struct aic_sdio_dev), GFP_KERNEL); ++ if (!sdiodev) { ++ sdio_err("alloc sdiodev fail\n"); ++ kfree(bus_if); ++ return -ENOMEM; ++ } ++ aicbsp_sdiodev = sdiodev; ++ ++ err = aicwf_sdio_chipmatch(sdiodev, func->vendor, func->device); ++ ++ sdiodev->func = func; ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdiodev->func_msg = func->card->sdio_func[1]; ++ } ++ sdiodev->bus_if = bus_if; ++ bus_if->bus_priv.sdio = sdiodev; ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ dev_set_drvdata(&sdiodev->func_msg->dev, bus_if); ++ printk("the device is PRODUCT_ID_AIC8800DC \n"); ++ } ++ dev_set_drvdata(&func->dev, bus_if); ++ sdiodev->dev = &func->dev; ++ ++ if (sdiodev->chipid != PRODUCT_ID_AIC8800D80 && sdiodev->chipid != PRODUCT_ID_AIC8800D80X2) { ++ err = aicwf_sdio_func_init(sdiodev); ++ } else { ++ err = aicwf_sdiov3_func_init(sdiodev); ++ } ++ if (err < 0) { ++ sdio_err("sdio func init fail\n"); ++ goto fail; ++ } ++ ++ if (aicwf_sdio_bus_init(sdiodev) == NULL) { ++ sdio_err("sdio bus init err\r\n"); ++ goto fail; ++ } ++ ++ aicbsp_platform_init(sdiodev); ++ ++ up(&aicbsp_probe_semaphore); ++ ++ return 0; ++fail: ++ aicwf_sdio_func_deinit(sdiodev); ++ dev_set_drvdata(&func->dev, NULL); ++ kfree(sdiodev); ++ kfree(bus_if); ++ return err; ++} ++ ++ ++static void aicbsp_sdio_remove(struct sdio_func *func) ++{ ++ struct mmc_host *host; ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_sdio_dev *sdiodev = NULL; ++ ++ AICWFDBG(LOGINFO, "%s\n", __func__); ++ if (aicbsp_sdiodev == NULL) { ++ AICWFDBG(LOGERROR, "%s: allready unregister\n", __func__); ++ goto done; ++ } ++ if (func == NULL) { ++ AICWFDBG(LOGERROR, "%s, sdio func is null\n", __func__); ++ goto done; ++ } ++ ++ host = func->card->host; ++ host->caps &= ~MMC_CAP_NONREMOVABLE; ++ ++ bus_if = aicbsp_get_drvdata(&func->dev); ++ ++ if (!bus_if) { ++ AICWFDBG(LOGERROR, "%s bus_if is NULL \r\n", __func__); ++ goto done; ++ } ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ if (!sdiodev) { ++ AICWFDBG(LOGERROR, "%s sdiodev is NULL \r\n", __func__); ++ goto done; ++ } ++ ++ aicwf_sdio_release(sdiodev); ++ aicwf_sdio_func_deinit(sdiodev); ++ ++ dev_set_drvdata(&sdiodev->func->dev, NULL); ++ kfree(sdiodev); ++ ++done: ++ if (bus_if) ++ kfree(bus_if); ++ aicbsp_sdiodev = NULL; ++ sdio_dbg("%s done\n", __func__); ++} ++ ++ ++static int aicbsp_sdio_suspend(struct device *dev) ++{ ++ struct sdio_func *func = dev_to_sdio_func(dev); ++ int err; ++ mmc_pm_flag_t sdio_flags; ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(false); ++#endif ++#endif ++ ++ sdio_dbg("%s, func->num = %d\n", __func__, func->num); ++ if (func->num != 2) ++ return 0; ++ ++ sdio_flags = sdio_get_host_pm_caps(func); ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ sdio_dbg("%s: can't keep power while host is suspended\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* keep power while host suspended */ ++ err = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); ++ if (err) { ++ sdio_dbg("%s: error while trying to keep power\n", __func__); ++ return err; ++ } ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(true); ++ printk("%s BT wake to SLEEP\r\n", __func__); ++#endif ++#endif ++ ++ return 0; ++} ++ ++static int aicbsp_sdio_resume(struct device *dev) ++{ ++ sdio_dbg("%s\n", __func__); ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_GPIO_WAKEUP ++ //BT_SLEEP:true,BT_WAKEUP:false ++ rfkill_rk_sleep_bt(false); ++#endif ++#endif ++ ++ return 0; ++} ++ ++static const struct sdio_device_id aicbsp_sdmmc_ids[] = { ++ {SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN)}, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(sdio, aicbsp_sdmmc_ids); ++ ++static const struct dev_pm_ops aicbsp_sdio_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(aicbsp_sdio_suspend, aicbsp_sdio_resume) ++}; ++ ++static struct sdio_driver aicbsp_sdio_driver = { ++ .probe = aicbsp_sdio_probe, ++ .remove = aicbsp_sdio_remove, ++ .name = AICBSP_SDIO_NAME, ++ .id_table = aicbsp_sdmmc_ids, ++ .drv = { ++ .pm = &aicbsp_sdio_pm_ops, ++ }, ++}; ++ ++static int aicbsp_platform_power_on(void) ++{ ++ int ret = 0; ++ struct semaphore aic_chipup_sem; ++ sdio_dbg("%s\n", __func__); ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ if (aicbsp_bus_index < 0) ++ aicbsp_bus_index = sunxi_wlan_get_bus_index(); ++ if (aicbsp_bus_index < 0) ++ return aicbsp_bus_index; ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++ mdelay(200); ++ extern_wifi_set_enable(1); ++ mdelay(200); ++ sdio_reinit(); ++ set_power_control_lock(1); ++#endif ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ rockchip_wifi_power(0); ++ mdelay(50); ++ rockchip_wifi_power(1); ++ mdelay(50); ++ rockchip_wifi_set_carddetect(1); ++#endif /*CONFIG_PLATFORM_ROCKCHIP2*/ ++ ++ sema_init(&aic_chipup_sem, 0); ++ ret = aicbsp_reg_sdio_notify(&aic_chipup_sem); ++ if (ret) { ++ sdio_dbg("%s aicbsp_reg_sdio_notify fail(%d)\n", __func__, ret); ++ return ret; ++ } ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ sunxi_wlan_set_power(0); ++ mdelay(50); ++ sunxi_wlan_set_power(1); ++ mdelay(50); ++ sunxi_mmc_rescan_card(aicbsp_bus_index); ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++ if (down_timeout(&aic_chipup_sem, msecs_to_jiffies(2000)) == 0) { ++ aicbsp_unreg_sdio_notify(); ++ if(aicbsp_load_fw_in_fdrv){ ++ printk("%s load fw in fdrv\r\n", __func__); ++ return -1; ++ } ++ return 0; ++ } ++ ++ aicbsp_unreg_sdio_notify(); ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ sunxi_wlan_set_power(0); ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++#endif ++ ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ rockchip_wifi_power(0); ++#endif /*CONFIG_PLATFORM_ROCKCHIP2*/ ++ ++ return -1; ++} ++ ++static void aicbsp_platform_power_off(void) ++{ ++//TODO wifi disable and sdio card detection ++#ifdef CONFIG_PLATFORM_ALLWINNER ++ if (aicbsp_bus_index < 0) ++ aicbsp_bus_index = sunxi_wlan_get_bus_index(); ++ if (aicbsp_bus_index < 0) { ++ sdio_dbg("no aicbsp_bus_index\n"); ++ return; ++ } ++ sunxi_wlan_set_power(0); ++ mdelay(100); ++ sunxi_mmc_rescan_card(aicbsp_bus_index); ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ rockchip_wifi_set_carddetect(0); ++ mdelay(200); ++ rockchip_wifi_power(0); ++ mdelay(200); ++#endif /*CONFIG_PLATFORM_ROCKCHIP*/ ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++#endif ++ ++ ++ sdio_dbg("%s\n", __func__); ++} ++ ++ ++int aicbsp_sdio_init(void) ++{ ++ ++ if (sdio_register_driver(&aicbsp_sdio_driver)) { ++ return -1; ++ } else { ++ //may add mmc_rescan here ++ } ++ if (down_timeout(&aicbsp_probe_semaphore, msecs_to_jiffies(2000)) != 0){ ++ printk("%s aicbsp_sdio_probe fail\r\n", __func__); ++ return -1; ++ } ++ ++ ++ return 0; ++} ++ ++void aicbsp_sdio_exit(void) ++{ ++ sdio_unregister_driver(&aicbsp_sdio_driver); ++} ++ ++void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev) ++{ ++ sdiodev->bus_if->state = BUS_DOWN_ST; ++ sdio_claim_host(sdiodev->func); ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func_msg); ++ sdio_release_irq(sdiodev->func_msg); ++ sdio_release_host(sdiodev->func_msg); ++ } ++} ++ ++int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ *val = sdio_readb(sdiodev->func, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_readb_func2(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func_msg); ++ *val = sdio_readb(sdiodev->func_msg, regaddr, &ret); ++ sdio_release_host(sdiodev->func_msg); ++ return ret; ++} ++ ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ sdio_writeb(sdiodev->func, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_writeb_func2(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func_msg); ++ sdio_writeb(sdiodev->func_msg, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func_msg); ++ return ret; ++} ++ ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = -1; ++ u8 fc_reg = 0; ++ u32 count = 0; ++ ++ while (true) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.flow_ctrl_reg, &fc_reg); ++ if (ret) { ++ return -1; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ fc_reg = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; ++ } ++ ++ if (fc_reg != 0) { ++ ret = fc_reg; ++ return ret; ++ } else { ++ if (count >= FLOW_CTRL_RETRY_COUNT) { ++ ret = -fc_reg; ++ break; ++ } ++ count++; ++ if (count < 30) ++ udelay(200); ++ else if (count < 40) ++ mdelay(1); ++ else ++ mdelay(10); ++ } ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_send_msg(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) ++{ ++ int ret = 0; ++ ++ sdio_claim_host(sdiodev->func_msg); ++ ret = sdio_writesb(sdiodev->func_msg, 7, buf, count); ++ sdio_release_host(sdiodev->func_msg); ++ ++ return ret; ++} ++ ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) ++{ ++ int ret = 0; ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, buf, count); ++ sdio_release_host(sdiodev->func); ++ ++ return ret; ++} ++ ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, ++ u32 size, u8 msg) ++{ ++ int ret; ++ ++ if ((!skbbuf) || (!size)) { ++ return -EINVAL;; ++ } ++ ++ if(!msg) { ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_readsb(sdiodev->func, skbbuf->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func); ++ } else { ++ sdio_claim_host(sdiodev->func_msg); ++ ret = sdio_readsb(sdiodev->func_msg, skbbuf->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func_msg); ++ } ++ ++ ++ if (ret < 0) { ++ return ret; ++ } ++ skbbuf->len = size; ++ ++ return ret; ++} ++ ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++int aicwf_sdio_wakeup(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ int read_retry; ++ int write_retry = 20; ++ int wakeup_reg_val = 0; ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ wakeup_reg_val = 1; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ wakeup_reg_val = 0x11; ++ } ++ ++ if (sdiodev->state == SDIO_SLEEP_ST) { ++ //if (sdiodev->rwnx_hw->vif_started) { ++ down(&sdiodev->pwrctl_wakeup_sema); ++ while (write_retry) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, wakeup_reg_val); ++ if (ret) { ++ txrx_err("sdio wakeup fail\n"); ++ ret = -1; ++ } else { ++ read_retry = 10; ++ while (read_retry) { ++ u8 val; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val); ++ if ((ret == 0) && (val & 0x10)) { ++ break; ++ } ++ read_retry--; ++ udelay(200); ++ } ++ if (read_retry != 0) ++ break; ++ } ++ sdio_dbg("write retry: %d \n", write_retry); ++ write_retry--; ++ udelay(100); ++ } ++ up(&sdiodev->pwrctl_wakeup_sema); ++ // } ++ } ++ ++ sdiodev->state = SDIO_ACTIVE_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ ++ return ret; ++} ++ ++extern u8 dhcped; ++int aicwf_sdio_sleep_allow(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = sdiodev->bus_if; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, 0x10); ++ if (ret) { ++ sdio_err("Write sleep fail!\n"); ++ } ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ return ret; ++ } ++ ++ if (sdiodev->state == SDIO_ACTIVE_ST) { ++ { ++ sdio_dbg("s\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, 0x10); ++ if (ret) ++ sdio_err("Write sleep fail!\n"); ++ } ++ sdiodev->state = SDIO_SLEEP_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ } else { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target) ++{ ++ int ret = 0; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ return -1; ++ } ++ ++ if (sdiodev->state == target) { ++ if (target == SDIO_ACTIVE_ST) { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ return ret; ++ } ++ ++ switch (target) { ++ case SDIO_ACTIVE_ST: ++ aicwf_sdio_wakeup(sdiodev); ++ break; ++ case SDIO_SLEEP_ST: ++ aicwf_sdio_sleep_allow(sdiodev); ++ break; ++ } ++ ++ return ret; ++} ++#endif ++ ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++{ ++ int ret = 0; ++ u8 *frame; ++ u32 len = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("tx bus is down!\n"); ++ return -EINVAL; ++ } ++ ++ frame = (u8 *) (pkt->data); ++ len = pkt->len; ++ len = (len + SDIOWIFI_FUNC_BLOCKSIZE - 1) / SDIOWIFI_FUNC_BLOCKSIZE * SDIOWIFI_FUNC_BLOCKSIZE; ++ ret = aicwf_sdio_send_pkt(sdiodev, pkt->data, len); ++ if (ret) ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", ret); ++ ++ return ret; ++} ++ ++static int aicwf_sdio_intr_get_len_bytemode(struct aic_sdio_dev *sdiodev, u8 *byte_len) ++{ ++ int ret = 0; ++ ++ if (!byte_len) ++ return -EBADE; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ *byte_len = 0; ++ } else { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.bytemode_len_reg, byte_len); ++ sdiodev->rx_priv->data_len = (*byte_len)*4; ++ } ++ ++ return ret; ++} ++ ++static void aicwf_sdio_bus_stop(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = aicbsp_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret; ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ sdio_dbg("%s\n", __func__); ++ if (sdiodev->pwrctl_tsk) { ++ complete_all(&sdiodev->pwrctrl_trgg); ++ kthread_stop(sdiodev->pwrctl_tsk); ++ sdiodev->pwrctl_tsk = NULL; ++ } ++#endif ++ bus_if->state = BUS_DOWN_ST; ++ ret = down_interruptible(&sdiodev->tx_priv->txctl_sema); ++ if (ret) ++ sdio_err("down txctl_sema fail\n"); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++#endif ++ if (!ret) ++ up(&sdiodev->tx_priv->txctl_sema); ++ aicwf_frame_queue_flush(&sdiodev->tx_priv->txq); ++} ++ ++struct sk_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev, u8 msg) ++{ ++ int ret = 0; ++ u32 size = 0; ++ struct sk_buff *skb = NULL; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("bus down\n"); ++ return NULL; ++ } ++ ++ size = sdiodev->rx_priv->data_len; ++ skb = __dev_alloc_skb(size, GFP_KERNEL); ++ if (!skb) { ++ return NULL; ++ } ++ ++ ret = aicwf_sdio_recv_pkt(sdiodev, skb, size, msg); ++ if (ret) { ++ dev_kfree_skb(skb); ++ skb = NULL; ++ } ++ ++ return skb; ++} ++ ++static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++ u16 len; ++ u8 *payload = sdiodev->tx_priv->cmd_buf; ++ u16 payload_len = sdiodev->tx_priv->cmd_len; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ int adjust_len = 0; ++ int buffer_cnt = 0; ++ u8 retry = 0; ++ ++ len = payload_len; ++ if ((len % TX_ALIGNMENT) != 0) { ++ adjust_len = roundup(len, TX_ALIGNMENT); ++ memcpy(payload+payload_len, adjust_str, (adjust_len - len)); ++ payload_len += (adjust_len - len); ++ } ++ len = payload_len; ++ ++ //link tail is necessary ++ if ((len % SDIOWIFI_FUNC_BLOCKSIZE) != 0) { ++ memset(payload+payload_len, 0, TAIL_LEN); ++ payload_len += TAIL_LEN; ++ len = (payload_len/SDIOWIFI_FUNC_BLOCKSIZE + 1) * SDIOWIFI_FUNC_BLOCKSIZE; ++ } else ++ len = payload_len; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); ++ while ((buffer_cnt <= 0 || (buffer_cnt > 0 && len > (buffer_cnt * BUFFER_SIZE))) && retry < 10) { ++ retry++; ++ buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); ++ printk("buffer_cnt = %d\n", buffer_cnt); ++ } ++ } ++ down(&sdiodev->tx_priv->cmd_txsema); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if (buffer_cnt > 0 && len < (buffer_cnt * BUFFER_SIZE)) { ++ err = aicwf_sdio_send_pkt(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ err = aicwf_sdio_send_msg(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ ++ sdiodev->tx_priv->cmd_txstate = false; ++ if (!err) ++ sdiodev->tx_priv->cmd_tx_succ = true; ++ else ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ return err; ++} ++ ++static void aicwf_sdio_tx_process(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("Bus is down\n"); ++ return; ++ } ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++#endif ++ ++ //config ++ sdio_info("send cmd\n"); ++ if (sdiodev->tx_priv->cmd_txstate) { ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txctl down bus->txctl_sema fail\n"); ++ return; ++ } ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ txrx_err("txctl up bus->txctl_sema fail\n"); ++ return; ++ } ++ ++ err = aicwf_sdio_tx_msg(sdiodev); ++ up(&sdiodev->tx_priv->txctl_sema); ++ if (waitqueue_active(&sdiodev->tx_priv->cmd_txdone_wait)) ++ wake_up(&sdiodev->tx_priv->cmd_txdone_wait); ++ } ++ ++ //data ++ sdio_info("send data\n"); ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txdata down bus->txctl_sema\n"); ++ return; ++ } ++ ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("sdio state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ return; ++ } ++ ++ if(!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) ++ sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ while (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) { ++ aicwf_sdio_send(sdiodev->tx_priv); ++ if (sdiodev->tx_priv->cmd_txstate) ++ break; ++ } ++ ++ up(&sdiodev->tx_priv->txctl_sema); ++} ++ ++static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) ++{ ++ uint prio; ++ int ret = -EBADE; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ prio = (pkt->priority & 0x7); ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ if (!aicwf_frame_enq(sdiodev->dev, &sdiodev->tx_priv->txq, pkt, prio)) { ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return -ENOSR; ++ } else { ++ ret = 0; ++ } ++ ++ if (bus_if->state != BUS_UP_ST) { ++ sdio_err("bus_if stopped\n"); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return -1; ++ } ++ ++ atomic_inc(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ complete(&bus_if->bustx_trgg); ++ ++ return ret; ++} ++ ++static int aicwf_sdio_bus_txmsg(struct device *dev, u8 *msg, uint msglen) ++{ ++ int ret = -1; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ down(&sdiodev->tx_priv->cmd_txsema); ++ sdiodev->tx_priv->cmd_txstate = true; ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ sdiodev->tx_priv->cmd_buf = msg; ++ sdiodev->tx_priv->cmd_len = msglen; ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ if (bus_if->state != BUS_UP_ST) { ++ sdio_err("bus has stop\n"); ++ return -1; ++ } ++ ++ complete(&bus_if->bustx_trgg); ++ ++ if (sdiodev->tx_priv->cmd_txstate) { ++ int timeout = msecs_to_jiffies(CMD_TX_TIMEOUT); ++ ret = wait_event_timeout(sdiodev->tx_priv->cmd_txdone_wait, \ ++ !(sdiodev->tx_priv->cmd_txstate), timeout); ++ } ++ ++ if (!sdiodev->tx_priv->cmd_txstate && sdiodev->tx_priv->cmd_tx_succ) { ++ ret = 0; ++ } else { ++ sdio_err("send faild:%d, %d,%x\n", sdiodev->tx_priv->cmd_txstate, sdiodev->tx_priv->cmd_tx_succ, ret); ++ ret = -EIO; ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv) ++{ ++ struct sk_buff *pkt; ++ struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; ++ u16 aggr_len = 0; ++ int retry_times = 0; ++ int max_retry_times = 5; ++ ++ aggr_len = (tx_priv->tail - tx_priv->head); ++ if (((atomic_read(&tx_priv->aggr_count) == 0) && (aggr_len != 0)) ++ || ((atomic_read(&tx_priv->aggr_count) != 0) && (aggr_len == 0))) { ++ if (aggr_len > 0) ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++ goto done; ++ } ++ ++ if (tx_priv->fw_avail_bufcnt <= 0) { //flow control failed ++ tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ while (tx_priv->fw_avail_bufcnt <= 0 && retry_times < max_retry_times) { ++ retry_times++; ++ tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ } ++ if (tx_priv->fw_avail_bufcnt <= 0) { ++ sdio_err("fc retry %d fail\n", tx_priv->fw_avail_bufcnt); ++ goto done; ++ } ++ } ++ ++ if (atomic_read(&tx_priv->aggr_count) == tx_priv->fw_avail_bufcnt) { ++ if (atomic_read(&tx_priv->aggr_count) > 0) { ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); //send and check the next pkt; ++ } ++ } else { ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ pkt = aicwf_frame_dequeue(&sdiodev->tx_priv->txq); ++ if (pkt == NULL) { ++ sdio_err("txq no pkt\n"); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ goto done; ++ } ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ ++ if (tx_priv == NULL || tx_priv->tail == NULL || pkt == NULL) ++ txrx_err("null error\n"); ++ if (aicwf_sdio_aggr(tx_priv, pkt)) { ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++ sdio_err("add aggr pkts failed!\n"); ++ goto done; ++ } ++ ++ //when aggr finish or there is cmd to send, just send this aggr pkt to fw ++ if ((int)atomic_read(&sdiodev->tx_priv->tx_pktcnt) == 0 || sdiodev->tx_priv->cmd_txstate) { //no more pkt send it! ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); ++ } else ++ goto done; ++ } ++ ++done: ++ return 0; ++} ++ ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt) ++{ ++ //struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; ++ u8 *start_ptr = tx_priv->tail; ++ u8 sdio_header[4]; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ u16 curr_len = 0; ++ int allign_len = 0; ++ ++ //sdio_header[0] =((pkt->len - sizeof(struct rwnx_txhdr) + sizeof(struct txdesc_api)) & 0xff); ++ //sdio_header[1] =(((pkt->len - sizeof(struct rwnx_txhdr) + sizeof(struct txdesc_api)) >> 8)&0x0f); ++ sdio_header[2] = 0x01; //data ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ sdio_header[3] = 0; //reserved ++ else if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ sdio_header[3] = crc8_ponl_107(&sdio_header[0], 3); // crc8 ++ ++ memcpy(tx_priv->tail, (u8 *)&sdio_header, sizeof(sdio_header)); ++ tx_priv->tail += sizeof(sdio_header); ++ //payload ++ //memcpy(tx_priv->tail, (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ //tx_priv->tail += sizeof(struct txdesc_api); //hostdesc ++ //memcpy(tx_priv->tail, (u8 *)((u8 *)txhdr + txhdr->sw_hdr->headroom), pkt->len-txhdr->sw_hdr->headroom); ++ //tx_priv->tail += (pkt->len - txhdr->sw_hdr->headroom); ++ ++ //word alignment ++ curr_len = tx_priv->tail - tx_priv->head; ++ if (curr_len & (TX_ALIGNMENT - 1)) { ++ allign_len = roundup(curr_len, TX_ALIGNMENT)-curr_len; ++ memcpy(tx_priv->tail, adjust_str, allign_len); ++ tx_priv->tail += allign_len; ++ } ++ ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ start_ptr[0] = ((tx_priv->tail - start_ptr - 4) & 0xff); ++ start_ptr[1] = (((tx_priv->tail - start_ptr - 4)>>8) & 0x0f); ++ } ++ ++ tx_priv->aggr_buf->dev = pkt->dev; ++ ++ #if 0 ++ if (!txhdr->sw_hdr->need_cfm) { ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, txhdr->sw_hdr->headroom); ++ consume_skb(pkt); ++ } ++ #endif ++ ++ consume_skb(pkt); ++ atomic_inc(&tx_priv->aggr_count); ++ return 0; ++} ++ ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv) ++{ ++ struct sk_buff *tx_buf = tx_priv->aggr_buf; ++ int ret = 0; ++ int curr_len = 0; ++ ++ //link tail is necessary ++ curr_len = tx_priv->tail - tx_priv->head; ++ if ((curr_len % TXPKT_BLOCKSIZE) != 0) { ++ memset(tx_priv->tail, 0, TAIL_LEN); ++ tx_priv->tail += TAIL_LEN; ++ } ++ ++ tx_buf->len = tx_priv->tail - tx_priv->head; ++ ret = aicwf_sdio_txpkt(tx_priv->sdiodev, tx_buf); ++ if (ret < 0) { ++ sdio_err("fail to send aggr pkt!\n"); ++ } ++ ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++} ++ ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv) ++{ ++ struct sk_buff *aggr_buf = tx_priv->aggr_buf; ++ ++ tx_priv->tail = tx_priv->head; ++ aggr_buf->len = 0; ++ atomic_set(&tx_priv->aggr_count, 0); ++} ++ ++static int aicwf_sdio_bus_start(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ sdio_claim_host(sdiodev->func); ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ sdio_release_host(sdiodev->func); ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func); ++ ++ //since we have func2 we don't register irq handler ++ sdio_claim_irq(sdiodev->func, NULL); ++ sdio_claim_irq(sdiodev->func_msg, NULL); ++ ++ sdiodev->func->irq_handler = (sdio_irq_handler_t *)aicwf_sdio_hal_irqhandler; ++ sdiodev->func_msg->irq_handler = (sdio_irq_handler_t *)aicwf_sdio_hal_irqhandler_func2; ++ sdio_release_host(sdiodev->func); ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ ++ if (ret != 0) ++ sdio_err("func2 intr register failed:%d\n", ret); ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdio_claim_host(sdiodev->func); ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++ ++ sdio_f0_writeb(sdiodev->func, 0x07, 0x04, &ret); ++ if (ret) { ++ sdio_err("set func0 int en fail %d\n", ret); ++ } ++ sdio_release_host(sdiodev->func); ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ } ++ ++ bus_if->state = BUS_UP_ST; ++ return ret; ++} ++ ++int aicwf_sdio_bustx_thread(void *data) ++{ ++ struct aicwf_bus *bus = (struct aicwf_bus *) data; ++ struct aic_sdio_dev *sdiodev = bus->bus_priv.sdio; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ sdio_err("sdio bustx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) > 0) || (sdiodev->tx_priv->cmd_txstate == true)) ++ aicwf_sdio_tx_process(sdiodev); ++ } ++ } ++ ++ return 0; ++} ++ ++int aicwf_sdio_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ sdio_err("sdio busrx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ aicwf_process_rxframes(rx_priv); ++ } ++ } ++ ++ return 0; ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static void aicwf_sdio_bus_pwrctl(struct timer_list *t) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ struct aic_sdio_dev *sdiodev = timer_container_of(sdiodev, t, timer); ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, timer); ++#endif ++#else ++static void aicwf_sdio_bus_pwrctl(ulong data) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#endif ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus down\n"); ++ return; ++ } ++ ++ if (sdiodev->pwrctl_tsk) { ++ complete(&sdiodev->pwrctrl_trgg); ++ } ++} ++#endif ++ ++static void aicwf_sdio_enq_rxpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++{ ++ struct aicwf_rx_priv *rx_priv = sdiodev->rx_priv; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (!aicwf_rxframe_enqueue(sdiodev->dev, &rx_priv->rxq, pkt)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ aicwf_dev_skb_free(pkt); ++ return; ++ } ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ ++ atomic_inc(&rx_priv->rx_cnt); ++} ++ ++#define SDIO_OTHER_INTERRUPT (0x1ul << 7) ++ ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(&func->dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ u8 intstatus = 0; ++ u8 byte_len = 0; ++ struct sk_buff *pkt = NULL; ++ int ret; ++ ++ //AICWFDBG(LOGDEBUG,"%s bsp enter \r\n", __func__); ++ ++ if(aicbsp_sdiodev->sdio_hal_irqhandler){ ++ aicbsp_sdiodev->sdio_hal_irqhandler(func); ++ return; ++ } ++ ++ if (!bus_if || bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus err\n"); ++ return; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ ++ while(intstatus){ ++ sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; ++ if (intstatus > 0) { ++ if(intstatus < 64) { ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } else { ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ } ++ }else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ do { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.misc_int_status_reg, &intstatus); ++ if (!ret) { ++ break; ++ } ++ sdio_err("ret=%d, intstatus=%x\r\n",ret, intstatus); ++ } while (1); ++ if (intstatus & SDIO_OTHER_INTERRUPT) { ++ u8 int_pending; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ int_pending &= ~0x01; // dev to host soft irq ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ } ++ ++ if (intstatus > 0) { ++ uint8_t intmaskf2 = intstatus | (0x1UL << 3); ++ if (intmaskf2 > 120U) { // func2 ++ if (intmaskf2 == 127U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 1);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev, 1); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7U) * SDIOWIFI_FUNC_BLOCKSIZE; ++ pkt = aicwf_sdio_readframes(sdiodev, 1); ++ } ++ } else { // func1 ++ if (intstatus == 120U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 0);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7FU) * SDIOWIFI_FUNC_BLOCKSIZE; ++ pkt = aicwf_sdio_readframes(sdiodev, 0); ++ } ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ } ++ ++ complete(&bus_if->busrx_trgg); ++} ++ ++void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(&func->dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ u8 intstatus = 0; ++ u8 byte_len = 0; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_buff *pkt = NULL; ++ #else ++ struct sk_buff *pkt = NULL; ++ #endif ++ int ret; ++ ++ if (!bus_if || bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus err\n"); ++ return; ++ } ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ if (list_empty(&aic_rx_buff_list.rxbuff_list)) { ++ printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); ++ return; ++ } ++ #endif ++ ++ ret = aicwf_sdio_readb_func2(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ ++ while(intstatus) { ++ sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; ++ if (intstatus > 0) { ++ if(intstatus < 64) { ++ pkt = aicwf_sdio_readframes(sdiodev,1); ++ } else { ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ pkt = aicwf_sdio_readframes(sdiodev,1); ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt){ ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ } ++ ret = aicwf_sdio_readb_func2(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ } ++ ++ complete(&bus_if->busrx_trgg); ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration) ++{ ++ uint timeout; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST && duration) ++ return; ++ ++ spin_lock_bh(&sdiodev->pwrctl_lock); ++ if (!duration) { ++ if (timer_pending(&sdiodev->timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&sdiodev->timer); ++#else ++ del_timer_sync(&sdiodev->timer); ++#endif ++ } else { ++ sdiodev->active_duration = duration; ++ timeout = msecs_to_jiffies(sdiodev->active_duration); ++ mod_timer(&sdiodev->timer, jiffies + timeout); ++ } ++ spin_unlock_bh(&sdiodev->pwrctl_lock); ++} ++#endif ++ ++static struct aicwf_bus_ops aicwf_sdio_bus_ops = { ++ .stop = aicwf_sdio_bus_stop, ++ .start = aicwf_sdio_bus_start, ++ .txdata = aicwf_sdio_bus_txdata, ++ .txmsg = aicwf_sdio_bus_txmsg, ++}; ++ ++void aicwf_sdio_release_func2(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ sdio_dbg("%s\n", __func__); ++ sdio_claim_host(sdiodev->func_msg); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); ++ } ++ sdio_release_irq(sdiodev->func_msg); ++ sdio_release_host(sdiodev->func_msg); ++ ++} ++ ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) ++{ ++ struct aicwf_bus *bus_if = NULL; ++ struct aicwf_bus *bus_if_t = NULL; ++ int ret = 0; ++ ++ sdio_dbg("%s\n", __func__); ++ if (sdiodev->func == NULL) { ++ printk("%s, NULL sdio func\n", __func__); ++ return; ++ } ++ ++ bus_if = aicbsp_get_drvdata(sdiodev->dev); ++ if (bus_if) ++ bus_if->state = BUS_DOWN_ST; ++ ++ bus_if_t = dev_get_drvdata(sdiodev->dev); ++ ++ if ((bus_if_t != NULL) && (sdiodev->bus_if == bus_if_t)) { ++ sdio_dbg("%s bsp release\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!, ret=%d\n", sdiodev->sdio_reg.intr_config_reg, ret); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ aicwf_sdio_release_func2(sdiodev); ++ } ++ ++ if (sdiodev->dev) ++ aicwf_bus_deinit(sdiodev->dev); ++ ++ if (sdiodev->tx_priv) ++ aicwf_tx_deinit(sdiodev->tx_priv); ++ ++ if (sdiodev->rx_priv) ++ aicwf_rx_deinit(sdiodev->rx_priv); ++ ++ rwnx_cmd_mgr_deinit(&sdiodev->cmd_mgr); ++} ++ ++ ++ ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev) ++{ ++ sdio_dbg("%s\n", __func__); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_CONFIG_REG; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_SLEEP_REG; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_WAKEUP_REG; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_REG; ++ sdiodev->sdio_reg.register_block = SDIOWIFI_REGISTER_BLOCK; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG; ++ sdiodev->sdio_reg.block_cnt_reg = SDIOWIFI_BLOCK_CNT_REG; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG_V3; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_ENABLE_REG_V3; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_INTR_PENDING_REG_V3; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_INTR_TO_DEVICE_REG_V3; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_Q1_REG_V3; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG_V3; ++ sdiodev->sdio_reg.misc_int_status_reg = SDIOWIFI_MISC_INT_STATUS_REG_V3; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR_V3; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR_V3; ++ } ++} ++ ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 block_bit0 = 0x1; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ struct aicbsp_feature_t feature; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++#if 0//SDIO PHASE SETTING ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ sdio_f0_writeb(sdiodev->func, feature.sdio_phase, 0x13, &ret); ++ if (ret < 0) { ++ sdio_err("write func0 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#endif ++ ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ sdio_err("set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_err("enable func fail %d.\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ udelay(100); ++#if 1//SDIO CLOCK SETTING ++ if (feature.sdio_clock > 0) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++ sdio_release_host(sdiodev->func); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ ++ sdio_claim_host(sdiodev->func_msg); ++ ++ //set sdio blocksize ++ ret = sdio_set_block_size(sdiodev->func_msg, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set func2 blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func_msg); ++ return ret; ++ } ++ ++ //set sdio enable func ++ ret = sdio_enable_func(sdiodev->func_msg); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "enable func2 fail %d.\n", ret); ++ } ++ ++ sdio_release_host(sdiodev->func_msg); ++ ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb_func2(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ } ++ ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ //u8 val; ++ struct aicbsp_feature_t feature; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ sdio_err("set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_err("enable func fail %d.\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ++ sdio_f0_writeb(sdiodev->func, 0x7F, 0xF2, &ret); ++ if (ret) { ++ sdio_err("set fn0 0xF2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#if 0 ++ if (host->ios.timing == MMC_TIMING_UHS_DDR50) { ++ val = 0x21;//0x1D;//0x5; ++ } else { ++ val = 0x01;//0x19;//0x1; ++ } ++ val |= SDIOCLK_FREE_RUNNING_BIT; ++ sdio_f0_writeb(sdiodev->func, val, 0xF0, &ret); ++ if (ret) { ++ sdio_err("set iopad ctrl fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x0, 0xF8, &ret); ++ if (ret) { ++ sdio_err("set iopad delay2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x40, 0xF1, &ret); ++ if (ret) { ++ sdio_err("set iopad delay1 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ msleep(1); ++#if 1//SDIO CLOCK SETTING ++ if ((feature.sdio_clock > 0) && (host->ios.timing != MMC_TIMING_UHS_DDR50)) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++#endif ++ sdio_release_host(sdiodev->func); ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev) ++{ ++ struct aicwf_bus *bus_if = NULL; ++ ++ if (sdiodev->func == NULL) { ++ sdio_err("%s, NULL sdio func\n", __func__); ++ return; ++ } ++ ++ bus_if = dev_get_drvdata(sdiodev->dev); ++ if (bus_if == NULL) { ++ sdio_err("%s, bus_if is null\n", __func__); ++ return; ++ } ++ ++ if (sdiodev->bus_if == bus_if) { ++ sdio_dbg("%s bsp disable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ sdio_disable_func(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func_msg); ++ sdio_disable_func(sdiodev->func_msg); ++ sdio_release_host(sdiodev->func_msg); ++ } ++ ++} ++ ++ ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret; ++ struct aicwf_bus *bus_if; ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ spin_lock_init(&sdiodev->pwrctl_lock); ++ sema_init(&sdiodev->pwrctl_wakeup_sema, 1); ++#endif ++ ++ bus_if = sdiodev->bus_if; ++ bus_if->dev = sdiodev->dev; ++ bus_if->ops = &aicwf_sdio_bus_ops; ++ bus_if->state = BUS_DOWN_ST; ++#if defined(CONFIG_SDIO_PWRCTRL) ++ sdiodev->state = SDIO_SLEEP_ST; ++ sdiodev->active_duration = SDIOWIFI_PWR_CTRL_INTERVAL; ++#else ++ sdiodev->state = SDIO_ACTIVE_ST; ++#endif ++ ++ rx_priv = aicwf_rx_init(sdiodev); ++ if (!rx_priv) { ++ sdio_err("rx init fail\n"); ++ goto fail; ++ } ++ sdiodev->rx_priv = rx_priv; ++ ++ tx_priv = aicwf_tx_init(sdiodev); ++ if (!tx_priv) { ++ sdio_err("tx init fail\n"); ++ goto fail; ++ } ++ sdiodev->tx_priv = tx_priv; ++ aicwf_frame_queue_init(&tx_priv->txq, 8, TXQLEN); ++ spin_lock_init(&tx_priv->txqlock); ++ sema_init(&tx_priv->txctl_sema, 1); ++ sema_init(&tx_priv->cmd_txsema, 1); ++ init_waitqueue_head(&tx_priv->cmd_txdone_wait); ++ atomic_set(&tx_priv->tx_pktcnt, 0); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ timer_setup(&sdiodev->timer, aicwf_sdio_bus_pwrctl, 0); ++#else ++ init_timer(&sdiodev->timer); ++ sdiodev->timer.data = (ulong) sdiodev; ++ sdiodev->timer.function = aicwf_sdio_bus_pwrctl; ++#endif ++ init_completion(&sdiodev->pwrctrl_trgg); ++#endif ++ ret = aicwf_bus_init(0, sdiodev->dev); ++ if (ret < 0) { ++ sdio_err("bus init fail\n"); ++ goto fail; ++ } ++ ++ ret = aicwf_bus_start(bus_if); ++ if (ret != 0) { ++ sdio_err("bus start fail\n"); ++ goto fail; ++ } ++ ++ return sdiodev; ++ ++fail: ++ aicwf_sdio_release(sdiodev); ++ return NULL; ++} ++ ++void get_fw_path(char* fw_path){ ++ if (strlen(aic_fw_path) > 0) { ++ memcpy(fw_path, aic_fw_path, strlen(aic_fw_path)); ++ }else{ ++ memcpy(fw_path, aic_default_fw_path, strlen(aic_default_fw_path)); ++ } ++} ++ ++int get_testmode(void){ ++ return testmode; ++} ++ ++struct sdio_func *get_sdio_func(void){ ++ return aicbsp_sdiodev->func; ++} ++ ++void set_irq_handler(void *fn){ ++ aicbsp_sdiodev->sdio_hal_irqhandler = (sdio_irq_handler_t *)fn; ++} ++ ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size) ++{ ++ uint8_t i; ++ uint8_t crc = 0; ++ if (cal_size==0) { ++ return crc; ++ } ++ while (cal_size--) { ++ for (i = 0x80; i > 0; i /= 2) { ++ if (crc & 0x80) { ++ crc *= 2; ++ crc ^= 0x07; //polynomial X8 + X2 + X + 1,(0x107) ++ } else { ++ crc *= 2; ++ } ++ if ((*p_buffer) & i) { ++ crc ^= 0x07; ++ } ++ } ++ p_buffer++; ++ } ++ return crc; ++} ++ ++EXPORT_SYMBOL(get_fw_path); ++EXPORT_SYMBOL(get_testmode); ++EXPORT_SYMBOL(get_sdio_func); ++EXPORT_SYMBOL(set_irq_handler); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h +new file mode 100644 +index 000000000000..65d73510ad3a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h +@@ -0,0 +1,149 @@ ++/** ++ * aicwf_sdio.h ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_SDMMC_H_ ++#define _AICWF_SDMMC_H_ ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include ++#include ++#include ++#include ++#include "aic_bsp_driver.h" ++ ++#define AICBSP_SDIO_NAME "aicbsp_sdio" ++#define SDIOWIFI_FUNC_BLOCKSIZE 512 ++ ++#define SDIO_VENDOR_ID_AIC 0x8800 ++#define SDIO_DEVICE_ID_AIC 0x0001 ++#define SDIOWIFI_BYTEMODE_LEN_REG 0x02 ++#define SDIOWIFI_INTR_CONFIG_REG 0x04 ++#define SDIOWIFI_SLEEP_REG 0x05 ++#define SDIOWIFI_WAKEUP_REG 0x09 ++#define SDIOWIFI_FLOW_CTRL_REG 0x0A ++#define SDIOWIFI_REGISTER_BLOCK 0x0B ++#define SDIOWIFI_BYTEMODE_ENABLE_REG 0x11 ++#define SDIOWIFI_BLOCK_CNT_REG 0x12 ++#define SDIOWIFI_FLOWCTRL_MASK_REG 0x7F ++#define SDIOWIFI_WR_FIFO_ADDR 0x07 ++#define SDIOWIFI_RD_FIFO_ADDR 0x08 ++ ++#define SDIOWIFI_INTR_ENABLE_REG_V3 0x00 ++#define SDIOWIFI_INTR_PENDING_REG_V3 0x01 ++#define SDIOWIFI_INTR_TO_DEVICE_REG_V3 0x02 ++#define SDIOWIFI_FLOW_CTRL_Q1_REG_V3 0x03 ++#define SDIOWIFI_MISC_INT_STATUS_REG_V3 0x04 ++#define SDIOWIFI_BYTEMODE_LEN_REG_V3 0x05 ++#define SDIOWIFI_BYTEMODE_LEN_MSB_REG_V3 0x06 ++#define SDIOWIFI_BYTEMODE_ENABLE_REG_V3 0x07 ++#define SDIOWIFI_MISC_CTRL_REG_V3 0x08 ++#define SDIOWIFI_FLOW_CTRL_Q2_REG_V3 0x09 ++#define SDIOWIFI_CLK_TEST_RESULT_REG_V3 0x0A ++#define SDIOWIFI_RD_FIFO_ADDR_V3 0x0F ++#define SDIOWIFI_WR_FIFO_ADDR_V3 0x10 ++ ++#define SDIOCLK_FREE_RUNNING_BIT (1 << 6) ++ ++#define SDIOWIFI_PWR_CTRL_INTERVAL 30 ++#define FLOW_CTRL_RETRY_COUNT 50 ++#define BUFFER_SIZE 1536 ++#define TAIL_LEN 4 ++#define TXQLEN (2048*4) ++ ++#define SDIO_SLEEP_ST 0 ++#define SDIO_ACTIVE_ST 1 ++ ++typedef enum { ++ SDIO_TYPE_DATA = 0X00, ++ SDIO_TYPE_CFG = 0X10, ++ SDIO_TYPE_CFG_CMD_RSP = 0X11, ++ SDIO_TYPE_CFG_DATA_CFM = 0X12 ++} sdio_type; ++ ++enum AICWF_IC{ ++ PRODUCT_ID_AIC8801 = 0, ++ PRODUCT_ID_AIC8800DC, ++ PRODUCT_ID_AIC8800DW, ++ PRODUCT_ID_AIC8800D80, ++ PRODUCT_ID_AIC8800D80X2 ++}; ++ ++struct aic_sdio_reg { ++ u8 bytemode_len_reg; ++ u8 intr_config_reg; ++ u8 sleep_reg; ++ u8 wakeup_reg; ++ u8 flow_ctrl_reg; ++ u8 flowctrl_mask_reg; ++ u8 register_block; ++ u8 bytemode_enable_reg; ++ u8 block_cnt_reg; ++ u8 misc_int_status_reg; ++ u8 rd_fifo_addr; ++ u8 wr_fifo_addr; ++}; ++ ++struct aic_sdio_dev { ++ struct rwnx_cmd_mgr cmd_mgr; ++ struct sdio_func *func; ++ struct sdio_func *func_msg; ++ struct device *dev; ++ struct aicwf_bus *bus_if; ++ ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ u32 state; ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ //for sdio pwr ctrl ++ struct timer_list timer; ++ uint active_duration; ++ struct completion pwrctrl_trgg; ++ struct task_struct *pwrctl_tsk; ++ spinlock_t pwrctl_lock; ++ struct semaphore pwrctl_wakeup_sema; ++#endif ++ u16 chipid; ++ u32 fw_version_uint; ++ struct aic_sdio_reg sdio_reg; ++ void (*sdio_hal_irqhandler) (struct sdio_func *func); ++}; ++ ++void *aicbsp_get_drvdata(void *args); ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func); ++void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func); ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration); ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target); ++#endif ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size, u8 msg); ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count); ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev); ++void aicbsp_sdio_exit(void); ++int aicbsp_sdio_init(void); ++void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt); ++int aicwf_sdio_bustx_thread(void *data); ++int aicwf_sdio_busrx_thread(void *data); ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt); ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv); ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv); ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv); ++extern void aicwf_hostif_ready(void); ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv); ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size); ++#endif /* AICWF_SDIO_SUPPORT */ ++ ++#endif /*_AICWF_SDMMC_H_*/ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c +new file mode 100644 +index 000000000000..84e6ca71c7ae +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c +@@ -0,0 +1,464 @@ ++/** ++ * aicwf_bus.c ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aicsdio_txrxif.h" ++#include "aic_bsp_driver.h" ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if; ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return -1; ++ } ++ bus_if = dev_get_drvdata(dev); ++ bus_if->cmd_buf = kzalloc(CMD_BUF_MAX, GFP_KERNEL); ++ if (!bus_if->cmd_buf) { ++ ret = -ENOMEM; ++ txrx_err("proto_attach failed\n"); ++ goto fail; ++ } ++ memset(bus_if->cmd_buf, '\0', CMD_BUF_MAX); ++ ++ init_completion(&bus_if->bustx_trgg); ++ init_completion(&bus_if->busrx_trgg); ++#ifdef AICWF_SDIO_SUPPORT ++ bus_if->bustx_thread = kthread_run(aicwf_sdio_bustx_thread, (void *)bus_if, "aicwf_bustx_thread"); ++ if (IS_ERR(bus_if->bustx_thread)) { ++ bus_if->bustx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ ret = -1; ++ goto fail; ++ } ++ ++ bus_if->busrx_thread = kthread_run(aicwf_sdio_busrx_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busrx_thread"); ++ if (IS_ERR(bus_if->busrx_thread)) { ++ bus_if->busrx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ ret = -1; ++ goto fail; ++ } ++ ++#endif ++ return ret; ++fail: ++ aicwf_bus_deinit(dev); ++ ++ return ret; ++} ++ ++void aicwf_bus_deinit(struct device *dev) ++{ ++ struct aicwf_bus *bus_if; ++ struct aic_sdio_dev *sdiodev; ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return; ++ } ++ sdio_dbg("%s", __func__); ++ bus_if = aicbsp_get_drvdata(dev); ++ aicwf_bus_stop(bus_if); ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ ++ if (bus_if->cmd_buf) { ++ kfree(bus_if->cmd_buf); ++ bus_if->cmd_buf = NULL; ++ } ++ ++ if (bus_if->bustx_thread) { ++ complete_all(&bus_if->bustx_trgg); ++ kthread_stop(bus_if->bustx_thread); ++ bus_if->bustx_thread = NULL; ++ } ++} ++ ++void aicwf_frame_tx(void *dev, struct sk_buff *skb) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ aicwf_bus_txdata(sdiodev->bus_if, skb); ++} ++ ++struct aicwf_tx_priv *aicwf_tx_init(void *arg) ++{ ++ struct aicwf_tx_priv *tx_priv; ++ ++ tx_priv = kzalloc(sizeof(struct aicwf_tx_priv), GFP_KERNEL); ++ if (!tx_priv) ++ return NULL; ++ ++ tx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++ ++ atomic_set(&tx_priv->aggr_count, 0); ++ tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN); ++ if (!tx_priv->aggr_buf) { ++ txrx_err("Alloc bus->txdata_buf failed!\n"); ++ kfree(tx_priv); ++ return NULL; ++ } ++ tx_priv->head = tx_priv->aggr_buf->data; ++ tx_priv->tail = tx_priv->aggr_buf->data; ++ ++ return tx_priv; ++} ++ ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv) ++{ ++ if (tx_priv && tx_priv->aggr_buf) ++ dev_kfree_skb(tx_priv->aggr_buf); ++ ++ kfree(tx_priv); ++ //tx_priv = NULL; ++} ++ ++static bool aicwf_another_ptk(struct sk_buff *skb) ++{ ++ u8 *data; ++ u16 aggr_len = 0; ++ ++ if (skb->data == NULL || skb->len == 0) { ++ return false; ++ } ++ data = skb->data; ++ aggr_len = (*skb->data | (*(skb->data + 1) << 8)); ++ if (aggr_len == 0) { ++ return false; ++ } ++ ++ return true; ++} ++ ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv) ++{ ++ int ret = 0; ++ unsigned long flags = 0; ++ struct sk_buff *skb = NULL; ++ u16 pkt_len = 0; ++ struct sk_buff *skb_inblock = NULL; ++ u16 aggr_len = 0, adjust_len = 0; ++ u8 *data = NULL; ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ skb = aicwf_frame_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (skb == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ while (aicwf_another_ptk(skb)) { ++ data = skb->data; ++ pkt_len = (*skb->data | (*(skb->data + 1) << 8)); ++ ++ if ((skb->data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv ++ if (skb_inblock == NULL) { ++ txrx_err("no more space!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ #if 0 ++ rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ #endif ++ skb_pull(skb, adjust_len); ++ } else { // type : config ++ aggr_len = pkt_len; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len+4, GFP_KERNEL); ++ if (skb_inblock == NULL) { ++ txrx_err("no more space!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ ++ skb_put(skb_inblock, aggr_len+4); ++ memcpy(skb_inblock->data, data, aggr_len+4); ++ if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) ++ rwnx_rx_handle_msg(rx_priv->sdiodev, (struct ipc_e2a_msg *)(skb_inblock->data + 4)); ++ #if 0 ++ if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) ++ aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(skb_inblock->data + 4)); ++ #endif ++ skb_pull(skb, adjust_len+4); ++ } ++ } ++ ++ /* skb_inblock no used currently, just free it! */ ++ dev_kfree_skb(skb_inblock); ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(rx_priv->sdiodev, SDIO_ACTIVE_ST); ++#endif ++ ++ return ret; ++} ++ ++static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize) ++{ ++ int i; ++ struct recv_msdu *req, *reqs; ++ ++ reqs = vmalloc(qsize*sizeof(struct recv_msdu)); ++ if (reqs == NULL) ++ return NULL; ++ ++ req = reqs; ++ for (i = 0; i < qsize; i++) { ++ INIT_LIST_HEAD(&req->rxframe_list); ++ list_add(&req->rxframe_list, q); ++ req->len = 0; ++ req++; ++ } ++ ++ return reqs; ++} ++ ++struct aicwf_rx_priv *aicwf_rx_init(void *arg) ++{ ++ struct aicwf_rx_priv *rx_priv; ++ rx_priv = kzalloc(sizeof(struct aicwf_rx_priv), GFP_KERNEL); ++ if (!rx_priv) ++ return NULL; ++ ++ rx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++ aicwf_frame_queue_init(&rx_priv->rxq, 1, MAX_RXQLEN); ++ spin_lock_init(&rx_priv->rxqlock); ++ atomic_set(&rx_priv->rx_cnt, 0); ++ ++ INIT_LIST_HEAD(&rx_priv->rxframes_freequeue); ++ spin_lock_init(&rx_priv->freeq_lock); ++ rx_priv->recv_frames = aicwf_rxframe_queue_init(&rx_priv->rxframes_freequeue, MAX_REORD_RXFRAME); ++ if (!rx_priv->recv_frames) { ++ txrx_err("no enough buffer for free recv frame queue!\n"); ++ kfree(rx_priv); ++ return NULL; ++ } ++ spin_lock_init(&rx_priv->stas_reord_lock); ++ INIT_LIST_HEAD(&rx_priv->stas_reord_list); ++ ++ return rx_priv; ++} ++ ++ ++static void aicwf_recvframe_queue_deinit(struct list_head *q) ++{ ++ struct recv_msdu *req, *next; ++ ++ list_for_each_entry_safe(req, next, q, rxframe_list) { ++ list_del_init(&req->rxframe_list); ++ } ++} ++ ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv) ++{ ++ if (rx_priv->sdiodev->bus_if->busrx_thread) { ++ complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg); ++ kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread); ++ rx_priv->sdiodev->bus_if->busrx_thread = NULL; ++ } ++ ++ aicwf_frame_queue_flush(&rx_priv->rxq); ++ aicwf_recvframe_queue_deinit(&rx_priv->rxframes_freequeue); ++ if (rx_priv->recv_frames) ++ vfree(rx_priv->recv_frames); ++ ++ kfree(rx_priv); ++ //rx_priv = NULL; ++} ++ ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt) ++{ ++ return aicwf_frame_enq(dev, q, pkt, 0); ++} ++ ++ ++void aicwf_dev_skb_free(struct sk_buff *skb) ++{ ++ if (!skb) ++ return; ++ ++ dev_kfree_skb_any(skb); ++} ++ ++static struct sk_buff *aicwf_frame_queue_penq(struct frame_queue *pq, int prio, struct sk_buff *p) ++{ ++ struct sk_buff_head *q; ++ ++ if (pq->queuelist[prio].qlen >= pq->qmax) ++ return NULL; ++ ++ q = &pq->queuelist[prio]; ++ __skb_queue_tail(q, p); ++ pq->qcnt++; ++ if (pq->hi_prio < prio) ++ pq->hi_prio = (u16)prio; ++ ++ return p; ++} ++ ++void aicwf_frame_queue_flush(struct frame_queue *pq) ++{ ++ int prio; ++ struct sk_buff_head *q; ++ struct sk_buff *p, *next; ++ ++ for (prio = 0; prio < pq->num_prio; prio++) { ++ q = &pq->queuelist[prio]; ++ skb_queue_walk_safe(q, p, next) { ++ skb_unlink(p, q); ++ aicwf_dev_skb_free(p); ++ pq->qcnt--; ++ } ++ } ++} ++ ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len) ++{ ++ int prio; ++ ++ memset(pq, 0, offsetof(struct frame_queue, queuelist) + (sizeof(struct sk_buff_head) * num_prio)); ++ pq->num_prio = (u16)num_prio; ++ pq->qmax = (u16)max_len; ++ ++ for (prio = 0; prio < num_prio; prio++) { ++ skb_queue_head_init(&pq->queuelist[prio]); ++ } ++} ++ ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out) ++{ ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ for (prio = 0; prio < pq->hi_prio; prio++) ++ if (!skb_queue_empty(&pq->queuelist[prio])) ++ break; ++ ++ if (prio_out) ++ *prio_out = prio; ++ ++ return skb_peek_tail(&pq->queuelist[prio]); ++} ++ ++bool aicwf_is_framequeue_empty(struct frame_queue *pq) ++{ ++ int prio, len = 0; ++ ++ for (prio = 0; prio <= pq->hi_prio; prio++) ++ len += pq->queuelist[prio].qlen; ++ ++ if (len > 0) ++ return false; ++ else ++ return true; ++} ++ ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq) ++{ ++ struct sk_buff_head *q; ++ struct sk_buff *p; ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ while ((prio = pq->hi_prio) > 0 && skb_queue_empty(&pq->queuelist[prio])) ++ pq->hi_prio--; ++ ++ q = &pq->queuelist[prio]; ++ p = __skb_dequeue(q); ++ if (p == NULL) ++ return NULL; ++ ++ pq->qcnt--; ++ ++ return p; ++} ++ ++static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio) ++{ ++ struct sk_buff_head *q = &pq->queuelist[prio]; ++ struct sk_buff *p = skb_dequeue_tail(q); ++ ++ if (!p) ++ return NULL; ++ ++ pq->qcnt--; ++ return p; ++} ++ ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio) ++{ ++ struct sk_buff *p = NULL; ++ int prio_modified = -1; ++ ++ if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { ++ aicwf_frame_queue_penq(q, prio, pkt); ++ return true; ++ } ++ if (q->queuelist[prio].qlen >= q->qmax) { ++ prio_modified = prio; ++ } else if (q->qcnt >= q->qmax) { ++ p = aicwf_frame_queue_peek_tail(q, &prio_modified); ++ if (prio_modified > prio) ++ return false; ++ } ++ ++ if (prio_modified >= 0) { ++ if (prio_modified == prio) ++ return false; ++ ++ p = aicwf_skb_dequeue_tail(q, prio_modified); ++ aicwf_dev_skb_free(p); ++ ++ p = aicwf_frame_queue_penq(q, prio_modified, pkt); ++ if (p == NULL) ++ txrx_err("failed\n"); ++ } ++ ++ return p != NULL; ++} ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h +new file mode 100644 +index 000000000000..801e0ea4965c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h +@@ -0,0 +1,214 @@ ++/** ++ * aicwf_txrxif.h ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_TXRXIF_H_ ++#define _AICWF_TXRXIF_H_ ++ ++#include ++#include ++#include "aicsdio.h" ++ ++#define CMD_BUF_MAX 1536 ++#define TXPKT_BLOCKSIZE 512 ++#define MAX_AGGR_TXPKT_LEN (1536*4) ++#define CMD_TX_TIMEOUT 5000 ++#define TX_ALIGNMENT 4 ++ ++#define RX_HWHRD_LEN 60 //58->60 word allined ++#define CCMP_OR_WEP_INFO 8 ++#define MAX_RXQLEN 2000 ++#define RX_ALIGNMENT 4 ++ ++#define DEBUG_ERROR_LEVEL 0 ++#define DEBUG_DEBUG_LEVEL 1 ++#define DEBUG_INFO_LEVEL 2 ++ ++#define DBG_LEVEL DEBUG_DEBUG_LEVEL ++ ++#define txrx_err(fmt, ...) pr_err("aicbsp: txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define sdio_err(fmt, ...) pr_err("aicbsp: sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define usb_err(fmt, ...) pr_err("aicbsp: usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL ++#define sdio_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#define usb_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#else ++#define sdio_dbg(fmt, ...) ++#define usb_dbg(fmt, ...) ++#endif ++#if DBG_LEVEL >= DEBUG_INFO_LEVEL ++#define sdio_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#define usb_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) ++#else ++#define sdio_info(fmt, ...) ++#define usb_info(fmt, ...) ++#endif ++ ++enum aicwf_bus_state { ++ BUS_DOWN_ST, ++ BUS_UP_ST ++}; ++ ++struct aicwf_bus_ops { ++ int (*start) (struct device *dev); ++ void (*stop) (struct device *dev); ++ int (*txdata) (struct device *dev, struct sk_buff *skb); ++ int (*txmsg) (struct device *dev, u8 *msg, uint len); ++}; ++ ++struct frame_queue { ++ u16 num_prio; ++ u16 hi_prio; ++ u16 qmax; /* max number of queued frames */ ++ u16 qcnt; ++ struct sk_buff_head queuelist[8]; ++}; ++ ++struct aicwf_bus { ++ union { ++ struct aic_sdio_dev *sdio; ++ struct aic_usb_dev *usb; ++ } bus_priv; ++ struct device *dev; ++ struct aicwf_bus_ops *ops; ++ enum aicwf_bus_state state; ++ u8 *cmd_buf; ++ struct completion bustx_trgg; ++ struct completion busrx_trgg; ++ struct task_struct *bustx_thread; ++ struct task_struct *busrx_thread; ++}; ++ ++struct aicwf_tx_priv { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++ int fw_avail_bufcnt; ++ //for cmd tx ++ u8 *cmd_buf; ++ uint cmd_len; ++ bool cmd_txstate; ++ bool cmd_tx_succ; ++ struct semaphore cmd_txsema; ++ wait_queue_head_t cmd_txdone_wait; ++ //for data tx ++ atomic_t tx_pktcnt; ++ ++ struct frame_queue txq; ++ spinlock_t txqlock; ++ struct semaphore txctl_sema; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ struct sk_buff *aggr_buf; ++ atomic_t aggr_count; ++ u8 *head; ++ u8 *tail; ++}; ++ ++ ++#define MAX_REORD_RXFRAME 250 ++#define REORDER_UPDATE_TIME 50 ++#define AICWF_REORDER_WINSIZE 64 ++#define SN_LESS(a, b) (((a-b)&0x800) != 0) ++#define SN_EQUAL(a, b) (a == b) ++ ++struct reord_ctrl { ++ struct aicwf_rx_priv *rx_priv; ++ u8 enable; ++ u16 ind_sn; ++ u8 wsize_b; ++ spinlock_t reord_list_lock; ++ struct list_head reord_list; ++ struct timer_list reord_timer; ++ struct work_struct reord_timer_work; ++}; ++ ++struct reord_ctrl_info { ++ u8 mac_addr[6]; ++ struct reord_ctrl preorder_ctrl[8]; ++ struct list_head list; ++}; ++ ++struct recv_msdu { ++ struct sk_buff *pkt; ++ u8 tid; ++ u16 seq_num; ++ uint len; ++ u8 *rx_data; ++ //for pending rx reorder list ++ struct list_head reord_pending_list; ++ //for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue ++ struct list_head rxframe_list; ++ struct reord_ctrl *preorder_ctrl; ++}; ++ ++struct aicwf_rx_priv { ++ struct aic_sdio_dev *sdiodev; ++ void *rwnx_vif; ++ atomic_t rx_cnt; ++ u32 data_len; ++ spinlock_t rxqlock; ++ struct frame_queue rxq; ++ ++ spinlock_t freeq_lock; ++ struct list_head rxframes_freequeue; ++ struct list_head stas_reord_list; ++ spinlock_t stas_reord_lock; ++ struct recv_msdu *recv_frames; ++}; ++ ++static inline int aicwf_bus_start(struct aicwf_bus *bus) ++{ ++ return bus->ops->start(bus->dev); ++} ++ ++static inline void aicwf_bus_stop(struct aicwf_bus *bus) ++{ ++ bus->ops->stop(bus->dev); ++} ++ ++static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb) ++{ ++ return bus->ops->txdata(bus->dev, skb); ++} ++ ++static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len) ++{ ++ return bus->ops->txmsg(bus->dev, msg, len); ++} ++ ++static inline void aicwf_sched_timeout(u32 millisec) ++{ ++ ulong timeout = 0, expires = 0; ++ expires = jiffies + msecs_to_jiffies(millisec); ++ timeout = millisec; ++ ++ while (timeout) { ++ timeout = schedule_timeout(timeout); ++ if (time_after(jiffies, expires)) ++ break; ++ } ++} ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev); ++void aicwf_bus_deinit(struct device *dev); ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv); ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv); ++struct aicwf_tx_priv *aicwf_tx_init(void *arg); ++struct aicwf_rx_priv *aicwf_rx_init(void *arg); ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len); ++void aicwf_frame_queue_flush(struct frame_queue *pq); ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio); ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt); ++bool aicwf_is_framequeue_empty(struct frame_queue *pq); ++void aicwf_frame_tx(void *dev, struct sk_buff *skb); ++void aicwf_dev_skb_free(struct sk_buff *skb); ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq); ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out); ++ ++#endif /* _AICWF_TXRXIF_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c +new file mode 100644 +index 000000000000..77130f76bafa +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c +@@ -0,0 +1,16138 @@ ++#include ++ ++char fmacfw[259592] = { ++0x00, 0x38, 0x18, 0x00, 0x89, 0x01, 0x12, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0xA1, 0xCA, 0x12, 0x00, 0xA9, 0xCA, 0x12, 0x00, ++0xB1, 0xCA, 0x12, 0x00, 0xB9, 0xCA, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x12, 0x00, ++0xA5, 0xC6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0xBB, 0x12, 0x00, 0x19, 0x1E, 0x14, 0x00, 0x35, 0xEE, 0x12, 0x00, ++0x49, 0xED, 0x12, 0x00, 0x79, 0x5C, 0x13, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x79, 0x5C, 0x13, 0x00, 0x49, 0x11, 0x12, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x65, 0x5A, 0x12, 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, 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, 0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, ++0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, 0x7D, 0x4A, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x99, 0x1A, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x8D, 0x52, 0x12, 0x00, 0x79, 0x51, 0x12, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xCD, 0x5B, 0x12, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x05, 0x48, 0x00, 0x68, 0x10, 0xF0, 0x00, 0x4F, ++0x0C, 0xBF, 0x04, 0x48, 0x20, 0xF0, 0x7F, 0x40, 0x80, 0xF3, 0x08, 0x88, 0x02, 0x48, 0x00, 0x47, 0x44, 0x01, 0x50, 0x40, ++0x00, 0x38, 0x18, 0x00, 0x05, 0xC7, 0x12, 0x00, 0xF0, 0xB4, 0x86, 0x07, 0x46, 0xD0, 0x54, 0x1E, 0x00, 0x2A, 0x3C, 0xD0, ++0xCA, 0xB2, 0x03, 0x46, 0x01, 0xE0, 0x01, 0x3C, 0x37, 0xD3, 0x03, 0xF8, 0x01, 0x2B, 0x9D, 0x07, 0xF9, 0xD1, 0x03, 0x2C, ++0x2A, 0xD9, 0xCD, 0xB2, 0x45, 0xEA, 0x05, 0x25, 0x0F, 0x2C, 0x45, 0xEA, 0x05, 0x45, 0x34, 0xD9, 0xA4, 0xF1, 0x10, 0x02, ++0x22, 0xF0, 0x0F, 0x0C, 0x03, 0xF1, 0x20, 0x07, 0x16, 0x09, 0x67, 0x44, 0x03, 0xF1, 0x10, 0x02, 0x42, 0xE9, 0x04, 0x55, ++0x42, 0xE9, 0x02, 0x55, 0x10, 0x32, 0xBA, 0x42, 0xF8, 0xD1, 0x72, 0x1C, 0x14, 0xF0, 0x0C, 0x0F, 0x03, 0xEB, 0x02, 0x12, ++0x04, 0xF0, 0x0F, 0x06, 0x13, 0xD0, 0x33, 0x1F, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x42, 0xF8, 0x04, 0x5B, ++0x93, 0x42, 0xFB, 0xD1, 0x06, 0xF0, 0x03, 0x04, 0x2C, 0xB1, 0xCA, 0xB2, 0x1C, 0x44, 0x03, 0xF8, 0x01, 0x2B, 0x9C, 0x42, ++0xFB, 0xD1, 0xF0, 0xBC, 0x70, 0x47, 0x34, 0x46, 0x13, 0x46, 0x00, 0x2C, 0xF3, 0xD1, 0xF8, 0xE7, 0x14, 0x46, 0x03, 0x46, ++0xC1, 0xE7, 0x1A, 0x46, 0x26, 0x46, 0xE0, 0xE7, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x68, 0x91, 0x4F, 0x4F, 0xD9, 0xF8, ++0x00, 0x60, 0xDF, 0xF8, 0x64, 0xC1, 0x33, 0x89, 0xD6, 0xF8, 0x34, 0xE0, 0xC7, 0xF8, 0x10, 0xE0, 0xD6, 0xE9, 0x09, 0x10, ++0xD6, 0xE9, 0x0B, 0x45, 0x39, 0x60, 0xC9, 0x08, 0x03, 0x29, 0x78, 0x60, 0x4F, 0xEA, 0xD0, 0x00, 0x38, 0xBF, 0x03, 0x21, ++0xBC, 0x60, 0x03, 0x28, 0x4F, 0xEA, 0xD4, 0x04, 0x38, 0xBF, 0x03, 0x20, 0xFD, 0x60, 0x03, 0x2C, 0x4F, 0xEA, 0xD5, 0x05, ++0x4F, 0xF0, 0x54, 0x02, 0x4F, 0xEA, 0xDE, 0x07, 0x2C, 0xF0, 0x03, 0x0C, 0x38, 0xBF, 0x03, 0x24, 0xDF, 0xF8, 0x1C, 0xE1, ++0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0xA1, 0xC8, 0xF8, 0x00, 0x10, 0x03, 0x2D, 0x03, 0xFB, 0x02, 0x22, 0x38, 0xBF, ++0x03, 0x25, 0x62, 0x44, 0x03, 0x2F, 0x38, 0xBF, 0x03, 0x27, 0x72, 0x45, 0xC8, 0xE9, 0x01, 0x04, 0xC8, 0xE9, 0x03, 0x57, ++0xCA, 0xF8, 0x00, 0xC0, 0x4F, 0xD8, 0x01, 0x33, 0xDF, 0xF8, 0xF4, 0xE0, 0x2E, 0x4A, 0xDF, 0xF8, 0xF4, 0x80, 0xDF, 0xF8, ++0xF4, 0x90, 0x4F, 0xF0, 0x58, 0x0C, 0x0C, 0xFB, 0x03, 0xE3, 0xD2, 0xF8, 0x00, 0xC0, 0x2A, 0x4A, 0x13, 0x60, 0x4F, 0xF4, ++0xAC, 0x72, 0x02, 0xFB, 0x01, 0x33, 0x02, 0xFB, 0x00, 0x30, 0x02, 0xFB, 0x04, 0x04, 0x02, 0xFB, 0x05, 0x45, 0xDC, 0xF8, ++0x00, 0x10, 0xC8, 0xF8, 0x00, 0x50, 0x02, 0xFB, 0x07, 0x52, 0xC9, 0xF8, 0x00, 0x40, 0x21, 0x4F, 0x21, 0x4D, 0x22, 0x4C, ++0x38, 0x60, 0x2B, 0x60, 0xC4, 0xF8, 0x00, 0xE0, 0x41, 0xB9, 0xDC, 0xF8, 0x04, 0x30, 0x04, 0x33, 0x11, 0x1D, 0x23, 0xF0, ++0x03, 0x03, 0xCC, 0xF8, 0x00, 0x10, 0x1A, 0x44, 0xDC, 0xF8, 0x08, 0x30, 0x13, 0xB9, 0x04, 0x32, 0xCC, 0xF8, 0x08, 0x20, ++0x18, 0x4B, 0xF2, 0x68, 0x1A, 0x60, 0x33, 0x78, 0x02, 0x2B, 0x0E, 0xD0, 0x01, 0x2B, 0x01, 0xD0, 0xBD, 0xE8, 0xF0, 0x87, ++0x72, 0x69, 0x00, 0x2A, 0xFA, 0xD0, 0x13, 0x49, 0x91, 0x42, 0xF7, 0xD9, 0xBD, 0xE8, 0xF0, 0x47, 0x11, 0x48, 0x05, 0xF0, ++0xC1, 0xBF, 0x32, 0x69, 0xF3, 0xE7, 0x71, 0x46, 0x0F, 0x48, 0x05, 0xF0, 0xBB, 0xFF, 0xD9, 0xF8, 0x00, 0x60, 0xD8, 0xF8, ++0x00, 0x10, 0x33, 0x89, 0xD8, 0xE9, 0x01, 0x04, 0xD8, 0xE9, 0x03, 0x57, 0x01, 0x33, 0xA1, 0xE7, 0x7C, 0x28, 0x17, 0x00, ++0x30, 0x36, 0x17, 0x00, 0xEC, 0x57, 0x18, 0x00, 0xF4, 0x57, 0x18, 0x00, 0xF0, 0x57, 0x18, 0x00, 0x14, 0x63, 0x18, 0x00, ++0x00, 0x38, 0x18, 0x00, 0x00, 0x38, 0x18, 0x00, 0x44, 0x76, 0x15, 0x00, 0x18, 0x76, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, ++0x2B, 0x07, 0x18, 0x00, 0x00, 0x24, 0x18, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x40, 0x61, 0x17, 0x00, 0xE0, 0x9F, 0x18, 0x00, ++0xFC, 0x57, 0x18, 0x00, 0xF8, 0x57, 0x18, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x49, 0x4C, 0x4A, 0x49, 0x4A, 0x4E, 0x4B, 0x4A, ++0x4B, 0x4D, 0x4C, 0x48, 0x0C, 0x60, 0x04, 0xF1, 0x44, 0x07, 0x21, 0x1D, 0xD4, 0xF8, 0xD0, 0x30, 0x37, 0x60, 0x04, 0xF1, ++0x80, 0x07, 0x11, 0x60, 0x2F, 0x60, 0x47, 0x49, 0x47, 0x4A, 0x04, 0xF1, 0x90, 0x05, 0x23, 0xF0, 0x7F, 0x43, 0x05, 0x60, ++0x04, 0xF1, 0xA8, 0x00, 0x08, 0x60, 0x23, 0xF0, 0xFF, 0x03, 0x04, 0xF1, 0xAA, 0x01, 0x11, 0x60, 0x83, 0xB1, 0x94, 0xF8, ++0xD1, 0x30, 0x23, 0xB1, 0x3F, 0x4A, 0x53, 0x6D, 0x23, 0xF0, 0x01, 0x03, 0x53, 0x65, 0x94, 0xF8, 0xD2, 0x30, 0x00, 0x2B, ++0x5B, 0xD1, 0x3B, 0x4B, 0x4F, 0xF0, 0x80, 0x62, 0xC3, 0xF8, 0x10, 0x21, 0x39, 0x4D, 0x3A, 0x4F, 0xD5, 0xF8, 0x30, 0x32, ++0xDF, 0xF8, 0xF8, 0x80, 0x98, 0x47, 0x01, 0x21, 0x00, 0x20, 0x05, 0xF0, 0x5F, 0xFF, 0x00, 0x20, 0x05, 0xF0, 0x9A, 0xFF, ++0x01, 0x21, 0x02, 0x20, 0x05, 0xF0, 0x58, 0xFF, 0x02, 0x20, 0x05, 0xF0, 0x93, 0xFF, 0x01, 0x21, 0x03, 0x20, 0x05, 0xF0, ++0x51, 0xFF, 0x03, 0x20, 0x05, 0xF0, 0x8C, 0xFF, 0x3B, 0x68, 0x03, 0xF0, 0x0F, 0x03, 0xA3, 0xF1, 0x0A, 0x03, 0xB3, 0xFA, ++0x83, 0xF3, 0x5B, 0x09, 0x88, 0xF8, 0x02, 0x30, 0x25, 0xF0, 0x0E, 0xFA, 0x05, 0xF0, 0x90, 0xFA, 0x06, 0xF0, 0x54, 0xF8, ++0xD5, 0xF8, 0x74, 0x32, 0x98, 0x47, 0x94, 0xF8, 0x44, 0x10, 0x23, 0x48, 0x24, 0xF0, 0xEE, 0xF8, 0x07, 0xF0, 0x8C, 0xF8, ++0x06, 0xF0, 0xA8, 0xF9, 0x98, 0xF8, 0x02, 0x30, 0x0B, 0xB3, 0xD5, 0xF8, 0x6C, 0x34, 0x98, 0x47, 0x1D, 0x4A, 0x1E, 0x49, ++0x13, 0x68, 0x23, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0x0F, 0x03, 0x3B, 0x60, 0x02, 0x20, 0x24, 0xF0, ++0x27, 0xF9, 0x33, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x02, 0xD1, 0x17, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD5, 0xF8, 0x80, 0x32, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x0D, 0x4A, 0x53, 0x6D, 0x23, 0xF0, 0x02, 0x03, 0x53, 0x65, 0x9D, 0xE7, 0x11, 0x49, ++0x02, 0x20, 0x24, 0xF0, 0x11, 0xF9, 0xE8, 0xE7, 0x2C, 0x19, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, ++0xC8, 0x35, 0x17, 0x00, 0x30, 0x36, 0x17, 0x00, 0xAC, 0x35, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x00, 0x58, 0x40, 0x70, 0x76, 0x15, 0x00, 0x10, 0x00, 0x58, 0x40, ++0x80, 0x76, 0x15, 0x00, 0x00, 0x41, 0x04, 0x40, 0x8C, 0x76, 0x15, 0x00, 0x3C, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x20, 0x4B, ++0x04, 0x46, 0x1E, 0x68, 0x1D, 0x68, 0x00, 0xF0, 0xAB, 0xFE, 0x07, 0x46, 0x00, 0xF0, 0xAA, 0xFE, 0x01, 0x2C, 0xC6, 0xF3, ++0x03, 0x26, 0xC5, 0xF3, 0xC0, 0x65, 0x14, 0xD0, 0x02, 0x2C, 0x0E, 0xD0, 0x3C, 0xB1, 0x18, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x1C, 0xDB, 0x00, 0x20, 0xF8, 0xBD, 0x90, 0xB9, 0x05, 0xBB, 0x70, 0x1E, 0x18, 0xBF, 0x01, 0x20, ++0xF8, 0xBD, 0x01, 0x2E, 0x0D, 0xD0, 0x68, 0x1D, 0xF8, 0xBD, 0x30, 0xB9, 0x01, 0x2E, 0x17, 0xD0, 0x00, 0x2F, 0x0C, 0xBF, ++0x03, 0x20, 0x09, 0x20, 0xF8, 0xBD, 0x0B, 0x20, 0xF8, 0xBD, 0x0A, 0x20, 0xF8, 0xBD, 0x00, 0x2D, 0x14, 0xBF, 0x07, 0x20, ++0x04, 0x20, 0xF8, 0xBD, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xB5, 0x12, 0x24, 0xF0, 0xDC, 0xFA, 0x00, 0x20, 0xF8, 0xBD, ++0x08, 0x20, 0xF8, 0xBD, 0x02, 0x20, 0xF8, 0xBD, 0x00, 0x00, 0x33, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x10, 0xB4, 0x09, 0x49, 0x0B, 0x69, 0x83, 0xB0, 0x18, 0x44, 0x20, 0x24, 0x01, 0x94, 0x01, 0x9B, ++0x5A, 0x1E, 0x01, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x0B, 0x69, 0x1B, 0x1A, 0x00, 0x2B, 0xF5, 0xDB, 0x03, 0xB0, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x08, 0xB5, 0xFF, 0xF7, 0x9D, 0xFF, 0x03, 0x4B, 0x1A, 0x78, 0x82, 0x42, ++0x18, 0xBF, 0x18, 0x70, 0x08, 0xBD, 0x00, 0xBF, 0x60, 0x25, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4B, 0x10, 0x4C, 0x18, 0x68, ++0xC0, 0xF3, 0x01, 0x60, 0xFF, 0xF7, 0x8C, 0xFF, 0x08, 0x22, 0x05, 0x46, 0x00, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0xB6, 0xFD, ++0x0B, 0x48, 0x0C, 0x4A, 0x00, 0xEB, 0x05, 0x10, 0xFF, 0x21, 0xC3, 0x88, 0x80, 0x88, 0x10, 0x60, 0xC3, 0xF3, 0x85, 0x12, ++0x03, 0xF0, 0x3F, 0x03, 0x1A, 0x44, 0x21, 0x70, 0x4F, 0xF4, 0x96, 0x63, 0xB3, 0xFB, 0xF2, 0xF3, 0x63, 0x70, 0x38, 0xBD, ++0x00, 0x00, 0x33, 0x40, 0x60, 0x25, 0x17, 0x00, 0x98, 0x76, 0x15, 0x00, 0x6C, 0x00, 0x34, 0x40, 0x01, 0x4B, 0x58, 0x78, ++0x70, 0x47, 0x00, 0xBF, 0x60, 0x25, 0x17, 0x00, 0x10, 0xB4, 0x13, 0x4B, 0x13, 0x49, 0x11, 0x22, 0x1A, 0x60, 0x08, 0x69, ++0x83, 0xB0, 0x0A, 0x30, 0x20, 0x24, 0x00, 0x94, 0x00, 0x9B, 0x5A, 0x1E, 0x00, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x0A, 0x69, ++0x12, 0x1A, 0x00, 0x2A, 0xF5, 0xDB, 0x0A, 0x4A, 0x0A, 0x4C, 0x13, 0x60, 0x09, 0x69, 0x20, 0x20, 0x0A, 0x31, 0x01, 0x90, ++0x01, 0x9B, 0x5A, 0x1E, 0x01, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x23, 0x69, 0x5B, 0x1A, 0x00, 0x2B, 0xF5, 0xDB, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x00, 0x34, 0x40, 0x00, 0x10, 0x50, 0x40, 0x16, 0x4A, 0x13, 0x68, ++0x43, 0xF4, 0x80, 0x53, 0x10, 0xB4, 0x13, 0x60, 0x00, 0xBF, 0x02, 0xF5, 0x99, 0x42, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x53, ++0x13, 0x60, 0x00, 0xBF, 0x10, 0x4B, 0x11, 0x48, 0x03, 0xF5, 0x00, 0x64, 0xC0, 0x1A, 0x1A, 0x18, 0x53, 0xF8, 0x04, 0x1B, ++0x11, 0x60, 0xA3, 0x42, 0xF9, 0xD1, 0x00, 0xBF, 0x09, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x00, 0xBF, ++0x1A, 0x68, 0x22, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x00, 0xBF, 0x07, 0x4A, 0x5D, 0xF8, 0x04, 0x4B, 0x13, 0x68, 0x23, 0xF0, ++0x00, 0x53, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x90, 0xB3, 0x33, 0x40, 0xB0, 0x05, 0x17, 0x00, 0x00, 0xA0, 0x33, 0x40, ++0x10, 0x00, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x15, 0x46, 0x1C, 0x46, 0x9D, 0xF8, 0x18, 0x80, 0x0E, 0x46, ++0xFF, 0xF7, 0x94, 0xFF, 0x6C, 0x4A, 0x13, 0x68, 0x01, 0x2F, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x00, 0xF0, 0x98, 0x80, ++0x69, 0x4A, 0x6A, 0x49, 0x13, 0x68, 0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x40, 0x43, 0x13, 0x60, 0x0B, 0x68, 0x02, 0xF5, ++0xD9, 0x32, 0x02, 0xF5, 0xA2, 0x72, 0x43, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, ++0x61, 0x4A, 0x10, 0x68, 0x20, 0xF4, 0xFF, 0x40, 0x20, 0xF0, 0x7F, 0x00, 0x4F, 0xF0, 0x80, 0x63, 0xB3, 0xFB, 0xF5, 0xF3, ++0xC3, 0xF3, 0x0E, 0x03, 0x03, 0x43, 0x01, 0x2C, 0x13, 0x60, 0x60, 0xD0, 0x02, 0x2C, 0x48, 0xD0, 0x00, 0x25, 0x59, 0x4B, ++0x1E, 0x68, 0x26, 0xF0, 0x03, 0x06, 0x35, 0x43, 0x1D, 0x60, 0x00, 0x23, 0x56, 0x4A, 0x57, 0x49, 0x13, 0x60, 0x0B, 0x68, ++0x56, 0x4D, 0x57, 0x48, 0x57, 0x4E, 0x22, 0x06, 0x02, 0xF0, 0x40, 0x72, 0x23, 0xF0, 0x40, 0x73, 0x13, 0x43, 0x0B, 0x60, ++0x29, 0x68, 0x23, 0x04, 0x21, 0xF4, 0x40, 0x31, 0x03, 0xF4, 0x40, 0x33, 0x0B, 0x43, 0x2B, 0x60, 0x03, 0x68, 0x23, 0xF0, ++0x80, 0x43, 0x03, 0x60, 0x31, 0x68, 0x05, 0xF5, 0x82, 0x35, 0x04, 0xF0, 0x0F, 0x03, 0x21, 0xF0, 0x0F, 0x01, 0x05, 0xF5, ++0x88, 0x75, 0x0B, 0x43, 0x33, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0x40, 0x73, 0x1A, 0x43, 0x2A, 0x60, 0xEC, 0xB9, 0x50, 0xF8, ++0x08, 0x3C, 0x45, 0x49, 0x45, 0x4A, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0xC8, 0x53, 0x40, 0xF8, 0x08, 0x3C, 0x0B, 0x68, ++0x23, 0xF0, 0x30, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0x1C, 0x43, 0x13, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0xAD, 0x1B, 0x00, 0x2D, 0x42, 0xDD, 0x0A, 0x2D, 0xCC, 0xBF, 0x00, 0x25, 0x01, 0x25, 0xAF, 0xE7, 0x01, 0x2C, ++0x41, 0xD0, 0x38, 0x4A, 0x38, 0x49, 0x13, 0x68, 0x38, 0x48, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0x60, 0x63, 0x13, 0x60, ++0x08, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0xF5, 0x28, 0x42, 0xB5, 0x42, 0x53, 0x6B, 0x88, 0xBF, 0x01, 0x21, 0x23, 0xF0, ++0x03, 0x03, 0x98, 0xBF, 0x02, 0x21, 0x43, 0xEA, 0x01, 0x03, 0x02, 0xF1, 0x34, 0x02, 0x13, 0x60, 0x94, 0xBF, 0x01, 0x23, ++0x00, 0x23, 0x95, 0xE7, 0x1D, 0x49, 0x1E, 0x48, 0x0B, 0x68, 0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0xC0, 0x33, 0x0B, 0x60, ++0x03, 0x68, 0x01, 0xF5, 0xD9, 0x31, 0x01, 0xF5, 0xA2, 0x71, 0x23, 0xF0, 0x01, 0x03, 0x03, 0x60, 0x0B, 0x68, 0x18, 0xF0, ++0x04, 0x0F, 0x43, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x3F, 0xF4, 0x64, 0xAF, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, ++0x5E, 0xE7, 0x15, 0xF1, 0x0A, 0x0F, 0xB4, 0xBF, 0x03, 0x25, 0x02, 0x25, 0x6B, 0xE7, 0x1A, 0x48, 0x14, 0x49, 0x03, 0x68, ++0x14, 0x4A, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0xC0, 0x53, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x30, 0x03, 0x43, 0xF0, ++0x10, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0xD8, 0x43, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, ++0x24, 0x03, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x20, 0x08, 0x33, 0x40, 0x4C, 0x08, 0x33, 0x40, 0x80, 0xB0, 0x33, 0x40, ++0x50, 0x08, 0x33, 0x40, 0x24, 0x08, 0x33, 0x40, 0x10, 0x03, 0x32, 0x40, 0x0C, 0x08, 0x33, 0x40, 0x00, 0x08, 0x33, 0x40, ++0x08, 0x00, 0x34, 0x40, 0x8C, 0x08, 0x33, 0x40, 0x34, 0x08, 0x33, 0x40, 0x18, 0x08, 0x33, 0x40, 0x06, 0x0C, 0x8E, 0x01, ++0x04, 0x08, 0x33, 0x40, 0x44, 0x49, 0x45, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0xFC, 0x63, 0x70, 0xB4, 0x0B, 0x60, 0x13, 0x68, ++0x42, 0x4C, 0x43, 0x4D, 0x43, 0x4E, 0x23, 0xF4, 0xE0, 0x23, 0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0xE0, 0x03, 0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x23, 0x68, 0xA1, 0xF5, 0x0F, 0x41, 0x23, 0xF4, 0x00, 0x03, 0x23, 0x60, ++0x04, 0x39, 0x0C, 0x23, 0x2B, 0x60, 0x0B, 0x68, 0x32, 0x6A, 0x23, 0xF4, 0xFE, 0x43, 0x23, 0xF0, 0x7F, 0x03, 0x13, 0x43, ++0x40, 0xF6, 0xB4, 0x12, 0x90, 0x42, 0x0B, 0x60, 0x34, 0x4B, 0x26, 0xD0, 0x72, 0x6A, 0x1A, 0x60, 0xA0, 0xF6, 0x6C, 0x13, ++0x3C, 0x2B, 0x22, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, ++0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, ++0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, ++0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x00, 0x21, 0x4A, 0x1A, 0x60, 0x21, 0x4A, 0x21, 0x49, 0x13, 0x68, ++0x91, 0xF8, 0xB4, 0x10, 0x23, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x99, 0xB1, 0x1E, 0x49, 0x1F, 0x4B, 0x0A, 0x68, 0x22, 0xF4, ++0xFE, 0x62, 0x0A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x9A, 0x68, 0x22, 0xF0, ++0x0F, 0x02, 0x9A, 0x60, 0xDA, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0xDA, 0x60, 0x70, 0xBC, 0x70, 0x47, 0x15, 0x49, 0x16, 0x4B, ++0xB0, 0x6A, 0x72, 0x6B, 0x08, 0x60, 0x1A, 0x60, 0xD9, 0xE7, 0x12, 0x4B, 0xF4, 0x6A, 0xB1, 0x6B, 0x11, 0x4A, 0x1C, 0x60, ++0x40, 0xF6, 0xA8, 0x13, 0x98, 0x42, 0x11, 0x60, 0xCF, 0xD1, 0x0F, 0x4B, 0x11, 0x22, 0x1A, 0x60, 0xCB, 0xE7, 0x00, 0xBF, ++0x04, 0x40, 0x34, 0x40, 0x34, 0x21, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x00, 0xB3, 0x33, 0x40, 0xDC, 0x18, 0x17, 0x00, ++0x20, 0x03, 0x33, 0x40, 0x1B, 0x88, 0xB3, 0x01, 0x30, 0x20, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x78, 0x40, 0x34, 0x40, ++0x00, 0x30, 0x50, 0x40, 0x30, 0x40, 0x34, 0x40, 0x2C, 0x40, 0x34, 0x40, 0x24, 0x01, 0x58, 0x40, 0x70, 0x47, 0x00, 0xBF, ++0x3A, 0x49, 0x3B, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0xFC, 0x63, 0x43, 0xF4, 0xA8, 0x63, 0x30, 0xB4, 0x0B, 0x60, 0x13, 0x68, ++0x37, 0x4C, 0x38, 0x4D, 0x23, 0xF4, 0xE0, 0x23, 0x43, 0xF4, 0x00, 0x33, 0x13, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xE0, 0x03, ++0x13, 0x60, 0x23, 0x68, 0x33, 0x4A, 0xA1, 0xF5, 0x0F, 0x41, 0x43, 0xF4, 0x00, 0x03, 0x23, 0x60, 0x04, 0x39, 0x0C, 0x23, ++0x2B, 0x60, 0x0B, 0x68, 0xD4, 0x6C, 0x23, 0xF4, 0xFE, 0x43, 0x23, 0xF0, 0x7F, 0x03, 0x23, 0x43, 0x41, 0xF2, 0xC8, 0x44, ++0xA0, 0x42, 0x0B, 0x60, 0x40, 0xD8, 0x2A, 0x4B, 0x12, 0x6C, 0x1A, 0x60, 0x29, 0x4A, 0x2A, 0x4C, 0x13, 0x68, 0x2A, 0x4D, ++0x2A, 0x48, 0x2B, 0x49, 0x23, 0xF0, 0x80, 0x63, 0x13, 0x60, 0x13, 0x68, 0x94, 0xF8, 0xB4, 0x40, 0x23, 0xF0, 0x0F, 0x03, ++0x43, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x80, 0x63, 0x2B, 0x60, 0x03, 0x68, ++0x43, 0xF4, 0x70, 0x63, 0x03, 0x60, 0x0B, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x0B, 0x60, 0xDC, 0xB1, 0x01, 0xF5, 0x01, 0x51, ++0x1D, 0x4B, 0x8A, 0x68, 0x22, 0xF4, 0xFE, 0x62, 0x42, 0xF4, 0x88, 0x62, 0x8A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x0F, 0x02, ++0x42, 0xF0, 0x03, 0x02, 0x1A, 0x60, 0x9A, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x03, 0x02, 0x9A, 0x60, 0xDA, 0x68, ++0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x03, 0x02, 0x08, 0x31, 0xDA, 0x60, 0x30, 0xBC, 0x70, 0x47, 0x41, 0xF2, 0x44, 0x63, ++0x98, 0x42, 0x08, 0x4B, 0x94, 0xBF, 0x52, 0x6C, 0x92, 0x6C, 0x1A, 0x60, 0xB8, 0xE7, 0x00, 0xBF, 0x04, 0x40, 0x34, 0x40, ++0x34, 0x21, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x00, 0xB3, 0x33, 0x40, 0xDC, 0x18, 0x17, 0x00, 0x30, 0x40, 0x34, 0x40, ++0x38, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x3C, 0x40, 0x34, 0x40, 0x08, 0x01, 0x58, 0x40, 0x30, 0x20, 0x34, 0x40, ++0x00, 0x30, 0x50, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x85, 0xB0, 0x0F, 0x46, 0x9D, 0xF8, 0x3C, 0x10, ++0x02, 0x91, 0xCD, 0xE9, 0x00, 0x23, 0x05, 0x46, 0x14, 0x46, 0x1E, 0x46, 0x02, 0x46, 0x3B, 0x46, 0xAE, 0x49, 0xAF, 0x48, ++0x9D, 0xF8, 0x38, 0xA0, 0xDF, 0xF8, 0x08, 0x83, 0xDF, 0xF8, 0x08, 0x93, 0x23, 0xF0, 0x4C, 0xFD, 0xAB, 0x49, 0x22, 0x46, ++0x04, 0x20, 0x23, 0xF0, 0x97, 0xFD, 0x30, 0x46, 0xFF, 0xF7, 0x06, 0xFD, 0x39, 0x46, 0x33, 0x46, 0xD8, 0xF8, 0x40, 0x71, ++0xCD, 0xF8, 0x00, 0xA0, 0x22, 0x46, 0x28, 0x46, 0xB8, 0x47, 0x99, 0xF8, 0x2A, 0x30, 0xAB, 0x42, 0x0A, 0xD0, 0xD8, 0xF8, ++0x80, 0x34, 0x28, 0x46, 0x98, 0x47, 0x99, 0xF8, 0x2A, 0x20, 0x9F, 0x49, 0x2B, 0x46, 0x04, 0x20, 0x23, 0xF0, 0x7C, 0xFD, ++0x9D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA8, 0x80, 0x00, 0x2D, 0x00, 0xF0, 0xB7, 0x80, ++0x41, 0xF2, 0x43, 0x63, 0x9C, 0x42, 0x00, 0xF2, 0xAE, 0x80, 0x41, 0xF2, 0x7B, 0x53, 0x9C, 0x42, 0x8B, 0xBF, 0x4F, 0xF0, ++0xEC, 0x09, 0x4F, 0xF0, 0xFC, 0x09, 0x3B, 0x27, 0x3F, 0x27, 0x20, 0x46, 0x35, 0xF0, 0x0E, 0xFD, 0x02, 0x46, 0x0B, 0x46, ++0x82, 0x46, 0x8B, 0x46, 0x35, 0xF0, 0xBC, 0xFB, 0x8D, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0x98, 0xFE, 0x8C, 0x4B, 0x00, 0x22, ++0x35, 0xF0, 0x6A, 0xFD, 0x35, 0xF0, 0x62, 0xFB, 0x36, 0xF0, 0x00, 0xF8, 0x52, 0x46, 0x5B, 0x46, 0x88, 0x49, 0x05, 0x46, ++0x00, 0x20, 0x35, 0xF0, 0x89, 0xFE, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x35, 0xF0, 0x5A, 0xFD, 0x35, 0xF0, 0x52, 0xFB, ++0x35, 0xF0, 0xF0, 0xFF, 0x03, 0x46, 0x38, 0x46, 0x1F, 0x46, 0x35, 0xF0, 0xE7, 0xFC, 0x80, 0x4B, 0x00, 0x22, 0x35, 0xF0, ++0x4D, 0xFD, 0x02, 0x46, 0x0B, 0x46, 0x50, 0x46, 0x59, 0x46, 0x35, 0xF0, 0x71, 0xFE, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, ++0x35, 0xF0, 0x42, 0xFD, 0x35, 0xF0, 0x3A, 0xFB, 0x35, 0xF0, 0xD8, 0xFF, 0x77, 0x4B, 0x78, 0x4A, 0xD3, 0xF8, 0x00, 0xE0, ++0x2E, 0xF4, 0x00, 0x0E, 0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x4E, 0xF4, 0x80, 0x0E, 0xC3, 0xF8, 0x00, 0xE0, ++0xD3, 0xF8, 0x00, 0xE0, 0x2E, 0xF4, 0x00, 0x1E, 0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x4E, 0xF0, 0x08, 0x0E, ++0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x01, 0x46, 0x2E, 0xF0, 0x04, 0x0E, 0x6A, 0x48, 0xC3, 0xF8, 0x00, 0xE0, ++0x03, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x03, 0x60, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x53, 0x03, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0xFF, 0x63, 0x23, 0xF0, 0x04, 0x03, 0x43, 0xEA, 0x09, 0x03, 0x13, 0x60, 0x20, 0x46, 0xD8, 0xF8, 0xA8, 0x34, 0x89, 0x46, ++0x98, 0x47, 0x20, 0x46, 0xD8, 0xF8, 0xAC, 0x34, 0x64, 0x08, 0x98, 0x47, 0x5C, 0x4B, 0x5D, 0x4A, 0x1D, 0x60, 0x17, 0x60, ++0xC3, 0xF8, 0x48, 0x90, 0x00, 0x2E, 0x00, 0xF0, 0x8D, 0x80, 0x01, 0x2E, 0x04, 0xD1, 0x59, 0x4A, 0x13, 0x68, 0x23, 0xF4, ++0x00, 0x63, 0x13, 0x60, 0x57, 0x49, 0x58, 0x4B, 0x08, 0x68, 0x58, 0x4A, 0x03, 0x40, 0x43, 0xEA, 0x04, 0x33, 0x01, 0x20, ++0x0B, 0x60, 0x10, 0x60, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x2D, 0x7F, 0xF6, 0x55, 0xAF, 0x52, 0x49, 0x53, 0x48, ++0x40, 0xF6, 0x4A, 0x22, 0x23, 0xF0, 0xEE, 0xFE, 0x41, 0xF2, 0x43, 0x63, 0x9C, 0x42, 0x7F, 0xF6, 0x52, 0xAF, 0x4F, 0xF0, ++0xF0, 0x09, 0x3C, 0x27, 0x57, 0xE7, 0x20, 0x46, 0x35, 0xF0, 0x66, 0xFC, 0x4B, 0x4B, 0x00, 0x22, 0x82, 0x46, 0x8B, 0x46, ++0x35, 0xF0, 0xCA, 0xFC, 0x39, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0xF0, 0xFD, 0x38, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0xC2, 0xFC, ++0x35, 0xF0, 0xBA, 0xFA, 0x35, 0xF0, 0x58, 0xFF, 0x52, 0x46, 0x5B, 0x46, 0x05, 0x46, 0x42, 0x49, 0x00, 0x20, 0x35, 0xF0, ++0xE1, 0xFD, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x35, 0xF0, 0xB2, 0xFC, 0x35, 0xF0, 0xAA, 0xFA, 0x35, 0xF0, 0x48, 0xFF, ++0x24, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x07, 0x46, 0x59, 0x46, 0x50, 0x46, 0x35, 0xF0, 0xD0, 0xFD, 0x00, 0x22, 0x4F, 0xF0, ++0x83, 0x43, 0x35, 0xF0, 0xA1, 0xFC, 0x35, 0xF0, 0x99, 0xFA, 0x35, 0xF0, 0x37, 0xFF, 0x27, 0x4B, 0x28, 0x4A, 0x19, 0x68, ++0x21, 0xF4, 0x00, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x80, 0x01, 0x19, 0x60, 0x19, 0x68, 0x41, 0xF4, 0x00, 0x11, ++0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x08, 0x01, 0x19, 0x60, 0x19, 0x68, 0x41, 0xF0, 0x04, 0x01, 0x19, 0x60, 0x13, 0x68, ++0x23, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x81, 0x46, 0x23, 0xF0, 0x00, 0x53, 0x19, 0x48, 0x13, 0x60, 0x03, 0x68, ++0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, 0x04, 0x03, 0x43, 0xF0, 0xEC, 0x03, 0x03, 0x60, 0xD8, 0xF8, 0xA0, 0x34, 0x20, 0x46, ++0x98, 0x47, 0xD8, 0xF8, 0xA4, 0x34, 0x20, 0x46, 0x98, 0x47, 0x69, 0xE7, 0x13, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x63, ++0x13, 0x60, 0x73, 0xE7, 0xAF, 0xF3, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xA2, 0x40, 0x78, 0x78, 0x15, 0x00, ++0x58, 0x77, 0x15, 0x00, 0x8C, 0x77, 0x15, 0x00, 0x9C, 0x77, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x00, 0x6A, 0x40, ++0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0xB9, 0x40, 0x00, 0x00, 0x54, 0x40, 0x14, 0x40, 0x34, 0x40, 0x3C, 0x40, 0x34, 0x40, ++0x30, 0x40, 0x34, 0x40, 0x10, 0x20, 0x34, 0x40, 0x54, 0x20, 0x34, 0x40, 0x20, 0x40, 0x34, 0x40, 0x1C, 0x20, 0x34, 0x40, ++0xFF, 0x0F, 0x00, 0xE0, 0x84, 0x21, 0x34, 0x40, 0x70, 0x79, 0x15, 0x00, 0xB4, 0x77, 0x15, 0x00, 0x00, 0x00, 0x10, 0x40, ++0x00, 0x00, 0xA4, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0xF8, 0xB5, 0x43, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x6B, 0xDB, 0xFF, 0xF7, 0xBD, 0xFB, 0x40, 0x49, 0x40, 0x4A, 0x0B, 0x68, 0x40, 0x48, 0x43, 0xF0, ++0x00, 0x63, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x03, 0x68, 0xC3, 0xF3, 0x03, 0x23, 0x02, 0x2B, ++0x06, 0xD1, 0xA2, 0xF5, 0x99, 0x42, 0x04, 0x3A, 0x13, 0x68, 0x43, 0xF0, 0x03, 0x03, 0x13, 0x60, 0x36, 0x4B, 0x1B, 0x68, ++0xC3, 0xF3, 0x03, 0x13, 0x02, 0x2B, 0x02, 0xD1, 0x34, 0x4B, 0x35, 0x4A, 0x1A, 0x60, 0x35, 0x4A, 0x35, 0x49, 0x13, 0x68, ++0xDF, 0xF8, 0x04, 0xC1, 0x34, 0x4D, 0x35, 0x4F, 0x35, 0x4C, 0x36, 0x48, 0x36, 0x4E, 0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, ++0x07, 0x03, 0x43, 0xF4, 0xE0, 0x63, 0x13, 0x60, 0x4F, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x04, 0x23, 0xCC, 0xF8, 0x00, 0x30, ++0x01, 0x22, 0xC4, 0x23, 0x3A, 0x60, 0x2B, 0x60, 0x00, 0x23, 0x23, 0x60, 0x6F, 0x24, 0x04, 0x60, 0x2C, 0x4C, 0xB0, 0x27, ++0x37, 0x60, 0x23, 0x60, 0xC3, 0x60, 0xAB, 0x61, 0x6B, 0x25, 0xE5, 0x60, 0x29, 0x4D, 0x83, 0x61, 0x2A, 0x60, 0xA3, 0x61, ++0x07, 0x24, 0x44, 0x62, 0xEC, 0x26, 0x27, 0x4C, 0xEE, 0x60, 0x03, 0x25, 0xC5, 0x62, 0x23, 0x60, 0xD0, 0xF8, 0xEC, 0x31, ++0x93, 0x42, 0x00, 0xF5, 0xF6, 0x70, 0x0F, 0xD9, 0x22, 0x4B, 0xA0, 0xF5, 0x56, 0x70, 0x1A, 0x60, 0x03, 0x68, 0x23, 0xF0, ++0x7F, 0x43, 0x43, 0xF0, 0x20, 0x43, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x40, 0x73, 0x43, 0xF4, 0x80, 0x73, 0x0B, 0x60, ++0xF8, 0xBD, 0x1B, 0x4A, 0x13, 0x68, 0x12, 0x68, 0x1B, 0x0E, 0x02, 0x33, 0x03, 0xEB, 0x83, 0x03, 0xC2, 0xF3, 0x07, 0x42, ++0x02, 0xEB, 0x43, 0x03, 0x1E, 0x2B, 0x86, 0xD0, 0x15, 0x49, 0x16, 0x48, 0x40, 0xF6, 0x2C, 0x32, 0x23, 0xF0, 0xBC, 0xFD, ++0x7F, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x10, 0x00, 0x34, 0x40, 0x14, 0x00, 0x34, 0x40, 0x00, 0x00, 0x33, 0x40, ++0x04, 0xB1, 0x33, 0x40, 0x34, 0x34, 0x34, 0x00, 0xB4, 0xB3, 0x33, 0x40, 0x00, 0x10, 0x34, 0x40, 0x08, 0x12, 0x34, 0x40, ++0x04, 0x12, 0x34, 0x40, 0x0C, 0x12, 0x34, 0x40, 0x10, 0x12, 0x34, 0x40, 0x14, 0x12, 0x34, 0x40, 0x18, 0x12, 0x34, 0x40, ++0x2C, 0x12, 0x34, 0x40, 0x40, 0x12, 0x34, 0x40, 0x0C, 0x10, 0x34, 0x40, 0x3C, 0x00, 0x33, 0x40, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0x77, 0x15, 0x00, 0x00, 0x12, 0x34, 0x40, 0x10, 0xB5, 0x1A, 0x4C, 0x82, 0xB0, 0xD4, 0xF8, 0x3C, 0x31, 0x98, 0x47, ++0x18, 0x4B, 0x19, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, ++0x15, 0x4A, 0x1A, 0x60, 0x19, 0x68, 0x12, 0x4A, 0x41, 0xF0, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xDB, ++0x11, 0x4B, 0x13, 0x60, 0x13, 0x68, 0x0D, 0x49, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x0B, 0x68, 0xDB, 0x0F, 0xFC, 0xD1, ++0xCD, 0xE9, 0x00, 0x33, 0x40, 0xF6, 0x85, 0x12, 0x11, 0x46, 0x18, 0x46, 0xD4, 0xF8, 0x28, 0x42, 0xA0, 0x47, 0x09, 0x49, ++0x09, 0x4B, 0x0A, 0x4A, 0x0C, 0x20, 0x08, 0x60, 0x1A, 0x60, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0x20, 0x00, 0x58, 0x40, 0xBF, 0x3F, 0x42, 0x01, 0xA2, 0x30, 0x43, 0x01, 0xDD, 0x1D, 0x44, 0x01, 0x00, 0xB3, 0x33, 0x40, ++0xC0, 0xB3, 0x33, 0x40, 0xA0, 0xA0, 0x28, 0x28, 0x70, 0xB5, 0x13, 0x4B, 0x13, 0x4D, 0x04, 0x46, 0xED, 0x1A, 0x03, 0xF2, ++0x3C, 0x50, 0x5A, 0x19, 0x53, 0xF8, 0x04, 0x1B, 0x11, 0x60, 0x83, 0x42, 0xF9, 0xD1, 0xFF, 0xF7, 0xEB, 0xFA, 0x0E, 0x4B, ++0x0E, 0x4E, 0xD3, 0xF8, 0x24, 0x32, 0x20, 0x46, 0x98, 0x47, 0x00, 0x23, 0x86, 0xF8, 0x2A, 0x30, 0x0F, 0xCC, 0x35, 0x46, ++0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, 0x23, 0x68, 0x2B, 0x60, 0x05, 0x21, 0x4F, 0xF0, 0xFF, 0x12, 0xFF, 0x23, 0x86, 0xF8, ++0x2B, 0x10, 0x72, 0x62, 0x33, 0x85, 0x70, 0xBD, 0xB0, 0x0D, 0x17, 0x00, 0x00, 0x90, 0x33, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0x08, 0xB5, 0x05, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x00, 0xD4, 0x08, 0xBD, 0x14, 0xF0, 0xF4, 0xFD, ++0x02, 0x4B, 0x08, 0x22, 0x1A, 0x60, 0x08, 0xBD, 0xA8, 0x10, 0x34, 0x40, 0xAC, 0x10, 0x34, 0x40, 0x03, 0x4A, 0x04, 0x4B, ++0x12, 0x68, 0x02, 0x60, 0x1B, 0x68, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x3C, 0x00, 0x33, 0x40, ++0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0x9D, 0xF8, 0x38, 0x40, 0xBD, 0xF8, 0x30, 0xA0, 0x9D, 0xF8, 0x34, 0x90, 0x00, 0x2C, ++0x43, 0xD1, 0x98, 0x46, 0x25, 0x4B, 0x1B, 0x78, 0x05, 0x46, 0x0E, 0x46, 0x17, 0x46, 0xD3, 0xB1, 0x23, 0x4C, 0x24, 0x4A, ++0xCD, 0xF8, 0x00, 0x90, 0x00, 0x23, 0xD2, 0xF8, 0x28, 0xB2, 0x01, 0x93, 0x42, 0x46, 0x33, 0x46, 0x39, 0x46, 0x28, 0x46, ++0xD8, 0x47, 0x84, 0xF8, 0x2A, 0x50, 0x84, 0xF8, 0x2B, 0x60, 0x84, 0xF8, 0x2C, 0x90, 0xA7, 0x84, 0xA4, 0xF8, 0x26, 0x80, ++0xA4, 0xF8, 0x28, 0xA0, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0x4A, 0x15, 0x4C, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, ++0x13, 0x60, 0x94, 0xF8, 0x2A, 0x30, 0x83, 0x42, 0xDB, 0xD1, 0x94, 0xF8, 0x2B, 0x30, 0x8B, 0x42, 0xD7, 0xD1, 0x94, 0xF8, ++0x2C, 0x30, 0x4B, 0x45, 0xD3, 0xD1, 0xA3, 0x8C, 0xBB, 0x42, 0xD0, 0xD1, 0xE3, 0x8C, 0x43, 0x45, 0xCD, 0xD1, 0x23, 0x8D, ++0x53, 0x45, 0xCA, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x23, 0xF0, 0x35, 0xBA, 0x08, 0x49, ++0x09, 0x48, 0x22, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x23, 0xF0, 0x2D, 0xBA, 0x00, 0xBF, 0x3C, 0x36, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x8C, 0x78, 0x15, 0x00, 0x38, 0x78, 0x15, 0x00, ++0x18, 0x78, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x71, 0xB9, 0x0A, 0x4A, 0x93, 0x8C, 0x92, 0xF8, 0x2B, 0x00, 0x92, 0xF8, ++0x2A, 0x10, 0xD2, 0xF8, 0x26, 0x20, 0x62, 0x60, 0x1B, 0x04, 0x43, 0xEA, 0x00, 0x23, 0x0B, 0x43, 0x23, 0x60, 0x10, 0xBD, ++0x0A, 0x46, 0x03, 0x48, 0x03, 0x49, 0x23, 0xF0, 0x07, 0xFA, 0xEA, 0xE7, 0xBC, 0x34, 0x17, 0x00, 0x18, 0x78, 0x15, 0x00, ++0x9C, 0x78, 0x15, 0x00, 0x04, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x00, 0xD1, 0x70, 0x47, 0x03, 0x49, 0x03, 0x48, 0x23, 0xF0, ++0xF7, 0xB9, 0x00, 0xBF, 0x38, 0x00, 0x32, 0x40, 0xAC, 0x78, 0x15, 0x00, 0x60, 0x78, 0x15, 0x00, 0x4F, 0xF4, 0x7A, 0x70, ++0x70, 0x47, 0x00, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0x01, 0x28, 0x94, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x00, 0xBF, ++0xFC, 0x13, 0x34, 0x40, 0x04, 0x4A, 0x13, 0x68, 0xC0, 0x00, 0x00, 0xF0, 0x08, 0x00, 0x23, 0xF0, 0x08, 0x03, 0x18, 0x43, ++0x10, 0x60, 0x70, 0x47, 0xA0, 0x10, 0x34, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x80, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x00, 0x33, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x00, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, ++0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x80, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x06, 0x4B, 0x02, 0x68, ++0x1A, 0x60, 0x42, 0x68, 0x5A, 0x60, 0x0A, 0x68, 0x9A, 0x60, 0x4A, 0x68, 0xDA, 0x60, 0x8A, 0x68, 0x1A, 0x61, 0xCA, 0x68, ++0x5A, 0x61, 0x70, 0x47, 0xA8, 0x08, 0x33, 0x40, 0x30, 0xB4, 0x06, 0x49, 0x06, 0x4D, 0x07, 0x4B, 0x00, 0x24, 0xC0, 0xF3, ++0x0A, 0x00, 0x40, 0xF2, 0xFF, 0x72, 0x28, 0x60, 0x0C, 0x60, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0xC4, 0x08, 0x33, 0x40, ++0xC0, 0x08, 0x33, 0x40, 0xC8, 0x08, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x03, 0x20, 0x01, 0x38, 0xC0, 0xB2, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x03, 0x10, 0x01, 0x38, 0xC0, 0xB2, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0x00, 0xF0, 0x0F, 0x00, 0x01, 0x38, 0xC0, 0xB2, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0xF0, 0xB5, 0xBE, 0x4C, 0x94, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x76, 0xD1, ++0xBC, 0x4B, 0x93, 0xF8, 0xBD, 0x50, 0x00, 0x2D, 0x66, 0xD0, 0xE0, 0x8C, 0x40, 0xF6, 0x7B, 0x14, 0xA0, 0x42, 0x40, 0xF2, ++0xCA, 0x80, 0x40, 0xF6, 0x94, 0x14, 0xA0, 0x42, 0xB6, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x01, 0x60, 0x90, 0xF9, 0x02, 0x60, ++0x93, 0xF8, 0xBE, 0x40, 0xB3, 0x48, 0x06, 0xF1, 0x0F, 0x05, 0x1E, 0x2D, 0x00, 0x5D, 0xA8, 0xBF, 0x1E, 0x25, 0x0A, 0x2C, ++0x4F, 0xEA, 0x20, 0x17, 0x00, 0xF0, 0x0F, 0x0C, 0x25, 0xEA, 0xE5, 0x75, 0x00, 0xF3, 0xCF, 0x80, 0x00, 0xF0, 0xE4, 0x80, ++0xAB, 0x48, 0x04, 0xEB, 0x44, 0x04, 0x10, 0xF9, 0x14, 0xE0, 0x75, 0x45, 0x00, 0xEB, 0x44, 0x04, 0x00, 0xF3, 0x06, 0x81, ++0x64, 0x78, 0xA4, 0xEB, 0x0E, 0x04, 0x2C, 0x44, 0x60, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, 0x07, 0xF1, 0xFF, 0x37, ++0xB8, 0xBF, 0x20, 0x46, 0x60, 0x44, 0x80, 0xF3, 0x04, 0x00, 0x40, 0xEA, 0x07, 0x10, 0x08, 0x70, 0x93, 0xF8, 0xBF, 0x10, ++0x9D, 0x4B, 0x5B, 0x5C, 0x0A, 0x29, 0x4F, 0xEA, 0x23, 0x10, 0x03, 0xF0, 0x0F, 0x03, 0x17, 0xDC, 0x00, 0xF0, 0xD1, 0x80, ++0x01, 0x31, 0x97, 0x4C, 0x01, 0xEB, 0x41, 0x01, 0x14, 0xF9, 0x11, 0x60, 0xAE, 0x42, 0x04, 0xEB, 0x41, 0x01, 0xC0, 0xF2, ++0xD2, 0x80, 0x49, 0x78, 0x89, 0x1B, 0x0D, 0x44, 0x6D, 0xB2, 0x6F, 0xF0, 0x04, 0x01, 0x01, 0x38, 0x8D, 0x42, 0xAC, 0xBF, ++0x5B, 0x19, 0x5B, 0x18, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x00, 0x13, 0x13, 0x70, 0xF0, 0xBD, 0x93, 0xF8, 0xAC, 0x40, ++0xE5, 0x07, 0x68, 0xD5, 0x93, 0xF8, 0xB7, 0x00, 0x08, 0x70, 0x93, 0xF8, 0xAD, 0x30, 0x13, 0x70, 0xF0, 0xBD, 0x81, 0x4B, ++0x93, 0xF8, 0xBD, 0x50, 0x00, 0x2D, 0x3A, 0xD0, 0xE0, 0x8C, 0x41, 0xF2, 0xC8, 0x44, 0xA0, 0x42, 0x4F, 0xD9, 0xB0, 0xF5, ++0xAF, 0x5F, 0x7D, 0xD8, 0x7F, 0x48, 0x90, 0xF9, 0x01, 0x60, 0x93, 0xF8, 0xC3, 0x00, 0x7E, 0x4B, 0x1B, 0x5C, 0x0A, 0x28, ++0x4F, 0xEA, 0x23, 0x15, 0x03, 0xF0, 0x0F, 0x03, 0x1D, 0xDC, 0x06, 0xF1, 0x0F, 0x04, 0x1E, 0x2C, 0xA8, 0xBF, 0x1E, 0x24, ++0x0A, 0x28, 0x24, 0xEA, 0xE4, 0x74, 0x7A, 0xD0, 0x76, 0x4E, 0x00, 0xEB, 0x40, 0x00, 0x16, 0xF9, 0x10, 0x70, 0xBC, 0x42, ++0x06, 0xEB, 0x40, 0x00, 0x00, 0xF3, 0x9E, 0x80, 0x40, 0x78, 0xC0, 0x1B, 0x04, 0x44, 0x64, 0xB2, 0x6F, 0xF0, 0x04, 0x00, ++0x01, 0x3D, 0x84, 0x42, 0xAC, 0xBF, 0x1B, 0x19, 0x1B, 0x18, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x05, 0x13, 0xDB, 0xB2, ++0x13, 0x70, 0x0B, 0x70, 0xF0, 0xBD, 0x93, 0xF8, 0xAC, 0x40, 0xA4, 0x07, 0x04, 0xD5, 0x93, 0xF8, 0xAE, 0x30, 0x0B, 0x70, ++0x13, 0x70, 0xF0, 0xBD, 0x90, 0xF9, 0x00, 0x30, 0x61, 0x48, 0x6F, 0xF0, 0x04, 0x04, 0xA3, 0x42, 0xB8, 0xBF, 0x23, 0x46, ++0x12, 0x2B, 0xA8, 0xBF, 0x12, 0x23, 0x05, 0x33, 0x5B, 0x10, 0xC3, 0x5C, 0x0B, 0x70, 0x13, 0x70, 0xF0, 0xBD, 0x59, 0x48, ++0x90, 0xF9, 0x00, 0x60, 0xB1, 0xE7, 0x53, 0x48, 0x90, 0xF9, 0x00, 0x60, 0x3A, 0xE7, 0x90, 0xF9, 0x00, 0x30, 0x51, 0x4D, ++0x52, 0x4C, 0x01, 0x2B, 0x6F, 0xF0, 0x01, 0x06, 0x18, 0x46, 0xB8, 0xBF, 0x01, 0x20, 0xB3, 0x42, 0xB8, 0xBF, 0x33, 0x46, ++0x17, 0x28, 0xA8, 0xBF, 0x17, 0x20, 0x14, 0x2B, 0xA8, 0xBF, 0x14, 0x23, 0x01, 0x38, 0x02, 0x33, 0x40, 0x10, 0x5B, 0x10, ++0x28, 0x5C, 0xE3, 0x5C, 0x08, 0x70, 0x13, 0x70, 0xF0, 0xBD, 0x74, 0x1C, 0x55, 0xDA, 0xA5, 0xF1, 0x0D, 0x00, 0x40, 0xB2, ++0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, 0xA7, 0xF1, 0x02, 0x07, 0xB8, 0xBF, 0x20, 0x46, 0x3B, 0xE7, 0x41, 0xF2, 0x44, 0x64, ++0xA0, 0x42, 0x3F, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x02, 0x60, 0x90, 0xF9, 0x03, 0x60, 0x7A, 0xE7, 0xB0, 0x1C, 0x53, 0xDB, ++0x01, 0x2E, 0x00, 0xF3, 0x8D, 0x80, 0xA5, 0xF1, 0x0F, 0x00, 0x40, 0xB2, 0x28, 0xE7, 0x03, 0x36, 0x43, 0xDA, 0x09, 0x3C, ++0x64, 0xB2, 0x6F, 0xF0, 0x04, 0x00, 0x01, 0x3D, 0x84, 0x42, 0xAC, 0xBF, 0x1B, 0x19, 0x1B, 0x18, 0x8D, 0xE7, 0x03, 0x36, ++0x30, 0xDA, 0x09, 0x3D, 0x6D, 0xB2, 0x6F, 0xF0, 0x04, 0x01, 0x01, 0x38, 0x8D, 0x42, 0xAC, 0xBF, 0x5B, 0x19, 0x5B, 0x18, ++0x38, 0xE7, 0x91, 0xF9, 0x04, 0x40, 0xAC, 0x42, 0x3B, 0xDD, 0xCC, 0x78, 0x89, 0x78, 0x61, 0x1A, 0x0D, 0x44, 0x43, 0xFA, ++0x85, 0xF3, 0x2D, 0xE7, 0x94, 0xF9, 0x04, 0xE0, 0x75, 0x45, 0x57, 0xDA, 0xE0, 0x78, 0xA4, 0x78, 0x00, 0x1B, 0x28, 0x44, ++0x40, 0xB2, 0xFB, 0xE6, 0x90, 0xF9, 0x04, 0x60, 0xB4, 0x42, 0x43, 0xDA, 0xC6, 0x78, 0x80, 0x78, 0x30, 0x1A, 0x04, 0x44, ++0x43, 0xFA, 0x84, 0xF3, 0x61, 0xE7, 0xA5, 0xF1, 0x0F, 0x04, 0x60, 0xB2, 0x03, 0x28, 0xA8, 0xBF, 0x03, 0x20, 0xE9, 0xE6, ++0x0F, 0x3D, 0x6D, 0xB2, 0x05, 0x2D, 0xD4, 0xBF, 0x5B, 0x19, 0x05, 0x33, 0x0A, 0xE7, 0x0F, 0x3C, 0x64, 0xB2, 0x05, 0x2C, ++0xD4, 0xBF, 0x1B, 0x19, 0x05, 0x33, 0x4C, 0xE7, 0xA5, 0xF1, 0x0A, 0x00, 0x40, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, ++0x07, 0xF1, 0xFF, 0x37, 0xB8, 0xBF, 0x20, 0x46, 0xD0, 0xE6, 0x49, 0x79, 0x09, 0x1B, 0x0D, 0x44, 0x6D, 0xB2, 0x05, 0x2D, ++0xD4, 0xBF, 0x5B, 0x19, 0x05, 0x33, 0x01, 0x30, 0xEE, 0xE6, 0x00, 0xBF, 0xBC, 0x34, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0x68, 0x25, 0x17, 0x00, 0xEC, 0x12, 0x17, 0x00, 0xB8, 0x78, 0x15, 0x00, 0xF8, 0x12, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, ++0x04, 0x13, 0x17, 0x00, 0x0C, 0x79, 0x15, 0x00, 0x40, 0x79, 0x80, 0x1B, 0x04, 0x44, 0x64, 0xB2, 0x05, 0x2C, 0xD4, 0xBF, ++0x1B, 0x19, 0x05, 0x33, 0x01, 0x35, 0x1A, 0xE7, 0x60, 0x79, 0xA0, 0xEB, 0x0E, 0x00, 0x28, 0x44, 0x40, 0xB2, 0x05, 0x28, ++0xA8, 0xBF, 0x05, 0x20, 0x01, 0x37, 0x9F, 0xE6, 0xA5, 0xF1, 0x11, 0x00, 0x40, 0xB2, 0x03, 0x28, 0x07, 0xF1, 0x02, 0x07, ++0xA8, 0xBF, 0x03, 0x20, 0x96, 0xE6, 0x00, 0xBF, 0xF0, 0xB4, 0xB9, 0x4B, 0x93, 0xF8, 0x2A, 0x20, 0xDC, 0x8C, 0x52, 0xBB, ++0xC0, 0xB9, 0x03, 0x29, 0x00, 0xF2, 0x91, 0x80, 0xB5, 0x4A, 0xB6, 0x4B, 0x92, 0xF8, 0xBE, 0x50, 0x5B, 0x5D, 0x02, 0x46, ++0x01, 0x46, 0x07, 0x46, 0x40, 0xF6, 0x7B, 0x10, 0x84, 0x42, 0x00, 0xF2, 0xBA, 0x80, 0xB1, 0x48, 0x90, 0xF9, 0x00, 0x60, ++0x00, 0x29, 0x00, 0xF0, 0xC0, 0x80, 0xD8, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x04, 0x28, 0x40, 0xF2, 0x8F, 0x80, 0x09, 0x29, ++0x40, 0xF2, 0x8E, 0x80, 0xA7, 0x4B, 0x93, 0xF8, 0xC2, 0x50, 0x08, 0x2D, 0x40, 0xF3, 0x17, 0x81, 0x01, 0x21, 0x0F, 0x46, ++0x09, 0x25, 0xD4, 0x23, 0xE0, 0xE7, 0x04, 0x28, 0x44, 0xD9, 0x09, 0x29, 0x44, 0xD9, 0xA0, 0x4B, 0xA2, 0x49, 0x93, 0xF8, ++0xC6, 0x30, 0x09, 0x2B, 0xA8, 0xBF, 0x09, 0x23, 0x41, 0xF2, 0xC8, 0x42, 0x94, 0x42, 0xC8, 0x5C, 0x4F, 0xF0, 0x00, 0x05, ++0x53, 0xD9, 0xB4, 0xF5, 0xAF, 0x5F, 0x00, 0xF2, 0xCC, 0x80, 0x9B, 0x4A, 0x92, 0xF9, 0x01, 0x20, 0x00, 0x2D, 0xD1, 0xD1, ++0x0A, 0x2B, 0x4F, 0xEA, 0x20, 0x14, 0x00, 0xF0, 0x0F, 0x00, 0x1E, 0xDC, 0x02, 0xF1, 0x0F, 0x01, 0x1E, 0x29, 0xA8, 0xBF, ++0x1E, 0x21, 0x0A, 0x2B, 0x21, 0xEA, 0xE1, 0x71, 0x00, 0xF0, 0x3C, 0x81, 0x91, 0x4A, 0x03, 0xEB, 0x43, 0x03, 0x12, 0xF9, ++0x13, 0x50, 0x8D, 0x42, 0x02, 0xEB, 0x43, 0x02, 0x80, 0xF2, 0xF6, 0x80, 0x92, 0xF9, 0x04, 0x50, 0x8D, 0x42, 0x40, 0xF3, ++0x40, 0x81, 0xD3, 0x78, 0x92, 0x78, 0x9B, 0x1A, 0x19, 0x44, 0x40, 0xFA, 0x81, 0xF0, 0x80, 0xF3, 0x04, 0x00, 0x40, 0xEA, ++0x04, 0x10, 0xC0, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x01, 0x28, 0x0C, 0xD9, 0x07, 0x29, 0x2C, 0xD8, 0x04, 0x29, 0x0A, 0xD8, ++0x7B, 0x4B, 0x93, 0xF8, 0xC3, 0x30, 0xA3, 0xF1, 0x0B, 0x05, 0xB5, 0xFA, 0x85, 0xF5, 0x6D, 0x09, 0x09, 0xE0, 0x09, 0x29, ++0xF4, 0xD9, 0x76, 0x4B, 0x93, 0xF8, 0xC4, 0x30, 0x0A, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0xA8, 0xBF, 0x0A, 0x23, 0x75, 0x49, ++0x41, 0xF2, 0xC8, 0x42, 0x94, 0x42, 0xC8, 0x5C, 0xAB, 0xD8, 0x73, 0x4A, 0x92, 0xF9, 0x00, 0x20, 0xAE, 0xE7, 0x09, 0x29, ++0x26, 0xD8, 0x6C, 0x4B, 0x93, 0xF8, 0xBF, 0x50, 0x0B, 0x2D, 0x00, 0xF0, 0xF0, 0x80, 0x6F, 0x4B, 0x00, 0x22, 0x5B, 0x5D, ++0x11, 0x46, 0x01, 0x27, 0x68, 0xE7, 0x66, 0x4B, 0x93, 0xF8, 0xC5, 0x30, 0x09, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0xA8, 0xBF, ++0x09, 0x23, 0xDE, 0xE7, 0x01, 0x28, 0xE6, 0xD0, 0x07, 0x29, 0x0B, 0xD9, 0x5F, 0x4A, 0x65, 0x4B, 0x92, 0xF8, 0xC1, 0x50, ++0x0A, 0x2D, 0xA8, 0xBF, 0x0A, 0x25, 0x00, 0x22, 0x5B, 0x5D, 0x11, 0x46, 0x01, 0x27, 0x4F, 0xE7, 0x04, 0x29, 0xD8, 0xD9, ++0x58, 0x4A, 0x5E, 0x4B, 0x92, 0xF8, 0xC0, 0x50, 0xA5, 0xF1, 0x0B, 0x01, 0xB1, 0xFA, 0x81, 0xF1, 0x5B, 0x5D, 0x00, 0x22, ++0x49, 0x09, 0x01, 0x27, 0x40, 0xE7, 0x40, 0xF6, 0x94, 0x10, 0x84, 0x42, 0x52, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x01, 0x60, ++0x90, 0xF9, 0x02, 0x60, 0x00, 0x29, 0x7F, 0xF4, 0x40, 0xAF, 0x06, 0xF1, 0x0F, 0x01, 0x1E, 0x29, 0xA8, 0xBF, 0x1E, 0x21, ++0x0B, 0x2D, 0x21, 0xEA, 0xE1, 0x74, 0x4F, 0xEA, 0x23, 0x10, 0x29, 0x46, 0x03, 0xF0, 0x0F, 0x03, 0xA8, 0xBF, 0x0B, 0x21, ++0x00, 0x2F, 0x3B, 0xD1, 0x0A, 0x2D, 0x2C, 0xDC, 0x48, 0xD0, 0x49, 0x4D, 0x01, 0xEB, 0x41, 0x01, 0x15, 0xF9, 0x11, 0x60, ++0xB4, 0x42, 0x05, 0xEB, 0x41, 0x01, 0x34, 0xDC, 0x49, 0x78, 0x89, 0x1B, 0x21, 0x44, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, ++0x01, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x00, 0x13, 0xD8, 0xB2, ++0x00, 0x2A, 0x3F, 0xF4, 0x11, 0xAF, 0x82, 0x42, 0xBF, 0xF6, 0x0E, 0xAF, 0xD0, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x41, 0xF2, ++0x44, 0x62, 0x94, 0x42, 0x33, 0x4A, 0x94, 0xBF, 0x92, 0xF9, 0x02, 0x20, 0x92, 0xF9, 0x03, 0x20, 0x2C, 0xE7, 0x01, 0x36, ++0x2A, 0xDA, 0xA4, 0xF1, 0x0D, 0x01, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0x02, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, ++0x1B, 0x19, 0xDA, 0xE7, 0x0A, 0x2D, 0xD8, 0xDC, 0x58, 0xD0, 0x01, 0x31, 0xC1, 0xE7, 0x91, 0xF9, 0x04, 0x50, 0xAC, 0x42, ++0x1E, 0xDA, 0xCD, 0x78, 0x89, 0x78, 0x69, 0x1A, 0x21, 0x44, 0x43, 0xFA, 0x81, 0xF3, 0xCA, 0xE7, 0xB1, 0x1C, 0x2B, 0xDB, ++0x01, 0x2E, 0x76, 0xDC, 0xA4, 0xF1, 0x0F, 0x01, 0x43, 0xFA, 0x81, 0xF3, 0xC1, 0xE7, 0x1F, 0x4B, 0x08, 0xBF, 0xD4, 0x22, ++0x5B, 0x5D, 0x00, 0x21, 0x01, 0x27, 0xC7, 0xE6, 0xA4, 0xF1, 0x0F, 0x01, 0x49, 0xB2, 0x03, 0x29, 0xD4, 0xBF, 0x5B, 0x18, ++0x03, 0x33, 0xB2, 0xE7, 0x49, 0x79, 0x49, 0x1B, 0x21, 0x44, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x05, 0x33, ++0x01, 0x30, 0xA8, 0xE7, 0x53, 0x78, 0x5B, 0x1B, 0x19, 0x44, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x03, 0x01, 0x3C, 0x99, 0x42, ++0xAC, 0xBF, 0x40, 0x18, 0xC0, 0x18, 0x08, 0xE7, 0xA4, 0xF1, 0x0A, 0x01, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0x01, 0x38, ++0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x91, 0xE7, 0x00, 0xBF, 0xBC, 0x34, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xEC, 0x12, 0x17, 0x00, 0x68, 0x25, 0x17, 0x00, 0x04, 0x13, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x0C, 0x79, 0x15, 0x00, ++0xF8, 0x12, 0x17, 0x00, 0xB8, 0x78, 0x15, 0x00, 0x03, 0x36, 0x35, 0xDA, 0xA4, 0xF1, 0x09, 0x01, 0x49, 0xB2, 0x6F, 0xF0, ++0x04, 0x04, 0x01, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x71, 0xE7, 0x01, 0x21, 0x0F, 0x46, 0x00, 0x22, ++0x0F, 0x23, 0x79, 0xE6, 0x03, 0x32, 0x09, 0xDA, 0x09, 0x39, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x03, 0x01, 0x3C, 0x99, 0x42, ++0xAC, 0xBF, 0x40, 0x18, 0xC0, 0x18, 0xCC, 0xE6, 0x0F, 0x39, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x40, 0x18, 0x05, 0x30, ++0xC5, 0xE6, 0x53, 0x79, 0x5B, 0x1B, 0x19, 0x44, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x40, 0x18, 0x05, 0x30, 0x01, 0x34, ++0xBB, 0xE6, 0xA4, 0xF1, 0x11, 0x01, 0x49, 0xB2, 0x03, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x03, 0x33, 0x02, 0x30, 0x46, 0xE7, ++0xA4, 0xF1, 0x0F, 0x01, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x05, 0x33, 0x3E, 0xE7, 0x14, 0x22, 0xF6, 0x23, ++0x02, 0x70, 0x0B, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x08, 0xB5, 0x09, 0x49, 0x09, 0x48, 0x22, 0xF0, 0xF3, 0xFD, 0x09, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x08, 0xBD, 0xBD, 0xE8, 0x08, 0x40, 0x05, 0x49, 0x06, 0x48, ++0x39, 0x22, 0x23, 0xF0, 0x5F, 0xB8, 0x00, 0xBF, 0x50, 0x79, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x1F, 0x49, 0x20, 0x4A, 0x88, 0x68, 0x20, 0x4B, 0x10, 0xB4, 0xD2, 0xF8, ++0x14, 0x44, 0x04, 0x65, 0x10, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0xA0, 0x42, 0x44, 0x65, 0x20, 0x20, 0x18, 0x60, ++0x88, 0x68, 0xD2, 0xF8, 0xA0, 0x42, 0xC4, 0x65, 0x80, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0xD8, 0x40, 0x84, 0x64, ++0x04, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0x0C, 0x44, 0xC4, 0x64, 0xF8, 0x24, 0x08, 0x20, 0x83, 0xF8, 0x03, 0x43, ++0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0x1C, 0x41, 0xC0, 0xF8, 0x0C, 0x41, 0x4F, 0xF4, 0x00, 0x20, 0x58, 0x60, 0x89, 0x68, ++0xD2, 0xF8, 0x2C, 0x21, 0xC1, 0xF8, 0x10, 0x21, 0x4F, 0xF4, 0x80, 0x10, 0x4F, 0xF4, 0x00, 0x41, 0x4F, 0xF4, 0x00, 0x12, ++0x58, 0x60, 0x99, 0x60, 0x1A, 0x60, 0x62, 0xB6, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xED, 0x00, 0xE0, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, 0x33, 0x49, 0x34, 0x4B, 0x0A, 0x68, 0x00, 0x28, 0x22, 0xF4, 0x00, 0x62, ++0xF0, 0xB5, 0x32, 0x4D, 0x0A, 0x60, 0x06, 0xBF, 0x1D, 0x46, 0x30, 0x26, 0x20, 0x26, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x2A, 0x4F, 0x2C, 0x4C, 0x3A, 0x68, 0x22, 0xF4, 0x80, 0x52, 0x3A, 0x60, 0x3A, 0x68, ++0x42, 0xF4, 0x80, 0x62, 0x3A, 0x60, 0x3A, 0x68, 0x42, 0xF4, 0x00, 0x62, 0x3A, 0x60, 0xB6, 0x00, 0x19, 0x46, 0x3A, 0x46, ++0x4F, 0xF0, 0xFF, 0x0E, 0xC8, 0x1C, 0xC0, 0xB2, 0xAC, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x43, 0x13, 0x60, ++0x5C, 0xF8, 0x04, 0x3B, 0x23, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, ++0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, 0xFC, 0xD5, 0x01, 0x38, 0xC0, 0xB2, 0x70, 0x45, 0xE8, 0xD1, 0x04, 0x31, 0x04, 0x30, ++0xB1, 0x42, 0x5F, 0xFA, 0x80, 0xFE, 0x05, 0xF1, 0x10, 0x05, 0xDD, 0xD1, 0x3B, 0x68, 0x23, 0xF4, 0x80, 0x63, 0x3B, 0x60, ++0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, ++0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, ++0x80, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0xF0, 0xBD, 0x00, 0xBF, 0x60, 0x40, 0x34, 0x40, ++0x1C, 0x13, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, 0x64, 0x40, 0x34, 0x40, 0x44, 0x4A, 0x45, 0x49, 0x13, 0x68, 0xF0, 0xB4, ++0x44, 0x4D, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x00, 0x28, 0x0C, 0xBF, 0x28, 0x46, 0x08, 0x46, 0x32, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x3B, 0x4A, 0x3E, 0x4D, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x53, 0x13, 0x60, ++0x13, 0x68, 0x43, 0xF4, 0x80, 0x63, 0x13, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x03, 0x21, 0xA0, 0xF1, ++0x0C, 0x04, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x54, 0xF8, 0x21, 0x30, 0x2B, 0x60, 0x13, 0x68, ++0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9E, 0x04, 0xFC, 0xD5, ++0x04, 0x31, 0x43, 0x29, 0xE9, 0xD1, 0x28, 0x4B, 0x2B, 0x4E, 0x2A, 0x4D, 0x04, 0x1F, 0x02, 0x21, 0x1A, 0x68, 0x22, 0xF0, ++0xFF, 0x02, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, ++0x00, 0xBF, 0x1A, 0x68, 0x90, 0x04, 0xFC, 0xD5, 0x37, 0x68, 0x54, 0xF8, 0x21, 0x20, 0x18, 0x68, 0x27, 0xF0, 0x7F, 0x47, ++0x02, 0xF0, 0x7F, 0x42, 0x20, 0xF0, 0xFF, 0x00, 0x3A, 0x43, 0x08, 0x43, 0x18, 0x60, 0x2A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x80, 0x72, 0x1A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x1A, 0x68, 0x92, 0x04, 0xFC, 0xD5, 0x04, 0x31, ++0x42, 0x29, 0xD3, 0xD1, 0x1A, 0x68, 0x22, 0xF4, 0x80, 0x62, 0x1A, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, ++0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x00, 0x62, 0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x60, 0x40, 0x34, 0x40, 0x1C, 0x16, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, ++0x64, 0x40, 0x34, 0x40, 0x68, 0x40, 0x34, 0x40, 0x2C, 0x49, 0x2D, 0x4B, 0x0A, 0x68, 0x30, 0xB4, 0x2C, 0x4C, 0x00, 0x28, ++0x22, 0xF4, 0x80, 0x72, 0x0C, 0xBF, 0x18, 0x46, 0x20, 0x46, 0x0A, 0x60, 0x0C, 0xBF, 0x20, 0x24, 0x10, 0x24, 0x32, 0x23, ++0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x22, 0x49, 0x24, 0x4D, 0x0A, 0x68, 0x22, 0xF4, 0x00, 0x72, ++0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x72, 0x04, 0x38, 0x0A, 0x60, ++0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x50, 0xF8, 0x04, 0x2F, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF0, ++0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, 0xFC, 0xD5, 0x01, 0x33, ++0x9C, 0x42, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, ++0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x80, 0x72, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x6C, 0x40, 0x34, 0x40, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, ++0x70, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0xA6, 0x49, 0xA7, 0x4C, 0xA7, 0x4B, 0xA8, 0x4A, 0xDF, 0xF8, 0xE8, 0xE2, ++0x00, 0x28, 0x0E, 0xBF, 0xA4, 0x46, 0x8C, 0x46, 0x9E, 0x46, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0xA3, 0x4C, 0xA4, 0x49, ++0x23, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x23, 0x60, 0x01, 0x23, 0x13, 0x60, 0x0B, 0x68, 0xA1, 0x4A, 0x23, 0xF4, 0x00, 0x63, ++0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x24, 0x00, 0xBF, 0x01, 0x3C, 0x14, 0xF0, 0xFF, 0x04, ++0xFA, 0xD1, 0xDF, 0xF8, 0x64, 0x82, 0x99, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x98, 0x4F, 0x23, 0xF4, 0x80, 0x53, 0xC8, 0xF8, ++0x00, 0x30, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x80, 0x63, 0xC8, 0xF8, ++0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x00, 0x63, 0xC8, 0xF8, 0x00, 0x30, 0x42, 0x46, 0xFF, 0x26, 0xE1, 0x1C, ++0xC9, 0xB2, 0x75, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x55, 0xF8, 0x04, 0x3B, 0x3B, 0x60, ++0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, ++0xFC, 0xD5, 0x01, 0x39, 0xC9, 0xB2, 0x8E, 0x42, 0xE8, 0xD1, 0x04, 0x34, 0x04, 0x36, 0x80, 0x2C, 0xF6, 0xB2, 0x0E, 0xF1, ++0x10, 0x0E, 0xDE, 0xD1, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x80, 0x63, 0xC8, 0xF8, 0x00, 0x30, 0xC8, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x74, 0x4C, 0x75, 0x49, 0x22, 0x68, 0x22, 0xF4, 0x00, 0x62, 0x22, 0x60, ++0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x72, 0x10, 0x34, 0xAC, 0xF1, 0x04, 0x0C, ++0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x5C, 0xF8, 0x04, 0x2F, 0x22, 0x60, 0x0A, 0x68, ++0x42, 0xF0, 0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, 0xFC, 0xD5, ++0x01, 0x33, 0x10, 0x2B, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x5D, 0x49, 0x5E, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x13, 0x68, ++0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x54, 0x49, ++0x54, 0x4B, 0x0C, 0x68, 0x56, 0x4A, 0x57, 0x4D, 0x44, 0xF4, 0x80, 0x54, 0x0C, 0x60, 0x1C, 0x68, 0x44, 0xF4, 0x00, 0x74, ++0x1C, 0x60, 0x0C, 0x68, 0x44, 0xF4, 0x00, 0x64, 0x0C, 0x60, 0x19, 0x68, 0x51, 0x4C, 0x41, 0xF4, 0x80, 0x71, 0x19, 0x60, ++0x11, 0x68, 0x50, 0x4B, 0x41, 0xF4, 0x80, 0x51, 0x11, 0x60, 0x29, 0x68, 0x21, 0xF4, 0x80, 0x21, 0x29, 0x60, 0x21, 0x68, ++0x21, 0xF0, 0x00, 0x51, 0x21, 0x60, 0xA5, 0xF5, 0xBC, 0x45, 0x1C, 0x68, 0x2C, 0x60, 0x49, 0x49, 0x5D, 0x68, 0x0D, 0x60, ++0x48, 0x4C, 0x9D, 0x68, 0x25, 0x60, 0xDD, 0x68, 0x8D, 0x60, 0x1D, 0x69, 0xA5, 0x60, 0x5C, 0x69, 0x0C, 0x61, 0xD3, 0xE9, ++0x06, 0x64, 0x44, 0x4D, 0x44, 0x4B, 0x2E, 0x60, 0x8C, 0x61, 0x9B, 0x78, 0x18, 0x31, 0xCB, 0xB1, 0xA5, 0xF6, 0x78, 0x65, ++0x41, 0x4C, 0x2B, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x00, 0x73, 0x2B, 0x60, 0x23, 0x68, 0x01, 0xF5, 0xBB, 0x41, ++0x7C, 0x31, 0x43, 0xF0, 0x80, 0x63, 0x23, 0x60, 0x0B, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0x40, 0x63, 0x43, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x36, 0x4B, 0x93, 0xF8, 0xFA, 0x30, 0x38, 0xB9, 0x43, 0xBB, 0x35, 0x4A, ++0x13, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0xCB, 0xB1, 0x32, 0x49, 0x32, 0x4A, 0x0B, 0x68, ++0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xB5, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xB5, 0x03, ++0x13, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x32, 0x23, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x23, ++0x43, 0xF4, 0x32, 0x23, 0x13, 0x60, 0x24, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, ++0x21, 0x49, 0x22, 0x4A, 0x0B, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, ++0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x0B, 0x60, ++0x13, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x13, 0x60, 0xBB, 0xE7, 0x00, 0xBF, 0x9C, 0x18, 0x17, 0x00, ++0x1C, 0x18, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x60, 0x40, 0x34, 0x40, ++0x6C, 0x40, 0x34, 0x40, 0x64, 0x40, 0x34, 0x40, 0x58, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, ++0x1C, 0x20, 0x34, 0x40, 0xDC, 0x18, 0x17, 0x00, 0x1C, 0xC2, 0x33, 0x40, 0x20, 0xC2, 0x33, 0x40, 0x30, 0xC2, 0x33, 0x40, ++0x3C, 0x36, 0x17, 0x00, 0x38, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0xAC, 0xB3, 0x33, 0x40, ++0xD4, 0xB3, 0x33, 0x40, 0x1C, 0x13, 0x17, 0x00, 0x10, 0xB4, 0x1C, 0x4B, 0x1C, 0x4C, 0x0F, 0xCB, 0x85, 0xB0, 0x0D, 0xF1, ++0x10, 0x0C, 0x0C, 0xE9, 0x0F, 0x00, 0x63, 0x68, 0xDB, 0x06, 0x16, 0xD5, 0x61, 0x68, 0xA3, 0x69, 0x5C, 0xFA, 0x83, 0xF3, ++0xC8, 0x04, 0x13, 0xF8, 0x10, 0x2C, 0x22, 0xD4, 0x60, 0x68, 0x14, 0x49, 0x14, 0x4B, 0x10, 0xF4, 0x80, 0x7F, 0x08, 0xBF, ++0x0B, 0x46, 0x11, 0x06, 0x44, 0xBF, 0x5B, 0x00, 0x02, 0xF0, 0x7F, 0x02, 0xB3, 0xFB, 0xF2, 0xF3, 0x00, 0xE0, 0x0F, 0x4B, ++0x0B, 0x4A, 0x0F, 0x4C, 0x52, 0x69, 0x0F, 0x48, 0x0F, 0x49, 0xD2, 0xB2, 0xB3, 0xFB, 0xF2, 0xF3, 0x23, 0x60, 0xD0, 0xF8, ++0x84, 0x20, 0xD2, 0xB2, 0xB3, 0xFB, 0xF2, 0xF3, 0x0B, 0x60, 0x05, 0xB0, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x09, 0x4B, ++0xE1, 0xE7, 0x00, 0xBF, 0x60, 0x79, 0x15, 0x00, 0x00, 0x00, 0x50, 0x40, 0x00, 0x38, 0x9C, 0x1C, 0x00, 0xD0, 0x12, 0x13, ++0x00, 0x75, 0x19, 0x03, 0x18, 0x13, 0x17, 0x00, 0x00, 0x00, 0x10, 0x40, 0x14, 0x13, 0x17, 0x00, 0x00, 0x70, 0x38, 0x39, ++0x70, 0xB4, 0x5D, 0x4C, 0x5D, 0x48, 0x23, 0x68, 0x5D, 0x4D, 0x5E, 0x49, 0x5E, 0x4A, 0x23, 0xF4, 0xC0, 0x63, 0x43, 0xF4, ++0x00, 0x73, 0x23, 0x60, 0x03, 0x68, 0x95, 0xF8, 0xFA, 0x40, 0x23, 0xF4, 0xBC, 0x03, 0x23, 0xF4, 0x70, 0x53, 0x43, 0xF4, ++0x60, 0x23, 0x43, 0xF4, 0x80, 0x63, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x60, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0xFE, 0x33, 0x43, 0xF4, 0x98, 0x33, 0x13, 0x60, 0x00, 0x2C, 0x00, 0xF0, 0x8F, 0x80, 0xA2, 0xF5, 0x11, 0x12, 0xA2, 0xF6, ++0x4C, 0x52, 0x13, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x13, 0x60, 0x4C, 0x4D, 0x4C, 0x48, 0x2B, 0x68, 0x4C, 0x4C, 0x4D, 0x4A, ++0x4D, 0x49, 0x4E, 0x4E, 0x43, 0xF0, 0x80, 0x63, 0x2B, 0x60, 0x03, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x03, 0x60, 0x23, 0x68, ++0x23, 0xF4, 0x7F, 0x73, 0x43, 0xF0, 0x04, 0x03, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x80, 0x53, 0x43, 0xF4, 0x00, 0x63, ++0x03, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xCC, 0x03, 0x43, 0xF0, 0xC4, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x03, 0xF0, 0x7F, 0x43, ++0xA5, 0xF5, 0xF8, 0x55, 0x43, 0xF4, 0x78, 0x13, 0x0C, 0x3D, 0x43, 0xF4, 0x78, 0x73, 0x0B, 0x60, 0x2B, 0x68, 0x1B, 0x0C, ++0xA4, 0xF5, 0x00, 0x54, 0x1B, 0x04, 0x34, 0x3C, 0x43, 0xF0, 0x84, 0x03, 0x2B, 0x60, 0x23, 0x68, 0x37, 0x4D, 0x23, 0xF4, ++0x40, 0x63, 0x43, 0xF4, 0x00, 0x63, 0x23, 0x60, 0xD0, 0xF8, 0x04, 0x31, 0x02, 0xF5, 0xF8, 0x52, 0x23, 0xF4, 0xE0, 0x23, ++0x18, 0x32, 0x43, 0xF4, 0x80, 0x33, 0xC0, 0xF8, 0x04, 0x31, 0x13, 0x68, 0x23, 0xF0, 0x76, 0x53, 0x23, 0xF0, 0x07, 0x03, ++0x01, 0xF5, 0xF7, 0x51, 0x43, 0xF0, 0x04, 0x53, 0x04, 0x31, 0x43, 0xF0, 0x07, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x04, 0xF5, ++0x00, 0x54, 0x02, 0xF1, 0xEF, 0x52, 0x00, 0xF5, 0x01, 0x50, 0x1C, 0x34, 0x02, 0xF5, 0x3D, 0x22, 0x02, 0xF6, 0x44, 0x02, ++0x1D, 0x40, 0x08, 0x30, 0x22, 0x4B, 0x0D, 0x60, 0x32, 0x60, 0x23, 0x60, 0x03, 0x68, 0x21, 0x4A, 0x21, 0x4C, 0x23, 0xF4, ++0x7F, 0x23, 0x23, 0xF4, 0x00, 0x63, 0x43, 0xF4, 0x32, 0x33, 0x03, 0x60, 0xCB, 0x68, 0x43, 0xF4, 0x00, 0x63, 0xCB, 0x60, ++0x13, 0x68, 0x23, 0xF0, 0x09, 0x03, 0x43, 0xF4, 0x80, 0x53, 0x13, 0x60, 0x23, 0x68, 0x1B, 0x07, 0x08, 0xD5, 0xA2, 0xF5, ++0x0F, 0x12, 0xA2, 0xF5, 0x03, 0x52, 0x24, 0x3A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x53, 0x13, 0x60, 0x70, 0xBC, 0x70, 0x47, ++0x12, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x00, 0x73, 0x13, 0x60, 0x70, 0xE7, 0x20, 0x40, 0x34, 0x40, ++0x24, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x28, 0x40, 0x34, 0x40, 0x04, 0x01, 0x58, 0x40, 0x38, 0x40, 0x34, 0x40, ++0x30, 0x20, 0x34, 0x40, 0x48, 0x40, 0x34, 0x40, 0x28, 0x21, 0x34, 0x40, 0x24, 0x21, 0x34, 0x40, 0x2C, 0x40, 0x34, 0x40, ++0x03, 0x00, 0x00, 0xFF, 0x08, 0x51, 0x2E, 0x1A, 0x08, 0x01, 0x58, 0x40, 0x94, 0x40, 0x04, 0x40, 0xB8, 0xB3, 0x33, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xDE, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xE6, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xE8, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x24, 0x1C, 0x60, 0x0D, 0x4D, ++0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xEA, 0x73, 0x1B, 0x68, ++0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x2D, 0xE9, 0xF0, 0x47, 0x4C, 0x4B, 0x4D, 0x4D, 0x08, 0x22, 0xC3, 0xF8, 0x00, 0x21, 0xAB, 0x78, 0x33, 0xB9, 0x4B, 0x4A, ++0x93, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x43, 0xF4, 0x00, 0x33, 0x93, 0x60, 0x47, 0x4A, 0x13, 0x6B, 0x03, 0xF0, 0x22, 0x03, ++0x02, 0x2B, 0xFA, 0xD1, 0x93, 0x68, 0x45, 0x4C, 0x41, 0x49, 0x45, 0x48, 0x23, 0xF4, 0x00, 0x63, 0x43, 0xF0, 0x01, 0x13, ++0x43, 0xF4, 0x04, 0x43, 0x93, 0x60, 0x06, 0x23, 0x23, 0x60, 0x53, 0x6D, 0x40, 0x4C, 0x23, 0xF4, 0x40, 0x13, 0x53, 0x65, ++0x4F, 0xF4, 0x00, 0x63, 0xC1, 0xF8, 0x34, 0x31, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x03, ++0x01, 0x40, 0x0B, 0x43, 0x13, 0x60, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x08, 0xD1, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, ++0x09, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x08, 0x40, 0x18, 0x43, 0x10, 0x60, 0x2E, 0x49, 0x2C, 0x4E, 0x0B, 0x68, 0x0A, 0x68, ++0x30, 0x48, 0xC3, 0xF3, 0x09, 0x03, 0x22, 0xF4, 0x7F, 0x72, 0x22, 0xF0, 0x03, 0x02, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x43, ++0x0B, 0x60, 0x73, 0x6F, 0x2B, 0x4A, 0x43, 0xF0, 0x02, 0x03, 0x73, 0x67, 0x03, 0x68, 0x2A, 0x4E, 0x23, 0xF4, 0x00, 0x63, ++0x03, 0x60, 0x13, 0x68, 0x96, 0xF8, 0xA9, 0x00, 0x43, 0xF0, 0x80, 0x73, 0x13, 0x60, 0x68, 0xB1, 0x0B, 0x6B, 0x5F, 0x06, ++0x05, 0xD4, 0x0B, 0x6B, 0x58, 0x07, 0x02, 0xD5, 0x22, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x1A, 0x4B, 0x1A, 0x6B, 0x52, 0x06, ++0x40, 0xF1, 0x10, 0x82, 0x1F, 0x4B, 0xD6, 0xF8, 0xA0, 0x20, 0x1A, 0x60, 0xAB, 0x78, 0x00, 0x2B, 0x3E, 0xD0, 0x1D, 0x4B, ++0x1A, 0x68, 0x13, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x6C, 0x82, 0x11, 0x4B, 0x0E, 0x48, 0x02, 0x21, 0x11, 0x70, 0x1A, 0x6D, ++0xA9, 0x78, 0x42, 0xF4, 0x80, 0x22, 0x1A, 0x65, 0x02, 0x69, 0x22, 0xF0, 0x80, 0x02, 0x02, 0x61, 0x5A, 0x6A, 0x22, 0xF0, ++0xFF, 0x02, 0x42, 0xF0, 0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, 0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, ++0x00, 0x29, 0x33, 0xD0, 0x03, 0xF0, 0xB0, 0xFC, 0x0C, 0x4F, 0x33, 0xE0, 0x00, 0x00, 0x50, 0x40, 0x3C, 0x36, 0x17, 0x00, ++0x00, 0x60, 0x50, 0x40, 0x10, 0x00, 0x58, 0x40, 0x00, 0xFC, 0xFF, 0xFF, 0x78, 0x36, 0x17, 0x00, 0x00, 0x01, 0x58, 0x40, ++0x20, 0x01, 0x58, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, 0x74, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xC0, 0x4B, 0xC1, 0x49, 0x1A, 0x6D, 0x42, 0xF4, 0x80, 0x22, 0x1A, 0x65, 0x0A, 0x69, 0x22, 0xF0, ++0x80, 0x02, 0x0A, 0x61, 0x5A, 0x6A, 0x22, 0xF0, 0xFF, 0x02, 0x42, 0xF0, 0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, ++0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, 0xB7, 0x4F, 0xD7, 0xF8, 0xCC, 0x30, 0x98, 0x47, 0x03, 0xF0, 0xF4, 0xF9, ++0xD7, 0xF8, 0x9C, 0x34, 0x98, 0x47, 0xB2, 0x4B, 0xB3, 0x49, 0x1B, 0x68, 0xB3, 0x4A, 0xA8, 0x78, 0x1B, 0x0C, 0x0B, 0x70, ++0x04, 0x23, 0x1B, 0x68, 0x1B, 0x09, 0x13, 0x70, 0x10, 0xB9, 0xD7, 0xF8, 0x80, 0x34, 0x98, 0x47, 0xAE, 0x48, 0xAF, 0x4D, ++0xFF, 0xF7, 0x78, 0xFE, 0xAE, 0x48, 0xFF, 0xF7, 0x9D, 0xFE, 0x03, 0x46, 0x1A, 0x0C, 0xAD, 0x49, 0x2A, 0x70, 0x1B, 0x0F, ++0x02, 0x22, 0x0B, 0x70, 0xAB, 0x48, 0x11, 0x46, 0xFF, 0xF7, 0xE2, 0xFE, 0x4F, 0xF4, 0x80, 0x52, 0x11, 0x46, 0xA9, 0x48, ++0xFF, 0xF7, 0xDC, 0xFE, 0xA8, 0x4A, 0xA9, 0x49, 0xA9, 0x48, 0xFF, 0xF7, 0xD7, 0xFE, 0x2B, 0x78, 0x01, 0x2B, 0x00, 0xF0, ++0x8E, 0x81, 0xA7, 0x48, 0x4F, 0xF4, 0x7F, 0x52, 0x4F, 0xF4, 0x9E, 0x51, 0xFF, 0xF7, 0xCC, 0xFE, 0x04, 0x22, 0xA4, 0x48, ++0x11, 0x46, 0xFF, 0xF7, 0xC7, 0xFE, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x04, 0xD0, 0xA1, 0x48, 0x07, 0x22, 0x00, 0x21, ++0xFF, 0xF7, 0xBE, 0xFE, 0x01, 0x21, 0x02, 0x20, 0x03, 0xF0, 0x5C, 0xFE, 0x04, 0x22, 0x9D, 0x48, 0x00, 0x21, 0xFF, 0xF7, ++0xB5, 0xFE, 0x01, 0x21, 0x03, 0x20, 0x03, 0xF0, 0x53, 0xFE, 0x08, 0x22, 0x98, 0x48, 0x00, 0x21, 0xFF, 0xF7, 0xAC, 0xFE, ++0x00, 0x21, 0x05, 0x20, 0x03, 0xF0, 0x4A, 0xFE, 0x95, 0x48, 0x20, 0x22, 0x00, 0x21, 0xFF, 0xF7, 0xA3, 0xFE, 0x20, 0x22, ++0x11, 0x46, 0x93, 0x48, 0xFF, 0xF7, 0x9E, 0xFE, 0x20, 0x22, 0x11, 0x46, 0x91, 0x48, 0xFF, 0xF7, 0x99, 0xFE, 0x02, 0x22, ++0x90, 0x48, 0x11, 0x46, 0xFF, 0xF7, 0x94, 0xFE, 0x4F, 0xF4, 0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x00, 0xF0, ++0x60, 0x00, 0x20, 0x28, 0x00, 0xF0, 0x74, 0x81, 0x4F, 0xF4, 0xFC, 0x02, 0x11, 0x46, 0x89, 0x48, 0xFF, 0xF7, 0x84, 0xFE, ++0x88, 0x4A, 0x89, 0x48, 0x4F, 0xF0, 0x46, 0x41, 0xFF, 0xF7, 0x7E, 0xFE, 0x87, 0x48, 0x3F, 0x22, 0x1F, 0x21, 0xFF, 0xF7, ++0x79, 0xFE, 0x4F, 0xF4, 0x80, 0x22, 0x85, 0x48, 0x00, 0x21, 0xFF, 0xF7, 0x73, 0xFE, 0x84, 0x48, 0x4F, 0xF4, 0x8E, 0x71, ++0xFF, 0xF7, 0x46, 0xFE, 0x82, 0x48, 0x4F, 0xF4, 0xF8, 0x22, 0x4F, 0xF4, 0xD8, 0x21, 0xFF, 0xF7, 0x67, 0xFE, 0x40, 0x22, ++0x11, 0x46, 0x7F, 0x48, 0xFF, 0xF7, 0x62, 0xFE, 0x4F, 0xF4, 0xC0, 0x32, 0x11, 0x46, 0x7D, 0x48, 0xFF, 0xF7, 0x5C, 0xFE, ++0x7C, 0x48, 0x4F, 0xF4, 0xE0, 0x62, 0x4F, 0xF4, 0x00, 0x71, 0xFF, 0xF7, 0x55, 0xFE, 0x96, 0xF8, 0xC7, 0x70, 0xB7, 0xB3, ++0x78, 0x4A, 0x96, 0xF8, 0xC8, 0x10, 0x78, 0x4B, 0x96, 0xF8, 0xC9, 0x00, 0x11, 0x70, 0x96, 0xF8, 0xCA, 0x10, 0x50, 0x70, ++0x91, 0x70, 0x96, 0xF8, 0xCB, 0x50, 0x96, 0xF8, 0xCC, 0x00, 0x96, 0xF8, 0xCD, 0x10, 0x96, 0xF8, 0xCE, 0x20, 0x1D, 0x70, ++0x58, 0x70, 0x99, 0x70, 0xDA, 0x70, 0x4F, 0xF4, 0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x10, 0xF4, 0x60, 0x2F, ++0xC0, 0xF3, 0x42, 0x41, 0x0E, 0xD0, 0x6A, 0x4A, 0x8D, 0x01, 0x02, 0xF1, 0x40, 0x00, 0x52, 0xF8, 0x04, 0x3F, 0x23, 0xF4, ++0xE0, 0x73, 0x2B, 0x43, 0x90, 0x42, 0x13, 0x60, 0xF7, 0xD1, 0x65, 0x48, 0x03, 0xF0, 0x68, 0xFD, 0x23, 0x68, 0x1C, 0x78, ++0x01, 0x2C, 0x00, 0xF0, 0xEF, 0x80, 0xBD, 0xE8, 0xF0, 0x87, 0x4F, 0xF4, 0xD2, 0x76, 0x0A, 0x20, 0x33, 0x68, 0xDF, 0xF8, ++0x6C, 0xA1, 0x98, 0x47, 0x33, 0x68, 0x05, 0x46, 0x0B, 0x20, 0x98, 0x47, 0x33, 0x68, 0x80, 0x46, 0x0F, 0x20, 0x98, 0x47, ++0x5F, 0xEA, 0x95, 0x7C, 0x3A, 0x46, 0x0C, 0xBF, 0x4F, 0xF0, 0x08, 0x09, 0x4F, 0xF0, 0x10, 0x09, 0x4F, 0xEA, 0x15, 0x6E, ++0xD3, 0x00, 0x25, 0xFA, 0x03, 0xF3, 0xDF, 0xB2, 0xC3, 0xF3, 0x03, 0x13, 0xBC, 0xF1, 0x00, 0x0F, 0x38, 0xD1, 0x00, 0x2B, ++0x54, 0xD1, 0x00, 0x2F, 0x40, 0xF0, 0x1F, 0x81, 0x01, 0x32, 0x03, 0x2A, 0xEE, 0xD1, 0xDF, 0xF8, 0x24, 0xE1, 0x07, 0x0E, ++0x00, 0x21, 0xCB, 0x00, 0x28, 0xFA, 0x03, 0xF3, 0xDE, 0xB2, 0xC3, 0xF3, 0x03, 0x13, 0xBC, 0xF1, 0x00, 0x0F, 0x0B, 0xD1, ++0xEB, 0xB1, 0x08, 0x22, 0x93, 0x42, 0x28, 0xBF, 0xD3, 0x1A, 0x5B, 0xB2, 0x0E, 0xF8, 0x01, 0x30, 0x01, 0x31, 0x04, 0x29, ++0xEB, 0xD1, 0x9C, 0xE7, 0x4D, 0x00, 0x6A, 0x1C, 0x47, 0xFA, 0x02, 0xF2, 0x12, 0x01, 0x02, 0xF0, 0x10, 0x02, 0x13, 0x43, ++0x13, 0xF0, 0xFF, 0x03, 0x1F, 0xD1, 0x47, 0xFA, 0x05, 0xF3, 0x1B, 0x01, 0x03, 0xF0, 0x10, 0x03, 0x06, 0xF0, 0x0F, 0x06, ++0x1E, 0x43, 0x00, 0x2E, 0xE6, 0xD0, 0x33, 0x46, 0x4A, 0x46, 0xDD, 0xE7, 0x56, 0x00, 0x71, 0x1C, 0x4E, 0xFA, 0x01, 0xF1, ++0x09, 0x01, 0x01, 0xF0, 0x10, 0x01, 0x0B, 0x43, 0x13, 0xF0, 0xFF, 0x03, 0x09, 0xD0, 0x10, 0x21, 0x8B, 0x42, 0x28, 0xBF, ++0xCB, 0x1A, 0x5B, 0xB2, 0x0A, 0xF8, 0x02, 0x30, 0xB8, 0xE7, 0x10, 0x22, 0xC8, 0xE7, 0x4E, 0xFA, 0x06, 0xF3, 0x1B, 0x01, ++0x03, 0xF0, 0x10, 0x03, 0x07, 0xF0, 0x0F, 0x07, 0x1F, 0x43, 0xAA, 0xE7, 0x08, 0x21, 0xEB, 0xE7, 0x00, 0x60, 0x50, 0x40, ++0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x11, 0x13, 0x17, 0x00, 0x12, 0x13, 0x17, 0x00, 0x04, 0x02, 0x22, 0x03, ++0x10, 0x13, 0x17, 0x00, 0x00, 0x00, 0x01, 0x50, 0x70, 0x25, 0x17, 0x00, 0x50, 0x91, 0x01, 0x50, 0x20, 0x91, 0x01, 0x50, ++0xC0, 0xFD, 0x01, 0x00, 0xC0, 0xF1, 0x01, 0x00, 0x24, 0x91, 0x01, 0x50, 0x08, 0x88, 0x01, 0x50, 0x18, 0x88, 0x01, 0x50, ++0x2C, 0x91, 0x01, 0x50, 0x00, 0x10, 0x01, 0x50, 0x0C, 0x10, 0x01, 0x50, 0x10, 0x10, 0x01, 0x50, 0x18, 0x10, 0x01, 0x50, ++0x00, 0x30, 0x01, 0x50, 0x00, 0x88, 0x01, 0x50, 0x00, 0x00, 0xC0, 0xFF, 0x04, 0x88, 0x01, 0x50, 0x28, 0x91, 0x01, 0x50, ++0x5C, 0x00, 0x01, 0x50, 0x58, 0x00, 0x01, 0x50, 0x74, 0x91, 0x01, 0x50, 0x18, 0x91, 0x01, 0x50, 0x00, 0x91, 0x01, 0x50, ++0x30, 0x88, 0x01, 0x50, 0x68, 0x25, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x18, 0x18, 0x17, 0x00, 0x74, 0x79, 0x15, 0x00, ++0x1B, 0x6B, 0x59, 0x07, 0x7F, 0xF5, 0xEC, 0xAD, 0xD6, 0xF8, 0xA0, 0x30, 0x3F, 0x48, 0x40, 0x49, 0x40, 0x4A, 0x43, 0xF0, ++0x00, 0x73, 0x01, 0x27, 0x07, 0x70, 0x0B, 0x60, 0x53, 0x6F, 0x43, 0xF0, 0x10, 0x03, 0x53, 0x67, 0xE0, 0xE5, 0x3C, 0x4A, ++0x3C, 0x49, 0x3D, 0x48, 0xFF, 0xF7, 0x40, 0xFD, 0x3C, 0x48, 0x4F, 0xF4, 0x08, 0x42, 0x4F, 0xF4, 0x00, 0x41, 0xFF, 0xF7, ++0x39, 0xFD, 0x3A, 0x4A, 0x3A, 0x49, 0x3B, 0x48, 0xFF, 0xF7, 0x34, 0xFD, 0x3A, 0x48, 0x8F, 0x22, 0x06, 0x21, 0xFF, 0xF7, ++0x2F, 0xFD, 0x66, 0xE6, 0x38, 0x49, 0x39, 0x48, 0x4F, 0xF0, 0xFF, 0x32, 0xFF, 0xF7, 0x28, 0xFD, 0x4F, 0xF0, 0xFF, 0x32, ++0x36, 0x48, 0x4F, 0xF0, 0x02, 0x11, 0xFF, 0xF7, 0x21, 0xFD, 0x35, 0x49, 0x35, 0x48, 0xFF, 0xF7, 0xF5, 0xFC, 0x22, 0x46, ++0x21, 0x46, 0x34, 0x48, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x16, 0xBD, 0x32, 0x48, 0x0F, 0x22, 0x01, 0x21, 0xFF, 0xF7, ++0x11, 0xFD, 0x02, 0x22, 0x11, 0x46, 0x30, 0x48, 0xFF, 0xF7, 0x0C, 0xFD, 0x02, 0x22, 0x11, 0x46, 0x2E, 0x48, 0xFF, 0xF7, ++0x07, 0xFD, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x2A, 0x48, 0xFF, 0xF7, 0x01, 0xFD, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, ++0x28, 0x48, 0xFF, 0xF7, 0xFB, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x27, 0x48, 0xFF, 0xF7, 0xF6, 0xFC, 0x25, 0x48, 0x4F, 0xF4, ++0x00, 0x52, 0x00, 0x21, 0xFF, 0xF7, 0xF0, 0xFC, 0x64, 0xE6, 0x23, 0x4B, 0x0F, 0x49, 0x1A, 0x6D, 0x22, 0x4F, 0x42, 0xF4, ++0x80, 0x22, 0x1A, 0x65, 0x0A, 0x69, 0x22, 0xF0, 0x80, 0x02, 0x0A, 0x61, 0x5A, 0x6A, 0x22, 0xF0, 0xFF, 0x02, 0x42, 0xF0, ++0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, 0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, 0x03, 0xF0, 0x48, 0xFA, ++0xCC, 0xE5, 0x3B, 0x46, 0x49, 0x46, 0x1D, 0xE7, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, 0x00, 0x00, 0x50, 0x40, ++0xC0, 0x3F, 0x00, 0x40, 0x40, 0x12, 0x00, 0x40, 0x08, 0x88, 0x01, 0x50, 0x04, 0x91, 0x01, 0x50, 0xE0, 0x01, 0x00, 0x22, ++0xC0, 0x00, 0x00, 0x02, 0x08, 0x91, 0x01, 0x50, 0x00, 0x91, 0x01, 0x50, 0x00, 0x01, 0x00, 0x03, 0x0C, 0x80, 0x01, 0x50, ++0x18, 0x80, 0x01, 0x50, 0x0A, 0x33, 0x41, 0x01, 0x38, 0x91, 0x01, 0x50, 0x04, 0x00, 0x01, 0x50, 0x04, 0x20, 0x01, 0x50, ++0x04, 0x10, 0x01, 0x50, 0x08, 0x10, 0x01, 0x50, 0x00, 0x10, 0x01, 0x50, 0x00, 0x60, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x10, 0x4B, 0x11, 0x4A, 0x19, 0x68, 0x21, 0xF4, 0x78, 0x11, 0x41, 0xF4, 0x50, 0x11, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, ++0x78, 0x11, 0x41, 0xF4, 0xA0, 0x11, 0x19, 0x60, 0x11, 0x69, 0x18, 0x68, 0x20, 0xF4, 0x78, 0x10, 0x40, 0xF4, 0x50, 0x10, ++0x32, 0x31, 0x18, 0x60, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x78, 0x13, ++0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x70, 0x47, 0x58, 0x40, 0x34, 0x40, 0x00, 0x10, 0x50, 0x40, 0x1E, 0x49, 0x1F, 0x4A, ++0x0B, 0x68, 0x43, 0xF4, 0x00, 0x13, 0x10, 0xB4, 0x0B, 0x60, 0x13, 0x68, 0x59, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x59, 0x07, 0xF6, 0xD5, 0x15, 0x49, 0x15, 0x4A, 0x0B, 0x68, ++0x43, 0xF4, 0xC0, 0x23, 0x0B, 0x60, 0x13, 0x68, 0x9B, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, ++0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x9B, 0x07, 0xF6, 0xD5, 0x0E, 0x4C, 0x0E, 0x48, 0x23, 0x68, 0x0E, 0x4A, 0x0F, 0x49, ++0x43, 0xF4, 0x00, 0x33, 0x23, 0x60, 0x03, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x43, 0xF0, 0x80, 0x73, 0x03, 0x60, 0x13, 0x68, ++0x43, 0xF4, 0xA4, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0xA1, 0xBD, 0x00, 0xBF, ++0x58, 0x40, 0x34, 0x40, 0x80, 0x40, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x10, 0x00, 0x34, 0x40, 0x30, 0x20, 0x34, 0x40, ++0x9C, 0x79, 0x15, 0x00, 0x10, 0xB5, 0x10, 0x4C, 0x10, 0x48, 0x23, 0x68, 0x10, 0x49, 0x11, 0x4A, 0x23, 0xF4, 0x05, 0x43, ++0x23, 0xF0, 0xEC, 0x03, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x00, 0x33, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x73, ++0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xC0, 0x23, 0x0A, 0x20, 0x13, 0x60, 0xFD, 0xF7, 0xD6, 0xFC, 0xBD, 0xE8, 0x10, 0x40, ++0x06, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0x73, 0xBD, 0x00, 0xBF, 0x30, 0x20, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, ++0x10, 0x00, 0x34, 0x40, 0x58, 0x40, 0x34, 0x40, 0xB8, 0x79, 0x15, 0x00, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, ++0x00, 0x2B, 0xFA, 0xD1, 0x19, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, ++0xFA, 0xD1, 0x16, 0x4A, 0x13, 0x68, 0xDB, 0x07, 0x11, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, ++0xFA, 0xD1, 0x13, 0x68, 0xDB, 0x07, 0xF6, 0xD5, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, ++0x13, 0x68, 0xDB, 0x07, 0xED, 0xD5, 0x0B, 0x4B, 0x1A, 0x68, 0x53, 0x0C, 0x00, 0x2A, 0xBC, 0xBF, 0x6F, 0xEA, 0x43, 0x43, ++0x6F, 0xEA, 0x53, 0x43, 0x03, 0x60, 0xC2, 0xF3, 0x4E, 0x03, 0x12, 0x04, 0x44, 0xBF, 0x6F, 0xEA, 0x43, 0x43, 0x6F, 0xEA, ++0x53, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x84, 0x21, 0x34, 0x40, 0x00, 0x22, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x2A, 0x4F, 0x2B, 0x4D, 0x3B, 0x68, 0x2B, 0x4A, 0x23, 0xF4, 0x7F, 0x53, 0x3B, 0x60, 0x2B, 0x68, 0x43, 0xF4, 0x80, 0x63, ++0x2B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x01, 0x20, 0xFD, 0xF7, 0x72, 0xFC, 0x00, 0x24, 0x26, 0x46, ++0x4F, 0xF0, 0x07, 0x08, 0x02, 0x20, 0xFD, 0xF7, 0x6B, 0xFC, 0x2B, 0x68, 0xDA, 0x05, 0x54, 0xBF, 0x01, 0x36, 0x06, 0xF1, ++0xFF, 0x36, 0x76, 0xB2, 0x1B, 0x06, 0x3B, 0x68, 0x54, 0xBF, 0x01, 0x34, 0x04, 0xF1, 0xFF, 0x34, 0x00, 0x2E, 0x23, 0xF4, ++0x7F, 0x53, 0xDC, 0xBF, 0x70, 0x42, 0x43, 0xEA, 0x80, 0x23, 0x64, 0xB2, 0xD4, 0xBF, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xEA, ++0x86, 0x23, 0x00, 0x2C, 0xDC, 0xBF, 0x60, 0x42, 0x43, 0xEA, 0x80, 0x13, 0x08, 0xF1, 0xFF, 0x32, 0xCC, 0xBF, 0x43, 0xEA, ++0x84, 0x13, 0x43, 0xF4, 0x00, 0x73, 0x12, 0xF0, 0xFF, 0x08, 0x3B, 0x60, 0xD2, 0xD1, 0x0A, 0x48, 0x0A, 0x49, 0x02, 0x68, ++0x22, 0xF4, 0x80, 0x62, 0x02, 0x60, 0x0A, 0x68, 0xC3, 0xF3, 0x83, 0x10, 0x22, 0xF0, 0x40, 0x02, 0xC3, 0xF3, 0x83, 0x23, ++0x0A, 0x60, 0x43, 0xEA, 0x00, 0x10, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x50, 0x40, 0x34, 0x40, 0x14, 0x40, 0x34, 0x40, ++0x5C, 0x40, 0x34, 0x40, 0x01, 0x28, 0x15, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x4B, 0x78, 0x10, 0x2B, 0x19, 0xD8, 0x30, 0x23, ++0x8B, 0x70, 0x70, 0x47, 0xD2, 0xE9, 0x00, 0x32, 0x00, 0x2B, 0x24, 0xDD, 0x00, 0x2A, 0x37, 0xDB, 0xB3, 0xEB, 0x42, 0x0F, ++0x0B, 0x78, 0xCC, 0xBF, 0x10, 0x3B, 0x18, 0x3B, 0x4B, 0x70, 0x70, 0x47, 0x13, 0x68, 0xB3, 0xF5, 0x00, 0x5F, 0x10, 0xDA, ++0x00, 0x2B, 0x1A, 0xDD, 0x40, 0x23, 0x0B, 0x70, 0x70, 0x47, 0x30, 0x2B, 0x0C, 0xD9, 0x60, 0x2B, 0x1A, 0xD8, 0x92, 0x68, ++0x00, 0x2A, 0x28, 0xDB, 0x60, 0x2B, 0xDC, 0xD1, 0x20, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x20, 0x23, 0x0B, 0x70, 0x70, 0x47, ++0x18, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x00, 0x2A, 0x1E, 0xDD, 0x0B, 0x78, 0x20, 0x3B, 0x4B, 0x70, 0x70, 0x47, 0x13, 0xF5, ++0x00, 0x5F, 0xD4, 0xBF, 0xE0, 0x23, 0xC0, 0x23, 0x0B, 0x70, 0x70, 0x47, 0xC0, 0x2B, 0x09, 0xD8, 0x92, 0x68, 0x00, 0x2A, ++0x19, 0xDD, 0x60, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x0B, 0x78, 0x20, 0x33, 0x4B, 0x70, 0x70, 0x47, 0xD8, 0x2B, 0x0D, 0xD8, ++0xE8, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xA0, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xB3, 0xEB, 0x42, 0x0F, 0x0B, 0x78, 0xB4, 0xBF, ++0x10, 0x33, 0x18, 0x33, 0x4B, 0x70, 0x70, 0x47, 0xD0, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xA0, 0x2B, 0xFA, 0xD1, 0xE0, 0x23, ++0x8B, 0x70, 0x70, 0x47, 0x01, 0x28, 0x1D, 0xD0, 0x02, 0x28, 0x08, 0xD0, 0x09, 0x78, 0x01, 0x39, 0x05, 0x29, 0x69, 0xD8, ++0xDF, 0xE8, 0x01, 0xF0, 0x3C, 0x42, 0x39, 0x33, 0x2D, 0x2A, 0x10, 0xB4, 0x1C, 0x68, 0xB4, 0xF5, 0x00, 0x5F, 0x19, 0xDA, ++0x00, 0x2C, 0x4A, 0xDD, 0x5B, 0x68, 0x00, 0x2B, 0x13, 0x78, 0xAA, 0xBF, 0x03, 0x20, 0x10, 0x33, 0x10, 0x3B, 0x53, 0x70, ++0x08, 0x70, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x1B, 0x68, 0xB3, 0xF5, 0x00, 0x5F, 0x04, 0xDA, 0x00, 0x2B, 0x2B, 0xDD, ++0x50, 0x23, 0x13, 0x70, 0x70, 0x47, 0x30, 0x23, 0x13, 0x70, 0x70, 0x47, 0x13, 0x78, 0x01, 0x20, 0x10, 0x33, 0x53, 0x70, ++0x08, 0x70, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xC8, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0x21, 0xDD, ++0x70, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0x18, 0xDD, 0x90, 0x23, 0x93, 0x70, 0x70, 0x47, 0x38, 0x23, ++0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0xF0, 0xDD, 0x20, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, ++0xF0, 0xDD, 0x40, 0x23, 0x93, 0x70, 0x70, 0x47, 0x13, 0xF5, 0x00, 0x5F, 0xD4, 0xBF, 0xD0, 0x23, 0xB0, 0x23, 0x13, 0x70, ++0x70, 0x47, 0xE0, 0x23, 0x93, 0x70, 0x70, 0x47, 0xC0, 0x23, 0x93, 0x70, 0x70, 0x47, 0x14, 0xF5, 0x00, 0x5F, 0x05, 0xDC, ++0x13, 0x78, 0x04, 0x20, 0x10, 0x3B, 0x53, 0x70, 0x08, 0x70, 0xB4, 0xE7, 0x5B, 0x68, 0x00, 0x2B, 0x13, 0x78, 0xCC, 0xBF, ++0x05, 0x20, 0x06, 0x20, 0x10, 0x3B, 0x53, 0x70, 0x08, 0x70, 0xAA, 0xE7, 0x88, 0x23, 0x93, 0x70, 0x70, 0x47, 0x00, 0xBF, ++0x30, 0xB4, 0x0F, 0x29, 0x15, 0x46, 0x1C, 0x46, 0x02, 0x9A, 0x03, 0xD0, 0x30, 0xBC, 0x19, 0x46, 0xFF, 0xF7, 0x1C, 0xBF, ++0x13, 0x46, 0x29, 0x46, 0x22, 0x46, 0x30, 0xBC, 0xFF, 0xF7, 0x7A, 0xBF, 0x70, 0xB4, 0x50, 0xEA, 0x01, 0x04, 0x02, 0xD1, ++0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x08, 0x18, 0x18, 0xBF, 0x00, 0x21, 0x03, 0xD1, 0x20, 0xE0, 0xE9, 0xB2, 0x81, 0x42, ++0x1D, 0xDA, 0x53, 0xF8, 0x21, 0x40, 0x94, 0x42, 0x01, 0xF1, 0x01, 0x05, 0x03, 0xEB, 0x81, 0x06, 0xF4, 0xDC, 0xC0, 0xB2, ++0x88, 0x42, 0x0F, 0xD9, 0x44, 0x1E, 0x61, 0x1A, 0x1C, 0x1F, 0xC9, 0xB2, 0x04, 0xEB, 0x80, 0x04, 0xA4, 0xEB, 0x81, 0x04, ++0x03, 0xEB, 0x80, 0x03, 0x53, 0xF8, 0x04, 0x1C, 0x43, 0xF8, 0x04, 0x19, 0xA3, 0x42, 0xF9, 0xD1, 0x32, 0x60, 0x70, 0xBC, ++0x70, 0x47, 0x70, 0xBC, 0x43, 0xF8, 0x20, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0xF1, 0xFF, 0x3C, ++0x85, 0xB0, 0xCC, 0xF3, 0x47, 0x0C, 0x4F, 0xF0, 0x80, 0x34, 0x48, 0xF2, 0x80, 0x03, 0x01, 0x28, 0xCD, 0xE9, 0x01, 0xC4, ++0xAD, 0xF8, 0x0C, 0x30, 0x40, 0xF2, 0x83, 0x80, 0x80, 0x24, 0xA2, 0x46, 0x16, 0x46, 0x00, 0x25, 0x01, 0x23, 0x43, 0xF2, ++0xB0, 0x69, 0x8E, 0x46, 0x00, 0x92, 0x18, 0xE0, 0x80, 0x2C, 0x04, 0xBF, 0x04, 0xAA, 0x02, 0xEB, 0x45, 0x01, 0x4F, 0xEA, ++0x45, 0x07, 0x04, 0xAA, 0x17, 0x44, 0x04, 0xBF, 0x03, 0xF1, 0xFF, 0x34, 0x01, 0xF8, 0x08, 0x4C, 0x07, 0xF8, 0x07, 0x3C, ++0x01, 0x33, 0xDB, 0xB2, 0x98, 0x42, 0x22, 0xD0, 0x04, 0xAA, 0x02, 0xEB, 0x45, 0x01, 0x11, 0xF8, 0x08, 0x4C, 0x37, 0x68, ++0x56, 0xF8, 0x04, 0x1F, 0x7F, 0x1A, 0x77, 0x45, 0xE0, 0xDD, 0x80, 0x2C, 0xEE, 0xD0, 0x00, 0x9A, 0x52, 0xF8, 0x24, 0x10, ++0x49, 0x45, 0x4F, 0xEA, 0x45, 0x07, 0x04, 0xAA, 0x55, 0xDD, 0x02, 0xEB, 0x45, 0x01, 0x11, 0xF8, 0x07, 0x8C, 0x61, 0x46, ++0x0C, 0x44, 0xA0, 0x45, 0x61, 0xDB, 0x01, 0x33, 0xDB, 0xB2, 0x01, 0x35, 0x98, 0x42, 0xED, 0xB2, 0xDC, 0xD1, 0x02, 0x2D, ++0x00, 0x9A, 0x68, 0xD9, 0x9D, 0xF8, 0x08, 0x10, 0x80, 0x29, 0x3A, 0xD0, 0x9D, 0xF8, 0x09, 0x30, 0x52, 0xF8, 0x21, 0x40, ++0x52, 0xF8, 0x23, 0x50, 0x58, 0x1C, 0x40, 0x1A, 0x64, 0x1B, 0xC0, 0xB2, 0x02, 0xAD, 0x94, 0xFB, 0xF0, 0xF4, 0x01, 0x27, ++0xA4, 0xB2, 0x00, 0x26, 0x95, 0xF8, 0x02, 0xE0, 0xBE, 0xF1, 0x80, 0x0F, 0x5F, 0xFA, 0x87, 0xFC, 0x16, 0xD0, 0x95, 0xF8, ++0x03, 0x80, 0x52, 0xF8, 0x2E, 0x30, 0x08, 0xF1, 0x01, 0x01, 0xA1, 0xEB, 0x0E, 0x01, 0xC9, 0xB2, 0x52, 0xF8, 0x28, 0xE0, ++0x81, 0x42, 0xA3, 0xEB, 0x0E, 0x03, 0x93, 0xFB, 0xF1, 0xF3, 0x9B, 0xB2, 0x32, 0xD8, 0x61, 0xD0, 0x02, 0x2F, 0x05, 0xF1, ++0x02, 0x05, 0x34, 0xD1, 0x04, 0xAB, 0x03, 0xEB, 0x46, 0x06, 0x16, 0xF8, 0x08, 0x1C, 0x16, 0xF8, 0x07, 0x3C, 0x5B, 0x1A, ++0x01, 0x33, 0x01, 0xEB, 0x63, 0x03, 0xDB, 0xB2, 0x01, 0x93, 0x01, 0x9B, 0x52, 0xF8, 0x23, 0x00, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x02, 0xEB, 0x45, 0x08, 0x00, 0x9A, 0x18, 0xF8, 0x07, 0x8C, 0x52, 0xF8, 0x28, 0xB0, 0x25, 0x4A, 0x93, 0x45, ++0xA3, 0xDB, 0xB1, 0xF5, 0x7A, 0x7F, 0x02, 0xDA, 0x23, 0x4A, 0x93, 0x45, 0x9D, 0xDA, 0x02, 0x21, 0x0C, 0x44, 0xA0, 0x45, ++0x9D, 0xDA, 0x04, 0xAA, 0x17, 0x44, 0x07, 0xF8, 0x08, 0xAC, 0x07, 0xF8, 0x07, 0xAC, 0x75, 0xE7, 0x02, 0x2F, 0x1C, 0x46, ++0x08, 0x46, 0x66, 0x46, 0x05, 0xF1, 0x02, 0x05, 0xCA, 0xD0, 0x02, 0x27, 0xAA, 0xE7, 0x04, 0xAB, 0x03, 0xEB, 0x45, 0x01, ++0x6D, 0x00, 0x11, 0xF8, 0x08, 0x3C, 0x80, 0x2B, 0x8E, 0xD0, 0x52, 0xF8, 0x23, 0x00, 0x11, 0xF8, 0x07, 0x1C, 0x43, 0xF2, ++0xB0, 0x64, 0xA0, 0x42, 0x0A, 0xDC, 0x0F, 0x4E, 0x52, 0xF8, 0x21, 0x40, 0xB4, 0x42, 0x05, 0xDB, 0xB0, 0xF5, 0x7A, 0x7F, ++0x13, 0xDA, 0x14, 0xF5, 0x7A, 0x7F, 0x10, 0xDD, 0x9C, 0x44, 0x61, 0x45, 0xBF, 0xF6, 0x78, 0xAF, 0x04, 0xAB, 0x1D, 0x44, ++0x80, 0x23, 0x05, 0xF8, 0x08, 0x3C, 0x05, 0xF8, 0x07, 0x3C, 0x6F, 0xE7, 0xA3, 0x42, 0x9B, 0xD2, 0x1C, 0x46, 0x66, 0x46, ++0x98, 0xE7, 0x4F, 0xF0, 0x02, 0x0C, 0xEB, 0xE7, 0x50, 0xC9, 0xFF, 0xFF, 0x19, 0xFC, 0xFF, 0xFF, 0xD0, 0xED, 0x00, 0x7A, ++0x90, 0xED, 0x01, 0x7A, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, ++0x01, 0x6A, 0xB4, 0xEE, 0xE6, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x5E, 0xDA, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x08, 0xDD, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, 0x01, 0x6A, 0xB4, 0xEE, 0xE6, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x50, 0xD9, ++0xD0, 0xED, 0x02, 0x6A, 0xF4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0xD1, 0xED, 0x00, 0x5A, 0x91, 0xED, ++0x02, 0x6A, 0xF4, 0xEE, 0xC6, 0x5A, 0xF1, 0xEE, 0x10, 0xFA, 0x40, 0xDA, 0xF4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x32, 0xDC, 0xB4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0x91, 0xED, 0x01, 0x6A, 0xD1, 0xED, 0x02, 0x7A, ++0xB4, 0xEE, 0xE7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x2D, 0xDA, 0xB4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xDD, ++0x91, 0xED, 0x01, 0x7A, 0xD1, 0xED, 0x02, 0x7A, 0xB4, 0xEE, 0xE7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x1F, 0xD9, 0xD1, 0xED, ++0x00, 0x7A, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x1A, 0xDD, 0x91, 0xED, 0x01, 0x7A, 0xB5, 0xEE, 0xC0, 0x7A, ++0xF1, 0xEE, 0x10, 0xFA, 0x13, 0xDD, 0x91, 0xED, 0x02, 0x7A, 0xB5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x0C, 0xDD, ++0x01, 0x20, 0x70, 0x47, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, 0x02, 0x7A, 0xB4, 0xEE, 0xE7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, ++0xC3, 0xD8, 0x02, 0x20, 0x70, 0x47, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x01, 0xD4, 0x00, 0x20, 0x70, 0x47, ++0xD1, 0xED, 0x01, 0x7A, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0xF6, 0xD5, 0xD1, 0xED, 0x02, 0x7A, 0xF5, 0xEE, ++0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x4C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x28, 0x00, 0xF0, ++0xC7, 0x80, 0x2D, 0xE9, 0xF0, 0x47, 0x00, 0x22, 0xA1, 0xF1, 0x02, 0x08, 0x82, 0xB0, 0x44, 0x46, 0x17, 0x46, 0x94, 0x46, ++0x10, 0x46, 0x4F, 0xF0, 0x01, 0x0E, 0x02, 0xE0, 0x05, 0x2E, 0x11, 0xD0, 0x01, 0x32, 0x34, 0xF9, 0x02, 0x5F, 0x0E, 0xFA, ++0x02, 0xF3, 0x00, 0x2D, 0xD6, 0xB2, 0x43, 0xEA, 0x00, 0x03, 0xF3, 0xDA, 0x01, 0x2A, 0xD8, 0xB2, 0x40, 0xF2, 0x83, 0x80, ++0x01, 0x37, 0x05, 0x2E, 0xFF, 0xB2, 0xED, 0xD1, 0x04, 0x2F, 0x00, 0xF0, 0x81, 0x80, 0x02, 0x2F, 0x00, 0xF2, 0x81, 0x80, ++0xBC, 0xF1, 0x00, 0x0F, 0x0B, 0xD1, 0xB1, 0xF9, 0x02, 0x30, 0xB1, 0xF9, 0x00, 0x20, 0x03, 0xF1, 0x09, 0x04, 0x94, 0x42, ++0x02, 0xDB, 0x09, 0x3B, 0x9A, 0x42, 0x00, 0xDA, 0x4A, 0x80, 0xB1, 0xF9, 0x04, 0x20, 0xB1, 0xF9, 0x06, 0x30, 0x03, 0x24, ++0x40, 0xF2, 0x04, 0x55, 0x9A, 0x42, 0x8D, 0xF8, 0x01, 0x40, 0xAD, 0xF8, 0x02, 0x50, 0xC0, 0xF2, 0x8E, 0x80, 0xB1, 0xF9, ++0x08, 0x20, 0xB1, 0xF9, 0x0A, 0x30, 0x9A, 0x42, 0x25, 0x46, 0x4F, 0xF0, 0x06, 0x09, 0x4F, 0xF0, 0x04, 0x07, 0x4F, 0xF0, ++0x02, 0x04, 0x80, 0xF2, 0x8E, 0x80, 0x40, 0xF2, 0x05, 0x43, 0xAD, 0xF8, 0x02, 0x30, 0x4F, 0xF0, 0x05, 0x0E, 0x4F, 0xF0, ++0x08, 0x08, 0x04, 0x26, 0x0A, 0x22, 0xCB, 0x5F, 0x8F, 0x5E, 0xBB, 0x42, 0x07, 0xDA, 0xBA, 0x46, 0x72, 0x46, 0x8D, 0xF8, ++0x02, 0x40, 0x1F, 0x46, 0xA6, 0x46, 0x53, 0x46, 0x14, 0x46, 0x31, 0xF9, 0x09, 0x20, 0x31, 0xF9, 0x08, 0x80, 0x42, 0x45, ++0x05, 0xDA, 0x8D, 0xF8, 0x03, 0x50, 0x8D, 0xF8, 0x01, 0x60, 0x42, 0x46, 0x35, 0x46, 0x97, 0x42, 0x05, 0xDD, 0x8D, 0xF8, ++0x02, 0x50, 0x8D, 0xF8, 0x01, 0xE0, 0x3A, 0x46, 0x75, 0x46, 0x9D, 0xF8, 0x02, 0xE0, 0x9D, 0xF8, 0x01, 0x60, 0x31, 0xF9, ++0x1E, 0x70, 0x31, 0xF9, 0x16, 0x80, 0x07, 0x32, 0xFE, 0x1D, 0x93, 0x42, 0xD4, 0xBF, 0x04, 0x23, 0x00, 0x23, 0xB0, 0x45, ++0x9D, 0xF8, 0x03, 0x60, 0x31, 0xF9, 0x16, 0x20, 0x02, 0xF1, 0x07, 0x02, 0xD8, 0xBF, 0x43, 0xF0, 0x02, 0x03, 0xBA, 0x42, ++0xA8, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0x06, 0x2B, 0x4E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x4A, 0xA9, 0xA1, 0x9B, 0x93, 0x4A, ++0xB1, 0x00, 0x0C, 0xF1, 0x01, 0x0C, 0x5F, 0xFA, 0x8C, 0xFC, 0x69, 0xE7, 0xBC, 0xF1, 0x02, 0x0F, 0x78, 0xD0, 0x00, 0x23, ++0x1C, 0x46, 0x1A, 0x46, 0x40, 0xFA, 0x03, 0xF5, 0xEF, 0x07, 0x05, 0xD4, 0x31, 0xF8, 0x13, 0x50, 0x01, 0x34, 0x2A, 0x44, ++0xE4, 0xB2, 0x12, 0xB2, 0x01, 0x33, 0x06, 0x2B, 0xF2, 0xD1, 0x92, 0xFB, 0xF4, 0xF2, 0x00, 0x23, 0x40, 0xFA, 0x03, 0xF4, ++0xE6, 0x07, 0x48, 0xBF, 0x21, 0xF8, 0x13, 0x20, 0x01, 0x33, 0x06, 0x2B, 0xF6, 0xD1, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, ++0x8B, 0x1E, 0x80, 0x20, 0x0A, 0x31, 0x33, 0xF9, 0x02, 0x2F, 0x00, 0x2A, 0xB8, 0xBF, 0x18, 0x80, 0x99, 0x42, 0xF8, 0xD1, ++0x70, 0x47, 0xB1, 0xF9, 0x08, 0x20, 0xB1, 0xF9, 0x0A, 0x30, 0x02, 0x25, 0x9A, 0x42, 0x8D, 0xF8, 0x01, 0x50, 0x4F, 0xF0, ++0x04, 0x09, 0x4F, 0xF0, 0x06, 0x07, 0xFF, 0xF6, 0x72, 0xAF, 0x4F, 0xF0, 0x0A, 0x08, 0x08, 0x22, 0x4F, 0xF0, 0x04, 0x0E, ++0x75, 0xE7, 0xBC, 0xF1, 0x00, 0x0F, 0x69, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x02, 0x23, 0x40, 0xFA, 0x03, 0xF5, 0xED, 0x07, ++0x05, 0xD4, 0x31, 0xF8, 0x13, 0x50, 0x01, 0x34, 0x2A, 0x44, 0xE4, 0xB2, 0x12, 0xB2, 0x01, 0x33, 0x06, 0x2B, 0xF2, 0xD1, ++0x64, 0xB9, 0xC3, 0x07, 0x03, 0xD4, 0x0B, 0x88, 0x1A, 0x44, 0x12, 0xB2, 0x01, 0x24, 0x87, 0x07, 0x04, 0xD4, 0x4B, 0x88, ++0x01, 0x34, 0x13, 0x44, 0xE4, 0xB2, 0x1A, 0xB2, 0x00, 0x23, 0x92, 0xFB, 0xF4, 0xF4, 0x00, 0xE0, 0x01, 0x33, 0x40, 0xFA, ++0x03, 0xF2, 0xD6, 0x07, 0xDD, 0xB2, 0x03, 0xD5, 0x01, 0x2B, 0x14, 0xD9, 0x21, 0xF8, 0x13, 0x40, 0x05, 0x2D, 0xF3, 0xD1, ++0xBC, 0xF1, 0x01, 0x0F, 0xA9, 0xD1, 0xC2, 0x07, 0x0F, 0xD4, 0x83, 0x07, 0xA5, 0xD5, 0x0B, 0x88, 0x4B, 0x80, 0xA2, 0xE7, ++0x0A, 0x31, 0x80, 0x23, 0x28, 0xF8, 0x02, 0x3F, 0x88, 0x45, 0xFB, 0xD1, 0x9B, 0xE7, 0xBC, 0xF1, 0x02, 0x0F, 0xDF, 0xD1, ++0xE6, 0xE7, 0x4B, 0x88, 0x0B, 0x80, 0x94, 0xE7, 0x01, 0x22, 0x02, 0xFA, 0x0E, 0xF3, 0xB2, 0x40, 0x13, 0x43, 0x18, 0x43, ++0xC0, 0xB2, 0xB1, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x04, 0xF4, 0x20, 0x43, 0xC0, 0xB2, 0xAB, 0xE7, 0x01, 0x23, 0x03, 0xFA, ++0x06, 0xF6, 0x30, 0x43, 0xA3, 0x40, 0x18, 0x43, 0xC0, 0xB2, 0xA3, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x04, 0xF4, 0x20, 0x43, ++0xAB, 0x40, 0x18, 0x43, 0xC0, 0xB2, 0x9B, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x06, 0xF6, 0x30, 0x43, 0xC0, 0xB2, 0x95, 0xE7, ++0x40, 0xF0, 0x3C, 0x00, 0x92, 0xE7, 0x00, 0xBF, 0xF0, 0xB5, 0xD1, 0xED, 0x01, 0x6A, 0x91, 0xED, 0x00, 0x7A, 0x2D, 0xED, ++0x08, 0x8B, 0xF4, 0xEE, 0xC7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x83, 0xB0, 0x0C, 0x46, 0x07, 0x46, 0x15, 0x46, 0x1E, 0x46, ++0x05, 0xDC, 0xF0, 0xEE, 0x66, 0x7A, 0xF0, 0xEE, 0x47, 0x6A, 0xB0, 0xEE, 0x67, 0x7A, 0xD4, 0xED, 0x02, 0x7A, 0xF4, 0xEE, ++0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xDC, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x48, 0xBF, 0xB0, 0xEE, ++0x67, 0x7A, 0xF0, 0xEE, 0x66, 0x7A, 0x77, 0xEE, 0xC7, 0x7A, 0xB0, 0xEE, 0x08, 0xBA, 0xFC, 0xEE, 0xE7, 0x7A, 0x17, 0xEE, ++0x90, 0x3A, 0xB3, 0x70, 0xD4, 0xED, 0x00, 0x8A, 0x94, 0xED, 0x01, 0xAA, 0xD4, 0xED, 0x02, 0x9A, 0x6A, 0xEE, 0x0A, 0x7A, ++0x28, 0xEE, 0xA8, 0x6A, 0x69, 0xEE, 0xA9, 0xAA, 0x36, 0xEE, 0x27, 0x6A, 0x38, 0xEE, 0x8A, 0x7A, 0x76, 0xEE, 0x2A, 0xAA, ++0x37, 0xEE, 0x29, 0x9A, 0x2A, 0xEE, 0x8B, 0xBA, 0x69, 0xEE, 0x09, 0x7A, 0x3B, 0xEE, 0x67, 0xBA, 0xB5, 0xEE, 0xC0, 0xBA, ++0xF1, 0xEE, 0x10, 0xFA, 0x40, 0xF3, 0xD0, 0x80, 0x1B, 0xEE, 0x10, 0x0A, 0x33, 0xF0, 0x44, 0xF8, 0x6F, 0xA3, 0xD3, 0xE9, ++0x00, 0x23, 0x33, 0xF0, 0x09, 0xFB, 0x80, 0xB1, 0x9F, 0xED, 0x6E, 0xBA, 0x33, 0x78, 0x6E, 0x49, 0x43, 0xF0, 0x04, 0x03, ++0x33, 0x70, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0x73, 0xF8, 0xD4, 0xED, 0x00, 0x8A, 0x94, 0xED, 0x01, 0xAA, 0xD4, 0xED, ++0x02, 0x9A, 0x95, 0xED, 0x00, 0x4A, 0xD5, 0xED, 0x01, 0x4A, 0x95, 0xED, 0x02, 0x5A, 0xF7, 0xEE, 0x00, 0x7A, 0x87, 0xEE, ++0x8B, 0x6A, 0x0D, 0x2F, 0xF0, 0xEE, 0x08, 0x6A, 0x26, 0xEE, 0x49, 0x7A, 0x66, 0xEE, 0x26, 0x6A, 0x2A, 0xEE, 0x86, 0x6A, ++0x66, 0xEE, 0xA8, 0x7A, 0x66, 0xEE, 0x8A, 0x5A, 0x67, 0xEE, 0x28, 0x8A, 0x27, 0xEE, 0x0A, 0xAA, 0x77, 0xEE, 0x87, 0x7A, ++0x26, 0xEE, 0xA9, 0x8A, 0x78, 0xEE, 0x86, 0x8A, 0x67, 0xEE, 0x29, 0x9A, 0x75, 0xEE, 0x87, 0x5A, 0x3A, 0xEE, 0x06, 0xAA, ++0x38, 0xEE, 0x07, 0x8A, 0x67, 0xEE, 0x84, 0x7A, 0x68, 0xEE, 0x84, 0x8A, 0x79, 0xEE, 0x86, 0x9A, 0x25, 0xEE, 0xA4, 0x7A, ++0x2A, 0xEE, 0x24, 0xAA, 0x77, 0xEE, 0x87, 0x7A, 0x78, 0xEE, 0x8A, 0x8A, 0x28, 0xEE, 0x05, 0x8A, 0x69, 0xEE, 0x85, 0x9A, ++0x37, 0xEE, 0x88, 0x8A, 0x78, 0xEE, 0xA9, 0x8A, 0x2E, 0xD9, 0xF3, 0xEE, 0x04, 0x7A, 0xB4, 0xEE, 0xE7, 0x8A, 0xF1, 0xEE, ++0x10, 0xFA, 0x27, 0xD5, 0x33, 0x78, 0x44, 0x49, 0x43, 0xF0, 0x08, 0x03, 0x33, 0x70, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, ++0x1D, 0xF8, 0xB7, 0xEE, 0x00, 0x8A, 0xF0, 0xEE, 0x00, 0x6A, 0xB1, 0xEE, 0x68, 0x7A, 0xC7, 0xEE, 0x08, 0x7A, 0x9F, 0xED, ++0x3D, 0x7A, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x21, 0xDC, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x4E, 0xD4, 0xB6, 0xEE, 0x00, 0x7A, 0x77, 0xEE, 0x87, 0x7A, 0xFC, 0xEE, 0xE7, 0x7A, 0xCD, 0xED, 0x01, 0x7A, 0x9D, 0xF8, ++0x04, 0x30, 0x12, 0xE0, 0x18, 0xEE, 0x10, 0x0A, 0x32, 0xF0, 0xBA, 0xFF, 0x2A, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x33, 0xF0, ++0x7F, 0xFA, 0x00, 0x28, 0xCC, 0xD1, 0x68, 0xEE, 0x08, 0x6A, 0xF7, 0xEE, 0x00, 0x7A, 0x76, 0xEE, 0xA7, 0x6A, 0xD2, 0xE7, ++0xFF, 0x23, 0x73, 0x70, 0xD4, 0xED, 0x00, 0x7A, 0x94, 0xED, 0x01, 0x7A, 0xD4, 0xED, 0x02, 0x4A, 0x95, 0xED, 0x00, 0x5A, ++0xD5, 0xED, 0x01, 0x5A, 0x95, 0xED, 0x02, 0x6A, 0x68, 0xEE, 0x27, 0x7A, 0x28, 0xEE, 0x07, 0x7A, 0x77, 0xEE, 0xA8, 0x7A, ++0x37, 0xEE, 0x28, 0x7A, 0x28, 0xEE, 0x24, 0x8A, 0x77, 0xEE, 0xC5, 0x7A, 0x37, 0xEE, 0x65, 0x7A, 0x38, 0xEE, 0x28, 0x8A, ++0x27, 0xEE, 0x07, 0x7A, 0x38, 0xEE, 0x46, 0x8A, 0x67, 0xEE, 0xA7, 0x7A, 0x28, 0xEE, 0x08, 0x8A, 0x77, 0xEE, 0x87, 0x7A, ++0x37, 0xEE, 0x88, 0x8A, 0xC8, 0xEE, 0x26, 0x7A, 0xC6, 0xED, 0x01, 0x7A, 0x03, 0xB0, 0xBD, 0xEC, 0x08, 0x8B, 0xF0, 0xBD, ++0x00, 0x23, 0xCC, 0xE7, 0xF1, 0xEE, 0x4B, 0x7A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x72, 0xFF, 0x06, 0xA3, 0xD3, 0xE9, ++0x00, 0x23, 0x33, 0xF0, 0x37, 0xFA, 0x00, 0x28, 0x3F, 0xF4, 0x3D, 0xAF, 0x9F, 0xED, 0x08, 0xBA, 0x2A, 0xE7, 0x00, 0xBF, ++0xAF, 0xF3, 0x00, 0x80, 0xF1, 0x68, 0xE3, 0x88, 0xB5, 0xF8, 0xE4, 0x3E, 0x00, 0x50, 0xC3, 0x47, 0xD4, 0x79, 0x15, 0x00, ++0x00, 0x7A, 0x15, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xAC, 0xC5, 0x27, 0xB7, 0x2D, 0xE9, 0xF0, 0x47, 0x09, 0x29, 0x8E, 0xB0, ++0x88, 0x46, 0x1D, 0x46, 0x70, 0xD9, 0x03, 0x28, 0x6E, 0xD0, 0x4F, 0xF0, 0x86, 0x4A, 0x57, 0x1E, 0x00, 0x26, 0x0D, 0xF1, ++0x18, 0x09, 0x00, 0x22, 0x10, 0x46, 0xF1, 0xB2, 0xD3, 0xB2, 0x8B, 0x42, 0x19, 0xD0, 0x00, 0x2B, 0x00, 0xF0, 0xAF, 0x80, ++0xBB, 0x5C, 0x07, 0xEE, 0x90, 0x3A, 0x0E, 0xAB, 0xF8, 0xEE, 0x67, 0x7A, 0x03, 0xEB, 0x80, 0x03, 0x43, 0xED, 0x0E, 0x7A, ++0x84, 0x00, 0x55, 0xF8, 0x22, 0x30, 0x07, 0xEE, 0x90, 0x3A, 0x0E, 0xAB, 0xF8, 0xEE, 0xE7, 0x7A, 0x1C, 0x44, 0x01, 0x30, ++0xC0, 0xB2, 0x44, 0xED, 0x0B, 0x7A, 0x01, 0x32, 0x04, 0x2A, 0xDF, 0xD1, 0x00, 0x23, 0x03, 0xA9, 0x68, 0x46, 0x09, 0xF8, ++0x36, 0x30, 0xFF, 0xF7, 0x9F, 0xFC, 0x10, 0xF0, 0x0E, 0x0F, 0x09, 0xF8, 0x36, 0x00, 0x00, 0xF0, 0x95, 0x80, 0x01, 0x36, ++0x04, 0x2E, 0xCC, 0xD1, 0x07, 0xAD, 0x00, 0x24, 0x2A, 0x46, 0x23, 0x46, 0x80, 0x21, 0x12, 0xF8, 0x04, 0x0C, 0x00, 0x28, ++0x40, 0xF0, 0x82, 0x80, 0x0E, 0xA8, 0x80, 0x29, 0x00, 0xEB, 0xC1, 0x00, 0x00, 0xF0, 0x8A, 0x80, 0x92, 0xED, 0x00, 0x7A, ++0x50, 0xED, 0x07, 0x7A, 0xB4, 0xEE, 0x67, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x98, 0xBF, 0x19, 0x46, 0x01, 0x33, 0xDB, 0xB2, ++0x04, 0x2B, 0x02, 0xF1, 0x08, 0x02, 0xE4, 0xD1, 0x00, 0x2C, 0x00, 0xF0, 0x84, 0x80, 0x80, 0x29, 0x76, 0xD0, 0x0E, 0xAB, ++0x03, 0xEB, 0xC1, 0x00, 0x42, 0x46, 0x10, 0xF8, 0x1F, 0x4C, 0x10, 0xF8, 0x20, 0x3C, 0x55, 0x49, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x22, 0xFF, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x13, 0x78, 0xD5, 0xED, 0x00, 0x6A, 0x95, 0xED, ++0x01, 0x7A, 0xD5, 0xED, 0x02, 0x7A, 0x05, 0xEE, 0x90, 0x3A, 0x53, 0x78, 0x06, 0xEE, 0x10, 0x3A, 0xF8, 0xEE, 0x65, 0x5A, ++0xB8, 0xEE, 0x46, 0x6A, 0xF8, 0xEE, 0xE6, 0x6A, 0xB8, 0xEE, 0xC7, 0x7A, 0xF8, 0xEE, 0xE7, 0x7A, 0x4F, 0xF0, 0x86, 0x42, ++0x00, 0x23, 0xB8, 0xF1, 0x09, 0x0F, 0xCD, 0xED, 0x01, 0x5A, 0x8D, 0xED, 0x02, 0x6A, 0xCD, 0xED, 0x03, 0x6A, 0x8D, 0xED, ++0x04, 0x7A, 0xCD, 0xED, 0x05, 0x7A, 0x00, 0x92, 0x8D, 0xF8, 0x18, 0x30, 0x16, 0xD8, 0x06, 0xAB, 0x03, 0xAA, 0x69, 0x46, ++0x40, 0x46, 0xFF, 0xF7, 0x17, 0xFE, 0x9D, 0xF8, 0x18, 0x30, 0x13, 0xF0, 0x0E, 0x0F, 0x4C, 0xD1, 0x9D, 0xF8, 0x19, 0x40, ++0x35, 0x49, 0x42, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xE2, 0xFE, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, ++0x03, 0xA9, 0x68, 0x46, 0xFF, 0xF7, 0x1C, 0xFC, 0x10, 0xF0, 0x0E, 0x0F, 0x8D, 0xF8, 0x18, 0x00, 0x18, 0xBF, 0x03, 0x46, ++0x49, 0xD0, 0xC8, 0xF1, 0x09, 0x04, 0x64, 0x01, 0xE6, 0xE7, 0x0E, 0xAB, 0x03, 0xEB, 0x80, 0x03, 0x84, 0x00, 0x43, 0xF8, ++0x38, 0xAC, 0x54, 0xE7, 0x06, 0x07, 0x1B, 0xD4, 0x01, 0x28, 0x08, 0xBF, 0x01, 0x24, 0x87, 0xE7, 0x09, 0xEB, 0xC6, 0x03, ++0x03, 0xAA, 0x69, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xE3, 0xFD, 0x62, 0xE7, 0x19, 0x46, 0x7D, 0xE7, 0x00, 0x23, 0x15, 0xF8, ++0x04, 0x2C, 0x01, 0x2A, 0x17, 0xD0, 0x01, 0x33, 0xDB, 0xB2, 0x04, 0x2B, 0x05, 0xF1, 0x08, 0x05, 0xF5, 0xD1, 0x80, 0x29, ++0x7F, 0xF4, 0x7B, 0xAF, 0x17, 0x49, 0x42, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xA4, 0xFE, 0xC8, 0xF1, 0x09, 0x04, ++0x64, 0x01, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x80, 0x24, 0xB2, 0xE7, 0x0E, 0xAA, 0x80, 0x29, 0x02, 0xEB, ++0xC1, 0x02, 0x0A, 0xD0, 0x95, 0xED, 0x00, 0x7A, 0x52, 0xED, 0x07, 0x7A, 0xB4, 0xEE, 0x67, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, ++0x98, 0xBF, 0x19, 0x46, 0xD7, 0xE7, 0x19, 0x46, 0xD5, 0xE7, 0x06, 0xAB, 0x03, 0xAA, 0x69, 0x46, 0x40, 0x46, 0xFF, 0xF7, ++0xAB, 0xFD, 0x9D, 0xF8, 0x18, 0x30, 0x13, 0xF0, 0x0E, 0x0F, 0x93, 0xD0, 0xA9, 0xE7, 0x00, 0xBF, 0x14, 0x7A, 0x15, 0x00, ++0x30, 0x7A, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x9A, 0x4A, 0xDF, 0xF8, 0x8C, 0x82, 0x13, 0x68, 0x2D, 0xED, 0x08, 0x8B, ++0x23, 0xF4, 0xFF, 0x43, 0x43, 0xF4, 0xCE, 0x35, 0x8B, 0xB0, 0x43, 0xF4, 0x1D, 0x43, 0x0C, 0x46, 0x45, 0xF4, 0x80, 0x75, ++0x01, 0x46, 0x13, 0x60, 0x01, 0x20, 0x15, 0x60, 0x0D, 0x46, 0x03, 0x91, 0xFC, 0xF7, 0xBA, 0xFD, 0xA2, 0x7B, 0x8F, 0x48, ++0x02, 0xF0, 0x0F, 0x03, 0x01, 0x68, 0x12, 0x09, 0x9B, 0x02, 0x43, 0xEA, 0x82, 0x13, 0x21, 0xF4, 0x7F, 0x52, 0x13, 0x43, ++0x03, 0x60, 0x02, 0x20, 0xFC, 0xF7, 0xAA, 0xFD, 0xAB, 0x6B, 0xC3, 0xF3, 0x07, 0x22, 0x02, 0x92, 0x4F, 0xEA, 0x02, 0x4B, ++0xDA, 0xB2, 0x01, 0x92, 0x4F, 0xEA, 0x03, 0x6A, 0x4F, 0xF0, 0x00, 0x09, 0xDD, 0xE9, 0x01, 0x32, 0xB9, 0xF1, 0x00, 0x0F, ++0x18, 0xBF, 0x13, 0x46, 0xA3, 0xF1, 0x40, 0x02, 0x12, 0xB2, 0x40, 0x33, 0x5F, 0xFA, 0x89, 0xF1, 0x00, 0x2A, 0xAD, 0xF8, ++0x14, 0x20, 0xAD, 0xF8, 0x16, 0x30, 0x00, 0x91, 0xC0, 0xF2, 0xEA, 0x80, 0xFF, 0x2B, 0x01, 0xD9, 0x77, 0x4B, 0x05, 0x93, ++0x00, 0x25, 0x2E, 0x46, 0x05, 0x24, 0x48, 0xF2, 0x80, 0x07, 0xBD, 0xF9, 0x14, 0x30, 0x08, 0xA9, 0x06, 0xA8, 0xB9, 0xF1, ++0x00, 0x0F, 0x00, 0xF0, 0xC3, 0x80, 0x4A, 0xEA, 0x03, 0x43, 0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0xFF, 0xF7, 0xAE, 0xF8, ++0xBD, 0xF9, 0x16, 0x30, 0x4A, 0xEA, 0x03, 0x43, 0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0x09, 0xA9, 0x07, 0xA8, 0xFF, 0xF7, ++0xA3, 0xF8, 0xDD, 0xE9, 0x06, 0x02, 0xDD, 0xE9, 0x08, 0x13, 0x01, 0x3C, 0x12, 0x1A, 0x5B, 0x1A, 0x14, 0xF0, 0xFF, 0x04, ++0x16, 0x44, 0x1D, 0x44, 0xD9, 0xD1, 0x62, 0x4B, 0x83, 0xFB, 0x06, 0x12, 0xF6, 0x17, 0xC6, 0xEB, 0x62, 0x06, 0x07, 0xEE, ++0x90, 0x6A, 0x83, 0xFB, 0x05, 0x13, 0xED, 0x17, 0xC5, 0xEB, 0x63, 0x05, 0xB8, 0xEE, 0xE7, 0x7A, 0x07, 0xEE, 0x90, 0x5A, ++0xF8, 0xEE, 0xE7, 0x7A, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x9D, 0x80, 0x00, 0x9B, 0x01, 0x2B, 0x40, 0xF0, 0x9D, 0x80, ++0xC7, 0xEE, 0x27, 0x9A, 0x03, 0x9B, 0x54, 0x49, 0x54, 0x4F, 0x4F, 0xF4, 0x00, 0x50, 0x1E, 0x1F, 0x03, 0xF1, 0x3C, 0x08, ++0xB6, 0xEE, 0x00, 0xAA, 0x79, 0xEE, 0x88, 0x9A, 0xF7, 0xEE, 0x00, 0xAA, 0x69, 0xEE, 0x8A, 0x9A, 0x8A, 0xEE, 0xA9, 0x8A, ++0xFD, 0xEE, 0xC8, 0x8A, 0x18, 0xEE, 0x90, 0x2A, 0x20, 0xF0, 0xCA, 0xFD, 0xF8, 0xEE, 0xE8, 0x8A, 0xDF, 0xED, 0x49, 0x7A, ++0x49, 0x49, 0x38, 0xEE, 0x68, 0x8A, 0x4F, 0xF4, 0x00, 0x50, 0x28, 0xEE, 0x27, 0x8A, 0xFD, 0xEE, 0xC8, 0x7A, 0x17, 0xEE, ++0x90, 0x2A, 0x20, 0xF0, 0xB9, 0xFD, 0x69, 0xEE, 0xA9, 0x7A, 0x39, 0xEE, 0xAA, 0xBA, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, ++0x71, 0xFD, 0x40, 0x4B, 0x00, 0x22, 0x32, 0xF0, 0x0F, 0xFC, 0x7A, 0xEE, 0xE9, 0xAA, 0x04, 0x46, 0x0D, 0x46, 0x56, 0xF8, ++0x04, 0x3F, 0xC3, 0xF3, 0x07, 0x22, 0x08, 0xEE, 0x90, 0x2A, 0xDB, 0xB2, 0x08, 0xEE, 0x10, 0x3A, 0xF8, 0xEE, 0xE8, 0x8A, ++0xB8, 0xEE, 0xC8, 0x8A, 0x68, 0xEE, 0xAA, 0x8A, 0x28, 0xEE, 0x0B, 0x8A, 0x69, 0xEE, 0xA8, 0x7A, 0x78, 0xEE, 0x67, 0x7A, ++0x29, 0xEE, 0x88, 0x8A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x4E, 0xFD, 0x22, 0x46, 0x2B, 0x46, 0x32, 0xF0, 0xCC, 0xFE, ++0x33, 0xF0, 0x5A, 0xF8, 0x78, 0xEE, 0x28, 0x7A, 0x09, 0xEE, 0x10, 0x0A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x40, 0xFD, ++0x22, 0x46, 0x2B, 0x46, 0x32, 0xF0, 0xBE, 0xFE, 0x33, 0xF0, 0x4C, 0xF8, 0x07, 0xEE, 0x90, 0x0A, 0x77, 0xEE, 0x8A, 0x7A, ++0x39, 0xEE, 0x0A, 0x9A, 0xFD, 0xEE, 0xE7, 0x7A, 0xB0, 0x45, 0x17, 0xEE, 0x90, 0x3A, 0xFD, 0xEE, 0xC9, 0x7A, 0x4F, 0xEA, ++0x03, 0x23, 0xCD, 0xED, 0x00, 0x7A, 0x9D, 0xF8, 0x00, 0x20, 0x03, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x02, 0x03, 0x43, 0xEA, ++0x07, 0x03, 0x33, 0x60, 0xB5, 0xD1, 0x0B, 0xB0, 0xBD, 0xEC, 0x08, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0xEA, 0x03, 0x63, ++0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0x08, 0xA9, 0x06, 0xA8, 0xFE, 0xF7, 0xE9, 0xFF, 0xBD, 0xF9, 0x16, 0x30, 0x4B, 0xEA, ++0x03, 0x63, 0x3B, 0x43, 0x39, 0xE7, 0xF1, 0xEE, 0x67, 0x7A, 0x87, 0xEE, 0x87, 0x8A, 0x09, 0xF1, 0x01, 0x09, 0x01, 0xE7, ++0x4F, 0xF4, 0x00, 0x03, 0x05, 0x93, 0x15, 0xE7, 0x58, 0x40, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, 0x80, 0x00, 0xFF, 0x00, ++0x67, 0x66, 0x66, 0x66, 0x48, 0x7A, 0x15, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x7A, 0x44, 0x58, 0x7A, 0x15, 0x00, ++0x00, 0x00, 0xF0, 0x3F, 0x4C, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0xB5, 0x4C, 0x2D, 0xED, 0x04, 0x8B, 0x27, 0x68, ++0xAD, 0xF2, 0xE4, 0x7D, 0x06, 0x46, 0x0D, 0x46, 0x14, 0x46, 0xB2, 0x49, 0x0A, 0x94, 0x3A, 0x46, 0x4F, 0xF4, 0x00, 0x50, ++0x9A, 0x46, 0xCD, 0xE9, 0x13, 0x56, 0x20, 0xF0, 0x17, 0xFD, 0xAE, 0x4B, 0xAE, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x10, 0xFD, 0xAC, 0x4B, 0xAD, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x09, 0xFD, 0xAB, 0x4B, ++0xAB, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x02, 0xFD, 0xA9, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, ++0xFD, 0xFC, 0x16, 0xF0, 0x01, 0x03, 0x15, 0x93, 0x07, 0xD1, 0xA6, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x61, 0x43, 0xF4, ++0xC0, 0x53, 0x11, 0x60, 0x13, 0x60, 0x14, 0x9A, 0xC2, 0xF3, 0x40, 0x03, 0x03, 0x33, 0x12, 0xF0, 0x0C, 0x0F, 0x09, 0xEE, ++0x10, 0x3A, 0xC2, 0xF3, 0x81, 0x03, 0x00, 0xF0, 0x9C, 0x82, 0x01, 0x2B, 0x14, 0xBF, 0x0A, 0x23, 0x05, 0x23, 0x08, 0xEE, ++0x90, 0x3A, 0x9A, 0x4A, 0x9A, 0x4E, 0x14, 0x68, 0xDF, 0xF8, 0x7C, 0xE2, 0x99, 0x4B, 0x9A, 0x49, 0xDF, 0xF8, 0x78, 0x92, ++0xDF, 0xF8, 0x78, 0xB2, 0x98, 0x48, 0xDF, 0xF8, 0x78, 0xC2, 0x98, 0x4F, 0xDF, 0xF8, 0x74, 0x82, 0x24, 0xF0, 0x04, 0x04, ++0x14, 0x60, 0x35, 0x68, 0x00, 0x24, 0x25, 0xF4, 0x70, 0x45, 0x35, 0x60, 0xCE, 0xF8, 0x00, 0x40, 0x1D, 0x68, 0x45, 0xF0, ++0x80, 0x05, 0x1D, 0x60, 0x0D, 0x68, 0x45, 0xF0, 0x00, 0x45, 0x0D, 0x60, 0x15, 0x68, 0x01, 0x26, 0x45, 0xF0, 0x04, 0x05, ++0x15, 0x60, 0xCB, 0xF8, 0x00, 0x60, 0xC9, 0xF8, 0x00, 0x40, 0x15, 0x68, 0x25, 0xF0, 0x04, 0x05, 0x15, 0x60, 0x0D, 0x68, ++0x25, 0xF0, 0x00, 0x45, 0x0D, 0x60, 0x1D, 0x68, 0x25, 0xF0, 0x80, 0x05, 0x1D, 0x60, 0x15, 0x68, 0x45, 0xF0, 0x04, 0x05, ++0x15, 0x60, 0x82, 0x4D, 0x2A, 0x68, 0x42, 0xF0, 0x02, 0x02, 0x2A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x42, 0x22, 0xF0, ++0x04, 0x02, 0x42, 0xF4, 0x80, 0x42, 0x32, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x07, 0x22, 0x42, 0xF0, 0xC0, 0x62, ++0x42, 0xF4, 0x84, 0x72, 0x1A, 0x60, 0x0B, 0x68, 0x03, 0xF0, 0x00, 0x43, 0x43, 0xEA, 0x0A, 0x03, 0x0B, 0x60, 0x03, 0x68, ++0x43, 0xF0, 0x3F, 0x03, 0x03, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x0B, 0x94, 0x43, 0xF4, 0x00, 0x63, 0x38, 0xAA, 0x78, 0xA9, ++0x10, 0x92, 0x0F, 0x91, 0xCC, 0xF8, 0x00, 0x30, 0x0D, 0xF1, 0x7F, 0x03, 0xCD, 0xE9, 0x11, 0x21, 0x0D, 0x93, 0x08, 0xEE, ++0x10, 0x4A, 0x0D, 0xF1, 0xAF, 0x03, 0x81, 0x46, 0x0E, 0x93, 0x00, 0x23, 0x0C, 0x93, 0x9D, 0xF8, 0x30, 0x50, 0x18, 0xEE, ++0x10, 0x3A, 0x2B, 0x43, 0x09, 0x93, 0x00, 0x24, 0x3D, 0xE0, 0x0C, 0x9B, 0x00, 0x2B, 0x6C, 0xD0, 0x66, 0x00, 0x0D, 0x9B, ++0x26, 0x44, 0x48, 0xF2, 0x80, 0x0B, 0x13, 0xF8, 0x06, 0xA0, 0x0E, 0x9B, 0x9E, 0x5D, 0x4F, 0xEA, 0x0A, 0x63, 0x43, 0xEA, ++0x0A, 0x43, 0x43, 0xEA, 0x0B, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0x19, 0xA9, 0x18, 0xA8, 0xFE, 0xF7, 0xE3, 0xFE, 0xB2, 0x45, ++0x0A, 0xD0, 0x33, 0x06, 0x43, 0xEA, 0x06, 0x46, 0x46, 0xEA, 0x0B, 0x06, 0xC8, 0xF8, 0x00, 0x60, 0x19, 0xA9, 0x17, 0xA8, ++0xFE, 0xF7, 0xD6, 0xFE, 0x04, 0xEB, 0x84, 0x03, 0xB8, 0xAA, 0xDE, 0x00, 0x00, 0x21, 0x02, 0xEB, 0xC3, 0x03, 0x28, 0x46, ++0x18, 0x9A, 0xFF, 0xF7, 0x51, 0xF8, 0x0D, 0xF5, 0xAC, 0x63, 0x33, 0x44, 0x19, 0x9A, 0x01, 0x34, 0x00, 0x21, 0x28, 0x46, ++0xFF, 0xF7, 0x48, 0xF8, 0x10, 0x2C, 0xB8, 0xAE, 0x0D, 0xF5, 0xAC, 0x6B, 0x59, 0xD0, 0x3B, 0x68, 0x23, 0xF4, 0xFF, 0x43, ++0x43, 0xEA, 0x44, 0x23, 0x43, 0xF4, 0x01, 0x42, 0x43, 0xF4, 0xC0, 0x33, 0x43, 0xF4, 0x80, 0x73, 0x3A, 0x60, 0x01, 0x20, ++0x3B, 0x60, 0xFC, 0xF7, 0x71, 0xFB, 0x09, 0x9B, 0xE6, 0xB2, 0x00, 0x2B, 0x3D, 0xD0, 0x0A, 0x9B, 0xD9, 0xF8, 0x00, 0x10, ++0x1A, 0x5D, 0x02, 0xF0, 0x0F, 0x03, 0x9B, 0x02, 0x12, 0x09, 0x43, 0xEA, 0x82, 0x13, 0x21, 0xF4, 0x7F, 0x52, 0x13, 0x43, ++0xC9, 0xF8, 0x00, 0x30, 0x02, 0x20, 0xFC, 0xF7, 0x5B, 0xFB, 0x0B, 0x9B, 0x00, 0x2B, 0x98, 0xD1, 0x4F, 0xF0, 0x80, 0x33, ++0xC8, 0xF8, 0x00, 0x30, 0x19, 0xA9, 0x18, 0xA8, 0xFE, 0xF7, 0x8C, 0xFE, 0xB4, 0xE7, 0x10, 0x9B, 0x04, 0xEB, 0x44, 0x0B, ++0x03, 0xEB, 0x04, 0x12, 0x20, 0xAB, 0x18, 0xEE, 0x10, 0x0A, 0x5B, 0x44, 0x00, 0x92, 0x31, 0x46, 0x0D, 0xF1, 0x5A, 0x02, ++0xFE, 0xF7, 0xF2, 0xFF, 0x0F, 0x9B, 0x4F, 0xEA, 0x04, 0x1A, 0x0A, 0xEB, 0x03, 0x02, 0x2C, 0xAB, 0x31, 0x46, 0x00, 0x92, ++0x18, 0xEE, 0x10, 0x0A, 0x5B, 0x44, 0x0D, 0xF1, 0x5B, 0x02, 0x66, 0x00, 0xFE, 0xF7, 0xE2, 0xFF, 0x73, 0xE7, 0xFE, 0xF7, ++0xA7, 0xFE, 0x0A, 0x9B, 0x18, 0x55, 0x02, 0x20, 0xFC, 0xF7, 0x28, 0xFB, 0xCE, 0xE7, 0x0C, 0x9B, 0x18, 0xEE, 0x90, 0x2A, ++0x01, 0x33, 0x93, 0x42, 0x0C, 0x93, 0x7F, 0xF4, 0x58, 0xAF, 0x18, 0xEE, 0x90, 0xAA, 0x00, 0x25, 0x45, 0xE0, 0x00, 0xBF, ++0x10, 0x20, 0x34, 0x40, 0x60, 0x7A, 0x15, 0x00, 0x1C, 0x20, 0x34, 0x40, 0x74, 0x7A, 0x15, 0x00, 0x04, 0x22, 0x34, 0x40, ++0x88, 0x7A, 0x15, 0x00, 0x18, 0x00, 0x58, 0x40, 0x9C, 0x7A, 0x15, 0x00, 0xB0, 0x7A, 0x15, 0x00, 0x04, 0x40, 0x34, 0x40, ++0x30, 0x20, 0x34, 0x40, 0x60, 0x20, 0x34, 0x40, 0x5C, 0x20, 0x34, 0x40, 0x64, 0x20, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, ++0x58, 0x40, 0x34, 0x40, 0x80, 0x21, 0x34, 0x40, 0x68, 0x20, 0x34, 0x40, 0x0C, 0xB6, 0x33, 0x40, 0x08, 0xB6, 0x33, 0x40, ++0x20, 0x40, 0x34, 0x40, 0x4C, 0x40, 0x34, 0x40, 0x06, 0x2D, 0x34, 0xBF, 0x32, 0x21, 0x64, 0x21, 0x09, 0x91, 0xFE, 0xF7, ++0xDB, 0xFF, 0x11, 0x9B, 0x09, 0x99, 0x84, 0x46, 0x43, 0xF8, 0x04, 0xC0, 0x5A, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xD2, 0xFF, ++0x01, 0x35, 0x12, 0x9B, 0x10, 0x2D, 0x18, 0x51, 0x06, 0xF1, 0x28, 0x06, 0x0B, 0xF1, 0x28, 0x0B, 0x14, 0xD0, 0xBA, 0xF1, ++0x01, 0x0F, 0x32, 0x46, 0x4F, 0xEA, 0x05, 0x14, 0x50, 0x46, 0xDF, 0xD1, 0x11, 0x9B, 0x30, 0x68, 0x18, 0x51, 0x01, 0x35, ++0x12, 0x9B, 0xDB, 0xF8, 0x00, 0x10, 0x19, 0x51, 0x10, 0x2D, 0x06, 0xF1, 0x28, 0x06, 0x0B, 0xF1, 0x28, 0x0B, 0xEA, 0xD1, ++0x11, 0x9A, 0x0B, 0x9B, 0x04, 0x32, 0x11, 0x92, 0x12, 0x9A, 0x04, 0x32, 0x12, 0x92, 0x0D, 0x9A, 0x01, 0x32, 0x0D, 0x92, ++0x0E, 0x9A, 0x01, 0x32, 0x01, 0x33, 0x0E, 0x92, 0x19, 0xEE, 0x10, 0x2A, 0x0B, 0x93, 0xDB, 0xB2, 0x9A, 0x42, 0x08, 0xEE, ++0x10, 0x3A, 0x3F, 0xF6, 0xE0, 0xAE, 0x20, 0xAD, 0x2C, 0xAC, 0xAB, 0x46, 0x0B, 0x95, 0xDD, 0xF8, 0x40, 0x80, 0x0F, 0x9F, ++0x09, 0x94, 0x19, 0xEE, 0x10, 0x5A, 0xA2, 0x46, 0x00, 0x26, 0x09, 0xE0, 0x13, 0x9A, 0x42, 0xF8, 0x26, 0x30, 0x01, 0x36, ++0x0B, 0xF1, 0x03, 0x0B, 0x08, 0xF1, 0x10, 0x08, 0x0A, 0xF1, 0x03, 0x0A, 0x5F, 0xFA, 0x86, 0xF9, 0x49, 0x46, 0x43, 0x46, ++0x5A, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x98, 0xFB, 0x07, 0xEB, 0x06, 0x13, 0x04, 0x46, 0x52, 0x46, 0x49, 0x46, 0x28, 0x46, ++0xFF, 0xF7, 0x90, 0xFB, 0x03, 0x02, 0xE2, 0xB2, 0x03, 0xF4, 0x7F, 0x43, 0x13, 0x43, 0x43, 0xF0, 0x00, 0x43, 0x09, 0x2E, ++0x43, 0xF4, 0x00, 0x03, 0xDA, 0xD9, 0x1A, 0xAB, 0x03, 0xEB, 0x46, 0x02, 0x1D, 0xAB, 0x03, 0xEB, 0x46, 0x03, 0xB9, 0xF1, ++0x0F, 0x0F, 0x22, 0xF8, 0x14, 0x4C, 0x23, 0xF8, 0x14, 0x0C, 0xD0, 0xD1, 0x14, 0x9B, 0x09, 0x9C, 0x0B, 0x9D, 0xC3, 0xF3, ++0x40, 0x10, 0x1A, 0xA9, 0x09, 0x90, 0xFF, 0xF7, 0xD3, 0xF8, 0x09, 0x98, 0x1D, 0xA9, 0xFF, 0xF7, 0xCF, 0xF8, 0x13, 0x9B, ++0xDF, 0xF8, 0x98, 0xC1, 0x1D, 0xA8, 0x1A, 0xA9, 0x03, 0xF1, 0x24, 0x06, 0x03, 0xF1, 0x3C, 0x07, 0x30, 0xF9, 0x02, 0x3B, ++0x31, 0xF9, 0x02, 0x2B, 0x1B, 0x02, 0x03, 0xF4, 0x7F, 0x43, 0xD2, 0xB2, 0x13, 0x43, 0x43, 0xEA, 0x0C, 0x03, 0x46, 0xF8, ++0x04, 0x3F, 0xBE, 0x42, 0xF0, 0xD1, 0x10, 0x9B, 0xDF, 0xF8, 0x6C, 0x81, 0xDD, 0xF8, 0x3C, 0xA0, 0x03, 0xF5, 0x80, 0x77, ++0x00, 0x26, 0x99, 0x46, 0xD9, 0xF8, 0x0C, 0x20, 0xAB, 0x78, 0xD9, 0xF8, 0x08, 0xC0, 0x68, 0x78, 0xD9, 0xF8, 0x04, 0x10, ++0x06, 0x92, 0x15, 0xF8, 0x03, 0x2B, 0x05, 0x93, 0x59, 0xF8, 0x10, 0x3B, 0x00, 0x93, 0xCD, 0xE9, 0x03, 0x0C, 0xCD, 0xE9, ++0x01, 0x21, 0x80, 0x23, 0x32, 0x46, 0x41, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xC6, 0xFA, 0xDA, 0xF8, 0x0C, 0x20, ++0xA3, 0x78, 0x60, 0x78, 0xDA, 0xF8, 0x04, 0x10, 0xDA, 0xF8, 0x08, 0xC0, 0x06, 0x92, 0x14, 0xF8, 0x03, 0x2B, 0x05, 0x93, ++0x5A, 0xF8, 0x10, 0x3B, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x21, 0xCD, 0xE9, 0x03, 0x0C, 0x32, 0x46, 0x36, 0x49, 0x80, 0x23, ++0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xAC, 0xFA, 0x4F, 0x45, 0x06, 0xF1, 0x01, 0x06, 0xC7, 0xD1, 0x13, 0x9B, 0x32, 0x4E, ++0x1D, 0x1F, 0x00, 0x24, 0x55, 0xF8, 0x04, 0x3F, 0xC3, 0xF3, 0x07, 0x22, 0x00, 0x92, 0xDB, 0xB2, 0x22, 0x46, 0x31, 0x46, ++0x01, 0x34, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x97, 0xFA, 0x10, 0x2C, 0xF0, 0xD1, 0x14, 0x9B, 0xDB, 0x06, 0x0D, 0xD5, ++0x15, 0x9B, 0x3B, 0xB1, 0x27, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x61, 0x43, 0xF4, 0xC0, 0x53, 0x11, 0x60, 0x13, 0x60, ++0x0A, 0x99, 0x13, 0x98, 0xFF, 0xF7, 0x0C, 0xFC, 0x22, 0x49, 0x23, 0x4A, 0x0B, 0x68, 0x23, 0x4E, 0x23, 0x4C, 0x24, 0x48, ++0x23, 0xF0, 0x02, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xEE, 0x43, 0x23, 0xF0, 0x09, 0x03, 0x43, 0xF4, 0x58, 0x53, ++0xA1, 0xF5, 0xD6, 0x41, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x74, 0x39, 0x02, 0xF5, 0xFF, 0x52, 0x1C, 0x32, 0x00, 0x23, ++0x4F, 0xF0, 0x80, 0x35, 0x33, 0x60, 0x25, 0x60, 0x03, 0x60, 0x0B, 0x60, 0x13, 0x68, 0x17, 0x49, 0x23, 0xF4, 0x7F, 0x43, ++0x00, 0xF5, 0x09, 0x40, 0x23, 0xF0, 0x80, 0x03, 0xFC, 0x30, 0x43, 0xF4, 0x80, 0x34, 0x13, 0x60, 0x14, 0x60, 0x03, 0x68, ++0x23, 0xF4, 0xC0, 0x53, 0x03, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x4F, 0xFA, 0x0D, 0xF2, 0xE4, 0x7D, 0xBD, 0xEC, ++0x04, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x23, 0x08, 0xEE, 0x90, 0x3A, 0x65, 0xE5, 0x00, 0xBF, 0xF0, 0x7A, 0x15, 0x00, ++0x1C, 0x7B, 0x15, 0x00, 0x04, 0x40, 0x34, 0x40, 0x80, 0x21, 0x34, 0x40, 0x5C, 0x20, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, ++0x4C, 0x40, 0x34, 0x40, 0x08, 0xB6, 0x33, 0x40, 0x3C, 0x7B, 0x15, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC4, 0x7A, 0x15, 0x00, ++0xF0, 0xB5, 0x07, 0x78, 0x43, 0x68, 0x83, 0xB0, 0x0E, 0x46, 0x3A, 0x46, 0x27, 0x49, 0x01, 0x93, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x22, 0xFA, 0x01, 0x9B, 0x30, 0x1F, 0x06, 0xF1, 0x3C, 0x01, 0x4F, 0xF0, 0x80, 0x32, 0x40, 0xF8, 0x04, 0x2F, ++0x88, 0x42, 0xFB, 0xD1, 0x06, 0xF1, 0x3F, 0x00, 0x06, 0xF1, 0x4F, 0x02, 0x00, 0x24, 0x00, 0xF8, 0x01, 0x4F, 0x82, 0x42, ++0xFB, 0xD1, 0x30, 0x46, 0x34, 0x65, 0x06, 0xF1, 0x94, 0x05, 0x40, 0xF8, 0x54, 0x4F, 0x00, 0x24, 0x40, 0xF8, 0x04, 0x4F, ++0xA8, 0x42, 0xFB, 0xD1, 0xBA, 0x09, 0x18, 0xD0, 0x15, 0x4C, 0xDF, 0xF8, 0x74, 0xC0, 0x21, 0x68, 0x14, 0x4D, 0x15, 0x4A, ++0x15, 0x48, 0x21, 0xF4, 0x00, 0x11, 0x21, 0x60, 0xF9, 0x09, 0x00, 0x29, 0x08, 0xBF, 0x62, 0x46, 0x2A, 0x60, 0x05, 0x68, ++0x11, 0x49, 0x12, 0x4C, 0x12, 0x4A, 0x01, 0xEA, 0x05, 0x01, 0x08, 0xBF, 0x22, 0x46, 0x0A, 0x43, 0x02, 0x60, 0x01, 0x93, ++0xFE, 0xF7, 0x08, 0xFC, 0x0E, 0x4A, 0x01, 0x9B, 0xD2, 0xF8, 0xBC, 0x44, 0x38, 0x46, 0x06, 0xF1, 0x40, 0x02, 0x31, 0x46, ++0xA0, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFE, 0xF7, 0x44, 0xBC, 0x50, 0x7B, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, ++0x10, 0x20, 0x34, 0x40, 0x76, 0x62, 0xF7, 0x0B, 0x1C, 0x20, 0x34, 0x40, 0xFF, 0x0F, 0x00, 0xE0, 0x00, 0x50, 0x98, 0x00, ++0x00, 0x90, 0x9B, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x76, 0x62, 0xB7, 0x0B, 0x17, 0x4B, 0x01, 0x22, 0x30, 0xB4, 0x1A, 0x60, ++0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0x08, 0xDB, ++0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x00, 0x2B, 0xF6, 0xDA, 0x0E, 0x4A, ++0x0C, 0x4B, 0x15, 0x68, 0x1C, 0x68, 0xC5, 0xF3, 0x10, 0x02, 0xED, 0x03, 0x44, 0xBF, 0x6F, 0xEA, 0x02, 0x42, 0x6F, 0xEA, ++0x12, 0x42, 0xC4, 0xF3, 0x10, 0x03, 0x02, 0x60, 0xE2, 0x03, 0x44, 0xBF, 0x6F, 0xEA, 0x03, 0x43, 0x6F, 0xEA, 0x13, 0x43, ++0x30, 0xBC, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x6C, 0x08, 0x62, 0x40, 0x90, 0x08, 0x62, 0x40, 0x8C, 0x08, 0x62, 0x40, ++0x30, 0xB4, 0x11, 0x4C, 0x11, 0x4D, 0x12, 0x4B, 0x04, 0xEA, 0x02, 0x42, 0xC1, 0xF3, 0x0E, 0x01, 0x0A, 0x43, 0x2A, 0x60, ++0x1A, 0x68, 0x00, 0xF0, 0x07, 0x00, 0x22, 0xF0, 0xE0, 0x62, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x00, 0x42, ++0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x1A, 0x68, ++0x22, 0xF0, 0x00, 0x42, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0xFF, 0x7F, 0x44, 0x05, 0x62, 0x40, ++0x28, 0x05, 0x62, 0x40, 0x38, 0xB5, 0x28, 0x4C, 0x28, 0x4A, 0x23, 0x68, 0x28, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x43, ++0x43, 0xF0, 0x80, 0x03, 0x23, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x03, 0x02, ++0x42, 0xF0, 0x02, 0x03, 0x0B, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x1D, 0x4B, ++0x42, 0xF0, 0x03, 0x02, 0x1A, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x19, 0x4A, ++0x13, 0x68, 0x98, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, ++0x98, 0x07, 0xF6, 0xD5, 0x13, 0x4C, 0x22, 0x68, 0x51, 0x00, 0x0E, 0xD4, 0x12, 0x4D, 0x29, 0x46, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0x28, 0xF9, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x22, 0x68, 0x53, 0x00, ++0xF1, 0xD5, 0x0C, 0x4A, 0x0C, 0x49, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x03, 0x13, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0xBD, 0xE8, ++0x38, 0x40, 0x20, 0xF0, 0x13, 0xB9, 0x00, 0xBF, 0x08, 0x01, 0x60, 0x40, 0x08, 0x05, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, ++0x80, 0x40, 0x34, 0x40, 0x04, 0x22, 0x34, 0x40, 0x68, 0x7B, 0x15, 0x00, 0x04, 0x00, 0x62, 0x40, 0x7C, 0x7B, 0x15, 0x00, ++0x10, 0xB5, 0x0F, 0x4C, 0x0F, 0x4A, 0x23, 0x68, 0x0F, 0x48, 0x10, 0x49, 0x23, 0xF4, 0x80, 0x03, 0x23, 0x60, 0x13, 0x68, ++0x23, 0xF0, 0x03, 0x03, 0x13, 0x60, 0x13, 0x60, 0x03, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, ++0x01, 0x03, 0x0B, 0x60, 0x14, 0x20, 0xFC, 0xF7, 0x45, 0xF8, 0xBD, 0xE8, 0x10, 0x40, 0x06, 0x49, 0x4F, 0xF4, 0x00, 0x50, ++0x20, 0xF0, 0xE2, 0xB8, 0x04, 0x00, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, 0x08, 0x01, 0x60, 0x40, 0x08, 0x05, 0x62, 0x40, ++0x88, 0x7B, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0x07, 0x46, 0x10, 0x1A, 0x0E, 0x46, 0x9B, 0x46, 0xDD, 0xE9, ++0x0E, 0x54, 0x9D, 0xF8, 0x30, 0x90, 0x9D, 0xF8, 0x34, 0x80, 0x32, 0xF0, 0x65, 0xFD, 0x82, 0x46, 0xAB, 0xEB, 0x06, 0x00, ++0x32, 0xF0, 0x60, 0xFD, 0xBA, 0xF1, 0x00, 0x0F, 0x11, 0xD0, 0x07, 0xFA, 0x09, 0xF7, 0x07, 0xEE, 0x90, 0x7A, 0xB8, 0xEE, ++0xE7, 0x7A, 0x07, 0xEE, 0x90, 0xAA, 0xF8, 0xEE, 0xE7, 0x7A, 0xC7, 0xEE, 0x27, 0x6A, 0xFD, 0xEE, 0xE6, 0x7A, 0xCD, 0xED, ++0x01, 0x7A, 0x9D, 0xF9, 0x04, 0xA0, 0x85, 0xF8, 0x00, 0xA0, 0xA8, 0xB1, 0x06, 0xFA, 0x08, 0xF6, 0x07, 0xEE, 0x90, 0x6A, ++0xB8, 0xEE, 0xE7, 0x7A, 0x07, 0xEE, 0x90, 0x0A, 0xF8, 0xEE, 0xE7, 0x7A, 0xC7, 0xEE, 0x27, 0x6A, 0xFD, 0xEE, 0xE6, 0x7A, ++0xCD, 0xED, 0x01, 0x7A, 0x9D, 0xF9, 0x04, 0x30, 0x23, 0x70, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x03, 0x46, 0x23, 0x70, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0xA1, 0x4F, 0xA2, 0x4C, 0x3D, 0x68, 0xA2, 0x4E, ++0xAD, 0xB2, 0x25, 0x43, 0x2D, 0xED, 0x02, 0x8B, 0x3D, 0x60, 0x35, 0x68, 0x91, 0xB0, 0x25, 0xF0, 0x01, 0x05, 0x86, 0x46, ++0x35, 0x60, 0x8C, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x9B, 0x49, 0xCD, 0xF8, 0x1C, 0xE0, 0xCD, 0xE9, 0x08, 0x23, 0x08, 0xEE, ++0x10, 0xCA, 0x75, 0x46, 0x20, 0xF0, 0x72, 0xF8, 0x3B, 0x68, 0x9B, 0xB2, 0x23, 0x43, 0x3B, 0x60, 0x00, 0x2D, 0x00, 0xF0, ++0x16, 0x81, 0x00, 0x26, 0x34, 0x46, 0x35, 0x46, 0x0D, 0xF1, 0x34, 0x0B, 0x0D, 0xF1, 0x30, 0x0A, 0x32, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x96, 0xFE, 0xDD, 0xE9, 0x0C, 0x32, ++0x8A, 0x49, 0xCD, 0xE9, 0x00, 0x32, 0x4F, 0xF4, 0x00, 0x50, 0x23, 0x46, 0x2A, 0x46, 0x20, 0xF0, 0x4F, 0xF8, 0x0C, 0x9B, ++0x00, 0x2B, 0xC0, 0xF2, 0xA5, 0x80, 0x00, 0x2E, 0x00, 0xF0, 0xB9, 0x80, 0x01, 0x2E, 0x00, 0xF0, 0xDD, 0x80, 0x0D, 0x9B, ++0x15, 0xF1, 0x7C, 0x0F, 0xAC, 0xBF, 0x2A, 0x1F, 0x2A, 0x1D, 0x00, 0x2B, 0x80, 0xF2, 0xA1, 0x80, 0x01, 0x2E, 0x4F, 0xF0, ++0x02, 0x08, 0x00, 0xF0, 0xDA, 0x80, 0x7B, 0x2C, 0x00, 0xF3, 0xA1, 0x80, 0x23, 0x1D, 0x4F, 0xF0, 0x02, 0x09, 0xA3, 0xF1, ++0x80, 0x01, 0x38, 0x68, 0xC9, 0xB2, 0x09, 0x04, 0xA2, 0xF1, 0x80, 0x0C, 0x41, 0xEA, 0x0C, 0x61, 0x80, 0xB2, 0x01, 0x43, ++0x39, 0x60, 0x32, 0x21, 0x00, 0xBF, 0x01, 0x39, 0x89, 0xB2, 0x00, 0x29, 0xFA, 0xD1, 0x0F, 0xA9, 0x0E, 0xA8, 0xCD, 0xE9, ++0x05, 0x23, 0xFF, 0xF7, 0x55, 0xFE, 0xDD, 0xE9, 0x0E, 0x10, 0xDD, 0xE9, 0x05, 0x23, 0x01, 0x90, 0x00, 0x91, 0x4F, 0xF4, ++0x00, 0x50, 0x68, 0x49, 0x20, 0xF0, 0x0E, 0xF8, 0x0D, 0xF1, 0x2F, 0x03, 0x03, 0x93, 0x0D, 0xF1, 0x2E, 0x03, 0xCD, 0xE9, ++0x01, 0x93, 0xDD, 0xE9, 0x0C, 0x01, 0xDD, 0xE9, 0x0E, 0x23, 0xCD, 0xF8, 0x00, 0x80, 0xFF, 0xF7, 0x27, 0xFF, 0x9D, 0xF9, ++0x2F, 0x30, 0x9D, 0xF9, 0x2E, 0x20, 0x5E, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, 0xF6, 0xFF, 0x9D, 0xF9, 0x2F, 0x30, ++0x9D, 0xF9, 0x2E, 0x20, 0x39, 0x68, 0xE4, 0x1A, 0x6F, 0xF0, 0x7F, 0x03, 0x9C, 0x42, 0xB8, 0xBF, 0x1C, 0x46, 0xAD, 0x1A, ++0x7F, 0x2C, 0xA8, 0xBF, 0x7F, 0x24, 0x9D, 0x42, 0xB8, 0xBF, 0x1D, 0x46, 0x04, 0xEB, 0x03, 0x08, 0x7F, 0x2D, 0xA8, 0xBF, ++0x7F, 0x25, 0x5F, 0xFA, 0x88, 0xF8, 0xA5, 0xF1, 0x80, 0x02, 0x4F, 0xEA, 0x08, 0x43, 0x43, 0xEA, 0x02, 0x63, 0x89, 0xB2, ++0x0B, 0x43, 0x01, 0x36, 0x3B, 0x60, 0x07, 0x9B, 0xF6, 0xB2, 0xB3, 0x42, 0x5F, 0xFA, 0x82, 0xF9, 0x7F, 0xF4, 0x68, 0xAF, ++0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0xFE, 0xFD, ++0xDD, 0xE9, 0x0C, 0x13, 0x2A, 0x46, 0x01, 0x93, 0x00, 0x91, 0x23, 0x46, 0x3F, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, ++0xB7, 0xFF, 0x08, 0x9B, 0x83, 0xF8, 0x00, 0x90, 0x09, 0x9B, 0xDD, 0xE9, 0x0C, 0x12, 0x18, 0xEE, 0x10, 0x0A, 0x83, 0xF8, ++0x00, 0x80, 0xFF, 0xF7, 0x1D, 0xFE, 0x11, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0xB3, 0x01, 0x2E, ++0x29, 0xD0, 0x0D, 0x9B, 0x7B, 0x2D, 0xD4, 0xBF, 0x2A, 0x1D, 0x2A, 0x1F, 0x00, 0x2B, 0xFF, 0xF6, 0x5F, 0xAF, 0x01, 0x2E, ++0x4F, 0xF0, 0x02, 0x08, 0x26, 0xD0, 0x14, 0xF1, 0x7C, 0x0F, 0xFF, 0xF6, 0x5F, 0xAF, 0x23, 0x1F, 0x4F, 0xF0, 0x02, 0x09, ++0x5D, 0xE7, 0x0D, 0x9B, 0x00, 0x2B, 0xA5, 0xF1, 0x20, 0x02, 0x0A, 0xDA, 0x4F, 0xF0, 0x05, 0x08, 0xC1, 0x46, 0x04, 0xF1, ++0x20, 0x03, 0x52, 0xE7, 0x0D, 0x9B, 0x00, 0x2B, 0x05, 0xF1, 0x20, 0x02, 0xF4, 0xDB, 0x4F, 0xF0, 0x05, 0x08, 0xC1, 0x46, ++0xA4, 0xF1, 0x20, 0x03, 0x47, 0xE7, 0x6F, 0x2D, 0xD3, 0xDC, 0x0D, 0x9B, 0x00, 0x2B, 0x05, 0xF1, 0x10, 0x02, 0x4F, 0xF0, ++0x04, 0x08, 0x12, 0xDB, 0x14, 0xF1, 0x70, 0x0F, 0xD5, 0xDB, 0xA4, 0xF1, 0x10, 0x03, 0x4F, 0xF0, 0x04, 0x09, 0x36, 0xE7, ++0x15, 0xF1, 0x70, 0x0F, 0xFF, 0xF6, 0x1F, 0xAF, 0x0D, 0x9B, 0x00, 0x2B, 0xA5, 0xF1, 0x10, 0x02, 0x4F, 0xF0, 0x04, 0x08, ++0xEC, 0xDA, 0x6F, 0x2C, 0x3F, 0xF7, 0x23, 0xAF, 0x04, 0xF1, 0x10, 0x03, 0x4F, 0xF0, 0x04, 0x09, 0x23, 0xE7, 0x07, 0x9C, ++0x4F, 0xF0, 0x80, 0x08, 0x25, 0x46, 0xC1, 0x46, 0x0D, 0xF1, 0x34, 0x0B, 0x0D, 0xF1, 0x30, 0x0A, 0x7E, 0xE7, 0x00, 0xBF, ++0x4C, 0x40, 0x34, 0x40, 0x00, 0x00, 0x80, 0x80, 0x1C, 0x40, 0x34, 0x40, 0x94, 0x7B, 0x15, 0x00, 0xA8, 0x7B, 0x15, 0x00, ++0xCC, 0x7B, 0x15, 0x00, 0xF0, 0x7B, 0x15, 0x00, 0x0C, 0x7C, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x22, 0x4B, 0x23, 0x4E, ++0x1A, 0x68, 0x00, 0x25, 0x22, 0xF4, 0x7F, 0x52, 0x1A, 0x60, 0x98, 0x46, 0x2F, 0x46, 0x4F, 0xF0, 0x07, 0x09, 0x02, 0x20, ++0xFB, 0xF7, 0x86, 0xFE, 0x33, 0x68, 0xD8, 0xF8, 0x00, 0x40, 0xDA, 0x05, 0x54, 0xBF, 0x01, 0x37, 0x07, 0xF1, 0xFF, 0x37, ++0x7F, 0xB2, 0x1B, 0x06, 0x54, 0xBF, 0x01, 0x35, 0x05, 0xF1, 0xFF, 0x35, 0x00, 0x2F, 0x24, 0xF4, 0x7F, 0x54, 0xDC, 0xBF, ++0x7B, 0x42, 0x44, 0xEA, 0x83, 0x24, 0x6D, 0xB2, 0xD4, 0xBF, 0x44, 0xF4, 0x00, 0x54, 0x44, 0xEA, 0x87, 0x24, 0x00, 0x2D, ++0xDC, 0xBF, 0x6B, 0x42, 0x44, 0xEA, 0x83, 0x14, 0x09, 0xF1, 0xFF, 0x33, 0xCC, 0xBF, 0x44, 0xEA, 0x85, 0x14, 0x44, 0xF4, ++0x00, 0x74, 0x13, 0xF0, 0xFF, 0x09, 0xC8, 0xF8, 0x00, 0x40, 0xD0, 0xD1, 0x07, 0x49, 0x2B, 0x46, 0x3A, 0x46, 0x4F, 0xF4, ++0x00, 0x50, 0x1F, 0xF0, 0xF7, 0xFE, 0xC4, 0xF3, 0x87, 0x10, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x50, 0x40, 0x34, 0x40, ++0x14, 0x40, 0x34, 0x40, 0x34, 0x7C, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x4E, 0x4A, 0x4F, 0x4D, 0x13, 0x68, 0x87, 0xB0, ++0xC1, 0xF3, 0x03, 0x24, 0x03, 0x93, 0x23, 0xF0, 0x00, 0x43, 0x23, 0xF4, 0xE0, 0x03, 0x43, 0xEA, 0x04, 0x53, 0x43, 0xF0, ++0x0A, 0x03, 0x13, 0x60, 0x2C, 0x68, 0x48, 0x4B, 0x24, 0xF4, 0xC0, 0x54, 0xC1, 0xF3, 0x01, 0x62, 0x22, 0x43, 0x2A, 0x60, ++0x1A, 0x68, 0x01, 0xF0, 0x0F, 0x04, 0xC1, 0xF3, 0x03, 0x15, 0x42, 0xF0, 0x3F, 0x02, 0xA5, 0x42, 0x02, 0x94, 0xC1, 0xF3, ++0x03, 0x3A, 0x1A, 0x60, 0x5E, 0xD8, 0xDF, 0xF8, 0x04, 0x81, 0x3E, 0x4E, 0xDF, 0xF8, 0x00, 0xB1, 0x44, 0x19, 0x99, 0x46, ++0xEF, 0xB2, 0xD8, 0xF8, 0x00, 0x20, 0x22, 0xF4, 0xFF, 0x42, 0x42, 0xEA, 0x45, 0x22, 0x42, 0xF4, 0x40, 0x40, 0x42, 0xF4, ++0xE0, 0x31, 0xC8, 0xF8, 0x00, 0x00, 0x2A, 0x46, 0xC8, 0xF8, 0x00, 0x10, 0x4F, 0xF4, 0x00, 0x50, 0x33, 0x49, 0x1F, 0xF0, ++0xA9, 0xFE, 0x32, 0x68, 0x42, 0xF4, 0x80, 0x62, 0x32, 0x60, 0xDB, 0xF8, 0x00, 0x20, 0x42, 0xF0, 0x40, 0x02, 0xCB, 0xF8, ++0x00, 0x20, 0x32, 0x22, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0xFF, 0xF7, 0x5D, 0xFF, 0x04, 0xF8, ++0x01, 0x0B, 0x32, 0x68, 0x22, 0xF4, 0x80, 0x62, 0x32, 0x60, 0xD9, 0xF8, 0x00, 0x20, 0x22, 0xF0, 0x40, 0x02, 0xC9, 0xF8, ++0x00, 0x20, 0x32, 0x22, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0x0D, 0xF1, 0x17, 0x03, 0x01, 0x93, ++0x0D, 0xF1, 0x16, 0x03, 0x39, 0x46, 0x00, 0x93, 0x05, 0xAA, 0x0D, 0xF1, 0x15, 0x03, 0x50, 0x46, 0xFF, 0xF7, 0xE8, 0xFD, ++0x01, 0x35, 0x02, 0x9B, 0x9D, 0xF8, 0x16, 0xC0, 0x9D, 0xF8, 0x17, 0x00, 0x9D, 0xF8, 0x14, 0x10, 0x9D, 0xF8, 0x15, 0x20, ++0x84, 0xF8, 0x04, 0xC0, 0xEF, 0xB2, 0xBB, 0x42, 0x60, 0x72, 0xA1, 0x73, 0xE2, 0x74, 0xA8, 0xD2, 0x11, 0x4A, 0x0D, 0x48, ++0x13, 0x68, 0x0D, 0x49, 0x0A, 0x4C, 0x23, 0xF4, 0x7F, 0x43, 0x23, 0xF0, 0x80, 0x03, 0x13, 0x60, 0x43, 0xF4, 0x80, 0x33, ++0x13, 0x60, 0x03, 0x68, 0x23, 0xF4, 0xC0, 0x53, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x3F, 0x03, 0x0B, 0x60, 0x03, 0x9B, ++0x23, 0x60, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1C, 0x05, 0x62, 0x40, 0x04, 0x40, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, ++0x14, 0x40, 0x34, 0x40, 0x54, 0x7C, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, 0x5C, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, ++0x3C, 0x4D, 0x3D, 0x49, 0x81, 0x46, 0x89, 0xB0, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, 0x34, 0xFE, 0x2B, 0x68, 0xD9, 0xF8, ++0x00, 0x40, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE2, 0xB2, 0x04, 0xF0, 0x7F, 0x0A, 0xC4, 0xF3, 0x03, 0x18, 0x04, 0xF0, ++0x0F, 0x04, 0x4A, 0xDB, 0x33, 0x4D, 0x34, 0x4F, 0x2E, 0x68, 0x2B, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x2B, 0x60, 0xD7, 0xF8, ++0x00, 0xB0, 0x3B, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x3B, 0x60, 0x50, 0x46, 0xFF, 0xF7, 0xB2, 0xFC, 0xD9, 0xF8, 0x00, 0x10, ++0x01, 0xA8, 0xFF, 0xF7, 0x25, 0xFF, 0xFF, 0xF7, 0x0D, 0xFD, 0xC7, 0xF8, 0x00, 0xB0, 0x2B, 0x68, 0x2B, 0x68, 0x06, 0xF4, ++0x80, 0x76, 0x1E, 0x43, 0xA0, 0x45, 0x2E, 0x60, 0x26, 0xD8, 0x25, 0x48, 0x0D, 0xF1, 0x05, 0x03, 0xA4, 0xEB, 0x08, 0x04, ++0x43, 0x44, 0x01, 0xAA, 0x42, 0x44, 0x53, 0xFA, 0x84, 0xF4, 0x00, 0xEB, 0x08, 0x10, 0x15, 0x78, 0x53, 0x79, 0x92, 0xF8, ++0x0A, 0xC0, 0xD7, 0x7B, 0x16, 0x7D, 0x29, 0x06, 0x1B, 0x04, 0x01, 0xF0, 0x70, 0x41, 0x43, 0xEA, 0x0C, 0x63, 0x41, 0xEA, ++0x05, 0x51, 0x3B, 0x43, 0x01, 0x32, 0x09, 0x0E, 0x43, 0xEA, 0x06, 0x23, 0xA2, 0x42, 0x80, 0xF8, 0x07, 0x12, 0xC0, 0xF8, ++0x00, 0x32, 0x00, 0xF1, 0x10, 0x00, 0xE4, 0xD1, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0xF0, 0x0C, 0x0F, 0x08, 0xD1, ++0xA0, 0x45, 0xAF, 0xD9, 0x0E, 0x49, 0x0F, 0x48, 0x41, 0xF2, 0x7F, 0x02, 0x1F, 0xF0, 0xFA, 0xFF, 0xA8, 0xE7, 0x0B, 0x49, ++0x0C, 0x48, 0x41, 0xF2, 0x7E, 0x02, 0x1F, 0xF0, 0xF3, 0xFF, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEB, 0xDB, ++0x9C, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x7C, 0x15, 0x00, 0x00, 0x04, 0x60, 0x40, 0x18, 0x00, 0x58, 0x40, ++0x1C, 0x13, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x88, 0x7C, 0x15, 0x00, 0x78, 0x7C, 0x15, 0x00, 0x24, 0x4B, 0x25, 0x4A, ++0x06, 0x21, 0x10, 0xB4, 0xC3, 0xF8, 0x00, 0x11, 0x53, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x53, 0x60, 0x53, 0x68, 0x43, 0xF4, ++0x00, 0x33, 0x53, 0x60, 0x13, 0x6B, 0x03, 0xF0, 0x44, 0x03, 0x04, 0x2B, 0xFA, 0xD1, 0x1D, 0x4B, 0x1D, 0x4C, 0x1B, 0x68, ++0x1D, 0x48, 0x19, 0x49, 0xA4, 0xFB, 0x03, 0x43, 0x9B, 0x0C, 0x43, 0xF0, 0x00, 0x44, 0x44, 0xF4, 0xA0, 0x14, 0x43, 0xF4, ++0xA0, 0x13, 0x03, 0x60, 0x04, 0x60, 0x03, 0x60, 0x53, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x43, 0xF4, 0xC4, 0x33, 0x43, 0xF0, ++0x02, 0x03, 0x4F, 0xF4, 0x80, 0x50, 0x53, 0x60, 0xC1, 0xF8, 0x34, 0x01, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, ++0x4B, 0x6F, 0x43, 0xF0, 0x01, 0x03, 0x4B, 0x67, 0x53, 0x6C, 0x43, 0xF0, 0x08, 0x43, 0x53, 0x64, 0x53, 0x6D, 0x23, 0xF4, ++0x00, 0x13, 0x53, 0x65, 0x53, 0x6D, 0x43, 0xF0, 0x02, 0x03, 0x53, 0x65, 0x53, 0x6D, 0x23, 0xF4, 0x00, 0x63, 0x53, 0x65, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, 0x18, 0x13, 0x17, 0x00, 0x83, 0xDE, 0x1B, 0x43, ++0x08, 0x00, 0x58, 0x40, 0x3B, 0x4A, 0x3C, 0x48, 0x13, 0x68, 0x3C, 0x49, 0xDF, 0xF8, 0x24, 0xC1, 0x43, 0xF0, 0x7C, 0x53, ++0xF0, 0xB4, 0x13, 0x60, 0x39, 0x4C, 0x3A, 0x4B, 0x23, 0x60, 0x03, 0xF1, 0xBE, 0x43, 0xA3, 0xF5, 0x69, 0x03, 0xA3, 0xF6, ++0x77, 0x33, 0x03, 0x60, 0x36, 0x4B, 0x0B, 0x60, 0x36, 0x4F, 0x37, 0x4E, 0x37, 0x4D, 0x40, 0xF6, 0x77, 0x13, 0xCC, 0xF8, ++0x00, 0x30, 0x36, 0x4B, 0x3B, 0x60, 0x04, 0xF5, 0x00, 0x24, 0x01, 0xF5, 0x2F, 0x11, 0x00, 0xF5, 0x2F, 0x10, 0x49, 0xF2, ++0x02, 0x43, 0x02, 0xF5, 0x00, 0x22, 0x33, 0x60, 0x0C, 0x34, 0x30, 0x4B, 0x2B, 0x60, 0x01, 0xF5, 0x05, 0x61, 0x00, 0xF6, ++0x58, 0x00, 0x02, 0xF6, 0x7C, 0x02, 0x07, 0xF5, 0x2F, 0x17, 0x2C, 0x4D, 0x25, 0x60, 0x07, 0xF6, 0x68, 0x07, 0x0B, 0x60, ++0x06, 0xF5, 0x37, 0x16, 0x03, 0x60, 0x13, 0x60, 0x40, 0xF6, 0x34, 0x03, 0x3B, 0x60, 0x06, 0xF2, 0xE4, 0x46, 0x26, 0x4B, ++0x33, 0x60, 0x01, 0xF5, 0xFE, 0x31, 0x03, 0xF1, 0x50, 0x53, 0x88, 0x31, 0x03, 0xF5, 0x54, 0x13, 0x0F, 0x33, 0x0B, 0x60, ++0x00, 0xF5, 0xFE, 0x30, 0x03, 0xF1, 0x48, 0x43, 0x1F, 0x4D, 0x00, 0xF5, 0x90, 0x70, 0x02, 0xF5, 0xFE, 0x32, 0xA3, 0xF5, ++0x78, 0x13, 0x02, 0xF5, 0xB4, 0x72, 0xA3, 0xF2, 0x1F, 0x63, 0x4F, 0xF0, 0x36, 0x36, 0x2B, 0x60, 0x06, 0x60, 0x4F, 0xF4, ++0x7F, 0x40, 0x10, 0x60, 0x04, 0xF5, 0x01, 0x34, 0x02, 0xF1, 0xAC, 0x42, 0x20, 0x34, 0x15, 0x4B, 0x15, 0x4D, 0x25, 0x60, ++0xA2, 0xF5, 0xB5, 0x12, 0x45, 0xF2, 0x55, 0x30, 0xA2, 0xF6, 0x8A, 0x62, 0xC1, 0xF8, 0xA8, 0x00, 0xF0, 0xBC, 0x1A, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x0C, 0x00, 0x58, 0x40, 0x2C, 0x40, 0x34, 0x40, 0x30, 0x40, 0x34, 0x40, 0x04, 0x01, 0x58, 0x40, ++0xFB, 0x23, 0x09, 0x00, 0x08, 0x51, 0x2E, 0x1A, 0x24, 0x40, 0x34, 0x40, 0x28, 0x40, 0x34, 0x40, 0x8C, 0x04, 0x60, 0x40, ++0x94, 0xC5, 0x2E, 0x00, 0x34, 0x08, 0x50, 0x00, 0x58, 0x00, 0x7E, 0x02, 0x13, 0x20, 0x20, 0x20, 0xA0, 0x05, 0x62, 0x40, ++0x1C, 0x05, 0x62, 0x40, 0x0F, 0x12, 0x15, 0x0C, 0x20, 0x40, 0x34, 0x40, 0x63, 0x49, 0x64, 0x4A, 0x0B, 0x68, 0x23, 0xF4, ++0x00, 0x63, 0xF0, 0xB4, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, ++0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0xDF, 0xF8, 0x6C, 0xC1, 0x5B, 0x4A, 0xDC, 0xF8, 0x00, 0x30, 0x5A, 0x4F, 0x5B, 0x4E, ++0x23, 0xF4, 0x80, 0x53, 0xCC, 0xF8, 0x00, 0x30, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, 0xDC, 0xF8, 0x00, 0x30, ++0x43, 0xF4, 0x80, 0x63, 0xCC, 0xF8, 0x00, 0x30, 0xDC, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x00, 0x63, 0xCC, 0xF8, 0x00, 0x30, ++0x62, 0x46, 0xFF, 0x25, 0x2B, 0x1D, 0x2C, 0x46, 0xDD, 0xB2, 0x29, 0x46, 0x38, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, ++0x0B, 0x43, 0x13, 0x60, 0x50, 0xF8, 0x04, 0x3B, 0x33, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, ++0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, 0xFC, 0xD5, 0x01, 0x39, 0xC9, 0xB2, 0xA1, 0x42, 0xE8, 0xD1, ++0x8F, 0x2D, 0x07, 0xF1, 0x10, 0x07, 0xDF, 0xD1, 0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x80, 0x63, 0xCC, 0xF8, 0x00, 0x30, ++0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x36, 0x4D, 0x37, 0x49, 0x2A, 0x68, 0x39, 0x48, ++0x39, 0x4C, 0x22, 0xF4, 0x00, 0x62, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, ++0x80, 0x72, 0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x50, 0xF8, 0x04, 0x2F, 0x22, 0x60, ++0x0A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, ++0xFC, 0xD5, 0x01, 0x33, 0x20, 0x2B, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, ++0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x1F, 0x4C, 0x24, 0x48, 0x22, 0x68, 0x24, 0x49, 0x24, 0x4D, 0x22, 0xF4, ++0x80, 0x72, 0x22, 0x60, 0x02, 0x68, 0x22, 0xF0, 0x02, 0x02, 0x02, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x62, 0x0A, 0x60, ++0x32, 0x22, 0x2B, 0x60, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0x13, 0x49, 0x13, 0x4A, 0x08, 0x68, ++0x1A, 0x4D, 0x1B, 0x4C, 0x1B, 0x4B, 0x40, 0xF4, 0x80, 0x50, 0x08, 0x60, 0x08, 0x68, 0x40, 0xF4, 0x00, 0x60, 0x08, 0x60, ++0x11, 0x68, 0x41, 0xF4, 0x00, 0x71, 0x11, 0x60, 0x11, 0x68, 0x41, 0xF4, 0x80, 0x71, 0x11, 0x60, 0x2A, 0x68, 0x42, 0xF4, ++0x80, 0x52, 0x2A, 0x60, 0x22, 0x68, 0x22, 0xF4, 0x80, 0x22, 0x22, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x00, 0x52, 0x1A, 0x60, ++0x1A, 0x68, 0x42, 0xF0, 0x80, 0x42, 0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x60, 0x40, 0x34, 0x40, 0x6C, 0x40, 0x34, 0x40, ++0x1C, 0x13, 0x17, 0x00, 0x64, 0x40, 0x34, 0x40, 0x18, 0x18, 0x17, 0x00, 0x70, 0x40, 0x34, 0x40, 0x18, 0x00, 0x58, 0x40, ++0x58, 0x40, 0x34, 0x40, 0x08, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, 0x1C, 0x20, 0x34, 0x40, ++0x10, 0xB5, 0x09, 0x4C, 0x82, 0xB0, 0xD4, 0xF8, 0xC0, 0x34, 0x01, 0x90, 0x98, 0x47, 0xD4, 0xF8, 0xC4, 0x34, 0x98, 0x47, ++0xD4, 0xF8, 0xC8, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0xCC, 0x34, 0x00, 0x21, 0x01, 0xA8, 0x98, 0x47, 0x02, 0xB0, 0x10, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x2D, 0x4C, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x17, 0xD0, 0x0F, 0x24, 0x4F, 0xF4, ++0x00, 0x62, 0x11, 0x46, 0x29, 0x48, 0xFD, 0xF7, 0x61, 0xFA, 0x4F, 0xF4, 0x40, 0x72, 0x28, 0x48, 0x00, 0x21, 0xFD, 0xF7, ++0x5B, 0xFA, 0x21, 0x46, 0x26, 0x48, 0xFD, 0xF7, 0x2F, 0xFA, 0x02, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x24, 0x48, 0x11, 0x46, ++0xFD, 0xF7, 0x50, 0xBA, 0x04, 0xF0, 0x2E, 0xFD, 0x22, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0xC3, 0xF8, 0x80, 0x20, 0xBF, 0xF3, ++0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0x1F, 0x48, 0x1F, 0xF0, 0x52, 0xFB, 0x1E, 0x4A, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF0, ++0x02, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x13, 0x69, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x61, 0x13, 0x69, 0xDB, 0x07, 0xFC, 0xD4, ++0x18, 0x48, 0x1F, 0xF0, 0x41, 0xFB, 0x18, 0x4A, 0x18, 0x48, 0x4F, 0xF4, 0x00, 0x21, 0xFD, 0xF7, 0x2B, 0xFA, 0x17, 0x4B, ++0x4F, 0xF4, 0x80, 0x61, 0x4F, 0xF4, 0x00, 0x02, 0xC3, 0xF8, 0x28, 0x11, 0xC3, 0xF8, 0x18, 0x21, 0x23, 0x68, 0x1B, 0x78, ++0x02, 0x2B, 0xB5, 0xD1, 0x04, 0xF0, 0xB6, 0xFE, 0x00, 0x28, 0xB1, 0xD0, 0x0F, 0x4B, 0x10, 0x48, 0xD3, 0xF8, 0x00, 0x41, ++0x21, 0x46, 0x1F, 0xF0, 0x23, 0xFB, 0xAA, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x0C, 0x88, 0x01, 0x50, 0x14, 0x88, 0x01, 0x50, ++0x00, 0x70, 0x01, 0x50, 0x08, 0x70, 0x01, 0x50, 0x00, 0xE1, 0x00, 0xE0, 0x9C, 0x7C, 0x15, 0x00, 0x00, 0x00, 0x20, 0x40, ++0xA8, 0x7C, 0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x90, 0x01, 0x50, 0x00, 0x00, 0x10, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0xB8, 0x7C, 0x15, 0x00, 0x38, 0xB5, 0x36, 0x4C, 0x36, 0x48, 0x44, 0x22, 0x00, 0x21, 0xFB, 0xF7, 0x91, 0xF8, 0x23, 0x68, ++0x1A, 0x07, 0xC3, 0xF3, 0xC0, 0x01, 0x51, 0xD5, 0x22, 0x46, 0x00, 0xBF, 0x13, 0x68, 0xDB, 0x06, 0xFB, 0xD5, 0x30, 0x4D, ++0x30, 0x48, 0x29, 0x68, 0x30, 0x4B, 0x00, 0x68, 0x30, 0x4A, 0xC1, 0xF8, 0x44, 0x02, 0x00, 0x21, 0x19, 0x60, 0x11, 0x60, ++0x19, 0x68, 0x2E, 0x48, 0x2E, 0x4C, 0x21, 0xF0, 0x03, 0x01, 0x41, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, ++0x0C, 0x01, 0x41, 0xF0, 0x08, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x40, 0x71, 0x41, 0xF4, 0x00, 0x71, 0x19, 0x60, ++0x19, 0x68, 0x21, 0xF4, 0x40, 0x61, 0x41, 0xF4, 0x00, 0x61, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x40, 0x51, 0x41, 0xF4, ++0x00, 0x51, 0x19, 0x60, 0x11, 0x68, 0x21, 0xF0, 0x40, 0x51, 0x41, 0xF0, 0x00, 0x51, 0x11, 0x60, 0x11, 0x68, 0x21, 0xF0, ++0x40, 0x41, 0x41, 0xF0, 0x00, 0x41, 0x11, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x32, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x40, 0x22, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x12, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x02, 0x1A, 0x60, ++0x1A, 0x68, 0x42, 0xF0, 0x40, 0x72, 0x1A, 0x60, 0x04, 0x60, 0x38, 0xBD, 0x23, 0x68, 0x09, 0x4D, 0x43, 0xF0, 0x08, 0x03, ++0x23, 0x60, 0x28, 0x68, 0x4F, 0xF4, 0x12, 0x72, 0xFB, 0xF7, 0x30, 0xF8, 0x23, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x23, 0x60, ++0xA4, 0xE7, 0x00, 0xBF, 0x80, 0x40, 0x04, 0x40, 0x04, 0x35, 0x17, 0x00, 0x00, 0x38, 0x18, 0x00, 0x84, 0x1A, 0x17, 0x00, ++0x14, 0x41, 0x04, 0x40, 0x18, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x33, 0x1F, 0x00, 0xC0, 0x0C, 0x4B, 0x10, 0xB5, ++0x1C, 0x68, 0x14, 0xF4, 0xF8, 0x54, 0x00, 0xD1, 0x10, 0xBD, 0x60, 0x08, 0x1E, 0xF0, 0x02, 0xF8, 0x08, 0x4A, 0x09, 0x49, ++0x09, 0x4B, 0x0C, 0x60, 0x14, 0x60, 0x1A, 0x78, 0x00, 0x2A, 0xF3, 0xD0, 0x07, 0x4A, 0x01, 0x21, 0x59, 0x70, 0x13, 0x68, ++0x0B, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x1C, 0x41, 0x04, 0x40, 0x08, 0x41, 0x04, 0x40, 0x10, 0x41, 0x04, 0x40, ++0x3C, 0x36, 0x17, 0x00, 0x10, 0x00, 0x58, 0x40, 0x2D, 0xE9, 0xF8, 0x4F, 0x29, 0x4B, 0x06, 0x46, 0x53, 0xF8, 0x20, 0x00, ++0x1E, 0xF0, 0x04, 0xF8, 0x27, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x26, 0x4B, 0xD3, 0xF8, 0x00, 0xA0, 0xDA, 0xF8, ++0x3C, 0x32, 0x0A, 0xF5, 0x0F, 0x7B, 0x8B, 0xB3, 0x23, 0x4D, 0xDF, 0xF8, 0x98, 0x90, 0xDF, 0xF8, 0x98, 0x80, 0x05, 0xF2, ++0x14, 0x57, 0x1D, 0xE0, 0x95, 0xF8, 0x10, 0x35, 0x85, 0xF8, 0x11, 0x45, 0x01, 0x33, 0xA9, 0xFB, 0x03, 0x24, 0xA4, 0x09, ++0x04, 0xEB, 0xC4, 0x04, 0x04, 0xEB, 0xC4, 0x04, 0x1C, 0x1B, 0x85, 0xF8, 0x10, 0x45, 0x1E, 0xF0, 0xA1, 0xF8, 0xD8, 0xF8, ++0x00, 0x20, 0x05, 0xEB, 0x04, 0x11, 0x02, 0x44, 0xC1, 0xE9, 0x01, 0x26, 0x38, 0x46, 0x1E, 0xF0, 0x53, 0xF8, 0xDA, 0xF8, ++0x3C, 0x32, 0x5B, 0xB1, 0x95, 0xF8, 0x11, 0x15, 0x95, 0xF8, 0x12, 0x25, 0x91, 0x42, 0x58, 0x46, 0x01, 0xF1, 0x01, 0x04, ++0xD8, 0xD3, 0x0D, 0x48, 0x01, 0xF0, 0x54, 0xF8, 0x08, 0x4B, 0x01, 0x24, 0x1C, 0x60, 0x20, 0x20, 0x08, 0x36, 0x1D, 0xF0, ++0x9B, 0xFF, 0x04, 0xFA, 0x06, 0xF6, 0x08, 0x4B, 0x06, 0xF4, 0xF8, 0x56, 0x1E, 0x60, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, ++0x80, 0x7E, 0x15, 0x00, 0x4C, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x58, 0x58, 0x17, 0x00, 0xCC, 0x7C, 0x15, 0x00, ++0x0C, 0x41, 0x04, 0x40, 0xE7, 0x87, 0x45, 0xCA, 0x84, 0x1A, 0x17, 0x00, 0x1D, 0x4B, 0x10, 0xB5, 0x1C, 0x68, 0xA0, 0x06, ++0x2C, 0xD4, 0xE1, 0x06, 0x20, 0xD4, 0xA2, 0x07, 0x16, 0xD4, 0x63, 0x00, 0x08, 0xD5, 0x19, 0x4B, 0x01, 0x20, 0xD3, 0xF8, ++0x78, 0x34, 0x98, 0x47, 0x17, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x00, 0x2C, 0x00, 0xDB, 0x10, 0xBD, 0x13, 0x4B, ++0xD3, 0xF8, 0x68, 0x34, 0x98, 0x47, 0x12, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x80, 0x50, ++0x1D, 0xF0, 0x5E, 0xFF, 0x0E, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0xE0, 0xE7, 0x0C, 0x49, 0x0B, 0x4A, 0x10, 0x23, 0x0B, 0x60, ++0x4F, 0xF4, 0x00, 0x10, 0x13, 0x60, 0x1D, 0xF0, 0x51, 0xFF, 0xD4, 0xE7, 0x07, 0x49, 0x06, 0x4A, 0x20, 0x23, 0x0B, 0x60, ++0x4F, 0xF4, 0x80, 0x10, 0x13, 0x60, 0x1D, 0xF0, 0x47, 0xFF, 0xC8, 0xE7, 0x1C, 0x41, 0x04, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x10, 0x41, 0x04, 0x40, 0x06, 0x4A, 0x07, 0x49, 0x12, 0x68, 0xD2, 0xF8, 0x24, 0x02, 0x20, 0x23, ++0x0B, 0x60, 0x08, 0xB1, 0x01, 0x20, 0x70, 0x47, 0x03, 0x4A, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x38, 0x18, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x15, 0x4C, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x14, 0x4B, ++0x18, 0x68, 0xD0, 0xF8, 0x24, 0x32, 0xBB, 0xB1, 0x00, 0xF5, 0x09, 0x70, 0x1E, 0xF0, 0x02, 0xF8, 0x10, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x22, 0x60, 0x01, 0xDB, 0x14, 0x30, 0x10, 0xBD, 0x00, 0x28, 0xFB, 0xD1, ++0x0B, 0x49, 0x0C, 0x48, 0x40, 0xF2, 0x92, 0x32, 0x1F, 0xF0, 0x00, 0xFC, 0x14, 0x20, 0x10, 0xBD, 0x06, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x22, 0x60, 0xF5, 0xDA, 0xEE, 0xE7, 0x00, 0xBF, 0x54, 0x40, 0x04, 0x40, ++0x00, 0x38, 0x18, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xE4, 0x7C, 0x15, 0x00, 0x10, 0xB5, 0x0A, 0x4C, ++0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x09, 0x4B, 0x1B, 0x68, 0xD3, 0xF8, 0x14, 0x02, 0x40, 0xB1, 0x03, 0xF5, 0x05, 0x70, ++0x1D, 0xF0, 0xCC, 0xFF, 0x01, 0x23, 0x23, 0x60, 0x00, 0xB1, 0x04, 0x30, 0x10, 0xBD, 0x01, 0x23, 0x23, 0x60, 0x10, 0xBD, ++0x58, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x01, 0x4B, 0x08, 0x22, 0x1A, 0x60, 0x70, 0x47, ++0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x41, 0x04, 0x40, ++0x01, 0x4B, 0x80, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x00, 0x41, 0x04, 0x40, 0xF8, 0xB5, 0x04, 0x46, 0x40, 0x89, 0x29, 0x4F, ++0x10, 0x30, 0x1D, 0xF0, 0xA3, 0xFB, 0x3E, 0x68, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x22, 0xDB, 0xA3, 0x88, ++0x62, 0x89, 0xE0, 0x88, 0xAB, 0x80, 0x00, 0x21, 0x0C, 0x23, 0x2B, 0x81, 0x6A, 0x81, 0xE8, 0x80, 0x29, 0x60, 0xE3, 0x18, ++0x62, 0xB1, 0x01, 0x3A, 0x22, 0xF0, 0x03, 0x02, 0x10, 0x32, 0x14, 0x44, 0x05, 0xF1, 0x08, 0x02, 0x53, 0xF8, 0x04, 0x1B, ++0x42, 0xF8, 0x04, 0x1F, 0xA3, 0x42, 0xF9, 0xD1, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x05, 0xF1, 0x0C, 0x00, ++0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0xD8, 0xBA, 0x00, 0x28, 0xDA, 0xD1, 0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x6F, 0x42, ++0x1F, 0xF0, 0x82, 0xFB, 0x3E, 0x68, 0xD2, 0xE7, 0x0D, 0x28, 0x0D, 0xD8, 0x0B, 0x28, 0xEB, 0xD9, 0x0C, 0x49, 0x0E, 0x48, ++0x4F, 0xF4, 0x90, 0x62, 0x1F, 0xF0, 0x76, 0xFB, 0x05, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0xBE, 0xBA, ++0x06, 0x49, 0x09, 0x48, 0xBB, 0x22, 0x1F, 0xF0, 0x6B, 0xFB, 0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x90, 0x62, 0x1F, 0xF0, ++0x65, 0xFB, 0xED, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x7C, 0x15, 0x00, 0x20, 0x7D, 0x15, 0x00, ++0x10, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x05, 0x46, 0x40, 0x89, 0x2B, 0x4F, 0x10, 0x30, 0x1D, 0xF0, 0x43, 0xFB, 0x3E, 0x68, ++0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x2A, 0xDB, 0xAB, 0x88, 0x6A, 0x89, 0xEF, 0x88, 0xA3, 0x80, 0x00, 0x21, ++0x0C, 0x23, 0x23, 0x81, 0x62, 0x81, 0xE7, 0x80, 0x21, 0x60, 0xEB, 0x18, 0x62, 0xB1, 0x01, 0x3A, 0x22, 0xF0, 0x03, 0x02, ++0x10, 0x32, 0x2A, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x53, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0F, 0x93, 0x42, 0xF9, 0xD1, ++0x1A, 0x4A, 0x53, 0x7D, 0x59, 0x1C, 0x51, 0x75, 0x2B, 0x81, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x12, 0xDB, 0x17, 0x4B, ++0x04, 0x22, 0x04, 0xF1, 0x0C, 0x00, 0x1A, 0x60, 0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0x70, 0xBA, 0x00, 0x28, 0xD2, 0xD1, ++0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x8E, 0x42, 0x1F, 0xF0, 0x1A, 0xFB, 0x3E, 0x68, 0xCA, 0xE7, 0x0D, 0x2F, 0x08, 0xD8, ++0x0B, 0x2F, 0xE8, 0xD9, 0x0C, 0x49, 0x0E, 0x48, 0x40, 0xF2, 0xA3, 0x42, 0x1F, 0xF0, 0x0E, 0xFB, 0xE1, 0xE7, 0x09, 0x49, ++0x0B, 0x48, 0xBB, 0x22, 0x1F, 0xF0, 0x08, 0xFB, 0x06, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xA3, 0x42, 0x1F, 0xF0, 0x02, 0xFB, ++0xD5, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x04, 0x35, 0x17, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0x79, 0x15, 0x00, ++0xFC, 0x7C, 0x15, 0x00, 0x20, 0x7D, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x0B, 0x4C, 0x23, 0x68, 0x9A, 0x07, ++0x0A, 0xD5, 0x0A, 0x4F, 0x0A, 0x4E, 0x02, 0x25, 0x38, 0x68, 0x35, 0x60, 0x04, 0x30, 0xFF, 0xF7, 0x8B, 0xFF, 0x23, 0x68, ++0x9B, 0x07, 0xF7, 0xD4, 0x4F, 0xF0, 0x80, 0x50, 0x1D, 0xF0, 0x0C, 0xFE, 0x04, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0xF8, 0xBD, ++0x04, 0x41, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x47, ++0xDF, 0xF8, 0x20, 0x93, 0xD9, 0xF8, 0x00, 0x20, 0x13, 0x78, 0x03, 0x2B, 0x82, 0xB0, 0x04, 0x46, 0x00, 0xF0, 0x16, 0x81, ++0x00, 0x27, 0x3E, 0x46, 0x01, 0x2B, 0x00, 0xF0, 0xC2, 0x80, 0x02, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0x00, 0xF0, 0xD3, 0x80, ++0x62, 0x89, 0xA3, 0x88, 0x33, 0x80, 0xF2, 0x80, 0x7A, 0xB9, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x03, 0x2B, 0x1C, 0xD0, ++0x02, 0x2B, 0x2F, 0xD0, 0x01, 0x2B, 0x00, 0xF0, 0x89, 0x80, 0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x1D, 0xF0, ++0x41, 0xBA, 0xA3, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x20, 0x81, 0x06, 0xF1, 0x0C, 0x00, ++0x04, 0xF1, 0x0C, 0x01, 0x31, 0xF0, 0x40, 0xFD, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x03, 0x2B, 0xE2, 0xD1, 0x9B, 0x4E, ++0x33, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x9A, 0x4B, 0x18, 0x68, 0x39, 0x1F, 0x00, 0xF5, 0x03, 0x70, 0x1D, 0xF0, 0x36, 0xFE, ++0x97, 0x4B, 0x01, 0x21, 0x02, 0x22, 0x31, 0x60, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x02, 0x2B, 0xCF, 0xD1, ++0x60, 0x89, 0x10, 0xF0, 0x03, 0x03, 0x40, 0xF0, 0xE9, 0x80, 0x19, 0x46, 0x9C, 0x46, 0x90, 0x4E, 0x42, 0xF2, 0x34, 0x03, ++0xF2, 0x5A, 0xB2, 0xF5, 0xC3, 0x7F, 0x00, 0xF2, 0xFD, 0x80, 0x57, 0x1C, 0xBF, 0xB2, 0x4F, 0xEA, 0xC2, 0x0E, 0x8B, 0x4B, ++0xA8, 0xF8, 0x0C, 0x20, 0xD3, 0xF8, 0x00, 0xA0, 0x00, 0xF1, 0x10, 0x03, 0x0A, 0xEB, 0x0E, 0x00, 0x0C, 0xEB, 0x03, 0x02, ++0x45, 0x60, 0x2A, 0xF8, 0x0E, 0x20, 0xC2, 0x78, 0x02, 0xF0, 0x31, 0x02, 0x42, 0xF0, 0x04, 0x02, 0xC2, 0x70, 0x96, 0xF8, ++0x02, 0x2C, 0x42, 0xF2, 0x34, 0x0C, 0x0B, 0x44, 0x01, 0x32, 0x01, 0x21, 0x4F, 0xF0, 0x00, 0x0E, 0x26, 0xF8, 0x0C, 0x70, ++0x86, 0xF8, 0x02, 0x2C, 0xC8, 0xE9, 0x01, 0x03, 0x88, 0xF8, 0x0E, 0x10, 0xC8, 0xF8, 0x00, 0xE0, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x76, 0x4B, 0x19, 0x60, 0x76, 0x4E, 0x76, 0x48, 0x33, 0x68, 0x41, 0x46, 0x01, 0x33, ++0x33, 0x60, 0x1D, 0xF0, 0xE3, 0xFD, 0x74, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x33, 0x68, 0x33, 0xB1, 0x6E, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x01, 0x2B, ++0x7F, 0xF4, 0x77, 0xAF, 0x01, 0xF0, 0xF2, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x0C, 0x81, 0xA1, 0x7A, 0x68, 0x4A, 0x0C, 0x31, ++0x29, 0x70, 0x61, 0x89, 0x0C, 0x31, 0x00, 0x27, 0x09, 0x12, 0x11, 0x26, 0x69, 0x70, 0xAE, 0x70, 0xEF, 0x70, 0x61, 0x89, ++0x86, 0x68, 0x47, 0x60, 0x10, 0x31, 0xC1, 0xF3, 0x0B, 0x01, 0x32, 0x40, 0x0A, 0x43, 0x42, 0xF0, 0x00, 0x42, 0x05, 0x60, ++0x82, 0x60, 0x03, 0xF0, 0x35, 0xF8, 0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x1D, 0xF0, 0x99, 0xB9, 0x63, 0x89, ++0x6C, 0x2B, 0x40, 0xF2, 0x8C, 0x80, 0x58, 0x4B, 0x1B, 0x68, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x05, 0x46, ++0x00, 0x2D, 0x00, 0xF0, 0x8A, 0x80, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0xF1, 0x04, 0x06, 0x7F, 0xF4, ++0x2D, 0xAF, 0x63, 0x89, 0x6C, 0x2B, 0x7A, 0xD9, 0x4D, 0x4B, 0x1B, 0x68, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, ++0x05, 0x46, 0x00, 0x2D, 0x75, 0xD0, 0x42, 0x4A, 0x42, 0xF2, 0x24, 0x03, 0xD3, 0x58, 0x00, 0x2B, 0x00, 0xF0, 0x9A, 0x80, ++0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x3D, 0x4E, 0x42, 0x48, ++0x33, 0x68, 0x01, 0x33, 0x33, 0x60, 0x1D, 0xF0, 0xB7, 0xFD, 0x33, 0x68, 0x80, 0x46, 0x33, 0xB1, 0x37, 0x4A, 0x01, 0x3B, ++0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xA3, 0x7A, 0x0C, 0x33, 0x2B, 0x70, 0x63, 0x89, 0x0C, 0x33, ++0x1B, 0x12, 0x11, 0x22, 0x6B, 0x70, 0x00, 0x23, 0xAA, 0x70, 0xEB, 0x70, 0x2E, 0x1D, 0xF3, 0xE6, 0x28, 0x4D, 0x2B, 0x68, ++0x00, 0x2B, 0xFC, 0xD0, 0x27, 0x4B, 0x18, 0x68, 0xD0, 0xF8, 0x04, 0x32, 0xD3, 0xB1, 0x00, 0xF5, 0x01, 0x70, 0x1D, 0xF0, ++0x93, 0xFD, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x2A, 0x60, 0xC0, 0xF2, 0x8B, 0x80, ++0x07, 0x1D, 0xD9, 0xF8, 0x00, 0x20, 0x3E, 0x46, 0x27, 0x4B, 0xB3, 0x60, 0x13, 0x78, 0xCD, 0xE6, 0xC3, 0xF1, 0x04, 0x03, ++0x5F, 0xFA, 0x83, 0xFC, 0x61, 0x46, 0x12, 0xE7, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x01, 0x21, 0x00, 0x2B, ++0x29, 0x60, 0xC0, 0xF2, 0x82, 0x80, 0x04, 0x26, 0x37, 0x46, 0xE9, 0xE7, 0xB2, 0xF5, 0x80, 0x6F, 0x7F, 0xF6, 0xDC, 0xAE, ++0x4F, 0xF4, 0xB1, 0x62, 0x1A, 0x49, 0x1B, 0x48, 0x1F, 0xF0, 0x76, 0xF9, 0x62, 0x89, 0xD3, 0xE6, 0x4F, 0xF0, 0x00, 0x0E, ++0x72, 0x46, 0x01, 0x27, 0x01, 0xE7, 0x01, 0xF0, 0xCF, 0xFF, 0x05, 0x46, 0x76, 0xE7, 0x05, 0xF0, 0x2B, 0xF8, 0x05, 0x46, ++0x87, 0xE7, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x11, 0x48, 0x00, 0xF0, 0x1D, 0xFD, 0xB2, 0xE6, 0x38, 0x36, 0x17, 0x00, ++0x50, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x00, 0x41, 0x04, 0x40, 0x7C, 0x36, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xF0, 0xFF, 0x7F, ++0x1C, 0x58, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x2A, 0xDE, 0xDE, 0xAD, 0x70, 0x79, 0x15, 0x00, 0xDC, 0x7D, 0x15, 0x00, ++0x68, 0x7D, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x20, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x1F, 0x4D, 0x20, 0x4A, 0x2B, 0x68, 0xD2, 0xF8, 0x44, 0x24, 0x01, 0x33, 0x2B, 0x60, 0x90, 0x47, ++0x2A, 0x68, 0x03, 0x46, 0x32, 0xB1, 0x19, 0x49, 0x01, 0x3A, 0x09, 0x68, 0x2A, 0x60, 0x0A, 0xB9, 0x01, 0xB1, 0x62, 0xB6, ++0x18, 0x48, 0x01, 0x93, 0x1D, 0xF0, 0x4E, 0xFD, 0x00, 0x90, 0x17, 0x48, 0x1D, 0xF0, 0x4A, 0xFD, 0xDD, 0xE9, 0x00, 0x13, ++0x02, 0x46, 0x15, 0x48, 0x00, 0xF0, 0xD0, 0xFC, 0x65, 0xE6, 0x14, 0x48, 0x00, 0xF0, 0xCC, 0xFC, 0x61, 0xE6, 0x60, 0xB1, ++0x07, 0x1D, 0x7F, 0xF4, 0x72, 0xAF, 0x40, 0xF2, 0x31, 0x52, 0x10, 0x49, 0x10, 0x48, 0x1F, 0xF0, 0x05, 0xF9, 0x3E, 0x46, ++0xD9, 0xF8, 0x00, 0x20, 0x6A, 0xE7, 0x40, 0xF2, 0x26, 0x32, 0x0B, 0x49, 0x0C, 0x48, 0x04, 0x26, 0x1F, 0xF0, 0xFA, 0xF8, ++0x37, 0x46, 0xD9, 0xF8, 0x00, 0x20, 0x5F, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xA0, 0x56, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0xA4, 0x7D, 0x15, 0x00, 0x08, 0x7E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x54, 0x7D, 0x15, 0x00, 0x44, 0x7D, 0x15, 0x00, 0x10, 0xB4, 0x15, 0x49, 0x15, 0x4C, 0x16, 0x4B, 0x4F, 0xF4, 0x4C, 0x02, ++0x22, 0x60, 0x0A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x30, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0xC0, 0x02, 0x1A, 0x60, ++0x1A, 0x68, 0x22, 0xF4, 0x40, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x4F, 0xF0, 0x60, 0x50, 0x22, 0xF4, 0x40, 0x42, 0x1A, 0x60, ++0x20, 0x60, 0x08, 0x60, 0x1A, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x22, 0xF4, 0x40, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, ++0x40, 0x72, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x40, 0x62, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x0C, 0x40, 0x04, 0x40, ++0x08, 0x40, 0x04, 0x40, 0x18, 0x40, 0x04, 0x40, 0x10, 0xB5, 0x01, 0x46, 0x04, 0x46, 0x05, 0x48, 0x1E, 0xF0, 0x30, 0xFE, ++0x04, 0x4A, 0x05, 0x4B, 0x14, 0x60, 0x4F, 0xF0, 0x80, 0x72, 0x1A, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x2C, 0x7E, 0x15, 0x00, ++0x98, 0x40, 0x04, 0x40, 0x00, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF0, 0x00, 0x72, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF0, 0x80, 0x62, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x40, 0x04, 0x40, ++0x08, 0xB5, 0x25, 0x4B, 0x19, 0x68, 0x4A, 0x03, 0x04, 0xD5, 0x4F, 0xF4, 0x80, 0x22, 0x43, 0xF8, 0x14, 0x2C, 0x08, 0xBD, ++0x08, 0x03, 0x04, 0xD5, 0x20, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x08, 0xBD, 0x4A, 0x02, 0x0F, 0xD4, 0x0B, 0x02, ++0x1D, 0xD4, 0x08, 0x01, 0x10, 0xD5, 0x1C, 0x4B, 0x1A, 0x4A, 0xDB, 0x7D, 0x4F, 0xF0, 0x00, 0x61, 0x01, 0x2B, 0x11, 0x60, ++0xE9, 0xD1, 0xBD, 0xE8, 0x08, 0x40, 0x23, 0xF0, 0xED, 0xBE, 0x15, 0x4B, 0x4F, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x08, 0xBD, ++0x11, 0xF0, 0x80, 0x53, 0x16, 0xD0, 0x12, 0x49, 0x10, 0x4B, 0x01, 0x20, 0x4F, 0xF0, 0x80, 0x52, 0x48, 0x75, 0x1A, 0x60, ++0x08, 0xBD, 0x0D, 0x4B, 0x0E, 0x48, 0x4F, 0xF4, 0x00, 0x02, 0x1A, 0x60, 0x00, 0xF0, 0x0E, 0xFC, 0x03, 0x20, 0x00, 0xF0, ++0x93, 0xFC, 0x0B, 0x4B, 0x4F, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x08, 0xBD, 0x8A, 0x00, 0xC4, 0xD5, 0x05, 0x49, 0x04, 0x4A, ++0x4B, 0x75, 0x4F, 0xF0, 0x00, 0x53, 0x13, 0x60, 0x08, 0xBD, 0x00, 0xBF, 0x1C, 0x40, 0x04, 0x40, 0x08, 0x40, 0x04, 0x40, ++0x4C, 0x36, 0x17, 0x00, 0x40, 0x7E, 0x15, 0x00, 0x00, 0x40, 0x04, 0x40, 0x15, 0x4B, 0xD3, 0xF8, 0x24, 0x31, 0x59, 0x06, ++0x09, 0xD5, 0x10, 0xB5, 0x13, 0x4C, 0x23, 0x68, 0x1A, 0x07, 0x88, 0xB0, 0xC3, 0xF3, 0xC0, 0x00, 0x03, 0xD4, 0x08, 0xB0, ++0x10, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x0F, 0x49, 0x20, 0x22, 0x68, 0x46, 0x31, 0xF0, 0xC6, 0xFA, 0x0D, 0x4B, 0x1B, 0x68, ++0x23, 0x68, 0xC3, 0xF3, 0x40, 0x00, 0x9B, 0x07, 0xEF, 0xD5, 0x0B, 0x4B, 0x0B, 0x4A, 0x4F, 0xF4, 0x00, 0x11, 0x19, 0x60, ++0x10, 0x68, 0x10, 0xF4, 0x40, 0x13, 0xFB, 0xD0, 0x08, 0x4A, 0xC0, 0xF3, 0x00, 0x50, 0x13, 0x60, 0xE1, 0xE7, 0x00, 0xBF, ++0x00, 0x00, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x30, 0x95, 0x16, 0x00, 0x30, 0x60, 0x50, 0x40, 0x00, 0x40, 0x04, 0x40, ++0x04, 0x40, 0x04, 0x40, 0x08, 0x40, 0x04, 0x40, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x09, 0xD1, 0x0B, 0x4B, 0x4F, 0xF4, ++0x00, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x09, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x07, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x52, 0x72, 0x1E, 0xF0, ++0xE1, 0xBF, 0x00, 0xBF, 0x00, 0x40, 0x04, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x38, 0xB5, 0x22, 0x48, 0xFC, 0xF7, 0xFA, 0xFB, 0x83, 0x07, 0x23, 0xD5, 0x20, 0x48, 0x00, 0xF0, 0x8B, 0xFB, 0x20, 0x48, ++0xFC, 0xF7, 0xF2, 0xFB, 0x04, 0x46, 0x1F, 0x48, 0xFC, 0xF7, 0xEE, 0xFB, 0x03, 0x46, 0x1D, 0x48, 0x1C, 0x40, 0xFC, 0xF7, ++0xE9, 0xFB, 0x84, 0x42, 0x1F, 0xD0, 0x05, 0x20, 0x00, 0xF0, 0x14, 0xFC, 0x01, 0x28, 0x04, 0x46, 0x17, 0xD0, 0x03, 0x20, ++0x00, 0xF0, 0x06, 0xFC, 0x02, 0x25, 0x21, 0x46, 0x15, 0x48, 0x00, 0xF0, 0x6F, 0xFB, 0x28, 0x46, 0xBD, 0xE8, 0x38, 0x40, ++0xFF, 0xF7, 0xB2, 0xBF, 0x01, 0x46, 0x12, 0x48, 0x00, 0xF0, 0x66, 0xFB, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x08, 0xDB, 0x38, 0xBD, 0x05, 0x46, 0xE9, 0xE7, 0x20, 0x22, 0x0D, 0x48, 0x11, 0x46, 0xFC, 0xF7, 0x12, 0xFC, ++0xD9, 0xE7, 0xBD, 0xE8, 0x38, 0x40, 0x0B, 0x49, 0x0B, 0x48, 0x4F, 0xF4, 0xD3, 0x62, 0x1E, 0xF0, 0x93, 0xBF, 0x00, 0xBF, ++0x08, 0x30, 0x01, 0x50, 0x54, 0x7E, 0x15, 0x00, 0x20, 0x10, 0x01, 0x50, 0x18, 0x10, 0x01, 0x50, 0x60, 0x7E, 0x15, 0x00, ++0x6C, 0x7E, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x24, 0x10, 0x01, 0x50, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x02, 0x48, 0x38, 0x22, 0x00, 0x21, 0xFA, 0xF7, 0x91, 0xBA, 0x00, 0xBF, 0x48, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x5D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x80, 0x46, 0x0F, 0x46, 0x16, 0x46, 0xC0, 0xF2, 0xA8, 0x80, ++0x00, 0x23, 0x3B, 0x62, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x56, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xB5, 0x01, 0x05, 0xF1, 0x80, 0x42, 0x02, 0xF5, 0xE2, 0x24, 0x53, 0x49, 0x23, 0x68, 0x08, 0x68, 0x43, 0xF0, 0x01, 0x03, ++0x00, 0xF1, 0x01, 0x0C, 0x02, 0xF5, 0xE0, 0x22, 0x23, 0x60, 0xC1, 0xF8, 0x00, 0xC0, 0x23, 0x68, 0xDB, 0x03, 0xFC, 0xD5, ++0xDF, 0xF8, 0x38, 0xE1, 0x5E, 0xF8, 0x26, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0x05, 0xF1, 0x80, 0x43, 0x03, 0xF5, ++0xE0, 0x23, 0x41, 0xF2, 0x0C, 0x0A, 0x53, 0xF8, 0x0A, 0xA0, 0x1A, 0xF4, 0x00, 0x6F, 0x61, 0xD0, 0x05, 0xF1, 0x80, 0x43, ++0x03, 0xF5, 0xE0, 0x23, 0x41, 0xF2, 0x08, 0x09, 0xDF, 0xF8, 0x0C, 0xA1, 0x43, 0xF8, 0x09, 0xA0, 0x41, 0xF2, 0x0C, 0x05, ++0x4F, 0xF0, 0x14, 0x0A, 0x43, 0xF8, 0x05, 0xA0, 0x41, 0xF2, 0x10, 0x0B, 0x41, 0xF2, 0x14, 0x0A, 0x00, 0x25, 0x43, 0xF8, ++0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x18, 0x0B, 0x41, 0xF2, 0x1C, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, ++0x0A, 0x50, 0x03, 0xF5, 0x81, 0x5B, 0x41, 0xF2, 0x24, 0x0A, 0xCB, 0xF8, 0x00, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, ++0x28, 0x0B, 0x41, 0xF2, 0x2C, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x34, 0x0B, 0x41, 0xF2, ++0x38, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x3C, 0x0B, 0x41, 0xF2, 0x30, 0x0A, 0x43, 0xF8, ++0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x80, 0xBD, 0x68, 0x45, 0xF4, 0x00, 0x25, 0xBD, 0x60, 0x53, 0xF8, 0x09, 0x50, 0x45, 0xF0, ++0x01, 0x05, 0x43, 0xF8, 0x09, 0x50, 0x41, 0xF2, 0x04, 0x05, 0x53, 0x59, 0x43, 0xF0, 0x01, 0x03, 0x53, 0x51, 0x23, 0x68, ++0x4E, 0xF8, 0x26, 0x70, 0x23, 0xF0, 0x01, 0x03, 0x23, 0x60, 0xBC, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0x14, 0x4B, 0x08, 0x60, ++0x1B, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x41, 0xF2, 0x18, 0x02, 0x9D, 0x58, 0x2D, 0x03, ++0x07, 0xD5, 0x9D, 0x58, 0x41, 0xF2, 0x30, 0x0A, 0x25, 0xF4, 0x00, 0x25, 0x9D, 0x50, 0x43, 0xF8, 0x0A, 0x80, 0xD9, 0xF8, ++0x08, 0x30, 0x23, 0xF4, 0x00, 0x23, 0xC9, 0xF8, 0x08, 0x30, 0xC9, 0xF8, 0x20, 0x80, 0xD8, 0xE7, 0x0D, 0x2A, 0x7F, 0xF7, ++0x55, 0xAF, 0x06, 0x49, 0x06, 0x48, 0x4E, 0x22, 0x1E, 0xF0, 0xBA, 0xFE, 0x4E, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0x7E, 0x15, 0x00, 0x48, 0x35, 0x17, 0x00, ++0x10, 0x00, 0x01, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x01, 0x30, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x63, 0x70, 0x47, 0x00, 0xBF, ++0x3F, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x40, 0x70, 0xB4, 0x18, 0x4D, 0x18, 0x4C, 0x2E, 0x6B, 0xB1, 0xF5, 0x00, 0x6F, ++0x46, 0xF0, 0x80, 0x56, 0x2E, 0x63, 0x60, 0x60, 0xEB, 0x63, 0x20, 0x60, 0x0B, 0x46, 0x28, 0xBF, 0x4F, 0xF4, 0x00, 0x63, ++0x80, 0x07, 0x11, 0xD0, 0xC1, 0xF3, 0x10, 0x05, 0x10, 0x48, 0x43, 0xF0, 0x0C, 0x53, 0x21, 0xF0, 0x70, 0x41, 0xA3, 0x60, ++0xE5, 0x60, 0x21, 0x61, 0x60, 0x61, 0x0B, 0x49, 0x00, 0x23, 0x23, 0x62, 0x08, 0x46, 0x70, 0xBC, 0xFF, 0xF7, 0x04, 0xBF, ++0xC1, 0xF3, 0x10, 0x05, 0x43, 0xF0, 0x23, 0x43, 0x21, 0xF0, 0x70, 0x41, 0x4F, 0xF0, 0x04, 0x10, 0xA3, 0x60, 0xE5, 0x60, ++0x21, 0x61, 0x60, 0x61, 0xEB, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x07, 0x40, 0x74, 0x25, 0x17, 0x00, 0x01, 0x00, 0x04, 0x00, ++0x01, 0x23, 0x06, 0x4A, 0x03, 0xFA, 0x00, 0xF0, 0x93, 0x69, 0x03, 0x42, 0xFC, 0xD1, 0x13, 0x6B, 0x23, 0xF0, 0x80, 0x53, ++0x13, 0x63, 0x10, 0x6C, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x07, 0x40, 0x08, 0x4A, 0xD3, 0x68, 0x19, 0x04, 0x44, 0xBF, ++0x4F, 0xF4, 0x00, 0x01, 0x91, 0x60, 0x5B, 0x05, 0x00, 0xD4, 0x70, 0x47, 0x03, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x9A, 0x60, ++0x4F, 0xF0, 0x80, 0x40, 0x1D, 0xF0, 0x4E, 0xB9, 0x00, 0x10, 0x50, 0x40, 0x11, 0x4A, 0x13, 0x68, 0x13, 0xF0, 0x01, 0x01, ++0x0A, 0xD1, 0x23, 0xF4, 0x40, 0x73, 0x43, 0xF4, 0x90, 0x73, 0x43, 0xF0, 0x01, 0x03, 0x11, 0x20, 0x11, 0x61, 0x51, 0x61, ++0x50, 0x60, 0x13, 0x60, 0x5A, 0x04, 0x03, 0xD4, 0x08, 0x4A, 0x43, 0xF4, 0x80, 0x43, 0x13, 0x60, 0x07, 0x4B, 0x08, 0x49, ++0x9A, 0x68, 0xD1, 0xF8, 0xD0, 0x10, 0xC2, 0xF8, 0xB4, 0x10, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF0, 0x00, 0x52, 0x1A, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x06, 0x4B, 0x07, 0x49, ++0x9A, 0x68, 0xD1, 0xF8, 0xD0, 0x10, 0xC2, 0xF8, 0xB4, 0x10, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF0, 0x00, 0x52, 0x1A, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x3E, 0x4B, 0x1A, 0x68, 0x00, 0x2A, 0x6F, 0xD1, ++0x3D, 0x49, 0xD1, 0xF8, 0xA4, 0x10, 0x00, 0x29, 0xF0, 0xB4, 0x56, 0xDA, 0x3B, 0x48, 0x00, 0x68, 0x00, 0x28, 0x4E, 0xD0, ++0x3A, 0x4D, 0x3B, 0x48, 0x3B, 0x4C, 0x2A, 0x60, 0x01, 0x25, 0x02, 0x60, 0x25, 0x60, 0xC2, 0x68, 0x39, 0x4D, 0x3A, 0x4C, ++0x42, 0xF4, 0x80, 0x72, 0xC2, 0x60, 0x03, 0x22, 0x2A, 0x60, 0x62, 0x68, 0x92, 0x07, 0x21, 0xF0, 0x00, 0x41, 0x57, 0xD5, ++0x35, 0x4A, 0x12, 0x68, 0x10, 0x09, 0x81, 0x42, 0x4D, 0xD2, 0xB2, 0xFB, 0xF1, 0xF1, 0xC1, 0xF3, 0x42, 0x04, 0x01, 0xF0, ++0x0F, 0x02, 0x12, 0x1B, 0xC1, 0xF3, 0x07, 0x1C, 0x04, 0xEB, 0x02, 0x14, 0xC1, 0xF3, 0x07, 0x31, 0x2A, 0x4A, 0x28, 0x4D, ++0x10, 0x68, 0x2C, 0x4E, 0x2C, 0x4F, 0x40, 0xF0, 0x80, 0x00, 0x10, 0x60, 0xC7, 0xF8, 0x00, 0xC0, 0x29, 0x60, 0x34, 0x60, ++0x11, 0x68, 0x21, 0x4C, 0x22, 0x48, 0x28, 0x4E, 0x21, 0xF0, 0x80, 0x01, 0x11, 0x60, 0x07, 0x22, 0x22, 0x60, 0x02, 0x68, ++0x25, 0x4C, 0x26, 0x49, 0xD4, 0xF8, 0xBC, 0x40, 0x22, 0xF4, 0xFF, 0x72, 0x22, 0xF0, 0x01, 0x02, 0x42, 0xF0, 0x01, 0x02, ++0x02, 0x60, 0x01, 0x22, 0x2A, 0x60, 0xB0, 0x68, 0x4F, 0xF4, 0x80, 0x32, 0xC0, 0xF8, 0x80, 0x40, 0x0A, 0x60, 0x01, 0x22, ++0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x10, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0xF7, 0xD0, 0x10, 0x48, 0x17, 0x4C, 0x16, 0x49, ++0xD4, 0xF8, 0xBC, 0x40, 0x16, 0x4A, 0x01, 0x25, 0x05, 0x60, 0x88, 0x68, 0x4F, 0xF4, 0x80, 0x31, 0xC0, 0xF8, 0x80, 0x40, ++0x11, 0x60, 0xE8, 0xE7, 0x70, 0x47, 0x00, 0x24, 0x21, 0x46, 0x4F, 0xF0, 0x01, 0x0C, 0xB9, 0xE7, 0x0F, 0x48, 0x10, 0x4A, ++0xA7, 0xE7, 0x00, 0xBF, 0xA4, 0x25, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x68, 0x28, 0x17, 0x00, 0x08, 0x10, 0x04, 0x40, ++0x04, 0x10, 0x04, 0x40, 0x24, 0x10, 0x04, 0x40, 0x0C, 0x10, 0x04, 0x40, 0x00, 0x00, 0x10, 0x40, 0x14, 0x13, 0x17, 0x00, ++0x28, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, ++0x50, 0x97, 0x31, 0x00, 0x00, 0x75, 0x19, 0x03, 0x03, 0x4A, 0x13, 0x68, 0x1B, 0x03, 0xFC, 0xD4, 0x02, 0x4B, 0x18, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0x03, 0x4A, 0x13, 0x68, 0xDB, 0x07, 0xFC, 0xD5, ++0x02, 0x4B, 0x18, 0x68, 0xC0, 0xB2, 0x70, 0x47, 0x14, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0xF0, 0xB5, 0x03, 0x46, ++0xC3, 0xB0, 0xEF, 0xF3, 0x05, 0x85, 0x73, 0x4C, 0x22, 0x68, 0x12, 0x78, 0x02, 0x2A, 0x04, 0xD1, 0x71, 0x4A, 0xB2, 0xF8, ++0xAA, 0x20, 0x52, 0x04, 0x56, 0xD4, 0x00, 0x91, 0x00, 0x22, 0x4F, 0xF4, 0x80, 0x71, 0x02, 0xA8, 0x1D, 0xF0, 0x46, 0xFE, ++0x06, 0x46, 0x00, 0x2E, 0x31, 0xDD, 0x6B, 0x4B, 0x1B, 0x68, 0x1B, 0xB9, 0x6A, 0x4B, 0xD3, 0xF8, 0x28, 0x33, 0x98, 0x47, ++0x1D, 0xB9, 0x69, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x68, 0x4B, 0x1B, 0x68, 0x33, 0xB9, 0x67, 0x4A, 0x13, 0x68, ++0x1F, 0x03, 0xFC, 0xD4, 0x66, 0x4B, 0x5F, 0x22, 0x1A, 0x60, 0x5F, 0x4B, 0xB3, 0xF8, 0xAA, 0x30, 0x13, 0xF4, 0x80, 0x43, ++0x18, 0xD1, 0x02, 0xA9, 0x60, 0x4A, 0x61, 0x48, 0x77, 0x18, 0x4F, 0xF0, 0x0D, 0x0C, 0x11, 0xF8, 0x01, 0x4B, 0x0A, 0x2C, ++0x1C, 0xD0, 0x13, 0x68, 0x1B, 0x03, 0xFC, 0xD4, 0x04, 0x60, 0xB9, 0x42, 0x11, 0xF8, 0x01, 0x3C, 0xF3, 0xD1, 0x15, 0xB9, ++0x55, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x30, 0x46, 0x43, 0xB0, 0xF0, 0xBD, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x1C, 0xD0, ++0x02, 0x2B, 0xF2, 0xD1, 0x53, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xED, 0xD0, 0x00, 0x2D, 0xEF, 0xD1, 0x26, 0xE0, ++0x0D, 0x2B, 0xE0, 0xD0, 0x13, 0x68, 0x1C, 0x03, 0xFC, 0xD4, 0xC0, 0xF8, 0x00, 0xC0, 0x11, 0xF8, 0x01, 0x4C, 0xD8, 0xE7, ++0x00, 0x91, 0x00, 0x22, 0x4F, 0xF4, 0x80, 0x71, 0x03, 0xA8, 0x1D, 0xF0, 0xEF, 0xFD, 0x06, 0x46, 0xA7, 0xE7, 0x46, 0x4F, ++0x3B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xD2, 0xD0, 0x00, 0x2D, 0xD4, 0xD1, 0x43, 0x48, 0x1D, 0xF0, 0x07, 0xF9, 0x04, 0x28, ++0x62, 0xD8, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0xC8, 0xD1, 0x3B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xC4, 0xD0, 0x3E, 0x48, ++0x1D, 0xF0, 0xFA, 0xF8, 0x04, 0x28, 0xBF, 0xD9, 0x3B, 0x48, 0x3C, 0x4C, 0x1D, 0xF0, 0xB4, 0xF8, 0x42, 0xF2, 0x34, 0x03, ++0x13, 0x25, 0xE2, 0x5A, 0x8D, 0xF8, 0x08, 0x60, 0x00, 0x23, 0xB2, 0xF5, 0xC3, 0x7F, 0x02, 0xAF, 0x01, 0x46, 0x7D, 0x80, ++0x7B, 0x70, 0x4D, 0xD8, 0x55, 0x1C, 0xAD, 0xB2, 0xD3, 0x00, 0x33, 0x48, 0x8A, 0x81, 0xD0, 0xF8, 0x00, 0xC0, 0x0C, 0xEB, ++0x03, 0x00, 0x32, 0x1D, 0x47, 0x60, 0x2C, 0xF8, 0x03, 0x20, 0xC3, 0x78, 0x03, 0xF0, 0x31, 0x03, 0x43, 0xF0, 0x04, 0x03, ++0xC3, 0x70, 0x94, 0xF8, 0x02, 0x3C, 0x42, 0xF2, 0x34, 0x0C, 0x01, 0x33, 0x84, 0xF8, 0x02, 0x3C, 0x01, 0x27, 0x00, 0x23, ++0x24, 0xF8, 0x0C, 0x50, 0xC1, 0xE9, 0x01, 0x02, 0x8F, 0x73, 0x0B, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, ++0x72, 0xB6, 0x22, 0x4B, 0x1F, 0x60, 0x22, 0x4C, 0x22, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1D, 0xF0, 0x32, 0xF8, ++0x13, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x23, 0x68, 0x00, 0x2B, 0x3F, 0xF4, 0x76, 0xAF, 0x19, 0x4A, 0x01, 0x3B, ++0x12, 0x68, 0x23, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0x6F, 0xAF, 0x00, 0x2A, 0x3F, 0xF4, 0x6C, 0xAF, 0x62, 0xB6, 0x69, 0xE7, ++0x7C, 0x2E, 0x32, 0x46, 0xA8, 0xBF, 0x7C, 0x22, 0x92, 0xB2, 0x02, 0xA9, 0x13, 0x20, 0x02, 0xF0, 0xF9, 0xFA, 0x5F, 0xE7, ++0x1A, 0x46, 0x01, 0x25, 0xB1, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xA4, 0x25, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x40, 0x40, 0x04, 0x40, 0x68, 0x28, 0x17, 0x00, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, ++0x74, 0x36, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x0F, 0xB4, 0x00, 0xB5, 0x83, 0xB0, 0x04, 0xA9, ++0x05, 0x4B, 0x51, 0xF8, 0x04, 0x0B, 0xD3, 0xF8, 0x30, 0x34, 0x01, 0x91, 0x98, 0x47, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xEB, ++0x04, 0xB0, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x01, 0x22, 0x90, 0x42, 0x10, 0xB4, 0x02, 0xFA, 0x00, 0xF4, 0x11, 0xDD, ++0xA0, 0xF1, 0x08, 0x03, 0x93, 0x42, 0x0D, 0xD9, 0x0F, 0x28, 0x25, 0xDD, 0x1F, 0x28, 0x12, 0xDC, 0x15, 0x4A, 0x52, 0xF8, ++0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x43, 0xF0, 0x02, 0x03, 0x42, 0xF8, 0x20, 0x30, 0x08, 0xE0, 0x10, 0x4A, 0x52, 0xF8, ++0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x43, 0xF0, 0x01, 0x03, 0x42, 0xF8, 0x20, 0x30, 0x0D, 0x4B, 0x5A, 0x68, 0x22, 0x43, ++0x5A, 0x60, 0x9A, 0x68, 0x29, 0xB9, 0x22, 0xEA, 0x04, 0x02, 0x9A, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x22, 0x43, ++0x9A, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x03, 0x4A, 0x52, 0xF8, 0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x42, 0xF8, ++0x20, 0x30, 0xE6, 0xE7, 0x00, 0x30, 0x50, 0x40, 0x00, 0x40, 0x50, 0x40, 0x04, 0x49, 0x01, 0x22, 0x0B, 0x68, 0x02, 0xFA, ++0x00, 0xF0, 0x23, 0xEA, 0x00, 0x03, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x40, 0x50, 0x40, 0x10, 0xB5, 0x01, 0x29, ++0x82, 0xB0, 0x04, 0x46, 0x10, 0xD0, 0x20, 0xF0, 0x03, 0x03, 0x0F, 0x22, 0x9A, 0x40, 0x11, 0x46, 0x0D, 0x48, 0xFC, 0xF7, ++0x51, 0xF8, 0x01, 0x22, 0xA2, 0x40, 0x0C, 0x48, 0x11, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7, 0x48, 0xB8, ++0x01, 0xFA, 0x00, 0xF2, 0x11, 0x46, 0x07, 0x48, 0x01, 0x92, 0xFC, 0xF7, 0x41, 0xF8, 0x01, 0x9A, 0x05, 0x48, 0x11, 0x46, ++0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7, 0x39, 0xB8, 0x00, 0xBF, 0x2C, 0x10, 0x01, 0x50, 0x04, 0x10, 0x01, 0x50, ++0x08, 0x10, 0x01, 0x50, 0x01, 0x23, 0x03, 0xFA, 0x00, 0xF2, 0x11, 0x46, 0x01, 0x48, 0xFC, 0xF7, 0x2B, 0xB8, 0x00, 0xBF, ++0x00, 0x10, 0x01, 0x50, 0x01, 0x22, 0x82, 0x40, 0x00, 0x21, 0x01, 0x48, 0xFC, 0xF7, 0x22, 0xB8, 0x00, 0x10, 0x01, 0x50, ++0x10, 0xB5, 0x04, 0x46, 0x03, 0x48, 0xFB, 0xF7, 0xCB, 0xFF, 0xE0, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x10, 0xBD, 0x00, 0xBF, ++0x00, 0x10, 0x01, 0x50, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x0E, 0x48, 0x0F, 0x4A, ++0x03, 0x68, 0x0F, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x03, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, ++0x43, 0xF0, 0xC2, 0x03, 0x13, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x03, 0x60, 0x13, 0x68, ++0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0xC2, 0x20, 0x13, 0x60, 0xC8, 0x71, 0x70, 0x47, 0xAC, 0xB3, 0x33, 0x40, ++0xD4, 0xB3, 0x33, 0x40, 0x80, 0x35, 0x17, 0x00, 0x24, 0x4B, 0x25, 0x48, 0x1B, 0x68, 0x2D, 0xE9, 0xF0, 0x41, 0x24, 0x4D, ++0x24, 0x4F, 0x6A, 0x79, 0x95, 0xF9, 0x07, 0x10, 0x3C, 0x68, 0x23, 0x4E, 0x03, 0xF0, 0x0F, 0x03, 0x1A, 0x44, 0x52, 0xB2, ++0x89, 0x1A, 0x6F, 0xF0, 0x3D, 0x03, 0x99, 0x42, 0xB8, 0xBF, 0x19, 0x46, 0x5F, 0xFA, 0x81, 0xFC, 0x24, 0xF0, 0xFF, 0x04, ++0x44, 0xEA, 0x0C, 0x04, 0x3C, 0x60, 0x33, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xEA, 0x0C, 0x03, 0x33, 0x60, 0x3C, 0x68, ++0xCB, 0x1E, 0x5F, 0xFA, 0x83, 0xFC, 0x24, 0xF4, 0x7F, 0x24, 0x44, 0xEA, 0x0C, 0x34, 0x3C, 0x60, 0x33, 0x68, 0x23, 0xF4, ++0x7F, 0x23, 0x4C, 0xB2, 0x43, 0xEA, 0x0C, 0x33, 0x33, 0x60, 0x21, 0x46, 0xEC, 0x71, 0x1E, 0xF0, 0xC3, 0xF8, 0x3D, 0x34, ++0x0E, 0xDB, 0x0D, 0x4B, 0x29, 0x89, 0x1A, 0x69, 0x0C, 0x4B, 0x47, 0xF2, 0x30, 0x54, 0x05, 0xF1, 0x0C, 0x00, 0x04, 0xFB, ++0x01, 0x21, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x81, 0x1C, 0x01, 0x32, 0x40, ++0xB8, 0x7E, 0x15, 0x00, 0x80, 0x35, 0x17, 0x00, 0xAC, 0xB3, 0x33, 0x40, 0xD4, 0xB3, 0x33, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x12, 0x4A, 0x12, 0x68, 0xD2, 0xE9, 0x06, 0x01, 0x38, 0xB5, 0x11, 0x4B, 0x15, 0x6A, 0x18, 0x60, ++0x59, 0x60, 0x50, 0x6A, 0x0F, 0x4C, 0xD2, 0xE9, 0x0A, 0x12, 0xC3, 0xE9, 0x02, 0x50, 0xC3, 0xE9, 0x04, 0x12, 0xD4, 0xF8, ++0x2C, 0x33, 0x98, 0x47, 0xD4, 0xF8, 0xC0, 0x30, 0x98, 0x47, 0xFB, 0xF7, 0xAF, 0xFA, 0x09, 0x4B, 0x1B, 0x68, 0x1B, 0x78, ++0x03, 0x2B, 0x02, 0xD1, 0xD4, 0xF8, 0x20, 0x31, 0x98, 0x47, 0xBD, 0xE8, 0x38, 0x40, 0xFF, 0xF7, 0x79, 0xBB, 0x00, 0xBF, ++0xC8, 0x35, 0x17, 0x00, 0xB0, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x30, 0xB4, 0x08, 0x4B, ++0x08, 0x48, 0x18, 0x60, 0xC2, 0x25, 0x40, 0xF6, 0xEC, 0x20, 0x4F, 0xF4, 0x7A, 0x74, 0x06, 0x49, 0x06, 0x4A, 0xDD, 0x71, ++0x98, 0x80, 0x1C, 0x81, 0x19, 0x61, 0x30, 0xBC, 0x1A, 0x62, 0x70, 0x47, 0x80, 0x35, 0x17, 0x00, 0x01, 0x00, 0x00, 0x14, ++0x95, 0x64, 0x12, 0x00, 0x4D, 0x64, 0x12, 0x00, 0x90, 0xF8, 0x62, 0x30, 0xCB, 0xB9, 0x0D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x03, 0xDB, 0x00, 0x23, 0x84, 0xF8, 0xAC, 0x30, 0x10, 0xBD, 0x90, 0xF8, ++0xAC, 0x30, 0x01, 0x2B, 0xF7, 0xD0, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xE7, 0x12, 0x1E, 0xF0, 0xBB, 0xFA, 0x00, 0x23, ++0x84, 0xF8, 0xAC, 0x30, 0x10, 0xBD, 0x70, 0x47, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xCC, 0x7E, 0x15, 0x00, ++0x13, 0x4A, 0x90, 0xF8, 0x22, 0x30, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, ++0x1B, 0xD1, 0x0F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x08, 0xDB, 0x94, 0xF8, ++0x23, 0x10, 0x0B, 0x48, 0x1E, 0xF0, 0x1E, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x70, 0x32, 0x10, 0xBD, 0x90, 0xF8, 0x70, 0x32, ++0x01, 0x2B, 0xF2, 0xD0, 0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xF3, 0x12, 0x1E, 0xF0, 0x8A, 0xFA, 0xEB, 0xE7, 0x70, 0x47, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x10, 0x7F, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x7E, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x41, 0x90, 0xF8, 0x62, 0x40, 0x1C, 0xB9, 0x90, 0xF8, 0x64, 0x30, 0x06, 0x46, 0x0B, 0xB9, 0xBD, 0xE8, ++0xF0, 0x81, 0xD0, 0xE9, 0x24, 0x23, 0xD0, 0xF8, 0x98, 0x10, 0x42, 0x48, 0xDF, 0xF8, 0x30, 0x81, 0x1D, 0xF0, 0xF0, 0xFF, ++0x45, 0x46, 0x06, 0xF5, 0xB2, 0x77, 0x28, 0x46, 0x06, 0x22, 0x39, 0x46, 0x30, 0xF0, 0xD8, 0xFC, 0x14, 0x35, 0x40, 0xB1, ++0x01, 0x34, 0x05, 0x2C, 0xF5, 0xD1, 0x3A, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5B, 0xDB, 0x04, 0xEB, ++0x84, 0x03, 0x08, 0xEB, 0x83, 0x03, 0xA2, 0x00, 0xD9, 0x79, 0x00, 0x29, 0xD9, 0xD1, 0x1B, 0x7A, 0x03, 0xBB, 0xD6, 0xF8, ++0x90, 0x30, 0x31, 0x2B, 0x29, 0xD9, 0xD6, 0xF8, 0x94, 0x10, 0xB1, 0xEB, 0x53, 0x0F, 0x3B, 0xD8, 0x14, 0x44, 0x08, 0xEB, ++0x84, 0x08, 0x98, 0xF8, 0x06, 0x30, 0x00, 0x2B, 0x48, 0xD1, 0x00, 0x23, 0xC6, 0xE9, 0x24, 0x33, 0x29, 0x4A, 0xC6, 0xF8, ++0x98, 0x30, 0x12, 0x69, 0x28, 0x49, 0x29, 0x4B, 0x06, 0xF1, 0x9C, 0x00, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, ++0x11, 0x44, 0x18, 0x47, 0xD6, 0xF8, 0x98, 0x30, 0x53, 0xB3, 0xD6, 0xF8, 0x90, 0x30, 0x00, 0x2B, 0x37, 0xD0, 0x11, 0x19, ++0x08, 0xEB, 0x81, 0x01, 0x00, 0x20, 0x08, 0x72, 0xD3, 0xE7, 0x0B, 0x2B, 0x12, 0xD8, 0xD6, 0xF8, 0x98, 0x20, 0x14, 0x2A, ++0xDB, 0xD9, 0x00, 0x2B, 0xD9, 0xD1, 0x1B, 0x48, 0x1D, 0xF0, 0x9A, 0xFF, 0x18, 0x4B, 0x01, 0x22, 0x88, 0xF8, 0x06, 0x20, ++0x30, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xD6, 0xF8, 0x94, 0x10, 0x14, 0x4A, 0xA2, 0xFB, ++0x03, 0x02, 0x22, 0xF0, 0x03, 0x00, 0x00, 0xEB, 0x92, 0x02, 0x8A, 0x42, 0xE1, 0xD8, 0xE6, 0xE7, 0xD6, 0xF8, 0x90, 0x30, ++0xD5, 0xE7, 0x0F, 0x49, 0x0F, 0x48, 0x40, 0xF2, 0x13, 0x22, 0x1E, 0xF0, 0xF5, 0xF9, 0x9C, 0xE7, 0x00, 0x23, 0x0D, 0x48, ++0x88, 0xF8, 0x06, 0x30, 0x1D, 0xF0, 0x74, 0xFF, 0xAF, 0xE7, 0x0B, 0x48, 0xD4, 0xE7, 0x00, 0xBF, 0x1C, 0x7F, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x80, 0xC3, 0xC9, 0x01, 0x88, 0x1A, 0x17, 0x00, 0x44, 0x7F, 0x15, 0x00, ++0xAB, 0xAA, 0xAA, 0xAA, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x3C, 0x7F, 0x15, 0x00, 0x30, 0x7F, 0x15, 0x00, ++0xCC, 0x35, 0x17, 0x00, 0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, 0x01, 0xD0, 0x04, 0xF0, ++0xEF, 0xBC, 0x03, 0xF0, 0xD5, 0xBF, 0x00, 0xF0, 0xD7, 0xBF, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x46, ++0x00, 0xF0, 0x6C, 0xFE, 0x01, 0x20, 0x08, 0xBD, 0x70, 0xB5, 0x30, 0x4C, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x1E, 0xD0, ++0x02, 0x2B, 0x14, 0xD1, 0x2D, 0x4B, 0x2E, 0x49, 0x2E, 0x4A, 0xC3, 0xE9, 0x06, 0x12, 0x2E, 0x4D, 0xD5, 0xF8, 0x14, 0x31, ++0x98, 0x47, 0xD5, 0xF8, 0x18, 0x31, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x36, 0xD0, 0x02, 0x2B, 0x1D, 0xD0, ++0x03, 0x2B, 0x0E, 0xD0, 0x70, 0xBD, 0x03, 0x2B, 0xED, 0xD1, 0x22, 0x4B, 0x25, 0x49, 0x26, 0x4A, 0xC3, 0xE9, 0x08, 0x12, ++0xE7, 0xE7, 0x1F, 0x4B, 0x24, 0x49, 0x25, 0x4A, 0xC3, 0xE9, 0x02, 0x12, 0xE1, 0xE7, 0x24, 0x4B, 0x1B, 0x4C, 0x24, 0x4A, ++0x1A, 0x60, 0x04, 0xF0, 0x87, 0xFC, 0x23, 0x6A, 0x22, 0x48, 0x98, 0x47, 0x63, 0x6A, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, ++0x1D, 0x4B, 0x20, 0x49, 0x20, 0x4A, 0x19, 0x60, 0x13, 0x4D, 0x42, 0xF2, 0x34, 0x03, 0x00, 0x21, 0xD1, 0x52, 0x04, 0xF0, ++0x1B, 0xF8, 0x03, 0xF0, 0x35, 0xFF, 0xAB, 0x69, 0x18, 0x48, 0x98, 0x47, 0xEB, 0x69, 0x98, 0x47, 0x04, 0xF0, 0x1A, 0xFC, ++0x23, 0x68, 0x1B, 0x78, 0xCA, 0xE7, 0x12, 0x4B, 0x09, 0x4D, 0x16, 0x4A, 0x1A, 0x60, 0x00, 0xF0, 0xCB, 0xFE, 0x00, 0xF0, ++0xE9, 0xFE, 0x00, 0xF0, 0x13, 0xFF, 0xAB, 0x68, 0x0E, 0x48, 0x98, 0x47, 0xEB, 0x68, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, ++0xB6, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x28, 0x58, 0x17, 0x00, 0xA1, 0xA9, 0x12, 0x00, 0x85, 0xA9, 0x12, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x3D, 0xB2, 0x12, 0x00, 0x29, 0xB2, 0x12, 0x00, 0x0D, 0x7A, 0x12, 0x00, 0xF9, 0x79, 0x12, 0x00, ++0x1C, 0x58, 0x17, 0x00, 0xBC, 0x60, 0x17, 0x00, 0xB8, 0x7F, 0x15, 0x00, 0xA4, 0x60, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x28, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x0B, 0x4C, 0x50, 0x22, 0x51, 0x23, 0x04, 0xF2, 0x14, 0x50, 0xA4, 0xF8, 0x10, 0x25, ++0x84, 0xF8, 0x12, 0x35, 0x1C, 0xF0, 0xD8, 0xFC, 0x27, 0x22, 0x28, 0x23, 0x04, 0xF5, 0xF4, 0x60, 0xA4, 0xF8, 0x9C, 0x27, ++0x84, 0xF8, 0x9E, 0x37, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0xF0, 0xCC, 0xBC, 0x58, 0x58, 0x17, 0x00, 0x70, 0xB5, 0x41, 0xF6, ++0x10, 0x02, 0x25, 0x4D, 0x25, 0x4C, 0x4C, 0xF2, 0xBF, 0x03, 0x41, 0xF6, 0x12, 0x00, 0x00, 0x26, 0xAB, 0x52, 0x41, 0xF6, ++0x14, 0x01, 0x05, 0xF5, 0xC1, 0x52, 0xA5, 0xF8, 0x00, 0x3C, 0x2E, 0x54, 0x05, 0xF6, 0x08, 0x40, 0x6E, 0x50, 0x16, 0x70, ++0x85, 0xF8, 0x02, 0x6C, 0xC5, 0xF8, 0x04, 0x6C, 0x1C, 0xF0, 0xAE, 0xFC, 0xA4, 0xF1, 0x0C, 0x00, 0x1C, 0xF0, 0xAA, 0xFC, ++0x04, 0xF5, 0x00, 0x60, 0x1C, 0xF0, 0xA6, 0xFC, 0x04, 0xF6, 0x08, 0x00, 0x1C, 0xF0, 0xA2, 0xFC, 0x42, 0xF2, 0x34, 0x03, ++0x31, 0x46, 0x4F, 0xF4, 0x00, 0x62, 0x20, 0x46, 0xEE, 0x52, 0x85, 0xF8, 0x02, 0x6C, 0xC5, 0xF8, 0x04, 0x6C, 0xF9, 0xF7, ++0x05, 0xFC, 0x04, 0xF5, 0x00, 0x65, 0x2E, 0x46, 0x21, 0x46, 0x30, 0x46, 0x10, 0x34, 0x1C, 0xF0, 0x91, 0xFC, 0xAC, 0x42, ++0xF8, 0xD1, 0x09, 0x4A, 0x00, 0x21, 0x02, 0xF5, 0xB4, 0x70, 0xA2, 0xF1, 0x24, 0x03, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, ++0xFB, 0xD1, 0x03, 0xF1, 0x24, 0x02, 0x82, 0x42, 0xF5, 0xD1, 0x70, 0xBD, 0x7C, 0x36, 0x17, 0x00, 0xA0, 0x4E, 0x17, 0x00, ++0xD8, 0x56, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x40, 0x20, 0x85, 0xB0, 0x1C, 0xF0, 0xF6, 0xFB, 0xA7, 0x4B, 0x9B, 0x68, ++0x03, 0x93, 0x00, 0x2B, 0x00, 0xF0, 0x80, 0x81, 0xDF, 0xF8, 0xB0, 0x92, 0xDF, 0xF8, 0xB0, 0xB2, 0x09, 0xE0, 0x94, 0xF8, ++0x64, 0x30, 0x63, 0xB1, 0x03, 0x9B, 0x1B, 0x68, 0x03, 0x93, 0x03, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0x71, 0x81, 0x03, 0x9C, ++0x20, 0x46, 0x07, 0xF0, 0x33, 0xFF, 0x00, 0x28, 0xEF, 0xD0, 0x03, 0x9B, 0x9A, 0x4C, 0x03, 0xF5, 0xA3, 0x65, 0x01, 0x26, ++0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0x60, 0x23, 0x68, 0x28, 0x46, 0x01, 0x33, ++0x23, 0x60, 0x1C, 0xF0, 0x8B, 0xFC, 0x23, 0x68, 0x5A, 0x1E, 0x2B, 0xB1, 0xD9, 0xF8, 0x00, 0x30, 0x22, 0x60, 0x0A, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x05, 0x21, 0x38, 0xB1, 0xDB, 0xF8, 0x24, 0x34, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, ++0xE7, 0xD4, 0xE3, 0xE7, 0x89, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0xC8, 0xD1, 0xDD, 0xF8, 0x0C, 0xA0, 0x87, 0x4E, ++0x04, 0x23, 0x01, 0x93, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, 0x00, 0xF0, 0x8C, 0x80, 0x9D, 0xF8, 0x04, 0x70, 0x0A, 0xF5, ++0xA2, 0x68, 0x40, 0x46, 0x1C, 0xF0, 0x62, 0xFC, 0x80, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, ++0x43, 0x7F, 0x7F, 0xDB, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x62, 0x92, 0xF8, 0x25, 0x10, 0x19, 0xB9, 0xE9, 0x8B, ++0x08, 0x07, 0x40, 0xF1, 0x07, 0x81, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x62, 0x92, 0xF8, 0x24, 0x20, 0x01, 0x2A, ++0x00, 0xF0, 0x9E, 0x80, 0xDB, 0xF8, 0x24, 0x34, 0x28, 0x46, 0x39, 0x46, 0x98, 0x47, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, ++0xD7, 0xD1, 0x0A, 0xF5, 0x9D, 0x65, 0xA8, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, ++0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0xDA, 0xF8, 0xE8, 0x14, 0x5A, 0x1C, 0x22, 0x60, 0x2A, 0xB1, 0xD9, 0xF8, 0x00, 0x20, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x00, 0x29, 0x34, 0xD0, 0x4A, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x02, 0x63, 0x93, 0xF8, 0x25, 0x00, 0x00, 0x28, 0x00, 0xF0, 0x87, 0x80, 0x93, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x46, 0xD0, ++0xC9, 0x7E, 0xDB, 0xF8, 0x34, 0x31, 0x10, 0x46, 0x98, 0x47, 0x00, 0x28, 0x00, 0xF0, 0xD7, 0x80, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x40, 0x46, 0x01, 0x33, 0x23, 0x60, ++0x1C, 0xF0, 0x00, 0xFC, 0x23, 0x68, 0x05, 0x46, 0x33, 0xB1, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0xDB, 0xF8, 0x24, 0x34, 0x39, 0x46, 0x28, 0x46, 0x98, 0x47, 0x00, 0x2D, 0xB4, 0xD1, 0x01, 0x9B, ++0x01, 0x3B, 0x1D, 0x46, 0x38, 0x46, 0x01, 0x93, 0x0B, 0xF0, 0x26, 0xFA, 0x2B, 0x46, 0x01, 0x33, 0xAA, 0xF1, 0x08, 0x0A, ++0x3F, 0xF4, 0x38, 0xAF, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, 0x7F, 0xF4, 0x74, 0xAF, 0x9D, 0xF8, 0x04, 0x70, 0x9C, 0xE7, ++0x09, 0x2B, 0x7F, 0xF6, 0x7D, 0xAF, 0x3C, 0x49, 0x3C, 0x48, 0x4F, 0xF4, 0x96, 0x72, 0x1D, 0xF0, 0xE1, 0xFF, 0x6B, 0x7F, ++0x74, 0xE7, 0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x02, 0x92, ++0x01, 0x33, 0x40, 0x46, 0x23, 0x60, 0x1C, 0xF0, 0xC1, 0xFB, 0x23, 0x68, 0x02, 0x9A, 0x05, 0x46, 0x33, 0xB1, 0x01, 0x3B, ++0xD9, 0xF8, 0x00, 0x10, 0x23, 0x60, 0x0B, 0xB9, 0x01, 0xB1, 0x62, 0xB6, 0x01, 0x9B, 0x4F, 0x20, 0x00, 0xFB, 0x02, 0x30, ++0x41, 0x30, 0x06, 0xEB, 0xC0, 0x00, 0x29, 0x46, 0x1C, 0xF0, 0x68, 0xFB, 0x00, 0x2D, 0x7F, 0xF4, 0x6F, 0xAF, 0xB8, 0xE7, ++0x23, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x4D, 0xDB, 0xEA, 0x8B, 0xD2, 0x07, 0x7F, 0xF5, 0x5D, 0xAF, ++0x01, 0x9A, 0x4F, 0x20, 0x46, 0x32, 0x10, 0xFB, 0x03, 0x20, 0x29, 0x46, 0x06, 0xEB, 0xC0, 0x00, 0x1C, 0xF0, 0x50, 0xFB, ++0x51, 0xE7, 0x93, 0xF8, 0x23, 0x10, 0x1B, 0x48, 0x1D, 0xF0, 0x24, 0xFD, 0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x01, 0x23, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x40, 0x46, 0x01, 0x33, 0x23, 0x60, 0x1C, 0xF0, 0x80, 0xFB, ++0x4F, 0xF0, 0x00, 0x42, 0x39, 0x46, 0x05, 0x46, 0x28, 0xF0, 0x2A, 0xFE, 0x23, 0x68, 0x00, 0x2B, 0x85, 0xD0, 0x01, 0x3B, ++0xD9, 0xF8, 0x00, 0x20, 0x23, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0x7F, 0xAF, 0x00, 0x2A, 0x3F, 0xF4, 0x7C, 0xAF, 0x62, 0xB6, ++0x00, 0x2D, 0x7F, 0xF4, 0x2F, 0xAF, 0x78, 0xE7, 0x00, 0x88, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x50, 0x7F, 0x15, 0x00, 0x7C, 0x7F, 0x15, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xEA, 0x8B, 0xD1, 0x07, 0xB2, 0xD4, 0x11, 0x49, 0x11, 0x48, 0x02, 0x93, ++0x40, 0xF2, 0x35, 0x12, 0x1D, 0xF0, 0x5A, 0xFF, 0x02, 0x9B, 0xA5, 0xE7, 0x92, 0xF8, 0x23, 0x10, 0x0D, 0x48, 0x1D, 0xF0, ++0xD9, 0xFC, 0x28, 0x46, 0x4F, 0xF0, 0x00, 0x42, 0x39, 0x46, 0x28, 0xF0, 0xED, 0xFD, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, ++0x7F, 0xF4, 0xD3, 0xAE, 0xF9, 0xE6, 0x07, 0x4A, 0x01, 0x23, 0x82, 0xF8, 0x00, 0x32, 0x42, 0xE7, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0x8C, 0x7F, 0x15, 0x00, 0x7C, 0x7F, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, 0x07, 0xD0, 0x06, 0x4B, 0xD3, 0xF8, 0x30, 0x31, ++0x18, 0x47, 0x04, 0x4B, 0xD3, 0xF8, 0x08, 0x33, 0x18, 0x47, 0x03, 0xF0, 0x8F, 0xBF, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x03, 0xD1, 0x06, 0x4B, ++0xD3, 0xF8, 0x34, 0x34, 0x18, 0x47, 0x04, 0xF0, 0x93, 0xBB, 0x03, 0x4B, 0xD3, 0xF8, 0x00, 0x33, 0x18, 0x47, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x07, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, ++0x01, 0xD0, 0x04, 0xF0, 0x83, 0xBB, 0x04, 0xF0, 0x7B, 0xB8, 0x03, 0x4B, 0xD3, 0xF8, 0x0C, 0x33, 0x18, 0x47, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, ++0x03, 0xD1, 0x06, 0x4B, 0xD3, 0xF8, 0x38, 0x34, 0x18, 0x47, 0x04, 0xF0, 0x6D, 0xBB, 0x03, 0x4B, 0xD3, 0xF8, 0x04, 0x33, ++0x18, 0x47, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, ++0x05, 0xD0, 0x02, 0x2B, 0x01, 0xD0, 0x04, 0xF0, 0x5D, 0xBB, 0x04, 0xF0, 0xAD, 0xB9, 0x01, 0xF0, 0x6B, 0xB9, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x08, 0xB5, 0x0C, 0x22, 0x08, 0x23, 0x01, 0x21, 0x40, 0xF2, 0x0D, 0x40, 0x1B, 0xF0, 0xE6, 0xFD, ++0xBD, 0xE8, 0x08, 0x40, 0x1B, 0xF0, 0x12, 0xBE, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x82, 0x46, 0x00, 0x68, 0x05, 0x91, ++0x03, 0x90, 0x07, 0x92, 0x62, 0xB1, 0xB0, 0xFB, 0xF2, 0xF3, 0x11, 0x46, 0x02, 0xFB, 0x13, 0x02, 0x0B, 0x46, 0x00, 0x2A, ++0x40, 0xF0, 0xDE, 0x80, 0x03, 0x9A, 0x04, 0x3B, 0x1A, 0x44, 0x03, 0x92, 0x9A, 0xF8, 0x08, 0x30, 0x00, 0x2B, 0x00, 0xF0, ++0xD2, 0x80, 0x00, 0x23, 0xDF, 0xF8, 0xC0, 0x81, 0xDF, 0xF8, 0xC0, 0x91, 0x00, 0x93, 0x1F, 0x46, 0xD3, 0x46, 0x08, 0xE0, ++0x00, 0x9B, 0x9B, 0xF8, 0x08, 0x20, 0x01, 0x33, 0xDF, 0xB2, 0xBA, 0x42, 0x00, 0x93, 0x40, 0xF2, 0xC0, 0x80, 0x05, 0x9B, ++0xDB, 0xF8, 0x0C, 0x10, 0x33, 0xF8, 0x27, 0x00, 0x03, 0xEB, 0x87, 0x02, 0x00, 0x24, 0x55, 0x88, 0x07, 0xEB, 0x47, 0x02, ++0x01, 0xEB, 0x82, 0x06, 0x41, 0xF8, 0x22, 0x40, 0xB4, 0x80, 0x00, 0x2D, 0xE4, 0xD0, 0x03, 0x1D, 0x01, 0x93, 0x03, 0x9B, ++0x75, 0x80, 0x03, 0xF1, 0x04, 0x0A, 0x02, 0x95, 0xB0, 0x80, 0x55, 0x46, 0xCD, 0xF8, 0x18, 0xB0, 0xA2, 0x46, 0x04, 0x97, ++0x34, 0xE0, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x37, 0xD3, 0x04, 0x9B, 0x05, 0xF8, 0x04, 0x3C, 0xD8, 0xF8, ++0x00, 0x30, 0xAB, 0x42, 0x41, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x3C, 0xD3, 0x55, 0x23, 0x05, 0xF8, ++0x03, 0x3C, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x46, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x41, 0xD3, ++0x00, 0x23, 0x05, 0xF8, 0x02, 0x3C, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x4B, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, ++0xAB, 0x42, 0x46, 0xD3, 0xCB, 0xF8, 0x04, 0x70, 0x33, 0x88, 0x01, 0x99, 0x01, 0x33, 0x01, 0x34, 0x33, 0x80, 0x02, 0x9B, ++0xA2, 0xB2, 0x93, 0x42, 0x0D, 0x44, 0x48, 0xD9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x57, 0x46, 0xA5, 0xF1, 0x04, 0x0B, ++0xAA, 0x46, 0xC2, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, ++0xBE, 0xD2, 0x31, 0x48, 0x29, 0x46, 0xFF, 0xF7, 0xE9, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0xBD, 0xD9, 0xD9, 0xF8, ++0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0xB9, 0xD2, 0x29, 0x48, 0x29, 0x46, ++0xFF, 0xF7, 0xD8, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0xB8, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, ++0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0xB4, 0xD2, 0x22, 0x48, 0x29, 0x46, 0xFF, 0xF7, 0xC7, 0xF9, 0xD8, 0xF8, ++0x00, 0x30, 0xAB, 0x42, 0xB3, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, ++0xAB, 0x42, 0xAF, 0xD2, 0x29, 0x46, 0x1A, 0x48, 0xFF, 0xF7, 0xB6, 0xF9, 0xAC, 0xE7, 0x0A, 0x46, 0x5D, 0x1E, 0x03, 0x99, ++0xDD, 0xF8, 0x18, 0xB0, 0xAD, 0xB2, 0x05, 0xFB, 0x02, 0x13, 0x05, 0xFB, 0x02, 0x25, 0x48, 0x19, 0x07, 0x99, 0x03, 0x90, ++0x04, 0x33, 0xB3, 0x60, 0x00, 0x29, 0x3F, 0xF4, 0x47, 0xAF, 0xB0, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, 0x13, 0x02, 0x0B, 0x46, ++0x22, 0xB1, 0x8B, 0x1A, 0x03, 0x2B, 0x9C, 0xBF, 0x0A, 0x46, 0x9B, 0x18, 0x03, 0x9A, 0x04, 0x3B, 0x1A, 0x44, 0x03, 0x92, ++0x36, 0xE7, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x8B, 0x1A, 0x03, 0x2B, 0x9C, 0xBF, 0x0A, 0x46, 0x9B, 0x18, 0x1B, 0xE7, ++0xE0, 0x7F, 0x15, 0x00, 0x10, 0x80, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, 0x64, 0x80, 0x15, 0x00, 0xC8, 0x25, 0x17, 0x00, ++0xE4, 0x25, 0x17, 0x00, 0xF8, 0xB5, 0x06, 0x7A, 0x00, 0x2E, 0x00, 0xF0, 0xBC, 0x80, 0xC5, 0x68, 0x00, 0x2D, 0x00, 0xF0, ++0x82, 0x80, 0x2C, 0x46, 0x01, 0x23, 0x09, 0xE0, 0x22, 0x88, 0xA2, 0xB9, 0x9E, 0x42, 0x0F, 0xD9, 0x03, 0xEB, 0x43, 0x04, ++0x05, 0xEB, 0x84, 0x04, 0x01, 0x33, 0xDB, 0xB2, 0xA0, 0x88, 0x88, 0x42, 0x03, 0xEB, 0x43, 0x02, 0xF0, 0xD2, 0x9E, 0x42, ++0x02, 0xD9, 0x05, 0xEB, 0x82, 0x04, 0xF3, 0xE7, 0x9E, 0x42, 0x00, 0xF0, 0x9E, 0x80, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x4E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x4E, 0x4E, 0x23, 0x88, 0x35, 0x68, 0x6A, 0x1C, 0x32, 0x60, ++0x00, 0x2B, 0x5D, 0xD0, 0x4B, 0x4F, 0xA5, 0x68, 0x3A, 0x68, 0xAA, 0x42, 0x28, 0xD8, 0x79, 0x68, 0x11, 0x44, 0x8D, 0x42, ++0x24, 0xD8, 0x29, 0x68, 0xA1, 0x60, 0x01, 0x3B, 0xAA, 0x42, 0x23, 0x80, 0x32, 0xD8, 0x7B, 0x68, 0x13, 0x44, 0xAB, 0x42, ++0x2E, 0xD3, 0x15, 0xF8, 0x03, 0x1C, 0x55, 0x29, 0x53, 0xD1, 0xAA, 0x23, 0x05, 0xF8, 0x03, 0x3C, 0x3B, 0x68, 0x9D, 0x42, ++0x5D, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9D, 0x42, 0x59, 0xD8, 0x01, 0x23, 0x05, 0xF8, 0x02, 0x3C, 0x33, 0x68, 0x00, 0x2B, ++0x34, 0xD0, 0x36, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x7B, 0xBB, 0x72, 0xB3, 0x35, 0xE0, 0x35, 0x48, 0x01, 0x68, ++0x8D, 0x42, 0x03, 0xD3, 0x40, 0x68, 0x01, 0x44, 0x8D, 0x42, 0xD2, 0xD9, 0x29, 0x46, 0x32, 0x48, 0xFF, 0xF7, 0x12, 0xF9, ++0x23, 0x88, 0x3A, 0x68, 0x00, 0x21, 0x01, 0x3B, 0xAA, 0x42, 0xA1, 0x60, 0x23, 0x80, 0xCC, 0xD9, 0x2B, 0x48, 0x03, 0x68, ++0xAB, 0x42, 0x1F, 0xD8, 0x41, 0x68, 0x19, 0x44, 0xA9, 0x42, 0x1B, 0xD3, 0x15, 0xF8, 0x03, 0x1C, 0x55, 0x29, 0x1C, 0xD1, ++0xAA, 0x42, 0x37, 0xD9, 0x42, 0x68, 0x13, 0x44, 0x9D, 0x42, 0xC2, 0xD9, 0x29, 0x46, 0x24, 0x48, 0xFF, 0xF7, 0xF4, 0xF8, ++0xC0, 0xE7, 0x23, 0x48, 0xFF, 0xF7, 0xF0, 0xF8, 0x28, 0x46, 0xF8, 0xBD, 0xC2, 0xB1, 0x1A, 0x4B, 0x35, 0x60, 0x1B, 0x68, ++0xA5, 0xB9, 0x9B, 0xB1, 0x62, 0xB6, 0xF5, 0xE7, 0x29, 0x46, 0x1D, 0x48, 0xFF, 0xF7, 0xE2, 0xF8, 0x00, 0x21, 0x33, 0x68, ++0x33, 0xB1, 0x13, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x17, 0x48, 0x2A, 0x46, ++0xFF, 0xF7, 0xD4, 0xF8, 0x00, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x0F, 0x4A, 0x13, 0x68, 0x9D, 0x42, 0x03, 0xD3, 0x52, 0x68, ++0x13, 0x44, 0x9D, 0x42, 0x9D, 0xD9, 0x29, 0x46, 0x10, 0x48, 0xFF, 0xF7, 0xC5, 0xF8, 0x9B, 0xE7, 0x79, 0x68, 0x0A, 0x44, ++0x95, 0x42, 0x8A, 0xD9, 0x9D, 0x42, 0xC5, 0xD3, 0xC0, 0xE7, 0x0C, 0x48, 0xFF, 0xF7, 0xBA, 0xF8, 0x00, 0x25, 0xC7, 0xE7, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xCC, 0x80, 0x15, 0x00, ++0x10, 0x80, 0x15, 0x00, 0x98, 0x80, 0x15, 0x00, 0x00, 0x81, 0x15, 0x00, 0x28, 0x81, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, ++0xB4, 0x80, 0x15, 0x00, 0x00, 0x29, 0x00, 0xF0, 0x0F, 0x81, 0x2D, 0xE9, 0xF8, 0x43, 0x03, 0x68, 0x8B, 0x42, 0x05, 0x46, ++0x0C, 0x46, 0x59, 0xD8, 0x42, 0x68, 0x13, 0x44, 0x99, 0x42, 0x55, 0xD8, 0x83, 0x4F, 0x3B, 0x68, 0x99, 0x42, 0x55, 0xD3, ++0x7A, 0x68, 0x13, 0x44, 0x99, 0x42, 0x51, 0xD8, 0x14, 0xF8, 0x04, 0x6C, 0x2B, 0x7A, 0xB3, 0x42, 0x48, 0xD9, 0xD5, 0xF8, ++0x0C, 0x80, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x7A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x7A, 0x4D, ++0x38, 0x68, 0x2B, 0x68, 0x84, 0x42, 0x03, 0xF1, 0x01, 0x03, 0x2B, 0x60, 0x25, 0xD3, 0x7B, 0x68, 0x03, 0x44, 0x9C, 0x42, ++0x21, 0xD8, 0x14, 0xF8, 0x03, 0x9C, 0xB9, 0xF1, 0xAA, 0x0F, 0x00, 0xF0, 0xAB, 0x80, 0xB9, 0xF1, 0xFF, 0x0F, 0x20, 0xD1, ++0x7B, 0x68, 0x18, 0x44, 0x84, 0x42, 0x00, 0xF2, 0xA1, 0x80, 0x14, 0xF8, 0x02, 0x0C, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0xF8, ++0x02, 0x0C, 0x00, 0x28, 0x47, 0xD0, 0x2B, 0x68, 0x33, 0xB1, 0x67, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x40, 0xB2, 0xBD, 0xE8, 0xF8, 0x83, 0x64, 0x4B, 0x1A, 0x68, 0x94, 0x42, 0x1E, 0xD2, 0x63, 0x48, ++0x21, 0x46, 0xFF, 0xF7, 0x47, 0xF8, 0x2B, 0x68, 0x33, 0xB1, 0x5D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x4F, 0xF0, 0xFF, 0x30, 0xBD, 0xE8, 0xF8, 0x83, 0x59, 0x4B, 0x1A, 0x68, 0x94, 0x42, 0x03, 0xD3, ++0x5B, 0x68, 0x1A, 0x44, 0x94, 0x42, 0xA5, 0xD9, 0x57, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0x2E, 0xF8, 0x00, 0x26, 0xA1, 0xE7, ++0x59, 0x68, 0x11, 0x44, 0x8C, 0x42, 0xDC, 0xD8, 0x14, 0xF8, 0x03, 0x9C, 0xB9, 0xF1, 0xAA, 0x0F, 0x6C, 0xD0, 0xB9, 0xF1, ++0xFF, 0x0F, 0xD8, 0xD1, 0x84, 0x42, 0xB5, 0xD2, 0x1A, 0x68, 0x94, 0x42, 0x03, 0xD3, 0x5B, 0x68, 0x1A, 0x44, 0x94, 0x42, ++0xB3, 0xD9, 0x4B, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0x13, 0xF8, 0xB9, 0xF1, 0xFF, 0x0F, 0x5D, 0xD0, 0x06, 0xEB, 0x46, 0x06, ++0x08, 0xEB, 0x86, 0x09, 0x38, 0xF8, 0x26, 0x20, 0xB9, 0xF8, 0x02, 0x30, 0x9A, 0x42, 0x4F, 0xEA, 0x86, 0x06, 0xBC, 0xD2, ++0x3B, 0x68, 0x9C, 0x42, 0x31, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x2D, 0xD8, 0x55, 0x23, 0x04, 0xF8, 0x03, 0x3C, ++0x3B, 0x68, 0x9C, 0x42, 0x1A, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x16, 0xD8, 0xD9, 0xF8, 0x08, 0x30, 0x23, 0x60, ++0x38, 0xF8, 0x06, 0x30, 0x28, 0x68, 0xC9, 0xF8, 0x08, 0x40, 0x01, 0x33, 0x28, 0xF8, 0x06, 0x30, 0x38, 0xB1, 0x2E, 0x4B, ++0x01, 0x38, 0x1B, 0x68, 0x28, 0x60, 0x10, 0xB9, 0x0B, 0xB1, 0x62, 0xB6, 0xA2, 0xE7, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, ++0x2A, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, 0xE0, 0xD9, 0x21, 0x46, 0x2A, 0x48, ++0xFE, 0xF7, 0xD0, 0xFF, 0xDE, 0xE7, 0x24, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, ++0xC9, 0xD9, 0x21, 0x46, 0x24, 0x48, 0xFE, 0xF7, 0xC3, 0xFF, 0xC7, 0xE7, 0x1D, 0x4B, 0xA1, 0xE7, 0x14, 0xF8, 0x02, 0x0C, ++0x01, 0x38, 0xC0, 0xB2, 0x04, 0xF8, 0x02, 0x0C, 0x00, 0x28, 0x7F, 0xF4, 0x5C, 0xAF, 0xA5, 0xE7, 0x84, 0x42, 0xBF, 0xF4, ++0x4B, 0xAF, 0x96, 0xE7, 0x3B, 0x68, 0x9C, 0x42, 0x11, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x0D, 0xD8, 0x01, 0x23, ++0x04, 0xF8, 0x02, 0x3C, 0x2B, 0x68, 0x33, 0xB1, 0x0D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x01, 0x20, 0x60, 0xE7, 0x0B, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, ++0xE9, 0xD9, 0x21, 0x46, 0x0C, 0x48, 0xFE, 0xF7, 0x91, 0xFF, 0xE7, 0xE7, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0x47, 0x00, 0xBF, ++0xC8, 0x25, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x00, 0x81, 0x15, 0x00, ++0x50, 0x81, 0x15, 0x00, 0x80, 0x81, 0x15, 0x00, 0x64, 0x80, 0x15, 0x00, 0x10, 0x80, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, ++0x0B, 0x4A, 0x13, 0x68, 0x83, 0x42, 0x05, 0xD8, 0x52, 0x68, 0x13, 0x44, 0x98, 0x42, 0x01, 0xD8, 0x01, 0x20, 0x70, 0x47, ++0x07, 0x4A, 0x13, 0x68, 0x98, 0x42, 0x06, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x98, 0x42, 0x8C, 0xBF, 0x00, 0x20, 0x01, 0x20, ++0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0xC8, 0x25, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x10, 0x4B, 0x70, 0xB5, ++0x10, 0x4C, 0xDC, 0x60, 0x15, 0x46, 0x0E, 0x46, 0x03, 0x24, 0x01, 0x46, 0x20, 0x22, 0x18, 0x46, 0x5D, 0x60, 0x1C, 0x72, ++0x1E, 0x60, 0xFF, 0xF7, 0xCD, 0xFC, 0x0B, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x01, 0x21, 0x4F, 0xF0, 0x02, 0x15, 0x04, 0x24, ++0x4F, 0xF4, 0x80, 0x20, 0x5A, 0x60, 0x00, 0x22, 0xC3, 0xE9, 0x05, 0x40, 0xDD, 0x60, 0x19, 0x60, 0x99, 0x60, 0x1A, 0x61, ++0x9A, 0x83, 0x70, 0xBD, 0xE4, 0x25, 0x17, 0x00, 0xF4, 0x25, 0x17, 0x00, 0xA8, 0x25, 0x17, 0x00, 0x38, 0xB5, 0x0F, 0x4B, ++0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0x46, 0x0D, 0xD0, 0x0D, 0x48, 0x7C, 0x21, 0xFF, 0xF7, 0xAB, 0xFD, 0x04, 0x46, ++0x2C, 0xB1, 0x20, 0x46, 0xFF, 0xF7, 0xAC, 0xFF, 0x38, 0xB1, 0x04, 0xF8, 0x01, 0x5C, 0x20, 0x46, 0x38, 0xBD, 0x00, 0xF0, ++0xC3, 0xF9, 0x04, 0x46, 0xF2, 0xE7, 0x21, 0x46, 0x04, 0x48, 0xFE, 0xF7, 0x17, 0xFF, 0x20, 0x46, 0x38, 0xBD, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xAC, 0x81, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0xFF, 0xF7, 0x92, 0xFF, ++0x98, 0xB1, 0x31, 0x4B, 0x14, 0xF8, 0x04, 0x2C, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x23, 0xD0, 0x02, 0x2B, 0x2A, 0xD0, ++0x03, 0x2B, 0x15, 0xD1, 0x2C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x30, 0xDB, 0x02, 0x2A, 0x30, 0xD0, ++0x10, 0xBD, 0x29, 0x48, 0x21, 0x46, 0xFE, 0xF7, 0xF1, 0xFE, 0x25, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x11, 0xD0, ++0x02, 0x2B, 0x18, 0xD0, 0x03, 0x2B, 0x29, 0xD0, 0x20, 0x46, 0xFF, 0xF7, 0x6D, 0xFF, 0x90, 0xB3, 0x21, 0x46, 0x21, 0x48, ++0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x3C, 0xBE, 0x02, 0x2A, 0x0F, 0xD0, 0x00, 0x2A, 0xE3, 0xD1, 0x20, 0x46, 0xBD, 0xE8, ++0x10, 0x40, 0x00, 0xF0, 0x9B, 0xB9, 0x02, 0x2A, 0x26, 0xD0, 0x00, 0x2A, 0xDA, 0xD1, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, ++0x03, 0xF0, 0xF2, 0xB9, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x45, 0xB9, 0x02, 0x2A, 0x0C, 0xD1, 0x13, 0x4B, ++0x20, 0x46, 0xD3, 0xF8, 0xE8, 0x34, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC1, 0xDA, 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x49, 0x0D, 0x48, 0xBE, 0x22, 0x1D, 0xF0, 0xF5, 0xBA, 0x21, 0x46, ++0x0B, 0x48, 0xFE, 0xF7, 0xAD, 0xFE, 0xC7, 0xE7, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x03, 0xF0, 0x21, 0xB9, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x50, 0x81, 0x15, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xD4, 0x81, 0x15, 0x00, 0xE4, 0x81, 0x15, 0x00, 0x30, 0xB5, 0x1A, 0x4C, 0x1A, 0x4A, 0x23, 0x68, ++0x1A, 0x48, 0x5D, 0x88, 0x99, 0x88, 0xB2, 0xF8, 0xD4, 0x20, 0x85, 0xB0, 0x04, 0x3A, 0xAD, 0xF8, 0x02, 0x50, 0xDD, 0x88, ++0xAD, 0xF8, 0x06, 0x10, 0x19, 0x89, 0xAD, 0xF8, 0x0A, 0x50, 0xD3, 0xE9, 0x05, 0x35, 0xAD, 0xF8, 0x0E, 0x10, 0x01, 0x21, ++0x03, 0x60, 0x01, 0x72, 0x10, 0x4B, 0x45, 0x60, 0x0C, 0x21, 0xC3, 0x60, 0xAD, 0xF8, 0x0C, 0x20, 0x40, 0xF2, 0x3C, 0x63, ++0xAD, 0xF8, 0x00, 0x10, 0x7C, 0x25, 0x69, 0x46, 0x20, 0x22, 0xAD, 0xF8, 0x08, 0x30, 0xAD, 0xF8, 0x04, 0x50, 0xFF, 0xF7, ++0xE9, 0xFB, 0x23, 0x68, 0x01, 0xA8, 0xD3, 0xE9, 0x07, 0x12, 0xFF, 0xF7, 0x07, 0xFF, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, 0xD8, 0x25, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, ++0x0C, 0x48, 0x1B, 0xF0, 0x3F, 0xFE, 0x2B, 0x68, 0x5B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, 0x00, 0x24, 0x0C, 0x21, ++0x38, 0x46, 0xFF, 0xF7, 0xCB, 0xFC, 0x01, 0x46, 0x30, 0x46, 0x1B, 0xF0, 0x35, 0xFE, 0x2B, 0x68, 0x01, 0x34, 0x5A, 0x88, ++0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, 0x78, 0x36, 0x17, 0x00, 0x08, 0x60, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x4C, 0x80, 0x0F, 0x48, 0x1B, 0xF0, 0x1D, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0x1B, 0x89, ++0xB3, 0xB1, 0x0D, 0x4D, 0x0D, 0x4F, 0x0B, 0x4E, 0x00, 0x24, 0x4F, 0xF4, 0xD7, 0x61, 0x38, 0x46, 0xFF, 0xF7, 0xA6, 0xFC, ++0x01, 0x46, 0x30, 0x46, 0x1B, 0xF0, 0x10, 0xFE, 0xD8, 0xF8, 0x00, 0x20, 0x2B, 0x68, 0x11, 0x89, 0x01, 0x34, 0xA2, 0xB2, ++0x01, 0x33, 0x91, 0x42, 0x2B, 0x60, 0xEC, 0xD8, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x60, 0x17, 0x00, 0x18, 0x26, 0x17, 0x00, ++0xE4, 0x25, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, 0x0C, 0x48, 0x1B, 0xF0, 0xF3, 0xFD, 0x2B, 0x68, ++0x9B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, 0x00, 0x24, 0x7C, 0x21, 0x38, 0x46, 0xFF, 0xF7, 0x7F, 0xFC, 0x01, 0x46, ++0x30, 0x46, 0x1B, 0xF0, 0xE9, 0xFD, 0x2B, 0x68, 0x01, 0x34, 0x9A, 0x88, 0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, ++0x78, 0x36, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, ++0x1B, 0xF0, 0x10, 0xFE, 0x23, 0x68, 0x33, 0xB1, 0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x08, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, ++0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0xAB, 0xFD, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x08, 0x60, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x0C, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0xCE, 0xFD, 0x18, 0xB1, 0x0A, 0x4A, ++0x13, 0x68, 0x01, 0x3B, 0x13, 0x60, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x60, 0x17, 0x00, ++0x18, 0x26, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0x61, 0xFD, 0x0A, 0x49, ++0x23, 0x68, 0x0A, 0x68, 0x01, 0x32, 0x0A, 0x60, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x60, 0x17, 0x00, ++0x18, 0x26, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0x7E, 0xFD, 0x23, 0x68, 0x33, 0xB1, ++0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, ++0x19, 0xFD, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x41, 0x4B, 0xDF, 0xF8, 0x20, 0xB1, 0x1B, 0x68, 0x40, 0x4D, 0x1F, 0x8E, 0xDF, 0xF8, 0x18, 0x91, 0xDF, 0xF8, 0x18, 0x81, ++0x8B, 0x89, 0x0C, 0x46, 0x06, 0x46, 0x9F, 0x42, 0x6A, 0xD9, 0xD8, 0xF8, 0x00, 0x30, 0x04, 0x2B, 0x63, 0xD9, 0xD6, 0xE9, ++0x01, 0x03, 0x1B, 0x69, 0x98, 0x47, 0x82, 0x46, 0x00, 0x28, 0x62, 0xD0, 0xFF, 0xF7, 0x0E, 0xFF, 0x00, 0x28, 0x4A, 0xD0, ++0x00, 0x22, 0x34, 0x4B, 0x02, 0x60, 0x1B, 0x68, 0x42, 0x60, 0x53, 0x44, 0x82, 0x60, 0x03, 0x60, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x4A, 0xDB, 0xF8, 0x00, 0x30, 0xD2, 0xF8, ++0x00, 0xC0, 0x43, 0xF0, 0x01, 0x03, 0x0C, 0xF1, 0x01, 0x01, 0x11, 0x60, 0xCB, 0xF8, 0x00, 0x30, 0xDB, 0xF8, 0x00, 0x30, ++0x9B, 0x07, 0xFB, 0xD4, 0x2B, 0x68, 0x1B, 0xBB, 0xD9, 0xF8, 0x00, 0x30, 0xC9, 0xF8, 0x00, 0x00, 0x2B, 0x68, 0xB4, 0xF8, ++0x0C, 0xE0, 0x60, 0x60, 0x0E, 0xF1, 0x01, 0x0E, 0x98, 0xB2, 0x01, 0x30, 0x1F, 0xFA, 0x8E, 0xF3, 0xA3, 0x81, 0x28, 0x60, ++0xDB, 0xF8, 0x00, 0x00, 0x20, 0xF0, 0x01, 0x00, 0xCB, 0xF8, 0x00, 0x00, 0x00, 0x29, 0xB4, 0xD0, 0x18, 0x49, 0xC2, 0xF8, ++0x00, 0xC0, 0x0A, 0x68, 0xBC, 0xF1, 0x00, 0x0F, 0xAD, 0xD1, 0x00, 0x2A, 0xAB, 0xD0, 0x62, 0xB6, 0xA3, 0x89, 0xA8, 0xE7, ++0x63, 0x68, 0x00, 0x2B, 0xDC, 0xD0, 0x58, 0x60, 0xDA, 0xE7, 0x12, 0x48, 0xFE, 0xF7, 0xAA, 0xFC, 0xD6, 0xE9, 0x01, 0x03, ++0x51, 0x46, 0x5B, 0x69, 0x98, 0x47, 0x09, 0x4B, 0xA2, 0x89, 0x1B, 0x68, 0x5B, 0x8E, 0x9A, 0x42, 0x02, 0xD2, 0x04, 0x20, ++0x1B, 0xF0, 0xEA, 0xFB, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0xD8, 0xF8, 0x00, 0x10, 0x08, 0x48, 0xFE, 0xF7, 0x94, 0xFC, ++0xED, 0xE7, 0x00, 0xBF, 0xC8, 0x35, 0x17, 0x00, 0x64, 0x00, 0x24, 0x40, 0x34, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x24, 0x82, 0x15, 0x00, 0x0C, 0x82, 0x15, 0x00, 0x60, 0x00, 0x24, 0x40, 0x68, 0x00, 0x24, 0x40, ++0x18, 0x26, 0x17, 0x00, 0x08, 0xB5, 0x03, 0x4B, 0xD3, 0xF8, 0xF8, 0x32, 0x98, 0x47, 0x01, 0x20, 0x08, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0A, 0x4A, 0x0A, 0x49, 0x0B, 0x4C, 0x00, 0x23, 0xC2, 0xE9, 0x02, 0x03, 0xC2, 0xE9, ++0x04, 0x33, 0xC2, 0xE9, 0x00, 0x33, 0xC1, 0xE9, 0x00, 0x33, 0x8B, 0x81, 0x8B, 0x60, 0x8B, 0x73, 0x10, 0x46, 0xD4, 0xF8, ++0x10, 0x31, 0x98, 0x47, 0x01, 0x20, 0x10, 0xBD, 0x28, 0x60, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0xB9, 0x4B, 0xD3, 0xF8, 0x14, 0x35, 0x00, 0x2B, 0x00, 0xF0, 0x30, 0x81, 0xEF, 0xF3, ++0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0xB4, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xDF, 0xF8, 0x04, 0x93, 0xB1, 0x4B, ++0xD9, 0xF8, 0x00, 0x20, 0xD3, 0xF8, 0x14, 0x35, 0x51, 0x1C, 0xC9, 0xF8, 0x00, 0x10, 0x31, 0xB1, 0xAD, 0x49, 0xC9, 0xF8, ++0x00, 0x20, 0x09, 0x68, 0x0A, 0xB9, 0x01, 0xB1, 0x62, 0xB6, 0x93, 0xF8, 0x0C, 0xB0, 0x5A, 0x7B, 0x5C, 0x68, 0x05, 0x92, ++0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x38, 0x81, 0x00, 0x2C, 0x00, 0xF0, 0x35, 0x81, 0x9B, 0x68, 0x00, 0x2B, 0x00, 0xF0, ++0x31, 0x81, 0xA3, 0x4B, 0x07, 0x93, 0x9B, 0x89, 0x1F, 0xFA, 0x8B, 0xF2, 0x5B, 0x45, 0x06, 0x92, 0xC0, 0xF0, 0x5C, 0x81, ++0xDF, 0xF8, 0xB0, 0xA2, 0x00, 0x26, 0xAA, 0xE0, 0xD4, 0xE9, 0x00, 0x53, 0x03, 0x93, 0x6B, 0x1E, 0xB3, 0xF5, 0xE8, 0x1F, ++0x27, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x95, 0x4A, 0x01, 0x23, 0x13, 0x60, 0x03, 0x9B, ++0xD9, 0xF8, 0x00, 0x70, 0x01, 0x93, 0x23, 0x68, 0x93, 0x48, 0x00, 0x93, 0x5A, 0x46, 0x23, 0x46, 0x31, 0x46, 0x01, 0x37, ++0xC9, 0xF8, 0x00, 0x70, 0x1C, 0xF0, 0xC4, 0xFD, 0x4F, 0xF4, 0x80, 0x71, 0xA4, 0xF1, 0x80, 0x00, 0x1D, 0xF0, 0x9C, 0xF9, ++0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x88, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x20, 0x46, 0xFF, 0xF7, 0x1A, 0xFE, 0x6B, 0x7E, 0x2F, 0x7E, 0x09, 0x2B, 0x09, 0xD8, 0x83, 0x4A, 0x4F, 0xF4, ++0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x25, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xDD, 0x80, 0x6B, 0x8B, 0x13, 0xF0, ++0x08, 0x0F, 0x7E, 0x4B, 0x40, 0xF0, 0xBC, 0x80, 0x1A, 0x46, 0x04, 0x93, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x23, ++0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xCC, 0x80, 0x95, 0xF8, 0x16, 0x80, 0xB8, 0xF1, 0x05, 0x0F, 0x00, 0xF2, ++0x09, 0x81, 0x75, 0x4C, 0x75, 0x48, 0x1B, 0xF0, 0xF1, 0xFB, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, ++0xC0, 0xF2, 0xA5, 0x80, 0xE1, 0x8B, 0x71, 0x4B, 0xE2, 0x6C, 0x13, 0xF8, 0x08, 0xC0, 0x21, 0xF0, 0x01, 0x01, 0x00, 0x23, ++0xE1, 0x83, 0x63, 0x64, 0x13, 0x61, 0xE3, 0x62, 0x6B, 0x4B, 0x29, 0x46, 0x0C, 0xF1, 0x01, 0x0C, 0x1C, 0x22, 0x20, 0x1D, ++0x03, 0xF8, 0x08, 0xC0, 0x2F, 0xF0, 0x8A, 0xFA, 0xE1, 0x8B, 0xDA, 0xF8, 0x00, 0x00, 0x00, 0x23, 0x21, 0xF4, 0x00, 0x42, ++0x84, 0xF8, 0x42, 0x30, 0x22, 0xF0, 0x02, 0x02, 0x2D, 0x1A, 0x63, 0x62, 0x23, 0x65, 0x0B, 0x07, 0xE2, 0x83, 0xA5, 0x64, ++0x00, 0xF1, 0x87, 0x80, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, ++0x13, 0x44, 0x5A, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x02, 0x44, 0x41, 0xF8, 0x23, 0x20, ++0xA4, 0x20, 0x04, 0x9B, 0x00, 0xFB, 0x07, 0x80, 0x99, 0x30, 0x21, 0x46, 0x03, 0xEB, 0xC0, 0x00, 0x03, 0x9C, 0x1B, 0xF0, ++0x61, 0xFB, 0x01, 0x36, 0xF3, 0xB2, 0x9B, 0x45, 0x16, 0xD9, 0x05, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0x51, 0xAF, 0x4D, 0x49, ++0x4F, 0xF4, 0x80, 0x60, 0x1C, 0xF0, 0x7E, 0xFD, 0x20, 0x46, 0xD4, 0xE9, 0x00, 0x54, 0xFF, 0xF7, 0x93, 0xFD, 0xDA, 0xF8, ++0x00, 0x00, 0x01, 0x36, 0x28, 0x1A, 0xFF, 0xF7, 0x4B, 0xFC, 0xF3, 0xB2, 0x9B, 0x45, 0xE8, 0xD8, 0x07, 0x9A, 0x06, 0x99, ++0x93, 0x89, 0x5B, 0x1A, 0x93, 0x81, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4A, 0x01, 0x23, ++0x13, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x3D, 0x48, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x75, 0xFB, 0x2F, 0x49, ++0x91, 0xF8, 0x11, 0x35, 0xD1, 0xF8, 0x14, 0x25, 0x01, 0x3B, 0x81, 0xF8, 0x11, 0x35, 0x00, 0x2A, 0x00, 0xF0, 0x94, 0x80, ++0xD9, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0xDC, 0xAE, 0x28, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, ++0x00, 0x2B, 0x7F, 0xF4, 0xD4, 0xAE, 0x00, 0x2A, 0x3F, 0xF4, 0xD1, 0xAE, 0x62, 0xB6, 0x21, 0x4B, 0xD3, 0xF8, 0x14, 0x35, ++0x00, 0x2B, 0x7F, 0xF4, 0xD0, 0xAE, 0x40, 0x20, 0x1B, 0xF0, 0x6A, 0xFA, 0x04, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, ++0x1B, 0xF0, 0x64, 0xBA, 0x1F, 0x4C, 0x04, 0x93, 0x4F, 0xF0, 0x05, 0x08, 0x50, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0x58, 0xAF, ++0x21, 0x49, 0x22, 0x48, 0x4F, 0xF4, 0xE5, 0x72, 0x1C, 0xF0, 0x4C, 0xFF, 0x50, 0xE7, 0x04, 0x9B, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x07, 0x30, 0x21, 0x46, 0x00, 0xF5, 0xA3, 0x60, 0x03, 0x9C, 0x1B, 0xF0, 0xEC, 0xFA, 0x89, 0xE7, 0xDA, 0xF8, ++0x00, 0x00, 0x03, 0x9C, 0x28, 0x1A, 0xFF, 0xF7, 0xE7, 0xFB, 0x82, 0xE7, 0x0A, 0x4B, 0x16, 0x48, 0x07, 0x93, 0x1D, 0x46, ++0xFE, 0xF7, 0xEE, 0xFA, 0xAB, 0x89, 0x1F, 0xFA, 0x8B, 0xF2, 0x5B, 0x45, 0x06, 0x92, 0x27, 0xD3, 0xBB, 0xF1, 0x00, 0x0F, ++0x7F, 0xF4, 0xC8, 0xAE, 0x8C, 0xE7, 0x00, 0xBF, 0x58, 0x58, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, ++0x50, 0x82, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, ++0x74, 0x28, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0xB4, 0x82, 0x15, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x9C, 0x82, 0x15, 0x00, 0x34, 0x82, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x10, 0x48, 0xFE, 0xF7, ++0xBD, 0xFA, 0xBB, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0x9D, 0xAE, 0x61, 0xE7, 0x0D, 0x48, 0x0E, 0x4C, 0x1C, 0xF0, 0x7E, 0xFC, ++0x80, 0x21, 0xA5, 0xF1, 0x40, 0x00, 0x1D, 0xF0, 0x57, 0xF8, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0xE9, 0xAE, 0x08, 0x49, 0x08, 0x48, 0x4F, 0xF4, 0xE3, 0x72, 0x1C, 0xF0, 0xE7, 0xFE, 0xE1, 0xE6, 0x20, 0x20, 0x1B, 0xF0, ++0x11, 0xFA, 0x67, 0xE7, 0x44, 0x82, 0x15, 0x00, 0x74, 0x82, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x88, 0x82, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x24, 0x91, 0xDF, 0xF8, 0x24, 0x81, 0x42, 0x4F, 0x43, 0x4B, ++0xD3, 0xF8, 0xA0, 0x27, 0x00, 0x2A, 0x5E, 0xD0, 0x15, 0x7B, 0xD2, 0xF8, 0x04, 0xA0, 0x56, 0x7B, 0x65, 0xB3, 0x4F, 0xF0, ++0x00, 0x0B, 0x11, 0xE0, 0xDA, 0xE9, 0x00, 0x4A, 0xFF, 0xF7, 0xB0, 0xFC, 0x20, 0x46, 0xFD, 0xF7, 0x03, 0xFB, 0xD8, 0xF8, ++0x00, 0x00, 0x0B, 0xF1, 0x01, 0x0B, 0x20, 0x1A, 0xFF, 0xF7, 0x64, 0xFB, 0x5F, 0xFA, 0x8B, 0xF1, 0xA9, 0x42, 0x17, 0xD2, ++0x50, 0x46, 0x39, 0x46, 0x00, 0x2E, 0xE9, 0xD0, 0x4F, 0xF4, 0x80, 0x60, 0x1C, 0xF0, 0x80, 0xFC, 0x50, 0x46, 0xDA, 0xE9, ++0x00, 0x4A, 0xFF, 0xF7, 0x95, 0xFC, 0xD8, 0xF8, 0x00, 0x00, 0x0B, 0xF1, 0x01, 0x0B, 0x20, 0x1A, 0xFF, 0xF7, 0x4C, 0xFB, ++0x5F, 0xFA, 0x8B, 0xF1, 0xA9, 0x42, 0xE7, 0xD3, 0x28, 0x4A, 0x93, 0x89, 0x5D, 0x1B, 0x95, 0x81, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x25, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x23, 0x48, 0x01, 0x33, ++0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x76, 0xFA, 0x1D, 0x49, 0xD9, 0xF8, 0x00, 0x20, 0x91, 0xF8, 0x9D, 0x37, 0x01, 0x3B, ++0x81, 0xF8, 0x9D, 0x37, 0x00, 0x2A, 0xAA, 0xD0, 0x1A, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, ++0xA3, 0xD1, 0x00, 0x2B, 0xA1, 0xD0, 0x62, 0xB6, 0x13, 0x4B, 0xD3, 0xF8, 0xA0, 0x27, 0x00, 0x2A, 0xA0, 0xD1, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x4F, 0xF4, ++0x00, 0x00, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x8A, 0xF9, 0x04, 0x20, 0x1B, 0xF0, 0x63, 0xF9, 0xD9, 0xF8, ++0x00, 0x30, 0x3B, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0xBD, 0xE8, 0xF8, 0x8F, 0xB0, 0x82, 0x15, 0x00, 0x58, 0x58, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0xF8, 0x5F, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0xD8, 0x80, ++0xDF, 0xF8, 0xD8, 0x90, 0xDF, 0xF8, 0xD8, 0xA0, 0xD9, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0x41, 0xD0, 0x1F, 0x89, 0x5D, 0x68, ++0xBF, 0xB1, 0x00, 0x24, 0x26, 0x46, 0x23, 0x46, 0xB3, 0x42, 0xAB, 0x46, 0x04, 0xF1, 0x01, 0x04, 0x6D, 0x68, 0x08, 0xD1, ++0xDA, 0xF8, 0x8C, 0x32, 0x98, 0x47, 0x9B, 0xF8, 0x0B, 0x30, 0x03, 0xF0, 0x7F, 0x03, 0x1E, 0x44, 0xB6, 0xB2, 0x58, 0x46, ++0xFF, 0xF7, 0x0A, 0xFC, 0xA3, 0xB2, 0xBB, 0x42, 0xEA, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x1F, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x1E, 0x48, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x1B, 0xF0, ++0xF7, 0xF9, 0x99, 0xF8, 0x02, 0x3C, 0xD8, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0x89, 0xF8, 0x02, 0x3C, 0x00, 0x2A, 0xC7, 0xD0, ++0x15, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xD1, 0x00, 0x2B, 0xBE, 0xD0, 0x62, 0xB6, ++0xD9, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0xBD, 0xD1, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x10, 0x20, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x0E, 0xF9, ++0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x84, 0x42, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x7C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0xB4, 0x80, 0x2A, 0x4E, 0xC1, 0x46, ++0xA8, 0xF1, 0x06, 0x07, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0x33, 0xD0, 0x1D, 0x89, 0x5C, 0x68, 0x7D, 0xB1, 0x4F, 0xF0, ++0x00, 0x0B, 0x20, 0x68, 0xA2, 0x46, 0x0B, 0xF1, 0x01, 0x0B, 0x64, 0x68, 0xFF, 0xF7, 0x5E, 0xFA, 0x50, 0x46, 0xFF, 0xF7, ++0x9D, 0xFB, 0x1F, 0xFA, 0x8B, 0xF2, 0xAA, 0x42, 0xF1, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x1B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x33, 0x68, 0x48, 0x46, 0x01, 0x33, 0x33, 0x60, 0x1B, 0xF0, 0x8B, 0xF9, 0x3B, 0x78, ++0x32, 0x68, 0x01, 0x3B, 0x3B, 0x70, 0x00, 0x2A, 0xD4, 0xD0, 0x14, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0x32, 0x60, 0x00, 0x2A, ++0xCE, 0xD1, 0x00, 0x2B, 0xCC, 0xD0, 0x62, 0xB6, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0xCB, 0xD1, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x33, 0x68, 0x08, 0x20, 0x01, 0x33, 0x33, 0x60, ++0x1B, 0xF0, 0xA8, 0xF8, 0x33, 0x68, 0x33, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x94, 0x4E, 0x17, 0x00, ++0x10, 0xB5, 0x04, 0x20, 0x1B, 0xF0, 0x92, 0xF8, 0x03, 0x4B, 0x04, 0x49, 0xD3, 0xF8, 0x10, 0x31, 0x03, 0x48, 0xBD, 0xE8, ++0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x28, 0x60, 0x17, 0x00, 0xF8, 0xB5, 0xA8, 0x4B, ++0xA8, 0x4A, 0x1B, 0x68, 0x14, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB7, 0x81, 0x65, 0x05, 0x18, 0xD5, ++0xA4, 0x4A, 0x13, 0x68, 0x98, 0x00, 0xFC, 0xD4, 0xA3, 0x4B, 0xA2, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x13, 0xF0, 0x00, 0x53, ++0xFB, 0xD1, 0xA1, 0x49, 0xA1, 0x48, 0x0A, 0x68, 0x42, 0xF0, 0x10, 0x02, 0x0A, 0x60, 0x02, 0x78, 0x02, 0xB1, 0x03, 0x70, ++0x9E, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0xE0, 0x81, 0x21, 0x05, 0x09, 0xD5, 0x97, 0x4A, 0x13, 0x68, 0x9B, 0x00, ++0xFC, 0xD4, 0x9A, 0x4B, 0x94, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0xE2, 0x04, 0x05, 0xD5, 0x94, 0x49, ++0x96, 0x4B, 0x97, 0x4A, 0x01, 0x20, 0x08, 0x70, 0x1A, 0x60, 0x66, 0x06, 0x04, 0xD5, 0x95, 0x4B, 0x95, 0x48, 0x19, 0x68, ++0x1C, 0xF0, 0x9C, 0xFA, 0x14, 0xF4, 0x9B, 0x7F, 0x40, 0xF0, 0x89, 0x81, 0xA5, 0x05, 0x00, 0xF1, 0x8D, 0x81, 0x20, 0x06, ++0x00, 0xF1, 0x94, 0x81, 0x21, 0x04, 0x00, 0xF1, 0x9F, 0x81, 0xE2, 0x02, 0x00, 0xF1, 0xA6, 0x81, 0xA3, 0x02, 0x03, 0xD5, ++0x8B, 0x4B, 0x4F, 0xF4, 0x00, 0x12, 0x1A, 0x60, 0xE7, 0x03, 0x41, 0xD5, 0x89, 0x4B, 0x93, 0xF8, 0x11, 0x15, 0x93, 0xF8, ++0x12, 0x25, 0x91, 0x42, 0x80, 0xF0, 0xB1, 0x81, 0x93, 0xF8, 0x10, 0x05, 0x85, 0x4A, 0x86, 0x4D, 0x86, 0x4E, 0x01, 0x30, ++0xA2, 0xFB, 0x00, 0x72, 0x92, 0x09, 0x02, 0xEB, 0xC2, 0x02, 0x02, 0xEB, 0xC2, 0x02, 0x82, 0x1A, 0x01, 0x31, 0x83, 0xF8, ++0x11, 0x15, 0x83, 0xF8, 0x10, 0x25, 0x03, 0xEB, 0x02, 0x11, 0x30, 0x68, 0x2E, 0x68, 0x4E, 0x60, 0x6E, 0x68, 0x8E, 0x60, ++0x28, 0x3D, 0xC0, 0xF3, 0x00, 0x26, 0x08, 0x73, 0x4E, 0x73, 0x28, 0x68, 0x40, 0xF0, 0x10, 0x00, 0x11, 0x01, 0x28, 0x60, ++0x28, 0x68, 0x86, 0x06, 0xFC, 0xD4, 0x19, 0x44, 0x75, 0x4B, 0x8A, 0x68, 0x75, 0x48, 0x52, 0x68, 0x1A, 0x60, 0x2B, 0x68, ++0x23, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x1B, 0xF0, 0x6F, 0xF8, 0x20, 0x20, 0x1A, 0xF0, 0xCA, 0xFF, 0x69, 0x4B, 0x4F, 0xF4, ++0x80, 0x32, 0x1A, 0x60, 0x65, 0x03, 0x4E, 0xD5, 0x67, 0x4B, 0x93, 0xF8, 0x9D, 0x17, 0x93, 0xF8, 0x9E, 0x27, 0x91, 0x42, ++0x80, 0xF0, 0x7B, 0x81, 0x93, 0xF8, 0x9C, 0x07, 0x68, 0x4A, 0x69, 0x4F, 0x69, 0x4D, 0xDF, 0xF8, 0xE0, 0xC1, 0x01, 0x30, ++0xA2, 0xFB, 0x00, 0x62, 0x56, 0x09, 0x06, 0xEB, 0x86, 0x06, 0xA0, 0xEB, 0xC6, 0x06, 0x4A, 0x1C, 0x83, 0xF8, 0x9D, 0x27, ++0x83, 0xF8, 0x9C, 0x67, 0x03, 0xEB, 0x06, 0x11, 0x3A, 0x68, 0x28, 0x68, 0xC1, 0xF8, 0x20, 0x05, 0x06, 0xF1, 0x52, 0x07, ++0x03, 0xEB, 0x07, 0x15, 0xDC, 0xF8, 0x00, 0x10, 0x5C, 0x48, 0x69, 0x60, 0xC2, 0xF3, 0x00, 0x21, 0x69, 0x72, 0x2A, 0x72, ++0x05, 0x68, 0x45, 0xF0, 0x04, 0x05, 0x05, 0x60, 0x31, 0x01, 0x05, 0x46, 0x2A, 0x68, 0x10, 0x07, 0xFC, 0xD4, 0x03, 0xEB, ++0x07, 0x12, 0x01, 0xF2, 0x1C, 0x51, 0x50, 0x68, 0x53, 0x4A, 0x40, 0x68, 0x10, 0x60, 0x2A, 0x68, 0x52, 0x48, 0x22, 0xF0, ++0x04, 0x02, 0x19, 0x44, 0x2A, 0x60, 0x1B, 0xF0, 0x1F, 0xF8, 0x4F, 0xF4, 0x00, 0x00, 0x1A, 0xF0, 0x79, 0xFF, 0x41, 0x4B, ++0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0xA2, 0x03, 0x1B, 0xD5, 0x4B, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0x35, 0x81, ++0x49, 0x48, 0x90, 0xF8, 0x02, 0x1C, 0x90, 0xF8, 0x01, 0x2C, 0x91, 0x42, 0xC0, 0xF0, 0xA2, 0x80, 0x46, 0x48, 0x1C, 0xF0, ++0xDF, 0xF9, 0x36, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x1A, 0x60, 0x44, 0x4B, 0x1B, 0x68, 0x23, 0xB9, 0x43, 0x4A, 0x13, 0x78, ++0x23, 0xF0, 0x01, 0x03, 0x13, 0x70, 0x23, 0x03, 0x1D, 0xD5, 0x3C, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0x09, 0x81, ++0x3A, 0x48, 0x41, 0xF6, 0x12, 0x04, 0x41, 0xF6, 0x11, 0x03, 0x02, 0x5D, 0xC3, 0x5C, 0x93, 0x42, 0x10, 0xD8, 0x11, 0x46, ++0x39, 0x48, 0x1C, 0xF0, 0xBF, 0xF9, 0x26, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x37, 0x4B, 0x1B, 0x68, 0x23, 0xB9, ++0x33, 0x4A, 0x13, 0x78, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x70, 0xF8, 0xBD, 0x41, 0xF6, 0x10, 0x05, 0x32, 0x4B, 0x41, 0x5D, ++0x01, 0x31, 0xA3, 0xFB, 0x01, 0x63, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, 0xA1, 0xEB, 0x83, 0x13, 0x43, 0x55, 0x03, 0xF1, ++0xC1, 0x01, 0x2D, 0x4E, 0x00, 0xEB, 0x01, 0x11, 0x35, 0x68, 0x4D, 0x60, 0x2B, 0x4D, 0x00, 0xEB, 0x03, 0x13, 0x01, 0x32, ++0x2D, 0x68, 0xA3, 0xF8, 0x18, 0x5C, 0x02, 0x55, 0x28, 0x48, 0x1A, 0xF0, 0xB9, 0xFF, 0x08, 0x20, 0x1A, 0xF0, 0x14, 0xFF, ++0x0E, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0xCF, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x24, 0x00, 0x24, 0x40, ++0x40, 0x00, 0x24, 0x40, 0x01, 0x09, 0x00, 0x32, 0x44, 0x00, 0x24, 0x40, 0x1C, 0x26, 0x17, 0x00, 0x3C, 0x36, 0x17, 0x00, ++0x02, 0x09, 0x00, 0x32, 0x2C, 0x00, 0x24, 0x40, 0x09, 0x70, 0x00, 0xCF, 0x08, 0x00, 0x24, 0x40, 0xDC, 0x82, 0x15, 0x00, ++0x28, 0x00, 0x24, 0x40, 0x58, 0x58, 0x17, 0x00, 0xE7, 0x87, 0x45, 0xCA, 0x88, 0x00, 0x24, 0x40, 0x90, 0x00, 0x24, 0x40, ++0x74, 0x00, 0x24, 0x40, 0x6C, 0x5D, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, 0x84, 0x00, 0x24, 0x40, 0x7C, 0x00, 0x24, 0x40, ++0x60, 0x00, 0x24, 0x40, 0x6C, 0x00, 0x24, 0x40, 0xF8, 0x5F, 0x17, 0x00, 0x1D, 0x26, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x80, 0x83, 0x15, 0x00, 0xA0, 0x00, 0x24, 0x40, 0x9C, 0x4E, 0x17, 0x00, 0x98, 0x83, 0x15, 0x00, 0x98, 0x00, 0x24, 0x40, ++0xAB, 0xAA, 0xAA, 0xAA, 0xA4, 0x00, 0x24, 0x40, 0xA8, 0x00, 0x24, 0x40, 0x94, 0x4E, 0x17, 0x00, 0x80, 0x00, 0x24, 0x40, ++0x90, 0xF8, 0x00, 0x2C, 0x4B, 0x4B, 0x4C, 0x4D, 0x01, 0x32, 0xA3, 0xFB, 0x02, 0x63, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, ++0xA2, 0xEB, 0x83, 0x13, 0x00, 0xEB, 0x03, 0x12, 0x2D, 0x68, 0x55, 0x60, 0x46, 0x4D, 0x80, 0xF8, 0x00, 0x3C, 0x2B, 0x68, ++0x13, 0x81, 0x01, 0x31, 0x80, 0xF8, 0x02, 0x1C, 0x11, 0x46, 0x00, 0xF6, 0x08, 0x40, 0x1A, 0xF0, 0x49, 0xFF, 0x10, 0x20, ++0x1A, 0xF0, 0xA4, 0xFE, 0x3F, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x1A, 0x60, 0x3F, 0xE7, 0x00, 0x2C, 0x7F, 0xF4, 0x46, 0xAE, ++0x3C, 0x49, 0x3D, 0x48, 0x26, 0x22, 0x1C, 0xF0, 0x8D, 0xFB, 0x14, 0xF4, 0x9B, 0x7F, 0x3F, 0xF4, 0x77, 0xAE, 0x3A, 0x48, ++0x21, 0x46, 0x1C, 0xF0, 0x0B, 0xF9, 0xA5, 0x05, 0x7F, 0xF5, 0x73, 0xAE, 0x37, 0x48, 0x1C, 0xF0, 0x05, 0xF9, 0x32, 0x4B, ++0x4F, 0xF4, 0x00, 0x72, 0x20, 0x06, 0x1A, 0x60, 0x7F, 0xF5, 0x6C, 0xAE, 0x33, 0x48, 0x1C, 0xF0, 0xFB, 0xF8, 0x33, 0x4A, ++0x2C, 0x49, 0x13, 0x68, 0x80, 0x20, 0x23, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x08, 0x60, 0x21, 0x04, 0x7F, 0xF5, 0x61, 0xAE, ++0x2E, 0x48, 0x1C, 0xF0, 0xED, 0xF8, 0x26, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0x1A, 0x60, 0xE2, 0x02, 0x7F, 0xF5, 0x5A, 0xAE, ++0x2A, 0x4A, 0x2B, 0x4B, 0x15, 0x68, 0x2B, 0x48, 0x1A, 0x78, 0x29, 0x46, 0xFD, 0xF7, 0x14, 0xFF, 0x29, 0x4A, 0x1E, 0x4B, ++0x15, 0x60, 0x4F, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x4A, 0xE6, 0x27, 0x4A, 0x01, 0x21, 0x59, 0x70, 0x13, 0x68, 0x26, 0x49, ++0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x02, 0x20, 0x1C, 0xF0, 0x1C, 0xF9, 0x13, 0xE6, 0x23, 0x48, 0x1C, 0xF0, 0xC8, 0xF8, ++0x13, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x1A, 0x60, 0x80, 0xE6, 0x00, 0x22, 0x02, 0x20, 0x1A, 0x70, 0xFD, 0xF7, 0x86, 0xFF, ++0xF0, 0xE6, 0x1D, 0x48, 0x1C, 0xF0, 0xBA, 0xF8, 0x0C, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0xC3, 0xE6, 0x00, 0x22, ++0x02, 0x20, 0x1A, 0x70, 0xFD, 0xF7, 0x78, 0xFF, 0x17, 0x48, 0x90, 0xF8, 0x02, 0x1C, 0x90, 0xF8, 0x01, 0x2C, 0x91, 0x42, ++0xBF, 0xF4, 0xC6, 0xAE, 0x66, 0xE7, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, 0xAC, 0x00, 0x24, 0x40, 0xB0, 0x00, 0x24, 0x40, ++0x28, 0x00, 0x24, 0x40, 0x70, 0x79, 0x15, 0x00, 0xC0, 0x82, 0x15, 0x00, 0xEC, 0x82, 0x15, 0x00, 0x08, 0x83, 0x15, 0x00, ++0x1C, 0x83, 0x15, 0x00, 0x4C, 0x00, 0x24, 0x40, 0x30, 0x83, 0x15, 0x00, 0x30, 0x00, 0x24, 0x40, 0x45, 0x00, 0x24, 0x40, ++0x48, 0x83, 0x15, 0x00, 0x34, 0x00, 0x24, 0x40, 0x10, 0x00, 0x58, 0x40, 0xD0, 0x82, 0x15, 0x00, 0xCC, 0x7C, 0x15, 0x00, ++0x64, 0x83, 0x15, 0x00, 0x7C, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x47, 0x4B, 0x1A, 0x68, 0x42, 0xF0, 0x10, 0x02, 0x1A, 0x60, ++0x1B, 0x68, 0x5A, 0x07, 0x7F, 0xD4, 0x44, 0x49, 0x0B, 0x68, 0x9B, 0x00, 0xFC, 0xD4, 0x43, 0x4B, 0x41, 0x4A, 0x0B, 0x60, ++0x13, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0x13, 0x68, 0x9E, 0x07, 0x03, 0xD4, 0x3C, 0x4A, 0x13, 0x68, 0xDD, 0x07, 0xFC, 0xD5, ++0x3A, 0x4A, 0x3D, 0x4D, 0x13, 0x68, 0x3D, 0x48, 0x3D, 0x49, 0x3E, 0x4C, 0x3E, 0x4F, 0x3F, 0x4E, 0x43, 0xF0, 0x02, 0x03, ++0x13, 0x60, 0x2B, 0x68, 0x03, 0x40, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x2B, 0x68, 0x9B, 0xB2, 0x43, 0xF4, 0x80, 0x13, ++0x2B, 0x60, 0x0B, 0x68, 0x03, 0x40, 0x43, 0xF0, 0x10, 0x03, 0x0B, 0x60, 0x0B, 0x68, 0x9B, 0xB2, 0x43, 0xF4, 0x80, 0x13, ++0x0B, 0x60, 0x4F, 0xF6, 0xFF, 0x73, 0x23, 0x60, 0x52, 0xF8, 0x34, 0x3C, 0x03, 0x40, 0x43, 0xF4, 0x88, 0x53, 0x43, 0xF0, ++0x11, 0x03, 0x42, 0xF8, 0x34, 0x3C, 0x03, 0x23, 0xAB, 0x64, 0x4F, 0xF4, 0xFC, 0x53, 0x3B, 0x60, 0x4F, 0xF0, 0xFF, 0x33, ++0x33, 0x60, 0x2A, 0x48, 0x2A, 0x4B, 0x23, 0x62, 0x00, 0x24, 0x20, 0x23, 0x04, 0x60, 0x41, 0xF8, 0xAC, 0x3C, 0x52, 0xF8, ++0x34, 0x3C, 0x27, 0x4C, 0x27, 0x48, 0x23, 0xF4, 0x7F, 0x03, 0x43, 0xF4, 0x80, 0x33, 0x42, 0xF8, 0x34, 0x3C, 0x41, 0xF8, ++0x84, 0x4C, 0x1C, 0xF0, 0x1B, 0xF8, 0x17, 0x4B, 0x17, 0x49, 0x1A, 0x68, 0x94, 0x00, 0xFC, 0xD4, 0x19, 0x60, 0x1A, 0x68, ++0x90, 0x00, 0xFC, 0xD4, 0x1A, 0x68, 0x12, 0xF0, 0x06, 0x0F, 0xF4, 0xD0, 0x10, 0x4A, 0x13, 0x68, 0x99, 0x00, 0xFC, 0xD4, ++0x1A, 0x4B, 0x0E, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x9B, 0x00, 0xFC, 0xD4, 0x18, 0x48, 0x1C, 0xF0, 0x01, 0xF8, 0x18, 0x4B, ++0x18, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0xFC, 0x12, 0x91, 0x67, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF4, 0x80, 0x42, 0x1A, 0x60, ++0xF8, 0xBD, 0x14, 0x4B, 0x0C, 0x4A, 0x1A, 0x60, 0xFE, 0xF7, 0x9A, 0xFB, 0xED, 0xE7, 0x00, 0xBF, 0x44, 0x00, 0x24, 0x40, ++0x40, 0x00, 0x24, 0x40, 0x00, 0x02, 0x00, 0x20, 0x04, 0x00, 0x24, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x24, 0x40, ++0x0C, 0x00, 0x24, 0x40, 0xB4, 0x00, 0x24, 0x40, 0x28, 0x00, 0x24, 0x40, 0x38, 0x00, 0x24, 0x40, 0x09, 0x60, 0x00, 0xCF, ++0x00, 0x00, 0x20, 0x4E, 0xB8, 0x83, 0x15, 0x00, 0x06, 0x03, 0x00, 0x30, 0xCC, 0x83, 0x15, 0x00, 0x00, 0xED, 0x00, 0xE0, ++0x88, 0x1A, 0x17, 0x00, 0x2C, 0x00, 0x24, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x82, 0xB0, 0xEF, 0xF3, 0x10, 0x83, ++0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x24, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x23, 0x4E, 0x24, 0x4B, 0x35, 0x68, 0x1B, 0x68, ++0x01, 0x35, 0x35, 0x60, 0x1C, 0x78, 0x01, 0x2C, 0x2B, 0xD0, 0x21, 0x4C, 0x23, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x23, 0x60, ++0x23, 0x68, 0x9B, 0x05, 0xFC, 0xD4, 0x1E, 0x4B, 0x18, 0x68, 0xC8, 0xB1, 0x1D, 0x4B, 0x1E, 0x4C, 0xD3, 0xF8, 0x04, 0x0C, ++0x47, 0x60, 0x20, 0x68, 0x01, 0x44, 0x21, 0x60, 0x17, 0x49, 0xC3, 0xF8, 0x04, 0x2C, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x73, ++0x0B, 0x60, 0x35, 0xB1, 0x10, 0x4B, 0x01, 0x3D, 0x1B, 0x68, 0x35, 0x60, 0x0D, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x02, 0xB0, ++0xBD, 0xE8, 0xF0, 0x81, 0x11, 0x48, 0x1F, 0x60, 0x04, 0x68, 0x0F, 0x4B, 0x21, 0x44, 0x01, 0x60, 0xE6, 0xE7, 0xDF, 0xF8, ++0x3C, 0x80, 0x98, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0xCD, 0xD1, 0x02, 0x20, 0xCD, 0xE9, 0x00, 0x12, 0xFD, 0xF7, 0x3C, 0xFE, ++0xDD, 0xE9, 0x00, 0x12, 0x35, 0x68, 0x88, 0xF8, 0x00, 0x40, 0xC2, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x74, 0x36, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0xA0, 0x00, 0x24, 0x40, 0x7C, 0x36, 0x17, 0x00, 0x9C, 0x00, 0x24, 0x40, ++0x1D, 0x26, 0x17, 0x00, 0x30, 0xB4, 0x85, 0x68, 0x06, 0x4C, 0xC3, 0xF3, 0x0B, 0x03, 0x2C, 0x40, 0x02, 0x9D, 0x1C, 0x43, ++0x44, 0xEA, 0xC5, 0x74, 0x84, 0x60, 0xC0, 0xE9, 0x00, 0x12, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xF0, 0xFF, 0x7F, ++0xF8, 0xB5, 0x04, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x23, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x22, 0x4D, 0x23, 0x4B, 0x29, 0x68, 0x1B, 0x68, 0x01, 0x31, 0x29, 0x60, 0x1E, 0x78, 0x01, 0x2E, 0x30, 0xD0, 0x20, 0x4A, ++0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x13, 0x68, 0x1B, 0x06, 0xFC, 0xD4, 0x1D, 0x4B, 0x1A, 0x68, 0xF2, 0xB1, ++0x1C, 0x4B, 0x1D, 0x48, 0x41, 0xF6, 0x14, 0x02, 0x9A, 0x58, 0x54, 0x60, 0x02, 0x68, 0x01, 0x32, 0x02, 0x60, 0x41, 0xF6, ++0x14, 0x02, 0x15, 0x4E, 0x9C, 0x50, 0x18, 0x48, 0x32, 0x68, 0x03, 0x78, 0x22, 0xF0, 0x40, 0x02, 0x43, 0xF0, 0x02, 0x03, ++0x32, 0x60, 0x03, 0x70, 0x31, 0xB1, 0x0C, 0x4B, 0x01, 0x39, 0x1B, 0x68, 0x29, 0x60, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, ++0xF8, 0xBD, 0x0E, 0x48, 0x1C, 0x60, 0x02, 0x68, 0x0B, 0x4B, 0x01, 0x32, 0x02, 0x60, 0xE2, 0xE7, 0x0C, 0x4F, 0x3B, 0x78, ++0x00, 0x2B, 0xCA, 0xD1, 0x02, 0x20, 0xFD, 0xF7, 0xC9, 0xFD, 0x29, 0x68, 0x3E, 0x70, 0xC4, 0xE7, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0x98, 0x00, 0x24, 0x40, 0x7C, 0x36, 0x17, 0x00, ++0x94, 0x00, 0x24, 0x40, 0x9C, 0x4E, 0x17, 0x00, 0x1D, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x80, 0x46, 0x04, 0x20, ++0x0F, 0x46, 0x15, 0x46, 0xFE, 0xF7, 0xF0, 0xFD, 0x68, 0xB3, 0x04, 0x46, 0xFE, 0xF7, 0x34, 0xFF, 0x06, 0x46, 0x00, 0xB3, ++0xC5, 0xF3, 0x03, 0x23, 0x4F, 0xF0, 0x00, 0x09, 0x25, 0x70, 0x63, 0x70, 0x2A, 0x46, 0x84, 0xF8, 0x02, 0x80, 0x39, 0x46, ++0x84, 0xF8, 0x03, 0x90, 0x20, 0x1D, 0x2E, 0xF0, 0xF9, 0xFB, 0xB2, 0x68, 0x0E, 0x4B, 0xC6, 0xF8, 0x04, 0x90, 0x04, 0x35, ++0x13, 0x40, 0xC5, 0xF3, 0x0B, 0x05, 0x1D, 0x43, 0x45, 0xF0, 0x00, 0x45, 0x34, 0x60, 0xB5, 0x60, 0x30, 0x46, 0xBD, 0xE8, ++0xF8, 0x43, 0xFF, 0xF7, 0x71, 0xBF, 0x07, 0x48, 0x1C, 0xF0, 0xCC, 0xFF, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0xFE, 0xF7, ++0xE7, 0xBD, 0xBD, 0xE8, 0xF8, 0x43, 0x03, 0x48, 0x1C, 0xF0, 0xC2, 0xBF, 0x00, 0xF0, 0xFF, 0x7F, 0xEC, 0x83, 0x15, 0x00, ++0xD8, 0x83, 0x15, 0x00, 0x05, 0x4B, 0x1B, 0x78, 0x33, 0xB9, 0x05, 0x4B, 0x18, 0x68, 0x6F, 0xEA, 0x10, 0x10, 0x00, 0xF0, ++0x01, 0x00, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x1C, 0x26, 0x17, 0x00, 0x44, 0x00, 0x24, 0x40, 0x44, 0x4A, 0x13, 0x69, ++0x43, 0xF0, 0x01, 0x03, 0x30, 0xB4, 0x13, 0x61, 0x13, 0x69, 0xD9, 0x07, 0xFC, 0xD4, 0x40, 0x4A, 0x13, 0x69, 0x00, 0x2B, ++0xFC, 0xDA, 0xD3, 0x68, 0x3E, 0x48, 0x3D, 0x49, 0x43, 0xF0, 0x80, 0x43, 0x43, 0xF0, 0x07, 0x03, 0xD3, 0x60, 0xD3, 0x68, ++0x18, 0x43, 0xD0, 0x60, 0xD3, 0x68, 0x23, 0xF4, 0x71, 0x53, 0x23, 0xF0, 0x28, 0x03, 0xD3, 0x60, 0x13, 0x69, 0x43, 0xF0, ++0x01, 0x03, 0x13, 0x61, 0x0B, 0x69, 0xDA, 0x07, 0xFC, 0xD4, 0x32, 0x4B, 0x1A, 0x69, 0x00, 0x2A, 0xFC, 0xDA, 0xDA, 0x68, ++0x30, 0x48, 0x2F, 0x49, 0x42, 0xF0, 0x80, 0x42, 0x42, 0xF0, 0x07, 0x02, 0xDA, 0x60, 0xDA, 0x68, 0x10, 0x43, 0xD8, 0x60, ++0xDA, 0x68, 0x22, 0xF4, 0x71, 0x52, 0x22, 0xF0, 0x28, 0x02, 0xDA, 0x60, 0xD3, 0xF8, 0x00, 0x28, 0x22, 0xF4, 0xC0, 0x52, ++0x22, 0xF0, 0x03, 0x02, 0xC3, 0xF8, 0x00, 0x28, 0xD3, 0xF8, 0x00, 0x28, 0x42, 0xF4, 0x00, 0x02, 0x42, 0xF0, 0x04, 0x02, ++0xC3, 0xF8, 0x00, 0x28, 0x00, 0x24, 0x4F, 0xF0, 0xFF, 0x35, 0x01, 0x22, 0x9C, 0x61, 0x01, 0x2A, 0x5D, 0x61, 0xC3, 0xF8, ++0x1C, 0x48, 0xC3, 0xF8, 0x14, 0x48, 0xC3, 0xF8, 0x10, 0x48, 0xA2, 0xF1, 0x02, 0x03, 0x28, 0x46, 0x01, 0xEB, 0x43, 0x13, ++0x0B, 0xD0, 0x05, 0x2A, 0xC3, 0xF8, 0x28, 0x0B, 0xC3, 0xF8, 0x28, 0x09, 0x0A, 0xD0, 0x01, 0x32, 0x93, 0x1E, 0x01, 0x2A, ++0x01, 0xEB, 0x43, 0x13, 0xF3, 0xD1, 0xC1, 0xF8, 0x08, 0x0B, 0xC1, 0xF8, 0x08, 0x09, 0xF4, 0xE7, 0x0F, 0x48, 0x10, 0x4B, ++0x0C, 0x4A, 0x88, 0x61, 0x4B, 0x63, 0x53, 0x6B, 0x1B, 0x01, 0xFC, 0xD5, 0xD2, 0xF8, 0x04, 0x38, 0x23, 0xF0, 0x02, 0x03, ++0xC2, 0xF8, 0x04, 0x38, 0xD2, 0xF8, 0x04, 0x38, 0x2E, 0x21, 0x43, 0xF4, 0x00, 0x43, 0xC2, 0xF8, 0x04, 0x38, 0x91, 0x60, ++0x93, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x30, 0xBC, 0x93, 0x60, 0x70, 0x47, 0x00, 0x00, 0x20, 0x40, 0x10, 0x00, 0x06, 0x40, ++0x00, 0x38, 0x00, 0x80, 0x41, 0x00, 0x44, 0x02, 0x0A, 0x4B, 0x0B, 0x49, 0x1A, 0x68, 0x08, 0x68, 0x0A, 0x49, 0x0B, 0x4B, ++0xC2, 0xE9, 0x00, 0x10, 0xC3, 0xF8, 0x14, 0x2B, 0xD3, 0xF8, 0x08, 0x2B, 0xC3, 0xF8, 0x08, 0x2B, 0xD3, 0xF8, 0x00, 0x2B, ++0x42, 0xF0, 0x04, 0x42, 0xC3, 0xF8, 0x00, 0x2B, 0x70, 0x47, 0x00, 0xBF, 0x5C, 0x60, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, ++0x40, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x20, 0x40, 0x12, 0x4A, 0x13, 0x4B, 0x11, 0x68, 0x18, 0x68, 0x12, 0x4B, 0x30, 0xB4, ++0x12, 0x4C, 0x4F, 0xF0, 0x20, 0x62, 0x00, 0x25, 0x65, 0x81, 0xC1, 0xE9, 0x00, 0x20, 0x1A, 0x69, 0x22, 0xF4, 0xFC, 0x62, ++0x42, 0xF0, 0x20, 0x02, 0x1A, 0x61, 0x18, 0x69, 0x10, 0xF0, 0x20, 0x00, 0xFB, 0xD1, 0xD3, 0xF8, 0x08, 0x29, 0xC3, 0xF8, ++0x08, 0x29, 0xC3, 0xF8, 0x14, 0x19, 0xD3, 0xF8, 0x00, 0x29, 0x42, 0xF0, 0x04, 0x42, 0x30, 0xBC, 0xC3, 0xF8, 0x00, 0x29, ++0x70, 0x47, 0x00, 0xBF, 0x40, 0x60, 0x17, 0x00, 0x58, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xB4, 0x27, 0x17, 0x00, ++0x70, 0xB5, 0x0B, 0x4B, 0x04, 0x46, 0x01, 0x38, 0x03, 0xEB, 0x00, 0x10, 0x10, 0x22, 0x05, 0x7A, 0x00, 0x21, 0xF7, 0xF7, ++0x4D, 0xFB, 0x55, 0xB1, 0x06, 0x48, 0x00, 0xEB, 0x84, 0x04, 0x23, 0x6A, 0x2B, 0xB1, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, ++0x08, 0x46, 0x01, 0x22, 0x18, 0x47, 0x70, 0xBD, 0x08, 0x28, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0x70, 0xB5, 0x0B, 0x4B, ++0x04, 0x46, 0x01, 0x38, 0x03, 0xEB, 0x00, 0x10, 0x10, 0x22, 0xC5, 0x7A, 0x00, 0x21, 0xF7, 0xF7, 0x31, 0xFB, 0x55, 0xB1, ++0x06, 0x48, 0x00, 0xEB, 0x84, 0x04, 0x23, 0x6B, 0x2B, 0xB1, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0x08, 0x46, 0x01, 0x22, ++0x18, 0x47, 0x70, 0xBD, 0xC8, 0x27, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x24, 0x82, 0xB0, 0xE0, 0xB2, ++0x01, 0x90, 0x01, 0x34, 0xFF, 0xF7, 0xC0, 0xFF, 0x01, 0x98, 0xFF, 0xF7, 0xD9, 0xFF, 0x05, 0x2C, 0xF5, 0xD1, 0x02, 0xB0, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0xB5, 0x0C, 0x46, 0x00, 0x28, 0x39, 0xD0, 0x09, 0xBB, 0x1D, 0x4B, 0x1D, 0x4A, 0x1B, 0x68, ++0x51, 0x81, 0x1D, 0x4D, 0x4F, 0xF0, 0x42, 0x42, 0x1A, 0x60, 0xDA, 0x78, 0x42, 0xF0, 0x04, 0x02, 0xDA, 0x70, 0xD9, 0x78, ++0x28, 0x68, 0x19, 0x4A, 0x58, 0x60, 0x01, 0xF0, 0x07, 0x01, 0x41, 0xF0, 0x08, 0x01, 0xD9, 0x70, 0xD2, 0xF8, 0x08, 0x19, ++0xC2, 0xF8, 0x08, 0x19, 0xC2, 0xF8, 0x14, 0x39, 0xD2, 0xF8, 0x00, 0x39, 0x43, 0xF0, 0x04, 0x43, 0xC2, 0xF8, 0x00, 0x39, ++0x38, 0xBD, 0x0E, 0x4D, 0x01, 0x46, 0x22, 0x46, 0x28, 0x68, 0x2E, 0xF0, 0x71, 0xFA, 0x09, 0x4B, 0x09, 0x4A, 0x1B, 0x68, ++0x54, 0x81, 0x4F, 0xF0, 0x40, 0x41, 0xC2, 0x22, 0x40, 0x2C, 0x19, 0x60, 0x1C, 0x80, 0xDA, 0x70, 0xD3, 0xD1, 0xD2, 0xB2, ++0x6F, 0xF3, 0x82, 0x02, 0xDA, 0x70, 0xD2, 0xE7, 0x02, 0x4D, 0xEC, 0xE7, 0x40, 0x60, 0x17, 0x00, 0xB4, 0x27, 0x17, 0x00, ++0x58, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xF0, 0xB4, 0x80, 0xB3, 0x27, 0x4D, 0x43, 0x1E, 0x05, 0xEB, 0x43, 0x16, ++0x08, 0x36, 0x05, 0xEB, 0x43, 0x15, 0x2F, 0x68, 0x17, 0xF0, 0x80, 0x2F, 0x22, 0xD0, 0x23, 0x4B, 0x3B, 0x40, 0xB3, 0xF5, ++0x00, 0x3F, 0x2C, 0xD0, 0x21, 0x4C, 0xD4, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x00, 0x73, 0xC4, 0xF8, 0x04, 0x38, 0x63, 0x69, ++0x1B, 0x06, 0xFC, 0xD5, 0x2B, 0x68, 0x19, 0x43, 0x41, 0xF0, 0x00, 0x61, 0x41, 0xF4, 0x00, 0x41, 0x29, 0x60, 0x1A, 0xB1, ++0x2B, 0x68, 0x23, 0xEA, 0x02, 0x02, 0x2A, 0x60, 0x60, 0xB9, 0x16, 0x4A, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x80, 0x63, ++0xC2, 0xF8, 0x04, 0x38, 0xF0, 0xBC, 0xFF, 0xF7, 0x3D, 0xBF, 0x12, 0x4E, 0x12, 0x4D, 0xD2, 0xE7, 0x00, 0x2F, 0x0C, 0xDB, ++0x3B, 0x04, 0xEE, 0xD4, 0x2B, 0x68, 0x23, 0xF4, 0x00, 0x43, 0x2B, 0x60, 0xE9, 0xE7, 0xB1, 0xF1, 0x00, 0x6F, 0xCF, 0xD1, ++0x00, 0x2A, 0xCD, 0xD1, 0xEA, 0xE7, 0x02, 0x23, 0x33, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x2B, 0x60, 0x33, 0x68, ++0x9A, 0x07, 0xFC, 0xD5, 0x3B, 0x04, 0xD8, 0xD4, 0xE8, 0xE7, 0x00, 0xBF, 0x20, 0x0B, 0x20, 0x40, 0x00, 0x00, 0x02, 0x80, ++0x00, 0x00, 0x20, 0x40, 0x08, 0x0B, 0x20, 0x40, 0x00, 0x0B, 0x20, 0x40, 0x70, 0xB4, 0x70, 0xB3, 0x44, 0x1E, 0x36, 0x4B, ++0x66, 0x01, 0x03, 0xEB, 0x44, 0x14, 0xF5, 0x58, 0x15, 0xF0, 0x80, 0x2F, 0x4D, 0xD0, 0x08, 0x36, 0x33, 0x44, 0x32, 0x4E, ++0x2E, 0x40, 0xB6, 0xF5, 0x00, 0x3F, 0x29, 0xD1, 0xB1, 0xF1, 0x00, 0x6F, 0x46, 0xD0, 0x40, 0x26, 0x1E, 0x60, 0x23, 0x68, ++0x0B, 0x43, 0x43, 0xF0, 0x00, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x23, 0x60, 0x00, 0x2A, 0x45, 0xD1, 0x29, 0x4A, 0x83, 0x01, ++0x43, 0xF0, 0x20, 0x03, 0x13, 0x61, 0x13, 0x69, 0x99, 0x06, 0xFC, 0xD4, 0x2B, 0x04, 0x03, 0xD4, 0x23, 0x68, 0x23, 0xF4, ++0x00, 0x43, 0x23, 0x60, 0x48, 0xBB, 0x70, 0xBC, 0x70, 0x47, 0x22, 0x4C, 0x25, 0x68, 0x15, 0xF0, 0x80, 0x2F, 0xF8, 0xD0, ++0x1D, 0x4E, 0x20, 0x4B, 0x2E, 0x40, 0xB6, 0xF5, 0x00, 0x3F, 0xD5, 0xD0, 0x40, 0x26, 0x1E, 0x60, 0x26, 0x68, 0x31, 0x43, ++0x41, 0xF0, 0x00, 0x61, 0x41, 0xF4, 0x00, 0x41, 0x00, 0x2D, 0x21, 0x60, 0xD6, 0xDA, 0xAE, 0x03, 0x04, 0xD4, 0x19, 0x68, ++0x49, 0x06, 0xFC, 0xD5, 0x40, 0x21, 0x19, 0x60, 0xDA, 0xB9, 0x02, 0x22, 0x1A, 0x60, 0x22, 0x68, 0x42, 0xF0, 0x80, 0x42, ++0x22, 0x60, 0x1A, 0x68, 0x96, 0x07, 0xFC, 0xD5, 0xC6, 0xE7, 0x70, 0xBC, 0xFF, 0xF7, 0xD4, 0xBE, 0x00, 0x2A, 0xCF, 0xD0, ++0x40, 0x21, 0x19, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x23, 0x60, 0x23, 0x68, 0x23, 0xEA, ++0x02, 0x02, 0x22, 0x60, 0xB4, 0xE7, 0x21, 0x68, 0x21, 0xEA, 0x02, 0x02, 0x22, 0x60, 0xDE, 0xE7, 0x20, 0x09, 0x20, 0x40, ++0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x40, 0x00, 0x09, 0x20, 0x40, 0x08, 0x09, 0x20, 0x40, 0x49, 0xB9, 0x0A, 0x4B, ++0x0A, 0x4A, 0x01, 0x28, 0x0C, 0xBF, 0x18, 0x46, 0x10, 0x46, 0x00, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x01, 0x28, ++0x0C, 0xBF, 0x04, 0x48, 0x04, 0x48, 0x49, 0x01, 0x08, 0x44, 0x00, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x00, 0xBF, ++0x00, 0x09, 0x20, 0x40, 0x00, 0x0B, 0x20, 0x40, 0x38, 0xB9, 0x04, 0x29, 0x0D, 0xD8, 0x02, 0x46, 0x08, 0x46, 0x4F, 0xF0, ++0x00, 0x61, 0xFF, 0xF7, 0x07, 0xBF, 0x04, 0x29, 0x05, 0xD8, 0x08, 0x46, 0x00, 0x22, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, ++0x5B, 0xBF, 0x70, 0x47, 0x38, 0xB9, 0x04, 0x29, 0x0D, 0xD8, 0x02, 0x46, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0xFF, 0xF7, ++0xF5, 0xBE, 0x04, 0x29, 0x05, 0xD8, 0x08, 0x46, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x11, 0xFF, 0xF7, 0x49, 0xBF, 0x70, 0x47, ++0x40, 0xB9, 0x04, 0x29, 0x0F, 0xD8, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x12, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, 0xE2, 0xBE, ++0x04, 0x29, 0x06, 0xD8, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x12, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, 0x35, 0xBF, 0x70, 0x47, ++0xFF, 0xF7, 0xC6, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0x04, 0x46, 0x0D, 0x46, 0x57, 0x48, 0x00, 0x21, 0x1B, 0xF0, 0x04, 0xFC, ++0x00, 0x2C, 0x00, 0xF0, 0x95, 0x80, 0x23, 0x68, 0x00, 0x2B, 0x7B, 0xD0, 0x63, 0x68, 0x00, 0x2B, 0x78, 0xD0, 0xA3, 0x68, ++0x00, 0x2B, 0x75, 0xD0, 0x63, 0x69, 0x00, 0x2B, 0x72, 0xD0, 0x4F, 0x4E, 0x33, 0x78, 0x03, 0xF0, 0xFF, 0x07, 0x00, 0x2B, ++0x6F, 0xD1, 0xDF, 0xF8, 0x68, 0x81, 0x21, 0x46, 0x40, 0x46, 0x01, 0x24, 0x48, 0x22, 0x34, 0x70, 0x2E, 0xF0, 0x06, 0xF9, ++0x48, 0x4B, 0xD3, 0xF8, 0x94, 0x30, 0x00, 0x2B, 0x77, 0xD0, 0x47, 0x48, 0x1B, 0xF0, 0xDE, 0xFB, 0x46, 0x4B, 0xD3, 0xF8, ++0x00, 0x28, 0x12, 0xF4, 0xFE, 0x6F, 0x5B, 0xD0, 0x44, 0x49, 0x45, 0x4A, 0xD1, 0xF8, 0x00, 0xC0, 0x44, 0x49, 0x12, 0x68, ++0xDF, 0xF8, 0x30, 0x91, 0x09, 0x68, 0xC9, 0xF8, 0x04, 0x70, 0x04, 0x20, 0xC9, 0xF8, 0x08, 0x70, 0x89, 0xF8, 0x00, 0x70, ++0xC2, 0xF8, 0x04, 0xC0, 0x30, 0x70, 0xC3, 0xF8, 0x14, 0x2B, 0xC8, 0x78, 0x3C, 0x4A, 0x40, 0xF0, 0xC0, 0x00, 0xD2, 0xF8, ++0x00, 0xC0, 0xC8, 0x70, 0x9C, 0xF8, 0x03, 0x00, 0x39, 0x4A, 0x40, 0xF0, 0xC0, 0x00, 0x17, 0x68, 0x8C, 0xF8, 0x03, 0x00, ++0xF8, 0x78, 0xD2, 0xF8, 0x04, 0xE0, 0x40, 0xF0, 0xC0, 0x00, 0xF8, 0x70, 0x9E, 0xF8, 0x03, 0x00, 0xD2, 0xE9, 0x02, 0xC7, ++0x40, 0xF0, 0xC0, 0x02, 0x8E, 0xF8, 0x03, 0x20, 0x9C, 0xF8, 0x03, 0x20, 0x42, 0xF0, 0xC0, 0x02, 0x8C, 0xF8, 0x03, 0x20, ++0xFA, 0x78, 0x42, 0xF0, 0xC0, 0x02, 0xFA, 0x70, 0xC3, 0xF8, 0x14, 0x19, 0xFF, 0xF7, 0x86, 0xFD, 0xD8, 0xF8, 0x44, 0x30, ++0x89, 0xF8, 0x00, 0x40, 0x03, 0xB1, 0x98, 0x47, 0x26, 0x4B, 0x27, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0x04, 0x11, 0xD1, 0x67, ++0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF4, 0x00, 0x42, 0x01, 0x2D, 0x1A, 0x60, 0x23, 0xD0, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, ++0x02, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x03, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x9A, 0x68, 0xD2, 0x07, 0x14, 0xD5, 0x9A, 0x68, ++0x22, 0xF0, 0x01, 0x02, 0x9A, 0x60, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, 0xFF, 0xF7, ++0xC9, 0xFC, 0xD9, 0xE7, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x14, 0x48, 0xFD, 0xF7, 0x9C, 0xF9, 0x04, 0x20, 0xE2, 0xE7, ++0xFF, 0xF7, 0xBE, 0xFC, 0xCE, 0xE7, 0x11, 0x4B, 0x11, 0x48, 0x1B, 0x69, 0x1B, 0xF0, 0x5C, 0xFB, 0x33, 0x78, 0x04, 0x2B, ++0xFC, 0xD1, 0xD2, 0xE7, 0xFC, 0x83, 0x15, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x00, 0x00, 0x10, 0x40, 0x08, 0x84, 0x15, 0x00, ++0x00, 0x00, 0x20, 0x40, 0x60, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x44, 0x60, 0x17, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x84, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x34, 0x84, 0x15, 0x00, 0x20, 0x26, 0x17, 0x00, 0xB4, 0x27, 0x17, 0x00, 0x14, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0xC3, 0xF8, ++0x80, 0x20, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0x11, 0x4A, 0x11, 0x4B, 0x12, 0x48, 0x00, 0x21, 0x11, 0x70, ++0x9A, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x9A, 0x60, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, ++0x1A, 0x69, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x61, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, ++0x1A, 0x69, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x61, 0x48, 0x22, 0xF7, 0xF7, 0x9F, 0xB8, 0x00, 0xBF, 0x00, 0xE1, 0x00, 0xE0, ++0x6F, 0x26, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x4E, 0x1E, 0xF7, 0xB2, ++0x03, 0x2F, 0x41, 0xD8, 0x14, 0x46, 0x0D, 0x46, 0x9B, 0x46, 0x02, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0x04, 0xF0, 0xFD, 0x01, ++0x01, 0x29, 0x5B, 0xD0, 0xDF, 0x1C, 0xBF, 0x10, 0x7F, 0x00, 0xBF, 0xB2, 0xBA, 0x46, 0x4F, 0xEA, 0x07, 0x49, 0x4F, 0xEA, ++0x45, 0x18, 0x08, 0xF1, 0x80, 0x48, 0x08, 0xF5, 0x00, 0x18, 0xD8, 0xF8, 0x00, 0x19, 0x11, 0xF0, 0x80, 0x2F, 0x68, 0xD1, ++0xA2, 0x04, 0x02, 0xF4, 0x40, 0x22, 0xCB, 0xF3, 0x0A, 0x03, 0x3B, 0x4C, 0x13, 0x43, 0x43, 0xEA, 0x85, 0x53, 0x21, 0x88, ++0x43, 0xF0, 0xC0, 0x53, 0x43, 0xF4, 0x00, 0x43, 0xC8, 0xF8, 0x00, 0x39, 0x01, 0xEB, 0x0A, 0x03, 0xB3, 0xF5, 0xC0, 0x6F, ++0x5E, 0xDC, 0x34, 0x4A, 0x40, 0x36, 0x02, 0xEB, 0x86, 0x06, 0x41, 0xEA, 0x09, 0x03, 0x73, 0x60, 0xD2, 0xF8, 0x1C, 0x38, ++0x0F, 0x44, 0x01, 0x21, 0x01, 0xFA, 0x05, 0xF5, 0x1D, 0x43, 0x27, 0x80, 0xC2, 0xF8, 0x1C, 0x58, 0xBD, 0xE8, 0xF8, 0x8F, ++0x4E, 0x01, 0x06, 0xF1, 0x80, 0x46, 0x06, 0xF5, 0x00, 0x16, 0xD6, 0xF8, 0x00, 0x2B, 0x12, 0xF0, 0x80, 0x2F, 0x33, 0xD1, ++0xA4, 0x04, 0x04, 0xF4, 0x40, 0x24, 0xCB, 0xF3, 0x0A, 0x03, 0x23, 0x43, 0x43, 0xF0, 0xC0, 0x53, 0x21, 0x4A, 0x43, 0xF4, ++0x00, 0x43, 0xC6, 0xF8, 0x00, 0x3B, 0xD2, 0xF8, 0x1C, 0x38, 0x4F, 0xF4, 0x80, 0x31, 0x01, 0xFA, 0x05, 0xF5, 0x1D, 0x43, ++0xC2, 0xF8, 0x1C, 0x58, 0xBD, 0xE8, 0xF8, 0x8F, 0xB3, 0xF5, 0x48, 0x7F, 0x20, 0xD8, 0xDF, 0x1C, 0xBF, 0x10, 0x7F, 0x00, ++0xBF, 0xB2, 0xBA, 0x46, 0x4F, 0xEA, 0x07, 0x49, 0xBB, 0xF5, 0x80, 0x6F, 0x9D, 0xD9, 0x6F, 0xF4, 0x80, 0x63, 0x0B, 0xEB, ++0x03, 0x01, 0xB1, 0xF5, 0x80, 0x6F, 0x25, 0xBF, 0x10, 0x4B, 0xA3, 0xFB, 0x0B, 0x13, 0x4F, 0xEA, 0x5B, 0x0B, 0xC3, 0xF3, ++0x4F, 0x0B, 0x8E, 0xE7, 0xFF, 0xF7, 0x34, 0xFE, 0xC8, 0xE7, 0x10, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0x2F, 0xFE, 0x91, 0xE7, ++0x4F, 0xF4, 0xC8, 0x7A, 0x57, 0x46, 0x4F, 0xF0, 0xC8, 0x79, 0xDF, 0xE7, 0x06, 0x48, 0x52, 0x46, 0x4F, 0xF4, 0xC0, 0x63, ++0xFD, 0xF7, 0x9E, 0xF8, 0x21, 0x88, 0x98, 0xE7, 0x48, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xAB, 0xAA, 0xAA, 0xAA, ++0x40, 0x84, 0x15, 0x00, 0xF8, 0xB5, 0x27, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x3C, 0xD1, 0x44, 0x1E, 0xDF, 0xB2, 0xE3, 0xB2, ++0x04, 0x2B, 0x39, 0xD8, 0x8D, 0x07, 0x3D, 0xD1, 0x22, 0x4E, 0x4F, 0xEA, 0x04, 0x1E, 0x06, 0xEB, 0x04, 0x1C, 0x56, 0xF8, ++0x0E, 0x50, 0x8D, 0xBB, 0x43, 0x01, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x00, 0x13, 0xD3, 0xF8, 0x00, 0x0B, 0x00, 0x04, ++0x2A, 0xD5, 0x1B, 0x48, 0x46, 0xF8, 0x0E, 0x10, 0x50, 0xF8, 0x24, 0x00, 0x19, 0x4F, 0x01, 0x26, 0x8C, 0xF8, 0x08, 0x60, ++0xC6, 0x78, 0x64, 0x01, 0x04, 0xF1, 0x80, 0x44, 0xBA, 0x42, 0x04, 0xF5, 0x00, 0x14, 0x06, 0xF0, 0x31, 0x06, 0x28, 0xBF, ++0x3A, 0x46, 0x46, 0xF0, 0x0E, 0x06, 0xCC, 0xF8, 0x04, 0x20, 0x02, 0x80, 0x41, 0x60, 0xC6, 0x70, 0xC4, 0xF8, 0x34, 0x0B, ++0xD3, 0xF8, 0x00, 0x2B, 0x42, 0xF0, 0x04, 0x42, 0x28, 0x46, 0xC3, 0xF8, 0x00, 0x2B, 0xF8, 0xBD, 0x01, 0x20, 0xF8, 0xBD, ++0x02, 0x20, 0xF8, 0xBD, 0x38, 0x46, 0xF8, 0xBD, 0x05, 0x20, 0xF8, 0xBD, 0x06, 0x48, 0xFD, 0xF7, 0x47, 0xF8, 0x03, 0x20, ++0xF8, 0xBD, 0x00, 0xBF, 0x6F, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, 0xFF, 0xFF, 0x07, 0x00, ++0x80, 0x84, 0x15, 0x00, 0xF8, 0xB5, 0x28, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x3E, 0xD1, 0x44, 0x1E, 0xDF, 0xB2, 0xE3, 0xB2, ++0x04, 0x2B, 0x3B, 0xD8, 0x8D, 0x07, 0x3F, 0xD1, 0x23, 0x4E, 0x4F, 0xEA, 0x04, 0x1E, 0x06, 0xEB, 0x04, 0x1C, 0x56, 0xF8, ++0x0E, 0x50, 0x9D, 0xBB, 0x43, 0x01, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x00, 0x13, 0xD3, 0xF8, 0x00, 0x0B, 0x00, 0x04, ++0x2C, 0xD5, 0x1C, 0x48, 0x46, 0xF8, 0x0E, 0x10, 0x50, 0xF8, 0x24, 0x00, 0x1A, 0x4F, 0x01, 0x26, 0x8C, 0xF8, 0x08, 0x60, ++0xC6, 0x78, 0x64, 0x01, 0x04, 0xF1, 0x80, 0x44, 0xBA, 0x42, 0x04, 0xF5, 0x00, 0x14, 0x06, 0xF0, 0x31, 0x06, 0x28, 0xBF, ++0x3A, 0x46, 0x46, 0xF0, 0x0E, 0x06, 0xCC, 0xF8, 0x04, 0x20, 0x02, 0x80, 0x41, 0x60, 0xC6, 0x70, 0xC4, 0xF8, 0x34, 0x0B, ++0xD3, 0xF8, 0x00, 0x2B, 0x22, 0xF0, 0x04, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x28, 0x46, 0xC3, 0xF8, 0x00, 0x2B, 0xF8, 0xBD, ++0x01, 0x20, 0xF8, 0xBD, 0x02, 0x20, 0xF8, 0xBD, 0x38, 0x46, 0xF8, 0xBD, 0x05, 0x20, 0xF8, 0xBD, 0x06, 0x48, 0xFC, 0xF7, ++0xEB, 0xFF, 0x03, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x6F, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, ++0xFF, 0xFF, 0x07, 0x00, 0x80, 0x84, 0x15, 0x00, 0x10, 0xB5, 0x0C, 0x4C, 0x0C, 0x4B, 0xE0, 0x89, 0x18, 0x80, 0x20, 0xB9, ++0x0B, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x0A, 0x4B, 0x5B, 0x69, 0x4B, 0xB1, 0xC0, 0xB2, 0x98, 0x47, ++0x30, 0xB1, 0x06, 0x4A, 0x04, 0x21, 0x07, 0x23, 0x11, 0x70, 0x23, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, ++0xB4, 0x27, 0x17, 0x00, 0x6C, 0x26, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x46, ++0x00, 0x28, 0x70, 0xD1, 0x01, 0xF0, 0x21, 0x03, 0x21, 0x2B, 0x7F, 0xD0, 0xE1, 0x07, 0x76, 0xD5, 0x14, 0xF0, 0x08, 0x01, ++0x00, 0xF0, 0x8B, 0x80, 0xB5, 0x4D, 0x2B, 0x78, 0x00, 0x2B, 0x40, 0xF0, 0x76, 0x82, 0x63, 0x06, 0x40, 0xF1, 0x15, 0x81, ++0xB2, 0x4B, 0xD3, 0xF8, 0x14, 0x3B, 0x08, 0x3B, 0x00, 0x22, 0xC5, 0xE9, 0x01, 0x22, 0x02, 0x20, 0x28, 0x70, 0x1A, 0x78, ++0x29, 0x7B, 0xD2, 0x09, 0x62, 0xF3, 0xC7, 0x11, 0x29, 0x73, 0x19, 0x78, 0x2A, 0x7B, 0x49, 0x11, 0x61, 0xF3, 0x46, 0x12, ++0x2A, 0x73, 0x19, 0x78, 0x61, 0xF3, 0x04, 0x02, 0x2A, 0x73, 0x5A, 0x78, 0x6A, 0x73, 0xD9, 0x78, 0x9A, 0x78, 0x42, 0xEA, ++0x01, 0x22, 0xEA, 0x81, 0x59, 0x79, 0x1A, 0x79, 0x42, 0xEA, 0x01, 0x22, 0x2A, 0x82, 0xDA, 0x79, 0x9B, 0x79, 0x43, 0xEA, ++0x02, 0x23, 0x6B, 0x82, 0x23, 0xB9, 0x95, 0xF9, 0x0C, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x73, 0x82, 0x9A, 0x4B, 0x9B, 0x4C, ++0xD3, 0xF8, 0x14, 0x28, 0xE1, 0x68, 0x22, 0xF0, 0x10, 0x02, 0xC3, 0xF8, 0x14, 0x28, 0xD3, 0xF8, 0x10, 0x28, 0x22, 0xF0, ++0x10, 0x02, 0xC3, 0xF8, 0x10, 0x28, 0x21, 0xB1, 0x91, 0x48, 0x88, 0x47, 0x00, 0x28, 0x40, 0xF0, 0xB5, 0x80, 0x92, 0x4F, ++0x2B, 0x7B, 0x3A, 0x78, 0x13, 0xF0, 0x60, 0x0F, 0xD6, 0xB2, 0x40, 0xF0, 0xCF, 0x80, 0x68, 0x7B, 0x0B, 0x28, 0x00, 0xF2, ++0xDA, 0x80, 0xDF, 0xE8, 0x10, 0xF0, 0xDE, 0x00, 0x27, 0x01, 0xD8, 0x00, 0xFA, 0x00, 0xD8, 0x00, 0x8C, 0x00, 0x5D, 0x01, ++0xD8, 0x00, 0x4F, 0x01, 0x44, 0x01, 0x98, 0x01, 0x85, 0x01, 0x82, 0x4D, 0x2B, 0x78, 0x02, 0x2B, 0x53, 0xD0, 0xCA, 0x07, ++0x55, 0xD4, 0xA1, 0x06, 0x02, 0xD5, 0x2B, 0x78, 0x06, 0x2B, 0x3D, 0xD0, 0xF8, 0xBD, 0x7C, 0x4D, 0x22, 0x07, 0x2B, 0x78, ++0x35, 0xD5, 0x01, 0x2B, 0x8B, 0xD0, 0xF8, 0xBD, 0x79, 0x4A, 0xD2, 0xF8, 0x10, 0x3B, 0x03, 0xF0, 0x7F, 0x03, 0x40, 0x2B, ++0x7F, 0xF4, 0x78, 0xAF, 0xD2, 0xF8, 0x10, 0x3B, 0x18, 0x03, 0x7F, 0xF5, 0x73, 0xAF, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, ++0xDB, 0xBA, 0x74, 0x4B, 0x6F, 0x4D, 0x1E, 0x68, 0xF3, 0x78, 0x13, 0xF0, 0x01, 0x03, 0x40, 0xF0, 0xE2, 0x81, 0x2A, 0x78, ++0x02, 0x2A, 0x3F, 0xF4, 0x6E, 0xAF, 0x03, 0x2A, 0x00, 0xF0, 0xE6, 0x81, 0x05, 0x2A, 0x0D, 0xD1, 0x68, 0x4A, 0x2B, 0x70, ++0xD2, 0xF8, 0x14, 0x38, 0x23, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xD2, 0xF8, 0x10, 0x38, 0x23, 0xF0, 0x10, 0x03, ++0xC2, 0xF8, 0x10, 0x38, 0xFF, 0xF7, 0xBA, 0xFA, 0xBF, 0xE7, 0x02, 0x2B, 0xBD, 0xD1, 0x54, 0xE7, 0xFF, 0xF7, 0xB4, 0xFA, ++0x5D, 0x4A, 0x07, 0x23, 0x2B, 0x70, 0xD2, 0xF8, 0x14, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xBD, 0xE8, ++0xF8, 0x40, 0xFF, 0xF7, 0xC5, 0xBA, 0x5B, 0x48, 0xFC, 0xF7, 0xEC, 0xFE, 0x41, 0xE7, 0x04, 0x2B, 0x00, 0xF0, 0xDD, 0x81, ++0x07, 0x2B, 0xA4, 0xD1, 0x52, 0x4B, 0x57, 0x49, 0x00, 0x20, 0x28, 0x70, 0xD3, 0xF8, 0x14, 0x28, 0x22, 0xF0, 0x10, 0x02, ++0xC3, 0xF8, 0x14, 0x28, 0xD3, 0xF8, 0x10, 0x28, 0x22, 0xF0, 0x10, 0x02, 0xC3, 0xF8, 0x10, 0x28, 0x0A, 0x78, 0x00, 0x2A, ++0x96, 0xD0, 0xD3, 0xF8, 0x04, 0x48, 0x12, 0x01, 0x02, 0xF0, 0x70, 0x02, 0x24, 0xF0, 0x70, 0x04, 0x22, 0x43, 0xC3, 0xF8, ++0x04, 0x28, 0x08, 0x70, 0xF8, 0xBD, 0x43, 0x48, 0xE9, 0x89, 0xD0, 0xF8, 0x00, 0x28, 0x0B, 0x01, 0x22, 0xF4, 0xFE, 0x62, ++0x03, 0xF4, 0xFE, 0x63, 0x13, 0x43, 0x07, 0x22, 0xC0, 0xF8, 0x00, 0x38, 0x2A, 0x70, 0x00, 0x29, 0x40, 0xF0, 0xF2, 0x81, ++0x02, 0x23, 0x3B, 0x70, 0x04, 0x2E, 0x40, 0xF0, 0x9F, 0x80, 0x3B, 0x78, 0x04, 0x2B, 0x01, 0xD0, 0xFF, 0xF7, 0xE8, 0xFA, ++0x2B, 0x78, 0x03, 0x2B, 0x26, 0xD0, 0x04, 0x2B, 0x00, 0xF0, 0xAB, 0x80, 0x07, 0x2B, 0x00, 0xF0, 0x91, 0x80, 0x00, 0x24, ++0x22, 0x46, 0x20, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x2C, 0x70, 0xFF, 0xF7, 0x2F, 0xFB, 0x22, 0x46, 0x20, 0x46, 0x4F, 0xF4, ++0x00, 0x11, 0xFF, 0xF7, 0x85, 0xFB, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0x49, 0xBA, 0x2B, 0x4B, 0x1B, 0x68, 0x5B, 0x68, ++0xEA, 0xE6, 0x2C, 0x48, 0xFC, 0xF7, 0x8A, 0xFE, 0x04, 0x2E, 0xE4, 0xD1, 0x3B, 0x78, 0x04, 0x2B, 0xE1, 0xD0, 0xFF, 0xF7, ++0xBF, 0xFA, 0xDE, 0xE7, 0x6B, 0x68, 0x00, 0x2B, 0x7F, 0xF4, 0x57, 0xAF, 0x25, 0x4B, 0x6B, 0x60, 0x53, 0xE7, 0x04, 0x2E, ++0xD5, 0xD1, 0x3B, 0x78, 0x04, 0x2B, 0xF0, 0xD1, 0xD1, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0x00, 0xF0, 0xCB, 0x81, 0x2B, 0x8A, ++0x00, 0x2B, 0xE3, 0xD1, 0x2B, 0x7B, 0x03, 0xF0, 0x1F, 0x03, 0x01, 0x2B, 0x00, 0xF0, 0xCF, 0x81, 0x02, 0x2B, 0x00, 0xF0, ++0xC1, 0x80, 0x00, 0x2B, 0xE7, 0xD1, 0x19, 0x4A, 0x19, 0x4B, 0x12, 0x78, 0x1A, 0x80, 0x02, 0x21, 0x04, 0x22, 0x6B, 0x60, ++0x29, 0x81, 0x2A, 0x70, 0x5A, 0xE0, 0x3B, 0x78, 0x04, 0x2B, 0x02, 0xD0, 0x2B, 0x8A, 0x00, 0x2B, 0xC8, 0xD1, 0x2B, 0x7B, ++0x13, 0xF0, 0x1F, 0x03, 0x00, 0xF0, 0xB9, 0x81, 0x02, 0x2B, 0x03, 0xD1, 0xEB, 0x89, 0x00, 0x2B, 0x00, 0xF0, 0xBF, 0x81, ++0x07, 0x23, 0x04, 0x2E, 0x2B, 0x70, 0xA0, 0xD1, 0xC9, 0xE7, 0x00, 0xBF, 0xB4, 0x27, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, ++0x20, 0x26, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x98, 0x84, 0x15, 0x00, 0x70, 0x26, 0x17, 0x00, ++0xD8, 0x84, 0x15, 0x00, 0x74, 0x26, 0x17, 0x00, 0x6E, 0x26, 0x17, 0x00, 0x50, 0x28, 0x17, 0x00, 0x3B, 0x78, 0x04, 0x2B, ++0x02, 0xD0, 0x2B, 0x8A, 0x00, 0x2B, 0x9B, 0xD1, 0x2B, 0x7B, 0x03, 0xF0, 0x1F, 0x03, 0x02, 0x2B, 0xD8, 0xD1, 0xEB, 0x89, ++0x00, 0x2B, 0xD5, 0xD1, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, 0xC0, 0xF3, 0xC0, 0x10, 0xFF, 0xF7, 0xBF, 0xFB, 0x07, 0x23, ++0x04, 0x2E, 0x2B, 0x70, 0x00, 0xF0, 0x95, 0x81, 0xFF, 0xF7, 0xE6, 0xF9, 0xE7, 0xE6, 0xA9, 0x4B, 0xD3, 0xF8, 0xE0, 0x34, ++0x98, 0x47, 0x04, 0x46, 0x04, 0x2E, 0x5A, 0xD0, 0x00, 0x2C, 0x7F, 0xF4, 0x59, 0xAF, 0x60, 0xE7, 0xA4, 0x4B, 0x6B, 0x60, ++0x02, 0x22, 0x04, 0x23, 0x2A, 0x81, 0x2B, 0x70, 0x04, 0x2E, 0x3F, 0xF4, 0x4A, 0xAF, 0x29, 0x89, 0x68, 0x68, 0xFF, 0xF7, ++0x43, 0xFA, 0xCE, 0xE6, 0xE8, 0x89, 0x03, 0x0A, 0x01, 0x3B, 0x01, 0x0A, 0x0E, 0x2B, 0x3F, 0xF6, 0x62, 0xAF, 0x01, 0xA2, ++0x52, 0xF8, 0x23, 0xF0, 0xC1, 0x97, 0x12, 0x00, 0x05, 0x98, 0x12, 0x00, 0xF1, 0x97, 0x12, 0x00, 0xFF, 0x95, 0x12, 0x00, ++0xFF, 0x95, 0x12, 0x00, 0x65, 0x98, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, ++0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, ++0x45, 0x98, 0x12, 0x00, 0xA3, 0x69, 0x00, 0x2B, 0x3F, 0xF4, 0x40, 0xAF, 0xE9, 0x89, 0x28, 0x8A, 0x98, 0x47, 0x00, 0x28, ++0x3F, 0xF4, 0x3A, 0xAF, 0x85, 0x4A, 0x86, 0x4B, 0x29, 0x8A, 0x11, 0x80, 0xEA, 0x89, 0x1A, 0x70, 0x07, 0x23, 0x2B, 0x70, ++0x06, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0xDA, 0xB2, 0x7F, 0xF4, 0x2C, 0xAF, 0x7E, 0x4B, 0x7F, 0x49, 0x18, 0x88, 0x2A, 0x70, ++0x01, 0x23, 0x28, 0x82, 0x69, 0x60, 0x2B, 0x81, 0xAE, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0xA1, 0xD0, 0xFF, 0xF7, 0xE4, 0xF9, ++0x00, 0x2C, 0x7F, 0xF4, 0xF9, 0xAE, 0x00, 0xE7, 0x01, 0x46, 0xFF, 0xF7, 0x0B, 0xFB, 0x00, 0x28, 0x00, 0xF0, 0x05, 0x81, ++0x74, 0x4B, 0x01, 0x22, 0x1A, 0x80, 0x3A, 0xE7, 0x23, 0x68, 0x01, 0x20, 0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0x0A, 0xAF, ++0x03, 0x78, 0x12, 0x2B, 0x7F, 0xF4, 0x06, 0xAF, 0x42, 0x78, 0x01, 0x2A, 0x7F, 0xF4, 0x02, 0xAF, 0x2B, 0x81, 0x68, 0x60, ++0x6B, 0x8A, 0x2A, 0x89, 0x9A, 0x42, 0x88, 0xBF, 0x2B, 0x81, 0x04, 0x23, 0x2B, 0x70, 0x83, 0xE7, 0xA3, 0x68, 0xC0, 0xB2, ++0x98, 0x47, 0x68, 0x60, 0x00, 0x28, 0x3F, 0xF4, 0xF1, 0xAE, 0x03, 0x78, 0x2B, 0x81, 0xED, 0xE7, 0x63, 0x68, 0x00, 0x20, ++0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0xE8, 0xAE, 0x03, 0x78, 0x09, 0x2B, 0x7F, 0xF4, 0xE4, 0xAE, 0x43, 0x78, 0x02, 0x2B, ++0x7F, 0xF4, 0xE0, 0xAE, 0xC2, 0x78, 0x83, 0x78, 0x68, 0x60, 0x43, 0xEA, 0x02, 0x23, 0x2B, 0x81, 0xC3, 0x79, 0x58, 0x4A, ++0x13, 0xF0, 0x40, 0x0F, 0x13, 0x78, 0x14, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x70, 0xCD, 0xE7, ++0x23, 0x68, 0x0F, 0x20, 0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0xC8, 0xAE, 0x03, 0x78, 0x05, 0x2B, 0x7F, 0xF4, 0xC4, 0xAE, ++0x43, 0x78, 0x0F, 0x2B, 0x7F, 0xF4, 0xC0, 0xAE, 0x83, 0x78, 0xBB, 0xE7, 0x23, 0x68, 0x06, 0x20, 0x98, 0x47, 0x00, 0x28, ++0x3F, 0xF4, 0xB8, 0xAE, 0x03, 0x78, 0x0A, 0x2B, 0x7F, 0xF4, 0xB4, 0xAE, 0x42, 0x78, 0x06, 0x2A, 0x7F, 0xF4, 0xB0, 0xAE, ++0xAC, 0xE7, 0x2B, 0x78, 0x00, 0x2B, 0x51, 0xD1, 0x01, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x00, 0x21, 0x01, 0x20, 0xFF, 0xF7, ++0xB3, 0xFA, 0x84, 0xE5, 0x68, 0x89, 0x2B, 0x89, 0x36, 0x88, 0x6A, 0x68, 0x3C, 0x49, 0x1B, 0x1A, 0xC6, 0xF1, 0x40, 0x06, ++0x9B, 0xB2, 0x9E, 0x42, 0xA8, 0xBF, 0x1E, 0x46, 0x10, 0x44, 0x09, 0x68, 0xB2, 0xB2, 0x2D, 0xF0, 0x07, 0xFC, 0x6A, 0x89, ++0x2B, 0x89, 0x16, 0x44, 0xB6, 0xB2, 0xB3, 0x42, 0x6E, 0x81, 0x7F, 0xF4, 0x11, 0xAE, 0x33, 0x4B, 0x1B, 0x69, 0x0B, 0xB1, ++0x28, 0x46, 0x98, 0x47, 0xA0, 0x06, 0x35, 0xD4, 0x06, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x29, 0x89, 0x6A, 0x89, 0x88, 0x1A, ++0x80, 0xB2, 0x30, 0xB9, 0x05, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x2B, 0x48, 0xFC, 0xF7, 0x00, 0xFD, 0x88, 0xE5, 0x40, 0x28, ++0x22, 0xD0, 0x40, 0x28, 0x28, 0xBF, 0x40, 0x20, 0x00, 0x26, 0x02, 0x44, 0x92, 0xB2, 0x91, 0x42, 0x6A, 0x81, 0x29, 0xD3, ++0x89, 0x1A, 0x89, 0xB2, 0x40, 0x29, 0x0F, 0xD8, 0x79, 0xB9, 0x66, 0xBB, 0x21, 0x4A, 0x05, 0x23, 0x2B, 0x70, 0xD2, 0xF8, ++0x10, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x10, 0x38, 0xF8, 0xBD, 0x01, 0x20, 0xFF, 0xF7, 0x65, 0xFA, 0xA9, 0xE7, ++0x40, 0x21, 0x68, 0x68, 0x10, 0x44, 0xFF, 0xF7, 0x27, 0xF9, 0x98, 0xE5, 0x01, 0x26, 0xDE, 0xE7, 0xFF, 0xF7, 0x8E, 0xF8, ++0x15, 0x4A, 0x07, 0x23, 0x2B, 0x70, 0xD2, 0xF8, 0x14, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xFF, 0xF7, ++0xA1, 0xF8, 0x8A, 0xE5, 0x10, 0x48, 0xFC, 0xF7, 0xC7, 0xFC, 0x29, 0x89, 0x6A, 0x89, 0xCF, 0xE7, 0x03, 0x23, 0x3B, 0x70, ++0x0C, 0xE6, 0x08, 0x46, 0xFF, 0xF7, 0x0A, 0xF9, 0x7B, 0xE5, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x6C, 0x26, 0x17, 0x00, ++0x6A, 0x26, 0x17, 0x00, 0x68, 0x26, 0x17, 0x00, 0x50, 0x28, 0x17, 0x00, 0x6E, 0x26, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, ++0x20, 0x26, 0x17, 0x00, 0xB4, 0x84, 0x15, 0x00, 0x00, 0x00, 0x20, 0x40, 0xF0, 0x84, 0x15, 0x00, 0x2B, 0x7B, 0x03, 0xF0, ++0x1F, 0x03, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x7F, 0xF4, 0x39, 0xAE, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, 0x04, 0x29, ++0x2A, 0xD9, 0x17, 0x4B, 0x00, 0x22, 0x1A, 0x80, 0x35, 0xE6, 0xE8, 0x89, 0x02, 0x28, 0x19, 0xD0, 0x00, 0xF1, 0xFF, 0x3C, ++0x07, 0x23, 0xDC, 0xF1, 0x00, 0x04, 0x44, 0xEB, 0x0C, 0x04, 0x2B, 0x70, 0x7E, 0xE6, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, ++0xC0, 0xF3, 0xC0, 0x10, 0xFF, 0xF7, 0x18, 0xFA, 0x07, 0x23, 0x04, 0x2E, 0x2B, 0x70, 0x7F, 0xF4, 0x6B, 0xAE, 0x3B, 0x78, ++0x04, 0x2B, 0x3F, 0xF4, 0x67, 0xAE, 0xC9, 0xE5, 0x2B, 0x8A, 0x07, 0x49, 0x1B, 0x0A, 0x07, 0x22, 0x04, 0x2E, 0x0B, 0x70, ++0x2A, 0x70, 0x7F, 0xF4, 0x5D, 0xAE, 0xF0, 0xE7, 0xC0, 0xF3, 0xC0, 0x10, 0xC7, 0xE6, 0x00, 0xBF, 0x50, 0x28, 0x17, 0x00, ++0x70, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xB4, 0x4B, 0xB5, 0x4D, 0xD3, 0xF8, 0x00, 0x38, 0x13, 0xF4, 0xFE, 0x6F, ++0x03, 0xD0, 0x2B, 0x78, 0x04, 0x2B, 0x00, 0xF0, 0x8F, 0x81, 0xAF, 0x4C, 0xB0, 0x4A, 0xB1, 0x48, 0x00, 0x21, 0x02, 0x23, ++0x2B, 0x70, 0x11, 0x70, 0x1A, 0xF0, 0x1A, 0xFE, 0xD4, 0xF8, 0x00, 0x3E, 0x23, 0xF0, 0x01, 0x03, 0xC4, 0xF8, 0x00, 0x3E, ++0xD4, 0xF8, 0x04, 0x38, 0x23, 0xF0, 0x01, 0x03, 0xC4, 0xF8, 0x04, 0x38, 0xFF, 0xF7, 0x7E, 0xF8, 0xA3, 0x69, 0x1D, 0x06, ++0x03, 0xD5, 0xA3, 0x69, 0x23, 0xF0, 0x80, 0x03, 0xA3, 0x61, 0xA0, 0x4B, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF4, 0x00, 0x72, ++0xC3, 0xF8, 0x04, 0x28, 0x5A, 0x69, 0x14, 0x06, 0xFC, 0xD5, 0x01, 0x23, 0x01, 0x2B, 0x9E, 0x4C, 0x9E, 0x4D, 0x9F, 0x4A, ++0x9F, 0x4F, 0x4F, 0xF0, 0x02, 0x0C, 0x1C, 0xD0, 0x4F, 0xEA, 0x43, 0x1E, 0x5E, 0xF8, 0x02, 0x10, 0x11, 0xF0, 0x80, 0x2F, ++0x10, 0xD0, 0x5E, 0xF8, 0x02, 0x00, 0x00, 0x29, 0x40, 0xEA, 0x05, 0x00, 0x4E, 0xF8, 0x02, 0x00, 0xC0, 0xF2, 0x0F, 0x81, ++0x08, 0x04, 0x05, 0xD4, 0x5E, 0xF8, 0x02, 0x10, 0x21, 0xF4, 0x00, 0x41, 0x4E, 0xF8, 0x02, 0x10, 0x05, 0x2B, 0x0A, 0xD0, ++0x01, 0x33, 0x01, 0x2B, 0xE2, 0xD1, 0x21, 0x68, 0x11, 0xF0, 0x80, 0x2F, 0xF8, 0xD0, 0x21, 0x68, 0x29, 0x43, 0x21, 0x60, ++0xF4, 0xE7, 0x84, 0x4B, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF4, 0x80, 0x62, 0xC3, 0xF8, 0x04, 0x28, 0xD3, 0xF8, 0x04, 0x28, ++0x42, 0xF0, 0x80, 0x02, 0xC3, 0xF8, 0x04, 0x28, 0x5A, 0x69, 0x51, 0x06, 0xFC, 0xD5, 0x01, 0x23, 0x01, 0x2B, 0x83, 0x4F, ++0xDF, 0xF8, 0x40, 0x82, 0xDF, 0xF8, 0xF8, 0xC1, 0x81, 0x4D, 0xDF, 0xF8, 0x3C, 0xE2, 0x4F, 0xF0, 0x40, 0x06, 0x4F, 0xF0, ++0x02, 0x09, 0x19, 0xD0, 0x5A, 0x01, 0x05, 0xEB, 0x43, 0x10, 0x51, 0x59, 0x11, 0xF0, 0x80, 0x2F, 0x0D, 0xD0, 0x72, 0x44, ++0x16, 0x60, 0x04, 0x68, 0x00, 0x29, 0x44, 0xEA, 0x0C, 0x04, 0x04, 0x60, 0x11, 0xDB, 0x0A, 0x04, 0x03, 0xD4, 0x02, 0x68, ++0x22, 0xF4, 0x00, 0x42, 0x02, 0x60, 0x05, 0x2B, 0x1A, 0xD0, 0x01, 0x33, 0x01, 0x2B, 0xE5, 0xD1, 0x39, 0x68, 0x11, 0xF0, ++0x80, 0x2F, 0xF8, 0xD0, 0x42, 0x46, 0x38, 0x46, 0xE6, 0xE7, 0x8C, 0x03, 0x09, 0xD5, 0xC2, 0xF8, 0x00, 0x90, 0x04, 0x68, ++0x44, 0xF0, 0x80, 0x44, 0x04, 0x60, 0x14, 0x68, 0xA4, 0x07, 0xFC, 0xD5, 0xE1, 0xE7, 0x14, 0x68, 0x64, 0x06, 0xFC, 0xD5, ++0x16, 0x60, 0xF0, 0xE7, 0x5B, 0x4B, 0x4F, 0xF4, 0x86, 0x62, 0x1A, 0x61, 0x1A, 0x69, 0x12, 0xF0, 0x30, 0x0F, 0xFB, 0xD1, ++0xD3, 0xF8, 0x04, 0x28, 0x4F, 0xF0, 0x01, 0x14, 0x42, 0xF4, 0x80, 0x72, 0x29, 0x20, 0x09, 0x21, 0xC3, 0xF8, 0x04, 0x28, ++0xC3, 0xF8, 0x1C, 0x48, 0xC3, 0xF8, 0x14, 0x08, 0xC3, 0xF8, 0x10, 0x18, 0x9A, 0x69, 0x42, 0xF4, 0x40, 0x22, 0x9A, 0x61, ++0x9A, 0x6C, 0x14, 0x03, 0x4C, 0xD4, 0x4C, 0x4D, 0x55, 0x4B, 0xD5, 0xF8, 0x00, 0x28, 0x55, 0x48, 0x00, 0x24, 0x22, 0xF4, ++0xFE, 0x62, 0xC5, 0xF8, 0x00, 0x28, 0x21, 0x46, 0xC3, 0xE9, 0x01, 0x44, 0x40, 0x22, 0x1C, 0x70, 0xF6, 0xF7, 0xDE, 0xFA, ++0x21, 0x46, 0x40, 0x22, 0x4E, 0x48, 0xF6, 0xF7, 0xD9, 0xFA, 0x4E, 0x4A, 0x4E, 0x4B, 0x11, 0x68, 0x4E, 0x4A, 0x1B, 0x68, ++0x12, 0x68, 0x59, 0x60, 0xC5, 0xF8, 0x14, 0x3B, 0xD1, 0x78, 0x4C, 0x4B, 0x4C, 0x48, 0x1F, 0x68, 0x4C, 0x4B, 0x06, 0x6A, ++0x18, 0x68, 0xD3, 0xF8, 0x04, 0xC0, 0x41, 0xF0, 0xC0, 0x01, 0xD1, 0x70, 0xF9, 0x78, 0x41, 0xF0, 0xC0, 0x01, 0xF9, 0x70, ++0xC1, 0x78, 0x41, 0xF0, 0xC0, 0x01, 0xC1, 0x70, 0x9C, 0xF8, 0x03, 0x10, 0xD3, 0xE9, 0x02, 0x70, 0x41, 0xF0, 0xC0, 0x03, ++0x8C, 0xF8, 0x03, 0x30, 0xFB, 0x78, 0x43, 0xF0, 0xC0, 0x03, 0xFB, 0x70, 0xC3, 0x78, 0x43, 0xF0, 0xC0, 0x03, 0xC3, 0x70, ++0xC5, 0xF8, 0x14, 0x29, 0x0E, 0xB1, 0x20, 0x46, 0xB0, 0x47, 0xBD, 0xE8, 0xF8, 0x43, 0x3A, 0x48, 0x1A, 0xF0, 0x10, 0xBD, ++0x39, 0x49, 0x3A, 0x4C, 0x24, 0x4A, 0x40, 0xF2, 0x17, 0x15, 0x5D, 0x62, 0x4F, 0xF4, 0x9C, 0x70, 0x9C, 0x62, 0x08, 0x80, ++0xD3, 0xF8, 0x04, 0x18, 0x41, 0xF0, 0x80, 0x01, 0xC3, 0xF8, 0x04, 0x18, 0x53, 0x69, 0x58, 0x06, 0xFC, 0xD5, 0x1C, 0x49, ++0x0B, 0x69, 0x00, 0x2B, 0xFC, 0xDA, 0x4F, 0xF4, 0x84, 0x63, 0x19, 0x4A, 0x0B, 0x61, 0x13, 0x69, 0x99, 0x06, 0xFC, 0xD4, ++0xD2, 0xF8, 0x04, 0x38, 0x15, 0x49, 0x43, 0xF4, 0x80, 0x73, 0xC2, 0xF8, 0x04, 0x38, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, ++0x00, 0x73, 0xC2, 0xF8, 0x04, 0x38, 0x4B, 0x69, 0x1A, 0x06, 0xFC, 0xD5, 0x0B, 0x69, 0x0E, 0x4A, 0x43, 0xF0, 0x10, 0x03, ++0x0B, 0x61, 0x13, 0x69, 0xDB, 0x06, 0xFC, 0xD4, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x80, 0x63, 0xC2, 0xF8, 0x04, 0x38, ++0x75, 0xE7, 0x4E, 0xF8, 0x07, 0xC0, 0x5E, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x80, 0x40, 0x4E, 0xF8, 0x02, 0x00, 0x0E, 0xEB, ++0x07, 0x06, 0x30, 0x68, 0x80, 0x07, 0xFC, 0xD5, 0xE2, 0xE6, 0x00, 0xBF, 0x00, 0x00, 0x20, 0x40, 0x6F, 0x26, 0x17, 0x00, ++0x6E, 0x26, 0x17, 0x00, 0x20, 0x85, 0x15, 0x00, 0x00, 0x0B, 0x20, 0x40, 0x00, 0x80, 0x00, 0x08, 0xE0, 0x0A, 0x20, 0x40, ++0xE8, 0x0A, 0x20, 0x40, 0x00, 0x09, 0x20, 0x40, 0xE0, 0x08, 0x20, 0x40, 0xB4, 0x27, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, ++0xC8, 0x27, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x20, 0x26, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, 0x28, 0x85, 0x15, 0x00, 0x48, 0x28, 0x17, 0x00, 0x17, 0x01, 0x21, 0x00, ++0x08, 0x09, 0x20, 0x40, 0xE8, 0x08, 0x20, 0x40, 0x05, 0x48, 0x1E, 0x21, 0x1A, 0xF0, 0x90, 0xFC, 0x4F, 0xF4, 0xF0, 0x42, ++0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0x7F, 0xFC, 0x64, 0xE6, 0x0C, 0x85, 0x15, 0x00, 0x08, 0xB5, 0x04, 0x49, ++0x04, 0x48, 0x1A, 0xF0, 0x81, 0xFC, 0x04, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x08, 0xBD, 0x00, 0xBF, 0x54, 0x85, 0x15, 0x00, ++0xCC, 0xB5, 0x15, 0x00, 0x52, 0x28, 0x17, 0x00, 0x01, 0x4B, 0x18, 0x78, 0x70, 0x47, 0x00, 0xBF, 0x52, 0x28, 0x17, 0x00, ++0x08, 0xB5, 0x07, 0x48, 0x1A, 0xF0, 0x6C, 0xFC, 0x06, 0x4B, 0x07, 0x4A, 0x00, 0x21, 0x19, 0x70, 0xD2, 0xF8, 0x00, 0x3E, ++0x23, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x00, 0x3E, 0x08, 0xBD, 0x00, 0xBF, 0x30, 0x85, 0x15, 0x00, 0x52, 0x28, 0x17, 0x00, ++0x00, 0x00, 0x20, 0x40, 0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x1A, 0x4C, 0x1A, 0x4D, 0x23, 0x68, 0x2A, 0x78, 0x01, 0x33, 0x23, 0x60, 0x1A, 0xB1, 0x18, 0x4A, 0x12, 0x78, ++0x04, 0x2A, 0x08, 0xD0, 0x33, 0xB1, 0x13, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x38, 0xBD, 0x13, 0x4A, 0x13, 0x49, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x0A, 0x69, ++0x02, 0xF5, 0x0C, 0x52, 0x28, 0x32, 0x0B, 0x69, 0xD3, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x0B, 0x4A, 0x0C, 0x48, 0xD2, 0xF8, ++0x04, 0x38, 0x23, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x1A, 0xF0, 0x23, 0xFC, 0x00, 0x22, 0x23, 0x68, 0x2A, 0x70, ++0xD8, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x52, 0x28, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, ++0x00, 0x00, 0x20, 0x40, 0x00, 0x10, 0x50, 0x40, 0x3C, 0x85, 0x15, 0x00, 0x38, 0xB5, 0x04, 0x46, 0x0D, 0x46, 0xFF, 0xF7, ++0xB1, 0xFF, 0x15, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x20, 0xD1, 0x62, 0x1E, 0xD3, 0xB2, 0x04, 0x2B, 0x1E, 0xD8, 0x60, 0x01, ++0x00, 0xF1, 0x80, 0x40, 0x00, 0xF5, 0x00, 0x10, 0xD0, 0xF8, 0x00, 0x39, 0x1B, 0x04, 0x17, 0xD5, 0x0D, 0x49, 0x53, 0x01, ++0x03, 0xF1, 0x80, 0x43, 0x01, 0xEB, 0x02, 0x12, 0x03, 0xF5, 0x00, 0x13, 0x01, 0x21, 0xD1, 0x72, 0xC3, 0xF8, 0x34, 0x59, ++0xD0, 0xF8, 0x00, 0x39, 0x43, 0xF0, 0x04, 0x43, 0xC0, 0xF8, 0x00, 0x39, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x20, 0x38, 0xBD, ++0x02, 0x20, 0x38, 0xBD, 0x05, 0x20, 0x38, 0xBD, 0x6F, 0x26, 0x17, 0x00, 0xC8, 0x27, 0x17, 0x00, 0x93, 0x4B, 0x5A, 0x69, ++0x2D, 0xE9, 0xF0, 0x4F, 0x5A, 0x61, 0x9C, 0x69, 0x14, 0x40, 0xE1, 0x04, 0x85, 0xB0, 0x0A, 0xD5, 0x8F, 0x4B, 0xD3, 0xF8, ++0xDC, 0x34, 0x98, 0x47, 0x14, 0xF4, 0x00, 0x5A, 0x40, 0xF0, 0xAB, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, ++0x44, 0xA2, 0xA2, 0x04, 0x04, 0xEA, 0x0A, 0x0A, 0x04, 0xF4, 0x80, 0x25, 0x04, 0xF4, 0x00, 0x29, 0x04, 0xF4, 0x00, 0x6B, ++0x00, 0xF1, 0x9F, 0x80, 0x00, 0x2D, 0x42, 0xD0, 0x81, 0x4D, 0x83, 0x4E, 0xD5, 0xF8, 0x18, 0x28, 0xD5, 0xF8, 0x1C, 0x38, ++0x00, 0x24, 0x02, 0xEA, 0x03, 0x08, 0x01, 0x20, 0x00, 0xFA, 0x04, 0xF3, 0x13, 0xEA, 0x08, 0x0F, 0xE7, 0xB2, 0x2D, 0xD0, ++0x00, 0x2C, 0x00, 0xF0, 0xA0, 0x80, 0x63, 0x1E, 0x05, 0xEB, 0x43, 0x13, 0xD3, 0xF8, 0x28, 0x29, 0xC3, 0xF8, 0x28, 0x29, ++0xD5, 0xF8, 0x10, 0x18, 0x11, 0x40, 0x11, 0xF0, 0x09, 0x0F, 0x74, 0xD0, 0x16, 0xF8, 0x05, 0x3C, 0xD3, 0xB1, 0x56, 0xF8, ++0x0C, 0x3C, 0x01, 0x93, 0xD2, 0x43, 0x56, 0xF8, 0x10, 0x3C, 0x02, 0x93, 0x12, 0xF0, 0x01, 0x03, 0x00, 0x93, 0x40, 0xF0, ++0xB6, 0x80, 0x10, 0x22, 0x00, 0x21, 0xA6, 0xF1, 0x10, 0x00, 0xF6, 0xF7, 0x15, 0xF9, 0x6A, 0x4B, 0x03, 0xEB, 0x84, 0x03, ++0x1B, 0x6B, 0x1B, 0xB1, 0xDD, 0xE9, 0x00, 0x21, 0x02, 0x98, 0x98, 0x47, 0x04, 0x2F, 0x02, 0xD0, 0x01, 0x34, 0x10, 0x36, ++0xC5, 0xE7, 0xB9, 0xF1, 0x00, 0x0F, 0x3C, 0xD0, 0x5E, 0x4D, 0x62, 0x4E, 0xD5, 0xF8, 0x18, 0x78, 0xD5, 0xF8, 0x1C, 0x38, ++0xDF, 0xF8, 0x90, 0x81, 0xDF, 0xF8, 0x74, 0x91, 0x1F, 0x40, 0x00, 0x24, 0x4F, 0xF4, 0x80, 0x33, 0xA3, 0x40, 0x3B, 0x42, ++0x0C, 0xD0, 0xC4, 0xB1, 0x63, 0x1E, 0x05, 0xEB, 0x43, 0x13, 0xD3, 0xF8, 0x28, 0x2B, 0xC3, 0xF8, 0x28, 0x2B, 0xD5, 0xF8, ++0x14, 0x38, 0x13, 0x40, 0xDB, 0x07, 0x5F, 0xD4, 0xE3, 0xB2, 0x04, 0x2B, 0x1B, 0xD0, 0x01, 0x34, 0x4F, 0xF4, 0x80, 0x33, ++0xA3, 0x40, 0x3B, 0x42, 0x06, 0xF1, 0x10, 0x06, 0xF4, 0xD0, 0x00, 0x2C, 0xE6, 0xD1, 0xD5, 0xF8, 0x08, 0x1B, 0xC5, 0xF8, ++0x08, 0x1B, 0xD5, 0xF8, 0x14, 0x38, 0x0B, 0x40, 0xDA, 0x06, 0x7B, 0xD4, 0x13, 0xF0, 0x29, 0x0F, 0xE9, 0xD0, 0x44, 0x4B, ++0x20, 0x46, 0xD3, 0xF8, 0x00, 0x31, 0x98, 0x47, 0xE3, 0xE7, 0xBB, 0xF1, 0x00, 0x0F, 0x03, 0xD0, 0x3F, 0x4B, 0xD3, 0xF8, ++0x8C, 0x34, 0x98, 0x47, 0xBA, 0xF1, 0x00, 0x0F, 0xBF, 0xF6, 0x60, 0xAF, 0x3B, 0x4B, 0xD3, 0xF8, 0x90, 0x34, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x3C, 0x48, 0xFC, 0xF7, 0x56, 0xF9, 0xA4, 0xE7, 0x4F, 0xF0, 0x00, 0x0B, 0xD9, 0x46, ++0x5D, 0x46, 0x33, 0x4B, 0xD3, 0xF8, 0x08, 0x38, 0x13, 0xF0, 0x06, 0x0F, 0xC3, 0xF3, 0x47, 0x02, 0x04, 0xD0, 0xD3, 0x07, ++0x02, 0xD5, 0x34, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2C, 0x4B, 0x33, 0x4A, 0xC3, 0xF8, 0x00, 0x29, 0xC3, 0xF8, 0x00, 0x2B, ++0xFE, 0xF7, 0xF4, 0xFC, 0x4A, 0xE7, 0xD5, 0xF8, 0x08, 0x19, 0xC5, 0xF8, 0x08, 0x19, 0xD5, 0xF8, 0x10, 0x38, 0x0B, 0x40, ++0x13, 0xF0, 0x18, 0x0F, 0x2B, 0xD1, 0xDF, 0x07, 0x80, 0xD5, 0x23, 0x4B, 0xD3, 0xF8, 0x00, 0x31, 0x98, 0x47, 0x7B, 0xE7, ++0x16, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0x9B, 0xD0, 0x58, 0xF8, 0x24, 0x30, 0x56, 0xF8, 0x0C, 0x1C, 0x1B, 0x88, 0x02, 0x93, ++0x30, 0x46, 0xA3, 0x00, 0x50, 0xF8, 0x10, 0x2D, 0x03, 0x92, 0x01, 0x91, 0x10, 0x22, 0x00, 0x21, 0x00, 0x93, 0xF6, 0xF7, ++0x71, 0xF8, 0x00, 0x9B, 0x4B, 0x44, 0x1B, 0x6A, 0x00, 0x2B, 0x85, 0xD0, 0xDD, 0xE9, 0x01, 0x01, 0x00, 0x22, 0x41, 0x1A, ++0x03, 0x98, 0x98, 0x47, 0x7E, 0xE7, 0x39, 0x46, 0xFE, 0xF7, 0x8A, 0xFE, 0x45, 0xE7, 0xD5, 0xF8, 0x10, 0x38, 0x23, 0xF0, ++0x10, 0x03, 0xC5, 0xF8, 0x10, 0x38, 0x22, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x20, 0x46, 0xFE, 0xF7, 0xE9, 0xFD, 0x49, 0xE7, ++0xD5, 0xF8, 0x14, 0x38, 0x23, 0xF0, 0x10, 0x03, 0xC5, 0xF8, 0x14, 0x38, 0x22, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x20, 0x46, ++0xFE, 0xF7, 0x80, 0xFD, 0x63, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x20, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x27, 0x17, 0x00, ++0x20, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x48, 0x85, 0x15, 0x00, 0x4C, 0x28, 0x17, 0x00, 0x00, 0x80, 0x00, 0x08, ++0x00, 0x3C, 0x0C, 0x88, 0x40, 0x60, 0x17, 0x00, 0x38, 0xB9, 0x0C, 0x4A, 0x0C, 0x4B, 0x10, 0x70, 0x18, 0x70, 0x0C, 0x4B, ++0x1B, 0x68, 0x5B, 0xB1, 0x18, 0x47, 0x01, 0x28, 0x09, 0xD0, 0x09, 0x4B, 0x02, 0x38, 0x1B, 0x68, 0x01, 0x28, 0x94, 0xBF, ++0x02, 0x20, 0x03, 0x20, 0x00, 0x2B, 0xF3, 0xD1, 0x70, 0x47, 0x05, 0x4A, 0x05, 0x4B, 0x10, 0x70, 0x18, 0x70, 0xEA, 0xE7, ++0x59, 0x28, 0x17, 0x00, 0x5A, 0x28, 0x17, 0x00, 0x60, 0x28, 0x17, 0x00, 0x5B, 0x28, 0x17, 0x00, 0x5C, 0x28, 0x17, 0x00, ++0x00, 0x48, 0x70, 0x47, 0x54, 0x86, 0x15, 0x00, 0x01, 0x28, 0x15, 0xD1, 0x08, 0xB5, 0x0B, 0x4B, 0x1B, 0x68, 0x0B, 0xB1, ++0x04, 0x20, 0x98, 0x47, 0x02, 0x22, 0x11, 0x46, 0x4F, 0xF4, 0x00, 0x73, 0x01, 0x20, 0xFE, 0xF7, 0x65, 0xFF, 0x4F, 0xF4, ++0x00, 0x73, 0x02, 0x22, 0x01, 0x21, 0x00, 0x20, 0xFE, 0xF7, 0x5E, 0xFF, 0x01, 0x20, 0x08, 0xBD, 0x00, 0x20, 0x70, 0x47, ++0x60, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x58, 0x4E, 0xDF, 0xF8, 0x9C, 0xE1, 0x33, 0x88, 0x57, 0x4C, 0x00, 0x2A, ++0x03, 0xF1, 0x01, 0x03, 0x0C, 0xBF, 0x02, 0x25, 0x03, 0x25, 0x9B, 0xB2, 0x00, 0x27, 0x33, 0x80, 0x8E, 0xF8, 0x00, 0x50, ++0x27, 0x70, 0x9E, 0xF8, 0x00, 0xC0, 0xBC, 0xF1, 0x02, 0x0F, 0x4C, 0xD1, 0x03, 0x29, 0x04, 0x46, 0x0D, 0x46, 0x8E, 0xF8, ++0x00, 0x70, 0x55, 0xD9, 0x43, 0x78, 0x4C, 0x4A, 0x07, 0x78, 0x12, 0x78, 0x90, 0xF8, 0x02, 0x80, 0x1B, 0x02, 0x03, 0xF4, ++0x70, 0x63, 0x1F, 0x43, 0x00, 0x2A, 0x78, 0xD1, 0xB8, 0xF1, 0x01, 0x0F, 0x64, 0xD0, 0xB8, 0xF1, 0x11, 0x0F, 0x55, 0xD1, ++0xDF, 0xF8, 0x44, 0x81, 0x98, 0xF8, 0x9D, 0x27, 0x98, 0xF8, 0x9E, 0x37, 0x9A, 0x42, 0x77, 0xD2, 0x3B, 0x1D, 0xAB, 0x42, ++0x02, 0xD0, 0x7B, 0x1D, 0x9D, 0x42, 0x6E, 0xD1, 0x3D, 0x4B, 0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x98, 0xF8, 0x9C, 0x37, ++0x3B, 0x49, 0x98, 0xF8, 0x9D, 0x27, 0x01, 0x33, 0xA1, 0xFB, 0x03, 0x01, 0x49, 0x09, 0x01, 0xEB, 0x81, 0x01, 0xA3, 0xEB, ++0xC1, 0x01, 0x08, 0xEB, 0x01, 0x15, 0x04, 0x34, 0x53, 0x1C, 0x88, 0xF8, 0x9C, 0x17, 0x34, 0x48, 0xC5, 0xF8, 0x20, 0x45, ++0x05, 0xF2, 0x1C, 0x51, 0xC5, 0xF8, 0x24, 0x75, 0x88, 0xF8, 0x9D, 0x37, 0x19, 0xF0, 0x22, 0xF8, 0x4F, 0xF4, 0x00, 0x00, ++0x18, 0xF0, 0x7C, 0xFF, 0x0B, 0xE0, 0x9E, 0xF8, 0x00, 0x10, 0x2C, 0x48, 0xFC, 0xF7, 0x28, 0xF8, 0x47, 0xF2, 0x30, 0x52, ++0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0xE1, 0xF9, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x31, 0x88, 0x26, 0x48, ++0x89, 0xB2, 0x2A, 0x46, 0xFC, 0xF7, 0x18, 0xF8, 0x24, 0x4B, 0x18, 0x68, 0x20, 0x1A, 0xFD, 0xF7, 0x05, 0xF9, 0x1D, 0x4B, ++0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x41, 0x46, 0x1F, 0x48, 0xFC, 0xF7, 0x08, 0xF8, ++0x31, 0x88, 0x1E, 0x48, 0x89, 0xB2, 0x2B, 0x46, 0x3A, 0x46, 0xFC, 0xF7, 0x01, 0xF8, 0xE7, 0xE7, 0xBD, 0x42, 0x02, 0xD0, ++0x7B, 0x1C, 0xAB, 0x42, 0x12, 0xD1, 0x11, 0x4D, 0xD5, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x20, 0x1D, 0xD5, 0xF8, 0x0C, 0x31, ++0x98, 0x47, 0x40, 0x20, 0x18, 0xF0, 0x3E, 0xFF, 0xCD, 0xE7, 0x0A, 0x46, 0x4F, 0xF4, 0x00, 0x70, 0x11, 0x49, 0x1A, 0xF0, ++0x03, 0xFA, 0x7F, 0xE7, 0x31, 0x88, 0x10, 0x48, 0xDE, 0xE7, 0x31, 0x88, 0x0F, 0x48, 0xDB, 0xE7, 0x0F, 0x48, 0xFB, 0xF7, ++0xDF, 0xFF, 0xC5, 0xE7, 0x56, 0x28, 0x17, 0x00, 0x58, 0x28, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xCD, 0xCC, 0xCC, 0xCC, 0xF8, 0x5F, 0x17, 0x00, 0xD0, 0x85, 0x15, 0x00, 0xC0, 0x85, 0x15, 0x00, 0x80, 0x1A, 0x17, 0x00, ++0xB0, 0x85, 0x15, 0x00, 0x78, 0x85, 0x15, 0x00, 0x68, 0x85, 0x15, 0x00, 0x70, 0x85, 0x15, 0x00, 0x84, 0x85, 0x15, 0x00, ++0x98, 0x85, 0x15, 0x00, 0x59, 0x28, 0x17, 0x00, 0x58, 0x58, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x2A, 0x2A, 0x4B, ++0x0C, 0xBF, 0x02, 0x21, 0x03, 0x21, 0x19, 0x70, 0x19, 0x78, 0x02, 0x29, 0x3D, 0xD1, 0x27, 0x4C, 0x22, 0x78, 0x00, 0x21, ++0x19, 0x70, 0x52, 0xB3, 0x25, 0x4D, 0x26, 0x4F, 0xA5, 0xF1, 0x08, 0x06, 0x0A, 0xE0, 0x01, 0x2A, 0x41, 0x46, 0x38, 0x46, ++0x28, 0xD1, 0x13, 0x2B, 0x40, 0x46, 0x01, 0xD0, 0xFD, 0xF7, 0x90, 0xF8, 0x23, 0x78, 0xD3, 0xB1, 0x28, 0x46, 0x18, 0xF0, ++0xCD, 0xFF, 0x42, 0x68, 0x23, 0x78, 0xD2, 0xF8, 0x04, 0x80, 0x01, 0x3B, 0x01, 0x46, 0x30, 0x46, 0x23, 0x70, 0x18, 0xF0, ++0x7F, 0xFF, 0x98, 0xF8, 0x02, 0x30, 0x1A, 0x09, 0xE3, 0xD1, 0x17, 0x4A, 0x13, 0x88, 0x10, 0x20, 0x01, 0x33, 0x13, 0x80, ++0x18, 0xF0, 0xD2, 0xFE, 0x23, 0x78, 0x00, 0x2B, 0xE4, 0xD1, 0x13, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x01, 0x20, ++0xBD, 0xE8, 0xF0, 0x81, 0xFB, 0xF7, 0x78, 0xFF, 0x40, 0x46, 0x20, 0x21, 0x1A, 0xF0, 0x1C, 0xFD, 0xD4, 0xE7, 0x19, 0x78, ++0x0C, 0x48, 0xFB, 0xF7, 0x6F, 0xFF, 0x47, 0xF2, 0x30, 0x52, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0x28, 0xF9, ++0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x5A, 0x28, 0x17, 0x00, 0x64, 0x60, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, ++0xF0, 0x85, 0x15, 0x00, 0x54, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x86, 0x15, 0x00, 0x10, 0x4B, 0x11, 0x49, ++0x11, 0x4A, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x00, 0x68, 0x18, 0x60, 0xDF, 0xF8, 0x44, 0x80, 0x0E, 0x4F, 0x0F, 0x4E, ++0x00, 0x23, 0x0B, 0x70, 0x13, 0x70, 0x29, 0x7A, 0xD8, 0xF8, 0x08, 0x31, 0x00, 0x39, 0x18, 0xBF, 0x01, 0x21, 0x38, 0x46, ++0x98, 0x47, 0x04, 0x46, 0x01, 0x46, 0x30, 0x46, 0x1A, 0xF0, 0x04, 0xF9, 0x00, 0x2C, 0xF0, 0xD1, 0x20, 0x46, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x60, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x5A, 0x28, 0x17, 0x00, 0x38, 0x1A, 0x17, 0x00, ++0x20, 0x86, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x1D, 0x4D, 0x2B, 0x78, 0xFB, 0xB9, 0xD8, 0xB1, 0x0A, 0x46, ++0xC9, 0xB1, 0x1B, 0x4F, 0x3B, 0x78, 0xE3, 0xB9, 0x1A, 0x4C, 0x01, 0x26, 0x3E, 0x70, 0xD4, 0xF8, 0x30, 0x3B, 0x23, 0xF0, ++0xFF, 0x53, 0x23, 0xF4, 0xC0, 0x13, 0x01, 0x46, 0xC4, 0xF8, 0x30, 0x3B, 0x30, 0x46, 0xFE, 0xF7, 0x7B, 0xFE, 0x04, 0x46, ++0xC8, 0xB9, 0x13, 0x4B, 0x1E, 0x70, 0x2B, 0x78, 0x73, 0xB9, 0x20, 0x46, 0xF8, 0xBD, 0x6F, 0xF0, 0x0A, 0x04, 0xFA, 0xE7, ++0x6F, 0xF0, 0x0D, 0x04, 0xF7, 0xE7, 0x39, 0x78, 0x0D, 0x48, 0xFB, 0xF7, 0xFD, 0xFE, 0x6F, 0xF0, 0x02, 0x04, 0xF0, 0xE7, ++0x31, 0x46, 0xFE, 0xF7, 0xB3, 0xFC, 0x3C, 0x70, 0x6F, 0xF0, 0x0D, 0x04, 0xE9, 0xE7, 0x01, 0x46, 0x07, 0x48, 0xFB, 0xF7, ++0xEF, 0xFE, 0x4F, 0xF0, 0xFF, 0x34, 0xE2, 0xE7, 0x5B, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, ++0x58, 0x28, 0x17, 0x00, 0x30, 0x86, 0x15, 0x00, 0x48, 0x86, 0x15, 0x00, 0xF8, 0xB5, 0x20, 0x4D, 0x2B, 0x78, 0x2B, 0xBB, ++0x08, 0xB3, 0x0A, 0x46, 0xF9, 0xB1, 0x1E, 0x4F, 0x3B, 0x78, 0x13, 0xBB, 0x1D, 0x4C, 0x01, 0x26, 0x3E, 0x70, 0xD4, 0xF8, ++0x30, 0x3B, 0x23, 0xF0, 0xFF, 0x53, 0x23, 0xF4, 0xC0, 0x13, 0xC4, 0xF8, 0x30, 0x3B, 0xD4, 0xF8, 0x00, 0x38, 0x43, 0xF4, ++0x00, 0x53, 0x01, 0x46, 0xC4, 0xF8, 0x00, 0x38, 0x30, 0x46, 0xFE, 0xF7, 0x87, 0xFE, 0x04, 0x46, 0xC8, 0xB9, 0x13, 0x4B, ++0x1E, 0x70, 0x2B, 0x78, 0x73, 0xB9, 0x20, 0x46, 0xF8, 0xBD, 0x6F, 0xF0, 0x0A, 0x04, 0xFA, 0xE7, 0x6F, 0xF0, 0x0D, 0x04, ++0xF7, 0xE7, 0x39, 0x78, 0x0D, 0x48, 0xFB, 0xF7, 0xAF, 0xFE, 0x6F, 0xF0, 0x02, 0x04, 0xF0, 0xE7, 0x31, 0x46, 0xFE, 0xF7, ++0x65, 0xFC, 0x3C, 0x70, 0x6F, 0xF0, 0x0D, 0x04, 0xE9, 0xE7, 0x01, 0x46, 0x07, 0x48, 0xFB, 0xF7, 0xA1, 0xFE, 0x4F, 0xF0, ++0xFF, 0x34, 0xE2, 0xE7, 0x5B, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x58, 0x28, 0x17, 0x00, ++0x30, 0x86, 0x15, 0x00, 0x48, 0x86, 0x15, 0x00, 0xF8, 0xB5, 0x26, 0x4C, 0xFF, 0xF7, 0xFE, 0xFB, 0x23, 0x78, 0x00, 0x2B, ++0x42, 0xD1, 0x24, 0x4D, 0x28, 0x46, 0x18, 0xF0, 0xFB, 0xFE, 0xDF, 0xF8, 0x90, 0xC0, 0xC0, 0xB2, 0x8C, 0xF8, 0x00, 0x00, ++0x00, 0x28, 0x31, 0xD0, 0x1F, 0x4A, 0x2F, 0x68, 0x42, 0xF2, 0x30, 0x03, 0x01, 0x28, 0xD6, 0x58, 0x28, 0xD0, 0xBD, 0x89, ++0xB3, 0x89, 0xAB, 0x42, 0x11, 0xD2, 0x39, 0x46, 0x03, 0x46, 0x03, 0xE0, 0x53, 0xB1, 0x95, 0x89, 0x0E, 0x46, 0x11, 0x46, ++0xC2, 0x1A, 0xD2, 0xB2, 0x01, 0x3B, 0xF5, 0xB1, 0x0A, 0x68, 0xDB, 0xB2, 0x00, 0x2A, 0xF3, 0xD1, 0x8C, 0xF8, 0x00, 0x30, ++0x0E, 0x46, 0xB3, 0x7B, 0x72, 0x68, 0x79, 0x68, 0x01, 0x3B, 0x02, 0xEB, 0xC3, 0x02, 0x01, 0x20, 0xD3, 0x78, 0x20, 0x70, ++0x23, 0xF0, 0x0A, 0x03, 0x43, 0xF0, 0x0A, 0x03, 0xD3, 0x70, 0x02, 0x20, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0x0A, 0xBC, ++0x00, 0x2E, 0xEA, 0xD1, 0x6F, 0xF0, 0x61, 0x00, 0xF8, 0xBD, 0x8C, 0xF8, 0x00, 0x20, 0xE4, 0xE7, 0x6F, 0xF0, 0x62, 0x00, ++0xF8, 0xBD, 0x00, 0xBF, 0x5A, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x64, 0x60, 0x17, 0x00, ++0x01, 0x28, 0x07, 0xD0, 0x06, 0x28, 0x07, 0xD0, 0x04, 0x4B, 0x0F, 0x28, 0x0C, 0xBF, 0x18, 0x46, 0x00, 0x20, 0x70, 0x47, ++0x02, 0x48, 0x70, 0x47, 0x02, 0x48, 0x70, 0x47, 0x74, 0x86, 0x15, 0x00, 0x80, 0x86, 0x15, 0x00, 0x94, 0x86, 0x15, 0x00, ++0x06, 0x28, 0x0B, 0xD8, 0x01, 0x38, 0x05, 0x28, 0x16, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x05, 0x03, 0x13, 0x0F, 0x11, 0x03, ++0x09, 0x48, 0x70, 0x47, 0x09, 0x48, 0x70, 0x47, 0x12, 0x30, 0xC0, 0xB2, 0x06, 0x4B, 0x02, 0x28, 0x34, 0xBF, 0x18, 0x46, ++0x00, 0x20, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, ++0xC4, 0x86, 0x15, 0x00, 0xB4, 0x86, 0x15, 0x00, 0xA0, 0x86, 0x15, 0x00, 0xA8, 0x86, 0x15, 0x00, 0xD8, 0x86, 0x15, 0x00, ++0xEC, 0x86, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x1D, 0x4F, 0x1E, 0x48, 0x18, 0xF0, 0xE4, 0xFD, 0x3B, 0x68, 0x1B, 0x89, ++0x93, 0xB3, 0xDF, 0xF8, 0x7C, 0x90, 0x1B, 0x4E, 0xDF, 0xF8, 0x78, 0x80, 0xDF, 0xF8, 0x78, 0xB0, 0xDF, 0xF8, 0x78, 0xA0, ++0x00, 0x25, 0x0C, 0xE0, 0x21, 0x46, 0x15, 0x48, 0x18, 0xF0, 0xD6, 0xFD, 0x3A, 0x68, 0x33, 0x88, 0x11, 0x89, 0x01, 0x35, ++0xAA, 0xB2, 0x01, 0x33, 0x91, 0x42, 0x33, 0x80, 0x1A, 0xD9, 0xB9, 0xF8, 0xD4, 0x10, 0x04, 0x39, 0x89, 0xB2, 0x40, 0x46, ++0xFC, 0xF7, 0x58, 0xFC, 0x04, 0x46, 0x00, 0x28, 0xE8, 0xD1, 0xA9, 0xB2, 0x58, 0x46, 0x19, 0xF0, 0x99, 0xFF, 0xDA, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDE, 0xDA, 0x07, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0xFB, 0x72, 0x1A, 0xF0, ++0x07, 0xFA, 0xD7, 0xE7, 0xBD, 0xE8, 0xF8, 0x8F, 0x78, 0x36, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xF0, 0x86, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x0C, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0xD2, 0xFD, 0x18, 0xB1, 0x0A, 0x4A, ++0x13, 0x88, 0x01, 0x3B, 0x13, 0x80, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, ++0x66, 0x28, 0x17, 0x00, 0x38, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x28, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x27, 0x4C, 0x28, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x65, 0xFD, 0x26, 0x4A, ++0x26, 0x49, 0x13, 0x88, 0x0D, 0x78, 0x01, 0x33, 0x9B, 0xB2, 0x13, 0x80, 0x24, 0x4A, 0x11, 0x78, 0x9D, 0xB9, 0x49, 0xB9, ++0x23, 0x68, 0x33, 0xB1, 0x1C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, ++0x1E, 0x49, 0x09, 0x78, 0x99, 0x42, 0xF1, 0xD8, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0x15, 0x70, 0x1B, 0xE0, 0x00, 0x29, ++0xEA, 0xD0, 0x19, 0x49, 0x09, 0x78, 0x99, 0x42, 0xE6, 0xD8, 0x18, 0x4B, 0x00, 0x21, 0x11, 0x70, 0xD3, 0xF8, 0x00, 0x28, ++0x22, 0xF4, 0x00, 0x52, 0xC3, 0xF8, 0x00, 0x28, 0xD3, 0xF8, 0x20, 0x2B, 0x8A, 0x42, 0x05, 0xDA, 0xD3, 0xF8, 0x20, 0x2B, ++0x42, 0xF0, 0x80, 0x62, 0xC3, 0xF8, 0x20, 0x2B, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0x17, 0xF0, 0xA9, 0xFF, 0x0D, 0x49, ++0x4F, 0xF4, 0x00, 0x70, 0x19, 0xF0, 0x4E, 0xFF, 0x0B, 0x4B, 0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0xC4, 0xE7, 0x00, 0xBF, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, 0x68, 0x60, 0x17, 0x00, ++0x64, 0x28, 0x17, 0x00, 0x88, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x87, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xF8, 0xB5, 0x0C, 0x4D, 0x0C, 0x48, 0x18, 0xF0, 0x01, 0xFD, 0x2B, 0x68, 0x9B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, ++0x00, 0x24, 0x7C, 0x21, 0x38, 0x46, 0xFC, 0xF7, 0x8D, 0xFB, 0x01, 0x46, 0x30, 0x46, 0x18, 0xF0, 0xF7, 0xFC, 0x2B, 0x68, ++0x01, 0x34, 0x9A, 0x88, 0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, 0x78, 0x36, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, ++0xE4, 0x25, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x1E, 0xFD, 0x23, 0x68, 0x33, 0xB1, ++0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, ++0xB9, 0xFC, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x48, ++0xFF, 0xF7, 0x5E, 0xFD, 0x03, 0x48, 0x19, 0xF0, 0x7B, 0xFE, 0x01, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0xFC, 0x87, 0x15, 0x00, ++0x28, 0x87, 0x15, 0x00, 0x70, 0xB5, 0x3C, 0x4D, 0x3C, 0x4C, 0x2A, 0x68, 0x3C, 0x49, 0x12, 0x69, 0x3C, 0x4B, 0x22, 0x60, ++0x02, 0xF1, 0x40, 0x06, 0x00, 0x24, 0x0E, 0x60, 0x3A, 0x4E, 0x98, 0x60, 0xC3, 0xE9, 0x00, 0x44, 0x21, 0x46, 0x10, 0x46, ++0x4F, 0xF4, 0xA0, 0x72, 0xC3, 0xE9, 0x04, 0x44, 0xDC, 0x60, 0xB4, 0x81, 0xF5, 0xF7, 0xEC, 0xFB, 0x2B, 0x68, 0x34, 0x49, ++0x58, 0x69, 0x34, 0x4A, 0x34, 0x4B, 0x08, 0x60, 0x21, 0x46, 0x00, 0xF1, 0x08, 0x04, 0x14, 0x60, 0x00, 0xF1, 0x10, 0x02, ++0x1A, 0x60, 0x00, 0xF1, 0x18, 0x02, 0x5A, 0x60, 0x00, 0xF1, 0x20, 0x02, 0x9A, 0x60, 0x2E, 0x4C, 0x00, 0xF1, 0x28, 0x02, ++0xDA, 0x60, 0x00, 0xF1, 0x30, 0x03, 0x4F, 0xF4, 0x4B, 0x62, 0x23, 0x60, 0xF5, 0xF7, 0xCE, 0xFB, 0x29, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2E, 0xDB, 0x27, 0x4B, 0x28, 0x49, 0xB3, 0xF8, 0xD4, 0x20, 0x0C, 0x68, 0xB3, 0xF8, ++0xD6, 0x00, 0xB3, 0xF8, 0xE6, 0x10, 0x25, 0x4D, 0x25, 0x4E, 0x12, 0x1B, 0x25, 0x4C, 0x04, 0x3A, 0x22, 0x60, 0x04, 0x38, ++0x24, 0x4C, 0x30, 0x60, 0x05, 0xFB, 0x01, 0xF1, 0x93, 0xF8, 0xE0, 0x00, 0x22, 0x4D, 0x20, 0x70, 0x22, 0x4A, 0x93, 0xF8, ++0xE1, 0x00, 0x28, 0x70, 0x93, 0xF8, 0xE2, 0x50, 0x20, 0x48, 0x15, 0x70, 0x20, 0x4C, 0x21, 0x4A, 0x93, 0xF8, 0xE3, 0x50, ++0x93, 0xF8, 0xE4, 0x30, 0x03, 0x70, 0x1F, 0x4B, 0x25, 0x70, 0x91, 0x42, 0xD4, 0xBF, 0x19, 0x60, 0x1A, 0x60, 0x01, 0x20, ++0x70, 0xBD, 0x2B, 0x68, 0x9B, 0x69, 0xB3, 0xF5, 0x4B, 0x6F, 0xCB, 0xD2, 0x19, 0x49, 0x1A, 0x48, 0x40, 0xF2, 0xF2, 0x22, ++0x1A, 0xF0, 0x76, 0xF8, 0xC4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, 0x58, 0x60, 0x17, 0x00, ++0xA4, 0x60, 0x17, 0x00, 0x8C, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, ++0x54, 0x60, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x40, 0x42, 0x0F, 0x00, ++0x9C, 0x60, 0x17, 0x00, 0x78, 0x60, 0x17, 0x00, 0x7C, 0x60, 0x17, 0x00, 0x88, 0x60, 0x17, 0x00, 0xA0, 0x60, 0x17, 0x00, ++0x68, 0x60, 0x17, 0x00, 0xA1, 0x60, 0x17, 0x00, 0xFF, 0xA2, 0xE1, 0x11, 0x6C, 0x60, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x3C, 0x87, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x43, 0x7E, 0x07, 0x7E, 0x09, 0x2B, 0x05, 0x46, 0x09, 0xD8, 0x49, 0x4A, ++0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x25, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x81, 0x80, 0x6B, 0x8B, ++0xDF, 0xF8, 0x30, 0x81, 0x1A, 0x07, 0x5A, 0xD4, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x83, 0x93, 0xF8, 0x64, 0x30, ++0x00, 0x2B, 0x73, 0xD0, 0x3E, 0x4B, 0xAE, 0x7D, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x63, 0xDB, 0x3C, 0x48, ++0x18, 0xF0, 0x0C, 0xFC, 0x04, 0x46, 0x00, 0x28, 0x4C, 0xD0, 0x3A, 0x48, 0xE1, 0x8B, 0x83, 0x5D, 0xE2, 0x6C, 0x4F, 0xF0, ++0x00, 0x09, 0x01, 0x33, 0x21, 0xF0, 0x01, 0x01, 0x83, 0x55, 0xE1, 0x83, 0xC4, 0xF8, 0x44, 0x90, 0x29, 0x46, 0xC2, 0xF8, ++0x10, 0x90, 0x20, 0x1D, 0x1C, 0x22, 0xC4, 0xF8, 0x2C, 0x90, 0x2C, 0xF0, 0xA9, 0xFA, 0x30, 0x4B, 0xE1, 0x8B, 0x1B, 0x68, ++0x84, 0xF8, 0x42, 0x90, 0xEB, 0x1A, 0x04, 0x3B, 0x21, 0xF4, 0x00, 0x42, 0x22, 0xF0, 0x02, 0x02, 0xA3, 0x64, 0x0B, 0x07, ++0xC4, 0xF8, 0x24, 0x90, 0xC4, 0xF8, 0x50, 0x90, 0xE2, 0x83, 0x29, 0xD4, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, ++0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x23, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, ++0x23, 0x20, 0x02, 0x44, 0x41, 0xF8, 0x23, 0x20, 0xA4, 0x20, 0x00, 0xFB, 0x07, 0x60, 0x99, 0x30, 0x21, 0x46, 0x08, 0xEB, ++0xC0, 0x00, 0xBD, 0xE8, 0xF8, 0x43, 0x18, 0xF0, 0x7F, 0xBB, 0x16, 0x48, 0x18, 0xF0, 0xC0, 0xFB, 0x05, 0x26, 0x04, 0x46, ++0x00, 0x28, 0xB2, 0xD1, 0x13, 0x4B, 0x16, 0x48, 0x99, 0x5D, 0xFB, 0xF7, 0x83, 0xFB, 0xFE, 0xE7, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x07, 0x80, 0x21, 0x46, 0x00, 0xF5, 0xA3, 0x60, 0xBD, 0xE8, 0xF8, 0x43, 0x18, 0xF0, 0x67, 0xBB, 0x05, 0x2E, ++0x99, 0xD9, 0x0E, 0x49, 0x0E, 0x48, 0x40, 0xF2, 0x5F, 0x32, 0x19, 0xF0, 0xB3, 0xFF, 0x92, 0xE7, 0x07, 0x4B, 0x18, 0x68, ++0x28, 0x1A, 0x04, 0x38, 0xBD, 0xE8, 0xF8, 0x43, 0xFC, 0xF7, 0x58, 0xBC, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x58, 0x17, 0x00, 0x74, 0x28, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x60, 0x87, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x88, 0x82, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x48, 0x81, ++0xDF, 0xF8, 0x48, 0x91, 0xDF, 0xF8, 0x48, 0xA1, 0x59, 0xE0, 0x47, 0x48, 0x18, 0xF0, 0x7A, 0xFB, 0x04, 0x46, 0xDF, 0xF8, ++0x40, 0xE1, 0x1C, 0x22, 0x29, 0x46, 0x04, 0x30, 0x00, 0x2C, 0x63, 0xD0, 0xB4, 0xF8, 0x1E, 0xB0, 0x1E, 0xF8, 0x07, 0xC0, ++0xE3, 0x6C, 0x66, 0x64, 0x2B, 0xF0, 0x01, 0x0B, 0x0C, 0xF1, 0x01, 0x0C, 0xA4, 0xF8, 0x1E, 0xB0, 0x1E, 0x61, 0xE6, 0x62, ++0x0E, 0xF8, 0x07, 0xC0, 0x2C, 0xF0, 0x16, 0xFA, 0x95, 0xF8, 0x20, 0x20, 0xE3, 0x8B, 0x38, 0x48, 0x12, 0xF0, 0x01, 0x0F, ++0x14, 0xBF, 0x4F, 0xF4, 0x00, 0x52, 0x4F, 0xF4, 0x08, 0x52, 0x2A, 0x61, 0x84, 0xF8, 0x42, 0x60, 0xC5, 0xE9, 0x05, 0x66, ++0x62, 0x7F, 0x10, 0x32, 0x92, 0x02, 0x45, 0xF8, 0x18, 0x2C, 0x21, 0x7F, 0x26, 0x65, 0xA4, 0x22, 0x99, 0x37, 0x23, 0xF4, ++0x00, 0x43, 0x12, 0xFB, 0x01, 0x77, 0x23, 0xF0, 0x02, 0x03, 0x4C, 0x3D, 0xA5, 0x64, 0x00, 0xEB, 0xC7, 0x00, 0xE3, 0x83, ++0x21, 0x46, 0x18, 0xF0, 0xF5, 0xFA, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x24, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x24, 0x4C, 0x24, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x2A, 0xFB, 0x98, 0xF8, 0x11, 0x35, ++0x22, 0x68, 0x01, 0x3B, 0x88, 0xF8, 0x11, 0x35, 0x3A, 0xBB, 0xD8, 0xF8, 0x14, 0x35, 0x00, 0x26, 0xDB, 0xB1, 0xD9, 0xF8, ++0x00, 0x20, 0x5D, 0x68, 0xB2, 0xF9, 0x00, 0x30, 0xAF, 0x7D, 0x00, 0x2B, 0x99, 0xDA, 0x05, 0x2F, 0x97, 0xD9, 0x18, 0x49, ++0x4F, 0xF4, 0x66, 0x72, 0x50, 0x46, 0x19, 0xF0, 0x1F, 0xFF, 0x90, 0xE7, 0x15, 0x48, 0x1E, 0xF8, 0x07, 0x10, 0xFB, 0xF7, ++0xD5, 0xFA, 0x14, 0x4B, 0x18, 0x68, 0x28, 0x1A, 0x04, 0x38, 0xFC, 0xF7, 0xC1, 0xFB, 0x20, 0x20, 0x18, 0xF0, 0x3E, 0xFA, ++0xBD, 0xE8, 0xF8, 0x4F, 0x40, 0x20, 0x18, 0xF0, 0x15, 0xBA, 0x08, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0x22, 0x60, 0x00, 0x2A, ++0x7F, 0xF4, 0x74, 0xAF, 0x00, 0x2B, 0x3F, 0xF4, 0x71, 0xAF, 0x62, 0xB6, 0x6E, 0xE7, 0x00, 0xBF, 0x20, 0x58, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x60, 0x87, 0x15, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x58, 0x58, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x82, 0x15, 0x00, ++0x74, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xB8, 0x90, 0x29, 0x4D, 0x2A, 0x4F, 0xDF, 0xF8, 0xAC, 0x80, ++0x29, 0x4E, 0x20, 0xE0, 0x5C, 0x68, 0x20, 0x46, 0xFA, 0xF7, 0x1E, 0xFB, 0x38, 0x68, 0x20, 0x1A, 0x04, 0x38, 0xFC, 0xF7, ++0x81, 0xFB, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, ++0x00, 0x30, 0x30, 0x46, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0xB3, 0xFA, 0x95, 0xF8, 0x9D, 0x37, 0xD9, 0xF8, ++0x00, 0x20, 0x01, 0x3B, 0x85, 0xF8, 0x9D, 0x37, 0x0A, 0xBB, 0xD5, 0xF8, 0xA0, 0x37, 0x00, 0x2B, 0xDA, 0xD1, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x14, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x4F, 0xF4, ++0x00, 0x00, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0xD4, 0xF9, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x0D, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x01, 0x3A, ++0xD8, 0xF8, 0x00, 0x30, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, 0xB3, 0xD1, 0x00, 0x2B, 0xB1, 0xD0, 0x62, 0xB6, 0xAF, 0xE7, ++0x58, 0x58, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0xF8, 0x5F, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x0E, 0x4B, 0x10, 0xB5, 0xD3, 0xF8, 0x90, 0x32, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0A, 0x4C, 0x23, 0x68, 0x10, 0x20, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x9E, 0xF9, ++0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF8, 0xB5, 0x16, 0x4C, 0x16, 0x4E, 0x17, 0x4F, ++0x14, 0x4D, 0x15, 0xE0, 0x58, 0x68, 0xFC, 0xF7, 0x05, 0xFB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, ++0x01, 0x23, 0x33, 0x60, 0x3B, 0x68, 0x28, 0x46, 0x01, 0x33, 0x3B, 0x60, 0x18, 0xF0, 0x3A, 0xFA, 0x0E, 0x4A, 0x39, 0x68, ++0x13, 0x78, 0x01, 0x3B, 0x13, 0x70, 0x39, 0xB9, 0x23, 0x68, 0x00, 0x2B, 0xE6, 0xD1, 0xBD, 0xE8, 0xF8, 0x40, 0x08, 0x20, ++0x18, 0xF0, 0x6A, 0xB9, 0x01, 0x39, 0x33, 0x68, 0x39, 0x60, 0x00, 0x29, 0xDA, 0xD1, 0x00, 0x2B, 0xD8, 0xD0, 0x62, 0xB6, ++0xD6, 0xE7, 0x00, 0xBF, 0x94, 0x4E, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x8E, 0x4E, 0x17, 0x00, ++0x59, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x67, 0xD1, 0x2D, 0xE9, 0xF0, 0x47, 0x57, 0x4D, 0x2B, 0x78, 0x00, 0x2B, 0x47, 0xD1, ++0x56, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x5B, 0xD1, 0x55, 0x49, 0x56, 0x4A, 0x09, 0x78, 0x12, 0x88, 0x91, 0x42, 0x5E, 0xD2, ++0x54, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x04, 0x46, 0x00, 0x28, 0x78, 0xD0, 0x2B, 0x78, 0x00, 0x2B, ++0x4D, 0xD0, 0x4C, 0x4B, 0xDF, 0xF8, 0x60, 0xA1, 0x1B, 0x78, 0x4E, 0x4F, 0xDA, 0xF8, 0x00, 0x00, 0x00, 0x2B, 0x7B, 0xD1, ++0x4C, 0x4B, 0x39, 0x68, 0xD3, 0xF8, 0x40, 0x34, 0x20, 0x44, 0x98, 0x47, 0x00, 0x28, 0x39, 0xD0, 0x01, 0x46, 0x49, 0x48, ++0xDF, 0xF8, 0x08, 0x91, 0xDF, 0xF8, 0x18, 0x81, 0xFB, 0xF7, 0xAE, 0xF9, 0x05, 0x26, 0x2B, 0x78, 0x00, 0x2B, 0x48, 0xD1, ++0xDA, 0xF8, 0x00, 0x00, 0xD8, 0xF8, 0x40, 0x34, 0x39, 0x68, 0x20, 0x44, 0x98, 0x47, 0x28, 0xB3, 0x01, 0x3E, 0xF2, 0xD1, ++0x05, 0x21, 0x3F, 0x48, 0xFB, 0xF7, 0x9C, 0xF9, 0x20, 0x46, 0xFC, 0xF7, 0x8B, 0xFA, 0xBD, 0xE8, 0xF0, 0x47, 0x04, 0x20, ++0x18, 0xF0, 0xE2, 0xB8, 0x34, 0x4B, 0x1B, 0x88, 0x00, 0x2B, 0x46, 0xD0, 0x31, 0x4A, 0x12, 0x78, 0x9A, 0x42, 0xB9, 0xD3, ++0x36, 0x4A, 0x2E, 0x4B, 0x12, 0x68, 0x01, 0x21, 0x19, 0x70, 0x00, 0x2A, 0x47, 0xD1, 0x34, 0x4B, 0x34, 0x49, 0x1A, 0x88, ++0x4F, 0xF4, 0x00, 0x70, 0x92, 0xB2, 0x19, 0xF0, 0x97, 0xFB, 0xA9, 0xE7, 0xBD, 0xE8, 0xF0, 0x87, 0x70, 0x47, 0xDF, 0xF8, ++0xC8, 0xA0, 0x28, 0x4F, 0xDA, 0xF8, 0x00, 0x00, 0xB4, 0xE7, 0x1A, 0x78, 0x00, 0x2A, 0x9D, 0xD1, 0x28, 0x4A, 0x12, 0x68, ++0x01, 0x21, 0x19, 0x70, 0x92, 0xBB, 0x27, 0x4B, 0x27, 0x49, 0x1A, 0x88, 0xBD, 0xE8, 0xF0, 0x47, 0x4F, 0xF4, 0x00, 0x70, ++0x92, 0xB2, 0x19, 0xF0, 0x7B, 0xBB, 0x99, 0xF8, 0x00, 0x30, 0xDA, 0xF8, 0x00, 0x00, 0x2B, 0xB9, 0xD8, 0xF8, 0x40, 0x34, ++0x39, 0x68, 0x20, 0x44, 0x98, 0x47, 0xB2, 0xE7, 0x39, 0x68, 0x20, 0x44, 0xFF, 0xF7, 0x72, 0xFA, 0xAD, 0xE7, 0x04, 0x20, ++0x18, 0xF0, 0x9C, 0xF8, 0xBD, 0xE8, 0xF0, 0x47, 0x19, 0x48, 0xFB, 0xF7, 0x49, 0xB9, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x49, ++0x4F, 0xF4, 0x00, 0x70, 0x19, 0xF0, 0x5C, 0xBB, 0x39, 0x68, 0x20, 0x44, 0xFF, 0xF7, 0x5E, 0xFA, 0x84, 0xE7, 0x40, 0xF2, ++0x1F, 0x40, 0x17, 0xF0, 0xF9, 0xFA, 0xB2, 0xE7, 0x40, 0xF2, 0x1F, 0x40, 0x17, 0xF0, 0xF4, 0xFA, 0xC7, 0xE7, 0x00, 0xBF, ++0x58, 0x28, 0x17, 0x00, 0x68, 0x60, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0x7C, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, ++0xA4, 0x60, 0x17, 0x00, 0x78, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x8C, 0x87, 0x15, 0x00, 0xAC, 0x87, 0x15, 0x00, ++0x6C, 0x60, 0x17, 0x00, 0x56, 0x28, 0x17, 0x00, 0x7C, 0x87, 0x15, 0x00, 0x98, 0x87, 0x15, 0x00, 0x84, 0x87, 0x15, 0x00, ++0x80, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x0F, 0x48, 0x19, 0xF0, 0xD8, 0xFA, 0x0E, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, ++0x98, 0x47, 0x80, 0xB1, 0x0C, 0x4B, 0x0D, 0x49, 0x1A, 0x68, 0x0D, 0x4B, 0x09, 0x68, 0xD3, 0xF8, 0x40, 0x34, 0x10, 0x44, ++0x98, 0x47, 0x01, 0x1E, 0x00, 0xDB, 0x08, 0xBD, 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x48, 0xFB, 0xF7, 0xF7, 0xB8, 0xBD, 0xE8, ++0x08, 0x40, 0x07, 0x48, 0xFB, 0xF7, 0xF2, 0xB8, 0xC0, 0x87, 0x15, 0x00, 0xA4, 0x60, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, ++0x78, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xCC, 0x87, 0x15, 0x00, 0xE4, 0x87, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x20, ++0x18, 0xF0, 0x52, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x09, 0x4C, 0x0A, 0x4A, 0x23, 0x68, 0xD2, 0xF8, 0x3C, 0x24, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x33, 0xB1, ++0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x11, 0x4D, 0x11, 0x4F, 0x28, 0x68, 0x00, 0xF5, 0x0D, 0x70, ++0x18, 0xF0, 0xA4, 0xF8, 0x28, 0x68, 0x00, 0xF5, 0x0F, 0x70, 0x18, 0xF0, 0x9F, 0xF8, 0x3B, 0x68, 0x1B, 0x89, 0x93, 0xB1, ++0x0B, 0x4E, 0x00, 0x24, 0x4F, 0xF4, 0xD7, 0x61, 0x30, 0x46, 0xFB, 0xF7, 0x2B, 0xFF, 0x01, 0x46, 0x28, 0x68, 0x00, 0xF5, ++0x0D, 0x70, 0x18, 0xF0, 0x93, 0xF8, 0x3B, 0x68, 0x01, 0x34, 0x1A, 0x89, 0xA3, 0xB2, 0x9A, 0x42, 0xEE, 0xD8, 0xF8, 0xBD, ++0x00, 0x38, 0x18, 0x00, 0x78, 0x36, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x12, 0x4A, ++0x01, 0x46, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0E, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4C, 0x0E, 0x4A, 0x23, 0x68, 0x10, 0x68, 0x01, 0x33, 0x00, 0xF5, 0x0D, 0x70, 0x23, 0x60, ++0x18, 0xF0, 0x6C, 0xF8, 0x23, 0x68, 0x33, 0xB1, 0x06, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x02, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x4C, 0x40, 0x04, 0x40, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x00, 0x38, 0x18, 0x00, 0x08, 0xB5, 0x03, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x19, 0xF0, 0x7A, 0xFA, ++0x01, 0x20, 0x08, 0xBD, 0x08, 0x88, 0x15, 0x00, 0x05, 0x4A, 0x06, 0x49, 0x00, 0x23, 0xC2, 0xE9, 0x02, 0x03, 0xC2, 0xE9, ++0x04, 0x33, 0xC2, 0xE9, 0x00, 0x33, 0x8B, 0x81, 0x01, 0x20, 0x70, 0x47, 0xBC, 0x60, 0x17, 0x00, 0xD4, 0x60, 0x17, 0x00, ++0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x0C, 0x92, 0xDF, 0xF8, 0x0C, 0x82, 0xD9, 0xF8, 0x14, 0x35, 0x00, 0x2B, 0x00, 0xF0, ++0x8F, 0x80, 0xDF, 0xF8, 0xE8, 0xA1, 0xDF, 0xF8, 0x00, 0xB2, 0x78, 0xE0, 0x71, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, ++0x06, 0x12, 0x92, 0xF8, 0x64, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xB2, 0x80, 0x6D, 0x4A, 0x1F, 0x7A, 0x13, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA1, 0x80, 0x6A, 0x48, 0x18, 0xF0, 0x5B, 0xF8, 0x04, 0x46, 0x00, 0x28, 0x6C, 0xD0, ++0xC2, 0x8B, 0xC1, 0x6C, 0x1A, 0xF8, 0x07, 0xC0, 0x00, 0x23, 0x22, 0xF0, 0x01, 0x02, 0xC2, 0x83, 0x43, 0x64, 0x0C, 0xF1, ++0x01, 0x0C, 0x0B, 0x61, 0x1C, 0x22, 0xC3, 0x62, 0x29, 0x46, 0x04, 0x30, 0x0A, 0xF8, 0x07, 0xC0, 0x2B, 0xF0, 0xFA, 0xFE, ++0xE2, 0x8B, 0xDB, 0xF8, 0x00, 0x10, 0x6D, 0x1A, 0xC2, 0xF3, 0x0E, 0x01, 0x00, 0x23, 0xE1, 0x83, 0x11, 0x07, 0x84, 0xF8, ++0x42, 0x30, 0x23, 0x65, 0xA5, 0x64, 0x6F, 0xD4, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, ++0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x53, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x02, 0x44, ++0x41, 0xF8, 0x23, 0x20, 0xA4, 0x20, 0x00, 0xFB, 0x06, 0x76, 0x4A, 0x48, 0x99, 0x36, 0x21, 0x46, 0x00, 0xEB, 0xC6, 0x00, ++0x17, 0xF0, 0xD6, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x48, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xD8, 0xF8, 0x00, 0x30, 0x46, 0x48, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0x0A, 0xF8, 0x99, 0xF8, 0x11, 0x35, ++0xD8, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0x89, 0xF8, 0x11, 0x35, 0x3A, 0xB1, 0x3E, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, ++0x00, 0x20, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD9, 0xF8, 0x14, 0x35, 0x83, 0xB1, 0x5D, 0x68, 0x6A, 0x8B, 0x2E, 0x7E, ++0x14, 0x07, 0x81, 0xD5, 0x34, 0x48, 0x17, 0xF0, 0xEF, 0xFF, 0x05, 0x27, 0x04, 0x46, 0x00, 0x28, 0x92, 0xD1, 0x35, 0x4B, ++0x35, 0x48, 0xD9, 0x5D, 0xFA, 0xF7, 0xB2, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2E, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x20, 0x20, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x17, 0xF0, 0x14, 0xFF, ++0x40, 0x20, 0x17, 0xF0, 0xED, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x25, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, ++0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x24, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x21, 0x46, ++0x00, 0xFB, 0x06, 0x30, 0x17, 0xF0, 0x7A, 0xFF, 0xA2, 0xE7, 0x05, 0x2F, 0x7F, 0xF6, 0x5C, 0xAF, 0x1F, 0x49, 0x20, 0x48, ++0xB8, 0x22, 0x19, 0xF0, 0xC5, 0xFB, 0x55, 0xE7, 0xDB, 0xF8, 0x00, 0x00, 0x28, 0x1A, 0xFC, 0xF7, 0x6D, 0xF8, 0xEF, 0xF3, ++0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x12, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x11, 0x48, ++0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x17, 0xF0, 0x9F, 0xFF, 0x99, 0xF8, 0x11, 0x25, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0x3A, ++0x89, 0xF8, 0x11, 0x25, 0x00, 0x2B, 0x9B, 0xD0, 0x08, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x00, 0x2B, ++0x94, 0xD1, 0x00, 0x2A, 0x92, 0xD0, 0x90, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, ++0x7C, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x74, 0x28, 0x17, 0x00, 0x1C, 0x88, 0x15, 0x00, ++0x30, 0x8D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x88, 0x82, 0x15, 0x00, 0x58, 0x58, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x84, 0x1A, 0x17, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x04, 0x20, 0x17, 0xF0, ++0xA5, 0xBE, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0xD0, 0xF8, 0xA8, 0x44, 0xD1, 0xF8, 0xB0, 0x50, 0x07, 0x46, 0x0E, 0x46, ++0x00, 0x2C, 0x00, 0xF0, 0x8F, 0x80, 0xA2, 0x49, 0xA2, 0x4A, 0x4F, 0xF0, 0xFF, 0x33, 0x0B, 0x60, 0x13, 0x60, 0x94, 0xF8, ++0x60, 0x80, 0xB8, 0xF1, 0x04, 0x0F, 0x00, 0xF2, 0xB9, 0x81, 0xDF, 0xE8, 0x18, 0xF0, 0x49, 0x00, 0xF3, 0x00, 0x45, 0x01, ++0x03, 0x01, 0x05, 0x00, 0x9A, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, 0x22, 0x6F, ++0xDA, 0x60, 0x22, 0x6D, 0xDA, 0x61, 0x62, 0x6D, 0x1A, 0x62, 0xA2, 0x6D, 0x5A, 0x62, 0x94, 0x4B, 0x94, 0x4A, 0xE1, 0x6D, ++0x1B, 0x68, 0x11, 0x60, 0x1B, 0x78, 0x13, 0xF0, 0x02, 0x0F, 0xC1, 0x46, 0x4F, 0xF4, 0x80, 0x63, 0x4F, 0xF4, 0x80, 0x51, ++0x4F, 0xF0, 0x01, 0x08, 0x48, 0xD0, 0x97, 0xF8, 0x63, 0xC0, 0x94, 0xF8, 0x62, 0x00, 0x8C, 0x4A, 0x43, 0xEA, 0x0C, 0x13, ++0x43, 0xEA, 0x00, 0x43, 0x0B, 0x43, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0x00, 0x2D, ++0x48, 0xD0, 0x81, 0x4B, 0x7F, 0x49, 0xD6, 0xF8, 0x26, 0x00, 0x72, 0x8D, 0x08, 0x60, 0x1A, 0x60, 0x95, 0xF8, 0x60, 0x30, ++0x04, 0x2B, 0x00, 0xF2, 0x68, 0x81, 0xDF, 0xE8, 0x13, 0xF0, 0x78, 0x00, 0x41, 0x00, 0xD4, 0x00, 0xCF, 0x00, 0xC5, 0x00, ++0x00, 0x21, 0x4F, 0xF0, 0x01, 0x09, 0x77, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, ++0x22, 0x6F, 0xDA, 0x60, 0x73, 0x4B, 0x1B, 0x68, 0xB9, 0xF1, 0x02, 0x0F, 0x1B, 0x78, 0x40, 0xF0, 0xF2, 0x80, 0xD8, 0x07, ++0x40, 0xF1, 0x20, 0x81, 0x71, 0x48, 0x22, 0x6D, 0x02, 0x60, 0x62, 0x6D, 0x42, 0x60, 0xA2, 0x6D, 0x82, 0x60, 0xE2, 0x6D, ++0xC2, 0x60, 0x9B, 0x07, 0x00, 0xF1, 0xFF, 0x80, 0x4F, 0xF4, 0x00, 0x73, 0x97, 0xF8, 0x63, 0xC0, 0x94, 0xF8, 0x62, 0x00, ++0x67, 0x4A, 0x43, 0xEA, 0x0C, 0x13, 0x43, 0xEA, 0x00, 0x43, 0x0B, 0x43, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, ++0x58, 0x00, 0xFC, 0xD4, 0x00, 0x2D, 0xB6, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0xA1, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0xAE, 0xE7, ++0x4F, 0xF0, 0x02, 0x09, 0x59, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, ++0xDA, 0x60, 0xB9, 0xF1, 0x04, 0x0F, 0x40, 0xF0, 0x96, 0x80, 0x57, 0x4B, 0x2A, 0x6D, 0x1A, 0x60, 0x6A, 0x6D, 0x5A, 0x60, ++0xAA, 0x6D, 0x9A, 0x60, 0x50, 0x4B, 0x51, 0x4A, 0xE9, 0x6D, 0x1B, 0x68, 0x11, 0x60, 0x1B, 0x78, 0x99, 0x07, 0x40, 0xF1, ++0xD6, 0x80, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF4, 0x80, 0x69, 0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x4A, 0x4A, ++0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, 0x08, 0x03, 0x43, 0xEA, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, ++0x13, 0x68, 0x58, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x01, 0x09, 0x3D, 0x4B, ++0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, 0xDA, 0x60, 0xB9, 0xF1, 0x02, 0x0F, ++0x62, 0xD1, 0x38, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0xDA, 0x07, 0x40, 0xF1, 0xB3, 0x80, 0x38, 0x4A, 0x29, 0x6D, 0x11, 0x60, ++0x69, 0x6D, 0x51, 0x60, 0xA9, 0x6D, 0x91, 0x60, 0xE9, 0x6D, 0xD1, 0x60, 0x9A, 0x07, 0x7A, 0xD4, 0x4F, 0xF4, 0x00, 0x79, ++0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x2E, 0x4A, 0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, 0x08, 0x03, ++0x43, 0xEA, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x59, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, ++0x4F, 0xF0, 0x02, 0x09, 0x22, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, 0x22, 0x6F, ++0xDA, 0x60, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x01, 0x08, 0x51, 0xE7, 0x4F, 0xF0, 0x01, 0x09, 0xC8, 0x46, 0x4F, 0xF4, ++0x80, 0x51, 0x42, 0xE7, 0x18, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, ++0xDA, 0x60, 0x80, 0xE7, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF0, 0x01, 0x09, 0xA7, 0xE7, 0x95, 0xF8, 0x74, 0x30, 0x10, 0x2B, ++0x00, 0xF0, 0x83, 0x80, 0x20, 0x2B, 0x7B, 0xD0, 0x0D, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, ++0x9A, 0x60, 0x2A, 0x6F, 0xDA, 0x60, 0x4F, 0xF0, 0x03, 0x09, 0xB9, 0xF1, 0x02, 0x0F, 0x4F, 0xEA, 0x08, 0x38, 0x9C, 0xD0, ++0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9E, 0x07, 0x56, 0xD4, 0x4F, 0xEA, 0x09, 0x29, 0xA7, 0xE7, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0xD4, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, ++0xC8, 0x00, 0x32, 0x40, 0x94, 0xF8, 0x74, 0x30, 0x10, 0x2B, 0x5B, 0xD0, 0x20, 0x2B, 0x4A, 0xD0, 0x4F, 0xF0, 0x03, 0x09, ++0xA6, 0xE7, 0x9A, 0x07, 0x42, 0xD5, 0x09, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x01, 0x2B, 0x14, 0xD9, 0x4F, 0xEA, 0x09, 0x23, ++0xCB, 0xE6, 0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x3A, 0x4A, 0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, ++0x08, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, 0x97, 0xF8, ++0x63, 0x30, 0x94, 0xF8, 0x62, 0x00, 0x31, 0x4A, 0x41, 0xEA, 0x03, 0x13, 0x43, 0xEA, 0x00, 0x43, 0x43, 0xF0, 0x80, 0x43, ++0x13, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0xB9, 0xE6, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF4, 0x80, 0x69, 0x5F, 0xE7, ++0x29, 0x48, 0x02, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x02, 0x60, 0xE2, 0xE6, 0x26, 0x49, 0x0A, 0x68, 0x22, 0xF0, 0x01, 0x02, ++0x0A, 0x60, 0x4F, 0xE7, 0x09, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x01, 0x2B, 0xC7, 0xD9, 0x4F, 0xEA, 0x09, 0x29, 0x14, 0xE7, ++0x4F, 0xEA, 0x09, 0x23, 0xD6, 0xE6, 0x4F, 0xF4, 0x00, 0x51, 0x4F, 0xF0, 0x03, 0x09, 0xB0, 0xE6, 0x4F, 0xF4, 0x00, 0x58, ++0x4F, 0xF0, 0x03, 0x09, 0x1F, 0xE7, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x03, 0x09, 0x1A, 0xE7, 0x00, 0x21, 0x88, 0x46, ++0x4F, 0xF0, 0x03, 0x09, 0xA1, 0xE6, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xD6, 0xAE, ++0x12, 0x49, 0x13, 0x48, 0xA6, 0x22, 0x19, 0xF0, 0xA7, 0xF9, 0xCF, 0xE6, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x06, 0xDB, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x01, 0x08, 0x87, 0xE6, 0x09, 0x49, ++0x09, 0x48, 0x4F, 0x22, 0x19, 0xF0, 0x94, 0xF9, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x01, 0x08, ++0x7B, 0xE6, 0x00, 0xBF, 0xC4, 0x00, 0x32, 0x40, 0x64, 0x05, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xA3, 0x4E, 0x0D, 0x46, 0xD6, 0xF8, 0xF0, 0x70, 0x04, 0x46, 0xF4, 0xF7, ++0xF7, 0xFE, 0xB8, 0x47, 0xA0, 0x4A, 0xA1, 0x49, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x0A, 0x68, 0x9F, 0x4B, ++0x42, 0xF4, 0x80, 0x32, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x7F, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x02, ++0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xFE, 0x02, 0x42, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x97, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x4F, 0xF4, 0x40, 0x52, 0x00, 0x2B, 0xC1, 0xF8, 0x04, 0x21, 0xC0, 0xF2, 0xAD, 0x80, 0x92, 0x4B, 0x8E, 0x4A, ++0x92, 0x49, 0x19, 0x60, 0x13, 0x68, 0x92, 0x4F, 0x43, 0xF4, 0x00, 0x53, 0x13, 0x60, 0xF5, 0xF7, 0x49, 0xFD, 0xDF, 0xF8, ++0x9C, 0xC2, 0x8F, 0x49, 0xDC, 0xF8, 0x00, 0x20, 0x43, 0x1C, 0x9B, 0x06, 0x22, 0xF0, 0xE0, 0x52, 0x03, 0xF0, 0xE0, 0x53, ++0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0x0B, 0x68, 0x89, 0x4A, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, ++0x02, 0x03, 0x13, 0x60, 0x3B, 0x68, 0x9A, 0x03, 0x00, 0xF1, 0xAF, 0x80, 0x84, 0x4A, 0x28, 0x8C, 0x13, 0x68, 0x80, 0x49, ++0x9B, 0xB2, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x60, 0x0B, 0x68, 0x1F, 0x04, 0x00, 0xF1, 0x87, 0x80, 0x75, 0x4B, 0xDF, 0xF8, ++0x50, 0xE2, 0x1A, 0x68, 0xDF, 0xF8, 0x4C, 0xC2, 0x7C, 0x48, 0x7D, 0x4F, 0x7D, 0x49, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, ++0x4F, 0xF4, 0x40, 0x72, 0xCE, 0xF8, 0x00, 0x20, 0xE2, 0x6D, 0xCC, 0xF8, 0x00, 0x20, 0xB4, 0xF8, 0x60, 0x20, 0x02, 0x60, ++0xA2, 0x6B, 0xA0, 0x8F, 0x3A, 0x60, 0xD4, 0xF8, 0x90, 0x21, 0x08, 0x60, 0x91, 0x78, 0x74, 0x4A, 0x02, 0xEB, 0x81, 0x01, ++0x50, 0x68, 0x49, 0x69, 0xC7, 0xF8, 0xBC, 0x10, 0x19, 0x68, 0x21, 0xF4, 0xE0, 0x61, 0x19, 0x60, 0x13, 0x68, 0x6F, 0x49, ++0x6F, 0x4A, 0x03, 0x43, 0x3B, 0x64, 0x6F, 0x48, 0x6F, 0x4B, 0x08, 0x60, 0x13, 0x60, 0xD6, 0xF8, 0xB0, 0x31, 0x94, 0xF8, ++0x63, 0x10, 0x95, 0xF8, 0x23, 0x00, 0x98, 0x47, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x70, 0xFD, 0x09, 0xF0, 0xAC, 0xFB, ++0x68, 0x4B, 0x93, 0xF8, 0xB6, 0x30, 0x23, 0xB1, 0x67, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0xD6, 0xF8, ++0x60, 0x32, 0x98, 0x47, 0x64, 0x4A, 0x65, 0x49, 0xD6, 0xF8, 0x9C, 0x34, 0x11, 0x60, 0x98, 0x47, 0x4D, 0x4A, 0x63, 0x48, ++0x13, 0x68, 0x30, 0x24, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x01, 0x21, 0x04, 0x60, 0x00, 0x20, 0x17, 0xF0, 0xDE, 0xF9, ++0x5E, 0x4B, 0x1B, 0x68, 0x5A, 0x78, 0x22, 0xB1, 0x5D, 0x49, 0x0A, 0x68, 0x42, 0xF0, 0x40, 0x02, 0x0A, 0x60, 0x5C, 0x49, ++0x9B, 0x78, 0x0A, 0x68, 0xD8, 0x06, 0x4C, 0xBF, 0x22, 0xF0, 0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x58, 0x4A, ++0x13, 0xF0, 0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, 0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0x3C, 0x4B, 0x1B, 0x68, 0xB3, 0xF1, 0xC8, 0x5F, 0xBF, 0xF4, 0x4D, 0xAF, 0x50, 0x49, 0x50, 0x48, 0xF3, 0x22, ++0x19, 0xF0, 0x9C, 0xF8, 0x46, 0xE7, 0xF5, 0xF7, 0x35, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x74, 0xAF, 0x6B, 0x68, 0x9A, 0x06, ++0x7F, 0xF5, 0x70, 0xAF, 0x28, 0x8C, 0xF5, 0xF7, 0x71, 0xFC, 0x07, 0xF0, 0xB9, 0xFF, 0xD6, 0xF8, 0xE0, 0x33, 0x98, 0x47, ++0x94, 0xF8, 0x62, 0x30, 0x04, 0x2B, 0x3F, 0xF4, 0x63, 0xAF, 0xD6, 0xF8, 0x30, 0x33, 0x94, 0xF8, 0x63, 0x00, 0x98, 0x47, ++0x5C, 0xE7, 0xF5, 0xF7, 0x3F, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x4C, 0xAF, 0xF5, 0xF7, 0x6E, 0xFC, 0xDF, 0xF8, 0xF4, 0x80, ++0xD8, 0xF8, 0x00, 0x30, 0x00, 0x02, 0x23, 0xF4, 0xE0, 0x63, 0x00, 0xF4, 0xE0, 0x60, 0x18, 0x43, 0xC8, 0xF8, 0x00, 0x00, ++0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, ++0x43, 0xF0, 0x04, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF0, 0x01, 0x03, 0xC8, 0xF8, 0x00, 0x30, ++0x3B, 0x68, 0x1B, 0x04, 0x0F, 0xD4, 0x15, 0x4B, 0x1B, 0x68, 0x9B, 0x03, 0x7F, 0xF5, 0x22, 0xAF, 0xF5, 0xF7, 0x18, 0xFC, ++0x00, 0x28, 0x3F, 0xF4, 0x1D, 0xAF, 0x27, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x16, 0xE7, 0xF5, 0xF7, ++0xDF, 0xFB, 0x00, 0x28, 0xEB, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, 0x80, 0x63, 0xC8, 0xF8, ++0x00, 0x30, 0xE2, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x54, 0x00, 0x32, 0x40, 0x64, 0x00, 0x32, 0x40, ++0x38, 0x36, 0x17, 0x00, 0xD8, 0x00, 0x32, 0x40, 0x10, 0x19, 0x04, 0x00, 0x04, 0x00, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x68, 0x00, 0x32, 0x40, 0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0xC0, 0x07, 0xF9, 0x80, ++0x2C, 0x19, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, 0xC0, 0xB3, 0x33, 0x40, 0xA0, 0xA0, 0x28, 0x28, 0x38, 0x00, 0x32, 0x40, ++0x34, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, 0x80, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x40, 0x88, 0x15, 0x00, 0x50, 0x03, 0x32, 0x40, 0x9C, 0x00, 0x32, 0x40, 0x1C, 0x00, 0x32, 0x40, 0x10, 0x00, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x47, 0x5B, 0x4B, 0x5C, 0x4A, 0x1D, 0x68, 0xD2, 0xF8, 0x20, 0x80, 0x15, 0xF0, 0x01, 0x05, 0xD8, 0xF8, ++0xE4, 0x90, 0x84, 0xB0, 0x00, 0xF0, 0x83, 0x80, 0x1A, 0x68, 0x57, 0x4F, 0x22, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x00, 0x23, ++0x7B, 0x70, 0x01, 0x22, 0x54, 0x48, 0x55, 0x49, 0x03, 0x68, 0x55, 0x4C, 0x43, 0xF0, 0x10, 0x03, 0x03, 0x60, 0x0B, 0x68, ++0x00, 0xF5, 0xEC, 0x10, 0x00, 0xF6, 0x6C, 0x70, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x23, 0x68, 0x01, 0x69, 0x00, 0x91, ++0x02, 0x20, 0x4E, 0x49, 0x4E, 0x4C, 0x18, 0xF0, 0x9D, 0xFD, 0x3B, 0x78, 0x00, 0x2B, 0x42, 0xD0, 0xD4, 0xF8, 0x3C, 0x31, ++0xD8, 0xF8, 0x40, 0x60, 0x00, 0x20, 0x98, 0x47, 0x49, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x62, 0xDB, ++0xD4, 0xF8, 0x9C, 0x34, 0xDF, 0xF8, 0x38, 0xA1, 0x98, 0x47, 0xD4, 0xF8, 0x80, 0x34, 0x30, 0x79, 0x98, 0x47, 0x4F, 0xF0, ++0x00, 0x0C, 0x33, 0x89, 0xF2, 0x88, 0x71, 0x79, 0x30, 0x79, 0xCD, 0xF8, 0x08, 0xC0, 0x96, 0xF8, 0x0D, 0xC0, 0xCD, 0xF8, ++0x04, 0xC0, 0xB6, 0xF8, 0x0A, 0xC0, 0xCD, 0xF8, 0x00, 0xC0, 0xF5, 0xF7, 0x9F, 0xFA, 0xD4, 0xF8, 0x3C, 0x33, 0x96, 0xF9, ++0x0C, 0x00, 0x98, 0x47, 0x9A, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x33, 0xD0, 0xD4, 0xF8, 0xA8, 0x34, 0xBA, 0xF8, 0x26, 0x00, ++0x98, 0x47, 0xBA, 0xF8, 0x26, 0x00, 0xD4, 0xF8, 0xAC, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0xD8, 0x34, 0x49, 0x46, 0x40, 0x46, ++0x98, 0x47, 0x00, 0x23, 0xC7, 0xE9, 0x01, 0x33, 0x3B, 0x70, 0x00, 0x2D, 0x33, 0xD0, 0x2B, 0x49, 0x2B, 0x4A, 0x0B, 0x68, ++0x23, 0xF4, 0x00, 0x73, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x28, 0x4A, 0x28, 0x48, 0x13, 0x68, ++0x28, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x83, 0x68, 0xD4, 0xF8, 0xA0, 0x22, 0x5A, 0x65, ++0x20, 0x23, 0x0B, 0x60, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x16, 0x4F, 0x2A, 0x46, 0x81, 0xE7, 0xD4, 0xF8, 0xA0, 0x34, ++0xBA, 0xF8, 0x26, 0x00, 0x98, 0x47, 0xBA, 0xF8, 0x26, 0x00, 0xD4, 0xF8, 0xA4, 0x34, 0x98, 0x47, 0xCA, 0xE7, 0x33, 0x7E, ++0xFF, 0x2B, 0x99, 0xD1, 0x19, 0x49, 0x1A, 0x48, 0x40, 0xF2, 0x89, 0x12, 0x18, 0xF0, 0x4C, 0xFF, 0x92, 0xE7, 0x40, 0x46, ++0x0B, 0xF0, 0xF6, 0xF8, 0xD8, 0xF8, 0x04, 0x30, 0x15, 0x4A, 0x43, 0xF0, 0x01, 0x03, 0xC8, 0xF8, 0x04, 0x30, 0x92, 0xF8, ++0xB6, 0x30, 0x00, 0x2B, 0xC7, 0xD0, 0x03, 0xF0, 0x99, 0xF8, 0xC4, 0xE7, 0x10, 0x00, 0x58, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x3C, 0x36, 0x17, 0x00, 0x94, 0x80, 0x32, 0x40, 0x84, 0x40, 0x04, 0x40, 0x88, 0x00, 0x32, 0x40, 0x88, 0x88, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x8C, 0x00, 0x32, 0x40, 0x78, 0x00, 0x32, 0x40, ++0x00, 0xED, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE0, 0x70, 0x79, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0xF8, 0xB5, 0x3F, 0x4F, 0x3F, 0x4C, 0x3E, 0x6A, 0x3F, 0x49, 0xD6, 0xF8, 0xE4, 0x50, 0x4F, 0xF4, ++0xBE, 0x72, 0x20, 0x46, 0x2B, 0xF0, 0xB0, 0xF9, 0x31, 0x46, 0x4F, 0xF4, 0xA4, 0x62, 0x04, 0xF5, 0xBE, 0x70, 0x2B, 0xF0, ++0xA9, 0xF9, 0x29, 0x46, 0x4F, 0xF4, 0x1E, 0x72, 0x04, 0xF2, 0x9C, 0x60, 0x2B, 0xF0, 0xA2, 0xF9, 0x06, 0xF1, 0xEC, 0x01, ++0xE8, 0x22, 0x04, 0xF6, 0x14, 0x10, 0x2B, 0xF0, 0x9B, 0xF9, 0x31, 0x6C, 0x1C, 0x22, 0x04, 0xF6, 0xFC, 0x10, 0x2B, 0xF0, ++0x95, 0xF9, 0x2F, 0x49, 0x34, 0x22, 0x04, 0xF6, 0x18, 0x20, 0x2B, 0xF0, 0x8F, 0xF9, 0x2D, 0x49, 0x18, 0x22, 0x04, 0xF6, ++0x4C, 0x20, 0x2B, 0xF0, 0x89, 0xF9, 0x2B, 0x49, 0x4F, 0xF4, 0x40, 0x72, 0x04, 0xF6, 0x64, 0x20, 0x2B, 0xF0, 0x82, 0xF9, ++0x28, 0x49, 0x4F, 0xF4, 0x98, 0x62, 0x04, 0xF6, 0x64, 0x50, 0x2B, 0xF0, 0x7B, 0xF9, 0x26, 0x49, 0x26, 0x48, 0x40, 0x22, ++0x2B, 0xF0, 0x76, 0xF9, 0x39, 0x46, 0x28, 0x22, 0x24, 0x48, 0x2B, 0xF0, 0x71, 0xF9, 0x24, 0x49, 0x24, 0x48, 0x60, 0x22, ++0x2B, 0xF0, 0x6C, 0xF9, 0x23, 0x4A, 0x24, 0x4B, 0x12, 0x68, 0xD3, 0xF8, 0x84, 0x60, 0xB2, 0xF8, 0x3C, 0xC0, 0xD3, 0xF8, ++0x80, 0x20, 0xD3, 0xE9, 0x22, 0x07, 0x41, 0xF2, 0x10, 0x33, 0x41, 0xF2, 0x30, 0x31, 0x24, 0xF8, 0x03, 0xC0, 0x41, 0xF2, ++0x2C, 0x33, 0x66, 0x50, 0xE2, 0x50, 0x41, 0xF2, 0x38, 0x36, 0x41, 0xF2, 0x3C, 0x33, 0x41, 0xF2, 0x34, 0x31, 0x18, 0x4A, ++0xE2, 0x50, 0xA7, 0x51, 0x17, 0x4B, 0x60, 0x50, 0x05, 0xF5, 0xBC, 0x70, 0x05, 0xF5, 0xCE, 0x71, 0x50, 0xF8, 0x04, 0x2F, ++0x1A, 0xB1, 0x14, 0x7B, 0x9C, 0x70, 0x12, 0x89, 0x1A, 0x80, 0x88, 0x42, 0x03, 0xF1, 0x04, 0x03, 0xF4, 0xD1, 0xF8, 0xBD, ++0x1C, 0x9E, 0x17, 0x00, 0x00, 0x40, 0x1E, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0x34, 0xE0, 0x17, 0x00, 0xF4, 0xDF, 0x17, 0x00, 0x24, 0x52, 0x1E, 0x00, 0x64, 0x52, 0x1E, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x8C, 0x52, 0x1E, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, ++0xEC, 0x52, 0x1E, 0x00, 0x70, 0xB5, 0x65, 0x4A, 0x53, 0x78, 0x00, 0x2B, 0x7F, 0xD1, 0x64, 0x4B, 0x1B, 0x68, 0x3B, 0xB1, ++0x63, 0x48, 0xD9, 0x68, 0x00, 0x69, 0x09, 0x1A, 0xB1, 0xF5, 0xFA, 0x6F, 0x00, 0xF1, 0xA5, 0x80, 0x13, 0x78, 0x00, 0x2B, ++0x68, 0xD0, 0xD2, 0xE9, 0x01, 0x35, 0x5D, 0x48, 0x5D, 0x4A, 0x5E, 0x49, 0x04, 0x69, 0x0E, 0x68, 0xB2, 0xF8, 0xB0, 0x00, ++0xB2, 0xF8, 0xB2, 0x10, 0xB2, 0x8E, 0x2B, 0x44, 0x1B, 0x1B, 0x1B, 0x1A, 0x5B, 0x1A, 0x9B, 0x1A, 0x00, 0x2B, 0xC0, 0xF2, ++0x98, 0x80, 0xFF, 0xF7, 0x37, 0xFF, 0x56, 0x4B, 0x1B, 0x6A, 0x1C, 0x6C, 0x23, 0x79, 0x20, 0x89, 0x00, 0x2B, 0x56, 0xD0, ++0x2A, 0xF0, 0xC8, 0xFB, 0x02, 0x46, 0x0B, 0x46, 0x2A, 0xF0, 0x78, 0xFA, 0x50, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0x54, 0xFD, ++0x4F, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0x26, 0xFC, 0x2A, 0xF0, 0x1E, 0xFA, 0x2A, 0xF0, 0xBC, 0xFE, 0x05, 0x46, 0x20, 0x89, ++0x2A, 0xF0, 0xB4, 0xFB, 0x02, 0x46, 0x0B, 0x46, 0x00, 0x20, 0x49, 0x49, 0x2A, 0xF0, 0x42, 0xFD, 0x00, 0x22, 0x4F, 0xF0, ++0x83, 0x43, 0x2A, 0xF0, 0x13, 0xFC, 0x2A, 0xF0, 0x0B, 0xFA, 0x2A, 0xF0, 0xA9, 0xFE, 0x03, 0x46, 0x20, 0x89, 0x1C, 0x46, ++0x2A, 0xF0, 0xA0, 0xFB, 0x34, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x2A, 0xF0, 0x2F, 0xFD, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, ++0x2A, 0xF0, 0x00, 0xFC, 0x2A, 0xF0, 0xF8, 0xF9, 0x2A, 0xF0, 0x96, 0xFE, 0x3A, 0x4B, 0x3B, 0x49, 0x03, 0xF5, 0x99, 0x56, ++0x02, 0x46, 0x35, 0x60, 0x41, 0xF2, 0x24, 0x30, 0x41, 0xF2, 0x28, 0x35, 0x1C, 0x50, 0x5A, 0x51, 0x02, 0x20, 0x18, 0xF0, ++0xD5, 0xFB, 0x35, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x33, 0x49, 0x02, 0x20, 0x18, 0xF0, 0xCC, 0xFB, ++0x30, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x30, 0x49, 0xF5, 0xE7, 0x2A, 0xF0, 0x71, 0xFB, 0x2F, 0x4B, ++0x00, 0x22, 0x2A, 0xF0, 0xD7, 0xFB, 0x25, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0xFD, 0xFC, 0x24, 0x4B, 0x00, 0x22, 0x2A, 0xF0, ++0xCF, 0xFB, 0x2A, 0xF0, 0xC7, 0xF9, 0x2A, 0xF0, 0x65, 0xFE, 0x05, 0x46, 0x20, 0x89, 0x2A, 0xF0, 0x5D, 0xFB, 0x02, 0x46, ++0x0B, 0x46, 0x00, 0x20, 0x24, 0x49, 0x2A, 0xF0, 0xEB, 0xFC, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x2A, 0xF0, 0xBC, 0xFB, ++0x2A, 0xF0, 0xB4, 0xF9, 0x2A, 0xF0, 0x52, 0xFE, 0x03, 0x46, 0x20, 0x89, 0x1C, 0x46, 0x2A, 0xF0, 0x49, 0xFB, 0x0B, 0xA3, ++0xD3, 0xE9, 0x00, 0x23, 0xA7, 0xE7, 0x5A, 0x68, 0x1A, 0x49, 0x02, 0x20, 0x18, 0xF0, 0x92, 0xFB, 0x13, 0x4B, 0x4F, 0xF0, ++0x00, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x17, 0x49, 0xBB, 0xE7, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x10, 0xB3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xA2, 0x40, 0x3C, 0x36, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x00, 0x6A, 0x40, ++0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0xB9, 0x40, 0x00, 0x40, 0x1E, 0x00, 0x20, 0x89, 0x15, 0x00, 0x00, 0x41, 0x04, 0x40, ++0x1C, 0x89, 0x15, 0x00, 0xC4, 0x88, 0x15, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0xA4, 0x40, 0xE8, 0x88, 0x15, 0x00, ++0x00, 0x89, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, 0x56, 0x4E, 0xDF, 0xF8, 0x90, 0x81, 0x96, 0xF8, ++0xDF, 0x31, 0x96, 0xF8, 0xBF, 0x56, 0xDF, 0xF8, 0x88, 0xB1, 0x53, 0x4C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xF7, ++0x83, 0xB0, 0x08, 0xEB, 0x07, 0x09, 0x06, 0xF5, 0xBE, 0x71, 0x48, 0x46, 0x01, 0x93, 0x4F, 0xF4, 0x1E, 0x7A, 0x00, 0x97, ++0x2B, 0xF0, 0x0E, 0xF8, 0x07, 0xF1, 0xEC, 0x00, 0x0A, 0xFB, 0x05, 0xF5, 0x06, 0xF6, 0x14, 0x11, 0xE8, 0x22, 0x40, 0x44, ++0x2B, 0xF0, 0x04, 0xF8, 0x05, 0xEB, 0x0B, 0x03, 0x18, 0x46, 0x52, 0x46, 0x06, 0xF2, 0x9C, 0x61, 0x08, 0xEE, 0x10, 0x3A, ++0x2A, 0xF0, 0xFA, 0xFF, 0x06, 0xF6, 0xFC, 0x11, 0x1C, 0x22, 0xD9, 0xF8, 0x40, 0x00, 0x3F, 0x4F, 0xDF, 0xF8, 0x30, 0xA1, ++0x2A, 0xF0, 0xF0, 0xFF, 0x06, 0xF6, 0x18, 0x21, 0x34, 0x22, 0x3C, 0x48, 0x2A, 0xF0, 0xEA, 0xFF, 0x31, 0x46, 0x4F, 0xF4, ++0xBE, 0x72, 0x3A, 0x48, 0x2A, 0xF0, 0xE4, 0xFF, 0x06, 0xF6, 0x4C, 0x21, 0x18, 0x22, 0x38, 0x48, 0x2A, 0xF0, 0xDE, 0xFF, ++0x06, 0xF6, 0x64, 0x21, 0x4F, 0xF4, 0x18, 0x62, 0x35, 0x48, 0x2A, 0xF0, 0xD7, 0xFF, 0x06, 0xF6, 0x64, 0x51, 0x4F, 0xF4, ++0x98, 0x62, 0x33, 0x48, 0x33, 0x4E, 0x2A, 0xF0, 0xCF, 0xFF, 0x40, 0x22, 0xA4, 0xF1, 0xC8, 0x01, 0x31, 0x48, 0x2A, 0xF0, ++0xC9, 0xFF, 0x28, 0x22, 0xA4, 0xF1, 0x88, 0x01, 0x2F, 0x48, 0x2A, 0xF0, 0xC3, 0xFF, 0x2F, 0x48, 0x60, 0x22, 0xA4, 0xF1, ++0x60, 0x01, 0x2A, 0xF0, 0xBD, 0xFF, 0x05, 0xF5, 0xBE, 0x75, 0xAB, 0x44, 0x5B, 0xF8, 0x04, 0x3B, 0x50, 0x46, 0x19, 0x46, ++0x4B, 0xB1, 0xA2, 0x78, 0x1A, 0x73, 0xD7, 0xF8, 0xDC, 0x22, 0x25, 0x88, 0x1D, 0x81, 0xC3, 0xE9, 0x45, 0x23, 0x17, 0xF0, ++0x01, 0xF9, 0x04, 0x34, 0xB4, 0x42, 0xED, 0xD1, 0x1B, 0x48, 0x22, 0x4D, 0x49, 0x46, 0x17, 0xF0, 0xF9, 0xF8, 0x21, 0x48, ++0x49, 0x46, 0x17, 0xF0, 0xA5, 0xF8, 0x00, 0x9E, 0x06, 0xF1, 0xE4, 0x00, 0x18, 0xEE, 0x10, 0x1A, 0x40, 0x44, 0x17, 0xF0, ++0x9D, 0xF8, 0x01, 0x9A, 0xA4, 0x24, 0x99, 0x23, 0x14, 0xFB, 0x02, 0x34, 0x08, 0xEB, 0xC4, 0x04, 0x35, 0x44, 0x20, 0x46, ++0x17, 0xF0, 0x8E, 0xF8, 0x04, 0xF1, 0x28, 0x00, 0x08, 0x34, 0x17, 0xF0, 0x89, 0xF8, 0xAC, 0x42, 0xF5, 0xD1, 0x00, 0x9B, ++0x03, 0xF5, 0xA3, 0x60, 0x40, 0x44, 0x03, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x4F, 0x17, 0xF0, 0x7C, 0xB8, ++0x00, 0x40, 0x1E, 0x00, 0xEC, 0x52, 0x1E, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x34, 0xE0, 0x17, 0x00, 0x10, 0x53, 0x1E, 0x00, 0xF4, 0xDF, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x08, 0x8D, 0x17, 0x00, 0x08, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0xF8, 0xDE, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x6C, 0x4E, 0x6D, 0x4A, 0x33, 0x68, 0xDF, 0xF8, ++0x00, 0x82, 0x0D, 0x46, 0x09, 0x8C, 0x9B, 0xB2, 0x43, 0xEA, 0x01, 0x43, 0xD0, 0xF8, 0x90, 0x11, 0x33, 0x60, 0x8B, 0x78, ++0x67, 0x49, 0x02, 0xEB, 0x83, 0x03, 0x1C, 0x3E, 0x5B, 0x69, 0x0B, 0x60, 0x31, 0x68, 0x21, 0xF4, 0xE0, 0x61, 0x04, 0x46, ++0x50, 0x68, 0x31, 0x60, 0x13, 0x68, 0x62, 0x49, 0x62, 0x4A, 0x03, 0x43, 0x0B, 0x60, 0x62, 0x4B, 0x62, 0x49, 0x11, 0x60, ++0x62, 0x4A, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x9F, 0x03, 0x70, 0xD4, 0x60, 0x4B, 0x1B, 0x68, 0x1A, 0x68, 0xE2, 0xB1, ++0x5F, 0x49, 0x0A, 0x60, 0x5A, 0x68, 0xF2, 0xB1, 0xC2, 0xF3, 0x0B, 0x01, 0x00, 0x29, 0x61, 0xD1, 0xE1, 0x68, 0x5C, 0x48, ++0x22, 0xF4, 0x7F, 0x62, 0x22, 0xF0, 0x0F, 0x02, 0xC1, 0xF3, 0x0B, 0x01, 0x0A, 0x43, 0x02, 0x60, 0x9A, 0x68, 0xA2, 0xB9, ++0x57, 0x4A, 0x21, 0x69, 0x11, 0x60, 0xDB, 0x68, 0xA3, 0xB9, 0x56, 0x4B, 0x62, 0x69, 0x1A, 0x60, 0x12, 0xE0, 0x51, 0x4A, ++0xA1, 0x68, 0x11, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0xE0, 0xD1, 0x4F, 0x4A, 0xE1, 0x68, 0x11, 0x60, 0x9A, 0x68, 0x00, 0x2A, ++0xEA, 0xD0, 0x4D, 0x49, 0x0A, 0x60, 0xDB, 0x68, 0x00, 0x2B, 0xEA, 0xD0, 0x4B, 0x4A, 0x13, 0x60, 0x4B, 0x4B, 0xD3, 0xF8, ++0x60, 0x32, 0x98, 0x47, 0x4A, 0x4B, 0x1B, 0x68, 0x9C, 0x01, 0x06, 0xD4, 0x49, 0x4B, 0x3E, 0x4A, 0x01, 0x21, 0x19, 0x60, ++0x13, 0x68, 0x0B, 0x43, 0x13, 0x60, 0x28, 0x46, 0x1B, 0xF0, 0xE4, 0xFA, 0x43, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x04, 0x03, ++0x13, 0x60, 0x01, 0x21, 0x00, 0x20, 0x16, 0xF0, 0x51, 0xFD, 0x41, 0x4B, 0x1B, 0x68, 0x5A, 0x78, 0x22, 0xB1, 0x40, 0x49, ++0x0A, 0x68, 0x42, 0xF0, 0x40, 0x02, 0x0A, 0x60, 0x3E, 0x49, 0x9B, 0x78, 0x0A, 0x68, 0xD8, 0x06, 0x4C, 0xBF, 0x22, 0xF0, ++0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x3A, 0x4A, 0x13, 0xF0, 0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, ++0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x2B, 0x49, 0x0A, 0x60, 0xB8, 0xE7, 0xF4, 0xF7, ++0xD7, 0xFF, 0x00, 0x28, 0x8A, 0xD0, 0xF5, 0xF7, 0x07, 0xF8, 0x31, 0x4F, 0x3B, 0x68, 0x00, 0x02, 0x23, 0xF4, 0xE0, 0x63, ++0x00, 0xF4, 0xE0, 0x60, 0x18, 0x43, 0x38, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0x3B, 0x60, ++0x3B, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x3B, 0x60, 0x3B, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, ++0x1B, 0x04, 0x0F, 0xD4, 0x24, 0x4B, 0x1B, 0x68, 0x9E, 0x03, 0x7F, 0xF5, 0x69, 0xAF, 0xF4, 0xF7, 0xB9, 0xFF, 0x00, 0x28, ++0x3F, 0xF4, 0x64, 0xAF, 0x1E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x5D, 0xE7, 0xF4, 0xF7, 0x80, 0xFF, ++0x00, 0x28, 0xEB, 0xD0, 0x33, 0x68, 0x43, 0xF4, 0x00, 0x23, 0x33, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, ++0x80, 0x63, 0x3B, 0x60, 0xE0, 0xE7, 0x00, 0xBF, 0x68, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, ++0x60, 0x00, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0xC0, 0x07, 0xF9, 0x80, ++0xAC, 0x35, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, ++0x80, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x50, 0x03, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x33, 0x4D, 0xDF, 0xF8, 0xE4, 0x80, 0xD5, 0xF8, 0xD0, 0x34, 0x32, 0x4E, 0x41, 0xF2, 0x12, 0x32, 0x18, 0xF8, 0x02, 0x70, ++0x98, 0x47, 0xD5, 0xF8, 0x9C, 0x34, 0x98, 0x47, 0xD8, 0xF8, 0xBC, 0x41, 0xF4, 0xF7, 0x46, 0xF9, 0x2C, 0x49, 0xD5, 0xF8, ++0x88, 0x24, 0x0B, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x0B, 0x60, 0x20, 0x79, 0x90, 0x47, 0x23, 0x79, 0x86, 0xF8, 0x2A, 0x30, ++0x62, 0x79, 0x86, 0xF8, 0x2B, 0x20, 0x62, 0x7B, 0x86, 0xF8, 0x2C, 0x20, 0xE1, 0x88, 0x20, 0x89, 0x62, 0x89, 0x32, 0x85, ++0xFF, 0xB2, 0xB1, 0x84, 0xF0, 0x84, 0xD3, 0xB9, 0xD5, 0xF8, 0xA0, 0x34, 0x98, 0x47, 0xF0, 0x8C, 0xD5, 0xF8, 0xA4, 0x34, ++0x98, 0x47, 0x1D, 0x4E, 0x94, 0xF9, 0x0C, 0x00, 0xD5, 0xF8, 0x3C, 0x33, 0x98, 0x47, 0xD5, 0xF8, 0xD4, 0x34, 0x06, 0xF5, ++0xA4, 0x61, 0x30, 0x46, 0x98, 0x47, 0x17, 0xF0, 0x0D, 0x0F, 0x0C, 0xD0, 0xD5, 0xF8, 0x54, 0x32, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0xD5, 0xF8, 0xA8, 0x34, 0x98, 0x47, 0xF0, 0x8C, 0xD5, 0xF8, 0xAC, 0x34, 0x98, 0x47, 0xE3, 0xE7, 0xBB, 0x07, ++0x14, 0xD5, 0x0F, 0x4A, 0xD8, 0xF8, 0x80, 0x31, 0x11, 0x69, 0x0E, 0x48, 0xD5, 0xF8, 0xE0, 0x21, 0x46, 0x61, 0x05, 0x24, ++0x44, 0x77, 0x01, 0xF5, 0x1C, 0x51, 0x43, 0xF0, 0x02, 0x03, 0xC8, 0xF8, 0x80, 0x31, 0x10, 0x31, 0xBD, 0xE8, 0xF0, 0x41, ++0x0C, 0x30, 0x10, 0x47, 0xBD, 0xE8, 0xF0, 0x81, 0x88, 0x1A, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, ++0x7C, 0x41, 0x1E, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x40, 0x1E, 0x00, 0x38, 0xB5, 0x50, 0xBB, ++0x1A, 0x4B, 0x1A, 0x68, 0x52, 0xB1, 0x1A, 0x4B, 0x1A, 0x49, 0x18, 0x69, 0xD3, 0x68, 0xB1, 0xF8, 0xB0, 0x10, 0x1B, 0x1A, ++0x5B, 0x1A, 0xB3, 0xF5, 0xFA, 0x6F, 0x17, 0xD4, 0x16, 0x4A, 0x13, 0x78, 0x7B, 0xB1, 0xD2, 0xE9, 0x01, 0x34, 0x12, 0x48, ++0x14, 0x4D, 0x12, 0x49, 0x00, 0x69, 0x2A, 0x68, 0xB1, 0xF8, 0xB0, 0x10, 0x92, 0x8E, 0x23, 0x44, 0x1B, 0x1A, 0x5B, 0x1A, ++0x9B, 0x1A, 0x00, 0x2B, 0x0E, 0xDB, 0x0F, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x38, 0xBD, 0x52, 0x68, 0x0D, 0x49, ++0x02, 0x20, 0x18, 0xF0, 0xDB, 0xF8, 0x0A, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x38, 0xBD, 0x09, 0x49, 0x02, 0x20, ++0x18, 0xF0, 0xD2, 0xF8, 0xF5, 0xE7, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0x3C, 0x36, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x41, 0x04, 0x40, 0xE8, 0x88, 0x15, 0x00, 0x28, 0x89, 0x15, 0x00, ++0xF0, 0xB5, 0x1B, 0x4B, 0x01, 0x22, 0x85, 0xB0, 0xDA, 0x60, 0xEF, 0xF3, 0x14, 0x81, 0xEF, 0xF3, 0x03, 0x82, 0xEF, 0xF3, ++0x09, 0x85, 0xEF, 0xF3, 0x08, 0x84, 0xEF, 0xF3, 0x10, 0x83, 0x70, 0x46, 0xCD, 0xE9, 0x01, 0x30, 0x00, 0x94, 0x13, 0x48, ++0x2B, 0x46, 0x18, 0xF0, 0x59, 0xF8, 0x15, 0xB9, 0x34, 0xB9, 0x05, 0xB0, 0xF0, 0xBD, 0x10, 0x48, 0x18, 0xF0, 0x52, 0xF8, ++0x00, 0x2C, 0xF8, 0xD0, 0x0E, 0x48, 0x0F, 0x4F, 0x0F, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0x18, 0xF0, 0x49, 0xF8, 0x04, 0xF5, ++0x80, 0x75, 0x06, 0xE0, 0x54, 0xF8, 0x04, 0x1B, 0x30, 0x46, 0x18, 0xF0, 0x41, 0xF8, 0xA5, 0x42, 0xE7, 0xD0, 0x23, 0x07, ++0xF6, 0xD1, 0x21, 0x46, 0x38, 0x46, 0x18, 0xF0, 0x39, 0xF8, 0xF1, 0xE7, 0x00, 0xA0, 0x10, 0x40, 0x40, 0x89, 0x15, 0x00, ++0x94, 0x89, 0x15, 0x00, 0xA0, 0x89, 0x15, 0x00, 0xAC, 0x89, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0x30, 0xB4, 0x0C, 0x4C, ++0x0C, 0x49, 0xD4, 0xF8, 0x3C, 0x31, 0x0C, 0x4A, 0x0C, 0x4D, 0x43, 0xF0, 0x04, 0x03, 0xC4, 0xF8, 0x3C, 0x31, 0xC0, 0x03, ++0x03, 0x24, 0xF4, 0x23, 0x08, 0x60, 0x8C, 0x60, 0x82, 0xF8, 0x44, 0x33, 0xAB, 0x68, 0x07, 0x49, 0xC3, 0xF8, 0x50, 0x11, ++0x10, 0x23, 0x30, 0xBC, 0x93, 0x60, 0x70, 0x47, 0x00, 0x00, 0x50, 0x40, 0x00, 0xA0, 0x10, 0x40, 0x00, 0xE1, 0x00, 0xE0, ++0x00, 0xED, 0x00, 0xE0, 0xA9, 0xC5, 0x12, 0x00, 0x01, 0x4B, 0x1A, 0x68, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, ++0x02, 0x4A, 0x93, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x93, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, 0x02, 0x4A, 0x93, 0x68, ++0x43, 0xF0, 0x02, 0x03, 0x93, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, 0x08, 0xB5, 0x06, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0xFE, 0xE7, 0x03, 0x49, 0x04, 0x48, 0xBA, 0x22, 0x18, 0xF0, 0x5F, 0xFA, 0xF8, 0xE7, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x0B, 0x4B, 0x41, 0xF2, 0x1C, 0x32, 0x41, 0xF2, ++0x18, 0x31, 0x9A, 0x58, 0x5B, 0x58, 0x72, 0xB1, 0x10, 0xB4, 0x08, 0x4C, 0x00, 0x22, 0x19, 0x68, 0x58, 0x68, 0x08, 0x60, ++0x21, 0x68, 0x02, 0x32, 0x91, 0x42, 0x03, 0xF1, 0x08, 0x03, 0xF6, 0xD8, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x70, 0x47, ++0x00, 0x40, 0x1E, 0x00, 0x1C, 0x53, 0x1E, 0x00, 0x32, 0x49, 0x33, 0x4B, 0x99, 0x42, 0x10, 0xB5, 0x0C, 0xD2, 0x01, 0x3B, ++0x5B, 0x1A, 0x31, 0x4A, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x52, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0B, ++0x9A, 0x42, 0xF9, 0xD1, 0x2C, 0x4A, 0x2D, 0x4B, 0x9A, 0x42, 0x0A, 0xD2, 0x01, 0x3B, 0x9B, 0x1A, 0x23, 0xF0, 0x03, 0x03, ++0x04, 0x33, 0x13, 0x44, 0x00, 0x21, 0x42, 0xF8, 0x04, 0x1B, 0x9A, 0x42, 0xFB, 0xD1, 0x27, 0x49, 0x27, 0x4B, 0x99, 0x42, ++0x0D, 0xD2, 0x01, 0x3B, 0x5B, 0x1A, 0x26, 0x4A, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x08, 0x46, 0x52, 0xF8, ++0x04, 0x4B, 0x40, 0xF8, 0x04, 0x4B, 0x9A, 0x42, 0xF9, 0xD1, 0x21, 0x4A, 0x21, 0x48, 0xD2, 0xF8, 0x88, 0x30, 0x43, 0xF4, ++0x70, 0x03, 0xC2, 0xF8, 0x88, 0x30, 0x91, 0x60, 0x00, 0x23, 0xFF, 0x21, 0xC2, 0x18, 0x01, 0x33, 0x50, 0x2B, 0x82, 0xF8, ++0x00, 0x13, 0xF9, 0xD1, 0x1A, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x80, 0x6F, 0x16, 0x4B, 0x1B, 0x68, 0x4F, 0xF6, 0xF0, 0x72, ++0x03, 0xEA, 0x02, 0x03, 0x0D, 0xD0, 0x4C, 0xF2, 0x40, 0x22, 0x93, 0x42, 0x0D, 0xD0, 0x14, 0x4C, 0xF5, 0xF7, 0xBC, 0xFC, ++0xD4, 0xF8, 0x7C, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0x74, 0x34, 0x98, 0x47, 0xFE, 0xE7, 0x4D, 0xF2, 0x10, 0x22, 0x93, 0x42, ++0xF1, 0xD1, 0x0E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xED, 0xE7, 0x00, 0xBF, 0x80, 0x01, 0x17, 0x00, 0x5C, 0x25, 0x17, 0x00, ++0x2C, 0xD2, 0x15, 0x00, 0x60, 0x25, 0x17, 0x00, 0x28, 0x07, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x80, 0x01, 0x17, 0x00, ++0x00, 0x00, 0x12, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x68, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x72, 0x4F, 0x73, 0x4E, 0x86, 0xB0, 0x3D, 0x46, 0x00, 0x24, 0x21, 0x46, ++0x55, 0xF8, 0x04, 0x2B, 0x30, 0x46, 0x01, 0x34, 0xF9, 0xF7, 0x6A, 0xFD, 0x0D, 0x2C, 0xF6, 0xD1, 0xD7, 0xE9, 0x11, 0x21, ++0x3B, 0x6C, 0x6C, 0x4D, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x21, 0x6B, 0x48, 0x79, 0x6B, 0xD7, 0xE9, 0x0E, 0x23, 0xF9, 0xF7, ++0x5B, 0xFD, 0x29, 0x68, 0x6A, 0x68, 0xAB, 0x68, 0xE8, 0x68, 0x00, 0x90, 0x66, 0x48, 0xF9, 0xF7, 0x53, 0xFD, 0x69, 0x6A, ++0xAA, 0x6A, 0xEB, 0x6A, 0x28, 0x6B, 0xEC, 0x6B, 0xCD, 0xE9, 0x00, 0x04, 0x62, 0x48, 0xF9, 0xF7, 0x49, 0xFD, 0xAC, 0x6A, ++0x14, 0xF0, 0xFF, 0x01, 0x68, 0xD1, 0xC4, 0xF3, 0x07, 0x25, 0x14, 0xF4, 0x7F, 0x4F, 0x29, 0x46, 0x44, 0xD1, 0x21, 0x0C, ++0x2E, 0xD1, 0xFB, 0x6C, 0x1C, 0x07, 0x23, 0xD5, 0x5A, 0x48, 0xF9, 0xF7, 0x37, 0xFD, 0x3B, 0x6D, 0xD8, 0x07, 0x21, 0xD4, ++0x58, 0x48, 0xF9, 0xF7, 0x31, 0xFD, 0xFB, 0x6C, 0x59, 0x07, 0x4C, 0xBF, 0x56, 0x48, 0x57, 0x48, 0xF9, 0xF7, 0x2A, 0xFD, ++0x39, 0x6D, 0xEF, 0xF3, 0x10, 0x82, 0xEF, 0xF3, 0x13, 0x83, 0xEF, 0xF3, 0x11, 0x80, 0x00, 0x90, 0x52, 0x48, 0xF9, 0xF7, ++0x1F, 0xFD, 0xBC, 0x6C, 0x00, 0x2C, 0x71, 0xD1, 0x7C, 0x6C, 0x00, 0x2C, 0x56, 0xD1, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, ++0x4D, 0x48, 0xF9, 0xF7, 0x13, 0xFD, 0xDD, 0xE7, 0x4C, 0x48, 0xF9, 0xF7, 0x0F, 0xFD, 0xDC, 0xE7, 0xC4, 0xF3, 0x40, 0x63, ++0xC4, 0xF3, 0x00, 0x60, 0xC4, 0xF3, 0xC0, 0x42, 0x03, 0x93, 0xC4, 0xF3, 0x80, 0x43, 0xCD, 0xE9, 0x01, 0x20, 0x00, 0x93, ++0xC4, 0xF3, 0x00, 0x42, 0xC4, 0xF3, 0x40, 0x43, 0x43, 0x48, 0xF9, 0xF7, 0xFB, 0xFC, 0xBC, 0xE7, 0xC4, 0xF3, 0xC0, 0x33, ++0xC4, 0xF3, 0x00, 0x30, 0xC4, 0xF3, 0xC0, 0x22, 0x04, 0x93, 0xC4, 0xF3, 0x40, 0x36, 0xC4, 0xF3, 0x80, 0x23, 0xCD, 0xE9, ++0x00, 0x32, 0xCD, 0xE9, 0x02, 0x06, 0xC4, 0xF3, 0x40, 0x23, 0x3A, 0x48, 0xC4, 0xF3, 0x00, 0x22, 0xF9, 0xF7, 0xE4, 0xFC, ++0x2D, 0x06, 0xA2, 0xD5, 0x2A, 0x4B, 0x37, 0x48, 0x99, 0x6B, 0xF9, 0xF7, 0xDD, 0xFC, 0x9C, 0xE7, 0xC4, 0xF3, 0xC0, 0x16, ++0xC4, 0xF3, 0x40, 0x10, 0xC4, 0xF3, 0x00, 0x12, 0xC4, 0xF3, 0xC0, 0x03, 0xCD, 0xE9, 0x02, 0x06, 0xCD, 0xE9, 0x00, 0x32, ++0x2F, 0x48, 0xC4, 0xF3, 0x40, 0x03, 0x04, 0xF0, 0x01, 0x02, 0xF9, 0xF7, 0xC9, 0xFC, 0x26, 0x06, 0x81, 0xD5, 0x69, 0x6B, ++0x2B, 0x48, 0xF9, 0xF7, 0xC3, 0xFC, 0x7C, 0xE7, 0x2A, 0x48, 0x2B, 0x4F, 0x2B, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0xF9, 0xF7, ++0xBB, 0xFC, 0x04, 0xF5, 0x80, 0x75, 0x06, 0xE0, 0x54, 0xF8, 0x04, 0x1B, 0x30, 0x46, 0xF9, 0xF7, 0xB3, 0xFC, 0xA5, 0x42, ++0x97, 0xD0, 0x23, 0x07, 0xF6, 0xD1, 0x21, 0x46, 0x38, 0x46, 0xF9, 0xF7, 0xAB, 0xFC, 0xF1, 0xE7, 0x21, 0x48, 0xDF, 0xF8, ++0x7C, 0x80, 0x1F, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0xF9, 0xF7, 0xA2, 0xFC, 0x04, 0xF5, 0x80, 0x75, 0x07, 0xE0, 0x54, 0xF8, ++0x04, 0x1B, 0x30, 0x46, 0xF9, 0xF7, 0x9A, 0xFC, 0xA5, 0x42, 0x3F, 0xF4, 0x7B, 0xAF, 0x22, 0x07, 0xF5, 0xD1, 0x21, 0x46, ++0x40, 0x46, 0xF9, 0xF7, 0x91, 0xFC, 0xF0, 0xE7, 0xE4, 0x60, 0x17, 0x00, 0xC0, 0x89, 0x15, 0x00, 0x00, 0xED, 0x00, 0xE0, ++0xD0, 0x89, 0x15, 0x00, 0x1C, 0x8A, 0x15, 0x00, 0x50, 0x8A, 0x15, 0x00, 0xF0, 0x8B, 0x15, 0x00, 0x10, 0x8C, 0x15, 0x00, ++0x34, 0x8C, 0x15, 0x00, 0x40, 0x8C, 0x15, 0x00, 0x4C, 0x8C, 0x15, 0x00, 0x24, 0x8C, 0x15, 0x00, 0x00, 0x8C, 0x15, 0x00, ++0x8C, 0x8B, 0x15, 0x00, 0x04, 0x8B, 0x15, 0x00, 0x7C, 0x8B, 0x15, 0x00, 0x90, 0x8A, 0x15, 0x00, 0xF4, 0x8A, 0x15, 0x00, ++0x80, 0x8C, 0x15, 0x00, 0xAC, 0x89, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0xA0, 0x89, 0x15, 0x00, 0x08, 0xB5, 0x02, 0x48, ++0xF9, 0xF7, 0x60, 0xFC, 0xFE, 0xE7, 0x00, 0xBF, 0x8C, 0x8C, 0x15, 0x00, 0x04, 0x46, 0x08, 0xB5, 0x10, 0x48, 0xF9, 0xF7, ++0x57, 0xFC, 0x30, 0x2C, 0x10, 0xD0, 0x40, 0x2C, 0x16, 0xD0, 0x20, 0x2C, 0x10, 0xD0, 0x0D, 0x48, 0xF9, 0xF7, 0x4E, 0xFC, ++0x0C, 0x48, 0xF9, 0xF7, 0x4B, 0xFC, 0xFF, 0xF7, 0xD1, 0xFE, 0x0B, 0x48, 0xF9, 0xF7, 0x46, 0xFC, 0xFF, 0xF7, 0xE0, 0xFF, ++0x09, 0x48, 0xF9, 0xF7, 0x41, 0xFC, 0xF1, 0xE7, 0x08, 0x48, 0xF9, 0xF7, 0x3D, 0xFC, 0xED, 0xE7, 0x07, 0x48, 0xF9, 0xF7, ++0x39, 0xFC, 0xE9, 0xE7, 0x98, 0x8C, 0x15, 0x00, 0xE8, 0x8C, 0x15, 0x00, 0xF4, 0x8C, 0x15, 0x00, 0x00, 0x8D, 0x15, 0x00, ++0xD0, 0x8C, 0x15, 0x00, 0xC0, 0x8C, 0x15, 0x00, 0xDC, 0x8C, 0x15, 0x00, 0x4F, 0xF0, 0x10, 0x03, 0x00, 0xF0, 0x0C, 0xB8, ++0x4F, 0xF0, 0x20, 0x03, 0x00, 0xF0, 0x08, 0xB8, 0x4F, 0xF0, 0x30, 0x03, 0x00, 0xF0, 0x04, 0xB8, 0x4F, 0xF0, 0x40, 0x03, ++0x00, 0xF0, 0x00, 0xB8, 0xEF, 0xF3, 0x08, 0x80, 0x4F, 0xF0, 0x04, 0x01, 0x72, 0x46, 0x0A, 0x42, 0x01, 0xD0, 0xEF, 0xF3, ++0x09, 0x80, 0x9C, 0x46, 0x24, 0x49, 0x02, 0x68, 0x0A, 0x60, 0x04, 0x31, 0x42, 0x68, 0x0A, 0x60, 0x04, 0x31, 0x82, 0x68, ++0x0A, 0x60, 0x04, 0x31, 0xC2, 0x68, 0x0A, 0x60, 0x04, 0x31, 0xF0, 0xC1, 0x47, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x4F, 0x46, ++0x0F, 0x60, 0x04, 0x31, 0x57, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x5F, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x02, 0x69, 0x0A, 0x60, ++0x08, 0x31, 0x42, 0x69, 0x0A, 0x60, 0x04, 0x31, 0x82, 0x69, 0x0A, 0x60, 0x04, 0x31, 0xC2, 0x69, 0x0A, 0x60, 0x04, 0x31, ++0x03, 0x46, 0x20, 0x33, 0x4F, 0xF4, 0x00, 0x76, 0x32, 0x42, 0x00, 0xD0, 0x04, 0x33, 0x75, 0x46, 0x4F, 0xF0, 0x10, 0x06, ++0x35, 0x42, 0x00, 0xD1, 0x48, 0x33, 0x0C, 0x46, 0x10, 0x3C, 0x23, 0x60, 0xEF, 0xF3, 0x09, 0x82, 0x0A, 0x60, 0x04, 0x31, ++0xEF, 0xF3, 0x08, 0x82, 0x0A, 0x60, 0x04, 0x31, 0x72, 0x46, 0x0A, 0x60, 0x04, 0x31, 0xEF, 0xF3, 0x14, 0x82, 0x0A, 0x60, ++0x03, 0x4B, 0x60, 0x46, 0x01, 0x49, 0x98, 0x47, 0xFE, 0xE7, 0x00, 0x00, 0xE4, 0x60, 0x17, 0x00, 0x3D, 0xCA, 0x12, 0x00, ++0x08, 0xB5, 0x08, 0x4B, 0x00, 0x22, 0x5A, 0x70, 0x18, 0xF0, 0x3E, 0xF8, 0x1A, 0xF0, 0x14, 0xFC, 0x05, 0x4B, 0xD3, 0xF8, ++0xA8, 0x31, 0x98, 0x47, 0x16, 0xF0, 0x88, 0xFB, 0xBD, 0xE8, 0x08, 0x40, 0x18, 0xF0, 0x42, 0xB8, 0x70, 0x28, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x4B, 0x4E, 0x4C, 0x4A, 0x4C, 0x49, 0x4D, 0x48, 0x17, 0xF0, 0x6E, 0xFD, ++0x33, 0x68, 0xDB, 0x78, 0x00, 0x2B, 0x40, 0xF0, 0x89, 0x80, 0x62, 0xB6, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, ++0xDF, 0xF8, 0x3C, 0x81, 0xDF, 0xF8, 0x3C, 0x91, 0x45, 0x4D, 0x46, 0x4F, 0x46, 0x4C, 0xDF, 0xF8, 0x38, 0xB1, 0x4F, 0xF0, ++0x01, 0x0A, 0x33, 0x68, 0xDB, 0x78, 0xFB, 0xB9, 0x98, 0xF8, 0x00, 0x30, 0x13, 0xB3, 0x18, 0xF0, 0x71, 0xFE, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0xA0, 0x2B, 0x68, 0x3A, 0x68, 0x01, 0x33, 0x2B, 0x60, ++0xBA, 0xB1, 0x00, 0x2B, 0xE9, 0xD0, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x2B, 0x60, 0x00, 0x2B, 0xE3, 0xD1, 0x00, 0x2A, ++0xE1, 0xD0, 0x62, 0xB6, 0x33, 0x68, 0xDB, 0x78, 0x00, 0x2B, 0xDF, 0xD0, 0xFF, 0xF7, 0x2C, 0xFD, 0x98, 0xF8, 0x00, 0x30, ++0x00, 0x2B, 0xDC, 0xD1, 0x16, 0xF0, 0xF8, 0xFA, 0xD9, 0xE7, 0xD4, 0xF8, 0x7C, 0x32, 0x98, 0x47, 0x33, 0x68, 0xDB, 0x78, ++0x00, 0x2B, 0x37, 0xD1, 0xDB, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x01, 0x2B, 0x17, 0xD0, 0xBF, 0xF3, 0x4F, 0x8F, 0x30, 0xBF, ++0xBF, 0xF3, 0x6F, 0x8F, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0xD4, 0xF8, 0x78, 0x32, 0x98, 0x47, 0x00, 0x28, ++0xF1, 0xD0, 0x33, 0x68, 0xDB, 0x78, 0x23, 0xBB, 0xD4, 0xF8, 0x84, 0x32, 0x98, 0x47, 0x2B, 0x68, 0x00, 0x2B, 0xB0, 0xD0, ++0xC5, 0xE7, 0x1D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xE3, 0xD0, 0x1C, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x17, 0xD0, ++0x01, 0x2B, 0x05, 0xD0, 0x00, 0x2B, 0xDA, 0xD1, 0x18, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xD6, 0xD0, 0x17, 0x4B, 0x5B, 0x78, ++0x00, 0x2B, 0xD2, 0xD0, 0x16, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x53, 0x13, 0x60, 0xCC, 0xE7, 0xFF, 0xF7, 0xEA, 0xFC, ++0xC4, 0xE7, 0xFF, 0xF7, 0xEF, 0xFC, 0xD7, 0xE7, 0xFB, 0xF7, 0x32, 0xFE, 0x00, 0x28, 0xEF, 0xD1, 0x0B, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0xDF, 0xE7, 0x10, 0x20, 0xFF, 0xF7, 0xB1, 0xFC, 0x72, 0xE7, 0x34, 0x36, 0x17, 0x00, 0xDC, 0xD1, 0x15, 0x00, ++0x00, 0xD2, 0x15, 0x00, 0x1C, 0x8D, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x3D, 0x61, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x3C, 0x61, 0x17, 0x00, 0x70, 0x28, 0x17, 0x00, 0x00, 0x60, 0x50, 0x40, ++0x3C, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x72, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x71, 0x4C, 0x72, 0x4A, 0x23, 0x68, 0x72, 0x49, ++0x72, 0x4D, 0x01, 0x33, 0x4F, 0xF4, 0x80, 0x60, 0x23, 0x60, 0x17, 0xF0, 0xF9, 0xFC, 0x4F, 0xF0, 0x00, 0x40, 0x16, 0xF0, ++0x4D, 0xFA, 0xD5, 0xF8, 0xEC, 0x30, 0x98, 0x47, 0x6C, 0x4B, 0x6D, 0x4A, 0x19, 0x68, 0x21, 0xF0, 0x7F, 0x41, 0x19, 0x60, ++0x19, 0x68, 0x41, 0xF0, 0x10, 0x01, 0x19, 0x60, 0x11, 0x69, 0x64, 0x31, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, ++0x66, 0x4E, 0xD5, 0xF8, 0x10, 0x24, 0x33, 0x68, 0x40, 0xF2, 0x11, 0x17, 0x3B, 0x43, 0x33, 0x60, 0x90, 0x47, 0x60, 0x49, ++0x62, 0x4A, 0x0B, 0x68, 0xDF, 0xF8, 0xAC, 0xC1, 0x23, 0xF0, 0x10, 0x03, 0x0B, 0x60, 0x33, 0x68, 0x23, 0xF4, 0x88, 0x73, ++0x23, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x0B, 0x23, 0x10, 0x68, 0x13, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0xDB, 0x06, 0x18, 0xD5, ++0x59, 0x4B, 0x40, 0xF2, 0x01, 0x2C, 0x19, 0x68, 0xC3, 0xF8, 0x00, 0xC0, 0x19, 0x60, 0x33, 0x68, 0xA2, 0xF5, 0x7C, 0x72, ++0x1F, 0x43, 0x37, 0x60, 0x11, 0x68, 0x02, 0x31, 0x13, 0x68, 0x5B, 0x1A, 0x00, 0x2B, 0xFB, 0xDB, 0x4E, 0x4A, 0x13, 0x68, ++0x23, 0xF4, 0x88, 0x73, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x4C, 0x4B, 0x18, 0x60, 0x0A, 0xF0, 0xBD, 0xFF, 0x00, 0x20, ++0x16, 0xF0, 0x8E, 0xF8, 0x00, 0x28, 0x6C, 0xD0, 0x49, 0x4E, 0x09, 0xF0, 0xA1, 0xFB, 0xB3, 0x79, 0x00, 0x2B, 0x4F, 0xD0, ++0x47, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x66, 0xD0, 0x33, 0x78, 0x00, 0x2B, 0x47, 0xD0, 0x44, 0x4B, 0x77, 0x79, ++0x1A, 0x68, 0x96, 0xF9, 0x07, 0x30, 0x96, 0xF9, 0x04, 0xE0, 0xDF, 0xF8, 0x20, 0xC1, 0x41, 0x48, 0xDC, 0xF8, 0x00, 0x10, ++0xD5, 0xF8, 0xE0, 0x81, 0x37, 0x4D, 0x02, 0xF0, 0x0F, 0x02, 0x17, 0x44, 0x7F, 0xB2, 0x3B, 0x44, 0x73, 0x45, 0xA8, 0xBF, ++0x73, 0x46, 0x5F, 0xFA, 0x83, 0xFE, 0x21, 0xF0, 0xFF, 0x01, 0x41, 0xEA, 0x0E, 0x01, 0xCC, 0xF8, 0x00, 0x10, 0x02, 0x68, ++0x22, 0xF0, 0xFF, 0x02, 0x42, 0xEA, 0x0E, 0x02, 0x02, 0x60, 0xDC, 0xF8, 0x00, 0x10, 0xDA, 0x1E, 0x5F, 0xFA, 0x82, 0xFE, ++0x21, 0xF4, 0x7F, 0x21, 0x41, 0xEA, 0x0E, 0x31, 0xCC, 0xF8, 0x00, 0x10, 0x02, 0x68, 0xB6, 0xF8, 0x08, 0xC0, 0x22, 0xF4, ++0x7F, 0x22, 0x42, 0xEA, 0x0E, 0x32, 0x02, 0x60, 0x2A, 0x69, 0x2A, 0x48, 0x5D, 0xB2, 0x4E, 0xF6, 0x60, 0x21, 0x01, 0xFB, ++0x0C, 0x21, 0xF5, 0x71, 0xC0, 0x47, 0x00, 0x23, 0x26, 0x48, 0xB3, 0x71, 0x29, 0x46, 0x3A, 0x46, 0x17, 0xF0, 0xFC, 0xFB, ++0x24, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x17, 0xF0, 0x47, 0xFC, 0x08, 0xF0, 0x85, 0xFE, 0x18, 0xB1, 0x4F, 0xF4, 0x80, 0x10, ++0x16, 0xF0, 0x74, 0xF9, 0x23, 0x68, 0x33, 0xB1, 0x0D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF0, 0x80, 0x60, 0x16, 0xF0, 0x89, 0xF9, 0x8D, 0xE7, 0x17, 0x4B, 0x1B, 0x68, ++0x00, 0x22, 0x1A, 0x60, 0xF8, 0xF7, 0x8C, 0xFA, 0x33, 0x78, 0x00, 0x2B, 0xDA, 0xD0, 0xB3, 0x79, 0x00, 0x2B, 0x8F, 0xD1, ++0xD6, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x30, 0x8E, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x04, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x18, 0x00, 0x34, 0x40, 0x10, 0x05, 0x32, 0x40, ++0x00, 0x10, 0x34, 0x40, 0x80, 0x35, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x01, 0x32, 0x40, 0xD4, 0xB3, 0x33, 0x40, ++0x8C, 0x35, 0x17, 0x00, 0x30, 0x8D, 0x15, 0x00, 0x40, 0x8D, 0x15, 0x00, 0x00, 0x38, 0x18, 0x00, 0x0C, 0x05, 0x32, 0x40, ++0xAC, 0xB3, 0x33, 0x40, 0x22, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x20, 0x4B, ++0xD3, 0xF8, 0x04, 0x31, 0x1A, 0x03, 0x10, 0xB5, 0x16, 0xD4, 0x00, 0x22, 0x93, 0x00, 0x03, 0xF1, 0x60, 0x43, 0x03, 0xF5, ++0x61, 0x43, 0x01, 0x2A, 0xD3, 0xF8, 0x00, 0x01, 0x1B, 0x68, 0x00, 0xEA, 0x03, 0x00, 0x04, 0xD0, 0x30, 0xB9, 0x02, 0x2A, ++0x05, 0xD0, 0x01, 0x32, 0xEE, 0xE7, 0x30, 0xF4, 0x00, 0x23, 0xFA, 0xD0, 0x01, 0x20, 0x10, 0xBD, 0x12, 0x4B, 0x1C, 0x68, ++0x41, 0xF6, 0x33, 0x70, 0x20, 0x40, 0xF7, 0xD1, 0x63, 0x00, 0x0F, 0xD4, 0x00, 0x2C, 0x07, 0xDA, 0x0E, 0x4B, 0xD3, 0xF8, ++0x68, 0x34, 0x98, 0x47, 0x0D, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x08, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0xC3, 0xF8, ++0x84, 0x21, 0xD0, 0xE7, 0x07, 0x4B, 0xD3, 0xF8, 0x78, 0x34, 0x98, 0x47, 0x06, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, ++0xE6, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, 0x1C, 0x41, 0x04, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x38, 0xB5, 0x3F, 0x4C, 0x3F, 0x4D, 0x23, 0x68, 0x3F, 0x49, 0x03, 0xF0, 0x0F, 0x03, 0x02, 0x20, ++0x2B, 0x70, 0x17, 0xF0, 0x9F, 0xFB, 0x23, 0x68, 0x18, 0x07, 0x40, 0xD0, 0x3B, 0x49, 0x3C, 0x4A, 0x0B, 0x68, 0x00, 0x20, ++0x23, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x20, 0x60, 0x13, 0x68, 0x59, 0x07, 0xFC, 0xD5, 0x38, 0x4B, 0x35, 0x49, 0x38, 0x4A, ++0x04, 0x20, 0x18, 0x60, 0x0B, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x63, 0x13, 0x60, ++0x33, 0x4B, 0x1B, 0x78, 0x01, 0x22, 0x6A, 0x70, 0x9B, 0xB1, 0x32, 0x49, 0x32, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0x00, 0x13, ++0x0B, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x2F, 0x4B, 0x19, 0x68, 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, ++0x01, 0x20, 0x41, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x10, 0x60, 0x20, 0x4B, 0x2A, 0x4A, 0x2B, 0x49, 0x20, 0x20, 0x18, 0x60, ++0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x26, 0xD0, 0x01, 0x2B, 0x06, 0xD0, ++0x38, 0xBD, 0x1E, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x63, 0x13, 0x60, 0xD0, 0xE7, 0x22, 0x4A, 0x13, 0x68, 0x5B, 0x03, ++0xFC, 0xD5, 0x21, 0x4A, 0x11, 0x69, 0x1C, 0x31, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x1E, 0x49, 0x1F, 0x4A, ++0x0B, 0x68, 0x43, 0xF4, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x6D, 0x43, 0xF4, 0x00, 0x43, 0x13, 0x65, 0xD3, 0x6D, 0x23, 0xF0, ++0x03, 0x03, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xF0, 0x01, 0x03, 0xD3, 0x65, 0x38, 0xBD, 0x17, 0x4B, 0x1A, 0x68, 0x42, 0xF0, ++0x01, 0x02, 0x1A, 0x60, 0x1B, 0x68, 0x5A, 0x07, 0xD2, 0xD5, 0x14, 0x4B, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x38, 0xBD, ++0x38, 0x00, 0x32, 0x40, 0x70, 0x28, 0x17, 0x00, 0x50, 0x8D, 0x15, 0x00, 0x74, 0x80, 0x32, 0x40, 0x6C, 0x80, 0x32, 0x40, ++0x70, 0x80, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, 0x3D, 0x61, 0x17, 0x00, 0x58, 0x40, 0x34, 0x40, 0x40, 0x42, 0x04, 0x40, ++0x18, 0x00, 0x58, 0x40, 0x10, 0x00, 0x58, 0x40, 0x78, 0x36, 0x17, 0x00, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x14, 0x00, 0x24, 0x40, 0x00, 0x60, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x00, 0x41, 0x04, 0x40, 0x00, 0x28, 0x00, 0xF0, ++0xE7, 0x80, 0x2D, 0xE9, 0xF8, 0x4F, 0x90, 0xF8, 0x64, 0x30, 0x04, 0x46, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x8F, 0x83, 0x4B, ++0x83, 0x4A, 0x84, 0x4F, 0xDF, 0xF8, 0x2C, 0x92, 0xDF, 0xF8, 0x64, 0x82, 0x82, 0x4E, 0x83, 0x48, 0x0D, 0x46, 0x83, 0x49, ++0x4F, 0xF0, 0x02, 0x0B, 0xD1, 0xF8, 0x70, 0xC4, 0xC3, 0xF8, 0x80, 0xB1, 0x92, 0x68, 0x80, 0x49, 0xC2, 0xF8, 0x44, 0xC0, ++0x01, 0x22, 0xC3, 0xF8, 0x00, 0xB0, 0x3A, 0x70, 0xD9, 0xF8, 0x10, 0x20, 0x0B, 0x68, 0x7A, 0x60, 0x23, 0xF0, 0x02, 0x03, ++0x0B, 0x60, 0xD8, 0xF8, 0x00, 0x10, 0xB6, 0xF8, 0xB2, 0xC0, 0x8B, 0x8F, 0x01, 0x68, 0x63, 0x44, 0xB3, 0xEB, 0x41, 0x1F, ++0x4F, 0xEA, 0x41, 0x1A, 0xD1, 0xD2, 0x74, 0x49, 0x58, 0x46, 0x17, 0xF0, 0xC9, 0xFA, 0xD9, 0xF8, 0x10, 0x20, 0xFB, 0x68, ++0x9B, 0x1A, 0x00, 0x2B, 0x80, 0xF2, 0xB6, 0x80, 0xB4, 0xF8, 0x68, 0x20, 0x6E, 0x4B, 0xA8, 0x68, 0x41, 0xF2, 0x13, 0x31, ++0x01, 0x2A, 0x5C, 0x5C, 0x40, 0xF2, 0x9F, 0x80, 0x01, 0x3A, 0x00, 0xFB, 0x02, 0xAA, 0x41, 0xF2, 0x13, 0x31, 0x52, 0x46, ++0x5B, 0x5C, 0x68, 0x49, 0x02, 0x20, 0x17, 0xF0, 0xAD, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB6, 0xF8, 0xB2, 0x00, 0x9A, 0x8F, ++0x60, 0x49, 0x64, 0x4B, 0xDF, 0xF8, 0xA8, 0xC1, 0x1C, 0x69, 0x0B, 0x68, 0x02, 0x44, 0xAA, 0xEB, 0x02, 0x02, 0x22, 0xF0, ++0x03, 0x05, 0x03, 0xF0, 0x03, 0x03, 0x2B, 0x43, 0x5E, 0x4D, 0x0B, 0x60, 0x2B, 0x68, 0xBA, 0x60, 0x43, 0xF0, 0x01, 0x03, ++0x2B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0xDC, 0xF8, 0x00, 0x10, 0xC3, 0xF3, 0x09, 0x03, 0x21, 0xF4, 0x7F, 0x71, 0x43, 0xF0, ++0x01, 0x03, 0x21, 0xF0, 0x03, 0x01, 0x0B, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0x2B, 0x68, 0x22, 0x44, 0x5B, 0x07, 0xFA, 0x60, ++0x03, 0xD5, 0x52, 0x4B, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x51, 0x49, 0x51, 0x4A, 0x0B, 0x68, 0x43, 0xF0, 0x08, 0x03, ++0x0B, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4E, 0x4C, 0x45, 0x49, 0x23, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x23, 0x60, ++0x01, 0x23, 0x13, 0x60, 0x0B, 0x68, 0x45, 0x4A, 0x43, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x11, 0x69, 0x01, 0xF5, 0x96, 0x71, ++0x13, 0x69, 0x5B, 0x1A, 0x00, 0x2B, 0xFB, 0xDB, 0x45, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x7F, 0xF4, 0x5D, 0xAF, ++0x43, 0x49, 0x44, 0x4C, 0x4B, 0x6A, 0x24, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xDF, 0x03, 0x4B, 0x62, 0x4B, 0x6A, ++0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0x5F, 0x43, 0x4B, 0x62, 0xB4, 0xB1, 0x3D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x3F, 0xDB, 0xE3, 0x68, 0x62, 0x68, 0x3A, 0x49, 0x02, 0x20, 0x17, 0xF0, 0x3C, 0xFA, 0xB6, 0xF8, 0xB2, 0x10, ++0xE2, 0x68, 0x2D, 0x4B, 0x52, 0x1A, 0x4F, 0xF4, 0x80, 0x20, 0x04, 0x21, 0x98, 0x60, 0x1A, 0x63, 0x99, 0x60, 0x34, 0x49, ++0x2F, 0x4A, 0x0B, 0x68, 0x43, 0xF4, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x6D, 0x43, 0xF4, 0x00, 0x43, 0x13, 0x65, 0xD3, 0x6D, ++0x23, 0xF0, 0x03, 0x03, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xF0, 0x01, 0x03, 0xD3, 0x65, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x53, ++0x13, 0x60, 0x1E, 0xE7, 0x70, 0x47, 0x41, 0xF2, 0x14, 0x32, 0x9C, 0x5C, 0x01, 0x2C, 0x7F, 0xF6, 0x5E, 0xAF, 0x5C, 0x5C, ++0xDC, 0xB1, 0x5A, 0x5C, 0x01, 0x3A, 0x00, 0xFB, 0x02, 0xAA, 0x56, 0xE7, 0x14, 0x4A, 0x22, 0x49, 0x41, 0xF2, 0x13, 0x33, ++0x58, 0x46, 0xD3, 0x5C, 0x52, 0x46, 0x17, 0xF0, 0x03, 0xFA, 0x54, 0xE7, 0x12, 0x69, 0xE3, 0x68, 0x9A, 0x1A, 0x10, 0x1A, ++0x00, 0x28, 0xBA, 0xDA, 0x1B, 0x49, 0x1C, 0x48, 0x40, 0xF2, 0x4F, 0x22, 0x17, 0xF0, 0x20, 0xFC, 0xB2, 0xE7, 0x9A, 0x5C, ++0x3A, 0xE7, 0x00, 0xBF, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0xED, 0x00, 0xE0, 0x3C, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0x40, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x84, 0x00, 0x32, 0x40, 0x54, 0x8D, 0x15, 0x00, 0x00, 0x40, 0x1E, 0x00, ++0x70, 0x8D, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x00, 0x41, 0x04, 0x40, 0x10, 0x00, 0x58, 0x40, ++0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x78, 0x36, 0x17, 0x00, 0x00, 0x60, 0x50, 0x40, 0xD0, 0x9C, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0xC8, 0x8D, 0x15, 0x00, 0x14, 0x00, 0x24, 0x40, 0x5C, 0x8D, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x80, 0x8D, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x70, 0xB5, 0x45, 0x4C, 0x21, 0x68, 0x0B, 0x78, 0x73, 0xB9, 0x44, 0x4B, ++0x44, 0x4D, 0x9B, 0x68, 0x01, 0x22, 0x2A, 0x70, 0x00, 0x2B, 0x3E, 0xD1, 0x0A, 0x78, 0x42, 0x49, 0x01, 0x23, 0x02, 0x20, ++0x17, 0xF0, 0xAC, 0xF9, 0x01, 0x23, 0x2B, 0x70, 0x3F, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x40, 0xD0, 0x02, 0x2B, ++0x28, 0xD0, 0x11, 0xF0, 0x8F, 0xFD, 0x28, 0xB3, 0x3B, 0x4B, 0xD3, 0xF8, 0xF8, 0x31, 0x0B, 0xBB, 0x3A, 0x4B, 0x3B, 0x4D, ++0x1B, 0x68, 0x95, 0xF8, 0x24, 0x20, 0xC3, 0xF3, 0x40, 0x63, 0x13, 0x43, 0x18, 0xD0, 0x6B, 0x7F, 0xB3, 0xB9, 0x37, 0x4E, ++0xD6, 0xF8, 0xF4, 0x30, 0x98, 0x47, 0x88, 0xB1, 0xF8, 0xF7, 0x7E, 0xFB, 0x34, 0x4A, 0xC0, 0xB2, 0x10, 0x70, 0x00, 0x28, ++0x35, 0xD0, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD8, 0xD6, 0xF8, 0xB4, 0x34, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, ++0x02, 0x2B, 0x22, 0xD0, 0x70, 0xBD, 0x93, 0xF8, 0x64, 0x20, 0x42, 0xB9, 0x1B, 0x68, 0x00, 0x2B, 0xC0, 0xD0, 0x93, 0xF8, ++0x62, 0x20, 0x00, 0x2A, 0xF5, 0xD0, 0x02, 0x2A, 0xF6, 0xD1, 0x0A, 0x78, 0x1F, 0x49, 0x00, 0x23, 0x02, 0x20, 0x17, 0xF0, ++0x67, 0xF9, 0x00, 0x23, 0x2B, 0x70, 0x70, 0xBD, 0x23, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x15, 0xD0, 0xFB, 0xF7, 0x5A, 0xFA, ++0x00, 0x28, 0xE1, 0xD0, 0x1E, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xB4, 0xD0, 0x70, 0xBD, 0x28, 0x6A, 0xD6, 0xF8, 0xB8, 0x34, ++0xD0, 0xF8, 0xE4, 0x10, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x19, 0x49, 0x02, 0x20, 0x17, 0xF0, 0x4B, 0xF9, 0xC4, 0xE7, ++0xF8, 0xF7, 0x3C, 0xFB, 0x13, 0x4B, 0x18, 0x70, 0xFB, 0xF7, 0x40, 0xFA, 0x18, 0xB1, 0x10, 0x4B, 0xD3, 0xF8, 0xB4, 0x34, ++0x98, 0x47, 0x12, 0x4A, 0x13, 0x68, 0x5B, 0x03, 0xFC, 0xD5, 0x11, 0x4A, 0x11, 0x69, 0x1C, 0x31, 0x13, 0x69, 0xCB, 0x1A, ++0x00, 0x2B, 0xFB, 0xDA, 0x70, 0xBD, 0x00, 0xBF, 0x74, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x3C, 0x61, 0x17, 0x00, ++0xD8, 0x8D, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x3D, 0x61, 0x17, 0x00, 0x9C, 0x4E, 0x17, 0x00, 0xD4, 0x8D, 0x15, 0x00, 0x20, 0x10, 0x04, 0x40, ++0x00, 0x10, 0x50, 0x40, 0x38, 0xB5, 0x43, 0x4D, 0x6B, 0x78, 0x03, 0xB9, 0x38, 0xBD, 0x42, 0x48, 0x42, 0x49, 0x03, 0x68, ++0x42, 0x4A, 0x23, 0xF0, 0x10, 0x03, 0x03, 0x60, 0x4B, 0x6F, 0x43, 0xF0, 0x10, 0x03, 0x4B, 0x67, 0x13, 0x68, 0x23, 0xF0, ++0x00, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x3C, 0x4C, 0x3C, 0x49, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x43, ++0x23, 0x60, 0x02, 0x20, 0x17, 0xF0, 0xF6, 0xF8, 0x00, 0x23, 0x22, 0x46, 0x6B, 0x70, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD5, ++0x36, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x3C, 0xDB, 0x31, 0x4B, 0x34, 0x4A, 0x19, 0x68, 0x21, 0xF0, ++0x80, 0x41, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x2F, 0x4B, ++0x2F, 0x48, 0x19, 0x68, 0x2F, 0x4C, 0x41, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, 0x01, 0x25, 0x21, 0xF0, 0x02, 0x01, ++0x19, 0x60, 0x15, 0x60, 0x03, 0x68, 0x43, 0xF4, 0x00, 0x13, 0x03, 0x60, 0x23, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x2E, 0xD0, ++0x01, 0x2B, 0x26, 0xD0, 0x26, 0x4B, 0x1B, 0x78, 0x53, 0xB1, 0x1D, 0x4A, 0x25, 0x49, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x73, ++0x13, 0x60, 0x02, 0x20, 0xBD, 0xE8, 0x38, 0x40, 0x17, 0xF0, 0xB8, 0xB8, 0x16, 0x4A, 0x20, 0x49, 0x53, 0x6F, 0x23, 0xF0, ++0x10, 0x03, 0x53, 0x67, 0x02, 0x20, 0xBD, 0xE8, 0x38, 0x40, 0x17, 0xF0, 0xAD, 0xB8, 0x1C, 0x4B, 0x2A, 0x78, 0x1B, 0x68, ++0x03, 0xF0, 0x0F, 0x03, 0x9A, 0x42, 0xBB, 0xD0, 0x19, 0x49, 0x1A, 0x48, 0x4F, 0xF4, 0x3A, 0x72, 0x17, 0xF0, 0xCA, 0xFA, ++0xB4, 0xE7, 0x18, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x43, 0x13, 0x60, 0xD2, 0xE7, 0x16, 0x4A, 0x13, 0x68, 0x23, 0xF0, ++0x01, 0x03, 0x13, 0x60, 0x0D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xCC, 0xD1, 0xD6, 0xE7, 0x00, 0xBF, 0x70, 0x28, 0x17, 0x00, ++0x10, 0x00, 0x58, 0x40, 0x00, 0x00, 0x50, 0x40, 0xE0, 0x50, 0x34, 0x40, 0x48, 0x80, 0x32, 0x40, 0xEC, 0x8D, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x58, 0x40, 0x34, 0x40, 0x78, 0x36, 0x17, 0x00, ++0x4C, 0x36, 0x17, 0x00, 0x28, 0x8E, 0x15, 0x00, 0x38, 0x00, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x8D, 0x15, 0x00, ++0x14, 0x00, 0x24, 0x40, 0x84, 0x40, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x47, 0x1F, 0x48, 0x20, 0x4D, 0x15, 0xF0, 0x36, 0xFE, ++0x1F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0x1D, 0x4E, 0x28, 0x68, 0xDF, 0xF8, 0x7C, 0x90, ++0xDF, 0xF8, 0x60, 0x80, 0xD9, 0xF8, 0x00, 0x30, 0x1A, 0x89, 0x54, 0x24, 0x02, 0xFB, 0x04, 0x42, 0x00, 0x21, 0xF2, 0xF7, ++0x91, 0xFD, 0x4F, 0xF0, 0x00, 0x0A, 0x58, 0x27, 0x29, 0x68, 0x33, 0x68, 0x1F, 0xFA, 0x8A, 0xF2, 0x04, 0xFB, 0x02, 0x11, ++0x07, 0xFB, 0x02, 0x33, 0xCB, 0x64, 0x40, 0x46, 0x15, 0xF0, 0x16, 0xFE, 0xD9, 0xF8, 0x00, 0x30, 0x0A, 0xF1, 0x01, 0x0A, ++0x1A, 0x89, 0x1F, 0xFA, 0x8A, 0xF3, 0x9A, 0x42, 0xEA, 0xD2, 0xBD, 0xE8, 0xF0, 0x87, 0x28, 0x68, 0x08, 0x4E, 0x10, 0xB1, ++0x33, 0x68, 0x00, 0x2B, 0xD2, 0xD1, 0x07, 0x48, 0x07, 0x49, 0x5B, 0x22, 0x17, 0xF0, 0x54, 0xFA, 0x28, 0x68, 0xCB, 0xE7, ++0x20, 0x58, 0x17, 0x00, 0x40, 0x61, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x14, 0x63, 0x18, 0x00, 0x40, 0x8E, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0x0D, 0x49, 0x00, 0xEB, 0xC0, 0x03, 0x10, 0xB4, 0x9C, 0x00, 0x00, 0x22, ++0x01, 0xEB, 0x83, 0x03, 0x16, 0x30, 0x0A, 0x51, 0x01, 0xEB, 0xC0, 0x00, 0x4F, 0xF4, 0x55, 0x64, 0x4F, 0xF0, 0xFF, 0x31, ++0xC3, 0xE9, 0x02, 0x41, 0xC0, 0xE9, 0x01, 0x22, 0x5D, 0xF8, 0x04, 0x4B, 0x5A, 0x60, 0x83, 0xF8, 0x20, 0x20, 0x5A, 0x61, ++0x19, 0x61, 0x70, 0x47, 0x44, 0x61, 0x17, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x80, 0x6C, 0x18, 0xB1, 0xF9, 0xF7, 0xCE, 0xFE, ++0x00, 0x23, 0xA3, 0x64, 0x10, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, 0x38, 0x4C, 0xDF, 0xF8, 0xF0, 0x80, 0x38, 0x4F, ++0x38, 0x4D, 0x04, 0xF5, 0x20, 0x76, 0xC4, 0xF8, 0x00, 0x80, 0xF3, 0xF7, 0x0F, 0xFE, 0x80, 0x03, 0x60, 0x60, 0xF3, 0xF7, ++0x0B, 0xFE, 0x01, 0x23, 0x01, 0x30, 0x03, 0xFA, 0x00, 0xF0, 0x01, 0x38, 0x00, 0x23, 0xC4, 0xE9, 0x02, 0x03, 0xC4, 0xE9, ++0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x27, 0x61, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, ++0x63, 0x62, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0xA3, 0x62, 0x2B, 0x68, 0x2A, 0x68, ++0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0xE3, 0x62, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, ++0x13, 0x43, 0x4F, 0xF4, 0x08, 0x51, 0x4F, 0xF4, 0x7C, 0x12, 0xA2, 0x63, 0xC4, 0xE9, 0x0C, 0x31, 0x40, 0x34, 0xB4, 0x42, ++0xC5, 0xD1, 0x1B, 0x4C, 0x1B, 0x4F, 0x18, 0x4E, 0xDF, 0xF8, 0x60, 0x80, 0x04, 0xF5, 0x80, 0x75, 0x27, 0x60, 0xF3, 0xF7, ++0xCF, 0xFD, 0x80, 0x03, 0x60, 0x60, 0xF3, 0xF7, 0xCB, 0xFD, 0x01, 0x23, 0x01, 0x30, 0x03, 0xFA, 0x00, 0xF0, 0x01, 0x38, ++0x00, 0x23, 0xC4, 0xE9, 0x02, 0x03, 0xC4, 0xE9, 0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x26, 0x61, 0xD8, 0xF8, 0x00, 0x20, ++0xD8, 0xF8, 0x00, 0x10, 0xA3, 0x62, 0x12, 0x02, 0xC9, 0xB2, 0x92, 0xB2, 0x0A, 0x43, 0x4F, 0xF4, 0x7C, 0x11, 0x62, 0x62, ++0xC4, 0xE9, 0x0B, 0x33, 0xC4, 0xE9, 0x0D, 0x31, 0x40, 0x34, 0xAC, 0x42, 0xD8, 0xD1, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, ++0x04, 0x39, 0x18, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0xA0, 0x00, 0x32, 0x40, 0x04, 0x38, 0x18, 0x00, 0x1E, 0xAB, 0xDC, 0xBA, ++0xF0, 0xB5, 0x16, 0x4C, 0x24, 0x68, 0x24, 0x78, 0x1D, 0x46, 0xE3, 0x07, 0x87, 0xB0, 0x16, 0x46, 0x06, 0xD5, 0x50, 0x19, ++0x00, 0x21, 0x08, 0x22, 0xF2, 0xF7, 0xA8, 0xFC, 0x07, 0xB0, 0xF0, 0xBD, 0xC3, 0x7E, 0x00, 0x93, 0x02, 0xAC, 0x07, 0x46, ++0x07, 0xF1, 0x12, 0x03, 0x20, 0x46, 0x07, 0xF1, 0x0C, 0x02, 0x1A, 0xF0, 0xE7, 0xFF, 0x2A, 0x46, 0x31, 0x46, 0x20, 0x46, ++0x1B, 0xF0, 0x08, 0xF8, 0x20, 0x46, 0x1B, 0xF0, 0xA3, 0xF8, 0x35, 0x44, 0x21, 0x46, 0x04, 0xAA, 0x60, 0x1A, 0x14, 0xF8, ++0x01, 0x3B, 0x43, 0x55, 0x94, 0x42, 0xF9, 0xD1, 0x07, 0xB0, 0xF0, 0xBD, 0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x83, 0x6C, 0x90, 0xF8, 0x42, 0xA0, 0x90, 0xF8, 0x33, 0x40, 0x90, 0xF8, 0x35, 0x20, 0x87, 0x88, 0x90, 0xF8, 0x32, 0x80, ++0xD3, 0xF8, 0x24, 0xC0, 0xC6, 0x6C, 0x93, 0xF8, 0x20, 0xE0, 0xA3, 0xEB, 0x0A, 0x05, 0xA8, 0x35, 0x22, 0x44, 0x01, 0x3F, ++0xAA, 0xEB, 0x04, 0x04, 0x3A, 0x44, 0x08, 0xEB, 0x05, 0x09, 0x2C, 0xF0, 0x02, 0x07, 0x04, 0xEB, 0x09, 0x0B, 0x5F, 0x62, ++0x54, 0x19, 0x03, 0xF1, 0x0C, 0x0A, 0xB8, 0xF1, 0x00, 0x0F, 0x03, 0xD0, 0x09, 0xF1, 0xFF, 0x32, 0xC6, 0xE9, 0x09, 0x52, ++0xF2, 0x6C, 0xC3, 0xF8, 0x14, 0xB0, 0x00, 0x25, 0x42, 0xF4, 0x80, 0x72, 0x1C, 0xF0, 0x01, 0x0F, 0x9C, 0x61, 0x1D, 0x61, ++0xC6, 0xF8, 0x20, 0xA0, 0xDD, 0x61, 0xF2, 0x64, 0x16, 0xD1, 0x40, 0x6A, 0x00, 0xF4, 0x60, 0x14, 0xB4, 0xF5, 0x60, 0x1F, ++0x01, 0xD0, 0x80, 0x02, 0x0E, 0xD4, 0x09, 0x48, 0x71, 0x44, 0x01, 0xEB, 0xC1, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x47, 0xF0, ++0x01, 0x07, 0x91, 0xF8, 0x20, 0x00, 0x5F, 0x62, 0x01, 0x30, 0x81, 0xF8, 0x20, 0x00, 0xF2, 0x64, 0x00, 0x22, 0x1A, 0x61, ++0xBD, 0xE8, 0xF0, 0x8F, 0x44, 0x61, 0x17, 0x00, 0x0A, 0x88, 0x03, 0x7F, 0x0A, 0x49, 0x12, 0xF4, 0x00, 0x5F, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x03, 0x12, 0x4F, 0xF4, 0xA4, 0x60, 0x92, 0xF8, 0xDA, 0x20, 0x00, 0xFB, 0x03, 0x13, 0x14, 0xBF, ++0x42, 0xF0, 0x02, 0x02, 0x02, 0xF0, 0xFD, 0x02, 0x83, 0xF8, 0xDA, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x43, 0x6A, 0x2D, 0xE9, 0xF0, 0x47, 0x91, 0x46, 0x9A, 0x02, 0xD0, 0xF8, 0x48, 0x80, 0x06, 0x46, 0x0F, 0x46, 0x29, 0xD5, ++0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x24, 0xD0, 0x50, 0x4C, 0x88, 0xF8, 0x20, 0x90, 0xD4, 0xF8, 0x80, 0x33, ++0x39, 0x46, 0x30, 0x46, 0x98, 0x47, 0x31, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x99, 0x42, 0x68, 0xD0, 0x4A, 0x4B, 0xB1, 0x6C, ++0x93, 0xF8, 0x05, 0x31, 0x00, 0x2B, 0x59, 0xD1, 0xB3, 0x68, 0x00, 0x2B, 0x49, 0xDB, 0x4B, 0x6A, 0x46, 0x4A, 0xCA, 0x60, ++0x23, 0xF0, 0x10, 0x03, 0x4B, 0x62, 0x30, 0x46, 0xD4, 0xF8, 0x04, 0x34, 0x8E, 0x60, 0x3A, 0x46, 0x98, 0x47, 0x00, 0x20, ++0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0x2C, 0xA0, 0x08, 0xF1, 0x24, 0x04, 0x0A, 0xF1, 0x40, 0x00, 0x53, 0x46, 0x53, 0xF8, ++0x04, 0x5B, 0x44, 0xF8, 0x04, 0x5F, 0x83, 0x42, 0xF9, 0xD1, 0xF3, 0x8B, 0x9D, 0x04, 0xCA, 0xD5, 0x38, 0x4B, 0x39, 0x49, ++0x1A, 0x68, 0x73, 0x7F, 0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, ++0x4C, 0x41, 0x38, 0xDB, 0x41, 0x46, 0xDA, 0xF8, 0x14, 0x20, 0xD4, 0xF8, 0x9C, 0x30, 0xC8, 0xF8, 0x40, 0x20, 0xDA, 0xF8, ++0x24, 0x20, 0xC8, 0xF8, 0x50, 0x20, 0xC3, 0xF3, 0xC2, 0x22, 0x05, 0x2A, 0xC8, 0xF8, 0x3C, 0x30, 0x31, 0xD0, 0xDA, 0xF8, ++0x3C, 0x30, 0x5C, 0x07, 0x5E, 0xBF, 0xD8, 0xF8, 0x2C, 0x30, 0x23, 0xF4, 0xC0, 0x73, 0xC8, 0xF8, 0x2C, 0x30, 0x88, 0x46, ++0x9F, 0xE7, 0x32, 0x8B, 0x33, 0x65, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0xAF, 0xD1, 0x8B, 0x6B, 0x23, 0xF4, 0x7F, 0x43, ++0x43, 0xF4, 0x60, 0x63, 0x8B, 0x63, 0xA8, 0xE7, 0xF2, 0x8B, 0x10, 0x07, 0xA5, 0xD4, 0xB2, 0x68, 0x52, 0x00, 0x58, 0xBF, ++0x81, 0xF8, 0x39, 0x30, 0x9F, 0xE7, 0xF3, 0x6C, 0x19, 0x48, 0xDA, 0x6A, 0x16, 0xF0, 0xFA, 0xFD, 0x90, 0xE7, 0x00, 0x2C, ++0xC4, 0xD1, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0x17, 0xF0, 0x6B, 0xF8, 0xB1, 0x6C, 0xBD, 0xE7, 0x03, 0xF4, ++0xC0, 0x63, 0xD8, 0xF8, 0x4C, 0x20, 0x94, 0xF8, 0xA1, 0x00, 0xB3, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x34, ++0x4F, 0xF4, 0x00, 0x34, 0x22, 0xF4, 0x40, 0x33, 0x23, 0x43, 0x20, 0xB1, 0x43, 0xF4, 0x80, 0x23, 0xC8, 0xF8, 0x4C, 0x30, ++0xB7, 0xE7, 0x23, 0xF4, 0x80, 0x23, 0xC8, 0xF8, 0x4C, 0x30, 0xB2, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xDE, 0xFA, 0xFE, 0xCA, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x78, 0x8E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x43, 0x6A, 0x85, 0x6C, 0x13, 0xF4, 0x00, 0x18, 0x83, 0xB0, 0x04, 0x46, ++0x05, 0xF1, 0x28, 0x07, 0x08, 0xD0, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x00, 0xF0, 0x93, 0x80, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0xC3, 0x8B, 0xC6, 0x6C, 0x1A, 0x07, 0x38, 0xD5, 0xDF, 0xF8, 0x58, 0x92, 0xD9, 0xF8, 0x00, 0x20, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xCF, 0x80, 0x71, 0x6A, 0x09, 0xB9, 0x32, 0x6A, 0x91, 0x68, 0x18, 0x06, ++0x09, 0xD5, 0x94, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xDD, 0x80, 0x94, 0xF8, 0x35, 0x30, 0x00, 0x2B, 0x40, 0xF0, ++0xDF, 0x80, 0xF3, 0x6C, 0x23, 0xF4, 0xF0, 0x03, 0xF3, 0x64, 0x0B, 0x79, 0xB7, 0x63, 0x13, 0xF0, 0x01, 0x0F, 0x08, 0xBF, ++0x4F, 0xF4, 0x00, 0x78, 0x00, 0x23, 0xC6, 0xF8, 0x48, 0x80, 0x33, 0x65, 0xEB, 0x6A, 0x2A, 0x6E, 0x72, 0x63, 0x43, 0xF0, ++0x02, 0x03, 0xEB, 0x62, 0x20, 0x46, 0x06, 0xF0, 0xBB, 0xF8, 0xA2, 0x6C, 0x53, 0x6A, 0x43, 0xF0, 0x10, 0x03, 0x53, 0x62, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x74, 0x4B, 0xD3, 0xF8, 0x28, 0x34, 0x98, 0x47, 0xEB, 0x6D, 0xB3, 0x64, 0x22, 0x7F, ++0x71, 0x49, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x12, 0x92, 0xF8, 0x62, 0x20, 0x5A, 0xBB, 0x6E, 0x49, 0x62, 0x7F, ++0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x52, 0x68, 0x91, 0x06, 0x22, 0xD5, 0xE2, 0x8B, 0x12, 0xF4, 0x00, 0x5F, ++0xE2, 0x6A, 0xD2, 0x6B, 0x14, 0xBF, 0xC2, 0xF3, 0x00, 0x12, 0xC2, 0xF3, 0xC0, 0x02, 0xBA, 0xB9, 0x70, 0x6A, 0x02, 0x88, ++0x91, 0xB2, 0x12, 0x04, 0x12, 0xD5, 0xC1, 0xF3, 0x0E, 0x01, 0x01, 0x80, 0x94, 0xF8, 0x33, 0x10, 0x94, 0xF8, 0x32, 0x20, ++0x04, 0x39, 0x04, 0x3A, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x32, 0x20, 0xD6, 0xE9, 0x0A, 0x21, 0x04, 0x39, 0x04, 0x3A, ++0xC6, 0xE9, 0x0A, 0x21, 0xDF, 0xF8, 0x70, 0x81, 0xB7, 0x63, 0xD8, 0xF8, 0x00, 0x20, 0xE7, 0x6C, 0xB2, 0xF9, 0x00, 0x20, ++0x00, 0x2A, 0x4F, 0xDB, 0x7A, 0x6A, 0x0A, 0xB9, 0x3A, 0x6A, 0x92, 0x68, 0x23, 0xF4, 0xC0, 0x63, 0xB3, 0x64, 0x12, 0x79, ++0xD2, 0x07, 0x5C, 0xBF, 0x43, 0xF4, 0x00, 0x73, 0xB3, 0x64, 0x9B, 0xE7, 0x83, 0x6A, 0x46, 0x6C, 0xC3, 0xF3, 0xC2, 0x22, ++0x05, 0x2A, 0x37, 0x63, 0x15, 0xD1, 0x03, 0xF4, 0xC0, 0x63, 0xEA, 0x6C, 0x90, 0xF8, 0x36, 0x10, 0xB3, 0xF5, 0x80, 0x6F, ++0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x33, 0x4F, 0xF4, 0x00, 0x33, 0x22, 0xF4, 0x40, 0x32, 0x1A, 0x43, 0x89, 0x06, 0x4C, 0xBF, ++0x42, 0xF4, 0x80, 0x22, 0x22, 0xF4, 0x80, 0x22, 0xEA, 0x64, 0x04, 0xF1, 0x28, 0x00, 0x04, 0xF0, 0xDD, 0xF9, 0xD4, 0xF8, ++0x48, 0xC0, 0xA2, 0x6A, 0xB0, 0x88, 0xDC, 0xF8, 0x24, 0x30, 0xE9, 0x6D, 0xEA, 0x63, 0xEA, 0x6A, 0x40, 0xF0, 0x08, 0x04, ++0xB4, 0x80, 0x41, 0xF4, 0xC0, 0x60, 0x2C, 0x6E, 0xF4, 0x62, 0x42, 0xF0, 0x02, 0x02, 0x30, 0x64, 0x43, 0xF0, 0x10, 0x03, ++0xEA, 0x62, 0x39, 0x46, 0x06, 0xF5, 0x82, 0x70, 0x34, 0x22, 0xCC, 0xF8, 0x24, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, ++0x29, 0xF0, 0xFE, 0xB9, 0xA2, 0x6C, 0x00, 0x2A, 0x3C, 0xD0, 0x7A, 0x6A, 0x00, 0x2A, 0xAD, 0xD1, 0x3A, 0x6A, 0x92, 0xB1, ++0xB3, 0x6C, 0xA8, 0xE7, 0x2D, 0xB3, 0x71, 0x6A, 0x00, 0x29, 0x7F, 0xF4, 0x30, 0xAF, 0x32, 0x6A, 0x0A, 0xB1, 0xE3, 0x8B, ++0x2A, 0xE7, 0x23, 0x49, 0x23, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x3F, 0xFF, 0x32, 0x6A, 0xF5, 0xE7, 0x1F, 0x49, ++0x1F, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x37, 0xFF, 0x3A, 0x6A, 0xE4, 0xE7, 0x20, 0x22, 0x20, 0x46, 0x01, 0x91, ++0x22, 0xF0, 0xD8, 0xF8, 0x01, 0x99, 0x20, 0xE7, 0xA2, 0x88, 0x01, 0x91, 0x20, 0x46, 0x23, 0xF0, 0x87, 0xFA, 0x01, 0x99, ++0x19, 0xE7, 0x14, 0x49, 0x15, 0x48, 0x4F, 0xF4, 0xD9, 0x72, 0x16, 0xF0, 0x21, 0xFF, 0x71, 0x6A, 0xA9, 0xB9, 0xD9, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCF, 0xDB, 0xD8, 0xE7, 0x4F, 0xF4, 0xD9, 0x72, 0x0B, 0x49, 0x0D, 0x48, ++0x16, 0xF0, 0x12, 0xFF, 0x7A, 0x6A, 0x42, 0xB9, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB7, 0xDB, ++0xD1, 0xE7, 0xE3, 0x8B, 0xED, 0xE6, 0xB3, 0x6C, 0x60, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x8E, 0x15, 0x00, 0x8C, 0x8E, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x05, 0x28, 0x1C, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x07, 0x0B, 0x0F, 0x13, 0x17, 0x03, 0x12, 0x4B, 0x20, 0x22, 0x1A, 0x60, ++0x70, 0x47, 0x10, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0E, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0C, 0x4B, ++0x08, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0A, 0x4B, 0x10, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x70, 0x47, 0x07, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x04, 0x49, 0x05, 0x48, ++0x4F, 0xF4, 0x77, 0x72, 0x16, 0xF0, 0xCA, 0xBE, 0x80, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x05, 0x28, 0x85, 0xB0, 0x06, 0x46, 0x00, 0xF0, 0xE5, 0x81, 0xAE, 0x4C, ++0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, 0xAB, 0x4B, 0xAC, 0x4F, 0xDF, 0xF8, 0xD4, 0x92, ++0x01, 0x22, 0x19, 0x46, 0xB2, 0x40, 0x71, 0x18, 0x00, 0x92, 0xA3, 0x7E, 0x02, 0x91, 0xD2, 0x43, 0x4F, 0xEA, 0x81, 0x08, ++0x01, 0x92, 0x00, 0x2B, 0x3A, 0xD0, 0x3B, 0x68, 0x65, 0x6A, 0x5B, 0x78, 0xD5, 0xF8, 0x8C, 0x20, 0x00, 0x2B, 0x00, 0xF0, ++0x8B, 0x80, 0x69, 0x6D, 0x00, 0x29, 0x00, 0xF0, 0x11, 0x81, 0x00, 0x2A, 0x80, 0xF2, 0x29, 0x81, 0x9D, 0x49, 0xD9, 0xF8, ++0x00, 0x30, 0x51, 0xF8, 0x26, 0x10, 0x0B, 0x44, 0x11, 0x02, 0xC8, 0xF8, 0x00, 0x30, 0x40, 0xF1, 0xA2, 0x80, 0xAB, 0x88, ++0x99, 0x06, 0x40, 0xF1, 0x43, 0x81, 0x97, 0x4A, 0x43, 0xF0, 0x10, 0x03, 0x52, 0xF8, 0x26, 0x00, 0xAB, 0x80, 0x15, 0xF0, ++0x87, 0xF9, 0x94, 0xF8, 0x50, 0x30, 0x3A, 0x68, 0x01, 0x3B, 0x84, 0xF8, 0x50, 0x30, 0x00, 0x23, 0xA3, 0x76, 0x63, 0x62, ++0x53, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0x6B, 0x6D, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0xA5, 0x62, 0xEB, 0x7A, ++0x01, 0x33, 0xEB, 0x72, 0xE5, 0x68, 0x00, 0x2D, 0x00, 0xF0, 0x90, 0x81, 0xD5, 0xF8, 0x4C, 0xB0, 0xDB, 0xF8, 0x50, 0xA0, ++0xBA, 0xF1, 0x00, 0x0F, 0x80, 0xF2, 0xA9, 0x81, 0x30, 0x46, 0xCB, 0xF8, 0x10, 0xA0, 0x04, 0xF0, 0x03, 0xF9, 0x6A, 0x6A, ++0x12, 0xF4, 0x00, 0x10, 0x11, 0xD1, 0xDB, 0xF8, 0x18, 0x10, 0x00, 0x29, 0x00, 0xF0, 0x97, 0x80, 0x8B, 0x6B, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x00, 0x1F, 0x8C, 0x46, 0x00, 0xF0, 0x29, 0x81, 0xDC, 0xF8, 0x3C, 0x30, 0x00, 0x2B, 0x80, 0xF2, ++0x9D, 0x81, 0x1A, 0xF4, 0x00, 0x0F, 0x0B, 0xD0, 0x6B, 0x7F, 0x0D, 0x2B, 0x08, 0xD8, 0x73, 0x48, 0x73, 0x49, 0x4F, 0xF4, ++0x1E, 0x7C, 0x0C, 0xFB, 0x03, 0x03, 0x09, 0x69, 0xC3, 0xF8, 0x58, 0x12, 0x02, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x60, 0x1F, ++0x00, 0xF0, 0x9E, 0x80, 0x04, 0xF1, 0x0C, 0x00, 0x15, 0xF0, 0x18, 0xFA, 0x6B, 0x6A, 0x9B, 0x02, 0x04, 0xD4, 0x94, 0xF8, ++0x50, 0x30, 0x01, 0x3B, 0x84, 0xF8, 0x50, 0x30, 0xAB, 0x88, 0x00, 0x2B, 0x5F, 0xD1, 0x28, 0x46, 0x02, 0xF0, 0x4C, 0xF8, ++0x60, 0x4A, 0xD9, 0xF8, 0x00, 0x30, 0x52, 0xF8, 0x26, 0x20, 0x13, 0x44, 0xC8, 0xF8, 0x00, 0x30, 0xA3, 0x7E, 0x6A, 0xE7, ++0x29, 0x69, 0x00, 0x29, 0x00, 0xF0, 0xA4, 0x80, 0xAB, 0x6C, 0x00, 0x2B, 0x80, 0xF2, 0x9D, 0x80, 0x57, 0x4B, 0xD9, 0xF8, ++0x00, 0x20, 0x53, 0xF8, 0x26, 0x10, 0xAB, 0x88, 0x0A, 0x44, 0xC8, 0xF8, 0x00, 0x20, 0x9A, 0x06, 0x3F, 0xF5, 0x77, 0xAF, ++0xDF, 0xF8, 0x6C, 0xB1, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x4F, 0xF0, 0x04, 0x0A, 0xAB, 0x88, 0x99, 0x06, 0x3F, 0xF5, ++0x6C, 0xAF, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xBA, 0xF1, 0x01, 0x0A, 0xF5, 0xD1, 0xAB, 0x88, 0x9A, 0x06, 0x3F, 0xF5, ++0x62, 0xAF, 0x04, 0xF1, 0x1C, 0x00, 0x15, 0xF0, 0xD3, 0xF9, 0xAB, 0x88, 0x5B, 0xE7, 0x2B, 0x69, 0x00, 0x2B, 0x7F, 0xF4, ++0x71, 0xAF, 0x46, 0x4B, 0x1B, 0x68, 0xEF, 0xF3, 0x10, 0x82, 0xD0, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x43, 0x4A, 0x01, 0x21, ++0x11, 0x60, 0x43, 0x4A, 0x01, 0x99, 0x10, 0x68, 0x3F, 0x4D, 0x0B, 0x40, 0x41, 0x1C, 0x11, 0x60, 0x2B, 0x60, 0x29, 0xB1, ++0x3D, 0x4B, 0x10, 0x60, 0x1B, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x3C, 0x4B, 0x00, 0x9A, 0x1A, 0x60, 0x00, 0x22, ++0xA3, 0x7E, 0x22, 0x60, 0x17, 0xE7, 0x51, 0x46, 0x28, 0x46, 0x32, 0x46, 0x01, 0xF0, 0xC6, 0xF9, 0x9C, 0xE7, 0x33, 0x4B, ++0x1B, 0x68, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x30, 0x4A, 0x01, 0x21, 0x11, 0x60, 0xDF, 0xF8, ++0xC0, 0xC0, 0x01, 0x99, 0xDC, 0xF8, 0x00, 0x00, 0x2B, 0x4A, 0x0B, 0x40, 0x41, 0x1C, 0xCC, 0xF8, 0x00, 0x10, 0x13, 0x60, ++0x39, 0xB1, 0x29, 0x4B, 0xCC, 0xF8, 0x00, 0x00, 0x1B, 0x68, 0x10, 0xB9, 0x00, 0x2B, 0x40, 0xF0, 0xA2, 0x80, 0x27, 0x4B, ++0x00, 0x9A, 0x1A, 0x60, 0x94, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x2B, 0x22, 0x60, 0x7C, 0xD0, 0x6A, 0x6A, 0x4C, 0xE7, ++0x6B, 0x6C, 0x63, 0x62, 0x01, 0x23, 0x40, 0x20, 0xA3, 0x76, 0x15, 0xF0, 0x91, 0xF8, 0x59, 0xE7, 0x94, 0xF8, 0x50, 0x10, ++0x01, 0x29, 0x7F, 0xF4, 0xEA, 0xAE, 0xE1, 0x6A, 0x00, 0x29, 0x3F, 0xF4, 0xE6, 0xAE, 0x21, 0x6B, 0x19, 0x48, 0x09, 0x7F, ++0x4F, 0xF0, 0xA4, 0x0C, 0x0C, 0xFB, 0x01, 0x61, 0x99, 0x31, 0x50, 0xF8, 0x31, 0x10, 0x00, 0x29, 0x7B, 0xD0, 0x00, 0x2B, ++0x3F, 0xF4, 0x62, 0xAF, 0x00, 0x2A, 0xFF, 0xF6, 0xD7, 0xAE, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x94, 0xF8, 0x50, 0x10, ++0x01, 0x29, 0x7F, 0xF4, 0x57, 0xAF, 0xE1, 0x6A, 0x00, 0x29, 0xE2, 0xD1, 0x52, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, ++0x4A, 0x80, 0x0C, 0x10, 0x34, 0x36, 0x17, 0x00, 0xB0, 0x35, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x80, 0x32, 0x40, ++0x18, 0x88, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xDF, 0xF8, 0x68, 0xB1, 0xDB, 0xF8, 0x9C, 0x32, ++0x98, 0x47, 0x4F, 0xF0, 0x04, 0x0A, 0xAB, 0x88, 0x9A, 0x06, 0x3F, 0xF5, 0xB2, 0xAE, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, ++0xBA, 0xF1, 0x01, 0x0A, 0xF5, 0xD1, 0x4D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xAB, 0x88, 0xBF, 0xF6, ++0xA4, 0xAE, 0x98, 0x06, 0x3F, 0xF5, 0xA1, 0xAE, 0x48, 0x49, 0x49, 0x48, 0x4F, 0xF4, 0xAC, 0x62, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x16, 0xF0, 0xEB, 0xBC, 0x43, 0x48, 0x8B, 0x68, 0x01, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x00, 0x29, 0x33, 0xDB, ++0x60, 0x46, 0x9C, 0x46, 0xCC, 0xE6, 0xE3, 0x6A, 0x00, 0x2B, 0x3F, 0xF4, 0x7F, 0xAF, 0x23, 0x6B, 0x3E, 0x4A, 0x1B, 0x7F, ++0xA4, 0x21, 0x01, 0xFB, 0x03, 0x63, 0x99, 0x33, 0x52, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x73, 0xAF, 0x3A, 0x4B, ++0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0x6D, 0xAF, 0x38, 0x4B, 0x30, 0x46, 0xD3, 0xF8, 0x5C, 0x33, 0x98, 0x47, ++0x66, 0xE7, 0x62, 0xB6, 0x5B, 0xE7, 0x33, 0x49, 0x91, 0xF8, 0xFF, 0x11, 0x00, 0x29, 0x7F, 0xF4, 0x7E, 0xAF, 0x31, 0x4B, ++0x03, 0x92, 0xD3, 0xF8, 0x5C, 0x33, 0x30, 0x46, 0x98, 0x47, 0x3B, 0x68, 0x03, 0x9A, 0x5B, 0x78, 0x00, 0x2B, 0x7F, 0xF4, ++0x75, 0xAF, 0xD5, 0xE6, 0x00, 0x2B, 0xC9, 0xD1, 0x25, 0x49, 0x2A, 0x48, 0x00, 0x93, 0x40, 0xF2, 0x56, 0x42, 0x16, 0xF0, ++0xD9, 0xFC, 0x00, 0x9B, 0xDB, 0x6B, 0xFF, 0xDE, 0x26, 0x4C, 0x1F, 0xE6, 0x26, 0x4B, 0x25, 0x60, 0x1B, 0x68, 0xEF, 0xF3, ++0x10, 0x82, 0xD0, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x23, 0x4A, 0x01, 0x21, 0x11, 0x60, 0x23, 0x4A, 0x01, 0x99, 0x10, 0x68, ++0x1F, 0x4C, 0x19, 0x40, 0x0B, 0x46, 0x41, 0x1C, 0x11, 0x60, 0x23, 0x60, 0x29, 0xB1, 0x1D, 0x4B, 0x10, 0x60, 0x1B, 0x68, ++0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x1C, 0x4B, 0x00, 0x9A, 0x1A, 0x60, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x6B, 0x6A, ++0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x7F, 0xF4, 0x41, 0xAF, 0x68, 0x6C, 0x31, 0x46, 0x0C, 0x30, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0x03, 0xF0, 0x28, 0xBF, 0x10, 0xB1, 0x31, 0x46, 0x03, 0xF0, 0x24, 0xFF, 0x10, 0x4B, 0x11, 0x4A, ++0x53, 0xF8, 0x26, 0x10, 0x02, 0x9B, 0x12, 0x68, 0x9B, 0x00, 0x0A, 0x44, 0x1A, 0x60, 0x2A, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xD4, 0x8E, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xC0, 0x8E, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x88, 0x80, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x43, 0x6A, 0x9B, 0x02, 0x03, 0xD5, 0x4B, 0x6A, ++0x5B, 0x07, 0x07, 0xD4, 0x70, 0x47, 0xC1, 0x6C, 0x05, 0x4B, 0x14, 0x31, 0xD3, 0xF8, 0x9C, 0x33, 0x08, 0x46, 0x18, 0x47, ++0x42, 0x6C, 0x93, 0x88, 0x43, 0xF0, 0x02, 0x03, 0x93, 0x80, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x43, 0x7F, ++0x0B, 0x4E, 0x4F, 0xF4, 0x1E, 0x75, 0x04, 0x46, 0x05, 0xFB, 0x03, 0xF5, 0x05, 0xF5, 0xFE, 0x70, 0x01, 0x23, 0xE1, 0x76, ++0x84, 0xF8, 0x5D, 0x30, 0x30, 0x44, 0x21, 0x46, 0x14, 0xF0, 0xFE, 0xFF, 0x04, 0x4B, 0x71, 0x19, 0x20, 0x46, 0x5B, 0x69, ++0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x83, 0x88, 0x2D, 0xE9, ++0xF0, 0x41, 0x04, 0x46, 0x0E, 0x46, 0x15, 0x46, 0xEB, 0xB1, 0x3A, 0x4B, 0xD0, 0xF8, 0x4C, 0x80, 0x1A, 0x68, 0xB2, 0xF9, ++0x00, 0x20, 0x00, 0x2A, 0x23, 0xDB, 0xD8, 0xF8, 0x24, 0x70, 0x17, 0xB9, 0xD8, 0xF8, 0x20, 0x30, 0x9F, 0x68, 0x04, 0x2D, ++0x03, 0xD1, 0x39, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x13, 0xFB, 0xE3, 0x7E, 0xFF, 0x2B, 0x25, 0xD0, 0x2F, 0x4F, 0x29, 0x46, ++0xD7, 0xF8, 0x00, 0x34, 0x20, 0x46, 0x98, 0x47, 0x05, 0xE0, 0x82, 0x6C, 0x2B, 0x4F, 0x53, 0x6A, 0x43, 0xF0, 0x10, 0x03, ++0x53, 0x62, 0xD7, 0xF8, 0xA4, 0x33, 0x2A, 0x46, 0x31, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x82, 0x6C, ++0x5A, 0xB3, 0xD8, 0xF8, 0x24, 0x70, 0x00, 0x2F, 0xDB, 0xD1, 0xD8, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0xD6, 0xD1, 0x21, 0x49, ++0x21, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x03, 0xFC, 0xCD, 0xE7, 0xE3, 0x8B, 0x1A, 0x07, 0x04, 0xD5, 0x3A, 0x88, ++0x02, 0xF0, 0xDC, 0x02, 0x10, 0x2A, 0x25, 0xD0, 0xBB, 0x7D, 0x13, 0xF0, 0x0F, 0x03, 0x07, 0xF1, 0x16, 0x07, 0x06, 0xD0, ++0x18, 0x4A, 0xB2, 0xF8, 0xFC, 0x21, 0x43, 0xEA, 0x02, 0x13, 0x3B, 0x80, 0xC4, 0xE7, 0x15, 0x49, 0xB1, 0xF8, 0xFC, 0x21, ++0x01, 0x32, 0x92, 0xB2, 0xA1, 0xF8, 0xFC, 0x21, 0xF3, 0xE7, 0x0F, 0x49, 0x11, 0x48, 0x4F, 0xF4, 0xD9, 0x72, 0x16, 0xF0, ++0xDF, 0xFB, 0xD8, 0xF8, 0x24, 0x70, 0x00, 0x2F, 0xA9, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC7, 0xDB, 0x9F, 0xE7, 0x7A, 0x8B, 0x00, 0x2A, 0xD6, 0xD1, 0x43, 0xF0, 0x20, 0x03, 0xE3, 0x83, 0x38, 0x1D, 0x20, 0xF0, ++0xF9, 0xFE, 0xCF, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x8E, 0x15, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x8C, 0x8E, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x46, 0x05, 0x29, 0x00, 0xF2, 0x33, 0x81, 0xDF, 0xE8, ++0x01, 0xF0, 0x36, 0x44, 0x51, 0x5E, 0x6B, 0x03, 0x9D, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0x00, 0xF0, ++0x04, 0x81, 0x9B, 0x4A, 0x9B, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x42, 0x1A, 0x60, 0x9A, 0x49, 0x9A, 0x4A, 0x9B, 0x4B, ++0x51, 0xF8, 0x24, 0x50, 0x12, 0x68, 0x9A, 0x48, 0x23, 0x44, 0x9B, 0x00, 0x01, 0x21, 0x2A, 0x44, 0x01, 0xFA, 0x04, 0xF4, ++0x1A, 0x60, 0x04, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x94, 0x4B, 0x19, 0x60, 0x94, 0x4B, ++0x94, 0x49, 0x18, 0x68, 0x0D, 0x68, 0x42, 0x1C, 0x2C, 0x43, 0x1A, 0x60, 0x0C, 0x60, 0x2A, 0xB1, 0x8E, 0x4A, 0x18, 0x60, ++0x13, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x84, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x13, 0x02, 0x2B, ++0x00, 0xF0, 0xAE, 0x80, 0x8A, 0x4A, 0x82, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0xCB, 0xE7, 0x7D, 0x4A, ++0x13, 0x68, 0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0x7D, 0xD0, 0x85, 0x4A, 0x7B, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x62, ++0x1A, 0x60, 0xBE, 0xE7, 0x76, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x33, 0x02, 0x2B, 0x4F, 0xD0, 0x7F, 0x4A, 0x75, 0x4B, ++0x10, 0x60, 0x4F, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0xB1, 0xE7, 0x70, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, ++0x21, 0xD0, 0x7A, 0x4A, 0x6E, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0xA4, 0xE7, 0x77, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0xDB, 0x75, 0x4A, 0x68, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, ++0x97, 0xE7, 0x63, 0x4B, 0x1B, 0x68, 0x03, 0xF0, 0x03, 0x03, 0x02, 0x2B, 0xF2, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x6F, 0x49, ++0x6F, 0x48, 0x4F, 0xF4, 0xEC, 0x62, 0x16, 0xF0, 0xFF, 0xBA, 0x60, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, ++0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, 0xF6, 0xD0, 0x63, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCA, 0xDA, 0x52, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, 0xC4, 0xD1, ++0xBD, 0xE8, 0x38, 0x40, 0x5E, 0x49, 0x60, 0x48, 0x40, 0xF2, 0x6C, 0x72, 0x16, 0xF0, 0xDE, 0xBA, 0x4F, 0x49, 0x0D, 0x68, ++0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x33, 0x02, 0x2B, ++0xF6, 0xD0, 0x53, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x9C, 0xDA, 0x42, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, ++0x01, 0x33, 0x02, 0x2B, 0x96, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x4E, 0x49, 0x50, 0x48, 0x4F, 0xF4, 0xEF, 0x62, 0x16, 0xF0, ++0xBD, 0xBA, 0x3F, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, ++0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0xF6, 0xD0, 0x42, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0x6E, 0xAF, 0x31, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0x7F, 0xF4, 0x67, 0xAF, 0xBD, 0xE8, 0x38, 0x40, ++0x3C, 0x49, 0x40, 0x48, 0x40, 0xF2, 0x84, 0x72, 0x16, 0xF0, 0x9A, 0xBA, 0x2D, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, ++0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x13, 0x02, 0x2B, 0xF6, 0xD0, 0x31, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0x3E, 0xAF, 0x1F, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x13, ++0x02, 0x2B, 0x7F, 0xF4, 0x37, 0xAF, 0xBD, 0xE8, 0x38, 0x40, 0x2B, 0x49, 0x2F, 0x48, 0x4F, 0xF4, 0xF2, 0x62, 0x16, 0xF0, ++0x77, 0xBA, 0x1C, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, ++0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0xF6, 0xD0, 0x1F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0xE8, 0xAE, 0x0E, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0x7F, 0xF4, 0xE1, 0xAE, 0xBD, 0xE8, 0x38, 0x40, ++0x19, 0x49, 0x1F, 0x48, 0x40, 0xF2, 0x9C, 0x72, 0x16, 0xF0, 0x54, 0xBA, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xBF, 0xF6, 0xD8, 0xAE, 0x13, 0x49, 0x19, 0x48, 0x40, 0xF2, 0xA2, 0x72, 0x16, 0xF0, 0x79, 0xFA, 0xD0, 0xE6, ++0x88, 0x81, 0x32, 0x40, 0x34, 0x83, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, ++0x4A, 0x80, 0x0C, 0x10, 0x88, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, ++0x9C, 0x81, 0x32, 0x40, 0xA0, 0x81, 0x32, 0x40, 0xA4, 0x81, 0x32, 0x40, 0xA8, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x98, 0x81, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0xF8, 0x8E, 0x15, 0x00, 0x18, 0x8F, 0x15, 0x00, 0x38, 0x8F, 0x15, 0x00, ++0x58, 0x8F, 0x15, 0x00, 0x78, 0x8F, 0x15, 0x00, 0x98, 0x8F, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x05, 0x2A, 0xF8, 0xB5, ++0x06, 0x46, 0x0D, 0x46, 0x35, 0xD0, 0x54, 0x21, 0x33, 0x4C, 0x01, 0xFB, 0x02, 0xF1, 0x02, 0xEB, 0x42, 0x03, 0x61, 0x58, ++0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, 0x00, 0x29, 0x37, 0xD0, 0x2E, 0x4F, 0x3B, 0x68, 0x5B, 0x78, 0xF3, 0xB1, ++0x4E, 0x60, 0x05, 0x2A, 0x0B, 0xD0, 0x2C, 0x48, 0x02, 0xEB, 0x42, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x91, 0xF8, 0x2E, 0x10, ++0x41, 0xB9, 0x90, 0xF8, 0x8C, 0x10, 0x00, 0x29, 0x3E, 0xD1, 0x10, 0x46, 0xFF, 0xF7, 0x2A, 0xFB, 0x3B, 0x68, 0x5B, 0x78, ++0x3B, 0xB9, 0xAA, 0x6B, 0x92, 0x02, 0x46, 0xBF, 0x01, 0x23, 0xC4, 0xE9, 0x01, 0x63, 0xC4, 0xE9, 0x01, 0x33, 0x25, 0x60, ++0xF8, 0xBD, 0xA0, 0x68, 0x00, 0x28, 0xDD, 0xD0, 0x61, 0x68, 0x4E, 0x60, 0xDB, 0xE7, 0x19, 0x4C, 0xD4, 0xF8, 0xA4, 0x11, ++0x04, 0xF5, 0xD2, 0x74, 0x00, 0x29, 0xCF, 0xD1, 0x11, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x44, 0xFE, 0x14, 0x4B, 0x1B, 0x68, ++0x5B, 0x78, 0xDF, 0xE7, 0x13, 0x4B, 0x02, 0xEB, 0x42, 0x00, 0x03, 0xEB, 0x80, 0x00, 0x51, 0x00, 0x90, 0xF8, 0x2E, 0x00, ++0x38, 0xB9, 0x93, 0xF8, 0x8C, 0x00, 0x93, 0xF8, 0x7E, 0x70, 0x00, 0x28, 0xE8, 0xD0, 0xBA, 0x42, 0xE6, 0xD1, 0x0A, 0x44, ++0x03, 0xEB, 0x82, 0x03, 0x5A, 0x6A, 0x42, 0xB1, 0x07, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0xC5, 0xE7, 0x90, 0xF8, 0x7E, 0x10, ++0x91, 0x42, 0xBC, 0xD1, 0xC0, 0xE7, 0x03, 0x4A, 0x5E, 0x62, 0x13, 0x68, 0x5B, 0x78, 0xBB, 0xE7, 0x20, 0x62, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x38, 0xB5, 0x83, 0x88, 0x33, 0xB1, 0x04, 0x46, 0x80, 0x6C, 0x18, 0xB1, ++0x63, 0x6A, 0x13, 0xF4, 0x00, 0x15, 0x00, 0xD0, 0x38, 0xBD, 0xF8, 0xF7, 0x75, 0xFE, 0xA5, 0x64, 0x38, 0xBD, 0x00, 0xBF, ++0x70, 0xB5, 0x20, 0x4C, 0x20, 0x4D, 0x02, 0xF0, 0xD9, 0xFC, 0xD4, 0xF8, 0x44, 0x33, 0x98, 0x47, 0xFE, 0xF7, 0x9E, 0xFF, ++0x00, 0xF0, 0xA8, 0xFD, 0xD4, 0xF8, 0xA8, 0x33, 0x00, 0x20, 0x98, 0x47, 0x04, 0xF0, 0xBA, 0xFE, 0x4F, 0xF4, 0x01, 0x72, ++0x00, 0x21, 0xA5, 0xF1, 0x0C, 0x00, 0xF1, 0xF7, 0xC3, 0xFC, 0x05, 0xF5, 0xD2, 0x76, 0x00, 0x24, 0x28, 0x46, 0x14, 0xF0, ++0x4D, 0xFD, 0x45, 0xF8, 0x0C, 0x4C, 0xAC, 0x73, 0x85, 0xF8, 0x44, 0x40, 0xC5, 0xE9, 0x06, 0x44, 0x05, 0xF1, 0x10, 0x00, ++0x54, 0x35, 0x14, 0xF0, 0x41, 0xFD, 0xB5, 0x42, 0xEE, 0xD1, 0x0C, 0x4D, 0x05, 0xF5, 0xD8, 0x70, 0x14, 0xF0, 0x3A, 0xFD, ++0x05, 0xF5, 0xE0, 0x70, 0xC5, 0xE9, 0x72, 0x44, 0xC5, 0xF8, 0xA4, 0x41, 0x85, 0xF8, 0xBE, 0x41, 0x85, 0xF8, 0xF4, 0x41, ++0x14, 0xF0, 0x2E, 0xFD, 0xA5, 0xF8, 0xFC, 0x41, 0x70, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x62, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x0C, 0x4B, 0x93, 0xF8, 0xFE, 0x31, 0x0B, 0xB1, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x04, 0x46, ++0x10, 0xF0, 0xBC, 0xF8, 0x20, 0xB1, 0x94, 0xF8, 0xC0, 0x34, 0x1B, 0xB9, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, ++0x94, 0xF8, 0xC1, 0x04, 0x11, 0xF0, 0x16, 0xFD, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x10, 0xBD, 0x20, 0x62, 0x17, 0x00, ++0x45, 0x4B, 0x01, 0x22, 0x70, 0xB4, 0x1B, 0x68, 0x02, 0xFA, 0x00, 0xF6, 0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, ++0x72, 0xB6, 0x41, 0x49, 0x0A, 0x60, 0x41, 0x4A, 0x3E, 0x4D, 0x14, 0x68, 0x23, 0xEA, 0x06, 0x03, 0x61, 0x1C, 0x11, 0x60, ++0x2B, 0x60, 0x29, 0xB1, 0x3B, 0x4B, 0x14, 0x60, 0x1B, 0x68, 0x0C, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x3A, 0x4B, 0x1E, 0x60, ++0x05, 0x28, 0x5D, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x12, 0x21, 0x3F, 0x30, 0x4E, 0x03, 0x37, 0x4B, 0x37, 0x4A, 0x4F, 0xF4, ++0x00, 0x11, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF0, 0x40, 0x7F, 0xFB, 0xD1, 0x34, 0x4B, 0x4F, 0xF4, 0x00, 0x12, 0x70, 0xBC, ++0x1A, 0x60, 0x70, 0x47, 0x2F, 0x4B, 0x30, 0x4A, 0x4F, 0xF4, 0x80, 0x31, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF0, 0x30, 0x0F, ++0xFB, 0xD1, 0x2D, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x28, 0x4B, 0x28, 0x4A, 0x4F, 0xF4, ++0x00, 0x31, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x7F, 0xFB, 0xD1, 0x25, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x70, 0xBC, ++0x1A, 0x60, 0x70, 0x47, 0x20, 0x4B, 0x21, 0x4A, 0x4F, 0xF4, 0x00, 0x21, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x3F, ++0xFB, 0xD1, 0x1E, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x19, 0x4B, 0x19, 0x4A, 0x4F, 0xF4, ++0x80, 0x21, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x5F, 0xFB, 0xD1, 0x16, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x70, 0xBC, ++0x1A, 0x60, 0x70, 0x47, 0x11, 0x4B, 0x12, 0x4A, 0x4F, 0xF4, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x9B, 0x07, 0xFC, 0xD1, ++0x0F, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0x1A, 0x60, 0x70, 0xBC, 0x70, 0x47, 0x0D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xF7, 0xDA, 0x70, 0xBC, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0xE7, 0x02, 0x16, 0xF0, 0xD5, 0xB8, 0x00, 0xBF, ++0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x80, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, ++0x88, 0x81, 0x32, 0x40, 0x84, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x70, 0xB5, 0x05, 0x28, 0x82, 0xB0, 0x04, 0x46, 0x0A, 0x46, 0x3B, 0xD0, 0x1E, 0x4B, 0x00, 0xEB, 0x40, 0x05, 0xC5, 0xEB, ++0xC5, 0x05, 0x03, 0xEB, 0x85, 0x05, 0x1C, 0x4E, 0x1C, 0x49, 0xD6, 0xF8, 0x84, 0x33, 0x01, 0x92, 0x01, 0xEB, 0xC4, 0x01, ++0x20, 0x46, 0x98, 0x47, 0x01, 0x9A, 0xD6, 0xF8, 0x84, 0x33, 0x05, 0xF1, 0x0C, 0x01, 0x20, 0x46, 0x98, 0x47, 0x00, 0x23, ++0x20, 0x46, 0x2B, 0x60, 0x6B, 0x61, 0xFE, 0xF7, 0x59, 0xFE, 0x13, 0x4B, 0x01, 0x22, 0x1B, 0x68, 0x02, 0xFA, 0x04, 0xF4, ++0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x0F, 0x49, 0x0A, 0x60, 0x0F, 0x4A, 0x0C, 0x4D, 0x11, 0x68, ++0x23, 0xEA, 0x04, 0x03, 0x48, 0x1C, 0x10, 0x60, 0x2B, 0x60, 0x28, 0xB1, 0x09, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x08, 0x4B, 0x1C, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x07, 0x4D, 0xC8, 0xE7, 0x20, 0x62, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x24, 0x64, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x88, 0x80, 0x32, 0x40, 0xC4, 0x63, 0x17, 0x00, 0x70, 0xB5, 0x0E, 0x4E, 0x82, 0xB0, 0x00, 0xF5, 0x9E, 0x64, 0x00, 0x25, ++0xE8, 0xB2, 0x21, 0x46, 0xD6, 0xF8, 0x84, 0x33, 0x01, 0x90, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0x01, 0x35, 0xA4, 0xF1, ++0x28, 0x01, 0x01, 0x98, 0xD6, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0x05, 0x2D, 0x04, 0xF1, 0x08, 0x04, ++0xEA, 0xD1, 0x02, 0xB0, 0x70, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x05, 0x29, 0x2D, 0xE9, 0xF0, 0x41, 0x0E, 0x46, ++0x04, 0x46, 0x64, 0xD0, 0x33, 0x4D, 0x01, 0xEB, 0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x05, 0xEB, 0x83, 0x05, 0x94, 0xF8, ++0x35, 0x10, 0x94, 0xF8, 0x33, 0x20, 0xA3, 0x88, 0x2E, 0x48, 0x0A, 0x44, 0x1A, 0x44, 0xE3, 0x6C, 0xE1, 0x8B, 0x58, 0x61, ++0x04, 0x32, 0xDA, 0x62, 0x00, 0x22, 0xC3, 0xE9, 0x0F, 0x22, 0xC3, 0xE9, 0x06, 0x22, 0xC3, 0xE9, 0x08, 0x22, 0x5A, 0x64, ++0x9A, 0x62, 0x9A, 0x63, 0xDA, 0x64, 0x1A, 0x63, 0x1A, 0x65, 0xCA, 0x07, 0x05, 0xD4, 0x22, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, ++0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x21, 0x4B, 0x1B, 0x6A, 0x23, 0xB1, 0x20, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x33, ++0x13, 0x60, 0xDF, 0xF8, 0x88, 0x80, 0x61, 0x7F, 0x20, 0x7F, 0x00, 0x22, 0x12, 0xF0, 0x5A, 0xF9, 0xD8, 0xF8, 0x48, 0x32, ++0xE1, 0x7E, 0x60, 0x7F, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x16, 0x4F, 0xD8, 0xF8, 0x68, 0x33, 0x3A, 0x68, 0x01, 0x32, 0x3A, 0x60, 0x31, 0x46, 0x20, 0x46, 0x98, 0x47, ++0xD8, 0xF8, 0x08, 0x34, 0x31, 0x46, 0x00, 0x22, 0x20, 0x46, 0x98, 0x47, 0x21, 0x46, 0x05, 0xF1, 0x0C, 0x00, 0x14, 0xF0, ++0x99, 0xFB, 0x3B, 0x68, 0x33, 0xB1, 0x0A, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x07, 0x4D, 0x9F, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, ++0x1C, 0x9E, 0x17, 0x00, 0x80, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x03, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, 0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x70, 0x47, 0x00, 0xBF, ++0x20, 0x62, 0x17, 0x00, 0x05, 0x29, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x46, 0x04, 0x46, 0x1C, 0xD0, 0x47, 0x4E, 0x01, 0xEB, ++0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x06, 0xEB, 0x83, 0x06, 0x22, 0x7F, 0x44, 0x4B, 0xE7, 0x6C, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x02, 0x30, 0xFF, 0xF7, 0x32, 0xFE, 0x68, 0xB9, 0x63, 0x7F, 0xFF, 0x2B, 0x67, 0xD0, 0x3F, 0x4B, 0x20, 0x46, ++0xD3, 0xF8, 0x90, 0x33, 0x29, 0x46, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x3C, 0x4E, 0xE7, 0xE7, 0x20, 0x46, ++0x1C, 0xF0, 0xEE, 0xFF, 0x00, 0x28, 0xEC, 0xD0, 0xFB, 0x6C, 0x43, 0xF4, 0x80, 0x73, 0xFB, 0x64, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x34, 0x4F, 0x96, 0xF8, 0x50, 0x30, 0x3A, 0x68, ++0xF1, 0x6A, 0xDF, 0xF8, 0xBC, 0x80, 0x01, 0x32, 0x01, 0x33, 0x3A, 0x60, 0x86, 0xF8, 0x50, 0x30, 0x19, 0xB1, 0xD8, 0xF8, ++0x5C, 0x33, 0x28, 0x46, 0x98, 0x47, 0x73, 0x69, 0x00, 0x2B, 0x42, 0xD0, 0x06, 0xF1, 0x0C, 0x00, 0x21, 0x46, 0x14, 0xF0, ++0x21, 0xFB, 0x3B, 0x68, 0x2B, 0xB1, 0x26, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x00, 0x2B, 0x31, 0xD0, 0x1F, 0x4A, ++0x24, 0x49, 0xD2, 0xF8, 0xF8, 0x31, 0x09, 0x6A, 0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x21, 0xB1, 0x21, 0x4A, 0x13, 0x68, ++0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x19, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x3B, 0x68, 0xD8, 0xF8, 0x04, 0x64, 0xA1, 0x6C, 0x01, 0x33, 0x3B, 0x60, 0x2A, 0x46, 0x20, 0x46, 0xB0, 0x47, ++0x3B, 0x68, 0x33, 0xB1, 0x12, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x01, 0x20, ++0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x46, 0x00, 0x21, 0x01, 0xF0, 0x7E, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x2A, ++0xCB, 0xD0, 0x62, 0xB6, 0xC9, 0xE7, 0xA3, 0x6C, 0x0B, 0x49, 0x5A, 0x6A, 0x9C, 0x60, 0x22, 0xF0, 0x10, 0x02, 0x5A, 0x62, ++0xD9, 0x60, 0xB3, 0xE7, 0x20, 0x62, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x80, 0x00, 0x32, 0x40, 0xDE, 0xFA, 0xFE, 0xCA, ++0x70, 0x47, 0x00, 0xBF, 0x20, 0x4B, 0x70, 0xB5, 0x1C, 0x68, 0xE1, 0x04, 0x2C, 0xD4, 0x1F, 0x4D, 0x2C, 0x42, 0x24, 0xD1, ++0x1E, 0x4B, 0x23, 0x40, 0x20, 0xD0, 0x22, 0x03, 0x0B, 0xD5, 0x1D, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x05, 0x24, ++0x1B, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xA0, 0x33, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x19, 0x4A, 0x12, 0x68, 0xB2, 0xF9, ++0x00, 0x20, 0xB3, 0xFA, 0x83, 0xF3, 0xC3, 0xF1, 0x19, 0x04, 0x00, 0x2A, 0xE4, 0xB2, 0x14, 0xDB, 0x05, 0x2C, 0xE6, 0xD0, ++0x10, 0x4A, 0xA1, 0x1D, 0x01, 0x23, 0x8B, 0x40, 0x13, 0x60, 0xE5, 0xE7, 0x70, 0xBD, 0x04, 0xF0, 0x07, 0xFB, 0x0C, 0x4B, ++0x1D, 0x60, 0xD5, 0xE7, 0x04, 0xF0, 0x56, 0xFA, 0x09, 0x4B, 0x4F, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0xCB, 0xE7, 0x06, 0x2C, ++0xE8, 0xD9, 0x09, 0x49, 0x09, 0x48, 0x40, 0xF6, 0xC2, 0x22, 0x15, 0xF0, 0xD9, 0xFE, 0xE3, 0xE7, 0x78, 0x80, 0x32, 0x40, ++0x00, 0x08, 0x00, 0x20, 0xC0, 0x07, 0x08, 0x00, 0x7C, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xB8, 0x8F, 0x15, 0x00, 0x38, 0xB5, 0x0D, 0x4B, 0x0D, 0x4D, 0x1C, 0x68, 0xE3, 0x06, 0x05, 0xEA, ++0x04, 0x05, 0x03, 0xD5, 0x0B, 0x4B, 0xD3, 0xF8, 0xF0, 0x33, 0x98, 0x47, 0x14, 0xF4, 0x70, 0x04, 0x08, 0xD0, 0x08, 0x4B, ++0xB4, 0xFA, 0x84, 0xF4, 0xC4, 0xF1, 0x0B, 0x00, 0xD3, 0xF8, 0x48, 0x33, 0xC0, 0xB2, 0x98, 0x47, 0x04, 0x4B, 0x1D, 0x60, ++0x38, 0xBD, 0x00, 0xBF, 0x78, 0x80, 0x32, 0x40, 0x1F, 0x00, 0xF0, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x7C, 0x80, 0x32, 0x40, ++0xFF, 0xF7, 0xDA, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1C, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x70, 0x90, 0x1A, 0x4F, 0xD9, 0xF8, 0x00, 0x30, 0xDF, 0xF8, 0x6C, 0x80, 0x01, 0x33, ++0xC9, 0xF8, 0x00, 0x30, 0x3D, 0x46, 0x46, 0x46, 0x04, 0x24, 0x95, 0xF8, 0x5E, 0x30, 0xE2, 0xB2, 0x63, 0xB9, 0x97, 0xF8, ++0x8C, 0x30, 0x97, 0xF8, 0x7E, 0x10, 0x10, 0x46, 0x0B, 0xB1, 0x91, 0x42, 0x04, 0xD0, 0xD6, 0xF8, 0x50, 0x31, 0x0B, 0xB1, ++0xFF, 0xF7, 0x1A, 0xFD, 0x01, 0x3C, 0x63, 0x1C, 0xA5, 0xF1, 0x0C, 0x05, 0xA6, 0xF1, 0x54, 0x06, 0xE7, 0xD1, 0xD9, 0xF8, ++0x00, 0x30, 0x01, 0x22, 0x88, 0xF8, 0xFF, 0x21, 0x3B, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x31, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x31, 0x4E, 0x31, 0x4D, 0x33, 0x68, 0x31, 0x4F, 0xDF, 0xF8, ++0xD0, 0xB0, 0xDF, 0xF8, 0xD0, 0xA0, 0xDF, 0xF8, 0xD0, 0x80, 0x01, 0x33, 0x00, 0x22, 0x33, 0x60, 0x85, 0xF8, 0xFF, 0x21, ++0xB9, 0x46, 0x04, 0x24, 0x99, 0xF8, 0x5E, 0x30, 0xE0, 0xB2, 0x00, 0x2B, 0x34, 0xD1, 0x97, 0xF8, 0x8C, 0x30, 0x97, 0xF8, ++0x7E, 0x20, 0x0B, 0xB1, 0x82, 0x42, 0x2D, 0xD0, 0xD5, 0xF8, 0x50, 0x31, 0x43, 0xB3, 0x01, 0x90, 0xFE, 0xF7, 0x36, 0xFF, ++0x5A, 0xF8, 0x24, 0x30, 0xDB, 0xF8, 0x00, 0x20, 0x20, 0x48, 0x1A, 0x44, 0x40, 0xF8, 0x24, 0x20, 0x01, 0x21, 0x1F, 0x4A, ++0x01, 0xFA, 0x04, 0xF3, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x82, 0x12, 0xF0, 0x01, 0x0F, 0x01, 0x98, 0x02, 0xD1, 0x72, 0xB6, ++0x14, 0x4A, 0x11, 0x60, 0x32, 0x68, 0xD8, 0xF8, 0x00, 0xC0, 0x51, 0x1C, 0x43, 0xEA, 0x0C, 0x03, 0x31, 0x60, 0xC8, 0xF8, ++0x00, 0x30, 0x29, 0xB1, 0x0E, 0x4B, 0x32, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x03, 0xF0, 0x32, 0xF8, ++0x01, 0x3C, 0x63, 0x1C, 0xA9, 0xF1, 0x0C, 0x09, 0xA5, 0xF1, 0x54, 0x05, 0xBE, 0xD1, 0x33, 0x68, 0x33, 0xB1, 0x06, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x40, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, ++0x14, 0xF0, 0xF8, 0xB8, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x28, 0x01, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x20, 0x01, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x4F, 0x5D, 0x4E, 0xDF, 0xF8, 0x90, 0x91, 0xB6, 0xF8, 0xFC, 0x31, 0x83, 0xB0, 0x4F, 0xF4, 0x78, 0x30, ++0x00, 0x93, 0x06, 0xF1, 0x0C, 0x05, 0x14, 0xF0, 0xFB, 0xF8, 0x01, 0x23, 0x86, 0xF8, 0xFE, 0x31, 0xAA, 0x46, 0x4F, 0xF4, ++0x9E, 0x67, 0x4F, 0xF0, 0x00, 0x0B, 0x01, 0x95, 0x53, 0x49, 0xD9, 0xF8, 0x84, 0x33, 0x5F, 0xFA, 0x8B, 0xF8, 0x40, 0x46, ++0x4F, 0xF0, 0x80, 0x42, 0x39, 0x44, 0x98, 0x47, 0x4F, 0x4B, 0x9D, 0x68, 0xA7, 0xF1, 0x28, 0x04, 0xC5, 0xB1, 0xE9, 0x19, ++0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x40, 0x46, 0x98, 0x47, 0x29, 0x19, 0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, ++0x80, 0x42, 0x40, 0x46, 0x98, 0x47, 0x05, 0xF5, 0xA3, 0x61, 0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x40, 0x46, ++0x98, 0x47, 0x2D, 0x68, 0x00, 0x2D, 0xE6, 0xD1, 0x51, 0x46, 0xD9, 0xF8, 0x84, 0x33, 0x40, 0x46, 0x08, 0x37, 0x4F, 0xF0, ++0x80, 0x42, 0x98, 0x47, 0xB7, 0xF5, 0xA3, 0x6F, 0x0B, 0xF1, 0x01, 0x0B, 0x0A, 0xF1, 0x54, 0x0A, 0xC8, 0xD1, 0xD9, 0xF8, ++0x84, 0x33, 0x39, 0x49, 0x01, 0x9D, 0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0x37, 0x49, 0xD9, 0xF8, 0x84, 0x33, ++0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0x02, 0xF0, 0x30, 0xF9, 0x00, 0xF0, 0x6A, 0xF9, 0xD9, 0xF8, 0xCC, 0x33, ++0x98, 0x47, 0x2C, 0x48, 0x4F, 0xF4, 0x01, 0x72, 0x00, 0x21, 0xF1, 0xF7, 0x89, 0xF8, 0x2B, 0x4B, 0xD3, 0xF8, 0x08, 0x80, ++0x00, 0x9B, 0xA6, 0xF8, 0xFC, 0x31, 0xB8, 0xF1, 0x00, 0x0F, 0x17, 0xD0, 0x2B, 0x46, 0x45, 0x46, 0x98, 0x46, 0x05, 0xF5, ++0x9E, 0x64, 0x05, 0xF5, 0xA3, 0x67, 0x20, 0x46, 0x14, 0xF0, 0x06, 0xF9, 0xA4, 0xF1, 0x28, 0x00, 0x08, 0x34, 0x14, 0xF0, ++0x01, 0xF9, 0xBC, 0x42, 0xF5, 0xD1, 0x20, 0x46, 0x14, 0xF0, 0xFC, 0xF8, 0x2D, 0x68, 0x00, 0x2D, 0xEB, 0xD1, 0x45, 0x46, ++0x1B, 0x4F, 0x00, 0x24, 0x28, 0x46, 0x14, 0xF0, 0xF3, 0xF8, 0x45, 0xF8, 0x0C, 0x4C, 0xAC, 0x73, 0x85, 0xF8, 0x44, 0x40, ++0xC5, 0xE9, 0x06, 0x44, 0x05, 0xF1, 0x10, 0x00, 0x54, 0x35, 0x14, 0xF0, 0xE7, 0xF8, 0xAF, 0x42, 0xEE, 0xD1, 0x12, 0x48, ++0x14, 0xF0, 0xE2, 0xF8, 0x12, 0x48, 0xC6, 0xF8, 0xA4, 0x41, 0xC6, 0xE9, 0x72, 0x44, 0x86, 0xF8, 0xBE, 0x41, 0x86, 0xF8, ++0xF4, 0x41, 0x14, 0xF0, 0xD7, 0xF8, 0x0E, 0x4A, 0x00, 0x21, 0x02, 0xF5, 0xB4, 0x70, 0xA2, 0xF1, 0x24, 0x03, 0x43, 0xF8, ++0x04, 0x1B, 0x93, 0x42, 0xFB, 0xD1, 0x03, 0xF1, 0x24, 0x02, 0x90, 0x42, 0xF5, 0xD1, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x20, 0x62, 0x17, 0x00, 0x34, 0x5F, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xD0, 0x63, 0x17, 0x00, 0x4C, 0x64, 0x17, 0x00, ++0xE0, 0x63, 0x17, 0x00, 0xD8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x03, 0x8C, 0x08, 0x8C, 0x83, 0x42, 0x08, 0xD8, ++0x05, 0xD2, 0xC0, 0x1A, 0x3F, 0x28, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x51, 0xB9, 0x81, 0x6C, 0x90, 0xF8, 0x42, 0x30, 0xCB, 0x1A, 0x93, 0xF8, 0xB8, 0x30, 0xDB, 0x07, ++0x02, 0xD4, 0x03, 0x8B, 0x08, 0x2B, 0x00, 0xD0, 0x70, 0x47, 0x91, 0xF8, 0xA8, 0x30, 0x03, 0xF0, 0xF0, 0x03, 0x40, 0x2B, ++0xF8, 0xD1, 0x91, 0xF8, 0xB1, 0x30, 0x06, 0x2B, 0x01, 0xD0, 0x01, 0x2B, 0xF2, 0xD1, 0x13, 0x68, 0x01, 0x33, 0x13, 0x60, ++0xEE, 0xE7, 0x00, 0xBF, 0x03, 0x6D, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x43, 0x56, 0x4A, 0x12, 0x68, ++0x12, 0x78, 0x02, 0x2A, 0x83, 0xB0, 0x04, 0x46, 0x0D, 0x46, 0x07, 0xD0, 0x01, 0x2A, 0x7E, 0xD0, 0x03, 0x2A, 0x00, 0xF0, ++0x8D, 0x80, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0xFB, 0xF7, 0x8A, 0xFB, 0x06, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x94, 0x80, ++0xDF, 0xF8, 0x60, 0x91, 0x42, 0xF2, 0x24, 0x03, 0x59, 0xF8, 0x03, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x87, 0x80, 0x48, 0x48, ++0x14, 0xF0, 0xA8, 0xF8, 0x4F, 0xF0, 0x00, 0x08, 0x08, 0x22, 0x12, 0x23, 0x32, 0x70, 0x86, 0xF8, 0x01, 0x80, 0x86, 0xF8, ++0x03, 0x80, 0xB3, 0x70, 0x23, 0x6D, 0x29, 0x68, 0x00, 0x91, 0x23, 0xF0, 0x40, 0x43, 0x07, 0x46, 0x69, 0x46, 0x30, 0x1D, ++0x01, 0x93, 0x27, 0xF0, 0x49, 0xFF, 0x42, 0xF2, 0x34, 0x03, 0x39, 0xF8, 0x03, 0x30, 0xB3, 0xF5, 0xC3, 0x7F, 0x62, 0xD8, ++0x03, 0xF1, 0x01, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xDA, 0x00, 0x37, 0x49, 0xBB, 0x81, 0x09, 0x68, 0x36, 0x4B, 0x01, 0xEB, ++0x02, 0x0C, 0x42, 0xF2, 0x34, 0x08, 0xCC, 0xF8, 0x04, 0x60, 0x88, 0x58, 0x03, 0x40, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF0, ++0x0C, 0x03, 0x8B, 0x50, 0x99, 0xF8, 0x02, 0x3C, 0x29, 0xF8, 0x08, 0xE0, 0x01, 0x33, 0x01, 0x22, 0x00, 0x20, 0x0C, 0x21, ++0x89, 0xF8, 0x02, 0x3C, 0xC7, 0xF8, 0x04, 0xC0, 0xBA, 0x73, 0x38, 0x60, 0xB9, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x02, 0xD4, 0x72, 0xB6, 0x26, 0x4B, 0x1A, 0x60, 0x26, 0x4E, 0x2B, 0x68, 0x31, 0x68, 0x22, 0x8C, 0x25, 0x48, 0x4D, 0x1C, ++0x21, 0x46, 0x35, 0x60, 0x15, 0xF0, 0xEC, 0xF9, 0x23, 0x48, 0x39, 0x46, 0x14, 0xF0, 0x0E, 0xF8, 0x22, 0x4B, 0xD3, 0xF8, ++0x44, 0x34, 0x98, 0x47, 0x33, 0x68, 0x00, 0x2B, 0x8D, 0xD0, 0x1B, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x00, 0x2B, ++0x87, 0xD1, 0x00, 0x2A, 0x85, 0xD0, 0x62, 0xB6, 0x83, 0xE7, 0x0E, 0x68, 0x00, 0x96, 0x23, 0xF0, 0x40, 0x43, 0x69, 0x46, ++0x08, 0x22, 0x12, 0x20, 0x01, 0x93, 0xF9, 0xF7, 0xD7, 0xFA, 0x2B, 0x68, 0x22, 0x8C, 0x15, 0x48, 0x21, 0x46, 0x15, 0xF0, ++0xC7, 0xF9, 0x72, 0xE7, 0x13, 0x4B, 0x0A, 0x68, 0x1B, 0x68, 0x1A, 0x60, 0xF6, 0xF7, 0x72, 0xF8, 0x6B, 0xE7, 0x42, 0x46, ++0x43, 0x46, 0x4F, 0xF0, 0x01, 0x0E, 0x9C, 0xE7, 0x0E, 0x48, 0xF6, 0xF7, 0xED, 0xFF, 0x62, 0xE7, 0x0D, 0x48, 0xF6, 0xF7, ++0xE9, 0xFF, 0x5E, 0xE7, 0x78, 0x36, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, 0x00, 0x00, 0xFF, 0x31, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x90, 0x15, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x20, 0x90, 0x15, 0x00, 0x00, 0x38, 0x18, 0x00, 0xDC, 0x8F, 0x15, 0x00, 0xD8, 0x83, 0x15, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x10, 0xB5, 0x0D, 0x4C, 0x30, 0x22, 0x00, 0x21, 0x20, 0x46, 0xF0, 0xF7, 0x21, 0xFF, 0x20, 0x46, 0x13, 0xF0, 0xAE, 0xFF, ++0x04, 0xF1, 0x08, 0x00, 0x13, 0xF0, 0xAA, 0xFF, 0x04, 0xF1, 0x10, 0x00, 0x13, 0xF0, 0xA6, 0xFF, 0x04, 0xF1, 0x18, 0x00, ++0x13, 0xF0, 0xA2, 0xFF, 0x04, 0xF1, 0x20, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0xF0, 0x9C, 0xBF, 0x24, 0x64, 0x17, 0x00, ++0x38, 0xB5, 0xC3, 0x6C, 0x04, 0x46, 0x09, 0x48, 0x19, 0x61, 0x00, 0xEB, 0xC2, 0x00, 0x21, 0x46, 0x15, 0x46, 0x13, 0xF0, ++0x93, 0xFF, 0x63, 0x6A, 0x9B, 0x02, 0x00, 0xD5, 0x38, 0xBD, 0x04, 0x4B, 0x53, 0xF8, 0x25, 0x00, 0xBD, 0xE8, 0x38, 0x40, ++0x13, 0xF0, 0xE6, 0xBE, 0x24, 0x64, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x38, 0xB5, 0x38, 0x4B, 0x93, 0xF8, 0x8C, 0x20, ++0x05, 0x46, 0x00, 0x2A, 0x42, 0xD1, 0x43, 0x6D, 0xC3, 0xF3, 0xC1, 0x23, 0x54, 0x22, 0x1C, 0x21, 0x33, 0x48, 0x12, 0xFB, ++0x03, 0x13, 0x18, 0x44, 0x13, 0xF0, 0xB6, 0xFF, 0x04, 0x46, 0x31, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, ++0x01, 0xDB, 0x14, 0xB9, 0x38, 0xBD, 0x00, 0x2C, 0x4C, 0xD0, 0xA2, 0x88, 0x68, 0x6D, 0x42, 0xF0, 0x20, 0x02, 0x81, 0x01, ++0xA2, 0x80, 0xF5, 0xD5, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF3, 0xCF, 0x31, 0xC0, 0xF3, 0xC9, 0x33, 0x26, 0xDB, ++0x62, 0x7A, 0x10, 0x3B, 0x93, 0x42, 0xE9, 0xD1, 0xEB, 0x69, 0x99, 0x68, 0x0B, 0x8A, 0x03, 0xF0, 0x1E, 0x02, 0x16, 0x2A, ++0x25, 0xD0, 0x82, 0x05, 0xE0, 0xD4, 0x2A, 0x8E, 0x1C, 0x2A, 0xDD, 0xD1, 0xA2, 0x7A, 0xB2, 0xEB, 0x13, 0x3F, 0xD9, 0xD1, ++0x04, 0xF1, 0xE0, 0x05, 0x12, 0x31, 0x28, 0x46, 0x0A, 0x22, 0x27, 0xF0, 0x37, 0xFE, 0xC4, 0xF8, 0xDC, 0x50, 0x1A, 0xE0, ++0x93, 0xF8, 0x7E, 0x30, 0x05, 0x2B, 0xBB, 0xD1, 0x14, 0x48, 0x13, 0xF0, 0x77, 0xFF, 0x04, 0x46, 0xBF, 0xE7, 0x11, 0xF4, ++0x7C, 0x7F, 0xD5, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x10, 0x49, 0x11, 0x48, 0xD0, 0x22, 0x15, 0xF0, 0x49, 0xBB, 0x10, 0x4B, ++0x28, 0x46, 0xD3, 0xF8, 0xB4, 0x33, 0x21, 0x46, 0x98, 0x47, 0x00, 0x28, 0xB4, 0xD0, 0xA3, 0x88, 0x43, 0xF0, 0x40, 0x03, ++0xA3, 0x80, 0x38, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x06, 0x49, 0x09, 0x48, 0x40, 0xF2, 0x5F, 0x12, 0x15, 0xF0, 0x34, 0xBB, ++0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xE0, 0x63, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x50, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x3C, 0x90, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xB0, 0x4B, 0xB1, 0x4C, ++0x1B, 0x68, 0xB1, 0x4A, 0xB3, 0xF9, 0x00, 0x30, 0x2D, 0xED, 0x02, 0x8B, 0x87, 0xB0, 0x01, 0x46, 0x01, 0x90, 0x00, 0x2B, ++0x04, 0xEB, 0xC0, 0x00, 0x08, 0xEE, 0x10, 0x0A, 0x52, 0xF8, 0x21, 0x40, 0xC0, 0xF2, 0x38, 0x83, 0x20, 0x46, 0x13, 0xF0, ++0x6B, 0xFE, 0xA6, 0x4B, 0x01, 0x9A, 0x53, 0xF8, 0x32, 0x40, 0x00, 0x2C, 0x00, 0xF0, 0xAD, 0x80, 0x00, 0x23, 0xCD, 0xE9, ++0x04, 0x33, 0x9B, 0x46, 0x98, 0x46, 0xA2, 0x4B, 0x62, 0x7F, 0x93, 0xF8, 0x00, 0x32, 0x03, 0x92, 0x01, 0x2B, 0x22, 0x7F, ++0xE6, 0x6C, 0x67, 0x6C, 0x02, 0x92, 0x00, 0xF0, 0xA1, 0x80, 0x00, 0x2F, 0x00, 0xF0, 0xA8, 0x80, 0x3B, 0x79, 0xD8, 0x06, ++0x40, 0xF1, 0x95, 0x80, 0x35, 0x69, 0x59, 0x06, 0x25, 0xF4, 0x00, 0x05, 0x0B, 0xF1, 0x01, 0x0B, 0x35, 0x61, 0x00, 0xF1, ++0x9B, 0x81, 0xDF, 0xF8, 0x70, 0xA2, 0x00, 0x21, 0xDA, 0xF8, 0x18, 0x34, 0x20, 0x46, 0x98, 0x47, 0x63, 0x6A, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x08, 0xBF, 0xA0, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x8B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x38, 0x92, 0xD9, 0xF8, 0x00, 0x30, 0x18, 0xEE, 0x10, 0x0A, 0x01, 0x33, ++0xC9, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0xE4, 0xFE, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x60, 0x1F, 0x00, 0xF0, ++0x5F, 0x81, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x7F, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x22, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0x00, 0xF0, 0x30, 0x81, 0xE2, 0x6A, 0xD3, 0x6B, ++0x98, 0x06, 0x40, 0xF1, 0xFD, 0x80, 0x15, 0xF4, 0x00, 0x05, 0x00, 0xF0, 0x7E, 0x81, 0xE1, 0x6C, 0x4F, 0x6A, 0x39, 0x88, ++0x88, 0xB2, 0x09, 0x04, 0x00, 0xF1, 0xEB, 0x81, 0x71, 0x4F, 0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0x36, 0xD0, 0x63, 0x7F, ++0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x6B, 0x49, 0xA0, 0x88, ++0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x12, 0x1A, 0x41, 0xF8, 0x23, 0x20, 0x68, 0x4B, 0x93, 0xF8, 0x04, 0x31, ++0x13, 0xB1, 0x00, 0x2D, 0x40, 0xF0, 0x33, 0x82, 0x06, 0xF1, 0x10, 0x01, 0x20, 0x46, 0xFF, 0xF7, 0xC9, 0xFD, 0xE3, 0x8B, ++0xDA, 0x07, 0x00, 0xF1, 0x93, 0x81, 0xA0, 0x6C, 0x30, 0xB1, 0xF7, 0xF7, 0x4F, 0xFF, 0x3B, 0x68, 0x1D, 0x78, 0x01, 0x2D, ++0x00, 0xF0, 0xCB, 0x81, 0x9D, 0xF8, 0x04, 0x00, 0x21, 0x46, 0x15, 0xF0, 0x5B, 0xFB, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, ++0xB3, 0xF5, 0x60, 0x1F, 0x00, 0xF0, 0x74, 0x81, 0x4F, 0x4B, 0x01, 0x9A, 0x53, 0xF8, 0x32, 0x40, 0x00, 0x2C, 0x7F, 0xF4, ++0x58, 0xAF, 0x07, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0x4A, 0x00, 0x23, 0x40, 0x20, 0x82, 0xF8, ++0x00, 0x32, 0x13, 0xF0, 0x87, 0xFD, 0x00, 0x2F, 0x7F, 0xF4, 0x58, 0xAF, 0xEF, 0xF3, 0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x45, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x47, 0x4D, 0x2B, 0x68, 0x18, 0xEE, 0x10, 0x0A, 0x01, 0x33, 0x2B, 0x60, ++0x13, 0xF0, 0x5A, 0xFE, 0x2B, 0x68, 0x3B, 0xB1, 0x3E, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x13, 0xB9, 0x00, 0x2A, ++0x40, 0xF0, 0xF3, 0x81, 0x20, 0x46, 0xD6, 0xF8, 0x10, 0x90, 0x94, 0xF8, 0x1C, 0xA0, 0x23, 0xF0, 0x95, 0xFF, 0xE2, 0x6A, ++0xD3, 0x6B, 0x98, 0x06, 0x40, 0xF1, 0x8C, 0x80, 0x19, 0xF4, 0x00, 0x0F, 0x0C, 0xD0, 0xE1, 0x6C, 0x4D, 0x6A, 0x29, 0x88, ++0x88, 0xB2, 0x09, 0x04, 0x00, 0xF1, 0xFE, 0x81, 0x32, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x00, 0x2B, 0x40, 0xF0, 0x86, 0x80, ++0x31, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x53, 0x93, 0xF8, 0xC0, 0x24, 0x42, 0xB1, 0x93, 0xF8, 0xC1, 0x34, ++0x2D, 0x4F, 0x03, 0xEB, 0x83, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x07, 0xEB, 0x83, 0x07, 0x63, 0x7F, 0x09, 0x2B, 0x08, 0xD8, ++0xE3, 0x8B, 0x18, 0x07, 0x05, 0xD4, 0x09, 0xF4, 0x01, 0x09, 0xB9, 0xF5, 0x80, 0x3F, 0x00, 0xF0, 0x2B, 0x82, 0x25, 0x4F, ++0x9D, 0xF8, 0x04, 0x50, 0xD7, 0xF8, 0x18, 0x34, 0x00, 0x21, 0x20, 0x46, 0x98, 0x47, 0xD7, 0xF8, 0xAC, 0x33, 0x00, 0x22, ++0x29, 0x46, 0x20, 0x46, 0x98, 0x47, 0x22, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0x00, 0xF0, 0x05, 0x81, 0x63, 0x7F, ++0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x11, 0x49, 0xA0, 0x88, ++0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x12, 0x1A, 0x41, 0xF8, 0x23, 0x20, 0x06, 0xF1, 0x10, 0x01, 0x20, 0x46, ++0xFF, 0xF7, 0x1C, 0xFD, 0xE3, 0x8B, 0xDB, 0x07, 0x00, 0xF1, 0x08, 0x81, 0x21, 0x46, 0x28, 0x46, 0x15, 0xF0, 0xB8, 0xFA, ++0x62, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x24, 0x64, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xB7, 0x4F, 0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, ++0x3F, 0xF4, 0x44, 0xAF, 0x15, 0xF4, 0x00, 0x05, 0x7F, 0xF4, 0x09, 0xAF, 0xB4, 0xF9, 0x1E, 0x30, 0xE2, 0x8B, 0x00, 0x2B, ++0xC0, 0xF2, 0x81, 0x80, 0x00, 0x25, 0x00, 0xE7, 0xAF, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x00, 0x2B, 0x3F, 0xF4, 0x7E, 0xAF, ++0x19, 0xF4, 0x00, 0x0F, 0x3F, 0xF4, 0x7A, 0xAF, 0xE3, 0x8B, 0x1D, 0x07, 0x3F, 0xF5, 0x76, 0xAF, 0x23, 0x7F, 0xA9, 0x4D, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x53, 0x03, 0xF1, 0x98, 0x02, 0x93, 0xF8, 0x62, 0x10, 0x20, 0x46, 0xFF, 0xF7, ++0xAF, 0xFC, 0x68, 0xE7, 0x33, 0x69, 0x03, 0xF0, 0x0F, 0x03, 0x09, 0x2B, 0x7F, 0xF4, 0xCA, 0xAE, 0x03, 0x9B, 0xA0, 0x48, ++0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x00, 0x90, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x3F, 0xF6, 0xBF, 0xAE, 0xE2, 0x6C, ++0xB0, 0xF8, 0x5E, 0x12, 0xD2, 0x6A, 0x8A, 0x42, 0x3F, 0xF4, 0xB8, 0xAE, 0x01, 0x33, 0x80, 0xF8, 0x5D, 0x32, 0xA0, 0xF8, ++0x5E, 0x22, 0xB1, 0xE6, 0x95, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9B, 0x80, 0x59, 0x46, ++0x40, 0x46, 0x04, 0x9A, 0x23, 0xF0, 0xCA, 0xFE, 0x38, 0x46, 0x02, 0xF0, 0x9D, 0xF8, 0x00, 0x23, 0x04, 0x93, 0x9B, 0x46, ++0x98, 0x46, 0x8C, 0xE6, 0xD7, 0xF8, 0xDC, 0x20, 0xDA, 0xB1, 0x11, 0x88, 0x23, 0x8C, 0xA3, 0xEB, 0x11, 0x13, 0xC3, 0xF3, ++0x0B, 0x03, 0x40, 0xF2, 0xFE, 0x71, 0x8B, 0x42, 0x0C, 0xD8, 0x3F, 0x2B, 0x4F, 0xEA, 0x13, 0x11, 0x08, 0xD8, 0x02, 0xEB, ++0x41, 0x02, 0x03, 0xF0, 0x0F, 0x03, 0x52, 0x88, 0x42, 0xFA, 0x03, 0xF3, 0xDA, 0x07, 0x04, 0xD4, 0x4F, 0xF4, 0x80, 0x23, ++0x1D, 0x43, 0x35, 0x61, 0x45, 0xE6, 0x04, 0x9B, 0x01, 0x33, 0x04, 0x93, 0x4F, 0xF4, 0x04, 0x03, 0xF6, 0xE7, 0x75, 0x4F, ++0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0x3F, 0xF4, 0xBF, 0xAE, 0xB4, 0xF9, 0x1E, 0x30, 0xE2, 0x8B, 0x00, 0x2B, 0xBF, 0xF6, ++0x7F, 0xAF, 0x71, 0x4D, 0x02, 0x99, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x53, 0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, ++0x3F, 0xF4, 0x74, 0xAF, 0xE6, 0x6C, 0x01, 0x98, 0x00, 0x21, 0xC2, 0xF3, 0x0E, 0x03, 0x31, 0x65, 0x43, 0xF0, 0x01, 0x03, ++0x61, 0x64, 0x31, 0x61, 0x02, 0x9E, 0xE3, 0x83, 0x9E, 0x30, 0xA4, 0x23, 0x13, 0xFB, 0x06, 0x00, 0xE1, 0x62, 0x61, 0x62, ++0x65, 0x4A, 0x05, 0xEB, 0xC0, 0x00, 0x21, 0x46, 0x13, 0xF0, 0x60, 0xFD, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, ++0x60, 0x1F, 0x00, 0xF0, 0xE4, 0x80, 0x01, 0x23, 0x05, 0x93, 0x8B, 0xE6, 0x05, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0xDC, 0x80, ++0x40, 0x20, 0x13, 0xF0, 0x1F, 0xFC, 0x00, 0x23, 0x05, 0x93, 0x81, 0xE6, 0x40, 0x20, 0x13, 0xF0, 0x19, 0xFC, 0x68, 0xE6, ++0x33, 0x69, 0x03, 0xF0, 0x0F, 0x03, 0x09, 0x2B, 0x7F, 0xF4, 0xF5, 0xAE, 0x03, 0x9B, 0x51, 0x48, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x03, 0x00, 0x90, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x3F, 0xF6, 0xEA, 0xAE, 0xE2, 0x6C, 0xB0, 0xF8, 0x5E, 0x12, ++0xD2, 0x6A, 0x8A, 0x42, 0x3F, 0xF4, 0xE3, 0xAE, 0x01, 0x33, 0x80, 0xF8, 0x5D, 0x32, 0xA0, 0xF8, 0x5E, 0x22, 0xDC, 0xE6, ++0x40, 0x20, 0x13, 0xF0, 0xF7, 0xFB, 0xF3, 0xE6, 0xB8, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0x61, 0xAF, 0x44, 0x49, 0x45, 0x48, ++0x40, 0xF2, 0x3D, 0x22, 0x15, 0xF0, 0xE2, 0xF8, 0x59, 0xE7, 0x00, 0xF0, 0x0C, 0x00, 0x08, 0x28, 0x7F, 0xF4, 0x10, 0xAE, ++0xD7, 0xF8, 0x1A, 0x10, 0x01, 0xF0, 0x3F, 0x01, 0x07, 0x29, 0x7F, 0xF4, 0x09, 0xAE, 0x23, 0xF0, 0x20, 0x03, 0xD3, 0x63, ++0x04, 0xE6, 0x3B, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x06, 0x46, 0x00, 0x28, 0x3F, 0xF4, 0x2C, 0xAE, ++0xF7, 0xF7, 0x96, 0xFE, 0x07, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x02, 0x81, 0x00, 0x22, 0x34, 0x4B, 0x02, 0x60, 0x1B, 0x68, ++0x42, 0x60, 0x1E, 0x44, 0x82, 0x60, 0x06, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x2F, 0x4B, ++0x1D, 0x60, 0x2F, 0x49, 0xD9, 0xF8, 0x00, 0x20, 0x0B, 0x68, 0x01, 0x32, 0x43, 0xF0, 0x01, 0x03, 0xC9, 0xF8, 0x00, 0x20, ++0x0B, 0x60, 0x2A, 0x4B, 0x1B, 0x68, 0x9E, 0x07, 0xFB, 0xD4, 0x29, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xE4, 0x80, ++0x27, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xF0, 0x80, 0x25, 0x4B, 0x25, 0x4D, 0x1F, 0x60, 0x22, 0x48, 0xA9, 0x89, ++0x03, 0x68, 0x6F, 0x60, 0x01, 0x31, 0xA9, 0x81, 0x01, 0x33, 0x1E, 0x49, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, ++0x0B, 0x60, 0x00, 0x2A, 0x3F, 0xF4, 0xEC, 0xAD, 0x18, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, ++0x7F, 0xF4, 0xE4, 0xAD, 0x00, 0x2B, 0x3F, 0xF4, 0xE1, 0xAD, 0x62, 0xB6, 0xDE, 0xE5, 0x23, 0x7F, 0x09, 0x4D, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x03, 0x55, 0x05, 0xF1, 0x98, 0x02, 0x95, 0xF8, 0x62, 0x10, 0x20, 0x46, 0xFF, 0xF7, 0x70, 0xFB, ++0xBE, 0xE5, 0x62, 0xB6, 0x0A, 0xE6, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x61, 0xF1, 0x12, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x90, 0x15, 0x00, ++0x28, 0x60, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0x64, 0x00, 0x24, 0x40, ++0x68, 0x00, 0x24, 0x40, 0x10, 0x60, 0x17, 0x00, 0x00, 0xF0, 0x0C, 0x00, 0x08, 0x28, 0x7F, 0xF4, 0xFD, 0xAD, 0xD5, 0xF8, ++0x1A, 0x10, 0x01, 0xF0, 0x3F, 0x01, 0x07, 0x29, 0x7F, 0xF4, 0xF6, 0xAD, 0x23, 0xF0, 0x20, 0x03, 0xD3, 0x63, 0xF1, 0xE5, ++0x4E, 0x4D, 0x02, 0x9B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x03, 0x50, 0xFE, 0xF7, 0xB8, 0xFE, 0x00, 0x28, 0x3F, 0xF4, ++0x19, 0xAF, 0x4A, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0x13, 0xAF, 0x01, 0x9A, 0x02, 0x99, 0xA4, 0x23, ++0x02, 0xF1, 0x9E, 0x06, 0x13, 0xFB, 0x01, 0x66, 0x03, 0xFB, 0x01, 0x23, 0x03, 0xF1, 0x9E, 0x04, 0x05, 0xEB, 0xC6, 0x06, ++0xD7, 0xB2, 0xA1, 0x46, 0x0C, 0xE0, 0x13, 0xF0, 0x09, 0xFC, 0xDA, 0xF8, 0x24, 0x34, 0x20, 0x46, 0x39, 0x46, 0x98, 0x47, ++0x3B, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0xF6, 0xAE, 0x55, 0xF8, 0x39, 0x40, 0x30, 0x46, 0x00, 0x2C, ++0xED, 0xD1, 0xEF, 0xE6, 0x36, 0x4B, 0x1B, 0x68, 0x1C, 0x42, 0x7F, 0xF4, 0xC3, 0xAC, 0x35, 0x49, 0x35, 0x48, 0x4F, 0xF4, ++0xF2, 0x72, 0x14, 0xF0, 0xFD, 0xFF, 0xBB, 0xE4, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x0A, 0x59, 0x99, 0xF8, 0x64, 0x10, ++0x00, 0x29, 0x3F, 0xF4, 0xCC, 0xAD, 0x2F, 0x48, 0x03, 0x99, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, 0x01, 0x01, 0x91, 0xF8, ++0x24, 0x10, 0x01, 0x29, 0x0F, 0xD0, 0x99, 0x07, 0x2F, 0xD4, 0x00, 0x2A, 0x3F, 0xF4, 0xBD, 0xAD, 0x97, 0xF8, 0x70, 0x30, ++0x01, 0x2B, 0x7F, 0xF4, 0xB8, 0xAD, 0x97, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0xB3, 0xAD, 0xE3, 0x8B, 0xE1, 0x6C, ++0x01, 0x98, 0x22, 0x4A, 0xC3, 0xF3, 0x0E, 0x03, 0x00, 0x26, 0x43, 0xF0, 0x01, 0x03, 0x0E, 0x65, 0x0E, 0x61, 0x9E, 0x30, ++0xE3, 0x83, 0xA4, 0x23, 0x13, 0xFB, 0x0A, 0x00, 0x05, 0xEB, 0xC0, 0x00, 0xE6, 0x62, 0x21, 0x46, 0x13, 0xF0, 0xFE, 0xFB, ++0x40, 0x20, 0x13, 0xF0, 0xCB, 0xFA, 0x2F, 0xE5, 0x30, 0x46, 0xF7, 0xF7, 0x6B, 0xFC, 0x1F, 0xE5, 0x15, 0x4D, 0x6B, 0x68, ++0x9B, 0xB1, 0x5F, 0x60, 0x1E, 0xE7, 0xB4, 0xF8, 0x40, 0x00, 0x20, 0xF0, 0x75, 0xFC, 0x00, 0x28, 0xD6, 0xD0, 0x99, 0xF8, ++0xC0, 0x24, 0x00, 0x2A, 0x3F, 0xF4, 0x85, 0xAD, 0xC6, 0xE7, 0x0E, 0x48, 0x14, 0xF0, 0x2E, 0xFD, 0xD9, 0xF8, 0x00, 0x20, ++0x09, 0xE7, 0x0C, 0x48, 0x14, 0xF0, 0x28, 0xFD, 0xD9, 0xF8, 0x00, 0x20, 0x06, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x61, 0xF1, 0x12, 0x00, 0x10, 0x60, 0x17, 0x00, 0xA8, 0x90, 0x15, 0x00, 0xB0, 0x90, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x27, 0x4F, 0xDF, 0xF8, 0xA0, 0xA0, 0x91, 0x46, 0x06, 0x46, 0x0D, 0x46, 0x42, 0xF0, 0x70, 0x58, 0x28, 0x46, 0x13, 0xF0, ++0x6D, 0xFB, 0x04, 0x46, 0x80, 0xB1, 0x42, 0x6C, 0xC1, 0x6C, 0x00, 0x2A, 0x38, 0xD0, 0xC1, 0xF8, 0x10, 0x80, 0xA2, 0x88, ++0x62, 0xB9, 0x20, 0x46, 0x00, 0xF0, 0xA2, 0xF9, 0x28, 0x46, 0x13, 0xF0, 0x5D, 0xFB, 0x04, 0x46, 0x00, 0x28, 0xEE, 0xD1, ++0xBD, 0xE8, 0xF0, 0x47, 0x00, 0xF0, 0xBC, 0xB9, 0x0A, 0x69, 0x42, 0xF4, 0x00, 0x02, 0x41, 0xF8, 0x10, 0x2F, 0x20, 0x46, ++0xFF, 0xF7, 0x7E, 0xFA, 0xD7, 0xF8, 0x18, 0x34, 0x01, 0x21, 0x20, 0x46, 0x98, 0x47, 0x63, 0x7F, 0x09, 0x2B, 0x0D, 0xD8, ++0xE2, 0x7E, 0x08, 0x2A, 0x0A, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x03, 0xF6, 0x0E, 0x03, 0xA1, 0x88, 0x5A, 0xF8, ++0x23, 0x20, 0x52, 0x1A, 0x4A, 0xF8, 0x23, 0x20, 0x31, 0x46, 0x20, 0x46, 0xD7, 0xF8, 0x78, 0x33, 0x98, 0x47, 0x21, 0x46, ++0x30, 0x46, 0x15, 0xF0, 0x03, 0xF8, 0xBD, 0xE7, 0x0A, 0x69, 0x00, 0x2A, 0xA8, 0xBF, 0xC1, 0xF8, 0x10, 0x90, 0xC2, 0xE7, ++0x88, 0x1A, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x6C, 0x80, 0x92, 0x46, 0x06, 0x46, ++0x0F, 0x46, 0x42, 0xF0, 0x70, 0x59, 0x38, 0x46, 0x13, 0xF0, 0x18, 0xFB, 0x04, 0x46, 0xF0, 0xB1, 0x42, 0x6C, 0xC3, 0x6C, ++0x12, 0xB3, 0xC3, 0xF8, 0x10, 0x90, 0xA2, 0x88, 0x00, 0x21, 0x20, 0x46, 0xCA, 0xB1, 0x1D, 0x69, 0x45, 0xF4, 0x00, 0x05, ++0x1D, 0x61, 0xD8, 0xF8, 0x18, 0x34, 0x98, 0x47, 0xD8, 0xF8, 0x78, 0x33, 0x20, 0x46, 0x31, 0x46, 0x98, 0x47, 0x21, 0x46, ++0x30, 0x46, 0x14, 0xF0, 0xD1, 0xFF, 0x38, 0x46, 0x13, 0xF0, 0xFA, 0xFA, 0x04, 0x46, 0x00, 0x28, 0xE0, 0xD1, 0xBD, 0xE8, ++0xF0, 0x47, 0x00, 0xF0, 0x59, 0xB9, 0x00, 0xF0, 0x33, 0xF9, 0xD4, 0xE7, 0x1A, 0x69, 0x00, 0x2A, 0xA8, 0xBF, 0xC3, 0xF8, ++0x10, 0xA0, 0xD8, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x14, 0x46, 0x05, 0x46, 0x0F, 0x46, 0x60, 0x22, 0x00, 0x21, ++0x1E, 0x46, 0xF0, 0xF7, 0x07, 0xFA, 0x4F, 0xF0, 0x01, 0x0C, 0x85, 0xF8, 0x5C, 0xC0, 0x00, 0x23, 0x07, 0x49, 0x08, 0x4A, ++0xAF, 0x64, 0x07, 0xF1, 0x68, 0x00, 0xEE, 0x62, 0xEC, 0x64, 0xC4, 0xE9, 0x0F, 0x33, 0x60, 0x62, 0x61, 0x61, 0x23, 0x63, ++0x63, 0x64, 0x32, 0x60, 0xF8, 0xBD, 0x00, 0xBF, 0xBE, 0xBA, 0xFE, 0xCA, 0x1E, 0xAB, 0xDC, 0xBA, 0x2D, 0xE9, 0xF8, 0x4F, ++0x07, 0x46, 0x3C, 0x48, 0x3C, 0x4C, 0xDF, 0xF8, 0x08, 0xA1, 0x3C, 0x4E, 0x3C, 0x4D, 0xDF, 0xF8, 0x04, 0xB1, 0x81, 0x46, ++0x13, 0xF0, 0x70, 0xFA, 0x09, 0xF1, 0x08, 0x00, 0x13, 0xF0, 0x6C, 0xFA, 0x04, 0xF5, 0xC0, 0x78, 0x00, 0x21, 0x20, 0x46, ++0x60, 0x22, 0x17, 0xB1, 0x94, 0xF8, 0x5D, 0x30, 0xC3, 0xB9, 0xF0, 0xF7, 0xD1, 0xF9, 0x00, 0x22, 0x32, 0x4B, 0xC4, 0xF8, ++0x48, 0xA0, 0x0A, 0xF1, 0x68, 0x0C, 0xC5, 0xE9, 0x0F, 0x22, 0x21, 0x46, 0x48, 0x46, 0xE6, 0x62, 0xE5, 0x64, 0xC5, 0xF8, ++0x14, 0xB0, 0x33, 0x60, 0x84, 0xF8, 0x5C, 0x20, 0x2A, 0x63, 0x6A, 0x64, 0xC5, 0xF8, 0x24, 0xC0, 0x13, 0xF0, 0x4E, 0xFA, ++0x60, 0x34, 0xA0, 0x45, 0x0A, 0xF5, 0xF4, 0x7A, 0x06, 0xF1, 0x40, 0x06, 0x05, 0xF1, 0x58, 0x05, 0xD6, 0xD1, 0x24, 0x4E, ++0xDF, 0xF8, 0x88, 0x90, 0xC6, 0xF8, 0x00, 0x90, 0x00, 0x24, 0xC6, 0xE9, 0x0D, 0x44, 0xF4, 0x63, 0xF1, 0xF7, 0x8E, 0xFA, ++0x80, 0x03, 0x70, 0x60, 0xF1, 0xF7, 0x8A, 0xFA, 0x01, 0x27, 0x43, 0x1C, 0x07, 0xFA, 0x03, 0xF3, 0x1B, 0x4D, 0xDF, 0xF8, ++0x78, 0x80, 0xF4, 0x60, 0x01, 0x3B, 0xB3, 0x60, 0x4F, 0xF4, 0x80, 0x63, 0xC6, 0xE9, 0x04, 0x83, 0xC6, 0xE9, 0x06, 0x44, ++0x34, 0x62, 0xC5, 0xF8, 0x00, 0x90, 0xC6, 0xE9, 0x0A, 0x44, 0xC5, 0xE9, 0x0D, 0x44, 0x34, 0x63, 0xEC, 0x63, 0xF1, 0xF7, ++0x6F, 0xFA, 0x80, 0x03, 0x68, 0x60, 0xF1, 0xF7, 0x6B, 0xFA, 0x38, 0x44, 0x87, 0x40, 0x01, 0x3F, 0x04, 0x23, 0xC5, 0xE9, ++0x02, 0x74, 0xC5, 0xE9, 0x06, 0x44, 0xC5, 0xE9, 0x0A, 0x44, 0xC5, 0xF8, 0x10, 0x80, 0x2C, 0x62, 0x2C, 0x63, 0x6B, 0x61, ++0xBD, 0xE8, 0xF8, 0x8F, 0x54, 0x64, 0x17, 0x00, 0x90, 0x28, 0x17, 0x00, 0x84, 0x3B, 0x18, 0x00, 0x04, 0x3D, 0x18, 0x00, ++0x1E, 0xAB, 0xDC, 0xBA, 0xC4, 0x3C, 0x18, 0x00, 0x84, 0x3C, 0x18, 0x00, 0x4C, 0x50, 0x18, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, ++0x04, 0x07, 0xFF, 0xFF, 0xF8, 0xB5, 0xD0, 0xE9, 0x12, 0x64, 0x63, 0x6A, 0x05, 0x46, 0x50, 0x1E, 0x03, 0x44, 0x04, 0x32, ++0xC4, 0xE9, 0x0A, 0x32, 0xC1, 0xB1, 0x01, 0x29, 0x1A, 0xD0, 0x06, 0xF1, 0x28, 0x01, 0x0F, 0x46, 0x34, 0x22, 0x38, 0x46, ++0x27, 0xF0, 0xD8, 0xF8, 0x0B, 0x4A, 0x13, 0x68, 0x12, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0x00, 0x22, ++0xF3, 0x64, 0xC4, 0xE9, 0x0D, 0x27, 0xE2, 0x64, 0x22, 0x62, 0xC5, 0xE9, 0x15, 0x22, 0xF8, 0xBD, 0x04, 0x49, 0x06, 0xF1, ++0x28, 0x07, 0xE7, 0xE7, 0x03, 0x49, 0x06, 0xF1, 0x28, 0x07, 0xE3, 0xE7, 0xA0, 0x00, 0x32, 0x40, 0xC4, 0x3C, 0x18, 0x00, ++0x84, 0x3C, 0x18, 0x00, 0x70, 0xB5, 0x05, 0x46, 0x05, 0x48, 0x0E, 0x46, 0x13, 0xF0, 0xFE, 0xF9, 0x04, 0x46, 0x18, 0xB1, ++0x32, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0xC2, 0xFF, 0x20, 0x46, 0x70, 0xBD, 0x54, 0x64, 0x17, 0x00, 0x16, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x2D, 0xE9, 0xF0, 0x41, 0xC4, 0x6C, 0x00, 0x2B, 0x62, 0x6A, 0x05, 0x46, 0x0E, 0x46, 0x16, 0xDB, ++0xE3, 0x6C, 0x11, 0x4F, 0x23, 0xF4, 0xF0, 0x03, 0xE3, 0x64, 0x00, 0x23, 0xC4, 0xE9, 0x06, 0x33, 0x12, 0x79, 0x23, 0x65, ++0x12, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x4F, 0xF4, 0x00, 0x73, 0xA3, 0x64, 0xD7, 0xF8, 0x98, 0x33, 0x31, 0x46, 0x28, 0x46, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xD3, 0x07, 0xE6, 0xD5, 0x4F, 0xF4, 0xB1, 0x72, 0x05, 0x49, 0x05, 0x48, 0x14, 0xF0, ++0xD9, 0xFD, 0x62, 0x6A, 0xDE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xDC, 0x90, 0x15, 0x00, 0x08, 0xB5, 0x01, 0x46, 0x04, 0x48, 0x13, 0xF0, 0x75, 0xF9, 0xBD, 0xE8, 0x08, 0x40, 0x4F, 0xF4, ++0x80, 0x20, 0x13, 0xF0, 0xCD, 0xB8, 0x00, 0xBF, 0x5C, 0x64, 0x17, 0x00, 0x70, 0xB5, 0x90, 0xF8, 0x5C, 0x30, 0x04, 0x46, ++0x0D, 0x46, 0x43, 0xB1, 0x35, 0xB1, 0x63, 0x6D, 0x23, 0xB1, 0xA0, 0x6D, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, ++0x70, 0xBD, 0x01, 0x46, 0x01, 0x48, 0x13, 0xF0, 0x59, 0xF9, 0xF1, 0xE7, 0x54, 0x64, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x4F, 0xF4, 0x80, 0x20, 0x13, 0xF0, 0xD2, 0xF8, 0xDF, 0xF8, 0x88, 0x80, 0x1D, 0x4F, 0x1E, 0x4E, 0x1E, 0x4D, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x30, 0x46, 0x01, 0x33, ++0xC8, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0x80, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0x04, 0x46, 0x33, 0xB1, 0x01, 0x3B, 0x3A, 0x68, ++0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD4, 0xB1, 0xD5, 0xF8, 0xF8, 0x31, 0x62, 0x6D, 0x01, 0x3B, ++0xC5, 0xF8, 0xF8, 0x31, 0x32, 0xB1, 0xE3, 0x6C, 0xA0, 0x6D, 0x19, 0x6D, 0x90, 0x47, 0x94, 0xF8, 0x5E, 0x30, 0x43, 0xB9, ++0x94, 0xF8, 0x5C, 0x30, 0x00, 0x2B, 0xD2, 0xD1, 0x08, 0x48, 0x21, 0x46, 0x13, 0xF0, 0x1A, 0xF9, 0xCD, 0xE7, 0x00, 0x23, ++0x84, 0xF8, 0x5E, 0x30, 0xC9, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x5C, 0x64, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x54, 0x64, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x78, 0x91, ++0x58, 0x4D, 0x80, 0x46, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x08, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x90, 0xF8, 0x22, 0xA0, ++0x03, 0xFB, 0x0A, 0x53, 0x0F, 0x46, 0x1B, 0x6C, 0x16, 0x46, 0x00, 0x2B, 0x00, 0xF0, 0x98, 0x80, 0x50, 0x49, 0x1A, 0x79, ++0x0B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5A, 0xDB, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x53, 0x18, 0x21, ++0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xFF, 0xF7, 0x1E, 0xFF, 0x04, 0x46, 0x00, 0x28, ++0x59, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x55, 0x28, 0x46, 0x21, 0x46, 0x12, 0xF0, 0x11, 0xF8, 0x95, 0xF8, ++0x62, 0x20, 0xA3, 0x6C, 0x02, 0x2A, 0x4F, 0xD0, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x08, 0x92, 0xE8, 0x6D, 0x52, 0xF8, ++0x26, 0x1F, 0xB5, 0xF8, 0x60, 0xC0, 0xB2, 0xF8, 0x04, 0xE0, 0x15, 0x68, 0xD9, 0x66, 0x91, 0x88, 0xA3, 0xF8, 0x7C, 0x10, ++0x00, 0x22, 0x9D, 0x67, 0x01, 0x21, 0x48, 0x25, 0xA3, 0xF8, 0x70, 0xE0, 0xC3, 0xF8, 0x72, 0x00, 0xA3, 0xF8, 0x76, 0xC0, ++0x83, 0xF8, 0x6A, 0x20, 0x83, 0xF8, 0x6B, 0x20, 0x83, 0xF8, 0x68, 0x50, 0x83, 0xF8, 0x69, 0x10, 0x2E, 0x49, 0xB1, 0xF8, ++0xFC, 0x51, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x08, 0x99, 0x01, 0x35, 0xAD, 0xB2, 0xA1, 0xF8, 0xFC, 0x51, 0x99, 0xF8, ++0x22, 0x20, 0x2D, 0x01, 0xA3, 0xF8, 0x7E, 0x50, 0x20, 0x46, 0xC4, 0xE9, 0x15, 0x76, 0x22, 0x77, 0x84, 0xF8, 0x1D, 0x80, ++0x05, 0x21, 0xFF, 0xF7, 0xE3, 0xFE, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x02, 0x2A, 0xA2, 0xD1, 0x20, 0x49, 0x21, 0x48, ++0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0xDC, 0xFC, 0x01, 0x20, 0x18, 0x21, 0xFF, 0xF7, 0xC4, 0xFE, 0x04, 0x46, 0x00, 0x28, ++0xA5, 0xD1, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x08, 0x91, 0xE8, 0x6D, 0x51, 0xF8, ++0x26, 0xEF, 0x83, 0xF8, 0x69, 0x20, 0x89, 0x88, 0xA3, 0xF8, 0x70, 0x10, 0x00, 0x22, 0xB5, 0xF8, 0x60, 0x10, 0xC3, 0xF8, ++0x72, 0x00, 0x4F, 0xF0, 0x48, 0x0C, 0xE8, 0x6D, 0x83, 0xF8, 0x6A, 0x20, 0x83, 0xF8, 0x6B, 0x20, 0xB5, 0xF8, 0x60, 0x20, ++0xC3, 0xF8, 0x6C, 0xE0, 0x83, 0xF8, 0x68, 0xC0, 0xA3, 0xF8, 0x76, 0x10, 0x98, 0x67, 0xA3, 0xF8, 0x7C, 0x20, 0xAD, 0xE7, ++0x04, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCB, 0xDA, 0xC4, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x38, 0xB1, 0x49, 0x4C, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0xB5, 0x06, 0x46, ++0x95, 0xF8, 0x22, 0x70, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x07, 0x40, 0x98, 0x46, 0x00, 0x6C, 0x43, 0x4B, 0x8A, 0x46, ++0x91, 0x46, 0x00, 0x28, 0x7A, 0xD0, 0x1B, 0x68, 0x02, 0x79, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x62, 0xDB, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x07, 0x43, 0x1A, 0x21, 0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, ++0xFF, 0xF7, 0x5C, 0xFE, 0x05, 0x46, 0x00, 0x28, 0x61, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x47, 0x38, 0x46, ++0x29, 0x46, 0x11, 0xF0, 0x4F, 0xFF, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0xB3, 0xAC, 0x6C, 0x53, 0xF8, 0x26, 0x1F, ++0x97, 0xF8, 0x62, 0xC0, 0xB3, 0xF8, 0x04, 0xE0, 0xF8, 0x6D, 0xB7, 0xF8, 0x60, 0x20, 0xA4, 0xF8, 0x76, 0x20, 0x00, 0x23, ++0xA4, 0xF8, 0x70, 0xE0, 0xE1, 0x66, 0xC4, 0xF8, 0x72, 0x00, 0x84, 0xF8, 0x6A, 0x30, 0x84, 0xF8, 0x6B, 0x30, 0xBC, 0xF1, ++0x00, 0x0F, 0x22, 0xD0, 0xF8, 0x6D, 0xA0, 0x67, 0x6F, 0xF0, 0x37, 0x01, 0x02, 0x23, 0xA4, 0xF8, 0x7C, 0x20, 0x84, 0xF8, ++0x68, 0x10, 0x84, 0xF8, 0x69, 0x30, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0xBB, 0x00, 0x27, 0x9B, 0xF8, 0x22, 0x30, ++0xA4, 0xF8, 0x80, 0xA0, 0x84, 0xF8, 0x7E, 0x70, 0x84, 0xF8, 0x7F, 0x70, 0x28, 0x46, 0xC5, 0xE9, 0x15, 0x98, 0x2B, 0x77, ++0x6E, 0x77, 0x05, 0x21, 0xFF, 0xF7, 0x24, 0xFE, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x6F, 0xF0, 0x37, 0x02, 0x01, 0x23, ++0xA1, 0x67, 0xA4, 0xF8, 0x7C, 0xE0, 0x84, 0xF8, 0x68, 0x20, 0x84, 0xF8, 0x69, 0x30, 0xDC, 0xE7, 0x02, 0x2A, 0x9A, 0xD1, ++0x0C, 0x49, 0x0D, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0x12, 0xFC, 0x01, 0x20, 0x1A, 0x21, 0xFF, 0xF7, 0xFA, 0xFD, ++0x05, 0x46, 0x00, 0x28, 0x9D, 0xD1, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xF0, 0xDA, 0xE9, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x9C, 0xA1, 0xDF, 0xF8, 0x9C, 0x81, 0x4F, 0xF4, 0x1E, 0x76, ++0x06, 0xFB, 0x00, 0xA6, 0x05, 0x46, 0x96, 0xF8, 0x22, 0x90, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x09, 0x80, 0x83, 0xB0, ++0x00, 0x6C, 0x00, 0x93, 0x0E, 0x1E, 0x17, 0x46, 0x9D, 0xF8, 0x30, 0x40, 0x9D, 0xF8, 0x34, 0xB0, 0x55, 0x4A, 0x0C, 0xBF, ++0x1E, 0x23, 0x1D, 0x23, 0x00, 0x28, 0x00, 0xF0, 0x9D, 0x80, 0x12, 0x68, 0x01, 0x79, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, ++0xC0, 0xF2, 0x85, 0x80, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x82, 0x92, 0xF8, 0xC0, 0x24, 0x0A, 0x43, 0x14, 0xBF, ++0x01, 0x20, 0x00, 0x20, 0x19, 0x46, 0xFF, 0xF7, 0xAF, 0xFD, 0x03, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x81, 0x80, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x09, 0x88, 0xD0, 0xF8, 0x48, 0x90, 0x01, 0x93, 0x40, 0x46, 0x19, 0x46, 0x11, 0xF0, 0x9E, 0xFE, ++0xD9, 0xF8, 0x38, 0x00, 0x01, 0x9B, 0x40, 0x4A, 0x99, 0x6C, 0xB8, 0xF8, 0x60, 0xE0, 0x00, 0x0C, 0x4F, 0xF0, 0x00, 0x0C, ++0x46, 0xEA, 0x07, 0x17, 0x00, 0x04, 0xC9, 0xF8, 0x38, 0x00, 0xD8, 0xF8, 0x5C, 0x00, 0x8F, 0x67, 0x81, 0xF8, 0x7C, 0xC0, ++0x81, 0xF8, 0x7D, 0xC0, 0x81, 0xF8, 0x7E, 0xC0, 0x81, 0xF8, 0x7F, 0xC0, 0x92, 0xF8, 0x43, 0x70, 0xDF, 0xF8, 0xE8, 0x80, ++0xC1, 0xF8, 0x72, 0x00, 0x24, 0x20, 0xB8, 0xF8, 0x04, 0x20, 0xA1, 0xF8, 0x76, 0xE0, 0x81, 0xF8, 0x68, 0x00, 0xD8, 0xF8, ++0x00, 0xE0, 0xA1, 0xF8, 0x70, 0x20, 0xB8, 0x06, 0xC1, 0xF8, 0x6C, 0xE0, 0x81, 0xF8, 0x69, 0xC0, 0x81, 0xF8, 0x6A, 0xC0, ++0x81, 0xF8, 0x6B, 0xC0, 0xC7, 0xF3, 0x40, 0x12, 0x0B, 0xD5, 0x27, 0x48, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x05, 0x02, ++0x52, 0x78, 0x12, 0xF0, 0x20, 0x0F, 0x0C, 0xBF, 0x62, 0x46, 0x4F, 0xF4, 0x80, 0x12, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x05, 0xA5, 0x64, 0x05, 0x28, 0x8C, 0x00, 0x9D, 0x44, 0xEA, 0x45, 0x34, 0x04, 0x43, 0x14, 0x43, 0xD8, 0x22, 0xC1, 0xF8, ++0x80, 0x40, 0x81, 0xF8, 0x84, 0x20, 0x6E, 0xB1, 0x0E, 0x9A, 0x5A, 0x65, 0x0F, 0x9A, 0x9A, 0x65, 0x59, 0x46, 0x18, 0x46, ++0xFF, 0xF7, 0x54, 0xFD, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x4A, 0x12, 0xF8, ++0x0B, 0x20, 0x92, 0x01, 0x81, 0xF8, 0x85, 0x20, 0xEA, 0xE7, 0x02, 0x29, 0x7F, 0xF4, 0x78, 0xAF, 0x0E, 0x48, 0x0F, 0x49, ++0x01, 0x93, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0x41, 0xFB, 0x01, 0x9B, 0x01, 0x20, 0x77, 0xE7, 0x01, 0x20, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xEC, 0xDB, 0x01, 0x20, 0x6C, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x62, 0x66, 0x17, 0x00, 0xA0, 0xB2, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xAC, 0xB2, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0x90, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x77, 0xD1, 0x03, 0x6C, 0x04, 0x46, 0x89, 0x46, 0x00, 0x2B, 0x79, 0xD0, 0x40, 0x4A, ++0x1B, 0x79, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x51, 0xDB, 0x94, 0xF8, 0xC0, 0x24, 0xDF, 0xF8, 0x08, 0x81, ++0x13, 0x43, 0xB8, 0xF8, 0x00, 0x10, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xFF, 0xF7, 0xEE, 0xFC, 0x06, 0x46, 0x00, 0x28, ++0x54, 0xD0, 0x01, 0x46, 0x20, 0x46, 0x11, 0xF0, 0xE5, 0xFD, 0xB5, 0x6C, 0x00, 0x27, 0x50, 0x23, 0x49, 0x46, 0x85, 0xF8, ++0x68, 0x30, 0x85, 0xF8, 0x69, 0x70, 0x85, 0xF8, 0x6A, 0x70, 0x85, 0xF8, 0x6B, 0x70, 0x05, 0xF1, 0x6C, 0x00, 0x06, 0x22, ++0x26, 0xF0, 0x90, 0xFD, 0x2B, 0x49, 0xE0, 0x6D, 0xB1, 0xF8, 0xFC, 0x31, 0xB4, 0xF8, 0x60, 0xC0, 0xB8, 0xF8, 0x00, 0x20, ++0xB4, 0xF8, 0x60, 0xE0, 0xC5, 0xF8, 0x72, 0x00, 0x01, 0x33, 0x9B, 0xB2, 0xE0, 0x6D, 0xA5, 0xF8, 0x76, 0xC0, 0x4F, 0xEA, ++0x03, 0x1C, 0xA8, 0x67, 0xA5, 0xF8, 0x7C, 0xE0, 0x18, 0x3A, 0xA1, 0xF8, 0xFC, 0x31, 0x05, 0xF1, 0x80, 0x00, 0xA5, 0xF8, ++0x7E, 0xC0, 0x1E, 0x49, 0x26, 0xF0, 0x70, 0xFD, 0xC6, 0xE9, 0x15, 0x77, 0x94, 0xF8, 0x63, 0x30, 0x33, 0x77, 0xFF, 0x23, ++0x73, 0x77, 0x30, 0x46, 0x05, 0x21, 0xFF, 0xF7, 0xBB, 0xFC, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x2B, 0xAB, 0xD1, ++0x15, 0x49, 0x16, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0xB4, 0xFA, 0xDF, 0xF8, 0x58, 0x80, 0x01, 0x20, 0xB8, 0xF8, ++0x00, 0x10, 0xFF, 0xF7, 0x99, 0xFC, 0x06, 0x46, 0x00, 0x28, 0xAA, 0xD1, 0xB8, 0xF8, 0x00, 0x10, 0x0E, 0x48, 0x14, 0xF0, ++0x2B, 0xF8, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x48, 0x19, 0x46, 0x14, 0xF0, 0x24, 0xF8, 0x01, 0x20, 0xBD, 0xE8, ++0xF8, 0x83, 0x03, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE0, 0xDA, 0xD9, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x2C, 0x2A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0x28, 0x91, 0x15, 0x00, ++0x14, 0x91, 0x15, 0x00, 0x14, 0x2C, 0x17, 0x00, 0x02, 0x4B, 0x40, 0xEA, 0x41, 0x01, 0x33, 0xF8, 0x11, 0x00, 0x70, 0x47, ++0xA0, 0x92, 0x15, 0x00, 0x02, 0x4B, 0x40, 0xEA, 0x41, 0x01, 0x58, 0x5C, 0x70, 0x47, 0x00, 0xBF, 0x40, 0x93, 0x15, 0x00, ++0xF0, 0xB4, 0x1D, 0x4C, 0x1D, 0x4D, 0x1E, 0x4F, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x02, 0x42, 0x16, 0x46, 0x92, 0xF8, ++0x22, 0x40, 0x4F, 0xF4, 0xA4, 0x6C, 0x0C, 0xFB, 0x04, 0x54, 0x56, 0xF8, 0x26, 0x5F, 0xB4, 0xF8, 0x60, 0xC0, 0x02, 0x46, ++0xE0, 0x6D, 0xB4, 0x88, 0xA2, 0xF8, 0x9C, 0x40, 0x00, 0x24, 0x54, 0x65, 0xC2, 0xF8, 0x8C, 0x40, 0x3C, 0x68, 0x3E, 0x68, ++0x9D, 0xF8, 0x10, 0x70, 0xC2, 0xF8, 0x9E, 0x00, 0x24, 0x02, 0xF6, 0xB2, 0x1B, 0x03, 0xA4, 0xB2, 0x40, 0xF6, 0x08, 0x00, ++0x34, 0x43, 0x40, 0xEA, 0xC7, 0x10, 0x43, 0xF0, 0x04, 0x03, 0x09, 0x01, 0xC2, 0xF8, 0x98, 0x50, 0xC2, 0xF8, 0xCC, 0x40, ++0xA2, 0xF8, 0xA2, 0xC0, 0xF0, 0xBC, 0xA2, 0xF8, 0xA4, 0x30, 0xA2, 0xF8, 0xA6, 0x10, 0xC2, 0xF8, 0xBC, 0x00, 0x70, 0x47, ++0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0xC2, 0x6C, 0x53, 0x6A, 0x13, 0xB3, 0x12, 0x49, ++0x12, 0x4B, 0xC9, 0x6E, 0x10, 0xB5, 0x04, 0x46, 0x18, 0x68, 0x63, 0x6A, 0x92, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, ++0x60, 0x1F, 0x42, 0xF8, 0x03, 0x1C, 0x08, 0xD0, 0xB0, 0xF9, 0x00, 0x30, 0x24, 0x68, 0x00, 0x2B, 0x04, 0xDB, 0xE2, 0x6C, ++0x53, 0x6A, 0x00, 0x2B, 0xED, 0xD1, 0x10, 0xBD, 0x00, 0x2C, 0xF8, 0xD1, 0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xF9, 0x22, ++0x14, 0xF0, 0x0E, 0xFA, 0xE3, 0x6C, 0xFF, 0xDE, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x04, 0x46, 0x9D, 0xF8, 0x48, 0x00, ++0x67, 0x6C, 0x07, 0x90, 0x9B, 0x46, 0x05, 0x28, 0x4F, 0xF0, 0x00, 0x03, 0x06, 0x91, 0x03, 0x92, 0x9A, 0x46, 0x00, 0xF0, ++0x12, 0x81, 0xAA, 0x4A, 0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x04, 0x93, 0xDF, 0xF8, ++0xC8, 0x92, 0xA6, 0x48, 0x12, 0xF0, 0xD4, 0xFD, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, ++0xC0, 0xF2, 0xF3, 0x80, 0xBB, 0x88, 0xAB, 0x80, 0x7B, 0x7A, 0x6B, 0x72, 0xBB, 0x7A, 0xAB, 0x72, 0x01, 0x23, 0xEB, 0x72, ++0xD7, 0xE9, 0x10, 0xC0, 0xFE, 0x6A, 0x79, 0x69, 0x3A, 0x6B, 0xEE, 0x62, 0x00, 0x23, 0x1E, 0x46, 0x69, 0x61, 0x6B, 0x62, ++0x19, 0x46, 0x98, 0x46, 0x02, 0x93, 0x05, 0xF1, 0x0C, 0x03, 0xC5, 0xE9, 0x10, 0xC0, 0x2A, 0x63, 0x05, 0x93, 0x01, 0x96, ++0x53, 0xE0, 0x9B, 0x45, 0x40, 0xF2, 0xB4, 0x80, 0xAB, 0xEB, 0x03, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x0A, 0xF1, 0x03, 0x0A, ++0x4F, 0xEA, 0x9A, 0x0A, 0x03, 0xEB, 0x8A, 0x03, 0x9B, 0xB2, 0x03, 0x9E, 0x19, 0x44, 0xB1, 0x42, 0x5A, 0xD8, 0xB8, 0xF1, ++0x00, 0x0F, 0x57, 0xD1, 0xDE, 0xF8, 0x24, 0x00, 0x28, 0xB1, 0x87, 0x4E, 0xDE, 0xF8, 0x28, 0x00, 0xF6, 0x6E, 0x40, 0xF8, ++0x03, 0x6C, 0xDC, 0x45, 0x65, 0x64, 0x0D, 0xD2, 0xDE, 0xF8, 0x4C, 0x20, 0x22, 0xF4, 0xFF, 0x22, 0x22, 0xF4, 0xC0, 0x62, ++0x42, 0xEA, 0x4A, 0x22, 0x42, 0xF4, 0x80, 0x70, 0x62, 0x62, 0x63, 0x46, 0xCE, 0xF8, 0x4C, 0x00, 0x69, 0x62, 0x79, 0x6A, ++0x02, 0xF4, 0x60, 0x12, 0xCB, 0x1A, 0xB2, 0xF5, 0x60, 0x1F, 0x7B, 0x62, 0x00, 0xF0, 0xAA, 0x80, 0x77, 0x4A, 0xD9, 0xF8, ++0x00, 0x30, 0x11, 0x68, 0x76, 0x4A, 0x91, 0xF8, 0x3E, 0x80, 0x12, 0x68, 0xB3, 0xF9, 0x00, 0x10, 0x23, 0x68, 0x02, 0xF0, ++0x3F, 0x02, 0x90, 0x45, 0x94, 0xBF, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x01, 0x08, 0x00, 0x29, 0x5D, 0xDB, 0x01, 0x9A, ++0x69, 0x6A, 0x02, 0x94, 0x01, 0x32, 0x01, 0x92, 0x1C, 0x46, 0xD4, 0xF8, 0x4C, 0xE0, 0x62, 0x6A, 0xDE, 0xF8, 0x2C, 0x30, ++0x9D, 0xF8, 0x04, 0x00, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0xC2, 0xF3, 0x49, 0x2C, 0x03, 0xEB, ++0x8C, 0x0C, 0x1F, 0xFA, 0x8C, 0xFC, 0xDC, 0x45, 0x97, 0xD3, 0x03, 0x9E, 0x63, 0x46, 0x19, 0x44, 0xB1, 0x42, 0xA4, 0xD9, ++0x02, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0xA2, 0x80, 0x02, 0x9B, 0x5B, 0x6A, 0x03, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x20, 0x1F, ++0x41, 0xD0, 0x02, 0x9E, 0xF2, 0x6C, 0x43, 0xF4, 0x60, 0x11, 0x43, 0xF4, 0x60, 0x13, 0x50, 0x73, 0xC5, 0xF8, 0x38, 0x61, ++0x73, 0x62, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x41, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x00, 0x2B, 0xD1, 0x64, ++0xD0, 0x61, 0x3D, 0xDB, 0x04, 0x9A, 0x92, 0xF8, 0x50, 0x30, 0x01, 0x33, 0x82, 0xF8, 0x50, 0x30, 0x63, 0x6A, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x60, 0x1F, 0x73, 0xD0, 0x1C, 0x32, 0x16, 0x46, 0x48, 0x4B, 0x06, 0x9A, 0x1B, 0x68, 0x14, 0x60, ++0x5B, 0x78, 0x13, 0xB9, 0x63, 0x6C, 0x0C, 0x33, 0x2B, 0x61, 0x29, 0x46, 0x30, 0x46, 0x12, 0xF0, 0xE7, 0xFC, 0x05, 0x98, ++0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2B, 0x9F, 0xD1, 0x40, 0x49, 0x40, 0x48, 0x02, 0x93, 0x40, 0xF2, 0xBD, 0x32, ++0x14, 0xF0, 0x0A, 0xF9, 0x02, 0x9B, 0x96, 0xE7, 0x4F, 0xF0, 0x00, 0x0A, 0x53, 0xE7, 0x02, 0x9E, 0x3B, 0x4B, 0x01, 0x21, ++0xD3, 0xF8, 0x58, 0x33, 0x30, 0x46, 0x98, 0x47, 0xF3, 0x6C, 0x75, 0x64, 0x14, 0x33, 0x05, 0x93, 0xD9, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC1, 0xDA, 0x04, 0x9B, 0xDB, 0x69, 0x9F, 0x42, 0xBD, 0xD0, 0x2F, 0x49, 0x32, 0x48, ++0x40, 0xF2, 0xC3, 0x32, 0x14, 0xF0, 0xEA, 0xF8, 0xB6, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0x0A, 0xAF, 0x2A, 0x49, 0x2E, 0x48, ++0x40, 0xF2, 0x27, 0x32, 0x14, 0xF0, 0xE0, 0xF8, 0x02, 0xE7, 0x2C, 0x4B, 0x04, 0x93, 0xF2, 0xE6, 0xD9, 0xF8, 0x00, 0x30, ++0xC5, 0xF8, 0x38, 0x41, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x16, 0xDB, 0x04, 0x9E, 0x1C, 0x36, 0x30, 0x46, 0x12, 0xF0, ++0xBF, 0xFC, 0x1E, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0x0B, 0xB9, 0x3B, 0x69, 0x2B, 0x61, 0x39, 0x46, 0xD7, 0xF8, 0x48, 0x01, ++0x12, 0xF0, 0x70, 0xFC, 0x06, 0x99, 0x22, 0x68, 0xE3, 0x6C, 0x0A, 0x60, 0x00, 0x22, 0xDA, 0x61, 0xA1, 0xE7, 0x04, 0x9B, ++0xDB, 0x69, 0xBB, 0x42, 0xE4, 0xD0, 0x14, 0x49, 0x16, 0x48, 0x40, 0xF2, 0xC3, 0x32, 0x14, 0xF0, 0xB3, 0xF8, 0xDD, 0xE7, ++0x04, 0x9E, 0x1C, 0x36, 0x30, 0x46, 0x12, 0xF0, 0x9D, 0xFC, 0x87, 0xE7, 0x0F, 0x4B, 0x07, 0x99, 0xD3, 0xF8, 0xBC, 0x33, ++0x07, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0x02, 0x9B, 0xD5, 0xF8, 0x48, 0x01, 0x05, 0x93, 0x29, 0x46, 0x12, 0xF0, 0x4A, 0xFC, ++0x85, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x8C, 0x64, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, ++0x54, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x64, 0x91, 0x15, 0x00, 0x4C, 0x91, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x0C, 0x46, 0x41, 0x7F, 0x63, 0x7F, 0x99, 0x42, 0x85, 0xB0, 0x05, 0xD1, 0xE3, 0x7E, 0x16, 0x46, 0xC2, 0x7E, 0x9A, 0x42, ++0x05, 0x46, 0x03, 0xD0, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD4, 0xE9, 0x11, 0x73, 0x00, 0x2B, 0x00, 0xF0, ++0x8F, 0x80, 0xBB, 0x88, 0x13, 0xF0, 0x08, 0x00, 0xF3, 0xD0, 0x13, 0xF0, 0x02, 0x00, 0xF0, 0xD0, 0x13, 0xF0, 0x01, 0x00, ++0x40, 0xF0, 0x86, 0x80, 0xDF, 0xF8, 0x4C, 0x91, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x93, 0x93, 0xF8, 0x4D, 0x20, 0x01, 0x2A, ++0xE3, 0xD0, 0xD3, 0xF8, 0x34, 0x80, 0xD8, 0xE9, 0x12, 0xBA, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0xDA, 0xF8, 0x20, 0x20, ++0x46, 0x4B, 0x12, 0x68, 0x9A, 0x42, 0xD6, 0xD1, 0x45, 0x4A, 0x46, 0x4B, 0x11, 0x68, 0x1A, 0x68, 0x91, 0xF8, 0x3E, 0x30, ++0x91, 0xF8, 0x3F, 0x10, 0x02, 0xF0, 0x3F, 0x02, 0x0B, 0x44, 0x9A, 0x42, 0xC8, 0xDD, 0xD8, 0xF8, 0x24, 0x20, 0x54, 0x23, ++0x03, 0xFB, 0x06, 0x93, 0x42, 0xF4, 0x60, 0x12, 0x18, 0x6B, 0xC8, 0xF8, 0x24, 0x20, 0xC7, 0xF8, 0x38, 0x81, 0x03, 0x93, ++0x03, 0xF0, 0xE0, 0xF8, 0x39, 0x4A, 0x03, 0x9B, 0x12, 0x68, 0x93, 0xF8, 0x4D, 0x10, 0x8A, 0xF8, 0x0D, 0x10, 0x52, 0x78, ++0x00, 0x2A, 0x4F, 0xD1, 0xEB, 0x6C, 0x3A, 0x61, 0xD9, 0x6C, 0xCA, 0xE9, 0x06, 0x22, 0x8A, 0x02, 0x44, 0xD5, 0x6B, 0x6C, ++0x07, 0xF1, 0x0C, 0x01, 0x19, 0x61, 0x54, 0x23, 0x03, 0xFB, 0x06, 0xF3, 0x0A, 0xF1, 0x14, 0x00, 0x09, 0xEB, 0x03, 0x02, ++0x49, 0xF8, 0x03, 0x00, 0x01, 0x23, 0xC2, 0xE9, 0x01, 0x13, 0xD8, 0xF8, 0x24, 0x30, 0xBA, 0x88, 0x43, 0xF4, 0x80, 0x73, ++0xCA, 0xF8, 0x4C, 0x30, 0x42, 0xF0, 0x01, 0x03, 0xBB, 0x80, 0xBB, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x50, 0x07, 0x06, 0xD4, ++0x11, 0x07, 0x37, 0xD4, 0xA1, 0x6C, 0x4A, 0x6A, 0x42, 0xF0, 0x04, 0x02, 0x4A, 0x62, 0x9B, 0x07, 0x06, 0xD5, 0x54, 0x23, ++0x03, 0xFB, 0x06, 0x93, 0x3A, 0x6B, 0x1B, 0x6B, 0x9B, 0x6A, 0x53, 0x61, 0x54, 0x24, 0x04, 0xFB, 0x06, 0x90, 0x04, 0xFB, ++0x06, 0x96, 0x1C, 0x30, 0x39, 0x46, 0x12, 0xF0, 0x91, 0xFB, 0x96, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x33, 0xF2, 0x62, ++0x86, 0xF8, 0x50, 0x30, 0x01, 0x20, 0x68, 0xE7, 0xBB, 0x88, 0x72, 0xE7, 0x01, 0x20, 0x64, 0xE7, 0x07, 0xF1, 0x0C, 0x01, ++0x99, 0x61, 0xBA, 0xE7, 0xB8, 0x7A, 0x93, 0xF8, 0x4E, 0x30, 0x7A, 0x7A, 0xB8, 0xF8, 0x22, 0x10, 0x00, 0x93, 0x03, 0x46, ++0x38, 0x46, 0xFF, 0xF7, 0x55, 0xFD, 0x07, 0xF1, 0x50, 0x03, 0xCA, 0xF8, 0x1C, 0x30, 0xB6, 0xE7, 0x42, 0xF0, 0x03, 0x03, ++0xBB, 0x80, 0xC8, 0xE7, 0xDE, 0xFA, 0xFE, 0xCA, 0xC8, 0x35, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x45, 0x6C, 0x0C, 0x68, 0x6E, 0x7A, 0x60, 0x7F, 0x9D, 0xF8, 0x20, 0x70, ++0x86, 0x42, 0x03, 0xD1, 0xAE, 0x7A, 0xE0, 0x7E, 0x86, 0x42, 0x02, 0xD0, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xE6, 0x6C, ++0xD5, 0xF8, 0x38, 0xE1, 0xD6, 0xF8, 0x24, 0xC0, 0xDE, 0xF8, 0x4C, 0x80, 0xBC, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x82, 0x80, ++0xBC, 0xF8, 0x00, 0x90, 0x19, 0xF4, 0x00, 0x4F, 0x1F, 0xFA, 0x89, 0xF0, 0x7A, 0xD1, 0x6F, 0xEA, 0x40, 0x40, 0x6F, 0xEA, ++0x50, 0x40, 0xAC, 0xF8, 0x00, 0x00, 0x94, 0xF8, 0x33, 0x90, 0x94, 0xF8, 0x32, 0x00, 0x09, 0xF1, 0x04, 0x09, 0x04, 0x30, ++0x84, 0xF8, 0x33, 0x90, 0x84, 0xF8, 0x32, 0x00, 0xF0, 0x6A, 0x00, 0xF1, 0x04, 0x0A, 0xB0, 0x6A, 0x00, 0xF1, 0x04, 0x09, ++0xC6, 0xE9, 0x0A, 0x9A, 0x0A, 0xF1, 0x03, 0x00, 0x20, 0xF0, 0x03, 0x00, 0x04, 0x30, 0x80, 0xB2, 0x83, 0x42, 0x5C, 0xD9, ++0xA3, 0xEB, 0x00, 0x09, 0x1F, 0xFA, 0x89, 0xF9, 0x09, 0xF1, 0x03, 0x09, 0x4F, 0xEA, 0x99, 0x09, 0x00, 0xEB, 0x89, 0x00, ++0x80, 0xB2, 0x6B, 0x6A, 0x18, 0x44, 0x90, 0x42, 0xBA, 0xD8, 0x28, 0x4A, 0xDE, 0xF8, 0x24, 0x30, 0x4F, 0xF0, 0x54, 0x0A, ++0x0A, 0xFB, 0x07, 0x27, 0x23, 0xF4, 0xC0, 0x13, 0x97, 0xF8, 0x50, 0x20, 0xDF, 0xF8, 0x90, 0xA0, 0x01, 0x3A, 0x87, 0xF8, ++0x50, 0x20, 0x43, 0xF4, 0x40, 0x12, 0xCE, 0xF8, 0x24, 0x20, 0x62, 0x6A, 0xDA, 0xF8, 0x00, 0x70, 0xD4, 0xF8, 0x00, 0xE0, ++0x22, 0xF4, 0xC0, 0x12, 0x42, 0xEA, 0x49, 0x29, 0x43, 0xF4, 0x40, 0x13, 0x49, 0xF4, 0xF0, 0x0A, 0x43, 0xF4, 0x80, 0x73, ++0xC8, 0xF8, 0x4C, 0x30, 0x49, 0xF4, 0xF0, 0x02, 0x00, 0x23, 0x4A, 0xF4, 0x80, 0x7A, 0x06, 0xF1, 0x14, 0x09, 0xC8, 0xF8, ++0x1C, 0x90, 0x62, 0x62, 0xC6, 0xF8, 0x4C, 0xA0, 0xB3, 0x61, 0xB3, 0x63, 0x68, 0x62, 0x65, 0x64, 0xC5, 0xF8, 0x38, 0x41, ++0xC1, 0xF8, 0x00, 0xE0, 0x7B, 0x78, 0x03, 0xB9, 0x2B, 0x61, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0x09, 0x4A, 0xB3, 0x6A, ++0xD2, 0x6E, 0x43, 0xF8, 0x03, 0x2C, 0x98, 0xF8, 0x0D, 0x30, 0x01, 0x33, 0x73, 0x73, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, ++0xD6, 0xF8, 0x2C, 0xA0, 0x9A, 0xE7, 0x4F, 0xF0, 0x00, 0x09, 0xAA, 0xE7, 0x20, 0x62, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x85, 0xB0, 0xD1, 0xF8, 0x00, 0xB0, 0x9D, 0xF8, 0x38, 0x90, 0xDF, 0xF8, ++0x20, 0xA1, 0xDB, 0xF8, 0x44, 0x60, 0xDA, 0xF8, 0x60, 0x43, 0x03, 0x93, 0x0F, 0x46, 0x90, 0x46, 0x59, 0x46, 0x4A, 0x46, ++0x05, 0x46, 0xA0, 0x47, 0x00, 0x28, 0x60, 0xD0, 0xE9, 0x6C, 0x03, 0x9B, 0xCA, 0x6A, 0x02, 0xF1, 0x03, 0x0E, 0x2E, 0xF0, ++0x03, 0x0E, 0x0E, 0xF1, 0x04, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0x73, 0x45, 0x01, 0xF1, 0x14, 0x0C, 0x54, 0xD8, 0x00, 0x20, ++0x72, 0x6A, 0x0E, 0xEB, 0x02, 0x03, 0x43, 0x45, 0x05, 0xD9, 0x34, 0x4A, 0x12, 0x68, 0x02, 0xF0, 0x3F, 0x02, 0x11, 0x2A, ++0x5D, 0xD9, 0x32, 0x4A, 0x6C, 0x6A, 0x4F, 0xF0, 0x54, 0x0E, 0x0E, 0xFB, 0x09, 0x22, 0x24, 0xF4, 0xC0, 0x14, 0x92, 0xF8, ++0x50, 0xE0, 0x44, 0xEA, 0x40, 0x24, 0x0E, 0xF1, 0xFF, 0x30, 0x82, 0xF8, 0x50, 0x00, 0x44, 0xF4, 0xD0, 0x0E, 0x72, 0x69, ++0xCA, 0x61, 0xC6, 0xF8, 0x14, 0xC0, 0x73, 0x62, 0xC5, 0xF8, 0x24, 0xE0, 0xDB, 0xF8, 0x24, 0x20, 0xD6, 0xF8, 0x38, 0xC1, ++0x6E, 0x64, 0x22, 0xF4, 0xC0, 0x12, 0x74, 0x46, 0x42, 0xF4, 0x40, 0x10, 0xDB, 0xF8, 0x4C, 0xE0, 0xDC, 0xF8, 0x4C, 0xC0, ++0x44, 0xF4, 0x80, 0x74, 0xCC, 0x64, 0x42, 0xF4, 0x40, 0x12, 0x40, 0xF4, 0x80, 0x70, 0x00, 0x24, 0x8C, 0x63, 0xCB, 0xF8, ++0x24, 0x20, 0xCE, 0xF8, 0x4C, 0x00, 0x9C, 0xF8, 0x0D, 0x20, 0x43, 0x45, 0x02, 0xF1, 0x01, 0x02, 0x8C, 0xF8, 0x0D, 0x20, ++0x16, 0xD9, 0xDA, 0xF8, 0x70, 0x63, 0x03, 0x9B, 0xCD, 0xF8, 0x00, 0x90, 0x42, 0x46, 0x39, 0x46, 0x28, 0x46, 0xB0, 0x47, ++0x20, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA3, 0xEB, 0x0E, 0x04, 0xA4, 0xB2, 0x03, 0x34, 0xA0, 0x08, 0x0E, 0xEB, ++0x80, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xA1, 0xE7, 0x58, 0x46, 0xFF, 0xF7, 0x53, 0xFC, 0xD6, 0xF8, 0x38, 0x31, 0x1B, 0x68, ++0x3B, 0x60, 0x01, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, ++0x54, 0x83, 0x32, 0x40, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, ++0x05, 0x46, 0x89, 0xB0, 0x6E, 0x6C, 0x9D, 0xF8, 0x50, 0x40, 0x04, 0x91, 0x0F, 0x46, 0x1C, 0x20, 0x54, 0x21, 0x11, 0xFB, ++0x04, 0x01, 0xD6, 0xF8, 0x38, 0x01, 0x06, 0x90, 0xAB, 0x48, 0x05, 0x94, 0x41, 0x18, 0x3C, 0x68, 0x01, 0x92, 0x08, 0x46, ++0x08, 0xEE, 0x10, 0x1A, 0x07, 0x93, 0xD4, 0xF8, 0x44, 0x80, 0xD4, 0xF8, 0x4C, 0x90, 0x12, 0xF0, 0x41, 0xFA, 0xA5, 0x4B, ++0x05, 0x9A, 0xD3, 0xF8, 0x60, 0x33, 0x28, 0x46, 0x21, 0x46, 0x98, 0x47, 0x00, 0x23, 0x02, 0x93, 0x00, 0x28, 0x00, 0xF0, ++0xF8, 0x80, 0xDF, 0xF8, 0x98, 0xA2, 0x9F, 0x48, 0xDA, 0xF8, 0x00, 0x20, 0x03, 0x68, 0x92, 0xF8, 0x3E, 0x20, 0x03, 0xF0, ++0x3F, 0x03, 0x9A, 0x42, 0x00, 0xF2, 0xFD, 0x80, 0x06, 0x9A, 0x04, 0x9D, 0x53, 0x6A, 0x2D, 0x68, 0x03, 0x90, 0x17, 0x46, ++0x23, 0xF4, 0xC0, 0x13, 0xD2, 0x6C, 0x43, 0xF4, 0x40, 0x11, 0x09, 0xF1, 0x14, 0x0C, 0x92, 0xF8, 0x0D, 0xB0, 0xC2, 0xF8, ++0x1C, 0xC0, 0x79, 0x62, 0x61, 0x6A, 0x07, 0x9F, 0x43, 0xF4, 0x40, 0x13, 0x21, 0xF4, 0xC0, 0x11, 0x43, 0xF4, 0x80, 0x73, ++0x41, 0xF4, 0x40, 0x11, 0xD3, 0x64, 0x61, 0x62, 0x6B, 0x6A, 0x43, 0xF4, 0x80, 0x73, 0xC9, 0xF8, 0x4C, 0x30, 0x02, 0x9B, ++0x99, 0x46, 0x4C, 0xE0, 0x9F, 0x42, 0x40, 0xF2, 0x93, 0x80, 0xFA, 0x1A, 0x92, 0xB2, 0x03, 0x32, 0x4F, 0xEA, 0x92, 0x09, ++0x03, 0xEB, 0x89, 0x03, 0x9B, 0xB2, 0x72, 0x6A, 0x01, 0x98, 0x1A, 0x44, 0x82, 0x42, 0x53, 0xD8, 0x03, 0x9D, 0xDA, 0xF8, ++0x00, 0x00, 0x2D, 0x68, 0x90, 0xF8, 0x3E, 0x00, 0x05, 0xF0, 0x3F, 0x05, 0xA8, 0x42, 0x49, 0xD8, 0xDC, 0xF8, 0x24, 0x00, ++0x28, 0xB1, 0x79, 0x4D, 0xDC, 0xF8, 0x28, 0x00, 0xED, 0x6E, 0x40, 0xF8, 0x03, 0x5C, 0xBE, 0x45, 0x66, 0x64, 0x0D, 0xD2, ++0xDC, 0xF8, 0x4C, 0x10, 0x21, 0xF4, 0xFF, 0x21, 0x21, 0xF4, 0xC0, 0x61, 0x41, 0xEA, 0x49, 0x21, 0x41, 0xF4, 0x80, 0x70, ++0x61, 0x62, 0x73, 0x46, 0xCC, 0xF8, 0x4C, 0x00, 0x72, 0x62, 0xD8, 0xF8, 0x24, 0x20, 0x01, 0xF4, 0x60, 0x11, 0xD3, 0x1A, ++0xB1, 0xF5, 0x60, 0x1F, 0xC8, 0xF8, 0x24, 0x30, 0x59, 0xD0, 0x69, 0x4B, 0x25, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x0B, 0xF1, 0x01, 0x0B, 0x00, 0x2B, 0x5F, 0xFA, 0x8B, 0xFB, 0x42, 0xDB, 0x69, 0x6A, 0x02, 0x94, 0x2C, 0x46, 0xD4, 0xF8, ++0x4C, 0xC0, 0xDC, 0xF8, 0x2C, 0x30, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0xC1, 0xF3, 0x49, 0x2E, ++0x03, 0xEB, 0x8E, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xBE, 0x45, 0xA1, 0xD3, 0x72, 0x6A, 0x01, 0x98, 0x73, 0x46, 0x1A, 0x44, ++0x82, 0x42, 0xAB, 0xD9, 0xDD, 0xF8, 0x08, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x7E, 0xD0, 0xD9, 0xF8, 0x4C, 0x10, 0x81, 0xF8, ++0x0D, 0xB0, 0xD9, 0xF8, 0x24, 0x30, 0xC6, 0xF8, 0x38, 0x91, 0x43, 0xF4, 0x60, 0x12, 0xC9, 0xF8, 0x24, 0x20, 0x62, 0x6A, ++0x43, 0xF4, 0x60, 0x13, 0x02, 0xF4, 0x60, 0x12, 0x43, 0xF4, 0x80, 0x73, 0x00, 0x20, 0xB2, 0xF5, 0x60, 0x1F, 0xCB, 0x64, ++0xC8, 0x61, 0x60, 0xD0, 0x48, 0x4B, 0x04, 0x9A, 0x1B, 0x68, 0x14, 0x60, 0x5D, 0x78, 0x00, 0x2D, 0x47, 0xD1, 0x63, 0x6C, ++0x0C, 0x33, 0x33, 0x61, 0x2C, 0xE0, 0x00, 0x2D, 0xBA, 0xD1, 0x43, 0x49, 0x43, 0x48, 0x40, 0xF2, 0xF4, 0x52, 0x13, 0xF0, ++0x7D, 0xFD, 0xB3, 0xE7, 0x4F, 0xF0, 0x00, 0x09, 0x71, 0xE7, 0x05, 0x9A, 0x11, 0x46, 0x37, 0x4A, 0x54, 0x23, 0x03, 0xFB, ++0x01, 0x23, 0x3A, 0x49, 0x93, 0xF8, 0x50, 0x20, 0x09, 0x68, 0xC6, 0xF8, 0x38, 0x41, 0x01, 0x3A, 0x83, 0xF8, 0x50, 0x20, ++0x4B, 0x78, 0x43, 0xB3, 0x18, 0xEE, 0x10, 0x0A, 0x12, 0xF0, 0x54, 0xF9, 0x41, 0x46, 0xD8, 0xF8, 0x48, 0x01, 0x12, 0xF0, ++0x0B, 0xF9, 0x04, 0x99, 0x22, 0x68, 0xE3, 0x6C, 0x0A, 0x60, 0x00, 0x22, 0xDA, 0x61, 0x01, 0x25, 0x18, 0xEE, 0x10, 0x0A, ++0x31, 0x46, 0x12, 0xF0, 0x23, 0xF9, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x05, 0x46, ++0x31, 0x46, 0x18, 0xEE, 0x10, 0x0A, 0x12, 0xF0, 0x17, 0xF9, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0x25, 0xE6, 0xE7, 0xD8, 0xF8, 0x10, 0x30, 0x33, 0x61, 0xD2, 0xE7, 0x18, 0xEE, 0x10, 0x0A, 0x31, 0x46, ++0x12, 0xF0, 0x06, 0xF9, 0x02, 0x9D, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0xEE, ++0x10, 0x0A, 0x12, 0xF0, 0x1B, 0xF9, 0x99, 0xE7, 0x06, 0x99, 0x4A, 0x6A, 0xCD, 0x6C, 0x42, 0xF4, 0x60, 0x13, 0xC5, 0xF8, ++0x1C, 0x90, 0x4B, 0x62, 0x63, 0x6A, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0x20, 0x17, 0x42, 0xF4, 0x60, 0x12, 0x43, 0xF4, ++0x20, 0x13, 0x42, 0xF4, 0x80, 0x72, 0x47, 0xF4, 0x80, 0x77, 0xEA, 0x64, 0x18, 0xEE, 0x10, 0x0A, 0x63, 0x62, 0x31, 0x46, ++0xCC, 0xF8, 0x4C, 0x70, 0x12, 0xF0, 0xDC, 0xF8, 0x04, 0x9B, 0x4D, 0x46, 0x1C, 0x60, 0xB4, 0xE7, 0x20, 0x62, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xA4, 0x91, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x82, 0x69, 0x03, 0x32, 0x22, 0xF0, 0x03, 0x02, ++0x04, 0x32, 0x93, 0xB2, 0x99, 0x42, 0x04, 0xD9, 0xC8, 0x1A, 0x80, 0xB2, 0x03, 0x30, 0x80, 0x08, 0x70, 0x47, 0x00, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, 0x43, 0x4A, 0x44, 0x4B, 0x11, 0x68, 0x18, 0x68, 0x88, 0x42, 0x08, 0xD0, ++0xD2, 0xE9, 0x01, 0x54, 0xD2, 0xE9, 0x03, 0x02, 0xC3, 0xE9, 0x00, 0x15, 0xC3, 0xE9, 0x02, 0x40, 0x1A, 0x61, 0x3E, 0x48, ++0x3C, 0x4D, 0x3E, 0x4F, 0xDF, 0xF8, 0x04, 0x81, 0x30, 0x22, 0x00, 0x21, 0x06, 0x46, 0xEE, 0xF7, 0xE3, 0xFF, 0x05, 0xF1, ++0x18, 0x09, 0x3B, 0x68, 0x55, 0xF8, 0x04, 0x0B, 0x4F, 0xF4, 0xAC, 0x72, 0x02, 0xFB, 0x03, 0xF2, 0x00, 0x21, 0xEE, 0xF7, ++0xD7, 0xFF, 0x57, 0xF8, 0x04, 0x3B, 0x00, 0x2B, 0x58, 0xDD, 0x4F, 0xF0, 0x00, 0x0B, 0xDA, 0x46, 0x55, 0xF8, 0x04, 0x4C, ++0x30, 0x4B, 0x5C, 0x44, 0x05, 0x20, 0x04, 0xF1, 0xA8, 0x01, 0x63, 0x64, 0x2E, 0x4B, 0xC4, 0xF8, 0xA8, 0x30, 0x84, 0xF8, ++0x97, 0x00, 0x04, 0xF1, 0x94, 0x03, 0x04, 0xF1, 0xAB, 0x00, 0x61, 0x67, 0x18, 0x21, 0x6F, 0xF0, 0x7B, 0x0C, 0x23, 0x66, ++0x60, 0x66, 0x4F, 0xF4, 0xC0, 0x63, 0x40, 0xF2, 0x43, 0x10, 0xA1, 0x66, 0x00, 0x21, 0xC4, 0xE9, 0x21, 0x30, 0xC4, 0xE9, ++0x0D, 0x11, 0xC4, 0xE9, 0x16, 0x11, 0xC4, 0xE9, 0x1E, 0x11, 0x84, 0xF8, 0x94, 0xC0, 0x84, 0xF8, 0x95, 0x10, 0x84, 0xF8, ++0x96, 0x10, 0xA1, 0x62, 0xE1, 0x63, 0xE1, 0x66, 0xC4, 0xF8, 0x80, 0x10, 0x21, 0x67, 0xC4, 0xF8, 0x48, 0x61, 0xC4, 0xF8, ++0x0C, 0x80, 0xC4, 0xF8, 0x50, 0x80, 0xF0, 0xF7, 0x7F, 0xF8, 0x80, 0x03, 0xC4, 0xF8, 0xAC, 0x00, 0xF0, 0xF7, 0x7A, 0xF8, ++0x4F, 0xF0, 0x01, 0x0C, 0x01, 0x30, 0x0C, 0xFA, 0x00, 0xF0, 0x12, 0x4B, 0xC4, 0xF8, 0xB8, 0x30, 0x01, 0x38, 0x00, 0x21, ++0xC4, 0xE9, 0x2C, 0x01, 0x21, 0x46, 0x30, 0x46, 0x12, 0xF0, 0x16, 0xF8, 0x57, 0xF8, 0x04, 0x1C, 0x0A, 0xF1, 0x01, 0x0A, ++0x8A, 0x45, 0x0B, 0xF5, 0xAC, 0x7B, 0xA9, 0xDB, 0x4D, 0x45, 0x06, 0xF1, 0x08, 0x06, 0x94, 0xD1, 0xBD, 0xE8, 0xF8, 0x8F, ++0xEC, 0x57, 0x18, 0x00, 0x74, 0x1F, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x00, 0x01, 0x20, 0x00, ++0x1E, 0xAB, 0xDC, 0xBA, 0x04, 0x07, 0xFF, 0xFF, 0xBE, 0xBA, 0xFE, 0xCA, 0x2D, 0xE9, 0xF8, 0x43, 0x18, 0x4A, 0x19, 0x4B, ++0x11, 0x68, 0x18, 0x68, 0x88, 0x42, 0x08, 0xD0, 0xD2, 0xE9, 0x01, 0x54, 0xD2, 0xE9, 0x03, 0x02, 0xC3, 0xE9, 0x00, 0x15, ++0xC3, 0xE9, 0x02, 0x40, 0x1A, 0x61, 0x13, 0x4C, 0x13, 0x4F, 0x11, 0x4E, 0x04, 0xF1, 0x30, 0x09, 0x20, 0x46, 0x11, 0xF0, ++0xDB, 0xFF, 0x57, 0xF8, 0x04, 0x3B, 0x00, 0x2B, 0x0E, 0xDD, 0x00, 0x25, 0xA8, 0x46, 0x31, 0x68, 0x20, 0x46, 0x29, 0x44, ++0x11, 0xF0, 0xD4, 0xFF, 0x57, 0xF8, 0x04, 0x3C, 0x08, 0xF1, 0x01, 0x08, 0x98, 0x45, 0x05, 0xF5, 0xAC, 0x75, 0xF2, 0xDB, ++0x08, 0x34, 0x4C, 0x45, 0x06, 0xF1, 0x04, 0x06, 0xE4, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0xEC, 0x57, 0x18, 0x00, ++0x74, 0x1F, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x28, 0x82, 0xB0, ++0x06, 0x46, 0x00, 0xF0, 0xBD, 0x80, 0x6A, 0x4C, 0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, ++0x94, 0xF8, 0x4D, 0x30, 0xE7, 0x6A, 0x65, 0x6B, 0x01, 0x2B, 0x69, 0xD1, 0xD5, 0xE9, 0x12, 0x38, 0x00, 0x22, 0x4F, 0xF4, ++0x80, 0x71, 0x6A, 0x62, 0xC8, 0xF8, 0x1C, 0x20, 0xC8, 0xF8, 0x4C, 0x10, 0x00, 0x2B, 0x4C, 0xD0, 0xBA, 0x88, 0x11, 0x07, ++0x49, 0xD5, 0xD3, 0xE9, 0x17, 0x21, 0x28, 0x33, 0xC8, 0xF8, 0x34, 0x10, 0xC8, 0xF8, 0x48, 0x20, 0xC8, 0xF8, 0x38, 0x30, ++0x2B, 0x7F, 0x58, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x63, 0xBB, 0x55, 0x4A, ++0x6B, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x5B, 0x68, 0x9A, 0x06, 0x23, 0xD5, 0xEB, 0x8B, 0x13, 0xF4, ++0x00, 0x5F, 0xEB, 0x6A, 0xDB, 0x6B, 0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0xC3, 0xB9, 0xD8, 0xF8, ++0x24, 0x10, 0x0B, 0x88, 0x9A, 0xB2, 0x1B, 0x04, 0x12, 0xD5, 0xC2, 0xF3, 0x0E, 0x02, 0x0A, 0x80, 0x95, 0xF8, 0x33, 0x20, ++0x95, 0xF8, 0x32, 0x30, 0x04, 0x3A, 0x04, 0x3B, 0x85, 0xF8, 0x33, 0x20, 0x85, 0xF8, 0x32, 0x30, 0xD8, 0xE9, 0x0A, 0x32, ++0x04, 0x3A, 0x04, 0x3B, 0xC8, 0xE9, 0x0A, 0x32, 0x28, 0x46, 0x02, 0xF0, 0x71, 0xFC, 0x3E, 0x4B, 0x08, 0xF1, 0x14, 0x01, ++0xD3, 0xF8, 0x9C, 0x33, 0x32, 0x46, 0x08, 0x46, 0x98, 0x47, 0xD7, 0xF8, 0x48, 0x01, 0x39, 0x46, 0x11, 0xF0, 0x4A, 0xFF, ++0x00, 0x23, 0x6B, 0x64, 0x94, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x33, 0x84, 0xF8, 0x50, 0x30, 0xE2, 0x62, 0x02, 0xB0, ++0xBD, 0xE8, 0xF0, 0x87, 0x6B, 0x6A, 0xDF, 0xF8, 0xCC, 0x90, 0x20, 0x6B, 0xD5, 0xE9, 0x12, 0xA8, 0x43, 0xF4, 0x60, 0x13, ++0x6B, 0x62, 0xC7, 0xF8, 0x38, 0x51, 0x02, 0xF0, 0x37, 0xFC, 0x94, 0xF8, 0x4D, 0x20, 0xD9, 0xF8, 0x00, 0x30, 0x88, 0xF8, ++0x0D, 0x20, 0x5B, 0x78, 0x00, 0x2B, 0x34, 0xD1, 0x3B, 0x61, 0x6B, 0x6A, 0xB9, 0x88, 0x43, 0xF4, 0x80, 0x73, 0x41, 0xF0, ++0x01, 0x02, 0xC8, 0xF8, 0x4C, 0x30, 0xBA, 0x80, 0xBA, 0xF1, 0x00, 0x0F, 0x09, 0xD0, 0x4D, 0x07, 0x07, 0xD4, 0x08, 0x07, ++0x31, 0xD4, 0x23, 0x6B, 0x99, 0x6C, 0x4B, 0x6A, 0x43, 0xF0, 0x04, 0x03, 0x4B, 0x62, 0x93, 0x07, 0x10, 0xD5, 0xD9, 0xF8, ++0x00, 0x30, 0x5B, 0x78, 0xA3, 0xB9, 0x08, 0xF1, 0x14, 0x01, 0x23, 0x6B, 0x3A, 0x6B, 0x98, 0x6A, 0x15, 0x4B, 0x50, 0x61, ++0xD3, 0xF8, 0x9C, 0x33, 0x32, 0x46, 0x07, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0x39, 0x46, 0x04, 0xF1, 0x1C, 0x00, 0x11, 0xF0, ++0xF9, 0xFE, 0xAF, 0xE7, 0x0F, 0x4C, 0x47, 0xE7, 0x07, 0xF1, 0x50, 0x01, 0xE9, 0xE7, 0x94, 0xF8, 0x4E, 0x00, 0xBB, 0x7A, ++0x7A, 0x7A, 0x69, 0x8C, 0x00, 0x90, 0x38, 0x46, 0xFF, 0xF7, 0xCA, 0xF8, 0x07, 0xF1, 0x50, 0x03, 0xC8, 0xF8, 0x1C, 0x30, ++0xBD, 0xE7, 0x41, 0xF0, 0x03, 0x02, 0xBA, 0x80, 0xCF, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xD0, 0xF8, 0x4C, 0x90, 0x8B, 0xB0, 0x09, 0xF1, 0x14, 0x03, 0x05, 0x29, 0x04, 0x46, 0x0E, 0x46, 0x00, 0x93, 0x00, 0xF0, ++0xAD, 0x81, 0x57, 0x4D, 0x01, 0xEB, 0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x05, 0xEB, 0x83, 0x05, 0x94, 0xF8, 0x1B, 0xB0, ++0x94, 0xF8, 0x1D, 0xA0, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x50, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xDF, 0xF8, 0x40, 0x81, 0xEA, 0x6A, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x00, 0x2A, 0x79, 0xD0, ++0x4A, 0x4F, 0x06, 0xE0, 0xD7, 0xF8, 0x5C, 0x33, 0x30, 0x46, 0x98, 0x47, 0xEA, 0x6A, 0x00, 0x2A, 0x70, 0xD0, 0x63, 0x6A, ++0x99, 0x02, 0xF5, 0xD5, 0x03, 0xF4, 0x60, 0x11, 0xB1, 0xF5, 0x20, 0x1F, 0xF0, 0xD0, 0x50, 0x7A, 0x61, 0x7F, 0x88, 0x42, ++0xEC, 0xD1, 0x90, 0x7A, 0xE1, 0x7E, 0x88, 0x42, 0xE8, 0xD1, 0xD9, 0xF8, 0x2C, 0x10, 0xB5, 0xF8, 0x48, 0x00, 0x03, 0x31, ++0x21, 0xF0, 0x03, 0x01, 0x04, 0x31, 0x89, 0xB2, 0x88, 0x42, 0x00, 0xF2, 0x5D, 0x81, 0x00, 0x20, 0x03, 0x90, 0x05, 0x90, ++0x86, 0x46, 0x68, 0x6B, 0x01, 0x90, 0x50, 0x6A, 0x02, 0x90, 0x01, 0x98, 0x95, 0xF8, 0x4F, 0xC0, 0xC0, 0x6C, 0x04, 0x90, ++0x03, 0x98, 0xA5, 0xF8, 0x4A, 0xE0, 0x08, 0x44, 0x02, 0x99, 0x05, 0xEB, 0x8C, 0x0E, 0x08, 0x44, 0x4F, 0xEA, 0x8C, 0x01, ++0x03, 0x91, 0xDE, 0xF8, 0x38, 0x10, 0x88, 0x42, 0x40, 0xF2, 0x82, 0x81, 0x95, 0xF8, 0x4E, 0x10, 0x61, 0x45, 0xBB, 0xD9, ++0x95, 0xF8, 0x4D, 0x10, 0x01, 0x29, 0xB7, 0xD0, 0xDE, 0xF8, 0x3C, 0xE0, 0x70, 0x45, 0xB3, 0xD8, 0x03, 0x9F, 0x17, 0x44, ++0xBB, 0x46, 0x01, 0x9F, 0xCB, 0xF8, 0x3C, 0x71, 0x0C, 0xF1, 0x01, 0x0C, 0x02, 0x9F, 0xCB, 0xF8, 0x34, 0x70, 0x85, 0xF8, ++0x4F, 0xC0, 0x05, 0x9F, 0x62, 0x64, 0x43, 0xEA, 0x47, 0x23, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0xE0, 0x03, 0x63, 0x62, ++0xC9, 0xF8, 0x4C, 0x30, 0x04, 0x9B, 0x1F, 0x46, 0x00, 0x9B, 0xFB, 0x61, 0x50, 0x62, 0x95, 0xF8, 0x4C, 0x20, 0x6C, 0x63, ++0x4B, 0x1C, 0xDB, 0xB2, 0x9A, 0x42, 0x85, 0xF8, 0x4D, 0x30, 0x0D, 0xD8, 0x10, 0x4B, 0x30, 0x46, 0xD3, 0xF8, 0x5C, 0x33, ++0x98, 0x47, 0x07, 0xE0, 0x63, 0x6A, 0x98, 0x02, 0x1C, 0xD4, 0x95, 0xF8, 0x50, 0x30, 0x01, 0x33, 0x85, 0xF8, 0x50, 0x30, ++0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x00, 0x20, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA3, 0x6A, 0xDB, 0x0A, 0x13, 0xF0, 0x06, 0x0F, 0xDD, 0xD0, 0xB0, 0x48, ++0x00, 0xEB, 0xC6, 0x00, 0x11, 0xF0, 0x4A, 0xFE, 0xE8, 0x62, 0x00, 0x28, 0x00, 0xF0, 0xEA, 0x80, 0xAC, 0x4F, 0x80, 0xF8, ++0x0A, 0xB0, 0x00, 0x23, 0x01, 0x21, 0x3A, 0x68, 0x80, 0xF8, 0x09, 0xA0, 0x03, 0x72, 0x43, 0x60, 0xC1, 0x72, 0xA3, 0x6A, ++0xB2, 0xF9, 0x00, 0x20, 0x61, 0x7F, 0x03, 0x91, 0xC3, 0xF3, 0xC1, 0x1B, 0xC3, 0xF3, 0xC7, 0x21, 0x00, 0x2A, 0xC3, 0xF3, ++0xC2, 0x23, 0x01, 0x93, 0xC0, 0xF2, 0xD2, 0x80, 0x01, 0x9B, 0x05, 0x2B, 0x00, 0xF0, 0xD9, 0x80, 0xD4, 0xF8, 0x28, 0xA0, ++0x63, 0x7F, 0x05, 0x93, 0x0A, 0xF0, 0x7F, 0x03, 0x04, 0x93, 0xCA, 0xF3, 0x40, 0x23, 0x06, 0x93, 0x01, 0x9B, 0x04, 0x2B, ++0x3B, 0x68, 0x00, 0xF0, 0xF2, 0x80, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x01, 0x81, 0x94, 0x4A, 0x05, 0x99, ++0x02, 0x92, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x23, 0x04, 0x9A, 0x9B, 0x8A, 0x08, 0x93, 0xC2, 0xF3, 0xC1, 0x02, ++0x01, 0x32, 0x09, 0x92, 0x0A, 0xF0, 0x07, 0x0A, 0x8D, 0x4B, 0x05, 0x93, 0x8D, 0x4B, 0x9C, 0x46, 0x06, 0x9B, 0x00, 0x27, ++0x43, 0xEA, 0xCA, 0x0A, 0x5F, 0xFA, 0x8B, 0xF3, 0x19, 0x46, 0x05, 0xF1, 0x38, 0x0B, 0x04, 0x93, 0x85, 0xF8, 0x4E, 0x10, ++0x00, 0x23, 0x31, 0x1D, 0xCD, 0xF8, 0x18, 0x90, 0x07, 0x94, 0xD1, 0x46, 0x85, 0xF8, 0x4F, 0x30, 0xDA, 0x46, 0x1E, 0x46, ++0x64, 0x46, 0x8B, 0x46, 0x01, 0x2A, 0xF1, 0xB2, 0x00, 0xF0, 0xA8, 0x80, 0x48, 0x46, 0xA0, 0x47, 0x7E, 0x4B, 0x09, 0x9A, ++0x33, 0xF8, 0x1B, 0xC0, 0x08, 0x99, 0x02, 0xFB, 0x0C, 0xFC, 0x00, 0xFB, 0x0C, 0xF0, 0xF8, 0x40, 0x81, 0x42, 0x28, 0xBF, ++0x01, 0x46, 0x4A, 0xF8, 0x04, 0x1B, 0x95, 0xF8, 0x4E, 0x10, 0x01, 0x36, 0x8E, 0x42, 0xE5, 0xDD, 0xCA, 0x46, 0x04, 0x99, ++0x05, 0x9B, 0x50, 0x46, 0xDD, 0xE9, 0x06, 0x94, 0x98, 0x47, 0x03, 0x9B, 0xD5, 0xF8, 0x38, 0xC0, 0x1E, 0x46, 0x02, 0x9B, ++0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x06, 0x32, 0x09, 0x9B, 0x16, 0x7F, 0xEA, 0x6A, 0x03, 0xFB, 0x06, 0xF6, 0x00, 0xFB, ++0x06, 0xF6, 0xFE, 0x40, 0xB6, 0xB2, 0xA5, 0xF8, 0x48, 0x60, 0xE1, 0x7E, 0x63, 0x7F, 0xEF, 0x6B, 0x9E, 0x20, 0x00, 0xFB, ++0x03, 0x13, 0x02, 0x99, 0x28, 0x6C, 0x01, 0xEB, 0x83, 0x03, 0x4F, 0xF0, 0x01, 0x0E, 0x93, 0xF8, 0x5A, 0x31, 0x85, 0xF8, ++0x4C, 0x30, 0xD9, 0xF8, 0x2C, 0x10, 0x00, 0x9B, 0x53, 0x61, 0x03, 0x31, 0x21, 0xF0, 0x03, 0x01, 0x04, 0x31, 0x00, 0x23, ++0x89, 0xB2, 0x51, 0x62, 0xC2, 0xF8, 0x54, 0x01, 0xC2, 0xE9, 0x53, 0xC7, 0xC2, 0xE9, 0x0D, 0x33, 0x93, 0x64, 0x93, 0x61, ++0xD3, 0x63, 0x85, 0xF8, 0x4D, 0xE0, 0xD9, 0xF8, 0x2C, 0x00, 0x03, 0x30, 0x20, 0xF0, 0x03, 0x00, 0x04, 0x30, 0x80, 0xB2, ++0xB0, 0x42, 0x57, 0xD2, 0x30, 0x1A, 0x80, 0xB2, 0x03, 0x30, 0x83, 0x10, 0x01, 0xEB, 0x83, 0x01, 0x80, 0x08, 0x5B, 0x02, ++0x66, 0x6A, 0xA5, 0xF8, 0x4A, 0x00, 0x33, 0x43, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0xD0, 0x03, 0x51, 0x62, 0xC5, 0xE9, ++0x0C, 0x44, 0x63, 0x62, 0x62, 0x64, 0xC9, 0xF8, 0x4C, 0x30, 0xFF, 0xE6, 0xA0, 0xEB, 0x01, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, ++0x0E, 0xF1, 0x03, 0x0E, 0x4F, 0xEA, 0xAE, 0x00, 0x05, 0x90, 0x80, 0x00, 0x4F, 0xEA, 0x9E, 0x0E, 0x03, 0x90, 0x98, 0xE6, ++0x3D, 0x4D, 0x57, 0xE6, 0x60, 0x62, 0xE8, 0xE6, 0x11, 0xF0, 0x06, 0x0F, 0x7F, 0xF4, 0x2A, 0xAF, 0x3A, 0x49, 0x3B, 0x48, ++0x4F, 0xF4, 0xEA, 0x72, 0x13, 0xF0, 0x60, 0xF9, 0x22, 0xE7, 0x09, 0xAB, 0x08, 0xAA, 0x01, 0x99, 0x20, 0x46, 0x02, 0xF0, ++0x39, 0xF9, 0x36, 0x4B, 0x05, 0x93, 0x36, 0x4B, 0x94, 0xF8, 0x36, 0x70, 0x09, 0x9A, 0x9C, 0x46, 0x2B, 0x4B, 0x02, 0x93, ++0x82, 0x46, 0xC7, 0xF3, 0x40, 0x17, 0x3F, 0xE7, 0x01, 0x9B, 0x04, 0x2B, 0x7F, 0xF4, 0x54, 0xAF, 0x4F, 0xEA, 0xE9, 0x02, ++0x00, 0x2E, 0x7F, 0xF4, 0x4F, 0xAF, 0x09, 0x2A, 0x04, 0xBF, 0x09, 0xF0, 0x07, 0x03, 0x43, 0xF0, 0x40, 0x09, 0x47, 0xE7, ++0x18, 0x46, 0xAD, 0xE7, 0x95, 0xF8, 0x4D, 0x10, 0x93, 0xE6, 0x04, 0x9A, 0xB3, 0xF9, 0x00, 0x30, 0x11, 0x09, 0x4A, 0x1C, ++0x00, 0x2B, 0x0A, 0xF0, 0x0F, 0x0A, 0x09, 0x92, 0x14, 0xDB, 0x19, 0x49, 0x05, 0x98, 0x02, 0x91, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x00, 0x13, 0x1B, 0x69, 0x08, 0x93, 0x0E, 0xE7, 0x1A, 0xF0, 0x60, 0x0F, 0x3F, 0xF4, 0xFB, 0xAE, 0x17, 0x49, ++0x1A, 0x48, 0x4F, 0xF4, 0xD2, 0x72, 0x13, 0xF0, 0x19, 0xF9, 0xF3, 0xE6, 0x03, 0x29, 0x04, 0xD8, 0xBA, 0xF1, 0x09, 0x0F, ++0x0D, 0xD8, 0x09, 0x9A, 0xE3, 0xE7, 0x10, 0x49, 0x14, 0x48, 0x40, 0xF2, 0x9B, 0x12, 0x13, 0xF0, 0x0B, 0xF9, 0x3B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEF, 0xDB, 0xF1, 0xE7, 0x0A, 0x49, 0x0F, 0x48, 0x4F, 0xF4, 0xCE, 0x72, 0x13, 0xF0, ++0xFF, 0xF8, 0xEA, 0xE7, 0x64, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x85, 0x06, 0x13, 0x00, ++0x75, 0x06, 0x13, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB8, 0x91, 0x15, 0x00, ++0x21, 0x3B, 0x13, 0x00, 0x05, 0x3B, 0x13, 0x00, 0x0C, 0x92, 0x15, 0x00, 0xE0, 0x91, 0x15, 0x00, 0xFC, 0x91, 0x15, 0x00, ++0xC3, 0x7A, 0x01, 0x3B, 0xDB, 0xB2, 0xC3, 0x72, 0x03, 0xB1, 0x70, 0x47, 0x01, 0x46, 0xD0, 0xF8, 0x48, 0x01, 0x11, 0xF0, ++0x83, 0xBC, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0xD0, 0xE9, 0x12, 0x67, 0x00, 0x23, 0x4F, 0xF4, 0x80, 0x72, 0x43, 0x62, ++0x43, 0x64, 0xFB, 0x61, 0xFA, 0x64, 0x00, 0x2E, 0x00, 0xF0, 0x81, 0x80, 0xD0, 0xF8, 0x2C, 0x80, 0x8A, 0x46, 0x05, 0x46, ++0x06, 0xF1, 0x28, 0x09, 0x08, 0xF1, 0x40, 0x01, 0x43, 0x46, 0x06, 0xF1, 0x24, 0x02, 0x53, 0xF8, 0x04, 0x4B, 0x42, 0xF8, ++0x04, 0x4F, 0x8B, 0x42, 0xF9, 0xD1, 0xEB, 0x8B, 0x9C, 0x04, 0x22, 0xD5, 0x48, 0x4B, 0x49, 0x49, 0x1A, 0x68, 0x6B, 0x7F, ++0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x41, 0x61, 0xDB, ++0xD8, 0xF8, 0x14, 0x20, 0xD4, 0xF8, 0x9C, 0x30, 0x32, 0x64, 0xD8, 0xF8, 0x24, 0x20, 0x32, 0x65, 0xC3, 0xF3, 0xC2, 0x22, ++0x05, 0x2A, 0xF3, 0x63, 0x5D, 0xD0, 0xD8, 0xF8, 0x3C, 0x30, 0x58, 0x07, 0x03, 0xD4, 0xF3, 0x6A, 0x23, 0xF4, 0xC0, 0x73, ++0xF3, 0x62, 0x39, 0x4A, 0x2B, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x7B, 0xB1, ++0x73, 0x6A, 0x43, 0xF0, 0x10, 0x03, 0x28, 0x46, 0x73, 0x62, 0x02, 0xF0, 0x47, 0xF9, 0xD6, 0xE9, 0x17, 0x23, 0x07, 0xF1, ++0x14, 0x00, 0xC7, 0xE9, 0x0D, 0x39, 0xBA, 0x64, 0xBD, 0xE8, 0xF0, 0x87, 0x2B, 0x4A, 0x6B, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, ++0x01, 0xFB, 0x03, 0x23, 0x5B, 0x68, 0x99, 0x06, 0xE6, 0xD5, 0xBA, 0xF1, 0x00, 0x0F, 0xE3, 0xD1, 0xEB, 0x8B, 0x13, 0xF4, ++0x00, 0x5F, 0xEB, 0x6A, 0xDB, 0x6B, 0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0x00, 0x2B, 0xD7, 0xD1, ++0x79, 0x6A, 0x0A, 0x88, 0x93, 0xB2, 0x12, 0x04, 0xD2, 0xD5, 0xC3, 0xF3, 0x0E, 0x03, 0x0B, 0x80, 0x95, 0xF8, 0x33, 0x20, ++0x95, 0xF8, 0x32, 0x30, 0x04, 0x3A, 0x04, 0x3B, 0x85, 0xF8, 0x33, 0x20, 0x85, 0xF8, 0x32, 0x30, 0xD7, 0xE9, 0x0A, 0x32, ++0x04, 0x3A, 0x04, 0x3B, 0xC7, 0xE9, 0x0A, 0x32, 0xBE, 0xE7, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x2C, 0x9B, 0xD1, ++0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0x13, 0xF0, 0x3C, 0xF8, 0x94, 0xE7, 0x03, 0xF4, 0xC0, 0x63, 0xF2, 0x6C, ++0x94, 0xF8, 0xA1, 0x10, 0xB3, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x30, 0x4F, 0xF4, 0x00, 0x30, 0x22, 0xF4, ++0x40, 0x33, 0x03, 0x43, 0x19, 0xB1, 0x43, 0xF4, 0x80, 0x23, 0xF3, 0x64, 0x8D, 0xE7, 0x23, 0xF4, 0x80, 0x23, 0xF3, 0x64, ++0x89, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x05, 0x28, 0x89, 0xB0, 0x81, 0x46, 0x00, 0xF0, 0x79, 0x81, 0xBE, 0x4A, ++0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x03, 0x93, 0x03, 0x9B, 0xDC, 0x68, 0xBA, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x09, 0xDA, 0x5D, 0xE1, 0xE3, 0x6C, 0x1B, 0x6D, 0x00, 0x2B, 0x80, 0xF2, ++0xFE, 0x80, 0x24, 0x68, 0x00, 0x2C, 0x00, 0xF0, 0xFA, 0x80, 0x63, 0x6A, 0x9A, 0x02, 0xF3, 0xD5, 0xB0, 0x4D, 0x2A, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x80, 0x81, 0xAE, 0x4B, 0x67, 0x6C, 0x1B, 0x68, 0xDB, 0xB2, 0x07, 0xEB, ++0x83, 0x03, 0xD3, 0xF8, 0x3C, 0x41, 0xE5, 0x6C, 0x63, 0x6A, 0xAA, 0x49, 0x43, 0xF4, 0x60, 0x10, 0x09, 0x68, 0x60, 0x62, ++0x49, 0x78, 0x23, 0xF4, 0xC0, 0x13, 0x00, 0x29, 0x40, 0xF0, 0x58, 0x81, 0x43, 0xF4, 0x60, 0x13, 0x43, 0xF4, 0x80, 0x73, ++0x00, 0x2A, 0x26, 0x68, 0xEB, 0x64, 0xE9, 0x61, 0xC0, 0xF2, 0x57, 0x81, 0x72, 0x6A, 0x02, 0xF4, 0x60, 0x1A, 0xBA, 0xF5, ++0x60, 0x1F, 0x00, 0xF0, 0xEC, 0x80, 0x9D, 0x48, 0x50, 0xF8, 0x39, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xE6, 0x80, 0x00, 0xEB, ++0xC9, 0x00, 0x11, 0xF0, 0xAD, 0xFB, 0xBB, 0x88, 0x83, 0x80, 0x7B, 0x7A, 0x43, 0x72, 0xBB, 0x7A, 0x83, 0x72, 0x01, 0x23, ++0xC3, 0x72, 0x72, 0x6A, 0xD6, 0xF8, 0x4C, 0xA0, 0xF9, 0x6A, 0xD7, 0xF8, 0x4C, 0xB1, 0xB5, 0x6C, 0x05, 0x95, 0x04, 0x46, ++0xD7, 0xE9, 0x10, 0x03, 0x22, 0xF4, 0xC0, 0x12, 0xE1, 0x62, 0x42, 0xF4, 0x20, 0x12, 0x00, 0x21, 0xC4, 0xE9, 0x10, 0x03, ++0xA1, 0x64, 0x3B, 0x6B, 0x72, 0x62, 0xCA, 0xF8, 0x4C, 0x20, 0xC4, 0xF8, 0x4C, 0xB1, 0x06, 0x93, 0xD7, 0xF8, 0x50, 0x31, ++0xC4, 0xF8, 0x50, 0x31, 0xD7, 0xF8, 0x54, 0x31, 0xC4, 0xF8, 0x54, 0x31, 0x04, 0xF1, 0x0C, 0x03, 0x0A, 0xF1, 0x14, 0x0C, ++0x28, 0x35, 0xC4, 0xE9, 0x0D, 0x11, 0xA1, 0x61, 0xE1, 0x63, 0x61, 0x62, 0x04, 0x93, 0x04, 0xF5, 0x82, 0x73, 0xC4, 0xF8, ++0x14, 0xC0, 0x25, 0x63, 0xBC, 0x46, 0x08, 0x46, 0x57, 0x46, 0x07, 0x93, 0xAA, 0x46, 0x8E, 0x46, 0x25, 0x46, 0x0C, 0x46, ++0x06, 0xE0, 0x5A, 0x6A, 0xDF, 0x6C, 0xD8, 0xF8, 0x34, 0x00, 0xD8, 0xF8, 0x4C, 0xB1, 0x1E, 0x46, 0xFB, 0x6A, 0x03, 0x33, ++0xC2, 0xF3, 0x49, 0x28, 0x23, 0xF0, 0x03, 0x03, 0x03, 0xEB, 0x88, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x18, 0x44, 0x01, 0x31, ++0x58, 0x45, 0x02, 0xF4, 0x60, 0x12, 0xC9, 0xB2, 0x06, 0xD9, 0x05, 0xEB, 0x8E, 0x00, 0x0E, 0xF1, 0x01, 0x0E, 0x44, 0x63, ++0x5F, 0xFA, 0x8E, 0xFE, 0x05, 0xEB, 0x8E, 0x08, 0x1C, 0x44, 0xC8, 0xF8, 0x3C, 0x61, 0xB2, 0xF5, 0x60, 0x1F, 0x33, 0x68, ++0x75, 0x64, 0x6C, 0x62, 0x00, 0xF0, 0x18, 0x81, 0x00, 0x2B, 0xD2, 0xD1, 0x2C, 0x46, 0x98, 0x46, 0x55, 0x46, 0xC4, 0xF8, ++0x38, 0x61, 0xBA, 0x46, 0x67, 0x46, 0x03, 0x98, 0x8A, 0xF8, 0x0D, 0x10, 0x90, 0xF8, 0x50, 0x30, 0x03, 0xF1, 0x01, 0x0C, ++0x03, 0x46, 0x22, 0x46, 0x1C, 0x30, 0x83, 0xF8, 0x50, 0xC0, 0x39, 0x46, 0x11, 0xF0, 0xA0, 0xFB, 0x53, 0x4B, 0x1B, 0x68, ++0x58, 0x78, 0x00, 0x28, 0x40, 0xF0, 0x11, 0x81, 0xD7, 0xF8, 0x38, 0x11, 0xF2, 0x6C, 0xDF, 0xF8, 0x30, 0xC1, 0xC9, 0x6C, ++0xD0, 0x61, 0x54, 0x23, 0x03, 0xFB, 0x09, 0xF3, 0x3A, 0x69, 0x5C, 0xF8, 0x03, 0x00, 0x22, 0x61, 0x14, 0x31, 0x04, 0x9A, ++0x3A, 0x61, 0x88, 0x42, 0x63, 0x44, 0x00, 0xF0, 0x2A, 0x81, 0x06, 0x9B, 0x07, 0x9A, 0xA3, 0xF1, 0x28, 0x00, 0x05, 0x9B, ++0xC0, 0x1A, 0x03, 0xF1, 0x5C, 0x01, 0x2B, 0x18, 0x1C, 0x68, 0x45, 0xF8, 0x04, 0x4B, 0x1B, 0x68, 0x42, 0xF8, 0x04, 0x3B, ++0x8D, 0x42, 0xF6, 0xD1, 0x3B, 0x4C, 0x48, 0x46, 0xFC, 0xF7, 0x10, 0xF8, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xD7, 0xF8, 0x38, 0x31, 0x04, 0xDB, 0xB3, 0x42, 0x1C, 0xD1, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0x42, 0xFA, 0xD0, ++0x36, 0x49, 0x37, 0x48, 0x40, 0xF6, 0x2A, 0x42, 0x12, 0xF0, 0xF2, 0xFE, 0xD7, 0xF8, 0x38, 0x31, 0xB3, 0x42, 0xF0, 0xD0, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x08, 0xDA, 0xB8, 0xF1, 0x00, 0x0F, 0x05, 0xD1, 0x2D, 0x49, 0x2F, 0x48, ++0x4F, 0xF4, 0x43, 0x62, 0x12, 0xF0, 0xE0, 0xFE, 0xD8, 0xF8, 0x24, 0x20, 0x46, 0x46, 0x02, 0xF4, 0x60, 0x1A, 0x26, 0x4B, ++0x1B, 0x68, 0x5B, 0x78, 0x00, 0x2B, 0x58, 0xD1, 0xD7, 0xF8, 0x38, 0x31, 0xD7, 0xF8, 0x10, 0x80, 0xDB, 0x6C, 0x07, 0xF1, ++0x0C, 0x05, 0x03, 0xF1, 0x14, 0x07, 0x1C, 0x4B, 0x04, 0x97, 0x54, 0x24, 0x04, 0xFB, 0x09, 0x34, 0x57, 0x46, 0xDF, 0xF8, ++0x88, 0xB0, 0xDF, 0xF8, 0x7C, 0x90, 0xA2, 0x46, 0x03, 0x9C, 0x94, 0xF8, 0x50, 0x10, 0xDB, 0xF8, 0x58, 0x33, 0x01, 0x31, ++0x84, 0xF8, 0x50, 0x10, 0x30, 0x46, 0x00, 0x21, 0x98, 0x47, 0x58, 0xB1, 0x13, 0x4B, 0x68, 0x60, 0x1B, 0x68, 0x59, 0x78, ++0xDA, 0xF8, 0x00, 0x30, 0x00, 0x29, 0x65, 0xD0, 0xAB, 0x42, 0x00, 0xF0, 0xAD, 0x80, 0x05, 0x46, 0xB7, 0xF5, 0x60, 0x1F, ++0x65, 0xD1, 0xC0, 0xF8, 0x04, 0x80, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2C, 0x7F, 0xF4, 0xA8, 0xAE, 0x0A, 0x49, ++0x0B, 0x48, 0x40, 0xF6, 0x8B, 0x32, 0x12, 0xF0, 0x99, 0xFE, 0xA0, 0xE6, 0x09, 0x4B, 0x03, 0x93, 0x8B, 0xE6, 0x00, 0xBF, ++0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x30, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x4C, 0x92, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x07, 0xF1, 0x50, 0x01, 0xA4, 0xE6, 0xD7, 0xF8, 0x54, 0x80, 0x07, 0xF1, 0x50, 0x05, 0x00, 0x27, 0xA9, 0xE7, 0x00, 0x2E, ++0x7F, 0xF4, 0xA6, 0xAE, 0x49, 0x49, 0x4A, 0x48, 0x40, 0xF6, 0xB6, 0x32, 0x12, 0xF0, 0x6E, 0xFE, 0x9E, 0xE6, 0x03, 0xF4, ++0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x3E, 0xD0, 0x40, 0xF6, 0x9B, 0x32, 0x42, 0x49, 0x44, 0x48, 0x12, 0xF0, 0x62, 0xFE, ++0x43, 0x4B, 0x67, 0x6C, 0x1B, 0x68, 0x2A, 0x68, 0xDB, 0xB2, 0x07, 0xEB, 0x83, 0x03, 0xB2, 0xF9, 0x00, 0x20, 0xD3, 0xF8, ++0x3C, 0x41, 0x00, 0x2A, 0xE5, 0x6C, 0xBF, 0xF6, 0x6F, 0xAE, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x60, 0x1F, ++0x60, 0xD0, 0x3A, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x64, 0xE6, 0x04, 0x9A, 0x93, 0x42, 0x99, 0xD1, 0xCA, 0xE9, ++0x01, 0x11, 0x05, 0x46, 0x96, 0xE7, 0x34, 0x4B, 0x36, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x3F, 0xDB, ++0x77, 0x6A, 0x07, 0xF4, 0x60, 0x17, 0x74, 0xE7, 0x20, 0x46, 0x2C, 0x46, 0x04, 0xEB, 0x8E, 0x0E, 0x55, 0x46, 0xC4, 0xF8, ++0x38, 0x61, 0xBA, 0x46, 0x98, 0x46, 0x67, 0x46, 0xCE, 0xF8, 0x34, 0x00, 0xE3, 0xE6, 0x27, 0x4B, 0x67, 0x6C, 0x1B, 0x68, ++0xDB, 0xB2, 0x07, 0xEB, 0x83, 0x03, 0xD3, 0xF8, 0x3C, 0x41, 0xE5, 0x6C, 0xCB, 0xE7, 0xB0, 0x6A, 0xA3, 0x7A, 0x62, 0x7A, ++0x71, 0x8C, 0xC0, 0xF3, 0xC1, 0x10, 0x00, 0x90, 0x20, 0x46, 0xFE, 0xF7, 0xA1, 0xFB, 0x54, 0x23, 0x1E, 0x49, 0xF2, 0x6C, ++0xD7, 0xF8, 0x54, 0xE0, 0x03, 0xFB, 0x09, 0xF3, 0x04, 0xF1, 0x50, 0x00, 0x51, 0xF8, 0x03, 0xC0, 0xD0, 0x61, 0x07, 0xF1, ++0x50, 0x02, 0xC4, 0xF8, 0x54, 0xE0, 0x94, 0x45, 0x04, 0x9C, 0x7C, 0x65, 0x7F, 0xF4, 0xE5, 0xAE, 0xC8, 0x50, 0xE2, 0xE6, ++0xCA, 0xF8, 0x00, 0x00, 0x05, 0x46, 0x4F, 0xE7, 0x00, 0x2E, 0xBD, 0xD1, 0x0B, 0x49, 0x40, 0xF6, 0x62, 0x42, 0x48, 0x46, ++0x12, 0xF0, 0xF2, 0xFD, 0xB6, 0xE7, 0x04, 0x99, 0x01, 0x22, 0xC3, 0xE9, 0x01, 0x12, 0xD0, 0xE6, 0x40, 0xF6, 0xA5, 0x32, ++0x04, 0x49, 0x0A, 0x48, 0x12, 0xF0, 0xE6, 0xFD, 0x06, 0x4B, 0x1A, 0x68, 0x63, 0x6A, 0xB2, 0xF9, 0x00, 0x20, 0xFC, 0xE5, ++0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x1C, 0x92, 0x15, 0x00, 0x30, 0x83, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x34, 0x92, 0x15, 0x00, 0x05, 0x28, 0x10, 0xB5, 0x25, 0xD0, 0x14, 0x4A, 0x00, 0xEB, 0x40, 0x03, ++0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x02, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0F, 0x4B, ++0x01, 0x21, 0x19, 0x60, 0x0E, 0x4C, 0x92, 0xF8, 0x50, 0x10, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x31, 0xB9, 0xD2, 0x6A, ++0x22, 0xB1, 0x0B, 0x4B, 0xD3, 0xF8, 0x5C, 0x33, 0x98, 0x47, 0x23, 0x68, 0x33, 0xB1, 0x06, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x05, 0x4A, 0xDE, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x03, 0x68, 0x13, 0xF4, ++0xE0, 0x3F, 0x1A, 0xD1, 0x9A, 0x04, 0x4C, 0xBF, 0x03, 0xF0, 0x0F, 0x02, 0x03, 0xF0, 0x07, 0x02, 0x02, 0x2A, 0xC3, 0xF3, ++0xC1, 0x11, 0x88, 0xBF, 0x4F, 0xF4, 0x80, 0x12, 0x23, 0xF0, 0xFF, 0x53, 0x98, 0xBF, 0x4F, 0xF4, 0x00, 0x22, 0x23, 0xF4, ++0xFE, 0x13, 0x42, 0xEA, 0x01, 0x62, 0x13, 0x43, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x03, 0x60, 0x70, 0x47, ++0xC3, 0x6B, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x10, 0xB4, 0x0E, 0x4C, 0x42, 0x6A, 0x24, 0x68, 0xB4, 0xF9, 0x00, 0x40, ++0x00, 0x2C, 0x01, 0xDA, 0xDB, 0x03, 0x0B, 0xD5, 0x53, 0x69, 0x23, 0xF4, 0xE0, 0x33, 0x00, 0x24, 0x43, 0xF4, 0x80, 0x43, ++0xC4, 0x63, 0x5D, 0xF8, 0x04, 0x4B, 0x53, 0x61, 0xFC, 0xF7, 0xA4, 0xB9, 0x04, 0x49, 0x05, 0x48, 0x5D, 0xF8, 0x04, 0x4B, ++0x40, 0xF6, 0xD9, 0x42, 0x12, 0xF0, 0x28, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x92, 0x15, 0x00, ++0x05, 0x28, 0x10, 0xB5, 0x17, 0xD0, 0x0D, 0x4C, 0x00, 0xEB, 0x40, 0x00, 0xC0, 0xEB, 0xC0, 0x00, 0x04, 0xEB, 0x80, 0x04, ++0xA1, 0x6A, 0x31, 0xB1, 0xCB, 0x7A, 0x01, 0x3B, 0xDB, 0xB2, 0xCB, 0x72, 0x13, 0xB1, 0x00, 0x23, 0xA3, 0x62, 0x10, 0xBD, ++0xD1, 0xF8, 0x48, 0x01, 0x11, 0xF0, 0xE8, 0xF8, 0x00, 0x23, 0xA3, 0x62, 0xF7, 0xE7, 0x02, 0x4C, 0xEC, 0xE7, 0x00, 0xBF, ++0x20, 0x62, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0xF0, 0xB4, 0xC5, 0x6C, 0x42, 0x6A, 0xEB, 0x6C, 0xD0, 0xE9, 0x11, 0x67, ++0x22, 0xF4, 0xC0, 0x12, 0x23, 0xF4, 0x60, 0x13, 0x05, 0xF1, 0x14, 0x0C, 0x42, 0xF4, 0x20, 0x14, 0x43, 0xF4, 0x20, 0x12, ++0x06, 0xF5, 0x82, 0x73, 0xC6, 0xF8, 0x14, 0xC0, 0x33, 0x63, 0x44, 0x62, 0xEA, 0x64, 0x06, 0xF1, 0x0C, 0x00, 0x07, 0xF1, ++0x24, 0x02, 0x06, 0xF5, 0x9C, 0x75, 0x53, 0xF8, 0x04, 0x4B, 0x42, 0xF8, 0x04, 0x4F, 0xAB, 0x42, 0xF9, 0xD1, 0x77, 0xB1, ++0x09, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0x33, 0xB9, 0xD6, 0xF8, 0x38, 0x31, 0xDB, 0x6C, 0x14, 0x33, 0x0B, 0x60, 0xF0, 0xBC, ++0x70, 0x47, 0x50, 0x36, 0x0E, 0x60, 0xF0, 0xBC, 0x70, 0x47, 0x01, 0x23, 0x38, 0x46, 0x73, 0x60, 0xF5, 0xE7, 0x00, 0xBF, ++0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x47, 0x6A, 0xD0, 0xF8, 0x4C, 0xE0, 0x85, 0xB0, 0x17, 0xF4, 0x00, 0x1C, ++0x9D, 0xF8, 0x38, 0x90, 0x04, 0x46, 0x0E, 0xF1, 0x14, 0x08, 0x0D, 0x46, 0x16, 0x46, 0x9A, 0x46, 0x2A, 0xD0, 0x07, 0xF4, ++0x60, 0x17, 0xB7, 0xF5, 0x20, 0x1F, 0x40, 0xF0, 0xBB, 0x80, 0xD0, 0xF8, 0x44, 0xB0, 0xBB, 0xF8, 0x04, 0x70, 0x07, 0xF0, ++0x03, 0x07, 0x03, 0x2F, 0x40, 0xF0, 0xB2, 0x80, 0xDF, 0xF8, 0x30, 0xC2, 0x83, 0x4F, 0xDC, 0xF8, 0x00, 0xC0, 0x3F, 0x68, ++0x9C, 0xF8, 0x3E, 0xC0, 0x07, 0xF0, 0x3F, 0x07, 0xBC, 0x45, 0x00, 0xF2, 0xA5, 0x80, 0xDB, 0xF8, 0x24, 0x70, 0x97, 0x42, ++0x40, 0xF2, 0xC1, 0x80, 0x7C, 0x4C, 0xCD, 0xF8, 0x38, 0x90, 0xD4, 0xF8, 0x70, 0x43, 0xA4, 0x46, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x60, 0x47, 0x83, 0x6C, 0x00, 0x2B, 0x00, 0xF0, 0x92, 0x80, 0x5B, 0x6A, 0x13, 0xF0, 0x10, 0x03, 0x00, 0xF0, ++0x8D, 0x80, 0x82, 0x88, 0x00, 0x2A, 0x00, 0xF0, 0x8F, 0x80, 0xC3, 0x8B, 0x1F, 0x07, 0x00, 0xF1, 0x8B, 0x80, 0xDE, 0xF8, ++0x24, 0x10, 0x00, 0x29, 0x00, 0xF0, 0xB9, 0x80, 0x08, 0x88, 0x83, 0xB2, 0x00, 0x04, 0x00, 0xF1, 0xB4, 0x80, 0x6F, 0xEA, ++0x43, 0x43, 0x6F, 0xEA, 0x53, 0x43, 0x0B, 0x80, 0x94, 0xF8, 0x33, 0x20, 0x94, 0xF8, 0x32, 0x30, 0x04, 0x32, 0x04, 0x33, ++0x84, 0xF8, 0x32, 0x30, 0x84, 0xF8, 0x33, 0x20, 0xDE, 0xE9, 0x0A, 0x12, 0xD3, 0x1D, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, ++0x9B, 0xB2, 0x04, 0x32, 0x04, 0x31, 0xB3, 0x42, 0xCE, 0xE9, 0x0A, 0x12, 0x6D, 0xD8, 0xA2, 0x88, 0x32, 0xB1, 0xE3, 0x8B, ++0x1F, 0x07, 0x03, 0xD4, 0x5A, 0x4B, 0xDB, 0x6E, 0x41, 0xF8, 0x03, 0x3C, 0x23, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x36, 0xD0, ++0x11, 0x46, 0xDF, 0xF8, 0x70, 0xB1, 0x54, 0x4F, 0x32, 0x46, 0x00, 0x29, 0x2C, 0xD0, 0xE1, 0x8B, 0x0E, 0x07, 0x29, 0xD4, ++0x99, 0x88, 0x39, 0xB3, 0xD9, 0x8B, 0x08, 0x07, 0x24, 0xD4, 0x4D, 0x49, 0xDB, 0xF8, 0x00, 0x00, 0x09, 0x68, 0x90, 0xF8, ++0x3E, 0x60, 0x01, 0xF0, 0x3F, 0x01, 0x8E, 0x42, 0x1A, 0xD8, 0x5B, 0x6A, 0xBC, 0xF1, 0x00, 0x0F, 0x4C, 0xD1, 0x9B, 0x02, ++0x17, 0xD5, 0xCD, 0xF8, 0x00, 0x90, 0xD7, 0xF8, 0x54, 0x63, 0x03, 0x92, 0x53, 0x46, 0x29, 0x46, 0x20, 0x46, 0xB0, 0x47, ++0x03, 0x9A, 0x00, 0x28, 0x77, 0xD0, 0x2B, 0x68, 0x00, 0x2B, 0x74, 0xD0, 0x60, 0x6A, 0xA1, 0x88, 0x00, 0xF4, 0x00, 0x1C, ++0x00, 0x29, 0xD2, 0xD1, 0xBC, 0xF1, 0x00, 0x0F, 0x47, 0xD1, 0x63, 0x6C, 0xD3, 0xB9, 0x3B, 0x48, 0x11, 0xF0, 0x2C, 0xF8, ++0x3A, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x56, 0xDB, 0x54, 0x23, 0x1C, 0x22, 0x37, 0x48, ++0x13, 0xFB, 0x09, 0x29, 0x00, 0x22, 0x01, 0x23, 0xAA, 0x80, 0xEB, 0x72, 0x48, 0x44, 0x29, 0x46, 0x65, 0x64, 0x10, 0xF0, ++0xF7, 0xFF, 0x01, 0xE0, 0x4F, 0xF0, 0x00, 0x08, 0x40, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDE, 0xF8, 0x2C, 0x30, ++0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x9E, 0x42, 0x9A, 0xD2, 0x25, 0x4B, 0x40, 0x46, 0xD3, 0xF8, ++0xBC, 0x33, 0x49, 0x46, 0x98, 0x47, 0x4F, 0xF0, 0x00, 0x08, 0xE9, 0xE7, 0xCD, 0xF8, 0x00, 0x90, 0x99, 0x02, 0x54, 0xBF, ++0xD7, 0xF8, 0x50, 0x63, 0xD7, 0xF8, 0x4C, 0x63, 0xAF, 0xE7, 0xFE, 0xF7, 0xD1, 0xF9, 0xDB, 0xF8, 0x38, 0x31, 0x67, 0x6A, ++0x1B, 0x68, 0x2B, 0x60, 0x5B, 0xB3, 0xA2, 0x88, 0x07, 0xF4, 0x00, 0x1C, 0x80, 0xE7, 0x63, 0x6C, 0xD3, 0xF8, 0x38, 0x21, ++0x03, 0xF1, 0x0C, 0x08, 0xD2, 0x6C, 0x00, 0x21, 0x40, 0x46, 0xD1, 0x61, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDE, 0xF8, ++0x2C, 0x30, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x9E, 0x42, 0xCC, 0xD3, 0x00, 0x29, 0x3F, 0xF4, ++0x65, 0xAF, 0xDE, 0xF8, 0x28, 0x10, 0x5D, 0xE7, 0x00, 0x28, 0xA6, 0xD1, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF6, 0x92, 0x52, ++0x12, 0xF0, 0xD6, 0xFB, 0x9F, 0xE7, 0x67, 0x6A, 0x07, 0xF4, 0x00, 0x1C, 0x8C, 0xE7, 0x07, 0xF4, 0x00, 0x1C, 0x89, 0xE7, ++0x54, 0x83, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x8C, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x90, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x28, ++0x2C, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x0B, 0x23, 0x13, 0x1B, 0x03, 0x00, 0x1B, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x03, 0x0F, ++0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x17, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x30, 0x0F, 0x0C, 0xBF, 0x01, 0x20, ++0x00, 0x20, 0x08, 0xBD, 0x13, 0x4B, 0x1B, 0x68, 0x13, 0xF4, 0x40, 0x5F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, ++0x0F, 0x4B, 0x1B, 0x68, 0x13, 0xF4, 0x40, 0x3F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x0B, 0x4B, 0x1B, 0x68, ++0x13, 0xF4, 0x40, 0x7F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x01, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xF3, 0x12, 0x12, 0xF0, 0x7E, 0xFB, ++0x00, 0x20, 0x08, 0xBD, 0x88, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x90, 0xF8, 0x25, 0x30, 0xE3, 0xB1, 0x10, 0xB5, 0x0F, 0x4A, 0x10, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x01, 0xF5, ++0x9C, 0x51, 0x84, 0xB0, 0x04, 0x46, 0x08, 0x31, 0x0C, 0x48, 0x98, 0x47, 0x00, 0x21, 0x02, 0x22, 0x05, 0x23, 0x94, 0xF8, ++0x23, 0x00, 0xCD, 0xE9, 0x00, 0x32, 0xCD, 0xE9, 0x02, 0x11, 0x25, 0x23, 0x40, 0xF6, 0xC4, 0x12, 0xFD, 0xF7, 0x5E, 0xFF, ++0x04, 0xB0, 0x10, 0xBD, 0x03, 0x4A, 0xC2, 0xE9, 0x01, 0x33, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x94, 0x64, 0x17, 0x00, 0x03, 0x68, 0x70, 0xB4, 0xC3, 0xF3, 0xC2, 0x24, 0x05, 0x2C, 0x01, 0xD0, 0x70, 0xBC, 0x70, 0x47, ++0xC3, 0xF3, 0x00, 0x26, 0x75, 0x00, 0x03, 0xF0, 0x7F, 0x04, 0x35, 0x44, 0x04, 0xEB, 0x44, 0x04, 0x05, 0xEB, 0x44, 0x04, ++0xC3, 0xF3, 0x41, 0x25, 0x2C, 0x44, 0x16, 0x4D, 0x35, 0xF8, 0x14, 0x50, 0xC3, 0xF3, 0xC0, 0x14, 0x05, 0xFA, 0x04, 0xF4, ++0x01, 0x3A, 0x02, 0xFB, 0x04, 0xF2, 0x8A, 0x42, 0xC3, 0xF3, 0xC1, 0x14, 0xE2, 0xD2, 0x13, 0xF4, 0xE0, 0x3F, 0x06, 0xD0, ++0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x00, 0x43, 0x70, 0xBC, 0x03, 0x60, 0x70, 0x47, 0x03, 0xF0, 0x0F, 0x02, 0x02, 0x2A, ++0x23, 0xF0, 0xFF, 0x53, 0x8C, 0xBF, 0x4F, 0xF4, 0x80, 0x12, 0x4F, 0xF4, 0x00, 0x22, 0x23, 0xF4, 0xFE, 0x13, 0x42, 0xEA, ++0x04, 0x62, 0x13, 0x43, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF4, 0x00, 0x43, 0xE8, 0xE7, 0x00, 0xBF, 0xE0, 0x94, 0x15, 0x00, ++0x70, 0xB5, 0x0C, 0x4D, 0x00, 0xEB, 0x40, 0x03, 0x05, 0xEB, 0x83, 0x03, 0x93, 0xF8, 0x2E, 0x20, 0x72, 0xB1, 0x04, 0x46, ++0x46, 0x00, 0x58, 0x6A, 0x00, 0x22, 0x83, 0xF8, 0x2E, 0x20, 0x10, 0xB1, 0x21, 0x46, 0xFB, 0xF7, 0x35, 0xFF, 0x34, 0x44, ++0x05, 0xEB, 0x84, 0x05, 0x00, 0x23, 0x6B, 0x62, 0x70, 0xBD, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x41, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x41, 0x4F, ++0x41, 0x4E, 0x3B, 0x68, 0xDF, 0xF8, 0x0C, 0x81, 0x01, 0x33, 0x00, 0x24, 0x3B, 0x60, 0x35, 0x46, 0xA2, 0x46, 0x4F, 0xF0, ++0x01, 0x0B, 0x96, 0xF8, 0x60, 0x10, 0x0B, 0xFA, 0x04, 0xF3, 0x0B, 0x42, 0x5F, 0xFA, 0x83, 0xF9, 0x4D, 0xD1, 0x96, 0xF8, ++0x61, 0x10, 0x11, 0xEA, 0x09, 0x0F, 0x30, 0xD0, 0xA8, 0x6A, 0x21, 0xEA, 0x03, 0x03, 0x86, 0xF8, 0x61, 0x30, 0x03, 0x07, ++0x4F, 0xD0, 0x33, 0x4B, 0x43, 0xF8, 0x24, 0x00, 0xE0, 0xB2, 0xD8, 0xF8, 0xD0, 0x33, 0x98, 0x47, 0x95, 0xF8, 0x2C, 0x30, ++0x85, 0xF8, 0x2D, 0x30, 0x49, 0xEA, 0x0A, 0x0A, 0x01, 0x34, 0x04, 0x2C, 0x05, 0xF1, 0x0C, 0x05, 0xD9, 0xD1, 0xBA, 0xF1, ++0x00, 0x0F, 0x47, 0xD0, 0x29, 0x4A, 0x2A, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x29, 0x48, 0x01, 0xF5, 0x00, 0x51, ++0x98, 0x47, 0x3B, 0x68, 0x33, 0xB1, 0x20, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x95, 0xF8, 0x2D, 0x30, 0x00, 0x2B, 0xDE, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x85, 0xF8, ++0x2D, 0x30, 0x5B, 0xB9, 0x32, 0x69, 0xA3, 0x1C, 0xE0, 0xB2, 0x52, 0xF8, 0x23, 0x30, 0x17, 0x4A, 0x42, 0xF8, 0x24, 0x30, ++0xD8, 0xF8, 0xD0, 0x33, 0x98, 0x47, 0xCD, 0xE7, 0x49, 0xEA, 0x0A, 0x0A, 0xCA, 0xE7, 0xE0, 0xB2, 0x01, 0x93, 0xFF, 0xF7, ++0xBD, 0xFE, 0x01, 0x9B, 0x00, 0x28, 0xF5, 0xD0, 0x96, 0xF8, 0x60, 0x10, 0x21, 0xEA, 0x03, 0x01, 0x86, 0xF8, 0x60, 0x10, ++0xA3, 0xE7, 0x95, 0xF8, 0x2E, 0x30, 0x00, 0x2B, 0xB2, 0xD1, 0x85, 0xF8, 0x2E, 0xB0, 0x96, 0xF8, 0x60, 0x30, 0x49, 0xEA, ++0x03, 0x03, 0x86, 0xF8, 0x60, 0x30, 0xA9, 0xE7, 0xC6, 0xF8, 0x18, 0xA0, 0xBD, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0xA8, 0x64, 0x17, 0x00, 0x70, 0xB5, 0x14, 0x4C, 0x94, 0xF8, 0x62, 0x20, 0x4A, 0xB1, 0x94, 0xF8, 0x61, 0x20, 0xA5, 0x69, ++0x01, 0x21, 0x01, 0xFA, 0x00, 0xF3, 0x13, 0x43, 0x84, 0xF8, 0x61, 0x30, 0x05, 0xB1, 0x70, 0xBD, 0x0D, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0xDB, 0x0B, 0x4B, 0x0C, 0x48, 0xD3, 0xF8, 0xC8, 0x33, 0xA3, 0x61, 0xBD, 0xE8, ++0x70, 0x40, 0x18, 0x47, 0xFF, 0xF7, 0x74, 0xFE, 0x00, 0x28, 0xF3, 0xD1, 0xBD, 0xE8, 0x70, 0x40, 0x06, 0x49, 0x07, 0x48, ++0x4F, 0xF4, 0x22, 0x72, 0x12, 0xF0, 0xF4, 0xB9, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xA8, 0x64, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x93, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x1D, 0x4D, 0x1E, 0x4E, ++0x1E, 0x4F, 0xDF, 0xF8, 0x80, 0x80, 0xDF, 0xF8, 0x80, 0x90, 0x2B, 0x68, 0x00, 0x24, 0x01, 0x2C, 0x11, 0xD0, 0x53, 0xF8, ++0x24, 0x30, 0x1B, 0xB9, 0x33, 0x69, 0xA2, 0x1C, 0x53, 0xF8, 0x22, 0x30, 0x47, 0xF8, 0x24, 0x30, 0xE0, 0xB2, 0xFF, 0xF7, ++0xFB, 0xFE, 0x03, 0x2C, 0x0D, 0xD0, 0x01, 0x34, 0x01, 0x2C, 0x2B, 0x68, 0xED, 0xD1, 0x5B, 0x68, 0x73, 0xB9, 0x33, 0x69, ++0xDB, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x01, 0x20, 0xFF, 0xF7, 0xEC, 0xFE, 0xF1, 0xE7, 0x0D, 0x48, 0x08, 0xF0, 0x3C, 0xFC, ++0x00, 0x23, 0xB3, 0x61, 0xBD, 0xE8, 0xF8, 0x83, 0xC3, 0xF3, 0x0B, 0x02, 0x00, 0x2A, 0xEE, 0xD1, 0x32, 0x69, 0xD2, 0x68, ++0x03, 0xEA, 0x09, 0x03, 0xC2, 0xF3, 0x0B, 0x02, 0x13, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0xE6, 0xE7, 0xAC, 0x35, 0x17, 0x00, ++0x94, 0x64, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0xA8, 0x64, 0x17, 0x00, 0x04, 0x02, 0x32, 0x40, 0x00, 0xF0, 0xFF, 0xFF, ++0x1A, 0x4A, 0x1B, 0x4B, 0xF0, 0xB4, 0x02, 0xF1, 0x74, 0x04, 0x94, 0xE8, 0x03, 0x00, 0x16, 0x69, 0xC3, 0xF8, 0xE0, 0x03, ++0xF0, 0x6D, 0xA3, 0xF8, 0xE4, 0x13, 0xB6, 0xF8, 0x60, 0x10, 0xC3, 0xF8, 0xE6, 0x03, 0xA3, 0xF8, 0xEA, 0x13, 0x94, 0xE8, ++0x03, 0x00, 0xD3, 0xF8, 0xD4, 0x53, 0xA3, 0xF8, 0xF0, 0x13, 0xD1, 0x6E, 0xC3, 0xF8, 0xEC, 0x03, 0xC3, 0xF8, 0xF6, 0x13, ++0x0D, 0x4F, 0x0E, 0x48, 0x03, 0xF5, 0x88, 0x64, 0x00, 0x21, 0x82, 0xF8, 0x88, 0x10, 0xC3, 0xF8, 0xBC, 0x43, 0x05, 0xF4, ++0x7F, 0x45, 0x03, 0xF5, 0x66, 0x74, 0x4F, 0xF4, 0x00, 0x52, 0xC3, 0xF8, 0xD4, 0x53, 0xC3, 0xF8, 0x9C, 0x13, 0x3C, 0x60, ++0xF0, 0xBC, 0x02, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x60, 0x5D, 0x18, 0x00, 0xAC, 0x81, 0x32, 0x40, ++0x80, 0x81, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x68, 0xB2, 0x03, 0x68, 0x90, 0x4C, 0xDB, 0xF8, 0x10, 0x20, ++0x80, 0x46, 0x53, 0xF8, 0x26, 0x0F, 0xA0, 0x64, 0xD0, 0x6D, 0x9D, 0x88, 0xC4, 0xF8, 0x4E, 0x00, 0x18, 0x68, 0xB8, 0xF8, ++0x12, 0x10, 0x9B, 0x88, 0xB2, 0xF8, 0x60, 0x20, 0x60, 0x65, 0x00, 0x27, 0x83, 0xB0, 0x04, 0xF1, 0x5C, 0x00, 0xA4, 0xF8, ++0x4C, 0x50, 0xA4, 0xF8, 0x52, 0x20, 0xA4, 0xF8, 0x58, 0x30, 0xA7, 0x61, 0xFE, 0xF7, 0x78, 0xFC, 0x63, 0x6F, 0xD8, 0xF8, ++0x00, 0x10, 0x80, 0x4A, 0x91, 0xF8, 0x23, 0xC0, 0xA5, 0x69, 0xDE, 0x1C, 0x42, 0xF2, 0x38, 0x0E, 0x26, 0xF0, 0x03, 0x06, ++0x24, 0x23, 0x39, 0x46, 0x04, 0x36, 0x13, 0xFB, 0x0C, 0xE7, 0x06, 0xEB, 0x80, 0x06, 0x4F, 0xEA, 0x40, 0x2E, 0x17, 0x44, ++0xB6, 0xB2, 0x89, 0x46, 0x04, 0xF1, 0x5C, 0x02, 0xA4, 0x46, 0x4F, 0xF4, 0x20, 0x10, 0xF2, 0x46, 0x01, 0x97, 0x1C, 0xE0, ++0x0F, 0x33, 0x1B, 0x09, 0x1B, 0x02, 0x43, 0xF0, 0x30, 0x03, 0x9B, 0xB2, 0x4A, 0xEA, 0x00, 0x00, 0x0B, 0x43, 0x90, 0x63, ++0xC2, 0xF8, 0x24, 0x90, 0xC2, 0xF8, 0x3C, 0x90, 0xA2, 0xF8, 0x58, 0x30, 0xCC, 0xF8, 0x08, 0x20, 0xA5, 0x69, 0x35, 0x44, ++0xA5, 0x61, 0x94, 0x46, 0x4F, 0xF4, 0x40, 0x10, 0x01, 0x31, 0x09, 0x29, 0x02, 0xF1, 0x5C, 0x02, 0x22, 0xD0, 0x01, 0x9F, ++0x57, 0xF8, 0x04, 0x3B, 0x01, 0x97, 0x00, 0x2B, 0xF4, 0xD0, 0xD8, 0xF8, 0x08, 0x70, 0x06, 0xEB, 0x05, 0x0E, 0xBE, 0x45, ++0x16, 0xD8, 0xB3, 0xF5, 0x7C, 0x7F, 0xD3, 0xD9, 0xB3, 0xF5, 0x80, 0x6F, 0x0D, 0xD9, 0xB3, 0xF5, 0x86, 0x4F, 0x45, 0xD8, ++0x6F, 0xF4, 0x7C, 0x75, 0x2B, 0x44, 0xC3, 0xF3, 0x07, 0x13, 0x1B, 0x02, 0x43, 0xF4, 0x80, 0x43, 0x43, 0xF0, 0x30, 0x03, ++0xC8, 0xE7, 0x44, 0xF2, 0x30, 0x03, 0xC5, 0xE7, 0x00, 0x2D, 0x3B, 0xD0, 0xDC, 0xF8, 0x38, 0x30, 0x03, 0xF4, 0x60, 0x11, ++0x00, 0x22, 0xB1, 0xF5, 0x20, 0x1F, 0xCC, 0xF8, 0x08, 0x20, 0x63, 0xD0, 0x4C, 0x49, 0x4D, 0x4A, 0x4D, 0x4E, 0x43, 0xF4, ++0x60, 0x13, 0xCC, 0xF8, 0x38, 0x30, 0x0D, 0x68, 0x10, 0x68, 0x04, 0x35, 0xC0, 0xF3, 0x05, 0x20, 0x06, 0xE0, 0x33, 0x68, ++0xDB, 0x04, 0x08, 0xD4, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0x03, 0xF0, 0x3F, 0x03, 0x98, 0x42, ++0xF3, 0xD0, 0xE3, 0x6B, 0x42, 0x48, 0x43, 0x49, 0x43, 0x4A, 0x04, 0x60, 0x03, 0xF4, 0x7F, 0x43, 0xE3, 0x63, 0x4F, 0xF4, ++0x00, 0x50, 0x00, 0x23, 0x08, 0x60, 0x63, 0x60, 0x8B, 0xF8, 0x88, 0x30, 0x62, 0x62, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0xB3, 0xF5, 0x88, 0x4F, 0x1F, 0xD8, 0x48, 0xF2, 0x30, 0x03, 0x87, 0xE7, 0xD4, 0xF8, 0x98, 0x30, 0x37, 0x4A, 0x35, 0x4E, ++0x35, 0x49, 0xC4, 0xF8, 0x94, 0x50, 0x03, 0xF4, 0x7F, 0x43, 0xC4, 0xF8, 0x98, 0x30, 0xA2, 0xF5, 0x79, 0x73, 0xC4, 0xE9, ++0x18, 0x55, 0x8B, 0xF8, 0x88, 0x50, 0x4F, 0xF4, 0x00, 0x50, 0x33, 0x60, 0x30, 0x23, 0x08, 0x60, 0xA4, 0xF8, 0xB4, 0x30, ++0xC4, 0xF8, 0x80, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0xF5, 0x0F, 0x3F, 0x2A, 0xD9, 0xB3, 0xF5, 0x11, 0x3F, ++0x32, 0xD9, 0x28, 0x4D, 0xAB, 0x42, 0x32, 0xD8, 0xA3, 0xF1, 0x01, 0x13, 0xA3, 0xF5, 0x44, 0x43, 0xC3, 0xF3, 0xC7, 0x33, ++0x1B, 0x02, 0x43, 0xF4, 0x40, 0x43, 0x43, 0xF0, 0x30, 0x03, 0x55, 0xE7, 0xDC, 0xF8, 0x3C, 0x30, 0xCC, 0xF8, 0x38, 0x20, ++0xCC, 0xF8, 0x04, 0x20, 0x8B, 0xF8, 0x88, 0x20, 0x19, 0x48, 0x1A, 0x49, 0x1A, 0x4A, 0xCC, 0xF8, 0x24, 0x20, 0x03, 0xF4, ++0x7F, 0x43, 0xCC, 0xF8, 0x3C, 0x30, 0x4F, 0xF4, 0x00, 0x53, 0xC0, 0xF8, 0x00, 0xC0, 0x0B, 0x60, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0xA3, 0xF5, 0x70, 0x53, 0x01, 0x3B, 0xC3, 0xF3, 0xC7, 0x23, 0x1B, 0x02, 0x43, 0xF4, 0x00, 0x43, 0x43, 0xF0, ++0x30, 0x03, 0x31, 0xE7, 0x4C, 0xF2, 0x30, 0x03, 0x2E, 0xE7, 0x4F, 0xF6, 0x30, 0x65, 0x4F, 0xF6, 0x30, 0x77, 0xB3, 0xF1, ++0xFF, 0x3F, 0x08, 0xBF, 0x3D, 0x46, 0x2B, 0x46, 0x24, 0xE7, 0x00, 0xBF, 0x60, 0x5D, 0x18, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0x20, 0x01, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x78, 0x80, 0x32, 0x40, 0xAC, 0x81, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, ++0xA0, 0x61, 0x18, 0x00, 0x00, 0xC4, 0x20, 0x00, 0x94, 0x64, 0x17, 0x00, 0x1C, 0x4A, 0x1D, 0x49, 0x13, 0x68, 0xF0, 0xB4, ++0x03, 0xF5, 0xDA, 0x53, 0x1B, 0x4F, 0x1C, 0x4E, 0x1C, 0x4C, 0x1D, 0x4D, 0x18, 0x33, 0x3B, 0x60, 0x40, 0x23, 0x33, 0x60, ++0x23, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x23, 0x60, 0x17, 0x68, 0x0C, 0x68, 0x01, 0x23, 0x10, 0x3E, 0x04, 0x37, 0xC4, 0xF3, ++0x05, 0x24, 0x85, 0xF8, 0x8C, 0x30, 0x06, 0xE0, 0x33, 0x68, 0xDB, 0x04, 0x08, 0xD4, 0x13, 0x68, 0xDB, 0x1B, 0x00, 0x2B, ++0x04, 0xDA, 0x0B, 0x68, 0x03, 0xF0, 0x3F, 0x03, 0x9C, 0x42, 0xF3, 0xD0, 0xC3, 0x6B, 0x0E, 0x4C, 0x0E, 0x4A, 0x0F, 0x49, ++0x42, 0x62, 0x03, 0xF4, 0x7F, 0x43, 0xC3, 0x63, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x53, 0x42, 0x60, 0x85, 0xF8, 0x88, 0x20, ++0x20, 0x60, 0xF0, 0xBC, 0x0B, 0x60, 0x70, 0x47, 0x20, 0x01, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x40, 0x01, 0x32, 0x40, ++0x88, 0x80, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0xAC, 0x81, 0x32, 0x40, 0xA0, 0x61, 0x18, 0x00, ++0x80, 0x81, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x10, 0x4F, 0x0C, 0x23, 0x0E, 0x46, 0x54, 0x25, 0x04, 0x46, 0x15, 0xFB, ++0x01, 0x30, 0x05, 0xFB, 0x06, 0x75, 0x38, 0x44, 0xD4, 0xF8, 0x4C, 0x80, 0x10, 0xF0, 0xEC, 0xFB, 0x95, 0xF8, 0x50, 0x30, ++0xA2, 0x88, 0x01, 0x3B, 0x85, 0xF8, 0x50, 0x30, 0x22, 0xB9, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFD, 0xF7, 0x22, 0xBA, ++0xD8, 0xF8, 0x50, 0x10, 0x32, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFC, 0xF7, 0xF6, 0xBB, 0x20, 0x62, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x00, 0x23, 0x2E, 0x4D, 0x03, 0x60, 0x95, 0xF8, 0x8C, 0x30, 0x82, 0xB0, 0x00, 0x2B, 0x37, 0xD1, ++0x95, 0xF8, 0x85, 0x30, 0x03, 0x2B, 0x33, 0xD8, 0x29, 0x4E, 0xDF, 0xF8, 0xB4, 0xA0, 0x81, 0x46, 0x4F, 0xF0, 0x03, 0x08, ++0x14, 0xE0, 0x95, 0xF8, 0x7E, 0x30, 0xDA, 0xF8, 0x64, 0x73, 0x00, 0x93, 0x2A, 0x6F, 0xB5, 0xF8, 0x7A, 0x30, 0x49, 0x46, ++0x20, 0x46, 0xB8, 0x47, 0x07, 0x46, 0x20, 0xBB, 0x95, 0xF8, 0x85, 0x30, 0x08, 0xF1, 0xFF, 0x38, 0x98, 0x45, 0xA6, 0xF1, ++0x54, 0x06, 0x17, 0xDB, 0x96, 0xF8, 0x16, 0x31, 0x5F, 0xFA, 0x88, 0xF7, 0x01, 0x2B, 0x85, 0xF8, 0x7E, 0x70, 0x0F, 0xD0, ++0xD6, 0xF8, 0x08, 0x41, 0x00, 0x2C, 0xEB, 0xD0, 0x63, 0x6A, 0x9B, 0x02, 0xDB, 0xD4, 0xE3, 0x6C, 0x1B, 0x6D, 0x00, 0x2B, ++0xD7, 0xDA, 0x20, 0x46, 0x39, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xEF, 0xE7, 0x00, 0x27, 0x38, 0x46, 0x02, 0xB0, 0xBD, 0xE8, ++0xF0, 0x87, 0x0E, 0x4B, 0x64, 0x6C, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0xDB, 0xA3, 0x88, 0x38, 0x46, ++0x43, 0xF4, 0x00, 0x73, 0xA3, 0x80, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x2C, 0xF5, 0xD1, 0x06, 0x49, 0x07, 0x48, ++0x40, 0xF2, 0xDF, 0x42, 0x11, 0xF0, 0x88, 0xFF, 0xEE, 0xE7, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xDF, 0xF8, 0x8C, 0x92, 0x99, 0xF8, 0x7E, 0x80, 0x83, 0xB0, 0x04, 0x46, 0x00, 0x27, 0x40, 0x46, 0x01, 0x97, 0xFB, 0xF7, ++0x0D, 0xFE, 0x99, 0xF8, 0x7E, 0x00, 0xFF, 0xF7, 0x15, 0xFA, 0x00, 0x2C, 0x00, 0xF0, 0xA4, 0x80, 0x63, 0x6A, 0x9E, 0x02, ++0x76, 0xD5, 0x03, 0xF4, 0x60, 0x10, 0xB0, 0xF5, 0x60, 0x1F, 0x65, 0x6C, 0x00, 0xF0, 0xE1, 0x80, 0xB0, 0xF5, 0x40, 0x1F, ++0x00, 0xF0, 0xCE, 0x80, 0xAA, 0x88, 0x02, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0x8E, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x01, 0xC0, ++0x00, 0xF0, 0xFF, 0x80, 0x2A, 0x6B, 0x52, 0x69, 0x00, 0x21, 0xC2, 0xF3, 0xC1, 0x1E, 0xC5, 0xE9, 0x0E, 0x11, 0x69, 0x63, ++0x0E, 0x46, 0x0A, 0x46, 0x14, 0xE0, 0xD1, 0xF8, 0x4C, 0x31, 0x9A, 0x45, 0x02, 0xF1, 0x01, 0x03, 0x22, 0xD9, 0xDA, 0xB2, ++0x05, 0xEB, 0x82, 0x03, 0xB0, 0xF5, 0x60, 0x1F, 0x4E, 0x63, 0x56, 0x46, 0xC3, 0xF8, 0x3C, 0x41, 0x20, 0xD0, 0x24, 0x68, ++0x34, 0xB3, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x10, 0xE1, 0x6C, 0xD1, 0xF8, 0x2C, 0xA0, 0xC3, 0xF3, 0x49, 0x2B, 0x0A, 0xF1, ++0x03, 0x03, 0x23, 0xF0, 0x03, 0x03, 0x0B, 0xF1, 0x01, 0x0A, 0x03, 0xEB, 0x8A, 0x03, 0x9B, 0xB2, 0x96, 0x45, 0x05, 0xEB, ++0x82, 0x01, 0x03, 0xEB, 0x06, 0x0A, 0xD6, 0xD8, 0x05, 0xEB, 0x82, 0x03, 0xB0, 0xF5, 0x60, 0x1F, 0x56, 0x46, 0xC3, 0xF8, ++0x3C, 0x41, 0xDE, 0xD1, 0x6B, 0x6A, 0xB3, 0x42, 0x00, 0xF0, 0xCE, 0x80, 0x00, 0x23, 0xC5, 0xE9, 0x0D, 0x33, 0xEB, 0x63, ++0x00, 0x2F, 0x49, 0xD0, 0x08, 0xEB, 0x48, 0x03, 0x09, 0xEB, 0x83, 0x09, 0x01, 0x9A, 0xC9, 0xF8, 0x24, 0x70, 0xBC, 0xF1, ++0x00, 0x0F, 0x30, 0xD1, 0x93, 0x6B, 0x9B, 0x02, 0x00, 0xF1, 0x97, 0x80, 0x53, 0x68, 0x00, 0x2B, 0x4B, 0xD1, 0x61, 0x49, ++0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x01, 0xEB, 0x08, 0x03, 0xC3, 0xE9, 0x01, 0xCC, 0x41, 0xF8, 0x08, 0x20, 0x40, 0xE0, ++0xA3, 0x6C, 0x3B, 0xB3, 0xE3, 0x8B, 0xE2, 0x6C, 0x13, 0xF4, 0x00, 0x5F, 0xE3, 0x6A, 0xDB, 0x6B, 0x02, 0xF1, 0x14, 0x07, ++0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0x01, 0x97, 0x93, 0xB3, 0x52, 0x4B, 0x1B, 0x68, 0x93, 0xF8, ++0x01, 0xC0, 0x3A, 0x46, 0x08, 0xEB, 0x48, 0x03, 0x09, 0xEB, 0x83, 0x09, 0xC9, 0xF8, 0x24, 0x70, 0xBC, 0xF1, 0x00, 0x0F, ++0xCE, 0xD0, 0x53, 0x68, 0xFB, 0xB9, 0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x49, 0x4B, 0x43, 0xF8, 0x08, 0x20, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x45, 0x4B, 0x1B, 0x68, 0x93, 0xF8, 0x01, 0xC0, 0x44, 0x4B, 0x54, 0x22, 0x08, 0xEB, 0x48, 0x01, ++0x09, 0xEB, 0x81, 0x09, 0x02, 0xFB, 0x08, 0xF8, 0x00, 0x22, 0x43, 0xF8, 0x08, 0x20, 0xC9, 0xF8, 0x24, 0x20, 0x43, 0x44, ++0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0xC3, 0xE9, 0x01, 0xCC, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x50, 0x6A, 0x03, 0x88, ++0x1D, 0x04, 0x99, 0xB2, 0xC7, 0xD5, 0xC1, 0xF3, 0x0E, 0x01, 0x01, 0x80, 0x94, 0xF8, 0x33, 0x10, 0x94, 0xF8, 0x32, 0x30, ++0x32, 0x48, 0x04, 0x39, 0x04, 0x3B, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x32, 0x30, 0xD2, 0xE9, 0x0A, 0x31, 0x04, 0x39, ++0x04, 0x3B, 0xC2, 0xE9, 0x0A, 0x31, 0x00, 0x68, 0x3A, 0x46, 0x90, 0xF8, 0x01, 0xC0, 0xB3, 0xE7, 0x2B, 0x4B, 0x01, 0xA9, ++0xD3, 0xF8, 0x6C, 0x33, 0x20, 0x46, 0x98, 0x47, 0x26, 0x4A, 0x63, 0x6A, 0x12, 0x68, 0x07, 0x46, 0x92, 0xF8, 0x01, 0xC0, ++0x03, 0xF4, 0x60, 0x10, 0x2C, 0xE7, 0x24, 0x4B, 0x21, 0x4E, 0xD3, 0xF8, 0x58, 0x33, 0x39, 0x46, 0x20, 0x46, 0x98, 0x47, ++0x33, 0x68, 0x01, 0x90, 0x5B, 0x78, 0x07, 0x46, 0xD3, 0xB1, 0x08, 0xB1, 0x6B, 0x6D, 0x43, 0x60, 0xD5, 0xF8, 0x48, 0x01, ++0x29, 0x46, 0x10, 0xF0, 0x13, 0xFA, 0x33, 0x68, 0x93, 0xF8, 0x01, 0xC0, 0x58, 0xE7, 0x7B, 0x68, 0x00, 0x2B, 0xB4, 0xD1, ++0x15, 0x49, 0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x01, 0xEB, 0x08, 0x03, 0x01, 0x20, 0xC3, 0xE9, 0x01, 0x70, 0x41, 0xF8, ++0x08, 0x20, 0xA8, 0xE7, 0x00, 0x28, 0xE5, 0xD0, 0x2B, 0x69, 0x43, 0x60, 0xE2, 0xE7, 0x05, 0xF1, 0x0C, 0x07, 0xBC, 0xF1, ++0x00, 0x0F, 0x03, 0xD0, 0x05, 0xF1, 0x50, 0x02, 0x01, 0x92, 0xF7, 0xE6, 0xD5, 0xF8, 0x38, 0x21, 0xD2, 0x6C, 0x14, 0x32, ++0x01, 0x92, 0xF1, 0xE6, 0xD5, 0xF8, 0x38, 0x31, 0xA3, 0x42, 0x7F, 0xF4, 0x2D, 0xAF, 0x05, 0xEB, 0x82, 0x02, 0x56, 0x63, ++0x2C, 0xE7, 0x00, 0xBF, 0x34, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x70, 0xB5, 0x1E, 0x48, 0x82, 0xB0, 0x90, 0xF8, 0x88, 0x30, 0x00, 0x22, 0x01, 0x92, 0x93, 0xB1, 0x90, 0xF8, 0x7F, 0x30, ++0x04, 0x2B, 0x2A, 0xD0, 0x19, 0x4C, 0x01, 0xA8, 0xD4, 0xF8, 0xE8, 0x33, 0x98, 0x47, 0x08, 0xB3, 0xD4, 0xF8, 0xF8, 0x33, ++0x98, 0x47, 0xD4, 0xF8, 0xD4, 0x33, 0x01, 0x98, 0x98, 0x47, 0x02, 0xB0, 0x70, 0xBD, 0x13, 0x4A, 0x13, 0x4D, 0xD2, 0xF8, ++0x38, 0x14, 0x13, 0x4C, 0x80, 0xF8, 0x88, 0x30, 0xC2, 0xF8, 0x00, 0x34, 0x01, 0xF4, 0x7F, 0x41, 0x02, 0xF5, 0x88, 0x66, ++0x02, 0xF5, 0x7F, 0x70, 0x4F, 0xF4, 0x00, 0x53, 0xC2, 0xF8, 0x38, 0x14, 0xC2, 0xF8, 0x20, 0x64, 0x28, 0x60, 0x23, 0x60, ++0x02, 0xB0, 0x70, 0xBD, 0xFF, 0xF7, 0x28, 0xFC, 0xE1, 0xE7, 0x04, 0x4B, 0x68, 0x30, 0xD3, 0xF8, 0xF4, 0x33, 0x98, 0x47, ++0x02, 0xB0, 0x70, 0xBD, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x60, 0x5D, 0x18, 0x00, 0xAC, 0x81, 0x32, 0x40, ++0x80, 0x81, 0x32, 0x40, 0xF8, 0xB5, 0x2C, 0x4C, 0x2C, 0x4D, 0x40, 0xF2, 0x74, 0x42, 0x20, 0x46, 0x00, 0x21, 0x26, 0x46, ++0xED, 0xF7, 0xF4, 0xF8, 0x4F, 0xF4, 0xE4, 0x73, 0x28, 0x4A, 0x26, 0xF8, 0x44, 0x3F, 0x4F, 0xF6, 0x30, 0x70, 0x48, 0xF2, ++0xC8, 0x13, 0x04, 0xF5, 0x77, 0x77, 0x4F, 0xF0, 0x22, 0x0C, 0x04, 0xF2, 0xFD, 0x31, 0xC4, 0xF8, 0x40, 0x24, 0xA4, 0xF8, ++0xDC, 0x33, 0xA4, 0xF8, 0xF4, 0x03, 0x04, 0xF5, 0x88, 0x63, 0x00, 0x20, 0x4F, 0xF4, 0x00, 0x12, 0xDF, 0xF8, 0x74, 0xE0, ++0xC4, 0xF8, 0xB0, 0xC3, 0xC4, 0xE9, 0xEA, 0x71, 0xC4, 0xF8, 0xBC, 0x33, 0xC4, 0xF8, 0x20, 0x34, 0x63, 0x62, 0xA2, 0x63, ++0xC4, 0xF8, 0x98, 0x53, 0xC4, 0xF8, 0xFC, 0x53, 0x25, 0x60, 0xC4, 0xF8, 0xA4, 0x03, 0xC4, 0xF8, 0xCC, 0x03, 0xC4, 0xF8, ++0x30, 0x04, 0x04, 0xF1, 0x5B, 0x0C, 0x04, 0xF1, 0xB4, 0x03, 0x1E, 0x27, 0x04, 0xF5, 0x7C, 0x74, 0xA3, 0xF1, 0x14, 0x01, ++0x5A, 0x1C, 0x43, 0xF8, 0x58, 0x5C, 0x43, 0xF8, 0x40, 0x7C, 0x43, 0xF8, 0x24, 0x0C, 0x43, 0xF8, 0x14, 0xEC, 0x43, 0xF8, ++0x4C, 0x1C, 0x43, 0xF8, 0x08, 0x2C, 0x43, 0xE9, 0x12, 0x6C, 0x43, 0xF8, 0x0C, 0x3C, 0x5C, 0x33, 0x9C, 0x42, 0xE9, 0xD1, ++0xF8, 0xBD, 0x00, 0xBF, 0x60, 0x5D, 0x18, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, 0x1E, 0xAB, 0xDC, 0xBA, 0xDE, 0xFA, 0xFE, 0xCA, ++0x2D, 0xE9, 0xF0, 0x41, 0x13, 0x4A, 0x14, 0x4B, 0x92, 0xF8, 0x7E, 0x40, 0xD3, 0xF8, 0xAC, 0x33, 0x12, 0x4F, 0x00, 0x22, ++0x0E, 0x46, 0x21, 0x46, 0x05, 0x46, 0x4F, 0xF0, 0x54, 0x08, 0x98, 0x47, 0x0C, 0x20, 0x18, 0xFB, 0x04, 0x00, 0x38, 0x44, ++0x10, 0xF0, 0x5E, 0xF9, 0x22, 0x46, 0x31, 0x46, 0x28, 0x46, 0xFC, 0xF7, 0x77, 0xF9, 0x6B, 0x6A, 0x03, 0xF4, 0x60, 0x13, ++0xB3, 0xF5, 0x60, 0x1F, 0x05, 0xD1, 0x08, 0xFB, 0x04, 0x74, 0x6B, 0x6C, 0x63, 0x62, 0x02, 0x23, 0xA3, 0x76, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x90, 0xF8, 0x62, 0x40, 0x87, 0xB0, 0x84, 0xB9, 0x90, 0xF8, 0x64, 0x30, 0x6B, 0xB1, 0x90, 0xF8, 0x6C, 0x30, 0x58, 0x4A, ++0x01, 0x93, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x03, 0x25, 0x95, 0xF8, 0x25, 0x30, 0x13, 0xB1, 0x6B, 0x68, 0x9B, 0x06, ++0x02, 0xD4, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x10, 0x22, 0x21, 0x46, 0x02, 0xA8, 0xED, 0xF7, 0x4D, 0xF8, 0x95, 0xF8, ++0x23, 0x30, 0x4E, 0x4A, 0x4E, 0x49, 0x00, 0x94, 0x42, 0xF2, 0x34, 0x06, 0x03, 0xEB, 0xC3, 0x03, 0x06, 0xEB, 0x83, 0x03, ++0x9E, 0x18, 0x01, 0xF1, 0x08, 0x0B, 0xA6, 0x46, 0x22, 0x46, 0xA2, 0x46, 0x20, 0x46, 0x56, 0xF8, 0x04, 0x3F, 0xB3, 0xF5, ++0xFE, 0x0F, 0x1F, 0x46, 0x04, 0xF1, 0x01, 0x08, 0x28, 0xBF, 0x4F, 0xF4, 0xFE, 0x07, 0xF3, 0xB1, 0x42, 0x4C, 0x0B, 0x78, ++0xE3, 0x5C, 0x06, 0xAC, 0x04, 0xEB, 0x83, 0x0C, 0x22, 0xFA, 0x03, 0xF9, 0x5C, 0xF8, 0x10, 0x5C, 0x3D, 0x44, 0x55, 0x45, ++0x84, 0xBF, 0xAA, 0x46, 0x00, 0x93, 0x19, 0xF0, 0x01, 0x0F, 0x5F, 0xFA, 0x88, 0xF4, 0x38, 0x44, 0x4C, 0xF8, 0x10, 0x5C, ++0x07, 0xD1, 0x01, 0x25, 0x05, 0xFA, 0x03, 0xF3, 0x1A, 0x43, 0xAE, 0x44, 0xD2, 0xB2, 0x5F, 0xFA, 0x8E, 0xFE, 0x01, 0x31, ++0x8B, 0x45, 0xD2, 0xD1, 0x08, 0x2C, 0x41, 0xD0, 0xA4, 0xEB, 0x0E, 0x04, 0xE4, 0xB2, 0xA4, 0x02, 0x92, 0x01, 0xB0, 0xF5, ++0x7D, 0x6F, 0x1E, 0xD8, 0x0F, 0x30, 0x0A, 0xF1, 0x0F, 0x0A, 0xC0, 0xF3, 0x07, 0x13, 0xCA, 0xF3, 0x07, 0x1A, 0x00, 0x21, ++0x00, 0x98, 0x1B, 0x06, 0x43, 0xEA, 0x00, 0x33, 0x13, 0x43, 0x23, 0x43, 0x0B, 0x43, 0x01, 0x99, 0x08, 0x46, 0x21, 0x49, ++0x4F, 0xF4, 0x1E, 0x72, 0x43, 0xEA, 0x0A, 0x43, 0x02, 0xFB, 0x00, 0x12, 0x43, 0xF0, 0x0F, 0x03, 0xC2, 0xF8, 0x04, 0x32, ++0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB0, 0xF5, 0x7D, 0x4F, 0x0D, 0xD9, 0xB0, 0xF5, 0xFD, 0x2F, 0x18, 0xD8, 0x00, 0xF2, ++0xFF, 0x70, 0x0A, 0xF2, 0xFF, 0x7A, 0xC0, 0xF3, 0xC7, 0x23, 0xCA, 0xF3, 0xC7, 0x2A, 0x4F, 0xF4, 0x00, 0x41, 0xD7, 0xE7, ++0xFF, 0x30, 0x0A, 0xF1, 0xFF, 0x0A, 0xC0, 0xF3, 0x07, 0x23, 0xCA, 0xF3, 0x07, 0x2A, 0x4F, 0xF4, 0x80, 0x41, 0xCD, 0xE7, ++0x4F, 0xF4, 0x40, 0x64, 0x00, 0x22, 0xBE, 0xE7, 0x47, 0xF6, 0xFF, 0x73, 0xBA, 0xF5, 0xFE, 0x0F, 0x94, 0xBF, 0x9A, 0x44, ++0x03, 0xF5, 0xFE, 0x0A, 0xB0, 0xF5, 0xFE, 0x0F, 0x94, 0xBF, 0x18, 0x18, 0x03, 0xF5, 0xFE, 0x00, 0xC0, 0xF3, 0xC7, 0x33, ++0xCA, 0xF3, 0xC7, 0x3A, 0x4F, 0xF4, 0x40, 0x41, 0xB4, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, ++0xC0, 0xB2, 0x15, 0x00, 0xA0, 0xB2, 0x15, 0x00, 0x49, 0x4B, 0x4A, 0x4A, 0x4F, 0xF4, 0x80, 0x11, 0x2D, 0xE9, 0xF0, 0x47, ++0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x1F, 0xFB, 0xD1, 0xDF, 0xF8, 0x34, 0x81, 0x45, 0x4A, 0x98, 0xF8, 0x8C, 0x30, ++0x4F, 0xF4, 0x80, 0x11, 0x11, 0x60, 0x00, 0x2B, 0x6E, 0xD0, 0x98, 0xF8, 0x7E, 0x60, 0xDF, 0xF8, 0x20, 0x91, 0x54, 0x23, ++0x03, 0xFB, 0x06, 0x93, 0x9A, 0x7E, 0x00, 0x2A, 0x38, 0xD0, 0x54, 0x20, 0x00, 0xFB, 0x06, 0x94, 0x20, 0x46, 0x62, 0x6A, ++0x93, 0x88, 0x43, 0xF0, 0x10, 0x03, 0x93, 0x80, 0x1C, 0x30, 0x10, 0xF0, 0x55, 0xF8, 0x37, 0x4B, 0x53, 0xF8, 0x26, 0x00, ++0x0F, 0xF0, 0x6A, 0xFF, 0x00, 0x23, 0xA3, 0x76, 0x63, 0x62, 0x06, 0xEB, 0x46, 0x04, 0x08, 0xEB, 0x84, 0x04, 0x94, 0xF8, ++0x2E, 0x50, 0x2D, 0xB9, 0x60, 0x6A, 0x18, 0xB1, 0x31, 0x46, 0xFB, 0xF7, 0x93, 0xF8, 0x65, 0x62, 0x2D, 0x4A, 0x2E, 0x49, ++0x13, 0x68, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x99, 0x40, 0x22, 0x0A, 0x60, 0x99, 0xF8, ++0x50, 0x30, 0x00, 0x22, 0x01, 0x3B, 0x30, 0x46, 0x89, 0xF8, 0x50, 0x30, 0x88, 0xF8, 0x8C, 0x20, 0xBD, 0xE8, 0xF0, 0x47, ++0xFE, 0xF7, 0x66, 0xBE, 0xDC, 0x68, 0x62, 0x6A, 0x92, 0x02, 0x2D, 0xD4, 0x54, 0x25, 0xDF, 0xF8, 0x98, 0xA0, 0x20, 0x4F, ++0x05, 0xFB, 0x06, 0x95, 0x11, 0xE0, 0xE3, 0x6C, 0x62, 0x6A, 0x19, 0x6D, 0x41, 0xF0, 0x00, 0x41, 0x41, 0xF4, 0x80, 0x01, ++0x19, 0x65, 0x93, 0x02, 0x20, 0x46, 0x17, 0xD5, 0xD7, 0xF8, 0xD8, 0x33, 0x98, 0x47, 0xAB, 0x7E, 0xEC, 0x68, 0x00, 0x2B, ++0xA9, 0xD1, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE7, 0xDA, 0x00, 0x2C, 0xE5, 0xD1, 0x12, 0x49, ++0x12, 0x48, 0x40, 0xF2, 0xB3, 0x72, 0x11, 0xF0, 0x0D, 0xFC, 0xDE, 0xE7, 0xBD, 0xE8, 0xF0, 0x87, 0xD7, 0xF8, 0xE4, 0x33, ++0x98, 0x47, 0xA8, 0xE7, 0x5A, 0x69, 0x61, 0x6C, 0x52, 0x6C, 0x8A, 0x42, 0xCC, 0xD1, 0xD2, 0xF8, 0x38, 0x21, 0x12, 0x68, ++0x5A, 0x61, 0xC7, 0xE7, 0x80, 0x81, 0x32, 0x40, 0x88, 0x81, 0x32, 0x40, 0x84, 0x81, 0x32, 0x40, 0xC4, 0x90, 0x15, 0x00, ++0x8C, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, ++0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x69, 0x4F, 0xDF, 0xF8, ++0xCC, 0x81, 0x97, 0xF8, 0x7E, 0x60, 0x54, 0x25, 0x05, 0xFB, 0x06, 0x85, 0xAB, 0x7E, 0x53, 0xBB, 0xDF, 0xF8, 0xA0, 0xA1, ++0xDF, 0xF8, 0xAC, 0x91, 0x15, 0xE0, 0xD4, 0xF8, 0x4C, 0xC0, 0xDF, 0xF8, 0xA0, 0xE1, 0xDC, 0xF8, 0x50, 0x30, 0x43, 0xF4, ++0x80, 0x02, 0x00, 0x2B, 0x20, 0x46, 0x11, 0x46, 0x26, 0xDA, 0x63, 0x6A, 0xCC, 0xF8, 0x50, 0x20, 0x9C, 0x02, 0x23, 0xD5, ++0xDE, 0xF8, 0xD8, 0x33, 0x98, 0x47, 0xAB, 0x7E, 0x7B, 0xB9, 0xDA, 0xF8, 0x00, 0x30, 0xEC, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xE2, 0xDA, 0x00, 0x2C, 0xE0, 0xD1, 0x53, 0x48, 0x4F, 0xF4, 0x02, 0x62, 0x49, 0x46, 0x11, 0xF0, 0xAE, 0xFB, ++0xD9, 0xE7, 0x54, 0x22, 0x02, 0xFB, 0x06, 0x82, 0x02, 0x2B, 0x54, 0x6A, 0x0C, 0xBF, 0x04, 0xF1, 0x0C, 0x03, 0x04, 0xF1, ++0x50, 0x03, 0xDB, 0x6B, 0x00, 0x2B, 0x29, 0xDB, 0xBD, 0xE8, 0xF0, 0x87, 0xDE, 0xF8, 0xE4, 0x33, 0x98, 0x47, 0x06, 0xEB, ++0x46, 0x04, 0x07, 0xEB, 0x84, 0x04, 0x94, 0xF8, 0x2E, 0x50, 0x2D, 0xB9, 0x60, 0x6A, 0x18, 0xB1, 0x31, 0x46, 0xFA, 0xF7, ++0xD1, 0xFF, 0x65, 0x62, 0x41, 0x4A, 0x42, 0x49, 0x13, 0x68, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x54, 0x23, 0x03, 0xFB, ++0x06, 0x88, 0x40, 0x22, 0x0A, 0x60, 0x98, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x3B, 0x30, 0x46, 0x88, 0xF8, 0x50, 0x30, ++0x87, 0xF8, 0x8C, 0x20, 0xBD, 0xE8, 0xF0, 0x47, 0xFE, 0xF7, 0xA4, 0xBD, 0x18, 0x02, 0x35, 0xD5, 0xA3, 0x88, 0x99, 0x06, ++0x13, 0xD4, 0xDF, 0xF8, 0xE0, 0x90, 0xD9, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x04, 0x25, 0xA3, 0x88, 0x9A, 0x06, 0x0A, 0xD4, ++0xD9, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x01, 0x3D, 0xF7, 0xD1, 0x2E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x42, 0xDB, 0x97, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x37, 0xD0, 0x2A, 0x49, 0x97, 0xF8, 0x64, 0x30, 0x0A, 0x68, 0x1B, 0x06, ++0x22, 0xF0, 0xE0, 0x62, 0x03, 0xF0, 0xE0, 0x63, 0x13, 0x43, 0x0B, 0x60, 0xA3, 0x88, 0x25, 0x4A, 0x43, 0xF0, 0x10, 0x03, ++0x52, 0xF8, 0x26, 0x00, 0xA3, 0x80, 0x0F, 0xF0, 0x4F, 0xFE, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x83, 0x00, 0x22, 0x9A, 0x76, ++0x5A, 0x62, 0xA2, 0xE7, 0x54, 0x20, 0x00, 0xFB, 0x06, 0x80, 0x1C, 0x30, 0x0F, 0xF0, 0x28, 0xFF, 0x97, 0xF8, 0x87, 0x30, ++0x00, 0x2B, 0xE5, 0xD0, 0x17, 0x4A, 0x97, 0xF8, 0x65, 0x00, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, 0x02, 0x63, 0x01, 0x33, ++0x83, 0x42, 0x28, 0xBF, 0x03, 0x46, 0x1B, 0x06, 0x03, 0xF0, 0xE0, 0x63, 0x21, 0xF0, 0xE0, 0x61, 0x0B, 0x43, 0x13, 0x60, ++0xD2, 0xE7, 0x10, 0x4B, 0x97, 0xF8, 0x7E, 0x00, 0xD3, 0xF8, 0xC0, 0x33, 0x98, 0x47, 0xCB, 0xE7, 0xA3, 0x88, 0x9B, 0x06, ++0xB9, 0xD4, 0xBD, 0xE8, 0xF0, 0x47, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0x6A, 0x02, 0x11, 0xF0, 0xDD, 0xBA, 0x00, 0xBF, ++0x94, 0x64, 0x17, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x54, 0x83, 0x32, 0x40, 0xC4, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD4, 0x8E, 0x15, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x10, 0xB5, 0x0D, 0x4C, 0x90, 0x22, 0x00, 0x21, 0x20, 0x46, 0xEC, 0xF7, 0x09, 0xFE, 0xFF, 0xF7, ++0x09, 0xFD, 0x40, 0xF2, 0xD3, 0x13, 0xE3, 0x66, 0xED, 0xF7, 0xA4, 0xFE, 0x07, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x70, 0x43, ++0x18, 0xB1, 0x43, 0xF0, 0x30, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x43, 0xF0, 0x10, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, ++0x94, 0x64, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x43, 0x2A, 0x4C, 0x65, 0x68, 0x95, 0xB0, 0x00, 0x2D, ++0x44, 0xD0, 0x29, 0x4E, 0xA7, 0x68, 0xD6, 0xF8, 0xD8, 0x31, 0x20, 0x46, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0x80, 0xB8, 0xF1, ++0x00, 0x0F, 0x26, 0xD0, 0x01, 0x25, 0x24, 0x49, 0x68, 0x46, 0x50, 0x22, 0x23, 0xF0, 0x66, 0xFD, 0xA3, 0x69, 0x94, 0xF8, ++0x62, 0x90, 0x23, 0xB1, 0x1E, 0x4E, 0x1F, 0x48, 0xD6, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xFF, 0xF7, 0xBD, 0xFF, 0xC4, 0xF8, ++0x10, 0x80, 0x84, 0xF8, 0x62, 0x90, 0x18, 0x4C, 0x6B, 0x46, 0x22, 0x46, 0x0C, 0xAE, 0x58, 0x69, 0x19, 0x7E, 0x90, 0x62, ++0x0C, 0x33, 0xB3, 0x42, 0x82, 0xF8, 0x2C, 0x10, 0x02, 0xF1, 0x0C, 0x02, 0xF5, 0xD1, 0xFD, 0xB9, 0x15, 0xB0, 0xBD, 0xE8, ++0xF0, 0x83, 0xFF, 0xF7, 0xA5, 0xFF, 0xC4, 0xF8, 0x10, 0x80, 0x10, 0x4B, 0x10, 0x4A, 0x19, 0x69, 0x0B, 0x48, 0xD6, 0xF8, ++0xE0, 0x31, 0xA7, 0x60, 0x01, 0xF5, 0x9C, 0x51, 0x08, 0x31, 0x62, 0x60, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, ++0xD4, 0xF8, 0x10, 0x80, 0xB8, 0xF1, 0x00, 0x0F, 0xC1, 0xD1, 0xFF, 0xF7, 0x8D, 0xFF, 0xC4, 0xF8, 0x10, 0x80, 0xDF, 0xE7, ++0x01, 0x4E, 0xE4, 0xE7, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xA8, 0x64, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x95, 0x24, 0x13, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x42, 0x6D, 0xC3, 0x69, 0x91, 0xF8, 0x09, 0xC0, 0x9D, 0x68, 0x03, 0x8E, ++0x88, 0x46, 0x91, 0x05, 0x02, 0xD5, 0x12, 0xF4, 0x80, 0x60, 0x3B, 0xD0, 0x12, 0x3B, 0x01, 0x2B, 0x05, 0xF1, 0x12, 0x05, ++0x3A, 0xDD, 0x28, 0x4A, 0xDF, 0xF8, 0xA0, 0x90, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x0C, 0x2C, 0x40, 0xF2, 0xFD, 0x7E, ++0x15, 0xE0, 0x03, 0x2B, 0x2A, 0xDD, 0x6A, 0x88, 0x12, 0xF0, 0x08, 0x06, 0xC2, 0xF3, 0x42, 0x01, 0x24, 0xD1, 0x19, 0xF8, ++0x01, 0x20, 0x04, 0x32, 0x9A, 0x42, 0x2B, 0xDC, 0xBC, 0xF8, 0x20, 0x10, 0xB9, 0x42, 0xA3, 0xEB, 0x02, 0x03, 0x11, 0xD0, ++0x01, 0x2B, 0x15, 0x44, 0x1A, 0xDD, 0x2C, 0x88, 0xC4, 0xF3, 0x0A, 0x07, 0x77, 0x45, 0x13, 0xD0, 0x14, 0xF4, 0x00, 0x60, ++0xE1, 0xD0, 0xBC, 0xF8, 0x20, 0x10, 0x02, 0x22, 0xB9, 0x42, 0xA3, 0xEB, 0x02, 0x03, 0xED, 0xD1, 0x14, 0xF4, 0x00, 0x60, ++0x0B, 0xD1, 0x98, 0xF8, 0x0A, 0x30, 0xB3, 0xEB, 0x14, 0x3F, 0x0D, 0xD0, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x22, 0xDB, 0xE7, ++0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0x23, 0xC8, 0xF8, 0xDC, 0x30, 0x01, 0x20, 0xF3, 0xE7, 0x30, 0x46, 0xF1, 0xE7, ++0x08, 0xF1, 0xE0, 0x04, 0x02, 0x3A, 0xA9, 0x1C, 0x20, 0x46, 0x23, 0xF0, 0xBD, 0xFC, 0xC8, 0xF8, 0xDC, 0x40, 0x01, 0x20, ++0xE6, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x00, 0x96, 0x15, 0x00, 0x85, 0x4B, 0x86, 0x4A, 0x19, 0x68, 0x43, 0x6D, ++0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0x24, 0xC5, 0x69, 0x82, 0xF8, 0x88, 0x40, 0xB1, 0xF9, 0x00, 0x10, 0xA1, 0x42, 0x83, 0xB0, ++0xC0, 0xF2, 0xC6, 0x80, 0x9E, 0x01, 0x40, 0xF1, 0xAD, 0x80, 0x00, 0x29, 0xC3, 0xF3, 0xCF, 0x30, 0xC3, 0xF3, 0xC9, 0x33, ++0xC0, 0xF2, 0xB3, 0x80, 0x7A, 0x49, 0x10, 0x3B, 0xDB, 0xB2, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x03, 0x14, 0x94, 0xF8, ++0x25, 0x00, 0x00, 0x28, 0x00, 0xF0, 0x9A, 0x80, 0x94, 0xF8, 0x22, 0x50, 0x54, 0xF8, 0x26, 0x0F, 0x50, 0x67, 0x73, 0x48, ++0x73, 0x4E, 0xA4, 0x88, 0x84, 0x80, 0x4F, 0xF4, 0xA4, 0x67, 0x10, 0x69, 0x07, 0xFB, 0x05, 0x65, 0xA8, 0x42, 0x40, 0xF0, ++0x93, 0x80, 0x6F, 0x48, 0x00, 0x68, 0x00, 0xF0, 0x3F, 0x00, 0x09, 0x28, 0x40, 0xF2, 0x8C, 0x80, 0x6C, 0x4C, 0x6D, 0x48, ++0x24, 0x68, 0x05, 0x68, 0xD2, 0xF8, 0x68, 0x80, 0xC4, 0xF3, 0x0B, 0x10, 0x04, 0xF0, 0x0F, 0x09, 0xC4, 0xF3, 0x01, 0x4E, ++0x24, 0x03, 0x00, 0x90, 0xA2, 0xF8, 0x7C, 0x00, 0x82, 0xF8, 0x7F, 0x90, 0x82, 0xF8, 0x83, 0xE0, 0xC5, 0xF3, 0x03, 0x10, ++0x05, 0xF0, 0x07, 0x06, 0x40, 0xF1, 0x8B, 0x80, 0x4F, 0xF0, 0x02, 0x0B, 0x4F, 0xF4, 0x80, 0x64, 0x5F, 0x46, 0x01, 0x94, ++0xC5, 0xF3, 0x00, 0x34, 0xC5, 0xF3, 0x42, 0x2C, 0x82, 0xF8, 0x80, 0x70, 0xF7, 0xB2, 0x82, 0xF8, 0x81, 0x00, 0x82, 0xF8, ++0x87, 0x40, 0x82, 0xF8, 0x82, 0xC0, 0x82, 0xF8, 0x84, 0x70, 0xB9, 0xF1, 0x00, 0x0F, 0x79, 0xD0, 0x92, 0xF8, 0x86, 0x50, ++0xDF, 0xF8, 0x64, 0x91, 0xD9, 0xF8, 0x00, 0x40, 0x00, 0x2C, 0xFB, 0xDA, 0xD9, 0xF8, 0x00, 0x90, 0x50, 0x4C, 0x02, 0x2E, ++0x09, 0xEA, 0x04, 0x04, 0x76, 0xD8, 0x4F, 0x4F, 0x00, 0xEB, 0x40, 0x09, 0x57, 0xF8, 0x26, 0x70, 0xD9, 0x44, 0x37, 0xF8, ++0x19, 0x90, 0xD8, 0xF8, 0x0C, 0x70, 0xDF, 0xF8, 0x3C, 0xA1, 0xBC, 0x42, 0x28, 0xBF, 0x3C, 0x46, 0x14, 0x67, 0xDA, 0xF8, ++0x00, 0xB0, 0x01, 0x9F, 0x98, 0xF8, 0x1C, 0x80, 0x4F, 0xF4, 0x1E, 0x7A, 0x0A, 0xFB, 0x03, 0x13, 0x07, 0x43, 0x01, 0x21, ++0x47, 0xEA, 0xCE, 0x1E, 0x01, 0xFA, 0x05, 0xF5, 0x4F, 0xEA, 0x1B, 0x67, 0xD3, 0xF8, 0x4C, 0x11, 0x93, 0x66, 0x00, 0x9B, ++0x27, 0x2C, 0x4E, 0xEA, 0x0C, 0x1C, 0x4F, 0xEA, 0x87, 0x17, 0x18, 0xFB, 0x05, 0xF8, 0x4C, 0xF4, 0x40, 0x5C, 0x46, 0xEA, ++0xC3, 0x06, 0x94, 0xBF, 0x00, 0x24, 0x01, 0x24, 0x47, 0xF0, 0x13, 0x07, 0x18, 0xFB, 0x09, 0xF9, 0x82, 0xF8, 0x88, 0x40, ++0xD7, 0x66, 0xA1, 0xF8, 0x82, 0xC0, 0xA1, 0xF8, 0x84, 0x60, 0xA2, 0xF8, 0x7A, 0x90, 0x09, 0xE0, 0xAB, 0x68, 0x59, 0x89, ++0xA2, 0xF8, 0x74, 0x10, 0x99, 0x89, 0xA2, 0xF8, 0x76, 0x10, 0xDB, 0x89, 0xA2, 0xF8, 0x78, 0x30, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x10, 0xF4, 0x7C, 0x7F, 0x7F, 0xF4, 0x49, 0xAF, 0x27, 0x49, 0x27, 0x48, 0x40, 0xF6, 0x53, 0x12, 0x07, 0xE0, ++0x00, 0x8E, 0x1C, 0x28, 0x3F, 0xF6, 0x36, 0xAF, 0x22, 0x49, 0x24, 0x48, 0x40, 0xF6, 0x46, 0x12, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x11, 0xF0, 0xF9, 0xB8, 0x4F, 0xF0, 0x01, 0x0B, 0x4F, 0xF4, 0x00, 0x74, 0x5F, 0x46, 0x01, 0x94, 0x73, 0xE7, ++0xAC, 0x0F, 0xDF, 0xF8, 0x7C, 0x90, 0xC5, 0xF3, 0x01, 0x65, 0x19, 0xF8, 0x04, 0x40, 0x82, 0xF8, 0x85, 0x40, 0x82, 0xF8, ++0x86, 0x50, 0x7B, 0xE7, 0x03, 0x3F, 0x00, 0xEB, 0x40, 0x09, 0xC7, 0xF3, 0x46, 0x0A, 0x0B, 0xEB, 0x49, 0x09, 0x4F, 0xF0, ++0x03, 0x0B, 0x1B, 0xFB, 0x0A, 0x99, 0xDF, 0xF8, 0x54, 0xA0, 0x3A, 0xF8, 0x19, 0x90, 0x07, 0xF0, 0x01, 0x07, 0x09, 0xFA, ++0x07, 0xF9, 0x1F, 0xFA, 0x89, 0xF9, 0x7A, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x08, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x58, 0x83, 0x32, 0x40, 0x5C, 0x83, 0x32, 0x40, ++0xFC, 0xFF, 0x0F, 0x00, 0x04, 0x96, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x50, 0x90, 0x15, 0x00, 0xB0, 0x93, 0x15, 0x00, ++0x60, 0x83, 0x32, 0x40, 0x64, 0x83, 0x32, 0x40, 0xA8, 0xB2, 0x15, 0x00, 0x70, 0x95, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x4C, ++0xD4, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xD4, 0xF8, 0xEC, 0x33, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0x10, 0xB5, 0x03, 0xF0, 0x85, 0xFB, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x04, 0x03, 0xD4, 0x07, 0x4B, 0x00, 0x24, 0x1C, 0x61, ++0x10, 0xBD, 0x04, 0x46, 0xED, 0xF7, 0x62, 0xFC, 0x00, 0x28, 0xF6, 0xD0, 0x02, 0x4B, 0x1C, 0x61, 0x10, 0xBD, 0x00, 0xBF, ++0x04, 0x00, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0x18, 0x4B, 0x1B, 0x69, 0x63, 0xB3, 0x93, 0xF8, 0x64, 0x20, 0x4A, 0xB3, ++0x16, 0x4A, 0x93, 0xF8, 0x6C, 0x30, 0x10, 0x68, 0x15, 0x49, 0x40, 0xF0, 0x10, 0x00, 0x30, 0xB4, 0x10, 0x60, 0x10, 0x68, ++0x13, 0x4D, 0x14, 0x4C, 0x40, 0xF4, 0x00, 0x60, 0x10, 0x60, 0x10, 0x68, 0x40, 0xF4, 0x80, 0x50, 0x10, 0x60, 0x2A, 0x68, ++0x10, 0x48, 0xC4, 0xF8, 0x50, 0x04, 0x42, 0xF4, 0x00, 0x72, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x32, 0x0A, 0x60, ++0x0A, 0x68, 0x10, 0x33, 0xDB, 0xB2, 0x43, 0xEA, 0x83, 0x23, 0x22, 0xF4, 0x00, 0x32, 0xC4, 0xF8, 0x4C, 0x34, 0x30, 0xBC, ++0x0A, 0x60, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x80, 0x80, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, ++0x24, 0x03, 0x32, 0x40, 0x60, 0x5D, 0x18, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0x08, 0xB5, 0x0F, 0x4B, 0x1B, 0x69, 0x1B, 0xB1, ++0x0E, 0x4B, 0xD3, 0xF8, 0xC4, 0x33, 0x98, 0x47, 0x0D, 0x48, 0x0E, 0x4B, 0x02, 0x68, 0x0E, 0x49, 0x22, 0xF4, 0x00, 0x72, ++0x02, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x10, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0x1A, 0x68, ++0x22, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x33, 0x0B, 0x60, 0x08, 0xBD, 0x94, 0x64, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x24, 0x03, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x43, 0x6C, 0x13, 0xB1, ++0x9B, 0x88, 0x9A, 0x05, 0x0C, 0xD4, 0xC3, 0x6A, 0xDB, 0x6B, 0x9B, 0x06, 0x43, 0xBF, 0x91, 0xF8, 0x2D, 0x31, 0x48, 0xF2, ++0x07, 0x00, 0x40, 0xEA, 0x43, 0x20, 0xD1, 0xF8, 0x04, 0x02, 0x70, 0x47, 0x01, 0x4B, 0xD8, 0x6E, 0x70, 0x47, 0x00, 0xBF, ++0x94, 0x64, 0x17, 0x00, 0x4B, 0x08, 0x03, 0x22, 0x02, 0xFB, 0x03, 0x00, 0x03, 0x4B, 0x33, 0xF8, 0x10, 0x00, 0x01, 0xF0, ++0x01, 0x01, 0x88, 0x40, 0x70, 0x47, 0x00, 0xBF, 0xE0, 0x94, 0x15, 0x00, 0x4B, 0x08, 0x03, 0x22, 0x02, 0xFB, 0x03, 0x00, ++0x03, 0x4B, 0x33, 0xF8, 0x10, 0x00, 0x01, 0xF0, 0x01, 0x01, 0x88, 0x40, 0x80, 0xB2, 0x70, 0x47, 0x70, 0x95, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x2B, 0x4F, 0x84, 0x6A, 0x3D, 0x68, 0x90, 0xF8, 0x1D, 0x80, 0xB5, 0xF9, 0x00, 0xC0, 0xBC, 0xF1, ++0x00, 0x0F, 0x16, 0x46, 0x99, 0x46, 0xC4, 0xF3, 0x41, 0x25, 0x12, 0xDB, 0xC4, 0xF3, 0x02, 0x12, 0x01, 0x32, 0x1A, 0x60, ++0x04, 0xF0, 0x0F, 0x04, 0x22, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x08, 0x23, 0x04, 0xEB, 0x44, 0x04, 0xDB, 0x68, ++0x33, 0x60, 0x05, 0xEB, 0x44, 0x00, 0xBD, 0xE8, 0xF8, 0x83, 0x05, 0x29, 0x1E, 0xD0, 0x1C, 0x49, 0x1C, 0x48, 0x40, 0xF6, ++0xF5, 0x12, 0x10, 0xF0, 0xF5, 0xFF, 0x39, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0xC4, 0xF3, 0x02, 0x12, 0x01, 0x32, 0x00, 0x29, ++0x4F, 0xEA, 0x14, 0x13, 0xC9, 0xF8, 0x00, 0x20, 0x04, 0xF0, 0x0F, 0x04, 0xDC, 0xDA, 0x5B, 0x07, 0x11, 0xD4, 0x0B, 0x2C, ++0xD8, 0xD9, 0x10, 0x49, 0x11, 0x48, 0x40, 0xF6, 0xFF, 0x12, 0x10, 0xF0, 0xDD, 0xFF, 0xD1, 0xE7, 0xC4, 0xF3, 0x02, 0x12, ++0x01, 0x32, 0x1A, 0x60, 0x23, 0x09, 0x5B, 0x07, 0x04, 0xF0, 0x0F, 0x04, 0xED, 0xD5, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, ++0xFE, 0x12, 0x10, 0xF0, 0xCD, 0xFF, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE2, 0xDB, 0xBC, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD8, 0x93, 0x15, 0x00, 0xF8, 0x93, 0x15, 0x00, ++0xE0, 0x91, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x14, 0x4E, 0xDF, 0xF8, 0x54, 0xC0, 0x35, 0x69, 0x04, 0x38, 0x31, 0x46, ++0x05, 0xF1, 0x08, 0x04, 0x05, 0xF1, 0x18, 0x0E, 0x00, 0x27, 0x50, 0xF8, 0x04, 0x2F, 0x13, 0x09, 0x02, 0xF0, 0x0F, 0x08, ++0x03, 0xF4, 0x7F, 0x63, 0x43, 0xEA, 0x08, 0x03, 0x12, 0x0C, 0x8B, 0x62, 0x81, 0xF8, 0x2C, 0x20, 0x25, 0xB1, 0x22, 0x68, ++0x02, 0xEA, 0x0C, 0x02, 0x13, 0x43, 0x8B, 0x62, 0x04, 0x34, 0xA6, 0x45, 0x4F, 0x62, 0x01, 0xF1, 0x0C, 0x01, 0xE6, 0xD1, ++0x01, 0x23, 0x86, 0xF8, 0x62, 0x30, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x00, 0xF0, 0xFF, 0xFF, ++0x03, 0x4B, 0x02, 0x78, 0x83, 0xF8, 0x64, 0x20, 0x42, 0x78, 0x83, 0xF8, 0x65, 0x20, 0x70, 0x47, 0x94, 0x64, 0x17, 0x00, ++0x0A, 0x4B, 0x9A, 0x69, 0x8A, 0xB1, 0x30, 0xB4, 0x01, 0xEB, 0x41, 0x02, 0x03, 0xEB, 0x82, 0x02, 0x4C, 0x00, 0x92, 0xF8, ++0x2E, 0x50, 0x05, 0xB1, 0x50, 0x62, 0x21, 0x44, 0x03, 0xEB, 0x81, 0x03, 0x01, 0x22, 0x30, 0xBC, 0x83, 0xF8, 0x2D, 0x20, ++0x70, 0x47, 0x70, 0x47, 0x94, 0x64, 0x17, 0x00, 0x08, 0x4A, 0x09, 0x4B, 0x11, 0x69, 0x09, 0x4A, 0x10, 0xB4, 0x01, 0xF5, ++0x9C, 0x51, 0x08, 0x4C, 0x5C, 0x60, 0x98, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x18, 0x46, 0x08, 0x31, 0xD2, 0xF8, 0xE0, 0x31, ++0x18, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x95, 0x24, 0x13, 0x00, ++0x08, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x40, 0xF2, 0xFF, 0x31, 0xB3, 0xF8, 0xBE, 0x24, ++0x8A, 0x42, 0x00, 0xD1, 0x70, 0x47, 0x43, 0x6C, 0x28, 0x30, 0x59, 0x6A, 0xFE, 0xF7, 0xF2, 0xBB, 0x18, 0x88, 0x17, 0x00, ++0xF8, 0xB5, 0x0E, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x40, 0xF2, 0xFF, 0x31, 0xB3, 0xF8, ++0xBE, 0x24, 0x8A, 0x42, 0x0F, 0xD0, 0xD0, 0xE9, 0x12, 0x67, 0x1D, 0x46, 0x06, 0xF1, 0x3C, 0x04, 0x4C, 0x36, 0x20, 0x46, ++0xF9, 0x6A, 0x04, 0x34, 0xFE, 0xF7, 0xD8, 0xFB, 0xB4, 0x42, 0x02, 0xD0, 0xB5, 0xF8, 0xBE, 0x24, 0xF5, 0xE7, 0xF8, 0xBD, ++0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x9C, 0x4E, 0xD0, 0xF8, 0x44, 0xB0, 0xC7, 0x6C, 0x96, 0xF8, 0x7E, 0x50, ++0x96, 0xF8, 0x87, 0x30, 0x11, 0xF4, 0x00, 0x09, 0x83, 0xB0, 0x04, 0x46, 0x8A, 0x46, 0x3E, 0xD0, 0x7B, 0xBB, 0xDF, 0xF8, ++0x58, 0x82, 0x28, 0x46, 0xD8, 0xF8, 0xC0, 0x33, 0x98, 0x47, 0xD8, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xBB, 0xF8, 0x04, 0x30, ++0x99, 0x06, 0x49, 0xD5, 0x13, 0xF0, 0x40, 0x02, 0x69, 0xD0, 0x58, 0x46, 0xFD, 0xF7, 0x14, 0xFE, 0x00, 0x23, 0xDF, 0xF8, ++0x4C, 0x82, 0x63, 0x64, 0xB9, 0xF1, 0x00, 0x0F, 0x4D, 0xD0, 0x89, 0x4B, 0x00, 0x22, 0xD3, 0xF8, 0xAC, 0x33, 0x29, 0x46, ++0x20, 0x46, 0x98, 0x47, 0x54, 0x20, 0x00, 0xFB, 0x05, 0x80, 0x0C, 0x30, 0x0F, 0xF0, 0xD2, 0xFA, 0xA3, 0x88, 0x00, 0x2B, ++0x47, 0xD1, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xFC, 0xF7, 0x0B, 0xB9, 0x7F, 0x48, 0x96, 0xF8, 0x64, 0x30, ++0x01, 0x68, 0xDF, 0xF8, 0xF0, 0x81, 0x1B, 0x06, 0x21, 0xF0, 0xE0, 0x61, 0x03, 0xF0, 0xE0, 0x63, 0x0B, 0x43, 0x03, 0x60, ++0xC7, 0xE7, 0x00, 0x2B, 0xC8, 0xD0, 0x77, 0x48, 0x96, 0xF8, 0x65, 0xE0, 0x01, 0x68, 0x02, 0x68, 0xC1, 0xF3, 0x02, 0x61, ++0x4B, 0x1C, 0x73, 0x45, 0x28, 0xBF, 0x73, 0x46, 0x1B, 0x06, 0x03, 0xF0, 0xE0, 0x63, 0x22, 0xF0, 0xE0, 0x6C, 0x43, 0xEA, ++0x0C, 0x03, 0x03, 0x60, 0xBB, 0xF8, 0x04, 0x30, 0x99, 0x06, 0xB5, 0xD4, 0x1C, 0x23, 0xDF, 0xF8, 0xC4, 0x81, 0x54, 0x20, ++0x10, 0xFB, 0x05, 0x30, 0x40, 0x44, 0x0F, 0xF0, 0x99, 0xFA, 0x58, 0x46, 0xFD, 0xF7, 0xC4, 0xFD, 0x00, 0x23, 0x63, 0x64, ++0xB9, 0xF1, 0x00, 0x0F, 0xB1, 0xD1, 0xCA, 0xF3, 0x07, 0x29, 0xB9, 0xF1, 0x04, 0x0F, 0x1F, 0xD9, 0x3B, 0x6D, 0x43, 0xF4, ++0x80, 0x33, 0x3B, 0x65, 0xA7, 0xE7, 0x2A, 0x46, 0x51, 0x46, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xFB, 0xF7, ++0x9D, 0xBA, 0x3B, 0x6D, 0x00, 0x92, 0x23, 0xF4, 0x00, 0x03, 0x2A, 0xF4, 0x00, 0x0A, 0x58, 0x46, 0x3B, 0x65, 0xCA, 0xF3, ++0x07, 0x29, 0xFD, 0xF7, 0xA1, 0xFD, 0x00, 0x9A, 0xDF, 0xF8, 0x64, 0x81, 0x62, 0x64, 0xB9, 0xF1, 0x04, 0x0F, 0xDF, 0xD8, ++0xD4, 0xF8, 0x48, 0xA0, 0xB9, 0xF1, 0x00, 0x0F, 0x25, 0xD0, 0x0A, 0xF1, 0x28, 0x0B, 0x05, 0xEB, 0x45, 0x03, 0x06, 0xEB, ++0x83, 0x03, 0x09, 0xF1, 0x01, 0x09, 0x59, 0x6A, 0xDA, 0xE9, 0x17, 0x32, 0xBB, 0x64, 0x4F, 0xEA, 0x09, 0x23, 0xC7, 0xE9, ++0x0D, 0x2B, 0x3B, 0x65, 0x07, 0xF1, 0x14, 0x02, 0x6B, 0x00, 0x00, 0x29, 0x4B, 0xD0, 0xB9, 0x61, 0x54, 0x20, 0x00, 0xFB, ++0x05, 0x88, 0x1D, 0x44, 0x98, 0xF8, 0x50, 0x30, 0x06, 0xEB, 0x85, 0x06, 0x01, 0x33, 0x72, 0x62, 0x88, 0xF8, 0x50, 0x30, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xE3, 0x6A, 0x0A, 0xF1, 0x28, 0x0B, 0x03, 0xF1, 0x40, 0x0C, 0x1A, 0x46, 0x0A, 0xF1, ++0x24, 0x01, 0x52, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0F, 0x62, 0x45, 0xF9, 0xD1, 0xE2, 0x8B, 0x92, 0x04, 0x26, 0xD5, ++0x33, 0x4A, 0x34, 0x48, 0x11, 0x68, 0x62, 0x7F, 0xB1, 0xF9, 0x00, 0x10, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, 0x02, 0x02, ++0x00, 0x29, 0xD2, 0xF8, 0x4C, 0x21, 0x00, 0x92, 0x29, 0xDB, 0x00, 0x9A, 0x59, 0x69, 0xD2, 0xF8, 0x9C, 0x20, 0xCA, 0xF8, ++0x40, 0x10, 0x59, 0x6A, 0xCA, 0xF8, 0x50, 0x10, 0xC2, 0xF3, 0xC2, 0x21, 0x05, 0x29, 0xCA, 0xF8, 0x3C, 0x20, 0x25, 0xD0, ++0xDB, 0x6B, 0x5B, 0x07, 0x05, 0xD4, 0xDA, 0xF8, 0x2C, 0x30, 0x23, 0xF4, 0xC0, 0x73, 0xCA, 0xF8, 0x2C, 0x30, 0x20, 0x46, ++0xFF, 0xF7, 0xDC, 0xFE, 0x9F, 0xE7, 0x54, 0x21, 0x01, 0xFB, 0x05, 0xF1, 0x1E, 0x48, 0x48, 0xF8, 0x01, 0x20, 0x00, 0x68, ++0x40, 0x78, 0x41, 0x44, 0x00, 0x28, 0xA9, 0xD1, 0xC1, 0xE9, 0x01, 0x00, 0xA6, 0xE7, 0x00, 0x2A, 0xD3, 0xD1, 0x19, 0x49, ++0x19, 0x48, 0x01, 0x93, 0x40, 0xF2, 0x4B, 0x12, 0x10, 0xF0, 0xFE, 0xFD, 0x01, 0x9B, 0xCA, 0xE7, 0x00, 0x98, 0xDA, 0xF8, ++0x4C, 0x10, 0x90, 0xF8, 0xA1, 0x00, 0x02, 0xF4, 0xC0, 0x62, 0xB2, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x3C, ++0x4F, 0xF4, 0x00, 0x3C, 0x21, 0xF4, 0x40, 0x32, 0x42, 0xEA, 0x0C, 0x02, 0x20, 0xB1, 0x42, 0xF4, 0x80, 0x22, 0xCA, 0xF8, ++0x4C, 0x20, 0xC1, 0xE7, 0x22, 0xF4, 0x80, 0x22, 0xCA, 0xF8, 0x4C, 0x20, 0xBC, 0xE7, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, 0x10, 0xB5, 0x05, 0x4C, 0x20, 0x46, 0x0F, 0xF0, ++0x6F, 0xF9, 0x10, 0xF0, 0x25, 0xFE, 0x01, 0x38, 0xC0, 0xB2, 0xE0, 0x72, 0xA0, 0x72, 0x10, 0xBD, 0x24, 0x65, 0x17, 0x00, ++0xC2, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x02, 0x38, 0x85, 0xB0, 0x98, 0xF8, 0x62, 0x30, ++0x02, 0x2B, 0x17, 0xD1, 0x4F, 0xF4, 0x1E, 0x79, 0x93, 0x46, 0x0C, 0x46, 0x09, 0xFB, 0x01, 0xF2, 0xBA, 0x49, 0x01, 0x92, ++0x8E, 0x18, 0xB0, 0xF8, 0x00, 0xA0, 0x96, 0xF8, 0x24, 0x90, 0xB9, 0xF1, 0x01, 0x0F, 0x05, 0x46, 0x41, 0xF2, 0x04, 0x42, ++0x07, 0xD0, 0x0A, 0xEA, 0x02, 0x0A, 0xBA, 0xF5, 0x80, 0x5F, 0x5A, 0xD0, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0xEA, ++0x02, 0x02, 0x00, 0xF0, 0x6B, 0x81, 0x0A, 0xF0, 0xFC, 0x03, 0xA4, 0x2B, 0x00, 0xF0, 0x75, 0x82, 0x0A, 0xF0, 0x8C, 0x03, ++0x88, 0x2B, 0xEF, 0xD1, 0x0A, 0xF4, 0x40, 0x7A, 0xBA, 0xF5, 0x40, 0x7F, 0x0C, 0xBF, 0xEF, 0x8B, 0x2F, 0x8B, 0xA7, 0x4B, ++0xA5, 0x49, 0xA7, 0x4A, 0x07, 0xF0, 0x07, 0x07, 0x4F, 0xF4, 0x1E, 0x75, 0xDB, 0x5D, 0x05, 0xFB, 0x04, 0x15, 0xD2, 0x5C, ++0x95, 0xF8, 0x2E, 0x31, 0x1A, 0x42, 0xD9, 0xD0, 0x95, 0xF8, 0x31, 0x30, 0x13, 0xF0, 0x0C, 0x0F, 0x00, 0xF0, 0x7E, 0x82, ++0x95, 0xF8, 0x32, 0x20, 0x12, 0xF0, 0x06, 0x0F, 0xCE, 0xD1, 0x18, 0x07, 0x95, 0xF8, 0x2F, 0x91, 0x40, 0xF1, 0x8A, 0x82, ++0x99, 0x4B, 0x02, 0x22, 0x85, 0xF8, 0x32, 0x20, 0xD3, 0xF8, 0x20, 0x33, 0x31, 0x46, 0x40, 0x46, 0x4A, 0x46, 0x98, 0x47, ++0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x7A, 0x82, 0xA9, 0xEB, 0x00, 0x09, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF3, 0x74, 0x82, ++0x8C, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x24, 0x00, 0x23, 0x1A, 0x46, 0x94, 0xF8, 0x23, 0x00, 0x47, 0xF0, ++0x10, 0x01, 0xFC, 0xF7, 0xA9, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x32, 0x30, 0xA4, 0xE7, 0x00, 0x22, 0x0C, 0x21, 0x49, 0x20, ++0x0E, 0xF0, 0x58, 0xFC, 0x4F, 0xF0, 0x01, 0x09, 0x86, 0xF8, 0x24, 0x90, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, 0x0E, 0xF0, ++0x7F, 0xFC, 0x96, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x58, 0xD1, 0x96, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x54, 0xD8, 0x96, 0xF8, ++0x22, 0x20, 0x77, 0x48, 0x7B, 0x4D, 0xCD, 0xF8, 0x08, 0x90, 0x9E, 0x23, 0xA4, 0x21, 0x11, 0xFB, 0x02, 0x31, 0x07, 0xFB, ++0x02, 0x07, 0x4F, 0x23, 0x46, 0x22, 0x13, 0xFB, 0x04, 0x24, 0x71, 0x4A, 0x02, 0xF5, 0x16, 0x73, 0x02, 0xEB, 0xC4, 0x04, ++0x01, 0x9A, 0x1A, 0x44, 0x00, 0xEB, 0xC1, 0x0A, 0x91, 0x46, 0xD6, 0xF8, 0x08, 0x32, 0x1B, 0xB3, 0xEF, 0xF3, 0x10, 0x83, ++0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x6D, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0x2B, 0x68, 0xA4, 0xF1, 0x28, 0x00, 0x01, 0x33, ++0xAA, 0xF1, 0x28, 0x01, 0x01, 0x90, 0x2B, 0x60, 0x0F, 0xF0, 0x98, 0xF9, 0xD6, 0xE9, 0x82, 0x23, 0x01, 0x98, 0xC7, 0xF8, ++0xC8, 0x24, 0xC7, 0xF8, 0xCC, 0x34, 0x0F, 0xF0, 0x99, 0xF8, 0x2B, 0x68, 0x5A, 0x1E, 0x2B, 0xB1, 0x60, 0x4B, 0x2A, 0x60, ++0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD6, 0xF8, 0x30, 0x32, 0x50, 0x46, 0x21, 0x46, 0x08, 0x36, 0x0A, 0xF1, ++0x08, 0x0A, 0x08, 0x37, 0x23, 0xB1, 0x0F, 0xF0, 0x7B, 0xF9, 0x20, 0x46, 0x0F, 0xF0, 0x82, 0xF8, 0x08, 0x34, 0x4C, 0x45, ++0xC7, 0xD1, 0x40, 0x20, 0x0E, 0xF0, 0xDE, 0xFF, 0x4D, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x36, 0x96, 0xF8, ++0xDE, 0x20, 0x00, 0x2A, 0x40, 0xF0, 0x82, 0x80, 0x0B, 0xF1, 0x0A, 0x05, 0x48, 0x4B, 0xED, 0xB2, 0x4F, 0xF4, 0x1E, 0x79, ++0x09, 0xFB, 0x05, 0xF9, 0x03, 0xEB, 0x09, 0x04, 0x94, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x73, 0xD0, 0x02, 0x23, 0x0C, 0x21, ++0x49, 0x20, 0x0E, 0xF0, 0xD5, 0xFB, 0x4F, 0xF0, 0x01, 0x0A, 0x84, 0xF8, 0x24, 0xA0, 0x05, 0x70, 0x80, 0xF8, 0x01, 0xA0, ++0x0E, 0xF0, 0xFC, 0xFB, 0x94, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xA9, 0x81, 0x94, 0xF8, 0x23, 0x30, 0x09, 0x2B, ++0x00, 0xF2, 0xA4, 0x81, 0x94, 0xF8, 0x22, 0x00, 0xCD, 0xF8, 0x08, 0xA0, 0xA4, 0x21, 0x9E, 0x23, 0x11, 0xFB, 0x00, 0x33, ++0x4F, 0xF0, 0x46, 0x0A, 0x4F, 0x21, 0x11, 0xFB, 0x05, 0xAA, 0x36, 0x4A, 0x2E, 0x4E, 0x2E, 0x49, 0x07, 0xFB, 0x00, 0x67, ++0x01, 0xEB, 0xC3, 0x05, 0x30, 0x4E, 0xA2, 0xF5, 0x16, 0x73, 0x03, 0xEB, 0xCA, 0x0A, 0x91, 0x44, 0xD4, 0xF8, 0x08, 0x32, ++0x1B, 0xB3, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2A, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0x33, 0x68, ++0xAA, 0xF1, 0x28, 0x00, 0x01, 0x33, 0xA5, 0xF1, 0x28, 0x01, 0x01, 0x90, 0x33, 0x60, 0x0F, 0xF0, 0x13, 0xF9, 0xD4, 0xE9, ++0x82, 0x23, 0x01, 0x98, 0xC7, 0xF8, 0xC8, 0x24, 0xC7, 0xF8, 0xCC, 0x34, 0x0F, 0xF0, 0x14, 0xF8, 0x33, 0x68, 0x5A, 0x1E, ++0x2B, 0xB1, 0x1E, 0x4B, 0x32, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD4, 0xF8, 0x30, 0x32, 0x28, 0x46, ++0x51, 0x46, 0x08, 0x34, 0x08, 0x35, 0x08, 0x37, 0x23, 0xB1, 0x0F, 0xF0, 0xF7, 0xF8, 0x50, 0x46, 0x0E, 0xF0, 0xFE, 0xFF, ++0x0A, 0xF1, 0x08, 0x0A, 0xCA, 0x45, 0xC7, 0xD1, 0x40, 0x20, 0x0E, 0xF0, 0x59, 0xFF, 0x0B, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x0B, 0x23, 0x93, 0xF8, 0xDE, 0x20, 0x07, 0x48, 0x0B, 0x49, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0B, 0x03, ++0x01, 0x32, 0x83, 0xF8, 0xDE, 0x20, 0xD1, 0xF8, 0x0C, 0x32, 0x40, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, ++0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0xA4, 0xB2, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x0C, 0x21, 0x49, 0x20, 0x02, 0x92, 0x0E, 0xF0, ++0x41, 0xFB, 0x02, 0x9A, 0x86, 0xF8, 0x24, 0x20, 0x04, 0x70, 0x42, 0x70, 0x0E, 0xF0, 0x6A, 0xFB, 0x96, 0xF8, 0x24, 0x30, ++0x00, 0x2B, 0x60, 0xD1, 0x96, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x5C, 0xD8, 0x96, 0xF8, 0x22, 0x20, 0xA8, 0x48, 0xCD, 0xF8, ++0x08, 0x90, 0xA4, 0x21, 0x9E, 0x23, 0x11, 0xFB, 0x02, 0x33, 0xA6, 0x49, 0xDF, 0xF8, 0xA0, 0xA2, 0x03, 0x94, 0x07, 0xFB, ++0x02, 0x19, 0x4F, 0x25, 0x01, 0xEB, 0xC3, 0x07, 0x46, 0x22, 0x01, 0x9B, 0x15, 0xFB, 0x04, 0x25, 0x00, 0xF5, 0x16, 0x72, ++0x13, 0x44, 0x3C, 0x46, 0x00, 0xEB, 0xC5, 0x05, 0x1F, 0x46, 0xD6, 0xF8, 0x08, 0x22, 0x3A, 0xB3, 0xEF, 0xF3, 0x10, 0x82, ++0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x99, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0xA5, 0xF1, 0x28, 0x00, ++0x01, 0x32, 0xA4, 0xF1, 0x28, 0x01, 0x01, 0x90, 0xCA, 0xF8, 0x00, 0x20, 0x0F, 0xF0, 0x7E, 0xF8, 0xD6, 0xE9, 0x82, 0x21, ++0x01, 0x98, 0xC9, 0xF8, 0xC8, 0x24, 0xC9, 0xF8, 0xCC, 0x14, 0x0E, 0xF0, 0x7F, 0xFF, 0xDA, 0xF8, 0x00, 0x20, 0x51, 0x1E, ++0x32, 0xB1, 0x8B, 0x4B, 0xCA, 0xF8, 0x00, 0x10, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD6, 0xF8, 0x30, 0x22, ++0x20, 0x46, 0x29, 0x46, 0x08, 0x36, 0x08, 0x34, 0x09, 0xF1, 0x08, 0x09, 0x22, 0xB1, 0x0F, 0xF0, 0x5F, 0xF8, 0x28, 0x46, ++0x0E, 0xF0, 0x66, 0xFF, 0x08, 0x35, 0xBD, 0x42, 0xC3, 0xD1, 0x40, 0x20, 0x03, 0x9C, 0x0E, 0xF0, 0xC1, 0xFE, 0x7E, 0x4D, ++0x21, 0x46, 0xEB, 0x68, 0x40, 0x46, 0x98, 0x47, 0x79, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x33, 0x93, 0xF8, ++0xDE, 0xA0, 0x0A, 0xF1, 0xFF, 0x3A, 0x5F, 0xFA, 0x8A, 0xFA, 0x83, 0xF8, 0xDE, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, ++0x84, 0x80, 0x0B, 0xF1, 0x0A, 0x06, 0x6F, 0x49, 0xF6, 0xB2, 0x4F, 0xF4, 0x1E, 0x79, 0x09, 0xFB, 0x06, 0xF9, 0x01, 0xEB, ++0x09, 0x04, 0x94, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x71, 0xD0, 0x02, 0x23, 0x52, 0x46, 0x0C, 0x21, 0x49, 0x20, 0x0E, 0xF0, ++0xAB, 0xFA, 0x84, 0xF8, 0x24, 0xA0, 0x06, 0x70, 0x80, 0xF8, 0x01, 0xA0, 0x0E, 0xF0, 0xD4, 0xFA, 0x94, 0xF8, 0x24, 0x30, ++0x00, 0x2B, 0x60, 0xD1, 0x94, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x5C, 0xD8, 0x94, 0xF8, 0x22, 0x10, 0x5E, 0x4A, 0xDF, 0xF8, ++0x88, 0xC1, 0xDF, 0xF8, 0x80, 0xA1, 0x02, 0x96, 0x9E, 0x23, 0xA4, 0x20, 0x10, 0xFB, 0x01, 0x30, 0x07, 0xFB, 0x01, 0x27, ++0x4F, 0x23, 0x46, 0x21, 0x13, 0xFB, 0x06, 0x13, 0xAC, 0xF5, 0x16, 0x71, 0x02, 0xEB, 0xC0, 0x0B, 0xE1, 0x44, 0x01, 0xEB, ++0xC3, 0x03, 0x5E, 0x46, 0xCB, 0x46, 0xB9, 0x46, 0x1F, 0x46, 0xD4, 0xF8, 0x08, 0x22, 0x3A, 0xB3, 0xEF, 0xF3, 0x10, 0x82, ++0xD3, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x4E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0xA7, 0xF1, 0x28, 0x00, ++0x01, 0x32, 0xA6, 0xF1, 0x28, 0x01, 0x01, 0x90, 0xCA, 0xF8, 0x00, 0x20, 0x0E, 0xF0, 0xE8, 0xFF, 0xD4, 0xE9, 0x82, 0x21, ++0x01, 0x98, 0xC9, 0xF8, 0xC8, 0x24, 0xC9, 0xF8, 0xCC, 0x14, 0x0E, 0xF0, 0xE9, 0xFE, 0xDA, 0xF8, 0x00, 0x20, 0x51, 0x1E, ++0x32, 0xB1, 0x40, 0x4B, 0xCA, 0xF8, 0x00, 0x10, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD4, 0xF8, 0x30, 0x22, ++0x30, 0x46, 0x39, 0x46, 0x08, 0x34, 0x08, 0x36, 0x09, 0xF1, 0x08, 0x09, 0x22, 0xB1, 0x0E, 0xF0, 0xC9, 0xFF, 0x38, 0x46, ++0x0E, 0xF0, 0xD0, 0xFE, 0x08, 0x37, 0x5F, 0x45, 0xC3, 0xD1, 0x40, 0x20, 0x02, 0x9E, 0x0E, 0xF0, 0x2B, 0xFE, 0xEB, 0x68, ++0x31, 0x46, 0x40, 0x46, 0x98, 0x47, 0xD5, 0xF8, 0x0C, 0x32, 0x40, 0x46, 0xDC, 0xE6, 0x96, 0xF8, 0x31, 0x20, 0x12, 0xF0, ++0x02, 0x07, 0x16, 0xD0, 0x96, 0xF8, 0x32, 0x30, 0x2B, 0x49, 0x43, 0xF0, 0x01, 0x03, 0x86, 0xF8, 0x32, 0x30, 0x4A, 0x46, ++0xD1, 0xF8, 0x20, 0x33, 0x40, 0x46, 0x31, 0x46, 0x98, 0x47, 0x96, 0xF8, 0x32, 0x30, 0x23, 0xF0, 0x01, 0x03, 0x86, 0xF8, ++0x32, 0x30, 0x71, 0xE5, 0x96, 0xF8, 0xDE, 0x20, 0xB4, 0xE6, 0x04, 0x23, 0x3A, 0x46, 0x0C, 0x21, 0x4A, 0x20, 0x0E, 0xF0, ++0x15, 0xFA, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, 0x87, 0x70, 0x0E, 0xF0, 0x3F, 0xFA, 0x61, 0xE5, 0x95, 0xF8, 0x32, 0x30, ++0x13, 0xF0, 0x06, 0x04, 0x7F, 0xF4, 0x50, 0xAD, 0x02, 0x26, 0x95, 0xF8, 0x23, 0x00, 0x85, 0xF8, 0x32, 0x60, 0x47, 0xF0, ++0x10, 0x01, 0x23, 0x46, 0x22, 0x46, 0xFB, 0xF7, 0x45, 0xFE, 0x85, 0xF8, 0x32, 0x40, 0x41, 0xE5, 0x95, 0xF8, 0x31, 0x30, ++0x59, 0x07, 0x7F, 0xF5, 0x87, 0xAD, 0x0B, 0x4B, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x04, 0x30, 0x04, 0x23, 0x80, 0xF8, ++0x32, 0x30, 0x00, 0x22, 0x0C, 0x21, 0x4A, 0x20, 0x0E, 0xF0, 0xE8, 0xF9, 0x01, 0x22, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, ++0x82, 0x70, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x0E, 0xF0, 0x0E, 0xBA, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x05, 0x8E, 0x87, 0xB0, 0xAD, 0xB1, 0x7A, 0x4B, 0xC6, 0x69, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, ++0x11, 0xDB, 0x77, 0x4A, 0x65, 0x6D, 0x12, 0x68, 0x12, 0x78, 0x92, 0x07, 0x03, 0xD5, 0x05, 0xF0, 0x3C, 0x02, 0x3C, 0x2A, ++0x77, 0xD0, 0x73, 0x4A, 0xAA, 0x43, 0x0E, 0xD0, 0x01, 0x25, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2E, ++0xEB, 0xD1, 0x6F, 0x49, 0x6F, 0x48, 0x4F, 0xF4, 0xD4, 0x72, 0x35, 0x46, 0x10, 0xF0, 0x5A, 0xFA, 0xF1, 0xE7, 0x00, 0x2B, ++0xC5, 0xF3, 0xCF, 0x30, 0xC5, 0xF3, 0xC9, 0x31, 0x68, 0xDB, 0x6A, 0x4A, 0x10, 0x39, 0xC9, 0xB2, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x25, 0x00, 0x00, 0x28, 0x68, 0xD0, 0xD6, 0xF8, 0x08, 0xB0, 0x0D, 0x29, 0xBB, 0xF8, ++0x00, 0x00, 0x00, 0x90, 0x69, 0xD9, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x22, 0x13, 0x8C, 0xFF, 0x2B, 0x67, 0xD0, ++0x01, 0x92, 0x01, 0x9B, 0xDF, 0xF8, 0x88, 0x81, 0x93, 0xF8, 0x22, 0x90, 0xDF, 0xF8, 0x84, 0xA1, 0x02, 0x91, 0x4F, 0xF4, ++0xA4, 0x67, 0x07, 0xFB, 0x09, 0x87, 0xDA, 0xF8, 0xB8, 0x32, 0x97, 0xF8, 0x63, 0x20, 0x58, 0x46, 0x98, 0x47, 0x97, 0xF8, ++0x64, 0x30, 0x00, 0x2B, 0xBA, 0xD0, 0x00, 0x9B, 0x13, 0xF0, 0x04, 0x03, 0x03, 0x93, 0x05, 0xD1, 0x02, 0x99, 0x97, 0xF8, ++0x63, 0x00, 0x01, 0x22, 0x0C, 0xF0, 0x96, 0xFB, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0x88, 0x98, 0xF8, 0x62, 0x30, ++0x00, 0x2B, 0xA7, 0xD1, 0x00, 0x9A, 0x02, 0xF0, 0xFC, 0x07, 0x80, 0x2F, 0x4A, 0xD0, 0x50, 0x2F, 0x67, 0xD0, 0x03, 0x9B, ++0x00, 0x2B, 0x9D, 0xD1, 0xDA, 0xF8, 0x44, 0x32, 0x29, 0x46, 0x58, 0x46, 0x42, 0x46, 0x98, 0x47, 0x98, 0xF8, 0xC0, 0x34, ++0x00, 0x2B, 0x93, 0xD0, 0xD0, 0x2F, 0x91, 0xD1, 0xB1, 0x68, 0x63, 0x6B, 0x22, 0x8E, 0x40, 0x46, 0x0B, 0xF0, 0x5C, 0xFF, ++0x8A, 0xE7, 0x37, 0x4A, 0x25, 0xF0, 0x40, 0x05, 0x45, 0xF4, 0x00, 0x55, 0xAA, 0x43, 0x65, 0x65, 0x82, 0xD1, 0x90, 0xE7, ++0x10, 0xF4, 0x7C, 0x73, 0x93, 0xD1, 0x32, 0x49, 0x34, 0x48, 0x40, 0xF2, 0xE3, 0x12, 0x1D, 0x46, 0x10, 0xF0, 0xE0, 0xF9, ++0x77, 0xE7, 0x25, 0xF0, 0x00, 0x75, 0x65, 0x65, 0x01, 0x25, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2E, 0x48, ++0x00, 0x69, 0xC3, 0xF8, 0x58, 0x02, 0x90, 0xE7, 0x00, 0x9B, 0x03, 0xF0, 0xFC, 0x03, 0x80, 0x2B, 0xED, 0xD1, 0xD3, 0x6A, ++0x01, 0x93, 0x93, 0xF8, 0x23, 0x20, 0x25, 0xF0, 0xFF, 0x73, 0x10, 0x32, 0x23, 0xF4, 0xC0, 0x33, 0x43, 0xEA, 0xC2, 0x33, ++0x63, 0x65, 0x86, 0xE7, 0x04, 0xF1, 0x14, 0x07, 0x01, 0x9A, 0xDA, 0xF8, 0x98, 0x51, 0x05, 0x93, 0x41, 0x46, 0x05, 0xAB, ++0x38, 0x46, 0xA8, 0x47, 0xDA, 0xF8, 0x40, 0x32, 0x21, 0x8E, 0x05, 0x46, 0x42, 0x46, 0x05, 0x98, 0x98, 0x47, 0xDA, 0xF8, ++0x4C, 0x34, 0x40, 0x46, 0x98, 0x47, 0x00, 0x2D, 0x3F, 0xF4, 0x41, 0xAF, 0xDA, 0xF8, 0xE4, 0x31, 0x3A, 0x46, 0x31, 0x46, ++0x40, 0x46, 0x98, 0x47, 0x39, 0xE7, 0x14, 0x4B, 0x5A, 0x7F, 0x07, 0x2A, 0x7F, 0xF4, 0x34, 0xAF, 0x93, 0xF8, 0x24, 0x00, ++0x00, 0x28, 0x7F, 0xF4, 0x2F, 0xAF, 0x10, 0x4C, 0x10, 0x4D, 0x58, 0x77, 0xD4, 0xE9, 0x00, 0x12, 0x22, 0xF4, 0x00, 0x72, ++0x01, 0x20, 0x11, 0x43, 0x62, 0x60, 0x29, 0x60, 0x83, 0xF8, 0x24, 0x00, 0x05, 0x46, 0x20, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x00, 0x20, 0x00, 0x02, 0x70, 0x79, 0x15, 0x00, 0x10, 0x96, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x50, 0x90, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0xA3, 0x7A, 0xE2, 0x7A, 0x01, 0x33, 0xDB, 0xB2, ++0x9A, 0x42, 0xA3, 0x72, 0x00, 0xD3, 0x10, 0xBD, 0x10, 0xF0, 0xF6, 0xF9, 0x00, 0x23, 0xA3, 0x72, 0x10, 0xBD, 0x00, 0xBF, ++0x24, 0x65, 0x17, 0x00, 0x10, 0xB5, 0x10, 0x4C, 0xA3, 0x7A, 0xD3, 0xB9, 0xE3, 0x7A, 0xA3, 0x72, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4A, 0x0C, 0x4C, 0x11, 0x68, 0x23, 0x68, ++0x48, 0x1C, 0x23, 0xF4, 0x80, 0x73, 0x10, 0x60, 0x23, 0x60, 0x28, 0xB1, 0x05, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xF0, 0xCF, 0xF9, 0xE1, 0xE7, 0x24, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x08, 0xB5, 0x00, 0xF0, 0x29, 0xFC, 0xFF, 0xF7, 0x93, 0xFB, 0xBD, 0xE8, ++0x08, 0x40, 0x1A, 0xF0, 0x9F, 0xB8, 0x00, 0xBF, 0x0A, 0x4A, 0x0B, 0x4B, 0x10, 0xB5, 0xD2, 0xE9, 0x20, 0x04, 0xD2, 0xE9, ++0x22, 0x12, 0x04, 0x44, 0x0A, 0x44, 0xC3, 0xE9, 0x01, 0x40, 0xC3, 0xE9, 0x03, 0x12, 0x18, 0x60, 0x59, 0x61, 0xFF, 0xF7, ++0x7D, 0xFB, 0xBD, 0xE8, 0x10, 0x40, 0x1A, 0xF0, 0x89, 0xB8, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x68, 0x81, 0xDF, 0xF8, 0x68, 0x91, 0xDF, 0xF8, 0x68, 0xA1, 0xDF, 0xF8, 0x68, 0xB1, ++0x4D, 0x4F, 0x87, 0xB0, 0x00, 0x25, 0x3C, 0xE0, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF5, 0x80, 0x1F, 0x4E, 0xD8, 0x20, 0x2D, ++0x4C, 0xD0, 0x10, 0xF0, 0x8D, 0xF9, 0x00, 0x28, 0x61, 0xD0, 0x1A, 0xF0, 0x81, 0xFC, 0x00, 0x28, 0x5D, 0xD0, 0x62, 0x69, ++0x5A, 0x45, 0x0E, 0xD0, 0x43, 0x4B, 0xB9, 0x68, 0x1E, 0x68, 0x53, 0xF8, 0x04, 0x0C, 0x7B, 0x68, 0xCD, 0xE9, 0x02, 0x60, ++0xCD, 0xE9, 0x00, 0x31, 0x3F, 0x48, 0x3B, 0x68, 0x21, 0x46, 0x0F, 0xF0, 0x97, 0xFE, 0x20, 0x46, 0x3D, 0x4E, 0x01, 0xF0, ++0x41, 0xF9, 0x00, 0x22, 0xD6, 0xF8, 0x94, 0x32, 0x8D, 0xF8, 0x17, 0x20, 0x0D, 0xF1, 0x17, 0x01, 0x20, 0x46, 0x98, 0x47, ++0x58, 0xBB, 0x9D, 0xF8, 0x17, 0x30, 0x73, 0xB3, 0x36, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x31, 0xD0, 0x03, 0x2B, ++0x02, 0xD1, 0xD6, 0xF8, 0x8C, 0x32, 0x98, 0x47, 0x01, 0x35, 0x01, 0xF0, 0x09, 0xF9, 0x4F, 0xF4, 0x80, 0x33, 0xC9, 0xF8, ++0x00, 0x30, 0x04, 0x46, 0x4F, 0xF4, 0x80, 0x10, 0x0E, 0xF0, 0x18, 0xFC, 0x98, 0xF8, 0xB8, 0x30, 0x94, 0xB3, 0x00, 0x2B, ++0xB2, 0xD1, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF5, 0x80, 0x1F, 0x01, 0xD8, 0x03, 0x2D, 0xB2, 0xDD, 0x4F, 0xF4, 0x80, 0x10, ++0x0E, 0xF0, 0xE4, 0xFB, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD6, 0xF8, 0xC8, 0x32, 0x20, 0x46, 0x98, 0x47, 0x00, 0x28, ++0xD0, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0xC4, 0xF8, 0x1D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0xCD, 0xD1, 0xD6, 0xF8, ++0x90, 0x32, 0x98, 0x47, 0xCE, 0xE7, 0x1A, 0x4B, 0x01, 0x22, 0x83, 0xF8, 0x45, 0x20, 0x1A, 0xF0, 0x1B, 0xFC, 0xB0, 0xFA, ++0x80, 0xF2, 0x17, 0x49, 0x52, 0x09, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x8D, 0xFE, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x1B, 0xB1, 0x13, 0x4D, 0x95, 0xF8, 0x21, 0x30, 0x3B, 0xB9, 0x12, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, ++0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD5, 0xE9, 0x05, 0x12, 0x28, 0x69, 0xF3, 0xF7, 0x5E, 0xFE, 0x6C, 0x61, 0xEC, 0x61, ++0x2C, 0x61, 0xAC, 0x61, 0x85, 0xF8, 0x21, 0x40, 0xEB, 0xE7, 0x00, 0xBF, 0xEC, 0x34, 0x17, 0x00, 0xD4, 0x81, 0x32, 0x40, ++0x3C, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x28, 0x96, 0x15, 0x00, ++0x30, 0x65, 0x17, 0x00, 0x80, 0x80, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x7C, 0x80, 0x32, 0x40, 0x80, 0xB6, 0x17, 0x00, ++0x0D, 0xF0, 0xAD, 0xBA, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0x86, 0xBB, 0x2D, 0xE9, 0xF8, 0x43, 0x30, 0x4D, 0x2C, 0x68, ++0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0xA2, 0xFB, 0x00, 0x2C, 0x31, 0xD0, 0xDF, 0xF8, 0xC4, 0x90, 0x2C, 0x4F, 0x2E, 0x46, ++0x4F, 0xF0, 0x01, 0x08, 0x23, 0x7C, 0xD9, 0x07, 0x02, 0xD4, 0x2B, 0x89, 0x01, 0x33, 0x2B, 0x81, 0x30, 0x46, 0x0E, 0xF0, ++0x53, 0xFC, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC7, 0xF8, 0x00, 0x80, 0xD9, 0xF8, 0x00, 0x30, ++0x62, 0x68, 0x01, 0x33, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x30, 0x21, 0x74, 0x0A, 0xB1, 0xA0, 0x68, 0x90, 0x47, 0xE0, 0x68, ++0x08, 0xB1, 0x00, 0xF0, 0x77, 0xFB, 0xD9, 0xF8, 0x00, 0x30, 0x33, 0xB1, 0x01, 0x3B, 0x3A, 0x68, 0xC9, 0xF8, 0x00, 0x30, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x2C, 0x68, 0x00, 0x2C, 0xD3, 0xD1, 0xAA, 0x7A, 0xEB, 0x7A, 0x9A, 0x42, 0x20, 0xD0, ++0x13, 0x4B, 0x14, 0x48, 0x1B, 0x69, 0x14, 0x4A, 0xC8, 0x33, 0x4F, 0xF4, 0x80, 0x71, 0x03, 0x60, 0x11, 0x60, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0E, 0x4A, 0x0E, 0x4C, 0x11, 0x68, ++0x23, 0x68, 0x48, 0x1C, 0x43, 0xF4, 0x80, 0x73, 0x10, 0x60, 0x23, 0x60, 0x28, 0xB1, 0x05, 0x4B, 0x11, 0x60, 0x1B, 0x68, ++0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x48, 0x01, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, ++0x2D, 0xE9, 0xF8, 0x43, 0x27, 0x4D, 0x2C, 0x68, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0x30, 0xFB, 0x9C, 0xB3, 0xDF, 0xF8, ++0x9C, 0x80, 0xDF, 0xF8, 0x9C, 0x90, 0x00, 0x27, 0x2E, 0x46, 0x27, 0xE0, 0x01, 0x27, 0x30, 0x46, 0x0E, 0xF0, 0xE6, 0xFB, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x00, 0x30, ++0x62, 0x68, 0x01, 0x33, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x30, 0x21, 0x74, 0x0A, 0xB1, 0xA0, 0x68, 0x90, 0x47, 0xE0, 0x68, ++0x08, 0xB1, 0x00, 0xF0, 0x09, 0xFB, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0xC9, 0xF8, ++0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x2C, 0x68, 0x24, 0xB1, 0x23, 0x7C, 0xDA, 0x07, 0xD5, 0xD4, 0x00, 0x2F, ++0xD2, 0xD0, 0x0B, 0x4C, 0x94, 0xF8, 0x45, 0x30, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0x80, 0x10, 0x0E, 0xF0, ++0xCD, 0xFA, 0x07, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x94, 0xFD, 0x00, 0x23, 0x84, 0xF8, 0x45, 0x30, 0xBD, 0xE8, ++0xF8, 0x83, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x96, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x2B, 0x4E, 0x34, 0x68, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0xD4, 0xFA, ++0x00, 0x2C, 0x3F, 0xD0, 0x28, 0x4D, 0x2B, 0x88, 0x00, 0x2B, 0x3B, 0xD0, 0xDF, 0xF8, 0xA4, 0x80, 0xDF, 0xF8, 0xA4, 0x90, ++0x37, 0x46, 0x23, 0x7C, 0xD9, 0x07, 0x01, 0xD4, 0x2B, 0x88, 0x6B, 0xB3, 0x38, 0x46, 0x0E, 0xF0, 0x83, 0xFB, 0xEF, 0xF3, ++0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x00, 0x30, 0x22, 0x7C, ++0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0xD3, 0x07, 0x02, 0xD4, 0x2B, 0x88, 0x01, 0x3B, 0x2B, 0x80, 0x63, 0x68, 0x00, 0x22, ++0x22, 0x74, 0x0B, 0xB1, 0xA0, 0x68, 0x98, 0x47, 0xE0, 0x68, 0x08, 0xB1, 0x00, 0xF0, 0xA0, 0xFA, 0xD9, 0xF8, 0x00, 0x30, ++0x3B, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x34, 0x68, ++0x00, 0x2C, 0xCC, 0xD1, 0x0B, 0x4C, 0x94, 0xF8, 0x45, 0x30, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0x80, 0x10, ++0x0E, 0xF0, 0x68, 0xFA, 0x07, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x2F, 0xFD, 0x00, 0x23, 0x84, 0xF8, 0x45, 0x30, ++0xBD, 0xE8, 0xF8, 0x83, 0x24, 0x65, 0x17, 0x00, 0x54, 0x28, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x96, 0x15, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF8, 0xB5, 0x0D, 0x4E, 0x35, 0x68, 0x95, 0xB1, 0x34, 0x89, 0x01, 0x34, ++0xA4, 0xB2, 0x37, 0x46, 0x38, 0x46, 0x0E, 0xF0, 0x2D, 0xFB, 0x6B, 0x68, 0x0B, 0xB1, 0xA8, 0x68, 0x98, 0x47, 0x0F, 0xF0, ++0x99, 0xFF, 0x35, 0x68, 0x34, 0x81, 0x01, 0x34, 0xA4, 0xB2, 0x00, 0x2D, 0xF0, 0xD1, 0xBD, 0xE8, 0xF8, 0x40, 0x00, 0xF0, ++0xF5, 0xB9, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x44, 0x4F, 0x06, 0x68, 0x15, 0x88, 0xDF, 0xF8, ++0x20, 0x91, 0xDF, 0xF8, 0x20, 0xA1, 0xDF, 0xF8, 0x20, 0xB1, 0x85, 0xB0, 0x4F, 0xF0, 0x00, 0x08, 0xCD, 0xE9, 0x02, 0x02, ++0x87, 0xF8, 0x02, 0x80, 0xCD, 0xF8, 0x04, 0x80, 0x4A, 0xE0, 0xC4, 0x1A, 0x2C, 0x44, 0x0C, 0x44, 0x55, 0x1B, 0xA9, 0xB2, ++0xA4, 0xB2, 0x00, 0x25, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x36, 0x4A, 0x01, 0x23, 0x13, 0x60, ++0xBA, 0xF8, 0x00, 0x30, 0xDB, 0xF8, 0x00, 0x20, 0xD9, 0xF8, 0x00, 0xC0, 0x00, 0x92, 0x02, 0xEB, 0xC3, 0x00, 0xB2, 0x68, ++0x42, 0x60, 0x00, 0x9A, 0x0C, 0xF1, 0x01, 0x0E, 0xC9, 0xF8, 0x00, 0xE0, 0x42, 0xF8, 0x33, 0x10, 0xFA, 0x78, 0x01, 0x33, ++0x01, 0x32, 0x88, 0x44, 0xAA, 0xF8, 0x00, 0x30, 0xFA, 0x70, 0x64, 0xBB, 0xC3, 0x78, 0xA7, 0xF8, 0x00, 0x80, 0x43, 0xF0, ++0x04, 0x03, 0x01, 0x22, 0xC3, 0x70, 0xBA, 0x70, 0xB8, 0x60, 0xBE, 0xF1, 0x00, 0x0F, 0x38, 0xD0, 0x21, 0x4B, 0xC9, 0xF8, ++0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, 0x31, 0xD1, 0x00, 0x2B, 0x2F, 0xD0, 0x62, 0xB6, 0x00, 0x2C, 0x2C, 0xD0, ++0x1C, 0x4B, 0x1A, 0x68, 0x73, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x1A, 0xDB, 0x01, 0x96, 0x21, 0x46, 0x1E, 0x46, ++0xF3, 0x68, 0x30, 0x89, 0x01, 0x33, 0x9B, 0xB2, 0x1A, 0x1A, 0x92, 0xB2, 0x4C, 0x19, 0x94, 0x42, 0xAB, 0xDA, 0x00, 0x24, ++0xB0, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, 0xE7, 0xD0, 0x0F, 0x4B, 0xC9, 0xF8, 0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, ++0xE0, 0xD1, 0x00, 0x2B, 0xDB, 0xD1, 0xDD, 0xE7, 0x00, 0x2B, 0xE2, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x00, 0x93, 0x4F, 0xF4, ++0x17, 0x72, 0x0F, 0xF0, 0xA9, 0xFE, 0x00, 0x9B, 0xD9, 0xE7, 0x02, 0x9B, 0x01, 0x98, 0x1E, 0x60, 0x03, 0x9B, 0x1D, 0x80, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x54, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xB0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x41, 0x4F, 0xB2, 0xF8, 0x00, 0xA0, 0x06, 0x68, 0xDF, 0xF8, 0x0C, 0xB1, 0x87, 0xB0, 0x4F, 0xF0, ++0x00, 0x08, 0xCD, 0xE9, 0x04, 0x02, 0x01, 0x22, 0x0B, 0x46, 0x87, 0xF8, 0x20, 0x20, 0xC1, 0x46, 0xCD, 0xF8, 0x0C, 0x80, ++0x39, 0xE0, 0x05, 0x44, 0xAD, 0x1A, 0xA1, 0xEB, 0x0A, 0x03, 0xAD, 0xB2, 0x9B, 0xB2, 0x00, 0x2D, 0x02, 0x93, 0x08, 0xBF, ++0x4F, 0xF0, 0x01, 0x09, 0xF2, 0xF7, 0x3C, 0xFC, 0x4F, 0xF0, 0x00, 0x0A, 0x02, 0x9B, 0x04, 0x46, 0x00, 0x28, 0x3A, 0xD0, ++0x7A, 0x68, 0x02, 0xB9, 0x38, 0x60, 0xDB, 0xF8, 0x00, 0x00, 0xF9, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x19, 0x44, 0x01, 0x32, ++0x00, 0x28, 0xF9, 0x60, 0x7A, 0x60, 0xB1, 0x68, 0x36, 0xDB, 0xCD, 0xF8, 0x00, 0x90, 0x00, 0x22, 0x20, 0x46, 0xF3, 0xF7, ++0x6F, 0xFC, 0xB8, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0xC8, 0xF8, 0x04, 0x40, 0xBC, 0x60, 0x05, 0xB3, 0xDB, 0xF8, 0x00, 0x20, ++0x73, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x2E, 0xDB, 0x03, 0x96, 0xA0, 0x46, 0x1E, 0x46, 0x2B, 0x46, 0xF2, 0x68, ++0x35, 0x89, 0x01, 0x32, 0x92, 0xB2, 0x51, 0x1B, 0x89, 0xB2, 0x03, 0xEB, 0x0A, 0x00, 0x88, 0x42, 0xBB, 0xDA, 0x02, 0x93, ++0xF2, 0xF7, 0x02, 0xFC, 0x00, 0x25, 0x02, 0x9B, 0x4F, 0xF0, 0x01, 0x09, 0x04, 0x46, 0x00, 0x28, 0xC4, 0xD1, 0x87, 0xF8, ++0x20, 0x00, 0x04, 0x9B, 0x03, 0x98, 0x1E, 0x60, 0x05, 0x9B, 0xA3, 0xF8, 0x00, 0xA0, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x00, 0x29, 0xC6, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x02, 0x93, 0x40, 0xF2, 0x9E, 0x22, 0x0F, 0xF0, 0x17, 0xFE, 0xB1, 0x68, ++0x02, 0x9B, 0xBC, 0xE7, 0x00, 0x2B, 0xCE, 0xD1, 0x05, 0x49, 0x07, 0x48, 0x02, 0x93, 0x40, 0xF2, 0xB3, 0x22, 0x0F, 0xF0, ++0x0B, 0xFE, 0x02, 0x9B, 0xC5, 0xE7, 0x00, 0xBF, 0x30, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x96, 0x15, 0x00, ++0xA0, 0x96, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x08, 0x91, 0x07, 0x68, 0xD9, 0xF8, ++0x00, 0x40, 0x1D, 0x88, 0x94, 0xF8, 0x00, 0xC0, 0xDF, 0xF8, 0xFC, 0xA0, 0x85, 0xB0, 0xB1, 0xF5, 0xC8, 0x6F, 0x0E, 0x9E, ++0x03, 0x93, 0x06, 0xEB, 0x46, 0x06, 0x28, 0xBF, 0x4F, 0xF4, 0xC8, 0x61, 0xBC, 0xF1, 0x03, 0x0F, 0x08, 0xBF, 0x34, 0x4B, ++0x02, 0x90, 0x07, 0xEB, 0x06, 0x16, 0x06, 0xF1, 0x14, 0x06, 0x90, 0x46, 0x08, 0xBF, 0x1E, 0x60, 0x00, 0x20, 0x2C, 0xE0, ++0xAE, 0xEB, 0x03, 0x04, 0x2C, 0x44, 0x0C, 0x44, 0x52, 0x1B, 0xA4, 0xB2, 0x91, 0xB2, 0x00, 0x25, 0xBC, 0xF1, 0x03, 0x0F, ++0x0D, 0xD1, 0xB1, 0xF5, 0x00, 0x6F, 0x0B, 0x46, 0x28, 0xBF, 0x4F, 0xF4, 0x00, 0x63, 0x43, 0xF0, 0x23, 0x43, 0x4F, 0xF0, ++0x04, 0x12, 0xB3, 0x60, 0xF1, 0x60, 0x31, 0x61, 0x72, 0x61, 0x88, 0x44, 0xA4, 0xB3, 0xDA, 0xF8, 0x00, 0x20, 0x7B, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xF1, 0x14, 0x0B, 0x1C, 0xDB, 0xBC, 0xF1, 0x03, 0x0F, 0x01, 0xD1, 0xC6, 0xF8, ++0x20, 0xB0, 0x38, 0x46, 0x5E, 0x46, 0x1F, 0x46, 0x21, 0x46, 0xD7, 0xE9, 0x02, 0x43, 0x01, 0x33, 0x1F, 0xFA, 0x84, 0xFE, ++0x9B, 0xB2, 0xA3, 0xEB, 0x0E, 0x02, 0x05, 0xEB, 0x04, 0x0B, 0x92, 0xB2, 0x4C, 0x19, 0x94, 0x42, 0xC6, 0xF8, 0x04, 0x80, ++0xC6, 0xF8, 0x00, 0xB0, 0xC0, 0xDA, 0x00, 0x24, 0xC6, 0xE7, 0x00, 0x2B, 0xE0, 0xD1, 0x4F, 0xF4, 0x4A, 0x72, 0x0D, 0x49, ++0x0D, 0x48, 0x01, 0x93, 0x0F, 0xF0, 0x90, 0xFD, 0xD9, 0xF8, 0x00, 0x20, 0x01, 0x9B, 0x92, 0xF8, 0x00, 0xC0, 0xD3, 0xE7, ++0xBC, 0xF1, 0x03, 0x0F, 0x02, 0xD1, 0x05, 0x4B, 0x34, 0x62, 0x5E, 0x60, 0x02, 0x9B, 0x1F, 0x60, 0x03, 0x9B, 0x1D, 0x80, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x60, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, ++0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x61, 0xB3, 0x0B, 0x8A, 0xDA, 0x07, 0x12, 0xD4, 0x16, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x20, 0x02, 0xE0, 0x0B, 0x8A, 0xDB, 0x07, 0x0A, 0xD4, 0x00, 0x2A, 0x49, 0x68, 0xF9, 0xDA, 0x00, 0x29, ++0xF7, 0xD1, 0x11, 0x49, 0x11, 0x48, 0x40, 0xF2, 0xE6, 0x32, 0x0F, 0xF0, 0x29, 0xBD, 0xCB, 0x68, 0x23, 0xF0, 0x03, 0x03, ++0x04, 0x33, 0x0E, 0x49, 0x4A, 0x68, 0x9A, 0x42, 0x8A, 0x68, 0x08, 0xBF, 0x0B, 0x68, 0xC0, 0xF8, 0x98, 0x30, 0x22, 0xF0, ++0x00, 0x40, 0x83, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, 0x13, 0x43, 0x8B, 0x60, 0x70, 0x47, ++0x00, 0xF1, 0xA0, 0x03, 0xE9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, ++0xEC, 0x34, 0x17, 0x00, 0x18, 0x4B, 0x19, 0x4A, 0x18, 0x68, 0x19, 0x49, 0xDF, 0xF8, 0x7C, 0xC0, 0xF0, 0xB5, 0xD0, 0xE9, ++0x00, 0x34, 0x17, 0x4D, 0x13, 0x60, 0x1C, 0x44, 0x2B, 0x60, 0x25, 0x1F, 0x0D, 0x60, 0x15, 0x4E, 0x15, 0x4D, 0x11, 0x68, ++0x31, 0x60, 0x29, 0x60, 0xD0, 0xE9, 0x02, 0x10, 0xDF, 0xF8, 0x5C, 0xE0, 0x12, 0x4F, 0x54, 0x60, 0x08, 0x44, 0x69, 0x60, ++0x11, 0x4C, 0x93, 0x60, 0x11, 0x4E, 0x03, 0x1F, 0xCE, 0xF8, 0x00, 0x30, 0xCC, 0xF8, 0x00, 0x10, 0x39, 0x60, 0x6E, 0x61, ++0x23, 0x68, 0x10, 0x61, 0x03, 0xF4, 0x00, 0x23, 0x43, 0xF4, 0xF0, 0x23, 0x43, 0xF0, 0x25, 0x03, 0xD1, 0x60, 0x51, 0x61, ++0x23, 0x60, 0xF0, 0xBD, 0x30, 0x36, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, 0xCC, 0x81, 0x32, 0x40, 0xC8, 0x81, 0x32, 0x40, ++0xD0, 0x81, 0x32, 0x40, 0xD4, 0x81, 0x32, 0x40, 0xE4, 0x81, 0x32, 0x40, 0x0C, 0x01, 0x32, 0x40, 0x05, 0x12, 0x00, 0x0C, ++0xE0, 0x81, 0x32, 0x40, 0xDC, 0x81, 0x32, 0x40, 0x10, 0xB4, 0x0A, 0x4C, 0x0A, 0x49, 0x22, 0x68, 0x83, 0x02, 0x03, 0xF4, ++0x80, 0x63, 0x22, 0xF4, 0x80, 0x62, 0x13, 0x43, 0x23, 0x60, 0x0B, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0xC0, 0x04, 0x00, 0xF4, ++0x00, 0x20, 0x23, 0xF4, 0x00, 0x23, 0x18, 0x43, 0x08, 0x60, 0x70, 0x47, 0x24, 0x03, 0x32, 0x40, 0x0C, 0x01, 0x32, 0x40, ++0x90, 0xF8, 0x9C, 0x20, 0xD0, 0xF8, 0x98, 0x30, 0x6A, 0xB9, 0x0E, 0x4A, 0x12, 0x68, 0x22, 0xF0, 0x00, 0x41, 0x8B, 0x42, ++0x02, 0xF0, 0x00, 0x42, 0x0A, 0x49, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, 0x13, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x08, 0x4A, ++0x12, 0x68, 0x22, 0xF0, 0x00, 0x41, 0x8B, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x04, 0x49, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, ++0x13, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0xD0, 0x81, 0x32, 0x40, 0xE0, 0x81, 0x32, 0x40, 0x10, 0xB5, 0x03, 0x8E, ++0x82, 0xB0, 0xC3, 0xB1, 0x2D, 0x4B, 0xC4, 0x69, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x38, 0xDB, 0xA3, 0x68, ++0x42, 0x6D, 0x1B, 0x88, 0x03, 0xF0, 0xFC, 0x03, 0x24, 0x2B, 0x43, 0xD0, 0x94, 0x2B, 0x03, 0xD1, 0x42, 0xF2, 0x02, 0x03, ++0x93, 0x43, 0x36, 0xD0, 0xE3, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x07, 0xE0, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x18, 0xDB, 0x00, 0xF1, 0xA0, 0x03, 0x1E, 0x49, 0x0A, 0x69, 0x9A, 0x42, 0x4A, 0x69, 0x08, 0xBF, ++0xCB, 0x68, 0xC0, 0xF8, 0x98, 0x30, 0x22, 0xF0, 0x00, 0x44, 0xA3, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x38, 0xBF, 0x02, 0xF1, ++0x00, 0x42, 0x13, 0x43, 0x4B, 0x61, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x9E, 0xBF, 0xC3, 0x69, 0x00, 0x2B, ++0xE3, 0xD0, 0x12, 0x49, 0x12, 0x48, 0x4F, 0xF4, 0xD7, 0x72, 0x05, 0xE0, 0x00, 0x2C, 0xC4, 0xD1, 0x0E, 0x49, 0x10, 0x48, ++0x4F, 0xF4, 0xC2, 0x72, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0x0F, 0xF0, 0x2F, 0xBC, 0x0D, 0x4B, 0x01, 0x90, 0xD3, 0xF8, ++0x74, 0x33, 0x98, 0x47, 0x01, 0x98, 0xC1, 0xE7, 0x93, 0x04, 0xBF, 0xD5, 0x08, 0x4B, 0x01, 0x90, 0xD3, 0xF8, 0xFC, 0x33, ++0x98, 0x47, 0x01, 0x98, 0xB8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0x96, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x29, 0x46, 0xD0, 0x2D, 0xE9, 0xF8, 0x4F, ++0x07, 0x46, 0xDF, 0xF8, 0x8C, 0xA0, 0xDF, 0xF8, 0x8C, 0xB0, 0x08, 0x46, 0x1F, 0x49, 0x99, 0x46, 0x4F, 0xF0, 0x00, 0x08, ++0xD7, 0xE9, 0x02, 0x45, 0x01, 0x35, 0xAB, 0xB2, 0xA6, 0xB2, 0x9D, 0x1B, 0xAD, 0xB2, 0xAD, 0x1A, 0xA8, 0x42, 0x23, 0xDB, ++0xF6, 0x1A, 0x16, 0x44, 0x06, 0x44, 0xB6, 0xB2, 0xA8, 0xB2, 0xC5, 0x1C, 0x4F, 0xEA, 0x98, 0x03, 0xAD, 0x08, 0x14, 0x44, ++0x09, 0xEB, 0x83, 0x03, 0x08, 0xD0, 0x1A, 0x46, 0x03, 0xEB, 0x85, 0x05, 0xE3, 0x1A, 0xD4, 0x58, 0x42, 0xF8, 0x04, 0x4B, ++0xAA, 0x42, 0xFA, 0xD1, 0xBE, 0xB1, 0xDA, 0xF8, 0x00, 0x30, 0x7F, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x80, 0x44, 0x00, 0x2B, ++0x1F, 0xFA, 0x88, 0xF8, 0x04, 0xDB, 0x30, 0x46, 0x00, 0x22, 0xD1, 0xE7, 0x00, 0x26, 0xDE, 0xE7, 0x00, 0x2F, 0xF8, 0xD1, ++0x40, 0xF2, 0x2D, 0x42, 0x58, 0x46, 0x0F, 0xF0, 0xFF, 0xFB, 0x02, 0x49, 0xF1, 0xE7, 0xBD, 0xE8, 0xF8, 0x8F, 0x70, 0x47, ++0x70, 0x79, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xEC, 0x96, 0x15, 0x00, 0x38, 0xB5, 0x13, 0x4C, 0x94, 0xF8, 0x21, 0x30, ++0xA3, 0xB9, 0x20, 0x61, 0x11, 0x48, 0xE3, 0x69, 0xE2, 0x68, 0x61, 0x69, 0x65, 0x68, 0x90, 0xF8, 0xB9, 0x00, 0x13, 0x44, ++0x29, 0x44, 0xA2, 0x68, 0x61, 0x61, 0x01, 0x25, 0xB3, 0xEB, 0x40, 0x2F, 0xE3, 0x61, 0x84, 0xF8, 0x21, 0x50, 0xA2, 0x61, ++0x03, 0xD2, 0x38, 0xBD, 0xA3, 0x69, 0x58, 0x60, 0xE8, 0xE7, 0x20, 0x69, 0xF3, 0xF7, 0x90, 0xF9, 0x00, 0x23, 0xC4, 0xE9, ++0x04, 0x33, 0xC4, 0xE9, 0x06, 0x33, 0x84, 0xF8, 0x21, 0x30, 0x38, 0xBD, 0x30, 0x65, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0xAB, 0x4E, 0xD0, 0xF8, 0x1C, 0xC0, 0x35, 0x68, 0x86, 0xB0, 0x04, 0x46, 0xCD, 0xF8, 0x14, 0xC0, ++0xAD, 0xF8, 0x0E, 0x30, 0x2B, 0x78, 0x02, 0x2B, 0x91, 0x46, 0x00, 0xF0, 0xAD, 0x80, 0x01, 0x2B, 0xDF, 0xF8, 0xC4, 0x82, ++0x22, 0xD0, 0x01, 0x20, 0x00, 0x23, 0xD8, 0xF8, 0xAC, 0x52, 0x4A, 0x46, 0xCD, 0xE9, 0x00, 0x30, 0x0D, 0xF1, 0x0E, 0x03, ++0x05, 0xA8, 0xA8, 0x47, 0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0x46, 0x1F, 0xD0, 0x01, 0x2B, 0x59, 0xD0, 0xD8, 0xF8, ++0x98, 0x32, 0x05, 0x99, 0x20, 0x46, 0x2A, 0x46, 0x98, 0x47, 0x0E, 0x9B, 0x63, 0x60, 0x0F, 0x9B, 0x95, 0x48, 0xA3, 0x60, ++0x21, 0x46, 0x0D, 0xF0, 0x3F, 0xFF, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xD8, 0xF8, 0xB0, 0x52, 0x00, 0x23, 0x00, 0x93, ++0x0D, 0xF1, 0x0E, 0x02, 0x05, 0xA8, 0xA8, 0x47, 0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0x46, 0xDF, 0xD1, 0xDF, 0xF8, ++0x64, 0x92, 0x99, 0xF8, 0x02, 0x30, 0x00, 0x2B, 0xDB, 0xD0, 0xB9, 0xF8, 0x00, 0x30, 0x7A, 0x68, 0x3A, 0x33, 0xBB, 0x60, ++0xD3, 0x78, 0x6F, 0xF3, 0x87, 0x13, 0xD3, 0x70, 0x99, 0xF8, 0x03, 0x30, 0xBB, 0x73, 0x00, 0x23, 0x3B, 0x60, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x7F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x20, 0xA2, 0x7E, 0x48, ++0xDA, 0xF8, 0x00, 0x30, 0x39, 0x46, 0x01, 0x33, 0xCA, 0xF8, 0x00, 0x30, 0x0D, 0xF0, 0x08, 0xFF, 0xD8, 0xF8, 0x44, 0x34, ++0x98, 0x47, 0xDA, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x75, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCA, 0xF8, 0x00, 0x30, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x00, 0x23, 0xC9, 0xE9, 0x00, 0x33, 0x32, 0x68, 0x13, 0x78, 0x01, 0x2B, 0xA5, 0xD1, 0xF2, 0xF7, ++0x15, 0xF9, 0x07, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x92, 0x80, 0x6D, 0x4E, 0x96, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x00, 0xF0, ++0x96, 0x80, 0x73, 0x68, 0x81, 0x68, 0x32, 0x68, 0x03, 0xF1, 0x01, 0x0C, 0x4F, 0xEA, 0x0C, 0x63, 0x21, 0xF0, 0xFE, 0x41, ++0x03, 0xF0, 0xFE, 0x43, 0x0B, 0x43, 0x00, 0x21, 0x83, 0x60, 0x00, 0x91, 0x3A, 0x23, 0x04, 0xF1, 0x30, 0x01, 0xC6, 0xF8, ++0x04, 0xC0, 0xF3, 0xF7, 0x43, 0xF9, 0x60, 0x4A, 0xF3, 0x68, 0x92, 0xF8, 0xB8, 0x20, 0x3A, 0x33, 0xF3, 0x60, 0x38, 0x46, ++0x00, 0x2A, 0x40, 0xF0, 0xA7, 0x80, 0xD6, 0xE9, 0x01, 0x12, 0xF3, 0xF7, 0xD3, 0xF8, 0x5A, 0x49, 0x0A, 0x78, 0x00, 0x23, ++0x42, 0xF0, 0x01, 0x02, 0x0A, 0x70, 0x73, 0x60, 0xF3, 0x60, 0x33, 0x60, 0xB3, 0x60, 0x86, 0xF8, 0x20, 0x30, 0x68, 0xE7, ++0x54, 0x4D, 0x42, 0xF2, 0x24, 0x03, 0xEA, 0x58, 0x00, 0x2A, 0x68, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x4A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x42, 0xF2, 0x34, 0x02, 0xDF, 0xF8, 0x44, 0x81, 0xA8, 0x5A, 0xD8, 0xF8, ++0x00, 0x30, 0x02, 0x91, 0x01, 0x33, 0xB0, 0xF5, 0xC3, 0x7F, 0xC8, 0xF8, 0x00, 0x30, 0x48, 0x48, 0xDF, 0xF8, 0x3C, 0xA1, ++0x84, 0xBF, 0x00, 0x23, 0xAB, 0x52, 0x0D, 0xF0, 0xD7, 0xFE, 0x45, 0x4A, 0x02, 0x99, 0xD2, 0xF8, 0x00, 0xC0, 0x42, 0xF2, ++0x34, 0x0E, 0x07, 0x46, 0x35, 0xF8, 0x0E, 0x30, 0xBB, 0x81, 0x0C, 0xEB, 0xC3, 0x00, 0x04, 0xF1, 0x30, 0x02, 0x42, 0x60, ++0x4C, 0xF8, 0x33, 0xA0, 0xDF, 0xF8, 0x08, 0xC1, 0x78, 0x60, 0x95, 0xF8, 0x02, 0xAC, 0x9C, 0xF8, 0x03, 0x00, 0xD8, 0xF8, ++0x00, 0x20, 0x01, 0x33, 0x0A, 0xF1, 0x01, 0x0A, 0x01, 0x30, 0x25, 0xF8, 0x0E, 0x30, 0x85, 0xF8, 0x02, 0xAC, 0x8C, 0xF8, ++0x03, 0x00, 0x3A, 0xB1, 0x2B, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, 0x00, 0x20, 0x0A, 0xB9, 0x00, 0x2B, 0x48, 0xD1, ++0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x7F, 0xF4, 0xFE, 0xAE, 0xDF, 0xF8, 0xC4, 0x80, 0x00, 0x23, 0xD8, 0xF8, 0xB4, 0x52, ++0x21, 0xE7, 0x23, 0x7C, 0x29, 0x48, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x0F, 0xF0, 0x2E, 0xF8, 0x20, 0x4B, 0x83, 0xF8, ++0x20, 0x70, 0x26, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x76, 0xF8, 0x23, 0x7C, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, ++0xF9, 0xE6, 0x03, 0x7C, 0xDF, 0xF8, 0x8C, 0x80, 0x43, 0xF0, 0x01, 0x03, 0x03, 0x74, 0xD8, 0xF8, 0x98, 0x32, 0x61, 0x46, ++0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x19, 0x4C, ++0xD8, 0xF8, 0x44, 0x24, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x01, 0x46, 0x33, 0xB1, 0x0A, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x11, 0x48, 0xF0, 0xF7, 0x31, 0xFE, 0xE0, 0xE6, ++0xFF, 0xF7, 0x7E, 0xFE, 0x59, 0xE7, 0x62, 0xB6, 0xB4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x24, 0x65, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x30, 0x65, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x9C, 0x4E, 0x17, 0x00, ++0x7C, 0x36, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, 0x0C, 0x97, 0x15, 0x00, 0x20, 0x97, 0x15, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xF8, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x54, 0x65, 0x17, 0x00, 0x3C, 0x00, 0x00, 0xC0, ++0x2D, 0xE9, 0xF0, 0x4F, 0xAE, 0x4B, 0xDF, 0xF8, 0x00, 0xA3, 0xC1, 0x69, 0x9A, 0xF8, 0x32, 0x20, 0x1B, 0x68, 0x87, 0xB0, ++0x04, 0x46, 0x05, 0x91, 0xAD, 0xF8, 0x12, 0x20, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xF0, 0x3F, 0x81, 0x02, 0x2B, 0x77, 0xD0, ++0xA6, 0x4A, 0x27, 0x8E, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xBF, 0x80, 0x01, 0x2B, 0xA3, 0x4E, ++0x4F, 0xF0, 0x00, 0x03, 0x00, 0xF0, 0x3A, 0x81, 0xCD, 0xE9, 0x00, 0x33, 0x39, 0x46, 0xD6, 0xF8, 0xAC, 0x52, 0x0D, 0xF1, ++0x12, 0x03, 0x5A, 0x46, 0x05, 0xA8, 0xA8, 0x47, 0x07, 0xEB, 0x0B, 0x01, 0xCA, 0xF8, 0x1C, 0x10, 0x07, 0x46, 0x00, 0x21, ++0x04, 0xF1, 0x58, 0x00, 0xEB, 0xF7, 0x7E, 0xFD, 0x94, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xF0, 0xB8, 0x80, ++0x01, 0x2B, 0x00, 0xF0, 0x49, 0x81, 0x02, 0x2B, 0x41, 0xD1, 0xDF, 0xF8, 0x88, 0xA2, 0x9A, 0xF8, 0x02, 0x30, 0x00, 0x2B, ++0x3B, 0xD0, 0xBA, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x04, 0x20, 0x3A, 0x33, 0xC8, 0xF8, 0x08, 0x30, 0xD3, 0x78, 0x6F, 0xF3, ++0x87, 0x13, 0xD3, 0x70, 0x9A, 0xF8, 0x03, 0x30, 0x88, 0xF8, 0x0E, 0x30, 0x00, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xEF, 0xF3, ++0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x83, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x14, 0xB2, 0x82, 0x48, ++0xDB, 0xF8, 0x00, 0x30, 0x41, 0x46, 0x01, 0x33, 0xCB, 0xF8, 0x00, 0x30, 0x0D, 0xF0, 0x8C, 0xFD, 0xD6, 0xF8, 0x44, 0x34, ++0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x79, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x72, 0x4B, 0x1A, 0x68, 0x00, 0x23, 0xCA, 0xE9, 0x00, 0x33, 0x13, 0x78, 0x03, 0x2B, 0x00, 0xF0, ++0x9E, 0x81, 0xD6, 0xF8, 0x98, 0x32, 0x05, 0x99, 0x3A, 0x46, 0x20, 0x46, 0x98, 0x47, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x6E, 0x4E, 0x42, 0xF2, 0x24, 0x03, 0xF2, 0x58, 0x00, 0x2A, 0x00, 0xF0, 0x60, 0x81, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x66, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x42, 0xF2, 0x34, 0x02, 0x67, 0x4F, 0xB1, 0x5A, 0x3B, 0x68, ++0x66, 0x48, 0x01, 0x33, 0xB1, 0xF5, 0xC3, 0x7F, 0x3B, 0x60, 0x84, 0xBF, 0x00, 0x23, 0xB3, 0x52, 0x0D, 0xF0, 0x92, 0xFD, ++0x62, 0x4A, 0x42, 0xF2, 0x34, 0x0E, 0xD2, 0xF8, 0x00, 0xC0, 0x36, 0xF8, 0x0E, 0x30, 0x83, 0x81, 0x0C, 0xEB, 0xC3, 0x01, ++0x04, 0xF1, 0x30, 0x02, 0x4A, 0x60, 0x5D, 0x4A, 0x4C, 0xF8, 0x33, 0x20, 0xDF, 0xF8, 0x94, 0xC1, 0x41, 0x60, 0x96, 0xF8, ++0x02, 0x1C, 0x9C, 0xF8, 0x03, 0x20, 0x80, 0x46, 0x38, 0x68, 0x01, 0x33, 0x01, 0x31, 0x01, 0x32, 0x26, 0xF8, 0x0E, 0x30, ++0x86, 0xF8, 0x02, 0x1C, 0x8C, 0xF8, 0x03, 0x20, 0x30, 0xB1, 0x4C, 0x4B, 0x01, 0x38, 0x1B, 0x68, 0x38, 0x60, 0x08, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0x46, 0x4B, 0x27, 0x8E, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0xDA, 0x00, 0x2F, ++0x00, 0xF0, 0x07, 0x81, 0xB7, 0xF5, 0x40, 0x5F, 0x00, 0xF2, 0x0A, 0x81, 0x3E, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, ++0x7F, 0xF4, 0x34, 0xAF, 0x3D, 0x4E, 0x39, 0x46, 0xD6, 0xF8, 0xB4, 0x72, 0x00, 0x23, 0x00, 0x93, 0x0D, 0xF1, 0x12, 0x02, ++0x05, 0xA8, 0xB8, 0x47, 0x07, 0x46, 0x3C, 0xE7, 0x3F, 0x4A, 0x40, 0x48, 0x53, 0x68, 0x60, 0x66, 0x04, 0xF1, 0x30, 0x00, ++0xA0, 0x66, 0x04, 0xF1, 0x68, 0x00, 0x3D, 0x49, 0xC4, 0xF8, 0x6C, 0x90, 0x18, 0x62, 0x3A, 0x23, 0x21, 0x67, 0x63, 0x67, ++0x4F, 0xF0, 0x04, 0x11, 0xA3, 0x67, 0x00, 0x23, 0x03, 0x90, 0xE1, 0x67, 0xC4, 0xF8, 0x88, 0x30, 0x10, 0x68, 0x03, 0x99, ++0x05, 0x22, 0xF0, 0xF7, 0xC5, 0xF9, 0x34, 0x4A, 0x13, 0x68, 0x18, 0x05, 0xFC, 0xD5, 0x13, 0x68, 0x59, 0x03, 0x03, 0xD5, ++0x11, 0x68, 0x41, 0xF0, 0x80, 0x61, 0x11, 0x60, 0x1A, 0x05, 0x21, 0xD5, 0xEF, 0xF3, 0x05, 0x80, 0x2D, 0x49, 0x41, 0xF2, ++0x4C, 0x12, 0x8B, 0x58, 0x43, 0xF0, 0x00, 0x63, 0x8B, 0x50, 0x00, 0x28, 0x40, 0xF0, 0xF3, 0x80, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1C, 0x4B, 0x25, 0x48, 0x19, 0x68, 0x00, 0x25, ++0x4A, 0x1C, 0x1A, 0x60, 0x45, 0x61, 0x2A, 0xB1, 0x15, 0x4A, 0x19, 0x60, 0x13, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, ++0x1F, 0x4D, 0x2B, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x1E, 0x4B, 0x18, 0x68, 0xA9, 0xF1, 0x14, 0x01, 0x00, 0xF5, 0x0B, 0x70, ++0x0D, 0xF0, 0xAC, 0xFC, 0x01, 0x23, 0x2B, 0x60, 0xEF, 0xF7, 0x2E, 0xFD, 0x31, 0xE7, 0x0A, 0xF1, 0x40, 0x00, 0x0F, 0xF0, ++0x67, 0xF9, 0x05, 0x4B, 0x1B, 0x68, 0x81, 0x46, 0x1B, 0x78, 0x00, 0xF1, 0x3C, 0x0B, 0xB5, 0xE6, 0x39, 0x46, 0xD6, 0xF8, ++0xB0, 0x72, 0x8C, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0xA8, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, ++0x3C, 0x00, 0x00, 0xC0, 0x60, 0x65, 0x17, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x3A, 0x00, 0x00, 0xA3, 0x4C, 0x11, 0x07, 0x40, ++0x00, 0x00, 0x07, 0x40, 0x48, 0x35, 0x17, 0x00, 0x54, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0xB0, 0xDE, 0x17, 0x00, ++0x54, 0x65, 0x17, 0x00, 0xF1, 0xF7, 0x92, 0xFE, 0x83, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0xDF, 0xF8, 0x38, 0xA1, 0x9A, 0xF8, ++0x20, 0x30, 0x00, 0x2B, 0x41, 0xD0, 0xDA, 0xF8, 0x04, 0x30, 0x81, 0x68, 0xDA, 0xF8, 0x00, 0x20, 0x03, 0xF1, 0x01, 0x0C, ++0x4F, 0xEA, 0x0C, 0x63, 0x21, 0xF0, 0xFE, 0x41, 0x03, 0xF0, 0xFE, 0x43, 0x0B, 0x43, 0x00, 0x21, 0x83, 0x60, 0x00, 0x91, ++0x3A, 0x23, 0x04, 0xF1, 0x30, 0x01, 0xCA, 0xF8, 0x04, 0xC0, 0xF2, 0xF7, 0xBF, 0xFE, 0x3C, 0x4A, 0xDA, 0xF8, 0x0C, 0x30, ++0x92, 0xF8, 0xB8, 0x20, 0x3A, 0x33, 0xCA, 0xF8, 0x0C, 0x30, 0x58, 0x46, 0x00, 0x2A, 0x63, 0xD1, 0xDA, 0xE9, 0x01, 0x12, ++0xF2, 0xF7, 0x4E, 0xFE, 0x35, 0x49, 0x0A, 0x78, 0x00, 0x23, 0x42, 0xF0, 0x01, 0x02, 0x0A, 0x70, 0xCA, 0xF8, 0x04, 0x30, ++0xCA, 0xF8, 0x0C, 0x30, 0xCA, 0xF8, 0x00, 0x30, 0xCA, 0xF8, 0x08, 0x30, 0x8A, 0xF8, 0x20, 0x30, 0x12, 0xE0, 0x23, 0x7C, ++0x2D, 0x48, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x0E, 0xF0, 0x00, 0xFE, 0x2B, 0x4B, 0x83, 0xF8, 0x20, 0xB0, 0x2B, 0x49, ++0x4F, 0xF4, 0x80, 0x60, 0x0E, 0xF0, 0x48, 0xFE, 0x23, 0x7C, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x27, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x02, 0x2B, 0x3F, 0xF4, 0x5D, 0xAE, 0x9A, 0xE6, 0x25, 0x49, 0x25, 0x48, 0x40, 0xF2, 0x21, 0x52, 0x0F, 0xF0, ++0x2F, 0xF8, 0x9C, 0xE6, 0x21, 0x49, 0x23, 0x48, 0x40, 0xF2, 0x23, 0x52, 0x0F, 0xF0, 0x28, 0xF8, 0x95, 0xE6, 0x23, 0x7C, ++0x20, 0x4E, 0x05, 0x99, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0xD6, 0xF8, 0x98, 0x32, 0x20, 0x46, 0x98, 0x47, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1A, 0x4C, 0xD6, 0xF8, 0x44, 0x24, ++0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x01, 0x46, 0x33, 0xB1, 0x14, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x12, 0x48, 0xF0, 0xF7, 0xEF, 0xFB, 0x6E, 0xE6, 0xFF, 0xF7, 0x3C, 0xFC, ++0x9C, 0xE7, 0x10, 0x4B, 0x00, 0x22, 0x5A, 0x61, 0x1E, 0xE7, 0x0F, 0x4A, 0xE8, 0xE6, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, ++0x9C, 0x4E, 0x17, 0x00, 0x0C, 0x97, 0x15, 0x00, 0x30, 0x65, 0x17, 0x00, 0x20, 0x97, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x34, 0x97, 0x15, 0x00, 0x44, 0x97, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xFC, 0x96, 0x15, 0x00, 0x48, 0x35, 0x17, 0x00, 0x60, 0x65, 0x17, 0x00, 0x0D, 0x4B, 0xC1, 0x69, ++0xD3, 0xF8, 0x98, 0x32, 0x10, 0xB5, 0x00, 0x22, 0x04, 0x46, 0x98, 0x47, 0x0A, 0x48, 0x03, 0x68, 0x53, 0xB1, 0x23, 0x7C, ++0x43, 0xF0, 0x01, 0x03, 0x00, 0x22, 0x23, 0x74, 0x62, 0x60, 0x21, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x0D, 0xF0, 0xA0, 0xBB, ++0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x19, 0xBB, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x24, 0x65, 0x17, 0x00, ++0x0C, 0x4A, 0x0D, 0x49, 0x93, 0x68, 0x09, 0x68, 0x8B, 0x42, 0x11, 0xD0, 0x51, 0x68, 0x23, 0xF0, 0x00, 0x40, 0x09, 0x1A, ++0x9F, 0x29, 0x0C, 0xD8, 0x11, 0x68, 0x03, 0xF0, 0x00, 0x43, 0x88, 0x42, 0x88, 0xBF, 0x03, 0xF1, 0x00, 0x43, 0x0B, 0x43, ++0x93, 0x60, 0x23, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0xEC, 0x34, 0x17, 0x00, 0xD4, 0x81, 0x32, 0x40, ++0x1E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x21, 0xDB, 0x1B, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x9B, 0x07, 0x04, 0xD5, 0x63, 0x6D, 0x03, 0xF0, 0x3C, 0x03, 0x3C, 0x2B, 0x25, 0xD0, 0x23, 0x8E, 0x53, 0xB1, ++0x62, 0x6D, 0x02, 0xF0, 0x7C, 0x02, 0x08, 0x2A, 0x0D, 0xD0, 0x0C, 0x2A, 0x19, 0xD0, 0x04, 0x2A, 0x09, 0xD0, 0x04, 0x3B, ++0x23, 0x86, 0x00, 0x23, 0x10, 0x4A, 0x23, 0x74, 0x84, 0xF8, 0x9C, 0x30, 0xE4, 0x60, 0x62, 0x60, 0x10, 0xBD, 0x08, 0x3B, ++0x23, 0x86, 0xF4, 0xE7, 0x0C, 0x4B, 0x42, 0x69, 0x9A, 0x42, 0xD9, 0xD0, 0x0B, 0x49, 0x0C, 0x48, 0x40, 0xF2, 0x14, 0x62, ++0x0E, 0xF0, 0x98, 0xFF, 0xD2, 0xE7, 0x0C, 0x3B, 0x23, 0x86, 0xE6, 0xE7, 0x23, 0x8E, 0x04, 0x3B, 0x9B, 0xB2, 0x23, 0x86, ++0xD5, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x3D, 0x48, 0x13, 0x00, 0x0D, 0xF0, 0xAD, 0xBA, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x97, 0x15, 0x00, 0x06, 0x4B, 0x07, 0x4A, 0x4F, 0xF4, 0x80, 0x31, 0x19, 0x60, 0x13, 0x68, ++0x23, 0xF4, 0x80, 0x33, 0x13, 0x60, 0x4F, 0xF4, 0x80, 0x10, 0x0D, 0xF0, 0x7F, 0xBA, 0x00, 0xBF, 0x7C, 0x80, 0x32, 0x40, ++0x80, 0x80, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x47, 0x21, 0x4D, 0x22, 0x4E, 0x6B, 0x69, 0x32, 0x68, 0x93, 0x42, 0x84, 0xB0, ++0x38, 0xD0, 0xDF, 0xF8, 0x88, 0x80, 0x1F, 0x4F, 0xDF, 0xF8, 0x84, 0x90, 0x20, 0xE0, 0x6B, 0x69, 0x1D, 0x48, 0x23, 0xF0, ++0x00, 0x44, 0x21, 0x46, 0x62, 0x69, 0xBA, 0x42, 0x0A, 0xD0, 0xD6, 0xF8, 0x00, 0xE0, 0xD9, 0xF8, 0x00, 0xA0, 0xCD, 0xE9, ++0x00, 0xC3, 0xCD, 0xE9, 0x02, 0xEA, 0xEB, 0x68, 0x0E, 0xF0, 0xD4, 0xFC, 0x20, 0x46, 0xFF, 0xF7, 0x7F, 0xFF, 0x01, 0x23, ++0x84, 0xF8, 0x9C, 0x30, 0xD8, 0xF8, 0xC0, 0x32, 0x20, 0x46, 0x98, 0x47, 0x6B, 0x69, 0x32, 0x68, 0x93, 0x42, 0x11, 0xD0, ++0xD5, 0xF8, 0x10, 0xC0, 0x23, 0xF0, 0x00, 0x41, 0xAC, 0xEB, 0x01, 0x02, 0x9F, 0x2A, 0x03, 0xF0, 0x00, 0x43, 0xD4, 0xD8, ++0xEA, 0x68, 0x91, 0x42, 0x88, 0xBF, 0x03, 0xF1, 0x00, 0x43, 0x13, 0x43, 0x6B, 0x61, 0xCD, 0xE7, 0x04, 0xB0, 0xBD, 0xE8, ++0xF0, 0x87, 0x00, 0xBF, 0xEC, 0x34, 0x17, 0x00, 0xE4, 0x81, 0x32, 0x40, 0x0D, 0xF0, 0xAD, 0xBA, 0x90, 0x97, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xE0, 0x81, 0x32, 0x40, 0x00, 0xB5, 0x10, 0x4A, 0x10, 0x4B, 0x12, 0x68, 0x89, 0xB0, 0x08, 0x33, ++0x03, 0x92, 0x53, 0xF8, 0x08, 0x2C, 0x04, 0x92, 0x53, 0xF8, 0x04, 0x2C, 0x05, 0x92, 0x1B, 0x68, 0x06, 0x93, 0x01, 0xA8, ++0x00, 0x21, 0xEB, 0xF7, 0x73, 0xFA, 0x03, 0x9B, 0x03, 0xF0, 0x0F, 0x03, 0x02, 0x2B, 0x02, 0xD0, 0x09, 0xB0, 0x5D, 0xF8, ++0x04, 0xFB, 0x01, 0xA8, 0x0E, 0xF0, 0x8C, 0xFF, 0x09, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x00, 0xBF, 0xB0, 0x10, 0x34, 0x40, ++0xB4, 0x10, 0x34, 0x40, 0x38, 0xB5, 0xD0, 0xF8, 0xFC, 0x31, 0x04, 0x46, 0x00, 0xF5, 0xFE, 0x75, 0x4B, 0xB1, 0x28, 0x46, ++0x0D, 0xF0, 0xDE, 0xFA, 0x01, 0x21, 0xFA, 0xF7, 0x2B, 0xF9, 0xD4, 0xF8, 0xFC, 0x31, 0x00, 0x2B, 0xF5, 0xD1, 0x4F, 0xF4, ++0x1E, 0x72, 0x00, 0x21, 0x20, 0x46, 0xEA, 0xF7, 0xF9, 0xF9, 0x23, 0x46, 0x04, 0xF1, 0x48, 0x01, 0x21, 0x22, 0x83, 0xF8, ++0xA4, 0x21, 0x83, 0xF8, 0xA5, 0x21, 0x08, 0x33, 0x8B, 0x42, 0xF8, 0xD1, 0xFF, 0x23, 0x84, 0xF8, 0x22, 0x30, 0x38, 0xBD, ++0x2D, 0xE9, 0xF0, 0x43, 0x49, 0x48, 0x4A, 0x4F, 0x83, 0xB0, 0x81, 0x46, 0x0D, 0xF0, 0x72, 0xFA, 0x07, 0xF5, 0x0C, 0x75, ++0x00, 0x26, 0x40, 0xF2, 0x16, 0x38, 0xA5, 0xF5, 0x0C, 0x71, 0x08, 0x46, 0x01, 0x91, 0xFF, 0xF7, 0xC7, 0xFF, 0x01, 0x99, ++0x48, 0x46, 0x0D, 0xF0, 0x67, 0xFA, 0xA5, 0xF1, 0x28, 0x04, 0x20, 0x46, 0x0D, 0xF0, 0x5E, 0xFA, 0x04, 0xF1, 0x28, 0x00, ++0x08, 0x34, 0x0D, 0xF0, 0x59, 0xFA, 0xAC, 0x42, 0xF5, 0xD1, 0x4F, 0x36, 0x46, 0x45, 0x04, 0xF5, 0x1E, 0x75, 0xE4, 0xD1, ++0x38, 0x4D, 0x40, 0xF2, 0x52, 0x48, 0xA5, 0xF1, 0x28, 0x04, 0x20, 0x46, 0x0D, 0xF0, 0x4A, 0xFA, 0x04, 0xF1, 0x28, 0x00, ++0x08, 0x34, 0x0D, 0xF0, 0x45, 0xFA, 0xAC, 0x42, 0xF5, 0xD1, 0x4F, 0x36, 0x46, 0x45, 0x04, 0xF5, 0x1E, 0x75, 0xEE, 0xD1, ++0x2F, 0x48, 0x30, 0x4D, 0x30, 0x4C, 0x00, 0xF1, 0x30, 0x06, 0xFF, 0xF7, 0x97, 0xFF, 0x41, 0xF6, 0xF8, 0x12, 0x4F, 0xF0, ++0x00, 0x08, 0x41, 0xF6, 0x64, 0x11, 0x41, 0xF6, 0xD0, 0x03, 0xBD, 0x50, 0x06, 0xF5, 0x12, 0x70, 0x86, 0xF8, 0x00, 0x80, ++0x4F, 0xF0, 0x20, 0x62, 0x7C, 0x50, 0xFA, 0x50, 0xFF, 0xF7, 0x84, 0xFF, 0x41, 0xF6, 0x58, 0x30, 0x41, 0xF6, 0x70, 0x41, ++0x07, 0xF8, 0x00, 0x80, 0x41, 0xF6, 0xDC, 0x32, 0x05, 0xF1, 0x40, 0x00, 0x78, 0x50, 0x41, 0xF6, 0x48, 0x33, 0x04, 0xF5, ++0xA4, 0x61, 0xB9, 0x50, 0x06, 0xF5, 0x98, 0x60, 0x1C, 0x4A, 0xFA, 0x50, 0xFF, 0xF7, 0x6E, 0xFF, 0x41, 0xF6, 0xD0, 0x52, ++0x41, 0xF6, 0xE8, 0x61, 0x41, 0xF6, 0x54, 0x63, 0x18, 0x48, 0x07, 0xF8, 0x02, 0x80, 0xC6, 0xF8, 0xE0, 0x04, 0x04, 0xF5, ++0x24, 0x62, 0x06, 0xF5, 0xE7, 0x60, 0x05, 0xF1, 0x80, 0x06, 0x7E, 0x50, 0xFA, 0x50, 0xFF, 0xF7, 0x59, 0xFF, 0x42, 0xF2, ++0x60, 0x16, 0x11, 0x4A, 0x42, 0xF2, 0xCC, 0x00, 0x42, 0xF2, 0x48, 0x01, 0x42, 0xF2, 0x38, 0x03, 0xC0, 0x35, 0x04, 0xF5, ++0x76, 0x64, 0xBD, 0x51, 0x3C, 0x50, 0x07, 0xF8, 0x01, 0x80, 0xFA, 0x50, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x00, 0xBF, ++0xF8, 0x87, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x48, 0x80, 0x17, 0x00, 0x18, 0x7E, 0x17, 0x00, 0x04, 0x38, 0x18, 0x00, ++0xC0, 0x8C, 0x17, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x02, 0x0C, 0x00, 0x00, 0x03, 0x0D, 0x2D, 0xE9, 0xF0, 0x41, ++0x05, 0x46, 0x79, 0x48, 0x95, 0xF8, 0x19, 0x80, 0x0E, 0x46, 0x0D, 0xF0, 0x11, 0xFA, 0x00, 0x28, 0x00, 0xF0, 0xE1, 0x80, ++0x6B, 0x7F, 0x04, 0x46, 0x00, 0x2B, 0x40, 0xF0, 0xA5, 0x80, 0x73, 0x4F, 0x05, 0xF1, 0x12, 0x02, 0x11, 0x68, 0x2B, 0x68, ++0x92, 0x88, 0x62, 0x85, 0xC4, 0xF8, 0x26, 0x10, 0x63, 0x60, 0x28, 0x7E, 0x6E, 0x4B, 0x6F, 0x4A, 0x6F, 0x49, 0x10, 0x28, ++0x38, 0xBF, 0x10, 0x20, 0x20, 0x77, 0x28, 0x8A, 0xA0, 0x82, 0xA8, 0x68, 0x20, 0x61, 0x68, 0x68, 0xE0, 0x60, 0xE8, 0x68, ++0xA0, 0x61, 0xE0, 0x1B, 0xC0, 0x10, 0x03, 0xFB, 0x00, 0xF3, 0xDB, 0xB2, 0x68, 0x7E, 0x84, 0xF8, 0x22, 0x00, 0x33, 0x70, ++0x4F, 0xF4, 0x80, 0x70, 0x84, 0xF8, 0x23, 0x30, 0x0E, 0xF0, 0xC6, 0xFB, 0x62, 0x48, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x08, 0x03, 0x4F, 0xF4, 0xC8, 0x31, 0x93, 0xF8, 0xC0, 0x24, 0xA1, 0x60, 0x22, 0xB1, 0x93, 0xF8, 0xC2, 0x24, 0x01, 0x32, ++0x83, 0xF8, 0xC2, 0x24, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xF8, 0xE8, 0x11, 0x04, 0xF5, 0xF4, 0x72, 0x23, 0x46, 0x04, 0xF5, ++0xFD, 0x75, 0x22, 0xF8, 0x02, 0x1F, 0xAA, 0x42, 0xFB, 0xD1, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x08, 0xF8, 0x00, 0xEB, ++0x08, 0x05, 0x00, 0x22, 0x31, 0x78, 0x84, 0xF8, 0x30, 0x20, 0xD5, 0xF8, 0xB0, 0x54, 0x4F, 0x4A, 0x02, 0xEB, 0x81, 0x12, ++0x29, 0x07, 0xC4, 0xF8, 0x48, 0x21, 0x4D, 0x49, 0x56, 0xBF, 0x08, 0xF5, 0x95, 0x62, 0x04, 0xF1, 0xB0, 0x02, 0x12, 0x18, ++0xC4, 0xF8, 0xB4, 0x20, 0x0A, 0x69, 0xA2, 0xF5, 0x74, 0x22, 0xA2, 0xF5, 0x10, 0x72, 0x04, 0xF1, 0x48, 0x01, 0xC3, 0xF8, ++0xA0, 0x21, 0x08, 0x33, 0x8B, 0x42, 0xFA, 0xD1, 0xEA, 0x06, 0x03, 0xD5, 0x63, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x63, 0x60, ++0x08, 0xF1, 0xE4, 0x08, 0x40, 0x44, 0x21, 0x46, 0x0D, 0xF0, 0x4C, 0xF9, 0x3D, 0x4B, 0xC4, 0xF8, 0x04, 0x32, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x3A, 0x4B, 0xE0, 0x6A, 0x1A, 0x68, ++0x01, 0x25, 0x51, 0x19, 0x19, 0x60, 0x84, 0xF8, 0x25, 0x50, 0x08, 0xB1, 0x80, 0xF8, 0x25, 0x50, 0x21, 0xB1, 0x33, 0x49, ++0x1A, 0x60, 0x0B, 0x68, 0x00, 0x2A, 0x42, 0xD0, 0xF6, 0xB2, 0x0D, 0x2E, 0x07, 0xD8, 0x4F, 0xF4, 0x1E, 0x73, 0x2C, 0x4A, ++0x06, 0xFB, 0x03, 0x76, 0x13, 0x69, 0xC6, 0xF8, 0x58, 0x32, 0x00, 0x20, 0x84, 0xF8, 0x5C, 0x02, 0xBD, 0xE8, 0xF0, 0x81, ++0x1F, 0x48, 0x0D, 0xF0, 0x61, 0xF9, 0x00, 0x28, 0x34, 0xD0, 0x2A, 0x46, 0xE0, 0x62, 0xC4, 0x62, 0xA9, 0x7F, 0x52, 0xF8, ++0x12, 0x3F, 0x95, 0xF8, 0x1D, 0xC0, 0xC0, 0xF8, 0x26, 0x30, 0x01, 0x23, 0x8B, 0x40, 0x91, 0x88, 0x41, 0x85, 0x01, 0x3B, ++0x41, 0x8D, 0x16, 0x4F, 0x1B, 0x02, 0x1B, 0xB2, 0x21, 0xEA, 0x03, 0x01, 0x09, 0xB2, 0x41, 0x85, 0xB5, 0xF8, 0x16, 0xE0, ++0xAE, 0xEB, 0x0C, 0x2C, 0x03, 0xEA, 0x0C, 0x03, 0xA0, 0xEB, 0x07, 0x0E, 0xDF, 0xF8, 0x3C, 0xC0, 0x4F, 0xEA, 0xEE, 0x0E, ++0x0B, 0x43, 0x0C, 0xFB, 0x0E, 0xF1, 0x4F, 0xF0, 0xFF, 0x0C, 0x43, 0x85, 0x80, 0xF8, 0x23, 0x10, 0xA0, 0xF8, 0x20, 0xC0, ++0x2A, 0xE7, 0x00, 0x2B, 0xBA, 0xD0, 0x62, 0xB6, 0xB8, 0xE7, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x48, 0x21, 0x46, ++0x0D, 0xF0, 0xE2, 0xF8, 0x01, 0x20, 0xBD, 0xE7, 0xF8, 0x87, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xAF, 0x16, 0x37, 0x61, ++0xEC, 0x97, 0x15, 0x00, 0xDC, 0x97, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x04, 0x39, 0x18, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x0F, 0xCC, 0xFF, 0xFF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x33, 0x4F, 0xDF, 0xF8, ++0xE4, 0x80, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x74, 0x4F, 0xF4, 0xA4, 0x63, 0x94, 0xF8, 0x22, 0x60, 0x03, 0xFB, ++0x06, 0x83, 0x05, 0x46, 0x93, 0xF8, 0xC0, 0x24, 0x22, 0xB1, 0x93, 0xF8, 0xC2, 0x24, 0x01, 0x3A, 0x83, 0xF8, 0xC2, 0x24, ++0x29, 0x4A, 0x2A, 0x49, 0x2B, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0E, 0xF0, 0xD5, 0xFA, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, ++0x06, 0x80, 0xE4, 0x30, 0x21, 0x46, 0x0D, 0xF0, 0xF3, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x21, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x21, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x73, 0x11, 0x68, 0xD8, 0x6A, ++0x4E, 0x1C, 0x4F, 0xF0, 0x00, 0x0C, 0x16, 0x60, 0x83, 0xF8, 0x25, 0xC0, 0xD8, 0xB1, 0x80, 0xF8, 0x25, 0xC0, 0x96, 0xB9, ++0xFF, 0xF7, 0xE4, 0xFD, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x75, 0x16, 0x48, 0xE9, 0x6A, 0x0D, 0xF0, 0x80, 0xF8, ++0x20, 0x46, 0xFF, 0xF7, 0xD9, 0xFD, 0x21, 0x46, 0x12, 0x48, 0xBD, 0xE8, 0xF0, 0x41, 0x0D, 0xF0, 0x77, 0xB8, 0x0E, 0x48, ++0x11, 0x60, 0x02, 0x68, 0x41, 0xB1, 0xD8, 0x6A, 0xE6, 0xE7, 0x00, 0x2E, 0xEE, 0xD0, 0x0A, 0x4B, 0x11, 0x60, 0x1A, 0x68, ++0x00, 0x29, 0xE9, 0xD1, 0x02, 0xB1, 0x62, 0xB6, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x73, 0xD8, 0x6A, 0x00, 0x28, ++0xE0, 0xD0, 0xD5, 0xE7, 0x68, 0x65, 0x17, 0x00, 0x00, 0x98, 0x15, 0x00, 0xDC, 0x97, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xF8, 0x87, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x44, 0x78, 0xDF, 0xF8, ++0x14, 0x81, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0xF6, 0x08, 0xEB, 0x06, 0x07, 0x38, 0x36, 0x87, 0xF8, 0x9A, 0x10, ++0x90, 0xF8, 0x28, 0x30, 0x87, 0xF8, 0x98, 0x30, 0x03, 0x78, 0x87, 0xF8, 0x99, 0x30, 0x46, 0x44, 0x05, 0x46, 0x48, 0x22, ++0x30, 0x46, 0x00, 0x21, 0x97, 0xF8, 0x22, 0x90, 0xE9, 0xF7, 0xA0, 0xFF, 0x97, 0xF8, 0x98, 0x30, 0x04, 0x2B, 0x55, 0xD8, ++0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x3F, 0x54, 0x03, 0x27, 0x00, 0x21, 0xF0, 0x29, 0xF8, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x04, 0x83, 0x03, 0xF1, 0x80, 0x02, 0x20, 0xF0, 0x7F, 0x40, 0xC3, 0xF8, 0x80, 0x00, 0x00, 0x23, 0x53, 0x60, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, 0x01, 0x22, 0xD5, 0xE9, 0x02, 0x40, 0x29, 0x69, 0x83, 0xF8, 0x9B, 0x20, 0x6A, 0x69, ++0xC3, 0xF8, 0xB0, 0x60, 0xC3, 0xE9, 0x27, 0x40, 0xC3, 0xE9, 0x29, 0x12, 0x2A, 0x79, 0x83, 0xF8, 0xAC, 0x20, 0xBD, 0xE8, ++0xF8, 0x83, 0x20, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x39, 0x19, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x99, 0xF8, ++0x62, 0x00, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x04, 0x81, 0x02, 0x28, 0xC1, 0xE9, 0x20, 0x23, 0xD7, 0xD1, 0x15, 0xA3, ++0xD3, 0xE9, 0x00, 0x23, 0xC1, 0xE9, 0x20, 0x23, 0xD1, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, 0xAA, 0x69, ++0xC3, 0xF8, 0x88, 0x20, 0xEA, 0x69, 0xC3, 0xF8, 0x8C, 0x20, 0x2A, 0x6A, 0xC3, 0xF8, 0x90, 0x20, 0x00, 0x20, 0x6A, 0x6A, ++0xC3, 0xF8, 0x94, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x20, 0x01, 0xBC, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, ++0x00, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x20, 0x01, 0xB3, 0xE7, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, 0x36, 0x5C, 0x36, 0x5C, ++0x36, 0x5C, 0x36, 0x5C, 0x37, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x23, 0x01, 0x22, 0x80, 0xF8, 0x30, 0x20, 0x80, 0xF8, 0x9B, 0x30, 0xC0, 0xF8, 0xB0, 0x30, 0x70, 0x47, 0x00, 0xBF, ++0x2D, 0xE9, 0xF0, 0x47, 0xD1, 0xF8, 0xFC, 0xA1, 0x82, 0xB0, 0xBA, 0xF1, 0x00, 0x0F, 0x32, 0xD0, 0x00, 0x24, 0xDF, 0xF8, ++0x6C, 0x80, 0x0D, 0x46, 0x06, 0x46, 0x91, 0x46, 0x27, 0x46, 0x10, 0xE0, 0x80, 0xF8, 0x5D, 0x70, 0xD8, 0xF8, 0x98, 0x33, ++0xC1, 0x7E, 0x01, 0x34, 0x98, 0x47, 0xB9, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x4C, 0x45, 0x1F, 0xD0, 0xD5, 0xF8, 0xFC, 0xA1, ++0xBA, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x30, 0x46, 0x01, 0x97, 0xF8, 0xF7, 0x6B, 0xFA, 0x03, 0x46, 0x50, 0x46, 0x9B, 0xB1, ++0x15, 0xF0, 0x34, 0xFC, 0x03, 0x46, 0x01, 0xAA, 0x29, 0x46, 0x30, 0x46, 0x63, 0xB1, 0xD8, 0xF8, 0x10, 0x30, 0x98, 0x47, ++0x01, 0x9B, 0x3B, 0xB9, 0x00, 0x28, 0xD9, 0xD1, 0x05, 0xF5, 0xFE, 0x70, 0x0C, 0xF0, 0xC2, 0xFF, 0xD4, 0xE7, 0x54, 0x46, ++0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x88, 0x1A, 0x17, 0x00, 0x0A, 0x4B, 0x9B, 0x68, 0x93, 0xF8, 0x62, 0x20, ++0x7A, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x62, 0xB1, 0x93, 0xF8, 0x6D, 0x20, 0x4A, 0xB1, 0x93, 0xF8, 0x6E, 0x20, 0x08, 0x2A, ++0x05, 0xD8, 0x01, 0x23, 0x93, 0x40, 0x01, 0x3B, 0x02, 0x4A, 0x1B, 0x02, 0x13, 0x60, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, ++0x2C, 0x00, 0x32, 0x40, 0x10, 0xB5, 0x90, 0xF8, 0xC0, 0x34, 0x04, 0x46, 0x00, 0x2B, 0x2D, 0xD1, 0x23, 0x6C, 0x1B, 0xB1, ++0x1B, 0x4B, 0x20, 0x46, 0x1B, 0x6B, 0x98, 0x47, 0x63, 0x68, 0xD8, 0x07, 0x1A, 0xD5, 0x19, 0x4A, 0x11, 0x68, 0x89, 0x01, ++0x17, 0xD5, 0x23, 0xF0, 0x01, 0x03, 0x63, 0x60, 0x16, 0x4A, 0x41, 0xF2, 0x14, 0x33, 0xD3, 0x5C, 0x01, 0x2B, 0x41, 0xF2, ++0x13, 0x33, 0x8C, 0xBF, 0x01, 0x21, 0x00, 0x21, 0xD1, 0x54, 0x12, 0x4B, 0x93, 0xF8, 0xB6, 0x30, 0x23, 0xB1, 0x11, 0x4B, ++0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x0C, 0xD0, 0x10, 0xBD, 0x12, 0x68, 0x92, 0x01, 0xFB, 0xD4, 0x0D, 0x4A, 0x92, 0xF8, ++0x24, 0x20, 0x00, 0x2A, 0xF6, 0xD0, 0xDE, 0xE7, 0x0A, 0xF0, 0x34, 0xF8, 0xCE, 0xE7, 0xF8, 0xF7, 0x1D, 0xFD, 0x09, 0x4A, ++0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, ++0x00, 0x40, 0x1E, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, ++0x19, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x18, 0x22, 0x80, 0x46, 0x00, 0x21, 0xE9, 0xF7, 0x72, 0xFE, 0x40, 0x46, 0x0C, 0xF0, ++0xFF, 0xFE, 0x08, 0xF1, 0x08, 0x00, 0x14, 0x4C, 0x14, 0x4F, 0x0C, 0xF0, 0xF9, 0xFE, 0x04, 0xF5, 0xA4, 0x56, 0x45, 0x46, ++0x4F, 0xF4, 0xA4, 0x62, 0x00, 0x21, 0x20, 0x46, 0xE9, 0xF7, 0x60, 0xFE, 0x7F, 0x23, 0xD7, 0xF8, 0x50, 0x24, 0x24, 0x63, ++0x05, 0x21, 0x84, 0xF8, 0x62, 0x10, 0x84, 0xF8, 0x65, 0x30, 0x84, 0xF8, 0x66, 0x30, 0xE2, 0x62, 0x21, 0x46, 0x28, 0x46, ++0x04, 0xF5, 0xA4, 0x64, 0x0C, 0xF0, 0xE2, 0xFE, 0xB4, 0x42, 0xE5, 0xD1, 0xFF, 0x23, 0x88, 0xF8, 0x10, 0x30, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x06, 0x4B, ++0x9C, 0x68, 0x3C, 0xB1, 0x05, 0x4D, 0xD5, 0xF8, 0x5C, 0x34, 0x20, 0x46, 0x98, 0x47, 0x24, 0x68, 0x00, 0x2C, 0xF8, 0xD1, ++0x38, 0xBD, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAC, 0x4D, 0x8D, 0xB0, ++0x2C, 0x68, 0x05, 0x90, 0x88, 0x46, 0x17, 0x46, 0x04, 0x93, 0x00, 0x2C, 0x00, 0xF0, 0xA4, 0x80, 0x00, 0x2A, 0x40, 0xF0, ++0x9E, 0x80, 0xAC, 0x68, 0x00, 0x2C, 0x00, 0xF0, 0x42, 0x81, 0x05, 0x9B, 0xA4, 0x48, 0x1A, 0x68, 0x9B, 0x88, 0x06, 0x92, ++0x4F, 0xF0, 0x00, 0x09, 0x07, 0x93, 0xCB, 0x46, 0xBA, 0x46, 0xE7, 0x6D, 0xB4, 0xF8, 0x60, 0x60, 0x94, 0xF8, 0xC0, 0x34, ++0x39, 0x46, 0x32, 0x46, 0x0E, 0xF0, 0x76, 0xF8, 0x94, 0xF8, 0xC0, 0x34, 0x9A, 0x48, 0x1B, 0xB9, 0x8B, 0xEA, 0x07, 0x0B, ++0x89, 0xEA, 0x06, 0x09, 0x24, 0x68, 0x00, 0x2C, 0xEB, 0xD1, 0x57, 0x46, 0x00, 0x2F, 0x00, 0xF0, 0x99, 0x80, 0x95, 0x4B, ++0x95, 0x48, 0x49, 0xF4, 0x40, 0x74, 0xDD, 0xE9, 0x06, 0x12, 0x1C, 0x60, 0xC0, 0xF8, 0x00, 0xB0, 0x5B, 0x46, 0xCD, 0xE9, ++0x00, 0x97, 0x91, 0x48, 0x0E, 0xF0, 0x58, 0xF8, 0x8B, 0x48, 0x0C, 0xF0, 0xBF, 0xFE, 0x05, 0x99, 0x8E, 0x4A, 0x80, 0xF8, ++0x62, 0x80, 0x04, 0x46, 0x8D, 0x4B, 0x82, 0x1A, 0x08, 0x68, 0xE0, 0x65, 0x52, 0x11, 0x89, 0x88, 0xA4, 0xF8, 0x60, 0x10, ++0x03, 0xFB, 0x02, 0xF2, 0xD3, 0xB2, 0x40, 0xF6, 0x47, 0x21, 0x40, 0xF6, 0x43, 0x22, 0xA1, 0x60, 0xE2, 0x60, 0x86, 0x49, ++0x86, 0x4A, 0x21, 0x61, 0x62, 0x61, 0x40, 0xF2, 0xFF, 0x31, 0x00, 0x22, 0x84, 0xF8, 0xC0, 0x74, 0xA4, 0xF8, 0xBE, 0x14, ++0x84, 0xF8, 0x63, 0x30, 0x84, 0xF8, 0x4C, 0x30, 0x22, 0x64, 0x84, 0xF8, 0x84, 0x20, 0x17, 0xB1, 0xEA, 0x7C, 0x01, 0x32, ++0xEA, 0x74, 0xB8, 0xF1, 0x02, 0x0F, 0x00, 0xF0, 0x89, 0x80, 0xB8, 0xF1, 0x04, 0x0F, 0x00, 0xF0, 0xC3, 0x80, 0xB8, 0xF1, ++0x00, 0x0F, 0x00, 0xF0, 0x9C, 0x80, 0x6B, 0x7C, 0xAA, 0x7C, 0x13, 0x44, 0x01, 0x2B, 0x78, 0xDD, 0x74, 0x48, 0x75, 0x4E, ++0xD0, 0xE9, 0x00, 0x12, 0x42, 0xF4, 0x80, 0x72, 0x11, 0x43, 0x42, 0x60, 0x31, 0x60, 0x01, 0x2B, 0x4D, 0xD0, 0x00, 0x2F, ++0x52, 0xD1, 0x04, 0x9A, 0x94, 0xF8, 0x63, 0x30, 0x6E, 0x48, 0x13, 0x70, 0x21, 0x46, 0x0C, 0xF0, 0x29, 0xFE, 0x04, 0xF5, ++0x99, 0x66, 0x04, 0xF5, 0x9E, 0x69, 0x30, 0x46, 0x0C, 0xF0, 0x1E, 0xFE, 0x06, 0xF1, 0x28, 0x00, 0x08, 0x36, 0x0C, 0xF0, ++0x19, 0xFE, 0x4E, 0x45, 0xF5, 0xD1, 0x04, 0xF5, 0xA3, 0x60, 0x0C, 0xF0, 0x13, 0xFE, 0x00, 0x24, 0x03, 0xE0, 0x63, 0x4B, ++0x1B, 0x78, 0x23, 0xB3, 0x01, 0x24, 0xAA, 0x7C, 0x6B, 0x7C, 0x61, 0x49, 0x13, 0x44, 0x00, 0x20, 0x01, 0x2B, 0x08, 0x60, ++0x04, 0xDC, 0xFF, 0xF7, 0x91, 0xFE, 0xAA, 0x7C, 0x6B, 0x7C, 0x13, 0x44, 0x04, 0x99, 0x09, 0x78, 0x4F, 0xF4, 0x80, 0x70, ++0xCD, 0xE9, 0x02, 0x71, 0xCD, 0xE9, 0x00, 0x28, 0x58, 0x49, 0x59, 0x4A, 0x0E, 0xF0, 0x22, 0xF8, 0x20, 0x46, 0x0D, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x9B, 0x8B, 0xEA, 0x03, 0x0B, 0x07, 0x9B, 0x89, 0xEA, 0x03, 0x09, 0x5F, 0xE7, 0xAC, 0x68, ++0x00, 0x2C, 0x7C, 0xD0, 0xEB, 0x7C, 0x02, 0x2B, 0x7F, 0xF4, 0x37, 0xAF, 0xD2, 0xE7, 0x4F, 0x4A, 0x13, 0x68, 0x43, 0xF0, ++0x01, 0x03, 0x13, 0x60, 0x00, 0x2F, 0xAC, 0xD0, 0xB8, 0xF1, 0x00, 0x01, 0x18, 0xBF, 0x01, 0x21, 0x94, 0xF8, 0x63, 0x00, ++0x09, 0xF0, 0x22, 0xFD, 0x48, 0x4B, 0x84, 0xF8, 0xC1, 0x04, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x9C, 0xDA, ++0xFF, 0x28, 0x9A, 0xD1, 0x44, 0x49, 0x45, 0x48, 0x40, 0xF2, 0x0B, 0x22, 0x0E, 0xF0, 0x1A, 0xFA, 0x93, 0xE7, 0x00, 0x2A, ++0x8D, 0xD0, 0x83, 0xE7, 0xAA, 0x7C, 0x00, 0x2A, 0x00, 0xF0, 0xA8, 0x80, 0x39, 0x46, 0x3F, 0x48, 0x0A, 0x33, 0x4F, 0xF4, ++0x1E, 0x76, 0x06, 0xFB, 0x03, 0x03, 0x01, 0x32, 0x01, 0x20, 0xAA, 0x74, 0x83, 0xF8, 0x25, 0x00, 0x11, 0xB1, 0x3A, 0x4B, ++0xC4, 0xE9, 0x07, 0x34, 0x39, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x80, 0x31, 0x98, 0x47, 0x6B, 0x7C, 0x64, 0xE7, 0x36, 0x4B, ++0x36, 0x49, 0xD3, 0xF8, 0xCC, 0x31, 0xE3, 0x61, 0xFF, 0x23, 0x84, 0xF8, 0x6C, 0x30, 0x34, 0x4A, 0x6B, 0x7C, 0x24, 0x62, ++0xA4, 0xF8, 0x8A, 0x80, 0xC4, 0xF8, 0xB8, 0x40, 0xC4, 0xF8, 0xB4, 0x10, 0x01, 0x33, 0x92, 0xF8, 0x04, 0x21, 0xDB, 0xB2, ++0x6B, 0x74, 0x00, 0x2A, 0x3F, 0xF4, 0x4C, 0xAF, 0x2C, 0x4A, 0xC4, 0xF8, 0xA4, 0x40, 0xC4, 0xE9, 0x24, 0x88, 0xC4, 0xF8, ++0x98, 0x80, 0xC4, 0xF8, 0xA0, 0x20, 0x41, 0xE7, 0x2A, 0x7C, 0xFF, 0x2A, 0x17, 0xD1, 0xAA, 0x68, 0x2B, 0x74, 0x00, 0x2A, ++0x4C, 0xD0, 0x14, 0x49, 0x24, 0x4B, 0x4E, 0x68, 0x12, 0x6C, 0x13, 0x48, 0x0B, 0x60, 0x33, 0x43, 0x03, 0x60, 0x00, 0x2A, ++0x3F, 0xF4, 0x2F, 0xAF, 0x1B, 0x4B, 0x10, 0x7E, 0x1B, 0x6D, 0x98, 0x47, 0x29, 0xE7, 0x05, 0x98, 0x01, 0xF0, 0x4E, 0xFE, ++0xEA, 0xE6, 0x01, 0x24, 0x6E, 0xE7, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x14, 0x98, 0x15, 0x00, 0x1C, 0x00, 0x32, 0x40, ++0x18, 0x00, 0x32, 0x40, 0x2C, 0x98, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x19, 0x9C, 0x8F, 0xC1, 0x32, 0xE4, 0x05, 0x00, ++0x22, 0xF3, 0x02, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0x08, 0x88, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, ++0x2C, 0x00, 0x32, 0x40, 0x74, 0x98, 0x15, 0x00, 0xC8, 0x98, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x50, 0x98, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0xB1, 0x7F, 0x13, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xD5, 0x65, 0x12, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x81, 0x66, 0x12, 0x00, 0xDC, 0xFF, 0xFF, 0x7F, 0x10, 0x4E, 0x11, 0x4A, ++0x09, 0x92, 0x40, 0xF6, 0x85, 0x12, 0xD6, 0xF8, 0xE8, 0x30, 0x0A, 0x92, 0x98, 0x47, 0x73, 0x6C, 0x0D, 0xF1, 0x23, 0x01, ++0x09, 0xA8, 0x98, 0x47, 0x00, 0x28, 0xB6, 0xD1, 0x63, 0x68, 0x32, 0x6D, 0x9D, 0xF8, 0x23, 0x00, 0x43, 0xF0, 0x80, 0x03, ++0x63, 0x60, 0x90, 0x47, 0x6B, 0x7C, 0xD3, 0xE6, 0x01, 0xF0, 0x32, 0xFE, 0xAA, 0x7C, 0x94, 0xF8, 0x63, 0x30, 0x94, 0xF8, ++0xC0, 0x14, 0x50, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x00, 0x85, 0x09, 0x2D, 0xE9, 0xF0, 0x4F, 0x02, 0x46, 0x6A, 0x4D, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xF3, 0x8B, 0xB0, 0xEF, 0x18, 0x04, 0x90, 0x39, 0x46, 0x66, 0x48, 0x06, 0x93, ++0x0C, 0xF0, 0x4A, 0xFD, 0x97, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xDD, 0x80, 0x04, 0x2B, 0x00, 0xF0, 0x98, 0x80, ++0xDF, 0xF8, 0x98, 0xA1, 0x60, 0x4C, 0x00, 0x2B, 0x00, 0xF0, 0x89, 0x80, 0x9A, 0xF8, 0x12, 0x30, 0x9A, 0xF8, 0x11, 0x20, ++0x1A, 0x44, 0x01, 0x2A, 0x5E, 0xD0, 0x0A, 0xB9, 0x5B, 0x4B, 0x1A, 0x60, 0x06, 0x9E, 0xD4, 0xF8, 0xD8, 0x31, 0x06, 0xF1, ++0x18, 0x00, 0x28, 0x44, 0x98, 0x47, 0x06, 0xF1, 0x28, 0x00, 0xD4, 0xF8, 0xD8, 0x31, 0x28, 0x44, 0x98, 0x47, 0x04, 0x9A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0x93, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0x3A, 0xD1, 0x04, 0x9A, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0x05, 0x26, 0x93, 0xF8, 0x63, 0x00, 0x0A, 0xF0, 0x02, 0xFA, 0x4B, 0x4B, 0x1A, 0x69, ++0xBA, 0x42, 0x04, 0xBF, 0x00, 0x22, 0x1A, 0x61, 0x00, 0x21, 0x4F, 0xF4, 0xA4, 0x62, 0x38, 0x46, 0xE9, 0xF7, 0x22, 0xFC, ++0x04, 0x99, 0x9A, 0xF8, 0x11, 0x20, 0x9A, 0xF8, 0x12, 0x30, 0xD4, 0xF8, 0x50, 0xC4, 0x01, 0x91, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x01, 0x55, 0x7F, 0x24, 0x00, 0x93, 0x3F, 0x49, 0xC5, 0xF8, 0x2C, 0xC0, 0x13, 0x44, 0x4F, 0xF4, 0x80, 0x70, ++0x3D, 0x4A, 0x2F, 0x63, 0x85, 0xF8, 0x62, 0x60, 0x85, 0xF8, 0x65, 0x40, 0x85, 0xF8, 0x66, 0x40, 0x0D, 0xF0, 0xC2, 0xFE, ++0x39, 0x48, 0x39, 0x46, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x0C, 0xF0, 0x91, 0xBC, 0x93, 0xF8, 0xC1, 0x04, 0x01, 0x21, ++0x09, 0xF0, 0x2E, 0xFC, 0x9A, 0xF8, 0x13, 0x30, 0x01, 0x3B, 0x8A, 0xF8, 0x13, 0x30, 0xB9, 0xE7, 0x31, 0x4A, 0xDA, 0xF8, ++0x08, 0x60, 0xDF, 0xF8, 0xC8, 0xE0, 0xDF, 0xF8, 0xC8, 0x90, 0xDF, 0xF8, 0xC8, 0x80, 0xD2, 0xE9, 0x00, 0x01, 0x21, 0xF0, ++0x10, 0x0C, 0x4C, 0xEA, 0x00, 0x00, 0xC2, 0xF8, 0x04, 0xC0, 0xCE, 0xF8, 0x00, 0x00, 0xB0, 0x6B, 0xB6, 0x8F, 0xC9, 0xF8, ++0x00, 0x00, 0xC8, 0xF8, 0x00, 0x60, 0x00, 0x2B, 0x88, 0xD1, 0x13, 0x68, 0x21, 0xF4, 0x88, 0x71, 0x0B, 0x43, 0x51, 0x60, ++0xCE, 0xF8, 0x00, 0x30, 0x80, 0xE7, 0x9A, 0xF8, 0x11, 0x20, 0x9A, 0xF8, 0x12, 0x30, 0x01, 0x3A, 0xD2, 0xB2, 0x8A, 0xF8, ++0x11, 0x20, 0x71, 0xE7, 0xEA, 0xF7, 0x50, 0xFC, 0x00, 0x28, 0x40, 0xF0, 0x28, 0x81, 0xDF, 0xF8, 0x60, 0xA0, 0x12, 0x4C, ++0x9A, 0xF8, 0x10, 0x00, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x53, 0x5A, 0x68, 0x19, 0x6C, 0x22, 0xF0, 0x80, 0x02, ++0x5A, 0x60, 0x09, 0xB1, 0x63, 0x6D, 0x98, 0x47, 0x9A, 0xF8, 0x12, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x0D, 0x81, 0x0E, 0x48, ++0x0E, 0x49, 0x42, 0x68, 0x0E, 0x4E, 0x01, 0x60, 0x0A, 0x43, 0x32, 0x60, 0xFF, 0x21, 0x9A, 0xF8, 0x11, 0x20, 0x8A, 0xF8, ++0x10, 0x10, 0x49, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x08, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, ++0x94, 0x64, 0x17, 0x00, 0xB8, 0x98, 0x15, 0x00, 0xDC, 0x98, 0x15, 0x00, 0x00, 0x88, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x8C, 0x84, 0x03, 0x35, 0x60, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x04, 0x9E, 0xDF, 0xF8, ++0x28, 0xA2, 0x7F, 0x49, 0x9A, 0xF8, 0x12, 0x20, 0x7E, 0x4C, 0xDF, 0xF8, 0x20, 0xB2, 0x06, 0xF1, 0x0A, 0x08, 0x08, 0xEB, ++0x88, 0x03, 0x4F, 0xF4, 0x1E, 0x70, 0xC8, 0xEB, 0x03, 0x13, 0x4F, 0xF0, 0xA4, 0x0C, 0x00, 0xFB, 0x08, 0x18, 0x46, 0x33, ++0x9E, 0x20, 0xCD, 0xE9, 0x08, 0x7A, 0x1C, 0xFB, 0x06, 0x06, 0x01, 0x3A, 0x00, 0x20, 0x01, 0xEB, 0xC3, 0x03, 0x03, 0x93, ++0x8A, 0xF8, 0x12, 0x20, 0x88, 0xF8, 0x25, 0x00, 0x05, 0x90, 0x05, 0xEB, 0xC6, 0x06, 0xB9, 0x46, 0xD8, 0xF8, 0x08, 0x32, ++0x9D, 0xF8, 0x14, 0x70, 0x3B, 0xB1, 0x03, 0x99, 0xD4, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x28, 0x39, 0x38, 0x46, ++0x98, 0x47, 0xD8, 0xF8, 0x30, 0x32, 0x33, 0xB1, 0xD4, 0xF8, 0x84, 0x33, 0x03, 0x99, 0x4F, 0xF0, 0x80, 0x42, 0x38, 0x46, ++0x98, 0x47, 0xD9, 0xF8, 0xF0, 0x34, 0x00, 0x2B, 0x00, 0xF0, 0x93, 0x80, 0x30, 0x46, 0x0C, 0xF0, 0x55, 0xFC, 0xA6, 0xF1, ++0x28, 0x0A, 0x07, 0x90, 0x50, 0x46, 0x0C, 0xF0, 0x4F, 0xFC, 0x07, 0x99, 0x02, 0x46, 0x5B, 0x48, 0x0D, 0xF0, 0xA0, 0xFD, ++0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x58, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xDB, 0xF8, 0x00, 0x20, ++0xD4, 0xF8, 0x84, 0x33, 0x01, 0x32, 0xCB, 0xF8, 0x00, 0x20, 0x31, 0x46, 0x4F, 0xF0, 0x80, 0x42, 0x38, 0x46, 0x98, 0x47, ++0xD4, 0xF8, 0x84, 0x33, 0x51, 0x46, 0x38, 0x46, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, ++0x4B, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x00, 0x2A, 0x66, 0xD1, 0x05, 0x9B, 0x03, 0x9A, ++0x01, 0x33, 0x08, 0x32, 0x05, 0x2B, 0x05, 0x93, 0x08, 0xF1, 0x08, 0x08, 0x06, 0xF1, 0x08, 0x06, 0x09, 0xF1, 0x08, 0x09, ++0x03, 0x92, 0xA1, 0xD1, 0x04, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0xDD, 0xE9, 0x08, 0x7A, 0xD3, 0xF8, ++0x18, 0x35, 0x00, 0x2B, 0x4F, 0xD0, 0x06, 0x9B, 0x03, 0xF5, 0xA3, 0x66, 0x2E, 0x44, 0x30, 0x46, 0x0C, 0xF0, 0x04, 0xFC, ++0x01, 0x46, 0x38, 0x48, 0x0D, 0xF0, 0x56, 0xFD, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x33, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xDB, 0xF8, 0x00, 0x20, 0xD4, 0xF8, 0x84, 0x33, 0x01, 0x32, 0xCB, 0xF8, 0x00, 0x20, 0x31, 0x46, ++0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x2A, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x00, 0x2A, 0x43, 0xD1, 0x9A, 0xF8, 0x12, 0x20, 0x00, 0x2A, 0x3C, 0xD0, 0x9A, 0xF8, ++0x11, 0x30, 0x13, 0x44, 0x01, 0x2B, 0x7F, 0xF4, 0x71, 0xAE, 0x23, 0x49, 0xDA, 0xF8, 0x08, 0x00, 0x22, 0x4E, 0xD1, 0xE9, ++0x00, 0x23, 0x23, 0xF0, 0x10, 0x03, 0x4B, 0x60, 0x1A, 0x43, 0x20, 0x49, 0x20, 0x4B, 0x32, 0x60, 0x86, 0x6B, 0x82, 0x8F, ++0x0E, 0x60, 0x1A, 0x60, 0x5E, 0xE6, 0xD9, 0xF8, 0xC8, 0x34, 0x00, 0x2B, 0x7F, 0xF4, 0x68, 0xAF, 0xA6, 0xF1, 0x28, 0x0A, ++0x72, 0xE7, 0x62, 0xB6, 0x96, 0xE7, 0x06, 0x9B, 0x03, 0xF5, 0xA3, 0x66, 0x2E, 0x44, 0xB5, 0xE7, 0x01, 0xF0, 0x4E, 0xFC, ++0x9A, 0xF8, 0x12, 0x30, 0xF4, 0xE6, 0x00, 0x20, 0xEA, 0xF7, 0x2C, 0xFB, 0x12, 0x4B, 0x1A, 0x68, 0xD2, 0x05, 0x7F, 0xF5, ++0xD0, 0xAE, 0x4F, 0xF4, 0x80, 0x72, 0xC3, 0xF8, 0x80, 0x20, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0xC6, 0xE6, ++0x01, 0xF0, 0x5E, 0xFC, 0x2C, 0xE6, 0x62, 0xB6, 0xB9, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x88, 0x98, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0xA0, 0x98, 0x15, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, ++0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0x88, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x2E, 0x78, 0x95, 0xF8, 0x29, 0x80, 0x4F, 0x4C, 0x00, 0xFB, ++0x08, 0xF0, 0xC6, 0xEB, 0x06, 0x17, 0x00, 0xEB, 0xC7, 0x07, 0x27, 0x44, 0x4F, 0xF0, 0x78, 0x0A, 0x1A, 0xFB, 0x06, 0x0A, ++0x87, 0xF8, 0x3A, 0x12, 0x0A, 0xF5, 0xEC, 0x79, 0x95, 0xF8, 0x28, 0x30, 0x87, 0xF8, 0x38, 0x32, 0xA1, 0x44, 0x87, 0xF8, ++0x39, 0x62, 0x48, 0x46, 0x48, 0x22, 0x00, 0x21, 0xE9, 0xF7, 0x46, 0xFA, 0x97, 0xF8, 0x38, 0x32, 0x37, 0x01, 0x05, 0x2B, ++0x0C, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x41, 0x51, 0x0B, 0x41, 0x6A, 0x03, 0x0A, 0xF5, 0x0A, 0x70, 0x20, 0x44, 0x10, 0x22, ++0x05, 0xF1, 0x08, 0x01, 0x20, 0xF0, 0xC2, 0xF9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, 0xBA, 0x1B, 0x03, 0xEB, ++0xC2, 0x03, 0x23, 0x44, 0x00, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x88, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, ++0xBA, 0x1B, 0x03, 0xEB, 0xC2, 0x02, 0x22, 0x44, 0x23, 0x44, 0x92, 0xF8, 0x38, 0x12, 0x05, 0x29, 0x4F, 0xF0, 0x01, 0x00, ++0x0C, 0xBF, 0xC3, 0xF8, 0xAC, 0x94, 0xC3, 0xF8, 0xA8, 0x94, 0x4F, 0xF4, 0xA4, 0x63, 0x82, 0xF8, 0x3B, 0x02, 0x03, 0xFB, ++0x08, 0xF8, 0xD5, 0xE9, 0x02, 0x01, 0xD5, 0xE9, 0x04, 0x23, 0xBF, 0x1B, 0x08, 0xEB, 0xC7, 0x07, 0x3C, 0x44, 0xC4, 0xE9, ++0x8F, 0x01, 0xC4, 0xE9, 0x91, 0x23, 0x2B, 0x79, 0x84, 0xF8, 0x4C, 0x32, 0xBD, 0xE8, 0xF0, 0x87, 0x20, 0xF0, 0x90, 0xFA, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, 0xBA, 0x1B, 0x03, 0xEB, 0xC2, 0x03, 0x23, 0x44, 0x20, 0xF0, 0x7F, 0x40, ++0x00, 0x21, 0xC3, 0xE9, 0x88, 0x01, 0xC5, 0xE7, 0x4F, 0xF4, 0xA4, 0x60, 0xBB, 0x1B, 0x00, 0xFB, 0x08, 0xF0, 0x00, 0xEB, ++0xC3, 0x00, 0x20, 0x44, 0xA9, 0x69, 0xC0, 0xF8, 0x28, 0x12, 0xE9, 0x69, 0xC0, 0xF8, 0x2C, 0x12, 0x29, 0x6A, 0xC0, 0xF8, ++0x30, 0x12, 0x00, 0x22, 0x69, 0x6A, 0xC0, 0xF8, 0x34, 0x12, 0x00, 0x23, 0xC0, 0xE9, 0x88, 0x23, 0xAC, 0xE7, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF2, 0x05, 0xA1, 0xD1, 0xE9, 0x00, 0x01, 0xBB, 0x1B, 0x02, 0xEB, 0xC3, 0x03, 0x23, 0x44, ++0xC3, 0xE9, 0x88, 0x01, 0x9E, 0xE7, 0x00, 0xBF, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x18, 0x88, 0x17, 0x00, ++0x78, 0x22, 0x10, 0xB4, 0xC1, 0xEB, 0x01, 0x13, 0xD0, 0xF8, 0xA8, 0x44, 0x02, 0xFB, 0x01, 0x01, 0x00, 0xEB, 0xC3, 0x03, ++0x01, 0xF5, 0xEC, 0x71, 0x00, 0x22, 0x8C, 0x42, 0x83, 0xF8, 0x3B, 0x22, 0x06, 0xD0, 0xD0, 0xF8, 0xAC, 0x34, 0x8B, 0x42, ++0x1C, 0xD0, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x90, 0xF8, 0x3B, 0x32, 0xC0, 0xF8, 0xA8, 0x24, 0x00, 0xF5, 0xEC, 0x71, ++0x7B, 0xB9, 0x90, 0xF8, 0xB3, 0x32, 0x00, 0xF5, 0x14, 0x71, 0x53, 0xB9, 0x90, 0xF8, 0x2B, 0x33, 0x00, 0xF5, 0x32, 0x71, ++0x2B, 0xB9, 0x90, 0xF8, 0xA3, 0x33, 0x00, 0xF5, 0x50, 0x71, 0x00, 0x2B, 0xE1, 0xD0, 0xC0, 0xF8, 0xA8, 0x14, 0xE2, 0xE7, ++0x90, 0xF8, 0x1B, 0x34, 0x00, 0x22, 0xC0, 0xF8, 0xAC, 0x24, 0x43, 0xB9, 0x90, 0xF8, 0x93, 0x34, 0x00, 0x2B, 0xD8, 0xD0, ++0x00, 0xF5, 0x86, 0x63, 0xC0, 0xF8, 0xAC, 0x34, 0xD3, 0xE7, 0x00, 0xF5, 0x6E, 0x73, 0xF9, 0xE7, 0x70, 0xB5, 0xD0, 0xF8, ++0xE4, 0x40, 0x54, 0xB1, 0x05, 0x4E, 0x05, 0x46, 0x21, 0x46, 0xD6, 0xF8, 0x20, 0x33, 0x00, 0x22, 0x28, 0x46, 0x98, 0x47, ++0x24, 0x68, 0x00, 0x2C, 0xF6, 0xD1, 0x70, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x04, 0x4A, 0x05, 0x4B, 0x11, 0x69, 0xD3, 0xF8, ++0xE0, 0x31, 0x01, 0xF5, 0x1C, 0x51, 0x28, 0x30, 0x10, 0x31, 0x18, 0x47, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x0B, 0x4B, 0x1A, 0x78, 0x02, 0xB9, 0x70, 0x47, 0x5B, 0x68, 0x1B, 0x07, 0xFB, 0xD4, 0x43, 0x68, 0x70, 0xB5, 0x04, 0x46, ++0x03, 0xB1, 0x70, 0xBD, 0x06, 0x4D, 0x28, 0x30, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xD5, 0xF8, 0x50, 0x34, 0x20, 0x46, ++0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF0, 0xB4, 0xA0, 0xF8, ++0xD2, 0x10, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1F, 0x4D, ++0x1F, 0x4B, 0x2E, 0x68, 0x9A, 0x7C, 0x77, 0x1C, 0x01, 0x2A, 0x2F, 0x60, 0x2B, 0xD9, 0x1D, 0x4C, 0x1A, 0x7D, 0x4F, 0xF4, ++0xA4, 0x6C, 0x0C, 0xFB, 0x02, 0x42, 0xB2, 0xF8, 0xD2, 0x40, 0xA1, 0x42, 0x1C, 0xD3, 0x9B, 0x68, 0x5B, 0xB1, 0x01, 0x21, ++0xB3, 0xF8, 0xD2, 0x20, 0x83, 0xF8, 0xD5, 0x10, 0xB2, 0xFB, 0xF4, 0xF2, 0x83, 0xF8, 0xD4, 0x20, 0x1B, 0x68, 0x00, 0x2B, ++0xF4, 0xD1, 0x12, 0x4A, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x23, 0x43, 0x13, 0x60, 0x2F, 0xB1, 0x0A, 0x4B, 0x2E, 0x60, ++0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, 0x70, 0x47, 0x90, 0xF8, 0x63, 0x20, 0x1A, 0x75, 0x0C, 0x46, ++0xDD, 0xE7, 0x90, 0xF8, 0x63, 0x20, 0x1A, 0x75, 0x40, 0xF2, 0x01, 0x13, 0x0C, 0x46, 0xA0, 0xF8, 0xD4, 0x30, 0xE2, 0xE7, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x21, 0x04, 0x46, 0x82, 0xB0, 0x03, 0x23, 0x00, 0x22, 0x58, 0x20, 0x0B, 0xF0, 0xEA, 0xFC, ++0x3B, 0x4F, 0xFF, 0x22, 0x7B, 0x6D, 0x8D, 0xF8, 0x07, 0x20, 0x05, 0x46, 0x94, 0xF8, 0x63, 0x00, 0x98, 0x47, 0xB4, 0xF8, ++0xB6, 0x14, 0x94, 0xF8, 0xB4, 0x04, 0x10, 0xF0, 0xED, 0xF9, 0x94, 0xF8, 0xB5, 0x24, 0xB4, 0xF8, 0xB8, 0x64, 0xB4, 0xF8, ++0xBA, 0x14, 0x84, 0xF8, 0xC5, 0x21, 0x04, 0x2A, 0x08, 0xBF, 0x03, 0x22, 0x03, 0x46, 0xC4, 0xF8, 0x90, 0x01, 0xA4, 0xF8, ++0x94, 0x61, 0xA4, 0xF8, 0x96, 0x11, 0x84, 0xF8, 0xC4, 0x21, 0x00, 0x28, 0x50, 0xD0, 0x1B, 0x79, 0x84, 0xF8, 0xBC, 0x34, ++0x7B, 0x6C, 0x0D, 0xF1, 0x07, 0x01, 0x04, 0xF2, 0xB4, 0x40, 0x98, 0x47, 0x9D, 0xF8, 0x07, 0x10, 0x68, 0x70, 0xA9, 0x70, ++0x06, 0x46, 0x94, 0xF8, 0x63, 0x00, 0x28, 0x70, 0x94, 0xF8, 0x62, 0x30, 0x2B, 0xBB, 0x84, 0xF8, 0x8A, 0x30, 0x7E, 0xBB, ++0xFB, 0x6C, 0x94, 0xF8, 0x6C, 0x80, 0x98, 0x47, 0xD7, 0xF8, 0xD8, 0x31, 0x04, 0xF1, 0x28, 0x00, 0x98, 0x47, 0x1A, 0x4A, ++0x1A, 0x49, 0xD7, 0xF8, 0xE0, 0x31, 0x09, 0x69, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x08, 0x28, 0x04, 0xF1, 0x18, 0x00, ++0xD8, 0xF8, 0x08, 0x20, 0x11, 0x44, 0x98, 0x47, 0x01, 0x23, 0x84, 0xF8, 0x78, 0x60, 0x84, 0xF8, 0x8B, 0x30, 0x28, 0x46, ++0x0B, 0xF0, 0xBE, 0xFC, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x2B, 0xF7, 0xD1, 0x00, 0x23, 0x84, 0xF8, 0xDB, 0x30, ++0x00, 0x2E, 0xF2, 0xD1, 0xFB, 0x6C, 0x98, 0x47, 0x0A, 0x4B, 0x01, 0x22, 0x5A, 0x72, 0xEC, 0xE7, 0xD7, 0xF8, 0xBC, 0x31, ++0x20, 0x46, 0x98, 0x47, 0x28, 0x46, 0x0B, 0xF0, 0xA7, 0xFC, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1B, 0x79, 0xFF, 0xDE, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0xD8, 0x9C, 0x17, 0x00, 0x07, 0x4A, 0x93, 0x7C, ++0x51, 0x7C, 0x0B, 0x44, 0x01, 0x2B, 0x06, 0xD1, 0x90, 0x68, 0x90, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x18, 0xBF, 0x00, 0x20, ++0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x05, 0x4A, 0x06, 0x49, 0x93, 0x7C, 0x50, 0x7C, ++0x03, 0x44, 0x00, 0x22, 0x01, 0x2B, 0x0A, 0x60, 0x01, 0xDC, 0xFF, 0xF7, 0x65, 0xB9, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, ++0x2C, 0x00, 0x32, 0x40, 0x13, 0x4B, 0x00, 0x22, 0x02, 0x70, 0x9B, 0x68, 0x03, 0xB3, 0x10, 0xB4, 0x01, 0x46, 0x01, 0x24, ++0x10, 0x46, 0x08, 0xE0, 0x93, 0xF8, 0x64, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0xC0, 0x24, 0x72, 0xB9, 0x01, 0x30, 0x1B, 0x68, ++0x7B, 0xB1, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xF2, 0xD0, 0x93, 0xF8, 0x64, 0x20, 0x00, 0x2A, 0xF5, 0xD0, 0x93, 0xF8, ++0xC0, 0x24, 0x00, 0x2A, 0xF1, 0xD0, 0x0C, 0x70, 0x1B, 0x68, 0x00, 0x2B, 0xEF, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x18, 0x46, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, 0x10, 0xB5, 0x04, 0x23, 0x04, 0x46, 0xFF, 0x22, 0x00, 0x21, 0x87, 0x20, ++0x0B, 0xF0, 0x16, 0xFC, 0x04, 0x60, 0xBD, 0xE8, 0x10, 0x40, 0x0B, 0xF0, 0x41, 0xBC, 0x00, 0xBF, 0x11, 0xF4, 0x00, 0x01, ++0x70, 0xB5, 0x04, 0x46, 0x16, 0xD0, 0x00, 0x25, 0x2A, 0x4B, 0x80, 0xF8, 0x78, 0x50, 0x19, 0x69, 0x29, 0x48, 0x2A, 0x4B, ++0x80, 0xF8, 0x24, 0x50, 0x40, 0xF2, 0x01, 0x72, 0x01, 0xF5, 0x1C, 0x51, 0x44, 0x61, 0x82, 0x83, 0xD3, 0xF8, 0xE0, 0x31, ++0x10, 0x31, 0x0C, 0x30, 0x98, 0x47, 0x84, 0xF8, 0x6B, 0x50, 0x70, 0xBD, 0x90, 0xF8, 0x6B, 0x30, 0x21, 0x4A, 0x01, 0x33, ++0xDB, 0xB2, 0x12, 0x68, 0x80, 0xF8, 0x6B, 0x30, 0x52, 0x78, 0x9A, 0x42, 0x25, 0xD0, 0x90, 0xF8, 0x64, 0x30, 0xC3, 0xB9, ++0x1C, 0x4B, 0x5B, 0x78, 0x23, 0xB1, 0x1C, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x15, 0x4B, 0x1A, 0x7A, ++0x0A, 0xB1, 0x01, 0x3A, 0x1A, 0x72, 0x14, 0x4A, 0x17, 0x48, 0xD2, 0xF8, 0xD8, 0x21, 0x01, 0x21, 0x99, 0x83, 0x90, 0x47, ++0x63, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x70, 0xBD, 0x0E, 0x4B, 0x90, 0xF8, 0x63, 0x00, 0xD3, 0xF8, 0x94, 0x34, ++0x10, 0x49, 0x22, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x80, 0xF8, 0x6B, 0x10, 0x4F, 0xF4, 0x80, 0x60, 0x0D, 0x49, ++0x0D, 0xF0, 0x74, 0xFA, 0x05, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, ++0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, ++0x34, 0x04, 0x32, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x99, 0x71, 0x13, 0x00, 0xF0, 0x98, 0x15, 0x00, 0x30, 0xB4, 0x01, 0x25, ++0x00, 0x24, 0x1D, 0x70, 0x14, 0x70, 0x04, 0x28, 0x20, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x03, 0x18, 0x09, 0x05, 0x14, 0x00, ++0x00, 0x21, 0x19, 0x70, 0x01, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x09, 0x78, 0x10, 0x29, 0x0F, 0xD0, 0x20, 0x29, ++0x01, 0xD1, 0x02, 0x21, 0x19, 0x70, 0x03, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x04, 0x23, 0x13, 0x70, 0x30, 0xBC, ++0x70, 0x47, 0x02, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x21, 0x19, 0x70, 0xF0, 0xE7, 0x05, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE1, 0xDA, 0x30, 0xBC, 0x03, 0x49, 0x03, 0x48, 0xAD, 0x22, 0x0D, 0xF0, 0x50, 0xBC, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x22, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x0F, 0x33, ++0x23, 0xB1, 0x13, 0x68, 0xC3, 0xF3, 0x0F, 0x33, 0x96, 0x2B, 0x36, 0xD9, 0x96, 0x20, 0x1E, 0x49, 0x1E, 0x4B, 0x0A, 0x68, ++0x18, 0x81, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x96, 0x2A, 0x25, 0xD9, 0x96, 0x22, ++0x19, 0x49, 0x5A, 0x81, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x96, 0x2A, ++0x15, 0xD9, 0x96, 0x22, 0x14, 0x49, 0x9A, 0x81, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, ++0x0F, 0x32, 0x96, 0x2A, 0x03, 0xD9, 0x96, 0x22, 0xDA, 0x81, 0x1A, 0x82, 0x70, 0x47, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, ++0xDA, 0x81, 0x1A, 0x82, 0x70, 0x47, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0xE6, 0xE7, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, ++0xD6, 0xE7, 0x10, 0x68, 0xC0, 0xF3, 0x0F, 0x30, 0xC5, 0xE7, 0x00, 0xBF, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, 0x38, 0xB5, 0x0B, 0x4C, 0x34, 0x22, 0x00, 0x21, ++0x20, 0x46, 0xE8, 0xF7, 0x0B, 0xFF, 0x09, 0x48, 0x09, 0x4A, 0x0A, 0x49, 0x22, 0x60, 0x01, 0x25, 0x00, 0x23, 0xE5, 0x77, ++0x02, 0x60, 0x63, 0x82, 0x63, 0x60, 0xD1, 0xF8, 0xA0, 0x31, 0x98, 0x47, 0x05, 0x4B, 0x63, 0x62, 0x38, 0xBD, 0x00, 0xBF, ++0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x88, 0x1A, 0x17, 0x00, 0x7D, 0x71, 0x13, 0x00, ++0x38, 0xB5, 0x51, 0x4D, 0x51, 0x4C, 0xAB, 0x78, 0x13, 0xB9, 0xD4, 0xF8, 0xE4, 0x30, 0x98, 0x47, 0xFF, 0xF7, 0xD4, 0xFF, ++0xFF, 0xF7, 0x6A, 0xF8, 0xFE, 0xF7, 0xF8, 0xFC, 0x09, 0xF0, 0xDC, 0xFC, 0x07, 0xF0, 0x78, 0xFD, 0x08, 0xF0, 0xAA, 0xFE, ++0xD4, 0xF8, 0x8C, 0x33, 0x98, 0x47, 0xAB, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x82, 0x80, 0xFD, 0xF7, 0x61, 0xFA, 0x45, 0x4D, ++0x2B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x7D, 0xD4, 0x03, 0xF0, 0x70, 0xFD, 0x09, 0xF0, 0x7C, 0xFE, 0x63, 0x6E, 0x98, 0x47, ++0xD4, 0xF8, 0x7C, 0x31, 0x98, 0x47, 0xEF, 0xF7, 0x0D, 0xF8, 0xEF, 0xF7, 0x0D, 0xF8, 0xEF, 0xF7, 0x0D, 0xF8, 0x3C, 0x4B, ++0x93, 0xF8, 0xFA, 0x30, 0x00, 0x2B, 0x62, 0xD1, 0xD4, 0xF8, 0xE4, 0x34, 0x98, 0x47, 0x39, 0x4A, 0x29, 0x68, 0x13, 0x68, ++0x38, 0x48, 0x39, 0x4D, 0xC3, 0xF3, 0x15, 0x03, 0x43, 0xF0, 0x20, 0x73, 0x13, 0x60, 0x8B, 0x78, 0x02, 0x68, 0xDC, 0x06, ++0x4C, 0xBF, 0x22, 0xF0, 0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x02, 0x60, 0x32, 0x4A, 0x33, 0x4C, 0x33, 0x48, 0x13, 0xF0, ++0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, 0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0x22, 0x68, 0x2F, 0x4B, ++0x42, 0xF0, 0x00, 0x62, 0x22, 0x60, 0x02, 0x68, 0x2D, 0x4C, 0x22, 0xF4, 0x70, 0x02, 0x42, 0xF4, 0x00, 0x12, 0x02, 0x60, ++0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x62, 0x42, 0xF4, 0xC0, 0x62, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0x60, 0x52, 0x42, 0xF4, ++0x00, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x32, 0x42, 0xF4, 0x40, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, ++0x60, 0x22, 0x1A, 0x60, 0x2B, 0x68, 0x20, 0x4A, 0x23, 0x40, 0x43, 0xF4, 0xBB, 0x63, 0xA0, 0xF5, 0x66, 0x70, 0x43, 0xF0, ++0x04, 0x03, 0x2B, 0x60, 0x03, 0x68, 0xA5, 0xF1, 0xF6, 0x55, 0xA5, 0xF5, 0x32, 0x25, 0x23, 0x40, 0x43, 0xF0, 0x3F, 0x03, ++0xA5, 0xF6, 0xFF, 0x15, 0x03, 0x60, 0x15, 0x60, 0x4B, 0x78, 0x2B, 0xB1, 0xD2, 0xF8, 0x24, 0x31, 0x43, 0xF0, 0x40, 0x03, ++0xC2, 0xF8, 0x24, 0x31, 0x38, 0xBD, 0x12, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x9B, 0xE7, 0xFD, 0xF7, 0xD5, 0xF9, 0x7C, 0xE7, ++0x03, 0x20, 0xEE, 0xF7, 0x8B, 0xFC, 0x7D, 0xE7, 0x3C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x2C, 0x19, 0x17, 0x00, 0xF0, 0x00, 0x32, 0x40, 0x80, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, ++0x40, 0x04, 0x32, 0x40, 0x34, 0x04, 0x32, 0x40, 0x2C, 0x04, 0x32, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x32, 0x40, ++0x80, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x1C, 0x46, 0x05, 0x8C, 0x93, 0xF8, 0x62, 0x30, 0xD2, 0xF8, 0x20, 0x90, ++0x87, 0x69, 0xD0, 0xF8, 0x1C, 0xB0, 0x89, 0xB0, 0x16, 0x46, 0xAD, 0x02, 0xDD, 0xE9, 0x12, 0x20, 0xD3, 0xB9, 0xB4, 0xF8, ++0x68, 0xC0, 0xBC, 0xF1, 0x00, 0x0F, 0x15, 0xD0, 0xD2, 0x8B, 0xB3, 0x6A, 0x0C, 0xFB, 0x02, 0xF2, 0x05, 0x92, 0x18, 0x07, ++0x05, 0xFB, 0x0C, 0xF2, 0x06, 0x92, 0x19, 0xD0, 0x00, 0x23, 0xB7, 0xEB, 0x09, 0x0A, 0x4F, 0xF4, 0xFA, 0x76, 0x07, 0x93, ++0x05, 0x9B, 0x03, 0xF5, 0xC8, 0x73, 0xC4, 0xE9, 0x1F, 0xA3, 0x74, 0xE0, 0x00, 0x28, 0x40, 0xF0, 0xC1, 0x80, 0x06, 0x95, ++0x4F, 0xF0, 0x01, 0x0A, 0xD0, 0x8B, 0xB2, 0x6A, 0x0A, 0xFB, 0x00, 0xF0, 0x12, 0x07, 0x05, 0x90, 0x40, 0xF0, 0x32, 0x81, ++0xF2, 0x6A, 0xDF, 0xF8, 0x94, 0xC2, 0xDF, 0xF8, 0xD4, 0x82, 0xDC, 0xF8, 0x00, 0x30, 0x9F, 0x48, 0xC2, 0xF3, 0x03, 0x12, ++0x23, 0xF0, 0x7F, 0x03, 0x18, 0xF8, 0x02, 0x20, 0x02, 0xF0, 0x7F, 0x02, 0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0xB3, 0x6A, ++0x99, 0x4A, 0xC3, 0xF3, 0xC0, 0x13, 0x41, 0xEA, 0x03, 0x51, 0x4F, 0xF0, 0x00, 0x43, 0x01, 0x60, 0x13, 0x60, 0xBF, 0xF3, ++0x4F, 0x8F, 0x00, 0xBF, 0x13, 0x68, 0x58, 0x00, 0xFC, 0xD5, 0x93, 0x4B, 0x19, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x00, 0x29, ++0xC0, 0xF2, 0xB4, 0x80, 0x8E, 0x4A, 0x12, 0x68, 0x1F, 0xFA, 0x82, 0xFA, 0xB2, 0x6A, 0x12, 0x07, 0x40, 0xF0, 0xA3, 0x80, ++0xF2, 0x6A, 0x8C, 0x49, 0x88, 0x48, 0xD1, 0xF8, 0x00, 0xC0, 0xC2, 0xF3, 0x03, 0x12, 0x2C, 0xF0, 0x7F, 0x0C, 0x18, 0xF8, ++0x02, 0x20, 0x02, 0xF0, 0x7F, 0x02, 0x42, 0xEA, 0x0C, 0x02, 0x0A, 0x60, 0xB2, 0x6A, 0xC2, 0xF3, 0xC0, 0x12, 0x08, 0x31, ++0x12, 0x05, 0x42, 0xF0, 0x18, 0x02, 0x4F, 0xF0, 0x00, 0x46, 0x02, 0x60, 0x0E, 0x60, 0xBF, 0xF3, 0x4F, 0x8F, 0x00, 0xBF, ++0x0A, 0x68, 0x56, 0x00, 0xFC, 0xD5, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x73, 0xDB, 0x77, 0x4A, 0x94, 0xF8, ++0x62, 0x30, 0x16, 0x68, 0x00, 0x22, 0xB6, 0xB2, 0xAA, 0xEB, 0x06, 0x0A, 0x07, 0x92, 0xB7, 0xEB, 0x09, 0x09, 0x19, 0xEB, ++0x0A, 0x0A, 0x00, 0x2B, 0x84, 0xD0, 0x4F, 0xEA, 0xE5, 0x79, 0x2A, 0x46, 0x4B, 0x46, 0x38, 0x46, 0x59, 0x46, 0x1F, 0xF0, ++0x67, 0xFB, 0xBA, 0x1B, 0x02, 0x92, 0x07, 0x9A, 0x00, 0xFB, 0x09, 0xF3, 0x6B, 0xEB, 0x02, 0x02, 0x05, 0xFB, 0x01, 0x33, ++0x03, 0x92, 0xA0, 0xFB, 0x05, 0x01, 0x19, 0x44, 0xDD, 0xE9, 0x02, 0x23, 0x99, 0x42, 0x08, 0xBF, 0x90, 0x42, 0x38, 0xBF, ++0xCD, 0xE9, 0x02, 0x01, 0x64, 0x4B, 0x06, 0x9A, 0x1B, 0x68, 0xDD, 0xE9, 0x02, 0x67, 0xB6, 0x18, 0x99, 0x01, 0x34, 0xD4, ++0x05, 0x9B, 0xF1, 0x1A, 0xA1, 0xF5, 0xC8, 0x71, 0x5F, 0x4F, 0x60, 0x4B, 0x3E, 0x69, 0x1B, 0x68, 0xF6, 0x1A, 0x0E, 0x44, ++0xE9, 0xF7, 0xDC, 0xFD, 0x3B, 0x69, 0xF3, 0x1A, 0xA3, 0xF5, 0x86, 0x53, 0x0C, 0x3B, 0x18, 0x1A, 0x00, 0x28, 0x63, 0x6A, ++0xB8, 0xBF, 0x76, 0x19, 0xB3, 0x42, 0x24, 0xD0, 0x57, 0x4B, 0x1A, 0x6A, 0xA2, 0x42, 0x43, 0xD0, 0x56, 0x4D, 0x31, 0x46, ++0xD5, 0xF8, 0xE0, 0x31, 0x04, 0xF1, 0x18, 0x00, 0x98, 0x47, 0xD5, 0xF8, 0xA8, 0x30, 0x20, 0x46, 0x09, 0xB0, 0xBD, 0xE8, ++0xF0, 0x4F, 0x18, 0x47, 0x90, 0xF8, 0x02, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0x90, 0xF8, 0x03, 0xA0, 0x05, 0xFB, ++0x0A, 0xF0, 0x06, 0x90, 0x36, 0xE7, 0x4B, 0x49, 0x05, 0x9B, 0xC9, 0x1A, 0xA1, 0xEB, 0x0A, 0x0A, 0x0A, 0xEB, 0x06, 0x01, ++0xC6, 0xE7, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0B, 0x68, 0x58, 0x00, 0x88, 0xD4, 0x45, 0x49, 0x45, 0x48, 0x4F, 0xF4, ++0xBE, 0x72, 0x0D, 0xF0, 0xD7, 0xF9, 0x00, 0x22, 0x94, 0xF8, 0x62, 0x30, 0x07, 0x92, 0xAA, 0xF5, 0xFA, 0x7A, 0x4F, 0xF4, ++0xFA, 0x76, 0x82, 0xE7, 0x12, 0x68, 0x51, 0x00, 0x3F, 0xF5, 0x48, 0xAF, 0x3B, 0x49, 0x3C, 0x48, 0x4F, 0xF4, 0xBE, 0x72, ++0x0D, 0xF0, 0xC4, 0xF9, 0x4F, 0xF4, 0xFA, 0x7A, 0x2F, 0x4B, 0x41, 0xE7, 0x30, 0x4A, 0x66, 0x62, 0x12, 0x68, 0x92, 0x01, ++0xB6, 0xD4, 0x36, 0x4A, 0x36, 0x4D, 0x12, 0x68, 0x93, 0xF8, 0x24, 0x10, 0x41, 0xF2, 0x13, 0x30, 0xC2, 0xF3, 0x07, 0x42, ++0x2A, 0x54, 0x00, 0x29, 0x32, 0xD1, 0x32, 0x4A, 0x32, 0x49, 0x12, 0x68, 0x09, 0x68, 0x41, 0xF2, 0x14, 0x30, 0xD2, 0xB2, ++0x2A, 0x54, 0x01, 0x22, 0x83, 0xF8, 0x24, 0x20, 0x0B, 0x78, 0x93, 0x42, 0x06, 0xD1, 0x2D, 0x49, 0x2D, 0x4A, 0x0B, 0x60, ++0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x41, 0xF2, 0x13, 0x32, 0x41, 0xF2, 0x14, 0x33, 0xA8, 0x5C, 0xE9, 0x5C, ++0x88, 0x42, 0x1D, 0xD2, 0x17, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDA, 0x41, 0xF2, 0x13, 0x32, ++0x41, 0xF2, 0x14, 0x33, 0xAA, 0x5C, 0xEB, 0x5C, 0x9A, 0x42, 0x07, 0xD3, 0x18, 0x49, 0x20, 0x48, 0x15, 0x4D, 0x40, 0xF2, ++0xD7, 0x12, 0x0D, 0xF0, 0xAF, 0xF9, 0x7E, 0xE7, 0x12, 0x4D, 0x7C, 0xE7, 0x00, 0x22, 0x4F, 0xF4, 0xFA, 0x76, 0x07, 0x92, ++0x92, 0x46, 0x28, 0xE7, 0x12, 0x4E, 0x14, 0x48, 0xA9, 0x5C, 0xEA, 0x5C, 0x33, 0x68, 0x06, 0x68, 0x16, 0x48, 0xF6, 0xB2, ++0x1B, 0x0C, 0x00, 0x96, 0x0C, 0xF0, 0x20, 0xFF, 0xD4, 0xE7, 0x00, 0xBF, 0x60, 0x81, 0x32, 0x40, 0x6C, 0x81, 0x32, 0x40, ++0x38, 0x36, 0x17, 0x00, 0x64, 0x81, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0xA4, 0x80, 0x32, 0x40, ++0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xFE, 0xFF, 0xFF, 0x70, 0x79, 0x15, 0x00, 0x04, 0x99, 0x15, 0x00, ++0x44, 0x80, 0x32, 0x40, 0x00, 0x40, 0x1E, 0x00, 0x90, 0x00, 0x32, 0x40, 0x74, 0x36, 0x17, 0x00, 0x70, 0x80, 0x32, 0x40, ++0x74, 0x80, 0x32, 0x40, 0x3C, 0x99, 0x15, 0x00, 0x28, 0x99, 0x15, 0x00, 0x40, 0xA9, 0x15, 0x00, 0x0B, 0x02, 0x10, 0xB5, ++0x04, 0x46, 0x03, 0xD5, 0x00, 0x23, 0x80, 0xF8, 0x78, 0x30, 0x10, 0xBD, 0x4F, 0xF4, 0x80, 0x60, 0x04, 0x49, 0x0C, 0xF0, ++0x37, 0xFF, 0x04, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0xB0, 0x99, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x70, 0x93, 0xD9, 0xF8, 0x20, 0xB0, 0x83, 0xB0, 0x4F, 0xF4, ++0x00, 0x20, 0x0B, 0xF0, 0x79, 0xFC, 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xF5, 0x80, 0xBA, 0x4C, 0xDF, 0xF8, 0x58, 0xA3, ++0xA1, 0x7F, 0xB9, 0x4F, 0xDF, 0xF8, 0x54, 0x83, 0xB8, 0x4E, 0x00, 0x29, 0x00, 0xF0, 0xEA, 0x80, 0x08, 0x07, 0x0E, 0xD5, ++0xB6, 0x4B, 0xDB, 0xF8, 0x70, 0x00, 0x1B, 0x68, 0xDA, 0xF8, 0x10, 0x20, 0x5B, 0x68, 0x03, 0x44, 0x9B, 0x1A, 0x00, 0x2B, ++0xC0, 0xF2, 0xCB, 0x80, 0x01, 0xF0, 0xF7, 0x01, 0xA1, 0x77, 0x4A, 0x07, 0x00, 0xF1, 0x99, 0x80, 0x8B, 0x07, 0x15, 0xD5, ++0xDB, 0xF8, 0x04, 0x30, 0x23, 0xF0, 0x02, 0x03, 0xCB, 0xF8, 0x04, 0x30, 0x99, 0xF8, 0x1D, 0x30, 0x05, 0x2B, 0x08, 0xD1, ++0xA8, 0x4D, 0xA9, 0x48, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x23, 0xA1, 0x7F, 0x89, 0xF8, 0x1D, 0x30, 0x01, 0xF0, ++0xFD, 0x01, 0xA1, 0x77, 0xCD, 0x07, 0x2E, 0xD5, 0x33, 0x68, 0x58, 0x01, 0x40, 0xF1, 0xA3, 0x80, 0x31, 0x68, 0x09, 0x0C, ++0x11, 0xF4, 0x7C, 0x7F, 0x00, 0xF0, 0xAA, 0x80, 0x9E, 0x4A, 0x10, 0x39, 0x01, 0xF0, 0xFF, 0x01, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x25, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xA1, 0x80, 0x99, 0x4A, 0x93, 0xF8, 0x22, 0x10, ++0x13, 0x68, 0x98, 0x4A, 0xB3, 0xF9, 0x00, 0x30, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x22, 0x00, 0x2B, 0x00, 0x92, ++0xC0, 0xF2, 0x9F, 0x80, 0x3B, 0x68, 0x13, 0xF4, 0xE0, 0x2F, 0x00, 0xF0, 0xA8, 0x80, 0xA1, 0x7F, 0x01, 0xF0, 0xFE, 0x01, ++0xA1, 0x77, 0x8A, 0x06, 0x9D, 0xD5, 0x8E, 0x4E, 0x8E, 0x49, 0x35, 0x68, 0xC5, 0xF3, 0x41, 0x17, 0x3A, 0x46, 0x02, 0x20, ++0x0C, 0xF0, 0xAA, 0xFE, 0x00, 0x23, 0xC5, 0xF3, 0x47, 0x15, 0x8B, 0xF8, 0x78, 0x30, 0x00, 0x2F, 0x40, 0xF0, 0xB2, 0x80, ++0x87, 0x4B, 0x80, 0x4E, 0x5A, 0x78, 0x1A, 0x70, 0x86, 0x4A, 0x87, 0x4D, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, ++0xDB, 0xF8, 0x04, 0x30, 0xD6, 0xF8, 0xD8, 0x21, 0x23, 0xF0, 0x01, 0x03, 0xCB, 0xF8, 0x04, 0x30, 0x0B, 0xF1, 0x28, 0x00, ++0x90, 0x47, 0x2A, 0x68, 0x13, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x24, 0x81, 0x78, 0x49, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, ++0x0B, 0x60, 0x13, 0x78, 0x01, 0x2B, 0x12, 0xD1, 0x01, 0xF5, 0xFF, 0x41, 0x34, 0x31, 0x78, 0x4A, 0xDA, 0xF8, 0x10, 0x30, ++0x08, 0x68, 0xB2, 0xF8, 0xB2, 0x10, 0xD6, 0xF8, 0xE0, 0x21, 0x03, 0xEB, 0x40, 0x13, 0x59, 0x1A, 0x0B, 0xF1, 0x18, 0x00, ++0x90, 0x47, 0x2B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x00, 0x81, 0xA1, 0x7F, 0x01, 0xF0, 0xDF, 0x01, 0xA1, 0x77, ++0x4B, 0xE7, 0x6D, 0x49, 0x61, 0x4D, 0x02, 0x20, 0x0C, 0xF0, 0x60, 0xFE, 0x6B, 0x49, 0x63, 0x68, 0x0A, 0x68, 0x22, 0xF0, ++0x04, 0x02, 0x0A, 0x60, 0x22, 0x68, 0x43, 0xF4, 0x00, 0x73, 0x1A, 0x43, 0x4A, 0x61, 0xD5, 0xF8, 0x98, 0x14, 0x63, 0x60, ++0x9B, 0xF8, 0x63, 0x00, 0xD5, 0xF8, 0x94, 0x34, 0x5A, 0x46, 0x98, 0x47, 0x3B, 0x68, 0xA1, 0x7F, 0x23, 0xF0, 0x7C, 0x73, ++0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0xF0, 0xFB, 0x01, 0x43, 0xF4, 0x80, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xA1, 0x77, ++0x3E, 0xE7, 0x5B, 0x48, 0x0C, 0xF0, 0xEA, 0xFD, 0x7F, 0xE7, 0x00, 0x22, 0x9B, 0xF8, 0x6C, 0x00, 0x11, 0x46, 0xF8, 0xF7, ++0x01, 0xFB, 0x60, 0xB1, 0xA1, 0x7F, 0x2B, 0xE7, 0x55, 0x48, 0x0C, 0xF0, 0xDD, 0xFD, 0x72, 0xE7, 0x54, 0x48, 0x0C, 0xF0, ++0xD9, 0xFD, 0x6E, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x10, 0x30, 0xA1, 0x7F, 0xCB, 0xF8, 0x70, 0x30, ++0x1A, 0xE7, 0x93, 0x45, 0x3F, 0xF4, 0x5E, 0xAF, 0x4D, 0x49, 0x4E, 0x48, 0x40, 0xF2, 0x22, 0x32, 0x0D, 0xF0, 0x40, 0xF8, ++0x3B, 0x68, 0x13, 0xF4, 0xE0, 0x2F, 0x7F, 0xF4, 0x58, 0xAF, 0x32, 0x68, 0x33, 0x68, 0x49, 0x49, 0xD0, 0x0F, 0xC3, 0xF3, ++0x80, 0x73, 0x05, 0x46, 0x02, 0x46, 0x02, 0x20, 0x01, 0x93, 0x0C, 0xF0, 0x05, 0xFE, 0x01, 0x9B, 0x53, 0xEA, 0x05, 0x02, ++0x28, 0x46, 0x3F, 0xF4, 0x46, 0xAF, 0x2F, 0x4D, 0x00, 0x9A, 0x19, 0x46, 0xD5, 0xF8, 0x3C, 0x32, 0x98, 0x47, 0x33, 0x68, ++0x23, 0xF0, 0x00, 0x43, 0x33, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x80, 0x43, 0x33, 0x60, 0x36, 0xE7, 0xDA, 0xF8, 0x10, 0x10, ++0x01, 0xF5, 0x9C, 0x51, 0x32, 0x46, 0x08, 0x31, 0x05, 0xE0, 0xDA, 0xF8, 0x10, 0x30, 0xCB, 0x1A, 0x00, 0x2B, 0xC0, 0xF2, ++0xC2, 0x80, 0x13, 0x68, 0x1B, 0x07, 0xF6, 0xD5, 0xDF, 0xF8, 0x90, 0x80, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x08, 0x03, ++0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0xDE, 0x06, 0x19, 0xD5, 0x2C, 0x49, 0x19, 0x4E, 0x02, 0x20, 0x0C, 0xF0, ++0xCF, 0xFD, 0x2B, 0x4B, 0xDF, 0xF8, 0x74, 0xC0, 0x1A, 0x68, 0xD6, 0xF8, 0x3C, 0x32, 0x12, 0x0C, 0x8C, 0xF8, 0x00, 0x20, ++0x05, 0xF0, 0x01, 0x01, 0x78, 0x08, 0x5A, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x10, 0x03, 0xC8, 0xF8, ++0x00, 0x30, 0x1B, 0xE7, 0x21, 0x4B, 0x22, 0x49, 0x0B, 0x4E, 0x01, 0x25, 0x1D, 0x60, 0x02, 0x20, 0x0C, 0xF0, 0xB2, 0xFD, ++0x0F, 0x4A, 0x1F, 0x49, 0x53, 0x78, 0x0D, 0x60, 0xAB, 0x42, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x13, 0x70, 0x09, 0xE7, ++0x98, 0x9C, 0x17, 0x00, 0x74, 0x00, 0x32, 0x40, 0x70, 0x00, 0x32, 0x40, 0xC8, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x28, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, ++0x20, 0x9A, 0x15, 0x00, 0x13, 0x53, 0x1E, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, ++0xC0, 0x99, 0x15, 0x00, 0x4C, 0x00, 0x32, 0x40, 0xC4, 0x99, 0x15, 0x00, 0xDC, 0x99, 0x15, 0x00, 0xF0, 0x99, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x04, 0x9A, 0x15, 0x00, 0x14, 0x9A, 0x15, 0x00, 0x40, 0x9A, 0x15, 0x00, 0x44, 0x80, 0x32, 0x40, ++0x64, 0x85, 0x32, 0x40, 0x4C, 0x9A, 0x15, 0x00, 0x68, 0x85, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x36, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0xF7, 0xF7, 0x35, 0xF9, 0xF9, 0xE6, 0xEF, 0xF3, 0x10, 0x83, ++0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x32, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x31, 0x4B, 0x2F, 0x4F, 0x1A, 0x68, 0x01, 0x32, ++0x1A, 0x60, 0x00, 0x21, 0x3A, 0x68, 0x39, 0x60, 0x02, 0xF0, 0x0F, 0x08, 0xDA, 0xF8, 0x10, 0x20, 0x31, 0x46, 0x16, 0x46, ++0x0A, 0x46, 0x47, 0xF2, 0x30, 0x50, 0x04, 0xE0, 0xDA, 0xF8, 0x10, 0x10, 0x89, 0x1B, 0x81, 0x42, 0x1B, 0xD8, 0x39, 0x68, ++0x09, 0x07, 0xF7, 0xD1, 0x25, 0x48, 0x26, 0x49, 0xD0, 0xF8, 0x00, 0xC0, 0x0F, 0x68, 0x16, 0x46, 0xDA, 0xF8, 0x10, 0x20, ++0xB8, 0xF1, 0x00, 0x0F, 0x1A, 0xD1, 0x22, 0x4A, 0x04, 0x21, 0x11, 0x60, 0x1A, 0x68, 0x32, 0xB1, 0x1B, 0x49, 0x01, 0x3A, ++0x1A, 0x60, 0x0B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x2A, 0x68, 0xA0, 0xE6, 0x1C, 0x49, 0x00, 0x92, 0x02, 0x20, ++0x0C, 0xF0, 0x24, 0xFD, 0x15, 0x4B, 0x00, 0x9A, 0xD3, 0xE7, 0x19, 0x49, 0x02, 0x20, 0x0C, 0xF0, 0x1D, 0xFD, 0x3B, 0xE7, ++0x07, 0xEA, 0x0C, 0x07, 0x7F, 0x07, 0xE0, 0xD4, 0xCD, 0xE9, 0x00, 0x16, 0x80, 0x46, 0x16, 0x46, 0x01, 0xE0, 0x7A, 0x07, ++0x12, 0xD4, 0x00, 0x9A, 0xD8, 0xF8, 0x00, 0x70, 0x12, 0x68, 0xDA, 0xF8, 0x10, 0x10, 0x47, 0xF2, 0x30, 0x50, 0x89, 0x1B, ++0x81, 0x42, 0x07, 0xEA, 0x02, 0x07, 0xF0, 0xD9, 0x0B, 0x49, 0x02, 0x20, 0x0C, 0xF0, 0x00, 0xFD, 0x03, 0x4B, 0xEA, 0xE7, ++0x01, 0x9E, 0xC4, 0xE7, 0x38, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, ++0x74, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x5C, 0x9A, 0x15, 0x00, 0x2C, 0x9A, 0x15, 0x00, 0x68, 0x9A, 0x15, 0x00, ++0x10, 0xB5, 0x00, 0x20, 0x0B, 0xF0, 0xD0, 0xF8, 0x01, 0x28, 0x05, 0xD1, 0x05, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, ++0x60, 0x31, 0x18, 0x47, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x0B, 0xF0, 0x1A, 0xB8, 0x88, 0x1A, 0x17, 0x00, ++0x03, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0x01, 0x21, 0x00, 0x20, 0x0B, 0xF0, 0x11, 0xB8, 0x00, 0xBF, 0x38, 0x00, 0x32, 0x40, ++0xF8, 0xB5, 0x90, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x46, 0xD0, 0x90, 0xF8, 0x8A, 0x30, 0x04, 0x46, 0x00, 0x2B, 0x42, 0xD1, ++0x3D, 0x4E, 0x3E, 0x49, 0x94, 0xF8, 0x6C, 0x30, 0x3D, 0x4A, 0x67, 0x6A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, ++0x9D, 0x68, 0x13, 0x6A, 0xA3, 0x42, 0x3D, 0x44, 0x54, 0xD0, 0xD6, 0xF8, 0xE0, 0x31, 0x29, 0x46, 0x04, 0xF1, 0x18, 0x00, ++0x98, 0x47, 0x20, 0x46, 0xFF, 0xF7, 0x82, 0xF8, 0xD4, 0xF8, 0x80, 0x10, 0xD6, 0xF8, 0x14, 0x32, 0x39, 0x44, 0x20, 0x46, ++0x98, 0x47, 0xD6, 0xF8, 0xA4, 0x30, 0x2A, 0x46, 0x39, 0x46, 0x20, 0x46, 0x98, 0x47, 0xD8, 0xB9, 0x94, 0xF8, 0x78, 0x30, ++0x62, 0x68, 0x2C, 0x49, 0x01, 0x33, 0xDB, 0xB2, 0x42, 0xF0, 0x01, 0x02, 0x09, 0x68, 0x84, 0xF8, 0x78, 0x30, 0x62, 0x60, ++0x0A, 0x78, 0x93, 0x42, 0x21, 0xD8, 0x39, 0xD0, 0xB3, 0xEB, 0x52, 0x0F, 0x26, 0xD0, 0xB3, 0xEB, 0x92, 0x0F, 0x4F, 0xEA, ++0x92, 0x01, 0x21, 0xD0, 0x01, 0xEB, 0x41, 0x01, 0x8B, 0x42, 0x1D, 0xD0, 0xF8, 0xBD, 0x90, 0xF8, 0x8C, 0x20, 0x00, 0x2A, ++0xB8, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x01, 0x2B, 0x80, 0xF8, 0x8A, 0x30, 0x29, 0xD9, 0x02, 0x2B, 0x16, 0x4E, 0xB0, 0xD1, ++0x90, 0xF8, 0x63, 0x00, 0xD6, 0xF8, 0xC0, 0x31, 0x00, 0x21, 0x98, 0x47, 0xA9, 0xE7, 0xD6, 0xF8, 0x64, 0x11, 0x94, 0xF8, ++0x6C, 0x00, 0x22, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xF8, 0xF7, 0x30, 0xB9, 0xBD, 0xE8, 0xF8, 0x40, 0xEA, 0xF7, 0x5A, 0xBE, ++0x0F, 0x4B, 0x65, 0x62, 0x93, 0xF8, 0xB5, 0x30, 0x00, 0x2B, 0xAA, 0xD1, 0x0D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, ++0x9F, 0xD1, 0xA4, 0xE7, 0xEA, 0xF7, 0x4C, 0xFE, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0x06, 0xF0, 0x47, 0xBD, 0xBD, 0xE8, ++0xF8, 0x40, 0xFF, 0xF7, 0x9B, 0xB8, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0xC8, 0x35, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x4B, 0x2D, 0xE9, 0xF0, 0x47, 0x9C, 0x68, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x34, 0x4D, 0x2B, 0x68, ++0x04, 0x20, 0x01, 0x33, 0x2B, 0x60, 0xF6, 0xF7, 0xF1, 0xFC, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xF6, 0xF7, 0x8C, 0xFD, ++0x2B, 0x68, 0x2B, 0xB1, 0x2C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x4C, 0xD0, 0xDF, 0xF8, 0xB4, 0x80, ++0x00, 0x2C, 0x43, 0xD0, 0x29, 0x4F, 0x2A, 0x4E, 0x40, 0xF6, 0xE7, 0x35, 0x02, 0xE0, 0x24, 0x68, 0x00, 0x2C, 0x3B, 0xD0, ++0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0xF8, 0xD1, 0x94, 0xF8, 0xD5, 0x30, 0x01, 0x3B, 0xDB, 0xB2, 0x84, 0xF8, 0xD5, 0x30, ++0x00, 0x2B, 0xF0, 0xD1, 0x94, 0xF8, 0xD4, 0x30, 0x84, 0xF8, 0xD5, 0x30, 0x20, 0x46, 0xFE, 0xF7, 0xD3, 0xFF, 0x61, 0x6A, ++0xD8, 0xF8, 0x14, 0x32, 0x01, 0xF6, 0xE8, 0x31, 0x20, 0x46, 0x98, 0x47, 0x3B, 0x68, 0xB4, 0xF8, 0xD2, 0x20, 0x59, 0x01, ++0xB5, 0xEB, 0x43, 0x1F, 0x28, 0xBF, 0x01, 0xEB, 0x82, 0x21, 0x32, 0x69, 0x23, 0x6C, 0xA2, 0xF6, 0xE8, 0x39, 0x89, 0x44, ++0x20, 0x46, 0x4A, 0x46, 0x1B, 0xB1, 0xD8, 0xF8, 0xA4, 0x30, 0x61, 0x6A, 0x98, 0x47, 0x94, 0xF8, 0xC0, 0x34, 0x04, 0xF1, ++0x18, 0x00, 0x49, 0x46, 0x00, 0x2B, 0xC6, 0xD0, 0xD8, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0x24, 0x68, 0x00, 0x2C, 0xC3, 0xD1, ++0xD8, 0xF8, 0x84, 0x31, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x00, 0x2A, 0xB0, 0xD0, 0x62, 0xB6, 0xAE, 0xE7, 0x00, 0xBF, ++0x00, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x40, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0xF0, 0x4A, 0xBE, 0x14, 0x4B, 0x15, 0x4A, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x10, 0xB5, ++0x14, 0x68, 0x00, 0x2B, 0x04, 0xF0, 0x40, 0x74, 0x14, 0xDB, 0x20, 0x46, 0x0B, 0xF0, 0x04, 0xF9, 0x0F, 0x4B, 0x9B, 0x7C, ++0x3B, 0xB9, 0x0F, 0x4A, 0x0F, 0x4B, 0x10, 0x6A, 0xD3, 0xF8, 0xCC, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x0C, 0x4B, ++0x20, 0x46, 0xD3, 0xF8, 0x68, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0xB4, 0xF1, 0x40, 0x7F, 0xE7, 0xD1, 0x08, 0x49, ++0x08, 0x48, 0x4F, 0xF4, 0x9D, 0x62, 0x0C, 0xF0, 0xBB, 0xFD, 0xE0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x9A, 0x15, 0x00, ++0xF0, 0xB5, 0x2D, 0x4E, 0x2D, 0x4B, 0xDF, 0xF8, 0xC8, 0xE0, 0xDF, 0xF8, 0xC8, 0xC0, 0x2C, 0x4F, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x00, 0x62, 0x15, 0x8D, 0xD4, 0x8C, 0x44, 0xEA, 0x05, 0x44, 0x1C, 0x60, 0x52, 0x8D, 0x27, 0x4D, 0x5A, 0x60, ++0x00, 0x24, 0x27, 0x4A, 0xCE, 0xF8, 0x00, 0x40, 0x4F, 0xF0, 0x00, 0x53, 0xCC, 0xF8, 0x00, 0x40, 0x2C, 0x60, 0x00, 0xF1, ++0x10, 0x05, 0x3C, 0x60, 0xEC, 0xB2, 0x13, 0x60, 0x13, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0xDD, 0x00, 0x26, 0xD4, 0x15, 0x68, ++0xC5, 0xF3, 0x07, 0x43, 0xA3, 0x42, 0x4F, 0xEA, 0x15, 0x45, 0x1F, 0xD0, 0xED, 0xB2, 0xDF, 0xF8, 0x5C, 0xE0, 0xDF, 0xF8, ++0x68, 0xC0, 0x18, 0x4F, 0x2D, 0x04, 0x4F, 0xF0, 0xFF, 0x33, 0x45, 0xF0, 0x80, 0x45, 0xCE, 0xF8, 0x00, 0x30, 0xCC, 0xF8, ++0x00, 0x30, 0x15, 0x60, 0x3B, 0x68, 0x5A, 0x00, 0xFC, 0xD4, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x00, 0x63, 0x0C, 0x48, ++0x1D, 0x8D, 0xDA, 0x8C, 0x42, 0xEA, 0x05, 0x42, 0x02, 0x60, 0x0D, 0x4A, 0x5B, 0x8D, 0x13, 0x60, 0x0B, 0x01, 0x43, 0xEA, ++0x04, 0x43, 0x09, 0x4A, 0x43, 0xF0, 0x80, 0x43, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, ++0x20, 0x46, 0xF0, 0xBD, 0x68, 0x65, 0x17, 0x00, 0xBC, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0xB4, 0x00, 0x32, 0x40, ++0xC4, 0x00, 0x32, 0x40, 0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x82, 0xB0, 0x47, 0x78, 0x90, 0xF8, 0x29, 0x60, 0x01, 0x23, 0x8D, 0xF8, 0x06, 0x30, 0xFF, 0x2F, 0x4F, 0xF0, 0x00, 0x03, ++0x04, 0x46, 0x00, 0xF1, 0x04, 0x08, 0x8D, 0xF8, 0x07, 0x30, 0x00, 0xF0, 0x83, 0x80, 0x74, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x73, 0xDB, 0x3A, 0x46, 0x94, 0xF8, 0x28, 0x30, 0x70, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x0C, 0xF0, ++0xF5, 0xFA, 0x07, 0xF1, 0x10, 0x05, 0x6E, 0x4B, 0xED, 0xB2, 0xD3, 0xF8, 0x18, 0x33, 0x29, 0x46, 0x20, 0x46, 0x98, 0x47, ++0x6B, 0x4A, 0x6C, 0x48, 0x6C, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0x22, 0x17, 0x8D, 0xD3, 0x8C, 0x43, 0xEA, ++0x07, 0x43, 0x03, 0x60, 0x53, 0x8D, 0x0B, 0x60, 0x0D, 0xF1, 0x06, 0x03, 0x0D, 0xF1, 0x07, 0x02, 0x94, 0xF8, 0x28, 0x00, ++0x41, 0x46, 0xFF, 0xF7, 0x7B, 0xF8, 0x63, 0x4B, 0xA2, 0x68, 0x1A, 0x60, 0xE2, 0x68, 0x5A, 0x60, 0x22, 0x69, 0x9A, 0x60, ++0x62, 0x69, 0xDA, 0x60, 0x9D, 0xF8, 0x07, 0x30, 0x04, 0x2B, 0x65, 0xD0, 0x5D, 0x4A, 0x12, 0x68, 0x02, 0x2B, 0x12, 0x78, ++0x1F, 0xD1, 0xD1, 0x07, 0x00, 0xF1, 0x85, 0x80, 0x5A, 0x48, 0x01, 0x68, 0x21, 0xF0, 0x01, 0x01, 0x01, 0x60, 0x92, 0x07, ++0x17, 0xD5, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x56, 0x4A, 0x2B, 0x04, 0x43, 0xEA, 0x00, 0x33, 0x43, 0xEA, ++0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0x28, 0x46, ++0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x97, 0x07, 0x6F, 0xD4, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x4A, 0x4A, ++0x1B, 0x02, 0x43, 0xEA, 0x00, 0x33, 0x43, 0xEA, 0x05, 0x43, 0x43, 0xEA, 0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, ++0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x59, 0x00, 0xFC, 0xD4, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x0D, 0x2F, ++0x89, 0xD9, 0x40, 0x49, 0x40, 0x48, 0x40, 0xF2, 0x5C, 0x52, 0x0C, 0xF0, 0xAB, 0xFC, 0x82, 0xE7, 0x90, 0xF8, 0x28, 0x30, ++0x05, 0x2B, 0x4E, 0xD0, 0x34, 0x48, 0x35, 0x4A, 0x25, 0x78, 0x3B, 0x49, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x60, 0x13, 0x60, ++0x94, 0xF8, 0x28, 0x30, 0x94, 0xF8, 0x29, 0x20, 0x4F, 0xF4, 0x80, 0x70, 0x0C, 0xF0, 0x6C, 0xFA, 0x05, 0xEB, 0x86, 0x05, ++0x29, 0x4B, 0xED, 0xB2, 0xD3, 0xF8, 0x48, 0x34, 0x29, 0x46, 0x20, 0x46, 0x98, 0x47, 0x83, 0xE7, 0x30, 0x4A, 0xA1, 0x69, ++0x11, 0x60, 0xE1, 0x69, 0x51, 0x60, 0x21, 0x6A, 0x91, 0x60, 0x27, 0x4A, 0x2D, 0x49, 0x60, 0x6A, 0x12, 0x68, 0x08, 0x60, ++0x12, 0x78, 0x90, 0x07, 0xB1, 0xD5, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x23, 0x4A, 0x1B, 0x02, 0x43, 0xEA, ++0x00, 0x33, 0x43, 0xEA, 0x05, 0x43, 0x43, 0xEA, 0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, ++0x13, 0x68, 0x58, 0x00, 0xFC, 0xD4, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1D, 0x49, 0xA0, 0x69, 0x08, 0x60, ++0xE0, 0x69, 0x48, 0x60, 0x20, 0x6A, 0x88, 0x60, 0x60, 0x6A, 0xC8, 0x60, 0x75, 0xE7, 0x5A, 0x1E, 0x01, 0x2A, 0xDA, 0xD8, ++0x73, 0xE7, 0x18, 0x4B, 0x05, 0x78, 0x1B, 0x68, 0x09, 0x4A, 0x1B, 0x0E, 0x03, 0x3B, 0x2B, 0x44, 0x03, 0xEB, 0x46, 0x03, ++0xDD, 0xB2, 0x29, 0x46, 0xD2, 0xF8, 0x48, 0x34, 0x98, 0x47, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0xB4, 0x9A, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x64, 0x05, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, ++0x70, 0x79, 0x15, 0x00, 0xA0, 0x9A, 0x15, 0x00, 0x90, 0x9A, 0x15, 0x00, 0xC8, 0x00, 0x32, 0x40, 0xD4, 0x00, 0x32, 0x40, ++0xD8, 0x00, 0x32, 0x40, 0x33, 0x4A, 0x13, 0x68, 0xB0, 0xEB, 0x13, 0x6F, 0x70, 0xB5, 0x04, 0x46, 0x46, 0xD8, 0x0F, 0x28, ++0x24, 0xD8, 0x30, 0x4B, 0x30, 0x4D, 0x31, 0x49, 0x31, 0x48, 0x4F, 0xF0, 0xFF, 0x32, 0x1A, 0x60, 0xA3, 0x10, 0x2A, 0x60, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x00, 0xD1, 0xF8, 0x54, 0x34, 0x04, 0xF0, 0x03, 0x01, 0x98, 0x47, 0x2B, 0x4A, ++0x2B, 0x49, 0x2C, 0x4E, 0x2C, 0x4D, 0x2D, 0x48, 0x24, 0x04, 0x00, 0x23, 0x44, 0xF0, 0x80, 0x44, 0x33, 0x60, 0x2B, 0x60, ++0x13, 0x60, 0x03, 0x60, 0x0A, 0x46, 0x0C, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0x70, 0xBD, 0xA0, 0xF1, 0x10, 0x05, ++0x25, 0x48, 0x4F, 0xF4, 0x1E, 0x73, 0xED, 0xB2, 0x03, 0xFB, 0x05, 0x05, 0x28, 0x46, 0x95, 0xF8, 0x22, 0x60, 0xFD, 0xF7, ++0xD3, 0xFF, 0x1A, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x06, 0x36, 0x96, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0xE8, 0xD0, ++0x28, 0x8D, 0xEB, 0x8C, 0x11, 0x49, 0x12, 0x4A, 0x43, 0xEA, 0x00, 0x43, 0x0B, 0x60, 0x6B, 0x8D, 0x13, 0x60, 0xCC, 0xE7, ++0x13, 0x68, 0x15, 0x68, 0x0F, 0x48, 0x0E, 0x4A, 0x1B, 0x0E, 0x01, 0x33, 0xE3, 0x1A, 0x61, 0x1E, 0xA1, 0xEB, 0x15, 0x61, ++0x03, 0xEB, 0xD3, 0x73, 0x5B, 0x10, 0x4F, 0xF4, 0xA4, 0x64, 0x01, 0xF0, 0x01, 0x01, 0x04, 0xFB, 0x03, 0x00, 0x04, 0x31, ++0xBD, 0xE8, 0x70, 0x40, 0xD2, 0xF8, 0x54, 0x34, 0x18, 0x47, 0x00, 0xBF, 0xD8, 0x00, 0x32, 0x40, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xB4, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, ++0xAC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0x68, 0x65, 0x17, 0x00, 0xF0, 0xB4, 0x0E, 0x49, ++0x0E, 0x4F, 0x0F, 0x4E, 0x0F, 0x4D, 0x10, 0x4C, 0x4F, 0xF0, 0xFF, 0x32, 0x00, 0xF1, 0x10, 0x03, 0x0E, 0x48, 0x3A, 0x60, ++0xDB, 0xB2, 0x0A, 0x60, 0x00, 0x21, 0x01, 0x60, 0x1B, 0x04, 0x18, 0x30, 0x43, 0xF0, 0x80, 0x43, 0x31, 0x60, 0x02, 0x46, ++0x29, 0x60, 0x21, 0x60, 0x03, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0xF0, 0xBC, 0x70, 0x47, 0xC0, 0x00, 0x32, 0x40, ++0xBC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0xB4, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, ++0x08, 0xB5, 0x4F, 0xF0, 0x80, 0x60, 0x0A, 0xF0, 0xA5, 0xFE, 0x00, 0x21, 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x46, 0x0A, 0xF0, ++0x89, 0xBC, 0x00, 0xBF, 0x14, 0x4B, 0x15, 0x49, 0x1A, 0x68, 0x22, 0xF0, 0x02, 0x02, 0xF0, 0xB4, 0x1A, 0x60, 0x1A, 0x68, ++0x12, 0x4F, 0x13, 0x4E, 0x13, 0x4D, 0x14, 0x4C, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x4F, 0xF4, 0x40, 0x72, 0x3A, 0x60, ++0x07, 0x68, 0x82, 0x88, 0x00, 0x20, 0x30, 0x60, 0x28, 0x60, 0x27, 0x60, 0x0E, 0x4C, 0x0A, 0x60, 0x19, 0x68, 0x62, 0x68, ++0x0D, 0x4D, 0xA6, 0xF5, 0x00, 0x46, 0x44, 0x3E, 0x2A, 0x43, 0x21, 0xF4, 0xE0, 0x61, 0x19, 0x60, 0x25, 0x60, 0x32, 0x60, ++0xF0, 0xBC, 0xFC, 0xF7, 0x57, 0xBE, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x14, 0x00, 0x32, 0x40, 0x1C, 0x00, 0x32, 0x40, ++0xA4, 0x80, 0x32, 0x40, 0xA8, 0x80, 0x32, 0x40, 0x10, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x8C, 0x84, 0x03, 0x35, ++0x0B, 0x49, 0x0C, 0x48, 0x38, 0xB5, 0x02, 0x68, 0x4B, 0x68, 0x0B, 0x4C, 0x0B, 0x4D, 0x42, 0xF0, 0x02, 0x02, 0x23, 0x43, ++0x02, 0x60, 0x0C, 0x60, 0x00, 0x20, 0x2B, 0x60, 0xFC, 0xF7, 0x36, 0xFE, 0x07, 0x4B, 0x08, 0x49, 0x08, 0x4A, 0x19, 0x60, ++0x13, 0x68, 0x0B, 0x43, 0x13, 0x60, 0x38, 0xBD, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x8C, 0xA4, 0x07, 0x35, ++0x60, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x74, 0x80, 0x32, 0x40, 0x0D, 0x49, 0x0E, 0x48, ++0x38, 0xB5, 0x02, 0x68, 0x4B, 0x68, 0x0D, 0x4C, 0x0D, 0x4D, 0x22, 0xF0, 0x02, 0x02, 0x23, 0x43, 0x02, 0x60, 0x0C, 0x60, ++0x00, 0x20, 0x2B, 0x60, 0xFC, 0xF7, 0x10, 0xFE, 0x09, 0x4B, 0x0A, 0x4A, 0x0A, 0x49, 0x19, 0x60, 0x13, 0x68, 0x23, 0xF4, ++0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x38, 0xBD, 0x00, 0xBF, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, ++0x8C, 0x84, 0x03, 0x35, 0x60, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, ++0x00, 0xEB, 0x80, 0x03, 0xC0, 0xEB, 0x03, 0x10, 0x04, 0x4B, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0x90, 0xF8, 0xA5, 0x01, ++0x21, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x68, 0x65, 0x17, 0x00, 0x00, 0xEB, 0x80, 0x03, 0xC0, 0xEB, 0x03, 0x10, ++0x04, 0x4B, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0x90, 0xF8, 0xA4, 0x01, 0x21, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, ++0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x37, 0x4A, 0x37, 0x4B, 0x92, 0xF8, 0x30, 0x10, 0x1B, 0x68, 0x00, 0x29, 0x45, 0xD1, ++0x00, 0x28, 0x40, 0xD0, 0x9B, 0xB2, 0x01, 0x21, 0x80, 0xEA, 0xE0, 0x76, 0x00, 0x28, 0x4F, 0xEA, 0x83, 0x23, 0x82, 0xF8, ++0x30, 0x10, 0xA6, 0xEB, 0xE0, 0x76, 0x4E, 0xDD, 0xB6, 0xEB, 0x53, 0x0F, 0x23, 0xFA, 0x01, 0xF4, 0x98, 0xBF, 0x04, 0x46, ++0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x29, 0x49, 0x01, 0x20, 0x08, 0x60, 0x28, 0x4D, 0x29, 0x4F, ++0x29, 0x68, 0x29, 0x48, 0x01, 0x31, 0x00, 0x68, 0x29, 0x60, 0x39, 0x69, 0x00, 0x2C, 0x4F, 0xEA, 0x40, 0x17, 0x01, 0xEB, ++0x40, 0x11, 0x4F, 0xEA, 0x93, 0x00, 0x25, 0xDD, 0xB8, 0x42, 0x1A, 0xD8, 0x64, 0x36, 0xDB, 0x1B, 0x9E, 0x42, 0x31, 0xD9, ++0x20, 0x4B, 0x94, 0x62, 0x09, 0x1A, 0xD3, 0xF8, 0xE0, 0x31, 0x1F, 0x48, 0x98, 0x47, 0x2B, 0x68, 0x43, 0xB1, 0x18, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x1B, 0xB9, 0x12, 0xB1, 0x62, 0xB6, 0x00, 0xE0, 0x04, 0x46, 0x20, 0x46, 0xF8, 0xBD, ++0x00, 0x24, 0x20, 0x46, 0xF8, 0xBD, 0x15, 0x4E, 0x94, 0x62, 0x19, 0x44, 0x09, 0x1A, 0xD6, 0xF8, 0xE0, 0x31, 0x13, 0x48, ++0x98, 0x47, 0xE6, 0xE7, 0x30, 0x44, 0xB8, 0x42, 0x0E, 0xD3, 0x0F, 0x4B, 0x0F, 0x48, 0xD3, 0xF8, 0xE0, 0x31, 0x94, 0x62, ++0x64, 0x31, 0x98, 0x47, 0xDB, 0xE7, 0x5C, 0x08, 0xB6, 0xEB, 0x53, 0x0F, 0x8C, 0xBF, 0x64, 0x42, 0x04, 0x46, 0xAF, 0xE7, ++0x20, 0x46, 0xFE, 0xF7, 0x57, 0xFD, 0xD0, 0xE7, 0x98, 0x9C, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x40, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xB8, 0x9C, 0x17, 0x00, ++0x13, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x0E, 0xDB, 0x11, 0x4B, 0xDB, 0x7F, 0x2B, 0xB1, ++0x10, 0x4A, 0x93, 0x7C, 0x52, 0x7C, 0x13, 0x44, 0x01, 0x2B, 0x11, 0xDD, 0x0E, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, ++0x60, 0x31, 0x18, 0x47, 0x00, 0x20, 0x0A, 0xF0, 0xED, 0xFB, 0x03, 0x28, 0xEB, 0xD0, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF2, ++0x06, 0x72, 0x0C, 0xF0, 0x25, 0xFA, 0xE4, 0xE7, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x0A, 0xF0, 0x36, 0xBB, ++0x38, 0x36, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC4, 0x9A, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x39, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x61, 0xDB, ++0x37, 0x49, 0x04, 0x20, 0x0B, 0xF0, 0xDC, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x34, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0xFC, 0x80, 0x32, 0x4C, 0xD8, 0xF8, 0x00, 0x30, 0x32, 0x4D, 0x01, 0x33, 0x00, 0x22, ++0xC8, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x22, 0x60, 0x2F, 0x69, 0x03, 0xF0, 0x0F, 0x09, 0x47, 0xF2, 0x30, 0x56, 0x05, 0xE0, ++0xF6, 0xF7, 0x22, 0xFB, 0x2B, 0x69, 0xDB, 0x1B, 0xB3, 0x42, 0x2C, 0xD8, 0x23, 0x68, 0x19, 0x07, 0xF6, 0xD1, 0x28, 0x4A, ++0x28, 0x48, 0x53, 0x68, 0x28, 0x49, 0x04, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x53, 0x60, 0x0B, 0x68, 0xB9, 0xF1, 0x00, 0x0F, ++0x22, 0xD1, 0x25, 0x4B, 0x25, 0x49, 0x04, 0x20, 0x18, 0x60, 0x0B, 0xF0, 0xA7, 0xFF, 0x24, 0x4B, 0x93, 0xF8, 0x5A, 0x30, ++0x0B, 0xBB, 0x03, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0xE1, 0xFA, 0x21, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x21, 0x51, 0x82, ++0x3B, 0xB1, 0x15, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, ++0xF8, 0x83, 0x1A, 0x49, 0x04, 0x20, 0x0B, 0xF0, 0x8B, 0xFF, 0xC4, 0xE7, 0x23, 0x40, 0x5A, 0x07, 0xD9, 0xD4, 0x02, 0x68, ++0x0B, 0x68, 0x13, 0x40, 0x5B, 0x07, 0xFA, 0xD5, 0xD3, 0xE7, 0xF6, 0xF7, 0x07, 0xFB, 0xDA, 0xE7, 0x00, 0x20, 0x0A, 0xF0, ++0x65, 0xFB, 0x04, 0x28, 0x98, 0xD1, 0x10, 0x49, 0x10, 0x48, 0x40, 0xF2, 0x14, 0x72, 0x0C, 0xF0, 0x9D, 0xF9, 0x91, 0xE7, ++0x38, 0x36, 0x17, 0x00, 0x14, 0x9B, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, ++0x1C, 0x9E, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x28, 0x9B, 0x15, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x5C, 0x9A, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x9A, 0x15, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x24, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x31, 0xDB, 0x00, 0x20, ++0x0A, 0xF0, 0x32, 0xFB, 0x02, 0x28, 0x05, 0xD0, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0x82, 0xBA, ++0x1C, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x19, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x19, 0x4C, 0x23, 0x68, 0x4F, 0xF0, 0x80, 0x60, 0x01, 0x33, 0x23, 0x60, 0x0A, 0xF0, 0x85, 0xFC, 0x16, 0x4B, ++0x1B, 0x68, 0x5B, 0x07, 0x02, 0xD5, 0x15, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xDC, 0xD0, 0x0F, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x00, 0x2B, 0xD6, 0xD1, 0x00, 0x2A, 0xD4, 0xD0, 0x62, 0xB6, 0xD2, 0xE7, 0x00, 0x20, ++0x0A, 0xF0, 0x00, 0xFB, 0x03, 0x28, 0x04, 0xD0, 0x00, 0x20, 0x0A, 0xF0, 0xFB, 0xFA, 0x00, 0x28, 0xC3, 0xD1, 0x09, 0x49, ++0x09, 0x48, 0x40, 0xF2, 0x4F, 0x72, 0x0C, 0xF0, 0x33, 0xF9, 0xBC, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x3C, 0x9B, 0x15, 0x00, 0x08, 0xB5, 0x00, 0x20, 0x0A, 0xF0, 0xDE, 0xFA, 0x04, 0x28, 0x00, 0xD0, 0x08, 0xBD, 0xBD, 0xE8, ++0x08, 0x40, 0x01, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0x2D, 0xBA, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x78, 0xA0, ++0xDA, 0xF8, 0x1C, 0x33, 0x17, 0x46, 0x05, 0x46, 0x0E, 0x46, 0x98, 0x47, 0x04, 0x46, 0x60, 0xBB, 0x96, 0xF8, 0x00, 0x90, ++0x16, 0x4A, 0x95, 0xF8, 0x19, 0x80, 0xDA, 0xF8, 0xB0, 0x31, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x09, 0x29, 0x41, 0x46, ++0x89, 0xF8, 0x5D, 0x02, 0xA9, 0xF8, 0x5E, 0x02, 0x30, 0x78, 0x98, 0x47, 0x38, 0x70, 0xD9, 0xF8, 0x2C, 0x30, 0x2B, 0xB1, ++0xDA, 0xF8, 0xB0, 0x21, 0x93, 0xF8, 0x23, 0x00, 0x69, 0x7E, 0x90, 0x47, 0x0A, 0x49, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x08, 0x11, 0x91, 0xF8, 0x62, 0x30, 0x43, 0xB9, 0x33, 0x78, 0x81, 0xF8, 0x6C, 0x30, 0x6B, 0x7F, 0x81, 0xF8, 0x6D, 0x30, ++0xAB, 0x7F, 0x81, 0xF8, 0x6E, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x7C, 0x4E, 0x7D, 0x4C, 0x4F, 0xF4, 0x1E, 0x77, 0x07, 0xFB, 0x00, 0x67, ++0x4F, 0xF0, 0x4F, 0x08, 0x46, 0x23, 0x18, 0xFB, 0x00, 0x38, 0x97, 0xF8, 0x22, 0xB0, 0x85, 0xB0, 0x05, 0x46, 0x06, 0xEB, ++0xC8, 0x08, 0x4F, 0xF0, 0x00, 0x09, 0xD7, 0xF8, 0x08, 0x32, 0x5F, 0xFA, 0x89, 0xFA, 0xA8, 0xF1, 0x28, 0x01, 0x4F, 0xF0, ++0x80, 0x42, 0x09, 0xF1, 0x01, 0x09, 0x50, 0x46, 0x13, 0xB1, 0xD4, 0xF8, 0x84, 0x33, 0x98, 0x47, 0xD7, 0xF8, 0x30, 0x32, ++0x41, 0x46, 0x08, 0x37, 0x08, 0xF1, 0x08, 0x08, 0x4F, 0xF0, 0x80, 0x42, 0x50, 0x46, 0x13, 0xB1, 0xD4, 0xF8, 0x84, 0x33, ++0x98, 0x47, 0xB9, 0xF1, 0x05, 0x0F, 0xE0, 0xD1, 0x65, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x33, 0x93, 0xF8, ++0x62, 0x10, 0xC1, 0xB9, 0xFF, 0x22, 0x83, 0xF8, 0x6C, 0x20, 0xD4, 0xF8, 0xAC, 0x31, 0x28, 0x46, 0x98, 0x47, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x05, 0x66, 0xF3, 0x6A, 0x23, 0xB1, 0x93, 0xF8, 0x23, 0x00, 0xD4, 0xF8, 0xAC, 0x31, 0x98, 0x47, ++0xD4, 0xF8, 0x24, 0x33, 0x28, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x4F, 0xF4, 0x1E, 0x78, 0x08, 0xFB, ++0x05, 0x62, 0x92, 0xF8, 0x24, 0x90, 0xB9, 0xF1, 0x01, 0x0F, 0x02, 0xD0, 0x02, 0x29, 0xED, 0xD0, 0xDD, 0xE7, 0x93, 0xF8, ++0xDE, 0x20, 0x01, 0x3A, 0xD2, 0xB2, 0x83, 0xF8, 0xDE, 0x20, 0x00, 0x2A, 0xF4, 0xD1, 0x93, 0xF8, 0x63, 0xA0, 0x0A, 0xF1, ++0x0A, 0x0A, 0x5F, 0xFA, 0x8A, 0xFA, 0x08, 0xFB, 0x0A, 0xF3, 0x06, 0xEB, 0x03, 0x08, 0x00, 0x93, 0x98, 0xF8, 0x24, 0x30, ++0x73, 0xB9, 0x44, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x37, 0x38, 0x46, 0x97, 0xF8, 0x63, 0x10, 0xE3, 0x68, ++0x0A, 0x31, 0xC9, 0xB2, 0x98, 0x47, 0x97, 0xF8, 0x62, 0x10, 0xD7, 0xE7, 0x02, 0x23, 0x0C, 0x21, 0x49, 0x20, 0x01, 0x92, ++0x09, 0xF0, 0x64, 0xFF, 0x01, 0x9A, 0x88, 0xF8, 0x24, 0x20, 0x80, 0xF8, 0x00, 0xA0, 0x42, 0x70, 0x09, 0xF0, 0x8C, 0xFF, ++0x98, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0xDE, 0xD1, 0x98, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0xDA, 0xD8, 0x98, 0xF8, 0x22, 0x00, ++0x31, 0x4B, 0xCD, 0xF8, 0x04, 0x90, 0x9E, 0x22, 0xA4, 0x21, 0x11, 0xFB, 0x00, 0x21, 0x2D, 0x4A, 0x03, 0x95, 0x07, 0xFB, ++0x00, 0x27, 0x2B, 0x48, 0x02, 0x97, 0x4F, 0xF0, 0x4F, 0x0C, 0x46, 0x27, 0x1C, 0xFB, 0x0A, 0x77, 0x00, 0xEB, 0xC1, 0x0A, ++0x00, 0x99, 0x28, 0x4A, 0x02, 0x9D, 0xC1, 0x46, 0x88, 0x46, 0x06, 0xEB, 0xC7, 0x07, 0x98, 0x44, 0xD9, 0xF8, 0x08, 0x12, ++0x31, 0xB3, 0xEF, 0xF3, 0x10, 0x81, 0xCB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x21, 0x4B, 0x01, 0x99, 0x19, 0x60, 0x11, 0x68, ++0xA7, 0xF1, 0x28, 0x00, 0x4B, 0x1C, 0xAA, 0xF1, 0x28, 0x01, 0x13, 0x60, 0x00, 0x90, 0x0A, 0xF0, 0xA1, 0xFC, 0xD9, 0xF8, ++0x08, 0x12, 0xD9, 0xF8, 0x0C, 0x32, 0x00, 0x98, 0xC5, 0xF8, 0xC8, 0x14, 0xC5, 0xF8, 0xCC, 0x34, 0x0A, 0xF0, 0xA0, 0xFB, ++0x14, 0x4A, 0x11, 0x68, 0x48, 0x1E, 0x29, 0xB1, 0x13, 0x4B, 0x10, 0x60, 0x19, 0x68, 0x08, 0xB9, 0x01, 0xB1, 0x62, 0xB6, ++0xD9, 0xF8, 0x30, 0x32, 0x50, 0x46, 0x39, 0x46, 0x09, 0xF1, 0x08, 0x09, 0x0A, 0xF1, 0x08, 0x0A, 0x08, 0x35, 0x2B, 0xB1, ++0x0A, 0xF0, 0x80, 0xFC, 0x38, 0x46, 0x0A, 0xF0, 0x87, 0xFB, 0x08, 0x4A, 0x08, 0x37, 0x47, 0x45, 0xC2, 0xD1, 0x40, 0x20, ++0x03, 0x9D, 0x0A, 0xF0, 0xE1, 0xFA, 0x7A, 0xE7, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xC0, 0x67, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x23, 0x04, 0x46, 0x00, 0x22, ++0x06, 0x21, 0x43, 0x20, 0x09, 0xF0, 0xE0, 0xFE, 0x94, 0xF8, 0x63, 0x30, 0x03, 0x70, 0xBD, 0xE8, 0x10, 0x40, 0x09, 0xF0, ++0x09, 0xBF, 0x00, 0xBF, 0x70, 0xB5, 0x90, 0xF9, 0x87, 0x30, 0x04, 0x46, 0x90, 0xF9, 0x86, 0x00, 0x94, 0xF8, 0x88, 0x20, ++0x94, 0xF8, 0x89, 0x60, 0x84, 0xF8, 0x86, 0x10, 0xBB, 0xB1, 0x0D, 0x46, 0x52, 0xB2, 0xAE, 0xB9, 0x88, 0x42, 0x10, 0xDD, ++0x9B, 0x1A, 0x99, 0x42, 0x0D, 0xDA, 0x01, 0x26, 0x00, 0x22, 0x03, 0x23, 0x0C, 0x21, 0x57, 0x20, 0x09, 0xF0, 0xBC, 0xFE, ++0x94, 0xF8, 0x63, 0x20, 0x02, 0x70, 0x46, 0x70, 0x85, 0x70, 0x09, 0xF0, 0xE5, 0xFE, 0x84, 0xF8, 0x89, 0x60, 0x70, 0xBD, ++0x01, 0x2E, 0xFA, 0xD1, 0x88, 0x42, 0xF8, 0xDA, 0x13, 0x44, 0x99, 0x42, 0xF5, 0xDD, 0x00, 0x26, 0xE6, 0xE7, 0x00, 0xBF, ++0x14, 0x4B, 0x93, 0xF9, 0x00, 0x20, 0x22, 0xB3, 0x30, 0xB4, 0x9C, 0x78, 0x90, 0xF9, 0x86, 0x00, 0x93, 0xF9, 0x01, 0x50, ++0x6C, 0xB9, 0x88, 0x42, 0x08, 0xDD, 0x52, 0x1B, 0x91, 0x42, 0x05, 0xDA, 0x0D, 0x49, 0x0A, 0x68, 0x42, 0xF4, 0x00, 0x72, ++0x0A, 0x60, 0x01, 0x24, 0x9C, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x01, 0x2C, 0xFA, 0xD1, 0x88, 0x42, 0xF8, 0xDA, 0x2A, 0x44, ++0x91, 0x42, 0xF5, 0xDD, 0x05, 0x49, 0x0A, 0x68, 0x00, 0x24, 0x22, 0xF4, 0x00, 0x72, 0x0A, 0x60, 0x9C, 0x70, 0x30, 0xBC, ++0x70, 0x47, 0x70, 0x47, 0xA4, 0x1F, 0x17, 0x00, 0xB0, 0xB3, 0x33, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x0C, 0x46, 0x06, 0x46, ++0x80, 0x68, 0x91, 0xF8, 0x8B, 0x10, 0xD0, 0xF8, 0x08, 0x80, 0x60, 0x6F, 0xB6, 0xF8, 0x1C, 0xB0, 0xDF, 0xF8, 0x1C, 0xA1, ++0x87, 0xB0, 0x00, 0x25, 0x05, 0x90, 0x03, 0x92, 0x1F, 0x46, 0x84, 0xF8, 0x78, 0x50, 0x49, 0xB1, 0x94, 0xF8, 0x63, 0x00, ++0xDA, 0xF8, 0xC0, 0x31, 0x01, 0x21, 0x98, 0x47, 0xA4, 0xF8, 0x8A, 0x50, 0x84, 0xF8, 0x8C, 0x50, 0x3A, 0x4B, 0x3B, 0x4D, ++0x1B, 0x68, 0x22, 0x6F, 0x5B, 0x68, 0x01, 0x21, 0x84, 0xF8, 0x85, 0x10, 0x29, 0x69, 0x5B, 0x1A, 0xD3, 0x42, 0x58, 0xD4, ++0x96, 0xF9, 0x2D, 0x10, 0x04, 0x91, 0xE8, 0xF7, 0x35, 0xFB, 0x34, 0x4B, 0x04, 0x99, 0x5B, 0x7C, 0x01, 0x2B, 0x59, 0xD0, ++0xDA, 0xF8, 0x9C, 0x31, 0x20, 0x46, 0xAB, 0xF1, 0x24, 0x05, 0x98, 0x47, 0xAD, 0xB2, 0x00, 0x22, 0x04, 0x21, 0x08, 0xF1, ++0x20, 0x00, 0x0A, 0xF0, 0x19, 0xFC, 0x00, 0x23, 0x01, 0x2D, 0x3B, 0x60, 0x08, 0xF1, 0x24, 0x02, 0x22, 0xD9, 0x04, 0x96, ++0x3E, 0x46, 0x27, 0x46, 0x2C, 0x46, 0x09, 0xE0, 0x32, 0x60, 0xC9, 0xF5, 0x7F, 0x42, 0xFE, 0x32, 0x14, 0x44, 0xA4, 0xB2, ++0x01, 0x2C, 0x05, 0xEB, 0x09, 0x02, 0x10, 0xD9, 0x92, 0xF8, 0x01, 0x90, 0x15, 0x46, 0x09, 0xF1, 0x01, 0x0C, 0xA4, 0x45, ++0x15, 0xF8, 0x02, 0x1B, 0x07, 0xDA, 0x05, 0x29, 0xEA, 0xD0, 0x02, 0x46, 0x49, 0x46, 0x28, 0x46, 0x0A, 0xF0, 0xF4, 0xFB, ++0xE5, 0xE7, 0x3C, 0x46, 0x37, 0x46, 0x04, 0x9E, 0x60, 0x67, 0x3B, 0x68, 0x01, 0x93, 0x03, 0x9B, 0x00, 0x93, 0x32, 0x46, ++0x59, 0x46, 0x40, 0x46, 0x23, 0x46, 0xDA, 0xF8, 0xD0, 0x51, 0xA8, 0x47, 0x04, 0x20, 0x0A, 0xF0, 0xA1, 0xF8, 0x01, 0x28, ++0x04, 0xD0, 0x60, 0x6F, 0x05, 0x9B, 0xC0, 0x1A, 0x18, 0xBF, 0x01, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x22, ++0x94, 0xF8, 0x6C, 0x00, 0x11, 0x46, 0xF7, 0xF7, 0x75, 0xF9, 0x00, 0x28, 0x9E, 0xD1, 0x2B, 0x69, 0x23, 0x67, 0x9B, 0xE7, ++0x20, 0x46, 0xFF, 0xF7, 0x3F, 0xFF, 0x04, 0x99, 0xA0, 0xE7, 0x00, 0xBF, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x00, 0x22, 0x05, 0x46, 0x0C, 0x46, 0x02, 0x23, 0x0C, 0x21, ++0x59, 0x20, 0x09, 0xF0, 0xD3, 0xFD, 0x05, 0x70, 0x44, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x09, 0xF0, 0xFD, 0xBD, 0x00, 0xBF, ++0x08, 0xB5, 0x03, 0x4B, 0x08, 0x46, 0xD3, 0xF8, 0x74, 0x31, 0x98, 0x47, 0x01, 0x20, 0x08, 0xBD, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0xB5, 0x04, 0x4A, 0x08, 0x78, 0xD2, 0xF8, 0x5C, 0x22, 0x19, 0x46, 0x90, 0x47, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x0E, 0x46, 0x2F, 0x20, 0x19, 0x46, 0x02, 0x23, 0x34, 0x78, 0x09, 0xF0, 0xAE, 0xFD, ++0x0D, 0x49, 0x76, 0x78, 0x0D, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x05, 0x46, 0x07, 0xFB, 0x04, 0x10, 0x29, 0x46, 0x90, 0xF8, ++0x65, 0x20, 0x80, 0xF8, 0x66, 0x60, 0x01, 0xF8, 0x01, 0x2F, 0x7F, 0x22, 0xD3, 0xF8, 0x40, 0x33, 0x80, 0xF8, 0x65, 0x20, ++0x2A, 0x46, 0x98, 0x47, 0x28, 0x46, 0x09, 0xF0, 0xC5, 0xFD, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x18, 0x46, 0x38, 0xB5, 0x0D, 0x46, 0x03, 0x23, 0x01, 0x46, 0x0B, 0x20, 0x09, 0xF0, 0x86, 0xFD, ++0x06, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xC4, 0x31, 0xA2, 0x1C, 0x61, 0x1C, 0x28, 0x46, 0x98, 0x47, 0x20, 0x70, 0x20, 0x46, ++0x09, 0xF0, 0xAA, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x0E, 0x4E, 0x0D, 0x46, 0x1C, 0x46, ++0x19, 0x46, 0x28, 0x46, 0xD6, 0xF8, 0x80, 0x30, 0x17, 0x46, 0x98, 0x47, 0x0C, 0xB9, 0x00, 0x20, 0xF8, 0xBD, 0x06, 0x46, ++0x3A, 0x46, 0x21, 0x46, 0x03, 0x23, 0x47, 0x20, 0x09, 0xF0, 0x62, 0xFD, 0x2A, 0x78, 0x02, 0x70, 0x04, 0x22, 0x46, 0x70, ++0x82, 0x70, 0x09, 0xF0, 0x8B, 0xFD, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x0C, 0x46, ++0x76, 0x20, 0x19, 0x46, 0x0C, 0x23, 0x09, 0xF0, 0x4F, 0xFD, 0x23, 0x78, 0x0C, 0x4A, 0x0D, 0x4C, 0x4F, 0xF4, 0x1E, 0x71, ++0x01, 0xFB, 0x03, 0x23, 0x4F, 0xF4, 0xA4, 0x65, 0x93, 0xF8, 0x22, 0x20, 0xD3, 0xF8, 0x48, 0x11, 0x05, 0xFB, 0x02, 0x42, ++0x49, 0x69, 0x92, 0xF8, 0x86, 0x20, 0x02, 0x72, 0x00, 0x24, 0xC0, 0xE9, 0x00, 0x14, 0x09, 0xF0, 0x67, 0xFD, 0x20, 0x46, ++0x38, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xF0, 0xB5, 0x00, 0x22, 0x0D, 0x46, 0x85, 0xB0, ++0x01, 0x23, 0x0C, 0x21, 0x53, 0x20, 0x09, 0xF0, 0x27, 0xFD, 0x01, 0x22, 0x02, 0x70, 0x04, 0x46, 0x28, 0x78, 0x04, 0x28, ++0x28, 0xD8, 0x1D, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x03, 0xB3, 0xAB, 0x78, ++0x23, 0xB3, 0x19, 0x4A, 0x19, 0x49, 0x16, 0x68, 0x09, 0x69, 0x17, 0x68, 0xB0, 0xF8, 0xD2, 0x20, 0xC9, 0x1B, 0x92, 0x02, ++0xEF, 0x68, 0xB6, 0xFB, 0xF2, 0xF6, 0x06, 0xFB, 0x02, 0x22, 0x14, 0x4E, 0x39, 0x44, 0x6F, 0x68, 0xD6, 0xF8, 0x04, 0x62, ++0x01, 0x97, 0x0A, 0x44, 0xA9, 0x68, 0x00, 0x91, 0x02, 0x92, 0xEA, 0x78, 0x00, 0x21, 0xB0, 0x47, 0xFF, 0x28, 0x01, 0xD0, ++0x00, 0x23, 0x23, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x25, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, 0x08, 0x4B, 0x69, 0x78, ++0xD3, 0xF8, 0x08, 0x32, 0x98, 0x47, 0x20, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x19, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, ++0x18, 0x88, 0x17, 0x00, 0xA4, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x19, 0x46, ++0x05, 0x20, 0x1C, 0x23, 0x09, 0xF0, 0xD8, 0xFC, 0x2C, 0x4D, 0x2D, 0x4B, 0x03, 0x60, 0x2A, 0x68, 0x2C, 0x4B, 0x42, 0x60, ++0x1B, 0x68, 0x83, 0x60, 0x0A, 0x22, 0x04, 0x23, 0x83, 0x76, 0x02, 0x83, 0x04, 0x46, 0x00, 0xF1, 0x10, 0x01, 0x0C, 0x30, ++0xE8, 0xF7, 0x9E, 0xF8, 0x26, 0x4B, 0x63, 0x61, 0x2B, 0x68, 0x98, 0x03, 0x24, 0xD4, 0x21, 0x4B, 0x1B, 0x68, 0x99, 0x03, ++0x2C, 0xD4, 0x1F, 0x4B, 0x1B, 0x68, 0x9A, 0x04, 0x03, 0xD5, 0x63, 0x69, 0x43, 0xF4, 0x00, 0x23, 0x63, 0x61, 0xE8, 0xF7, ++0x2F, 0xF9, 0x18, 0xB1, 0x63, 0x69, 0x43, 0xF4, 0x80, 0x33, 0x63, 0x61, 0x17, 0x4B, 0x1B, 0x68, 0x1B, 0x04, 0x22, 0xD4, ++0xE8, 0xF7, 0x2E, 0xF9, 0x63, 0x69, 0x08, 0xB1, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF0, 0x40, 0x53, 0x20, 0x46, 0x63, 0x61, ++0x09, 0xF0, 0xCE, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0xE8, 0xF7, 0x3E, 0xF9, 0x00, 0x28, 0xD6, 0xD0, 0x63, 0x69, 0x43, 0xF4, ++0x00, 0x33, 0x63, 0x61, 0x0A, 0x4B, 0x1B, 0x68, 0x99, 0x03, 0xD2, 0xD5, 0xE8, 0xF7, 0x3A, 0xF9, 0x00, 0x28, 0xCE, 0xD0, ++0x63, 0x69, 0x43, 0xF4, 0x00, 0x13, 0x63, 0x61, 0xC9, 0xE7, 0xE8, 0xF7, 0x03, 0xF9, 0x00, 0x28, 0xD8, 0xD0, 0x63, 0x69, ++0x43, 0xF0, 0x80, 0x43, 0x63, 0x61, 0xD3, 0xE7, 0x04, 0x00, 0x32, 0x40, 0x01, 0x03, 0x04, 0x06, 0x08, 0x00, 0x32, 0x40, ++0x5F, 0xFA, 0x10, 0x00, 0xF0, 0xB5, 0x23, 0x48, 0x4D, 0x79, 0x00, 0x68, 0x8C, 0x79, 0x50, 0xF8, 0x25, 0xC0, 0x21, 0x4F, ++0x0E, 0x68, 0x4F, 0xF4, 0xA4, 0x70, 0x00, 0xFB, 0x04, 0x50, 0x02, 0x30, 0x83, 0xB0, 0x47, 0xF8, 0x20, 0x60, 0x19, 0x46, ++0xBC, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0xCC, 0xF3, 0x0B, 0x03, 0x1B, 0xBB, 0x2C, 0xF4, 0x7F, 0x6C, 0x2C, 0xF0, 0x0F, 0x0C, ++0xC6, 0xF3, 0x0B, 0x06, 0x4C, 0xEA, 0x06, 0x06, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x74, 0x94, 0xF8, 0x64, 0x30, ++0x73, 0xB1, 0x01, 0x2D, 0x1A, 0xD0, 0x02, 0x2D, 0x12, 0xD0, 0xA5, 0xB1, 0x0F, 0x4B, 0x1E, 0x60, 0x0F, 0x4B, 0xD3, 0xF8, ++0xA0, 0x31, 0xCD, 0xE9, 0x00, 0x21, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0x1B, 0x20, 0x09, 0xF0, 0xA5, 0xFC, 0x00, 0x20, ++0x03, 0xB0, 0xF0, 0xBD, 0x66, 0x46, 0xE1, 0xE7, 0x08, 0x4B, 0x1E, 0x60, 0xEC, 0xE7, 0x08, 0x4B, 0x1E, 0x60, 0xE9, 0xE7, ++0x07, 0x4B, 0x1E, 0x60, 0xE6, 0xE7, 0x00, 0xBF, 0xAC, 0x35, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x0C, 0x02, 0x32, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x38, 0xB5, 0x07, 0x48, ++0x8C, 0x78, 0x0D, 0x88, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x04, 0x04, 0x19, 0x46, 0x70, 0x20, 0xA4, 0xF8, 0xBE, 0x54, ++0x09, 0xF0, 0x7A, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0x18, 0x88, 0x17, 0x00, 0x10, 0xB5, 0x08, 0x4C, 0x08, 0x78, 0xD4, 0xF8, ++0xC8, 0x41, 0x82, 0xB0, 0x01, 0x92, 0x00, 0x93, 0xA0, 0x47, 0xDD, 0xE9, 0x00, 0x12, 0x0D, 0x20, 0x09, 0xF0, 0x68, 0xFC, ++0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0x08, 0x78, 0x64, 0x6D, ++0x82, 0xB0, 0x01, 0x92, 0x00, 0x93, 0xA0, 0x47, 0xDD, 0xE9, 0x00, 0x12, 0x3A, 0x20, 0x09, 0xF0, 0x55, 0xFC, 0x00, 0x20, ++0x02, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0C, 0x78, 0x08, 0x46, 0x19, 0x46, 0x24, 0xB1, 0x25, 0x4B, ++0x93, 0xF8, 0xA9, 0x30, 0x00, 0x2B, 0x36, 0xD1, 0x23, 0x4B, 0x24, 0x4E, 0x24, 0x4D, 0x00, 0x24, 0x1C, 0x70, 0x34, 0x68, ++0x24, 0xF0, 0x00, 0x74, 0x34, 0x60, 0x6C, 0x6F, 0x24, 0xF0, 0x10, 0x04, 0x6C, 0x67, 0x1E, 0x4D, 0x2C, 0x68, 0x24, 0xF4, ++0x00, 0x64, 0x2C, 0x60, 0xC4, 0x78, 0x9C, 0x70, 0x84, 0x78, 0x00, 0x25, 0x5D, 0x70, 0xC4, 0xB1, 0x1A, 0x4C, 0x23, 0x68, ++0x43, 0xF0, 0x00, 0x43, 0x23, 0x60, 0x03, 0x79, 0x63, 0xB1, 0x18, 0x4C, 0x85, 0x68, 0x18, 0x4B, 0x25, 0x60, 0x1C, 0x68, ++0xC4, 0xF3, 0x13, 0x04, 0x1C, 0x60, 0xC4, 0x68, 0x18, 0x68, 0x40, 0xEA, 0x04, 0x50, 0x18, 0x60, 0x66, 0x20, 0x09, 0xF0, ++0x17, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x0E, 0x4C, 0x23, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x23, 0x60, 0xE5, 0xE7, 0x08, 0x4B, ++0x08, 0x4E, 0x09, 0x4D, 0x01, 0x24, 0x1C, 0x70, 0x34, 0x68, 0x44, 0xF0, 0x00, 0x74, 0x34, 0x60, 0x6C, 0x6F, 0x44, 0xF0, ++0x10, 0x04, 0x6C, 0x67, 0xC7, 0xE7, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, ++0x00, 0x00, 0x50, 0x40, 0x48, 0x30, 0x34, 0x40, 0xF4, 0x00, 0x60, 0x40, 0xF8, 0x00, 0x60, 0x40, 0x70, 0xB5, 0x08, 0x46, ++0x07, 0x4C, 0x09, 0x68, 0x46, 0x68, 0x05, 0x89, 0xC4, 0xF8, 0xBD, 0x10, 0x78, 0x20, 0x19, 0x46, 0xC4, 0xF8, 0xC1, 0x60, ++0xA4, 0xF8, 0xC5, 0x50, 0x09, 0xF0, 0xE2, 0xFB, 0x00, 0x20, 0x70, 0xBD, 0x2C, 0x19, 0x17, 0x00, 0x38, 0xB5, 0x08, 0x46, ++0x0E, 0x49, 0x44, 0x78, 0x0C, 0x70, 0x84, 0x78, 0x4C, 0x70, 0xC4, 0x78, 0x8C, 0x70, 0x0C, 0x4C, 0x05, 0x79, 0x41, 0x79, ++0x61, 0x70, 0x25, 0x70, 0xC1, 0x79, 0x85, 0x79, 0xA5, 0x70, 0xE1, 0x70, 0x08, 0x4C, 0x41, 0x68, 0x05, 0x68, 0xC4, 0xF8, ++0xCB, 0x10, 0x7A, 0x20, 0x19, 0x46, 0xC4, 0xF8, 0xC7, 0x50, 0x09, 0xF0, 0xC1, 0xFB, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xBF, ++0x68, 0x25, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x48, 0x09, 0x68, 0x01, 0x60, ++0x19, 0x46, 0x72, 0x20, 0x09, 0xF0, 0xB0, 0xFB, 0x00, 0x20, 0x08, 0xBD, 0x34, 0x00, 0x32, 0x40, 0x30, 0xB5, 0x19, 0x46, ++0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x16, 0x4C, ++0x16, 0x4D, 0x23, 0x68, 0x01, 0x33, 0xCD, 0xE9, 0x00, 0x21, 0x23, 0x60, 0x08, 0xF0, 0x12, 0xFA, 0xE7, 0xF7, 0x96, 0xFF, ++0x09, 0xF0, 0x02, 0xFB, 0x0E, 0xF0, 0x22, 0xF8, 0xD5, 0xF8, 0x10, 0x34, 0x98, 0x47, 0xD5, 0xF8, 0xA8, 0x31, 0x98, 0x47, ++0x23, 0x68, 0xDD, 0xE9, 0x00, 0x21, 0x33, 0xB1, 0x08, 0x48, 0x01, 0x3B, 0x00, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x00, 0xB1, ++0x62, 0xB6, 0x01, 0x20, 0x09, 0xF0, 0x7E, 0xFB, 0x00, 0x21, 0x08, 0x46, 0x09, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x03, 0xB0, ++0x30, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x18, 0x46, ++0x21, 0x4E, 0x02, 0x23, 0x0D, 0x46, 0x01, 0x46, 0x25, 0x20, 0x09, 0xF0, 0xFF, 0xFA, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0x46, 0x0C, 0xDB, 0x1C, 0x4B, 0x28, 0x46, 0xD3, 0xF8, 0xB8, 0x31, 0x98, 0x47, 0x00, 0x25, 0x60, 0x70, ++0x25, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x1E, 0xFB, 0x28, 0x46, 0x70, 0xBD, 0x2B, 0x78, 0x05, 0x2B, 0x19, 0xD8, 0x2B, 0x79, ++0x20, 0x2B, 0x0A, 0xD8, 0x95, 0xF8, 0x28, 0x30, 0x05, 0x2B, 0xE8, 0xD9, 0x11, 0x49, 0x12, 0x48, 0x40, 0xF2, 0xFB, 0x62, ++0x0B, 0xF0, 0xBE, 0xFB, 0xE1, 0xE7, 0x0E, 0x49, 0x0F, 0x48, 0x4F, 0xF4, 0xDF, 0x62, 0x0B, 0xF0, 0xB7, 0xFB, 0x33, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE9, 0xDB, 0xD5, 0xE7, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0xF2, 0x62, 0x0B, 0xF0, ++0xAB, 0xFB, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDB, 0xC9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xE4, 0x9B, 0x15, 0x00, 0xBC, 0x9B, 0x15, 0x00, 0x90, 0x9B, 0x15, 0x00, ++0x11, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x70, 0xB5, 0x0C, 0x46, 0x16, 0x46, 0x1D, 0x46, 0x0B, 0xDB, ++0x20, 0x78, 0x0D, 0x4B, 0xD3, 0xF8, 0xB4, 0x31, 0x98, 0x47, 0x32, 0x46, 0x29, 0x46, 0x27, 0x20, 0x09, 0xF0, 0x0A, 0xFB, ++0x00, 0x20, 0x70, 0xBD, 0x08, 0x4B, 0x08, 0x78, 0x1B, 0x68, 0x1B, 0x0E, 0x09, 0x33, 0x98, 0x42, 0xED, 0xDD, 0x06, 0x49, ++0x06, 0x48, 0x40, 0xF2, 0x22, 0x72, 0x0B, 0xF0, 0x75, 0xFB, 0xE5, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xD8, 0x00, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0x14, 0x9C, 0x15, 0x00, 0x16, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x68, ++0x15, 0x4F, 0x0C, 0x46, 0xB0, 0xF9, 0x00, 0x10, 0x25, 0x78, 0x00, 0x29, 0x16, 0x46, 0x98, 0x46, 0x11, 0xDB, 0x4F, 0xF4, ++0xA4, 0x60, 0x00, 0xFB, 0x05, 0x70, 0x62, 0x88, 0xA0, 0xF8, 0x68, 0x20, 0x23, 0x79, 0x80, 0xF8, 0x6A, 0x30, 0x32, 0x46, ++0x41, 0x46, 0x4C, 0x20, 0x09, 0xF0, 0xD4, 0xFA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, ++0x05, 0x72, 0x92, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xE5, 0xD0, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF6, 0x5B, 0x22, 0x0B, 0xF0, ++0x3D, 0xFB, 0xDE, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, ++0x13, 0x4B, 0x70, 0xB5, 0x1B, 0x68, 0x0C, 0x78, 0xB3, 0xF9, 0x00, 0x30, 0x11, 0x4E, 0x00, 0x2B, 0x0D, 0x46, 0x0D, 0xDB, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x63, 0x6A, 0x78, 0x83, 0xF8, 0x87, 0x20, 0xAA, 0x78, 0x83, 0xF8, 0x88, 0x20, ++0x00, 0x20, 0x83, 0xF8, 0x89, 0x00, 0x70, 0xBD, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x63, 0x93, 0xF8, 0x62, 0x30, ++0x00, 0x2B, 0xE9, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF6, 0x78, 0x52, 0x0B, 0xF0, 0x0E, 0xFB, 0xE2, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x20, 0x48, 0x2D, 0xE9, ++0xF0, 0x41, 0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x84, 0xB0, 0x0E, 0x46, 0x15, 0x46, 0x98, 0x46, 0x29, 0xDB, ++0x30, 0x46, 0xE7, 0xF7, 0xAB, 0xFD, 0x00, 0x24, 0x19, 0x4F, 0x00, 0x94, 0x40, 0xF6, 0xB4, 0x13, 0x21, 0x46, 0x1A, 0x46, ++0x20, 0x46, 0xCD, 0xE9, 0x01, 0x44, 0xE7, 0xF7, 0xEB, 0xFD, 0xD7, 0xF8, 0x3C, 0x33, 0x0F, 0x20, 0x98, 0x47, 0x13, 0x4B, ++0xB6, 0xF8, 0x44, 0x20, 0x9A, 0x83, 0x41, 0x46, 0x2A, 0x46, 0x03, 0x20, 0x09, 0xF0, 0x62, 0xFA, 0xD7, 0xF8, 0x60, 0x31, ++0x98, 0x47, 0xD7, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x28, 0x46, 0x02, 0x21, 0x09, 0xF0, 0xEA, 0xFB, 0x20, 0x46, 0x04, 0xB0, ++0xBD, 0xE8, 0xF0, 0x81, 0x10, 0x46, 0x09, 0xF0, 0x8B, 0xFC, 0x00, 0x28, 0xD0, 0xD0, 0x06, 0x49, 0x06, 0x48, 0x4F, 0xF4, ++0xA7, 0x72, 0x0B, 0xF0, 0xC3, 0xFA, 0xC9, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x58, 0x9C, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x46, 0x49, 0x78, 0x16, 0x46, 0x1D, 0x46, 0xE1, 0xB1, ++0x01, 0x29, 0x63, 0x88, 0x3C, 0xD0, 0x02, 0x29, 0x32, 0xD0, 0x03, 0x29, 0x0C, 0xBF, 0x20, 0x48, 0x20, 0x48, 0xA2, 0x88, ++0x18, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x1D, 0xF0, 0x49, 0xFD, 0xE3, 0x88, 0x23, 0xB1, 0x1D, 0x4B, 0x20, 0x78, 0xD3, 0xF8, ++0x80, 0x34, 0x98, 0x47, 0x32, 0x46, 0x29, 0x46, 0x68, 0x20, 0x09, 0xF0, 0x1D, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x04, 0xF1, ++0x08, 0x01, 0x4F, 0xF4, 0x40, 0x72, 0x16, 0x48, 0x1D, 0xF0, 0x34, 0xFD, 0x04, 0xF5, 0x42, 0x71, 0x4F, 0xF4, 0x00, 0x72, ++0x13, 0x48, 0x1D, 0xF0, 0x2D, 0xFD, 0x04, 0xF5, 0xA1, 0x61, 0x80, 0x22, 0x0C, 0x48, 0x1D, 0xF0, 0x27, 0xFD, 0x40, 0x22, ++0x04, 0xF5, 0xB1, 0x61, 0x0A, 0x48, 0x1D, 0xF0, 0x21, 0xFD, 0xD6, 0xE7, 0x0B, 0x48, 0xA2, 0x88, 0x18, 0x44, 0x04, 0xF1, ++0x08, 0x01, 0x1D, 0xF0, 0x19, 0xFD, 0xCE, 0xE7, 0x06, 0x48, 0xA2, 0x88, 0x18, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x1D, 0xF0, ++0x11, 0xFD, 0xC6, 0xE7, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, ++0x1C, 0x16, 0x17, 0x00, 0x38, 0xB5, 0x19, 0x46, 0x81, 0x20, 0x40, 0x23, 0x09, 0xF0, 0x78, 0xF9, 0x00, 0x25, 0x04, 0x46, ++0x08, 0x49, 0x00, 0xF8, 0x01, 0x5B, 0x24, 0x22, 0x1D, 0xF0, 0xF8, 0xFC, 0x23, 0x78, 0x24, 0x33, 0xDB, 0xB2, 0xE2, 0x18, ++0x23, 0x70, 0x20, 0x46, 0x55, 0x70, 0x09, 0xF0, 0x97, 0xF9, 0x28, 0x46, 0x38, 0xBD, 0x00, 0xBF, 0xDC, 0xD1, 0x15, 0x00, ++0x10, 0xB5, 0x82, 0xB0, 0x08, 0x46, 0x1C, 0x46, 0x01, 0x92, 0xFA, 0xF7, 0x83, 0xFA, 0x06, 0x49, 0x4F, 0xF4, 0x80, 0x70, ++0x0B, 0xF0, 0x0E, 0xF8, 0x01, 0x9A, 0x21, 0x46, 0x6C, 0x20, 0x09, 0xF0, 0xB9, 0xF9, 0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, ++0x7C, 0x9C, 0x15, 0x00, 0x25, 0x48, 0x2D, 0xE9, 0xF8, 0x43, 0x00, 0x68, 0xDF, 0xF8, 0xA0, 0x90, 0x0C, 0x46, 0xB0, 0xF9, ++0x00, 0x10, 0x65, 0x79, 0x00, 0x29, 0x17, 0x46, 0x1E, 0x46, 0x2D, 0xDB, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x05, 0xF0, ++0x09, 0xEB, 0x00, 0x08, 0x21, 0x79, 0x98, 0xF8, 0xAC, 0x20, 0x23, 0x68, 0xC8, 0xF8, 0xC4, 0x34, 0x01, 0x2A, 0x88, 0xF8, ++0xC3, 0x14, 0x0A, 0xD1, 0x17, 0x4B, 0xB0, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x48, 0x44, 0x98, 0x47, 0x00, 0x22, 0xD8, 0xF8, ++0xC4, 0x34, 0x88, 0xF8, 0xAC, 0x20, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x05, 0x95, 0x11, 0x49, 0x95, 0xF8, 0xC3, 0x24, ++0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0xD0, 0xFF, 0x3A, 0x46, 0x31, 0x46, 0x62, 0x20, 0x09, 0xF0, 0x7B, 0xF9, 0x00, 0x20, ++0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0x93, 0x93, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xC9, 0xD0, ++0x06, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0x27, 0x62, 0x0B, 0xF0, 0xE4, 0xF9, 0xC2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x8C, 0x9C, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x00, 0xB5, 0x83, 0xB0, 0x08, 0x46, 0x01, 0x92, 0x00, 0x93, 0xFA, 0xF7, 0x45, 0xFA, 0xDD, 0xE9, 0x00, 0x12, 0x6E, 0x20, ++0x09, 0xF0, 0x50, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0xF0, 0xB5, 0x0C, 0x46, 0x0E, 0x78, 0x60, 0x78, ++0x89, 0x78, 0x83, 0xB0, 0x1D, 0x46, 0x01, 0x92, 0x9E, 0xB9, 0xFE, 0xF7, 0xD5, 0xFE, 0x01, 0x9A, 0x00, 0xBB, 0x03, 0x26, ++0x29, 0x46, 0x03, 0x23, 0x2B, 0x20, 0x09, 0xF0, 0xD1, 0xF8, 0x62, 0x78, 0x02, 0x70, 0xA2, 0x78, 0x42, 0x70, 0x86, 0x70, ++0x09, 0xF0, 0xFA, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0xFE, 0xF7, 0xD1, 0xFE, 0x01, 0x9A, 0x00, 0x28, 0xEA, 0xD0, ++0x60, 0x78, 0x14, 0x4B, 0xA1, 0x78, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x00, 0x30, 0x15, 0xF0, 0x9D, 0xFC, 0x02, 0x26, ++0x01, 0x9A, 0xDF, 0xE7, 0x61, 0x78, 0x94, 0xF8, 0x02, 0xC0, 0x0D, 0x48, 0x0D, 0x4F, 0x01, 0xEB, 0x81, 0x03, 0xC1, 0xEB, ++0x03, 0x13, 0x63, 0x44, 0x00, 0xEB, 0xC3, 0x03, 0x4F, 0xF0, 0x9E, 0x0E, 0x93, 0xF8, 0xA5, 0x31, 0x0E, 0xFB, 0x01, 0xC1, ++0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x81, 0x01, 0x07, 0xEB, 0xC3, 0x03, 0x81, 0xF8, 0x5A, 0x61, 0x1E, 0x81, 0x02, 0x26, ++0xC2, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x46, 0x02, 0xF0, 0x0C, 0xFA, ++0x01, 0x20, 0x08, 0xBD, 0x70, 0xB5, 0x48, 0x78, 0xFF, 0x28, 0x0C, 0x46, 0x16, 0x46, 0x1D, 0x46, 0x01, 0xD0, 0x17, 0xF0, ++0xB3, 0xF9, 0x21, 0x78, 0xA0, 0x78, 0x0A, 0x4B, 0x0A, 0x4A, 0x00, 0x39, 0x18, 0xBF, 0x01, 0x21, 0x00, 0x38, 0x18, 0xBF, ++0x01, 0x20, 0x18, 0x70, 0x11, 0x70, 0x02, 0x46, 0x06, 0x48, 0x0A, 0xF0, 0xDD, 0xFE, 0x32, 0x46, 0x29, 0x46, 0x64, 0x20, ++0x09, 0xF0, 0xD8, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0xB9, 0x34, 0x17, 0x00, 0xB8, 0x34, 0x17, 0x00, 0x9C, 0x9C, 0x15, 0x00, ++0xF8, 0xB5, 0x19, 0x46, 0x74, 0x20, 0x06, 0x23, 0x09, 0xF0, 0x62, 0xF8, 0x4F, 0xF4, 0xD2, 0x77, 0x04, 0x46, 0x3B, 0x68, ++0x08, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x06, 0x46, 0x09, 0x20, 0x98, 0x47, 0x36, 0x0C, 0x36, 0x04, 0x56, 0xEA, 0x00, 0x03, ++0x1A, 0xD1, 0x3B, 0x68, 0x07, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x05, 0x46, 0x08, 0x20, 0x98, 0x47, 0x83, 0xB2, 0x19, 0x0A, ++0x28, 0x0A, 0x2A, 0x0C, 0x63, 0x70, 0x2B, 0x0E, 0x21, 0x70, 0x20, 0x71, 0xE2, 0x70, 0xA3, 0x70, 0xEA, 0xB2, 0x07, 0x48, ++0x65, 0x71, 0x0A, 0xF0, 0xA5, 0xFE, 0x20, 0x46, 0x09, 0xF0, 0x6A, 0xF8, 0x00, 0x20, 0xF8, 0xBD, 0x05, 0x04, 0x45, 0xEA, ++0x16, 0x45, 0x03, 0x0C, 0xE7, 0xE7, 0x00, 0xBF, 0xC0, 0x9C, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x46, 0x48, 0x7A, ++0x09, 0x7A, 0x16, 0x46, 0xE2, 0x88, 0x84, 0xB0, 0xCD, 0xE9, 0x00, 0x21, 0x02, 0x90, 0x62, 0x88, 0x5E, 0x48, 0x21, 0x88, ++0x1D, 0x46, 0xA3, 0x88, 0x0A, 0xF0, 0x86, 0xFE, 0xB4, 0xF8, 0x00, 0xC0, 0x67, 0x88, 0xA0, 0x88, 0xE2, 0x88, 0x5A, 0x4B, ++0xBC, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x9E, 0x80, 0x19, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0x0B, 0x68, 0xDF, 0xF8, 0x6C, 0xE1, ++0x03, 0xEA, 0x08, 0x03, 0x43, 0xEA, 0x0C, 0x33, 0x0B, 0x60, 0xDE, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x08, 0x03, 0x43, 0xEA, ++0x0C, 0x33, 0xCE, 0xF8, 0x00, 0x30, 0x00, 0x2F, 0x79, 0xD0, 0x4B, 0x68, 0xDF, 0xF8, 0x44, 0xE1, 0xDF, 0xF8, 0x48, 0xC1, ++0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, 0x07, 0x33, 0x4B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, ++0x07, 0x33, 0xCC, 0xF8, 0x00, 0x30, 0x00, 0x28, 0x3F, 0xD0, 0x8F, 0x68, 0xDF, 0xF8, 0x1C, 0xE1, 0xDF, 0xF8, 0x14, 0xC1, ++0x07, 0xEA, 0x0E, 0x07, 0x47, 0xEA, 0x00, 0x37, 0x8F, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, ++0x00, 0x33, 0xCC, 0xF8, 0x00, 0x30, 0x00, 0x2A, 0x38, 0xD0, 0xC8, 0x68, 0xDF, 0xF8, 0xF4, 0xC0, 0x38, 0x4F, 0x00, 0xEA, ++0x0C, 0x00, 0x40, 0xEA, 0x02, 0x30, 0xC8, 0x60, 0x3B, 0x68, 0x03, 0xEA, 0x0C, 0x03, 0x43, 0xEA, 0x02, 0x33, 0x3B, 0x60, ++0x23, 0x7A, 0x33, 0x4A, 0x00, 0x2B, 0x31, 0xD0, 0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x63, 0x7A, 0x2F, 0x4A, ++0x00, 0x2B, 0x31, 0xD0, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x2C, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, 0x98, 0x47, ++0x32, 0x46, 0x29, 0x46, 0x7F, 0x20, 0x09, 0xF0, 0x17, 0xF8, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x88, 0x68, ++0xDF, 0xF8, 0x9C, 0xC0, 0x25, 0x4F, 0x00, 0xEA, 0x0C, 0x00, 0x88, 0x60, 0x3B, 0x68, 0x03, 0xEA, 0x0C, 0x03, 0x3B, 0x60, ++0x00, 0x2A, 0xC6, 0xD1, 0xCA, 0x68, 0x21, 0x4F, 0x1C, 0x48, 0x3A, 0x40, 0xCA, 0x60, 0x03, 0x68, 0x1B, 0x4A, 0x3B, 0x40, ++0x03, 0x60, 0x23, 0x7A, 0x00, 0x2B, 0xCD, 0xD1, 0x13, 0x68, 0x23, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x63, 0x7A, 0x16, 0x4A, ++0x00, 0x2B, 0xCD, 0xD1, 0x13, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xCC, 0xE7, 0x4F, 0x68, 0xDF, 0xF8, 0x50, 0xE0, ++0xDF, 0xF8, 0x54, 0xC0, 0x07, 0xEA, 0x0E, 0x07, 0x4F, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0xCC, 0xF8, ++0x00, 0x30, 0x88, 0xE7, 0x19, 0x68, 0xDF, 0xF8, 0x34, 0xE0, 0x0B, 0x68, 0xDF, 0xF8, 0x30, 0xC0, 0x03, 0xEA, 0x0E, 0x03, ++0x0B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0xCC, 0xF8, 0x00, 0x30, 0x64, 0xE7, 0xD8, 0x9C, 0x15, 0x00, ++0xAC, 0x35, 0x17, 0x00, 0x0C, 0x02, 0x32, 0x40, 0x24, 0x02, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, ++0xFF, 0x0F, 0x00, 0xF0, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x8A, 0x46, 0x83, 0xB0, ++0x49, 0x7C, 0x28, 0x48, 0xDF, 0xF8, 0xBC, 0x90, 0x27, 0x4F, 0x16, 0x46, 0xDA, 0xF8, 0x0C, 0x20, 0x00, 0x92, 0x01, 0x91, ++0x9A, 0xF8, 0x10, 0xB0, 0xDA, 0xF8, 0x00, 0x10, 0x1D, 0x46, 0xDA, 0xE9, 0x01, 0x23, 0x0A, 0xF0, 0xA5, 0xFD, 0x21, 0x4A, ++0x21, 0x49, 0x9A, 0xF8, 0x11, 0x00, 0x82, 0xF8, 0x05, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0B, 0xF3, 0x03, 0xF1, ++0x08, 0x02, 0x01, 0xEB, 0x02, 0x08, 0x01, 0xEB, 0x03, 0x0B, 0xAA, 0xF1, 0x04, 0x0A, 0x00, 0x24, 0x5A, 0xF8, 0x04, 0x0F, ++0xE3, 0xB2, 0x90, 0xB1, 0x48, 0xF8, 0x24, 0x00, 0x16, 0x4A, 0x9B, 0xF8, 0x64, 0x10, 0x12, 0x68, 0x42, 0xF8, 0x24, 0x00, ++0x49, 0xB1, 0x01, 0x2C, 0x13, 0xD0, 0x02, 0x2B, 0x17, 0xD0, 0x9B, 0xB1, 0x38, 0x60, 0x11, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, ++0x98, 0x47, 0x01, 0x34, 0x04, 0x2C, 0xE5, 0xD1, 0x32, 0x46, 0x29, 0x46, 0x83, 0x20, 0x08, 0xF0, 0x73, 0xFF, 0x00, 0x20, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC9, 0xF8, 0x00, 0x00, 0xEC, 0xE7, 0x08, 0x4B, 0x18, 0x60, 0xE9, 0xE7, 0x08, 0x4B, ++0x18, 0x60, 0xE6, 0xE7, 0x18, 0x9D, 0x15, 0x00, 0x0C, 0x02, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xAC, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, ++0xF8, 0xB5, 0x7C, 0x20, 0x0C, 0x46, 0x19, 0x46, 0x02, 0x23, 0x08, 0xF0, 0xE5, 0xFE, 0x23, 0x78, 0x05, 0x46, 0x00, 0x2B, ++0x5F, 0xD0, 0x35, 0x48, 0x0A, 0xF0, 0x46, 0xFD, 0x34, 0x4B, 0x1B, 0x68, 0x00, 0x22, 0x1A, 0x70, 0x4F, 0xF4, 0xD2, 0x73, ++0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x68, 0x70, 0x62, 0x78, 0x06, 0x46, 0x00, 0x2A, 0x45, 0xD0, 0x2E, 0x4F, 0xC0, 0xF3, ++0x40, 0x11, 0x42, 0x06, 0x87, 0xF8, 0xB4, 0x10, 0x4F, 0xD4, 0x2C, 0x48, 0x0F, 0x22, 0x01, 0x21, 0xE8, 0xF7, 0x1C, 0xFC, ++0x02, 0x22, 0x11, 0x46, 0x29, 0x48, 0xE8, 0xF7, 0x17, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x28, 0x48, 0xE8, 0xF7, 0x12, 0xFC, ++0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x24, 0x48, 0xE8, 0xF7, 0x0C, 0xFC, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x22, 0x48, ++0xE8, 0xF7, 0x06, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x20, 0x48, 0xE8, 0xF7, 0x01, 0xFC, 0x4F, 0xF4, 0x00, 0x52, 0x00, 0x21, ++0x1D, 0x48, 0xE8, 0xF7, 0xFB, 0xFB, 0x97, 0xF8, 0xB4, 0x10, 0x01, 0x22, 0x23, 0x78, 0x6B, 0xB1, 0xE3, 0x78, 0x2B, 0xB1, ++0xB7, 0xF8, 0xAA, 0x30, 0x43, 0xF4, 0x80, 0x43, 0xA7, 0xF8, 0xAA, 0x30, 0x16, 0x48, 0xF3, 0xB2, 0x0A, 0xF0, 0xFA, 0xFC, ++0x97, 0xF8, 0xB4, 0x10, 0x29, 0x70, 0x28, 0x46, 0x08, 0xF0, 0xBC, 0xFE, 0x00, 0x20, 0xF8, 0xBD, 0xA3, 0x78, 0x0B, 0x4F, ++0xC3, 0xF3, 0x40, 0x11, 0x5B, 0x06, 0x87, 0xF8, 0xB4, 0x10, 0xB8, 0xD5, 0xE0, 0xE7, 0x0D, 0x48, 0x0A, 0xF0, 0xE6, 0xFC, ++0x04, 0x4B, 0x1B, 0x68, 0x03, 0x22, 0x1A, 0x70, 0x9E, 0xE7, 0x00, 0x22, 0xD6, 0xE7, 0x00, 0xBF, 0x48, 0x9D, 0x15, 0x00, ++0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x04, 0x20, 0x01, 0x50, 0x04, 0x10, 0x01, 0x50, 0x08, 0x10, 0x01, 0x50, ++0x00, 0x10, 0x01, 0x50, 0x68, 0x9D, 0x15, 0x00, 0x58, 0x9D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x18, 0x46, 0xB1, 0xB0, ++0x0C, 0x46, 0x10, 0x23, 0x01, 0x46, 0x6A, 0x20, 0x04, 0x94, 0x08, 0xF0, 0x59, 0xFE, 0x4F, 0xF4, 0xD2, 0x73, 0x02, 0x46, ++0x1B, 0x68, 0x05, 0x92, 0x06, 0x20, 0x98, 0x47, 0x04, 0x46, 0x01, 0x46, 0x91, 0x48, 0x0A, 0xF0, 0xB5, 0xFC, 0x14, 0xF4, ++0x7F, 0x4F, 0xC4, 0xF3, 0x07, 0x25, 0x6F, 0xD1, 0x26, 0x0E, 0xE5, 0xB2, 0x6E, 0xD0, 0xF4, 0xB2, 0x00, 0x2D, 0x6F, 0xD1, ++0x04, 0x9B, 0x19, 0x7D, 0x00, 0x29, 0x40, 0xF0, 0x83, 0x80, 0x00, 0x2E, 0x40, 0xF0, 0x89, 0x80, 0x59, 0x7D, 0x31, 0xB1, ++0x86, 0x48, 0x0A, 0xF0, 0x9D, 0xFC, 0x04, 0x9B, 0x5C, 0x7D, 0x00, 0x2C, 0x7F, 0xD1, 0x04, 0x9B, 0xDB, 0x68, 0x00, 0x2B, ++0x40, 0xF0, 0x8D, 0x80, 0x04, 0x9B, 0xDF, 0xF8, 0x40, 0xB2, 0x99, 0x68, 0x1A, 0x68, 0x7F, 0x4B, 0xDF, 0xF8, 0x38, 0xA2, ++0xD3, 0xF8, 0x70, 0x32, 0x7D, 0x4C, 0xCD, 0xE9, 0x08, 0x21, 0x08, 0xA8, 0x0A, 0xA9, 0x98, 0x47, 0x1A, 0xAE, 0x6F, 0xF0, ++0x3F, 0x08, 0x09, 0xAF, 0x0A, 0xAB, 0x07, 0x97, 0xA8, 0xEB, 0x03, 0x08, 0x35, 0x46, 0x0D, 0xF1, 0x78, 0x09, 0x06, 0x96, ++0xE3, 0x79, 0x00, 0x93, 0x08, 0xEB, 0x05, 0x02, 0x23, 0x68, 0x03, 0x92, 0x59, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, ++0xBD, 0xFC, 0x15, 0xF8, 0x01, 0x6B, 0x57, 0xF8, 0x04, 0x3F, 0x03, 0x9A, 0x00, 0x96, 0x51, 0x46, 0x23, 0x60, 0xE6, 0x71, ++0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, 0xB0, 0xFC, 0x4D, 0x45, 0x04, 0xF1, 0x10, 0x04, 0xE3, 0xD1, 0xDF, 0xF8, 0xD8, 0xB1, ++0x06, 0x9E, 0x9B, 0xF8, 0xB4, 0x30, 0x00, 0x2B, 0x52, 0xD1, 0xDF, 0xF8, 0xD0, 0xA1, 0x61, 0x4B, 0x00, 0x20, 0xD3, 0xF8, ++0xB0, 0x34, 0x98, 0x47, 0x05, 0x98, 0x5F, 0x4C, 0x5F, 0x4A, 0x60, 0x4B, 0x82, 0x60, 0xC0, 0xE9, 0x00, 0x4A, 0xC3, 0x60, ++0x08, 0xF0, 0x0C, 0xFE, 0x00, 0x20, 0x31, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x23, 0x0E, 0x0B, 0xD1, 0x26, 0x0C, 0xF4, 0xB2, ++0x00, 0x2D, 0x8F, 0xD0, 0x3C, 0xB9, 0x04, 0x9B, 0x59, 0x7D, 0x00, 0x29, 0x40, 0xF0, 0x99, 0x80, 0x00, 0x24, 0x00, 0xE0, ++0xDC, 0xB2, 0x1F, 0x2D, 0x28, 0xBF, 0x1F, 0x25, 0xE9, 0x06, 0x41, 0xEA, 0x85, 0x51, 0x51, 0x4A, 0x51, 0x48, 0xE8, 0xF7, ++0x17, 0xFB, 0x51, 0x48, 0x29, 0x46, 0x0A, 0xF0, 0x23, 0xFC, 0x86, 0xE7, 0x4F, 0x48, 0x0A, 0xF0, 0x1F, 0xFC, 0x04, 0x9B, ++0x1D, 0x7D, 0x00, 0x2E, 0x70, 0xD0, 0x00, 0x2D, 0xE7, 0xD1, 0x3F, 0x2C, 0x21, 0x46, 0x4B, 0x48, 0x28, 0xBF, 0x3F, 0x21, ++0x3F, 0x22, 0x03, 0x91, 0xE8, 0xF7, 0x00, 0xFB, 0x03, 0x99, 0x48, 0x48, 0x0A, 0xF0, 0x0C, 0xFC, 0x04, 0x9B, 0xDB, 0x68, ++0x00, 0x2B, 0x3F, 0xF4, 0x73, 0xAF, 0x04, 0x9B, 0x18, 0x69, 0xEB, 0xF7, 0x6F, 0xF8, 0x6D, 0xE7, 0x42, 0x4A, 0x38, 0x4D, ++0x93, 0x69, 0xD5, 0xF8, 0x28, 0x42, 0xDF, 0xF8, 0x20, 0xA1, 0x40, 0x4F, 0x43, 0xF0, 0x01, 0x03, 0x93, 0x61, 0x04, 0x9B, ++0x5B, 0x68, 0x08, 0x93, 0x41, 0xF2, 0x7C, 0x52, 0x00, 0x23, 0x11, 0x46, 0xCD, 0xE9, 0x00, 0x33, 0x01, 0x20, 0xA0, 0x47, ++0x39, 0x4A, 0x01, 0x23, 0x82, 0xF8, 0x2A, 0x30, 0x0A, 0xA9, 0xD5, 0xF8, 0x70, 0x32, 0x37, 0x4D, 0x08, 0xA8, 0x98, 0x47, ++0x54, 0x46, 0xCD, 0xF8, 0x10, 0xA0, 0xDD, 0xF8, 0x1C, 0xA0, 0xE3, 0x79, 0x00, 0x93, 0x06, 0xEB, 0x08, 0x02, 0x23, 0x68, ++0x03, 0x92, 0x39, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, 0x22, 0xFC, 0x16, 0xF8, 0x01, 0xCB, 0x5A, 0xF8, 0x04, 0x3F, ++0x03, 0x9A, 0xCD, 0xF8, 0x00, 0xC0, 0x29, 0x46, 0x23, 0x60, 0x84, 0xF8, 0x07, 0xC0, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, ++0x13, 0xFC, 0x4E, 0x45, 0x04, 0xF1, 0x10, 0x04, 0xE1, 0xD1, 0x9B, 0xF8, 0xB4, 0x30, 0xDD, 0xF8, 0x10, 0xA0, 0x00, 0x2B, ++0x3F, 0xF4, 0x65, 0xAF, 0x13, 0x4B, 0x00, 0x20, 0xD3, 0xF8, 0x80, 0x34, 0x98, 0x47, 0x1D, 0x4B, 0x1E, 0x49, 0x93, 0xF8, ++0x2A, 0x20, 0x08, 0x20, 0x00, 0x23, 0x0A, 0xF0, 0xFB, 0xFB, 0x5B, 0xE7, 0x59, 0x7D, 0x1C, 0x46, 0x39, 0xB1, 0x0A, 0x48, ++0x0A, 0xF0, 0xA4, 0xFB, 0x64, 0x7D, 0x00, 0x2D, 0x3F, 0xF4, 0x05, 0xAF, 0x6D, 0xE7, 0x00, 0x2D, 0x3F, 0xF4, 0x03, 0xAF, ++0x66, 0xE7, 0x04, 0x48, 0x0A, 0xF0, 0x98, 0xFB, 0x04, 0x9B, 0x5C, 0x7D, 0x63, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x15, 0x00, ++0xBC, 0x9D, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, ++0x00, 0x00, 0xC0, 0xFF, 0x04, 0x88, 0x01, 0x50, 0xD0, 0x9D, 0x15, 0x00, 0xAC, 0x9D, 0x15, 0x00, 0x28, 0x91, 0x01, 0x50, ++0xE4, 0x9D, 0x15, 0x00, 0x00, 0x80, 0x50, 0x40, 0x44, 0x9E, 0x15, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x64, 0x9E, 0x15, 0x00, ++0x9C, 0x77, 0x15, 0x00, 0xFC, 0x9D, 0x15, 0x00, 0x20, 0x9E, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, ++0x38, 0xB5, 0x00, 0x22, 0x0D, 0x46, 0x01, 0x23, 0x0C, 0x21, 0x54, 0x20, 0x08, 0xF0, 0xFA, 0xFC, 0x01, 0x23, 0x03, 0x70, ++0x04, 0x46, 0x28, 0x78, 0x04, 0x28, 0x0D, 0xD8, 0x0C, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, ++0xC0, 0x34, 0x2B, 0xB1, 0x00, 0x23, 0x23, 0x70, 0x69, 0x78, 0x31, 0xB1, 0x06, 0xF0, 0xA2, 0xFB, 0x20, 0x46, 0x08, 0xF0, ++0x13, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x06, 0xF0, 0xBD, 0xFB, 0x20, 0x46, 0x08, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x38, 0xBD, ++0x18, 0x88, 0x17, 0x00, 0x70, 0xB5, 0x10, 0x46, 0x14, 0x46, 0x0D, 0x46, 0x1E, 0x46, 0x08, 0xF0, 0x73, 0xFF, 0x03, 0x28, ++0x25, 0xD0, 0x20, 0x46, 0x08, 0xF0, 0x6E, 0xFF, 0x04, 0x28, 0x20, 0xD0, 0x2A, 0x78, 0x1B, 0x4D, 0x20, 0x46, 0xEA, 0x77, ++0x72, 0xB9, 0x08, 0xF0, 0x65, 0xFF, 0x02, 0x28, 0x17, 0xD0, 0x18, 0x4B, 0xD3, 0xF8, 0x60, 0x31, 0x98, 0x47, 0x23, 0x20, ++0x22, 0x46, 0x31, 0x46, 0x08, 0xF0, 0x20, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x08, 0xF0, 0x56, 0xFF, 0x58, 0xB1, 0x02, 0x28, ++0xF9, 0xD0, 0x10, 0x4B, 0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x20, 0x46, 0x02, 0x21, 0x08, 0xF0, 0xA3, 0xFE, 0x02, 0x20, ++0x70, 0xBD, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x02, 0xDB, 0x00, 0x23, 0x6B, 0x82, 0xE0, 0xE7, ++0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0xF8, 0xD0, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x31, 0x62, 0x0A, 0xF0, 0x76, 0xFD, ++0xF1, 0xE7, 0x00, 0xBF, 0x98, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, ++0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x70, 0xB5, 0x1E, 0x4D, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x0E, 0x46, 0x14, 0x46, 0x1C, 0xDB, 0x20, 0x46, 0x08, 0xF0, 0x1C, 0xFF, 0x58, 0xB1, 0x02, 0x28, 0x08, 0xD0, 0x18, 0x4B, ++0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x20, 0x46, 0x02, 0x21, 0x08, 0xF0, 0x69, 0xFE, 0x02, 0x20, 0x70, 0xBD, 0x2B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x13, 0xDB, 0x20, 0x46, 0x03, 0x21, 0x08, 0xF0, 0x5E, 0xFE, 0x33, 0x68, 0x98, 0x47, ++0x00, 0x20, 0x70, 0xBD, 0x10, 0x46, 0x08, 0xF0, 0xFF, 0xFE, 0x04, 0x28, 0xDD, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, ++0x71, 0x62, 0x0A, 0xF0, 0x37, 0xFD, 0xD6, 0xE7, 0x09, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0xE7, 0xD0, 0x05, 0x49, 0x08, 0x48, ++0x4F, 0xF4, 0xCF, 0x62, 0x0A, 0xF0, 0x2C, 0xFD, 0xE0, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xAC, 0x9E, 0x15, 0x00, 0x38, 0x00, 0x32, 0x40, 0x84, 0x9E, 0x15, 0x00, 0x70, 0xB5, 0x12, 0x4C, ++0x88, 0x78, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x40, 0x82, 0xB0, 0x90, 0xF8, 0x62, 0x40, 0x1E, 0x46, 0x84, 0xB9, ++0x90, 0xF8, 0x6C, 0x00, 0x0C, 0x4D, 0x0C, 0x88, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x00, 0x51, 0xA4, 0x02, 0x8C, 0x60, ++0x31, 0x46, 0x15, 0x20, 0x08, 0xF0, 0x8A, 0xFC, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x06, 0x4C, 0x09, 0x88, 0xD4, 0xF8, ++0x60, 0x44, 0x01, 0x92, 0xA0, 0x47, 0x01, 0x9A, 0xF0, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x88, 0x79, 0x19, 0x4D, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x00, 0xF6, ++0x06, 0xF1, 0x38, 0x00, 0x28, 0x44, 0x35, 0x44, 0x82, 0xB0, 0x90, 0x46, 0x06, 0x22, 0x1F, 0x46, 0x0C, 0x46, 0x1C, 0xF0, ++0x85, 0xFF, 0x95, 0xF8, 0xC0, 0x34, 0x73, 0xB9, 0x10, 0x49, 0x11, 0x4B, 0x20, 0x68, 0xA2, 0x88, 0x08, 0x60, 0x1A, 0x60, ++0x42, 0x46, 0x39, 0x46, 0x19, 0x20, 0x08, 0xF0, 0x57, 0xFC, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x0D, 0xF1, ++0x07, 0x00, 0xFC, 0xF7, 0x9F, 0xFF, 0x00, 0x28, 0xF0, 0xD1, 0x08, 0x49, 0x08, 0x48, 0xD1, 0xE9, 0x00, 0x23, 0x43, 0xF0, ++0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, 0x02, 0x60, 0xE6, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x20, 0x00, 0x32, 0x40, ++0x24, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x0D, 0x46, 0x9E, 0x4F, ++0x95, 0xF8, 0x03, 0xA0, 0x4F, 0xF4, 0xA4, 0x61, 0x89, 0xB0, 0x01, 0xFB, 0x0A, 0xFB, 0x07, 0xEB, 0x0B, 0x06, 0x00, 0x24, ++0x0D, 0xF1, 0x1F, 0x00, 0x90, 0x46, 0x99, 0x46, 0x8D, 0xF8, 0x1F, 0x40, 0xFC, 0xF7, 0x72, 0xFF, 0x96, 0xF8, 0x62, 0x30, ++0xAA, 0x78, 0x86, 0xF8, 0x64, 0x20, 0x04, 0x46, 0x00, 0x2B, 0x40, 0xF0, 0xED, 0x80, 0x96, 0xF8, 0x6C, 0x10, 0x02, 0x91, ++0x00, 0x2A, 0x00, 0xF0, 0x45, 0x81, 0x8E, 0x4A, 0x8E, 0x4B, 0x03, 0x92, 0x8C, 0x46, 0x8E, 0x49, 0x18, 0x69, 0xD2, 0xF8, ++0xE0, 0x31, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x0C, 0x12, 0x0B, 0xF1, 0x18, 0x01, 0x79, 0x18, 0x04, 0x91, 0x91, 0x68, ++0x05, 0x92, 0x41, 0x18, 0x04, 0x98, 0x98, 0x47, 0x05, 0x9A, 0x2B, 0x88, 0x13, 0x84, 0xFC, 0xF7, 0x39, 0xFF, 0x05, 0x9A, ++0x96, 0xF8, 0xC0, 0x14, 0x01, 0x94, 0x13, 0x8C, 0x92, 0xF8, 0x23, 0x20, 0x00, 0x91, 0x4F, 0xF4, 0x80, 0x70, 0x7F, 0x49, ++0x0A, 0xF0, 0x3C, 0xFA, 0x96, 0xF8, 0xC0, 0x34, 0x33, 0xB9, 0x7D, 0x4A, 0x29, 0x88, 0x13, 0x68, 0x9B, 0xB2, 0x43, 0xEA, ++0x01, 0x43, 0x13, 0x60, 0x7A, 0x4B, 0x1B, 0x68, 0x18, 0x04, 0x00, 0xF1, 0xD2, 0x81, 0x79, 0x49, 0x79, 0x4B, 0xB1, 0xF8, ++0x1C, 0xC0, 0x02, 0x99, 0x08, 0x46, 0x72, 0x49, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x00, 0x12, 0x4F, 0xF4, 0xA4, 0x6B, ++0x90, 0x68, 0x02, 0x92, 0x0B, 0xFB, 0x0A, 0x7B, 0x0C, 0xF1, 0x14, 0x0C, 0x00, 0xFB, 0x0C, 0xFC, 0xA3, 0xFB, 0x0C, 0x3C, ++0xDB, 0xF8, 0x04, 0x00, 0x4F, 0xEA, 0x9C, 0x4C, 0x00, 0x23, 0xA2, 0xF8, 0x1E, 0xC0, 0x40, 0xF0, 0x01, 0x00, 0xDF, 0xF8, ++0x90, 0xC1, 0xAB, 0xF8, 0x68, 0x30, 0x8B, 0xF8, 0x6A, 0x30, 0x8B, 0xF8, 0x8C, 0x30, 0x8B, 0xF8, 0x78, 0x30, 0xCB, 0xF8, ++0x74, 0x30, 0xCB, 0xF8, 0x04, 0x00, 0xDC, 0xF8, 0x10, 0x00, 0xCB, 0xF8, 0x70, 0x00, 0x30, 0x46, 0x04, 0xF0, 0xF4, 0xFA, ++0x9B, 0xF8, 0xC0, 0x04, 0x5D, 0x49, 0x00, 0x23, 0x00, 0x28, 0x40, 0xF0, 0x76, 0x81, 0x5D, 0x4B, 0x02, 0x9A, 0x9B, 0x7C, ++0x00, 0x2B, 0x40, 0xF0, 0x8B, 0x81, 0x00, 0x2C, 0x40, 0xF0, 0xD5, 0x81, 0xDF, 0xF8, 0x7C, 0xB1, 0xDB, 0xF8, 0x20, 0x30, ++0x00, 0x2B, 0x40, 0xF0, 0x81, 0x81, 0x9D, 0xF8, 0x1F, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x87, 0x82, 0x53, 0x49, 0x93, 0x68, ++0x0A, 0x68, 0xCB, 0xF8, 0x20, 0x60, 0x12, 0x0C, 0x12, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x13, 0x43, 0x0B, 0x60, 0xDD, 0xE9, ++0x03, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x8B, 0xF8, 0x24, 0x40, 0xD3, 0xF8, 0x60, 0x32, 0x98, 0x47, ++0xAA, 0x78, 0x11, 0x46, 0x30, 0x46, 0x05, 0xF0, 0x5B, 0xFF, 0xAB, 0x78, 0x00, 0x2B, 0x38, 0xD0, 0x45, 0x4B, 0x1B, 0x68, ++0x1A, 0x68, 0x00, 0x2A, 0x00, 0xF0, 0xE0, 0x80, 0x43, 0x49, 0x0A, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0x00, 0xF0, 0xE5, 0x80, ++0xC2, 0xF3, 0x0B, 0x01, 0x00, 0x29, 0x40, 0xF0, 0x4F, 0x81, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x0A, 0x71, 0x22, 0xF4, ++0x7F, 0x62, 0xC9, 0x68, 0x3B, 0x48, 0x22, 0xF0, 0x0F, 0x02, 0xC1, 0xF3, 0x0B, 0x01, 0x0A, 0x43, 0x02, 0x60, 0x9A, 0x68, ++0x00, 0x2A, 0x40, 0xF0, 0xD9, 0x80, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, 0x35, 0x49, 0x12, 0x69, 0x0A, 0x60, ++0xDB, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xD4, 0x80, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x77, 0x30, 0x4B, 0x7A, 0x69, ++0x1A, 0x60, 0x21, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, 0x98, 0x47, 0x42, 0x46, 0x49, 0x46, 0x1F, 0x20, 0x08, 0xF0, 0x30, 0xFB, ++0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x80, 0xB1, 0x22, 0x4B, 0x9C, 0x68, 0x6C, 0xB1, 0x94, 0xF8, 0x62, 0x30, ++0x3B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x23, 0xB1, 0xA6, 0x42, 0x02, 0xD0, 0x94, 0xF8, 0xC0, 0x34, 0x13, 0xB1, 0x24, 0x68, ++0x00, 0x2C, 0xF1, 0xD1, 0x00, 0x2A, 0x00, 0xF0, 0xB2, 0x80, 0x1F, 0x4B, 0x19, 0x6A, 0xA1, 0x42, 0x9D, 0xD1, 0x0E, 0x49, ++0x1D, 0x4C, 0xD1, 0xF8, 0x64, 0x12, 0x00, 0x22, 0x1A, 0x62, 0x83, 0xF8, 0x24, 0x20, 0x88, 0x47, 0x0F, 0x4A, 0x1A, 0x48, ++0xD2, 0xE9, 0x00, 0x13, 0x43, 0xF0, 0x10, 0x03, 0x19, 0x43, 0x01, 0x60, 0x17, 0x48, 0x18, 0x49, 0x20, 0x60, 0x53, 0x60, ++0x0B, 0x68, 0x03, 0x43, 0x0B, 0x60, 0xAA, 0x78, 0x83, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0xD0, 0x9E, 0x15, 0x00, 0x68, 0x00, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x83, 0xDE, 0x1B, 0x43, 0x00, 0x88, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, 0xAC, 0x35, 0x17, 0x00, ++0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x70, 0x80, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x74, 0x80, 0x32, 0x40, 0xAC, 0x4B, 0x03, 0x93, ++0x0B, 0xF1, 0x18, 0x00, 0x38, 0x44, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0xD3, 0xF8, 0xDC, 0x33, 0x98, 0x47, ++0xA7, 0x49, 0x96, 0xF8, 0xC0, 0x24, 0x23, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0x0A, 0xF9, 0xA4, 0x4B, 0x1B, 0x68, ++0x19, 0x04, 0x00, 0xF1, 0xD8, 0x80, 0xA3, 0x4B, 0x9B, 0x7F, 0x3B, 0xB9, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, ++0x82, 0xF8, 0xC3, 0x34, 0xC2, 0xF8, 0xC4, 0x34, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x73, 0x93, 0xF8, 0xC0, 0x34, ++0x00, 0x2B, 0x00, 0xF0, 0x8C, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0x8E, 0x80, 0x98, 0x4B, 0x9C, 0x68, 0x00, 0x2C, 0x00, 0xF0, ++0x89, 0x80, 0x94, 0xF8, 0x62, 0x30, 0x4B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x33, 0xB1, 0xA6, 0x42, 0x04, 0xD0, 0x94, 0xF8, ++0xC0, 0x34, 0x00, 0x2B, 0x00, 0xF0, 0x4A, 0x81, 0x24, 0x68, 0x00, 0x2C, 0xEF, 0xD1, 0x77, 0xE0, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x0A, 0x72, 0x8C, 0x49, 0x92, 0x68, 0x0A, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0x7F, 0xF4, 0x1B, 0xAF, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, 0x88, 0x49, 0xD2, 0x68, 0x0A, 0x60, 0x9A, 0x68, 0x00, 0x2A, 0x3F, 0xF4, 0x27, 0xAF, ++0x85, 0x49, 0x0A, 0x60, 0xDB, 0x68, 0x00, 0x2B, 0x3F, 0xF4, 0x2C, 0xAF, 0x83, 0x4A, 0x13, 0x60, 0x7A, 0x4B, 0xD3, 0xF8, ++0xA0, 0x31, 0x98, 0x47, 0x2F, 0xE7, 0x81, 0x48, 0x81, 0x49, 0x03, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x03, 0x60, 0x0B, 0x6A, ++0x00, 0x2B, 0x7F, 0xF4, 0xE6, 0xAE, 0x00, 0x2C, 0x3F, 0xF4, 0xE3, 0xAE, 0xDF, 0xF8, 0xC4, 0xB1, 0x0C, 0x62, 0x81, 0xF8, ++0x24, 0x20, 0x04, 0xF1, 0x18, 0x00, 0xDB, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xDB, 0xF8, 0x60, 0x32, 0x98, 0x47, 0x76, 0x49, ++0xDF, 0xF8, 0xE4, 0xC1, 0x75, 0x48, 0xD4, 0xF8, 0x38, 0xE0, 0xA4, 0x8F, 0xD1, 0xE9, 0x00, 0x32, 0x22, 0xF0, 0x10, 0x02, ++0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0xC0, 0xF8, 0x00, 0xE0, 0x70, 0x4B, 0x4C, 0xF8, 0x3C, 0x4C, 0x00, 0xF5, 0x00, 0x40, ++0x54, 0x30, 0x6E, 0x4C, 0x1C, 0x60, 0x03, 0x68, 0x4A, 0x60, 0x23, 0xF4, 0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, 0x03, 0x60, ++0x1A, 0xE0, 0xCC, 0xB1, 0x64, 0x4A, 0x10, 0x6A, 0xB0, 0xB1, 0x13, 0x62, 0x82, 0xF8, 0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, ++0x64, 0x32, 0x98, 0x47, 0x60, 0x49, 0x64, 0x48, 0xD1, 0xE9, 0x00, 0x23, 0x43, 0xF0, 0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, ++0x02, 0x60, 0xAA, 0x78, 0x9F, 0xE6, 0x02, 0x2C, 0x65, 0xD0, 0x01, 0x2C, 0x00, 0xF0, 0xC0, 0x80, 0xAA, 0x78, 0x98, 0xE6, ++0x52, 0x49, 0x0A, 0x60, 0x94, 0xE7, 0xE6, 0xF7, 0x1F, 0xFE, 0x00, 0x28, 0x3F, 0xF4, 0x29, 0xAE, 0x02, 0x9A, 0x11, 0x46, ++0x57, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x23, 0x5B, 0x68, 0x9A, 0x06, 0x7F, 0xF5, 0x1E, 0xAE, 0x28, 0x88, ++0xE6, 0xF7, 0x54, 0xFE, 0xF9, 0xF7, 0x9C, 0xF9, 0x51, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0x41, 0xF8, 0x03, 0x9B, ++0xD3, 0xF8, 0xE0, 0x33, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x73, 0x93, 0xF8, 0x62, 0x20, 0x04, 0x2A, ++0x3F, 0xF4, 0x07, 0xAE, 0x93, 0xF8, 0x63, 0x00, 0x03, 0x9B, 0xD3, 0xF8, 0x30, 0x33, 0x98, 0x47, 0xFF, 0xE5, 0xE6, 0xF7, ++0xF1, 0xFD, 0x00, 0x28, 0x3F, 0xF4, 0x23, 0xAF, 0x41, 0x4B, 0x02, 0x99, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0x3B, ++0xDB, 0xF8, 0x04, 0x30, 0x9B, 0x06, 0x7F, 0xF5, 0x18, 0xAF, 0x96, 0xF8, 0x62, 0x30, 0x04, 0x2B, 0x3F, 0xF4, 0x13, 0xAF, ++0x96, 0xF8, 0x63, 0x00, 0x06, 0xF0, 0x2A, 0xFB, 0x0D, 0xE7, 0x01, 0x2C, 0xB0, 0xD1, 0x30, 0x4C, 0x22, 0x6A, 0xB2, 0x42, ++0xAC, 0xD0, 0x23, 0x62, 0x02, 0x93, 0xDD, 0xE9, 0x03, 0x30, 0xD3, 0xF8, 0xD8, 0x21, 0x90, 0x47, 0x02, 0x9B, 0x84, 0xF8, ++0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, 0x64, 0x32, 0x98, 0x47, 0xAA, 0x78, 0x37, 0xE6, 0x26, 0x4C, 0x23, 0x6A, 0x00, 0x2B, ++0x98, 0xD1, 0x1E, 0x4B, 0x98, 0x68, 0x20, 0xB9, 0xA3, 0xE0, 0x00, 0x68, 0x00, 0x28, 0x00, 0xF0, 0xA0, 0x80, 0x90, 0xF8, ++0x62, 0x30, 0x00, 0x2B, 0xF7, 0xD1, 0x90, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF3, 0xD0, 0x86, 0x42, 0xF1, 0xD0, 0x90, 0xF8, ++0xC0, 0x34, 0x00, 0x2B, 0xED, 0xD1, 0x1F, 0x49, 0x17, 0x4A, 0x20, 0x62, 0x9B, 0x46, 0x90, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, ++0x1E, 0x7C, 0x0C, 0xFB, 0x03, 0x13, 0x11, 0x68, 0x9B, 0x68, 0x09, 0x0C, 0x09, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x0B, 0x43, ++0x13, 0x60, 0x03, 0x9B, 0x18, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x84, 0xF8, 0x24, 0xB0, 0xD3, 0xF8, ++0x60, 0x32, 0x98, 0x47, 0xAA, 0x78, 0xFE, 0xE5, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x9F, 0x15, 0x00, 0x04, 0x00, 0x32, 0x40, ++0x64, 0xBA, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, ++0x0C, 0x02, 0x32, 0x40, 0x64, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x20, 0x00, 0x32, 0x40, ++0x70, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x60, 0x00, 0x32, 0x40, 0x68, 0x65, 0x17, 0x00, 0xF0, 0x9E, 0x15, 0x00, ++0x29, 0x4A, 0x11, 0x6A, 0xB1, 0x42, 0x7F, 0xF4, 0x3B, 0xAF, 0x13, 0x62, 0x82, 0xF8, 0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, ++0x64, 0x32, 0x98, 0x47, 0xAA, 0x78, 0xCC, 0xE5, 0xDF, 0xF8, 0x88, 0xB0, 0xDB, 0xF8, 0x20, 0x20, 0x00, 0x2A, 0x7F, 0xF4, ++0x2B, 0xAF, 0x94, 0xF8, 0x6C, 0x30, 0x1F, 0x48, 0x1F, 0x49, 0xCB, 0xF8, 0x20, 0x40, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, ++0x03, 0x03, 0x08, 0x68, 0x9B, 0x68, 0x02, 0x92, 0x00, 0x0C, 0x00, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x03, 0x43, 0x0B, 0x60, ++0x03, 0x9B, 0x04, 0xF1, 0x18, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x02, 0x9A, 0x8B, 0xF8, 0x24, 0x20, ++0xD3, 0xF8, 0x60, 0x32, 0xDF, 0xF8, 0x50, 0xB0, 0x98, 0x47, 0x11, 0x49, 0xDF, 0xF8, 0x4C, 0xC0, 0x10, 0x48, 0xD4, 0xF8, ++0x38, 0xE0, 0xA4, 0x8F, 0xD1, 0xE9, 0x00, 0x23, 0x23, 0xF0, 0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, 0xCB, 0xF8, 0x00, 0x20, ++0xCC, 0xF8, 0x00, 0xE0, 0x04, 0x60, 0xAA, 0x78, 0x8F, 0xE5, 0x01, 0x2B, 0x7F, 0xF4, 0xF2, 0xAE, 0xE1, 0xE6, 0x00, 0x23, ++0x93, 0xF8, 0x6C, 0x30, 0xFF, 0xDE, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x24, 0x00, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x38, 0xB5, 0x07, 0x20, ++0x0C, 0x46, 0x19, 0x46, 0x02, 0x23, 0x08, 0xF0, 0x7F, 0xF8, 0x23, 0x46, 0x07, 0x4D, 0x13, 0xF8, 0x02, 0x1B, 0x22, 0x7A, ++0xD5, 0xF8, 0x58, 0x54, 0x04, 0x46, 0x18, 0x46, 0x63, 0x1C, 0xA8, 0x47, 0x20, 0x70, 0x20, 0x46, 0x08, 0xF0, 0xA0, 0xF8, ++0x00, 0x20, 0x38, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xB5, 0x08, 0x78, 0x03, 0x28, 0x83, 0xB0, 0x19, 0x46, 0x07, 0xD8, ++0xCD, 0xE9, 0x00, 0x23, 0x0C, 0x4B, 0xD3, 0xF8, 0x64, 0x34, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0x0A, 0x4B, 0x9B, 0x68, ++0x33, 0xB1, 0x09, 0x20, 0x08, 0xF0, 0xC0, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x04, 0x4B, 0xD3, 0xF8, ++0xE8, 0x30, 0xCD, 0xE9, 0x00, 0x21, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0xEF, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x78, 0x0C, 0x46, 0x16, 0x46, 0x98, 0x46, 0x00, 0x2D, 0x3B, 0xD1, ++0x91, 0xF8, 0x02, 0xC0, 0x26, 0x49, 0x27, 0x4A, 0x11, 0xF8, 0x0C, 0x00, 0xE1, 0x78, 0x52, 0xF8, 0x20, 0x20, 0x60, 0x78, ++0x24, 0x4F, 0x25, 0x4B, 0x91, 0x42, 0xB8, 0xBF, 0x4A, 0x08, 0x00, 0xEB, 0x80, 0x01, 0xC0, 0xEB, 0x01, 0x11, 0x61, 0x44, ++0x07, 0xEB, 0xC1, 0x01, 0x4F, 0xF0, 0x9E, 0x0E, 0x91, 0xF8, 0xA5, 0x11, 0x0E, 0xFB, 0x00, 0xC0, 0xA8, 0xBF, 0x02, 0xEB, ++0xD2, 0x72, 0x07, 0xEB, 0x80, 0x00, 0xA8, 0xBF, 0xC2, 0xF3, 0x47, 0x02, 0x01, 0xEB, 0x41, 0x01, 0x80, 0xF8, 0x5A, 0x21, ++0x03, 0xEB, 0xC1, 0x01, 0xA2, 0x88, 0x0A, 0x81, 0x32, 0x46, 0x41, 0x46, 0x03, 0x23, 0x29, 0x20, 0x08, 0xF0, 0x0C, 0xF8, ++0x62, 0x78, 0x02, 0x70, 0xA2, 0x78, 0x42, 0x70, 0x85, 0x70, 0x08, 0xF0, 0x35, 0xF8, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, ++0x48, 0x78, 0x0B, 0x49, 0xA2, 0x88, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0x10, 0xA1, 0x78, 0x14, 0xF0, 0xA0, 0xFB, ++0x08, 0xB9, 0x04, 0x25, 0xE2, 0xE7, 0x07, 0x49, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x00, 0x25, 0xDB, 0xE7, ++0xC0, 0xB2, 0x15, 0x00, 0x7C, 0x28, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x54, 0x00, 0x32, 0x40, ++0x2D, 0xE9, 0xF0, 0x43, 0x04, 0x46, 0x87, 0xB0, 0x10, 0x46, 0x15, 0x46, 0x0E, 0x46, 0x1F, 0x46, 0x08, 0xF0, 0x7C, 0xFA, ++0x40, 0xB1, 0x02, 0x38, 0x80, 0xB2, 0x02, 0x28, 0x4D, 0xD8, 0x02, 0x24, 0x20, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, ++0xDF, 0xF8, 0x88, 0x83, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x65, 0xDB, 0x3B, 0x2C, 0x00, 0xF2, ++0xA7, 0x80, 0x05, 0x2C, 0x40, 0xF2, 0xE3, 0x80, 0x06, 0x3C, 0x35, 0x2C, 0x4A, 0xD8, 0xDF, 0xE8, 0x14, 0xF0, 0xBF, 0x01, ++0x49, 0x00, 0xB5, 0x01, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x88, 0x01, 0x49, 0x00, 0x6E, 0x01, ++0x49, 0x00, 0x5A, 0x01, 0x49, 0x00, 0x50, 0x01, 0x49, 0x00, 0x3A, 0x01, 0x49, 0x00, 0x30, 0x01, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0x1D, 0x01, 0x49, 0x00, 0x13, 0x01, 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0xF6, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0xEF, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, ++0x49, 0x00, 0x49, 0x00, 0xE2, 0x00, 0xB1, 0x4B, 0xB1, 0x4C, 0x1B, 0x68, 0x28, 0x46, 0x03, 0xF0, 0x0F, 0x03, 0xE3, 0x74, ++0x08, 0xF0, 0x20, 0xFA, 0xAE, 0x4B, 0xA0, 0x74, 0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x28, 0x46, 0x02, 0x21, 0x08, 0xF0, ++0x6F, 0xF9, 0x9E, 0xE7, 0xDF, 0xF8, 0xA0, 0x82, 0x02, 0x24, 0x98, 0xF8, 0x13, 0x30, 0xA5, 0x4A, 0x1B, 0x01, 0xDB, 0xB2, ++0x13, 0x60, 0x28, 0x46, 0x98, 0xF8, 0x12, 0x10, 0x08, 0xF0, 0x60, 0xF9, 0x20, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, ++0x9E, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x40, 0xF0, 0x6F, 0x81, 0x3B, 0x2C, 0x67, 0xD8, 0x05, 0x2C, 0x67, 0xD9, 0x06, 0x3C, ++0x35, 0x2C, 0x64, 0xD8, 0xDF, 0xE8, 0x14, 0xF0, 0x56, 0x01, 0x63, 0x00, 0x4C, 0x01, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, ++0x63, 0x00, 0x63, 0x00, 0x1F, 0x01, 0x63, 0x00, 0x05, 0x01, 0x63, 0x00, 0xF1, 0x00, 0x63, 0x00, 0xE7, 0x00, 0x63, 0x00, ++0xD1, 0x00, 0x63, 0x00, 0xC7, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0xB4, 0x00, 0x63, 0x00, 0xAA, 0x00, 0x63, 0x00, ++0x97, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x8D, 0x00, 0x63, 0x00, ++0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x86, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, ++0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x79, 0x00, 0x87, 0x2C, 0x3C, 0xD1, ++0xDF, 0xF8, 0xF0, 0x81, 0xDF, 0xF8, 0xF0, 0x91, 0x00, 0x27, 0x88, 0xF8, 0x30, 0x70, 0x30, 0x68, 0xD9, 0xF8, 0xF8, 0x30, ++0x98, 0x47, 0x04, 0x46, 0x00, 0x28, 0x40, 0xF0, 0x19, 0x81, 0x98, 0xF8, 0x31, 0x30, 0x00, 0x2B, 0x97, 0xD0, 0x05, 0xA8, ++0x88, 0xF8, 0x31, 0x40, 0x01, 0xF0, 0x74, 0xFD, 0x00, 0x28, 0x90, 0xD0, 0x05, 0x9A, 0x71, 0x49, 0x92, 0xF8, 0x63, 0x30, ++0x92, 0xF8, 0xC1, 0x04, 0x03, 0xEB, 0xC3, 0x02, 0x03, 0xEB, 0x42, 0x03, 0x01, 0xEB, 0x43, 0x01, 0x05, 0xF0, 0x9C, 0xFF, ++0x81, 0xE7, 0x87, 0x2C, 0xD4, 0xD0, 0x6A, 0x49, 0x6A, 0x48, 0xDF, 0xF8, 0x98, 0x81, 0x40, 0xF6, 0x06, 0x22, 0x09, 0xF0, ++0xCB, 0xFF, 0x02, 0x24, 0x75, 0xE7, 0x87, 0x2C, 0xC8, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xED, 0xDB, 0xDF, 0xF8, 0x78, 0x81, 0x02, 0x24, 0x69, 0xE7, 0x5D, 0x4B, 0xDF, 0xF8, 0x6C, 0x81, 0x9B, 0x6D, 0x30, 0x46, ++0x98, 0x47, 0x2A, 0x46, 0x39, 0x46, 0x3C, 0x20, 0x07, 0xF0, 0x38, 0xFF, 0x00, 0x24, 0x5C, 0xE7, 0x30, 0x46, 0x09, 0xF0, ++0xD3, 0xFF, 0xDF, 0xF8, 0x50, 0x81, 0x00, 0x24, 0x55, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x28, 0x20, 0xFF, 0xF7, ++0x7B, 0xFE, 0xDF, 0xF8, 0x3C, 0x81, 0x04, 0x46, 0x4B, 0xE7, 0x52, 0x4B, 0x32, 0x78, 0x1B, 0x68, 0x51, 0x48, 0xDF, 0xF8, ++0x2C, 0x81, 0xDB, 0xB2, 0x03, 0xFB, 0x02, 0xF3, 0x42, 0xEA, 0x03, 0x23, 0x03, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x21, 0x20, ++0x07, 0xF0, 0x14, 0xFF, 0x00, 0x24, 0x38, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x1E, 0x20, 0xFF, 0xF7, 0xD4, 0xFA, ++0xDF, 0xF8, 0x00, 0x81, 0x04, 0x46, 0x2E, 0xE7, 0x45, 0x48, 0x33, 0x78, 0x02, 0x68, 0xDF, 0xF8, 0xF4, 0x80, 0x9B, 0x03, ++0x22, 0xF4, 0xE0, 0x32, 0x03, 0xF4, 0xE0, 0x33, 0x13, 0x43, 0x03, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x1D, 0x20, 0x07, 0xF0, ++0xF7, 0xFE, 0x00, 0x24, 0x1B, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x18, 0x20, 0xFF, 0xF7, 0x77, 0xFA, 0xDF, 0xF8, ++0xC8, 0x80, 0x04, 0x46, 0x11, 0xE7, 0x73, 0x79, 0xDF, 0xF8, 0xBC, 0x80, 0x36, 0x4A, 0x31, 0x68, 0x92, 0x6A, 0x08, 0xEB, ++0x83, 0x00, 0x41, 0x61, 0x22, 0xB1, 0x12, 0x79, 0x9A, 0x42, 0x04, 0xBF, 0x32, 0x4B, 0x19, 0x60, 0x39, 0x46, 0x2A, 0x46, ++0x17, 0x20, 0x07, 0xF0, 0xD7, 0xFE, 0x00, 0x24, 0xFB, 0xE6, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x14, 0x20, 0xFF, 0xF7, ++0x2B, 0xFA, 0xDF, 0xF8, 0x88, 0x80, 0x04, 0x46, 0xF1, 0xE6, 0x2A, 0x4A, 0x31, 0x78, 0x13, 0x68, 0xDF, 0xF8, 0x78, 0x80, ++0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x39, 0x46, 0x2A, 0x46, ++0x13, 0x20, 0x07, 0xF0, 0xB9, 0xFE, 0x00, 0x24, 0xDD, 0xE6, 0x39, 0x46, 0x02, 0x23, 0x2A, 0x46, 0x11, 0x20, 0x07, 0xF0, ++0x49, 0xFE, 0x72, 0x7A, 0xF3, 0x88, 0xB1, 0x7A, 0x02, 0x91, 0xCD, 0xE9, 0x00, 0x32, 0x04, 0x46, 0xB3, 0x88, 0x72, 0x88, ++0x71, 0x78, 0x30, 0x78, 0xDF, 0xF8, 0x34, 0x80, 0xE6, 0xF7, 0x1E, 0xFA, 0x20, 0x46, 0x07, 0xF0, 0x67, 0xFE, 0x00, 0x24, ++0xC3, 0xE6, 0xDF, 0xF8, 0x24, 0x80, 0x33, 0x68, 0xD8, 0xF8, 0x04, 0x10, 0x11, 0x4A, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0x43, ++0x13, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x0F, 0x20, 0x07, 0xF0, 0x8E, 0xFE, 0x00, 0x24, 0xB2, 0xE6, 0x38, 0x00, 0x32, 0x40, ++0x98, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0xE4, 0x00, 0x32, 0x40, 0xE8, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x30, 0x9D, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, ++0x90, 0x00, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x08, 0x20, ++0xFF, 0xF7, 0x96, 0xFD, 0xDF, 0xF8, 0x2C, 0x81, 0x04, 0x46, 0x8C, 0xE6, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x06, 0x20, ++0xFF, 0xF7, 0x72, 0xFD, 0xDF, 0xF8, 0x18, 0x81, 0x04, 0x46, 0x82, 0xE6, 0xD9, 0xF8, 0x6C, 0x31, 0x30, 0x68, 0x98, 0x47, ++0x3C, 0x46, 0x7C, 0xE6, 0x3F, 0x49, 0x40, 0x48, 0x40, 0xF6, 0xC9, 0x12, 0x09, 0xF0, 0xCA, 0xFE, 0x3B, 0x2C, 0x3F, 0xF6, ++0xFE, 0xAE, 0x05, 0x2C, 0x7F, 0xF6, 0xFD, 0xAE, 0x06, 0x3C, 0x35, 0x2C, 0x3F, 0xF6, 0xF9, 0xAE, 0x01, 0xA3, 0x53, 0xF8, ++0x24, 0xF0, 0x00, 0xBF, 0xBD, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xA9, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x4F, 0xAD, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0x1B, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xF3, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xDF, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xB3, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x9F, 0xAC, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x79, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0x65, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x3F, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0x2B, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x1D, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, ++0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x03, 0xAC, 0x13, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xC0, 0x68, 0xCB, 0x68, 0xC0, 0x1A, 0xC0, 0x0F, ++0x70, 0x47, 0x00, 0xBF, 0x01, 0x48, 0x08, 0xF0, 0xE9, 0xB9, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, 0x06, 0x4B, 0x38, 0xB1, ++0xC1, 0x68, 0x04, 0x22, 0x4F, 0xF4, 0x80, 0x20, 0x98, 0x60, 0x19, 0x63, 0x9A, 0x60, 0x70, 0x47, 0x4F, 0xF4, 0x80, 0x62, ++0x9A, 0x60, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x33, 0x4A, 0xF8, 0xB5, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0x0C, 0x46, ++0x05, 0x46, 0x57, 0xDB, 0x30, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x46, 0xDB, 0xEF, 0xF3, 0x10, 0x83, ++0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2B, 0x4F, 0x2C, 0x4E, 0x3B, 0x68, 0x32, 0x68, ++0x01, 0x33, 0x95, 0x42, 0x3B, 0x60, 0x19, 0xD0, 0x29, 0x46, 0x30, 0x46, 0x08, 0xF0, 0x08, 0xFA, 0x30, 0x46, 0x27, 0x4A, ++0xEC, 0x60, 0x29, 0x46, 0x08, 0xF0, 0x40, 0xFA, 0x30, 0x68, 0x85, 0x42, 0x16, 0xD0, 0x3B, 0x68, 0x23, 0xB1, 0x1F, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0xA3, 0xB1, 0x1A, 0x4B, 0x19, 0x69, 0x64, 0x1A, 0x00, 0x2C, 0x17, 0xDB, 0xF8, 0xBD, ++0x30, 0x46, 0x08, 0xF0, 0xE3, 0xF9, 0x30, 0x46, 0x1A, 0x4A, 0xEC, 0x60, 0x29, 0x46, 0x08, 0xF0, 0x27, 0xFA, 0x30, 0x68, ++0x18, 0x4B, 0xD3, 0xF8, 0xDC, 0x31, 0x98, 0x47, 0xE3, 0xE7, 0x00, 0x2A, 0xE8, 0xD0, 0x62, 0xB6, 0x0E, 0x4B, 0x19, 0x69, ++0x64, 0x1A, 0x00, 0x2C, 0xE7, 0xDA, 0xBD, 0xE8, 0xF8, 0x40, 0x4F, 0xF0, 0x80, 0x40, 0x08, 0xF0, 0xE3, 0xB8, 0x09, 0x4B, ++0x1B, 0x69, 0xE3, 0x1A, 0x00, 0x2B, 0xB3, 0xDA, 0x0D, 0x49, 0x0E, 0x48, 0x7D, 0x22, 0x09, 0xF0, 0xCF, 0xFD, 0xAD, 0xE7, ++0x13, 0x69, 0x41, 0x68, 0x0B, 0x48, 0x22, 0x46, 0x09, 0xF0, 0x4E, 0xFB, 0xA0, 0xE7, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, ++0x38, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, 0xE9, 0xAE, 0x13, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x74, 0x9F, 0x15, 0x00, 0x4C, 0x9F, 0x15, 0x00, 0x38, 0xB5, 0x01, 0x46, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0F, 0x4C, 0x10, 0x4D, ++0x23, 0x68, 0x2A, 0x68, 0x01, 0x33, 0x8A, 0x42, 0x23, 0x60, 0x28, 0x46, 0x0B, 0xD0, 0x08, 0xF0, 0x99, 0xF9, 0x23, 0x68, ++0x33, 0xB1, 0x08, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x08, 0xF0, ++0x81, 0xF9, 0x06, 0x4B, 0x28, 0x68, 0xD3, 0xF8, 0xDC, 0x31, 0x98, 0x47, 0xED, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x2C, 0x4F, 0x2D, 0x4D, ++0xDF, 0xF8, 0xC8, 0xA0, 0xDF, 0xF8, 0xC0, 0x80, 0x2B, 0x4E, 0xB9, 0x46, 0x01, 0xE0, 0xA0, 0x68, 0x98, 0x47, 0x4F, 0xF0, ++0x80, 0x40, 0x08, 0xF0, 0x9F, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, ++0x00, 0x30, 0x2B, 0x68, 0x3C, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x4C, 0xB3, 0x32, 0x69, 0xE3, 0x68, 0x9B, 0x1A, 0x32, 0x2B, ++0x08, 0xD4, 0xDA, 0xF8, 0xDC, 0x31, 0x20, 0x46, 0x98, 0x47, 0x32, 0x69, 0xE3, 0x68, 0x9B, 0x1A, 0x00, 0x2B, 0x2A, 0xDA, ++0x48, 0x46, 0x08, 0xF0, 0x43, 0xF9, 0x2B, 0x68, 0x33, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0x2B, 0x60, 0x0B, 0xB9, ++0x02, 0xB1, 0x62, 0xB6, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x63, 0x68, 0xCB, 0xDA, 0x00, 0x2B, ++0xC9, 0xD1, 0x11, 0x49, 0x11, 0x48, 0xEB, 0x22, 0x09, 0xF0, 0x3C, 0xFD, 0x63, 0x68, 0xC2, 0xE7, 0xDA, 0xF8, 0xDC, 0x31, ++0x20, 0x46, 0x98, 0x47, 0x2B, 0x68, 0x33, 0xB1, 0x0C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0xBD, 0xE8, 0xF0, 0x87, 0x2B, 0x68, 0x00, 0x2B, 0xFA, 0xD0, 0xF2, 0xE7, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x9F, 0x15, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x11, 0xF4, 0x00, 0x05, 0x04, 0x46, 0x0E, 0xD1, 0x90, 0xF8, ++0x5C, 0x22, 0x1E, 0x49, 0x1E, 0x48, 0x01, 0x32, 0xD2, 0xB2, 0x84, 0xF8, 0x5C, 0x22, 0x09, 0xF0, 0x8D, 0xFA, 0x94, 0xF8, ++0x5C, 0x32, 0x09, 0x2B, 0x15, 0xD8, 0x70, 0xBD, 0x17, 0x49, 0x19, 0x48, 0x09, 0xF0, 0x84, 0xFA, 0x94, 0xF8, 0x23, 0x30, ++0x00, 0x22, 0x0D, 0x2B, 0x84, 0xF8, 0x5C, 0x22, 0xF3, 0xD8, 0x15, 0x49, 0x15, 0x4A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x03, 0x13, 0x12, 0x69, 0xC3, 0xF8, 0x58, 0x22, 0x70, 0xBD, 0x2A, 0x46, 0x08, 0x23, 0x0C, 0x21, 0x7D, 0x20, 0x07, 0xF0, ++0x05, 0xFC, 0x94, 0xF8, 0x23, 0x30, 0x03, 0x70, 0x94, 0xF8, 0x22, 0x30, 0x43, 0x70, 0x06, 0x46, 0x04, 0xF1, 0x26, 0x01, ++0x84, 0xF8, 0x5C, 0x52, 0x02, 0x30, 0x06, 0x22, 0x1B, 0xF0, 0x7E, 0xFF, 0x30, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x07, 0xF0, ++0x21, 0xBC, 0x00, 0xBF, 0x34, 0xA0, 0x15, 0x00, 0x9C, 0x9F, 0x15, 0x00, 0xB4, 0x9F, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x63, 0x30, 0x63, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x0A, 0x33, ++0x04, 0xFB, 0x03, 0xF3, 0x11, 0x46, 0x02, 0xF1, 0x28, 0x04, 0x1C, 0x44, 0x1A, 0x44, 0x83, 0xB0, 0x0B, 0x46, 0xD2, 0xF8, ++0x08, 0x12, 0x00, 0x29, 0x40, 0xF0, 0xA2, 0x80, 0xD2, 0xF8, 0x30, 0x12, 0x08, 0x32, 0x00, 0x29, 0x40, 0xF0, 0x9C, 0x80, ++0xA2, 0x42, 0xF2, 0xD1, 0x57, 0x4A, 0x58, 0x4C, 0xDF, 0xF8, 0x70, 0xB1, 0x4F, 0xF4, 0xA4, 0x61, 0x93, 0xF8, 0x25, 0x60, ++0x2E, 0xB1, 0x93, 0xF8, 0x22, 0x60, 0x01, 0xFB, 0x06, 0x46, 0xB0, 0x42, 0x06, 0xD0, 0x03, 0xF5, 0x1E, 0x73, 0x9A, 0x42, ++0xF2, 0xD1, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x93, 0xF8, 0x23, 0x60, 0x0D, 0x2E, 0x77, 0xD9, 0x4F, 0xF0, 0x00, 0x08, ++0xDB, 0xF8, 0x10, 0xE0, 0x1E, 0x46, 0x03, 0xF1, 0x28, 0x0C, 0xD6, 0xF8, 0x08, 0x72, 0x77, 0xB9, 0xD6, 0xF8, 0x30, 0x72, ++0x08, 0x36, 0x57, 0xB9, 0xB4, 0x45, 0xF6, 0xD1, 0xCE, 0xF5, 0x64, 0x0E, 0x0E, 0xF5, 0x61, 0x4E, 0x0E, 0xF1, 0xC0, 0x0E, ++0x1E, 0xEB, 0x08, 0x0F, 0xDB, 0xD5, 0x90, 0xF8, 0x63, 0x60, 0x93, 0xF8, 0x20, 0xE0, 0x00, 0x96, 0x35, 0x46, 0xC6, 0xEB, ++0x86, 0x17, 0x3C, 0x4E, 0x4F, 0xEA, 0xDE, 0x08, 0x06, 0xEB, 0x87, 0x07, 0x0E, 0xF0, 0x07, 0x0C, 0x01, 0x26, 0x18, 0xF8, ++0x07, 0x90, 0x06, 0xFA, 0x0C, 0xFC, 0x1C, 0xEA, 0x09, 0x0F, 0x07, 0xEB, 0xDE, 0x06, 0x01, 0x96, 0x5F, 0xFA, 0x8C, 0xFA, ++0x0F, 0xFA, 0x85, 0xFE, 0xBD, 0xD1, 0x4A, 0xEA, 0x09, 0x09, 0x08, 0xF8, 0x07, 0x90, 0xB0, 0xF8, 0xD0, 0x90, 0x90, 0xF8, ++0xD8, 0xC0, 0x09, 0xF1, 0x01, 0x09, 0xC4, 0x45, 0xA0, 0xF8, 0xD0, 0x90, 0x3E, 0xD8, 0xAF, 0x00, 0x90, 0xF8, 0xD9, 0x90, ++0xC1, 0x45, 0x0B, 0xD2, 0x00, 0x9D, 0x28, 0x4E, 0x80, 0xF8, 0xD9, 0x80, 0x07, 0xEB, 0x05, 0x0A, 0x06, 0xEB, 0xCA, 0x0A, ++0x01, 0x9E, 0xCA, 0xF8, 0x20, 0x60, 0xC1, 0x46, 0x23, 0x4E, 0x00, 0x9D, 0xCC, 0xF1, 0x06, 0x0C, 0xCC, 0x44, 0x06, 0xEB, ++0xCE, 0x0E, 0x1F, 0xFA, 0x8C, 0xFC, 0x1E, 0x4E, 0xA0, 0xF8, 0xCE, 0xC0, 0xAC, 0xF1, 0x02, 0x08, 0x8E, 0xF8, 0x01, 0x80, ++0x4F, 0xF0, 0x28, 0x0C, 0x2F, 0x44, 0x06, 0xEB, 0xC7, 0x07, 0x0C, 0xFB, 0x05, 0x66, 0x90, 0xF8, 0xD8, 0xC0, 0x8E, 0xF8, ++0x04, 0xC0, 0x14, 0x36, 0x0E, 0xF1, 0x04, 0x0E, 0xC7, 0xF8, 0x0C, 0xE0, 0x7E, 0x60, 0x7C, 0xE7, 0x0D, 0x4D, 0x4F, 0xF4, ++0x1E, 0x77, 0x07, 0xFB, 0x06, 0x56, 0xD6, 0xF8, 0x58, 0x82, 0x81, 0xE7, 0x0F, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x61, 0xE7, ++0x00, 0x9D, 0x0B, 0x4E, 0x05, 0xEB, 0x85, 0x09, 0x08, 0xF0, 0x1E, 0x0C, 0x06, 0xEB, 0xC9, 0x09, 0x67, 0x44, 0x80, 0xF8, ++0xD8, 0xC0, 0xC9, 0xF8, 0x1C, 0x70, 0xAF, 0x00, 0xB2, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x7E, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x3C, 0x4C, 0x18, 0x00, 0x9C, 0x4B, 0x18, 0x00, 0x2C, 0x50, 0x18, 0x00, 0x16, 0x2C, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF8, 0x43, 0x02, 0x88, 0xC3, 0x78, 0x04, 0x46, 0xB2, 0xB9, 0x82, 0x78, 0x00, 0x2A, ++0x40, 0xF0, 0xAD, 0x80, 0x88, 0x48, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x03, 0x83, 0xF8, 0xDA, 0x20, 0x34, 0xF8, ++0x04, 0x1C, 0x42, 0x20, 0x00, 0x22, 0x07, 0xF0, 0x5B, 0xFB, 0xA4, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0xF8, 0x43, 0x07, 0xF0, ++0x69, 0xBB, 0x80, 0x48, 0x80, 0x4D, 0x94, 0xF8, 0x02, 0xE0, 0xC3, 0xEB, 0x83, 0x11, 0x00, 0xEB, 0x81, 0x00, 0x01, 0x26, ++0xC2, 0xF3, 0xC7, 0x01, 0x02, 0xF0, 0x07, 0x02, 0x06, 0xFA, 0x02, 0xF2, 0x0F, 0x5C, 0x0E, 0x18, 0x5F, 0xFA, 0x82, 0xFC, ++0x05, 0xEB, 0xC3, 0x05, 0xBE, 0xF1, 0x00, 0x0F, 0x4D, 0xD0, 0x1C, 0xEA, 0x07, 0x0F, 0xD8, 0xD1, 0xDF, 0xF8, 0xC4, 0xE1, ++0x4F, 0xF4, 0xA4, 0x62, 0x4C, 0xEA, 0x07, 0x07, 0x02, 0xFB, 0x03, 0xE2, 0x37, 0x70, 0xB2, 0xF8, 0xD0, 0x70, 0x92, 0xF8, ++0xD8, 0xC0, 0x01, 0x37, 0x8C, 0x45, 0xA2, 0xF8, 0xD0, 0x70, 0x6C, 0x4F, 0x0A, 0xD9, 0x03, 0xEB, 0x83, 0x0C, 0x01, 0xF0, ++0xFE, 0x08, 0x07, 0xEB, 0xCC, 0x0C, 0x40, 0x44, 0xCC, 0xF8, 0x1C, 0x00, 0x82, 0xF8, 0xD8, 0x80, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x03, 0xE0, 0x4F, 0xEA, 0x83, 0x0C, 0x90, 0xF8, 0xD9, 0x80, 0x88, 0x45, 0x07, 0xD2, 0x0C, 0xEB, 0x03, 0x02, ++0x07, 0xEB, 0xC2, 0x02, 0x80, 0xF8, 0xD9, 0x10, 0x88, 0x46, 0x16, 0x62, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xEE, ++0x0C, 0xEB, 0x03, 0x01, 0x9E, 0xF8, 0xD8, 0x20, 0x2A, 0x71, 0xC2, 0xF1, 0x06, 0x02, 0x28, 0x20, 0x42, 0x44, 0x07, 0xEB, ++0xC1, 0x01, 0x00, 0xFB, 0x03, 0x73, 0x92, 0xB2, 0x2E, 0x1D, 0x14, 0x33, 0x90, 0x1E, 0xCE, 0x60, 0x4B, 0x60, 0xAE, 0xF8, ++0xCE, 0x20, 0x68, 0x70, 0x8D, 0xE7, 0x1C, 0xEA, 0x07, 0x0F, 0x8A, 0xD0, 0xDF, 0xF8, 0x28, 0xE1, 0x4F, 0xF4, 0xA4, 0x68, ++0x08, 0xFB, 0x03, 0xF8, 0x27, 0xEA, 0x02, 0x02, 0x0E, 0xEB, 0x08, 0x0C, 0x32, 0x70, 0xBC, 0xF8, 0xD0, 0x70, 0x01, 0x3F, ++0xBF, 0xB2, 0xAC, 0xF8, 0xD0, 0x70, 0x00, 0x2F, 0x4D, 0xD0, 0x9C, 0xF8, 0xD8, 0x70, 0x01, 0xF0, 0xFE, 0x02, 0x97, 0x42, ++0x29, 0xD0, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE2, 0x92, 0xF8, 0xD9, 0x70, 0x8F, 0x42, 0x35, 0xD0, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE3, 0x93, 0xF8, 0xD8, 0x10, 0x29, 0x71, 0xC1, 0xF1, 0x06, 0x01, 0x39, 0x44, 0x89, 0xB2, ++0x8A, 0x1E, 0xA3, 0xF8, 0xCE, 0x10, 0x6A, 0x70, 0x59, 0xE7, 0x32, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x13, ++0x01, 0x22, 0x83, 0xF8, 0xDA, 0x20, 0x50, 0xE7, 0x3A, 0x5C, 0x07, 0xF1, 0x01, 0x08, 0x00, 0x2A, 0x51, 0xD1, 0x5F, 0xFA, ++0x88, 0xF7, 0x8C, 0xF8, 0xD8, 0x70, 0xFB, 0x2F, 0xF4, 0xD1, 0xFA, 0x22, 0x17, 0x46, 0xDF, 0xF8, 0xA8, 0x90, 0x03, 0xEB, ++0x83, 0x08, 0x4F, 0xF4, 0xA4, 0x6C, 0x09, 0xEB, 0xC8, 0x08, 0x0C, 0xFB, 0x03, 0xEC, 0x02, 0x44, 0xC8, 0xF8, 0x1C, 0x20, ++0x8C, 0xF8, 0xD8, 0x70, 0xC1, 0xE7, 0x41, 0xB3, 0x37, 0x78, 0x01, 0x39, 0xB4, 0x46, 0xC9, 0xB2, 0x01, 0x3E, 0x57, 0xBB, ++0x82, 0xF8, 0xD9, 0x10, 0xF5, 0xE7, 0x0E, 0xF1, 0xD8, 0x02, 0x06, 0x21, 0xAC, 0xF8, 0xCE, 0x10, 0xFF, 0x21, 0x28, 0xF8, ++0x02, 0x10, 0x19, 0x4A, 0x9C, 0xF8, 0xCE, 0x10, 0x2F, 0x71, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x6E, 0x1D, ++0x8A, 0x1E, 0xDE, 0x60, 0x6A, 0x70, 0xE2, 0x78, 0x9C, 0xF8, 0xD9, 0x50, 0x12, 0x49, 0x02, 0xEB, 0x82, 0x02, 0x28, 0x44, ++0x01, 0xEB, 0x82, 0x02, 0x18, 0x62, 0x5A, 0x60, 0x09, 0xE7, 0x0F, 0x46, 0x0C, 0x4A, 0x03, 0xEB, 0x83, 0x01, 0x02, 0xEB, ++0xC1, 0x02, 0x10, 0x62, 0x97, 0xE7, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE2, 0x60, 0x46, 0x92, 0xF8, 0xD9, 0x70, ++0xF0, 0xE7, 0x07, 0xF0, 0xFE, 0x07, 0x3A, 0x46, 0xB1, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x3C, 0x4C, 0x18, 0x00, ++0x2C, 0x50, 0x18, 0x00, 0x9C, 0x4B, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x89, 0x46, 0xD0, 0xF8, ++0xB8, 0x50, 0x89, 0x88, 0x99, 0xF8, 0x08, 0xA0, 0x90, 0xF8, 0x63, 0xB0, 0xD5, 0xF8, 0x24, 0x80, 0x2A, 0x4B, 0xB9, 0xF8, ++0x06, 0x70, 0xD3, 0xF8, 0x54, 0x31, 0x29, 0x4E, 0xA1, 0xEB, 0x0A, 0x0A, 0x04, 0x46, 0x42, 0x46, 0xA0, 0xF8, 0xCC, 0xA0, ++0x58, 0x46, 0x98, 0x47, 0xB9, 0xF8, 0x06, 0x30, 0x6A, 0x6A, 0x21, 0x6C, 0x23, 0x48, 0x03, 0xF1, 0xFF, 0x3C, 0x62, 0x44, ++0xAA, 0x62, 0x99, 0xF8, 0x08, 0xC0, 0x06, 0xEB, 0xCB, 0x06, 0xDB, 0x43, 0x0B, 0xEB, 0x8B, 0x0B, 0x0C, 0xF1, 0x01, 0x0C, ++0x00, 0xEB, 0x8B, 0x0B, 0x62, 0x44, 0x53, 0x44, 0x13, 0x44, 0x00, 0x20, 0xCB, 0xE9, 0x02, 0x23, 0x03, 0x37, 0xCB, 0xF8, ++0x10, 0x00, 0x31, 0xB3, 0x94, 0xF8, 0xC0, 0x34, 0x0A, 0x79, 0x16, 0x49, 0xE3, 0xB1, 0x16, 0x4A, 0x16, 0x48, 0x13, 0x68, ++0x12, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0x00, 0x22, 0x4B, 0x62, 0xC5, 0xE9, 0x0D, 0x21, 0xE8, 0x64, ++0x94, 0xF8, 0x63, 0x30, 0x10, 0x4A, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x01, 0x22, 0x2B, 0x62, 0x84, 0xF8, ++0xD6, 0x20, 0x18, 0xF8, 0x07, 0x30, 0xF3, 0x70, 0xBD, 0xE8, 0xF8, 0x8F, 0x0A, 0x4B, 0x82, 0x42, 0x08, 0xBF, 0x19, 0x46, ++0xDD, 0xE7, 0x04, 0x49, 0xDB, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x50, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, ++0x84, 0x3C, 0x18, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x41, 0x00, 0x00, 0x01, 0x9C, 0x4B, 0x18, 0x00, 0xC4, 0x3C, 0x18, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x4D, 0x4D, 0x90, 0xF8, 0x63, 0x30, 0xD0, 0xF8, 0xB8, 0x80, 0x05, 0xEB, 0xC3, 0x05, 0x04, 0x46, ++0x2F, 0x79, 0x00, 0xF1, 0x6C, 0x06, 0xFF, 0xF7, 0x7D, 0xFD, 0xB0, 0xF8, 0xCC, 0x30, 0xB0, 0xF8, 0xCE, 0x20, 0x13, 0x44, ++0x04, 0x33, 0xC8, 0xF8, 0x2C, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x54, 0xD1, 0x42, 0x4A, 0xD8, 0xF8, 0x24, 0x10, ++0xB2, 0xF8, 0xFC, 0x31, 0x01, 0x33, 0x9B, 0xB2, 0x18, 0x01, 0xA2, 0xF8, 0xFC, 0x31, 0xC8, 0x82, 0x94, 0xF8, 0xD7, 0x30, ++0xAB, 0x70, 0x94, 0xF8, 0xDA, 0x90, 0xCB, 0xBB, 0xB9, 0xF1, 0x00, 0x0F, 0x31, 0xD1, 0x07, 0xF0, 0xFE, 0x07, 0x38, 0x4B, ++0x1B, 0x78, 0x0B, 0xB1, 0x47, 0xF0, 0x01, 0x07, 0xEB, 0x78, 0x84, 0xF8, 0xD7, 0x30, 0x2F, 0x71, 0x94, 0xF8, 0xD7, 0x30, ++0x94, 0xF8, 0xDB, 0x50, 0x01, 0x3B, 0x84, 0xF8, 0xD7, 0x30, 0xBD, 0xB1, 0x01, 0x3D, 0x94, 0xF8, 0xDC, 0x30, 0xED, 0xB2, ++0x84, 0xF8, 0xDB, 0x50, 0x63, 0xB1, 0xD8, 0xF8, 0x24, 0x20, 0xD5, 0x54, 0x94, 0xF8, 0xDD, 0x30, 0x23, 0xB1, 0xD8, 0xF8, ++0x24, 0x20, 0x94, 0xF8, 0xDB, 0x10, 0xD1, 0x54, 0x94, 0xF8, 0xDB, 0x50, 0x7D, 0xBB, 0x01, 0x23, 0x84, 0xF8, 0xDB, 0x30, ++0x20, 0x46, 0x31, 0x46, 0x06, 0xF0, 0xE0, 0xFC, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x47, 0xF0, 0x01, 0x07, 0x4F, 0xF0, ++0x01, 0x09, 0xCA, 0xE7, 0x19, 0xF0, 0x02, 0x09, 0x1A, 0xBF, 0x47, 0xF0, 0x01, 0x07, 0x4F, 0xF0, 0x01, 0x09, 0x07, 0xF0, ++0xFE, 0x07, 0xC8, 0xE7, 0x90, 0xF8, 0xC1, 0x04, 0x05, 0xF0, 0x7E, 0xF9, 0x00, 0x28, 0xA4, 0xD0, 0x94, 0xF8, 0x63, 0x10, ++0x15, 0x4A, 0xD8, 0xF8, 0x2C, 0x30, 0x01, 0xEB, 0x81, 0x01, 0x02, 0xEB, 0x81, 0x02, 0x19, 0x18, 0x93, 0x68, 0xC8, 0xF8, ++0x2C, 0x10, 0x01, 0x3B, 0x18, 0x44, 0xD0, 0x60, 0x93, 0xE7, 0x02, 0x23, 0x00, 0x22, 0x0C, 0x21, 0x4E, 0x20, 0x94, 0xF8, ++0x63, 0x70, 0x07, 0xF0, 0xE3, 0xF8, 0x07, 0x70, 0x45, 0x70, 0x07, 0xF0, 0x0F, 0xF9, 0x94, 0xF8, 0xDB, 0x30, 0x00, 0x2B, ++0xBF, 0xD0, 0x20, 0x46, 0x31, 0x46, 0x06, 0xF0, 0xA3, 0xFC, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x2C, 0x50, 0x18, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x16, 0x2C, 0x17, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0xF8, 0xB5, 0x18, 0x4D, 0x18, 0x4F, 0x2E, 0x68, ++0x04, 0x46, 0x36, 0xF8, 0x04, 0x1C, 0x00, 0x22, 0x40, 0x20, 0x07, 0xF0, 0x29, 0xF9, 0xD7, 0xF8, 0x78, 0x31, 0x29, 0x68, ++0x20, 0x46, 0x98, 0x47, 0x2A, 0x68, 0x00, 0x23, 0x84, 0xF8, 0xDB, 0x30, 0x93, 0x7A, 0x84, 0xF8, 0xDC, 0x30, 0xD2, 0x7A, ++0x84, 0xF8, 0xDD, 0x20, 0x0C, 0x3E, 0xD4, 0xF8, 0xB8, 0x20, 0x23, 0xB1, 0x52, 0x6A, 0xD3, 0x5C, 0x01, 0x33, 0x84, 0xF8, ++0xDB, 0x30, 0x2B, 0x7A, 0x00, 0x22, 0x6A, 0x72, 0x13, 0xB1, 0xD7, 0xF8, 0x84, 0x31, 0x98, 0x47, 0x00, 0x23, 0x30, 0x46, ++0x2B, 0x60, 0xBD, 0xE8, 0xF8, 0x40, 0x07, 0xF0, 0x17, 0xB9, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0xB5, 0x0E, 0x4D, 0x44, 0x7A, 0x0E, 0x4A, 0x0E, 0x49, 0x03, 0x46, 0x4F, 0xF4, 0x1A, 0x70, 0x00, 0xFB, 0x04, 0x50, ++0x01, 0x25, 0x55, 0x72, 0x00, 0x25, 0x95, 0x72, 0x9A, 0x88, 0x68, 0x30, 0x1B, 0xF0, 0x0C, 0xFC, 0x08, 0x4A, 0x09, 0x4B, ++0x4F, 0xF4, 0xA4, 0x60, 0x29, 0x46, 0x00, 0xFB, 0x04, 0x20, 0xD3, 0xF8, 0x94, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, ++0xFC, 0x41, 0x18, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x14, 0x2A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x7E, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x1B, 0x68, 0x7D, 0x4D, 0xB3, 0xF9, 0x00, 0x30, 0x6E, 0x68, 0x00, 0x2B, 0x83, 0xB0, ++0x04, 0x46, 0x44, 0xDB, 0x01, 0x3E, 0x6E, 0x60, 0x00, 0x2E, 0x4D, 0xD0, 0xDF, 0xF8, 0xE0, 0x91, 0x77, 0x4D, 0x78, 0x4E, ++0x78, 0x4F, 0xDF, 0xF8, 0x00, 0xA2, 0xDF, 0xF8, 0x00, 0x82, 0x03, 0xE0, 0x05, 0xF5, 0x1E, 0x75, 0xB5, 0x42, 0x2F, 0xD0, ++0x95, 0xF8, 0x25, 0x20, 0x4F, 0xF4, 0xA4, 0x61, 0x00, 0x2A, 0xF5, 0xD0, 0x95, 0xF8, 0x22, 0x30, 0x01, 0xFB, 0x03, 0x73, ++0x9C, 0x42, 0xEF, 0xD1, 0x95, 0xF8, 0x23, 0x30, 0x0D, 0x2B, 0x9B, 0xBF, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x93, ++0x00, 0x22, 0xD3, 0xF8, 0x58, 0x22, 0xDA, 0xF8, 0x10, 0x30, 0xA8, 0xEB, 0x03, 0x03, 0xD3, 0x42, 0xDE, 0xD5, 0x20, 0x46, ++0xF2, 0xF7, 0x96, 0xFF, 0x00, 0x28, 0xD9, 0xD0, 0x63, 0x49, 0x95, 0xF8, 0x23, 0x00, 0x2A, 0x46, 0xF4, 0xF7, 0xAE, 0xFB, ++0x00, 0x28, 0xD1, 0xD1, 0x95, 0xF8, 0x23, 0x10, 0x5F, 0x48, 0x08, 0xF0, 0x89, 0xFE, 0xCB, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0x2E, 0xB8, 0xD1, 0x5C, 0x49, 0x5C, 0x48, 0x4F, 0xF4, 0x3F, 0x72, 0x09, 0xF0, 0xF7, 0xF8, 0x6E, 0x68, ++0x01, 0x3E, 0x6E, 0x60, 0x00, 0x2E, 0xB1, 0xD1, 0xDF, 0xF8, 0x74, 0xB1, 0xFC, 0xF7, 0xCC, 0xFF, 0x94, 0xF8, 0x63, 0x30, ++0x9B, 0xF8, 0x00, 0x20, 0x03, 0xF1, 0x0A, 0x08, 0x00, 0x2A, 0x58, 0xD1, 0xDF, 0xF8, 0x2C, 0x91, 0x51, 0x4B, 0x1B, 0x78, ++0x53, 0xB3, 0x08, 0xEB, 0x88, 0x02, 0x4F, 0xF4, 0x1E, 0x73, 0xC8, 0xEB, 0x02, 0x12, 0x4E, 0x4F, 0x01, 0x92, 0x03, 0xFB, ++0x08, 0x9B, 0x4F, 0xF0, 0x00, 0x0A, 0xDB, 0xF8, 0x08, 0x32, 0x5F, 0xFA, 0x8A, 0xF6, 0x0B, 0xF5, 0x02, 0x78, 0x53, 0xB1, ++0x40, 0x46, 0x07, 0xF0, 0xBB, 0xFC, 0xD7, 0xF8, 0x24, 0x34, 0x31, 0x46, 0x98, 0x47, 0xDB, 0xF8, 0x08, 0x32, 0x00, 0x2B, ++0xF4, 0xD1, 0xDB, 0xF8, 0x30, 0x22, 0x00, 0x2A, 0x5B, 0xD1, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x04, 0x0F, 0x0B, 0xF1, ++0x08, 0x0B, 0xE2, 0xD1, 0x3B, 0x4B, 0x1A, 0x70, 0xAB, 0x7A, 0x03, 0xBB, 0xEB, 0x68, 0x63, 0xB1, 0x39, 0x4F, 0xDF, 0xF8, ++0xF8, 0x80, 0xD7, 0xF8, 0xD4, 0x61, 0x40, 0x46, 0x07, 0xF0, 0x9A, 0xFC, 0x0C, 0x30, 0xB0, 0x47, 0xEB, 0x68, 0x00, 0x2B, ++0xF5, 0xD1, 0x94, 0xF8, 0x63, 0x00, 0x05, 0x44, 0x29, 0x7D, 0x19, 0xB1, 0x30, 0x4B, 0xD3, 0xF8, 0x90, 0x31, 0x98, 0x47, ++0x94, 0xF8, 0xDB, 0x30, 0x01, 0x2B, 0x7F, 0xF4, 0x59, 0xAF, 0x20, 0x46, 0xFB, 0xF7, 0xBE, 0xFA, 0x54, 0xE7, 0x2A, 0x4F, ++0x28, 0x68, 0xD7, 0xF8, 0x8C, 0x31, 0x98, 0x47, 0xD8, 0xE7, 0x04, 0x23, 0x32, 0x46, 0x0C, 0x21, 0x4A, 0x20, 0x06, 0xF0, ++0xA5, 0xFF, 0x80, 0xF8, 0x00, 0x80, 0x46, 0x70, 0x86, 0x70, 0x06, 0xF0, 0xCF, 0xFF, 0x9B, 0xF8, 0x00, 0x30, 0xDF, 0xF8, ++0x60, 0x90, 0x00, 0x2B, 0x96, 0xD0, 0x4F, 0xF4, 0x1E, 0x7A, 0x0A, 0xFB, 0x08, 0x9A, 0x9A, 0xF8, 0x31, 0x30, 0x9B, 0x07, ++0x0B, 0xD5, 0x1A, 0x4F, 0x09, 0x22, 0x8A, 0xF8, 0x32, 0x20, 0xD7, 0xF8, 0x20, 0x33, 0x32, 0x46, 0x51, 0x46, 0x20, 0x46, ++0x98, 0x47, 0x8A, 0xF8, 0x32, 0x60, 0x00, 0x23, 0x8B, 0xF8, 0x00, 0x30, 0x7E, 0xE7, 0x01, 0x98, 0x46, 0x30, 0x50, 0x44, ++0x09, 0xEB, 0xC0, 0x00, 0x07, 0xF0, 0x4C, 0xFC, 0x0E, 0x4B, 0x31, 0x46, 0xD3, 0xF8, 0x24, 0x34, 0x98, 0x47, 0x0D, 0x48, ++0x08, 0xF0, 0xDA, 0xFD, 0xFE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x7E, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x51, 0xB1, 0x13, 0x00, 0xF8, 0x9F, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0x9F, 0x15, 0x00, 0x16, 0x2C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xDC, 0x9F, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, ++0xC0, 0xE1, 0xE4, 0x00, 0x10, 0x2A, 0x17, 0x00, 0xE4, 0x9C, 0x17, 0x00, 0x38, 0xB5, 0x0E, 0x4D, 0x0E, 0x4C, 0x18, 0x22, ++0x00, 0x21, 0x28, 0x46, 0xE4, 0xF7, 0x42, 0xFB, 0x05, 0xF1, 0x0C, 0x00, 0x07, 0xF0, 0xCE, 0xFB, 0x20, 0x46, 0x04, 0xF0, ++0xD9, 0xFF, 0x04, 0xF1, 0x26, 0x00, 0x04, 0xF0, 0xD5, 0xFF, 0x04, 0xF1, 0x4C, 0x00, 0x04, 0xF0, 0xD1, 0xFF, 0x04, 0xF1, ++0x72, 0x00, 0xBD, 0xE8, 0x38, 0x40, 0x04, 0xF0, 0xCB, 0xBF, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x64, 0x3E, 0x18, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x90, 0xF8, 0x63, 0x30, 0x3F, 0x4D, 0x40, 0x49, 0x40, 0x4F, 0xDF, 0xF8, 0x1C, 0x91, 0x04, 0x46, ++0x03, 0xEB, 0x83, 0x02, 0x3E, 0x48, 0x4F, 0xF4, 0x1A, 0x76, 0x03, 0xEB, 0x42, 0x02, 0x06, 0xFB, 0x03, 0x11, 0x05, 0xEB, ++0xC2, 0x02, 0x00, 0xEB, 0x83, 0x13, 0x04, 0xF1, 0x6C, 0x00, 0xF4, 0xF7, 0xFD, 0xF8, 0x94, 0xF8, 0x63, 0x30, 0x37, 0x49, ++0xDF, 0xF8, 0xF0, 0xC0, 0x36, 0x48, 0x06, 0x22, 0xA4, 0xF8, 0xCE, 0x20, 0x00, 0x25, 0x01, 0xEB, 0xC3, 0x02, 0x4F, 0xF0, ++0x05, 0x0E, 0xFF, 0x26, 0xA4, 0xF8, 0xD8, 0x60, 0x84, 0xF8, 0xD7, 0x50, 0xA4, 0xF8, 0xD0, 0x50, 0x84, 0xF8, 0xDA, 0x50, ++0x04, 0x26, 0x01, 0xF8, 0x33, 0xE0, 0x56, 0x70, 0x94, 0xF8, 0xD7, 0x10, 0x91, 0x70, 0x01, 0x21, 0x15, 0x71, 0x55, 0x71, ++0xD1, 0x70, 0x94, 0xF8, 0xD9, 0x10, 0x03, 0xEB, 0x83, 0x08, 0xC3, 0xEB, 0x83, 0x16, 0x00, 0xEB, 0x86, 0x00, 0x0C, 0xEB, ++0xC8, 0x06, 0x01, 0x44, 0x07, 0xEB, 0x88, 0x03, 0x31, 0x62, 0x02, 0xEB, 0x0E, 0x01, 0xC6, 0xE9, 0x03, 0x15, 0x4C, 0xF8, ++0x38, 0x90, 0xB2, 0x60, 0x73, 0x60, 0xB3, 0x61, 0x29, 0x46, 0xFC, 0x22, 0xC6, 0xF8, 0x14, 0x90, 0xE4, 0xF7, 0xCE, 0xFA, ++0x07, 0xEB, 0x88, 0x03, 0x47, 0xF8, 0x28, 0x90, 0x5D, 0x60, 0x1D, 0x61, 0x94, 0xF8, 0xC0, 0x34, 0x93, 0xB1, 0x94, 0xF8, ++0x63, 0x30, 0x15, 0x48, 0x15, 0x49, 0x03, 0xEB, 0xC3, 0x02, 0x03, 0xEB, 0x42, 0x02, 0x03, 0xEB, 0x83, 0x03, 0x01, 0xEB, ++0x42, 0x01, 0x00, 0xEB, 0x83, 0x02, 0xC2, 0xE9, 0x01, 0x51, 0x40, 0xF8, 0x23, 0x90, 0x15, 0x61, 0xD4, 0xF8, 0xB8, 0x30, ++0x0D, 0x49, 0x00, 0x22, 0x5A, 0x63, 0xDA, 0x64, 0x1A, 0x62, 0xD1, 0xF8, 0x88, 0x31, 0xC4, 0xE9, 0x30, 0x34, 0xBD, 0xE8, ++0xF8, 0x83, 0x00, 0xBF, 0x9C, 0x40, 0x18, 0x00, 0xFC, 0x41, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, 0x4C, 0x3F, 0x18, 0x00, ++0x2C, 0x50, 0x18, 0x00, 0x3C, 0x4C, 0x18, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xDE, 0xFA, 0xFE, 0xCA, 0x9C, 0x4B, 0x18, 0x00, 0x05, 0x4B, 0x5A, 0x68, 0x18, 0x60, 0x12, 0xB1, 0x01, 0x22, 0x9A, 0x72, ++0x70, 0x47, 0x03, 0x4B, 0xD3, 0xF8, 0x8C, 0x31, 0x18, 0x47, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x06, 0x4B, 0x5A, 0x68, 0x1A, 0xB9, 0x06, 0x4B, 0xD3, 0xF8, 0xD4, 0x31, 0x18, 0x47, 0xA0, 0xF1, 0x0C, 0x01, 0x03, 0xF1, ++0x0C, 0x00, 0x07, 0xF0, 0x05, 0xBB, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x40, 0x4B, 0x41, 0x4A, 0x1B, 0x68, 0x94, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x3F, 0x4E, 0x00, 0x2B, 0x41, 0xDB, 0x75, 0x7A, ++0x00, 0x2D, 0x4A, 0xD1, 0x3D, 0x4A, 0x35, 0x72, 0x17, 0x68, 0x7F, 0x01, 0x6C, 0xB1, 0xDF, 0xF8, 0xF8, 0x90, 0xDF, 0xF8, ++0xF8, 0x80, 0xAA, 0x46, 0x4F, 0xF0, 0x01, 0x0B, 0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x04, 0xD0, 0x24, 0x68, 0x00, 0x2C, ++0xF8, 0xD1, 0xBD, 0xE8, 0xF8, 0x8F, 0x94, 0xF8, 0xD6, 0x30, 0x00, 0x2B, 0xF6, 0xD0, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, ++0xF2, 0xD0, 0x94, 0xF8, 0xD5, 0x20, 0x94, 0xF8, 0xD4, 0x30, 0x9A, 0x42, 0xEC, 0xD1, 0xD9, 0xF8, 0x70, 0x31, 0x20, 0x46, ++0x98, 0x47, 0x20, 0xB1, 0x98, 0xF8, 0x00, 0x30, 0x01, 0x33, 0x88, 0xF8, 0x00, 0x30, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD0, ++0xA7, 0xF1, 0x32, 0x02, 0x40, 0xF6, 0xB6, 0x33, 0x9A, 0x42, 0x18, 0xD8, 0xD5, 0xB9, 0x20, 0x46, 0x02, 0xF0, 0x7A, 0xFE, ++0x83, 0x46, 0xF0, 0xB9, 0x88, 0xF8, 0x00, 0x50, 0xD0, 0xE7, 0x73, 0x68, 0x00, 0x2B, 0xBA, 0xD0, 0x1D, 0x49, 0x1E, 0x48, ++0x40, 0xF2, 0x2F, 0x42, 0x08, 0xF0, 0xFE, 0xFE, 0x75, 0x7A, 0x00, 0x2D, 0xB4, 0xD0, 0x01, 0x23, 0x33, 0x72, 0xBD, 0xE8, ++0xF8, 0x8F, 0x20, 0x46, 0x02, 0xF0, 0x62, 0xFE, 0x88, 0xF8, 0x00, 0xA0, 0x24, 0x68, 0x4F, 0xF0, 0x00, 0x0B, 0x01, 0x25, ++0x00, 0x2C, 0xB1, 0xD1, 0xB7, 0xE7, 0x94, 0xF8, 0x63, 0x30, 0x84, 0xF8, 0x88, 0x30, 0xFF, 0x23, 0x84, 0xF8, 0x89, 0x30, ++0x04, 0x21, 0x04, 0xF1, 0x6C, 0x00, 0xF4, 0xF7, 0xDB, 0xF8, 0x73, 0x68, 0x08, 0xB1, 0x01, 0x33, 0x73, 0x60, 0x01, 0x2B, ++0x02, 0xD0, 0x4F, 0xF0, 0x00, 0x0B, 0x9F, 0xE7, 0xFC, 0xF7, 0x58, 0xFD, 0x4F, 0xF0, 0x00, 0x0B, 0x9A, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x40, 0x80, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x20, 0xA0, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x10, 0x2A, 0x17, 0x00, 0xF8, 0xB5, 0x27, 0x4F, 0x7B, 0x68, 0x04, 0x46, ++0x0E, 0x46, 0x13, 0xB1, 0x3C, 0x44, 0x21, 0x75, 0xF8, 0xBD, 0x02, 0x29, 0x34, 0xD0, 0x03, 0x29, 0x21, 0xD0, 0x01, 0x29, ++0x14, 0xD0, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x32, 0xDB, 0x1F, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x04, 0x53, 0x3C, 0x44, 0x00, 0x22, 0x22, 0x75, 0x93, 0xF8, 0xC1, 0x04, 0x31, 0x46, 0xBD, 0xE8, 0xF8, 0x40, ++0x04, 0xF0, 0xC6, 0xBE, 0x18, 0x4B, 0x19, 0x4A, 0x16, 0x4D, 0x00, 0xEB, 0x80, 0x01, 0x03, 0xEB, 0x81, 0x03, 0x02, 0xEB, ++0x81, 0x02, 0x5A, 0x60, 0xE6, 0xE7, 0x12, 0x4D, 0x14, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x52, 0x00, 0xEB, ++0xC0, 0x03, 0x00, 0xEB, 0x43, 0x03, 0x01, 0xEB, 0x43, 0x01, 0x92, 0xF8, 0xC1, 0x04, 0x04, 0xF0, 0x47, 0xFE, 0xD5, 0xE7, ++0x0A, 0x4A, 0x09, 0x4D, 0x00, 0xEB, 0x80, 0x01, 0x02, 0xEB, 0x81, 0x02, 0x53, 0x60, 0xCD, 0xE7, 0x09, 0x49, 0x0A, 0x48, ++0x04, 0x4D, 0x40, 0xF2, 0xC6, 0x42, 0x08, 0xF0, 0x71, 0xFE, 0xC5, 0xE7, 0xD8, 0x9C, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x4C, 0x40, 0x18, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x04, 0x23, 0x00, 0x22, 0x0C, 0x21, 0x44, 0x20, 0x06, 0xF0, 0x76, 0xFD, ++0x23, 0x7E, 0x03, 0x70, 0x04, 0x2B, 0x09, 0xD0, 0x00, 0x23, 0x00, 0x22, 0x43, 0x70, 0xC2, 0x70, 0xA3, 0x7E, 0x83, 0x70, ++0xBD, 0xE8, 0x10, 0x40, 0x06, 0xF0, 0x98, 0xBD, 0xE3, 0x89, 0x00, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0xF1, 0xE7, 0x00, 0xBF, ++0x38, 0xB5, 0x05, 0xF0, 0xE1, 0xFA, 0x0C, 0x23, 0x05, 0x46, 0x19, 0x46, 0x00, 0x22, 0x4F, 0x20, 0x06, 0xF0, 0x58, 0xFD, ++0x2B, 0x88, 0x03, 0x80, 0x04, 0x46, 0x28, 0x46, 0x05, 0xF0, 0xDE, 0xFA, 0x10, 0x4A, 0x11, 0x4D, 0x11, 0x49, 0xA2, 0xFB, ++0x00, 0x03, 0x9B, 0x09, 0x63, 0x60, 0x2B, 0x68, 0xA2, 0xFB, 0x03, 0x23, 0x9B, 0x09, 0x00, 0x22, 0xA3, 0x60, 0xA2, 0x70, ++0x0A, 0x23, 0x0A, 0x68, 0x52, 0xB2, 0x01, 0x3B, 0x3A, 0xB9, 0x13, 0xF0, 0xFF, 0x03, 0xF8, 0xD1, 0x20, 0x46, 0xBD, 0xE8, ++0x38, 0x40, 0x06, 0xF0, 0x67, 0xBD, 0xA2, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0x38, 0x40, 0x06, 0xF0, 0x61, 0xBD, 0x00, 0xBF, ++0xD3, 0x4D, 0x62, 0x10, 0x20, 0x02, 0x32, 0x40, 0x0C, 0xB2, 0x33, 0x40, 0x10, 0xB5, 0xC1, 0x89, 0x04, 0x46, 0x02, 0x23, ++0x00, 0x22, 0x48, 0x20, 0x06, 0xF0, 0x22, 0xFD, 0x22, 0x7E, 0x42, 0x70, 0xA1, 0x7E, 0x05, 0x4A, 0x01, 0x70, 0x13, 0x68, ++0x23, 0xF0, 0x04, 0x03, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0x60, 0x06, 0xF0, 0x45, 0xBD, 0x00, 0xBF, 0x94, 0x40, 0x04, 0x40, ++0xF0, 0xB5, 0x04, 0x68, 0x0E, 0x68, 0xA5, 0x1B, 0x32, 0xD4, 0x8E, 0x46, 0xAB, 0x42, 0x0C, 0xD2, 0xDE, 0xE9, 0x00, 0x76, ++0xDC, 0x19, 0xF6, 0x1B, 0xED, 0x1A, 0xAB, 0x42, 0x06, 0xEB, 0x04, 0x07, 0xA4, 0x46, 0x1C, 0x44, 0xF8, 0xD3, 0xCE, 0xE9, ++0x00, 0xC7, 0xB5, 0xEB, 0x53, 0x0F, 0x05, 0xD9, 0xDE, 0xE9, 0x00, 0x54, 0x1D, 0x44, 0x23, 0x44, 0xCE, 0xE9, 0x00, 0x53, ++0x43, 0x68, 0x4C, 0x68, 0x1D, 0x1B, 0x00, 0x2D, 0x09, 0xDB, 0xB2, 0xB1, 0x05, 0x68, 0x09, 0x68, 0x53, 0x60, 0x68, 0x1A, ++0x00, 0x28, 0x17, 0xDA, 0x58, 0x1B, 0x15, 0x60, 0xF0, 0xBD, 0xAA, 0xB1, 0x05, 0x68, 0x09, 0x68, 0x54, 0x60, 0x6B, 0x1A, ++0x00, 0x2B, 0xA8, 0xBF, 0x60, 0x1A, 0x18, 0xDB, 0x11, 0x60, 0xF0, 0xBD, 0x35, 0x1B, 0x86, 0x46, 0xCA, 0xE7, 0x00, 0x68, ++0x0A, 0x68, 0x81, 0x1A, 0x00, 0x29, 0x0C, 0xDA, 0x18, 0x1A, 0xF0, 0xBD, 0x58, 0x1A, 0xF1, 0xE7, 0x00, 0x68, 0x0B, 0x68, ++0xC1, 0x1A, 0x00, 0x29, 0xA8, 0xBF, 0xE0, 0x1A, 0xE0, 0xDA, 0x20, 0x1A, 0xF0, 0xBD, 0x98, 0x1A, 0xF0, 0xBD, 0x60, 0x1B, ++0xD9, 0xE7, 0x00, 0xBF, 0x70, 0xB5, 0x19, 0x4E, 0x90, 0xF8, 0xC1, 0x44, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0x05, 0x46, ++0x93, 0xF8, 0x20, 0x20, 0x0A, 0xB9, 0x1B, 0x7C, 0xFB, 0xB9, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x64, 0x94, 0xF8, 0x50, 0x20, ++0x12, 0xB9, 0x94, 0xF8, 0x40, 0x30, 0x7B, 0xB9, 0x0F, 0x4B, 0x9B, 0x68, 0x5B, 0xB1, 0x95, 0xF8, 0x63, 0x10, 0xFF, 0x20, ++0x93, 0xF8, 0x4E, 0x20, 0x8A, 0x42, 0x08, 0xBF, 0x83, 0xF8, 0x4E, 0x00, 0x1B, 0x68, 0x00, 0x2B, 0xF6, 0xD1, 0x70, 0xBD, ++0x08, 0x4B, 0x01, 0x21, 0xD3, 0xF8, 0x08, 0x32, 0x28, 0x46, 0x98, 0x47, 0xE8, 0xE7, 0x05, 0x4B, 0x11, 0x46, 0xD3, 0xF8, ++0x08, 0x32, 0x98, 0x47, 0xD9, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x48, 0x4B, 0x93, 0xF8, 0x5A, 0x30, 0x9B, 0xB0, 0x01, 0x2B, 0x08, 0x90, 0x40, 0xF2, 0x93, 0x81, ++0xDF, 0xF8, 0x20, 0x91, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB7, 0x81, 0x08, 0x9C, ++0x40, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x94, 0x30, 0x98, 0x47, 0x23, 0x6C, 0x94, 0xF8, 0x63, 0x20, 0xDA, 0x76, 0x94, 0xF8, ++0x62, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xB9, 0x81, 0x02, 0x2A, 0x08, 0xBF, 0x08, 0x9A, 0x39, 0x48, 0x0A, 0xBF, 0xB2, 0xF8, ++0xD2, 0x20, 0x4F, 0xF4, 0xC8, 0x32, 0x92, 0x02, 0x0A, 0x92, 0x1A, 0x7E, 0x02, 0x2A, 0x02, 0xF1, 0x01, 0x03, 0x00, 0xF0, ++0xB9, 0x81, 0xC3, 0xEB, 0xC3, 0x04, 0x00, 0xEB, 0x84, 0x04, 0xD9, 0x00, 0x24, 0x7E, 0xFF, 0x2C, 0x0D, 0xD1, 0x01, 0x2A, ++0x02, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, 0xC3, 0xEB, 0xC3, 0x02, 0x00, 0xEB, 0x82, 0x02, 0xD9, 0x00, 0x12, 0x7E, ++0xFF, 0x2A, 0x00, 0xF0, 0x98, 0x82, 0x28, 0x4A, 0xCB, 0x1A, 0x00, 0xEB, 0x83, 0x03, 0x96, 0x68, 0x5B, 0x7E, 0x06, 0x93, ++0x00, 0x2E, 0x00, 0xF0, 0x4A, 0x81, 0x0A, 0x9B, 0x4F, 0xF0, 0x00, 0x0B, 0x5B, 0x00, 0x0B, 0x93, 0x5F, 0x46, 0x03, 0xE0, ++0x36, 0x68, 0x00, 0x2E, 0x00, 0xF0, 0x9A, 0x80, 0x33, 0x6C, 0x00, 0x2B, 0xF8, 0xD0, 0x08, 0x9A, 0x12, 0x6C, 0x93, 0x42, ++0xF4, 0xD0, 0x96, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x93, 0x81, 0x02, 0x2B, 0x0A, 0xBF, 0xB6, 0xF8, 0xD2, 0x30, ++0x4F, 0xF4, 0xC8, 0x3B, 0x4F, 0xEA, 0x83, 0x2B, 0x0B, 0x9B, 0x5B, 0x45, 0x04, 0xD8, 0x0A, 0x9B, 0xBB, 0xFB, 0xF3, 0xF2, ++0xBB, 0xFB, 0xF2, 0xFB, 0x06, 0x9B, 0x4F, 0xEA, 0x5B, 0x00, 0xB0, 0xFB, 0xF3, 0xF5, 0x09, 0x95, 0xE5, 0xF7, 0x7C, 0xF8, ++0x43, 0xF2, 0xB0, 0x64, 0x20, 0x44, 0xA8, 0x42, 0x00, 0xF2, 0x18, 0x81, 0x00, 0x2F, 0x00, 0xF0, 0x1C, 0x81, 0x06, 0x9B, ++0x09, 0x9A, 0x03, 0xFB, 0x02, 0xF3, 0x07, 0x93, 0x10, 0xAC, 0x00, 0x25, 0x10, 0xE0, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x01, 0x35, 0xAF, 0x42, ++0x04, 0xF1, 0x14, 0x04, 0x00, 0xF0, 0x03, 0x81, 0x22, 0x68, 0x5A, 0x45, 0xF6, 0xD1, 0x72, 0x6A, 0x0C, 0x92, 0xD4, 0xE9, ++0x02, 0x01, 0x0D, 0xF1, 0x38, 0x0C, 0x0D, 0xF1, 0x30, 0x0A, 0x02, 0xF5, 0x1C, 0x5E, 0x8C, 0xE8, 0x03, 0x00, 0x0E, 0xF1, ++0x10, 0x0E, 0x52, 0x46, 0x61, 0x46, 0x50, 0x46, 0x5B, 0x46, 0xCD, 0xF8, 0x34, 0xE0, 0xFF, 0xF7, 0xB7, 0xFE, 0xD9, 0xF8, ++0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x80, 0x46, 0xC0, 0xF2, 0x2D, 0x81, 0x06, 0x9B, 0x5A, 0x1E, 0x07, 0x9B, ++0xB3, 0xFB, 0xF2, 0xF2, 0x05, 0x92, 0xE5, 0xF7, 0x31, 0xF8, 0x05, 0x9A, 0x61, 0x68, 0xA2, 0xF5, 0x7A, 0x62, 0x12, 0x1A, ++0x8A, 0x42, 0x38, 0xBF, 0x0A, 0x46, 0x42, 0x45, 0xC6, 0xD9, 0x05, 0x92, 0x05, 0xEB, 0x85, 0x05, 0xE5, 0xF7, 0x22, 0xF8, ++0x1A, 0xAB, 0x03, 0xEB, 0x85, 0x05, 0x96, 0xF8, 0x63, 0x10, 0x05, 0x9A, 0x55, 0xF8, 0x18, 0x3C, 0x36, 0x68, 0x01, 0x24, ++0x8C, 0x40, 0x02, 0x44, 0x9A, 0xE8, 0x03, 0x00, 0x23, 0x43, 0x02, 0xF5, 0x7A, 0x62, 0xA5, 0xF1, 0x20, 0x04, 0x84, 0xE8, ++0x03, 0x00, 0x45, 0xF8, 0x24, 0x2C, 0x45, 0xF8, 0x18, 0x3C, 0x00, 0x2E, 0x7F, 0xF4, 0x66, 0xAF, 0x00, 0x2F, 0x00, 0xF0, ++0xA2, 0x80, 0xDF, 0xF8, 0x88, 0xA3, 0xDD, 0xF8, 0x20, 0xB0, 0x05, 0x96, 0x09, 0x96, 0x0B, 0x96, 0x07, 0x96, 0x12, 0xAC, ++0x06, 0x97, 0x54, 0xF8, 0x08, 0x7C, 0x0A, 0x9B, 0xB7, 0xFB, 0xF3, 0xF2, 0x03, 0xFB, 0x12, 0x72, 0x00, 0x2A, 0x00, 0xF0, ++0x3A, 0x81, 0xE4, 0xF7, 0xED, 0xFF, 0x54, 0xE9, 0x01, 0x63, 0xA3, 0xF5, 0xBB, 0x53, 0x10, 0x3B, 0x1D, 0x1A, 0xE4, 0xF7, ++0xE5, 0xFF, 0xDA, 0xF8, 0x10, 0x30, 0x54, 0xF8, 0x08, 0x1C, 0xEB, 0x1A, 0x06, 0xF5, 0x7A, 0x66, 0x00, 0x2B, 0x06, 0xEB, ++0x00, 0x07, 0xC0, 0xF2, 0xEA, 0x80, 0xDA, 0xF8, 0x10, 0x20, 0x6B, 0x1A, 0x9A, 0x1A, 0x00, 0x2A, 0x80, 0xF2, 0xDB, 0x80, ++0xCD, 0xE9, 0x01, 0x75, 0xBE, 0x4B, 0x00, 0x91, 0xD3, 0xF8, 0x04, 0x32, 0xDF, 0xF8, 0x1C, 0x83, 0x1E, 0x46, 0x00, 0x22, ++0xFF, 0x23, 0x01, 0x21, 0x58, 0x46, 0xB0, 0x47, 0xEB, 0x19, 0xB9, 0x4E, 0x25, 0x60, 0x63, 0x60, 0x07, 0x46, 0x00, 0x25, ++0xA3, 0x68, 0xEB, 0x40, 0xDB, 0x07, 0x22, 0xD5, 0x72, 0x6A, 0x54, 0xF8, 0x08, 0x3C, 0x0E, 0x92, 0x02, 0xF5, 0x1C, 0x5C, ++0x0C, 0xF1, 0x10, 0x0C, 0x00, 0x22, 0x0E, 0xA9, 0x20, 0x46, 0xCD, 0xF8, 0x3C, 0xC0, 0xFF, 0xF7, 0x21, 0xFE, 0xD9, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xC3, 0x80, 0x0E, 0x9A, 0x63, 0x68, 0x9B, 0xF8, 0x63, 0x10, ++0x86, 0xF8, 0x4E, 0x10, 0x9B, 0x1A, 0x00, 0x22, 0x73, 0x65, 0x86, 0xF8, 0x4F, 0x70, 0xA6, 0xF8, 0x58, 0x20, 0x01, 0x35, ++0x04, 0x2D, 0x06, 0xF5, 0xA4, 0x66, 0xD3, 0xD1, 0x05, 0x9B, 0x06, 0x9A, 0x01, 0x33, 0x9A, 0x42, 0x05, 0x93, 0x04, 0xF1, ++0x14, 0x04, 0x90, 0xD1, 0x07, 0x9B, 0x33, 0xB3, 0x0B, 0x9B, 0x0A, 0x99, 0x03, 0xF5, 0x9C, 0x50, 0x09, 0x9B, 0x08, 0x30, ++0x83, 0x42, 0xA8, 0xBF, 0x03, 0x46, 0x18, 0x46, 0x01, 0xEB, 0xD1, 0x73, 0xB0, 0xEB, 0x63, 0x0F, 0x4F, 0xEA, 0x63, 0x02, ++0x00, 0xF3, 0x18, 0x81, 0x52, 0x42, 0x82, 0x42, 0xC4, 0xBF, 0x0A, 0x9B, 0xC0, 0x18, 0x8F, 0x4B, 0xD3, 0xF8, 0x6C, 0x31, ++0x98, 0x47, 0x08, 0x9C, 0x8E, 0x4A, 0x94, 0xF8, 0x4D, 0x30, 0x20, 0x65, 0x43, 0xF0, 0x20, 0x03, 0x01, 0x21, 0x84, 0xF8, ++0x4D, 0x30, 0x82, 0xF8, 0x31, 0x10, 0x1B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xE4, 0xF7, 0x5C, 0xFF, 0x03, 0x19, 0x09, 0x93, ++0x00, 0x2F, 0x7F, 0xF4, 0xE4, 0xAE, 0xD9, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x7B, 0xDB, 0x1A, 0xAB, ++0x07, 0xEB, 0x87, 0x02, 0x70, 0x6A, 0x03, 0xEB, 0x82, 0x02, 0x09, 0x9B, 0x42, 0xF8, 0x28, 0xBC, 0x00, 0xF5, 0x1C, 0x51, ++0x42, 0xE9, 0x09, 0x30, 0x10, 0x31, 0x42, 0xF8, 0x1C, 0x1C, 0xBC, 0x00, 0x96, 0xF8, 0x63, 0x20, 0x3C, 0x44, 0x1A, 0xAB, ++0x03, 0xEB, 0x84, 0x04, 0x01, 0x23, 0x93, 0x40, 0x01, 0x37, 0x44, 0xF8, 0x18, 0x3C, 0x8F, 0xE6, 0x03, 0x6C, 0xDB, 0x7E, ++0xFF, 0x2B, 0x3F, 0xF4, 0x44, 0xAE, 0x90, 0xF8, 0x63, 0x20, 0x9A, 0x42, 0x3F, 0xF4, 0x3F, 0xAE, 0x6E, 0x49, 0x6F, 0x48, ++0x40, 0xF2, 0xA7, 0x22, 0x08, 0xF0, 0x8E, 0xFB, 0x37, 0xE6, 0x08, 0x9A, 0x6C, 0x49, 0x92, 0xF8, 0x6C, 0x20, 0x4F, 0xF4, ++0x1E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x6A, 0x48, 0x92, 0x68, 0x0A, 0x92, 0x1A, 0x7E, 0x02, 0x2A, 0x02, 0xF1, 0x01, 0x03, ++0x7F, 0xF4, 0x47, 0xAE, 0x03, 0x7E, 0xFF, 0x2B, 0x40, 0xF0, 0xEE, 0x80, 0x01, 0x23, 0x4D, 0xE6, 0x06, 0x9B, 0x01, 0x2B, ++0x3F, 0xF6, 0xCF, 0xAE, 0x5D, 0x49, 0x61, 0x48, 0x40, 0xF2, 0xD3, 0x22, 0x08, 0xF0, 0x6C, 0xFB, 0xC7, 0xE6, 0x5C, 0x4A, ++0x96, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0xD3, 0xF8, 0x08, 0xB0, 0x6A, 0xE6, 0xDA, 0xF8, ++0x10, 0x20, 0x1D, 0x46, 0x5B, 0x1A, 0x9A, 0x1A, 0x00, 0x2A, 0xF8, 0xDA, 0x1C, 0xE7, 0xDA, 0xF8, 0x10, 0x30, 0x0D, 0x44, ++0xEB, 0x1A, 0x00, 0x2B, 0xBF, 0xF6, 0x16, 0xAF, 0xDA, 0xF8, 0x10, 0x30, 0x0D, 0x44, 0xEB, 0x1A, 0x00, 0x2B, 0xF2, 0xDB, ++0x0E, 0xE7, 0x96, 0xF8, 0x4E, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0x38, 0xAF, 0x47, 0x49, 0x4F, 0xF4, 0x58, 0x72, 0x40, 0x46, ++0x08, 0xF0, 0x40, 0xFB, 0x30, 0xE7, 0x02, 0x2F, 0x00, 0xF0, 0x98, 0x80, 0x1A, 0xAB, 0x07, 0xEB, 0x87, 0x02, 0x70, 0x6A, ++0x03, 0xEB, 0x82, 0x02, 0x09, 0x9B, 0x42, 0xF8, 0x28, 0xBC, 0x00, 0xF5, 0x1C, 0x51, 0x42, 0xE9, 0x09, 0x30, 0x10, 0x31, ++0x42, 0xF8, 0x1C, 0x1C, 0xBC, 0x00, 0x96, 0xF8, 0x63, 0x20, 0x1F, 0x2A, 0x7F, 0xF6, 0x7E, 0xAF, 0x37, 0x49, 0x3C, 0x48, ++0x40, 0xF2, 0xED, 0x22, 0x08, 0xF0, 0x20, 0xFB, 0x74, 0xE7, 0x3A, 0x4B, 0xDA, 0xF8, 0x10, 0x00, 0x19, 0x68, 0x0A, 0x9B, ++0x00, 0xEB, 0x41, 0x10, 0x9F, 0x42, 0x28, 0xBF, 0x1F, 0x46, 0x00, 0xF5, 0x1C, 0x55, 0x10, 0x35, 0x3B, 0x46, 0x0E, 0xA9, ++0x0E, 0x90, 0x20, 0x46, 0x0F, 0x95, 0xFF, 0xF7, 0x17, 0xFD, 0x0E, 0x9E, 0x23, 0x68, 0x54, 0xF8, 0x04, 0x5C, 0x9A, 0x1B, ++0x00, 0x2A, 0x1D, 0x44, 0x62, 0x68, 0xA5, 0xF5, 0xFA, 0x65, 0xB4, 0xBF, 0xB6, 0x1A, 0x3E, 0x1A, 0xAD, 0x1A, 0xE4, 0xF7, ++0x91, 0xFE, 0x00, 0xF5, 0x7A, 0x60, 0xA8, 0x42, 0x34, 0xDC, 0x54, 0xE9, 0x02, 0x78, 0xE4, 0xF7, 0x89, 0xFE, 0xA7, 0xF5, ++0x5A, 0x53, 0x30, 0x3B, 0xA3, 0xEB, 0x08, 0x03, 0x07, 0x9A, 0xAD, 0x1B, 0x1B, 0x1A, 0x2B, 0x44, 0xDA, 0xB1, 0x09, 0x9A, ++0xAA, 0x42, 0x1F, 0xDB, 0x0B, 0x9A, 0x9A, 0x42, 0x0A, 0xDD, 0x0A, 0x9A, 0x13, 0x44, 0x15, 0x44, 0x09, 0x9A, 0xAA, 0x42, ++0xFF, 0xF6, 0x83, 0xAE, 0x0B, 0x9A, 0x9A, 0x42, 0x3F, 0xF7, 0x7F, 0xAE, 0x0B, 0x9A, 0xAA, 0x42, 0xB8, 0xBF, 0x2A, 0x46, ++0x0B, 0x92, 0x09, 0x9A, 0x9A, 0x42, 0xA8, 0xBF, 0x1A, 0x46, 0x09, 0x92, 0x73, 0xE6, 0x09, 0x93, 0x01, 0x23, 0x0B, 0x95, ++0x07, 0x93, 0x6E, 0xE6, 0x40, 0x1A, 0xEA, 0xE6, 0x0A, 0x9A, 0xAD, 0x1A, 0x9B, 0x1A, 0xE1, 0xE7, 0xE4, 0xF7, 0x56, 0xFE, ++0x00, 0xF5, 0x7A, 0x65, 0xC5, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x48, 0xA0, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0xD0, 0xA0, 0x15, 0x00, ++0x00, 0xA1, 0x15, 0x00, 0x40, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x10, 0xA1, 0x15, 0x00, 0x40, 0xF2, 0xE7, 0x22, ++0x14, 0x49, 0x15, 0x48, 0x08, 0xF0, 0x9E, 0xFA, 0xD9, 0xF8, 0x00, 0x20, 0x09, 0x9B, 0xB2, 0xF9, 0x00, 0x20, 0xCD, 0xF8, ++0x68, 0xB0, 0x1B, 0x93, 0x73, 0x6A, 0x1C, 0x93, 0x03, 0xF5, 0x1C, 0x53, 0x10, 0x33, 0x00, 0x2A, 0x1D, 0x93, 0x4F, 0xF0, ++0x08, 0x04, 0xFF, 0xF6, 0x60, 0xAF, 0xDF, 0xE6, 0x00, 0x23, 0x19, 0x46, 0x67, 0xE5, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0xDA, 0x04, 0x49, 0x05, 0x48, 0x40, 0xF2, 0xAE, 0x22, 0x08, 0xF0, 0x7B, 0xFA, 0x00, 0x23, ++0x5B, 0x7E, 0xFF, 0xDE, 0x70, 0x79, 0x15, 0x00, 0xE4, 0xA0, 0x15, 0x00, 0xC4, 0xA0, 0x15, 0x00, 0x0A, 0x4B, 0x03, 0xF1, ++0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x02, 0xD0, 0xDA, 0x7E, 0xFF, 0x2A, 0x04, 0xD1, 0x1C, 0x33, 0x8B, 0x42, 0xF6, 0xD1, ++0x00, 0x20, 0x70, 0x47, 0x04, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x02, 0x32, 0x02, 0x60, 0x01, 0x20, 0x70, 0x47, ++0x90, 0x9D, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x0E, 0x46, 0x85, 0xB0, 0x14, 0x46, 0x05, 0x46, ++0x00, 0x28, 0x54, 0xD0, 0x07, 0x46, 0x00, 0x2C, 0x3A, 0xD0, 0xA3, 0x7A, 0xFF, 0x2B, 0x37, 0xD0, 0x3D, 0x4A, 0x23, 0x7A, ++0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0x5E, 0xD0, 0x02, 0x2A, 0x52, 0xD0, ++0x4F, 0xF4, 0x48, 0x4A, 0x4F, 0xF4, 0xC8, 0x39, 0x60, 0x68, 0xDF, 0xF8, 0xE0, 0x80, 0x00, 0xF5, 0x1C, 0x5B, 0xE4, 0xF7, ++0xC9, 0xFD, 0x0B, 0xF1, 0x10, 0x0B, 0x03, 0x46, 0xE1, 0x7A, 0xD8, 0xF8, 0xFC, 0x21, 0x28, 0x46, 0x9B, 0x44, 0x90, 0x47, ++0x83, 0x1B, 0x13, 0xEB, 0x0A, 0x0F, 0x05, 0xD5, 0xAA, 0xEB, 0x06, 0x03, 0x48, 0x44, 0xC3, 0x42, 0xFC, 0xD4, 0x83, 0x1B, ++0x00, 0x2B, 0x0B, 0xF5, 0x0C, 0x53, 0xB8, 0xBF, 0x00, 0xF1, 0xFF, 0x36, 0x28, 0x33, 0x9B, 0x1B, 0x00, 0x2B, 0x31, 0xDB, ++0x0B, 0xF5, 0x7A, 0x60, 0x80, 0x1B, 0x06, 0xE0, 0xE4, 0xF7, 0xA6, 0xFD, 0xDF, 0xF8, 0x8C, 0x80, 0x00, 0xF5, 0x5A, 0x50, ++0x30, 0x30, 0x00, 0x22, 0x01, 0x23, 0xCD, 0xE9, 0x01, 0x06, 0xD8, 0xF8, 0x04, 0x42, 0x00, 0x92, 0x38, 0x46, 0x19, 0x46, ++0xA0, 0x47, 0xFF, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x17, 0x4B, 0x03, 0xF1, 0x54, 0x01, ++0x1A, 0x7E, 0xFF, 0x2A, 0x02, 0xD0, 0xDF, 0x7E, 0xFF, 0x2F, 0x1C, 0xD1, 0x1C, 0x33, 0x99, 0x42, 0xF6, 0xD1, 0x00, 0x20, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0xF8, 0xD2, 0x30, 0x4F, 0xEA, 0x83, 0x29, 0x4F, 0xEA, 0x43, 0x2A, 0xA9, 0xE7, ++0x41, 0xF2, 0x88, 0x30, 0xD5, 0xE7, 0x93, 0xF8, 0x6C, 0x30, 0x0A, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, ++0xD3, 0xF8, 0x08, 0x90, 0x4F, 0xEA, 0x59, 0x0A, 0x9A, 0xE7, 0x03, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x37, ++0x7F, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0xB5, 0x0C, 0x46, 0x02, 0x7A, 0x17, 0x49, 0x23, 0x7A, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x02, 0x12, 0x05, 0xFB, ++0x03, 0x13, 0x12, 0x6C, 0x1B, 0x6C, 0x9A, 0x42, 0x0D, 0xD0, 0x45, 0x68, 0xE4, 0xF7, 0x4A, 0xFD, 0x64, 0x68, 0x06, 0x46, ++0xE4, 0xF7, 0x46, 0xFD, 0x2A, 0x1B, 0x06, 0xD4, 0x63, 0x1B, 0x00, 0x2B, 0x0C, 0xDB, 0xA5, 0x42, 0x08, 0xD0, 0x00, 0x20, ++0x70, 0xBD, 0xA4, 0xF5, 0x5A, 0x53, 0x30, 0x3B, 0x5B, 0x1B, 0x9E, 0x1B, 0x00, 0x2E, 0xF1, 0xDA, 0x01, 0x20, 0x70, 0xBD, ++0xA2, 0xF5, 0x5A, 0x53, 0x30, 0x3B, 0x1B, 0x1A, 0x00, 0x2B, 0xF7, 0xDB, 0xA5, 0x42, 0xEC, 0xD1, 0xF4, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x83, 0xB0, 0x0D, 0x46, 0x00, 0xF1, 0x44, 0x08, 0x91, 0x46, ++0x22, 0xB9, 0x90, 0xF8, 0x4D, 0x30, 0xDB, 0x07, 0x00, 0xF1, 0xA3, 0x80, 0xDF, 0xF8, 0x64, 0xA1, 0xD7, 0xF8, 0x40, 0xB0, ++0xDA, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x79, 0xD1, 0xDA, 0xF8, 0x50, 0x30, 0x0B, 0xB1, 0x9B, 0x45, 0x2E, 0xD1, 0xBD, 0x64, ++0xE4, 0xF7, 0x0A, 0xFD, 0x05, 0xF5, 0x5A, 0x53, 0xDA, 0xF8, 0x10, 0x40, 0x2F, 0x33, 0x1E, 0x18, 0x00, 0x2C, 0x00, 0xF0, ++0x88, 0x80, 0xDF, 0xF8, 0x38, 0xA1, 0x0B, 0xE0, 0xDA, 0xF8, 0xA0, 0x30, 0x98, 0x47, 0xD3, 0x46, 0x40, 0xBB, 0x63, 0x68, ++0xEB, 0x1A, 0x00, 0x2B, 0x08, 0xDB, 0x24, 0x68, 0x00, 0x2C, 0x78, 0xD0, 0x63, 0x68, 0xF3, 0x1A, 0x00, 0x2B, 0x21, 0x46, ++0x40, 0x46, 0xED, 0xDA, 0x3F, 0x48, 0x42, 0x46, 0x21, 0x46, 0x06, 0xF0, 0xD9, 0xFD, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, ++0x01, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x54, 0x60, 0xE4, 0xF7, 0xDA, 0xFC, ++0xAE, 0x1B, 0xA6, 0xF5, 0x7A, 0x66, 0x30, 0x1A, 0xC4, 0x0F, 0x00, 0x2C, 0xC5, 0xD0, 0xDF, 0xF8, 0xDC, 0xB0, 0x00, 0x24, ++0x97, 0xF8, 0xC0, 0x34, 0x4B, 0xB1, 0x31, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, ++0x70, 0x30, 0x01, 0x2B, 0x1D, 0xD0, 0x97, 0xF8, 0x62, 0x30, 0xDB, 0xF8, 0x2C, 0x40, 0x7B, 0xB1, 0x02, 0x2B, 0x0A, 0xBF, ++0xB7, 0xF8, 0xD2, 0x10, 0x4F, 0xF4, 0xC8, 0x31, 0x89, 0x02, 0x09, 0xF1, 0x01, 0x02, 0x29, 0x44, 0x38, 0x46, 0x23, 0x46, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x22, 0x4A, 0x97, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, ++0x03, 0x23, 0x99, 0x68, 0xED, 0xE7, 0xDB, 0xF8, 0x90, 0x30, 0x22, 0x46, 0x29, 0x46, 0x38, 0x46, 0x98, 0x47, 0x97, 0xF8, ++0x62, 0x30, 0xDB, 0xF8, 0x2C, 0x40, 0x00, 0x2B, 0xDA, 0xD1, 0xE9, 0xE7, 0xDA, 0xF8, 0x24, 0x20, 0x01, 0x92, 0x56, 0x68, ++0xE4, 0xF7, 0x92, 0xFC, 0x01, 0x9A, 0x93, 0x68, 0x06, 0xF5, 0x7A, 0x66, 0x9B, 0x45, 0x06, 0xEB, 0x00, 0x04, 0x0A, 0xD0, ++0xE4, 0xF7, 0x88, 0xFC, 0x01, 0x9A, 0xD3, 0x68, 0x04, 0xF5, 0x7A, 0x64, 0x04, 0x44, 0x13, 0xB1, 0x04, 0xF5, 0x1C, 0x54, ++0x10, 0x34, 0x2C, 0x1B, 0xE4, 0x0F, 0x00, 0x2C, 0x3F, 0xF4, 0x6D, 0xAF, 0xA5, 0xE7, 0x00, 0x24, 0x8A, 0xE7, 0x05, 0x48, ++0x41, 0x46, 0x06, 0xF0, 0xD9, 0xFC, 0x97, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x01, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x51, 0xE7, ++0x40, 0x9D, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x81, 0x46, 0x1A, 0x48, 0x88, 0x46, 0x17, 0x46, 0x06, 0xF0, 0xB4, 0xFC, 0x18, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x0C, 0xDB, 0x16, 0x4D, 0x28, 0x46, 0x21, 0x46, 0x50, 0xF8, 0x20, 0x6F, ++0xE7, 0x60, 0xC4, 0xE9, 0x01, 0x98, 0x06, 0xF0, 0x5F, 0xFC, 0x4E, 0xB1, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x28, 0xF0, 0xD1, ++0x0F, 0x49, 0x10, 0x48, 0xD6, 0x22, 0x08, 0xF0, 0xA9, 0xF8, 0xEA, 0xE7, 0x0E, 0x4B, 0x61, 0x68, 0x1B, 0x69, 0xAC, 0x64, ++0xCB, 0x1A, 0x14, 0x2B, 0x07, 0xD4, 0x0C, 0x4B, 0x05, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x47, ++0x18, 0x47, 0x6B, 0x6C, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x48, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x48, 0xA1, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0xC1, 0x4B, 0xDF, 0xF8, 0x0C, 0x83, 0x1D, 0x69, 0xD0, 0xF8, 0x40, 0x90, 0x2F, 0x7A, 0x6B, 0x68, ++0x89, 0xB0, 0x4F, 0xF4, 0xA4, 0x6A, 0xA3, 0xF5, 0x7A, 0x63, 0x0A, 0xFB, 0x07, 0x8B, 0x0C, 0x46, 0x03, 0x92, 0x01, 0x93, ++0x06, 0x46, 0xE4, 0xF7, 0x05, 0xFC, 0x01, 0x9B, 0xDB, 0xF8, 0x40, 0x20, 0x1B, 0x1B, 0x1B, 0x1A, 0x4A, 0x45, 0x01, 0x93, ++0x66, 0xD0, 0x6B, 0x68, 0x02, 0x93, 0xE4, 0xF7, 0xF9, 0xFB, 0x02, 0x9B, 0x99, 0xF8, 0x1B, 0x20, 0x04, 0x90, 0xA3, 0xF5, ++0x7A, 0x63, 0x19, 0x1A, 0xFF, 0x2A, 0x02, 0x91, 0x20, 0xD1, 0x96, 0xF8, 0x4E, 0x60, 0x05, 0x93, 0xFF, 0x2E, 0x40, 0xF0, ++0x8F, 0x80, 0x01, 0x9B, 0x03, 0x9A, 0x18, 0x46, 0x10, 0x44, 0xB2, 0xEB, 0x50, 0x0F, 0x4F, 0xEA, 0x50, 0x03, 0x00, 0xF2, ++0xA9, 0x80, 0x03, 0x9A, 0xA4, 0x4E, 0xA4, 0x1A, 0x1C, 0x44, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x87, 0x2A, 0x46, ++0xD6, 0xF8, 0x88, 0x30, 0x39, 0x6C, 0x20, 0x46, 0x98, 0x47, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0A, 0xFB, 0x02, 0x8A, ++0x50, 0x46, 0x07, 0xAA, 0x06, 0xA9, 0xDB, 0xF8, 0x40, 0x90, 0x01, 0x93, 0x03, 0xF0, 0xE8, 0xFB, 0x83, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0x8C, 0x80, 0x07, 0x9C, 0x02, 0x99, 0x01, 0x9B, 0x0A, 0x1B, 0x00, 0x2A, 0xC0, 0xF2, 0x41, 0x81, 0x06, 0x9A, ++0xD1, 0x1A, 0x04, 0x9B, 0xD9, 0x42, 0x7D, 0xD5, 0x14, 0x1B, 0xE4, 0xF7, 0xB1, 0xFB, 0x00, 0xF5, 0x0C, 0x50, 0x28, 0x30, ++0x84, 0x42, 0x40, 0xF2, 0x3B, 0x81, 0x8B, 0x4E, 0x07, 0x98, 0xD6, 0xF8, 0x88, 0x30, 0x49, 0x46, 0x00, 0x22, 0x98, 0x47, ++0x06, 0x9C, 0xD6, 0xF8, 0x88, 0x90, 0xE4, 0xF7, 0x9F, 0xFB, 0xA4, 0xF5, 0x7A, 0x64, 0x20, 0x1A, 0xDA, 0xF8, 0x40, 0x10, ++0x02, 0x9C, 0x00, 0x22, 0xC8, 0x47, 0xBA, 0xE7, 0xE4, 0xF7, 0x94, 0xFB, 0x01, 0x9B, 0xA3, 0xF5, 0x7A, 0x62, 0x12, 0x1A, ++0x41, 0xF2, 0x87, 0x33, 0x9A, 0x42, 0x01, 0x92, 0xB9, 0xDD, 0x6F, 0x68, 0xE4, 0xF7, 0x88, 0xFB, 0x99, 0xF8, 0x1B, 0xB0, ++0x02, 0x97, 0x3B, 0x1A, 0xBB, 0xF1, 0xFF, 0x0F, 0x01, 0x9A, 0x04, 0x90, 0xA3, 0xF5, 0x7A, 0x67, 0x70, 0xD0, 0x0A, 0xFB, ++0x0B, 0x80, 0x07, 0xAA, 0x06, 0xA9, 0x03, 0xF0, 0x9B, 0xFB, 0x00, 0x28, 0x40, 0xF0, 0xE6, 0x80, 0xE4, 0xF7, 0x72, 0xFB, ++0x06, 0x9E, 0xC6, 0xF5, 0x9C, 0x52, 0x08, 0x32, 0x00, 0xF5, 0x7A, 0x60, 0x22, 0x44, 0x12, 0xEB, 0x40, 0x03, 0x00, 0xF1, ++0xF9, 0x80, 0xE4, 0xF7, 0x65, 0xFB, 0x07, 0x9C, 0x04, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0xDB, 0x1B, 0xC3, 0x42, 0x8C, 0xD5, ++0x64, 0x4E, 0xDF, 0xF8, 0x98, 0xA1, 0x5F, 0xE0, 0x07, 0xAA, 0x0A, 0xFB, 0x06, 0x80, 0x06, 0xA9, 0x03, 0xF0, 0x78, 0xFB, ++0x83, 0x46, 0xE4, 0xF7, 0x51, 0xFB, 0x06, 0x9A, 0xA2, 0xF5, 0x7A, 0x62, 0x10, 0x1A, 0xDD, 0xE9, 0x04, 0x23, 0x06, 0x90, ++0xA2, 0xEB, 0x03, 0x0A, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD1, 0x02, 0x9B, 0x10, 0xEB, 0x0A, 0x0F, 0x54, 0xBF, 0x1C, 0x46, ++0x04, 0x46, 0xE4, 0xF7, 0x3D, 0xFB, 0x07, 0x9B, 0x03, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0x53, 0x44, 0xC3, 0x42, 0x65, 0xD4, ++0x50, 0x4E, 0x58, 0xE7, 0x06, 0x9E, 0x02, 0x9B, 0x9A, 0x1B, 0x00, 0x2A, 0xF8, 0xDB, 0xE4, 0xF7, 0x2D, 0xFB, 0x00, 0xF5, ++0x0C, 0x50, 0x36, 0x1B, 0x28, 0x30, 0x86, 0x42, 0x49, 0x4E, 0x11, 0xD9, 0x49, 0x46, 0x20, 0x46, 0x5A, 0x46, 0xD6, 0xF8, ++0x88, 0x30, 0x98, 0x47, 0x06, 0x9C, 0xD6, 0xF8, 0x88, 0x90, 0xE4, 0xF7, 0x1B, 0xFB, 0xA4, 0xF5, 0x7A, 0x64, 0xDA, 0xF8, ++0x40, 0x10, 0x20, 0x1A, 0x5A, 0x46, 0xC8, 0x47, 0x07, 0x9C, 0x02, 0x9B, 0x1B, 0x1B, 0x00, 0x2B, 0xBF, 0xF6, 0x33, 0xAF, ++0x02, 0x9C, 0x30, 0xE7, 0x96, 0xF8, 0x4E, 0x00, 0x01, 0x93, 0xFF, 0x28, 0x51, 0xD1, 0x03, 0x99, 0x0A, 0x44, 0xB1, 0xEB, ++0x52, 0x0F, 0x4F, 0xEA, 0x52, 0x03, 0xA1, 0xD8, 0x03, 0x9A, 0x35, 0x4E, 0xDF, 0xF8, 0xD8, 0xA0, 0xA4, 0x1A, 0x1C, 0x44, ++0x99, 0xF8, 0x18, 0x30, 0xD6, 0xF8, 0x88, 0x80, 0x02, 0x2B, 0x03, 0xF1, 0x01, 0x01, 0x7B, 0xD0, 0xC1, 0xEB, 0xC1, 0x01, ++0x0A, 0xEB, 0x81, 0x01, 0x0A, 0x7E, 0xFF, 0x2A, 0x0E, 0xD1, 0x01, 0x2B, 0x03, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, ++0xC3, 0xEB, 0xC3, 0x03, 0x0A, 0xEB, 0x83, 0x0A, 0x9A, 0xF8, 0x18, 0x30, 0xFF, 0x2B, 0x14, 0xBF, 0x51, 0x46, 0x00, 0x21, ++0x20, 0x46, 0x00, 0x22, 0xC0, 0x47, 0xD6, 0xF8, 0x88, 0x30, 0x2A, 0x46, 0x49, 0x46, 0x38, 0x46, 0x98, 0x47, 0x09, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x06, 0x83, 0x1B, 0x4E, 0x19, 0x6C, 0xD6, 0xF8, 0x88, 0x30, ++0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0xD6, 0xF8, 0x88, 0x30, 0x07, 0x98, 0x49, 0x46, 0x00, 0x22, 0x98, 0x47, 0xBB, 0xF1, ++0x00, 0x0F, 0xAD, 0xD0, 0x06, 0x9C, 0x02, 0x9B, 0x1A, 0xEB, 0x04, 0x0F, 0x58, 0xBF, 0x1C, 0x46, 0xD9, 0xE6, 0x07, 0xAA, ++0x06, 0xA9, 0x0A, 0xFB, 0x00, 0x80, 0x03, 0xF0, 0xD3, 0xFA, 0x06, 0x9C, 0xE4, 0xF7, 0xAC, 0xFA, 0x01, 0x9B, 0x1B, 0x1B, ++0xC3, 0x42, 0x3F, 0xF5, 0xD6, 0xAE, 0x06, 0x9C, 0x08, 0x4E, 0xDF, 0xF8, 0x28, 0xA0, 0xE4, 0xF7, 0xA1, 0xFA, 0x07, 0x9B, ++0xA4, 0xF5, 0x7A, 0x64, 0xFA, 0x1A, 0x24, 0x1A, 0x17, 0xEA, 0x22, 0x07, 0x38, 0xBF, 0x1F, 0x46, 0x9C, 0xE7, 0x00, 0xBF, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0xDD, 0xE9, 0x06, 0x64, ++0xE4, 0xF7, 0x8A, 0xFA, 0x02, 0x9B, 0x04, 0x9A, 0xF6, 0x1A, 0x32, 0x44, 0x13, 0x1A, 0x00, 0x2B, 0x5B, 0xDB, 0xE4, 0xF7, ++0x81, 0xFA, 0x3B, 0x1B, 0xA3, 0xF5, 0x0C, 0x53, 0x28, 0x3B, 0x18, 0x1A, 0x00, 0x28, 0xBF, 0xF6, 0x1B, 0xAF, 0xA6, 0xE6, ++0x37, 0x4E, 0x67, 0xE7, 0x9A, 0xF8, 0x18, 0x30, 0xFF, 0x2B, 0x5F, 0xD1, 0x01, 0x23, 0x89, 0xE7, 0x02, 0x9C, 0x37, 0xE7, ++0xE4, 0xF7, 0x6C, 0xFA, 0x02, 0x9B, 0xF6, 0x1A, 0x04, 0x9B, 0x33, 0x44, 0x1B, 0x1A, 0x00, 0x2B, 0x4A, 0xDB, 0x01, 0x97, ++0xE4, 0xF7, 0x62, 0xFA, 0x07, 0x9B, 0x03, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0xDB, 0x1B, 0xC3, 0x42, 0x4A, 0xD5, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x0B, 0x83, 0x27, 0x4E, 0x1A, 0x6C, 0xDF, 0xF8, 0x9C, 0xA0, 0x11, 0x7E, 0xD6, 0xF8, 0x88, 0x30, ++0x02, 0x29, 0x01, 0xF1, 0x01, 0x02, 0x2B, 0xD0, 0xC2, 0xEB, 0xC2, 0x00, 0x0A, 0xEB, 0x80, 0x00, 0x00, 0x7E, 0xFF, 0x28, ++0x37, 0xD1, 0x01, 0x29, 0x01, 0xF1, 0x02, 0x02, 0x08, 0xBF, 0x00, 0x22, 0xC2, 0xEB, 0xC2, 0x01, 0x0A, 0xEB, 0x81, 0x01, ++0x09, 0x7E, 0xFF, 0x29, 0x08, 0xBF, 0x00, 0x21, 0x29, 0xD1, 0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x0B, 0x88, 0x01, 0x98, 0xD8, 0xF8, 0x40, 0x10, 0xD6, 0xF8, 0x88, 0x30, 0x00, 0x22, 0x98, 0x47, 0x07, 0x9C, ++0x2C, 0xE7, 0x06, 0x9E, 0xE4, 0xF7, 0x24, 0xFA, 0xA6, 0xF5, 0x7A, 0x66, 0x37, 0x1A, 0x9C, 0xE7, 0x9A, 0xF8, 0x18, 0x20, ++0xFF, 0x2A, 0x0D, 0xD1, 0x01, 0x22, 0xD9, 0xE7, 0x06, 0x9E, 0xE4, 0xF7, 0x17, 0xFA, 0xA6, 0xF5, 0x7A, 0x66, 0x33, 0x1A, ++0x01, 0x93, 0xAD, 0xE7, 0x05, 0x49, 0x33, 0xE7, 0x01, 0x9F, 0xAF, 0xE6, 0x00, 0x22, 0x1C, 0x21, 0x01, 0xFB, 0x02, 0xA1, ++0xD1, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x30, 0xB5, 0x0E, 0x48, 0x83, 0xB0, 0x06, 0xF0, ++0x59, 0xFA, 0x01, 0x90, 0xA0, 0xB1, 0x0C, 0x4B, 0x0C, 0x4C, 0xD3, 0xF8, 0xD8, 0x31, 0x0C, 0x48, 0x98, 0x47, 0x00, 0x23, ++0x01, 0x99, 0xA3, 0x64, 0x04, 0xF1, 0x18, 0x05, 0x20, 0x34, 0x28, 0x46, 0x06, 0xF0, 0x04, 0xFA, 0x20, 0x46, 0x06, 0xF0, ++0x45, 0xFA, 0x01, 0x46, 0x00, 0x28, 0xF6, 0xD1, 0x03, 0xB0, 0x30, 0xBD, 0x50, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x4C, 0x4B, 0x42, 0x69, 0x1F, 0x69, 0x4C, 0x4B, ++0x4C, 0x4C, 0x98, 0x42, 0x83, 0xB0, 0x05, 0x46, 0x17, 0x44, 0x6F, 0xD0, 0xA3, 0x6A, 0xAB, 0x42, 0x04, 0xD0, 0xE4, 0xF7, ++0xCD, 0xF9, 0x07, 0xF5, 0x7A, 0x67, 0x07, 0x44, 0x94, 0xF8, 0x5B, 0x80, 0x94, 0xF8, 0x58, 0x30, 0xC4, 0xE9, 0x14, 0x57, ++0xB8, 0xF1, 0x00, 0x0F, 0x57, 0xD1, 0x42, 0x4E, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x73, 0x6B, 0x98, 0x47, ++0xD6, 0xF8, 0x88, 0x30, 0x42, 0x46, 0x41, 0x46, 0x38, 0x46, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, ++0x3A, 0xD0, 0x3A, 0x4B, 0xDF, 0xF8, 0xF8, 0x90, 0xDB, 0x1B, 0x01, 0x93, 0x4F, 0xF4, 0xA4, 0x68, 0x0C, 0xE0, 0x02, 0x2A, ++0x04, 0xBF, 0xB0, 0xF8, 0xD2, 0x20, 0x91, 0x02, 0x61, 0x44, 0x00, 0x22, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, ++0x00, 0x0F, 0x25, 0xD0, 0xDB, 0xF8, 0x04, 0xA0, 0xE4, 0xF7, 0x96, 0xF9, 0x01, 0x9B, 0xAA, 0xEB, 0x00, 0x00, 0xD8, 0x42, ++0x1C, 0xD5, 0x9B, 0xF8, 0x08, 0x00, 0xDB, 0xF8, 0x04, 0xC0, 0xF3, 0x6A, 0x08, 0xFB, 0x00, 0x90, 0x4F, 0xF4, 0xC8, 0x31, ++0x90, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xDC, 0xD1, 0x90, 0xF8, 0x6C, 0x20, 0x24, 0x4F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, ++0x02, 0x72, 0x91, 0x68, 0x00, 0x22, 0x61, 0x44, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, 0xD9, 0xD1, ++0xE3, 0x6A, 0xD3, 0xB1, 0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1B, 0xDB, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x43, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x94, 0xF8, 0x58, 0x30, ++0x5A, 0x07, 0x8B, 0xD4, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD6, 0xF8, ++0x9C, 0x30, 0x28, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x94, 0xF8, 0x58, 0x30, 0x13, 0xF0, 0x0C, 0x0F, ++0xDE, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0x86, 0x62, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x07, 0xF0, 0xAC, 0xBD, ++0x00, 0x10, 0x50, 0x40, 0x00, 0x9E, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x60, 0xF0, 0xFF, 0xFF, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x5C, 0xA1, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x10, 0xB5, 0x22, 0x4C, 0x94, 0xF8, 0x58, 0x30, 0xD8, 0x07, 0x11, 0xD5, 0x20, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, ++0x00, 0x2A, 0x22, 0xDB, 0x23, 0xF0, 0x01, 0x03, 0x43, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x1B, 0x4B, 0x1C, 0x48, ++0xDB, 0x6D, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x03, 0xF0, 0x06, 0x02, 0x02, 0x2A, 0x11, 0xD1, 0x15, 0x4A, 0x12, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x17, 0xDB, 0x23, 0xF0, 0x02, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x58, 0x30, ++0x10, 0x4B, 0x12, 0x48, 0xDB, 0x6D, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x10, 0xBD, 0x59, 0x07, 0xDA, 0xD5, 0x0F, 0x49, ++0x0F, 0x48, 0x40, 0xF2, 0x9B, 0x62, 0x07, 0xF0, 0x61, 0xFD, 0x94, 0xF8, 0x58, 0x30, 0xD1, 0xE7, 0x1A, 0x07, 0xE5, 0xD5, ++0x09, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0xA6, 0x62, 0x07, 0xF0, 0x56, 0xFD, 0x94, 0xF8, 0x58, 0x30, 0xDC, 0xE7, 0x00, 0xBF, ++0x30, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x9E, 0x17, 0x00, 0xE4, 0x9D, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x8C, 0xA1, 0x15, 0x00, 0xC0, 0xA1, 0x15, 0x00, 0x0D, 0x4A, 0x92, 0xF8, 0x58, 0x30, 0xD9, 0x06, ++0x14, 0xD4, 0x92, 0xF8, 0x5A, 0x00, 0x43, 0xF0, 0x10, 0x03, 0x82, 0xF8, 0x58, 0x30, 0x50, 0xB1, 0x08, 0x49, 0x09, 0x4B, ++0x09, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x01, 0xF5, 0xEA, 0x41, 0x02, 0xF1, 0x30, 0x00, 0x30, 0x31, 0x18, 0x47, 0x04, 0x4B, ++0xDB, 0x6B, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x70, 0xB5, 0x32, 0x4C, 0x00, 0x23, 0x05, 0x46, 0xA3, 0x62, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x2E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x4A, 0x2E, 0x4E, 0x11, 0x68, 0x73, 0x68, 0x48, 0x1C, 0x23, 0xF0, 0x02, 0x03, ++0x10, 0x60, 0x73, 0x60, 0x18, 0xB1, 0x28, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0xF9, 0xB1, 0x29, 0x49, 0x94, 0xF8, 0x5C, 0x30, ++0x0A, 0x68, 0x9B, 0x00, 0x22, 0xF0, 0x04, 0x02, 0x03, 0xF0, 0x04, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x2B, 0x7E, 0x03, 0x2B, ++0x26, 0xD0, 0x04, 0x2B, 0x94, 0xF8, 0x58, 0x30, 0x19, 0xD0, 0x23, 0xF0, 0x10, 0x02, 0xFF, 0x21, 0x9B, 0x07, 0x29, 0x76, ++0x84, 0xF8, 0x58, 0x20, 0x02, 0xD0, 0x1D, 0x4B, 0x1B, 0x6C, 0x98, 0x47, 0xE3, 0x6A, 0x23, 0xB1, 0x70, 0xBD, 0x00, 0x2B, ++0xDD, 0xD0, 0x62, 0xB6, 0xDB, 0xE7, 0x18, 0x4B, 0xD3, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xBD, 0xE8, 0x70, 0x40, 0xFB, 0xF7, ++0x93, 0xBA, 0x23, 0xF0, 0x04, 0x02, 0x84, 0xF8, 0x58, 0x20, 0xEA, 0x89, 0x92, 0xB9, 0x03, 0xF0, 0xDB, 0x03, 0xDC, 0xE7, ++0x94, 0xF8, 0x58, 0x30, 0x23, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x58, 0x30, 0xFE, 0xF7, 0x84, 0xFE, 0xFF, 0x22, 0x02, 0x21, ++0x86, 0x20, 0x05, 0xF0, 0x49, 0xFC, 0x94, 0xF8, 0x58, 0x30, 0xCC, 0xE7, 0x28, 0x46, 0xFE, 0xF7, 0xB1, 0xFE, 0x94, 0xF8, ++0x58, 0x30, 0xC6, 0xE7, 0x30, 0x9D, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x4C, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x6B, 0x4F, 0x6C, 0x4E, 0x04, 0x46, 0x6C, 0x48, ++0x06, 0xF0, 0x96, 0xF8, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0xC0, 0xF2, 0x85, 0x80, 0x33, 0x78, ++0x00, 0x2B, 0x44, 0xD0, 0x66, 0x4C, 0x01, 0x2B, 0x42, 0xD1, 0x94, 0xF8, 0x58, 0x30, 0x19, 0x07, 0x00, 0xF1, 0x9D, 0x80, ++0x5A, 0x07, 0x40, 0xF1, 0xB0, 0x80, 0x62, 0x4F, 0xE3, 0x6A, 0xBB, 0x42, 0x02, 0xD0, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, ++0xA3, 0x6A, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, 0x00, 0x23, 0xC4, 0xE9, 0x0A, 0x73, 0x39, 0x7E, 0x04, 0x23, 0x03, 0x29, ++0x3B, 0x74, 0x00, 0xF0, 0xA0, 0x80, 0x02, 0x29, 0x24, 0xD9, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x55, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x55, 0x4A, 0x55, 0x48, 0x17, 0x68, 0x43, 0x68, 0x79, 0x1C, 0x43, 0xF0, 0x02, 0x03, ++0x11, 0x60, 0x43, 0x60, 0x29, 0xB1, 0x4F, 0x4B, 0x17, 0x60, 0x1B, 0x68, 0x0F, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x4F, 0x4A, ++0xA3, 0x6A, 0x11, 0x68, 0xC1, 0xF3, 0x80, 0x01, 0x84, 0xF8, 0x5C, 0x10, 0x11, 0x68, 0x21, 0xF0, 0x04, 0x01, 0x11, 0x60, ++0x01, 0xE0, 0x44, 0x4C, 0xA3, 0x6A, 0x01, 0x22, 0x1A, 0x74, 0x22, 0x6D, 0x00, 0x23, 0x33, 0x70, 0x00, 0x2A, 0x31, 0xD0, ++0x94, 0xF8, 0x5A, 0x20, 0x23, 0x65, 0x00, 0x2A, 0x53, 0xD0, 0x01, 0x2A, 0x53, 0xD0, 0x23, 0x69, 0x00, 0x2B, 0x50, 0xD0, ++0x1B, 0x7A, 0x40, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x18, 0x6C, 0xA8, 0x60, 0x18, 0xB1, 0x3D, 0x4B, ++0xD3, 0xF8, 0x9C, 0x30, 0x98, 0x47, 0x3C, 0x48, 0x29, 0x46, 0x05, 0xF0, 0xDF, 0xFF, 0xA0, 0x6A, 0x03, 0x7E, 0x02, 0x2B, ++0x02, 0xD9, 0x37, 0x4B, 0x9B, 0x6B, 0x98, 0x47, 0x20, 0x6A, 0xA0, 0x64, 0x58, 0xB3, 0x36, 0x4B, 0x41, 0x68, 0x1B, 0x69, ++0xCB, 0x1A, 0x14, 0x2B, 0x27, 0xD4, 0x31, 0x4B, 0x33, 0x48, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, ++0xA8, 0x68, 0xDD, 0xE7, 0x84, 0x42, 0x32, 0xD0, 0x2F, 0x49, 0x30, 0x48, 0x40, 0xF2, 0x4F, 0x72, 0x07, 0xF0, 0x12, 0xFC, ++0x33, 0x78, 0x00, 0x2B, 0x7F, 0xF4, 0x72, 0xAF, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB1, 0xDA, 0x1D, 0x4C, ++0xA3, 0x6A, 0x00, 0x2B, 0xAF, 0xD1, 0x26, 0x49, 0x27, 0x48, 0x40, 0xF2, 0x51, 0x72, 0x07, 0xF0, 0xFF, 0xFB, 0x33, 0x78, ++0x61, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x63, 0x6C, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x22, 0x4F, 0x64, 0xE7, 0xAA, 0x60, ++0xBB, 0xE7, 0x21, 0x48, 0x02, 0x7E, 0xFF, 0x2A, 0xB1, 0xD1, 0x90, 0xF8, 0x34, 0x20, 0xFF, 0x2A, 0x12, 0xD1, 0x90, 0xF8, ++0x50, 0x20, 0xFF, 0x2A, 0x10, 0xD1, 0xAB, 0x60, 0xAD, 0xE7, 0x33, 0x78, 0x00, 0x2B, 0xD8, 0xD0, 0x44, 0xE7, 0xE7, 0x6A, ++0x00, 0x2F, 0x87, 0xD0, 0x52, 0xE7, 0x02, 0x20, 0x05, 0xF0, 0xF2, 0xFC, 0x39, 0x7E, 0x5A, 0xE7, 0x1C, 0x30, 0x98, 0xE7, ++0x38, 0x30, 0x96, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x17, 0x2C, 0x17, 0x00, 0x50, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, ++0x00, 0x9E, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x9D, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xF4, 0xA1, 0x15, 0x00, 0x10, 0xA2, 0x15, 0x00, 0xE4, 0x9D, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x0D, 0x4B, 0x93, 0xF8, 0x58, 0x20, 0x11, 0x07, 0x03, 0xD4, 0x52, 0x07, 0x0D, 0xD5, 0x0B, 0x49, 0x00, 0xE0, 0x0B, 0x49, ++0xDA, 0x6A, 0x8A, 0x42, 0x03, 0xD0, 0x0A, 0xB1, 0x01, 0x20, 0x10, 0x74, 0xD9, 0x62, 0x08, 0x4B, 0xD3, 0xF8, 0x98, 0x30, ++0x18, 0x47, 0xDB, 0x6A, 0x00, 0x2B, 0xF8, 0xD1, 0x05, 0x49, 0x08, 0x20, 0x07, 0xF0, 0x68, 0xB9, 0x30, 0x9D, 0x17, 0x00, ++0x00, 0x9E, 0x17, 0x00, 0xE4, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x28, 0xA2, 0x15, 0x00, 0x0B, 0x4A, 0x92, 0xF8, ++0x59, 0x30, 0x43, 0xB1, 0x01, 0x3B, 0xDB, 0xB2, 0x82, 0xF8, 0x59, 0x30, 0x1B, 0xB9, 0x08, 0x4A, 0x11, 0x78, 0x01, 0x29, ++0x00, 0xD0, 0x70, 0x47, 0x10, 0xB5, 0x06, 0x4C, 0x13, 0x70, 0xD4, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xE3, 0x6F, 0xBD, 0xE8, ++0x10, 0x40, 0x18, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x17, 0x2C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x1D, 0x4B, ++0x1D, 0x49, 0x1E, 0x4A, 0xD3, 0xF8, 0xE0, 0x33, 0x8C, 0x68, 0x95, 0x6A, 0x98, 0x47, 0x1C, 0x4B, 0x5B, 0x78, 0x23, 0xB1, ++0x1B, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x1A, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x13, 0x60, ++0x1C, 0xB3, 0x18, 0x4F, 0x8C, 0x26, 0x01, 0xE0, 0x24, 0x68, 0xF4, 0xB1, 0x23, 0x6C, 0xAB, 0x42, 0xFA, 0xD1, 0x94, 0xF8, ++0x62, 0x30, 0x00, 0x2B, 0xF6, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x22, ++0x11, 0x46, 0x3B, 0xB1, 0x94, 0xF8, 0xC1, 0x34, 0x06, 0xFB, 0x03, 0x73, 0x93, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0xE5, 0xD0, ++0x94, 0xF8, 0x6C, 0x00, 0xF2, 0xF7, 0xD6, 0xFD, 0x24, 0x68, 0x00, 0x2C, 0xE0, 0xD1, 0xF8, 0xBD, 0x88, 0x1A, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, ++0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x08, 0x81, 0x3D, 0x4A, 0x3E, 0x4E, 0xD8, 0xF8, 0xDC, 0x33, ++0x94, 0x68, 0x96, 0xF8, 0x59, 0x90, 0x83, 0xB0, 0x98, 0x47, 0xB5, 0x6A, 0x00, 0x2D, 0x5E, 0xD0, 0x39, 0x4A, 0x3A, 0x49, ++0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x4B, 0x78, 0x4F, 0x46, 0x00, 0x2B, 0x4D, 0xD1, 0x00, 0x2C, 0x3A, 0xD0, ++0xDF, 0xF8, 0xD8, 0xB0, 0xDF, 0xF8, 0xD8, 0xA0, 0x4F, 0xF0, 0x06, 0x09, 0x01, 0xE0, 0x24, 0x68, 0x7C, 0xB3, 0x23, 0x6C, ++0x9D, 0x42, 0xFA, 0xD1, 0x94, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xF6, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, ++0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x4F, 0xF0, 0x8C, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0xEA, 0xD0, 0x94, 0xF8, 0xC0, 0x34, ++0x3B, 0xB1, 0x94, 0xF8, 0xC1, 0x34, 0x01, 0xFB, 0x03, 0xA3, 0x93, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0xDF, 0xD0, 0x2B, 0x7C, ++0x85, 0xF8, 0x10, 0x90, 0xD8, 0xF8, 0xB0, 0x10, 0x01, 0x93, 0xF2, 0xF7, 0x79, 0xFD, 0x01, 0x9B, 0x00, 0xB9, 0x01, 0x37, ++0x01, 0x22, 0x2B, 0x74, 0x8B, 0xF8, 0x00, 0x20, 0x24, 0x68, 0x00, 0x2C, 0xCF, 0xD1, 0x5F, 0xFA, 0x87, 0xF9, 0x96, 0xF8, ++0x59, 0x40, 0xF5, 0x6A, 0x86, 0xF8, 0x59, 0x90, 0x3C, 0x1B, 0xAD, 0xB1, 0x27, 0xB1, 0x03, 0x23, 0x2B, 0x74, 0xD8, 0xF8, ++0x60, 0x31, 0x98, 0x47, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD2, 0xF8, 0xE8, 0x33, 0x43, 0xF0, 0x00, 0x43, ++0xC2, 0xF8, 0xE8, 0x33, 0xAA, 0xE7, 0x00, 0x24, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD8, 0xF8, 0x60, 0x31, ++0x98, 0x47, 0x00, 0x2F, 0xF5, 0xD0, 0x96, 0xF8, 0x59, 0x30, 0x01, 0x3B, 0x2C, 0x46, 0x86, 0xF8, 0x59, 0x30, 0xE3, 0xE7, ++0x00, 0x88, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x17, 0x2C, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0xD4, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xA3, 0x6E, ++0x98, 0x47, 0x18, 0xB9, 0xE3, 0x6F, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x43, 0x4D, 0x4E, 0x4E, 0x4F, 0xF4, 0x6A, 0x85, 0xB0, 0x00, 0x25, 0xE2, 0x88, 0x61, 0x79, 0x23, 0x89, ++0x20, 0x79, 0x02, 0x95, 0x65, 0x7B, 0x01, 0x95, 0x65, 0x89, 0x00, 0x95, 0xE3, 0xF7, 0x72, 0xFD, 0xD7, 0xF8, 0x3C, 0x33, ++0x94, 0xF9, 0x0C, 0x00, 0x98, 0x47, 0x21, 0x79, 0x44, 0x4B, 0x45, 0x4A, 0x03, 0xEB, 0x81, 0x03, 0x5B, 0x69, 0x13, 0x60, ++0x23, 0x7E, 0x03, 0x2B, 0x02, 0xD0, 0x20, 0x46, 0xFE, 0xF7, 0xFE, 0xFB, 0xB3, 0x6A, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, ++0x00, 0x23, 0xC6, 0xE9, 0x0A, 0x43, 0x23, 0x7E, 0x04, 0x22, 0x02, 0x2B, 0x22, 0x74, 0x4E, 0xD9, 0x96, 0xF8, 0x5A, 0x20, ++0x00, 0x2A, 0x4A, 0xD0, 0x03, 0x2B, 0x52, 0xD0, 0x04, 0x2B, 0x24, 0xD0, 0xFB, 0x6E, 0x98, 0x47, 0x23, 0x7E, 0x02, 0x2B, ++0x1F, 0xD8, 0x34, 0x4B, 0x9D, 0x68, 0x00, 0x2D, 0x37, 0xD0, 0xDF, 0xF8, 0xE4, 0x90, 0x4F, 0xF0, 0x01, 0x08, 0x01, 0xE0, ++0x2D, 0x68, 0x8D, 0xB1, 0x2B, 0x6C, 0xA3, 0x42, 0xFA, 0xD1, 0x95, 0xF8, 0x63, 0x30, 0xD7, 0xF8, 0x5C, 0x24, 0xC3, 0xEB, ++0xC3, 0x03, 0x09, 0xEB, 0x83, 0x03, 0x28, 0x46, 0x83, 0xF8, 0x1B, 0x80, 0x90, 0x47, 0x2D, 0x68, 0x00, 0x2D, 0xED, 0xD1, ++0x23, 0x7E, 0x02, 0x2B, 0x1B, 0xD9, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x22, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x22, 0x4A, 0x22, 0x4C, 0x11, 0x68, 0x63, 0x68, 0x48, 0x1C, 0x43, 0xF0, 0x02, 0x03, 0x10, 0x60, 0x63, 0x60, ++0x28, 0xBB, 0x1F, 0x4B, 0x19, 0x68, 0x1A, 0x68, 0xC1, 0xF3, 0x80, 0x01, 0x22, 0xF0, 0x04, 0x02, 0x86, 0xF8, 0x5C, 0x10, ++0x1A, 0x60, 0xD7, 0xF8, 0x60, 0x31, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, 0x18, 0x4A, 0x92, 0xF8, 0xFF, 0x21, ++0x00, 0x2A, 0xAF, 0xD0, 0xF1, 0xF7, 0xA2, 0xFB, 0x23, 0x7E, 0x03, 0x2B, 0xAC, 0xD1, 0x14, 0x4B, 0x00, 0x22, 0x1A, 0x60, ++0x02, 0x21, 0xFF, 0x22, 0x85, 0x20, 0x05, 0xF0, 0x77, 0xF9, 0x23, 0x7E, 0x02, 0x2B, 0xE4, 0xD9, 0xC7, 0xE7, 0x09, 0x4B, ++0x11, 0x60, 0x1B, 0x68, 0x00, 0x29, 0xD4, 0xD1, 0x00, 0x2B, 0xD2, 0xD0, 0x62, 0xB6, 0xD0, 0xE7, 0x30, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x20, 0x62, 0x17, 0x00, 0x20, 0x02, 0x32, 0x40, ++0x80, 0x9F, 0x17, 0x00, 0x70, 0xB5, 0x25, 0x4D, 0xEA, 0x6A, 0x04, 0x46, 0x0A, 0xB1, 0xE8, 0x62, 0x70, 0xBD, 0xAE, 0x6A, ++0x86, 0x42, 0x3D, 0xD0, 0x5E, 0xB1, 0x33, 0x7E, 0x03, 0x2B, 0x08, 0xD0, 0x01, 0x23, 0x0C, 0x21, 0x45, 0x20, 0x05, 0xF0, ++0xD7, 0xF8, 0x33, 0x7E, 0x03, 0x70, 0x05, 0xF0, 0x03, 0xF9, 0x1B, 0x4B, 0x5B, 0x68, 0x00, 0x2B, 0x1C, 0xDD, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x17, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x17, 0x4E, 0x33, 0x68, 0x04, 0x20, ++0x01, 0x33, 0x33, 0x60, 0xF1, 0xF7, 0x42, 0xF8, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xF1, 0xF7, 0xDD, 0xF8, 0x33, 0x68, ++0x33, 0xB1, 0x0F, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x02, 0x22, 0xEC, 0x62, ++0x04, 0x23, 0x22, 0x74, 0x00, 0x21, 0xFF, 0x22, 0x84, 0x20, 0x05, 0xF0, 0xA9, 0xF8, 0x09, 0x4B, 0x1B, 0x6E, 0x03, 0x60, ++0xBD, 0xE8, 0x70, 0x40, 0x05, 0xF0, 0xD2, 0xB8, 0x04, 0x23, 0x33, 0x74, 0x70, 0xBD, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, ++0xD8, 0x9C, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x0A, 0x4D, ++0x04, 0x46, 0xD5, 0xF8, 0x6C, 0x31, 0x00, 0x6D, 0x98, 0x47, 0xD5, 0xF8, 0x00, 0x32, 0x20, 0x65, 0x01, 0x46, 0x20, 0x46, ++0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x40, 0x03, 0x43, 0xF0, 0x20, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x38, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x02, 0x6D, 0x41, 0x6A, 0x70, 0xB5, 0x17, 0x4D, 0x04, 0x46, 0xD5, 0xF8, 0xE0, 0x31, 0x11, 0x44, ++0x18, 0x30, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x20, 0x02, 0xDB, 0x07, 0x84, 0xF8, 0x4D, 0x20, 0x0E, 0xD5, ++0x10, 0x4B, 0x5B, 0x6A, 0x23, 0xB1, 0xDA, 0x68, 0x04, 0xF1, 0x44, 0x03, 0x9A, 0x42, 0x07, 0xD0, 0xEB, 0x6A, 0x61, 0x6A, ++0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x70, 0xBD, 0x6B, 0x6B, 0x98, 0x47, 0xEB, 0x6A, 0x61, 0x6A, ++0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0x06, 0x4A, 0xD5, 0xF8, 0x84, 0x30, 0x11, 0x69, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, ++0x70, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF8, 0x43, ++0xDF, 0xF8, 0xB8, 0x80, 0x90, 0xF8, 0x4E, 0x70, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x07, 0x85, 0x95, 0xF8, 0x4D, 0x60, ++0x16, 0xF0, 0x60, 0x06, 0x1F, 0xD1, 0x26, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xFC, 0x31, 0x89, 0x46, 0x90, 0xF8, 0x4F, 0x10, ++0x28, 0x46, 0x98, 0x47, 0x63, 0x6D, 0xA0, 0xEB, 0x09, 0x01, 0x58, 0x1A, 0x00, 0xB2, 0x80, 0xEA, 0xE0, 0x73, 0xA3, 0xEB, ++0xE0, 0x73, 0x9B, 0xB2, 0xB3, 0xF5, 0xFA, 0x6F, 0xA4, 0xF8, 0x58, 0x00, 0x09, 0xD9, 0x95, 0xF8, 0x4D, 0x30, 0x23, 0xF0, ++0x40, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x85, 0xF8, 0x4D, 0x30, 0xBD, 0xE8, 0xF8, 0x83, 0xC8, 0x2B, 0xFB, 0xD9, 0x15, 0x4B, ++0x9B, 0x68, 0x9B, 0xB1, 0x95, 0xF8, 0x63, 0x10, 0x30, 0x46, 0x93, 0xF8, 0x4E, 0x20, 0x8A, 0x42, 0x07, 0xD1, 0xB3, 0xF9, ++0x58, 0x20, 0x90, 0x42, 0xA8, 0xBF, 0x10, 0x46, 0x96, 0x42, 0xB8, 0xBF, 0x16, 0x46, 0x1B, 0x68, 0x00, 0x2B, 0xF0, 0xD1, ++0x60, 0xB9, 0x73, 0x10, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x87, 0x97, 0xF8, 0x4D, 0x20, 0x3B, 0x65, 0x42, 0xF0, ++0x40, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0xD8, 0xE7, 0x00, 0x2E, 0xD6, 0xD1, 0x00, 0xEB, 0xD0, 0x73, 0x5B, 0x10, 0xED, 0xE7, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x23, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x60, 0x22, ++0x00, 0x21, 0x22, 0x4F, 0x06, 0x46, 0xE2, 0xF7, 0xD3, 0xFB, 0x00, 0x25, 0x3C, 0x46, 0xA8, 0x46, 0x00, 0x21, 0x1C, 0x22, ++0x20, 0x46, 0xE2, 0xF7, 0xCB, 0xFB, 0xFF, 0x23, 0x02, 0x2D, 0xE3, 0x81, 0x23, 0x76, 0xE3, 0x76, 0x21, 0x46, 0x30, 0x46, ++0x04, 0xD8, 0x05, 0xF0, 0x55, 0xFC, 0x01, 0x35, 0x1C, 0x34, 0xED, 0xE7, 0x03, 0x2D, 0x22, 0xD0, 0x04, 0x2D, 0xF8, 0xD1, ++0x14, 0x48, 0x05, 0xF0, 0x47, 0xFC, 0x14, 0x48, 0x05, 0xF0, 0x44, 0xFC, 0x13, 0x49, 0x11, 0x48, 0x05, 0xF0, 0x44, 0xFC, ++0x12, 0x49, 0x0F, 0x48, 0x05, 0xF0, 0x40, 0xFC, 0x11, 0x49, 0x0D, 0x48, 0x05, 0xF0, 0x3C, 0xFC, 0x10, 0x49, 0x0B, 0x48, ++0x05, 0xF0, 0x38, 0xFC, 0x0F, 0x4A, 0x07, 0x4B, 0xD2, 0xF8, 0xAC, 0x10, 0xD0, 0x6B, 0x58, 0x63, 0x00, 0x22, 0xC3, 0xE9, ++0x11, 0x12, 0xBD, 0xE8, 0xF0, 0x81, 0xA7, 0xF8, 0x5E, 0x80, 0x87, 0xF8, 0x59, 0x80, 0xD2, 0xE7, 0x30, 0x9D, 0x17, 0x00, ++0x90, 0x9D, 0x17, 0x00, 0x48, 0x9D, 0x17, 0x00, 0x50, 0x9D, 0x17, 0x00, 0xF0, 0x9C, 0x17, 0x00, 0x00, 0x9D, 0x17, 0x00, ++0x10, 0x9D, 0x17, 0x00, 0x20, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x21, 0x4C, 0x24, 0x68, ++0xB4, 0xF9, 0x00, 0x40, 0x83, 0xB0, 0x00, 0x2C, 0x9D, 0xF8, 0x28, 0x90, 0x9D, 0xF8, 0x2C, 0x80, 0x1D, 0x4C, 0x07, 0x46, ++0x0D, 0x46, 0x16, 0x46, 0x27, 0xDB, 0x1C, 0x49, 0x84, 0xF8, 0x58, 0x70, 0x91, 0xF8, 0x58, 0x20, 0xA4, 0xF8, 0x5C, 0x50, ++0xA4, 0xF8, 0x5A, 0x50, 0x42, 0xF0, 0x02, 0x07, 0x84, 0xF8, 0x60, 0x60, 0xFF, 0x25, 0x03, 0x26, 0x01, 0x20, 0xA3, 0x66, ++0xD3, 0x06, 0x84, 0xF8, 0x61, 0x90, 0x84, 0xF8, 0x6E, 0x80, 0x81, 0xF8, 0x58, 0x70, 0x84, 0xF8, 0x6C, 0x60, 0xA4, 0xF8, ++0x62, 0x50, 0x84, 0xF8, 0x64, 0x00, 0x05, 0xD4, 0x0D, 0x4B, 0x1B, 0x6C, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x94, 0xF8, 0x6C, 0x20, 0xFF, 0x2A, 0xD3, 0xD0, 0x08, 0x49, 0x08, 0x48, 0x01, 0x93, ++0x40, 0xF6, 0x8C, 0x22, 0x07, 0xF0, 0x26, 0xF8, 0x01, 0x9B, 0xCA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x48, 0xA2, 0x15, 0x00, 0xF0, 0xB5, 0x65, 0x4F, ++0x04, 0x46, 0x83, 0xB0, 0x97, 0xF8, 0x80, 0x00, 0xE3, 0x68, 0x22, 0x78, 0x00, 0x90, 0x0E, 0x46, 0x08, 0x20, 0x61, 0x49, ++0x06, 0xF0, 0xE0, 0xFD, 0x25, 0x78, 0x25, 0xB3, 0x01, 0x2D, 0x2F, 0xD1, 0x97, 0xF8, 0x88, 0x30, 0xFF, 0x2B, 0x1A, 0xD0, ++0x97, 0xF8, 0x80, 0x30, 0x03, 0x2B, 0x2B, 0xD8, 0x01, 0x2B, 0x5A, 0x4C, 0x44, 0xD8, 0x09, 0xD1, 0x94, 0xF8, 0x58, 0x30, ++0x07, 0xF1, 0x70, 0x00, 0x23, 0xF0, 0x05, 0x03, 0x84, 0xF8, 0x58, 0x30, 0xFE, 0xF7, 0xE4, 0xF9, 0x94, 0xF8, 0x58, 0x30, ++0x03, 0xF0, 0x12, 0x02, 0xFF, 0x21, 0x10, 0x2A, 0x87, 0xF8, 0x88, 0x10, 0x24, 0xD0, 0x00, 0x25, 0x28, 0x46, 0x03, 0xB0, ++0xF0, 0xBD, 0x97, 0xF8, 0x88, 0x30, 0xFF, 0x2B, 0x3A, 0xD0, 0x4B, 0x4A, 0x92, 0xF8, 0x58, 0x30, 0x99, 0x06, 0x03, 0xD5, ++0x23, 0xF0, 0x20, 0x03, 0x82, 0xF8, 0x58, 0x30, 0x01, 0x25, 0x28, 0x46, 0x03, 0xB0, 0xF0, 0xBD, 0x04, 0x2B, 0x17, 0xD1, ++0x44, 0x48, 0x45, 0x4D, 0xA0, 0xF1, 0x40, 0x04, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x22, 0xD5, 0xF8, 0xAC, 0x30, ++0x20, 0x6A, 0xA2, 0x64, 0x98, 0x47, 0xD1, 0xE7, 0x3E, 0x4A, 0x3F, 0x48, 0xD2, 0xF8, 0xD8, 0x21, 0x23, 0xF0, 0x10, 0x03, ++0x84, 0xF8, 0x58, 0x30, 0x90, 0x47, 0xD0, 0xE7, 0x37, 0x4C, 0xC5, 0xE7, 0x94, 0xF8, 0x58, 0x30, 0xE2, 0x6A, 0x23, 0xF0, ++0x04, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x2A, 0xB1, 0x07, 0xF1, 0x70, 0x03, 0x9A, 0x42, 0x50, 0xD0, 0x00, 0x23, 0xE3, 0x62, ++0x33, 0x48, 0xFE, 0xF7, 0x99, 0xF9, 0xB3, 0xE7, 0x97, 0xF8, 0x80, 0x30, 0x04, 0x2B, 0xC0, 0xD0, 0x04, 0x20, 0x05, 0xF0, ++0x5D, 0xF9, 0x01, 0x28, 0xBB, 0xD0, 0x04, 0x23, 0x87, 0xF8, 0x88, 0x30, 0xA3, 0x78, 0x87, 0xF8, 0x74, 0x30, 0xE3, 0x78, ++0x87, 0xF8, 0x75, 0x30, 0xA3, 0x88, 0xE2, 0x88, 0xA7, 0xF8, 0x76, 0x30, 0x01, 0x21, 0x23, 0x89, 0x87, 0xF8, 0x80, 0x10, ++0xA7, 0xF8, 0x78, 0x20, 0xE2, 0x68, 0xA7, 0xF8, 0x7A, 0x30, 0x4F, 0xF4, 0x7A, 0x73, 0x03, 0xFB, 0x02, 0xF3, 0x23, 0x2A, ++0x84, 0xBF, 0xA3, 0xF5, 0x08, 0x43, 0xB8, 0x3B, 0xA7, 0xF8, 0x7E, 0x60, 0xC7, 0xF8, 0x84, 0x30, 0x63, 0x78, 0x17, 0x4A, ++0x87, 0xF8, 0x8A, 0x30, 0x23, 0x7C, 0x87, 0xF8, 0x7C, 0x30, 0x16, 0x49, 0x92, 0xF8, 0x58, 0x30, 0x66, 0xB9, 0x43, 0xF0, ++0x04, 0x03, 0xC9, 0x6D, 0x14, 0x48, 0x82, 0xF8, 0x58, 0x30, 0x88, 0x47, 0x13, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, ++0x13, 0x60, 0x8A, 0xE7, 0x43, 0xF0, 0x01, 0x03, 0x09, 0x6C, 0x82, 0xF8, 0x58, 0x30, 0x88, 0x47, 0xF2, 0xE7, 0x23, 0x6D, ++0x93, 0x42, 0xAB, 0xD1, 0x08, 0x4B, 0x04, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x23, 0xA3, 0x64, ++0xA2, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, 0x68, 0xA2, 0x15, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x60, 0x9D, 0x17, 0x00, 0x00, 0x9E, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x41, ++0x36, 0x4E, 0x84, 0xB0, 0x04, 0x46, 0x0F, 0x46, 0x33, 0x46, 0x00, 0x25, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, 0x1A, 0x79, ++0x20, 0x78, 0x90, 0x42, 0x1B, 0xD0, 0x01, 0x35, 0x03, 0x2D, 0x03, 0xF1, 0x1C, 0x03, 0xF3, 0xD1, 0x2E, 0x48, 0x05, 0xF0, ++0x15, 0xFB, 0x03, 0x46, 0x70, 0xB3, 0x2D, 0x4A, 0x86, 0x1B, 0xB6, 0x10, 0x02, 0xFB, 0x06, 0xF6, 0xF6, 0xB2, 0x06, 0x76, ++0x3E, 0x70, 0x20, 0x68, 0x61, 0x68, 0x04, 0x33, 0x03, 0xC3, 0x22, 0x89, 0x1A, 0x80, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, ++0xF0, 0x81, 0xD9, 0x88, 0x62, 0x88, 0x8A, 0x42, 0xDF, 0xD1, 0x93, 0xF8, 0x05, 0xC0, 0x61, 0x78, 0x8C, 0x45, 0x08, 0xD0, ++0x02, 0xD2, 0xBC, 0xF1, 0x03, 0x0F, 0x13, 0xD1, 0x8C, 0x45, 0xD4, 0xD9, 0x03, 0x29, 0xD2, 0xD0, 0x07, 0xE0, 0x19, 0x89, ++0xA2, 0x88, 0x91, 0x42, 0xCD, 0xD1, 0x59, 0x89, 0xE2, 0x88, 0x91, 0x42, 0xC9, 0xD1, 0x3D, 0x70, 0x00, 0x20, 0xDF, 0xE7, ++0x01, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0xDF, 0xF8, 0x48, 0xE0, 0xB4, 0xF8, 0x04, 0x80, 0xB4, 0xF8, 0x06, 0xC0, ++0xDE, 0xF8, 0x28, 0x30, 0xC5, 0xEB, 0xC5, 0x04, 0x06, 0xEB, 0x84, 0x04, 0xA3, 0x42, 0x61, 0x71, 0xA4, 0xF8, 0x08, 0x80, ++0xA4, 0xF8, 0x0A, 0xC0, 0xE5, 0xD1, 0x9E, 0xF8, 0x5A, 0x40, 0x01, 0x2C, 0xE1, 0xD1, 0x1C, 0x24, 0x04, 0xFB, 0x05, 0x66, ++0x00, 0x24, 0x76, 0x7B, 0xCD, 0xF8, 0x00, 0xC0, 0xCD, 0xE9, 0x01, 0x64, 0x43, 0x46, 0xE3, 0xF7, 0xCF, 0xF9, 0xD4, 0xE7, ++0x90, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0xB7, 0x6D, 0xDB, 0xB6, 0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x98, 0x80, ++0x20, 0x4D, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0xC0, 0xEB, 0xC0, 0x06, 0x00, 0x2B, 0x04, 0x46, 0x05, 0xEB, ++0x86, 0x06, 0x12, 0xDB, 0xC7, 0x00, 0x1B, 0x48, 0x31, 0x46, 0x3C, 0x1B, 0x05, 0xF0, 0x5C, 0xFA, 0x05, 0xEB, 0x84, 0x04, ++0x30, 0x46, 0x1C, 0x22, 0x00, 0x21, 0xE2, 0xF7, 0xC1, 0xF9, 0xFF, 0x23, 0xE3, 0x81, 0x23, 0x76, 0xE3, 0x76, 0xBD, 0xE8, ++0xF0, 0x81, 0xC0, 0xEB, 0xC0, 0x03, 0x05, 0xEB, 0x83, 0x03, 0xC7, 0x00, 0x1B, 0x7E, 0xFF, 0x2B, 0x0C, 0xD0, 0x3B, 0x1B, ++0x05, 0xEB, 0x83, 0x03, 0x5B, 0x7E, 0x00, 0x2B, 0xDF, 0xD0, 0x0C, 0x49, 0x0C, 0x48, 0x40, 0xF6, 0x5C, 0x32, 0x06, 0xF0, ++0x8F, 0xFE, 0xD8, 0xE7, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0x5A, 0x32, 0x06, 0xF0, 0x88, 0xFE, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE6, 0xDB, 0xCB, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0xA2, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xDF, 0xF8, 0x4C, 0x82, 0xDF, 0xF8, 0x24, 0xA2, 0xD8, 0xF8, 0x00, 0x20, 0x84, 0x4F, 0xB2, 0xF9, 0x00, 0x30, 0xC1, 0xEB, ++0xC1, 0x06, 0x00, 0x2B, 0x85, 0xB0, 0x0C, 0x46, 0x05, 0x46, 0x0A, 0xEB, 0x86, 0x06, 0x5F, 0xDB, 0x4F, 0xEA, 0xC4, 0x0B, ++0xAB, 0xEB, 0x04, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x4A, 0x7E, 0xDF, 0xF8, 0x1C, 0x92, 0x01, 0x32, ++0x03, 0xFB, 0x05, 0x73, 0xD2, 0xB2, 0x00, 0x20, 0x01, 0x2A, 0x4A, 0x76, 0x1E, 0x64, 0x83, 0xF8, 0x4D, 0x00, 0x6B, 0xD0, ++0xDF, 0xF8, 0x04, 0x82, 0x99, 0xF8, 0x5B, 0x10, 0x99, 0xF8, 0x5A, 0x30, 0x4F, 0xF4, 0x80, 0x70, 0xCD, 0xE9, 0x00, 0x31, ++0x6F, 0x49, 0x23, 0x46, 0x06, 0xF0, 0x12, 0xFC, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0x73, 0xFF, 0x21, 0x93, 0xF8, ++0xC0, 0x24, 0x83, 0xF8, 0x4E, 0x10, 0x4A, 0xB1, 0x69, 0x49, 0x93, 0xF8, 0xC1, 0x24, 0x8C, 0x20, 0x00, 0xFB, 0x02, 0x12, ++0x92, 0xF8, 0x70, 0x20, 0x01, 0x2A, 0x20, 0xD0, 0x65, 0x4B, 0x03, 0xF1, 0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, ++0xDA, 0x7E, 0xFF, 0x2A, 0x40, 0xF0, 0xAA, 0x80, 0x1C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0xD8, 0xF8, 0xB4, 0x30, 0x30, 0x46, ++0x98, 0x47, 0x5E, 0x4B, 0x1B, 0x7C, 0xAB, 0x42, 0x08, 0xD0, 0xFF, 0x2B, 0x06, 0xD0, 0xD8, 0xF8, 0x50, 0x30, 0x20, 0x46, ++0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x93, 0xF8, 0x4D, 0x20, 0x42, 0xF0, ++0x10, 0x02, 0x83, 0xF8, 0x4D, 0x20, 0xE4, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x73, 0x1B, 0x6C, 0x5B, 0xB1, ++0x50, 0x49, 0x51, 0x48, 0x40, 0xF6, 0x6B, 0x32, 0x06, 0xF0, 0xF4, 0xFD, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x8D, 0xDA, 0xC4, 0xEB, 0xC4, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0xC4, 0x0B, 0x1B, 0x7E, 0xFF, 0x2B, ++0x86, 0xD1, 0x46, 0x49, 0x47, 0x48, 0x40, 0xF6, 0x6C, 0x32, 0x06, 0xF0, 0xDF, 0xFD, 0x7F, 0xE7, 0x99, 0xF8, 0x5A, 0x00, ++0x0A, 0x74, 0x42, 0x1C, 0xD8, 0xF8, 0x00, 0x30, 0xD2, 0xB2, 0x89, 0xF8, 0x5A, 0x20, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x28, 0xDB, 0x02, 0x2A, 0x3C, 0xD0, 0x3E, 0x48, 0x31, 0x46, 0x05, 0xF0, 0x77, 0xF9, 0x99, 0xF8, 0x58, 0x30, 0x13, 0xF0, ++0x0C, 0x0F, 0x0F, 0xD0, 0xD8, 0xF8, 0x00, 0x20, 0xD9, 0xF8, 0x20, 0x30, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x20, 0xDB, ++0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0x9E, 0x60, 0x9A, 0xF8, 0x19, 0x20, 0x6B, 0xE7, 0xD9, 0xF8, 0x2C, 0x30, ++0x8B, 0xB3, 0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0xDF, 0xF8, 0xD0, 0x80, 0x9A, 0xF8, 0x19, 0x20, 0xC9, 0xF8, ++0x2C, 0x60, 0x5F, 0xE7, 0x02, 0x2A, 0xD4, 0xD9, 0x40, 0xF6, 0x81, 0x32, 0x25, 0x49, 0x29, 0x48, 0x06, 0xF0, 0xA0, 0xFD, ++0x99, 0xF8, 0x5A, 0x20, 0xCB, 0xE7, 0x00, 0x2B, 0xDC, 0xD1, 0x21, 0x49, 0x25, 0x48, 0x03, 0x93, 0x4F, 0xF4, 0x39, 0x62, ++0x06, 0xF0, 0x94, 0xFD, 0x03, 0x9B, 0xD3, 0xE7, 0x22, 0x48, 0x05, 0xF0, 0x37, 0xF9, 0x16, 0x4B, 0x03, 0xF5, 0xA4, 0x51, ++0x93, 0xF8, 0x4D, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x4D, 0x20, 0x03, 0xF5, 0xA4, 0x63, 0x99, 0x42, 0xF5, 0xD1, ++0xB1, 0xE7, 0xDF, 0xF8, 0x74, 0x80, 0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0xD8, 0xF8, 0x9C, 0x30, 0x30, 0x46, ++0x98, 0x47, 0x9A, 0xF8, 0x19, 0x20, 0x2B, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x72, 0x12, 0x6C, 0xB2, 0x42, ++0x3F, 0xF4, 0x51, 0xAF, 0x03, 0xFB, 0x05, 0x77, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x10, 0x03, 0x87, 0xF8, 0x4D, 0x30, ++0x47, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0xE0, 0xA2, 0x15, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x38, 0x9D, 0x17, 0x00, ++0xB8, 0xA2, 0x15, 0x00, 0xD4, 0xA2, 0x15, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xBC, 0xA2, 0xDF, 0xF8, 0xB4, 0x82, 0xDA, 0xF8, 0x00, 0x30, ++0x4F, 0xF4, 0xA4, 0x69, 0xB3, 0xF9, 0x00, 0x30, 0x09, 0xFB, 0x00, 0xF9, 0x08, 0xEB, 0x09, 0x02, 0x00, 0x2B, 0x14, 0x6C, ++0x85, 0xB0, 0x05, 0x46, 0xC0, 0xF2, 0x99, 0x80, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x05, 0x86, 0x9A, 0x4F, 0x96, 0xF8, ++0x4D, 0x00, 0x21, 0x7C, 0x97, 0xF8, 0x5A, 0x30, 0x62, 0x7E, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x01, 0x97, 0xF8, 0x5B, 0x30, ++0x95, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x06, 0xF0, 0xEF, 0xFA, 0x09, 0xF1, 0x44, 0x01, 0x07, 0xF1, 0x10, 0x00, 0x41, 0x44, ++0x05, 0xF0, 0x0E, 0xF9, 0x96, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x01, 0x02, 0x86, 0xF8, 0x4D, 0x20, 0x9A, 0x07, 0x09, 0xD5, ++0x97, 0xF8, 0x5B, 0x30, 0x97, 0xF8, 0x5A, 0x20, 0x01, 0x3B, 0xDB, 0xB2, 0x01, 0x2A, 0x87, 0xF8, 0x5B, 0x30, 0x5D, 0xD9, ++0xDF, 0xF8, 0x3C, 0xB2, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x05, 0x85, 0x00, 0x23, 0x85, 0xF8, 0x4D, 0x30, 0x2B, 0x64, ++0x66, 0x7E, 0x23, 0x7C, 0x01, 0x3E, 0xF6, 0xB2, 0x66, 0x76, 0x00, 0x2B, 0x45, 0xD0, 0x95, 0xF8, 0x63, 0x30, 0xE2, 0x7E, ++0x9A, 0x42, 0x00, 0xF0, 0x85, 0x80, 0x7C, 0x4B, 0x03, 0xF1, 0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, 0xD8, 0x7E, ++0xFF, 0x28, 0x40, 0xF0, 0xBD, 0x80, 0x1C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0x00, 0x2E, 0x4E, 0xD0, 0xDB, 0xF8, 0xB4, 0x30, ++0x20, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x97, 0xF8, 0x5A, 0x30, 0x00, 0x20, 0xB8, 0x62, 0x00, 0x2B, ++0x59, 0xD0, 0x21, 0x7E, 0xDB, 0xF8, 0x9C, 0x50, 0x6C, 0x4A, 0x02, 0x29, 0x01, 0xF1, 0x01, 0x03, 0x00, 0xF0, 0xC0, 0x80, ++0xC3, 0xEB, 0xC3, 0x06, 0x02, 0xEB, 0x86, 0x06, 0xD8, 0x00, 0x36, 0x7E, 0xFF, 0x2E, 0x40, 0xF0, 0xC3, 0x80, 0x01, 0x29, ++0x01, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, 0xC3, 0xEB, 0xC3, 0x01, 0x02, 0xEB, 0x81, 0x01, 0xD8, 0x00, 0x09, 0x7E, ++0xFF, 0x29, 0x08, 0xBF, 0x00, 0x20, 0x40, 0xF0, 0xB3, 0x80, 0xA8, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0xCC, 0xD1, 0xDB, 0xF8, ++0x48, 0x30, 0x20, 0x7E, 0x98, 0x47, 0xC7, 0xE7, 0x00, 0x2B, 0x9F, 0xD1, 0x97, 0xF8, 0x58, 0x30, 0xDF, 0xF8, 0x78, 0xB1, ++0x5B, 0x06, 0x9B, 0xD5, 0x38, 0x6D, 0xDB, 0xF8, 0x5C, 0x30, 0x98, 0x47, 0x96, 0xE7, 0x00, 0x2C, 0x7F, 0xF4, 0x64, 0xAF, ++0x51, 0x49, 0x52, 0x48, 0x40, 0xF6, 0xC4, 0x32, 0x06, 0xF0, 0x8C, 0xFC, 0x5C, 0xE7, 0x50, 0x48, 0x21, 0x46, 0x05, 0xF0, ++0x83, 0xF8, 0x26, 0x74, 0x97, 0xF8, 0x5A, 0x30, 0xDA, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0xDB, 0xB2, 0x87, 0xF8, 0x5A, 0x30, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x0A, 0xDB, 0x03, 0xBB, 0xBB, 0x6A, 0xA3, 0x42, 0xA2, 0xD0, 0xFB, 0x6A, 0xA3, 0x42, ++0x31, 0xD0, 0x66, 0x7E, 0x00, 0x2E, 0xC8, 0xD0, 0x94, 0xE7, 0x01, 0x2B, 0xF2, 0xD9, 0x3F, 0x49, 0x41, 0x48, 0x4F, 0xF4, ++0x40, 0x62, 0x06, 0xF0, 0x67, 0xFC, 0x97, 0xF8, 0x5A, 0x30, 0xE9, 0xE7, 0xDB, 0xF8, 0x94, 0x30, 0x08, 0xEB, 0x09, 0x00, ++0x98, 0x47, 0x66, 0x7E, 0xFF, 0x23, 0xE3, 0x76, 0x00, 0x2E, 0x7F, 0xF4, 0x7F, 0xAF, 0xCC, 0xE7, 0x38, 0x48, 0x04, 0xF0, ++0xFD, 0xFF, 0x38, 0x4B, 0x03, 0xF5, 0xA4, 0x51, 0x93, 0xF8, 0x4D, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x4D, 0x20, ++0x03, 0xF5, 0xA4, 0x63, 0x99, 0x42, 0xF5, 0xD1, 0x3B, 0x6D, 0x00, 0x2B, 0xCB, 0xD1, 0xDB, 0xF8, 0x34, 0x30, 0x98, 0x47, ++0xC7, 0xE7, 0x21, 0x7E, 0x27, 0x4A, 0x02, 0x29, 0x01, 0xF1, 0x01, 0x03, 0x29, 0xD0, 0xC3, 0xEB, 0xC3, 0x05, 0x02, 0xEB, ++0x85, 0x05, 0xD8, 0x00, 0x2D, 0x7E, 0xFF, 0x2D, 0x35, 0xD1, 0x01, 0x29, 0x01, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, ++0xC3, 0xEB, 0xC3, 0x01, 0x02, 0xEB, 0x81, 0x01, 0xD8, 0x00, 0x09, 0x7E, 0xFF, 0x29, 0x08, 0xBF, 0x00, 0x22, 0x26, 0xD1, ++0xFA, 0x62, 0xAE, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x80, 0x03, 0x6C, 0xA3, 0x42, 0x3F, 0xF4, 0x3E, 0xAF, ++0x66, 0xB1, 0xDB, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0x7F, 0xF4, 0x38, 0xAF, 0x85, 0xE7, 0x13, 0x7E, ++0xFF, 0x2B, 0x0E, 0xD1, 0x01, 0x23, 0xDD, 0xE7, 0xDB, 0xF8, 0x94, 0x30, 0x98, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0x7F, 0xF4, ++0x2B, 0xAF, 0x78, 0xE7, 0x13, 0x7E, 0xFF, 0x2B, 0x07, 0xD1, 0x01, 0x23, 0x48, 0xE7, 0x00, 0x23, 0x18, 0x46, 0xC3, 0x1A, ++0x02, 0xEB, 0x83, 0x02, 0xD4, 0xE7, 0x03, 0x46, 0xC0, 0x1A, 0x02, 0xEB, 0x80, 0x00, 0x48, 0xE7, 0x30, 0x9D, 0x17, 0x00, ++0x08, 0xA3, 0x15, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF8, 0xA2, 0x15, 0x00, 0x38, 0x9D, 0x17, 0x00, ++0x28, 0xA3, 0x15, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x43, 0x03, 0x46, 0x05, 0x78, 0x29, 0x4E, 0x2A, 0x4A, 0x04, 0x46, 0x53, 0xF8, 0x02, 0x0F, 0x97, 0x6A, ++0x59, 0x68, 0xB3, 0xF8, 0x08, 0xC0, 0xC5, 0xEB, 0xC5, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x04, 0x33, 0x03, 0xC3, 0xC5, 0xEB, ++0xC5, 0x02, 0x06, 0xEB, 0x82, 0x02, 0x97, 0x42, 0x85, 0xB0, 0xA3, 0xF8, 0x00, 0xC0, 0x02, 0xD0, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x83, 0x4F, 0xEA, 0xC5, 0x08, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x1A, 0x4F, 0xDF, 0xF8, 0x68, 0x90, 0x3B, 0x68, 0xD9, 0xF8, 0xA0, 0x22, 0x01, 0x33, 0x3B, 0x60, 0x90, 0x47, ++0xD9, 0xF8, 0x88, 0x32, 0x00, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x33, 0xB1, 0x11, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xE2, 0x7A, 0x23, 0x89, 0x00, 0x93, 0x00, 0x21, 0xCD, 0xE9, 0x01, 0x21, 0xA8, 0xEB, ++0x05, 0x05, 0xE3, 0x88, 0xA0, 0x78, 0xA2, 0x88, 0xE1, 0x78, 0x06, 0xEB, 0x85, 0x06, 0xE2, 0xF7, 0x91, 0xFE, 0xD9, 0xF8, ++0x3C, 0x33, 0x96, 0xF9, 0x0C, 0x00, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, ++0x30, 0x9D, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x12, 0x4D, ++0x12, 0x4A, 0x2B, 0x7C, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x03, 0x24, 0x06, 0x46, 0x22, 0x6C, 0x4A, 0xB1, 0x0F, 0x4C, ++0x18, 0x46, 0x63, 0x6D, 0x98, 0x47, 0xE3, 0x6C, 0x28, 0x7C, 0x31, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x05, 0x22, ++0x11, 0x46, 0x02, 0x23, 0x41, 0xF2, 0x17, 0x40, 0x04, 0xF0, 0x7E, 0xFA, 0x01, 0x22, 0x02, 0x70, 0x94, 0xF8, 0x63, 0x20, ++0x42, 0x70, 0x04, 0xF0, 0xA7, 0xFA, 0x03, 0x4C, 0xE9, 0xE7, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x6B, 0x4D, 0x2C, 0x69, 0x07, 0x46, 0x8B, 0x46, 0x91, 0x46, 0x8C, 0xB3, ++0x63, 0x68, 0xD0, 0xF8, 0x40, 0xA0, 0xD5, 0xF8, 0x28, 0x80, 0x8B, 0x42, 0x12, 0xD0, 0x05, 0xF1, 0x10, 0x06, 0xA3, 0xEB, ++0x0B, 0x03, 0x00, 0x2B, 0x21, 0x46, 0x30, 0x46, 0x26, 0xDA, 0x04, 0xF0, 0x33, 0xFF, 0x63, 0x7A, 0x23, 0xF0, 0x01, 0x03, ++0x63, 0x72, 0x2C, 0x69, 0xF4, 0xB1, 0x63, 0x68, 0x5B, 0x45, 0xEE, 0xD1, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x4F, 0xF0, ++0x00, 0x04, 0x1B, 0xD8, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x02, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, ++0xB8, 0xEB, 0x0A, 0x00, 0x03, 0xF1, 0x01, 0x03, 0x18, 0xBF, 0x01, 0x20, 0x85, 0xF8, 0x5B, 0x30, 0xBD, 0xE8, 0xF8, 0x8F, ++0xD0, 0xF8, 0x40, 0xA0, 0xD5, 0xF8, 0x28, 0x80, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x4F, 0xF0, 0x01, 0x04, 0xE3, 0xD9, ++0x97, 0xF8, 0x4E, 0x30, 0xFF, 0x2B, 0x26, 0xD0, 0x49, 0x4E, 0x59, 0x46, 0x73, 0x6F, 0x38, 0x46, 0x98, 0x47, 0x00, 0x2C, ++0x41, 0xD0, 0x97, 0xF8, 0x4D, 0x30, 0x97, 0xF8, 0xC0, 0x24, 0x43, 0xF0, 0x04, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x82, 0xB1, ++0x42, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x06, 0xD1, ++0xBB, 0x6C, 0x4B, 0x45, 0x03, 0xD0, 0xA3, 0xEB, 0x09, 0x02, 0x32, 0x2A, 0x5D, 0xD4, 0xB8, 0xEB, 0x0A, 0x00, 0x18, 0xBF, ++0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x97, 0xF8, 0xC0, 0x34, 0xB3, 0xB3, 0x35, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, ++0x01, 0xFB, 0x03, 0x21, 0x91, 0xF8, 0x70, 0x10, 0x01, 0x29, 0x35, 0xD0, 0x00, 0x2C, 0x4F, 0xD1, 0x30, 0x48, 0x07, 0xF1, ++0x44, 0x01, 0x04, 0xF0, 0xC9, 0xFE, 0x97, 0xF8, 0x4D, 0x30, 0x03, 0xF0, 0xFE, 0x03, 0x43, 0xF0, 0x02, 0x03, 0x87, 0xF8, ++0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, 0x01, 0x33, 0x85, 0xF8, 0x5B, 0x30, 0xD7, 0xE7, 0x97, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0xE8, 0xD0, 0x24, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, ++0xDE, 0xD1, 0xF3, 0x6A, 0x49, 0x46, 0x00, 0x22, 0x38, 0x46, 0x98, 0x47, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x08, 0x03, ++0xDD, 0xE7, 0x00, 0x2C, 0xD2, 0xD0, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x04, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0xB6, 0xE7, ++0x97, 0xF8, 0x4D, 0x10, 0xC8, 0x06, 0x0B, 0xD5, 0x12, 0x4E, 0x38, 0x46, 0xD6, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x97, 0xF8, ++0x4D, 0x30, 0x23, 0xF0, 0x10, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x8A, 0xE7, 0x4E, 0x06, 0x10, 0xD4, 0x54, 0xB9, 0x0B, 0x4E, ++0xD7, 0xE7, 0xA9, 0xEB, 0x03, 0x03, 0x32, 0x2B, 0x9D, 0xD5, 0xC7, 0xF8, 0x48, 0x90, 0x9A, 0xE7, 0x97, 0xF8, 0x4D, 0x10, ++0x41, 0xF0, 0x04, 0x01, 0x87, 0xF8, 0x4D, 0x10, 0x85, 0xE7, 0x03, 0x4E, 0x38, 0x46, 0x33, 0x6F, 0x98, 0x47, 0x72, 0xE7, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x4D, 0x4D, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x2B, 0xD9, 0x90, 0xF8, 0x4D, 0x20, 0x04, 0x46, 0xD0, 0x06, 0x0F, 0xD5, ++0x49, 0x4B, 0x03, 0xF1, 0x54, 0x00, 0x19, 0x7E, 0xFF, 0x29, 0x02, 0xD0, 0xD9, 0x7E, 0xFF, 0x29, 0x3B, 0xD1, 0x1C, 0x33, ++0x98, 0x42, 0xF6, 0xD1, 0x02, 0xF0, 0xEF, 0x02, 0x84, 0xF8, 0x4D, 0x20, 0x91, 0x07, 0x14, 0xD4, 0x53, 0x07, 0x6E, 0x6A, ++0x44, 0xBF, 0x22, 0xF0, 0x04, 0x02, 0x84, 0xF8, 0x4D, 0x20, 0x26, 0xB1, 0xF2, 0x68, 0x04, 0xF1, 0x44, 0x03, 0x9A, 0x42, ++0x09, 0xD0, 0x3B, 0x4B, 0x61, 0x6A, 0xDB, 0x6A, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xBD, 0xE8, ++0xF0, 0x81, 0xD4, 0xF8, 0x48, 0x80, 0x67, 0x6A, 0xA8, 0xEB, 0x07, 0x03, 0x00, 0x2B, 0x20, 0xDB, 0xA7, 0xEB, 0x08, 0x03, ++0x00, 0x2B, 0x29, 0xDB, 0x30, 0x4D, 0x6B, 0x6B, 0x98, 0x47, 0xEB, 0x6A, 0x61, 0x6A, 0x20, 0x46, 0x00, 0x22, 0x98, 0x47, ++0x2D, 0x4A, 0xD5, 0xF8, 0x84, 0x30, 0x11, 0x69, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x2A, 0x4A, ++0x27, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x20, 0xD3, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x20, ++0xBA, 0xE7, 0xE2, 0xF7, 0xA5, 0xFD, 0xA7, 0xF5, 0x7A, 0x67, 0xA7, 0xEB, 0x08, 0x07, 0x38, 0x1A, 0x00, 0x28, 0x0C, 0xDB, ++0x67, 0x6A, 0xD4, 0xF8, 0x48, 0x80, 0xD1, 0xE7, 0xE2, 0xF7, 0x98, 0xFD, 0xA8, 0xF5, 0x7A, 0x68, 0xA8, 0xEB, 0x07, 0x07, ++0x3F, 0x1A, 0x00, 0x2F, 0xCC, 0xDA, 0x67, 0x6A, 0xA7, 0x64, 0xE2, 0xF7, 0x8D, 0xFD, 0x73, 0x68, 0xFF, 0x1A, 0x3F, 0x1A, ++0xB7, 0xF5, 0x7A, 0x6F, 0xB5, 0xD5, 0xA4, 0x6C, 0xE2, 0xF7, 0x84, 0xFD, 0xAB, 0x6C, 0xA4, 0xF5, 0x7A, 0x64, 0x24, 0x1A, ++0xB3, 0x42, 0x74, 0x60, 0xAB, 0xD1, 0x0D, 0x4C, 0x0F, 0x48, 0xD4, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x0B, 0x4B, 0x71, 0x68, ++0x1B, 0x69, 0xAE, 0x64, 0xCB, 0x1A, 0x14, 0x2B, 0x05, 0xD4, 0xD4, 0xF8, 0xE0, 0x31, 0x09, 0x48, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x6B, 0x6C, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x18, 0x88, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x45, 0x4D, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x04, 0x46, 0x90, 0xF8, 0x4D, 0x30, 0x51, 0xD9, 0x9E, 0x06, 0x04, 0xD5, ++0x41, 0x4B, 0x9B, 0x6F, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x67, 0x6A, 0x13, 0xF0, 0x04, 0x06, 0x3D, 0xD1, 0x99, 0x07, ++0x42, 0xD5, 0x03, 0xF0, 0xFD, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x20, 0x01, 0x3A, 0xD2, 0xB2, 0x85, 0xF8, ++0x5B, 0x20, 0x4A, 0xB9, 0x95, 0xF8, 0x58, 0x20, 0x52, 0x06, 0x5B, 0xD5, 0x34, 0x4B, 0x28, 0x6D, 0xDB, 0x6D, 0x98, 0x47, ++0x94, 0xF8, 0x4D, 0x30, 0xD4, 0xF8, 0x48, 0x80, 0x13, 0xF0, 0x08, 0x02, 0x42, 0xD0, 0x94, 0xF8, 0x62, 0x20, 0x23, 0xF0, ++0x08, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x00, 0x2A, 0x4A, 0xD0, 0x02, 0x2A, 0x0A, 0xBF, 0xB4, 0xF8, 0xD2, 0x30, 0x4F, 0xF4, ++0xC8, 0x33, 0x9B, 0x02, 0xA8, 0xEB, 0x03, 0x08, 0xB6, 0xB1, 0xEB, 0x6A, 0x26, 0x4A, 0x15, 0x69, 0x93, 0xB9, 0x24, 0x4E, ++0x73, 0x6B, 0x98, 0x47, 0xD6, 0xF8, 0x84, 0x30, 0xA5, 0xEB, 0x08, 0x02, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x13, 0xF0, 0x01, 0x02, 0x23, 0xD0, 0x23, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0xBD, 0xE8, 0xF0, 0x81, ++0x9A, 0x07, 0xFB, 0xD5, 0x23, 0xF0, 0x02, 0x03, 0x80, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, 0x01, 0x3B, 0xDB, 0xB2, ++0x85, 0xF8, 0x5B, 0x30, 0x00, 0x2B, 0xEF, 0xD1, 0x95, 0xF8, 0x58, 0x30, 0x5F, 0x06, 0xEB, 0xD5, 0x10, 0x4B, 0x28, 0x6D, ++0xDB, 0x6D, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x0D, 0x4B, 0x39, 0x46, 0xDB, 0x6A, 0x20, 0x46, 0x98, 0x47, 0xC7, 0xE7, ++0x0A, 0x4B, 0x39, 0x46, 0xDB, 0x6A, 0x20, 0x46, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0xD3, 0xE7, 0x01, 0x26, 0xA7, 0xE7, ++0x07, 0x4A, 0x94, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x9B, 0x68, 0xB2, 0xE7, 0x00, 0xBF, ++0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0x28, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x6C, 0x05, 0x46, 0x3E, 0xDB, 0x24, 0x4E, 0x96, 0xF8, ++0x58, 0x20, 0x12, 0xF0, 0x20, 0x04, 0x03, 0xD1, 0x96, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x01, 0xD8, 0xBD, 0xE8, 0xF0, 0x81, ++0x14, 0x23, 0x22, 0x46, 0x21, 0x46, 0x46, 0x20, 0x95, 0xF8, 0x6C, 0x80, 0x04, 0xF0, 0x2E, 0xF8, 0x04, 0x70, 0x95, 0xF8, ++0x63, 0x10, 0x41, 0x70, 0x39, 0x79, 0x19, 0x4A, 0x81, 0x70, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x08, 0x28, 0x7A, 0x79, ++0xC2, 0x70, 0xD8, 0xF8, 0x08, 0x20, 0x15, 0x4D, 0xB7, 0xF8, 0x06, 0xC0, 0x3C, 0x89, 0x79, 0x89, 0x01, 0x81, 0xA2, 0xF5, ++0x9C, 0x52, 0x08, 0x3A, 0xA5, 0xFB, 0x02, 0x52, 0x92, 0x09, 0xA0, 0xF8, 0x04, 0xC0, 0xC4, 0x80, 0xC2, 0x60, 0x3A, 0x7B, ++0x02, 0x74, 0x04, 0xF0, 0x3B, 0xF8, 0x96, 0xF8, 0x58, 0x30, 0x43, 0xF0, 0x20, 0x03, 0x86, 0xF8, 0x58, 0x30, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0x2F, 0xBE, 0xD1, 0x07, 0x49, 0x07, 0x48, 0x40, 0xF6, 0x71, 0x52, 0x06, 0xF0, 0xDD, 0xF8, 0xB7, 0xE7, ++0x38, 0x36, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xD3, 0x4D, 0x62, 0x10, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0xA0, 0x15, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x0A, 0x4B, 0x9B, 0x6A, 0x83, 0xB1, 0x1A, 0x7E, 0x02, 0x2A, 0x05, 0xD8, ++0x00, 0x6C, 0xC0, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x9B, 0x7E, 0x90, 0xF8, 0x63, 0x00, 0x18, 0x1A, ++0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x18, 0x46, 0x70, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x10, 0x4A, 0x93, 0x6A, ++0xDB, 0xB1, 0x19, 0x7E, 0x02, 0x29, 0x0E, 0xD8, 0x00, 0x6C, 0xC0, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x88, 0xB1, ++0xD2, 0x6A, 0x7A, 0xB1, 0x18, 0x7C, 0xA0, 0xF1, 0x06, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x90, 0xF8, ++0x63, 0x10, 0x98, 0x7E, 0x40, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x00, 0x28, 0xED, 0xD1, 0x70, 0x47, 0x18, 0x46, ++0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x0E, 0x4B, 0x9B, 0x6A, 0x23, 0xB1, 0x02, 0x6C, 0x98, 0x88, 0x91, 0x88, ++0x88, 0x42, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x58, 0x7B, 0x51, 0x7B, 0x88, 0x42, 0xF9, 0xD1, 0xD8, 0x88, 0xD1, 0x88, ++0x88, 0x42, 0xF5, 0xD1, 0x18, 0x89, 0x11, 0x89, 0x88, 0x42, 0xF1, 0xD1, 0x5B, 0x89, 0x50, 0x89, 0x18, 0x1A, 0xB0, 0xFA, ++0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x43, 0x7E, 0xDB, 0xB1, 0x0E, 0x4B, 0x30, 0xB4, ++0x7F, 0x21, 0x03, 0xF5, 0xA4, 0x54, 0x1A, 0x6C, 0x82, 0x42, 0x08, 0xD0, 0x03, 0xF5, 0xA4, 0x63, 0xA3, 0x42, 0xF8, 0xD1, ++0x7F, 0x29, 0x30, 0xBC, 0x18, 0xBF, 0x01, 0x73, 0x70, 0x47, 0x93, 0xF9, 0x66, 0x20, 0x93, 0xF9, 0x65, 0x50, 0xAA, 0x42, ++0xA8, 0xBF, 0x2A, 0x46, 0x91, 0x42, 0xA8, 0xBF, 0x11, 0x46, 0xEB, 0xE7, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x70, 0xB5, 0x11, 0x4E, 0x11, 0x4A, 0xD6, 0xF8, 0x4C, 0x32, 0x04, 0x46, 0x98, 0x47, 0xD0, 0xB1, 0x0F, 0x4B, 0x10, 0x4D, ++0x5B, 0x78, 0x00, 0x22, 0x2A, 0x77, 0x23, 0xB1, 0x0E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x2B, 0x7A, ++0x0B, 0xB1, 0x01, 0x3B, 0x2B, 0x72, 0xD6, 0xF8, 0xD8, 0x31, 0x0A, 0x48, 0x98, 0x47, 0x00, 0x23, 0x6B, 0x77, 0x63, 0x68, ++0x23, 0xF4, 0x01, 0x73, 0x23, 0xF0, 0x02, 0x03, 0x63, 0x60, 0x70, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xDD, 0xEA, 0x13, 0x00, ++0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x70, 0xB5, 0x14, 0x4D, ++0x14, 0x4A, 0xD5, 0xF8, 0x4C, 0x32, 0x04, 0x46, 0x98, 0x47, 0xF8, 0xB1, 0x12, 0x4A, 0x13, 0x4B, 0x52, 0x78, 0x01, 0x21, ++0x19, 0x77, 0x22, 0xB1, 0x11, 0x49, 0x0A, 0x68, 0x22, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x1A, 0x7A, 0x0A, 0xB1, 0x01, 0x3A, ++0x1A, 0x72, 0x0E, 0x4A, 0x0E, 0x49, 0x12, 0x68, 0x09, 0x69, 0xD0, 0x8E, 0x5C, 0x61, 0x04, 0x26, 0x5E, 0x77, 0x01, 0x44, ++0xD5, 0xF8, 0xE0, 0x21, 0x0A, 0x48, 0x90, 0x47, 0x63, 0x68, 0x43, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x70, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x3D, 0xEB, 0x13, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, ++0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4A, 0x0B, 0x46, 0x0C, 0x46, ++0x05, 0x46, 0x0F, 0x49, 0x02, 0x20, 0x05, 0xF0, 0xB3, 0xFD, 0x0E, 0x4B, 0x0E, 0x4A, 0xD3, 0xF8, 0x4C, 0x32, 0x21, 0x46, ++0x28, 0x46, 0x98, 0x47, 0x30, 0xB1, 0x0C, 0x4A, 0x13, 0x7A, 0x23, 0xB1, 0x01, 0x3B, 0xDB, 0xB2, 0x13, 0x72, 0x03, 0xB1, ++0x38, 0xBD, 0x01, 0x23, 0x13, 0x70, 0x51, 0x88, 0xBD, 0xE8, 0x38, 0x40, 0x00, 0x22, 0x32, 0x20, 0x03, 0xF0, 0x4A, 0xBF, ++0x68, 0xA3, 0x15, 0x00, 0x44, 0xA3, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xB1, 0xEB, 0x13, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x38, 0xB5, 0x18, 0x4A, 0x0B, 0x46, 0x0C, 0x46, 0x05, 0x46, 0x17, 0x49, 0x02, 0x20, 0x05, 0xF0, 0x87, 0xFD, 0x16, 0x4B, ++0x16, 0x4A, 0xD3, 0xF8, 0x4C, 0x32, 0x21, 0x46, 0x28, 0x46, 0x98, 0x47, 0xF8, 0xB1, 0x14, 0x48, 0x03, 0x7A, 0xBB, 0xB9, ++0x13, 0x4B, 0x9B, 0x68, 0x63, 0xB1, 0x93, 0xF8, 0x62, 0x20, 0x32, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x1A, 0xB1, 0x5A, 0x68, ++0x22, 0xF0, 0x0E, 0x02, 0x5A, 0x60, 0x1B, 0x68, 0x00, 0x2B, 0xF2, 0xD1, 0x00, 0x22, 0x02, 0x70, 0x41, 0x88, 0xBD, 0xE8, ++0x38, 0x40, 0x32, 0x20, 0x03, 0xF0, 0x14, 0xBF, 0x01, 0x3B, 0xDB, 0xB2, 0x03, 0x72, 0x00, 0x2B, 0xE2, 0xD0, 0x38, 0xBD, ++0x78, 0xA3, 0x15, 0x00, 0x44, 0xA3, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x09, 0xEC, 0x13, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x38, 0xB5, 0x11, 0xF4, 0x00, 0x03, 0x04, 0x46, 0x2A, 0xD1, 0x90, 0xF8, 0x6B, 0x00, 0x25, 0x49, ++0x01, 0x30, 0xC0, 0xB2, 0x09, 0x68, 0x84, 0xF8, 0x6B, 0x00, 0x49, 0x78, 0x81, 0x42, 0x29, 0xD0, 0x94, 0xF8, 0x64, 0x50, ++0x00, 0x2D, 0x34, 0xD1, 0x1F, 0x4A, 0x20, 0x4B, 0x52, 0x78, 0x01, 0x21, 0x19, 0x77, 0x22, 0xB1, 0x1E, 0x49, 0x0A, 0x68, ++0x22, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x1A, 0x7A, 0x0A, 0xB1, 0x01, 0x3A, 0x1A, 0x72, 0x1B, 0x4A, 0x1B, 0x48, 0xD2, 0xF8, ++0xD8, 0x21, 0x00, 0x21, 0x59, 0x77, 0x90, 0x47, 0x63, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x28, 0x46, 0x38, 0xBD, ++0x28, 0xB1, 0x00, 0x23, 0x01, 0x25, 0x80, 0xF8, 0x6B, 0x30, 0x28, 0x46, 0x38, 0xBD, 0x01, 0x25, 0x28, 0x46, 0x38, 0xBD, ++0x11, 0x49, 0x84, 0xF8, 0x6B, 0x30, 0x4F, 0xF4, 0x80, 0x60, 0x05, 0xF0, 0x11, 0xFD, 0x0C, 0x4B, 0x20, 0x46, 0xD3, 0xF8, ++0xBC, 0x31, 0x01, 0x25, 0x98, 0x47, 0x28, 0x46, 0x38, 0xBD, 0x11, 0x46, 0x1D, 0x46, 0x94, 0xF8, 0x6C, 0x00, 0x22, 0x46, ++0xF1, 0xF7, 0xD0, 0xF9, 0x28, 0x46, 0x38, 0xBD, 0xC8, 0x35, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x34, 0x04, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x28, 0x9E, 0x17, 0x00, 0x4C, 0xA3, 0x15, 0x00, 0x70, 0xB5, 0x13, 0x4D, ++0x2B, 0x78, 0x13, 0xB3, 0x2B, 0x7F, 0x03, 0xB3, 0x11, 0x4A, 0x12, 0x49, 0x13, 0x68, 0x8C, 0x68, 0x43, 0xF0, 0x04, 0x03, ++0x00, 0x21, 0x13, 0x60, 0x29, 0x72, 0xB4, 0xB1, 0x0E, 0x4E, 0x94, 0xF8, 0x62, 0x30, 0x7B, 0xB9, 0x94, 0xF8, 0x64, 0x30, ++0x63, 0xB1, 0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x22, 0x46, 0x07, 0xD0, 0xD6, 0xF8, 0x34, 0x12, 0xF1, 0xF7, 0xA0, 0xF9, ++0x10, 0xB9, 0x2B, 0x7A, 0x01, 0x33, 0x2B, 0x72, 0x24, 0x68, 0x00, 0x2C, 0xE9, 0xD1, 0x70, 0xBD, 0x1C, 0x9E, 0x17, 0x00, ++0x4C, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x12, 0x4D, 0x2B, 0x7F, 0xFB, 0xB9, ++0x11, 0x49, 0x12, 0x48, 0x0A, 0x68, 0x84, 0x68, 0x2B, 0x72, 0x22, 0xF0, 0x04, 0x02, 0x0A, 0x60, 0xB4, 0xB1, 0x0F, 0x4E, ++0x94, 0xF8, 0x62, 0x30, 0x7B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x63, 0xB1, 0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x22, 0x46, ++0x07, 0xD0, 0xD6, 0xF8, 0x58, 0x12, 0xF1, 0xF7, 0x73, 0xF9, 0x10, 0xB9, 0x2B, 0x7A, 0x01, 0x33, 0x2B, 0x72, 0x24, 0x68, ++0x00, 0x2C, 0xE9, 0xD1, 0x70, 0xBD, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x2E, 0x4B, 0x2E, 0x4D, 0x1B, 0x68, 0x2E, 0x4A, 0x1B, 0x78, 0xD2, 0xF8, 0xF8, 0x21, ++0x01, 0x2B, 0x6B, 0x68, 0x04, 0x46, 0x03, 0xF0, 0x20, 0x03, 0x44, 0xD0, 0x13, 0x43, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, ++0x94, 0xF8, 0xAC, 0x30, 0x53, 0xB1, 0x27, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x13, 0xB1, 0x94, 0xF8, 0x64, 0x30, 0x33, 0xBB, ++0x00, 0x23, 0x6B, 0x77, 0x63, 0x60, 0x70, 0xBD, 0x21, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0xF6, 0xD0, 0x94, 0xF8, ++0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, 0xC0, 0xB1, 0x1D, 0x4B, 0x1A, 0x68, 0x92, 0x01, 0x05, 0xD4, 0x1B, 0x68, 0x9B, 0x01, ++0x11, 0xD4, 0x95, 0xF8, 0x24, 0x30, 0x73, 0xB1, 0x6B, 0x7F, 0x05, 0x2B, 0x05, 0xD1, 0x63, 0x68, 0x00, 0x22, 0x23, 0xF0, ++0x02, 0x03, 0x63, 0x60, 0x6A, 0x77, 0x15, 0x4B, 0xBD, 0xE8, 0x70, 0x40, 0xD3, 0xF8, 0x50, 0x32, 0x18, 0x47, 0x13, 0x4B, ++0x13, 0x4A, 0x19, 0x68, 0x10, 0x4B, 0xC9, 0x8E, 0x6C, 0x61, 0x01, 0x20, 0x68, 0x77, 0x12, 0x69, 0xD3, 0xF8, 0xE0, 0x31, ++0x0F, 0x48, 0xBD, 0xE8, 0x70, 0x40, 0x11, 0x44, 0x18, 0x47, 0x13, 0x43, 0x01, 0xD0, 0x00, 0x20, 0xBA, 0xE7, 0xE9, 0xF7, ++0x37, 0xFD, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0xB4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0x28, 0x22, 0x20, 0x46, 0x00, 0x21, 0xE1, 0xF7, ++0x5F, 0xF9, 0x04, 0x4A, 0x01, 0x23, 0xD2, 0xF8, 0x38, 0x22, 0x22, 0x61, 0x23, 0x77, 0x10, 0xBD, 0x1C, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x4C, 0x23, 0x78, 0x33, 0xB9, 0x0B, 0x4B, 0xD3, 0xF8, 0xF8, 0x31, 0x98, 0x47, ++0x08, 0xB9, 0x00, 0x20, 0x10, 0xBD, 0x63, 0x68, 0x00, 0x2B, 0xFA, 0xD1, 0x07, 0x4B, 0x9B, 0x68, 0x13, 0xB9, 0x05, 0xE0, ++0x1B, 0x68, 0x1B, 0xB1, 0x5A, 0x68, 0x00, 0x2A, 0xFA, 0xD0, 0xF0, 0xE7, 0x01, 0x20, 0x10, 0xBD, 0x1C, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x08, 0x4B, 0x09, 0x4A, 0x1B, 0x68, 0x51, 0x80, 0x1B, 0x78, 0x02, 0x2B, ++0x07, 0x4B, 0x03, 0xD0, 0x07, 0x49, 0x00, 0x28, 0x18, 0xBF, 0x0B, 0x46, 0x00, 0x20, 0x10, 0x72, 0x4F, 0xF4, 0x00, 0x01, ++0x18, 0x47, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x09, 0xEC, 0x13, 0x00, 0xB1, 0xEB, 0x13, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x92, 0xF8, 0x6C, 0x30, 0x42, 0x4C, 0x43, 0x4E, 0x51, 0x68, 0x4F, 0xF4, 0x1E, 0x75, 0x91, 0x46, ++0x05, 0xFB, 0x03, 0x43, 0x32, 0x78, 0x1D, 0x8C, 0x21, 0xF0, 0x01, 0x07, 0xC9, 0xF8, 0x04, 0x70, 0x00, 0x2A, 0x49, 0xD0, ++0x04, 0x46, 0x00, 0x28, 0x46, 0xD0, 0x99, 0xF8, 0x6A, 0x30, 0x00, 0x2B, 0x44, 0xD0, 0x00, 0xF1, 0x04, 0x08, 0x98, 0xF8, ++0x00, 0x30, 0x03, 0xF0, 0xFE, 0x03, 0xB3, 0xEB, 0xD5, 0x0F, 0x4F, 0xEA, 0xD5, 0x00, 0x31, 0xD8, 0x61, 0x78, 0x04, 0x39, ++0x19, 0x44, 0x88, 0x42, 0x2C, 0xD8, 0x20, 0x44, 0xC3, 0x1A, 0x05, 0xF0, 0x07, 0x05, 0x59, 0x79, 0x01, 0x23, 0x03, 0xFA, ++0x05, 0xF5, 0x29, 0x42, 0x22, 0xD0, 0x2C, 0x4B, 0x19, 0x68, 0x8A, 0x05, 0x03, 0xD5, 0x19, 0x68, 0x21, 0xF4, 0x00, 0x71, ++0x19, 0x60, 0x29, 0x4C, 0xD4, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x28, 0x48, 0xD9, 0xF8, 0x04, 0x30, 0x00, 0x68, 0x27, 0x49, ++0xD4, 0xF8, 0xE0, 0x41, 0x40, 0x8F, 0x43, 0xF0, 0x04, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0x09, 0x69, 0xC6, 0xF8, 0x14, 0x90, ++0x06, 0x23, 0x73, 0x77, 0x01, 0x44, 0x23, 0x46, 0x20, 0x48, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0xD9, 0xF8, 0x04, 0x30, ++0x23, 0xF0, 0x04, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0xBD, 0xE8, 0xF0, 0x87, 0x03, 0x79, 0x00, 0xF1, 0x04, 0x08, 0xD8, 0x07, ++0x1E, 0xD5, 0x14, 0x4B, 0x47, 0xF0, 0x02, 0x07, 0xC9, 0xF8, 0x04, 0x70, 0x19, 0x68, 0x89, 0x05, 0x03, 0xD5, 0x19, 0x68, ++0x21, 0xF4, 0x00, 0x71, 0x19, 0x60, 0x73, 0x7F, 0x00, 0x2B, 0xA8, 0xD1, 0x0E, 0x4B, 0x0F, 0x49, 0x1B, 0x68, 0x09, 0x69, ++0x1F, 0x8F, 0x0B, 0x4B, 0xC6, 0xF8, 0x14, 0x90, 0x05, 0x20, 0x70, 0x77, 0xD3, 0xF8, 0xE0, 0x31, 0x0A, 0x48, 0x39, 0x44, ++0x98, 0x47, 0x98, 0xE7, 0x21, 0xF0, 0x03, 0x01, 0xC9, 0xF8, 0x04, 0x10, 0x93, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x28, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x21, 0x4E, 0x14, 0x46, 0x52, 0x68, 0x35, 0x78, 0x22, 0xF0, 0x01, 0x03, ++0x63, 0x60, 0x00, 0x2D, 0x32, 0xD0, 0x0F, 0x46, 0x94, 0xF8, 0x6A, 0x10, 0xA1, 0xB9, 0x00, 0x28, 0x2E, 0xD0, 0x1B, 0x4A, ++0x1B, 0x49, 0x10, 0x68, 0x1B, 0x4A, 0x00, 0x8F, 0xD2, 0xF8, 0xE0, 0x21, 0x43, 0xF0, 0x02, 0x03, 0x63, 0x60, 0x09, 0x69, ++0x74, 0x61, 0x05, 0x23, 0x01, 0x44, 0x73, 0x77, 0x06, 0xF1, 0x0C, 0x00, 0x90, 0x47, 0x63, 0x68, 0xAF, 0xB1, 0x13, 0x4D, ++0x43, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xD5, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x0D, 0x4B, 0x0E, 0x4A, 0x1B, 0x68, 0x11, 0x69, ++0x58, 0x8F, 0x74, 0x61, 0x06, 0x22, 0xD5, 0xF8, 0xE0, 0x31, 0x72, 0x77, 0x01, 0x44, 0xBD, 0xE8, 0xF0, 0x41, 0x0A, 0x48, ++0x18, 0x47, 0x23, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x22, 0xF0, 0x03, 0x03, 0x00, 0x2F, 0xF6, 0xD0, ++0xDF, 0xE7, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x28, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x21, 0x4D, 0x2B, 0x78, 0xAB, 0xB1, 0x03, 0x79, 0x06, 0x88, 0xDF, 0x07, ++0x14, 0x46, 0x12, 0xD5, 0x6B, 0x7F, 0x05, 0x2B, 0x07, 0xD1, 0x1D, 0x4B, 0x05, 0xF1, 0x0C, 0x00, 0xD3, 0xF8, 0xD8, 0x31, ++0x98, 0x47, 0x00, 0x23, 0x6B, 0x77, 0xB5, 0x04, 0x23, 0xD4, 0x63, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x63, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0x88, 0x05, 0xFB, 0xD4, 0x15, 0x4A, 0x15, 0x4B, 0x12, 0x68, 0x1B, 0x69, 0xD1, 0x8E, 0x11, 0x4F, 0x6C, 0x61, ++0x02, 0x22, 0x19, 0x44, 0x6A, 0x77, 0xD7, 0xF8, 0xE0, 0x31, 0x05, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0xB1, 0x04, 0x63, 0x68, ++0x0E, 0xD5, 0x5A, 0x07, 0x5C, 0xBF, 0x43, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xD7, 0xF8, 0x54, 0x32, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x94, 0xF8, 0x6A, 0x30, 0x00, 0x2B, 0xDB, 0xD0, 0xD6, 0xE7, 0x23, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x38, 0xB5, 0x23, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x3F, 0xD0, 0xFF, 0x28, 0x3D, 0xD0, 0xFF, 0x29, 0x3B, 0xD0, 0x20, 0x4A, ++0x20, 0x49, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x20, 0x4F, 0xF4, 0xA4, 0x64, 0x90, 0xF8, 0x22, 0x20, 0x04, 0xFB, ++0x02, 0x12, 0x92, 0xF8, 0x62, 0x10, 0x00, 0x29, 0x2B, 0xD1, 0x92, 0xF8, 0x64, 0x10, 0x41, 0xB3, 0x18, 0x48, 0x19, 0x49, ++0x00, 0x68, 0x09, 0x69, 0xC5, 0x8E, 0x18, 0x4C, 0x5A, 0x61, 0x03, 0x20, 0x58, 0x77, 0xD4, 0xF8, 0xE0, 0x21, 0x03, 0xF1, ++0x0C, 0x00, 0x29, 0x44, 0x90, 0x47, 0x14, 0x4B, 0x1B, 0x68, 0x5B, 0x07, 0x15, 0xD5, 0x13, 0x4B, 0x93, 0xF8, 0xB6, 0x30, ++0x73, 0xB1, 0x12, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x09, 0xD1, 0x10, 0x49, 0x11, 0x4A, 0x0B, 0x68, 0x23, 0xF4, ++0x00, 0x73, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0xD4, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x00, 0x20, ++0x38, 0xBD, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, ++0x90, 0xB3, 0x33, 0x40, 0x8C, 0x00, 0x32, 0x40, 0x3B, 0x4A, 0xDF, 0xF8, 0x1C, 0xC1, 0x13, 0x68, 0x3A, 0x49, 0xF0, 0xB5, ++0x3A, 0x4F, 0x3B, 0x4C, 0xB7, 0xF8, 0xB2, 0x00, 0x3A, 0x4D, 0x3B, 0x4E, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x23, 0x68, ++0x39, 0x4A, 0x43, 0xF0, 0x80, 0x53, 0x23, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x70, 0x23, 0xCC, 0xF8, 0x00, 0x30, ++0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0x10, 0x03, 0xCC, 0xF8, 0x00, 0x30, 0x2B, 0x68, 0x23, 0xF0, ++0xFC, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x0B, 0x68, 0x40, 0x09, 0x00, 0xF1, 0x20, 0x0C, 0xC3, 0xF3, 0x15, 0x03, ++0x43, 0xEA, 0x8C, 0x53, 0x0B, 0x60, 0x83, 0xB0, 0x33, 0x68, 0x29, 0x49, 0x1B, 0x78, 0xCD, 0xF8, 0x00, 0xC0, 0x02, 0x20, ++0x05, 0xF0, 0x0A, 0xFA, 0x32, 0x68, 0x13, 0x78, 0x01, 0x2B, 0x15, 0xD0, 0x02, 0x2B, 0x11, 0xD1, 0x23, 0x48, 0x24, 0x49, ++0x03, 0x68, 0x24, 0x4C, 0x1D, 0x4A, 0x43, 0xF4, 0x80, 0x33, 0x03, 0x60, 0x0B, 0x68, 0x3F, 0x20, 0x23, 0xF0, 0x00, 0x73, ++0x0B, 0x60, 0x20, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x03, 0xB0, 0xF0, 0xBD, 0x97, 0xF8, 0xB5, 0x10, ++0x69, 0xB1, 0x19, 0x49, 0x19, 0x48, 0x0B, 0x68, 0x23, 0xF0, 0x00, 0x73, 0x0B, 0x60, 0x2B, 0x68, 0x24, 0x21, 0x43, 0xF4, ++0x00, 0x13, 0x2B, 0x60, 0x01, 0x60, 0x13, 0x78, 0xD8, 0xE7, 0x12, 0x48, 0x12, 0x4E, 0x01, 0x68, 0x12, 0x4D, 0x41, 0xF0, ++0x00, 0x71, 0x01, 0x60, 0x04, 0x21, 0x31, 0x60, 0x2B, 0x60, 0x23, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, ++0x23, 0x60, 0x13, 0x78, 0xC6, 0xE7, 0x00, 0xBF, 0x90, 0x00, 0x32, 0x40, 0xF0, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0x74, 0x80, 0x32, 0x40, 0x6C, 0x00, 0x32, 0x40, 0x74, 0x36, 0x17, 0x00, 0x88, 0xA3, 0x15, 0x00, 0x5C, 0xA3, 0x15, 0x00, ++0x44, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x78, 0x00, 0x32, 0x40, ++0x15, 0x48, 0x16, 0x4A, 0x16, 0x49, 0x38, 0xB5, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x02, 0x20, 0x05, 0xF0, ++0xA7, 0xF9, 0x13, 0x4B, 0x9B, 0x7C, 0x23, 0xB9, 0x12, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x11, 0x4C, ++0x11, 0x48, 0x23, 0x68, 0x0E, 0x49, 0x11, 0x4D, 0x11, 0x4A, 0x23, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF0, ++0x80, 0x43, 0x03, 0x60, 0x0B, 0x68, 0x00, 0x20, 0x23, 0xF0, 0x80, 0x53, 0x0B, 0x60, 0x28, 0x60, 0x13, 0x68, 0x23, 0xF0, ++0x01, 0x03, 0x13, 0x60, 0x38, 0xBD, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x98, 0xA3, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, ++0x00, 0x88, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x44, 0x00, 0x32, 0x40, 0x90, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x70, 0xB5, 0x90, 0xF8, 0x72, 0x30, 0x01, 0x2B, 0x04, 0x46, 0x11, 0xD0, 0x02, 0x2B, 0x00, 0xD0, ++0x70, 0xBD, 0x0C, 0x4D, 0x41, 0x6F, 0x01, 0x23, 0x80, 0xF8, 0x72, 0x30, 0xD5, 0xF8, 0xE0, 0x31, 0x60, 0x30, 0x98, 0x47, ++0xD5, 0xF8, 0x18, 0x32, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x04, 0x4B, 0x00, 0x22, 0x80, 0xF8, 0x72, 0x20, ++0xBD, 0xE8, 0x70, 0x40, 0xD3, 0xF8, 0x18, 0x32, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x4F, 0xF0, 0x00, 0x0C, 0x4F, 0xF0, 0x01, 0x0E, 0x83, 0xB0, 0x06, 0x46, 0x04, 0x46, 0x00, 0xF1, 0x60, 0x05, 0x03, 0x46, ++0x67, 0x46, 0x71, 0x46, 0x1A, 0x7C, 0x02, 0x2A, 0x13, 0xD1, 0xDA, 0x7C, 0x01, 0x2A, 0x10, 0xD8, 0x96, 0xF8, 0x87, 0x20, ++0x32, 0xB1, 0x93, 0xF8, 0x21, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x20, 0x01, 0x2A, 0x06, 0xD0, 0xDA, 0x68, 0x00, 0x29, ++0x00, 0xF0, 0xC0, 0x80, 0x01, 0x37, 0x94, 0x46, 0x00, 0x21, 0x30, 0x33, 0x9D, 0x42, 0xE5, 0xD1, 0x01, 0x22, 0x8E, 0x46, ++0x33, 0x46, 0x4F, 0xF0, 0x00, 0x09, 0x00, 0x92, 0xA0, 0x46, 0x1A, 0x7C, 0x02, 0x2A, 0x1D, 0xD1, 0xD9, 0x7C, 0x01, 0x29, ++0x1A, 0xD9, 0x96, 0xF8, 0x87, 0x20, 0x32, 0xB1, 0x93, 0xF8, 0x21, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x20, 0x01, 0x2A, ++0x10, 0xD0, 0xD3, 0xE9, 0x06, 0x04, 0xDA, 0x68, 0x04, 0xEB, 0x02, 0x0A, 0xAA, 0xEB, 0x00, 0x00, 0xBE, 0xF1, 0x00, 0x0F, ++0x42, 0xD0, 0x00, 0x21, 0x00, 0x91, 0x01, 0x37, 0x81, 0x46, 0x94, 0x46, 0x4F, 0xF0, 0x00, 0x0E, 0x30, 0x33, 0x9D, 0x42, ++0xDB, 0xD1, 0x01, 0x96, 0x44, 0x46, 0x00, 0x9E, 0x18, 0xE0, 0x00, 0x2F, 0x5F, 0xD1, 0xA1, 0xEB, 0x09, 0x02, 0x00, 0x2A, ++0x58, 0xDB, 0xAC, 0xEB, 0x03, 0x02, 0x00, 0x2A, 0x0B, 0xDB, 0xA3, 0xEB, 0x09, 0x00, 0xAC, 0xEB, 0x01, 0x02, 0x39, 0xEA, ++0x20, 0x09, 0x28, 0xBF, 0x99, 0x46, 0x3C, 0xEA, 0x22, 0x0C, 0x28, 0xBF, 0x8C, 0x46, 0x30, 0x34, 0xA5, 0x42, 0x0F, 0xD0, ++0x23, 0x7C, 0x01, 0x2B, 0xF9, 0xD1, 0xE3, 0x68, 0xA1, 0x69, 0x19, 0x44, 0xBE, 0xF1, 0x00, 0x0F, 0xDD, 0xD0, 0x30, 0x34, ++0x00, 0x26, 0xA5, 0x42, 0x99, 0x46, 0x8C, 0x46, 0xB6, 0x46, 0xEF, 0xD1, 0x33, 0x46, 0x01, 0x9E, 0xC6, 0xF8, 0x80, 0xC0, ++0x0B, 0xB1, 0x0C, 0xF1, 0x0A, 0x09, 0xC6, 0xF8, 0x7C, 0x90, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA0, 0xEB, 0x0C, 0x0A, ++0xBA, 0xF1, 0x00, 0x0F, 0x80, 0xF2, 0x88, 0x80, 0xA4, 0xEB, 0x02, 0x0B, 0x02, 0xEB, 0x0C, 0x0A, 0x01, 0x39, 0x83, 0x44, ++0xA0, 0xEB, 0x0A, 0x0A, 0x01, 0xE0, 0x01, 0x39, 0xB2, 0xD0, 0x0B, 0xEB, 0x02, 0x00, 0x22, 0x44, 0x1A, 0xEB, 0x02, 0x0F, ++0xF7, 0xD4, 0xAC, 0xEB, 0x02, 0x04, 0x3C, 0xEA, 0x24, 0x0C, 0x28, 0xBF, 0x94, 0x46, 0x01, 0x29, 0x3D, 0xD0, 0x62, 0x46, ++0x00, 0x99, 0x00, 0x29, 0x99, 0xD1, 0xA0, 0xEB, 0x09, 0x01, 0x10, 0xEA, 0x21, 0x00, 0x38, 0xBF, 0x48, 0x46, 0x94, 0xE7, ++0x99, 0x46, 0x8C, 0x46, 0xB3, 0xE7, 0xA1, 0xEB, 0x0C, 0x02, 0x00, 0x2A, 0x94, 0xF8, 0x13, 0x80, 0x61, 0xDA, 0x08, 0xF1, ++0xFF, 0x30, 0xB8, 0xF1, 0x00, 0x0F, 0xA8, 0xD0, 0xD4, 0xF8, 0x1C, 0xB0, 0x9A, 0x46, 0x03, 0xE0, 0x42, 0x1E, 0x00, 0x28, ++0xA1, 0xD0, 0x10, 0x46, 0xDA, 0x44, 0x01, 0xEB, 0x0A, 0x08, 0xA8, 0xEB, 0x0C, 0x02, 0xD2, 0x1A, 0x00, 0x2A, 0xA8, 0xEB, ++0x03, 0x08, 0xF1, 0xDB, 0xA6, 0xB1, 0xAC, 0xEB, 0x0A, 0x03, 0x00, 0x2B, 0x29, 0xDB, 0x58, 0xB3, 0xE3, 0x69, 0xC4, 0x46, ++0x0A, 0xEB, 0x03, 0x09, 0x00, 0x26, 0x8A, 0xE7, 0xAC, 0xEB, 0x02, 0x01, 0x12, 0xEA, 0x21, 0x02, 0x38, 0xBF, 0x62, 0x46, ++0x38, 0xE7, 0x48, 0x46, 0x62, 0x46, 0x5E, 0xE7, 0xA9, 0xEB, 0x0A, 0x03, 0x00, 0x2B, 0x11, 0xDB, 0xAC, 0xEB, 0x0A, 0x03, ++0x00, 0x2B, 0x15, 0xDB, 0xA8, 0xEB, 0x09, 0x03, 0x00, 0x2B, 0x14, 0xDB, 0x1B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x29, 0xDB, 0xE3, 0x69, 0xC4, 0x46, 0x0A, 0xEB, 0x03, 0x09, 0x4F, 0xF0, 0x00, 0x0E, 0x67, 0xE7, 0xD1, 0x46, ++0x00, 0x26, 0x64, 0xE7, 0xC4, 0x46, 0x62, 0xE7, 0xD1, 0x46, 0xB6, 0x46, 0x5F, 0xE7, 0x01, 0x28, 0x15, 0xDD, 0xE3, 0x69, ++0x9A, 0x44, 0xAA, 0xEB, 0x09, 0x03, 0xC4, 0x46, 0x39, 0xEA, 0x23, 0x09, 0x28, 0xBF, 0xD1, 0x46, 0xB6, 0x46, 0x52, 0xE7, ++0xAC, 0xEB, 0x02, 0x01, 0x12, 0xEA, 0x21, 0x02, 0x38, 0xBF, 0x62, 0x46, 0x8A, 0xE7, 0x40, 0x46, 0x9A, 0x46, 0x88, 0x46, ++0xB0, 0xE7, 0xC4, 0x46, 0xB6, 0x46, 0x44, 0xE7, 0x04, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x4D, 0x12, 0x05, 0xF0, 0x64, 0xFA, ++0xCE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x03, 0x7C, 0x02, 0x2B, 0x83, 0xB0, 0x04, 0x46, 0x69, 0xD0, 0x90, 0xF8, 0x40, 0x30, 0x02, 0x2B, 0x54, 0xD0, 0x94, 0xF8, ++0x73, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x18, 0xD1, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x40, 0xF0, 0xD2, 0x80, 0x94, 0xF8, ++0x70, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xB8, 0x80, 0xDF, 0xF8, 0x24, 0x93, 0xC3, 0x4B, 0x94, 0xF8, 0x71, 0x20, 0xD3, 0xF8, ++0x5C, 0x34, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x90, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x94, 0xF8, ++0x72, 0x30, 0x01, 0x2B, 0x00, 0xF0, 0x54, 0x81, 0x94, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x00, 0xF0, 0xB9, 0x81, 0xB9, 0x4A, ++0x92, 0xF8, 0x00, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xA8, 0x80, 0x52, 0x68, 0x11, 0x07, 0x00, 0xF1, 0xD4, 0x81, ++0x94, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0xD0, 0x92, 0x02, 0x23, ++0x0C, 0x21, 0x00, 0x22, 0x4D, 0x20, 0x03, 0xF0, 0x15, 0xF9, 0x01, 0x25, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x45, 0x70, ++0x03, 0xF0, 0x3E, 0xF9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x00, 0x22, 0x84, 0xF8, 0x85, 0x20, 0x18, 0x6C, ++0x29, 0x46, 0xFF, 0xF7, 0x15, 0xF9, 0x55, 0xE0, 0x90, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x7B, 0xD0, 0xFF, 0x23, 0x00, 0x21, ++0x94, 0xF8, 0x51, 0x20, 0x00, 0x2A, 0x6F, 0xD0, 0x94, 0xF8, 0x50, 0x20, 0x01, 0x2A, 0x6B, 0xD1, 0x00, 0x29, 0x9A, 0xD0, ++0x11, 0xE0, 0x90, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x5F, 0xD0, 0x90, 0xF8, 0x21, 0x30, 0x23, 0xB1, 0x90, 0xF8, 0x20, 0x30, ++0x01, 0x2B, 0x00, 0xF0, 0xA6, 0x81, 0x94, 0xF8, 0x40, 0x20, 0x23, 0x7D, 0x02, 0x2A, 0x00, 0xF0, 0x9E, 0x81, 0x01, 0x2B, ++0xB8, 0xD0, 0x94, 0xF8, 0x86, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x0D, 0x81, 0x94, 0xF8, 0x72, 0x50, 0x94, 0xF8, ++0x85, 0x30, 0xA5, 0xF1, 0x01, 0x06, 0xB6, 0xFA, 0x86, 0xF6, 0x76, 0x09, 0xB3, 0x42, 0x00, 0xF0, 0x4C, 0x81, 0x02, 0x23, ++0x0C, 0x21, 0x52, 0x46, 0x4D, 0x20, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x20, 0x92, 0x03, 0xF0, 0xC1, 0xF8, 0x6F, 0x1E, ++0x18, 0xBF, 0x01, 0x27, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x47, 0x70, 0x03, 0xF0, 0xE8, 0xF8, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x08, 0x93, 0x84, 0xF8, 0x85, 0x60, 0x18, 0x6C, 0x39, 0x46, 0xFF, 0xF7, 0xC0, 0xF8, 0x01, 0x2D, 0x4C, 0xD0, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x93, 0xF8, 0x62, 0x20, 0x02, 0x2A, 0x00, 0xF0, 0xF1, 0x80, 0x94, 0xF8, ++0x70, 0x30, 0x7B, 0xB9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x98, 0x98, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x07, 0xD0, ++0x6E, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x01, 0x22, 0x83, 0xF8, 0x24, 0x20, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x90, 0xF8, 0x40, 0x20, 0x03, 0x7D, 0x02, 0x2A, 0xA8, 0xD1, 0x94, 0xF8, 0x44, 0x20, 0x93, 0x42, 0x28, 0xBF, ++0x13, 0x46, 0xA2, 0xE7, 0xFF, 0x23, 0xF7, 0xE7, 0x94, 0xF8, 0x85, 0x20, 0x01, 0x2A, 0x3F, 0xF4, 0x30, 0xAF, 0x94, 0xF8, ++0x71, 0x80, 0xDF, 0xF8, 0x88, 0x91, 0x02, 0x23, 0x0C, 0x21, 0x00, 0x22, 0x4D, 0x20, 0x03, 0xF0, 0x71, 0xF8, 0x00, 0x25, ++0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x45, 0x70, 0x03, 0xF0, 0x9A, 0xF8, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, ++0x01, 0x22, 0x84, 0xF8, 0x85, 0x20, 0x18, 0x6C, 0x29, 0x46, 0xFF, 0xF7, 0x71, 0xF8, 0x94, 0xF8, 0x70, 0xE0, 0xBE, 0xF1, ++0x00, 0x0F, 0x40, 0xF0, 0xD4, 0x80, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x08, 0x97, 0x97, 0xF8, 0x6C, 0x10, 0xFF, 0x29, ++0x00, 0xF0, 0xF0, 0x80, 0x4A, 0x4D, 0x01, 0x94, 0x4F, 0xF4, 0x1E, 0x7B, 0xA4, 0x23, 0x0B, 0xFB, 0x01, 0xF0, 0x03, 0xFB, ++0x08, 0xF3, 0x05, 0xF5, 0x16, 0x7B, 0x2E, 0x18, 0x9E, 0x33, 0x58, 0x44, 0x00, 0x90, 0x09, 0xEB, 0xC3, 0x0B, 0x4F, 0xF0, ++0x4F, 0x0C, 0x46, 0x20, 0x1C, 0xFB, 0x01, 0x01, 0x5C, 0x46, 0x40, 0x4A, 0xDD, 0xF8, 0x00, 0xB0, 0x86, 0xF8, 0x24, 0xE0, ++0x05, 0xEB, 0xC1, 0x05, 0xD6, 0xF8, 0x08, 0x12, 0x39, 0xB3, 0xEF, 0xF3, 0x10, 0x81, 0xCB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x39, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x11, 0x68, 0xA5, 0xF1, 0x28, 0x00, 0x4B, 0x1C, 0xA4, 0xF1, 0x28, 0x01, 0x13, 0x60, ++0x00, 0x90, 0x03, 0xF0, 0x9D, 0xFD, 0xD6, 0xF8, 0x08, 0x12, 0xD6, 0xF8, 0x0C, 0x32, 0x00, 0x98, 0xC7, 0xF8, 0xC8, 0x14, ++0xC7, 0xF8, 0xCC, 0x34, 0x03, 0xF0, 0x9C, 0xFC, 0x2C, 0x4A, 0x11, 0x68, 0x48, 0x1E, 0x31, 0xB1, 0x2B, 0x4B, 0x10, 0x60, ++0x19, 0x68, 0x10, 0xB9, 0x00, 0x29, 0x40, 0xF0, 0xB5, 0x80, 0xD6, 0xF8, 0x30, 0x32, 0x20, 0x46, 0x29, 0x46, 0x08, 0x36, ++0x08, 0x34, 0x08, 0x37, 0x2B, 0xB1, 0x03, 0xF0, 0x7D, 0xFD, 0x28, 0x46, 0x03, 0xF0, 0x84, 0xFC, 0x20, 0x4A, 0x08, 0x35, ++0x5D, 0x45, 0xC3, 0xD1, 0x01, 0x9C, 0x40, 0x20, 0x03, 0xF0, 0xDE, 0xFB, 0x94, 0xF8, 0x70, 0x20, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x08, 0x98, 0x98, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x13, 0xD0, 0x00, 0x2A, 0x7F, 0xF4, 0x55, 0xAF, 0xBA, 0xF1, ++0x00, 0x0F, 0x7F, 0xF4, 0x51, 0xAF, 0x99, 0xE6, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0x8E, 0xAE, 0x94, 0xF8, ++0x71, 0x80, 0xDF, 0xF8, 0x48, 0x90, 0x4F, 0xF0, 0x00, 0x0A, 0x5C, 0xE7, 0xD8, 0xF8, 0x04, 0x30, 0x43, 0xF0, 0x20, 0x03, ++0xC8, 0xF8, 0x04, 0x30, 0x00, 0x2A, 0x7F, 0xF4, 0x3B, 0xAF, 0xE4, 0xE7, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, ++0x35, 0xAF, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x1C, 0x90, 0x4F, 0xF0, 0x01, 0x0A, 0x46, 0xE7, 0x88, 0x1A, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x3C, 0x49, 0x5A, 0x68, 0x49, 0x68, 0x22, 0xF0, 0x20, 0x02, 0x00, 0x29, 0x5A, 0x60, 0x7F, 0xF7, 0x06, 0xAF, 0xEF, 0xF3, ++0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x36, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x36, 0x4D, 0x2B, 0x68, 0x04, 0x20, ++0x01, 0x33, 0x2B, 0x60, 0xEE, 0xF7, 0x1C, 0xFF, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xEE, 0xF7, 0xB7, 0xFF, 0x2B, 0x68, ++0x00, 0x2B, 0x3F, 0xF4, 0xEE, 0xAE, 0x2D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0xE7, 0xAE, ++0x00, 0x2A, 0x3F, 0xF4, 0xE4, 0xAE, 0x62, 0xB6, 0xE1, 0xE6, 0x40, 0x20, 0x03, 0xF0, 0x6E, 0xFB, 0x94, 0xF8, 0x70, 0x20, ++0x8E, 0xE7, 0x94, 0xF8, 0x70, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0xEA, 0xAE, 0x01, 0x2D, 0x7F, 0xF4, 0xE7, 0xAE, 0x2D, 0xE6, ++0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x80, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x93, 0xF8, 0xDE, 0x20, ++0x93, 0xF8, 0xC2, 0x34, 0x9A, 0x42, 0x20, 0xD0, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0xD3, 0xAE, 0x4F, 0xF0, ++0x00, 0x0A, 0xE8, 0xE6, 0x97, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x7F, 0xF4, 0x76, 0xAF, 0x7B, 0x68, 0x43, 0xF0, 0x20, 0x03, ++0x7B, 0x60, 0xBA, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0xC3, 0xAE, 0x0B, 0xE6, 0x62, 0xB6, 0x48, 0xE7, 0x94, 0xF8, 0x85, 0x20, ++0x01, 0x2A, 0x7F, 0xF4, 0x70, 0xAF, 0x00, 0x2B, 0x3F, 0xF4, 0x00, 0xAE, 0xB6, 0xE6, 0x94, 0xF8, 0x85, 0x30, 0x00, 0x2B, ++0x7F, 0xF4, 0x27, 0xAE, 0xB0, 0xE6, 0x01, 0x21, 0x42, 0xE6, 0x90, 0xF8, 0x40, 0x30, 0x02, 0x2B, 0x7F, 0xF4, 0xE3, 0xAD, ++0x3A, 0xE6, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xF4, 0x92, 0x47, 0x7C, 0xB6, 0x49, 0x90, 0xF8, 0x10, 0xB0, 0x8C, 0x23, 0x03, 0xFB, ++0x07, 0x93, 0x83, 0xB0, 0x93, 0xF8, 0x71, 0x20, 0x93, 0xF8, 0x70, 0x30, 0x00, 0x92, 0x07, 0xEB, 0x87, 0x06, 0x4F, 0xF4, ++0xA4, 0x6A, 0xC6, 0xEB, 0xC6, 0x06, 0x01, 0x2B, 0x05, 0x46, 0x0A, 0xFB, 0x02, 0x1A, 0x09, 0xEB, 0x86, 0x06, 0x00, 0xF0, ++0x0B, 0x81, 0xAA, 0x4B, 0xC4, 0x6A, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xD3, 0x80, 0xDA, 0xF8, ++0x7C, 0x30, 0xE4, 0x1A, 0xA4, 0x4B, 0xA5, 0x49, 0xDF, 0xF8, 0x94, 0x82, 0xBB, 0xF1, 0x01, 0x0F, 0x17, 0xD0, 0xBB, 0xF1, ++0x02, 0x0F, 0x00, 0xF0, 0x82, 0x80, 0x1A, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x7F, 0xDB, 0xD8, 0xF8, 0x10, 0x20, ++0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0x80, 0xF2, 0xE9, 0x80, 0xBB, 0xF1, 0x00, 0x0F, 0xE7, 0xD1, ++0xDF, 0xF8, 0x70, 0x82, 0x20, 0xE0, 0xA8, 0x69, 0xDF, 0xF8, 0x68, 0x82, 0x95, 0x4B, 0x1B, 0x69, 0x04, 0x44, 0xE3, 0x1A, ++0xA3, 0xF5, 0x9C, 0x53, 0x08, 0x3B, 0x00, 0x2B, 0x80, 0xF2, 0xFA, 0x80, 0xEA, 0x7C, 0xFF, 0x2A, 0x1B, 0xD0, 0x01, 0x3A, ++0xD2, 0xB2, 0xEA, 0x74, 0xBA, 0xB9, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x97, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x5D, 0xD0, ++0xD8, 0xF8, 0xE8, 0x31, 0x28, 0x46, 0x98, 0x47, 0x87, 0x4B, 0x1B, 0x69, 0xD8, 0xF8, 0x1C, 0x32, 0x30, 0x46, 0x98, 0x47, ++0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x4F, 0xF0, 0x8C, 0x0E, 0x0E, 0xFB, ++0x07, 0x9E, 0xD5, 0xE9, 0x06, 0x0B, 0x9E, 0xF8, 0x70, 0x30, 0xAB, 0xEB, 0x00, 0x01, 0x01, 0x2B, 0x0C, 0x44, 0x47, 0xD0, ++0x7A, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xA8, 0xBF, 0x4F, 0xF0, 0x01, 0x0B, ++0xBE, 0xDB, 0x53, 0xB9, 0x72, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB0, 0x80, 0xDA, 0xF8, ++0x7C, 0x30, 0x23, 0x44, 0xEB, 0x62, 0x21, 0x46, 0xD8, 0xF8, 0xE0, 0x31, 0x28, 0x46, 0x98, 0x47, 0x85, 0xF8, 0x10, 0xB0, ++0xD8, 0xF8, 0x1C, 0x32, 0x30, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x98, 0x47, 0x00, 0x9A, 0x11, 0x46, ++0x63, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xA4, 0x80, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, 0x90, 0x81, 0x9B, 0xE7, 0x5F, 0x48, 0x4F, 0xF4, 0x31, 0x72, 0x04, 0xF0, ++0x53, 0xFF, 0x5A, 0x4B, 0x5A, 0x49, 0x77, 0xE7, 0xD8, 0xF8, 0x08, 0x32, 0xA9, 0x7C, 0x50, 0x46, 0x98, 0x47, 0x58, 0x4B, ++0x1B, 0x69, 0x9F, 0xE7, 0x9E, 0xF8, 0x84, 0x10, 0x00, 0x29, 0x36, 0xD0, 0xA9, 0x6A, 0x01, 0x91, 0x69, 0x6A, 0x01, 0xEB, ++0x0B, 0x0C, 0x01, 0x99, 0x01, 0x39, 0xC5, 0xE9, 0x09, 0xC1, 0x00, 0x29, 0x5E, 0xD1, 0x2A, 0x75, 0xBB, 0xF1, 0x00, 0x0F, ++0x05, 0xD0, 0x4F, 0xF0, 0x00, 0x43, 0xB3, 0xFB, 0xFB, 0xF3, 0x01, 0x3B, 0xAB, 0x62, 0x00, 0x9B, 0x19, 0x46, 0x46, 0x4B, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x32, 0xD8, 0xF8, 0x90, 0x31, 0x92, 0xF8, 0x63, 0x00, 0x03, 0x21, 0x98, 0x47, ++0x43, 0x4B, 0x1B, 0x69, 0xE3, 0x1A, 0xA3, 0xF5, 0x9C, 0x53, 0x08, 0x3B, 0x00, 0x2B, 0x71, 0xDA, 0xA8, 0x69, 0x51, 0xE7, ++0x9A, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x28, 0xAF, 0x3B, 0x49, 0x3D, 0x48, 0x58, 0x22, 0x04, 0xF0, 0x0E, 0xFF, ++0x21, 0xE7, 0x39, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xFF, 0xF6, 0x3E, 0xAF, ++0xD8, 0xF8, 0xE0, 0x21, 0x01, 0x93, 0x21, 0x46, 0x28, 0x46, 0x90, 0x47, 0x01, 0x9B, 0x2B, 0x74, 0xD8, 0xF8, 0x1C, 0x32, ++0x30, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x98, 0x47, 0x00, 0x9A, 0x11, 0x46, 0x28, 0x4A, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x8A, 0xD1, 0x31, 0xE0, 0xC4, 0x68, 0xFD, 0xE6, ++0xBB, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x16, 0xAF, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0xDF, 0xF8, 0x98, 0x80, 0x97, 0xF8, ++0x70, 0x30, 0x54, 0xE7, 0x1F, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xFF, 0xF6, ++0x0B, 0xAF, 0x9B, 0x46, 0x9E, 0xF8, 0x70, 0x30, 0x47, 0xE7, 0x9A, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x4B, 0xAF, ++0x15, 0x49, 0x18, 0x48, 0x49, 0x22, 0x04, 0xF0, 0xC3, 0xFE, 0x44, 0xE7, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x4F, 0xF0, ++0x02, 0x0B, 0x97, 0xF8, 0x70, 0x30, 0x34, 0xE7, 0xBB, 0xF1, 0x01, 0x0F, 0x7F, 0xF4, 0x58, 0xAF, 0x00, 0x9A, 0x11, 0x46, ++0x09, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x5A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x5A, 0x60, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x4F, 0xF0, 0x01, 0x0B, 0x97, 0xF8, 0x70, 0x30, 0x1A, 0xE7, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x64, 0x7D, 0x15, 0x00, ++0x40, 0x9C, 0x15, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x00, 0x22, 0x04, 0x46, 0x0D, 0x46, ++0x10, 0x23, 0x0C, 0x21, 0x55, 0x20, 0x02, 0xF0, 0xA5, 0xFD, 0x05, 0xEB, 0x45, 0x03, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, ++0x04, 0xEB, 0x03, 0x13, 0x45, 0x70, 0x1A, 0x7C, 0x22, 0xB9, 0xC2, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0xF0, 0xC6, 0xBD, ++0x1A, 0x7D, 0xC2, 0x70, 0x00, 0x2A, 0xF7, 0xD0, 0x93, 0xF8, 0x20, 0x20, 0x82, 0x70, 0xD3, 0xE9, 0x06, 0x12, 0x5B, 0x6A, ++0xC3, 0x60, 0xC0, 0xE9, 0x01, 0x12, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0xF0, 0xB5, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, ++0x16, 0x46, 0x2D, 0x4D, 0x4F, 0xF4, 0xA4, 0x62, 0xB3, 0x42, 0x04, 0x46, 0x02, 0xFB, 0x01, 0x58, 0x0B, 0xD3, 0xC2, 0x7C, ++0x01, 0x2A, 0x30, 0xD0, 0xC5, 0x69, 0x9B, 0x1B, 0xB3, 0xFB, 0xF5, 0xF3, 0x03, 0xFB, 0x05, 0x55, 0x2E, 0x44, 0x5F, 0x1C, ++0x00, 0xE0, 0x00, 0x27, 0x23, 0x4B, 0xE6, 0x62, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0xE3, 0x7C, ++0xD8, 0xF8, 0x7C, 0x00, 0xFF, 0x2B, 0xA6, 0xEB, 0x00, 0x00, 0x31, 0xD0, 0xBB, 0x42, 0x94, 0xBF, 0xDB, 0x1A, 0xDB, 0x1B, ++0x1B, 0x4A, 0xDB, 0xB2, 0xE3, 0x74, 0x12, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0x0C, 0xDA, 0x18, 0x49, 0x5B, 0xB1, 0xE5, 0x69, ++0xFF, 0x2B, 0x28, 0x44, 0x0A, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0xE3, 0x74, 0x0A, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0xF3, 0xDB, ++0x03, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x0A, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0xED, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, ++0x98, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xD2, 0xD0, 0x0B, 0x48, 0x0C, 0x49, 0x58, 0x22, 0x04, 0xF0, 0x15, 0xFE, 0xE3, 0x7C, ++0xD8, 0xF8, 0x7C, 0x00, 0xFF, 0x2B, 0xA6, 0xEB, 0x00, 0x00, 0xCD, 0xD1, 0x04, 0x4A, 0x12, 0x69, 0x82, 0x1A, 0x00, 0x2A, ++0xD3, 0xDB, 0xE1, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x40, 0x9C, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x70, 0xB5, 0x08, 0x4E, 0xD6, 0xF8, 0xEC, 0x41, 0x05, 0x46, 0xA0, 0x47, 0x04, 0x46, 0x30, 0xB1, ++0xD6, 0xF8, 0xE0, 0x31, 0x01, 0x46, 0x28, 0x46, 0x98, 0x47, 0x01, 0x23, 0x2B, 0x74, 0xE0, 0xB2, 0x70, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x03, 0x7C, 0x43, 0xB1, 0x10, 0xB5, 0x04, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, ++0x00, 0x23, 0x23, 0x74, 0x10, 0xBD, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x5C, 0x4F, 0x00, 0xEB, ++0x80, 0x04, 0xC4, 0xEB, 0xC4, 0x04, 0x4F, 0xEA, 0x84, 0x0A, 0x83, 0xB0, 0x05, 0x46, 0x07, 0xEB, 0x84, 0x04, 0x0E, 0x46, ++0x00, 0x29, 0x74, 0xD0, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x73, 0x91, 0x46, 0xCA, 0x78, 0x93, 0xF8, 0x84, 0x10, 0x00, 0x29, ++0x40, 0xF0, 0x8A, 0x80, 0x4F, 0xF0, 0x8C, 0x08, 0x08, 0xFB, 0x05, 0x78, 0x01, 0x21, 0x98, 0xF8, 0x79, 0x30, 0x88, 0xF8, ++0x78, 0x20, 0x88, 0xF8, 0x84, 0x10, 0xAB, 0xB1, 0xDF, 0xF8, 0x30, 0xB1, 0x20, 0x46, 0xDB, 0xF8, 0xE8, 0x31, 0x98, 0x47, ++0x00, 0x22, 0x0A, 0xF1, 0x30, 0x00, 0xDB, 0xF8, 0xE8, 0x31, 0x88, 0xF8, 0x79, 0x20, 0x38, 0x44, 0x98, 0x47, 0x00, 0x22, ++0xDB, 0xF8, 0x18, 0x32, 0x88, 0xF8, 0x79, 0x20, 0x20, 0x46, 0x98, 0x47, 0xB6, 0xF8, 0x01, 0x20, 0x3F, 0x49, 0x02, 0x3A, ++0x81, 0xFB, 0x02, 0x31, 0xD3, 0x17, 0xC3, 0xEB, 0xA1, 0x03, 0x13, 0xF0, 0xFF, 0x0B, 0x2E, 0xD0, 0x8C, 0x23, 0x03, 0xFB, ++0x05, 0x73, 0x00, 0x93, 0x06, 0xF1, 0x05, 0x08, 0x4F, 0xF0, 0x00, 0x0A, 0x01, 0x95, 0x98, 0xF8, 0x00, 0x20, 0x36, 0x49, ++0x22, 0x75, 0x0A, 0xF1, 0x01, 0x0A, 0x20, 0x46, 0x4B, 0x46, 0x9A, 0xB1, 0x01, 0x2A, 0xD8, 0xF8, 0x05, 0x50, 0x00, 0xD9, ++0x75, 0xB1, 0xD8, 0xF8, 0x01, 0xC0, 0xE2, 0x74, 0xC4, 0xE9, 0x06, 0xC5, 0x00, 0x9A, 0xD1, 0xF8, 0xF4, 0x51, 0x92, 0xF8, ++0x71, 0x10, 0xD8, 0xF8, 0x09, 0x20, 0xA8, 0x47, 0x00, 0x28, 0x45, 0xD1, 0x5F, 0xFA, 0x8A, 0xF3, 0x5B, 0x45, 0x08, 0xF1, ++0x0D, 0x08, 0x04, 0xF1, 0x30, 0x04, 0xDA, 0xD3, 0x01, 0x9D, 0x96, 0xF9, 0x04, 0x20, 0x33, 0x79, 0x00, 0x2A, 0x2D, 0xDB, ++0x8C, 0x20, 0x00, 0xFB, 0x05, 0x75, 0x00, 0x23, 0x85, 0xF8, 0x73, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xF0, ++0x8C, 0x08, 0x08, 0xFB, 0x00, 0x78, 0x98, 0xF8, 0x79, 0x30, 0x88, 0xF8, 0x84, 0x10, 0x00, 0x2B, 0xEC, 0xD0, 0xDF, 0xF8, ++0x60, 0x90, 0x20, 0x46, 0xD9, 0xF8, 0xE8, 0x31, 0x98, 0x47, 0x0A, 0xF1, 0x30, 0x00, 0xD9, 0xF8, 0xE8, 0x31, 0x88, 0xF8, ++0x79, 0x60, 0x38, 0x44, 0x98, 0x47, 0xD9, 0xF8, 0x18, 0x32, 0x88, 0xF8, 0x79, 0x60, 0x20, 0x46, 0x98, 0x47, 0xD7, 0xE7, ++0x93, 0xF8, 0x78, 0x30, 0x93, 0x42, 0x7F, 0xF4, 0x71, 0xAF, 0xD7, 0xE7, 0x8C, 0x20, 0x00, 0xFB, 0x05, 0x75, 0x03, 0xF0, ++0x7F, 0x03, 0x85, 0xF8, 0x73, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x9A, 0x92, 0xF8, 0x79, 0x30, 0x01, 0x33, ++0x82, 0xF8, 0x79, 0x30, 0xB2, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x4F, 0xEC, 0xC4, 0x4E, 0x88, 0x1A, 0x17, 0x00, ++0x08, 0xB5, 0x01, 0x22, 0x05, 0x48, 0x00, 0x21, 0xE0, 0xF7, 0x2C, 0xF8, 0x04, 0x4B, 0xFF, 0x22, 0x83, 0xF8, 0x71, 0x20, ++0x83, 0xF8, 0xFD, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x44, 0x9E, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x25, 0x4C, 0x94, 0xF8, 0x71, 0x30, 0xFF, 0x2B, 0x07, 0x46, 0x0E, 0x46, 0x08, 0xD0, 0x94, 0xF8, 0xFD, 0x30, 0xFF, 0x2B, ++0x18, 0xBF, 0xFF, 0x25, 0x36, 0xD0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x25, 0xA8, 0x46, 0x4F, 0xF0, 0x30, 0x0A, ++0xA1, 0x46, 0x8C, 0x22, 0x00, 0x21, 0x48, 0x46, 0xE0, 0xF7, 0x04, 0xF8, 0x8C, 0x23, 0x03, 0xFB, 0x08, 0x43, 0x01, 0x2E, ++0x83, 0xF8, 0x71, 0x70, 0x83, 0xF8, 0x70, 0x60, 0x03, 0xD1, 0x15, 0x4A, 0x13, 0x78, 0x01, 0x33, 0x13, 0x70, 0x8C, 0x23, ++0x03, 0xFB, 0x08, 0x43, 0x12, 0x4A, 0xC3, 0xF8, 0x08, 0x90, 0x54, 0x44, 0x00, 0x21, 0x01, 0x26, 0x9C, 0x63, 0x99, 0x74, ++0x0F, 0x4C, 0xD2, 0xF8, 0x10, 0x12, 0x5D, 0x74, 0x83, 0xF8, 0x41, 0x50, 0xC3, 0xF8, 0x68, 0x90, 0x83, 0xF8, 0x42, 0x60, ++0x5C, 0x66, 0x59, 0x60, 0x59, 0x63, 0x48, 0x46, 0xD2, 0xF8, 0x18, 0x32, 0x98, 0x47, 0xC8, 0xE7, 0x01, 0x25, 0xA8, 0x46, ++0x4F, 0xF0, 0xBC, 0x0A, 0x04, 0xF1, 0x8C, 0x09, 0xC9, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x41, 0xF4, 0x13, 0x00, 0x0E, 0x4A, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x23, 0x10, 0xB4, 0x93, 0xF8, ++0x71, 0x40, 0xFF, 0x2C, 0x0A, 0xD0, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x09, 0xD0, 0x29, 0xB1, 0x8C, 0x23, 0x03, 0xFB, ++0x00, 0x20, 0xFF, 0x23, 0x80, 0xF8, 0x71, 0x30, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x04, 0x4C, 0x23, 0x78, 0x01, 0x3B, ++0x23, 0x70, 0x00, 0x29, 0xF6, 0xD0, 0xEF, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, 0x90, 0xF8, 0xC0, 0x34, ++0xBB, 0xB3, 0x2D, 0xE9, 0xF0, 0x47, 0x90, 0xF8, 0x62, 0x40, 0x0C, 0x43, 0x2F, 0xD1, 0x90, 0xF8, 0xC1, 0x54, 0xDF, 0xF8, ++0x64, 0x80, 0x17, 0x4F, 0x05, 0xEB, 0x85, 0x00, 0xC0, 0xEB, 0xC0, 0x00, 0x08, 0xEB, 0x80, 0x09, 0xD7, 0xF8, 0xE8, 0x31, ++0x86, 0x00, 0x48, 0x46, 0x98, 0x47, 0x06, 0xF1, 0x30, 0x00, 0xD7, 0xF8, 0xE8, 0x31, 0x40, 0x44, 0x98, 0x47, 0x8C, 0x23, ++0x03, 0xFB, 0x05, 0x85, 0x95, 0xF8, 0x72, 0x30, 0x85, 0xF8, 0x73, 0x40, 0x85, 0xF8, 0x78, 0x40, 0x85, 0xF8, 0x84, 0x40, ++0x3B, 0xB1, 0x06, 0xF1, 0x60, 0x00, 0xD7, 0xF8, 0xD8, 0x31, 0x40, 0x44, 0x98, 0x47, 0x85, 0xF8, 0x72, 0x40, 0xD7, 0xF8, ++0x18, 0x32, 0x48, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x87, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0x48, 0x9E, 0x17, 0x00, 0x03, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0x85, 0x00, 0x70, 0x47, 0x00, 0xBF, ++0x48, 0x9E, 0x17, 0x00, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x70, 0xB5, 0x05, 0x46, 0x0C, 0x46, ++0x16, 0x46, 0x0E, 0xDB, 0x95, 0xF8, 0xC1, 0x34, 0x0C, 0x4A, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0xD3, 0xF8, 0x80, 0x20, ++0x22, 0x60, 0xD8, 0x6F, 0x30, 0x60, 0x23, 0x68, 0xC0, 0x1A, 0xC0, 0x0F, 0x70, 0xBD, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0xEC, 0xD1, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x06, 0x52, 0x04, 0xF0, 0x23, 0xFC, 0xE5, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x48, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA4, 0xA3, 0x15, 0x00, 0x70, 0xB5, 0x35, 0x4E, 0x33, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, 0x12, 0xDB, 0x90, 0xF8, 0xC1, 0x24, 0x31, 0x48, 0x8C, 0x23, 0x01, 0xEB, ++0x41, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, 0x1B, 0x7C, 0x01, 0x2B, 0x28, 0xD0, ++0x02, 0x2B, 0x1D, 0xD0, 0x00, 0x20, 0x70, 0xBD, 0x90, 0xF8, 0xC0, 0x34, 0x0B, 0xB1, 0x01, 0x29, 0x30, 0xD9, 0x27, 0x49, ++0x27, 0x48, 0x40, 0xF2, 0x14, 0x52, 0x04, 0xF0, 0xF3, 0xFB, 0x95, 0xF8, 0xC1, 0x24, 0x22, 0x48, 0x8C, 0x23, 0x04, 0xEB, ++0x44, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, 0x1B, 0x7C, 0x01, 0x2B, 0x0A, 0xD0, ++0x02, 0x2B, 0x13, 0xD1, 0x8C, 0x23, 0x0C, 0x44, 0x03, 0xFB, 0x02, 0xF1, 0x01, 0xEB, 0x04, 0x11, 0x01, 0x44, 0xC8, 0x68, ++0x70, 0xBD, 0x8C, 0x23, 0x0C, 0x44, 0x03, 0xFB, 0x02, 0xF1, 0x01, 0xEB, 0x04, 0x14, 0x01, 0x19, 0xC8, 0x68, 0x8B, 0x69, ++0x18, 0x44, 0x70, 0xBD, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC8, 0xDA, 0x10, 0xE0, 0x90, 0xF8, 0xC1, 0x24, ++0x0C, 0x48, 0x8C, 0x23, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, ++0x1B, 0x7C, 0x01, 0x2B, 0xDF, 0xD0, 0x02, 0x2B, 0xD4, 0xD0, 0x06, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0xA4, 0x62, 0x04, 0xF0, ++0xC9, 0xFB, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xB0, 0xA3, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x43, 0xD0, 0x2D, 0xE9, 0xF0, 0x41, ++0x28, 0x4F, 0x90, 0xF8, 0xC1, 0x24, 0x44, 0x68, 0x8C, 0x26, 0x06, 0xFB, 0x02, 0x76, 0x02, 0xEB, 0x82, 0x03, 0x96, 0xF8, ++0x73, 0xC0, 0x01, 0x25, 0xC3, 0xEB, 0xC3, 0x03, 0x24, 0xF0, 0x40, 0x04, 0x86, 0xF8, 0x86, 0x50, 0x4F, 0xEA, 0x83, 0x0E, ++0x07, 0xEB, 0x83, 0x05, 0x44, 0x60, 0xBC, 0xF1, 0x00, 0x0F, 0x06, 0xD1, 0x1C, 0x4E, 0x28, 0x46, 0xD6, 0xF8, 0x18, 0x32, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x96, 0xF8, 0x70, 0x30, 0x01, 0xEB, 0x8C, 0x24, 0x3B, 0xB9, 0x17, 0x4B, 0x18, 0x69, ++0x01, 0xF5, 0x96, 0x73, 0xC1, 0x1A, 0x11, 0xF1, 0x32, 0x0F, 0x14, 0xD4, 0x8C, 0x23, 0x03, 0xFB, 0x02, 0x72, 0x11, 0x4E, ++0x0E, 0xF1, 0x60, 0x00, 0x01, 0x23, 0x38, 0x44, 0x21, 0x46, 0x82, 0xF8, 0x72, 0x30, 0xD6, 0xF8, 0xE0, 0x31, 0x98, 0x47, ++0xD6, 0xF8, 0x18, 0x32, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x70, 0x47, 0x08, 0x4D, 0x74, 0x67, 0x0E, 0xF1, ++0x60, 0x00, 0x02, 0x22, 0x38, 0x44, 0x19, 0x46, 0x86, 0xF8, 0x72, 0x20, 0xD5, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, ++0x18, 0x47, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0xB4, 0x0A, 0x49, ++0x90, 0xF8, 0xC1, 0x34, 0x09, 0x4C, 0x8C, 0x20, 0x03, 0xEB, 0x83, 0x02, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x25, 0xC2, 0xEB, ++0xC2, 0x02, 0x83, 0xF8, 0x86, 0x50, 0x01, 0xEB, 0x82, 0x00, 0xD4, 0xF8, 0x18, 0x32, 0x30, 0xBC, 0x18, 0x47, 0x00, 0xBF, ++0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x90, 0xF8, 0xC0, 0x44, 0x00, 0x2C, 0x3E, 0xD0, ++0x90, 0xF8, 0x62, 0x30, 0x05, 0x46, 0x00, 0x2B, 0x3C, 0xD1, 0x27, 0x4B, 0x90, 0xF8, 0xC1, 0x74, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x88, 0x46, 0x16, 0x46, 0x36, 0xDB, 0xD8, 0xF8, 0x08, 0x00, 0xB2, 0x8B, 0x00, 0xF1, 0x24, 0x03, ++0x10, 0x44, 0x83, 0x42, 0x02, 0xD3, 0x38, 0xE0, 0x98, 0x42, 0x36, 0xD9, 0x5D, 0x78, 0x1A, 0x78, 0xA9, 0x1C, 0xDD, 0x2A, ++0x1C, 0x46, 0x0B, 0x44, 0xF6, 0xD1, 0x62, 0x79, 0x09, 0x2A, 0xF3, 0xD1, 0x06, 0x34, 0x04, 0x3D, 0x14, 0xFA, 0x85, 0xF5, ++0xAC, 0x42, 0x06, 0xD3, 0xEC, 0xE7, 0xB4, 0xF8, 0x01, 0x10, 0x03, 0x31, 0x0C, 0x44, 0xA5, 0x42, 0xE6, 0xD9, 0x22, 0x78, ++0x0C, 0x2A, 0xF6, 0xD1, 0x00, 0x2C, 0xE1, 0xD0, 0xB2, 0x68, 0x0F, 0x4B, 0x92, 0x68, 0xD3, 0xF8, 0xF0, 0x31, 0x92, 0x69, ++0x38, 0x46, 0x21, 0x46, 0x98, 0x47, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x24, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, ++0x01, 0x2F, 0xC6, 0xD9, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x73, 0x52, 0x04, 0xF0, 0xD8, 0xFA, 0x95, 0xF8, 0xC1, 0x74, ++0xBD, 0xE7, 0x00, 0x24, 0xE2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xD8, 0xA3, 0x15, 0x00, 0xF0, 0xB5, 0x0C, 0x7E, 0x7F, 0x2C, 0x83, 0xB0, 0x23, 0xD1, 0x4A, 0x7F, 0x0A, 0xBB, 0xCA, 0x7F, ++0xDD, 0x2A, 0x1E, 0xD1, 0x91, 0xF8, 0x24, 0x20, 0x09, 0x2A, 0x1A, 0xD1, 0x91, 0xF8, 0x25, 0x20, 0x0C, 0x2A, 0x01, 0xF1, ++0x25, 0x04, 0x14, 0xD1, 0x11, 0x4A, 0x12, 0x49, 0x12, 0x68, 0xD1, 0xF8, 0xF0, 0x61, 0xB2, 0xF9, 0x00, 0x20, 0x90, 0xF8, ++0xC1, 0x74, 0x00, 0x2A, 0x05, 0x46, 0x0A, 0xDB, 0xEA, 0x6F, 0x21, 0x46, 0x1A, 0x44, 0x38, 0x46, 0x33, 0x46, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x40, 0x18, 0x47, 0x03, 0xB0, 0xF0, 0xBD, 0x90, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xF0, 0xD0, 0x06, 0x49, ++0x06, 0x48, 0x01, 0x93, 0x49, 0x22, 0x04, 0xF0, 0x95, 0xFA, 0x01, 0x9B, 0xE8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x12, 0x4B, 0x18, 0x78, 0xF8, 0xB1, 0x12, 0x4B, ++0x58, 0x7C, 0xD8, 0xB9, 0x9A, 0x7C, 0x01, 0x2A, 0x19, 0xD8, 0x9B, 0x68, 0x13, 0xB9, 0x16, 0xE0, 0x1B, 0x68, 0xAB, 0xB1, ++0x93, 0xF8, 0x62, 0x20, 0x02, 0x2A, 0xF9, 0xD1, 0x93, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0xF5, 0xD0, 0x93, 0xF8, 0xC1, 0x34, ++0x08, 0x4A, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x85, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x44, 0x9E, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, ++0x18, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x1B, 0xB1, 0x90, 0xF8, 0x62, 0x30, ++0x02, 0x2B, 0x00, 0xD0, 0x70, 0x47, 0x70, 0xB5, 0x90, 0xF8, 0xC1, 0x34, 0x11, 0x4C, 0x8C, 0x22, 0x02, 0xFB, 0x03, 0x42, ++0x00, 0x39, 0x03, 0xEB, 0x83, 0x03, 0x92, 0xF8, 0x84, 0x50, 0x18, 0xBF, 0x01, 0x21, 0xC3, 0xEB, 0xC3, 0x03, 0x82, 0xF8, ++0x87, 0x10, 0x04, 0xEB, 0x83, 0x04, 0x35, 0xB9, 0x09, 0x4D, 0xD5, 0xF8, 0x18, 0x32, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, ++0x18, 0x47, 0x06, 0x4D, 0x92, 0xF8, 0x71, 0x00, 0xD5, 0xF8, 0x90, 0x31, 0x03, 0x21, 0x98, 0x47, 0xF1, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0E, 0x4E, 0x90, 0xF8, 0xC1, 0x44, ++0x0D, 0x4D, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0x01, 0x22, 0x04, 0xEB, 0x84, 0x04, 0x93, 0xF8, 0x71, 0x00, 0x83, 0xF8, ++0x73, 0x10, 0x83, 0xF8, 0x72, 0x20, 0xC4, 0xEB, 0xC4, 0x04, 0xD5, 0xF8, 0x90, 0x31, 0x03, 0x21, 0x98, 0x47, 0xD5, 0xF8, ++0x18, 0x32, 0x06, 0xEB, 0x84, 0x00, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x1D, 0x4F, 0x90, 0xF8, 0xC1, 0x44, 0x8C, 0x26, 0x06, 0xFB, 0x04, 0x76, 0x04, 0xEB, 0x84, 0x00, ++0x96, 0xF8, 0x72, 0x20, 0xC0, 0xEB, 0xC0, 0x00, 0x4F, 0xF0, 0x00, 0x09, 0x07, 0xEB, 0x80, 0x05, 0x86, 0xF8, 0x73, 0x90, ++0x9A, 0xB9, 0xDF, 0xF8, 0x54, 0x80, 0xD8, 0xF8, 0x18, 0x32, 0x28, 0x46, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x74, ++0x94, 0xF8, 0x79, 0x30, 0x9B, 0xB9, 0xD8, 0xF8, 0x90, 0x31, 0x94, 0xF8, 0x71, 0x00, 0x02, 0x21, 0xBD, 0xE8, 0xF0, 0x47, ++0x18, 0x47, 0x83, 0x00, 0xDF, 0xF8, 0x28, 0x80, 0x03, 0xF1, 0x60, 0x00, 0x38, 0x44, 0xD8, 0xF8, 0xD8, 0x31, 0x98, 0x47, ++0x86, 0xF8, 0x72, 0x90, 0xE1, 0xE7, 0xD8, 0xF8, 0x90, 0x31, 0x94, 0xF8, 0x71, 0x00, 0x03, 0x21, 0xBD, 0xE8, 0xF0, 0x47, ++0x18, 0x47, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x90, 0xF8, 0xC0, 0x34, 0x63, 0xB1, 0x90, 0xF8, ++0xC1, 0x34, 0x06, 0x4A, 0x06, 0x48, 0x03, 0xEB, 0x83, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x00, 0xEB, 0x83, 0x00, 0xD2, 0xF8, ++0x18, 0x32, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0x42, 0x4E, 0x90, 0xF8, 0xC1, 0x84, 0xDD, 0xF8, 0x30, 0xC0, 0x8C, 0x24, 0x04, 0xFB, 0x08, 0x64, 0x94, 0xF8, 0x70, 0x70, ++0x01, 0x2F, 0x0F, 0xD1, 0x08, 0xEB, 0x88, 0x05, 0x94, 0xF8, 0x10, 0x90, 0xC5, 0xEB, 0xC5, 0x05, 0xA8, 0x00, 0x06, 0xEB, ++0x85, 0x05, 0xB9, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x94, 0xF8, 0x40, 0x40, 0x00, 0x2C, 0x64, 0xD0, 0x4F, 0xF0, 0xFF, 0x09, ++0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x28, 0x46, 0xCA, 0x46, 0x8C, 0x24, 0x4F, 0xEA, 0x4A, 0x07, 0x04, 0xFB, 0x08, 0xF4, ++0x07, 0xEB, 0x0A, 0x0B, 0x06, 0xEB, 0x04, 0x0E, 0x04, 0xEB, 0x0B, 0x14, 0x00, 0x29, 0x06, 0xEB, 0x04, 0x01, 0x9E, 0xF8, ++0x79, 0xB0, 0xCB, 0x74, 0x0B, 0x75, 0x0A, 0x9B, 0xCB, 0x61, 0x0B, 0xF1, 0x01, 0x0B, 0x0B, 0x9B, 0x8B, 0x61, 0x0C, 0xBF, ++0x01, 0x24, 0x00, 0x24, 0xC1, 0xF8, 0x24, 0xC0, 0x81, 0xF8, 0x21, 0x20, 0x81, 0xF8, 0x20, 0x40, 0x8E, 0xF8, 0x79, 0xB0, ++0x04, 0xD0, 0x9E, 0xF8, 0x7A, 0x30, 0x01, 0x33, 0x8E, 0xF8, 0x7A, 0x30, 0x0A, 0x9B, 0x73, 0xB1, 0x8C, 0x23, 0x07, 0xEB, ++0x0A, 0x02, 0x03, 0xFB, 0x08, 0xF3, 0x03, 0xEB, 0x02, 0x13, 0x33, 0x44, 0x0A, 0x99, 0x4F, 0xF0, 0x00, 0x42, 0xB2, 0xFB, ++0xF1, 0xF2, 0x01, 0x3A, 0x9A, 0x62, 0x15, 0x4C, 0x61, 0x46, 0xD4, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, ++0x08, 0xF8, 0x57, 0x44, 0x08, 0xEB, 0x07, 0x17, 0x37, 0x44, 0x46, 0x44, 0x01, 0x23, 0x96, 0xF8, 0x71, 0x00, 0x3B, 0x74, ++0x03, 0x21, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x47, 0x49, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0xA4, 0xFA, 0xD4, 0xF8, 0x1C, 0x32, ++0x28, 0x46, 0x98, 0x47, 0x28, 0x46, 0xD4, 0xF8, 0x18, 0x32, 0x98, 0x47, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x30, 0x30, ++0xB9, 0x46, 0x30, 0x44, 0xBA, 0x46, 0x9C, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x90, 0xF8, 0xC1, 0x64, 0x37, 0x4D, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0xF3, 0xE8, 0x18, 0x90, 0xF8, 0x70, 0x00, 0x01, 0x28, ++0x5C, 0xD1, 0x01, 0x29, 0x0C, 0x46, 0x57, 0xD8, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x01, 0x13, 0x2B, 0x44, 0x4F, 0xEA, ++0x44, 0x08, 0x19, 0x7C, 0x00, 0x29, 0x4D, 0xD0, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x48, 0xD0, 0x06, 0xEB, ++0x86, 0x07, 0x04, 0xEB, 0x44, 0x00, 0xDF, 0xF8, 0xA4, 0x90, 0xC7, 0xEB, 0xC7, 0x07, 0x00, 0x01, 0x00, 0xEB, 0x87, 0x00, ++0xD9, 0xF8, 0xD8, 0x31, 0x28, 0x44, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0xFA, 0xA0, 0x44, 0x0A, 0xEB, 0x08, 0x18, ++0xA8, 0x44, 0x00, 0x23, 0x05, 0xEB, 0x87, 0x07, 0x88, 0xF8, 0x10, 0x30, 0xD9, 0xF8, 0x1C, 0x22, 0x38, 0x46, 0x90, 0x47, ++0xD9, 0xF8, 0x18, 0x22, 0x38, 0x46, 0x90, 0x47, 0x05, 0xEB, 0x0A, 0x03, 0x98, 0xF8, 0x20, 0x10, 0x93, 0xF8, 0x79, 0x20, ++0x01, 0x3A, 0xD2, 0xB2, 0x01, 0x29, 0x83, 0xF8, 0x79, 0x20, 0x04, 0xD1, 0x93, 0xF8, 0x7A, 0x10, 0x01, 0x39, 0x83, 0xF8, ++0x7A, 0x10, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0x53, 0x93, 0xF8, 0x73, 0x10, 0x01, 0xB9, 0x92, 0xB1, 0x8C, 0x23, 0x03, 0xFB, ++0x06, 0x55, 0x03, 0x21, 0xD9, 0xF8, 0x90, 0x31, 0x95, 0xF8, 0x71, 0x00, 0x98, 0x47, 0x38, 0x46, 0x21, 0x46, 0xFF, 0xF7, ++0x29, 0xFA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xD9, 0xF8, 0x90, 0x21, 0x93, 0xF8, ++0x71, 0x00, 0x02, 0x21, 0x90, 0x47, 0xEE, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x1F, 0x4F, 0x90, 0xF8, 0xC1, 0x84, 0x8C, 0x25, 0x05, 0xFB, 0x08, 0x75, 0x08, 0xEB, 0x88, 0x03, 0x95, 0xF8, 0x20, 0x20, ++0xC3, 0xEB, 0xC3, 0x03, 0x0E, 0x46, 0x9C, 0x00, 0xAA, 0xB9, 0x2B, 0x7C, 0x9B, 0xB1, 0xE9, 0x68, 0xDF, 0xF8, 0x5C, 0x90, ++0x31, 0x44, 0xD9, 0xF8, 0xE0, 0x31, 0x38, 0x19, 0x98, 0x47, 0x95, 0xF8, 0x50, 0x30, 0x13, 0xB9, 0x95, 0xF8, 0x40, 0x30, ++0x6B, 0xB9, 0xD9, 0xF8, 0x1C, 0x32, 0x38, 0x19, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x95, 0xF8, 0x50, 0x30, 0xAB, 0xB9, ++0x95, 0xF8, 0x40, 0x30, 0x93, 0xB1, 0xDF, 0xF8, 0x2C, 0x90, 0x8C, 0x23, 0x03, 0xFB, 0x08, 0x73, 0x04, 0xF1, 0x30, 0x00, ++0xD9, 0x6B, 0xD9, 0xF8, 0xE0, 0x31, 0x38, 0x44, 0x31, 0x44, 0x98, 0x47, 0xD9, 0xF8, 0x1C, 0x32, 0x38, 0x19, 0xBD, 0xE8, ++0xF0, 0x47, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x87, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x0A, 0x4B, 0x8C, 0x22, ++0x02, 0xFB, 0x00, 0x33, 0x93, 0xF8, 0x71, 0x20, 0xFF, 0x2A, 0x0B, 0xD0, 0x93, 0xF8, 0x84, 0x00, 0x48, 0xB1, 0x93, 0xF8, ++0x88, 0x00, 0x00, 0xEB, 0x40, 0x03, 0x00, 0xEB, 0x83, 0x00, 0x0B, 0x30, 0xC0, 0xB2, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x48, 0x9E, 0x17, 0x00, 0x30, 0xB4, 0xDD, 0x23, 0x50, 0x25, 0x6F, 0x24, 0x9A, 0x21, 0x09, 0x22, 0x03, 0x70, 0x0C, 0x23, ++0x85, 0x70, 0xC4, 0x70, 0x01, 0x71, 0x42, 0x71, 0x83, 0x71, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x43, ++0x2D, 0x4E, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x63, 0x93, 0xF8, 0x78, 0x20, 0x4A, 0x72, 0x93, 0xF8, 0x73, 0x40, 0x01, 0x32, ++0x83, 0xF8, 0x78, 0x20, 0x00, 0x2C, 0x46, 0xD0, 0x64, 0xF0, 0x7F, 0x04, 0x8C, 0x72, 0x00, 0xEB, 0x80, 0x03, 0xC3, 0xEB, ++0xC3, 0x03, 0x4F, 0xF0, 0x8C, 0x0C, 0xDF, 0xF8, 0x8C, 0x90, 0xDF, 0xF8, 0x8C, 0x80, 0x06, 0xEB, 0x83, 0x03, 0x0C, 0xFB, ++0x00, 0x6C, 0x01, 0xF1, 0x0B, 0x02, 0x01, 0xF1, 0x25, 0x0E, 0x00, 0x24, 0x1D, 0x7C, 0xC5, 0xB1, 0x9C, 0xF8, 0x87, 0x50, ++0x15, 0xB1, 0x93, 0xF8, 0x21, 0x50, 0x55, 0xBB, 0x1D, 0x7D, 0x15, 0x70, 0xD3, 0xE9, 0x06, 0x57, 0xC2, 0xF8, 0x01, 0x50, ++0xC2, 0xF8, 0x05, 0x70, 0xD9, 0xF8, 0x00, 0x50, 0xD8, 0xF8, 0x10, 0x70, 0xED, 0x1B, 0x5F, 0x6A, 0x01, 0x34, 0x3D, 0x44, ++0xE4, 0xB2, 0xC2, 0xF8, 0x09, 0x50, 0x0D, 0x32, 0x72, 0x45, 0x03, 0xF1, 0x30, 0x03, 0xDF, 0xD1, 0x8C, 0x22, 0x04, 0xEB, ++0x44, 0x03, 0x04, 0xEB, 0x83, 0x03, 0x02, 0xFB, 0x00, 0x60, 0x03, 0xF1, 0x09, 0x02, 0x80, 0xF8, 0x88, 0x40, 0x02, 0x33, ++0x4A, 0x70, 0xA1, 0xF8, 0x07, 0x30, 0xBD, 0xE8, 0xF0, 0x83, 0x8C, 0x72, 0xB9, 0xE7, 0x93, 0xF8, 0x20, 0x50, 0x01, 0x2D, ++0xD0, 0xD1, 0xE2, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0xA4, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x02, 0x29, 0x20, 0xD0, ++0x03, 0x29, 0x0F, 0xD0, 0x01, 0x29, 0x06, 0xD0, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1E, 0xDB, ++0x70, 0x47, 0x13, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x80, 0xF8, 0x84, 0x10, 0x70, 0x47, 0x0F, 0x4B, 0x8C, 0x22, ++0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0x84, 0x30, 0x00, 0x2B, 0xEF, 0xD1, 0x0C, 0x4B, 0x90, 0xF8, 0x71, 0x00, 0xD3, 0xF8, ++0x90, 0x31, 0x01, 0x21, 0x18, 0x47, 0x08, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x00, 0x23, 0x80, 0xF8, 0x84, 0x30, ++0x70, 0x47, 0x06, 0x49, 0x06, 0x48, 0x4F, 0xF4, 0xEA, 0x62, 0x03, 0xF0, 0xA5, 0xBF, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x90, 0xF8, 0xC0, 0x34, ++0x33, 0xB1, 0x90, 0xF8, 0x64, 0x30, 0x1B, 0xB1, 0x43, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x43, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0x2D, 0xE9, 0xF0, 0x47, 0x36, 0x4F, 0x02, 0x7E, 0xDF, 0xF8, 0xE0, 0x80, 0x35, 0x49, 0xD8, 0xF8, 0xB0, 0x33, 0x0E, 0x69, ++0x05, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x70, 0x98, 0x47, 0xEB, 0x7E, 0x00, 0x2B, 0x3A, 0xD0, 0xD5, 0xE9, ++0x04, 0x43, 0x02, 0x2C, 0x8C, 0xBF, 0x01, 0x24, 0x00, 0x24, 0x02, 0x2B, 0x6B, 0x7E, 0x95, 0xF8, 0x18, 0xA0, 0x88, 0xBF, ++0x44, 0xF0, 0x02, 0x04, 0x63, 0x40, 0x9B, 0x07, 0x44, 0xD1, 0xD1, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x0A, 0x7A, ++0x6C, 0x76, 0xDA, 0xF8, 0xE4, 0x00, 0x18, 0xB3, 0xDF, 0xF8, 0x94, 0xC0, 0x4F, 0xF0, 0x00, 0x0E, 0x90, 0xF8, 0x23, 0x10, ++0x00, 0x68, 0x01, 0xEB, 0x41, 0x04, 0x64, 0x44, 0x4B, 0x00, 0x62, 0x78, 0xA4, 0x78, 0x02, 0x2A, 0x0B, 0x44, 0x88, 0xBF, ++0x01, 0x22, 0x0C, 0xEB, 0x03, 0x01, 0x98, 0xBF, 0x00, 0x22, 0x02, 0x2C, 0x88, 0xBF, 0x42, 0xF0, 0x02, 0x02, 0x0C, 0xF8, ++0x03, 0x20, 0x81, 0xF8, 0x01, 0xE0, 0x81, 0xF8, 0x02, 0xE0, 0x00, 0x28, 0xE2, 0xD1, 0x01, 0xE0, 0x95, 0xF8, 0x18, 0x90, ++0x11, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x77, 0x9B, 0x6A, 0x39, 0x6C, 0x00, 0x22, 0x5B, 0x1A, 0xC5, 0xE9, ++0x04, 0x22, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0x06, 0xF5, 0xC3, 0x31, 0xEB, 0x76, 0xD8, 0xF8, 0xE0, 0x31, 0x28, 0x46, ++0xA0, 0x31, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x21, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0xC4, 0xFC, 0x95, 0xF8, 0x18, 0x90, ++0xB4, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x60, 0x9F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x10, 0x4D, 0xDF, 0xF8, 0x44, 0x80, 0xC0, 0xEB, 0xC0, 0x03, 0x05, 0xEB, ++0x83, 0x03, 0xC0, 0xEB, 0xC0, 0x06, 0x9B, 0x7E, 0x04, 0x46, 0x05, 0xEB, 0x86, 0x06, 0xC7, 0x00, 0x1B, 0xB1, 0xD8, 0xF8, ++0xD8, 0x31, 0x30, 0x46, 0x98, 0x47, 0x3F, 0x1B, 0x05, 0xEB, 0x87, 0x05, 0x1C, 0x22, 0x00, 0x21, 0x30, 0x46, 0xDF, 0xF7, ++0x0F, 0xFA, 0xD8, 0xF8, 0x34, 0x33, 0xAE, 0x60, 0x2C, 0x76, 0x6B, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x80, 0x9F, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x00, 0x20, 0xFF, 0xF7, 0xD4, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0xD1, 0xFF, 0x02, 0x20, ++0xFF, 0xF7, 0xCE, 0xFF, 0x03, 0x20, 0xFF, 0xF7, 0xCB, 0xFF, 0x05, 0x4B, 0x00, 0x22, 0x03, 0xF1, 0x1E, 0x01, 0x5A, 0x70, ++0x9A, 0x70, 0x03, 0xF8, 0x03, 0x2B, 0x8B, 0x42, 0xF9, 0xD1, 0x08, 0xBD, 0x60, 0x9F, 0x17, 0x00, 0x0B, 0x4A, 0xC0, 0xEB, ++0xC0, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x99, 0x7E, 0x71, 0xB9, 0x30, 0xB4, 0x08, 0x49, 0x09, 0x4C, 0x09, 0x69, 0xD4, 0xF8, ++0xE0, 0x41, 0x01, 0x25, 0x01, 0xF5, 0xC3, 0x31, 0x9D, 0x76, 0x18, 0x46, 0xA0, 0x31, 0x23, 0x46, 0x30, 0xBC, 0x18, 0x47, ++0x70, 0x47, 0x00, 0xBF, 0x80, 0x9F, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x09, 0x29, 0x08, 0xB5, ++0x09, 0xD9, 0x6A, 0xBB, 0x21, 0x4B, 0xC0, 0xEB, 0xC0, 0x00, 0x03, 0xEB, 0x80, 0x00, 0x03, 0x69, 0x01, 0x33, 0x03, 0x61, ++0x08, 0xBD, 0x8A, 0xB1, 0x1C, 0x4B, 0x1D, 0x4A, 0xC0, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x80, 0x00, ++0x11, 0x44, 0x42, 0x69, 0x8B, 0x78, 0x01, 0x32, 0x02, 0x2B, 0x42, 0x61, 0xEE, 0xD8, 0x01, 0x33, 0x8B, 0x70, 0x08, 0xBD, ++0x13, 0x4B, 0x14, 0x4A, 0xC0, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x80, 0x00, 0x11, 0x44, 0x03, 0x69, ++0x4A, 0x78, 0x01, 0x33, 0x02, 0x2A, 0x03, 0x61, 0xDC, 0xD8, 0x01, 0x32, 0x4A, 0x70, 0x08, 0xBD, 0x0A, 0x4A, 0x0C, 0x4B, ++0x1C, 0x21, 0x01, 0xFB, 0x00, 0x20, 0x1A, 0x68, 0x43, 0x69, 0xB2, 0xF9, 0x00, 0x20, 0x01, 0x33, 0x00, 0x2A, 0x43, 0x61, ++0x05, 0xDA, 0x07, 0x49, 0x07, 0x48, 0x40, 0xF2, 0x69, 0x12, 0x03, 0xF0, 0x6F, 0xFE, 0x00, 0x23, 0x9B, 0x78, 0xFF, 0xDE, ++0x80, 0x9F, 0x17, 0x00, 0x60, 0x9F, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF8, 0xA3, 0x15, 0x00, ++0x70, 0xB5, 0x1E, 0x46, 0x0D, 0x46, 0x01, 0x23, 0x31, 0x46, 0x40, 0xF6, 0x01, 0x00, 0x01, 0xF0, 0x77, 0xFD, 0x04, 0x46, ++0x02, 0x20, 0x02, 0xF0, 0x15, 0xF8, 0x18, 0x4A, 0x18, 0x49, 0x03, 0x46, 0x04, 0x20, 0x03, 0xF0, 0x25, 0xFC, 0x02, 0x20, ++0x02, 0xF0, 0x0C, 0xF8, 0xA0, 0xB9, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x16, 0xDB, 0x13, 0x4A, ++0x00, 0x23, 0x23, 0x70, 0x28, 0x46, 0x15, 0x60, 0x93, 0x72, 0x16, 0x81, 0x01, 0x25, 0x00, 0xF0, 0x7D, 0xF9, 0x20, 0x46, ++0x01, 0xF0, 0x86, 0xFD, 0x28, 0x46, 0x70, 0xBD, 0x08, 0x23, 0x20, 0x46, 0x23, 0x70, 0x00, 0x25, 0x01, 0xF0, 0x7E, 0xFD, ++0x28, 0x46, 0x70, 0xBD, 0x95, 0xF8, 0x6F, 0x31, 0x00, 0x2B, 0xE4, 0xD1, 0x06, 0x49, 0x07, 0x48, 0x46, 0x22, 0x03, 0xF0, ++0x25, 0xFE, 0xDE, 0xE7, 0x84, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xF4, 0x9F, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x08, 0xA4, 0x15, 0x00, 0x17, 0x4A, 0x18, 0x4B, 0x12, 0x68, 0x70, 0xB5, 0xB2, 0xF9, 0x00, 0x20, ++0x1D, 0x68, 0x9C, 0x7A, 0x00, 0x2A, 0x19, 0xDB, 0x14, 0x4A, 0x15, 0x48, 0xD2, 0xE9, 0x00, 0x63, 0x04, 0xEB, 0x44, 0x04, ++0x05, 0xEB, 0x44, 0x04, 0x43, 0xF4, 0x08, 0x53, 0xE1, 0x78, 0x53, 0x60, 0x33, 0x43, 0x03, 0x60, 0xCB, 0x07, 0x03, 0xD4, ++0x0E, 0x4B, 0xD3, 0xF8, 0xEC, 0x32, 0x98, 0x47, 0x03, 0x21, 0x02, 0x20, 0x01, 0xF0, 0x0E, 0xFF, 0x00, 0x20, 0x70, 0xBD, ++0x02, 0x20, 0x01, 0xF0, 0xB1, 0xFF, 0x02, 0x28, 0xE0, 0xD0, 0x08, 0x49, 0x08, 0x48, 0x9C, 0x22, 0x03, 0xF0, 0xEA, 0xFD, ++0xDA, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xF4, 0x9F, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x1C, 0xA4, 0x15, 0x00, 0x38, 0xB5, 0x22, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x32, 0xDB, 0x20, 0x49, 0x20, 0x48, 0x21, 0x4C, 0xD1, 0xE9, 0x00, 0x32, 0x22, 0xF4, 0x08, 0x52, ++0x13, 0x43, 0x03, 0x60, 0xA3, 0x7A, 0x20, 0x68, 0x4A, 0x60, 0x90, 0xF8, 0x6F, 0x51, 0x01, 0x33, 0xDB, 0xB2, 0x9D, 0x42, ++0xA3, 0x72, 0x01, 0xD9, 0xE3, 0x7A, 0x93, 0xB1, 0x0C, 0x38, 0x01, 0xF0, 0x55, 0xFD, 0xE3, 0x7A, 0x8B, 0xB1, 0x16, 0x4B, ++0x21, 0x89, 0xD3, 0xF8, 0xF0, 0x32, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0xE3, 0x72, 0x00, 0x21, 0x02, 0x20, 0x01, 0xF0, ++0xC5, 0xFE, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xF0, 0x8D, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x21, 0x89, 0x02, 0x22, 0x40, 0xF6, ++0x02, 0x00, 0x01, 0xF0, 0x27, 0xFD, 0xEE, 0xE7, 0x02, 0x20, 0x01, 0xF0, 0x5D, 0xFF, 0x03, 0x28, 0xC7, 0xD0, 0x08, 0x49, ++0x08, 0x48, 0xC2, 0x22, 0x03, 0xF0, 0x96, 0xFD, 0xC1, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, ++0x60, 0x00, 0x32, 0x40, 0xF4, 0x9F, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x4C, 0xA4, 0x15, 0x00, ++0x38, 0xB5, 0x02, 0x20, 0x1D, 0x46, 0x01, 0xF0, 0x41, 0xFF, 0x0A, 0x4A, 0x0A, 0x49, 0x04, 0x46, 0x03, 0x46, 0x04, 0x20, ++0x03, 0xF0, 0x50, 0xFB, 0x24, 0xB1, 0x08, 0x4B, 0x01, 0x22, 0xDA, 0x72, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x4B, 0x29, 0x46, ++0xD3, 0xF8, 0xF0, 0x32, 0x01, 0x20, 0x98, 0x47, 0x00, 0x20, 0x38, 0xBD, 0x9C, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, ++0xF4, 0x9F, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x15, 0x4A, 0x03, 0x88, 0x11, 0x68, 0x40, 0xF6, 0x6C, 0x12, 0x93, 0x42, ++0x08, 0x69, 0x1F, 0xD0, 0x40, 0xF6, 0x85, 0x12, 0x93, 0x42, 0x1B, 0xD0, 0x40, 0xF6, 0x9E, 0x12, 0x93, 0x42, 0x17, 0xD0, ++0x40, 0xF6, 0xA8, 0x12, 0x93, 0x42, 0x13, 0xD0, 0x41, 0xF2, 0x3C, 0x42, 0x93, 0x42, 0x0F, 0xD0, 0x41, 0xF2, 0x64, 0x42, ++0x93, 0x42, 0x0B, 0xD0, 0x41, 0xF2, 0x85, 0x62, 0x93, 0x42, 0x07, 0xD0, 0x41, 0xF2, 0x99, 0x62, 0x93, 0x42, 0x03, 0xD0, ++0x41, 0xF2, 0xAD, 0x62, 0x93, 0x42, 0x02, 0xD1, 0x00, 0xF5, 0x9C, 0x40, 0x20, 0x30, 0x70, 0x47, 0xC8, 0x35, 0x17, 0x00, ++0x08, 0xB5, 0x0C, 0x22, 0x00, 0x21, 0x08, 0x48, 0xDF, 0xF7, 0x48, 0xF8, 0x00, 0x21, 0x02, 0x20, 0x01, 0xF0, 0x44, 0xFE, ++0x05, 0x4B, 0x06, 0x4A, 0x1A, 0x60, 0x03, 0xF1, 0x14, 0x01, 0x00, 0x22, 0x99, 0x60, 0x1A, 0x61, 0x5A, 0x60, 0x08, 0xBD, ++0xF4, 0x9F, 0x17, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xDE, 0xFA, 0xFE, 0xCA, 0x2D, 0xE9, 0xF0, 0x41, 0x2A, 0x4F, 0xBB, 0x7A, ++0x3E, 0x68, 0x03, 0xEB, 0x43, 0x03, 0x06, 0xEB, 0x43, 0x05, 0x82, 0xB0, 0x95, 0xF8, 0x03, 0x80, 0x18, 0xF0, 0x05, 0x0F, ++0x4F, 0xEA, 0x43, 0x04, 0x28, 0xD0, 0x24, 0x4B, 0x1B, 0x68, 0x5B, 0x69, 0x96, 0xF8, 0x6E, 0xC1, 0x95, 0xF9, 0x04, 0x20, ++0x31, 0x5B, 0xA8, 0x78, 0xCD, 0xE9, 0x00, 0x8C, 0xFC, 0xF7, 0x94, 0xFC, 0x7B, 0x68, 0x93, 0xB1, 0xAA, 0x78, 0x31, 0x5B, ++0xDA, 0xB9, 0xA1, 0xF6, 0x6C, 0x10, 0x48, 0x28, 0x0A, 0xD8, 0x40, 0xF6, 0xB4, 0x12, 0x91, 0x42, 0x28, 0xD0, 0x18, 0x48, ++0xA1, 0xF6, 0x67, 0x12, 0xA0, 0xFB, 0x02, 0x12, 0xC2, 0xF3, 0x87, 0x02, 0x9A, 0x70, 0x02, 0x21, 0x08, 0x46, 0x02, 0xB0, ++0xBD, 0xE8, 0xF0, 0x41, 0x01, 0xF0, 0xFA, 0xBD, 0x28, 0x46, 0xFF, 0xF7, 0x7B, 0xFF, 0x03, 0x46, 0xD4, 0xE7, 0x01, 0x2A, ++0x02, 0xD0, 0x00, 0x22, 0x9A, 0x70, 0xEE, 0xE7, 0xA1, 0xF5, 0x9C, 0x51, 0xA1, 0xF1, 0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, ++0x4D, 0x7F, 0xF4, 0xD8, 0x07, 0x4A, 0x08, 0x39, 0xA2, 0xFB, 0x01, 0x12, 0xC2, 0xF3, 0x87, 0x02, 0x9A, 0x70, 0xDE, 0xE7, ++0x0E, 0x22, 0x9A, 0x70, 0xDB, 0xE7, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, ++0x70, 0xB5, 0x0B, 0x4E, 0x0B, 0x4C, 0x33, 0x68, 0x05, 0x46, 0xB3, 0xF8, 0x6C, 0x11, 0x20, 0x46, 0x02, 0xF0, 0x7A, 0xFB, ++0x70, 0x60, 0xFF, 0xF7, 0x95, 0xFF, 0x54, 0xF8, 0x0C, 0x2C, 0xB5, 0xF8, 0x6C, 0x11, 0x01, 0x3A, 0x0A, 0x44, 0x00, 0x21, ++0x44, 0xE9, 0x02, 0x21, 0x70, 0xBD, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0xE8, 0x61, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0xDF, 0xF8, 0xD8, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x93, 0x06, 0x46, 0x93, 0xF8, 0xC0, 0x04, 0x93, 0xF8, ++0x6C, 0x50, 0x88, 0x46, 0x17, 0x46, 0x00, 0x28, 0x52, 0xD1, 0x1B, 0x6C, 0x18, 0x79, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, ++0x1A, 0x21, 0xEE, 0xF7, 0x75, 0xFE, 0x04, 0x46, 0x00, 0x28, 0x4E, 0xD0, 0x28, 0x4A, 0xDF, 0xF8, 0xA8, 0xE0, 0x4F, 0xF4, ++0x1E, 0x71, 0x01, 0xFB, 0x05, 0x21, 0xD0, 0xE9, 0x12, 0x3C, 0x0A, 0x46, 0xBE, 0xF8, 0xFC, 0x51, 0x52, 0xF8, 0x26, 0x0F, ++0xD8, 0x66, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x06, 0x99, 0x40, 0x20, 0x83, 0xF8, 0x68, 0x00, 0x90, 0x88, 0xA3, 0xF8, ++0x70, 0x00, 0xD9, 0xF8, 0x5C, 0x00, 0xB9, 0xF8, 0x60, 0x90, 0xC3, 0xF8, 0x72, 0x00, 0x01, 0x35, 0x90, 0x88, 0xA3, 0xF8, ++0x76, 0x90, 0xAD, 0xB2, 0xD2, 0xF8, 0x00, 0x90, 0xA3, 0xF8, 0x7C, 0x00, 0x00, 0x20, 0x83, 0xF8, 0x69, 0x00, 0x83, 0xF8, ++0x6A, 0x00, 0x83, 0xF8, 0x6B, 0x00, 0xC3, 0xF8, 0x78, 0x90, 0xAE, 0xF8, 0xFC, 0x51, 0x2D, 0x01, 0x83, 0xF8, 0x80, 0x00, ++0x83, 0xF8, 0x81, 0x00, 0xA3, 0xF8, 0x7E, 0x50, 0xCC, 0xF8, 0x20, 0x00, 0x26, 0x77, 0x91, 0xF8, 0x23, 0x30, 0x63, 0x77, ++0xC4, 0xE9, 0x15, 0x87, 0x20, 0x46, 0x05, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xEE, 0xF7, 0x3A, 0xBE, 0x01, 0x20, 0x1A, 0x21, ++0xEE, 0xF7, 0x26, 0xFE, 0x04, 0x46, 0x00, 0x28, 0xB0, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x52, 0x4B, 0x83, 0xB0, 0x1D, 0x68, 0x9B, 0x7A, ++0x01, 0x93, 0x95, 0xF8, 0x70, 0x31, 0x95, 0xF8, 0x6E, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0x8B, 0x80, 0x4D, 0x4B, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x08, 0x38, 0x08, 0xF1, 0x5C, 0x07, 0x05, 0xF1, 0xFD, 0x09, 0x00, 0x26, 0x98, 0xF8, 0xC0, 0x34, ++0x00, 0x2B, 0x7F, 0xD1, 0x01, 0x9B, 0x03, 0xEB, 0x43, 0x03, 0x05, 0xEB, 0x43, 0x03, 0x9B, 0x78, 0x00, 0x2B, 0x77, 0xD1, ++0x95, 0xF8, 0x71, 0x01, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x19, 0xF8, 0x01, 0x3C, 0xB5, 0xF8, 0x6C, 0x11, 0x1A, 0x33, ++0x19, 0x44, 0xEE, 0xF7, 0xE9, 0xFD, 0x4A, 0x46, 0x01, 0x46, 0x00, 0x28, 0x63, 0xD0, 0xD0, 0xE9, 0x12, 0x3C, 0x40, 0x24, ++0x00, 0x20, 0x83, 0xF8, 0x68, 0x40, 0x83, 0xF8, 0x69, 0x00, 0x83, 0xF8, 0x6A, 0x00, 0x83, 0xF8, 0x6B, 0x00, 0x95, 0xF8, ++0x60, 0x01, 0xC0, 0x07, 0x58, 0xD4, 0xD5, 0xF8, 0x60, 0x01, 0xB5, 0xF8, 0x64, 0x41, 0xA3, 0xF8, 0x70, 0x40, 0xD8, 0x66, ++0x05, 0xF5, 0xB0, 0x7A, 0xDF, 0xF8, 0xC0, 0xE0, 0x38, 0x68, 0xBE, 0xF8, 0xFC, 0x41, 0xB7, 0xF8, 0x04, 0xB0, 0xC3, 0xF8, ++0x72, 0x00, 0x01, 0x34, 0xDA, 0xF8, 0x00, 0x00, 0xBA, 0xF8, 0x04, 0xA0, 0xA3, 0xF8, 0x76, 0xB0, 0xA4, 0xB2, 0x4F, 0xF0, ++0x00, 0x0B, 0x98, 0x67, 0xA3, 0xF8, 0x7C, 0xA0, 0xAE, 0xF8, 0xFC, 0x41, 0x83, 0xF8, 0x80, 0xB0, 0x19, 0xF8, 0x01, 0x0C, ++0x83, 0xF8, 0x81, 0x00, 0x19, 0xF8, 0x01, 0x0C, 0x24, 0x01, 0xA3, 0xF8, 0x7E, 0x40, 0x40, 0xB1, 0x81, 0x33, 0x09, 0xEB, ++0x00, 0x04, 0x12, 0xF8, 0x01, 0x0B, 0x03, 0xF8, 0x01, 0x0F, 0xA2, 0x42, 0xF9, 0xD1, 0xB5, 0xF8, 0x6C, 0x21, 0xDC, 0xF8, ++0x28, 0x30, 0x16, 0x48, 0xCC, 0xF8, 0x20, 0x00, 0x9B, 0x1A, 0x00, 0x22, 0xCC, 0xF8, 0x28, 0x30, 0xC1, 0xE9, 0x15, 0x22, ++0x95, 0xF8, 0x6E, 0x31, 0x0B, 0x77, 0xFF, 0x23, 0x4B, 0x77, 0x08, 0x46, 0x05, 0x21, 0xEE, 0xF7, 0x99, 0xFD, 0x95, 0xF8, ++0x70, 0x31, 0x01, 0x36, 0xB3, 0x42, 0x09, 0xF1, 0x21, 0x09, 0x3F, 0xF7, 0x7F, 0xAF, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x01, 0x20, 0x8A, 0xE7, 0x07, 0x48, 0x04, 0x68, 0x80, 0x88, 0xDC, 0x66, 0xA3, 0xF8, 0x70, 0x00, 0x05, 0xF5, 0xB0, 0x7A, ++0xA6, 0xE7, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xAC, 0xB2, 0x15, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x38, 0xB5, 0x02, 0x22, 0x05, 0x46, 0x01, 0x23, 0x40, 0xF6, 0x04, 0x00, 0x01, 0xF0, 0x92, 0xFA, ++0x04, 0x46, 0x02, 0x20, 0x01, 0xF0, 0x30, 0xFD, 0x05, 0x4A, 0x06, 0x49, 0x03, 0x46, 0x04, 0x20, 0x03, 0xF0, 0x40, 0xF9, ++0x25, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0x38, 0x40, 0x01, 0xF0, 0xB2, 0xBA, 0xBC, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, ++0x03, 0x4A, 0x93, 0x7A, 0x10, 0x68, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x43, 0x00, 0x70, 0x47, 0xF4, 0x9F, 0x17, 0x00, ++0xC3, 0x78, 0x13, 0xF0, 0x05, 0x0F, 0x03, 0xD0, 0x02, 0x4B, 0x1B, 0x68, 0x58, 0x69, 0x70, 0x47, 0xFF, 0xF7, 0xE8, 0xBD, ++0xC8, 0x35, 0x17, 0x00, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDA, 0x0C, 0x4B, 0x1B, 0x68, ++0x1B, 0x07, 0x0D, 0xD1, 0x0B, 0x48, 0x0C, 0x49, 0x02, 0x68, 0x4B, 0x68, 0x22, 0xF0, 0x80, 0x02, 0x02, 0x60, 0x23, 0xF0, ++0x04, 0x03, 0x4F, 0xF0, 0x80, 0x60, 0x4B, 0x60, 0x01, 0xF0, 0x3C, 0xBE, 0x06, 0x49, 0x07, 0x48, 0x84, 0x22, 0x03, 0xF0, ++0xFB, 0xBA, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x5A, 0x4A, 0x5B, 0x49, 0x13, 0x68, 0xF0, 0xB4, 0x14, 0x68, 0x5A, 0x4E, ++0x5A, 0x4D, 0x24, 0xF0, 0xFF, 0x04, 0x04, 0x43, 0x14, 0x60, 0x14, 0x68, 0x17, 0x68, 0xC4, 0xF3, 0x09, 0x24, 0x27, 0xF4, ++0x7F, 0x37, 0xDB, 0xB2, 0x00, 0xFB, 0x04, 0xF4, 0x27, 0xF4, 0x40, 0x77, 0xB4, 0xFB, 0xF3, 0xF4, 0x01, 0xEA, 0x04, 0x24, ++0x3C, 0x43, 0x14, 0x60, 0x11, 0x68, 0x14, 0x68, 0xC1, 0xF3, 0x89, 0x41, 0x2C, 0x40, 0x00, 0xFB, 0x01, 0xF1, 0xB1, 0xFB, ++0xF3, 0xF1, 0x06, 0xEA, 0x81, 0x41, 0x21, 0x43, 0x11, 0x60, 0x11, 0x68, 0x49, 0x4E, 0x4A, 0x4C, 0x0D, 0x40, 0x45, 0xF0, ++0x89, 0x65, 0x15, 0x60, 0x32, 0x68, 0x35, 0x68, 0x47, 0x49, 0xC2, 0xF3, 0x0F, 0x22, 0x25, 0xF4, 0x7F, 0x05, 0x25, 0xF4, ++0x7F, 0x45, 0x00, 0xFB, 0x02, 0xF2, 0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x2A, 0x43, 0x32, 0x60, 0x0A, 0x68, ++0x0D, 0x68, 0x40, 0x4C, 0xC2, 0xF3, 0x09, 0x52, 0x25, 0xF0, 0x7F, 0x55, 0x00, 0xFB, 0x02, 0xF2, 0x25, 0xF4, 0x40, 0x15, ++0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x52, 0x2A, 0x43, 0x0A, 0x60, 0x0A, 0x68, 0x0C, 0x68, 0xC2, 0xF3, 0x09, 0x02, ++0x24, 0xF4, 0x7F, 0x74, 0x00, 0xFB, 0x02, 0xF2, 0x24, 0xF0, 0x03, 0x04, 0xB2, 0xFB, 0xF3, 0xF2, 0xC2, 0xF3, 0x09, 0x02, ++0x22, 0x43, 0x1D, 0x28, 0x0A, 0x60, 0x44, 0xD8, 0x4A, 0x68, 0x42, 0xF0, 0x03, 0x02, 0x4A, 0x60, 0x2E, 0x49, 0x2B, 0x4C, ++0x0A, 0x68, 0x2E, 0x4E, 0x0F, 0x68, 0x2E, 0x4D, 0xC2, 0xF3, 0x0F, 0x22, 0x37, 0x40, 0x00, 0xFB, 0x02, 0xF2, 0xB2, 0xFB, ++0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x3A, 0x43, 0x0A, 0x60, 0x2A, 0x68, 0x2F, 0x68, 0xC2, 0xF3, 0x0F, 0x22, 0x00, 0xFB, ++0x02, 0xF2, 0x3E, 0x40, 0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x32, 0x43, 0x2A, 0x60, 0x0A, 0x69, 0x0D, 0x69, ++0x1D, 0x4C, 0xC2, 0xF3, 0x09, 0x52, 0x25, 0xF0, 0x7F, 0x55, 0x00, 0xFB, 0x02, 0xF2, 0x25, 0xF4, 0x40, 0x15, 0xB2, 0xFB, ++0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x52, 0x2A, 0x43, 0x0A, 0x61, 0x0C, 0x69, 0x0A, 0x69, 0xC4, 0xF3, 0x09, 0x04, 0x22, 0xF4, ++0x7F, 0x72, 0x00, 0xFB, 0x04, 0xF0, 0x22, 0xF0, 0x03, 0x02, 0xB0, 0xFB, 0xF3, 0xF0, 0xC0, 0xF3, 0x09, 0x00, 0x10, 0x43, ++0xF0, 0xBC, 0x08, 0x61, 0x70, 0x47, 0x11, 0x49, 0x0A, 0x68, 0x3B, 0x28, 0x22, 0xF0, 0x03, 0x02, 0x94, 0xBF, 0x42, 0xF0, ++0x02, 0x02, 0x42, 0xF0, 0x01, 0x02, 0x0A, 0x60, 0xB2, 0xE7, 0x00, 0xBF, 0xE4, 0x00, 0x32, 0x40, 0x00, 0xFF, 0x03, 0x00, ++0x00, 0x00, 0xFC, 0x0F, 0xFF, 0xFF, 0x03, 0xF0, 0xE8, 0x00, 0x32, 0x40, 0x00, 0xFF, 0xFF, 0x00, 0xEC, 0x00, 0x32, 0x40, ++0x00, 0x00, 0xF0, 0x3F, 0xF4, 0x00, 0x32, 0x40, 0xFF, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x32, 0x40, 0xF0, 0x00, 0x32, 0x40, ++0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2C, 0xDB, 0xF0, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x18, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x18, 0x4B, 0x18, 0x49, 0x1B, 0x68, 0x0E, 0x68, 0x18, 0x4C, ++0x18, 0x4A, 0x19, 0x4D, 0x19, 0x4F, 0x03, 0xF5, 0xC3, 0x43, 0x28, 0x33, 0x70, 0x1C, 0x08, 0x60, 0x23, 0x60, 0x17, 0x4C, ++0x80, 0x23, 0x13, 0x60, 0x2A, 0x68, 0x63, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x43, 0xF0, 0x04, 0x03, 0x2A, 0x60, 0x63, 0x60, ++0x00, 0x23, 0x3B, 0x60, 0x28, 0xB1, 0x09, 0x4B, 0x0E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, ++0x70, 0x47, 0x0B, 0x4B, 0x1B, 0x68, 0x1A, 0x07, 0xCE, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0xD9, 0x22, 0x03, 0xF0, 0xE4, 0xB9, ++0x38, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x44, 0x01, 0x32, 0x40, ++0x88, 0x80, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xD4, 0xA4, 0x15, 0x00, 0x03, 0x4A, 0x01, 0x23, 0x13, 0x60, 0x13, 0x68, 0x13, 0xF0, 0xFF, 0x0F, 0xFB, 0xD1, 0x70, 0x47, ++0x50, 0x80, 0x32, 0x40, 0x70, 0xB5, 0x76, 0x4A, 0x01, 0x23, 0x82, 0xB0, 0x13, 0x60, 0x13, 0x68, 0x13, 0xF0, 0xFF, 0x0F, ++0xFB, 0xD1, 0x73, 0x4B, 0xD3, 0xF8, 0xF0, 0x40, 0xDE, 0xF7, 0x66, 0xFF, 0xA0, 0x47, 0x71, 0x4B, 0x71, 0x49, 0x72, 0x4A, ++0x19, 0x60, 0x13, 0x68, 0x71, 0x49, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x0B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x86, 0x80, 0x6D, 0x48, 0x6E, 0x4B, 0x6A, 0x49, 0x6E, 0x4C, 0x6E, 0x4A, 0x04, 0x60, 0x1A, 0x60, 0x0A, 0x68, ++0x6D, 0x4C, 0x6E, 0x4D, 0x42, 0xF0, 0x80, 0x62, 0x42, 0xF4, 0xF8, 0x62, 0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x62, ++0x0A, 0x60, 0x50, 0xF8, 0x84, 0x2C, 0x69, 0x49, 0xA3, 0xF5, 0x00, 0x43, 0x1C, 0x3B, 0x42, 0xF4, 0x80, 0x32, 0x40, 0xF8, ++0x84, 0x2C, 0x25, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x7F, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x02, 0x1A, 0x60, ++0x1A, 0x68, 0x22, 0xF4, 0xFE, 0x02, 0x42, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x8A, 0x78, 0x2A, 0xB9, 0x1A, 0x68, 0x12, 0x0C, ++0x12, 0x04, 0x42, 0xF0, 0x64, 0x02, 0x1A, 0x60, 0x5A, 0x4B, 0x5B, 0x49, 0x50, 0x4C, 0x5B, 0x4E, 0x5B, 0x4D, 0x00, 0x22, ++0x4F, 0xF4, 0x40, 0x50, 0x08, 0x60, 0x1A, 0x60, 0x0D, 0xF1, 0x06, 0x01, 0x0D, 0xF1, 0x07, 0x00, 0xE0, 0xF7, 0x1C, 0xF9, ++0x9D, 0xF8, 0x07, 0x20, 0x9D, 0xF8, 0x06, 0x00, 0x54, 0x49, 0x13, 0x02, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x43, 0x0B, 0x60, ++0x23, 0x68, 0x52, 0x4A, 0x43, 0xF4, 0x80, 0x53, 0x23, 0x60, 0x23, 0x68, 0x41, 0xF6, 0x25, 0x40, 0x43, 0xF4, 0x00, 0x53, ++0x23, 0x60, 0xC1, 0xF8, 0x70, 0x04, 0x13, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x13, 0x60, 0xDF, 0xF7, 0x77, 0xFD, 0x32, 0x68, ++0x49, 0x49, 0x43, 0x1C, 0x9B, 0x06, 0x22, 0xF0, 0xE0, 0x52, 0x03, 0xF0, 0xE0, 0x53, 0x13, 0x43, 0x33, 0x60, 0x23, 0x68, ++0x45, 0x4A, 0x43, 0xF0, 0x20, 0x03, 0x23, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, ++0x02, 0x03, 0x13, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x23, 0x60, 0x2B, 0x68, 0x99, 0x03, 0x13, 0xD4, 0x3D, 0x4A, ++0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x2A, 0x4B, 0x1B, 0x68, 0xB3, 0xF1, 0xC8, 0x5F, ++0xBF, 0xF4, 0x74, 0xAF, 0x37, 0x49, 0x38, 0x48, 0x40, 0xF2, 0x21, 0x12, 0x03, 0xF0, 0x46, 0xF9, 0x6C, 0xE7, 0xDF, 0xF7, ++0x05, 0xFD, 0x00, 0x28, 0xE7, 0xD0, 0xDF, 0xF7, 0x35, 0xFD, 0x33, 0x4E, 0x32, 0x68, 0x00, 0x02, 0x00, 0xF4, 0xE0, 0x63, ++0x22, 0xF4, 0xE0, 0x62, 0x13, 0x43, 0x33, 0x60, 0x33, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0x33, 0x60, ++0x33, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x33, 0x60, 0x33, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x2B, 0x68, 0x1B, 0x04, ++0x0D, 0xD4, 0x1E, 0x4B, 0x1B, 0x68, 0x9A, 0x03, 0xC7, 0xD5, 0xDF, 0xF7, 0xE9, 0xFC, 0x00, 0x28, 0xC3, 0xD0, 0x22, 0x4A, ++0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE7, 0xDF, 0xF7, 0xB1, 0xFC, 0x00, 0x28, 0xED, 0xD0, 0x23, 0x68, ++0x43, 0xF4, 0x00, 0x23, 0x23, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, 0x80, 0x63, 0x33, 0x60, 0xE2, 0xE7, ++0x50, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0x4C, 0x00, 0x32, 0x40, ++0x38, 0x36, 0x17, 0x00, 0xD8, 0x00, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x10, 0x19, 0x04, 0x00, 0xC0, 0x07, 0xF9, 0x80, ++0x60, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x3C, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, 0x58, 0x01, 0x32, 0x40, ++0x9C, 0x00, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, 0xA0, 0x00, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x00, 0x04, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0x40, 0x88, 0x15, 0x00, 0x50, 0x03, 0x32, 0x40, ++0x05, 0x49, 0x06, 0x4A, 0x0B, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, ++0x70, 0x47, 0x00, 0xBF, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x1D, 0x4A, 0x1E, 0x49, 0x13, 0x68, 0x1E, 0x48, ++0x30, 0xB4, 0x23, 0xF0, 0x80, 0x03, 0x00, 0x25, 0x3C, 0x24, 0x13, 0x60, 0x0D, 0x60, 0x0A, 0x46, 0x04, 0x60, 0x13, 0x68, ++0x1B, 0x07, 0xFC, 0xD1, 0x17, 0x4A, 0x18, 0x49, 0x13, 0x68, 0x18, 0x4D, 0x18, 0x48, 0x19, 0x4C, 0x43, 0xF4, 0x80, 0x33, ++0x13, 0x60, 0x0B, 0x68, 0x02, 0xF5, 0x00, 0x42, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x60, 0x20, 0x32, 0x4F, 0xF0, 0xFF, 0x33, ++0x2B, 0x60, 0x04, 0x60, 0x13, 0x68, 0x12, 0x4C, 0x12, 0x49, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x22, 0x68, 0x4B, 0x68, ++0xA0, 0xF5, 0x00, 0x40, 0x24, 0x38, 0x42, 0xF0, 0x00, 0x42, 0x22, 0x60, 0x02, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x42, 0xF0, ++0x80, 0x02, 0x02, 0x60, 0x30, 0xBC, 0x4B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x38, 0x00, 0x32, 0x40, ++0x54, 0x00, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x7C, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x44, 0xF1, 0x73, 0x0B, ++0x80, 0x80, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x0B, 0x49, 0x0C, 0x4A, 0x0C, 0x4B, 0x10, 0xB4, 0x04, 0x68, 0x80, 0x88, ++0x0C, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x10, 0x60, 0x1A, 0x46, 0x19, 0x60, 0x10, 0x68, 0x81, 0x00, 0xFC, 0xD4, 0xC3, 0x00, ++0x5D, 0xBF, 0x00, 0x0C, 0x10, 0x38, 0xC0, 0xB2, 0xFF, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xBC, 0x00, 0x32, 0x40, ++0xC0, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, 0x38, 0xB5, 0x11, 0x4B, 0x11, 0x48, 0x19, 0x68, 0x42, 0x68, 0x11, 0x4C, ++0x11, 0x4D, 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x23, 0x68, 0x0E, 0x49, ++0x43, 0xF4, 0xE0, 0x63, 0x2A, 0x43, 0x23, 0x60, 0x05, 0x60, 0x01, 0x20, 0x0A, 0x60, 0xF3, 0xF7, 0x51, 0xFB, 0x23, 0x68, ++0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x23, 0x68, 0x43, 0xF4, 0x00, 0x53, 0x23, 0x60, 0x38, 0xBD, ++0x74, 0x80, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x60, 0x00, 0x32, 0x40, ++0x80, 0xEA, 0xE0, 0x72, 0xF0, 0xB4, 0xA2, 0xEB, 0xE0, 0x72, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x16, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x16, 0x4D, 0x16, 0x4B, 0x2E, 0x68, 0x1B, 0x68, 0x16, 0x49, 0x77, 0x1C, 0x00, 0x28, ++0x09, 0x68, 0x2F, 0x60, 0x43, 0xF0, 0x80, 0x73, 0x15, 0xDD, 0x8A, 0x42, 0x18, 0xD8, 0x11, 0x49, 0x0F, 0x4C, 0x0A, 0x68, ++0x10, 0x1A, 0x08, 0x60, 0x23, 0x60, 0x08, 0x60, 0x23, 0x60, 0x08, 0x60, 0x00, 0x20, 0x23, 0x60, 0x2F, 0xB1, 0x08, 0x4B, ++0x2E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, 0x70, 0x47, 0xEA, 0xD0, 0xC9, 0x43, 0x20, 0x32, ++0x91, 0x42, 0xE6, 0xD2, 0x4F, 0xF0, 0xFF, 0x30, 0xEE, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x4C, 0x00, 0x32, 0x40, 0xA4, 0x80, 0x32, 0x40, 0x35, 0x4B, 0x1B, 0x68, 0x70, 0xB5, 0xC3, 0xF3, 0x40, 0x64, 0x9B, 0x01, ++0x12, 0xD4, 0x33, 0x49, 0x33, 0x48, 0x0B, 0x69, 0x33, 0x4A, 0x05, 0x68, 0x08, 0x69, 0xB2, 0xF8, 0xB0, 0x10, 0xB2, 0xF8, ++0xB2, 0x20, 0xA3, 0xF5, 0xFA, 0x63, 0x03, 0xEB, 0x45, 0x13, 0x1B, 0x1A, 0x5B, 0x1A, 0x9B, 0x1A, 0x00, 0x2B, 0x17, 0xDB, ++0x2C, 0x4B, 0x1D, 0x68, 0x9D, 0xB1, 0x28, 0x48, 0x29, 0x4E, 0xEA, 0x68, 0x03, 0x69, 0xB6, 0xF8, 0xB0, 0x40, 0xB6, 0xF8, ++0xB2, 0x10, 0xD3, 0x1A, 0xA3, 0xF5, 0xFA, 0x63, 0x1B, 0x1B, 0x5B, 0x1A, 0x00, 0x2B, 0x07, 0xDB, 0x24, 0x4B, 0x1B, 0x68, ++0x1C, 0x78, 0x01, 0x2C, 0x0B, 0xD0, 0x01, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x12, 0xDB, 0x00, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x18, 0xDB, 0x15, 0x4B, 0x52, 0x1A, 0x4F, 0xF4, 0x80, 0x20, 0x04, 0x21, 0x98, 0x60, 0x1A, 0x63, 0x20, 0x46, 0x99, 0x60, ++0x70, 0xBD, 0x03, 0x69, 0xD2, 0x1A, 0x02, 0xF5, 0x9C, 0x52, 0x08, 0x32, 0x00, 0x2A, 0xE5, 0xDA, 0x12, 0x49, 0x13, 0x48, ++0x40, 0xF2, 0x3E, 0x22, 0x02, 0xF0, 0x92, 0xFF, 0x00, 0x24, 0xD5, 0xE7, 0x03, 0x69, 0xD3, 0x1A, 0x5B, 0x1A, 0x00, 0x2B, ++0xE1, 0xDA, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF2, 0x43, 0x22, 0x02, 0xF0, 0x85, 0xFF, 0xEA, 0x68, 0xB6, 0xF8, 0xB2, 0x10, ++0xD7, 0xE7, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x40, 0x80, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0xD0, 0x9C, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0xA4, 0x15, 0x00, ++0x80, 0x8D, 0x15, 0x00, 0x70, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x0B, 0x4B, 0x0B, 0x49, 0x0C, 0x4D, 0x0E, 0x68, 0x1A, 0x68, 0x28, 0x68, 0x09, 0x68, 0x54, 0x1C, 0xB1, 0x42, ++0x18, 0xBF, 0x28, 0x68, 0x1C, 0x60, 0x2C, 0xB1, 0x03, 0x4C, 0x1A, 0x60, 0x23, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, ++0x70, 0xBC, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x80, 0x32, 0x40, 0xA4, 0x80, 0x32, 0x40, ++0x3B, 0x4A, 0x3C, 0x4B, 0x10, 0xB5, 0x14, 0x68, 0x1C, 0x60, 0x61, 0x05, 0x1D, 0xD4, 0xE2, 0x05, 0x16, 0xD4, 0xA3, 0x05, ++0x10, 0xD4, 0xE0, 0x06, 0x31, 0xD4, 0x37, 0x4B, 0x1A, 0x78, 0x22, 0xB1, 0x14, 0xF0, 0x2F, 0x0F, 0x1C, 0xBF, 0x01, 0x22, ++0x9A, 0x71, 0x34, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0D, 0xDB, 0x10, 0xBD, 0x31, 0x48, 0x02, 0xF0, ++0xAD, 0xFC, 0xFE, 0xE7, 0xF2, 0xF7, 0x96, 0xFD, 0xA3, 0x05, 0xE6, 0xD5, 0xF6, 0xE7, 0x2E, 0x48, 0x02, 0xF0, 0xA4, 0xFC, ++0xFE, 0xE7, 0xE1, 0x07, 0x1C, 0xD4, 0xA2, 0x07, 0x42, 0xD4, 0x63, 0x07, 0x38, 0xD4, 0x20, 0x07, 0x2E, 0xD4, 0x21, 0x06, ++0x24, 0xD4, 0x62, 0x06, 0x1A, 0xD4, 0xA3, 0x06, 0xE3, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x25, 0x49, 0x25, 0x48, 0x40, 0xF2, ++0xB5, 0x22, 0x02, 0xF0, 0xD5, 0xBE, 0x04, 0x20, 0xEC, 0xF7, 0xA4, 0xFD, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xEC, 0xF7, ++0x3F, 0xFE, 0xC4, 0xE7, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0x2B, 0x72, 0x02, 0xF0, 0xC4, 0xBE, ++0xBD, 0xE8, 0x10, 0x40, 0x18, 0x49, 0x1B, 0x48, 0x40, 0xF2, 0xB3, 0x22, 0x02, 0xF0, 0xBC, 0xBE, 0xBD, 0xE8, 0x10, 0x40, ++0x14, 0x49, 0x18, 0x48, 0x40, 0xF2, 0xB1, 0x22, 0x02, 0xF0, 0xB4, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x10, 0x49, 0x15, 0x48, ++0x40, 0xF2, 0xAF, 0x22, 0x02, 0xF0, 0xAC, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x49, 0x12, 0x48, 0x40, 0xF2, 0xAE, 0x22, ++0x02, 0xF0, 0xA4, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x49, 0x0F, 0x48, 0x40, 0xF2, 0xAD, 0x22, 0x02, 0xF0, 0x9C, 0xBE, ++0x84, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x80, 0x35, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x5C, 0xA5, 0x15, 0x00, ++0x28, 0xA5, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x80, 0xA6, 0x15, 0x00, 0x90, 0xA5, 0x15, 0x00, 0x58, 0xA6, 0x15, 0x00, ++0x30, 0xA6, 0x15, 0x00, 0x08, 0xA6, 0x15, 0x00, 0xE0, 0xA5, 0x15, 0x00, 0xB8, 0xA5, 0x15, 0x00, 0x38, 0xB5, 0x62, 0x4A, ++0x62, 0x4B, 0x11, 0x68, 0x1C, 0x68, 0x62, 0x4B, 0x0C, 0x40, 0x23, 0x40, 0x54, 0x60, 0x00, 0x2B, 0x54, 0xD1, 0x60, 0x4B, ++0x23, 0x40, 0x00, 0x2B, 0x4B, 0xD1, 0x62, 0x07, 0x03, 0xD5, 0x5E, 0x4B, 0xD3, 0xF8, 0xDC, 0x30, 0x98, 0x47, 0x23, 0x07, ++0x03, 0xD5, 0x5B, 0x4B, 0xD3, 0xF8, 0xD4, 0x30, 0x98, 0x47, 0xE5, 0x00, 0x2E, 0xD4, 0xE0, 0x05, 0x28, 0xD4, 0x58, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x38, 0xBD, 0x61, 0x02, 0x3C, 0xD4, 0xA2, 0x02, 0x42, 0xD4, ++0x63, 0x06, 0x48, 0xD4, 0xE5, 0x04, 0x4E, 0xD4, 0xA0, 0x04, 0x54, 0xD4, 0x61, 0x04, 0x5A, 0xD4, 0x22, 0x04, 0x60, 0xD4, ++0xE3, 0x03, 0x66, 0xD4, 0xA5, 0x03, 0x6C, 0xD4, 0xE0, 0x01, 0x72, 0xD4, 0xA1, 0x01, 0x78, 0xD4, 0xE2, 0x02, 0x7E, 0xD4, ++0x23, 0x01, 0xE4, 0xD5, 0xBD, 0xE8, 0x38, 0x40, 0x47, 0x49, 0x48, 0x48, 0x40, 0xF2, 0x19, 0x32, 0x02, 0xF0, 0x38, 0xBE, ++0x46, 0x48, 0x02, 0xF0, 0xED, 0xFB, 0xD2, 0xE7, 0x45, 0x4B, 0x46, 0x4A, 0x1D, 0x68, 0x93, 0x7F, 0x05, 0xF0, 0x3F, 0x01, ++0x0B, 0x43, 0x4F, 0xF4, 0x00, 0x20, 0x93, 0x77, 0x01, 0xF0, 0x64, 0xF9, 0x41, 0x4B, 0x1D, 0x60, 0xC1, 0xE7, 0x4F, 0xF0, ++0x80, 0x70, 0x01, 0xF0, 0x5D, 0xF9, 0xAE, 0xE7, 0x4F, 0xF0, 0x00, 0x70, 0x01, 0xF0, 0x58, 0xF9, 0xA5, 0xE7, 0xBD, 0xE8, ++0x38, 0x40, 0x35, 0x49, 0x3A, 0x48, 0x40, 0xF2, 0x0B, 0x32, 0x02, 0xF0, 0x13, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x31, 0x49, ++0x37, 0x48, 0x4F, 0xF4, 0x43, 0x72, 0x02, 0xF0, 0x0B, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x2D, 0x49, 0x34, 0x48, 0x40, 0xF2, ++0x0D, 0x32, 0x02, 0xF0, 0x03, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x29, 0x49, 0x31, 0x48, 0x4F, 0xF4, 0x44, 0x72, 0x02, 0xF0, ++0xFB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x25, 0x49, 0x2E, 0x48, 0x40, 0xF2, 0x11, 0x32, 0x02, 0xF0, 0xF3, 0xBD, 0xBD, 0xE8, ++0x38, 0x40, 0x21, 0x49, 0x2B, 0x48, 0x40, 0xF2, 0x12, 0x32, 0x02, 0xF0, 0xEB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x1D, 0x49, ++0x28, 0x48, 0x40, 0xF2, 0x13, 0x32, 0x02, 0xF0, 0xE3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x19, 0x49, 0x25, 0x48, 0x4F, 0xF4, ++0x45, 0x72, 0x02, 0xF0, 0xDB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x15, 0x49, 0x22, 0x48, 0x40, 0xF2, 0x15, 0x32, 0x02, 0xF0, ++0xD3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x11, 0x49, 0x1F, 0x48, 0x40, 0xF2, 0x16, 0x32, 0x02, 0xF0, 0xCB, 0xBD, 0xBD, 0xE8, ++0x38, 0x40, 0x0D, 0x49, 0x1C, 0x48, 0x40, 0xF2, 0x17, 0x32, 0x02, 0xF0, 0xC3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x09, 0x49, ++0x19, 0x48, 0x4F, 0xF4, 0x46, 0x72, 0x02, 0xF0, 0xBB, 0xBD, 0x00, 0xBF, 0x6C, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, ++0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x08, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x10, 0xA9, 0x15, 0x00, 0xA8, 0xA6, 0x15, 0x00, 0x90, 0x80, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x94, 0x80, 0x32, 0x40, ++0xD8, 0xA6, 0x15, 0x00, 0x00, 0xA7, 0x15, 0x00, 0x34, 0xA7, 0x15, 0x00, 0x68, 0xA7, 0x15, 0x00, 0x90, 0xA7, 0x15, 0x00, ++0xC0, 0xA7, 0x15, 0x00, 0xF0, 0xA7, 0x15, 0x00, 0x20, 0xA8, 0x15, 0x00, 0x50, 0xA8, 0x15, 0x00, 0x80, 0xA8, 0x15, 0x00, ++0xB4, 0xA8, 0x15, 0x00, 0xE8, 0xA8, 0x15, 0x00, 0x10, 0xB5, 0x18, 0x4B, 0x84, 0xB0, 0xD3, 0xF8, 0x20, 0x32, 0x8D, 0xF8, ++0x07, 0x00, 0x0D, 0xF1, 0x0F, 0x02, 0x0D, 0xF1, 0x0E, 0x01, 0x0D, 0xF1, 0x07, 0x00, 0x98, 0x47, 0x12, 0x4A, 0x13, 0x49, ++0x13, 0x68, 0x9D, 0xF8, 0x0E, 0x40, 0x91, 0xF8, 0xBA, 0x00, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x04, 0x23, 0x13, 0x60, ++0x18, 0xB1, 0x0E, 0x4B, 0x93, 0xF8, 0x2A, 0x30, 0x4B, 0xB1, 0x0A, 0x4A, 0x9D, 0xF8, 0x0F, 0x10, 0x13, 0x68, 0x23, 0xF0, ++0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x04, 0xB0, 0x10, 0xBD, 0x13, 0x68, 0x91, 0xF8, 0xBB, 0x10, 0x23, 0xF0, 0xFF, 0x03, ++0x0B, 0x43, 0x13, 0x60, 0x04, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, ++0xBC, 0x34, 0x17, 0x00, 0x30, 0xB5, 0x90, 0xF9, 0x65, 0x50, 0x7F, 0x2D, 0x83, 0xB0, 0x0E, 0xD0, 0x90, 0xF9, 0x66, 0x30, ++0x0B, 0x48, 0x9D, 0x42, 0xA8, 0xBF, 0x1D, 0x46, 0x8D, 0xF8, 0x07, 0x50, 0xD0, 0xF8, 0x20, 0x32, 0x0D, 0xF1, 0x07, 0x00, ++0x98, 0x47, 0x03, 0xB0, 0x30, 0xBD, 0x0C, 0x46, 0x05, 0x49, 0x13, 0x46, 0x0A, 0x68, 0x12, 0x0A, 0x22, 0x70, 0x0A, 0x68, ++0x1A, 0x70, 0x03, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x91, 0xF9, 0x00, 0x30, ++0x7F, 0x2B, 0x40, 0xD0, 0xF0, 0xB5, 0x20, 0x4E, 0x90, 0xF9, 0x65, 0x70, 0xD6, 0xF8, 0x20, 0x32, 0x85, 0xB0, 0x0C, 0x46, ++0x05, 0x46, 0x11, 0x46, 0x20, 0x46, 0x0D, 0xF1, 0x0F, 0x02, 0x01, 0x91, 0x98, 0x47, 0x94, 0xF9, 0x00, 0x30, 0x95, 0xF9, ++0x66, 0x20, 0x85, 0xF8, 0x65, 0x30, 0x93, 0x42, 0x20, 0xDC, 0x94, 0xF9, 0x00, 0x30, 0xBB, 0x42, 0x1A, 0xD0, 0xD5, 0xF8, ++0xE4, 0x30, 0x43, 0xB1, 0x93, 0xF8, 0x56, 0x21, 0x42, 0xF0, 0x10, 0x02, 0x83, 0xF8, 0x56, 0x21, 0x1B, 0x68, 0x00, 0x2B, ++0xF6, 0xD1, 0x28, 0x6C, 0x60, 0xB1, 0xD6, 0xF8, 0xB4, 0x30, 0x98, 0x47, 0x28, 0x46, 0xFC, 0xF7, 0x5D, 0xFC, 0x28, 0xB1, ++0x2A, 0x6C, 0xD6, 0xF8, 0x3C, 0x33, 0x92, 0xF9, 0x0C, 0x00, 0x98, 0x47, 0x05, 0xB0, 0xF0, 0xBD, 0x22, 0x70, 0x01, 0x99, ++0xD6, 0xF8, 0x20, 0x32, 0x0D, 0xF1, 0x0F, 0x02, 0x20, 0x46, 0x98, 0x47, 0xD5, 0xE7, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0x10, 0xB5, 0x15, 0x4B, 0x82, 0xB0, 0x0C, 0x46, 0xD3, 0xF8, 0x38, 0x33, 0x0D, 0xF1, 0x07, 0x02, 0x0D, 0xF1, 0x06, 0x01, ++0x98, 0x47, 0xE2, 0x6C, 0x10, 0x4B, 0x94, 0x6B, 0x93, 0xF8, 0xBD, 0x30, 0x61, 0x69, 0xC1, 0xF3, 0xC2, 0x20, 0xC9, 0xB2, ++0x6B, 0xB9, 0x01, 0xF0, 0x7C, 0x01, 0x50, 0xEA, 0x01, 0x03, 0x0C, 0xBF, 0x9D, 0xF8, 0x06, 0x30, 0x9D, 0xF8, 0x07, 0x30, ++0x43, 0xEA, 0x03, 0x23, 0x63, 0x62, 0x02, 0xB0, 0x10, 0xBD, 0x01, 0xF0, 0x7F, 0x01, 0xDF, 0xF7, 0xB1, 0xFA, 0x40, 0xEA, ++0x00, 0x20, 0x60, 0x62, 0x02, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x00, 0x29, 0x11, 0xDD, ++0x10, 0xB4, 0x01, 0x39, 0x00, 0x23, 0x01, 0x24, 0x10, 0xF0, 0x01, 0x0F, 0x1C, 0xBF, 0x04, 0xFA, 0x01, 0xF2, 0x13, 0x43, ++0x01, 0x39, 0x4F, 0xEA, 0x50, 0x00, 0xF5, 0xD2, 0x18, 0x46, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x23, 0x18, 0x46, ++0x70, 0x47, 0x00, 0xBF, 0x0B, 0x1F, 0x03, 0x44, 0x01, 0x44, 0x03, 0xF8, 0x01, 0x2B, 0x8B, 0x42, 0x4F, 0xEA, 0x12, 0x22, ++0xF9, 0xD1, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x8D, 0x88, 0x0C, 0x7D, 0x00, 0x95, 0x0D, 0x68, 0x01, 0x95, ++0x03, 0x93, 0x1C, 0xB1, 0x0B, 0x69, 0xAB, 0x42, 0x00, 0xF0, 0xAC, 0x81, 0x01, 0x9B, 0xD9, 0x4F, 0x9C, 0xB2, 0x4F, 0xEA, ++0x13, 0x4C, 0xCC, 0x80, 0xA1, 0xF8, 0x08, 0xC0, 0x53, 0x78, 0x16, 0x78, 0x46, 0xEA, 0x03, 0x26, 0x4E, 0x81, 0xD3, 0x78, ++0x95, 0x78, 0x45, 0xEA, 0x03, 0x25, 0x8D, 0x81, 0x92, 0xF8, 0x05, 0xE0, 0x13, 0x79, 0x43, 0xEA, 0x0E, 0x23, 0xCB, 0x81, ++0x4F, 0xF0, 0x00, 0x09, 0x09, 0xF0, 0x01, 0x0A, 0x00, 0xEB, 0x4A, 0x02, 0x10, 0xF8, 0x1A, 0x80, 0x92, 0xF8, 0x01, 0xE0, ++0x02, 0x92, 0x48, 0xEA, 0x0E, 0x22, 0x5A, 0x40, 0x4F, 0xEA, 0x12, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, ++0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x4F, 0xEA, 0x4A, 0x08, 0x14, 0x44, ++0x08, 0xF1, 0x04, 0x02, 0xA4, 0xB2, 0x00, 0xEB, 0x02, 0x0E, 0xCC, 0x80, 0x82, 0x5C, 0x9E, 0xF8, 0x01, 0xE0, 0x42, 0xEA, ++0x0E, 0x2E, 0x84, 0xEA, 0x0E, 0x0E, 0xCE, 0xF3, 0x0F, 0x22, 0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x12, 0x20, 0x37, 0xF8, ++0x1E, 0xB0, 0x4F, 0xEA, 0x12, 0x2E, 0x4E, 0xEA, 0x02, 0x2E, 0x8E, 0xEA, 0x0B, 0x0B, 0xDC, 0x44, 0x08, 0xF1, 0x08, 0x0E, ++0x1F, 0xFA, 0x8C, 0xFC, 0x00, 0xEB, 0x0E, 0x02, 0xA1, 0xF8, 0x08, 0xC0, 0x10, 0xF8, 0x0E, 0xE0, 0x52, 0x78, 0x4E, 0xEA, ++0x02, 0x22, 0x8C, 0xEA, 0x02, 0x02, 0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, 0x12, 0xB0, ++0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x0B, 0x0B, 0x08, 0xF1, 0x0C, 0x08, 0x5E, 0x44, 0x00, 0xEB, ++0x08, 0x02, 0xB6, 0xB2, 0x4E, 0x81, 0x92, 0xF8, 0x01, 0xE0, 0x10, 0xF8, 0x08, 0x20, 0x42, 0xEA, 0x0E, 0x22, 0x72, 0x40, ++0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, 0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, ++0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x15, 0x44, 0xAD, 0xB2, 0x02, 0x9A, 0x8D, 0x81, 0x92, 0xF8, 0x01, 0xE0, 0x10, 0xF8, ++0x1A, 0x20, 0x42, 0xEA, 0x0E, 0x22, 0x6A, 0x40, 0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, ++0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x19, 0xFA, 0x82, 0xF2, 0x13, 0x44, ++0x09, 0xF1, 0x01, 0x09, 0x9B, 0xB2, 0xB9, 0xF1, 0x08, 0x0F, 0xCB, 0x81, 0x7F, 0xF4, 0x6E, 0xAF, 0x01, 0x9A, 0x0A, 0x61, ++0x4F, 0xF0, 0x01, 0x0E, 0x81, 0xF8, 0x14, 0xE0, 0x00, 0x9A, 0x90, 0xF8, 0x01, 0x80, 0x90, 0xF8, 0x00, 0xE0, 0x90, 0xF8, ++0x03, 0x90, 0x1A, 0x44, 0x4E, 0xEA, 0x08, 0x2E, 0x92, 0xB2, 0x82, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x28, 0x5F, 0xFA, ++0x8E, 0xFE, 0x37, 0xF8, 0x18, 0xA0, 0x37, 0xF8, 0x1E, 0x80, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, ++0x08, 0x0A, 0x90, 0xF8, 0x02, 0x80, 0x90, 0xF8, 0x05, 0xE0, 0x54, 0x44, 0xA4, 0xB2, 0x48, 0xEA, 0x09, 0x28, 0x84, 0xEA, ++0x08, 0x08, 0x4F, 0xEA, 0x18, 0x2A, 0x5F, 0xFA, 0x88, 0xF8, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x18, 0x90, 0x4F, 0xEA, ++0x1A, 0x28, 0x48, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x04, 0x90, 0x90, 0xF8, 0x07, 0x80, 0xD4, 0x44, ++0x1F, 0xFA, 0x8C, 0xFC, 0x49, 0xEA, 0x0E, 0x2E, 0x8C, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, 0x5F, 0xFA, 0x8E, 0xFE, ++0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x1E, 0x90, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, ++0x90, 0xF8, 0x06, 0x90, 0x90, 0xF8, 0x09, 0xE0, 0x56, 0x44, 0xB6, 0xB2, 0x49, 0xEA, 0x08, 0x28, 0x86, 0xEA, 0x08, 0x08, ++0x4F, 0xEA, 0x18, 0x2A, 0x5F, 0xFA, 0x88, 0xF8, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x18, 0x90, 0x4F, 0xEA, 0x1A, 0x28, ++0x48, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x08, 0x90, 0x90, 0xF8, 0x0B, 0x80, 0x55, 0x44, 0xAD, 0xB2, ++0x49, 0xEA, 0x0E, 0x2E, 0x85, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, 0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x1A, 0xA0, ++0x37, 0xF8, 0x1E, 0x90, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x0A, 0xE0, ++0x90, 0xF8, 0x0D, 0x90, 0x53, 0x44, 0x9B, 0xB2, 0x4E, 0xEA, 0x08, 0x2E, 0x83, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, ++0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x1E, 0x80, 0x07, 0x7B, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, ++0x0A, 0x2E, 0x8E, 0xEA, 0x08, 0x08, 0x42, 0x44, 0x92, 0xB2, 0x47, 0xEA, 0x09, 0x29, 0x82, 0xEA, 0x09, 0x07, 0xFF, 0x03, ++0x82, 0xEA, 0x09, 0x09, 0x90, 0xF8, 0x0F, 0xE0, 0x47, 0xEA, 0x59, 0x09, 0x87, 0x7B, 0x4C, 0x44, 0xA4, 0xB2, 0x47, 0xEA, ++0x0E, 0x27, 0x84, 0xEA, 0x07, 0x0E, 0x4F, 0xEA, 0xCE, 0x3E, 0x67, 0x40, 0x4E, 0xEA, 0x57, 0x07, 0x67, 0x44, 0xBF, 0xB2, ++0x4F, 0xEA, 0xC7, 0x3C, 0x4C, 0xEA, 0x57, 0x0C, 0x66, 0x44, 0xB6, 0xB2, 0x4F, 0xEA, 0xC6, 0x3C, 0x4C, 0xEA, 0x56, 0x0C, ++0x65, 0x44, 0xAD, 0xB2, 0x4F, 0xEA, 0xC5, 0x3C, 0x4C, 0xEA, 0x55, 0x0C, 0x63, 0x44, 0x1F, 0xFA, 0x83, 0xF9, 0x00, 0x9B, ++0xAD, 0xF8, 0x18, 0x60, 0x4F, 0xEA, 0x13, 0x2E, 0x0E, 0xF0, 0x7F, 0x0C, 0xAD, 0xF8, 0x16, 0x70, 0xAD, 0xF8, 0x1A, 0x50, ++0x03, 0x9E, 0x00, 0x9D, 0xB5, 0x70, 0x4C, 0xF0, 0x20, 0x0C, 0x86, 0xF8, 0x00, 0xE0, 0x86, 0xF8, 0x01, 0xC0, 0x4F, 0xEA, ++0xC9, 0x38, 0x45, 0x78, 0x03, 0x78, 0xAD, 0xF8, 0x1C, 0x90, 0x48, 0xEA, 0x59, 0x08, 0x42, 0x44, 0x92, 0xB2, 0x43, 0xEA, ++0x05, 0x23, 0xAD, 0xF8, 0x1E, 0x20, 0x5A, 0x40, 0x52, 0x08, 0xF2, 0x70, 0x33, 0x46, 0x06, 0xF1, 0x0C, 0x00, 0x05, 0xAA, ++0x01, 0xE0, 0x32, 0xF8, 0x02, 0x4F, 0x1C, 0x71, 0x25, 0x0A, 0x5D, 0x71, 0x02, 0x33, 0x98, 0x42, 0xF7, 0xD1, 0x00, 0x23, ++0x0B, 0x75, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xCC, 0x88, 0xB1, 0xF8, 0x08, 0xC0, 0x4E, 0x89, 0x8D, 0x89, 0xCB, 0x89, ++0x00, 0x4F, 0xFD, 0xE6, 0x50, 0xA9, 0x15, 0x00, 0xF0, 0xB4, 0x13, 0x4F, 0x01, 0x22, 0x3C, 0x1F, 0x00, 0x23, 0xC7, 0xF8, ++0x00, 0x24, 0xC7, 0xF8, 0x04, 0x34, 0x22, 0x46, 0x42, 0xF8, 0x04, 0x3F, 0x01, 0x33, 0xB3, 0xF5, 0x80, 0x7F, 0xF9, 0xD1, ++0x00, 0x23, 0xDF, 0xF8, 0x30, 0xC0, 0x1D, 0x46, 0xC2, 0x5C, 0x54, 0xF8, 0x04, 0x6F, 0x2A, 0x44, 0x32, 0x44, 0xD5, 0xB2, ++0x01, 0x33, 0x57, 0xF8, 0x25, 0x20, 0x22, 0x60, 0x8B, 0x42, 0xA8, 0xBF, 0x00, 0x23, 0xA4, 0x45, 0x47, 0xF8, 0x25, 0x60, ++0xEE, 0xD1, 0x00, 0x20, 0xF0, 0xBC, 0x70, 0x47, 0x18, 0x2C, 0x17, 0x00, 0x14, 0x30, 0x17, 0x00, 0x71, 0xB3, 0x18, 0x4B, ++0xF0, 0xB5, 0xD3, 0xF8, 0x00, 0x54, 0xD3, 0xF8, 0x04, 0x24, 0x53, 0xF8, 0x25, 0x60, 0x32, 0x44, 0x01, 0x39, 0xD2, 0xB2, ++0x89, 0xB2, 0x01, 0x31, 0x53, 0xF8, 0x22, 0x40, 0x01, 0x44, 0x6F, 0x1C, 0x43, 0xF8, 0x22, 0x60, 0x43, 0xF8, 0x25, 0x40, ++0xFD, 0xB2, 0x34, 0x44, 0xE4, 0xB2, 0x53, 0xF8, 0x25, 0x60, 0x53, 0xF8, 0x24, 0x70, 0x10, 0xF8, 0x01, 0x4B, 0x02, 0xEB, ++0x06, 0x0C, 0x96, 0x46, 0x5F, 0xFA, 0x8C, 0xF2, 0x67, 0x40, 0x88, 0x42, 0x53, 0xF8, 0x22, 0x40, 0x00, 0xF8, 0x01, 0x7C, ++0xE5, 0xD1, 0xC3, 0xF8, 0x00, 0x54, 0xC3, 0xF8, 0x04, 0xE4, 0xF0, 0xBD, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x2C, 0x17, 0x00, ++0xFF, 0xF7, 0xCA, 0xBF, 0x83, 0x68, 0x8A, 0x68, 0x03, 0x48, 0x9B, 0x1A, 0x83, 0x42, 0x94, 0xBF, 0x00, 0x20, 0x01, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0xA3, 0xE1, 0x11, 0x83, 0x88, 0xB3, 0xEB, 0x11, 0x4F, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, ++0xC0, 0x88, 0x89, 0xB2, 0x40, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, ++0xDF, 0xF8, 0x4C, 0xB1, 0xDB, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0x46, 0x89, 0x46, 0x15, 0x46, ++0x5E, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, ++0x2C, 0x81, 0xDF, 0xF8, 0x2C, 0xA1, 0xD8, 0xF8, 0x00, 0x30, 0xDA, 0xF8, 0x14, 0x60, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, ++0x1E, 0xB1, 0xB3, 0x88, 0xBB, 0x42, 0x40, 0xD0, 0x00, 0x26, 0x37, 0x49, 0x37, 0x48, 0x49, 0xEA, 0x07, 0x42, 0x00, 0xF0, ++0xF5, 0xF9, 0x04, 0x46, 0x00, 0x28, 0x47, 0xD0, 0x34, 0x4B, 0x35, 0x4A, 0x1B, 0x69, 0x32, 0x48, 0x1D, 0x44, 0xA5, 0x60, ++0x21, 0x46, 0x00, 0xF0, 0x87, 0xFE, 0x9E, 0xB9, 0xDA, 0xF8, 0x14, 0x30, 0xA3, 0x42, 0x13, 0xD0, 0xD8, 0xF8, 0x00, 0x30, ++0x2B, 0xB1, 0x29, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x8B, 0xB1, 0x29, 0x4B, 0x1A, 0x69, 0xAD, 0x1A, ++0x00, 0x2D, 0x14, 0xDB, 0xBD, 0xE8, 0xF8, 0x8F, 0xDA, 0xF8, 0x14, 0x40, 0x00, 0x2C, 0xEB, 0xD0, 0x25, 0x4B, 0xA1, 0x68, ++0xD3, 0xF8, 0xE0, 0x31, 0x24, 0x48, 0x98, 0x47, 0xE4, 0xE7, 0x00, 0x2A, 0xEB, 0xD0, 0x62, 0xB6, 0x1E, 0x4B, 0x1A, 0x69, ++0xAD, 0x1A, 0x00, 0x2D, 0xEA, 0xDA, 0xBD, 0xE8, 0xF8, 0x4F, 0x4F, 0xF0, 0x00, 0x50, 0x00, 0xF0, 0x29, 0xBD, 0xF6, 0x88, ++0xA6, 0xEB, 0x09, 0x06, 0xB6, 0xFA, 0x86, 0xF6, 0x76, 0x09, 0xB8, 0xE7, 0xB2, 0xB1, 0x19, 0x4B, 0x9A, 0x42, 0x9C, 0xD9, ++0x18, 0x49, 0x19, 0x48, 0x94, 0x22, 0x02, 0xF0, 0x0F, 0xFA, 0x96, 0xE7, 0x0C, 0x20, 0x00, 0xF0, 0xFB, 0xF9, 0xDB, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x09, 0xDB, 0xA7, 0x80, 0xA4, 0xF8, 0x06, 0x90, 0xA9, 0xE7, ++0x0E, 0x49, 0x10, 0x48, 0x93, 0x22, 0x02, 0xF0, 0xFB, 0xF9, 0x82, 0xE7, 0x00, 0x28, 0xF3, 0xD1, 0x0A, 0x49, 0x0D, 0x48, ++0xA5, 0x22, 0x02, 0xF0, 0xF3, 0xF9, 0xED, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x59, 0x26, 0x14, 0x00, 0x94, 0xB6, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x41, 0x26, 0x14, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0xB6, 0x17, 0x00, 0xFF, 0xA2, 0xE1, 0x11, ++0x70, 0x79, 0x15, 0x00, 0x5C, 0xAB, 0x15, 0x00, 0x50, 0xAB, 0x15, 0x00, 0x78, 0xAB, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0xF8, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x25, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x25, 0x4D, 0x25, 0x4E, 0x2B, 0x68, 0x74, 0x69, 0x01, 0x33, 0x2B, 0x60, 0x74, 0xB1, ++0xA3, 0x88, 0x83, 0x42, 0x02, 0xD1, 0xE3, 0x88, 0x8B, 0x42, 0x11, 0xD0, 0x41, 0xEA, 0x00, 0x42, 0x1F, 0x49, 0x20, 0x48, ++0x00, 0xF0, 0x54, 0xF9, 0x04, 0x46, 0x38, 0xBB, 0x2B, 0x68, 0x33, 0xB1, 0x18, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xF8, 0xBD, 0x06, 0xF1, 0x14, 0x00, 0x00, 0xF0, 0x98, 0xFD, 0x77, 0x69, 0x17, 0x4B, ++0xDF, 0xB1, 0xD3, 0xF8, 0xE0, 0x31, 0xB9, 0x68, 0x06, 0xF1, 0x20, 0x00, 0x98, 0x47, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x0A, 0xDA, 0x12, 0x4A, 0xBB, 0x68, 0x12, 0x69, 0x9B, 0x1A, 0x00, 0x2B, 0x04, 0xDA, 0x10, 0x49, ++0x10, 0x48, 0xE7, 0x22, 0x02, 0xF0, 0x8E, 0xF9, 0x20, 0x46, 0x00, 0xF0, 0xED, 0xF9, 0x2B, 0x68, 0xD3, 0xE7, 0xD3, 0xF8, ++0xD8, 0x31, 0x06, 0xF1, 0x20, 0x00, 0x98, 0x47, 0xF4, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x80, 0xB6, 0x17, 0x00, 0x59, 0x26, 0x14, 0x00, 0x94, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, 0x80, 0xAB, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x28, 0x4D, 0x29, 0x4F, ++0xDF, 0xF8, 0xB0, 0x80, 0x28, 0x4E, 0xDF, 0xF8, 0xB0, 0x90, 0x21, 0xE0, 0xA1, 0x68, 0x33, 0x69, 0xCB, 0x1A, 0x32, 0x2B, ++0x07, 0xD4, 0xD9, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0xA3, 0x68, 0x32, 0x69, 0x9B, 0x1A, 0x00, 0x2B, 0x30, 0xDA, 0x21, 0x48, ++0x00, 0xF0, 0x44, 0xFD, 0x2B, 0x68, 0x04, 0x46, 0x5A, 0x1E, 0x2B, 0xB1, 0xD8, 0xF8, 0x00, 0x30, 0x2A, 0x60, 0x0A, 0xB9, ++0x03, 0xB1, 0x62, 0xB6, 0xA0, 0x88, 0xE1, 0x88, 0xFF, 0x22, 0x00, 0xF0, 0xCB, 0xF8, 0x20, 0x46, 0x00, 0xF0, 0xA4, 0xF9, ++0x4F, 0xF0, 0x00, 0x50, 0x00, 0xF0, 0x6C, 0xFC, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, ++0xC8, 0xF8, 0x00, 0x30, 0x2A, 0x68, 0x7C, 0x69, 0x10, 0x48, 0x53, 0x1C, 0x2B, 0x60, 0x00, 0x2C, 0xCA, 0xD1, 0x2B, 0xB1, ++0x0E, 0x4B, 0x2A, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x2B, 0x68, 0x00, 0x2B, ++0xFA, 0xD0, 0x09, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0xF4, 0xD1, 0x00, 0x2A, 0xF2, 0xD0, 0xF0, 0xE7, ++0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x94, 0xB6, 0x17, 0x00, 0xA0, 0xB6, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x0E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0E, 0x4D, 0x0E, 0x4C, 0x2B, 0x68, 0x4F, 0xF0, 0x00, 0x50, 0x01, 0x33, 0x2B, 0x60, ++0x00, 0xF0, 0x28, 0xFC, 0x01, 0xE0, 0x00, 0xF0, 0x59, 0xF9, 0x20, 0x46, 0x00, 0xF0, 0xE4, 0xFC, 0x00, 0x28, 0xF8, 0xD1, ++0x2B, 0x68, 0x33, 0xB1, 0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x94, 0xB6, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x80, 0x46, 0x03, 0xF1, ++0x0C, 0x00, 0x1D, 0x46, 0x0F, 0x46, 0x16, 0x46, 0x00, 0xF0, 0xC8, 0xF8, 0x0F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0x46, 0x0F, 0xDB, 0x00, 0x21, 0xA4, 0xF8, 0x04, 0x80, 0x04, 0xF1, 0x0C, 0x08, 0xE7, 0x80, 0x26, 0x81, ++0x65, 0x81, 0x2A, 0x46, 0x21, 0x60, 0x40, 0x46, 0xDD, 0xF7, 0xDC, 0xFB, 0x40, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x28, ++0xED, 0xD1, 0x04, 0x49, 0x04, 0x48, 0x52, 0x22, 0x02, 0xF0, 0xBA, 0xF8, 0xE7, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, 0x16, 0x4B, 0x1A, 0x68, 0x30, 0xF8, 0x06, 0x3C, 0xB2, 0xF9, 0x00, 0x10, ++0x00, 0x29, 0x10, 0xB5, 0xDA, 0xB2, 0x04, 0x46, 0x0C, 0xDB, 0x0B, 0x2A, 0x13, 0xD8, 0x11, 0x48, 0xA4, 0xF1, 0x0C, 0x01, ++0x00, 0xF0, 0x4C, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0xA4, 0xBB, 0x0D, 0x2A, 0xF0, 0xD9, ++0x0B, 0x49, 0x0C, 0x48, 0xBB, 0x22, 0x02, 0xF0, 0x93, 0xF8, 0x34, 0xF8, 0x06, 0x3C, 0x34, 0xF8, 0x04, 0x2C, 0x34, 0xF8, ++0x08, 0x1C, 0x08, 0x48, 0x01, 0xF0, 0x10, 0xFE, 0xA4, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0xF0, 0xDE, 0xB8, ++0x38, 0x36, 0x17, 0x00, 0x84, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0xB4, 0xAB, 0x15, 0x00, ++0x08, 0xB5, 0x00, 0x23, 0xFF, 0xF7, 0x94, 0xFF, 0xBD, 0xE8, 0x08, 0x40, 0xFF, 0xF7, 0xC0, 0xBF, 0x10, 0xB4, 0x5D, 0xF8, ++0x04, 0x4B, 0x20, 0xF8, 0x08, 0x1C, 0x20, 0xF8, 0x06, 0x2C, 0x20, 0xF8, 0x04, 0x3C, 0xFF, 0xF7, 0xB5, 0xBF, 0x00, 0xBF, ++0x00, 0xF0, 0xC6, 0xB8, 0x2D, 0xE9, 0xF0, 0x41, 0x04, 0x68, 0xD4, 0xB1, 0x07, 0x46, 0x0D, 0x46, 0x16, 0x46, 0x4F, 0xF0, ++0x00, 0x08, 0x02, 0xE0, 0xA0, 0x46, 0x93, 0xB1, 0x1C, 0x46, 0x31, 0x46, 0x20, 0x46, 0xA8, 0x47, 0x23, 0x68, 0x00, 0x28, ++0xF6, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0x0C, 0xD0, 0xC8, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x5B, 0xB1, 0x00, 0x23, 0x23, 0x60, ++0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x24, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x3B, 0x60, 0x00, 0x2B, 0xF3, 0xD1, ++0xC7, 0xF8, 0x04, 0x80, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x0F, 0x48, 0x30, 0xB4, 0x20, 0xF0, 0x03, 0x00, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4A, 0x0C, 0x4B, ++0x11, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x4C, 0x1C, 0x1B, 0x1A, 0x00, 0x25, 0x14, 0x60, 0xC0, 0xE9, 0x00, 0x53, 0x2C, 0xB1, ++0x04, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x03, 0xA0, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0xF8, 0xB5, 0x31, 0x4F, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x03, 0x30, 0x20, 0xF0, 0x03, 0x04, 0x00, 0x2B, 0x04, 0xF1, 0x04, 0x06, 0x48, 0xDB, 0x2C, 0x4B, 0xDB, 0x69, ++0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2A, 0x4A, 0x01, 0x21, 0x11, 0x60, 0x29, 0x4D, 0x2A, 0x68, ++0x02, 0xF1, 0x01, 0x0C, 0xC5, 0xF8, 0x00, 0xC0, 0x00, 0x2B, 0x3E, 0xD0, 0x04, 0xF1, 0x0C, 0x00, 0x00, 0x21, 0x05, 0xE0, ++0x4C, 0x68, 0xA2, 0x42, 0x38, 0xBF, 0x19, 0x46, 0x1B, 0x68, 0x43, 0xB1, 0x5A, 0x68, 0x82, 0x42, 0xFA, 0xD3, 0x00, 0x29, ++0xF4, 0xD1, 0x19, 0x46, 0x1B, 0x68, 0x00, 0x2B, 0xF6, 0xD1, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x12, 0xDB, ++0x0A, 0x46, 0x4B, 0x68, 0x9B, 0x1B, 0x98, 0x18, 0x4B, 0x60, 0x04, 0x30, 0x9E, 0x50, 0xBC, 0xF1, 0x00, 0x0F, 0x07, 0xD0, ++0x13, 0x4A, 0x0C, 0xF1, 0xFF, 0x33, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xF8, 0xBD, 0x00, 0x29, ++0xEA, 0xD1, 0x10, 0x49, 0x10, 0x48, 0x97, 0x22, 0x01, 0xF0, 0xC0, 0xFF, 0x00, 0x22, 0xD5, 0xF8, 0x00, 0xC0, 0x11, 0x46, ++0xE1, 0xE7, 0x07, 0x2E, 0xB4, 0xD8, 0x0A, 0x49, 0x0B, 0x48, 0x7B, 0x22, 0x01, 0xF0, 0xB4, 0xFF, 0xAE, 0xE7, 0x3A, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xE8, 0xDB, 0x5B, 0x68, 0xFF, 0xDE, 0x38, 0x36, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x08, 0xAC, 0x15, 0x00, 0xE0, 0xAB, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xF4, 0x90, 0x36, 0x4A, 0xD9, 0xF8, 0x00, 0x30, 0xD4, 0x69, 0xB3, 0xF9, 0x00, 0x30, ++0x50, 0xF8, 0x04, 0x8C, 0x00, 0x2B, 0x06, 0x46, 0xA0, 0xF1, 0x04, 0x05, 0x2F, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x2E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x48, 0xD0, 0xF8, 0x00, 0xC0, 0x0C, 0xF1, 0x01, 0x07, ++0x07, 0x60, 0x00, 0x2C, 0x47, 0xD0, 0x63, 0x68, 0x1A, 0x19, 0xAA, 0x42, 0x23, 0xD0, 0xAC, 0x42, 0x06, 0xD9, 0x37, 0xE0, ++0x63, 0x68, 0x1A, 0x19, 0xAA, 0x42, 0x1C, 0xD0, 0xAC, 0x42, 0x26, 0xD8, 0x21, 0x46, 0x24, 0x68, 0x00, 0x2C, 0xF5, 0xD1, ++0x0D, 0x60, 0x46, 0xE9, 0x01, 0x48, 0x47, 0xB1, 0x1E, 0x4B, 0xC0, 0xF8, 0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, ++0x01, 0xD1, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0xA0, 0x42, 0xCD, 0xD8, 0x1A, 0x49, 0x1A, 0x48, 0xC7, 0x22, ++0x01, 0xF0, 0x56, 0xFF, 0xC7, 0xE7, 0x43, 0x44, 0x22, 0x68, 0x63, 0x60, 0xE1, 0x18, 0x8A, 0x42, 0xE5, 0xD1, 0xD2, 0xE9, ++0x00, 0x21, 0x0B, 0x44, 0x22, 0x60, 0x63, 0x60, 0xDF, 0xE7, 0x05, 0xEB, 0x08, 0x03, 0x9C, 0x42, 0x0D, 0x60, 0xD8, 0xD1, ++0x23, 0x68, 0x46, 0xF8, 0x04, 0x3C, 0x52, 0x1B, 0x32, 0x60, 0xD4, 0xE7, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0xDB, 0x00, 0x23, 0x1D, 0x60, 0xFF, 0xDE, 0x25, 0x60, 0xFF, 0xDE, 0x06, 0x49, 0x07, 0x48, 0xE2, 0x22, ++0x01, 0xF0, 0x2E, 0xFF, 0xF4, 0xE7, 0x00, 0xBF, 0x80, 0xB6, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x18, 0xAC, 0x15, 0x00, 0x3C, 0xAC, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xC0, 0x88, 0x40, 0x1A, ++0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x2A, 0xB3, 0xF8, 0xB5, 0x53, 0x1E, 0x0F, 0x46, 0x0A, 0x68, 0x01, 0xE0, ++0x59, 0x1C, 0x11, 0xD0, 0x32, 0xF8, 0x33, 0x40, 0x84, 0x42, 0x4F, 0xEA, 0xC3, 0x06, 0x02, 0xEB, 0xC3, 0x05, 0x03, 0xF1, ++0xFF, 0x33, 0xF3, 0xD1, 0x0B, 0x4B, 0x68, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x02, 0xDB, 0xF8, 0xBD, ++0x00, 0x20, 0xF8, 0xBD, 0x00, 0x28, 0xFA, 0xD1, 0x06, 0x49, 0x07, 0x48, 0xF4, 0x22, 0x01, 0xF0, 0xF5, 0xFE, 0x3B, 0x68, ++0x1E, 0x44, 0x70, 0x68, 0xF8, 0xBD, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x50, 0xAC, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x44, 0x4F, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, ++0x0D, 0x46, 0x4F, 0xEA, 0x10, 0x29, 0xC6, 0xB2, 0x3B, 0xDB, 0x40, 0x4B, 0x03, 0xEB, 0x06, 0x16, 0xB3, 0x68, 0x03, 0xEB, ++0x49, 0x09, 0x3E, 0x48, 0x2A, 0x46, 0x21, 0x46, 0x01, 0xF0, 0x56, 0xFC, 0xB9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x01, 0xD1, ++0xBD, 0xE8, 0xF8, 0x83, 0xDF, 0xF8, 0x0C, 0x81, 0x38, 0x4F, 0x39, 0x4E, 0xA9, 0xF8, 0x00, 0x50, 0x19, 0xE0, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0x33, 0x60, 0x34, 0x4D, 0x35, 0x48, 0x2B, 0x68, 0x01, 0x33, ++0x2B, 0x60, 0x00, 0xF0, 0x61, 0xFA, 0x2A, 0x68, 0x53, 0x1E, 0x22, 0xB1, 0x32, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0xB3, 0xF9, 0x41, 0x46, 0x22, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0x40, 0xFE, ++0x01, 0x46, 0x00, 0x28, 0xDD, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x2E, 0x23, 0xD8, 0x33, 0xD0, 0x20, 0x4B, 0x03, 0xEB, ++0x06, 0x16, 0xF3, 0x89, 0x4B, 0x45, 0x0B, 0xD9, 0xB3, 0x68, 0x03, 0xEB, 0x49, 0x09, 0xB9, 0xF1, 0x00, 0x0F, 0xBA, 0xD1, ++0x20, 0x49, 0x21, 0x48, 0xB9, 0x22, 0x01, 0xF0, 0x8B, 0xFE, 0xB4, 0xE7, 0xB4, 0x22, 0x1D, 0x49, 0x1E, 0x48, 0x01, 0xF0, ++0x85, 0xFE, 0x3A, 0x68, 0xB3, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xEB, 0x49, 0x09, 0xA7, 0xDA, 0xB9, 0xF1, ++0x00, 0x0F, 0xA4, 0xD1, 0xE8, 0xE7, 0x15, 0x49, 0x17, 0x48, 0xB2, 0x22, 0x01, 0xF0, 0x74, 0xFE, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x93, 0xDA, 0x0D, 0x2E, 0x04, 0xD0, 0x0F, 0x49, 0x12, 0x48, 0xBB, 0x22, 0x01, 0xF0, 0x68, 0xFE, ++0x0C, 0x49, 0x11, 0x48, 0xB3, 0x22, 0x01, 0xF0, 0x63, 0xFE, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC1, 0xDB, ++0x81, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x14, 0xAD, 0x15, 0x00, 0xC8, 0xAC, 0x15, 0x00, 0x8C, 0xB6, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x84, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB8, 0xAC, 0x15, 0x00, ++0x98, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, 0x41, 0x2D, 0x14, 0x00, ++0x70, 0xB5, 0x20, 0x4D, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x4F, 0xEA, 0x10, 0x26, 0xC4, 0xB2, 0x06, 0xDB, ++0x1C, 0x4D, 0x24, 0x01, 0x25, 0x44, 0xAB, 0x68, 0x33, 0xF8, 0x16, 0x00, 0x70, 0xBD, 0x0C, 0x2C, 0x11, 0xD8, 0x21, 0xD0, ++0x17, 0x4D, 0x05, 0xEB, 0x04, 0x13, 0x24, 0x01, 0xDB, 0x89, 0xB3, 0x42, 0xF0, 0xD8, 0x25, 0x44, 0x14, 0x49, 0x15, 0x48, ++0xD9, 0x22, 0x01, 0xF0, 0x1F, 0xFE, 0xAB, 0x68, 0x33, 0xF8, 0x16, 0x00, 0x70, 0xBD, 0x10, 0x49, 0x11, 0x48, 0xD7, 0x22, ++0x01, 0xF0, 0x16, 0xFE, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDA, 0x0D, 0x2C, 0x04, 0xD0, 0x0A, 0x49, ++0x0C, 0x48, 0xBB, 0x22, 0x01, 0xF0, 0x0A, 0xFE, 0x07, 0x49, 0x0B, 0x48, 0xD8, 0x22, 0x01, 0xF0, 0x05, 0xFE, 0x2B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xD3, 0xDB, 0xC8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x14, 0xAD, 0x15, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x98, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x68, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x67, 0x4D, 0x68, 0x48, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x00, 0xF0, 0xCF, 0xF9, 0x2B, 0x68, 0x04, 0x46, 0x2B, 0xB1, ++0x61, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x54, 0xD0, 0x00, 0x2C, 0x39, 0xD0, 0x60, 0x4F, 0xB4, 0xF8, ++0x06, 0xA0, 0x3B, 0x68, 0xB4, 0xF8, 0x04, 0x80, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5F, 0xFA, 0x8A, 0xF6, 0x4F, 0xEA, ++0x1A, 0x2A, 0x48, 0xDB, 0xDF, 0xF8, 0x90, 0x91, 0x36, 0x01, 0x59, 0xF8, 0x06, 0x10, 0xB1, 0x44, 0x00, 0x29, 0x52, 0xD0, ++0xD9, 0xF8, 0x08, 0x30, 0x33, 0xF8, 0x1A, 0x30, 0x01, 0xEB, 0xC3, 0x01, 0x40, 0x46, 0x8A, 0x88, 0xFF, 0xF7, 0x9C, 0xFE, ++0x06, 0x46, 0x00, 0x28, 0x45, 0xD0, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x4E, 0x48, 0x01, 0xF0, 0x31, 0xFB, 0x23, 0x89, ++0xE2, 0x88, 0xA0, 0x88, 0x04, 0xF1, 0x0C, 0x01, 0xB0, 0x47, 0x01, 0x28, 0x08, 0xD0, 0x02, 0x28, 0x7B, 0xD0, 0x00, 0x28, ++0x50, 0xD0, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x79, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x3E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x41, 0x4A, 0x2B, 0x68, 0x52, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x00, 0x2A, ++0x40, 0xD0, 0x33, 0xB1, 0x38, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, ++0xF0, 0x87, 0x00, 0x2A, 0xA8, 0xD0, 0x62, 0xB6, 0xA6, 0xE7, 0x0C, 0x2E, 0x36, 0xD8, 0x48, 0xD0, 0xDF, 0xF8, 0xF8, 0x90, ++0x09, 0xEB, 0x06, 0x13, 0x36, 0x01, 0xDB, 0x89, 0x53, 0x45, 0xAE, 0xD8, 0x32, 0x49, 0x33, 0x48, 0x4F, 0xF4, 0x89, 0x72, ++0x01, 0xF0, 0x6C, 0xFD, 0xA7, 0xE7, 0xD9, 0xF8, 0x04, 0x10, 0x69, 0xB1, 0x8A, 0x88, 0x40, 0x46, 0xFF, 0xF7, 0x4C, 0xFE, ++0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x06, 0x46, 0x27, 0x48, 0x01, 0xF0, 0xE3, 0xFA, 0x00, 0x2E, 0xAF, 0xD1, 0x05, 0xE0, ++0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x23, 0x48, 0x01, 0xF0, 0xDA, 0xFA, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x24, 0x48, ++0x01, 0xF0, 0xD4, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0xE5, 0xFC, 0xAF, 0xE7, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0x74, 0xF8, ++0x2B, 0x68, 0xB8, 0xE7, 0x1B, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0x88, 0x72, 0x01, 0xF0, 0x3E, 0xFD, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0x72, 0xAF, 0x0D, 0x2E, 0x04, 0xD0, 0x14, 0x49, 0x18, 0x48, 0xBB, 0x22, 0x01, 0xF0, ++0x31, 0xFD, 0x12, 0x49, 0x16, 0x48, 0x40, 0xF2, 0x11, 0x12, 0x01, 0xF0, 0x2B, 0xFD, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xAB, 0xDB, 0x5E, 0xE7, 0x12, 0x48, 0x21, 0x46, 0x00, 0xF0, 0xCD, 0xF8, 0x85, 0xE7, 0x09, 0x49, 0x10, 0x48, ++0x40, 0xF2, 0x6D, 0x12, 0x01, 0xF0, 0x1A, 0xFD, 0x7E, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x84, 0xB6, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xB4, 0xAB, 0x15, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x98, 0xAC, 0x15, 0x00, 0xDC, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, ++0x8C, 0xB6, 0x17, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x14, 0xAD, 0x15, 0x00, 0x00, 0x20, 0x70, 0x47, 0x02, 0x20, 0x70, 0x47, ++0x30, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4A, ++0x09, 0x4D, 0x11, 0x68, 0x2B, 0x68, 0x4C, 0x1C, 0x18, 0x43, 0x14, 0x60, 0x28, 0x60, 0x2C, 0xB1, 0x03, 0x4B, 0x11, 0x60, ++0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x80, 0xB6, 0x17, 0x00, 0x4F, 0xF0, 0x00, 0x50, 0xFF, 0xF7, 0xDC, 0xBF, 0x30, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0A, 0x4A, 0x0A, 0x4D, 0x11, 0x68, 0x2B, 0x68, 0x4C, 0x1C, ++0x23, 0xEA, 0x00, 0x00, 0x14, 0x60, 0x28, 0x60, 0x2C, 0xB1, 0x04, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, ++0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x18, 0x4E, 0x34, 0x68, 0xDC, 0xB1, 0xDF, 0xF8, 0x68, 0x80, 0x17, 0x4D, 0x17, 0x4F, 0xDF, 0xF8, ++0x64, 0xA0, 0xDF, 0xF8, 0x64, 0x90, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB4, 0xFA, 0x84, 0xF4, ++0x12, 0xDB, 0x55, 0xF8, 0x34, 0x30, 0x05, 0xEB, 0xC4, 0x04, 0x60, 0x68, 0x98, 0x47, 0x3B, 0x68, 0x34, 0x68, 0xDB, 0x78, ++0x1B, 0xB9, 0x00, 0x2C, 0xEB, 0xD1, 0xBD, 0xE8, 0xF0, 0x87, 0xE9, 0xF7, 0x09, 0xFA, 0x00, 0x2C, 0xE5, 0xD1, 0xF8, 0xE7, ++0x1D, 0x2C, 0x03, 0xDC, 0x55, 0xF8, 0x34, 0x30, 0x00, 0x2B, 0xE8, 0xD1, 0xDC, 0x22, 0x51, 0x46, 0x48, 0x46, 0x01, 0xF0, ++0x7D, 0xFC, 0xE0, 0xE7, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x21, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xE4, 0xAD, 0x15, 0x00, 0x08, 0xB5, 0xFF, 0xF7, 0x35, 0xFC, 0x08, 0x4B, 0x08, 0x49, 0xD8, 0x61, ++0x00, 0x22, 0xC3, 0xE9, 0x03, 0x22, 0xC3, 0xE9, 0x01, 0x22, 0xC3, 0xE9, 0x05, 0x22, 0x59, 0x62, 0x4F, 0xF0, 0xFF, 0x30, ++0xBD, 0xE8, 0x08, 0x40, 0xFF, 0xF7, 0x8A, 0xBF, 0x80, 0xB6, 0x17, 0x00, 0xD1, 0x31, 0x14, 0x00, 0x00, 0x23, 0xC0, 0xE9, ++0x00, 0x33, 0x70, 0x47, 0x38, 0xB5, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, ++0x07, 0xDB, 0x2B, 0x68, 0x6B, 0xB1, 0x6B, 0x68, 0x1C, 0x60, 0x00, 0x23, 0x6C, 0x60, 0x23, 0x60, 0x38, 0xBD, 0x00, 0x29, ++0xF5, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x48, 0x22, 0x01, 0xF0, 0x3C, 0xFC, 0xEF, 0xE7, 0x00, 0x23, 0x2C, 0x60, 0x6C, 0x60, ++0x23, 0x60, 0x38, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x14, 0xAE, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, 0x04, 0xDB, 0x2B, 0x68, 0x53, 0xB1, 0x23, 0x60, ++0x2C, 0x60, 0x38, 0xBD, 0x00, 0x29, 0xF8, 0xD1, 0x05, 0x49, 0x06, 0x48, 0x5F, 0x22, 0x01, 0xF0, 0x1B, 0xFC, 0xF2, 0xE7, ++0x6C, 0x60, 0x23, 0x60, 0x2C, 0x60, 0x38, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x14, 0xAE, 0x15, 0x00, ++0x03, 0x68, 0x33, 0xB1, 0x42, 0x68, 0x19, 0x68, 0x01, 0x60, 0x9A, 0x42, 0x04, 0xBF, 0x00, 0x22, 0x42, 0x60, 0x18, 0x46, ++0x70, 0x47, 0x00, 0xBF, 0x38, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, ++0x0B, 0xDB, 0x2B, 0x68, 0x43, 0xB1, 0xA3, 0x42, 0x02, 0xD1, 0x14, 0xE0, 0xA3, 0x42, 0x0C, 0xD0, 0x1A, 0x46, 0x1B, 0x68, ++0x00, 0x2B, 0xF9, 0xD1, 0x38, 0xBD, 0x00, 0x28, 0xF1, 0xD1, 0x0C, 0x49, 0x0C, 0x48, 0x84, 0x22, 0x01, 0xF0, 0xE8, 0xFB, ++0xEB, 0xE7, 0x6B, 0x68, 0xA3, 0x42, 0x0A, 0xD0, 0x23, 0x68, 0x13, 0x60, 0x38, 0xBD, 0x6B, 0x68, 0x22, 0x68, 0x2A, 0x60, ++0xA3, 0x42, 0xEB, 0xD1, 0x00, 0x23, 0x6B, 0x60, 0x38, 0xBD, 0x6A, 0x60, 0xF2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x28, 0xAE, 0x15, 0x00, 0x03, 0x68, 0x2B, 0xB1, 0x00, 0x20, 0x1B, 0x68, 0x01, 0x30, 0x00, 0x2B, ++0xFB, 0xD1, 0x70, 0x47, 0x18, 0x46, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0xD0, 0xE9, 0x00, 0x47, 0x80, 0x46, 0x0D, 0x46, ++0x16, 0x46, 0x1F, 0xB1, 0x39, 0x46, 0x28, 0x46, 0x90, 0x47, 0x88, 0xB1, 0x00, 0x27, 0x24, 0xB9, 0x1A, 0xE0, 0x23, 0x68, ++0x27, 0x46, 0x8B, 0xB1, 0x1C, 0x46, 0x21, 0x46, 0x28, 0x46, 0xB0, 0x47, 0x00, 0x28, 0xF6, 0xD0, 0x2C, 0x60, 0x67, 0xB9, ++0xC8, 0xF8, 0x00, 0x50, 0xBD, 0xE8, 0xF0, 0x81, 0x3D, 0x60, 0xC8, 0xF8, 0x04, 0x50, 0x28, 0x60, 0xBD, 0xE8, 0xF0, 0x81, ++0xC8, 0xF8, 0x04, 0x50, 0x2B, 0x60, 0x3D, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x23, 0xC8, 0xF8, 0x04, 0x50, 0x2B, 0x60, ++0xEA, 0xE7, 0x00, 0xBF, 0x03, 0x68, 0xB9, 0xB1, 0xCB, 0xB1, 0x8B, 0x42, 0x10, 0xB4, 0x04, 0x46, 0x02, 0xD1, 0x07, 0xE0, ++0x99, 0x42, 0x05, 0xD0, 0x1B, 0x68, 0x00, 0x2B, 0xFA, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x63, 0x68, 0x08, 0x68, ++0x10, 0x60, 0x8B, 0x42, 0x0A, 0x60, 0xF6, 0xD1, 0x62, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x11, 0x46, 0xFF, 0xF7, ++0x49, 0xBF, 0x70, 0x47, 0x81, 0xB1, 0x03, 0x68, 0x8B, 0x42, 0x0A, 0xD0, 0x2B, 0xB1, 0x18, 0x68, 0x88, 0x42, 0x03, 0xD0, ++0x03, 0x46, 0x00, 0x2B, 0xF9, 0xD1, 0x70, 0x47, 0x11, 0x60, 0x1A, 0x60, 0x70, 0x47, 0x11, 0x46, 0xFF, 0xF7, 0x36, 0xBF, ++0x11, 0x46, 0xFF, 0xF7, 0x0F, 0xBF, 0x00, 0xBF, 0x0B, 0x46, 0x09, 0x68, 0x99, 0xB1, 0x02, 0x46, 0x00, 0x68, 0x48, 0xB1, ++0x10, 0xB4, 0x54, 0x68, 0x58, 0x68, 0x21, 0x60, 0x50, 0x60, 0x00, 0x22, 0x5D, 0xF8, 0x04, 0x4B, 0x1A, 0x60, 0x70, 0x47, ++0x93, 0xE8, 0x03, 0x00, 0x82, 0xE8, 0x03, 0x00, 0x00, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x70, 0x47, 0xF8, 0xB5, 0x1F, 0x4F, ++0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0x46, 0x0D, 0x46, 0x14, 0x46, 0x0A, 0xDB, 0x25, 0xB3, 0x23, 0x68, ++0x2B, 0x60, 0x73, 0x68, 0xA3, 0x42, 0x4F, 0xF0, 0x00, 0x03, 0x08, 0xBF, 0x75, 0x60, 0x23, 0x60, 0xF8, 0xBD, 0xE0, 0xB1, ++0xB5, 0xB1, 0x2B, 0x68, 0xA3, 0x42, 0x0A, 0xD0, 0x13, 0x49, 0x14, 0x48, 0x40, 0xF2, 0x75, 0x12, 0x01, 0xF0, 0x2A, 0xFB, ++0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE5, 0xDA, 0x00, 0x2C, 0xE3, 0xD1, 0x0D, 0x49, 0x0E, 0x48, 0x4F, 0xF4, ++0xBB, 0x72, 0x01, 0xF0, 0x1D, 0xFB, 0xDB, 0xE7, 0x00, 0x2C, 0xF6, 0xD0, 0x23, 0x68, 0x33, 0x60, 0xD9, 0xE7, 0x07, 0x49, ++0x09, 0x48, 0x4F, 0xF4, 0xBA, 0x72, 0x01, 0xF0, 0x11, 0xFB, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xD7, 0xDB, ++0xCA, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x38, 0xAE, 0x15, 0x00, 0x74, 0xAE, 0x15, 0x00, ++0x28, 0xAE, 0x15, 0x00, 0x81, 0xB1, 0x10, 0xB4, 0x08, 0x4C, 0x01, 0x44, 0x10, 0xF8, 0x01, 0x3B, 0x83, 0xEA, 0x12, 0x63, ++0x81, 0x42, 0x54, 0xF8, 0x23, 0x30, 0x83, 0xEA, 0x02, 0x22, 0xF5, 0xD1, 0x10, 0x46, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x10, 0x46, 0x70, 0x47, 0x84, 0xAE, 0x15, 0x00, 0xF8, 0xB5, 0x0F, 0x18, 0xB8, 0x42, 0xBC, 0x46, 0x06, 0xD3, 0x1D, 0xE0, ++0x44, 0x78, 0x2E, 0x78, 0x02, 0x34, 0xFF, 0x2E, 0x20, 0x44, 0x06, 0xD0, 0x46, 0x1C, 0xB7, 0x42, 0x05, 0x46, 0xF5, 0xD8, ++0x00, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x87, 0x42, 0xFA, 0xD3, 0x1C, 0x80, 0x00, 0x2D, 0xF7, 0xD0, 0xEE, 0x1C, 0x66, 0x45, ++0xF4, 0xD8, 0xAE, 0x78, 0x96, 0x42, 0xF2, 0xD0, 0x0C, 0x1B, 0x84, 0x45, 0xA1, 0xB2, 0x01, 0xD9, 0x0F, 0x18, 0xE7, 0xE7, ++0x06, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE5, 0xDA, 0x84, 0x45, 0xE3, 0xD0, 0x03, 0x49, 0x04, 0x48, ++0x7F, 0x22, 0x01, 0xF0, 0xB9, 0xFA, 0xDD, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x84, 0xB2, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x43, 0x01, 0xEB, 0x00, 0x08, 0x40, 0x45, 0xC6, 0x46, 0x2D, 0xD2, 0x02, 0xF1, 0x05, 0x0C, 0xC2, 0xF1, ++0x02, 0x07, 0x05, 0xE0, 0x44, 0x78, 0x35, 0x78, 0x02, 0x34, 0xDD, 0x2D, 0x20, 0x44, 0x07, 0xD0, 0x45, 0x1C, 0xA8, 0x45, ++0x06, 0x46, 0xF5, 0xD8, 0x00, 0x26, 0x30, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x80, 0x45, 0xF9, 0xD3, 0x1C, 0x80, 0x00, 0x2E, ++0xF6, 0xD0, 0xF5, 0x1D, 0xAE, 0x45, 0xF3, 0xD3, 0x15, 0x46, 0x01, 0xE0, 0x65, 0x45, 0xF0, 0xD0, 0x05, 0xEB, 0x06, 0x08, ++0x15, 0xF8, 0x01, 0x9B, 0x18, 0xF8, 0x07, 0x80, 0xC1, 0x45, 0xF5, 0xD0, 0x0C, 0x1B, 0x86, 0x45, 0xA1, 0xB2, 0x02, 0xD9, ++0x01, 0xEB, 0x00, 0x08, 0xDC, 0xE7, 0x07, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDA, 0x86, 0x45, ++0xD8, 0xD0, 0x04, 0x49, 0x04, 0x48, 0xB4, 0x22, 0x01, 0xF0, 0x70, 0xFA, 0xD2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0xB2, 0x15, 0x00, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x70, 0xB4, 0x03, 0xE0, ++0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x10, 0xD9, 0x44, 0x78, 0x06, 0x78, 0xA3, 0x1C, 0x01, 0x2E, 0x03, 0xEB, 0x00, 0x05, ++0xF4, 0xD1, 0xA9, 0x42, 0x07, 0xD3, 0x38, 0xB1, 0x0A, 0x2B, 0x04, 0xD8, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x70, 0x70, 0xBC, ++0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x17, 0xD9, ++0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, 0xA3, 0x1C, 0x32, 0x2E, ++0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x70, 0x70, 0xBC, ++0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x70, 0xB4, 0x03, 0xE0, 0x73, 0x1C, 0x99, 0x42, 0x30, 0x46, 0x10, 0xD9, 0x45, 0x78, 0x04, 0x78, 0xAB, 0x1C, 0x1E, 0x18, ++0x00, 0x2C, 0xF5, 0xD1, 0xB1, 0x42, 0x05, 0xD3, 0x10, 0xB1, 0x22, 0x2B, 0x02, 0xD8, 0x15, 0x70, 0x70, 0xBC, 0x70, 0x47, ++0x20, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x17, 0xD9, 0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, ++0xA3, 0x1C, 0x07, 0x2E, 0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x07, 0x2B, 0x02, 0xD9, ++0x14, 0x70, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x17, 0xD9, 0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, ++0xA3, 0x1C, 0x30, 0x2E, 0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x13, 0x2B, 0x02, 0xD9, ++0x14, 0x70, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x25, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x05, 0x2B, 0x18, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, ++0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x3C, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, ++0x06, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x1A, 0xD9, 0x30, 0xB4, 0x03, 0xE0, 0x63, 0x1C, 0x99, 0x42, ++0x20, 0x46, 0x11, 0xD9, 0x43, 0x78, 0x05, 0x78, 0x02, 0x33, 0x3E, 0x2D, 0x03, 0xEB, 0x00, 0x04, 0xF4, 0xD1, 0xA1, 0x42, ++0x08, 0xD3, 0x40, 0xB1, 0xA3, 0xF1, 0x03, 0x03, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0x30, 0xBC, 0x13, 0x70, 0x70, 0x47, ++0x00, 0x20, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x2B, 0xD9, ++0x30, 0xB4, 0x03, 0xE0, 0x18, 0x46, 0x01, 0x33, 0x99, 0x42, 0x16, 0xD9, 0x44, 0x78, 0x05, 0x78, 0xA3, 0x1C, 0xC4, 0x2D, ++0x03, 0x44, 0xF5, 0xD1, 0x99, 0x42, 0x0E, 0xD3, 0x70, 0xB1, 0x02, 0x30, 0x04, 0x44, 0x07, 0xE0, 0x43, 0x78, 0x05, 0x78, ++0x02, 0x33, 0xC2, 0x2D, 0x03, 0xEB, 0x00, 0x01, 0x06, 0xD0, 0x08, 0x46, 0x43, 0x1C, 0x9C, 0x42, 0xF4, 0xD8, 0x00, 0x20, ++0x30, 0xBC, 0x70, 0x47, 0x8C, 0x42, 0xFA, 0xD3, 0x00, 0x28, 0xF9, 0xD0, 0xA3, 0xF1, 0x05, 0x03, 0xB3, 0xFA, 0x83, 0xF3, ++0x5B, 0x09, 0x30, 0xBC, 0x13, 0x70, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x03, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x4C, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x12, 0x2B, 0x18, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, ++0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x2A, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, ++0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, ++0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xC7, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, ++0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, ++0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x20, 0x2C, 0x03, 0xEB, 0x00, 0x02, ++0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x36, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x05, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xB5, 0x83, 0xB0, ++0x06, 0x4A, 0x0D, 0xF1, 0x06, 0x03, 0xFF, 0xF7, 0xC1, 0xFD, 0x20, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0x1A, 0x2B, 0x18, 0xBF, ++0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x98, 0xB2, 0x15, 0x00, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x2D, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x1C, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x47, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x06, 0x2B, 0x38, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x1D, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x63, 0x1C, 0x99, 0x42, 0x20, 0x46, 0x13, 0xD9, ++0x43, 0x78, 0x02, 0x78, 0x02, 0x33, 0x1C, 0x18, 0x00, 0x2A, 0xF5, 0xD1, 0xA1, 0x42, 0x03, 0xD2, 0x10, 0x46, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x28, 0xFA, 0xD0, 0x06, 0x2B, 0x38, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, ++0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x53, 0x2C, ++0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x04, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, ++0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, ++0x02, 0x33, 0x55, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x02, 0x2B, 0x08, 0xBF, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, ++0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, ++0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xBF, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, ++0x0E, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, 0x06, 0x03, 0x23, 0x22, 0xFF, 0xF7, 0xB2, 0xFC, ++0x40, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0xA3, 0xF1, 0x18, 0x02, 0x21, 0x2A, 0x9A, 0xBF, 0x03, 0x3B, 0x23, 0x70, 0x00, 0x20, ++0x02, 0xB0, 0x10, 0xBD, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, ++0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x3D, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, ++0x06, 0xD3, 0x30, 0xB1, 0x18, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, ++0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xC0, 0x2C, 0x03, 0xEB, 0x00, 0x02, ++0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x07, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, ++0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, ++0x06, 0x03, 0x24, 0x22, 0xFF, 0xF7, 0x5E, 0xFC, 0x40, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0xA3, 0xF1, 0x09, 0x02, 0x09, 0x2A, ++0x9A, 0xBF, 0x03, 0x3B, 0x23, 0x70, 0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x06, 0x03, ++0x26, 0x22, 0xFF, 0xF7, 0x4B, 0xFC, 0x20, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0x10, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0xFB, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x06, 0x03, 0x25, 0x22, 0xFF, 0xF7, 0x3B, 0xFC, 0x20, 0xB1, ++0xBD, 0xF8, 0x06, 0x30, 0x04, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x43, 0x79, 0x02, 0x79, ++0x58, 0x00, 0x40, 0xEA, 0xD2, 0x10, 0x80, 0x05, 0x70, 0x47, 0x00, 0xBF, 0x43, 0x79, 0x07, 0x48, 0x83, 0xEA, 0x13, 0x13, ++0x5B, 0x01, 0xC1, 0xF3, 0x08, 0x01, 0x03, 0xF4, 0xF0, 0x73, 0x0B, 0x44, 0x00, 0xEA, 0x83, 0x50, 0x40, 0xF4, 0x7C, 0x10, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x28, 0x08, 0xDA, 0x10, 0xF1, 0x6D, 0x0F, 0x01, 0xDA, 0x00, 0x20, ++0x70, 0x47, 0x6E, 0x30, 0x40, 0x00, 0xC0, 0xB2, 0x70, 0x47, 0xDC, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, ++0x1D, 0x46, 0x95, 0xB0, 0x90, 0x46, 0xDD, 0xF8, 0x78, 0xB0, 0x15, 0xF8, 0x01, 0x2B, 0x03, 0x91, 0x07, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0x7F, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x91, 0x83, 0x00, 0x24, 0xCD, 0xE9, 0x00, 0x44, 0x03, 0x9E, 0x02, 0x94, ++0xA1, 0x46, 0xA2, 0x46, 0xA2, 0xF1, 0x20, 0x03, 0x58, 0x2B, 0x5A, 0xD8, 0xDF, 0xE8, 0x13, 0xF0, 0x35, 0x01, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x34, 0x03, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x17, 0x03, 0x35, 0x01, ++0x59, 0x00, 0x35, 0x01, 0x36, 0x03, 0x59, 0x00, 0x12, 0x01, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, ++0x10, 0x01, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x01, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, ++0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0xA2, 0xF1, 0x31, 0x01, 0x08, 0x29, ++0x40, 0xF2, 0xE2, 0x80, 0x00, 0x21, 0x9E, 0x48, 0x00, 0xEB, 0xCA, 0x0A, 0x1A, 0xF8, 0x01, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, ++0x00, 0xF2, 0xD8, 0x83, 0xDF, 0xE8, 0x0A, 0xF0, 0x75, 0x5B, 0x45, 0x9A, 0x70, 0x8E, 0x80, 0x06, 0x07, 0x21, 0xEE, 0xE7, ++0xA2, 0xF1, 0x41, 0x03, 0x37, 0x2B, 0x00, 0xF2, 0x05, 0x82, 0xDF, 0xE8, 0x13, 0xF0, 0x05, 0x02, 0x03, 0x02, 0x03, 0x02, ++0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x54, 0x02, ++0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, ++0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x05, 0x02, ++0x29, 0x01, 0x5E, 0x01, 0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0xA3, 0x01, 0x03, 0x02, 0x03, 0x02, ++0x03, 0x02, 0x54, 0x02, 0x03, 0x02, 0x03, 0x02, 0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0xF8, 0x01, 0x03, 0x02, 0x29, 0x01, ++0x03, 0x02, 0x03, 0x02, 0x29, 0x01, 0x10, 0x2B, 0x00, 0xF2, 0xCA, 0x80, 0xDF, 0xE8, 0x13, 0xF0, 0xD2, 0x00, 0xC8, 0x00, ++0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xD9, 0x00, ++0xC8, 0x00, 0xE0, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC1, 0x00, 0x00, 0x23, 0x00, 0x93, 0x02, 0x93, 0x4F, 0xF0, 0xFF, 0x33, ++0x01, 0x93, 0x4F, 0xF0, 0x01, 0x0A, 0x15, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0x7F, 0xF4, 0x28, 0xAF, 0x00, 0x2E, 0x62, 0xD0, ++0x00, 0x23, 0x3B, 0x70, 0x20, 0x46, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x23, 0x01, 0x93, 0x4F, 0xF0, 0x04, 0x0A, ++0xED, 0xE7, 0x2E, 0xB1, 0xA0, 0x45, 0x9C, 0xBF, 0x07, 0xF8, 0x01, 0x2B, 0x06, 0xF1, 0xFF, 0x36, 0x01, 0x34, 0x4F, 0xF0, ++0x00, 0x0A, 0xE2, 0xE7, 0x68, 0x2A, 0x7B, 0xD0, 0x6C, 0x2A, 0x3F, 0xD0, 0x57, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC0, 0xF2, 0x92, 0x82, 0x4F, 0xF0, 0x06, 0x0A, 0xD4, 0xE7, 0x2A, 0x2A, 0x61, 0xD0, 0x01, 0x9B, 0x30, 0x3A, ++0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x43, 0x03, 0x01, 0x93, 0x4F, 0xF0, 0x05, 0x0A, 0xC8, 0xE7, 0x2A, 0x2A, 0x5B, 0xD0, ++0x02, 0x9B, 0x30, 0x3A, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x43, 0x03, 0x02, 0x93, 0x4F, 0xF0, 0x03, 0x0A, 0xBC, 0xE7, ++0x06, 0x21, 0x4C, 0xE7, 0x44, 0x4B, 0x03, 0xEB, 0xCA, 0x0A, 0x9A, 0xF8, 0x03, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, ++0x25, 0x83, 0x01, 0xA3, 0x53, 0xF8, 0x2A, 0xF0, 0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0xBB, 0x40, 0x14, 0x00, ++0xD9, 0x3F, 0x14, 0x00, 0x85, 0x3F, 0x14, 0x00, 0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, ++0x00, 0x9B, 0x43, 0xF0, 0x02, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x06, 0x0A, 0x97, 0xE7, 0x05, 0x21, 0x27, 0xE7, 0x03, 0x9B, ++0x00, 0x2B, 0x9B, 0xD0, 0x20, 0x46, 0x07, 0xF8, 0x01, 0x6C, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0x49, 0x01, 0xEB, ++0xCA, 0x0A, 0x9A, 0xF8, 0x04, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, 0xF7, 0x82, 0x01, 0xA1, 0x51, 0xF8, 0x2A, 0xF0, ++0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0x2F, 0x3F, 0x14, 0x00, 0xDD, 0x3F, 0x14, 0x00, 0x85, 0x3F, 0x14, 0x00, ++0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, 0x5B, 0xF8, 0x04, 0x3B, 0x01, 0x93, 0x4F, 0xF0, ++0x05, 0x0A, 0x6A, 0xE7, 0x5B, 0xF8, 0x04, 0x3B, 0x02, 0x93, 0x4F, 0xF0, 0x03, 0x0A, 0x64, 0xE7, 0x00, 0x9B, 0x43, 0xF0, ++0x01, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x06, 0x0A, 0x5D, 0xE7, 0x14, 0x46, 0x00, 0x2A, 0x3F, 0xF4, 0x63, 0xAF, 0x03, 0x90, ++0x7D, 0xE6, 0x00, 0x9B, 0x43, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x50, 0xE7, 0x10, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9E, 0x82, 0x4F, 0xF0, 0x02, 0x0A, 0x46, 0xE7, 0x00, 0x9B, 0x43, 0xF0, ++0x10, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x3F, 0xE7, 0x00, 0x9B, 0x43, 0xF0, 0x08, 0x03, 0x00, 0x93, 0x4F, 0xF0, ++0x02, 0x0A, 0x38, 0xE7, 0x00, 0x9B, 0x43, 0xF0, 0x20, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x31, 0xE7, 0x00, 0xBF, ++0x24, 0xB3, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x9B, 0x9B, 0x07, 0x00, 0xF1, 0x94, 0x81, 0x00, 0x9B, 0xD8, 0x07, ++0x40, 0xF1, 0x90, 0x81, 0x64, 0x2A, 0x00, 0xF0, 0x32, 0x82, 0x5B, 0xF8, 0x04, 0x1B, 0x58, 0x3A, 0x89, 0xB2, 0x20, 0x2A, ++0x00, 0xF2, 0x24, 0x82, 0xDF, 0xE8, 0x12, 0xF0, 0x5A, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, ++0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x4E, 0x02, 0x22, 0x02, 0x72, 0x00, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, ++0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x36, 0x02, 0x22, 0x02, ++0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x72, 0x00, 0x22, 0x02, 0x22, 0x02, 0x69, 0x02, 0x02, 0x9B, 0x59, 0x1E, 0x5B, 0xF8, ++0x04, 0x3B, 0x8D, 0xF8, 0x10, 0x30, 0x00, 0x9B, 0x04, 0xAA, 0x03, 0xF0, 0x40, 0x00, 0x01, 0x23, 0x00, 0x28, 0x70, 0xD1, ++0x00, 0x98, 0x80, 0x06, 0x40, 0xF1, 0x15, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0xEA, 0x81, 0x10, 0x46, 0x02, 0xEB, 0x03, 0x09, ++0xA4, 0xEB, 0x02, 0x0E, 0x09, 0xE0, 0xE0, 0x45, 0x04, 0xD8, 0x07, 0x78, 0x02, 0xF8, 0x01, 0x7B, 0x01, 0x3E, 0x17, 0x46, ++0x01, 0x30, 0x48, 0x45, 0x07, 0xD0, 0x00, 0xEB, 0x0E, 0x0C, 0x3A, 0x46, 0x00, 0x2E, 0xF0, 0xD1, 0x01, 0x30, 0x48, 0x45, ++0xF4, 0xD1, 0x23, 0x44, 0x00, 0x29, 0x40, 0xF3, 0xCA, 0x81, 0xCC, 0x18, 0x20, 0x21, 0x08, 0xE0, 0x98, 0x45, 0x03, 0xD8, ++0x02, 0xF8, 0x01, 0x1B, 0x01, 0x3E, 0x17, 0x46, 0x01, 0x33, 0xA3, 0x42, 0x05, 0xD0, 0x3A, 0x46, 0x00, 0x2E, 0xF3, 0xD1, ++0x01, 0x33, 0xA3, 0x42, 0xF6, 0xD1, 0x4F, 0xF0, 0x07, 0x0A, 0xB2, 0xE6, 0x00, 0x9B, 0x99, 0x07, 0x03, 0xD4, 0x00, 0x9B, ++0xDA, 0x07, 0x00, 0xF1, 0xBC, 0x81, 0x5B, 0xF8, 0x04, 0x1B, 0x00, 0x29, 0xC0, 0xF2, 0xBE, 0x81, 0xDF, 0xF8, 0x5C, 0xA4, ++0x00, 0x23, 0x0D, 0xF1, 0x50, 0x0E, 0xAA, 0xFB, 0x01, 0x2C, 0x4F, 0xEA, 0xDC, 0x0C, 0x0C, 0xEB, 0x8C, 0x00, 0xA1, 0xEB, ++0x40, 0x00, 0x89, 0x46, 0x30, 0x30, 0xB9, 0xF1, 0x09, 0x0F, 0x72, 0x46, 0x61, 0x46, 0x0E, 0xF8, 0x01, 0x0D, 0x18, 0x46, ++0x03, 0xF1, 0x01, 0x03, 0xEB, 0xD8, 0x00, 0x99, 0x09, 0x06, 0x00, 0xF1, 0x9E, 0x81, 0x00, 0x99, 0x09, 0x07, 0x40, 0xF1, ++0xE7, 0x81, 0x83, 0x1C, 0x2B, 0x20, 0x0E, 0xF8, 0x01, 0x0C, 0x00, 0x98, 0x02, 0x99, 0x00, 0xF0, 0x40, 0x00, 0x02, 0x3A, ++0xC9, 0x1A, 0x00, 0x28, 0x8E, 0xD0, 0x00, 0x29, 0x14, 0xDD, 0x0C, 0x44, 0x4F, 0xF0, 0x30, 0x0E, 0x08, 0xE0, 0xE0, 0x45, ++0x03, 0xD8, 0x00, 0xF8, 0x01, 0xEB, 0x01, 0x3E, 0x07, 0x46, 0x01, 0x39, 0x00, 0xF0, 0xB0, 0x80, 0xA4, 0xEB, 0x01, 0x0C, ++0x38, 0x46, 0x00, 0x2E, 0xF1, 0xD1, 0x01, 0x39, 0xF5, 0xD1, 0x00, 0x21, 0x00, 0x2B, 0x7F, 0xF4, 0x7C, 0xAF, 0x91, 0x46, ++0xA7, 0xE7, 0x5B, 0xF8, 0x04, 0x2B, 0x00, 0x2A, 0x40, 0xF0, 0x2C, 0x81, 0x00, 0x9B, 0x02, 0x99, 0x03, 0xF0, 0x40, 0x00, ++0x00, 0x23, 0x65, 0xE7, 0x4A, 0x46, 0xF7, 0xE7, 0x5B, 0xF8, 0x04, 0x3B, 0x02, 0x9A, 0xDF, 0xF8, 0xB0, 0xE3, 0x9C, 0x46, ++0x1C, 0xF8, 0x01, 0x3B, 0x00, 0x2A, 0x00, 0xF0, 0x09, 0x81, 0x19, 0x11, 0x15, 0x2A, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, ++0x01, 0x10, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, 0x10, 0x10, 0x28, 0xBF, 0x15, 0x22, 0x02, 0xEB, 0x42, 0x01, 0x01, 0x3A, ++0x8D, 0xF8, 0x11, 0x30, 0x01, 0xF1, 0xFF, 0x33, 0xC1, 0xF1, 0x01, 0x01, 0x1D, 0xD0, 0x0C, 0xEB, 0x02, 0x0A, 0x0D, 0xF1, ++0x13, 0x02, 0x1C, 0xF0, 0x03, 0x0F, 0x1C, 0xF8, 0x01, 0x0B, 0x4F, 0xEA, 0x20, 0x19, 0x00, 0xF0, 0x0F, 0x00, 0x1E, 0xF8, ++0x09, 0x90, 0x82, 0xF8, 0x00, 0x90, 0x1E, 0xF8, 0x00, 0x00, 0x50, 0x70, 0x0C, 0xBF, 0x4F, 0xF0, 0x3A, 0x09, 0x4F, 0xF0, ++0x2E, 0x09, 0xE2, 0x45, 0x02, 0xF8, 0x01, 0x9C, 0x02, 0xF1, 0x03, 0x02, 0xE5, 0xD1, 0x00, 0x9A, 0x02, 0xF0, 0x40, 0x02, ++0x00, 0x2A, 0x40, 0xF0, 0x69, 0x81, 0x00, 0x98, 0x02, 0x92, 0x80, 0x06, 0x04, 0xAA, 0x3F, 0xF5, 0x1F, 0xAF, 0x00, 0x2B, ++0x7F, 0xF4, 0x1F, 0xAF, 0xA1, 0xE7, 0x5B, 0xF8, 0x04, 0x1B, 0xDF, 0xF8, 0x14, 0xE3, 0x8C, 0x46, 0x4F, 0xF0, 0x3A, 0x09, ++0x1C, 0xF8, 0x06, 0x3B, 0x1A, 0x11, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, 0x02, 0x20, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, ++0x11, 0x30, 0x8D, 0xF8, 0x10, 0x20, 0x01, 0x31, 0x04, 0xAB, 0x11, 0xF8, 0x01, 0x2B, 0x83, 0xF8, 0x02, 0x90, 0x10, 0x11, ++0x02, 0xF0, 0x0F, 0x02, 0x1E, 0xF8, 0x00, 0x00, 0x1E, 0xF8, 0x02, 0x20, 0xD8, 0x70, 0x8C, 0x45, 0x1A, 0x71, 0x03, 0xF1, ++0x03, 0x03, 0xEE, 0xD1, 0x02, 0x9B, 0xA3, 0xF1, 0x11, 0x01, 0x00, 0x9B, 0x04, 0xAA, 0x03, 0xF0, 0x40, 0x00, 0x11, 0x23, ++0xE4, 0xE6, 0x00, 0x29, 0x7F, 0xF7, 0x6C, 0xAF, 0x21, 0x44, 0x4F, 0xF0, 0x20, 0x0C, 0x08, 0xE0, 0xA0, 0x45, 0x03, 0xD8, ++0x00, 0xF8, 0x01, 0xCB, 0x01, 0x3E, 0x07, 0x46, 0x01, 0x34, 0xA1, 0x42, 0x05, 0xD0, 0x38, 0x46, 0x00, 0x2E, 0xF3, 0xD1, ++0x01, 0x34, 0xA1, 0x42, 0xF6, 0xD1, 0x0C, 0x46, 0x00, 0x21, 0x00, 0x2B, 0x7F, 0xF4, 0xD3, 0xAE, 0x55, 0xE7, 0x04, 0x23, ++0x9A, 0x49, 0x01, 0xEB, 0xCA, 0x0A, 0x1A, 0xF8, 0x03, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, 0x1F, 0x81, 0x01, 0xA3, ++0x53, 0xF8, 0x2A, 0xF0, 0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0xC9, 0x40, 0x14, 0x00, 0xD9, 0x3F, 0x14, 0x00, ++0x85, 0x3F, 0x14, 0x00, 0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, 0x01, 0x23, 0xE1, 0xE7, ++0x02, 0x21, 0x26, 0xE5, 0x58, 0x3A, 0x5B, 0xF8, 0x04, 0x1B, 0x20, 0x2A, 0x00, 0xF2, 0x98, 0x80, 0x01, 0xA3, 0x53, 0xF8, ++0x22, 0xF0, 0x00, 0xBF, 0xED, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0xD5, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x17, 0x42, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0xA5, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, ++0x1D, 0x42, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x0B, 0x46, 0x14, 0x00, 0x03, 0x9E, 0x14, 0x46, ++0x4A, 0xE5, 0x64, 0x49, 0x64, 0x48, 0x4F, 0xF4, 0xA2, 0x72, 0x00, 0xF0, 0x49, 0xFB, 0x4F, 0xF0, 0x06, 0x0A, 0x3C, 0xE5, ++0x1A, 0x11, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, 0x02, 0x20, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, 0x10, 0x20, 0x8D, 0xF8, ++0x11, 0x30, 0x6F, 0xF0, 0x2E, 0x01, 0x2F, 0x23, 0x0F, 0x22, 0xFC, 0xE6, 0x13, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x97, 0x80, ++0x01, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0xCC, 0xAE, 0x01, 0x9B, 0x11, 0x46, 0xC2, 0xF1, 0x01, 0x00, 0x00, 0x2B, 0x00, 0xEB, ++0x01, 0x0C, 0x0F, 0xDD, 0x11, 0xF8, 0x01, 0xEF, 0x01, 0x3B, 0xBE, 0xF1, 0x00, 0x0F, 0x10, 0xD0, 0x00, 0x2B, 0xF3, 0xD1, ++0x02, 0x99, 0x00, 0x98, 0x01, 0x93, 0x63, 0x46, 0xC9, 0x1A, 0x00, 0xF0, 0x40, 0x00, 0x1F, 0xE6, 0x00, 0xEB, 0x01, 0x0C, ++0x11, 0xF8, 0x01, 0xEF, 0xBE, 0xF1, 0x00, 0x0F, 0xE4, 0xD1, 0x01, 0x93, 0x63, 0x46, 0x02, 0x99, 0x00, 0x98, 0xC9, 0x1A, ++0x00, 0xF0, 0x40, 0x00, 0x10, 0xE6, 0x1C, 0x46, 0x4F, 0xF0, 0x07, 0x0A, 0xF9, 0xE4, 0x23, 0x46, 0x91, 0x46, 0x2B, 0xE6, ++0x00, 0x9B, 0x02, 0x99, 0x03, 0xF0, 0x40, 0x00, 0x14, 0xAA, 0x00, 0x23, 0x02, 0xE6, 0x5B, 0xF8, 0x04, 0x1B, 0x09, 0xB2, ++0x41, 0xE6, 0x83, 0x1C, 0x2D, 0x20, 0x64, 0xE6, 0x00, 0x9B, 0x43, 0xF0, 0x80, 0x03, 0x49, 0x42, 0x00, 0x93, 0x3B, 0xE6, ++0x00, 0x9B, 0x43, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x08, 0x23, 0x40, 0x20, 0x02, 0x93, 0xDF, 0xF8, 0xD0, 0xC0, 0x14, 0xAA, ++0x01, 0xF0, 0x0F, 0x03, 0x09, 0x09, 0x1C, 0xF8, 0x03, 0x30, 0x02, 0xF8, 0x01, 0x3D, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, ++0xF4, 0xD1, 0x02, 0x99, 0xC9, 0x1A, 0xDD, 0xE5, 0x14, 0xAA, 0x01, 0xF0, 0x01, 0x03, 0x30, 0x33, 0x02, 0xF8, 0x01, 0x3D, ++0x49, 0x08, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, 0xF5, 0xD1, 0xBA, 0xE7, 0xDF, 0xF8, 0x90, 0xE0, 0x14, 0xAA, 0x01, 0xF0, ++0x0F, 0x03, 0x09, 0x09, 0x1E, 0xF8, 0x03, 0x30, 0x02, 0xF8, 0x01, 0x3D, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, 0xF4, 0xD1, ++0xAB, 0xE7, 0x00, 0x9B, 0x03, 0xF0, 0x40, 0x00, 0xCF, 0xE7, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0x11, 0x12, 0x00, 0xF0, ++0xAF, 0xFA, 0x4F, 0xF0, 0x02, 0x0A, 0xA2, 0xE4, 0x00, 0x22, 0x02, 0x92, 0x04, 0xAA, 0xBA, 0xE5, 0x00, 0x99, 0xC9, 0x06, ++0x06, 0xD4, 0x02, 0x98, 0xC1, 0x1A, 0x00, 0x98, 0x72, 0x46, 0x00, 0xF0, 0x40, 0x00, 0xA7, 0xE5, 0x83, 0x1C, 0x20, 0x20, ++0x0D, 0xE6, 0x00, 0x99, 0x01, 0xF0, 0x40, 0x00, 0x02, 0x99, 0x9F, 0xE5, 0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xBF, 0xF6, 0x86, 0xAC, 0x04, 0x49, 0x04, 0x48, 0x4F, 0xF4, 0x12, 0x72, 0x00, 0xF0, 0x89, 0xFA, 0x7E, 0xE4, ++0x24, 0xB3, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, ++0x10, 0xB3, 0x15, 0x00, 0xFC, 0xB2, 0x15, 0x00, 0x0F, 0xB4, 0x2D, 0xE9, 0xF0, 0x47, 0x21, 0x4E, 0xD6, 0xF8, 0x04, 0x31, ++0x82, 0xB0, 0xFB, 0xB1, 0x0A, 0x9C, 0xDF, 0xF8, 0x80, 0x80, 0xDF, 0xF8, 0x80, 0xA0, 0xDF, 0xF8, 0x80, 0x90, 0xA7, 0x1C, ++0x20, 0x46, 0x14, 0xF8, 0x01, 0x5B, 0x29, 0x06, 0xA5, 0xF1, 0x80, 0x02, 0x0A, 0xD5, 0x88, 0x2D, 0x13, 0xD8, 0xD6, 0xF8, ++0x00, 0x31, 0xDB, 0x43, 0xD3, 0x40, 0xDB, 0x07, 0x08, 0xD4, 0xA7, 0x42, 0x20, 0x46, 0xED, 0xD1, 0x12, 0x4B, 0x0B, 0xA9, ++0xD3, 0xF8, 0x30, 0x34, 0x01, 0x91, 0x98, 0x47, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x04, 0xB0, 0x70, 0x47, 0xD8, 0xF8, ++0x00, 0x30, 0xB3, 0xF9, 0x00, 0x20, 0x05, 0xF1, 0x66, 0x03, 0x00, 0x2A, 0xDB, 0xB2, 0x05, 0xDB, 0xD6, 0xF8, 0x04, 0x31, ++0x9A, 0x3D, 0xAB, 0x42, 0xE3, 0xD8, 0xEB, 0xE7, 0x05, 0x2B, 0xF7, 0xD9, 0x40, 0xF2, 0xA9, 0x22, 0x51, 0x46, 0x48, 0x46, ++0x00, 0xF0, 0x36, 0xFA, 0xF0, 0xE7, 0x00, 0xBF, 0xB0, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xCC, 0xB2, 0x15, 0x00, 0x0E, 0xB4, 0x09, 0x4B, 0x00, 0xB5, 0x1B, 0x68, 0x1B, 0x88, 0x18, 0x42, ++0x82, 0xB0, 0x06, 0xD0, 0x06, 0x4B, 0x03, 0x98, 0xD3, 0xF8, 0x30, 0x34, 0x04, 0xA9, 0x01, 0x91, 0x98, 0x47, 0x02, 0xB0, ++0x5D, 0xF8, 0x04, 0xEB, 0x03, 0xB0, 0x70, 0x47, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x05, 0x48, ++0xFF, 0xF7, 0x94, 0xFF, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0xFE, 0xF7, 0x35, 0xF8, 0xE0, 0xF7, 0x0F, 0xFC, 0xFE, 0xE7, ++0x64, 0xB3, 0x15, 0x00, 0x08, 0xB5, 0x05, 0x48, 0xFF, 0xF7, 0x86, 0xFF, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0xFE, 0xF7, ++0x27, 0xF8, 0xE0, 0xF7, 0x01, 0xFC, 0xFE, 0xE7, 0x7C, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x17, 0x48, 0x00, 0x68, 0x00, 0x78, ++0x02, 0x28, 0x83, 0xB0, 0x1D, 0x46, 0x06, 0xD1, 0x48, 0x78, 0x83, 0x1E, 0x01, 0x2B, 0x0C, 0x46, 0x0E, 0xD9, 0x05, 0x28, ++0x0C, 0xD0, 0x11, 0x48, 0x01, 0x92, 0xFF, 0xF7, 0x69, 0xFF, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, 0x1C, 0x40, 0xFE, 0xF7, ++0x63, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x23, 0x78, 0x53, 0xB9, 0xA3, 0x78, 0x01, 0x92, 0x1B, 0xB1, 0xE1, 0xF7, ++0x17, 0xFE, 0x01, 0x9A, 0xEE, 0xE7, 0xE1, 0xF7, 0x1D, 0xFE, 0x01, 0x9A, 0xEA, 0xE7, 0x01, 0x21, 0x01, 0x92, 0xE1, 0xF7, ++0xE1, 0xFD, 0x60, 0x78, 0x01, 0x9A, 0xED, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x88, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x83, 0xB0, ++0x0C, 0x46, 0x09, 0x48, 0x09, 0x68, 0x01, 0x92, 0x1D, 0x46, 0xFF, 0xF7, 0x3F, 0xFF, 0x07, 0x4B, 0x21, 0x68, 0xC3, 0xF8, ++0x04, 0x11, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, 0x07, 0x40, 0xFE, 0xF7, 0x35, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, ++0xA0, 0xB3, 0x15, 0x00, 0xB0, 0xB6, 0x17, 0x00, 0x30, 0xB5, 0x83, 0xB0, 0x0C, 0x46, 0x09, 0x48, 0x09, 0x68, 0x01, 0x92, ++0x1D, 0x46, 0xFF, 0xF7, 0x25, 0xFF, 0x07, 0x4B, 0x21, 0x68, 0xC3, 0xF8, 0x00, 0x11, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, ++0x05, 0x40, 0xFE, 0xF7, 0x1B, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0xC8, 0xB3, 0x15, 0x00, 0xB0, 0xB6, 0x17, 0x00, ++0x18, 0x46, 0x38, 0xB5, 0x0D, 0x46, 0x04, 0x23, 0x01, 0x46, 0x4F, 0xF4, 0x82, 0x60, 0xFE, 0xF7, 0xA3, 0xF8, 0x22, 0x4B, ++0xA9, 0x88, 0x93, 0xF8, 0xA9, 0x30, 0x04, 0x46, 0xEB, 0xB1, 0x4B, 0x1E, 0x01, 0x2B, 0x0D, 0xD9, 0x02, 0x29, 0x2A, 0xD0, ++0x03, 0x29, 0x2F, 0xD0, 0x04, 0x29, 0x1C, 0xD1, 0x1B, 0x4B, 0x2A, 0x68, 0xDA, 0x65, 0x4F, 0xF0, 0x80, 0x72, 0xC3, 0xF8, ++0x34, 0x21, 0x14, 0xE0, 0x18, 0x48, 0x17, 0x4A, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x53, 0x6F, 0x16, 0x48, ++0x43, 0xF0, 0x10, 0x03, 0x53, 0x67, 0x01, 0x23, 0x03, 0x70, 0x01, 0x29, 0xE2, 0xD1, 0x10, 0x4B, 0x2A, 0x68, 0xDA, 0x63, ++0x40, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0x00, 0x25, 0x0F, 0x48, 0x25, 0x60, 0xFF, 0xF7, 0xDA, 0xFE, 0x20, 0x46, 0xFE, 0xF7, ++0x9F, 0xF8, 0x28, 0x46, 0x38, 0xBD, 0x08, 0x4B, 0x2A, 0x68, 0x9A, 0x65, 0x20, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0xEE, 0xE7, ++0x04, 0x4B, 0x2A, 0x68, 0x1A, 0x64, 0x80, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0xE7, 0xE7, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, ++0x00, 0x00, 0x50, 0x40, 0xE0, 0x50, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, 0xF0, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x18, 0x46, ++0x0C, 0x46, 0x08, 0x23, 0x01, 0x46, 0x85, 0xB0, 0x40, 0xF2, 0x12, 0x40, 0xFE, 0xF7, 0x4A, 0xF8, 0x18, 0x4B, 0x22, 0x68, ++0x1B, 0x68, 0x1B, 0x78, 0x01, 0x3B, 0x01, 0x2B, 0x05, 0x46, 0x19, 0xD9, 0x11, 0x68, 0xA3, 0x68, 0x60, 0x68, 0x4B, 0x40, ++0x03, 0x40, 0x4B, 0x40, 0x13, 0x60, 0x22, 0x68, 0x2A, 0x60, 0x11, 0x68, 0xA3, 0x68, 0x69, 0x60, 0xCD, 0xE9, 0x01, 0x11, ++0x00, 0x92, 0x61, 0x68, 0x0D, 0x48, 0x1A, 0x46, 0xFF, 0xF7, 0x96, 0xFE, 0x28, 0x46, 0xFE, 0xF7, 0x5B, 0xF8, 0x00, 0x20, ++0x05, 0xB0, 0x30, 0xBD, 0x09, 0x4B, 0x9A, 0x42, 0x07, 0xD1, 0xD4, 0xE9, 0x01, 0x03, 0x11, 0x68, 0x4B, 0x40, 0x03, 0x40, ++0x4B, 0x40, 0x13, 0x60, 0x22, 0x68, 0xA3, 0x68, 0xC5, 0xE9, 0x00, 0x23, 0x19, 0x46, 0xE1, 0xE7, 0x78, 0x36, 0x17, 0x00, ++0x04, 0xB4, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, 0x10, 0xB5, 0x19, 0x46, 0x40, 0xF2, 0x0A, 0x40, 0x0C, 0x23, 0xFE, 0xF7, ++0x0B, 0xF8, 0x00, 0x24, 0xC0, 0xE9, 0x00, 0x44, 0x84, 0x60, 0xFE, 0xF7, 0x35, 0xF8, 0x20, 0x46, 0x10, 0xBD, 0x00, 0xBF, ++0x30, 0xB5, 0x18, 0x46, 0x83, 0xB0, 0x08, 0x23, 0x0C, 0x46, 0x01, 0x46, 0x40, 0xF2, 0x03, 0x40, 0xFD, 0xF7, 0xF8, 0xFF, ++0x10, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x3B, 0x01, 0x2B, 0x05, 0x46, 0x13, 0xD9, 0xD4, 0xE9, 0x00, 0x32, 0x1A, 0x60, ++0x23, 0x68, 0x03, 0x60, 0x19, 0x68, 0x62, 0x68, 0x41, 0x60, 0xCD, 0xE9, 0x00, 0x11, 0x09, 0x48, 0x11, 0x46, 0xFF, 0xF7, ++0x4B, 0xFE, 0x28, 0x46, 0xFE, 0xF7, 0x10, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0xD4, 0xE9, 0x00, 0x32, 0xC0, 0xE9, ++0x00, 0x32, 0x11, 0x46, 0xED, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x58, 0xB4, 0x15, 0x00, 0x38, 0xB5, 0x0D, 0x46, ++0x40, 0xF2, 0x01, 0x40, 0x19, 0x46, 0x08, 0x23, 0xFD, 0xF7, 0xCA, 0xFF, 0x29, 0x68, 0x0B, 0x68, 0x04, 0x46, 0xC4, 0xE9, ++0x00, 0x13, 0x1A, 0x46, 0x03, 0x48, 0xFF, 0xF7, 0x29, 0xFE, 0x20, 0x46, 0xFD, 0xF7, 0xEE, 0xFF, 0x00, 0x20, 0x38, 0xBD, ++0x98, 0xB4, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x46, 0x40, 0xF2, 0x0E, 0x40, 0x19, 0x46, 0x04, 0x23, 0xFD, 0xF7, 0xB2, 0xFF, ++0x61, 0x68, 0x02, 0x29, 0x05, 0x46, 0x20, 0xD9, 0x03, 0x29, 0x11, 0xD0, 0x13, 0x48, 0xFF, 0xF7, 0x11, 0xFE, 0x4F, 0xF4, ++0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0xC0, 0xB2, 0x28, 0x60, 0x0F, 0x48, 0xFF, 0xF7, 0x07, 0xFE, 0x28, 0x46, ++0xFD, 0xF7, 0xCC, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x24, 0x68, 0x0C, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0xFD, 0xFD, 0x5C, 0xB1, ++0xA2, 0x02, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0xFD, 0xF7, 0xEC, 0xFD, 0xE3, 0xE7, 0x22, 0x68, 0x06, 0x48, 0xFF, 0xF7, ++0xF1, 0xFD, 0xDE, 0xE7, 0xE0, 0xF7, 0x70, 0xFA, 0xFE, 0xE7, 0x00, 0xBF, 0xF4, 0xB4, 0x15, 0x00, 0x08, 0xB5, 0x15, 0x00, ++0xE8, 0xB4, 0x15, 0x00, 0xC8, 0xB4, 0x15, 0x00, 0x30, 0xB5, 0x40, 0xF2, 0x0C, 0x40, 0x83, 0xB0, 0x0C, 0x46, 0x19, 0x46, ++0x04, 0x23, 0xFD, 0xF7, 0x73, 0xFF, 0x05, 0x46, 0x20, 0x68, 0x00, 0x23, 0x82, 0x07, 0x62, 0x68, 0x2B, 0x60, 0x1C, 0xBF, ++0xFF, 0x23, 0x2B, 0x60, 0x93, 0x07, 0x1C, 0xBF, 0x01, 0x23, 0x2B, 0x60, 0x04, 0xF1, 0x08, 0x01, 0x12, 0xF0, 0xEA, 0xFA, ++0xD4, 0xE9, 0x00, 0x12, 0x28, 0x68, 0xA3, 0x68, 0x00, 0x90, 0x0A, 0x44, 0x04, 0x48, 0xFF, 0xF7, 0xC1, 0xFD, 0x28, 0x46, ++0xFD, 0xF7, 0x86, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x1C, 0xB5, 0x15, 0x00, 0x70, 0xB5, 0x06, 0x46, ++0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x11, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x10, 0x4C, 0x11, 0x48, ++0x25, 0x68, 0x22, 0xF0, 0x7F, 0x43, 0x01, 0x35, 0x0A, 0x46, 0x31, 0x46, 0x25, 0x60, 0xFF, 0xF7, 0xA3, 0xFD, 0x0D, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x05, 0xDB, 0xFC, 0xF7, 0x41, 0xFF, 0x4F, 0xF0, 0x00, 0x40, 0xFE, 0xF7, 0x1D, 0xFB, 0x23, 0x68, ++0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x70, 0xBD, 0x00, 0xBF, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x78, 0xB5, 0x15, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0xB5, 0x04, 0x46, ++0x72, 0xB6, 0x07, 0x4D, 0x07, 0x48, 0x00, 0x26, 0x22, 0xF0, 0x7F, 0x43, 0x2E, 0x60, 0x0A, 0x46, 0x21, 0x46, 0xFF, 0xF7, ++0x79, 0xFD, 0x04, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xFD, 0xD1, 0x70, 0xBD, 0x38, 0x00, 0x32, 0x40, 0x78, 0xB5, 0x15, 0x00, ++0xD0, 0x22, 0x17, 0x00, 0x10, 0xB4, 0x0C, 0x46, 0x22, 0xF0, 0x7F, 0x43, 0x01, 0x46, 0x22, 0x46, 0x02, 0x48, 0x5D, 0xF8, ++0x04, 0x4B, 0xFF, 0xF7, 0x63, 0xBD, 0x00, 0xBF, 0x90, 0xB5, 0x15, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x07, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x06, 0x4B, 0x1A, 0x68, 0x51, 0x1C, 0x19, 0x60, 0x29, 0xB1, 0x03, 0x49, ++0x1A, 0x60, 0x0B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, ++0x10, 0xB5, 0x06, 0x4C, 0x4F, 0xF4, 0x84, 0x72, 0x20, 0x46, 0x00, 0x21, 0xDB, 0xF7, 0xD2, 0xFA, 0x4F, 0xF0, 0xFF, 0x32, ++0x02, 0x23, 0xC4, 0xE9, 0x40, 0x23, 0x10, 0xBD, 0xB0, 0xB6, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x22, 0x00, 0x21, 0x02, 0x48, ++0xDB, 0xF7, 0xC4, 0xFA, 0x00, 0x20, 0x08, 0xBD, 0xB8, 0xB7, 0x17, 0x00, 0xE0, 0xF7, 0xB4, 0xBC, 0x01, 0x4B, 0xD3, 0xF8, ++0x24, 0x31, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x02, 0x20, 0x70, 0x47, 0xE0, 0xF7, 0xCC, 0xBB, 0x04, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x03, 0x2B, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0xE0, 0xF7, 0x5F, 0xBB, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, ++0xE0, 0xF7, 0x6E, 0xBB, 0x70, 0xB5, 0x04, 0x68, 0x9C, 0xB1, 0x0A, 0x4E, 0x05, 0x46, 0x03, 0xE0, 0xFE, 0xF7, 0x32, 0xFB, ++0x2C, 0x68, 0x64, 0xB1, 0x28, 0x46, 0xFE, 0xF7, 0x71, 0xFB, 0xE3, 0x68, 0x21, 0x46, 0x30, 0x46, 0x00, 0x2B, 0xF3, 0xD1, ++0xA2, 0x68, 0x2C, 0x68, 0x13, 0x81, 0x00, 0x2C, 0xF2, 0xD1, 0x70, 0xBD, 0x24, 0x65, 0x17, 0x00, 0x38, 0xB5, 0x14, 0x4B, ++0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xD0, 0x38, 0xBD, 0x04, 0x46, 0xE0, 0xF7, 0x80, 0xFB, 0x05, 0x46, 0xB8, 0xB1, ++0x4C, 0xF2, 0xDE, 0x03, 0xA3, 0x61, 0x21, 0x46, 0x1C, 0x22, 0x12, 0xF0, 0x07, 0xFA, 0x0C, 0x4C, 0x23, 0x68, 0x00, 0x2B, ++0xFC, 0xD0, 0x0B, 0x4B, 0x18, 0x68, 0x29, 0x1F, 0x00, 0xF5, 0x07, 0x70, 0xFE, 0xF7, 0x02, 0xFB, 0x01, 0x23, 0x23, 0x60, ++0xBD, 0xE8, 0x38, 0x40, 0xE0, 0xF7, 0x90, 0xBB, 0xBD, 0xE8, 0x38, 0x40, 0x04, 0x48, 0xFF, 0xF7, 0xD1, 0xBC, 0x00, 0xBF, ++0x78, 0x36, 0x17, 0x00, 0x58, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0xA8, 0xB5, 0x15, 0x00, 0x01, 0x4B, 0xD3, 0xF8, ++0x28, 0x31, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x04, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, ++0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0F, 0x4D, 0x10, 0x48, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0xFE, 0xF7, ++0xD7, 0xFA, 0x05, 0x2C, 0x03, 0xD8, 0x0D, 0x4A, 0x13, 0x5D, 0x01, 0x3B, 0x13, 0x55, 0x2B, 0x68, 0x33, 0xB1, 0x07, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x07, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, 0x01, 0x3B, ++0xC2, 0xF8, 0xF8, 0x31, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, ++0x74, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x4C, 0xDF, 0xF8, 0x3C, 0x80, 0x0C, 0x4F, ++0x0C, 0x4E, 0x04, 0xF5, 0x7C, 0x75, 0x62, 0x69, 0x30, 0x46, 0x13, 0x46, 0x3A, 0xB1, 0x12, 0x78, 0x21, 0x69, 0x20, 0x2A, ++0x0C, 0xBF, 0x42, 0x46, 0x3A, 0x46, 0xE1, 0xF7, 0xB1, 0xFA, 0x10, 0x34, 0xAC, 0x42, 0xF0, 0xD1, 0x00, 0x20, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0x24, 0x30, 0x17, 0x00, 0xC4, 0xB5, 0x15, 0x00, 0xC8, 0xB5, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xF8, 0xB5, 0x10, 0xF8, 0x01, 0x3C, 0x09, 0x2B, 0x00, 0xF1, 0xFF, 0x36, 0x30, 0xD1, 0x1C, 0x4C, 0x23, 0x68, 0x99, 0x42, ++0x0D, 0x46, 0x08, 0xDA, 0x1A, 0x4F, 0x38, 0x46, 0x00, 0xF0, 0x64, 0xFD, 0x23, 0x68, 0x01, 0x3B, 0xAB, 0x42, 0x23, 0x60, ++0xF7, 0xDC, 0x17, 0x4D, 0xAE, 0x42, 0x19, 0xD9, 0x16, 0x4F, 0x06, 0xE0, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x00, 0xF0, ++0x53, 0xFD, 0xAE, 0x42, 0x10, 0xD0, 0x15, 0xF8, 0x01, 0x0B, 0x09, 0x28, 0xF4, 0xD1, 0x20, 0x68, 0x00, 0xF0, 0x07, 0x00, ++0x38, 0x44, 0x00, 0xF0, 0x49, 0xFD, 0x23, 0x68, 0x23, 0xF0, 0x07, 0x03, 0x08, 0x33, 0xAE, 0x42, 0x23, 0x60, 0xEE, 0xD1, ++0x0A, 0x4A, 0x13, 0x68, 0x01, 0x3B, 0x30, 0x46, 0x13, 0x60, 0xF8, 0xBD, 0x04, 0x48, 0x00, 0xF0, 0x39, 0xFD, 0x02, 0x4A, ++0x13, 0x68, 0x01, 0x3B, 0x13, 0x60, 0xF1, 0xE7, 0x24, 0x34, 0x17, 0x00, 0x1C, 0xB8, 0x15, 0x00, 0x28, 0x34, 0x17, 0x00, ++0x20, 0xB8, 0x15, 0x00, 0x68, 0x34, 0x17, 0x00, 0x61, 0xB3, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0x64, 0x90, 0x16, 0x4F, ++0xDF, 0xF8, 0x58, 0x80, 0x0E, 0x46, 0x45, 0x1E, 0x00, 0x24, 0x08, 0xE0, 0x15, 0xF8, 0x01, 0x1F, 0x38, 0x46, 0xFF, 0xF7, ++0x11, 0xFC, 0x23, 0x07, 0x10, 0xD0, 0xB4, 0x42, 0x13, 0xD0, 0x14, 0xF0, 0x07, 0x0F, 0x04, 0xF1, 0x01, 0x04, 0xF1, 0xD1, ++0x48, 0x46, 0xFF, 0xF7, 0x05, 0xFC, 0x15, 0xF8, 0x01, 0x1F, 0x38, 0x46, 0xFF, 0xF7, 0x00, 0xFC, 0x23, 0x07, 0xEE, 0xD1, ++0x40, 0x46, 0xFF, 0xF7, 0xFB, 0xFB, 0xB4, 0x42, 0xEB, 0xD1, 0xBD, 0xE8, 0xF8, 0x43, 0x04, 0x48, 0xFF, 0xF7, 0xF4, 0xBB, ++0x02, 0x48, 0xFF, 0xF7, 0xF1, 0xBB, 0x00, 0xBF, 0xD8, 0xB5, 0x15, 0x00, 0xB4, 0x79, 0x15, 0x00, 0xD4, 0xB5, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x87, 0xB0, 0x04, 0x93, 0x00, 0x29, 0x7E, 0xD0, 0x04, 0x2A, 0x14, 0x46, 0x02, 0xD0, 0x53, 0x1E, ++0x01, 0x2B, 0x78, 0xD8, 0x65, 0x42, 0x04, 0xFB, 0x01, 0xF3, 0xDF, 0xF8, 0x8C, 0x91, 0x03, 0x93, 0x05, 0x40, 0x5C, 0x48, ++0x29, 0x46, 0xE1, 0xF7, 0x09, 0xFA, 0x03, 0x9A, 0x2B, 0x0E, 0x10, 0x2A, 0x17, 0x46, 0x28, 0xBF, 0x10, 0x27, 0x01, 0x2B, ++0x68, 0xD0, 0x2B, 0x0D, 0xB3, 0xF5, 0xA0, 0x6F, 0x64, 0xD0, 0x00, 0x2A, 0x00, 0xF0, 0x9C, 0x80, 0xDF, 0xF8, 0x60, 0x81, ++0xDF, 0xF8, 0x60, 0xA1, 0x2E, 0x46, 0x4F, 0xF0, 0x00, 0x0B, 0x0A, 0xE0, 0x02, 0x2C, 0x0A, 0xBF, 0x31, 0x88, 0x31, 0x78, ++0x50, 0x46, 0xA3, 0x44, 0xE1, 0xF7, 0xEA, 0xF9, 0x5F, 0x45, 0x26, 0x44, 0x0A, 0xD9, 0x04, 0x2C, 0x40, 0x46, 0xF1, 0xD1, ++0x31, 0x68, 0x48, 0x48, 0xA3, 0x44, 0xE1, 0xF7, 0xDF, 0xF9, 0x5F, 0x45, 0x26, 0x44, 0xF4, 0xD8, 0x04, 0x9B, 0xB3, 0xB3, ++0x03, 0x9B, 0x0F, 0x2B, 0x7D, 0xD8, 0x4F, 0xF0, 0x00, 0x08, 0xC7, 0xF1, 0x10, 0x03, 0x04, 0xF1, 0xFF, 0x3A, 0x05, 0x94, ++0xDF, 0xF8, 0x14, 0xB1, 0x44, 0x46, 0x98, 0x46, 0x04, 0xE0, 0x58, 0x46, 0x00, 0xF0, 0x9A, 0xFC, 0xA0, 0x45, 0x0C, 0xD0, ++0x1A, 0xEA, 0x04, 0x0F, 0x04, 0xF1, 0x01, 0x04, 0xF5, 0xD1, 0x20, 0x20, 0x00, 0xF0, 0x8E, 0xFC, 0x58, 0x46, 0x00, 0xF0, ++0x8D, 0xFC, 0xA0, 0x45, 0xF2, 0xD1, 0x34, 0x48, 0x05, 0x9C, 0x00, 0xF0, 0x87, 0xFC, 0x03, 0x9B, 0x00, 0x2B, 0x4D, 0xD0, ++0x4F, 0xF0, 0x00, 0x08, 0x15, 0xF8, 0x08, 0x00, 0xA0, 0xF1, 0x1F, 0x03, 0x5F, 0x2B, 0x88, 0xBF, 0x2E, 0x20, 0x08, 0xF1, ++0x01, 0x08, 0x00, 0xF0, 0x75, 0xFC, 0x47, 0x45, 0xF2, 0xD8, 0x35, 0x46, 0x29, 0x48, 0x00, 0xF0, 0x71, 0xFC, 0x03, 0x9B, ++0xDB, 0x1B, 0x03, 0x93, 0x8D, 0xD1, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x03, 0x9B, 0x8B, 0xB3, 0xDF, 0xF8, 0x84, 0xA0, ++0x4F, 0xF0, 0x00, 0x08, 0x09, 0xE0, 0xCD, 0xF8, 0x00, 0xC0, 0xE1, 0xF7, 0x8D, 0xF9, 0x08, 0xF1, 0x04, 0x08, 0x47, 0x45, ++0x05, 0xF1, 0x04, 0x05, 0x1A, 0xD9, 0x28, 0x46, 0xDD, 0xF7, 0xEE, 0xF9, 0x04, 0x2C, 0x06, 0x46, 0x4F, 0xEA, 0x10, 0x6C, ++0xC0, 0xF3, 0x07, 0x43, 0xC0, 0xF3, 0x07, 0x22, 0xC1, 0xB2, 0x48, 0x46, 0x0F, 0xD0, 0x02, 0x2C, 0xE5, 0xD1, 0x15, 0x48, ++0x32, 0x0C, 0xB1, 0xB2, 0x08, 0xF1, 0x04, 0x08, 0xE1, 0xF7, 0x70, 0xF9, 0x47, 0x45, 0x05, 0xF1, 0x04, 0x05, 0xE4, 0xD8, ++0x00, 0x23, 0x04, 0x93, 0xC6, 0xE7, 0x31, 0x46, 0x50, 0x46, 0xE1, 0xF7, 0x65, 0xF9, 0xD6, 0xE7, 0x0A, 0x48, 0x07, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0x00, 0xF0, 0x30, 0xBC, 0x04, 0x9B, 0x00, 0x2B, 0xB8, 0xD0, 0x2E, 0x46, 0x81, 0xE7, 0x04, 0x48, ++0x00, 0xF0, 0x28, 0xFC, 0xA2, 0xE7, 0x00, 0xBF, 0xE0, 0xB5, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0x1C, 0xB6, 0x15, 0x00, ++0xD0, 0x79, 0x15, 0x00, 0xE8, 0xB5, 0x15, 0x00, 0xF4, 0xB5, 0x15, 0x00, 0x14, 0xB6, 0x15, 0x00, 0x0C, 0xB6, 0x15, 0x00, ++0xD4, 0xB5, 0x15, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x22, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x22, 0x4C, 0x22, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0xFE, 0xF7, 0x1E, 0xF9, 0x20, 0x48, 0xFE, 0xF7, ++0x1B, 0xF9, 0x20, 0x49, 0x1D, 0x48, 0xFE, 0xF7, 0x1B, 0xF9, 0x1F, 0x49, 0x1B, 0x48, 0xFE, 0xF7, 0x17, 0xF9, 0x1E, 0x49, ++0x19, 0x48, 0xFE, 0xF7, 0x13, 0xF9, 0x1D, 0x49, 0x17, 0x48, 0xFE, 0xF7, 0x0F, 0xF9, 0x23, 0x68, 0x33, 0xB1, 0x13, 0x4A, ++0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x01, 0x22, ++0x00, 0xF0, 0xFC, 0xFB, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x04, 0x22, 0x00, 0xF0, 0xF6, 0xFB, 0x17, 0x4B, 0x18, 0x49, ++0x18, 0x48, 0x03, 0x22, 0x00, 0xF0, 0xF0, 0xFB, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x04, 0x22, 0x00, 0xF0, 0xEA, 0xFB, ++0xBD, 0xE8, 0x10, 0x40, 0x16, 0x4B, 0x17, 0x49, 0x17, 0x48, 0x02, 0x22, 0x00, 0xF0, 0xE2, 0xBB, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0xD8, 0xB8, 0x17, 0x00, 0xC0, 0xB7, 0x17, 0x00, 0xC8, 0xB7, 0x17, 0x00, 0x0C, 0xB8, 0x17, 0x00, ++0x50, 0xB8, 0x17, 0x00, 0x94, 0xB8, 0x17, 0x00, 0x69, 0x4D, 0x14, 0x00, 0x24, 0xB6, 0x15, 0x00, 0x30, 0xB6, 0x15, 0x00, ++0x61, 0x56, 0x14, 0x00, 0x38, 0xB6, 0x15, 0x00, 0x7C, 0xAB, 0x15, 0x00, 0x2D, 0x57, 0x14, 0x00, 0x4C, 0xB6, 0x15, 0x00, ++0x58, 0xB6, 0x15, 0x00, 0xED, 0x55, 0x14, 0x00, 0x5C, 0xB6, 0x15, 0x00, 0x68, 0xB6, 0x15, 0x00, 0x99, 0x57, 0x14, 0x00, ++0x6C, 0xB6, 0x15, 0x00, 0x7C, 0xB6, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x54, 0x4D, 0x55, 0x4E, 0x29, 0x68, 0x31, 0x60, ++0x17, 0x28, 0x04, 0x46, 0x10, 0xD8, 0x17, 0x28, 0x00, 0xF2, 0x8E, 0x80, 0xDF, 0xE8, 0x00, 0xF0, 0x15, 0x8C, 0x8C, 0x71, ++0x8C, 0x8C, 0x8C, 0x8C, 0x48, 0x8C, 0x1A, 0x8C, 0x8C, 0x1A, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x55, 0x8C, 0x60, ++0x7F, 0x28, 0x39, 0xD0, 0x49, 0x4F, 0x3B, 0x68, 0x3D, 0x2B, 0x65, 0xDD, 0x07, 0x20, 0x00, 0xF0, 0x75, 0xFB, 0x4F, 0xF0, ++0xFF, 0x34, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x44, 0x4E, 0x45, 0x48, 0x33, 0x68, 0xDF, 0xF8, 0x20, 0x81, 0x00, 0x22, ++0x1A, 0x70, 0x00, 0xF0, 0x69, 0xFB, 0x34, 0x68, 0xA4, 0xEB, 0x08, 0x04, 0x00, 0x2C, 0xEE, 0xDB, 0x0F, 0xD1, 0x3F, 0x48, ++0x00, 0xF0, 0x60, 0xFB, 0x00, 0x24, 0x3D, 0x48, 0x12, 0xF0, 0x70, 0xF9, 0x38, 0x4B, 0x28, 0x60, 0x00, 0x22, 0xC6, 0xF8, ++0x00, 0x80, 0x1A, 0x60, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x48, 0xFE, 0xF7, 0xB2, 0xF8, 0x07, 0x46, 0x00, 0x28, ++0x48, 0xD0, 0x41, 0x46, 0x04, 0x30, 0x12, 0xF0, 0xED, 0xF8, 0x34, 0x48, 0x39, 0x46, 0xFE, 0xF7, 0x63, 0xF8, 0xE4, 0xE7, ++0x2C, 0x4B, 0x2D, 0x4E, 0x1B, 0x68, 0x30, 0x68, 0x0B, 0xB1, 0xFF, 0xF7, 0xC9, 0xFD, 0x4F, 0xF0, 0xFF, 0x34, 0x30, 0x60, ++0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x27, 0x4A, 0x25, 0x4B, 0x2B, 0x49, 0x11, 0x60, 0x4F, 0xF0, 0xFF, 0x34, 0x00, 0x22, ++0x1A, 0x60, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x4F, 0x21, 0x4E, 0x3B, 0x68, 0x30, 0x68, 0x0B, 0xB9, 0xAE, 0xE7, ++0x29, 0x68, 0xFF, 0xF7, 0xAF, 0xFD, 0x3B, 0x68, 0x30, 0x60, 0x00, 0x2B, 0xA7, 0xDD, 0x03, 0x78, 0x20, 0x2B, 0xF5, 0xD1, ++0xA3, 0xE7, 0xDF, 0xF8, 0x78, 0x80, 0x18, 0x4E, 0x00, 0x23, 0x88, 0xF8, 0x00, 0x30, 0xB0, 0xE7, 0x01, 0x31, 0x20, 0x46, ++0x31, 0x60, 0x00, 0xF0, 0x0D, 0xFB, 0x13, 0x49, 0x0B, 0x68, 0x1C, 0x70, 0x3A, 0x68, 0x01, 0x33, 0x01, 0x32, 0x0B, 0x60, ++0x3A, 0x60, 0x4F, 0xF0, 0xFF, 0x34, 0x8E, 0xE7, 0x13, 0x48, 0x00, 0xF0, 0x01, 0xFB, 0xA0, 0xE7, 0x0A, 0x4F, 0x3B, 0x68, ++0x3D, 0x2B, 0x81, 0xDC, 0x09, 0x28, 0xE5, 0xD1, 0x0F, 0x48, 0x01, 0xF0, 0x07, 0x01, 0x08, 0x44, 0x00, 0xF0, 0xF4, 0xFA, ++0x33, 0x68, 0x23, 0xF0, 0x07, 0x03, 0x08, 0x33, 0x33, 0x60, 0xDE, 0xE7, 0x6C, 0x34, 0x17, 0x00, 0x24, 0x34, 0x17, 0x00, ++0x68, 0x34, 0x17, 0x00, 0xD4, 0x22, 0x17, 0x00, 0xD0, 0x79, 0x15, 0x00, 0xA0, 0xB6, 0x15, 0x00, 0xD8, 0xB8, 0x17, 0x00, ++0xC0, 0xB7, 0x17, 0x00, 0x28, 0x34, 0x17, 0x00, 0x84, 0xB6, 0x15, 0x00, 0x20, 0xB8, 0x15, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, ++0x2C, 0x68, 0x3F, 0x2C, 0x0D, 0xD8, 0x0B, 0x4F, 0x4F, 0xEA, 0x04, 0x1C, 0x07, 0xEB, 0x04, 0x16, 0x01, 0x34, 0x47, 0xF8, ++0x0C, 0x00, 0xC6, 0xE9, 0x01, 0x12, 0xF3, 0x60, 0x2C, 0x60, 0x00, 0x20, 0xF8, 0xBD, 0x05, 0x48, 0xE0, 0xF7, 0xF0, 0xFF, ++0x4F, 0xF0, 0xFF, 0x30, 0xF8, 0xBD, 0x00, 0xBF, 0x20, 0x30, 0x17, 0x00, 0x24, 0x30, 0x17, 0x00, 0xA8, 0xB6, 0x15, 0x00, ++0x2D, 0xE9, 0xF0, 0x4F, 0x95, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x76, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0xDF, 0xF8, 0xFC, 0xB1, 0x75, 0x48, 0xDB, 0xF8, 0x00, 0x30, 0x01, 0x33, 0xCB, 0xF8, 0x00, 0x30, 0xFE, 0xF7, ++0x05, 0xF8, 0xDB, 0xF8, 0x00, 0x30, 0x06, 0x46, 0x3B, 0xB1, 0x6E, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, ++0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x00, 0x2E, 0x00, 0xF0, 0x94, 0x80, 0x33, 0x1D, 0x03, 0xAC, 0x01, 0x22, 0x4F, 0xF0, ++0x00, 0x0C, 0x57, 0x1E, 0x3D, 0x46, 0x19, 0x46, 0x13, 0xF8, 0x01, 0x0B, 0x20, 0x28, 0xFA, 0xD0, 0x09, 0x28, 0xF8, 0xD0, ++0x00, 0x28, 0x00, 0xF0, 0xA0, 0x80, 0x22, 0x28, 0x00, 0xF0, 0x83, 0x80, 0x21, 0x60, 0x08, 0x78, 0x15, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0xAC, 0x80, 0x0B, 0x46, 0x06, 0xE0, 0x09, 0x28, 0x06, 0xD0, 0x13, 0xF8, 0x01, 0x0F, 0x00, 0x28, 0x00, 0xF0, ++0xA3, 0x80, 0x20, 0x28, 0xF6, 0xD1, 0x19, 0x78, 0x00, 0x29, 0x00, 0xF0, 0x9D, 0x80, 0x01, 0x32, 0x11, 0x2A, 0x03, 0xF8, ++0x01, 0xCB, 0x04, 0xF1, 0x04, 0x04, 0xD4, 0xD1, 0x52, 0x48, 0x10, 0x21, 0xE0, 0xF7, 0x8E, 0xFF, 0x10, 0x25, 0xDD, 0xF8, ++0x0C, 0x90, 0x2E, 0x21, 0x48, 0x46, 0x11, 0xF0, 0x95, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x83, 0x80, 0xA0, 0xEB, 0x09, 0x04, ++0x4B, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x28, 0xDD, 0x4A, 0x4F, 0x01, 0x95, 0x4F, 0xF0, 0x00, 0x08, 0xC2, 0x46, 0x3D, 0x46, ++0x05, 0xE0, 0x46, 0x4B, 0x1A, 0x68, 0x92, 0x45, 0x07, 0xF1, 0x10, 0x07, 0x16, 0xDA, 0x39, 0x68, 0x22, 0x46, 0x48, 0x46, ++0x0A, 0xF1, 0x01, 0x0A, 0x12, 0xF0, 0xBE, 0xF8, 0x00, 0x28, 0xF0, 0xD1, 0x38, 0x68, 0x12, 0xF0, 0x4B, 0xF8, 0x84, 0x42, ++0x43, 0xD0, 0x3C, 0x4B, 0x1A, 0x68, 0x92, 0x45, 0x3D, 0x46, 0x08, 0xF1, 0x01, 0x08, 0x07, 0xF1, 0x10, 0x07, 0xE8, 0xDB, ++0xB8, 0xF1, 0x01, 0x0F, 0x2B, 0x46, 0x01, 0x9D, 0x37, 0xD0, 0x03, 0x99, 0x36, 0x48, 0xE0, 0xF7, 0x51, 0xFF, 0x36, 0x48, ++0x00, 0xF0, 0x20, 0xFA, 0x35, 0x48, 0x00, 0xF0, 0x1D, 0xFA, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x2A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDB, 0xF8, 0x00, 0x30, 0x30, 0x48, 0x01, 0x33, 0x31, 0x46, 0xCB, 0xF8, 0x00, 0x30, ++0xFD, 0xF7, 0x2A, 0xFF, 0x25, 0x48, 0xFD, 0xF7, 0x6B, 0xFF, 0xDB, 0xF8, 0x00, 0x30, 0x06, 0x46, 0x00, 0x2B, 0x7F, 0xF4, ++0x64, 0xAF, 0x00, 0x2E, 0x7F, 0xF4, 0x6C, 0xAF, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0x1C, 0x23, 0x60, 0x49, 0x78, ++0x15, 0x46, 0x19, 0xB9, 0x28, 0xE0, 0x13, 0xF8, 0x01, 0x1F, 0x29, 0xB3, 0x22, 0x29, 0xFA, 0xD1, 0x81, 0xE7, 0x01, 0x9D, ++0x3B, 0x46, 0x9A, 0x68, 0xAA, 0x42, 0x24, 0xDB, 0xDB, 0x68, 0x00, 0x2B, 0xC8, 0xD0, 0x28, 0x46, 0x03, 0xA9, 0x98, 0x47, ++0x00, 0x28, 0xC3, 0xD0, 0xBF, 0xE7, 0x14, 0xAB, 0x03, 0xEB, 0x87, 0x03, 0x43, 0xF8, 0x44, 0x0C, 0x00, 0x2F, 0xB8, 0xD0, ++0xDD, 0xF8, 0x0C, 0x90, 0x2E, 0x21, 0x48, 0x46, 0x11, 0xF0, 0x12, 0xFF, 0x00, 0x28, 0x7F, 0xF4, 0x7D, 0xAF, 0x48, 0x46, ++0x11, 0xF0, 0xE4, 0xFF, 0x04, 0x46, 0x79, 0xE7, 0x14, 0xAB, 0x03, 0xEB, 0x82, 0x02, 0x00, 0x23, 0x42, 0xF8, 0x44, 0x3C, ++0x67, 0xE7, 0x59, 0x68, 0x0A, 0x48, 0xE0, 0xF7, 0xF1, 0xFE, 0x9E, 0xE7, 0x38, 0x61, 0x17, 0x00, 0xC0, 0xB7, 0x17, 0x00, ++0xC4, 0xB6, 0x15, 0x00, 0x20, 0x30, 0x17, 0x00, 0x24, 0x30, 0x17, 0x00, 0xE4, 0xB6, 0x15, 0x00, 0x08, 0xB7, 0x15, 0x00, ++0xA0, 0xB6, 0x15, 0x00, 0xD8, 0xB8, 0x17, 0x00, 0xFC, 0xB6, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF0, 0xB4, 0x05, 0x78, ++0x30, 0x2D, 0x2B, 0xD0, 0x00, 0x2A, 0x08, 0xBF, 0x0A, 0x22, 0x2D, 0x2D, 0x32, 0xD0, 0x00, 0x27, 0x00, 0x26, 0xA5, 0xF1, ++0x30, 0x03, 0x5F, 0xFA, 0x83, 0xFC, 0x25, 0xF0, 0x20, 0x04, 0xBC, 0xF1, 0x09, 0x0F, 0xA4, 0xF1, 0x41, 0x04, 0x12, 0xD9, ++0x05, 0x2C, 0x06, 0xD9, 0x07, 0xB1, 0x76, 0x42, 0x01, 0xB1, 0x08, 0x60, 0x30, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0xA5, 0xF1, ++0x61, 0x04, 0xA5, 0xF1, 0x20, 0x03, 0x19, 0x2C, 0xDB, 0xB2, 0x94, 0xBF, 0x37, 0x3B, 0xA5, 0xF1, 0x37, 0x03, 0x93, 0x42, ++0xEC, 0xD2, 0x10, 0xF8, 0x01, 0x5F, 0x02, 0xFB, 0x06, 0x36, 0xDA, 0xE7, 0x45, 0x78, 0x78, 0x2D, 0x00, 0xF1, 0x01, 0x03, ++0x0A, 0xD0, 0x18, 0x46, 0x00, 0x2A, 0xCE, 0xD1, 0x2D, 0x2D, 0x4F, 0xF0, 0x08, 0x02, 0xCC, 0xD1, 0x01, 0x27, 0x45, 0x78, ++0x38, 0x44, 0xC9, 0xE7, 0x84, 0x78, 0xA4, 0xF1, 0x30, 0x06, 0x09, 0x2E, 0x09, 0xD9, 0x24, 0xF0, 0x20, 0x06, 0x41, 0x3E, ++0x05, 0x2E, 0x04, 0xD9, 0x3A, 0xB9, 0x17, 0x46, 0x18, 0x46, 0x08, 0x22, 0xBA, 0xE7, 0x02, 0x30, 0x25, 0x46, 0x10, 0x22, ++0xB3, 0xE7, 0x18, 0x46, 0xB3, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x0A, 0x22, 0x0C, 0x46, 0x05, 0x46, 0x48, 0x68, 0x00, 0x21, ++0xFF, 0xF7, 0xA2, 0xFF, 0xC0, 0xB1, 0x01, 0x28, 0x10, 0xD1, 0x02, 0x2D, 0x1C, 0xDD, 0x10, 0x22, 0xA0, 0x68, 0x00, 0x21, ++0xFF, 0xF7, 0x98, 0xFF, 0x0E, 0x4B, 0x1B, 0x68, 0x01, 0x46, 0x19, 0x80, 0x0D, 0x48, 0x89, 0xB2, 0xFF, 0xF7, 0x34, 0xF8, ++0x00, 0x20, 0x38, 0xBD, 0x01, 0x46, 0x0B, 0x48, 0xFF, 0xF7, 0x2E, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x4B, 0x09, 0x48, ++0x1B, 0x68, 0x19, 0x88, 0xFF, 0xF7, 0x26, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x48, 0xFF, 0xF7, 0x21, 0xF8, 0x00, 0x20, ++0x38, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x2C, 0xB7, 0x15, 0x00, 0x50, 0xB7, 0x15, 0x00, 0x18, 0xB7, 0x15, 0x00, ++0x40, 0xB7, 0x15, 0x00, 0x01, 0x28, 0xF8, 0xB5, 0x2A, 0xDD, 0x0D, 0x46, 0x04, 0x46, 0x10, 0x22, 0x68, 0x68, 0x00, 0x21, ++0xFF, 0xF7, 0x66, 0xFF, 0x02, 0x2C, 0x06, 0x46, 0x0D, 0xD1, 0x03, 0x0E, 0x01, 0x2B, 0x22, 0xD0, 0x03, 0x0D, 0xB3, 0xF5, ++0xA0, 0x6F, 0x1E, 0xD0, 0x32, 0x68, 0x24, 0x48, 0x31, 0x46, 0xFE, 0xF7, 0xFB, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0x22, ++0xA8, 0x68, 0x11, 0x46, 0x00, 0xF0, 0x18, 0xF9, 0x03, 0x2C, 0x07, 0x46, 0x19, 0xD1, 0x04, 0x20, 0x01, 0x2F, 0x1C, 0xD0, ++0xC2, 0xB2, 0x39, 0x46, 0x30, 0x46, 0x00, 0x23, 0xFF, 0xF7, 0xFE, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x18, 0x48, 0xFE, 0xF7, ++0xE3, 0xFF, 0x01, 0x20, 0xF8, 0xBD, 0x30, 0x46, 0xDC, 0xF7, 0x7E, 0xFE, 0x31, 0x46, 0x02, 0x46, 0x12, 0x48, 0xFE, 0xF7, ++0xD9, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0x22, 0xE8, 0x68, 0x11, 0x46, 0xFF, 0xF7, 0x2E, 0xFF, 0xE0, 0xE7, 0x33, 0x0E, ++0x01, 0x2B, 0xEC, 0xD0, 0x33, 0x0D, 0xB3, 0xF5, 0xA0, 0x6F, 0xE8, 0xD0, 0x01, 0x28, 0x06, 0xD1, 0x32, 0x78, 0x0A, 0x48, ++0x31, 0x46, 0xFE, 0xF7, 0xC3, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x02, 0x28, 0xBE, 0xD1, 0x32, 0x88, 0x06, 0x48, 0x92, 0xB2, ++0x31, 0x46, 0xFE, 0xF7, 0xB9, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x7C, 0xB7, 0x15, 0x00, 0x64, 0xB7, 0x15, 0x00, ++0x90, 0xB7, 0x15, 0x00, 0xA4, 0xB7, 0x15, 0x00, 0x02, 0x28, 0x38, 0xB5, 0x21, 0xDD, 0x0D, 0x46, 0x10, 0x22, 0x68, 0x68, ++0x00, 0x21, 0xFF, 0xF7, 0x01, 0xFF, 0x10, 0x22, 0x04, 0x46, 0x00, 0x21, 0xA8, 0x68, 0xFF, 0xF7, 0xFB, 0xFE, 0x21, 0x46, ++0x02, 0x46, 0x05, 0x46, 0x0F, 0x48, 0xFE, 0xF7, 0x99, 0xFF, 0x23, 0x0E, 0x01, 0x2B, 0x06, 0xD0, 0x23, 0x0D, 0xB3, 0xF5, ++0xA0, 0x6F, 0x0D, 0xD0, 0x25, 0x60, 0x00, 0x20, 0x38, 0xBD, 0x20, 0x46, 0x29, 0x46, 0xDC, 0xF7, 0x53, 0xFE, 0x00, 0x20, ++0x38, 0xBD, 0x07, 0x48, 0xFE, 0xF7, 0x86, 0xFF, 0x01, 0x20, 0x38, 0xBD, 0xB4, 0xF1, 0xA0, 0x4F, 0xF1, 0xD1, 0x28, 0x46, ++0xDC, 0xF7, 0xF6, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x7C, 0xB7, 0x15, 0x00, 0xB8, 0xB7, 0x15, 0x00, 0x02, 0x28, 0x38, 0xB5, ++0x46, 0xDC, 0x01, 0x28, 0x32, 0xD0, 0x00, 0x22, 0x48, 0x68, 0x11, 0x46, 0xFF, 0xF7, 0xCA, 0xFE, 0x25, 0x4A, 0x26, 0x4B, ++0x02, 0xFB, 0x00, 0xF2, 0x9A, 0x42, 0x04, 0x46, 0x3E, 0xD8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, ++0x21, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x21, 0x4D, 0x21, 0x49, 0x2B, 0x68, 0x0A, 0x60, 0x01, 0x33, 0x2B, 0x60, 0x82, 0xB1, ++0x1F, 0x49, 0x09, 0x78, 0xF9, 0xB9, 0x33, 0xB1, 0x1A, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x1B, 0x48, 0x21, 0x46, 0xFE, 0xF7, 0x49, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, ++0xFC, 0xF7, 0xE8, 0xFF, 0x2B, 0x68, 0xEA, 0xE7, 0x12, 0x4A, 0x15, 0x4B, 0x11, 0x68, 0x15, 0x48, 0xA3, 0xFB, 0x01, 0x31, ++0x89, 0x0C, 0xFE, 0xF7, 0x37, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0xFC, 0xF7, 0x26, 0xFF, ++0x2B, 0x68, 0xD8, 0xE7, 0x0E, 0x48, 0xFE, 0xF7, 0x2B, 0xFF, 0x4F, 0xF0, 0xFF, 0x30, 0x38, 0xBD, 0x0C, 0x48, 0xFE, 0xF7, ++0x25, 0xFF, 0x4F, 0xF0, 0xFF, 0x30, 0x38, 0xBD, 0x40, 0x42, 0x0F, 0x00, 0xFF, 0xA2, 0xE1, 0x11, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x6C, 0x60, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0xF8, 0xB7, 0x15, 0x00, 0x83, 0xDE, 0x1B, 0x43, ++0xE8, 0xB7, 0x15, 0x00, 0xD0, 0xB7, 0x15, 0x00, 0x08, 0xB8, 0x15, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0x01, 0xE0, 0x04, 0x2A, ++0x05, 0xD0, 0x23, 0x68, 0x03, 0xF0, 0x0F, 0x02, 0xDB, 0x07, 0xF8, 0xD5, 0x10, 0xBD, 0xE0, 0xF7, 0x1D, 0xFC, 0xFF, 0xF7, ++0x6B, 0xFC, 0xF4, 0xE7, 0x08, 0x10, 0x04, 0x40, 0xE0, 0xF7, 0x0A, 0xBC, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x78, 0x28, 0xB1, ++0xE0, 0xF7, 0x04, 0xFC, 0x14, 0xF8, 0x01, 0x0F, 0x00, 0x28, 0xF9, 0xD1, 0x10, 0xBD, 0x00, 0xBF, 0x10, 0xB5, 0x04, 0x4C, ++0xD4, 0xF8, 0xB8, 0x30, 0x98, 0x47, 0xD4, 0xF8, 0x28, 0x33, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, ++0xFF, 0xF7, 0x2E, 0xBD, 0xFF, 0xF7, 0x0C, 0xBD, 0xFF, 0xF7, 0x36, 0xBE, 0x70, 0xB4, 0x02, 0x68, 0x1C, 0x4C, 0x2D, 0x21, ++0xA3, 0x89, 0x11, 0x70, 0x02, 0x68, 0x1A, 0x21, 0x51, 0x70, 0x23, 0xF0, 0x1C, 0x03, 0x02, 0x68, 0x9B, 0xB2, 0x43, 0xF0, ++0x0C, 0x03, 0x53, 0x80, 0xA3, 0x7B, 0x13, 0x71, 0x06, 0x68, 0x04, 0xF1, 0x0F, 0x03, 0x04, 0xF1, 0x1F, 0x05, 0x13, 0xF8, ++0x01, 0x1B, 0x1A, 0x1B, 0x32, 0x44, 0xAB, 0x42, 0x02, 0xF8, 0x0B, 0x1C, 0xF7, 0xD1, 0x01, 0x68, 0x0E, 0x4A, 0x00, 0x23, ++0xCB, 0x73, 0x01, 0x68, 0x0B, 0x74, 0x05, 0x68, 0x23, 0x8C, 0xA5, 0xF8, 0x15, 0x30, 0x05, 0xF1, 0x17, 0x03, 0x1B, 0x35, ++0x12, 0xF8, 0x01, 0x1B, 0x03, 0xF8, 0x01, 0x1B, 0xAB, 0x42, 0xF9, 0xD1, 0x03, 0x68, 0x94, 0xF8, 0x28, 0x20, 0xDA, 0x76, ++0x03, 0x68, 0x1C, 0x33, 0x03, 0x60, 0x70, 0xBC, 0x1C, 0x20, 0x70, 0x47, 0xE4, 0xB8, 0x17, 0x00, 0x08, 0xB9, 0x17, 0x00, ++0x03, 0x68, 0x28, 0x4A, 0xFF, 0x21, 0x70, 0xB4, 0x19, 0x70, 0x03, 0x68, 0x23, 0x21, 0x99, 0x70, 0x05, 0x68, 0xEB, 0x1C, ++0x05, 0xF1, 0x09, 0x04, 0x12, 0xF8, 0x01, 0x1F, 0x03, 0xF8, 0x01, 0x1B, 0xA3, 0x42, 0xF9, 0xD1, 0x20, 0x4A, 0xA2, 0xF1, ++0x41, 0x01, 0x02, 0xF1, 0x0B, 0x06, 0xA2, 0xF1, 0x38, 0x03, 0x12, 0xF8, 0x01, 0x4F, 0x5B, 0x1A, 0xB2, 0x42, 0x5C, 0x55, ++0xF7, 0xD1, 0x91, 0xF8, 0x42, 0x30, 0xB1, 0xF8, 0x50, 0x40, 0xB1, 0xF8, 0x4E, 0x20, 0xEC, 0x82, 0x1C, 0x07, 0xAA, 0x82, ++0x05, 0xF1, 0x18, 0x06, 0x4F, 0xEA, 0x63, 0x02, 0x07, 0xD5, 0xB1, 0xF8, 0x52, 0x40, 0xB1, 0xF8, 0x54, 0x30, 0x6B, 0x83, ++0x2C, 0x83, 0x05, 0xF1, 0x1C, 0x06, 0x13, 0x07, 0x04, 0xD5, 0xB1, 0xF8, 0x56, 0x30, 0x33, 0x80, 0x73, 0x80, 0x04, 0x36, ++0x0C, 0x4C, 0x32, 0x46, 0x14, 0xF8, 0x01, 0x5F, 0x15, 0x70, 0x91, 0xF8, 0x75, 0x51, 0x93, 0x1B, 0x9D, 0x42, 0x02, 0xF1, ++0x01, 0x02, 0xF5, 0xDA, 0x03, 0x68, 0xD2, 0x1A, 0x91, 0x1E, 0x59, 0x70, 0x03, 0x68, 0x13, 0x44, 0x03, 0x60, 0x70, 0xBC, ++0x10, 0x46, 0x70, 0x47, 0x1F, 0xB9, 0x17, 0x00, 0x25, 0xB9, 0x17, 0x00, 0x3D, 0xB9, 0x17, 0x00, 0x70, 0xB4, 0x0F, 0x4C, ++0x03, 0x46, 0x22, 0x6B, 0x09, 0xB1, 0x22, 0xF4, 0xC0, 0x52, 0x19, 0x68, 0xBF, 0x20, 0x08, 0x70, 0x19, 0x68, 0x0C, 0x20, ++0x48, 0x70, 0x18, 0x68, 0xA1, 0x8E, 0xC0, 0xF8, 0x02, 0x20, 0x1A, 0x68, 0x60, 0x8F, 0xE6, 0x8E, 0x25, 0x8F, 0xD1, 0x80, ++0x02, 0xF1, 0x0E, 0x01, 0x16, 0x81, 0x55, 0x81, 0x90, 0x81, 0x70, 0xBC, 0x0E, 0x20, 0x19, 0x60, 0x70, 0x47, 0x00, 0xBF, ++0xE4, 0xB8, 0x17, 0x00, 0x03, 0x68, 0x10, 0xB4, 0xC7, 0x24, 0x1C, 0x70, 0x03, 0x68, 0x01, 0x24, 0x5C, 0x70, 0x03, 0x68, ++0x42, 0xEA, 0x01, 0x11, 0x99, 0x70, 0x03, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x03, 0x33, 0x03, 0x60, 0x03, 0x20, 0x70, 0x47, ++0x03, 0x68, 0x46, 0x22, 0x1A, 0x70, 0x03, 0x68, 0x05, 0x22, 0x5A, 0x70, 0x03, 0x68, 0x70, 0x22, 0x9A, 0x70, 0x02, 0x68, ++0x00, 0x23, 0xD3, 0x70, 0x02, 0x68, 0x13, 0x71, 0x02, 0x68, 0x53, 0x71, 0x02, 0x68, 0x93, 0x71, 0x03, 0x68, 0x07, 0x33, ++0x03, 0x60, 0x07, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x30, 0xB4, 0x02, 0x9C, 0x01, 0x80, 0x42, 0x80, 0x83, 0x80, 0x84, 0xB1, ++0x10, 0x22, 0x80, 0x23, 0x82, 0x71, 0xC3, 0x71, 0xE5, 0x18, 0x22, 0x46, 0x13, 0x46, 0x08, 0x33, 0x12, 0xF8, 0x01, 0x1B, ++0x1B, 0x1B, 0xAA, 0x42, 0x19, 0x54, 0xF7, 0xD1, 0x88, 0x20, 0x30, 0xBC, 0x70, 0x47, 0x06, 0x20, 0x30, 0xBC, 0x70, 0x47, ++0x01, 0x80, 0x02, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x8F, 0xB0, 0x1F, 0x46, 0x1A, 0x9E, 0x03, 0x93, ++0x34, 0x8F, 0xB6, 0xF8, 0x36, 0x80, 0x0D, 0x46, 0x03, 0x46, 0x01, 0x2C, 0x38, 0x46, 0x38, 0xBF, 0x01, 0x24, 0x07, 0x93, ++0x17, 0x46, 0x01, 0xF0, 0xC1, 0xFE, 0xB5, 0xF8, 0xAE, 0x90, 0x07, 0x9B, 0x09, 0xF0, 0x10, 0x09, 0x40, 0xEA, 0x09, 0x00, ++0x06, 0xF1, 0x40, 0x02, 0x5C, 0x80, 0x02, 0x92, 0x18, 0x80, 0x1F, 0xFA, 0x80, 0xF9, 0x14, 0x46, 0x00, 0x2F, 0x00, 0xF0, ++0xDE, 0x81, 0x3A, 0x88, 0x9A, 0x80, 0x7A, 0x88, 0xDA, 0x80, 0xBA, 0x88, 0x1A, 0x81, 0x0A, 0x22, 0x17, 0x46, 0x18, 0x99, ++0x98, 0x18, 0x08, 0x60, 0x00, 0x21, 0x07, 0x90, 0x95, 0xF8, 0x7E, 0x00, 0x99, 0x54, 0x07, 0x9B, 0x00, 0xF1, 0x02, 0x0E, ++0x58, 0x70, 0x00, 0x28, 0x40, 0xF0, 0xC7, 0x80, 0x07, 0x9B, 0x95, 0xF8, 0xB0, 0x10, 0x0E, 0xEB, 0x03, 0x00, 0x01, 0x22, ++0x07, 0x90, 0x0E, 0xF8, 0x03, 0x20, 0x07, 0x9B, 0x08, 0x29, 0x8C, 0x46, 0x28, 0xBF, 0x4F, 0xF0, 0x08, 0x0C, 0x83, 0xF8, ++0x01, 0xC0, 0x07, 0x9B, 0x1F, 0xFA, 0x8E, 0xFE, 0x0C, 0xF1, 0x02, 0x0A, 0x05, 0xF1, 0xB1, 0x02, 0x51, 0xB1, 0x0C, 0xF1, ++0xB1, 0x0C, 0xAC, 0x44, 0x12, 0xF8, 0x01, 0x0B, 0xD1, 0x18, 0x49, 0x1B, 0x94, 0x45, 0x01, 0xF8, 0xB0, 0x0C, 0xF7, 0xD1, ++0x95, 0xF8, 0xB0, 0x20, 0xD6, 0x44, 0x0A, 0xEB, 0x03, 0x01, 0x08, 0x2A, 0x77, 0x44, 0x07, 0x91, 0x1A, 0xD9, 0x32, 0x21, ++0x0A, 0xF8, 0x03, 0x10, 0x07, 0x9B, 0xA2, 0xF1, 0x08, 0x01, 0x59, 0x70, 0x02, 0xF1, 0xB1, 0x0C, 0x07, 0x9B, 0xA2, 0xF1, ++0x06, 0x0E, 0xAC, 0x44, 0x05, 0xF1, 0xB9, 0x02, 0x12, 0xF8, 0x01, 0x0B, 0xD1, 0x18, 0x49, 0x1B, 0x94, 0x45, 0x01, 0xF8, ++0xB8, 0x0C, 0xF7, 0xD1, 0x73, 0x44, 0x77, 0x44, 0x07, 0x93, 0xBF, 0xB2, 0x19, 0xF4, 0x80, 0x7F, 0x40, 0xF0, 0xB5, 0x80, ++0x07, 0xA8, 0xFF, 0xF7, 0x3F, 0xFF, 0x47, 0x44, 0x07, 0x9B, 0x80, 0xB2, 0xBF, 0xB2, 0xB8, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, ++0x02, 0x9A, 0x42, 0x44, 0x94, 0x46, 0x14, 0xF8, 0x01, 0x1B, 0xE2, 0x18, 0x92, 0x1B, 0x64, 0x45, 0x02, 0xF8, 0x41, 0x1C, ++0xF7, 0xD1, 0xD5, 0xF8, 0xE0, 0x40, 0x07, 0x44, 0x43, 0x44, 0xE2, 0x07, 0xBF, 0xB2, 0x07, 0x93, 0x1A, 0xD5, 0xB4, 0x4A, ++0x07, 0xCA, 0x0A, 0xAE, 0x03, 0xC6, 0x00, 0x20, 0x0A, 0xA9, 0x32, 0x80, 0xAD, 0xF8, 0x36, 0x00, 0xCD, 0xF8, 0x32, 0x00, ++0x8D, 0xF8, 0x30, 0x00, 0x5B, 0x1A, 0x0C, 0xA8, 0xDD, 0x22, 0x01, 0xE0, 0x11, 0xF8, 0x01, 0x2F, 0x5A, 0x54, 0x88, 0x42, ++0xFA, 0xD1, 0x07, 0x9B, 0x09, 0x37, 0x09, 0x33, 0xBF, 0xB2, 0x07, 0x93, 0xA6, 0x07, 0x04, 0xD5, 0xA6, 0x4B, 0x93, 0xF8, ++0x76, 0x31, 0xDC, 0x07, 0x53, 0xD4, 0xA5, 0x4B, 0x9B, 0x7D, 0x01, 0x2B, 0x5A, 0xD0, 0xD5, 0xF8, 0xE0, 0x30, 0x18, 0x07, ++0x04, 0xD5, 0xA0, 0x4A, 0x92, 0xF8, 0x76, 0x21, 0x51, 0x07, 0x3C, 0xD4, 0x5A, 0x07, 0x22, 0xD5, 0x9C, 0x4D, 0x95, 0xF8, ++0x76, 0x31, 0x9B, 0x07, 0x1D, 0xD5, 0x03, 0x99, 0x9B, 0x4B, 0x9C, 0x4C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x33, ++0x07, 0xA8, 0x93, 0xF8, 0xC0, 0x14, 0xD4, 0xF8, 0x50, 0x21, 0x90, 0x47, 0x07, 0x44, 0x28, 0x8F, 0xD4, 0xF8, 0x4C, 0x61, ++0x01, 0xF0, 0x9A, 0xFC, 0x95, 0xF8, 0x75, 0x21, 0x04, 0x2A, 0x01, 0x46, 0x08, 0xBF, 0x03, 0x22, 0x07, 0xA8, 0xB0, 0x47, ++0xBF, 0xB2, 0x38, 0x44, 0x87, 0xB2, 0x18, 0x9B, 0x1A, 0x68, 0x07, 0x9B, 0x9B, 0x1A, 0x19, 0x9A, 0x38, 0x46, 0x13, 0x80, ++0x0F, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x7F, 0x30, 0x07, 0x9B, 0x28, 0x44, 0x05, 0xF1, 0x7F, 0x02, 0x12, 0xF8, 0x01, 0xCB, ++0xD1, 0x18, 0x49, 0x1B, 0x90, 0x42, 0x01, 0xF8, 0x7E, 0xCC, 0xF7, 0xD1, 0x2B, 0xE7, 0x82, 0x4B, 0x07, 0xA8, 0xD3, 0xF8, ++0x44, 0x31, 0x98, 0x47, 0x38, 0x44, 0xD5, 0xF8, 0xE0, 0x30, 0x87, 0xB2, 0xB8, 0xE7, 0x7D, 0x4B, 0x07, 0xA8, 0xD3, 0xF8, ++0x48, 0x31, 0x98, 0x47, 0x78, 0x4B, 0x9B, 0x7D, 0x38, 0x44, 0x01, 0x2B, 0x87, 0xB2, 0xA4, 0xD1, 0xB5, 0xF8, 0xE4, 0x30, ++0x00, 0x2B, 0xA0, 0xD0, 0x07, 0x9B, 0x36, 0x22, 0x1A, 0x70, 0x07, 0x9B, 0x03, 0x22, 0x5A, 0x70, 0x07, 0x9B, 0xB5, 0xF8, ++0xE4, 0x20, 0x5A, 0x80, 0x95, 0xF8, 0xE6, 0x20, 0x1A, 0x71, 0x07, 0x9B, 0x05, 0x37, 0x05, 0x33, 0xBF, 0xB2, 0x07, 0x93, ++0x8D, 0xE7, 0x07, 0x9B, 0x21, 0x22, 0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x02, 0x22, 0x59, 0x1C, 0x07, 0x91, ++0x0A, 0xA8, 0x1A, 0x70, 0x0D, 0xF1, 0x27, 0x01, 0xDB, 0xF7, 0x8E, 0xFE, 0xD5, 0xF8, 0xA4, 0x30, 0x9D, 0xF9, 0x28, 0x20, ++0x93, 0xF9, 0x04, 0x30, 0x9A, 0x42, 0xC8, 0xBF, 0x8D, 0xF8, 0x28, 0x30, 0x07, 0x9B, 0x9D, 0xF8, 0x27, 0x20, 0x59, 0x1C, ++0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x9D, 0xF8, 0x28, 0x20, 0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x24, 0x22, ++0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x04, 0x93, 0x1A, 0x46, 0x02, 0xF1, 0x01, 0x0B, 0xD5, 0xF8, 0xA4, 0x30, ++0xCD, 0xF8, 0x1C, 0xB0, 0x9B, 0x78, 0x4F, 0x4A, 0x00, 0x2B, 0x52, 0xD1, 0x01, 0x23, 0x92, 0xF8, 0x72, 0xA1, 0x05, 0x93, ++0x76, 0x32, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x8C, 0x80, 0x00, 0x21, 0x06, 0x95, 0x01, 0x91, 0x08, 0x46, 0x8E, 0x46, ++0xA1, 0x46, 0x0D, 0x46, 0x1A, 0x96, 0xD3, 0x78, 0x13, 0xF0, 0x02, 0x03, 0x1F, 0xD1, 0x94, 0x78, 0xB2, 0xF8, 0x00, 0xC0, ++0x00, 0x2C, 0x43, 0xD1, 0xAC, 0xF6, 0x6C, 0x14, 0x48, 0x2C, 0x3A, 0xD8, 0x40, 0xF6, 0xB4, 0x13, 0x9C, 0x45, 0x6F, 0xD0, ++0x40, 0x4C, 0xAC, 0xF6, 0x67, 0x13, 0xA4, 0xFB, 0x03, 0x43, 0x9C, 0x08, 0xC3, 0xF3, 0x87, 0x03, 0x00, 0x28, 0x45, 0xD0, ++0xA4, 0xEB, 0x0E, 0x0E, 0x05, 0x9C, 0xA6, 0x45, 0x44, 0xD1, 0x01, 0x30, 0xC0, 0xB2, 0x9E, 0x46, 0x06, 0x32, 0x01, 0x31, ++0xCB, 0xB2, 0x9A, 0x45, 0xD7, 0xD8, 0x01, 0x9B, 0x1A, 0x9E, 0x03, 0xF1, 0x02, 0x0E, 0x29, 0x46, 0x5F, 0xFA, 0x8E, 0xF3, ++0x06, 0x9D, 0x4C, 0x46, 0x9E, 0x46, 0x0B, 0xF1, 0x01, 0x02, 0x07, 0x92, 0x8B, 0xF8, 0x00, 0x10, 0x07, 0x9A, 0x51, 0x1C, ++0x07, 0x91, 0x06, 0x37, 0x10, 0x70, 0x04, 0x9A, 0x1E, 0xFA, 0x87, 0xF7, 0xBF, 0xB2, 0x13, 0x70, 0xC0, 0xE6, 0x04, 0x23, ++0x92, 0xF8, 0x73, 0xA1, 0x05, 0x93, 0xCA, 0x32, 0xAB, 0xE7, 0xD8, 0xB9, 0x86, 0x46, 0x05, 0x46, 0x01, 0x20, 0xD5, 0xE7, ++0x01, 0x2C, 0xF8, 0xD1, 0xAC, 0xF5, 0x9C, 0x5C, 0xAC, 0xF1, 0x0D, 0x04, 0xA4, 0xB2, 0xB4, 0xF5, 0x4D, 0x7F, 0xF0, 0xD8, ++0x1D, 0x4B, 0xAC, 0xF1, 0x08, 0x0C, 0xA3, 0xFB, 0x0C, 0x43, 0x9C, 0x08, 0xC3, 0xF3, 0x87, 0x03, 0x00, 0x28, 0xB9, 0xD1, ++0x9E, 0x46, 0x1D, 0x46, 0x01, 0x20, 0xBD, 0xE7, 0x0B, 0xF1, 0x01, 0x04, 0x07, 0x94, 0x8B, 0xF8, 0x00, 0x50, 0x07, 0x9C, ++0x01, 0x9E, 0x04, 0xF1, 0x01, 0x0C, 0x06, 0xF1, 0x02, 0x0E, 0xCD, 0xF8, 0x1C, 0xC0, 0x00, 0xF1, 0x02, 0x0C, 0x20, 0x70, ++0x5F, 0xFA, 0x8E, 0xF0, 0x01, 0x90, 0xDD, 0xF8, 0x1C, 0xB0, 0x9E, 0x46, 0x5F, 0xFA, 0x8C, 0xF0, 0xA4, 0xE7, 0x04, 0x22, ++0x17, 0x46, 0x26, 0xE6, 0x0E, 0x23, 0x1C, 0x46, 0x94, 0xE7, 0x02, 0x23, 0x50, 0x46, 0x51, 0x46, 0x9E, 0x46, 0xA8, 0xE7, ++0x2C, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xCD, 0xCC, 0xCC, 0xCC, 0x03, 0x22, 0x00, 0x23, 0x30, 0xB4, 0x02, 0x70, 0x43, 0x70, 0x4B, 0x7C, 0x83, 0x70, 0x0B, 0x7C, ++0x8C, 0x7B, 0xCA, 0x7B, 0x4D, 0x89, 0xA0, 0xF8, 0x05, 0x50, 0x9B, 0x00, 0x43, 0xEA, 0x44, 0x03, 0x43, 0xEA, 0x82, 0x13, ++0xA0, 0xF8, 0x03, 0x30, 0x0B, 0x89, 0x1B, 0x01, 0xA0, 0xF8, 0x07, 0x30, 0x30, 0xBC, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, ++0x30, 0xB4, 0x22, 0xF0, 0x01, 0x02, 0xBD, 0xF8, 0x08, 0x40, 0xA0, 0xF8, 0x05, 0x20, 0x03, 0x25, 0x01, 0x22, 0xA0, 0xF8, ++0x03, 0x40, 0x83, 0x70, 0x05, 0x70, 0x42, 0x70, 0x2C, 0xB1, 0x00, 0x23, 0xC3, 0x71, 0x03, 0x72, 0x30, 0xBC, 0x09, 0x20, ++0x70, 0x47, 0x4B, 0x89, 0xA0, 0xF8, 0x07, 0x30, 0x30, 0xBC, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x10, 0xB4, 0x02, 0x23, ++0x03, 0x24, 0x04, 0x70, 0x43, 0x70, 0x0B, 0x7C, 0x49, 0x7B, 0x5D, 0xF8, 0x04, 0x4B, 0x82, 0x80, 0x1B, 0x03, 0x9B, 0xB2, ++0x01, 0x29, 0x08, 0xBF, 0x43, 0xF4, 0x00, 0x63, 0x43, 0x80, 0x06, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, ++0x82, 0xB0, 0x16, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0x07, 0x46, 0x88, 0x46, 0xFD, 0xF7, 0x7A, 0xFB, 0xA8, 0xB3, 0x9D, 0xF8, ++0x07, 0x40, 0x83, 0x1C, 0x7C, 0xB1, 0x02, 0x34, 0x20, 0x44, 0x00, 0x24, 0x1D, 0x78, 0x25, 0xF0, 0x81, 0x02, 0x7E, 0x2A, ++0x03, 0xF1, 0x01, 0x03, 0x03, 0xD0, 0x32, 0x19, 0x01, 0x34, 0x55, 0x70, 0xE4, 0xB2, 0x98, 0x42, 0xF2, 0xD1, 0x0D, 0xF1, ++0x07, 0x02, 0x41, 0x46, 0x38, 0x46, 0xFD, 0xF7, 0x7F, 0xFB, 0xB0, 0xB1, 0x9D, 0xF8, 0x07, 0x30, 0x81, 0x1C, 0x93, 0xB1, ++0x02, 0x33, 0x1F, 0x18, 0x0A, 0x78, 0x22, 0xF0, 0x81, 0x00, 0x63, 0x1C, 0x7E, 0x28, 0x06, 0xEB, 0x04, 0x05, 0x01, 0xF1, ++0x01, 0x01, 0xDB, 0xB2, 0x03, 0xD0, 0x0B, 0x2B, 0x6A, 0x70, 0x1C, 0x46, 0x01, 0xD8, 0x8F, 0x42, 0xEE, 0xD1, 0x34, 0x70, ++0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x04, 0x46, 0x34, 0x70, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x10, 0xB5, 0x14, 0x46, ++0xFD, 0xF7, 0xE8, 0xFC, 0x00, 0xB1, 0x80, 0x78, 0x84, 0xF8, 0xDA, 0x00, 0x10, 0xBD, 0x00, 0xBF, 0xF0, 0xB5, 0x83, 0xB0, ++0x14, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0xFD, 0xF7, 0x8B, 0xFB, 0x60, 0xB3, 0xD4, 0xF8, 0xA4, 0xE0, 0x9E, 0xF8, 0x02, 0x40, ++0x4C, 0xB3, 0x01, 0x2C, 0xBE, 0xF8, 0x00, 0x30, 0x40, 0xD0, 0x00, 0x24, 0x04, 0x25, 0x9D, 0xF8, 0x07, 0x70, 0x02, 0x37, ++0xFF, 0xB2, 0x08, 0x2F, 0x8D, 0xF8, 0x07, 0x70, 0x19, 0xD9, 0x05, 0x26, 0x06, 0xEB, 0x00, 0x0C, 0x33, 0x5C, 0x9C, 0xF8, ++0x01, 0x10, 0x69, 0xB1, 0x9C, 0x42, 0x25, 0xD0, 0x01, 0x39, 0xC9, 0xB2, 0x00, 0x22, 0x01, 0xE0, 0x9C, 0x42, 0x1F, 0xD0, ++0x2B, 0x44, 0x8A, 0x42, 0xDB, 0xB2, 0x02, 0xF1, 0x01, 0x02, 0xF7, 0xD1, 0x03, 0x36, 0xF6, 0xB2, 0xF3, 0x1C, 0x9F, 0x42, ++0xE6, 0xDC, 0x03, 0xB0, 0xF0, 0xBD, 0xBE, 0xF8, 0x00, 0x30, 0xA3, 0xF6, 0x6C, 0x12, 0x48, 0x2A, 0x12, 0xD8, 0x40, 0xF6, ++0xB4, 0x12, 0x93, 0x42, 0x20, 0xD0, 0x12, 0x4A, 0xA3, 0xF6, 0x67, 0x14, 0xA2, 0xFB, 0x04, 0x34, 0xC4, 0xF3, 0x87, 0x04, ++0x01, 0x25, 0xC8, 0xE7, 0x9C, 0xF8, 0x02, 0x30, 0x8E, 0xF8, 0x04, 0x30, 0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x25, 0xC0, 0xE7, ++0xA3, 0xF5, 0x9C, 0x53, 0xA3, 0xF1, 0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, 0x4D, 0x7F, 0xB6, 0xD8, 0x05, 0x4C, 0x08, 0x3B, ++0xA4, 0xFB, 0x03, 0x34, 0xC4, 0xF3, 0x87, 0x04, 0x04, 0x25, 0xB0, 0xE7, 0x0E, 0x24, 0x01, 0x25, 0xAD, 0xE7, 0x00, 0xBF, ++0xCD, 0xCC, 0xCC, 0xCC, 0x10, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0x96, 0xFC, 0x48, 0xB1, 0x83, 0x78, 0xC2, 0x78, 0x43, 0xEA, ++0x02, 0x23, 0xA4, 0xF8, 0xE4, 0x30, 0x03, 0x79, 0x84, 0xF8, 0xE6, 0x30, 0x10, 0xBD, 0x84, 0xF8, 0xE6, 0x00, 0xA4, 0xF8, ++0xE4, 0x00, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x82, 0xB0, 0x1C, 0x46, 0x05, 0x46, 0x0E, 0x46, 0x91, 0x46, 0xFD, 0xF7, ++0x49, 0xFB, 0x31, 0x46, 0x07, 0x46, 0x28, 0x46, 0xFD, 0xF7, 0x64, 0xFB, 0x57, 0xEA, 0x00, 0x03, 0x72, 0xD0, 0x80, 0x46, ++0x0D, 0xF1, 0x07, 0x02, 0x31, 0x46, 0x28, 0x46, 0xFD, 0xF7, 0x7A, 0xFB, 0x82, 0x46, 0x18, 0xB1, 0x9D, 0xF8, 0x07, 0x30, ++0x00, 0x2B, 0x65, 0xD0, 0x31, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0x28, 0x46, 0xFD, 0xF7, 0x90, 0xFB, 0x01, 0x46, 0x00, 0x28, ++0x58, 0xD1, 0x00, 0x2F, 0x7A, 0xD0, 0xBB, 0x78, 0x38, 0x79, 0x89, 0xF8, 0x00, 0x30, 0x97, 0xF8, 0x03, 0xC0, 0x00, 0x28, ++0x08, 0xBF, 0x02, 0x20, 0xBC, 0xF1, 0x0E, 0x0F, 0x0C, 0xF1, 0xFF, 0x33, 0x8C, 0xBF, 0x01, 0x27, 0x00, 0x27, 0x4D, 0xD8, ++0x0D, 0x2B, 0x70, 0xD8, 0xBC, 0xF1, 0x0E, 0x0F, 0x00, 0xF0, 0x97, 0x80, 0x0C, 0xEB, 0x8C, 0x06, 0x06, 0xF6, 0x67, 0x16, ++0x00, 0x29, 0x4A, 0xD0, 0x8D, 0x78, 0xCA, 0x78, 0x91, 0xF8, 0x04, 0xE0, 0x05, 0xF1, 0xFF, 0x38, 0xB8, 0xF1, 0x02, 0x0F, ++0x9A, 0xBF, 0x01, 0x35, 0xED, 0xB2, 0x01, 0x25, 0xBC, 0xF1, 0x0E, 0x0F, 0x93, 0xB2, 0x1F, 0xFA, 0x8E, 0xF1, 0x57, 0xD8, ++0x02, 0xF1, 0xFF, 0x3C, 0xBC, 0xF1, 0x0D, 0x0F, 0x72, 0xD8, 0x0E, 0x2A, 0x00, 0xF0, 0x90, 0x80, 0x03, 0xEB, 0x83, 0x03, ++0x03, 0xF6, 0x67, 0x13, 0x61, 0xB1, 0x0E, 0xF1, 0xFF, 0x32, 0x0D, 0x2A, 0x60, 0xD8, 0xBE, 0xF1, 0x0E, 0x0F, 0x00, 0xF0, ++0x9A, 0x80, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF6, 0x67, 0x11, 0x89, 0xB2, 0x4B, 0x4A, 0x92, 0xF8, 0x75, 0x21, 0xAA, 0x42, ++0x24, 0xD2, 0x01, 0x2A, 0x67, 0xD0, 0x02, 0x2A, 0x5E, 0xD0, 0x00, 0x2A, 0x08, 0xBF, 0x33, 0x46, 0x15, 0x46, 0x1B, 0xE0, ++0x9D, 0xF8, 0x07, 0x30, 0x00, 0x2B, 0xA2, 0xD1, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xA4, 0x2B, 0x22, 0xD8, ++0x0C, 0xEB, 0x8C, 0x06, 0x06, 0xF5, 0x9C, 0x56, 0x08, 0x36, 0x00, 0x29, 0xB4, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x31, 0xD0, ++0x9A, 0xF8, 0x02, 0x50, 0x01, 0x2D, 0x3A, 0xD0, 0x03, 0x2D, 0x50, 0xD0, 0x0D, 0x46, 0x33, 0x46, 0x27, 0x70, 0x65, 0x70, ++0x66, 0x80, 0xA3, 0x80, 0xE1, 0x80, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x98, 0xF8, 0x02, 0x30, 0x98, 0xF8, 0x05, 0x00, ++0x89, 0xF8, 0x00, 0x30, 0x98, 0xF8, 0x04, 0xC0, 0x81, 0xE7, 0x4F, 0xF6, 0xFF, 0x76, 0x93, 0xE7, 0x01, 0x3A, 0xA4, 0x2A, ++0x19, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x53, 0x08, 0x33, 0x00, 0x29, 0xB7, 0xD0, 0x0E, 0xF1, 0xFF, 0x3E, ++0xBE, 0xF1, 0xA4, 0x0F, 0x0A, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, 0x9C, 0x51, 0x08, 0x31, 0x89, 0xB2, 0xAB, 0xE7, ++0x51, 0x46, 0x55, 0x46, 0x33, 0x46, 0xD1, 0xE7, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xE7, 0x4F, 0xF6, 0xFF, 0x73, 0xE7, 0xE7, ++0x4F, 0xF6, 0xFF, 0x73, 0x90, 0xE7, 0x06, 0xF1, 0x0A, 0x03, 0x9B, 0xB2, 0xC4, 0xE7, 0x40, 0xF6, 0xB4, 0x16, 0x69, 0xE7, ++0x9E, 0x42, 0x94, 0xBF, 0x28, 0x3B, 0x28, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0xBA, 0xE7, 0x02, 0x2D, 0x0F, 0xD0, 0x03, 0xF1, ++0x28, 0x05, 0xB5, 0x42, 0x15, 0xDA, 0x3C, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0xB0, 0xE7, 0xA6, 0xF1, 0x0A, 0x03, 0x9B, 0xB2, ++0x01, 0x25, 0xAB, 0xE7, 0x40, 0xF6, 0xB4, 0x13, 0x70, 0xE7, 0x9E, 0x42, 0x03, 0xD8, 0x14, 0x3B, 0x9B, 0xB2, 0x15, 0x46, ++0xA2, 0xE7, 0x14, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0x9E, 0xE7, 0x9E, 0x42, 0xF9, 0xD8, 0xA3, 0xF1, 0x27, 0x05, 0xAE, 0x42, ++0xF1, 0xDA, 0x3C, 0x3B, 0x9B, 0xB2, 0x15, 0x46, 0x94, 0xE7, 0x40, 0xF6, 0xB4, 0x11, 0x67, 0xE7, 0xE4, 0xB8, 0x17, 0x00, ++0x70, 0xB5, 0x1D, 0x46, 0x14, 0x46, 0xFD, 0xF7, 0x95, 0xFB, 0x00, 0x23, 0x2B, 0x70, 0x00, 0x28, 0x48, 0xD0, 0x02, 0x7A, ++0xA1, 0x7C, 0x02, 0xF0, 0x0F, 0x03, 0x99, 0x42, 0x40, 0xD0, 0x01, 0x21, 0x29, 0x70, 0xA3, 0x74, 0x22, 0x74, 0xD0, 0xF8, ++0x0A, 0x20, 0x13, 0x0A, 0xD1, 0x08, 0x02, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x03, 0x12, 0x04, 0xBF, 0x40, 0xF6, 0x43, 0x23, ++0x63, 0x60, 0xD0, 0xF8, 0x0E, 0x30, 0x18, 0xBF, 0x62, 0x60, 0x1D, 0x0A, 0x03, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x05, 0x12, ++0x08, 0xBF, 0x40, 0xF6, 0x47, 0x22, 0x22, 0x60, 0xD0, 0xF8, 0x12, 0x20, 0x95, 0x08, 0x16, 0x0A, 0x02, 0xF0, 0x0F, 0x02, ++0x52, 0xEA, 0x06, 0x12, 0x08, 0xBF, 0x12, 0x4A, 0xA2, 0x60, 0xD0, 0xF8, 0x16, 0x20, 0xC3, 0xF3, 0x00, 0x13, 0x50, 0x08, ++0x05, 0xF0, 0x04, 0x05, 0x01, 0xF0, 0x02, 0x01, 0x2B, 0x43, 0x00, 0xF0, 0x08, 0x00, 0x49, 0xB2, 0x03, 0x43, 0x0B, 0x43, ++0x11, 0x0A, 0x02, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x01, 0x12, 0x63, 0x74, 0x0A, 0xBF, 0x07, 0x4B, 0xE2, 0x60, 0xE3, 0x60, ++0x01, 0x20, 0x70, 0xBD, 0x40, 0xF6, 0x43, 0x23, 0xC4, 0xE9, 0x00, 0x33, 0xC4, 0xE9, 0x02, 0x33, 0x70, 0xBD, 0x00, 0xBF, ++0x32, 0xE4, 0x05, 0x00, 0x22, 0xF3, 0x02, 0x00, 0x38, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0x4A, 0xFB, 0xE8, 0xB1, 0xC2, 0x78, ++0x83, 0x78, 0x43, 0xEA, 0x02, 0x23, 0x23, 0x80, 0x23, 0x46, 0x02, 0x79, 0x03, 0xF8, 0x02, 0x2F, 0x04, 0xF1, 0x12, 0x05, ++0xC4, 0xF1, 0x03, 0x02, 0xC1, 0x18, 0x89, 0x5C, 0x03, 0xF8, 0x01, 0x1F, 0xAB, 0x42, 0xF9, 0xD1, 0x43, 0x7D, 0x82, 0x7D, ++0xB0, 0xF8, 0x17, 0x10, 0xA1, 0x61, 0x43, 0xEA, 0x02, 0x23, 0xA3, 0x82, 0xC3, 0x7E, 0x23, 0x77, 0x01, 0x20, 0x38, 0xBD, ++0xF8, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0xCA, 0xFB, 0xB8, 0xB1, 0xC7, 0x79, 0x43, 0x7A, 0x85, 0x79, 0x02, 0x7A, 0x81, 0x7A, ++0xC6, 0x7A, 0x45, 0xEA, 0x07, 0x25, 0x42, 0xEA, 0x03, 0x22, 0xD0, 0xF8, 0x02, 0x70, 0x03, 0x7B, 0x40, 0x7B, 0x27, 0x60, ++0x43, 0xEA, 0x00, 0x23, 0x41, 0xEA, 0x06, 0x21, 0xA5, 0x80, 0x21, 0x81, 0xE2, 0x80, 0x63, 0x81, 0x01, 0x20, 0xF8, 0xBD, ++0xF0, 0xB5, 0x83, 0xB0, 0x15, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0xFD, 0xF7, 0xC9, 0xFB, 0x00, 0x28, 0x45, 0xD0, 0x9D, 0xF8, ++0x07, 0x30, 0xC6, 0x1C, 0xC5, 0xF1, 0x04, 0x04, 0x1E, 0x44, 0x04, 0x44, 0x6B, 0x1E, 0x69, 0x1D, 0x1A, 0x5D, 0x03, 0xF8, ++0x01, 0x2F, 0x8B, 0x42, 0xFA, 0xD1, 0x05, 0xF1, 0x10, 0x02, 0x19, 0x5D, 0x03, 0xF8, 0x01, 0x1F, 0x93, 0x42, 0xFA, 0xD1, ++0x02, 0x7D, 0x47, 0x7D, 0x83, 0x7D, 0xC4, 0x7D, 0xA9, 0x79, 0x42, 0xEA, 0x07, 0x22, 0x43, 0xEA, 0x04, 0x23, 0x6A, 0x82, ++0x4A, 0x10, 0x09, 0x07, 0xAB, 0x82, 0x00, 0xF1, 0x18, 0x03, 0x0E, 0xD5, 0x00, 0xF1, 0x1C, 0x01, 0xB1, 0x42, 0x1C, 0xD8, ++0x5F, 0x78, 0x04, 0x7E, 0x83, 0x7E, 0xC0, 0x7E, 0x44, 0xEA, 0x07, 0x24, 0x43, 0xEA, 0x00, 0x20, 0xEC, 0x82, 0x0B, 0x46, ++0x28, 0x83, 0x12, 0x07, 0x12, 0xD5, 0x1A, 0x1D, 0xB2, 0x42, 0x0C, 0xD8, 0x58, 0x78, 0x19, 0x78, 0x9A, 0x78, 0xDB, 0x78, ++0x41, 0xEA, 0x00, 0x21, 0x42, 0xEA, 0x03, 0x23, 0x01, 0x20, 0x69, 0x83, 0xAB, 0x83, 0x03, 0xB0, 0xF0, 0xBD, 0x00, 0x20, ++0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, ++0x07, 0x02, 0xFD, 0xF7, 0xC7, 0xFB, 0x40, 0xB1, 0xD0, 0xF8, 0x03, 0x30, 0xC4, 0xF8, 0xDC, 0x30, 0x00, 0x38, 0x18, 0xBF, ++0x01, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x01, 0x4B, 0xF6, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x01, 0x80, 0xF8, 0xB5, 0x1D, 0x46, ++0x14, 0x46, 0xFD, 0xF7, 0xC7, 0xFB, 0x00, 0x23, 0x2B, 0x70, 0x00, 0xB3, 0xC2, 0x78, 0x61, 0x7C, 0x02, 0xF0, 0x0F, 0x03, ++0x99, 0x42, 0x1B, 0xD0, 0x01, 0x26, 0x2E, 0x70, 0x22, 0x74, 0x63, 0x74, 0xB0, 0xF8, 0x05, 0x10, 0x03, 0x79, 0x02, 0x89, ++0xB0, 0xF8, 0x0B, 0x70, 0xC5, 0x89, 0x43, 0xEA, 0x01, 0x23, 0x63, 0x60, 0xC1, 0x79, 0x41, 0xEA, 0x02, 0x21, 0x21, 0x60, ++0x82, 0x7A, 0x42, 0xEA, 0x07, 0x22, 0xA2, 0x60, 0x43, 0x7B, 0x43, 0xEA, 0x05, 0x23, 0x30, 0x46, 0xE3, 0x60, 0xF8, 0xBD, ++0x01, 0x20, 0xF8, 0xBD, 0x10, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0xAC, 0xFB, 0x40, 0xB1, 0xC3, 0x78, 0x03, 0xF0, 0x07, 0x02, ++0xC3, 0xF3, 0xC2, 0x03, 0x22, 0x70, 0x63, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x03, 0x22, 0x05, 0x23, 0x22, 0x70, 0x63, 0x70, ++0x10, 0xBD, 0x00, 0xBF, 0x38, 0xB5, 0x07, 0x48, 0x1C, 0x46, 0x15, 0x46, 0xFE, 0x22, 0x10, 0xF0, 0x67, 0xFD, 0x2A, 0x46, ++0x21, 0x46, 0x41, 0xF2, 0x03, 0x40, 0xFC, 0xF7, 0x41, 0xFA, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x5A, 0xB9, 0x17, 0x00, ++0x70, 0xB5, 0x32, 0x4C, 0x08, 0x78, 0x24, 0x68, 0x01, 0x28, 0x19, 0x46, 0x20, 0x70, 0x29, 0xD0, 0x02, 0x28, 0x05, 0xD0, ++0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0x2E, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x2B, 0x4C, 0x2C, 0x48, 0x23, 0x68, 0x2C, 0x4E, ++0x2C, 0x4D, 0x43, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x03, 0x68, 0x2B, 0x4C, 0x23, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x3F, 0x23, ++0x33, 0x60, 0x2B, 0x68, 0x28, 0x48, 0x23, 0xF0, 0x01, 0x03, 0x2B, 0x60, 0x23, 0x6D, 0x23, 0xF4, 0x80, 0x23, 0x23, 0x65, ++0x03, 0x69, 0x43, 0xF0, 0x80, 0x03, 0x03, 0x61, 0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0x0C, 0xFA, 0x00, 0x20, 0x70, 0xBD, ++0x20, 0x4B, 0x1B, 0x4C, 0x93, 0xF8, 0xB5, 0x30, 0x0B, 0xBB, 0x23, 0x68, 0x19, 0x4E, 0x1E, 0x4D, 0x43, 0xF0, 0x00, 0x73, ++0x23, 0x60, 0x04, 0xF5, 0x00, 0x44, 0x04, 0x23, 0x28, 0x34, 0x33, 0x60, 0x28, 0x60, 0x23, 0x68, 0x23, 0xF4, 0x80, 0x23, ++0x23, 0xF0, 0x01, 0x03, 0x23, 0x60, 0x13, 0x4C, 0x13, 0x48, 0x23, 0x6D, 0x43, 0xF4, 0x80, 0x23, 0x23, 0x65, 0x03, 0x69, ++0x23, 0xF0, 0x80, 0x03, 0x03, 0x61, 0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0xE5, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0x23, 0x68, ++0x09, 0x48, 0x08, 0x4D, 0x23, 0xF0, 0x00, 0x73, 0x23, 0x60, 0x03, 0x68, 0x24, 0x24, 0x43, 0xF4, 0x00, 0x13, 0x03, 0x60, ++0x2C, 0x60, 0xE2, 0xE7, 0x74, 0x36, 0x17, 0x00, 0x44, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, ++0x6C, 0x00, 0x32, 0x40, 0x00, 0x60, 0x50, 0x40, 0x00, 0x00, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x70, 0x80, 0x32, 0x40, ++0xF8, 0xB5, 0x4C, 0x78, 0x08, 0x78, 0x16, 0x46, 0x1D, 0x46, 0x2C, 0xB3, 0x17, 0x4C, 0x18, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x00, 0x44, 0x4F, 0xF4, 0xA4, 0x61, 0x94, 0xF8, 0x22, 0x20, 0x01, 0xFB, 0x02, 0x32, 0x02, 0x23, 0x92, 0xF8, ++0x62, 0x70, 0x84, 0xF8, 0x30, 0x30, 0x5F, 0xB9, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xFC, 0xF7, 0x3E, 0xF9, ++0x07, 0x70, 0x94, 0xF8, 0x22, 0x20, 0x42, 0x70, 0xFC, 0xF7, 0x68, 0xF9, 0x32, 0x46, 0x29, 0x46, 0x41, 0xF2, 0x05, 0x40, ++0xFC, 0xF7, 0x9A, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x04, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x00, 0x30, 0x01, 0x23, ++0x80, 0xF8, 0x30, 0x30, 0xEE, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0x0C, 0x20, 0x0C, 0x46, 0x17, 0x46, 0x00, 0x21, 0x05, 0x22, 0x1E, 0x46, 0x01, 0x23, 0xFC, 0xF7, 0x17, 0xF9, 0xDF, 0xF8, ++0x6C, 0x90, 0xDF, 0xF8, 0x6C, 0x80, 0xD9, 0xF8, 0x24, 0x30, 0x05, 0x46, 0x20, 0x78, 0x98, 0x47, 0x23, 0x78, 0x2B, 0x70, ++0x28, 0x46, 0xFC, 0xF7, 0x39, 0xF9, 0x20, 0x78, 0xD9, 0xF8, 0xD8, 0x31, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0xF0, ++0x00, 0xF5, 0x18, 0x70, 0x40, 0x44, 0x98, 0x47, 0x63, 0x78, 0x43, 0xB9, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x0A, 0x40, ++0xFC, 0xF7, 0x5E, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x23, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, ++0xFC, 0xF7, 0xEC, 0xF8, 0x00, 0x22, 0x02, 0x70, 0x22, 0x78, 0x05, 0xFB, 0x02, 0x88, 0x98, 0xF8, 0x22, 0x20, 0x42, 0x70, ++0xFC, 0xF7, 0x12, 0xF9, 0xE4, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x0C, 0x46, 0x89, 0x78, 0x25, 0x78, 0xDF, 0xF8, 0xAC, 0x80, 0x1E, 0x46, 0x17, 0x46, 0x63, 0x78, 0xA1, 0xB1, 0x00, 0x2B, ++0x44, 0xD1, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x02, 0xF0, 0xFB, 0x02, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x2E, 0x11, 0x83, 0xF8, 0x31, 0x20, 0x0F, 0x29, 0x1E, 0xD1, 0x0A, 0xE0, ++0x2B, 0xBB, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, ++0x31, 0x20, 0x04, 0x23, 0x05, 0x22, 0x00, 0x21, 0x41, 0x20, 0xFC, 0xF7, 0xAB, 0xF8, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x05, 0x85, 0x95, 0xF8, 0x22, 0x30, 0x2A, 0x8C, 0x02, 0x80, 0xC3, 0x70, 0x63, 0x78, 0x83, 0x70, 0xFC, 0xF7, 0xCE, 0xF8, ++0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x0D, 0x40, 0xFC, 0xF7, 0x00, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x42, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x31, 0x20, 0xD8, 0xE7, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x42, 0xF0, 0x04, 0x02, 0xB9, 0xE7, 0x00, 0xBF, ++0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x31, 0x20, 0x0D, 0x46, 0x4B, 0x4C, 0x91, 0x46, 0x98, 0x46, 0x05, 0x22, ++0x01, 0x23, 0x00, 0x21, 0xFC, 0xF7, 0x72, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x76, 0x31, 0x95, 0xF8, 0x67, 0x30, 0x82, 0x46, ++0x5B, 0xB1, 0x01, 0x23, 0x84, 0xF8, 0x76, 0x31, 0x2F, 0x46, 0x0F, 0xCF, 0x04, 0xF1, 0x0C, 0x06, 0x0F, 0xC6, 0x97, 0xE8, ++0x0F, 0x00, 0x86, 0xE8, 0x0F, 0x00, 0x95, 0xF8, 0x68, 0x30, 0x5B, 0xB1, 0x94, 0xF8, 0x76, 0x21, 0x3C, 0x4B, 0x42, 0xF0, ++0x02, 0x02, 0x84, 0xF8, 0x76, 0x21, 0x05, 0xF1, 0x20, 0x02, 0x07, 0xCA, 0x83, 0xE8, 0x07, 0x00, 0x95, 0xF8, 0x69, 0x30, ++0x93, 0xB1, 0x94, 0xF8, 0x76, 0x31, 0x36, 0x4E, 0x43, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x76, 0x31, 0x05, 0xF1, 0x2C, 0x07, ++0x0F, 0xCF, 0x0F, 0xC6, 0x0F, 0xCF, 0x0F, 0xC6, 0x0F, 0xCF, 0x0F, 0xC6, 0x97, 0xE8, 0x03, 0x00, 0x86, 0xE8, 0x03, 0x00, ++0x95, 0xF8, 0x6A, 0x30, 0x2B, 0xB1, 0x94, 0xF8, 0x76, 0x31, 0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x76, 0x31, 0x95, 0xF8, ++0x66, 0x30, 0x84, 0xF8, 0x75, 0x31, 0x4A, 0x46, 0x41, 0x46, 0x41, 0xF2, 0x01, 0x40, 0xFC, 0xF7, 0x8F, 0xF8, 0x94, 0xF8, ++0x76, 0x31, 0x13, 0xF0, 0x01, 0x03, 0x14, 0xD1, 0x84, 0xF8, 0x74, 0x31, 0x95, 0xF8, 0x6B, 0x30, 0xB5, 0xF8, 0x64, 0x10, ++0x84, 0xF8, 0x77, 0x31, 0x95, 0xF8, 0x6D, 0x20, 0xA1, 0x85, 0x00, 0x2A, 0x14, 0xBF, 0x02, 0x22, 0x01, 0x22, 0x84, 0xF8, ++0x78, 0x21, 0xF3, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xDA, 0xF7, 0xE3, 0xFC, 0x94, 0xF8, 0x76, 0x31, 0x01, 0x30, ++0x40, 0x10, 0x5B, 0x07, 0x84, 0xF8, 0x74, 0x01, 0xE2, 0xD5, 0x94, 0xF8, 0x75, 0x21, 0x94, 0xF8, 0x44, 0x30, 0x02, 0x2A, ++0x88, 0xBF, 0x94, 0xF8, 0x49, 0x20, 0x4F, 0xEA, 0x93, 0x03, 0x88, 0xBF, 0x03, 0xEA, 0x92, 0x13, 0x03, 0xF0, 0x01, 0x03, ++0x84, 0xF8, 0x74, 0x30, 0xD0, 0xE7, 0xFF, 0x23, 0x23, 0x81, 0x50, 0x46, 0x8A, 0xF8, 0x00, 0x20, 0xFC, 0xF7, 0x1A, 0xF8, ++0x01, 0x21, 0x05, 0x20, 0xFC, 0xF7, 0xE0, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, ++0x14, 0xB9, 0x17, 0x00, 0x20, 0xB9, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x41, 0xF2, 0x08, 0x40, 0x97, 0xB0, 0x0C, 0x46, ++0x19, 0x46, 0x03, 0x23, 0xFB, 0xF7, 0xD2, 0xFF, 0x4F, 0xF0, 0x00, 0x0A, 0xCD, 0xE9, 0x0C, 0xAA, 0x05, 0x46, 0xAD, 0xF8, ++0x2E, 0xA0, 0x8D, 0xF8, 0x2C, 0xA0, 0x08, 0xF0, 0xEB, 0xFB, 0x94, 0xF8, 0x81, 0x70, 0xA2, 0x6F, 0x06, 0x90, 0x4F, 0xF4, ++0xA4, 0x61, 0x01, 0xFB, 0x07, 0xF1, 0x12, 0xF0, 0x02, 0x06, 0x07, 0x91, 0x1B, 0xD0, 0x12, 0xF0, 0x04, 0x06, 0x04, 0xF1, ++0x14, 0x08, 0x40, 0xF0, 0xDC, 0x81, 0xB1, 0x46, 0x0B, 0xAB, 0x12, 0xF0, 0x20, 0x02, 0x0D, 0xF1, 0x34, 0x0C, 0x02, 0x93, ++0x0C, 0xAB, 0xCD, 0xE9, 0x00, 0x3C, 0x18, 0xBF, 0x04, 0xF1, 0x40, 0x02, 0x0D, 0xF1, 0x2E, 0x03, 0x49, 0x46, 0x40, 0x46, ++0x00, 0xF0, 0x00, 0xFE, 0x94, 0xF8, 0x81, 0x30, 0x00, 0xE0, 0x3B, 0x46, 0x00, 0x22, 0xDF, 0xF8, 0xC4, 0x93, 0x20, 0x68, ++0x0C, 0x99, 0xB4, 0xF8, 0x04, 0xE0, 0xBD, 0xF8, 0x2E, 0xC0, 0x0E, 0x92, 0x8D, 0xF8, 0x55, 0x20, 0x8D, 0xF8, 0x56, 0x20, ++0x9D, 0xF8, 0x2C, 0x20, 0x8D, 0xF8, 0x51, 0x30, 0xCD, 0xF8, 0x4A, 0x00, 0x10, 0x91, 0x8D, 0xF8, 0x50, 0x20, 0xD9, 0xF8, ++0xC4, 0x31, 0x11, 0x96, 0xAD, 0xF8, 0x4E, 0xE0, 0xAD, 0xF8, 0x48, 0xC0, 0x0D, 0xF1, 0x2D, 0x02, 0x29, 0x46, 0x0E, 0xA8, ++0x98, 0x47, 0x83, 0x46, 0x68, 0x70, 0x00, 0x28, 0x40, 0xF0, 0x1C, 0x81, 0x23, 0x46, 0x2E, 0x78, 0x53, 0xF8, 0x06, 0x0F, ++0xDF, 0xF8, 0x70, 0x83, 0x59, 0x68, 0x9A, 0x68, 0x93, 0xF8, 0x0C, 0xE0, 0xD4, 0xF8, 0x78, 0xC0, 0x04, 0x96, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x06, 0xF3, 0x08, 0xEB, 0x03, 0x0A, 0x08, 0x93, 0x0A, 0xF1, 0xB8, 0x03, 0x07, 0xC3, 0x1C, 0xF0, ++0x01, 0x0F, 0x83, 0xF8, 0x00, 0xE0, 0x40, 0xF0, 0x06, 0x81, 0xC7, 0x4B, 0x05, 0x93, 0x1C, 0xF0, 0x08, 0x0F, 0x08, 0xD0, ++0x04, 0x9A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0x5A, 0x68, 0x42, 0xF0, 0x08, 0x02, 0x5A, 0x60, 0x04, 0x9A, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0x94, 0xF8, 0x7E, 0x20, 0x83, 0xF8, 0x2E, 0x21, 0x94, 0xF8, 0x7F, 0x10, ++0xB4, 0xF8, 0x7C, 0x20, 0x1A, 0x84, 0x83, 0xF8, 0x2F, 0x11, 0x50, 0x46, 0x09, 0x93, 0x00, 0xF0, 0xBB, 0xFE, 0xA2, 0x6F, ++0xD2, 0x06, 0x06, 0xD5, 0x94, 0xF9, 0x80, 0x20, 0x94, 0xF8, 0x80, 0x10, 0x00, 0x2A, 0x80, 0xF2, 0x77, 0x81, 0xBB, 0xF1, ++0x00, 0x0F, 0x40, 0xF0, 0x7F, 0x81, 0x05, 0x9B, 0xAF, 0x48, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x34, 0x04, 0x9B, ++0xB4, 0xF8, 0xE0, 0x20, 0x4F, 0xF4, 0x1E, 0x7B, 0x0B, 0xFB, 0x03, 0x86, 0xD4, 0xF8, 0xB0, 0x34, 0x96, 0xF8, 0x56, 0x11, ++0xC6, 0xF8, 0x68, 0xA2, 0x03, 0xF0, 0x01, 0x03, 0xC3, 0xF1, 0x02, 0x03, 0x86, 0xF8, 0x30, 0x30, 0x41, 0xF0, 0x10, 0x01, ++0xA3, 0x4B, 0x86, 0xF8, 0x56, 0x11, 0x52, 0xBA, 0x4F, 0xF0, 0x01, 0x0A, 0xC6, 0xF8, 0x64, 0x02, 0xB2, 0x86, 0x08, 0x98, ++0x86, 0xF8, 0x70, 0xA2, 0x1A, 0x69, 0x9E, 0x49, 0xD9, 0xF8, 0xE0, 0x31, 0x00, 0xF5, 0x18, 0x70, 0x40, 0x44, 0x11, 0x44, ++0x98, 0x47, 0x06, 0x9B, 0xAB, 0x70, 0x00, 0x2B, 0x00, 0xF0, 0x9A, 0x80, 0x94, 0xF8, 0xDE, 0x20, 0x86, 0xF8, 0x24, 0x30, ++0x00, 0x2A, 0x40, 0xF0, 0x85, 0x80, 0x94, 0xF8, 0x63, 0x60, 0x0A, 0x36, 0xF6, 0xB2, 0x0B, 0xFB, 0x06, 0xF3, 0x08, 0xEB, ++0x03, 0x0B, 0x04, 0x93, 0x9B, 0xF8, 0x24, 0x30, 0x53, 0x45, 0x77, 0xD0, 0x02, 0x23, 0x0C, 0x21, 0x49, 0x20, 0xFB, 0xF7, ++0xDB, 0xFE, 0x8B, 0xF8, 0x24, 0xA0, 0x06, 0x70, 0x80, 0xF8, 0x01, 0xA0, 0xFB, 0xF7, 0x04, 0xFF, 0x9B, 0xF8, 0x24, 0x30, ++0x00, 0x2B, 0x40, 0xF0, 0x48, 0x81, 0x9B, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x00, 0xF2, 0x43, 0x81, 0x9B, 0xF8, 0x22, 0x00, ++0x05, 0x9C, 0xCD, 0xF8, 0x18, 0xA0, 0x9E, 0x23, 0xA4, 0x21, 0x4F, 0xF4, 0xA4, 0x6C, 0x11, 0xFB, 0x00, 0x31, 0x0C, 0xFB, ++0x00, 0x4A, 0x4F, 0x23, 0x46, 0x20, 0x13, 0xFB, 0x06, 0x03, 0x7B, 0x4A, 0x05, 0x98, 0x7B, 0x4C, 0x08, 0x95, 0x08, 0xEB, ++0xC3, 0x08, 0x04, 0x9B, 0x00, 0xEB, 0xC1, 0x06, 0x13, 0x44, 0x35, 0x46, 0x1E, 0x46, 0xDB, 0xF8, 0x08, 0x22, 0x1A, 0xB3, ++0xEF, 0xF3, 0x10, 0x82, 0xD3, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x73, 0x4B, 0x06, 0x9A, 0x1A, 0x60, 0x22, 0x68, 0xA8, 0xF1, ++0x28, 0x00, 0x01, 0x32, 0xA5, 0xF1, 0x28, 0x01, 0x04, 0x90, 0x22, 0x60, 0xFC, 0xF7, 0x18, 0xFC, 0xDB, 0xE9, 0x82, 0x21, ++0x04, 0x98, 0xCA, 0xF8, 0xC8, 0x24, 0xCA, 0xF8, 0xCC, 0x14, 0xFC, 0xF7, 0x19, 0xFB, 0x22, 0x68, 0x51, 0x1E, 0x2A, 0xB1, ++0x66, 0x4B, 0x21, 0x60, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xDB, 0xF8, 0x30, 0x22, 0x28, 0x46, 0x41, 0x46, ++0x0B, 0xF1, 0x08, 0x0B, 0x08, 0x35, 0x0A, 0xF1, 0x08, 0x0A, 0x22, 0xB1, 0xFC, 0xF7, 0xFA, 0xFB, 0x40, 0x46, 0xFC, 0xF7, ++0x01, 0xFB, 0x08, 0xF1, 0x08, 0x08, 0x46, 0x45, 0xC5, 0xD1, 0x40, 0x20, 0x08, 0x9D, 0xFC, 0xF7, 0x5B, 0xFA, 0x05, 0x9A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x23, 0x93, 0xF8, 0xDE, 0x20, 0x05, 0x9C, 0xD9, 0xF8, 0x0C, 0x32, 0x4F, 0xF4, ++0xA4, 0x61, 0x01, 0xFB, 0x07, 0x47, 0x07, 0x99, 0x01, 0x32, 0x21, 0x44, 0x08, 0x46, 0x87, 0xF8, 0xDE, 0x20, 0x98, 0x47, ++0x28, 0x46, 0xFB, 0xF7, 0x87, 0xFE, 0x00, 0x20, 0x17, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x04, 0x30, 0x05, 0x93, ++0x1C, 0xF0, 0x02, 0x0F, 0x43, 0xF0, 0x01, 0x03, 0xCA, 0xF8, 0x04, 0x30, 0x3F, 0xF4, 0xEF, 0xAE, 0x45, 0x4B, 0x93, 0xF8, ++0x76, 0x31, 0x09, 0x93, 0x13, 0xF0, 0x01, 0x0B, 0x3F, 0xF4, 0xE7, 0xAE, 0x04, 0xF1, 0x14, 0x0E, 0xBE, 0xE8, 0x0F, 0x00, ++0x0A, 0xF1, 0xC8, 0x0B, 0xAB, 0xE8, 0x0F, 0x00, 0x9E, 0xE8, 0x0F, 0x00, 0x05, 0x9E, 0x1C, 0xF0, 0x20, 0x0F, 0x46, 0xF0, ++0x03, 0x0E, 0x8B, 0xE8, 0x0F, 0x00, 0xCA, 0xF8, 0x04, 0xE0, 0x22, 0xD0, 0x09, 0x9B, 0x58, 0x07, 0x1F, 0xD5, 0x04, 0xF1, ++0x40, 0x0E, 0xBE, 0xE8, 0x0F, 0x00, 0x0A, 0xF1, 0xF4, 0x0B, 0xAB, 0xE8, 0x0F, 0x00, 0xBE, 0xE8, 0x0F, 0x00, 0xAB, 0xE8, ++0x0F, 0x00, 0xBE, 0xE8, 0x0F, 0x00, 0xAB, 0xE8, 0x0F, 0x00, 0x9E, 0xE8, 0x03, 0x00, 0x46, 0xF0, 0x23, 0x03, 0xCA, 0xF8, ++0x04, 0x30, 0x09, 0x9B, 0x8B, 0xE8, 0x03, 0x00, 0x19, 0x07, 0x04, 0xD5, 0x50, 0x46, 0xEC, 0xF7, 0x85, 0xFF, 0xD4, 0xF8, ++0x78, 0xC0, 0x1C, 0xF0, 0x04, 0x0F, 0x1F, 0xD0, 0x24, 0x4B, 0x04, 0x9A, 0x93, 0xF8, 0x76, 0x31, 0x13, 0xF0, 0x02, 0x0F, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0xD3, 0xF8, 0x04, 0xC0, 0x02, 0xD1, 0x1C, 0xF0, 0x20, 0x0F, 0x0F, 0xD0, ++0x04, 0xF1, 0x34, 0x03, 0x93, 0xE8, 0x07, 0x00, 0x04, 0x9E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0x83, 0x03, 0xF1, ++0xE8, 0x0E, 0x8E, 0xE8, 0x07, 0x00, 0x4C, 0xF0, 0x04, 0x02, 0x5A, 0x60, 0x07, 0x9A, 0x0D, 0x4B, 0x05, 0x93, 0x02, 0xF1, ++0xEC, 0x01, 0x19, 0x44, 0x50, 0x46, 0x00, 0xF0, 0x53, 0xFB, 0xD4, 0xF8, 0x78, 0xC0, 0x83, 0x46, 0x81, 0xE6, 0x07, 0x4B, ++0x05, 0x93, 0x0B, 0x44, 0x04, 0xF1, 0x34, 0x09, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x43, 0xD0, 0x03, 0x2B, 0x2F, 0xD0, ++0xA3, 0xB3, 0x56, 0x46, 0x16, 0xE6, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x1D, 0x66, 0x12, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x40, 0x4B, 0x4C, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x09, 0x9B, 0x0A, 0x09, 0x93, 0xF8, 0x23, 0x00, 0x01, 0xF0, 0x03, 0x01, ++0x01, 0xF0, 0x34, 0xF8, 0xBB, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x81, 0xAE, 0x04, 0x9A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x02, 0x83, 0xFF, 0x21, 0x93, 0xF8, 0x23, 0x00, 0x00, 0x22, 0x01, 0xF0, 0x25, 0xF8, 0x74, 0xE6, 0x20, 0x46, 0xFC, 0xF7, ++0x61, 0xFF, 0xA2, 0x6F, 0x06, 0x46, 0xE3, 0xE5, 0x09, 0x4B, 0x01, 0xF5, 0xB2, 0x70, 0x03, 0x44, 0xB4, 0xF8, 0x7C, 0x10, ++0x18, 0x46, 0xFC, 0xF7, 0x5D, 0xFF, 0xA2, 0x6F, 0x06, 0x46, 0xD7, 0xE5, 0x07, 0x9B, 0x03, 0xF1, 0x5C, 0x00, 0x05, 0x9B, ++0xF1, 0xE7, 0x94, 0xF8, 0xDE, 0x20, 0x1B, 0xE7, 0x18, 0x88, 0x17, 0x00, 0xF0, 0xB5, 0x0C, 0x46, 0x21, 0x4D, 0x09, 0x78, ++0x6F, 0x68, 0x1E, 0x46, 0x63, 0x78, 0x01, 0x20, 0x83, 0xB0, 0x98, 0x40, 0xC1, 0xB1, 0x38, 0x43, 0x95, 0xF8, 0x77, 0x31, ++0x68, 0x60, 0x5B, 0xB1, 0x05, 0x20, 0x01, 0x92, 0xFC, 0xF7, 0x10, 0xF8, 0x01, 0x28, 0x2C, 0xD0, 0x17, 0xF0, 0xFF, 0x0F, ++0x23, 0x78, 0x01, 0x9A, 0x0B, 0xD0, 0x63, 0xB1, 0x41, 0xF2, 0x1A, 0x40, 0x31, 0x46, 0xFB, 0xF7, 0xC9, 0xFD, 0x00, 0x20, ++0x03, 0xB0, 0xF0, 0xBD, 0x27, 0xEA, 0x00, 0x00, 0xE4, 0xE7, 0x00, 0x2B, 0xF2, 0xD0, 0x01, 0x23, 0x00, 0x21, 0x31, 0x20, ++0x01, 0x92, 0xFB, 0xF7, 0x53, 0xFD, 0x6B, 0x68, 0x01, 0x9A, 0x2E, 0x81, 0x63, 0xB1, 0x00, 0x23, 0x03, 0x70, 0x01, 0x92, ++0xFB, 0xF7, 0x7A, 0xFD, 0x01, 0x9A, 0x01, 0x21, 0x10, 0x46, 0xFB, 0xF7, 0x3F, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, ++0x95, 0xF8, 0x78, 0x31, 0xF0, 0xE7, 0x02, 0x20, 0xDC, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0x11, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x14, 0x46, 0x0E, 0xDB, 0x0E, 0x4B, 0x19, 0x89, 0xFF, 0x29, 0x04, 0xD0, ++0x22, 0x46, 0x41, 0xF2, 0x18, 0x40, 0xFB, 0xF7, 0x91, 0xFD, 0x20, 0x46, 0x00, 0x21, 0xFB, 0xF7, 0x1F, 0xFF, 0x00, 0x20, ++0x10, 0xBD, 0x10, 0x46, 0xFB, 0xF7, 0xC2, 0xFF, 0x01, 0x28, 0xEB, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x7F, 0x22, ++0xFD, 0xF7, 0xFA, 0xFD, 0xE4, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x3C, 0xB8, 0x15, 0x00, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x14, 0x46, 0x0E, 0xDB, ++0x0E, 0x4B, 0x19, 0x89, 0xFF, 0x29, 0x04, 0xD0, 0x22, 0x46, 0x41, 0xF2, 0x1A, 0x40, 0xFB, 0xF7, 0x65, 0xFD, 0x20, 0x46, ++0x00, 0x21, 0xFB, 0xF7, 0xF3, 0xFE, 0x00, 0x20, 0x10, 0xBD, 0x10, 0x46, 0xFB, 0xF7, 0x96, 0xFF, 0x01, 0x28, 0xEB, 0xD0, ++0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x15, 0x32, 0xFD, 0xF7, 0xCE, 0xFD, 0xE4, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0xB8, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x46, 0x41, 0xF2, 0x0F, 0x40, ++0x19, 0x46, 0xC8, 0x23, 0xFB, 0xF7, 0xDA, 0xFC, 0x22, 0x78, 0x37, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, ++0x06, 0x46, 0xD3, 0xF8, 0x4C, 0x51, 0x02, 0x70, 0x00, 0x2D, 0x5C, 0xD0, 0xB5, 0xF8, 0xB4, 0x00, 0xB5, 0xF8, 0x90, 0x10, ++0xB5, 0xF8, 0x92, 0x20, 0xD5, 0xF8, 0x94, 0x30, 0xB3, 0x60, 0x70, 0x80, 0xB1, 0x80, 0xF2, 0x80, 0x95, 0xF8, 0xA4, 0x30, ++0x33, 0x73, 0xB5, 0xF8, 0x98, 0x30, 0x73, 0x73, 0x08, 0x22, 0x05, 0xF1, 0x88, 0x01, 0x06, 0xF1, 0x0E, 0x00, 0x10, 0xF0, ++0x3D, 0xF8, 0x78, 0x22, 0x29, 0x1D, 0x06, 0xF1, 0x16, 0x00, 0x10, 0xF0, 0x37, 0xF8, 0xB5, 0xF8, 0xB4, 0x30, 0x83, 0xB1, ++0x00, 0x24, 0x00, 0x22, 0xE1, 0xB2, 0x28, 0x46, 0x0C, 0xF0, 0x2C, 0xFE, 0xA3, 0xB2, 0x06, 0xEB, 0x83, 0x03, 0xB5, 0xF8, ++0xB4, 0x20, 0xC3, 0xF8, 0x9C, 0x00, 0x01, 0x34, 0xA3, 0xB2, 0x9A, 0x42, 0xEF, 0xD8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x05, 0xF1, 0x7C, 0x03, 0x07, 0xCB, 0x14, 0x4C, 0xC6, 0xF8, ++0x8E, 0x00, 0x23, 0x68, 0xC6, 0xF8, 0x92, 0x10, 0x01, 0x33, 0xC6, 0xF8, 0x96, 0x20, 0x28, 0x46, 0x00, 0x22, 0x0A, 0x21, ++0x23, 0x60, 0x0C, 0xF0, 0x07, 0xFE, 0x23, 0x68, 0xC6, 0xF8, 0xC4, 0x00, 0x33, 0xB1, 0x0A, 0x4A, 0x01, 0x3B, 0x12, 0x68, ++0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x30, 0x46, 0xFB, 0xF7, 0xA3, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x45, 0x80, ++0x30, 0x46, 0xFB, 0xF7, 0x9D, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, ++0x6C, 0x28, 0x17, 0x00, 0x70, 0xB5, 0x23, 0x4A, 0x0B, 0x78, 0x12, 0x68, 0x0C, 0x46, 0x22, 0x49, 0xB2, 0xF9, 0x00, 0x20, ++0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x22, 0xDB, 0x66, 0x88, 0x4F, 0xF6, ++0xFF, 0x73, 0x9E, 0x42, 0x0B, 0xD1, 0x95, 0xF8, 0xA2, 0x30, 0xA5, 0xF8, 0xBA, 0x60, 0x03, 0xF0, 0xCF, 0x03, 0x85, 0xF8, ++0xA2, 0x30, 0x1B, 0x06, 0x1C, 0xD4, 0x00, 0x20, 0x70, 0xBD, 0x31, 0x46, 0x28, 0x46, 0x0C, 0xF0, 0x65, 0xFD, 0x00, 0x28, ++0xF7, 0xD0, 0x95, 0xF8, 0xA2, 0x30, 0xA5, 0xF8, 0xBA, 0x60, 0x23, 0xF0, 0x30, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x85, 0xF8, ++0xA2, 0x30, 0x00, 0x20, 0x70, 0xBD, 0x00, 0x2D, 0xDA, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0xAF, 0x32, 0xFD, 0xF7, ++0x0B, 0xFD, 0xD3, 0xE7, 0x20, 0x78, 0x0C, 0xF0, 0xC9, 0xFB, 0x95, 0xF8, 0xA2, 0x30, 0x03, 0xF0, 0x7F, 0x03, 0x85, 0xF8, ++0xA2, 0x30, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0xF8, 0xB5, 0x05, 0x20, 0x0E, 0x46, 0x15, 0x46, 0x1C, 0x46, 0xFB, 0xF7, 0xAF, 0xFE, 0x01, 0x28, ++0x4F, 0xD0, 0x2A, 0x46, 0x0C, 0x23, 0x21, 0x46, 0x41, 0xF2, 0x12, 0x40, 0xFB, 0xF7, 0x04, 0xFC, 0x37, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x2A, 0xDB, 0x35, 0x4B, 0x1C, 0x7C, 0xDA, 0xF7, 0x7F, 0xF8, 0x00, 0x28, ++0x30, 0xD1, 0xF3, 0x7A, 0x53, 0xB1, 0x32, 0x4B, 0x32, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0x2C, 0x12, 0x11, 0x66, 0xA3, 0xF5, ++0x40, 0x63, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x2E, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x77, 0x3C, 0x6C, ++0x4C, 0xB3, 0x23, 0x7E, 0x2B, 0x70, 0xB3, 0x7A, 0xE3, 0xB9, 0x23, 0x1D, 0x03, 0xCB, 0x1B, 0x88, 0x6B, 0x81, 0xC5, 0xF8, ++0x02, 0x00, 0xC5, 0xF8, 0x06, 0x10, 0x28, 0x46, 0xFB, 0xF7, 0x04, 0xFC, 0x00, 0x20, 0xF8, 0xBD, 0x1F, 0x4F, 0x3C, 0x7C, ++0xFF, 0x2C, 0xD2, 0xD1, 0x21, 0x49, 0x22, 0x48, 0x40, 0xF2, 0xEB, 0x32, 0xFD, 0xF7, 0xAA, 0xFC, 0x3C, 0x7C, 0xCA, 0xE7, ++0xF0, 0x7A, 0xDA, 0xF7, 0x53, 0xF8, 0xCA, 0xE7, 0x1D, 0x48, 0xFC, 0xF7, 0xD1, 0xF8, 0x01, 0x28, 0x0A, 0xD0, 0x3C, 0x6C, ++0xDB, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xFF, 0x23, 0x28, 0x46, 0x2B, 0x70, 0xFB, 0xF7, 0xE4, 0xFB, 0x20, 0x46, 0xF8, 0xBD, ++0x05, 0x22, 0x0C, 0x23, 0x00, 0x21, 0x3B, 0x20, 0xFB, 0xF7, 0xAC, 0xFB, 0x39, 0x6C, 0x03, 0x46, 0x09, 0x7E, 0x03, 0xF8, ++0x02, 0x1B, 0x31, 0x89, 0x37, 0x68, 0x74, 0x68, 0xC0, 0xF8, 0x02, 0x70, 0x19, 0x81, 0x5C, 0x60, 0xFB, 0xF7, 0xCE, 0xFB, ++0x31, 0x68, 0x72, 0x68, 0x33, 0x89, 0x6B, 0x81, 0xC5, 0xF8, 0x02, 0x10, 0xC5, 0xF8, 0x06, 0x20, 0xBD, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x60, 0xB8, 0x15, 0x00, 0x08, 0x88, 0x17, 0x00, 0xF8, 0xB5, 0x05, 0x20, 0x0C, 0x46, 0x15, 0x46, ++0x1E, 0x46, 0xFB, 0xF7, 0x1F, 0xFE, 0x01, 0x28, 0x3C, 0xD0, 0x1F, 0x4F, 0x3B, 0x68, 0x73, 0xB1, 0x22, 0x78, 0xB2, 0xB1, ++0x61, 0x78, 0x01, 0x22, 0x8A, 0x40, 0x13, 0x43, 0x31, 0x46, 0x2A, 0x46, 0x41, 0xF2, 0x18, 0x40, 0x3B, 0x60, 0xFB, 0xF7, ++0xD3, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x23, 0x78, 0x3B, 0xB9, 0x2A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x18, 0x40, 0xFB, 0xF7, ++0xC9, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x01, 0x23, 0x00, 0x21, 0x2A, 0x46, 0x22, 0x20, 0xFB, 0xF7, 0x59, 0xFB, 0x23, 0x78, ++0x61, 0x78, 0x8B, 0xB1, 0x3A, 0x68, 0x01, 0x23, 0x8B, 0x40, 0x13, 0x43, 0xB3, 0xFA, 0x83, 0xF2, 0x52, 0x09, 0x3B, 0x60, ++0x3E, 0x81, 0x02, 0x70, 0xFB, 0xF7, 0x7A, 0xFB, 0x28, 0x46, 0x01, 0x21, 0xFB, 0xF7, 0x40, 0xFD, 0x00, 0x20, 0xF8, 0xBD, ++0x3B, 0x68, 0x01, 0x22, 0x8A, 0x40, 0x23, 0xEA, 0x02, 0x03, 0xEB, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xE4, 0xB8, 0x17, 0x00, ++0xF8, 0xB5, 0x05, 0x20, 0x0D, 0x46, 0x17, 0x46, 0x1E, 0x46, 0xFB, 0xF7, 0xD5, 0xFD, 0x01, 0x28, 0x24, 0xD0, 0x13, 0x4C, ++0x2B, 0x78, 0x61, 0x68, 0x00, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0x84, 0xF8, 0x77, 0x31, 0x81, 0xB9, 0x01, 0x23, 0x05, 0x22, ++0x31, 0x20, 0xFB, 0xF7, 0x23, 0xFB, 0x94, 0xF8, 0x77, 0x31, 0xFF, 0x22, 0x22, 0x81, 0x73, 0xB9, 0x03, 0x70, 0xFB, 0xF7, ++0x4B, 0xFB, 0x01, 0x21, 0x05, 0x20, 0xFB, 0xF7, 0x11, 0xFD, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x14, 0x40, 0xFB, 0xF7, ++0x79, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x94, 0xF8, 0x78, 0x31, 0xED, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xE4, 0xB8, 0x17, 0x00, ++0x08, 0xB5, 0x4F, 0xF4, 0xBE, 0x72, 0x00, 0x21, 0x09, 0x48, 0xD8, 0xF7, 0xFB, 0xFE, 0x00, 0x21, 0x05, 0x20, 0xFB, 0xF7, ++0xF7, 0xFC, 0x04, 0xF0, 0xFB, 0xFF, 0x04, 0xF0, 0x7D, 0xFA, 0x02, 0xF0, 0x25, 0xF9, 0x09, 0xF0, 0x41, 0xF9, 0xBD, 0xE8, ++0x08, 0x40, 0x0E, 0xF0, 0xD5, 0xB8, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0xA8, 0xB9, 0x10, 0x4B, 0x93, 0xF8, 0x72, 0x01, ++0x76, 0x33, 0xC8, 0xB1, 0x00, 0xEB, 0x40, 0x00, 0x10, 0xB4, 0x03, 0xEB, 0x40, 0x04, 0x01, 0xE0, 0xA3, 0x42, 0x0D, 0xD0, ++0x1A, 0x88, 0x8A, 0x42, 0x18, 0x46, 0x03, 0xF1, 0x06, 0x03, 0xF7, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x05, 0x4B, ++0x93, 0xF8, 0x73, 0x01, 0xCA, 0x33, 0xE8, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, ++0xE4, 0xB8, 0x17, 0x00, 0xF0, 0xB9, 0x4B, 0x1E, 0x0D, 0x2B, 0x31, 0xD8, 0x0E, 0x29, 0x32, 0xD0, 0x01, 0xEB, 0x81, 0x01, ++0x01, 0xF6, 0x67, 0x11, 0x19, 0x4B, 0x93, 0xF8, 0x72, 0x01, 0x76, 0x33, 0x60, 0xB3, 0x00, 0xEB, 0x40, 0x00, 0x10, 0xB4, ++0x03, 0xEB, 0x40, 0x04, 0x01, 0xE0, 0xA3, 0x42, 0x1A, 0xD0, 0x1A, 0x88, 0x8A, 0x42, 0x18, 0x46, 0x03, 0xF1, 0x06, 0x03, ++0xF7, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x01, 0x28, 0x06, 0xD0, 0x4F, 0xF6, 0xFF, 0x71, 0x0C, 0x4B, 0x93, 0xF8, ++0x73, 0x01, 0xCA, 0x33, 0xE4, 0xE7, 0x4B, 0x1E, 0xA4, 0x2B, 0xF5, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, 0x9C, 0x51, ++0x08, 0x31, 0xF1, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x4F, 0xF6, 0xFF, 0x71, 0xD0, 0xE7, 0x40, 0xF6, ++0xB4, 0x11, 0xCD, 0xE7, 0x70, 0x47, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0xF0, 0xB4, 0x03, 0x46, 0x42, 0x48, 0x5C, 0x68, ++0x90, 0xF8, 0x75, 0x21, 0xA5, 0x06, 0x2E, 0xD5, 0x93, 0xF8, 0xFA, 0x70, 0x93, 0xF8, 0xFC, 0x50, 0x93, 0xF8, 0x01, 0x61, ++0x7C, 0x10, 0xFF, 0x06, 0x4F, 0xEA, 0xD5, 0x05, 0x55, 0xD5, 0x04, 0x24, 0x05, 0xEA, 0xD6, 0x16, 0x90, 0xF8, 0x74, 0x50, ++0xB3, 0xF8, 0xC8, 0x00, 0xB5, 0x42, 0x28, 0xBF, 0x35, 0x46, 0x94, 0x42, 0x28, 0xBF, 0x14, 0x46, 0x83, 0xF8, 0x2C, 0x41, ++0x91, 0xF8, 0xD9, 0x20, 0x04, 0x2A, 0x46, 0xD0, 0xA2, 0x42, 0x28, 0xBF, 0x22, 0x46, 0x04, 0x2A, 0x43, 0xD0, 0xD2, 0xB2, ++0x00, 0xF0, 0x0C, 0x00, 0x0C, 0x38, 0x83, 0xF8, 0x2D, 0x21, 0x83, 0xF8, 0x30, 0x51, 0x18, 0xBF, 0x01, 0x20, 0xF0, 0xBC, ++0x70, 0x47, 0x90, 0xF8, 0x74, 0x51, 0x60, 0x07, 0x13, 0xD5, 0xD3, 0xF8, 0xE8, 0x00, 0x00, 0xF0, 0x0C, 0x04, 0x04, 0x2C, ++0x44, 0xD0, 0x08, 0x2C, 0x0C, 0xBF, 0x04, 0x24, 0x02, 0x24, 0xC0, 0xF3, 0x02, 0x20, 0x04, 0x28, 0x27, 0xD8, 0x85, 0x42, ++0x28, 0xBF, 0x05, 0x46, 0xB3, 0xF8, 0xC8, 0x00, 0xCD, 0xE7, 0xB3, 0xF8, 0xC8, 0x00, 0x10, 0xF0, 0x02, 0x04, 0xC0, 0xF3, ++0x01, 0x26, 0x28, 0xD0, 0x01, 0x2A, 0x28, 0xBF, 0x01, 0x22, 0x83, 0xF8, 0x2C, 0x21, 0x14, 0x46, 0x91, 0xF8, 0xD9, 0x20, ++0xB5, 0x42, 0x28, 0xBF, 0x35, 0x46, 0x04, 0x2A, 0xC2, 0xD1, 0x02, 0x2C, 0x22, 0x46, 0x28, 0xBF, 0x02, 0x22, 0xD2, 0xB2, ++0xC2, 0xE7, 0x67, 0x07, 0x09, 0xD5, 0x03, 0x24, 0xA6, 0xE7, 0x04, 0x2C, 0xF3, 0xD1, 0x03, 0x22, 0xBA, 0xE7, 0xB3, 0xF8, ++0xC8, 0x00, 0x00, 0x25, 0xA7, 0xE7, 0xA6, 0x07, 0x47, 0xBF, 0x05, 0xF0, 0x01, 0x06, 0x02, 0x24, 0x04, 0xF0, 0x01, 0x04, ++0x05, 0xF0, 0x01, 0x06, 0x96, 0xE7, 0xB5, 0x42, 0x83, 0xF8, 0x2C, 0x41, 0x28, 0xBF, 0x35, 0x46, 0x22, 0x46, 0xA5, 0xE7, ++0x03, 0x24, 0xBC, 0xE7, 0xE4, 0xB8, 0x17, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x01, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x14, 0xBF, ++0x07, 0x20, 0x09, 0x20, 0x70, 0x47, 0x08, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xF0, 0x03, 0x00, 0x01, 0x28, 0x04, 0xD0, ++0x02, 0x28, 0x14, 0xBF, 0x07, 0x20, 0x0B, 0x20, 0x70, 0x47, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x10, 0xB4, 0x0E, 0x22, ++0x04, 0x46, 0x07, 0x20, 0x44, 0xFA, 0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, ++0x02, 0x02, 0x02, 0xD1, 0x11, 0xF0, 0xFF, 0x00, 0xF2, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xC3, 0x78, 0x33, 0xB9, ++0x83, 0x78, 0x33, 0xB9, 0x40, 0x78, 0x00, 0x28, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x02, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x23, 0x40, 0xFA, 0x03, 0xF2, 0x12, 0xF0, 0x01, 0x0F, 0xD9, 0xB2, 0x03, 0xF1, 0x01, 0x03, ++0x02, 0xD1, 0x0C, 0x2B, 0xF5, 0xD1, 0x19, 0x46, 0x08, 0x46, 0x70, 0x47, 0x68, 0xB1, 0x00, 0x23, 0xC3, 0xF1, 0x0B, 0x02, ++0x40, 0xFA, 0x02, 0xF2, 0xD2, 0x07, 0xD9, 0xB2, 0x03, 0xF1, 0x01, 0x03, 0x05, 0xD4, 0x0C, 0x2B, 0xF4, 0xD1, 0xFF, 0x20, ++0x70, 0x47, 0x0C, 0x20, 0x70, 0x47, 0xC1, 0xF1, 0x0B, 0x01, 0xC8, 0xB2, 0x70, 0x47, 0x00, 0xBF, 0xF0, 0xB5, 0xDD, 0xE9, ++0x05, 0x56, 0x00, 0x24, 0x1C, 0x80, 0x2C, 0x60, 0x34, 0x60, 0x50, 0xB3, 0x84, 0x78, 0xC4, 0xF3, 0x82, 0x0C, 0xBC, 0xF1, ++0x02, 0x0F, 0x04, 0xF0, 0x03, 0x04, 0x23, 0xDC, 0x4F, 0xF0, 0x01, 0x0C, 0x04, 0xF1, 0x0D, 0x00, 0x4F, 0xF0, 0x01, 0x0E, ++0x0E, 0xFA, 0x00, 0xF0, 0x07, 0x9F, 0x01, 0x38, 0x80, 0xB2, 0x87, 0xF8, 0x00, 0xC0, 0x18, 0x80, 0xF9, 0xB1, 0x09, 0x68, ++0xC1, 0xF3, 0xC2, 0x51, 0x01, 0xF1, 0x0D, 0x03, 0x0E, 0xFA, 0x03, 0xF3, 0x01, 0x3B, 0x2B, 0x60, 0x4A, 0xB1, 0x07, 0x29, ++0x11, 0xD1, 0xD3, 0x78, 0xC3, 0xF3, 0xC1, 0x03, 0x14, 0x33, 0x0E, 0xFA, 0x03, 0xF7, 0x01, 0x3F, 0x37, 0x60, 0xF0, 0xBD, ++0xAC, 0xF1, 0x03, 0x00, 0x4F, 0xF0, 0x01, 0x0C, 0x0C, 0xFA, 0x00, 0xFC, 0x5F, 0xFA, 0x8C, 0xFC, 0xD4, 0xE7, 0x33, 0x60, ++0xF0, 0xBD, 0x00, 0x2A, 0xF1, 0xD0, 0x03, 0x2C, 0x01, 0xD0, 0x30, 0x60, 0xF0, 0xBD, 0xD3, 0x78, 0xC3, 0xF3, 0xC1, 0x03, ++0x10, 0x33, 0x0E, 0xFA, 0x03, 0xF7, 0x01, 0x3F, 0x37, 0x60, 0xF0, 0xBD, 0x00, 0xF0, 0x7F, 0x03, 0x48, 0x2B, 0x31, 0xD8, ++0x10, 0xF0, 0x7E, 0x0F, 0x2C, 0xD0, 0x02, 0x3B, 0x46, 0x2B, 0x29, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x26, 0x28, 0x24, 0x28, ++0x28, 0x28, 0x28, 0x28, 0x28, 0x35, 0x37, 0x28, 0x28, 0x28, 0x28, 0x28, 0x39, 0x28, 0x28, 0x28, 0x3B, 0x28, 0x3D, 0x28, ++0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x3F, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, ++0x28, 0x28, 0x41, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, ++0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x33, 0x00, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0xFF, 0x20, 0x70, 0x47, ++0x60, 0x2B, 0x04, 0xD0, 0x6C, 0x2B, 0x14, 0xBF, 0xFF, 0x20, 0x0B, 0x20, 0x70, 0x47, 0x0A, 0x20, 0x70, 0x47, 0x09, 0x20, ++0x70, 0x47, 0x02, 0x20, 0x70, 0x47, 0x04, 0x20, 0x70, 0x47, 0x05, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x06, 0x20, ++0x70, 0x47, 0x07, 0x20, 0x70, 0x47, 0x08, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, 0x90, 0xF8, 0x00, 0xB0, ++0xBB, 0xF1, 0x00, 0x0F, 0x34, 0xD0, 0xDF, 0xF8, 0x70, 0x80, 0xDF, 0xF8, 0x70, 0xA0, 0xDF, 0xF8, 0x70, 0x90, 0x05, 0x46, ++0x0E, 0x46, 0x04, 0x46, 0x00, 0x27, 0x9E, 0xB9, 0x60, 0x78, 0xFF, 0xF7, 0x9B, 0xFF, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x4F, 0xF0, 0x01, 0x03, 0x0E, 0xDB, 0x0B, 0x28, 0x0E, 0xDD, 0x01, 0x34, 0x63, 0x1B, 0x5B, 0x45, ++0xED, 0xDB, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x94, 0xF9, 0x01, 0x30, 0x60, 0x78, 0x00, 0x2B, 0xE7, 0xDB, 0xF2, 0xE7, ++0x0B, 0x28, 0x04, 0xDC, 0x03, 0xFA, 0x00, 0xF0, 0x07, 0x43, 0xBF, 0xB2, 0xEB, 0xE7, 0x4F, 0xF4, 0x15, 0x72, 0x51, 0x46, ++0x48, 0x46, 0xFD, 0xF7, 0xC5, 0xF9, 0x95, 0xF8, 0x00, 0xB0, 0xE2, 0xE7, 0x5F, 0x46, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xB8, 0x15, 0x00, 0xF0, 0xB4, 0x00, 0x24, 0x4F, 0xF6, 0xFF, 0x77, ++0x03, 0x26, 0x40, 0xFA, 0x04, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x06, 0xFA, 0x04, 0xF2, 0x41, 0xFA, 0x04, 0xF5, 0x03, 0x2B, ++0x27, 0xEA, 0x02, 0x02, 0x05, 0xF0, 0x03, 0x05, 0x0A, 0xD0, 0x03, 0x2D, 0x08, 0xD0, 0xAB, 0x42, 0x28, 0xBF, 0x2B, 0x46, ++0xA3, 0x40, 0x02, 0x34, 0x1A, 0x43, 0x10, 0x2C, 0x97, 0xB2, 0xE6, 0xD1, 0x38, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0xBF, ++0x08, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x41, 0xF2, 0x21, 0x42, 0xD0, 0xF8, 0x90, 0x31, 0x98, 0x78, ++0x41, 0xF2, 0x21, 0x53, 0x01, 0x28, 0x14, 0xBF, 0x10, 0x46, 0x18, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0xD0, 0xF8, 0xDC, 0x30, 0xC3, 0xF3, 0x05, 0x60, 0x5B, 0x00, 0x54, 0xBF, 0x40, 0xF4, 0x80, 0x70, 0x40, 0xF4, 0x40, 0x70, ++0x70, 0x47, 0x00, 0xBF, 0x10, 0xB5, 0x04, 0x46, 0x0C, 0xF0, 0x86, 0xFB, 0x03, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x5C, 0x31, ++0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x90, 0xF8, 0xB8, 0x00, 0x18, 0xDB, 0x68, 0xB1, 0x05, 0xF1, 0xB8, 0x03, 0x1C, 0x18, ++0x00, 0x20, 0x13, 0xF8, 0x01, 0x2F, 0x22, 0xF0, 0x80, 0x01, 0x81, 0x42, 0xC8, 0xBF, 0x02, 0xF0, 0x7F, 0x00, 0xA3, 0x42, ++0xF5, 0xD1, 0xFF, 0xF7, 0xFF, 0xFE, 0x01, 0x46, 0x28, 0x46, 0x0C, 0xF0, 0x5F, 0xF9, 0x00, 0x23, 0x85, 0xF8, 0x56, 0x31, ++0x38, 0xBD, 0x00, 0x28, 0xE5, 0xD1, 0x05, 0x48, 0x05, 0x49, 0x40, 0xF2, 0xC1, 0x22, 0xFD, 0xF7, 0x25, 0xF9, 0x95, 0xF8, ++0xB8, 0x00, 0xDB, 0xE7, 0x38, 0x36, 0x17, 0x00, 0xB0, 0xB8, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x90, 0xF8, 0x56, 0x31, 0xD0, 0xF8, 0x48, 0x71, 0x99, 0xB0, 0x00, 0x2B, 0x00, 0xF0, 0xDB, 0x80, 0xFA, 0x6B, 0x09, 0x92, ++0x7A, 0x68, 0x05, 0x92, 0x07, 0xF1, 0x14, 0x04, 0xBA, 0x68, 0x07, 0x92, 0x10, 0xAE, 0x0D, 0xF1, 0x50, 0x08, 0x05, 0x46, ++0x22, 0x46, 0xB4, 0x46, 0x40, 0x46, 0x07, 0xF1, 0x24, 0x0B, 0x52, 0xF8, 0x04, 0x1B, 0x4C, 0xF8, 0x04, 0x1B, 0x5A, 0x45, ++0xD1, 0x68, 0x40, 0xF8, 0x04, 0x1B, 0xF6, 0xD1, 0x13, 0xF0, 0x01, 0x02, 0x06, 0x92, 0x40, 0xF0, 0xC0, 0x80, 0x09, 0x9A, ++0xC2, 0xF3, 0xC0, 0x02, 0x06, 0x92, 0x9A, 0x06, 0x00, 0xF1, 0x16, 0x81, 0x98, 0x07, 0x1A, 0xD5, 0xDF, 0xF8, 0x64, 0x93, ++0x06, 0xF1, 0x10, 0x0E, 0x31, 0x46, 0x51, 0xF8, 0x04, 0x2B, 0xC2, 0xF3, 0xC2, 0x2A, 0x02, 0xF0, 0x7C, 0x00, 0x5A, 0xEA, ++0x00, 0x00, 0xC2, 0xF3, 0xC1, 0x1C, 0x02, 0xEA, 0x09, 0x02, 0x06, 0xD0, 0xD5, 0xF8, 0x50, 0x01, 0x02, 0x43, 0x42, 0xEA, ++0x0C, 0x62, 0x41, 0xF8, 0x04, 0x2C, 0x8E, 0x45, 0xE9, 0xD1, 0xD9, 0x06, 0x5C, 0xD5, 0x95, 0xF8, 0x22, 0x10, 0xC3, 0x4A, ++0xC3, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x20, 0xD3, 0xF8, 0x38, 0x33, 0x0D, 0xF1, 0x3F, 0x02, 0x0D, 0xF1, ++0x3E, 0x01, 0x98, 0x47, 0x06, 0xF1, 0x10, 0x03, 0x06, 0x94, 0x08, 0x95, 0x0D, 0xF1, 0x50, 0x09, 0x1C, 0x46, 0x35, 0x46, ++0xBA, 0x4B, 0x59, 0xF8, 0x04, 0xAB, 0x55, 0xF8, 0x04, 0x1B, 0x93, 0xF8, 0xBD, 0x30, 0x4F, 0xEA, 0x1A, 0x4A, 0xC1, 0xF3, ++0xC7, 0x22, 0xC1, 0xF3, 0xC2, 0x20, 0x5F, 0xFA, 0x81, 0xFC, 0x4F, 0xEA, 0x0A, 0x4A, 0x01, 0xF0, 0x7F, 0x01, 0xD3, 0xB9, ++0x0C, 0xF0, 0x7C, 0x0C, 0x50, 0xEA, 0x0C, 0x03, 0x00, 0xF0, 0x29, 0x81, 0xAD, 0x4B, 0x93, 0xF8, 0xBA, 0x30, 0x00, 0x2B, ++0x00, 0xF0, 0xF3, 0x80, 0xAB, 0x4B, 0x93, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xED, 0x80, 0x00, 0x28, 0x40, 0xF0, ++0x2F, 0x81, 0x09, 0x29, 0x00, 0xF2, 0x2C, 0x81, 0x02, 0xF0, 0x06, 0x02, 0x2D, 0xE1, 0xD9, 0xF7, 0x47, 0xFE, 0xA4, 0x4B, ++0x1A, 0x7D, 0x00, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x5A, 0x7D, 0x00, 0x2A, 0x00, 0xF0, 0x02, 0x81, 0x4A, 0xEA, 0x00, 0x20, ++0x40, 0xF0, 0xA8, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xAC, 0x42, 0xBD, 0xD1, 0x08, 0x9D, 0x06, 0x9C, 0x95, 0xF8, 0x56, 0x31, ++0x5A, 0x06, 0x13, 0xD5, 0x94, 0x4A, 0x95, 0xF8, 0x22, 0x30, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x07, 0x9A, ++0xD3, 0xF8, 0xC8, 0x31, 0x22, 0xF0, 0x7C, 0x72, 0x00, 0x2B, 0x07, 0x92, 0x04, 0xDB, 0xC3, 0xF3, 0x05, 0x63, 0x42, 0xEA, ++0x03, 0x53, 0x07, 0x93, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x8D, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x8C, 0x4A, 0x05, 0x9B, 0x11, 0x68, 0x7B, 0x60, 0x48, 0x1C, 0x07, 0x9B, 0xBB, 0x60, 0x10, 0x60, 0x56, 0xF8, 0x04, 0x3B, ++0x44, 0xF8, 0x04, 0x3B, 0x58, 0xF8, 0x04, 0x3B, 0xE3, 0x60, 0xA3, 0x45, 0xF6, 0xD1, 0x28, 0xB1, 0x82, 0x4B, 0x11, 0x60, ++0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x00, 0x23, 0x85, 0xF8, 0x56, 0x31, 0x38, 0x46, 0x19, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0xD5, 0xF8, 0x4C, 0x01, 0x95, 0xF8, 0x30, 0x21, 0x0D, 0x92, 0xCD, 0xE9, 0x0B, 0x34, 0x00, 0x22, 0x08, 0x92, ++0x00, 0xF1, 0x88, 0x0E, 0x0A, 0x92, 0x31, 0x46, 0x82, 0x46, 0x3E, 0xF8, 0x02, 0x3B, 0x03, 0xEB, 0x43, 0x03, 0x0A, 0xEB, ++0x83, 0x03, 0x58, 0x89, 0xC0, 0xF3, 0x0D, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x4F, 0xEA, 0xD3, 0x29, 0x19, 0xF0, 0x06, 0x0C, ++0x00, 0xF0, 0x8E, 0x80, 0x09, 0xF0, 0x07, 0x09, 0xB9, 0xF1, 0x04, 0x0F, 0x03, 0xF0, 0x7F, 0x0C, 0x00, 0xF0, 0xE5, 0x80, ++0xB9, 0xF1, 0x05, 0x0F, 0x00, 0xF0, 0xE4, 0x80, 0xCC, 0xF3, 0xC1, 0x0C, 0x00, 0x2A, 0x00, 0xF0, 0xD1, 0x80, 0x08, 0x98, ++0x00, 0x28, 0x40, 0xF0, 0x95, 0x80, 0x08, 0x68, 0x20, 0xF0, 0x60, 0x40, 0x20, 0xF4, 0x7F, 0x50, 0x20, 0xF0, 0x3F, 0x00, ++0x18, 0x43, 0x08, 0x60, 0x01, 0x32, 0x04, 0x2A, 0x01, 0xF1, 0x04, 0x01, 0xCB, 0xD1, 0x05, 0x9A, 0x22, 0xF4, 0xC0, 0x71, ++0x08, 0x9A, 0x05, 0x91, 0xDD, 0xE9, 0x0B, 0x34, 0x22, 0xB1, 0x0A, 0x9A, 0x01, 0x32, 0x41, 0xEA, 0xC2, 0x12, 0x05, 0x92, ++0x06, 0x9A, 0x00, 0x2A, 0x7E, 0xD1, 0x09, 0x9A, 0x22, 0xF0, 0x08, 0x02, 0x43, 0xF0, 0x02, 0x03, 0xFA, 0x63, 0x9A, 0x06, ++0x85, 0xF8, 0x56, 0x31, 0x7F, 0xF5, 0xEA, 0xAE, 0xD5, 0xF8, 0x4C, 0x01, 0x7A, 0x69, 0x90, 0xF8, 0xA0, 0x30, 0xDF, 0xF8, ++0x38, 0xE1, 0x05, 0x99, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x0E, 0xEA, 0x02, 0x0E, 0xB3, 0xF8, 0x0A, 0xC0, ++0xCC, 0xF3, 0x0D, 0x02, 0xC1, 0xF3, 0xC1, 0x13, 0x42, 0xF0, 0x80, 0x42, 0x11, 0xF4, 0xC0, 0x7F, 0xCC, 0xF3, 0x80, 0x3C, ++0x4E, 0xEA, 0x02, 0x01, 0x03, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x80, 0xF8, 0xA1, 0xC0, 0xC0, 0xF8, 0x9C, 0x10, 0x4F, 0xF0, ++0x00, 0x02, 0x06, 0x98, 0x00, 0x93, 0x03, 0x90, 0x14, 0xBF, 0x01, 0x23, 0x13, 0x46, 0xCD, 0xE9, 0x01, 0x22, 0x38, 0x46, ++0x0C, 0xF0, 0x56, 0xFF, 0x95, 0xF8, 0x56, 0x31, 0xB6, 0xE6, 0x9D, 0xF8, 0x3F, 0x00, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, ++0x0A, 0x00, 0x02, 0xF0, 0x06, 0x02, 0x49, 0xF8, 0x04, 0x0C, 0x00, 0x2A, 0x3F, 0xF4, 0x20, 0xAF, 0x09, 0x29, 0x7F, 0xF6, ++0x1D, 0xAF, 0x29, 0x4B, 0x59, 0xF8, 0x04, 0x2C, 0x93, 0xF8, 0xAF, 0x10, 0x12, 0x0C, 0x41, 0xEA, 0x01, 0x21, 0x12, 0x04, ++0x0A, 0x43, 0x49, 0xF8, 0x04, 0x2C, 0x0F, 0xE7, 0x08, 0x68, 0xCD, 0xF8, 0x18, 0xC0, 0x20, 0xF0, 0x60, 0x40, 0x20, 0xF4, ++0x7F, 0x50, 0x20, 0xF0, 0x3F, 0x00, 0x18, 0x43, 0x08, 0x60, 0x83, 0xE7, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, 0x0A, 0x00, ++0x49, 0xF8, 0x04, 0x0C, 0xFC, 0xE6, 0x9D, 0xF8, 0x3E, 0x20, 0x42, 0xEA, 0x02, 0x22, 0x42, 0xEA, 0x0A, 0x02, 0x49, 0xF8, ++0x04, 0x2C, 0xF3, 0xE6, 0x0A, 0x98, 0xAC, 0xEB, 0x00, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x08, 0x90, 0x62, 0xE7, ++0x09, 0x9A, 0x42, 0xF0, 0x08, 0x02, 0x7F, 0xE7, 0x12, 0xF0, 0x06, 0x02, 0x0B, 0xD0, 0x04, 0x29, 0x09, 0xD8, 0x0C, 0x4B, ++0x93, 0xF8, 0xBB, 0x00, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, 0x0A, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xB5, 0xE7, 0x07, 0x4B, ++0xB3, 0xF8, 0xBB, 0x00, 0x40, 0xBA, 0x80, 0xB2, 0x40, 0xEA, 0x0A, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xAB, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xFF, 0x3F, 0x00, 0xE0, 0x00, 0xC0, 0xFF, 0x1F, 0x0D, 0x98, 0x84, 0x45, ++0x0A, 0x98, 0x38, 0xBF, 0x60, 0x46, 0x0A, 0x90, 0x08, 0x98, 0x38, 0xBF, 0x01, 0x20, 0x08, 0x90, 0x27, 0xE7, 0x4F, 0xEA, ++0x1C, 0x1C, 0x1D, 0xE7, 0x14, 0xAC, 0x03, 0xF4, 0xC0, 0x69, 0x54, 0xF8, 0x22, 0x40, 0xB9, 0xF5, 0x80, 0x6F, 0x0C, 0xBF, ++0x4F, 0xF4, 0x00, 0x39, 0x4F, 0xF4, 0x80, 0x39, 0x24, 0xF4, 0x40, 0x34, 0x44, 0xEA, 0x09, 0x09, 0x40, 0x04, 0x14, 0xAC, ++0x4C, 0xBF, 0x49, 0xF4, 0x80, 0x20, 0x29, 0xF4, 0x80, 0x20, 0x44, 0xF8, 0x22, 0x00, 0x4F, 0xEA, 0x1C, 0x1C, 0x01, 0xE7, ++0xF0, 0xB4, 0xD2, 0xF8, 0xA4, 0x50, 0x2C, 0x88, 0x30, 0xBB, 0x00, 0x29, 0x44, 0xD0, 0x51, 0x4E, 0x03, 0x46, 0x96, 0xF8, ++0x75, 0x01, 0x26, 0x46, 0x01, 0x28, 0x4F, 0xD9, 0x8F, 0x78, 0x17, 0xF0, 0x03, 0x07, 0x3C, 0xD0, 0xAD, 0x78, 0xCB, 0x78, ++0x09, 0x79, 0x00, 0x2D, 0x41, 0xD1, 0x5E, 0x1E, 0x0D, 0x2E, 0x40, 0xD8, 0x0E, 0x2B, 0x00, 0xF0, 0x86, 0x80, 0x03, 0xEB, ++0x83, 0x03, 0x03, 0xF6, 0x67, 0x13, 0x00, 0x29, 0x47, 0xD0, 0x03, 0x2F, 0x60, 0xD0, 0x02, 0x2F, 0x57, 0xD0, 0x02, 0x20, ++0x1C, 0x46, 0x00, 0x21, 0x03, 0x46, 0x05, 0xE0, 0x3E, 0x4B, 0x93, 0xF8, 0x75, 0x31, 0x5B, 0xB9, 0x18, 0x46, 0x00, 0x21, ++0xA2, 0xF8, 0xA8, 0x40, 0x82, 0xF8, 0xD8, 0x30, 0xF0, 0xBC, 0x82, 0xF8, 0xD9, 0x00, 0xA2, 0xF8, 0xAA, 0x10, 0x70, 0x47, ++0xC0, 0x78, 0x10, 0xF0, 0x03, 0x00, 0x12, 0xD0, 0x01, 0x28, 0x4F, 0xF6, 0xF6, 0x76, 0x08, 0xBF, 0x0A, 0x26, 0x26, 0x44, ++0xB6, 0xB2, 0x51, 0xBB, 0x01, 0x23, 0x34, 0x46, 0x18, 0x46, 0xE5, 0xE7, 0x08, 0x46, 0x0B, 0x46, 0xE2, 0xE7, 0x34, 0x46, ++0x39, 0x46, 0x18, 0x46, 0xDE, 0xE7, 0x99, 0xB1, 0x1F, 0x46, 0x26, 0x46, 0x03, 0x46, 0x38, 0x46, 0xB2, 0xE7, 0x01, 0x2D, ++0x1A, 0xD0, 0x4F, 0xF6, 0xFF, 0x73, 0xC2, 0xE7, 0x34, 0x46, 0xCF, 0xE7, 0x4F, 0xF6, 0xD8, 0x71, 0x9C, 0x42, 0x94, 0xBF, ++0x0C, 0x46, 0x28, 0x24, 0x23, 0x44, 0x9C, 0xB2, 0x03, 0x46, 0x00, 0x21, 0xC6, 0xE7, 0x02, 0x2F, 0x11, 0xD0, 0x03, 0x2F, ++0x20, 0xD0, 0x02, 0x20, 0x1C, 0x46, 0x03, 0x46, 0xBE, 0xE7, 0x18, 0x46, 0x01, 0x23, 0x95, 0xE7, 0x5E, 0x1E, 0xA4, 0x2E, ++0xE1, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x53, 0x08, 0x33, 0xA1, 0xE7, 0x02, 0x28, 0xDE, 0xD0, 0x03, 0x20, ++0x1C, 0x46, 0x00, 0x21, 0x03, 0x46, 0xAB, 0xE7, 0x85, 0xB9, 0x4C, 0x1E, 0x0D, 0x2C, 0x0A, 0xD8, 0x0E, 0x29, 0x19, 0xD0, ++0x01, 0xEB, 0x81, 0x01, 0x01, 0xF6, 0x67, 0x11, 0x04, 0x28, 0x94, 0xD1, 0x1C, 0x46, 0x03, 0x23, 0x9C, 0xE7, 0x4F, 0xF6, ++0xFF, 0x71, 0xF7, 0xE7, 0x01, 0x2D, 0xFA, 0xD1, 0x4C, 0x1E, 0xA4, 0x2C, 0xF7, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, ++0x9C, 0x51, 0x08, 0x31, 0xEC, 0xE7, 0x40, 0xF6, 0xB4, 0x13, 0x7A, 0xE7, 0x40, 0xF6, 0xB4, 0x11, 0xE6, 0xE7, 0x00, 0xBF, ++0xE4, 0xB8, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x7B, 0x4F, 0xDF, 0xF8, 0x08, 0x92, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x00, 0x73, 0x04, 0x46, 0x93, 0xF8, 0x22, 0x60, 0x58, 0x68, 0x77, 0x4B, 0x1B, 0x68, 0x10, 0xF0, 0x20, 0x0A, 0xB3, 0xF9, ++0x00, 0x30, 0x0D, 0x46, 0x90, 0x46, 0x4F, 0xD0, 0x00, 0x2B, 0xC0, 0xF2, 0x9F, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x04, 0x73, 0x0E, 0x21, 0xB3, 0xF8, 0x06, 0xC1, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, ++0x02, 0xF1, 0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, 0xB3, 0x80, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0x90, 0x46, ++0xB9, 0xF8, 0x50, 0xC0, 0x0E, 0x21, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, ++0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, 0x9B, 0x80, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0x5D, 0x4B, 0x4F, 0xF4, ++0x1E, 0x70, 0x00, 0xFB, 0x04, 0x74, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x06, 0x36, 0x94, 0xF8, 0x2C, 0x31, 0x96, 0xF8, ++0xC4, 0x11, 0x94, 0xF8, 0x23, 0x00, 0x04, 0x2B, 0x08, 0xBF, 0x03, 0x23, 0xA9, 0x42, 0x28, 0xBF, 0x29, 0x46, 0x99, 0x42, ++0x28, 0xBF, 0x19, 0x46, 0x84, 0xF8, 0x2D, 0x11, 0x0B, 0xF0, 0x22, 0xFD, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x08, 0x03, ++0x84, 0xF8, 0x56, 0x31, 0xBD, 0xE8, 0xF8, 0x8F, 0x10, 0xF0, 0x04, 0x0B, 0x28, 0xD0, 0x00, 0x2B, 0x58, 0xDB, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x04, 0x73, 0x0E, 0x22, 0xB3, 0xF8, 0xEC, 0xC0, 0x07, 0x20, 0x4C, 0xFA, 0x02, 0xF3, 0x03, 0xF0, ++0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, 0x6A, 0xD1, 0x11, 0xF0, 0xFF, 0x00, 0xF2, 0xD1, ++0xB9, 0xF8, 0x38, 0xC0, 0x0E, 0x21, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, ++0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x54, 0xD1, 0x10, 0xF0, 0xFF, 0x02, 0xF2, 0xD1, 0xAF, 0xE7, 0x00, 0x2B, 0x3A, 0xDB, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x73, 0x03, 0xF1, 0xCB, 0x02, 0x93, 0xF8, 0xCE, 0x30, 0x00, 0x2B, 0x54, 0xD1, ++0x93, 0x78, 0x00, 0x2B, 0x4B, 0xD1, 0x53, 0x78, 0x01, 0x20, 0x00, 0x2B, 0x48, 0xD1, 0x99, 0xF8, 0x12, 0x30, 0x00, 0x2B, ++0x4B, 0xD1, 0x99, 0xF8, 0x11, 0x30, 0x00, 0x2B, 0x49, 0xD1, 0x99, 0xF8, 0x10, 0x20, 0x00, 0x3A, 0x18, 0xBF, 0x01, 0x22, ++0x93, 0x45, 0x58, 0x46, 0x28, 0xBF, 0x10, 0x46, 0xC2, 0xB2, 0x89, 0xE7, 0x99, 0xF8, 0x76, 0x31, 0x59, 0x07, 0x3F, 0xF5, ++0x5C, 0xAF, 0x21, 0x49, 0x21, 0x48, 0x40, 0xF2, 0x55, 0x52, 0xFC, 0xF7, 0x99, 0xFD, 0x54, 0xE7, 0x99, 0xF8, 0x76, 0x31, ++0x9A, 0x07, 0xA2, 0xD4, 0x1B, 0x49, 0x1D, 0x48, 0x40, 0xF2, 0x62, 0x52, 0xFC, 0xF7, 0x8E, 0xFD, 0x9B, 0xE7, 0x99, 0xF8, ++0x76, 0x31, 0xDB, 0x07, 0xC0, 0xD4, 0x16, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x6D, 0x52, 0xFC, 0xF7, 0x83, 0xFD, 0xB9, 0xE7, ++0x42, 0x45, 0x28, 0xBF, 0x42, 0x46, 0xD2, 0xB2, 0x62, 0xE7, 0x90, 0x45, 0x28, 0xBF, 0x90, 0x46, 0x4C, 0xE7, 0x52, 0x45, ++0x28, 0xBF, 0x52, 0x46, 0xD2, 0xB2, 0x59, 0xE7, 0x40, 0x45, 0x28, 0xBF, 0x40, 0x46, 0x82, 0x46, 0x92, 0xE7, 0x02, 0x20, ++0x80, 0x45, 0x28, 0xBF, 0x80, 0x46, 0xC3, 0x46, 0xB1, 0xE7, 0x03, 0x20, 0xF8, 0xE7, 0x03, 0x22, 0xBA, 0xE7, 0x02, 0x22, ++0xB8, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC4, 0xB8, 0x15, 0x00, 0xD4, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x2D, 0xED, 0x02, 0x8B, 0xDF, 0xF8, 0xE4, 0xA3, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0xF3, 0x0A, 0xEB, 0x03, 0x06, ++0x8B, 0xB0, 0xB6, 0xF8, 0xC2, 0x41, 0x02, 0x93, 0x01, 0x90, 0xD6, 0xF8, 0x90, 0x31, 0x96, 0xF8, 0xC6, 0x51, 0x04, 0x95, ++0x00, 0x20, 0xA6, 0xF8, 0xC2, 0x01, 0x98, 0x78, 0x02, 0x9D, 0xD6, 0xF8, 0xC8, 0x31, 0x03, 0x94, 0x03, 0xF0, 0x7F, 0x43, ++0x05, 0xF1, 0xEC, 0x0C, 0x24, 0x32, 0x05, 0x93, 0x0A, 0xEB, 0x0C, 0x03, 0xD6, 0xF8, 0xE4, 0x40, 0x96, 0xF8, 0xC5, 0x71, ++0x08, 0xEE, 0x10, 0x2A, 0x08, 0xEE, 0x90, 0x3A, 0xA1, 0xF1, 0x24, 0x09, 0x00, 0x28, 0x00, 0xF0, 0xDD, 0x81, 0x1F, 0xFA, ++0x89, 0xF8, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x03, 0xA9, 0xD9, 0xF8, 0xCC, 0x31, 0xDD, 0x07, 0x05, 0xD5, ++0x99, 0xF8, 0x62, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x5C, 0x82, 0xD2, 0x4B, 0x93, 0xF8, 0x76, 0xB1, 0x1B, 0xF0, ++0x01, 0x0B, 0x40, 0xF0, 0xE9, 0x81, 0xD9, 0x46, 0x48, 0x46, 0x18, 0xEE, 0x90, 0x2A, 0x59, 0x46, 0xFF, 0xF7, 0xF8, 0xFD, ++0x02, 0x9B, 0x03, 0xF2, 0xB4, 0x43, 0x18, 0xEE, 0x10, 0x0A, 0x53, 0x44, 0x0D, 0xF1, 0x25, 0x02, 0x41, 0x46, 0xFD, 0xF7, ++0xD5, 0xFF, 0x10, 0xF0, 0xFF, 0x09, 0x1F, 0xD0, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x6B, 0x0B, 0xFB, 0x03, 0xAB, 0x9B, 0xF8, ++0x62, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x9D, 0x81, 0x9B, 0xF8, 0x8A, 0x10, 0x00, 0x29, 0x00, 0xF0, 0x6F, 0x82, 0x89, 0x45, ++0x07, 0xD0, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x01, 0x22, 0x83, 0xF8, 0x8C, 0x20, 0x01, 0x9A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x83, 0xF8, 0x8A, 0x90, 0x18, 0xEE, 0x90, 0x2A, 0x41, 0x46, 0x18, 0xEE, ++0x10, 0x0A, 0xFD, 0xF7, 0x25, 0xFF, 0x01, 0x9A, 0x04, 0x99, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x93, 0xF8, ++0xC6, 0x21, 0x8A, 0x42, 0x0E, 0xD0, 0xD3, 0xF8, 0x90, 0x11, 0xAC, 0x4B, 0x09, 0x79, 0xD3, 0xF8, 0x40, 0x33, 0x8A, 0x1A, ++0x8D, 0xF8, 0x26, 0x20, 0x0D, 0xF1, 0x26, 0x01, 0x0D, 0xF1, 0x27, 0x02, 0x30, 0x46, 0x98, 0x47, 0x01, 0x9B, 0x4F, 0xF4, ++0xA4, 0x68, 0x08, 0xFB, 0x03, 0xA8, 0x98, 0xF8, 0xC5, 0x31, 0xBB, 0x42, 0x00, 0xF2, 0x01, 0x81, 0x00, 0x2C, 0x00, 0xF0, ++0x8E, 0x80, 0x01, 0x9B, 0x9F, 0x4E, 0x03, 0x9D, 0xDD, 0xF8, 0x14, 0x90, 0x4F, 0xF4, 0xA4, 0x68, 0x08, 0xFB, 0x03, 0xA8, ++0xB8, 0xF8, 0xC2, 0x21, 0xAA, 0x42, 0x1D, 0xD0, 0x29, 0x46, 0x30, 0x46, 0xFC, 0xF7, 0x1A, 0xFA, 0x94, 0xF8, 0x56, 0x31, ++0xB8, 0xF8, 0xC2, 0x21, 0x94, 0xF8, 0x23, 0x00, 0x43, 0xF0, 0x02, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x53, 0x07, 0x4F, 0xF0, ++0x00, 0x01, 0x58, 0xBF, 0x4F, 0xF4, 0x80, 0x63, 0xC4, 0xF8, 0x50, 0x11, 0x4E, 0xBF, 0xA4, 0xF8, 0x54, 0x11, 0xA4, 0xF8, ++0x54, 0x31, 0x01, 0x21, 0x0B, 0xF0, 0x02, 0xFC, 0x98, 0xF8, 0xC5, 0x31, 0xBB, 0x42, 0x4B, 0xD0, 0x04, 0x2B, 0x94, 0xF8, ++0x2C, 0xA1, 0x5F, 0xD0, 0x53, 0x45, 0x28, 0xBF, 0x53, 0x46, 0x04, 0x2B, 0x00, 0xF0, 0x93, 0x80, 0x5F, 0xFA, 0x83, 0xFA, ++0x94, 0xF8, 0x2D, 0x31, 0x53, 0x45, 0x3B, 0xD0, 0x63, 0x68, 0x13, 0xF0, 0x20, 0x0B, 0x58, 0xD0, 0x7F, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA7, 0x80, 0xB4, 0xF8, 0x06, 0xC1, 0x0E, 0x22, 0x07, 0x20, 0x4C, 0xFA, ++0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, 0x02, 0xD1, 0x11, 0xF0, ++0xFF, 0x00, 0xF2, 0xD1, 0x70, 0x4B, 0x07, 0x22, 0xB3, 0xF8, 0x50, 0xE0, 0x0E, 0x23, 0x4E, 0xFA, 0x03, 0xF1, 0x01, 0xF0, ++0x03, 0x01, 0x03, 0x29, 0x02, 0xF1, 0xFF, 0x3C, 0xA3, 0xF1, 0x02, 0x03, 0x40, 0xF0, 0xF4, 0x80, 0x1C, 0xF0, 0xFF, 0x02, ++0xF1, 0xD1, 0x94, 0xF8, 0x23, 0x00, 0x84, 0xF8, 0x2D, 0xA1, 0x51, 0x46, 0x0B, 0xF0, 0x54, 0xFB, 0x94, 0xF8, 0x56, 0x31, ++0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x56, 0x31, 0xD8, 0xF8, 0xC8, 0x31, 0x03, 0xF0, 0x7F, 0x43, 0x4B, 0x45, 0x08, 0xD0, ++0x63, 0x68, 0x9B, 0x06, 0x05, 0xD5, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x24, 0x68, ++0x00, 0x2C, 0x7F, 0xF4, 0x7B, 0xAF, 0x0B, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0xBA, 0xF1, 0x03, 0x0F, ++0x35, 0xD8, 0xBA, 0xF1, 0x02, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, 0x02, 0x0A, 0x9E, 0xE7, 0x13, 0xF0, 0x04, 0x0F, 0x52, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x2B, 0xD0, 0x00, 0x2B, 0xC0, 0xF2, 0xA7, 0x80, 0xB4, 0xF8, 0xEC, 0xC0, 0x0E, 0x22, ++0x07, 0x20, 0x4C, 0xFA, 0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, ++0x40, 0xF0, 0x97, 0x81, 0x11, 0xF0, 0xFF, 0x00, 0xF1, 0xD1, 0x42, 0x4B, 0xB3, 0xF8, 0x38, 0xC0, 0x0E, 0x21, 0x07, 0x22, ++0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, 0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, ++0x7F, 0x81, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0xA1, 0xE7, 0x4F, 0xF0, 0x03, 0x0A, 0x6B, 0xE7, 0x00, 0x2B, 0x5E, 0xDB, ++0x94, 0xF8, 0xCE, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xDF, 0x81, 0x94, 0xF8, 0xCD, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xE0, 0x81, ++0x94, 0xF8, 0xCC, 0x20, 0x11, 0x1E, 0x18, 0xBF, 0x01, 0x21, 0x2E, 0x4A, 0x93, 0x7C, 0x00, 0x2B, 0x40, 0xF0, 0xD2, 0x81, ++0x53, 0x7C, 0x00, 0x2B, 0x40, 0xF0, 0xD0, 0x81, 0x13, 0x7C, 0x1A, 0x1E, 0x18, 0xBF, 0x01, 0x22, 0x8A, 0x42, 0x28, 0xBF, ++0x0A, 0x46, 0x7C, 0xE7, 0x25, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x58, 0x07, 0x3F, 0xF5, 0x53, 0xAF, 0x26, 0x49, 0x27, 0x48, ++0x40, 0xF2, 0xCD, 0x12, 0xFC, 0xF7, 0xA8, 0xFB, 0x4B, 0xE7, 0x0C, 0x23, 0x05, 0x22, 0x00, 0x21, 0x3B, 0x20, 0xFA, 0xF7, ++0xBF, 0xFA, 0x1F, 0x4B, 0xD8, 0xF8, 0x40, 0x20, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x81, 0x46, 0xC0, 0xF2, ++0x18, 0x81, 0x13, 0x7E, 0x89, 0xF8, 0x00, 0x30, 0xD6, 0xF8, 0x90, 0x31, 0x99, 0x78, 0x89, 0xF8, 0x02, 0x10, 0x96, 0xF8, ++0xC5, 0x11, 0x89, 0xF8, 0x03, 0x10, 0xB3, 0xF8, 0x00, 0xC0, 0xB6, 0xF8, 0x94, 0x01, 0xB6, 0xF8, 0x96, 0x11, 0xA9, 0xF8, ++0x08, 0x10, 0xA9, 0xF8, 0x06, 0x00, 0xA9, 0xF8, 0x04, 0xC0, 0x12, 0x7B, 0x89, 0xF8, 0x0A, 0x20, 0xDB, 0x78, 0x89, 0xF8, ++0x0B, 0x30, 0x48, 0x46, 0xFA, 0xF7, 0xC4, 0xFA, 0xCC, 0xE6, 0x06, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0xDA, 0x07, 0x9B, 0xD4, ++0x07, 0x49, 0x09, 0x48, 0x40, 0xF2, 0xE5, 0x12, 0xFC, 0xF7, 0x6A, 0xFB, 0x94, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x0C, 0xB9, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xC4, 0xB8, 0x15, 0x00, ++0xE4, 0xB8, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0xB9, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x99, 0x07, 0x3F, 0xF5, 0x53, 0xAF, ++0xB7, 0x49, 0xB8, 0x48, 0x4F, 0xF4, 0xED, 0x72, 0xFC, 0xF7, 0x4C, 0xFB, 0x4B, 0xE7, 0x02, 0x2B, 0x08, 0xBF, 0x8B, 0xF8, ++0xDB, 0x90, 0x73, 0xE6, 0x82, 0x42, 0x28, 0xBF, 0x02, 0x46, 0x0A, 0xE7, 0x1F, 0xFA, 0x89, 0xF8, 0x41, 0x46, 0x10, 0x46, ++0xFB, 0xF7, 0x42, 0xFA, 0x00, 0x28, 0x3F, 0xF4, 0x1A, 0xAE, 0xB6, 0xF8, 0xC2, 0x31, 0x82, 0x78, 0x23, 0xF0, 0x07, 0x03, ++0x9B, 0xB2, 0xD1, 0x07, 0x48, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0xA6, 0xF8, 0xC2, 0x31, 0x53, 0x07, 0x7F, 0xF5, 0x0B, 0xAE, ++0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0xB3, 0xF8, 0xC2, 0x21, 0x42, 0xF0, 0x04, 0x02, 0xA3, 0xF8, ++0xC2, 0x21, 0x00, 0xE6, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0xFB, 0xF7, 0x89, 0xFB, 0x9A, 0x4B, 0x93, 0xF8, 0x76, 0xB1, ++0x1B, 0xF0, 0x06, 0x0B, 0x81, 0x46, 0x3F, 0xF4, 0x0B, 0xAE, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0xFB, 0xF7, 0x9C, 0xFB, ++0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x83, 0x46, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0x00, 0xF0, ++0xAA, 0x80, 0x8E, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x59, 0x07, 0x7F, 0xF5, 0xF5, 0xAD, 0x18, 0xEE, 0x90, 0x2A, 0x18, 0xEE, ++0x10, 0x0A, 0x41, 0x46, 0xFD, 0xF7, 0xD6, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x09, 0x81, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x02, 0xA3, 0xD3, 0xF8, 0xC8, 0x31, 0xC3, 0xF3, 0x09, 0x12, 0x15, 0x46, 0xA2, 0xB1, 0x04, 0x23, 0x05, 0x22, ++0x00, 0x21, 0x6F, 0x20, 0xFA, 0xF7, 0xFE, 0xF9, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xA2, 0x06, 0x92, ++0x92, 0xF8, 0x63, 0x10, 0x81, 0x70, 0x05, 0x80, 0xFA, 0xF7, 0x22, 0xFA, 0x06, 0x9A, 0xD2, 0xF8, 0xC8, 0x31, 0x05, 0x9A, ++0x03, 0xF0, 0x7F, 0x43, 0x93, 0x42, 0x3F, 0xF4, 0xC5, 0xAD, 0x04, 0x23, 0x05, 0x22, 0x00, 0x21, 0x71, 0x20, 0xFA, 0xF7, ++0xE3, 0xF9, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0xD3, 0xF8, 0xC8, 0x21, 0xC2, 0xF3, 0x05, 0x63, ++0x52, 0x00, 0x54, 0xBF, 0x43, 0xF4, 0x80, 0x73, 0x43, 0xF4, 0x40, 0x73, 0x03, 0x60, 0xFA, 0xF7, 0x01, 0xFA, 0xAB, 0xE5, ++0x02, 0x9B, 0x03, 0xF5, 0xD6, 0x72, 0x52, 0x44, 0x0D, 0xF1, 0x27, 0x03, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0x06, 0x92, ++0xFD, 0xF7, 0x92, 0xFE, 0x9D, 0xF8, 0x27, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x93, 0xAD, 0x06, 0x9A, 0x06, 0x97, 0x03, 0x9F, ++0x25, 0x46, 0x4C, 0x46, 0x91, 0x46, 0x08, 0x23, 0x05, 0x22, 0x00, 0x21, 0x1A, 0x20, 0xFA, 0xF7, 0xB3, 0xF9, 0x59, 0xF8, ++0x04, 0x1B, 0x80, 0xF8, 0x05, 0xB0, 0x94, 0xF8, 0x63, 0x20, 0x82, 0x71, 0x4F, 0xF0, 0x00, 0x02, 0x01, 0x60, 0x0B, 0xF1, ++0x01, 0x0B, 0x02, 0x71, 0xFA, 0xF7, 0xD4, 0xF9, 0xBB, 0xF1, 0x04, 0x0F, 0xE7, 0xD1, 0x03, 0x97, 0x2C, 0x46, 0x06, 0x9F, ++0x70, 0xE5, 0x00, 0x2A, 0x7F, 0xF4, 0xE5, 0xAE, 0x45, 0x22, 0x4C, 0x49, 0x4D, 0x48, 0xFC, 0xF7, 0x77, 0xFA, 0xD8, 0xF8, ++0x40, 0x20, 0xDC, 0xE6, 0x9B, 0xF8, 0x8C, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x96, 0xAD, 0x9D, 0xF8, 0x25, 0x30, 0x01, 0x2B, ++0x7F, 0xF4, 0x91, 0xAD, 0x46, 0x4B, 0x9B, 0xF8, 0x63, 0x00, 0xD3, 0xF8, 0xC0, 0x31, 0x98, 0x47, 0x9B, 0xF8, 0x8A, 0x10, ++0x00, 0x29, 0x3F, 0xF4, 0x86, 0xAD, 0x7A, 0xE5, 0x5A, 0x45, 0x28, 0xBF, 0x5A, 0x46, 0xD2, 0xB2, 0x21, 0xE6, 0x83, 0x46, ++0x69, 0xE6, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0x06, 0x93, 0xFB, 0xF7, 0x77, 0xF9, 0xB0, 0xB1, 0x06, 0x9B, 0x3A, 0x49, ++0x93, 0xF8, 0x6C, 0x20, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, 0x5B, 0x68, 0x13, 0xF0, 0x24, 0x0F, 0x0A, 0xD0, ++0x90, 0xF9, 0x02, 0x30, 0x81, 0x78, 0x00, 0x2B, 0x05, 0xDB, 0x10, 0x46, 0x0A, 0x09, 0x01, 0xF0, 0x03, 0x01, 0xFF, 0xF7, ++0xDD, 0xFB, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x06, 0x93, 0xD3, 0xF8, 0xCC, 0x31, 0x18, 0x07, ++0x7F, 0xF5, 0x2D, 0xAF, 0x02, 0x23, 0x05, 0x22, 0x00, 0x21, 0x6D, 0x20, 0xFA, 0xF7, 0x46, 0xF9, 0x41, 0x46, 0x02, 0x46, ++0x07, 0x90, 0x18, 0xEE, 0x10, 0x0A, 0xFD, 0xF7, 0x45, 0xFF, 0x07, 0x9A, 0x10, 0x46, 0xFA, 0xF7, 0x6B, 0xF9, 0x22, 0x4B, ++0x1B, 0x69, 0x00, 0x2B, 0x3F, 0xF4, 0x17, 0xAF, 0x02, 0x9B, 0x03, 0xF5, 0xA8, 0x72, 0x18, 0xEE, 0x10, 0x0A, 0x0D, 0xF1, ++0x27, 0x03, 0x52, 0x44, 0x41, 0x46, 0xFD, 0xF7, 0x05, 0xFF, 0x9D, 0xF8, 0x27, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x07, 0xAF, ++0x10, 0x23, 0x05, 0x22, 0x00, 0x21, 0x6B, 0x20, 0xFA, 0xF7, 0x20, 0xF9, 0x06, 0x9A, 0x11, 0x46, 0x15, 0x46, 0xD2, 0xF8, ++0x50, 0xE1, 0xD2, 0xF8, 0x54, 0x21, 0xD1, 0xF8, 0x58, 0x11, 0xD5, 0xF8, 0x5C, 0x51, 0xC5, 0x60, 0xC0, 0xE9, 0x00, 0xE2, ++0x81, 0x60, 0xFA, 0xF7, 0x3F, 0xF9, 0xEE, 0xE6, 0x03, 0x21, 0x28, 0xE6, 0x03, 0x22, 0x33, 0xE6, 0x02, 0x22, 0x31, 0xE6, ++0x02, 0x21, 0x22, 0xE6, 0x40, 0xF2, 0xFF, 0x33, 0x1D, 0x46, 0xFD, 0xE6, 0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xD4, 0xB8, 0x15, 0x00, 0xF4, 0xB8, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, ++0x70, 0xB5, 0x0C, 0x46, 0x84, 0xB0, 0x89, 0x78, 0x0C, 0x4D, 0x26, 0x79, 0x8D, 0xF8, 0x04, 0x10, 0xAD, 0xF8, 0x08, 0x20, ++0x01, 0x46, 0x9D, 0xF8, 0x20, 0x20, 0x20, 0x88, 0xE4, 0x78, 0xAD, 0xF8, 0x0A, 0x30, 0xAD, 0xF8, 0x06, 0x00, 0x6B, 0x6C, ++0x8D, 0xF8, 0x0C, 0x60, 0x8D, 0xF8, 0x0D, 0x40, 0x8D, 0xF8, 0x05, 0x20, 0x01, 0xA8, 0x98, 0x47, 0x04, 0xB0, 0x70, 0xBD, ++0x88, 0x1A, 0x17, 0x00, 0x03, 0x68, 0x30, 0xB4, 0x0C, 0x68, 0x5A, 0x40, 0x84, 0xEA, 0xF2, 0x34, 0x22, 0x44, 0x13, 0x0A, ++0x15, 0x02, 0x05, 0xF0, 0xFF, 0x25, 0x03, 0xF0, 0xFF, 0x13, 0x2B, 0x43, 0x63, 0x40, 0x1A, 0x44, 0x83, 0xEA, 0x72, 0x73, ++0x1A, 0x44, 0x83, 0xEA, 0xB2, 0x03, 0x1A, 0x44, 0x0B, 0x60, 0x30, 0xBC, 0x02, 0x60, 0x70, 0x47, 0xF8, 0xB5, 0x1F, 0x88, ++0xD3, 0xF8, 0x02, 0x50, 0x0B, 0x68, 0x96, 0x88, 0x12, 0x68, 0x03, 0x60, 0x9D, 0xF8, 0x18, 0x40, 0x4B, 0x68, 0x43, 0x60, ++0x00, 0x23, 0xFF, 0x2C, 0x83, 0x60, 0x03, 0x73, 0x00, 0xF1, 0x04, 0x01, 0x46, 0xEA, 0x07, 0x46, 0x14, 0xBF, 0x04, 0xF0, ++0x07, 0x04, 0x00, 0x24, 0xFF, 0xF7, 0xCC, 0xFF, 0x32, 0x46, 0xFF, 0xF7, 0xC9, 0xFF, 0x2A, 0x46, 0xFF, 0xF7, 0xC6, 0xFF, ++0x22, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0xC1, 0xBF, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x21, 0xF0, 0x03, 0x06, ++0x01, 0xF0, 0x03, 0x01, 0xC1, 0xF1, 0x04, 0x03, 0x37, 0x68, 0x90, 0xF8, 0x0C, 0xC0, 0x85, 0x68, 0xDB, 0xB2, 0x04, 0x36, ++0xC9, 0x00, 0x9A, 0x42, 0x83, 0xB0, 0x27, 0xFA, 0x01, 0xF1, 0xB1, 0x46, 0x78, 0xD2, 0xC2, 0xF1, 0x04, 0x04, 0xE3, 0x00, ++0x4F, 0xF0, 0xFF, 0x34, 0x4F, 0xF0, 0x00, 0x0B, 0xDC, 0x40, 0x21, 0x40, 0xD8, 0x46, 0x5F, 0x46, 0x0C, 0xEB, 0x02, 0x04, ++0x03, 0x2C, 0x52, 0xD8, 0x4F, 0xEA, 0xCC, 0x0C, 0x01, 0xFA, 0x0C, 0xF1, 0x0D, 0x43, 0xB8, 0xF1, 0x00, 0x0F, 0x22, 0xD0, ++0xE3, 0x00, 0xC4, 0xF1, 0x04, 0x0A, 0x00, 0x93, 0x4F, 0xEA, 0x88, 0x03, 0x4F, 0xEA, 0xCA, 0x0A, 0x01, 0x1D, 0x01, 0x93, ++0x06, 0xEB, 0x88, 0x08, 0xB1, 0x46, 0xD9, 0xF8, 0x00, 0x30, 0x00, 0x9A, 0x03, 0xFA, 0x02, 0xF2, 0xBA, 0xF1, 0x20, 0x0F, ++0x42, 0xEA, 0x05, 0x02, 0x09, 0xF1, 0x04, 0x09, 0x14, 0xBF, 0x23, 0xFA, 0x0A, 0xF5, 0x00, 0x25, 0xFF, 0xF7, 0x76, 0xFF, ++0xC1, 0x45, 0xEC, 0xD1, 0x01, 0x9B, 0x33, 0x44, 0x99, 0x46, 0x5F, 0x45, 0x20, 0xD9, 0x07, 0xF0, 0x03, 0x07, 0xC7, 0xF1, ++0x04, 0x03, 0xDA, 0x00, 0x20, 0x2A, 0xD9, 0xF8, 0x00, 0x10, 0x40, 0xD0, 0x4F, 0xF0, 0xFF, 0x33, 0xD3, 0x40, 0x0B, 0x40, ++0xE2, 0x00, 0x03, 0xFA, 0x02, 0xF2, 0x15, 0x43, 0x27, 0x44, 0x03, 0x2F, 0x2F, 0xD9, 0xC4, 0xF1, 0x04, 0x04, 0xE4, 0x00, ++0x20, 0x2C, 0x14, 0xBF, 0xE3, 0x40, 0x00, 0x23, 0x2A, 0x46, 0x01, 0x1D, 0x3C, 0x1F, 0x1D, 0x46, 0xFF, 0xF7, 0x4E, 0xFF, ++0x85, 0x60, 0x04, 0x73, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xEA, 0xCC, 0x02, 0xCC, 0xF1, 0x04, 0x0C, 0x4F, 0xEA, ++0xCC, 0x0C, 0xBC, 0xF1, 0x20, 0x0F, 0x01, 0xFA, 0x02, 0xF2, 0x42, 0xEA, 0x05, 0x02, 0x18, 0xBF, 0x21, 0xFA, 0x0C, 0xF5, ++0x00, 0xF1, 0x04, 0x01, 0x08, 0xBF, 0x00, 0x25, 0x04, 0x3C, 0xFF, 0xF7, 0x33, 0xFF, 0x9A, 0xE7, 0xD7, 0x1A, 0x4F, 0xEA, ++0x97, 0x08, 0x1A, 0x46, 0x27, 0xF0, 0x03, 0x0B, 0x8A, 0xE7, 0x3C, 0x46, 0x85, 0x60, 0x04, 0x73, 0x03, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x00, 0x23, 0xC4, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x10, 0x4B, 0x85, 0x68, 0x1B, 0x68, 0x02, 0x7B, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x0D, 0xDB, 0x5A, 0x23, 0xD2, 0x00, 0x03, 0xFA, 0x02, 0xF2, 0x2A, 0x43, 0x21, 0x1D, ++0x20, 0x46, 0xFF, 0xF7, 0x0F, 0xFF, 0xBD, 0xE8, 0x38, 0x40, 0x00, 0x22, 0xFF, 0xF7, 0x0A, 0xBF, 0x03, 0x2A, 0xEF, 0xD9, ++0x40, 0xF2, 0x41, 0x12, 0x03, 0x49, 0x04, 0x48, 0xFC, 0xF7, 0xB8, 0xF8, 0x22, 0x7B, 0xE7, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x20, 0xB9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x06, 0x20, 0x83, 0xB0, 0x00, 0x24, 0xCD, 0xE9, ++0x00, 0x44, 0x91, 0xF8, 0x3D, 0x90, 0x0D, 0x46, 0x17, 0x46, 0x1E, 0x46, 0xFA, 0xF7, 0x62, 0xFA, 0x09, 0x28, 0x79, 0xD0, ++0x01, 0x23, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF6, 0x01, 0x00, 0xF9, 0xF7, 0xB7, 0xFF, 0x80, 0x46, 0x06, 0x20, 0xFA, 0xF7, ++0x55, 0xFA, 0x48, 0xB1, 0x08, 0x26, 0x40, 0x46, 0x88, 0xF8, 0x00, 0x60, 0xF9, 0xF7, 0xDC, 0xFF, 0x20, 0x46, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, 0xAC, 0xA1, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0xA3, 0x93, 0xF8, 0x62, 0x20, ++0x00, 0x2A, 0x4F, 0xD1, 0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x4B, 0xD1, 0xDF, 0xF8, 0x94, 0xB1, 0x5A, 0x4A, 0x5B, 0x49, ++0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x95, 0xF8, 0x3B, 0x30, 0x01, 0x22, 0x02, 0x2B, 0xCA, 0x75, 0x0E, 0xD0, ++0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0xA2, 0x92, 0xF8, 0x64, 0x10, 0x29, 0xB9, 0x53, 0x4C, 0x21, 0x68, 0xB1, 0xF9, ++0x00, 0x10, 0x00, 0x29, 0x7F, 0xDB, 0x03, 0x2B, 0x57, 0xD0, 0x3A, 0x46, 0x4F, 0xF4, 0x55, 0x73, 0x31, 0x46, 0x41, 0xF6, ++0x02, 0x00, 0xCB, 0xF8, 0x00, 0x50, 0xF9, 0xF7, 0x73, 0xFF, 0x95, 0xF8, 0x3B, 0x30, 0xCB, 0xF8, 0x04, 0x00, 0x00, 0x27, ++0x02, 0x2B, 0x8B, 0xF8, 0x16, 0x70, 0x4F, 0xD0, 0x9B, 0xF8, 0x1E, 0x60, 0x3E, 0xB3, 0x95, 0xF8, 0x3D, 0x10, 0x44, 0x48, ++0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x01, 0xA1, 0x06, 0x22, 0x38, 0x31, 0x0E, 0xF0, 0xE4, 0xFA, 0x09, 0x21, 0x06, 0x20, ++0xFA, 0xF7, 0x52, 0xF9, 0x95, 0xF8, 0x3D, 0x00, 0x39, 0x46, 0x04, 0xFB, 0x00, 0xA0, 0x01, 0xF0, 0xCB, 0xF8, 0x3E, 0x46, ++0x01, 0x24, 0x9C, 0xE7, 0x95, 0xF8, 0x3B, 0x30, 0x02, 0x2B, 0xAF, 0xD0, 0x2C, 0x6B, 0x14, 0xF0, 0x20, 0x04, 0x17, 0xD1, ++0x09, 0x26, 0x92, 0xE7, 0x02, 0x24, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0xA9, 0x68, 0x46, 0x00, 0xF0, ++0x75, 0xFD, 0xDD, 0xE9, 0x00, 0x01, 0x28, 0xB1, 0x21, 0xB1, 0x32, 0x46, 0x00, 0xF0, 0x14, 0xFE, 0x01, 0x24, 0x80, 0xE7, ++0x00, 0xF0, 0x90, 0xFD, 0x01, 0x24, 0x7C, 0xE7, 0xDF, 0xF8, 0xBC, 0xB0, 0x28, 0x48, 0x01, 0x23, 0x8B, 0xF8, 0x1E, 0x30, ++0xFB, 0xF7, 0x8E, 0xFD, 0x8C, 0xE7, 0xE9, 0x8E, 0x05, 0xF1, 0x40, 0x00, 0x02, 0xF0, 0x32, 0xF8, 0x00, 0x28, 0xC4, 0xBF, ++0x00, 0x23, 0x85, 0xF8, 0x3B, 0x30, 0x9C, 0xE7, 0x95, 0xF8, 0x3D, 0x10, 0x1F, 0x48, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, ++0x01, 0xA1, 0x06, 0x22, 0x38, 0x31, 0x01, 0x24, 0x8B, 0xF8, 0x16, 0x40, 0x0E, 0xF0, 0x94, 0xFA, 0x09, 0x21, 0x06, 0x20, ++0xFA, 0xF7, 0x02, 0xF9, 0x95, 0xF8, 0x3D, 0x00, 0x39, 0x46, 0x06, 0xFB, 0x00, 0xA0, 0x01, 0xF0, 0x7B, 0xF8, 0x3E, 0x46, ++0x4D, 0xE7, 0x92, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x09, 0xD0, 0x12, 0x49, 0x12, 0x48, 0x64, 0x22, 0xFB, 0xF7, 0xD8, 0xFF, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0B, 0xDA, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0xA9, 0xD9, 0xF8, ++0x40, 0x30, 0x23, 0xB1, 0x09, 0x49, 0x0B, 0x48, 0x65, 0x22, 0xFB, 0xF7, 0xC7, 0xFF, 0x95, 0xF8, 0x3B, 0x30, 0x62, 0xE7, ++0x94, 0x40, 0x04, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x84, 0xBA, 0x17, 0x00, 0x40, 0xB9, 0x15, 0x00, ++0x7C, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x4C, 0xB9, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x64, 0xBA, 0x17, 0x00, 0x38, 0xB5, 0x0B, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0F, 0x49, 0x1C, 0x78, 0xFB, 0xF7, 0x7C, 0xFD, ++0x06, 0x20, 0xFA, 0xF7, 0x63, 0xF9, 0xA8, 0xB9, 0x0C, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, ++0x62, 0x50, 0x15, 0xB9, 0x94, 0xF8, 0x64, 0x00, 0x00, 0xB9, 0x38, 0xBD, 0x09, 0x21, 0x06, 0x20, 0xFA, 0xF7, 0xAA, 0xF8, ++0x20, 0x46, 0x01, 0x21, 0x01, 0xF0, 0x26, 0xF8, 0x28, 0x46, 0x38, 0xBD, 0x02, 0x20, 0x38, 0xBD, 0x70, 0xB9, 0x15, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x08, 0xB5, 0x06, 0x20, 0xFA, 0xF7, 0x42, 0xF9, 0x05, 0x28, 0x04, 0xD0, 0x06, 0x20, 0xFA, 0xF7, ++0x3D, 0xF9, 0x06, 0x28, 0x04, 0xD1, 0x01, 0x20, 0x01, 0xF0, 0x9C, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xFA, 0xF7, ++0x33, 0xF9, 0x07, 0x28, 0xF5, 0xD0, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x16, 0x4B, 0x00, 0xB5, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x20, 0x00, 0x23, 0x83, 0xB0, 0x9A, 0x42, 0xCD, 0xE9, 0x00, 0x33, 0x15, 0xDB, 0x68, 0x46, 0x01, 0xA9, 0x00, 0xF0, ++0xB7, 0xFC, 0x00, 0x98, 0x40, 0xB1, 0x01, 0x99, 0x31, 0xB1, 0x00, 0x22, 0x00, 0xF0, 0x56, 0xFD, 0x00, 0x20, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0xFB, 0x01, 0x20, 0x01, 0xF0, 0x75, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x06, 0x20, ++0xFA, 0xF7, 0x0A, 0xF9, 0x01, 0x28, 0xE4, 0xD0, 0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x8F, 0x72, 0xFB, 0xF7, 0x42, 0xFF, ++0xDD, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x80, 0xB9, 0x15, 0x00, 0x93, 0x4B, 0x2D, 0xE9, ++0xF0, 0x4F, 0x1B, 0x68, 0x92, 0x4D, 0xB3, 0xF9, 0x00, 0x30, 0x2F, 0x68, 0x00, 0x2B, 0x89, 0xB0, 0xC0, 0xF2, 0x91, 0x80, ++0x97, 0xF8, 0x3D, 0x80, 0x8E, 0x4E, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x08, 0x64, 0xD4, 0xF8, 0xCC, 0x31, 0x00, 0x2B, ++0x18, 0xDB, 0x6B, 0x7D, 0x33, 0xB9, 0x01, 0x20, 0x01, 0xF0, 0x42, 0xF9, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x00, 0x23, 0x07, 0xA9, 0x06, 0xA8, 0xCD, 0xE9, 0x06, 0x33, 0x00, 0xF0, 0x6B, 0xFC, 0xDD, 0xE9, 0x06, 0x01, 0x01, 0x22, ++0x00, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x07, 0xA8, 0x00, 0xF0, 0xE1, 0xFD, 0x00, 0x28, ++0x74, 0xD1, 0x01, 0x46, 0x20, 0x23, 0x06, 0x22, 0x0A, 0x20, 0xF9, 0xF7, 0x1D, 0xFE, 0x94, 0xF8, 0xC0, 0x34, 0x05, 0x46, ++0x2B, 0xB1, 0xD4, 0xF8, 0xCC, 0x21, 0x22, 0xF0, 0x08, 0x02, 0xC4, 0xF8, 0xCC, 0x21, 0x74, 0x4A, 0x92, 0xF8, 0x04, 0x21, ++0x4A, 0xB1, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x08, 0xF2, 0xB1, 0x18, 0xD1, 0xF8, 0x90, 0x01, 0x80, 0x78, 0x01, 0x28, ++0x6D, 0xD0, 0x6E, 0x4B, 0x97, 0xF8, 0x3D, 0x00, 0xDB, 0x6C, 0x9D, 0xF8, 0x1C, 0x10, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x6B, ++0x00, 0x23, 0x2B, 0x60, 0x0B, 0xFB, 0x08, 0xFB, 0x97, 0xF8, 0x3D, 0x20, 0x6A, 0x76, 0x06, 0xEB, 0x0B, 0x0A, 0xDA, 0xF8, ++0x64, 0x01, 0xBA, 0xF8, 0x68, 0x21, 0xAB, 0x76, 0x9A, 0xF8, 0x8B, 0x31, 0x6B, 0x77, 0x9A, 0xF8, 0x8C, 0x31, 0xAB, 0x77, ++0xDA, 0xF8, 0xCC, 0x31, 0xC5, 0xF8, 0x12, 0x00, 0x13, 0xF0, 0x02, 0x04, 0xEA, 0x82, 0x1B, 0xD0, 0x0B, 0xF1, 0xEC, 0x09, ++0x13, 0xF0, 0x04, 0x04, 0xB1, 0x44, 0x6E, 0xD1, 0x21, 0x46, 0x13, 0xF0, 0x08, 0x02, 0x05, 0xF1, 0x18, 0x03, 0x18, 0xBF, ++0x0B, 0xF5, 0x8C, 0x72, 0x05, 0xF1, 0x04, 0x0C, 0x02, 0x93, 0x05, 0xF1, 0x08, 0x03, 0xCD, 0xE9, 0x00, 0x3C, 0x18, 0xBF, ++0x92, 0x19, 0x48, 0x46, 0x05, 0xF1, 0x10, 0x03, 0xFE, 0xF7, 0x22, 0xFC, 0x28, 0x46, 0xEC, 0x60, 0xF9, 0xF7, 0xF0, 0xFD, ++0x03, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0xB6, 0xFF, 0x0F, 0xE0, 0x06, 0x20, 0xFA, 0xF7, 0x5A, 0xF8, 0x02, 0x28, 0x3F, 0xF4, ++0x69, 0xAF, 0x47, 0x49, 0x47, 0x48, 0x4F, 0xF4, 0xA3, 0x72, 0xFB, 0xF7, 0x91, 0xFE, 0x61, 0xE7, 0x01, 0x20, 0x01, 0xF0, ++0xB1, 0xF8, 0x3A, 0x6B, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x66, 0x53, 0x07, 0xC6, 0xF8, 0xB0, 0x24, 0x7F, 0xF5, ++0x65, 0xAF, 0xD6, 0xF8, 0xCC, 0x31, 0x00, 0x20, 0x23, 0xF0, 0x0E, 0x03, 0xC6, 0xF8, 0xCC, 0x31, 0x09, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0xD1, 0xF8, 0xCC, 0x11, 0x11, 0xF0, 0x0C, 0x0F, 0x8C, 0xD0, 0x00, 0x2B, 0x8A, 0xD1, 0xDF, 0xF8, 0xD8, 0x90, ++0x02, 0xF5, 0xB2, 0x72, 0xB4, 0x18, 0x9A, 0x46, 0xCB, 0x46, 0x58, 0x46, 0x06, 0x22, 0x21, 0x46, 0x0E, 0xF0, 0xDC, 0xF8, ++0x0B, 0xF1, 0x14, 0x0B, 0x18, 0xB3, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x05, 0x0F, 0xF2, 0xD1, 0x2C, 0x49, 0x50, 0x22, ++0x01, 0xF1, 0x14, 0x00, 0x0E, 0xF0, 0xFE, 0xF8, 0x29, 0x48, 0x21, 0x46, 0x06, 0x22, 0x0E, 0xF0, 0xF9, 0xF8, 0x01, 0x23, ++0xA9, 0xF8, 0x06, 0x30, 0x89, 0xF8, 0x08, 0x30, 0x65, 0xE7, 0x0B, 0xF5, 0xB2, 0x70, 0x0B, 0xF5, 0x86, 0x71, 0x31, 0x44, ++0x30, 0x44, 0x05, 0x91, 0xFA, 0xF7, 0x28, 0xFF, 0xDA, 0xF8, 0xCC, 0x31, 0x05, 0x99, 0x04, 0x46, 0x83, 0xE7, 0x0A, 0xEB, ++0x8A, 0x03, 0x09, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0x8A, 0x0B, 0x9A, 0x79, 0x14, 0x23, 0x03, 0xFB, 0x0A, 0x93, 0x4A, 0xB1, ++0xDB, 0x79, 0x53, 0xB1, 0x0B, 0xEB, 0x0A, 0x03, 0x09, 0xEB, 0x83, 0x09, 0x01, 0x23, 0x89, 0xF8, 0x08, 0x30, 0x42, 0xE7, ++0x01, 0x22, 0x9A, 0x71, 0xF4, 0xE7, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x08, 0x64, 0x00, 0x92, 0xB4, 0xF8, 0x68, 0x31, ++0xB4, 0xF8, 0x66, 0x21, 0xB4, 0xF8, 0x64, 0x11, 0x0C, 0x48, 0xFB, 0xF7, 0x9F, 0xFB, 0xD4, 0xF8, 0xCC, 0x31, 0x23, 0xF0, ++0x0C, 0x03, 0xC4, 0xF8, 0xCC, 0x31, 0xDF, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x2C, 0x19, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xB9, 0x15, 0x00, 0xCC, 0x35, 0x17, 0x00, ++0xCC, 0xB9, 0x15, 0x00, 0x08, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x06, 0x20, ++0xF9, 0xF7, 0xB6, 0xFF, 0x04, 0x28, 0x06, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0xB1, 0xFF, 0x09, 0x28, 0x01, 0xD0, 0x00, 0x20, ++0x08, 0xBD, 0x00, 0xF0, 0xF5, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0xA6, 0xFF, 0x04, 0x28, 0xEA, 0xD0, ++0x06, 0x20, 0xF9, 0xF7, 0xA1, 0xFF, 0x00, 0x28, 0xE5, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0x9C, 0xFF, 0x09, 0x28, 0xE0, 0xD0, ++0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x16, 0x72, 0xFB, 0xF7, 0xD4, 0xFD, 0xD9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xE4, 0xB9, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x03, 0xDB, 0x00, 0xF0, 0xCD, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x7E, 0xFF, 0x04, 0x28, 0xF6, 0xD0, ++0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x79, 0x22, 0xFB, 0xF7, 0xB6, 0xFD, 0x00, 0xF0, 0xBE, 0xFC, 0x00, 0x20, 0x08, 0xBD, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x6C, 0xBA, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0xAD, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x5E, 0xFF, ++0x09, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x29, 0x32, 0xFB, 0xF7, 0x96, 0xFD, 0x00, 0xF0, 0x9E, 0xFC, ++0x00, 0x20, 0x08, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x9C, 0xBA, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0x8D, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, ++0xF9, 0xF7, 0x3E, 0xFF, 0x09, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x43, 0x32, 0xFB, 0xF7, 0x76, 0xFD, ++0x00, 0xF0, 0x7E, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x9C, 0xBA, 0x15, 0x00, ++0x37, 0x4B, 0x30, 0xB5, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x83, 0xB0, 0x37, 0xDB, 0x06, 0x20, 0xF9, 0xF7, ++0x21, 0xFF, 0x09, 0x28, 0x10, 0xD0, 0x32, 0x4B, 0x9A, 0x7D, 0x01, 0x2A, 0x50, 0xD0, 0x1B, 0x68, 0x93, 0xF8, 0x3B, 0x30, ++0x02, 0x2B, 0x3A, 0xD9, 0x03, 0x2B, 0x3F, 0xD1, 0x2D, 0x48, 0x01, 0xF0, 0xF5, 0xFC, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, ++0x29, 0x4C, 0xA2, 0x6A, 0x23, 0x7D, 0x00, 0x25, 0xC2, 0xF8, 0xCC, 0x51, 0x00, 0x2B, 0x40, 0xD1, 0xA0, 0x68, 0x0C, 0x30, ++0xF9, 0xF7, 0x90, 0xFC, 0xA3, 0x7D, 0x00, 0x22, 0x01, 0x2B, 0xA2, 0x60, 0x01, 0xD0, 0xA1, 0x7F, 0x61, 0xB3, 0x00, 0x24, ++0x01, 0xA9, 0x68, 0x46, 0xCD, 0xE9, 0x00, 0x44, 0x00, 0xF0, 0x8C, 0xFA, 0xDD, 0xE9, 0x00, 0x01, 0x22, 0x46, 0x00, 0xF0, ++0x2D, 0xFB, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0xE9, 0xFE, 0x04, 0x28, 0xC2, 0xD0, 0x06, 0x20, ++0xF9, 0xF7, 0xE4, 0xFE, 0x09, 0x28, 0xBD, 0xD0, 0x15, 0x49, 0x16, 0x48, 0x40, 0xF2, 0x93, 0x22, 0xFB, 0xF7, 0x1C, 0xFD, ++0xB6, 0xE7, 0x00, 0x21, 0x01, 0x20, 0x01, 0xF0, 0x2B, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x01, 0x20, 0x00, 0xF0, ++0x35, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x23, 0xFE, 0xDA, 0xE7, 0x01, 0xF0, 0x48, 0xF9, ++0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x04, 0x00, 0xF9, 0xF7, 0x85, 0xFC, 0x25, 0x75, ++0xB6, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x08, 0xAC, 0x0F, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xC8, 0xBA, 0x15, 0x00, 0x4B, 0x88, 0x03, 0xF0, 0xFC, 0x03, 0xB0, 0x2B, 0x10, 0xB5, 0x0C, 0x46, 0x13, 0xD0, 0x10, 0x2B, ++0x0A, 0xD0, 0x30, 0x2B, 0x08, 0xD0, 0xC0, 0x2B, 0x01, 0xD0, 0xA0, 0x2B, 0x14, 0xD1, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, ++0x01, 0xF0, 0x78, 0xBB, 0x06, 0x20, 0xF9, 0xF7, 0x9B, 0xFE, 0x07, 0x28, 0x13, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x06, 0x20, ++0xF9, 0xF7, 0x94, 0xFE, 0x05, 0x28, 0xF8, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0x37, 0xFA, 0xF4, 0xE7, 0xD0, 0x2B, 0xF2, 0xD1, ++0x23, 0x7B, 0x08, 0x2B, 0xEF, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0xD4, 0xFB, 0xEB, 0xE7, 0x20, 0x46, 0x01, 0xF0, 0x70, 0xFA, ++0xE7, 0xE7, 0x00, 0xBF, 0x10, 0xB5, 0x06, 0x20, 0x0C, 0x46, 0xF9, 0xF7, 0x7B, 0xFE, 0x06, 0x28, 0x01, 0xD0, 0x00, 0x20, ++0x10, 0xBD, 0x60, 0x88, 0x01, 0xF0, 0xC8, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, ++0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4C, 0x0D, 0x4A, 0x23, 0x68, 0xD2, 0x7D, 0x01, 0x33, ++0x01, 0x2A, 0x23, 0x60, 0x0C, 0xD0, 0x33, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, ++0x62, 0xB6, 0x07, 0x48, 0xFB, 0xF7, 0x1C, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0x00, 0xF0, 0x16, 0xFB, 0x23, 0x68, 0xEE, 0xE7, ++0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x28, 0xBB, 0x15, 0x00, 0x38, 0xB5, 0x06, 0x20, ++0x0D, 0x46, 0xF9, 0xF7, 0x43, 0xFE, 0x30, 0xB9, 0x04, 0x46, 0x29, 0x88, 0xA8, 0x78, 0x00, 0xF0, 0xB7, 0xFD, 0x20, 0x46, ++0x38, 0xBD, 0x02, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x8B, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x89, 0xB0, 0x0C, 0x46, 0xC0, 0xF2, 0xFD, 0x80, 0x25, 0x78, 0x00, 0x2D, 0x40, 0xF0, 0xF2, 0x80, 0x63, 0x78, ++0x00, 0x93, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x03, 0xF4, 0x82, 0x4B, 0xDF, 0xF8, 0x18, 0xA2, 0x1F, 0x19, 0x4F, 0xF4, ++0xA4, 0x6C, 0x97, 0xF8, 0x22, 0xE0, 0x0C, 0xFB, 0x0E, 0xAC, 0x0C, 0xF5, 0xCE, 0x73, 0x0F, 0xCB, 0x07, 0xF1, 0xB8, 0x06, ++0x07, 0xC6, 0xDC, 0xF8, 0xCC, 0x81, 0x33, 0x70, 0x18, 0xF0, 0x01, 0x0F, 0x03, 0xD0, 0x7B, 0x68, 0x43, 0xF0, 0x01, 0x03, ++0x7B, 0x60, 0x18, 0xF0, 0x02, 0x0F, 0x58, 0xD0, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x0E, 0xA3, 0x03, 0xF1, 0xEC, 0x0B, ++0x00, 0x9E, 0x01, 0x93, 0xBB, 0xE8, 0x0F, 0x00, 0xB4, 0x46, 0x6E, 0x4E, 0x4F, 0xF4, 0x1E, 0x79, 0x09, 0xFB, 0x0C, 0x69, ++0x09, 0xF1, 0xC8, 0x0C, 0xAC, 0xE8, 0x0F, 0x00, 0x9B, 0xE8, 0x0F, 0x00, 0xD9, 0xF8, 0x04, 0xB0, 0x18, 0xF0, 0x08, 0x0F, ++0x4B, 0xF0, 0x02, 0x06, 0x8C, 0xE8, 0x0F, 0x00, 0xC9, 0xF8, 0x04, 0x60, 0x15, 0xD0, 0x01, 0x9B, 0x03, 0xF5, 0x8C, 0x76, ++0x0F, 0xCE, 0x09, 0xF1, 0xF4, 0x0C, 0xAC, 0xE8, 0x0F, 0x00, 0x0F, 0xCE, 0xAC, 0xE8, 0x0F, 0x00, 0x0F, 0xCE, 0xAC, 0xE8, ++0x0F, 0x00, 0x96, 0xE8, 0x03, 0x00, 0x8C, 0xE8, 0x03, 0x00, 0x4B, 0xF0, 0x22, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0x18, 0xF0, ++0x04, 0x0F, 0x16, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x00, 0x9E, 0x03, 0xFB, 0x0E, 0xA3, 0x03, 0xF5, 0x86, 0x73, 0x93, 0xE8, ++0x07, 0x00, 0xB4, 0x46, 0x51, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x0C, 0x63, 0x03, 0xF1, 0xE8, 0x06, 0x86, 0xE8, ++0x07, 0x00, 0x5A, 0x68, 0x42, 0xF0, 0x04, 0x02, 0x5A, 0x60, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x0E, 0xA1, 0xEC, 0x31, ++0x38, 0x46, 0xFE, 0xF7, 0x81, 0xF8, 0x48, 0x4B, 0xD3, 0xF8, 0x14, 0x33, 0x98, 0x47, 0x47, 0x4B, 0x1B, 0x78, 0x00, 0x2B, ++0x66, 0xD0, 0x00, 0x9A, 0x42, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, 0x93, 0xF8, 0xB8, 0x20, 0x00, 0x23, ++0xCD, 0xE9, 0x02, 0x33, 0xCD, 0xE9, 0x05, 0x33, 0x04, 0x93, 0x07, 0x93, 0x00, 0x2A, 0x70, 0xD0, 0x01, 0x3A, 0xD2, 0xB2, ++0xB8, 0x34, 0x02, 0xAE, 0x0D, 0xF1, 0x14, 0x0C, 0x9B, 0x46, 0x0D, 0xF1, 0x09, 0x03, 0x01, 0x92, 0x0C, 0x44, 0x03, 0xEB, ++0x02, 0x09, 0x31, 0x46, 0x62, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0x40, 0xF2, 0x05, 0x2A, 0x07, 0xE0, 0x01, 0xF8, 0x01, 0x0B, ++0x49, 0x45, 0x82, 0xF8, 0x00, 0x80, 0x02, 0xF1, 0x01, 0x02, 0x14, 0xD0, 0x14, 0xF8, 0x01, 0x0F, 0x00, 0xF0, 0x7F, 0x03, ++0x02, 0x3B, 0xDB, 0xB2, 0x09, 0x2B, 0x08, 0xFA, 0x03, 0xFE, 0xED, 0xD8, 0x1E, 0xEA, 0x0A, 0x0F, 0xEA, 0xD0, 0x01, 0xF8, ++0x01, 0x0B, 0x49, 0x45, 0x82, 0xF8, 0x00, 0xB0, 0x02, 0xF1, 0x01, 0x02, 0xEA, 0xD1, 0x01, 0x9A, 0x0C, 0xF1, 0x01, 0x03, ++0x1A, 0x44, 0x11, 0x46, 0x00, 0x9A, 0x10, 0x46, 0x1E, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x24, 0x00, 0xE0, ++0x01, 0x33, 0x9C, 0xF8, 0x00, 0x20, 0x9C, 0x46, 0x2A, 0xB1, 0x62, 0x19, 0x30, 0x78, 0x82, 0xF8, 0xB9, 0x00, 0x01, 0x35, ++0xED, 0xB2, 0x8B, 0x42, 0x06, 0xF1, 0x01, 0x06, 0xF0, 0xD1, 0x00, 0x9A, 0x11, 0x46, 0x13, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x01, 0x23, 0x83, 0xF8, 0xB8, 0x50, 0x38, 0x46, 0xFE, 0xF7, 0x1D, 0xFA, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x01, 0x20, 0x00, 0xF0, 0x98, 0xFD, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x20, 0xF9, 0xF7, ++0x2D, 0xFD, 0x03, 0x28, 0x3F, 0xF4, 0xFD, 0xAE, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF2, 0xF1, 0x12, 0xFB, 0xF7, 0x64, 0xFB, ++0xF5, 0xE6, 0x15, 0x46, 0xD9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xB8, 0x34, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0xBB, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0xB5, 0x06, 0x20, ++0xF9, 0xF7, 0x0E, 0xFD, 0x08, 0x28, 0x06, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0x09, 0xFD, 0x09, 0x28, 0x33, 0xD0, 0x00, 0x20, ++0x70, 0xBD, 0x22, 0x4A, 0x22, 0x4B, 0x14, 0x68, 0x94, 0xF8, 0x3D, 0x60, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x06, 0x36, ++0x06, 0x23, 0x1A, 0x46, 0x00, 0x21, 0x4B, 0x20, 0x96, 0xF8, 0x6C, 0x50, 0xF9, 0xF7, 0x52, 0xFA, 0x94, 0xF8, 0x3A, 0x20, ++0x02, 0x71, 0x22, 0x8F, 0x42, 0x80, 0x94, 0xF8, 0x3D, 0x20, 0x02, 0x70, 0xF9, 0xF7, 0x78, 0xFA, 0xD6, 0xF8, 0xB0, 0x34, ++0x15, 0x4A, 0xA1, 0x8E, 0x4F, 0xF4, 0x1E, 0x70, 0x03, 0xF0, 0x01, 0x03, 0x00, 0xFB, 0x05, 0x22, 0xC3, 0xF1, 0x02, 0x03, ++0x49, 0xBA, 0x02, 0x2B, 0x82, 0xF8, 0x30, 0x30, 0x91, 0x86, 0x08, 0xD0, 0x00, 0x20, 0x00, 0xF0, 0x39, 0xFD, 0x00, 0x20, ++0x70, 0xBD, 0x00, 0xF0, 0x1B, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF9, 0xF7, ++0x27, 0xFA, 0x00, 0x22, 0x02, 0x70, 0x94, 0xF8, 0x3D, 0x20, 0x42, 0x70, 0xF9, 0xF7, 0x50, 0xFA, 0xE8, 0xE7, 0x00, 0xBF, ++0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0xB5, 0x06, 0x46, 0x06, 0x20, 0x0D, 0x46, ++0xF9, 0xF7, 0xB4, 0xFC, 0x2B, 0x46, 0x02, 0x46, 0x0A, 0x49, 0x04, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFB, 0xF7, 0xC2, 0xF8, ++0x08, 0x4B, 0x1D, 0x42, 0x04, 0xD0, 0x24, 0xF0, 0x02, 0x01, 0x89, 0xB2, 0x05, 0x29, 0x00, 0xD0, 0x70, 0xBD, 0x30, 0x46, ++0xE6, 0xF7, 0xDC, 0xFC, 0x01, 0x23, 0x86, 0xF8, 0x5E, 0x30, 0x70, 0xBD, 0x70, 0xBB, 0x15, 0x00, 0x00, 0x00, 0x03, 0x40, ++0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x08, 0x40, 0x09, 0x48, ++0xF9, 0xF7, 0x74, 0xBE, 0x08, 0x4B, 0xDB, 0x68, 0x00, 0x2B, 0xF6, 0xD0, 0x07, 0x48, 0x08, 0x49, 0x70, 0x22, 0xFB, 0xF7, ++0xC3, 0xFA, 0xBD, 0xE8, 0x08, 0x40, 0x02, 0x48, 0xF9, 0xF7, 0x66, 0xBE, 0x38, 0x36, 0x17, 0x00, 0x70, 0xBA, 0x17, 0x00, ++0x64, 0xBA, 0x17, 0x00, 0x80, 0xBB, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x03, 0x4A, 0x04, 0x4B, 0x00, 0x21, 0x06, 0x20, ++0xD1, 0x75, 0x19, 0x60, 0xF9, 0xF7, 0xC4, 0xBB, 0x4C, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x70, 0xB5, 0x11, 0x4B, ++0x1E, 0x68, 0x00, 0x23, 0x03, 0x60, 0x0B, 0x60, 0x96, 0xF8, 0x22, 0x30, 0xDB, 0x07, 0x05, 0x46, 0x0C, 0x46, 0x08, 0xD5, ++0x30, 0x46, 0x03, 0xF0, 0x57, 0xFB, 0x58, 0xB1, 0x83, 0x1C, 0x2B, 0x60, 0xC3, 0x6A, 0x23, 0x60, 0x70, 0xBD, 0x06, 0xF1, ++0x22, 0x00, 0x28, 0x60, 0x03, 0xF0, 0x46, 0xFB, 0x00, 0x28, 0xF5, 0xD1, 0x32, 0x8D, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, ++0x1C, 0xBF, 0x28, 0x36, 0x26, 0x60, 0x70, 0xBD, 0x64, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x3B, 0x4C, 0x4F, 0xF4, ++0xBA, 0x73, 0x06, 0x22, 0x84, 0xB0, 0x80, 0x46, 0x0F, 0x46, 0x4F, 0xF4, 0x80, 0x50, 0x04, 0x21, 0x25, 0x68, 0xF9, 0xF7, ++0x91, 0xF9, 0x95, 0xF8, 0x3D, 0x30, 0x80, 0xF8, 0x6E, 0x31, 0x04, 0x46, 0x0F, 0xCD, 0x4F, 0xF0, 0x00, 0x0C, 0x04, 0xF1, ++0xFC, 0x06, 0xC4, 0xF8, 0x68, 0xC1, 0xA4, 0xF8, 0x6C, 0xC1, 0x0F, 0xC6, 0x0F, 0xCD, 0x0F, 0xC6, 0x01, 0x23, 0x2A, 0x68, ++0x32, 0x70, 0x84, 0xF8, 0x70, 0x31, 0xB8, 0xF1, 0x00, 0x0F, 0x19, 0xD0, 0xD8, 0xF8, 0x00, 0x00, 0xC4, 0xF8, 0x60, 0x01, ++0xB8, 0xF8, 0x04, 0x30, 0xA4, 0xF8, 0x64, 0x31, 0xCF, 0xB1, 0x38, 0x68, 0x20, 0x60, 0xBB, 0x88, 0xA3, 0x80, 0x01, 0x23, ++0x84, 0xF8, 0x6F, 0x31, 0x20, 0x46, 0xF9, 0xF7, 0x95, 0xF9, 0x01, 0x21, 0x06, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x41, ++0xF9, 0xF7, 0x58, 0xBB, 0x1C, 0x4B, 0x18, 0x68, 0x9B, 0x88, 0xC4, 0xF8, 0x60, 0x01, 0xA4, 0xF8, 0x64, 0x31, 0x00, 0x2F, ++0xE5, 0xD1, 0x19, 0x4B, 0x02, 0x93, 0x93, 0xF8, 0xFD, 0x50, 0x93, 0xF8, 0xFC, 0x00, 0x8D, 0xF8, 0x05, 0x50, 0x03, 0xF1, ++0x54, 0x02, 0x03, 0x92, 0x84, 0xF8, 0x6F, 0x71, 0x0D, 0xF1, 0x08, 0x0C, 0x06, 0x26, 0xB8, 0xB1, 0x5C, 0xF8, 0x27, 0x30, ++0x16, 0xFB, 0x00, 0x30, 0xDA, 0x78, 0x92, 0x07, 0x0D, 0xD4, 0x94, 0xF8, 0x6F, 0x21, 0x51, 0x1C, 0x84, 0xF8, 0x6F, 0x11, ++0x02, 0xEB, 0x42, 0x02, 0x19, 0x68, 0x44, 0xF8, 0x12, 0x10, 0x04, 0xEB, 0x42, 0x02, 0x99, 0x88, 0x91, 0x80, 0x06, 0x33, ++0x83, 0x42, 0xEB, 0xD1, 0x00, 0x2F, 0xC1, 0xD1, 0x28, 0x46, 0x01, 0x27, 0xE1, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, ++0xAC, 0xB2, 0x15, 0x00, 0x5A, 0xB9, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x8B, 0x78, 0x0D, 0x46, 0x80, 0x46, 0x17, 0x46, ++0x1B, 0xB9, 0x37, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x49, 0xDB, 0x36, 0x4C, 0xDF, 0xF8, 0xEC, 0xA0, 0x4F, 0xF0, 0x00, 0x09, ++0x4F, 0xF4, 0xBA, 0x73, 0x06, 0x22, 0x04, 0x21, 0x41, 0xF2, 0x02, 0x00, 0xDA, 0xF8, 0x00, 0xB0, 0x84, 0xF8, 0x17, 0x90, ++0xF9, 0xF7, 0x04, 0xF9, 0x04, 0x46, 0x28, 0x68, 0x20, 0x60, 0x4F, 0xF0, 0x01, 0x0C, 0xB5, 0xF8, 0x04, 0xE0, 0x84, 0xF8, ++0x6F, 0xC1, 0x5E, 0x46, 0x0F, 0xCE, 0x04, 0xF1, 0xFC, 0x05, 0xA4, 0xF8, 0x04, 0xE0, 0x0F, 0xC5, 0x0F, 0xCE, 0x0F, 0xC5, ++0x33, 0x68, 0x2B, 0x70, 0x84, 0xF8, 0x70, 0xC1, 0xA4, 0xF8, 0x6C, 0x91, 0xC4, 0xF8, 0x68, 0x91, 0x9B, 0xF8, 0x3D, 0x30, ++0x84, 0xF8, 0x6E, 0x31, 0xD8, 0xF8, 0x00, 0x00, 0xC4, 0xF8, 0x60, 0x01, 0xB8, 0xF8, 0x04, 0x30, 0xA4, 0xF8, 0x64, 0x31, ++0x1F, 0xB1, 0xE3, 0x78, 0x43, 0xEA, 0x0C, 0x03, 0xE3, 0x70, 0xB7, 0xFA, 0x87, 0xF2, 0x20, 0x46, 0x52, 0x09, 0x8A, 0xF8, ++0x15, 0x20, 0xF9, 0xF7, 0x01, 0xF9, 0xBD, 0xE8, 0xF8, 0x4F, 0x02, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0xC5, 0xBA, 0x12, 0x4B, ++0x10, 0x4C, 0xD3, 0xF8, 0x24, 0x31, 0x5B, 0x06, 0xB0, 0xD5, 0xE3, 0x7D, 0x01, 0x2B, 0xAD, 0xD1, 0x0E, 0x4A, 0x63, 0x70, ++0x13, 0x68, 0x0E, 0x49, 0x0E, 0x48, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x08, 0x60, 0x0D, 0x4A, 0xC4, 0xF8, 0x0C, 0x80, ++0x06, 0x21, 0x41, 0xF6, 0x09, 0x00, 0x25, 0x61, 0xA7, 0x75, 0xF8, 0xF7, 0x0D, 0xFF, 0xBD, 0xE8, 0xF8, 0x4F, 0xDC, 0xF7, ++0xF9, 0xB8, 0x00, 0xBF, 0x48, 0x30, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x00, 0x00, 0x50, 0x40, 0x34, 0x04, 0x32, 0x40, ++0x20, 0x04, 0x32, 0x40, 0x40, 0x1F, 0xDC, 0x05, 0xA0, 0x86, 0x01, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x27, 0x4D, 0xDF, 0xF8, 0xA0, 0x80, 0xAF, 0x7D, 0xD8, 0xF8, 0x00, 0x90, 0x4F, 0xF4, 0xBA, 0x73, 0x06, 0x22, 0x04, 0x21, ++0x41, 0xF2, 0x02, 0x00, 0xF9, 0xF7, 0x8A, 0xF8, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, 0x09, 0x00, 0xF8, 0xF7, 0x92, 0xFF, ++0xD5, 0xE9, 0x03, 0x23, 0x4F, 0xF0, 0x00, 0x0C, 0x85, 0xF8, 0x17, 0xC0, 0x10, 0x68, 0xC4, 0xF8, 0x60, 0x01, 0x18, 0x68, ++0x95, 0x88, 0x20, 0x60, 0x4F, 0xF0, 0x01, 0x0E, 0xB3, 0xF8, 0x04, 0xA0, 0x84, 0xF8, 0x6F, 0xE1, 0x4E, 0x46, 0x0F, 0xCE, ++0xA4, 0xF8, 0x64, 0x51, 0x04, 0xF1, 0xFC, 0x05, 0xA4, 0xF8, 0x04, 0xA0, 0x0F, 0xC5, 0x0F, 0xCE, 0x0F, 0xC5, 0x33, 0x68, ++0x2B, 0x70, 0x84, 0xF8, 0x70, 0xE1, 0xA4, 0xF8, 0x6C, 0xC1, 0xC4, 0xF8, 0x68, 0xC1, 0x99, 0xF8, 0x3D, 0x30, 0x84, 0xF8, ++0x6E, 0x31, 0x1F, 0xB1, 0xE3, 0x78, 0x43, 0xEA, 0x0E, 0x03, 0xE3, 0x70, 0xB7, 0xFA, 0x87, 0xF3, 0x20, 0x46, 0x5B, 0x09, ++0x88, 0xF8, 0x15, 0x30, 0xF9, 0xF7, 0x7E, 0xF8, 0xBD, 0xE8, 0xF0, 0x47, 0x02, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0x42, 0xBA, ++0x4C, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x30, 0xB5, 0x14, 0x4A, 0x14, 0x4B, 0x11, 0x68, 0x14, 0x4A, 0x91, 0xF8, ++0x3D, 0x10, 0x54, 0x6C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0xF2, 0x99, 0x18, 0x85, 0xB0, 0xD1, 0xF8, 0x90, 0x31, ++0x91, 0xF8, 0xC5, 0x51, 0x8D, 0xF8, 0x05, 0x50, 0x0A, 0x46, 0x99, 0x78, 0xD2, 0xF8, 0x94, 0x21, 0x8D, 0xF8, 0x04, 0x10, ++0x19, 0x88, 0x02, 0x92, 0x1A, 0x79, 0xAD, 0xF8, 0x06, 0x10, 0x8D, 0xF8, 0x0C, 0x20, 0xDB, 0x78, 0x8D, 0xF8, 0x0D, 0x30, ++0x01, 0x46, 0x01, 0xA8, 0xA0, 0x47, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x48, 0xF9, 0xF7, 0xE2, 0xFC, 0x0B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x04, 0x46, 0x05, 0xDB, 0x04, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0xF9, 0xF7, 0x33, 0xB8, 0x00, 0x28, ++0xF7, 0xD1, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x0D, 0x22, 0xFB, 0xF7, 0xDD, 0xF8, 0xF0, 0xE7, 0x70, 0xBA, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x02, 0x23, 0x04, 0x46, ++0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF8, 0xF7, 0xE8, 0xFF, 0x06, 0x22, 0x02, 0x23, 0x06, 0x46, 0x05, 0x21, ++0x41, 0xF2, 0x17, 0x40, 0xF8, 0xF7, 0xE0, 0xFF, 0x38, 0x4F, 0x39, 0x49, 0x05, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, ++0x91, 0xFE, 0xFF, 0xF7, 0xE1, 0xFD, 0x20, 0x46, 0xE5, 0xF7, 0x4A, 0xF8, 0x4F, 0xF0, 0x00, 0x08, 0x94, 0xF8, 0x6C, 0x00, ++0x7B, 0x6A, 0x98, 0x47, 0x86, 0xF8, 0x00, 0x80, 0x94, 0xF8, 0x63, 0x30, 0x73, 0x70, 0x2F, 0x48, 0xA6, 0xF1, 0x0C, 0x01, ++0xF9, 0xF7, 0x52, 0xFC, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x3F, 0xD1, 0x94, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x0D, 0xD0, ++0x01, 0x23, 0x00, 0x21, 0x06, 0x22, 0x0C, 0x20, 0xF8, 0xF7, 0xB6, 0xFF, 0x01, 0x46, 0x94, 0xF8, 0x6C, 0x30, 0x01, 0xF8, ++0x0C, 0x39, 0x23, 0x48, 0xF9, 0xF7, 0x3C, 0xFC, 0x23, 0x6C, 0x6B, 0xB1, 0x01, 0x23, 0x00, 0x21, 0x06, 0x22, 0x39, 0x20, ++0xF8, 0xF7, 0xA6, 0xFF, 0x01, 0x46, 0x94, 0xF8, 0x63, 0x30, 0x01, 0xF8, 0x0C, 0x39, 0x1B, 0x48, 0xF9, 0xF7, 0x2C, 0xFC, ++0x00, 0x26, 0x2E, 0x70, 0x94, 0xF8, 0x63, 0x20, 0x18, 0x4B, 0x6A, 0x70, 0x93, 0xF8, 0x04, 0x31, 0x43, 0xB1, 0xD7, 0xF8, ++0xD8, 0x31, 0x04, 0xF1, 0x9C, 0x00, 0x98, 0x47, 0xC4, 0xE9, 0x24, 0x66, 0xC4, 0xF8, 0x98, 0x60, 0x00, 0x23, 0xA5, 0xF1, ++0x0C, 0x01, 0xC4, 0xF8, 0xCC, 0x31, 0x0E, 0x48, 0xF9, 0xF7, 0x12, 0xFC, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7, 0x6C, 0xBF, ++0x41, 0x46, 0x04, 0x23, 0x06, 0x22, 0x1E, 0x20, 0xF8, 0xF7, 0x7A, 0xFF, 0x80, 0xF8, 0x02, 0x80, 0x94, 0xF8, 0x63, 0x30, ++0xC3, 0x70, 0xA0, 0xF1, 0x0C, 0x01, 0x04, 0x48, 0xF9, 0xF7, 0xFE, 0xFB, 0xAE, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, ++0xA8, 0xBB, 0x15, 0x00, 0x70, 0xBA, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x6A, 0x4B, 0xDF, 0xF8, ++0xB4, 0xA1, 0x1D, 0x68, 0x83, 0xB0, 0x95, 0xF8, 0x3D, 0x20, 0x00, 0x92, 0x16, 0x46, 0x02, 0x23, 0x06, 0x22, 0x05, 0x21, ++0x41, 0xF2, 0x19, 0x40, 0xF8, 0xF7, 0x54, 0xFF, 0x08, 0x23, 0x81, 0x46, 0x06, 0x22, 0x00, 0x21, 0x18, 0x20, 0xF8, 0xF7, ++0x4D, 0xFF, 0x08, 0x23, 0x07, 0x46, 0x06, 0x22, 0x00, 0x21, 0x16, 0x20, 0xF8, 0xF7, 0x46, 0xFF, 0x4F, 0xF4, 0xA4, 0x64, ++0x04, 0xFB, 0x06, 0xF4, 0x04, 0x23, 0x06, 0x46, 0x06, 0x22, 0x00, 0x21, 0x14, 0x20, 0xF8, 0xF7, 0x3B, 0xFF, 0x02, 0x23, ++0x06, 0x22, 0x05, 0x21, 0x83, 0x46, 0x41, 0xF2, 0x17, 0x40, 0xF8, 0xF7, 0x33, 0xFF, 0x80, 0x46, 0xFF, 0xF7, 0x3A, 0xFD, ++0x4F, 0xF0, 0x01, 0x02, 0x89, 0xF8, 0x00, 0x20, 0x95, 0xF8, 0x3D, 0x30, 0x89, 0xF8, 0x01, 0x30, 0x0A, 0xEB, 0x04, 0x03, ++0x01, 0x93, 0x4B, 0x4B, 0xA9, 0xF1, 0x0C, 0x01, 0x03, 0xF1, 0x0C, 0x00, 0xF9, 0xF7, 0xAC, 0xFB, 0x01, 0x9B, 0xD3, 0xF8, ++0x64, 0x01, 0xB3, 0xF8, 0x68, 0x21, 0xBA, 0x80, 0x44, 0x4B, 0x38, 0x60, 0x95, 0xF8, 0x3D, 0x20, 0xBA, 0x71, 0x03, 0xF1, ++0x0C, 0x00, 0xA7, 0xF1, 0x0C, 0x01, 0xF9, 0xF7, 0x9B, 0xFB, 0x01, 0x9B, 0xD3, 0xF8, 0x90, 0x31, 0x04, 0xF5, 0xCE, 0x70, ++0x9B, 0x78, 0x73, 0x71, 0x01, 0x21, 0x50, 0x44, 0xFD, 0xF7, 0xFE, 0xFD, 0x73, 0x79, 0x30, 0x60, 0x95, 0xF8, 0x3D, 0x20, ++0x32, 0x71, 0x2B, 0xB9, 0xC1, 0x07, 0x4F, 0xD5, 0x36, 0x4B, 0x4F, 0xF4, 0x80, 0x62, 0x5A, 0x61, 0xA6, 0xF1, 0x0C, 0x01, ++0x34, 0x48, 0xF9, 0xF7, 0x7F, 0xFB, 0x00, 0x9B, 0x32, 0x48, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x03, 0xA6, 0xAB, 0xF1, ++0x0C, 0x01, 0xB6, 0xF8, 0x98, 0x31, 0xAB, 0xF8, 0x00, 0x30, 0x95, 0xF8, 0x3D, 0x30, 0x8B, 0xF8, 0x02, 0x30, 0xF9, 0xF7, ++0x6D, 0xFB, 0xD6, 0xF8, 0xCC, 0x31, 0x1B, 0x07, 0x36, 0xD4, 0x04, 0xF5, 0xD6, 0x74, 0x00, 0x26, 0x26, 0x4F, 0xA2, 0x44, ++0x34, 0x46, 0x08, 0x23, 0x06, 0x22, 0x00, 0x21, 0x1A, 0x20, 0xF8, 0xF7, 0xCF, 0xFE, 0x5A, 0xF8, 0x04, 0x3B, 0x03, 0x60, ++0x46, 0x71, 0x95, 0xF8, 0x3D, 0x30, 0x83, 0x71, 0x04, 0x71, 0xA0, 0xF1, 0x0C, 0x01, 0x01, 0x36, 0x38, 0x46, 0xF9, 0xF7, ++0x4F, 0xFB, 0x04, 0x2E, 0xE9, 0xD1, 0x01, 0x23, 0x88, 0xF8, 0x00, 0x30, 0x95, 0xF8, 0x3D, 0x30, 0x17, 0x48, 0x88, 0xF8, ++0x01, 0x30, 0xA8, 0xF1, 0x0C, 0x01, 0xF9, 0xF7, 0x41, 0xFB, 0xFF, 0xF7, 0x9D, 0xFE, 0x31, 0x46, 0x06, 0x20, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0xF9, 0xF7, 0xA4, 0xB8, 0xC2, 0x06, 0xB1, 0xD5, 0x0D, 0x4B, 0x04, 0x22, 0x5A, 0x61, 0xAD, 0xE7, ++0x06, 0x22, 0x00, 0x21, 0x04, 0x23, 0x71, 0x20, 0xF8, 0xF7, 0x9E, 0xFE, 0x04, 0xF1, 0xEC, 0x03, 0x06, 0x46, 0x0A, 0xEB, ++0x03, 0x00, 0xFD, 0xF7, 0x0F, 0xFE, 0x31, 0x46, 0x03, 0x46, 0x41, 0xF8, 0x0C, 0x39, 0x04, 0x48, 0xF9, 0xF7, 0x1E, 0xFB, ++0xB3, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0xC4, 0x3C, 0x18, 0x00, 0x70, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0x06, 0x23, 0x2D, 0xE9, 0xF0, 0x41, 0x1A, 0x46, 0x04, 0x46, 0x0F, 0x46, 0x41, 0xF6, 0x05, 0x00, 0x0C, 0x21, 0xF8, 0xF7, ++0x7B, 0xFE, 0x38, 0x4E, 0x94, 0xF8, 0xC0, 0x34, 0xB4, 0x62, 0x05, 0x46, 0x00, 0x2B, 0x3F, 0xD0, 0x35, 0x4B, 0x9B, 0x68, ++0x00, 0x2B, 0x61, 0xD0, 0x93, 0xF8, 0x62, 0x20, 0x7A, 0xB9, 0x33, 0x49, 0x33, 0x4A, 0xD8, 0x6D, 0x08, 0x60, 0xB3, 0xF8, ++0x60, 0x10, 0x11, 0x60, 0x93, 0xF8, 0x64, 0x20, 0x2A, 0xB1, 0x30, 0x49, 0x98, 0x6B, 0x30, 0x4A, 0x08, 0x60, 0x99, 0x8F, ++0x11, 0x60, 0x2F, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x2C, 0xDB, 0xDF, 0xF8, 0xC4, 0x80, 0x00, 0x20, 0xDB, 0xF7, 0x86, 0xFE, ++0x00, 0x22, 0xD8, 0xF8, 0xD8, 0x31, 0x84, 0xF8, 0xAC, 0x20, 0x04, 0xF1, 0xB0, 0x00, 0x98, 0x47, 0xD8, 0xF8, 0x10, 0x33, ++0x20, 0x46, 0x98, 0x47, 0x2F, 0x80, 0x94, 0xF8, 0x63, 0x30, 0xAB, 0x70, 0xB3, 0x7D, 0x01, 0x2B, 0x08, 0xBF, 0xEB, 0x70, ++0xB3, 0x7F, 0xA3, 0xF1, 0x01, 0x03, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0xA5, 0xF1, 0x0C, 0x02, 0x2B, 0x71, 0xB2, 0x60, ++0xBD, 0xE8, 0xF0, 0x81, 0x1A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xD6, 0xDA, 0x13, 0x4B, 0x9B, 0x68, 0x00, 0x2B, 0xD2, 0xD0, ++0x00, 0x21, 0x93, 0xF8, 0x62, 0x20, 0x1A, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x02, 0xB1, 0x01, 0x31, 0x1B, 0x68, 0x00, 0x2B, ++0xF5, 0xD1, 0x01, 0x29, 0xC5, 0xD1, 0x11, 0x4A, 0x11, 0x49, 0x53, 0x70, 0x0B, 0x68, 0x11, 0x4A, 0x43, 0xF0, 0x00, 0x43, ++0x0B, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x43, 0xF4, 0xBB, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0xB4, 0xE7, ++0x07, 0x4B, 0x1B, 0x68, 0xB1, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x10, 0x00, 0x32, 0x40, ++0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x48, 0x30, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, ++0x34, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0A, 0x46, 0x04, 0x46, 0x05, 0x49, ++0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, 0xA4, 0xFC, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x60, 0xBF, ++0xBC, 0xBB, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xC8, 0x81, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x00, 0x84, ++0x0B, 0x46, 0x02, 0x46, 0x06, 0x46, 0x0F, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x66, 0x49, 0x94, 0xF8, 0x6C, 0x90, 0xFA, 0xF7, ++0x89, 0xFC, 0x94, 0xF8, 0x62, 0x50, 0x15, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x3B, 0xB9, 0xBD, 0xE8, 0xF8, 0x43, 0x06, 0x22, ++0x0C, 0x21, 0x41, 0xF6, 0x04, 0x00, 0xF8, 0xF7, 0x2B, 0xBE, 0x5E, 0x4B, 0x01, 0x25, 0x09, 0x21, 0x06, 0x20, 0x1D, 0x75, ++0xF8, 0xF7, 0xB6, 0xFF, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x79, 0xD1, 0xD4, 0xF8, 0x90, 0x31, 0x9D, 0x78, 0x2C, 0x1E, ++0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x06, 0x85, 0x28, 0x46, 0x18, 0xBF, 0x01, 0x24, 0xE4, 0xF7, 0x11, 0xFD, 0x00, 0x28, ++0x74, 0xD0, 0x20, 0x46, 0x4F, 0xF4, 0xC0, 0x71, 0xE6, 0xF7, 0x72, 0xF8, 0x04, 0x46, 0x01, 0x46, 0x28, 0x46, 0x00, 0x2C, ++0x6C, 0xD0, 0xF8, 0xF7, 0x69, 0xF9, 0x4C, 0x4B, 0xD4, 0xF8, 0x48, 0x80, 0x4B, 0x49, 0xE8, 0x6D, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x09, 0x39, 0xB1, 0xF8, 0xFC, 0x31, 0x59, 0xF8, 0x26, 0x2F, 0xC8, 0xF8, 0x6C, 0x20, 0x6F, 0xF0, 0x3F, 0x02, ++0x88, 0xF8, 0x68, 0x20, 0xB9, 0xF8, 0x04, 0x20, 0xA8, 0xF8, 0x70, 0x20, 0xB5, 0xF8, 0x60, 0x20, 0xA8, 0xF8, 0x76, 0x20, ++0x01, 0x33, 0xD9, 0xF8, 0x00, 0x20, 0xC8, 0xF8, 0x72, 0x00, 0x9B, 0xB2, 0xB9, 0xF8, 0x04, 0x00, 0xC8, 0xF8, 0x78, 0x20, ++0x00, 0x22, 0xA8, 0xF8, 0x7C, 0x00, 0x88, 0xF8, 0x69, 0x20, 0x88, 0xF8, 0x6A, 0x20, 0x88, 0xF8, 0x6B, 0x20, 0x18, 0x01, ++0xA1, 0xF8, 0xFC, 0x31, 0x35, 0x4B, 0xA8, 0xF8, 0x7E, 0x00, 0x26, 0x77, 0xA5, 0x65, 0x63, 0x65, 0x95, 0xF8, 0x6C, 0x30, ++0x63, 0x77, 0x84, 0xF8, 0x33, 0x20, 0x84, 0xF8, 0x35, 0x20, 0xC0, 0x21, 0x20, 0x46, 0x07, 0xF0, 0x5F, 0xF9, 0x01, 0x28, ++0x06, 0x46, 0x08, 0xF1, 0x68, 0x09, 0x34, 0xD0, 0x39, 0x46, 0x08, 0xF1, 0x80, 0x00, 0xFB, 0xF7, 0xDD, 0xFD, 0x02, 0x2E, ++0x00, 0xF1, 0x18, 0x05, 0x3D, 0xD0, 0xE2, 0x6C, 0x53, 0x6A, 0x01, 0x3B, 0x2B, 0x44, 0x04, 0x35, 0xC2, 0xE9, 0x0A, 0x35, ++0x05, 0x21, 0x20, 0x46, 0xE6, 0xF7, 0x20, 0xF8, 0x05, 0x46, 0x88, 0xB1, 0xBD, 0xE8, 0xF8, 0x83, 0x2C, 0x46, 0x4F, 0xF4, ++0xA4, 0x65, 0x05, 0xFB, 0x06, 0x85, 0x28, 0x46, 0xE4, 0xF7, 0x9C, 0xFC, 0x00, 0x28, 0x8A, 0xD1, 0x01, 0x46, 0x28, 0x46, ++0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0xA8, 0xBE, 0xA4, 0x6D, 0x17, 0x49, 0x02, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, ++0xDF, 0xFB, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0x9B, 0xBE, 0x18, 0x22, 0x49, 0x46, 0x20, 0x46, ++0x05, 0xF0, 0x84, 0xFF, 0x94, 0xF8, 0x33, 0x50, 0x18, 0x35, 0x09, 0xEB, 0x05, 0x00, 0x39, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, ++0x94, 0xF8, 0x35, 0x20, 0x15, 0x44, 0x05, 0x44, 0xC1, 0xE7, 0x2A, 0x46, 0x49, 0x46, 0x20, 0x46, 0x07, 0xF0, 0x4A, 0xF9, ++0x05, 0x44, 0xBA, 0xE7, 0xD4, 0xBB, 0x15, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0xD1, 0x9D, 0x14, 0x00, 0xBC, 0xBB, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x66, 0x4D, 0x67, 0x49, ++0xD5, 0xE9, 0x00, 0x34, 0x93, 0xF8, 0x3D, 0x70, 0x67, 0x72, 0x0A, 0x68, 0x20, 0x80, 0x22, 0xF0, 0x10, 0x02, 0x4F, 0xF4, ++0xA4, 0x66, 0x83, 0xB0, 0x80, 0x46, 0x06, 0xFB, 0x07, 0xF6, 0x0A, 0x60, 0x00, 0x28, 0x6C, 0xD1, 0xDF, 0xF8, 0x98, 0x91, ++0x09, 0xEB, 0x06, 0x01, 0x91, 0xF8, 0x6C, 0x20, 0xD1, 0xF8, 0x64, 0x01, 0xB1, 0xF8, 0x68, 0xC1, 0xA2, 0x72, 0x0A, 0x6C, ++0xA4, 0xF8, 0x06, 0xC0, 0xC4, 0xF8, 0x02, 0x00, 0x10, 0x7E, 0xE0, 0x72, 0x10, 0x79, 0x84, 0xF8, 0x36, 0x03, 0xD0, 0x88, ++0xB2, 0xF8, 0x08, 0xC0, 0xA4, 0xF8, 0x38, 0x03, 0x50, 0x89, 0xC4, 0xE9, 0xCF, 0xC0, 0x52, 0x79, 0x84, 0xF8, 0x3A, 0x23, ++0xD1, 0xF8, 0xCC, 0x21, 0x02, 0xF0, 0x01, 0x02, 0x22, 0x73, 0x00, 0x2A, 0x6D, 0xD1, 0x42, 0x46, 0x62, 0x73, 0x1A, 0x6B, ++0x4F, 0xF4, 0xA4, 0x63, 0x02, 0xF0, 0x20, 0x02, 0x03, 0xFB, 0x07, 0x93, 0x22, 0x72, 0x93, 0xF8, 0xC0, 0x24, 0xA2, 0xB1, ++0xB3, 0xF8, 0x5E, 0x00, 0xB3, 0xF8, 0x5C, 0x20, 0x42, 0x49, 0x42, 0xEA, 0x00, 0x42, 0x0A, 0x60, 0x41, 0x4A, 0xB3, 0xF8, ++0x60, 0x10, 0x11, 0x60, 0x58, 0x8F, 0x1A, 0x8F, 0x3F, 0x49, 0x42, 0xEA, 0x00, 0x42, 0x0A, 0x60, 0x3E, 0x4A, 0x9B, 0x8F, ++0x13, 0x60, 0x20, 0x46, 0xF8, 0xF7, 0xC8, 0xFC, 0x94, 0xF8, 0x3A, 0x33, 0xB4, 0xF8, 0x3C, 0x03, 0x40, 0xEA, 0x03, 0x40, ++0x40, 0xF0, 0x00, 0x40, 0xDB, 0xF7, 0xC0, 0xFC, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x97, 0x01, 0x22, 0x35, 0x4B, ++0x87, 0xF8, 0xAC, 0x20, 0x1A, 0x69, 0x34, 0x49, 0x34, 0x4B, 0x06, 0xF1, 0xB0, 0x00, 0x48, 0x44, 0x11, 0x44, 0xD3, 0xF8, ++0xE0, 0x31, 0x98, 0x47, 0x00, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x72, 0xFE, 0x12, 0xE0, 0x2F, 0x4B, 0x1B, 0x68, 0x00, 0x2B, ++0x26, 0xDB, 0x2E, 0x4B, 0x06, 0x20, 0x09, 0x21, 0x1E, 0x44, 0xF8, 0xF7, 0x67, 0xFE, 0x29, 0x4A, 0xAE, 0x62, 0xA4, 0xF1, ++0x0C, 0x03, 0xD2, 0xF8, 0x10, 0x23, 0xAB, 0x60, 0x30, 0x46, 0x90, 0x47, 0xB4, 0xF8, 0x34, 0x33, 0x62, 0x7A, 0x26, 0x49, ++0x00, 0x93, 0x4F, 0xF4, 0x80, 0x70, 0x43, 0x46, 0xFA, 0xF7, 0x12, 0xFB, 0x28, 0x68, 0x0C, 0x38, 0xF8, 0xF7, 0xD2, 0xFC, ++0x00, 0x23, 0x2B, 0x60, 0xAB, 0x75, 0xAB, 0x77, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x91, 0xF8, 0xBD, 0x21, 0x8F, 0xE7, ++0x1C, 0x4B, 0x9A, 0x68, 0x62, 0xB1, 0x00, 0x21, 0x92, 0xF8, 0x62, 0x30, 0x1B, 0xB9, 0x92, 0xF8, 0x64, 0x30, 0x03, 0xB1, ++0x01, 0x31, 0x12, 0x68, 0x00, 0x2A, 0xF5, 0xD1, 0x00, 0x29, 0xC8, 0xD1, 0x15, 0x4B, 0x16, 0x49, 0x00, 0x22, 0x5A, 0x70, ++0x0B, 0x68, 0x15, 0x4A, 0x43, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x43, 0xF4, 0xBB, 0x63, ++0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0xB6, 0xE7, 0x64, 0xBA, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0x10, 0x00, 0x32, 0x40, ++0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x40, 0x4B, 0x4C, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x48, 0x30, 0x34, 0x40, 0x18, 0x88, 0x17, 0x00, 0xE8, 0xBB, 0x15, 0x00, 0x00, 0x88, 0x17, 0x00, ++0x4C, 0x36, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0x4B, 0x8C, 0x4E, ++0xD3, 0xF8, 0x00, 0x90, 0x8B, 0x4A, 0x99, 0xF8, 0x3D, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x05, 0x64, 0x89, 0xB0, ++0x07, 0x46, 0x88, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x86, 0x49, 0x94, 0xF8, 0x6C, 0xA0, 0xFA, 0xF7, 0xAB, 0xFA, 0x94, 0xF8, ++0xC0, 0x34, 0x00, 0x2B, 0x40, 0xF0, 0x82, 0x80, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x78, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, ++0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0xB2, 0xFE, 0x04, 0x46, 0x00, 0x28, 0x7C, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x05, 0x65, 0x28, 0x46, 0x21, 0x46, 0xF7, 0xF7, 0xA5, 0xFF, 0x78, 0x4B, 0xA2, 0x6C, 0x78, 0x49, 0x4F, 0xF4, 0x1E, 0x70, ++0x00, 0xFB, 0x0A, 0x3A, 0x53, 0x46, 0xB1, 0xF8, 0xFC, 0x61, 0x53, 0xF8, 0x26, 0x0F, 0xD0, 0x66, 0x6F, 0xF0, 0x4F, 0x00, ++0x82, 0xF8, 0x68, 0x00, 0x98, 0x88, 0xA2, 0xF8, 0x70, 0x00, 0xE8, 0x6D, 0xC2, 0xF8, 0x72, 0x00, 0x01, 0x36, 0xB5, 0xF8, ++0x60, 0x00, 0xA2, 0xF8, 0x76, 0x00, 0x4F, 0xF0, 0x00, 0x0B, 0x18, 0x68, 0x9B, 0x88, 0xA2, 0xF8, 0x7C, 0x30, 0xB6, 0xB2, ++0x90, 0x67, 0x82, 0xF8, 0x69, 0xB0, 0x82, 0xF8, 0x6A, 0xB0, 0x82, 0xF8, 0x6B, 0xB0, 0x65, 0x4B, 0xA1, 0xF8, 0xFC, 0x61, ++0x30, 0x01, 0x95, 0xF8, 0x63, 0x10, 0xA2, 0xF8, 0x7E, 0x00, 0x21, 0x77, 0x95, 0xF8, 0x6C, 0x10, 0x1B, 0x68, 0x61, 0x77, ++0x84, 0xF8, 0x33, 0xB0, 0x84, 0xF8, 0x35, 0xB0, 0x1B, 0x78, 0x99, 0xF8, 0x3B, 0x10, 0x9B, 0x07, 0x02, 0xF1, 0x68, 0x05, ++0x38, 0xD4, 0x01, 0x29, 0x44, 0xD0, 0x18, 0x26, 0xCD, 0xF8, 0x00, 0x80, 0x3A, 0x46, 0xA8, 0x19, 0x00, 0x23, 0xFB, 0xF7, ++0xFF, 0xFB, 0x30, 0x44, 0xE1, 0x6C, 0x94, 0xF8, 0x35, 0x30, 0x4A, 0x6A, 0xA4, 0x65, 0x18, 0x44, 0x01, 0x3A, 0x02, 0x44, ++0x03, 0x1D, 0x50, 0x48, 0x60, 0x65, 0xC1, 0xE9, 0x0A, 0x23, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, 0x59, 0xFE, 0x4D, 0x4B, ++0x1B, 0x68, 0x06, 0x21, 0xDA, 0x68, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, 0xD1, 0xF9, 0x05, 0x21, 0x06, 0x20, 0xF8, 0xF7, ++0x69, 0xFD, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0x35, 0xFE, 0x04, 0x46, ++0x00, 0x28, 0x82, 0xD1, 0x01, 0x20, 0xFF, 0xF7, 0x67, 0xFE, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x29, 0x01, 0xD1, ++0x03, 0x2F, 0x17, 0xD0, 0xCD, 0xF8, 0x00, 0x80, 0x3A, 0x46, 0x05, 0xF1, 0x18, 0x00, 0x00, 0x23, 0xFB, 0xF7, 0xC4, 0xFB, ++0x18, 0x30, 0xC3, 0xE7, 0x03, 0x2F, 0xB8, 0xD1, 0x29, 0x46, 0x20, 0x46, 0x18, 0x22, 0x05, 0xF0, 0xB1, 0xFD, 0x94, 0xF8, ++0x33, 0x00, 0x99, 0xF8, 0x3B, 0x10, 0x00, 0xF1, 0x18, 0x06, 0xAD, 0xE7, 0xDA, 0xF8, 0xB4, 0x30, 0x29, 0x46, 0x18, 0x22, ++0x20, 0x46, 0x1E, 0x68, 0x05, 0xF0, 0xA2, 0xFD, 0x94, 0xF8, 0x33, 0x00, 0x99, 0xF8, 0x3B, 0x10, 0xCD, 0xF8, 0x00, 0x80, ++0x00, 0xF1, 0x18, 0x08, 0x05, 0xEB, 0x08, 0x09, 0x5B, 0x46, 0x3A, 0x46, 0x48, 0x46, 0xFB, 0xF7, 0x9D, 0xFB, 0x05, 0x46, ++0x3A, 0x46, 0x29, 0x46, 0x4F, 0xF0, 0xFF, 0x33, 0x48, 0x46, 0xDB, 0xF7, 0x67, 0xFD, 0x96, 0xF8, 0x60, 0x30, 0x21, 0x8F, ++0x62, 0x8F, 0xAD, 0xF8, 0x10, 0x10, 0x8D, 0xF8, 0x12, 0x20, 0x06, 0xF1, 0x64, 0x01, 0x93, 0xB1, 0x03, 0x2B, 0x1A, 0xD0, ++0x03, 0x20, 0xDB, 0xF7, 0x8F, 0xFD, 0x29, 0x1D, 0x02, 0x46, 0x89, 0xB2, 0x48, 0x46, 0x03, 0x91, 0xF7, 0xF7, 0x20, 0xFF, ++0x48, 0x46, 0x03, 0x99, 0xF8, 0xF7, 0x16, 0xF9, 0x05, 0xEB, 0x08, 0x00, 0x78, 0xE7, 0x05, 0x22, 0x0D, 0xF1, 0x13, 0x00, ++0x0C, 0xF0, 0x88, 0xFE, 0x04, 0xA8, 0x08, 0x21, 0xF8, 0xF7, 0xDE, 0xF8, 0xE4, 0xE7, 0x0D, 0x22, 0x0D, 0xF1, 0x13, 0x00, ++0x0C, 0xF0, 0x7E, 0xFE, 0x04, 0xA8, 0x10, 0x21, 0xF8, 0xF7, 0xD4, 0xF8, 0xDA, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x9C, 0xBC, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x34, 0x36, 0x17, 0x00, 0x89, 0x95, 0x14, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x77, 0x4F, 0x78, 0x4E, ++0xD7, 0xF8, 0x00, 0x80, 0x77, 0x4A, 0x98, 0xF8, 0x3D, 0x50, 0x77, 0x49, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x05, 0x64, ++0x87, 0xB0, 0x4F, 0xF4, 0x80, 0x70, 0x94, 0xF8, 0x6C, 0xA0, 0xFA, 0xF7, 0x81, 0xF9, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0x40, 0xF0, 0xAA, 0x80, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x78, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, ++0xE5, 0xF7, 0x88, 0xFD, 0x04, 0x46, 0x00, 0x28, 0x00, 0xF0, 0xA5, 0x80, 0x4F, 0xF4, 0xA4, 0x6B, 0x0B, 0xFB, 0x05, 0xFB, ++0x06, 0xEB, 0x0B, 0x00, 0x21, 0x46, 0xD7, 0xF8, 0x04, 0x90, 0xF7, 0xF7, 0x77, 0xFE, 0xBA, 0x7D, 0xA3, 0x6C, 0x01, 0x2A, ++0x03, 0xF1, 0x68, 0x0C, 0x00, 0xF0, 0x99, 0x80, 0xBA, 0x7F, 0x00, 0x2A, 0x00, 0xF0, 0xA7, 0x80, 0x20, 0x22, 0x00, 0x21, ++0x83, 0xF8, 0x68, 0x20, 0x5B, 0x4A, 0x83, 0xF8, 0x69, 0x10, 0x5B, 0x49, 0x5B, 0x4F, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x0A, 0x10, 0xB7, 0xF8, 0xFC, 0xE1, 0x50, 0xF8, 0x26, 0xAF, 0xC3, 0xF8, 0x6C, 0xA0, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, ++0x05, 0x65, 0xB0, 0xF8, 0x04, 0xA0, 0xA3, 0xF8, 0x70, 0xA0, 0x0B, 0xF1, 0xEC, 0x01, 0x0E, 0xF1, 0x01, 0x0E, 0xD0, 0xF8, ++0x00, 0xA0, 0xB0, 0xF8, 0x04, 0xB0, 0xE8, 0x6D, 0xC3, 0xF8, 0x72, 0x00, 0x1F, 0xFA, 0x8E, 0xFE, 0x31, 0x44, 0x00, 0x26, ++0xB5, 0xF8, 0x60, 0x00, 0xC3, 0xF8, 0x78, 0xA0, 0x83, 0xF8, 0x6A, 0x60, 0x83, 0xF8, 0x6B, 0x60, 0x4F, 0xEA, 0x0E, 0x1A, ++0x46, 0x4E, 0xA3, 0xF8, 0x76, 0x00, 0xA3, 0xF8, 0x7C, 0xB0, 0x0C, 0xF1, 0x18, 0x00, 0xA7, 0xF8, 0xFC, 0xE1, 0x0D, 0xF1, ++0x12, 0x0C, 0xA3, 0xF8, 0x7E, 0xA0, 0x05, 0xAF, 0x95, 0xF8, 0x63, 0x30, 0xCD, 0xF8, 0x08, 0x80, 0xD6, 0xF8, 0x58, 0x61, ++0xCD, 0xE9, 0x00, 0x7C, 0xB0, 0x47, 0x95, 0xF8, 0x63, 0x30, 0x23, 0x77, 0x95, 0xF8, 0x6C, 0x30, 0xE1, 0x6C, 0x63, 0x77, ++0x4B, 0x6A, 0xBD, 0xF8, 0x12, 0x20, 0x37, 0x4D, 0xA4, 0x65, 0x17, 0x33, 0x03, 0x44, 0xB2, 0xF5, 0x48, 0x7F, 0x00, 0xF1, ++0x1C, 0x00, 0x65, 0x65, 0xC1, 0xE9, 0x0A, 0x30, 0x3B, 0xD8, 0x05, 0x98, 0x6A, 0xB1, 0x4A, 0x44, 0x13, 0x38, 0x13, 0x32, ++0xA0, 0xEB, 0x09, 0x00, 0x09, 0xF1, 0x13, 0x03, 0xC1, 0x5C, 0x03, 0xF8, 0x01, 0x1F, 0x93, 0x42, 0xFA, 0xD1, 0xBD, 0xF8, ++0x12, 0x20, 0xA9, 0xF8, 0x0E, 0x20, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, 0x07, 0xFD, 0x27, 0x4B, 0x1B, 0x68, 0x06, 0x21, ++0x9A, 0x68, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, 0x7F, 0xF8, 0x07, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x17, 0xFC, 0x07, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0xE3, 0xFC, 0x04, 0x46, 0x00, 0x28, 0x7F, 0xF4, ++0x5B, 0xAF, 0x01, 0x20, 0xFF, 0xF7, 0x14, 0xFD, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x20, 0x22, 0x00, 0x21, 0x83, 0xF8, ++0x68, 0x20, 0x83, 0xF8, 0x69, 0x10, 0x16, 0x4A, 0x69, 0xE7, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x08, 0xDB, 0x00, 0x23, 0xA9, 0xF8, 0x0E, 0x30, 0xCB, 0xE7, 0x83, 0xF8, 0x68, 0x20, 0x83, 0xF8, 0x69, 0x20, 0x5A, 0xE7, ++0x0F, 0x49, 0x10, 0x48, 0x4F, 0xF4, 0x82, 0x62, 0xFA, 0xF7, 0xE8, 0xFA, 0xEF, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0xAC, 0xBC, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x84, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x89, 0x95, 0x14, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x7C, 0xBA, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0xB5, 0x0B, 0x4D, 0x04, 0x46, 0x04, 0x23, ++0x00, 0x21, 0x06, 0x22, 0x1E, 0x20, 0x2D, 0x68, 0xF8, 0xF7, 0xC6, 0xF9, 0x01, 0x22, 0x04, 0x80, 0x82, 0x70, 0x95, 0xF8, ++0x3D, 0x20, 0xC2, 0x70, 0xF8, 0xF7, 0xEE, 0xF9, 0xBD, 0xE8, 0x38, 0x40, 0x08, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0xB2, 0xBB, ++0x64, 0xBA, 0x17, 0x00, 0x70, 0xB5, 0x00, 0xF1, 0x0C, 0x06, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, ++0xBB, 0xF8, 0xB5, 0x88, 0x19, 0x49, 0x2A, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, 0x5E, 0xF8, 0x45, 0xB9, 0xA3, 0x89, ++0x13, 0xB1, 0x01, 0x2B, 0x09, 0xD0, 0x70, 0xBD, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xBE, 0xBE, 0x28, 0x46, 0xBD, 0xE8, ++0x70, 0x40, 0xFF, 0xF7, 0x9D, 0xBC, 0x73, 0x88, 0x04, 0x2B, 0xF3, 0xD0, 0x02, 0x2B, 0x11, 0xD0, 0x0D, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0xFF, 0xF7, 0x8D, 0xBC, 0x09, 0x49, ++0x09, 0x48, 0x4F, 0xF4, 0x8C, 0x62, 0xFA, 0xF7, 0x7B, 0xFA, 0xF3, 0xE7, 0x04, 0xF1, 0x14, 0x01, 0x03, 0x20, 0xBD, 0xE8, ++0x70, 0x40, 0xFF, 0xF7, 0x6F, 0xBD, 0x00, 0xBF, 0x00, 0xBC, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x69, 0x4B, 0xD3, 0xE9, 0x00, 0x2A, 0x05, 0x46, 0x83, 0xB0, 0x06, 0x21, ++0x00, 0x24, 0x41, 0xF6, 0x08, 0x00, 0x92, 0xF8, 0x3D, 0x80, 0x8D, 0xF8, 0x06, 0x40, 0xF8, 0xF7, 0x6D, 0xF8, 0x29, 0x88, ++0xEE, 0x89, 0x4F, 0xF4, 0xA4, 0x67, 0x05, 0x29, 0x05, 0xF1, 0x0C, 0x09, 0x07, 0xFB, 0x08, 0xF7, 0x34, 0xD9, 0xBA, 0xF8, ++0x0E, 0x30, 0x06, 0x39, 0x89, 0xB2, 0xCA, 0x18, 0x05, 0xF1, 0x12, 0x0B, 0xB2, 0xF5, 0x48, 0x7F, 0x5C, 0x46, 0x09, 0xDD, ++0x58, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x81, 0x80, 0xC3, 0xF5, 0x48, 0x71, 0x89, 0xB2, ++0x0A, 0xF1, 0x14, 0x00, 0x18, 0x44, 0x8B, 0x44, 0x39, 0xB1, 0xA4, 0xF1, 0x12, 0x03, 0x14, 0xF8, 0x01, 0x2B, 0x5B, 0x1B, ++0x5C, 0x45, 0x1A, 0x54, 0xF7, 0xD1, 0xAA, 0xF8, 0x10, 0x10, 0x32, 0x46, 0x4C, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, ++0xE3, 0xFF, 0x9E, 0xB1, 0x4A, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x2B, 0xBB, 0x30, 0x46, 0xFF, 0xF7, 0x29, 0xFC, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x44, 0x49, 0xAA, 0xF8, 0x10, 0x40, 0x32, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0xD0, 0xFF, ++0x00, 0x2E, 0xEB, 0xD1, 0xB9, 0xF8, 0x04, 0x00, 0x40, 0x4C, 0xC0, 0xF3, 0x0D, 0x00, 0xFF, 0xF7, 0x3F, 0xFF, 0x3D, 0x4B, ++0x93, 0xF8, 0x04, 0x31, 0x63, 0xB3, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x08, 0x45, 0xD5, 0xF8, 0x90, 0x31, 0x9A, 0x78, ++0x01, 0x2A, 0x48, 0xD0, 0x38, 0x4E, 0x28, 0xE0, 0x12, 0x2E, 0xD7, 0xD1, 0x35, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, ++0x08, 0x38, 0xD8, 0xF8, 0x90, 0x21, 0x92, 0x78, 0x01, 0x2A, 0xCD, 0xD1, 0x98, 0xF8, 0xC0, 0x44, 0x00, 0x2C, 0xC9, 0xD1, ++0x30, 0x4D, 0x07, 0xF5, 0xB2, 0x77, 0x1F, 0x44, 0xA8, 0x46, 0x40, 0x46, 0x06, 0x22, 0x39, 0x46, 0x0C, 0xF0, 0x3E, 0xFC, ++0x08, 0xF1, 0x14, 0x08, 0x00, 0x28, 0x3F, 0xD0, 0x01, 0x34, 0x05, 0x2C, 0xF3, 0xD1, 0xB7, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x08, 0x43, 0x24, 0x4E, 0xD3, 0xF8, 0x90, 0x31, 0x1B, 0x79, 0xD6, 0xF8, 0x40, 0x53, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x08, 0x48, 0xE0, 0x19, 0x98, 0xF8, 0xC6, 0x21, 0x9B, 0x1A, 0x8D, 0xF8, 0x07, 0x30, 0x0D, 0xF1, 0x06, 0x02, ++0x0D, 0xF1, 0x07, 0x01, 0xA8, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0x49, 0x1B, 0x48, 0x40, 0xF2, 0x8B, 0x42, ++0xFA, 0xF7, 0xB6, 0xF9, 0xBA, 0xF8, 0x0E, 0x30, 0x75, 0xE7, 0xD5, 0xF8, 0xCC, 0x21, 0x12, 0xF0, 0x0C, 0x0F, 0xB1, 0xD0, ++0x95, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0xAD, 0xD1, 0x13, 0x4B, 0x14, 0x49, 0x1B, 0x69, 0x0E, 0x4E, 0x07, 0xF1, 0x9C, 0x00, ++0x19, 0x44, 0x20, 0x44, 0xD6, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0xD5, 0xF8, 0x90, 0x31, 0xCA, 0xE7, 0x04, 0xEB, 0x84, 0x04, ++0x05, 0xEB, 0x84, 0x04, 0x01, 0x23, 0xE3, 0x71, 0x74, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x14, 0xBC, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xCC, 0x35, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x80, 0x96, 0x98, 0x00, 0x2D, 0xE9, 0xF0, 0x47, ++0x04, 0x46, 0x06, 0x20, 0x25, 0x7A, 0xF8, 0xF7, 0x1F, 0xFB, 0x09, 0x28, 0x0A, 0xD0, 0x06, 0x20, 0xF8, 0xF7, 0x1A, 0xFB, ++0x48, 0xB1, 0x2D, 0x4A, 0x23, 0x7A, 0x12, 0x68, 0x92, 0xF8, 0x3D, 0x20, 0x9A, 0x42, 0x0D, 0xD0, 0x02, 0x20, 0xBD, 0xE8, ++0xF0, 0x87, 0x29, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0xF5, 0x7E, 0x19, 0x96, 0xF8, 0x64, 0x00, 0x60, 0xB9, ++0xBD, 0xE8, 0xF0, 0x87, 0x24, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0x15, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0x60, 0xFB, ++0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xA4, 0x89, 0x1F, 0x49, 0x22, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0x08, 0xFF, ++0x1D, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x0B, 0xB1, 0x08, 0x2C, 0x0A, 0xD0, 0x09, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x40, 0xFA, ++0x78, 0x19, 0x21, 0x46, 0xFF, 0xF7, 0xBC, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0x90, 0x31, 0x9B, 0x78, ++0x01, 0x2B, 0xEF, 0xD1, 0x96, 0xF8, 0xC0, 0x64, 0x00, 0x2E, 0xEB, 0xD1, 0xDF, 0xF8, 0x44, 0x90, 0x05, 0xF5, 0xB2, 0x7A, ++0xC8, 0x46, 0xBA, 0x44, 0x40, 0x46, 0x06, 0x22, 0x51, 0x46, 0x0C, 0xF0, 0x83, 0xFB, 0x08, 0xF1, 0x14, 0x08, 0x18, 0xB1, ++0x01, 0x36, 0x05, 0x2E, 0xF4, 0xD1, 0xD9, 0xE7, 0x06, 0xEB, 0x86, 0x06, 0x09, 0xEB, 0x86, 0x06, 0x01, 0x23, 0xB3, 0x71, ++0xD2, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2C, 0xBC, 0x15, 0x00, 0x50, 0xBC, 0x15, 0x00, ++0x2C, 0x19, 0x17, 0x00, 0xCC, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x46, 0x4B, 0x04, 0x7A, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, 0x64, 0x30, 0xC3, 0xB1, 0x94, 0xF8, 0x62, 0x30, 0xAB, 0xB9, 0xC3, 0x79, 0xFF, 0x2B, ++0x05, 0x46, 0x11, 0xD0, 0x94, 0xF8, 0x6C, 0x20, 0x9A, 0x42, 0x0D, 0xD1, 0x3D, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x02, 0x66, 0x96, 0xF8, 0x30, 0x30, 0x02, 0x2B, 0x04, 0xD1, 0x90, 0xF8, 0x0D, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x01, 0xD0, ++0xBD, 0xE8, 0xF8, 0x83, 0x80, 0x79, 0xB5, 0xF8, 0x0E, 0x80, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, ++0xE5, 0xF7, 0xAE, 0xFA, 0x07, 0x46, 0x00, 0x28, 0xF0, 0xD0, 0x01, 0x46, 0x20, 0x46, 0xF7, 0xF7, 0xA5, 0xFB, 0x32, 0x46, ++0xDF, 0xF8, 0xB4, 0xC0, 0xBB, 0x6C, 0x52, 0xF8, 0x26, 0x0F, 0xBC, 0xF8, 0xFC, 0x11, 0xD8, 0x66, 0x6F, 0xF0, 0x2F, 0x00, ++0x83, 0xF8, 0x68, 0x00, 0x01, 0x31, 0x90, 0x88, 0xA3, 0xF8, 0x70, 0x00, 0x89, 0xB2, 0xE0, 0x6D, 0xB4, 0xF8, 0x60, 0x40, ++0xA3, 0xF8, 0x76, 0x40, 0xC3, 0xF8, 0x72, 0x00, 0x14, 0x68, 0x90, 0x88, 0x83, 0xF8, 0x69, 0x90, 0x0A, 0x01, 0x83, 0xF8, ++0x6A, 0x90, 0x83, 0xF8, 0x6B, 0x90, 0x9C, 0x67, 0xA3, 0xF8, 0x7C, 0x00, 0xAC, 0xF8, 0xFC, 0x11, 0xA3, 0xF8, 0x7E, 0x20, ++0x2A, 0x7A, 0x3A, 0x77, 0xEA, 0x79, 0x7A, 0x77, 0x03, 0xF1, 0x68, 0x04, 0x87, 0xF8, 0x33, 0x90, 0x87, 0xF8, 0x35, 0x90, ++0x08, 0x22, 0xD0, 0x21, 0x38, 0x46, 0x06, 0xF0, 0xA5, 0xFB, 0x21, 0x46, 0x38, 0x46, 0x18, 0x22, 0x05, 0xF0, 0x04, 0xFA, ++0x97, 0xF8, 0x33, 0x30, 0x18, 0x33, 0x1A, 0x19, 0x08, 0x21, 0x19, 0x55, 0x01, 0x21, 0x51, 0x70, 0xF9, 0x6C, 0xA2, 0xF8, ++0x02, 0x80, 0x97, 0xF8, 0x35, 0x00, 0x4A, 0x6A, 0x04, 0x30, 0x03, 0x44, 0x01, 0x3A, 0x1A, 0x44, 0x04, 0x33, 0xC1, 0xE9, ++0x0A, 0x23, 0x38, 0x46, 0x05, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xE5, 0xF7, 0x5F, 0xBA, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x31, 0x4B, 0x32, 0x4A, 0x1B, 0x68, 0x2D, 0xE9, 0xF0, 0x41, 0xB3, 0xF9, ++0x00, 0x30, 0xD2, 0xF8, 0x00, 0x80, 0x2F, 0x4F, 0x98, 0xF8, 0x3D, 0x50, 0x00, 0x2B, 0x06, 0x46, 0x45, 0xDB, 0x2C, 0x23, ++0x06, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x06, 0x00, 0xF7, 0xF7, 0x64, 0xFF, 0x4F, 0xF4, 0xA4, 0x61, 0x03, 0x46, 0x98, 0xF8, ++0x3D, 0x20, 0x03, 0xF8, 0x01, 0x2B, 0x01, 0xFB, 0x05, 0x71, 0x01, 0xF5, 0xB5, 0x72, 0x04, 0x46, 0x01, 0xF5, 0xC5, 0x71, ++0xD2, 0xF8, 0x00, 0xE0, 0xD2, 0xF8, 0x04, 0xC0, 0x90, 0x68, 0xD2, 0xF8, 0x0C, 0x80, 0xC3, 0xF8, 0x0C, 0x80, 0x10, 0x32, ++0x8A, 0x42, 0xC3, 0xF8, 0x00, 0xE0, 0xC3, 0xF8, 0x04, 0xC0, 0x98, 0x60, 0x03, 0xF1, 0x10, 0x03, 0xEC, 0xD1, 0x4F, 0xF4, ++0xA4, 0x61, 0x12, 0x78, 0x1A, 0x70, 0x01, 0xFB, 0x05, 0x75, 0x36, 0xBA, 0xD5, 0xF8, 0x64, 0x01, 0xB5, 0xF8, 0x68, 0x31, ++0xE3, 0x84, 0x06, 0x21, 0xC4, 0xF8, 0x22, 0x00, 0xA6, 0x62, 0x08, 0x46, 0xF8, 0xF7, 0x2A, 0xF9, 0x41, 0xF6, 0x08, 0x00, ++0x0E, 0x4A, 0x06, 0x21, 0xF7, 0xF7, 0x88, 0xFD, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xF7, 0xF7, 0x55, 0xBF, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x05, 0x73, 0xD3, 0xF8, 0xCC, 0x31, 0x00, 0x2B, 0xB1, 0xDB, 0x07, 0x49, 0x07, 0x48, 0x4F, 0xF4, ++0xAB, 0x62, 0xF9, 0xF7, 0xF9, 0xFF, 0xAA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xC0, 0x27, 0x09, 0x00, 0x70, 0x79, 0x15, 0x00, 0x74, 0xBC, 0x15, 0x00, 0x10, 0xB5, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, ++0x08, 0x00, 0xF7, 0xF7, 0x11, 0xFE, 0x1C, 0xB9, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x20, 0xBC, 0x20, 0x46, 0xBD, 0xE8, ++0x10, 0x40, 0xFF, 0xF7, 0xFF, 0xB9, 0x00, 0xBF, 0x08, 0xB5, 0x06, 0x20, 0xF8, 0xF7, 0x96, 0xF9, 0xA0, 0xF1, 0x06, 0x00, ++0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x08, 0xBD, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x07, 0x02, 0xF8, 0xF7, 0xDE, 0xFD, ++0xB8, 0xB1, 0x9D, 0xF8, 0x07, 0x30, 0x1D, 0x2B, 0x16, 0xD9, 0x02, 0x89, 0x92, 0x00, 0x0A, 0x3B, 0x92, 0xB2, 0x9B, 0x1A, ++0xDB, 0xB2, 0x15, 0x2B, 0x0E, 0xD9, 0x0A, 0x30, 0x02, 0x3B, 0x81, 0x5A, 0x89, 0x00, 0x89, 0xB2, 0x5B, 0x1A, 0xDB, 0xB2, ++0x13, 0x2B, 0x10, 0x44, 0x04, 0xD9, 0x04, 0x30, 0x40, 0x5A, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x00, 0x20, 0x03, 0xB0, ++0x5D, 0xF8, 0x04, 0xFB, 0x2D, 0xE9, 0xF0, 0x4F, 0x4F, 0xF4, 0xA4, 0x68, 0x95, 0xB0, 0xDF, 0xF8, 0x50, 0x93, 0xDF, 0xF8, ++0x50, 0xB3, 0x08, 0xFB, 0x00, 0xF3, 0x07, 0x93, 0x4B, 0x44, 0x05, 0x46, 0xD3, 0xF8, 0x90, 0x01, 0x93, 0xF8, 0x6C, 0x40, ++0x80, 0x78, 0x02, 0x93, 0x17, 0x46, 0x4F, 0xF4, 0x1E, 0x78, 0x00, 0x38, 0x08, 0xFB, 0x04, 0xB6, 0x0A, 0x46, 0x3B, 0x78, ++0xD6, 0xF8, 0xB0, 0xA0, 0x04, 0x94, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0x05, 0x92, 0x06, 0x93, 0xE5, 0xF7, ++0x6F, 0xF9, 0x00, 0x28, 0x00, 0xF0, 0xED, 0x80, 0x02, 0x9B, 0x04, 0x46, 0x21, 0x46, 0x18, 0x46, 0xF7, 0xF7, 0x64, 0xFA, ++0xB9, 0x4B, 0x96, 0xF8, 0x23, 0x00, 0xD3, 0xF8, 0x34, 0x21, 0xA3, 0x6C, 0x02, 0x93, 0x00, 0x21, 0x90, 0x47, 0x02, 0x9B, ++0x03, 0x90, 0x03, 0xF1, 0x68, 0x02, 0x08, 0x92, 0x00, 0x28, 0x40, 0xF0, 0xD9, 0x80, 0xB2, 0x49, 0xB1, 0xF8, 0xFC, 0x21, ++0x01, 0x32, 0x92, 0xB2, 0x08, 0x20, 0x83, 0xF8, 0x68, 0x00, 0x10, 0x01, 0x01, 0x26, 0x80, 0xB2, 0x83, 0xF8, 0x69, 0x60, ++0x09, 0x90, 0xA1, 0xF8, 0xFC, 0x21, 0x04, 0x99, 0x02, 0x93, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0xB2, 0x4F, 0xF4, ++0xA4, 0x66, 0x52, 0xF8, 0x26, 0x1F, 0xD9, 0x66, 0x06, 0xFB, 0x05, 0x96, 0x91, 0x88, 0xF0, 0x6D, 0xB6, 0xF8, 0x60, 0x20, ++0xA3, 0xF8, 0x76, 0x20, 0x4F, 0xF0, 0x00, 0x08, 0xA3, 0xF8, 0x70, 0x10, 0xC3, 0xF8, 0x72, 0x00, 0x05, 0x99, 0x83, 0xF8, ++0x6A, 0x80, 0x83, 0xF8, 0x6B, 0x80, 0x06, 0x22, 0x03, 0xF1, 0x78, 0x00, 0x0C, 0xF0, 0xDC, 0xF9, 0x09, 0x9B, 0x96, 0xF8, ++0x63, 0x20, 0x19, 0x01, 0x02, 0x9B, 0xA3, 0xF8, 0x7E, 0x10, 0x22, 0x77, 0x96, 0xF8, 0x6C, 0x20, 0x62, 0x77, 0x03, 0x9A, ++0x00, 0x2A, 0x00, 0xF0, 0xE1, 0x80, 0x1A, 0x22, 0x83, 0xF8, 0x80, 0x80, 0x83, 0xF8, 0x81, 0x80, 0x02, 0x92, 0x7A, 0x78, ++0x00, 0x21, 0x12, 0xF0, 0x40, 0x02, 0xCD, 0xE9, 0x0A, 0x11, 0x40, 0xF0, 0xB5, 0x80, 0x84, 0xF8, 0x33, 0x20, 0x84, 0xF8, ++0x35, 0x20, 0x89, 0x4B, 0x02, 0x9A, 0x93, 0xE8, 0x03, 0x00, 0x08, 0x9B, 0x13, 0x44, 0x1E, 0x46, 0x0D, 0xF1, 0x30, 0x0C, ++0x07, 0x9B, 0x8C, 0xE8, 0x03, 0x00, 0x08, 0x22, 0x61, 0x46, 0x30, 0x46, 0x03, 0xF1, 0x5C, 0x08, 0x0C, 0xF0, 0xA8, 0xF9, ++0x7F, 0x4B, 0xD3, 0xE9, 0x02, 0x01, 0x08, 0x22, 0x0E, 0xAB, 0x83, 0xE8, 0x03, 0x00, 0xC8, 0x44, 0x19, 0x46, 0xB0, 0x18, ++0x0C, 0xF0, 0x9C, 0xF9, 0x06, 0x22, 0x41, 0x46, 0x06, 0xF1, 0x10, 0x00, 0x0C, 0xF0, 0x96, 0xF9, 0x4F, 0xF4, 0xA4, 0x60, ++0x00, 0xFB, 0x05, 0x95, 0x9D, 0xF9, 0x18, 0x20, 0xD5, 0xF8, 0xC4, 0x34, 0xB3, 0x75, 0xD5, 0xF8, 0xC4, 0x34, 0x1B, 0x0A, ++0xF3, 0x75, 0xB5, 0xF8, 0xC6, 0x34, 0x33, 0x76, 0x95, 0xF8, 0xC7, 0x34, 0x73, 0x76, 0x7B, 0x78, 0x58, 0x06, 0x67, 0xD4, ++0x00, 0x2A, 0xB8, 0xBF, 0x07, 0xF1, 0x2A, 0x01, 0x4F, 0xF0, 0x0A, 0x02, 0xA8, 0xBF, 0x07, 0xF1, 0x28, 0x01, 0x06, 0xF1, ++0x1A, 0x00, 0x0C, 0xF0, 0x73, 0xF9, 0xE2, 0x6C, 0x94, 0xF8, 0x35, 0x50, 0x53, 0x6A, 0x02, 0x99, 0xA4, 0x65, 0x24, 0x35, ++0x0D, 0x44, 0x01, 0x3B, 0x2B, 0x44, 0x00, 0x20, 0x29, 0x1D, 0x60, 0x65, 0xC2, 0xE9, 0x0A, 0x31, 0x03, 0x9B, 0x6B, 0xB1, ++0x04, 0x9B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0xB3, 0x93, 0xF8, 0x23, 0x30, 0x02, 0xFB, 0x03, 0xBB, 0x9B, 0xF8, ++0xA5, 0x91, 0xB9, 0xF1, 0x21, 0x0F, 0x6A, 0xD1, 0x7B, 0x78, 0x59, 0x06, 0x2F, 0xD5, 0x9A, 0xF8, 0x60, 0x30, 0x01, 0x2B, ++0x00, 0xF0, 0x53, 0x81, 0x52, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x09, 0xD5, 0x9A, 0xF8, 0x60, 0x30, 0x01, 0x2B, ++0x0A, 0xF1, 0x64, 0x09, 0x40, 0xF2, 0x36, 0x81, 0x03, 0x2B, 0x00, 0xF0, 0x34, 0x81, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, ++0x8F, 0xF8, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x96, 0xF8, 0x23, 0x20, 0x08, 0xFB, 0x02, 0xB8, 0x6F, 0xF0, 0x77, 0x02, ++0xB8, 0xF8, 0x34, 0x11, 0x83, 0xF8, 0x68, 0x20, 0x4A, 0x1C, 0x01, 0x20, 0xC2, 0xF3, 0x0B, 0x02, 0x83, 0xF8, 0x69, 0x00, ++0x09, 0x91, 0x03, 0x90, 0xA8, 0xF8, 0x34, 0x21, 0x21, 0xE7, 0x3D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9A, 0x07, 0xDE, 0xD5, ++0xBA, 0xF1, 0x00, 0x0F, 0xDB, 0xD0, 0xD0, 0xE7, 0x00, 0x2A, 0xB8, 0xBF, 0x07, 0xF1, 0x32, 0x01, 0x4F, 0xF0, 0x0A, 0x02, ++0xA8, 0xBF, 0x07, 0xF1, 0x30, 0x01, 0x06, 0xF1, 0x1A, 0x00, 0x0C, 0xF0, 0x0B, 0xF9, 0x96, 0xE7, 0xE2, 0x6C, 0xB3, 0xF8, ++0x68, 0x10, 0x90, 0x6B, 0x41, 0xF4, 0x80, 0x41, 0xC2, 0x68, 0xA3, 0xF8, 0x68, 0x10, 0x22, 0xF4, 0x7F, 0x73, 0x9A, 0xF8, ++0x62, 0x20, 0x08, 0x99, 0x23, 0xF0, 0x03, 0x03, 0x13, 0x43, 0xC3, 0x60, 0x9A, 0xF8, 0x60, 0x30, 0x02, 0x98, 0x0E, 0x18, ++0x04, 0x2B, 0x00, 0xF2, 0xD3, 0x81, 0xDF, 0xE8, 0x03, 0xF0, 0x1E, 0x51, 0xBA, 0x1E, 0x85, 0x00, 0x18, 0x22, 0x02, 0x92, ++0x21, 0xE7, 0x4F, 0xEA, 0x09, 0x20, 0x40, 0xF0, 0x08, 0x00, 0xF7, 0xF7, 0xFD, 0xFF, 0x01, 0x28, 0x8C, 0xD1, 0x1E, 0x4B, ++0x09, 0x99, 0x09, 0xEB, 0x49, 0x09, 0x03, 0xEB, 0xC9, 0x09, 0x02, 0x22, 0xD9, 0xF8, 0x14, 0x00, 0x02, 0x90, 0x05, 0xF0, ++0x1D, 0xFB, 0x02, 0x98, 0x05, 0xF0, 0xF8, 0xFA, 0x7C, 0xE7, 0x04, 0x23, 0x84, 0xF8, 0x33, 0x30, 0x84, 0xF8, 0x35, 0x30, ++0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, ++0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0xBD, 0xF8, 0x02, 0x99, 0x08, 0x9A, 0xBD, 0xF8, 0x28, 0x30, 0x53, 0x52, ++0xBD, 0xF8, 0x2A, 0x30, 0x9A, 0xF8, 0x61, 0x20, 0x43, 0xEA, 0x82, 0x33, 0x73, 0x80, 0x94, 0xF8, 0x33, 0x30, 0xCB, 0x18, ++0x02, 0x93, 0xF0, 0xE6, 0x88, 0x1A, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x8C, 0xBC, 0x15, 0x00, 0x34, 0x36, 0x17, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x08, 0x22, 0x0C, 0x23, 0x84, 0xF8, 0x33, 0x20, ++0x84, 0xF8, 0x35, 0x30, 0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, ++0xE3, 0xE9, 0x12, 0x01, 0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0x89, 0xF8, 0xBD, 0xF8, 0x28, 0x20, 0x02, 0x99, ++0x42, 0xF4, 0x00, 0x53, 0x03, 0xF4, 0xFE, 0x43, 0x43, 0xEA, 0x12, 0x23, 0x08, 0x9A, 0x53, 0x52, 0x9D, 0xF8, 0x28, 0x30, ++0x9A, 0xF8, 0x61, 0x20, 0x43, 0xEA, 0x82, 0x33, 0x43, 0xF4, 0x00, 0x53, 0x73, 0x80, 0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, ++0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0x94, 0xF8, 0x33, 0x30, 0xCB, 0x18, 0x02, 0x93, 0xAE, 0xE6, 0x10, 0x23, 0x12, 0x21, ++0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x35, 0x30, 0x0F, 0x2A, 0xDA, 0xF8, 0x48, 0x30, 0xDA, 0xF8, 0x4C, 0x20, 0x40, 0xF2, ++0x00, 0x81, 0x02, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, 0x08, 0x22, ++0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0x50, 0xF8, 0x9A, 0xF8, 0x61, 0x30, 0x33, 0x80, 0xBD, 0xF8, 0x28, 0x30, 0x73, 0x80, ++0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, 0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0xBD, 0xF8, 0x2E, 0x30, 0x33, 0x81, 0x45, 0xF6, ++0x36, 0x43, 0x73, 0x81, 0xB3, 0x81, 0xF3, 0x81, 0x33, 0x82, 0x02, 0x9A, 0x94, 0xF8, 0x33, 0x30, 0x1A, 0x44, 0x02, 0x92, ++0x79, 0xE6, 0x08, 0x23, 0x84, 0xF8, 0x33, 0x30, 0x84, 0xF8, 0x35, 0x30, 0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, ++0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, 0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, ++0x21, 0xF8, 0x08, 0x9A, 0xBD, 0xF8, 0x28, 0x30, 0x10, 0x46, 0x02, 0x9A, 0x83, 0x52, 0x9A, 0xF8, 0x61, 0x30, 0x9B, 0x03, ++0x43, 0xF4, 0x00, 0x53, 0x73, 0x80, 0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, 0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0x94, 0xF8, ++0x33, 0x30, 0xD3, 0x18, 0x02, 0x93, 0x4E, 0xE6, 0x31, 0xD0, 0x03, 0x9B, 0x0D, 0xF1, 0x40, 0x0B, 0x00, 0x2B, 0x5D, 0xD1, ++0x94, 0xF8, 0x33, 0x70, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xEC, 0x37, 0x2F, 0x44, 0xBF, 0xB2, ++0x5C, 0xE0, 0x05, 0x99, 0x06, 0x22, 0x04, 0xF1, 0x0C, 0x00, 0x0B, 0xF0, 0xF3, 0xFF, 0x06, 0x22, 0x41, 0x46, 0x04, 0xF1, ++0x12, 0x00, 0x0B, 0xF0, 0xED, 0xFF, 0x03, 0x9B, 0x00, 0x22, 0xE2, 0x76, 0x00, 0x2B, 0x78, 0xD0, 0x94, 0xF8, 0x35, 0x10, ++0x94, 0xF8, 0x33, 0x30, 0x69, 0x48, 0x0B, 0x44, 0xEB, 0x1A, 0xD0, 0xF8, 0x7C, 0x73, 0x00, 0x92, 0x1A, 0x3B, 0x32, 0x46, ++0x0A, 0xF1, 0x50, 0x01, 0x20, 0x46, 0xB8, 0x47, 0x8A, 0xE6, 0x03, 0x9B, 0x94, 0xF8, 0x33, 0x70, 0x00, 0x2B, 0x00, 0xF0, ++0x82, 0x80, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xF2, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, ++0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x30, 0x46, 0xDA, 0xF7, 0x7E, 0xFE, 0xDA, 0xF8, 0x48, 0xC0, 0xDA, 0xF8, 0x4C, 0x00, ++0x57, 0x49, 0x4F, 0xEA, 0x1C, 0x43, 0x43, 0xEA, 0x00, 0x43, 0x0D, 0xF1, 0x40, 0x0B, 0x0B, 0x60, 0x42, 0x46, 0x5B, 0x46, ++0x48, 0x46, 0xA1, 0xF8, 0x04, 0xC0, 0xF7, 0xF7, 0x45, 0xF8, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0x05, 0xFA, 0x9A, 0xF8, ++0x60, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x85, 0x80, 0x94, 0xF8, 0x33, 0x70, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, ++0x7F, 0x47, 0xEA, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x39, 0x1F, 0x30, 0x46, 0xDA, 0xF7, ++0x51, 0xFE, 0x9A, 0xF8, 0x60, 0x30, 0xBA, 0xF8, 0x48, 0x10, 0xBA, 0xF8, 0x4A, 0x20, 0xAD, 0xF8, 0x40, 0x10, 0x8D, 0xF8, ++0x42, 0x20, 0x49, 0x46, 0x7B, 0xBB, 0x05, 0x22, 0x0D, 0xF1, 0x43, 0x00, 0x0B, 0xF0, 0x84, 0xFF, 0x58, 0x46, 0x08, 0x21, ++0xF7, 0xF7, 0xDA, 0xF9, 0x03, 0x20, 0xDA, 0xF7, 0x71, 0xFE, 0x39, 0x46, 0x02, 0x46, 0x30, 0x46, 0xF7, 0xF7, 0x04, 0xF8, ++0x39, 0x46, 0x30, 0x46, 0xF7, 0xF7, 0xFA, 0xF9, 0x20, 0x46, 0x05, 0x21, 0xE4, 0xF7, 0xC6, 0xFE, 0x35, 0xE6, 0x94, 0xF8, ++0x35, 0x20, 0x94, 0xF8, 0x33, 0x30, 0x2D, 0x49, 0x13, 0x44, 0xD1, 0xF8, 0x7C, 0x73, 0x03, 0x99, 0x00, 0x91, 0xEB, 0x1A, ++0x18, 0x3B, 0x32, 0x46, 0x0A, 0xF1, 0x50, 0x01, 0x20, 0x46, 0xB8, 0x47, 0x10, 0xE6, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, ++0xFE, 0xE6, 0x0D, 0x22, 0x0D, 0xF1, 0x43, 0x00, 0x0B, 0xF0, 0x54, 0xFF, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0xAA, 0xF9, ++0xCE, 0xE7, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xF4, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, ++0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x30, 0x46, 0xDA, 0xF7, 0xFC, 0xFD, 0xDA, 0xF8, 0x48, 0xC0, 0xDA, 0xF8, 0x4C, 0x00, ++0x16, 0x49, 0x4F, 0xEA, 0x1C, 0x43, 0x43, 0xEA, 0x00, 0x43, 0x0D, 0xF1, 0x40, 0x0B, 0x0B, 0x60, 0x42, 0x46, 0x5B, 0x46, ++0x48, 0x46, 0xA1, 0xF8, 0x04, 0xC0, 0xF6, 0xF7, 0xC3, 0xFF, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0x83, 0xF9, 0x9A, 0xF8, ++0x60, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x20, 0xAF, 0x03, 0x2B, 0xA1, 0xD1, 0x1C, 0xE7, 0x03, 0x2B, 0x9E, 0xD1, 0x77, 0xE7, ++0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xDC, 0xAE, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, ++0x2C, 0x62, 0xF9, 0xF7, 0x6B, 0xFC, 0xD4, 0xE6, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x34, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x05, 0xDB, 0x0A, 0x4B, 0x00, 0x20, 0x5B, 0x68, 0x98, 0x47, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x10, 0xFE, ++0x02, 0x28, 0xF4, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x31, 0x12, 0xF9, 0xF7, 0x48, 0xFC, 0xED, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xC0, 0xBC, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x0C, 0x46, 0x36, 0x49, 0x60, 0x7C, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x10, 0x86, 0xB0, 0x90, 0xF8, 0x62, 0x10, ++0x00, 0x25, 0x02, 0x29, 0x98, 0x46, 0x8D, 0xF8, 0x0B, 0x50, 0x10, 0xD0, 0x04, 0x25, 0x41, 0x46, 0x02, 0x23, 0x41, 0xF6, ++0x05, 0x40, 0xF7, 0xF7, 0x43, 0xFB, 0x05, 0x70, 0x9D, 0xF8, 0x0B, 0x20, 0x42, 0x70, 0xF7, 0xF7, 0x6D, 0xFB, 0x00, 0x20, ++0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x90, 0xF8, 0x64, 0x10, 0x09, 0xB1, 0x08, 0x25, 0xEA, 0xE7, 0x07, 0x20, 0x01, 0x92, ++0xF7, 0xF7, 0xD2, 0xFD, 0x01, 0x9A, 0x00, 0x28, 0xF6, 0xD1, 0xA7, 0x78, 0x20, 0x7C, 0x21, 0x88, 0x1F, 0x4E, 0x8D, 0xF8, ++0x0C, 0x70, 0x8D, 0xF8, 0x0D, 0x00, 0xA7, 0x68, 0xE0, 0x68, 0xAD, 0xF8, 0x0E, 0x10, 0x21, 0x79, 0x75, 0x6C, 0xAD, 0xF8, ++0x12, 0x00, 0x8D, 0xF8, 0x14, 0x10, 0xAD, 0xF8, 0x10, 0x70, 0x0D, 0xF1, 0x0B, 0x01, 0x03, 0xA8, 0xA8, 0x47, 0x01, 0x9A, ++0x05, 0x46, 0x10, 0xBB, 0xF6, 0x6C, 0x60, 0x7C, 0x9D, 0xF8, 0x0B, 0x10, 0xB0, 0x47, 0xEF, 0xF3, 0x10, 0x81, 0x11, 0xF0, ++0x01, 0x0F, 0x01, 0x9A, 0x03, 0xD1, 0x72, 0xB6, 0x0E, 0x49, 0x01, 0x20, 0x08, 0x60, 0x0E, 0x48, 0x0E, 0x4F, 0x04, 0x68, ++0x79, 0x68, 0x66, 0x1C, 0x41, 0xF0, 0x10, 0x01, 0x06, 0x60, 0x79, 0x60, 0x00, 0x2E, 0xAE, 0xD0, 0x07, 0x49, 0x04, 0x60, ++0x09, 0x68, 0x00, 0x2C, 0xA9, 0xD1, 0x00, 0x29, 0xA7, 0xD0, 0x62, 0xB6, 0xA5, 0xE7, 0x01, 0x25, 0xA3, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x43, 0x0C, 0x46, 0x85, 0xB0, 0x90, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x4A, 0x69, 0x4D, 0x49, 0x4E, 0x4F, ++0x99, 0x46, 0xF9, 0xF7, 0x8D, 0xF9, 0x94, 0xF8, 0x33, 0x60, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x06, 0x75, 0x95, 0xF8, ++0x62, 0x10, 0x02, 0x29, 0x11, 0xD0, 0x04, 0x25, 0x42, 0x46, 0x49, 0x46, 0x04, 0x23, 0x41, 0xF6, 0x01, 0x40, 0xF7, 0xF7, ++0xC3, 0xFA, 0x05, 0x70, 0x94, 0xF8, 0x33, 0x20, 0x42, 0x70, 0xF7, 0xF7, 0xED, 0xFA, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x83, 0x07, 0x20, 0xF7, 0xF7, 0x58, 0xFD, 0xC0, 0xB9, 0x95, 0xF8, 0x64, 0x30, 0xBB, 0xB9, 0x3B, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x13, 0xDB, 0x23, 0x7F, 0x39, 0x49, 0x00, 0x93, 0xD4, 0xE9, 0x05, 0x23, 0x0C, 0x60, ++0x0D, 0xF1, 0x0D, 0x00, 0x04, 0xF1, 0x0E, 0x01, 0xFD, 0xF7, 0xAC, 0xF9, 0x05, 0x46, 0x70, 0xB1, 0x01, 0x25, 0xD1, 0xE7, ++0x08, 0x25, 0xCF, 0xE7, 0x09, 0x25, 0xCD, 0xE7, 0x2B, 0x6C, 0x00, 0x2B, 0xE8, 0xD0, 0x2F, 0x49, 0x2F, 0x48, 0x56, 0x22, ++0xF9, 0xF7, 0x72, 0xFB, 0xE2, 0xE7, 0xE1, 0x89, 0x20, 0x7C, 0xDF, 0xF8, 0xB4, 0x80, 0xFB, 0xF7, 0x9B, 0xFF, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x06, 0xF2, 0x07, 0xEB, 0x02, 0x09, 0xC9, 0xF8, 0x90, 0x01, 0x94, 0xF9, 0x12, 0x30, 0x03, 0x71, ++0xD4, 0xE9, 0x05, 0x31, 0xA9, 0xF8, 0x96, 0x11, 0xA9, 0xF8, 0x94, 0x31, 0x23, 0x7F, 0x89, 0xF8, 0xC5, 0x31, 0x04, 0x2B, ++0x08, 0xBF, 0x03, 0x23, 0x89, 0xF8, 0xC4, 0x31, 0x89, 0xF8, 0xC6, 0x51, 0xD8, 0xF8, 0x4C, 0x30, 0x94, 0xF8, 0x33, 0x00, ++0x9D, 0xF8, 0x0D, 0x10, 0x15, 0x46, 0x98, 0x47, 0x23, 0x7C, 0xA3, 0xB1, 0x00, 0xF0, 0x8C, 0xFA, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x06, 0x73, 0x78, 0x19, 0xD3, 0xF8, 0x90, 0x31, 0xD8, 0xF8, 0x40, 0x43, 0x1B, 0x79, 0x8D, 0xF8, 0x0E, 0x30, ++0x0D, 0xF1, 0x0F, 0x02, 0x0D, 0xF1, 0x0E, 0x01, 0xA0, 0x47, 0x01, 0x20, 0x92, 0xE7, 0x05, 0xF5, 0xCE, 0x70, 0x38, 0x44, ++0x01, 0x21, 0xFC, 0xF7, 0x45, 0xF9, 0x10, 0xF0, 0x0F, 0x00, 0x1A, 0xBF, 0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x1F, 0x03, ++0x01, 0x23, 0x89, 0xF8, 0xC1, 0x31, 0xD9, 0xE7, 0xEC, 0xBC, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x94, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x4F, 0x88, ++0x0D, 0x48, 0x0C, 0x46, 0x16, 0x46, 0x04, 0x31, 0x3A, 0x46, 0x1D, 0x46, 0x0B, 0xF0, 0xAE, 0xFD, 0xDF, 0xF8, 0x28, 0xC0, ++0x32, 0x46, 0x29, 0x46, 0x02, 0x23, 0x41, 0xF6, 0x09, 0x40, 0xAC, 0xF8, 0x00, 0x70, 0xF7, 0xF7, 0x1B, 0xFA, 0x01, 0x22, ++0x02, 0x70, 0x22, 0x78, 0x42, 0x70, 0xF7, 0xF7, 0x45, 0xFA, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x14, 0x2A, 0x17, 0x00, ++0x14, 0x2C, 0x17, 0x00, 0x08, 0xB5, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x07, 0x20, ++0xF7, 0xF7, 0xA6, 0xFC, 0x01, 0x28, 0x06, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0xA1, 0xFC, 0x03, 0x28, 0x01, 0xD0, 0x00, 0x20, ++0x08, 0xBD, 0x00, 0xF0, 0x01, 0xFA, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x96, 0xFC, 0x01, 0x28, 0xEA, 0xD0, ++0x07, 0x20, 0xF7, 0xF7, 0x91, 0xFC, 0x00, 0x28, 0xE5, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x8C, 0xFC, 0x03, 0x28, 0xE0, 0xD0, ++0x03, 0x49, 0x04, 0x48, 0xC2, 0x22, 0xF9, 0xF7, 0xC5, 0xFA, 0xDA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0xFC, 0xBC, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, ++0xDB, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x70, 0xFC, 0x01, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, ++0xE6, 0x22, 0xF9, 0xF7, 0xA9, 0xFA, 0x00, 0xF0, 0xCD, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x84, 0xBD, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0x03, 0xDB, 0x00, 0xF0, 0xBB, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x50, 0xFC, 0x03, 0x28, 0xF6, 0xD0, ++0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0xF9, 0xF7, 0x88, 0xFA, 0x00, 0xF0, 0xAC, 0xF9, 0x00, 0x20, 0x08, 0xBD, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB4, 0xBD, 0x15, 0x00, 0x08, 0xB5, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x06, 0xDB, 0x07, 0x20, 0xF7, 0xF7, 0x34, 0xFC, 0x03, 0x28, 0x12, 0xD0, 0x00, 0x20, 0x08, 0xBD, ++0x07, 0x20, 0xF7, 0xF7, 0x2D, 0xFC, 0x03, 0x28, 0xF3, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x28, 0xFC, 0x00, 0x28, 0xEE, 0xD0, ++0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0x65, 0x12, 0xF9, 0xF7, 0x60, 0xFA, 0xE7, 0xE7, 0x00, 0xF0, 0x83, 0xF9, 0x00, 0x20, ++0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xDC, 0xBD, 0x15, 0x00, 0xF8, 0xB5, 0x0C, 0x46, ++0x4F, 0xF4, 0x80, 0x70, 0x13, 0x49, 0x16, 0x46, 0x1D, 0x46, 0xF9, 0xF7, 0x21, 0xF8, 0x24, 0x78, 0x11, 0x4B, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, 0x62, 0x70, 0x02, 0x2F, 0x02, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x3B, 0xB9, ++0x32, 0x46, 0x29, 0x46, 0x41, 0xF6, 0x03, 0x40, 0xF7, 0xF7, 0xBE, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x07, 0x20, 0xF7, 0xF7, ++0xF3, 0xFB, 0x05, 0x46, 0x28, 0xB9, 0x06, 0x4B, 0x20, 0x46, 0x9B, 0x68, 0x98, 0x47, 0x28, 0x46, 0xF8, 0xBD, 0x38, 0x46, ++0xF8, 0xBD, 0x00, 0xBF, 0x30, 0xBE, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0C, 0x46, ++0x21, 0x49, 0x20, 0x78, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x10, 0x82, 0xB0, 0x90, 0xF8, 0x62, 0x50, 0x02, 0x2D, ++0x19, 0x46, 0x06, 0xD0, 0x41, 0xF6, 0x07, 0x40, 0xF7, 0xF7, 0x96, 0xF9, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x90, 0xF8, ++0x64, 0x30, 0x00, 0x2B, 0xF4, 0xD1, 0x07, 0x20, 0xCD, 0xE9, 0x00, 0x21, 0xF7, 0xF7, 0xC4, 0xFB, 0xDD, 0xE9, 0x00, 0x21, ++0x00, 0x28, 0xEB, 0xD1, 0x12, 0x4B, 0x20, 0x78, 0x5B, 0x6D, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0x13, 0xF0, 0x01, 0x0F, ++0xDD, 0xE9, 0x00, 0x21, 0x03, 0xD1, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x0D, 0x48, 0x0D, 0x4E, 0x04, 0x68, ++0x73, 0x68, 0x65, 0x1C, 0x23, 0xF0, 0x10, 0x03, 0x05, 0x60, 0x73, 0x60, 0x00, 0x2D, 0xD1, 0xD0, 0x06, 0x4B, 0x04, 0x60, ++0x1B, 0x68, 0x00, 0x2C, 0xCC, 0xD1, 0x00, 0x2B, 0xCA, 0xD0, 0x62, 0xB6, 0xC8, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x22, 0x4C, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0x07, 0x20, 0xF7, 0xF7, 0x88, 0xFB, 0x01, 0x28, 0x13, 0xD1, ++0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0x9B, 0xF9, 0x00, 0x20, 0x10, 0xBD, 0x19, 0x4B, ++0x5B, 0x68, 0x00, 0x2B, 0xF7, 0xD0, 0x18, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x0B, 0x12, 0xF9, 0xF7, 0xB3, 0xF9, 0xF0, 0xE7, ++0x07, 0x20, 0xF7, 0xF7, 0x6F, 0xFB, 0x03, 0x28, 0xED, 0xD1, 0x07, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x03, 0x40, 0xF7, 0xF7, ++0x2D, 0xF9, 0x00, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0xBB, 0xFA, 0xE2, 0xE7, 0x07, 0x20, 0xF7, 0xF7, 0x5F, 0xFB, 0x01, 0x28, ++0xD1, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x5A, 0xFB, 0x00, 0x28, 0xCC, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x55, 0xFB, 0x03, 0x28, ++0xC7, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x03, 0x12, 0xF9, 0xF7, 0x8D, 0xF9, 0xC0, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0x94, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0xBE, 0x15, 0x00, 0xFC, 0xBC, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x08, 0x40, 0x09, 0x48, 0xF7, 0xF7, 0x1E, 0xBD, ++0x08, 0x4B, 0x5B, 0x68, 0x00, 0x2B, 0xF6, 0xD0, 0x07, 0x48, 0x08, 0x49, 0x2D, 0x22, 0xF9, 0xF7, 0x6D, 0xF9, 0xBD, 0xE8, ++0x08, 0x40, 0x02, 0x48, 0xF7, 0xF7, 0x10, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x98, 0xBA, 0x17, 0x00, 0x94, 0xBA, 0x17, 0x00, ++0x3C, 0xBE, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0x00, 0x21, 0x20, 0x46, 0x10, 0x22, 0xD4, 0xF7, ++0x6F, 0xFC, 0x00, 0x21, 0x21, 0x73, 0x07, 0x20, 0xBD, 0xE8, 0x10, 0x40, 0xF7, 0xF7, 0x68, 0xBA, 0x94, 0xBA, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0xD8, 0x80, 0x05, 0x46, 0x04, 0x23, 0x07, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x01, 0x40, ++0xD8, 0xF8, 0x00, 0x60, 0xF7, 0xF7, 0x5E, 0xF8, 0x04, 0x46, 0x95, 0xB1, 0x96, 0xF8, 0x33, 0x30, 0x63, 0x70, 0x20, 0x46, ++0x25, 0x70, 0xF7, 0xF7, 0x85, 0xF8, 0xA6, 0xF1, 0x0C, 0x00, 0xF7, 0xF7, 0xCD, 0xF8, 0x00, 0x21, 0xC8, 0xF8, 0x00, 0x10, ++0x07, 0x20, 0xBD, 0xE8, 0xF0, 0x47, 0xF7, 0xF7, 0x43, 0xBA, 0x04, 0x23, 0x29, 0x46, 0x07, 0x22, 0x1E, 0x20, 0x96, 0xF8, ++0x33, 0x70, 0xF7, 0xF7, 0x41, 0xF8, 0x21, 0x4A, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x07, 0x29, 0x4F, 0xF0, 0x01, 0x0A, ++0x80, 0xF8, 0x02, 0xA0, 0x99, 0xF8, 0x63, 0x20, 0xC2, 0x70, 0xF7, 0xF7, 0x63, 0xF8, 0xF1, 0x6A, 0x32, 0x8E, 0xD9, 0xF8, ++0x40, 0x30, 0xC9, 0xF8, 0xB0, 0x14, 0xA9, 0xF8, 0xE0, 0x20, 0x89, 0xF8, 0xDE, 0x50, 0x1B, 0x7E, 0xA3, 0x70, 0x96, 0xF8, ++0x33, 0x30, 0xDF, 0xF8, 0x54, 0xC0, 0x0A, 0x33, 0xE3, 0x70, 0x96, 0xE8, 0x0F, 0x00, 0x4F, 0xF4, 0x1E, 0x7E, 0x0A, 0x37, ++0x0E, 0xFB, 0x07, 0xC7, 0x07, 0xF1, 0xB8, 0x0C, 0xAC, 0xE8, 0x07, 0x00, 0x02, 0x22, 0x87, 0xF8, 0x30, 0x20, 0x8C, 0xF8, ++0x00, 0x30, 0x38, 0x46, 0xFB, 0xF7, 0xA0, 0xFF, 0x97, 0xF8, 0x56, 0x31, 0xA7, 0xF8, 0x26, 0xA0, 0x43, 0xF0, 0x10, 0x03, ++0x87, 0xF8, 0x56, 0x31, 0x96, 0xF8, 0x33, 0x30, 0x03, 0xF1, 0x0A, 0x02, 0x87, 0xF8, 0x23, 0x20, 0xA4, 0xE7, 0x00, 0xBF, ++0x18, 0x88, 0x17, 0x00, 0x94, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x48, 0xF7, 0xF7, 0xC6, 0xFC, ++0x0B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x05, 0xDB, 0x04, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, ++0x10, 0x40, 0xF7, 0xF7, 0x17, 0xB8, 0x00, 0x28, 0xF7, 0xD1, 0x05, 0x49, 0x05, 0x48, 0xCB, 0x22, 0xF9, 0xF7, 0xC2, 0xF8, ++0xF1, 0xE7, 0x00, 0xBF, 0x98, 0xBA, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, ++0x2D, 0xE9, 0xF8, 0x4F, 0x44, 0x4B, 0xDF, 0xF8, 0x1C, 0xB1, 0x1C, 0x68, 0x07, 0x22, 0x08, 0x23, 0x00, 0x21, 0x18, 0x20, ++0x94, 0xF8, 0x33, 0x90, 0xF6, 0xF7, 0xC8, 0xFF, 0x08, 0x23, 0x07, 0x22, 0x00, 0x21, 0x06, 0x46, 0x16, 0x20, 0xF6, 0xF7, ++0xC1, 0xFF, 0x04, 0x23, 0x07, 0x22, 0x00, 0x21, 0x05, 0x46, 0x14, 0x20, 0xF6, 0xF7, 0xBA, 0xFF, 0x02, 0x23, 0x07, 0x22, ++0x05, 0x21, 0x80, 0x46, 0x41, 0xF2, 0x17, 0x40, 0xF6, 0xF7, 0xB2, 0xFF, 0x4F, 0xF4, 0xA4, 0x6A, 0x0A, 0xFB, 0x09, 0xBA, ++0x07, 0x46, 0xFF, 0xF7, 0x0B, 0xFF, 0x9A, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x49, 0xD0, 0x2F, 0x4A, 0x13, 0x68, 0x23, 0xF0, ++0x04, 0x03, 0x13, 0x60, 0xDA, 0xF8, 0x04, 0x30, 0x43, 0xF0, 0x20, 0x03, 0xCA, 0xF8, 0x04, 0x30, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x09, 0xB9, 0xA6, 0xF1, 0x0C, 0x01, 0xD9, 0xF8, 0x5C, 0x00, 0xB9, 0xF8, 0x60, 0x30, 0xB3, 0x80, 0x30, 0x60, ++0x94, 0xF8, 0x33, 0x30, 0xB3, 0x71, 0x23, 0x48, 0xF7, 0xF7, 0x18, 0xFC, 0x23, 0x7C, 0x6B, 0x71, 0x01, 0x21, 0x20, 0x46, ++0xFB, 0xF7, 0x80, 0xFE, 0x28, 0x60, 0x94, 0xF8, 0x33, 0x30, 0x2B, 0x71, 0xA5, 0xF1, 0x0C, 0x01, 0x1B, 0x48, 0xF7, 0xF7, ++0x09, 0xFC, 0x23, 0x8D, 0xA8, 0xF8, 0x00, 0x30, 0x94, 0xF8, 0x33, 0x30, 0x88, 0xF8, 0x02, 0x30, 0xA8, 0xF1, 0x0C, 0x01, ++0x01, 0x25, 0x15, 0x48, 0xF7, 0xF7, 0xFC, 0xFB, 0x3D, 0x70, 0x94, 0xF8, 0x33, 0x30, 0x12, 0x48, 0x7B, 0x70, 0xA7, 0xF1, ++0x0C, 0x01, 0xF7, 0xF7, 0xF3, 0xFB, 0xFF, 0xF7, 0x6B, 0xFF, 0x29, 0x46, 0x07, 0x20, 0xBD, 0xE8, 0xF8, 0x4F, 0xF7, 0xF7, ++0x57, 0xB9, 0x02, 0x23, 0x07, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF6, 0xF7, 0x56, 0xFF, 0x01, 0x23, 0x03, 0x70, ++0x9A, 0xF8, 0x63, 0x30, 0x43, 0x70, 0x03, 0x4B, 0x01, 0x46, 0x0C, 0x39, 0x18, 0x1D, 0xF7, 0xF7, 0xD9, 0xFB, 0xAD, 0xE7, ++0x94, 0xBA, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x98, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0xB5, 0x0E, 0x4C, ++0x0C, 0x23, 0x07, 0x22, 0x00, 0x21, 0x3F, 0x20, 0x24, 0x68, 0xF6, 0xF7, 0x39, 0xFF, 0xA1, 0x8C, 0xE2, 0x8C, 0x25, 0x6A, ++0x05, 0x60, 0x81, 0x80, 0xC2, 0x80, 0x94, 0xF8, 0x32, 0x20, 0x02, 0x72, 0x94, 0xF8, 0x33, 0x20, 0x42, 0x72, 0xF6, 0xF7, ++0x5B, 0xFF, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0x1F, 0xB9, 0x00, 0xBF, 0x94, 0xBA, 0x17, 0x00, ++0xF8, 0xB5, 0x07, 0x22, 0x04, 0x46, 0x02, 0x23, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF6, 0xF7, 0x19, 0xFF, 0x02, 0x23, ++0x06, 0x46, 0x07, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x17, 0x40, 0xF6, 0xF7, 0x11, 0xFF, 0x00, 0x27, 0x05, 0x46, 0xFF, 0xF7, ++0x6D, 0xFE, 0x37, 0x70, 0x94, 0xF8, 0x63, 0x30, 0x73, 0x70, 0x1D, 0x48, 0xA6, 0xF1, 0x0C, 0x01, 0xF7, 0xF7, 0x92, 0xFB, ++0x94, 0xF8, 0x64, 0x30, 0x0B, 0xBB, 0x23, 0x6C, 0x6B, 0xB1, 0x01, 0x23, 0x00, 0x21, 0x07, 0x22, 0x39, 0x20, 0xF6, 0xF7, ++0xF9, 0xFE, 0x01, 0x46, 0x94, 0xF8, 0x63, 0x30, 0x01, 0xF8, 0x0C, 0x39, 0x12, 0x48, 0xF7, 0xF7, 0x7F, 0xFB, 0x00, 0x23, ++0x2B, 0x70, 0x94, 0xF8, 0x63, 0x30, 0x0F, 0x48, 0x6B, 0x70, 0xA5, 0xF1, 0x0C, 0x01, 0xF7, 0xF7, 0x75, 0xFB, 0xFF, 0xF7, ++0xED, 0xFE, 0xBD, 0xE8, 0xF8, 0x40, 0x03, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0xD9, 0xB8, 0x39, 0x46, 0x04, 0x23, 0x07, 0x22, ++0x1E, 0x20, 0xF6, 0xF7, 0xD9, 0xFE, 0x87, 0x70, 0x94, 0xF8, 0x63, 0x30, 0xC3, 0x70, 0xA0, 0xF1, 0x0C, 0x01, 0x02, 0x48, ++0xF7, 0xF7, 0x5E, 0xFB, 0xCD, 0xE7, 0x00, 0xBF, 0x98, 0xBA, 0x17, 0x00, 0x15, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, ++0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x13, 0xD1, 0x43, 0x7F, 0x0D, 0x2B, 0x10, 0xD8, 0x82, 0x88, ++0x2A, 0xB9, 0x82, 0x6C, 0xB2, 0xF8, 0x68, 0x20, 0xB2, 0xF5, 0x12, 0x7F, 0x08, 0xD0, 0x0C, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, ++0x01, 0xFB, 0x03, 0x22, 0x92, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x02, 0xD0, 0x01, 0x23, 0x18, 0x46, 0x70, 0x47, 0x92, 0xF8, ++0x32, 0x20, 0x12, 0xF0, 0x03, 0x02, 0xF8, 0xD1, 0xC1, 0x8B, 0x41, 0xF4, 0x80, 0x51, 0x13, 0x46, 0xC1, 0x83, 0xF2, 0xE7, ++0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xC3, 0x8B, 0xDB, 0x04, 0x00, 0xD4, 0x70, 0x47, 0x10, 0xB5, 0x0C, 0x46, ++0xC2, 0x7E, 0x15, 0x49, 0x94, 0xF8, 0x2E, 0x31, 0x8A, 0x5C, 0x13, 0x42, 0x1A, 0xD0, 0x94, 0xF8, 0x31, 0x20, 0x11, 0x07, ++0x1A, 0xD4, 0x42, 0xF0, 0x08, 0x02, 0x0F, 0x2B, 0x84, 0xF8, 0x31, 0x20, 0x14, 0xD1, 0x05, 0x22, 0x04, 0x23, 0x00, 0x21, ++0x41, 0x20, 0xF6, 0xF7, 0x7F, 0xFE, 0x22, 0x8C, 0x02, 0x80, 0x94, 0xF8, 0x22, 0x20, 0xC2, 0x70, 0x01, 0x22, 0x82, 0x70, ++0xBD, 0xE8, 0x10, 0x40, 0xF6, 0xF7, 0xA4, 0xBE, 0x94, 0xF8, 0x31, 0x30, 0x9A, 0x07, 0x00, 0xD5, 0x10, 0xBD, 0x43, 0xF0, ++0x02, 0x03, 0x84, 0xF8, 0x31, 0x30, 0xE4, 0xE7, 0xA4, 0xB2, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x90, 0xF8, 0x62, 0x70, ++0x02, 0x2F, 0x91, 0x46, 0x5A, 0xD1, 0x91, 0xF8, 0x32, 0x20, 0x0E, 0x46, 0x00, 0x2A, 0x55, 0xD0, 0x12, 0xF0, 0x01, 0x08, ++0x91, 0xF8, 0x31, 0x30, 0x04, 0xBF, 0x08, 0x27, 0x4F, 0xF0, 0x04, 0x08, 0x1F, 0x42, 0x78, 0xD0, 0xD1, 0xF8, 0xFC, 0x41, ++0x00, 0x2C, 0x68, 0xD0, 0xA2, 0xF1, 0x02, 0x02, 0xB2, 0xFA, 0x82, 0xF2, 0x91, 0xF8, 0x2E, 0x11, 0x3C, 0x4D, 0x52, 0x09, ++0x4F, 0xF0, 0x00, 0x0A, 0x04, 0xE0, 0x23, 0x68, 0xA2, 0x46, 0x00, 0x2B, 0x59, 0xD0, 0x1C, 0x46, 0xE3, 0x7E, 0xEB, 0x5C, ++0x19, 0x42, 0x0C, 0xBF, 0x01, 0x23, 0x00, 0x23, 0x93, 0x42, 0xF2, 0xD0, 0x51, 0x46, 0x22, 0x46, 0x06, 0xF5, 0xFE, 0x70, ++0xF7, 0xF7, 0xC8, 0xFB, 0x96, 0xF8, 0x32, 0x10, 0x11, 0xF0, 0x08, 0x0F, 0x0C, 0xBF, 0x03, 0x23, 0x04, 0x23, 0xE3, 0x76, ++0xBA, 0xF1, 0x00, 0x0F, 0x52, 0xD0, 0xDA, 0xF8, 0x00, 0x30, 0x0B, 0xB3, 0xA1, 0xF1, 0x02, 0x01, 0xB1, 0xFA, 0x81, 0xF1, ++0x96, 0xF8, 0x2E, 0x01, 0x49, 0x09, 0x01, 0xE0, 0x1B, 0x68, 0xBB, 0xB1, 0xDA, 0x7E, 0xAA, 0x5C, 0x10, 0x42, 0x0C, 0xBF, ++0x01, 0x22, 0x00, 0x22, 0x8A, 0x42, 0xF5, 0xD0, 0xA2, 0x6C, 0xB2, 0xF8, 0x68, 0x30, 0x43, 0xF4, 0x00, 0x53, 0xA2, 0xF8, ++0x68, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x24, 0xC9, 0xF8, 0x00, 0x40, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, ++0x96, 0xF8, 0x31, 0x10, 0x21, 0xEA, 0x07, 0x07, 0x17, 0xEA, 0x08, 0x01, 0x86, 0xF8, 0x31, 0x70, 0x07, 0xEA, 0x08, 0x05, ++0xE4, 0xD1, 0x04, 0x23, 0x05, 0x22, 0x41, 0x20, 0xF6, 0xF7, 0xF0, 0xFD, 0x32, 0x8C, 0x02, 0x80, 0x96, 0xF8, 0x22, 0x20, ++0xC2, 0x70, 0x85, 0x70, 0xF6, 0xF7, 0x18, 0xFE, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x05, 0xDA, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0x91, 0x12, 0xF8, 0xF7, 0xD3, 0xFE, 0x01, 0x23, ++0x00, 0x24, 0xC9, 0xF8, 0x00, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0xFC, 0x31, 0xAB, 0xE7, 0x00, 0xBF, ++0xA4, 0xB2, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0xB5, 0x90, 0xF8, ++0x62, 0x30, 0x02, 0x2B, 0x14, 0xD1, 0x13, 0x4C, 0x13, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0x44, 0x21, 0x46, ++0xD3, 0xF8, 0x20, 0x33, 0x00, 0x22, 0x98, 0x47, 0x94, 0xF8, 0x31, 0x10, 0x11, 0xF0, 0x0A, 0x0F, 0x04, 0xD0, 0x01, 0xF0, ++0xF5, 0x05, 0x84, 0xF8, 0x31, 0x50, 0x05, 0xB1, 0x38, 0xBD, 0x29, 0x46, 0x04, 0x23, 0x05, 0x22, 0x41, 0x20, 0xF6, 0xF7, ++0xA5, 0xFD, 0x94, 0xF8, 0x22, 0x20, 0x21, 0x8C, 0xC2, 0x70, 0x85, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x01, 0x80, 0xF6, 0xF7, ++0xCB, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x03, 0x6C, 0x2D, 0xE9, 0xF0, 0x41, 0x04, 0x46, ++0x88, 0x46, 0x00, 0x2B, 0x6C, 0xD0, 0x3A, 0x4A, 0x1B, 0x79, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x53, 0xDB, ++0x94, 0xF8, 0xC0, 0x24, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE4, 0xF7, 0x4C, 0xF8, ++0x05, 0x46, 0x00, 0x28, 0x56, 0xD0, 0x01, 0x46, 0x20, 0x46, 0xF6, 0xF7, 0x43, 0xF9, 0xAE, 0x6C, 0x00, 0x27, 0x6F, 0xF0, ++0x3F, 0x03, 0x41, 0x46, 0x86, 0xF8, 0x68, 0x30, 0x86, 0xF8, 0x69, 0x70, 0x86, 0xF8, 0x6A, 0x70, 0x86, 0xF8, 0x6B, 0x70, ++0x06, 0xF1, 0x6C, 0x00, 0x06, 0x22, 0x0B, 0xF0, 0xED, 0xF8, 0x26, 0x4A, 0xE0, 0x6D, 0xB2, 0xF8, 0xFC, 0x31, 0xB4, 0xF8, ++0x60, 0x10, 0xB4, 0xF8, 0x60, 0xC0, 0xC6, 0xF8, 0x72, 0x00, 0x01, 0x33, 0x9B, 0xB2, 0xE0, 0x6D, 0xA6, 0xF8, 0x76, 0x10, ++0x19, 0x01, 0xB0, 0x67, 0xA6, 0xF8, 0x7C, 0xC0, 0xA2, 0xF8, 0xFC, 0x31, 0xA6, 0xF8, 0x7E, 0x10, 0xC5, 0xE9, 0x15, 0x74, ++0x94, 0xF8, 0x63, 0x30, 0x2B, 0x77, 0xFF, 0x23, 0x6B, 0x77, 0x06, 0xF1, 0x80, 0x00, 0x07, 0x21, 0xF9, 0xF7, 0xCE, 0xFD, ++0xE9, 0x6C, 0x4B, 0x6A, 0x17, 0x33, 0x1A, 0x18, 0x00, 0xF1, 0x1C, 0x03, 0xC1, 0xE9, 0x0A, 0x23, 0x28, 0x46, 0x05, 0x21, ++0xBD, 0xE8, 0xF0, 0x41, 0xE4, 0xF7, 0x12, 0xB8, 0x02, 0x2B, 0xA9, 0xD1, 0x0D, 0x49, 0x0E, 0x48, 0x4F, 0xF4, 0x09, 0x72, ++0xF8, 0xF7, 0x0E, 0xFE, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE3, 0xF7, 0xF5, 0xFF, 0x05, 0x46, 0x00, 0x28, 0xA8, 0xD1, ++0xBD, 0xE8, 0xF0, 0x81, 0x03, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEF, 0xDA, 0xE8, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0xF8, 0xB5, 0x14, 0x4A, ++0x14, 0x4D, 0x41, 0xF2, 0x0A, 0x00, 0x41, 0xF2, 0x08, 0x07, 0x00, 0x26, 0x16, 0x52, 0x0C, 0x46, 0xD3, 0x53, 0x41, 0xF2, ++0x0C, 0x06, 0xD1, 0xF8, 0x64, 0x11, 0xD4, 0xF8, 0x60, 0x01, 0x90, 0x51, 0x0B, 0x2B, 0x14, 0x60, 0xA9, 0x80, 0x0D, 0xD0, ++0x19, 0x46, 0x04, 0x22, 0x02, 0x23, 0x41, 0xF2, 0x09, 0x00, 0xF6, 0xF7, 0xF5, 0xFC, 0x01, 0x22, 0x42, 0x70, 0x94, 0xF8, ++0x6E, 0x21, 0x02, 0x70, 0xF6, 0xF7, 0x1E, 0xFD, 0x04, 0x4B, 0xD3, 0xF8, 0xF4, 0x32, 0x98, 0x47, 0x01, 0x20, 0xF8, 0xBD, ++0xA8, 0xBA, 0x17, 0x00, 0xB4, 0xCA, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1A, 0x46, 0x70, 0xB5, 0x40, 0x23, 0x14, 0x4C, ++0x0D, 0x46, 0x41, 0xF2, 0x06, 0x00, 0x11, 0x46, 0x04, 0x22, 0xF6, 0xF7, 0xD7, 0xFC, 0xA3, 0x88, 0x06, 0x46, 0x13, 0xB1, ++0x2A, 0x78, 0x93, 0x42, 0x06, 0xD8, 0x00, 0x23, 0x30, 0x46, 0x33, 0x70, 0xF6, 0xF7, 0xFC, 0xFC, 0x00, 0x20, 0x70, 0xBD, ++0x04, 0xEB, 0x82, 0x14, 0x08, 0x34, 0x0F, 0xCC, 0x35, 0x46, 0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, ++0x94, 0xE8, 0x0F, 0x00, 0x85, 0xE8, 0x0F, 0x00, 0x30, 0x46, 0xF6, 0xF7, 0xE9, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, ++0xA8, 0xBA, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x22, 0x01, 0x23, 0x02, 0x21, 0x40, 0xF6, 0x03, 0x00, 0xF6, 0xF7, 0xAC, 0xFC, ++0xF6, 0xF7, 0xDA, 0xFC, 0x04, 0x20, 0xF6, 0xF7, 0x49, 0xFF, 0x03, 0x49, 0x02, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x5A, 0xFB, ++0x00, 0x20, 0x08, 0xBD, 0x6C, 0xBE, 0x15, 0x00, 0x08, 0xB5, 0x19, 0x46, 0x04, 0x22, 0x01, 0x23, 0x41, 0xF2, 0x0B, 0x00, ++0xF6, 0xF7, 0x96, 0xFC, 0xF6, 0xF7, 0xC4, 0xFC, 0x02, 0x49, 0x08, 0x20, 0xF8, 0xF7, 0x48, 0xFB, 0x00, 0x20, 0x08, 0xBD, ++0x80, 0xBE, 0x15, 0x00, 0x1A, 0x46, 0x38, 0xB5, 0x41, 0xF2, 0x08, 0x00, 0x0D, 0x46, 0x02, 0x23, 0x11, 0x46, 0x04, 0x22, ++0xF6, 0xF7, 0x82, 0xFC, 0x06, 0x49, 0x04, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x35, 0xFB, 0x01, 0x23, 0x23, 0x70, 0xAB, 0x78, ++0x63, 0x70, 0x20, 0x46, 0xF6, 0xF7, 0xA6, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0x98, 0xBE, 0x15, 0x00, 0x10, 0xB5, 0x41, 0xF2, ++0x08, 0x00, 0x04, 0x4C, 0x04, 0x49, 0x1A, 0x46, 0x23, 0x5A, 0x08, 0x20, 0xF8, 0xF7, 0x20, 0xFB, 0x02, 0x20, 0x10, 0xBD, ++0xA8, 0xBA, 0x17, 0x00, 0xB4, 0xBE, 0x15, 0x00, 0xF8, 0xB5, 0x36, 0x4C, 0x91, 0xF8, 0x6E, 0x21, 0x35, 0x4E, 0x21, 0x60, ++0x0D, 0x46, 0x41, 0xF2, 0x08, 0x00, 0x4F, 0xF4, 0xA4, 0x67, 0x41, 0xF2, 0x0A, 0x01, 0x07, 0xFB, 0x02, 0x62, 0x01, 0x26, ++0x23, 0x52, 0x66, 0x52, 0x00, 0x23, 0xC2, 0xF8, 0xCC, 0x31, 0x05, 0xF5, 0xB0, 0x77, 0x97, 0xE8, 0x03, 0x00, 0xDF, 0xF8, ++0xC4, 0xC0, 0x41, 0xF2, 0x0C, 0x02, 0xAC, 0xF8, 0x04, 0x10, 0x41, 0xF2, 0x3B, 0x01, 0xA0, 0x50, 0x63, 0x54, 0x38, 0x46, ++0x1A, 0x46, 0x19, 0x46, 0x00, 0xF0, 0x4A, 0xF9, 0x18, 0xB1, 0x90, 0xF8, 0x3D, 0x10, 0x03, 0x46, 0x91, 0xB9, 0x97, 0xE8, ++0x03, 0x00, 0x21, 0x4B, 0x41, 0xF2, 0x34, 0x02, 0x99, 0x80, 0x20, 0x4B, 0xA0, 0x50, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x28, 0xDB, 0x1D, 0x4B, 0xD3, 0xF8, 0xF4, 0x32, 0x98, 0x47, 0x01, 0x20, 0xF8, 0xBD, 0x02, 0x46, 0x41, 0xF2, ++0x34, 0x0C, 0x52, 0xF8, 0x02, 0x0F, 0x93, 0xF8, 0x3E, 0x70, 0x44, 0xF8, 0x0C, 0x00, 0x14, 0x48, 0x92, 0x88, 0x82, 0x80, ++0xBE, 0x40, 0x41, 0xF2, 0x38, 0x00, 0x01, 0x3E, 0x22, 0x5A, 0x36, 0x02, 0x36, 0xB2, 0x22, 0xEA, 0x06, 0x02, 0x12, 0xB2, ++0x22, 0x52, 0xDB, 0x88, 0xA3, 0xEB, 0x01, 0x21, 0x0E, 0x40, 0x0C, 0x4B, 0x16, 0x43, 0x26, 0x52, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xD6, 0xDA, 0x95, 0xF8, 0x60, 0x31, 0xDB, 0x07, 0xD2, 0xD5, 0x08, 0x49, 0x08, 0x48, 0xA1, 0x22, ++0xF8, 0xF7, 0xD8, 0xFC, 0xCC, 0xE7, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xDC, 0xCA, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD0, 0xBE, 0x15, 0x00, 0xB4, 0xCA, 0x17, 0x00, ++0x1A, 0x46, 0x38, 0xB5, 0x41, 0xF2, 0x08, 0x00, 0x0D, 0x46, 0x02, 0x23, 0x11, 0x46, 0x04, 0x22, 0xF6, 0xF7, 0xDA, 0xFB, ++0x0A, 0x49, 0x04, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x8D, 0xFA, 0x29, 0x46, 0x08, 0x48, 0x31, 0xF8, 0x03, 0x2B, 0x20, 0xF8, ++0x03, 0x2B, 0x0A, 0xF0, 0x55, 0xFF, 0x01, 0x23, 0x23, 0x70, 0xAB, 0x78, 0x63, 0x70, 0x20, 0x46, 0xF6, 0xF7, 0xF6, 0xFB, ++0x00, 0x20, 0x38, 0xBD, 0xF0, 0xBE, 0x15, 0x00, 0x68, 0xCB, 0x17, 0x00, 0x08, 0x78, 0x08, 0xB9, 0x00, 0x20, 0x70, 0x47, ++0x08, 0xB5, 0x00, 0xF0, 0x31, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x70, 0xB5, 0x0B, 0x4E, 0x41, 0xF2, 0x08, 0x05, ++0x01, 0x23, 0x0C, 0x46, 0x04, 0x22, 0x71, 0x5B, 0x41, 0xF2, 0x0B, 0x00, 0xF6, 0xF7, 0xAA, 0xFB, 0xF6, 0xF7, 0xD8, 0xFB, ++0x72, 0x5B, 0x05, 0x49, 0x08, 0x20, 0xF8, 0xF7, 0x5B, 0xFA, 0x20, 0x78, 0x00, 0xF0, 0x18, 0xF8, 0x00, 0x20, 0x70, 0xBD, ++0xA8, 0xBA, 0x17, 0x00, 0x00, 0xBF, 0x15, 0x00, 0x08, 0xB5, 0x05, 0x49, 0x41, 0xF2, 0x0B, 0x02, 0x8B, 0x5C, 0x01, 0x33, ++0x8B, 0x54, 0x00, 0xF0, 0x65, 0xFD, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x08, 0x46, 0x00, 0xF0, ++0x19, 0xB9, 0x00, 0xBF, 0xF0, 0xB5, 0x39, 0x4C, 0x41, 0xF2, 0x0A, 0x05, 0x83, 0xB0, 0x63, 0x5D, 0x06, 0x46, 0x00, 0x2B, ++0x43, 0xD0, 0x41, 0xF2, 0x08, 0x02, 0x03, 0x23, 0xA1, 0x5A, 0x41, 0xF2, 0x03, 0x00, 0x04, 0x22, 0xF6, 0xF7, 0x76, 0xFB, ++0x05, 0x46, 0x23, 0x68, 0x30, 0x49, 0x93, 0xF8, 0x6E, 0x21, 0x00, 0x96, 0x41, 0xF2, 0x0A, 0x07, 0x08, 0x20, 0xE3, 0x5D, ++0xF8, 0xF7, 0x22, 0xFA, 0xE3, 0x5D, 0x63, 0xB9, 0x2B, 0x49, 0x2C, 0x4A, 0x0B, 0x68, 0x2C, 0x48, 0x23, 0xF0, 0x04, 0x03, ++0x0B, 0x60, 0x13, 0x68, 0x01, 0x88, 0x1B, 0x0C, 0x1B, 0x04, 0x0B, 0x43, 0x13, 0x60, 0x20, 0x68, 0x27, 0x4B, 0x90, 0xF8, ++0x6E, 0x21, 0x2A, 0x70, 0x6E, 0x70, 0xA2, 0x88, 0xAA, 0x70, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x20, 0xD0, 0x0C, 0x38, ++0xF6, 0xF7, 0xC8, 0xFB, 0x00, 0x26, 0x28, 0x46, 0x26, 0x60, 0xF6, 0xF7, 0x77, 0xFB, 0x1F, 0x4A, 0x53, 0x68, 0x31, 0x46, ++0x23, 0xF0, 0x20, 0x03, 0x04, 0x20, 0x53, 0x60, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xF6, 0xF7, 0x35, 0xBD, 0xA3, 0x88, ++0xF3, 0xB1, 0x41, 0xF2, 0x08, 0x02, 0x03, 0x23, 0xA1, 0x5A, 0x41, 0xF2, 0x01, 0x00, 0x04, 0x22, 0xF6, 0xF7, 0x30, 0xFB, ++0x05, 0x46, 0xB8, 0xE7, 0x13, 0x4B, 0x93, 0xF8, 0xB5, 0x30, 0x00, 0x2B, 0xD9, 0xD0, 0x12, 0x49, 0x12, 0x4B, 0x0A, 0x68, ++0x22, 0xF0, 0x7C, 0x72, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x12, ++0x1A, 0x60, 0xCA, 0xE7, 0xD6, 0xF7, 0xCC, 0xFB, 0x63, 0x5D, 0x00, 0x2B, 0xDB, 0xD0, 0x94, 0xE7, 0xA8, 0xBA, 0x17, 0x00, ++0x30, 0xBF, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x20, 0x04, 0x32, 0x40, 0x28, 0x25, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, ++0x1C, 0x9E, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x00, 0x32, 0x40, 0x6C, 0x00, 0x32, 0x40, 0x08, 0xB5, 0x00, 0x21, ++0x04, 0x20, 0xF6, 0xF7, 0xF5, 0xFC, 0xBD, 0xE8, 0x08, 0x40, 0x03, 0x48, 0x4F, 0xF4, 0x86, 0x52, 0x00, 0x21, 0xD3, 0xF7, ++0xED, 0xBE, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x3C, 0x4D, 0x83, 0xB0, 0xA8, 0x46, 0x2B, 0x46, ++0x00, 0x22, 0x08, 0xE0, 0x5F, 0x89, 0x04, 0x88, 0xA7, 0x42, 0x14, 0xD0, 0x01, 0x32, 0x40, 0x2A, 0x03, 0xF1, 0x40, 0x03, ++0x1C, 0xD0, 0x1C, 0x7A, 0x03, 0xF1, 0x08, 0x06, 0x00, 0x2C, 0xF1, 0xD1, 0x00, 0x29, 0xF3, 0xD0, 0x08, 0xEB, 0x82, 0x12, ++0x80, 0x23, 0x82, 0xF8, 0x44, 0x30, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x9F, 0x89, 0x44, 0x88, 0xA7, 0x42, ++0xE6, 0xD1, 0xDF, 0x89, 0x84, 0x88, 0xA7, 0x42, 0xF3, 0xD0, 0x01, 0x32, 0x40, 0x2A, 0x03, 0xF1, 0x40, 0x03, 0xE2, 0xD1, ++0x00, 0x29, 0x46, 0xD0, 0x26, 0x4F, 0x4F, 0xF0, 0x00, 0x0B, 0x4F, 0xF0, 0x21, 0x0A, 0x06, 0xE0, 0x0B, 0xF1, 0x01, 0x0B, ++0xBB, 0xF1, 0x40, 0x0F, 0x05, 0xF1, 0x40, 0x05, 0x39, 0xD0, 0x2B, 0x7A, 0x05, 0xF1, 0x08, 0x06, 0x00, 0x2B, 0xF3, 0xD0, ++0x95, 0xF8, 0x45, 0x40, 0x00, 0x2C, 0xEF, 0xD1, 0x38, 0x68, 0x30, 0xB3, 0x90, 0xF8, 0x70, 0x31, 0x1B, 0xB3, 0x05, 0xF1, ++0x11, 0x01, 0x4F, 0xF0, 0xFD, 0x09, 0x06, 0xE0, 0x38, 0x68, 0x01, 0x34, 0x90, 0xF8, 0x70, 0x31, 0xE4, 0xB2, 0xA3, 0x42, ++0x15, 0xD9, 0x04, 0xEB, 0x44, 0x13, 0x03, 0x44, 0x93, 0xF8, 0xFC, 0x30, 0x00, 0x2B, 0xF1, 0xD0, 0x2A, 0x7C, 0x9A, 0x42, ++0xEE, 0xD1, 0x1A, 0xFB, 0x04, 0x93, 0x18, 0x44, 0x01, 0x91, 0x0A, 0xF0, 0xE1, 0xFD, 0x01, 0x99, 0x00, 0x28, 0xE5, 0xD1, ++0x3B, 0x68, 0x93, 0xF8, 0x70, 0x31, 0x9C, 0x42, 0xC6, 0xD1, 0x08, 0xEB, 0x8B, 0x11, 0x80, 0x20, 0x00, 0x23, 0x81, 0xF8, ++0x44, 0x00, 0x0B, 0x72, 0xA5, 0xE7, 0x00, 0x26, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA8, 0xBA, 0x17, 0x00, ++0xF4, 0x9F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, 0x61, 0x4B, 0x99, 0xB0, 0x1C, 0x68, 0x03, 0x46, ++0x04, 0x93, 0x04, 0x20, 0x94, 0xF8, 0x6E, 0x31, 0x07, 0x93, 0xF6, 0xF7, 0x03, 0xFD, 0x01, 0x28, 0x05, 0xD0, 0x00, 0x20, ++0x19, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x58, 0x49, 0x41, 0xF2, 0x0C, 0x03, 0xCA, 0x5C, 0xD2, 0x07, ++0x19, 0xD4, 0xCA, 0x5A, 0x04, 0x9B, 0x9B, 0x8B, 0x9A, 0x42, 0x00, 0xF0, 0x85, 0x80, 0x52, 0x49, 0x41, 0xF2, 0x34, 0x02, ++0x8A, 0x5A, 0x9A, 0x42, 0xE7, 0xD1, 0x04, 0x9A, 0x41, 0xF2, 0x36, 0x03, 0xD2, 0x8B, 0xCB, 0x5A, 0x9A, 0x42, 0xE0, 0xD1, ++0x04, 0x9A, 0x41, 0xF2, 0x38, 0x03, 0x12, 0x8C, 0xCB, 0x5A, 0x9A, 0x42, 0xD9, 0xD1, 0x04, 0x98, 0x30, 0xF8, 0x30, 0x3B, ++0x0B, 0x90, 0x24, 0x3B, 0x9B, 0xB2, 0x0D, 0xF1, 0x37, 0x02, 0x19, 0x46, 0x08, 0xEE, 0x10, 0x3A, 0xF7, 0xF7, 0xE4, 0xF8, ++0x00, 0x28, 0x73, 0xD0, 0x9D, 0xF8, 0x37, 0x60, 0x10, 0xAD, 0x4E, 0xB1, 0xAF, 0x19, 0x2B, 0x46, 0xC5, 0xF1, 0x02, 0x01, ++0xC2, 0x18, 0x52, 0x5C, 0x03, 0xF8, 0x01, 0x2B, 0xBB, 0x42, 0xF9, 0xD1, 0x04, 0x9F, 0x38, 0x46, 0x01, 0x21, 0x2B, 0x46, ++0x32, 0x46, 0x1C, 0x30, 0xFF, 0xF7, 0x24, 0xFF, 0x01, 0x46, 0x0A, 0x90, 0x00, 0x28, 0xB0, 0xD0, 0xBB, 0x8B, 0x43, 0x80, ++0xFB, 0x8B, 0x83, 0x80, 0x3B, 0x8C, 0xC3, 0x80, 0x97, 0xF8, 0x2C, 0x30, 0x97, 0xF8, 0x2D, 0x20, 0x43, 0xEA, 0x02, 0x23, ++0x03, 0x86, 0xFB, 0x8D, 0x43, 0x86, 0x03, 0xF0, 0x01, 0x03, 0xC3, 0xF1, 0x02, 0x03, 0x43, 0x85, 0x00, 0x2E, 0x46, 0xD1, ++0x0A, 0x9B, 0x1E, 0x72, 0x27, 0x4A, 0x41, 0xF2, 0x3A, 0x03, 0xD3, 0x5C, 0x00, 0x2B, 0x40, 0xF0, 0xA5, 0x82, 0x24, 0x4A, ++0x41, 0xF2, 0x0A, 0x03, 0xD5, 0x5C, 0x00, 0x2D, 0x48, 0xD1, 0x94, 0xF8, 0x70, 0x11, 0x00, 0x29, 0x44, 0xD0, 0x0A, 0x9B, ++0x26, 0x46, 0x03, 0xF1, 0x09, 0x07, 0x98, 0x46, 0x08, 0x46, 0x05, 0xE0, 0x01, 0x35, 0xA8, 0x42, 0x06, 0xF1, 0x21, 0x06, ++0x03, 0x46, 0x34, 0xDD, 0x96, 0xF8, 0xFC, 0x30, 0x83, 0xB3, 0x98, 0xF8, 0x08, 0x20, 0x9A, 0x42, 0xF2, 0xD1, 0x39, 0x46, ++0x06, 0xF1, 0xFD, 0x00, 0x0A, 0xF0, 0x26, 0xFD, 0x00, 0x28, 0x00, 0xF0, 0x2C, 0x83, 0x94, 0xF8, 0x70, 0x01, 0xE7, 0xE7, ++0x04, 0x99, 0x0F, 0x48, 0xC9, 0x8B, 0x41, 0xF2, 0x0E, 0x02, 0x82, 0x5A, 0x91, 0x42, 0x7F, 0xF4, 0x72, 0xAF, 0x04, 0x99, ++0x41, 0xF2, 0x10, 0x02, 0x09, 0x8C, 0x82, 0x5A, 0x91, 0x42, 0x7F, 0xF4, 0x6A, 0xAF, 0x7C, 0xE7, 0x06, 0x46, 0x10, 0xAD, ++0x96, 0xE7, 0x0B, 0x46, 0x03, 0xF8, 0x08, 0x6F, 0x2E, 0x44, 0x15, 0xF8, 0x01, 0x2B, 0x03, 0xF8, 0x01, 0x2F, 0xAE, 0x42, ++0xF9, 0xD1, 0xAF, 0xE7, 0xA8, 0xBA, 0x17, 0x00, 0x03, 0x46, 0x9D, 0x42, 0x3F, 0xF4, 0x43, 0xAF, 0x18, 0xEE, 0x10, 0x1A, ++0x0B, 0x98, 0xF7, 0xF7, 0x45, 0xF9, 0x00, 0x28, 0x00, 0xF0, 0x3A, 0x82, 0x04, 0x9B, 0x9A, 0x79, 0x83, 0x78, 0x00, 0x2A, ++0x40, 0xF0, 0x56, 0x82, 0x59, 0x1E, 0x0D, 0x29, 0x00, 0xF2, 0x4F, 0x82, 0x0E, 0x2B, 0x00, 0xF0, 0xEB, 0x82, 0x03, 0xEB, ++0x83, 0x03, 0x03, 0xF6, 0x67, 0x11, 0x10, 0x46, 0xFA, 0xF7, 0x98, 0xFE, 0x0A, 0x99, 0x04, 0x9B, 0xC8, 0x62, 0x91, 0xF9, ++0x3C, 0x20, 0x93, 0xF9, 0x09, 0x30, 0x9A, 0x42, 0xB8, 0xBF, 0x81, 0xF8, 0x3C, 0x30, 0x04, 0x99, 0x03, 0x88, 0x8A, 0x88, ++0x9A, 0x42, 0x00, 0xD0, 0x8B, 0x80, 0x41, 0xF2, 0xBD, 0x03, 0xB4, 0x4A, 0x00, 0x25, 0xD5, 0x54, 0x18, 0xEE, 0x10, 0x3A, ++0x00, 0x2B, 0x6C, 0xD0, 0x0B, 0x9B, 0x8D, 0xED, 0x05, 0x8A, 0x2C, 0x46, 0xA8, 0x46, 0x06, 0x93, 0xDD, 0xE9, 0x05, 0x10, ++0xF7, 0xF7, 0xFC, 0xF9, 0x08, 0x90, 0x00, 0x28, 0x5F, 0xD0, 0x43, 0x78, 0xAA, 0x4A, 0x81, 0x78, 0x11, 0x70, 0x5E, 0x1E, ++0x02, 0x33, 0xB6, 0xB2, 0x09, 0x93, 0x00, 0xF1, 0x03, 0x0A, 0x00, 0x2E, 0x44, 0xD0, 0x31, 0x46, 0x50, 0x46, 0xF7, 0xF7, ++0x09, 0xFA, 0x07, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0x90, 0xF8, 0x01, 0x90, 0x00, 0xF1, 0x02, 0x0B, 0x09, 0xF1, 0x02, 0x03, ++0xF6, 0x1A, 0x58, 0x46, 0x04, 0x21, 0xB6, 0xB2, 0x9A, 0x44, 0xF7, 0xF7, 0x1D, 0xFA, 0x00, 0x28, 0x00, 0xF0, 0x81, 0x81, ++0x49, 0x46, 0x58, 0x46, 0xF7, 0xF7, 0x36, 0xFA, 0x07, 0xF1, 0x04, 0x08, 0x04, 0x46, 0x49, 0x46, 0x58, 0x46, 0x0E, 0xAA, ++0xF6, 0xF7, 0xE8, 0xFF, 0x05, 0x46, 0x00, 0x2C, 0xD7, 0xD0, 0x00, 0x2D, 0xD5, 0xD0, 0x92, 0x4B, 0x98, 0xF8, 0x00, 0xC0, ++0x1A, 0x78, 0xA7, 0x78, 0xA3, 0xF1, 0x81, 0x00, 0x81, 0x1D, 0x98, 0xF8, 0x01, 0x30, 0x01, 0xF8, 0x32, 0x70, 0x4C, 0xEA, ++0x03, 0x21, 0x53, 0x1C, 0xDB, 0xB2, 0x07, 0x1D, 0x10, 0x2B, 0x40, 0xF8, 0x32, 0x50, 0x80, 0xF8, 0x81, 0x30, 0x27, 0xF8, ++0x32, 0x10, 0x12, 0xD0, 0x4F, 0xF0, 0x00, 0x08, 0x00, 0x2E, 0xBA, 0xD1, 0x06, 0x9B, 0x08, 0x9A, 0x05, 0x99, 0x9B, 0x1A, ++0x19, 0x44, 0x09, 0x9B, 0xA1, 0xEB, 0x03, 0x0B, 0x1F, 0xFA, 0x8B, 0xF1, 0xD3, 0x18, 0x05, 0x91, 0x06, 0x93, 0x00, 0x29, ++0x98, 0xD1, 0x0A, 0x99, 0x00, 0x23, 0x4B, 0x63, 0x8B, 0x63, 0x41, 0xF2, 0x0A, 0x02, 0x77, 0x4B, 0x9B, 0x5C, 0x00, 0x2B, ++0x00, 0xF0, 0xB4, 0x80, 0x0A, 0x9A, 0x07, 0x9F, 0x76, 0x4C, 0x56, 0x8D, 0x51, 0x8E, 0x13, 0x46, 0x4F, 0xF4, 0xA4, 0x65, ++0x53, 0xF8, 0x02, 0x0F, 0x12, 0x8E, 0x9B, 0x88, 0x05, 0xFB, 0x07, 0xF5, 0x67, 0x19, 0xA7, 0xF8, 0x68, 0x31, 0xA7, 0xF8, ++0x98, 0x21, 0xFF, 0x23, 0x0A, 0x9A, 0xA7, 0xF8, 0x8E, 0x61, 0xC7, 0xF8, 0x64, 0x01, 0xA7, 0xF8, 0x9A, 0x11, 0x87, 0xF8, ++0x61, 0x31, 0x87, 0xF8, 0xBE, 0x31, 0x13, 0x7A, 0x05, 0xF1, 0xEC, 0x06, 0x26, 0x44, 0x00, 0x2B, 0x40, 0xF0, 0xA2, 0x81, ++0x0A, 0x9A, 0xD2, 0x6A, 0xC7, 0xF8, 0x90, 0x21, 0xA7, 0xF8, 0xC2, 0x31, 0x07, 0x9B, 0x0A, 0x9A, 0x0B, 0x98, 0x4F, 0xF4, ++0xA4, 0x67, 0x07, 0xFB, 0x03, 0x47, 0x92, 0xF8, 0x3D, 0x30, 0x87, 0xF8, 0x8B, 0x31, 0x92, 0xF8, 0x3E, 0x30, 0x87, 0xF8, ++0x8C, 0x31, 0x05, 0xF5, 0xCE, 0x78, 0x00, 0x23, 0xA0, 0x44, 0xC7, 0xF8, 0xCC, 0x31, 0x18, 0xEE, 0x10, 0x1A, 0x42, 0x46, ++0xF9, 0xF7, 0xA4, 0xFB, 0x0A, 0x9B, 0xDB, 0x6A, 0x9B, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0xB3, 0x81, 0x05, 0xF5, 0xD6, 0x72, ++0x18, 0xEE, 0x10, 0x1A, 0x0B, 0x98, 0x22, 0x44, 0x0E, 0xAB, 0xF9, 0xF7, 0x6D, 0xFD, 0x80, 0xB1, 0x07, 0x9A, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, 0xB3, 0xF8, 0x9A, 0x11, 0xD3, 0xF8, 0xCC, 0x21, 0x41, 0xF4, 0x00, 0x71, 0x42, 0xF0, ++0x01, 0x02, 0xA3, 0xF8, 0x9A, 0x11, 0xC3, 0xF8, 0xCC, 0x21, 0x45, 0x4F, 0x97, 0xF8, 0x76, 0x31, 0xDB, 0x07, 0x09, 0xD5, ++0x07, 0x9B, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x03, 0x49, 0xD9, 0xF8, 0xCC, 0x31, 0xD8, 0x07, 0x00, 0xF1, 0x98, 0x81, ++0x00, 0x21, 0x88, 0x46, 0x40, 0x46, 0x32, 0x46, 0xFB, 0xF7, 0x52, 0xFA, 0x0B, 0x9D, 0x18, 0xEE, 0x10, 0x1A, 0x28, 0x46, ++0x32, 0x46, 0xF9, 0xF7, 0xAD, 0xFB, 0x28, 0x46, 0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, 0xF9, 0xF7, 0xB1, 0xFB, 0x28, 0x46, ++0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, 0xF9, 0xF7, 0x13, 0xFC, 0x07, 0x9A, 0x31, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, ++0x02, 0x44, 0x29, 0x6D, 0xD4, 0xF8, 0xCC, 0x31, 0x43, 0xF0, 0x00, 0x43, 0x41, 0xF2, 0x3B, 0x02, 0xC4, 0xF8, 0xCC, 0x31, ++0x25, 0x4B, 0x01, 0x20, 0x98, 0x54, 0x2A, 0x6A, 0x00, 0x29, 0x00, 0xF0, 0x1C, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x19, 0x81, ++0x0B, 0x7E, 0x03, 0x2B, 0x08, 0xD1, 0x25, 0x4B, 0x05, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xD5, 0xE9, ++0x11, 0x30, 0x98, 0x47, 0x0A, 0x9A, 0x14, 0x78, 0xDC, 0xB9, 0x19, 0x48, 0x1F, 0x4B, 0x81, 0x88, 0x1B, 0x68, 0x01, 0x31, ++0x89, 0xB2, 0x81, 0x80, 0x1B, 0x88, 0x5B, 0x07, 0x11, 0xD5, 0x13, 0x7A, 0x00, 0x2B, 0x40, 0xF0, 0x7A, 0x81, 0x1A, 0x4D, ++0x0A, 0x9A, 0x04, 0x9C, 0xD2, 0x6A, 0x94, 0xF9, 0x09, 0x00, 0x12, 0x88, 0x00, 0x90, 0xCD, 0xE9, 0x01, 0x35, 0x16, 0x48, ++0x23, 0x7B, 0xF7, 0xF7, 0x89, 0xFE, 0x0A, 0x99, 0x00, 0x25, 0x01, 0x22, 0x0A, 0x70, 0x81, 0xF8, 0x3D, 0x50, 0x81, 0xF8, ++0x3E, 0x50, 0x41, 0xF2, 0xBD, 0x03, 0x08, 0x46, 0x05, 0x49, 0xCB, 0x5C, 0x00, 0x2B, 0x4D, 0xD0, 0x0D, 0x4C, 0x83, 0x46, ++0x04, 0xF1, 0x80, 0x0A, 0x04, 0xF1, 0x81, 0x09, 0x43, 0xE0, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x64, 0xCB, 0x17, 0x00, ++0x65, 0xCB, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x48, 0xBF, 0x15, 0x00, 0x84, 0xBF, 0x15, 0x00, 0xE4, 0xCA, 0x17, 0x00, 0x9A, 0xF8, 0x00, 0x70, ++0x08, 0x2F, 0x2B, 0xD8, 0x5A, 0x46, 0x21, 0x68, 0x52, 0xF8, 0x02, 0x0F, 0x4E, 0x78, 0x0E, 0x90, 0x92, 0x88, 0xAD, 0xF8, ++0x3C, 0x20, 0xBB, 0xF8, 0x06, 0x20, 0xBD, 0xF9, 0x3C, 0x10, 0x4F, 0xF0, 0x01, 0x08, 0x02, 0xEB, 0x03, 0x22, 0x08, 0xFA, ++0x07, 0xF3, 0x4A, 0x40, 0x01, 0x3B, 0x02, 0xEA, 0x03, 0x22, 0x00, 0x23, 0x81, 0xEA, 0x02, 0x0C, 0x0E, 0xA8, 0x1A, 0x46, ++0x19, 0x46, 0xAD, 0xF8, 0x3C, 0xC0, 0xFF, 0xF7, 0xDF, 0xFC, 0x68, 0xB3, 0x99, 0xF8, 0x00, 0x30, 0x01, 0x35, 0x9D, 0x42, ++0x04, 0xF1, 0x08, 0x04, 0x02, 0xDA, 0xA3, 0x79, 0x00, 0x2B, 0xCF, 0xD1, 0x04, 0x98, 0x04, 0x23, 0x0C, 0x22, 0x41, 0xF2, ++0x04, 0x01, 0xF6, 0xF7, 0x2D, 0xF8, 0x01, 0x20, 0x5C, 0xE5, 0xB8, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x62, 0xAE, 0x4C, 0xB1, ++0x00, 0x2D, 0x7F, 0xF4, 0x88, 0xAE, 0x49, 0x46, 0x58, 0x46, 0x0E, 0xAA, 0xF6, 0xF7, 0x66, 0xFE, 0x05, 0x46, 0x7E, 0xE6, ++0x49, 0x46, 0x58, 0x46, 0xF7, 0xF7, 0xA6, 0xF8, 0x04, 0x46, 0x00, 0x2D, 0x3F, 0xF4, 0x6F, 0xAE, 0x00, 0x28, 0x3F, 0xF4, ++0x4C, 0xAE, 0x74, 0xE6, 0x23, 0x68, 0x41, 0x46, 0x02, 0x33, 0x32, 0x46, 0x0E, 0xA8, 0xFF, 0xF7, 0xA9, 0xFC, 0x86, 0x46, ++0x00, 0x28, 0xD1, 0xD0, 0xD8, 0x46, 0xB8, 0xE8, 0x0F, 0x00, 0xF4, 0x46, 0xAC, 0xE8, 0x0F, 0x00, 0xB8, 0xE8, 0x0F, 0x00, ++0xAC, 0xE8, 0x0F, 0x00, 0xB8, 0xE8, 0x0F, 0x00, 0xAC, 0xE8, 0x0F, 0x00, 0x98, 0xE8, 0x0F, 0x00, 0x8C, 0xE8, 0x0F, 0x00, ++0x0E, 0x98, 0xCE, 0xF8, 0x02, 0x00, 0xBD, 0xF8, 0x3C, 0x30, 0x8E, 0xF8, 0x08, 0x60, 0x21, 0x68, 0xAE, 0xF8, 0x06, 0x30, ++0x5E, 0xB1, 0x08, 0x36, 0x06, 0x39, 0x76, 0x44, 0xA1, 0xEB, 0x0E, 0x01, 0x0E, 0xF1, 0x08, 0x03, 0xCA, 0x5C, 0x03, 0xF8, ++0x01, 0x2F, 0x9E, 0x42, 0xFA, 0xD1, 0x7E, 0x49, 0x8E, 0xF8, 0x3E, 0x70, 0x8B, 0x88, 0xA2, 0x79, 0x8E, 0xF8, 0x3D, 0x20, ++0x01, 0x33, 0x01, 0x22, 0x8B, 0x80, 0x8E, 0xF8, 0x00, 0x20, 0x91, 0xE7, 0x04, 0x9B, 0x93, 0xF9, 0x09, 0x20, 0x0A, 0x9B, ++0x93, 0xF9, 0x3C, 0x30, 0x9A, 0x42, 0x7F, 0xF7, 0xE2, 0xAD, 0x04, 0x9C, 0xA1, 0x88, 0xA0, 0x79, 0xFA, 0xF7, 0x64, 0xFC, ++0x0A, 0x9A, 0xD0, 0x62, 0x63, 0x7A, 0x82, 0xF8, 0x3C, 0x30, 0xD6, 0xE5, 0x0A, 0x9B, 0x6E, 0x49, 0x07, 0x22, 0x03, 0xF1, ++0x09, 0x00, 0x0A, 0xF0, 0x9D, 0xFA, 0x00, 0x28, 0x7F, 0xF4, 0xE3, 0xAC, 0x9E, 0xE5, 0x4F, 0xF6, 0xFF, 0x71, 0xB4, 0xE5, ++0x01, 0x2A, 0xFA, 0xD1, 0x59, 0x1E, 0xA4, 0x29, 0xF7, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x51, 0x08, 0x31, ++0xA9, 0xE5, 0xB2, 0xFA, 0x82, 0xF2, 0x62, 0x48, 0x52, 0x09, 0xF7, 0xF7, 0x95, 0xFD, 0xEB, 0xE6, 0x02, 0xF1, 0x09, 0x00, ++0x0A, 0xF0, 0xAC, 0xFC, 0xA8, 0xB1, 0x0A, 0x9B, 0x07, 0xF5, 0xB5, 0x77, 0x03, 0xF1, 0x08, 0x08, 0x03, 0xF1, 0x28, 0x0E, ++0xC4, 0x46, 0xBC, 0xE8, 0x0F, 0x00, 0xF4, 0x45, 0x38, 0x60, 0x79, 0x60, 0xBA, 0x60, 0xFB, 0x60, 0xE0, 0x46, 0x07, 0xF1, ++0x10, 0x07, 0xF3, 0xD1, 0x9C, 0xF8, 0x00, 0x30, 0x3B, 0x70, 0x0A, 0x9B, 0x07, 0x98, 0x19, 0x7A, 0x0A, 0x9B, 0xDA, 0x6A, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x43, 0x00, 0x27, 0xC3, 0xF8, 0x90, 0x21, 0xA3, 0xF8, 0xC2, 0x71, 0x00, 0x29, ++0x3F, 0xF4, 0x38, 0xAE, 0x0B, 0x44, 0x05, 0xF2, 0x6B, 0x11, 0x12, 0x88, 0x48, 0x48, 0x83, 0xF8, 0x6B, 0x71, 0x21, 0x44, ++0xF7, 0xF7, 0x5E, 0xFD, 0x2C, 0xE6, 0x40, 0x46, 0x01, 0x21, 0xFA, 0xF7, 0xED, 0xFD, 0x10, 0xF0, 0x0F, 0x00, 0x1A, 0xBF, ++0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x1F, 0x03, 0x01, 0x23, 0x87, 0xF8, 0xC1, 0x31, 0x3D, 0xE6, 0x18, 0xEE, 0x10, 0x1A, ++0x0B, 0x98, 0x32, 0x46, 0xF9, 0xF7, 0x0C, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x5F, 0xAE, 0xD9, 0xF8, 0xCC, 0x31, 0x0B, 0x98, ++0x43, 0xF0, 0x02, 0x03, 0x18, 0xEE, 0x10, 0x1A, 0xC9, 0xF8, 0xCC, 0x31, 0xF7, 0xF7, 0x24, 0xF8, 0x97, 0xF8, 0x76, 0x31, ++0x59, 0x07, 0x80, 0x46, 0x30, 0xD4, 0x9A, 0x07, 0x0A, 0xD4, 0x07, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, ++0xD3, 0xF8, 0xCC, 0x11, 0x11, 0xF0, 0x08, 0x01, 0x3F, 0xF4, 0x44, 0xAE, 0x05, 0xF5, 0x86, 0x72, 0x18, 0xEE, 0x10, 0x1A, ++0x0B, 0x98, 0x22, 0x44, 0xF9, 0xF7, 0x08, 0xFC, 0x30, 0xBB, 0x01, 0x46, 0x38, 0xE6, 0x02, 0xF1, 0x09, 0x05, 0x28, 0x46, ++0x16, 0x46, 0x0A, 0xF0, 0x33, 0xFC, 0x20, 0xB9, 0x1E, 0x4B, 0x22, 0x4D, 0x99, 0x88, 0x33, 0x7A, 0x7A, 0xE6, 0x0A, 0x9A, ++0x1B, 0x49, 0x13, 0x7A, 0x89, 0x88, 0x1A, 0x44, 0x54, 0x72, 0x73, 0xE6, 0x40, 0xF6, 0xB4, 0x11, 0x15, 0xE5, 0x94, 0xF8, ++0x70, 0x31, 0xF6, 0xE4, 0x05, 0xF5, 0x8C, 0x72, 0x18, 0xEE, 0x10, 0x1A, 0x0B, 0x98, 0x22, 0x44, 0xF9, 0xF7, 0x02, 0xFC, ++0xA0, 0xB9, 0x97, 0xF8, 0x76, 0x31, 0xC2, 0xE7, 0x07, 0x9A, 0x0B, 0x98, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, ++0x18, 0xEE, 0x10, 0x1A, 0xD3, 0xF8, 0xCC, 0x21, 0x42, 0xF0, 0x04, 0x02, 0xC3, 0xF8, 0xCC, 0x21, 0xF6, 0xF7, 0xF2, 0xFF, ++0x01, 0x46, 0x01, 0xE6, 0xD9, 0xF8, 0xCC, 0x31, 0x0B, 0x98, 0x43, 0xF0, 0x08, 0x03, 0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, ++0xC9, 0xF8, 0xCC, 0x31, 0xF9, 0xF7, 0x36, 0xFC, 0xDD, 0xE7, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x54, 0xBF, 0x15, 0x00, ++0x68, 0xBF, 0x15, 0x00, 0x5C, 0xBF, 0x15, 0x00, 0x48, 0xBF, 0x15, 0x00, 0x00, 0x23, 0x1A, 0x46, 0x19, 0x46, 0xFF, 0xF7, ++0x71, 0xBB, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0x03, 0x78, 0x43, 0xB3, 0x16, 0x4C, 0x07, 0x46, 0x4F, 0xF0, 0x00, 0x08, ++0x04, 0xF5, 0x80, 0x56, 0x6F, 0xF0, 0x7F, 0x05, 0x00, 0xF1, 0x01, 0x09, 0x02, 0xE0, 0x40, 0x34, 0xB4, 0x42, 0x17, 0xD0, ++0x23, 0x7A, 0xAB, 0xB1, 0x94, 0xF9, 0x44, 0x30, 0xAB, 0x42, 0xF6, 0xDD, 0x23, 0x7C, 0x3A, 0x78, 0x9A, 0x42, 0xF2, 0xD1, ++0x49, 0x46, 0x04, 0xF1, 0x11, 0x00, 0x0A, 0xF0, 0x97, 0xF9, 0x00, 0x28, 0xEB, 0xD1, 0x94, 0xF9, 0x44, 0x50, 0x04, 0xF1, ++0x08, 0x08, 0x40, 0x34, 0xB4, 0x42, 0xE7, 0xD1, 0x40, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x98, 0x46, 0x40, 0x46, 0xBD, 0xE8, ++0xF8, 0x83, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x41, 0xF2, 0x0B, 0x03, 0xC2, 0x4D, 0xE9, 0x5C, ++0x2E, 0x68, 0x01, 0x29, 0x82, 0xB0, 0x00, 0xF2, 0xB8, 0x81, 0x96, 0xF8, 0x6F, 0x01, 0x00, 0x27, 0x00, 0x28, 0x00, 0xF0, ++0x57, 0x81, 0x33, 0x46, 0x00, 0x24, 0x03, 0xE0, 0x01, 0x34, 0x84, 0x42, 0x00, 0xF0, 0x50, 0x81, 0x9A, 0x78, 0x8A, 0x42, ++0x03, 0xF1, 0x06, 0x03, 0xF6, 0xD1, 0x17, 0xB1, 0x41, 0xF2, 0x0B, 0x03, 0xE9, 0x54, 0x4F, 0xF4, 0xBA, 0x73, 0x02, 0x21, ++0x04, 0x22, 0x4F, 0xF4, 0x00, 0x60, 0xF5, 0xF7, 0x03, 0xFE, 0x96, 0xF8, 0x6E, 0x31, 0x80, 0xF8, 0x6E, 0x31, 0x07, 0x46, ++0xD6, 0xE9, 0x58, 0x01, 0xC7, 0xF8, 0x60, 0x01, 0xA7, 0xF8, 0x64, 0x11, 0x96, 0xF8, 0x70, 0x01, 0x87, 0xF8, 0x70, 0x01, ++0x96, 0xF8, 0x71, 0x31, 0x87, 0xF8, 0x71, 0x31, 0x96, 0xF8, 0x6F, 0x31, 0x9C, 0x42, 0x80, 0xF2, 0x79, 0x81, 0x41, 0xF2, ++0x0B, 0x02, 0x04, 0xEB, 0x44, 0x04, 0x06, 0x21, 0x15, 0xF8, 0x02, 0x80, 0x06, 0xEB, 0x44, 0x04, 0x11, 0xFB, 0x03, 0x61, ++0xA3, 0x78, 0x43, 0x45, 0x10, 0xD1, 0x97, 0xF8, 0x6F, 0x31, 0xD4, 0xF8, 0x00, 0xC0, 0x03, 0xEB, 0x43, 0x02, 0x01, 0x33, ++0x47, 0xF8, 0x12, 0xC0, 0x07, 0xEB, 0x42, 0x02, 0xB4, 0xF8, 0x04, 0xC0, 0xA2, 0xF8, 0x04, 0xC0, 0x87, 0xF8, 0x6F, 0x31, ++0x06, 0x34, 0xA1, 0x42, 0xE8, 0xD1, 0xF0, 0xB1, 0x4F, 0xF0, 0x21, 0x0A, 0xFC, 0x21, 0x1A, 0xFB, 0x00, 0x1A, 0x73, 0x18, ++0x03, 0xF1, 0x20, 0x09, 0x7A, 0x18, 0xD3, 0xF8, 0x00, 0xC0, 0x5C, 0x68, 0x98, 0x68, 0xD3, 0xF8, 0x0C, 0xE0, 0xC2, 0xF8, ++0x0C, 0xE0, 0x10, 0x33, 0x4B, 0x45, 0xC2, 0xF8, 0x00, 0xC0, 0x54, 0x60, 0x90, 0x60, 0x02, 0xF1, 0x10, 0x02, 0xEE, 0xD1, ++0x21, 0x31, 0x1B, 0x78, 0x13, 0x70, 0x51, 0x45, 0xE5, 0xD1, 0x2B, 0x68, 0xDF, 0xF8, 0x2C, 0xC2, 0xB3, 0xF8, 0x6C, 0x91, ++0x81, 0x4C, 0xB9, 0xF1, 0xC9, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, 0x00, 0x09, 0xB8, 0xF1, 0x01, 0x0F, 0x66, 0x46, 0x00, 0xF0, ++0xE5, 0x80, 0x93, 0xF8, 0x71, 0x21, 0x7C, 0x4B, 0x00, 0x2A, 0xA3, 0xF1, 0x04, 0x02, 0x0A, 0xBF, 0x13, 0x46, 0x4F, 0xF0, ++0x08, 0x0E, 0x4F, 0xF0, 0x0C, 0x0E, 0x78, 0x4A, 0x01, 0x20, 0x08, 0x21, 0x10, 0x75, 0x15, 0x32, 0x61, 0x70, 0x58, 0x18, ++0x13, 0xF8, 0x01, 0x1B, 0x02, 0xF8, 0x01, 0x1F, 0x98, 0x42, 0xF9, 0xD1, 0x72, 0x4B, 0x01, 0x93, 0xB9, 0xF1, 0x00, 0x0F, ++0x40, 0xF0, 0x99, 0x80, 0xBE, 0xF1, 0x08, 0x0F, 0x19, 0xD0, 0x01, 0x9B, 0x6E, 0x4A, 0x58, 0x1C, 0x32, 0x21, 0x01, 0x90, ++0x19, 0x70, 0x01, 0x9B, 0xAE, 0xF1, 0x08, 0x0E, 0x59, 0x1C, 0x5F, 0xFA, 0x8E, 0xFE, 0x01, 0x91, 0x83, 0xF8, 0x00, 0xE0, ++0x01, 0x9B, 0x18, 0x1D, 0x12, 0xF8, 0x01, 0x1B, 0x03, 0xF8, 0x01, 0x1B, 0x98, 0x42, 0xF9, 0xD1, 0x01, 0x9B, 0x73, 0x44, ++0x01, 0x93, 0x41, 0xF2, 0x0B, 0x03, 0xEB, 0x5C, 0x63, 0xB9, 0x01, 0x9B, 0x03, 0x22, 0x59, 0x1C, 0x01, 0x91, 0x1A, 0x70, ++0x01, 0x9B, 0x01, 0x22, 0x59, 0x1C, 0x01, 0x91, 0x1A, 0x70, 0x01, 0x9B, 0x13, 0x44, 0x01, 0x93, 0xB9, 0xF1, 0x00, 0x0F, ++0x36, 0xD1, 0xDF, 0xF8, 0x7C, 0x81, 0x98, 0xF8, 0x76, 0x31, 0xD8, 0x07, 0x06, 0xD5, 0x56, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, ++0x48, 0x31, 0x98, 0x47, 0x98, 0xF8, 0x76, 0x31, 0x41, 0xF2, 0x0B, 0x02, 0xAA, 0x5C, 0x01, 0x2A, 0x4A, 0xD0, 0x5D, 0x07, ++0x04, 0xD5, 0x4F, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, 0x44, 0x31, 0x98, 0x47, 0x4D, 0x4D, 0x01, 0x98, 0x29, 0x46, 0x31, 0xF8, ++0x03, 0x2B, 0x0A, 0xF0, 0xB1, 0xF8, 0x4B, 0x4A, 0x01, 0x99, 0x12, 0x68, 0x2B, 0x88, 0xB2, 0xF9, 0x00, 0x20, 0x0B, 0x44, ++0x00, 0x2A, 0x01, 0x93, 0xA3, 0xEB, 0x04, 0x03, 0x5D, 0xDB, 0x00, 0x22, 0xA7, 0xF8, 0x6C, 0x31, 0xC7, 0xF8, 0x68, 0x21, ++0x38, 0x46, 0xF5, 0xF7, 0x45, 0xFD, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x32, 0x78, 0x3B, 0x2A, 0x60, 0xD0, 0xDF, 0xF8, ++0x08, 0x81, 0x98, 0xF8, 0x76, 0x31, 0xD9, 0x07, 0x58, 0xD5, 0x39, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, 0x48, 0x31, 0x98, 0x47, ++0xB9, 0xF1, 0x00, 0x0F, 0xC2, 0xD0, 0x01, 0x99, 0x32, 0x78, 0x0B, 0x46, 0x76, 0x1A, 0x49, 0x44, 0x00, 0xE0, 0xF2, 0x5C, ++0x03, 0xF8, 0x01, 0x2B, 0x99, 0x42, 0xFA, 0xD1, 0x01, 0x9A, 0x98, 0xF8, 0x76, 0x31, 0x4A, 0x44, 0x01, 0x92, 0x41, 0xF2, ++0x0B, 0x02, 0xAA, 0x5C, 0x01, 0x2A, 0xB4, 0xD1, 0x9E, 0x07, 0xB2, 0xD5, 0x29, 0x4B, 0x00, 0x21, 0xD3, 0xF8, 0x50, 0x31, ++0x01, 0xA8, 0x98, 0x47, 0x98, 0xF8, 0x76, 0x31, 0xA9, 0xE7, 0x9C, 0xF8, 0x00, 0x20, 0x0A, 0x2A, 0x7F, 0xF4, 0x62, 0xAF, ++0x9C, 0xF8, 0x01, 0x60, 0x02, 0x36, 0x16, 0xF0, 0xFF, 0x06, 0x09, 0xD0, 0x22, 0x49, 0x98, 0x19, 0x01, 0xE0, 0x11, 0xF8, ++0x01, 0x2F, 0x03, 0xF8, 0x01, 0x2B, 0x83, 0x42, 0xF9, 0xD1, 0x01, 0x9B, 0x33, 0x44, 0xA9, 0xEB, 0x06, 0x09, 0x01, 0x93, ++0x1F, 0xFA, 0x89, 0xF9, 0x66, 0x44, 0x49, 0xE7, 0x01, 0x27, 0xB9, 0x42, 0x53, 0xD0, 0x39, 0x46, 0xA0, 0xE6, 0xB3, 0xF5, ++0x96, 0x7F, 0x9E, 0xD9, 0x16, 0x49, 0x17, 0x48, 0xB4, 0x22, 0xF7, 0xF7, 0x99, 0xFD, 0x01, 0x9B, 0x1B, 0x1B, 0x96, 0xE7, ++0x0A, 0x4B, 0x4F, 0xF0, 0x08, 0x0E, 0x22, 0xE7, 0x01, 0x99, 0xAE, 0xE7, 0x70, 0x78, 0x01, 0x99, 0x02, 0x30, 0x10, 0xF0, ++0xFF, 0x00, 0x42, 0xD0, 0x0B, 0x46, 0xA6, 0xEB, 0x03, 0x0C, 0x01, 0x44, 0x1C, 0xE0, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, ++0xE8, 0x61, 0x18, 0x00, 0xB8, 0xB2, 0x15, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xF2, 0x61, 0x18, 0x00, 0xBC, 0xB2, 0x15, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0xCB, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x63, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x9C, 0xBF, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x1C, 0xF8, 0x03, 0x20, 0x03, 0xF8, 0x01, 0x2B, 0x99, 0x42, 0xF9, 0xD1, ++0xDF, 0xF8, 0x48, 0x80, 0x01, 0x9B, 0x98, 0xF8, 0x76, 0x21, 0x03, 0x44, 0xA9, 0xEB, 0x00, 0x09, 0x01, 0x93, 0xD3, 0x07, ++0x1F, 0xFA, 0x89, 0xF9, 0x06, 0x44, 0x7F, 0xF5, 0x6F, 0xAF, 0x68, 0xE7, 0x41, 0xF2, 0x0B, 0x03, 0x15, 0xF8, 0x03, 0x80, ++0xA3, 0xE6, 0x41, 0xF2, 0x0B, 0x03, 0x02, 0x22, 0xEA, 0x54, 0x00, 0x20, 0xFF, 0xF7, 0xDE, 0xF8, 0x4F, 0xE7, 0xDF, 0xF8, ++0x10, 0x80, 0x98, 0xF8, 0x76, 0x31, 0xDB, 0x07, 0x3F, 0xF5, 0x55, 0xAF, 0x5D, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, ++0xF0, 0xB5, 0x4C, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x83, 0xB0, 0x04, 0xD1, 0x4A, 0x4A, 0x13, 0x68, 0x23, 0xF4, ++0x00, 0x13, 0x13, 0x60, 0x48, 0x4C, 0x49, 0x4D, 0x23, 0x68, 0x5B, 0x07, 0x4E, 0xD4, 0x48, 0x4E, 0x41, 0xF2, 0x0A, 0x03, ++0xEB, 0x5C, 0x5B, 0xB9, 0x44, 0x4A, 0x19, 0x46, 0x02, 0xF5, 0x80, 0x54, 0x80, 0x20, 0x11, 0x72, 0x82, 0xF8, 0x44, 0x00, ++0x40, 0x32, 0x94, 0x42, 0xF9, 0xD1, 0xA9, 0x80, 0x29, 0x68, 0x91, 0xF8, 0x70, 0x21, 0x01, 0x2A, 0x5F, 0xD0, 0x00, 0x24, ++0x20, 0x46, 0x41, 0xF2, 0x3A, 0x02, 0xA8, 0x54, 0x91, 0xF8, 0x6E, 0x21, 0x91, 0xF8, 0x6F, 0x11, 0x08, 0x20, 0xCD, 0xE9, ++0x00, 0x41, 0x38, 0x49, 0xF7, 0xF7, 0xDC, 0xFA, 0x41, 0xF2, 0x0A, 0x03, 0xEB, 0x5C, 0x83, 0xB9, 0x35, 0x49, 0x36, 0x4A, ++0x0B, 0x68, 0x36, 0x48, 0x43, 0xF0, 0x04, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x03, 0x80, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, ++0x43, 0xF4, 0xBB, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x73, 0x68, 0x01, 0x21, 0x43, 0xF0, 0x20, 0x03, 0x04, 0x20, ++0x73, 0x60, 0xF5, 0xF7, 0x01, 0xFE, 0x2B, 0x68, 0xD3, 0xF8, 0x68, 0x11, 0x19, 0xB1, 0xB3, 0xF8, 0x6C, 0x21, 0xC8, 0x2A, ++0x23, 0xD9, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFF, 0xF7, 0xCE, 0xBD, 0x2B, 0x68, 0x25, 0x4A, 0x93, 0xF8, 0x6E, 0x31, ++0x24, 0x49, 0x1E, 0x4E, 0x10, 0x68, 0x24, 0x4A, 0xC0, 0x8E, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x03, 0x13, 0x03, 0x21, ++0x71, 0x77, 0x11, 0x69, 0x20, 0x4A, 0x73, 0x61, 0x01, 0x44, 0xD2, 0xF8, 0xE0, 0x31, 0x06, 0xF1, 0x0C, 0x00, 0x98, 0x47, ++0x01, 0x23, 0x33, 0x77, 0x23, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x23, 0x60, 0x92, 0xE7, 0x1A, 0x48, 0x09, 0xF0, 0x60, 0xFF, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFF, 0xF7, 0xA7, 0xBD, 0x91, 0xF8, 0xFC, 0x20, 0x07, 0x2A, 0x9B, 0xD1, 0x01, 0xF1, ++0xFD, 0x00, 0x14, 0x49, 0x09, 0xF0, 0x22, 0xFF, 0x41, 0xF2, 0x0A, 0x03, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0xEB, 0x5C, ++0x29, 0x68, 0x04, 0x46, 0x8F, 0xE7, 0x00, 0xBF, 0x74, 0x36, 0x17, 0x00, 0x6C, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, ++0xA8, 0xBA, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0xCC, 0xBF, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x20, 0x04, 0x32, 0x40, ++0x28, 0x25, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, ++0x18, 0x63, 0x18, 0x00, 0x54, 0xBF, 0x15, 0x00, 0x00, 0x22, 0x02, 0x81, 0xE7, 0xF7, 0xE0, 0xBA, 0x2D, 0xE9, 0xF0, 0x41, ++0x14, 0x46, 0x52, 0x78, 0x00, 0x2B, 0x18, 0xBF, 0x02, 0x23, 0x52, 0x06, 0x44, 0xBF, 0x08, 0x33, 0xDB, 0xB2, 0x23, 0x44, ++0x06, 0x46, 0x9A, 0x7F, 0x08, 0x2A, 0x0D, 0x46, 0x03, 0xD0, 0x00, 0x27, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0xDA, 0x7F, ++0x06, 0x2A, 0xF8, 0xD1, 0x93, 0xF8, 0x26, 0x70, 0x00, 0x2F, 0xF4, 0xD1, 0x93, 0xF8, 0x27, 0x80, 0xB8, 0xF1, 0x01, 0x0F, ++0x07, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0xED, 0xD1, 0x13, 0x49, 0x80, 0x20, 0xF7, 0xF7, 0x2E, 0xFA, 0xE8, 0xE7, 0x93, 0xF8, ++0x3A, 0x70, 0x93, 0xF8, 0x3B, 0xC0, 0x93, 0xF8, 0x38, 0x00, 0x93, 0xF8, 0x39, 0x20, 0x0B, 0x68, 0x0D, 0x49, 0x3F, 0x04, ++0x47, 0xEA, 0x0C, 0x67, 0x07, 0x43, 0x47, 0xEA, 0x02, 0x27, 0x3A, 0x46, 0x80, 0x20, 0xF7, 0xF7, 0x19, 0xFA, 0x2B, 0x68, ++0x9F, 0x42, 0x01, 0xD0, 0x47, 0x46, 0xCF, 0xE7, 0x06, 0x4B, 0x30, 0x78, 0x9B, 0x69, 0x22, 0x46, 0x04, 0xF1, 0x10, 0x01, ++0x47, 0x46, 0x98, 0x47, 0xC6, 0xE7, 0x00, 0xBF, 0x08, 0xC0, 0x15, 0x00, 0xE8, 0xBF, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xF8, 0xB5, 0x21, 0x4B, 0x21, 0x4D, 0x1E, 0x68, 0x95, 0xF8, 0x44, 0x40, 0xB6, 0xF9, 0x00, 0x70, 0x1F, 0x4B, 0x04, 0xEB, ++0x84, 0x06, 0x00, 0x2F, 0x8E, 0x46, 0x03, 0xEB, 0x06, 0x16, 0x23, 0xDB, 0xA7, 0x00, 0x07, 0xEB, 0x04, 0x0C, 0x03, 0xEB, ++0x0C, 0x1C, 0xCC, 0xF8, 0x0C, 0x00, 0x10, 0xB1, 0x01, 0x7C, 0x8C, 0xF8, 0x10, 0x10, 0x3C, 0x44, 0x03, 0xEB, 0x04, 0x13, ++0x31, 0x46, 0x5A, 0x64, 0xA3, 0xF8, 0x4C, 0xE0, 0x13, 0x48, 0xF5, 0xF7, 0xB5, 0xFF, 0x95, 0xF8, 0x44, 0x20, 0x12, 0x4B, ++0x01, 0x32, 0xA3, 0xFB, 0x02, 0x13, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, 0xA2, 0xEB, 0x83, 0x13, 0x85, 0xF8, 0x44, 0x30, ++0x30, 0x46, 0xF8, 0xBD, 0x04, 0xEB, 0x84, 0x01, 0x03, 0xEB, 0x01, 0x11, 0xA7, 0x00, 0xB1, 0xF8, 0x4C, 0x10, 0x00, 0x29, ++0xD3, 0xD0, 0x08, 0x49, 0x08, 0x48, 0xC6, 0x22, 0xF7, 0xF7, 0xBA, 0xFB, 0x00, 0x26, 0xED, 0xE7, 0x38, 0x36, 0x17, 0x00, ++0xB0, 0xDE, 0x17, 0x00, 0xE0, 0x63, 0x18, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0xAB, 0xAA, 0xAA, 0xAA, 0x70, 0x79, 0x15, 0x00, ++0x14, 0xC0, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x4D, 0x42, 0x69, 0x04, 0x46, 0x04, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, ++0x21, 0x46, 0x28, 0x46, 0xF5, 0xF7, 0xCC, 0xFF, 0xA5, 0xF1, 0x08, 0x00, 0x21, 0x46, 0xF5, 0xF7, 0x77, 0xFF, 0x05, 0x4B, ++0xA5, 0xF1, 0x20, 0x00, 0xD3, 0xF8, 0x38, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x08, 0xDF, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xB3, 0x4B, 0x01, 0xF0, 0x7C, 0x04, 0x1A, 0x7A, 0x04, 0x3C, 0x00, 0xEB, ++0x02, 0x0C, 0x01, 0xF4, 0x80, 0x6E, 0x18, 0x2C, 0x0E, 0xD8, 0xDF, 0xE8, 0x04, 0xF0, 0x54, 0x0D, 0x0D, 0x0D, 0x58, 0x0D, ++0x0D, 0x0D, 0x8D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0xB5, 0x00, ++0x00, 0x24, 0xA7, 0x4D, 0x2D, 0x68, 0x2D, 0x78, 0xAD, 0x07, 0x03, 0xD5, 0x01, 0xF0, 0x3C, 0x01, 0x3C, 0x29, 0x02, 0xD0, ++0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xBE, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xD1, 0x80, 0xBC, 0xF8, 0x02, 0x10, 0x9E, 0x7A, ++0x9E, 0x4C, 0x8D, 0x0B, 0x4F, 0xF4, 0xA4, 0x61, 0xC5, 0xEB, 0x05, 0x17, 0x01, 0xFB, 0x06, 0xF1, 0x01, 0xEB, 0xC7, 0x01, ++0x21, 0x44, 0x2F, 0x01, 0x91, 0xF8, 0x3B, 0xE2, 0xBE, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xCC, 0x80, 0x91, 0xF8, 0x38, 0x12, ++0x01, 0x29, 0x00, 0xF0, 0xEB, 0x80, 0x02, 0x29, 0x00, 0xF0, 0xC1, 0x80, 0x0A, 0x1F, 0x01, 0x2A, 0x40, 0xF2, 0xBD, 0x80, ++0x1A, 0x7A, 0x04, 0x32, 0x1A, 0x72, 0xDC, 0xF8, 0x00, 0x00, 0xC1, 0x17, 0xC3, 0xE9, 0x04, 0x01, 0x4F, 0xF4, 0xA4, 0x62, ++0x02, 0xFB, 0x06, 0xF2, 0x79, 0x1B, 0x02, 0xF5, 0xEC, 0x72, 0x02, 0xEB, 0xC1, 0x02, 0x22, 0x44, 0x1A, 0x62, 0x01, 0x24, ++0xC2, 0xE7, 0x14, 0x1D, 0x1C, 0x72, 0x01, 0x24, 0xB5, 0xE7, 0x02, 0xF1, 0x08, 0x04, 0x1C, 0x72, 0x30, 0xF8, 0x02, 0x80, ++0xBC, 0xF8, 0x06, 0x40, 0x9C, 0xF8, 0x02, 0xA0, 0x93, 0xF8, 0x30, 0x90, 0x4F, 0xEA, 0x08, 0x28, 0x1F, 0xFA, 0x88, 0xF8, ++0x46, 0x46, 0xF7, 0x17, 0x44, 0xEA, 0x07, 0x06, 0xBC, 0xF8, 0x04, 0x40, 0x4A, 0xEA, 0x04, 0x44, 0x44, 0xEA, 0x08, 0x04, ++0x49, 0xF0, 0x03, 0x09, 0xC3, 0xE9, 0x04, 0x46, 0x83, 0xF8, 0x30, 0x90, 0xBE, 0xF1, 0x00, 0x0F, 0x5F, 0xD0, 0x9E, 0x7A, ++0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x6E, 0x4E, 0x04, 0xF5, 0xEC, 0x74, ++0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x1C, 0x62, 0x01, 0x24, 0x80, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, ++0x50, 0xD0, 0x9E, 0x7A, 0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x63, 0x4E, ++0x04, 0xF5, 0xEC, 0x74, 0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x02, 0xF1, 0x08, 0x05, 0x1D, 0x72, ++0xBC, 0xF8, 0x04, 0x60, 0x93, 0xF8, 0x30, 0x80, 0x1C, 0x62, 0x84, 0x5A, 0xBC, 0xF8, 0x06, 0x50, 0x5D, 0x61, 0x44, 0xEA, ++0x06, 0x44, 0x48, 0xF0, 0x02, 0x05, 0x1C, 0x61, 0x83, 0xF8, 0x30, 0x50, 0x01, 0x24, 0x58, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, ++0x2F, 0xD0, 0x9E, 0x7A, 0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x4F, 0x4E, ++0x04, 0xF5, 0xEC, 0x74, 0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x02, 0xF1, 0x12, 0x05, 0x66, 0x46, ++0x1D, 0x72, 0x56, 0xF8, 0x02, 0x7F, 0x93, 0xF8, 0x30, 0x50, 0x76, 0x68, 0x1C, 0x62, 0x45, 0xF0, 0x02, 0x04, 0x83, 0xF8, ++0x30, 0x40, 0xC3, 0xE9, 0x04, 0x76, 0x01, 0x24, 0x33, 0xE7, 0x5C, 0x7A, 0x42, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, ++0x04, 0x54, 0xA8, 0xE7, 0x5C, 0x7A, 0x3F, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0x54, 0xB7, 0xE7, 0x5C, 0x7A, ++0x3B, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0x54, 0xD8, 0xE7, 0x59, 0x7A, 0x39, 0x4D, 0x4F, 0xF4, 0x1E, 0x74, ++0x04, 0xFB, 0x01, 0xF4, 0x29, 0x19, 0x91, 0xF8, 0x98, 0x10, 0x01, 0x29, 0x43, 0xD0, 0x02, 0x29, 0x04, 0xD1, 0x34, 0x48, ++0xF7, 0xF7, 0x36, 0xF8, 0x00, 0x24, 0x15, 0xE7, 0x0A, 0x1F, 0x01, 0x2A, 0xF7, 0xD9, 0x18, 0x7A, 0xBC, 0xF8, 0x02, 0x10, ++0x9D, 0x7A, 0x2B, 0x4E, 0x04, 0x30, 0x18, 0x72, 0xDC, 0xF8, 0x00, 0x40, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x05, 0xF2, ++0x89, 0x0B, 0xE5, 0x17, 0xC1, 0xEB, 0x01, 0x11, 0x02, 0xF5, 0xEC, 0x72, 0xC3, 0xE9, 0x04, 0x45, 0x02, 0xEB, 0xC1, 0x02, ++0x32, 0x44, 0x92, 0xF8, 0x63, 0x10, 0x00, 0x29, 0xDE, 0xD0, 0x1A, 0x62, 0x01, 0x24, 0xF3, 0xE6, 0x19, 0x7A, 0x93, 0xF8, ++0x30, 0xE0, 0x08, 0x31, 0x19, 0x72, 0x82, 0x5A, 0x9C, 0xF8, 0x02, 0x80, 0xBC, 0xF8, 0x04, 0x00, 0xBC, 0xF8, 0x06, 0x90, ++0x12, 0x02, 0x92, 0xB2, 0xD1, 0x17, 0x48, 0xEA, 0x00, 0x40, 0x49, 0xEA, 0x01, 0x09, 0x02, 0x43, 0x4E, 0xF0, 0x03, 0x0E, ++0xC3, 0xE9, 0x04, 0x29, 0x83, 0xF8, 0x30, 0xE0, 0x08, 0xE7, 0x19, 0x7A, 0x93, 0xF8, 0x30, 0x70, 0x08, 0x31, 0x19, 0x72, ++0x81, 0x5A, 0xBC, 0xF8, 0x04, 0x80, 0x9C, 0xF8, 0x02, 0x00, 0xBC, 0xF8, 0x06, 0x60, 0x09, 0x02, 0x89, 0xB2, 0x04, 0xF1, ++0x38, 0x02, 0x40, 0xEA, 0x08, 0x44, 0x0C, 0x43, 0xC9, 0x17, 0x47, 0xF0, 0x03, 0x07, 0x0E, 0x43, 0xC3, 0xE9, 0x04, 0x46, ++0x2A, 0x44, 0x83, 0xF8, 0x30, 0x70, 0xC0, 0xE7, 0xB0, 0xDE, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, ++0xA0, 0x65, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x34, 0xC0, 0x15, 0x00, 0x70, 0xB5, 0x18, 0x4E, 0x18, 0x4A, 0xB3, 0x7A, ++0x75, 0x7A, 0x12, 0x7C, 0x1B, 0x02, 0x43, 0xEA, 0x05, 0x43, 0xF5, 0x7A, 0x04, 0x46, 0x00, 0x6E, 0x43, 0xEA, 0x05, 0x63, ++0xFF, 0x2A, 0x0D, 0x46, 0x43, 0xEA, 0x00, 0x03, 0x17, 0xD0, 0x41, 0xF0, 0x80, 0x05, 0x43, 0xF0, 0x80, 0x03, 0xEA, 0x07, ++0x48, 0xBF, 0x43, 0xF0, 0x40, 0x03, 0x0D, 0x4A, 0x58, 0xBF, 0x23, 0xF0, 0x40, 0x03, 0x23, 0x66, 0x20, 0x46, 0xD2, 0xF8, ++0xA8, 0x32, 0x98, 0x47, 0x32, 0x6C, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xEF, 0xBD, 0x29, 0x06, ++0x58, 0xBF, 0x23, 0xF0, 0x80, 0x03, 0xE6, 0xD5, 0xE3, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x21, 0x4B, 0x21, 0x4E, 0x1B, 0x7C, 0xFF, 0x2B, 0x04, 0x46, 0x0D, 0x46, 0x21, 0xD0, ++0xB2, 0x7A, 0xFF, 0x2A, 0x32, 0xD0, 0x01, 0xF0, 0x01, 0x01, 0x45, 0xF0, 0x80, 0x05, 0x77, 0x7A, 0x20, 0x6E, 0x13, 0x02, ++0x43, 0xEA, 0x07, 0x43, 0x03, 0x43, 0x43, 0xF0, 0x82, 0x03, 0x11, 0xB3, 0x43, 0xF0, 0x40, 0x03, 0x16, 0x49, 0x23, 0x66, ++0x00, 0x22, 0xD1, 0xF8, 0xA8, 0x32, 0x86, 0xF8, 0x32, 0x20, 0x20, 0x46, 0x98, 0x47, 0x32, 0x6C, 0x29, 0x46, 0x20, 0x46, ++0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0xB8, 0xBD, 0xB3, 0x7A, 0x71, 0x7A, 0x02, 0x6E, 0x1B, 0x02, 0x43, 0xEA, 0x01, 0x43, ++0x13, 0x43, 0x2A, 0x06, 0x0D, 0xD4, 0x23, 0xF0, 0x80, 0x03, 0x05, 0xF0, 0x01, 0x01, 0x43, 0xF0, 0x02, 0x03, 0x00, 0x29, ++0xDC, 0xD1, 0x23, 0xF0, 0x40, 0x03, 0xDB, 0xE7, 0x00, 0x21, 0x80, 0x25, 0xCD, 0xE7, 0x05, 0xF0, 0x01, 0x01, 0xD0, 0xE7, ++0x00, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x32, 0x4B, 0x01, 0x88, 0x70, 0xB4, 0x19, 0x80, ++0xC2, 0x8A, 0x5A, 0x80, 0x01, 0xF0, 0x88, 0x06, 0xC2, 0xF3, 0x0B, 0x14, 0x00, 0x25, 0x02, 0xF0, 0x0F, 0x02, 0x88, 0x2E, ++0x9C, 0x80, 0x9A, 0x71, 0x8C, 0xB2, 0x83, 0xF8, 0x30, 0x50, 0x45, 0xD0, 0xDD, 0x71, 0x04, 0xF4, 0x40, 0x72, 0xB2, 0xF5, ++0x40, 0x7F, 0x04, 0xF0, 0xFC, 0x05, 0x0C, 0xBF, 0x1E, 0x22, 0x18, 0x22, 0x88, 0x2D, 0x08, 0xBF, 0x02, 0x32, 0x0E, 0x04, ++0x44, 0xBF, 0x04, 0x32, 0xD2, 0xB2, 0x1A, 0x72, 0x02, 0x79, 0xD5, 0x07, 0x44, 0xBF, 0x08, 0x22, 0x83, 0xF8, 0x30, 0x20, ++0xE4, 0x05, 0x12, 0xD5, 0x02, 0x8A, 0x9A, 0x84, 0x42, 0x8A, 0xDA, 0x84, 0x82, 0x8A, 0x1A, 0x85, 0x02, 0x88, 0x91, 0x05, ++0x12, 0xD5, 0xD2, 0x05, 0x18, 0xD5, 0x02, 0x8B, 0x5A, 0x85, 0x42, 0x8B, 0x9A, 0x85, 0x82, 0x8B, 0xDA, 0x85, 0x70, 0xBC, ++0x70, 0x47, 0x82, 0x88, 0x9A, 0x84, 0xC2, 0x88, 0xDA, 0x84, 0x02, 0x89, 0x1A, 0x85, 0x02, 0x88, 0x91, 0x05, 0xEC, 0xD4, ++0x42, 0x89, 0x5A, 0x85, 0x82, 0x89, 0x9A, 0x85, 0xC2, 0x89, 0xDA, 0x85, 0x70, 0xBC, 0x70, 0x47, 0x02, 0x8A, 0x5A, 0x85, ++0x42, 0x8A, 0x9A, 0x85, 0x82, 0x8A, 0xDA, 0x85, 0x70, 0xBC, 0x70, 0x47, 0x04, 0xF4, 0x40, 0x72, 0xB2, 0xF5, 0x40, 0x7F, ++0x0C, 0xBF, 0xC5, 0x8B, 0x05, 0x8B, 0x05, 0xF0, 0x07, 0x05, 0xDD, 0x71, 0xB1, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, ++0xF8, 0xB5, 0x05, 0x22, 0x18, 0x23, 0x0C, 0x21, 0x41, 0xF2, 0x06, 0x40, 0xF5, 0xF7, 0x74, 0xF8, 0x0F, 0x4A, 0x03, 0x46, ++0x51, 0x7A, 0x0F, 0x48, 0x94, 0x69, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x01, 0x01, 0xD2, 0xE9, 0x04, 0x67, 0x51, 0xF8, ++0x26, 0x0F, 0x89, 0x88, 0x99, 0x80, 0xC3, 0xE9, 0x02, 0x67, 0x18, 0x60, 0x91, 0x7A, 0x99, 0x74, 0xC4, 0xF3, 0x80, 0x24, ++0x1C, 0x74, 0x12, 0x6A, 0x92, 0xF8, 0x61, 0x20, 0x5A, 0x74, 0x18, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xF5, 0xF7, 0x84, 0xB8, ++0xB0, 0xDE, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x3C, 0x82, 0xD8, 0xF8, 0x00, 0x40, ++0x27, 0x78, 0x87, 0xB0, 0x17, 0xF0, 0x01, 0x07, 0x04, 0x46, 0x03, 0x93, 0x08, 0xD0, 0x43, 0x6D, 0x03, 0xF0, 0x07, 0x03, ++0x02, 0x2B, 0x7F, 0xD0, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x80, 0x4D, 0x89, 0x46, 0x00, 0x2A, 0x40, 0xF0, ++0xA2, 0x80, 0x02, 0x8E, 0x2B, 0x7A, 0xC6, 0x69, 0xD4, 0x1A, 0x03, 0x9A, 0xA4, 0xB2, 0x10, 0x31, 0x12, 0xB1, 0x07, 0x2C, ++0x40, 0xF2, 0xA9, 0x80, 0x08, 0x22, 0x48, 0x46, 0xFA, 0xF7, 0x92, 0xFF, 0x29, 0x7A, 0x8A, 0xB2, 0xD6, 0xE9, 0x02, 0x03, ++0x08, 0x3C, 0x01, 0x33, 0xA5, 0xB2, 0x1C, 0x1A, 0xA4, 0xB2, 0x4B, 0x19, 0x9C, 0x42, 0x01, 0x44, 0x80, 0xF2, 0x82, 0x80, ++0xDF, 0xF8, 0xD4, 0xA1, 0x13, 0x1B, 0x1D, 0x44, 0xA2, 0x1A, 0x92, 0xB2, 0x48, 0x46, 0xAD, 0xB2, 0xFA, 0xF7, 0x7A, 0xFF, ++0x00, 0x22, 0x95, 0xB1, 0xDA, 0xF8, 0x00, 0x30, 0x76, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x93, 0x42, 0x4D, 0xDB, 0xD6, 0xE9, ++0x02, 0x14, 0x01, 0x34, 0x64, 0x1A, 0xA4, 0xB2, 0xAC, 0x42, 0xE7, 0xD3, 0x2C, 0x46, 0x2A, 0x46, 0x48, 0x46, 0xFA, 0xF7, ++0x65, 0xFF, 0xDF, 0xF8, 0x98, 0xE1, 0x0D, 0xF1, 0x10, 0x0C, 0x08, 0x25, 0xD6, 0xE9, 0x02, 0x32, 0x01, 0x32, 0x98, 0xB2, ++0x92, 0xB2, 0xA2, 0xEB, 0x00, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x29, 0x19, 0x51, 0x45, 0x23, 0x44, 0x3B, 0xDD, 0xAA, 0xEB, ++0x04, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x0A, 0xF1, 0xFF, 0x3B, 0xBA, 0xF1, 0x00, 0x0F, 0x37, 0xD0, 0x82, 0x1A, 0x14, 0x44, ++0x25, 0x44, 0xAD, 0xB2, 0x59, 0x1C, 0x59, 0x44, 0xAC, 0xEB, 0x03, 0x00, 0x1A, 0x78, 0xC2, 0x54, 0x01, 0x33, 0x8B, 0x42, ++0xFA, 0xD1, 0xD4, 0x44, 0x65, 0xB3, 0xDE, 0xF8, 0x00, 0x30, 0x76, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x24, 0xA3, 0x42, ++0xD2, 0xDA, 0x00, 0x2E, 0xD0, 0xD1, 0x47, 0x49, 0x47, 0x48, 0x40, 0xF2, 0x66, 0x42, 0xF7, 0xF7, 0x6F, 0xF8, 0x7F, 0xE7, ++0xFF, 0xF7, 0x40, 0xFF, 0x00, 0x27, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2E, 0xAF, 0xD1, 0x3F, 0x49, ++0x3F, 0x48, 0x40, 0xF2, 0x3C, 0x42, 0xF7, 0xF7, 0x5F, 0xF8, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xAA, 0x46, ++0x05, 0xF1, 0xFF, 0x3B, 0x00, 0x25, 0xCB, 0xE7, 0x01, 0x44, 0x8A, 0x1A, 0x95, 0xB2, 0xD2, 0xE7, 0x03, 0x9B, 0x00, 0x2B, ++0x3C, 0xD1, 0xDD, 0xE9, 0x04, 0x23, 0xC9, 0xE9, 0x04, 0x23, 0x01, 0x27, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x2A, 0x44, 0x94, 0xB2, 0x95, 0xE7, 0x29, 0x6A, 0xEB, 0x79, 0x00, 0x93, 0x58, 0x31, 0x05, 0xF1, 0x2A, 0x03, 0x05, 0xF1, ++0x24, 0x02, 0x48, 0x46, 0xFA, 0xF7, 0xCE, 0xFE, 0x29, 0x7A, 0x23, 0x8E, 0xE6, 0x69, 0x5C, 0x1A, 0xA4, 0xB2, 0x8A, 0xB2, ++0x5C, 0xE7, 0xB5, 0x68, 0x03, 0x91, 0x22, 0x46, 0x48, 0x46, 0x1D, 0x44, 0xFA, 0xF7, 0xE6, 0xFE, 0x03, 0x99, 0xC4, 0xF1, ++0x08, 0x06, 0x04, 0xAB, 0xF6, 0xB2, 0x21, 0x44, 0xF2, 0x18, 0xC9, 0x1A, 0xC8, 0x5C, 0x03, 0xF8, 0x01, 0x0B, 0x9A, 0x42, ++0xFA, 0xD1, 0xD6, 0xF1, 0x08, 0x06, 0x07, 0xD0, 0x2B, 0x46, 0xD2, 0x1A, 0x35, 0x44, 0x19, 0x78, 0xD1, 0x54, 0x01, 0x33, ++0x9D, 0x42, 0xFA, 0xD1, 0x48, 0x46, 0xFA, 0xF7, 0x69, 0xFF, 0x04, 0x9A, 0xD9, 0xF8, 0x00, 0x30, 0x9A, 0x42, 0x0D, 0xD0, ++0xD8, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x9B, 0x07, 0x05, 0xD5, 0x03, 0x20, 0xD8, 0xF7, 0xCE, 0xF9, 0x0F, 0x4B, 0x98, 0x42, ++0x12, 0xD1, 0xFF, 0xF7, 0xD1, 0xFE, 0x0D, 0xE7, 0xD9, 0xF8, 0x04, 0x30, 0x05, 0x9A, 0x9A, 0x42, 0xEC, 0xD1, 0xD8, 0xF8, ++0x00, 0x30, 0x1B, 0x78, 0x9A, 0x07, 0xA6, 0xD5, 0x03, 0x20, 0xD8, 0xF7, 0xBB, 0xF9, 0x06, 0x4B, 0x98, 0x42, 0xA0, 0xD0, ++0x05, 0x48, 0xF6, 0xF7, 0xA1, 0xFD, 0xF9, 0xE6, 0xB0, 0xDE, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, ++0x1C, 0xDF, 0x44, 0x21, 0x44, 0xC0, 0x15, 0x00, 0x34, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x10, 0xB5, 0x10, 0x48, ++0xF5, 0xF7, 0xF8, 0xFB, 0x10, 0xB1, 0x04, 0x46, 0x20, 0x46, 0x10, 0xBD, 0x0D, 0x48, 0xF5, 0xF7, 0xF1, 0xFB, 0x0D, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x06, 0xDB, 0x62, 0x69, 0x04, 0x21, 0x00, 0x20, 0xFF, 0xF7, ++0xC7, 0xFB, 0x20, 0x46, 0x10, 0xBD, 0x00, 0x28, 0xF6, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xEA, 0x42, 0xF6, 0xF7, ++0xEB, 0xFF, 0xEF, 0xE7, 0x00, 0xDF, 0x17, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x54, 0xC0, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x63, 0x79, 0x62, 0x69, 0x83, 0x42, 0x14, 0xBF, 0x18, 0x21, ++0x08, 0x21, 0xFF, 0xF7, 0xA7, 0xFB, 0x08, 0xB1, 0xA3, 0x89, 0x83, 0x64, 0x10, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, ++0xA3, 0x4F, 0x8A, 0xB0, 0x05, 0x46, 0x14, 0x46, 0x1A, 0xB3, 0x3E, 0x88, 0x97, 0xF8, 0x07, 0x80, 0x16, 0xF4, 0x80, 0x66, ++0x22, 0xD1, 0x97, 0xF8, 0x06, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x6A, 0xD0, 0xBC, 0x6D, 0xBA, 0x88, 0x14, 0xB9, 0x31, 0xE1, ++0x24, 0x68, 0xEC, 0xB1, 0xA3, 0x79, 0x8B, 0x42, 0xFA, 0xD1, 0xE3, 0x79, 0x43, 0x45, 0xF7, 0xD1, 0x63, 0x89, 0x93, 0x42, ++0xF4, 0xD1, 0x23, 0x7A, 0x53, 0x45, 0x00, 0xF0, 0x90, 0x80, 0x4F, 0xF0, 0x00, 0x0A, 0x50, 0x46, 0x0A, 0xB0, 0xBD, 0xE8, ++0xF0, 0x87, 0x3E, 0x88, 0x16, 0xF4, 0x80, 0x66, 0x90, 0x46, 0xDC, 0xD0, 0xBC, 0x6D, 0xBA, 0x88, 0x97, 0xF8, 0x06, 0xA0, ++0x00, 0x2C, 0xE1, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0xEB, 0xD1, 0x03, 0x91, 0xFF, 0xF7, 0x88, 0xFF, 0x01, 0x26, 0x03, 0x99, ++0x81, 0x71, 0x80, 0xF8, 0x07, 0x80, 0x06, 0x72, 0xBA, 0x88, 0x80, 0xF8, 0x04, 0xA0, 0x39, 0x7A, 0x82, 0x4B, 0xC0, 0xF8, ++0x10, 0xA0, 0x41, 0x72, 0x19, 0x69, 0xDF, 0xF8, 0x0C, 0x92, 0x80, 0x4B, 0x42, 0x81, 0x01, 0xF5, 0xC3, 0x31, 0x83, 0x63, ++0xC0, 0x63, 0xD9, 0xF8, 0xE0, 0x31, 0x04, 0x46, 0xA0, 0x31, 0x34, 0x30, 0x98, 0x47, 0x97, 0xF8, 0x30, 0x30, 0xDA, 0x07, ++0x00, 0xF1, 0xC9, 0x80, 0x2B, 0x6E, 0x23, 0xF0, 0x20, 0x03, 0x2B, 0x66, 0xD9, 0xF8, 0xE8, 0x32, 0x01, 0x21, 0x28, 0x46, ++0x98, 0x47, 0x3B, 0x6C, 0xFA, 0x69, 0x73, 0x48, 0xC4, 0xE9, 0x04, 0x23, 0x97, 0xF8, 0x31, 0x30, 0x63, 0x71, 0x2B, 0x8E, ++0xA3, 0x81, 0x21, 0x46, 0xF5, 0xF7, 0x08, 0xFB, 0x6B, 0x4B, 0x4F, 0xF0, 0x01, 0x0A, 0x1B, 0x69, 0xA3, 0x61, 0x50, 0x46, ++0x0A, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x97, 0xF8, 0x30, 0x30, 0xD8, 0x07, 0x1D, 0xD5, 0x68, 0x4A, 0x01, 0x23, 0xD2, 0xF8, ++0xCC, 0x62, 0x04, 0xA9, 0x1A, 0x46, 0x28, 0x46, 0xB0, 0x47, 0x00, 0x28, 0x9B, 0xD0, 0x2B, 0x8E, 0x63, 0x4A, 0x08, 0x3B, ++0x12, 0x68, 0x2B, 0x86, 0x13, 0x78, 0x99, 0x07, 0x0B, 0xD5, 0x6B, 0x6D, 0x03, 0xF0, 0x3C, 0x02, 0x3C, 0x2A, 0x06, 0xD1, ++0x23, 0xF0, 0x7C, 0x03, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xF0, 0x08, 0x03, 0x6B, 0x65, 0x5B, 0x4B, 0xB8, 0x7A, 0x4F, 0xF4, ++0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC3, 0x34, 0x00, 0x2B, 0x6D, 0xD1, 0x54, 0x4B, 0x28, 0x46, 0xD3, 0xF8, ++0xE8, 0x32, 0x03, 0x21, 0x98, 0x47, 0x4F, 0xF0, 0x01, 0x0A, 0x50, 0x46, 0x0A, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x29, 0x8E, ++0x94, 0xF8, 0x09, 0x80, 0xA3, 0x89, 0xDF, 0xF8, 0x30, 0x91, 0xA1, 0xEB, 0x08, 0x08, 0x1F, 0xFA, 0x88, 0xF8, 0x43, 0x44, ++0x0A, 0xF1, 0x01, 0x0A, 0x84, 0xF8, 0x08, 0xA0, 0xA3, 0x81, 0x97, 0xF8, 0x30, 0x30, 0xDB, 0x07, 0x22, 0xD5, 0xB6, 0xFA, ++0x86, 0xF3, 0xD9, 0xF8, 0xCC, 0x72, 0x5B, 0x09, 0x00, 0x22, 0x04, 0xF1, 0x1C, 0x01, 0x28, 0x46, 0xB8, 0x47, 0x00, 0x28, ++0x4C, 0xD0, 0x2B, 0x6E, 0x00, 0x2E, 0x57, 0xD0, 0x61, 0x7A, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, 0x40, 0x03, ++0x2B, 0x66, 0x41, 0x44, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0xD9, 0xF8, 0xA4, 0x62, 0x89, 0xB2, 0x28, 0x46, 0xB0, 0x47, ++0x23, 0x69, 0x43, 0x44, 0x23, 0x61, 0x87, 0xE7, 0x01, 0x27, 0x2B, 0x6E, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, ++0x40, 0x03, 0x2B, 0x66, 0x00, 0x23, 0xCD, 0xE9, 0x00, 0x33, 0x28, 0x46, 0xD9, 0xF8, 0xA4, 0x52, 0xA8, 0x47, 0x23, 0x69, ++0x43, 0x44, 0x23, 0x61, 0x00, 0x2E, 0x7F, 0xF4, 0x73, 0xAF, 0x20, 0x46, 0xFF, 0xF7, 0xEC, 0xFE, 0x62, 0x69, 0x39, 0x46, ++0x00, 0x20, 0xFF, 0xF7, 0x99, 0xFA, 0xD9, 0xF8, 0xD8, 0x31, 0x04, 0xF1, 0x34, 0x00, 0x98, 0x47, 0x21, 0x46, 0x20, 0x48, ++0xF5, 0xF7, 0xBA, 0xFA, 0x22, 0x48, 0x21, 0x46, 0xF5, 0xF7, 0x66, 0xFA, 0x5C, 0xE7, 0xEA, 0x69, 0x00, 0xF2, 0xC4, 0x41, ++0x92, 0x68, 0x23, 0x46, 0x63, 0x30, 0xFF, 0xF7, 0x31, 0xFA, 0x01, 0x28, 0x87, 0xD1, 0x04, 0xE7, 0x61, 0x7A, 0x41, 0x44, ++0x89, 0xB2, 0x04, 0x27, 0xC5, 0xE7, 0x32, 0x46, 0x53, 0x46, 0xD9, 0xF8, 0xCC, 0x62, 0x04, 0xF1, 0x1C, 0x01, 0x28, 0x46, ++0xB0, 0x47, 0x2D, 0xE7, 0xA0, 0x89, 0x61, 0x7A, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, 0x40, 0x03, 0x08, 0x38, ++0xA0, 0x81, 0x41, 0x44, 0x2B, 0x66, 0x28, 0x46, 0x33, 0x46, 0xCD, 0xE9, 0x00, 0x66, 0xD9, 0xF8, 0xA4, 0x52, 0x89, 0xB2, ++0xA8, 0x47, 0x23, 0x69, 0x43, 0x44, 0x23, 0x61, 0x01, 0x27, 0xB8, 0xE7, 0xA2, 0x46, 0xDC, 0xE6, 0xB0, 0xDE, 0x17, 0x00, ++0x00, 0x10, 0x50, 0x40, 0xC5, 0xD3, 0x14, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x00, 0xDF, 0x17, 0x00, 0xF8, 0xB5, 0x03, 0x88, 0x13, 0x4D, 0x13, 0xF4, 0x00, 0x6F, 0x04, 0x46, ++0xC3, 0x8A, 0x0B, 0xD1, 0x05, 0xF1, 0x60, 0x07, 0x00, 0xF1, 0x0A, 0x06, 0x30, 0x68, 0xB2, 0x88, 0xBA, 0x80, 0x28, 0x66, ++0xA5, 0xF8, 0x66, 0x30, 0x01, 0x20, 0xF8, 0xBD, 0xB5, 0xF8, 0x66, 0x20, 0x9A, 0x42, 0x04, 0xD0, 0x00, 0xF1, 0x0A, 0x06, ++0x05, 0xF1, 0x60, 0x07, 0xEE, 0xE7, 0x05, 0xF1, 0x60, 0x07, 0x00, 0xF1, 0x0A, 0x06, 0x39, 0x46, 0x30, 0x46, 0x06, 0x22, ++0x09, 0xF0, 0xC6, 0xF8, 0x00, 0x28, 0xEA, 0xD0, 0xE3, 0x8A, 0xE1, 0xE7, 0xB0, 0xDE, 0x17, 0x00, 0xF0, 0xB4, 0x01, 0xB3, ++0x00, 0x22, 0x87, 0x7A, 0x94, 0x46, 0x07, 0xE0, 0x1E, 0x69, 0x1E, 0xB1, 0x01, 0x3C, 0xC3, 0xF8, 0x10, 0xC0, 0xC4, 0x72, ++0x8D, 0x42, 0x09, 0xD2, 0xBB, 0x18, 0xC4, 0x7A, 0x03, 0xF0, 0x3F, 0x03, 0x01, 0x32, 0x00, 0xEB, 0x83, 0x03, 0x95, 0xB2, ++0x00, 0x2C, 0xED, 0xD1, 0x03, 0x89, 0x0F, 0x44, 0x19, 0x44, 0x07, 0xF0, 0x3F, 0x07, 0xC1, 0xF3, 0x0B, 0x01, 0x87, 0x72, ++0x01, 0x81, 0xF0, 0xBC, 0x70, 0x47, 0x87, 0x7A, 0xF2, 0xE7, 0x00, 0xBF, 0xF8, 0xB5, 0x83, 0x7A, 0x04, 0x33, 0x50, 0xF8, ++0x23, 0x30, 0x53, 0xB3, 0xC1, 0x7A, 0x15, 0x4D, 0x15, 0x4F, 0x16, 0x4E, 0x04, 0x46, 0x15, 0xE0, 0xA3, 0x7A, 0x22, 0x89, ++0x18, 0x1D, 0x01, 0x33, 0x03, 0xF0, 0x3F, 0x03, 0x01, 0x39, 0x4F, 0xF0, 0x00, 0x0C, 0x44, 0xF8, 0x20, 0xC0, 0xC9, 0xB2, ++0x18, 0x1D, 0xA3, 0x72, 0xE1, 0x72, 0x54, 0xF8, 0x20, 0x00, 0x53, 0x1C, 0xC3, 0xF3, 0x0B, 0x03, 0x23, 0x81, 0x70, 0xB1, ++0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE4, 0xDA, 0x00, 0x29, 0xE2, 0xD1, 0x39, 0x46, 0x4F, 0xF4, 0xD6, 0x62, ++0x30, 0x46, 0xF6, 0xF7, 0xF5, 0xFD, 0xE1, 0x7A, 0xDA, 0xE7, 0xF8, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x9E, 0x23, 0x0C, 0x8A, 0x38, 0x4A, 0x03, 0xFB, 0x00, 0xF0, 0x00, 0xEB, ++0x14, 0x30, 0x02, 0xEB, 0x80, 0x00, 0xD0, 0xF8, 0x7C, 0x41, 0x4C, 0xB3, 0x94, 0xF8, 0x21, 0x31, 0x49, 0x8A, 0xC3, 0xB1, ++0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x30, 0xD5, 0x30, 0x48, 0x31, 0x4D, 0x03, 0x68, 0x2E, 0x68, 0x03, 0xF0, 0x60, 0x42, ++0x77, 0x1C, 0xB2, 0xF1, 0xC0, 0x4F, 0x2F, 0x60, 0x31, 0xD0, 0x2D, 0x4B, 0x80, 0x22, 0x1A, 0x60, 0x2F, 0xB1, 0x2C, 0x4B, ++0x2E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x22, 0x89, 0xB2, 0xEB, 0x11, 0x1F, 0x4F, 0xEA, 0x11, 0x13, ++0x06, 0xD0, 0x9B, 0x1A, 0x99, 0xB2, 0x1B, 0x05, 0x04, 0xD5, 0x94, 0xF8, 0x21, 0x31, 0x9B, 0xB1, 0xBD, 0xE8, 0xF0, 0x81, ++0x22, 0x4D, 0x20, 0x46, 0xD5, 0xF8, 0xD8, 0x32, 0xC1, 0xF3, 0x0B, 0x01, 0x98, 0x47, 0xD5, 0xF8, 0x38, 0x31, 0x1F, 0x48, ++0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xC9, 0xE7, 0x1B, 0x48, 0xF6, 0xF7, ++0x23, 0xFB, 0x01, 0x23, 0x84, 0xF8, 0x21, 0x31, 0xE4, 0xE7, 0x19, 0x4A, 0x03, 0xF4, 0xF0, 0x33, 0xD2, 0xF8, 0x00, 0xC0, ++0xB3, 0xF5, 0xF0, 0x3F, 0x0C, 0xF1, 0x10, 0x0C, 0xC3, 0xD0, 0x96, 0x46, 0x03, 0x68, 0x03, 0xF0, 0x60, 0x42, 0xB2, 0xF1, ++0xC0, 0x4F, 0x02, 0xD0, 0x10, 0x4B, 0x1B, 0x68, 0xB9, 0xE7, 0x03, 0xF4, 0xF0, 0x33, 0xB3, 0xF5, 0xF0, 0x3F, 0xF7, 0xD0, ++0xDE, 0xF8, 0x00, 0x30, 0xA3, 0xEB, 0x0C, 0x03, 0x00, 0x2B, 0xEB, 0xDB, 0x00, 0x2F, 0xB6, 0xD0, 0xAF, 0xE7, 0x00, 0xBF, ++0x68, 0x65, 0x17, 0x00, 0x04, 0x05, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x54, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0x7C, 0xC0, 0x15, 0x00, 0x20, 0x01, 0x32, 0x40, 0x2D, 0xE9, 0xF8, 0x43, ++0x8D, 0x4F, 0x8E, 0x4B, 0xBC, 0x7A, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x80, 0x46, 0x94, 0xF8, 0xC3, 0x54, ++0x89, 0x46, 0x00, 0x2D, 0x40, 0xF0, 0x90, 0x80, 0xF8, 0x79, 0x88, 0x49, 0xBA, 0x88, 0x9E, 0x23, 0x03, 0xFB, 0x09, 0x03, ++0x01, 0xEB, 0x83, 0x03, 0xD3, 0xF8, 0x7C, 0x41, 0x23, 0x89, 0x9A, 0x42, 0x00, 0xF0, 0xA5, 0x80, 0xD2, 0x1A, 0x12, 0xF4, ++0x7C, 0x6F, 0xC2, 0xF3, 0x0B, 0x03, 0x38, 0xD1, 0xA6, 0x7A, 0x1E, 0x44, 0x06, 0xF0, 0x3F, 0x06, 0x01, 0x23, 0x04, 0xEB, ++0x86, 0x06, 0x84, 0xF8, 0x20, 0x31, 0x33, 0x69, 0x00, 0x2B, 0x6B, 0xD1, 0x8D, 0xB9, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, ++0x32, 0x30, 0x77, 0x49, 0x42, 0xF0, 0x20, 0x02, 0xC8, 0xF8, 0x60, 0x20, 0x23, 0xF0, 0xFF, 0x03, 0xD1, 0xF8, 0xE8, 0x22, ++0xA8, 0xF8, 0x32, 0x30, 0x40, 0x46, 0x03, 0x21, 0x90, 0x47, 0x71, 0x4B, 0x33, 0x61, 0xE3, 0x7A, 0x70, 0x4A, 0x01, 0x33, ++0x12, 0x68, 0xDB, 0xB2, 0xE3, 0x72, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xB1, 0x80, 0x01, 0x2B, 0x00, 0xF0, ++0xB9, 0x80, 0xC5, 0xF1, 0x01, 0x05, 0xED, 0xB2, 0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xFE, 0xFE, 0x28, 0x46, 0xBD, 0xE8, ++0xF8, 0x83, 0x40, 0xF2, 0xFE, 0x72, 0x93, 0x42, 0x40, 0xF2, 0x91, 0x80, 0x94, 0xF8, 0x20, 0x31, 0x13, 0xB1, 0x94, 0xF8, ++0x21, 0x31, 0x9B, 0xB3, 0x3B, 0x88, 0x1B, 0x05, 0x21, 0xD4, 0x7A, 0x88, 0x4F, 0xF4, 0x9E, 0x73, 0x03, 0xFB, 0x09, 0x03, ++0x01, 0xEB, 0x43, 0x03, 0xA3, 0xF8, 0xEA, 0x21, 0x15, 0xBB, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, 0x32, 0x30, 0x55, 0x49, ++0x42, 0xF0, 0x20, 0x02, 0x23, 0xF0, 0xFF, 0x03, 0xC8, 0xF8, 0x60, 0x20, 0xD1, 0xF8, 0xE8, 0x22, 0xA8, 0xF8, 0x32, 0x30, ++0x40, 0x46, 0x03, 0x21, 0x90, 0x47, 0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xCD, 0xFE, 0x01, 0x25, 0xCC, 0xE7, 0x4F, 0xF4, ++0x9E, 0x73, 0x03, 0xFB, 0x09, 0x03, 0x01, 0xEB, 0x43, 0x03, 0x7A, 0x88, 0xB3, 0xF8, 0xEA, 0x31, 0x93, 0x42, 0xD3, 0xD1, ++0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xBC, 0xFE, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0xC2, 0x69, 0x04, 0xF2, ++0xC4, 0x41, 0x92, 0x68, 0x01, 0x23, 0x04, 0xF1, 0x63, 0x00, 0xFF, 0xF7, 0x3B, 0xF8, 0x05, 0x46, 0xF8, 0x79, 0x3B, 0x49, ++0xBA, 0x88, 0x9E, 0x23, 0x03, 0xFB, 0x09, 0x03, 0x01, 0xEB, 0x83, 0x03, 0x01, 0x2D, 0xD3, 0xF8, 0x7C, 0x41, 0x23, 0x89, ++0x60, 0xD0, 0x9A, 0x42, 0x09, 0xD0, 0xD2, 0x1A, 0x12, 0xF4, 0x7C, 0x6F, 0x4F, 0xF0, 0x00, 0x05, 0xC2, 0xF3, 0x0B, 0x03, ++0x3F, 0xF4, 0x62, 0xAF, 0x99, 0xE7, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, 0x32, 0x30, 0x2E, 0x49, 0x42, 0xF0, 0x20, 0x02, ++0x23, 0xF0, 0xFF, 0x03, 0xC8, 0xF8, 0x60, 0x20, 0xD1, 0xF8, 0xE8, 0x22, 0xA8, 0xF8, 0x32, 0x30, 0x40, 0x46, 0x03, 0x21, ++0x90, 0x47, 0x23, 0x89, 0x01, 0x25, 0x01, 0x20, 0x28, 0x4A, 0xA1, 0x7A, 0x84, 0xF8, 0x20, 0x01, 0x12, 0x69, 0x62, 0x60, ++0x04, 0xEB, 0x81, 0x00, 0x02, 0x69, 0x12, 0xB1, 0xE2, 0x7A, 0x01, 0x3A, 0xE2, 0x72, 0x5A, 0x1C, 0x01, 0x31, 0xC2, 0xF3, ++0x0B, 0x02, 0x01, 0xF0, 0x3F, 0x01, 0x00, 0x23, 0x03, 0x61, 0x20, 0x46, 0x22, 0x81, 0xA1, 0x72, 0xFF, 0xF7, 0x4E, 0xFE, ++0x62, 0xE7, 0x18, 0x4A, 0xA3, 0xF1, 0x3F, 0x01, 0x89, 0xB2, 0xD2, 0xF8, 0xD8, 0x32, 0x20, 0x46, 0x98, 0x47, 0xBB, 0x88, ++0x21, 0x89, 0x5B, 0x1A, 0xC3, 0xF3, 0x0B, 0x03, 0x22, 0xE7, 0x40, 0x2B, 0x7F, 0xF6, 0x4C, 0xAF, 0x13, 0x49, 0x14, 0x48, ++0x40, 0xF2, 0xDB, 0x72, 0xF6, 0xF7, 0x5A, 0xFC, 0xE3, 0x7A, 0x43, 0xE7, 0x0E, 0x4A, 0x0B, 0x4B, 0x11, 0x69, 0xD3, 0xF8, ++0xE0, 0x31, 0x01, 0xF5, 0x43, 0x41, 0x04, 0xF5, 0x88, 0x70, 0x50, 0x31, 0x98, 0x47, 0x3A, 0xE7, 0x9A, 0x42, 0x7F, 0xF4, ++0x03, 0xAF, 0x00, 0x25, 0xB9, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x87, 0xA9, 0xDC, 0xFE, 0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x90, 0xC0, 0x15, 0x00, 0xC3, 0x7A, 0x03, 0xB9, 0x70, 0x47, 0x1A, 0x4B, 0x42, 0x68, 0x1B, 0x69, 0xC3, 0xF5, 0x43, 0x43, ++0x50, 0x33, 0xD3, 0x42, 0x10, 0xB5, 0x04, 0x46, 0x00, 0xD4, 0x10, 0xBD, 0x83, 0x7A, 0x1A, 0x1D, 0x50, 0xF8, 0x22, 0x20, ++0x42, 0xB9, 0x02, 0x89, 0x01, 0x33, 0x01, 0x32, 0x03, 0xF0, 0x3F, 0x03, 0xC2, 0xF3, 0x0B, 0x02, 0x83, 0x72, 0x02, 0x81, ++0x20, 0x46, 0xFF, 0xF7, 0xF1, 0xFD, 0xE3, 0x7A, 0x53, 0xB9, 0x0B, 0x4A, 0x0B, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, ++0x01, 0xF5, 0x43, 0x41, 0x04, 0xF5, 0x88, 0x70, 0x50, 0x31, 0x98, 0x47, 0x07, 0x48, 0x83, 0x6B, 0x00, 0x2B, 0xDC, 0xD0, ++0x04, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, 0x38, 0x31, 0x38, 0x30, 0x18, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, ++0x88, 0x1A, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x19, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x05, 0x46, ++0x04, 0xD0, 0x03, 0x88, 0x03, 0xF0, 0xEC, 0x03, 0xC4, 0x2B, 0x11, 0xD0, 0x15, 0x4F, 0x05, 0xF1, 0x04, 0x08, 0x07, 0xF5, ++0xA4, 0x56, 0xB9, 0x46, 0x3C, 0x46, 0x94, 0xF8, 0x64, 0x30, 0x1B, 0xB1, 0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x06, 0xD0, ++0x04, 0xF5, 0xA4, 0x64, 0xA6, 0x42, 0xF4, 0xD1, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x06, 0x22, 0x04, 0xF1, 0x5C, 0x01, ++0x40, 0x46, 0x08, 0xF0, 0x45, 0xFE, 0xA4, 0xEB, 0x07, 0x0A, 0x00, 0x28, 0xEE, 0xD1, 0x07, 0x49, 0x07, 0x48, 0xF6, 0xF7, ++0x4D, 0xF9, 0x05, 0xF1, 0x0A, 0x01, 0x09, 0xEB, 0x0A, 0x00, 0xFD, 0xF7, 0x49, 0xFD, 0xE7, 0xE7, 0x00, 0x88, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x20, 0xC1, 0x15, 0x00, 0xA8, 0xC0, 0x15, 0x00, 0x13, 0x4B, 0x93, 0xF8, 0x73, 0x20, 0x12, 0xB1, ++0x11, 0xF4, 0x00, 0x71, 0x00, 0xD0, 0x70, 0x47, 0x10, 0xB4, 0x42, 0x89, 0xB3, 0xF8, 0x6C, 0x40, 0x94, 0x42, 0x02, 0xD0, ++0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xB3, 0xF8, 0x6E, 0x40, 0x82, 0x89, 0x94, 0x42, 0xF7, 0xD1, 0xB3, 0xF8, 0x70, 0x40, ++0xC2, 0x89, 0x94, 0x42, 0xF2, 0xD1, 0x02, 0x88, 0x02, 0xF4, 0xA0, 0x52, 0xB2, 0xF5, 0x80, 0x5F, 0x06, 0xBF, 0x01, 0x22, ++0x83, 0xF8, 0x72, 0x20, 0x83, 0xF8, 0x72, 0x10, 0xE6, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0xF8, 0xB5, 0xBD, 0xF8, ++0x1C, 0x60, 0x06, 0x9D, 0xFF, 0x2A, 0x00, 0xEB, 0x06, 0x07, 0x2E, 0xD0, 0x14, 0x46, 0x82, 0x5D, 0x03, 0x3A, 0x12, 0x2A, ++0x18, 0xD8, 0xDF, 0xE8, 0x02, 0xF0, 0x2B, 0x17, 0x0A, 0x17, 0x30, 0x49, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, ++0x17, 0x17, 0x17, 0x17, 0x5C, 0x00, 0x1B, 0x78, 0x4B, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, ++0x62, 0x30, 0x02, 0x2B, 0x02, 0xD0, 0x7B, 0x78, 0x00, 0x2B, 0x6A, 0xD0, 0x01, 0x26, 0x2B, 0x88, 0xFF, 0x2B, 0x0A, 0xD0, ++0x44, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x57, 0xDB, 0x6F, 0xF0, 0xFF, 0x03, 0x2A, 0x88, 0x13, 0x43, ++0x2B, 0x80, 0x30, 0x46, 0xF8, 0xBD, 0x01, 0x26, 0x30, 0x46, 0xF8, 0xBD, 0x08, 0x23, 0x2B, 0x80, 0x00, 0x26, 0x00, 0x23, ++0xF2, 0xE7, 0x7E, 0x78, 0x00, 0x2E, 0x52, 0xD0, 0x01, 0x2E, 0xE1, 0xD1, 0x38, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x04, 0x23, 0x5E, 0x68, 0x16, 0xF0, 0x02, 0x06, 0xD9, 0xD0, 0xBE, 0x78, 0x16, 0xF0, 0x01, 0x06, 0x5A, 0xD0, 0x20, 0x46, ++0x00, 0x22, 0xFF, 0x21, 0xF9, 0xF7, 0xDC, 0xFC, 0x00, 0x26, 0xCE, 0xE7, 0x89, 0x1B, 0x03, 0x29, 0x2A, 0xDD, 0x1B, 0x78, ++0xFF, 0x2B, 0xC7, 0xD0, 0x29, 0x4A, 0x7E, 0x78, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, ++0x1E, 0x43, 0xBD, 0xD1, 0x06, 0x23, 0x2B, 0x80, 0xD1, 0xE7, 0x7B, 0x78, 0x01, 0x2B, 0x36, 0xD0, 0x02, 0x2B, 0xB5, 0xD1, ++0x22, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x23, 0x5E, 0x68, 0x16, 0xF0, 0x24, 0x06, 0xAD, 0xD0, 0x97, 0xF9, ++0x02, 0x30, 0xB9, 0x78, 0x00, 0x2B, 0x07, 0xDB, 0x0A, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x03, 0x01, 0xF9, 0xF7, 0xAE, 0xFC, ++0x00, 0x26, 0xA0, 0xE7, 0x00, 0x26, 0x9E, 0xE7, 0x17, 0x49, 0x18, 0x48, 0x40, 0xF6, 0x78, 0x12, 0xF6, 0xF7, 0x00, 0xFB, ++0x6F, 0xF0, 0xFF, 0x03, 0xA0, 0xE7, 0x0B, 0x23, 0x2B, 0x80, 0x01, 0x26, 0xA7, 0xE7, 0x10, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x04, 0x23, 0x5B, 0x68, 0x9B, 0x07, 0x89, 0xD5, 0xB9, 0x78, 0x01, 0x29, 0x86, 0xD8, 0x20, 0x46, 0xFF, 0x22, ++0xF9, 0xF7, 0x8E, 0xFC, 0x81, 0xE7, 0x07, 0xF1, 0x0A, 0x01, 0xB8, 0x1C, 0xD2, 0xF7, 0xB6, 0xFE, 0x00, 0x26, 0x7A, 0xE7, ++0xFF, 0x22, 0x20, 0x46, 0x11, 0x46, 0xF9, 0xF7, 0x81, 0xFC, 0x74, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xBC, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x89, 0xB0, 0x1F, 0x46, ++0x10, 0x9E, 0x34, 0x78, 0xFF, 0x2C, 0x47, 0xD0, 0x69, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x55, 0x00, 0xF0, ++0xFC, 0x04, 0x80, 0x2C, 0x95, 0xF8, 0x62, 0x80, 0x46, 0xD0, 0x0F, 0xD8, 0x40, 0x2C, 0x6B, 0xD0, 0x2C, 0xD9, 0x50, 0x2C, ++0x4F, 0xF0, 0x01, 0x04, 0x04, 0xD1, 0x13, 0x9A, 0x14, 0x70, 0x12, 0x9A, 0x04, 0x23, 0x13, 0x80, 0x20, 0x46, 0x09, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0xC0, 0x2C, 0x21, 0xD0, 0x10, 0xD9, 0xD0, 0x2C, 0x15, 0xD1, 0x13, 0x9B, 0x11, 0x98, 0xCD, 0xE9, ++0x01, 0x23, 0x12, 0x9B, 0x00, 0x93, 0x3A, 0x46, 0x33, 0x46, 0xFF, 0xF7, 0x11, 0xFF, 0x04, 0x46, 0x20, 0x46, 0x09, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0xA0, 0x2C, 0x0D, 0xD0, 0xB0, 0x2C, 0x02, 0xD1, 0xFC, 0xF7, 0xBA, 0xFA, 0x40, 0xB1, 0x01, 0x24, ++0x20, 0x46, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x00, 0xF0, 0xDC, 0x00, 0x10, 0x28, 0xF6, 0xD1, 0xB8, 0xF1, 0x00, 0x0F, ++0xF3, 0xD1, 0x12, 0x9A, 0x06, 0x23, 0x13, 0x80, 0x01, 0x24, 0xCF, 0xE7, 0x00, 0xF0, 0xFC, 0x00, 0xB0, 0x28, 0x72, 0xD0, ++0x28, 0xD8, 0x40, 0x28, 0x2A, 0xD0, 0x80, 0x28, 0xE5, 0xD1, 0x00, 0x25, 0x04, 0x20, 0x05, 0x91, 0xF4, 0xF7, 0x34, 0xFC, ++0x01, 0x28, 0x05, 0x99, 0x0E, 0xD1, 0x13, 0x9A, 0x3D, 0x4B, 0x10, 0x70, 0x12, 0x98, 0x1B, 0x68, 0x3A, 0x4D, 0x04, 0x22, ++0x02, 0x80, 0x93, 0xF8, 0x6E, 0x41, 0x34, 0x70, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x55, 0xFF, 0x2F, 0xCC, 0xD0, ++0x95, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xC8, 0xD0, 0x34, 0x4B, 0x30, 0x78, 0xD3, 0xF8, 0x54, 0x31, 0x11, 0x9A, 0x98, 0x47, ++0x01, 0x24, 0xA1, 0xE7, 0xD0, 0x28, 0xA8, 0xD0, 0x01, 0x24, 0xBD, 0xE7, 0x2F, 0x4B, 0x9A, 0x7C, 0x00, 0x2A, 0xB8, 0xD0, ++0x2E, 0x4A, 0x12, 0x68, 0x12, 0x78, 0x01, 0x3A, 0x01, 0x2A, 0xB2, 0xD8, 0x9D, 0x68, 0x00, 0x2D, 0xAF, 0xD0, 0x18, 0x39, ++0x2A, 0x4F, 0x1F, 0xFA, 0x81, 0xF8, 0x01, 0x24, 0x02, 0xE0, 0x2D, 0x68, 0x00, 0x2D, 0x87, 0xD0, 0x95, 0xF8, 0x62, 0x30, ++0x02, 0x2B, 0xF8, 0xD1, 0x95, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF4, 0xD0, 0x95, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0xF0, 0xD1, ++0x11, 0x9B, 0xB7, 0xF8, 0x00, 0x90, 0x03, 0xF1, 0x18, 0x00, 0x0D, 0xF1, 0x1E, 0x02, 0x41, 0x46, 0xF4, 0xF7, 0xFA, 0xFF, ++0xA9, 0xF1, 0x24, 0x01, 0x06, 0x46, 0x89, 0xB2, 0x0D, 0xF1, 0x1F, 0x02, 0x19, 0x48, 0xF4, 0xF7, 0xF1, 0xFF, 0x9D, 0xF8, ++0x1E, 0x30, 0x18, 0x49, 0x02, 0x36, 0x81, 0x46, 0x07, 0x22, 0x30, 0x46, 0x53, 0xB9, 0x11, 0x9B, 0x28, 0x46, 0x03, 0xF1, ++0x0A, 0x01, 0xE1, 0xF7, 0xED, 0xFE, 0x00, 0x24, 0xCD, 0xE7, 0xFC, 0xF7, 0x2F, 0xFA, 0x74, 0xE7, 0x08, 0xF0, 0x7C, 0xFC, ++0x00, 0x28, 0xC6, 0xD0, 0x9D, 0xF8, 0x1F, 0x30, 0x9D, 0xF8, 0x1E, 0x20, 0x9A, 0x42, 0xC0, 0xD1, 0x09, 0xF1, 0x02, 0x01, ++0x30, 0x46, 0x08, 0xF0, 0x6F, 0xFC, 0x00, 0x28, 0xE3, 0xD0, 0xB8, 0xE7, 0x18, 0x88, 0x17, 0x00, 0xA8, 0xBA, 0x17, 0x00, ++0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x14, 0x2C, 0x17, 0x00, 0x38, 0x2A, 0x17, 0x00, ++0x54, 0xBF, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xC6, 0x69, 0x8D, 0xB0, 0xD6, 0xF8, 0x08, 0x90, 0x01, 0x23, 0x8D, 0xF8, ++0x24, 0x30, 0x04, 0x46, 0xB9, 0xF8, 0x00, 0x00, 0x10, 0xF4, 0x80, 0x60, 0x40, 0xF0, 0x8B, 0x80, 0xB9, 0xF8, 0x16, 0x70, ++0x17, 0xF0, 0x0F, 0x07, 0x00, 0xF0, 0x89, 0x80, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB9, 0xF8, 0x00, 0x30, 0x98, 0xF8, ++0x08, 0x20, 0x04, 0x92, 0xDF, 0xF8, 0x08, 0xE2, 0xB4, 0xF8, 0x30, 0xA0, 0xBD, 0xF8, 0x10, 0x10, 0xAD, 0xF8, 0x16, 0x30, ++0x4F, 0xF0, 0xFF, 0x0C, 0x18, 0x46, 0xAD, 0xF8, 0x26, 0xC0, 0xB3, 0x68, 0xDE, 0xF8, 0xE0, 0x92, 0x07, 0x93, 0x0D, 0xF1, ++0x25, 0x0C, 0x01, 0x93, 0xCD, 0xF8, 0x0C, 0xC0, 0x72, 0x4B, 0x06, 0x91, 0x0D, 0xF1, 0x26, 0x0C, 0x0A, 0x46, 0x00, 0x93, ++0x51, 0x46, 0x8D, 0xF8, 0x25, 0xB0, 0x80, 0xB2, 0xCD, 0xF8, 0x08, 0xC0, 0x2B, 0x46, 0xC8, 0x47, 0xBD, 0xF8, 0x26, 0x10, ++0xFF, 0x29, 0x00, 0xF0, 0x90, 0x80, 0x0A, 0xF1, 0x0C, 0x03, 0x9B, 0xB2, 0x0A, 0x22, 0x4F, 0xF4, 0x20, 0x50, 0xF4, 0xF7, ++0xB5, 0xF8, 0x59, 0x46, 0x81, 0x46, 0x0A, 0xA8, 0xD2, 0xF7, 0xFA, 0xFC, 0x9D, 0xF8, 0x25, 0x30, 0xD3, 0x46, 0x63, 0xB9, ++0x61, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xAE, 0x80, 0x04, 0x9B, 0x06, 0x9F, 0xAA, 0xEB, ++0x03, 0x0B, 0x1F, 0xFA, 0x8B, 0xFA, 0x4B, 0x46, 0x3A, 0x46, 0x51, 0x46, 0x23, 0xF8, 0x0C, 0xAB, 0x30, 0x46, 0xE6, 0xF7, ++0x35, 0xFD, 0x98, 0xF8, 0x0A, 0x30, 0x89, 0xF8, 0x08, 0x30, 0xBD, 0xF8, 0x16, 0x30, 0x89, 0xF8, 0x07, 0x50, 0xA9, 0xF8, ++0x02, 0x30, 0x94, 0xF9, 0x41, 0x50, 0xD2, 0xF7, 0x75, 0xFD, 0x0A, 0x9B, 0x89, 0xF8, 0x06, 0x30, 0x1A, 0x0C, 0x89, 0xF8, ++0x09, 0x50, 0xA9, 0xF8, 0x04, 0x20, 0x48, 0x46, 0xF4, 0xF7, 0xAE, 0xF8, 0xBD, 0xF8, 0x26, 0x30, 0x04, 0x2B, 0x10, 0xD1, ++0xE1, 0x6B, 0xB9, 0xF8, 0x04, 0x30, 0x62, 0x6B, 0x07, 0x98, 0xC1, 0xF3, 0x03, 0x11, 0x02, 0x91, 0x99, 0xF9, 0x09, 0x10, ++0x01, 0x91, 0x99, 0xF8, 0x06, 0x10, 0x00, 0x91, 0x59, 0x46, 0x07, 0xF0, 0x15, 0xFB, 0x00, 0x20, 0x0D, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x0D, 0x46, 0xD2, 0xF7, 0x4E, 0xFD, 0xFF, 0x2D, 0x38, 0xD0, 0x3C, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x31, 0xD0, ++0x99, 0xF8, 0x04, 0x30, 0xDF, 0xF8, 0xEC, 0x80, 0xDA, 0x07, 0x10, 0xD4, 0x98, 0xF8, 0x0A, 0x00, 0x37, 0x4A, 0xB9, 0xF8, ++0x04, 0x10, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0xF3, 0x5C, 0x33, 0x98, 0x18, 0x9B, 0x5A, 0x8B, 0x42, 0x45, 0xD0, ++0xFF, 0x23, 0x88, 0xF8, 0x0A, 0x30, 0x22, 0x8E, 0x30, 0x48, 0x09, 0xAB, 0x49, 0x46, 0x02, 0xF0, 0x81, 0xFB, 0x83, 0x46, ++0x00, 0x28, 0x3F, 0xF4, 0x50, 0xAF, 0x9D, 0xF8, 0x24, 0x00, 0x00, 0x28, 0x3F, 0xF4, 0x48, 0xAF, 0x2A, 0x4B, 0x20, 0x46, ++0xD3, 0xF8, 0xE4, 0x32, 0x03, 0x21, 0x98, 0x47, 0x9D, 0xF8, 0x24, 0x00, 0x3E, 0xE7, 0x8D, 0xF8, 0x24, 0x00, 0xF0, 0xE7, ++0xDF, 0xF8, 0x8C, 0x80, 0xE1, 0xE7, 0x63, 0x6D, 0x13, 0xF4, 0xC0, 0x6F, 0x1E, 0xD1, 0x1E, 0x4B, 0x9B, 0x68, 0x9B, 0xB3, ++0xB9, 0xF8, 0x04, 0x10, 0x01, 0xE0, 0x1B, 0x68, 0xB3, 0xB1, 0xB3, 0xF8, 0x5C, 0x20, 0x8A, 0x42, 0xF9, 0xD1, 0xB3, 0xF8, ++0x5E, 0x00, 0xB9, 0xF8, 0x06, 0x20, 0x90, 0x42, 0xF3, 0xD1, 0xB3, 0xF8, 0x60, 0x00, 0xB9, 0xF8, 0x08, 0x20, 0x90, 0x42, ++0xED, 0xD1, 0x93, 0xF8, 0x63, 0x30, 0xDF, 0xF8, 0x4C, 0x80, 0x88, 0xF8, 0x0A, 0x30, 0xBE, 0xE7, 0xFF, 0x23, 0xF8, 0xE7, ++0x42, 0x88, 0xB9, 0xF8, 0x06, 0x30, 0x9A, 0x42, 0xB4, 0xD1, 0x82, 0x88, 0xB9, 0xF8, 0x08, 0x30, 0x9A, 0x42, 0xAF, 0xD1, ++0xB1, 0xE7, 0x04, 0x9A, 0x93, 0x07, 0x3F, 0xF4, 0x4E, 0xAF, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0x97, 0x22, 0xF6, 0xF7, ++0xE7, 0xF8, 0x46, 0xE7, 0x2B, 0x46, 0xE0, 0xE7, 0xBA, 0xDE, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD0, 0xC0, 0x15, 0x00, ++0x1D, 0x48, 0x70, 0xB5, 0x00, 0xF1, 0x10, 0x06, 0xF4, 0xF7, 0x5E, 0xFC, 0x30, 0x46, 0x1B, 0x4C, 0xF4, 0xF7, 0x5A, 0xFC, ++0x04, 0xF5, 0x92, 0x55, 0x21, 0x46, 0x30, 0x46, 0x04, 0xF5, 0x92, 0x74, 0xF4, 0xF7, 0x56, 0xFC, 0xAC, 0x42, 0xF7, 0xD1, ++0x15, 0x48, 0xF4, 0xF7, 0x4D, 0xFC, 0x15, 0x48, 0xF4, 0xF7, 0x4A, 0xFC, 0x14, 0x49, 0x12, 0x48, 0xF4, 0xF7, 0x4A, 0xFC, ++0x13, 0x49, 0x10, 0x48, 0xF4, 0xF7, 0x46, 0xFC, 0x12, 0x49, 0x0E, 0x48, 0xF4, 0xF7, 0x42, 0xFC, 0x11, 0x4A, 0x12, 0x4B, ++0x12, 0x48, 0x4F, 0xF6, 0xFF, 0x71, 0xA2, 0xF8, 0x66, 0x10, 0x03, 0xF5, 0x70, 0x51, 0x00, 0x22, 0x03, 0xF8, 0x34, 0x2C, ++0x1A, 0x81, 0x43, 0xE9, 0x10, 0x03, 0x43, 0xF8, 0x30, 0x3C, 0x50, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0x70, 0xBD, 0x00, 0xBF, ++0xE8, 0xDE, 0x17, 0x00, 0x70, 0xCC, 0x17, 0x00, 0x00, 0xDF, 0x17, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x28, 0xDF, 0x17, 0x00, ++0x6C, 0xDF, 0x17, 0x00, 0xB0, 0xDF, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x24, 0x64, 0x18, 0x00, 0x75, 0xD2, 0x14, 0x00, ++0x70, 0xB5, 0x90, 0xF9, 0x00, 0x30, 0x82, 0xB0, 0x00, 0x2B, 0x01, 0xF0, 0x78, 0x02, 0x05, 0x46, 0xB8, 0xBF, 0x1A, 0x23, ++0x4F, 0xF0, 0x00, 0x00, 0xA8, 0xBF, 0x18, 0x23, 0x08, 0x2A, 0xAD, 0xF8, 0x06, 0x00, 0x19, 0xD0, 0x01, 0xF0, 0x7C, 0x01, ++0x04, 0x29, 0x1F, 0xD0, 0x06, 0x33, 0xDC, 0xB2, 0x2E, 0x19, 0x31, 0x46, 0x02, 0x22, 0x0D, 0xF1, 0x06, 0x00, 0x08, 0xF0, ++0xF3, 0xFA, 0x28, 0x79, 0x10, 0xF0, 0x01, 0x00, 0x0B, 0xD0, 0xBD, 0xF8, 0x06, 0x00, 0xA0, 0xF5, 0xC1, 0x60, 0xB0, 0xFA, ++0x80, 0xF0, 0x40, 0x09, 0x02, 0xB0, 0x70, 0xBD, 0x08, 0x33, 0xDB, 0xB2, 0xE6, 0xE7, 0xBD, 0xF8, 0x06, 0x30, 0x08, 0x2B, ++0x04, 0xD0, 0x01, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x04, 0x33, 0xDD, 0xE7, 0xF3, 0x7A, 0x02, 0x2B, 0xEE, 0xD0, 0x11, 0x2B, ++0xF5, 0xD1, 0xB2, 0x78, 0xA3, 0x1C, 0x02, 0xF0, 0x0F, 0x04, 0x03, 0xEB, 0x84, 0x04, 0x2C, 0x44, 0x14, 0xF8, 0x04, 0x3C, ++0xEF, 0x2B, 0xEA, 0xD1, 0x14, 0xF8, 0x03, 0x3C, 0xFF, 0x2B, 0xE6, 0xD1, 0x14, 0xF8, 0x02, 0x3C, 0xFF, 0x2B, 0xE2, 0xD1, ++0x14, 0xF8, 0x01, 0x0C, 0xFA, 0x38, 0x18, 0xBF, 0x01, 0x20, 0xD3, 0xE7, 0x70, 0xB5, 0x90, 0xF9, 0x00, 0x30, 0x82, 0xB0, ++0x00, 0x2B, 0x01, 0xF0, 0x78, 0x05, 0x4F, 0xF0, 0x00, 0x06, 0xB4, 0xBF, 0x1A, 0x23, 0x18, 0x23, 0x08, 0x2D, 0x14, 0x46, ++0xAD, 0xF8, 0x06, 0x60, 0x13, 0xD0, 0x01, 0xF0, 0x7C, 0x01, 0x04, 0x29, 0x12, 0xD0, 0x99, 0x1D, 0x50, 0xFA, 0x81, 0xF1, ++0x02, 0x22, 0x0D, 0xF1, 0x06, 0x00, 0x08, 0xF0, 0x9F, 0xFA, 0xBD, 0xF8, 0x06, 0x10, 0x48, 0xF6, 0x88, 0x63, 0x99, 0x42, ++0x06, 0xD0, 0x02, 0xB0, 0x70, 0xBD, 0x08, 0x33, 0xDB, 0xB2, 0xEC, 0xE7, 0x04, 0x33, 0xEA, 0xE7, 0x02, 0x48, 0x22, 0x46, ++0xF5, 0xF7, 0x6E, 0xFD, 0x02, 0xB0, 0x70, 0xBD, 0xEC, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x45, 0x6D, 0x2D, 0xED, ++0x02, 0x8B, 0xAF, 0x04, 0x87, 0xB0, 0x04, 0x46, 0x1F, 0xD4, 0xC1, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9E, 0x07, 0x03, 0xD5, ++0x05, 0xF0, 0x3C, 0x03, 0x3C, 0x2B, 0x16, 0xD0, 0xBD, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x71, 0xD0, 0xBC, 0x4E, 0xBD, 0x4D, ++0xB3, 0x72, 0x20, 0x46, 0xD5, 0xF8, 0xE4, 0x32, 0x80, 0x21, 0x98, 0x47, 0x01, 0x27, 0xD5, 0xF8, 0x38, 0x31, 0xB9, 0x48, ++0x98, 0x47, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0xD4, 0xF8, 0x1C, 0xA0, 0xB2, 0x4E, ++0xDA, 0xF8, 0x08, 0x80, 0x00, 0x23, 0xB8, 0xF8, 0x00, 0x90, 0x23, 0x66, 0x40, 0x46, 0xFF, 0x23, 0x73, 0x72, 0xB3, 0x72, ++0xFE, 0xF7, 0xE6, 0xFD, 0xA8, 0x01, 0x50, 0xD5, 0xC5, 0xF3, 0xC9, 0x37, 0xDF, 0xF8, 0xBC, 0xB2, 0x10, 0x3F, 0xFF, 0xB2, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x93, 0xF8, 0x25, 0x20, 0x00, 0x2A, 0x39, 0xD0, 0x93, 0xF8, 0x22, 0x10, ++0xA5, 0x48, 0xD3, 0xF8, 0xB0, 0x30, 0x77, 0x72, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x02, 0xB5, 0x61, 0x92, 0xF8, ++0x62, 0x20, 0xB1, 0x72, 0x02, 0x2A, 0x00, 0x93, 0x52, 0xD0, 0x09, 0xF4, 0x40, 0x73, 0xB3, 0xF5, 0x40, 0x7F, 0x03, 0xD1, ++0x23, 0x6E, 0x43, 0xF0, 0x04, 0x03, 0x23, 0x66, 0x33, 0x88, 0x5B, 0x04, 0x00, 0xF1, 0x90, 0x80, 0x98, 0x4B, 0x1B, 0x68, ++0x1B, 0x78, 0x01, 0x2B, 0x09, 0xF0, 0x0C, 0x03, 0x00, 0xF0, 0x90, 0x80, 0x08, 0x2B, 0x00, 0xF0, 0x97, 0x80, 0x4F, 0xF4, ++0x1E, 0x72, 0x02, 0xFB, 0x07, 0xB2, 0x92, 0xF8, 0x5D, 0x22, 0x01, 0x2A, 0x40, 0xF2, 0xE7, 0x80, 0x04, 0x2B, 0x00, 0xF0, ++0xFA, 0x80, 0x08, 0x2B, 0x00, 0xF0, 0x97, 0x80, 0x00, 0x2B, 0x33, 0xD0, 0x85, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x01, 0xD0, ++0x85, 0x4D, 0x8F, 0xE7, 0x84, 0x4D, 0x00, 0x27, 0x93, 0xE7, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x9D, 0xFB, 0x19, 0xF0, ++0x0C, 0x0F, 0x0B, 0xD1, 0xFF, 0xF7, 0xDA, 0xF8, 0x00, 0x28, 0xEB, 0xD0, 0x33, 0x88, 0x59, 0x04, 0x55, 0xD5, 0x05, 0xF0, ++0x7C, 0x03, 0x04, 0x2B, 0x4B, 0xD0, 0x40, 0x46, 0x21, 0x46, 0xFF, 0xF7, 0x4D, 0xFB, 0x78, 0x4D, 0x07, 0x46, 0x75, 0x4B, ++0x1B, 0x7C, 0xFF, 0x2B, 0x3F, 0xF4, 0x77, 0xAF, 0x00, 0x2F, 0x7F, 0xF4, 0x74, 0xAF, 0x6B, 0xE7, 0x96, 0xF8, 0x24, 0x30, ++0xDA, 0x07, 0xA8, 0xD4, 0x06, 0xF1, 0x24, 0x00, 0xF2, 0xF7, 0xB8, 0xFE, 0xF0, 0x72, 0xA2, 0xE7, 0x19, 0xF4, 0x00, 0x6F, ++0x00, 0xF0, 0xCF, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x72, 0x88, 0xB3, 0xF8, 0xE8, 0x31, 0x93, 0x42, ++0xBE, 0xD0, 0x96, 0xF8, 0x30, 0x10, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB7, 0x8D, 0x07, 0xA7, 0xF8, 0xE8, 0x21, ++0x0A, 0xD5, 0x35, 0x6A, 0xD6, 0xE9, 0x04, 0x01, 0xD5, 0xE9, 0x10, 0x23, 0x8B, 0x42, 0x08, 0xBF, 0x82, 0x42, 0xAB, 0xD2, ++0xC5, 0xE9, 0x10, 0x01, 0x5F, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD1, 0x98, 0xF8, 0x00, 0x30, 0x80, 0x2B, ++0x00, 0xF0, 0xCF, 0x80, 0x71, 0x7A, 0x57, 0x4D, 0x20, 0x46, 0xFF, 0xF7, 0x17, 0xFD, 0x07, 0x46, 0xB9, 0xE7, 0x29, 0x46, ++0x40, 0x46, 0xFE, 0xF7, 0x39, 0xFB, 0x00, 0x28, 0xAD, 0xD0, 0xFF, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x0B, 0xFD, 0x4F, 0x4D, ++0x07, 0x46, 0xAC, 0xE7, 0xB1, 0x69, 0x40, 0x46, 0xFE, 0xF7, 0x2C, 0xFB, 0x00, 0x28, 0x7F, 0xF4, 0x69, 0xAF, 0x83, 0xE7, ++0x08, 0x2B, 0x7F, 0xF4, 0x70, 0xAF, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x73, 0xFE, 0x00, 0x28, 0x3F, 0xF4, 0x7A, 0xAF, ++0x3B, 0x46, 0x22, 0x8E, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xC0, 0xFE, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, ++0x93, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x40, 0xF2, 0x87, 0x80, 0x41, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x73, 0xB1, 0xB3, 0x7A, ++0x3C, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x13, 0x93, 0xF8, 0x62, 0x20, 0x2A, 0xB9, 0xD3, 0xF8, 0x90, 0x21, ++0x92, 0x78, 0x01, 0x2A, 0x00, 0xF0, 0x8D, 0x80, 0x19, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x7F, 0xF4, 0x53, 0xAF, 0x09, 0xF0, ++0x80, 0x03, 0x00, 0x2B, 0x14, 0xBF, 0x4F, 0xF0, 0x01, 0x08, 0x4F, 0xF0, 0x00, 0x08, 0x71, 0xD0, 0x96, 0xF8, 0x30, 0x30, ++0x1A, 0x07, 0x40, 0xF1, 0x9A, 0x80, 0xF2, 0x79, 0x4F, 0xF4, 0x9E, 0x73, 0xF5, 0x32, 0x03, 0xFB, 0x07, 0x23, 0x0B, 0xEB, ++0x43, 0x03, 0x19, 0xF4, 0x00, 0x6F, 0x72, 0x88, 0x03, 0xD0, 0x19, 0x88, 0x91, 0x42, 0x3F, 0xF4, 0x35, 0xAF, 0x1F, 0x49, ++0x1A, 0x80, 0x0B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x04, 0xD5, 0x05, 0xF0, 0x3C, 0x05, 0x3C, 0x2D, 0x00, 0xF0, 0x8E, 0x80, ++0x1C, 0x4D, 0x39, 0x46, 0xD5, 0xF8, 0xC4, 0x32, 0x42, 0x46, 0x20, 0x46, 0x98, 0x47, 0x07, 0x46, 0x41, 0xE7, 0x00, 0x9A, ++0x00, 0x2A, 0x3F, 0xF4, 0x15, 0xAF, 0x92, 0xF8, 0x60, 0x20, 0x01, 0x3A, 0x01, 0x2A, 0x3F, 0xF6, 0x0F, 0xAF, 0x19, 0xF4, ++0x80, 0x4F, 0x3F, 0xF4, 0x0B, 0xAF, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x07, 0xB2, 0x02, 0x21, 0x82, 0xF8, 0x5D, 0x12, ++0x02, 0xE7, 0x09, 0xF0, 0xFC, 0x09, 0xB9, 0xF1, 0x84, 0x0F, 0x7F, 0xF4, 0x05, 0xAF, 0x0A, 0x4D, 0x41, 0x46, 0xD5, 0xF8, ++0xD0, 0x32, 0x38, 0x46, 0x98, 0x47, 0x05, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x7F, 0xF4, 0x90, 0xAE, 0xFF, 0xE6, 0x72, 0x88, ++0x37, 0xE7, 0x00, 0xBF, 0x34, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0xE8, 0xDE, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x00, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0x75, 0xAF, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, 0x01, 0x2B, 0x3F, 0xF6, 0x6F, 0xAF, ++0x08, 0x23, 0xC0, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x03, 0xF5, 0xF4, 0x73, 0x93, 0xE7, 0x98, 0xF8, ++0x01, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x2C, 0xAF, 0xCA, 0xE6, 0xD3, 0xF8, 0xCC, 0x21, 0x12, 0xF0, 0x0C, 0x0F, 0x3F, 0xF4, ++0x6D, 0xAF, 0x98, 0xF8, 0x04, 0x20, 0xD0, 0x07, 0x3F, 0xF5, 0x68, 0xAF, 0xE2, 0x6B, 0x12, 0xF0, 0x0C, 0x0F, 0x3F, 0xF4, ++0x63, 0xAF, 0xD3, 0xF8, 0x90, 0x20, 0x01, 0x32, 0xC3, 0xF8, 0x90, 0x20, 0x98, 0xF8, 0x01, 0x20, 0x11, 0x07, 0x7F, 0xF5, ++0x59, 0xAF, 0xD3, 0xF8, 0x94, 0x20, 0x01, 0x32, 0xC3, 0xF8, 0x94, 0x20, 0x52, 0xE7, 0xF1, 0x79, 0x38, 0x46, 0xE9, 0xF7, ++0x33, 0xFB, 0x00, 0x28, 0x3F, 0xF4, 0x5F, 0xAF, 0x61, 0x4D, 0x39, 0x46, 0xD5, 0xF8, 0xD4, 0x32, 0x20, 0x46, 0x98, 0x47, ++0x07, 0x46, 0xBC, 0xE6, 0x33, 0x6A, 0x01, 0x93, 0x93, 0xF8, 0x60, 0x10, 0x01, 0x29, 0x03, 0xF1, 0x64, 0x09, 0x64, 0xD0, ++0x00, 0x29, 0x40, 0xF0, 0x97, 0x80, 0x08, 0xF1, 0x0E, 0x03, 0x5B, 0x00, 0xDA, 0xE9, 0x01, 0x25, 0x58, 0x19, 0x08, 0xEE, ++0x10, 0x0A, 0x00, 0x2A, 0x52, 0xD0, 0xDA, 0xF8, 0x0C, 0x20, 0x20, 0x8E, 0x01, 0x32, 0x52, 0x1B, 0x04, 0x30, 0xD2, 0x1A, ++0xC0, 0x1A, 0x93, 0xB2, 0x82, 0xB2, 0x9A, 0x42, 0x00, 0x92, 0x28, 0xBF, 0x1A, 0x46, 0x15, 0x46, 0x01, 0x29, 0x2F, 0xD0, ++0x00, 0x29, 0x50, 0xD0, 0x03, 0x29, 0x66, 0xD0, 0x18, 0xEE, 0x10, 0x0A, 0x29, 0x46, 0xF3, 0xF7, 0x2F, 0xFB, 0x4F, 0xF0, ++0xFF, 0x33, 0x18, 0xEE, 0x10, 0x0A, 0x03, 0x22, 0x29, 0x46, 0xD6, 0xF7, 0x29, 0xFF, 0xDA, 0xF8, 0x04, 0x30, 0x23, 0xB1, ++0x00, 0x9A, 0x55, 0x1B, 0xAD, 0xB2, 0x00, 0x2D, 0x67, 0xD1, 0x01, 0x9B, 0x93, 0xF8, 0x60, 0x30, 0x13, 0xB1, 0x03, 0x2B, ++0x7F, 0xF4, 0x2C, 0xAF, 0x03, 0x20, 0xD6, 0xF7, 0x4F, 0xFF, 0x3A, 0x4B, 0x98, 0x42, 0x01, 0x46, 0x3F, 0xD1, 0x63, 0x6D, ++0x23, 0xF0, 0x7C, 0x03, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xF0, 0x04, 0x03, 0x63, 0x65, 0x1B, 0xE7, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x07, 0xB2, 0x02, 0xAB, 0x32, 0x49, 0x26, 0x32, 0x48, 0x46, 0xF3, 0xF7, 0xDA, 0xF8, 0x10, 0x21, 0x02, 0xA8, ++0xF3, 0xF7, 0x9A, 0xFA, 0x01, 0x9B, 0x93, 0xF8, 0x60, 0x10, 0xBD, 0xE7, 0x22, 0x8E, 0x04, 0x32, 0xD3, 0x1A, 0x9D, 0xB2, ++0xB6, 0xE7, 0xD6, 0xE9, 0x04, 0x53, 0x28, 0x48, 0x2A, 0x0C, 0x42, 0xEA, 0x03, 0x42, 0x08, 0xF1, 0x10, 0x03, 0x02, 0x60, ++0x85, 0x80, 0x5B, 0x00, 0x94, 0xE7, 0x32, 0x8A, 0x73, 0x8A, 0xAD, 0xF8, 0x08, 0x20, 0x49, 0x46, 0x05, 0x22, 0x0D, 0xF1, ++0x0B, 0x00, 0x8D, 0xF8, 0x0A, 0x30, 0x08, 0xF0, 0x1F, 0xF8, 0x08, 0x21, 0x02, 0xA8, 0xF3, 0xF7, 0x75, 0xFA, 0x01, 0x9B, ++0x93, 0xF8, 0x60, 0x10, 0x9A, 0xE7, 0x1A, 0x48, 0xF5, 0xF7, 0xF4, 0xFA, 0x0A, 0xE6, 0x32, 0x8A, 0x73, 0x8A, 0xAD, 0xF8, ++0x08, 0x20, 0x49, 0x46, 0x0D, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x8D, 0xF8, 0x0A, 0x30, 0x08, 0xF0, 0x07, 0xF8, 0x02, 0xA8, ++0x10, 0x21, 0xF3, 0xF7, 0x5D, 0xFA, 0x87, 0xE7, 0x03, 0x29, 0x3F, 0xF4, 0x66, 0xAF, 0x00, 0x23, 0x66, 0xE7, 0xD3, 0xF8, ++0x08, 0x90, 0x29, 0x46, 0x48, 0x46, 0xF3, 0xF7, 0xB1, 0xFA, 0x03, 0x20, 0xD6, 0xF7, 0xE8, 0xFE, 0x20, 0x21, 0xC0, 0x43, ++0xF3, 0xF7, 0x64, 0xF8, 0x29, 0x46, 0x03, 0x46, 0x03, 0x22, 0x48, 0x46, 0xD6, 0xF7, 0xA6, 0xFE, 0x83, 0xE7, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x1C, 0xDF, 0x44, 0x21, 0x88, 0x34, 0x17, 0x00, 0x00, 0xC1, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x00, 0xEB, 0x81, 0x04, 0xD4, 0xF8, 0x7C, 0x61, 0x16, 0xB1, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x15, 0x48, 0x0D, 0x46, ++0x17, 0x46, 0xF4, 0xF7, 0x1B, 0xF9, 0x80, 0x46, 0x00, 0x28, 0xF4, 0xD0, 0x31, 0x46, 0x4F, 0xF4, 0x92, 0x72, 0xD1, 0xF7, ++0x3B, 0xF8, 0x07, 0xF0, 0x3F, 0x02, 0x0F, 0x4B, 0x88, 0xF8, 0x0C, 0x50, 0x88, 0xF8, 0x0A, 0x20, 0x19, 0x69, 0x0D, 0x4B, ++0xC8, 0xF8, 0x04, 0x10, 0xD3, 0xF8, 0xDC, 0x22, 0xA8, 0xF8, 0x08, 0x70, 0xC8, 0xE9, 0x45, 0x28, 0x01, 0xF5, 0x43, 0x41, ++0xC4, 0xF8, 0x7C, 0x81, 0x08, 0xF5, 0x88, 0x70, 0xD3, 0xF8, 0xE0, 0x31, 0x50, 0x31, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0xBF, 0xF8, 0xDE, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0xEB, 0x81, 0x04, 0x00, 0x2B, 0xD4, 0xF8, 0x7C, 0x51, 0x0D, 0xDB, 0x0C, 0x4B, ++0x05, 0xF5, 0x88, 0x70, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x0A, 0x48, 0x29, 0x46, 0xF4, 0xF7, 0x95, 0xF8, 0x00, 0x23, ++0xC4, 0xF8, 0x7C, 0x31, 0x38, 0xBD, 0x00, 0x2D, 0xEF, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF6, 0x7F, 0x52, 0xF5, 0xF7, ++0xDD, 0xFC, 0xE8, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xDE, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x10, 0xC1, 0x15, 0x00, 0x08, 0x4B, 0x93, 0xF8, 0x73, 0x20, 0x62, 0xB9, 0x02, 0x88, 0xA3, 0xF8, 0x6C, 0x20, 0x42, 0x88, ++0xA3, 0xF8, 0x6E, 0x20, 0x82, 0x88, 0xA3, 0xF8, 0x70, 0x20, 0x4F, 0xF4, 0x80, 0x72, 0xA3, 0xF8, 0x72, 0x20, 0x70, 0x47, ++0xB0, 0xDE, 0x17, 0x00, 0x03, 0x4B, 0x00, 0x22, 0x93, 0xF8, 0x72, 0x00, 0xA3, 0xF8, 0x72, 0x20, 0x70, 0x47, 0x00, 0xBF, ++0xB0, 0xDE, 0x17, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0xF3, 0xF7, 0xDD, 0xFF, 0x03, 0x4B, 0x03, 0x48, 0xD3, 0xF8, ++0x38, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0x06, 0x4B, 0x07, 0x4A, ++0x93, 0xF8, 0x44, 0x30, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x03, 0x13, 0xB3, 0xF8, 0x4C, 0x00, 0xB0, 0xFA, 0x80, 0xF0, ++0x40, 0x09, 0x70, 0x47, 0xB0, 0xDE, 0x17, 0x00, 0xE0, 0x63, 0x18, 0x00, 0xF8, 0xB5, 0x55, 0x4F, 0x46, 0x7F, 0x05, 0x7F, ++0x54, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x06, 0x74, 0xD4, 0xE9, 0x2C, 0xC3, 0x4F, 0xF4, 0xA4, 0x6E, 0x0E, 0xFB, ++0x05, 0x25, 0x1B, 0x68, 0xD5, 0xF8, 0xA8, 0xE4, 0x00, 0x22, 0x0A, 0x60, 0x4B, 0xB3, 0xBE, 0xF1, 0x00, 0x0F, 0x26, 0xD0, ++0xD5, 0xF8, 0xB0, 0x54, 0xAA, 0x07, 0x06, 0xD5, 0x05, 0x8B, 0xB4, 0xF8, 0x34, 0xE0, 0x6C, 0xBA, 0xA4, 0xB2, 0xA6, 0x45, ++0x1B, 0xD0, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0x9C, 0xF8, 0x60, 0x20, 0x01, 0x3A, 0x01, 0x2A, 0x1C, 0xD9, 0x93, 0xF8, ++0x60, 0x20, 0x04, 0x2A, 0x04, 0xD8, 0xDF, 0xE8, 0x02, 0xF0, 0x10, 0x20, 0x27, 0x10, 0x3C, 0x00, 0x3D, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDA, 0x3B, 0x49, 0x3C, 0x48, 0xC4, 0x22, 0xF5, 0xF7, 0x53, 0xFC, 0x00, 0x20, ++0xF8, 0xBD, 0xC2, 0x8B, 0x04, 0x24, 0xD5, 0x07, 0x0C, 0x60, 0x54, 0xD5, 0x20, 0x46, 0xF8, 0xBD, 0x4F, 0xF4, 0x1E, 0x72, ++0x02, 0xFB, 0x06, 0x76, 0x96, 0xF8, 0x5D, 0x22, 0x01, 0x2A, 0xDA, 0xD8, 0xED, 0xE7, 0xC2, 0x8B, 0x0C, 0x24, 0x0C, 0x60, ++0xD4, 0x07, 0x35, 0xD5, 0x08, 0x20, 0xF8, 0xBD, 0xC2, 0x8B, 0x08, 0x24, 0x0C, 0x60, 0xD1, 0x07, 0xF8, 0xD4, 0xD3, 0xE9, ++0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x16, 0x46, 0x0F, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x67, 0x06, 0x22, ++0x38, 0x30, 0x07, 0xF0, 0xCD, 0xFE, 0x20, 0x46, 0xF8, 0xBD, 0xC2, 0x8B, 0x10, 0x24, 0xD2, 0x07, 0x0C, 0x60, 0x13, 0xD4, ++0x93, 0xF8, 0x62, 0x20, 0x0F, 0x2A, 0xD3, 0xE9, 0x12, 0x21, 0x0F, 0xD9, 0x02, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x14, 0x46, ++0x0D, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x45, 0x08, 0x22, 0x38, 0x30, 0x07, 0xF0, 0xB4, 0xFE, 0x12, 0x20, 0xF8, 0xBD, ++0x12, 0x20, 0xF8, 0xBD, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0xEE, 0xE7, 0xD3, 0xE9, 0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, ++0x00, 0x01, 0x14, 0x46, 0x0D, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x45, 0x06, 0x22, 0x38, 0x30, 0x07, 0xF0, 0x9E, 0xFE, ++0xBA, 0xE7, 0xD3, 0xE9, 0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x16, 0x46, 0x0F, 0x46, 0x19, 0x46, 0xE1, 0xE9, ++0x12, 0x67, 0x22, 0x46, 0x38, 0x30, 0x07, 0xF0, 0x8F, 0xFE, 0x20, 0x46, 0xF8, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xF0, 0xB5, 0xC3, 0x8B, ++0x04, 0x46, 0xD8, 0x07, 0x83, 0xB0, 0x44, 0xD4, 0xE0, 0x7E, 0x66, 0x7F, 0x22, 0x7F, 0xFF, 0x28, 0x44, 0xD0, 0x4F, 0xF4, ++0x9E, 0x71, 0x01, 0xFB, 0x06, 0x01, 0x21, 0x48, 0x98, 0x31, 0x00, 0xEB, 0x41, 0x01, 0x1A, 0x25, 0x8F, 0x88, 0x78, 0x1C, ++0xC0, 0xF3, 0x0B, 0x00, 0x88, 0x80, 0x27, 0x84, 0xD9, 0x05, 0x1C, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x02, 0x33, ++0x48, 0xBF, 0x06, 0x35, 0x93, 0xF8, 0x62, 0x30, 0x43, 0xB9, 0x16, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x06, 0x36, ++0x73, 0x68, 0x9B, 0x06, 0x48, 0xBF, 0x04, 0x35, 0x01, 0xA9, 0x84, 0xF8, 0x32, 0x50, 0x20, 0x46, 0xFF, 0xF7, 0x16, 0xFF, ++0x23, 0x8B, 0xA2, 0x88, 0x22, 0x86, 0x5B, 0xBA, 0x9B, 0xB2, 0xB3, 0xF5, 0xC0, 0x6F, 0x28, 0x44, 0x88, 0xBF, 0x08, 0x30, ++0xC0, 0xB2, 0x01, 0x9B, 0x84, 0xF8, 0x33, 0x00, 0x8C, 0xBF, 0x08, 0x21, 0x00, 0x21, 0x84, 0xF8, 0x42, 0x00, 0x84, 0xF8, ++0x34, 0x10, 0x84, 0xF8, 0x35, 0x30, 0x00, 0x23, 0xC4, 0xE9, 0x09, 0x33, 0x03, 0xB0, 0xF0, 0xBD, 0x18, 0x25, 0xC7, 0xE7, ++0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x1D, 0xA0, 0xDF, 0xF8, 0x58, 0x92, ++0x90, 0xF8, 0x1C, 0x80, 0x92, 0x4F, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x0A, 0xF6, 0x09, 0xEB, 0x06, 0x02, 0x4F, 0xF4, ++0xA4, 0x64, 0x04, 0xFB, 0x08, 0x74, 0xD2, 0xF8, 0xB4, 0x30, 0x94, 0xF8, 0x62, 0xC0, 0xD3, 0xF8, 0x00, 0xB0, 0xD2, 0xF8, ++0xB0, 0x30, 0x83, 0xB0, 0x05, 0x46, 0x01, 0x93, 0xD4, 0xF8, 0xA8, 0x34, 0x00, 0x93, 0x0C, 0x46, 0xBC, 0xF1, 0x00, 0x0F, ++0x40, 0xF0, 0x8D, 0x80, 0x53, 0x68, 0x13, 0xF0, 0x20, 0x03, 0x40, 0xF0, 0x9F, 0x80, 0xE9, 0x7E, 0xB5, 0xF8, 0x1E, 0xC0, ++0xFF, 0x29, 0x0C, 0xBF, 0xA4, 0xF1, 0x18, 0x00, 0xA4, 0xF1, 0x1A, 0x00, 0x1C, 0xF4, 0x80, 0x72, 0x1D, 0xBF, 0x06, 0x38, ++0x00, 0xF1, 0x1E, 0x04, 0x02, 0x46, 0x00, 0xF1, 0x18, 0x04, 0xFF, 0x29, 0x00, 0xF0, 0x94, 0x80, 0x6F, 0xF0, 0x7F, 0x0C, ++0x4F, 0xF0, 0x00, 0x0E, 0x80, 0xF8, 0x00, 0xC0, 0x80, 0xF8, 0x01, 0xE0, 0x21, 0x80, 0x29, 0x8C, 0xB5, 0xF8, 0x1E, 0xC0, ++0x09, 0x01, 0x1C, 0xF4, 0x00, 0x7F, 0xC1, 0x82, 0x63, 0xD1, 0x01, 0x88, 0x0B, 0x43, 0x43, 0xF0, 0x08, 0x01, 0x1C, 0xF4, ++0x00, 0x6F, 0x01, 0x80, 0x69, 0xD0, 0x23, 0xF4, 0x40, 0x71, 0x41, 0xF0, 0x08, 0x01, 0x89, 0xB2, 0x01, 0x80, 0x4F, 0xF4, ++0xA4, 0x64, 0x1C, 0xF0, 0x04, 0x0F, 0x04, 0xFB, 0x08, 0xF4, 0x18, 0xBF, 0x41, 0xF4, 0x00, 0x51, 0x04, 0xF1, 0x5C, 0x03, ++0x18, 0xBF, 0x01, 0x80, 0x07, 0xEB, 0x03, 0x0C, 0xFB, 0x5A, 0x43, 0x81, 0xBC, 0xF8, 0x02, 0x30, 0x83, 0x81, 0x01, 0xF4, ++0x40, 0x71, 0xBC, 0xF8, 0x04, 0x30, 0xC3, 0x81, 0xB1, 0xF5, 0x80, 0x7F, 0x5C, 0xD0, 0xB1, 0xF5, 0x00, 0x7F, 0x76, 0xD0, ++0x00, 0x29, 0x40, 0xF0, 0x81, 0x80, 0xAB, 0x89, 0x83, 0x80, 0xEB, 0x89, 0xC3, 0x80, 0x2B, 0x8A, 0x03, 0x81, 0x04, 0xF5, ++0xB2, 0x74, 0x3B, 0x5B, 0x03, 0x82, 0x3C, 0x44, 0x63, 0x88, 0x43, 0x82, 0xA3, 0x88, 0x83, 0x82, 0xBB, 0xF1, 0x00, 0x0F, ++0x1C, 0xD0, 0x00, 0x9B, 0xD3, 0xB1, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x77, 0xD7, 0xF8, 0xB0, 0x34, 0x9B, 0x07, ++0x0A, 0xD5, 0x6A, 0x7F, 0x2B, 0x8B, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x02, 0x92, 0x5B, 0xBA, 0x92, 0x8E, 0x9B, 0xB2, ++0x9A, 0x42, 0x07, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x7B, 0xD0, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, 0x01, 0x2B, 0x6E, 0xD9, ++0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x23, 0x75, 0xE7, 0x21, 0x88, 0x41, 0xF0, 0x10, 0x01, 0x21, 0x80, 0x01, 0x88, ++0xB5, 0xF8, 0x1E, 0xC0, 0x0B, 0x43, 0x43, 0xF0, 0x08, 0x01, 0x1C, 0xF4, 0x00, 0x6F, 0x01, 0x80, 0x95, 0xD1, 0x1C, 0xF4, ++0x80, 0x7F, 0x22, 0xD0, 0x43, 0xF4, 0x42, 0x71, 0x01, 0x80, 0x94, 0xE7, 0x32, 0x4B, 0x11, 0x46, 0xD3, 0xF8, 0xB8, 0x33, ++0x98, 0x47, 0x4F, 0xF4, 0x00, 0x43, 0x44, 0xF8, 0x04, 0x0D, 0x56, 0xE7, 0x00, 0x21, 0x81, 0x75, 0xC1, 0x75, 0x7A, 0xE7, ++0x26, 0x36, 0x09, 0xEB, 0x06, 0x03, 0x39, 0xF8, 0x06, 0x20, 0x82, 0x80, 0x5A, 0x88, 0xC2, 0x80, 0x9B, 0x88, 0x03, 0x81, ++0xAB, 0x89, 0x03, 0x82, 0xEB, 0x89, 0x43, 0x82, 0x2B, 0x8A, 0x83, 0x82, 0xA6, 0xE7, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, ++0x08, 0x74, 0x94, 0xF8, 0x62, 0x40, 0x00, 0x2C, 0x27, 0xD1, 0x43, 0xF4, 0x84, 0x71, 0x01, 0x80, 0x69, 0xE7, 0xAB, 0x89, ++0x83, 0x80, 0xEB, 0x89, 0xC3, 0x80, 0x2B, 0x8A, 0x03, 0x81, 0x6B, 0x8A, 0x03, 0x82, 0xAB, 0x8A, 0x43, 0x82, 0xEB, 0x8A, ++0x83, 0x82, 0x8D, 0xE7, 0x26, 0x36, 0x09, 0xEB, 0x06, 0x03, 0x39, 0xF8, 0x06, 0x10, 0x91, 0x80, 0x59, 0x88, 0xD1, 0x80, ++0x9B, 0x88, 0x13, 0x81, 0xAB, 0x89, 0x13, 0x82, 0xEB, 0x89, 0x53, 0x82, 0x2B, 0x8A, 0x93, 0x82, 0x6B, 0x8A, 0x13, 0x83, ++0xAB, 0x8A, 0x53, 0x83, 0xEB, 0x8A, 0x93, 0x83, 0x76, 0xE7, 0x02, 0x2C, 0x04, 0xBF, 0x43, 0xF4, 0x02, 0x71, 0x01, 0x80, ++0x3F, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x0A, 0x99, 0x99, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x88, 0xD9, 0x03, 0x88, ++0x43, 0xF4, 0x80, 0x43, 0x03, 0x80, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, ++0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x06, 0x46, 0x54, 0x48, 0x75, 0x7F, 0x34, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x05, 0x03, 0x89, 0x46, 0xD3, 0xF8, 0xB4, 0x70, 0xD7, 0xF8, 0x00, 0x80, 0xB8, 0xF1, 0x00, 0x0F, 0x4C, 0xD0, ++0x17, 0x46, 0x4D, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x04, 0x24, 0xD4, 0xF8, 0xA8, 0x24, 0x00, 0x2A, 0x42, 0xD0, ++0xD4, 0xF8, 0xB0, 0x24, 0x92, 0x07, 0x05, 0xD5, 0x32, 0x8B, 0x99, 0x8E, 0x53, 0xBA, 0x9B, 0xB2, 0x99, 0x42, 0x38, 0xD0, ++0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x05, 0xD5, 0xF8, 0xB0, 0x30, 0x23, 0xB1, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, ++0x01, 0x2B, 0x40, 0xD9, 0x98, 0xF8, 0x60, 0x30, 0x04, 0x2B, 0x67, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x2A, 0x03, 0x40, 0x2A, ++0x49, 0x00, 0x32, 0x8F, 0x42, 0xF4, 0x00, 0x53, 0x03, 0xF4, 0xFE, 0x43, 0x43, 0xEA, 0x12, 0x23, 0x29, 0xF8, 0x08, 0x3C, ++0x96, 0xF8, 0x38, 0x30, 0x98, 0xF8, 0x61, 0x20, 0xA9, 0xF1, 0x08, 0x09, 0x43, 0xEA, 0x82, 0x33, 0x43, 0xF4, 0x00, 0x53, ++0xA9, 0xF8, 0x02, 0x30, 0x73, 0x8F, 0xA9, 0xF8, 0x04, 0x30, 0xB3, 0x8F, 0xA9, 0xF8, 0x06, 0x30, 0xC7, 0xB1, 0xF2, 0x6A, ++0xD4, 0x68, 0x2B, 0x4B, 0x98, 0xF8, 0x62, 0x00, 0x23, 0x40, 0x03, 0x43, 0xD3, 0x60, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, ++0x33, 0x8F, 0x29, 0xF8, 0x04, 0x3C, 0x98, 0xF8, 0x61, 0x20, 0x73, 0x8F, 0xA9, 0xF1, 0x04, 0x09, 0x43, 0xEA, 0x82, 0x33, ++0xA9, 0xF8, 0x02, 0x30, 0x00, 0x2F, 0xE6, 0xD1, 0xB2, 0x6C, 0x28, 0x32, 0xE4, 0xE7, 0x95, 0xF8, 0x5D, 0x32, 0x01, 0x2B, ++0xBA, 0xD8, 0xE6, 0xE7, 0x33, 0x8F, 0x29, 0xF8, 0x08, 0x3C, 0x98, 0xF8, 0x61, 0x30, 0xA9, 0xF1, 0x08, 0x09, 0x9B, 0x03, ++0xCA, 0xE7, 0x98, 0xF8, 0x61, 0x30, 0x29, 0xF8, 0x12, 0x3C, 0xA9, 0xF1, 0x12, 0x09, 0x33, 0x8F, 0xA9, 0xF8, 0x02, 0x30, ++0x73, 0x8F, 0xA9, 0xF8, 0x04, 0x30, 0xB3, 0x8F, 0xA9, 0xF8, 0x06, 0x30, 0xF3, 0x8F, 0xA9, 0xF8, 0x08, 0x30, 0x45, 0xF6, ++0x36, 0x43, 0xA9, 0xF8, 0x0A, 0x30, 0xA9, 0xF8, 0x0C, 0x30, 0xA9, 0xF8, 0x0E, 0x30, 0xA9, 0xF8, 0x10, 0x30, 0xB7, 0xE7, ++0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB1, 0xDA, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xD9, 0x22, ++0xF5, 0xF7, 0xA8, 0xF9, 0xAA, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x00, 0xFC, 0x0F, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x70, 0xB5, 0x1A, 0x4D, 0x1A, 0x4E, 0xD5, 0xF8, ++0x68, 0x32, 0x04, 0x46, 0x98, 0x47, 0x60, 0x7F, 0xD5, 0xF8, 0x5C, 0x31, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0x60, ++0x98, 0x47, 0xE3, 0x8B, 0xE0, 0x62, 0x99, 0x04, 0x11, 0xD5, 0x63, 0x7F, 0x05, 0xFB, 0x03, 0x66, 0xD6, 0xF8, 0x4C, 0x31, ++0xD3, 0xF8, 0x9C, 0x20, 0xA2, 0x62, 0x93, 0xF8, 0xA1, 0x30, 0x2B, 0xB1, 0x94, 0xF8, 0x36, 0x30, 0x43, 0xF0, 0x20, 0x03, ++0x84, 0xF8, 0x36, 0x30, 0x70, 0xBD, 0x94, 0xF8, 0x36, 0x30, 0x03, 0xF0, 0x03, 0x02, 0x00, 0xEB, 0x82, 0x00, 0x42, 0x6A, ++0x41, 0x69, 0xA1, 0x62, 0x52, 0x03, 0x44, 0xBF, 0x43, 0xF0, 0x20, 0x03, 0x84, 0xF8, 0x36, 0x30, 0x70, 0xBD, 0x00, 0xBF, ++0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0xC3, 0x7E, 0x00, 0x93, 0x04, 0x46, 0xC3, 0x8B, ++0x0F, 0x46, 0x16, 0x46, 0x16, 0x49, 0x02, 0x8C, 0x20, 0x20, 0xF4, 0xF7, 0x29, 0xFF, 0xE3, 0x8B, 0xD9, 0x07, 0x1E, 0xD5, ++0x13, 0x48, 0xF4, 0xF7, 0xD3, 0xFE, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, ++0x1A, 0x60, 0x10, 0x4D, 0x2B, 0x68, 0x3A, 0x46, 0x01, 0x33, 0x31, 0x46, 0x20, 0x46, 0x2B, 0x60, 0xDF, 0xF7, 0x4A, 0xFD, ++0x2B, 0x68, 0x33, 0xB1, 0x09, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x03, 0xB0, ++0xF0, 0xBD, 0xDF, 0xF7, 0x61, 0xF9, 0xE3, 0x8B, 0xDA, 0x07, 0xDB, 0xD4, 0xDD, 0xE7, 0x00, 0xBF, 0x3C, 0xC1, 0x15, 0x00, ++0x58, 0xC1, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x02, 0x8B, 0x53, 0xBA, 0x9B, 0xB2, 0xB3, 0xF5, ++0xC0, 0x6F, 0x10, 0xB5, 0x04, 0x46, 0x08, 0xD3, 0x4A, 0xF6, 0xAA, 0x23, 0x21, 0xF8, 0x08, 0x3D, 0x03, 0x20, 0x00, 0x23, ++0xCA, 0x80, 0x48, 0x80, 0x8B, 0x80, 0x20, 0x46, 0x01, 0x22, 0xFF, 0xF7, 0xBB, 0xFE, 0x04, 0x4B, 0x01, 0x46, 0xD3, 0xF8, ++0x20, 0x34, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xC5, 0x8B, 0xDF, 0xF8, 0x7C, 0x82, 0x07, 0x7F, 0x4F, 0xF4, 0xA4, 0x6A, 0x0E, 0x46, 0x29, 0x07, 0x83, 0xB0, 0x04, 0x46, ++0x0A, 0xFB, 0x07, 0x8A, 0x6B, 0xD4, 0x41, 0x7F, 0xDF, 0xF8, 0x64, 0xB2, 0x03, 0x8B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, ++0x01, 0xB1, 0x5B, 0xBA, 0x88, 0x8E, 0x91, 0xF8, 0x30, 0x20, 0x9B, 0xB2, 0x98, 0x42, 0x0F, 0xD0, 0x02, 0x2A, 0x16, 0xD0, ++0x8B, 0x49, 0x20, 0x20, 0xF4, 0xF7, 0xB4, 0xFE, 0x20, 0x46, 0x31, 0x46, 0x4F, 0xF0, 0x00, 0x42, 0xFF, 0xF7, 0x78, 0xFF, ++0x00, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x3A, 0x25, 0xF4, 0x80, 0x75, 0x01, 0x2A, 0xE5, 0x83, 0x02, 0xD9, ++0x91, 0xF8, 0x30, 0x20, 0xE8, 0xE7, 0xDF, 0xF8, 0x1C, 0x92, 0x20, 0x46, 0xD9, 0xF8, 0x2C, 0x34, 0x98, 0x47, 0x63, 0x7F, ++0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0xBB, 0x9B, 0xF8, 0x30, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xA2, 0x80, 0x4F, 0xF4, ++0xA4, 0x63, 0x03, 0xFB, 0x07, 0x87, 0x77, 0x4A, 0x3B, 0x6C, 0x77, 0x49, 0x1F, 0x79, 0x77, 0x4B, 0x00, 0x2F, 0x0C, 0xBF, ++0x0F, 0x46, 0x17, 0x46, 0xE7, 0x62, 0x7D, 0x69, 0x93, 0xF8, 0xBD, 0x20, 0xC5, 0xF3, 0xC2, 0x28, 0xED, 0xB2, 0x00, 0x2A, ++0x40, 0xF0, 0xB4, 0x80, 0xD9, 0xF8, 0x38, 0x33, 0x50, 0x46, 0x01, 0xAA, 0x0D, 0xF1, 0x03, 0x01, 0x98, 0x47, 0x05, 0xF0, ++0x7C, 0x03, 0x58, 0xEA, 0x03, 0x03, 0x0C, 0xBF, 0x9D, 0xF8, 0x03, 0x30, 0x9D, 0xF8, 0x04, 0x30, 0x43, 0xEA, 0x03, 0x23, ++0x7B, 0x62, 0xE3, 0x8B, 0xDB, 0x07, 0x4C, 0xD4, 0xA1, 0x6C, 0xD9, 0xF8, 0x1C, 0x34, 0xA8, 0x31, 0x20, 0x46, 0x98, 0x47, ++0x45, 0xE0, 0x00, 0x23, 0xEA, 0x06, 0x01, 0x93, 0x5B, 0xD5, 0x5D, 0x4B, 0xE3, 0x62, 0x15, 0xF0, 0x80, 0x05, 0x7D, 0xD1, ++0xA8, 0x46, 0xDF, 0xF8, 0x80, 0x91, 0x5B, 0x4F, 0xD9, 0xF8, 0x38, 0x33, 0x50, 0x46, 0x0D, 0xF1, 0x03, 0x02, 0x0D, 0xF1, ++0x02, 0x01, 0x98, 0x47, 0xE2, 0x6A, 0x4F, 0xF0, 0x00, 0x0A, 0xA3, 0x68, 0x02, 0xEB, 0x8A, 0x00, 0x23, 0xF0, 0x60, 0x41, ++0x13, 0xF0, 0x80, 0x4F, 0x41, 0xF0, 0x00, 0x51, 0x14, 0xBF, 0x41, 0x61, 0x43, 0x69, 0x97, 0xF8, 0xBD, 0x10, 0xC3, 0xF3, ++0xC2, 0x20, 0x03, 0xF0, 0x7F, 0x03, 0x51, 0xBB, 0x08, 0xBB, 0x03, 0x2B, 0x02, 0xEB, 0x8A, 0x01, 0x1D, 0xD8, 0x9D, 0xF8, ++0x02, 0x30, 0x43, 0xEA, 0x03, 0x23, 0x4B, 0x62, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x04, 0x0F, 0xDD, 0xD1, 0x00, 0x23, ++0xC4, 0xE9, 0x09, 0x33, 0x01, 0x9A, 0x84, 0xF8, 0x32, 0x80, 0x84, 0xF8, 0x33, 0x50, 0x84, 0xF8, 0x42, 0x50, 0x84, 0xF8, ++0x35, 0x20, 0xD9, 0xF8, 0x94, 0x33, 0x31, 0x46, 0x20, 0x46, 0x98, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x9D, 0xF8, ++0x03, 0x30, 0x02, 0xEB, 0x8A, 0x01, 0x43, 0xEA, 0x03, 0x23, 0x4B, 0x62, 0xDE, 0xE7, 0x19, 0x46, 0xD1, 0xF7, 0xF0, 0xFD, ++0xE2, 0x6A, 0x02, 0xEB, 0x8A, 0x03, 0x40, 0xEA, 0x00, 0x20, 0x58, 0x62, 0xD4, 0xE7, 0x9A, 0xF8, 0xC0, 0x34, 0x00, 0x2B, ++0x9F, 0xD1, 0xDA, 0xF8, 0x40, 0x20, 0x2D, 0x4B, 0x11, 0x79, 0x2B, 0x4A, 0x00, 0x29, 0x18, 0xBF, 0x13, 0x46, 0xC3, 0x62, ++0x97, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x83, 0x93, 0xF8, 0x62, 0x20, 0x52, 0xB3, 0x02, 0x2A, 0x04, 0xD1, ++0x9B, 0xF8, 0x70, 0x32, 0x00, 0x2B, 0x7F, 0xF4, 0x50, 0xAF, 0x24, 0x4B, 0x1B, 0x78, 0x1B, 0xB9, 0xD9, 0xF8, 0x1C, 0x30, ++0x20, 0x46, 0x98, 0x47, 0x20, 0x46, 0xFF, 0xF7, 0x67, 0xFE, 0x6E, 0xE7, 0x00, 0x22, 0xC0, 0x21, 0x20, 0x46, 0x01, 0xF0, ++0x1D, 0xFB, 0x01, 0x28, 0x1C, 0xD0, 0x02, 0x28, 0x15, 0xD0, 0xE3, 0x8B, 0x00, 0x25, 0x23, 0xF0, 0x80, 0x03, 0xE3, 0x83, ++0xA8, 0x46, 0x72, 0xE7, 0x05, 0xF0, 0x7F, 0x01, 0x40, 0x46, 0xD1, 0xF7, 0xAD, 0xFD, 0x40, 0xEA, 0x00, 0x20, 0x78, 0x62, ++0x55, 0xE7, 0x93, 0xF8, 0xAC, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x27, 0xAF, 0xD5, 0xE7, 0x12, 0x23, 0x00, 0x25, 0x01, 0x93, ++0xA8, 0x46, 0x5E, 0xE7, 0x01, 0xA9, 0x20, 0x46, 0xFF, 0xF7, 0x46, 0xFB, 0xA3, 0x6C, 0x05, 0x46, 0x03, 0xF1, 0xA8, 0x01, ++0x03, 0xF1, 0xA0, 0x00, 0x18, 0x22, 0x07, 0xF0, 0x75, 0xFA, 0xED, 0xB2, 0x4F, 0xF0, 0x18, 0x08, 0x4D, 0xE7, 0x00, 0xBF, ++0x70, 0xC1, 0x15, 0x00, 0x84, 0x3C, 0x18, 0x00, 0xC4, 0x3C, 0x18, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xB8, 0x34, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x51, 0x4A, 0x43, 0x7F, ++0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x03, 0x23, 0x86, 0xB0, 0xD3, 0xF8, 0xB4, 0x30, 0x1E, 0x68, 0x8E, 0xB1, 0x90, 0xF8, ++0x35, 0x30, 0x04, 0x46, 0x6B, 0xB1, 0x90, 0xF8, 0x34, 0x30, 0x85, 0x6C, 0x96, 0xF8, 0x60, 0x20, 0xED, 0x1A, 0x01, 0x2A, ++0x05, 0xF1, 0xA8, 0x05, 0x06, 0xD0, 0x03, 0x2A, 0x51, 0xD0, 0x00, 0x2A, 0x4F, 0xD0, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, ++0x07, 0x8E, 0x42, 0x4A, 0x00, 0x91, 0x3B, 0x44, 0x06, 0xF1, 0x50, 0x01, 0xD2, 0xF8, 0x7C, 0x73, 0x2A, 0x46, 0xB8, 0x47, ++0x3E, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9A, 0x07, 0xED, 0xD5, 0x96, 0xF8, 0x60, 0x20, 0x01, 0x2A, 0x06, 0xF1, 0x64, 0x08, ++0x3E, 0xD1, 0x23, 0x8E, 0x94, 0xF8, 0x34, 0x70, 0x0C, 0x33, 0x1F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, 0x4F, 0xF0, 0xFF, 0x33, ++0x03, 0x22, 0x28, 0x46, 0xD6, 0xF7, 0xD8, 0xF8, 0xD6, 0xE9, 0x12, 0x03, 0x32, 0x49, 0x94, 0xF8, 0x1C, 0xC0, 0x88, 0x80, ++0x31, 0x4A, 0x00, 0x0C, 0x4F, 0xF4, 0xA4, 0x6E, 0x40, 0xEA, 0x03, 0x40, 0x0E, 0xFB, 0x0C, 0x22, 0x08, 0x60, 0x02, 0xAB, ++0x40, 0x46, 0xF2, 0xF7, 0x9F, 0xFA, 0x02, 0xA8, 0x10, 0x21, 0xF2, 0xF7, 0x5F, 0xFC, 0x96, 0xF8, 0x60, 0x20, 0xCA, 0xB1, ++0x03, 0x2A, 0x17, 0xD0, 0x03, 0x20, 0xD6, 0xF7, 0xF1, 0xF8, 0x39, 0x46, 0x02, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x84, 0xFA, ++0x39, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x7A, 0xFC, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, ++0x9B, 0x07, 0xAA, 0xD5, 0x06, 0xF1, 0x64, 0x08, 0x00, 0x27, 0xE4, 0xE7, 0x23, 0x8E, 0x94, 0xF8, 0x34, 0x70, 0x04, 0x33, ++0x1F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x28, 0x46, 0xD6, 0xF7, 0x97, 0xF8, 0x96, 0xF8, ++0x60, 0x30, 0xB6, 0xF8, 0x48, 0x10, 0xB6, 0xF8, 0x4A, 0x20, 0xAD, 0xF8, 0x08, 0x10, 0x8D, 0xF8, 0x0A, 0x20, 0x41, 0x46, ++0x4B, 0xB9, 0x05, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x07, 0xF0, 0xCA, 0xF9, 0x02, 0xA8, 0x08, 0x21, 0xF2, 0xF7, 0x20, 0xFC, ++0xC4, 0xE7, 0x0D, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x07, 0xF0, 0xC0, 0xF9, 0x02, 0xA8, 0x10, 0x21, 0xF2, 0xF7, 0x16, 0xFC, ++0xBA, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0xA0, 0x34, 0x17, 0x00, ++0x74, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xC5, 0x6C, 0xC3, 0x8B, 0x2F, 0x69, 0x02, 0x8C, 0x2A, 0x81, 0x00, 0x26, ++0x13, 0xF0, 0x08, 0x02, 0x2E, 0x61, 0x04, 0x46, 0x07, 0xF4, 0x00, 0x06, 0x88, 0x46, 0x07, 0xF0, 0x40, 0x47, 0x1C, 0xD0, ++0x99, 0x06, 0x01, 0xD5, 0x00, 0x2E, 0x6C, 0xD0, 0x9A, 0x05, 0x3E, 0xD4, 0xB7, 0xF1, 0x40, 0x4F, 0x20, 0xD0, 0xE3, 0x7E, ++0xFF, 0x2B, 0x22, 0xD1, 0x2B, 0x69, 0x62, 0x6A, 0x01, 0x20, 0x02, 0xF4, 0x00, 0x12, 0x16, 0xB1, 0x43, 0xF0, 0x08, 0x03, ++0x2B, 0x61, 0x00, 0x2A, 0x47, 0xD0, 0x43, 0xF0, 0x01, 0x03, 0x28, 0x73, 0x2B, 0x61, 0xBD, 0xE8, 0xF0, 0x81, 0x9B, 0x05, ++0xE6, 0xD5, 0x43, 0x7F, 0x2A, 0x49, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0xB7, 0xF1, 0x40, 0x4F, 0x83, 0xF8, ++0x32, 0x20, 0xDE, 0xD1, 0x2B, 0x69, 0x43, 0xF0, 0x04, 0x03, 0x2B, 0x61, 0xDD, 0xE7, 0x31, 0x1E, 0x42, 0x46, 0x18, 0xBF, ++0x01, 0x21, 0x20, 0x46, 0x01, 0xF0, 0x3A, 0xF8, 0x63, 0x6A, 0x13, 0xF4, 0x00, 0x12, 0x20, 0xD0, 0x03, 0xF4, 0x60, 0x13, ++0xB3, 0xF5, 0x60, 0x1F, 0x01, 0xD0, 0x00, 0x23, 0x6B, 0x73, 0x2B, 0x69, 0x00, 0x2E, 0xD2, 0xD0, 0xCC, 0xE7, 0x19, 0x4B, ++0x60, 0x7F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1A, 0xDB, 0x00, 0x23, 0x1A, 0x46, 0x17, 0x21, 0xE0, 0xF7, ++0x0D, 0xFA, 0x12, 0x4A, 0x63, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x00, 0x22, 0x83, 0xF8, 0x32, 0x20, ++0xAA, 0xE7, 0x2B, 0x69, 0x0E, 0xB1, 0x43, 0xF0, 0x08, 0x03, 0x01, 0x22, 0x43, 0xF0, 0x01, 0x03, 0x6A, 0x73, 0x28, 0x73, ++0x2B, 0x61, 0xBD, 0xE8, 0xF0, 0x81, 0xFF, 0x28, 0xE2, 0xD1, 0x08, 0x48, 0x08, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0xF4, 0xF7, ++0x89, 0xFE, 0x60, 0x7F, 0xDA, 0xE7, 0xFF, 0xF7, 0xC7, 0xF9, 0xE3, 0x8B, 0x8E, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x84, 0xC1, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x70, 0xB5, 0x90, 0xF8, 0x33, 0x30, 0x82, 0xB0, ++0x04, 0x46, 0x0D, 0x46, 0x16, 0x46, 0x7B, 0xB1, 0x90, 0xF8, 0x35, 0x20, 0x01, 0x92, 0x18, 0x46, 0x2B, 0x88, 0x2E, 0x44, ++0x43, 0xF4, 0x80, 0x43, 0x31, 0x18, 0x2B, 0x80, 0x20, 0x46, 0x00, 0x22, 0xFF, 0xF7, 0x12, 0xFC, 0x02, 0xB0, 0x70, 0xBD, ++0x01, 0xA9, 0xFF, 0xF7, 0xCD, 0xF9, 0x01, 0x9B, 0x84, 0xF8, 0x33, 0x00, 0x84, 0xF8, 0x35, 0x30, 0xEA, 0xE7, 0x00, 0xBF, ++0x10, 0xB4, 0x0C, 0x88, 0x0B, 0x46, 0x44, 0xF4, 0x80, 0x44, 0x11, 0x44, 0x1C, 0x80, 0x00, 0x22, 0x5D, 0xF8, 0x04, 0x4B, ++0xFF, 0xF7, 0xFA, 0xBB, 0xF0, 0xB5, 0x00, 0x22, 0x18, 0x4C, 0x85, 0xB0, 0x05, 0x46, 0x0F, 0x46, 0x02, 0xE0, 0x01, 0x32, ++0x20, 0x2A, 0x26, 0xD0, 0xA5, 0x42, 0x96, 0xB2, 0x04, 0xF1, 0x18, 0x04, 0xF7, 0xD1, 0x12, 0x02, 0x02, 0xF4, 0x7F, 0x42, ++0x42, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0xF6, 0xFF, 0x04, 0x28, 0x18, 0xD1, 0x17, 0xF4, 0x00, 0x03, 0x02, 0xD1, 0xEA, 0x7C, ++0x02, 0x2A, 0x06, 0xD9, 0x28, 0x7B, 0x31, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0x00, 0xF0, 0x65, 0xBC, 0x08, 0x49, ++0x01, 0x32, 0xEA, 0x74, 0x27, 0x22, 0xCD, 0xE9, 0x01, 0x21, 0x00, 0x93, 0x28, 0x7B, 0x02, 0x22, 0x29, 0x46, 0x00, 0xF0, ++0xBB, 0xFC, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, 0xF4, 0xE4, 0x17, 0x00, 0xE5, 0xFE, 0x14, 0x00, 0x2D, 0xE9, 0xF0, 0x43, ++0x10, 0x46, 0x85, 0xB0, 0x14, 0x46, 0x0F, 0x46, 0xF2, 0xF7, 0xCC, 0xFF, 0x03, 0x28, 0x09, 0xD0, 0x50, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x72, 0xDB, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x4C, 0x4E, 0x4F, 0xEA, ++0x14, 0x28, 0x08, 0xEB, 0x48, 0x03, 0x06, 0xEB, 0xC3, 0x06, 0x96, 0xF8, 0x0D, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x39, 0xD0, ++0xB9, 0xF1, 0x01, 0x0F, 0x29, 0xD1, 0xBB, 0x78, 0x00, 0x2B, 0x7C, 0xD1, 0x05, 0x46, 0x30, 0x46, 0x96, 0xF8, 0x0F, 0x90, ++0x00, 0xF0, 0xA0, 0xFF, 0x41, 0x4B, 0x1B, 0x69, 0x73, 0x60, 0x05, 0x22, 0x2B, 0x46, 0x0C, 0x21, 0x41, 0xF2, 0x0B, 0x40, ++0x3D, 0x78, 0x7F, 0x78, 0xF2, 0xF7, 0xFA, 0xFC, 0xA9, 0xF1, 0x04, 0x09, 0x4F, 0xFA, 0x89, 0xF9, 0x80, 0xF8, 0x02, 0x90, ++0x05, 0x70, 0x47, 0x70, 0xF2, 0xF7, 0x20, 0xFD, 0x73, 0x89, 0x00, 0x2B, 0x39, 0xD1, 0x20, 0x46, 0x01, 0x21, 0xF2, 0xF7, ++0xE3, 0xFE, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x2F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xBC, 0xDA, 0x2F, 0x49, 0x2F, 0x48, 0x40, 0xF2, 0x29, 0x12, 0xF4, 0xF7, 0xD3, 0xFD, 0xB5, 0xE7, 0xBA, 0x78, 0x33, 0x7C, ++0x72, 0xBB, 0xB0, 0x7B, 0xF1, 0x7B, 0x02, 0x92, 0x9B, 0x00, 0x43, 0xEA, 0x40, 0x03, 0x43, 0xEA, 0x81, 0x13, 0xCD, 0xE9, ++0x00, 0x32, 0x31, 0x46, 0x73, 0x7C, 0x30, 0x7B, 0x01, 0x22, 0x00, 0xF0, 0x47, 0xFC, 0x3B, 0x78, 0x7D, 0x78, 0x23, 0x4A, ++0x1F, 0x48, 0x71, 0x89, 0x03, 0xEB, 0x83, 0x07, 0xC3, 0xEB, 0x07, 0x13, 0x2B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x83, 0xF8, ++0xA4, 0x81, 0x03, 0x69, 0x73, 0x60, 0x00, 0x29, 0xC5, 0xD0, 0x40, 0x46, 0x00, 0xF0, 0x9A, 0xFB, 0xC1, 0xE7, 0x17, 0x49, ++0x17, 0x48, 0xC8, 0x22, 0xF4, 0xF7, 0xA4, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0xB1, 0x7B, 0xF2, 0x7B, ++0xCD, 0xF8, 0x08, 0x90, 0x9B, 0x00, 0x43, 0xEA, 0x41, 0x03, 0x43, 0xEA, 0x82, 0x13, 0x25, 0x22, 0xCD, 0xE9, 0x00, 0x32, ++0x31, 0x46, 0x30, 0x7B, 0x73, 0x7C, 0x01, 0x22, 0x00, 0xF0, 0x16, 0xFC, 0x49, 0x46, 0x20, 0x46, 0xF2, 0xF7, 0x8A, 0xFE, ++0x6C, 0xE7, 0x40, 0x46, 0x00, 0xF0, 0xF8, 0xFA, 0x20, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0x82, 0xFE, 0x64, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, ++0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x8B, 0x78, 0x02, 0x2B, 0x01, 0xD0, 0x00, 0x20, 0xF8, 0xBD, 0x02, 0xF4, 0x7F, 0x40, ++0x40, 0xF0, 0x08, 0x00, 0x0C, 0x46, 0x15, 0x0A, 0xF2, 0xF7, 0x0E, 0xFF, 0x04, 0x28, 0xF3, 0xD1, 0x11, 0x4E, 0x05, 0xEB, ++0x45, 0x03, 0x06, 0xEB, 0xC3, 0x06, 0x73, 0x7B, 0x01, 0x2B, 0x04, 0xD0, 0x0E, 0x4B, 0x28, 0x46, 0x9B, 0x6A, 0x98, 0x47, ++0xE6, 0xE7, 0x70, 0x69, 0x00, 0xF0, 0x1E, 0xFF, 0xF3, 0x7B, 0x67, 0x78, 0x26, 0x78, 0xC3, 0xF1, 0x04, 0x03, 0x1C, 0x18, ++0x05, 0x22, 0x03, 0x23, 0x0C, 0x21, 0x41, 0xF2, 0x0B, 0x40, 0xF2, 0xF7, 0x4D, 0xFC, 0x64, 0xB2, 0x84, 0x70, 0x06, 0x70, ++0x47, 0x70, 0xF2, 0xF7, 0x77, 0xFC, 0xE3, 0xE7, 0xF4, 0xE4, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0xB7, 0x4F, 0xCE, 0x79, 0xB7, 0x4A, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x06, 0x75, 0x0C, 0x46, 0x95, 0xF8, 0x22, 0x30, ++0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x85, 0xB0, 0x93, 0xF8, 0x64, 0x30, 0x1B, 0xB9, 0x00, 0x20, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x20, 0x94, 0xF8, 0x0D, 0x80, 0xF2, 0xF7, 0xC7, 0xFE, 0x09, 0x28, 0x04, 0xF1, 0x0C, 0x09, ++0xF2, 0xD0, 0xB8, 0xF1, 0x01, 0x0F, 0x5B, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0x1B, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0xE9, 0xD1, ++0xB9, 0xF8, 0x03, 0x80, 0x99, 0xF8, 0x02, 0xB0, 0xC8, 0xF3, 0x83, 0x0A, 0xBA, 0xF1, 0x08, 0x0F, 0x04, 0xD8, 0xA1, 0x4B, ++0x1B, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x87, 0x80, 0x25, 0x23, 0x00, 0x21, 0xCD, 0xE9, 0x00, 0x83, 0x30, 0x46, 0x5B, 0x46, ++0x02, 0x91, 0x01, 0x22, 0x00, 0xF0, 0x82, 0xFB, 0xD0, 0xE7, 0xB9, 0xF8, 0x02, 0x10, 0xB1, 0xF5, 0x10, 0x4F, 0x4F, 0xEA, ++0x11, 0x35, 0xC9, 0xD2, 0xE3, 0x79, 0xFF, 0x2B, 0xC6, 0xD0, 0x09, 0x05, 0x2A, 0x46, 0x40, 0xF1, 0xBA, 0x80, 0x93, 0x49, ++0x4F, 0xF4, 0x00, 0x60, 0xF4, 0xF7, 0xA4, 0xFA, 0xE3, 0x79, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x2B, 0x44, ++0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA4, 0x51, 0x21, 0x2D, 0xB1, 0xD0, 0x2E, 0x02, 0x46, 0xF0, 0x08, 0x06, 0x30, 0x46, ++0xF2, 0xF7, 0x7C, 0xFE, 0x04, 0x28, 0xA9, 0xD0, 0x31, 0x46, 0x42, 0xF2, 0x01, 0x00, 0xF2, 0xF7, 0xE1, 0xFA, 0x30, 0x46, ++0xF2, 0xF7, 0x72, 0xFE, 0x01, 0x28, 0x00, 0xF0, 0xD2, 0x80, 0x30, 0x46, 0xF2, 0xF7, 0x6C, 0xFE, 0x03, 0x28, 0x00, 0xF0, ++0xCC, 0x80, 0x7F, 0x4B, 0x28, 0x46, 0x9B, 0x6A, 0x98, 0x47, 0x93, 0xE7, 0xB9, 0xF8, 0x05, 0x50, 0xC5, 0xF3, 0x83, 0x06, ++0x08, 0x2E, 0x8D, 0xD8, 0xE3, 0x79, 0x7A, 0x49, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x33, 0x44, 0x07, 0xEB, ++0xC3, 0x07, 0x32, 0x46, 0x97, 0xF8, 0xA5, 0x71, 0x4F, 0xF4, 0x00, 0x60, 0x3B, 0x46, 0xF4, 0xF7, 0x63, 0xFA, 0x21, 0x2F, ++0x3F, 0xF4, 0x7A, 0xAF, 0x4F, 0xEA, 0x07, 0x28, 0x48, 0xF0, 0x08, 0x08, 0x40, 0x46, 0xF2, 0xF7, 0x43, 0xFE, 0x02, 0x28, ++0x7F, 0xF4, 0x70, 0xAF, 0x41, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0xF2, 0xF7, 0xA7, 0xFA, 0x6A, 0x4A, 0x99, 0xF8, 0x02, 0x10, ++0x07, 0xEB, 0x47, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x58, 0x7C, 0x88, 0x42, 0x03, 0xD1, 0x1B, 0x7C, 0xB3, 0x42, 0x00, 0xF0, ++0x9B, 0x80, 0x38, 0x46, 0x00, 0xF0, 0xF4, 0xF9, 0x40, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0x7E, 0xFD, 0x54, 0xE7, 0x60, 0x49, ++0x4F, 0xF4, 0x00, 0x60, 0x52, 0x46, 0xF4, 0xF7, 0x35, 0xFA, 0x51, 0x46, 0x30, 0x46, 0xE8, 0xF7, 0x85, 0xF9, 0x00, 0x28, ++0x4F, 0xD1, 0x95, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0x68, 0xAF, 0x00, 0xF0, 0x04, 0xFA, 0x21, 0x28, 0x04, 0x46, ++0x3F, 0xF4, 0x62, 0xAF, 0x53, 0x4D, 0x55, 0x4A, 0x00, 0xEB, 0x40, 0x01, 0x05, 0xEB, 0xC1, 0x03, 0xC8, 0xF3, 0x40, 0x00, ++0x12, 0x68, 0x83, 0xF8, 0x10, 0xA0, 0x00, 0x27, 0x1E, 0x73, 0x83, 0xF8, 0x11, 0xB0, 0x98, 0x73, 0x5F, 0x73, 0x90, 0x6B, ++0xB9, 0xF8, 0x05, 0x20, 0x5A, 0x81, 0x4F, 0xEA, 0x98, 0x18, 0x80, 0x45, 0x28, 0xBF, 0x80, 0x46, 0x83, 0xF8, 0x0F, 0x80, ++0xB9, 0xF8, 0x07, 0x00, 0xC9, 0x00, 0x00, 0x09, 0x92, 0xB2, 0x6F, 0x50, 0x18, 0x81, 0x1A, 0xB9, 0x44, 0x4A, 0x12, 0x68, ++0x52, 0x88, 0x5A, 0x81, 0x30, 0x46, 0x21, 0x46, 0x00, 0xF0, 0x3C, 0xFA, 0x20, 0x02, 0x00, 0xF4, 0x7F, 0x40, 0x40, 0xF0, ++0x08, 0x00, 0x03, 0x21, 0xF2, 0xF7, 0x32, 0xFD, 0x08, 0xE7, 0x3D, 0x49, 0x4F, 0xF4, 0x00, 0x60, 0xF4, 0xF7, 0xEA, 0xF9, ++0xE3, 0x79, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x2B, 0x44, 0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA5, 0x51, ++0x44, 0xE7, 0x06, 0xEB, 0x86, 0x03, 0xC6, 0xEB, 0x03, 0x13, 0x53, 0x44, 0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA4, 0x71, ++0x3D, 0x02, 0x45, 0xF0, 0x08, 0x05, 0x28, 0x46, 0xF2, 0xF7, 0xBA, 0xFD, 0x01, 0x28, 0x7F, 0xF4, 0x0B, 0xAF, 0x2A, 0x4B, ++0x27, 0x4A, 0x1B, 0x68, 0x07, 0xEB, 0x47, 0x01, 0x02, 0xEB, 0xC1, 0x02, 0x99, 0x6B, 0xD2, 0x7B, 0x4F, 0xEA, 0x98, 0x13, ++0x8B, 0x42, 0x28, 0xBF, 0x0B, 0x46, 0x9A, 0x42, 0x12, 0xD0, 0x28, 0x46, 0x04, 0x21, 0xF2, 0xF7, 0xFB, 0xFC, 0xE0, 0x79, ++0x39, 0x46, 0x00, 0xF0, 0x1D, 0xFA, 0x25, 0x23, 0xF1, 0xE6, 0x30, 0x46, 0x04, 0x21, 0xF2, 0xF7, 0xF1, 0xFC, 0xE0, 0x79, ++0x29, 0x46, 0x00, 0xF0, 0x13, 0xFA, 0xC3, 0xE6, 0x00, 0x23, 0xE6, 0xE6, 0xB9, 0xF8, 0x03, 0x30, 0x00, 0x2B, 0x7F, 0xF4, ++0x60, 0xAF, 0x18, 0x23, 0x03, 0xFB, 0x07, 0x23, 0xA9, 0x09, 0xDB, 0x7B, 0xB3, 0xEB, 0x95, 0x1F, 0x03, 0xD9, 0x18, 0x23, ++0x03, 0xFB, 0x07, 0x23, 0xD9, 0x73, 0x18, 0x23, 0x03, 0xFB, 0x07, 0x22, 0x05, 0xF0, 0x01, 0x05, 0x95, 0x74, 0xE0, 0x79, ++0x39, 0x46, 0x00, 0xF0, 0xD1, 0xF9, 0x40, 0x46, 0x03, 0x21, 0xF2, 0xF7, 0xCB, 0xFC, 0xA1, 0xE6, 0x68, 0x65, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0xB9, 0x34, 0x17, 0x00, 0xE4, 0xC1, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC0, 0xC1, 0x15, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0xA4, 0xC1, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x08, 0xC2, 0x15, 0x00, ++0x10, 0xB5, 0x10, 0x46, 0x14, 0x46, 0xF2, 0xF7, 0x57, 0xFD, 0x02, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x20, 0x0A, ++0x00, 0xF0, 0x1A, 0xF9, 0x20, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0xA4, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x10, 0x46, ++0x84, 0xB0, 0x14, 0x46, 0xF2, 0xF7, 0x44, 0xFD, 0x01, 0x28, 0x02, 0xD0, 0x00, 0x20, 0x04, 0xB0, 0x70, 0xBD, 0x20, 0x0A, ++0x13, 0x4A, 0x00, 0xEB, 0x40, 0x05, 0x52, 0xF8, 0x35, 0x60, 0x02, 0xEB, 0xC5, 0x05, 0x3E, 0xB9, 0x10, 0x4B, 0x6A, 0x68, ++0x19, 0x69, 0x6B, 0x89, 0x52, 0x1A, 0x12, 0xEB, 0x83, 0x23, 0x04, 0xD4, 0x00, 0xF0, 0x74, 0xF9, 0x00, 0x20, 0x04, 0xB0, ++0x70, 0xBD, 0x20, 0x46, 0x04, 0x21, 0x2C, 0x7B, 0xF2, 0xF7, 0x7C, 0xFC, 0x08, 0x4B, 0x02, 0x93, 0x27, 0x22, 0x01, 0x92, ++0x00, 0x96, 0x20, 0x46, 0x33, 0x46, 0x29, 0x46, 0x02, 0x22, 0xEE, 0x74, 0x00, 0xF0, 0xF8, 0xF9, 0xD4, 0xE7, 0x00, 0xBF, ++0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0xE5, 0xFE, 0x14, 0x00, 0x90, 0xF8, 0x46, 0x30, 0x90, 0xF8, 0x47, 0x20, ++0x19, 0x44, 0xB1, 0xFB, 0xF2, 0xF0, 0x02, 0xFB, 0x10, 0x10, 0x70, 0x47, 0x90, 0xF8, 0x46, 0x30, 0x90, 0xF8, 0x48, 0x00, ++0x19, 0x44, 0x08, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x03, 0x4B, 0x1B, 0x69, 0xA0, 0xEB, 0x93, 0x20, 0xC0, 0xF3, 0xC0, 0x30, ++0x70, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x70, 0xB5, 0x90, 0xF8, 0x46, 0x30, 0x03, 0x44, 0x9A, 0x79, 0x02, 0x2A, ++0x17, 0xD1, 0x00, 0x26, 0x04, 0x46, 0x35, 0x46, 0x9D, 0x71, 0xA3, 0x88, 0x22, 0x68, 0x01, 0x33, 0xC3, 0xF3, 0x0B, 0x03, ++0xA3, 0x80, 0x01, 0x21, 0x20, 0x46, 0x90, 0x47, 0x54, 0xFA, 0x80, 0xF3, 0x84, 0xF8, 0x46, 0x00, 0x9A, 0x79, 0x01, 0x36, ++0x02, 0x2A, 0x76, 0xB2, 0xEC, 0xD0, 0x30, 0x46, 0x70, 0xBD, 0x00, 0x26, 0x30, 0x46, 0x70, 0xBD, 0x38, 0xB5, 0x85, 0x88, ++0x03, 0x68, 0x49, 0x1B, 0xC1, 0xF3, 0x0B, 0x01, 0x04, 0x46, 0x15, 0x46, 0x98, 0x47, 0x20, 0x44, 0x85, 0x71, 0x38, 0xBD, ++0xF8, 0xB5, 0x05, 0x46, 0x33, 0x48, 0x6F, 0x6A, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0xC1, 0x00, 0xBF, 0x02, 0x44, 0x69, ++0x03, 0xD5, 0x11, 0x46, 0x4B, 0xB3, 0x00, 0x2A, 0x49, 0xD0, 0xA2, 0x88, 0x29, 0x8C, 0x23, 0x68, 0x89, 0x1A, 0xC1, 0xF3, ++0x0B, 0x01, 0x20, 0x46, 0x98, 0x47, 0x20, 0x44, 0x02, 0x23, 0x83, 0x71, 0x94, 0xF8, 0x46, 0x30, 0x23, 0x44, 0x00, 0x26, ++0x9A, 0x79, 0x02, 0x2A, 0x13, 0xD1, 0x35, 0x46, 0x9D, 0x71, 0xA3, 0x88, 0x22, 0x68, 0x01, 0x33, 0xC3, 0xF3, 0x0B, 0x03, ++0xA3, 0x80, 0x01, 0x21, 0x20, 0x46, 0x90, 0x47, 0x54, 0xFA, 0x80, 0xF3, 0x84, 0xF8, 0x46, 0x00, 0x9A, 0x79, 0x01, 0x36, ++0x02, 0x2A, 0x76, 0xB2, 0xEC, 0xD0, 0x30, 0x46, 0xF8, 0xBD, 0x00, 0x2A, 0xD5, 0xD1, 0x19, 0x4B, 0xB5, 0xF8, 0x40, 0x00, ++0x1B, 0x69, 0xA0, 0xEB, 0x93, 0x23, 0x1B, 0x04, 0xCD, 0xD4, 0xEA, 0x8B, 0xEB, 0x6C, 0x6F, 0xEA, 0x42, 0x42, 0x1C, 0x69, ++0x6F, 0xEA, 0x52, 0x42, 0xEA, 0x83, 0x44, 0xF0, 0x02, 0x04, 0x6A, 0x8F, 0x0E, 0x46, 0x29, 0x8F, 0x19, 0x80, 0x1C, 0x61, ++0xE9, 0x8F, 0xAC, 0x8F, 0x5A, 0x80, 0x2A, 0x8C, 0x1A, 0x81, 0x9C, 0x80, 0xD9, 0x80, 0x58, 0x81, 0xDB, 0xE7, 0x09, 0x48, ++0xB5, 0xF8, 0x40, 0x20, 0x03, 0x69, 0xA2, 0xEB, 0x93, 0x23, 0x1E, 0x04, 0xAD, 0xD4, 0x03, 0x69, 0x05, 0x48, 0xA2, 0xEB, ++0x93, 0x22, 0xC2, 0xF3, 0xC0, 0x32, 0xF4, 0xF7, 0x23, 0xF8, 0xA4, 0xE7, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, ++0x34, 0xC2, 0x15, 0x00, 0xF8, 0xB5, 0x0D, 0x4D, 0x0D, 0x4E, 0xFF, 0x27, 0x2F, 0x73, 0x00, 0x24, 0x08, 0xE0, 0x0F, 0x2C, ++0x85, 0xF8, 0x24, 0x70, 0x03, 0xDD, 0x4C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0xEB, 0x62, 0x18, 0x35, 0x20, 0x02, 0x00, 0xF4, ++0x7F, 0x40, 0x40, 0xF0, 0x08, 0x00, 0x01, 0x34, 0x00, 0x21, 0xF2, 0xF7, 0x95, 0xFB, 0x20, 0x2C, 0xEB, 0xD1, 0xF8, 0xBD, ++0xF4, 0xE4, 0x17, 0x00, 0x74, 0xDB, 0x17, 0x00, 0x11, 0x4B, 0x00, 0xEB, 0x40, 0x00, 0x03, 0xEB, 0xC0, 0x00, 0x42, 0x7B, ++0x03, 0x7B, 0x01, 0x7C, 0x72, 0xB1, 0x01, 0x2A, 0x0B, 0xD1, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x0B, 0x4A, ++0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA5, 0x21, 0x70, 0x47, 0x70, 0x47, 0x03, 0xEB, 0x83, 0x02, ++0xC3, 0xEB, 0x02, 0x13, 0x04, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA4, 0x21, 0x70, 0x47, ++0xF4, 0xE4, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x00, 0x28, 0x09, 0x4B, 0x14, 0xBF, 0x10, 0x20, 0x00, 0x20, 0x03, 0xEB, ++0x40, 0x03, 0x14, 0xBF, 0x20, 0x21, 0x10, 0x21, 0x33, 0xF8, 0x02, 0x2F, 0x22, 0xB1, 0x01, 0x30, 0x88, 0x42, 0xF9, 0xDB, ++0x21, 0x20, 0x70, 0x47, 0x80, 0xB2, 0x70, 0x47, 0xF2, 0xDF, 0x17, 0x00, 0x38, 0xB5, 0x05, 0x02, 0x45, 0xF0, 0x08, 0x05, ++0x04, 0x46, 0x29, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0xF2, 0xF7, 0x5A, 0xF8, 0x29, 0x46, 0x42, 0xF2, 0x01, 0x00, 0xF2, 0xF7, ++0x55, 0xF8, 0x16, 0x48, 0x04, 0xEB, 0x44, 0x04, 0x00, 0xEB, 0xC4, 0x04, 0x62, 0x7B, 0x23, 0x7B, 0x21, 0x7C, 0x92, 0xB1, ++0x01, 0x2A, 0x0A, 0xD1, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x0F, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, ++0x21, 0x22, 0x83, 0xF8, 0xA5, 0x21, 0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x38, 0x40, 0xF2, 0xF7, 0x25, 0xBB, 0x03, 0xEB, ++0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x07, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA4, 0x21, ++0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x38, 0x40, 0xF2, 0xF7, 0x14, 0xBB, 0xF4, 0xE4, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x07, 0x4B, 0x00, 0xEB, 0x40, 0x02, 0x03, 0xEB, 0xC2, 0x03, 0x00, 0x02, 0x5A, 0x89, 0x00, 0xF4, 0x7F, 0x41, 0x41, 0xF0, ++0x08, 0x01, 0x92, 0x02, 0x42, 0xF2, 0x01, 0x00, 0xF1, 0xF7, 0x64, 0xBF, 0xF4, 0xE4, 0x17, 0x00, 0x0A, 0x02, 0x02, 0xF4, ++0x7F, 0x42, 0x38, 0xB5, 0x42, 0xF0, 0x08, 0x02, 0x05, 0x46, 0x0C, 0x46, 0x06, 0x23, 0x00, 0x21, 0x28, 0x20, 0xF2, 0xF7, ++0xF7, 0xF8, 0x0A, 0x49, 0x04, 0xEB, 0x44, 0x04, 0x01, 0xEB, 0xC4, 0x04, 0x62, 0x7B, 0x45, 0x70, 0x01, 0x3A, 0x18, 0xBF, ++0x01, 0x22, 0x02, 0x70, 0x22, 0x7C, 0x82, 0x70, 0xE2, 0x7B, 0xC2, 0x70, 0x22, 0x89, 0x82, 0x80, 0xBD, 0xE8, 0x38, 0x40, ++0xF2, 0xF7, 0x12, 0xB9, 0xF4, 0xE4, 0x17, 0x00, 0xF8, 0xB5, 0x0D, 0x02, 0x45, 0xF0, 0x08, 0x05, 0xAD, 0xB2, 0x03, 0x23, ++0x0C, 0x46, 0x07, 0x46, 0x2A, 0x46, 0x00, 0x21, 0x2A, 0x20, 0xF2, 0xF7, 0xD3, 0xF8, 0x12, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0x06, 0x46, 0x11, 0xDB, 0x0F, 0x49, 0x04, 0xEB, 0x44, 0x04, 0x01, 0xEB, 0xC4, 0x04, 0x30, 0x46, ++0x63, 0x7B, 0x77, 0x70, 0x01, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0x33, 0x70, 0x23, 0x7C, 0xB3, 0x70, 0xBD, 0xE8, 0xF8, 0x40, ++0xF2, 0xF7, 0xEA, 0xB8, 0x28, 0x46, 0xF2, 0xF7, 0x59, 0xFB, 0x04, 0x28, 0xE8, 0xD0, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, ++0x05, 0x22, 0xF4, 0xF7, 0x91, 0xF9, 0xE1, 0xE7, 0x38, 0x36, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x60, 0xC2, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x10, 0x4E, 0x11, 0x4D, 0x80, 0x46, 0x87, 0xB2, 0x00, 0x24, 0x36, 0xF8, ++0x02, 0x3F, 0x8B, 0xB1, 0x2B, 0x7B, 0x43, 0x45, 0x0E, 0xD1, 0x1F, 0xFA, 0x84, 0xF9, 0x4F, 0xEA, 0x09, 0x23, 0x03, 0xF4, ++0x7F, 0x43, 0x43, 0xF0, 0x08, 0x00, 0x04, 0x21, 0xF2, 0xF7, 0x88, 0xFA, 0x49, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xAA, 0xFF, ++0x01, 0x34, 0x20, 0x2C, 0x05, 0xF1, 0x18, 0x05, 0xE5, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0xF2, 0xDF, 0x17, 0x00, ++0xF4, 0xE4, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0xB0, 0xDF, 0xF8, 0x50, 0x92, 0xBD, 0xF8, 0x50, 0x40, 0x09, 0x94, ++0xBD, 0xF8, 0x54, 0x40, 0x07, 0x94, 0x16, 0x9C, 0x04, 0x94, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x94, 0x87, 0x4F, ++0x94, 0xF8, 0x22, 0x80, 0xDF, 0xF8, 0x30, 0xA2, 0x03, 0x91, 0x06, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x08, 0x70, ++0x93, 0x46, 0x00, 0x6C, 0x08, 0x93, 0x00, 0x28, 0x00, 0xF0, 0xC4, 0x80, 0xDA, 0xF8, 0x00, 0x30, 0x02, 0x79, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9B, 0x80, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x73, 0x4F, 0xF4, 0xC0, 0x71, ++0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xDF, 0xF7, 0x14, 0xFB, 0x04, 0x46, 0x00, 0x28, ++0x00, 0xF0, 0x9B, 0x80, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x08, 0xF5, 0x78, 0x19, 0x21, 0x46, 0x05, 0x90, 0xF1, 0xF7, ++0x05, 0xFC, 0x4F, 0xF4, 0x1E, 0x72, 0xA3, 0x6C, 0x02, 0xFB, 0x06, 0xF2, 0x00, 0x21, 0x26, 0x32, 0x6F, 0xF0, 0x2F, 0x0C, ++0x83, 0xF8, 0x68, 0xC0, 0x83, 0xF8, 0x69, 0x10, 0x83, 0xF8, 0x6A, 0x10, 0x83, 0xF8, 0x6B, 0x10, 0x39, 0xF8, 0x02, 0x10, ++0xA3, 0xF8, 0x6C, 0x10, 0x09, 0xEB, 0x02, 0x01, 0x5C, 0x35, 0xB1, 0xF8, 0x02, 0xC0, 0xA3, 0xF8, 0x6E, 0xC0, 0xB1, 0xF8, ++0x04, 0xC0, 0xA3, 0xF8, 0x70, 0xC0, 0x37, 0xF8, 0x05, 0xC0, 0xA3, 0xF8, 0x72, 0xC0, 0x07, 0xEB, 0x05, 0x0C, 0x03, 0xF1, ++0x68, 0x00, 0xBC, 0xF8, 0x02, 0xE0, 0xA3, 0xF8, 0x74, 0xE0, 0xBC, 0xF8, 0x04, 0xE0, 0x06, 0x90, 0x05, 0x98, 0xA3, 0xF8, ++0x76, 0xE0, 0x90, 0xF8, 0x62, 0x00, 0x02, 0x28, 0x5E, 0xD0, 0x39, 0xF8, 0x02, 0x20, 0xA3, 0xF8, 0x78, 0x20, 0x4A, 0x88, ++0xA3, 0xF8, 0x7A, 0x20, 0x8A, 0x88, 0xA3, 0xF8, 0x7C, 0x20, 0x4E, 0x49, 0xB1, 0xF8, 0xFC, 0x21, 0x01, 0x32, 0x92, 0xB2, ++0xA1, 0xF8, 0xFC, 0x21, 0x10, 0x01, 0x00, 0x21, 0xA3, 0xF8, 0x7E, 0x00, 0x03, 0x22, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, ++0x35, 0x10, 0x84, 0xF8, 0x1C, 0x80, 0x66, 0x77, 0xD0, 0x21, 0x20, 0x46, 0x00, 0xF0, 0xE6, 0xFB, 0x01, 0x28, 0x70, 0xD0, ++0x18, 0x25, 0xBB, 0xF1, 0x01, 0x0F, 0x4A, 0xD0, 0xBB, 0xF1, 0x02, 0x0F, 0x54, 0xD0, 0xBB, 0xF1, 0x00, 0x0F, 0x5C, 0xD0, ++0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x69, 0xDB, 0x03, 0x26, 0xE1, 0x6C, 0x94, 0xF8, 0x35, 0x30, ++0x4A, 0x6A, 0x1D, 0x44, 0x01, 0x3A, 0x04, 0x9B, 0x2A, 0x44, 0x04, 0x35, 0xC1, 0xE9, 0x0A, 0x25, 0x13, 0xB1, 0x63, 0x65, ++0x03, 0x9B, 0xA3, 0x65, 0x31, 0x46, 0x20, 0x46, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xDF, 0xF7, 0x97, 0xBA, 0x02, 0x2A, ++0x7F, 0xF4, 0x62, 0xAF, 0x2D, 0x49, 0x2E, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0xF4, 0xF7, 0x92, 0xF8, 0x01, 0x20, 0x4F, 0xF4, ++0xC0, 0x71, 0xDF, 0xF7, 0x79, 0xFA, 0x04, 0x46, 0x00, 0x28, 0x7F, 0xF4, 0x65, 0xAF, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x7A, 0x5B, 0xA3, 0xF8, 0x78, 0x20, 0xBC, 0xF8, 0x02, 0x20, 0xA3, 0xF8, 0x7A, 0x20, 0xBC, 0xF8, 0x04, 0x20, 0xA3, 0xF8, ++0x7C, 0x20, 0x9E, 0xE7, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE1, 0xDA, 0xDA, 0xE7, 0x06, 0x99, ++0x07, 0x9B, 0x00, 0x93, 0x29, 0x44, 0x08, 0x46, 0xDD, 0xE9, 0x08, 0x32, 0x03, 0x99, 0xF5, 0xF7, 0x4D, 0xFA, 0x03, 0x26, ++0x05, 0x44, 0xB4, 0xE7, 0xDD, 0xE9, 0x06, 0x02, 0x03, 0x99, 0x15, 0x4E, 0x0B, 0x7C, 0x28, 0x44, 0xF6, 0x5C, 0xF5, 0xF7, ++0x5D, 0xFA, 0x05, 0x44, 0xA9, 0xE7, 0x03, 0x99, 0x06, 0x98, 0x10, 0x4A, 0x0B, 0x7C, 0x28, 0x44, 0xD6, 0x5C, 0xF5, 0xF7, ++0x1B, 0xFA, 0x05, 0x44, 0x9F, 0xE7, 0x06, 0x99, 0x18, 0x22, 0x20, 0x46, 0xFF, 0xF7, 0xD2, 0xF9, 0x94, 0xF8, 0x33, 0x50, ++0x18, 0x35, 0x86, 0xE7, 0x05, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x6E, 0x22, 0xF4, 0xF7, 0x5A, 0xF8, 0x03, 0x26, 0x8E, 0xE7, ++0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0xC0, 0xB2, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x35, 0x4B, 0x87, 0xB0, ++0x81, 0x46, 0x8A, 0x46, 0x93, 0x46, 0x10, 0x24, 0x33, 0xF8, 0x02, 0x5F, 0x35, 0xB1, 0x01, 0x34, 0x20, 0x2C, 0xF9, 0xD1, ++0x03, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2E, 0x4A, 0xDF, 0xF8, 0xCC, 0x80, 0x04, 0xEB, 0x44, 0x03, 0x02, 0xEB, ++0xC3, 0x06, 0xDB, 0x00, 0x86, 0xF8, 0x0C, 0x90, 0x86, 0xF8, 0x10, 0xA0, 0x05, 0x93, 0x06, 0xF0, 0xBB, 0xFB, 0x28, 0x49, ++0x70, 0x74, 0x09, 0x68, 0x27, 0x48, 0xB1, 0xF8, 0x02, 0xC0, 0x10, 0xF8, 0x0A, 0x00, 0x05, 0x9B, 0x25, 0x49, 0x22, 0x4A, ++0x02, 0x95, 0x09, 0xEB, 0x89, 0x07, 0xC9, 0xEB, 0x07, 0x17, 0x57, 0x44, 0x00, 0x95, 0x34, 0x37, 0x51, 0xF8, 0x20, 0xE0, ++0xD5, 0x50, 0x08, 0xEB, 0xC7, 0x00, 0x27, 0x23, 0x01, 0x93, 0xA6, 0xF8, 0x0A, 0xC0, 0x4F, 0xF0, 0x01, 0x0C, 0x86, 0xF8, ++0x0F, 0xE0, 0x86, 0xF8, 0x0E, 0xC0, 0x86, 0xF8, 0x0D, 0xC0, 0x31, 0x46, 0x2B, 0x46, 0x44, 0x71, 0xA6, 0xF8, 0x08, 0xB0, ++0x48, 0x46, 0x02, 0x22, 0xFF, 0xF7, 0x82, 0xFE, 0x24, 0x02, 0x31, 0x46, 0x48, 0x46, 0x2B, 0x46, 0x2A, 0x46, 0xCD, 0xE9, ++0x01, 0x55, 0x00, 0x95, 0xFF, 0xF7, 0x78, 0xFE, 0x44, 0xF0, 0x08, 0x04, 0x0E, 0x4B, 0xA4, 0xB2, 0x1B, 0x69, 0x48, 0xF8, ++0x37, 0x30, 0x21, 0x46, 0x4F, 0xF4, 0xFA, 0x22, 0x4F, 0xF4, 0x00, 0x50, 0xF1, 0xF7, 0x46, 0xFD, 0x20, 0x46, 0x02, 0x21, ++0xF2, 0xF7, 0xDE, 0xF8, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0xE0, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, ++0xC8, 0x35, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0x7C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x19, 0x4C, 0x1A, 0x4D, 0xDF, 0xF8, 0x68, 0xA0, 0xC4, 0xEB, 0x44, 0x29, 0x4F, 0xEA, 0xC9, 0x19, ++0x84, 0xB0, 0x07, 0x46, 0x1F, 0xFA, 0x89, 0xF9, 0x04, 0xF1, 0x40, 0x06, 0x4F, 0xF0, 0x00, 0x08, 0x34, 0xF8, 0x02, 0x3F, ++0xCB, 0xB1, 0x2B, 0x7B, 0xBB, 0x42, 0x16, 0xD1, 0x09, 0xEB, 0xC4, 0x10, 0xA0, 0xF5, 0x80, 0x70, 0x40, 0xF0, 0x08, 0x00, ++0x80, 0xB2, 0x04, 0x21, 0xF2, 0xF7, 0xAA, 0xF8, 0x27, 0x23, 0xCD, 0xE9, 0x00, 0x83, 0xCD, 0xF8, 0x08, 0xA0, 0x00, 0x23, ++0x02, 0x22, 0x29, 0x46, 0x38, 0x46, 0x85, 0xF8, 0x13, 0x80, 0xFF, 0xF7, 0x25, 0xFE, 0xB4, 0x42, 0x05, 0xF1, 0x18, 0x05, ++0xDE, 0xD1, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xF2, 0xDF, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0xE5, 0xFE, 0x14, 0x00, ++0xFF, 0x29, 0x2F, 0xD0, 0xF8, 0xB5, 0xC3, 0xB2, 0x03, 0xEB, 0x83, 0x02, 0x16, 0x4F, 0xC3, 0xEB, 0x02, 0x13, 0x53, 0xFA, ++0x81, 0xF3, 0x07, 0xEB, 0xC3, 0x03, 0x0C, 0x46, 0x93, 0xF8, 0xA5, 0x61, 0x21, 0x2E, 0x05, 0x46, 0x1C, 0xD0, 0x30, 0x02, ++0x40, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0x20, 0xF9, 0x01, 0x28, 0x15, 0xD1, 0x0D, 0x4B, 0x06, 0xEB, 0x46, 0x06, 0x03, 0xEB, ++0xC6, 0x06, 0x4F, 0xF4, 0x9E, 0x71, 0x01, 0xFB, 0x05, 0x44, 0x73, 0x69, 0x07, 0xEB, 0x44, 0x04, 0x9A, 0x88, 0xB4, 0xF8, ++0x34, 0x31, 0x9B, 0x1A, 0x13, 0xF4, 0x7C, 0x6F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xF8, 0xBD, 0x01, 0x20, 0xF8, 0xBD, ++0x02, 0x20, 0x70, 0x47, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x04, 0x46, 0x50, 0x48, ++0xE1, 0x7E, 0xD0, 0xF8, 0x10, 0x90, 0xFF, 0x29, 0x23, 0xD0, 0x65, 0x7F, 0x4D, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, ++0x05, 0x63, 0x5A, 0x68, 0x97, 0x07, 0x1A, 0xD5, 0x05, 0xEB, 0x85, 0x07, 0xC5, 0xEB, 0x07, 0x17, 0x7A, 0x18, 0x34, 0x32, ++0x06, 0xEB, 0xC2, 0x0C, 0x9C, 0xF8, 0x07, 0xE0, 0x9C, 0xF8, 0x05, 0x80, 0x0E, 0xF1, 0x01, 0x0E, 0xB8, 0xF1, 0x21, 0x0F, ++0x8C, 0xF8, 0x07, 0xE0, 0x09, 0xD1, 0x00, 0x69, 0x56, 0xF8, 0x32, 0x20, 0xDF, 0xF8, 0x14, 0xC1, 0x82, 0x1A, 0x62, 0x45, ++0x48, 0xD8, 0xBD, 0xE8, 0xF0, 0x87, 0xDF, 0xF8, 0x0C, 0xA1, 0x08, 0xEB, 0x48, 0x07, 0x0A, 0xEB, 0xC7, 0x07, 0x4F, 0xEA, ++0x08, 0x20, 0xC7, 0xF8, 0x04, 0x90, 0x40, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0xC3, 0xF8, 0x01, 0x28, 0x4F, 0xEA, 0x48, 0x09, ++0xEB, 0xD1, 0x7F, 0x69, 0xE3, 0x8B, 0xB8, 0x88, 0x60, 0x84, 0xD9, 0x07, 0x57, 0xD4, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, ++0x05, 0x65, 0xD5, 0xF8, 0x4C, 0x21, 0x92, 0xF8, 0xA2, 0x20, 0x52, 0x07, 0x03, 0xD5, 0x62, 0x6A, 0x42, 0xF4, 0x00, 0x12, ++0x62, 0x62, 0x21, 0x8C, 0x3A, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x09, 0x1A, 0xE3, 0x83, 0xC1, 0xF3, 0x0B, 0x01, 0x38, 0x46, ++0x90, 0x47, 0x38, 0x44, 0x01, 0x23, 0x83, 0x71, 0xE3, 0x8B, 0xDB, 0x07, 0x07, 0xD4, 0x1F, 0x4A, 0x20, 0x4B, 0x12, 0x69, ++0x9B, 0x8D, 0x03, 0xEB, 0x92, 0x23, 0xA4, 0xF8, 0x40, 0x30, 0xC8, 0x44, 0x4F, 0xEA, 0xC8, 0x08, 0x5A, 0xF8, 0x08, 0x30, ++0x01, 0x33, 0x4A, 0xF8, 0x08, 0x30, 0xB6, 0xE7, 0x93, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0xB2, 0xD0, 0x17, 0x4B, 0x18, 0x48, ++0x5A, 0x5C, 0x54, 0x23, 0x03, 0xFB, 0x02, 0xF3, 0xC3, 0x58, 0x00, 0x2B, 0xA9, 0xD1, 0x15, 0x4B, 0x53, 0xF8, 0x32, 0x30, ++0x00, 0x2B, 0xA4, 0xD1, 0xBB, 0x18, 0x46, 0x33, 0x56, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x9E, 0xD1, 0x23, 0x7F, 0x10, 0x48, ++0xA4, 0x26, 0x06, 0xFB, 0x03, 0x23, 0x9E, 0x33, 0x50, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x94, 0xD1, 0x0C, 0x4B, 0x22, 0x8C, ++0x1B, 0x6A, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x03, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0x89, 0xD1, 0xA2, 0xE7, ++0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, ++0x24, 0x64, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x40, 0x42, 0x0F, 0x00, 0xF4, 0xE4, 0x17, 0x00, ++0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x1C, 0x48, 0x6C, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x03, 0x5E, 0x68, ++0xB6, 0x07, 0x0E, 0xD5, 0xEB, 0x7E, 0x04, 0xEB, 0x84, 0x06, 0xC4, 0xEB, 0x06, 0x14, 0x1C, 0x44, 0x34, 0x34, 0x00, 0xEB, ++0xC4, 0x04, 0xE3, 0x79, 0x01, 0x3B, 0xE3, 0x71, 0xEB, 0x8B, 0x9B, 0x07, 0x02, 0xD4, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, ++0x66, 0x79, 0x21, 0x2E, 0xF9, 0xD0, 0x30, 0x02, 0x40, 0xF0, 0x08, 0x00, 0x88, 0x46, 0x91, 0x46, 0xF2, 0xF7, 0x20, 0xF8, ++0x01, 0x28, 0xF0, 0xD1, 0x06, 0xEB, 0x46, 0x07, 0xFF, 0x00, 0xDF, 0xF8, 0x20, 0xC0, 0x5C, 0xF8, 0x07, 0x40, 0x01, 0x3C, ++0x4C, 0xF8, 0x07, 0x40, 0x4B, 0x46, 0x42, 0x46, 0x28, 0x46, 0x31, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x46, 0xBB, ++0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x38, 0xB5, 0x45, 0x69, 0x04, 0x46, 0x40, 0x22, 0x00, 0x21, 0xA8, 0x1D, ++0xCF, 0xF7, 0x58, 0xF9, 0x22, 0x7B, 0x21, 0x7C, 0x0C, 0x4B, 0x4F, 0xF4, 0x9E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x03, 0xEB, ++0x42, 0x03, 0x00, 0x22, 0xB3, 0xF8, 0x34, 0x31, 0xAB, 0x80, 0x85, 0xF8, 0x46, 0x20, 0xE3, 0x7B, 0x85, 0xF8, 0x47, 0x30, ++0x5A, 0x1E, 0x1A, 0x42, 0x12, 0xBF, 0x04, 0x4B, 0x04, 0x4B, 0x85, 0xF8, 0x48, 0x20, 0x2B, 0x60, 0x38, 0xBD, 0x00, 0xBF, ++0x68, 0x65, 0x17, 0x00, 0xDD, 0x04, 0x15, 0x00, 0xF1, 0x04, 0x15, 0x00, 0x90, 0xF8, 0x47, 0x10, 0x59, 0xB1, 0x43, 0x1D, ++0x19, 0x44, 0x00, 0x20, 0x13, 0xF8, 0x01, 0x2F, 0x02, 0x2A, 0x04, 0xBF, 0x01, 0x30, 0x40, 0xB2, 0x8B, 0x42, 0xF7, 0xD1, ++0x70, 0x47, 0x08, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x11, 0x4A, 0x12, 0x4B, 0x12, 0x68, 0x10, 0xB5, 0x00, 0xEB, 0x80, 0x04, ++0xC0, 0xEB, 0x04, 0x10, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x90, 0xF8, 0xA4, 0x41, 0x00, 0x2B, ++0x08, 0xDB, 0x0B, 0x4B, 0x0B, 0x4A, 0x04, 0xEB, 0x44, 0x04, 0x03, 0xEB, 0xC4, 0x04, 0x13, 0x69, 0x63, 0x60, 0x10, 0xBD, ++0x20, 0x2C, 0xF4, 0xD9, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x52, 0x32, 0xF3, 0xF7, 0xEA, 0xFD, 0xED, 0xE7, 0x00, 0xBF, ++0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, ++0x9C, 0xC2, 0x15, 0x00, 0x10, 0xF0, 0x0C, 0x0F, 0x11, 0xD1, 0x00, 0xF0, 0xF0, 0x03, 0xC0, 0x2B, 0x0B, 0xD0, 0xD0, 0x2B, ++0x05, 0xD0, 0xA3, 0xF1, 0xA0, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x0F, 0x29, 0x24, 0xD8, 0x03, 0x29, ++0x03, 0xD8, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x04, 0x39, 0x0B, 0x29, 0xF8, 0xD8, 0x01, 0xA3, 0x53, 0xF8, ++0x21, 0xF0, 0x00, 0xBF, 0xEF, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, ++0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, ++0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, 0xB1, 0xF1, 0x7F, 0x00, 0x18, 0xBF, 0x01, 0x20, ++0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x08, 0xB0, 0xB0, 0xF8, 0x00, 0x90, 0x1B, 0xF8, 0x01, 0xA0, ++0x0C, 0x46, 0x85, 0xB0, 0x80, 0x46, 0x51, 0x46, 0x48, 0x46, 0x1D, 0x46, 0xFF, 0xF7, 0xB4, 0xFF, 0x0B, 0xEB, 0x04, 0x0C, ++0x00, 0x28, 0x00, 0xF0, 0x81, 0x80, 0x98, 0xF8, 0x09, 0x30, 0xFF, 0x2B, 0x24, 0xD0, 0x98, 0xF8, 0x0A, 0x70, 0xFF, 0x2F, ++0x20, 0xD0, 0x50, 0x49, 0x16, 0x46, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x12, 0xD2, 0xF8, 0xA8, 0x24, 0x00, 0x2A, ++0x6E, 0xD0, 0x98, 0xF8, 0x30, 0x20, 0x12, 0x07, 0x6E, 0xD5, 0x09, 0xF0, 0xFC, 0x03, 0xD0, 0x2B, 0x00, 0xF0, 0x84, 0x80, ++0x46, 0x4B, 0x4F, 0xF4, 0xA4, 0x68, 0x08, 0xFB, 0x07, 0xF8, 0x43, 0x44, 0xD3, 0xF8, 0xAC, 0x34, 0x00, 0x2B, 0x5B, 0xD0, ++0x0B, 0xF1, 0x13, 0x03, 0xB3, 0x42, 0x05, 0xDB, 0x00, 0x23, 0x01, 0x20, 0x2B, 0x70, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0xB1, 0x1E, 0xA1, 0xEB, 0x0B, 0x01, 0x0C, 0xF1, 0x02, 0x00, 0x89, 0xB2, 0xF2, 0xF7, 0x3A, 0xFC, 0x1F, 0xFA, 0x8B, 0xF3, ++0x00, 0x28, 0xED, 0xD0, 0xB0, 0xF8, 0x02, 0xC0, 0xAC, 0xF1, 0x04, 0x02, 0x01, 0x2A, 0xE7, 0xD8, 0x33, 0x4A, 0xCC, 0xEB, ++0x0C, 0x11, 0x08, 0xEB, 0xC1, 0x01, 0x11, 0x44, 0x4F, 0xEA, 0x0C, 0x12, 0x03, 0x92, 0x91, 0xF8, 0x3B, 0x22, 0x00, 0x2A, ++0xDA, 0xD0, 0xD1, 0xE9, 0x76, 0xAB, 0x42, 0x68, 0x4F, 0xF0, 0x00, 0x0E, 0x22, 0xF0, 0x7F, 0x48, 0xF3, 0x45, 0x08, 0xBF, ++0xC2, 0x45, 0xF1, 0x46, 0xCE, 0xD2, 0x82, 0x46, 0xDD, 0xF8, 0x0C, 0xB0, 0x5A, 0xF8, 0x0A, 0x2F, 0x00, 0x92, 0xDA, 0xF8, ++0x04, 0x20, 0x01, 0x92, 0xC1, 0xE9, 0x76, 0x89, 0x12, 0x30, 0x52, 0x46, 0x02, 0xF8, 0x01, 0xEB, 0x82, 0x42, 0xFB, 0xD1, ++0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x07, 0xF0, 0xAB, 0xEB, 0x0C, 0x0C, 0x21, 0x46, 0x00, 0xF5, 0xEC, 0x70, 0x1A, 0x4C, ++0x00, 0xEB, 0xCC, 0x00, 0x20, 0x44, 0x32, 0x46, 0x00, 0xF0, 0xD2, 0xFA, 0xDD, 0xE9, 0x00, 0x34, 0x8C, 0x42, 0x08, 0xBF, ++0x83, 0x42, 0xA7, 0xD1, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x4A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, ++0x03, 0x23, 0x5B, 0x68, 0x1B, 0x07, 0xF3, 0xD5, 0x19, 0xF4, 0x80, 0x4F, 0xF0, 0xD1, 0x09, 0xF0, 0xFC, 0x09, 0xB9, 0xF1, ++0xC0, 0x0F, 0x02, 0xD0, 0xB9, 0xF1, 0xA0, 0x0F, 0x90, 0xD1, 0xAA, 0xF1, 0x06, 0x01, 0x01, 0x29, 0x8C, 0xD8, 0x01, 0x20, ++0x28, 0x70, 0xE2, 0xE7, 0xAA, 0xF1, 0x0D, 0x01, 0x01, 0x29, 0x3F, 0xF6, 0x77, 0xAF, 0x89, 0xF4, 0x80, 0x40, 0xC0, 0xF3, ++0x80, 0x30, 0xD8, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x45, 0x7F, 0x06, 0x7F, 0xFF, 0x2D, ++0x2B, 0xD0, 0x19, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x06, 0x73, 0xD3, 0xF8, 0xA8, 0x04, 0xE0, 0xB1, 0x0C, 0x46, ++0x20, 0x46, 0x11, 0x46, 0xFF, 0xF7, 0xF0, 0xFE, 0xB0, 0xB1, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0xF5, 0x11, 0x4B, ++0xE8, 0x5C, 0x10, 0xF0, 0x01, 0x00, 0x0E, 0xD0, 0x04, 0xF0, 0xFC, 0x04, 0xD0, 0x2C, 0x12, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, ++0x03, 0xFB, 0x06, 0x76, 0xD6, 0xF8, 0xAC, 0x34, 0x00, 0x2B, 0x0C, 0xBF, 0x00, 0x20, 0x02, 0x20, 0xF8, 0xBD, 0x1D, 0x44, ++0x55, 0xF8, 0x22, 0x0C, 0xC0, 0xF3, 0xC0, 0x00, 0xF8, 0xBD, 0x00, 0x20, 0xF8, 0xBD, 0x0D, 0x3A, 0x01, 0x2A, 0xE9, 0xD8, ++0xF2, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x8E, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x2A, 0x4C, 0x03, 0x7F, 0x4F, 0xF4, ++0xA4, 0x60, 0x00, 0xFB, 0x03, 0x43, 0x02, 0xEB, 0x01, 0x0C, 0xD3, 0xF8, 0xAC, 0x04, 0x00, 0x28, 0x47, 0xD0, 0x4C, 0x23, ++0x53, 0x54, 0x10, 0x23, 0x8C, 0xF8, 0x01, 0x30, 0xD0, 0xE9, 0x12, 0x37, 0x01, 0x33, 0x90, 0xF8, 0x61, 0x40, 0xAC, 0xF8, ++0x02, 0x40, 0x47, 0xF1, 0x00, 0x07, 0xC0, 0xE9, 0x12, 0x37, 0x0C, 0xF1, 0x04, 0x0E, 0x00, 0x24, 0x01, 0xE0, 0xD0, 0xE9, ++0x12, 0x37, 0xC4, 0xF1, 0x20, 0x06, 0xE3, 0x40, 0xA4, 0xF1, 0x20, 0x05, 0x07, 0xFA, 0x06, 0xF6, 0x33, 0x43, 0x27, 0xFA, ++0x05, 0xF5, 0x08, 0x34, 0x2B, 0x43, 0x30, 0x2C, 0x0E, 0xF8, 0x01, 0x3B, 0xED, 0xD1, 0x0C, 0xF1, 0x0A, 0x06, 0x0C, 0xF1, ++0x12, 0x04, 0x33, 0x46, 0x00, 0x25, 0x03, 0xF8, 0x01, 0x5B, 0xA3, 0x42, 0xFB, 0xD1, 0x12, 0x32, 0x18, 0x23, 0x92, 0xB2, ++0x00, 0xF0, 0x22, 0xFA, 0x00, 0x23, 0xC3, 0xF1, 0x20, 0x05, 0x20, 0xFA, 0x03, 0xF2, 0xA3, 0xF1, 0x20, 0x04, 0x01, 0xFA, ++0x05, 0xF5, 0x2A, 0x43, 0x21, 0xFA, 0x04, 0xF4, 0x08, 0x33, 0x22, 0x43, 0x40, 0x2B, 0x06, 0xF8, 0x01, 0x2B, 0xEE, 0xD1, ++0x12, 0x20, 0xF8, 0xBD, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x0A, 0x68, 0x05, 0x68, 0x4B, 0x68, 0xAE, 0x4C, ++0xDF, 0xF8, 0xBC, 0x82, 0x8F, 0xB0, 0x0E, 0x46, 0x6A, 0x40, 0x01, 0x92, 0x32, 0x46, 0x07, 0x46, 0x0D, 0x90, 0xF0, 0x68, ++0x01, 0x9E, 0x04, 0x91, 0x89, 0x68, 0x16, 0x60, 0x7E, 0x68, 0x07, 0x97, 0x83, 0xEA, 0x06, 0x05, 0x55, 0x60, 0x13, 0x46, ++0xBA, 0x68, 0x00, 0x95, 0x81, 0xEA, 0x02, 0x09, 0xC3, 0xF8, 0x08, 0x90, 0xFB, 0x68, 0xCD, 0xF8, 0x0C, 0x90, 0x43, 0x40, ++0x02, 0x93, 0x07, 0xF1, 0x90, 0x03, 0x0C, 0x93, 0x00, 0x9E, 0x01, 0x98, 0x02, 0x99, 0x03, 0x9D, 0xF3, 0xB2, 0x5F, 0xFA, ++0x80, 0xFC, 0xC6, 0xF3, 0x07, 0x2A, 0x4F, 0xEA, 0x10, 0x69, 0xE0, 0x5C, 0x06, 0x90, 0x0A, 0x0E, 0x96, 0x48, 0x08, 0x93, ++0x14, 0xF8, 0x0A, 0x30, 0x87, 0x5C, 0x18, 0xF8, 0x02, 0x10, 0x05, 0x93, 0xC5, 0xF3, 0x07, 0x26, 0xA3, 0x5C, 0x03, 0x9A, ++0x0A, 0x97, 0xC2, 0xF3, 0x07, 0x4E, 0xA7, 0x5D, 0x10, 0xF8, 0x0E, 0x20, 0x18, 0xF8, 0x09, 0xB0, 0x14, 0xF8, 0x0C, 0x50, ++0x38, 0x46, 0x06, 0x9F, 0x09, 0x90, 0x87, 0xEA, 0x0B, 0x0B, 0x05, 0x9F, 0x80, 0xEA, 0x0B, 0x0B, 0x69, 0x40, 0x87, 0x48, ++0x79, 0x40, 0x51, 0x40, 0x10, 0xF8, 0x0A, 0x20, 0x5D, 0x40, 0x6A, 0x40, 0x18, 0xF8, 0x0E, 0x50, 0x14, 0xF8, 0x0E, 0xE0, ++0x6A, 0x40, 0x09, 0x04, 0x41, 0xEA, 0x02, 0x21, 0x7F, 0x4A, 0x02, 0x9D, 0x12, 0xF8, 0x0C, 0x20, 0x5F, 0x46, 0x18, 0xF8, ++0x0A, 0xB0, 0x14, 0xF8, 0x09, 0xA0, 0x10, 0xF8, 0x09, 0x90, 0xCD, 0xF8, 0x2C, 0x90, 0x53, 0x40, 0xC5, 0xF3, 0x07, 0x49, ++0x06, 0x98, 0x18, 0xF8, 0x0C, 0x50, 0x76, 0x4A, 0x83, 0xEA, 0x0B, 0x0B, 0x0A, 0x9B, 0x18, 0xF8, 0x06, 0xC0, 0x5D, 0x40, ++0x12, 0xF8, 0x09, 0x30, 0x92, 0x5D, 0x71, 0x4E, 0x8A, 0xEA, 0x00, 0x00, 0x50, 0x40, 0x08, 0x9A, 0xB6, 0x5C, 0x18, 0xF8, ++0x02, 0x20, 0x8A, 0xEA, 0x06, 0x0A, 0x7B, 0x40, 0x0B, 0x9E, 0x05, 0x9F, 0x8A, 0xEA, 0x0C, 0x0A, 0x18, 0xF8, 0x09, 0xC0, ++0x14, 0xF8, 0x09, 0x90, 0x8E, 0xEA, 0x05, 0x05, 0x56, 0x40, 0x7D, 0x40, 0x1B, 0x04, 0x09, 0x9F, 0x80, 0xEA, 0x0C, 0x00, ++0x8E, 0xEA, 0x0B, 0x0B, 0x43, 0xEA, 0x00, 0x20, 0x89, 0xEA, 0x06, 0x03, 0x41, 0xEA, 0x0B, 0x02, 0x02, 0x99, 0x00, 0x9E, ++0x83, 0xEA, 0x07, 0x0B, 0x03, 0x9B, 0x89, 0xEA, 0x0A, 0x0A, 0x40, 0xEA, 0x0A, 0x0C, 0x5F, 0xFA, 0x83, 0xFE, 0x4F, 0xEA, ++0x13, 0x69, 0xC1, 0xF3, 0x07, 0x20, 0xCB, 0xB2, 0x01, 0x99, 0x02, 0x93, 0x42, 0xEA, 0x05, 0x67, 0x04, 0x9A, 0x03, 0x97, ++0xC1, 0xF3, 0x07, 0x4A, 0x4C, 0xEA, 0x0B, 0x65, 0x17, 0x60, 0x27, 0x5C, 0x55, 0x60, 0x36, 0x0E, 0x05, 0x95, 0x01, 0x97, ++0x4F, 0x4D, 0x14, 0xF8, 0x0A, 0x70, 0x06, 0x97, 0x18, 0xF8, 0x0A, 0x70, 0x15, 0xF8, 0x00, 0xB0, 0xA2, 0x5D, 0x18, 0xF8, ++0x06, 0x30, 0x08, 0x97, 0xC1, 0xF3, 0x07, 0x2C, 0x14, 0xF8, 0x0E, 0x10, 0x15, 0xF8, 0x0A, 0xA0, 0x18, 0xF8, 0x00, 0x00, ++0x01, 0x9F, 0x09, 0x90, 0xA8, 0x5D, 0x0A, 0x90, 0x4B, 0x40, 0x02, 0x98, 0x00, 0x9E, 0x25, 0x5C, 0x18, 0xF8, 0x09, 0x00, ++0x7B, 0x40, 0x83, 0xEA, 0x0A, 0x03, 0x14, 0xF8, 0x0C, 0xA0, 0x51, 0x40, 0x57, 0x46, 0x68, 0x40, 0x8B, 0xEA, 0x01, 0x0B, ++0x00, 0x97, 0x3B, 0x49, 0x14, 0xF8, 0x09, 0xA0, 0x11, 0xF8, 0x09, 0x90, 0xCD, 0xF8, 0x2C, 0x90, 0x78, 0x40, 0x08, 0x9F, ++0x8B, 0xEA, 0x07, 0x01, 0x35, 0x4F, 0x08, 0x91, 0x17, 0xF8, 0x0E, 0x90, 0x09, 0x99, 0x18, 0xF8, 0x0E, 0xE0, 0xC6, 0xF3, ++0x07, 0x46, 0x82, 0xEA, 0x09, 0x02, 0x17, 0xF8, 0x06, 0xB0, 0x17, 0xF8, 0x0C, 0x90, 0x02, 0x9F, 0x18, 0xF8, 0x0C, 0xC0, ++0x4A, 0x40, 0x2C, 0x49, 0x80, 0xEA, 0x0B, 0x00, 0x11, 0xF8, 0x07, 0xB0, 0x0A, 0x99, 0x8A, 0xEA, 0x05, 0x05, 0x89, 0xEA, ++0x05, 0x05, 0x8E, 0xEA, 0x01, 0x0E, 0x18, 0xF8, 0x07, 0x90, 0x0B, 0x99, 0x89, 0xEA, 0x01, 0x09, 0x08, 0x99, 0x1B, 0x04, ++0x43, 0xEA, 0x01, 0x21, 0x06, 0x9B, 0x8A, 0xEA, 0x0B, 0x0A, 0x18, 0xF8, 0x06, 0xB0, 0xA6, 0x5D, 0x01, 0x9F, 0x83, 0xEA, ++0x0E, 0x0E, 0x85, 0xEA, 0x0B, 0x05, 0x87, 0xEA, 0x0E, 0x0E, 0x00, 0x04, 0x00, 0x9F, 0x8A, 0xEA, 0x0C, 0x0A, 0x5A, 0x40, ++0x40, 0xEA, 0x05, 0x20, 0x86, 0xEA, 0x0A, 0x0A, 0x86, 0xEA, 0x09, 0x09, 0x11, 0x43, 0x87, 0xEA, 0x09, 0x09, 0x04, 0x9A, ++0x07, 0x9E, 0x03, 0x9F, 0x05, 0x9B, 0x40, 0xEA, 0x0A, 0x00, 0x41, 0xEA, 0x0E, 0x61, 0x40, 0xEA, 0x09, 0x60, 0xC2, 0xE9, ++0x02, 0x10, 0x35, 0x69, 0x6F, 0x40, 0x17, 0x60, 0x35, 0x46, 0x76, 0x69, 0x01, 0x97, 0x5E, 0x40, 0x56, 0x60, 0x00, 0x96, ++0x2E, 0x46, 0xAD, 0x69, 0x69, 0x40, 0x91, 0x60, 0xF3, 0x69, 0x03, 0x91, 0x43, 0x40, 0x02, 0x93, 0xD3, 0x60, 0x0C, 0x9B, ++0x06, 0xF1, 0x10, 0x01, 0x8B, 0x42, 0x07, 0x91, 0x7F, 0xF4, 0xC8, 0xAE, 0x06, 0xE0, 0x00, 0xBF, 0xE4, 0xC2, 0x15, 0x00, ++0xE4, 0xC3, 0x15, 0x00, 0xE4, 0xC4, 0x15, 0x00, 0xDD, 0xF8, 0x00, 0xE0, 0x3E, 0x0E, 0x5F, 0xFA, 0x8E, 0xF2, 0xDD, 0xE9, ++0x02, 0x39, 0x14, 0xF8, 0x06, 0xC0, 0xA2, 0x5C, 0x70, 0x46, 0x42, 0xEA, 0x0C, 0x62, 0x00, 0x92, 0x1D, 0x0E, 0x02, 0x9A, ++0x65, 0x5D, 0xF9, 0xB2, 0x5F, 0xFA, 0x89, 0xF3, 0x00, 0x0E, 0x61, 0x5C, 0x20, 0x5C, 0xE3, 0x5C, 0xB8, 0x46, 0x5F, 0xFA, ++0x82, 0xFC, 0x4F, 0xEA, 0x19, 0x67, 0x43, 0xEA, 0x00, 0x63, 0xE7, 0x5D, 0x14, 0xF8, 0x0C, 0x00, 0x41, 0xEA, 0x05, 0x61, ++0xCE, 0xF3, 0x07, 0x25, 0x40, 0xEA, 0x07, 0x67, 0x65, 0x5D, 0xC9, 0xF3, 0x07, 0x20, 0x41, 0xEA, 0x05, 0x21, 0x14, 0xF8, ++0x00, 0xB0, 0xC8, 0xF3, 0x07, 0x25, 0xC2, 0xF3, 0x07, 0x20, 0xCE, 0xF3, 0x07, 0x46, 0xC9, 0xF3, 0x07, 0x4A, 0xC2, 0xF3, ++0x07, 0x4C, 0xC8, 0xF3, 0x07, 0x48, 0x65, 0x5D, 0x00, 0x9A, 0x20, 0x5C, 0x14, 0xF8, 0x0A, 0xE0, 0x14, 0xF8, 0x0C, 0xC0, ++0x14, 0xF8, 0x08, 0x80, 0xA6, 0x5D, 0x47, 0xEA, 0x05, 0x27, 0x42, 0xEA, 0x0B, 0x24, 0x43, 0xEA, 0x00, 0x20, 0x04, 0x9A, ++0x0D, 0x9D, 0x41, 0xEA, 0x0E, 0x41, 0x44, 0xEA, 0x0C, 0x44, 0x40, 0xEA, 0x08, 0x40, 0x47, 0xEA, 0x06, 0x46, 0xC2, 0xE9, ++0x00, 0x14, 0xC2, 0xE9, 0x02, 0x06, 0xD5, 0xF8, 0xA0, 0x30, 0x59, 0x40, 0x11, 0x60, 0xD5, 0xF8, 0xA4, 0x30, 0x5C, 0x40, ++0x54, 0x60, 0xD5, 0xF8, 0xA8, 0x30, 0x58, 0x40, 0x90, 0x60, 0xD5, 0xF8, 0xAC, 0x30, 0x5E, 0x40, 0xD6, 0x60, 0x0F, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xD0, 0xE9, 0x01, 0x23, 0xF0, 0xB5, 0x19, 0x49, 0x05, 0x68, 0xC7, 0x68, 0x54, 0x04, 0x04, 0xF0, ++0x80, 0x76, 0x01, 0xEA, 0xD5, 0x34, 0x34, 0x43, 0x6E, 0x00, 0x06, 0xF0, 0xFE, 0x36, 0x34, 0x43, 0x4F, 0xEA, 0x43, 0x4E, ++0x7E, 0x04, 0x0E, 0xF0, 0x80, 0x7E, 0x04, 0x60, 0x01, 0xEA, 0xD2, 0x34, 0x52, 0x00, 0x06, 0xF0, 0x80, 0x7C, 0x44, 0xEA, ++0x0E, 0x04, 0x01, 0xEA, 0xD3, 0x36, 0x02, 0xF0, 0xFE, 0x32, 0x5B, 0x00, 0x22, 0x43, 0x46, 0xEA, 0x0C, 0x06, 0x03, 0xF0, ++0xFE, 0x33, 0x7C, 0x00, 0x33, 0x43, 0x01, 0xEA, 0xD7, 0x31, 0x04, 0xF0, 0xFE, 0x34, 0x21, 0x43, 0xC0, 0xE9, 0x01, 0x23, ++0x2B, 0x06, 0x48, 0xBF, 0x81, 0xF0, 0x07, 0x41, 0xC1, 0x60, 0xF0, 0xBD, 0x01, 0x01, 0x01, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x29, 0x2A, 0xBD, 0xB0, 0x0B, 0xD8, 0x8B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x00, 0x81, ++0x00, 0x20, 0x01, 0x46, 0x3D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x88, 0x46, 0x1D, 0x46, 0x31, 0xF8, 0x04, 0x3B, 0x06, 0x46, ++0x23, 0xF4, 0x60, 0x53, 0x14, 0x46, 0x0D, 0xF1, 0x2E, 0x00, 0x12, 0x22, 0xAD, 0xF8, 0x2C, 0x30, 0x05, 0xF0, 0xC4, 0xFC, ++0xD6, 0xE9, 0x14, 0x13, 0xD6, 0xE9, 0x16, 0x72, 0xC5, 0xF5, 0x7F, 0x40, 0xF4, 0x30, 0x80, 0xB2, 0x01, 0x90, 0xCD, 0xE9, ++0x11, 0x37, 0xDF, 0xF8, 0xEC, 0xE1, 0xDF, 0xF8, 0xEC, 0xC1, 0x10, 0x91, 0x13, 0x92, 0x10, 0xAE, 0x0D, 0xF1, 0xD0, 0x0A, ++0x01, 0x20, 0x02, 0xE0, 0x5E, 0xF8, 0x04, 0x0F, 0x10, 0x36, 0xC2, 0xF3, 0x07, 0x2B, 0x5F, 0xFA, 0x82, 0xF9, 0x1C, 0xF8, ++0x0B, 0xB0, 0x1C, 0xF8, 0x09, 0x90, 0x8B, 0xEA, 0x00, 0x00, 0x4F, 0xEA, 0x12, 0x6B, 0x40, 0xEA, 0x09, 0x60, 0xC2, 0xF3, ++0x07, 0x49, 0x1C, 0xF8, 0x0B, 0xB0, 0x1C, 0xF8, 0x09, 0x90, 0x40, 0xEA, 0x0B, 0x40, 0x40, 0xEA, 0x09, 0x20, 0x41, 0x40, ++0x4B, 0x40, 0x5F, 0x40, 0x7A, 0x40, 0x56, 0x45, 0xC6, 0xE9, 0x06, 0x72, 0xC6, 0xE9, 0x04, 0x13, 0xDA, 0xD1, 0x10, 0x22, ++0x00, 0x21, 0x03, 0xA8, 0xCE, 0xF7, 0xF6, 0xFC, 0x0D, 0xF1, 0x0A, 0x06, 0x00, 0x21, 0x07, 0xA8, 0x10, 0x22, 0xCE, 0xF7, ++0xEF, 0xFC, 0x0D, 0xF1, 0x1A, 0x07, 0x33, 0x46, 0x0D, 0xF1, 0x2A, 0x01, 0x33, 0xF8, 0x02, 0x2F, 0x31, 0xF8, 0x02, 0x0F, ++0x9F, 0x42, 0x82, 0xEA, 0x00, 0x02, 0x1A, 0x80, 0xF6, 0xD1, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x7B, 0xFD, 0x03, 0x9B, ++0x0F, 0x9A, 0x6D, 0x08, 0x08, 0xEB, 0x45, 0x08, 0x53, 0x40, 0xA8, 0xF1, 0x02, 0x01, 0x08, 0xF1, 0x0A, 0x05, 0x03, 0x93, ++0x0D, 0xF1, 0x0E, 0x02, 0x32, 0xF8, 0x02, 0x3F, 0x31, 0xF8, 0x02, 0x0F, 0x43, 0x40, 0x8D, 0x42, 0x13, 0x80, 0xF7, 0xD1, ++0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x62, 0xFD, 0x01, 0x9B, 0x1C, 0x44, 0xA4, 0xB2, 0x10, 0x2C, 0x08, 0xF1, 0x0C, 0x09, ++0x26, 0xD9, 0xA4, 0xF1, 0x11, 0x0A, 0xCA, 0xF3, 0x0B, 0x1A, 0x08, 0xEB, 0x0A, 0x18, 0x08, 0xF1, 0x1C, 0x08, 0x4D, 0x46, ++0xAA, 0x1E, 0x33, 0x46, 0x05, 0xF1, 0x0E, 0x00, 0x33, 0xF8, 0x02, 0x1F, 0x32, 0xF8, 0x02, 0xCF, 0x81, 0xEA, 0x0C, 0x01, ++0x90, 0x42, 0x19, 0x80, 0xF6, 0xD1, 0x10, 0x35, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x40, 0xFD, 0x45, 0x45, 0xEB, 0xD1, ++0xCA, 0xEB, 0x0A, 0x33, 0x10, 0x3C, 0x04, 0xEB, 0x03, 0x14, 0x0A, 0xF1, 0x01, 0x0A, 0xA4, 0xB2, 0x09, 0xEB, 0x0A, 0x19, ++0x07, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x30, 0xFD, 0x07, 0xA8, 0xFF, 0xF7, 0x01, 0xFF, 0x10, 0x2C, 0x34, 0xD0, 0x65, 0x08, ++0x07, 0xA8, 0xFF, 0xF7, 0xFB, 0xFE, 0x65, 0xB1, 0xA9, 0xF1, 0x02, 0x02, 0x02, 0xEB, 0x45, 0x0C, 0x39, 0x46, 0x31, 0xF8, ++0x02, 0x3F, 0x32, 0xF8, 0x02, 0x0F, 0x43, 0x40, 0x94, 0x45, 0x0B, 0x80, 0xF7, 0xD1, 0xE3, 0x07, 0x39, 0xD4, 0x80, 0x23, ++0xA4, 0x08, 0x05, 0xF0, 0x01, 0x05, 0x3C, 0xAA, 0x05, 0xEB, 0x44, 0x04, 0x02, 0xEB, 0x44, 0x04, 0x34, 0xF8, 0xD4, 0x2C, ++0x53, 0x40, 0x24, 0xF8, 0xD4, 0x3C, 0x3A, 0x46, 0x36, 0xF8, 0x02, 0x3F, 0x32, 0xF8, 0x02, 0x1F, 0xB7, 0x42, 0x83, 0xEA, ++0x01, 0x03, 0x33, 0x80, 0xF6, 0xD1, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0xFB, 0xFC, 0xDD, 0xE9, 0x03, 0x01, 0x3D, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xA9, 0xF1, 0x02, 0x02, 0x39, 0x46, 0x09, 0xF1, 0x0E, 0x09, 0x31, 0xF8, 0x02, 0x3F, 0x32, 0xF8, ++0x02, 0x0F, 0x43, 0x40, 0x91, 0x45, 0x0B, 0x80, 0xF7, 0xD1, 0xDE, 0xE7, 0x08, 0x49, 0x09, 0x48, 0x4F, 0xF4, 0xD6, 0x72, ++0xF3, 0xF7, 0x44, 0xF9, 0x00, 0x20, 0x01, 0x46, 0x3D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x19, 0xF8, 0x15, 0x30, 0x43, 0xF4, ++0x00, 0x43, 0xC1, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xBC, 0xC2, 0x15, 0x00, ++0xE4, 0xC2, 0x15, 0x00, 0x81, 0x04, 0x4F, 0xEA, 0xD0, 0x23, 0xC0, 0xF3, 0xC2, 0x22, 0x0C, 0xD4, 0x13, 0xF0, 0x06, 0x0F, ++0x03, 0xF0, 0x06, 0x02, 0x11, 0xD1, 0x00, 0xF0, 0x7F, 0x00, 0x62, 0xB9, 0x03, 0x28, 0x8C, 0xBF, 0x00, 0x20, 0x01, 0x20, ++0x70, 0x47, 0x07, 0x2A, 0x0C, 0xD0, 0x03, 0xF0, 0x06, 0x02, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x2A, 0xF2, 0xD0, 0x00, 0x20, ++0x70, 0x47, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x2A, 0xF9, 0xD1, 0xEB, 0xE7, 0x13, 0xF0, 0x06, 0x0F, 0x0C, 0xBF, 0x01, 0x20, ++0x00, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x40, 0x7F, 0x87, 0xB0, 0x4F, 0xF0, 0xFF, 0x34, 0x09, 0x28, ++0x05, 0x94, 0x02, 0xD9, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x89, 0x46, 0xF9, 0x6C, 0xC9, 0x4E, 0x8C, 0x6C, 0x0D, 0x6D, ++0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x00, 0x60, 0x90, 0x46, 0x90, 0xF8, 0x22, 0x10, 0xFA, 0x8B, 0x14, 0xF4, 0x00, 0x5F, ++0x08, 0xBF, 0x01, 0x23, 0x22, 0xF4, 0x00, 0x54, 0x05, 0xF4, 0x80, 0x05, 0x02, 0xF4, 0x00, 0x52, 0xFF, 0x29, 0x01, 0x95, ++0xFC, 0x83, 0x02, 0x92, 0xE0, 0xD0, 0xBD, 0x4A, 0xD0, 0xF8, 0x4C, 0xA1, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, ++0x50, 0xDB, 0xBA, 0xF8, 0xB4, 0x10, 0xBA, 0x6C, 0x48, 0x1E, 0x05, 0xAC, 0xC0, 0xB2, 0x01, 0xEB, 0x41, 0x0E, 0x00, 0x90, ++0x03, 0x94, 0x0A, 0xEB, 0x8E, 0x0E, 0x02, 0xF1, 0x3C, 0x00, 0x02, 0xF1, 0x4C, 0x0B, 0xA4, 0x46, 0x50, 0xF8, 0x04, 0x6B, ++0xC6, 0xF3, 0x0D, 0x06, 0x79, 0xB1, 0x74, 0x46, 0x00, 0x22, 0x02, 0xE0, 0x01, 0x32, 0x8A, 0x42, 0x09, 0xD0, 0x34, 0xF8, ++0x02, 0x5C, 0xB5, 0x42, 0xA4, 0xF1, 0x0C, 0x04, 0xF6, 0xD1, 0x00, 0x9C, 0xA2, 0x1A, 0x8C, 0xF8, 0x00, 0x20, 0x00, 0x2B, ++0x40, 0xF0, 0xAD, 0x80, 0x83, 0x45, 0x0C, 0xF1, 0x01, 0x0C, 0xE3, 0xD1, 0x97, 0xF8, 0x36, 0x30, 0x9A, 0xF8, 0xA3, 0x20, ++0xC3, 0xF3, 0x82, 0x03, 0x93, 0x42, 0x27, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x64, 0xD0, 0xBA, 0xF8, 0x92, 0x20, 0xBA, 0xF8, ++0x90, 0x30, 0x01, 0x32, 0x01, 0x33, 0xAA, 0xF8, 0x92, 0x20, 0xAA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x7E, 0x10, 0xBA, 0xF8, ++0x7C, 0x20, 0x1F, 0xFA, 0x89, 0xF9, 0xA9, 0xEB, 0x08, 0x03, 0x0B, 0x44, 0x91, 0x44, 0xAA, 0xF8, 0x7E, 0x30, 0xAA, 0xF8, ++0x7C, 0x90, 0x87, 0xE7, 0xBA, 0xF1, 0x00, 0x0F, 0xAB, 0xD1, 0x90, 0x49, 0x90, 0x48, 0x00, 0x93, 0x4F, 0xF4, 0x18, 0x62, ++0xF3, 0xF7, 0x64, 0xF8, 0x00, 0x9B, 0xA2, 0xE7, 0xBA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x92, 0x20, 0x01, 0x33, 0xAA, 0xF8, ++0x90, 0x30, 0x01, 0x9B, 0x01, 0x32, 0xAA, 0xF8, 0x92, 0x20, 0x00, 0x2B, 0xD7, 0xD1, 0x02, 0x9B, 0x00, 0x2B, 0x3A, 0xD0, ++0x83, 0x4E, 0x85, 0x4D, 0x03, 0x9F, 0x00, 0x24, 0xB9, 0xF1, 0x00, 0x0F, 0x24, 0xD0, 0x17, 0xF8, 0x01, 0x3B, 0xFF, 0x2B, ++0x00, 0xF0, 0xEC, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0x41, 0x81, 0x03, 0xEB, 0x43, 0x02, 0xB8, 0xF1, 0x01, 0x0F, 0x0A, 0xEB, ++0x82, 0x02, 0x40, 0xF2, 0x7A, 0x81, 0x92, 0x88, 0x59, 0x00, 0x19, 0x44, 0x0A, 0xEB, 0x81, 0x01, 0x02, 0x32, 0x8A, 0x80, ++0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x71, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, ++0x02, 0x81, 0x01, 0x34, 0x04, 0x2C, 0xD7, 0xD1, 0x00, 0x23, 0x8A, 0xF8, 0x9B, 0x30, 0x3B, 0xE7, 0xBA, 0xF8, 0x92, 0x20, ++0xBA, 0xF8, 0x90, 0x30, 0x01, 0x32, 0x01, 0x33, 0xAA, 0xF8, 0x92, 0x20, 0xAA, 0xF8, 0x90, 0x30, 0xC1, 0xE7, 0x66, 0x4E, ++0x67, 0x4D, 0x03, 0x9F, 0x1C, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x29, 0xAF, 0x17, 0xF8, 0x01, 0x3B, 0xFF, 0x2B, ++0x00, 0xF0, 0xA5, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0xF0, 0x80, 0x03, 0xEB, 0x43, 0x02, 0xB8, 0xF1, 0x01, 0x0F, 0x0A, 0xEB, ++0x82, 0x02, 0x40, 0xF2, 0x43, 0x81, 0x92, 0x88, 0x59, 0x00, 0x19, 0x44, 0x0A, 0xEB, 0x81, 0x01, 0x02, 0x32, 0x8A, 0x80, ++0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x53, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, ++0xB6, 0x80, 0x01, 0x34, 0x04, 0x2C, 0xD6, 0xD1, 0x02, 0xE7, 0x97, 0xF8, 0x36, 0x30, 0x9A, 0xF8, 0xA3, 0x20, 0xC3, 0xF3, ++0x82, 0x03, 0x93, 0x42, 0x38, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x69, 0xD1, 0xBA, 0xF8, 0x92, 0x30, 0xBA, 0xF8, 0x90, 0x20, ++0x01, 0x33, 0x1F, 0xFA, 0x89, 0xF0, 0xAA, 0xF8, 0x92, 0x30, 0x02, 0x9B, 0x02, 0x44, 0xAA, 0xF8, 0x90, 0x20, 0x00, 0x2B, ++0x40, 0xF0, 0x8A, 0x80, 0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0xE3, 0xAE, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, ++0x04, 0x33, 0x3C, 0x4A, 0x5D, 0x88, 0x19, 0x88, 0x14, 0x68, 0xA0, 0xEB, 0x08, 0x02, 0x2A, 0x44, 0x01, 0x44, 0x92, 0xB2, ++0x89, 0xB2, 0x5A, 0x80, 0x19, 0x80, 0xB4, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xCE, 0xAE, 0x91, 0x42, 0xBF, 0xF4, ++0xCB, 0xAE, 0x33, 0x49, 0x34, 0x48, 0x4F, 0xF4, 0x1F, 0x62, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xF2, 0xF7, 0xA8, 0xBF, ++0xBA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x92, 0x20, 0x1F, 0xFA, 0x89, 0xF0, 0x03, 0x44, 0xAA, 0xF8, 0x90, 0x30, 0x01, 0x9B, ++0x01, 0x32, 0xAA, 0xF8, 0x92, 0x20, 0x8B, 0xBB, 0x02, 0x9B, 0x00, 0x2B, 0x52, 0xD1, 0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, ++0x00, 0xF0, 0xFD, 0x80, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, 0x04, 0x33, 0xB9, 0xEB, 0x48, 0x0F, 0x9A, 0xF8, 0xA4, 0x20, ++0x80, 0xF0, 0xE9, 0x80, 0x01, 0x2A, 0x40, 0xF2, 0xF8, 0x80, 0x02, 0x2A, 0x03, 0xD0, 0x00, 0x2B, 0x3F, 0xF4, 0x9A, 0xAE, ++0xB9, 0xE7, 0xDA, 0xF8, 0x00, 0x20, 0xA2, 0xF5, 0x92, 0x32, 0xF8, 0x3A, 0xCA, 0xF8, 0x00, 0x20, 0x00, 0x2B, 0x3F, 0xF4, ++0x8F, 0xAE, 0xAE, 0xE7, 0xBA, 0xF8, 0x90, 0x20, 0xBA, 0xF8, 0x92, 0x30, 0x1F, 0xFA, 0x89, 0xF0, 0x02, 0x44, 0x01, 0x33, ++0xAA, 0xF8, 0x90, 0x20, 0xAA, 0xF8, 0x92, 0x30, 0x0A, 0xF1, 0x7C, 0x03, 0x9F, 0xE7, 0x00, 0x2C, 0x75, 0xD0, 0xB8, 0xF1, ++0x01, 0x0F, 0x7F, 0xF6, 0x79, 0xAE, 0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x6C, 0xE7, 0x00, 0x2C, 0x00, 0xF0, ++0x8C, 0x80, 0xB8, 0xF1, 0x01, 0x0F, 0x7F, 0xF6, 0x2D, 0xAF, 0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x24, 0xE7, ++0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0xE4, 0xC5, 0x15, 0x00, ++0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0x19, 0xAF, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, 0x00, 0x22, 0x04, 0x33, ++0x8A, 0xF8, 0x9B, 0x20, 0x71, 0xE7, 0x03, 0xEB, 0x43, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x9A, 0x88, 0xDB, 0x88, 0x9A, 0x42, ++0xBF, 0xF4, 0x41, 0xAF, 0x40, 0xF6, 0x61, 0x22, 0x31, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x28, 0xFF, 0x39, 0xE7, 0x03, 0xEB, ++0x43, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x9A, 0x88, 0xDB, 0x88, 0x9A, 0x42, 0xBF, 0xF4, 0xF5, 0xAE, 0x40, 0xF6, 0x33, 0x22, ++0x31, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x18, 0xFF, 0xED, 0xE6, 0xB8, 0xF1, 0x00, 0x0F, 0x6C, 0xD0, 0x03, 0xEB, 0x43, 0x01, ++0x0A, 0xEB, 0x81, 0x01, 0x08, 0xF1, 0xFF, 0x38, 0x8A, 0x88, 0x01, 0x32, 0x92, 0xB2, 0xB8, 0xF1, 0x01, 0x0F, 0x8A, 0x80, ++0x09, 0xF1, 0xFF, 0x39, 0x19, 0xB2, 0x73, 0xD9, 0x59, 0x00, 0x04, 0xE7, 0xB8, 0xF1, 0x00, 0x0F, 0x1B, 0xD0, 0x03, 0xEB, ++0x43, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x08, 0xF1, 0xFF, 0x38, 0x8A, 0x88, 0x01, 0x32, 0x92, 0xB2, 0xB8, 0xF1, 0x01, 0x0F, ++0x8A, 0x80, 0x09, 0xF1, 0xFF, 0x39, 0x19, 0xB2, 0x5B, 0xD9, 0x59, 0x00, 0xB3, 0xE6, 0xB8, 0xF1, 0x02, 0x0F, 0x7F, 0xF6, ++0x03, 0xAE, 0xA9, 0xF1, 0x03, 0x09, 0xA8, 0xF1, 0x03, 0x08, 0x01, 0x24, 0xCF, 0xE6, 0x03, 0xEB, 0x43, 0x02, 0x0A, 0xEB, ++0x82, 0x02, 0xA0, 0x46, 0x92, 0x88, 0x19, 0xB2, 0x01, 0xEB, 0x41, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x1F, 0xFA, 0x89, 0xF9, ++0xC8, 0x88, 0xA9, 0xEB, 0x08, 0x08, 0x4A, 0x44, 0x40, 0x44, 0x4F, 0xF0, 0x00, 0x09, 0x8A, 0x80, 0xC8, 0x80, 0xC8, 0x46, ++0x9A, 0xE6, 0xB8, 0xF1, 0x02, 0x0F, 0x7F, 0xF6, 0xA1, 0xAE, 0xA9, 0xF1, 0x03, 0x09, 0xA8, 0xF1, 0x03, 0x08, 0x01, 0x24, ++0x72, 0xE6, 0x92, 0x88, 0x1F, 0xFA, 0x88, 0xF8, 0x19, 0xB2, 0xDF, 0xE7, 0x92, 0x88, 0x1F, 0xFA, 0x88, 0xF8, 0x19, 0xB2, ++0x01, 0xEB, 0x41, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x1F, 0xFA, 0x89, 0xF9, 0xC8, 0x88, 0xA9, 0xEB, 0x08, 0x08, 0x4A, 0x44, ++0x40, 0x44, 0x4F, 0xF0, 0x00, 0x09, 0x8A, 0x80, 0xC8, 0x80, 0xC8, 0x46, 0xB2, 0xE6, 0x03, 0xEB, 0x43, 0x02, 0x0A, 0xEB, ++0x82, 0x02, 0xA0, 0x46, 0x92, 0x88, 0x19, 0xB2, 0xE6, 0xE7, 0x00, 0x2A, 0x3F, 0xF4, 0x19, 0xAF, 0x01, 0x3A, 0x8A, 0xF8, ++0xA4, 0x20, 0x00, 0x2B, 0x3F, 0xF4, 0xB0, 0xAD, 0xCF, 0xE6, 0x02, 0x9B, 0x04, 0xE7, 0x1F, 0xFA, 0x88, 0xF8, 0xB3, 0xE7, ++0x1F, 0xFA, 0x88, 0xF8, 0xD4, 0xE7, 0x01, 0x32, 0x8A, 0xF8, 0xA4, 0x20, 0x00, 0x2B, 0x3F, 0xF4, 0xA1, 0xAD, 0xC0, 0xE6, ++0x03, 0x88, 0xA3, 0xB1, 0x10, 0xB4, 0x42, 0x88, 0x44, 0x7A, 0x00, 0x21, 0x12, 0x04, 0x01, 0x72, 0xB2, 0xFB, 0xF3, 0xF1, ++0x8C, 0xB1, 0x83, 0x88, 0x5D, 0xF8, 0x04, 0x4B, 0x03, 0xEB, 0x43, 0x03, 0x0B, 0x44, 0xC3, 0xF3, 0x98, 0x03, 0x83, 0x80, ++0x01, 0x23, 0x43, 0x72, 0x70, 0x47, 0x03, 0x7A, 0xFF, 0x2B, 0x1C, 0xBF, 0x01, 0x33, 0x03, 0x72, 0x70, 0x47, 0x9A, 0x42, ++0x24, 0xBF, 0x01, 0xF1, 0xFF, 0x33, 0x83, 0x80, 0x4F, 0xF0, 0x01, 0x03, 0x38, 0xBF, 0x84, 0x80, 0x43, 0x72, 0x5D, 0xF8, ++0x04, 0x4B, 0x70, 0x47, 0xF8, 0xB5, 0x06, 0x46, 0x88, 0x04, 0x0C, 0x46, 0xC1, 0xF3, 0xC2, 0x25, 0x19, 0xD4, 0xCB, 0x0A, ++0x13, 0xF0, 0x06, 0x0F, 0x40, 0xD1, 0xCF, 0xB2, 0x01, 0xF0, 0x7F, 0x05, 0x05, 0xF0, 0xF8, 0xF9, 0x17, 0xF0, 0x7C, 0x0F, ++0x5B, 0xD1, 0x96, 0xF8, 0xAD, 0x20, 0x04, 0xE0, 0xB6, 0xF8, 0xAA, 0x30, 0xEB, 0x40, 0xD9, 0x07, 0x59, 0xD4, 0x6B, 0x1E, ++0x95, 0x42, 0xDD, 0xB2, 0xF6, 0xD8, 0x20, 0x46, 0xF8, 0xBD, 0x07, 0x2D, 0x47, 0xD0, 0x04, 0x3D, 0x05, 0xF0, 0xE2, 0xF9, ++0x04, 0xF0, 0x0F, 0x02, 0x01, 0x2D, 0xF4, 0xD8, 0xDF, 0xE8, 0x05, 0xF0, 0x01, 0x0E, 0x72, 0xB3, 0x53, 0x1E, 0x24, 0xF0, ++0x0F, 0x04, 0x96, 0xF8, 0xB1, 0x20, 0x23, 0x43, 0x98, 0xB2, 0x00, 0x2A, 0xE8, 0xD0, 0x40, 0xF4, 0x00, 0x70, 0xF8, 0xBD, ++0x0A, 0xB3, 0x24, 0xF0, 0x0F, 0x03, 0x51, 0x1E, 0x0B, 0x43, 0x98, 0xB2, 0x63, 0x04, 0xDD, 0xD5, 0x03, 0x2A, 0x03, 0xD0, ++0x96, 0xF8, 0xBD, 0x30, 0x99, 0x42, 0xD7, 0xDD, 0x20, 0xF4, 0x80, 0x43, 0x98, 0xB2, 0xF8, 0xBD, 0xC4, 0xF3, 0xC1, 0x05, ++0x05, 0xF0, 0xB8, 0xF9, 0x35, 0x44, 0x04, 0xF0, 0x07, 0x03, 0x05, 0xE0, 0x95, 0xF8, 0xA6, 0x20, 0xCB, 0xB2, 0xDA, 0x40, ++0xD2, 0x07, 0x24, 0xD4, 0x59, 0x1E, 0x00, 0x2B, 0xF6, 0xD1, 0x96, 0xF8, 0xAE, 0x30, 0x03, 0x2B, 0xBD, 0xD8, 0x43, 0xB3, ++0x96, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x60, 0x43, 0xEA, 0x82, 0x23, 0x03, 0x43, 0x98, 0xB2, 0xF8, 0xBD, 0x05, 0xF0, ++0x9B, 0xF9, 0x20, 0x46, 0xB0, 0xE7, 0x96, 0xF8, 0xAD, 0x20, 0x04, 0x2A, 0x38, 0xBF, 0x04, 0x22, 0xA5, 0xE7, 0x24, 0xF0, ++0x7F, 0x04, 0x44, 0xEA, 0x05, 0x00, 0x00, 0x2D, 0xA4, 0xD1, 0x40, 0xF4, 0x80, 0x63, 0x98, 0xB2, 0xF8, 0xBD, 0x96, 0xF8, ++0xB1, 0x20, 0x24, 0xF0, 0x07, 0x04, 0x44, 0xEA, 0x03, 0x00, 0x00, 0x2A, 0x98, 0xD0, 0x40, 0xF4, 0x00, 0x73, 0x98, 0xB2, ++0xF8, 0xBD, 0x4F, 0xF4, 0x80, 0x60, 0xF8, 0xBD, 0x8A, 0x04, 0x30, 0xB4, 0xC1, 0xF3, 0xC2, 0x23, 0x20, 0xD4, 0xCA, 0x0A, ++0x12, 0xF0, 0x06, 0x0F, 0x26, 0xD1, 0x11, 0xF0, 0x7C, 0x0F, 0x01, 0xF0, 0x7F, 0x03, 0x71, 0xD1, 0x90, 0xF8, 0xAE, 0x40, ++0x03, 0x2C, 0x28, 0xBF, 0x03, 0x24, 0x04, 0xE0, 0xB0, 0xF8, 0xAA, 0x20, 0xDA, 0x40, 0xD5, 0x07, 0x74, 0xD4, 0x5A, 0x1C, ++0xA3, 0x42, 0xD3, 0xB2, 0xF6, 0xD3, 0x90, 0xF8, 0xA5, 0x30, 0x01, 0x2B, 0x01, 0xD9, 0xD9, 0x02, 0x89, 0xB2, 0x08, 0x46, ++0x30, 0xBC, 0x70, 0x47, 0x07, 0x2B, 0xFA, 0xD0, 0x04, 0x3B, 0x01, 0xF0, 0x0F, 0x02, 0x01, 0x2B, 0xF5, 0xD8, 0xDF, 0xE8, ++0x03, 0xF0, 0x15, 0x30, 0xC1, 0xF3, 0xC1, 0x04, 0x90, 0xF8, 0xAC, 0x50, 0x04, 0x44, 0x01, 0xF0, 0x07, 0x03, 0x04, 0xE0, ++0x94, 0xF8, 0xA6, 0x20, 0xDA, 0x40, 0xD2, 0x07, 0x45, 0xD4, 0x5A, 0x1C, 0x9D, 0x42, 0xD3, 0xB2, 0xF6, 0xD8, 0x08, 0x46, ++0x30, 0xBC, 0x70, 0x47, 0x90, 0xF8, 0xAC, 0x30, 0x93, 0x42, 0xDA, 0xD9, 0xB0, 0xF8, 0xA6, 0x30, 0xC1, 0xF3, 0x02, 0x14, ++0x64, 0x00, 0x23, 0x41, 0x03, 0xF0, 0x03, 0x03, 0x07, 0x33, 0x93, 0x42, 0xCF, 0xD9, 0x21, 0xF0, 0x0F, 0x01, 0x01, 0x32, ++0x90, 0xF8, 0xB1, 0x30, 0x11, 0x43, 0x89, 0xB2, 0x00, 0x2B, 0xC6, 0xD0, 0x41, 0xF4, 0x00, 0x71, 0xC3, 0xE7, 0x90, 0xF8, ++0xAC, 0x30, 0x93, 0x42, 0xBF, 0xD9, 0xB0, 0xF8, 0xA6, 0x30, 0xC1, 0xF3, 0x02, 0x14, 0x64, 0x00, 0x23, 0x41, 0x03, 0xF0, ++0x03, 0x03, 0x5B, 0x00, 0x07, 0x33, 0x93, 0x42, 0xB3, 0xD9, 0x21, 0xF0, 0x0F, 0x01, 0x53, 0x1C, 0x0B, 0x43, 0x99, 0xB2, ++0x5B, 0x04, 0xAC, 0xD5, 0x01, 0x2A, 0x03, 0xD0, 0x90, 0xF8, 0xBD, 0x30, 0x93, 0x42, 0xA6, 0xD8, 0x21, 0xF4, 0x80, 0x41, ++0x89, 0xB2, 0xA2, 0xE7, 0x90, 0xF8, 0xAE, 0x40, 0x95, 0xE7, 0x90, 0xF8, 0xB1, 0x20, 0x21, 0xF0, 0x07, 0x01, 0x19, 0x43, ++0x00, 0x2A, 0x98, 0xD0, 0x41, 0xF4, 0x00, 0x71, 0x89, 0xB2, 0x94, 0xE7, 0x21, 0xF0, 0x7F, 0x01, 0x19, 0x43, 0x90, 0xE7, ++0x2D, 0xE9, 0xF0, 0x4F, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x85, 0xB0, 0x4C, 0x89, 0xE6, 0x0A, 0xC4, 0xF3, ++0x80, 0x22, 0x01, 0x92, 0x71, 0x07, 0x4F, 0xEA, 0x54, 0x22, 0x05, 0x46, 0x06, 0xF0, 0x04, 0x03, 0xC4, 0xF3, 0xC2, 0x27, ++0x02, 0x92, 0xC4, 0xF3, 0x40, 0x2B, 0xC4, 0xF3, 0xC1, 0x1A, 0x23, 0xD5, 0x07, 0x2F, 0x50, 0xD0, 0xC4, 0xF3, 0x02, 0x19, ++0x04, 0xF0, 0x0F, 0x04, 0xDF, 0xF8, 0x70, 0x83, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x22, 0xDA, ++0x05, 0x2F, 0x27, 0xD9, 0x40, 0xF2, 0xB5, 0x22, 0xCA, 0x49, 0xCB, 0x48, 0x03, 0x93, 0xF2, 0xF7, 0x0B, 0xFD, 0x95, 0xF8, ++0xA5, 0x20, 0x03, 0x9B, 0x05, 0x2A, 0x14, 0xD8, 0xDF, 0xE8, 0x12, 0xF0, 0xD6, 0x00, 0xD6, 0x00, 0x31, 0x01, 0x31, 0x01, ++0xF4, 0x00, 0x45, 0x01, 0x16, 0xF0, 0x06, 0x09, 0x26, 0xD1, 0x04, 0xF0, 0x7F, 0x04, 0xDF, 0xF8, 0x2C, 0x83, 0xD8, 0xF8, ++0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x06, 0xDB, 0x05, 0x2F, 0x17, 0xD8, 0xDF, 0xE8, 0x07, 0xF0, 0x22, 0x22, ++0x0F, 0x0F, 0x50, 0x91, 0x95, 0xF8, 0xA5, 0x10, 0x05, 0x29, 0xF4, 0xD8, 0xDF, 0xE8, 0x11, 0xF0, 0xBD, 0x00, 0xBD, 0x00, ++0x15, 0x01, 0x15, 0x01, 0xD8, 0x00, 0x29, 0x01, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, ++0xDF, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC4, 0xF3, 0xC1, 0x09, 0x04, 0xF0, 0x07, 0x04, 0xD5, 0xE7, 0x4F, 0xF0, ++0x00, 0x09, 0x4C, 0x46, 0xAE, 0xE7, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x03, 0x2C, 0x04, 0xD8, 0x95, 0xF8, ++0xB2, 0x10, 0x01, 0x29, 0x00, 0xF0, 0x7B, 0x81, 0x00, 0x2A, 0xE6, 0xDA, 0xBB, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x2E, 0x81, ++0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x1C, 0x81, 0xB9, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0xDC, 0x81, 0x95, 0xF8, 0xAD, 0x30, ++0xA3, 0x42, 0x00, 0xF2, 0xC9, 0x81, 0x95, 0xF8, 0xAE, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0xEE, 0x81, 0xB5, 0xF8, 0xAA, 0x30, ++0x23, 0xFA, 0x04, 0xF4, 0xE2, 0x07, 0xCA, 0xD4, 0x93, 0x49, 0x95, 0x48, 0x40, 0xF2, 0x06, 0x32, 0x3B, 0xE0, 0xD8, 0xF8, ++0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xBF, 0xDA, 0x01, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0xCB, 0x81, 0x95, 0xF8, ++0xB1, 0x30, 0x5B, 0x45, 0xC0, 0xF0, 0x52, 0x82, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, 0xC0, 0xF0, 0x3F, 0x82, 0x95, 0xF8, ++0xB0, 0x30, 0x4B, 0x45, 0xC0, 0xF0, 0x2C, 0x82, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0x19, 0x82, 0xB5, 0xF8, ++0xA6, 0x30, 0x4F, 0xEA, 0x49, 0x02, 0x13, 0x41, 0x03, 0xF0, 0x03, 0x03, 0x07, 0x33, 0x9C, 0x42, 0x00, 0xF3, 0x82, 0x81, ++0x06, 0x2C, 0x00, 0xF0, 0x3E, 0x81, 0x09, 0x2C, 0x97, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x4B, 0x82, 0xB9, 0xF1, ++0x02, 0x0F, 0x90, 0xD0, 0xB9, 0xF1, 0x05, 0x0F, 0x8D, 0xD0, 0x75, 0x49, 0x77, 0x48, 0x4F, 0xF4, 0x48, 0x72, 0x05, 0xB0, ++0xBD, 0xE8, 0xF0, 0x4F, 0xF2, 0xF7, 0x5C, 0xBC, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, ++0x7E, 0xAF, 0x02, 0x9B, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF0, 0x21, 0x82, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, ++0xC0, 0xF0, 0x9E, 0x81, 0x95, 0xF8, 0xB0, 0x30, 0x4B, 0x45, 0xC0, 0xF0, 0xD1, 0x81, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, ++0xC0, 0xF0, 0xBE, 0x81, 0xB5, 0xF8, 0xA6, 0x30, 0x4F, 0xEA, 0x49, 0x09, 0x43, 0xFA, 0x09, 0xF3, 0x03, 0xF0, 0x03, 0x03, ++0x5B, 0x00, 0x07, 0x33, 0x9C, 0x42, 0x7F, 0xF7, 0x5C, 0xAF, 0x5C, 0x49, 0x5F, 0x48, 0x40, 0xF2, 0x2F, 0x32, 0xCC, 0xE7, ++0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xBF, 0xF6, 0x36, 0xAF, 0x16, 0xF0, 0x06, 0x0F, 0x40, 0xF0, ++0x2A, 0x81, 0x05, 0x2F, 0x3F, 0xF6, 0x49, 0xAF, 0x01, 0xA3, 0x53, 0xF8, 0x27, 0xF0, 0x00, 0xBF, 0xE7, 0x21, 0x15, 0x00, ++0xE7, 0x21, 0x15, 0x00, 0x8D, 0x23, 0x15, 0x00, 0x8D, 0x23, 0x15, 0x00, 0x43, 0x22, 0x15, 0x00, 0xC5, 0x22, 0x15, 0x00, ++0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x60, 0xD8, 0x00, 0x2A, 0xBF, 0xF6, ++0x14, 0xAF, 0x04, 0x2F, 0x3F, 0xF4, 0x6B, 0xAF, 0x00, 0x2F, 0x3F, 0xF4, 0x38, 0xAF, 0x42, 0x49, 0x46, 0x48, 0x4F, 0xF4, ++0x36, 0x72, 0xF2, 0xF7, 0xF9, 0xFB, 0x06, 0xE7, 0x01, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0x64, 0x81, 0x95, 0xF8, 0xB1, 0x30, ++0x5B, 0x45, 0xC0, 0xF0, 0x51, 0x81, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, 0xC0, 0xF0, 0xD5, 0x80, 0x95, 0xF8, 0xB0, 0x30, ++0x4B, 0x45, 0xC0, 0xF0, 0xC2, 0x80, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0xD9, 0x80, 0x4D, 0x44, 0x95, 0xF8, ++0xA6, 0x30, 0x23, 0xFA, 0x04, 0xF4, 0xE3, 0x07, 0x3F, 0xF5, 0x01, 0xAF, 0x2E, 0x49, 0x34, 0x48, 0x40, 0xF2, 0x12, 0x32, ++0x71, 0xE7, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x77, 0xD8, 0x00, 0x2A, ++0xBF, 0xF6, 0xD7, 0xAE, 0x00, 0x2B, 0xA2, 0xD0, 0x25, 0x49, 0x2C, 0x48, 0x40, 0xF2, 0xCA, 0x22, 0xF2, 0xF7, 0xC0, 0xFB, ++0xCD, 0xE6, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x56, 0xD8, 0x00, 0x2A, ++0xBF, 0xF6, 0xC3, 0xAE, 0x05, 0x2F, 0x3F, 0xF4, 0x5C, 0xAF, 0x00, 0x2F, 0x3F, 0xF4, 0xE7, 0xAE, 0x19, 0x49, 0x21, 0x48, ++0x40, 0xF2, 0xE7, 0x22, 0xF2, 0xF7, 0xA8, 0xFB, 0xB5, 0xE6, 0x00, 0x2A, 0xBF, 0xF6, 0xB3, 0xAE, 0x04, 0x2F, 0x3F, 0xF4, ++0x0A, 0xAF, 0x13, 0x49, 0x1B, 0x48, 0x4F, 0xF4, 0x37, 0x72, 0xF2, 0xF7, 0x9B, 0xFB, 0xA8, 0xE6, 0x0F, 0x49, 0x19, 0x48, ++0x40, 0xF2, 0x02, 0x32, 0xF2, 0xF7, 0x94, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0xD7, 0xAE, 0xB4, 0xE6, 0x08, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x01, 0x32, 0xF2, 0xF7, 0x86, 0xFB, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xA8, 0xAE, 0xBA, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0xC5, 0xAE, 0xDF, 0xE7, ++0x70, 0x79, 0x15, 0x00, 0x08, 0xC6, 0x15, 0x00, 0xB0, 0xC7, 0x15, 0x00, 0xF0, 0xC8, 0x15, 0x00, 0xA8, 0xC9, 0x15, 0x00, ++0xA8, 0xC6, 0x15, 0x00, 0x3C, 0xC8, 0x15, 0x00, 0x48, 0xC6, 0x15, 0x00, 0x04, 0xC7, 0x15, 0x00, 0xE8, 0xC6, 0x15, 0x00, ++0x64, 0xC7, 0x15, 0x00, 0x58, 0xC7, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x2A, 0xBF, 0xF6, 0x6C, 0xAE, 0x05, 0x2F, ++0x3F, 0xF4, 0x05, 0xAF, 0xA9, 0x49, 0xAA, 0x48, 0x40, 0xF2, 0xEB, 0x22, 0xF2, 0xF7, 0x54, 0xFB, 0x61, 0xE6, 0x00, 0x2A, ++0xBF, 0xF6, 0x5F, 0xAE, 0xBA, 0x1E, 0x01, 0x2A, 0x7F, 0xF6, 0x54, 0xAF, 0xA2, 0x49, 0xA4, 0x48, 0x40, 0xF2, 0xCE, 0x22, ++0xF2, 0xF7, 0x46, 0xFB, 0x53, 0xE6, 0x00, 0x2A, 0xBF, 0xF6, 0x6B, 0xAE, 0x01, 0x9B, 0x00, 0x2B, 0x7F, 0xF4, 0x80, 0xAE, ++0x40, 0xF2, 0xFB, 0x22, 0x9A, 0x49, 0x9D, 0x48, 0xF2, 0xF7, 0x38, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x20, ++0x72, 0xE6, 0xBA, 0xF1, 0x02, 0x0F, 0x7F, 0xF4, 0x58, 0xAE, 0xB9, 0xF1, 0x03, 0x0F, 0x03, 0xD0, 0xB9, 0xF1, 0x06, 0x0F, ++0x7F, 0xF4, 0x51, 0xAE, 0x90, 0x49, 0x94, 0x48, 0x40, 0xF2, 0x1F, 0x32, 0xC1, 0xE6, 0x8E, 0x49, 0x92, 0x48, 0x4F, 0xF4, ++0x44, 0x72, 0xF2, 0xF7, 0x1D, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x31, 0xAF, ++0x3D, 0xE6, 0x87, 0x49, 0x8C, 0x48, 0x40, 0xF2, 0x0F, 0x32, 0xF2, 0xF7, 0x0F, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x1E, 0xAF, 0x2F, 0xE6, 0x80, 0x49, 0x86, 0x48, 0x40, 0xF2, 0x11, 0x32, 0xF2, 0xF7, ++0x01, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x1A, 0xAF, 0x21, 0xE6, 0x79, 0x49, ++0x80, 0x48, 0x40, 0xF2, 0xC2, 0x22, 0xF2, 0xF7, 0xF3, 0xFA, 0x00, 0xE6, 0x75, 0x49, 0x7E, 0x48, 0x40, 0xF2, 0x1E, 0x32, ++0xF2, 0xF7, 0xEC, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x71, 0xAE, 0x0C, 0xE6, ++0x6E, 0x49, 0x78, 0x48, 0x4F, 0xF4, 0x41, 0x72, 0xF2, 0xF7, 0xDE, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xFF, 0xF6, 0x2A, 0xAE, 0xFE, 0xE5, 0x67, 0x49, 0x72, 0x48, 0x40, 0xF2, 0x03, 0x32, 0xF2, 0xF7, 0xD0, 0xFA, ++0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x17, 0xAE, 0xF0, 0xE5, 0x60, 0x49, 0x6C, 0x48, ++0x40, 0xF2, 0x19, 0x32, 0xF2, 0xF7, 0xC2, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0x28, 0xAE, 0xE2, 0xE5, 0x59, 0x49, 0x66, 0x48, 0x40, 0xF2, 0x05, 0x32, 0xF2, 0xF7, 0xB4, 0xFA, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x05, 0xAE, 0xD4, 0xE5, 0x52, 0x49, 0x58, 0x48, 0x4F, 0xF4, 0x4B, 0x72, ++0xF2, 0xF7, 0xA6, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x55, 0xAE, 0xC6, 0xE5, ++0x4B, 0x49, 0x59, 0x48, 0x40, 0xF2, 0x0E, 0x32, 0xF2, 0xF7, 0x98, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xFF, 0xF6, 0xA2, 0xAE, 0xB8, 0xE5, 0x44, 0x49, 0x50, 0x48, 0x40, 0xF2, 0x0D, 0x32, 0xF2, 0xF7, 0x8A, 0xFA, ++0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x8F, 0xAE, 0xAA, 0xE5, 0x3D, 0x49, 0x44, 0x48, ++0x40, 0xF2, 0x2E, 0x32, 0xF2, 0xF7, 0x7C, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0x35, 0xAE, 0x9C, 0xE5, 0x36, 0x49, 0x3B, 0x48, 0x40, 0xF2, 0x2D, 0x32, 0xF2, 0xF7, 0x6E, 0xFA, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x22, 0xAE, 0x8E, 0xE5, 0x2F, 0x49, 0x36, 0x48, 0x40, 0xF2, 0x1D, 0x32, ++0xF2, 0xF7, 0x60, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xDA, 0xAD, 0x80, 0xE5, ++0x28, 0x49, 0x2D, 0x48, 0x4F, 0xF4, 0x47, 0x72, 0xF2, 0xF7, 0x52, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xFF, 0xF6, 0xC7, 0xAD, 0x72, 0xE5, 0x21, 0x49, 0x27, 0x48, 0x40, 0xF2, 0x1B, 0x32, 0xF2, 0xF7, 0x44, 0xFA, ++0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xB4, 0xAD, 0x64, 0xE5, 0x1A, 0x49, 0x28, 0x48, ++0x40, 0xF2, 0x1A, 0x32, 0xF2, 0xF7, 0x36, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, ++0xA1, 0xAD, 0x56, 0xE5, 0x13, 0x49, 0x22, 0x48, 0x40, 0xF2, 0x2B, 0x32, 0xF2, 0xF7, 0x28, 0xFA, 0xD8, 0xF8, 0x00, 0x30, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xD2, 0xAD, 0x48, 0xE5, 0xBA, 0xF1, 0x02, 0x0F, 0x08, 0xD1, 0xB9, 0xF1, ++0x05, 0x0F, 0x7F, 0xF4, 0x42, 0xAD, 0x09, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x21, 0x32, 0xB2, 0xE5, 0xBA, 0xF1, 0x03, 0x0F, ++0x7F, 0xF4, 0x39, 0xAD, 0xB9, 0xF1, 0x02, 0x0F, 0x7F, 0xF4, 0x35, 0xAD, 0x02, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x22, 0x32, ++0xA5, 0xE5, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0xD8, 0x93, 0x15, 0x00, 0x64, 0xC6, 0x15, 0x00, 0x48, 0xC7, 0x15, 0x00, ++0xAC, 0xC8, 0x15, 0x00, 0x10, 0xC8, 0x15, 0x00, 0xFC, 0xC7, 0x15, 0x00, 0x24, 0xC8, 0x15, 0x00, 0x28, 0xC6, 0x15, 0x00, ++0x64, 0xC8, 0x15, 0x00, 0x80, 0xC7, 0x15, 0x00, 0x74, 0xC7, 0x15, 0x00, 0xD4, 0xC7, 0x15, 0x00, 0x98, 0xC7, 0x15, 0x00, ++0xE4, 0xC7, 0x15, 0x00, 0xA0, 0xC9, 0x15, 0x00, 0x34, 0xC9, 0x15, 0x00, 0x68, 0xC9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0x04, 0x46, 0x04, 0xF0, 0x89, 0xFD, 0x94, 0xF8, 0xA5, 0x10, 0x94, 0xF8, 0xAF, 0x20, 0xCB, 0x02, 0x9B, 0xB2, 0x92, 0xB3, ++0x55, 0x1E, 0xED, 0xB2, 0x05, 0x29, 0x2B, 0xD8, 0xDF, 0xE8, 0x01, 0xF0, 0x6D, 0x6D, 0x2F, 0x2F, 0x94, 0x03, 0x94, 0xF8, ++0xAD, 0x10, 0x03, 0x29, 0x00, 0xF2, 0xD1, 0x80, 0x06, 0x05, 0x40, 0xF1, 0xCE, 0x80, 0x94, 0xF8, 0xAE, 0x60, 0xB4, 0xF8, ++0xAA, 0x20, 0x73, 0x1A, 0x01, 0x33, 0x00, 0xF0, 0x7F, 0x07, 0x97, 0xFB, 0xF3, 0xF5, 0x03, 0xFB, 0x15, 0x73, 0x19, 0x44, ++0xC9, 0xB2, 0x22, 0xFA, 0x01, 0xF3, 0x13, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x31, 0x46, 0x00, 0x29, 0x00, 0xF0, 0x3F, 0x81, ++0x94, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x63, 0x43, 0xEA, 0x82, 0x23, 0x0B, 0x43, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, ++0xF0, 0x81, 0x15, 0x46, 0xCC, 0xE7, 0x94, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x01, 0xD8, 0x06, 0x05, 0xD5, 0xD4, 0x94, 0xF8, ++0xB0, 0x70, 0x94, 0xF8, 0xAC, 0x60, 0x94, 0xF8, 0xB1, 0xC0, 0x01, 0x37, 0xC0, 0xF3, 0xC1, 0x01, 0xB1, 0xFB, 0xF7, 0xFE, ++0x07, 0xFB, 0x1E, 0x11, 0x0C, 0x44, 0x06, 0xF1, 0x01, 0x0E, 0x00, 0xF0, 0x07, 0x08, 0x94, 0xF8, 0xA6, 0x70, 0xB8, 0xFB, ++0xFE, 0xF4, 0x0E, 0xFB, 0x14, 0x84, 0xE7, 0x40, 0xFF, 0x07, 0x48, 0xBF, 0xE6, 0xB2, 0x52, 0x1B, 0x0C, 0xF1, 0x01, 0x04, ++0xC0, 0xF3, 0x40, 0x2C, 0x01, 0x32, 0xC0, 0xF3, 0xC1, 0x10, 0xBC, 0xFB, 0xF4, 0xF7, 0xC9, 0x00, 0x04, 0xFB, 0x17, 0xC4, ++0x41, 0xEA, 0x44, 0x21, 0x90, 0xFB, 0xF2, 0xF4, 0x02, 0xFB, 0x14, 0x00, 0x05, 0x44, 0x0B, 0x43, 0x43, 0xEA, 0xC5, 0x13, ++0x9B, 0xB2, 0x33, 0x43, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x94, 0xF8, 0xAE, 0x70, 0x94, 0xF8, 0xAD, 0x20, 0xB4, 0xF8, ++0xAA, 0x50, 0xB9, 0x1A, 0x01, 0x31, 0x00, 0xF0, 0x7F, 0x0C, 0x9C, 0xFB, 0xF1, 0xF6, 0x01, 0xFB, 0x16, 0xC1, 0x0A, 0x44, ++0xD2, 0xB2, 0x25, 0xFA, 0x02, 0xF1, 0x11, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x3A, 0x46, 0x13, 0x43, 0x00, 0x2A, 0x00, 0xF0, ++0xA2, 0x80, 0x01, 0x3A, 0xD2, 0xB2, 0x02, 0x2A, 0x9E, 0xD8, 0x94, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x60, 0x40, 0xEA, ++0x82, 0x20, 0x03, 0x43, 0x9B, 0xB2, 0x95, 0xE7, 0x94, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x40, 0xF2, 0x8C, 0x80, 0x94, 0xF8, ++0xB0, 0x10, 0xB4, 0xF8, 0xA6, 0x70, 0x94, 0xF8, 0xAC, 0xC0, 0x94, 0xF8, 0xB1, 0x40, 0x4E, 0x1C, 0xC0, 0xF3, 0x02, 0x11, ++0xB1, 0xFB, 0xF6, 0xFE, 0x06, 0xFB, 0x1E, 0x11, 0x4E, 0x00, 0x37, 0x41, 0x07, 0xF0, 0x03, 0x07, 0x0C, 0xF1, 0x01, 0x06, ++0x00, 0xF0, 0x0F, 0x0C, 0x07, 0x37, 0xBC, 0xFB, 0xF6, 0xFE, 0x06, 0xFB, 0x1E, 0xCC, 0xBC, 0x45, 0xCE, 0xB2, 0xA2, 0xEB, ++0x05, 0x02, 0x40, 0xF3, 0x81, 0x80, 0x02, 0xF1, 0x01, 0x0C, 0xC0, 0xF3, 0xC1, 0x1E, 0x9E, 0xFB, 0xFC, 0xF2, 0x0C, 0xFB, ++0x12, 0xE2, 0x15, 0x44, 0xFF, 0xB2, 0xED, 0xB2, 0x09, 0x2F, 0x40, 0xF0, 0xAE, 0x80, 0x00, 0x2D, 0x40, 0xF0, 0x98, 0x80, ++0x02, 0x29, 0x00, 0xF0, 0xC0, 0x80, 0x05, 0x2E, 0x14, 0xBF, 0x4F, 0xF0, 0x08, 0x0C, 0x4F, 0xF0, 0x09, 0x0C, 0x09, 0x01, ++0x09, 0xB2, 0x00, 0x25, 0x76, 0xE0, 0x94, 0xF8, 0xB0, 0x70, 0xB4, 0xF8, 0xA6, 0x60, 0x94, 0xF8, 0xAC, 0xC0, 0x79, 0x1C, ++0xC0, 0xF3, 0x02, 0x17, 0xB7, 0xFB, 0xF1, 0xFE, 0x01, 0xFB, 0x1E, 0x77, 0x79, 0x00, 0x0E, 0x41, 0x06, 0xF0, 0x03, 0x06, ++0x0C, 0xF1, 0x01, 0x0C, 0x00, 0xF0, 0x0F, 0x01, 0x76, 0x00, 0x07, 0x36, 0xB1, 0xFB, 0xFC, 0xFE, 0x0C, 0xFB, 0x1E, 0x11, ++0xB1, 0x42, 0xC0, 0xF3, 0x41, 0x2C, 0xA2, 0xEB, 0x05, 0x02, 0xC8, 0xBF, 0xF1, 0xB2, 0x02, 0xF1, 0x01, 0x02, 0xC0, 0xF3, ++0xC1, 0x1E, 0xD8, 0xBF, 0xC9, 0xB2, 0xBC, 0xF1, 0x03, 0x0F, 0x18, 0xBF, 0x4F, 0xEA, 0x4C, 0x26, 0x9E, 0xFB, 0xF2, 0xFC, ++0x02, 0xFB, 0x1C, 0xEC, 0x94, 0xF8, 0xBC, 0x20, 0x65, 0x44, 0x08, 0xBF, 0x4F, 0xF4, 0x80, 0x66, 0xED, 0xB2, 0xEA, 0xB1, ++0x02, 0x29, 0x1A, 0xD0, 0x94, 0xF8, 0xBD, 0x20, 0x8A, 0x42, 0x16, 0xD3, 0x94, 0xF8, 0xBE, 0xC0, 0xFA, 0xB2, 0x94, 0x45, ++0x11, 0xD3, 0x94, 0xF8, 0xBF, 0x20, 0xAA, 0x42, 0x0D, 0xD3, 0x00, 0xF4, 0x80, 0x42, 0x12, 0xB2, 0x0A, 0xE0, 0x07, 0x05, ++0x7F, 0xF5, 0x71, 0xAF, 0xE1, 0xE6, 0x43, 0xF4, 0x80, 0x63, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x22, ++0x43, 0xEA, 0x07, 0x13, 0x43, 0xEA, 0xC5, 0x15, 0x29, 0x43, 0x31, 0x43, 0x42, 0xEA, 0x01, 0x03, 0x9B, 0xB2, 0x18, 0x46, ++0xBD, 0xE8, 0xF0, 0x81, 0x57, 0x1C, 0xC0, 0xF3, 0xC1, 0x1E, 0x9E, 0xFB, 0xF7, 0xF2, 0x07, 0xFB, 0x12, 0xE2, 0x15, 0x44, ++0xBC, 0xF1, 0x06, 0x0F, 0xED, 0xB2, 0x5F, 0xFA, 0x8C, 0xF7, 0x7F, 0xF4, 0x7B, 0xAF, 0x02, 0x2D, 0x20, 0xD0, 0x09, 0x01, ++0x09, 0xB2, 0xED, 0x01, 0x01, 0x34, 0xC0, 0xF3, 0x40, 0x20, 0xB0, 0xFB, 0xF4, 0xF2, 0x04, 0xFB, 0x12, 0x00, 0x43, 0xEA, ++0x40, 0x23, 0x2B, 0x43, 0x0B, 0x43, 0x4C, 0xEA, 0x03, 0x03, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, ++0x80, 0x63, 0xC5, 0xE6, 0x02, 0x2D, 0x16, 0xD1, 0x05, 0x29, 0x2D, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0xBC, 0x46, 0x4F, 0xF4, ++0x80, 0x75, 0xE1, 0xE7, 0x03, 0x29, 0x16, 0xD0, 0x06, 0x29, 0x14, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0x4F, 0xF4, 0x80, 0x75, ++0xD8, 0xE7, 0x09, 0x01, 0x09, 0xB2, 0xED, 0x01, 0x0F, 0xFA, 0x87, 0xFC, 0xD2, 0xE7, 0x03, 0x2D, 0x1B, 0xD1, 0x02, 0x29, ++0x0F, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0xBC, 0x46, 0x4F, 0xF4, 0xC0, 0x75, 0xC8, 0xE7, 0x71, 0x1E, 0xC9, 0xB2, 0x09, 0x01, ++0x4F, 0xF0, 0x06, 0x0C, 0x4F, 0xF4, 0x80, 0x75, 0xC0, 0xE7, 0xBC, 0x46, 0x43, 0xE7, 0xBC, 0x46, 0x10, 0x21, 0x4F, 0xF4, ++0xC0, 0x75, 0xB9, 0xE7, 0xBC, 0x46, 0x40, 0x21, 0x4F, 0xF4, 0x80, 0x75, 0xB4, 0xE7, 0x09, 0x01, 0x09, 0xB2, 0xED, 0x01, ++0xBC, 0x46, 0xAF, 0xE7, 0xB0, 0xF8, 0xB4, 0x30, 0x00, 0x2B, 0x4A, 0xD0, 0x2D, 0xE9, 0xF0, 0x4F, 0x03, 0xF1, 0xFF, 0x3B, ++0x1F, 0xFA, 0x8B, 0xFB, 0xBB, 0xF1, 0x01, 0x0F, 0x85, 0xB0, 0x8A, 0x46, 0x00, 0xF1, 0x10, 0x09, 0x3A, 0xD9, 0x01, 0x25, ++0x2F, 0x46, 0x0A, 0xF1, 0x04, 0x04, 0x4E, 0x46, 0x00, 0x21, 0x0D, 0xE0, 0x13, 0x43, 0x04, 0xD1, 0x73, 0x7A, 0x13, 0xB9, ++0x73, 0x7D, 0x01, 0x2B, 0x0B, 0xD0, 0x01, 0x35, 0xAF, 0xB2, 0x06, 0xF1, 0x0C, 0x08, 0x5F, 0x45, 0x46, 0x46, 0x20, 0xD2, ++0x22, 0x68, 0x54, 0xF8, 0x04, 0x3F, 0x9A, 0x42, 0xEC, 0xD9, 0x0C, 0x22, 0x06, 0xEB, 0x02, 0x08, 0x31, 0x46, 0x01, 0xA8, ++0x04, 0xF0, 0x3E, 0xFB, 0x30, 0x46, 0x41, 0x46, 0x0C, 0x22, 0x04, 0xF0, 0x39, 0xFB, 0x0C, 0x22, 0x01, 0xA9, 0x40, 0x46, ++0x04, 0xF0, 0x34, 0xFB, 0x01, 0x35, 0x54, 0xE9, 0x01, 0x32, 0x39, 0x46, 0xAF, 0xB2, 0x5F, 0x45, 0x44, 0xF8, 0x04, 0x2C, ++0x23, 0x60, 0x46, 0x46, 0xDE, 0xD3, 0x19, 0xB1, 0x8B, 0x46, 0xBB, 0xF1, 0x01, 0x0F, 0xC4, 0xD8, 0x05, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0xB0, 0xF8, 0xB4, 0x50, 0x83, 0xB0, 0x06, 0x46, 0x89, 0x46, 0x00, 0x2D, ++0x00, 0xF0, 0xE2, 0x80, 0x6F, 0x1E, 0x1F, 0xFA, 0x87, 0xF8, 0x08, 0xEB, 0x48, 0x08, 0x00, 0xF1, 0x0C, 0x03, 0x03, 0xEB, ++0x88, 0x08, 0x04, 0x46, 0x4F, 0xF0, 0x00, 0x0A, 0x41, 0xF6, 0x98, 0x1B, 0x60, 0x89, 0xFE, 0xF7, 0xAD, 0xFE, 0x30, 0xB9, ++0x63, 0x7B, 0x23, 0xB1, 0x23, 0x89, 0x5B, 0x45, 0x07, 0xD8, 0x4F, 0xF0, 0x01, 0x0A, 0x0C, 0x34, 0x44, 0x45, 0xF1, 0xD1, ++0x4F, 0xEA, 0xCA, 0x00, 0x40, 0xB2, 0x96, 0xF8, 0xA2, 0x40, 0x24, 0xF0, 0x08, 0x04, 0x04, 0x43, 0xE4, 0xB2, 0x86, 0xF8, ++0xA2, 0x40, 0x14, 0xF0, 0x02, 0x04, 0x09, 0xD1, 0x05, 0xF1, 0x80, 0x43, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x59, 0xF8, ++0x23, 0x30, 0x9A, 0x42, 0x00, 0xF2, 0x9C, 0x80, 0x1F, 0xFA, 0x87, 0xFB, 0xCD, 0xF8, 0x00, 0xB0, 0x4F, 0xF0, 0x02, 0x08, ++0x00, 0x9C, 0xA6, 0xF8, 0x88, 0xB0, 0x04, 0xEB, 0x44, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x58, 0x89, 0xFE, 0xF7, 0x7A, 0xFE, ++0x63, 0x00, 0x01, 0x93, 0xE0, 0xB9, 0x00, 0x2F, 0x13, 0xDD, 0x82, 0x46, 0x84, 0x46, 0x0C, 0xEB, 0x4C, 0x0C, 0x06, 0xEB, ++0x8C, 0x04, 0x60, 0x89, 0xFE, 0xF7, 0x6C, 0xFE, 0x0A, 0xF1, 0x01, 0x03, 0x1F, 0xFA, 0x83, 0xFA, 0xD4, 0x46, 0x10, 0xB1, ++0x4F, 0xF0, 0x00, 0x03, 0xA3, 0x73, 0xBA, 0x45, 0xED, 0xDB, 0xDD, 0xE9, 0x00, 0x23, 0x13, 0x44, 0x06, 0xEB, 0x83, 0x04, ++0x01, 0x23, 0xA3, 0x73, 0xA8, 0x45, 0xA6, 0xF8, 0x8A, 0xB0, 0x76, 0xD2, 0xA5, 0xEB, 0x08, 0x03, 0x03, 0xEB, 0x43, 0x03, ++0x06, 0xEB, 0x83, 0x03, 0x03, 0xE0, 0x1F, 0xFA, 0x80, 0xF8, 0xA8, 0x45, 0x6B, 0xD0, 0x99, 0x7B, 0x08, 0xF1, 0x01, 0x00, ++0x0C, 0x3B, 0x00, 0x29, 0xF5, 0xD0, 0xA5, 0xEB, 0x08, 0x00, 0x08, 0xF1, 0x01, 0x08, 0x1F, 0xFA, 0x88, 0xF8, 0x80, 0xB2, ++0x45, 0x45, 0xA6, 0xF8, 0x8A, 0x00, 0x58, 0xD9, 0xA5, 0xEB, 0x08, 0x05, 0xA7, 0xEB, 0x08, 0x08, 0x4F, 0xEA, 0x18, 0x48, ++0x05, 0xEB, 0x45, 0x03, 0x4F, 0xEA, 0x08, 0x48, 0x06, 0xEB, 0x83, 0x03, 0x02, 0xE0, 0x01, 0x3D, 0x45, 0x45, 0x48, 0xD0, ++0x99, 0x7B, 0x0C, 0x3B, 0x00, 0x29, 0xF8, 0xD0, 0x05, 0xEB, 0x45, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x59, 0xF8, 0x25, 0x20, ++0xB3, 0xF8, 0x08, 0xE0, 0x30, 0xB3, 0x31, 0x46, 0x00, 0x23, 0x4F, 0xF2, 0x32, 0x38, 0x0C, 0xE0, 0x59, 0xF8, 0x23, 0x70, ++0x97, 0x42, 0x02, 0xD3, 0xA6, 0x46, 0x3A, 0x46, 0x1D, 0x46, 0x01, 0x33, 0x9C, 0xB2, 0xA0, 0x42, 0x01, 0xF1, 0x0C, 0x01, ++0x14, 0xD9, 0x8C, 0x7B, 0x9F, 0xB2, 0x00, 0x2C, 0xF5, 0xD0, 0x5F, 0x45, 0xF3, 0xD0, 0x0C, 0x89, 0x44, 0x45, 0xE9, 0xD8, ++0x74, 0x45, 0xEE, 0xD3, 0x59, 0xF8, 0x23, 0x20, 0x1D, 0x46, 0x01, 0x33, 0xA6, 0x46, 0x9C, 0xB2, 0xA0, 0x42, 0x01, 0xF1, ++0x0C, 0x01, 0xEA, 0xD8, 0x00, 0x23, 0xA6, 0xF8, 0x8C, 0x50, 0xA6, 0xF8, 0x8E, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x07, 0xEB, 0x47, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x5B, 0x7B, 0x00, 0x2B, 0x3F, 0xF4, 0x5C, 0xAF, 0x00, 0x94, 0xA3, 0x46, ++0x4F, 0xF0, 0x01, 0x08, 0x5C, 0xE7, 0x05, 0x46, 0xB8, 0xE7, 0x5D, 0x46, 0x58, 0x46, 0xB5, 0xE7, 0x28, 0x46, 0x4F, 0xF0, ++0xFF, 0x37, 0x38, 0xE7, 0xC1, 0xF3, 0xC2, 0x23, 0x05, 0x2B, 0x5B, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x03, 0x27, 0x27, ++0x0B, 0x32, 0xB0, 0xF8, 0xAA, 0x00, 0x01, 0xF0, 0x7F, 0x01, 0xC8, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x70, 0x47, 0xC1, 0xF3, ++0x02, 0x12, 0xB0, 0xF8, 0xA6, 0x00, 0x53, 0x00, 0x18, 0x41, 0x00, 0xF0, 0x03, 0x00, 0x07, 0x30, 0x01, 0xF0, 0x0F, 0x03, ++0x83, 0x42, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x06, 0x2B, 0xC1, 0xF3, 0xC1, 0x11, 0x24, 0xD0, 0x09, 0x2B, 0x24, 0xD1, ++0x21, 0xBB, 0x02, 0x2A, 0x21, 0xD0, 0x05, 0x2A, 0x18, 0xBF, 0x00, 0x20, 0x70, 0x47, 0xC1, 0xF3, 0xC1, 0x03, 0x18, 0x44, ++0x01, 0xF0, 0x07, 0x01, 0x90, 0xF8, 0xA6, 0x00, 0xC8, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x70, 0x47, 0xB0, 0xF8, 0xA6, 0x00, ++0xC1, 0xF3, 0x02, 0x13, 0x5B, 0x00, 0x18, 0x41, 0x00, 0xF0, 0x03, 0x00, 0x40, 0x00, 0x07, 0x30, 0x01, 0xF0, 0x0F, 0x01, ++0x81, 0x42, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x02, 0x29, 0x06, 0xD0, 0x70, 0x47, 0x02, 0x29, 0x09, 0xD1, ++0x05, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, 0x03, 0x2A, 0x09, 0xD0, 0x06, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, ++0x03, 0x29, 0xF0, 0xD1, 0x02, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0xEA, 0xE7, 0x01, 0x20, 0x70, 0x47, ++0x2D, 0xE9, 0xF0, 0x4F, 0x82, 0x46, 0xB0, 0xF8, 0x88, 0x70, 0xB0, 0xF8, 0x8A, 0x00, 0x9A, 0xF8, 0xAD, 0x30, 0x9A, 0xF8, ++0xAE, 0x60, 0x00, 0xEB, 0x40, 0x00, 0x07, 0xEB, 0x47, 0x07, 0x83, 0xB0, 0x0A, 0xEB, 0x80, 0x0C, 0x0A, 0xEB, 0x87, 0x07, ++0x14, 0x46, 0x0D, 0x46, 0x08, 0x46, 0x52, 0x00, 0x4F, 0xF0, 0xFF, 0x31, 0x7F, 0x89, 0xBC, 0xF8, 0x0A, 0x80, 0x00, 0x93, ++0xCD, 0xF7, 0x86, 0xF9, 0x00, 0x2C, 0x7E, 0xD0, 0x00, 0x9B, 0xA6, 0xEB, 0x03, 0x09, 0x01, 0x3C, 0x09, 0xF1, 0x01, 0x03, ++0xE4, 0xB2, 0x01, 0x93, 0x4F, 0xF0, 0x00, 0x0B, 0x5F, 0xFA, 0x8B, 0xF3, 0x05, 0x2B, 0x5E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, ++0x59, 0x41, 0x32, 0x23, 0x13, 0x03, 0x41, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xF9, 0xFF, 0x80, 0x45, 0x81, 0x46, 0x52, 0xD0, ++0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x5E, 0xFF, 0x00, 0x28, 0x4C, 0xD0, 0xA5, 0xF8, 0x0A, 0x90, 0x49, 0xE0, 0x41, 0x46, ++0x50, 0x46, 0xFF, 0xF7, 0x77, 0xF8, 0x80, 0x45, 0x81, 0x46, 0x42, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x4E, 0xFF, ++0x00, 0x28, 0x3C, 0xD0, 0xA5, 0xF8, 0x08, 0x90, 0x39, 0xE0, 0x39, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xD9, 0xFF, 0xB8, 0x42, ++0x81, 0x46, 0x32, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x3E, 0xFF, 0x68, 0xB3, 0xA5, 0xF8, 0x06, 0x90, 0x2A, 0xE0, ++0x39, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x58, 0xF8, 0xB8, 0x42, 0x81, 0x46, 0x23, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, ++0x2F, 0xFF, 0xF0, 0xB1, 0xA5, 0xF8, 0x04, 0x90, 0x1B, 0xE0, 0x00, 0x9B, 0x03, 0x2B, 0x03, 0xD8, 0x9A, 0xF8, 0xA2, 0x30, ++0x19, 0x07, 0x3B, 0xD4, 0xC7, 0xF3, 0xC2, 0x23, 0x05, 0x2B, 0x4F, 0xEA, 0xD7, 0x22, 0x23, 0xD0, 0x12, 0xF0, 0x06, 0x0F, ++0x0B, 0xD0, 0x9A, 0xF8, 0xB1, 0x30, 0x01, 0x2B, 0x07, 0xD1, 0x87, 0xF4, 0x00, 0x73, 0x6B, 0x80, 0x03, 0xE0, 0x50, 0x46, ++0xFF, 0xF7, 0x1E, 0xFC, 0x28, 0x80, 0x03, 0x2E, 0x09, 0xD8, 0x35, 0xF8, 0x1B, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, ++0x04, 0xBF, 0x46, 0xF4, 0x80, 0x63, 0x25, 0xF8, 0x1B, 0x30, 0x5C, 0x45, 0x0B, 0xF1, 0x01, 0x03, 0x01, 0xD0, 0x9B, 0x46, ++0x8A, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0x4A, 0xC7, 0xF3, 0x41, 0x23, 0x01, 0x33, 0xA2, 0xFB, 0x03, 0x21, ++0x21, 0xF0, 0x01, 0x02, 0x02, 0xEB, 0x51, 0x02, 0x27, 0xF4, 0xC0, 0x67, 0x9B, 0x1A, 0x47, 0xEA, 0x43, 0x23, 0x6B, 0x80, ++0xBF, 0xB2, 0xD8, 0xE7, 0x04, 0xF0, 0x82, 0xF9, 0x01, 0x99, 0x00, 0xF0, 0x7F, 0x02, 0x92, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, ++0x13, 0x23, 0x00, 0x9A, 0x13, 0x44, 0xBA, 0xF8, 0xAA, 0x20, 0xDB, 0xB2, 0xDA, 0x40, 0xD2, 0x07, 0x0F, 0xD5, 0x00, 0x2B, ++0x08, 0xBF, 0x33, 0x46, 0x5A, 0x1E, 0x02, 0x2A, 0x6B, 0x80, 0xCC, 0xD8, 0x9A, 0xF8, 0xB2, 0x10, 0x00, 0xF4, 0x80, 0x62, ++0x42, 0xEA, 0x81, 0x22, 0x13, 0x43, 0x6B, 0x80, 0xC3, 0xE7, 0x33, 0x46, 0xF0, 0xE7, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, ++0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x84, 0xB0, 0x01, 0xA9, 0x06, 0x22, 0xFF, 0xF7, 0x1C, 0xFF, 0xB5, 0xF8, 0xB4, 0x10, ++0x01, 0x29, 0x30, 0xD9, 0x00, 0x26, 0x01, 0x24, 0xB0, 0x46, 0xA1, 0x46, 0x4F, 0xF6, 0xFF, 0x77, 0x18, 0xE0, 0xB5, 0xF8, ++0x88, 0x20, 0xA2, 0x42, 0x21, 0xD0, 0xB5, 0xF8, 0x8A, 0x20, 0xA2, 0x42, 0x1D, 0xD0, 0xB5, 0xF8, 0x8C, 0x20, 0xA2, 0x42, ++0x19, 0xD0, 0x05, 0x2E, 0x17, 0xD8, 0x04, 0xAA, 0x02, 0xEB, 0x46, 0x02, 0x32, 0xF8, 0x0C, 0xEC, 0xBE, 0x45, 0x17, 0xD1, ++0xA1, 0x42, 0x06, 0xF1, 0x01, 0x06, 0x10, 0xD9, 0x04, 0xEB, 0x44, 0x03, 0x05, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0x44, 0x0C, ++0xB3, 0xF9, 0x08, 0x20, 0x00, 0x2A, 0xDC, 0xDA, 0x1A, 0x7B, 0x0A, 0x2A, 0xD9, 0xD8, 0x01, 0x34, 0xA4, 0xB2, 0xA1, 0x42, ++0xEE, 0xD8, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x59, 0xB1, 0x2A, 0x46, 0x00, 0x20, 0xB2, 0xF8, 0x0A, 0xA0, 0xF2, 0x45, ++0x00, 0xF1, 0x01, 0x00, 0x02, 0xF1, 0x0C, 0x02, 0xDC, 0xD0, 0x88, 0x42, 0xF5, 0xD1, 0x0C, 0xEB, 0x04, 0x02, 0x05, 0xEB, ++0x82, 0x02, 0xA3, 0xF8, 0x0A, 0xE0, 0xA3, 0xF8, 0x08, 0x80, 0x21, 0x46, 0x82, 0xF8, 0x0D, 0x80, 0x28, 0x46, 0xA3, 0xF8, ++0x04, 0x80, 0xA3, 0xF8, 0x06, 0x80, 0x01, 0x34, 0x82, 0xF8, 0x0C, 0x80, 0x82, 0xF8, 0x0E, 0x90, 0xFF, 0xF7, 0x12, 0xF8, ++0xA4, 0xB2, 0xB5, 0xF8, 0xB4, 0x10, 0xBF, 0xE7, 0x30, 0xB4, 0x90, 0xF8, 0xA5, 0x30, 0x05, 0x2B, 0x00, 0xF2, 0x8C, 0x80, ++0xDF, 0xE8, 0x03, 0xF0, 0x36, 0x36, 0x03, 0x03, 0x70, 0x57, 0x90, 0xF8, 0xAF, 0x50, 0x90, 0xF8, 0xB1, 0x20, 0x90, 0xF8, ++0xB0, 0x30, 0x90, 0xF8, 0xA6, 0x40, 0x01, 0x35, 0x95, 0x40, 0x03, 0xFB, 0x05, 0x55, 0xAD, 0xB2, 0x08, 0x21, 0x00, 0x23, ++0x04, 0xF0, 0x01, 0x02, 0x12, 0xFB, 0x05, 0xF2, 0x13, 0x44, 0x01, 0x39, 0x9B, 0xB2, 0x4F, 0xEA, 0x54, 0x04, 0xF5, 0xD1, ++0xB0, 0xF8, 0xAA, 0x20, 0x90, 0xF8, 0xB2, 0x10, 0xC2, 0xF3, 0x80, 0x04, 0xC2, 0xF3, 0x40, 0x00, 0xC1, 0xF1, 0x01, 0x01, ++0x20, 0x44, 0x88, 0x40, 0x02, 0xF0, 0x01, 0x04, 0xC2, 0xF3, 0xC0, 0x02, 0x20, 0x44, 0x8A, 0x40, 0x10, 0x44, 0x18, 0x44, ++0x80, 0xB2, 0x0A, 0x28, 0x28, 0xBF, 0x0A, 0x20, 0x30, 0xBC, 0x70, 0x47, 0xB0, 0xF8, 0xAA, 0x10, 0x90, 0xF8, 0xB2, 0x30, ++0xC1, 0xF3, 0x80, 0x02, 0xC1, 0xF3, 0x40, 0x00, 0xC3, 0xF1, 0x01, 0x03, 0x10, 0x44, 0x98, 0x40, 0x01, 0xF0, 0x01, 0x04, ++0xC1, 0xF3, 0xC0, 0x02, 0x02, 0xFA, 0x03, 0xF3, 0x20, 0x44, 0x13, 0xFA, 0x80, 0xF0, 0x80, 0xB2, 0x04, 0x23, 0x41, 0xFA, ++0x03, 0xF2, 0x02, 0xF0, 0x01, 0x02, 0x01, 0x33, 0x10, 0x44, 0x0C, 0x2B, 0x80, 0xB2, 0xF6, 0xD1, 0xD9, 0xE7, 0x90, 0xF8, ++0xB1, 0x30, 0xB0, 0xF8, 0xA6, 0x20, 0x90, 0xF8, 0xAF, 0x40, 0x90, 0xF8, 0xB0, 0x10, 0x58, 0x1C, 0x02, 0xF0, 0x03, 0x03, ++0x04, 0xFB, 0x00, 0x00, 0x01, 0x2B, 0x01, 0xFB, 0x00, 0x00, 0x1F, 0xD0, 0x02, 0x2B, 0x14, 0xBF, 0x08, 0x23, 0x0A, 0x23, ++0x10, 0xFB, 0x03, 0xF0, 0x80, 0xB2, 0xC0, 0xE7, 0xB0, 0xF8, 0xA6, 0x20, 0x90, 0xF8, 0xAF, 0x30, 0x90, 0xF8, 0xB1, 0x40, ++0x90, 0xF8, 0xB0, 0x10, 0x02, 0xF0, 0x03, 0x02, 0x01, 0x33, 0x01, 0x3A, 0x03, 0xFA, 0x04, 0xF0, 0x01, 0x2A, 0x8C, 0xBF, ++0x08, 0x23, 0x09, 0x23, 0x01, 0xFB, 0x00, 0x00, 0x10, 0xFB, 0x03, 0xF0, 0x80, 0xB2, 0xA8, 0xE7, 0x09, 0x23, 0xE1, 0xE7, ++0x00, 0x20, 0xA7, 0xE7, 0x2D, 0xE9, 0xF8, 0x4F, 0xB0, 0xF8, 0xB4, 0x40, 0x05, 0x46, 0x00, 0x2C, 0x00, 0xF0, 0xF4, 0x80, ++0x04, 0xF1, 0xFF, 0x38, 0x1F, 0xFA, 0x88, 0xF1, 0x01, 0xEB, 0x41, 0x03, 0x00, 0xF1, 0x0C, 0x01, 0x01, 0xEB, 0x83, 0x01, ++0x4F, 0xF6, 0xFF, 0x76, 0x03, 0x46, 0x00, 0x22, 0x01, 0x20, 0x5E, 0x81, 0x9A, 0x80, 0xDA, 0x80, 0x1A, 0x81, 0x1A, 0x73, ++0x5A, 0x73, 0x98, 0x73, 0x0C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0xC1, 0x46, 0x95, 0xF8, 0xA5, 0x30, 0x05, 0x2B, 0x00, 0xF2, ++0xD9, 0x80, 0xDF, 0xE8, 0x03, 0xF0, 0x4E, 0x4E, 0x03, 0x03, 0x8A, 0x5E, 0x95, 0xF8, 0xAD, 0x20, 0xDB, 0x02, 0x00, 0x2A, ++0x00, 0xF0, 0xC7, 0x80, 0x99, 0xB2, 0x95, 0xF8, 0xB0, 0x20, 0x69, 0x81, 0xA9, 0x18, 0x95, 0xF8, 0xB1, 0x60, 0x91, 0xF8, ++0xA6, 0x70, 0x95, 0xF8, 0xAF, 0x00, 0x43, 0xEA, 0x46, 0x23, 0xB7, 0xFA, 0x87, 0xF7, 0xC7, 0xF1, 0x1F, 0x07, 0x43, 0xEA, ++0xC0, 0x13, 0xFF, 0xB2, 0x43, 0xEA, 0xC2, 0x03, 0x3B, 0x43, 0x9F, 0xB2, 0x09, 0xEB, 0x49, 0x09, 0x05, 0xEB, 0x89, 0x03, ++0x01, 0x26, 0x46, 0x45, 0x5F, 0x81, 0x80, 0xF2, 0x9B, 0x80, 0x28, 0x46, 0xFF, 0xF7, 0x7E, 0xFA, 0xB5, 0xF8, 0xB4, 0x40, ++0x00, 0x2C, 0x00, 0xF0, 0x87, 0x80, 0x2B, 0x46, 0x00, 0x22, 0x02, 0xE0, 0xA2, 0x42, 0x00, 0xF0, 0x81, 0x80, 0x59, 0x89, ++0x81, 0x42, 0x02, 0xF1, 0x01, 0x02, 0x03, 0xF1, 0x0C, 0x03, 0xF5, 0xD1, 0x01, 0x3C, 0xA6, 0x42, 0xE7, 0xDB, 0x00, 0x24, ++0xA1, 0xB2, 0x28, 0x46, 0xFE, 0xF7, 0x0A, 0xFF, 0xB5, 0xF8, 0xB4, 0x30, 0x01, 0x34, 0x9C, 0x42, 0xF6, 0xD3, 0xBD, 0xE8, ++0xF8, 0x8F, 0x95, 0xF8, 0xAD, 0x20, 0x00, 0x2A, 0x7A, 0xD0, 0x92, 0xB2, 0x95, 0xF8, 0xB2, 0x10, 0x95, 0xF8, 0xAE, 0x70, ++0x6A, 0x81, 0xDB, 0x02, 0x43, 0xEA, 0x81, 0x23, 0x3B, 0x43, 0x9F, 0xB2, 0xC2, 0xE7, 0x95, 0xF8, 0xAD, 0x30, 0x00, 0x2B, ++0x67, 0xD0, 0x95, 0xF8, 0xBC, 0x30, 0x00, 0x2B, 0x0C, 0xBF, 0x4F, 0xF4, 0x28, 0x52, 0x4F, 0xF4, 0xD4, 0x42, 0x95, 0xF8, ++0xB0, 0x30, 0xB5, 0xF8, 0xA6, 0x60, 0x6A, 0x81, 0x5A, 0x00, 0x16, 0x41, 0x95, 0xF8, 0xAF, 0xA0, 0x06, 0xF0, 0x03, 0x06, ++0x1B, 0x01, 0x76, 0x00, 0x07, 0x36, 0x43, 0xEA, 0xCA, 0x1A, 0x4A, 0xEA, 0x06, 0x07, 0x47, 0xF4, 0x20, 0x57, 0x39, 0x46, ++0x28, 0x46, 0xFF, 0xF7, 0x1B, 0xFD, 0x01, 0x3E, 0xF3, 0xB2, 0xB6, 0xB2, 0x00, 0x28, 0x99, 0xD1, 0x06, 0x2B, 0xF0, 0xD1, ++0x96, 0xE7, 0x95, 0xF8, 0xB0, 0xA0, 0xB5, 0xF8, 0xA6, 0xB0, 0x95, 0xF8, 0xAF, 0x60, 0x95, 0xF8, 0xB1, 0x30, 0x4F, 0xEA, ++0x4A, 0x02, 0x4B, 0xFA, 0x02, 0xFB, 0xF6, 0x01, 0x46, 0xEA, 0x43, 0x26, 0x0B, 0xF0, 0x03, 0x0B, 0x4F, 0xF4, 0x00, 0x53, ++0x4F, 0xEA, 0x0A, 0x1A, 0x0B, 0xF1, 0x07, 0x0B, 0x36, 0xB2, 0x6B, 0x81, 0x4A, 0xEA, 0x0B, 0x07, 0x37, 0x43, 0x47, 0xF4, ++0x00, 0x57, 0xBF, 0xB2, 0x39, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0xF0, 0xFC, 0x0B, 0xF1, 0xFF, 0x3B, 0x5F, 0xFA, 0x8B, 0xF3, ++0x1F, 0xFA, 0x8B, 0xFB, 0x00, 0x28, 0x7F, 0xF4, 0x6B, 0xAF, 0x06, 0x2B, 0xEA, 0xD1, 0x67, 0xE7, 0x06, 0xEB, 0x46, 0x03, ++0x01, 0x36, 0x05, 0xEB, 0x83, 0x03, 0xB6, 0xB2, 0x04, 0xF1, 0xFF, 0x38, 0x46, 0x45, 0x58, 0x81, 0xFF, 0xF6, 0x65, 0xAF, ++0x00, 0x2C, 0x7F, 0xF4, 0x7A, 0xAF, 0xBD, 0xE8, 0xF8, 0x8F, 0x4F, 0xF4, 0x80, 0x62, 0x9C, 0xE7, 0x4F, 0xF4, 0x80, 0x62, ++0x82, 0xE7, 0x4F, 0xF4, 0x80, 0x61, 0x36, 0xE7, 0x4F, 0xF0, 0xFF, 0x39, 0xC8, 0x46, 0x21, 0xE7, 0x00, 0x27, 0x6F, 0x81, ++0x46, 0xE7, 0x00, 0xBF, 0x90, 0xF8, 0xAD, 0x30, 0x0B, 0x2B, 0xF0, 0xB4, 0x0C, 0xD9, 0x90, 0xF8, 0xA2, 0x20, 0x04, 0x23, ++0x01, 0x24, 0x22, 0xF0, 0x04, 0x02, 0x13, 0x43, 0x80, 0xF8, 0xA2, 0x30, 0x01, 0xB1, 0x0C, 0x70, 0xF0, 0xBC, 0x70, 0x47, ++0xB0, 0xF8, 0x88, 0x30, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, ++0x04, 0xD1, 0x00, 0x23, 0x90, 0xF8, 0xA2, 0x20, 0x1C, 0x46, 0xE6, 0xE7, 0xB0, 0xF8, 0x8A, 0x30, 0x03, 0xEB, 0x43, 0x03, ++0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, 0xEF, 0xD0, 0xB0, 0xF8, 0x8C, 0x30, 0x03, 0xEB, ++0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, 0xE4, 0xD0, 0x90, 0xF8, 0xA2, 0x20, ++0x12, 0xF0, 0x20, 0x04, 0x20, 0xD1, 0x90, 0xF8, 0xA4, 0x30, 0x44, 0x33, 0x30, 0xF8, 0x13, 0x30, 0x03, 0xEB, 0x43, 0x03, ++0x00, 0xEB, 0x83, 0x05, 0x6B, 0x89, 0x13, 0xF4, 0x00, 0x5F, 0x4F, 0xEA, 0xD3, 0x27, 0xC3, 0xF3, 0xC2, 0x26, 0x12, 0xD1, ++0x17, 0xF0, 0x06, 0x0F, 0x1D, 0xD1, 0x03, 0xF0, 0x7F, 0x03, 0x02, 0x2B, 0x15, 0xD9, 0x2D, 0x89, 0x40, 0xF2, 0x8E, 0x23, ++0x9D, 0x42, 0x86, 0xBF, 0x01, 0x24, 0x04, 0x23, 0x00, 0x23, 0xAA, 0xE7, 0x04, 0x23, 0x01, 0x24, 0xA7, 0xE7, 0x07, 0x2E, ++0x07, 0xD0, 0x03, 0xF0, 0x0F, 0x06, 0xC3, 0xF3, 0x02, 0x13, 0x02, 0x2E, 0xEB, 0xD8, 0x00, 0x2B, 0xE9, 0xD1, 0x2D, 0x89, ++0x41, 0xF6, 0x98, 0x13, 0xE8, 0xE7, 0x03, 0xF0, 0x07, 0x06, 0xC3, 0xF3, 0xC1, 0x03, 0xF2, 0xE7, 0xF8, 0xB5, 0x90, 0xF8, ++0xA2, 0x60, 0x16, 0xF0, 0x10, 0x05, 0x04, 0x46, 0x35, 0xD0, 0xB0, 0xF8, 0xB4, 0x00, 0x00, 0x28, 0x5F, 0xD0, 0xB4, 0xF8, ++0xBA, 0x70, 0x00, 0x23, 0x02, 0xE0, 0x82, 0x42, 0xCB, 0xB2, 0x46, 0xD2, 0x03, 0xEB, 0x43, 0x02, 0x04, 0xEB, 0x82, 0x02, ++0x59, 0x1C, 0x55, 0x89, 0xBD, 0x42, 0xCA, 0xB2, 0xF3, 0xD1, 0x9A, 0xB2, 0xA4, 0xF8, 0x88, 0x20, 0xA4, 0xF8, 0x8A, 0x20, ++0xA4, 0xF8, 0x8C, 0x20, 0x01, 0x38, 0x80, 0xB2, 0x04, 0xF1, 0x0C, 0x03, 0x00, 0xEB, 0x40, 0x00, 0x03, 0xEB, 0x80, 0x00, ++0x00, 0x22, 0x23, 0x46, 0x9A, 0x80, 0xDA, 0x80, 0x0C, 0x33, 0x98, 0x42, 0xFA, 0xD1, 0x26, 0xF0, 0x30, 0x06, 0x46, 0xF0, ++0x20, 0x06, 0x00, 0x23, 0x84, 0xF8, 0xA2, 0x60, 0x84, 0xF8, 0x9B, 0x30, 0x01, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x90, 0xF8, ++0x88, 0x00, 0x0C, 0x23, 0x03, 0xFB, 0x00, 0x40, 0x04, 0x30, 0xFE, 0xF7, 0x73, 0xFC, 0xB4, 0xF8, 0xB4, 0x30, 0x00, 0x2B, ++0xF1, 0xD0, 0x01, 0x3B, 0x9A, 0xB2, 0x02, 0xEB, 0x42, 0x03, 0x04, 0xF1, 0x0C, 0x02, 0x02, 0xEB, 0x83, 0x02, 0x2B, 0x46, ++0xA3, 0x80, 0xE3, 0x80, 0x0C, 0x34, 0x94, 0x42, 0xFA, 0xD1, 0x28, 0x46, 0xF8, 0xBD, 0xC1, 0xD1, 0x01, 0x38, 0xC3, 0xB2, ++0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0xC2, 0xB2, 0x00, 0x21, 0x5F, 0x81, 0x19, 0x81, 0xA4, 0xF8, 0x88, 0x20, ++0xA4, 0xF8, 0x8A, 0x20, 0xA4, 0xF8, 0x8C, 0x20, 0xB7, 0xE7, 0xB4, 0xF8, 0xBA, 0x20, 0xA4, 0xF8, 0xFE, 0x2B, 0x4F, 0xF0, ++0xFF, 0x11, 0xFF, 0x22, 0xA4, 0xF8, 0xFC, 0x0B, 0xC4, 0xF8, 0x88, 0x10, 0xA4, 0xF8, 0x8C, 0x20, 0xB7, 0xE7, 0x00, 0xBF, ++0xC2, 0x6C, 0x12, 0x69, 0xC2, 0xF3, 0x07, 0x21, 0xC2, 0xF3, 0x00, 0x42, 0x0A, 0x44, 0x00, 0x23, 0x01, 0x31, 0xFE, 0xF7, ++0xC9, 0xB9, 0x00, 0xBF, 0x8A, 0x1A, 0x01, 0x23, 0xFE, 0xF7, 0xC4, 0xB9, 0xC3, 0x88, 0x99, 0x04, 0x30, 0xB4, 0xC3, 0xF3, ++0xC2, 0x22, 0x11, 0xD4, 0xD9, 0x0A, 0x11, 0xF0, 0x06, 0x0F, 0x4A, 0xD1, 0x13, 0xF0, 0x7C, 0x0F, 0x03, 0xF0, 0x7F, 0x02, ++0x5D, 0xD1, 0xC3, 0xF3, 0x80, 0x23, 0x43, 0xEA, 0x42, 0x02, 0x3D, 0x4B, 0x30, 0xBC, 0x53, 0xF8, 0x22, 0x00, 0x70, 0x47, ++0x07, 0x2A, 0x37, 0xD0, 0x51, 0x1F, 0x03, 0xF0, 0x0F, 0x04, 0x01, 0x29, 0x37, 0xD8, 0xDF, 0xE8, 0x01, 0xF0, 0x01, 0x1B, ++0xC3, 0xF3, 0x00, 0x21, 0x4A, 0x00, 0x11, 0x44, 0x06, 0x22, 0x12, 0xFB, 0x04, 0x12, 0xC3, 0xF3, 0x41, 0x21, 0x0A, 0x44, ++0x31, 0x49, 0x51, 0xF8, 0x22, 0x00, 0xC3, 0xF3, 0xC0, 0x11, 0xC3, 0xF3, 0x02, 0x12, 0xC3, 0xF3, 0x80, 0x33, 0xC8, 0x40, ++0x01, 0x32, 0x30, 0xBC, 0xB0, 0xFB, 0xF2, 0xF0, 0x98, 0x40, 0x70, 0x47, 0x00, 0x7A, 0x00, 0xF0, 0x07, 0x00, 0x02, 0x28, ++0x31, 0xD8, 0x28, 0x49, 0xC3, 0xF3, 0x41, 0x25, 0x03, 0x22, 0x51, 0xF8, 0x20, 0x10, 0x12, 0xFB, 0x04, 0x52, 0xC3, 0xF3, ++0x02, 0x10, 0x01, 0x30, 0x51, 0xF8, 0x22, 0x30, 0xB3, 0xFB, 0xF0, 0xF0, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x30, 0xBC, ++0x70, 0x47, 0x03, 0xF0, 0x07, 0x04, 0xC3, 0xF3, 0x40, 0x20, 0xC3, 0xF3, 0xC1, 0x11, 0x40, 0xEA, 0x41, 0x01, 0x41, 0xEA, ++0xC4, 0x04, 0x04, 0x2A, 0x19, 0x49, 0x14, 0xBF, 0xC3, 0xF3, 0xC1, 0x03, 0xC3, 0xF3, 0x02, 0x13, 0x51, 0xF8, 0x24, 0x00, ++0x01, 0x33, 0x30, 0xBC, 0xB0, 0xFB, 0xF3, 0xF0, 0x70, 0x47, 0x14, 0x4B, 0x04, 0x3A, 0x30, 0xBC, 0x53, 0xF8, 0x22, 0x00, ++0x70, 0x47, 0xC2, 0x1E, 0xC2, 0xF3, 0x46, 0x01, 0x02, 0xF0, 0xFE, 0x00, 0x08, 0x44, 0x06, 0x21, 0x11, 0xFB, 0x04, 0x04, ++0xC3, 0xF3, 0x41, 0x21, 0x0C, 0x44, 0x08, 0x49, 0x51, 0xF8, 0x24, 0x00, 0xC3, 0xF3, 0x02, 0x13, 0x02, 0xF0, 0x01, 0x02, ++0x59, 0x1C, 0x30, 0xBC, 0x20, 0xFA, 0x02, 0xF3, 0xB3, 0xFB, 0xF1, 0xF0, 0x70, 0x47, 0x00, 0xBF, 0x54, 0xCC, 0x15, 0x00, ++0x74, 0xCC, 0x15, 0x00, 0xA4, 0xD0, 0x15, 0x00, 0x44, 0xCF, 0x15, 0x00, 0x84, 0xD0, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, ++0xB0, 0xF8, 0x96, 0x30, 0x90, 0xF8, 0xA2, 0x80, 0x90, 0xF8, 0xA5, 0x60, 0x03, 0xEB, 0x83, 0x03, 0x5B, 0x00, 0xA0, 0xF8, ++0x98, 0x30, 0x07, 0x46, 0x03, 0xF0, 0xB8, 0xFD, 0xB7, 0xF8, 0xB4, 0x10, 0x80, 0xB2, 0xB0, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, ++0x13, 0x00, 0x00, 0x29, 0x77, 0xD0, 0xB7, 0xF8, 0x88, 0xC0, 0x83, 0xB2, 0x08, 0xF0, 0x02, 0x08, 0x00, 0x20, 0x4F, 0xF2, ++0x33, 0x3E, 0x03, 0x44, 0xB3, 0xFB, 0xF1, 0xF5, 0x01, 0xFB, 0x15, 0x35, 0x05, 0xEB, 0x45, 0x02, 0x92, 0x00, 0xAB, 0xB2, ++0x07, 0xEB, 0x02, 0x0A, 0x9C, 0x45, 0x02, 0xF1, 0x04, 0x02, 0x00, 0xF1, 0x01, 0x00, 0x07, 0xEB, 0x02, 0x04, 0x4F, 0xEA, ++0x45, 0x09, 0x58, 0xD0, 0xBA, 0xF8, 0x08, 0x20, 0x72, 0x45, 0x54, 0xD8, 0xB8, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0xBA, 0xF8, ++0x0A, 0x20, 0xD2, 0x12, 0x12, 0xF0, 0x06, 0x0F, 0x4B, 0xD0, 0x01, 0x2E, 0x42, 0xD9, 0x0C, 0xEB, 0x4C, 0x0C, 0x07, 0xEB, ++0x8C, 0x0C, 0xBC, 0xF8, 0x0A, 0x30, 0x98, 0x04, 0x4F, 0xEA, 0xD3, 0x26, 0xC3, 0xF3, 0xC2, 0x22, 0x47, 0xD4, 0x16, 0xF0, ++0x06, 0x06, 0x01, 0xD0, 0xC3, 0xF3, 0xC1, 0x06, 0xE3, 0x88, 0x99, 0x04, 0x4F, 0xEA, 0xD3, 0x28, 0xC3, 0xF3, 0xC2, 0x22, ++0x36, 0xD4, 0x18, 0xF0, 0x06, 0x08, 0x01, 0xD0, 0xC3, 0xF3, 0xC1, 0x08, 0xB7, 0xF8, 0x8A, 0x00, 0x00, 0xEB, 0x40, 0x00, ++0x07, 0xEB, 0x80, 0x00, 0xA9, 0x44, 0x04, 0x30, 0x07, 0xEB, 0x89, 0x09, 0xFF, 0xF7, 0xFA, 0xFE, 0x99, 0xF8, 0x0D, 0x30, ++0x82, 0x46, 0x5B, 0xBB, 0xB7, 0xF8, 0x96, 0xB0, 0x20, 0x46, 0xFF, 0xF7, 0xF1, 0xFE, 0x50, 0x45, 0x81, 0x46, 0x0D, 0xD3, ++0x01, 0x3E, 0x46, 0x45, 0x23, 0xD2, 0x23, 0x7A, 0x5B, 0x45, 0x10, 0xD3, 0x97, 0xF8, 0x9A, 0x30, 0x01, 0x33, 0xDB, 0xB2, ++0x02, 0x2B, 0x87, 0xF8, 0x9A, 0x30, 0x29, 0xD8, 0x01, 0x20, 0x87, 0xF8, 0xA0, 0x50, 0x87, 0xF8, 0x9B, 0x00, 0xBD, 0xE8, ++0xF8, 0x8F, 0x88, 0x42, 0x8F, 0xD1, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x07, 0x2A, 0x18, 0xD0, 0xC3, 0xF3, 0x02, 0x18, ++0xC8, 0xE7, 0x07, 0x2A, 0x11, 0xD0, 0xC3, 0xF3, 0x02, 0x16, 0xB7, 0xE7, 0x4F, 0xF0, 0x20, 0x0B, 0xD2, 0xE7, 0xB7, 0xF8, ++0x8C, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x07, 0xEB, 0x80, 0x00, 0x04, 0x30, 0xFF, 0xF7, 0xBE, 0xFE, 0x81, 0x45, 0xDB, 0xD3, ++0xCF, 0xE7, 0x00, 0x26, 0xA6, 0xE7, 0x4F, 0xF0, 0x00, 0x08, 0xAF, 0xE7, 0x0F, 0x2B, 0x84, 0xBF, 0x0F, 0x23, 0x87, 0xF8, ++0x9A, 0x30, 0xD8, 0xE7, 0x90, 0xF8, 0xA2, 0x30, 0x99, 0x06, 0x1F, 0xD4, 0x10, 0xB5, 0x90, 0xF8, 0x9B, 0x20, 0x04, 0x46, ++0xC2, 0xB9, 0xB0, 0xF8, 0x98, 0x20, 0x92, 0xB9, 0x5A, 0x06, 0x0B, 0xD5, 0xB0, 0xF8, 0xB4, 0x20, 0x09, 0x2A, 0x03, 0xD9, ++0xFF, 0xF7, 0x9E, 0xFB, 0x94, 0xF8, 0xA2, 0x30, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0xA2, 0x30, 0x20, 0x46, 0xBD, 0xE8, ++0x10, 0x40, 0xFF, 0xF7, 0x29, 0xBF, 0x01, 0x3A, 0xA0, 0xF8, 0x98, 0x20, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x70, 0x47, ++0x2D, 0xE9, 0xF0, 0x41, 0x29, 0x4F, 0x2A, 0x4E, 0xD7, 0xF8, 0x00, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0xB8, 0xF9, 0x00, 0x20, ++0x03, 0xFB, 0x00, 0x63, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x8A, 0xB0, 0x04, 0x46, 0x20, 0xDB, 0x28, 0x46, 0xFF, 0xF7, ++0xDF, 0xFB, 0xA5, 0xF8, 0xB4, 0x00, 0xB8, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x22, 0xDB, 0x28, 0x46, 0xFF, 0xF7, 0x6A, 0xFC, ++0x69, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x3C, 0xF9, 0x28, 0x46, 0x00, 0x21, 0xFF, 0xF7, 0x66, 0xFD, 0x4F, 0xF4, 0x1E, 0x70, ++0x00, 0xFB, 0x04, 0x64, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x01, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x0A, 0xB0, 0xBD, 0xE8, ++0xF0, 0x81, 0x00, 0x2D, 0xDC, 0xD1, 0x12, 0x49, 0x12, 0x48, 0x40, 0xF6, 0xAF, 0x42, 0xF1, 0xF7, 0x03, 0xF9, 0xD7, 0xF8, ++0x00, 0x80, 0xD3, 0xE7, 0x40, 0xB1, 0x0A, 0x28, 0xD9, 0xD9, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF6, 0xB4, 0x42, 0xF1, 0xF7, ++0xF7, 0xF8, 0xD2, 0xE7, 0x08, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0xB3, 0x42, 0xF1, 0xF7, 0xF0, 0xF8, 0x3B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC7, 0xDA, 0xB5, 0xF8, 0xB4, 0x00, 0xE8, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x0C, 0xCA, 0x15, 0x00, 0xF4, 0xC9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0xDF, 0xF8, 0xBC, 0x80, 0x29, 0x4D, 0xD8, 0xF8, 0x00, 0x40, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x00, 0x53, 0x07, 0x46, ++0xB4, 0xF9, 0x00, 0x00, 0xD3, 0xF8, 0x4C, 0x41, 0x00, 0x28, 0x0D, 0x46, 0x16, 0x46, 0x20, 0xDB, 0x94, 0xF8, 0xAF, 0x30, ++0xAB, 0x42, 0x39, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0x84, 0xF8, 0xAF, 0x50, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x26, 0xDB, ++0x84, 0xF8, 0xB0, 0x60, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x17, 0xDB, 0x94, 0xF8, 0xA2, 0x30, 0x9A, 0x06, 0x05, 0xD5, ++0x63, 0xF0, 0x7F, 0x03, 0x84, 0xF8, 0xA2, 0x30, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7, ++0x69, 0xBF, 0x00, 0x2C, 0xDC, 0xD1, 0x11, 0x49, 0x11, 0x48, 0x40, 0xF6, 0xCC, 0x42, 0xF1, 0xF7, 0x9F, 0xF8, 0xD5, 0xE7, ++0x07, 0x2E, 0xE5, 0xD9, 0x0C, 0x49, 0x0E, 0x48, 0x40, 0xF6, 0xD4, 0x42, 0xF1, 0xF7, 0x96, 0xF8, 0xDE, 0xE7, 0x03, 0x2D, ++0xD6, 0xD9, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0xD2, 0x42, 0xF1, 0xF7, 0x8D, 0xF8, 0xD8, 0xF8, 0x00, 0x30, 0xCD, 0xE7, ++0x94, 0xF8, 0xB0, 0x30, 0xB3, 0x42, 0xC1, 0xD1, 0xD6, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x68, 0x8E, 0x15, 0x00, 0x50, 0xCA, 0x15, 0x00, 0x34, 0xCA, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x4D, 0x4B, 0x8D, 0xB0, 0x1A, 0x68, 0x01, 0x90, 0x04, 0x46, 0x4C, 0x48, 0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x73, ++0x03, 0xFB, 0x04, 0x03, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0xB1, 0x0C, 0x46, 0x79, 0xDB, 0x9B, 0xF8, 0xB2, 0x20, 0xA2, 0x42, ++0x72, 0xD0, 0x8B, 0xF8, 0xB2, 0x40, 0x00, 0x2C, 0x6E, 0xD0, 0x9B, 0xF8, 0xA2, 0x20, 0x12, 0xF0, 0x20, 0x07, 0x76, 0xD1, ++0xBB, 0xF8, 0xB4, 0x90, 0xB8, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x15, 0xD1, 0x4D, 0xE0, 0x25, 0x44, 0x0C, 0xAB, 0x01, 0x37, ++0x0B, 0xEB, 0x85, 0x05, 0x03, 0xEB, 0x84, 0x04, 0xB8, 0xB2, 0x4F, 0xF0, 0x01, 0x03, 0x81, 0x45, 0xAB, 0x73, 0xA6, 0xF8, ++0x0A, 0xA0, 0xA6, 0xF8, 0x08, 0x80, 0x85, 0xF8, 0x0D, 0x80, 0x44, 0xF8, 0x28, 0x8C, 0x38, 0xD9, 0xBC, 0xB2, 0x04, 0xEB, ++0x44, 0x06, 0x0B, 0xEB, 0x86, 0x06, 0x65, 0x00, 0xB6, 0xF8, 0x0A, 0xA0, 0x50, 0x46, 0xFD, 0xF7, 0x19, 0xFF, 0x00, 0x28, ++0xDD, 0xD0, 0x4A, 0xF4, 0x80, 0x6A, 0xB9, 0xF1, 0x00, 0x0F, 0x16, 0xD0, 0x58, 0x46, 0x4F, 0xF0, 0x00, 0x0C, 0x01, 0xE0, ++0xCC, 0x45, 0xD2, 0xD0, 0xB0, 0xF8, 0x0A, 0xE0, 0xD6, 0x45, 0x0C, 0xF1, 0x01, 0x0C, 0x00, 0xF1, 0x0C, 0x00, 0xF5, 0xD1, ++0x58, 0x46, 0xFE, 0xF7, 0x37, 0xFE, 0xBB, 0xF8, 0xB4, 0x90, 0x82, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0xE8, 0xD1, 0x28, 0x19, ++0x0C, 0xAB, 0x0B, 0xEB, 0x80, 0x00, 0x03, 0xEB, 0x84, 0x04, 0x01, 0x25, 0x85, 0x73, 0xA6, 0xF8, 0x0A, 0xA0, 0xA6, 0xF8, ++0x08, 0x90, 0x80, 0xF8, 0x0D, 0x90, 0x44, 0xF8, 0x28, 0x9C, 0x02, 0xA9, 0x58, 0x46, 0xFE, 0xF7, 0xCF, 0xFF, 0x02, 0xA9, ++0x58, 0x46, 0xFF, 0xF7, 0x1B, 0xF8, 0x01, 0x9A, 0x11, 0x46, 0x10, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x29, ++0x99, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x01, 0x03, 0x89, 0xF8, 0x56, 0x31, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xBB, 0xF1, ++0x00, 0x0F, 0x82, 0xD1, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF6, 0xEA, 0x42, 0xF0, 0xF7, 0xE2, 0xFF, 0x7B, 0xE7, 0x62, 0xF0, ++0x7F, 0x02, 0x8B, 0xF8, 0xA2, 0x20, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0xB0, 0xF8, 0x54, 0x21, 0x03, 0x29, 0x9A, 0xBF, 0x02, 0xF4, 0x80, 0x62, ++0x12, 0xB2, 0x00, 0x22, 0x10, 0xB4, 0x42, 0xEA, 0x01, 0x03, 0xD0, 0xF8, 0x48, 0x41, 0x43, 0xF0, 0x00, 0x53, 0xC4, 0xE9, ++0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x90, 0xF8, 0xA5, 0x30, 0xC1, 0xF3, 0xC2, 0x22, ++0x93, 0x42, 0x13, 0xD3, 0x05, 0x2B, 0x70, 0xB5, 0x4F, 0xEA, 0xD1, 0x24, 0x11, 0xD0, 0x04, 0x2B, 0x29, 0xD0, 0x02, 0x3B, ++0x01, 0x2B, 0x12, 0xD8, 0x14, 0xF0, 0x06, 0x03, 0x04, 0xF0, 0x06, 0x05, 0x26, 0xD1, 0x90, 0xF8, 0xAD, 0x20, 0x03, 0x2A, ++0x1B, 0xD8, 0x0D, 0xE0, 0x00, 0x23, 0x18, 0x46, 0x70, 0x47, 0x05, 0x2A, 0x03, 0xD0, 0x90, 0xF8, 0xAD, 0x30, 0x03, 0x2B, ++0x15, 0xD8, 0x14, 0xF0, 0x06, 0x0F, 0x04, 0xF0, 0x06, 0x05, 0x13, 0xD1, 0x4A, 0x05, 0xC1, 0xF3, 0x80, 0x23, 0x03, 0xD4, ++0x90, 0xF8, 0xB2, 0x20, 0x01, 0x2A, 0x04, 0xD0, 0xFF, 0xF7, 0x9A, 0xF8, 0x03, 0x1E, 0x18, 0xBF, 0x01, 0x23, 0x18, 0x46, ++0x70, 0xBD, 0x04, 0x2A, 0x1A, 0xD0, 0x00, 0x23, 0x18, 0x46, 0x70, 0xBD, 0x04, 0x2A, 0x1A, 0xD9, 0x90, 0xF8, 0xAF, 0x60, ++0xC1, 0xF3, 0xC1, 0x13, 0x9E, 0x42, 0xF4, 0xD3, 0x63, 0x07, 0x08, 0xD5, 0x07, 0x2A, 0xE7, 0xD0, 0xC1, 0xF3, 0x02, 0x13, ++0x90, 0xF8, 0xB0, 0x20, 0x9A, 0x42, 0xEA, 0xD3, 0xE0, 0xE7, 0x00, 0x2D, 0xDE, 0xD0, 0xC1, 0xF3, 0xC1, 0x03, 0xF5, 0xE7, ++0x14, 0xF0, 0x06, 0x0F, 0x04, 0xF0, 0x06, 0x05, 0xCE, 0xD0, 0x8E, 0x05, 0xE2, 0xD5, 0x90, 0xF8, 0xB1, 0x30, 0x00, 0x2B, ++0xD5, 0xD0, 0xDD, 0xE7, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0x81, 0x03, 0x2D, 0xE9, 0xF0, 0x47, 0x1F, 0x89, 0x80, 0x46, ++0x41, 0xF6, 0x98, 0x10, 0x87, 0x42, 0x38, 0xD9, 0xB3, 0xF8, 0x0A, 0x90, 0xD8, 0xF8, 0x94, 0xA0, 0x48, 0x46, 0x15, 0x46, ++0x8C, 0x00, 0xFD, 0xF7, 0x2F, 0xFE, 0x08, 0xB3, 0x00, 0x26, 0x20, 0x1D, 0x40, 0x44, 0xFF, 0xF7, 0x8D, 0xFC, 0x2D, 0x4A, ++0x4F, 0xF4, 0x7A, 0x73, 0x30, 0x44, 0x03, 0xFB, 0x07, 0xF3, 0xB3, 0xFB, 0xF0, 0xF3, 0x02, 0xFB, 0x03, 0xF3, 0x18, 0x0C, ++0x75, 0xB1, 0x43, 0xF2, 0x32, 0x33, 0x9F, 0x42, 0x1C, 0xD9, 0x44, 0xF6, 0xCB, 0x43, 0x9F, 0x42, 0x21, 0xD8, 0x24, 0x4B, ++0x5A, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xBD, 0xE8, 0xF0, 0x87, 0x20, 0x4E, 0x21, 0x4B, ++0xC9, 0xF3, 0xC2, 0x29, 0x4F, 0xEA, 0x1A, 0x4A, 0xB9, 0xF1, 0x06, 0x0F, 0x08, 0xBF, 0x1E, 0x46, 0xB6, 0xFB, 0xFA, 0xF6, ++0xD1, 0xE7, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x17, 0x4B, 0x1A, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, ++0x44, 0x60, 0xBD, 0xE8, 0xF0, 0x87, 0x46, 0xF2, 0x65, 0x63, 0x9F, 0x42, 0x0A, 0xD9, 0xB7, 0xF5, 0x00, 0x4F, 0x0F, 0xD2, ++0x0F, 0x4B, 0xDA, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xD5, 0xE7, 0x0B, 0x4B, 0x9A, 0x78, ++0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xCD, 0xE7, 0x49, 0xF6, 0x98, 0x13, 0x9F, 0x42, 0x06, 0x4B, ++0x94, 0xBF, 0x1A, 0x79, 0x5A, 0x79, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xC0, 0xE7, 0x00, 0xBF, ++0xB0, 0xE2, 0x0D, 0x00, 0x54, 0x25, 0x17, 0x00, 0x90, 0x53, 0x03, 0x00, 0x10, 0x09, 0x05, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, ++0x8F, 0xB0, 0x00, 0xF1, 0x88, 0x09, 0x02, 0xAD, 0x01, 0x91, 0x04, 0x46, 0x4A, 0x46, 0x07, 0x46, 0x00, 0xF1, 0x90, 0x06, ++0x29, 0x46, 0x32, 0xF8, 0x02, 0x3B, 0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0xB2, 0x42, 0x5B, 0x89, 0x21, 0xF8, ++0x02, 0x3B, 0xF4, 0xD1, 0xB4, 0xF8, 0x92, 0x10, 0x71, 0xB1, 0xD4, 0xF8, 0x94, 0x20, 0xB4, 0xF8, 0x90, 0x30, 0x02, 0xEB, ++0x42, 0x02, 0x1B, 0x04, 0x93, 0xFB, 0xF1, 0xF3, 0x13, 0x44, 0xC3, 0xF3, 0x98, 0x03, 0x00, 0x22, 0xC4, 0xE9, 0x24, 0x23, ++0x04, 0xF1, 0x7C, 0x00, 0xFE, 0xF7, 0x2A, 0xF8, 0xB4, 0xF8, 0xB4, 0x00, 0x00, 0x21, 0xA4, 0xF8, 0x7C, 0x10, 0xA4, 0xF8, ++0x7E, 0x10, 0x84, 0xF8, 0x9A, 0x10, 0x00, 0x28, 0x74, 0xD0, 0x01, 0x38, 0x05, 0xAB, 0x80, 0xB2, 0x0D, 0xF1, 0x10, 0x0A, ++0x03, 0xEB, 0x80, 0x00, 0x52, 0x46, 0x23, 0x46, 0x4F, 0xF0, 0x01, 0x0C, 0x42, 0xF8, 0x04, 0x1B, 0x82, 0x42, 0x83, 0xF8, ++0x0E, 0xC0, 0x03, 0xF1, 0x0C, 0x03, 0xF7, 0xD1, 0xB4, 0xF8, 0xBA, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, 0x14, 0xD0, ++0x32, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x6C, 0x32, 0x98, 0x47, 0x39, 0xF8, 0x02, 0x3B, 0x35, 0xF8, 0x02, 0x2B, 0x03, 0xEB, ++0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0x93, 0x42, 0x47, 0xD1, 0xB1, 0x45, 0xF2, 0xD1, 0x0F, 0xB0, 0xBD, 0xE8, ++0xF0, 0x8F, 0x4F, 0xF0, 0x00, 0x08, 0x1F, 0xFA, 0x88, 0xFB, 0x0B, 0xEB, 0x4B, 0x00, 0x04, 0xEB, 0x80, 0x00, 0x04, 0x30, ++0xFD, 0xF7, 0xE6, 0xFF, 0x01, 0x22, 0x5F, 0xFA, 0x88, 0xF1, 0x20, 0x46, 0x90, 0x44, 0xFF, 0xF7, 0x09, 0xFF, 0xB4, 0xF8, ++0xB4, 0x10, 0x0E, 0xAB, 0x03, 0xEB, 0x8B, 0x0B, 0x1F, 0xFA, 0x88, 0xF2, 0x91, 0x42, 0x4B, 0xF8, 0x28, 0x0C, 0xE4, 0xD8, ++0x51, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0x26, 0xFE, 0x51, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0x72, 0xFE, 0x01, 0x9B, 0xCB, 0xB9, ++0x94, 0xF8, 0xA2, 0x20, 0xB4, 0xF8, 0xB4, 0x30, 0x42, 0xF0, 0x40, 0x02, 0x84, 0xF8, 0xA2, 0x20, 0x83, 0xB1, 0x01, 0x3B, ++0x9B, 0xB2, 0x03, 0xEB, 0x43, 0x02, 0xDD, 0xF8, 0x04, 0x80, 0x04, 0xF1, 0x0C, 0x03, 0x03, 0xEB, 0x82, 0x03, 0xA7, 0xF8, ++0x04, 0x80, 0xA7, 0xF8, 0x06, 0x80, 0x0C, 0x37, 0x9F, 0x42, 0xF8, 0xD1, 0x00, 0x20, 0xAC, 0xE7, 0x01, 0x20, 0x0F, 0xB0, ++0xBD, 0xE8, 0xF0, 0x8F, 0xB4, 0xF8, 0xBA, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, 0x9D, 0xD1, 0x0D, 0xF1, 0x10, 0x0A, ++0xCC, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x23, 0x4B, 0x23, 0x4A, 0x1B, 0x68, 0x4F, 0xF4, 0x1E, 0x71, ++0xB3, 0xF9, 0x00, 0x30, 0x01, 0xFB, 0x00, 0x20, 0x00, 0x2B, 0xD0, 0xF8, 0x4C, 0x41, 0x2F, 0xDB, 0x20, 0x46, 0xFF, 0xF7, ++0x5D, 0xF9, 0xB4, 0xF8, 0xB4, 0x30, 0x59, 0x1E, 0x9A, 0x1E, 0x21, 0xEA, 0xE1, 0x71, 0x03, 0x3B, 0x22, 0xEA, 0xE2, 0x72, ++0x23, 0xEA, 0xE3, 0x73, 0x00, 0x25, 0x4F, 0xF4, 0x80, 0x30, 0xA4, 0xF8, 0x88, 0x10, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xF8, ++0x8A, 0x20, 0xA4, 0xF8, 0x8C, 0x30, 0xC4, 0xF8, 0x94, 0x00, 0xA4, 0xF8, 0xBA, 0x10, 0xA4, 0xF8, 0x8E, 0x50, 0x84, 0xF8, ++0xA2, 0x50, 0x01, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x13, 0xFF, 0x94, 0xF8, 0xB4, 0x30, 0x84, 0xF8, 0x9B, 0x50, 0x04, 0x3B, ++0x05, 0x22, 0x84, 0xF8, 0xA0, 0x30, 0xA4, 0xF8, 0x98, 0x20, 0x38, 0xBD, 0x00, 0x2C, 0xCD, 0xD1, 0x05, 0x49, 0x06, 0x48, ++0x40, 0xF6, 0x76, 0x02, 0xF0, 0xF7, 0xDE, 0xFD, 0xC6, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xC4, 0xA3, 0x90, 0xF8, 0x23, 0x70, ++0xDA, 0xF8, 0x00, 0x30, 0xD0, 0xF8, 0x48, 0x81, 0xB3, 0xF9, 0x00, 0x30, 0x8B, 0xB0, 0x07, 0xF1, 0x10, 0x02, 0xD2, 0xB2, ++0x00, 0x2B, 0x04, 0x46, 0x06, 0x92, 0xC0, 0xF2, 0xA9, 0x81, 0xDA, 0x4D, 0x07, 0xEB, 0x47, 0x03, 0x05, 0xEB, 0x83, 0x1B, ++0xC4, 0xF8, 0x4C, 0xB1, 0x9B, 0x01, 0x04, 0x93, 0xCD, 0xF7, 0xB4, 0xF9, 0x83, 0x03, 0x05, 0x93, 0xCD, 0xF7, 0xB0, 0xF9, ++0x4F, 0xF0, 0x01, 0x09, 0x01, 0x30, 0x09, 0xFA, 0x00, 0xF9, 0x00, 0x21, 0x58, 0x46, 0xC0, 0x22, 0xCC, 0xF7, 0xBE, 0xF8, ++0x61, 0x68, 0x11, 0xF0, 0x02, 0x01, 0x09, 0xF1, 0xFF, 0x39, 0x00, 0xF0, 0x9D, 0x80, 0x00, 0x21, 0x04, 0xF1, 0xB8, 0x00, ++0xF3, 0xF7, 0xB4, 0xFB, 0x63, 0x68, 0xAB, 0xF8, 0xAA, 0x00, 0x98, 0x06, 0x4F, 0xEA, 0x47, 0x06, 0x00, 0xF1, 0x30, 0x82, ++0x58, 0x07, 0x40, 0xF1, 0xA3, 0x81, 0xC3, 0x4B, 0x07, 0x93, 0x04, 0x23, 0xB4, 0xF8, 0xEC, 0x00, 0x8B, 0xF8, 0xA5, 0x30, ++0xCD, 0xF8, 0x24, 0xB0, 0xF3, 0xF7, 0xBA, 0xFA, 0x07, 0x9A, 0x03, 0x46, 0x10, 0x8F, 0x08, 0x93, 0xF3, 0xF7, 0xB4, 0xFA, ++0x08, 0x9B, 0x09, 0x9A, 0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xB0, 0x00, 0xB3, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xC0, 0x83, 0x07, 0x9B, 0xB4, 0xF8, 0xEC, 0x00, 0x19, 0x8F, 0xF3, 0xF7, 0xCA, 0xFB, ++0xF2, 0x19, 0x05, 0xEB, 0x82, 0x12, 0x03, 0x46, 0xB4, 0xF8, 0xEC, 0x00, 0xA2, 0xF8, 0xA6, 0x30, 0x09, 0x92, 0xF3, 0xF7, ++0x7D, 0xFA, 0x07, 0x9A, 0x03, 0x46, 0x10, 0x8F, 0x08, 0x93, 0xF3, 0xF7, 0x77, 0xFA, 0x08, 0x9B, 0x09, 0x9A, 0x98, 0x42, ++0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xAC, 0x00, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, ++0x91, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0x20, 0xF4, 0x7F, 0x60, 0x80, 0xB2, ++0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x96, 0xFA, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, ++0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x6D, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, ++0xF3, 0xF7, 0x92, 0xFA, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x4E, 0x83, 0xB4, 0xF8, 0x54, 0x21, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, 0x83, 0xF8, ++0xB2, 0x20, 0xCD, 0xF7, 0xD1, 0xF8, 0x00, 0x28, 0x40, 0xF0, 0x04, 0x83, 0xD4, 0xF8, 0xE8, 0x30, 0x03, 0xF0, 0x03, 0x03, ++0x01, 0x2B, 0x00, 0xF0, 0xD4, 0x83, 0x02, 0x2B, 0x00, 0xF0, 0xD9, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x40, 0xF6, ++0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x88, 0xE1, 0x04, 0xF1, 0xB8, 0x00, 0xF3, 0xF7, 0x18, 0xFB, 0x07, 0xEB, 0x47, 0x03, ++0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x4D, 0xFA, 0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, ++0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x4F, 0xEA, 0x47, 0x06, 0xC0, 0xF2, 0xBC, 0x80, 0xF3, 0x19, ++0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x47, 0xFA, 0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, ++0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9E, 0x80, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, ++0xFF, 0x21, 0x83, 0xF8, 0xAC, 0x10, 0x94, 0xF8, 0x2D, 0x11, 0x83, 0xF8, 0xAF, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x83, 0x80, 0xB4, 0xF8, 0x54, 0x11, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC1, 0xF3, 0x80, 0x21, 0x83, 0xF8, ++0xB2, 0x10, 0x58, 0x46, 0x07, 0x92, 0xFE, 0xF7, 0x71, 0xFF, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x07, 0x9A, 0xA3, 0xF8, ++0xB4, 0x00, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x8D, 0x80, 0x3E, 0x44, 0x05, 0xEB, 0x86, 0x1A, 0x94, 0xF8, ++0x23, 0x30, 0x9A, 0xF8, 0xAF, 0x70, 0x9A, 0xF8, 0xB1, 0x00, 0x9A, 0xF8, 0xB2, 0x10, 0x9A, 0xF8, 0xA5, 0x20, 0xCD, 0xE9, ++0x02, 0x07, 0xCD, 0xE9, 0x00, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0x4B, 0x4A, 0x4B, 0x49, 0xF0, 0xF7, 0x6F, 0xFA, 0xBA, 0xF8, ++0xB4, 0x00, 0x9A, 0xF8, 0xAE, 0x10, 0x9A, 0xF8, 0xAD, 0x20, 0x9A, 0xF8, 0xAC, 0x30, 0xCD, 0xE9, 0x02, 0x10, 0xCD, 0xE9, ++0x00, 0x32, 0x45, 0x49, 0x42, 0x4A, 0x9A, 0xF8, 0xB0, 0x30, 0x4F, 0xF4, 0x80, 0x50, 0xF0, 0xF7, 0x5B, 0xFA, 0x94, 0xF8, ++0x23, 0x00, 0xFF, 0xF7, 0x5D, 0xFE, 0x04, 0x99, 0x88, 0x31, 0xB0, 0x01, 0x29, 0x44, 0x08, 0xF1, 0x14, 0x02, 0x08, 0xF1, ++0x24, 0x07, 0x31, 0xF8, 0x02, 0x3B, 0xDB, 0xB2, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x2B, 0x44, 0x5B, 0x89, ++0x43, 0xF0, 0x80, 0x43, 0x42, 0xF8, 0x04, 0x3B, 0x97, 0x42, 0xF0, 0xD1, 0x58, 0x46, 0x00, 0x21, 0xFF, 0xF7, 0xB4, 0xF8, ++0x32, 0x4A, 0x06, 0x99, 0x12, 0x69, 0xD4, 0xF8, 0x48, 0x31, 0x31, 0x4F, 0x31, 0x48, 0xB6, 0x01, 0x89, 0x02, 0xAA, 0x51, ++0xA2, 0x69, 0x05, 0x9D, 0xC8, 0xF8, 0x0C, 0x10, 0x4F, 0xF4, 0x08, 0x51, 0xC8, 0xE9, 0x01, 0x59, 0xC8, 0xF8, 0x00, 0x70, ++0xC8, 0xF8, 0x10, 0x00, 0xC3, 0xE9, 0x0D, 0x12, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x11, 0x03, 0x84, 0xF8, 0x56, 0x31, ++0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x29, 0x3F, 0xF4, 0x7A, 0xAF, 0x40, 0xF6, 0x21, 0x42, 0x22, 0x49, 0x23, 0x48, ++0xF0, 0xF7, 0x3C, 0xFC, 0xDA, 0xF8, 0x00, 0x20, 0x70, 0xE7, 0x0B, 0x28, 0x7F, 0xF6, 0x5F, 0xAF, 0x40, 0xF6, 0x1E, 0x42, ++0x1C, 0x49, 0x1E, 0x48, 0xF0, 0xF7, 0x30, 0xFC, 0xDA, 0xF8, 0x00, 0x20, 0x55, 0xE7, 0x0B, 0x28, 0x7F, 0xF6, 0x41, 0xAF, ++0x17, 0x49, 0x1A, 0x48, 0x40, 0xF6, 0x1C, 0x42, 0xF0, 0xF7, 0x24, 0xFC, 0x39, 0xE7, 0x00, 0x28, 0x00, 0xF0, 0xFE, 0x81, ++0x0A, 0x28, 0x7F, 0xF6, 0x6D, 0xAF, 0x11, 0x49, 0x14, 0x48, 0x40, 0xF6, 0x28, 0x42, 0xF0, 0xF7, 0x17, 0xFC, 0x65, 0xE7, ++0x09, 0x2F, 0x7F, 0xF6, 0x54, 0xAE, 0x0C, 0x49, 0x10, 0x48, 0x40, 0xF6, 0xEB, 0x22, 0xF0, 0xF7, 0x0D, 0xFC, 0x94, 0xF8, ++0x23, 0x70, 0x4A, 0xE6, 0xF4, 0xE7, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x4C, 0xCC, 0x15, 0x00, 0xC4, 0xCB, 0x15, 0x00, ++0x08, 0xCC, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1E, 0xAB, 0xDC, 0xBA, 0x04, 0x07, 0xFF, 0xFF, 0x70, 0x79, 0x15, 0x00, ++0xA8, 0xCB, 0x15, 0x00, 0x84, 0xCB, 0x15, 0x00, 0x60, 0xCB, 0x15, 0x00, 0x0C, 0xCA, 0x15, 0x00, 0x64, 0xCA, 0x15, 0x00, ++0x38, 0x36, 0x17, 0x00, 0x04, 0xF1, 0xCB, 0x03, 0x02, 0x21, 0x18, 0x46, 0x8B, 0xF8, 0xA5, 0x10, 0x09, 0x93, 0xCD, 0xF8, ++0x20, 0xB0, 0xF3, 0xF7, 0x2B, 0xF9, 0x01, 0x46, 0xD9, 0x48, 0x07, 0x91, 0xF3, 0xF7, 0x26, 0xF9, 0x07, 0x99, 0x08, 0x9A, ++0x09, 0x9B, 0x88, 0x42, 0x28, 0xBF, 0x08, 0x46, 0xDA, 0xF8, 0x00, 0x10, 0x82, 0xF8, 0xB0, 0x00, 0xB1, 0xF9, 0x00, 0x20, ++0x00, 0x2A, 0xC0, 0xF2, 0x41, 0x82, 0x04, 0x9A, 0x02, 0xF1, 0xA6, 0x00, 0x19, 0x46, 0x04, 0x22, 0x28, 0x44, 0x02, 0xF0, ++0x6B, 0xFE, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xFF, 0x22, 0xB3, 0xF8, 0xAA, 0x00, 0x83, 0xF8, 0xA6, 0x20, 0x20, 0xF4, ++0x7F, 0x60, 0x07, 0x22, 0x80, 0xB2, 0x83, 0xF8, 0xAC, 0x20, 0xA3, 0xF8, 0xAA, 0x00, 0x07, 0x93, 0xF3, 0xF7, 0x0A, 0xF9, ++0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x0F, 0x82, ++0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x06, 0xF9, 0x07, 0x9B, 0xDA, 0xF8, ++0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xF0, 0x81, 0xB4, 0xF8, 0x54, 0x21, ++0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, 0x83, 0xF8, 0xB2, 0x20, 0xCC, 0xF7, 0x45, 0xFF, 0x00, 0x28, ++0x40, 0xF0, 0x88, 0x81, 0xB4, 0xF8, 0xC8, 0x30, 0x13, 0xF4, 0x00, 0x6F, 0x06, 0xEB, 0x07, 0x03, 0x05, 0xEB, 0x83, 0x13, ++0x14, 0xBF, 0x40, 0xF6, 0xB5, 0x72, 0x40, 0xF6, 0xFF, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0xF1, 0x19, 0x05, 0xEB, 0x81, 0x11, ++0x94, 0xF8, 0x2D, 0x31, 0xDA, 0xF8, 0x00, 0x20, 0x81, 0xF8, 0xAF, 0x30, 0xB2, 0xF9, 0x00, 0x10, 0x00, 0x29, 0xC0, 0xF2, ++0x31, 0x81, 0x03, 0x2B, 0x3F, 0xF6, 0xA9, 0xAE, 0xDF, 0xE8, 0x13, 0xF0, 0x26, 0x01, 0x20, 0x01, 0x15, 0x01, 0x04, 0x01, ++0x05, 0x23, 0x94, 0xF8, 0x22, 0x10, 0xB4, 0xF8, 0x06, 0x01, 0x8B, 0xF8, 0xA5, 0x30, 0x07, 0x91, 0xCD, 0xF8, 0x24, 0xB0, ++0xF3, 0xF7, 0x8C, 0xF8, 0x95, 0x4A, 0x03, 0x46, 0xB2, 0xF8, 0x50, 0x00, 0x08, 0x93, 0xF3, 0xF7, 0x85, 0xF8, 0x08, 0x9B, ++0x09, 0x9A, 0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xB0, 0x00, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC0, 0xF2, 0xE5, 0x81, 0x8B, 0x4B, 0xB4, 0xF8, 0x06, 0x01, 0xB3, 0xF8, 0x50, 0x10, 0xF3, 0xF7, 0x9A, 0xF9, ++0xF2, 0x19, 0x05, 0xEB, 0x82, 0x12, 0x03, 0x46, 0xB4, 0xF8, 0x06, 0x01, 0xA2, 0xF8, 0xA6, 0x30, 0x09, 0x92, 0xF3, 0xF7, ++0x59, 0xF8, 0x82, 0x4A, 0x03, 0x46, 0xB2, 0xF8, 0x50, 0x00, 0x08, 0x93, 0xF3, 0xF7, 0x52, 0xF8, 0x08, 0x9B, 0x09, 0x9A, ++0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xAC, 0x00, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0xB4, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0x20, 0xF4, 0x7F, 0x60, ++0x80, 0xB2, 0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x65, 0xF8, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, ++0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x90, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, ++0xAA, 0x00, 0xF3, 0xF7, 0x61, 0xF8, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0xC0, 0xF2, 0x71, 0x81, 0xB4, 0xF8, 0x54, 0x21, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, ++0x83, 0xF8, 0xB2, 0x20, 0xCC, 0xF7, 0xA0, 0xFE, 0x28, 0xB1, 0x5D, 0x4B, 0x93, 0xF8, 0x43, 0x30, 0x99, 0x06, 0x00, 0xF1, ++0x99, 0x81, 0x63, 0x68, 0x5B, 0x07, 0x40, 0xF1, 0xEB, 0x80, 0xD4, 0xF8, 0xE8, 0x30, 0x03, 0xF0, 0x03, 0x03, 0x01, 0x2B, ++0x00, 0xF0, 0xBD, 0x81, 0x02, 0x2B, 0x00, 0xF0, 0xB2, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x40, 0xF6, 0xED, 0x62, ++0xA3, 0xF8, 0xB6, 0x20, 0x50, 0x4B, 0x07, 0x99, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x33, 0x93, 0xF8, 0x62, 0x20, ++0x00, 0x2A, 0x40, 0xF0, 0xDF, 0x80, 0xD3, 0xF8, 0xC8, 0x31, 0xD4, 0xF8, 0x48, 0x01, 0x13, 0xF4, 0x80, 0x3F, 0xC1, 0x6B, ++0x40, 0xF0, 0x69, 0x81, 0x41, 0xF0, 0x20, 0x01, 0x00, 0x2B, 0xC1, 0x63, 0x06, 0xDB, 0xC3, 0xF3, 0x05, 0x63, 0x49, 0xEA, ++0x03, 0x59, 0x02, 0x2A, 0x00, 0xF0, 0x58, 0x81, 0x49, 0xF0, 0x80, 0x59, 0x49, 0xF4, 0xC0, 0x29, 0x3D, 0x4B, 0x93, 0xF8, ++0x45, 0x10, 0x94, 0xF8, 0xFD, 0x30, 0x01, 0xF0, 0x03, 0x00, 0xC3, 0xF3, 0xC1, 0x03, 0x83, 0x42, 0x06, 0xEB, 0x07, 0x02, ++0x28, 0xBF, 0x03, 0x46, 0x05, 0xEB, 0x82, 0x12, 0x01, 0x20, 0x83, 0x42, 0x82, 0xF8, 0xBC, 0x00, 0x00, 0xF0, 0x6A, 0x81, ++0x02, 0x2B, 0x00, 0xF0, 0x64, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0x68, 0x81, 0x04, 0x23, 0x82, 0xF8, 0xBD, 0x30, 0x2E, 0x4B, ++0x94, 0xF8, 0xFD, 0xC0, 0x93, 0xF8, 0x4B, 0x00, 0x93, 0xF8, 0x4A, 0x20, 0x8B, 0x08, 0xF1, 0x19, 0x03, 0xEA, 0x5C, 0x13, ++0x05, 0xEB, 0x81, 0x11, 0x03, 0xF0, 0x01, 0x03, 0x81, 0xF8, 0xBE, 0x30, 0x94, 0xF8, 0x03, 0xC1, 0x94, 0xF8, 0x02, 0x31, ++0x0C, 0xF0, 0x01, 0x0C, 0x9B, 0x11, 0x00, 0xF0, 0x01, 0x00, 0x92, 0x11, 0x43, 0xEA, 0x8C, 0x03, 0x42, 0xEA, 0x80, 0x02, ++0x93, 0x42, 0x28, 0xBF, 0x13, 0x46, 0x81, 0xF8, 0xBF, 0x30, 0xE8, 0xE6, 0xD4, 0xF8, 0xE8, 0x30, 0x59, 0x06, 0x7F, 0xF5, ++0x9E, 0xAD, 0x19, 0x4B, 0x9B, 0x89, 0x5B, 0x06, 0x7F, 0xF5, 0x99, 0xAD, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x01, 0x21, ++0x83, 0xF8, 0xB1, 0x10, 0x91, 0xE5, 0xD4, 0xF8, 0xE8, 0x30, 0x9B, 0x06, 0x7F, 0xF5, 0x8D, 0xAD, 0x10, 0x4B, 0x9B, 0x89, ++0x98, 0x06, 0x7F, 0xF5, 0x88, 0xAD, 0xED, 0xE7, 0xB4, 0xF8, 0xC8, 0x30, 0x59, 0x06, 0x7F, 0xF5, 0x82, 0xAD, 0xE2, 0xE7, ++0xB4, 0xF8, 0xC8, 0x30, 0x98, 0x06, 0x7F, 0xF5, 0x7C, 0xAD, 0xED, 0xE7, 0x03, 0x2B, 0x7F, 0xF6, 0xCC, 0xAE, 0x40, 0xF6, ++0xF9, 0x32, 0x07, 0x49, 0x07, 0x48, 0xF0, 0xF7, 0x31, 0xFA, 0x94, 0xF8, 0x2D, 0x31, 0xDA, 0xF8, 0x00, 0x20, 0xC0, 0xE6, ++0xF3, 0xB8, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x34, 0xCA, 0x15, 0x00, ++0x40, 0xF6, 0x27, 0x42, 0x88, 0x49, 0x89, 0x48, 0x07, 0x93, 0xF0, 0xF7, 0x1B, 0xFA, 0xDA, 0xF8, 0x00, 0x20, 0xB2, 0xF9, ++0x00, 0x20, 0x00, 0x2A, 0xBF, 0xF6, 0x64, 0xAD, 0x07, 0x9B, 0xB3, 0xF8, 0xB4, 0x00, 0xEF, 0xE5, 0x07, 0x9B, 0x1B, 0x6B, ++0x13, 0xF0, 0x10, 0x0F, 0xD4, 0xF8, 0xE8, 0x30, 0x3F, 0xF4, 0xF6, 0xAC, 0xD9, 0x06, 0x7F, 0xF5, 0xF3, 0xAC, 0x05, 0x9A, ++0x42, 0xF0, 0x40, 0x02, 0x05, 0x92, 0xED, 0xE4, 0x7A, 0x4B, 0x9B, 0x89, 0x13, 0xF0, 0x01, 0x0F, 0xB4, 0xF8, 0xC8, 0x30, ++0x3F, 0xF4, 0x72, 0xAE, 0xDA, 0x07, 0x7F, 0xF5, 0x6F, 0xAE, 0x05, 0x9A, 0x42, 0xF0, 0x40, 0x02, 0x05, 0x92, 0x69, 0xE6, ++0xB4, 0xF8, 0xC8, 0x30, 0x13, 0xF4, 0x00, 0x6F, 0x06, 0xEB, 0x07, 0x03, 0x05, 0xEB, 0x83, 0x13, 0x14, 0xBF, 0x41, 0xF6, ++0xFF, 0x62, 0x40, 0xF6, 0xFF, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x15, 0xE7, 0xD4, 0xF8, 0x48, 0x01, 0xD3, 0xF8, 0xC8, 0x31, ++0xC1, 0x6B, 0x00, 0x2B, 0x21, 0xF0, 0x20, 0x01, 0xC1, 0x63, 0xBF, 0xF6, 0x24, 0xAF, 0x26, 0xE7, 0x03, 0x28, 0x7F, 0xF6, ++0xAF, 0xAC, 0x0C, 0x28, 0x3F, 0xF4, 0xAC, 0xAC, 0x5F, 0x49, 0x62, 0x48, 0x40, 0xF6, 0xA2, 0x32, 0xF0, 0xF7, 0xC8, 0xF9, ++0xA4, 0xE4, 0x03, 0x28, 0x7F, 0xF6, 0x90, 0xAC, 0x0C, 0x28, 0x3F, 0xF4, 0x8D, 0xAC, 0x59, 0x49, 0x5C, 0x48, 0x4F, 0xF4, ++0x3A, 0x62, 0xF0, 0xF7, 0xBB, 0xF9, 0x85, 0xE4, 0x09, 0x28, 0x7F, 0xF6, 0x6C, 0xAC, 0x54, 0x49, 0x58, 0x48, 0x40, 0xF6, ++0x94, 0x32, 0xF0, 0xF7, 0xB1, 0xF9, 0x64, 0xE4, 0x07, 0x28, 0x7F, 0xF6, 0x3D, 0xAC, 0x4F, 0x49, 0x54, 0x48, 0x40, 0xF6, ++0x8E, 0x32, 0xF0, 0xF7, 0xA7, 0xF9, 0x35, 0xE4, 0x03, 0x28, 0x7F, 0xF6, 0x0D, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, 0x0A, 0xAE, ++0x48, 0x49, 0x4B, 0x48, 0x40, 0xF6, 0xD9, 0x32, 0xF0, 0xF7, 0x9A, 0xF9, 0x02, 0xE6, 0x03, 0x28, 0x7F, 0xF6, 0xEE, 0xAD, ++0x0C, 0x28, 0x3F, 0xF4, 0xEB, 0xAD, 0x42, 0x49, 0x45, 0x48, 0x40, 0xF6, 0xD7, 0x32, 0xF0, 0xF7, 0x8D, 0xF9, 0xE3, 0xE5, ++0x03, 0x28, 0x7F, 0xF6, 0xBC, 0xAD, 0x3D, 0x49, 0x43, 0x48, 0x07, 0x93, 0x40, 0xF6, 0xCC, 0x32, 0xF0, 0xF7, 0x82, 0xF9, ++0x07, 0x9B, 0xB2, 0xE5, 0x03, 0x28, 0x7F, 0xF6, 0x8C, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, 0x89, 0xAE, 0x35, 0x49, 0x38, 0x48, ++0x40, 0xF6, 0x22, 0x32, 0xF0, 0xF7, 0x74, 0xF9, 0x81, 0xE6, 0x03, 0x28, 0x7F, 0xF6, 0x6D, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, ++0x6A, 0xAE, 0x2F, 0x49, 0x32, 0x48, 0x4F, 0xF4, 0x32, 0x62, 0xF0, 0xF7, 0x67, 0xF9, 0x62, 0xE6, 0x0B, 0x28, 0x7F, 0xF6, ++0x49, 0xAE, 0x2A, 0x49, 0x31, 0x48, 0x40, 0xF6, 0x1C, 0x32, 0xF0, 0xF7, 0x5D, 0xF9, 0x41, 0xE6, 0x07, 0x28, 0x7F, 0xF6, ++0x18, 0xAE, 0x25, 0x49, 0x2A, 0x48, 0x40, 0xF6, 0x16, 0x32, 0xF0, 0xF7, 0x53, 0xF9, 0x10, 0xE6, 0x49, 0xF0, 0x80, 0x59, ++0x49, 0xF4, 0x00, 0x39, 0xA6, 0xE6, 0x21, 0xF0, 0x20, 0x01, 0x00, 0x2B, 0xC1, 0x63, 0xBF, 0xF6, 0x96, 0xAE, 0x9B, 0xE6, ++0x94, 0xF8, 0x2D, 0x31, 0x23, 0xB9, 0x94, 0xF8, 0xFB, 0x30, 0x9A, 0x06, 0x7F, 0xF5, 0x5F, 0xAE, 0x05, 0x9B, 0x43, 0xF0, ++0x40, 0x03, 0x05, 0x93, 0x59, 0xE6, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x41, 0xF6, 0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, ++0xB7, 0xE5, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x42, 0xF6, 0x74, 0x42, 0xA3, 0xF8, 0xB6, 0x20, 0xAF, 0xE5, 0x82, 0xF8, ++0xBD, 0x00, 0x9E, 0xE6, 0x00, 0x23, 0x82, 0xF8, 0xBD, 0x30, 0x9A, 0xE6, 0x82, 0xF8, 0xBC, 0x30, 0xA5, 0xE5, 0xF3, 0x19, ++0x05, 0xEB, 0x83, 0x13, 0x42, 0xF6, 0x74, 0x42, 0xA3, 0xF8, 0xB6, 0x20, 0x4C, 0xE6, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, ++0x41, 0xF6, 0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x44, 0xE6, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0xF4, 0xC9, 0x15, 0x00, ++0xE4, 0xB8, 0x17, 0x00, 0xE8, 0xCA, 0x15, 0x00, 0x98, 0xCA, 0x15, 0x00, 0x38, 0xCB, 0x15, 0x00, 0x50, 0xCA, 0x15, 0x00, ++0x4C, 0xCB, 0x15, 0x00, 0x84, 0xCA, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x46, 0x7F, 0x09, 0x2E, 0x83, 0xB0, 0x04, 0x46, ++0x00, 0xF2, 0x8D, 0x80, 0x4B, 0x4B, 0x4C, 0x4F, 0x1A, 0x68, 0x4F, 0xF4, 0x1E, 0x73, 0xB2, 0xF9, 0x00, 0x20, 0x03, 0xFB, ++0x06, 0x73, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x40, 0xDB, 0x95, 0xF8, 0xA2, 0x30, 0x59, 0x07, 0x34, 0xD4, 0x03, 0xF0, ++0xFD, 0x03, 0x4F, 0xF0, 0x00, 0x08, 0xDF, 0xF8, 0x18, 0x91, 0x85, 0xF8, 0xA2, 0x30, 0xD9, 0xF8, 0x10, 0x30, 0x2A, 0x68, ++0x3F, 0x49, 0x9B, 0x1A, 0x8B, 0x42, 0x36, 0xD8, 0x95, 0xF8, 0xA3, 0x20, 0x95, 0xF8, 0xA4, 0x30, 0x43, 0xEA, 0x82, 0x03, ++0x84, 0xF8, 0x36, 0x30, 0x28, 0x46, 0xFE, 0xF7, 0x65, 0xFF, 0xB0, 0xB1, 0xE2, 0x8B, 0x94, 0xF8, 0x36, 0x30, 0x42, 0xF4, ++0x00, 0x52, 0x23, 0xF0, 0x03, 0x03, 0xE2, 0x83, 0x84, 0xF8, 0x36, 0x30, 0xB8, 0xF1, 0x00, 0x0F, 0x59, 0xD1, 0x4F, 0xF4, ++0x1E, 0x73, 0x03, 0xFB, 0x06, 0x76, 0x96, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x20, 0x03, 0x86, 0xF8, 0x56, 0x31, 0x03, 0xB0, ++0xBD, 0xE8, 0xF0, 0x83, 0x62, 0x6A, 0x92, 0x02, 0xC7, 0xD5, 0x43, 0xF0, 0x02, 0x03, 0x4F, 0xF0, 0x01, 0x08, 0xC6, 0xE7, ++0x00, 0x2D, 0xBC, 0xD1, 0x26, 0x49, 0x27, 0x48, 0x40, 0xF6, 0x9A, 0x22, 0xF0, 0xF7, 0x9E, 0xF8, 0xB5, 0xE7, 0x00, 0x21, ++0x28, 0x46, 0xFF, 0xF7, 0xBB, 0xF9, 0x95, 0xF8, 0xA3, 0x30, 0x01, 0x33, 0x00, 0x22, 0x03, 0xF0, 0x07, 0x03, 0x85, 0xF8, ++0xA3, 0x30, 0x85, 0xF8, 0x9B, 0x20, 0x85, 0xF8, 0xA4, 0x20, 0xD9, 0xF8, 0x10, 0x20, 0x2A, 0x60, 0x9B, 0x00, 0x84, 0xF8, ++0x36, 0x30, 0x00, 0x28, 0xB8, 0xD0, 0x0D, 0xF1, 0x07, 0x01, 0x28, 0x46, 0xFE, 0xF7, 0xCE, 0xFC, 0x9D, 0xF8, 0x07, 0x30, ++0x53, 0xB9, 0x62, 0x6A, 0x22, 0xF4, 0x00, 0x12, 0x62, 0x62, 0x95, 0xF8, 0xA2, 0x20, 0x22, 0xF0, 0x02, 0x02, 0x98, 0x46, ++0x85, 0xF8, 0xA2, 0x20, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0x73, 0x93, 0xF8, 0x56, 0x21, 0x42, 0xF0, 0x11, 0x02, ++0x83, 0xF8, 0x56, 0x21, 0x9A, 0xE7, 0x00, 0x23, 0x80, 0xF8, 0x36, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x63, 0x6A, ++0x43, 0xF4, 0x20, 0x13, 0x63, 0x62, 0xA0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xA0, 0x86, 0x01, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0xB4, 0xCA, 0x0A, 0x12, 0xF0, 0x06, 0x0F, ++0x9D, 0xF8, 0x08, 0x50, 0x9D, 0xF8, 0x14, 0x40, 0x20, 0xD0, 0x02, 0xF0, 0x07, 0x02, 0x01, 0xF0, 0x7F, 0x01, 0x04, 0x2A, ++0x0C, 0xBF, 0x09, 0x09, 0xC1, 0xF3, 0xC1, 0x01, 0x4B, 0xB9, 0xC3, 0x6B, 0x23, 0xF0, 0x04, 0x03, 0xC3, 0x63, 0x64, 0xB1, ++0x43, 0xF0, 0x10, 0x03, 0x30, 0xBC, 0xC3, 0x63, 0x70, 0x47, 0xA9, 0x42, 0xF3, 0xD1, 0xC3, 0x6B, 0x43, 0xF0, 0x04, 0x03, ++0xC3, 0x63, 0x00, 0x2C, 0xF2, 0xD1, 0x23, 0xF0, 0x10, 0x03, 0x30, 0xBC, 0xC3, 0x63, 0x70, 0x47, 0xC3, 0x6B, 0x23, 0xF0, ++0x10, 0x03, 0xF8, 0xE7, 0x0B, 0x7B, 0x05, 0x2B, 0x0E, 0xD1, 0x2D, 0xE9, 0xF0, 0x41, 0x4B, 0x7B, 0x84, 0xB0, 0x0C, 0x46, ++0x01, 0xF1, 0x0C, 0x07, 0x13, 0xB9, 0x0D, 0x88, 0x09, 0x2D, 0x05, 0xDC, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, ++0x00, 0x20, 0x70, 0x47, 0x0B, 0x20, 0x97, 0xF8, 0x02, 0x80, 0x7E, 0x7A, 0xEE, 0xF7, 0xC8, 0xF9, 0x08, 0xBB, 0xFB, 0x78, ++0x3B, 0xBB, 0x69, 0x1F, 0x04, 0xF1, 0x11, 0x00, 0x1D, 0x46, 0x01, 0x22, 0x07, 0x78, 0x43, 0x78, 0x26, 0x2F, 0x03, 0xF1, ++0x02, 0x03, 0x14, 0xD1, 0x8B, 0x42, 0xA1, 0xEB, 0x03, 0x01, 0x10, 0xDC, 0x05, 0xB9, 0x03, 0x90, 0x02, 0x29, 0x18, 0x44, ++0x4F, 0xF0, 0x01, 0x05, 0xEE, 0xDC, 0x00, 0x92, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x03, 0xAB, 0x00, 0xF0, 0x1A, 0xFD, ++0x01, 0xF0, 0x52, 0xF8, 0xD0, 0xE7, 0x00, 0x96, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x04, 0x23, 0x00, 0xF0, 0xF4, 0xFC, ++0xC8, 0xE7, 0x00, 0x96, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x02, 0x23, 0x00, 0xF0, 0xEC, 0xFC, 0xC0, 0xE7, 0x00, 0xBF, ++0x08, 0xB5, 0x0B, 0x20, 0xEE, 0xF7, 0x90, 0xF9, 0x01, 0x28, 0x07, 0xD0, 0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, ++0x00, 0x2B, 0x05, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x01, 0xF0, 0xEA, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x04, 0x49, 0x05, 0x48, ++0x9D, 0x22, 0xEF, 0xF7, 0xD5, 0xFF, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0x08, 0xB5, 0x0B, 0x20, 0xEE, 0xF7, 0x70, 0xF9, 0x04, 0x28, 0x07, 0xD0, 0x09, 0x4B, 0x1B, 0x68, ++0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x01, 0xF0, 0x3E, 0xF8, 0x00, 0x20, 0x08, 0xBD, ++0x04, 0x49, 0x05, 0x48, 0x81, 0x22, 0xEF, 0xF7, 0xB5, 0xFF, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x3A, 0xB3, 0x93, 0x68, 0x10, 0xB4, 0x93, 0xB9, 0x54, 0x69, 0x64, 0xB1, ++0xFF, 0x28, 0x22, 0xD1, 0x00, 0x2C, 0x1A, 0xDD, 0x18, 0x32, 0x10, 0x19, 0x01, 0xE0, 0x82, 0x42, 0x15, 0xD0, 0x12, 0xF8, ++0x01, 0x3B, 0x99, 0x42, 0xF9, 0xD1, 0x01, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xFF, 0x28, 0x13, 0xD0, 0x00, 0x2B, ++0x09, 0xDD, 0x0C, 0x32, 0x13, 0x44, 0x01, 0xE0, 0x9A, 0x42, 0x04, 0xD0, 0x12, 0xF8, 0x01, 0x1B, 0x81, 0x42, 0xF9, 0xD1, ++0xED, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x18, 0x46, 0xE6, 0xE7, 0x54, 0x69, ++0xD8, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x0A, 0x4D, 0x41, 0xF2, 0x98, 0x74, 0x2B, 0x59, 0x63, 0xB1, 0x0B, 0x20, 0xEE, 0xF7, ++0x1B, 0xF9, 0x03, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x38, 0xBD, 0x2B, 0x59, 0x18, 0x68, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, ++0x38, 0xBD, 0x01, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x78, 0xEF, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0x46, 0x80, 0x6C, ++0x89, 0xB0, 0x14, 0x46, 0x99, 0x46, 0x00, 0xF1, 0x68, 0x05, 0x00, 0x29, 0x3B, 0xD1, 0xB0, 0xF8, 0x68, 0x10, 0xBE, 0x4A, ++0xB2, 0xF8, 0xFC, 0x31, 0x01, 0x33, 0x9B, 0xB2, 0x1E, 0x01, 0xA2, 0xF8, 0xFC, 0x31, 0xA0, 0xF8, 0x7E, 0x60, 0x05, 0x22, ++0x58, 0x46, 0xFC, 0xF7, 0x53, 0xFA, 0x01, 0x28, 0x00, 0xF0, 0xC8, 0x80, 0x1B, 0x23, 0x03, 0x93, 0x18, 0x23, 0xE9, 0x18, ++0x05, 0x22, 0xEA, 0x54, 0x01, 0x22, 0x4A, 0x70, 0x99, 0xF8, 0x00, 0x20, 0x8A, 0x70, 0x01, 0xF1, 0x03, 0x0A, 0x00, 0x2C, ++0x7B, 0xD0, 0x03, 0x22, 0x27, 0x20, 0xC8, 0x70, 0x0A, 0x71, 0x99, 0xF8, 0x01, 0x20, 0x4A, 0x71, 0x8C, 0x71, 0x99, 0xF8, ++0x02, 0x20, 0xCA, 0x71, 0x08, 0x33, 0xDB, 0xF8, 0x4C, 0x00, 0x9B, 0xF8, 0x35, 0x20, 0x41, 0x6A, 0x13, 0x44, 0x01, 0x39, ++0x19, 0x44, 0x04, 0x33, 0xC0, 0xE9, 0x0A, 0x13, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA2, 0x4B, 0xA2, 0x4E, 0x00, 0x22, ++0x41, 0xF2, 0xA8, 0x7C, 0x6F, 0xF0, 0x2F, 0x01, 0x80, 0xF8, 0x69, 0x20, 0x80, 0xF8, 0x6A, 0x20, 0x80, 0xF8, 0x6B, 0x20, ++0x80, 0xF8, 0x68, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x9B, 0x4A, 0x4F, 0xF4, 0x1E, 0x77, 0x07, 0xFB, 0x01, 0xF1, 0x41, 0xF2, ++0xA9, 0x78, 0x89, 0x5B, 0xA0, 0xF8, 0x6C, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x07, 0xFB, 0x01, 0x61, 0x4F, 0xF4, 0xA4, 0x6E, ++0x49, 0x88, 0xA0, 0xF8, 0x6E, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x07, 0xFB, 0x01, 0x61, 0x89, 0x88, 0xA0, 0xF8, 0x70, 0x10, ++0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0xF1, 0x89, 0x5A, 0xA0, 0xF8, 0x72, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, ++0x01, 0x21, 0x49, 0x88, 0xA0, 0xF8, 0x74, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0x21, 0x89, 0x88, 0xA0, 0xF8, ++0x76, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0xF1, 0x02, 0xEB, 0x01, 0x0A, 0x9A, 0xF8, 0x06, 0xA0, 0xBA, 0xF1, ++0x02, 0x0F, 0x5F, 0xD0, 0x13, 0xF8, 0x0C, 0x20, 0x07, 0xFB, 0x02, 0xF2, 0xD0, 0x21, 0x92, 0x5B, 0xA0, 0xF8, 0x78, 0x20, ++0x13, 0xF8, 0x0C, 0x20, 0x07, 0xFB, 0x02, 0x62, 0x52, 0x88, 0xA0, 0xF8, 0x7A, 0x20, 0x13, 0xF8, 0x0C, 0x30, 0x07, 0xFB, ++0x03, 0x66, 0xB3, 0x88, 0xA0, 0xF8, 0x7C, 0x30, 0x63, 0xE7, 0x03, 0x9B, 0x01, 0x94, 0xC3, 0xF5, 0xC0, 0x73, 0x9B, 0xB2, ++0x02, 0x93, 0xCD, 0xF8, 0x14, 0xB0, 0x99, 0xF8, 0x02, 0x30, 0x02, 0x9A, 0x05, 0x2B, 0xA2, 0xF1, 0x05, 0x04, 0xA4, 0xB2, ++0x00, 0xF0, 0xE2, 0x80, 0x27, 0x23, 0x8A, 0xF8, 0x00, 0x30, 0x99, 0xF8, 0x01, 0x30, 0x8A, 0xF8, 0x02, 0x30, 0x00, 0x23, ++0x8A, 0xF8, 0x03, 0x30, 0x99, 0xF8, 0x02, 0x30, 0x8A, 0xF8, 0x04, 0x30, 0x05, 0x2B, 0x3A, 0xD0, 0x03, 0x23, 0x8A, 0xF8, ++0x01, 0x30, 0x02, 0x94, 0x0A, 0xF1, 0x05, 0x0A, 0x05, 0x25, 0xFF, 0xF7, 0x15, 0xFF, 0x01, 0x9B, 0x2B, 0x44, 0x01, 0x93, ++0x08, 0xB9, 0x04, 0x2C, 0xD7, 0xD8, 0x5C, 0x4B, 0xDD, 0xF8, 0x14, 0xB0, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xC0, 0xF2, 0x9D, 0x80, 0x01, 0x9B, 0x03, 0x9A, 0x13, 0x44, 0x52, 0xE7, 0x18, 0x22, 0x29, 0x46, 0x58, 0x46, 0xFA, 0xF7, ++0xE7, 0xFF, 0x9B, 0xF8, 0x33, 0x20, 0x02, 0xF1, 0x18, 0x03, 0x1B, 0x32, 0x03, 0x92, 0x2E, 0xE7, 0x89, 0x5A, 0xA0, 0xF8, ++0x78, 0x10, 0x13, 0xF8, 0x08, 0x60, 0x0E, 0xFB, 0x06, 0x26, 0xD0, 0x21, 0x76, 0x88, 0xA0, 0xF8, 0x7A, 0x60, 0x13, 0xF8, ++0x08, 0x30, 0x0E, 0xFB, 0x03, 0x22, 0x93, 0x88, 0xA0, 0xF8, 0x7C, 0x30, 0x07, 0xE7, 0xD9, 0xF8, 0x5C, 0x20, 0x46, 0x49, ++0x01, 0x32, 0x0D, 0x68, 0xC9, 0xF8, 0x5C, 0x20, 0x0A, 0xF1, 0x05, 0x02, 0x04, 0x92, 0x00, 0x2D, 0x00, 0xF0, 0x45, 0x81, ++0xEB, 0x7C, 0x8A, 0xF8, 0x05, 0x30, 0x2B, 0x7C, 0x8A, 0xF8, 0x06, 0x30, 0xD9, 0xE9, 0x0A, 0x12, 0xB9, 0xF8, 0x30, 0x30, ++0xAA, 0xF8, 0x0F, 0x30, 0xCA, 0xF8, 0x07, 0x10, 0xCA, 0xF8, 0x0B, 0x20, 0xAB, 0x7C, 0x8A, 0xF8, 0x11, 0x30, 0x95, 0xF9, ++0x14, 0x00, 0xEE, 0xF7, 0x21, 0xFF, 0xFF, 0x23, 0x8A, 0xF8, 0x12, 0x00, 0x8A, 0xF8, 0x13, 0x30, 0x05, 0xF1, 0x0C, 0x00, ++0xAB, 0x1D, 0x13, 0xF8, 0x01, 0x1B, 0x03, 0xF1, 0x0D, 0x02, 0x52, 0x1B, 0x83, 0x42, 0x02, 0xF8, 0x0A, 0x10, 0xF6, 0xD1, ++0x6B, 0x7C, 0x8A, 0xF8, 0x1A, 0x30, 0x02, 0x9A, 0xEB, 0x68, 0xCA, 0xF8, 0x1B, 0x30, 0x40, 0xF2, 0x01, 0x14, 0x94, 0x42, ++0x99, 0xF8, 0x20, 0x30, 0x28, 0xBF, 0x14, 0x46, 0x0A, 0xF1, 0x1F, 0x02, 0xA4, 0xB2, 0x04, 0x92, 0x00, 0x2B, 0x40, 0xF0, ++0x05, 0x81, 0x1F, 0x3C, 0xA4, 0xB2, 0x99, 0xF8, 0x04, 0x30, 0x00, 0x2B, 0x6D, 0xD1, 0x6B, 0x8B, 0x2B, 0x83, 0x03, 0x23, ++0x1D, 0x48, 0xAB, 0x80, 0x29, 0x46, 0xEE, 0xF7, 0xEB, 0xF9, 0x99, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x12, 0x81, ++0x04, 0x9B, 0x02, 0x9A, 0xA3, 0xEB, 0x0A, 0x05, 0xAB, 0x1E, 0x8A, 0xF8, 0x01, 0x30, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, ++0x00, 0x30, 0x54, 0x1B, 0x00, 0x2B, 0xA4, 0xB2, 0x80, 0xF2, 0xF9, 0x80, 0xAA, 0x42, 0x80, 0xF0, 0xF6, 0x80, 0x10, 0x49, ++0x10, 0x48, 0xDD, 0xF8, 0x10, 0xA0, 0x40, 0xF2, 0x07, 0x52, 0xEF, 0xF7, 0xCF, 0xFD, 0x02, 0x94, 0x51, 0xE7, 0x01, 0x9B, ++0x00, 0x2B, 0x7F, 0xF4, 0x5F, 0xAF, 0x09, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0x12, 0x52, 0xEF, 0xF7, 0xDB, 0xFD, 0x57, 0xE7, ++0x20, 0x62, 0x17, 0x00, 0x78, 0xEF, 0x17, 0x00, 0x8E, 0x65, 0x17, 0x00, 0x74, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x10, 0x07, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF4, 0xD0, 0x15, 0x00, 0x0C, 0xD1, 0x15, 0x00, 0x94, 0x4B, 0x1A, 0x68, ++0x00, 0x2A, 0x3F, 0xF4, 0x19, 0xAF, 0x19, 0x2C, 0x7F, 0xF6, 0x35, 0xAF, 0x02, 0x98, 0x99, 0xF8, 0x20, 0x10, 0xA0, 0xF1, ++0x1F, 0x03, 0x9B, 0xB2, 0x29, 0xB1, 0x02, 0x2B, 0x7F, 0xF6, 0x2B, 0xAF, 0xA0, 0xF1, 0x22, 0x03, 0x9B, 0xB2, 0x99, 0xF8, ++0x04, 0x10, 0x00, 0x29, 0x3F, 0xF4, 0x04, 0xAF, 0x03, 0x2B, 0x7F, 0xF6, 0x20, 0xAF, 0x10, 0x8B, 0x04, 0x3B, 0x9D, 0xB2, ++0x00, 0x28, 0x40, 0xF0, 0xCF, 0x80, 0x0D, 0x2D, 0x3F, 0xF6, 0xF8, 0xAE, 0x15, 0xE7, 0x04, 0x9A, 0x01, 0x23, 0x13, 0x70, ++0x2B, 0x8B, 0xA2, 0x1F, 0x92, 0xB2, 0x0A, 0xF1, 0x21, 0x01, 0x0B, 0x2B, 0x06, 0x92, 0x8C, 0x46, 0x1B, 0xD8, 0x7C, 0x4B, ++0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xAE, 0x80, 0x05, 0xF1, 0x1C, 0x02, 0x05, 0xF1, 0x28, 0x00, ++0x13, 0x46, 0x05, 0x33, 0x12, 0xF8, 0x01, 0x1B, 0x5B, 0x1B, 0x82, 0x42, 0x03, 0xF8, 0x0A, 0x10, 0xF6, 0xD1, 0x0C, 0x23, ++0x12, 0x3C, 0xA2, 0xB2, 0x2B, 0x83, 0x0A, 0xF1, 0x2D, 0x03, 0x06, 0x92, 0x9C, 0x46, 0x99, 0xF8, 0x04, 0x30, 0x01, 0x2B, ++0x3A, 0xD0, 0x2B, 0x8B, 0x6E, 0x8B, 0xF6, 0x1A, 0x05, 0xF1, 0x1C, 0x07, 0xB6, 0xB2, 0x1F, 0x44, 0x00, 0x2E, 0x3B, 0xD0, ++0xCD, 0xF8, 0x1C, 0xA0, 0xE3, 0x46, 0xAA, 0x46, 0x09, 0xE0, 0xBA, 0xF8, 0x18, 0x10, 0x36, 0x1B, 0xB6, 0xB2, 0x0C, 0x44, ++0x2F, 0x44, 0xAA, 0xF8, 0x18, 0x40, 0x00, 0x2E, 0x5D, 0xD0, 0x97, 0xF8, 0x00, 0x80, 0xB9, 0x78, 0x7C, 0x78, 0x40, 0x46, ++0x4A, 0x46, 0xFF, 0xF7, 0xA9, 0xFD, 0xA5, 0x1C, 0x02, 0x34, 0xED, 0xB2, 0xE4, 0xB2, 0x00, 0x28, 0xE7, 0xD0, 0xD9, 0x2D, ++0xE5, 0xD8, 0x06, 0x9B, 0x9C, 0x42, 0x4A, 0xD8, 0x4D, 0xB1, 0x59, 0x46, 0x78, 0x1A, 0xAB, 0x44, 0x01, 0xE0, 0x10, 0xF8, ++0x01, 0x80, 0x01, 0xF8, 0x01, 0x8B, 0x8B, 0x45, 0xF9, 0xD1, 0x06, 0x9B, 0x1B, 0x1B, 0x9B, 0xB2, 0x06, 0x93, 0xD2, 0xE7, ++0xD9, 0xF8, 0x08, 0x30, 0x00, 0x2B, 0xC0, 0xD1, 0xD9, 0xF8, 0x14, 0x30, 0x00, 0x2B, 0xBC, 0xD1, 0x6B, 0x8B, 0x2B, 0x83, ++0x04, 0x9B, 0xC3, 0xF1, 0xFE, 0x0B, 0xE3, 0x44, 0x02, 0x23, 0x8A, 0xF8, 0x20, 0xB0, 0x8C, 0xF8, 0x00, 0x30, 0x8C, 0xF8, ++0x01, 0x30, 0xEA, 0x7D, 0x28, 0x8B, 0x69, 0x8B, 0x99, 0xF8, 0x01, 0x30, 0x54, 0x1C, 0x88, 0x42, 0x66, 0x46, 0xEC, 0x75, ++0x43, 0xEA, 0x02, 0x23, 0x23, 0xD2, 0x6F, 0xEA, 0x43, 0x43, 0x6F, 0xEA, 0x53, 0x43, 0xAC, 0xF8, 0x02, 0x30, 0x33, 0x1D, ++0x04, 0x93, 0x08, 0xE7, 0x22, 0x3C, 0xA4, 0xB2, 0xF9, 0xE6, 0x03, 0x22, 0x8A, 0xF8, 0x01, 0x20, 0x36, 0x4A, 0x12, 0x68, ++0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x09, 0xDB, 0xDD, 0xF8, 0x10, 0xA0, 0x02, 0x94, 0x1D, 0x46, 0x6B, 0xE6, 0x55, 0x46, ++0xDC, 0x46, 0xDD, 0xF8, 0x1C, 0xA0, 0xC9, 0xE7, 0x1D, 0x46, 0xDD, 0xF8, 0x10, 0xA0, 0x02, 0x94, 0x61, 0xE6, 0xAC, 0xF8, ++0x02, 0x30, 0x33, 0x1D, 0x04, 0x93, 0xE2, 0xE6, 0x04, 0x9D, 0xA4, 0x23, 0x01, 0x24, 0x2B, 0x70, 0x6C, 0x70, 0xFF, 0xF7, ++0x6D, 0xFD, 0x20, 0xB1, 0xAC, 0x70, 0x04, 0x9B, 0x03, 0x33, 0x04, 0x93, 0xE0, 0xE6, 0x04, 0x9B, 0x98, 0x70, 0xF8, 0xE7, ++0x0B, 0x2A, 0x3F, 0xF6, 0x4F, 0xAF, 0x21, 0x49, 0x21, 0x48, 0x40, 0xF2, 0x7D, 0x42, 0xEF, 0xF7, 0xBF, 0xFC, 0x47, 0xE7, ++0xB2, 0xF8, 0x1A, 0x80, 0x01, 0x29, 0x02, 0xF1, 0x1C, 0x02, 0xA8, 0xEB, 0x00, 0x08, 0x02, 0xEB, 0x00, 0x07, 0x08, 0xD0, ++0xB8, 0xF1, 0x00, 0x0F, 0x1B, 0xD0, 0x7B, 0x78, 0x03, 0x33, 0xAB, 0x42, 0xFF, 0xF6, 0x1A, 0xAE, 0x37, 0xE6, 0x7E, 0x78, ++0x10, 0x5C, 0x97, 0xF8, 0x02, 0xB0, 0x02, 0x36, 0xF6, 0xB2, 0x03, 0xE0, 0x7E, 0x78, 0x38, 0x78, 0x02, 0x36, 0xF6, 0xB2, ++0x4A, 0x46, 0x59, 0x46, 0xFF, 0xF7, 0x08, 0xFD, 0x08, 0xB1, 0xD9, 0x2E, 0xE4, 0xD9, 0xB8, 0xEB, 0x06, 0x08, 0x37, 0x44, ++0xF0, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xFC, 0xAD, 0x05, 0x49, 0x07, 0x48, ++0x40, 0xF2, 0x13, 0x42, 0xEF, 0xF7, 0xA0, 0xFC, 0xF4, 0xE5, 0x00, 0xBF, 0x10, 0x07, 0x18, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x70, 0x79, 0x15, 0x00, 0xD0, 0xD0, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x2D, 0x4E, 0x41, 0xF2, 0xA9, 0x73, ++0xF2, 0x5C, 0x03, 0x2A, 0x42, 0xD8, 0x41, 0xF2, 0xA8, 0x73, 0xF3, 0x5C, 0x09, 0x2B, 0x3D, 0xD8, 0x0D, 0x46, 0x28, 0x49, ++0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x13, 0x07, 0x46, 0x1B, 0x6C, 0x00, 0x2B, 0x3E, 0xD0, 0x24, 0x48, 0x1B, 0x79, ++0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x2D, 0xDB, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x12, 0x92, 0xF8, ++0xC0, 0x24, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xDA, 0xF7, 0x3D, 0xFE, 0x04, 0x46, ++0xE0, 0xB1, 0x41, 0xF2, 0xA9, 0x72, 0x41, 0xF2, 0xA8, 0x73, 0xB2, 0x5C, 0x02, 0x77, 0xF3, 0x5C, 0x43, 0x77, 0x00, 0x23, ++0x80, 0xF8, 0x33, 0x30, 0x80, 0xF8, 0x35, 0x30, 0x15, 0xB9, 0x13, 0x4B, 0xC0, 0xE9, 0x15, 0x30, 0x20, 0x46, 0x3B, 0x46, ++0x2A, 0x46, 0x01, 0x21, 0xFF, 0xF7, 0xEC, 0xFC, 0x20, 0x46, 0x03, 0x21, 0xBD, 0xE8, 0xF8, 0x40, 0xDA, 0xF7, 0x2E, 0xBE, ++0xF8, 0xBD, 0x02, 0x2B, 0xCF, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0xEF, 0xF7, 0x29, 0xFC, 0x01, 0x20, ++0xD1, 0xE7, 0x05, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xF7, 0xDA, 0xF0, 0xE7, 0x78, 0xEF, 0x17, 0x00, ++0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xA1, 0x5E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, ++0x00, 0x2A, 0x35, 0xD0, 0x70, 0xB5, 0x04, 0x46, 0x92, 0xF8, 0x32, 0x00, 0x8A, 0xB0, 0x13, 0x46, 0x58, 0xB9, 0x95, 0x8E, ++0x22, 0x88, 0x95, 0x42, 0x28, 0xD1, 0xDD, 0x8E, 0x62, 0x88, 0x95, 0x42, 0x24, 0xD1, 0xA2, 0x88, 0x1C, 0x8F, 0x94, 0x42, ++0x20, 0xD1, 0x93, 0xF8, 0x3A, 0x20, 0xE2, 0xB1, 0xD9, 0xB1, 0x4D, 0x78, 0x8D, 0xF8, 0x04, 0x50, 0x6D, 0xB1, 0x01, 0xA8, ++0x05, 0x44, 0xC0, 0xF1, 0x02, 0x06, 0x44, 0x18, 0xA4, 0x5D, 0x00, 0xF8, 0x01, 0x4F, 0xA8, 0x42, 0xF9, 0xD1, 0x9D, 0xF8, ++0x04, 0x10, 0x91, 0x42, 0x01, 0xD0, 0x00, 0x20, 0x08, 0xE0, 0x03, 0xF1, 0x3B, 0x00, 0x0D, 0xF1, 0x05, 0x01, 0x01, 0xF0, ++0x57, 0xFE, 0x00, 0x28, 0xF5, 0xD1, 0x01, 0x20, 0x0A, 0xB0, 0x70, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, ++0x04, 0x46, 0xB1, 0xB1, 0x64, 0x48, 0x65, 0x4D, 0xA0, 0xF1, 0x82, 0x07, 0xED, 0xF7, 0x78, 0xFF, 0x00, 0x26, 0x25, 0xF8, ++0x02, 0x6C, 0x28, 0x46, 0x06, 0x22, 0x00, 0x21, 0x05, 0xF5, 0xF6, 0x75, 0xCA, 0xF7, 0xDE, 0xFE, 0xBD, 0x42, 0xF4, 0xD1, ++0xEC, 0xF7, 0x56, 0xFC, 0xC4, 0xE9, 0x0A, 0x01, 0x26, 0x66, 0x5B, 0x4E, 0xDF, 0xF8, 0x6C, 0x81, 0x06, 0xF1, 0x88, 0x07, ++0x0B, 0x20, 0xED, 0xF7, 0x77, 0xFD, 0x01, 0x28, 0x39, 0xD1, 0x57, 0x4D, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x02, 0x0A, ++0x03, 0xE0, 0x05, 0xF5, 0xF6, 0x75, 0xB5, 0x42, 0x1A, 0xD0, 0xAB, 0x88, 0x01, 0x2B, 0xF8, 0xD1, 0x6B, 0x7D, 0x05, 0xF1, ++0x1C, 0x01, 0x19, 0x44, 0x22, 0x46, 0xA8, 0x1D, 0xFF, 0xF7, 0x8C, 0xFF, 0x00, 0x28, 0xEE, 0xD0, 0x29, 0x46, 0xA5, 0xF8, ++0x18, 0x90, 0x85, 0xF8, 0x17, 0x90, 0xA5, 0xF8, 0x04, 0xA0, 0x38, 0x46, 0x05, 0xF5, 0xF6, 0x75, 0xED, 0xF7, 0x3E, 0xFF, ++0xB5, 0x42, 0xE4, 0xD1, 0x23, 0x6E, 0x94, 0xF8, 0x65, 0x20, 0x01, 0x33, 0x93, 0x42, 0x23, 0x66, 0x5D, 0xDA, 0x03, 0x21, ++0x0B, 0x20, 0xED, 0xF7, 0x9D, 0xFC, 0xFF, 0xF7, 0x1F, 0xFC, 0x00, 0x28, 0xC6, 0xD1, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, ++0xF0, 0x47, 0xFF, 0xF7, 0xFF, 0xBE, 0x01, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x8F, 0xFC, 0x23, 0x6E, 0x06, 0xE0, 0x23, 0x6E, ++0x94, 0xF8, 0x65, 0x20, 0x01, 0x33, 0x93, 0x42, 0x23, 0x66, 0xB3, 0xDA, 0x23, 0x44, 0x94, 0xF8, 0x64, 0x00, 0x93, 0xF8, ++0x66, 0x10, 0xF1, 0xF7, 0xBB, 0xFF, 0x05, 0x46, 0x00, 0x28, 0xEE, 0xD0, 0xC3, 0x78, 0x9B, 0x07, 0xEB, 0xD4, 0x4F, 0xF4, ++0xBA, 0x73, 0x0B, 0x22, 0x04, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xED, 0xF7, 0x77, 0xFA, 0x06, 0x46, 0x28, 0x68, 0x30, 0x60, ++0xAB, 0x88, 0xB3, 0x80, 0xE3, 0x78, 0x1B, 0xB9, 0xF3, 0x78, 0x43, 0xF0, 0x01, 0x03, 0xF3, 0x70, 0x01, 0x25, 0x86, 0xF8, ++0x6F, 0x51, 0x94, 0xF8, 0x3A, 0x20, 0x86, 0xF8, 0xFC, 0x20, 0x04, 0xF1, 0x3B, 0x01, 0x06, 0xF1, 0xFD, 0x00, 0x01, 0xF0, ++0xE7, 0xFD, 0x86, 0xF8, 0x70, 0x51, 0xA3, 0x8E, 0xA6, 0xF8, 0x60, 0x31, 0xE3, 0x8E, 0xA6, 0xF8, 0x62, 0x31, 0x23, 0x8F, ++0xA6, 0xF8, 0x64, 0x31, 0x41, 0xF2, 0xA9, 0x73, 0x30, 0x46, 0x18, 0xF8, 0x03, 0x30, 0x86, 0xF8, 0x6E, 0x31, 0xBD, 0xE8, ++0xF0, 0x47, 0xED, 0xF7, 0x79, 0xBA, 0x13, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x09, 0xDB, 0x02, 0x21, ++0x0B, 0x20, 0xED, 0xF7, 0x39, 0xFC, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x9F, 0xBE, 0xFF, 0xF7, ++0xB5, 0xFB, 0x00, 0x28, 0xF1, 0xD0, 0xE3, 0x6D, 0x00, 0x2B, 0xEE, 0xD0, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF2, 0x22, 0x62, ++0xEF, 0xF7, 0x0E, 0xFB, 0xE7, 0xE7, 0x00, 0xBF, 0x10, 0x07, 0x18, 0x00, 0x7E, 0xEF, 0x17, 0x00, 0x88, 0x06, 0x18, 0x00, ++0x78, 0xEF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x1C, 0xD1, 0x15, 0x00, 0x10, 0xB5, 0x08, 0x4C, ++0x00, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x10, 0xFC, 0x20, 0x46, 0x41, 0xF2, 0xB0, 0x72, 0x00, 0x21, 0x04, 0xF5, 0xBD, 0x54, ++0xCA, 0xF7, 0x08, 0xFE, 0x4F, 0xF0, 0xFF, 0x33, 0x23, 0x60, 0x10, 0xBD, 0x78, 0xEF, 0x17, 0x00, 0xF0, 0xB5, 0xA3, 0xB0, ++0x0B, 0x4C, 0x9D, 0xF8, 0xA0, 0x50, 0x8D, 0xF8, 0x02, 0x50, 0x41, 0xF2, 0xA8, 0x75, 0x84, 0x46, 0x41, 0xF2, 0xA9, 0x77, ++0x08, 0x46, 0x66, 0x5B, 0x60, 0x55, 0x19, 0x46, 0x68, 0x46, 0x04, 0xF8, 0x07, 0xC0, 0x8D, 0xF8, 0x00, 0x20, 0xFF, 0xF7, ++0x57, 0xFE, 0x66, 0x53, 0x23, 0xB0, 0xF0, 0xBD, 0x78, 0xEF, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAB, 0xB0, 0x41, 0xF2, ++0xA8, 0x76, 0x00, 0x92, 0xC4, 0x4A, 0x41, 0xF2, 0xA9, 0x75, 0x91, 0x55, 0xCD, 0xE9, 0x01, 0x01, 0x02, 0xF5, 0xBD, 0x51, ++0x50, 0x55, 0x4F, 0xF0, 0xFF, 0x30, 0x08, 0x60, 0x34, 0x99, 0x16, 0x46, 0x41, 0xF2, 0xA4, 0x74, 0x00, 0x22, 0x91, 0x42, ++0x32, 0x51, 0x34, 0xDD, 0xDF, 0xF8, 0xF0, 0x82, 0x1F, 0x46, 0x91, 0x46, 0xBA, 0x46, 0x57, 0xF8, 0x04, 0x4B, 0x65, 0x78, ++0xAB, 0x1C, 0x04, 0x2B, 0x37, 0xD9, 0x88, 0x22, 0x00, 0x21, 0x40, 0x46, 0xCA, 0xF7, 0xBC, 0xFD, 0xA3, 0x78, 0x88, 0xF8, ++0x01, 0x30, 0xE3, 0x78, 0x22, 0x79, 0x88, 0xF8, 0x02, 0x20, 0xD9, 0x07, 0x03, 0xD4, 0x9B, 0x07, 0x1C, 0xD4, 0x05, 0x2A, ++0x73, 0xD0, 0xDA, 0xF8, 0x00, 0x40, 0x02, 0x21, 0x00, 0x9A, 0x23, 0x79, 0x8D, 0xF8, 0x20, 0x20, 0xA8, 0x4A, 0x02, 0x98, ++0x8D, 0xF8, 0x22, 0x30, 0x41, 0xF2, 0xA8, 0x75, 0x41, 0xF2, 0xA9, 0x73, 0x16, 0x46, 0x54, 0x5B, 0x01, 0x9F, 0x50, 0x55, ++0x08, 0xA8, 0xD7, 0x54, 0xFF, 0xF7, 0x04, 0xFE, 0x74, 0x53, 0x2B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x98, 0xF8, 0x00, 0x30, ++0x00, 0x9A, 0x93, 0x42, 0x4C, 0xD0, 0x34, 0x9B, 0x09, 0xF1, 0x01, 0x09, 0x4B, 0x45, 0xC1, 0xD1, 0xF1, 0xE7, 0x04, 0x21, ++0xDA, 0xE7, 0xA3, 0x2C, 0x00, 0xF0, 0x25, 0x81, 0xA4, 0x2C, 0x40, 0xF0, 0x18, 0x81, 0x98, 0x78, 0x88, 0xF8, 0x20, 0x00, ++0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0x0B, 0x44, 0x00, 0xF2, 0x82, 0x80, 0x98, 0xF8, 0x03, 0x30, 0x01, 0x2B, 0x3E, 0x46, ++0x03, 0x9F, 0x2C, 0xD8, 0x04, 0x9C, 0x72, 0x2C, 0x23, 0x46, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x30, ++0x00, 0x2E, 0x00, 0xF0, 0x2B, 0x81, 0xB6, 0xF8, 0x03, 0x20, 0xB1, 0x78, 0xB0, 0x88, 0x88, 0xF8, 0x66, 0x40, 0x41, 0xF2, ++0x88, 0x33, 0x9A, 0x42, 0x94, 0xBF, 0x00, 0x22, 0x01, 0x22, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x20, 0x88, 0xF8, 0x65, 0x30, ++0x00, 0x29, 0x40, 0xF0, 0x03, 0x81, 0x05, 0x9A, 0x88, 0xF8, 0x64, 0x10, 0x94, 0x42, 0x06, 0xD0, 0x80, 0xF0, 0x59, 0x81, ++0x04, 0x9B, 0x04, 0x33, 0x88, 0xF8, 0x67, 0x30, 0x02, 0x23, 0x88, 0xF8, 0x65, 0x30, 0x00, 0x9B, 0x88, 0xF8, 0x00, 0x30, ++0x76, 0x4A, 0x13, 0x68, 0x01, 0x33, 0x08, 0xF1, 0x88, 0x08, 0x13, 0x60, 0xAB, 0xE7, 0xEB, 0x1E, 0x0C, 0x2B, 0x40, 0xF2, ++0xDD, 0x80, 0xE3, 0x7A, 0x88, 0xF8, 0x03, 0x30, 0x02, 0x2B, 0x82, 0xD8, 0x62, 0x79, 0x63, 0x7A, 0x04, 0x92, 0xA2, 0x79, ++0x05, 0x92, 0xA8, 0xF8, 0x30, 0x30, 0x08, 0xF1, 0x3A, 0x0E, 0x08, 0xF1, 0x34, 0x03, 0xA4, 0xEB, 0x08, 0x01, 0x5A, 0x18, ++0x12, 0xF8, 0x28, 0x2C, 0x03, 0xF8, 0x01, 0x2B, 0x73, 0x45, 0xF8, 0xD1, 0xB8, 0xF8, 0x34, 0x20, 0x4F, 0xF6, 0xFF, 0x73, ++0x9A, 0x42, 0xA5, 0xF1, 0x10, 0x02, 0x08, 0xBF, 0x01, 0x23, 0x4F, 0xF0, 0x02, 0x01, 0x92, 0xB2, 0x08, 0xBF, 0x88, 0xF8, ++0x32, 0x30, 0x8A, 0x42, 0x04, 0xF1, 0x12, 0x03, 0x88, 0xF8, 0x04, 0x10, 0x40, 0xF2, 0x47, 0x81, 0x00, 0x21, 0x6F, 0xF0, ++0x13, 0x00, 0x0C, 0x46, 0x6F, 0xF0, 0x08, 0x06, 0x6F, 0xF0, 0x37, 0x0C, 0x0D, 0x46, 0xA0, 0xEB, 0x08, 0x01, 0x03, 0x97, ++0x06, 0x91, 0xA6, 0xEB, 0x08, 0x06, 0xAC, 0xEB, 0x08, 0x0C, 0x27, 0x46, 0x58, 0x78, 0x1C, 0x78, 0x81, 0x1C, 0x91, 0x42, ++0x00, 0xF2, 0x96, 0x80, 0x0B, 0x2C, 0x3F, 0xF6, 0x66, 0xAF, 0x0B, 0x2C, 0x3F, 0xF6, 0x6C, 0xAF, 0x0F, 0xF2, 0x04, 0x0B, ++0x5B, 0xF8, 0x24, 0xF0, 0xA9, 0x58, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0x97, 0x58, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, ++0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, ++0xB1, 0x56, 0x15, 0x00, 0x65, 0x58, 0x15, 0x00, 0x11, 0x58, 0x15, 0x00, 0x02, 0x29, 0x71, 0xD0, 0x9C, 0x78, 0xFF, 0x2C, ++0x7F, 0xF4, 0x4A, 0xAF, 0x00, 0xF1, 0xFF, 0x3B, 0x5F, 0xFA, 0x8B, 0xFB, 0xBB, 0xF1, 0x08, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, ++0x08, 0x0B, 0x01, 0x28, 0xC8, 0xF8, 0x14, 0xB0, 0x3F, 0xF4, 0x3C, 0xAF, 0x08, 0xF1, 0x17, 0x00, 0xCD, 0xF8, 0x1C, 0xA0, ++0xDD, 0xF8, 0x18, 0xA0, 0x83, 0x44, 0x1C, 0x18, 0x14, 0xF8, 0x0A, 0x40, 0x00, 0xF8, 0x01, 0x4F, 0x58, 0x45, 0xF8, 0xD1, ++0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0xDD, 0xF8, 0x1C, 0xA0, 0x0B, 0x44, 0xAE, 0xD8, 0x2B, 0xE7, 0x8C, 0x1E, 0x08, 0x2C, ++0xA8, 0xBF, 0x08, 0x24, 0x02, 0x29, 0xC8, 0xF8, 0x08, 0x40, 0x3F, 0xF4, 0x1D, 0xAF, 0x08, 0xF1, 0x0B, 0x00, 0x00, 0xEB, ++0x04, 0x0B, 0x1C, 0x18, 0xA4, 0x5D, 0x00, 0xF8, 0x01, 0x4F, 0x83, 0x45, 0xF9, 0xD1, 0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, ++0x0B, 0x44, 0x95, 0xD8, 0x12, 0xE7, 0x52, 0x1A, 0x92, 0xB2, 0x98, 0x78, 0x88, 0xF8, 0x04, 0x00, 0x02, 0x2A, 0x0B, 0x44, ++0x8C, 0xD8, 0x09, 0xE7, 0x22, 0x29, 0x25, 0xD8, 0x88, 0xF8, 0x3A, 0x00, 0x00, 0x28, 0x3F, 0xF4, 0xFD, 0xAE, 0x00, 0xEB, ++0x0E, 0x04, 0x70, 0x46, 0x00, 0xEB, 0x03, 0x0B, 0x1B, 0xF8, 0x0C, 0xB0, 0x00, 0xF8, 0x01, 0xBF, 0xA0, 0x42, 0xF7, 0xD1, ++0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0x0B, 0x44, 0x3F, 0xF6, 0x74, 0xAF, 0xF0, 0xE6, 0x52, 0x1A, 0x92, 0xB2, 0x33, 0x2C, ++0x08, 0xBF, 0x1D, 0x46, 0x02, 0x2A, 0x0B, 0x44, 0x3F, 0xF6, 0x6A, 0xAF, 0xE6, 0xE6, 0x1F, 0x46, 0xDE, 0xE6, 0x00, 0x23, ++0x88, 0xF8, 0x65, 0x30, 0xDA, 0xF8, 0x00, 0x40, 0x04, 0x21, 0xA9, 0xE6, 0x78, 0xEF, 0x17, 0x00, 0x1C, 0x07, 0x18, 0x00, ++0x88, 0x06, 0x18, 0x00, 0x01, 0x29, 0x08, 0xF1, 0x66, 0x03, 0x00, 0xF0, 0x47, 0x81, 0x04, 0x9A, 0x41, 0x2A, 0x35, 0xBF, ++0x40, 0x20, 0x80, 0x20, 0x24, 0x22, 0x64, 0x22, 0x11, 0x1D, 0x03, 0xF8, 0x01, 0x2B, 0xCA, 0xB2, 0x90, 0x42, 0xF9, 0xD2, ++0x08, 0x23, 0xF4, 0xE6, 0x05, 0x9B, 0xFF, 0x2B, 0x4E, 0xD0, 0x05, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0x85, 0x80, 0x05, 0x9A, ++0x88, 0xF8, 0x66, 0x20, 0x01, 0x23, 0x88, 0xF8, 0x65, 0x30, 0x04, 0x9B, 0xA3, 0xF1, 0x53, 0x02, 0x08, 0xF1, 0x66, 0x03, ++0x2E, 0x2A, 0x30, 0xD8, 0xDF, 0xE8, 0x12, 0xF0, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, ++0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, ++0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, ++0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, ++0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x71, 0x01, ++0x6E, 0x01, 0x01, 0x23, 0xAD, 0xE6, 0x05, 0x9B, 0x04, 0x93, 0x04, 0x9B, 0x04, 0x3B, 0x88, 0xF8, 0x67, 0x30, 0x02, 0x23, ++0xA5, 0xE6, 0x05, 0x9B, 0x04, 0x93, 0x9D, 0xE6, 0x00, 0x2D, 0x8D, 0xD0, 0xAB, 0x78, 0x04, 0x9A, 0x93, 0x42, 0x89, 0xD1, ++0x68, 0x78, 0x43, 0x1E, 0xDB, 0xB2, 0x1C, 0x2B, 0x28, 0xBF, 0x1C, 0x23, 0x59, 0x1E, 0x01, 0x28, 0x05, 0xF1, 0x03, 0x05, ++0xC9, 0xB2, 0x3F, 0xF4, 0x7D, 0xAF, 0x32, 0x46, 0x08, 0xEB, 0x02, 0x04, 0xAE, 0x5C, 0x84, 0xF8, 0x66, 0x60, 0x91, 0x42, ++0x02, 0xF1, 0x01, 0x02, 0xF6, 0xD1, 0x01, 0x28, 0x3F, 0xF4, 0x70, 0xAF, 0x88, 0xF8, 0x65, 0x30, 0x01, 0x2B, 0x7F, 0xF4, ++0x80, 0xAE, 0x98, 0xF8, 0x66, 0x30, 0x05, 0x93, 0x91, 0xE7, 0x98, 0xF8, 0x03, 0x30, 0x01, 0x2B, 0x3F, 0xF6, 0x77, 0xAE, ++0x04, 0x9B, 0x72, 0x2B, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x30, 0x05, 0x9B, 0xFF, 0x2B, 0x7F, 0xF4, ++0x78, 0xAF, 0x55, 0xE7, 0x04, 0x9A, 0x08, 0xF1, 0x66, 0x03, 0x51, 0x3A, 0x1E, 0x46, 0x30, 0x2A, 0x3F, 0xF6, 0x4B, 0xAF, ++0x01, 0xA1, 0x51, 0xF8, 0x22, 0xF0, 0x00, 0xBF, 0x9B, 0x5B, 0x15, 0x00, 0x27, 0x5C, 0x15, 0x00, 0x9B, 0x5B, 0x15, 0x00, ++0x9B, 0x5B, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, ++0xF3, 0x58, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x87, 0x5B, 0x15, 0x00, ++0x87, 0x5B, 0x15, 0x00, 0x87, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, ++0x29, 0x5B, 0x15, 0x00, 0x03, 0x5C, 0x15, 0x00, 0x29, 0x5B, 0x15, 0x00, 0x29, 0x5B, 0x15, 0x00, 0xE9, 0x5B, 0x15, 0x00, ++0x0D, 0x5C, 0x15, 0x00, 0x00, 0x25, 0x04, 0x20, 0xA2, 0x24, 0x95, 0x22, 0x71, 0x1E, 0x0B, 0x46, 0x02, 0x33, 0x01, 0xF8, ++0x01, 0x2F, 0x02, 0x44, 0x2B, 0x44, 0x94, 0x42, 0xA3, 0xEB, 0x06, 0x03, 0xF5, 0xDC, 0x40, 0x4A, 0xDB, 0xB2, 0x12, 0x68, ++0x88, 0xF8, 0x65, 0x30, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xDB, 0x00, 0x2B, 0x7F, 0xF4, 0x5F, 0xAF, 0xCB, 0xE6, ++0x1C, 0x2B, 0xF9, 0xD9, 0x39, 0x49, 0x3A, 0x48, 0x40, 0xF2, 0x01, 0x32, 0xEF, 0xF7, 0x06, 0xF8, 0x98, 0xF8, 0x65, 0x30, ++0x00, 0x2B, 0x7F, 0xF4, 0x51, 0xAF, 0xBD, 0xE6, 0x00, 0x25, 0x04, 0x20, 0x91, 0x24, 0x64, 0x22, 0xD4, 0xE7, 0x00, 0x25, ++0x04, 0x20, 0x41, 0x24, 0x34, 0x22, 0xCF, 0xE7, 0x00, 0x25, 0x04, 0x20, 0x31, 0x24, 0x24, 0x22, 0xCA, 0xE7, 0x01, 0x20, ++0x02, 0x46, 0x00, 0x25, 0x0E, 0x24, 0xC5, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0xB6, 0xAE, 0x04, 0x9A, 0x23, 0x2A, 0x7F, 0xF6, ++0x06, 0xAF, 0x30, 0x2A, 0x15, 0xD9, 0x40, 0x2A, 0x10, 0xD9, 0x70, 0x2A, 0x3B, 0xD9, 0x80, 0x2A, 0x36, 0xD9, 0x90, 0x2A, ++0x3F, 0xF6, 0xFB, 0xAE, 0x90, 0x21, 0x84, 0x22, 0x10, 0x1D, 0x03, 0xF8, 0x01, 0x2B, 0xC2, 0xB2, 0x91, 0x42, 0xF9, 0xD2, ++0x04, 0x23, 0xA0, 0xE5, 0x40, 0x21, 0x34, 0x22, 0xF4, 0xE7, 0x30, 0x21, 0x24, 0x22, 0xF1, 0xE7, 0x24, 0x22, 0x03, 0xF8, ++0x01, 0x2B, 0x04, 0x32, 0x44, 0x2A, 0xFA, 0xD1, 0x08, 0xF1, 0x6E, 0x06, 0x08, 0x25, 0x04, 0x20, 0x91, 0x24, 0x64, 0x22, ++0x96, 0xE7, 0x00, 0x25, 0x04, 0x20, 0xAA, 0x24, 0x95, 0x22, 0x91, 0xE7, 0x24, 0x22, 0x03, 0xF8, 0x01, 0x2B, 0x04, 0x32, ++0x44, 0x2A, 0xFA, 0xD1, 0x08, 0xF1, 0x6E, 0x06, 0x08, 0x25, 0x04, 0x20, 0x81, 0x24, 0x64, 0x22, 0x84, 0xE7, 0x0F, 0x24, ++0x01, 0x20, 0x00, 0x25, 0x0E, 0x22, 0x7F, 0xE7, 0x80, 0x21, 0x74, 0x22, 0xCA, 0xE7, 0x70, 0x21, 0x64, 0x22, 0xC7, 0xE7, ++0x05, 0x9A, 0x04, 0x92, 0x69, 0xE6, 0x05, 0x9A, 0x04, 0x92, 0xB0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, ++0x5C, 0xD1, 0x15, 0x00, 0x70, 0xB5, 0x15, 0x4D, 0x2C, 0x68, 0xA5, 0xF5, 0xBD, 0x56, 0x01, 0x34, 0xA5, 0xF1, 0x90, 0x01, ++0x2C, 0x60, 0x33, 0x46, 0x01, 0x20, 0x9A, 0x88, 0x01, 0x2A, 0x88, 0xBF, 0x98, 0x80, 0x03, 0xF5, 0xF6, 0x73, 0x8B, 0x42, ++0xF7, 0xD1, 0x41, 0xF2, 0xA4, 0x73, 0xF3, 0x58, 0x9C, 0x42, 0x0B, 0xDA, 0x04, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x90, 0xF8, ++0x0B, 0x22, 0xBD, 0xE8, 0x70, 0x40, 0x11, 0x46, 0x4F, 0xF4, 0x30, 0x50, 0xEC, 0xF7, 0xF6, 0xBE, 0x00, 0x21, 0x0B, 0x20, ++0xED, 0xF7, 0x84, 0xF8, 0x4F, 0xF0, 0xFF, 0x33, 0x2B, 0x60, 0x70, 0xBD, 0x18, 0x07, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x43, ++0x3E, 0x4C, 0x3F, 0x4E, 0x04, 0xF5, 0xBD, 0x53, 0x31, 0x68, 0x1B, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x03, 0xEB, 0x03, 0x13, ++0x04, 0xEB, 0xC3, 0x05, 0x05, 0xF5, 0xB8, 0x55, 0x00, 0x29, 0x05, 0xF1, 0x10, 0x05, 0x4F, 0xEA, 0xC3, 0x03, 0x3A, 0xDB, ++0x23, 0x44, 0x41, 0xF2, 0x13, 0x72, 0x9B, 0x5C, 0x01, 0x2B, 0x45, 0xD9, 0x02, 0x2B, 0x50, 0xD1, 0x02, 0x21, 0x0B, 0x20, ++0xED, 0xF7, 0x5C, 0xF8, 0x30, 0x48, 0x2E, 0x4C, 0xA0, 0xF1, 0x88, 0x06, 0x06, 0xF1, 0x88, 0x09, 0xED, 0xF7, 0xE4, 0xFA, ++0x00, 0x27, 0x4F, 0xF0, 0x02, 0x08, 0x03, 0xE0, 0x04, 0xF5, 0xF6, 0x74, 0xB4, 0x42, 0x18, 0xD0, 0xA3, 0x88, 0x01, 0x2B, ++0xF8, 0xD1, 0x63, 0x7D, 0x04, 0xF1, 0x1C, 0x01, 0x19, 0x44, 0x2A, 0x46, 0xA0, 0x1D, 0xFF, 0xF7, 0x15, 0xFB, 0x00, 0x28, ++0xEE, 0xD0, 0x21, 0x46, 0x27, 0x83, 0xE7, 0x75, 0xA4, 0xF8, 0x04, 0x80, 0x48, 0x46, 0x04, 0xF5, 0xF6, 0x74, 0xED, 0xF7, ++0xC9, 0xFA, 0xB4, 0x42, 0xE6, 0xD1, 0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0x99, 0xBA, 0x1C, 0x44, ++0x41, 0xF2, 0x12, 0x73, 0xE3, 0x5C, 0x05, 0x2B, 0x19, 0xD0, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0xA3, 0x62, 0xEE, 0xF7, ++0x09, 0xFF, 0x41, 0xF2, 0x13, 0x73, 0xE3, 0x5C, 0x01, 0x2B, 0x05, 0xD8, 0x28, 0x46, 0x01, 0x21, 0xBD, 0xE8, 0xF8, 0x43, ++0xFF, 0xF7, 0x24, 0xBB, 0x02, 0x2B, 0xB3, 0xD0, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x08, 0xDB, 0xBD, 0xE8, ++0xF8, 0x83, 0x41, 0xF2, 0x13, 0x73, 0xE3, 0x5C, 0x01, 0x2B, 0xEB, 0xD9, 0x02, 0x2B, 0xA5, 0xD0, 0xBD, 0xE8, 0xF8, 0x43, ++0x05, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xAF, 0x62, 0xEE, 0xF7, 0xE6, 0xBE, 0x78, 0xEF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, ++0x10, 0x07, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xD1, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, ++0xDF, 0xF8, 0xCC, 0x80, 0x2C, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x14, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0C, 0xDB, ++0x29, 0x4F, 0x04, 0xEB, 0x04, 0x13, 0x07, 0xEB, 0xC3, 0x03, 0x41, 0xF2, 0x13, 0x72, 0x25, 0x01, 0x9B, 0x5C, 0x01, 0x2B, ++0x19, 0xD9, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x2C, 0x35, 0xDB, 0x22, 0x4F, 0x04, 0xEB, 0x04, 0x16, 0x07, 0xEB, 0xC6, 0x06, ++0x41, 0xF2, 0x12, 0x73, 0x25, 0x01, 0xF3, 0x5C, 0x05, 0x2B, 0x15, 0xD0, 0x1D, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0xD7, 0x62, ++0xEE, 0xF7, 0xAE, 0xFE, 0x41, 0xF2, 0x13, 0x73, 0xF3, 0x5C, 0x01, 0x2B, 0x17, 0xD8, 0x2C, 0x44, 0x07, 0xEB, 0xC4, 0x00, ++0x00, 0xF5, 0xB8, 0x50, 0xBD, 0xE8, 0xF0, 0x41, 0x10, 0x30, 0x00, 0x21, 0xFF, 0xF7, 0xC4, 0xBA, 0x41, 0xF2, 0x13, 0x73, ++0xF3, 0x5C, 0x01, 0x2B, 0xEF, 0xD9, 0xBD, 0xE8, 0xF0, 0x41, 0x0F, 0x49, 0x10, 0x48, 0x40, 0xF2, 0xC1, 0x62, 0xEE, 0xF7, ++0x91, 0xBE, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xF1, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, 0x08, 0x49, ++0x0A, 0x48, 0x40, 0xF2, 0xB7, 0x62, 0xEE, 0xF7, 0x83, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, ++0xBD, 0xDB, 0xAD, 0xE7, 0x18, 0x07, 0x18, 0x00, 0x78, 0xEF, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xD1, 0x15, 0x00, ++0x64, 0x7D, 0x15, 0x00, 0xC0, 0xD1, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0xB5, 0x29, 0xB3, 0x18, 0x4C, 0x04, 0xF5, ++0xBD, 0x53, 0x05, 0x46, 0x1E, 0x68, 0xFE, 0xF7, 0x01, 0xFF, 0x02, 0x46, 0x40, 0xB1, 0x0B, 0x20, 0xED, 0xF7, 0x20, 0xF8, ++0x03, 0x28, 0x1F, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xC6, 0xBE, 0x06, 0xEB, 0x06, 0x16, 0x04, 0xEB, 0xC6, 0x03, ++0x01, 0x21, 0x03, 0xF5, 0xB8, 0x53, 0x85, 0xF8, 0x5E, 0x10, 0x10, 0x33, 0x01, 0x46, 0x28, 0x46, 0xFE, 0xF7, 0x00, 0xFF, ++0x28, 0x46, 0x03, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0xDA, 0xF7, 0x42, 0xB8, 0x0B, 0x20, 0xEC, 0xF7, 0x5B, 0xFF, 0x05, 0x4B, ++0x4F, 0xF0, 0xFF, 0x32, 0x1A, 0x60, 0x70, 0xBD, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0x60, 0xBF, 0x78, 0xEF, 0x17, 0x00, ++0x18, 0x07, 0x18, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0xB0, 0xB6, 0x4F, 0x9D, 0xF8, 0x50, 0x40, 0x03, 0x94, 0x9D, 0xF9, ++0x54, 0x40, 0x04, 0x94, 0x07, 0xF5, 0xBD, 0x55, 0x04, 0x46, 0x28, 0x68, 0x25, 0x7C, 0x8D, 0xF8, 0x20, 0x50, 0x65, 0x7C, ++0x8D, 0xF8, 0x21, 0x50, 0xA5, 0x7C, 0x8D, 0xF8, 0x22, 0x50, 0xE5, 0x7C, 0x8D, 0xF8, 0x23, 0x50, 0x25, 0x7D, 0x8D, 0xF8, ++0x24, 0x50, 0x00, 0x28, 0x65, 0x7D, 0x9D, 0xF8, 0x58, 0x90, 0x8D, 0xF8, 0x25, 0x50, 0x0E, 0x46, 0x90, 0x46, 0x05, 0x93, ++0xC0, 0xF2, 0x1A, 0x81, 0x00, 0xEB, 0x00, 0x10, 0x07, 0xEB, 0xC0, 0x00, 0x00, 0xF5, 0xB8, 0x57, 0x10, 0x37, 0x3A, 0x46, ++0x00, 0x21, 0x08, 0xA8, 0xFF, 0xF7, 0xEE, 0xF9, 0x10, 0xB9, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xBD, 0xF8, 0x20, 0x00, ++0xBD, 0xF8, 0x24, 0x30, 0x01, 0x93, 0x00, 0x21, 0xBD, 0xF8, 0x22, 0xE0, 0x97, 0x4B, 0x98, 0x4A, 0x02, 0x94, 0x8C, 0x46, ++0x0D, 0x46, 0x83, 0x46, 0x0B, 0xE0, 0x98, 0x88, 0x01, 0x28, 0x00, 0xF0, 0xC1, 0x80, 0x03, 0x28, 0x00, 0xF0, 0xB4, 0x80, ++0x88, 0xB1, 0x03, 0xF5, 0xF6, 0x73, 0x93, 0x42, 0x14, 0xD0, 0xB3, 0xF8, 0x06, 0xA0, 0xDA, 0x45, 0xEF, 0xD1, 0x18, 0x89, ++0x70, 0x45, 0xEC, 0xD1, 0x58, 0x89, 0x01, 0x9C, 0xA0, 0x42, 0xE8, 0xD1, 0x02, 0x9C, 0x1D, 0x46, 0x10, 0xE0, 0x00, 0x2D, ++0x08, 0xBF, 0x1D, 0x46, 0x03, 0xF5, 0xF6, 0x73, 0x93, 0x42, 0xEA, 0xD1, 0x02, 0x9C, 0x00, 0x2D, 0x00, 0xF0, 0x42, 0x81, ++0x4F, 0xF4, 0xF6, 0x72, 0x00, 0x21, 0x28, 0x46, 0xCA, 0xF7, 0xDC, 0xF8, 0xAB, 0x88, 0x03, 0x2B, 0xBF, 0xD0, 0x03, 0x9B, ++0xBD, 0xF8, 0x20, 0x10, 0xBD, 0xF8, 0x22, 0x20, 0xC5, 0xF8, 0x0C, 0x80, 0x00, 0x2B, 0xBD, 0xF8, 0x24, 0x30, 0x6B, 0x81, ++0x08, 0xBF, 0x05, 0x20, 0x05, 0xF1, 0x1C, 0x03, 0x18, 0xBF, 0x04, 0x20, 0x02, 0x93, 0x04, 0xF1, 0x24, 0x08, 0x85, 0xF8, ++0x11, 0x90, 0xA8, 0x74, 0xE9, 0x80, 0x2A, 0x81, 0x18, 0x34, 0x05, 0xF1, 0x1B, 0x03, 0x14, 0xF8, 0x01, 0x2B, 0x03, 0xF8, ++0x01, 0x2F, 0x44, 0x45, 0xF9, 0xD1, 0x02, 0x9B, 0xA6, 0xF1, 0x24, 0x09, 0x03, 0xF1, 0x0C, 0x0B, 0xB9, 0xF1, 0x02, 0x0F, ++0x4F, 0xF0, 0x00, 0x03, 0xCD, 0xE9, 0x06, 0x33, 0x40, 0xF3, 0x56, 0x81, 0x4F, 0xF4, 0xE2, 0x7A, 0x3A, 0x46, 0x98, 0xF8, ++0x01, 0x40, 0x98, 0xF8, 0x00, 0x60, 0x98, 0xF8, 0x02, 0x70, 0x02, 0x34, 0x08, 0xF1, 0x02, 0x00, 0x00, 0x2E, 0x71, 0xD0, ++0x03, 0x2E, 0x7D, 0xD0, 0xA9, 0x7C, 0x05, 0x29, 0x00, 0xF2, 0x81, 0x80, 0x2A, 0x2E, 0x00, 0xF0, 0x8D, 0x80, 0x3D, 0x2E, ++0x00, 0xF0, 0x8D, 0x80, 0xC0, 0x2E, 0x00, 0xF0, 0x9A, 0x80, 0xFF, 0x2E, 0x02, 0xD1, 0x08, 0x2C, 0x00, 0xF2, 0xCD, 0x80, ++0x54, 0x45, 0x07, 0xDC, 0x39, 0x46, 0x30, 0x46, 0x01, 0x92, 0xFE, 0xF7, 0xD5, 0xFD, 0x01, 0x9A, 0x00, 0x28, 0x46, 0xD1, ++0xA0, 0x44, 0xA9, 0xEB, 0x04, 0x09, 0xB9, 0xF1, 0x02, 0x0F, 0xD0, 0xDC, 0xCA, 0xF5, 0xE8, 0x7A, 0x1F, 0xFA, 0x8A, 0xFA, ++0xAB, 0x7D, 0xA5, 0xF8, 0x1A, 0xA0, 0x00, 0x2B, 0x00, 0xF0, 0x94, 0x80, 0x04, 0x9B, 0x2B, 0x75, 0x2B, 0x7C, 0x06, 0x9A, ++0x04, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x03, 0x2A, 0x00, 0xF0, 0x05, 0x81, 0x02, 0x2A, 0x00, 0xF0, 0x04, 0x81, 0x03, 0x99, ++0x00, 0x29, 0x40, 0xF0, 0xC0, 0x80, 0x0E, 0x2B, 0x00, 0xF0, 0x14, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x07, 0x9B, ++0x01, 0x2B, 0x0C, 0xBF, 0x54, 0x23, 0x53, 0x23, 0x01, 0x22, 0xEB, 0x74, 0xAA, 0x80, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, ++0x00, 0x29, 0x41, 0xD0, 0x93, 0xF9, 0x14, 0xA0, 0x91, 0xF9, 0x14, 0x00, 0x82, 0x45, 0xB8, 0xBF, 0x19, 0x46, 0x42, 0xE7, ++0xBC, 0xF1, 0x00, 0x0F, 0x34, 0xD0, 0x93, 0xF9, 0x14, 0xA0, 0x9C, 0xF9, 0x14, 0x00, 0x82, 0x45, 0xB8, 0xBF, 0x9C, 0x46, ++0x37, 0xE7, 0x43, 0x46, 0xAB, 0xEB, 0x03, 0x00, 0xA0, 0x44, 0x19, 0x78, 0xC1, 0x54, 0x01, 0x33, 0x98, 0x45, 0xFA, 0xD1, ++0xA3, 0x44, 0xAA, 0xEB, 0x04, 0x0A, 0xAC, 0xE7, 0x02, 0x9B, 0x01, 0x92, 0xAB, 0xEB, 0x03, 0x01, 0x69, 0x75, 0xA8, 0x1D, ++0x41, 0x46, 0xFF, 0xF7, 0xF5, 0xF8, 0x01, 0x9A, 0x00, 0x28, 0x95, 0xD1, 0xA8, 0x80, 0x02, 0xE7, 0x02, 0x9B, 0xAB, 0xEB, ++0x03, 0x01, 0xA9, 0x75, 0x01, 0x78, 0x29, 0x74, 0x8C, 0xE7, 0x06, 0x29, 0x3F, 0xF4, 0x7F, 0xAF, 0x08, 0x29, 0x7F, 0xF6, ++0x7F, 0xAF, 0x0D, 0x29, 0x84, 0xD8, 0x7E, 0xE7, 0x00, 0x27, 0xEA, 0xE6, 0x9C, 0x46, 0x08, 0xE7, 0x19, 0x46, 0x06, 0xE7, ++0x06, 0x21, 0xA9, 0x74, 0x7A, 0xE7, 0x18, 0x2C, 0x7F, 0xF4, 0x78, 0xAF, 0x4F, 0xF0, 0x07, 0x03, 0xAB, 0x74, 0x98, 0xF8, ++0x03, 0x10, 0x11, 0xF0, 0x03, 0x03, 0x07, 0x93, 0x06, 0x9B, 0x18, 0xBF, 0x01, 0x23, 0x06, 0x93, 0x6A, 0xE7, 0x07, 0x2C, ++0x7F, 0xF4, 0x68, 0xAF, 0x4F, 0xF0, 0x09, 0x03, 0xAB, 0x74, 0x01, 0x78, 0x00, 0x29, 0x3F, 0xF4, 0x61, 0xAF, 0x01, 0x29, ++0x76, 0xD0, 0x02, 0x29, 0x00, 0xF0, 0x97, 0x80, 0x03, 0x29, 0x06, 0x9B, 0x08, 0xBF, 0x04, 0x23, 0x06, 0x93, 0x55, 0xE7, ++0x78, 0xEF, 0x17, 0x00, 0x88, 0x06, 0x18, 0x00, 0xAA, 0x88, 0x22, 0xB1, 0x95, 0xF9, 0x14, 0x20, 0x04, 0x99, 0x8A, 0x42, ++0x60, 0xDA, 0x04, 0x9A, 0x2A, 0x75, 0x03, 0x9A, 0x00, 0x2A, 0x42, 0xD1, 0x05, 0x99, 0xA1, 0xF6, 0x6C, 0x13, 0x48, 0x2B, ++0x6D, 0xD8, 0x40, 0xF6, 0xB4, 0x13, 0x99, 0x42, 0x00, 0xF0, 0x82, 0x80, 0x48, 0x4A, 0xA1, 0xF6, 0x67, 0x13, 0xA2, 0xFB, ++0x03, 0x23, 0xC3, 0xF3, 0x87, 0x03, 0x2B, 0x74, 0x4F, 0xE7, 0x24, 0x2F, 0x7F, 0xF4, 0x30, 0xAF, 0x09, 0x29, 0x11, 0xD0, ++0x0B, 0x2C, 0x0F, 0xD9, 0xD8, 0xF8, 0x03, 0x10, 0x4B, 0x04, 0x0B, 0xD5, 0x98, 0xF8, 0x09, 0x10, 0x41, 0xB1, 0x01, 0x29, ++0x71, 0xD0, 0x02, 0x29, 0x72, 0xD0, 0x03, 0x29, 0x06, 0x9B, 0x08, 0xBF, 0x04, 0x23, 0x06, 0x93, 0x4F, 0xF0, 0x0E, 0x03, ++0xAB, 0x74, 0x17, 0xE7, 0x89, 0xB3, 0x0D, 0x46, 0xBA, 0xE6, 0x30, 0x2B, 0x24, 0xD9, 0x40, 0x2B, 0x40, 0xD9, 0x90, 0x2B, ++0x4C, 0xD9, 0xA4, 0x2B, 0x59, 0xD8, 0x06, 0x9B, 0x00, 0x2B, 0x54, 0xD0, 0x0A, 0x23, 0x07, 0x9A, 0x01, 0x2A, 0x0C, 0xBF, ++0x74, 0x33, 0x75, 0x33, 0x38, 0xE7, 0x03, 0x9A, 0x01, 0x2A, 0xCA, 0xD1, 0x05, 0x9A, 0xA2, 0xF5, 0x9C, 0x51, 0xA1, 0xF1, ++0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, 0x4D, 0x7F, 0xC1, 0xD8, 0x26, 0x4A, 0xA1, 0xF1, 0x08, 0x03, 0xA2, 0xFB, 0x03, 0x23, ++0xC3, 0xF3, 0x87, 0x03, 0x2B, 0x74, 0x0A, 0xE7, 0x06, 0x9B, 0x23, 0xB3, 0x00, 0x23, 0xE0, 0xE7, 0x2B, 0x7C, 0x04, 0xE7, ++0x02, 0x23, 0x06, 0x93, 0xE4, 0xE6, 0xBC, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x50, 0xAE, 0x9C, 0xF9, 0x14, 0x30, 0x04, 0x9A, ++0x93, 0x42, 0xBF, 0xF6, 0x4A, 0xAE, 0x65, 0x46, 0x7E, 0xE6, 0x82, 0x23, 0x0C, 0xE7, 0x81, 0x23, 0x0A, 0xE7, 0x80, 0x23, ++0x08, 0xE7, 0x03, 0x9B, 0x2B, 0x74, 0xEC, 0xE6, 0x06, 0x9B, 0x8B, 0xB1, 0x03, 0x23, 0xC2, 0xE7, 0x4F, 0xF0, 0x0C, 0x0A, ++0xDC, 0xE6, 0x51, 0x23, 0xFC, 0xE6, 0x73, 0x23, 0xFA, 0xE6, 0x03, 0x23, 0x06, 0x93, 0xC1, 0xE6, 0x06, 0x9B, 0x43, 0xB1, ++0x06, 0x23, 0xB4, 0xE7, 0x52, 0x23, 0xF1, 0xE6, 0x76, 0x23, 0xEF, 0xE6, 0x0E, 0x23, 0x2B, 0x74, 0xD3, 0xE6, 0x79, 0x23, ++0xEA, 0xE6, 0x7C, 0x23, 0xE8, 0xE6, 0x7D, 0x23, 0xE6, 0xE6, 0x02, 0x23, 0x06, 0x93, 0x91, 0xE7, 0x03, 0x23, 0x06, 0x93, ++0x8E, 0xE7, 0x00, 0xBF, 0xCD, 0xCC, 0xCC, 0xCC, 0x2D, 0xE9, 0xF0, 0x48, 0xC1, 0xF3, 0x0A, 0x57, 0xA7, 0xF2, 0xFF, 0x34, ++0x13, 0x2C, 0x0B, 0x46, 0x0D, 0x46, 0x02, 0x46, 0x0F, 0xDC, 0x00, 0x2C, 0x2A, 0xDB, 0x1D, 0x49, 0x21, 0x41, 0x03, 0xEA, ++0x01, 0x00, 0x10, 0x43, 0x2F, 0xD0, 0x4F, 0xF4, 0x00, 0x23, 0x23, 0x41, 0x1D, 0x44, 0x25, 0xEA, 0x01, 0x05, 0x00, 0x23, ++0x25, 0xE0, 0x33, 0x2C, 0x07, 0xDD, 0xB4, 0xF5, 0x80, 0x6F, 0x22, 0xD1, 0x00, 0xF0, 0x2E, 0xF8, 0x02, 0x46, 0x0B, 0x46, ++0x1D, 0xE0, 0xA7, 0xF2, 0x13, 0x47, 0x4F, 0xF0, 0xFF, 0x31, 0x21, 0xFA, 0x07, 0xF7, 0x38, 0x42, 0x15, 0xD0, 0x01, 0x22, ++0xC4, 0xF1, 0x33, 0x03, 0x02, 0xFA, 0x03, 0xF3, 0xC3, 0x18, 0x28, 0xBF, 0xAD, 0x18, 0x23, 0xEA, 0x07, 0x03, 0x08, 0xE0, ++0x01, 0xF0, 0x00, 0x45, 0x01, 0x34, 0x04, 0xBF, 0x45, 0xF0, 0x7F, 0x55, 0x45, 0xF4, 0x40, 0x15, 0x00, 0x23, 0x1A, 0x46, ++0x2B, 0x46, 0x10, 0x46, 0x19, 0x46, 0xBD, 0xE8, 0xF0, 0x88, 0x00, 0xBF, 0xFF, 0xFF, 0x0F, 0x00, 0x81, 0xF0, 0x00, 0x41, ++0x02, 0xE0, 0x00, 0xBF, 0x83, 0xF0, 0x00, 0x43, 0x30, 0xB5, 0x4F, 0xEA, 0x41, 0x04, 0x4F, 0xEA, 0x43, 0x05, 0x94, 0xEA, ++0x05, 0x0F, 0x08, 0xBF, 0x90, 0xEA, 0x02, 0x0F, 0x1F, 0xBF, 0x54, 0xEA, 0x00, 0x0C, 0x55, 0xEA, 0x02, 0x0C, 0x7F, 0xEA, ++0x64, 0x5C, 0x7F, 0xEA, 0x65, 0x5C, 0x00, 0xF0, 0xE2, 0x80, 0x4F, 0xEA, 0x54, 0x54, 0xD4, 0xEB, 0x55, 0x55, 0xB8, 0xBF, ++0x6D, 0x42, 0x0C, 0xDD, 0x2C, 0x44, 0x80, 0xEA, 0x02, 0x02, 0x81, 0xEA, 0x03, 0x03, 0x82, 0xEA, 0x00, 0x00, 0x83, 0xEA, ++0x01, 0x01, 0x80, 0xEA, 0x02, 0x02, 0x81, 0xEA, 0x03, 0x03, 0x36, 0x2D, 0x88, 0xBF, 0x30, 0xBD, 0x11, 0xF0, 0x00, 0x4F, ++0x4F, 0xEA, 0x01, 0x31, 0x4F, 0xF4, 0x80, 0x1C, 0x4C, 0xEA, 0x11, 0x31, 0x02, 0xD0, 0x40, 0x42, 0x61, 0xEB, 0x41, 0x01, ++0x13, 0xF0, 0x00, 0x4F, 0x4F, 0xEA, 0x03, 0x33, 0x4C, 0xEA, 0x13, 0x33, 0x02, 0xD0, 0x52, 0x42, 0x63, 0xEB, 0x43, 0x03, ++0x94, 0xEA, 0x05, 0x0F, 0x00, 0xF0, 0xA7, 0x80, 0xA4, 0xF1, 0x01, 0x04, 0xD5, 0xF1, 0x20, 0x0E, 0x0D, 0xDB, 0x02, 0xFA, ++0x0E, 0xFC, 0x22, 0xFA, 0x05, 0xF2, 0x80, 0x18, 0x41, 0xF1, 0x00, 0x01, 0x03, 0xFA, 0x0E, 0xF2, 0x80, 0x18, 0x43, 0xFA, ++0x05, 0xF3, 0x59, 0x41, 0x0E, 0xE0, 0xA5, 0xF1, 0x20, 0x05, 0x0E, 0xF1, 0x20, 0x0E, 0x01, 0x2A, 0x03, 0xFA, 0x0E, 0xFC, ++0x28, 0xBF, 0x4C, 0xF0, 0x02, 0x0C, 0x43, 0xFA, 0x05, 0xF3, 0xC0, 0x18, 0x51, 0xEB, 0xE3, 0x71, 0x01, 0xF0, 0x00, 0x45, ++0x07, 0xD5, 0x4F, 0xF0, 0x00, 0x0E, 0xDC, 0xF1, 0x00, 0x0C, 0x7E, 0xEB, 0x00, 0x00, 0x6E, 0xEB, 0x01, 0x01, 0xB1, 0xF5, ++0x80, 0x1F, 0x1B, 0xD3, 0xB1, 0xF5, 0x00, 0x1F, 0x0C, 0xD3, 0x49, 0x08, 0x5F, 0xEA, 0x30, 0x00, 0x4F, 0xEA, 0x3C, 0x0C, ++0x04, 0xF1, 0x01, 0x04, 0x4F, 0xEA, 0x44, 0x52, 0x12, 0xF5, 0x80, 0x0F, 0x80, 0xF0, 0x9A, 0x80, 0xBC, 0xF1, 0x00, 0x4F, ++0x08, 0xBF, 0x5F, 0xEA, 0x50, 0x0C, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, 0x04, 0x51, 0x41, 0xEA, 0x05, 0x01, 0x30, 0xBD, ++0x5F, 0xEA, 0x4C, 0x0C, 0x40, 0x41, 0x41, 0xEB, 0x01, 0x01, 0x01, 0x3C, 0x28, 0xBF, 0xB1, 0xF5, 0x80, 0x1F, 0xE9, 0xD2, ++0x91, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x01, 0x46, 0x00, 0x20, 0xB1, 0xFA, 0x81, 0xF3, 0x08, 0xBF, 0x20, 0x33, 0xA3, 0xF1, ++0x0B, 0x03, 0xB3, 0xF1, 0x20, 0x02, 0x0C, 0xDA, 0x0C, 0x32, 0x08, 0xDD, 0x02, 0xF1, 0x14, 0x0C, 0xC2, 0xF1, 0x0C, 0x02, ++0x01, 0xFA, 0x0C, 0xF0, 0x21, 0xFA, 0x02, 0xF1, 0x0C, 0xE0, 0x02, 0xF1, 0x14, 0x02, 0xD8, 0xBF, 0xC2, 0xF1, 0x20, 0x0C, ++0x01, 0xFA, 0x02, 0xF1, 0x20, 0xFA, 0x0C, 0xFC, 0xDC, 0xBF, 0x41, 0xEA, 0x0C, 0x01, 0x90, 0x40, 0xE4, 0x1A, 0xA2, 0xBF, ++0x01, 0xEB, 0x04, 0x51, 0x29, 0x43, 0x30, 0xBD, 0x6F, 0xEA, 0x04, 0x04, 0x1F, 0x3C, 0x1C, 0xDA, 0x0C, 0x34, 0x0E, 0xDC, ++0x04, 0xF1, 0x14, 0x04, 0xC4, 0xF1, 0x20, 0x02, 0x20, 0xFA, 0x04, 0xF0, 0x01, 0xFA, 0x02, 0xF3, 0x40, 0xEA, 0x03, 0x00, ++0x21, 0xFA, 0x04, 0xF3, 0x45, 0xEA, 0x03, 0x01, 0x30, 0xBD, 0xC4, 0xF1, 0x0C, 0x04, 0xC4, 0xF1, 0x20, 0x02, 0x20, 0xFA, ++0x02, 0xF0, 0x01, 0xFA, 0x04, 0xF3, 0x40, 0xEA, 0x03, 0x00, 0x29, 0x46, 0x30, 0xBD, 0x21, 0xFA, 0x04, 0xF0, 0x29, 0x46, ++0x30, 0xBD, 0x94, 0xF0, 0x00, 0x0F, 0x83, 0xF4, 0x80, 0x13, 0x06, 0xBF, 0x81, 0xF4, 0x80, 0x11, 0x01, 0x34, 0x01, 0x3D, ++0x4E, 0xE7, 0x7F, 0xEA, 0x64, 0x5C, 0x18, 0xBF, 0x7F, 0xEA, 0x65, 0x5C, 0x29, 0xD0, 0x94, 0xEA, 0x05, 0x0F, 0x08, 0xBF, ++0x90, 0xEA, 0x02, 0x0F, 0x05, 0xD0, 0x54, 0xEA, 0x00, 0x0C, 0x04, 0xBF, 0x19, 0x46, 0x10, 0x46, 0x30, 0xBD, 0x91, 0xEA, ++0x03, 0x0F, 0x1E, 0xBF, 0x00, 0x21, 0x00, 0x20, 0x30, 0xBD, 0x5F, 0xEA, 0x54, 0x5C, 0x05, 0xD1, 0x40, 0x00, 0x49, 0x41, ++0x28, 0xBF, 0x41, 0xF0, 0x00, 0x41, 0x30, 0xBD, 0x14, 0xF5, 0x80, 0x04, 0x3C, 0xBF, 0x01, 0xF5, 0x80, 0x11, 0x30, 0xBD, ++0x01, 0xF0, 0x00, 0x45, 0x45, 0xF0, 0xFE, 0x41, 0x41, 0xF4, 0x70, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x30, 0xBD, 0x7F, 0xEA, ++0x64, 0x5C, 0x1A, 0xBF, 0x19, 0x46, 0x10, 0x46, 0x7F, 0xEA, 0x65, 0x5C, 0x1C, 0xBF, 0x0B, 0x46, 0x02, 0x46, 0x50, 0xEA, ++0x01, 0x34, 0x06, 0xBF, 0x52, 0xEA, 0x03, 0x35, 0x91, 0xEA, 0x03, 0x0F, 0x41, 0xF4, 0x00, 0x21, 0x30, 0xBD, 0x00, 0xBF, ++0x90, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x00, 0x21, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, 0x32, 0x04, ++0x4F, 0xF0, 0x00, 0x05, 0x4F, 0xF0, 0x00, 0x01, 0x50, 0xE7, 0x00, 0xBF, 0x90, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x00, 0x21, ++0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, 0x32, 0x04, 0x10, 0xF0, 0x00, 0x45, 0x48, 0xBF, 0x40, 0x42, ++0x4F, 0xF0, 0x00, 0x01, 0x3E, 0xE7, 0x00, 0xBF, 0x42, 0x00, 0x4F, 0xEA, 0xE2, 0x01, 0x4F, 0xEA, 0x31, 0x01, 0x4F, 0xEA, ++0x02, 0x70, 0x1F, 0xBF, 0x12, 0xF0, 0x7F, 0x43, 0x93, 0xF0, 0x7F, 0x4F, 0x81, 0xF0, 0x60, 0x51, 0x70, 0x47, 0x32, 0xF0, ++0x7F, 0x42, 0x08, 0xBF, 0x70, 0x47, 0x93, 0xF0, 0x7F, 0x4F, 0x04, 0xBF, 0x41, 0xF4, 0x00, 0x21, 0x70, 0x47, 0x30, 0xB5, ++0x4F, 0xF4, 0x60, 0x74, 0x01, 0xF0, 0x00, 0x45, 0x21, 0xF0, 0x00, 0x41, 0x1C, 0xE7, 0x00, 0xBF, 0x50, 0xEA, 0x01, 0x02, ++0x08, 0xBF, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF0, 0x00, 0x05, 0x0A, 0xE0, 0x50, 0xEA, 0x01, 0x02, 0x08, 0xBF, 0x70, 0x47, ++0x30, 0xB5, 0x11, 0xF0, 0x00, 0x45, 0x02, 0xD5, 0x40, 0x42, 0x61, 0xEB, 0x41, 0x01, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, ++0x32, 0x04, 0x5F, 0xEA, 0x91, 0x5C, 0x3F, 0xF4, 0xD8, 0xAE, 0x4F, 0xF0, 0x03, 0x02, 0x5F, 0xEA, 0xDC, 0x0C, 0x18, 0xBF, ++0x03, 0x32, 0x5F, 0xEA, 0xDC, 0x0C, 0x18, 0xBF, 0x03, 0x32, 0x02, 0xEB, 0xDC, 0x02, 0xC2, 0xF1, 0x20, 0x03, 0x00, 0xFA, ++0x03, 0xFC, 0x20, 0xFA, 0x02, 0xF0, 0x01, 0xFA, 0x03, 0xFE, 0x40, 0xEA, 0x0E, 0x00, 0x21, 0xFA, 0x02, 0xF1, 0x14, 0x44, ++0xBD, 0xE6, 0x00, 0xBF, 0x70, 0xB5, 0x4F, 0xF0, 0xFF, 0x0C, 0x4C, 0xF4, 0xE0, 0x6C, 0x1C, 0xEA, 0x11, 0x54, 0x1D, 0xBF, ++0x1C, 0xEA, 0x13, 0x55, 0x94, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, 0x0F, 0x00, 0xF0, 0xDE, 0xF8, 0x2C, 0x44, 0x81, 0xEA, ++0x03, 0x06, 0x21, 0xEA, 0x4C, 0x51, 0x23, 0xEA, 0x4C, 0x53, 0x50, 0xEA, 0x01, 0x35, 0x18, 0xBF, 0x52, 0xEA, 0x03, 0x35, ++0x41, 0xF4, 0x80, 0x11, 0x43, 0xF4, 0x80, 0x13, 0x38, 0xD0, 0xA0, 0xFB, 0x02, 0xCE, 0x4F, 0xF0, 0x00, 0x05, 0xE1, 0xFB, ++0x02, 0xE5, 0x06, 0xF0, 0x00, 0x42, 0xE0, 0xFB, 0x03, 0xE5, 0x4F, 0xF0, 0x00, 0x06, 0xE1, 0xFB, 0x03, 0x56, 0x9C, 0xF0, ++0x00, 0x0F, 0x18, 0xBF, 0x4E, 0xF0, 0x01, 0x0E, 0xA4, 0xF1, 0xFF, 0x04, 0xB6, 0xF5, 0x00, 0x7F, 0x64, 0xF5, 0x40, 0x74, ++0x04, 0xD2, 0x5F, 0xEA, 0x4E, 0x0E, 0x6D, 0x41, 0x46, 0xEB, 0x06, 0x06, 0x42, 0xEA, 0xC6, 0x21, 0x41, 0xEA, 0x55, 0x51, ++0x4F, 0xEA, 0xC5, 0x20, 0x40, 0xEA, 0x5E, 0x50, 0x4F, 0xEA, 0xCE, 0x2E, 0xB4, 0xF1, 0xFD, 0x0C, 0x88, 0xBF, 0xBC, 0xF5, ++0xE0, 0x6F, 0x1E, 0xD8, 0xBE, 0xF1, 0x00, 0x4F, 0x08, 0xBF, 0x5F, 0xEA, 0x50, 0x0E, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, ++0x04, 0x51, 0x70, 0xBD, 0x06, 0xF0, 0x00, 0x46, 0x46, 0xEA, 0x01, 0x01, 0x40, 0xEA, 0x02, 0x00, 0x81, 0xEA, 0x03, 0x01, ++0xB4, 0xEB, 0x5C, 0x04, 0xC2, 0xBF, 0xD4, 0xEB, 0x0C, 0x05, 0x41, 0xEA, 0x04, 0x51, 0x70, 0xBD, 0x41, 0xF4, 0x80, 0x11, ++0x4F, 0xF0, 0x00, 0x0E, 0x01, 0x3C, 0x00, 0xF3, 0xAB, 0x80, 0x14, 0xF1, 0x36, 0x0F, 0xDE, 0xBF, 0x00, 0x20, 0x01, 0xF0, ++0x00, 0x41, 0x70, 0xBD, 0xC4, 0xF1, 0x00, 0x04, 0x20, 0x3C, 0x35, 0xDA, 0x0C, 0x34, 0x1B, 0xDC, 0x04, 0xF1, 0x14, 0x04, ++0xC4, 0xF1, 0x20, 0x05, 0x00, 0xFA, 0x05, 0xF3, 0x20, 0xFA, 0x04, 0xF0, 0x01, 0xFA, 0x05, 0xF2, 0x40, 0xEA, 0x02, 0x00, ++0x01, 0xF0, 0x00, 0x42, 0x21, 0xF0, 0x00, 0x41, 0x10, 0xEB, 0xD3, 0x70, 0x21, 0xFA, 0x04, 0xF6, 0x42, 0xEB, 0x06, 0x01, ++0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, 0xC4, 0xF1, 0x0C, 0x04, 0xC4, 0xF1, 0x20, 0x05, ++0x00, 0xFA, 0x04, 0xF3, 0x20, 0xFA, 0x05, 0xF0, 0x01, 0xFA, 0x04, 0xF2, 0x40, 0xEA, 0x02, 0x00, 0x01, 0xF0, 0x00, 0x41, ++0x10, 0xEB, 0xD3, 0x70, 0x41, 0xF1, 0x00, 0x01, 0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, ++0xC4, 0xF1, 0x20, 0x05, 0x00, 0xFA, 0x05, 0xF2, 0x4E, 0xEA, 0x02, 0x0E, 0x20, 0xFA, 0x04, 0xF3, 0x01, 0xFA, 0x05, 0xF2, ++0x43, 0xEA, 0x02, 0x03, 0x21, 0xFA, 0x04, 0xF0, 0x01, 0xF0, 0x00, 0x41, 0x21, 0xFA, 0x04, 0xF2, 0x20, 0xEA, 0x02, 0x00, ++0x00, 0xEB, 0xD3, 0x70, 0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, 0x94, 0xF0, 0x00, 0x0F, ++0x0F, 0xD1, 0x01, 0xF0, 0x00, 0x46, 0x40, 0x00, 0x41, 0xEB, 0x01, 0x01, 0x11, 0xF4, 0x80, 0x1F, 0x08, 0xBF, 0x01, 0x3C, ++0xF7, 0xD0, 0x41, 0xEA, 0x06, 0x01, 0x95, 0xF0, 0x00, 0x0F, 0x18, 0xBF, 0x70, 0x47, 0x03, 0xF0, 0x00, 0x46, 0x52, 0x00, ++0x43, 0xEB, 0x03, 0x03, 0x13, 0xF4, 0x80, 0x1F, 0x08, 0xBF, 0x01, 0x3D, 0xF7, 0xD0, 0x43, 0xEA, 0x06, 0x03, 0x70, 0x47, ++0x94, 0xEA, 0x0C, 0x0F, 0x0C, 0xEA, 0x13, 0x55, 0x18, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, 0x0C, 0xD0, 0x50, 0xEA, 0x41, 0x06, ++0x18, 0xBF, 0x52, 0xEA, 0x43, 0x06, 0xD1, 0xD1, 0x81, 0xEA, 0x03, 0x01, 0x01, 0xF0, 0x00, 0x41, 0x4F, 0xF0, 0x00, 0x00, ++0x70, 0xBD, 0x50, 0xEA, 0x41, 0x06, 0x06, 0xBF, 0x10, 0x46, 0x19, 0x46, 0x52, 0xEA, 0x43, 0x06, 0x19, 0xD0, 0x94, 0xEA, ++0x0C, 0x0F, 0x02, 0xD1, 0x50, 0xEA, 0x01, 0x36, 0x13, 0xD1, 0x95, 0xEA, 0x0C, 0x0F, 0x05, 0xD1, 0x52, 0xEA, 0x03, 0x36, ++0x1C, 0xBF, 0x10, 0x46, 0x19, 0x46, 0x0A, 0xD1, 0x81, 0xEA, 0x03, 0x01, 0x01, 0xF0, 0x00, 0x41, 0x41, 0xF0, 0xFE, 0x41, ++0x41, 0xF4, 0x70, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0xBD, 0x41, 0xF0, 0xFE, 0x41, 0x41, 0xF4, 0x78, 0x01, 0x70, 0xBD, ++0x70, 0xB5, 0x4F, 0xF0, 0xFF, 0x0C, 0x4C, 0xF4, 0xE0, 0x6C, 0x1C, 0xEA, 0x11, 0x54, 0x1D, 0xBF, 0x1C, 0xEA, 0x13, 0x55, ++0x94, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, 0x0F, 0x00, 0xF0, 0xA7, 0xF8, 0xA4, 0xEB, 0x05, 0x04, 0x81, 0xEA, 0x03, 0x0E, ++0x52, 0xEA, 0x03, 0x35, 0x4F, 0xEA, 0x01, 0x31, 0x00, 0xF0, 0x88, 0x80, 0x4F, 0xEA, 0x03, 0x33, 0x4F, 0xF0, 0x80, 0x55, ++0x45, 0xEA, 0x13, 0x13, 0x43, 0xEA, 0x12, 0x63, 0x4F, 0xEA, 0x02, 0x22, 0x45, 0xEA, 0x11, 0x15, 0x45, 0xEA, 0x10, 0x65, ++0x4F, 0xEA, 0x00, 0x26, 0x0E, 0xF0, 0x00, 0x41, 0x9D, 0x42, 0x08, 0xBF, 0x96, 0x42, 0x44, 0xF1, 0xFD, 0x04, 0x04, 0xF5, ++0x40, 0x74, 0x02, 0xD2, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0x1A, 0x65, 0xEB, 0x03, 0x05, 0x5B, 0x08, 0x4F, 0xEA, ++0x32, 0x02, 0x4F, 0xF4, 0x80, 0x10, 0x4F, 0xF4, 0x00, 0x2C, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, ++0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x0C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, ++0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x5C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0xEB, ++0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x9C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, ++0x32, 0x02, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0xDC, 0x00, ++0x55, 0xEA, 0x06, 0x0E, 0x18, 0xD0, 0x4F, 0xEA, 0x05, 0x15, 0x45, 0xEA, 0x16, 0x75, 0x4F, 0xEA, 0x06, 0x16, 0x4F, 0xEA, ++0xC3, 0x03, 0x43, 0xEA, 0x52, 0x73, 0x4F, 0xEA, 0xC2, 0x02, 0x5F, 0xEA, 0x1C, 0x1C, 0xC0, 0xD1, 0x11, 0xF4, 0x80, 0x1F, ++0x0B, 0xD1, 0x41, 0xEA, 0x00, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x4F, 0xF0, 0x00, 0x4C, 0xB6, 0xE7, 0x11, 0xF4, 0x80, 0x1F, ++0x04, 0xBF, 0x01, 0x43, 0x00, 0x20, 0xB4, 0xF1, 0xFD, 0x0C, 0x88, 0xBF, 0xBC, 0xF5, 0xE0, 0x6F, 0x3F, 0xF6, 0xAF, 0xAE, ++0xB5, 0xEB, 0x03, 0x0C, 0x04, 0xBF, 0xB6, 0xEB, 0x02, 0x0C, 0x5F, 0xEA, 0x50, 0x0C, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, ++0x04, 0x51, 0x70, 0xBD, 0x0E, 0xF0, 0x00, 0x4E, 0x4E, 0xEA, 0x11, 0x31, 0x14, 0xEB, 0x5C, 0x04, 0xC2, 0xBF, 0xD4, 0xEB, ++0x0C, 0x05, 0x41, 0xEA, 0x04, 0x51, 0x70, 0xBD, 0x41, 0xF4, 0x80, 0x11, 0x4F, 0xF0, 0x00, 0x0E, 0x01, 0x3C, 0x90, 0xE6, ++0x45, 0xEA, 0x06, 0x0E, 0x8D, 0xE6, 0x0C, 0xEA, 0x13, 0x55, 0x94, 0xEA, 0x0C, 0x0F, 0x08, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, ++0x3F, 0xF4, 0x3B, 0xAF, 0x94, 0xEA, 0x0C, 0x0F, 0x0A, 0xD1, 0x50, 0xEA, 0x01, 0x34, 0x7F, 0xF4, 0x34, 0xAF, 0x95, 0xEA, ++0x0C, 0x0F, 0x7F, 0xF4, 0x25, 0xAF, 0x10, 0x46, 0x19, 0x46, 0x2C, 0xE7, 0x95, 0xEA, 0x0C, 0x0F, 0x06, 0xD1, 0x52, 0xEA, ++0x03, 0x35, 0x3F, 0xF4, 0xFD, 0xAE, 0x10, 0x46, 0x19, 0x46, 0x22, 0xE7, 0x50, 0xEA, 0x41, 0x06, 0x18, 0xBF, 0x52, 0xEA, ++0x43, 0x06, 0x7F, 0xF4, 0xC5, 0xAE, 0x50, 0xEA, 0x41, 0x04, 0x7F, 0xF4, 0x0D, 0xAF, 0x52, 0xEA, 0x43, 0x05, 0x7F, 0xF4, ++0xEB, 0xAE, 0x12, 0xE7, 0x4F, 0xF0, 0xFF, 0x3C, 0x06, 0xE0, 0x00, 0xBF, 0x4F, 0xF0, 0x01, 0x0C, 0x02, 0xE0, 0x00, 0xBF, ++0x4F, 0xF0, 0x01, 0x0C, 0x4D, 0xF8, 0x04, 0xCD, 0x4F, 0xEA, 0x41, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0x4F, 0xEA, 0x43, 0x0C, ++0x18, 0xBF, 0x7F, 0xEA, 0x6C, 0x5C, 0x1B, 0xD0, 0x01, 0xB0, 0x50, 0xEA, 0x41, 0x0C, 0x0C, 0xBF, 0x52, 0xEA, 0x43, 0x0C, ++0x91, 0xEA, 0x03, 0x0F, 0x02, 0xBF, 0x90, 0xEA, 0x02, 0x0F, 0x00, 0x20, 0x70, 0x47, 0x10, 0xF1, 0x00, 0x0F, 0x91, 0xEA, ++0x03, 0x0F, 0x58, 0xBF, 0x99, 0x42, 0x08, 0xBF, 0x90, 0x42, 0x2C, 0xBF, 0xD8, 0x17, 0x6F, 0xEA, 0xE3, 0x70, 0x40, 0xF0, ++0x01, 0x00, 0x70, 0x47, 0x4F, 0xEA, 0x41, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0x02, 0xD1, 0x50, 0xEA, 0x01, 0x3C, 0x07, 0xD1, ++0x4F, 0xEA, 0x43, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0xD6, 0xD1, 0x52, 0xEA, 0x03, 0x3C, 0xD3, 0xD0, 0x5D, 0xF8, 0x04, 0x0B, ++0x70, 0x47, 0x00, 0xBF, 0x84, 0x46, 0x10, 0x46, 0x62, 0x46, 0x8C, 0x46, 0x19, 0x46, 0x63, 0x46, 0x00, 0xE0, 0x00, 0xBF, ++0x01, 0xB5, 0xFF, 0xF7, 0xB7, 0xFF, 0x00, 0x28, 0x48, 0xBF, 0x10, 0xF1, 0x00, 0x0F, 0x01, 0xBD, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xF4, 0xFF, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xEA, 0xFF, 0x34, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xE0, 0xFF, 0x94, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xCE, 0xFF, 0x94, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, ++0xFF, 0xF7, 0xC4, 0xFF, 0x34, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4A, 0x00, 0x11, 0xD2, ++0x12, 0xF5, 0x00, 0x12, 0x11, 0xD2, 0x0D, 0xD5, 0x6F, 0xF4, 0x78, 0x73, 0xB3, 0xEB, 0x62, 0x52, 0x0E, 0xD4, 0x4F, 0xEA, ++0xC1, 0x23, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xEA, 0x50, 0x53, 0x23, 0xFA, 0x02, 0xF0, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, ++0x70, 0x47, 0x50, 0xEA, 0x01, 0x30, 0x02, 0xD1, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, ++0x4F, 0xEA, 0x41, 0x02, 0xB2, 0xF1, 0xE0, 0x43, 0x24, 0xBF, 0xB3, 0xF5, 0x00, 0x1C, 0xDC, 0xF1, 0xFE, 0x5C, 0x0D, 0xD9, ++0x01, 0xF0, 0x00, 0x4C, 0x4F, 0xEA, 0xC0, 0x02, 0x4C, 0xEA, 0x50, 0x70, 0xB2, 0xF1, 0x00, 0x4F, 0x40, 0xEB, 0x83, 0x00, ++0x08, 0xBF, 0x20, 0xF0, 0x01, 0x00, 0x70, 0x47, 0x11, 0xF0, 0x80, 0x4F, 0x21, 0xD1, 0x13, 0xF1, 0x38, 0x72, 0xBC, 0xBF, ++0x01, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x41, 0xF4, 0x80, 0x11, 0x4F, 0xEA, 0x52, 0x52, 0xC2, 0xF1, 0x18, 0x02, 0xC2, 0xF1, ++0x20, 0x0C, 0x10, 0xFA, 0x0C, 0xF3, 0x20, 0xFA, 0x02, 0xF0, 0x18, 0xBF, 0x40, 0xF0, 0x01, 0x00, 0x4F, 0xEA, 0xC1, 0x23, ++0x4F, 0xEA, 0xD3, 0x23, 0x03, 0xFA, 0x0C, 0xFC, 0x40, 0xEA, 0x0C, 0x00, 0x23, 0xFA, 0x02, 0xF3, 0x4F, 0xEA, 0x43, 0x03, ++0xCC, 0xE7, 0x7F, 0xEA, 0x62, 0x53, 0x07, 0xD1, 0x50, 0xEA, 0x01, 0x33, 0x1E, 0xBF, 0x4F, 0xF0, 0xFE, 0x40, 0x40, 0xF4, ++0x40, 0x00, 0x70, 0x47, 0x01, 0xF0, 0x00, 0x40, 0x40, 0xF0, 0xFE, 0x40, 0x40, 0xF4, 0x00, 0x00, 0x70, 0x47, 0x00, 0xBF, ++0x53, 0xB9, 0x4A, 0xB9, 0x00, 0x29, 0x08, 0xBF, 0x00, 0x28, 0x1C, 0xBF, 0x4F, 0xF0, 0xFF, 0x31, 0x4F, 0xF0, 0xFF, 0x30, ++0x00, 0xF0, 0x6C, 0xB9, 0xAD, 0xF1, 0x08, 0x0C, 0x6D, 0xE9, 0x04, 0xCE, 0x00, 0xF0, 0x06, 0xF8, 0xDD, 0xF8, 0x04, 0xE0, ++0xDD, 0xE9, 0x02, 0x23, 0x04, 0xB0, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, 0x08, 0x9E, 0x0D, 0x46, 0x04, 0x46, 0x8E, 0x46, ++0x00, 0x2B, 0x40, 0xF0, 0x82, 0x80, 0x8A, 0x42, 0x17, 0x46, 0x46, 0xD9, 0xB2, 0xFA, 0x82, 0xF2, 0x4A, 0xB1, 0xC2, 0xF1, ++0x20, 0x01, 0x05, 0xFA, 0x02, 0xF3, 0x20, 0xFA, 0x01, 0xF1, 0x97, 0x40, 0x41, 0xEA, 0x03, 0x0E, 0x94, 0x40, 0x4F, 0xEA, ++0x17, 0x48, 0x23, 0x0C, 0xBE, 0xFB, 0xF8, 0xFC, 0xB9, 0xB2, 0x08, 0xFB, 0x1C, 0xEE, 0x43, 0xEA, 0x0E, 0x43, 0x0C, 0xFB, ++0x01, 0xF0, 0x98, 0x42, 0x0A, 0xD9, 0xFB, 0x18, 0x0C, 0xF1, 0xFF, 0x35, 0x80, 0xF0, 0x16, 0x81, 0x98, 0x42, 0x40, 0xF2, ++0x13, 0x81, 0xAC, 0xF1, 0x02, 0x0C, 0x3B, 0x44, 0x1B, 0x1A, 0xA4, 0xB2, 0xB3, 0xFB, 0xF8, 0xF0, 0x08, 0xFB, 0x10, 0x33, ++0x44, 0xEA, 0x03, 0x44, 0x00, 0xFB, 0x01, 0xF1, 0xA1, 0x42, 0x09, 0xD9, 0x3C, 0x19, 0x00, 0xF1, 0xFF, 0x33, 0x80, 0xF0, ++0x01, 0x81, 0xA1, 0x42, 0x40, 0xF2, 0xFE, 0x80, 0x02, 0x38, 0x3C, 0x44, 0x64, 0x1A, 0x40, 0xEA, 0x0C, 0x40, 0x00, 0x21, ++0x1E, 0xB1, 0xD4, 0x40, 0x00, 0x23, 0xC6, 0xE9, 0x00, 0x43, 0xBD, 0xE8, 0xF0, 0x87, 0x02, 0xB9, 0xFF, 0xDE, 0xB2, 0xFA, ++0x82, 0xF2, 0x00, 0x2A, 0x4F, 0xD1, 0xCB, 0x1B, 0x4F, 0xEA, 0x17, 0x4E, 0x1F, 0xFA, 0x87, 0xF8, 0x01, 0x21, 0xB3, 0xFB, ++0xFE, 0xFC, 0x25, 0x0C, 0x0E, 0xFB, 0x1C, 0x33, 0x45, 0xEA, 0x03, 0x45, 0x08, 0xFB, 0x0C, 0xF3, 0xAB, 0x42, 0x07, 0xD9, ++0x7D, 0x19, 0x0C, 0xF1, 0xFF, 0x30, 0x02, 0xD2, 0xAB, 0x42, 0x00, 0xF2, 0xE7, 0x80, 0x84, 0x46, 0xED, 0x1A, 0xA3, 0xB2, ++0xB5, 0xFB, 0xFE, 0xF0, 0x0E, 0xFB, 0x10, 0x55, 0x43, 0xEA, 0x05, 0x44, 0x08, 0xFB, 0x00, 0xF8, 0xA0, 0x45, 0x07, 0xD9, ++0x3C, 0x19, 0x00, 0xF1, 0xFF, 0x33, 0x02, 0xD2, 0xA0, 0x45, 0x00, 0xF2, 0xD7, 0x80, 0x18, 0x46, 0xA4, 0xEB, 0x08, 0x04, ++0x40, 0xEA, 0x0C, 0x40, 0xC0, 0xE7, 0x8B, 0x42, 0x08, 0xD9, 0x00, 0x2E, 0x00, 0xF0, 0xAF, 0x80, 0x00, 0x21, 0xC6, 0xE9, ++0x00, 0x05, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xB3, 0xFA, 0x83, 0xF1, 0x00, 0x29, 0x4B, 0xD1, 0xAB, 0x42, 0x02, 0xD3, ++0x82, 0x42, 0x00, 0xF2, 0xB7, 0x80, 0x84, 0x1A, 0x65, 0xEB, 0x03, 0x03, 0x01, 0x20, 0x9E, 0x46, 0x00, 0x2E, 0xAA, 0xD0, ++0xC6, 0xE9, 0x00, 0x4E, 0xA7, 0xE7, 0xC2, 0xF1, 0x20, 0x0C, 0x01, 0xFA, 0x02, 0xF3, 0x97, 0x40, 0x20, 0xFA, 0x0C, 0xF0, ++0x4F, 0xEA, 0x17, 0x4E, 0x21, 0xFA, 0x0C, 0xFC, 0x18, 0x43, 0xBC, 0xFB, 0xFE, 0xF1, 0x05, 0x0C, 0x0E, 0xFB, 0x11, 0xCC, ++0x1F, 0xFA, 0x87, 0xF8, 0x45, 0xEA, 0x0C, 0x45, 0x01, 0xFB, 0x08, 0xF3, 0xAB, 0x42, 0x04, 0xFA, 0x02, 0xF4, 0x09, 0xD9, ++0x7D, 0x19, 0x01, 0xF1, 0xFF, 0x3C, 0x80, 0xF0, 0x8B, 0x80, 0xAB, 0x42, 0x40, 0xF2, 0x88, 0x80, 0x02, 0x39, 0x3D, 0x44, ++0xEB, 0x1A, 0x85, 0xB2, 0xB3, 0xFB, 0xFE, 0xF0, 0x0E, 0xFB, 0x10, 0x33, 0x45, 0xEA, 0x03, 0x45, 0x00, 0xFB, 0x08, 0xF3, ++0xAB, 0x42, 0x07, 0xD9, 0x7D, 0x19, 0x00, 0xF1, 0xFF, 0x3C, 0x71, 0xD2, 0xAB, 0x42, 0x6F, 0xD9, 0x02, 0x38, 0x3D, 0x44, ++0xEB, 0x1A, 0x40, 0xEA, 0x01, 0x41, 0x78, 0xE7, 0xC1, 0xF1, 0x20, 0x0C, 0x8B, 0x40, 0x22, 0xFA, 0x0C, 0xF7, 0x1F, 0x43, ++0x20, 0xFA, 0x0C, 0xF4, 0x05, 0xFA, 0x01, 0xF3, 0x4F, 0xEA, 0x17, 0x4E, 0x25, 0xFA, 0x0C, 0xF5, 0x1C, 0x43, 0x23, 0x0C, ++0xB5, 0xFB, 0xFE, 0xF9, 0x1F, 0xFA, 0x87, 0xF8, 0x0E, 0xFB, 0x19, 0x55, 0x43, 0xEA, 0x05, 0x45, 0x09, 0xFB, 0x08, 0xFA, ++0xAA, 0x45, 0x02, 0xFA, 0x01, 0xF2, 0x00, 0xFA, 0x01, 0xF3, 0x08, 0xD9, 0x7D, 0x19, 0x09, 0xF1, 0xFF, 0x30, 0x47, 0xD2, ++0xAA, 0x45, 0x45, 0xD9, 0xA9, 0xF1, 0x02, 0x09, 0x3D, 0x44, 0xA5, 0xEB, 0x0A, 0x05, 0xA4, 0xB2, 0xB5, 0xFB, 0xFE, 0xF0, ++0x0E, 0xFB, 0x10, 0x55, 0x44, 0xEA, 0x05, 0x44, 0x00, 0xFB, 0x08, 0xF8, 0xA0, 0x45, 0x07, 0xD9, 0x3C, 0x19, 0x00, 0xF1, ++0xFF, 0x35, 0x2D, 0xD2, 0xA0, 0x45, 0x2B, 0xD9, 0x02, 0x38, 0x3C, 0x44, 0x40, 0xEA, 0x09, 0x40, 0xA4, 0xEB, 0x08, 0x04, ++0xA0, 0xFB, 0x02, 0x89, 0x4C, 0x45, 0xC6, 0x46, 0x4D, 0x46, 0x19, 0xD3, 0x16, 0xD0, 0x5E, 0xB1, 0xB3, 0xEB, 0x0E, 0x02, ++0x64, 0xEB, 0x05, 0x04, 0x04, 0xFA, 0x0C, 0xFC, 0xCA, 0x40, 0x4C, 0xEA, 0x02, 0x02, 0xCC, 0x40, 0xC6, 0xE9, 0x00, 0x24, ++0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x87, 0x31, 0x46, 0x30, 0x46, 0x0E, 0xE7, 0xAC, 0x46, 0xED, 0xE6, 0x18, 0x46, 0x01, 0xE7, ++0x43, 0x45, 0xE6, 0xD2, 0xB8, 0xEB, 0x02, 0x0E, 0x69, 0xEB, 0x07, 0x05, 0x01, 0x38, 0xE0, 0xE7, 0x28, 0x46, 0xD3, 0xE7, ++0x60, 0x46, 0x8F, 0xE7, 0x81, 0x46, 0xBA, 0xE7, 0x61, 0x46, 0x77, 0xE7, 0x08, 0x46, 0x4B, 0xE7, 0xAC, 0xF1, 0x02, 0x0C, ++0x3D, 0x44, 0x15, 0xE7, 0x02, 0x38, 0x3C, 0x44, 0x26, 0xE7, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x28, 0xB8, 0xBF, ++0x40, 0x42, 0x70, 0x47, 0x03, 0x2A, 0x70, 0xB4, 0x12, 0xD9, 0x40, 0xEA, 0x01, 0x05, 0xAD, 0x07, 0x04, 0x46, 0x0B, 0x46, ++0x1E, 0xD1, 0x19, 0x46, 0x20, 0x46, 0x53, 0xF8, 0x04, 0x5B, 0x54, 0xF8, 0x04, 0x6B, 0xAE, 0x42, 0x16, 0xD1, 0x04, 0x3A, ++0x03, 0x2A, 0x20, 0x46, 0x19, 0x46, 0xF2, 0xD8, 0x56, 0x1E, 0xA2, 0xB1, 0x01, 0x39, 0x44, 0x1E, 0x01, 0xE0, 0xC3, 0x18, ++0x0C, 0xD0, 0x14, 0xF8, 0x01, 0x5F, 0x11, 0xF8, 0x01, 0x2F, 0x95, 0x42, 0xA6, 0xEB, 0x04, 0x03, 0xF5, 0xD0, 0xA8, 0x1A, ++0x70, 0xBC, 0x70, 0x47, 0x56, 0x1E, 0xED, 0xE7, 0x18, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x10, 0x46, 0xF6, 0xE7, 0x00, 0xBF, ++0x84, 0x46, 0x41, 0xEA, 0x00, 0x03, 0x13, 0xF0, 0x03, 0x03, 0x6D, 0xD1, 0x40, 0x3A, 0x41, 0xD3, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x40, 0x3A, 0xBD, 0xD2, 0x30, 0x32, 0x11, 0xD3, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, ++0x40, 0xF8, 0x04, 0x3B, 0x10, 0x3A, 0xED, 0xD2, 0x0C, 0x32, 0x05, 0xD3, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, ++0x04, 0x3A, 0xF9, 0xD2, 0x04, 0x32, 0x08, 0xD0, 0xD2, 0x07, 0x1C, 0xBF, 0x11, 0xF8, 0x01, 0x3B, 0x00, 0xF8, 0x01, 0x3B, ++0x01, 0xD3, 0x0B, 0x88, 0x03, 0x80, 0x60, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x08, 0x2A, 0x13, 0xD3, 0x8B, 0x07, 0x8D, 0xD0, ++0x10, 0xF0, 0x03, 0x03, 0x8A, 0xD0, 0xC3, 0xF1, 0x04, 0x03, 0xD2, 0x1A, 0xDB, 0x07, 0x1C, 0xBF, 0x11, 0xF8, 0x01, 0x3B, ++0x00, 0xF8, 0x01, 0x3B, 0x80, 0xD3, 0x31, 0xF8, 0x02, 0x3B, 0x20, 0xF8, 0x02, 0x3B, 0x7B, 0xE7, 0x04, 0x3A, 0xD9, 0xD3, ++0x01, 0x3A, 0x11, 0xF8, 0x01, 0x3B, 0x00, 0xF8, 0x01, 0x3B, 0xF9, 0xD2, 0x0B, 0x78, 0x03, 0x70, 0x4B, 0x78, 0x43, 0x70, ++0x8B, 0x78, 0x83, 0x70, 0x60, 0x46, 0x70, 0x47, 0x88, 0x42, 0xF0, 0xB4, 0x0D, 0xD9, 0x8B, 0x18, 0x83, 0x42, 0x0A, 0xD9, ++0x84, 0x18, 0x32, 0xB1, 0x22, 0x46, 0x13, 0xF8, 0x01, 0x4D, 0x02, 0xF8, 0x01, 0x4D, 0x99, 0x42, 0xF9, 0xD1, 0xF0, 0xBC, ++0x70, 0x47, 0x0F, 0x2A, 0x0E, 0xD8, 0x03, 0x46, 0x54, 0x1E, 0x00, 0x2A, 0xF7, 0xD0, 0x01, 0x34, 0x0C, 0x44, 0x01, 0x3B, ++0x11, 0xF8, 0x01, 0x2B, 0x03, 0xF8, 0x01, 0x2F, 0xA1, 0x42, 0xF9, 0xD1, 0xF0, 0xBC, 0x70, 0x47, 0x40, 0xEA, 0x01, 0x03, ++0x9B, 0x07, 0x3F, 0xD1, 0xA2, 0xF1, 0x10, 0x03, 0x23, 0xF0, 0x0F, 0x04, 0x01, 0xF1, 0x20, 0x07, 0x27, 0x44, 0x1B, 0x09, ++0x01, 0xF1, 0x10, 0x04, 0x00, 0xF1, 0x10, 0x05, 0x54, 0xF8, 0x10, 0x6C, 0x45, 0xF8, 0x10, 0x6C, 0x54, 0xF8, 0x0C, 0x6C, ++0x45, 0xF8, 0x0C, 0x6C, 0x54, 0xF8, 0x08, 0x6C, 0x45, 0xF8, 0x08, 0x6C, 0x54, 0xF8, 0x04, 0x6C, 0x45, 0xF8, 0x04, 0x6C, ++0x10, 0x34, 0xBC, 0x42, 0x05, 0xF1, 0x10, 0x05, 0xEA, 0xD1, 0x01, 0x33, 0x12, 0xF0, 0x0C, 0x0F, 0x01, 0xEB, 0x03, 0x11, ++0x02, 0xF0, 0x0F, 0x04, 0x00, 0xEB, 0x03, 0x13, 0x17, 0xD0, 0x04, 0x3C, 0x24, 0xF0, 0x03, 0x0C, 0xA5, 0x08, 0x9C, 0x44, ++0x1C, 0x1F, 0x0E, 0x46, 0x56, 0xF8, 0x04, 0x7B, 0x44, 0xF8, 0x04, 0x7F, 0x64, 0x45, 0xF9, 0xD1, 0x6C, 0x1C, 0x03, 0xEB, ++0x84, 0x03, 0x01, 0xEB, 0x84, 0x01, 0x02, 0xF0, 0x03, 0x02, 0xAD, 0xE7, 0x54, 0x1E, 0x03, 0x46, 0xAD, 0xE7, 0x22, 0x46, ++0xA8, 0xE7, 0x00, 0xBF, 0x0B, 0x4B, 0x0C, 0x48, 0x19, 0x68, 0xD1, 0xE9, 0x2A, 0x23, 0x10, 0xB4, 0x0A, 0x4C, 0x00, 0xFB, ++0x02, 0xF0, 0x04, 0xFB, 0x03, 0x00, 0xA2, 0xFB, 0x04, 0x34, 0x04, 0x44, 0x5A, 0x1C, 0x44, 0xF1, 0x00, 0x00, 0xC1, 0xE9, ++0x2A, 0x20, 0x10, 0xBC, 0x20, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x80, 0x01, 0x17, 0x00, 0x2D, 0xF4, 0x51, 0x58, ++0x2D, 0x7F, 0x95, 0x4C, 0x11, 0xF0, 0xFF, 0x01, 0x03, 0x46, 0x44, 0xD0, 0x82, 0x07, 0x32, 0xD1, 0x70, 0xB4, 0x04, 0x68, ++0x41, 0xEA, 0x01, 0x26, 0x46, 0xEA, 0x06, 0x46, 0x86, 0xEA, 0x04, 0x05, 0xA5, 0xF1, 0x01, 0x33, 0xA4, 0xF1, 0x01, 0x32, ++0x23, 0xEA, 0x05, 0x03, 0x22, 0xEA, 0x04, 0x02, 0x13, 0x43, 0x13, 0xF0, 0x80, 0x3F, 0x0F, 0xD1, 0x50, 0xF8, 0x04, 0x4F, ++0x84, 0xEA, 0x06, 0x05, 0xA5, 0xF1, 0x01, 0x32, 0xA4, 0xF1, 0x01, 0x33, 0x22, 0xEA, 0x05, 0x02, 0x23, 0xEA, 0x04, 0x03, ++0x13, 0x43, 0x13, 0xF0, 0x80, 0x3F, 0xEF, 0xD0, 0x03, 0x78, 0x23, 0xB9, 0x36, 0xE0, 0x10, 0xF8, 0x01, 0x3F, 0x00, 0x2B, ++0x32, 0xD0, 0x99, 0x42, 0xF9, 0xD1, 0x30, 0xE0, 0x8A, 0x42, 0x11, 0xD0, 0x9A, 0x07, 0x18, 0x46, 0xCC, 0xD0, 0x18, 0x46, ++0x13, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0xF5, 0xD1, 0x10, 0x46, 0x70, 0x47, 0x99, 0x07, 0x18, 0x46, 0x07, 0xD0, 0x18, 0x46, ++0x01, 0x33, 0x02, 0x78, 0x00, 0x2A, 0xF7, 0xD1, 0x70, 0x47, 0x82, 0x07, 0xF7, 0xD1, 0x02, 0x68, 0xA2, 0xF1, 0x01, 0x33, ++0x23, 0xEA, 0x02, 0x03, 0x13, 0xF0, 0x80, 0x3F, 0x08, 0xD1, 0x50, 0xF8, 0x04, 0x2F, 0xA2, 0xF1, 0x01, 0x33, 0x23, 0xEA, ++0x02, 0x03, 0x13, 0xF0, 0x80, 0x3F, 0xF6, 0xD0, 0x03, 0x78, 0x00, 0x2B, 0xE8, 0xD0, 0x10, 0xF8, 0x01, 0x3F, 0x00, 0x2B, ++0xFB, 0xD1, 0x70, 0x47, 0x18, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x80, 0xEA, 0x01, 0x02, 0x84, 0x46, 0x12, 0xF0, ++0x03, 0x0F, 0x4F, 0xD1, 0x11, 0xF0, 0x03, 0x0F, 0x32, 0xD1, 0x4D, 0xF8, 0x04, 0x4D, 0x11, 0xF0, 0x04, 0x0F, 0x51, 0xF8, ++0x04, 0x3B, 0x0B, 0xD0, 0xA3, 0xF1, 0x01, 0x32, 0x9A, 0x43, 0x12, 0xF0, 0x80, 0x3F, 0x04, 0xBF, 0x4C, 0xF8, 0x04, 0x3B, ++0x51, 0xF8, 0x04, 0x3B, 0x16, 0xD1, 0x00, 0xBF, 0x51, 0xF8, 0x04, 0x4B, 0xA3, 0xF1, 0x01, 0x32, 0x9A, 0x43, 0x12, 0xF0, ++0x80, 0x3F, 0xA4, 0xF1, 0x01, 0x32, 0x0B, 0xD1, 0x4C, 0xF8, 0x04, 0x3B, 0xA2, 0x43, 0x12, 0xF0, 0x80, 0x3F, 0x04, 0xBF, ++0x51, 0xF8, 0x04, 0x3B, 0x4C, 0xF8, 0x04, 0x4B, 0xEA, 0xD0, 0x23, 0x46, 0x0C, 0xF8, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x0F, ++0x4F, 0xEA, 0x33, 0x23, 0xF8, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x11, 0xF0, 0x01, 0x0F, 0x06, 0xD0, 0x11, 0xF8, ++0x01, 0x2B, 0x0C, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0x08, 0xBF, 0x70, 0x47, 0x11, 0xF0, 0x02, 0x0F, 0xBF, 0xD0, 0x31, 0xF8, ++0x02, 0x2B, 0x12, 0xF0, 0xFF, 0x0F, 0x16, 0xBF, 0x2C, 0xF8, 0x02, 0x2B, 0x8C, 0xF8, 0x00, 0x20, 0x12, 0xF4, 0x7F, 0x4F, ++0xB3, 0xD1, 0x70, 0x47, 0x11, 0xF8, 0x01, 0x2B, 0x0C, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0xF9, 0xD1, 0x70, 0x47, 0x00, 0xBF, ++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, 0x00, 0x00, 0x00, 0x00, 0x90, 0xF8, 0x00, 0xF0, ++0x6D, 0xE9, 0x02, 0x45, 0x20, 0xF0, 0x07, 0x01, 0x6F, 0xF0, 0x00, 0x0C, 0x10, 0xF0, 0x07, 0x04, 0x91, 0xF8, 0x20, 0xF0, ++0x40, 0xF0, 0x49, 0x80, 0x4F, 0xF0, 0x00, 0x04, 0x6F, 0xF0, 0x07, 0x00, 0xD1, 0xE9, 0x00, 0x23, 0x91, 0xF8, 0x40, 0xF0, ++0x00, 0xF1, 0x08, 0x00, 0x82, 0xFA, 0x4C, 0xF2, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, ++0x4B, 0xBB, 0xD1, 0xE9, 0x02, 0x23, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, ++0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, 0xE3, 0xB9, 0xD1, 0xE9, 0x04, 0x23, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, ++0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, 0x7B, 0xB9, 0xD1, 0xE9, 0x06, 0x23, 0x01, 0xF1, ++0x20, 0x01, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, ++0x8C, 0xF3, 0x00, 0x2B, 0xC6, 0xD0, 0x00, 0x2A, 0x04, 0xBF, 0x04, 0x30, 0x1A, 0x46, 0x12, 0xBA, 0xB2, 0xFA, 0x82, 0xF2, ++0xFD, 0xE8, 0x02, 0x45, 0x00, 0xEB, 0xD2, 0x00, 0x70, 0x47, 0xD1, 0xE9, 0x00, 0x23, 0x04, 0xF0, 0x03, 0x05, 0xC4, 0xF1, ++0x00, 0x00, 0x4F, 0xEA, 0xC5, 0x05, 0x14, 0xF0, 0x04, 0x0F, 0x91, 0xF8, 0x40, 0xF0, 0x0C, 0xFA, 0x05, 0xF5, 0x62, 0xEA, ++0x05, 0x02, 0x1C, 0xBF, 0x63, 0xEA, 0x05, 0x03, 0x62, 0x46, 0x4F, 0xF0, 0x00, 0x04, 0xA9, 0xE7, 0x9A, 0xB3, 0xF0, 0xB4, ++0x40, 0xEA, 0x01, 0x05, 0xAD, 0x07, 0x04, 0x46, 0x03, 0x46, 0x08, 0x46, 0x28, 0xD0, 0x20, 0x78, 0x0E, 0x78, 0x86, 0x42, ++0x29, 0xD1, 0x01, 0x2A, 0x2A, 0xD0, 0x25, 0x46, 0x50, 0xB1, 0x15, 0xF8, 0x01, 0x0F, 0x11, 0xF8, 0x01, 0x6F, 0xEB, 0x43, ++0xB0, 0x42, 0x13, 0x44, 0x1D, 0xD1, 0xE3, 0x18, 0xF4, 0xD1, 0x18, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0x07, 0x68, 0x1C, 0x46, ++0x53, 0xF8, 0x04, 0x5B, 0xA5, 0xF1, 0x01, 0x36, 0xBD, 0x42, 0x01, 0x46, 0x26, 0xEA, 0x05, 0x06, 0x00, 0xF1, 0x04, 0x00, ++0xDD, 0xD1, 0x04, 0x3A, 0x1C, 0x46, 0x01, 0x46, 0x0A, 0xD0, 0x16, 0xF0, 0x80, 0x3F, 0x07, 0xD1, 0x03, 0x2A, 0xE9, 0xD8, ++0xD3, 0xE7, 0x10, 0x46, 0x70, 0x47, 0x80, 0x1B, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0x20, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0xBF, ++0x6D, 0x65, 0x6D, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x6C, 0x61, 0x70, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x6B, 0x5F, 0x73, 0x74, ++0x61, 0x72, 0x74, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x5F, 0x65, 0x6E, 0x64, 0x3D, 0x25, 0x78, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x6D, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x6C, 0x61, 0x70, 0x73, 0x3A, 0x20, 0x73, 0x74, ++0x6B, 0x5F, 0x65, 0x6E, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x3D, ++0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, ++0x6D, 0x61, 0x69, 0x6E, 0x21, 0x0D, 0x0A, 0x00, 0x10, 0x14, 0x08, 0x12, 0x3C, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, ++0x08, 0x12, 0xC7, 0x11, 0x10, 0x14, 0x08, 0x12, 0x3C, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, 0x08, 0x12, 0x45, 0x11, ++0x08, 0x12, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0x03, 0x11, 0x08, 0x12, 0x04, 0x11, ++0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0xC2, 0x10, 0x08, 0x12, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, ++0x07, 0x12, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x86, 0x11, 0xC3, 0x10, ++0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x86, 0x11, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, ++0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, 0x08, 0x12, 0x04, 0x11, ++0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, 0x08, 0x12, 0x03, 0x11, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, ++0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x8A, 0x12, 0x0C, 0x13, ++0x04, 0x11, 0x03, 0x11, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x8A, 0x12, 0x86, 0x11, 0x04, 0x11, 0x03, 0x11, ++0x9D, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x62, 0x61, 0x6E, 0x64, 0x3D, 0x25, 0x64, 0x20, 0x66, 0x72, 0x65, 0x71, 0x3D, 0x25, ++0x64, 0x20, 0x66, 0x72, 0x65, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x74, 0x79, 0x70, 0x65, 0x3D, ++0x25, 0x64, 0x20, 0x73, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x63, 0x68, 0x61, 0x6E, 0x3A, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x62, 0x61, 0x6E, 0x64, 0x20, ++0x25, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x62, 0x61, 0x6E, 0x64, 0x20, 0x3C, 0x20, 0x50, ++0x48, 0x59, 0x5F, 0x42, 0x41, 0x4E, 0x44, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x28, 0x6D, 0x64, 0x6D, 0x5F, 0x6D, 0x61, 0x6A, ++0x6F, 0x72, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x2B, 0x20, ++0x32, 0x29, 0x20, 0x2A, 0x20, 0x31, 0x30, 0x20, 0x2B, 0x20, 0x6D, 0x64, 0x6D, 0x5F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x5F, ++0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x58, ++0x5F, 0x4D, 0x44, 0x4D, 0x5F, 0x56, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x72, 0x61, ++0x64, 0x69, 0x6F, 0x20, 0x25, 0x64, 0x20, 0x64, 0x6F, 0x65, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, ++0x74, 0x0A, 0x00, 0x00, 0x9D, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x61, ++0x6D, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x2C, 0x20, 0x64, 0x6F, 0x20, 0x6E, 0x6F, 0x74, 0x68, 0x69, ++0x6E, 0x67, 0x0A, 0x00, 0x9B, 0x25, 0x73, 0x20, 0x4D, 0x41, 0x43, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x21, 0x3D, ++0x20, 0x49, 0x44, 0x4C, 0x45, 0x0A, 0x00, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x68, 0x77, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x63, ++0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x00, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x63, 0x68, 0x61, 0x6E, ++0x6E, 0x65, 0x6C, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x67, 0x65, 0x74, 0x5F, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x00, ++0x70, 0x68, 0x79, 0x5F, 0x73, 0x74, 0x6F, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x0D, 0xFE, 0x11, 0xFE, 0x0D, 0x02, ++0x0E, 0xFF, 0x13, 0xFE, 0x0B, 0x02, 0x0C, 0xFD, 0x12, 0xFD, 0x0C, 0x03, 0x0D, 0xFE, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, ++0x14, 0xFD, 0x0A, 0x03, 0x0B, 0xFC, 0x11, 0xFF, 0x0D, 0x01, 0x0E, 0xFF, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x12, 0xFE, ++0x0C, 0x02, 0x0D, 0xFE, 0x12, 0xFE, 0x0C, 0x02, 0x0D, 0xFE, 0x12, 0xFE, 0x0C, 0x02, 0x0D, 0xFE, 0x13, 0xFE, 0x0B, 0x02, ++0x0C, 0xFD, 0x1F, 0x00, 0x0C, 0x02, 0x0D, 0xFE, 0x11, 0x00, 0x0D, 0x00, 0x0E, 0xFF, 0x13, 0x03, 0x0B, 0x03, 0x0C, 0xFD, ++0x14, 0xFC, 0x0A, 0x04, 0x0B, 0xFC, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x11, 0xFE, 0x0D, 0x02, 0x0E, 0xFF, 0x13, 0xFE, ++0x0B, 0x02, 0x0C, 0xFD, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x12, 0xFD, 0x0C, 0x03, ++0x0D, 0xFE, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x13, 0xFE, 0x0B, 0x02, 0x0C, 0xFD, ++0x1F, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x74, 0x63, 0x5F, 0x73, 0x70, 0x75, 0x72, 0x69, 0x6F, 0x75, 0x73, 0x00, 0x00, 0x00, ++0x18, 0x10, 0x0C, 0x08, 0x07, 0x06, 0x8B, 0x05, 0x89, 0x04, 0x87, 0x03, 0x85, 0x02, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x65, 0x74, 0x20, 0x74, 0x78, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x32, 0x2E, 0x34, ++0x67, 0x28, 0x70, 0x61, 0x5F, 0x64, 0x72, 0x76, 0x5F, 0x69, 0x62, 0x69, 0x74, 0x29, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x77, 0x66, 0x20, 0x64, 0x66, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x66, 0x69, 0x6E, 0x74, 0x66, 0x20, 0x52, 0x58, ++0x4F, 0x4E, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, 0x66, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, ++0x66, 0x69, 0x6E, 0x74, 0x66, 0x20, 0x52, 0x58, 0x4F, 0x46, 0x46, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x64, 0x65, 0x74, 0x65, ++0x63, 0x74, 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x62, 0x79, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, ++0x69, 0x6E, 0x20, 0x63, 0x61, 0x6C, 0x5F, 0x6C, 0x73, 0x20, 0x64, 0x65, 0x74, 0x20, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x6C, 0x6F, 0x70, 0x65, 0x20, 0x74, 0x6F, 0x6F, 0x20, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x66, 0x69, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, ++0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x66, 0x69, ++0x74, 0x5F, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x21, 0x0D, 0x0A, 0x00, 0x63, 0x6F, 0x65, 0x66, 0x5F, 0x49, 0x51, 0x20, ++0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2E, 0x00, 0x25, 0x30, 0x33, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, ++0x73, 0x64, 0x6D, 0x20, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, ++0x66, 0x72, 0x65, 0x71, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, ++0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x66, 0x65, 0x6E, ++0x20, 0x72, 0x65, 0x67, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, ++0x63, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x21, 0x0D, 0x0A, 0x00, 0x66, 0x69, 0x74, 0x2D, ++0x69, 0x6E, 0x2D, 0x49, 0x20, 0x25, 0x78, 0x3A, 0x20, 0x5B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, ++0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x5D, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x66, 0x69, 0x74, 0x2D, 0x69, 0x6E, 0x2D, 0x51, 0x20, 0x25, 0x78, 0x3A, 0x20, 0x5B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x5D, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x63, 0x61, 0x6C, 0x49, 0x20, 0x25, ++0x78, 0x2C, 0x20, 0x63, 0x61, 0x6C, 0x51, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, ++0x63, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x20, 0x65, 0x6E, 0x64, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x5F, ++0x63, 0x66, 0x67, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, ++0x70, 0x6C, 0x6C, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x63, 0x6B, 0x3A, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x77, 0x66, 0x72, 0x66, 0x20, 0x6F, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x66, 0x72, 0x66, 0x20, 0x6F, 0x66, 0x66, ++0x0D, 0x0A, 0x00, 0x00, 0x20, 0x2A, 0x20, 0x63, 0x61, 0x6C, 0x20, 0x74, 0x69, 0x61, 0x5F, 0x69, 0x71, 0x3A, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x49, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x30, 0x3D, 0x25, 0x64, ++0x2C, 0x20, 0x56, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x30, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, ++0x20, 0x20, 0x49, 0x69, 0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x69, ++0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x20, 0x61, 0x64, 0x6A, ++0x49, 0x69, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x61, 0x64, 0x6A, 0x49, 0x71, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x2D, 0x3E, 0x20, 0x49, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x30, 0x3D, 0x25, ++0x64, 0x2C, 0x20, 0x56, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x30, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x2A, 0x6C, 0x6E, 0x61, 0x5F, 0x76, 0x63, 0x6D, 0x70, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6C, 0x6E, ++0x61, 0x5F, 0x76, 0x63, 0x6D, 0x6E, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, ++0x67, 0x61, 0x69, 0x6E, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x72, 0x66, ++0x20, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, ++0x3C, 0x3D, 0x20, 0x33, 0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x69, ++0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x00, 0x73, 0x66, 0x74, 0x20, 0x64, 0x69, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x66, 0x74, 0x72, 0x73, 0x74, 0x20, 0x64, 0x6F, 0x6E, 0x65, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x6F, 0x61, 0x64, ++0x5F, 0x76, 0x61, 0x6C, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x75, 0x73, ++0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x68, 0x6F, 0x73, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x5F, 0x64, 0x6D, 0x61, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x20, 0x21, 0x3D, ++0x20, 0x30, 0x00, 0x00, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x64, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, ++0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x20, 0x3C, 0x3D, 0x20, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, ++0x6B, 0x65, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x28, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x64, ++0x73, 0x74, 0x2D, 0x3E, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, ++0x6D, 0x73, 0x67, 0x62, 0x75, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x5F, 0x6D, 0x73, 0x67, ++0x5F, 0x62, 0x75, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x69, 0x70, 0x63, 0x5F, 0x65, 0x6D, 0x62, 0x5F, ++0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x66, 0x77, 0x64, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, ++0x6D, 0x73, 0x67, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x73, 0x72, 0x63, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x64, 0x73, ++0x74, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x69, ++0x70, 0x63, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x72, ++0x20, 0x75, 0x73, 0x62, 0x20, 0x69, 0x6E, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x25, 0x64, 0x2C, ++0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x73, 0x72, 0x63, 0x2D, 0x3E, 0x70, 0x61, ++0x72, 0x61, 0x6D, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x73, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x6D, 0x73, ++0x67, 0x2D, 0x3E, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x29, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6D, 0x73, 0x67, ++0x20, 0x63, 0x66, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6E, 0x6F, 0x20, ++0x64, 0x73, 0x63, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x6E, 0x6F, 0x74, 0x69, 0x66, 0x79, 0x3A, ++0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x42, 0x54, 0x20, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x20, 0x68, 0x6F, ++0x73, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x70, 0x6D, 0x69, 0x63, 0x20, 0x67, 0x70, 0x69, 0x6F, 0x0A, 0x00, 0x00, ++0x77, 0x6B, 0x62, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x50, 0x4D, 0x49, 0x43, 0x5F, 0x45, 0x52, 0x52, ++0x49, 0x52, 0x51, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x5F, ++0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x49, 0x50, 0x43, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x43, 0x48, 0x41, 0x4E, 0x4E, 0x45, ++0x4C, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x23, 0x20, 0x3D, 0x25, 0x64, 0x20, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x75, 0x2E, 0x73, 0x74, 0x61, 0x2E, 0x6C, ++0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x3D, 0x3D, ++0x20, 0x31, 0x00, 0x00, 0x73, 0x74, 0x61, 0x2D, 0x3E, 0x6C, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x63, 0x6F, 0x6E, ++0x6E, 0x5F, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x00, 0x00, 0x61, 0x70, 0x6D, 0x20, ++0x73, 0x74, 0x61, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x74, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x72, 0x3A, 0x25, 0x64, 0x2C, 0x20, ++0x72, 0x72, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x31, 0x0A, 0x00, ++0x63, 0x6C, 0x65, 0x61, 0x72, 0x0A, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x0A, 0x00, 0x00, ++0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x74, 0x6D, 0x70, 0x2D, 0x3E, 0x68, 0x6F, 0x73, 0x74, 0x2E, 0x73, 0x74, 0x61, ++0x69, 0x64, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, 0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, ++0x41, 0x58, 0x00, 0x00, 0x73, 0x74, 0x61, 0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x25, 0x64, 0x0A, 0x00, ++0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x74, 0x6D, 0x70, 0x2D, 0x3E, 0x68, 0x6F, 0x73, 0x74, 0x2E, 0x66, 0x6C, 0x61, ++0x67, 0x73, 0x20, 0x26, 0x20, 0x54, 0x58, 0x55, 0x5F, 0x43, 0x4E, 0x54, 0x52, 0x4C, 0x5F, 0x52, 0x45, 0x54, 0x52, 0x59, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xD9, 0x67, 0x12, 0x00, 0xF9, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x70, 0x6F, 0x6F, 0x6C, 0x5F, ++0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, ++0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x74, 0x74, ++0x65, 0x72, 0x6E, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, ++0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x6E, 0x75, 0x6D, 0x5F, ++0x75, 0x73, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, ++0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, ++0x6E, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x20, 0x49, 0x6E, ++0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, ++0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x65, 0x6D, 0x4D, 0x67, 0x72, 0x45, 0x72, 0x72, 0x3A, 0x20, 0x53, ++0x75, 0x62, 0x70, 0x6F, 0x6F, 0x6C, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x53, 0x77, 0x45, 0x72, ++0x3A, 0x4E, 0x6F, 0x53, 0x69, 0x7A, 0x65, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x0D, 0x00, ++0x67, 0x65, 0x74, 0x5F, 0x6E, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x61, 0x64, 0x64, 0x72, ++0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, ++0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x74, 0x74, ++0x65, 0x72, 0x6E, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, ++0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x53, 0x77, 0x45, 0x72, 0x3A, 0x41, 0x6C, 0x6C, ++0x63, 0x45, 0x72, 0x72, 0x50, 0x74, 0x72, 0x6E, 0x20, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, ++0x72, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x74, 0x69, ++0x76, 0x65, 0x5F, 0x70, 0x6F, 0x6F, 0x6C, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, ++0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x64, 0x65, 0x63, 0x72, 0x5F, 0x6E, 0x75, 0x6D, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, ++0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, ++0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, ++0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, ++0x25, 0x78, 0x0A, 0x00, 0x6E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x69, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x32, 0x00, 0x00, ++0x67, 0x65, 0x74, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, ++0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, ++0x72, 0x65, 0x70, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x2C, 0x20, 0x25, 0x64, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x64, 0x65, 0x73, 0x63, 0x0D, 0x0A, 0x00, 0x00, ++0x70, 0x61, 0x72, 0x61, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6E, 0x74, 0x20, ++0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x69, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6E, 0x75, 0x6D, 0x3D, 0x25, 0x64, ++0x2C, 0x20, 0x72, 0x78, 0x64, 0x65, 0x73, 0x63, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x61, 0x63, 0x3E, 0x3D, 0x4E, 0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x20, ++0x2B, 0x20, 0x31, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, 0x65, 0x77, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, ++0x4C, 0x4C, 0x00, 0x00, 0x6D, 0x73, 0x67, 0x20, 0x63, 0x72, 0x63, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x69, 0x6E, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x73, 0x6F, 0x66, 0x74, ++0x77, 0x6B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x61, 0x20, 0x69, 0x6E, 0x74, 0x20, 0x25, 0x78, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x20, 0x73, 0x74, ++0x61, 0x74, 0x75, 0x73, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x68, 0x6F, 0x73, ++0x74, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x61, 0x68, 0x62, 0x32, 0x73, 0x64, 0x69, 0x6F, ++0x20, 0x74, 0x78, 0x20, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x53, 0x44, 0x49, 0x4F, 0x32, 0x41, 0x48, 0x42, ++0x5F, 0x4C, 0x4C, 0x53, 0x54, 0x5F, 0x48, 0x44, 0x52, 0x5F, 0x45, 0x52, 0x52, 0x0D, 0x0A, 0x00, 0x73, 0x64, 0x69, 0x6F, ++0x20, 0x65, 0x72, 0x72, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3D, 0x25, 0x78, 0x2C, 0x30, 0x78, 0x34, 0x35, 0x3D, ++0x25, 0x78, 0x0A, 0x00, 0x6D, 0x73, 0x67, 0x72, 0x78, 0x75, 0x73, 0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, ++0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x63, 0x75, 0x73, 0x65, 0x64, 0x3D, ++0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x74, 0x78, 0x63, 0x6D, ++0x73, 0x67, 0x75, 0x73, 0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6D, 0x73, 0x67, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x61, 0x69, 0x74, 0x20, 0x69, 0x6F, 0x20, 0x65, 0x6E, 0x61, 0x62, ++0x6C, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6F, 0x20, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x0D, 0x0A, 0x00, ++0x65, 0x72, 0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x70, 0x6B, 0x74, 0x21, 0x0D, 0x0A, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x64, 0x73, 0x63, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x6F, 0x70, 0x65, 0x6E, ++0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x55, 0x4C, 0x50, 0x49, 0x20, 0x63, 0x6C, 0x6B, 0x20, 0x64, 0x65, 0x74, ++0x65, 0x63, 0x74, 0x65, 0x64, 0x0D, 0x0A, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x20, 0x6E, 0x6F, 0x20, 0x75, 0x73, 0x62, ++0x20, 0x75, 0x6C, 0x70, 0x69, 0x20, 0x63, 0x6C, 0x6B, 0x0D, 0x0A, 0x00, 0x77, 0x61, 0x69, 0x74, 0x20, 0x63, 0x66, 0x67, ++0x0A, 0x00, 0x00, 0x00, 0x46, 0x49, 0x46, 0x4F, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x3A, 0x20, 0x6F, 0x76, 0x65, 0x72, ++0x66, 0x6C, 0x6F, 0x77, 0x2C, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x69, ++0x7A, 0x65, 0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x20, 0x52, 0x41, 0x4D, 0x20, ++0x69, 0x73, 0x20, 0x25, 0x64, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E, ++0x6D, 0x65, 0x6E, 0x74, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x45, 0x50, 0x30, 0x20, 0x53, 0x45, 0x54, 0x55, ++0x50, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x2C, 0x20, 0x64, 0x69, 0x72, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x00, ++0x45, 0x50, 0x30, 0x20, 0x53, 0x45, 0x54, 0x55, 0x50, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x2C, 0x20, 0x77, 0x4C, 0x65, ++0x6E, 0x67, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6E, 0x6B, 0x6E, ++0x6F, 0x77, 0x6E, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6F, 0x72, 0x3A, 0x20, 0x25, 0x64, 0x00, 0x00, ++0x45, 0x70, 0x30, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x65, 0x72, 0x72, 0x20, ++0x25, 0x75, 0x2D, 0x25, 0x75, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x72, 0x65, 0x62, 0x6F, 0x6F, 0x74, ++0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x65, 0x74, 0x0D, 0x0A, 0x00, 0x65, 0x78, 0x69, 0x74, ++0x0D, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x0A, 0x00, 0x77, 0x61, 0x6B, 0x65, ++0x75, 0x70, 0x20, 0x75, 0x73, 0x62, 0x0A, 0x00, 0x69, 0x72, 0x71, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x77, 0x6C, 0x61, 0x6E, 0x5F, 0x75, 0x73, 0x62, 0x5F, 0x73, 0x75, 0x73, 0x70, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x00, ++0x52, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x64, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, ++0x64, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x6D, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, ++0x64, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x6E, 0x6F, 0x20, 0x72, 0x78, ++0x20, 0x6D, 0x73, 0x67, 0x20, 0x65, 0x6C, 0x65, 0x6D, 0x0D, 0x0A, 0x00, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, ++0x20, 0x25, 0x58, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x65, 0x6E, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, ++0x64, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x72, 0x65, 0x63, 0x76, 0x20, 0x65, 0x72, ++0x72, 0x21, 0x21, 0x21, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x23, 0x65, ++0x72, 0x72, 0x23, 0x23, 0x23, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x6C, 0x61, 0x6E, ++0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6F, 0x70, 0x65, 0x6E, 0x20, 0x72, 0x65, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x21, 0x21, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x64, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x74, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x20, 0x00, ++0x01, 0x01, 0x00, 0xA0, 0xFA, 0x09, 0x04, 0x00, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, ++0x00, 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00, 0x05, 0x0F, 0x0C, 0x00, 0x01, 0x07, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, ++0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x9C, 0xA6, 0x00, 0x88, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00, ++0x0A, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, ++0x0A, 0x03, 0x77, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x10, 0x03, 0x61, 0x00, 0x69, 0x00, 0x63, 0x00, ++0x73, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x12, 0x03, 0x41, 0x00, 0x49, 0x00, 0x43, 0x00, 0x20, 0x00, 0x57, 0x00, ++0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x12, 0x03, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x39, 0x00, 0x30, 0x00, ++0x32, 0x00, 0x32, 0x00, 0x37, 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x75, 0x73, 0x62, 0x5F, 0x77, 0x6C, 0x61, 0x6E, ++0x5F, 0x72, 0x78, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x6E, ++0x69, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, ++0x77, 0x66, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x75, 0x73, 0x62, 0x20, 0x73, 0x74, 0x61, ++0x72, 0x74, 0x20, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x68, 0x6F, 0x73, ++0x74, 0x5F, 0x69, 0x66, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x73, 0x69, 0x7A, ++0x65, 0x00, 0x00, 0x00, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x72, 0x78, 0x3A, 0x20, 0x64, 0x73, 0x63, 0x72, 0x20, 0x75, ++0x73, 0x65, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x23, 0x77, 0x66, 0x3A, 0x25, 0x58, 0x0A, 0x00, ++0x23, 0x77, 0x65, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x64, 0x20, 0x72, 0x78, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x21, 0x20, 0x77, 0x64, 0x20, 0x6E, 0x6F, 0x20, 0x72, 0x78, 0x20, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, ++0x77, 0x64, 0x20, 0x72, 0x78, 0x20, 0x6D, 0x61, 0x78, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, ++0x68, 0x6F, 0x73, 0x74, 0x5F, 0x72, 0x65, 0x61, 0x64, 0x79, 0x0A, 0x00, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x64, 0x61, 0x74, ++0x61, 0x20, 0x72, 0x65, 0x63, 0x76, 0x20, 0x72, 0x65, 0x74, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, ++0x20, 0x6E, 0x6F, 0x20, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x69, 0x70, 0x63, ++0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x69, 0x70, 0x63, 0x20, 0x68, 0x6F, 0x73, ++0x74, 0x20, 0x72, 0x78, 0x3A, 0x20, 0x6E, 0x6F, 0x62, 0x75, 0x66, 0x66, 0x2C, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x3D, ++0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x4D, 0x4D, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x54, 0x4F, 0x5F, 0x4B, 0x45, ++0x59, 0x28, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, 0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x20, ++0x2D, 0x20, 0x31, 0x29, 0x20, 0x3C, 0x3D, 0x20, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x6B, 0x65, ++0x79, 0x5F, 0x6D, 0x61, 0x78, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x00, 0x00, ++0x6C, 0x70, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x61, 0x63, 0x74, 0x73, 0x6C, 0x70, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x69, ++0x6D, 0x65, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x69, 0x64, 0x78, 0x20, 0x21, 0x3D, ++0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x43, 0x54, 0x58, 0x54, 0x5F, 0x55, 0x4E, 0x55, 0x53, 0x45, 0x44, 0x00, 0x00, 0x00, ++0x73, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, ++0x67, 0x3A, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x0D, 0x0A, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, ++0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x6C, 0x61, 0x73, 0x74, 0x20, 0x3C, 0x20, 0x31, 0x30, 0x6D, 0x73, 0x2C, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, ++0x6F, 0x77, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x0D, 0x0A, 0x00, ++0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x0A, 0x43, 0x4F, 0x4E, 0x54, 0x52, 0x4F, 0x4C, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x78, ++0x50, 0x53, 0x52, 0x20, 0x20, 0x20, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x50, 0x53, 0x50, 0x20, 0x20, 0x20, 0x20, 0x3D, ++0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x4D, 0x53, 0x50, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x50, ++0x52, 0x49, 0x4D, 0x41, 0x53, 0x4B, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x4C, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, ++0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x00, 0x0A, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x20, 0x50, 0x53, 0x50, 0x21, 0x00, ++0x0A, 0x44, 0x75, 0x6D, 0x70, 0x4D, 0x53, 0x50, 0x3A, 0x00, 0x00, 0x00, 0x0A, 0x5B, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x3A, ++0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x0A, 0x52, 0x25, 0x2D, 0x34, 0x64, 0x3A, 0x20, ++0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x53, 0x50, 0x20, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x4C, 0x52, 0x20, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x43, 0x20, 0x20, 0x20, 0x3A, 0x20, ++0x25, 0x30, 0x38, 0x58, 0x0A, 0x78, 0x50, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x53, 0x50, ++0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x4D, 0x53, 0x50, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x00, 0x00, 0x00, 0x00, 0x0A, 0x43, 0x50, 0x55, 0x49, 0x44, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x49, 0x43, 0x53, ++0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x56, 0x54, 0x4F, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x41, 0x49, 0x52, 0x43, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x53, 0x48, 0x43, ++0x53, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x43, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x48, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x44, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, ++0x25, 0x30, 0x38, 0x58, 0x0A, 0x41, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, ++0x0A, 0x4D, 0x4D, 0x46, 0x53, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x20, 0x20, 0x49, 0x41, 0x43, 0x43, 0x56, ++0x49, 0x4F, 0x4C, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x44, 0x41, 0x43, 0x43, 0x56, 0x49, 0x4F, 0x4C, 0x20, 0x3A, 0x25, 0x64, ++0x0A, 0x20, 0x20, 0x4D, 0x55, 0x4E, 0x53, 0x54, 0x4B, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x09, 0x4D, 0x53, 0x54, 0x4B, ++0x45, 0x52, 0x52, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x4D, 0x4C, 0x53, 0x50, 0x45, 0x52, 0x52, 0x20, 0x20, ++0x3A, 0x25, 0x64, 0x09, 0x4D, 0x4D, 0x41, 0x52, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x3A, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, ++0x0A, 0x4D, 0x4D, 0x46, 0x41, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x42, 0x46, 0x53, ++0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x20, 0x20, 0x49, 0x42, 0x55, 0x53, 0x45, 0x52, 0x52, 0x20, 0x20, ++0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x0A, 0x20, ++0x20, 0x49, 0x4D, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x09, 0x55, 0x4E, 0x53, 0x54, ++0x4B, 0x45, 0x52, 0x52, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x53, 0x54, 0x4B, 0x45, 0x52, 0x52, 0x20, 0x20, 0x20, ++0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x4C, 0x53, 0x50, 0x45, 0x52, 0x52, 0x20, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, ++0x20, 0x42, 0x46, 0x41, 0x52, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x00, 0x0A, 0x42, 0x46, 0x41, ++0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x55, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, ++0x25, 0x30, 0x34, 0x58, 0x0A, 0x20, 0x20, 0x55, 0x4E, 0x44, 0x45, 0x46, 0x49, 0x4E, 0x53, 0x54, 0x52, 0x3A, 0x25, 0x64, ++0x09, 0x49, 0x4E, 0x56, 0x53, 0x54, 0x41, 0x54, 0x45, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x49, 0x4E, 0x56, 0x50, ++0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x4E, 0x4F, 0x43, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, ++0x25, 0x64, 0x0A, 0x20, 0x20, 0x55, 0x4E, 0x41, 0x4C, 0x49, 0x47, 0x4E, 0x45, 0x44, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x44, ++0x49, 0x56, 0x42, 0x59, 0x5A, 0x45, 0x52, 0x4F, 0x3A, 0x25, 0x64, 0x00, 0x0A, 0x4D, 0x6F, 0x64, 0x65, 0x20, 0x3A, 0x20, ++0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x0A, 0x50, 0x72, 0x69, 0x76, 0x20, 0x3A, 0x20, 0x55, 0x73, 0x65, 0x72, ++0x00, 0x00, 0x00, 0x00, 0x0A, 0x50, 0x72, 0x69, 0x76, 0x20, 0x3A, 0x20, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6C, 0x65, 0x67, ++0x65, 0x64, 0x00, 0x00, 0x0A, 0x4D, 0x6F, 0x64, 0x65, 0x20, 0x3A, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, ++0x0A, 0x53, 0x74, 0x61, 0x63, 0x6B, 0x3A, 0x20, 0x50, 0x53, 0x50, 0x00, 0x0A, 0x53, 0x74, 0x61, 0x63, 0x6B, 0x3A, 0x20, ++0x4D, 0x53, 0x50, 0x00, 0x0A, 0x43, 0x4E, 0x54, 0x52, 0x4C, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x4D, 0x41, ++0x53, 0x4B, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x46, 0x4D, 0x41, 0x53, 0x4B, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, ++0x0A, 0x42, 0x41, 0x53, 0x45, 0x50, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x44, 0x75, 0x6D, ++0x70, 0x50, 0x53, 0x50, 0x3A, 0x00, 0x00, 0x00, 0x50, 0x61, 0x6E, 0x69, 0x63, 0x2E, 0x2E, 0x2E, 0x0A, 0x00, 0x00, 0x00, ++0x0A, 0x2B, 0x2B, 0x20, 0x43, 0x4D, 0x34, 0x20, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, ++0x72, 0x20, 0x2B, 0x2B, 0x0A, 0x0A, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x54, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x00, 0x00, 0x00, ++0x4D, 0x65, 0x6D, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x42, 0x75, 0x73, 0x46, ++0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, ++0x48, 0x61, 0x72, 0x64, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, ++0x74, 0x3A, 0x00, 0x00, 0x0A, 0x0A, 0x2D, 0x2D, 0x20, 0x43, 0x4D, 0x34, 0x20, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x48, ++0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x2D, 0x2D, 0x0A, 0x0A, 0x00, 0x9A, 0x25, 0x73, 0x20, 0x2D, 0x20, 0x62, 0x75, ++0x69, 0x6C, 0x64, 0x3A, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x25, ++0x64, 0x2C, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x64, 0x6F, 0x6E, 0x65, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x64, 0x2C, 0x00, 0x00, 0x74, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x6E, 0x6F, 0x74, 0x20, ++0x70, 0x61, 0x73, 0x74, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x70, 0x61, 0x73, 0x73, ++0x3A, 0x20, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, ++0x68, 0x77, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x2D, 0x3E, ++0x74, 0x69, 0x6D, 0x65, 0x20, 0x2D, 0x20, 0x67, 0x5F, 0x77, 0x69, 0x66, 0x69, 0x5F, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6E, ++0x67, 0x73, 0x2E, 0x70, 0x77, 0x72, 0x5F, 0x6F, 0x70, 0x65, 0x6E, 0x5F, 0x73, 0x79, 0x73, 0x64, 0x65, 0x6C, 0x61, 0x79, ++0x29, 0x00, 0x00, 0x00, 0x73, 0x6C, 0x70, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x62, 0x74, 0x0A, 0x00, ++0x6C, 0x70, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x69, 0x67, 0x6E, 0x6F, 0x72, 0x65, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, ++0x77, 0x2C, 0x20, 0x00, 0x72, 0x77, 0x6E, 0x78, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x70, 0x72, 0x65, 0x76, 0x5F, 0x68, 0x77, ++0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, ++0x65, 0x6E, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x00, 0x00, 0x00, 0x00, ++0x77, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x77, 0x6E, 0x78, 0x6C, 0x5F, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5F, ++0x65, 0x76, 0x74, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5B, 0x30, 0x5D, 0x20, ++0x26, 0x26, 0x20, 0x74, 0x78, 0x5F, 0x68, 0x77, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5B, ++0x30, 0x5D, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, ++0x74, 0x78, 0x6C, 0x20, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x6C, 0x65, 0x6E, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x74, 0x78, 0x6C, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, ++0x63, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x74, 0x68, 0x64, 0x2D, 0x3E, 0x66, 0x69, 0x72, ++0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x00, 0x00, 0x6E, 0x65, 0x78, 0x74, 0x64, 0x65, 0x73, 0x63, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, ++0x2D, 0x3E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x41, 0x47, 0x47, 0x5F, 0x42, 0x41, 0x5F, 0x52, 0x45, ++0x43, 0x45, 0x49, 0x56, 0x45, 0x44, 0x00, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x62, 0x63, 0x6E, ++0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x00, ++0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x33, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, ++0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, ++0x5F, 0x61, 0x63, 0x5F, 0x32, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, ++0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x31, 0x5F, 0x73, 0x74, ++0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, ++0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x30, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, ++0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x68, 0x69, 0x5F, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x00, 0x00, ++0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5F, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6F, 0x72, 0x79, 0x20, 0x3C, 0x20, 0x28, 0x4E, ++0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x2B, 0x32, 0x29, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, ++0x21, 0x21, 0x20, 0x74, 0x78, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, ++0x20, 0x66, 0x6F, 0x72, 0x20, 0x75, 0x73, 0x62, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x66, 0x6D, 0x20, 0x66, 0x6C, 0x75, 0x73, ++0x68, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x73, 0x6E, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x63, 0x66, 0x6D, 0x73, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x73, 0x6E, 0x3D, 0x25, 0x64, 0x2C, ++0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x79, 0x5F, 0x69, 0x64, 0x78, 0x5F, ++0x68, 0x77, 0x20, 0x3E, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x53, 0x45, 0x43, 0x5F, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4C, 0x54, ++0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x4F, 0x55, 0x4E, 0x54, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x65, 0x76, 0x74, 0x5F, 0x67, ++0x65, 0x74, 0x28, 0x29, 0x20, 0x26, 0x20, 0x65, 0x76, 0x74, 0x5F, 0x62, 0x69, 0x74, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, ++0x73, 0x63, 0x5F, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, ++0x62, 0x75, 0x67, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x74, 0x61, 0x69, 0x6C, 0x20, 0x65, 0x72, ++0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, ++0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x28, 0x74, 0x68, 0x64, 0x2D, 0x3E, 0x64, 0x61, ++0x74, 0x61, 0x73, 0x74, 0x61, 0x72, 0x74, 0x70, 0x74, 0x72, 0x20, 0x26, 0x20, 0x30, 0x78, 0x30, 0x31, 0x29, 0x20, 0x3D, ++0x3D, 0x20, 0x30, 0x00, 0x62, 0x61, 0x6E, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x50, 0x48, 0x59, 0x5F, 0x42, 0x41, 0x4E, 0x44, ++0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, ++0x6F, 0x72, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x6E, 0x6F, 0x20, 0x70, 0x72, 0x6F, 0x62, 0x65, 0x20, 0x62, 0x75, 0x66, ++0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, ++0x4C, 0x4C, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, 0x65, 0x77, 0x20, 0x21, 0x3D, 0x20, ++0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x70, 0x69, 0x63, 0x6B, ++0x28, 0x26, 0x74, 0x78, 0x6C, 0x69, 0x73, 0x74, 0x2D, 0x3E, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, ++0x29, 0x20, 0x3D, 0x3D, 0x20, 0x26, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6F, 0x6C, 0x64, 0x2D, 0x3E, ++0x6C, 0x69, 0x73, 0x74, 0x5F, 0x68, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, ++0x6F, 0x64, 0x20, 0x3E, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, 0x4F, 0x4E, 0x5F, 0x48, ++0x54, 0x5F, 0x44, 0x55, 0x50, 0x5F, 0x4F, 0x46, 0x44, 0x4D, 0x00, 0x00, 0x28, 0x2A, 0x6E, 0x73, 0x73, 0x20, 0x3E, 0x20, ++0x30, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x2A, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x34, 0x29, 0x00, 0x00, 0x00, ++0x6D, 0x63, 0x73, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x39, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x63, 0x73, 0x5F, ++0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x33, 0x31, 0x00, 0x00, 0x00, 0x69, 0x73, 0x5F, 0x6D, 0x70, 0x64, 0x75, 0x5F, ++0x66, 0x69, 0x72, 0x73, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x29, 0x00, 0x00, 0x00, 0x21, 0x69, 0x73, 0x5F, ++0x6D, 0x70, 0x64, 0x75, 0x5F, 0x6C, 0x61, 0x73, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x29, 0x00, 0x00, 0x00, ++0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x70, 0x72, 0x65, 0x76, 0x20, 0x3D, 0x3D, 0x20, 0x61, 0x67, 0x67, 0x5F, 0x64, ++0x65, 0x73, 0x63, 0x5F, 0x6F, 0x6C, 0x64, 0x2D, 0x3E, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6C, 0x61, 0x73, 0x74, ++0x00, 0x00, 0x00, 0x00, 0x61, 0x5F, 0x74, 0x68, 0x64, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x52, ++0x45, 0x54, 0x52, 0x59, 0x5F, 0x4C, 0x49, 0x4D, 0x49, 0x54, 0x5F, 0x52, 0x45, 0x41, 0x43, 0x48, 0x45, 0x44, 0x5F, 0x42, ++0x49, 0x54, 0x00, 0x00, 0x1A, 0x00, 0x1C, 0x00, 0x36, 0x00, 0x3C, 0x00, 0x75, 0x00, 0x82, 0x00, 0xEA, 0x00, 0x04, 0x01, ++0x34, 0x00, 0x39, 0x00, 0x6C, 0x00, 0x78, 0x00, 0xEA, 0x00, 0x04, 0x01, 0xD4, 0x01, 0x08, 0x02, 0x4E, 0x00, 0x56, 0x00, ++0xA2, 0x00, 0xB4, 0x00, 0x5F, 0x01, 0x86, 0x01, 0xBE, 0x02, 0x0C, 0x03, 0x68, 0x00, 0x73, 0x00, 0xD8, 0x00, 0xF0, 0x00, ++0xD4, 0x01, 0x08, 0x02, 0xA8, 0x03, 0x10, 0x04, 0x9C, 0x00, 0xAD, 0x00, 0x44, 0x01, 0x68, 0x01, 0xBE, 0x02, 0x0C, 0x03, ++0x7C, 0x05, 0x18, 0x06, 0xD0, 0x00, 0xE7, 0x00, 0xB0, 0x01, 0xE0, 0x01, 0xA8, 0x03, 0x10, 0x04, 0x50, 0x07, 0x20, 0x08, ++0xEA, 0x00, 0x04, 0x01, 0xE6, 0x01, 0x1C, 0x02, 0x1D, 0x04, 0x92, 0x04, 0x3A, 0x08, 0x24, 0x09, 0x04, 0x01, 0x20, 0x01, ++0x1C, 0x02, 0x58, 0x02, 0x92, 0x04, 0x14, 0x05, 0x24, 0x09, 0x28, 0x0A, 0x38, 0x01, 0x5A, 0x01, 0x88, 0x02, 0xD0, 0x02, ++0x7C, 0x05, 0x18, 0x06, 0xF8, 0x0A, 0x30, 0x0C, 0x5A, 0x01, 0x81, 0x01, 0xD0, 0x02, 0x20, 0x03, 0x18, 0x06, 0xC5, 0x06, ++0x30, 0x0C, 0x8A, 0x0D, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x08, 0x09, 0x02, 0x02, 0x04, 0x04, 0x08, 0x09, 0x0F, 0x11, ++0x03, 0x03, 0x06, 0x06, 0x0B, 0x0D, 0x16, 0x19, 0x04, 0x04, 0x07, 0x08, 0x0F, 0x11, 0x1E, 0x21, 0x05, 0x06, 0x0B, 0x0C, ++0x16, 0x19, 0x2C, 0x31, 0x07, 0x08, 0x0E, 0x0F, 0x1E, 0x21, 0x3B, 0x41, 0x08, 0x09, 0x10, 0x11, 0x21, 0x25, 0x42, 0x4A, ++0x09, 0x0A, 0x11, 0x13, 0x25, 0x29, 0x4A, 0x52, 0x0A, 0x0B, 0x15, 0x17, 0x2C, 0x31, 0x58, 0x62, 0x0B, 0x0D, 0x17, 0x19, ++0x31, 0x37, 0x62, 0x6D, 0x74, 0x78, 0x6C, 0x5F, 0x68, 0x65, 0x5F, 0x65, 0x64, 0x63, 0x61, 0x5F, 0x71, 0x75, 0x65, 0x75, ++0x65, 0x5F, 0x68, 0x61, 0x6C, 0x74, 0x65, 0x64, 0x28, 0x61, 0x63, 0x29, 0x00, 0x00, 0x00, 0x00, 0x68, 0x64, 0x72, 0x64, ++0x65, 0x73, 0x63, 0x2D, 0x3E, 0x66, 0x72, 0x6D, 0x6C, 0x65, 0x6E, 0x20, 0x3E, 0x3D, 0x20, 0x48, 0x45, 0x5F, 0x54, 0x52, ++0x49, 0x47, 0x5F, 0x46, 0x52, 0x4D, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, ++0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, ++0x48, 0x45, 0x5F, 0x53, 0x55, 0x00, 0x00, 0x00, 0x6D, 0x63, 0x73, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x31, ++0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, ++0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x07, 0x00, ++0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, ++0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, ++0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, ++0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, ++0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, ++0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, ++0x22, 0x00, 0x20, 0x00, 0x1D, 0x00, 0x90, 0x00, 0x88, 0x00, 0x7A, 0x00, 0x44, 0x00, 0x41, 0x00, 0x3A, 0x00, 0x20, 0x01, ++0x10, 0x01, 0xF5, 0x00, 0x67, 0x00, 0x61, 0x00, 0x57, 0x00, 0xB0, 0x01, 0x98, 0x01, 0x6F, 0x01, 0x89, 0x00, 0x82, 0x00, ++0x75, 0x00, 0x40, 0x02, 0x20, 0x02, 0xEA, 0x01, 0xCE, 0x00, 0xC3, 0x00, 0xAF, 0x00, 0x60, 0x03, 0x30, 0x03, 0xDF, 0x02, ++0x13, 0x01, 0x04, 0x01, 0xEA, 0x00, 0x80, 0x04, 0x40, 0x04, 0xD4, 0x03, 0x35, 0x01, 0x24, 0x01, 0x07, 0x01, 0x11, 0x05, ++0xC9, 0x04, 0x4E, 0x04, 0x58, 0x01, 0x45, 0x01, 0x24, 0x01, 0xA1, 0x05, 0x51, 0x05, 0xC9, 0x04, 0x9C, 0x01, 0x86, 0x01, ++0x5F, 0x01, 0xC1, 0x06, 0x61, 0x06, 0xBE, 0x05, 0xCA, 0x01, 0xB1, 0x01, 0x86, 0x01, 0x81, 0x07, 0x16, 0x07, 0x61, 0x06, ++0x04, 0x02, 0xE7, 0x01, 0xB6, 0x01, 0x71, 0x08, 0xF9, 0x07, 0x2D, 0x07, 0x3D, 0x02, 0x1D, 0x02, 0xE7, 0x01, 0x61, 0x09, ++0xDC, 0x08, 0xF9, 0x07, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, ++0x02, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x0D, 0x00, 0x0C, 0x00, ++0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x13, 0x00, 0x12, 0x00, 0x10, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x1C, 0x00, ++0x1A, 0x00, 0x17, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x25, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x0A, 0x00, 0x0A, 0x00, ++0x09, 0x00, 0x29, 0x00, 0x27, 0x00, 0x23, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x2E, 0x00, 0x2B, 0x00, 0x27, 0x00, ++0x0D, 0x00, 0x0D, 0x00, 0x0B, 0x00, 0x37, 0x00, 0x34, 0x00, 0x2E, 0x00, 0x0F, 0x00, 0x0E, 0x00, 0x0D, 0x00, 0x3D, 0x00, ++0x39, 0x00, 0x34, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x44, 0x00, 0x40, 0x00, 0x3A, 0x00, 0x12, 0x00, 0x11, 0x00, ++0x10, 0x00, 0x4C, 0x00, 0x47, 0x00, 0x40, 0x00, 0x08, 0x10, 0x20, 0x04, 0x50, 0x94, 0x15, 0x00, 0x98, 0x94, 0x15, 0x00, ++0x08, 0x94, 0x15, 0x00, 0x72, 0x68, 0x64, 0x2D, 0x3E, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, ++0x74, 0x72, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x6E, 0x6F, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, ++0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x72, 0x78, 0x62, 0x75, 0x66, 0x31, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, ++0x25, 0x30, 0x38, 0x78, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x65, 0x6E, ++0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x77, ++0x72, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x64, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, ++0x78, 0x0D, 0x0A, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x72, 0x65, 0x63, 0x6F, ++0x76, 0x65, 0x72, 0x79, 0x0D, 0x0A, 0x00, 0x00, 0x70, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, ++0x70, 0x64, 0x2D, 0x3E, 0x70, 0x62, 0x64, 0x2E, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x61, 0x72, 0x74, 0x70, 0x74, 0x72, ++0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x61, 0x5F, 0x68, 0x64, 0x72, 0x64, 0x65, 0x73, 0x63, 0x2D, ++0x3E, 0x68, 0x64, 0x2E, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x20, 0x3D, 0x3D, ++0x20, 0x30, 0x00, 0x00, 0x70, 0x62, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x72, 0x78, 0x6C, 0x20, ++0x65, 0x72, 0x72, 0x2C, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x6E, 0x6F, 0x20, 0x74, ++0x78, 0x5F, 0x64, 0x73, 0x63, 0x72, 0x5F, 0x68, 0x64, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x20, 0x74, ++0x78, 0x5F, 0x64, 0x73, 0x63, 0x72, 0x5F, 0x68, 0x64, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6D, 0x70, 0x64, 0x75, ++0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x6D, 0x70, 0x64, 0x75, 0x5F, 0x6C, 0x65, 0x6E, ++0x20, 0x3C, 0x3D, 0x20, 0x52, 0x57, 0x4E, 0x58, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x41, 0x4D, 0x53, 0x44, 0x55, 0x5F, 0x52, ++0x58, 0x00, 0x00, 0x00, 0x72, 0x68, 0x64, 0x2D, 0x3E, 0x75, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6E, 0x72, 0x78, 0x20, ++0x3D, 0x3D, 0x20, 0x52, 0x58, 0x5F, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5F, 0x44, 0x45, 0x53, 0x43, 0x5F, 0x50, 0x41, ++0x54, 0x54, 0x45, 0x52, 0x4E, 0x00, 0x00, 0x00, 0x72, 0x78, 0x62, 0x75, 0x66, 0x32, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, ++0x25, 0x30, 0x38, 0x78, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x65, 0x6E, ++0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x77, ++0x72, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x64, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, ++0x78, 0x0D, 0x0A, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, ++0x73, 0x74, 0x61, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, ++0x73, 0x74, 0x61, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, ++0x6D, 0x61, 0x63, 0x20, 0x69, 0x73, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x70, 0x32, 0x70, 0x3D, 0x25, ++0x64, 0x0D, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x20, 0x6D, 0x61, 0x63, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x20, 0x6D, ++0x61, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x70, 0x32, 0x70, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x21, 0x3D, 0x20, 0x50, 0x32, ++0x50, 0x5F, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x25, ++0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x76, 0x69, 0x66, 0x20, ++0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x20, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6D, 0x67, 0x6D, 0x74, 0x3A, ++0x25, 0x64, 0x0A, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, ++0x73, 0x6C, 0x65, 0x65, 0x70, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, 0x6C, 0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x6F, 0x6E, 0x5F, 0x61, 0x69, 0x72, 0x5F, 0x76, 0x61, ++0x6C, 0x69, 0x64, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x64, 0x74, 0x69, 0x6D, ++0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x2A, 0x28, 0x76, 0x6F, ++0x6C, 0x61, 0x74, 0x69, 0x6C, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x5F, 0x74, 0x20, 0x2A, 0x29, 0x26, 0x67, 0x5F, ++0x61, 0x6F, 0x6E, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2E, 0x64, 0x74, 0x69, 0x6D, 0x5F, 0x63, 0x6E, 0x74, 0x5F, ++0x61, 0x6F, 0x6E, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x3C, 0x20, 0x2A, 0x28, 0x76, 0x6F, 0x6C, 0x61, 0x74, 0x69, ++0x6C, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x5F, 0x74, 0x20, 0x2A, 0x29, 0x26, 0x67, 0x5F, 0x61, 0x6F, 0x6E, 0x5F, ++0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2E, 0x64, 0x74, 0x69, 0x6D, 0x5F, 0x70, 0x65, 0x72, 0x69, 0x6F, 0x64, 0x5F, 0x61, ++0x6F, 0x6E, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x6E, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, ++0x6C, 0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x4C, 0x2C, 0x00, 0x00, 0x9B, 0x84, 0x4B, 0x65, 0x79, 0x69, 0x64, 0x78, ++0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x2C, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x00, 0x00, 0x9B, 0x84, 0x49, 0x6E, ++0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x6B, 0x65, 0x79, 0x69, 0x64, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x9B, 0x84, 0x49, 0x6E, ++0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x53, 0x54, 0x41, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x5F, ++0x73, 0x74, 0x61, 0x20, 0x3D, 0x3D, 0x20, 0x76, 0x69, 0x66, 0x00, 0x00, 0x54, 0x3D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x42, 0x43, 0x4E, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x6E, 0x20, ++0x64, 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x66, 0x63, 0x73, 0x20, ++0x6F, 0x6B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x66, 0x63, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x6F, 0x6B, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x69, 0x64, 0x6C, 0x65, ++0x20, 0x69, 0x6E, 0x74, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x65, 0x76, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4D, ++0x4D, 0x5F, 0x54, 0x42, 0x54, 0x54, 0x5F, 0x45, 0x56, 0x54, 0x5F, 0x4D, 0x41, 0x53, 0x4B, 0x00, 0x61, 0x64, 0x64, 0x20, ++0x67, 0x74, 0x6B, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x20, ++0x3C, 0x20, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x20, 0x70, 0x74, 0x6B, 0x3A, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x48, 0x4F, 0x53, 0x54, ++0x5F, 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, ++0x4E, 0x4F, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x00, 0x66, 0x6F, 0x72, 0x63, 0x65, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x72, ++0x65, 0x71, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x63, 0x65, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x65, ++0x78, 0x69, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, ++0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x48, 0x4F, 0x53, ++0x54, 0x5F, 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, ++0x20, 0x4D, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x6B, ++0x65, 0x79, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4C, 0x54, ++0x5F, 0x4D, 0x46, 0x50, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x4F, 0x55, 0x4E, 0x54, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, ++0x6D, 0x2D, 0x3E, 0x6B, 0x65, 0x79, 0x2E, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x3C, 0x3D, 0x20, 0x4D, 0x41, 0x43, ++0x5F, 0x53, 0x45, 0x43, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, ++0x6D, 0x2D, 0x3E, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5F, 0x73, 0x75, 0x69, 0x74, 0x65, 0x20, 0x3C, 0x3D, 0x20, 0x4D, ++0x41, 0x43, 0x5F, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x50, 0x5F, 0x43, 0x4D, 0x41, 0x43, 0x5F, 0x31, ++0x32, 0x38, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x68, 0x77, 0x5F, 0x6B, 0x65, 0x79, 0x5F, 0x69, 0x64, ++0x78, 0x20, 0x3C, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x53, 0x45, 0x43, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x4D, 0x46, 0x50, 0x5F, ++0x4B, 0x45, 0x59, 0x5F, 0x4E, 0x42, 0x52, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, ++0x20, 0x56, 0x49, 0x46, 0x5F, 0x53, 0x54, 0x41, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, ++0x49, 0x44, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x6D, 0x75, 0x20, 0x65, 0x64, 0x63, 0x61, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x44, 0x48, 0x43, 0x50, 0x65, 0x64, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x78, 0x2E, 0x0D, 0x0A, 0x00, ++0x73, 0x65, 0x74, 0x20, 0x61, 0x67, 0x67, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x25, 0x64, 0x2C, 0x20, ++0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x72, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x20, ++0x6D, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x73, 0x65, 0x74, 0x20, 0x74, 0x78, 0x6F, 0x70, 0x20, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x62, 0x6B, 0x3A, 0x25, 0x78, 0x2C, ++0x20, 0x62, 0x65, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x76, 0x69, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x76, 0x6F, 0x3A, 0x25, 0x78, ++0x2C, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x6E, 0x61, 0x76, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x63, 0x66, 0x65, 0x3D, 0x25, 0x64, ++0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x20, 0x74, 0x72, 0x78, 0x3A, 0x20, ++0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, ++0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x73, ++0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x73, 0x74, 0x6F, 0x70, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x69, 0x73, 0x20, 0x35, 0x67, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x77, 0x5F, 0x65, 0x6E, 0x3D, ++0x25, 0x64, 0x2C, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x5F, 0x69, 0x6E, 0x66, 0x6F, 0x3D, 0x30, 0x78, 0x25, 0x78, ++0x0D, 0x0A, 0x00, 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, 0x20, 0x65, 0x66, ++0x75, 0x73, 0x65, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x61, 0x70, ++0x3A, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x61, 0x70, 0x5F, 0x66, 0x69, 0x6E, ++0x65, 0x3A, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, ++0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, ++0x5F, 0x66, 0x69, 0x6E, 0x65, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x32, 0x2E, 0x34, 0x67, 0x3A, 0x62, 0x65, 0x66, ++0x6F, 0x72, 0x65, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, ++0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x32, 0x2E, 0x34, 0x67, 0x3A, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x20, ++0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x35, 0x67, 0x3A, 0x62, 0x65, 0x66, 0x6F, 0x72, 0x65, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, ++0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x35, 0x67, 0x3A, 0x61, ++0x66, 0x74, 0x65, 0x72, 0x20, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, ++0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, ++0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x48, 0x57, ++0x5F, 0x49, 0x44, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x4E, 0x4F, 0x5F, 0x49, ++0x44, 0x4C, 0x45, 0x00, 0x76, 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, ++0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x68, 0x65, 0x20, 0x65, ++0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x74, ++0x65, 0x20, 0x69, 0x6E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0xA8, 0x1F, 0x17, 0x00, 0x35, 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, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x74, 0x3A, 0x20, ++0x63, 0x62, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x63, 0x75, 0x72, 0x72, ++0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, 0x68, 0x77, 0x5F, 0x74, ++0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x29, 0x00, 0x74, 0x69, 0x6D, 0x65, ++0x72, 0x2D, 0x3E, 0x63, 0x62, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x20, 0x70, 0x72, 0x6F, 0x62, ++0x65, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x20, ++0x70, 0x72, 0x6F, 0x62, 0x65, 0x20, 0x73, 0x75, 0x63, 0x63, 0x0A, 0x00, 0x6D, 0x6D, 0x5F, 0x62, 0x63, 0x6E, 0x5F, 0x65, ++0x6E, 0x76, 0x2E, 0x74, 0x78, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x6C, ++0x6C, 0x65, 0x20, 0x6E, 0x65, 0x76, 0x65, 0x72, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x61, 0x70, 0x6D, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6E, 0x75, 0x6C, 0x6C, 0x20, 0x74, 0x6F, 0x20, 0x70, 0x72, 0x6F, ++0x62, 0x65, 0x20, 0x73, 0x74, 0x61, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, ++0x21, 0x6D, 0x6D, 0x5F, 0x62, 0x63, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x74, 0x78, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, ++0x61, 0x70, 0x6D, 0x5F, 0x70, 0x72, 0x6F, 0x62, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, ++0x28, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, ++0x74, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3D, ++0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x29, 0x20, 0x7C, ++0x7C, 0x20, 0x28, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, ++0x74, 0x78, 0x74, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, ++0x20, 0x3D, 0x3D, 0x20, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x69, 0x6E, 0x64, 0x65, 0x78, ++0x29, 0x00, 0x00, 0x00, 0x6F, 0x74, 0x68, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x62, 0x5F, 0x76, ++0x69, 0x66, 0x5F, 0x6F, 0x74, 0x68, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3E, 0x20, 0x31, 0x00, 0x6E, 0x6F, 0x61, 0x5F, ++0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x50, 0x32, 0x50, 0x5F, 0x4E, 0x4F, 0x41, 0x5F, 0x4E, 0x42, 0x5F, 0x4D, 0x41, 0x58, ++0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x20, 0x33, 0x32, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x74, 0x62, 0x74, 0x74, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2E, 0x70, 0x32, 0x70, ++0x5F, 0x6E, 0x6F, 0x61, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3D, 0x3D, 0x20, 0x49, 0x4E, ++0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, 0x00, 0x63, 0x68, 0x5F, 0x73, ++0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x52, ++0x4F, 0x43, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x50, 0x45, 0x4E, 0x44, 0x49, 0x4E, 0x47, 0x5F, 0x4D, 0x41, 0x53, 0x4B, ++0x00, 0x00, 0x00, 0x00, 0x28, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, ++0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, 0x54, 0x28, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x45, 0x4E, 0x56, 0x5F, 0x52, ++0x4F, 0x43, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x28, 0x63, 0x68, 0x61, ++0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, ++0x54, 0x28, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x45, 0x4E, 0x56, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x42, 0x49, 0x54, 0x29, ++0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x28, 0x76, 0x6F, 0x69, 0x64, 0x20, 0x2A, 0x29, 0x63, 0x68, 0x5F, 0x73, ++0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6E, 0x76, 0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, ++0x4E, 0x6F, 0x20, 0x63, 0x74, 0x78, 0x74, 0x20, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x64, 0x20, 0x70, 0x72, ++0x65, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x69, 0x64, ++0x78, 0x20, 0x3D, 0x3D, 0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x43, 0x54, 0x58, 0x54, 0x5F, 0x55, 0x4E, 0x55, 0x53, 0x45, ++0x44, 0x00, 0x00, 0x00, 0x72, 0x6F, 0x63, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x64, 0x75, 0x72, 0x3D, 0x25, 0x64, 0x2C, ++0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x6E, 0x62, ++0x5F, 0x6C, 0x69, 0x6E, 0x6B, 0x65, 0x64, 0x5F, 0x76, 0x69, 0x66, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x55, ++0x4C, 0x4C, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x6E, 0x62, 0x5F, 0x73, 0x63, 0x68, 0x65, ++0x64, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3C, 0x3D, 0x20, 0x32, 0x00, 0x63, 0x68, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, ++0x68, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x6C, 0x69, 0x6E, 0x6B, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x63, 0x74, 0x78, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, ++0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x6C, 0x69, 0x6E, 0x6B, 0x3A, 0x20, 0x25, 0x64, 0x2C, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x6E, 0x62, 0x5F, 0x73, 0x63, 0x68, 0x65, 0x64, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3C, ++0x3D, 0x20, 0x31, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x70, 0x73, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, 0x6C, ++0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x70, 0x73, 0x5F, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x64, ++0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x75, 0x70, 0x6D, 0x5F, 0x65, ++0x6E, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x75, 0x70, 0x6D, 0x5F, 0x65, 0x78, 0x69, 0x74, 0x00, ++0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, ++0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x6F, 0x61, 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x20, 0x3C, 0x20, 0x50, 0x32, 0x50, 0x5F, ++0x4E, 0x4F, 0x41, 0x5F, 0x4E, 0x42, 0x5F, 0x4D, 0x41, 0x58, 0x29, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, ++0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x50, 0x32, 0x50, 0x5F, 0x56, 0x49, 0x46, 0x5F, ++0x4D, 0x41, 0x58, 0x00, 0x74, 0x64, 0x73, 0x5F, 0x65, 0x6E, 0x76, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, ++0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x6E, 0x74, 0x20, 0x3E, 0x20, 0x30, 0x00, ++0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x43, ++0x41, 0x4E, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x57, 0x41, 0x49, 0x54, 0x5F, 0x43, 0x48, 0x41, ++0x4E, 0x4E, 0x45, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, ++0x57, 0x41, 0x49, 0x54, 0x5F, 0x42, 0x45, 0x41, 0x43, 0x4F, 0x4E, 0x5F, 0x50, 0x52, 0x4F, 0x42, 0x45, 0x5F, 0x52, 0x53, ++0x50, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5F, 0x72, 0x65, 0x71, 0x5F, 0x68, ++0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x5F, ++0x72, 0x65, 0x71, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x50, 0x21, 0x17, 0x00, 0x04, 0x00, 0x00, 0x00, ++0x73, 0x63, 0x61, 0x6E, 0x5F, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x5F, 0x63, 0x66, 0x6D, ++0x00, 0x00, 0x00, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x5F, 0x73, 0x74, ++0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x49, 0x44, 0x4C, ++0x45, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x61, 0x6F, 0x6E, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, 0x74, 0x69, ++0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x2D, 0x3E, 0x74, 0x69, 0x6D, 0x65, 0x20, ++0x2B, 0x20, 0x35, 0x30, 0x30, 0x30, 0x29, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, ++0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x6B, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x67, ++0x65, 0x6E, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x79, 0x6D, 0x6F, 0x72, 0x65, 0x0D, 0x0A, 0x00, 0x00, ++0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x6D, ++0x6D, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x67, 0x65, 0x6E, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, ++0x20, 0x61, 0x6E, 0x79, 0x6D, 0x6F, 0x72, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x30, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x31, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x32, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x33, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x5F, 0x54, ++0x49, 0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x48, 0x45, 0x5F, 0x54, 0x42, 0x5F, ++0x54, 0x49, 0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, ++0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x48, 0x49, 0x51, 0x5F, 0x54, 0x49, ++0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x5F, 0x46, 0x49, 0x46, 0x4F, 0x5F, ++0x4F, 0x56, 0x45, 0x52, 0x5F, 0x46, 0x4C, 0x4F, 0x57, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x2C, 0x20, 0x68, 0x77, ++0x20, 0x72, 0x65, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6C, 0x66, 0x0D, 0x0A, 0x00, 0x00, ++0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, ++0x58, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x48, 0x59, 0x5F, 0x45, 0x52, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, ++0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, ++0x58, 0x4D, 0x41, 0x43, 0x5F, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x48, 0x59, 0x49, 0x46, 0x5F, 0x55, 0x4E, 0x44, 0x45, 0x52, ++0x5F, 0x52, 0x55, 0x4E, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, ++0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x4D, 0x41, 0x43, ++0x5F, 0x50, 0x48, 0x59, 0x49, 0x46, 0x5F, 0x4F, 0x56, 0x45, 0x52, 0x46, 0x4C, 0x4F, 0x57, 0x5F, 0x42, 0x49, 0x54, 0x29, ++0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, ++0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x54, 0x5F, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x5F, 0x42, 0x49, ++0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, ++0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x30, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, ++0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, ++0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, ++0x31, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, ++0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, ++0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x32, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, ++0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, ++0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x33, 0x5F, 0x54, 0x58, ++0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, ++0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, ++0x5F, 0x42, 0x43, 0x4E, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, ++0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, ++0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x58, 0x5F, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5F, 0x44, ++0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, ++0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, ++0x5F, 0x52, 0x58, 0x5F, 0x50, 0x41, 0x59, 0x4C, 0x4F, 0x41, 0x44, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, ++0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, ++0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x57, 0x5F, 0x45, 0x52, 0x52, 0x5F, ++0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, ++0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x49, 0x5F, 0x54, 0x58, 0x5F, 0x44, ++0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, ++0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x08, 0x06, 0x04, 0x0B, 0x09, 0x07, 0x05, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, 0x8D, 0xF6, ++0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, ++0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, ++0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, ++0xAE, 0x3D, 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, 0x08, 0xF9, ++0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, ++0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, ++0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, ++0x61, 0xB7, 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, 0x2C, 0xC1, ++0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, ++0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, ++0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, ++0xC0, 0x80, 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, 0x63, 0x42, ++0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, ++0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, ++0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, ++0xD3, 0x6B, 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, 0x1E, 0x14, ++0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, ++0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, ++0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, ++0x6F, 0x4A, 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, 0x21, 0x3E, ++0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, ++0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, ++0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, ++0x92, 0x15, 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, 0x17, 0x1A, ++0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, ++0xD6, 0x6D, 0x3A, 0x2C, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x20, 0x3E, 0x20, 0x30, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6C, 0x61, ++0x79, 0x20, 0x3C, 0x20, 0x4B, 0x45, 0x5F, 0x54, 0x49, 0x4D, 0x45, 0x52, 0x5F, 0x44, 0x45, 0x4C, 0x41, 0x59, 0x5F, 0x4D, ++0x41, 0x58, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0x21, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x7C, ++0x7C, 0x20, 0x21, 0x6B, 0x65, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x66, 0x69, 0x72, 0x73, ++0x74, 0x2D, 0x3E, 0x74, 0x69, 0x6D, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x73, 0x67, 0x20, 0x21, 0x3D, 0x20, 0x4E, ++0x55, 0x4C, 0x4C, 0x00, 0x9D, 0x80, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x73, ++0x67, 0x3A, 0x25, 0x78, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x20, 0x74, 0x6F, 0x20, ++0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x73, 0x69, 0x7A, 0x65, 0x20, 0x3E, 0x3D, ++0x20, 0x73, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6D, 0x62, 0x6C, 0x6F, 0x63, ++0x6B, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x29, 0x00, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, ++0x4C, 0x00, 0x00, 0x00, 0x28, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x5F, 0x74, 0x29, 0x6D, 0x65, 0x6D, 0x5F, 0x70, 0x74, ++0x72, 0x20, 0x3E, 0x20, 0x28, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x5F, 0x74, 0x29, 0x6E, 0x6F, 0x64, 0x65, 0x00, 0x00, ++0x70, 0x72, 0x65, 0x76, 0x5F, 0x6E, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x2D, 0x3E, 0x6D, 0x73, 0x67, 0x5F, 0x74, ++0x61, 0x62, 0x6C, 0x65, 0x5B, 0x69, 0x5D, 0x2E, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, ++0x20, 0x3C, 0x20, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x6B, 0x65, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x5F, ++0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x28, 0x74, 0x79, 0x70, 0x65, 0x29, 0x00, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x54, 0x41, ++0x53, 0x4B, 0x5F, 0x44, 0x45, 0x53, 0x43, 0x5B, 0x74, 0x79, 0x70, 0x65, 0x5D, 0x2E, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, ++0x78, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x69, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x00, 0x00, ++0x80, 0x9D, 0x73, 0x65, 0x74, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x9A, 0x80, 0x4E, 0x6F, 0x20, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x66, ++0x6F, 0x72, 0x20, 0x6D, 0x73, 0x67, 0x3A, 0x25, 0x78, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, ++0x78, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x24, 0x9F, 0x15, 0x00, ++0x1C, 0x9F, 0x15, 0x00, 0xCC, 0x9C, 0x17, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xB5, 0x15, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xA4, 0x15, 0x00, 0xF0, 0x9F, 0x17, 0x00, ++0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x20, 0xBF, 0x15, 0x00, 0x18, 0xBF, 0x15, 0x00, 0xA4, 0xBA, 0x17, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x8C, 0xB8, 0x15, 0x00, 0xE0, 0xB8, 0x17, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xBB, 0x15, 0x00, ++0x60, 0xBA, 0x17, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xBE, 0x15, 0x00, 0x90, 0xBA, 0x17, 0x00, ++0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xC2, 0x15, 0x00, 0xF4, 0xDF, 0x17, 0x00, 0x05, 0x00, 0x20, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xD0, 0x15, 0x00, ++0x74, 0xEF, 0x17, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x28, 0x65, 0x76, 0x65, 0x6E, 0x74, 0x20, 0x3C, 0x20, 0x4B, 0x45, 0x5F, 0x45, 0x56, 0x54, 0x5F, ++0x4D, 0x41, 0x58, 0x29, 0x20, 0x26, 0x26, 0x20, 0x6B, 0x65, 0x5F, 0x65, 0x76, 0x74, 0x5F, 0x68, 0x64, 0x6C, 0x72, 0x5B, ++0x65, 0x76, 0x65, 0x6E, 0x74, 0x5D, 0x2E, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x68, 0x64, 0x72, ++0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, ++0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x28, 0x70, 0x72, 0x65, 0x76, 0x5F, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, ++0x74, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x70, 0x72, 0x65, 0x76, 0x5F, ++0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x2D, 0x3E, 0x6E, 0x65, 0x78, 0x74, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6C, 0x65, ++0x6D, 0x65, 0x6E, 0x74, 0x29, 0x00, 0x00, 0x00, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, ++0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x30, 0x07, 0x77, 0x2C, 0x61, 0x0E, 0xEE, 0xBA, 0x51, 0x09, 0x99, ++0x19, 0xC4, 0x6D, 0x07, 0x8F, 0xF4, 0x6A, 0x70, 0x35, 0xA5, 0x63, 0xE9, 0xA3, 0x95, 0x64, 0x9E, 0x32, 0x88, 0xDB, 0x0E, ++0xA4, 0xB8, 0xDC, 0x79, 0x1E, 0xE9, 0xD5, 0xE0, 0x88, 0xD9, 0xD2, 0x97, 0x2B, 0x4C, 0xB6, 0x09, 0xBD, 0x7C, 0xB1, 0x7E, ++0x07, 0x2D, 0xB8, 0xE7, 0x91, 0x1D, 0xBF, 0x90, 0x64, 0x10, 0xB7, 0x1D, 0xF2, 0x20, 0xB0, 0x6A, 0x48, 0x71, 0xB9, 0xF3, ++0xDE, 0x41, 0xBE, 0x84, 0x7D, 0xD4, 0xDA, 0x1A, 0xEB, 0xE4, 0xDD, 0x6D, 0x51, 0xB5, 0xD4, 0xF4, 0xC7, 0x85, 0xD3, 0x83, ++0x56, 0x98, 0x6C, 0x13, 0xC0, 0xA8, 0x6B, 0x64, 0x7A, 0xF9, 0x62, 0xFD, 0xEC, 0xC9, 0x65, 0x8A, 0x4F, 0x5C, 0x01, 0x14, ++0xD9, 0x6C, 0x06, 0x63, 0x63, 0x3D, 0x0F, 0xFA, 0xF5, 0x0D, 0x08, 0x8D, 0xC8, 0x20, 0x6E, 0x3B, 0x5E, 0x10, 0x69, 0x4C, ++0xE4, 0x41, 0x60, 0xD5, 0x72, 0x71, 0x67, 0xA2, 0xD1, 0xE4, 0x03, 0x3C, 0x47, 0xD4, 0x04, 0x4B, 0xFD, 0x85, 0x0D, 0xD2, ++0x6B, 0xB5, 0x0A, 0xA5, 0xFA, 0xA8, 0xB5, 0x35, 0x6C, 0x98, 0xB2, 0x42, 0xD6, 0xC9, 0xBB, 0xDB, 0x40, 0xF9, 0xBC, 0xAC, ++0xE3, 0x6C, 0xD8, 0x32, 0x75, 0x5C, 0xDF, 0x45, 0xCF, 0x0D, 0xD6, 0xDC, 0x59, 0x3D, 0xD1, 0xAB, 0xAC, 0x30, 0xD9, 0x26, ++0x3A, 0x00, 0xDE, 0x51, 0x80, 0x51, 0xD7, 0xC8, 0x16, 0x61, 0xD0, 0xBF, 0xB5, 0xF4, 0xB4, 0x21, 0x23, 0xC4, 0xB3, 0x56, ++0x99, 0x95, 0xBA, 0xCF, 0x0F, 0xA5, 0xBD, 0xB8, 0x9E, 0xB8, 0x02, 0x28, 0x08, 0x88, 0x05, 0x5F, 0xB2, 0xD9, 0x0C, 0xC6, ++0x24, 0xE9, 0x0B, 0xB1, 0x87, 0x7C, 0x6F, 0x2F, 0x11, 0x4C, 0x68, 0x58, 0xAB, 0x1D, 0x61, 0xC1, 0x3D, 0x2D, 0x66, 0xB6, ++0x90, 0x41, 0xDC, 0x76, 0x06, 0x71, 0xDB, 0x01, 0xBC, 0x20, 0xD2, 0x98, 0x2A, 0x10, 0xD5, 0xEF, 0x89, 0x85, 0xB1, 0x71, ++0x1F, 0xB5, 0xB6, 0x06, 0xA5, 0xE4, 0xBF, 0x9F, 0x33, 0xD4, 0xB8, 0xE8, 0xA2, 0xC9, 0x07, 0x78, 0x34, 0xF9, 0x00, 0x0F, ++0x8E, 0xA8, 0x09, 0x96, 0x18, 0x98, 0x0E, 0xE1, 0xBB, 0x0D, 0x6A, 0x7F, 0x2D, 0x3D, 0x6D, 0x08, 0x97, 0x6C, 0x64, 0x91, ++0x01, 0x5C, 0x63, 0xE6, 0xF4, 0x51, 0x6B, 0x6B, 0x62, 0x61, 0x6C, 0x1C, 0xD8, 0x30, 0x65, 0x85, 0x4E, 0x00, 0x62, 0xF2, ++0xED, 0x95, 0x06, 0x6C, 0x7B, 0xA5, 0x01, 0x1B, 0xC1, 0xF4, 0x08, 0x82, 0x57, 0xC4, 0x0F, 0xF5, 0xC6, 0xD9, 0xB0, 0x65, ++0x50, 0xE9, 0xB7, 0x12, 0xEA, 0xB8, 0xBE, 0x8B, 0x7C, 0x88, 0xB9, 0xFC, 0xDF, 0x1D, 0xDD, 0x62, 0x49, 0x2D, 0xDA, 0x15, ++0xF3, 0x7C, 0xD3, 0x8C, 0x65, 0x4C, 0xD4, 0xFB, 0x58, 0x61, 0xB2, 0x4D, 0xCE, 0x51, 0xB5, 0x3A, 0x74, 0x00, 0xBC, 0xA3, ++0xE2, 0x30, 0xBB, 0xD4, 0x41, 0xA5, 0xDF, 0x4A, 0xD7, 0x95, 0xD8, 0x3D, 0x6D, 0xC4, 0xD1, 0xA4, 0xFB, 0xF4, 0xD6, 0xD3, ++0x6A, 0xE9, 0x69, 0x43, 0xFC, 0xD9, 0x6E, 0x34, 0x46, 0x88, 0x67, 0xAD, 0xD0, 0xB8, 0x60, 0xDA, 0x73, 0x2D, 0x04, 0x44, ++0xE5, 0x1D, 0x03, 0x33, 0x5F, 0x4C, 0x0A, 0xAA, 0xC9, 0x7C, 0x0D, 0xDD, 0x3C, 0x71, 0x05, 0x50, 0xAA, 0x41, 0x02, 0x27, ++0x10, 0x10, 0x0B, 0xBE, 0x86, 0x20, 0x0C, 0xC9, 0x25, 0xB5, 0x68, 0x57, 0xB3, 0x85, 0x6F, 0x20, 0x09, 0xD4, 0x66, 0xB9, ++0x9F, 0xE4, 0x61, 0xCE, 0x0E, 0xF9, 0xDE, 0x5E, 0x98, 0xC9, 0xD9, 0x29, 0x22, 0x98, 0xD0, 0xB0, 0xB4, 0xA8, 0xD7, 0xC7, ++0x17, 0x3D, 0xB3, 0x59, 0x81, 0x0D, 0xB4, 0x2E, 0x3B, 0x5C, 0xBD, 0xB7, 0xAD, 0x6C, 0xBA, 0xC0, 0x20, 0x83, 0xB8, 0xED, ++0xB6, 0xB3, 0xBF, 0x9A, 0x0C, 0xE2, 0xB6, 0x03, 0x9A, 0xD2, 0xB1, 0x74, 0x39, 0x47, 0xD5, 0xEA, 0xAF, 0x77, 0xD2, 0x9D, ++0x15, 0x26, 0xDB, 0x04, 0x83, 0x16, 0xDC, 0x73, 0x12, 0x0B, 0x63, 0xE3, 0x84, 0x3B, 0x64, 0x94, 0x3E, 0x6A, 0x6D, 0x0D, ++0xA8, 0x5A, 0x6A, 0x7A, 0x0B, 0xCF, 0x0E, 0xE4, 0x9D, 0xFF, 0x09, 0x93, 0x27, 0xAE, 0x00, 0x0A, 0xB1, 0x9E, 0x07, 0x7D, ++0x44, 0x93, 0x0F, 0xF0, 0xD2, 0xA3, 0x08, 0x87, 0x68, 0xF2, 0x01, 0x1E, 0xFE, 0xC2, 0x06, 0x69, 0x5D, 0x57, 0x62, 0xF7, ++0xCB, 0x67, 0x65, 0x80, 0x71, 0x36, 0x6C, 0x19, 0xE7, 0x06, 0x6B, 0x6E, 0x76, 0x1B, 0xD4, 0xFE, 0xE0, 0x2B, 0xD3, 0x89, ++0x5A, 0x7A, 0xDA, 0x10, 0xCC, 0x4A, 0xDD, 0x67, 0x6F, 0xDF, 0xB9, 0xF9, 0xF9, 0xEF, 0xBE, 0x8E, 0x43, 0xBE, 0xB7, 0x17, ++0xD5, 0x8E, 0xB0, 0x60, 0xE8, 0xA3, 0xD6, 0xD6, 0x7E, 0x93, 0xD1, 0xA1, 0xC4, 0xC2, 0xD8, 0x38, 0x52, 0xF2, 0xDF, 0x4F, ++0xF1, 0x67, 0xBB, 0xD1, 0x67, 0x57, 0xBC, 0xA6, 0xDD, 0x06, 0xB5, 0x3F, 0x4B, 0x36, 0xB2, 0x48, 0xDA, 0x2B, 0x0D, 0xD8, ++0x4C, 0x1B, 0x0A, 0xAF, 0xF6, 0x4A, 0x03, 0x36, 0x60, 0x7A, 0x04, 0x41, 0xC3, 0xEF, 0x60, 0xDF, 0x55, 0xDF, 0x67, 0xA8, ++0xEF, 0x8E, 0x6E, 0x31, 0x79, 0xBE, 0x69, 0x46, 0x8C, 0xB3, 0x61, 0xCB, 0x1A, 0x83, 0x66, 0xBC, 0xA0, 0xD2, 0x6F, 0x25, ++0x36, 0xE2, 0x68, 0x52, 0x95, 0x77, 0x0C, 0xCC, 0x03, 0x47, 0x0B, 0xBB, 0xB9, 0x16, 0x02, 0x22, 0x2F, 0x26, 0x05, 0x55, ++0xBE, 0x3B, 0xBA, 0xC5, 0x28, 0x0B, 0xBD, 0xB2, 0x92, 0x5A, 0xB4, 0x2B, 0x04, 0x6A, 0xB3, 0x5C, 0xA7, 0xFF, 0xD7, 0xC2, ++0x31, 0xCF, 0xD0, 0xB5, 0x8B, 0x9E, 0xD9, 0x2C, 0x1D, 0xAE, 0xDE, 0x5B, 0xB0, 0xC2, 0x64, 0x9B, 0x26, 0xF2, 0x63, 0xEC, ++0x9C, 0xA3, 0x6A, 0x75, 0x0A, 0x93, 0x6D, 0x02, 0xA9, 0x06, 0x09, 0x9C, 0x3F, 0x36, 0x0E, 0xEB, 0x85, 0x67, 0x07, 0x72, ++0x13, 0x57, 0x00, 0x05, 0x82, 0x4A, 0xBF, 0x95, 0x14, 0x7A, 0xB8, 0xE2, 0xAE, 0x2B, 0xB1, 0x7B, 0x38, 0x1B, 0xB6, 0x0C, ++0x9B, 0x8E, 0xD2, 0x92, 0x0D, 0xBE, 0xD5, 0xE5, 0xB7, 0xEF, 0xDC, 0x7C, 0x21, 0xDF, 0xDB, 0x0B, 0xD4, 0xD2, 0xD3, 0x86, ++0x42, 0xE2, 0xD4, 0xF1, 0xF8, 0xB3, 0xDD, 0x68, 0x6E, 0x83, 0xDA, 0x1F, 0xCD, 0x16, 0xBE, 0x81, 0x5B, 0x26, 0xB9, 0xF6, ++0xE1, 0x77, 0xB0, 0x6F, 0x77, 0x47, 0xB7, 0x18, 0xE6, 0x5A, 0x08, 0x88, 0x70, 0x6A, 0x0F, 0xFF, 0xCA, 0x3B, 0x06, 0x66, ++0x5C, 0x0B, 0x01, 0x11, 0xFF, 0x9E, 0x65, 0x8F, 0x69, 0xAE, 0x62, 0xF8, 0xD3, 0xFF, 0x6B, 0x61, 0x45, 0xCF, 0x6C, 0x16, ++0x78, 0xE2, 0x0A, 0xA0, 0xEE, 0xD2, 0x0D, 0xD7, 0x54, 0x83, 0x04, 0x4E, 0xC2, 0xB3, 0x03, 0x39, 0x61, 0x26, 0x67, 0xA7, ++0xF7, 0x16, 0x60, 0xD0, 0x4D, 0x47, 0x69, 0x49, 0xDB, 0x77, 0x6E, 0x3E, 0x4A, 0x6A, 0xD1, 0xAE, 0xDC, 0x5A, 0xD6, 0xD9, ++0x66, 0x0B, 0xDF, 0x40, 0xF0, 0x3B, 0xD8, 0x37, 0x53, 0xAE, 0xBC, 0xA9, 0xC5, 0x9E, 0xBB, 0xDE, 0x7F, 0xCF, 0xB2, 0x47, ++0xE9, 0xFF, 0xB5, 0x30, 0x1C, 0xF2, 0xBD, 0xBD, 0x8A, 0xC2, 0xBA, 0xCA, 0x30, 0x93, 0xB3, 0x53, 0xA6, 0xA3, 0xB4, 0x24, ++0x05, 0x36, 0xD0, 0xBA, 0x93, 0x06, 0xD7, 0xCD, 0x29, 0x57, 0xDE, 0x54, 0xBF, 0x67, 0xD9, 0x23, 0x2E, 0x7A, 0x66, 0xB3, ++0xB8, 0x4A, 0x61, 0xC4, 0x02, 0x1B, 0x68, 0x5D, 0x94, 0x2B, 0x6F, 0x2A, 0x37, 0xBE, 0x0B, 0xB4, 0xA1, 0x8E, 0x0C, 0xC3, ++0x1B, 0xDF, 0x05, 0x5A, 0x8D, 0xEF, 0x02, 0x2D, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6E, 0x64, 0x00, ++0x00, 0x50, 0xF2, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x03, ++0x04, 0x08, 0x02, 0x01, 0x01, 0x00, 0x02, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x02, 0x04, 0x0B, 0x16, ++0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, ++0x44, 0x42, 0x47, 0x5F, 0x53, 0x45, 0x56, 0x5F, 0x4D, 0x49, 0x4E, 0x20, 0x3C, 0x3D, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, ++0x78, 0x20, 0x26, 0x26, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3C, 0x20, 0x44, 0x42, 0x47, 0x5F, 0x53, 0x45, ++0x56, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, ++0x63, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, ++0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, ++0x03, 0x02, 0x06, 0x07, 0x00, 0x00, 0x04, 0x02, 0x03, 0x02, 0x06, 0x07, 0x00, 0x00, 0x04, 0x03, 0x03, 0x00, 0x06, 0x07, ++0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x2C, 0x20, 0x77, 0x6C, 0x61, ++0x6E, 0x20, 0x66, 0x63, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x62, 0x6F, ++0x6F, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x70, 0x69, 0x6F, 0x77, 0x72, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, ++0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x53, ++0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x20, 0x66, 0x69, 0x6C, 0x74, ++0x65, 0x72, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x53, ++0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x20, 0x66, 0x69, 0x6C, 0x74, 0x65, 0x72, ++0x3A, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x42, ++0x6F, 0x6F, 0x74, 0x20, 0x4E, 0x50, 0x43, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x57, ++0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6D, ++0x61, 0x73, 0x6B, 0x3A, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x3A, 0x30, 0x78, 0x25, ++0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, ++0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, ++0x47, 0x3A, 0x20, 0x57, 0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x77, 0x69, ++0x74, 0x68, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, ++0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, ++0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x52, 0x65, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, ++0x79, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, ++0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x42, 0x6F, 0x6F, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, ++0x25, 0x78, 0x2C, 0x20, 0x61, 0x64, 0x64, 0x72, 0x3D, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x64, 0x65, 0x6C, 0x61, 0x79, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, ++0x62, 0x6F, 0x6F, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0D, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x46, ++0x57, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x57, ++0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x7E, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x77, 0x69, ++0x74, 0x68, 0x20, 0x7B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x2E, 0x2E, 0x2E, 0x7D, 0x2C, 0x20, 0x77, 0x73, ++0x74, 0x61, 0x74, 0x75, 0x73, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x70, 0x22, 0x17, 0x00, ++0x0C, 0x00, 0x00, 0x00, 0x9B, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x20, 0x28, 0x25, 0x73, 0x29, 0x20, 0x61, 0x74, 0x20, ++0x25, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x9B, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x20, 0x28, 0x25, 0x73, ++0x29, 0x20, 0x61, 0x74, 0x20, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x45, 0x72, 0x72, 0x3A, 0x20, 0x55, 0x46, 0x20, ++0x68, 0x6F, 0x73, 0x74, 0x20, 0x72, 0x78, 0x20, 0x62, 0x75, 0x66, 0x66, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x0D, 0x0A, 0x00, ++0x09, 0x2D, 0x20, 0x00, 0x25, 0x73, 0x25, 0x73, 0x25, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, ++0x25, 0x30, 0x32, 0x78, 0x20, 0x00, 0x00, 0x00, 0x25, 0x30, 0x38, 0x78, 0x3A, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x34, ++0x58, 0x20, 0x25, 0x30, 0x34, 0x58, 0x00, 0x00, 0x20, 0x25, 0x30, 0x32, 0x58, 0x20, 0x25, 0x30, 0x32, 0x58, 0x20, 0x25, ++0x30, 0x32, 0x58, 0x20, 0x25, 0x30, 0x32, 0x58, 0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x34, 0x58, 0x00, 0x00, 0x00, ++0x20, 0x25, 0x30, 0x32, 0x58, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x68, 0x65, 0x6C, ++0x70, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0x00, 0x68, 0x65, 0x6C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x20, 0x72, 0x20, 0x61, ++0x64, 0x64, 0x72, 0x20, 0x3C, 0x63, 0x6E, 0x74, 0x3E, 0x20, 0x3C, 0x73, 0x7A, 0x3E, 0x00, 0x00, 0x20, 0x77, 0x20, 0x61, ++0x64, 0x64, 0x72, 0x20, 0x76, 0x61, 0x6C, 0x00, 0x77, 0x00, 0x00, 0x00, 0x20, 0x64, 0x62, 0x67, 0x20, 0x6D, 0x73, 0x6B, ++0x00, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x00, 0x00, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x76, 0x61, 0x6C, 0x28, 0x69, 0x6E, ++0x20, 0x73, 0x29, 0x00, 0x77, 0x66, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, 0x20, 0x63, 0x6D, 0x64, ++0x5F, 0x66, 0x72, 0x65, 0x65, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x20, 0x65, 0x6D, 0x70, 0x74, 0x79, 0x0D, 0x0A, 0x00, 0x00, ++0x61, 0x69, 0x63, 0x3E, 0x20, 0x00, 0x00, 0x00, 0x4E, 0x6F, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x63, 0x6D, 0x64, 0x73, ++0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x64, 0x2E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x2A, 0x20, 0x54, ++0x6F, 0x6F, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, 0x28, 0x6D, 0x61, 0x78, 0x2E, 0x20, 0x25, ++0x64, 0x29, 0x20, 0x2A, 0x2A, 0x0A, 0x00, 0x00, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x20, 0x63, 0x6F, 0x6D, 0x6D, ++0x61, 0x6E, 0x64, 0x20, 0x27, 0x25, 0x73, 0x27, 0x0A, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x25, ++0x73, 0x0A, 0x00, 0x00, 0x63, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x0D, 0x0A, 0x00, 0x00, ++0x63, 0x75, 0x72, 0x20, 0x64, 0x62, 0x67, 0x5F, 0x6D, 0x73, 0x6B, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x63, 0x66, 0x67, 0x20, 0x64, 0x62, 0x67, 0x5F, 0x6D, 0x73, 0x6B, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x76, 0x61, ++0x6C, 0x69, 0x64, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, ++0x65, 0x3A, 0x0A, 0x20, 0x20, 0x72, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3C, 0x63, 0x6E, 0x74, 0x3E, 0x0A, 0x00, 0x00, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x0D, 0x0A, 0x00, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x32, 0x58, 0x0D, 0x0A, 0x00, ++0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x34, 0x58, 0x0D, 0x0A, 0x00, ++0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x20, 0x20, 0x77, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x76, 0x61, 0x6C, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x76, 0x61, 0x6C, ++0x28, 0x69, 0x6E, 0x20, 0x73, 0x29, 0x0A, 0x00, 0x63, 0x75, 0x72, 0x20, 0x77, 0x66, 0x63, 0x74, 0x3A, 0x20, 0x25, 0x75, ++0x73, 0x0A, 0x00, 0x00, 0x63, 0x66, 0x67, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x25, 0x75, 0x73, 0x0A, 0x00, 0x00, 0x00, ++0x77, 0x66, 0x63, 0x74, 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x0A, 0x00, 0x00, ++0x08, 0x20, 0x08, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x07, 0x00, 0x50, ++0xF2, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x45, 0x5F, ++0x42, 0x55, 0x53, 0x59, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x65, 0x6E, 0x76, ++0x2E, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x5F, 0x76, 0x69, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, ++0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x00, 0xD8, 0x22, 0x17, 0x00, 0x18, 0x00, 0x00, 0x00, ++0x62, 0x69, 0x74, 0x5F, 0x70, 0x6F, 0x73, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, 0x45, ++0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2D, 0x3E, 0x6C, 0x65, 0x6E, 0x67, 0x74, ++0x68, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x48, ++0x45, 0x29, 0x00, 0x00, 0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x56, 0x48, 0x54, 0x29, 0x00, ++0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x48, 0x54, 0x29, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, ++0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, ++0x63, 0x75, 0x72, 0x72, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x6D, 0x69, 0x63, 0x5F, 0x63, 0x61, 0x6C, 0x63, 0x5F, 0x70, 0x74, 0x72, 0x2D, 0x3E, 0x6C, 0x61, 0x73, 0x74, 0x5F, 0x6D, ++0x5F, 0x69, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x20, 0x34, 0x00, 0x00, 0x72, 0x65, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x75, 0x2E, 0x73, 0x74, 0x61, 0x2E, 0x61, 0x70, 0x5F, 0x69, 0x64, ++0x20, 0x3D, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x49, 0x44, 0x58, 0x00, ++0x63, 0x6F, 0x6E, 0x6E, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x20, 0x69, 0x6E, 0x64, 0x0D, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, ++0x20, 0x53, 0x4D, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x4E, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, ++0x20, 0x53, 0x4D, 0x5F, 0x4A, 0x4F, 0x49, 0x4E, 0x49, 0x4E, 0x47, 0x00, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x3A, 0x20, 0x25, ++0x34, 0x78, 0x3A, 0x25, 0x34, 0x78, 0x3A, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x28, 0x6B, 0x65, 0x5F, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, ++0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, ++0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, ++0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, ++0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, ++0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, ++0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, ++0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, ++0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, ++0x47, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, ++0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, ++0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, ++0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, ++0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x00, 0x00, ++0x73, 0x6D, 0x20, 0x63, 0x6F, 0x65, 0x78, 0x20, 0x74, 0x73, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0D, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, ++0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x41, 0x44, 0x44, 0x49, ++0x4E, 0x47, 0x00, 0x00, 0x98, 0x23, 0x17, 0x00, 0x15, 0x00, 0x00, 0x00, 0x74, 0x78, 0x20, 0x63, 0x66, 0x6D, 0x3A, 0x25, ++0x64, 0x2C, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x73, 0x5F, 0x65, ++0x6D, 0x70, 0x74, 0x79, 0x28, 0x26, 0x73, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x62, 0x73, 0x73, 0x5F, 0x63, 0x6F, 0x6E, ++0x66, 0x69, 0x67, 0x29, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x20, 0x72, 0x65, 0x6F, 0x75, 0x72, ++0x63, 0x65, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x2F, 0x64, 0x69, 0x73, 0x61, 0x73, ++0x73, 0x6F, 0x63, 0x3A, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x63, ++0x74, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x3A, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x61, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x61, 0x75, 0x74, 0x68, ++0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x61, 0x73, 0x73, 0x6F, ++0x63, 0x5F, 0x72, 0x73, 0x70, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x20, ++0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x61, 0x75, ++0x74, 0x68, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x20, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x20, 0x63, ++0x6F, 0x64, 0x65, 0x20, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x42, 0x53, 0x53, 0x5F, 0x43, 0x41, 0x50, 0x41, ++0x28, 0x62, 0x73, 0x73, 0x2C, 0x20, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x29, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x03, 0x00, ++0x00, 0x00, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x73, 0x6D, 0x5F, 0x61, 0x75, 0x74, 0x68, 0x5F, ++0x73, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6D, 0x5F, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x5F, 0x72, 0x65, 0x71, ++0x5F, 0x73, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, 0x43, ++0x4E, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, 0x61, 0x70, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, ++0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, ++0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, ++0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, ++0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, ++0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x20, 0x7C, 0x7C, ++0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, ++0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, ++0x29, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, ++0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, ++0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, ++0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, ++0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, ++0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, ++0x50, 0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, ++0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, ++0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x00, 0x00, 0x00, 0x00, 0x61, 0x70, 0x20, 0x73, ++0x74, 0x6F, 0x70, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x73, 0x5F, 0x65, ++0x6D, 0x70, 0x74, 0x79, 0x28, 0x26, 0x61, 0x70, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x62, 0x73, 0x73, 0x5F, 0x63, 0x6F, ++0x6E, 0x66, 0x69, 0x67, 0x29, 0x00, 0x00, 0x00, 0x40, 0x24, 0x17, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, ++0x75, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, ++0x75, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x0D, 0x0A, 0x00, ++0x73, 0x63, 0x61, 0x6E, 0x75, 0x20, 0x73, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x76, 0x6E, 0x64, 0x72, 0x20, ++0x69, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x63, 0x61, ++0x6E, 0x75, 0x20, 0x72, 0x65, 0x71, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x4D, 0x41, 0x43, ++0x5F, 0x41, 0x44, 0x44, 0x52, 0x5F, 0x47, 0x52, 0x4F, 0x55, 0x50, 0x28, 0x26, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, ++0x62, 0x73, 0x73, 0x69, 0x64, 0x29, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x20, 0x76, 0x6E, 0x64, 0x72, 0x20, 0x69, ++0x65, 0x0D, 0x0A, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x20, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x24, 0x17, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC8, 0x24, 0x17, 0x00, ++0x05, 0x00, 0x00, 0x00, 0xF0, 0x24, 0x17, 0x00, 0x07, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x5F, 0x63, 0x6F, ++0x6E, 0x66, 0x69, 0x72, 0x6D, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x5B, 0x48, 0x49, 0x44, ++0x44, 0x45, 0x4E, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x2D, 0x00, 0x6A, 0x6F, 0x69, 0x6E, ++0x3A, 0x25, 0x73, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x66, 0x69, 0x78, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x6E, 0x6F, 0x5F, 0x73, ++0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x64, 0x20, ++0x25, 0x64, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x20, 0x25, 0x78, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00, 0x00, ++0x28, 0x69, 0x65, 0x5F, 0x62, 0x75, 0x66, 0x20, 0x2D, 0x20, 0x43, 0x50, 0x55, 0x32, 0x48, 0x57, 0x28, 0x69, 0x65, 0x2D, ++0x3E, 0x62, 0x75, 0x66, 0x29, 0x29, 0x20, 0x3C, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x49, ++0x45, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3A, ++0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x20, 0x61, ++0x72, 0x70, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x69, 0x70, 0x3D, 0x25, 0x78, 0x2E, 0x20, 0x76, 0x69, 0x66, 0x20, 0x69, 0x70, ++0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x78, 0x20, 0x61, 0x72, 0x70, 0x72, 0x65, 0x73, 0x70, 0x0A, 0x00, ++0x72, 0x78, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x2D, 0x3E, 0x76, 0x61, 0x6C, 0x2E, 0x73, 0x74, ++0x61, 0x74, 0x75, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x75, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x20, 0x73, ++0x74, 0x61, 0x74, 0x3A, 0x25, 0x64, 0x00, 0x00, 0x54, 0x4B, 0x49, 0x50, 0x20, 0x49, 0x43, 0x56, 0x20, 0x45, 0x52, 0x52, ++0x0A, 0x00, 0x00, 0x00, 0x64, 0x65, 0x66, 0x72, 0x61, 0x67, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, ++0x72, 0x78, 0x5F, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x2D, 0x3E, 0x6F, 0x6F, 0x6F, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x63, 0x6E, ++0x74, 0x00, 0x00, 0x00, 0x6F, 0x6C, 0x64, 0x5F, 0x77, 0x69, 0x6E, 0x5F, 0x62, 0x61, 0x72, 0x20, 0x64, 0x65, 0x74, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x2D, 0x3E, 0x6F, 0x6F, 0x6F, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x63, ++0x6E, 0x74, 0x3C, 0x3D, 0x36, 0x34, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x64, 0x65, 0x61, ++0x75, 0x74, 0x68, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x21, 0x3D, 0x20, ++0x30, 0x78, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6D, 0x61, 0x63, 0x68, 0x64, 0x72, 0x5F, 0x6C, 0x65, 0x6E, 0x67, ++0x74, 0x68, 0x20, 0x26, 0x20, 0x30, 0x78, 0x33, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x72, 0x78, 0x20, 0x65, ++0x61, 0x70, 0x6F, 0x6C, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x57, 0x45, 0x50, 0x20, ++0x49, 0x43, 0x56, 0x20, 0x45, 0x52, 0x52, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x20, 0x21, 0x3D, ++0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x72, 0x78, 0x75, 0x5F, 0x63, 0x6E, 0x74, 0x72, 0x6C, 0x5F, 0x73, 0x70, ++0x75, 0x72, 0x69, 0x6F, 0x75, 0x73, 0x5F, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x75, 0x20, ++0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x6D, 0x69, 0x74, 0x20, 0x74, 0x78, 0x75, 0x20, 0x64, ++0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x0A, 0x00, 0x70, 0x6F, 0x72, 0x74, 0x20, 0x66, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3A, ++0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x2D, 0x3E, 0x73, 0x74, 0x61, 0x69, 0x64, 0x20, ++0x21, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, ++0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x61, 0x64, 0x64, 0x62, 0x61, 0x5F, 0x72, 0x65, 0x71, 0x3A, 0x74, 0x69, 0x64, ++0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x61, 0x64, 0x64, 0x62, 0x61, ++0x5F, 0x72, 0x73, 0x70, 0x3A, 0x74, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, ++0x0A, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x72, 0x78, 0x5F, 0x64, 0x65, 0x6C, 0x62, 0x61, 0x3A, ++0x74, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, ++0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x74, 0x78, 0x5F, 0x64, 0x65, 0x6C, 0x62, 0x61, 0x3A, 0x74, 0x69, 0x64, 0x3D, ++0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x2C, 0x25, 0x17, 0x00, ++0x05, 0x00, 0x00, 0x00, 0x6D, 0x6F, 0x76, 0x65, 0x20, 0x77, 0x69, 0x6E, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x66, ++0x6C, 0x75, 0x73, 0x68, 0x3A, 0x20, 0x73, 0x75, 0x63, 0x63, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x70, ++0x61, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, ++0x28, 0x4B, 0x45, 0x5F, 0x42, 0x55, 0x49, 0x4C, 0x44, 0x5F, 0x49, 0x44, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x42, 0x41, ++0x4D, 0x2C, 0x20, 0x62, 0x61, 0x6D, 0x5F, 0x69, 0x64, 0x78, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x41, 0x4D, 0x5F, ++0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x00, 0x00, 0x62, 0x61, 0x6D, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x42, 0x41, ++0x4D, 0x5F, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, ++0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, ++0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, ++0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, ++0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, ++0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, ++0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, ++0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, ++0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, ++0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, ++0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, ++0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, ++0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, ++0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, ++0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, ++0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, 0xC6, 0xF8, 0xEE, 0xF6, ++0xFF, 0xD6, 0xDE, 0x91, 0x60, 0x02, 0xCE, 0x56, 0xE7, 0xB5, 0x4D, 0xEC, 0x8F, 0x1F, 0x89, 0xFA, 0xEF, 0xB2, 0x8E, 0xFB, ++0x41, 0xB3, 0x5F, 0x45, 0x23, 0x53, 0xE4, 0x9B, 0x75, 0xE1, 0x3D, 0x4C, 0x6C, 0x7E, 0xF5, 0x83, 0x68, 0x51, 0xD1, 0xF9, ++0xE2, 0xAB, 0x62, 0x2A, 0x08, 0x95, 0x46, 0x9D, 0x30, 0x37, 0x0A, 0x2F, 0x0E, 0x24, 0x1B, 0xDF, 0xCD, 0x4E, 0x7F, 0xEA, ++0x12, 0x1D, 0x58, 0x34, 0x36, 0xDC, 0xB4, 0x5B, 0xA4, 0x76, 0xB7, 0x7D, 0x52, 0xDD, 0x5E, 0x13, 0xA6, 0xB9, 0x00, 0xC1, ++0x40, 0xE3, 0x79, 0xB6, 0xD4, 0x8D, 0x67, 0x72, 0x94, 0x98, 0xB0, 0x85, 0xBB, 0xC5, 0x4F, 0xED, 0x86, 0x9A, 0x66, 0x11, ++0x8A, 0xE9, 0x04, 0xFE, 0xA0, 0x78, 0x25, 0x4B, 0xA2, 0x5D, 0x80, 0x05, 0x3F, 0x21, 0x70, 0xF1, 0x63, 0x77, 0xAF, 0x42, ++0x20, 0xE5, 0xFD, 0xBF, 0x81, 0x18, 0x26, 0xC3, 0xBE, 0x35, 0x88, 0x2E, 0x93, 0x55, 0xFC, 0x7A, 0xC8, 0xBA, 0x32, 0xE6, ++0xC0, 0x19, 0x9E, 0xA3, 0x44, 0x54, 0x3B, 0x0B, 0x8C, 0xC7, 0x6B, 0x28, 0xA7, 0xBC, 0x16, 0xAD, 0xDB, 0x64, 0x74, 0x14, ++0x92, 0x0C, 0x48, 0xB8, 0x9F, 0xBD, 0x43, 0xC4, 0x39, 0x31, 0xD3, 0xF2, 0xD5, 0x8B, 0x6E, 0xDA, 0x01, 0xB1, 0x9C, 0x49, ++0xD8, 0xAC, 0xF3, 0xCF, 0xCA, 0xF4, 0x47, 0x10, 0x6F, 0xF0, 0x4A, 0x5C, 0x38, 0x57, 0x73, 0x97, 0xCB, 0xA1, 0xE8, 0x3E, ++0x96, 0x61, 0x0D, 0x0F, 0xE0, 0x7C, 0x71, 0xCC, 0x90, 0x06, 0xF7, 0x1C, 0xC2, 0x6A, 0xAE, 0x69, 0x17, 0x99, 0x3A, 0x27, ++0xD9, 0xEB, 0x2B, 0x22, 0xD2, 0xA9, 0x07, 0x33, 0x2D, 0x3C, 0x15, 0xC9, 0x87, 0xAA, 0x50, 0xA5, 0x03, 0x59, 0x09, 0x1A, ++0x65, 0xD7, 0x84, 0xD0, 0x82, 0x29, 0x5A, 0x1E, 0x7B, 0xA8, 0x6D, 0x2C, 0xA5, 0x84, 0x99, 0x8D, 0x0D, 0xBD, 0xB1, 0x54, ++0x50, 0x03, 0xA9, 0x7D, 0x19, 0x62, 0xE6, 0x9A, 0x45, 0x9D, 0x40, 0x87, 0x15, 0xEB, 0xC9, 0x0B, 0xEC, 0x67, 0xFD, 0xEA, ++0xBF, 0xF7, 0x96, 0x5B, 0xC2, 0x1C, 0xAE, 0x6A, 0x5A, 0x41, 0x02, 0x4F, 0x5C, 0xF4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3F, ++0x0C, 0x52, 0x65, 0x5E, 0x28, 0xA1, 0x0F, 0xB5, 0x09, 0x36, 0x9B, 0x3D, 0x26, 0x69, 0xCD, 0x9F, 0x1B, 0x9E, 0x74, 0x2E, ++0x2D, 0xB2, 0xEE, 0xFB, 0xF6, 0x4D, 0x61, 0xCE, 0x7B, 0x3E, 0x71, 0x97, 0xF5, 0x68, 0x00, 0x2C, 0x60, 0x1F, 0xC8, 0xED, ++0xBE, 0x46, 0xD9, 0x4B, 0xDE, 0xD4, 0xE8, 0x4A, 0x6B, 0x2A, 0xE5, 0x16, 0xC5, 0xD7, 0x55, 0x94, 0xCF, 0x10, 0x06, 0x81, ++0xF0, 0x44, 0xBA, 0xE3, 0xF3, 0xFE, 0xC0, 0x8A, 0xAD, 0xBC, 0x48, 0x04, 0xDF, 0xC1, 0x75, 0x63, 0x30, 0x1A, 0x0E, 0x6D, ++0x4C, 0x14, 0x35, 0x2F, 0xE1, 0xA2, 0xCC, 0x39, 0x57, 0xF2, 0x82, 0x47, 0xAC, 0xE7, 0x2B, 0x95, 0xA0, 0x98, 0xD1, 0x7F, ++0x66, 0x7E, 0xAB, 0x83, 0xCA, 0x29, 0xD3, 0x3C, 0x79, 0xE2, 0x1D, 0x76, 0x3B, 0x56, 0x4E, 0x1E, 0xDB, 0x0A, 0x6C, 0xE4, ++0x5D, 0x6E, 0xEF, 0xA6, 0xA8, 0xA4, 0x37, 0x8B, 0x32, 0x43, 0x59, 0xB7, 0x8C, 0x64, 0xD2, 0xE0, 0xB4, 0xFA, 0x07, 0x25, ++0xAF, 0x8E, 0xE9, 0x18, 0xD5, 0x88, 0x6F, 0x72, 0x24, 0xF1, 0xC7, 0x51, 0x23, 0x7C, 0x9C, 0x21, 0xDD, 0xDC, 0x86, 0x85, ++0x90, 0x42, 0xC4, 0xAA, 0xD8, 0x05, 0x01, 0x12, 0xA3, 0x5F, 0xF9, 0xD0, 0x91, 0x58, 0x27, 0xB9, 0x38, 0x13, 0xB3, 0x33, ++0xBB, 0x70, 0x89, 0xA7, 0xB6, 0x22, 0x92, 0x20, 0x49, 0xFF, 0x78, 0x7A, 0x8F, 0xF8, 0x80, 0x17, 0xDA, 0x31, 0xC6, 0xB8, ++0xC3, 0xB0, 0x77, 0x11, 0xCB, 0xFC, 0xD6, 0x3A, 0x72, 0x63, 0x5F, 0x72, 0x73, 0x2D, 0x3E, 0x61, 0x74, 0x74, 0x65, 0x6D, ++0x70, 0x74, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x72, 0x73, 0x2D, 0x3E, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, ++0x73, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, 0x3D, 0x20, 0x46, 0x4F, ++0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, 0x45, 0x5F, 0x53, 0x55, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, ++0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, ++0x54, 0x5F, 0x4D, 0x46, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, ++0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x00, 0x00, 0x28, 0x66, 0x6F, 0x72, ++0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, ++0x5F, 0x48, 0x54, 0x5F, 0x4D, 0x46, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, ++0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, 0x54, 0x5F, 0x47, ++0x46, 0x29, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, ++0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x20, 0x7C, 0x7C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, ++0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, ++0x4F, 0x4E, 0x5F, 0x48, 0x54, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, ++0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x00, 0x28, 0x66, 0x6F, 0x72, ++0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, ++0x5F, 0x48, 0x45, 0x5F, 0x53, 0x55, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, ++0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, 0x4F, 0x4E, 0x5F, ++0x48, 0x54, 0x29, 0x00, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x00, ++0x73, 0x67, 0x69, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, ++0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, ++0x6D, 0x63, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, ++0x6D, 0x69, 0x6E, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, ++0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, ++0x5F, 0x6D, 0x61, 0x70, 0x5F, 0x6C, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, 0x54, 0x28, 0x6D, 0x63, 0x73, 0x29, ++0x29, 0x00, 0x00, 0x00, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, ++0x73, 0x67, 0x69, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x73, 0x68, 0x6F, 0x72, 0x74, 0x5F, ++0x67, 0x69, 0x00, 0x00, 0x62, 0x77, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, 0x77, 0x5F, ++0x6D, 0x61, 0x78, 0x00, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, ++0x5F, 0x73, 0x73, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, 0x63, ++0x73, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x00, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, ++0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x68, 0x74, 0x5B, 0x6E, 0x73, 0x73, 0x5D, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, ++0x54, 0x28, 0x6D, 0x63, 0x73, 0x29, 0x29, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x28, 0x37, 0x20, 0x2B, 0x20, ++0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, 0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x76, 0x68, 0x74, ++0x20, 0x3E, 0x3E, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3C, 0x20, 0x31, 0x29, 0x20, 0x26, 0x20, 0x4D, 0x41, 0x43, ++0x5F, 0x56, 0x48, 0x54, 0x5F, 0x4D, 0x43, 0x53, 0x5F, 0x4D, 0x41, 0x50, 0x5F, 0x4D, 0x53, 0x4B, 0x29, 0x29, 0x00, 0x00, ++0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x36, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, ++0x3D, 0x20, 0x42, 0x57, 0x5F, 0x38, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x28, 0x6E, 0x73, 0x73, ++0x20, 0x3D, 0x3D, 0x20, 0x33, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x36, 0x29, ++0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, ++0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, ++0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, ++0x73, 0x20, 0x21, 0x3D, 0x20, 0x35, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x28, 0x28, 0x6D, 0x63, ++0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, ++0x5F, 0x38, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x35, ++0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, ++0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x31, 0x36, 0x30, 0x4D, 0x48, 0x5A, 0x29, ++0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x32, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, ++0x00, 0x00, 0x00, 0x00, 0x67, 0x69, 0x20, 0x3C, 0x3D, 0x20, 0x32, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x28, ++0x37, 0x20, 0x2B, 0x20, 0x32, 0x20, 0x2A, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, ++0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x68, 0x65, 0x20, 0x3E, 0x3E, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3C, 0x20, 0x31, ++0x29, 0x20, 0x26, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x45, 0x5F, 0x4D, 0x43, 0x53, 0x5F, 0x4D, 0x41, 0x50, 0x5F, 0x4D, ++0x53, 0x4B, 0x29, 0x29, 0x00, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, 0x5F, 0x73, 0x61, ++0x6D, 0x70, 0x6C, 0x65, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, ++0x6F, 0x5F, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x52, 0x43, 0x5F, 0x4D, 0x41, 0x58, 0x5F, ++0x4E, 0x5F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, ++0x77, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x31, 0x36, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, ++0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, 0x5F, 0x73, 0x73, 0x20, 0x3C, 0x20, 0x38, 0x00, 0x00, 0x00, 0x00, ++0x73, 0x74, 0x61, 0x2D, 0x3E, 0x73, 0x74, 0x61, 0x69, 0x64, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, ++0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, ++0x63, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x31, 0x32, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x52, 0x41, 0x54, 0x45, ++0x5F, 0x31, 0x31, 0x4D, 0x42, 0x50, 0x53, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, ++0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x29, 0x00, 0x00, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x52, 0x41, 0x54, 0x45, ++0x5F, 0x31, 0x31, 0x4D, 0x42, 0x50, 0x53, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, ++0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, ++0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x29, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, ++0x63, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x31, 0x30, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, ++0x6F, 0x5F, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x33, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, ++0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, ++0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, 0x69, 0x64, 0x78, ++0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, ++0x45, 0x4E, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, 0x77, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3D, 0x3D, ++0x20, 0x42, 0x57, 0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x74, ++0x69, 0x6F, 0x6E, 0x5F, 0x69, 0x64, 0x3D, 0x25, 0x69, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, ++0x3D, 0x25, 0x69, 0x20, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x25, 0x69, 0x20, 0x73, 0x68, 0x6F, 0x72, ++0x74, 0x5F, 0x67, 0x69, 0x3D, 0x25, 0x69, 0x20, 0x6D, 0x61, 0x78, 0x5F, 0x62, 0x77, 0x3D, 0x25, 0x69, 0x0A, 0x00, 0x00, ++0x25, 0x73, 0x3A, 0x20, 0x6E, 0x73, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x6D, 0x63, 0x73, 0x5F, 0x6D, ++0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x3D, 0x25, 0x69, 0x20, 0x72, ++0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x6E, 0x6F, 0x5F, 0x73, 0x61, 0x6D, 0x70, 0x6C, ++0x65, 0x73, 0x3D, 0x25, 0x69, 0x0A, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x20, 0x7C, 0x9F, 0x00, ++0x20, 0xF3, 0xA0, 0x00, 0xA0, 0x17, 0x52, 0x00, 0xA0, 0x8E, 0x53, 0x00, 0xF8, 0x52, 0x23, 0x00, 0xF8, 0xC9, 0x24, 0x00, ++0x18, 0xF5, 0x15, 0x00, 0x18, 0x6C, 0x17, 0x00, 0xF9, 0x06, 0x11, 0x00, 0x62, 0x07, 0x12, 0x00, 0x35, 0x08, 0x14, 0x00, ++0xD1, 0x10, 0x04, 0x00, 0x0A, 0x4E, 0x04, 0x00, 0x7D, 0xC8, 0x04, 0x00, 0x7D, 0x83, 0x08, 0x00, 0xB1, 0x03, 0x09, 0x00, ++0x1A, 0x04, 0x0A, 0x00, 0x68, 0x08, 0x02, 0x00, 0x05, 0x27, 0x02, 0x00, 0x3F, 0x64, 0x02, 0x00, 0xFE, 0xAC, 0x05, 0x00, ++0x76, 0x02, 0x06, 0x00, 0x67, 0xAD, 0x06, 0x00, 0xF0, 0x5A, 0x01, 0x00, 0x59, 0x6F, 0x01, 0x00, 0x2A, 0x98, 0x01, 0x00, ++0xBE, 0x41, 0x04, 0x00, 0xD9, 0x81, 0x04, 0x00, 0x0D, 0x02, 0x05, 0x00, 0x34, 0x04, 0x01, 0x00, 0x83, 0x13, 0x01, 0x00, ++0x1F, 0x32, 0x01, 0x00, 0x7F, 0xD6, 0x02, 0x00, 0x3B, 0x01, 0x03, 0x00, 0xB3, 0x56, 0x03, 0x00, 0x78, 0xAD, 0x00, 0x00, ++0xAC, 0xB7, 0x00, 0x00, 0x15, 0xCC, 0x00, 0x00, 0xDF, 0x20, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, 0x07, 0x81, 0x02, 0x00, ++0x1A, 0x82, 0x00, 0x00, 0xC1, 0x89, 0x00, 0x00, 0x10, 0x99, 0x00, 0x00, 0x55, 0xE4, 0x01, 0x00, 0xD2, 0x00, 0x02, 0x00, ++0xCD, 0x39, 0x02, 0x00, 0xA5, 0x73, 0x00, 0x00, 0x73, 0x7A, 0x00, 0x00, 0x0E, 0x88, 0x00, 0x00, 0xE6, 0xB3, 0x01, 0x00, ++0x8A, 0xCD, 0x01, 0x00, 0xD2, 0x00, 0x02, 0x00, 0x15, 0x68, 0x00, 0x00, 0x34, 0x6E, 0x00, 0x00, 0x73, 0x7A, 0x00, 0x00, ++0x3F, 0x6B, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0x5A, 0xAB, 0x01, 0x00, 0xBC, 0x56, 0x00, 0x00, 0xD6, 0x5B, 0x00, 0x00, ++0x0A, 0x66, 0x00, 0x00, 0xEC, 0x46, 0x01, 0x00, 0x27, 0x5A, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0x11, 0x4E, 0x00, 0x00, ++0xA8, 0x52, 0x00, 0x00, 0xD7, 0x5B, 0x00, 0x00, 0x99, 0x22, 0x01, 0x00, 0xB1, 0x33, 0x01, 0x00, 0xE1, 0x55, 0x01, 0x00, ++0x63, 0x45, 0x00, 0x00, 0x78, 0x49, 0x00, 0x00, 0xA2, 0x51, 0x00, 0x00, 0x8A, 0x05, 0x01, 0x00, 0xEC, 0x14, 0x01, 0x00, ++0xB1, 0x33, 0x01, 0x00, 0x74, 0x3E, 0x00, 0x00, 0x21, 0x42, 0x00, 0x00, 0x7A, 0x49, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, ++0x3C, 0x5C, 0x29, 0x00, 0xB4, 0xF4, 0x2D, 0x00, 0x00, 0x88, 0x13, 0x00, 0x1E, 0xAE, 0x14, 0x00, 0x5A, 0xFA, 0x16, 0x00, ++0x55, 0x05, 0x0D, 0x00, 0x69, 0xC9, 0x0D, 0x00, 0x91, 0x51, 0x0F, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x0F, 0x57, 0x0A, 0x00, ++0x2D, 0x7D, 0x0B, 0x00, 0xAA, 0x82, 0x06, 0x00, 0xB4, 0xE4, 0x06, 0x00, 0xC8, 0xA8, 0x07, 0x00, 0x00, 0xE2, 0x04, 0x00, ++0x87, 0x2B, 0x05, 0x00, 0x96, 0xBE, 0x05, 0x00, 0x1C, 0x57, 0x04, 0x00, 0x78, 0x98, 0x04, 0x00, 0x30, 0x1B, 0x05, 0x00, ++0x00, 0xE8, 0x03, 0x00, 0xD2, 0x22, 0x04, 0x00, 0x78, 0x98, 0x04, 0x00, 0x55, 0x41, 0x03, 0x00, 0x5A, 0x72, 0x03, 0x00, ++0x64, 0xD4, 0x03, 0x00, 0x00, 0xEE, 0x02, 0x00, 0x1E, 0x1A, 0x03, 0x00, 0x5A, 0x72, 0x03, 0x00, 0xAA, 0x9A, 0x02, 0x00, ++0xE1, 0xC1, 0x02, 0x00, 0x50, 0x10, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x4B, 0x7B, 0x02, 0x00, 0xE1, 0xC1, 0x02, 0x00, ++0x00, 0x04, 0xA6, 0x00, 0x00, 0xC8, 0xAF, 0x00, 0x00, 0x50, 0xC3, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0xE4, 0x57, 0x00, ++0x00, 0xA8, 0x61, 0x00, 0xAA, 0x56, 0x37, 0x00, 0x00, 0x98, 0x3A, 0x00, 0xAA, 0x1A, 0x41, 0x00, 0x00, 0x81, 0x29, 0x00, ++0x00, 0xF2, 0x2B, 0x00, 0x00, 0xD4, 0x30, 0x00, 0x55, 0xAB, 0x1B, 0x00, 0x00, 0x4C, 0x1D, 0x00, 0x55, 0x8D, 0x20, 0x00, ++0x80, 0xC0, 0x14, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x38, 0x72, 0x12, 0x00, 0x00, 0x88, 0x13, 0x00, ++0x8E, 0xB3, 0x15, 0x00, 0x00, 0x9A, 0x10, 0x00, 0x00, 0x94, 0x11, 0x00, 0x00, 0x88, 0x13, 0x00, 0xAA, 0xD5, 0x0D, 0x00, ++0x00, 0xA6, 0x0E, 0x00, 0xAA, 0x46, 0x10, 0x00, 0x80, 0x73, 0x0C, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, 0xA6, 0x0E, 0x00, ++0x55, 0x11, 0x0B, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x55, 0x05, 0x0D, 0x00, 0x00, 0xF6, 0x09, 0x00, 0x00, 0x8C, 0x0A, 0x00, ++0x00, 0xB8, 0x0B, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, 0xA8, 0x61, 0x00, 0x00, 0x81, 0x29, 0x00, ++0x00, 0xF2, 0x2B, 0x00, 0x00, 0xD4, 0x30, 0x00, 0x55, 0xAB, 0x1B, 0x00, 0x00, 0x4C, 0x1D, 0x00, 0x55, 0x8D, 0x20, 0x00, ++0x80, 0xC0, 0x14, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x6A, 0x18, 0x00, 0xAA, 0xD5, 0x0D, 0x00, 0x00, 0xA6, 0x0E, 0x00, ++0xAA, 0x46, 0x10, 0x00, 0x40, 0x60, 0x0A, 0x00, 0x80, 0xFC, 0x0A, 0x00, 0x00, 0x35, 0x0C, 0x00, 0x1C, 0x39, 0x09, 0x00, ++0x00, 0xC4, 0x09, 0x00, 0xC7, 0xD9, 0x0A, 0x00, 0x00, 0x4D, 0x08, 0x00, 0x00, 0xCA, 0x08, 0x00, 0x00, 0xC4, 0x09, 0x00, ++0xD5, 0xEA, 0x06, 0x00, 0x00, 0x53, 0x07, 0x00, 0x55, 0x23, 0x08, 0x00, 0xC0, 0x39, 0x06, 0x00, 0x80, 0x97, 0x06, 0x00, ++0x00, 0x53, 0x07, 0x00, 0xAA, 0x88, 0x05, 0x00, 0x00, 0xDC, 0x05, 0x00, 0xAA, 0x82, 0x06, 0x00, 0x00, 0xFB, 0x04, 0x00, ++0x00, 0x46, 0x05, 0x00, 0x00, 0xDC, 0x05, 0x00, 0x3B, 0x89, 0x16, 0x00, 0x4F, 0x48, 0x14, 0x00, 0xC7, 0xD9, 0x0A, 0x00, ++0x00, 0xC4, 0x09, 0x00, 0x0D, 0x02, 0x05, 0x00, 0xD9, 0x81, 0x04, 0x00, 0x07, 0x81, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, ++0x9E, 0x44, 0x0B, 0x00, 0x27, 0x24, 0x0A, 0x00, 0xE4, 0x6C, 0x05, 0x00, 0x00, 0xE2, 0x04, 0x00, 0x07, 0x81, 0x02, 0x00, ++0xEC, 0x40, 0x02, 0x00, 0x83, 0x40, 0x01, 0x00, 0x76, 0x20, 0x01, 0x00, 0x14, 0x83, 0x07, 0x00, 0xC5, 0xC2, 0x06, 0x00, ++0xED, 0x9D, 0x03, 0x00, 0x55, 0x41, 0x03, 0x00, 0x5A, 0xAB, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0xAD, 0xD5, 0x00, 0x00, ++0x4F, 0xC0, 0x00, 0x00, 0x4F, 0xA2, 0x05, 0x00, 0x14, 0x12, 0x05, 0x00, 0x72, 0xB6, 0x02, 0x00, 0x00, 0x71, 0x02, 0x00, ++0x83, 0x40, 0x01, 0x00, 0x76, 0x20, 0x01, 0x00, 0x42, 0xA0, 0x00, 0x00, 0x3B, 0x90, 0x00, 0x00, 0x8A, 0xC1, 0x03, 0x00, ++0x62, 0x61, 0x03, 0x00, 0xF7, 0xCE, 0x01, 0x00, 0xAB, 0xA0, 0x01, 0x00, 0xAD, 0xD5, 0x00, 0x00, 0x4F, 0xC0, 0x00, 0x00, ++0xD6, 0x6A, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x27, 0xD1, 0x02, 0x00, 0x0A, 0x89, 0x02, 0x00, 0x39, 0x5B, 0x01, 0x00, ++0x80, 0x38, 0x01, 0x00, 0x42, 0xA0, 0x00, 0x00, 0x3B, 0x90, 0x00, 0x00, 0x21, 0x50, 0x00, 0x00, 0x1E, 0x48, 0x00, 0x00, ++0x07, 0x81, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, 0xA4, 0x34, 0x01, 0x00, 0xC7, 0x15, 0x01, 0x00, 0x73, 0x8E, 0x00, 0x00, ++0x35, 0x80, 0x00, 0x00, 0x3A, 0x47, 0x00, 0x00, 0x1A, 0x40, 0x00, 0x00, 0xEC, 0x40, 0x02, 0x00, 0x3B, 0x07, 0x02, 0x00, ++0xC7, 0x15, 0x01, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x35, 0x80, 0x00, 0x00, 0x62, 0x73, 0x00, 0x00, 0x1A, 0x40, 0x00, 0x00, ++0xB1, 0x39, 0x00, 0x00, 0xC5, 0xE0, 0x01, 0x00, 0xB1, 0xB0, 0x01, 0x00, 0x7B, 0xE7, 0x00, 0x00, 0x55, 0xD0, 0x00, 0x00, ++0xD6, 0x6A, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x6B, 0x35, 0x00, 0x00, 0x14, 0x30, 0x00, 0x00, 0xB1, 0xB0, 0x01, 0x00, ++0x6C, 0x85, 0x01, 0x00, 0x55, 0xD0, 0x00, 0x00, 0x80, 0xBB, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x8A, 0x56, 0x00, 0x00, ++0x14, 0x30, 0x00, 0x00, 0x45, 0x2B, 0x00, 0x00, 0x00, 0x6A, 0x18, 0x00, 0xE0, 0x4B, 0x10, 0x00, 0x00, 0x35, 0x0C, 0x00, ++0xC0, 0x2D, 0x08, 0x00, 0x80, 0x1A, 0x06, 0x00, 0xE0, 0x16, 0x04, 0x00, 0x40, 0x0D, 0x03, 0x00, 0x20, 0xBF, 0x02, 0x00, ++0x24, 0xCE, 0x15, 0x00, 0xB4, 0xCE, 0x15, 0x00, 0x94, 0xCD, 0x15, 0x00, 0xB8, 0xD0, 0x15, 0x00, 0x03, 0x00, 0x00, 0x00, ++0x00, 0x28, 0x00, 0x00, 0x39, 0x4B, 0x15, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x15, 0x4C, 0x15, 0x00, 0x01, 0x10, 0x00, 0x00, ++0xD5, 0x4B, 0x15, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x20, 0x3E, 0x3D, 0x20, 0x42, 0x43, 0x4E, 0x5F, 0x46, 0x49, 0x58, ++0x45, 0x44, 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x5F, 0x46, 0x49, 0x45, 0x4C, 0x44, 0x53, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, ++0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x62, 0x75, 0x66, 0x5F, 0x6C, 0x65, ++0x6E, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x73, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3E, 0x20, 0x30, 0x00, ++0x21, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x5F, 0x6D, 0x6F, 0x72, 0x65, 0x5F, 0x6D, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x5F, ++0x74, 0x6F, 0x5F, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x28, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x65, 0x71, 0x75, ++0x65, 0x73, 0x74, 0x2D, 0x3E, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x73, 0x65, 0x6E, 0x74, 0x20, 0x3D, 0x3D, 0x20, ++0x30, 0x29, 0x00, 0x00, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x6E, ++0x74, 0x20, 0x3C, 0x3D, 0x20, 0x43, 0x4F, 0x5F, 0x41, 0x52, 0x52, 0x41, 0x59, 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x28, 0x72, ++0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x29, 0x00, 0x00, ++0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, ++0x5F, 0x4D, 0x45, 0x41, 0x53, 0x5F, 0x52, 0x45, 0x51, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x45, 0x41, 0x43, 0x4F, ++0x4E, 0x00, 0x00, 0x00, 0x72, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x72, 0x65, ++0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x3E, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x64, 0x69, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, ++0x33, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x34, 0x37, 0x3A, 0x31, 0x34, 0x20, 0x2D, 0x20, 0x67, 0x37, ++0x34, 0x32, 0x30, 0x33, 0x31, 0x37, 0x31, 0x00, 0x76, 0x36, 0x2E, 0x34, 0x2E, 0x33, 0x2E, 0x31, 0x00, 0x00, 0x00, 0x00, ++0xF8, 0xB5, 0x00, 0xBF, 0xF8, 0xBC, 0x08, 0xBC, 0x9E, 0x46, 0x70, 0x47, 0xF8, 0xB5, 0x00, 0xBF, 0xF8, 0xBC, 0x08, 0xBC, ++0x9E, 0x46, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x74, 0x04, 0x17, 0x00, 0xDC, 0x04, 0x17, 0x00, 0x44, 0x05, 0x17, 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, 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, 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, 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, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x33, 0xCD, 0xAB, ++0x34, 0x12, 0x6D, 0xE6, 0xEC, 0xDE, 0x05, 0x00, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0E, 0x00, 0x00, 0x04, 0x0E, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x5B, ++0x4B, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x32, 0x7B, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, ++0x26, 0x00, 0x00, 0xF8, 0x11, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x19, 0x48, 0x20, 0x00, 0x00, 0x9C, 0x91, 0x01, 0x00, 0x08, ++0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x44, 0x10, 0x08, 0x00, 0x80, 0x01, 0x38, 0x41, 0x46, 0x00, 0x0C, ++0x14, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x3C, 0x1A, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x38, 0x01, 0x00, 0x00, 0x40, 0x1D, 0x00, 0x00, 0x08, ++0x8E, 0x00, 0x08, 0x38, 0x50, 0x00, 0x00, 0x14, 0x20, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x00, 0x40, 0x7B, 0x00, 0x00, 0xA4, ++0x01, 0x01, 0x00, 0x00, 0x9F, 0x33, 0x00, 0x30, 0x00, 0x07, 0x00, 0x41, 0x20, 0x44, 0x10, 0x04, 0x00, 0x00, 0x00, 0x90, ++0x00, 0x00, 0x00, 0x49, 0x2F, 0x84, 0x0E, 0xF0, 0x2C, 0x84, 0x0E, 0xEC, 0x2C, 0x84, 0x0E, 0xEC, 0x32, 0x00, 0x00, 0x04, ++0x00, 0x00, 0x00, 0x30, 0x01, 0x01, 0x00, 0x48, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x02, 0x02, 0x00, 0x48, ++0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x46, 0x11, 0x00, 0x00, 0x04, 0x06, 0x00, 0x01, 0x58, ++0x72, 0x04, 0x04, 0x3D, 0x39, 0x44, 0x20, 0xDC, 0xD2, 0xD4, 0x1D, 0x08, 0x06, 0x00, 0x0A, 0x48, 0xDC, 0x44, 0x20, 0xDC, ++0x3C, 0xD4, 0x1D, 0x08, 0x04, 0x00, 0x05, 0x38, 0xC3, 0xF1, 0xF1, 0x0E, 0xDC, 0x44, 0x20, 0x34, 0x00, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, 0x45, 0x44, 0x10, 0x04, ++0x00, 0x80, 0x00, 0x38, 0x9C, 0x10, 0x00, 0x22, 0x48, 0x44, 0x10, 0x08, 0x00, 0x80, 0x00, 0x38, 0x9C, 0x50, 0xD4, 0x23, ++0x17, 0x44, 0x10, 0x08, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x00, 0x00, 0x32, 0x63, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x14, ++0x51, 0x00, 0x00, 0x1C, 0x57, 0x00, 0x00, 0x10, 0x00, 0x80, 0x02, 0x38, 0x01, 0x00, 0x00, 0x0C, 0x66, 0x44, 0xD0, 0x08, ++0x0F, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x38, 0x01, 0x26, 0x00, 0x0C, ++0x5A, 0x44, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x30, 0x30, 0x02, 0x02, 0x3D, 0x5D, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, ++0x00, 0x01, 0x00, 0x3E, 0x66, 0x00, 0x00, 0x04, 0x00, 0x80, 0x02, 0x38, 0x01, 0x16, 0x00, 0x0C, 0x66, 0x44, 0x20, 0x34, ++0x00, 0x80, 0x02, 0x38, 0x01, 0x0A, 0x00, 0x0C, 0x66, 0x44, 0x20, 0x34, 0x04, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, ++0x7B, 0x00, 0x00, 0x08, 0x2F, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0x26, 0x6C, 0x00, 0x00, 0x08, 0xAF, 0x04, 0x04, 0x38, ++0x10, 0x10, 0x19, 0x1F, 0x6F, 0x00, 0x00, 0x08, 0xAF, 0x0C, 0x00, 0x20, 0x71, 0x00, 0x00, 0x04, 0xAF, 0x0C, 0x00, 0x60, ++0x79, 0x00, 0x70, 0x18, 0x77, 0x00, 0x00, 0x14, 0x75, 0x00, 0x00, 0x10, 0xAF, 0x0C, 0x14, 0x28, 0x84, 0x00, 0xB0, 0x09, ++0xAF, 0x0C, 0x0A, 0x28, 0x84, 0x00, 0xB0, 0x09, 0xAF, 0x0C, 0x06, 0x28, 0x84, 0x00, 0xB0, 0x09, 0x86, 0x80, 0x04, 0x28, ++0x7D, 0x00, 0x00, 0x08, 0x86, 0x00, 0x00, 0x38, 0x00, 0x00, 0x80, 0x22, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, ++0x01, 0xF1, 0xF1, 0x0E, 0x83, 0x48, 0x00, 0x36, 0x00, 0x00, 0x02, 0x28, 0x85, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x02, 0x38, ++0x31, 0x04, 0x04, 0x3D, 0x88, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x05, 0x38, 0x21, 0x18, 0x24, 0x1F, 0x8B, 0x00, 0x00, 0x08, ++0x8E, 0x00, 0x00, 0x30, 0x21, 0x30, 0x16, 0xA0, 0x8E, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x12, 0x00, 0xF1, 0x0E, ++0x91, 0x00, 0x00, 0x34, 0xCC, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x50, 0x94, 0x00, 0x00, 0x04, 0xFE, 0x95, 0x00, 0x38, ++0x00, 0x00, 0x01, 0x32, 0x97, 0x00, 0x00, 0x04, 0xFE, 0x1F, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5A, 0x9B, 0x98, 0xC9, 0x6D, ++0xB9, 0xD4, 0x19, 0xFC, 0x86, 0x01, 0x00, 0x30, 0x73, 0x03, 0x84, 0x3D, 0x9E, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x0A, 0xA1, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x00, 0xC0, 0x22, 0xA4, 0x00, 0x00, 0x04, ++0x8E, 0x02, 0x00, 0x90, 0x01, 0x00, 0x01, 0x32, 0xAA, 0x00, 0x40, 0x8E, 0xB0, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x30, 0x01, 0x00, 0x01, 0x32, 0xCB, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x01, 0x32, 0xB3, 0x00, 0x00, 0x04, ++0xB6, 0x19, 0x00, 0x30, 0x31, 0x04, 0x04, 0x3D, 0xB6, 0x00, 0x00, 0x04, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x80, 0x22, ++0x97, 0x00, 0x00, 0x04, 0x86, 0x01, 0x00, 0x30, 0x73, 0x04, 0x84, 0x3D, 0xBC, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x03, 0x29, 0xBF, 0x00, 0x00, 0x04, 0x8E, 0x02, 0xEE, 0x9A, 0x00, 0x01, 0x01, 0x32, 0xC5, 0x00, 0x00, 0x7C, ++0xB0, 0x00, 0x00, 0xCC, 0xB0, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x01, 0x01, 0x32, ++0xC8, 0x00, 0x00, 0x04, 0x8E, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x8E, 0x03, 0x00, 0x50, ++0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x35, 0x00, 0x00, 0xC0, 0x06, 0x00, 0x01, 0x38, 0x72, 0x04, 0x04, 0x3D, ++0xD2, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x30, 0x41, 0xF1, 0xF1, 0x0E, 0xD5, 0x00, 0x00, 0x34, 0x04, 0x00, 0x04, 0x28, ++0xD7, 0x00, 0x00, 0x08, 0x0E, 0x00, 0x08, 0x28, 0xD9, 0x00, 0x00, 0x08, 0x8E, 0x01, 0x00, 0x30, 0x52, 0x00, 0xF1, 0x0E, ++0xDC, 0x00, 0x00, 0x34, 0x8E, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x00, 0x00, 0x02, 0x38, ++0x00, 0x00, 0x00, 0x32, 0xE2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x60, 0xE6, 0x00, 0x00, 0xD8, 0xE9, 0x00, 0x00, 0xD4, ++0xEC, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x21, 0xF1, 0xF1, 0x0E, 0xEF, 0x48, 0x00, 0x36, 0x00, 0x00, 0x00, 0x30, ++0x21, 0x24, 0x00, 0x0C, 0xEF, 0x48, 0x00, 0x36, 0x00, 0x00, 0x00, 0x30, 0x21, 0x00, 0x00, 0x0C, 0xEF, 0x48, 0x00, 0x36, ++0x00, 0x00, 0x02, 0x28, 0x7B, 0x00, 0x00, 0x08, 0xFE, 0x1E, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5A, 0xF5, 0x98, 0xC9, 0x6D, ++0xF8, 0xD4, 0x19, 0xFC, 0x8E, 0x02, 0x00, 0x30, 0x40, 0x00, 0x00, 0x32, 0xFB, 0x00, 0x00, 0x04, 0x8E, 0x02, 0xEE, 0x3A, ++0x80, 0x00, 0x00, 0x32, 0xFB, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x01, 0xF1, 0xF1, 0x0E, 0xFE, 0x48, 0x00, 0x36, ++0x00, 0x00, 0x02, 0x28, 0x00, 0x01, 0x00, 0x08, 0x8E, 0x00, 0x02, 0x38, 0x31, 0x04, 0x04, 0x3D, 0x03, 0x01, 0x00, 0x08, ++0x8E, 0x00, 0x05, 0x38, 0x21, 0x18, 0x24, 0x1F, 0x06, 0x01, 0x00, 0x08, 0x8E, 0x00, 0x00, 0x30, 0x21, 0x30, 0x16, 0xA0, ++0x09, 0x01, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x12, 0x00, 0xF1, 0x0E, 0x0C, 0x01, 0x00, 0x34, 0xF6, 0x14, 0x00, 0x30, ++0x00, 0x00, 0x01, 0x32, 0x14, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x11, 0x01, 0x00, 0x04, 0xEC, 0x00, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x50, 0xF1, 0x00, 0x00, 0x04, 0xF6, 0x14, 0x00, 0x30, 0x00, 0x00, 0x03, 0x32, 0x17, 0x01, 0x00, 0x04, ++0x86, 0x10, 0x00, 0x30, 0x73, 0x04, 0x84, 0x3D, 0x1A, 0x01, 0x00, 0x04, 0x8E, 0x10, 0x00, 0x50, 0x00, 0x00, 0xC0, 0x22, ++0xCB, 0xC0, 0x47, 0x8E, 0x1E, 0x01, 0x30, 0xCB, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x04, 0x32, 0x21, 0x01, 0x00, 0x04, ++0xB6, 0x19, 0x00, 0x30, 0x31, 0x04, 0x04, 0x3D, 0x24, 0x01, 0x00, 0x04, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x80, 0x22, ++0x11, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, 0x30, ++0x73, 0x04, 0x84, 0x3D, 0x2D, 0x01, 0x00, 0x04, 0x8E, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, ++0x31, 0x01, 0x00, 0xC0, 0x0E, 0x80, 0x0C, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x34, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x30, ++0x03, 0xF1, 0xF1, 0x0F, 0x37, 0x01, 0x00, 0x34, 0x00, 0x00, 0x02, 0x28, 0x39, 0x01, 0x00, 0x08, 0x8E, 0x03, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x06, 0x00, 0x01, 0x58, 0x72, 0x04, 0x04, 0x3D, 0x43, 0x45, 0x20, 0xDC, 0xD2, 0xD4, 0x1D, 0x08, 0x06, 0x00, 0x0A, 0x48, ++0xDC, 0x44, 0x20, 0xDC, 0x46, 0xD5, 0x1D, 0x08, 0x04, 0x00, 0x05, 0x38, 0x41, 0xF1, 0xF1, 0x0E, 0xDC, 0x44, 0x20, 0x34, ++0x0E, 0x80, 0x02, 0x28, 0xDC, 0x00, 0x00, 0x08, 0x35, 0x00, 0x00, 0x48, 0x4A, 0x01, 0x00, 0x04, 0x8F, 0x63, 0x96, 0x78, ++0x0F, 0x00, 0x00, 0x41, 0x4F, 0x01, 0x00, 0x8C, 0xC4, 0x50, 0x04, 0x08, 0x74, 0x45, 0x10, 0x90, 0x0F, 0x62, 0xC8, 0x88, ++0x5A, 0x01, 0x00, 0xC0, 0x74, 0x45, 0x10, 0x90, 0x54, 0x45, 0x10, 0x08, 0x57, 0x45, 0x10, 0x94, 0x8F, 0x62, 0x00, 0x30, ++0x00, 0x00, 0x00, 0x29, 0x7A, 0x51, 0x04, 0x94, 0x8F, 0x63, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x7A, 0x45, 0x10, 0x04, ++0x05, 0xE0, 0x00, 0x38, 0x31, 0x01, 0x01, 0x3D, 0x5D, 0x45, 0x10, 0x08, 0x0F, 0x60, 0x32, 0xA8, 0x74, 0x45, 0x10, 0x90, ++0x54, 0x01, 0x00, 0x08, 0x57, 0x45, 0x10, 0x94, 0x67, 0x45, 0x10, 0xC6, 0x63, 0x55, 0x18, 0xC4, 0x0F, 0xE0, 0x02, 0x58, ++0x07, 0xEA, 0xEE, 0x0F, 0x74, 0x01, 0x00, 0x80, 0x6B, 0x45, 0x20, 0x34, 0x0F, 0xE0, 0x02, 0x58, 0x07, 0xEA, 0xEE, 0x0E, ++0x74, 0x01, 0x00, 0x80, 0x6B, 0x45, 0x20, 0x34, 0x00, 0x40, 0x00, 0x30, 0x01, 0x00, 0x00, 0x33, 0x6E, 0x01, 0x00, 0x04, ++0x05, 0x40, 0x03, 0x38, 0x73, 0x03, 0x03, 0x3D, 0x71, 0x01, 0x00, 0x08, 0x07, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, ++0x74, 0x01, 0x00, 0x04, 0x8F, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x77, 0x51, 0x04, 0x94, 0x8F, 0x60, 0x00, 0x40, ++0x7D, 0x45, 0x10, 0xA0, 0x7A, 0x45, 0x10, 0x04, 0x8F, 0x60, 0x00, 0x30, 0x01, 0x01, 0x00, 0x64, 0x11, 0x44, 0x10, 0x04, ++0x8F, 0x60, 0x00, 0x30, 0x01, 0x01, 0x00, 0x64, 0x80, 0x45, 0x10, 0x04, 0x8F, 0x61, 0x00, 0x30, 0x01, 0x00, 0x00, 0x42, ++0x83, 0x01, 0x00, 0x04, 0x00, 0x80, 0x02, 0x38, 0x00, 0x00, 0x00, 0x32, 0x86, 0x45, 0x10, 0x08, 0x8F, 0x61, 0x0A, 0x28, ++0x88, 0x01, 0x00, 0x08, 0x8F, 0x61, 0x0A, 0x48, 0x8B, 0x01, 0x00, 0xBC, 0x8E, 0x01, 0x00, 0x08, 0x8F, 0x61, 0x00, 0x30, ++0x01, 0x00, 0x00, 0x34, 0x05, 0x00, 0x00, 0x04, 0x8F, 0x61, 0x00, 0x30, 0x00, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00, 0x04, ++0x8F, 0x00, 0x00, 0x30, 0x0F, 0xED, 0xEA, 0x0E, 0x94, 0x01, 0x00, 0x36, 0x00, 0x80, 0x03, 0x38, 0x00, 0x00, 0x00, 0x34, ++0x97, 0x01, 0x00, 0x08, 0x05, 0x80, 0x02, 0x38, 0x02, 0x00, 0x01, 0x29, 0x9A, 0x01, 0x00, 0x08, 0x8F, 0x02, 0x00, 0x30, ++0x9C, 0x20, 0x00, 0x22, 0x9D, 0x01, 0x00, 0x04, 0x8F, 0x02, 0x00, 0x30, 0x9C, 0x50, 0xD4, 0x23, 0xA0, 0x01, 0x00, 0x04, ++0x8F, 0x02, 0x14, 0x28, 0xA2, 0x01, 0x00, 0x08, 0x8F, 0x02, 0x00, 0x30, 0x01, 0x02, 0x01, 0x43, 0xA5, 0x01, 0x00, 0x04, ++0x8F, 0x12, 0x00, 0x30, 0x00, 0x01, 0x00, 0x32, 0xA8, 0x01, 0x00, 0x04, 0x8F, 0x13, 0xEE, 0x5A, 0x0F, 0x00, 0x00, 0x41, ++0xAC, 0x01, 0x00, 0x7C, 0xF9, 0x00, 0x00, 0x08, 0x8F, 0x13, 0x2C, 0x59, 0x00, 0x00, 0x00, 0x29, 0xB0, 0x01, 0x00, 0x8C, ++0xF9, 0x00, 0x00, 0x08, 0x8F, 0x13, 0x00, 0x20, 0x11, 0x50, 0x04, 0x94, 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, 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, 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, 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, ++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, 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, 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, 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, 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, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x76, 0x76, 0x00, 0x70, 0xF8, 0xF8, 0x1D, ++0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x72, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xF8, 0x1D, ++0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x7B, 0x76, 0x76, 0x00, 0x70, 0xF8, 0xF8, 0x1D, ++0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x85, 0x7E, 0x7E, 0x00, 0x76, 0xF8, 0xF4, 0x1D, ++0x76, 0xF8, 0xF4, 0x1D, 0x76, 0xF8, 0xF4, 0x1D, 0x76, 0xF8, 0xF8, 0x1D, 0x8A, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x8D, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x8A, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7C, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x40, 0x7E, 0x7E, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, ++0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x92, 0x8B, 0x8B, 0x00, 0x87, 0xF8, 0xF8, 0x1D, ++0x89, 0xF8, 0xF8, 0x1D, 0x87, 0xF8, 0xF8, 0x1D, 0x87, 0xF8, 0xF8, 0x1D, 0x55, 0x51, 0x51, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x89, 0xF8, 0xF8, 0x1D, 0x89, 0xF8, 0xF8, 0x1D, 0x54, 0x51, 0x51, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x88, 0xF8, 0xF8, 0x1D, 0x88, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4E, 0x4E, 0x00, 0x49, 0xF8, 0xF8, 0x1D, ++0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x52, 0x4D, 0x4D, 0x00, 0x47, 0xF8, 0xF8, 0x1D, ++0x47, 0xF8, 0xF8, 0x1D, 0x47, 0xF8, 0xF8, 0x1D, 0x47, 0xF8, 0xF8, 0x1D, 0x55, 0x4F, 0x4F, 0x00, 0x4B, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4E, 0x4E, 0x00, 0x49, 0xF8, 0xF8, 0x1D, ++0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x4D, 0x49, 0x49, 0x00, 0x44, 0xF8, 0xF8, 0x1D, ++0x44, 0xF8, 0xF8, 0x1D, 0x44, 0xF8, 0xF8, 0x1D, 0x44, 0xF8, 0xF8, 0x1D, 0x8F, 0x51, 0x51, 0x00, 0x49, 0xF8, 0xF8, 0x1D, ++0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x77, 0x42, 0x42, 0x00, 0x3F, 0xF8, 0xF8, 0x1D, ++0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x75, 0x42, 0x42, 0x00, 0x9E, 0xF8, 0xF8, 0x1D, ++0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x5C, 0x55, 0x55, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x5C, 0x53, 0x53, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, ++0x4B, 0xF8, 0xF8, 0x1D, 0x4B, 0xF8, 0xF8, 0x1D, 0x4B, 0xF8, 0xF8, 0x1D, 0x9E, 0xF8, 0xF8, 0x00, 0x8C, 0xF8, 0xF8, 0x1D, ++0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x40, 0x89, 0x89, 0x00, 0x46, 0xF8, 0xF8, 0x18, ++0x45, 0xF8, 0xCF, 0x18, 0x44, 0xF8, 0xCF, 0x18, 0x44, 0xF8, 0xCF, 0x18, 0x5F, 0x56, 0x56, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, ++0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x5E, 0x55, 0x55, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x5F, 0x56, 0x56, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, ++0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x61, 0x55, 0x55, 0x00, 0x50, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x5F, 0x53, 0x53, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x5F, 0x55, 0x55, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0xAA, 0x55, 0x55, 0x00, 0x54, 0xF8, 0xF8, 0x1D, ++0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0xA6, 0x59, 0x59, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x9B, 0x4F, 0x4F, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, ++0x46, 0xF8, 0xF8, 0x1D, 0x46, 0xF8, 0xF8, 0x1D, 0x46, 0xF8, 0xF8, 0x1D, 0xA5, 0xF8, 0xF8, 0x00, 0x94, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0xA4, 0x98, 0x98, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, ++0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x86, 0x46, 0x46, 0x00, 0xB3, 0xF8, 0xF8, 0x1D, ++0x3D, 0xF8, 0xF8, 0x1D, 0x3D, 0xF8, 0xF8, 0x1D, 0x3D, 0xF8, 0xF8, 0x1D, 0x40, 0x8E, 0x8E, 0x00, 0x48, 0xF8, 0xF8, 0x1A, ++0x48, 0xF8, 0xDF, 0x1A, 0x46, 0xF8, 0xDF, 0x1A, 0x46, 0xF8, 0xDF, 0x1A, 0x40, 0x7F, 0x7F, 0x00, 0x75, 0xD2, 0xD2, 0x18, ++0x3A, 0xD2, 0xD2, 0x18, 0x3A, 0xD2, 0xD2, 0x18, 0x39, 0xD2, 0xD2, 0x18, 0x40, 0x45, 0x45, 0x00, 0x64, 0x86, 0x86, 0x0F, ++0x3E, 0x86, 0x86, 0x0F, 0x3D, 0x86, 0x86, 0x0F, 0x3D, 0x86, 0x86, 0x0F, 0x64, 0x5C, 0x5C, 0x00, 0x56, 0xF8, 0xF8, 0x1D, ++0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x68, 0x5B, 0x5B, 0x00, 0x58, 0xF8, 0xF8, 0x1D, ++0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x64, 0x5A, 0x5A, 0x00, 0x55, 0xF8, 0xF8, 0x1D, ++0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0xB5, 0x5A, 0x5A, 0x00, 0x5B, 0xF8, 0xF8, 0x1D, ++0x55, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0xB0, 0xF8, 0xF8, 0x00, 0xA3, 0xF8, 0xF8, 0x1D, ++0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0xAE, 0xA4, 0xA4, 0x00, 0x54, 0xF8, 0xF8, 0x1D, ++0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x40, 0x9A, 0x9A, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, ++0x4D, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x40, 0x9C, 0x9C, 0x00, 0x95, 0xF8, 0xF8, 0x1D, ++0x49, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x40, 0x49, 0x49, 0x00, 0x6F, 0x97, 0x97, 0x11, ++0x42, 0x97, 0x97, 0x11, 0x41, 0x97, 0x97, 0x11, 0x41, 0x97, 0x97, 0x11, 0x74, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xF8, 0x1D, ++0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x40, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xDE, 0x1A, ++0x69, 0xF8, 0xDE, 0x1A, 0x69, 0xF8, 0xDE, 0x1A, 0x69, 0xF8, 0xDE, 0x1A, 0x40, 0x75, 0x75, 0x00, 0x6E, 0xF8, 0x78, 0x0D, ++0x6E, 0xF8, 0x78, 0x0D, 0x6E, 0xF8, 0x78, 0x0D, 0x6E, 0xF8, 0x79, 0x0D, 0x85, 0x78, 0x78, 0x00, 0x73, 0xF8, 0xF8, 0x1D, ++0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x40, 0x78, 0x78, 0x00, 0x73, 0xF8, 0xF8, 0x1D, ++0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x40, 0x78, 0x78, 0x00, 0x73, 0xF8, 0x81, 0x0E, ++0x73, 0xF8, 0x81, 0x0E, 0x73, 0xF8, 0x81, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x40, 0x40, 0x40, 0x00, 0x73, 0xF8, 0x82, 0x0E, ++0x73, 0xF8, 0x82, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x40, 0x81, 0x81, 0x00, 0x7E, 0xF8, 0x92, 0x10, ++0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x40, 0x40, 0x40, 0x00, 0x7E, 0xF8, 0x92, 0x10, ++0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x40, 0x73, 0x73, 0x00, 0x6B, 0xB2, 0xB2, 0x14, ++0x35, 0xB2, 0xB2, 0x14, 0x35, 0xB2, 0xB2, 0x14, 0x35, 0xB2, 0xB2, 0x14, 0x40, 0x40, 0x40, 0x00, 0x60, 0x82, 0x82, 0x0E, ++0x3D, 0x82, 0x82, 0x0E, 0x3C, 0x82, 0x82, 0x0E, 0x3C, 0x82, 0x82, 0x0E, 0x40, 0x40, 0x40, 0x00, 0x66, 0x8B, 0x8B, 0x0F, ++0x3F, 0x8B, 0x8B, 0x0F, 0x3D, 0x8B, 0x8B, 0x0F, 0x3D, 0x8B, 0x8B, 0x0F, 0x40, 0x40, 0x40, 0x00, 0x3D, 0x68, 0x68, 0x0B, ++0x1E, 0x68, 0x68, 0x0B, 0x1E, 0x68, 0x68, 0x0B, 0x1E, 0x68, 0x68, 0x0B, 0x40, 0x22, 0x22, 0x00, 0x18, 0x43, 0x43, 0x06, ++0x29, 0x43, 0x43, 0x06, 0x18, 0x43, 0x43, 0x06, 0x18, 0x43, 0x43, 0x06, 0x40, 0x40, 0x40, 0x00, 0x72, 0x9D, 0x9D, 0x12, ++0x43, 0x9D, 0x9D, 0x12, 0x41, 0x9D, 0x9D, 0x12, 0x41, 0x9D, 0x9D, 0x12, 0x40, 0x40, 0x40, 0x00, 0x42, 0x75, 0x75, 0x0D, ++0x20, 0x75, 0x75, 0x0D, 0x20, 0x75, 0x75, 0x0D, 0x20, 0x75, 0x75, 0x0D, 0x40, 0x23, 0x23, 0x00, 0x19, 0x4C, 0x4C, 0x08, ++0x2C, 0x4C, 0x4C, 0x08, 0x19, 0x4C, 0x4C, 0x08, 0x19, 0x4C, 0x4C, 0x08, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, ++0xB8, 0xC8, 0xD8, 0xF8, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0x08, 0x58, 0x68, 0x78, 0x88, ++0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, 0x09, 0x01, 0x03, 0x1E, 0x00, 0x00, 0x75, 0x19, 0x03, 0x00, 0x75, 0x19, 0x03, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x04, 0x62, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, ++0x61, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x60, 0x23, 0x8D, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x60, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0xB4, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xE3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x84, 0x60, 0xC3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, ++0x60, 0xCB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xB3, 0x0C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0x1B, 0x0F, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xA2, 0x3E, 0x2A, 0x00, ++0xB5, 0x5A, 0x3F, 0x04, 0x60, 0x9B, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, ++0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3F, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0xD8, 0x3F, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, ++0x62, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x61, 0x03, 0x8D, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x60, 0x23, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x58, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x60, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0xB4, 0x2E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x44, 0x60, 0xE3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, ++0x60, 0xC3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x60, 0xCB, 0x0C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xB3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x2A, 0x00, ++0xB5, 0x5A, 0x2F, 0x44, 0x60, 0x1B, 0x0F, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xA2, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x04, ++0x60, 0x9B, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x58, 0x2F, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0xD8, 0x2F, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, ++0x6C, 0x00, 0x0F, 0x03, 0x60, 0xE7, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0x2F, 0x03, ++0x60, 0xD7, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0xEF, 0x03, 0x60, 0x9F, 0x0D, 0xE8, ++0x80, 0x80, 0x80, 0x80, 0x6D, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0xEF, 0x83, 0x60, 0x9F, 0x0D, 0xE8, 0x80, 0x80, 0x80, 0x80, ++0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, ++0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x2F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, ++0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x44, ++0x70, 0xE3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x63, 0x8C, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0x03, 0x11, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x43, 0x8D, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, ++0xB4, 0x00, 0x19, 0x44, 0x70, 0xE3, 0x10, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0xC4, ++0x70, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0xB4, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0xC3, 0x8C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x03, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0xEB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xB9, 0x00, ++0xB4, 0x00, 0x19, 0x84, 0x70, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x84, ++0x70, 0xF3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x84, 0x70, 0x3B, 0x0D, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0xB4, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x44, 0x70, 0xBB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0xEB, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0xAA, 0x00, ++0xB5, 0x5A, 0x39, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3F, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x04, ++0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0xE3, 0xAC, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x70, 0x63, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0x03, 0x11, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, ++0xB4, 0x00, 0x0F, 0x84, 0x70, 0x43, 0x8D, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, ++0x70, 0xE3, 0x10, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x70, 0xE3, 0x0C, 0x0F, ++0x80, 0x80, 0x80, 0x80, 0xB4, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0xC3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0x46, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x70, 0x03, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0xB9, 0x00, ++0xB4, 0x00, 0x0F, 0x44, 0x70, 0xEB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x84, ++0x70, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x84, 0x70, 0xF3, 0x0C, 0x0E, ++0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x84, 0x70, 0x3B, 0x0D, 0x0E, 0x80, 0x80, 0x80, 0x80, ++0xB4, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x70, 0xBB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x2E, 0xAA, 0x00, ++0xB5, 0x5A, 0x2F, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x2F, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x04, ++0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x2F, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x04, 0x70, 0xFB, 0x11, 0x0E, ++0x7F, 0xC1, 0x9F, 0x00, 0x0A, 0x01, 0x82, 0x00, 0x0C, 0x81, 0x82, 0x00, 0x10, 0x81, 0x82, 0x00, 0x10, 0x01, 0x83, 0x00, ++0x16, 0x01, 0x83, 0x00, 0x16, 0x01, 0x84, 0x00, 0x60, 0x01, 0x84, 0x00, 0x67, 0x01, 0x93, 0x00, 0x67, 0x41, 0x99, 0x00, ++0x7F, 0x41, 0x99, 0x00, 0x7F, 0xC1, 0x99, 0x00, 0x7F, 0x81, 0x9A, 0x00, 0x7F, 0x81, 0x9B, 0x00, 0x3F, 0xC1, 0x9C, 0x00, ++0x3F, 0xC1, 0x8F, 0x00, 0x08, 0x01, 0x82, 0x00, 0x0A, 0x01, 0x82, 0x00, 0x0C, 0x81, 0x82, 0x00, 0x10, 0x81, 0x82, 0x00, ++0x10, 0x01, 0x83, 0x00, 0x16, 0x01, 0x83, 0x00, 0x16, 0x01, 0x84, 0x00, 0x20, 0x01, 0x84, 0x00, 0x20, 0x01, 0x85, 0x00, ++0x20, 0x01, 0x8C, 0x00, 0x27, 0x81, 0x8C, 0x00, 0x27, 0x01, 0x8E, 0x00, 0x27, 0x01, 0x9B, 0x00, 0x3F, 0x01, 0x9B, 0x00, ++0x3F, 0xC1, 0x9C, 0x00, 0x3F, 0xC1, 0x8F, 0x00, 0x00, 0xC6, 0xFF, 0x00, 0x00, 0xC6, 0x40, 0x00, 0x00, 0x06, 0x41, 0x00, ++0x00, 0x46, 0x41, 0x00, 0x00, 0x86, 0x90, 0x00, 0x00, 0xC6, 0x90, 0x00, 0x00, 0x06, 0xB1, 0x00, 0x00, 0x46, 0xB1, 0x00, ++0x00, 0x86, 0xB1, 0x00, 0x00, 0x06, 0xB2, 0x00, 0x00, 0xC6, 0xB2, 0x00, 0x00, 0x46, 0xB9, 0x00, 0x00, 0xC6, 0xB9, 0x00, ++0x00, 0x46, 0xBA, 0x00, 0x00, 0x46, 0xBB, 0x00, 0x00, 0xC6, 0xBC, 0x00, 0x82, 0x01, 0x83, 0x01, 0x40, 0x02, 0x41, 0x02, ++0x80, 0x02, 0x81, 0x02, 0x82, 0x02, 0x83, 0x02, 0x40, 0x03, 0x41, 0x03, 0x80, 0x03, 0x81, 0x03, 0x00, 0x04, 0x01, 0x04, ++0x40, 0x04, 0x41, 0x04, 0x60, 0x60, 0x00, 0x00, 0x3B, 0x18, 0xB3, 0x03, 0x68, 0x51, 0x2E, 0x1A, 0x48, 0x51, 0x2E, 0x1A, ++0x00, 0x00, 0x00, 0x00, 0x84, 0x18, 0x20, 0x56, 0x84, 0x18, 0x20, 0x56, 0x00, 0x00, 0x00, 0x00, 0x08, 0x50, 0x2A, 0x7A, ++0xC8, 0x50, 0x1B, 0x79, 0xC8, 0xD0, 0x2A, 0x7A, 0x40, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x64, 0x32, 0x00, 0x00, ++0x00, 0x87, 0x93, 0x03, 0x00, 0x20, 0x03, 0x00, 0x00, 0x20, 0x03, 0x00, 0x30, 0x75, 0x00, 0x00, 0xB0, 0xAD, 0x01, 0x00, ++0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x10, 0x27, 0x00, 0x00, ++0x40, 0x0D, 0x03, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x27, 0x50, 0xC3, 0xA0, 0x0F, 0x40, 0x1F, 0x84, 0x03, 0x05, 0x08, ++0x01, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x1A, 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x1A, 0x00, 0xE0, 0x57, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, ++0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x19, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x19, 0x00, 0xF4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0xE0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x71, 0x04, 0x00, 0x10, 0x0E, 0x00, ++0x03, 0x01, 0x08, 0x8F, 0x03, 0xE6, 0xE0, 0xD0, 0xD6, 0x06, 0xD6, 0x06, 0x00, 0x00, 0x01, 0xF3, 0x01, 0x0A, 0x00, 0x0F, ++0x08, 0x01, 0x09, 0x08, 0x08, 0x08, 0x08, 0x0A, 0x09, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ++0x03, 0x01, 0x00, 0x00, 0xBC, 0x06, 0x04, 0x04, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, 0x0A, 0x02, 0x04, ++0x01, 0x00, 0xF0, 0x00, 0x08, 0x04, 0x00, 0x04, 0x04, 0x04, 0x09, 0x06, 0x04, 0x01, 0x04, 0x01, 0x05, 0x14, 0x38, 0x01, ++0x38, 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, ++0x7D, 0xA6, 0x12, 0x00, 0x91, 0xA1, 0x12, 0x00, 0xA5, 0xA6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x99, 0xA1, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xA1, 0x12, 0x00, 0xD1, 0xA1, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xA3, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x6D, 0x12, 0x00, 0x88, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, ++0x05, 0xC7, 0x12, 0x00, 0xE1, 0xB8, 0x14, 0x00, 0x75, 0xBB, 0x14, 0x00, 0x2D, 0xBE, 0x14, 0x00, 0xE9, 0xBC, 0x14, 0x00, ++0x81, 0xBC, 0x14, 0x00, 0x29, 0xAC, 0x14, 0x00, 0xFD, 0x0C, 0x15, 0x00, 0x1D, 0x0B, 0x15, 0x00, 0x6D, 0x08, 0x15, 0x00, ++0x0D, 0x07, 0x15, 0x00, 0x59, 0xC8, 0x13, 0x00, 0xF5, 0xE7, 0x13, 0x00, 0xA1, 0xCE, 0x13, 0x00, 0x3D, 0xD1, 0x13, 0x00, ++0x4D, 0xD0, 0x13, 0x00, 0xF9, 0xD0, 0x13, 0x00, 0x05, 0xDD, 0x13, 0x00, 0xF1, 0xDD, 0x13, 0x00, 0x95, 0xDE, 0x13, 0x00, ++0x85, 0xE4, 0x13, 0x00, 0xF5, 0xE0, 0x13, 0x00, 0xC1, 0xE3, 0x13, 0x00, 0xED, 0xCE, 0x13, 0x00, 0x59, 0xD6, 0x13, 0x00, ++0xF5, 0xD9, 0x13, 0x00, 0x3D, 0xD5, 0x13, 0x00, 0xA9, 0xD4, 0x13, 0x00, 0x91, 0xD8, 0x13, 0x00, 0x31, 0xD9, 0x13, 0x00, ++0xC1, 0xD8, 0x13, 0x00, 0x21, 0xD4, 0x13, 0x00, 0x4D, 0xDB, 0x13, 0x00, 0x71, 0xCA, 0x13, 0x00, 0xE5, 0xC9, 0x13, 0x00, ++0xAD, 0xC0, 0x13, 0x00, 0xCD, 0xC6, 0x13, 0x00, 0x39, 0xC0, 0x13, 0x00, 0x79, 0xD6, 0x13, 0x00, 0xE5, 0xD7, 0x13, 0x00, ++0xF1, 0xC7, 0x13, 0x00, 0xDD, 0xE4, 0x13, 0x00, 0xA1, 0xE6, 0x13, 0x00, 0x21, 0xD2, 0x13, 0x00, 0x6D, 0xD4, 0x13, 0x00, ++0x99, 0xEA, 0x13, 0x00, 0x71, 0x50, 0x14, 0x00, 0x71, 0x58, 0x14, 0x00, 0x25, 0x06, 0x12, 0x00, 0x7D, 0x4B, 0x14, 0x00, ++0x19, 0x4B, 0x14, 0x00, 0xF9, 0x5E, 0x12, 0x00, 0xD1, 0x5E, 0x12, 0x00, 0xF1, 0x1C, 0x14, 0x00, 0x19, 0x1E, 0x14, 0x00, ++0xE9, 0x14, 0x14, 0x00, 0xD9, 0x16, 0x14, 0x00, 0x91, 0x17, 0x14, 0x00, 0xC9, 0x1A, 0x14, 0x00, 0xF1, 0x19, 0x14, 0x00, ++0x3D, 0x15, 0x14, 0x00, 0xA5, 0x1B, 0x14, 0x00, 0x25, 0x1B, 0x14, 0x00, 0x1D, 0x90, 0x12, 0x00, 0x7D, 0x93, 0x12, 0x00, ++0xD1, 0x9E, 0x12, 0x00, 0x71, 0x8E, 0x12, 0x00, 0xF5, 0xAA, 0x12, 0x00, 0xC5, 0x78, 0x12, 0x00, 0x05, 0x69, 0x12, 0x00, ++0x39, 0x69, 0x12, 0x00, 0x8D, 0x52, 0x12, 0x00, 0x7D, 0x50, 0x12, 0x00, 0xD9, 0x55, 0x12, 0x00, 0xC1, 0x51, 0x12, 0x00, ++0x79, 0x51, 0x12, 0x00, 0x5D, 0xB2, 0x12, 0x00, 0x8D, 0x0C, 0x15, 0x00, 0x61, 0x4C, 0x14, 0x00, 0xF9, 0x0E, 0x12, 0x00, ++0x49, 0x07, 0x12, 0x00, 0x55, 0x59, 0x14, 0x00, 0xD5, 0x58, 0x14, 0x00, 0x49, 0x5A, 0x14, 0x00, 0x05, 0x5A, 0x14, 0x00, ++0xD9, 0x80, 0x14, 0x00, 0xD9, 0x5A, 0x14, 0x00, 0x45, 0x79, 0x14, 0x00, 0x7D, 0x7D, 0x13, 0x00, 0xA1, 0x78, 0x13, 0x00, ++0xB5, 0x7E, 0x13, 0x00, 0xF1, 0x85, 0x13, 0x00, 0xD5, 0xB6, 0x13, 0x00, 0x91, 0xBC, 0x13, 0x00, 0xF1, 0xB5, 0x13, 0x00, ++0x19, 0xBB, 0x13, 0x00, 0x5D, 0xBB, 0x13, 0x00, 0xD5, 0xBC, 0x13, 0x00, 0xDD, 0xB8, 0x13, 0x00, 0x8D, 0xB8, 0x13, 0x00, ++0xFD, 0xBD, 0x13, 0x00, 0x21, 0xB8, 0x13, 0x00, 0xC5, 0x8C, 0x13, 0x00, 0x09, 0x8C, 0x13, 0x00, 0xE9, 0x72, 0x13, 0x00, ++0x59, 0x87, 0x13, 0x00, 0xCD, 0x73, 0x13, 0x00, 0x31, 0x84, 0x13, 0x00, 0x25, 0x80, 0x13, 0x00, 0x35, 0x83, 0x13, 0x00, ++0xFD, 0x80, 0x13, 0x00, 0xE9, 0x8B, 0x13, 0x00, 0x01, 0x8E, 0x13, 0x00, 0x55, 0x89, 0x13, 0x00, 0xD9, 0x89, 0x13, 0x00, ++0x91, 0x7D, 0x13, 0x00, 0x4D, 0x75, 0x13, 0x00, 0xA5, 0xB3, 0x13, 0x00, 0x19, 0xB0, 0x13, 0x00, 0x01, 0xAF, 0x13, 0x00, ++0x21, 0xAF, 0x13, 0x00, 0x25, 0x05, 0x14, 0x00, 0xA9, 0xFF, 0x13, 0x00, 0xB1, 0xFE, 0x13, 0x00, 0xC5, 0xFF, 0x13, 0x00, ++0x81, 0xFF, 0x13, 0x00, 0x69, 0x06, 0x14, 0x00, 0x49, 0x03, 0x14, 0x00, 0x2D, 0x0A, 0x14, 0x00, 0x25, 0x08, 0x14, 0x00, ++0x3D, 0x09, 0x14, 0x00, 0xF9, 0x07, 0x14, 0x00, 0x59, 0xFB, 0x13, 0x00, 0x35, 0x04, 0x14, 0x00, 0xF5, 0xF6, 0x13, 0x00, ++0x89, 0xF4, 0x13, 0x00, 0xA5, 0x13, 0x12, 0x00, 0x5D, 0x10, 0x12, 0x00, 0xC1, 0x0B, 0x12, 0x00, 0x49, 0x11, 0x12, 0x00, ++0x4D, 0x02, 0x12, 0x00, 0xDD, 0xEA, 0x13, 0x00, 0x01, 0xEE, 0x13, 0x00, 0xA9, 0xF0, 0x13, 0x00, 0x79, 0xEF, 0x13, 0x00, ++0x49, 0xF1, 0x13, 0x00, 0xE5, 0xF1, 0x13, 0x00, 0x85, 0xEC, 0x13, 0x00, 0x45, 0xED, 0x13, 0x00, 0xA5, 0xED, 0x13, 0x00, ++0x3D, 0xEB, 0x13, 0x00, 0x45, 0xEF, 0x13, 0x00, 0xA1, 0xF2, 0x13, 0x00, 0xC5, 0xF3, 0x13, 0x00, 0x85, 0x49, 0x15, 0x00, ++0x01, 0x35, 0x15, 0x00, 0xCD, 0x42, 0x12, 0x00, 0x71, 0xCB, 0x12, 0x00, 0x35, 0xCF, 0x12, 0x00, 0xAD, 0xD3, 0x12, 0x00, ++0x9D, 0xCB, 0x12, 0x00, 0xFD, 0xD4, 0x12, 0x00, 0xFD, 0x48, 0x13, 0x00, 0x69, 0x4B, 0x13, 0x00, 0x21, 0x4C, 0x13, 0x00, ++0x15, 0x46, 0x13, 0x00, 0x99, 0x50, 0x13, 0x00, 0x9D, 0x5C, 0x13, 0x00, 0x79, 0x5C, 0x13, 0x00, 0xED, 0x53, 0x13, 0x00, ++0xE5, 0x56, 0x13, 0x00, 0x81, 0x4F, 0x13, 0x00, 0x61, 0x4E, 0x13, 0x00, 0x29, 0x4D, 0x13, 0x00, 0x01, 0x40, 0x13, 0x00, ++0xED, 0x4C, 0x13, 0x00, 0x1D, 0x52, 0x13, 0x00, 0xDD, 0xDB, 0x14, 0x00, 0xB5, 0xEB, 0x14, 0x00, 0x19, 0xD9, 0x14, 0x00, ++0xA5, 0xDF, 0x14, 0x00, 0xB5, 0xE0, 0x14, 0x00, 0xE9, 0xDE, 0x14, 0x00, 0x15, 0xE3, 0x14, 0x00, 0xD9, 0xE5, 0x14, 0x00, ++0x5D, 0xD7, 0x14, 0x00, 0xED, 0xD6, 0x14, 0x00, 0x21, 0x13, 0x14, 0x00, 0x85, 0x14, 0x14, 0x00, 0x05, 0xD1, 0x14, 0x00, ++0x8D, 0x85, 0x12, 0x00, 0xD1, 0x80, 0x12, 0x00, 0xCD, 0x7D, 0x12, 0x00, 0xED, 0x7F, 0x12, 0x00, 0x45, 0x7A, 0x12, 0x00, ++0x01, 0x7F, 0x12, 0x00, 0xD5, 0x99, 0x14, 0x00, 0xED, 0x9A, 0x14, 0x00, 0x31, 0x62, 0x13, 0x00, 0x29, 0x5F, 0x13, 0x00, ++0x65, 0x63, 0x13, 0x00, 0x41, 0x61, 0x13, 0x00, 0x71, 0x5F, 0x12, 0x00, 0xB9, 0x24, 0x12, 0x00, 0xD9, 0x0D, 0x14, 0x00, ++0x61, 0x0C, 0x14, 0x00, 0x79, 0x20, 0x14, 0x00, 0x05, 0x20, 0x14, 0x00, 0xC1, 0x20, 0x14, 0x00, 0x55, 0xD6, 0x12, 0x00, ++0x4D, 0x1B, 0x13, 0x00, 0x99, 0x0E, 0x13, 0x00, 0x11, 0x0C, 0x13, 0x00, 0x65, 0x0D, 0x13, 0x00, 0xD1, 0x19, 0x13, 0x00, ++0x5D, 0x13, 0x13, 0x00, 0x79, 0x0A, 0x13, 0x00, 0x8D, 0x21, 0x13, 0x00, 0x2D, 0x15, 0x13, 0x00, 0x19, 0x21, 0x13, 0x00, ++0x79, 0x07, 0x13, 0x00, 0xCD, 0xF3, 0x12, 0x00, 0x31, 0xD7, 0x12, 0x00, 0x41, 0xD8, 0x12, 0x00, 0xA1, 0xD8, 0x12, 0x00, ++0x69, 0xFC, 0x12, 0x00, 0x15, 0xFD, 0x12, 0x00, 0xF5, 0xE7, 0x12, 0x00, 0xB5, 0xE2, 0x12, 0x00, 0xE5, 0xEA, 0x12, 0x00, ++0xF5, 0xEB, 0x12, 0x00, 0xED, 0xE6, 0x12, 0x00, 0xF9, 0xDD, 0x12, 0x00, 0x89, 0xE2, 0x12, 0x00, 0xD1, 0xFD, 0x12, 0x00, ++0xD5, 0xE7, 0x12, 0x00, 0xD5, 0x30, 0x13, 0x00, 0x91, 0x36, 0x13, 0x00, 0xD5, 0x3A, 0x13, 0x00, 0x7D, 0x3C, 0x13, 0x00, ++0xDD, 0x26, 0x13, 0x00, 0x49, 0x27, 0x13, 0x00, 0xA9, 0x25, 0x13, 0x00, 0xCD, 0x35, 0x13, 0x00, 0x71, 0x25, 0x13, 0x00, ++0x89, 0x2C, 0x13, 0x00, 0x75, 0x30, 0x13, 0x00, 0x81, 0x3A, 0x13, 0x00, 0x05, 0x3A, 0x13, 0x00, 0x49, 0x3D, 0x13, 0x00, ++0xB1, 0x2B, 0x13, 0x00, 0x21, 0x2F, 0x13, 0x00, 0xBD, 0x39, 0x13, 0x00, 0x59, 0x28, 0x13, 0x00, 0xCD, 0x2A, 0x13, 0x00, ++0x61, 0x37, 0x13, 0x00, 0x01, 0xDB, 0x12, 0x00, 0xF1, 0xE2, 0x12, 0x00, 0x81, 0xD9, 0x12, 0x00, 0x35, 0xEE, 0x12, 0x00, ++0xC5, 0xEF, 0x12, 0x00, 0x49, 0xED, 0x12, 0x00, 0x69, 0xFD, 0x14, 0x00, 0x39, 0xF9, 0x14, 0x00, 0x71, 0xF4, 0x14, 0x00, ++0x79, 0xF9, 0x14, 0x00, 0x09, 0xFC, 0x14, 0x00, 0xC5, 0xF3, 0x14, 0x00, 0xDD, 0x60, 0x12, 0x00, 0xB1, 0xAD, 0x12, 0x00, ++0xBD, 0xAE, 0x12, 0x00, 0x29, 0xAF, 0x12, 0x00, 0xA5, 0xA4, 0x12, 0x00, 0xD1, 0xA5, 0x12, 0x00, 0xD9, 0x6C, 0x13, 0x00, ++0xF5, 0x6E, 0x13, 0x00, 0x1D, 0x64, 0x13, 0x00, 0x2D, 0x6E, 0x13, 0x00, 0x51, 0x65, 0x13, 0x00, 0xB5, 0x6E, 0x13, 0x00, ++0x2D, 0x6F, 0x13, 0x00, 0xC1, 0x68, 0x13, 0x00, 0x91, 0xBE, 0x12, 0x00, 0x29, 0xC4, 0x12, 0x00, 0x95, 0xBB, 0x12, 0x00, ++0xDD, 0x03, 0x12, 0x00, 0x19, 0xC5, 0x12, 0x00, 0xCD, 0xC6, 0x12, 0x00, 0x2D, 0x1E, 0x12, 0x00, 0x61, 0x1B, 0x12, 0x00, ++0x69, 0x1D, 0x12, 0x00, 0x7D, 0x9D, 0x12, 0x00, 0xA9, 0x9D, 0x12, 0x00, 0x39, 0x12, 0x14, 0x00, 0x99, 0x71, 0x13, 0x00, ++0xC1, 0x21, 0x12, 0x00, 0x51, 0x09, 0x12, 0x00, 0x9D, 0x0A, 0x12, 0x00, 0xA1, 0x0A, 0x12, 0x00, 0xBD, 0x0B, 0x12, 0x00, ++0x41, 0x1C, 0x12, 0x00, 0xD5, 0xCF, 0x12, 0x00, 0x21, 0xD1, 0x12, 0x00, 0xD1, 0x3C, 0x12, 0x00, 0xC5, 0x4B, 0x12, 0x00, ++0xA1, 0x4D, 0x12, 0x00, 0x6D, 0x4C, 0x12, 0x00, 0xAD, 0x4A, 0x12, 0x00, 0x71, 0xC0, 0x12, 0x00, 0x19, 0xC2, 0x12, 0x00, ++0x79, 0xB8, 0x12, 0x00, 0x29, 0x9A, 0x12, 0x00, 0x39, 0x93, 0x12, 0x00, 0xA1, 0x65, 0x12, 0x00, 0xCD, 0xB1, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x58, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC2, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x75, 0x95, 0x13, 0x00, ++0x04, 0x00, 0x00, 0x00, 0xFD, 0x8F, 0x13, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x08, 0x00, 0x00, 0x00, ++0xF1, 0xA9, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x93, 0x13, 0x00, 0x10, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, ++0x16, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x12, 0x00, 0x00, 0x00, ++0xF1, 0xA9, 0x13, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, ++0x1A, 0x00, 0x00, 0x00, 0xCD, 0x90, 0x13, 0x00, 0x6B, 0x00, 0x00, 0x00, 0xF5, 0x96, 0x13, 0x00, 0x6D, 0x00, 0x00, 0x00, ++0xD1, 0x97, 0x13, 0x00, 0x71, 0x00, 0x00, 0x00, 0x19, 0x93, 0x13, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x79, 0x91, 0x13, 0x00, ++0x20, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x1E, 0x00, 0x00, 0x00, ++0xF1, 0xA9, 0x13, 0x00, 0x30, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x22, 0x00, 0x00, 0x00, 0x09, 0xA0, 0x13, 0x00, ++0x84, 0x00, 0x00, 0x00, 0xAD, 0xA0, 0x13, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x4D, 0x8E, 0x13, 0x00, 0x24, 0x00, 0x00, 0x00, ++0xA9, 0x93, 0x13, 0x00, 0x26, 0x00, 0x00, 0x00, 0x4D, 0x94, 0x13, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x8E, 0x13, 0x00, ++0x0C, 0x00, 0x00, 0x00, 0x9D, 0x91, 0x13, 0x00, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x2A, 0x00, 0x00, 0x00, ++0xF1, 0x97, 0x13, 0x00, 0x39, 0x00, 0x00, 0x00, 0xC5, 0x91, 0x13, 0x00, 0x3B, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, ++0x46, 0x00, 0x00, 0x00, 0xCD, 0x8E, 0x13, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x21, 0x8E, 0x13, 0x00, 0x41, 0x00, 0x00, 0x00, ++0x91, 0x98, 0x13, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x8E, 0x13, 0x00, 0x4B, 0x00, 0x00, 0x00, 0xA9, 0x94, 0x13, 0x00, ++0x51, 0x00, 0x00, 0x00, 0x59, 0x8F, 0x13, 0x00, 0x52, 0x00, 0x00, 0x00, 0xB5, 0x9F, 0x13, 0x00, 0x56, 0x00, 0x00, 0x00, ++0x15, 0x95, 0x13, 0x00, 0x87, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x61, 0x00, 0x00, 0x00, 0x21, 0x97, 0x13, 0x00, ++0x63, 0x00, 0x00, 0x00, 0x9D, 0x98, 0x13, 0x00, 0x65, 0x00, 0x00, 0x00, 0xE9, 0x91, 0x13, 0x00, 0x67, 0x00, 0x00, 0x00, ++0x0D, 0x96, 0x13, 0x00, 0x69, 0x00, 0x00, 0x00, 0xF1, 0x9C, 0x13, 0x00, 0x73, 0x00, 0x00, 0x00, 0xE9, 0x98, 0x13, 0x00, ++0x75, 0x00, 0x00, 0x00, 0x0D, 0x8F, 0x13, 0x00, 0x77, 0x00, 0x00, 0x00, 0xA5, 0x92, 0x13, 0x00, 0x79, 0x00, 0x00, 0x00, ++0xCD, 0x92, 0x13, 0x00, 0x7B, 0x00, 0x00, 0x00, 0xE1, 0x9B, 0x13, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x59, 0x99, 0x13, 0x00, ++0x80, 0x00, 0x00, 0x00, 0xBD, 0x96, 0x13, 0x00, 0x82, 0x00, 0x00, 0x00, 0x11, 0x9B, 0x13, 0x00, 0x00, 0x08, 0x00, 0x00, ++0xB9, 0x0E, 0x14, 0x00, 0x85, 0x00, 0x00, 0x00, 0x4D, 0x0F, 0x14, 0x00, 0x86, 0x00, 0x00, 0x00, 0xC9, 0x0F, 0x14, 0x00, ++0x03, 0x08, 0x00, 0x00, 0x71, 0x10, 0x14, 0x00, 0x0D, 0xCD, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xB0, 0x13, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xA1, 0x28, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x4C, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x9D, 0x2F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x84, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x7F, 0x13, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xB5, 0x7F, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x85, 0x4A, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xF2, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x48, 0x13, 0x00, ++0x00, 0x00, 0x00, 0x00, 0xD1, 0x78, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xD1, 0xF4, 0x12, 0x00, 0x04, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, ++0x02, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xF9, 0x4C, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x05, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, ++0x03, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, ++0xF9, 0x4C, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x69, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x6D, 0x12, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x69, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, ++0xBD, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x15, 0x4A, 0x14, 0x00, 0x02, 0x04, 0x00, 0x00, 0xB5, 0x49, 0x14, 0x00, ++0x04, 0x04, 0x00, 0x00, 0x2D, 0x48, 0x14, 0x00, 0x06, 0x04, 0x00, 0x00, 0xF9, 0x47, 0x14, 0x00, 0x09, 0x04, 0x00, 0x00, ++0x95, 0x49, 0x14, 0x00, 0x11, 0x04, 0x00, 0x00, 0x11, 0x49, 0x14, 0x00, 0x0B, 0x04, 0x00, 0x00, 0xC1, 0x4A, 0x14, 0x00, ++0x0D, 0x04, 0x00, 0x00, 0x45, 0x4A, 0x14, 0x00, 0x0F, 0x04, 0x00, 0x00, 0x61, 0x48, 0x14, 0x00, 0x1B, 0x04, 0x00, 0x00, ++0x91, 0x47, 0x14, 0x00, 0x1E, 0x04, 0x00, 0x00, 0x75, 0x47, 0x14, 0x00, 0x1F, 0x04, 0x00, 0x00, 0x59, 0x47, 0x14, 0x00, ++0x01, 0x00, 0x00, 0x00, 0x28, 0x34, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0xBD, 0x68, 0x14, 0x00, 0x02, 0x14, 0x00, 0x00, ++0xED, 0x65, 0x14, 0x00, 0x04, 0x14, 0x00, 0x00, 0x01, 0x67, 0x14, 0x00, 0x07, 0x14, 0x00, 0x00, 0x01, 0x6A, 0x14, 0x00, ++0x09, 0x14, 0x00, 0x00, 0x75, 0x67, 0x14, 0x00, 0x17, 0x14, 0x00, 0x00, 0xB1, 0x72, 0x14, 0x00, 0x19, 0x14, 0x00, 0x00, ++0xB5, 0x6E, 0x14, 0x00, 0x0C, 0x14, 0x00, 0x00, 0x01, 0x68, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, ++0x23, 0x00, 0x00, 0x00, 0x45, 0x6F, 0x14, 0x00, 0x13, 0x14, 0x00, 0x00, 0x45, 0x73, 0x14, 0x00, 0x32, 0x00, 0x00, 0x00, ++0x9D, 0x6F, 0x14, 0x00, 0x15, 0x14, 0x00, 0x00, 0x11, 0x66, 0x14, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, ++0x3C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x42, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x1B, 0x00, 0x00, 0x00, ++0x89, 0x31, 0x14, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, ++0x70, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x72, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x0E, 0x14, 0x00, 0x00, ++0xF5, 0x6F, 0x14, 0x00, 0x10, 0x14, 0x00, 0x00, 0xF1, 0x70, 0x14, 0x00, 0x11, 0x14, 0x00, 0x00, 0x91, 0x71, 0x14, 0x00, ++0x00, 0x18, 0x00, 0x00, 0x1D, 0x8A, 0x14, 0x00, 0x03, 0x18, 0x00, 0x00, 0x6D, 0x92, 0x14, 0x00, 0x01, 0x10, 0x00, 0x00, ++0xA1, 0x8C, 0x14, 0x00, 0x03, 0x10, 0x00, 0x00, 0x09, 0x8D, 0x14, 0x00, 0x08, 0x18, 0x00, 0x00, 0x71, 0x8C, 0x14, 0x00, ++0x43, 0x00, 0x00, 0x00, 0x21, 0x8C, 0x14, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x8D, 0x92, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, ++0xA5, 0x90, 0x14, 0x00, 0x19, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x17, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, ++0x15, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x72, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x1B, 0x00, 0x00, 0x00, ++0xE5, 0x8F, 0x14, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xD9, 0x94, 0x14, 0x00, 0x1A, 0x14, 0x00, 0x00, 0x7D, 0x8F, 0x14, 0x00, ++0x4C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x90, 0x14, 0x00, 0x3A, 0x00, 0x00, 0x00, ++0x65, 0x90, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, 0x99, 0x91, 0x14, 0x00, 0x07, 0x18, 0x00, 0x00, 0xFD, 0x91, 0x14, 0x00, ++0x09, 0x18, 0x00, 0x00, 0x19, 0x92, 0x14, 0x00, 0x00, 0x1C, 0x00, 0x00, 0xF5, 0xB3, 0x14, 0x00, 0x02, 0x1C, 0x00, 0x00, ++0xD5, 0xB6, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, 0xD9, 0xB7, 0x14, 0x00, 0x40, 0x00, 0x00, 0x00, 0xBD, 0xB2, 0x14, 0x00, ++0x19, 0x00, 0x00, 0x00, 0x01, 0xB6, 0x14, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0xB6, 0x14, 0x00, 0x15, 0x00, 0x00, 0x00, ++0x01, 0xB6, 0x14, 0x00, 0x1A, 0x14, 0x00, 0x00, 0x9D, 0xB5, 0x14, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x81, 0xB6, 0x14, 0x00, ++0x3A, 0x00, 0x00, 0x00, 0x41, 0xB6, 0x14, 0x00, 0x04, 0x1C, 0x00, 0x00, 0x01, 0xB3, 0x14, 0x00, 0x06, 0x1C, 0x00, 0x00, ++0x39, 0xB7, 0x14, 0x00, 0x08, 0x1C, 0x00, 0x00, 0x59, 0xB5, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, ++0x02, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, 0x05, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, ++0x89, 0x31, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0x95, 0xBF, 0x14, 0x00, 0x02, 0x10, 0x00, 0x00, 0xF5, 0xC0, 0x14, 0x00, ++0x05, 0x10, 0x00, 0x00, 0xF5, 0xBF, 0x14, 0x00, 0x07, 0x10, 0x00, 0x00, 0xF1, 0xC1, 0x14, 0x00, 0x0A, 0x10, 0x00, 0x00, ++0x7D, 0xC0, 0x14, 0x00, 0x01, 0x08, 0x00, 0x00, 0x39, 0xC2, 0x14, 0x00, 0x02, 0x08, 0x00, 0x00, 0x85, 0xC2, 0x14, 0x00, ++0x00, 0x28, 0x00, 0x00, 0xA1, 0xC2, 0x14, 0x00, 0x0A, 0x10, 0x00, 0x00, 0x51, 0xC0, 0x14, 0x00, 0x04, 0x08, 0x00, 0x00, ++0x4D, 0xC2, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0xD5, 0xC0, 0x14, 0x00, 0x07, 0x10, 0x00, 0x00, 0xA1, 0xC0, 0x14, 0x00, ++0xDC, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x45, 0x04, 0x15, 0x00, 0x01, 0x20, 0x00, 0x00, 0x69, 0x04, 0x15, 0x00, ++0x2B, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x15, 0x00, 0x29, 0x00, 0x00, 0x00, 0x55, 0xFF, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, ++0x35, 0x01, 0x15, 0x00, 0x0D, 0x26, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, ++}; ++ ++char fw_adid_u03[1208] = { ++0x61, 0xBD, 0x08, 0x00, 0xFD, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0x03, 0x08, 0x00, ++0x71, 0x02, 0x08, 0x00, 0x21, 0x04, 0x08, 0x00, 0xD9, 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x0F, 0x08, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x15, 0x08, 0x00, ++0x6D, 0x18, 0x08, 0x00, 0xD1, 0x18, 0x08, 0x00, 0x15, 0x19, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x1D, 0x08, 0x00, ++0xA1, 0x24, 0x08, 0x00, 0x05, 0x26, 0x08, 0x00, 0x3D, 0x2A, 0x08, 0x00, 0x9D, 0x55, 0x08, 0x00, 0x39, 0x76, 0x08, 0x00, ++0x91, 0x76, 0x08, 0x00, 0x9D, 0x7C, 0x08, 0x00, 0xE5, 0x7C, 0x08, 0x00, 0x5D, 0x80, 0x08, 0x00, 0x75, 0xA9, 0x08, 0x00, ++0x9D, 0xBE, 0x08, 0x00, 0xD5, 0xBE, 0x08, 0x00, 0x39, 0xC0, 0x08, 0x00, 0x6D, 0xC2, 0x08, 0x00, 0x3D, 0x05, 0x09, 0x00, ++0xF1, 0x3B, 0x09, 0x00, 0x31, 0x3E, 0x09, 0x00, 0xFD, 0x40, 0x09, 0x00, 0x65, 0x9D, 0x09, 0x00, 0x25, 0xC0, 0x09, 0x00, ++0xF9, 0xBB, 0x09, 0x00, 0x05, 0xA2, 0x09, 0x00, 0x91, 0xD7, 0x09, 0x00, 0x4D, 0xB2, 0x0A, 0x00, 0x25, 0xB6, 0x0A, 0x00, ++0x75, 0xB8, 0x0A, 0x00, 0x2D, 0xB9, 0x0A, 0x00, 0x8D, 0xBB, 0x0A, 0x00, 0x99, 0xBC, 0x0A, 0x00, 0xA1, 0xC5, 0x0A, 0x00, ++0x31, 0xCD, 0x0A, 0x00, 0x09, 0xDE, 0x0A, 0x00, 0xB9, 0xEE, 0x0A, 0x00, 0x35, 0x58, 0x09, 0x00, 0xB1, 0x58, 0x09, 0x00, ++0x15, 0x54, 0x09, 0x00, 0xBD, 0x56, 0x09, 0x00, 0x11, 0x5B, 0x09, 0x00, 0xED, 0x5C, 0x09, 0x00, 0x15, 0x6C, 0x09, 0x00, ++0xB9, 0x60, 0x09, 0x00, 0xDD, 0x29, 0x0B, 0x00, 0x05, 0x76, 0x09, 0x00, 0x75, 0x76, 0x09, 0x00, 0x3D, 0x7A, 0x09, 0x00, ++0x5D, 0x7E, 0x09, 0x00, 0x69, 0x78, 0x09, 0x00, 0x61, 0x79, 0x09, 0x00, 0xD9, 0x7E, 0x09, 0x00, 0x35, 0x41, 0x0B, 0x00, ++0xB5, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x0C, 0x0B, 0x00, 0x85, 0x6F, 0x09, 0x00, 0xD5, 0x7B, 0x0B, 0x00, ++0x75, 0x7C, 0x0B, 0x00, 0xDD, 0x6C, 0x09, 0x00, 0xA9, 0x6D, 0x09, 0x00, 0x75, 0x6E, 0x09, 0x00, 0xE9, 0x1F, 0x0B, 0x00, ++0x35, 0x23, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x1B, 0x0B, 0x00, 0x45, 0x27, 0x0B, 0x00, 0x85, 0x1A, 0x0B, 0x00, ++0x69, 0x17, 0x0B, 0x00, 0xDD, 0x27, 0x0B, 0x00, 0x31, 0x2B, 0x0B, 0x00, 0x25, 0x78, 0x0B, 0x00, 0x15, 0x65, 0x0B, 0x00, ++0x3D, 0x6B, 0x0B, 0x00, 0x9D, 0x67, 0x0B, 0x00, 0x99, 0x6B, 0x0B, 0x00, 0xC5, 0x6C, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x2D, 0xAF, 0x0B, 0x00, 0x3D, 0x99, 0x0C, 0x00, 0xC5, 0xD9, 0x0C, 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, 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, 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, 0x00, 0x61, 0x95, 0x0C, 0x00, 0x3D, 0xD5, 0x0C, 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, 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, 0x00, ++0xF5, 0xA4, 0x08, 0x00, 0xB5, 0xA5, 0x08, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0xFD, 0x50, 0x08, 0x00, 0x9D, 0x7D, 0x08, 0x00, 0xBD, 0x7D, 0x08, 0x00, 0xDD, 0x7D, 0x08, 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, 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, 0xA9, 0x91, 0x08, 0x00, ++0xAB, 0x91, 0x08, 0x00, 0xAD, 0x91, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x71, 0xD5, 0x09, 0x00, 0x6D, 0x0E, 0x08, 0x00, ++}; ++ ++char fw_patch_table_u03[1256] = { ++0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x50, 0x54, 0x5F, 0x54, 0x41, 0x47, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, ++0x54, 0x5F, 0x54, 0x52, 0x41, 0x50, 0x5F, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, ++0x00, 0xF0, 0x16, 0x00, 0x04, 0x23, 0xA3, 0x55, 0x00, 0x10, 0x08, 0x40, 0x88, 0x48, 0x0C, 0x00, 0x04, 0xF0, 0x16, 0x00, ++0x00, 0x2B, 0x05, 0xE0, 0x04, 0x10, 0x08, 0x40, 0x58, 0x58, 0x0B, 0x00, 0x08, 0xF0, 0x16, 0x00, 0x00, 0x2B, 0xB1, 0xE7, ++0x08, 0x10, 0x08, 0x40, 0x30, 0x5A, 0x0B, 0x00, 0x14, 0xEA, 0x16, 0x00, 0x02, 0x49, 0x8E, 0x46, 0x18, 0xEA, 0x16, 0x00, ++0x00, 0xB5, 0x02, 0x4B, 0x1C, 0xEA, 0x16, 0x00, 0xDB, 0x6E, 0x00, 0xBD, 0x20, 0xEA, 0x16, 0x00, 0xD7, 0xCB, 0x0A, 0x00, ++0x24, 0xEA, 0x16, 0x00, 0xAC, 0x2B, 0x16, 0x00, 0x0C, 0xF0, 0x16, 0x00, 0xC1, 0xF0, 0x1F, 0xFF, 0x0C, 0x10, 0x08, 0x40, ++0xD2, 0xCB, 0x0A, 0x00, 0x00, 0xEA, 0x16, 0x00, 0x02, 0x49, 0x8E, 0x46, 0x04, 0xEA, 0x16, 0x00, 0x00, 0xB5, 0x02, 0x4B, ++0x08, 0xEA, 0x16, 0x00, 0xDA, 0x6E, 0x00, 0xBD, 0x0C, 0xEA, 0x16, 0x00, 0xC1, 0xE6, 0x0A, 0x00, 0x10, 0xEA, 0x16, 0x00, ++0xAC, 0x2B, 0x16, 0x00, 0x10, 0xF0, 0x16, 0x00, 0xC0, 0xF0, 0xA0, 0xF9, 0x10, 0x10, 0x08, 0x40, 0xBC, 0xE6, 0x0A, 0x00, ++0x14, 0xF0, 0x16, 0x00, 0x43, 0x1C, 0x05, 0xE0, 0x14, 0x10, 0x08, 0x40, 0x1C, 0xFD, 0x0C, 0x00, 0x30, 0xEA, 0x16, 0x00, ++0x01, 0x4B, 0x98, 0x47, 0x34, 0xEA, 0x16, 0x00, 0x01, 0x4B, 0x9F, 0x46, 0x38, 0xEA, 0x16, 0x00, 0xD9, 0x97, 0x10, 0x00, ++0x3C, 0xEA, 0x16, 0x00, 0x59, 0x1E, 0x0D, 0x00, 0x18, 0xF0, 0x16, 0x00, 0x9C, 0xF0, 0x92, 0xFF, 0x18, 0x10, 0x08, 0x40, ++0x08, 0x1B, 0x0D, 0x00, 0x1C, 0xF0, 0x16, 0x00, 0xEC, 0xE1, 0x10, 0x00, 0x1C, 0x10, 0x08, 0x40, 0x30, 0xB8, 0x0B, 0x00, ++0x84, 0x10, 0x08, 0x40, 0x00, 0xF0, 0x16, 0x00, 0x80, 0x10, 0x08, 0x40, 0xFF, 0x00, 0x00, 0x00, 0x58, 0x00, 0x10, 0x40, ++0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x50, 0x41, 0x54, 0x43, 0x48, 0x5F, 0x54, 0x42, 0x34, 0x00, ++0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x38, 0x1B, 0x16, 0x00, 0x99, 0x12, 0x10, 0x00, 0x98, 0x19, 0x16, 0x00, ++0xA9, 0x23, 0x10, 0x00, 0x18, 0x1B, 0x16, 0x00, 0x81, 0x07, 0x10, 0x00, 0x20, 0x1B, 0x16, 0x00, 0xCD, 0x09, 0x10, 0x00, ++0x28, 0x1B, 0x16, 0x00, 0xF1, 0x0B, 0x10, 0x00, 0xB0, 0x19, 0x16, 0x00, 0x21, 0x25, 0x10, 0x00, 0x70, 0x1A, 0x16, 0x00, ++0xB9, 0x30, 0x10, 0x00, 0x6C, 0x1A, 0x16, 0x00, 0x19, 0x64, 0x10, 0x00, 0xE0, 0x1A, 0x16, 0x00, 0xB9, 0x69, 0x10, 0x00, ++0xE0, 0x19, 0x16, 0x00, 0xCB, 0x09, 0x10, 0x00, 0xDC, 0x19, 0x16, 0x00, 0xC9, 0x09, 0x10, 0x00, 0x38, 0x19, 0x16, 0x00, ++0x89, 0x54, 0x10, 0x00, 0x1C, 0x1B, 0x16, 0x00, 0x69, 0x56, 0x10, 0x00, 0x24, 0x1B, 0x16, 0x00, 0x75, 0x58, 0x10, 0x00, ++0x7C, 0x1D, 0x16, 0x00, 0xDD, 0x5B, 0x10, 0x00, 0xB0, 0x1A, 0x16, 0x00, 0xB9, 0x5A, 0x10, 0x00, 0xB0, 0x1D, 0x16, 0x00, ++0x31, 0x6D, 0x10, 0x00, 0x8C, 0x1D, 0x16, 0x00, 0x19, 0x6E, 0x10, 0x00, 0x88, 0x1D, 0x16, 0x00, 0x49, 0x6E, 0x10, 0x00, ++0x40, 0x19, 0x16, 0x00, 0xF5, 0x6E, 0x10, 0x00, 0x2C, 0x1B, 0x16, 0x00, 0x51, 0x6F, 0x10, 0x00, 0x80, 0x1D, 0x16, 0x00, ++0xC1, 0x5F, 0x10, 0x00, 0xF4, 0x19, 0x16, 0x00, 0x89, 0x6F, 0x10, 0x00, 0xEC, 0x19, 0x16, 0x00, 0x0D, 0x70, 0x10, 0x00, ++0x54, 0x19, 0x16, 0x00, 0x31, 0x93, 0x10, 0x00, 0x14, 0x1B, 0x16, 0x00, 0x35, 0x94, 0x10, 0x00, 0x8C, 0x19, 0x16, 0x00, ++0xE9, 0x71, 0x10, 0x00, 0x88, 0x19, 0x16, 0x00, 0xB9, 0x7A, 0x10, 0x00, 0x04, 0x1B, 0x16, 0x00, 0x35, 0x97, 0x10, 0x00, ++0x90, 0x19, 0x16, 0x00, 0xFD, 0x9E, 0x10, 0x00, 0x94, 0x19, 0x16, 0x00, 0x5D, 0x9F, 0x10, 0x00, 0xE8, 0x19, 0x16, 0x00, ++0x3D, 0xA2, 0x10, 0x00, 0xE4, 0x1A, 0x16, 0x00, 0x35, 0x02, 0x10, 0x00, 0xD4, 0x1A, 0x16, 0x00, 0x69, 0xA2, 0x10, 0x00, ++0x64, 0x1A, 0x16, 0x00, 0x29, 0x33, 0x10, 0x00, 0x08, 0x1B, 0x16, 0x00, 0x55, 0x91, 0x10, 0x00, 0xBC, 0x19, 0x16, 0x00, ++0x31, 0x38, 0x10, 0x00, 0x68, 0x1A, 0x16, 0x00, 0x79, 0x61, 0x10, 0x00, 0x40, 0x1A, 0x16, 0x00, 0x8D, 0x40, 0x10, 0x00, ++0x3C, 0x1A, 0x16, 0x00, 0x41, 0x07, 0x10, 0x00, 0x4C, 0x1A, 0x16, 0x00, 0x85, 0x54, 0x10, 0x00, 0xB8, 0x19, 0x16, 0x00, ++0x9D, 0x3B, 0x10, 0x00, 0x7C, 0x1A, 0x16, 0x00, 0x41, 0x2A, 0x10, 0x00, 0x68, 0xAD, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x4D, 0x4F, 0x44, 0x45, 0x5F, 0x54, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ++0x09, 0x00, 0x00, 0x00, 0xA4, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x54, 0xE0, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xA8, 0xE5, 0x10, 0x00, ++0x02, 0x00, 0x00, 0x00, 0xB8, 0xE5, 0x10, 0x00, 0x60, 0xE3, 0x16, 0x00, 0xBC, 0xE5, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, ++0xAC, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xE5, 0x10, 0x00, 0x20, 0x60, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, ++0x54, 0x5F, 0x50, 0x4F, 0x57, 0x45, 0x52, 0x5F, 0x4F, 0x4E, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, ++0x3C, 0x00, 0x50, 0x40, 0x00, 0x00, 0x08, 0x00, 0x24, 0x01, 0x50, 0x40, 0x40, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, ++0x54, 0x5F, 0x50, 0x41, 0x54, 0x43, 0x48, 0x5F, 0x54, 0x41, 0x46, 0x00, 0x05, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, ++0x24, 0x0A, 0x16, 0x00, 0x65, 0x7E, 0x10, 0x00, 0xA4, 0x12, 0x16, 0x00, 0x1D, 0x84, 0x10, 0x00, 0xBC, 0x12, 0x16, 0x00, ++0xFD, 0xA3, 0x10, 0x00, 0xC4, 0x12, 0x16, 0x00, 0xE9, 0xB2, 0x10, 0x00, 0x0C, 0x08, 0x16, 0x00, 0x1D, 0xA3, 0x10, 0x00, ++0x5C, 0x07, 0x16, 0x00, 0x45, 0xA3, 0x10, 0x00, 0x84, 0x15, 0x16, 0x00, 0xB9, 0x89, 0x10, 0x00, 0x4C, 0x18, 0x16, 0x00, ++0x65, 0x8B, 0x10, 0x00, 0x6C, 0x18, 0x16, 0x00, 0xE9, 0x8B, 0x10, 0x00, 0xDC, 0x18, 0x16, 0x00, 0x35, 0x8C, 0x10, 0x00, ++0xF4, 0x1A, 0x16, 0x00, 0x99, 0x05, 0x10, 0x00, 0xAC, 0x12, 0x16, 0x00, 0x35, 0x76, 0x10, 0x00, 0x04, 0x10, 0x16, 0x00, ++0xD1, 0x8E, 0x10, 0x00, 0x0C, 0x10, 0x16, 0x00, 0x25, 0x90, 0x10, 0x00, 0x84, 0x10, 0x16, 0x00, 0x41, 0xAA, 0x10, 0x00, ++0x9C, 0x10, 0x16, 0x00, 0xB1, 0xAA, 0x10, 0x00, 0xA4, 0x10, 0x16, 0x00, 0x71, 0xAB, 0x10, 0x00, 0x4C, 0x10, 0x16, 0x00, ++0x5D, 0xAC, 0x10, 0x00, 0xE4, 0x0F, 0x16, 0x00, 0x65, 0x90, 0x10, 0x00, 0xEC, 0x13, 0x16, 0x00, 0xC5, 0xA7, 0x10, 0x00, ++0x0C, 0x13, 0x16, 0x00, 0x55, 0xB3, 0x10, 0x00, 0xFC, 0x12, 0x16, 0x00, 0x1D, 0x26, 0x10, 0x00, 0x74, 0x0A, 0x16, 0x00, ++0xED, 0x27, 0x10, 0x00, 0x74, 0x13, 0x16, 0x00, 0x35, 0xA8, 0x10, 0x00, 0x04, 0x14, 0x16, 0x00, 0xD9, 0xA8, 0x10, 0x00, ++0x4C, 0x14, 0x16, 0x00, 0xB1, 0xAE, 0x10, 0x00, 0x3C, 0x0A, 0x16, 0x00, 0x05, 0xAF, 0x10, 0x00, 0x44, 0x0A, 0x16, 0x00, ++0xF1, 0xAF, 0x10, 0x00, 0x04, 0x15, 0x16, 0x00, 0x51, 0x91, 0x10, 0x00, 0x2C, 0x13, 0x16, 0x00, 0xA1, 0x42, 0x10, 0x00, ++0xD4, 0x0A, 0x16, 0x00, 0xED, 0xAD, 0x10, 0x00, 0x44, 0x11, 0x16, 0x00, 0x51, 0xAD, 0x10, 0x00, 0xE4, 0x12, 0x16, 0x00, ++0x09, 0xA7, 0x10, 0x00, 0x7C, 0x09, 0x16, 0x00, 0x15, 0xCD, 0x10, 0x00, 0x8C, 0x09, 0x16, 0x00, 0x4D, 0xCD, 0x10, 0x00, ++0x94, 0x09, 0x16, 0x00, 0xC1, 0xCD, 0x10, 0x00, 0x6C, 0x14, 0x16, 0x00, 0x71, 0xCD, 0x10, 0x00, 0x70, 0x30, 0x50, 0x40, ++0x00, 0x00, 0x00, 0x00, 0x74, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x78, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, ++0x7C, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x56, 0x45, 0x52, 0x5F, 0x49, 0x4E, ++0x46, 0x4F, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2D, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, 0x33, ++0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x33, 0x38, 0x3A, 0x33, 0x39, 0x20, 0x2D, 0x20, 0x67, 0x69, 0x74, ++0x20, 0x30, 0x61, 0x61, 0x62, 0x66, 0x62, 0x66, 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, ++}; ++ ++char fw_patch_u03[59704] = { ++0x10, 0xB5, 0x15, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0x13, 0x4B, 0x1B, 0x68, ++0x3F, 0x22, 0x9A, 0x5C, 0x00, 0x2A, 0xF6, 0xD1, 0x3D, 0x32, 0x9C, 0x5C, 0x10, 0x4B, 0x1A, 0x78, 0x01, 0x32, 0xD2, 0xB2, ++0x10, 0x2A, 0x10, 0xD8, 0x1A, 0x70, 0x0D, 0x49, 0x0A, 0x78, 0x12, 0x03, 0x92, 0xB2, 0x62, 0x23, 0x63, 0x43, 0x0B, 0x4C, ++0x1C, 0x19, 0x22, 0x80, 0x0A, 0x78, 0x12, 0x09, 0x09, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x1A, 0x80, 0xDD, 0xE7, 0x05, 0x4B, ++0x00, 0x22, 0x1A, 0x70, 0xEB, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0xC1, 0xE9, 0x0A, 0x00, 0x28, 0x27, 0x16, 0x00, ++0xB0, 0xE6, 0x10, 0x00, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x0B, 0x4B, 0x1B, 0x68, ++0x00, 0x2B, 0x03, 0xD0, 0x3A, 0x22, 0x9B, 0x5C, 0x01, 0x2B, 0x06, 0xD0, 0x20, 0x00, 0x08, 0x4B, 0x98, 0x47, 0x62, 0x68, ++0x07, 0x4B, 0x1A, 0x60, 0x10, 0xBD, 0x07, 0x49, 0x0B, 0x68, 0x07, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, ++0x0B, 0x60, 0xEF, 0xE7, 0x18, 0x27, 0x16, 0x00, 0x25, 0xC3, 0x0C, 0x00, 0x30, 0xE6, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, ++0xFF, 0xFF, 0xDF, 0xFF, 0x10, 0xB5, 0x18, 0x4A, 0x00, 0x23, 0x00, 0x24, 0x14, 0x57, 0x84, 0x42, 0x04, 0xDA, 0x01, 0x33, ++0xDB, 0xB2, 0x01, 0x32, 0x08, 0x2B, 0xF6, 0xD1, 0x12, 0x4A, 0xD2, 0x56, 0x82, 0x42, 0x05, 0xD0, 0x00, 0x29, 0x03, 0xD1, ++0x00, 0x2B, 0x01, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x1A, 0x1C, 0x07, 0x2B, 0x00, 0xD9, 0x07, 0x22, 0xD2, 0xB2, 0x0C, 0x4B, ++0x99, 0x5C, 0x0C, 0x4A, 0x95, 0x23, 0x9B, 0x00, 0xD3, 0x5C, 0x1A, 0x1C, 0xDB, 0xB2, 0x8B, 0x42, 0x00, 0xD9, 0x0A, 0x1C, ++0x07, 0x49, 0x08, 0x4B, 0xCB, 0x5C, 0x18, 0x1C, 0xDB, 0xB2, 0xD1, 0xB2, 0x8B, 0x42, 0x00, 0xD2, 0x10, 0x1C, 0xC0, 0xB2, ++0x10, 0xBD, 0xC0, 0x46, 0x28, 0xE0, 0x10, 0x00, 0xBC, 0xDF, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x55, 0x02, 0x00, 0x00, ++0x10, 0xB5, 0x62, 0x22, 0x42, 0x43, 0x0F, 0x4B, 0x9C, 0x46, 0x62, 0x44, 0x13, 0x88, 0xDB, 0xB2, 0x1E, 0x2B, 0x13, 0xD0, ++0x0C, 0x49, 0x0D, 0x48, 0x0C, 0x5C, 0x0D, 0x48, 0x09, 0x5C, 0x09, 0x19, 0x01, 0x20, 0x8B, 0x42, 0x09, 0xDB, 0x1B, 0x1B, ++0xDB, 0xB2, 0x10, 0x2B, 0x08, 0xD0, 0x11, 0x88, 0xFF, 0x20, 0x81, 0x43, 0x0B, 0x43, 0x13, 0x80, 0x00, 0x20, 0x10, 0xBD, ++0x0E, 0x3B, 0xE9, 0xE7, 0x0E, 0x33, 0xF4, 0xE7, 0x0C, 0x65, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, 0x57, 0x02, 0x00, 0x00, ++0x55, 0x02, 0x00, 0x00, 0x30, 0xB5, 0x62, 0x22, 0x42, 0x43, 0x0F, 0x4B, 0x9C, 0x46, 0x62, 0x44, 0x13, 0x88, 0xDB, 0xB2, ++0x1E, 0x2B, 0x12, 0xD0, 0x0C, 0x49, 0x0D, 0x48, 0x0C, 0x5C, 0x1D, 0x19, 0x03, 0x38, 0x09, 0x5C, 0x01, 0x20, 0x8D, 0x42, ++0x08, 0xDC, 0xEB, 0xB2, 0x10, 0x2B, 0x08, 0xD0, 0x11, 0x88, 0xFF, 0x20, 0x81, 0x43, 0x0B, 0x43, 0x13, 0x80, 0x00, 0x20, ++0x30, 0xBD, 0x0E, 0x3B, 0xEA, 0xE7, 0x0E, 0x33, 0xF4, 0xE7, 0xC0, 0x46, 0x0C, 0x65, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, ++0x57, 0x02, 0x00, 0x00, 0x70, 0x47, 0x70, 0x47, 0x70, 0xB5, 0x00, 0x28, 0x1C, 0xD0, 0x12, 0x4B, 0x1D, 0x68, 0x00, 0x2D, ++0x18, 0xD0, 0xE9, 0x78, 0x09, 0x02, 0x01, 0x23, 0x19, 0x43, 0x03, 0x33, 0xFF, 0x22, 0x0E, 0x48, 0x81, 0xF7, 0xFA, 0xFE, ++0x04, 0x1E, 0x0E, 0xD0, 0x20, 0x00, 0x81, 0xF7, 0x1F, 0xFF, 0xAB, 0xF7, 0x23, 0xFB, 0x03, 0x00, 0x09, 0x48, 0x6A, 0x68, ++0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x43, 0x60, 0xD6, 0xF7, 0x9E, 0xFE, 0x70, 0xBD, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xE9, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x3F, 0x06, 0x00, 0x00, 0xFC, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x05, 0x00, 0x22, 0x4B, 0x23, 0x4A, 0x13, 0x60, 0x02, 0x22, 0xFF, 0x32, 0x9C, 0x5C, ++0x21, 0x4B, 0xE2, 0x18, 0x12, 0x01, 0x13, 0x88, 0x9B, 0x06, 0x5B, 0x0F, 0x01, 0x2B, 0x04, 0xD0, 0x13, 0x88, 0x9B, 0x06, ++0x5B, 0x0F, 0x02, 0x2B, 0x0F, 0xD1, 0x23, 0x01, 0x18, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x1B, 0x7B, 0x00, 0x2B, 0x05, 0xD1, ++0x13, 0x88, 0x38, 0x21, 0x8B, 0x43, 0x20, 0x39, 0x0B, 0x43, 0x13, 0x80, 0x15, 0x48, 0x83, 0xF7, 0xB9, 0xFF, 0x15, 0x4B, ++0x2A, 0x68, 0x9A, 0x42, 0x0F, 0xD0, 0x14, 0x4F, 0xDE, 0x26, 0x76, 0x00, 0x00, 0x23, 0xBB, 0x51, 0x28, 0x00, 0xD7, 0xF7, ++0x4B, 0xF9, 0x11, 0x4B, 0xBB, 0x51, 0xAB, 0xF7, 0xD5, 0xFA, 0xA4, 0x00, 0x0F, 0x4B, 0x18, 0x51, 0xF8, 0xBD, 0x0F, 0x4B, ++0x1B, 0x68, 0x02, 0x2B, 0xEB, 0xD1, 0x2B, 0x7C, 0x9B, 0x00, 0x0D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x68, 0x0C, 0x4A, ++0x12, 0x68, 0x1A, 0x66, 0x1A, 0x61, 0xE0, 0xE7, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0x00, 0x10, 0x06, 0x04, ++0xF8, 0xCD, 0x10, 0x00, 0xD1, 0x1F, 0x0D, 0x00, 0x28, 0x19, 0x16, 0x00, 0x35, 0x02, 0x10, 0x00, 0xE0, 0xE5, 0x10, 0x00, ++0x50, 0xE0, 0x10, 0x00, 0xF4, 0x29, 0x16, 0x00, 0xE8, 0xE1, 0x10, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x04, 0x1E, 0x32, 0xD0, ++0x9E, 0x23, 0xC5, 0x5C, 0x1B, 0x4B, 0x00, 0x93, 0x43, 0x68, 0x01, 0x93, 0x83, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1D, 0x76, ++0x04, 0x95, 0x18, 0x4B, 0x03, 0x93, 0x83, 0x7D, 0x6A, 0x46, 0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, 0x93, 0x75, ++0xB0, 0x22, 0x82, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, 0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, 0xD7, 0xF7, ++0xFB, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x47, 0x3A, 0x6A, 0x43, 0x0C, 0x4B, 0x9C, 0x46, 0x62, 0x44, ++0x13, 0x88, 0xFF, 0x21, 0x8B, 0x43, 0x01, 0x21, 0x0B, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0xA0, 0x23, 0xE1, 0x54, 0x09, 0xB0, ++0x30, 0xBD, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xF6, 0xE7, 0xD1, 0xBD, 0x10, 0x00, ++0xDE, 0x05, 0x00, 0x00, 0x1E, 0x65, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x03, 0x00, 0x0D, 0x00, ++0x89, 0x00, 0x2B, 0x4A, 0x8C, 0x58, 0x00, 0x2C, 0x36, 0xD0, 0xA6, 0x22, 0xA2, 0x5C, 0x12, 0x1A, 0x03, 0x20, 0x10, 0x40, ++0xC0, 0x18, 0x00, 0x01, 0x00, 0x09, 0x63, 0x68, 0xC3, 0x1A, 0x1A, 0x01, 0x12, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8A, 0x42, ++0x26, 0xD8, 0x1B, 0x01, 0x20, 0x2B, 0x23, 0xD9, 0x20, 0x4B, 0x00, 0x93, 0x01, 0x90, 0xA3, 0x68, 0x02, 0x93, 0x6B, 0x46, ++0x1D, 0x76, 0x04, 0x95, 0x1D, 0x4B, 0x03, 0x93, 0xA3, 0x7D, 0x6A, 0x46, 0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, ++0x93, 0x75, 0xB0, 0x22, 0xA2, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, 0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, ++0xD7, 0xF7, 0xA0, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x9F, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x01, 0xD0, ++0x09, 0xB0, 0x30, 0xBD, 0xA3, 0x6F, 0x9B, 0xB2, 0x62, 0x21, 0x4D, 0x43, 0x0D, 0x4A, 0xAA, 0x18, 0x13, 0x80, 0xA3, 0x6F, ++0x1B, 0x0C, 0x0C, 0x4A, 0xAA, 0x18, 0x13, 0x80, 0x0B, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x0B, 0x4B, 0x1B, 0x68, 0xDB, 0x03, ++0xFF, 0x22, 0xD2, 0x03, 0x1A, 0x40, 0x23, 0x6D, 0x13, 0x43, 0x9B, 0xB2, 0x2B, 0x80, 0xE3, 0xE7, 0x38, 0xE6, 0x10, 0x00, ++0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, ++0xC8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x00, 0x28, 0x08, 0xD0, 0x08, 0x4B, 0x98, 0x47, 0x08, 0x4B, 0x1B, 0x68, 0xD9, 0x6A, ++0x05, 0x20, 0xD7, 0xF7, 0x5B, 0xFF, 0x10, 0xBD, 0x05, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0xF7, 0xE7, 0xC0, 0x46, 0x85, 0xC0, 0x0A, 0x00, 0x18, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x04, 0x4B, ++0x98, 0x47, 0x04, 0x4B, 0x1B, 0x68, 0x59, 0x6B, 0x06, 0x20, 0xD7, 0xF7, 0x43, 0xFF, 0x10, 0xBD, 0xA5, 0xD7, 0x0A, 0x00, ++0x24, 0x27, 0x16, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x04, 0x1E, 0x5A, 0xD0, 0x9F, 0x23, 0xC3, 0x5C, 0x01, 0x2B, 0x04, 0xD0, ++0xA0, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x09, 0xB0, 0x30, 0xBD, 0x9D, 0x33, 0xC5, 0x5C, 0x2B, 0x4B, 0x00, 0x93, 0x43, 0x68, ++0x01, 0x93, 0x83, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1D, 0x76, 0x04, 0x95, 0x27, 0x4B, 0x03, 0x93, 0x83, 0x7D, 0x6A, 0x46, ++0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, 0x93, 0x75, 0xB0, 0x22, 0x82, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, ++0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, 0xD7, 0xF7, 0x1A, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, ++0x9F, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0xD3, 0xD1, 0x23, 0x6D, 0x01, 0x33, 0x5B, 0x08, 0xA2, 0x6F, 0x91, 0xB2, 0x62, 0x22, ++0x55, 0x43, 0x17, 0x4A, 0xAA, 0x18, 0x11, 0x80, 0xA2, 0x6F, 0x12, 0x0C, 0x15, 0x49, 0x69, 0x18, 0x0A, 0x80, 0x15, 0x4A, ++0x94, 0x46, 0x65, 0x44, 0x01, 0x33, 0x5B, 0x08, 0x13, 0x4A, 0x13, 0x43, 0x9B, 0xB2, 0x2B, 0x80, 0x9F, 0x23, 0xE3, 0x5C, ++0x01, 0x2B, 0xB7, 0xD1, 0xA5, 0x33, 0xE2, 0x5C, 0x01, 0x32, 0xA3, 0x3B, 0x13, 0x40, 0x9E, 0x22, 0xA1, 0x5C, 0x9C, 0x3A, ++0x0C, 0x48, 0xD7, 0xF7, 0x3D, 0xF9, 0xAA, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xA8, 0xE7, 0x0A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA4, 0xE7, 0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, 0xFA, 0x64, 0x61, 0x40, ++0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0x7D, 0x03, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x00, 0x09, 0x01, 0x4B, 0x18, 0x56, 0x70, 0x47, 0x28, 0xE0, 0x10, 0x00, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, ++0xC0, 0xB5, 0x8A, 0x46, 0x5B, 0x49, 0x09, 0x78, 0x06, 0x29, 0x23, 0xD0, 0x5A, 0x49, 0x0C, 0x78, 0x01, 0x2C, 0x07, 0xD0, ++0x20, 0x21, 0x55, 0x46, 0x69, 0x5C, 0x1E, 0x29, 0x08, 0xD8, 0x56, 0x49, 0x01, 0x25, 0x0D, 0x70, 0x20, 0x21, 0x55, 0x46, ++0x69, 0x5C, 0x1F, 0x29, 0x00, 0xD9, 0x9B, 0xE0, 0x52, 0x4F, 0xE6, 0x25, 0x6D, 0x00, 0x00, 0x21, 0x79, 0x51, 0x51, 0x46, ++0x50, 0x4E, 0xB0, 0x47, 0x50, 0x4B, 0x7B, 0x51, 0x4C, 0x4B, 0x1C, 0x70, 0x00, 0x20, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xF0, 0xBD, 0x00, 0x21, 0xE5, 0x20, 0x81, 0xF7, 0xC8, 0xFD, 0x80, 0x46, 0x00, 0x28, 0x14, 0xD0, 0x20, 0x23, ++0x52, 0x46, 0xD7, 0x5C, 0x04, 0x33, 0xD1, 0x5C, 0x53, 0x8C, 0xC9, 0x18, 0x89, 0xB2, 0x45, 0x4B, 0x9C, 0x46, 0x61, 0x44, ++0x3A, 0x00, 0x40, 0x46, 0xD8, 0xF7, 0xDC, 0xFB, 0x00, 0x2F, 0x64, 0xD0, 0x45, 0x46, 0x41, 0x4B, 0x99, 0x46, 0x14, 0xE0, ++0x3B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xE3, 0xE7, 0x05, 0x2C, 0x27, 0xD0, 0x4B, 0x46, ++0x1A, 0x88, 0x3B, 0x4B, 0x9A, 0x42, 0x36, 0xD0, 0xE2, 0x43, 0xBF, 0x18, 0xFF, 0xB2, 0x01, 0x34, 0x2D, 0x19, 0x00, 0x2F, ++0x4B, 0xD0, 0x2C, 0x78, 0x6E, 0x78, 0x16, 0x2E, 0xED, 0xD0, 0xFF, 0x2E, 0xED, 0xD1, 0x0D, 0x2C, 0xEB, 0xD1, 0xAB, 0x78, ++0x5D, 0x2B, 0xE8, 0xD1, 0xEB, 0x78, 0x00, 0x2B, 0xE5, 0xD1, 0x2B, 0x79, 0x03, 0x2B, 0xE2, 0xD1, 0x6B, 0x79, 0x00, 0x2B, ++0xDF, 0xD1, 0x2D, 0x48, 0x83, 0xF7, 0xB6, 0xFD, 0x2C, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xD7, 0xE7, 0xAB, 0x78, ++0x01, 0x2B, 0xD4, 0xD1, 0xEB, 0x78, 0xFD, 0x2B, 0xD1, 0xD1, 0x2B, 0x79, 0x00, 0x2B, 0xCE, 0xD1, 0x6B, 0x79, 0x01, 0x2B, ++0xCB, 0xD1, 0x25, 0x48, 0x83, 0xF7, 0xA2, 0xFD, 0x22, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xC3, 0xE7, 0x1D, 0x4B, ++0x5B, 0x88, 0xB3, 0x42, 0xC4, 0xD1, 0x1B, 0x4B, 0x9B, 0x68, 0x00, 0x2B, 0x0C, 0xD0, 0x19, 0x4B, 0x9A, 0x79, 0xA9, 0x1C, ++0x98, 0x68, 0xD8, 0xF7, 0x5F, 0xFB, 0x00, 0x28, 0xB8, 0xD1, 0x18, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xB3, 0xE7, ++0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEB, 0xE7, 0x20, 0x23, 0x52, 0x46, 0xD3, 0x5C, ++0x00, 0x2B, 0x03, 0xD1, 0x40, 0x46, 0x81, 0xF7, 0xEB, 0xFD, 0x73, 0xE7, 0x50, 0x8C, 0xBA, 0xF7, 0xAD, 0xFD, 0xF7, 0xE7, ++0x53, 0x46, 0x58, 0x8C, 0xBA, 0xF7, 0xA8, 0xFD, 0x6A, 0xE7, 0xC0, 0x46, 0xD0, 0xE5, 0x10, 0x00, 0x59, 0xA9, 0x16, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x45, 0xF8, 0x0B, 0x00, 0x99, 0x05, 0x10, 0x00, 0x00, 0x00, 0x61, 0x40, 0xC4, 0xE5, 0x10, 0x00, ++0x88, 0xAC, 0x00, 0x00, 0x10, 0xCE, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x00, 0xCE, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, ++0x07, 0x4E, 0x8A, 0x25, 0x6D, 0x00, 0x00, 0x21, 0x71, 0x51, 0x21, 0x00, 0xB3, 0xF7, 0xF0, 0xFC, 0xA4, 0x00, 0x04, 0x4B, ++0xE3, 0x58, 0x04, 0x4A, 0xDA, 0x61, 0x04, 0x4B, 0x73, 0x51, 0x70, 0xBD, 0x28, 0x19, 0x16, 0x00, 0x54, 0x27, 0x16, 0x00, ++0x21, 0x61, 0x10, 0x00, 0x41, 0x07, 0x10, 0x00, 0x10, 0xB5, 0xD2, 0x23, 0x5B, 0x00, 0x1B, 0x68, 0x98, 0x47, 0x10, 0xBD, ++0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0xE3, 0xB0, 0x01, 0xAC, 0xC2, 0x25, 0x6D, 0x00, 0x2A, 0x00, 0x00, 0x21, ++0x20, 0x00, 0x7F, 0xF7, 0xAB, 0xFC, 0x7A, 0x4E, 0x2A, 0x00, 0x00, 0x21, 0x30, 0x68, 0x7F, 0xF7, 0xA5, 0xFC, 0x31, 0x68, ++0x2A, 0x00, 0x01, 0xA8, 0xD8, 0xF7, 0x14, 0xFB, 0x75, 0x48, 0x83, 0xF7, 0x1D, 0xFD, 0x50, 0x22, 0x00, 0x21, 0x4E, 0xA8, ++0x7F, 0xF7, 0x98, 0xFC, 0x00, 0x26, 0x9A, 0x23, 0x5B, 0x00, 0xE6, 0x54, 0x4E, 0xA9, 0x00, 0x20, 0x8B, 0xF7, 0x3A, 0xF8, ++0x86, 0x3D, 0xC0, 0x23, 0x5B, 0x00, 0xE5, 0x54, 0x80, 0x3B, 0xFF, 0x3B, 0x98, 0x46, 0x82, 0x33, 0xFF, 0x33, 0x42, 0x46, ++0xE2, 0x54, 0x03, 0x27, 0x82, 0x23, 0xFF, 0x33, 0xE7, 0x54, 0x0D, 0x3B, 0xE7, 0x54, 0x36, 0x23, 0xFF, 0x33, 0x99, 0x46, ++0xE6, 0x54, 0x4E, 0xA9, 0x00, 0x20, 0x87, 0xF7, 0x6B, 0xFE, 0x4B, 0x46, 0xE0, 0x5C, 0x4E, 0xA9, 0x8B, 0xF7, 0x6A, 0xF8, ++0x50, 0x22, 0x00, 0x21, 0x3A, 0xA8, 0x7F, 0xF7, 0x6D, 0xFC, 0xE4, 0x23, 0xE6, 0x54, 0x3A, 0xA9, 0x00, 0x20, 0x8B, 0xF7, ++0x11, 0xF8, 0x32, 0x23, 0xFF, 0x33, 0xE5, 0x54, 0x30, 0x3B, 0xFF, 0x3B, 0x99, 0x22, 0x52, 0x00, 0xA3, 0x54, 0x02, 0x3A, ++0xA3, 0x54, 0x0C, 0x3A, 0xA3, 0x54, 0x19, 0x3D, 0x43, 0x46, 0x63, 0x55, 0x3A, 0xA9, 0x01, 0x20, 0x87, 0xF7, 0x48, 0xFE, ++0x60, 0x5D, 0x3A, 0xA9, 0x8B, 0xF7, 0x48, 0xF8, 0x4E, 0x4B, 0x1E, 0x60, 0x4E, 0x4D, 0x2E, 0x60, 0x4E, 0x4B, 0x42, 0x46, ++0x1A, 0x60, 0x4E, 0x49, 0x0B, 0x68, 0x4E, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x4C, 0x4C, ++0x27, 0x60, 0x4C, 0x4B, 0x19, 0x68, 0x4C, 0x48, 0xD7, 0xF7, 0x60, 0xFE, 0x0F, 0x23, 0x03, 0x40, 0x22, 0x68, 0x80, 0x21, ++0x8A, 0x43, 0x0A, 0x43, 0x22, 0x60, 0x06, 0x09, 0xFF, 0x22, 0x16, 0x40, 0x46, 0x4F, 0x3E, 0x60, 0x00, 0x0B, 0x10, 0x40, ++0x28, 0x60, 0x5A, 0x08, 0x9B, 0x1A, 0x1B, 0x01, 0x9B, 0x18, 0x43, 0x4A, 0x13, 0x60, 0x23, 0x68, 0x8B, 0x43, 0x23, 0x60, ++0x41, 0x4B, 0x1B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x3F, 0x4A, 0x13, 0x6F, 0x71, 0x39, 0x8B, 0x43, 0x0D, 0x39, 0x0B, 0x43, ++0x13, 0x67, 0x3C, 0x4B, 0x5B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x3A, 0x4A, 0x53, 0x6F, 0x0F, 0x21, 0x8B, 0x43, 0x0D, 0x39, ++0x0B, 0x43, 0x53, 0x67, 0x36, 0x4B, 0x9B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x34, 0x4A, 0x93, 0x6F, 0x0F, 0x21, 0x8B, 0x43, ++0x0D, 0x39, 0x0B, 0x43, 0x93, 0x67, 0x31, 0x4B, 0xDB, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x2F, 0x4A, 0xD3, 0x6F, 0x0F, 0x21, ++0x8B, 0x43, 0x0D, 0x39, 0x0B, 0x43, 0xD3, 0x67, 0x2B, 0x4B, 0x19, 0x69, 0x0F, 0x24, 0xA1, 0x43, 0x03, 0x20, 0x01, 0x43, ++0x19, 0x61, 0x59, 0x69, 0xA1, 0x43, 0x01, 0x43, 0x59, 0x61, 0x99, 0x69, 0xA1, 0x43, 0x01, 0x43, 0x99, 0x61, 0xDA, 0x69, ++0xA2, 0x43, 0x02, 0x43, 0xDA, 0x61, 0x18, 0x4B, 0x07, 0x22, 0x1A, 0x60, 0x01, 0xAA, 0x00, 0x23, 0x20, 0x21, 0x53, 0x54, ++0x06, 0x93, 0x05, 0x93, 0x02, 0x93, 0x01, 0x93, 0x15, 0x4A, 0x13, 0x68, 0x1E, 0x39, 0x0B, 0x43, 0x13, 0x60, 0x1B, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x03, 0xD0, 0x13, 0x68, 0x1E, 0x31, 0x0B, 0x43, 0x13, 0x60, 0x18, 0x4B, 0x9A, 0x68, 0x84, 0x23, ++0x17, 0x49, 0xD1, 0x50, 0x17, 0x4B, 0x80, 0x22, 0x92, 0x01, 0x1A, 0x60, 0xC2, 0x22, 0x05, 0x4B, 0x18, 0x68, 0x52, 0x00, ++0x01, 0xA9, 0xD8, 0xF7, 0x2F, 0xFA, 0x63, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0xFC, 0xE1, 0x10, 0x00, ++0x20, 0xCE, 0x10, 0x00, 0x08, 0x20, 0x04, 0x40, 0x04, 0x20, 0x04, 0x40, 0x24, 0x20, 0x04, 0x40, 0x10, 0x20, 0x04, 0x40, ++0xFF, 0xFE, 0xFF, 0xFF, 0x0C, 0x20, 0x04, 0x40, 0xB8, 0xE5, 0x10, 0x00, 0x00, 0x75, 0x19, 0x03, 0x00, 0x20, 0x04, 0x40, ++0x28, 0x20, 0x04, 0x40, 0x00, 0x30, 0x50, 0x40, 0xBC, 0xE5, 0x10, 0x00, 0x00, 0xED, 0x00, 0xE0, 0xC5, 0x88, 0x08, 0x00, ++0x00, 0xE1, 0x00, 0xE0, 0x70, 0x47, 0x70, 0x47, 0x3D, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, 0x3E, 0x4B, 0x8D, 0x22, 0x12, 0x03, ++0x1A, 0x60, 0x3D, 0x4B, 0x3D, 0x4A, 0x1A, 0x60, 0x3D, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, 0x3E, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, ++0x3E, 0x4B, 0x3F, 0x4A, 0x1A, 0x60, 0x3F, 0x4B, 0x3F, 0x4A, 0x1A, 0x60, 0x3F, 0x4B, 0x40, 0x4A, 0x1A, 0x60, 0x40, 0x4B, ++0x40, 0x4A, 0x1A, 0x60, 0x40, 0x4B, 0x41, 0x4A, 0x1A, 0x60, 0x41, 0x4B, 0x41, 0x4A, 0x1A, 0x60, 0x41, 0x4B, 0x42, 0x4A, ++0x1A, 0x60, 0x42, 0x4B, 0x42, 0x4A, 0x1A, 0x60, 0x42, 0x4B, 0x43, 0x4A, 0x1A, 0x60, 0x43, 0x4B, 0x43, 0x4A, 0x1A, 0x60, ++0x43, 0x4B, 0x44, 0x4A, 0x1A, 0x60, 0x44, 0x4B, 0x44, 0x4A, 0x1A, 0x60, 0x44, 0x4B, 0x45, 0x4A, 0x1A, 0x60, 0x45, 0x4B, ++0x45, 0x4A, 0x1A, 0x60, 0x45, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x88, 0x22, ++0x52, 0x01, 0x1A, 0x60, 0x45, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x46, 0x4A, 0x13, 0x60, 0x46, 0x4A, 0x47, 0x49, ++0x11, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4B, 0x47, 0x4A, 0x1A, 0x60, ++0x47, 0x4B, 0x48, 0x4A, 0x1A, 0x60, 0x48, 0x4B, 0x48, 0x4A, 0x1A, 0x60, 0x48, 0x4B, 0x49, 0x4A, 0x1A, 0x60, 0x49, 0x4B, ++0x49, 0x4A, 0x1A, 0x60, 0x49, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0xFF, 0x22, ++0x12, 0x02, 0x1A, 0x60, 0x49, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x74, 0x22, ++0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4B, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0x04, 0x01, 0x58, 0x40, ++0xFB, 0x33, 0x09, 0x00, 0x1C, 0x20, 0x62, 0x40, 0x28, 0x20, 0x62, 0x40, 0x20, 0x20, 0x91, 0x48, 0x14, 0x20, 0x62, 0x40, ++0x83, 0x89, 0x01, 0x00, 0x54, 0x20, 0x62, 0x40, 0x34, 0x8F, 0x00, 0x00, 0x48, 0x07, 0x62, 0x40, 0xA0, 0x01, 0x1A, 0x02, ++0x28, 0x07, 0x62, 0x40, 0x20, 0x00, 0x01, 0x00, 0x38, 0x07, 0x62, 0x40, 0xD4, 0x0F, 0x80, 0x04, 0x3C, 0x07, 0x62, 0x40, ++0x64, 0x00, 0xC8, 0x00, 0x2C, 0x20, 0x62, 0x40, 0x20, 0xB2, 0x0C, 0x00, 0x0C, 0x20, 0x62, 0x40, 0x45, 0x2B, 0xAD, 0xE9, ++0x30, 0x20, 0x62, 0x40, 0xD2, 0x30, 0x0C, 0x14, 0x34, 0x20, 0x62, 0x40, 0x02, 0x16, 0x00, 0x00, 0x54, 0x07, 0x62, 0x40, ++0xFD, 0x20, 0x42, 0x21, 0x58, 0x07, 0x62, 0x40, 0x1E, 0xF0, 0x07, 0x00, 0x1C, 0x07, 0x62, 0x40, 0x33, 0x0A, 0x00, 0x00, ++0x18, 0x20, 0x62, 0x40, 0x24, 0x41, 0x12, 0x00, 0x0C, 0x00, 0x62, 0x40, 0x00, 0x00, 0x04, 0x04, 0x90, 0x00, 0x62, 0x40, ++0x82, 0x90, 0x06, 0x00, 0x34, 0x10, 0x62, 0x40, 0x80, 0x30, 0x00, 0x02, 0x14, 0x10, 0x62, 0x40, 0x7A, 0x11, 0x45, 0x04, ++0x24, 0x20, 0x62, 0x40, 0x04, 0x20, 0x62, 0x40, 0xC0, 0xA9, 0x01, 0x00, 0x34, 0x08, 0x50, 0x00, 0x8C, 0x04, 0x60, 0x40, ++0x10, 0x01, 0x60, 0x40, 0x58, 0x00, 0x7E, 0x02, 0x80, 0x08, 0x60, 0x40, 0x84, 0x08, 0x60, 0x40, 0x88, 0x08, 0x60, 0x40, ++0x8C, 0x08, 0x60, 0x40, 0x34, 0x08, 0x00, 0x00, 0x18, 0x05, 0x62, 0x40, 0x0A, 0x88, 0x92, 0x36, 0x14, 0x05, 0x62, 0x40, ++0x10, 0x1A, 0x0C, 0xA8, 0x2C, 0x05, 0x62, 0x40, 0x03, 0x14, 0x0C, 0x9C, 0x0C, 0x05, 0x62, 0x40, 0x13, 0x20, 0x20, 0x20, ++0xA0, 0x05, 0x62, 0x40, 0x00, 0x0C, 0x15, 0x14, 0xA4, 0x05, 0x62, 0x40, 0x24, 0x36, 0x2D, 0x36, 0xF0, 0x05, 0x62, 0x40, ++0x08, 0x05, 0x62, 0x40, 0x32, 0x31, 0x55, 0x54, 0x30, 0x05, 0x62, 0x40, 0x00, 0x12, 0x17, 0x13, 0x34, 0x05, 0x62, 0x40, ++0xB0, 0x05, 0x62, 0x40, 0x55, 0x53, 0x00, 0x00, 0x1C, 0x05, 0x62, 0x40, 0x66, 0x57, 0x4B, 0x96, 0x2A, 0x49, 0x0B, 0x68, ++0x2A, 0x4A, 0x1A, 0x40, 0xFC, 0x23, 0x9B, 0x05, 0x13, 0x43, 0x0B, 0x60, 0x28, 0x4B, 0x29, 0x4A, 0x1A, 0x60, 0x29, 0x4B, ++0x29, 0x4A, 0x1A, 0x60, 0x29, 0x4B, 0x2A, 0x4A, 0x1A, 0x60, 0x2A, 0x4B, 0x2A, 0x4A, 0x1A, 0x60, 0x2A, 0x4B, 0x2B, 0x4A, ++0x1A, 0x60, 0x2B, 0x4B, 0x2B, 0x4A, 0x1A, 0x60, 0x2B, 0x4B, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x2C, 0x49, 0x11, 0x60, ++0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4B, 0x2D, 0x4A, 0x1A, 0x60, 0x2D, 0x4B, ++0x2D, 0x4A, 0x1A, 0x60, 0x2D, 0x4B, 0x2E, 0x4A, 0x1A, 0x60, 0x2E, 0x4B, 0x2E, 0x4A, 0x1A, 0x60, 0x2E, 0x4B, 0x2F, 0x4A, ++0x1A, 0x60, 0x2F, 0x4B, 0x2F, 0x4A, 0x1A, 0x60, 0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x30, 0x4A, 0x1A, 0x60, ++0x30, 0x4B, 0xFF, 0x22, 0x12, 0x02, 0x1A, 0x60, 0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x76, 0x22, 0x1A, 0x60, ++0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x31, 0x4A, 0x1A, 0x60, 0x31, 0x4B, ++0x31, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x0C, 0x00, 0x58, 0x40, 0xFF, 0xFF, 0xFF, 0xC0, 0x04, 0x01, 0x58, 0x40, ++0xFB, 0x33, 0x09, 0x00, 0x20, 0x40, 0x34, 0x40, 0x77, 0x0B, 0x00, 0x00, 0x24, 0x40, 0x34, 0x40, 0x94, 0xC5, 0x6E, 0x00, ++0x28, 0x40, 0x34, 0x40, 0x02, 0x94, 0x00, 0x00, 0x2C, 0x40, 0x34, 0x40, 0x84, 0x18, 0x20, 0x56, 0x30, 0x40, 0x34, 0x40, ++0x68, 0x51, 0x2E, 0x1A, 0x34, 0x08, 0x50, 0x00, 0x8C, 0x04, 0x60, 0x40, 0x10, 0x01, 0x60, 0x40, 0x58, 0x00, 0x7E, 0x02, ++0x80, 0x08, 0x60, 0x40, 0x84, 0x08, 0x60, 0x40, 0x88, 0x08, 0x60, 0x40, 0x8C, 0x08, 0x60, 0x40, 0x34, 0x08, 0x00, 0x00, ++0x18, 0x05, 0x62, 0x40, 0x0A, 0x88, 0x92, 0x36, 0x14, 0x05, 0x62, 0x40, 0x10, 0x1A, 0x0C, 0xA8, 0x2C, 0x05, 0x62, 0x40, ++0x03, 0x14, 0x0C, 0x9C, 0x0C, 0x05, 0x62, 0x40, 0x13, 0x20, 0x20, 0x20, 0x08, 0x05, 0x62, 0x40, 0x32, 0x31, 0x55, 0x54, ++0xA0, 0x05, 0x62, 0x40, 0x00, 0x16, 0x17, 0x0F, 0xA4, 0x05, 0x62, 0x40, 0x36, 0x36, 0x28, 0x36, 0xF0, 0x05, 0x62, 0x40, ++0x30, 0x05, 0x62, 0x40, 0x00, 0x1A, 0x17, 0x13, 0x34, 0x05, 0x62, 0x40, 0xB0, 0x05, 0x62, 0x40, 0x55, 0x53, 0x00, 0x00, ++0x1C, 0x05, 0x62, 0x40, 0x66, 0x57, 0x4B, 0x96, 0x90, 0x00, 0x62, 0x40, 0x32, 0x00, 0x05, 0x00, 0x10, 0x10, 0x62, 0x40, ++0x43, 0x01, 0x00, 0x12, 0x10, 0xB5, 0x01, 0x28, 0x03, 0xD0, 0x02, 0x38, 0x01, 0x28, 0x05, 0xD9, 0x10, 0xBD, 0x87, 0xF7, ++0x99, 0xFF, 0xFF, 0xF7, 0x2B, 0xFE, 0xF9, 0xE7, 0x88, 0xF7, 0x96, 0xF8, 0x0A, 0x4A, 0x11, 0x68, 0x80, 0x23, 0xDB, 0x05, ++0x0B, 0x43, 0x13, 0x60, 0xFF, 0xF7, 0x32, 0xFF, 0x07, 0x4B, 0x1B, 0x68, 0x9B, 0x02, 0xEB, 0xD4, 0x05, 0x49, 0x0B, 0x68, ++0x05, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0xE2, 0xE7, 0xC0, 0x46, 0x1C, 0x20, 0x34, 0x40, ++0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0x7F, 0xFF, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, ++0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x00, 0x24, 0x25, 0x4A, 0x26, 0x4B, 0x9B, 0x46, 0xE0, 0x23, 0xDB, 0x04, 0x9A, 0x46, ++0xC0, 0x23, 0x9B, 0x05, 0x99, 0x46, 0x23, 0x4B, 0x98, 0x46, 0x23, 0x4B, 0x00, 0x93, 0x23, 0x4F, 0x23, 0x4E, 0x13, 0x68, ++0x58, 0x46, 0x03, 0x40, 0x50, 0x46, 0x20, 0x40, 0x03, 0x43, 0x13, 0x60, 0x13, 0x68, 0x48, 0x46, 0x03, 0x43, 0x13, 0x60, ++0x43, 0x46, 0x1B, 0x68, 0x00, 0x98, 0x00, 0x68, 0x1B, 0x04, 0x3B, 0x40, 0x40, 0x04, 0x40, 0x0C, 0x03, 0x43, 0x08, 0xC5, ++0x13, 0x68, 0x33, 0x40, 0x13, 0x60, 0x80, 0x23, 0x5B, 0x04, 0x9C, 0x46, 0x64, 0x44, 0x80, 0x23, 0xDB, 0x04, 0x9C, 0x42, ++0xDF, 0xD1, 0x04, 0x20, 0x01, 0x9B, 0x01, 0x2B, 0x06, 0xD0, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, ++0xAB, 0x46, 0xF0, 0xBD, 0x0E, 0x4B, 0x1B, 0x68, 0x0B, 0x61, 0x0E, 0x4B, 0x1B, 0x68, 0x4B, 0x61, 0x0D, 0x4B, 0x1B, 0x68, ++0x8B, 0x61, 0x0D, 0x4B, 0x1B, 0x68, 0xCB, 0x61, 0x0C, 0x4B, 0x1B, 0x68, 0x0B, 0x62, 0x05, 0x30, 0xE7, 0xE7, 0xC0, 0x46, ++0x28, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0xFF, 0xF8, 0x8C, 0x08, 0x62, 0x40, 0x90, 0x08, 0x62, 0x40, 0x00, 0x00, 0xFF, 0x7F, ++0xFF, 0xFF, 0xFF, 0xCF, 0x30, 0x07, 0x62, 0x40, 0x34, 0x07, 0x62, 0x40, 0x5C, 0x07, 0x62, 0x40, 0x60, 0x07, 0x62, 0x40, ++0x20, 0x20, 0x62, 0x40, 0x12, 0x04, 0x12, 0x4B, 0x1A, 0x40, 0x49, 0x04, 0x49, 0x0C, 0x0A, 0x43, 0x10, 0x4B, 0x1A, 0x60, ++0x10, 0x4B, 0x1A, 0x68, 0x00, 0x06, 0xE0, 0x21, 0xC9, 0x04, 0x08, 0x40, 0x0E, 0x49, 0x0A, 0x40, 0x10, 0x43, 0x18, 0x60, ++0x19, 0x68, 0x80, 0x22, 0x12, 0x06, 0x0A, 0x43, 0x1A, 0x60, 0x19, 0x68, 0x80, 0x22, 0xD2, 0x05, 0x0A, 0x43, 0x1A, 0x60, ++0x1A, 0x68, 0x08, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x52, 0x00, 0x52, 0x08, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, ++0x00, 0x00, 0xFF, 0x7F, 0x44, 0x05, 0x62, 0x40, 0x28, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x1C, 0x49, 0x0B, 0x68, 0x99, 0x46, 0x1C, 0x4A, ++0x1A, 0x40, 0x1C, 0x4B, 0x13, 0x43, 0x0B, 0x60, 0x1B, 0x4B, 0x1B, 0x68, 0x98, 0x46, 0x1B, 0x4B, 0x1B, 0x68, 0x9A, 0x46, ++0x00, 0x24, 0xF0, 0x23, 0x47, 0x46, 0x9F, 0x43, 0x16, 0x4E, 0xE5, 0xB2, 0x00, 0x22, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, ++0xB1, 0xFF, 0x23, 0x01, 0x3B, 0x43, 0x33, 0x60, 0x88, 0xF7, 0x3D, 0xF9, 0x69, 0x46, 0x01, 0xA8, 0x88, 0xF7, 0x4A, 0xF9, ++0x00, 0x9A, 0x01, 0x99, 0x28, 0x00, 0xFF, 0xF7, 0xA3, 0xFF, 0x01, 0x34, 0x04, 0x2C, 0xE8, 0xD1, 0x07, 0x4B, 0x4A, 0x46, ++0x1A, 0x60, 0x09, 0x4B, 0x42, 0x46, 0x1A, 0x60, 0x08, 0x4B, 0x52, 0x46, 0x1A, 0x60, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x1C, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0x8F, 0x7F, 0x0A, 0x00, 0x20, 0x00, ++0x08, 0x05, 0x62, 0x40, 0x04, 0x00, 0x62, 0x40, 0x70, 0xB5, 0x0C, 0x4D, 0x2C, 0x68, 0x2A, 0x68, 0x0B, 0x4E, 0x32, 0x40, ++0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x2B, 0x60, 0x26, 0x20, 0x88, 0xF7, 0x3F, 0xFF, 0xFF, 0xF7, 0xA7, 0xFF, 0x88, 0xF7, ++0x81, 0xFF, 0x2B, 0x68, 0xE4, 0x05, 0xE4, 0x0F, 0x24, 0x02, 0x33, 0x40, 0x1C, 0x43, 0x2C, 0x60, 0x70, 0xBD, 0xC0, 0x46, ++0x00, 0x04, 0x60, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0x10, 0xB5, 0x26, 0x20, 0x88, 0xF7, 0x62, 0xF9, 0xFF, 0xF7, 0x92, 0xFF, ++0x88, 0xF7, 0xBA, 0xF9, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, ++0x8B, 0xB0, 0x82, 0x46, 0x0C, 0x00, 0x03, 0x68, 0x7F, 0x22, 0x1A, 0x40, 0x93, 0x46, 0x1E, 0x09, 0x0F, 0x25, 0x2E, 0x40, ++0x1D, 0x40, 0x01, 0x95, 0x0C, 0x22, 0x13, 0x42, 0x05, 0xD0, 0x35, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0x01, 0x9B, 0x9E, 0x42, 0x05, 0xD9, 0x30, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x2E, 0x4B, 0x98, 0x46, 0x1F, 0x68, 0x1A, 0x68, 0x2D, 0x4B, 0x99, 0x46, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, ++0x42, 0x46, 0x13, 0x60, 0x58, 0x46, 0x88, 0xF7, 0xF1, 0xFE, 0x53, 0x46, 0x19, 0x68, 0x03, 0xA8, 0x89, 0xF7, 0x0E, 0xF9, ++0x88, 0xF7, 0x30, 0xFF, 0x43, 0x46, 0x1B, 0x68, 0xFF, 0x05, 0xFF, 0x0F, 0x3F, 0x02, 0x4A, 0x46, 0x13, 0x40, 0x1F, 0x43, ++0x43, 0x46, 0x1F, 0x60, 0x01, 0x9B, 0x9E, 0x42, 0x30, 0xD8, 0x37, 0x00, 0x20, 0x36, 0x36, 0x01, 0x1D, 0x4B, 0xF6, 0x18, ++0x03, 0xA9, 0x1D, 0x4B, 0x98, 0x46, 0xF0, 0x23, 0x1B, 0x05, 0x9C, 0x46, 0x23, 0x1D, 0x99, 0x46, 0x05, 0xE0, 0x01, 0x37, ++0x10, 0x36, 0xFB, 0xB2, 0x01, 0x9A, 0x9A, 0x42, 0x1C, 0xD3, 0x7B, 0x18, 0x1A, 0x7D, 0x12, 0x02, 0xDB, 0x7B, 0x1A, 0x43, ++0x43, 0x46, 0x1A, 0x43, 0x32, 0x60, 0x7B, 0x5C, 0x18, 0x05, 0x65, 0x46, 0x28, 0x40, 0x1B, 0x07, 0x5B, 0x0F, 0x5B, 0x07, ++0x03, 0x43, 0x70, 0x68, 0x00, 0x02, 0x00, 0x0A, 0x03, 0x43, 0x73, 0x60, 0x00, 0x2C, 0xE2, 0xD0, 0xFB, 0x00, 0xE2, 0x50, ++0x4A, 0x46, 0x70, 0x68, 0xD0, 0x50, 0xDC, 0xE7, 0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0x00, 0x04, 0x60, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xD8, 0x99, 0x16, 0x00, ++0x00, 0x00, 0x80, 0x80, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x05, 0x00, ++0x01, 0x91, 0x03, 0x68, 0x5A, 0x02, 0x52, 0x0E, 0x90, 0x46, 0x1C, 0x09, 0x0F, 0x26, 0x34, 0x40, 0x1E, 0x40, 0x0C, 0x22, ++0x13, 0x42, 0x05, 0xD0, 0x38, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xB4, 0x42, 0x2F, 0xD9, ++0x34, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x40, 0x46, 0x88, 0xF7, 0xAD, 0xF8, 0x29, 0x68, ++0x02, 0xA8, 0x88, 0xF7, 0x09, 0xFB, 0x88, 0xF7, 0x03, 0xF9, 0x80, 0x22, 0x52, 0x00, 0x2D, 0x49, 0x2D, 0x48, 0xD7, 0xF7, ++0x49, 0xFE, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x01, 0x35, 0xEB, 0xB2, ++0x9E, 0x42, 0xEE, 0xD3, 0x2B, 0x01, 0xA8, 0x00, 0x63, 0x44, 0x1A, 0x68, 0x22, 0x40, 0x02, 0xA9, 0x41, 0x58, 0x00, 0x91, ++0xC9, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x01, 0x9B, 0x00, 0x2B, 0xED, 0xD0, 0x1A, 0x50, 0xEB, 0xE7, 0x40, 0x46, 0x88, 0xF7, ++0x83, 0xF8, 0x29, 0x68, 0x02, 0xA8, 0x88, 0xF7, 0xDF, 0xFA, 0x25, 0x00, 0xA2, 0x00, 0x02, 0xAB, 0x9C, 0x46, 0x62, 0x44, ++0xFC, 0x23, 0x1B, 0x01, 0x98, 0x46, 0xF8, 0x23, 0x5B, 0x02, 0x9C, 0x46, 0x3F, 0x20, 0xF8, 0x23, 0x9B, 0x03, 0x9B, 0x46, ++0x13, 0x68, 0x1F, 0x0A, 0x41, 0x46, 0x0F, 0x40, 0xB9, 0x46, 0xD9, 0x00, 0x0F, 0x00, 0x61, 0x46, 0x0F, 0x40, 0xBA, 0x46, ++0x4F, 0x46, 0x51, 0x46, 0x0F, 0x43, 0xB9, 0x46, 0x19, 0x0D, 0x0F, 0x00, 0x07, 0x40, 0xBA, 0x46, 0x4F, 0x46, 0x51, 0x46, ++0x0F, 0x43, 0x5B, 0x03, 0x59, 0x46, 0x0B, 0x40, 0x3B, 0x43, 0x08, 0xC2, 0x01, 0x34, 0xE4, 0xB2, 0xA6, 0x42, 0xE1, 0xD2, ++0x88, 0xF7, 0xAC, 0xF8, 0x02, 0x4B, 0x9C, 0x46, 0x03, 0x4C, 0xB5, 0xE7, 0x28, 0x19, 0x16, 0x00, 0xD8, 0x97, 0x16, 0x00, ++0x00, 0x50, 0x1E, 0x00, 0x7F, 0x00, 0x00, 0xE0, 0x70, 0xB5, 0x8E, 0xB0, 0x87, 0xF7, 0x76, 0xFF, 0x04, 0x00, 0x01, 0x28, ++0x05, 0xD0, 0x83, 0x1E, 0xDB, 0xB2, 0x01, 0x2B, 0x24, 0xD9, 0x0E, 0xB0, 0x70, 0xBD, 0x1C, 0x4B, 0x00, 0x93, 0x1C, 0x4C, ++0x25, 0x68, 0xF0, 0x23, 0x2A, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x70, 0x22, 0x13, 0x43, 0x23, 0x60, 0x01, 0xA9, 0x68, 0x46, ++0xFF, 0xF7, 0x56, 0xFF, 0x25, 0x60, 0x16, 0x4B, 0x00, 0x93, 0x00, 0x21, 0x68, 0x46, 0x88, 0xF7, 0xE9, 0xFC, 0x00, 0x20, ++0x88, 0xF7, 0xD0, 0xFB, 0x05, 0xA9, 0x01, 0x20, 0xFF, 0xF7, 0xB0, 0xFD, 0x01, 0x20, 0x89, 0xF7, 0x43, 0xFA, 0xFF, 0xF7, ++0xAF, 0xFE, 0xDA, 0xE7, 0x0A, 0x4B, 0x00, 0x93, 0x0A, 0x4D, 0x2E, 0x68, 0xF0, 0x23, 0x32, 0x00, 0x9A, 0x43, 0x13, 0x00, ++0x70, 0x22, 0x13, 0x43, 0x2B, 0x60, 0x01, 0xA9, 0x68, 0x46, 0xFF, 0xF7, 0xA9, 0xFE, 0x2E, 0x60, 0x20, 0x00, 0x89, 0xF7, ++0x2D, 0xFA, 0xFF, 0xF7, 0x7B, 0xFE, 0xC4, 0xE7, 0x03, 0x42, 0x26, 0x00, 0x08, 0x05, 0x62, 0x40, 0x0F, 0x30, 0x02, 0x00, ++0x30, 0xB5, 0x83, 0xB0, 0x41, 0x4B, 0x18, 0x78, 0x87, 0xF7, 0x12, 0xFF, 0x40, 0x4A, 0x80, 0x23, 0x5B, 0x00, 0x06, 0x21, ++0xD1, 0x50, 0x3F, 0x4B, 0x5A, 0x68, 0x3F, 0x49, 0x0A, 0x40, 0x5A, 0x60, 0x59, 0x68, 0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, ++0x5A, 0x60, 0x19, 0x00, 0x44, 0x22, 0x0B, 0x6B, 0x13, 0x40, 0x04, 0x2B, 0xFB, 0xD1, 0x39, 0x4B, 0x18, 0x68, 0x39, 0x49, ++0xD7, 0xF7, 0x32, 0xF9, 0xA0, 0x23, 0x5B, 0x03, 0x03, 0x43, 0x37, 0x4A, 0x13, 0x60, 0x37, 0x49, 0x08, 0x43, 0x10, 0x60, ++0x13, 0x60, 0x30, 0x4B, 0x59, 0x68, 0x35, 0x4A, 0x0A, 0x43, 0x5A, 0x60, 0x2C, 0x49, 0x9A, 0x22, 0x52, 0x00, 0x80, 0x20, ++0x40, 0x01, 0x88, 0x50, 0x1A, 0x68, 0x40, 0x20, 0x02, 0x43, 0x1A, 0x60, 0x18, 0x68, 0x02, 0x24, 0x20, 0x43, 0x18, 0x60, ++0x48, 0x6F, 0x01, 0x22, 0x10, 0x43, 0x48, 0x67, 0x59, 0x6D, 0x2B, 0x4A, 0x11, 0x40, 0x59, 0x65, 0x5A, 0x6D, 0x22, 0x43, ++0x5A, 0x65, 0x5A, 0x6D, 0x28, 0x49, 0x0A, 0x40, 0x5A, 0x65, 0x87, 0xF7, 0xE1, 0xFE, 0x04, 0x00, 0x80, 0x22, 0x52, 0x00, ++0x25, 0x49, 0x26, 0x48, 0xD7, 0xF7, 0x4C, 0xFD, 0x80, 0x22, 0x25, 0x49, 0x25, 0x48, 0xD7, 0xF7, 0x47, 0xFD, 0x01, 0x2C, ++0x05, 0xD1, 0x17, 0x4B, 0xDB, 0x6D, 0x9B, 0x07, 0x0D, 0xD5, 0x03, 0xB0, 0x30, 0xBD, 0xC0, 0x22, 0x92, 0x00, 0x20, 0x49, ++0x20, 0x48, 0xD7, 0xF7, 0x39, 0xFD, 0x80, 0x22, 0x1F, 0x49, 0x20, 0x48, 0xD7, 0xF7, 0x34, 0xFD, 0xED, 0xE7, 0x20, 0x00, ++0x87, 0xF7, 0xD2, 0xFE, 0x20, 0x00, 0xFF, 0xF7, 0xF1, 0xFC, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0xFF, 0xF7, 0x39, 0xFF, 0x05, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0xDF, 0xD1, 0x16, 0x4A, 0x13, 0x68, 0x01, 0x21, ++0x8B, 0x43, 0x13, 0x60, 0xD9, 0xE7, 0xC0, 0x46, 0xB4, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, ++0xFF, 0xFF, 0xFB, 0xFF, 0xB0, 0x06, 0x16, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x08, 0x00, 0x58, 0x40, 0x00, 0x00, 0x14, 0x80, ++0x02, 0x88, 0x01, 0x00, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x58, 0xE0, 0x10, 0x00, 0xD8, 0x97, 0x16, 0x00, ++0x58, 0xE1, 0x10, 0x00, 0xD8, 0x98, 0x16, 0x00, 0x18, 0xE2, 0x10, 0x00, 0xD8, 0x99, 0x16, 0x00, 0x18, 0xE5, 0x10, 0x00, ++0x58, 0x99, 0x16, 0x00, 0x04, 0x30, 0x34, 0x40, 0x80, 0x00, 0x01, 0x4B, 0xC0, 0x58, 0x70, 0x47, 0x38, 0x27, 0x16, 0x00, ++0x80, 0x00, 0x01, 0x4B, 0xC0, 0x58, 0x70, 0x47, 0x54, 0x27, 0x16, 0x00, 0x80, 0x00, 0x01, 0x4B, 0x19, 0x50, 0x70, 0x47, ++0x54, 0x27, 0x16, 0x00, 0x03, 0x23, 0x03, 0x40, 0x8B, 0x42, 0x05, 0xD8, 0x03, 0x23, 0x98, 0x43, 0x40, 0x18, 0x00, 0x01, ++0x00, 0x09, 0x70, 0x47, 0x03, 0x30, 0x03, 0x23, 0x98, 0x43, 0x40, 0x18, 0xF7, 0xE7, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x05, 0x00, 0x0F, 0x00, 0x14, 0x00, 0x06, 0xAB, 0x04, 0xCB, 0x90, 0x46, 0x1A, 0x78, 0x1B, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x01, 0xD0, 0x00, 0x2A, 0x06, 0xD0, 0x18, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x00, 0x21, 0x99, 0x70, 0xD9, 0x70, ++0x5A, 0x70, 0xAB, 0x68, 0x2A, 0x69, 0x94, 0x46, 0x63, 0x44, 0x18, 0x00, 0x13, 0x49, 0xD7, 0xF7, 0x63, 0xF8, 0x06, 0x00, ++0x10, 0x4B, 0x5D, 0x60, 0x9F, 0x60, 0xDC, 0x60, 0x18, 0x61, 0x00, 0x2C, 0x05, 0xD1, 0x0F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0A, 0x4D, 0x21, 0x00, 0x38, 0x00, 0xD7, 0xF7, 0xD6, 0xF8, 0x29, 0x77, 0x43, 0x46, ++0x6B, 0x61, 0xA4, 0x1B, 0x62, 0x01, 0x12, 0x1B, 0x92, 0x00, 0x12, 0x19, 0x90, 0x00, 0x12, 0x18, 0x78, 0x3A, 0xAA, 0x61, ++0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x74, 0xE6, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x80, 0x46, 0x00, 0x91, 0x01, 0x92, 0x99, 0x46, ++0x40, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA3, 0x46, 0xF0, 0xBD, ++0x3C, 0x4B, 0x1E, 0x68, 0xB4, 0x68, 0x00, 0x2C, 0xF4, 0xD0, 0x00, 0x25, 0x1F, 0x23, 0x9B, 0x46, 0x01, 0x27, 0x03, 0xE0, ++0x3B, 0x00, 0x83, 0x40, 0x9C, 0x43, 0x0D, 0xD0, 0x20, 0x00, 0xD7, 0xF7, 0x8B, 0xF9, 0x5B, 0x46, 0x18, 0x1A, 0x43, 0x1C, ++0xDB, 0x00, 0xF3, 0x18, 0x5B, 0x68, 0x00, 0x2B, 0xF0, 0xD0, 0x01, 0x35, 0xED, 0xB2, 0xED, 0xE7, 0x01, 0x2D, 0xDB, 0xD1, ++0x2C, 0x4B, 0x5C, 0x68, 0xA3, 0x68, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1E, 0x00, 0x2B, 0x49, 0x18, 0x00, 0xD6, 0xF7, ++0xFD, 0xFF, 0x05, 0x00, 0x64, 0x68, 0x04, 0x19, 0x27, 0x49, 0x30, 0x00, 0xD7, 0xF7, 0x7C, 0xF8, 0x4B, 0x46, 0x9B, 0x68, ++0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x64, 0x18, 0x4B, 0x46, 0x99, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, ++0x03, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x54, 0xFF, 0x04, 0x00, 0x43, 0x46, 0x1B, 0x68, 0xE1, 0x1A, 0x0A, 0x01, 0x12, 0x09, ++0x80, 0x20, 0x00, 0x05, 0x82, 0x42, 0x11, 0xD8, 0x09, 0x01, 0x0F, 0xD0, 0x15, 0x4A, 0xD1, 0x68, 0xCB, 0x18, 0xE2, 0x1A, ++0x12, 0x01, 0x12, 0x09, 0x82, 0x42, 0x07, 0xD8, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x1A, 0x1B, 0x01, 0x02, 0xD0, 0x64, 0x1A, ++0x24, 0x01, 0x24, 0x09, 0x43, 0x46, 0x1C, 0x60, 0x0C, 0x4B, 0xDA, 0x68, 0x55, 0x1B, 0x68, 0x01, 0x40, 0x1B, 0x80, 0x00, ++0x40, 0x19, 0x82, 0x00, 0x80, 0x18, 0x0B, 0x4A, 0x94, 0x46, 0x60, 0x44, 0x00, 0x9A, 0x10, 0x60, 0xD8, 0x68, 0x60, 0x28, ++0x02, 0xD8, 0x01, 0x9B, 0x18, 0x60, 0x87, 0xE7, 0x24, 0x21, 0xD6, 0xF7, 0xB1, 0xFF, 0x01, 0x9B, 0x18, 0x60, 0x81, 0xE7, ++0x74, 0xE6, 0x10, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x1E, 0xFB, 0xFF, 0xFF, 0x03, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x02, 0xD0, 0x01, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x70, 0x47, 0x74, 0xE6, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x06, 0x00, 0x01, 0x92, 0x38, 0x4B, 0x38, 0x4A, 0x13, 0x60, ++0x9C, 0x68, 0x00, 0x2C, 0x08, 0xD0, 0x43, 0x68, 0x9B, 0x46, 0x36, 0x4B, 0x99, 0x46, 0x36, 0x4B, 0x98, 0x46, 0x33, 0x4B, ++0x9A, 0x46, 0x0F, 0xE0, 0xD5, 0xF7, 0x8C, 0xF9, 0x04, 0x1E, 0x5B, 0xD0, 0x73, 0x68, 0x9B, 0x46, 0xF1, 0xE7, 0x75, 0x60, ++0x53, 0x46, 0x1B, 0x68, 0x9B, 0x68, 0xA3, 0x42, 0x46, 0xD0, 0x24, 0x68, 0x00, 0x2C, 0x47, 0xD0, 0x21, 0x00, 0x30, 0x00, ++0xC8, 0x47, 0x00, 0x28, 0x43, 0xD0, 0x05, 0x28, 0xF0, 0xD0, 0xA3, 0x68, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x00, ++0x41, 0x46, 0x18, 0x00, 0xD6, 0xF7, 0x64, 0xFF, 0x63, 0x68, 0xC5, 0x18, 0x41, 0x46, 0x38, 0x00, 0xD6, 0xF7, 0xE4, 0xFF, ++0xB3, 0x68, 0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x6D, 0x18, 0xB1, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, ++0x03, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0xBE, 0xFE, 0x05, 0x00, 0x5B, 0x46, 0xEB, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x22, ++0x12, 0x05, 0x93, 0x42, 0x04, 0xD9, 0x5B, 0x46, 0x5B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0x01, 0x9A, 0x93, 0x42, ++0xC1, 0xD9, 0x63, 0x7E, 0x0B, 0x2B, 0x03, 0xD8, 0x10, 0x4A, 0xDA, 0x40, 0xD3, 0x07, 0xBA, 0xD4, 0xA3, 0x7D, 0xB2, 0x7D, ++0x01, 0x20, 0x9A, 0x42, 0x07, 0xD8, 0x01, 0x33, 0xB3, 0x75, 0x04, 0xE0, 0xD5, 0xF7, 0x38, 0xF9, 0x04, 0x00, 0xB5, 0xE7, ++0x00, 0x20, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x00, 0x20, 0xF6, 0xE7, ++0x64, 0x2A, 0x16, 0x00, 0x10, 0xE7, 0x10, 0x00, 0x51, 0x62, 0x0D, 0x00, 0x71, 0x02, 0x00, 0x00, 0x6A, 0x0C, 0x00, 0x00, ++0x01, 0x4B, 0x18, 0x68, 0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x1B, 0x68, 0x01, 0x20, 0x18, 0x40, ++0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0x80, 0x07, 0xC0, 0x0F, 0x70, 0x47, 0xC0, 0x46, ++0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0xC0, 0x07, 0x70, 0x47, 0xC0, 0x46, 0x48, 0x30, 0x34, 0x40, ++0x01, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0x70, 0x47, 0x48, 0x30, 0x34, 0x40, 0x02, 0x4B, 0x18, 0x68, 0x40, 0x07, 0xC0, 0x0F, ++0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x03, 0x4B, 0x1B, 0x68, 0x14, 0x20, 0x18, 0x40, 0x43, 0x1E, 0x98, 0x41, ++0xC0, 0xB2, 0x70, 0x47, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0x06, 0xC0, 0x0F, 0x70, 0x47, 0xC0, 0x46, ++0x94, 0x40, 0x04, 0x40, 0x01, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0x70, 0x47, 0x98, 0x40, 0x04, 0x40, 0x10, 0xB5, 0x10, 0x4B, ++0x1A, 0x68, 0x00, 0x23, 0x01, 0x2A, 0x02, 0xD9, 0x01, 0x20, 0x18, 0x40, 0x10, 0xBD, 0xFF, 0xF7, 0xCF, 0xFF, 0x00, 0x23, ++0x00, 0x28, 0xF7, 0xD0, 0xFF, 0xF7, 0xE2, 0xFF, 0x00, 0x28, 0x03, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x05, 0xDA, ++0xFF, 0xF7, 0xB2, 0xFF, 0x01, 0x23, 0x43, 0x40, 0xDB, 0xB2, 0xE9, 0xE7, 0xFF, 0xF7, 0xC2, 0xFF, 0x00, 0x23, 0x00, 0x28, ++0xE4, 0xD0, 0xF3, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0x98, 0x40, 0x04, 0x40, 0x10, 0xB5, 0xFF, 0xF7, 0xB7, 0xFF, 0x00, 0x23, ++0x00, 0x28, 0x02, 0xD1, 0x01, 0x20, 0x18, 0x40, 0x10, 0xBD, 0xFF, 0xF7, 0x99, 0xFF, 0x01, 0x23, 0x43, 0x40, 0xDB, 0xB2, ++0xF6, 0xE7, 0x00, 0x00, 0x05, 0x4B, 0x1B, 0x68, 0x00, 0x28, 0x04, 0xD0, 0x08, 0x22, 0x13, 0x43, 0x02, 0x4A, 0x13, 0x60, ++0x70, 0x47, 0x08, 0x22, 0x93, 0x43, 0xF9, 0xE7, 0x94, 0x40, 0x04, 0x40, 0x04, 0x4A, 0x13, 0x68, 0x40, 0x01, 0x04, 0x49, ++0x0B, 0x40, 0x04, 0x49, 0x08, 0x40, 0x18, 0x43, 0x10, 0x60, 0x70, 0x47, 0x94, 0x40, 0x04, 0x40, 0x1F, 0x00, 0xFE, 0xFF, ++0xE0, 0xFF, 0x01, 0x00, 0x03, 0x4B, 0x1B, 0x68, 0x00, 0x20, 0x01, 0x22, 0x9A, 0x42, 0x40, 0x41, 0xC0, 0xB2, 0x70, 0x47, ++0x50, 0xE0, 0x10, 0x00, 0x02, 0x4B, 0x18, 0x68, 0x43, 0x42, 0x58, 0x41, 0xC0, 0xB2, 0x70, 0x47, 0x50, 0xE0, 0x10, 0x00, ++0x70, 0xB5, 0x01, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x0F, 0xD0, 0x70, 0xBD, 0x0E, 0x4C, 0xEA, 0x25, 0x6D, 0x00, 0x02, 0x22, ++0x02, 0x21, 0x20, 0x00, 0x2B, 0x68, 0x98, 0x47, 0x80, 0x22, 0x2B, 0x68, 0x92, 0x01, 0x00, 0x21, 0x20, 0x00, 0x98, 0x47, ++0xEF, 0xE7, 0x80, 0x21, 0x89, 0x01, 0x06, 0x4C, 0xEA, 0x25, 0x6D, 0x00, 0x0A, 0x00, 0x20, 0x00, 0x2B, 0x68, 0x98, 0x47, ++0x2B, 0x68, 0x02, 0x22, 0x00, 0x21, 0x20, 0x00, 0x98, 0x47, 0xE0, 0xE7, 0x00, 0x10, 0x01, 0x50, 0x70, 0xB5, 0x05, 0x00, ++0x0C, 0x00, 0x39, 0x4B, 0x1B, 0x68, 0x01, 0x20, 0x00, 0x2B, 0x45, 0xD1, 0x00, 0x29, 0x43, 0xD0, 0x00, 0x2D, 0x1A, 0xD0, ++0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x16, 0x00, 0x1E, 0x40, 0x1A, 0x42, 0x4E, 0xD1, 0x72, 0xB6, 0x31, 0x4B, 0x1B, 0x68, ++0x00, 0x2B, 0x41, 0xD1, 0x00, 0x20, 0x00, 0x2E, 0x4A, 0xD1, 0x62, 0xB6, 0x27, 0xE0, 0x20, 0x00, 0xFF, 0xF7, 0xBA, 0xFF, ++0x2B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x28, 0x00, 0x00, 0x2E, 0x20, 0xD1, 0xF3, 0xE7, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, ++0x16, 0x00, 0x1E, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x24, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x1B, 0xD1, 0x01, 0x20, ++0x87, 0xF7, 0x51, 0xFC, 0x20, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x14, 0xD1, 0x01, 0x20, 0x87, 0xF7, 0x4A, 0xFC, 0x28, 0x00, ++0x00, 0x2E, 0x00, 0xD1, 0x62, 0xB6, 0x1C, 0x4A, 0x13, 0x68, 0x01, 0x33, 0x13, 0x60, 0x00, 0x28, 0x1E, 0xD0, 0x00, 0x23, ++0x19, 0x4A, 0x13, 0x60, 0x19, 0x4A, 0x13, 0x60, 0x16, 0x4A, 0x13, 0x60, 0x70, 0xBD, 0x20, 0x00, 0xFF, 0xF7, 0x88, 0xFF, ++0x12, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x01, 0x20, 0x87, 0xF7, 0x2F, 0xFC, 0x01, 0x20, 0xE3, 0xE7, 0x08, 0x00, 0xFF, 0xF7, ++0x7D, 0xFF, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x28, 0x00, 0xB8, 0xE7, 0x0A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xB6, 0xD1, ++0x09, 0x4B, 0x1B, 0x68, 0x00, 0x20, 0x05, 0x2B, 0xDB, 0xD8, 0x08, 0x4B, 0x1C, 0x60, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0x07, 0x48, 0x82, 0xF7, 0x2F, 0xFC, 0x00, 0x20, 0xD8, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0x5C, 0x40, 0x04, 0x40, ++0x54, 0xE6, 0x10, 0x00, 0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x2C, 0xCE, 0x10, 0x00, 0xF0, 0xB5, 0xCE, 0x46, ++0x00, 0xB5, 0x86, 0xB0, 0x2A, 0x4B, 0x1C, 0x68, 0x21, 0x00, 0x2A, 0x48, 0x82, 0xF7, 0x16, 0xFC, 0x03, 0xAA, 0x29, 0x4B, ++0x03, 0xCB, 0x03, 0xC2, 0x1B, 0x88, 0x13, 0x80, 0x00, 0x2C, 0x0D, 0xDB, 0x0A, 0x22, 0x03, 0xA9, 0x25, 0x48, 0xD7, 0xF7, ++0xFD, 0xF9, 0x0A, 0x22, 0x03, 0xA9, 0x24, 0x48, 0xD7, 0xF7, 0xF8, 0xF9, 0x06, 0xB0, 0x04, 0xBC, 0x91, 0x46, 0xF0, 0xBD, ++0xFF, 0x23, 0x1B, 0x04, 0x23, 0x40, 0x80, 0x22, 0x52, 0x02, 0x93, 0x42, 0x11, 0xD0, 0x24, 0x04, 0x24, 0x0C, 0x1D, 0x4B, ++0xE7, 0x18, 0x1D, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0xFB, 0x43, 0xDB, 0x17, 0x1F, 0x40, 0x4E, 0x2C, 0x00, 0xDD, 0x4E, 0x24, ++0x03, 0xAD, 0x00, 0x26, 0x00, 0x23, 0x01, 0x93, 0x1B, 0xE0, 0x24, 0x04, 0x24, 0x0C, 0x16, 0x4B, 0xE7, 0x18, 0x16, 0x4B, ++0x9C, 0x46, 0x64, 0x44, 0xEC, 0xE7, 0x8B, 0x40, 0x1A, 0x43, 0xD2, 0xB2, 0x01, 0x31, 0x08, 0x29, 0x07, 0xD0, 0x88, 0x19, ++0x01, 0x23, 0xB8, 0x42, 0xF5, 0xDB, 0xA0, 0x42, 0xF3, 0xDC, 0x01, 0x9B, 0xF1, 0xE7, 0x4B, 0x46, 0x1A, 0x70, 0x01, 0x35, ++0x08, 0x36, 0x50, 0x2E, 0xBC, 0xD0, 0xA9, 0x46, 0x00, 0x22, 0x00, 0x21, 0xED, 0xE7, 0xC0, 0x46, 0x98, 0x40, 0x04, 0x40, ++0x34, 0xCE, 0x10, 0x00, 0x48, 0xCE, 0x10, 0x00, 0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x94, 0xF6, 0xFF, 0xFF, ++0xA7, 0xF6, 0xFF, 0xFF, 0x8A, 0xF6, 0xFF, 0xFF, 0xB1, 0xF6, 0xFF, 0xFF, 0x10, 0xB5, 0x84, 0xB0, 0x98, 0x4B, 0x1C, 0x68, ++0x21, 0x00, 0x98, 0x48, 0x82, 0xF7, 0xAC, 0xFB, 0x01, 0xAA, 0x97, 0x4B, 0x03, 0xCB, 0x03, 0xC2, 0x1B, 0x88, 0x13, 0x80, ++0x00, 0x2C, 0x0B, 0xDB, 0x0A, 0x22, 0x01, 0xA9, 0x93, 0x48, 0xD7, 0xF7, 0x93, 0xF9, 0x0A, 0x22, 0x01, 0xA9, 0x92, 0x48, ++0xD7, 0xF7, 0x8E, 0xF9, 0x04, 0xB0, 0x10, 0xBD, 0xFF, 0x23, 0x1B, 0x04, 0x23, 0x40, 0x80, 0x22, 0x52, 0x02, 0x93, 0x42, ++0x00, 0xD1, 0x02, 0xE1, 0x24, 0x04, 0x24, 0x0C, 0x8B, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x3C, 0x2C, 0xE4, 0xD8, 0xA4, 0x00, ++0x89, 0x4B, 0x1B, 0x59, 0x9F, 0x46, 0x01, 0xAB, 0x00, 0x22, 0x1A, 0x70, 0x5A, 0x70, 0x9A, 0x70, 0xFC, 0x32, 0xDA, 0x70, ++0xD8, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, 0x1A, 0x70, 0x00, 0x22, 0x5A, 0x70, 0x9A, 0x70, 0xFC, 0x32, 0xDA, 0x70, ++0x14, 0x29, 0xCD, 0xD1, 0x00, 0x22, 0x1A, 0x70, 0xDA, 0x70, 0x1A, 0x71, 0xC8, 0xE7, 0x14, 0x21, 0xEE, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x03, 0x22, 0x5A, 0x70, 0x00, 0x22, 0x9A, 0x70, 0xC0, 0x32, 0xDA, 0x70, 0x14, 0x29, 0xBC, 0xD1, 0x00, 0x22, ++0x1A, 0x70, 0x5A, 0x70, 0xDA, 0x70, 0x1A, 0x71, 0xF0, 0x32, 0x5A, 0x71, 0xB4, 0xE7, 0x14, 0x21, 0xEC, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x00, 0x22, 0x9A, 0x70, 0xDA, 0x70, 0xF0, 0x32, 0x1A, 0x71, 0x14, 0x29, 0xA9, 0xD1, 0xED, 0x3A, 0x1A, 0x70, ++0x00, 0x22, 0x5A, 0x70, 0x1A, 0x71, 0x5A, 0x71, 0xA2, 0xE7, 0x14, 0x21, 0xEE, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, ++0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x1A, 0x71, 0xFC, 0x32, 0x5A, 0x71, 0x14, 0x29, 0x95, 0xD1, 0x00, 0x22, 0x5A, 0x70, ++0x9A, 0x70, 0x5A, 0x71, 0xF0, 0x32, 0x9A, 0x71, 0x8E, 0xE7, 0x14, 0x21, 0xEC, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x03, 0x22, ++0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0xC0, 0x32, 0x5A, 0x71, 0x14, 0x29, 0x00, 0xD0, 0x81, 0xE7, 0x81, 0x3A, 0x5A, 0x70, ++0x00, 0x22, 0x9A, 0x70, 0xDA, 0x70, 0x5A, 0x71, 0xFC, 0x32, 0x9A, 0x71, 0x78, 0xE7, 0x14, 0x21, 0xEA, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x3F, 0x22, 0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0x5A, 0x71, 0xFC, 0x32, 0x9A, 0x71, 0x14, 0x29, 0x00, 0xD0, ++0x6A, 0xE7, 0xF9, 0x3A, 0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x9A, 0x71, 0xC0, 0x32, 0xDA, 0x71, 0x62, 0xE7, 0x14, 0x21, ++0xEA, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x0F, 0x22, 0x1A, 0x71, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0x14, 0x29, 0x00, 0xD0, ++0x56, 0xE7, 0x3F, 0x32, 0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x1A, 0x71, 0xDA, 0x71, 0x4F, 0xE7, 0x14, 0x21, 0xED, 0xE7, ++0x0A, 0x21, 0x01, 0xAB, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0xF0, 0x32, 0xDA, 0x71, 0x14, 0x29, 0x00, 0xD0, 0x43, 0xE7, ++0xE1, 0x3A, 0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0xDA, 0x71, 0x1A, 0x72, 0x3C, 0xE7, 0x14, 0x21, 0xED, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x3F, 0x22, 0x5A, 0x71, 0x00, 0x22, 0x9A, 0x71, 0xDA, 0x71, 0xFC, 0x32, 0x1A, 0x72, 0x14, 0x29, 0x00, 0xD0, ++0x2E, 0xE7, 0xED, 0x3A, 0x1A, 0x71, 0x00, 0x22, 0x5A, 0x71, 0x1A, 0x72, 0x5A, 0x72, 0x27, 0xE7, 0x14, 0x21, 0xEB, 0xE7, ++0x0A, 0x21, 0x01, 0xAB, 0x03, 0x22, 0x9A, 0x71, 0x00, 0x22, 0xDA, 0x71, 0xC0, 0x32, 0x1A, 0x72, 0x14, 0x29, 0x00, 0xD0, ++0x1A, 0xE7, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0x1A, 0x72, 0x5A, 0x72, 0x14, 0xE7, 0x14, 0x21, 0xED, 0xE7, 0x0A, 0x21, ++0x01, 0xAB, 0x00, 0x22, 0xDA, 0x71, 0x1A, 0x72, 0xF0, 0x32, 0x5A, 0x72, 0x14, 0x29, 0x00, 0xD0, 0x08, 0xE7, 0x00, 0x22, ++0x9A, 0x71, 0x5A, 0x72, 0x04, 0xE7, 0x14, 0x21, 0xF0, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, 0xDA, 0x71, 0x00, 0x22, ++0x1A, 0x72, 0x5A, 0x72, 0x14, 0x29, 0x00, 0xD0, 0xF8, 0xE6, 0x0F, 0x32, 0x9A, 0x71, 0x00, 0x22, 0xDA, 0x71, 0xF3, 0xE6, ++0x14, 0x21, 0xEF, 0xE7, 0x01, 0xAB, 0x00, 0x22, 0x1A, 0x70, 0x5A, 0x70, 0x9A, 0x70, 0xDA, 0x70, 0xFC, 0x32, 0x1A, 0x71, ++0xE8, 0xE6, 0x24, 0x04, 0x24, 0x0C, 0x0A, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x3C, 0x2C, 0x00, 0xD9, 0xE0, 0xE6, 0xA4, 0x00, ++0x08, 0x4B, 0x1B, 0x59, 0x9F, 0x46, 0xC0, 0x46, 0x98, 0x40, 0x04, 0x40, 0x34, 0xCE, 0x10, 0x00, 0x48, 0xCE, 0x10, 0x00, ++0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x94, 0xF6, 0xFF, 0xFF, 0x54, 0xCE, 0x10, 0x00, 0x48, 0xCF, 0x10, 0x00, ++0x10, 0xB5, 0x08, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0x06, 0x4B, 0x1A, 0x6B, 0x06, 0x4B, 0x19, 0x68, ++0x01, 0x20, 0x81, 0x43, 0x19, 0x60, 0x19, 0x68, 0x04, 0x48, 0x82, 0xF7, 0x5F, 0xFA, 0xF2, 0xE7, 0xB4, 0xE5, 0x10, 0x00, ++0x00, 0x60, 0x50, 0x40, 0x04, 0x30, 0x34, 0x40, 0x3C, 0xD0, 0x10, 0x00, 0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x4C, 0x4B, ++0x1B, 0x68, 0x01, 0x2B, 0x02, 0xD0, 0x4B, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x4A, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, ++0x13, 0x60, 0xA9, 0xF7, 0x71, 0xFD, 0x48, 0x4B, 0x18, 0x60, 0x5C, 0x60, 0x0C, 0x2D, 0x38, 0xD8, 0xAD, 0x00, 0x46, 0x4B, ++0x5B, 0x59, 0x9F, 0x46, 0x80, 0x23, 0xDB, 0x01, 0x00, 0x21, 0x9C, 0x42, 0x1B, 0xD3, 0x43, 0x4A, 0x13, 0x68, 0x43, 0x49, ++0x19, 0x40, 0x80, 0x23, 0x9B, 0x02, 0x0B, 0x43, 0x13, 0x60, 0x11, 0x68, 0xE3, 0x08, 0xC0, 0x20, 0x40, 0x01, 0x03, 0x40, ++0x76, 0x20, 0x03, 0x43, 0x09, 0x0C, 0x09, 0x04, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x3B, 0x49, 0x19, 0x40, 0x80, 0x23, ++0x1B, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x80, 0x21, 0xC9, 0x01, 0x35, 0x4B, 0x1A, 0x68, 0x35, 0x48, 0x02, 0x40, 0x1A, 0x60, ++0x1A, 0x68, 0xA4, 0x04, 0xA4, 0x0C, 0x0C, 0x43, 0x12, 0x0C, 0x12, 0x04, 0x14, 0x43, 0x1C, 0x60, 0x1A, 0x68, 0x30, 0x49, ++0x11, 0x40, 0x80, 0x22, 0x12, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x70, 0xBD, 0x2D, 0x4B, 0x1B, 0x68, 0x9A, 0x6A, 0x5B, 0x6B, ++0xD2, 0x1A, 0xD5, 0x00, 0x55, 0x19, 0x6D, 0x00, 0x55, 0x19, 0xAD, 0xB2, 0x2A, 0x00, 0x21, 0x00, 0x28, 0x48, 0x82, 0xF7, ++0xF7, 0xF9, 0x23, 0x4B, 0x19, 0x68, 0x23, 0x4E, 0x31, 0x40, 0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, ++0x12, 0x0C, 0x12, 0x04, 0x6D, 0x05, 0x6D, 0x0D, 0x2A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x1D, 0x48, 0x02, 0x40, 0x80, 0x21, ++0x09, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x16, 0x40, 0x1E, 0x60, 0x1A, 0x68, 0xA4, 0x04, 0xA4, 0x0C, 0x80, 0x25, ++0x2D, 0x02, 0x2C, 0x43, 0x12, 0x0C, 0x12, 0x04, 0x14, 0x43, 0x1C, 0x60, 0x1A, 0x68, 0x10, 0x40, 0x01, 0x43, 0x19, 0x60, ++0xC7, 0xE7, 0x0F, 0x4A, 0x13, 0x68, 0x0F, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x10, 0x49, ++0x0C, 0x43, 0xA4, 0xB2, 0x1C, 0x43, 0x14, 0x60, 0x13, 0x68, 0x0A, 0x49, 0x19, 0x40, 0x80, 0x23, 0x1B, 0x03, 0x0B, 0x43, ++0x13, 0x60, 0xB2, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, 0xFC, 0x00, 0x60, 0x40, 0x6C, 0xE6, 0x10, 0x00, ++0x5C, 0xD0, 0x10, 0x00, 0xF8, 0x00, 0x60, 0x40, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xF8, 0xE6, 0x10, 0x00, ++0x50, 0xD0, 0x10, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, ++0x07, 0x00, 0xD4, 0xF7, 0x4B, 0xFD, 0x04, 0x00, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0x3B, 0x4A, 0x13, 0x70, 0x01, 0x21, ++0x01, 0x20, 0xFF, 0xF7, 0xEF, 0xFC, 0x80, 0x46, 0x38, 0x4B, 0x1E, 0x78, 0x02, 0x3E, 0x73, 0x1E, 0x9E, 0x41, 0x76, 0x42, ++0x19, 0x23, 0x1E, 0x40, 0x02, 0x36, 0x00, 0x2C, 0x21, 0xD0, 0x65, 0x68, 0xFB, 0x7D, 0x9A, 0x46, 0xA3, 0x68, 0x99, 0x46, ++0x69, 0x46, 0x01, 0xA8, 0xA9, 0xF7, 0xB0, 0xFC, 0x01, 0x9B, 0x53, 0x44, 0xEB, 0x1A, 0x1B, 0x01, 0x1A, 0x09, 0x5B, 0x00, ++0x9C, 0x1A, 0xA4, 0x00, 0xA4, 0x18, 0xA3, 0x00, 0xE4, 0x18, 0x4B, 0x46, 0x00, 0x9A, 0x9B, 0x1A, 0xE4, 0x18, 0xA4, 0x09, ++0xA6, 0x42, 0x00, 0xD8, 0xA4, 0x1B, 0x80, 0x23, 0x5B, 0x02, 0x9C, 0x42, 0x02, 0xD9, 0x24, 0x4C, 0x00, 0xE0, 0x23, 0x4C, ++0xFF, 0xF7, 0xFC, 0xFB, 0x05, 0x00, 0x43, 0x46, 0x00, 0x2B, 0x12, 0xD0, 0x20, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, ++0x1F, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x0F, 0xD0, 0x0A, 0x2C, 0x16, 0xD8, 0x4F, 0x23, 0x00, 0x22, 0xFA, 0x54, 0x02, 0xB0, ++0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0x01, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xA3, 0xFC, 0xE7, 0xE7, ++0x16, 0x4B, 0x80, 0x22, 0x12, 0x05, 0x1A, 0x60, 0x13, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0x00, 0x25, 0xE6, 0xE7, 0xFF, 0xF7, ++0x0B, 0xFC, 0x00, 0x28, 0xE4, 0xD0, 0xB2, 0xF7, 0xC9, 0xFD, 0x06, 0x23, 0x00, 0x28, 0x05, 0xD1, 0x4A, 0x33, 0xFB, 0x5C, ++0x01, 0x3B, 0x58, 0x42, 0x43, 0x41, 0x05, 0x33, 0x00, 0x2D, 0xD7, 0xD1, 0xCF, 0x2C, 0x01, 0xD8, 0x06, 0x2B, 0xD3, 0xD1, ++0x21, 0x00, 0x18, 0x00, 0xFF, 0xF7, 0xCC, 0xFE, 0xCE, 0xE7, 0xC0, 0x46, 0xB2, 0xE6, 0x10, 0x00, 0xB4, 0xE5, 0x10, 0x00, ++0xFF, 0xFF, 0x00, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x4E, 0x23, ++0x01, 0x22, 0xC2, 0x54, 0x2A, 0x4B, 0x1D, 0x68, 0x2A, 0x4B, 0x1C, 0x68, 0x2A, 0x4B, 0x19, 0x68, 0x2A, 0x4B, 0x1A, 0x68, ++0x2A, 0x4B, 0x00, 0x26, 0x1E, 0x70, 0x00, 0x23, 0x00, 0x2D, 0x05, 0xD0, 0x42, 0x33, 0xEB, 0x5C, 0x01, 0x3B, 0x5D, 0x42, ++0x6B, 0x41, 0xDB, 0xB2, 0x00, 0x2C, 0x03, 0xD0, 0x3A, 0x25, 0x64, 0x5D, 0x01, 0x2C, 0x23, 0xD0, 0x00, 0x24, 0x00, 0x29, ++0x04, 0xD0, 0x3E, 0x34, 0x0D, 0x5D, 0x00, 0x24, 0x01, 0x2D, 0x1D, 0xD0, 0x00, 0x2A, 0x03, 0xD0, 0x2F, 0x21, 0x51, 0x5C, ++0x01, 0x29, 0x1A, 0xD0, 0x00, 0x2B, 0x1D, 0xD0, 0x1A, 0x49, 0x0B, 0x68, 0x1A, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, ++0x13, 0x43, 0x0B, 0x60, 0x18, 0x4B, 0x19, 0x4A, 0x13, 0x60, 0x81, 0x22, 0x52, 0x00, 0x9B, 0x5C, 0x00, 0x2B, 0x18, 0xD0, ++0x4F, 0x23, 0x01, 0x22, 0xC2, 0x54, 0x70, 0xBD, 0x01, 0x23, 0xD9, 0xE7, 0x8C, 0x62, 0x01, 0x34, 0xDE, 0xE7, 0x00, 0x21, ++0x91, 0x62, 0x00, 0x2B, 0xE2, 0xD1, 0x01, 0xE0, 0x00, 0x2C, 0xE7, 0xD0, 0x0A, 0x49, 0x0B, 0x68, 0x0D, 0x4A, 0x1A, 0x40, ++0x80, 0x23, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0xDE, 0xE7, 0xFF, 0xF7, 0x17, 0xFF, 0xE6, 0xE7, 0x24, 0x27, 0x16, 0x00, ++0x18, 0x27, 0x16, 0x00, 0x28, 0x27, 0x16, 0x00, 0x20, 0x27, 0x16, 0x00, 0xB1, 0xE6, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, ++0xFF, 0xFF, 0xDF, 0xFF, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0xFF, 0xFF, 0x7F, 0xFF, 0x02, 0x4B, 0x1B, 0x68, ++0x04, 0x20, 0x18, 0x40, 0x70, 0x47, 0xC0, 0x46, 0x80, 0x40, 0x34, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x01, 0x00, 0x12, 0x48, ++0x82, 0xF7, 0x98, 0xF8, 0x00, 0x2C, 0x1E, 0xD0, 0x10, 0x4B, 0x1A, 0x68, 0x10, 0x48, 0x02, 0x40, 0xD0, 0x21, 0x89, 0x03, ++0x0A, 0x43, 0x1A, 0x60, 0x1C, 0x68, 0x04, 0x40, 0xA0, 0x22, 0x52, 0x03, 0x22, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x02, 0x40, ++0x11, 0x43, 0x19, 0x60, 0x09, 0x49, 0x04, 0x22, 0x0B, 0x68, 0x1A, 0x42, 0xFC, 0xD0, 0x05, 0x49, 0x0B, 0x68, 0x05, 0x4A, ++0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x10, 0xBD, 0x90, 0xD0, 0x10, 0x00, 0x58, 0x40, 0x34, 0x40, ++0xFF, 0xFF, 0xC1, 0xFF, 0x80, 0x40, 0x34, 0x40, 0xF8, 0xB5, 0x04, 0x00, 0x83, 0x7D, 0x02, 0x33, 0x83, 0x75, 0x03, 0x6C, ++0x03, 0x61, 0xB2, 0xF7, 0xF9, 0xFC, 0x00, 0x28, 0x24, 0xD1, 0x20, 0x4E, 0x4C, 0x25, 0x20, 0x4F, 0x20, 0x00, 0xD4, 0xF7, ++0x19, 0xFA, 0x00, 0x28, 0x33, 0xD0, 0x31, 0x00, 0x20, 0x69, 0xD6, 0xF7, 0xFD, 0xF9, 0x63, 0x68, 0x9C, 0x46, 0x60, 0x44, ++0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x63, 0x5B, 0x5B, 0x00, 0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, ++0xE3, 0x60, 0xA3, 0x7D, 0x14, 0x4A, 0x52, 0x78, 0x9B, 0x18, 0xA3, 0x75, 0x10, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0xBE, 0x42, ++0xDE, 0xD1, 0xF8, 0xBD, 0x63, 0x68, 0x18, 0x33, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x18, 0x26, 0x65, 0x68, 0x00, 0x22, ++0x21, 0x69, 0x20, 0x00, 0xFF, 0xF7, 0x3C, 0xFA, 0x63, 0x68, 0xAB, 0x42, 0xCB, 0xD0, 0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, ++0x65, 0x60, 0x18, 0x36, 0x90, 0x2E, 0xEF, 0xD1, 0xC3, 0xE7, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xE3, 0xE7, 0xC0, 0x46, ++0xE2, 0x04, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x10, 0xB5, 0xFF, 0xF7, 0xAB, 0xFF, 0x10, 0xBD, ++0xF8, 0xB5, 0x04, 0x00, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xF8, 0xBD, 0x00, 0x21, 0xD4, 0xF7, 0x6E, 0xFB, ++0xA9, 0xF7, 0x38, 0xFB, 0x23, 0x6C, 0x23, 0x61, 0x60, 0x60, 0x04, 0x26, 0x4C, 0x27, 0x10, 0x4D, 0x20, 0x00, 0xD4, 0xF7, ++0xBF, 0xF9, 0x00, 0x28, 0x15, 0xD0, 0x63, 0x68, 0x04, 0x33, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0xE3, 0x5B, 0x5B, 0x00, ++0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x60, 0xA3, 0x7D, 0x6A, 0x78, 0x9B, 0x18, 0xA3, 0x75, ++0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xE5, 0xD1, 0xD8, 0xE7, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xD4, 0xE7, 0xC0, 0x46, ++0x7C, 0x91, 0x0D, 0x00, 0x70, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x1C, 0xD1, ++0x72, 0xB6, 0x10, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x07, 0xD0, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x05, 0xD0, 0x01, 0x2B, ++0x0D, 0xD0, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, 0x70, 0xBD, 0x00, 0x21, 0xD4, 0xF7, 0x2A, 0xFB, 0x07, 0x4D, 0x28, 0x68, ++0x80, 0xF7, 0x38, 0xF8, 0x00, 0x23, 0x2B, 0x60, 0xF1, 0xE7, 0x4E, 0x23, 0x02, 0x22, 0xC2, 0x54, 0xED, 0xE7, 0x02, 0x4B, ++0x18, 0x68, 0x00, 0x28, 0xE3, 0xD1, 0xEB, 0xE7, 0xF8, 0xE6, 0x10, 0x00, 0xF8, 0xB5, 0x05, 0x00, 0x36, 0x4B, 0x1B, 0x68, ++0x0C, 0x20, 0x00, 0x2B, 0x00, 0xD0, 0xF8, 0xBD, 0x00, 0x21, 0x48, 0x30, 0x7F, 0xF7, 0x7A, 0xFF, 0x31, 0x4B, 0x18, 0x60, ++0x00, 0x28, 0x56, 0xD0, 0xA9, 0xF7, 0xD2, 0xFA, 0x06, 0x00, 0x00, 0x27, 0x2E, 0x4B, 0x1F, 0x60, 0x2E, 0x4B, 0x1F, 0x60, ++0x2B, 0x4B, 0x1C, 0x68, 0x54, 0x22, 0x00, 0x21, 0x20, 0x00, 0x7D, 0xF7, 0x19, 0xFF, 0x2B, 0x68, 0xA3, 0x62, 0x6A, 0x68, ++0x22, 0x63, 0xEA, 0x68, 0xE2, 0x63, 0x2A, 0x68, 0xE2, 0x62, 0xAA, 0x68, 0xA2, 0x63, 0x62, 0x63, 0x1B, 0x01, 0x4C, 0x22, ++0xA3, 0x52, 0x24, 0x4A, 0x22, 0x64, 0x24, 0x4B, 0x63, 0x62, 0x24, 0x4B, 0xE3, 0x61, 0x24, 0x4B, 0x23, 0x62, 0x03, 0x23, ++0x23, 0x76, 0x23, 0x4B, 0x9B, 0x78, 0x02, 0x33, 0xA3, 0x75, 0x22, 0x61, 0xE7, 0x75, 0x05, 0x23, 0x63, 0x76, 0xEF, 0xF3, ++0x10, 0x83, 0x01, 0x22, 0x15, 0x00, 0x1D, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x66, 0x60, 0x00, 0x23, 0xA3, 0x60, ++0x1A, 0x4B, 0xA3, 0x82, 0x4C, 0x23, 0xE0, 0x5A, 0x40, 0x00, 0x80, 0x19, 0x00, 0x01, 0x00, 0x09, 0xE0, 0x60, 0x20, 0x00, ++0xD4, 0xF7, 0x1E, 0xF9, 0x00, 0x28, 0x06, 0xD1, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x00, 0x2D, 0xA9, 0xD1, 0x62, 0xB6, ++0xA7, 0xE7, 0x11, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0C, 0x20, 0xF3, 0xE7, 0x0D, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0C, 0x20, 0x97, 0xE7, 0xC0, 0x46, 0xF8, 0xE6, 0x10, 0x00, ++0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0xE8, 0xFD, 0x00, 0x00, 0xB9, 0x21, 0x10, 0x00, 0xC9, 0x1F, 0x10, 0x00, ++0x05, 0x4B, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x00, 0xA0, 0xFF, 0xFF, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x06, 0x4B, ++0x18, 0x68, 0x00, 0x28, 0x03, 0xD0, 0x4F, 0x23, 0xC3, 0x5C, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0xFF, 0xF7, 0x84, 0xFD, ++0xFB, 0xE7, 0xC0, 0x46, 0xF8, 0xE6, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x85, 0xF7, 0x55, 0xFE, 0x4C, 0x4B, ++0x1B, 0x68, 0x01, 0x2B, 0x02, 0xD0, 0x4A, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x49, 0x4A, 0x48, 0x4B, 0x19, 0x68, 0x49, 0x4B, ++0xD1, 0x54, 0x00, 0x21, 0x42, 0x3B, 0xD1, 0x54, 0x0B, 0x23, 0x47, 0x48, 0x13, 0x54, 0x01, 0x30, 0x13, 0x54, 0x46, 0x4B, ++0x1B, 0x68, 0x1C, 0x0A, 0x50, 0x38, 0x14, 0x54, 0x44, 0x48, 0x13, 0x54, 0x44, 0x4B, 0x20, 0x20, 0xD0, 0x54, 0x44, 0x4B, ++0x10, 0x38, 0xD0, 0x54, 0x43, 0x4B, 0x19, 0x60, 0x00, 0x24, 0x00, 0x23, 0x98, 0x46, 0x00, 0x27, 0x01, 0x34, 0xE4, 0xB2, ++0x01, 0x2C, 0x0B, 0xD0, 0x02, 0x2C, 0x3E, 0xD0, 0x03, 0x2C, 0x4C, 0xD0, 0x3D, 0x4A, 0x13, 0x78, 0x20, 0x21, 0x8B, 0x43, ++0x13, 0x70, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0C, 0x20, 0xFE, 0xF7, 0xA7, 0xF9, 0x06, 0x00, 0x0D, 0x20, 0xFE, 0xF7, ++0xA3, 0xF9, 0x05, 0x04, 0x2D, 0x0C, 0x2A, 0x00, 0x31, 0x00, 0x35, 0x48, 0x81, 0xF7, 0xDA, 0xFE, 0x2B, 0x00, 0x33, 0x43, ++0xDE, 0xD0, 0x43, 0x46, 0x00, 0x2B, 0x41, 0xD0, 0x27, 0x4B, 0x2A, 0x0A, 0x1A, 0x70, 0x5D, 0x70, 0x32, 0x0E, 0x9A, 0x70, ++0x32, 0x0C, 0xDA, 0x70, 0x32, 0x0A, 0x1A, 0x71, 0x5E, 0x71, 0x00, 0x2F, 0x0A, 0xD0, 0x21, 0x4A, 0x11, 0x1D, 0x13, 0x78, ++0x01, 0x33, 0xDB, 0xB2, 0x13, 0x70, 0x00, 0x2B, 0x02, 0xD1, 0x01, 0x32, 0x8A, 0x42, 0xF6, 0xD1, 0x1B, 0x4C, 0x20, 0x68, ++0x61, 0x68, 0xA9, 0xF7, 0xD1, 0xFC, 0x20, 0x00, 0xB9, 0xF7, 0x0E, 0xFB, 0xC2, 0xE7, 0x07, 0x20, 0xFE, 0xF7, 0x72, 0xF9, ++0x06, 0x00, 0x08, 0x20, 0xFE, 0xF7, 0x6E, 0xF9, 0x05, 0x04, 0x2D, 0x0C, 0x2A, 0x00, 0x31, 0x00, 0x1B, 0x48, 0x81, 0xF7, ++0xA5, 0xFE, 0x01, 0x27, 0xC8, 0xE7, 0x1A, 0x4B, 0x1E, 0x88, 0x58, 0x88, 0x00, 0x04, 0x06, 0x43, 0x18, 0x4B, 0x1D, 0x88, ++0x5B, 0x88, 0x2A, 0x00, 0x31, 0x00, 0x17, 0x48, 0x81, 0xF7, 0x96, 0xFE, 0x01, 0x23, 0x98, 0x46, 0x00, 0x27, 0xB7, 0xE7, ++0x06, 0x4B, 0x2A, 0x0A, 0x5A, 0x71, 0x1D, 0x71, 0x32, 0x0E, 0xDA, 0x70, 0x32, 0x0C, 0x9A, 0x70, 0x32, 0x0A, 0x5A, 0x70, ++0x1E, 0x70, 0xBC, 0xE7, 0xA8, 0xE5, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x9A, 0x02, 0x00, 0x00, 0xA3, 0x02, 0x00, 0x00, ++0xB0, 0xE5, 0x10, 0x00, 0x55, 0x02, 0x00, 0x00, 0x56, 0x02, 0x00, 0x00, 0x57, 0x02, 0x00, 0x00, 0xF8, 0xE6, 0x10, 0x00, ++0xEC, 0xE1, 0x10, 0x00, 0xA0, 0xD0, 0x10, 0x00, 0xB0, 0xD0, 0x10, 0x00, 0x12, 0xC0, 0x1F, 0x08, 0x16, 0xC0, 0x1F, 0x08, ++0xC4, 0xD0, 0x10, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x05, 0x00, 0x14, 0x00, 0x00, 0x28, 0x14, 0xD1, 0x1F, 0x4B, 0x20, 0x48, ++0x1A, 0x5C, 0x04, 0x35, 0xAA, 0x43, 0x1A, 0x54, 0x02, 0x30, 0x1A, 0x5C, 0x3E, 0x35, 0xAA, 0x43, 0x1A, 0x54, 0x22, 0x00, ++0x00, 0x20, 0x8D, 0xF7, 0xF9, 0xFF, 0x1A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x0E, 0xD0, 0x09, 0xB0, 0x30, 0xBD, 0x8D, 0xF7, ++0xF1, 0xFF, 0x02, 0x2D, 0xF5, 0xD1, 0x23, 0x78, 0x0C, 0x22, 0x93, 0x43, 0x23, 0x70, 0x63, 0x78, 0x0B, 0x3A, 0x93, 0x43, ++0x63, 0x70, 0xEC, 0xE7, 0x11, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0xEC, 0xD8, 0x00, 0x23, 0x07, 0x93, 0x0F, 0x4B, 0x1B, 0x68, ++0x03, 0x93, 0x0F, 0x4B, 0x1B, 0x68, 0x01, 0x93, 0x04, 0x93, 0x0E, 0x4B, 0x18, 0x68, 0x0E, 0x49, 0xD5, 0xF7, 0xD4, 0xFF, ++0x05, 0x90, 0x0D, 0x4B, 0x18, 0x68, 0x0B, 0x49, 0xD5, 0xF7, 0xCE, 0xFF, 0x06, 0x90, 0x03, 0xA8, 0xFF, 0xF7, 0x6C, 0xFE, ++0xD3, 0xE7, 0xC0, 0x46, 0x7C, 0x1E, 0x16, 0x00, 0x9E, 0x02, 0x00, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, ++0x0C, 0xE2, 0x10, 0x00, 0x10, 0xE2, 0x10, 0x00, 0x04, 0xE2, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x08, 0xE2, 0x10, 0x00, ++0x80, 0x00, 0x08, 0x4B, 0xC3, 0x58, 0x88, 0x22, 0xFF, 0x32, 0x9A, 0x5C, 0x00, 0x20, 0x01, 0x2A, 0x00, 0xD0, 0x70, 0x47, ++0x8A, 0x22, 0xFF, 0x32, 0x98, 0x5C, 0x01, 0x38, 0x43, 0x42, 0x58, 0x41, 0xF7, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x00, 0x23, 0x00, 0x20, 0x06, 0x49, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, 0x06, 0xD0, 0x9A, 0x00, 0x52, 0x58, 0x00, 0x2A, ++0xF8, 0xD0, 0x01, 0x30, 0xC0, 0xB2, 0xF5, 0xE7, 0x70, 0x47, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x70, 0xB5, 0x82, 0xB0, ++0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x30, 0x4B, 0xD6, 0x58, 0x20, 0x00, 0x80, 0xF7, 0xB2, 0xF8, 0x03, 0x00, 0x02, 0x00, ++0x01, 0x28, 0x12, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x05, 0xD9, 0x19, 0x2B, 0x05, 0xD8, 0x15, 0x23, 0x93, 0x42, 0x40, 0x41, ++0x40, 0x00, 0x02, 0xB0, 0x70, 0xBD, 0x58, 0x3B, 0xDB, 0xB2, 0x01, 0x20, 0x98, 0x42, 0x80, 0x41, 0x40, 0x42, 0x40, 0x00, ++0xF5, 0xE7, 0x4C, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x3A, 0xD1, 0x4B, 0x33, 0xF3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x4B, 0x23, ++0x00, 0x22, 0xF2, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x16, 0xD1, 0x36, 0x33, 0xF2, 0x5C, 0x35, 0x3B, 0x13, 0x40, ++0x3E, 0x22, 0x13, 0x43, 0x6A, 0x46, 0x13, 0x71, 0x00, 0x23, 0x53, 0x71, 0xE8, 0xB2, 0x01, 0xA9, 0xA7, 0xF7, 0x98, 0xF9, ++0x14, 0x48, 0x81, 0xF7, 0xA9, 0xFD, 0x59, 0x21, 0x20, 0x00, 0x80, 0xF7, 0x17, 0xF8, 0x00, 0x20, 0xCF, 0xE7, 0x01, 0xA9, ++0x36, 0x23, 0xF2, 0x5C, 0x38, 0x3B, 0x13, 0x43, 0x0B, 0x70, 0x1F, 0x23, 0x4B, 0x70, 0x1E, 0x3B, 0x8B, 0x70, 0xE8, 0xB2, ++0xA7, 0xF7, 0x82, 0xF9, 0x0A, 0x48, 0x81, 0xF7, 0x93, 0xFD, 0x20, 0x00, 0x97, 0xF7, 0x72, 0xFD, 0x58, 0x21, 0x20, 0x00, ++0x7F, 0xF7, 0xFE, 0xFF, 0x00, 0x20, 0xB6, 0xE7, 0x05, 0x48, 0x81, 0xF7, 0x87, 0xFD, 0x00, 0x20, 0xB1, 0xE7, 0xC0, 0x46, ++0x64, 0xA2, 0x16, 0x00, 0xDC, 0xD0, 0x10, 0x00, 0xEC, 0xD0, 0x10, 0x00, 0xFC, 0xD0, 0x10, 0x00, 0xF0, 0xB5, 0x05, 0xAC, ++0x24, 0x78, 0x4E, 0x28, 0x3C, 0xD8, 0xFF, 0x2C, 0x08, 0xD0, 0x10, 0x2C, 0x0B, 0xD9, 0x18, 0x2C, 0x37, 0xD9, 0x20, 0x2C, ++0x38, 0xD9, 0x03, 0x26, 0x00, 0x25, 0x06, 0xE0, 0x32, 0x4C, 0x24, 0x18, 0xED, 0x34, 0x24, 0x78, 0xF1, 0xE7, 0x00, 0x26, ++0x03, 0x25, 0x00, 0x29, 0x36, 0xD0, 0x2E, 0x4F, 0x39, 0x18, 0x0E, 0x00, 0x4F, 0x36, 0x33, 0x70, 0x3E, 0x56, 0xF3, 0x18, ++0x5B, 0x10, 0x3B, 0x54, 0x0B, 0x00, 0xED, 0x33, 0x1C, 0x70, 0x0E, 0x00, 0x9E, 0x36, 0x33, 0x78, 0x1C, 0x19, 0x64, 0x10, ++0x34, 0x70, 0x8C, 0x31, 0xFF, 0x31, 0x00, 0x23, 0x0B, 0x70, 0x24, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x1B, 0x78, ++0xED, 0x18, 0x6D, 0xB2, 0x06, 0x2D, 0x10, 0xDC, 0x1F, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x1D, 0x70, 0x02, 0x30, ++0x80, 0x00, 0x1C, 0x4B, 0x18, 0x18, 0x42, 0x60, 0xF0, 0xBD, 0x01, 0x26, 0x02, 0x25, 0xD0, 0xE7, 0x02, 0x26, 0x01, 0x25, ++0xCD, 0xE7, 0x17, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x06, 0x21, 0x19, 0x70, 0xEC, 0xE7, 0x12, 0x4B, 0x1B, 0x18, ++0x8C, 0x33, 0xFF, 0x33, 0x1B, 0x78, 0x01, 0x2B, 0x14, 0xD0, 0x0F, 0x49, 0x09, 0x18, 0x8C, 0x31, 0xFF, 0x31, 0x01, 0x23, ++0x0B, 0x70, 0x0D, 0x49, 0x09, 0x18, 0x49, 0x31, 0xFF, 0x31, 0x0B, 0x78, 0x9B, 0x1B, 0x5B, 0xB2, 0x99, 0x1D, 0x08, 0xDB, ++0x08, 0x49, 0x09, 0x18, 0x49, 0x31, 0xFF, 0x31, 0x0B, 0x70, 0xD0, 0xE7, 0x02, 0x36, 0xF6, 0xB2, 0xE7, 0xE7, 0x04, 0x4B, ++0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0xFA, 0x21, 0x19, 0x70, 0xC6, 0xE7, 0x1C, 0xE7, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, ++0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0x4C, 0x00, 0x25, 0x00, 0x22, 0x01, 0x26, ++0xC1, 0x27, 0xFF, 0x00, 0x03, 0xE0, 0x01, 0x35, 0x09, 0x34, 0x07, 0x2D, 0x0E, 0xD0, 0x23, 0x78, 0x03, 0x2B, 0xF8, 0xD1, ++0x63, 0x78, 0x00, 0x2B, 0xF5, 0xD1, 0x29, 0x02, 0x31, 0x43, 0x89, 0xB2, 0x00, 0x22, 0x38, 0x00, 0x7F, 0xF7, 0x20, 0xFC, ++0x01, 0x22, 0xEC, 0xE7, 0x00, 0x2A, 0x0B, 0xD1, 0x7E, 0x4A, 0xD9, 0x23, 0x5B, 0x00, 0x00, 0x21, 0xD1, 0x54, 0x00, 0x20, ++0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, 0xA8, 0xF7, 0xFE, 0xFF, 0x82, 0x46, 0x8E, 0xF7, ++0x09, 0xF8, 0x80, 0x46, 0xA9, 0xF7, 0x18, 0xFB, 0x81, 0x46, 0x00, 0x24, 0x73, 0x4B, 0x9B, 0x46, 0x63, 0xE0, 0x8D, 0xF7, ++0xF3, 0xFF, 0x00, 0x28, 0x19, 0xD0, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, ++0xC8, 0x22, 0x92, 0x01, 0x93, 0x42, 0x3D, 0xD2, 0x4B, 0x46, 0x3D, 0x33, 0xFF, 0x33, 0x1B, 0x57, 0x01, 0x33, 0x2D, 0xDB, ++0xD4, 0x20, 0x40, 0x00, 0x66, 0x4B, 0x5B, 0x19, 0x01, 0x21, 0xB1, 0x40, 0x1A, 0x5C, 0x0A, 0x43, 0x1A, 0x54, 0x2A, 0x00, ++0x63, 0x32, 0xFF, 0x32, 0x5A, 0x44, 0x00, 0x21, 0x06, 0x20, 0x38, 0x40, 0x03, 0x27, 0x13, 0x78, 0x03, 0x41, 0x3B, 0x40, ++0x03, 0x2B, 0x27, 0xD0, 0x01, 0x31, 0x0A, 0x32, 0x07, 0x29, 0xF6, 0xD1, 0xB3, 0x1E, 0x01, 0x2B, 0x00, 0xD8, 0x98, 0xE0, ++0x73, 0x1F, 0x01, 0x2B, 0x00, 0xD8, 0x94, 0xE0, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0xFA, 0x22, 0x12, 0x02, 0x93, 0x42, 0x1E, 0xD9, 0x93, 0xE0, 0xD4, 0x21, 0x49, 0x00, 0x4F, 0x4B, 0x5D, 0x19, ++0x01, 0x22, 0xB2, 0x40, 0x6B, 0x5C, 0x93, 0x43, 0x6B, 0x54, 0x13, 0xE0, 0x4B, 0x46, 0x3D, 0x33, 0xFF, 0x33, 0x00, 0x22, ++0x1A, 0x55, 0xCA, 0xE7, 0xD4, 0x20, 0x40, 0x00, 0x47, 0x4B, 0x9C, 0x46, 0xAC, 0x44, 0x01, 0x22, 0xB2, 0x40, 0x63, 0x46, ++0x1B, 0x5C, 0x93, 0x43, 0x62, 0x46, 0x13, 0x54, 0x07, 0x29, 0xCD, 0xD0, 0x01, 0x34, 0x4F, 0x2C, 0x13, 0xD0, 0xE7, 0xB2, ++0x07, 0x26, 0x26, 0x40, 0x65, 0x05, 0x2D, 0x0E, 0x43, 0x46, 0x5B, 0x5D, 0x33, 0x41, 0xDB, 0x07, 0x91, 0xD4, 0xD4, 0x21, ++0x49, 0x00, 0x3A, 0x4B, 0x5D, 0x19, 0x01, 0x22, 0xB2, 0x40, 0x6B, 0x5C, 0x93, 0x43, 0x6B, 0x54, 0xE8, 0xE7, 0x37, 0x48, ++0x81, 0xF7, 0xB0, 0xFC, 0x13, 0x28, 0x41, 0xD8, 0x14, 0x23, 0x1B, 0x1A, 0xDB, 0xB2, 0x9B, 0x46, 0x14, 0x25, 0x2D, 0x1A, ++0x00, 0x23, 0x99, 0x46, 0x00, 0x24, 0x2F, 0x4E, 0x0E, 0xE0, 0x48, 0x46, 0x13, 0x28, 0x09, 0xD9, 0x2C, 0x48, 0x84, 0x46, ++0x62, 0x44, 0x01, 0x20, 0x98, 0x40, 0x01, 0x43, 0xD4, 0x23, 0x5B, 0x00, 0xD1, 0x54, 0x01, 0x34, 0xAC, 0x42, 0x27, 0xDA, ++0xD6, 0xF7, 0xDA, 0xFA, 0x7F, 0x23, 0x18, 0x40, 0x4E, 0x28, 0x00, 0xD9, 0x4F, 0x38, 0xC2, 0x08, 0xB1, 0x18, 0xD4, 0x23, ++0x5B, 0x00, 0xC9, 0x5C, 0xA2, 0x3B, 0xFF, 0x3B, 0x03, 0x40, 0x0F, 0x00, 0x1F, 0x41, 0xFF, 0x07, 0xEA, 0xD4, 0x47, 0x46, ++0xBF, 0x5C, 0x1F, 0x41, 0xFF, 0x07, 0xE5, 0xD5, 0x4F, 0x46, 0x01, 0x37, 0xFF, 0xB2, 0xB9, 0x46, 0x1A, 0x4F, 0xBC, 0x46, ++0x60, 0x44, 0x9E, 0x30, 0x00, 0x78, 0x18, 0x28, 0xD0, 0xD9, 0xCB, 0x45, 0xCB, 0xD8, 0x20, 0x28, 0xCC, 0xD9, 0xC8, 0xE7, ++0x13, 0x48, 0x81, 0xF7, 0x69, 0xFC, 0x01, 0x00, 0x13, 0x48, 0x81, 0xF7, 0x01, 0xFC, 0xC8, 0x22, 0x00, 0x21, 0x12, 0x48, ++0x7F, 0xF7, 0x38, 0xFA, 0x1F, 0xE7, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, ++0xFA, 0x22, 0xD2, 0x01, 0x93, 0x42, 0x89, 0xD9, 0xD4, 0x21, 0x49, 0x00, 0x05, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x01, 0x22, ++0xB2, 0x40, 0x6B, 0x5C, 0x13, 0x43, 0x6B, 0x54, 0x7E, 0xE7, 0xC0, 0x46, 0xA4, 0x9E, 0x16, 0x00, 0x68, 0x9E, 0x16, 0x00, ++0x10, 0xA0, 0x16, 0x00, 0x1C, 0xE7, 0x10, 0x00, 0x0C, 0xD1, 0x10, 0x00, 0x0A, 0x05, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x07, 0x00, 0x08, 0x00, 0x00, 0x91, 0xBA, 0x00, 0xA4, 0x4B, ++0xD5, 0x58, 0xA6, 0x23, 0xEB, 0x5C, 0x9B, 0x46, 0x2B, 0x6D, 0x98, 0x46, 0x62, 0x23, 0x7B, 0x43, 0xA0, 0x4A, 0x9A, 0x18, ++0x16, 0x88, 0xA0, 0x4A, 0x9A, 0x18, 0x14, 0x88, 0x36, 0x04, 0x26, 0x43, 0x9E, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x92, 0x05, ++0x92, 0x0D, 0x91, 0x46, 0x9C, 0x4A, 0x9A, 0x18, 0x14, 0x88, 0x9C, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x24, 0x04, ++0x1C, 0x19, 0x9A, 0x4B, 0x98, 0x45, 0x1A, 0xD8, 0x73, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x80, 0x22, 0x12, 0x05, 0x91, 0x42, ++0x4A, 0xD9, 0x83, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0x49, 0xD0, 0x00, 0x2B, ++0x09, 0xDB, 0x89, 0x08, 0x00, 0x29, 0x06, 0xDD, 0x89, 0x00, 0x00, 0x9B, 0x9C, 0x46, 0x61, 0x44, 0x09, 0x01, 0x0B, 0x09, ++0x00, 0x93, 0xA4, 0x1B, 0x00, 0x9B, 0x9C, 0x46, 0x64, 0x44, 0x24, 0x01, 0x24, 0x09, 0xF4, 0x26, 0x76, 0x00, 0x4B, 0x46, ++0xF6, 0x1A, 0x3B, 0xD4, 0xAC, 0x67, 0x82, 0x23, 0xEE, 0x52, 0x62, 0x42, 0x7F, 0x3B, 0x13, 0x40, 0xA6, 0x22, 0xAB, 0x54, ++0x72, 0x3A, 0x2A, 0x65, 0x01, 0x96, 0xAE, 0x60, 0x42, 0x46, 0x34, 0x2A, 0x09, 0xD9, 0xEA, 0x7D, 0x00, 0x2A, 0x06, 0xD0, ++0xC8, 0x22, 0x52, 0x00, 0xB2, 0x42, 0x92, 0x41, 0x52, 0x42, 0x05, 0x32, 0xEA, 0x75, 0x5B, 0x45, 0x00, 0xD1, 0x9F, 0xE0, ++0xA1, 0x23, 0xEB, 0x5C, 0x03, 0x2B, 0x21, 0xD0, 0x3B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x02, 0x93, 0x01, 0x23, 0x98, 0x46, ++0xFE, 0x33, 0x9A, 0x46, 0xA9, 0x46, 0x45, 0x46, 0xA0, 0x46, 0x4D, 0xE0, 0x1B, 0x01, 0x1B, 0x09, 0xA1, 0x22, 0xAA, 0x5C, ++0x00, 0x2A, 0xB8, 0xD0, 0xB5, 0xE7, 0x00, 0x2B, 0xB5, 0xDA, 0x6C, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0xB8, 0xE7, 0x69, 0x4E, 0xF6, 0x1A, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0xBD, 0xE7, 0xC1, 0x33, 0x99, 0x46, ++0xEB, 0x58, 0x6A, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x4A, 0x46, 0xAB, 0x50, 0x3B, 0x02, ++0x01, 0x21, 0x19, 0x43, 0x02, 0x23, 0x3B, 0x32, 0x5F, 0x48, 0x7F, 0xF7, 0x2B, 0xFA, 0x80, 0x46, 0x4B, 0x46, 0xEB, 0x58, ++0x5B, 0x08, 0x99, 0x46, 0xCC, 0x23, 0xEB, 0x5A, 0x9A, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x57, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x51, 0x46, 0x48, 0x46, 0xD5, 0xF7, 0x47, 0xFD, 0x43, 0x46, 0x19, 0x80, 0x40, 0x46, ++0x7F, 0xF7, 0x3C, 0xFA, 0xB0, 0xE7, 0x21, 0x00, 0x03, 0x98, 0xD5, 0xF7, 0x3D, 0xFD, 0x04, 0x9B, 0x59, 0x80, 0x18, 0x00, ++0x7F, 0xF7, 0x32, 0xFA, 0x01, 0x3D, 0x3F, 0xD3, 0x53, 0x46, 0x2B, 0x40, 0x9B, 0x00, 0x4B, 0x4A, 0x9C, 0x58, 0x00, 0x2C, ++0xF6, 0xD0, 0x46, 0x23, 0xE3, 0x5C, 0xBB, 0x42, 0xF2, 0xD1, 0x63, 0x6B, 0x42, 0x46, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, ++0x63, 0x63, 0x4A, 0x46, 0x52, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x63, 0x63, 0x68, 0x42, 0x46, ++0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x4A, 0x46, 0x52, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, ++0x63, 0x60, 0x01, 0x9B, 0xA3, 0x60, 0x04, 0x23, 0x52, 0x46, 0x02, 0x99, 0x38, 0x48, 0x7F, 0xF7, 0xD9, 0xF9, 0x04, 0x90, ++0x47, 0x23, 0xE3, 0x5C, 0x03, 0x70, 0x63, 0x6B, 0x5B, 0x08, 0x03, 0x93, 0x42, 0x23, 0xE4, 0x5C, 0x00, 0x2C, 0xBC, 0xD1, ++0x2D, 0x4B, 0x9B, 0x6E, 0x05, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xB4, 0xE7, 0x44, 0x46, 0x4D, 0x46, ++0x6C, 0x67, 0x84, 0x23, 0xEE, 0x52, 0x1D, 0x33, 0xEB, 0x5C, 0x04, 0x2B, 0x0D, 0xD0, 0xA6, 0x23, 0xE8, 0x5C, 0x5B, 0x46, ++0xC0, 0x1A, 0x43, 0x1E, 0x98, 0x41, 0xC0, 0xB2, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, ++0xF0, 0xBD, 0x7C, 0x33, 0xEB, 0x5A, 0x9E, 0x1B, 0xF3, 0x17, 0xF6, 0x18, 0x5E, 0x40, 0x33, 0xB2, 0x9D, 0x22, 0x52, 0x00, ++0x93, 0x42, 0x02, 0xDB, 0x1D, 0x4B, 0x9B, 0x1B, 0x1B, 0xB2, 0x03, 0x2B, 0xE1, 0xDD, 0xE8, 0x23, 0xEB, 0x58, 0x1A, 0x68, ++0x00, 0x9B, 0xA8, 0x6F, 0x84, 0x46, 0x63, 0x44, 0x19, 0x00, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x20, 0x00, 0x05, ++0x83, 0x42, 0xD2, 0xD8, 0x09, 0x01, 0x09, 0x09, 0x51, 0x1A, 0x09, 0x01, 0x09, 0x09, 0x64, 0x29, 0xCB, 0xDD, 0x3F, 0x02, ++0x01, 0x21, 0x39, 0x43, 0xFF, 0x22, 0x0F, 0x48, 0x7F, 0xF7, 0xC2, 0xF9, 0xC3, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, ++0x4C, 0x65, 0x61, 0x40, 0x4A, 0x65, 0x61, 0x40, 0x4E, 0x65, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, ++0xE1, 0x04, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0x59, 0x04, 0x00, 0x00, 0x33, 0x06, 0x00, 0x00, 0x54, 0x27, 0x16, 0x00, ++0x34, 0x06, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x2E, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x89, 0xB0, 0x03, 0x90, 0x89, 0x46, 0x81, 0x00, 0xC9, 0x4B, 0xCF, 0x58, 0x53, 0x1E, 0xDB, 0xB2, ++0x9B, 0x46, 0x00, 0x2A, 0x00, 0xD1, 0x26, 0xE1, 0x03, 0x02, 0x01, 0x22, 0x13, 0x43, 0x07, 0x93, 0xC4, 0x4B, 0x98, 0x46, ++0x9A, 0x46, 0x5C, 0x46, 0x83, 0xE0, 0x6B, 0x46, 0x10, 0x21, 0x5B, 0x5E, 0x00, 0x2B, 0x06, 0xDB, 0xA7, 0x21, 0x79, 0x5C, ++0x77, 0x29, 0x02, 0xD8, 0x01, 0x31, 0xA7, 0x20, 0x39, 0x54, 0xE9, 0x06, 0x00, 0xD5, 0xD7, 0xE0, 0xA4, 0x21, 0x29, 0x42, ++0x5B, 0xD1, 0x29, 0x07, 0x54, 0xD4, 0x00, 0x2B, 0x00, 0xDA, 0xCF, 0xE0, 0xA7, 0x23, 0xFB, 0x5C, 0x77, 0x2B, 0x02, 0xD8, ++0xA7, 0x23, 0x02, 0x21, 0xF9, 0x54, 0x0F, 0x23, 0x1A, 0x40, 0x03, 0x25, 0x05, 0x9B, 0x1D, 0x40, 0x03, 0x2A, 0x01, 0xD0, ++0x08, 0x2A, 0x02, 0xD1, 0x03, 0x2D, 0x00, 0xD1, 0xCE, 0xE0, 0xEC, 0x23, 0xFB, 0x58, 0x00, 0x2B, 0x00, 0xD0, 0xB7, 0xE0, ++0x6B, 0x1E, 0x01, 0x2B, 0x00, 0xD9, 0xB3, 0xE0, 0x05, 0x9B, 0xDE, 0x04, 0xB6, 0x0D, 0x00, 0xD1, 0xAE, 0xE0, 0x04, 0x23, ++0xFF, 0x22, 0x07, 0x99, 0xA5, 0x48, 0x7F, 0xF7, 0x0B, 0xF9, 0xA5, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, ++0x9B, 0x1A, 0x5B, 0x00, 0xA2, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x03, 0x80, 0x43, 0x88, 0x9B, 0x0A, 0x9B, 0x02, ++0x33, 0x43, 0x9F, 0x4E, 0x33, 0x40, 0x2D, 0x03, 0x1D, 0x43, 0xAA, 0x04, 0x92, 0x0C, 0x06, 0x9B, 0x59, 0x42, 0x4B, 0x41, ++0x9B, 0x03, 0x13, 0x43, 0x43, 0x80, 0x7F, 0xF7, 0x17, 0xF9, 0x96, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, ++0x9B, 0x1A, 0x5B, 0x00, 0x93, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x00, 0x22, 0x1A, 0x80, 0x7D, 0xE0, 0xFF, 0x22, 0x07, 0x99, ++0x91, 0x48, 0x7F, 0xF7, 0x1B, 0xF9, 0xA8, 0xF7, 0x3F, 0xFA, 0x90, 0x4B, 0x1D, 0x68, 0x58, 0x46, 0x43, 0x46, 0xDB, 0x69, ++0x98, 0x47, 0x03, 0x00, 0x2D, 0x0A, 0xED, 0xB2, 0x00, 0x95, 0x4A, 0x46, 0x00, 0x21, 0x02, 0x98, 0xFF, 0xF7, 0x52, 0xFC, ++0x01, 0x3C, 0xE4, 0xB2, 0xFF, 0x2C, 0x00, 0xD1, 0x99, 0xE0, 0x03, 0x98, 0xA8, 0xF7, 0x54, 0xFA, 0x00, 0x28, 0x00, 0xD1, ++0x93, 0xE0, 0xD5, 0x23, 0x5B, 0x00, 0x7E, 0x4A, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x80, 0x4A, 0x9A, 0x18, ++0x15, 0x88, 0xAD, 0xB2, 0x7F, 0x4A, 0x9A, 0x18, 0x16, 0x88, 0xB6, 0xB2, 0x7E, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x92, 0xB2, ++0x05, 0x92, 0x7D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9A, 0xB2, 0x04, 0x92, 0xDA, 0xB2, 0x93, 0x46, 0x5B, 0x04, ++0x5B, 0x0E, 0x02, 0x93, 0x4B, 0x46, 0xFA, 0x6E, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xC8, 0x2B, 0x0A, 0xD9, 0xA7, 0x23, ++0xFB, 0x5C, 0x77, 0x2B, 0x06, 0xD8, 0xA1, 0x22, 0xBA, 0x5C, 0x00, 0x2A, 0x02, 0xD1, 0x01, 0x33, 0xA7, 0x32, 0xBB, 0x54, ++0xEB, 0x07, 0xB0, 0xD4, 0x07, 0x23, 0x1A, 0x00, 0x32, 0x40, 0x06, 0x92, 0x4A, 0x46, 0xFA, 0x66, 0x33, 0x42, 0x0B, 0xD0, ++0x5F, 0x4B, 0xDB, 0x69, 0x58, 0x46, 0x98, 0x47, 0x98, 0x22, 0xBB, 0x5A, 0x1B, 0x18, 0xBB, 0x52, 0x02, 0x32, 0xBB, 0x5C, ++0x01, 0x33, 0xBB, 0x54, 0xAB, 0x07, 0x9A, 0xD4, 0x4B, 0x46, 0x3B, 0x67, 0x6B, 0x06, 0x02, 0xD5, 0x06, 0x9B, 0x00, 0x2B, ++0x0C, 0xD1, 0xF6, 0x10, 0xF2, 0xB2, 0x0E, 0x23, 0x1E, 0x42, 0x00, 0xD0, 0x1F, 0xE7, 0x99, 0x33, 0xFB, 0x5C, 0x00, 0x2B, ++0x02, 0xD0, 0x01, 0x3B, 0xA7, 0x22, 0xBB, 0x54, 0xA8, 0xF7, 0xC6, 0xF9, 0x53, 0x4B, 0x1D, 0x68, 0x58, 0x46, 0x53, 0x46, ++0xDB, 0x69, 0x98, 0x47, 0x03, 0x00, 0x2D, 0x0A, 0xED, 0xB2, 0x00, 0x95, 0x4A, 0x46, 0x01, 0x21, 0x02, 0x98, 0xFF, 0xF7, ++0xD9, 0xFB, 0x85, 0xE7, 0x47, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x4D, 0x4A, ++0x94, 0x46, 0x63, 0x44, 0x19, 0x88, 0x8B, 0xB2, 0x04, 0x93, 0x05, 0x9A, 0xD5, 0x04, 0xAD, 0x0D, 0x6B, 0x1C, 0xFF, 0x22, ++0x07, 0x99, 0x48, 0x48, 0x7F, 0xF7, 0x3A, 0xF8, 0x06, 0x00, 0x05, 0x70, 0x04, 0x9B, 0x46, 0x4A, 0x94, 0x46, 0x63, 0x44, ++0x19, 0x00, 0x01, 0x30, 0x2A, 0x00, 0xD5, 0xF7, 0x27, 0xFF, 0x30, 0x00, 0x7F, 0xF7, 0x56, 0xF8, 0xC8, 0xE7, 0x62, 0x24, ++0x03, 0x9B, 0x5C, 0x43, 0x3F, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x80, 0x22, 0x93, 0x43, 0x23, 0x80, 0x89, 0xF7, ++0x59, 0xF9, 0x00, 0x28, 0x18, 0xD0, 0x2F, 0x4B, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x13, 0xD1, 0x38, 0x4B, 0x1B, 0x88, ++0x9B, 0xB2, 0x00, 0x2B, 0x0E, 0xD1, 0x37, 0x4B, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x09, 0xD1, 0x35, 0x4B, 0x1B, 0x88, ++0x9B, 0xB2, 0x00, 0x2B, 0x04, 0xD1, 0x23, 0x88, 0x80, 0x22, 0x93, 0x43, 0x13, 0x43, 0x23, 0x80, 0x9A, 0x23, 0xFB, 0x5C, ++0x96, 0x2B, 0x03, 0xD9, 0xEC, 0x23, 0xFB, 0x58, 0x00, 0x2B, 0x06, 0xD0, 0x09, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xAC, 0x33, 0xFB, 0x5C, 0x00, 0x2B, 0xF4, 0xD0, 0x9B, 0x23, 0x00, 0x22, 0xFA, 0x54, ++0x26, 0x4A, 0x27, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0x03, 0xD5, 0x26, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x05, 0xD1, 0x00, 0x23, ++0x9A, 0x22, 0xBB, 0x54, 0x02, 0x3A, 0xBB, 0x52, 0xE2, 0xE7, 0x03, 0x9B, 0x19, 0x02, 0x01, 0x23, 0x19, 0x43, 0xFF, 0x22, ++0x1F, 0x48, 0x7F, 0xF7, 0x17, 0xF8, 0x98, 0x23, 0xF8, 0x5E, 0x9A, 0x23, 0xF9, 0x5C, 0xD5, 0xF7, 0x05, 0xFB, 0x06, 0x4A, ++0x2F, 0x23, 0xD3, 0x5C, 0xC0, 0x1A, 0x9B, 0x23, 0xF8, 0x54, 0x17, 0x4A, 0x13, 0x78, 0x01, 0x3B, 0x13, 0x70, 0xE0, 0xE7, ++0x38, 0x27, 0x16, 0x00, 0x60, 0x92, 0x16, 0x00, 0x29, 0x06, 0x00, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x9A, 0x69, 0x61, 0x40, ++0xFF, 0xCF, 0xFF, 0xFF, 0x2A, 0x06, 0x00, 0x00, 0x0C, 0x01, 0x60, 0x40, 0x92, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, ++0x96, 0x69, 0x61, 0x40, 0x98, 0x69, 0x61, 0x40, 0x9C, 0x69, 0x61, 0x40, 0x27, 0x06, 0x00, 0x00, 0x00, 0x00, 0x61, 0x40, ++0x0E, 0x65, 0x61, 0x40, 0xA8, 0x69, 0x61, 0x40, 0xB6, 0x69, 0x61, 0x40, 0xC4, 0x69, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, ++0x9D, 0x02, 0x00, 0x00, 0x24, 0xE6, 0x10, 0x00, 0x2F, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x04, 0x00, ++0x88, 0x46, 0x16, 0x00, 0xFF, 0xF7, 0x84, 0xFA, 0x00, 0x28, 0x3F, 0xD1, 0x22, 0x4D, 0x23, 0x4F, 0xEB, 0x5D, 0x04, 0x22, ++0x93, 0x43, 0xEB, 0x55, 0x32, 0x00, 0x41, 0x46, 0x20, 0x00, 0xFF, 0xF7, 0x1F, 0xFE, 0xEB, 0x5D, 0x04, 0x22, 0x13, 0x43, ++0xEB, 0x55, 0xA4, 0x00, 0x1C, 0x4B, 0xE4, 0x58, 0xA7, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x02, 0xD9, 0xA7, 0x23, 0x04, 0x22, ++0xE2, 0x54, 0xFE, 0xF7, 0x49, 0xFB, 0x00, 0x28, 0x02, 0xD1, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xB1, 0xF7, 0x04, 0xFD, ++0x00, 0x28, 0xF8, 0xD1, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x0A, 0xD1, 0xA7, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x06, 0xD1, ++0xAA, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0xA7, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xA8, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x03, 0xD1, 0x62, 0x68, 0x09, 0x4B, 0x1A, 0x60, 0xE1, 0xE7, 0xA8, 0xF7, 0x81, 0xFB, 0x08, 0x4B, 0x18, 0x60, 0xF6, 0xE7, ++0x32, 0x00, 0x41, 0x46, 0x20, 0x00, 0xFF, 0xF7, 0xE5, 0xFD, 0xC8, 0xE7, 0x7C, 0x1E, 0x16, 0x00, 0x9D, 0x02, 0x00, 0x00, ++0x38, 0x27, 0x16, 0x00, 0x28, 0xE6, 0x10, 0x00, 0x2C, 0xE6, 0x10, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x1A, 0x60, 0x04, 0x4B, ++0x04, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x04, 0x30, 0x34, 0x40, 0xC1, 0x00, 0xA0, 0x00, 0x0C, 0x00, 0x58, 0x40, ++0x14, 0x00, 0x7F, 0x30, 0x01, 0x4B, 0x02, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0x04, 0x30, 0x34, 0x40, 0xC0, 0x00, 0xA0, 0x00, ++0x10, 0xB5, 0x30, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x09, 0xD0, 0x01, 0x28, 0x08, 0xD0, 0x02, 0x28, 0x47, 0xD0, 0x2D, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x10, 0xBD, 0xA8, 0xF7, 0x44, 0xFB, 0x27, 0x4B, 0x5B, 0x78, ++0x00, 0x2B, 0x11, 0xD1, 0x25, 0x4B, 0x01, 0x22, 0x5A, 0x70, 0x58, 0x60, 0x9B, 0x78, 0x01, 0x2B, 0xF1, 0xD0, 0xFE, 0xF7, ++0xA7, 0xFA, 0x00, 0x28, 0xED, 0xD1, 0xFE, 0xF7, 0xC1, 0xFA, 0x00, 0x28, 0xE9, 0xD1, 0xFF, 0xF7, 0xC1, 0xFF, 0xE6, 0xE7, ++0x1C, 0x4A, 0x53, 0x68, 0xC3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x92, 0x78, 0x00, 0x2A, 0x0B, 0xD1, 0x23, 0x2B, 0xDC, 0xD9, ++0x17, 0x4B, 0x01, 0x32, 0x9A, 0x70, 0x00, 0x22, 0x5A, 0x70, 0x58, 0x60, 0x16, 0x4B, 0x17, 0x4A, 0x1A, 0x60, 0xD2, 0xE7, ++0x01, 0x2A, 0xD0, 0xD1, 0x3B, 0x2B, 0xCE, 0xD9, 0x10, 0x4B, 0x00, 0x22, 0x9A, 0x70, 0x01, 0x32, 0x5A, 0x70, 0x58, 0x60, ++0xFE, 0xF7, 0x7E, 0xFA, 0x00, 0x28, 0xC4, 0xD1, 0xFE, 0xF7, 0x98, 0xFA, 0x00, 0x28, 0xC0, 0xD1, 0xFF, 0xF7, 0x98, 0xFF, ++0xBD, 0xE7, 0x08, 0x4B, 0x5B, 0x78, 0x01, 0x2B, 0x01, 0xD0, 0x00, 0x29, 0xB7, 0xD0, 0x05, 0x4B, 0x00, 0x22, 0x5A, 0x70, ++0x9A, 0x70, 0x01, 0x3A, 0x5A, 0x60, 0x04, 0x4B, 0x04, 0x4A, 0x1A, 0x60, 0xAD, 0xE7, 0xC0, 0x46, 0xDC, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x04, 0x30, 0x34, 0x40, 0xC0, 0x00, 0xA0, 0x00, 0xF0, 0xB5, 0x80, 0x00, 0x26, 0x4B, 0xC3, 0x58, ++0xAB, 0x20, 0x18, 0x5C, 0x00, 0x28, 0x27, 0xD0, 0x0D, 0x1C, 0xAA, 0x20, 0x80, 0x00, 0x81, 0x42, 0x01, 0xD3, 0x22, 0x49, ++0x0D, 0x1C, 0xAD, 0xB2, 0x9D, 0x21, 0x5F, 0x5C, 0x00, 0x23, 0x00, 0x24, 0x01, 0x26, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, ++0x0C, 0xD0, 0xD8, 0xB2, 0x39, 0x00, 0x19, 0x41, 0x0E, 0x42, 0xF7, 0xD0, 0x59, 0x00, 0x1A, 0x4C, 0x61, 0x5A, 0xA9, 0x42, ++0x01, 0xD2, 0x04, 0x00, 0xF0, 0xE7, 0x04, 0x00, 0x17, 0x4B, 0x18, 0x5D, 0x64, 0x00, 0x15, 0x4B, 0xE3, 0x5A, 0xAB, 0x42, ++0x00, 0xD9, 0x2B, 0x00, 0x13, 0x80, 0xF0, 0xBD, 0x9C, 0x20, 0x1F, 0x5C, 0x00, 0x23, 0x00, 0x25, 0x01, 0x26, 0x02, 0xE0, ++0x01, 0x33, 0x06, 0x2B, 0x0C, 0xD0, 0xDC, 0xB2, 0x38, 0x00, 0x18, 0x41, 0x06, 0x42, 0xF7, 0xD0, 0x58, 0x00, 0x0C, 0x4D, ++0x28, 0x5A, 0x88, 0x42, 0x01, 0xD2, 0x25, 0x00, 0xF0, 0xE7, 0x25, 0x00, 0x09, 0x4B, 0x58, 0x5D, 0x6D, 0x00, 0x07, 0x4B, ++0xEB, 0x5A, 0x8B, 0x42, 0x00, 0xD9, 0x0B, 0x00, 0x13, 0x80, 0xDE, 0xE7, 0x38, 0x27, 0x16, 0x00, 0xA7, 0x02, 0x00, 0x00, ++0x40, 0xC9, 0x0D, 0x00, 0x50, 0xC9, 0x0D, 0x00, 0x2C, 0xC9, 0x0D, 0x00, 0x38, 0xC9, 0x0D, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x85, 0xB0, 0x00, 0x90, 0x88, 0x46, 0x82, 0x00, 0x95, 0x4B, 0xD4, 0x58, ++0xAF, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD9, 0x0D, 0xE1, 0x03, 0x02, 0x01, 0x27, 0x1F, 0x43, 0x88, 0x23, 0x99, 0x46, ++0xBB, 0x46, 0x2A, 0xE0, 0xAB, 0x00, 0x5D, 0x19, 0x6D, 0x00, 0x8E, 0x4B, 0xEA, 0x18, 0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, ++0x60, 0x39, 0x0B, 0x43, 0x13, 0x80, 0x8B, 0x4B, 0xEA, 0x18, 0x83, 0x79, 0xDB, 0x00, 0x11, 0x39, 0x0B, 0x43, 0x13, 0x80, ++0x82, 0x88, 0x88, 0x4B, 0xEB, 0x18, 0x1A, 0x80, 0x87, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, ++0x2B, 0x80, 0xAE, 0x22, 0xA3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, ++0xAF, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD9, 0xDB, 0xE0, 0x9E, 0x23, 0xE5, 0x5C, 0x6D, 0x00, 0x10, 0x33, 0xE3, 0x5C, ++0xED, 0x18, 0xED, 0xB2, 0x20, 0x00, 0x40, 0x30, 0x81, 0xF7, 0x84, 0xFA, 0x00, 0x28, 0xC7, 0xD1, 0xEC, 0x23, 0xE3, 0x58, ++0x00, 0x2B, 0x39, 0xD0, 0x9A, 0x7A, 0x00, 0x2A, 0x36, 0xD1, 0xAC, 0x32, 0xA2, 0x5C, 0x00, 0x2A, 0x00, 0xD1, 0xC2, 0xE0, ++0x9A, 0x78, 0x05, 0x3A, 0x03, 0x2A, 0x00, 0xD8, 0xBD, 0xE0, 0x1A, 0x88, 0xA9, 0x00, 0x4D, 0x19, 0x6D, 0x00, 0x69, 0x49, ++0x68, 0x18, 0x01, 0x88, 0xDE, 0x79, 0x0F, 0x23, 0x33, 0x40, 0xDB, 0x00, 0x78, 0x26, 0xB1, 0x43, 0x0B, 0x43, 0x03, 0x80, ++0x64, 0x4B, 0xE9, 0x18, 0xD3, 0x00, 0x05, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x0B, 0x80, 0xEC, 0x23, 0xE3, 0x58, 0x1A, 0x89, ++0x62, 0x4B, 0xEB, 0x18, 0x1A, 0x80, 0x60, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x2B, 0x80, ++0xAE, 0x22, 0xA3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0xAF, 0xE7, ++0xAC, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x8B, 0xE0, 0x96, 0x23, 0xE1, 0x5A, 0x01, 0x27, 0x00, 0x29, 0x39, 0xD0, ++0x02, 0xAB, 0x9A, 0x1D, 0x00, 0x98, 0xFF, 0xF7, 0x07, 0xFF, 0xAB, 0x00, 0x5D, 0x19, 0x6D, 0x00, 0x4B, 0x4B, 0xEA, 0x18, ++0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, 0xC0, 0x00, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x48, 0x4B, 0xEA, 0x18, 0x02, 0xAB, ++0xDB, 0x88, 0xDB, 0x00, 0x1F, 0x43, 0x04, 0x23, 0x1F, 0x43, 0xBF, 0xB2, 0x17, 0x80, 0x94, 0x22, 0xA1, 0x5A, 0x45, 0x4B, ++0xEB, 0x18, 0x19, 0x80, 0x42, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x2B, 0x80, 0x02, 0xAB, ++0xDB, 0x88, 0x96, 0x20, 0x21, 0x5A, 0xC9, 0x1A, 0x21, 0x52, 0xA1, 0x5A, 0x5B, 0x18, 0xA3, 0x52, 0x1A, 0x32, 0xA3, 0x5C, ++0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x6B, 0xE7, 0x27, 0x00, 0x48, 0x37, ++0x80, 0x23, 0x1B, 0x05, 0x9A, 0x46, 0x0F, 0xE0, 0x52, 0x00, 0x8A, 0x42, 0x1E, 0xDA, 0x01, 0x23, 0xFF, 0x22, 0x59, 0x46, ++0x31, 0x48, 0x7E, 0xF7, 0x7F, 0xFD, 0x01, 0x23, 0x03, 0x70, 0x7E, 0xF7, 0xA5, 0xFD, 0x30, 0x89, 0x88, 0xF7, 0x98, 0xFE, ++0x38, 0x00, 0x81, 0xF7, 0xE7, 0xF9, 0x06, 0x1E, 0x46, 0xD0, 0x4B, 0x46, 0xE2, 0x5A, 0x00, 0x2A, 0x08, 0xD0, 0x43, 0x68, ++0x59, 0x1C, 0x05, 0xD0, 0x41, 0x46, 0xCB, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x51, 0x45, 0xDD, 0xD9, 0x73, 0x89, 0x9F, 0x04, ++0xBF, 0x0F, 0x9B, 0x05, 0x9B, 0x0D, 0x9A, 0x46, 0x90, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0x2C, 0xD0, 0x8C, 0x23, 0xE3, 0x58, ++0x00, 0x2B, 0x06, 0xD0, 0x1D, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x8C, 0x23, ++0xE6, 0x50, 0x96, 0x23, 0x52, 0x46, 0xE2, 0x52, 0x32, 0x89, 0x02, 0x3B, 0xE2, 0x52, 0x01, 0x2F, 0x00, 0xD0, 0x02, 0x27, ++0x96, 0x23, 0xE1, 0x5A, 0x00, 0x29, 0x00, 0xD0, 0x78, 0xE7, 0xAF, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x06, 0xD0, 0xA8, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x02, 0xD1, 0xA8, 0x33, 0x01, 0x22, 0xE2, 0x54, 0x05, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x90, 0x33, 0xE6, 0x50, 0xDC, 0xE7, 0x01, 0x27, 0xE3, 0xE7, 0x38, 0x27, 0x16, 0x00, ++0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xD0, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0xCE, 0x69, 0x61, 0x40, ++0x2B, 0x06, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, ++0x83, 0xB0, 0x82, 0x00, 0x4B, 0x4B, 0xD4, 0x58, 0x90, 0x23, 0xE2, 0x58, 0x00, 0x2A, 0x00, 0xD1, 0x84, 0xE0, 0x49, 0x4B, ++0x59, 0x88, 0x49, 0x4B, 0x1B, 0x78, 0x99, 0x42, 0x73, 0xD9, 0x9E, 0x23, 0xE3, 0x5C, 0x5B, 0x00, 0xAD, 0x21, 0x61, 0x5C, ++0x5B, 0x18, 0xDB, 0xB2, 0x56, 0x89, 0xB6, 0x05, 0xB2, 0x0D, 0x90, 0x46, 0x02, 0x22, 0x90, 0x26, 0x41, 0x49, 0x01, 0x91, ++0xAF, 0x21, 0x8A, 0x46, 0x01, 0x39, 0x89, 0x46, 0x10, 0x39, 0x8C, 0x46, 0x00, 0x90, 0x0C, 0xE0, 0x63, 0x46, 0xE5, 0x5C, ++0x6D, 0x00, 0xAD, 0x23, 0xE1, 0x5C, 0x4B, 0x42, 0x4B, 0x41, 0x5B, 0x19, 0xDB, 0xB2, 0x01, 0x3A, 0xD2, 0xB2, 0x00, 0x2A, ++0x31, 0xD0, 0x99, 0x00, 0xCB, 0x18, 0x5B, 0x00, 0x35, 0x49, 0x5F, 0x18, 0x39, 0x88, 0x89, 0xB2, 0xA5, 0x59, 0x2D, 0x89, ++0x8D, 0x42, 0xE7, 0xD8, 0x45, 0x44, 0xA9, 0x42, 0xE4, 0xDA, 0x31, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x01, 0x98, 0x01, 0x40, ++0x29, 0x80, 0x2F, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x2D, 0x48, 0x01, 0x43, 0x89, 0xB2, 0x29, 0x80, ++0x2C, 0x49, 0x8B, 0x46, 0x5B, 0x44, 0x19, 0x88, 0x78, 0x20, 0x81, 0x43, 0x19, 0x80, 0x00, 0x23, 0x3B, 0x80, 0x53, 0x46, ++0xE3, 0x5C, 0x01, 0x3B, 0x51, 0x46, 0x63, 0x54, 0x4B, 0x46, 0xE3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0x49, 0x46, 0x63, 0x54, ++0xC0, 0xE7, 0x00, 0x98, 0x00, 0x02, 0x01, 0x25, 0x28, 0x43, 0x81, 0xB2, 0x01, 0x23, 0xFF, 0x32, 0x1F, 0x48, 0x7E, 0xF7, ++0xA5, 0xFC, 0x05, 0x70, 0x7E, 0xF7, 0xCC, 0xFC, 0x1D, 0x48, 0x80, 0xF7, 0xA3, 0xFD, 0x90, 0x23, 0xE3, 0x58, 0x18, 0x89, ++0x88, 0xF7, 0xBA, 0xFD, 0x8C, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0x0B, 0xD0, 0x90, 0x22, 0xA3, 0x50, 0x8C, 0x23, 0x00, 0x22, ++0xE2, 0x50, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x96, 0x22, 0x00, 0x21, ++0xA1, 0x52, 0xEF, 0xE7, 0x8C, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0xF0, 0xD0, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0xE9, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x9C, 0xE5, 0x10, 0x00, 0xF8, 0xE1, 0x10, 0x00, ++0x07, 0xE0, 0xFF, 0xFF, 0xCE, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, ++0xCA, 0x69, 0x61, 0x40, 0x2B, 0x06, 0x00, 0x00, 0x18, 0xD1, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x03, 0x00, 0x00, 0x20, ++0x9A, 0x6C, 0x00, 0x2A, 0x00, 0xD0, 0x70, 0x47, 0xA7, 0x32, 0x9A, 0x5C, 0x00, 0x2A, 0xFA, 0xD1, 0xA8, 0x32, 0x98, 0x5C, ++0x43, 0x42, 0x58, 0x41, 0xC0, 0xB2, 0xF4, 0xE7, 0x04, 0x4B, 0x18, 0x68, 0x04, 0x4B, 0x1B, 0x68, 0x18, 0x43, 0x43, 0x1E, ++0x98, 0x41, 0xC0, 0xB2, 0x70, 0x47, 0xC0, 0x46, 0x24, 0x27, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0x70, 0xB5, 0x84, 0xB0, ++0x82, 0x00, 0x12, 0x4B, 0xD5, 0x58, 0x01, 0xA9, 0x11, 0x4C, 0x02, 0x01, 0x13, 0x1A, 0x9B, 0x00, 0xE3, 0x18, 0xDE, 0x88, ++0x4E, 0x80, 0x1E, 0x7B, 0x4E, 0x70, 0x1E, 0x89, 0xCE, 0x80, 0x5E, 0x89, 0x0E, 0x81, 0x9B, 0x88, 0x8B, 0x80, 0x12, 0x1A, ++0x92, 0x00, 0xA2, 0x18, 0x53, 0x7B, 0x01, 0x22, 0x53, 0x40, 0x36, 0x22, 0xAA, 0x5C, 0x5A, 0x40, 0x01, 0x23, 0x13, 0x40, ++0x2E, 0x22, 0x13, 0x43, 0x0B, 0x70, 0xA6, 0xF7, 0x0F, 0xF9, 0x04, 0xB0, 0x70, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0xC0, 0xA0, 0x16, 0x00, 0xF8, 0xB5, 0x06, 0x00, 0x0C, 0x00, 0x05, 0x0A, 0xAA, 0x00, 0x18, 0x4B, 0xD7, 0x58, 0x36, 0x23, ++0xFB, 0x5C, 0x00, 0x2B, 0x0C, 0xD0, 0x2B, 0x01, 0x5B, 0x1B, 0x9B, 0x00, 0x14, 0x4A, 0xD3, 0x18, 0x5B, 0x7B, 0x00, 0x2B, ++0x08, 0xD1, 0x01, 0x21, 0x30, 0x00, 0x7E, 0xF7, 0x77, 0xFF, 0xF8, 0xBD, 0xE8, 0xB2, 0xB2, 0xF7, 0x73, 0xF9, 0xEE, 0xE7, ++0x08, 0x23, 0x14, 0x22, 0x00, 0x21, 0x0D, 0x48, 0x7E, 0xF7, 0xF6, 0xFB, 0x04, 0x70, 0x2B, 0x00, 0x80, 0x33, 0x43, 0x80, ++0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, 0xFB, 0x5C, 0x03, 0x71, 0xD0, 0xF7, 0x4B, 0xFA, 0x2B, 0x01, 0x5D, 0x1B, 0xAD, 0x00, ++0x03, 0x4B, 0x5D, 0x19, 0x00, 0x23, 0x6B, 0x73, 0xDD, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xC0, 0xA0, 0x16, 0x00, ++0x03, 0x11, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x93, 0xB0, 0x05, 0x00, ++0x03, 0x91, 0x93, 0x46, 0x1E, 0x00, 0x1C, 0xAB, 0x1B, 0x88, 0x99, 0x46, 0x1D, 0xAB, 0x1B, 0x88, 0x9A, 0x46, 0x04, 0x0A, ++0xA2, 0x00, 0xCB, 0x4B, 0xD7, 0x58, 0x01, 0x00, 0xCA, 0x48, 0x7E, 0xF7, 0x7B, 0xFB, 0xB3, 0x1F, 0xC9, 0x4A, 0x9B, 0xB2, ++0x93, 0x42, 0x03, 0xD8, 0x5B, 0x46, 0x33, 0x43, 0xDB, 0x07, 0x0D, 0xD5, 0x39, 0x23, 0xFB, 0x5C, 0xE0, 0xB2, 0x12, 0x22, ++0x17, 0x21, 0xA6, 0xF7, 0xF6, 0xF8, 0x13, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, ++0x5E, 0x45, 0xEF, 0xD9, 0x4B, 0x46, 0x00, 0x2B, 0xEC, 0xD0, 0x73, 0x08, 0x4B, 0x45, 0xE9, 0xD3, 0x53, 0x46, 0x28, 0x2B, ++0xE6, 0xD8, 0x4B, 0x44, 0x5B, 0x00, 0xB3, 0x42, 0xE2, 0xD2, 0x28, 0x00, 0x7E, 0xF7, 0x70, 0xFF, 0x01, 0x28, 0x00, 0xD1, ++0x85, 0xE0, 0xB5, 0x4B, 0x22, 0x01, 0x11, 0x1B, 0x89, 0x00, 0xCE, 0x52, 0x5B, 0x18, 0x5E, 0x80, 0x4A, 0x46, 0x1A, 0x81, ++0x9E, 0x80, 0x5A, 0x46, 0xDA, 0x80, 0x52, 0x46, 0x5A, 0x81, 0x03, 0x9A, 0x1A, 0x73, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x22, ++0x04, 0x92, 0x01, 0x2B, 0x77, 0xD0, 0x0A, 0x96, 0x0B, 0x96, 0x36, 0x23, 0xF8, 0x5C, 0x4A, 0x46, 0x02, 0x2A, 0x00, 0xD9, ++0x02, 0x22, 0x90, 0x46, 0x80, 0x44, 0x0A, 0xAB, 0x42, 0x46, 0x0C, 0x92, 0x49, 0x46, 0x49, 0x00, 0x0D, 0x91, 0x00, 0x21, ++0x99, 0x74, 0x80, 0x31, 0x8C, 0x46, 0xA4, 0x44, 0x61, 0x46, 0x19, 0x82, 0x01, 0x21, 0x04, 0x9A, 0x11, 0x40, 0xD9, 0x74, ++0x06, 0xAB, 0x06, 0x96, 0x42, 0x46, 0x07, 0x92, 0x62, 0x46, 0x9A, 0x81, 0x00, 0x28, 0x5A, 0xD1, 0x58, 0x46, 0x08, 0x90, ++0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, 0x5A, 0xD0, 0x08, 0x9B, 0x10, 0x93, 0x11, 0x93, 0x06, 0x9B, 0x0F, 0x93, 0x06, 0xA8, ++0xD4, 0xF7, 0x5A, 0xFA, 0x80, 0x46, 0x00, 0x28, 0x72, 0xD1, 0x0A, 0xAA, 0x10, 0x98, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, ++0x8D, 0x49, 0xCB, 0x18, 0x98, 0x62, 0x0F, 0x99, 0x8C, 0x46, 0x59, 0x62, 0x0C, 0x99, 0xD9, 0x62, 0x0D, 0x99, 0x19, 0x63, ++0x12, 0x8A, 0x9A, 0x86, 0x00, 0x22, 0x9A, 0x63, 0x36, 0x33, 0x1A, 0x70, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x6B, 0xD1, ++0x80, 0xB2, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x81, 0x4A, 0xD3, 0x18, 0xD8, 0x80, 0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, ++0x67, 0xD0, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, 0x7D, 0x4B, 0x9A, 0x42, 0x79, 0xD1, 0x43, 0x46, 0x01, 0x2B, ++0x00, 0xD1, 0xDF, 0xE0, 0x02, 0x2B, 0x00, 0xD1, 0xBC, 0xE0, 0x00, 0x2B, 0x00, 0xD1, 0xAE, 0xE0, 0x77, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x5D, 0xE7, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x70, 0x4A, 0xD3, 0x18, ++0x00, 0x22, 0x5A, 0x73, 0x71, 0xE7, 0xE0, 0xB2, 0xAF, 0xF7, 0xAE, 0xFE, 0x43, 0x08, 0x04, 0x93, 0x81, 0xE7, 0x04, 0x9A, ++0x31, 0x00, 0x58, 0x46, 0xA5, 0xF7, 0x2E, 0xFD, 0x9F, 0xE7, 0x06, 0x9B, 0x9B, 0x46, 0x01, 0x3B, 0x98, 0x46, 0x80, 0x44, ++0x5B, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x66, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x59, 0x46, ++0x40, 0x46, 0xD4, 0xF7, 0x1B, 0xFE, 0x08, 0x91, 0x0A, 0xAB, 0xDA, 0x7C, 0x01, 0x21, 0x4A, 0x40, 0xDA, 0x74, 0x0C, 0x9A, ++0x03, 0x32, 0x0C, 0x92, 0x0D, 0x9A, 0x03, 0x32, 0x0D, 0x92, 0x07, 0x9B, 0x05, 0x93, 0x03, 0x33, 0x07, 0x93, 0x81, 0xE7, ++0x28, 0x00, 0x7E, 0xF7, 0xAD, 0xFE, 0x80, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x01, 0x23, 0x98, 0x46, 0x83, 0xE7, 0x0A, 0xA8, ++0xD4, 0xF7, 0x6A, 0xF9, 0x00, 0x28, 0x00, 0xD0, 0x7D, 0xE7, 0x02, 0x23, 0x98, 0x46, 0x7A, 0xE7, 0x63, 0x46, 0x99, 0xB2, ++0x80, 0xB2, 0x04, 0x9A, 0xA5, 0xF7, 0x0A, 0xFD, 0x8D, 0xE7, 0x43, 0x1C, 0x04, 0x93, 0x0F, 0x9B, 0x9B, 0x46, 0x00, 0x2B, ++0x05, 0xD1, 0x49, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, ++0x42, 0x4A, 0xD3, 0x18, 0x05, 0x93, 0x59, 0x46, 0x04, 0x98, 0xD4, 0xF7, 0xDB, 0xFD, 0x05, 0x9B, 0xD9, 0x80, 0x7E, 0xE7, ++0xE3, 0xB2, 0x9B, 0x46, 0x18, 0x00, 0x95, 0xF7, 0x71, 0xFF, 0x05, 0x90, 0x0F, 0x9B, 0x04, 0x93, 0x00, 0x28, 0x05, 0xD1, ++0x3A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x05, 0x99, 0x04, 0x98, 0xD4, 0xF7, 0xC4, 0xFD, ++0x00, 0x29, 0x00, 0xD0, 0x6E, 0xE7, 0x3C, 0x22, 0x62, 0x43, 0x31, 0x4B, 0x9B, 0x18, 0xD9, 0x88, 0x11, 0x9B, 0x04, 0x93, ++0x10, 0x9B, 0x05, 0x93, 0x04, 0x9B, 0x05, 0x9A, 0x9A, 0x1A, 0x8A, 0x18, 0x92, 0xB2, 0x58, 0x46, 0x95, 0xF7, 0x9C, 0xFF, ++0x04, 0x90, 0x0F, 0x9B, 0x9B, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x29, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, ++0x98, 0x47, 0x3C, 0x23, 0x63, 0x43, 0x23, 0x4A, 0xD3, 0x18, 0x05, 0x93, 0x59, 0x46, 0x04, 0x98, 0xD4, 0xF7, 0x9C, 0xFD, ++0x05, 0x9B, 0xD9, 0x80, 0x46, 0xE7, 0x39, 0x33, 0xFA, 0x5C, 0xE0, 0xB2, 0x17, 0x21, 0xA5, 0xF7, 0x87, 0xFF, 0x2F, 0x21, ++0x28, 0x00, 0x7E, 0xF7, 0xD5, 0xFD, 0xAA, 0xE6, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x0A, 0xD0, 0xE0, 0xB2, 0xFF, 0xF7, ++0x13, 0xFE, 0x28, 0x00, 0x96, 0xF7, 0x3A, 0xFB, 0x2E, 0x21, 0x28, 0x00, 0x7E, 0xF7, 0xC6, 0xFD, 0x9B, 0xE6, 0x3C, 0x22, ++0x62, 0x43, 0x10, 0x4B, 0x9B, 0x18, 0xD9, 0x88, 0xE0, 0xB2, 0x03, 0x9B, 0x9F, 0x07, 0xFF, 0x0F, 0x01, 0x97, 0x53, 0x46, ++0x00, 0x93, 0x4B, 0x46, 0x32, 0x00, 0xAF, 0xF7, 0x5F, 0xFC, 0xE3, 0xE7, 0x39, 0x23, 0xFB, 0x5C, 0xE0, 0xB2, 0x20, 0x22, ++0x17, 0x21, 0xA5, 0xF7, 0x7A, 0xFF, 0x20, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x1B, 0xFE, 0x7E, 0xE6, 0x64, 0xA2, 0x16, 0x00, ++0x05, 0x06, 0x00, 0x00, 0x3A, 0x05, 0x00, 0x00, 0xC0, 0xA0, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x8A, 0xB0, 0x06, 0x00, 0x88, 0x46, 0x91, 0x46, 0x1D, 0x00, ++0x12, 0xAB, 0x1B, 0x88, 0x9C, 0x46, 0x04, 0x0A, 0xA2, 0x00, 0x9C, 0x4B, 0xD7, 0x58, 0x9C, 0x4B, 0x22, 0x01, 0x11, 0x1B, ++0x89, 0x00, 0x40, 0x46, 0xC8, 0x52, 0x5B, 0x18, 0x4A, 0x46, 0x5A, 0x80, 0x1D, 0x81, 0x62, 0x46, 0x5A, 0x81, 0x36, 0x23, ++0xFB, 0x5C, 0x00, 0x22, 0x92, 0x46, 0x01, 0x2B, 0x00, 0xD1, 0x87, 0xE0, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x91, 0x4A, ++0xD3, 0x18, 0x00, 0x22, 0x1A, 0x73, 0xA7, 0xF7, 0x29, 0xFE, 0x50, 0x44, 0x03, 0x01, 0x06, 0xD5, 0x23, 0x01, 0x1B, 0x1B, ++0x9B, 0x00, 0x8B, 0x4A, 0xD3, 0x18, 0x02, 0x22, 0x1A, 0x73, 0x02, 0xAB, 0x4A, 0x46, 0x02, 0x92, 0x42, 0x46, 0x5A, 0x60, ++0x2A, 0x00, 0x02, 0x2D, 0x00, 0xD9, 0x02, 0x22, 0x9A, 0x60, 0x6D, 0x00, 0x05, 0x95, 0x00, 0x23, 0x02, 0xAA, 0x93, 0x74, ++0x25, 0x00, 0x80, 0x35, 0x15, 0x82, 0x53, 0x46, 0x5B, 0x08, 0x9A, 0x46, 0x01, 0x23, 0x52, 0x46, 0x13, 0x40, 0x02, 0xAA, ++0xD3, 0x74, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, 0x7B, 0x4B, 0x9A, 0x42, 0x58, 0xD1, 0x36, 0x23, 0xFB, 0x5C, ++0x01, 0x2B, 0x6A, 0xD0, 0x02, 0xA8, 0xD4, 0xF7, 0x63, 0xF8, 0x00, 0x28, 0x00, 0xD0, 0x72, 0xE0, 0x08, 0x98, 0x22, 0x01, ++0x12, 0x1B, 0x92, 0x00, 0x71, 0x4B, 0x9B, 0x18, 0x98, 0x62, 0x07, 0x99, 0x59, 0x62, 0x04, 0x9A, 0xDA, 0x62, 0x05, 0x9A, ++0x00, 0x92, 0x1A, 0x63, 0x02, 0xAA, 0x12, 0x8A, 0x9A, 0x86, 0x00, 0x22, 0x9A, 0x63, 0x36, 0x33, 0x1A, 0x70, 0x36, 0x23, ++0xFB, 0x5C, 0x00, 0x2B, 0x6A, 0xD1, 0x80, 0xB2, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x65, 0x4A, 0xD3, 0x18, 0xD8, 0x80, ++0x07, 0x9D, 0x9D, 0x80, 0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, 0x63, 0xD0, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, ++0x5F, 0x4B, 0x9A, 0x42, 0x00, 0xD0, 0x72, 0xE0, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x5B, 0x4A, 0xD3, 0x18, 0x01, 0x22, ++0x5A, 0x73, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0xA4, 0xE0, 0xE0, 0xB2, 0xFF, 0xF7, 0x43, 0xFD, 0x30, 0x00, ++0x96, 0xF7, 0x6A, 0xFA, 0x2E, 0x21, 0x30, 0x00, 0x7E, 0xF7, 0xF6, 0xFC, 0x0A, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xF0, 0xBD, 0xE0, 0xB2, 0xAF, 0xF7, 0x1F, 0xFD, 0x82, 0x46, 0x72, 0xE7, 0xE0, 0xB2, 0x95, 0xF7, 0x40, 0xFE, ++0x02, 0x00, 0x03, 0x00, 0x02, 0x98, 0x82, 0x42, 0x07, 0xD2, 0x00, 0x92, 0x11, 0x00, 0xD4, 0xF7, 0x13, 0xFC, 0x43, 0x1C, ++0x00, 0x9A, 0x5A, 0x43, 0x93, 0xB2, 0x03, 0x9A, 0x93, 0x42, 0x93, 0xD8, 0x02, 0x93, 0x03, 0x93, 0x90, 0xE7, 0x02, 0xAB, ++0xDB, 0x7C, 0x01, 0x22, 0x53, 0x40, 0x02, 0xAA, 0xD3, 0x74, 0x04, 0x9B, 0x03, 0x33, 0x04, 0x93, 0x05, 0x9B, 0x00, 0x93, ++0x03, 0x33, 0x05, 0x93, 0x86, 0xE7, 0x08, 0x23, 0x14, 0x22, 0x00, 0x21, 0x3A, 0x48, 0x7E, 0xF7, 0x4B, 0xF9, 0x20, 0x23, ++0x03, 0x70, 0x45, 0x80, 0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, 0xFB, 0x5C, 0x03, 0x71, 0xCF, 0xF7, 0xA1, 0xFF, 0xBF, 0xE7, ++0x89, 0xB2, 0x80, 0xB2, 0x52, 0x46, 0xA5, 0xF7, 0x83, 0xFB, 0x8F, 0xE7, 0x43, 0x1C, 0x98, 0x46, 0x00, 0x2D, 0x05, 0xD1, ++0x2F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x28, 0x4A, ++0x91, 0x46, 0x99, 0x44, 0x29, 0x00, 0x40, 0x46, 0xD4, 0xF7, 0x56, 0xFC, 0x4B, 0x46, 0xD9, 0x80, 0x84, 0xE7, 0xE3, 0xB2, ++0x98, 0x46, 0x18, 0x00, 0x95, 0xF7, 0xEC, 0xFD, 0x05, 0x1E, 0x07, 0x9B, 0x99, 0x46, 0x05, 0xD1, 0x21, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x29, 0x00, 0x48, 0x46, 0xD4, 0xF7, 0x40, 0xFC, 0x00, 0x29, 0x00, 0xD0, ++0x76, 0xE7, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x16, 0x4A, 0xD3, 0x18, 0xD9, 0x88, 0x09, 0x9B, 0x00, 0x93, 0x08, 0x9B, ++0x01, 0x93, 0x00, 0x9B, 0x01, 0x9A, 0x9A, 0x1A, 0x8A, 0x18, 0x92, 0xB2, 0x40, 0x46, 0x95, 0xF7, 0x17, 0xFE, 0x81, 0x46, ++0x07, 0x9B, 0x98, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x0F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x08, 0x4D, 0xED, 0x18, 0x41, 0x46, 0x48, 0x46, 0xD4, 0xF7, 0x17, 0xFC, 0xE9, 0x80, ++0x4E, 0xE7, 0xE0, 0xB2, 0x01, 0x33, 0x00, 0x22, 0x17, 0x21, 0x95, 0xF7, 0x89, 0xFC, 0x53, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0xC0, 0xA0, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x00, 0x24, 0x00, 0x20, 0x0E, 0x4E, 0xA1, 0x27, 0xAF, 0x23, 0x98, 0x46, 0x0C, 0xE0, 0x42, 0x46, 0x9D, 0x5C, ++0x45, 0x19, 0xED, 0xB2, 0x48, 0x33, 0x18, 0x00, 0x80, 0xF7, 0x18, 0xFE, 0x28, 0x18, 0xC0, 0xB2, 0x01, 0x34, 0x07, 0x2C, ++0x07, 0xD0, 0xA3, 0x00, 0x9B, 0x59, 0x00, 0x2B, 0xF8, 0xD0, 0xDA, 0x5D, 0x00, 0x2A, 0xF5, 0xD1, 0xEA, 0xE7, 0x04, 0xBC, ++0x90, 0x46, 0xF0, 0xBD, 0x38, 0x27, 0x16, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x40, 0x4B, 0x1A, 0x78, 0x01, 0x2A, 0x01, 0xD0, ++0x05, 0xB0, 0xF0, 0xBD, 0x3E, 0x4B, 0x1D, 0x78, 0x3E, 0x4B, 0x1B, 0x68, 0x00, 0x24, 0x5B, 0x05, 0x08, 0xD5, 0x3C, 0x48, ++0x03, 0x68, 0x3C, 0x49, 0x19, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x0B, 0x43, 0x03, 0x60, 0x80, 0x34, 0x39, 0x4B, 0x1B, 0x68, ++0x9B, 0x05, 0x09, 0xD4, 0x37, 0x48, 0x03, 0x68, 0x37, 0x49, 0x19, 0x40, 0x80, 0x23, 0x9B, 0x00, 0x0B, 0x43, 0x03, 0x60, ++0x40, 0x23, 0x1C, 0x43, 0x34, 0x4B, 0x18, 0x68, 0x34, 0x4B, 0x19, 0x68, 0x34, 0x4B, 0x1E, 0x68, 0x8B, 0x07, 0x31, 0xD4, ++0xF0, 0x23, 0x03, 0x40, 0x30, 0x2B, 0x0E, 0xD0, 0x20, 0x2B, 0x1F, 0xD0, 0x10, 0x2B, 0x29, 0xD1, 0x2F, 0x4B, 0xDB, 0x69, ++0xB3, 0x42, 0x25, 0xD0, 0xF0, 0x23, 0x07, 0x00, 0x9F, 0x43, 0x3B, 0x00, 0x20, 0x27, 0x3B, 0x43, 0x0A, 0xE0, 0x2A, 0x4B, ++0xDB, 0x6B, 0xB3, 0x42, 0x1A, 0xD0, 0xF0, 0x23, 0x02, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x20, 0x22, 0x13, 0x43, 0x1D, 0x3A, ++0x22, 0x4F, 0x3F, 0x68, 0xBF, 0x07, 0x1F, 0xD4, 0x1F, 0x4F, 0x3B, 0x60, 0x14, 0x43, 0x1D, 0xE0, 0x20, 0x4B, 0xDB, 0x6A, ++0xB3, 0x42, 0x07, 0xD0, 0xF0, 0x23, 0x02, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x10, 0x22, 0x13, 0x43, 0x0E, 0x3A, 0xEB, 0xE7, ++0x01, 0x2D, 0xA3, 0xD1, 0x17, 0x4B, 0x1B, 0x68, 0x02, 0x93, 0x00, 0x23, 0x01, 0x93, 0x00, 0x90, 0x33, 0x00, 0x00, 0x22, ++0x16, 0x48, 0x80, 0xF7, 0x47, 0xF9, 0x00, 0x2C, 0x96, 0xD0, 0x0D, 0xE0, 0x04, 0x27, 0x3C, 0x43, 0x01, 0x2D, 0x00, 0xD0, ++0x90, 0xE7, 0x0E, 0x4D, 0x2D, 0x68, 0x02, 0x95, 0x01, 0x93, 0x00, 0x90, 0x33, 0x00, 0x0E, 0x48, 0x80, 0xF7, 0x36, 0xF9, ++0x32, 0x00, 0x21, 0x00, 0x0C, 0x48, 0x80, 0xF7, 0x31, 0xF9, 0x81, 0xE7, 0xB4, 0xE5, 0x10, 0x00, 0xBC, 0xE6, 0x10, 0x00, ++0x4C, 0x20, 0x62, 0x40, 0xFF, 0xF3, 0xFF, 0xFF, 0x58, 0x20, 0x62, 0x40, 0xFF, 0xFD, 0xFF, 0xFF, 0x08, 0x05, 0x62, 0x40, ++0x74, 0x20, 0x62, 0x40, 0x78, 0x20, 0x62, 0x40, 0xD8, 0x97, 0x16, 0x00, 0x24, 0xD1, 0x10, 0x00, 0x3C, 0xD1, 0x10, 0x00, ++0x70, 0x47, 0x00, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x13, 0x60, 0x81, 0x22, 0x52, 0x00, 0x98, 0x5C, 0x70, 0x47, 0xC0, 0x46, ++0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x17, 0x4B, 0x17, 0x4A, 0x1A, 0x60, ++0x17, 0x48, 0x80, 0xF7, 0x53, 0xFD, 0x45, 0x1E, 0x6D, 0xB2, 0x40, 0xB2, 0x00, 0x28, 0x1F, 0xDD, 0x11, 0x4F, 0x14, 0x4B, ++0x98, 0x46, 0x14, 0x4E, 0x0A, 0xE0, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x43, 0x46, 0x9B, 0x6E, 0x98, 0x47, 0x09, 0xE0, ++0x01, 0x3D, 0x6D, 0xB2, 0x6B, 0x1C, 0x0F, 0xD0, 0x38, 0x68, 0x0C, 0x30, 0x80, 0xF7, 0x56, 0xFC, 0x04, 0x1E, 0xEE, 0xD0, ++0x61, 0x6A, 0x30, 0x00, 0x80, 0xF7, 0xE2, 0xF8, 0x63, 0x6A, 0x00, 0x2B, 0xEE, 0xD0, 0x20, 0x00, 0x98, 0x47, 0xEB, 0xE7, ++0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x10, 0xE7, 0x10, 0x00, 0x64, 0x2A, 0x16, 0x00, 0x70, 0x2A, 0x16, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xC0, 0xD3, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x78, 0x21, 0x88, 0xF7, 0xAB, 0xF9, 0x05, 0x00, ++0x08, 0x4B, 0xC0, 0x18, 0x78, 0x22, 0x55, 0x21, 0x7C, 0xF7, 0x42, 0xF8, 0x29, 0x00, 0x20, 0x00, 0x88, 0xF7, 0xBA, 0xF9, ++0x01, 0x00, 0x20, 0x00, 0xB0, 0xF7, 0x1E, 0xFD, 0x02, 0x48, 0x80, 0xF7, 0xB7, 0xF8, 0x70, 0xBD, 0x00, 0x00, 0x61, 0x40, ++0x4C, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x04, 0x00, ++0x83, 0x00, 0x76, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1D, 0x68, 0x00, 0x2D, 0x00, 0xD1, 0xDE, 0xE0, 0x4B, 0x23, 0xEB, 0x5C, ++0x00, 0x2B, 0x05, 0xD0, 0x71, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x28, 0x00, 0x50, 0x30, ++0x80, 0xF7, 0x02, 0xFC, 0x07, 0x00, 0x00, 0x21, 0x20, 0x00, 0x88, 0xF7, 0xDF, 0xF9, 0x63, 0x01, 0x6A, 0x4A, 0x9A, 0x18, ++0x12, 0x68, 0xD2, 0x0F, 0x49, 0x21, 0x69, 0x5C, 0x01, 0x26, 0x71, 0x40, 0x91, 0x42, 0x4F, 0xD0, 0x66, 0x49, 0x8A, 0x46, ++0x9A, 0x44, 0x51, 0x46, 0x09, 0x68, 0x89, 0xB2, 0x8B, 0x46, 0x64, 0x4E, 0xB1, 0x46, 0x99, 0x44, 0x4E, 0x46, 0x36, 0x68, ++0xB6, 0xB2, 0xB0, 0x46, 0x61, 0x4E, 0x9E, 0x19, 0x36, 0x68, 0xB6, 0x03, 0xB1, 0x0F, 0x01, 0x91, 0x56, 0x46, 0x36, 0x68, ++0x36, 0x0C, 0x36, 0x04, 0xB4, 0x46, 0x56, 0x46, 0x61, 0x46, 0x31, 0x60, 0x49, 0x46, 0x09, 0x68, 0x09, 0x0C, 0x09, 0x04, ++0x8C, 0x46, 0x49, 0x46, 0x66, 0x46, 0x0E, 0x60, 0x00, 0x2F, 0x67, 0xD0, 0x00, 0x2A, 0x4C, 0xD1, 0x52, 0x4A, 0x94, 0x46, ++0x9C, 0x44, 0x62, 0x46, 0x12, 0x68, 0x91, 0x46, 0xBA, 0x88, 0x12, 0x04, 0x49, 0x46, 0x0F, 0x04, 0x3F, 0x0C, 0x3A, 0x43, ++0x61, 0x46, 0x0A, 0x60, 0x00, 0x28, 0x0A, 0xD0, 0x4B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x68, 0x82, 0x88, 0x04, 0x32, ++0x12, 0x04, 0x38, 0x04, 0x00, 0x0C, 0x02, 0x43, 0x1A, 0x60, 0x5B, 0x46, 0x00, 0x2B, 0x4C, 0xD1, 0x43, 0x46, 0x00, 0x2B, ++0x4E, 0xD1, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x3E, 0x49, 0x8A, 0x46, ++0x9A, 0x44, 0x51, 0x46, 0x09, 0x68, 0x09, 0x0C, 0x8B, 0x46, 0x3C, 0x49, 0x89, 0x46, 0x99, 0x44, 0x49, 0x46, 0x0E, 0x68, ++0x31, 0x0C, 0x88, 0x46, 0x39, 0x49, 0x5E, 0x18, 0x36, 0x68, 0x36, 0x03, 0xB1, 0x0F, 0x01, 0x91, 0x51, 0x46, 0x09, 0x68, ++0x09, 0x04, 0x09, 0x0C, 0x8C, 0x46, 0x51, 0x46, 0x66, 0x46, 0x0E, 0x60, 0x49, 0x46, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0C, ++0x8C, 0x46, 0x49, 0x46, 0x66, 0x46, 0x0E, 0x60, 0xAE, 0xE7, 0x2C, 0x4A, 0x94, 0x46, 0x9C, 0x44, 0x62, 0x46, 0x12, 0x68, ++0x12, 0x0C, 0x12, 0x04, 0xBF, 0x88, 0x3A, 0x43, 0x61, 0x46, 0x0A, 0x60, 0x00, 0x28, 0xC0, 0xD0, 0x26, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1F, 0x68, 0x82, 0x88, 0x04, 0x32, 0x92, 0xB2, 0x38, 0x0C, 0x00, 0x04, 0x02, 0x43, 0x1A, 0x60, 0xB4, 0xE7, ++0x00, 0x28, 0xB2, 0xD0, 0x00, 0x2A, 0xEF, 0xD1, 0xA4, 0xE7, 0x59, 0x46, 0x20, 0x00, 0x88, 0xF7, 0x17, 0xF9, 0xAD, 0xE7, ++0x46, 0x23, 0xE9, 0x5C, 0x09, 0x02, 0x45, 0x3B, 0x19, 0x43, 0x05, 0x33, 0xFF, 0x22, 0x1A, 0x48, 0x7D, 0xF7, 0xDE, 0xFE, ++0x07, 0x00, 0x43, 0x46, 0x03, 0x80, 0x58, 0x23, 0xEA, 0x5C, 0x01, 0x32, 0x2B, 0x8F, 0x53, 0x43, 0x83, 0x70, 0x01, 0x99, ++0xC1, 0x70, 0x14, 0x4B, 0x1A, 0x68, 0x01, 0x32, 0x1A, 0x60, 0x00, 0x29, 0x04, 0xD1, 0x3C, 0x71, 0x38, 0x00, 0x7D, 0xF7, ++0xF3, 0xFE, 0x90, 0xE7, 0x0F, 0x49, 0x0B, 0x68, 0x01, 0x33, 0x0B, 0x60, 0x01, 0x99, 0x0E, 0x48, 0x7F, 0xF7, 0xC4, 0xFF, ++0xF1, 0xE7, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x80, 0xE7, 0x54, 0x27, 0x16, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xD0, 0x05, 0x60, 0x40, 0xD8, 0x05, 0x60, 0x40, 0xDC, 0x05, 0x60, 0x40, 0xD4, 0x05, 0x60, 0x40, ++0x35, 0x06, 0x00, 0x00, 0xC4, 0xE6, 0x10, 0x00, 0xC0, 0xE6, 0x10, 0x00, 0x54, 0xD1, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, ++0x15, 0x00, 0x10, 0x00, 0x7E, 0xF7, 0x74, 0xFA, 0x00, 0x28, 0x03, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x07, 0xD8, ++0x21, 0x88, 0x04, 0x39, 0x89, 0xB2, 0x20, 0x79, 0x88, 0xF7, 0xFA, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0x2E, 0x0A, 0x06, 0x23, ++0x2A, 0x00, 0x31, 0x00, 0x1B, 0x48, 0x7D, 0xF7, 0x89, 0xFE, 0x05, 0x00, 0x23, 0x88, 0x83, 0x80, 0xA3, 0x78, 0x83, 0x70, ++0x21, 0x79, 0x01, 0x31, 0x09, 0x02, 0x80, 0x36, 0x89, 0x19, 0x01, 0x80, 0xE1, 0x78, 0x0A, 0x03, 0x14, 0x4B, 0x1A, 0x42, ++0x06, 0xD0, 0xC0, 0x20, 0x13, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x80, 0x01, 0xB0, 0x47, 0x2B, 0x88, 0x0F, 0x4A, ++0x13, 0x40, 0xE2, 0x78, 0x12, 0x03, 0x13, 0x43, 0x2B, 0x80, 0xE3, 0x78, 0x00, 0x2B, 0x03, 0xD1, 0x28, 0x00, 0xCF, 0xF7, ++0xC5, 0xFC, 0xD1, 0xE7, 0xA2, 0x78, 0x20, 0x88, 0x09, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x7B, 0xF7, 0xE0, 0xFE, ++0xE1, 0x78, 0x00, 0x29, 0xF0, 0xD0, 0x06, 0x48, 0x7F, 0xF7, 0x5A, 0xFF, 0xEC, 0xE7, 0xC0, 0x46, 0x07, 0x11, 0x00, 0x00, ++0xFF, 0xCF, 0xFF, 0xFF, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0x6C, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0x89, 0xB0, ++0x04, 0x1E, 0x00, 0xD1, 0xAB, 0xE0, 0x46, 0x23, 0xC6, 0x5C, 0xB2, 0x00, 0x5A, 0x4B, 0xD5, 0x58, 0x00, 0x2D, 0x00, 0xD1, ++0xA9, 0xE0, 0x43, 0x68, 0x02, 0x3B, 0x1B, 0x01, 0x1B, 0x09, 0xC3, 0x62, 0x28, 0x30, 0xD2, 0xF7, 0xE9, 0xFD, 0x62, 0x68, ++0x61, 0x6B, 0x8A, 0x42, 0x13, 0xD0, 0x45, 0x23, 0xE3, 0x5C, 0x5B, 0x00, 0x5B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x9A, 0x42, ++0x0B, 0xD0, 0x4F, 0x4B, 0x9B, 0x7A, 0xA3, 0x75, 0x4A, 0x23, 0xE3, 0x5C, 0x03, 0x2B, 0x00, 0xD0, 0x8D, 0xE0, 0x47, 0x33, ++0x00, 0x22, 0xE2, 0x54, 0x89, 0xE0, 0x4A, 0x4B, 0x00, 0x93, 0x01, 0x92, 0xA3, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1E, 0x76, ++0x47, 0x23, 0xE0, 0x5C, 0x03, 0x01, 0x33, 0x43, 0x04, 0x93, 0x00, 0x23, 0x9C, 0x46, 0x03, 0x93, 0xA7, 0x7D, 0x6B, 0x46, ++0x1F, 0x75, 0x67, 0x46, 0x5F, 0x75, 0x9F, 0x75, 0x8A, 0x42, 0x00, 0xD1, 0x73, 0xE0, 0x10, 0x23, 0x6A, 0x46, 0xD3, 0x75, ++0x0C, 0x3B, 0x6A, 0x46, 0x93, 0x76, 0xD0, 0x76, 0x01, 0x23, 0x53, 0x76, 0x68, 0x46, 0xD3, 0xF7, 0x9B, 0xF8, 0x48, 0x22, ++0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x01, 0x21, 0x63, 0x68, 0x62, 0x6B, 0x93, 0x42, 0x35, 0xD0, 0x47, 0x23, 0xE3, 0x5C, ++0x33, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x5B, 0x01, 0x1A, 0x68, 0x32, 0x48, 0x02, 0x40, 0x09, 0x04, 0x0A, 0x43, 0x1A, 0x60, ++0x9F, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0xB6, 0xD1, 0x2B, 0x6D, 0x5F, 0x1C, 0x7F, 0x08, 0xAB, 0x6F, 0x9B, 0xB2, 0x62, 0x22, ++0x56, 0x43, 0x2B, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0xAB, 0x6F, 0x1B, 0x0C, 0x29, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0x80, 0x23, ++0x9B, 0x01, 0x9F, 0x42, 0x2B, 0xD3, 0x27, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0xF9, 0xF8, 0x00, 0x29, 0x19, 0xD0, 0x25, 0x4B, ++0x9C, 0x46, 0x66, 0x44, 0x22, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0x6A, 0xF8, 0x01, 0x30, 0x22, 0x4B, 0x03, 0x43, 0x9B, 0xB2, ++0x33, 0x80, 0x90, 0xE7, 0x20, 0x4B, 0x2A, 0x6D, 0x9A, 0x42, 0xC5, 0xD8, 0x4A, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0xC1, 0xD1, ++0x44, 0x33, 0xE1, 0x5C, 0x01, 0x31, 0xC9, 0xB2, 0xBC, 0xE7, 0x18, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0x15, 0x49, 0x38, 0x00, ++0xD4, 0xF7, 0x50, 0xF8, 0x15, 0x4B, 0x03, 0x43, 0x9B, 0xB2, 0x33, 0x80, 0x77, 0xE7, 0x01, 0x37, 0x7F, 0x08, 0xBF, 0xB2, ++0x10, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0x37, 0x80, 0x6F, 0xE7, 0x11, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0x09, 0xB0, 0xF0, 0xBD, 0x0F, 0x23, 0x6A, 0x46, 0xD3, 0x75, 0x0D, 0x3B, 0x8A, 0xE7, 0x38, 0x27, 0x16, 0x00, ++0x7C, 0x91, 0x0D, 0x00, 0x5D, 0x74, 0x0B, 0x00, 0x2F, 0x00, 0x03, 0x02, 0xFF, 0xFF, 0x00, 0xFF, 0xFA, 0x64, 0x61, 0x40, ++0xFC, 0x64, 0x61, 0x40, 0x71, 0x02, 0x00, 0x00, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0xE1, 0x04, 0x00, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x06, 0x00, 0x14, 0x4B, 0x1D, 0x68, 0x00, 0x2D, 0x05, 0xD1, 0x5D, 0x68, 0x00, 0x2D, ++0x02, 0xD1, 0x00, 0x24, 0x20, 0x00, 0xF8, 0xBD, 0xAB, 0x68, 0x2A, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x00, 0x0E, 0x49, ++0x18, 0x00, 0xD4, 0xF7, 0x09, 0xF8, 0x6C, 0x6B, 0x04, 0x19, 0x0B, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0x89, 0xF8, 0xB3, 0x68, ++0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x64, 0x18, 0xB1, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, 0xE3, 0xD0, ++0x20, 0x00, 0xFC, 0xF7, 0x63, 0xFF, 0x04, 0x00, 0xDE, 0xE7, 0xC0, 0x46, 0x54, 0x27, 0x16, 0x00, 0x71, 0x02, 0x00, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0xB0, 0xBD, 0x4B, 0x1C, 0x68, 0xA1, 0x46, ++0xBC, 0x4B, 0xA3, 0x82, 0x4C, 0x23, 0xE3, 0x5A, 0x5B, 0x00, 0x62, 0x6C, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, ++0xE3, 0x60, 0xA7, 0xF7, 0x5D, 0xF9, 0x04, 0x90, 0xB6, 0x4B, 0x1B, 0x68, 0x01, 0x93, 0xB6, 0x4B, 0x1B, 0x68, 0x02, 0x93, ++0xB5, 0x4B, 0x1B, 0x68, 0x07, 0x93, 0xB5, 0x4B, 0x1B, 0x68, 0x06, 0x93, 0x00, 0x25, 0x00, 0x20, 0x00, 0x27, 0x00, 0x23, ++0x03, 0x93, 0x00, 0x26, 0xB1, 0x4B, 0x98, 0x46, 0xA1, 0x23, 0x9A, 0x46, 0x02, 0x3B, 0x9B, 0x46, 0x0F, 0xE0, 0x01, 0x37, ++0xFF, 0xB2, 0xAF, 0x22, 0x9E, 0x5C, 0x86, 0x19, 0xF6, 0xB2, 0x48, 0x33, 0x18, 0x00, 0x80, 0xF7, 0x5F, 0xFA, 0x30, 0x18, ++0xC0, 0xB2, 0x01, 0x26, 0x01, 0x35, 0x07, 0x2D, 0x0E, 0xD0, 0xAB, 0x00, 0x42, 0x46, 0x9B, 0x58, 0x00, 0x2B, 0xF7, 0xD0, ++0x52, 0x46, 0x9A, 0x5C, 0x00, 0x2A, 0xF3, 0xD1, 0x5A, 0x46, 0x9A, 0x5C, 0x01, 0x2A, 0xE2, 0xD1, 0x03, 0x92, 0xE0, 0xE7, ++0x9F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x00, 0x23, 0x01, 0x32, 0xBA, 0x42, 0x5B, 0x41, 0x02, 0x33, 0x9C, 0x4A, 0x13, 0x70, ++0x83, 0x42, 0x08, 0xD8, 0x00, 0x22, 0x03, 0x28, 0x01, 0xD9, 0xC2, 0x1E, 0xD2, 0xB2, 0xC0, 0x1A, 0x10, 0x18, 0x96, 0x4B, ++0x18, 0x70, 0x50, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x95, 0x4B, 0x19, 0x00, 0x41, 0x31, 0xFF, 0x31, 0x00, 0x25, 0x04, 0xE0, ++0x01, 0x35, 0xED, 0xB2, 0x40, 0x33, 0x8B, 0x42, 0x07, 0xD0, 0x1A, 0x78, 0x09, 0x2A, 0xF9, 0xD1, 0x00, 0x2F, 0xF5, 0xD0, ++0x01, 0x37, 0xFF, 0xB2, 0xF2, 0xE7, 0xB0, 0xF7, 0x5F, 0xFA, 0x05, 0x90, 0x80, 0x46, 0x02, 0x9B, 0x01, 0x9A, 0x13, 0x43, ++0x5A, 0x1E, 0x93, 0x41, 0xDB, 0xB2, 0x9B, 0x46, 0x87, 0x4B, 0x1B, 0x78, 0x9A, 0x46, 0x00, 0x2B, 0x00, 0xD1, 0x79, 0xE0, ++0x85, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x28, 0xD9, 0x02, 0x2B, 0x64, 0xD0, 0x8C, 0xF7, 0xDC, 0xF8, 0x82, 0x46, 0x00, 0x28, ++0x00, 0xD1, 0x1B, 0xE2, 0x00, 0x23, 0x9A, 0x46, 0x7F, 0x4B, 0x23, 0x64, 0x02, 0x22, 0x62, 0x63, 0xFA, 0x22, 0x92, 0x01, ++0xA2, 0x62, 0x19, 0x00, 0x23, 0x61, 0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x77, 0xE0, 0xA3, 0x6A, 0x62, 0x6B, 0x98, 0x1A, ++0x40, 0x00, 0x04, 0x9B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x01, 0x2D, 0x00, 0xD1, 0x84, 0xE1, ++0x00, 0x22, 0x20, 0x00, 0xFC, 0xF7, 0x9A, 0xFF, 0x11, 0xE0, 0x71, 0x4B, 0x23, 0x64, 0x80, 0x22, 0x62, 0x63, 0xA2, 0x62, ++0x6C, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x16, 0x22, 0xA2, 0x75, 0x23, 0x61, 0x04, 0x98, 0x2C, 0x30, 0x00, 0x01, 0x00, 0x09, ++0x60, 0x60, 0x00, 0x23, 0x9A, 0x46, 0x69, 0x4E, 0x4C, 0x25, 0x69, 0x4F, 0x48, 0x46, 0xD1, 0xF7, 0x33, 0xFF, 0x00, 0x28, ++0x00, 0xD1, 0xB0, 0xE1, 0x31, 0x00, 0x20, 0x69, 0xD3, 0xF7, 0x16, 0xFF, 0x63, 0x68, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x01, ++0x00, 0x09, 0x60, 0x60, 0x63, 0x5B, 0x5B, 0x00, 0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x60, ++0xA3, 0x7D, 0x5D, 0x4A, 0xD2, 0x78, 0x9B, 0x18, 0xA3, 0x75, 0x59, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0xBE, 0x42, 0xDD, 0xD1, ++0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x56, 0x4B, 0x1B, 0x68, 0x5B, 0x00, ++0x23, 0x64, 0x02, 0x23, 0x63, 0x63, 0x4E, 0x33, 0xA3, 0x62, 0x4C, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0x49, 0x4B, 0x00, 0x22, ++0x1A, 0x70, 0x8B, 0xE7, 0xFD, 0xF7, 0x12, 0xF8, 0x00, 0x28, 0x04, 0xD1, 0x4D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x00, 0xD1, ++0x11, 0xE1, 0x43, 0x46, 0x00, 0x2B, 0x2C, 0xD0, 0x4A, 0x4B, 0x23, 0x64, 0x04, 0x23, 0x63, 0x63, 0x08, 0x33, 0xA3, 0x62, ++0x8C, 0xF7, 0x56, 0xF8, 0x00, 0x28, 0x00, 0xD0, 0x7C, 0xE7, 0x23, 0x6C, 0x23, 0x61, 0x20, 0x00, 0xFF, 0xF7, 0xAE, 0xFE, ++0x53, 0x46, 0x00, 0x2B, 0x00, 0xD1, 0x95, 0xE1, 0xC0, 0x30, 0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x18, 0x26, 0x4F, 0x46, ++0x65, 0x68, 0x00, 0x22, 0x21, 0x69, 0x38, 0x00, 0xFC, 0xF7, 0x20, 0xFF, 0x63, 0x68, 0xAB, 0x42, 0x00, 0xD1, 0x4A, 0xE1, ++0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x18, 0x36, 0x90, 0x2E, 0xEE, 0xD1, 0xB9, 0x46, 0x8B, 0xE7, 0x5B, 0x46, ++0x00, 0x2B, 0x21, 0xD0, 0x33, 0x4B, 0x1B, 0x68, 0x5B, 0x00, 0x23, 0x64, 0xE3, 0x6B, 0x63, 0x63, 0x23, 0x6B, 0xA3, 0x62, ++0x03, 0x9B, 0x00, 0x2B, 0x05, 0xD0, 0x2F, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0x46, 0x33, 0xA3, 0x62, 0xB2, 0x46, ++0x00, 0x2E, 0x00, 0xD1, 0xD4, 0xE0, 0x05, 0x9A, 0x92, 0x46, 0x01, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0xCE, 0xE0, 0x28, 0x4B, ++0x1B, 0x68, 0xA1, 0x6A, 0x8C, 0x46, 0x63, 0x44, 0xA3, 0x62, 0xC7, 0xE0, 0x15, 0x4B, 0x1B, 0x78, 0x5A, 0x00, 0x9B, 0x18, ++0x5B, 0x00, 0xDB, 0xB2, 0x01, 0x2F, 0x49, 0xD9, 0x21, 0x4A, 0x22, 0x64, 0x1A, 0x22, 0x62, 0x63, 0x2C, 0x32, 0xA2, 0x62, ++0x00, 0x2B, 0x03, 0xD0, 0x1E, 0x4B, 0x23, 0x64, 0x14, 0x23, 0x63, 0x63, 0x00, 0x2D, 0x03, 0xD0, 0x1C, 0x4B, 0x23, 0x64, ++0x10, 0x23, 0x63, 0x63, 0x63, 0x6B, 0xA3, 0x62, 0xDA, 0x46, 0xA9, 0xE0, 0xF8, 0xE6, 0x10, 0x00, 0x00, 0xA0, 0xFF, 0xFF, ++0x24, 0x27, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0x28, 0x27, 0x16, 0x00, 0x20, 0x27, 0x16, 0x00, 0x38, 0x27, 0x16, 0x00, ++0xB1, 0xE6, 0x10, 0x00, 0xD1, 0xE6, 0x10, 0x00, 0x70, 0xA6, 0x16, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, ++0xC4, 0x09, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, ++0x04, 0xE2, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x08, 0xE2, 0x10, 0x00, 0xDC, 0x82, 0x00, 0x00, ++0x14, 0xE2, 0x10, 0x00, 0xE8, 0x80, 0x00, 0x00, 0xF6, 0x54, 0x00, 0x00, 0xF2, 0x2B, 0x00, 0x00, 0x85, 0x4A, 0x5A, 0x43, ++0x03, 0x99, 0x00, 0x29, 0x33, 0xD0, 0x84, 0x49, 0x09, 0x68, 0x49, 0x00, 0x8A, 0x42, 0x29, 0xD8, 0x8A, 0x1A, 0x22, 0x64, ++0x28, 0x22, 0xD3, 0x1A, 0x63, 0x63, 0xE3, 0x6A, 0xA3, 0x62, 0x7F, 0x4B, 0x22, 0x6C, 0x9A, 0x42, 0x4B, 0xD9, 0xDA, 0x46, ++0x00, 0x2F, 0x5D, 0xD0, 0x07, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0xC4, 0xE0, 0x59, 0x68, 0x06, 0x9A, 0x00, 0x2A, 0x00, 0xD1, ++0xC4, 0xE0, 0x78, 0x4B, 0x99, 0x42, 0x00, 0xD1, 0xBE, 0xE0, 0x52, 0x68, 0x53, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x20, ++0x00, 0x05, 0x83, 0x42, 0x00, 0xD8, 0xBA, 0xE0, 0x8B, 0x1A, 0x1B, 0x01, 0x00, 0xD1, 0xB6, 0xE0, 0x11, 0x00, 0xB1, 0xE0, ++0x6F, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0xD5, 0xE7, 0x00, 0x2D, 0x0D, 0xD0, 0x6D, 0x4B, 0x23, 0x64, 0x10, 0x23, ++0x63, 0x63, 0xA3, 0x62, 0x01, 0x2D, 0x02, 0xD0, 0x01, 0x23, 0x9A, 0x46, 0xD0, 0xE7, 0x40, 0x33, 0x01, 0x22, 0xE2, 0x54, ++0xF8, 0xE7, 0x67, 0x49, 0x09, 0x68, 0x49, 0x00, 0x8A, 0x42, 0x0D, 0xD8, 0x8A, 0x1A, 0x22, 0x64, 0xA2, 0x6B, 0xD3, 0x1A, ++0x63, 0x63, 0xE3, 0x6A, 0xA3, 0x62, 0x5D, 0x4B, 0x22, 0x6C, 0x9A, 0x42, 0x09, 0xD9, 0x03, 0x9B, 0x9A, 0x46, 0xB9, 0xE7, ++0x5B, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0xF1, 0xE7, 0x00, 0x2D, 0x05, 0xD1, 0x58, 0x4B, 0x23, 0x64, 0x1A, 0x23, ++0x63, 0x63, 0xDA, 0x46, 0xAC, 0xE7, 0xDA, 0x46, 0xAA, 0xE7, 0x50, 0x4B, 0x23, 0x64, 0x02, 0x23, 0x63, 0x63, 0x43, 0x46, ++0x00, 0x2B, 0x0B, 0xD1, 0x30, 0x33, 0xA3, 0x62, 0x2F, 0x3B, 0x9A, 0x46, 0x8B, 0xF7, 0x42, 0xFF, 0x00, 0x28, 0x00, 0xD0, ++0x68, 0xE6, 0x21, 0x6C, 0x21, 0x61, 0x72, 0xE6, 0xC0, 0x23, 0xA3, 0x62, 0x05, 0x9B, 0x9A, 0x46, 0xDE, 0xE6, 0x00, 0x23, ++0x08, 0x93, 0x09, 0x93, 0x20, 0x1D, 0x23, 0x00, 0x08, 0xAA, 0x09, 0xA9, 0xFC, 0xF7, 0x72, 0xFD, 0x09, 0x9B, 0x00, 0x2B, ++0x04, 0xD0, 0x22, 0x69, 0x9A, 0x42, 0x00, 0xD9, 0x1A, 0x00, 0x22, 0x61, 0x00, 0x2F, 0x07, 0xD0, 0x08, 0x9B, 0x5B, 0x00, ++0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x63, 0x6B, 0x02, 0x2B, 0x1E, 0xD0, 0x53, 0x46, ++0x00, 0x2B, 0x04, 0xD1, 0x3A, 0x4B, 0x08, 0x9A, 0x53, 0x43, 0x23, 0x61, 0x23, 0x64, 0x03, 0x26, 0x4F, 0x46, 0x65, 0x68, ++0x00, 0x22, 0x21, 0x69, 0x38, 0x00, 0xFC, 0xF7, 0xEB, 0xFD, 0x63, 0x68, 0xAB, 0x42, 0x18, 0xD0, 0x08, 0x9B, 0x9C, 0x46, ++0x65, 0x44, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xEC, 0xD1, 0xB9, 0x46, 0x54, 0xE6, ++0x08, 0x9A, 0x53, 0x00, 0x9B, 0x18, 0x5B, 0x00, 0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, ++0xD5, 0xE7, 0xB9, 0x46, 0x47, 0xE6, 0xB9, 0x46, 0x45, 0xE6, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xA3, 0x7D, 0x10, 0x2B, ++0x00, 0xD9, 0x63, 0xE6, 0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x5F, 0xE6, 0x53, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x5B, 0xE6, ++0x11, 0x33, 0xA3, 0x75, 0x58, 0xE6, 0x06, 0x9B, 0x00, 0x2B, 0x91, 0xD0, 0x06, 0x9B, 0x59, 0x68, 0x15, 0x4B, 0x99, 0x42, ++0x8C, 0xD0, 0x63, 0x6B, 0x1A, 0x00, 0x28, 0x32, 0x52, 0x00, 0xA0, 0x6A, 0xC3, 0x1A, 0x5B, 0x00, 0x04, 0x98, 0x84, 0x46, ++0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x9A, 0x42, 0x00, 0xD2, 0x7A, 0xE7, 0x0C, 0x4B, ++0x23, 0x64, 0x77, 0xE7, 0x21, 0x6C, 0x21, 0x61, 0x43, 0x46, 0x00, 0x2B, 0x04, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x14, 0xFD, ++0x60, 0x60, 0x6B, 0xE6, 0x05, 0x9B, 0x9A, 0x46, 0xE5, 0xE5, 0xC0, 0x46, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xE2, 0x10, 0x00, ++0xE7, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xE8, 0x80, 0x00, 0x00, 0xF2, 0x2B, 0x00, 0x00, 0x04, 0xE2, 0x10, 0x00, ++0xA9, 0x03, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x1A, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x19, 0x4B, ++0x9B, 0x78, 0x83, 0x75, 0xFC, 0xF7, 0x06, 0xFE, 0x05, 0x00, 0x02, 0x21, 0x01, 0x20, 0xFC, 0xF7, 0xC3, 0xFE, 0x06, 0x00, ++0x00, 0x2D, 0x04, 0xD0, 0x11, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x4E, 0x23, 0xE3, 0x5C, 0x02, 0x2B, ++0x0E, 0xD0, 0xA6, 0xF7, 0x83, 0xFE, 0x60, 0x64, 0xFF, 0xF7, 0x0C, 0xFD, 0x00, 0x2E, 0x0E, 0xD0, 0x00, 0x2D, 0x04, 0xD0, ++0x08, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x70, 0xBD, 0x07, 0x4C, 0x20, 0x68, 0x7D, 0xF7, 0xB8, 0xFB, ++0x00, 0x23, 0x23, 0x60, 0xEE, 0xE7, 0x02, 0x21, 0x00, 0x20, 0xFC, 0xF7, 0x9D, 0xFE, 0xEB, 0xE7, 0xFC, 0x00, 0x60, 0x40, ++0x7C, 0x91, 0x0D, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x10, 0xBD, ++0x00, 0x21, 0xD1, 0xF7, 0x8F, 0xFE, 0xFF, 0xF7, 0xE5, 0xFC, 0xF8, 0xE7, 0x10, 0xB5, 0xA6, 0xF7, 0x55, 0xFE, 0x22, 0x4B, ++0x5A, 0x68, 0x92, 0x01, 0x1B, 0x68, 0xC0, 0x1A, 0x00, 0x01, 0x01, 0x09, 0x40, 0x00, 0x43, 0x1A, 0x9B, 0x00, 0x5B, 0x18, ++0x99, 0x00, 0x5B, 0x18, 0x9A, 0x42, 0x20, 0xD3, 0xD3, 0x1A, 0x1B, 0x4C, 0x9C, 0x42, 0xA4, 0x41, 0x64, 0x42, 0x1A, 0x4B, ++0x1A, 0x4A, 0x1A, 0x60, 0xD1, 0xF7, 0xC0, 0xFE, 0x00, 0x28, 0x0A, 0xD0, 0x00, 0x2C, 0x19, 0xD0, 0x17, 0x4B, 0x80, 0x22, ++0x12, 0x05, 0x1A, 0x60, 0x16, 0x48, 0x7F, 0xF7, 0x05, 0xFB, 0x10, 0xBD, 0x00, 0x24, 0x11, 0x4B, 0x1B, 0x68, 0x9B, 0x68, ++0x00, 0x2B, 0xF1, 0xD0, 0x12, 0x4A, 0xDB, 0x69, 0x93, 0x42, 0xEB, 0xD1, 0xEC, 0xE7, 0x0C, 0x4B, 0x0C, 0x4A, 0x1A, 0x60, ++0xD1, 0xF7, 0xA4, 0xFE, 0x00, 0x28, 0xED, 0xD0, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x0D, 0x4B, 0x00, 0x22, 0x1A, 0x70, ++0x0C, 0x4B, 0x18, 0x68, 0x00, 0x28, 0xE2, 0xD0, 0xFF, 0xF7, 0xAE, 0xFF, 0xDF, 0xE7, 0xC0, 0x46, 0x6C, 0xE6, 0x10, 0x00, ++0xFF, 0x70, 0x02, 0x00, 0x10, 0xE7, 0x10, 0x00, 0x64, 0x2A, 0x16, 0x00, 0x00, 0x41, 0x04, 0x40, 0x74, 0xD1, 0x10, 0x00, ++0xC9, 0x1F, 0x10, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0xF8, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x49, 0x4B, 0x1C, 0x68, 0xA4, 0x04, ++0xA4, 0x0E, 0x20, 0x00, 0x50, 0x43, 0x43, 0x01, 0x1B, 0x1A, 0x9B, 0x00, 0x1B, 0x18, 0x98, 0x00, 0x18, 0x18, 0x00, 0x02, ++0xD3, 0xF7, 0x5E, 0xFC, 0x81, 0x46, 0x03, 0x0A, 0x9B, 0x46, 0x29, 0x00, 0x80, 0x20, 0xC0, 0x00, 0xD3, 0xF7, 0x56, 0xFC, ++0x03, 0x00, 0x6B, 0x43, 0x9A, 0x46, 0xFF, 0x21, 0x4B, 0x46, 0x19, 0x40, 0x69, 0x43, 0x09, 0x0A, 0x48, 0x43, 0x53, 0x46, ++0x1B, 0x1A, 0x98, 0x46, 0x23, 0x01, 0x1B, 0x19, 0x9B, 0x00, 0x99, 0x46, 0xA1, 0x44, 0x53, 0x46, 0x00, 0x2B, 0x05, 0xD1, ++0x34, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x78, 0x01, 0xC0, 0x1B, 0x80, 0x00, 0xC7, 0x19, ++0xB8, 0x00, 0x38, 0x18, 0x29, 0x00, 0xD3, 0xF7, 0x33, 0xFC, 0x44, 0x43, 0x27, 0x00, 0x65, 0x09, 0x73, 0x01, 0x2C, 0x4A, ++0x9A, 0x18, 0x11, 0x68, 0x2B, 0x4A, 0x11, 0x60, 0x2B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x68, 0x2A, 0x4B, 0x1A, 0x60, ++0x2A, 0x4B, 0x5A, 0x46, 0x1A, 0x60, 0x51, 0x46, 0x48, 0x46, 0xD3, 0xF7, 0xA3, 0xFC, 0x09, 0x05, 0x43, 0x46, 0x19, 0x43, ++0x26, 0x4B, 0x19, 0x60, 0x26, 0x4B, 0x52, 0x46, 0x1A, 0x60, 0x26, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x25, 0x4B, 0x9E, 0x22, ++0xFF, 0x32, 0x99, 0x5C, 0x09, 0x02, 0x01, 0x3A, 0x9A, 0x5C, 0x0A, 0x43, 0x12, 0x04, 0x9C, 0x21, 0xFF, 0x31, 0x58, 0x5C, ++0x00, 0x02, 0x01, 0x39, 0x59, 0x5C, 0x01, 0x43, 0x0A, 0x43, 0x1E, 0x49, 0x0A, 0x60, 0xA0, 0x22, 0xFF, 0x32, 0x98, 0x5C, ++0x00, 0x02, 0x01, 0x3A, 0x9C, 0x5C, 0x04, 0x43, 0x24, 0x04, 0x20, 0x00, 0x28, 0x43, 0x01, 0x35, 0x6D, 0x01, 0xEC, 0x1B, ++0x24, 0x04, 0x04, 0x43, 0x16, 0x4A, 0x14, 0x60, 0x9A, 0x22, 0xFF, 0x32, 0x98, 0x5C, 0x00, 0x02, 0x01, 0x3A, 0x9B, 0x5C, ++0x03, 0x43, 0x36, 0x02, 0x1E, 0x43, 0x01, 0x20, 0x06, 0x43, 0x11, 0x4B, 0x1E, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, 0xC0, 0x46, 0x08, 0x04, 0x60, 0x40, 0x28, 0x19, 0x16, 0x00, 0xDC, 0x05, 0x60, 0x40, ++0x5C, 0x06, 0x60, 0x40, 0xD8, 0x05, 0x60, 0x40, 0x60, 0x06, 0x60, 0x40, 0x50, 0x06, 0x60, 0x40, 0x54, 0x06, 0x60, 0x40, ++0x58, 0x06, 0x60, 0x40, 0x4C, 0x06, 0x60, 0x40, 0x20, 0xA3, 0x16, 0x00, 0x44, 0x06, 0x60, 0x40, 0x48, 0x06, 0x60, 0x40, ++0x40, 0x06, 0x60, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8F, 0xB0, 0x80, 0x46, ++0x0E, 0x00, 0x15, 0x00, 0x03, 0x93, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x17, 0x00, 0x1F, 0x40, 0x1A, 0x42, 0x00, 0xD0, ++0xF6, 0xE2, 0x72, 0xB6, 0x00, 0x21, 0x5C, 0x20, 0x7D, 0xF7, 0xCE, 0xF9, 0x04, 0x1E, 0x00, 0xD1, 0x25, 0xE3, 0x00, 0x20, ++0x00, 0x2F, 0x00, 0xD0, 0xF1, 0xE2, 0x62, 0xB6, 0x00, 0x28, 0x00, 0xD1, 0xED, 0xE2, 0x0F, 0xB0, 0x3C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xDE, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x0C, 0x20, 0x00, 0x2F, 0xEF, 0xD1, 0xEA, 0xE7, 0x00, 0x23, 0x06, 0x93, 0xEC, 0xE2, 0x01, 0x23, 0x06, 0x93, 0xE9, 0xE2, ++0x00, 0x23, 0x5B, 0x00, 0xD6, 0x4A, 0xD3, 0x18, 0x5F, 0x78, 0xBA, 0x46, 0xBF, 0xE0, 0x2F, 0x7B, 0xD4, 0x4B, 0x19, 0x00, ++0x00, 0x22, 0x08, 0x78, 0xB8, 0x42, 0x00, 0xD1, 0xAD, 0xE0, 0x01, 0x32, 0x02, 0x31, 0x08, 0x2A, 0xF7, 0xD1, 0x02, 0x27, ++0x68, 0x7B, 0x00, 0x22, 0x19, 0x78, 0x81, 0x42, 0x00, 0xD1, 0xA7, 0xE0, 0x01, 0x32, 0x02, 0x33, 0x08, 0x2A, 0xF7, 0xD1, ++0x02, 0x23, 0x9A, 0x46, 0x09, 0x2F, 0x05, 0xD9, 0xC5, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x07, 0x97, 0xD3, 0x46, 0xC4, 0x4A, 0x7B, 0x00, 0xDF, 0x19, 0xD7, 0x19, 0x53, 0x46, 0x5B, 0x00, 0x53, 0x44, 0xD2, 0x18, ++0xBF, 0x78, 0x93, 0x78, 0xFF, 0x18, 0xFB, 0xB2, 0x1F, 0x00, 0x05, 0x93, 0x28, 0x7C, 0x19, 0x00, 0xD3, 0xF7, 0x48, 0xFB, ++0xC0, 0xB2, 0xBC, 0x4B, 0x63, 0x62, 0xBC, 0x4B, 0xE3, 0x61, 0xBC, 0x4B, 0x23, 0x62, 0x03, 0x23, 0x23, 0x76, 0xBB, 0x4B, ++0x9B, 0x7A, 0xA3, 0x75, 0xBA, 0x4A, 0x9F, 0x23, 0x9B, 0x00, 0xD2, 0x5C, 0x00, 0x23, 0x00, 0x2A, 0x02, 0xD1, 0x7B, 0x00, ++0x03, 0x33, 0xDB, 0xB2, 0xE3, 0x75, 0x00, 0x23, 0xA3, 0x82, 0x06, 0x33, 0x63, 0x76, 0x40, 0x33, 0x42, 0x46, 0xE2, 0x54, ++0x01, 0x33, 0xE6, 0x54, 0xEB, 0x88, 0x23, 0x87, 0x2B, 0x89, 0x63, 0x87, 0xAA, 0x7A, 0x3D, 0x23, 0xE2, 0x54, 0xEA, 0x7A, ++0x01, 0x33, 0xE2, 0x54, 0x2A, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0x6A, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0xAA, 0x7B, 0x01, 0x33, ++0xE2, 0x54, 0xEA, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0x6A, 0x7C, 0x01, 0x33, 0xE2, 0x54, 0x01, 0x33, 0xE0, 0x54, 0x9B, 0x4A, ++0xB0, 0x33, 0xD3, 0x58, 0x23, 0x63, 0xAA, 0x78, 0x4B, 0x23, 0xE2, 0x54, 0x2B, 0x7C, 0x05, 0x99, 0x8C, 0x46, 0x63, 0x44, ++0xEA, 0x7B, 0x9B, 0x1A, 0x5A, 0x42, 0x53, 0x41, 0x49, 0x22, 0xA3, 0x54, 0x45, 0x23, 0xE1, 0x54, 0x13, 0x33, 0x08, 0x9A, ++0xE2, 0x54, 0x01, 0x22, 0x31, 0x00, 0x01, 0x20, 0xA6, 0xF7, 0xF8, 0xF9, 0x03, 0x9B, 0x00, 0x2B, 0x00, 0xD0, 0x98, 0xE1, ++0x06, 0x99, 0x01, 0x31, 0x2A, 0x89, 0x4A, 0x43, 0xD3, 0xB2, 0x0C, 0x93, 0xEB, 0x88, 0x4B, 0x43, 0xDB, 0xB2, 0x0D, 0x93, ++0x2B, 0x79, 0x00, 0x22, 0x92, 0x46, 0x00, 0x2B, 0x02, 0xD0, 0xEA, 0x78, 0x04, 0x2A, 0x26, 0xD0, 0x68, 0x78, 0x03, 0x28, ++0x33, 0xD8, 0x2B, 0x78, 0x04, 0x2B, 0x30, 0xD8, 0x9B, 0x00, 0x88, 0x4A, 0xD3, 0x18, 0x1A, 0x5C, 0x0F, 0x23, 0x13, 0x40, ++0x0A, 0x93, 0x53, 0x11, 0x01, 0x21, 0x0B, 0x40, 0x03, 0x93, 0x12, 0x11, 0x11, 0x40, 0x0B, 0x91, 0x2C, 0xE0, 0x52, 0x00, ++0x79, 0x49, 0x8A, 0x18, 0x57, 0x78, 0x51, 0xE7, 0x52, 0x00, 0x77, 0x4B, 0x9A, 0x18, 0x53, 0x78, 0x9A, 0x46, 0x09, 0x2F, ++0x00, 0xD9, 0x57, 0xE7, 0x53, 0x46, 0x09, 0x2B, 0x00, 0xD9, 0x53, 0xE7, 0x58, 0xE7, 0x01, 0x2B, 0x0A, 0xD0, 0x02, 0x3B, ++0x5A, 0x42, 0x53, 0x41, 0x5B, 0x42, 0x76, 0x4A, 0x13, 0x40, 0x9A, 0x46, 0x75, 0x4B, 0x9C, 0x46, 0xE2, 0x44, 0xCB, 0xE7, ++0x74, 0x4B, 0x9A, 0x46, 0xC8, 0xE7, 0x29, 0x78, 0x66, 0x4B, 0xDB, 0x6E, 0x98, 0x46, 0x00, 0x23, 0x00, 0x22, 0xC0, 0x47, ++0x03, 0x9B, 0x0B, 0x93, 0x00, 0x23, 0x0A, 0x93, 0x2B, 0x79, 0x0E, 0x2B, 0x00, 0xD1, 0xBC, 0xE0, 0x00, 0xD9, 0xAC, 0xE0, ++0x00, 0x22, 0x06, 0x92, 0x08, 0x2B, 0x04, 0xD0, 0x01, 0x32, 0x06, 0x92, 0x0D, 0x2B, 0x00, 0xD0, 0xA8, 0xE0, 0xEB, 0x78, ++0x5A, 0x1E, 0x03, 0x2A, 0x00, 0xD9, 0xE3, 0xE0, 0xD3, 0xB2, 0x08, 0x93, 0x63, 0x4A, 0x13, 0x68, 0x63, 0x49, 0x19, 0x40, ++0x80, 0x23, 0x9B, 0x02, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x61, 0x49, 0x0B, 0x40, 0x80, 0x21, 0x49, 0x02, 0x8C, 0x46, ++0x0B, 0x43, 0x13, 0x60, 0x73, 0x01, 0x98, 0x46, 0x5D, 0x4A, 0x42, 0x44, 0x85, 0x23, 0x1B, 0x04, 0x51, 0x46, 0x0B, 0x43, ++0x13, 0x60, 0x5B, 0x4B, 0x43, 0x44, 0x9A, 0x46, 0x4B, 0x4A, 0x5B, 0x46, 0x59, 0x00, 0x59, 0x44, 0x53, 0x18, 0x5B, 0x78, ++0x1B, 0x01, 0xA8, 0x7A, 0x03, 0x43, 0xE8, 0x7A, 0x02, 0x38, 0x07, 0x00, 0x78, 0x42, 0x78, 0x41, 0xC0, 0x00, 0x03, 0x43, ++0x07, 0x9F, 0x78, 0x00, 0xBB, 0x46, 0x58, 0x44, 0x17, 0x18, 0x7F, 0x78, 0x7F, 0x01, 0x3B, 0x43, 0x67, 0x46, 0x3B, 0x43, ++0x57, 0x46, 0x3B, 0x60, 0x4C, 0x4B, 0x43, 0x44, 0x9A, 0x46, 0x2B, 0x89, 0x1B, 0x05, 0x9C, 0x46, 0xEB, 0x88, 0x1B, 0x01, ++0x67, 0x46, 0x3B, 0x43, 0x80, 0x5C, 0x03, 0x43, 0x88, 0x5C, 0x00, 0x04, 0x03, 0x43, 0x52, 0x46, 0x13, 0x60, 0x03, 0x9B, ++0xDB, 0x03, 0x0A, 0x9A, 0x12, 0x02, 0x13, 0x43, 0x0B, 0x9A, 0xD2, 0x01, 0x13, 0x43, 0x06, 0x9A, 0x12, 0x05, 0x13, 0x43, ++0x08, 0x9A, 0x12, 0x04, 0x13, 0x43, 0x3E, 0x4A, 0xB2, 0x18, 0x92, 0x00, 0x13, 0x60, 0xB3, 0x00, 0x3C, 0x4A, 0x9C, 0x50, ++0x4B, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x87, 0xE0, 0x32, 0x01, 0xB2, 0x18, 0xD3, 0x01, 0x9B, 0x1A, 0xF3, 0x18, ++0x37, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x9B, 0xB2, 0x36, 0x49, 0x41, 0x44, 0x0C, 0x98, 0xC2, 0x18, 0x12, 0x04, 0x13, 0x43, ++0x0B, 0x60, 0x87, 0x23, 0xDB, 0x00, 0x73, 0x43, 0x84, 0x46, 0x63, 0x44, 0x31, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x5B, 0x00, ++0x9B, 0xB2, 0x30, 0x49, 0x41, 0x44, 0x0D, 0x9A, 0x9A, 0x18, 0x92, 0xB2, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0x2D, 0x4B, ++0x43, 0x44, 0xE9, 0x7B, 0x80, 0x22, 0xD2, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x29, 0x89, 0x00, 0x29, 0x04, 0xD1, 0xEB, 0x88, ++0x01, 0x31, 0x00, 0x2B, 0x00, 0xD0, 0x19, 0x00, 0x00, 0x2E, 0x00, 0xD0, 0xDA, 0xE0, 0xEA, 0x7B, 0x89, 0xB2, 0x00, 0x20, ++0xFF, 0xF7, 0x72, 0xFD, 0xD4, 0xE0, 0x03, 0x22, 0x06, 0x92, 0x10, 0x2B, 0x00, 0xD1, 0x56, 0xE7, 0x05, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0x06, 0x93, 0x4D, 0xE7, 0x02, 0x23, 0x06, 0x93, 0x4A, 0xE7, ++0x28, 0x19, 0x16, 0x00, 0xE4, 0xDF, 0x10, 0x00, 0xD4, 0xDF, 0x10, 0x00, 0xE8, 0xDF, 0x10, 0x00, 0x69, 0xF5, 0x0A, 0x00, ++0x21, 0x61, 0x10, 0x00, 0x4D, 0xF3, 0x0A, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x08, 0xE0, 0x10, 0x00, ++0x00, 0xA0, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0xD0, 0x04, 0x60, 0x40, 0xFF, 0xFF, 0xFD, 0xFF, ++0xFF, 0xFF, 0xFE, 0xFF, 0xD4, 0x05, 0x60, 0x40, 0xE0, 0x05, 0x60, 0x40, 0xE4, 0x05, 0x60, 0x40, 0x8C, 0x01, 0x18, 0x10, ++0x54, 0x27, 0x16, 0x00, 0x5C, 0xAB, 0xFF, 0xFF, 0xD8, 0x05, 0x60, 0x40, 0xAE, 0x55, 0x00, 0x00, 0xDC, 0x05, 0x60, 0x40, ++0xD0, 0x05, 0x60, 0x40, 0x96, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0x08, 0x93, ++0x14, 0xE7, 0x42, 0x33, 0xE3, 0x5C, 0x5F, 0x1E, 0x20, 0x00, 0x50, 0x30, 0x7F, 0xF7, 0xF0, 0xFA, 0x49, 0x23, 0xE1, 0x5C, ++0xCB, 0x1C, 0xDB, 0xB2, 0x04, 0x31, 0xC9, 0xB2, 0x8B, 0x4A, 0x92, 0x46, 0x0D, 0x9A, 0x04, 0x32, 0xD2, 0xB2, 0x00, 0x92, ++0x84, 0x22, 0x50, 0x46, 0x82, 0x58, 0x93, 0x46, 0x0C, 0x9A, 0x30, 0x00, 0xD8, 0x47, 0x86, 0x4A, 0x42, 0x44, 0x00, 0x23, ++0x13, 0x60, 0x85, 0x4A, 0x42, 0x44, 0x13, 0x60, 0x19, 0x33, 0xFF, 0x33, 0x52, 0x46, 0xD0, 0x58, 0x31, 0x00, 0xD2, 0xF7, ++0x47, 0xFB, 0x81, 0x4A, 0x11, 0x68, 0x80, 0x23, 0x9B, 0x01, 0xB3, 0x40, 0x0B, 0x43, 0x13, 0x60, 0x7E, 0x4A, 0x42, 0x44, ++0xFF, 0x23, 0x3B, 0x40, 0x1F, 0x2B, 0x00, 0xD9, 0x1F, 0x23, 0x1B, 0x02, 0xE9, 0x7B, 0x0B, 0x43, 0x09, 0x99, 0x03, 0x39, ++0x48, 0x42, 0x41, 0x41, 0xC9, 0x03, 0x0B, 0x43, 0xC0, 0x21, 0xC9, 0x01, 0x0B, 0x43, 0x13, 0x60, 0x42, 0xE0, 0x75, 0x4B, ++0xF2, 0x18, 0x52, 0x01, 0x74, 0x49, 0x5B, 0x46, 0x58, 0x00, 0x58, 0x44, 0x0B, 0x18, 0x5B, 0x78, 0x1B, 0x01, 0xAF, 0x7A, ++0x1F, 0x43, 0xBC, 0x46, 0xEB, 0x7A, 0x02, 0x3B, 0x1F, 0x00, 0x7B, 0x42, 0x7B, 0x41, 0xDB, 0x00, 0x67, 0x46, 0x3B, 0x43, ++0x9A, 0x46, 0x07, 0x9F, 0x7B, 0x00, 0x98, 0x46, 0xBC, 0x46, 0xE0, 0x44, 0x8C, 0x46, 0xC4, 0x44, 0x63, 0x46, 0x5B, 0x78, ++0x5B, 0x01, 0x1F, 0x00, 0x53, 0x46, 0x1F, 0x43, 0x80, 0x23, 0x5B, 0x02, 0x3B, 0x43, 0x13, 0x60, 0x2B, 0x89, 0x1B, 0x05, ++0xED, 0x88, 0x2D, 0x01, 0x2B, 0x43, 0x45, 0x46, 0x6D, 0x5C, 0x2B, 0x43, 0x41, 0x5C, 0x09, 0x04, 0x0B, 0x43, 0x53, 0x60, ++0x31, 0x01, 0x71, 0x18, 0xCB, 0x01, 0x5B, 0x1A, 0xF3, 0x18, 0x5B, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x98, 0xB2, 0x11, 0x00, ++0x08, 0x39, 0x1B, 0x04, 0x03, 0x43, 0x0B, 0x60, 0x04, 0x3A, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x11, 0x00, ++0x19, 0x40, 0x88, 0x46, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x52, 0x4B, 0x05, 0x9A, 0x53, 0x43, 0x9B, 0xB2, 0x42, 0x22, ++0xA2, 0x5C, 0x52, 0x00, 0x44, 0x21, 0x61, 0x5C, 0x48, 0x1E, 0x81, 0x41, 0x00, 0x91, 0x31, 0x00, 0x0B, 0x20, 0xD3, 0xF7, ++0x41, 0xF8, 0x4B, 0x46, 0xDB, 0x07, 0x33, 0xD4, 0x4B, 0x46, 0x1F, 0x01, 0x3F, 0x09, 0x41, 0x23, 0xE5, 0x5C, 0x02, 0x33, ++0xE3, 0x5C, 0x9B, 0x06, 0x7F, 0x08, 0x5F, 0x40, 0x42, 0x23, 0xE3, 0x5C, 0x99, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x39, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x49, 0x46, 0x38, 0x00, 0xD3, 0xF7, 0x63, 0xF9, 0x69, 0x1A, ++0x00, 0x29, 0x21, 0xDD, 0x42, 0x23, 0xE3, 0x5C, 0xC9, 0x1A, 0x49, 0x00, 0x58, 0x00, 0x04, 0x9A, 0x94, 0x46, 0x60, 0x44, ++0x09, 0x18, 0x09, 0x01, 0x09, 0x09, 0x61, 0x63, 0x02, 0x2B, 0x02, 0xD9, 0x30, 0x00, 0x34, 0x4B, 0x98, 0x47, 0x00, 0x20, ++0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x28, 0xE5, 0x62, 0xB6, 0x26, 0xE5, 0x30, 0x4F, 0x4B, 0x46, 0x3B, 0x40, 0x1F, 0x00, ++0x04, 0x98, 0x01, 0x38, 0x00, 0x01, 0x03, 0x09, 0x04, 0x93, 0xC4, 0xE7, 0x42, 0x23, 0xE3, 0x5C, 0xC9, 0x18, 0xD9, 0xE7, ++0x00, 0x21, 0x5C, 0x20, 0x7C, 0xF7, 0xD8, 0xFE, 0x04, 0x1E, 0x00, 0xD1, 0x18, 0xE5, 0x43, 0x46, 0x9B, 0x00, 0x26, 0x4A, ++0x9F, 0x58, 0x6B, 0x78, 0x09, 0x93, 0x03, 0x2B, 0x00, 0xD1, 0x19, 0xE5, 0xAB, 0x78, 0x01, 0x2B, 0x00, 0xD1, 0x18, 0xE5, ++0x2A, 0x79, 0x08, 0x23, 0x93, 0x42, 0x9B, 0x41, 0x5B, 0x42, 0x06, 0x93, 0x06, 0x9B, 0x08, 0x93, 0xA6, 0xF7, 0x1C, 0xFA, ++0x04, 0x90, 0xBB, 0x6F, 0x81, 0x46, 0x99, 0x44, 0x5C, 0x22, 0x00, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0x67, 0xFE, 0xEB, 0x7A, ++0x00, 0x2B, 0x00, 0xD0, 0x0B, 0xE5, 0x2B, 0x7B, 0x00, 0x2B, 0x00, 0xD1, 0x00, 0xE5, 0x02, 0x22, 0x92, 0x46, 0x02, 0x27, ++0x02, 0x2B, 0x00, 0xD0, 0x22, 0xE5, 0x01, 0x3B, 0xF9, 0xE4, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0x0C, 0x20, 0xD5, 0xE4, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0xD8, 0x05, 0x60, 0x40, 0xDC, 0x05, 0x60, 0x40, ++0x0C, 0x04, 0x60, 0x40, 0xD0, 0x05, 0x60, 0x40, 0x2F, 0x00, 0x03, 0x02, 0xE8, 0xDF, 0x10, 0x00, 0x5C, 0xAB, 0xFF, 0xFF, ++0xE2, 0x04, 0x00, 0x00, 0x3D, 0xF4, 0x0A, 0x00, 0xFE, 0xFF, 0xFF, 0x0F, 0x38, 0x27, 0x16, 0x00, 0x00, 0x20, 0x70, 0x47, ++0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x5A, 0x4B, ++0x1B, 0x68, 0xDB, 0x05, 0x0B, 0xD5, 0x58, 0x49, 0x0B, 0x68, 0x5B, 0x00, 0x5B, 0x08, 0x80, 0x22, 0x12, 0x06, 0x13, 0x43, ++0x0B, 0x60, 0x0A, 0x00, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xDB, 0x53, 0x4B, 0x1B, 0x68, 0xDB, 0x05, 0x0B, 0xD5, 0x51, 0x49, ++0x0B, 0x68, 0x5B, 0x00, 0x5B, 0x08, 0x80, 0x22, 0x12, 0x06, 0x13, 0x43, 0x0B, 0x60, 0x0A, 0x00, 0x13, 0x68, 0x00, 0x2B, ++0xFC, 0xDB, 0x7A, 0xF7, 0x4F, 0xFF, 0x4B, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x09, 0xD0, 0x7C, 0xF7, 0xF5, 0xFE, 0x48, 0x4B, ++0x00, 0x22, 0x1A, 0x60, 0x47, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x46, 0x4B, 0x11, 0x22, 0x44, 0x21, ++0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x10, 0x3A, ++0x40, 0x49, 0x5A, 0x54, 0x40, 0x49, 0x5A, 0x54, 0x40, 0x4A, 0x00, 0x21, 0x99, 0x54, 0x40, 0x4B, 0x1B, 0x68, 0x01, 0x2B, ++0x47, 0xD9, 0x39, 0x4B, 0x1A, 0x68, 0x08, 0x21, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x01, 0x20, 0x82, 0x43, 0x1A, 0x60, ++0x1A, 0x68, 0x06, 0x39, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x38, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x12, 0x04, ++0x12, 0x0C, 0xB0, 0x21, 0x49, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x34, 0x4A, 0xA0, 0x23, 0x9B, 0x00, 0xD0, 0x54, 0x29, 0x4A, ++0x13, 0x68, 0x0F, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x30, 0x4A, 0x13, 0x68, 0x30, 0x49, 0x19, 0x40, 0xA0, 0x23, 0xDB, 0x03, ++0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0xFF, 0x21, 0x8B, 0x43, 0xAF, 0x39, 0x0B, 0x43, 0x13, 0x60, 0x2B, 0x4B, 0x2C, 0x4A, ++0x9A, 0x60, 0x2C, 0x4A, 0xDA, 0x60, 0x2C, 0x4A, 0x5A, 0x61, 0x2C, 0x4A, 0x9A, 0x61, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, ++0x00, 0x23, 0x2A, 0x4A, 0x13, 0x60, 0x2A, 0x4A, 0x13, 0x60, 0x2A, 0x4A, 0x13, 0x60, 0x0A, 0x22, 0x29, 0x49, 0x2A, 0x48, ++0xD3, 0xF7, 0x10, 0xFC, 0x10, 0xBD, 0x15, 0x4B, 0x1A, 0x68, 0x08, 0x31, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x07, 0x39, ++0x8A, 0x43, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x02, 0x20, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x13, 0x48, 0x10, 0x40, ++0x80, 0x22, 0x92, 0x01, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x12, 0x04, 0x12, 0x0C, 0xB0, 0x20, 0x40, 0x03, 0x02, 0x43, ++0x1A, 0x60, 0x0E, 0x4A, 0xA0, 0x23, 0x9B, 0x00, 0xD1, 0x54, 0x19, 0x4B, 0x19, 0x4A, 0x1A, 0x60, 0xAF, 0xE7, 0xC0, 0x46, ++0x00, 0x04, 0x60, 0x40, 0x00, 0x08, 0x60, 0x40, 0xF8, 0xE6, 0x10, 0x00, 0xFC, 0x00, 0x60, 0x40, 0xEC, 0xA4, 0x16, 0x00, ++0x1E, 0x03, 0x00, 0x00, 0x6F, 0x04, 0x00, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xFF, 0xDF, 0xFF, 0xFF, ++0x7C, 0x1E, 0x16, 0x00, 0x8C, 0x04, 0x60, 0x40, 0xFF, 0xFF, 0x00, 0xFF, 0x60, 0x92, 0x16, 0x00, 0x2D, 0x01, 0x10, 0x00, ++0x81, 0x01, 0x10, 0x00, 0x8D, 0x05, 0x10, 0x00, 0xB9, 0x00, 0x10, 0x00, 0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, ++0x54, 0xE6, 0x10, 0x00, 0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x30, 0x10, 0x62, 0x40, 0x15, 0x1C, 0x20, 0x00, ++0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x70, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x0B, 0xD5, ++0x6F, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x6C, 0x4A, 0x13, 0x68, 0x08, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x6B, 0x4B, ++0x01, 0x22, 0x1A, 0x60, 0x6A, 0x4C, 0x23, 0x68, 0x6A, 0x4E, 0x33, 0x40, 0x23, 0x60, 0x6A, 0x4D, 0x2B, 0x68, 0x6A, 0x4F, ++0x3B, 0x40, 0x2B, 0x60, 0x83, 0xF7, 0xEE, 0xFA, 0x23, 0x68, 0x68, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x2B, 0x68, 0x33, 0x40, ++0x2B, 0x60, 0x23, 0x68, 0x1F, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x3B, 0x43, 0x23, 0x60, 0x23, 0x68, 0x1E, 0x40, 0x80, 0x23, ++0x9B, 0x00, 0x33, 0x43, 0x23, 0x60, 0x60, 0x4B, 0x99, 0x46, 0xFF, 0x23, 0x9B, 0x46, 0x22, 0x00, 0xC0, 0x3B, 0x98, 0x46, ++0x5D, 0x4B, 0x9C, 0x46, 0x40, 0x25, 0x80, 0x21, 0x09, 0x01, 0x5F, 0x46, 0x5E, 0x46, 0x04, 0x36, 0xF3, 0xB2, 0x9B, 0x46, ++0x4C, 0x46, 0x18, 0x00, 0x13, 0x68, 0x46, 0x46, 0xB3, 0x43, 0x03, 0x43, 0x13, 0x60, 0x63, 0x46, 0x26, 0x68, 0x1E, 0x60, ++0x13, 0x68, 0xAB, 0x43, 0x2B, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, ++0xFC, 0xD0, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0x34, 0xB8, 0x42, 0xE7, 0xD1, 0x10, 0x23, 0x9A, 0x46, 0xD1, 0x44, 0x5B, 0x46, ++0x0F, 0x2B, 0xDA, 0xD1, 0x42, 0x4C, 0x23, 0x68, 0x44, 0x4D, 0x2B, 0x40, 0x23, 0x60, 0x83, 0xF7, 0xAA, 0xFA, 0x23, 0x68, ++0x3F, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x3F, 0x4B, 0x1A, 0x68, 0x80, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x15, 0x40, ++0x80, 0x22, 0x52, 0x00, 0x2A, 0x43, 0x1A, 0x60, 0x3E, 0x4B, 0x9A, 0x46, 0xFF, 0x24, 0x38, 0x4A, 0x1F, 0x23, 0x99, 0x46, ++0x3C, 0x4B, 0x98, 0x46, 0x20, 0x26, 0x80, 0x21, 0xC9, 0x00, 0x04, 0xE0, 0x08, 0x23, 0x9C, 0x46, 0xE2, 0x44, 0x1F, 0x2C, ++0x1D, 0xD0, 0xA4, 0x46, 0x02, 0x34, 0xE4, 0xB2, 0x55, 0x46, 0x20, 0x00, 0x13, 0x68, 0x4F, 0x46, 0xBB, 0x43, 0x03, 0x43, ++0x13, 0x60, 0x43, 0x46, 0x2F, 0x68, 0x1F, 0x60, 0x13, 0x68, 0xB3, 0x43, 0x33, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, ++0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0x35, 0x60, 0x45, 0xE7, 0xD1, ++0xDC, 0xE7, 0x22, 0x4C, 0x23, 0x68, 0x80, 0x22, 0x93, 0x43, 0x23, 0x60, 0x83, 0xF7, 0x65, 0xFA, 0x23, 0x68, 0x1F, 0x4D, ++0x2B, 0x40, 0x23, 0x60, 0x23, 0x49, 0x0B, 0x68, 0x23, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x02, 0x13, 0x43, 0x0B, 0x60, ++0x83, 0xF7, 0x50, 0xFA, 0x15, 0x49, 0x0B, 0x68, 0x18, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x0B, 0x60, ++0x0B, 0x68, 0x12, 0x48, 0x03, 0x40, 0x80, 0x22, 0x92, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x23, 0x68, 0x03, 0x40, 0x1A, 0x43, ++0x22, 0x60, 0x23, 0x68, 0x1D, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x2B, 0x43, 0x23, 0x60, 0x14, 0x49, 0x0B, 0x68, 0x14, 0x4A, ++0x1A, 0x40, 0x80, 0x23, 0x5B, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, ++0xF8, 0xBD, 0xC0, 0x46, 0x18, 0x00, 0x58, 0x40, 0x40, 0x42, 0x04, 0x40, 0x58, 0x20, 0x62, 0x40, 0xFF, 0xFD, 0xFF, 0xFF, ++0x64, 0x20, 0x62, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xD8, 0x97, 0x16, 0x00, 0x5C, 0x20, 0x62, 0x40, ++0xD8, 0x98, 0x16, 0x00, 0x68, 0x20, 0x62, 0x40, 0x4C, 0x20, 0x62, 0x40, 0xFF, 0xFF, 0xFE, 0xFF, 0x30, 0x20, 0x62, 0x40, ++0xFF, 0xFF, 0xEF, 0xFF, 0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x6E, 0x4C, 0x23, 0x68, ++0x6E, 0x4E, 0x33, 0x40, 0x23, 0x60, 0x6E, 0x4D, 0x2B, 0x68, 0x6E, 0x4A, 0x13, 0x40, 0x2B, 0x60, 0x83, 0xF7, 0xF8, 0xF9, ++0x23, 0x68, 0x6C, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x2B, 0x68, 0x6B, 0x4A, 0x13, 0x40, 0x2B, 0x60, 0x23, 0x68, 0x6A, 0x4A, ++0x1A, 0x40, 0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x23, 0x60, 0x23, 0x68, 0x1E, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x33, 0x43, ++0x23, 0x60, 0x65, 0x4B, 0x9A, 0x46, 0x7F, 0x25, 0x22, 0x00, 0xFF, 0x23, 0x99, 0x46, 0x63, 0x4B, 0x98, 0x46, 0x5D, 0x4B, ++0x9C, 0x46, 0x80, 0x21, 0x89, 0x01, 0x2E, 0x00, 0x04, 0x35, 0xED, 0xB2, 0x54, 0x46, 0x28, 0x00, 0x13, 0x68, 0x4F, 0x46, ++0xBB, 0x43, 0x03, 0x43, 0x13, 0x60, 0x43, 0x46, 0x27, 0x68, 0x1F, 0x60, 0x13, 0x68, 0x67, 0x46, 0x3B, 0x40, 0x80, 0x27, ++0x7F, 0x00, 0x3B, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, ++0x01, 0x38, 0xC0, 0xB2, 0x04, 0x34, 0x86, 0x42, 0xE4, 0xD1, 0x10, 0x23, 0x9B, 0x46, 0xDA, 0x44, 0x8F, 0x2D, 0xDA, 0xD1, ++0x45, 0x4C, 0x23, 0x68, 0x4A, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x83, 0xF7, 0xB2, 0xF9, 0x23, 0x68, 0x42, 0x4A, 0x13, 0x40, ++0x23, 0x60, 0x42, 0x4B, 0x1A, 0x68, 0x80, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x40, 0x49, 0x11, 0x40, 0x80, 0x22, ++0x52, 0x00, 0x0A, 0x43, 0x1A, 0x60, 0x10, 0x20, 0x1A, 0x00, 0x1F, 0x27, 0x41, 0x4E, 0x42, 0x4D, 0x20, 0x24, 0x80, 0x21, ++0xC9, 0x00, 0x13, 0x68, 0xBB, 0x43, 0x03, 0x43, 0x13, 0x60, 0x83, 0x00, 0xF3, 0x58, 0x2B, 0x60, 0x13, 0x68, 0xA3, 0x43, ++0x23, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, 0x01, 0x30, ++0x20, 0x28, 0xEA, 0xD1, 0x2D, 0x4C, 0x23, 0x68, 0x80, 0x22, 0x93, 0x43, 0x23, 0x60, 0x83, 0xF7, 0x7E, 0xF9, 0x23, 0x68, ++0x2A, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x31, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x30, 0x4A, 0x13, 0x68, 0x02, 0x21, ++0x8B, 0x43, 0x13, 0x60, 0x2C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2D, 0x4A, 0x13, 0x68, 0x2D, 0x49, 0x0B, 0x40, 0x13, 0x60, ++0x2C, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x83, 0xF7, 0x5D, 0xF9, 0x1B, 0x49, 0x0B, 0x68, 0x1E, 0x4A, 0x13, 0x40, 0x80, 0x22, ++0x52, 0x01, 0x13, 0x43, 0x0B, 0x60, 0x0B, 0x68, 0x17, 0x48, 0x18, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x03, 0x43, 0x0B, 0x60, ++0x15, 0x4B, 0x19, 0x68, 0x17, 0x48, 0x08, 0x40, 0x80, 0x21, 0x89, 0x00, 0x01, 0x43, 0x19, 0x60, 0x19, 0x68, 0x12, 0x48, ++0x08, 0x40, 0x80, 0x21, 0x49, 0x00, 0x01, 0x43, 0x19, 0x60, 0x1C, 0x4B, 0x19, 0x68, 0x0A, 0x43, 0x1A, 0x60, 0x1B, 0x4A, ++0x13, 0x68, 0x1B, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x1A, 0x4B, 0x1A, 0x68, 0x1A, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x19, 0x68, ++0x80, 0x22, 0xD2, 0x05, 0x0A, 0x43, 0x1A, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, ++0x60, 0x40, 0x34, 0x40, 0xFF, 0xF7, 0xFF, 0xFF, 0x6C, 0x40, 0x34, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, ++0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xD8, 0x9B, 0x16, 0x00, 0x64, 0x40, 0x34, 0x40, 0x58, 0x99, 0x16, 0x00, ++0x70, 0x40, 0x34, 0x40, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xFF, 0xFB, ++0x08, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, 0xFF, 0xFF, 0xFB, 0xFF, 0x1C, 0x20, 0x34, 0x40, ++0xFF, 0xFF, 0xFF, 0xDF, 0x10, 0xB5, 0x07, 0x49, 0x0A, 0x69, 0x0F, 0x24, 0xA2, 0x43, 0x03, 0x20, 0x02, 0x43, 0x0A, 0x61, ++0xCB, 0x69, 0xA3, 0x43, 0x03, 0x43, 0xCB, 0x61, 0x02, 0x48, 0x7E, 0xF7, 0xA1, 0xFB, 0x10, 0xBD, 0x00, 0x30, 0x50, 0x40, ++0x94, 0xD1, 0x10, 0x00, 0x70, 0xB5, 0x1B, 0x4B, 0x9B, 0x69, 0xDB, 0x05, 0x1F, 0xD4, 0x0C, 0x38, 0xEF, 0xF3, 0x10, 0x83, ++0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x15, 0x4B, 0x1B, 0x7F, 0x01, 0x2B, 0x1C, 0xD0, ++0xCF, 0xF7, 0x62, 0xF8, 0x12, 0x4B, 0x1B, 0x7F, 0xFF, 0x2B, 0x1A, 0xD0, 0x02, 0x20, 0x7B, 0xF7, 0xCB, 0xF9, 0xFF, 0xF7, ++0xCF, 0xFF, 0x0F, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, 0x70, 0xBD, 0x0C, 0x4D, ++0xC4, 0x24, 0x64, 0x00, 0x00, 0x23, 0x2B, 0x51, 0xCE, 0xF7, 0xCC, 0xF8, 0x09, 0x4B, 0x2B, 0x51, 0xF4, 0xE7, 0x05, 0x4B, ++0xFF, 0x22, 0x1A, 0x77, 0xDE, 0xE7, 0x03, 0x4B, 0x01, 0x22, 0x1A, 0x77, 0xE0, 0xE7, 0xC0, 0x46, 0x3C, 0x95, 0x16, 0x00, ++0x24, 0x2A, 0x16, 0x00, 0x00, 0x41, 0x04, 0x40, 0x28, 0x19, 0x16, 0x00, 0xB9, 0x5A, 0x10, 0x00, 0x01, 0x28, 0x02, 0xD0, ++0x02, 0x28, 0x05, 0xD0, 0x70, 0x47, 0x05, 0x4B, 0x80, 0x22, 0x92, 0x04, 0x1A, 0x60, 0xF9, 0xE7, 0x02, 0x4B, 0x80, 0x22, ++0x52, 0x04, 0x1A, 0x60, 0xF4, 0xE7, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, 0x15, 0x4B, 0x16, 0x4A, 0x13, 0x60, 0x16, 0x4A, ++0x13, 0x60, 0x16, 0x4B, 0x1A, 0x68, 0x30, 0x21, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x90, 0x31, 0x8A, 0x43, 0x1A, 0x60, ++0x1A, 0x68, 0x12, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x11, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x10, 0x49, ++0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x0F, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x0E, 0x4A, 0xC4, 0x20, 0x80, 0x00, 0x13, 0x58, ++0x1B, 0x02, 0x1B, 0x0A, 0xC0, 0x21, 0x09, 0x06, 0x0B, 0x43, 0x13, 0x50, 0x80, 0x23, 0x1B, 0x03, 0x13, 0x60, 0x70, 0x47, ++0x00, 0x00, 0x7C, 0x07, 0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x18, 0x41, 0x04, 0x40, 0xFF, 0xFC, 0xFF, 0xFF, ++0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0x00, 0xE1, 0x00, 0xE0, 0x70, 0xB5, 0x82, 0xB0, ++0x04, 0x00, 0x64, 0x4B, 0x18, 0x68, 0x04, 0x28, 0x04, 0xD8, 0x49, 0xD8, 0x80, 0x00, 0x62, 0x4B, 0x1B, 0x58, 0x9F, 0x46, ++0xFF, 0x28, 0x43, 0xD1, 0x60, 0x4B, 0x80, 0x22, 0xD2, 0x00, 0x1A, 0x60, 0x5F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x5F, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x40, 0xD1, 0x5E, 0x4B, 0x19, 0x68, 0x41, 0x29, 0x57, 0xD0, 0x43, 0xD8, 0x01, 0x29, 0x49, 0xD0, ++0x21, 0x29, 0x00, 0xD0, 0x81, 0xE0, 0x5A, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x52, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x58, 0x4B, ++0x1B, 0x68, 0x01, 0x2B, 0x54, 0xD1, 0x50, 0xE0, 0x54, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x4F, 0x4B, 0x80, 0x22, 0xD2, 0x00, ++0x1A, 0x60, 0x4E, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x50, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x00, 0xD1, 0x7D, 0xE0, 0x47, 0x4B, ++0x1B, 0x68, 0x02, 0x2B, 0x40, 0xD1, 0x00, 0x25, 0x4C, 0x4B, 0x1D, 0x70, 0x01, 0x20, 0xFB, 0xF7, 0xCB, 0xFD, 0x4B, 0x4B, ++0x1D, 0x70, 0x3D, 0xE0, 0x46, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0xE2, 0xE7, 0x44, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xDE, 0xE7, ++0x42, 0x4B, 0x19, 0x78, 0x45, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA8, 0x47, 0xD6, 0xE7, 0x0F, 0x20, 0xFA, 0xF7, ++0x6F, 0xFD, 0xFF, 0x23, 0x03, 0x40, 0x3B, 0x4A, 0x13, 0x60, 0xB6, 0xE7, 0x61, 0x29, 0x10, 0xD0, 0xFF, 0x29, 0x3E, 0xD1, ++0x3D, 0x48, 0x7E, 0xF7, 0xA1, 0xFA, 0xCD, 0xE7, 0x36, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0x2F, 0x4B, 0x01, 0x3A, 0x1A, 0x60, ++0x34, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x0D, 0xD1, 0x4C, 0xE0, 0x31, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x29, 0x4B, 0x01, 0x32, ++0x1A, 0x60, 0x2F, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0xC1, 0xD1, 0x26, 0x4B, 0x03, 0x22, 0x1A, 0x60, 0x2D, 0x4B, 0x01, 0x22, ++0x1A, 0x70, 0x00, 0x20, 0xFB, 0xF7, 0x8A, 0xFD, 0x2D, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0xFF, 0xF7, 0x35, 0xFF, 0x2C, 0x4B, ++0x1B, 0x68, 0x24, 0x4A, 0x12, 0x78, 0x1D, 0x49, 0x09, 0x68, 0x2A, 0x48, 0x00, 0x68, 0x01, 0x90, 0x1E, 0x48, 0x00, 0x68, ++0x00, 0x90, 0x28, 0x48, 0x7E, 0xF7, 0x6E, 0xFA, 0x00, 0x2C, 0x27, 0xD0, 0x26, 0x4A, 0x13, 0x68, 0x20, 0x21, 0x0B, 0x43, ++0x13, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x24, 0x48, 0x7E, 0xF7, 0x62, 0xFA, 0x17, 0x4E, 0x31, 0x78, 0x10, 0x4D, 0x00, 0x23, ++0x00, 0x22, 0x28, 0x68, 0x81, 0xF7, 0xFE, 0xFF, 0x02, 0x23, 0x33, 0x70, 0x01, 0x3B, 0x2B, 0x60, 0x12, 0x4B, 0x1B, 0x68, ++0x01, 0x2B, 0xC9, 0xD1, 0x0F, 0x4B, 0x1B, 0x78, 0x03, 0xE0, 0x0E, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0xBF, 0xD0, 0x02, 0x2B, ++0x00, 0xD0, 0x7A, 0xE7, 0x04, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0xBB, 0xE7, 0x12, 0x4A, 0x13, 0x68, 0x20, 0x21, 0x8B, 0x43, ++0x13, 0x60, 0xD6, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0xE0, 0xD1, 0x10, 0x00, 0xE4, 0xE1, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, ++0xA4, 0xE5, 0x10, 0x00, 0xC0, 0xE5, 0x10, 0x00, 0xB4, 0xE5, 0x10, 0x00, 0x54, 0xE0, 0x10, 0x00, 0x60, 0xE6, 0x10, 0x00, ++0xDC, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x9C, 0xD1, 0x10, 0x00, 0xD1, 0xE6, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, ++0xBC, 0xE5, 0x10, 0x00, 0xC8, 0xD1, 0x10, 0x00, 0x84, 0x40, 0x04, 0x40, 0xB0, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x38, 0x4B, 0x38, 0x4A, 0x1A, 0x60, 0x38, 0x4B, 0x39, 0x4A, 0x1A, 0x60, 0x40, 0x23, 0x38, 0x4A, 0x13, 0x60, ++0x28, 0x22, 0x38, 0x49, 0x0A, 0x80, 0xC8, 0x21, 0x49, 0x00, 0x37, 0x48, 0x01, 0x80, 0x37, 0x48, 0x01, 0x80, 0x03, 0x20, ++0x36, 0x49, 0x08, 0x80, 0x02, 0x21, 0x36, 0x4C, 0x21, 0x80, 0x36, 0x4C, 0x20, 0x80, 0x36, 0x48, 0x01, 0x80, 0x36, 0x49, ++0x0A, 0x80, 0x80, 0x25, 0xAD, 0x00, 0x35, 0x49, 0x0D, 0x80, 0x14, 0x21, 0x34, 0x48, 0x01, 0x80, 0x34, 0x48, 0x15, 0x24, ++0x04, 0x80, 0x34, 0x48, 0x01, 0x80, 0x20, 0x26, 0x33, 0x49, 0x0E, 0x60, 0x0D, 0x3C, 0x33, 0x49, 0x0C, 0x60, 0x33, 0x49, ++0x01, 0x20, 0x40, 0x42, 0x08, 0x60, 0x00, 0x20, 0x31, 0x49, 0x08, 0x60, 0x31, 0x49, 0x88, 0x46, 0x31, 0x4F, 0x39, 0x60, ++0x31, 0x4F, 0x14, 0x21, 0xFF, 0x31, 0x39, 0x60, 0x30, 0x4F, 0x31, 0x49, 0x39, 0x60, 0x31, 0x4F, 0x07, 0x21, 0x39, 0x80, ++0x30, 0x4F, 0x3B, 0x80, 0x30, 0x4F, 0x41, 0x31, 0x39, 0x80, 0x30, 0x4F, 0x01, 0x39, 0x39, 0x80, 0x2F, 0x4F, 0x3E, 0x80, ++0x2F, 0x4E, 0x35, 0x80, 0x2F, 0x4D, 0xD2, 0x26, 0x76, 0x00, 0x2E, 0x80, 0x64, 0x25, 0x2E, 0x4E, 0x35, 0x80, 0x2E, 0x4E, ++0x35, 0x80, 0x2E, 0x4D, 0x2C, 0x80, 0x2E, 0x4C, 0x18, 0x25, 0x25, 0x80, 0x2D, 0x4C, 0x22, 0x80, 0x2D, 0x4A, 0x8C, 0x24, ++0x14, 0x80, 0x2D, 0x4A, 0x10, 0x80, 0x2D, 0x4A, 0x13, 0x60, 0x2D, 0x4B, 0x42, 0x46, 0x1A, 0x60, 0x2C, 0x4B, 0x32, 0x22, ++0x1A, 0x80, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xA0, 0x06, 0x16, 0x00, 0x00, 0xD7, 0x18, 0x00, 0x9C, 0x06, 0x16, 0x00, ++0x00, 0xF7, 0x18, 0x00, 0x78, 0x06, 0x16, 0x00, 0x5C, 0x06, 0x16, 0x00, 0x8E, 0x06, 0x16, 0x00, 0x8C, 0x06, 0x16, 0x00, ++0x5A, 0x06, 0x16, 0x00, 0x4A, 0x06, 0x16, 0x00, 0x56, 0x06, 0x16, 0x00, 0x54, 0x06, 0x16, 0x00, 0x5E, 0x06, 0x16, 0x00, ++0x58, 0x06, 0x16, 0x00, 0x64, 0x06, 0x16, 0x00, 0x66, 0x06, 0x16, 0x00, 0x62, 0x06, 0x16, 0x00, 0x68, 0x06, 0x16, 0x00, ++0x6C, 0x06, 0x16, 0x00, 0x44, 0x1E, 0x16, 0x00, 0x40, 0x1E, 0x16, 0x00, 0x20, 0x4E, 0x00, 0x00, 0x7C, 0x06, 0x16, 0x00, ++0x38, 0x1E, 0x16, 0x00, 0x3C, 0x1E, 0x16, 0x00, 0x02, 0x73, 0x06, 0x20, 0x4C, 0x06, 0x16, 0x00, 0x4E, 0x06, 0x16, 0x00, ++0x50, 0x06, 0x16, 0x00, 0x52, 0x06, 0x16, 0x00, 0x90, 0x06, 0x16, 0x00, 0x94, 0x06, 0x16, 0x00, 0x92, 0x06, 0x16, 0x00, ++0x8A, 0x06, 0x16, 0x00, 0x88, 0x06, 0x16, 0x00, 0x82, 0x06, 0x16, 0x00, 0x80, 0x06, 0x16, 0x00, 0x86, 0x06, 0x16, 0x00, ++0x84, 0x06, 0x16, 0x00, 0x48, 0x1E, 0x16, 0x00, 0x70, 0x06, 0x16, 0x00, 0x74, 0x06, 0x16, 0x00, 0x60, 0x06, 0x16, 0x00, ++0x0F, 0x4B, 0x02, 0x22, 0x9A, 0x77, 0x0F, 0x4A, 0x11, 0x6D, 0x80, 0x23, 0xDB, 0x01, 0x0B, 0x43, 0x13, 0x65, 0x0D, 0x4B, ++0x1B, 0x78, 0x02, 0x2B, 0x0B, 0xD0, 0x0A, 0x4B, 0x19, 0x6D, 0x80, 0x22, 0x12, 0x02, 0x0A, 0x43, 0x1A, 0x65, 0x19, 0x6D, ++0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, 0x1A, 0x65, 0x70, 0x47, 0x11, 0x6D, 0x80, 0x23, 0xDB, 0x02, 0x0B, 0x43, 0x13, 0x65, ++0xED, 0xE7, 0xC0, 0x46, 0x3C, 0x95, 0x16, 0x00, 0x00, 0x60, 0x50, 0x40, 0xB4, 0xE5, 0x10, 0x00, 0x01, 0x4B, 0x01, 0x22, ++0xDA, 0x77, 0x70, 0x47, 0x3C, 0x95, 0x16, 0x00, 0x10, 0xB5, 0x01, 0x20, 0x7F, 0xF7, 0x48, 0xF9, 0x10, 0xBD, 0x10, 0xB5, ++0x80, 0x20, 0x40, 0x00, 0x7B, 0xF7, 0x3A, 0xFC, 0x10, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x20, 0x4B, 0x1B, 0x68, ++0x01, 0x2B, 0x03, 0xD0, 0x1F, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x22, 0xD1, 0x00, 0x2C, 0x2C, 0xD0, 0x1D, 0x4A, 0x13, 0x68, ++0x08, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x00, 0x23, 0x1B, 0x4A, 0x13, 0x60, 0x1B, 0x4A, 0x13, 0x60, 0x1B, 0x4A, 0x13, 0x60, ++0x1B, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x22, 0xD9, 0x1A, 0x4A, 0x0F, 0x21, 0x11, 0x70, 0x03, 0x3B, 0x01, 0x2B, 0x05, 0xD8, ++0x18, 0x4A, 0x80, 0x23, 0x1B, 0x02, 0x91, 0x69, 0x0B, 0x43, 0x93, 0x61, 0x16, 0x49, 0x17, 0x48, 0x7E, 0xF7, 0xEC, 0xF8, ++0x10, 0xBD, 0xFF, 0xF7, 0xCF, 0xFE, 0xFF, 0xF7, 0x97, 0xFF, 0x11, 0x4B, 0x01, 0x22, 0xDA, 0x77, 0xFF, 0xF7, 0xBE, 0xFF, ++0xFF, 0xF7, 0xC1, 0xFF, 0xD0, 0xE7, 0x07, 0x4A, 0x13, 0x68, 0x08, 0x21, 0x8B, 0x43, 0x13, 0x60, 0xD1, 0xE7, 0x09, 0x4B, ++0x0B, 0x22, 0x1A, 0x70, 0xE4, 0xE7, 0xC0, 0x46, 0xA8, 0xE5, 0x10, 0x00, 0xAC, 0xE5, 0x10, 0x00, 0x84, 0x40, 0x04, 0x40, ++0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x54, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xE2, 0xE1, 0x10, 0x00, ++0x3C, 0x95, 0x16, 0x00, 0xF8, 0xE8, 0x10, 0x00, 0xF4, 0xD1, 0x10, 0x00, 0x02, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, ++0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0x12, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, ++0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0xD2, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, ++0x04, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, 0x03, 0x4B, 0x80, 0x22, 0x52, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, ++0xD0, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x13, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x07, 0xD0, ++0x11, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x16, 0xD9, 0x20, 0x00, 0x10, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0xAD, 0x33, 0xC3, 0x5C, ++0x00, 0x2B, 0xF7, 0xD0, 0x0D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, 0xFD, 0xF7, 0x54, 0xF8, ++0xEA, 0xE7, 0xFF, 0xF7, 0xD5, 0xFF, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xAE, 0xF7, 0x09, 0xFD, 0x00, 0x28, ++0xE4, 0xD1, 0xA7, 0x23, 0x04, 0x22, 0xE2, 0x54, 0xE0, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0xD5, 0x0D, 0x0B, 0x00, ++0xD8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x0B, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x03, 0xD0, 0x20, 0x00, 0xFE, 0xF7, ++0x11, 0xF9, 0x10, 0xBD, 0x08, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, 0xFD, 0xF7, 0x2C, 0xF8, ++0xF2, 0xE7, 0xFF, 0xF7, 0xAD, 0xFF, 0x03, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, ++0xD8, 0xE6, 0x10, 0x00, 0x04, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, 0x03, 0x4B, 0x80, 0x22, 0x92, 0x05, 0x1A, 0x60, ++0x70, 0x47, 0xC0, 0x46, 0xD2, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x80, 0x46, 0x00, 0x91, 0x82, 0x00, 0x93, 0x4B, 0xD5, 0x58, 0x9E, 0x23, 0xEC, 0x5C, ++0x64, 0x00, 0x0F, 0x33, 0xEB, 0x5C, 0xE4, 0x18, 0xE4, 0xB2, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0xAF, 0xE0, ++0xA8, 0x23, 0xEB, 0x5C, 0x77, 0x2B, 0x02, 0xD8, 0x01, 0x33, 0xA8, 0x22, 0xAB, 0x54, 0x43, 0x46, 0x1B, 0x02, 0x01, 0x27, ++0x3B, 0x43, 0x9B, 0x46, 0x87, 0x4B, 0x99, 0x46, 0x47, 0xE0, 0xC5, 0x20, 0x02, 0x23, 0xFF, 0x22, 0x59, 0x46, 0xC0, 0x00, ++0x7B, 0xF7, 0x0A, 0xFF, 0x06, 0x00, 0x3B, 0x88, 0x03, 0x80, 0x7B, 0xF7, 0x2F, 0xFF, 0x30, 0x88, 0x43, 0x1C, 0x9B, 0xB2, ++0x7F, 0x49, 0x5A, 0x5C, 0x41, 0x5C, 0x49, 0x10, 0x7E, 0x48, 0x7D, 0xF7, 0xFF, 0xFF, 0x00, 0x23, 0x3B, 0x80, 0x7D, 0x4B, ++0xE2, 0x18, 0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, 0x13, 0x80, 0x7B, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x7A, 0x4A, ++0x13, 0x40, 0x23, 0x80, 0xAF, 0x22, 0xAB, 0x5C, 0x01, 0x3B, 0xDB, 0xB2, 0xAB, 0x54, 0x35, 0x31, 0x6A, 0x5C, 0x50, 0x42, ++0x42, 0x41, 0x6A, 0x54, 0x5A, 0x1E, 0x93, 0x41, 0xA8, 0x22, 0xAB, 0x54, 0x8C, 0x23, 0xEB, 0x58, 0x00, 0x2B, 0x05, 0xD0, ++0x6A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x9E, 0x23, 0xEC, 0x5C, 0x64, 0x00, 0x0F, 0x33, ++0xEB, 0x5C, 0xE4, 0x18, 0xE4, 0xB2, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x58, 0xD0, 0xA3, 0x00, 0x1C, 0x19, 0x64, 0x00, ++0x66, 0x4B, 0xE3, 0x18, 0x1B, 0x88, 0xDB, 0x0B, 0x50, 0xD0, 0x65, 0x4B, 0xE7, 0x18, 0x3B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, ++0xA9, 0xD1, 0x63, 0x4B, 0xE7, 0x18, 0x3B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x38, 0xD0, 0xEC, 0x23, 0xEB, 0x58, 0x00, 0x2B, ++0xB7, 0xD1, 0x5A, 0x4B, 0xE3, 0x18, 0x1B, 0x88, 0xDB, 0x04, 0x9B, 0x0D, 0x0A, 0xD0, 0x3A, 0x88, 0x90, 0x21, 0x69, 0x58, ++0xD3, 0x18, 0x4A, 0x89, 0x92, 0x05, 0x92, 0x0D, 0x09, 0x89, 0x52, 0x18, 0x93, 0x42, 0x0D, 0xDA, 0x8C, 0x23, 0xEB, 0x58, ++0x00, 0x2B, 0x06, 0xD0, 0x4B, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, ++0x3B, 0x80, 0x98, 0xE7, 0x01, 0x23, 0xFF, 0x22, 0x59, 0x46, 0x4E, 0x48, 0x7B, 0xF7, 0x8C, 0xFE, 0x00, 0x23, 0x9A, 0x46, ++0x03, 0x70, 0x7B, 0xF7, 0xB1, 0xFE, 0x90, 0x26, 0xAB, 0x59, 0x18, 0x89, 0x85, 0xF7, 0xA2, 0xFF, 0x8C, 0x23, 0xEA, 0x58, ++0xAA, 0x51, 0x52, 0x46, 0xEA, 0x50, 0xE6, 0xE7, 0xEC, 0x23, 0xEB, 0x58, 0x00, 0x2B, 0x00, 0xD0, 0x7D, 0xE7, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x4B, 0x46, 0x9B, 0x6E, 0x98, 0x47, 0x76, 0xE7, 0x00, 0x99, 0x40, 0x46, 0xFD, 0xF7, 0x0C, 0xF8, ++0x3D, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x0A, 0xD0, 0xFC, 0xF7, 0x6E, 0xF9, 0x01, 0x28, 0x28, 0xD0, 0x03, 0xB0, 0x3C, 0xBC, ++0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xAD, 0x33, 0xEB, 0x5C, 0x00, 0x2B, 0x0E, 0xD1, 0x35, 0x4B, ++0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0x2B, 0xFF, 0xE7, 0xE7, 0xFF, 0xF7, 0x08, 0xFF, ++0x2F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0x2D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, ++0xFC, 0xF7, 0x1C, 0xFF, 0xD8, 0xE7, 0xFF, 0xF7, 0x9D, 0xFE, 0x28, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xFB, 0xF7, ++0x0F, 0xFA, 0x00, 0x28, 0xD2, 0xD0, 0xAE, 0xF7, 0xCD, 0xFB, 0x00, 0x28, 0xCE, 0xD1, 0x8A, 0xF7, 0x5D, 0xFA, 0x00, 0x28, ++0xCA, 0xD1, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0xC6, 0xD1, 0xA7, 0x33, 0xEB, 0x5C, 0x01, 0x2B, 0xC2, 0xD8, 0xD0, 0xF7, ++0xD9, 0xFA, 0x04, 0x1E, 0xBE, 0xD0, 0x1B, 0x4B, 0xC2, 0x69, 0x9A, 0x42, 0xBA, 0xD1, 0xA5, 0xF7, 0x4D, 0xFA, 0x63, 0x68, ++0x05, 0x3B, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xAA, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0xAF, 0xD0, 0x0B, 0x2B, 0xAD, 0xD9, ++0x13, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x9E, 0x23, 0xE8, 0x5C, 0xD1, 0xF7, 0x35, 0xFA, 0xAA, 0x23, 0x00, 0x22, 0xEA, 0x54, ++0xA2, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0xFC, 0xD1, 0x10, 0x00, ++0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0x07, 0xE0, 0xFF, 0xFF, 0xC8, 0x69, 0x61, 0x40, 0xD0, 0x69, 0x61, 0x40, ++0xCE, 0x69, 0x61, 0x40, 0x2B, 0x06, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0xC9, 0x1F, 0x10, 0x00, ++0x98, 0xE5, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x81, 0x46, ++0x82, 0x00, 0xBA, 0x4B, 0xD4, 0x58, 0x01, 0x94, 0xB0, 0x23, 0x15, 0x22, 0xE2, 0x54, 0x2A, 0x3B, 0xFA, 0x22, 0x52, 0x01, ++0xE2, 0x52, 0xB6, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x15, 0xD0, 0xB4, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x26, 0xD9, 0xB3, 0x4B, ++0x00, 0x22, 0x1A, 0x70, 0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x2C, 0xD0, 0x86, 0x23, 0xE3, 0x5A, 0x00, 0x2B, 0x6B, 0xD0, ++0x5B, 0x00, 0x22, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1F, 0x09, 0x29, 0xE0, 0xAB, 0x4B, 0xE3, 0x61, 0xAF, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x03, 0xD1, 0xA9, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD0, 0x01, 0x21, 0x02, 0x20, 0xFC, 0xF7, ++0x87, 0xFE, 0xDA, 0xE7, 0xFF, 0xF7, 0x64, 0xFE, 0xA3, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xA0, 0x4B, 0xE3, 0x61, ++0x9E, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xD2, 0xD0, 0x9F, 0x4B, 0x18, 0x68, 0x00, 0x28, 0xCE, 0xD0, 0xFB, 0xF7, 0x86, 0xFE, ++0xCB, 0xE7, 0xE4, 0x33, 0xE3, 0x58, 0x19, 0x68, 0xA3, 0x6F, 0xC9, 0x1A, 0x14, 0x39, 0x09, 0x01, 0x0F, 0x09, 0xA6, 0x23, ++0xE3, 0x5C, 0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x1A, 0x40, 0x96, 0x4B, 0x59, 0x78, 0x0F, 0x23, 0x0B, 0x40, 0x13, 0x43, ++0x94, 0x4A, 0x13, 0x43, 0xA3, 0x82, 0xE7, 0x60, 0xFB, 0xF7, 0x56, 0xF9, 0x02, 0x90, 0xFD, 0xF7, 0x2B, 0xF9, 0x03, 0x90, ++0xAE, 0xF7, 0x12, 0xFB, 0x06, 0x00, 0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x00, 0xD1, 0x38, 0xE2, 0x00, 0x25, 0x00, 0x28, ++0x2B, 0xD0, 0x8B, 0x4B, 0xA2, 0x6F, 0x1A, 0x60, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x5C, 0xE1, 0x88, 0x4A, ++0xD2, 0x88, 0x22, 0x61, 0x01, 0x2B, 0x00, 0xD0, 0xDA, 0xE1, 0xA7, 0x33, 0xE3, 0x5C, 0xA7, 0x21, 0x61, 0x5C, 0x5B, 0x18, ++0x1B, 0x11, 0x83, 0x49, 0x4B, 0x43, 0x93, 0x42, 0x00, 0xD2, 0x13, 0x00, 0x23, 0x61, 0xCD, 0xE1, 0xA6, 0x23, 0xE3, 0x5C, ++0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x1A, 0x40, 0x78, 0x4B, 0x59, 0x78, 0x0F, 0x23, 0x0B, 0x40, 0x13, 0x43, 0x7B, 0x4A, ++0x13, 0x43, 0xA3, 0x82, 0x01, 0x27, 0x7F, 0x42, 0xC2, 0xE7, 0xA5, 0xF7, 0x73, 0xF9, 0x60, 0x60, 0x03, 0x9B, 0x00, 0x2B, ++0x52, 0xD0, 0x76, 0x4B, 0x23, 0x61, 0x11, 0x23, 0xA3, 0x75, 0x8E, 0x33, 0xE3, 0x5C, 0x01, 0x2B, 0x47, 0xD0, 0x00, 0x25, ++0x48, 0x23, 0x9B, 0x46, 0xAF, 0x23, 0xE3, 0x5C, 0x98, 0x46, 0x20, 0x00, 0x48, 0x30, 0x7E, 0xF7, 0x83, 0xFA, 0x6E, 0x4A, ++0x12, 0x68, 0x92, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0xE0, 0xE0, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x01, 0xD1, 0x6A, 0x4B, ++0x23, 0x61, 0x40, 0x44, 0xC3, 0xB2, 0xA7, 0x22, 0xA2, 0x5C, 0x11, 0x00, 0x19, 0x43, 0x06, 0xD0, 0xD3, 0x18, 0x65, 0x4A, ++0x53, 0x43, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x23, 0x61, 0x23, 0x69, 0x62, 0x4A, 0x93, 0x42, 0x00, 0xD9, 0x13, 0x00, ++0x23, 0x61, 0x5A, 0x46, 0x21, 0x69, 0x20, 0x00, 0xFB, 0xF7, 0x16, 0xF8, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x04, 0xD1, ++0x63, 0x68, 0x03, 0x33, 0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0xA7, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x50, 0x4B, 0xA2, 0x6F, ++0x1A, 0x60, 0x20, 0x00, 0xCF, 0xF7, 0xB6, 0xFF, 0x00, 0x28, 0x00, 0xD0, 0xAE, 0xE1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, ++0x49, 0xE1, 0x37, 0x33, 0x9B, 0x46, 0xB7, 0xE7, 0x02, 0x9B, 0x00, 0x2B, 0x6B, 0xD0, 0x00, 0x23, 0x00, 0x25, 0x3E, 0x4A, ++0x90, 0x46, 0xA1, 0x22, 0x94, 0x46, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, 0x0B, 0xD0, 0x9A, 0x00, 0x41, 0x46, 0x52, 0x58, ++0x00, 0x2A, 0xF7, 0xD0, 0x61, 0x46, 0x52, 0x5C, 0x00, 0x2A, 0xF3, 0xD1, 0x01, 0x35, 0xED, 0xB2, 0xF0, 0xE7, 0x01, 0x2D, ++0x08, 0xD9, 0xA0, 0x33, 0x00, 0x22, 0xE2, 0x54, 0x41, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x28, 0x23, 0x9B, 0x46, 0x93, 0xE7, ++0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x23, 0xD1, 0xA7, 0x33, 0x00, 0x22, 0xE2, 0x54, 0x01, 0x33, 0xE2, 0x5C, 0x53, 0x42, ++0x5A, 0x41, 0x53, 0x42, 0x08, 0x22, 0x1A, 0x40, 0x68, 0x32, 0x38, 0x4B, 0x1B, 0x68, 0x98, 0x46, 0xC3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8B, 0x42, 0x04, 0xD9, 0x43, 0x46, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, ++0x00, 0x21, 0x8B, 0x46, 0x9A, 0x42, 0x01, 0xD3, 0xD3, 0x1A, 0x9B, 0x46, 0x2C, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x6B, 0xE7, ++0x01, 0x2B, 0x00, 0xD0, 0x65, 0xE1, 0xA7, 0x33, 0xE2, 0x5C, 0x53, 0x42, 0x5A, 0x41, 0x53, 0x42, 0x0C, 0x22, 0x1A, 0x40, ++0x44, 0x32, 0xE3, 0x6E, 0x98, 0x46, 0xC3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8B, 0x42, 0x04, 0xD9, ++0x43, 0x46, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0x00, 0x21, 0x8B, 0x46, 0x9A, 0x42, 0x01, 0xD3, 0xD3, 0x1A, ++0x9B, 0x46, 0x1B, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x48, 0xE7, 0x0A, 0x4B, 0x1B, 0x68, 0x00, 0x25, 0x01, 0x2B, 0x00, 0xD9, ++0x05, 0xE7, 0x13, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0x00, 0xD1, 0x37, 0xE1, 0x13, 0x4B, 0x1B, 0x68, 0x23, 0x61, ++0x00, 0x23, 0x9B, 0x46, 0x36, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x98, 0xE5, 0x10, 0x00, ++0xC1, 0x60, 0x10, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x40, 0x80, 0xFF, 0xFF, ++0xCC, 0xE6, 0x10, 0x00, 0x5C, 0xAB, 0x16, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, ++0xF4, 0xE1, 0x10, 0x00, 0x5C, 0x1C, 0x00, 0x00, 0x70, 0x71, 0x00, 0x00, 0x40, 0xE0, 0x10, 0x00, 0x2C, 0xE6, 0x10, 0x00, ++0x00, 0x23, 0x04, 0x93, 0x05, 0x93, 0x20, 0x1D, 0x23, 0x00, 0x05, 0xAA, 0x04, 0xA9, 0xFA, 0xF7, 0xAD, 0xFE, 0x04, 0x9B, ++0x00, 0x2B, 0x28, 0xD0, 0x22, 0x69, 0x9A, 0x42, 0x00, 0xD9, 0x1A, 0x00, 0x22, 0x61, 0x03, 0x26, 0x63, 0x68, 0x9A, 0x46, ++0x5A, 0x46, 0x21, 0x69, 0x01, 0x98, 0xFA, 0xF7, 0x3B, 0xFF, 0x63, 0x68, 0x53, 0x45, 0x08, 0xD0, 0x05, 0x9B, 0x53, 0x44, ++0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xEC, 0xD1, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x00, 0xD0, 0x0E, 0xE7, 0x63, 0x68, 0x03, 0x33, 0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0x23, 0x69, 0x70, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x23, 0x61, 0x03, 0xE7, 0x02, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0x9B, 0xE6, 0xEA, 0xE7, 0xA7, 0x23, 0xE3, 0x5C, ++0x00, 0x2B, 0x00, 0xD0, 0x7B, 0xE0, 0xA8, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x76, 0xE0, 0xB3, 0x33, 0xE3, 0x5C, ++0x00, 0x2B, 0x00, 0xD0, 0x71, 0xE0, 0x65, 0x4B, 0x23, 0x61, 0x73, 0x42, 0x73, 0x41, 0x5B, 0x42, 0x4B, 0x22, 0x93, 0x43, ++0x60, 0x33, 0x5B, 0x00, 0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x60, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xB0, 0x23, 0x09, 0x22, ++0xE2, 0x54, 0x20, 0x00, 0xCF, 0xF7, 0xA8, 0xFE, 0x00, 0x28, 0x00, 0xD0, 0xA0, 0xE0, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, ++0x00, 0x2E, 0x3A, 0xD0, 0xA5, 0xF7, 0x0E, 0xF8, 0x57, 0x4B, 0x18, 0x60, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x66, 0x60, 0x80, 0xE0, 0x00, 0x2E, 0x00, 0xD1, 0x86, 0xE0, 0x51, 0x4B, 0x23, 0x61, ++0x20, 0x00, 0xFD, 0xF7, 0x57, 0xFE, 0x60, 0x60, 0x18, 0x26, 0x65, 0x68, 0x00, 0x22, 0x21, 0x69, 0x01, 0x98, 0xFA, 0xF7, ++0xD1, 0xFE, 0x63, 0x68, 0xAB, 0x42, 0x06, 0xD0, 0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x18, 0x36, 0x60, 0x2E, ++0xEF, 0xD1, 0x20, 0x00, 0xCF, 0xF7, 0x76, 0xFE, 0x00, 0x28, 0x6F, 0xD1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xCF, 0xE7, ++0x39, 0x00, 0x14, 0x31, 0x09, 0x01, 0x09, 0x09, 0x48, 0x46, 0x40, 0x4B, 0x98, 0x47, 0xCB, 0xE7, 0xA0, 0x23, 0x00, 0x22, ++0xE2, 0x54, 0xA3, 0x7D, 0x10, 0x2B, 0x01, 0xD8, 0x11, 0x23, 0xA3, 0x75, 0x02, 0x9B, 0x00, 0x2B, 0xBC, 0xD0, 0x01, 0x2D, ++0xBA, 0xD1, 0x39, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0xB5, 0xD1, 0x37, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x9F, 0x23, ++0xE3, 0x5C, 0x01, 0x2B, 0xAE, 0xD1, 0x35, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0xAA, 0xE7, 0x34, 0x4B, 0xDB, 0x88, 0x23, 0x61, ++0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0xB0, 0xD0, 0x00, 0x2E, 0xB1, 0xD1, 0x30, 0x4B, 0x23, 0x61, 0xA7, 0x23, 0xE3, 0x5C, ++0x00, 0x2B, 0x03, 0xD1, 0xA8, 0x22, 0xA2, 0x5C, 0x00, 0x2A, 0x2E, 0xD0, 0xA8, 0x22, 0xA1, 0x5C, 0xCB, 0x18, 0x2A, 0x49, ++0x59, 0x43, 0x29, 0x4B, 0x9C, 0x46, 0x61, 0x44, 0x21, 0x61, 0x23, 0x4B, 0x1A, 0x68, 0x53, 0x6F, 0x58, 0x42, 0x43, 0x41, ++0x5B, 0x42, 0x1B, 0x48, 0x03, 0x40, 0x24, 0x48, 0x84, 0x46, 0x63, 0x44, 0x92, 0x68, 0x00, 0x2A, 0x02, 0xD0, 0x22, 0x4A, ++0x12, 0x68, 0x9B, 0x1A, 0x99, 0x42, 0x00, 0xD9, 0x19, 0x00, 0x21, 0x61, 0x66, 0x68, 0x28, 0x22, 0x20, 0x00, 0xFA, 0xF7, ++0x63, 0xFE, 0x01, 0x28, 0x00, 0xD1, 0x7C, 0xE7, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x04, 0xD1, 0x63, 0x68, 0x03, 0x33, ++0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0x20, 0x00, 0xCF, 0xF7, 0x06, 0xFE, 0x00, 0x28, 0x9B, 0xD0, 0xA1, 0x23, 0xE3, 0x5C, ++0x04, 0x2B, 0x8F, 0xD0, 0x08, 0x21, 0x48, 0x46, 0x11, 0x4B, 0x98, 0x47, 0x5E, 0xE7, 0x00, 0x25, 0xC7, 0xE5, 0x00, 0x25, ++0xC5, 0xE5, 0x00, 0x23, 0x9B, 0x46, 0xFF, 0xE5, 0xAA, 0xF8, 0xFF, 0xFF, 0x98, 0x12, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, ++0x34, 0xE6, 0x10, 0x00, 0x88, 0x13, 0x00, 0x00, 0xB9, 0x4C, 0x0B, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x40, 0xE0, 0x10, 0x00, ++0x44, 0xE0, 0x10, 0x00, 0x5C, 0xAB, 0x16, 0x00, 0x5C, 0x1C, 0x00, 0x00, 0x7C, 0x42, 0x00, 0x00, 0xE8, 0xE1, 0x10, 0x00, ++0x95, 0x0F, 0x0B, 0x00, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0xB7, 0x4B, 0xB8, 0x4A, ++0x13, 0x60, 0x80, 0x22, 0x52, 0x00, 0x9C, 0x5C, 0xFD, 0xF7, 0x5A, 0xFA, 0xB5, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, ++0x09, 0xD0, 0xB2, 0x4B, 0x1D, 0x68, 0x02, 0x23, 0xFF, 0x33, 0xEB, 0x5C, 0xA3, 0x42, 0x00, 0xD1, 0x42, 0xE1, 0xB0, 0x4F, ++0x84, 0xE0, 0xFA, 0xF7, 0xFD, 0xFD, 0xF2, 0xE7, 0xAE, 0x4A, 0x93, 0x42, 0x46, 0xD1, 0xAE, 0x4B, 0x4B, 0x60, 0x43, 0xE0, ++0xAD, 0x49, 0x8B, 0x42, 0x00, 0xD1, 0xE5, 0xE0, 0xAC, 0x49, 0x8B, 0x42, 0x16, 0xD1, 0xAC, 0x4B, 0x1A, 0x68, 0x00, 0x2A, ++0x38, 0xD0, 0x23, 0x01, 0xED, 0x18, 0xA9, 0x68, 0x8B, 0x00, 0x9B, 0x58, 0x00, 0x9A, 0x48, 0x46, 0x02, 0x43, 0xD2, 0xB2, ++0x00, 0x2A, 0x04, 0xD0, 0x00, 0x29, 0x00, 0xD0, 0xCC, 0xE0, 0xD8, 0x22, 0x1A, 0x86, 0x00, 0x22, 0x9A, 0x62, 0x25, 0xE0, ++0xA1, 0x49, 0x8B, 0x42, 0x22, 0xD1, 0x02, 0x2A, 0x20, 0xD1, 0x00, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0xA5, 0xFB, 0x1B, 0xE0, ++0x9D, 0x4B, 0x1D, 0x68, 0x00, 0x9B, 0x4A, 0x46, 0x13, 0x43, 0xDB, 0xB2, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x23, 0xAB, 0x62, ++0x34, 0x33, 0x01, 0x22, 0xEA, 0x54, 0xAE, 0xF7, 0x53, 0xF8, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0xC0, 0x22, 0x92, 0x01, ++0x13, 0x40, 0x80, 0x22, 0x52, 0x01, 0x94, 0x46, 0x63, 0x44, 0x2B, 0x86, 0x12, 0x23, 0x6B, 0x86, 0x86, 0x4B, 0x1B, 0x68, ++0x52, 0x46, 0x98, 0x18, 0x45, 0x68, 0x00, 0x2D, 0x00, 0xD1, 0xD1, 0xE0, 0x42, 0x46, 0x04, 0x3A, 0x51, 0x42, 0x4A, 0x41, ++0xD2, 0xB2, 0x31, 0x01, 0x5B, 0x18, 0x99, 0x68, 0x00, 0x68, 0xA8, 0x47, 0x7D, 0x4B, 0x1D, 0x68, 0x33, 0x01, 0xEB, 0x18, ++0x85, 0x4A, 0x5B, 0x68, 0x93, 0x42, 0x00, 0xD1, 0xC5, 0xE0, 0x33, 0x01, 0xEB, 0x18, 0x00, 0x22, 0x1A, 0x73, 0x03, 0x32, ++0xFF, 0x32, 0xAB, 0x5C, 0x01, 0x3B, 0xAB, 0x54, 0x02, 0x23, 0xFF, 0x33, 0xEA, 0x5C, 0x0F, 0x21, 0xA2, 0x42, 0x00, 0xD1, ++0xC5, 0xE0, 0x01, 0x34, 0x0C, 0x40, 0x23, 0x01, 0xEB, 0x18, 0x1B, 0x7B, 0x00, 0x2B, 0xF5, 0xD0, 0x80, 0x23, 0x5B, 0x00, ++0xEC, 0x54, 0xA2, 0x42, 0x00, 0xD1, 0xBB, 0xE0, 0x26, 0x00, 0x75, 0x4B, 0xE3, 0x18, 0x1B, 0x01, 0x1B, 0x88, 0x9B, 0x06, ++0x5B, 0x0F, 0x98, 0x46, 0x03, 0x3B, 0x02, 0x2B, 0x00, 0xD9, 0xAF, 0xE0, 0xFB, 0xF7, 0x70, 0xFD, 0x00, 0x90, 0x01, 0x90, ++0x3A, 0x68, 0x00, 0x23, 0x01, 0x21, 0x91, 0x42, 0x5B, 0x41, 0xDB, 0xB2, 0x99, 0x46, 0x23, 0x01, 0x9A, 0x46, 0xE9, 0x18, ++0x4B, 0x68, 0x69, 0x48, 0x83, 0x42, 0x62, 0xD0, 0x00, 0xD9, 0x63, 0xE7, 0x67, 0x4A, 0x93, 0x42, 0x88, 0xD0, 0x63, 0x4A, ++0x93, 0x42, 0x00, 0xD0, 0x56, 0xE7, 0x65, 0x4B, 0x1D, 0x68, 0x00, 0x23, 0xAB, 0x62, 0x51, 0x33, 0x01, 0x22, 0xEA, 0x54, ++0xAD, 0xF7, 0xDE, 0xFF, 0x00, 0x28, 0x05, 0xD0, 0x80, 0x23, 0x9B, 0x01, 0xAB, 0x85, 0x06, 0x23, 0xEB, 0x85, 0x8F, 0xE7, ++0x50, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x0B, 0xD0, 0x00, 0x9B, 0x4A, 0x46, 0x13, 0x43, 0xDB, 0xB2, 0x00, 0x2B, 0x1C, 0xD1, ++0x80, 0x23, 0x1B, 0x01, 0xAB, 0x85, 0x12, 0x23, 0xEB, 0x85, 0x7F, 0xE7, 0x55, 0x4B, 0xEB, 0x61, 0x01, 0x9B, 0x00, 0x2B, ++0x03, 0xD1, 0xFD, 0xF7, 0x13, 0xFA, 0x01, 0x28, 0x07, 0xD9, 0x00, 0x9A, 0xD3, 0x02, 0xAB, 0x85, 0x09, 0x23, 0x9B, 0x1A, ++0x5B, 0x00, 0xEB, 0x85, 0x6E, 0xE7, 0x80, 0x23, 0x5B, 0x00, 0xAB, 0x85, 0xEE, 0x3B, 0xEB, 0x85, 0x68, 0xE7, 0xFD, 0xF7, ++0x41, 0xF9, 0x01, 0x28, 0x00, 0xD8, 0x63, 0xE7, 0x80, 0x23, 0xDB, 0x01, 0xAB, 0x85, 0x08, 0x23, 0xEB, 0x85, 0x5D, 0xE7, ++0xC8, 0x22, 0x92, 0x00, 0x1A, 0x86, 0x30, 0xE7, 0x01, 0x2A, 0x00, 0xD9, 0x56, 0xE7, 0x01, 0x9B, 0x00, 0x2B, 0x00, 0xD1, ++0x52, 0xE7, 0x23, 0x01, 0xED, 0x18, 0xAB, 0x68, 0x9B, 0x00, 0x3E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x68, 0xC0, 0x22, ++0x12, 0x01, 0xDA, 0x66, 0x46, 0xE7, 0x02, 0x2A, 0x00, 0xD0, 0x43, 0xE7, 0x23, 0x01, 0xED, 0x18, 0x2B, 0x7A, 0x9B, 0x00, ++0x37, 0x4A, 0x9D, 0x58, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x03, 0xD1, 0x35, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x09, 0xD0, ++0xA0, 0x23, 0xEB, 0x5C, 0x02, 0x2B, 0x00, 0xD0, 0x30, 0xE7, 0x01, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0xB5, 0xFA, 0x2B, 0xE7, ++0xFF, 0xF7, 0x92, 0xFA, 0x00, 0x23, 0x2D, 0x4A, 0x13, 0x70, 0xEF, 0xE7, 0x2C, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x30, 0xE7, 0x24, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x00, 0xD1, 0x34, 0xE7, 0x11, 0x22, 0x9A, 0x75, ++0x31, 0xE7, 0xFB, 0xF7, 0x93, 0xFB, 0x11, 0xE0, 0x80, 0x20, 0x80, 0x00, 0x7A, 0xF7, 0xE2, 0xFD, 0x13, 0xE0, 0x80, 0x23, ++0x5B, 0x00, 0xEC, 0x54, 0x81, 0x23, 0x5B, 0x00, 0xEB, 0x5C, 0x00, 0x2B, 0x04, 0xD1, 0x05, 0x33, 0xFF, 0x33, 0xEB, 0x58, ++0x00, 0x2B, 0xEA, 0xD0, 0x07, 0x4B, 0x1A, 0x68, 0x81, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0x00, 0x2B, 0xE6, 0xD0, 0x02, 0xB0, ++0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, ++0xF4, 0xE1, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x31, 0xC3, 0x0A, 0x00, 0xE1, 0xA1, 0x10, 0x00, 0xE9, 0x8F, 0x0C, 0x00, ++0xCD, 0x05, 0x0D, 0x00, 0xF0, 0x29, 0x16, 0x00, 0x5D, 0x74, 0x0B, 0x00, 0x20, 0x27, 0x16, 0x00, 0xD9, 0xEA, 0x0A, 0x00, ++0x00, 0x10, 0x06, 0x04, 0x11, 0x6F, 0x0B, 0x00, 0x99, 0xCA, 0x0A, 0x00, 0x28, 0x27, 0x16, 0x00, 0x01, 0x00, 0x10, 0x00, ++0x84, 0x29, 0x16, 0x00, 0x38, 0x27, 0x16, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x04, 0x4B, ++0x1B, 0x7F, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0x02, 0x4B, 0x98, 0x47, 0xFB, 0xE7, 0xC0, 0x46, 0x24, 0x2A, 0x16, 0x00, ++0x69, 0x44, 0x0D, 0x00, 0x10, 0xB5, 0x05, 0x4B, 0x80, 0x22, 0xD2, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, ++0xAF, 0xF8, 0xFF, 0xF7, 0xE7, 0xFF, 0x10, 0xBD, 0x08, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x2D, 0x4B, 0x1B, 0x68, 0xC0, 0x22, ++0x92, 0x02, 0x13, 0x42, 0x16, 0xD1, 0x5A, 0x03, 0x1E, 0xD4, 0x1A, 0x03, 0x2D, 0xD4, 0xDA, 0x02, 0x34, 0xD4, 0x9A, 0x02, ++0x36, 0xD4, 0x5A, 0x02, 0x38, 0xD4, 0xDA, 0x01, 0x39, 0xD4, 0x9A, 0x01, 0x3E, 0xD4, 0x5B, 0x01, 0x0F, 0xD5, 0xFD, 0xF7, ++0x1B, 0xFF, 0x22, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0x08, 0xE0, 0x20, 0x4D, 0x91, 0x24, 0xE4, 0x00, 0x00, 0x23, ++0x2B, 0x51, 0x84, 0xF7, 0x7F, 0xFB, 0x1E, 0x4B, 0x2B, 0x51, 0x70, 0xBD, 0x1D, 0x4B, 0x1C, 0x78, 0xFE, 0xF7, 0x84, 0xFE, ++0x02, 0x2C, 0x04, 0xD0, 0x17, 0x4B, 0x80, 0x22, 0xD2, 0x02, 0x1A, 0x60, 0xF3, 0xE7, 0x19, 0x4B, 0x01, 0x22, 0x1A, 0x70, ++0x84, 0xF7, 0x32, 0xFB, 0xED, 0xE7, 0x12, 0x4B, 0x80, 0x22, 0x12, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, ++0x3F, 0xFD, 0xE4, 0xE7, 0x01, 0x20, 0x84, 0xF7, 0x3D, 0xFB, 0xE0, 0xE7, 0x02, 0x20, 0x84, 0xF7, 0x39, 0xFB, 0xDC, 0xE7, ++0xFF, 0xF7, 0xA6, 0xFF, 0xD9, 0xE7, 0xFA, 0xF7, 0xF1, 0xFD, 0x07, 0x4B, 0x80, 0x22, 0x52, 0x04, 0x1A, 0x60, 0xD2, 0xE7, ++0xFA, 0xF7, 0x9A, 0xFF, 0x03, 0x4B, 0x80, 0x22, 0x92, 0x04, 0x1A, 0x60, 0xCB, 0xE7, 0xC0, 0x46, 0x1C, 0x41, 0x04, 0x40, ++0x08, 0x41, 0x04, 0x40, 0x28, 0x19, 0x16, 0x00, 0x31, 0x6D, 0x10, 0x00, 0xE0, 0x1D, 0x16, 0x00, 0xE1, 0x1D, 0x16, 0x00, ++0x10, 0xB5, 0x04, 0x4B, 0x80, 0x22, 0x12, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, 0x0F, 0xFD, 0x10, 0xBD, ++0x08, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x09, 0x4B, 0xDB, 0x7F, 0x00, 0x2B, 0x08, 0xD0, 0x00, 0x28, 0x01, 0xD1, 0x00, 0x29, ++0x04, 0xD0, 0x01, 0x20, 0x80, 0xF7, 0xD6, 0xFF, 0x84, 0xF7, 0x00, 0xFD, 0x03, 0x49, 0x40, 0x22, 0x0B, 0x6B, 0x1A, 0x42, ++0xFC, 0xD0, 0x10, 0xBD, 0x3C, 0x95, 0x16, 0x00, 0x00, 0x60, 0x50, 0x40, 0x70, 0xB5, 0x82, 0xB0, 0x27, 0x4A, 0xD3, 0x69, ++0x0F, 0x24, 0xA3, 0x43, 0xD3, 0x61, 0x26, 0x4B, 0x99, 0x68, 0x80, 0x20, 0x01, 0x43, 0x99, 0x60, 0x59, 0x68, 0x01, 0x43, ++0x59, 0x60, 0x19, 0x68, 0x01, 0x43, 0x19, 0x60, 0x13, 0x69, 0xA3, 0x43, 0x13, 0x61, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, ++0xEF, 0xFC, 0x01, 0x9C, 0x00, 0x9B, 0x1E, 0x00, 0x7A, 0x36, 0x9C, 0x22, 0x92, 0x00, 0x96, 0x42, 0x19, 0xD9, 0xF8, 0x3B, ++0xFF, 0x3B, 0x1E, 0x00, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0x80, 0x25, 0x2D, 0x05, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, ++0xDB, 0xFC, 0x01, 0x9A, 0xA3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xAB, 0x42, 0xF5, 0xD9, 0x12, 0x1B, 0x12, 0x01, 0xF2, 0xD0, ++0x00, 0x9B, 0xB3, 0x42, 0xEF, 0xD3, 0x02, 0xB0, 0x70, 0xBD, 0xB3, 0x42, 0xE9, 0xD2, 0x80, 0x25, 0x2D, 0x05, 0x02, 0xE0, ++0x00, 0x9B, 0xB3, 0x42, 0xF5, 0xD2, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, 0xC1, 0xFC, 0x01, 0x9A, 0xA3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0xAB, 0x42, 0xF2, 0xD9, 0x12, 0x1B, 0x12, 0x01, 0xEF, 0xD0, 0xE7, 0xE7, 0xC0, 0x46, 0x00, 0x30, 0x50, 0x40, ++0x00, 0x40, 0x50, 0x40, 0x70, 0xB5, 0x10, 0x4B, 0x9A, 0x69, 0x10, 0x4B, 0x1A, 0x42, 0x0A, 0xD1, 0x0F, 0x4D, 0x10, 0x4C, ++0x29, 0x68, 0x00, 0x20, 0xFA, 0xF7, 0xD0, 0xFC, 0x7B, 0xF7, 0x96, 0xFD, 0x23, 0x68, 0x01, 0x2B, 0xF6, 0xD0, 0x0C, 0x4A, ++0x13, 0x68, 0x01, 0x33, 0x13, 0x60, 0x0B, 0x4B, 0x1B, 0x68, 0x03, 0x3B, 0x01, 0x2B, 0x00, 0xD9, 0x70, 0xBD, 0x03, 0x4A, ++0x80, 0x23, 0x1B, 0x02, 0x91, 0x69, 0x0B, 0x43, 0x93, 0x61, 0xF7, 0xE7, 0x3C, 0x95, 0x16, 0x00, 0x01, 0x20, 0x00, 0x00, ++0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x20, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x02, 0x38, 0x01, 0x28, ++0x11, 0xD8, 0x09, 0x4A, 0x80, 0x23, 0x5B, 0x00, 0x08, 0x21, 0xD1, 0x50, 0x07, 0x49, 0x8B, 0x68, 0x07, 0x4A, 0x1A, 0x40, ++0x80, 0x23, 0x9B, 0x02, 0x13, 0x43, 0x8B, 0x60, 0x22, 0x22, 0x0B, 0x6B, 0x13, 0x40, 0x02, 0x2B, 0xFB, 0xD1, 0x70, 0x47, ++0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, 0xFF, 0xFF, 0xFB, 0xFF, 0x70, 0xB5, 0xA6, 0xF7, 0x3D, 0xFF, 0x04, 0x1E, ++0x0D, 0xD1, 0x1A, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x09, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x17, 0xD4, 0x72, 0xB6, ++0x3E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x62, 0xB6, 0x20, 0x00, 0x70, 0xBD, 0x13, 0x4B, 0x1D, 0x68, 0x00, 0x21, ++0xCF, 0xF7, 0x7A, 0xFC, 0x2B, 0x6B, 0x5B, 0x00, 0x6A, 0x68, 0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x0E, 0x4A, 0x13, 0x60, ++0x0E, 0x4B, 0x98, 0x47, 0xEC, 0xE7, 0x3E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0xE9, 0xD1, 0x09, 0x4B, 0x1D, 0x68, 0x00, 0x21, ++0xCF, 0xF7, 0x66, 0xFC, 0x2B, 0x6B, 0x5B, 0x00, 0x6A, 0x68, 0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x04, 0x4A, 0x13, 0x60, ++0x04, 0x4B, 0x98, 0x47, 0xD9, 0xE7, 0xC0, 0x46, 0x28, 0x27, 0x16, 0x00, 0x24, 0x27, 0x16, 0x00, 0x18, 0x2C, 0x16, 0x00, ++0x15, 0xE6, 0x0A, 0x00, 0x10, 0xB5, 0xA5, 0xF7, 0xC7, 0xFA, 0x00, 0x28, 0x0F, 0xD1, 0x0B, 0x4B, 0x19, 0x68, 0x00, 0x29, ++0x0B, 0xD0, 0x0A, 0x4B, 0xCB, 0x61, 0x0A, 0x4B, 0x1C, 0x00, 0x41, 0x34, 0xFF, 0x34, 0x1A, 0x78, 0x09, 0x2A, 0x03, 0xD0, ++0x40, 0x33, 0xA3, 0x42, 0xF9, 0xD1, 0x10, 0xBD, 0x0B, 0x69, 0x05, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x0B, 0x61, 0xF8, 0xE7, ++0x18, 0x27, 0x16, 0x00, 0x51, 0x04, 0x10, 0x00, 0x70, 0xA6, 0x16, 0x00, 0x78, 0xEC, 0xFF, 0xFF, 0x10, 0xB5, 0x02, 0x00, ++0x0C, 0x00, 0x01, 0x23, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0xC2, 0xFF, 0x04, 0x70, 0xCC, 0xF7, 0x1F, 0xFE, 0x10, 0xBD, ++0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x02, 0x00, 0x0C, 0x00, 0x01, 0x23, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0xB4, 0xFF, ++0x04, 0x70, 0xCC, 0xF7, 0x11, 0xFE, 0x10, 0xBD, 0x02, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x06, 0x23, 0x13, 0x4A, 0x00, 0x21, ++0x13, 0x48, 0x7A, 0xF7, 0xA7, 0xFF, 0x13, 0x4A, 0x2D, 0x23, 0xD3, 0x5C, 0x1B, 0x09, 0x12, 0x4A, 0x12, 0x78, 0x02, 0x2A, ++0x0B, 0xD0, 0x01, 0x2A, 0x10, 0xD0, 0x0E, 0x4A, 0x2D, 0x23, 0xD3, 0x5C, 0x03, 0x71, 0x00, 0x23, 0x03, 0x70, 0xCC, 0xF7, ++0xF5, 0xFD, 0x00, 0x20, 0x10, 0xBD, 0x0B, 0x4A, 0xD2, 0x5C, 0x80, 0x23, 0x9B, 0x00, 0x13, 0x43, 0x43, 0x80, 0xEE, 0xE7, ++0x08, 0x4A, 0xD2, 0x5C, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x43, 0x80, 0xE7, 0xE7, 0xC0, 0x46, 0x2D, 0x0C, 0x00, 0x00, ++0x01, 0x11, 0x00, 0x00, 0x60, 0x92, 0x16, 0x00, 0xB4, 0xE5, 0x10, 0x00, 0x30, 0xE0, 0x10, 0x00, 0x28, 0xE0, 0x10, 0x00, ++0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x19, 0x78, 0x03, 0x4A, 0x2D, 0x23, 0xD1, 0x54, 0x00, 0x21, 0xFF, 0xF7, 0xB2, 0xFF, ++0x00, 0x20, 0x10, 0xBD, 0x60, 0x92, 0x16, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0xD1, 0xF7, 0x96, 0xFF, ++0x06, 0x00, 0x2C, 0x4B, 0x99, 0x6F, 0x00, 0x29, 0x15, 0xD0, 0xF8, 0x22, 0x20, 0x00, 0xD1, 0xF7, 0xBB, 0xFF, 0x00, 0x21, ++0x00, 0x28, 0x0A, 0xD1, 0x26, 0x4A, 0x30, 0x23, 0xD3, 0x5C, 0x01, 0x2B, 0x21, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0x86, 0xFF, ++0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x21, 0x4B, 0x98, 0x6F, 0x7B, 0xF7, 0xBF, 0xF8, 0xFF, 0x20, 0x06, 0x40, 0xF8, 0x2E, ++0x00, 0xD9, 0xF8, 0x26, 0x70, 0x1C, 0x00, 0x21, 0x7B, 0xF7, 0x12, 0xF8, 0x1A, 0x4B, 0x98, 0x67, 0x07, 0x21, 0x00, 0x28, ++0xE2, 0xD0, 0x32, 0x00, 0x21, 0x00, 0xD1, 0xF7, 0x2F, 0xFE, 0x16, 0x4B, 0x9B, 0x6F, 0x00, 0x22, 0x9A, 0x55, 0x00, 0x21, ++0xD8, 0xE7, 0x7F, 0x33, 0x5B, 0x00, 0x2F, 0x22, 0x00, 0x21, 0x12, 0x48, 0x7A, 0xF7, 0x2A, 0xFF, 0x06, 0x00, 0x01, 0xA9, ++0x0D, 0x70, 0x2D, 0x0A, 0x4D, 0x70, 0xF8, 0x23, 0x8B, 0x70, 0x03, 0x22, 0xD1, 0xF7, 0x18, 0xFE, 0xF0, 0x1C, 0xF8, 0x22, ++0x21, 0x00, 0xD1, 0xF7, 0x13, 0xFE, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x30, 0x00, 0x0C, 0x38, 0x08, 0x4B, 0x98, 0x47, ++0x08, 0x4B, 0x5B, 0x7F, 0x5B, 0xB2, 0x04, 0x2B, 0xBE, 0xDC, 0x01, 0x33, 0x05, 0x4A, 0x53, 0x77, 0xBA, 0xE7, 0xC0, 0x46, ++0x68, 0x9E, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, 0x68, 0xE6, 0x10, 0x00, 0xA5, 0x4B, 0x0D, 0x00, 0x24, 0x2A, 0x16, 0x00, ++0xF8, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x16, 0x00, 0x1F, 0x00, 0x02, 0x20, 0x79, 0xF7, 0x46, 0xFE, 0x6B, 0x1E, 0x1C, 0x70, ++0x63, 0x1E, 0x03, 0x2B, 0x22, 0xD8, 0x04, 0x2C, 0x10, 0xD0, 0x68, 0x1E, 0x16, 0x4B, 0x18, 0x61, 0x1E, 0x83, 0x5F, 0x61, ++0x1B, 0x7F, 0xFF, 0x2B, 0x25, 0xD1, 0x13, 0x4B, 0x00, 0x22, 0x1A, 0x77, 0x71, 0x1C, 0x1A, 0x68, 0x54, 0x68, 0x11, 0x4A, ++0xA0, 0x47, 0x1C, 0xE0, 0x2B, 0x78, 0x2F, 0x2B, 0xEB, 0xD1, 0x0F, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xE7, 0xD0, 0x19, 0x23, ++0x2B, 0x70, 0xE2, 0x33, 0x6B, 0x70, 0x0B, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xFD, 0x26, 0xDE, 0xE7, 0x09, 0x4D, 0x00, 0x23, ++0x00, 0x22, 0x01, 0x21, 0x20, 0x00, 0xEE, 0x6E, 0xB0, 0x47, 0xED, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x01, 0x21, 0x20, 0x00, ++0xA8, 0x47, 0xF8, 0xBD, 0x58, 0x1E, 0x16, 0x00, 0x19, 0x74, 0x08, 0x00, 0x68, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0xC0, 0xB5, 0x86, 0xB0, 0x04, 0x00, 0x0E, 0x00, 0x03, 0x92, 0xCE, 0xF7, ++0x93, 0xFE, 0x07, 0x00, 0xB8, 0x4B, 0x1D, 0x25, 0x5D, 0x57, 0x2B, 0x00, 0x80, 0x33, 0x00, 0xD1, 0x61, 0xE1, 0x01, 0x3D, ++0x6D, 0xB2, 0xB4, 0x4B, 0x5D, 0x77, 0x00, 0x28, 0x00, 0xD1, 0x18, 0xE1, 0x00, 0x2D, 0x00, 0xDA, 0x59, 0xE1, 0x80, 0x78, ++0x0F, 0x23, 0x18, 0x40, 0x08, 0x28, 0x5F, 0xD8, 0x83, 0x00, 0xAE, 0x4A, 0xD3, 0x58, 0x9F, 0x46, 0x05, 0x23, 0x99, 0x46, ++0x67, 0xE0, 0x06, 0x28, 0x1E, 0xD0, 0x01, 0x2E, 0x00, 0xD8, 0x3B, 0xE1, 0x03, 0x9A, 0x53, 0x78, 0x1B, 0x02, 0x12, 0x78, ++0x13, 0x43, 0x0B, 0x2B, 0x00, 0xD9, 0x22, 0xE1, 0xA5, 0x4A, 0xD2, 0x18, 0x12, 0x7E, 0x00, 0x2A, 0x00, 0xD1, 0x2D, 0xE1, ++0xA2, 0x04, 0x37, 0xD4, 0xA2, 0x4A, 0x94, 0x42, 0x34, 0xD0, 0x27, 0xD8, 0xA1, 0x4A, 0x94, 0x42, 0x30, 0xD0, 0xA1, 0x4A, ++0x94, 0x42, 0x00, 0xD0, 0x20, 0xE1, 0x2B, 0xE0, 0x05, 0x2E, 0x00, 0xD8, 0x1C, 0xE1, 0x9E, 0x4D, 0x00, 0x23, 0x99, 0x46, ++0x07, 0xE0, 0x01, 0x23, 0x9C, 0x46, 0xE1, 0x44, 0x07, 0x35, 0x4B, 0x46, 0x07, 0x2B, 0x00, 0xD1, 0x10, 0xE1, 0x2B, 0x78, ++0x00, 0x2B, 0xF4, 0xD0, 0x69, 0x1C, 0x06, 0x22, 0x03, 0x98, 0xD1, 0xF7, 0x2D, 0xFD, 0x00, 0x28, 0xED, 0xD1, 0x4B, 0x46, ++0x1B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x26, 0xE0, 0x90, 0x4A, 0x94, 0x42, 0x04, 0xD8, 0x90, 0x4A, ++0x94, 0x42, 0x00, 0xD8, 0xF8, 0xE0, 0x03, 0xE0, 0x8E, 0x4A, 0x94, 0x42, 0x00, 0xD0, 0xF3, 0xE0, 0x1B, 0x02, 0x04, 0x22, ++0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x14, 0xE0, 0x1B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x0E, 0xE0, ++0x87, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xA8, 0x47, 0xAF, 0xE0, 0x03, 0x23, 0x99, 0x46, 0x04, 0xE0, ++0x02, 0x23, 0x99, 0x46, 0x01, 0xE0, 0x00, 0x23, 0x99, 0x46, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x00, 0x22, ++0x1A, 0x80, 0x7E, 0x4B, 0x92, 0x46, 0x9C, 0x42, 0x59, 0xD0, 0x00, 0x2E, 0x00, 0xD1, 0xAD, 0xE0, 0x7D, 0x68, 0x00, 0x2D, ++0x00, 0xD1, 0x9C, 0xE0, 0xBB, 0x78, 0x5B, 0x06, 0x65, 0xD5, 0xB3, 0xB2, 0x0E, 0x22, 0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, ++0x03, 0x99, 0x00, 0x20, 0xA8, 0x47, 0xC5, 0xB2, 0x01, 0x2D, 0x66, 0xD0, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, ++0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x6F, 0x48, 0x7A, 0xF7, 0x00, 0xFE, 0x81, 0x46, 0x00, 0x2D, 0x07, 0xD0, 0x6A, 0x4B, ++0xDB, 0x6E, 0x9B, 0x46, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0x28, 0x00, 0xD8, 0x47, 0x4B, 0x46, 0x00, 0x2B, 0x59, 0xD0, ++0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x00, 0x2B, 0x0F, 0xD0, 0x7B, 0x68, 0x9B, 0x46, 0x00, 0x2B, ++0x0B, 0xD0, 0xBB, 0x78, 0x5B, 0x06, 0x51, 0xD5, 0xB3, 0xB2, 0x0E, 0x22, 0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, 0x03, 0x99, ++0x48, 0x46, 0xD8, 0x47, 0xC5, 0xB2, 0x00, 0x2D, 0x06, 0xD0, 0x58, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, ++0x28, 0x00, 0xB0, 0x47, 0x48, 0x46, 0x7A, 0xF7, 0xF9, 0xFD, 0x54, 0x4B, 0x9C, 0x42, 0x4A, 0xD1, 0x53, 0x46, 0x00, 0x2B, ++0x47, 0xD0, 0x50, 0x46, 0x7A, 0xF7, 0x3C, 0xFF, 0x43, 0xE0, 0x75, 0x1C, 0x01, 0x21, 0x28, 0x00, 0x7A, 0xF7, 0x92, 0xFE, ++0x82, 0x46, 0x03, 0x99, 0x0B, 0x78, 0x03, 0x70, 0x72, 0x1E, 0x42, 0x70, 0x01, 0x31, 0x02, 0x30, 0xD1, 0xF7, 0xAE, 0xFC, ++0xEE, 0xB2, 0x49, 0x48, 0x7C, 0xF7, 0xB6, 0xFE, 0x53, 0x46, 0x03, 0x93, 0x8F, 0xE7, 0xB3, 0xB2, 0x00, 0x95, 0x0E, 0x22, ++0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, 0x03, 0x99, 0x00, 0x20, 0x7D, 0xF7, 0x57, 0xF8, 0x05, 0x00, 0x96, 0xE7, 0x21, 0x00, ++0x40, 0x48, 0x7C, 0xF7, 0xA3, 0xFE, 0x00, 0x23, 0x12, 0x22, 0x21, 0x00, 0x38, 0x00, 0x3E, 0x4D, 0xA8, 0x47, 0xC8, 0xE7, ++0x07, 0x22, 0x21, 0x00, 0x38, 0x00, 0x3B, 0x4D, 0xA8, 0x47, 0xC2, 0xE7, 0xB3, 0xB2, 0x5A, 0x46, 0x00, 0x92, 0x0E, 0x22, ++0x62, 0x44, 0x03, 0x99, 0x48, 0x46, 0x7D, 0xF7, 0x3B, 0xF8, 0x05, 0x00, 0xAB, 0xE7, 0x00, 0x23, 0x01, 0x22, 0x21, 0x00, ++0x00, 0x20, 0x32, 0x4C, 0xA0, 0x47, 0x06, 0xB0, 0x1C, 0xBC, 0x91, 0x46, 0x9A, 0x46, 0xA3, 0x46, 0xF0, 0xBD, 0x0E, 0x23, ++0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x27, 0x48, 0x7A, 0xF7, 0x71, 0xFD, 0x81, 0x46, ++0x04, 0x25, 0x70, 0xE7, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x21, 0x48, ++0x7A, 0xF7, 0x64, 0xFD, 0x81, 0x46, 0x35, 0x00, 0x6B, 0xE7, 0x22, 0x4A, 0x13, 0x40, 0x1A, 0x00, 0x80, 0x3A, 0x92, 0xB2, ++0x06, 0x2A, 0x09, 0xD8, 0x80, 0x3B, 0xD9, 0x00, 0xC9, 0x1A, 0x0F, 0x4A, 0x52, 0x18, 0x24, 0x32, 0x12, 0x78, 0x02, 0x2A, ++0x00, 0xD1, 0x11, 0xE7, 0x21, 0x00, 0x1A, 0x48, 0x7C, 0xF7, 0x50, 0xFE, 0x03, 0x9B, 0x02, 0x22, 0x21, 0x00, 0x38, 0x00, ++0x14, 0x4C, 0xA0, 0x47, 0xC3, 0xE7, 0x00, 0x28, 0xBB, 0xD0, 0x00, 0x23, 0x07, 0x22, 0x21, 0x00, 0x38, 0x00, 0x10, 0x4C, ++0xA0, 0x47, 0xBA, 0xE7, 0x24, 0x2A, 0x16, 0x00, 0x2C, 0xD2, 0x10, 0x00, 0xCC, 0xAA, 0x16, 0x00, 0x2D, 0x0C, 0x00, 0x00, ++0x06, 0x04, 0x00, 0x00, 0x1D, 0x04, 0x00, 0x00, 0xF0, 0xAA, 0x16, 0x00, 0x7C, 0x0C, 0x00, 0x00, 0x7A, 0x0C, 0x00, 0x00, ++0x05, 0x14, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0x57, 0xFD, 0x00, 0x00, 0x05, 0x11, 0x00, 0x00, 0x14, 0xD2, 0x10, 0x00, ++0x20, 0xD2, 0x10, 0x00, 0x7D, 0x4A, 0x0D, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0x08, 0xD2, 0x10, 0x00, 0x10, 0xB5, 0x07, 0x20, ++0x7B, 0xF7, 0x10, 0xFA, 0x08, 0x4C, 0xA1, 0x7A, 0x20, 0x89, 0x62, 0x68, 0xFF, 0xF7, 0x54, 0xFE, 0x60, 0x68, 0x00, 0x28, ++0x03, 0xD0, 0x7A, 0xF7, 0x7F, 0xFE, 0x00, 0x22, 0x62, 0x60, 0x02, 0x48, 0x02, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0xC0, 0x46, ++0x58, 0x1E, 0x16, 0x00, 0xA5, 0x73, 0x08, 0x00, 0x30, 0xB5, 0x0C, 0x4C, 0x25, 0x68, 0x29, 0x60, 0x24, 0x68, 0x60, 0x60, ++0xA2, 0x60, 0xE3, 0x60, 0x09, 0x4B, 0x0A, 0x4A, 0x98, 0x50, 0x0A, 0x48, 0x1A, 0x58, 0x0A, 0x43, 0x1A, 0x50, 0x04, 0x30, ++0x1A, 0x58, 0x11, 0x43, 0x19, 0x50, 0x07, 0x49, 0x5A, 0x58, 0x01, 0x20, 0x02, 0x43, 0x5A, 0x50, 0x30, 0xBD, 0xC0, 0x46, ++0xFC, 0xE1, 0x10, 0x00, 0x00, 0x00, 0x07, 0x40, 0x10, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, ++0x70, 0xB5, 0x0D, 0x00, 0x1A, 0x4C, 0x30, 0x21, 0x61, 0x5C, 0x01, 0x29, 0x04, 0xD0, 0x29, 0x00, 0x18, 0x4C, 0xA0, 0x47, ++0x00, 0x20, 0x70, 0xBD, 0x14, 0x0A, 0x84, 0xF7, 0x99, 0xFD, 0x06, 0x1E, 0x1F, 0xD0, 0x6A, 0x88, 0xA9, 0x88, 0x14, 0x4B, ++0x9C, 0x46, 0x61, 0x44, 0x00, 0x89, 0x60, 0x44, 0xD1, 0xF7, 0xB8, 0xFB, 0x08, 0x23, 0x00, 0x22, 0x21, 0x00, 0x10, 0x48, ++0x7A, 0xF7, 0xBA, 0xFC, 0x33, 0x89, 0x43, 0x60, 0x2B, 0x88, 0x03, 0x80, 0x6B, 0x88, 0x43, 0x80, 0xCC, 0xF7, 0x12, 0xFB, ++0x20, 0x00, 0x80, 0x30, 0x01, 0x21, 0x0A, 0x4B, 0x98, 0x47, 0xA8, 0x88, 0x84, 0xF7, 0xCA, 0xFD, 0xD8, 0xE7, 0x08, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEF, 0xE7, 0x68, 0x9E, 0x16, 0x00, 0x49, 0x86, 0x0A, 0x00, ++0x00, 0x00, 0x61, 0x40, 0x06, 0x11, 0x00, 0x00, 0xC1, 0xDC, 0x09, 0x00, 0x28, 0x19, 0x16, 0x00, 0x42, 0x7A, 0x12, 0x02, ++0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x83, 0x7A, 0x8B, 0x70, 0x70, 0x47, 0xC2, 0x7A, 0x12, 0x02, 0x83, 0x7A, 0x13, 0x43, ++0x4B, 0x80, 0x42, 0x7A, 0x12, 0x02, 0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x70, 0x47, 0x83, 0x7A, 0x8B, 0x70, 0x42, 0x7A, ++0x12, 0x02, 0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x70, 0x47, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x00, 0x22, 0x02, 0x73, ++0x0B, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x03, 0x4A, 0x01, 0x21, 0xA0, 0x47, 0x04, 0x20, 0x7A, 0xF7, 0x91, 0xF8, 0x10, 0xBD, ++0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x01, 0x22, 0x02, 0x73, 0x08, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x03, 0x4A, ++0xA0, 0x47, 0x04, 0x20, 0x79, 0xF7, 0xAC, 0xFB, 0x10, 0xBD, 0xC0, 0x46, 0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, ++0x02, 0x22, 0x02, 0x73, 0x40, 0x68, 0x1A, 0x68, 0x14, 0x68, 0x01, 0x4A, 0xA0, 0x47, 0x10, 0xBD, 0x59, 0x78, 0x10, 0x00, ++0x10, 0xB5, 0x03, 0x00, 0x03, 0x22, 0x02, 0x73, 0x0B, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x02, 0x4A, 0x01, 0x21, 0xA0, 0x47, ++0x10, 0xBD, 0xC0, 0x46, 0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x01, 0x23, 0x10, 0x22, 0x00, 0x21, 0x0B, 0x48, ++0x7A, 0xF7, 0x38, 0xFC, 0x00, 0x23, 0x03, 0x70, 0xCC, 0xF7, 0x94, 0xFA, 0x20, 0x00, 0x08, 0x30, 0x02, 0x22, 0x00, 0x21, ++0x78, 0xF7, 0xB2, 0xFC, 0xE3, 0x7A, 0xA3, 0x72, 0x20, 0x00, 0xFF, 0xF7, 0xDB, 0xFF, 0x04, 0x20, 0x7A, 0xF7, 0x4A, 0xF8, ++0x10, 0xBD, 0xC0, 0x46, 0x03, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x06, 0x20, 0x7B, 0xF7, 0x1A, 0xF9, 0x16, 0x4C, 0x17, 0x49, ++0x20, 0x00, 0xFF, 0xF7, 0x83, 0xFF, 0xA4, 0x7A, 0x00, 0x2C, 0x09, 0xD1, 0x12, 0x4C, 0x20, 0x89, 0x00, 0x22, 0x00, 0x21, ++0xFF, 0xF7, 0x56, 0xFD, 0x20, 0x00, 0xFF, 0xF7, 0x93, 0xFF, 0x10, 0xBD, 0x0D, 0x4B, 0x18, 0x89, 0xCD, 0xF7, 0x9C, 0xFA, ++0x84, 0x42, 0x03, 0xD9, 0x0A, 0x48, 0xFF, 0xF7, 0xC3, 0xFF, 0xF4, 0xE7, 0x08, 0x4C, 0xA0, 0x7A, 0x01, 0x21, 0x7A, 0xF7, ++0xCF, 0xFC, 0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0x20, 0x00, 0xA1, 0x7A, 0xFF, 0xF7, 0x9C, 0xFF, 0xE7, 0xE7, 0x02, 0x48, ++0xFF, 0xF7, 0xB2, 0xFF, 0xE3, 0xE7, 0xC0, 0x46, 0x58, 0x1E, 0x16, 0x00, 0x60, 0x1E, 0x16, 0x00, 0x10, 0xB5, 0x82, 0xB0, ++0x04, 0x00, 0x0E, 0x4B, 0x01, 0x93, 0x01, 0x00, 0x08, 0x31, 0x04, 0x22, 0x01, 0xA8, 0xD1, 0xF7, 0xB5, 0xFA, 0x00, 0x28, ++0x0B, 0xD0, 0x04, 0x20, 0x79, 0xF7, 0x2A, 0xFB, 0x63, 0x7A, 0x23, 0x72, 0xA3, 0x7A, 0x63, 0x72, 0xE3, 0x7A, 0xA3, 0x72, ++0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0x22, 0x00, 0x21, 0x03, 0x48, 0xCD, 0xF7, 0x6C, 0xFA, 0x01, 0x20, 0xF6, 0xE7, ++0x01, 0x03, 0x0C, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x00, 0x29, 0x0B, 0xD0, 0x01, 0x29, 0x02, 0xD0, ++0x03, 0x7B, 0x00, 0x2B, 0x03, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x7C, 0xFF, 0x10, 0xBD, 0xFF, 0xF7, 0x3F, 0xFF, 0xFB, 0xE7, ++0x03, 0x7B, 0x02, 0x2B, 0x44, 0xD0, 0x0F, 0xD8, 0x00, 0x2B, 0x17, 0xD0, 0x40, 0x7B, 0x02, 0x28, 0x25, 0xD0, 0x03, 0x28, ++0x27, 0xD0, 0x01, 0x28, 0x1D, 0xD0, 0xA1, 0x7B, 0x34, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA0, 0x47, 0xE7, 0xE7, ++0x03, 0x2B, 0x59, 0xD1, 0xFF, 0xF7, 0xB4, 0xFF, 0x00, 0x28, 0x51, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x21, 0xFF, 0xDD, 0xE7, ++0xC3, 0x7A, 0x43, 0x73, 0x5A, 0x1E, 0x02, 0x2A, 0x04, 0xD8, 0x2B, 0x4A, 0xD1, 0x5C, 0xFF, 0xF7, 0x27, 0xFF, 0xD3, 0xE7, ++0xFF, 0xF7, 0x4E, 0xFF, 0xD0, 0xE7, 0x05, 0x30, 0x7B, 0xF7, 0x5E, 0xF8, 0xCC, 0xE7, 0x08, 0x20, 0x7B, 0xF7, 0x5A, 0xF8, ++0xC8, 0xE7, 0x21, 0x00, 0x08, 0x31, 0x20, 0x00, 0xFF, 0xF7, 0xFD, 0xFE, 0xA1, 0x7A, 0x20, 0x89, 0xCD, 0xF7, 0x2E, 0xFC, ++0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0xA1, 0x7A, 0x20, 0x00, 0xFF, 0xF7, 0x1B, 0xFF, 0xB7, 0xE7, 0x20, 0x00, 0xFF, 0xF7, ++0x31, 0xFF, 0xB3, 0xE7, 0x40, 0x7B, 0x02, 0x28, 0x0E, 0xD0, 0x03, 0x28, 0x15, 0xD0, 0x01, 0x28, 0x06, 0xD0, 0xA1, 0x7B, ++0x13, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA0, 0x47, 0xA5, 0xE7, 0x06, 0x30, 0x7B, 0xF7, 0x33, 0xF8, 0xA1, 0xE7, ++0x61, 0x89, 0x20, 0x89, 0x62, 0x68, 0xCD, 0xF7, 0xB9, 0xFB, 0x20, 0x00, 0xFF, 0xF7, 0xDC, 0xFE, 0x98, 0xE7, 0xA1, 0x7A, ++0x20, 0x89, 0x62, 0x68, 0xCD, 0xF7, 0x2E, 0xFC, 0x20, 0x00, 0xFF, 0xF7, 0xD3, 0xFE, 0x8F, 0xE7, 0x20, 0x00, 0xFF, 0xF7, ++0xFB, 0xFE, 0x8B, 0xE7, 0x03, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x84, 0xE7, 0xC0, 0x46, ++0x28, 0x19, 0x16, 0x00, 0xC8, 0xDF, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, 0x03, 0x05, 0x1B, 0x0D, 0x82, 0x0B, 0x0B, 0x2B, ++0x1C, 0xD8, 0x00, 0x2A, 0x4C, 0xD1, 0x19, 0x02, 0x04, 0x22, 0x0A, 0x43, 0x92, 0xB2, 0xF8, 0x21, 0x09, 0x01, 0x08, 0x42, ++0x1F, 0xD1, 0xFB, 0x21, 0xFF, 0x2A, 0x46, 0xD0, 0x8C, 0x42, 0x44, 0xD8, 0xFF, 0x23, 0x13, 0x40, 0x02, 0x2B, 0x26, 0xD9, ++0x04, 0x2B, 0x26, 0xD1, 0xB3, 0xF7, 0x8A, 0xFC, 0x00, 0x28, 0x3A, 0xD0, 0x25, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x46, 0xE0, ++0x01, 0x2A, 0x31, 0xD0, 0x00, 0x2A, 0x32, 0xD1, 0xF8, 0x22, 0x12, 0x01, 0x10, 0x42, 0x2E, 0xD0, 0x00, 0x21, 0xFF, 0x22, ++0x86, 0x2B, 0xE1, 0xD8, 0x00, 0xE0, 0xFB, 0x21, 0x80, 0x3B, 0xDD, 0x00, 0xED, 0x1A, 0x1C, 0x48, 0x40, 0x19, 0x24, 0x30, ++0x00, 0x78, 0x02, 0x28, 0xD6, 0xD1, 0x1B, 0x02, 0x01, 0x22, 0x1A, 0x43, 0x92, 0xB2, 0x18, 0x49, 0xD2, 0xE7, 0x00, 0x2B, ++0x06, 0xD1, 0x17, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x10, 0xE0, 0x84, 0xF7, 0xE0, 0xFB, ++0x00, 0x28, 0x03, 0xD0, 0x0E, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x18, 0xE0, 0x10, 0x48, 0x7C, 0xF7, 0xEB, 0xFB, 0x04, 0xE0, ++0x01, 0x2A, 0x02, 0xD1, 0x0B, 0x4B, 0x9C, 0x42, 0xEE, 0xD9, 0x01, 0x23, 0x1A, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x7A, 0xF7, ++0xDB, 0xFA, 0x01, 0x25, 0x05, 0x70, 0xCC, 0xF7, 0x37, 0xF9, 0x01, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0xA5, 0xFB, 0x07, 0x4B, ++0x9D, 0x77, 0x70, 0xBD, 0x00, 0x00, 0x61, 0x40, 0xCC, 0xAA, 0x16, 0x00, 0xFD, 0x03, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x50, 0xD2, 0x10, 0x00, 0x03, 0x11, 0x00, 0x00, 0x24, 0x2A, 0x16, 0x00, 0x10, 0xB5, 0x08, 0x20, 0x7A, 0xF7, 0xBA, 0xFF, ++0x10, 0x4C, 0x11, 0x49, 0x20, 0x00, 0xFF, 0xF7, 0x2B, 0xFE, 0x61, 0x89, 0x00, 0x29, 0x0E, 0xD0, 0x20, 0x89, 0xFF, 0xF7, ++0x77, 0xFF, 0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0x09, 0x48, 0x41, 0x89, 0xFF, 0xF7, 0x52, 0xFE, 0x0C, 0xE0, 0x20, 0x00, ++0xFF, 0xF7, 0x68, 0xFE, 0x08, 0xE0, 0x05, 0x4C, 0x20, 0x89, 0x00, 0x22, 0x00, 0x21, 0xCD, 0xF7, 0x01, 0xFB, 0x20, 0x00, ++0xFF, 0xF7, 0x24, 0xFE, 0x10, 0xBD, 0xC0, 0x46, 0x58, 0x1E, 0x16, 0x00, 0x60, 0x1E, 0x16, 0x00, 0x10, 0xB5, 0x7F, 0xF7, ++0xBD, 0xFD, 0x06, 0x49, 0x06, 0x20, 0x7A, 0xF7, 0x47, 0xFF, 0x05, 0x49, 0x07, 0x20, 0x7A, 0xF7, 0x43, 0xFF, 0x04, 0x49, ++0x08, 0x20, 0x7A, 0xF7, 0x3F, 0xFF, 0x10, 0xBD, 0xA5, 0x77, 0x10, 0x00, 0xB9, 0x75, 0x10, 0x00, 0x65, 0x7A, 0x10, 0x00, ++0x10, 0xB5, 0x0A, 0x00, 0x41, 0x23, 0x00, 0x21, 0x0C, 0x48, 0x7A, 0xF7, 0x7B, 0xFA, 0x04, 0x00, 0x01, 0x30, 0x28, 0x22, ++0x0A, 0x49, 0xD1, 0xF7, 0x6D, 0xF9, 0xE2, 0x79, 0x2F, 0x23, 0x13, 0x40, 0xE3, 0x71, 0x20, 0x00, 0x29, 0x30, 0x18, 0x22, ++0x00, 0x21, 0x78, 0xF7, 0xEF, 0xFA, 0x00, 0x23, 0x23, 0x70, 0x20, 0x00, 0xCC, 0xF7, 0xC6, 0xF8, 0x00, 0x20, 0x10, 0xBD, ++0x01, 0x11, 0x00, 0x00, 0xA4, 0xB5, 0x0D, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x0D, 0x00, 0x90, 0x46, 0x06, 0x0A, ++0xB2, 0x00, 0x11, 0x4B, 0xD7, 0x58, 0x0C, 0x23, 0x03, 0x22, 0x00, 0x21, 0x0F, 0x48, 0x7A, 0xF7, 0x51, 0xFA, 0x04, 0x00, ++0x43, 0x46, 0x03, 0x70, 0x2D, 0x02, 0x81, 0x35, 0xFF, 0x35, 0x75, 0x19, 0x45, 0x80, 0x00, 0x23, 0x83, 0x72, 0x88, 0x23, ++0xFF, 0x33, 0xFB, 0x5C, 0xC3, 0x72, 0x39, 0x00, 0x72, 0x31, 0x04, 0x30, 0x06, 0x22, 0xD1, 0xF7, 0x35, 0xF9, 0x20, 0x00, ++0xCC, 0xF7, 0x9A, 0xF8, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, ++0x70, 0xB5, 0x05, 0x00, 0x0E, 0x00, 0x04, 0x78, 0x02, 0x2C, 0x21, 0xD8, 0x00, 0x2C, 0x04, 0xD1, 0x14, 0x4A, 0x30, 0x23, ++0x00, 0x21, 0xD1, 0x54, 0x1B, 0xE0, 0x03, 0x20, 0x88, 0xF7, 0x2E, 0xFC, 0x04, 0x1E, 0x1C, 0xD1, 0x2B, 0x78, 0x0F, 0x49, ++0x30, 0x22, 0x8B, 0x54, 0x01, 0x2B, 0x10, 0xD1, 0xDF, 0x20, 0x00, 0x21, 0x80, 0x00, 0x7A, 0xF7, 0xE7, 0xFA, 0x0B, 0x4B, ++0x18, 0x60, 0x0B, 0x4A, 0x24, 0x23, 0x01, 0x21, 0xD1, 0x54, 0x00, 0x21, 0x00, 0x20, 0x92, 0xF7, 0xA1, 0xF8, 0x00, 0xE0, ++0x12, 0x24, 0x21, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x3B, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x0C, 0x24, 0xF7, 0xE7, 0xC0, 0x46, ++0x68, 0x9E, 0x16, 0x00, 0x64, 0xA2, 0x16, 0x00, 0xCC, 0xAA, 0x16, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0F, 0x4B, ++0x5B, 0x68, 0x02, 0x00, 0x06, 0x21, 0x01, 0x20, 0x98, 0x47, 0x20, 0x78, 0x63, 0x78, 0x1B, 0x02, 0x03, 0x43, 0xA0, 0x78, ++0x00, 0x04, 0x03, 0x43, 0xE0, 0x78, 0x00, 0x06, 0x18, 0x43, 0x23, 0x79, 0x61, 0x79, 0x09, 0x02, 0x19, 0x43, 0xA4, 0xF7, ++0xFF, 0xF8, 0x20, 0x00, 0xB3, 0xF7, 0x3C, 0xFF, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x10, 0xFA, 0x00, 0x20, 0x70, 0xBD, ++0x94, 0x92, 0x16, 0x00, 0x10, 0x4A, 0xFF, 0x21, 0x13, 0x68, 0x8B, 0x43, 0x0F, 0x48, 0x00, 0x78, 0x03, 0x43, 0x80, 0x20, ++0x03, 0x43, 0x0E, 0x48, 0x03, 0x60, 0x0E, 0x4B, 0x1B, 0x78, 0x1B, 0x01, 0x0B, 0x40, 0xD0, 0x68, 0x88, 0x43, 0x03, 0x43, ++0x0B, 0x49, 0x0B, 0x60, 0x0B, 0x4B, 0x00, 0x21, 0x19, 0x60, 0x13, 0x69, 0x0A, 0x4A, 0x13, 0x40, 0x0A, 0x4A, 0x13, 0x60, ++0x0A, 0x4B, 0x0B, 0x4A, 0x1A, 0x60, 0x0B, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xE4, 0xE6, 0x10, 0x00, 0x14, 0xE7, 0x10, 0x00, ++0x08, 0x01, 0x60, 0x40, 0xF7, 0xE8, 0x10, 0x00, 0x28, 0x10, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, 0xFF, 0x0F, 0xF0, 0xFF, ++0x34, 0x08, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, 0x00, 0x01, 0x0A, 0x01, 0x00, 0x01, 0x0F, 0x01, 0x0B, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x11, 0xD1, 0x0A, 0x4B, 0x1B, 0x68, 0x03, 0x60, 0x0A, 0x4B, 0x1B, 0x68, 0x43, 0x60, 0x09, 0x4B, 0x1B, 0x68, ++0x83, 0x60, 0x09, 0x4B, 0x1B, 0x68, 0xC3, 0x60, 0x08, 0x4B, 0x1B, 0x68, 0x03, 0x61, 0x02, 0x4B, 0x01, 0x22, 0x1A, 0x70, ++0x70, 0x47, 0xC0, 0x46, 0xD3, 0xE6, 0x10, 0x00, 0x08, 0x01, 0x60, 0x40, 0x00, 0x00, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, ++0x28, 0x10, 0x62, 0x40, 0x34, 0x08, 0x62, 0x40, 0x09, 0x4B, 0x02, 0x68, 0x1A, 0x60, 0x09, 0x4B, 0x42, 0x68, 0x1A, 0x60, ++0x08, 0x4B, 0x82, 0x68, 0x1A, 0x60, 0x08, 0x4B, 0xC2, 0x68, 0x1A, 0x60, 0x02, 0x69, 0x07, 0x4B, 0x1A, 0x60, 0x07, 0x4B, ++0x00, 0x22, 0x1A, 0x70, 0x70, 0x47, 0xC0, 0x46, 0x08, 0x01, 0x60, 0x40, 0x00, 0x00, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, ++0x28, 0x10, 0x62, 0x40, 0x34, 0x08, 0x62, 0x40, 0xD3, 0xE6, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x03, 0x78, ++0x00, 0x2B, 0x17, 0xD0, 0x02, 0x20, 0xF9, 0xF7, 0x8D, 0xFD, 0x0E, 0x48, 0xFF, 0xF7, 0xB0, 0xFF, 0x62, 0x78, 0x0D, 0x4B, ++0x1A, 0x70, 0xA2, 0x78, 0x0C, 0x4B, 0x1A, 0x70, 0xFF, 0xF7, 0x70, 0xFF, 0x21, 0x78, 0x0B, 0x48, 0x7C, 0xF7, 0x46, 0xFA, ++0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x82, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0x03, 0x48, 0xFF, 0xF7, 0xBF, 0xFF, 0x01, 0x20, ++0xF9, 0xF7, 0x72, 0xFD, 0xEE, 0xE7, 0xC0, 0x46, 0xE4, 0xE6, 0x10, 0x00, 0x14, 0xE7, 0x10, 0x00, 0xF7, 0xE8, 0x10, 0x00, ++0x5C, 0xD2, 0x10, 0x00, 0x00, 0x23, 0x03, 0x73, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x88, ++0x12, 0x21, 0x15, 0x2B, 0x04, 0xD9, 0x04, 0x4B, 0x80, 0x22, 0xD2, 0x01, 0x9A, 0x82, 0x00, 0x21, 0xFF, 0xF7, 0x50, 0xF9, ++0x00, 0x20, 0x10, 0xBD, 0x68, 0x9E, 0x16, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0F, 0x4B, 0x1B, 0x68, 0x02, 0x2B, ++0x0B, 0xD0, 0x29, 0x00, 0x20, 0x00, 0x0D, 0x4B, 0x98, 0x47, 0x0D, 0x4B, 0x80, 0x22, 0x12, 0x01, 0x1A, 0x83, 0x12, 0x22, ++0x5A, 0x83, 0x00, 0x20, 0x70, 0xBD, 0xFA, 0xF7, 0x09, 0xFC, 0x00, 0x28, 0xEF, 0xD1, 0x23, 0x78, 0x9B, 0x07, 0xEC, 0xD5, ++0x05, 0x4B, 0x80, 0x22, 0x92, 0x00, 0x1A, 0x83, 0xEF, 0x3A, 0xFF, 0x3A, 0x5A, 0x83, 0xE4, 0xE7, 0x50, 0xE0, 0x10, 0x00, ++0x15, 0x28, 0x09, 0x00, 0x68, 0x9E, 0x16, 0x00, 0x70, 0xB5, 0x0C, 0x00, 0x0B, 0x4A, 0x8C, 0x23, 0xD3, 0x5C, 0x0C, 0x25, ++0x01, 0x2B, 0x05, 0xD0, 0x29, 0x00, 0x20, 0x00, 0xFF, 0xF7, 0x18, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xA4, 0xF7, 0xB8, 0xFC, ++0x05, 0x1E, 0xF5, 0xD0, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEE, 0xE7, 0xC0, 0x46, ++0x68, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x78, 0x01, 0x21, 0x99, 0x42, ++0x9B, 0x41, 0x11, 0x31, 0x19, 0x40, 0xFF, 0xF7, 0xFB, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0x70, 0xB5, 0x05, 0x00, ++0x08, 0x00, 0x1C, 0x00, 0x47, 0x4B, 0x9C, 0x42, 0x43, 0xD0, 0x23, 0xD8, 0x46, 0x4B, 0x9C, 0x42, 0x51, 0xD0, 0x13, 0xD8, ++0x45, 0x4B, 0x9C, 0x42, 0x45, 0xD0, 0x45, 0x4B, 0x9C, 0x42, 0x04, 0xD1, 0x43, 0x49, 0xFF, 0xF7, 0x43, 0xF9, 0x00, 0x25, ++0x6A, 0xE0, 0x42, 0x4B, 0x9C, 0x42, 0x00, 0xD0, 0x70, 0xE0, 0x40, 0x49, 0xFF, 0xF7, 0xB6, 0xFF, 0x00, 0x25, 0x61, 0xE0, ++0x3E, 0x4B, 0x9C, 0x42, 0x3E, 0xD0, 0x3E, 0x4B, 0x9C, 0x42, 0x65, 0xD1, 0x3C, 0x49, 0x00, 0x20, 0xFF, 0xF7, 0x16, 0xFE, ++0x00, 0x25, 0x55, 0xE0, 0x3A, 0x4B, 0x9C, 0x42, 0x20, 0xD0, 0x0A, 0xD9, 0x39, 0x4B, 0x9C, 0x42, 0x12, 0xD0, 0x39, 0x4B, ++0x9C, 0x42, 0x55, 0xD1, 0x19, 0x00, 0xFF, 0xF7, 0xDB, 0xF8, 0x00, 0x25, 0x46, 0xE0, 0x36, 0x4B, 0x9C, 0x42, 0x28, 0xD0, ++0x35, 0x4B, 0x9C, 0x42, 0x2A, 0xD1, 0x34, 0x49, 0xFF, 0xF7, 0x84, 0xFE, 0x00, 0x25, 0x3B, 0xE0, 0x2E, 0x49, 0xFF, 0xF7, ++0x01, 0xF9, 0x00, 0x25, 0x36, 0xE0, 0x24, 0x49, 0xFF, 0xF7, 0x42, 0xFE, 0x00, 0x25, 0x31, 0xE0, 0x28, 0x49, 0xFF, 0xF7, ++0x15, 0xFF, 0x00, 0x25, 0x2C, 0xE0, 0x00, 0x23, 0x0B, 0x73, 0x20, 0x4B, 0x28, 0x00, 0x29, 0x4D, 0xA8, 0x47, 0x05, 0x00, ++0x24, 0xE0, 0x1C, 0x49, 0xFF, 0xF7, 0x3A, 0xFF, 0x00, 0x25, 0x1F, 0xE0, 0x1D, 0x49, 0xFF, 0xF7, 0x47, 0xFF, 0x00, 0x25, ++0x1A, 0xE0, 0x20, 0x49, 0xFF, 0xF7, 0x88, 0xFF, 0x00, 0x25, 0x15, 0xE0, 0x23, 0x00, 0x28, 0x00, 0x1E, 0x4D, 0xA8, 0x47, ++0x05, 0x00, 0x1E, 0x4B, 0x9C, 0x42, 0x05, 0xD0, 0x1D, 0x4B, 0x08, 0x22, 0x21, 0x00, 0x91, 0x43, 0x99, 0x42, 0x04, 0xD1, ++0x02, 0x20, 0xF9, 0xF7, 0x81, 0xFC, 0xFA, 0xF7, 0x63, 0xF9, 0x19, 0x4B, 0x9C, 0x42, 0x05, 0xD0, 0x21, 0x00, 0x18, 0x48, ++0x7C, 0xF7, 0x40, 0xF9, 0x28, 0x00, 0x70, 0xBD, 0x01, 0x20, 0xF9, 0xF7, 0x73, 0xFC, 0xF5, 0xE7, 0x23, 0x00, 0x01, 0x00, ++0x28, 0x00, 0x0E, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xE0, 0xE7, 0xC0, 0x46, 0x02, 0x18, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, ++0x05, 0x04, 0x00, 0x00, 0x13, 0x0C, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x1A, 0x0C, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, ++0xC6, 0xFC, 0x00, 0x00, 0xC7, 0xFC, 0x00, 0x00, 0xC9, 0xFC, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x70, 0xFC, 0x00, 0x00, ++0x1D, 0x0C, 0x09, 0x00, 0x06, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x0C, 0x18, 0x00, 0x00, 0x6C, 0xD2, 0x10, 0x00, ++0x70, 0xB5, 0x0D, 0x00, 0x14, 0x00, 0x04, 0x23, 0x02, 0x00, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0x03, 0xF8, 0x05, 0x70, ++0x44, 0x80, 0xCB, 0xF7, 0x5F, 0xFE, 0x70, 0xBD, 0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x10, 0x00, 0x1A, 0x88, ++0x0C, 0x21, 0xFF, 0xF7, 0xE9, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x80, 0x46, 0x0C, 0x00, 0x91, 0x46, 0x0F, 0x0A, 0xBA, 0x00, 0x2E, 0x4B, 0xD5, 0x58, ++0x08, 0x00, 0x7A, 0xF7, 0xB7, 0xFB, 0x02, 0x26, 0x00, 0x28, 0x19, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x4F, 0xD0, ++0x3C, 0x23, 0xEE, 0x5C, 0x02, 0x2E, 0x03, 0xD1, 0x43, 0x46, 0x5B, 0x88, 0x00, 0x2B, 0x1B, 0xD1, 0xFA, 0x21, 0x49, 0x01, ++0xA9, 0x83, 0xFF, 0xB2, 0x36, 0x23, 0xEA, 0x5C, 0x38, 0x00, 0xA1, 0xF7, 0x6D, 0xFE, 0xA9, 0x8B, 0x38, 0x00, 0xAB, 0xF7, ++0x31, 0xFC, 0x00, 0x26, 0x43, 0x46, 0x1A, 0x88, 0x31, 0x00, 0x48, 0x46, 0xFF, 0xF7, 0xB2, 0xFF, 0x00, 0x20, 0x03, 0xB0, ++0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xFB, 0xB2, 0x9B, 0x46, 0x06, 0x23, 0x6B, 0x44, ++0x9A, 0x46, 0x6B, 0x46, 0x5A, 0x1D, 0x51, 0x46, 0x58, 0x46, 0x8B, 0xF7, 0x65, 0xFE, 0x43, 0x46, 0x5A, 0x88, 0x53, 0x46, ++0x19, 0x88, 0x8A, 0x42, 0x13, 0xD9, 0x6B, 0x46, 0x05, 0x33, 0x1B, 0x78, 0x00, 0x2B, 0xCD, 0xD0, 0x4B, 0x43, 0x9A, 0x42, ++0xCA, 0xD8, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0x58, 0x46, 0xAB, 0xF7, 0x73, 0xFA, 0x22, 0x00, 0x21, 0x00, 0x07, 0x48, ++0x79, 0xF7, 0xD2, 0xFF, 0xBE, 0xE7, 0x43, 0x46, 0x1A, 0x88, 0x12, 0x21, 0x48, 0x46, 0xFF, 0xF7, 0x7F, 0xFF, 0xC5, 0xE7, ++0x0C, 0x26, 0xC3, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x22, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0x93, 0xB0, 0x01, 0x90, 0x0C, 0x00, ++0x16, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x37, 0x4B, 0xD5, 0x58, 0x08, 0x00, 0x7A, 0xF7, 0x4E, 0xFB, 0x04, 0x28, 0x06, 0xD0, ++0x09, 0x28, 0x18, 0xD0, 0x0C, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x42, 0xFB, 0x10, 0xE0, 0x3C, 0x22, 0x30, 0x49, 0x03, 0xA8, ++0xD0, 0xF7, 0x62, 0xFE, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x38, 0xFB, 0x2D, 0x4A, 0xE8, 0x23, 0xD5, 0x58, 0x03, 0xAB, ++0x01, 0x22, 0x01, 0x21, 0x20, 0x00, 0xA8, 0x47, 0x00, 0x20, 0x13, 0xB0, 0xF0, 0xBD, 0x21, 0x00, 0x28, 0x48, 0x79, 0xF7, ++0x0F, 0xFF, 0x01, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0xC9, 0xFA, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x21, 0xFB, 0xBC, 0x23, ++0x5B, 0x00, 0xEB, 0x5C, 0xDB, 0x43, 0x9B, 0x07, 0x21, 0xD1, 0x00, 0x23, 0x01, 0x9A, 0x93, 0x71, 0xFF, 0xB2, 0x29, 0x00, ++0x38, 0x31, 0x38, 0x00, 0x88, 0xF7, 0x70, 0xF9, 0x00, 0x28, 0x1C, 0xD0, 0x1B, 0x48, 0x7C, 0xF7, 0x3F, 0xF8, 0x01, 0x23, ++0xAF, 0x22, 0x92, 0x00, 0xAB, 0x54, 0x43, 0x22, 0xAB, 0x54, 0x20, 0x00, 0x93, 0xF7, 0xA0, 0xF9, 0x88, 0xF7, 0x64, 0xFA, ++0x00, 0x28, 0x19, 0xD1, 0xC4, 0x20, 0x22, 0x00, 0x21, 0x00, 0xC0, 0x00, 0x79, 0xF7, 0x68, 0xFF, 0xC8, 0xE7, 0x22, 0x00, ++0x21, 0x00, 0x10, 0x48, 0x79, 0xF7, 0x62, 0xFF, 0xD7, 0xE7, 0x0F, 0x48, 0x7C, 0xF7, 0x22, 0xF8, 0x44, 0x23, 0x01, 0x22, ++0xEA, 0x54, 0x0B, 0x3B, 0xEA, 0x5C, 0x33, 0x21, 0x38, 0x00, 0xA1, 0xF7, 0x39, 0xFC, 0xE1, 0xE7, 0x22, 0x00, 0x21, 0x00, ++0x08, 0x48, 0x79, 0xF7, 0x4F, 0xFF, 0xDF, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x80, 0xD6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x06, 0x06, 0x00, 0x00, 0x74, 0xD2, 0x10, 0x00, 0x14, 0x06, 0x00, 0x00, 0x7C, 0xD2, 0x10, 0x00, 0x1D, 0x06, 0x00, 0x00, ++0x70, 0xB5, 0x04, 0x00, 0x0E, 0x00, 0x15, 0x00, 0x41, 0x88, 0x80, 0x23, 0x1B, 0x01, 0x99, 0x42, 0x06, 0xD3, 0x22, 0x88, ++0x0C, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0xE4, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x03, 0x48, 0x7B, 0xF7, 0xEF, 0xFF, 0x30, 0x0A, ++0x00, 0x21, 0xAB, 0xF7, 0xA7, 0xF8, 0xF0, 0xE7, 0x84, 0xD2, 0x10, 0x00, 0x70, 0xB5, 0x0E, 0x00, 0x15, 0x00, 0x07, 0x23, ++0x02, 0x00, 0x00, 0x21, 0x06, 0x48, 0x79, 0xF7, 0xDB, 0xFE, 0x04, 0x00, 0x06, 0x70, 0x01, 0x30, 0x06, 0x22, 0x29, 0x00, ++0xD0, 0xF7, 0xCC, 0xFD, 0x20, 0x00, 0xCB, 0xF7, 0x31, 0xFD, 0x70, 0xBD, 0x01, 0x11, 0x00, 0x00, 0xF0, 0xB5, 0x83, 0xB0, ++0x01, 0x90, 0x0D, 0x00, 0x16, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x22, 0x4B, 0xD4, 0x58, 0x08, 0x00, 0x7A, 0xF7, 0x98, 0xFA, ++0x00, 0x28, 0x1A, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x16, 0xD9, 0x88, 0x23, 0xFF, 0x33, 0xE3, 0x5C, 0x00, 0x2B, ++0x03, 0xD1, 0x36, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x14, 0xD0, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x81, 0xFA, 0x36, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x11, 0xD1, 0x2A, 0x00, 0x29, 0x00, 0x14, 0x48, 0x79, 0xF7, 0xE6, 0xFE, 0x03, 0xE0, 0x02, 0x21, ++0x30, 0x00, 0x91, 0xF7, 0x73, 0xFA, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x0C, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x6C, 0xFA, ++0xF7, 0xE7, 0x06, 0x23, 0x1C, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x79, 0xF7, 0x93, 0xFE, 0x05, 0x00, 0x00, 0x23, 0x03, 0x70, ++0x01, 0x9B, 0x1B, 0x88, 0x43, 0x80, 0xF8, 0xB2, 0xAB, 0xF7, 0x32, 0xFA, 0xC0, 0x03, 0x40, 0x0C, 0xA8, 0x80, 0x28, 0x00, ++0xCB, 0xF7, 0xE4, 0xFC, 0xE1, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x16, 0x06, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, ++0xF0, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x16, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x31, 0x4A, 0x9F, 0x58, 0x08, 0x00, ++0x7A, 0xF7, 0x46, 0xFA, 0x00, 0x28, 0x53, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x02, 0x24, 0x03, 0x28, 0x4F, 0xD9, 0x01, 0x99, ++0x4B, 0x88, 0xA8, 0x22, 0xD2, 0x00, 0x10, 0x34, 0x93, 0x42, 0x48, 0xD8, 0xDA, 0x07, 0x46, 0xD4, 0x8A, 0x88, 0x05, 0x2A, ++0x43, 0xD9, 0xD0, 0x07, 0x41, 0xD4, 0x08, 0x00, 0xC9, 0x88, 0x00, 0x29, 0x3D, 0xD0, 0x00, 0x89, 0x84, 0x46, 0x28, 0x28, ++0x39, 0xD8, 0x58, 0x08, 0x81, 0x42, 0x36, 0xD8, 0x93, 0x42, 0x34, 0xD3, 0x61, 0x44, 0x49, 0x00, 0x99, 0x42, 0x30, 0xD2, ++0x7B, 0x8C, 0x06, 0x3C, 0x5B, 0x07, 0x2C, 0xD5, 0x3C, 0x23, 0xFC, 0x5C, 0x00, 0x2C, 0x01, 0xD0, 0x0C, 0x24, 0x26, 0xE0, ++0x38, 0x00, 0x54, 0x30, 0x07, 0x21, 0xA1, 0xF7, 0x47, 0xFA, 0x00, 0x28, 0x01, 0xD1, 0x1A, 0x24, 0x1D, 0xE0, 0x08, 0x23, ++0x2A, 0x00, 0x29, 0x00, 0x11, 0x48, 0x79, 0xF7, 0x31, 0xFE, 0x01, 0x9B, 0x5A, 0x88, 0x02, 0x80, 0x9B, 0x88, 0x43, 0x80, ++0xC0, 0x21, 0x49, 0x00, 0x8A, 0x42, 0x00, 0xD9, 0x01, 0x80, 0xC0, 0x22, 0x52, 0x00, 0x93, 0x42, 0x00, 0xD9, 0x42, 0x80, ++0x01, 0x9A, 0xD3, 0x88, 0x83, 0x80, 0x13, 0x89, 0xC3, 0x80, 0x79, 0xF7, 0x45, 0xFE, 0x00, 0xE0, 0x02, 0x24, 0x21, 0x00, ++0x30, 0x00, 0x91, 0xF7, 0xE7, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x64, 0xA2, 0x16, 0x00, 0x0D, 0x06, 0x00, 0x00, ++0x70, 0xB5, 0x04, 0x00, 0x08, 0x00, 0x15, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x0F, 0x4A, 0x9E, 0x58, 0x7A, 0xF7, 0xDA, 0xF9, ++0x02, 0x21, 0x00, 0x28, 0x10, 0xD0, 0x63, 0x88, 0xF0, 0x22, 0x10, 0x31, 0x1A, 0x42, 0x0B, 0xD1, 0xE6, 0x3A, 0x01, 0x39, ++0x1A, 0x42, 0x07, 0xD1, 0x73, 0x84, 0x2C, 0x32, 0xB1, 0x5C, 0x00, 0x29, 0x08, 0xD1, 0x35, 0x3A, 0x93, 0x43, 0x73, 0x84, ++0x22, 0x88, 0x28, 0x00, 0xFF, 0xF7, 0xE0, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x00, 0x21, 0xF7, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0E, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x4B, 0x4B, ++0x9C, 0x42, 0x5D, 0xD0, 0x0E, 0xD9, 0x4A, 0x4B, 0x9C, 0x42, 0x67, 0xD0, 0x42, 0xD9, 0x49, 0x4B, 0x9C, 0x42, 0x00, 0xD0, ++0x81, 0xE0, 0x47, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0xDA, 0xFD, 0x00, 0x25, 0x43, 0xE0, 0x44, 0x4B, 0x9C, 0x42, ++0x69, 0xD0, 0x01, 0x33, 0x9C, 0x42, 0x13, 0xD3, 0x42, 0x4B, 0xE3, 0x18, 0x9B, 0xB2, 0x03, 0x2B, 0x00, 0xD9, 0x6E, 0xE0, ++0x10, 0x00, 0x7A, 0xF7, 0x91, 0xF9, 0x43, 0x28, 0x51, 0xD8, 0x41, 0x28, 0x51, 0xD8, 0x32, 0x00, 0x0C, 0x21, 0x20, 0x00, ++0xFF, 0xF7, 0xCE, 0xFE, 0x00, 0x25, 0x29, 0xE0, 0x39, 0x4B, 0x9C, 0x42, 0x37, 0xD0, 0x39, 0x4B, 0x9C, 0x42, 0x5A, 0xD1, ++0x38, 0x48, 0x7B, 0xF7, 0xAB, 0xFE, 0xB5, 0x1D, 0x16, 0x23, 0x9A, 0x46, 0xB2, 0x44, 0x36, 0x4B, 0x99, 0x46, 0x29, 0x78, ++0x48, 0x46, 0x7B, 0xF7, 0xA1, 0xFE, 0x01, 0x35, 0x55, 0x45, 0xF8, 0xD1, 0x2F, 0x4B, 0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, ++0x30, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0x0B, 0xE0, 0x2F, 0x4B, 0x9C, 0x42, 0x38, 0xD0, 0x2F, 0x4B, 0x9C, 0x42, 0x3C, 0xD1, ++0x2D, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x8B, 0xFD, 0x00, 0x25, 0x21, 0x00, 0x2B, 0x48, 0x7B, 0xF7, 0x86, 0xFE, ++0x28, 0x00, 0x03, 0xB0, 0x0C, 0xBC, 0x91, 0x46, 0x9A, 0x46, 0xF0, 0xBD, 0x1A, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, ++0xFB, 0xFE, 0x00, 0x25, 0xEE, 0xE7, 0x1C, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0xEC, 0xFD, 0x05, 0x00, 0xE7, 0xE7, ++0x14, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x6B, 0xFE, 0x05, 0x00, 0xE0, 0xE7, 0x4A, 0x28, 0xAD, 0xD1, 0x23, 0x00, ++0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, 0x16, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xD6, 0xE7, 0x0E, 0x4A, 0x39, 0x00, 0x30, 0x00, ++0xFF, 0xF7, 0x8A, 0xFE, 0x05, 0x00, 0xCF, 0xE7, 0x11, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x43, 0xFF, 0x05, 0x00, ++0xC8, 0xE7, 0x23, 0x00, 0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, 0x0B, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xC0, 0xE7, 0xC0, 0x46, ++0x03, 0x08, 0x00, 0x00, 0x28, 0x0C, 0x00, 0x00, 0x37, 0x0C, 0x00, 0x00, 0x1F, 0x04, 0x00, 0x00, 0xD4, 0xFB, 0xFF, 0xFF, ++0x09, 0x04, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x90, 0xD2, 0x10, 0x00, 0x98, 0xD2, 0x10, 0x00, 0xC1, 0xDB, 0x09, 0x00, ++0x0D, 0x08, 0x00, 0x00, 0x11, 0x08, 0x00, 0x00, 0x9C, 0xD2, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x78, ++0x00, 0x21, 0x01, 0x2B, 0x00, 0xD9, 0x12, 0x31, 0xB2, 0xF7, 0x7C, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x08, 0x00, ++0x00, 0x21, 0xB2, 0xF7, 0x75, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0xAD, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0x02, 0xAB, 0x00, 0x22, 0xDA, 0x71, 0x60, 0x32, 0x00, 0x21, ++0x14, 0xA8, 0x77, 0xF7, 0x8B, 0xFD, 0x9B, 0x4A, 0x9B, 0x4B, 0xD3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0xC8, 0xE1, 0x99, 0x4B, ++0x02, 0x21, 0xD1, 0x54, 0x02, 0xAB, 0x00, 0x21, 0xD9, 0x71, 0x44, 0x32, 0x00, 0x20, 0x00, 0x23, 0x01, 0x26, 0x11, 0x78, ++0x05, 0x29, 0x26, 0xD0, 0x01, 0x33, 0xDB, 0xB2, 0x40, 0x32, 0x30, 0x00, 0x0C, 0x2B, 0xF6, 0xD1, 0x02, 0xAB, 0x0C, 0x22, ++0xDA, 0x71, 0x27, 0x78, 0x00, 0x2F, 0x24, 0xD0, 0x60, 0x7A, 0x07, 0x23, 0x07, 0x00, 0x9F, 0x43, 0x00, 0x97, 0x00, 0xD0, ++0xB5, 0xE1, 0x8A, 0x49, 0x0F, 0x22, 0x02, 0x40, 0x03, 0x09, 0x8E, 0x5C, 0xCB, 0x5C, 0xF6, 0x18, 0xF6, 0xB2, 0x00, 0x2E, ++0x61, 0xDD, 0x23, 0x00, 0x0A, 0x33, 0x3A, 0x00, 0x02, 0x37, 0x07, 0x40, 0x01, 0x21, 0x01, 0x40, 0xA4, 0x46, 0x0C, 0x00, ++0x1E, 0xE0, 0x00, 0x28, 0x01, 0xD0, 0x02, 0xAA, 0xD3, 0x71, 0x0C, 0x21, 0x00, 0x27, 0x0B, 0x2B, 0x00, 0xD8, 0x8D, 0xE1, ++0xD7, 0xE7, 0xA1, 0x78, 0xE0, 0x1C, 0xB2, 0xF7, 0x35, 0xFF, 0x0B, 0x21, 0x00, 0x28, 0x00, 0xD0, 0x84, 0xE1, 0xD1, 0xE7, ++0x59, 0x88, 0x18, 0x88, 0x81, 0x42, 0x46, 0xD8, 0x03, 0x29, 0x44, 0xD9, 0x03, 0x28, 0x42, 0xD9, 0x01, 0x32, 0x10, 0x33, ++0xB2, 0x42, 0x04, 0xDA, 0x00, 0x2F, 0xF1, 0xD0, 0x94, 0x42, 0xEF, 0xD1, 0xF6, 0xE7, 0x64, 0x46, 0x23, 0x00, 0x0E, 0x33, ++0x00, 0x98, 0xC8, 0x22, 0x12, 0x01, 0x91, 0x46, 0x6B, 0x4A, 0x92, 0x46, 0xFA, 0x22, 0x52, 0x00, 0x93, 0x46, 0xA4, 0x46, ++0xA8, 0x46, 0x1F, 0x88, 0x5A, 0x88, 0x97, 0x42, 0x2D, 0xD8, 0x1D, 0x89, 0x59, 0x89, 0x8D, 0x42, 0x29, 0xD8, 0xD9, 0x88, ++0x05, 0x2F, 0x26, 0xD9, 0x4A, 0x45, 0x24, 0xD8, 0x0F, 0x00, 0x0A, 0x3F, 0xBF, 0xB2, 0x57, 0x45, 0x1F, 0xD8, 0x9F, 0x88, ++0x5F, 0x45, 0x1C, 0xD2, 0x8C, 0x00, 0x61, 0x18, 0x49, 0x00, 0x01, 0x37, 0x57, 0x43, 0xBA, 0x00, 0xD2, 0x19, 0x01, 0x32, ++0x52, 0x10, 0x91, 0x42, 0x11, 0xDB, 0x01, 0x30, 0x10, 0x33, 0xB0, 0x42, 0xDB, 0xDB, 0x64, 0x46, 0x45, 0x46, 0xA3, 0x78, ++0x01, 0x2B, 0x0F, 0xD9, 0x12, 0x21, 0x00, 0x27, 0x38, 0xE1, 0x64, 0x46, 0x96, 0x42, 0xC3, 0xDD, 0x12, 0x21, 0x00, 0x27, ++0x32, 0xE1, 0x64, 0x46, 0x45, 0x46, 0x86, 0x42, 0xEF, 0xDD, 0x12, 0x21, 0x00, 0x27, 0x2B, 0xE1, 0x63, 0x78, 0x03, 0x2B, ++0x00, 0xD9, 0x35, 0xE1, 0xDB, 0x07, 0x06, 0xD5, 0x49, 0x49, 0x4A, 0x48, 0x7B, 0xF7, 0x98, 0xFD, 0x00, 0x28, 0x00, 0xD0, ++0x2F, 0xE1, 0x02, 0xAB, 0xD8, 0x1D, 0xB3, 0xF7, 0x71, 0xF9, 0x01, 0x00, 0x01, 0x90, 0x00, 0x27, 0x00, 0x28, 0x00, 0xD0, ++0x14, 0xE1, 0x00, 0x2E, 0x00, 0xDC, 0x25, 0xE1, 0x0E, 0x23, 0x99, 0x46, 0xA1, 0x44, 0x14, 0xAF, 0x00, 0x9B, 0x9A, 0x46, ++0x00, 0x23, 0x9B, 0x46, 0xA0, 0x46, 0x4C, 0x46, 0xA9, 0x46, 0x55, 0x46, 0x13, 0xE0, 0x78, 0x60, 0x39, 0x60, 0xBA, 0x60, ++0xFB, 0x60, 0x5B, 0x46, 0xBB, 0x74, 0xFB, 0x74, 0x02, 0xAB, 0xDB, 0x79, 0x3B, 0x82, 0x38, 0x00, 0xCF, 0xF7, 0xCA, 0xFA, ++0x00, 0x28, 0x18, 0xD1, 0x01, 0x35, 0x10, 0x34, 0x20, 0x37, 0xB5, 0x42, 0x24, 0xDA, 0x23, 0x00, 0x21, 0x88, 0x49, 0x00, ++0x22, 0x89, 0x8A, 0x42, 0x00, 0xD9, 0x0A, 0x00, 0x02, 0x2A, 0x00, 0xD2, 0x02, 0x22, 0x58, 0x88, 0x40, 0x00, 0x5B, 0x89, ++0x83, 0x42, 0x00, 0xD9, 0x03, 0x00, 0x93, 0x42, 0xD9, 0xD2, 0x13, 0x00, 0xD7, 0xE7, 0xAA, 0x46, 0x44, 0x46, 0x4D, 0x46, ++0x51, 0x46, 0x25, 0x48, 0x7B, 0xF7, 0x10, 0xFD, 0x51, 0x46, 0x24, 0x48, 0x7B, 0xF7, 0x0C, 0xFD, 0x01, 0x9F, 0x3B, 0x21, ++0x56, 0x45, 0x00, 0xDD, 0xCC, 0xE0, 0x06, 0xE0, 0xAA, 0x46, 0x44, 0x46, 0x4D, 0x46, 0x51, 0x46, 0x1D, 0x48, 0x7B, 0xF7, ++0xFF, 0xFC, 0x02, 0xAB, 0xDA, 0x79, 0x92, 0x01, 0x13, 0x4B, 0x9B, 0x18, 0x9B, 0x68, 0x00, 0x2B, 0x05, 0xD0, 0x19, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x60, 0x78, 0x02, 0x28, 0x2D, 0xD0, 0x0E, 0xD8, 0x00, 0x28, ++0x2A, 0xD0, 0x0B, 0x49, 0x02, 0xAB, 0xD8, 0x79, 0x80, 0x01, 0x08, 0x18, 0x0C, 0x30, 0x11, 0x4B, 0x9C, 0x46, 0x61, 0x44, ++0x06, 0x22, 0xD0, 0xF7, 0xD3, 0xFA, 0x2B, 0xE0, 0x03, 0x28, 0xF0, 0xD0, 0x0B, 0x4B, 0xDF, 0x6E, 0x00, 0x23, 0x1A, 0x00, ++0x19, 0x00, 0xB8, 0x47, 0x22, 0xE0, 0xC0, 0x46, 0xEC, 0xA4, 0x16, 0x00, 0x6D, 0x04, 0x00, 0x00, 0xE4, 0x98, 0x0D, 0x00, ++0x76, 0x0C, 0x00, 0x00, 0xB4, 0x98, 0x0D, 0x00, 0xFA, 0xA7, 0x16, 0x00, 0xA4, 0xD2, 0x10, 0x00, 0xB0, 0xD2, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x0E, 0x03, 0x00, 0x00, 0x4E, 0x4A, 0x02, 0xAB, 0x07, 0x33, 0x1B, 0x78, 0x9B, 0x01, 0xD3, 0x18, ++0xC2, 0x21, 0x89, 0x00, 0x8C, 0x46, 0x62, 0x44, 0x11, 0x68, 0xD9, 0x60, 0x92, 0x88, 0x1A, 0x82, 0x02, 0xAB, 0x07, 0x33, ++0x1B, 0x78, 0x46, 0x4F, 0x9A, 0x01, 0xBA, 0x18, 0x94, 0x60, 0x01, 0x33, 0x9B, 0x01, 0xFB, 0x18, 0x05, 0x22, 0x1A, 0x71, ++0xE1, 0x1C, 0x01, 0x32, 0x0E, 0x20, 0x02, 0xAB, 0x9C, 0x46, 0x60, 0x44, 0xD0, 0xF7, 0x92, 0xFA, 0x3E, 0x4B, 0xF9, 0x18, ++0x05, 0x22, 0x07, 0xA8, 0xD0, 0xF7, 0x8C, 0xFA, 0x67, 0x7A, 0x04, 0xAB, 0x9F, 0x74, 0x00, 0x2E, 0x17, 0xDD, 0x22, 0x00, ++0x0A, 0x32, 0x14, 0xA9, 0x10, 0x88, 0x18, 0x83, 0x50, 0x88, 0x58, 0x83, 0x48, 0x69, 0x40, 0x08, 0x98, 0x83, 0x88, 0x69, ++0xD8, 0x83, 0x10, 0x89, 0x18, 0x84, 0x50, 0x89, 0x58, 0x84, 0x00, 0x98, 0x01, 0x30, 0x00, 0x90, 0x10, 0x32, 0x0C, 0x33, ++0x20, 0x31, 0xB0, 0x42, 0xEA, 0xDB, 0x05, 0x23, 0x3B, 0x40, 0x05, 0x2B, 0x20, 0xD0, 0x02, 0xAB, 0x07, 0x33, 0x1B, 0x78, ++0x04, 0xA8, 0xC3, 0x74, 0x62, 0x78, 0x02, 0x75, 0xA2, 0x78, 0x42, 0x75, 0x22, 0x78, 0x82, 0x75, 0x24, 0x4A, 0x9B, 0x01, ++0xD3, 0x18, 0xD9, 0x68, 0x04, 0x91, 0x1B, 0x8A, 0x83, 0x80, 0x01, 0x23, 0x43, 0x74, 0x22, 0x4B, 0xD2, 0x5C, 0x3C, 0x23, ++0xC2, 0x54, 0xC7, 0xF7, 0x29, 0xFF, 0x01, 0x00, 0x01, 0x27, 0x00, 0x28, 0x1E, 0xD0, 0x03, 0x21, 0x01, 0x27, 0x1B, 0xE0, ++0x01, 0x3E, 0x04, 0xA8, 0x43, 0x8B, 0x0C, 0x22, 0x72, 0x43, 0x82, 0x18, 0x51, 0x8B, 0x5F, 0x18, 0x02, 0x8B, 0xBA, 0x42, ++0x00, 0xD2, 0x07, 0x83, 0x0C, 0x22, 0x72, 0x43, 0x04, 0xA8, 0x84, 0x46, 0x62, 0x44, 0x12, 0x8B, 0xBA, 0x42, 0xCA, 0xD2, ++0x0C, 0x22, 0x72, 0x43, 0x62, 0x44, 0x5B, 0x18, 0x13, 0x83, 0xC4, 0xE7, 0x0C, 0x21, 0x00, 0x27, 0x28, 0x00, 0xB2, 0xF7, ++0x9B, 0xFD, 0x38, 0x00, 0x2D, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x12, 0x21, ++0x00, 0x27, 0xF1, 0xE7, 0x12, 0x21, 0x00, 0x27, 0xEE, 0xE7, 0x12, 0x21, 0x00, 0x27, 0xEB, 0xE7, 0x00, 0x9B, 0x9A, 0x46, ++0x1F, 0xE7, 0xC0, 0x46, 0xEC, 0xA4, 0x16, 0x00, 0x19, 0x03, 0x00, 0x00, 0xD6, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x80, 0x46, 0x0D, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x58, 0x4B, 0xE3, 0x18, 0x9A, 0xB2, 0x39, 0x2A, 0x00, 0xD9, ++0x90, 0xE0, 0x93, 0x00, 0x55, 0x4A, 0xD3, 0x58, 0x9F, 0x46, 0x02, 0x20, 0xF8, 0xF7, 0x40, 0xFF, 0x53, 0x4B, 0x00, 0x22, ++0x44, 0x21, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, ++0x00, 0x26, 0x7C, 0xE0, 0x01, 0x20, 0xF8, 0xF7, 0x2F, 0xFF, 0x4B, 0x4B, 0x11, 0x22, 0x44, 0x21, 0x5A, 0x54, 0x40, 0x31, ++0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x00, 0x26, 0x6B, 0xE0, 0x45, 0x4B, ++0x1B, 0x78, 0x00, 0x26, 0x00, 0x2B, 0x66, 0xD0, 0x43, 0x49, 0x28, 0x00, 0xFF, 0xF7, 0xB0, 0xFD, 0x05, 0x00, 0x21, 0x00, ++0x41, 0x48, 0x7B, 0xF7, 0xDB, 0xFB, 0x41, 0x4B, 0x9C, 0x42, 0x6E, 0xD1, 0x00, 0x26, 0x3B, 0x4A, 0x3F, 0x4B, 0x00, 0x21, ++0xD1, 0x54, 0x62, 0xE0, 0x39, 0x4B, 0x1B, 0x78, 0x00, 0x26, 0x00, 0x2B, 0x4F, 0xD0, 0x00, 0x21, 0x3B, 0x48, 0xB2, 0xF7, ++0x1F, 0xFD, 0x00, 0x25, 0xE7, 0xE7, 0x4B, 0x78, 0x02, 0x2B, 0x27, 0xD0, 0x38, 0x4E, 0x05, 0x22, 0xFF, 0x21, 0x30, 0x00, ++0x77, 0xF7, 0x3E, 0xFB, 0x36, 0x4B, 0xF3, 0x18, 0x36, 0x49, 0x58, 0x5C, 0x1F, 0x22, 0x02, 0x40, 0x5A, 0x54, 0x35, 0x4B, ++0x1B, 0x78, 0xEB, 0x81, 0x2B, 0x82, 0x12, 0x23, 0xAB, 0x81, 0x6B, 0x7A, 0x9A, 0x07, 0x07, 0xD5, 0x02, 0x22, 0x93, 0x43, ++0x6B, 0x72, 0x12, 0x23, 0xAB, 0x83, 0x6B, 0x8B, 0x9B, 0x00, 0x6B, 0x83, 0x6B, 0x7A, 0x00, 0x26, 0x5B, 0x07, 0x24, 0xD5, ++0x12, 0x23, 0xAB, 0x85, 0x6B, 0x8D, 0x5B, 0x00, 0x6B, 0x85, 0x1E, 0xE0, 0x00, 0x23, 0x4B, 0x70, 0xD4, 0xE7, 0x23, 0x4E, ++0x05, 0x22, 0xFF, 0x21, 0x30, 0x00, 0x77, 0xF7, 0x13, 0xFB, 0x21, 0x4B, 0xF0, 0x18, 0x21, 0x4A, 0x81, 0x5C, 0x1F, 0x23, ++0x0B, 0x40, 0x83, 0x54, 0x20, 0x4B, 0xC6, 0x5C, 0x00, 0x2E, 0x0A, 0xD0, 0x13, 0x4A, 0x00, 0x21, 0xD1, 0x54, 0x06, 0xE0, ++0x11, 0x4A, 0x16, 0x4B, 0x00, 0x21, 0xD1, 0x54, 0x00, 0x26, 0x00, 0xE0, 0x00, 0x26, 0x23, 0x00, 0x3A, 0x00, 0x29, 0x00, ++0x40, 0x46, 0x18, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0x21, 0x00, 0x0D, 0x48, 0x7B, 0xF7, 0x72, 0xFB, 0x0C, 0x4B, 0x9C, 0x42, ++0x97, 0xD0, 0x00, 0x2E, 0x03, 0xD0, 0x06, 0x4A, 0x10, 0x4B, 0x01, 0x21, 0xD1, 0x54, 0x28, 0x00, 0x04, 0xBC, 0x90, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0xF6, 0xDF, 0xFF, 0xFF, 0xC4, 0xD2, 0x10, 0x00, 0xEC, 0xA4, 0x16, 0x00, 0x60, 0xE6, 0x10, 0x00, ++0x0A, 0x20, 0x00, 0x00, 0xB8, 0xD2, 0x10, 0x00, 0x3B, 0x20, 0x00, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x39, 0x20, 0x00, 0x00, ++0x05, 0xA8, 0x16, 0x00, 0xE7, 0xFC, 0xFF, 0xFF, 0x1D, 0x03, 0x00, 0x00, 0xE2, 0xE1, 0x10, 0x00, 0xD6, 0x03, 0x00, 0x00, ++0x15, 0xC9, 0x0B, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x06, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x17, 0x4B, 0x9C, 0x42, ++0x24, 0xD0, 0x17, 0x4B, 0x9C, 0x42, 0x13, 0xD1, 0xCB, 0x88, 0x10, 0x2B, 0x01, 0xD9, 0x10, 0x23, 0xCB, 0x80, 0x14, 0x4B, ++0x1B, 0x78, 0x6A, 0x88, 0x9A, 0x42, 0x01, 0xD8, 0x6B, 0x80, 0xAB, 0x80, 0xEB, 0x88, 0xAA, 0x88, 0x69, 0x88, 0x28, 0x89, ++0x00, 0x90, 0x0F, 0x48, 0x7B, 0xF7, 0x26, 0xFB, 0x23, 0x00, 0x3A, 0x00, 0x29, 0x00, 0x30, 0x00, 0x0C, 0x4D, 0xA8, 0x47, ++0x05, 0x00, 0x21, 0x00, 0x0B, 0x48, 0x7B, 0xF7, 0x1B, 0xFB, 0x28, 0x00, 0x03, 0xB0, 0xF0, 0xBD, 0x0A, 0x88, 0x00, 0x21, ++0x02, 0x48, 0xFF, 0xF7, 0x03, 0xFA, 0x00, 0x25, 0xF1, 0xE7, 0xC0, 0x46, 0x0D, 0x08, 0x00, 0x00, 0x13, 0x20, 0x00, 0x00, ++0xE2, 0xE1, 0x10, 0x00, 0xAC, 0xD3, 0x10, 0x00, 0x09, 0x1C, 0x0C, 0x00, 0xBC, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0xCE, 0x46, ++0x47, 0x46, 0x80, 0xB5, 0x14, 0x0A, 0xA4, 0x00, 0x0E, 0x4D, 0x65, 0x59, 0x44, 0x24, 0x2C, 0x5D, 0x03, 0x27, 0x3E, 0x00, ++0x26, 0x40, 0x27, 0x42, 0x11, 0xD0, 0xB9, 0x46, 0xBC, 0x43, 0xA4, 0x46, 0x44, 0x24, 0x67, 0x46, 0x2F, 0x55, 0xB9, 0xF7, ++0x7F, 0xF8, 0x2B, 0x5D, 0x4A, 0x46, 0x93, 0x43, 0x1E, 0x43, 0x2E, 0x55, 0x00, 0x20, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, ++0xF8, 0xBD, 0xB9, 0xF7, 0x73, 0xF8, 0xF7, 0xE7, 0x5C, 0xA9, 0x16, 0x00, 0x70, 0xB5, 0x0D, 0x00, 0x14, 0x0A, 0xA2, 0x00, ++0x29, 0x4B, 0xD6, 0x58, 0x0B, 0x2C, 0x06, 0xD8, 0x00, 0x2E, 0x04, 0xD0, 0x44, 0x23, 0xF3, 0x5C, 0xDB, 0x43, 0x9B, 0x07, ++0x11, 0xD1, 0x2D, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x06, 0xD0, 0x2A, 0x00, 0x16, 0x21, 0x20, 0x00, 0x21, 0x4B, 0x98, 0x47, ++0x00, 0x20, 0x70, 0xBD, 0x45, 0x22, 0xB1, 0x5C, 0x7F, 0x23, 0x0B, 0x40, 0xB3, 0x54, 0x00, 0x20, 0xF7, 0xE7, 0x00, 0x21, ++0x20, 0x00, 0xB8, 0xF7, 0x83, 0xFC, 0x00, 0x28, 0x2C, 0xD1, 0x42, 0x23, 0xF3, 0x5A, 0xDB, 0x06, 0x04, 0xD5, 0x28, 0x00, ++0xB8, 0xF7, 0x92, 0xFC, 0x00, 0x28, 0x25, 0xD0, 0x28, 0x00, 0xB8, 0xF7, 0x8D, 0xFC, 0x00, 0x28, 0x0E, 0xD1, 0x2A, 0x00, ++0x00, 0x21, 0x20, 0x00, 0xB8, 0xF7, 0x20, 0xFC, 0x28, 0x00, 0xB8, 0xF7, 0x83, 0xFC, 0x01, 0x00, 0x00, 0x22, 0x20, 0x00, ++0x0D, 0x4B, 0x98, 0x47, 0x01, 0x20, 0xD4, 0xE7, 0x28, 0x00, 0xB8, 0xF7, 0x79, 0xFC, 0x01, 0x28, 0xEB, 0xD0, 0x0A, 0x4B, ++0xDE, 0x6E, 0x28, 0x00, 0xB8, 0xF7, 0x72, 0xFC, 0x01, 0x00, 0x00, 0x23, 0x00, 0x22, 0x20, 0x00, 0xB0, 0x47, 0xE0, 0xE7, ++0x02, 0x20, 0xC2, 0xE7, 0x02, 0x20, 0xC0, 0xE7, 0x5C, 0xA9, 0x16, 0x00, 0x81, 0x45, 0x0C, 0x00, 0xF5, 0x46, 0x0C, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x82, 0xB0, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0x1F, 0x00, ++0x13, 0x0A, 0x9B, 0x00, 0x0E, 0x4A, 0x9B, 0x58, 0x00, 0x2B, 0x0E, 0xD0, 0x89, 0x88, 0x0D, 0x4B, 0x9C, 0x46, 0x61, 0x44, ++0x01, 0xAB, 0x98, 0x46, 0x01, 0x22, 0x18, 0x00, 0xD0, 0xF7, 0x5A, 0xF8, 0x43, 0x46, 0x19, 0x78, 0x08, 0x48, 0x7B, 0xF7, ++0x61, 0xFA, 0x3B, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0xB9, 0xF7, 0x91, 0xF9, 0x02, 0xB0, 0x04, 0xBC, 0x90, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0x5C, 0xA9, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0xC8, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0x05, 0x00, ++0x0E, 0x00, 0x14, 0x00, 0x1F, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x08, 0x4A, 0x9B, 0x58, 0x9B, 0x6A, 0x00, 0x2B, 0x03, 0xD0, ++0x59, 0x7A, 0x06, 0x48, 0x7B, 0xF7, 0x40, 0xFA, 0x3B, 0x00, 0x22, 0x00, 0x31, 0x00, 0x28, 0x00, 0xB9, 0xF7, 0x50, 0xFA, ++0xF8, 0xBD, 0xC0, 0x46, 0x5C, 0xA9, 0x16, 0x00, 0xD4, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0x04, 0x00, 0x06, 0x0A, 0xB2, 0x00, ++0x28, 0x4B, 0xD5, 0x58, 0x28, 0x00, 0x54, 0x30, 0x2A, 0x21, 0xA0, 0xF7, 0x31, 0xFD, 0x00, 0x28, 0x3C, 0xD0, 0xF6, 0xB2, ++0x30, 0x00, 0xAA, 0xF7, 0xB5, 0xF8, 0x20, 0x00, 0x91, 0xF7, 0x02, 0xFA, 0x43, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x23, 0xD0, ++0x1F, 0x4B, 0xEB, 0x5C, 0x00, 0x2B, 0x14, 0xD0, 0x95, 0x23, 0x9B, 0x00, 0xEF, 0x18, 0x38, 0x00, 0x86, 0xF7, 0x80, 0xFA, ++0x36, 0x23, 0xE9, 0x5C, 0x3A, 0x00, 0x30, 0x00, 0xA1, 0xF7, 0x42, 0xF8, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x0A, 0xD0, ++0x2D, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x76, 0xFC, 0x22, 0xE0, 0x36, 0x23, 0xE9, 0x5C, 0x30, 0x00, 0xA1, 0xF7, 0x4B, 0xF8, ++0xF0, 0xE7, 0x2B, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x6B, 0xFC, 0x17, 0xE0, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x04, 0xD0, ++0x60, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x62, 0xFC, 0x0E, 0xE0, 0x61, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x5D, 0xFC, 0x09, 0xE0, ++0x00, 0x23, 0xAC, 0x22, 0x92, 0x00, 0xAB, 0x54, 0x05, 0x4A, 0xAB, 0x54, 0x00, 0x21, 0x20, 0x00, 0x93, 0xF7, 0xA6, 0xFB, ++0xF8, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xAF, 0x02, 0x00, 0x00, 0xB3, 0x02, 0x00, 0x00, 0xF8, 0xB5, 0x05, 0x00, ++0x0E, 0x00, 0x07, 0x0A, 0xBA, 0x00, 0x1D, 0x4B, 0xD4, 0x58, 0x1D, 0x4B, 0xE3, 0x5C, 0x00, 0x2B, 0x0A, 0xD1, 0x1B, 0x4B, ++0x00, 0x22, 0xE2, 0x54, 0x09, 0x3B, 0xE3, 0x5C, 0x00, 0x2B, 0x27, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0x8F, 0xFF, 0xF8, 0xBD, ++0x93, 0xF7, 0xCC, 0xF8, 0x00, 0x28, 0x03, 0xD0, 0x14, 0x4B, 0xE3, 0x5C, 0x00, 0x2B, 0x0C, 0xD0, 0x11, 0x4B, 0xE3, 0x5C, ++0x00, 0x2B, 0xE8, 0xD0, 0x88, 0x23, 0xFF, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0xE3, 0xD0, 0x43, 0x23, 0x01, 0x22, 0xE2, 0x54, ++0xDF, 0xE7, 0x04, 0x33, 0x06, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x79, 0xF7, 0xA3, 0xF8, 0x06, 0x70, 0x80, 0x37, 0x47, 0x80, ++0xCA, 0xF7, 0xFE, 0xFE, 0x43, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xE3, 0xE7, 0x31, 0x00, 0x28, 0x00, 0x93, 0xF7, 0x60, 0xFB, ++0xD5, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xB9, 0x02, 0x00, 0x00, 0xC5, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, ++0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x8C, 0xB0, 0x05, 0x00, 0x0C, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x4A, 0x4B, 0xD6, 0x58, ++0x08, 0x00, 0x79, 0xF7, 0x55, 0xFC, 0x20, 0x28, 0x07, 0xD0, 0x21, 0x00, 0x28, 0x00, 0x47, 0x4B, 0x98, 0x47, 0x0C, 0xB0, ++0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2A, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x69, 0x1C, 0x29, 0x3A, ++0x30, 0x00, 0xCB, 0x30, 0xFF, 0x30, 0xCF, 0xF7, 0x61, 0xFF, 0xFD, 0x23, 0x5B, 0x00, 0x98, 0x46, 0xB0, 0x44, 0x09, 0xAB, ++0x07, 0x93, 0x43, 0x46, 0x06, 0x93, 0x02, 0xA8, 0x10, 0x22, 0x31, 0x00, 0xCB, 0x31, 0xFF, 0x31, 0xCF, 0xF7, 0x52, 0xFF, ++0x6A, 0x46, 0x33, 0x00, 0x6C, 0x33, 0xF1, 0x6E, 0x00, 0x91, 0x9B, 0x88, 0x93, 0x80, 0xCD, 0x23, 0x5B, 0x00, 0xF3, 0x5A, ++0x35, 0x00, 0x9B, 0x35, 0xFF, 0x35, 0x68, 0x88, 0x00, 0x04, 0x18, 0x43, 0xAB, 0x88, 0xE9, 0x88, 0x09, 0x04, 0x19, 0x43, ++0x2B, 0x89, 0x6A, 0x89, 0x12, 0x04, 0x1A, 0x43, 0xAB, 0x89, 0x9C, 0x46, 0xEB, 0x89, 0x1B, 0x04, 0x65, 0x46, 0x2B, 0x43, ++0x83, 0xF7, 0xDA, 0xFD, 0x27, 0x4B, 0xF3, 0x5C, 0x00, 0x2B, 0x1F, 0xD0, 0x39, 0x23, 0xF2, 0x5C, 0xF8, 0xB2, 0x41, 0x46, ++0xA0, 0xF7, 0x93, 0xFE, 0xBE, 0x23, 0x5B, 0x00, 0xF3, 0x5C, 0x00, 0x2B, 0x1B, 0xD0, 0x88, 0x23, 0xFF, 0x33, 0xF3, 0x5C, ++0x00, 0x2B, 0x05, 0xD0, 0x01, 0x23, 0xAC, 0x22, 0x92, 0x00, 0xB3, 0x54, 0x1C, 0x4A, 0xB3, 0x54, 0x37, 0x23, 0xF3, 0x5C, ++0x05, 0x2B, 0x27, 0xD0, 0x00, 0x21, 0x20, 0x00, 0xFF, 0xF7, 0x44, 0xFF, 0x00, 0x20, 0x9C, 0xE7, 0x0C, 0x22, 0x09, 0xA9, ++0x16, 0x4B, 0xF0, 0x18, 0xCF, 0xF7, 0x08, 0xFF, 0xD8, 0xE7, 0x17, 0x33, 0x18, 0x22, 0x00, 0x21, 0x13, 0x48, 0x79, 0xF7, ++0x09, 0xF8, 0x05, 0x00, 0xC0, 0x23, 0x5B, 0x00, 0xF3, 0x5C, 0x83, 0x75, 0x06, 0x22, 0x31, 0x00, 0x72, 0x31, 0xCF, 0xF7, ++0xF7, 0xFE, 0xA8, 0x1D, 0x10, 0x22, 0x31, 0x00, 0x9B, 0x31, 0xFF, 0x31, 0xCF, 0xF7, 0xF0, 0xFE, 0x28, 0x00, 0xCA, 0xF7, ++0x55, 0xFE, 0xC8, 0xE7, 0x05, 0x21, 0x20, 0x00, 0x93, 0xF7, 0x2E, 0xFB, 0x00, 0x20, 0x74, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0x01, 0x4A, 0x0A, 0x00, 0xC5, 0x02, 0x00, 0x00, 0xB3, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, ++0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x0B, 0x4A, 0x9E, 0x58, 0x08, 0x00, 0x79, 0xF7, 0xAE, 0xFB, ++0x24, 0x28, 0x04, 0xD0, 0x21, 0x00, 0x28, 0x00, 0x07, 0x4B, 0x98, 0x47, 0x70, 0xBD, 0xBE, 0x23, 0x5B, 0x00, 0xF3, 0x5C, ++0x00, 0x2B, 0xF5, 0xD1, 0x7D, 0x33, 0xFF, 0x33, 0x01, 0x22, 0xF2, 0x54, 0xF0, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x55, 0x45, 0x0A, 0x00, 0xF8, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x0F, 0x0A, 0xBA, 0x00, ++0x2F, 0x4B, 0xD6, 0x58, 0x02, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x42, 0x78, 0x37, 0x23, 0xF2, 0x54, ++0x08, 0x00, 0x79, 0xF7, 0x83, 0xFB, 0x18, 0x28, 0x04, 0xD8, 0x01, 0x23, 0x83, 0x40, 0x28, 0x4A, 0x13, 0x42, 0x2B, 0xD1, ++0xFB, 0xB2, 0x99, 0x46, 0x18, 0x00, 0xAA, 0xF7, 0x81, 0xF9, 0x80, 0x46, 0x24, 0x4B, 0x01, 0x22, 0xF2, 0x54, 0x21, 0x00, ++0x23, 0x48, 0x78, 0xF7, 0x51, 0xFF, 0x23, 0x4B, 0xF3, 0x5C, 0x00, 0x2B, 0x1F, 0xD1, 0x3C, 0x23, 0xF3, 0x5C, 0x02, 0x2B, ++0x2D, 0xD0, 0x48, 0x46, 0xA9, 0xF7, 0x24, 0xFF, 0x36, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x2A, 0xD1, 0x43, 0x46, 0x58, 0x00, ++0x40, 0x44, 0x40, 0x00, 0x80, 0xB2, 0x7B, 0xF7, 0xE7, 0xF8, 0x02, 0x00, 0x21, 0x00, 0x16, 0x48, 0x78, 0xF7, 0xBE, 0xFE, ++0x19, 0x21, 0x20, 0x00, 0x79, 0xF7, 0xF0, 0xFA, 0x00, 0x20, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF8, 0xBD, 0x04, 0x23, ++0x06, 0x22, 0x00, 0x21, 0x10, 0x48, 0x78, 0xF7, 0x6F, 0xFF, 0x6B, 0x78, 0x03, 0x70, 0x80, 0x37, 0x47, 0x80, 0xCA, 0xF7, ++0xC9, 0xFD, 0x00, 0x23, 0x0A, 0x4A, 0xB3, 0x54, 0x43, 0x22, 0xB3, 0x54, 0xCD, 0xE7, 0x20, 0x00, 0x09, 0x4B, 0x98, 0x47, ++0xCD, 0xE7, 0x43, 0x46, 0x58, 0x00, 0x40, 0x44, 0x80, 0xB2, 0xD4, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x01, 0x00, 0x40, 0x01, ++0xC2, 0x02, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0xB9, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0xF5, 0x3A, 0x09, 0x00, ++0x00, 0x20, 0x70, 0x47, 0xF0, 0xB5, 0x83, 0xB0, 0x0C, 0x00, 0x04, 0x23, 0x5B, 0x4A, 0x00, 0x21, 0x5B, 0x48, 0x78, 0xF7, ++0x41, 0xFF, 0x05, 0x00, 0x21, 0x78, 0x5A, 0x48, 0x7B, 0xF7, 0x40, 0xF8, 0x23, 0x78, 0x01, 0x2B, 0x65, 0xD0, 0x06, 0x2B, ++0x00, 0xD1, 0x80, 0xE0, 0x00, 0x2B, 0x05, 0xD0, 0x28, 0x00, 0xCA, 0xF7, 0x91, 0xFD, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, ++0xA2, 0x78, 0x52, 0x4B, 0x1A, 0x70, 0x00, 0x23, 0x2B, 0x70, 0x6B, 0x70, 0xA3, 0x78, 0xAB, 0x70, 0x4F, 0x4B, 0x1B, 0x78, ++0xEB, 0x70, 0x63, 0x78, 0x01, 0x2B, 0xEB, 0xD1, 0x4D, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0xE7, 0xD1, 0x49, 0x4B, 0x1B, 0x78, ++0x06, 0x2B, 0xE3, 0xD1, 0xFC, 0xF7, 0x66, 0xF9, 0x49, 0x4C, 0x4A, 0x4B, 0x02, 0x22, 0xE2, 0x54, 0x6B, 0x46, 0xDF, 0x1D, ++0x38, 0x00, 0xB2, 0xF7, 0x2D, 0xFC, 0x3E, 0x78, 0x10, 0x23, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x78, 0xF7, 0x06, 0xFF, ++0xB6, 0x01, 0xA6, 0x19, 0xB0, 0x60, 0x3B, 0x78, 0x9B, 0x01, 0xE3, 0x18, 0x9B, 0x68, 0x01, 0x22, 0x9A, 0x70, 0x00, 0x26, ++0x1E, 0x71, 0x80, 0x22, 0x92, 0x01, 0xDA, 0x80, 0x1A, 0x81, 0x1E, 0x70, 0x5E, 0x70, 0x38, 0x78, 0x43, 0x1C, 0x9B, 0x01, ++0xE3, 0x18, 0x06, 0x22, 0x1A, 0x71, 0x38, 0x4A, 0xA3, 0x5C, 0x03, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x83, 0x01, 0xE3, 0x18, ++0x1E, 0x86, 0x5E, 0x86, 0x34, 0x4B, 0x98, 0x47, 0x3B, 0x78, 0x5A, 0x1C, 0x92, 0x01, 0xA2, 0x18, 0x07, 0x21, 0x11, 0x71, ++0x9B, 0x01, 0xE3, 0x18, 0x98, 0x68, 0x0C, 0x38, 0x78, 0xF7, 0x27, 0xFF, 0x3B, 0x78, 0x9B, 0x01, 0xE4, 0x18, 0xA6, 0x60, ++0x9E, 0xE7, 0xA3, 0x78, 0x00, 0x2B, 0x0C, 0xD1, 0x24, 0x4B, 0x1B, 0x78, 0x01, 0x33, 0xDB, 0xB2, 0x10, 0x2B, 0x02, 0xD8, ++0x21, 0x4A, 0x13, 0x70, 0x07, 0xE0, 0x20, 0x4B, 0x10, 0x22, 0x1A, 0x70, 0x03, 0xE0, 0x1E, 0x4A, 0x13, 0x78, 0x01, 0x3B, ++0x13, 0x70, 0x00, 0x23, 0x2B, 0x70, 0x01, 0x33, 0x6B, 0x70, 0xA3, 0x78, 0xAB, 0x70, 0x19, 0x4B, 0x1B, 0x78, 0xEB, 0x70, ++0x80, 0xE7, 0xE2, 0x78, 0x12, 0x02, 0xA3, 0x78, 0x13, 0x43, 0x1B, 0x4A, 0x1B, 0xB2, 0x93, 0x42, 0x00, 0xD0, 0x77, 0xE7, ++0x19, 0x4B, 0x1A, 0x80, 0x61, 0x79, 0x09, 0x02, 0x22, 0x79, 0x0A, 0x43, 0x5A, 0x80, 0xE1, 0x79, 0x09, 0x02, 0xA2, 0x79, ++0x0A, 0x43, 0x9A, 0x80, 0x98, 0x68, 0x00, 0x28, 0x01, 0xD0, 0x79, 0xF7, 0x11, 0xF8, 0x20, 0x7A, 0x10, 0x4E, 0xB0, 0x71, ++0x01, 0x21, 0x78, 0xF7, 0x67, 0xFF, 0xB0, 0x60, 0xB2, 0x79, 0x21, 0x00, 0x09, 0x31, 0xCF, 0xF7, 0x87, 0xFD, 0x59, 0xE7, ++0x57, 0xFD, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0xE0, 0xD3, 0x10, 0x00, 0xD0, 0xE5, 0x10, 0x00, 0x48, 0x06, 0x16, 0x00, ++0xA8, 0xE5, 0x10, 0x00, 0xEC, 0xA4, 0x16, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x6A, 0x04, 0x00, 0x00, 0xE1, 0xEA, 0x0B, 0x00, ++0x88, 0xAC, 0xFF, 0xFF, 0xC4, 0xE5, 0x10, 0x00, 0x09, 0x4B, 0x1B, 0x68, 0xDA, 0x6E, 0x53, 0x1C, 0x0C, 0xD0, 0x08, 0x4B, ++0x19, 0x68, 0x4B, 0x68, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x06, 0x48, 0x83, 0x42, 0x03, 0xD9, 0x04, 0x32, 0x12, 0x01, ++0x12, 0x09, 0x4A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0xF4, 0xE1, 0x10, 0x00, 0x28, 0x27, 0x16, 0x00, 0xFE, 0xFF, 0xFF, 0x07, ++0x30, 0xB5, 0x83, 0xB0, 0x68, 0x46, 0x77, 0xF7, 0xE5, 0xFC, 0x00, 0x9D, 0x34, 0x4C, 0x23, 0x68, 0x01, 0x22, 0x93, 0x43, ++0x23, 0x60, 0x82, 0xF7, 0x51, 0xFE, 0xB1, 0xF7, 0x69, 0xFE, 0x22, 0x68, 0x8C, 0x23, 0x5B, 0x01, 0x13, 0x43, 0x23, 0x60, ++0x2E, 0x4B, 0x1B, 0x68, 0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x41, 0xD0, 0x2A, 0x49, 0x0B, 0x68, 0x2B, 0x4A, 0x1A, 0x40, ++0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x27, 0x4B, 0x5B, 0x68, 0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x36, 0xD0, ++0x23, 0x49, 0x0B, 0x68, 0x25, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x13, 0x43, 0x0B, 0x60, 0x20, 0x4B, 0x9B, 0x68, ++0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x2B, 0xD0, 0x1C, 0x49, 0x0B, 0x68, 0x1F, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x00, ++0x13, 0x43, 0x0B, 0x60, 0x1D, 0x48, 0x78, 0xF7, 0x3F, 0xFA, 0x18, 0x4B, 0x5B, 0x7F, 0x00, 0x2B, 0x1F, 0xD1, 0x7F, 0xF7, ++0x9B, 0xFE, 0x02, 0x28, 0x21, 0xD1, 0x19, 0x49, 0x0B, 0x68, 0x19, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, ++0x0B, 0x60, 0x17, 0x4B, 0x1A, 0x68, 0x01, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x01, 0x31, 0x8A, 0x43, 0x1A, 0x60, ++0x03, 0xB0, 0x30, 0xBD, 0x77, 0xF7, 0x4E, 0xFB, 0xC2, 0xE7, 0x77, 0xF7, 0x5F, 0xFB, 0xCD, 0xE7, 0x77, 0xF7, 0x70, 0xFB, ++0xD8, 0xE7, 0xFC, 0xF7, 0x49, 0xFB, 0x05, 0x4B, 0x00, 0x22, 0x5A, 0x77, 0xD9, 0xE7, 0x7F, 0xF7, 0x75, 0xFE, 0x03, 0x28, ++0xEA, 0xD1, 0xD8, 0xE7, 0x0C, 0x00, 0x60, 0x40, 0x3C, 0x95, 0x16, 0x00, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, ++0xFF, 0xFD, 0xFF, 0xFF, 0x01, 0x20, 0x00, 0x00, 0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xDF, 0xFF, 0x18, 0x00, 0x58, 0x40, ++0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x91, 0x46, 0x9C, 0x4B, 0x1E, 0x68, 0x80, 0x00, 0x84, 0x59, ++0x3C, 0x23, 0xE3, 0x5C, 0x98, 0x46, 0x9A, 0x4B, 0xE3, 0x61, 0xBD, 0xF7, 0x4D, 0xFA, 0x01, 0x90, 0x00, 0x23, 0xA3, 0x62, ++0x00, 0x20, 0xCE, 0xF7, 0x51, 0xFF, 0x96, 0x4B, 0x1D, 0x68, 0xEB, 0x6E, 0x5A, 0x1C, 0x16, 0xD0, 0x63, 0x60, 0x00, 0x23, ++0xA3, 0x60, 0xE7, 0x8E, 0xA7, 0x62, 0x92, 0x49, 0x9A, 0x00, 0x52, 0x58, 0x00, 0x2A, 0x25, 0xD1, 0x01, 0x33, 0x07, 0x2B, ++0xF8, 0xD1, 0x00, 0x23, 0x9C, 0x46, 0x8E, 0x4B, 0x18, 0x00, 0x41, 0x30, 0xFF, 0x30, 0x00, 0x22, 0x00, 0x21, 0x00, 0x91, ++0x1E, 0xE0, 0x8B, 0x4B, 0x1B, 0x68, 0x01, 0x33, 0x09, 0xD0, 0x8A, 0x4B, 0x1B, 0x68, 0x5B, 0x00, 0x01, 0x9A, 0x94, 0x46, ++0x63, 0x44, 0x88, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xDB, 0xE7, 0xA3, 0x8E, 0xE2, 0x8E, 0x9B, 0x1A, 0x5B, 0x00, 0x01, 0x9A, ++0x94, 0x46, 0x63, 0x44, 0x82, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xD0, 0xE7, 0x01, 0x23, 0x9C, 0x46, 0xDB, 0xE7, 0x40, 0x33, ++0x83, 0x42, 0x07, 0xD0, 0x19, 0x78, 0x09, 0x29, 0xF9, 0xD1, 0x01, 0x32, 0xD2, 0xB2, 0x08, 0x39, 0x00, 0x91, 0xF4, 0xE7, ++0xEB, 0x6E, 0x59, 0x1C, 0x21, 0xD0, 0x63, 0x60, 0x75, 0x4B, 0x9A, 0x88, 0x77, 0x4B, 0x9A, 0x42, 0x02, 0xD9, 0x77, 0x4B, ++0x9C, 0x46, 0x62, 0x44, 0x76, 0x4B, 0x7B, 0x43, 0x93, 0x42, 0x00, 0xD9, 0x13, 0x00, 0x75, 0x4A, 0x93, 0x42, 0x00, 0xD2, ++0x13, 0x00, 0x23, 0x61, 0xB3, 0x68, 0x80, 0x22, 0x52, 0x05, 0x93, 0x42, 0x3B, 0xD2, 0x62, 0x68, 0xD3, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0x6F, 0x4A, 0x93, 0x42, 0x34, 0xD8, 0x6E, 0x4B, 0x98, 0x47, 0xAF, 0xE0, 0x65, 0x4B, 0x1B, 0x68, 0x01, 0x33, ++0x07, 0xD0, 0x64, 0x4B, 0x18, 0x68, 0x01, 0x9B, 0x1D, 0x18, 0x63, 0x48, 0x05, 0x40, 0x65, 0x60, 0xD2, 0xE7, 0x63, 0x46, ++0x00, 0x2B, 0x03, 0xD1, 0x66, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x08, 0xD0, 0x5C, 0x4B, 0x18, 0x68, 0x80, 0x00, 0x01, 0x9B, ++0xC5, 0x18, 0x5B, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xC2, 0xE7, 0x00, 0x9B, 0x00, 0x2B, 0xBF, 0xD0, 0x5F, 0x4B, 0x1B, 0x68, ++0x01, 0x2B, 0x06, 0xD9, 0xD3, 0x01, 0x01, 0x9A, 0x9D, 0x18, 0x54, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xB4, 0xE7, 0x51, 0x4B, ++0x1B, 0x68, 0x01, 0x9A, 0xD5, 0x18, 0x50, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xAC, 0xE7, 0x4B, 0x46, 0x00, 0x2B, 0x05, 0xD1, ++0x55, 0x4A, 0x26, 0x33, 0xD3, 0x5C, 0xA3, 0x75, 0x63, 0x68, 0xE3, 0x62, 0x52, 0x4A, 0x27, 0x23, 0xD2, 0x5C, 0x18, 0x3B, ++0x1A, 0x40, 0xC0, 0x23, 0xDB, 0x01, 0x13, 0x43, 0xA3, 0x82, 0x3F, 0x23, 0xE1, 0x5C, 0x1B, 0x33, 0x42, 0x46, 0x53, 0x43, ++0x4C, 0x4A, 0x98, 0x18, 0x8A, 0x00, 0x11, 0x43, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x02, 0x80, 0x21, 0x8D, 0x49, 0x4A, ++0x9A, 0x18, 0x11, 0x80, 0x3E, 0x22, 0xA2, 0x5C, 0x0A, 0x3A, 0x01, 0x2A, 0x5A, 0xD9, 0x46, 0x4A, 0x98, 0x18, 0xA1, 0x6A, ++0x80, 0x22, 0xD2, 0x01, 0x91, 0x42, 0x00, 0xD3, 0x43, 0x49, 0x44, 0x4A, 0x0A, 0x43, 0x92, 0xB2, 0x02, 0x80, 0x00, 0x21, ++0x42, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x32, 0x7D, 0x92, 0x07, 0x14, 0xD5, 0xF1, 0x7B, 0x09, 0x02, 0xB2, 0x7B, 0x0A, 0x43, ++0x3E, 0x49, 0x59, 0x18, 0x0A, 0x80, 0x71, 0x7C, 0x09, 0x02, 0x32, 0x7C, 0x0A, 0x43, 0x3C, 0x49, 0x59, 0x18, 0x0A, 0x80, ++0xF1, 0x7C, 0x09, 0x02, 0xB2, 0x7C, 0x0A, 0x43, 0x39, 0x49, 0x59, 0x18, 0x0A, 0x80, 0x71, 0x7D, 0xB5, 0x7D, 0x38, 0x4A, ++0x97, 0x78, 0x7A, 0x1E, 0x97, 0x41, 0x30, 0x7D, 0x80, 0x07, 0xC0, 0x0F, 0x01, 0x22, 0x94, 0x46, 0x00, 0x2D, 0x00, 0xD1, ++0x84, 0x46, 0x33, 0x4A, 0x9E, 0x18, 0x09, 0x02, 0xAA, 0x01, 0x0A, 0x43, 0xFF, 0x00, 0x3A, 0x43, 0x80, 0x00, 0x02, 0x43, ++0x61, 0x46, 0x0A, 0x43, 0x32, 0x80, 0x2E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x1F, 0x21, 0x8A, 0x43, 0x11, 0x00, ++0x3E, 0x22, 0xA2, 0x5C, 0x0A, 0x43, 0x1A, 0x80, 0x20, 0x00, 0xCC, 0xF7, 0x71, 0xFF, 0x00, 0x28, 0x0D, 0xD1, 0x00, 0x23, ++0x47, 0x22, 0xA3, 0x54, 0x63, 0x87, 0x03, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x22, 0x49, 0x23, 0x4A, ++0x9A, 0x18, 0x11, 0x80, 0x9F, 0xE7, 0x22, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEE, 0xE7, ++0xE4, 0x29, 0x16, 0x00, 0x71, 0x00, 0x10, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x38, 0x27, 0x16, 0x00, 0x70, 0xA6, 0x16, 0x00, ++0x5C, 0xAB, 0x16, 0x00, 0xE4, 0xE1, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x0F, 0xC4, 0x09, 0x00, 0x00, 0x3C, 0xF6, 0xFF, 0xFF, ++0xE2, 0x04, 0x00, 0x00, 0xA6, 0x0E, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x39, 0xC2, 0x0C, 0x00, 0xF0, 0x29, 0x16, 0x00, ++0x50, 0xE0, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x7A, 0x01, 0x61, 0x40, 0x96, 0x01, 0x61, 0x40, 0x90, 0x01, 0x61, 0x40, ++0xFF, 0x3F, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xBC, 0x01, 0x61, 0x40, 0x7C, 0x01, 0x61, 0x40, 0x7E, 0x01, 0x61, 0x40, ++0x80, 0x01, 0x61, 0x40, 0xE8, 0x29, 0x16, 0x00, 0x8A, 0x01, 0x61, 0x40, 0x76, 0x01, 0x61, 0x40, 0x72, 0x3E, 0x00, 0x00, ++0x9E, 0x01, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x10, 0x23, 0x0F, 0x4A, 0x00, 0x21, 0x0F, 0x48, 0x78, 0xF7, ++0x53, 0xFC, 0x00, 0x22, 0x02, 0x70, 0x05, 0x23, 0x43, 0x70, 0x04, 0x3B, 0x83, 0x70, 0x80, 0x21, 0x89, 0x00, 0x81, 0x80, ++0xFE, 0x39, 0xFF, 0x39, 0x81, 0x71, 0xC3, 0x71, 0x0B, 0x31, 0x01, 0x72, 0x43, 0x72, 0x53, 0x31, 0x41, 0x81, 0x57, 0x39, ++0x81, 0x81, 0x83, 0x73, 0xC2, 0x73, 0xCA, 0xF7, 0x9B, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0xC0, 0x46, 0x53, 0xFD, 0x00, 0x00, ++0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x10, 0x4A, 0x11, 0x68, 0xA0, 0x23, 0x5B, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x0E, 0x4C, ++0x01, 0x23, 0x23, 0x60, 0x05, 0x20, 0x7F, 0xF7, 0x10, 0xFD, 0x00, 0x23, 0x23, 0x60, 0x0B, 0x49, 0x04, 0x22, 0x0B, 0x68, ++0x1A, 0x42, 0xFC, 0xD0, 0x06, 0x4A, 0x13, 0x68, 0x08, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x08, 0x4C, 0x01, 0x23, 0x23, 0x60, ++0x05, 0x20, 0x7F, 0xF7, 0xFE, 0xFC, 0x00, 0x23, 0x23, 0x60, 0x10, 0xBD, 0x58, 0x40, 0x34, 0x40, 0x54, 0x40, 0x34, 0x40, ++0x80, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xEB, 0xFF, 0x48, 0x20, 0x62, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, ++0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x04, 0x90, 0x0F, 0x00, 0x16, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x11, 0x00, ++0x19, 0x40, 0x05, 0x91, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x04, 0x9A, 0x93, 0x00, 0xA3, 0x49, 0x8C, 0x46, 0x63, 0x44, ++0x1C, 0x68, 0xA2, 0x46, 0xA1, 0x4B, 0x63, 0x62, 0xE5, 0x6C, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD5, 0x4F, 0xE2, ++0x93, 0x00, 0x9E, 0x4A, 0x9B, 0x58, 0x1A, 0x8A, 0x00, 0x2A, 0x0E, 0xD0, 0x84, 0x23, 0xE3, 0x5A, 0x5B, 0x07, 0x00, 0xD5, ++0x36, 0xE2, 0x9A, 0x4B, 0x23, 0x61, 0xA2, 0x6E, 0x99, 0x4B, 0x1B, 0x68, 0x9A, 0x42, 0x00, 0xD1, 0x3C, 0xE2, 0x96, 0x4B, ++0x2F, 0xE2, 0x06, 0x32, 0x1A, 0x82, 0x96, 0x48, 0x7A, 0xF7, 0xD0, 0xFC, 0xEA, 0xE7, 0x96, 0x23, 0x00, 0x22, 0xE2, 0x54, ++0x00, 0x2E, 0x00, 0xD1, 0x34, 0xE2, 0x20, 0x3B, 0xE3, 0x5A, 0x00, 0x2B, 0x00, 0xD1, 0x2F, 0xE2, 0x80, 0x21, 0xC9, 0x00, ++0x8E, 0x4A, 0x02, 0x40, 0x8A, 0x42, 0x00, 0xD0, 0x28, 0xE2, 0x02, 0x07, 0x00, 0xD5, 0x25, 0xE2, 0x4A, 0x22, 0xA2, 0x5C, ++0x00, 0x2A, 0x00, 0xD0, 0x20, 0xE2, 0xA2, 0x6E, 0x5A, 0x43, 0x55, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x22, 0xA1, 0x5A, ++0x5B, 0x18, 0xA3, 0x52, 0x96, 0x23, 0x7D, 0x3A, 0xE2, 0x54, 0x7B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x81, 0x4A, 0x93, 0x42, ++0x00, 0xD8, 0x13, 0xE2, 0xE7, 0x6D, 0x2B, 0xE2, 0x46, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x26, 0xE2, 0x7C, 0x33, ++0xE3, 0x5A, 0x7E, 0x22, 0xA2, 0x5A, 0x9B, 0x18, 0x48, 0x22, 0xA2, 0x5A, 0x9B, 0x1A, 0x79, 0x4A, 0x9B, 0xB2, 0x93, 0x42, ++0x00, 0xD9, 0x19, 0xE2, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x21, 0xD1, 0x40, 0x33, 0xE3, 0x5A, 0x5D, 0x19, 0x2D, 0x01, ++0x2D, 0x09, 0xC3, 0x07, 0x00, 0xD4, 0xCA, 0xE1, 0x44, 0x23, 0xE3, 0x5A, 0x5B, 0x08, 0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, ++0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, 0xE3, 0x66, 0x46, 0x23, 0x01, 0x22, ++0xE2, 0x54, 0x48, 0x33, 0xE0, 0x5C, 0x68, 0x4B, 0x98, 0x47, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD4, 0xBB, 0xE1, ++0x7C, 0x23, 0xE2, 0x5A, 0x02, 0x33, 0xE3, 0x5A, 0xD2, 0x18, 0x48, 0x23, 0xE3, 0x5A, 0xD2, 0x1A, 0x92, 0xB2, 0x53, 0x1E, ++0x9B, 0xB2, 0x00, 0x2A, 0x0A, 0xD0, 0xA1, 0x6E, 0x2F, 0x00, 0x5E, 0x4A, 0x7F, 0x1A, 0x3F, 0x01, 0x3F, 0x09, 0x01, 0x3B, ++0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD1, 0xDB, 0xE1, 0x2F, 0x00, 0xD9, 0xE1, 0x00, 0x2B, 0x00, 0xD1, 0x5F, 0xE1, 0x68, 0xE1, ++0x01, 0x3B, 0x1B, 0x01, 0x1B, 0x09, 0x56, 0x4A, 0x94, 0x46, 0xE0, 0x44, 0x78, 0xE1, 0x2B, 0x00, 0x63, 0x60, 0x50, 0x46, ++0xCC, 0xF7, 0xFA, 0xFD, 0x00, 0x28, 0x00, 0xD1, 0x2E, 0xE1, 0xA3, 0x7D, 0x50, 0x49, 0x2F, 0x22, 0x8A, 0x5C, 0x9B, 0x18, ++0xA3, 0x75, 0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0x02, 0xD5, 0x03, 0x9B, 0x00, 0x2B, 0x4C, 0xD0, 0xA3, 0x6E, 0x9C, 0x46, ++0x65, 0x44, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x22, 0xA3, 0x5A, 0x01, 0x33, 0xA3, 0x52, 0xA3, 0x7D, 0x01, 0x33, 0xA3, 0x75, ++0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0x8C, 0xE0, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x99, 0x45, 0x00, 0xD8, ++0xF5, 0xE0, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0xCF, 0xD5, 0x72, 0x23, 0xE3, 0x5E, 0x98, 0x46, 0x63, 0x6D, 0xEE, 0x1A, ++0x36, 0x01, 0x36, 0x09, 0x77, 0xF7, 0x3C, 0xFF, 0x14, 0x23, 0x00, 0x28, 0x02, 0xD1, 0xC4, 0x33, 0x37, 0x4A, 0xD3, 0x5A, ++0x7A, 0x22, 0xA0, 0x5A, 0xC0, 0x18, 0x70, 0x43, 0xC8, 0x21, 0xC9, 0x00, 0xCE, 0xF7, 0xA2, 0xFD, 0x20, 0x30, 0x46, 0x00, ++0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0x00, 0xD5, 0x04, 0xE1, 0x74, 0x23, 0xE2, 0x5A, 0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, ++0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0xF6, 0x18, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD0, 0x05, 0xE1, 0x46, 0x23, ++0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x8E, 0xE1, 0xFF, 0xE0, 0xF7, 0xF7, 0xB1, 0xFE, 0x00, 0x28, 0xAE, 0xD0, 0x24, 0x4B, ++0x1A, 0x78, 0x01, 0x23, 0x00, 0x2A, 0x08, 0xD0, 0x22, 0x4B, 0x1B, 0x78, 0x01, 0x3B, 0x5A, 0x1E, 0x93, 0x41, 0x5B, 0x42, ++0x06, 0x22, 0x93, 0x43, 0x08, 0x33, 0xA0, 0x6E, 0x02, 0x00, 0x5A, 0x43, 0x80, 0x21, 0x49, 0x00, 0x8A, 0x42, 0x0C, 0xD9, ++0x5A, 0x1E, 0xD2, 0xB2, 0x42, 0x43, 0x8C, 0x46, 0x00, 0xE0, 0x0A, 0x00, 0x01, 0x3B, 0xDB, 0xB2, 0x62, 0x45, 0x02, 0xD9, ++0x11, 0x1A, 0x00, 0x2B, 0xF7, 0xD1, 0x55, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x21, 0x62, 0x5A, 0xD3, 0x18, 0x63, 0x52, ++0x01, 0x23, 0x03, 0x93, 0x8B, 0xE7, 0xC0, 0x46, 0xF4, 0x29, 0x16, 0x00, 0x95, 0x9D, 0x10, 0x00, 0x5C, 0xA9, 0x16, 0x00, ++0xDE, 0x0D, 0x00, 0x00, 0x64, 0xE6, 0x10, 0x00, 0xEC, 0xD3, 0x10, 0x00, 0x04, 0x04, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, ++0xFE, 0x7F, 0x00, 0x00, 0xF1, 0x12, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, ++0x8C, 0xA9, 0x16, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0x46, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, ++0x6D, 0xE7, 0x7C, 0x33, 0xE3, 0x5A, 0x7E, 0x22, 0xA2, 0x5A, 0x9B, 0x18, 0x48, 0x22, 0xA2, 0x5A, 0x9B, 0x1A, 0x9F, 0x4A, ++0x9B, 0xB2, 0x93, 0x42, 0x00, 0xD9, 0x60, 0xE7, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x26, 0xD1, 0x40, 0x33, 0xE3, 0x5A, ++0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD4, 0x76, 0xE0, 0x44, 0x23, 0xE3, 0x5A, ++0x5B, 0x08, 0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, ++0xE3, 0x6B, 0xE3, 0x66, 0x8E, 0x23, 0xE0, 0x5C, 0x8E, 0x4B, 0x98, 0x47, 0x46, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xE3, 0x6E, ++0x99, 0x46, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x01, 0xD4, 0x47, 0x23, 0xE2, 0x54, 0x7C, 0x23, 0xE2, 0x5A, 0x02, 0x33, ++0xE3, 0x5A, 0xD2, 0x18, 0x48, 0x23, 0xE3, 0x5A, 0xD2, 0x1A, 0x92, 0xB2, 0x53, 0x1E, 0x9B, 0xB2, 0x00, 0x2A, 0x0A, 0xD0, ++0xA1, 0x6E, 0x2F, 0x00, 0x81, 0x4A, 0x7F, 0x1A, 0x3F, 0x01, 0x3F, 0x09, 0x01, 0x3B, 0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD1, ++0x1D, 0xE7, 0x2F, 0x00, 0x1B, 0xE7, 0x7D, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x7C, 0x4B, 0x1B, 0x68, 0x00, 0x21, 0x1B, 0x02, ++0x0A, 0xD5, 0x7B, 0x48, 0x7A, 0xF7, 0x2E, 0xFB, 0x84, 0x23, 0xE2, 0x5A, 0x92, 0x07, 0xD2, 0x17, 0x4F, 0x3B, 0x9A, 0x43, ++0x3E, 0x32, 0x0A, 0xE0, 0x01, 0x20, 0xF8, 0xF7, 0x85, 0xFA, 0x01, 0x21, 0xEF, 0xE7, 0x84, 0x23, 0xE3, 0x5A, 0x08, 0x22, ++0x9B, 0x07, 0x00, 0xD4, 0xB6, 0xE0, 0x01, 0x21, 0x04, 0x98, 0x70, 0x4B, 0x98, 0x47, 0x05, 0x9B, 0x00, 0x2B, 0x00, 0xD1, ++0x62, 0xB6, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x8F, 0x23, 0x00, 0x22, ++0xE2, 0x54, 0xE5, 0x64, 0x0B, 0x3B, 0xE3, 0x5A, 0x9A, 0x07, 0x02, 0xD5, 0x62, 0x4A, 0x00, 0x21, 0x11, 0x70, 0xDB, 0x07, ++0xE7, 0xD5, 0x70, 0x23, 0x42, 0x46, 0xE2, 0x52, 0x1C, 0x36, 0x26, 0x65, 0xE1, 0xE7, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, ++0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, 0xE3, 0x66, 0x91, 0xE7, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, ++0x91, 0xE0, 0xA2, 0x6E, 0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, 0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0x5B, 0x08, 0xB3, 0x42, ++0xBF, 0xD9, 0x73, 0x08, 0x9B, 0x46, 0x54, 0x49, 0x18, 0x00, 0xCE, 0xF7, 0x81, 0xFC, 0x01, 0x00, 0x2B, 0x1A, 0x1B, 0x01, ++0x1B, 0x09, 0x40, 0x01, 0x40, 0x1A, 0x80, 0x00, 0x40, 0x18, 0x82, 0x00, 0x80, 0x18, 0x42, 0x46, 0x59, 0x46, 0x52, 0x1A, ++0x82, 0x18, 0x90, 0x46, 0x00, 0xD5, 0x7F, 0xE6, 0x42, 0x46, 0xA2, 0x60, 0x22, 0x6E, 0x92, 0x19, 0x22, 0x61, 0x81, 0xE6, ++0xE3, 0x6E, 0x99, 0x46, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x08, 0x22, 0x99, 0x45, 0xA0, 0xD9, 0x00, 0x23, 0x03, 0x93, ++0x1C, 0x26, 0x98, 0x46, 0x9F, 0xE6, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, ++0xE3, 0x66, 0x46, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x47, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x3F, 0xE6, 0x39, 0x4B, 0x23, 0x61, ++0xA2, 0x6E, 0xA1, 0x6D, 0x00, 0x20, 0x01, 0x90, 0x00, 0x93, 0x00, 0x23, 0x20, 0x00, 0xF7, 0xF7, 0xC1, 0xFB, 0x35, 0x4B, ++0xA2, 0x6E, 0x1A, 0x60, 0x84, 0x23, 0xE0, 0x5A, 0xC3, 0x43, 0x9B, 0x07, 0x00, 0xD1, 0xC4, 0xE5, 0x7B, 0x1B, 0x1B, 0x01, ++0x1B, 0x09, 0x30, 0x4A, 0x93, 0x42, 0x13, 0xD8, 0xA1, 0x6E, 0x7E, 0x23, 0xE2, 0x5A, 0x01, 0x32, 0x92, 0xB2, 0x2C, 0x4E, ++0x4D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x03, 0x92, 0x01, 0x32, 0x92, 0xB2, 0x7B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0xB3, 0x42, ++0xF4, 0xD9, 0x7E, 0x23, 0x03, 0x9A, 0xE2, 0x52, 0xE7, 0x6D, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0xD3, 0xE5, ++0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0xAB, 0xD4, 0x14, 0x23, 0xA3, 0x75, 0xA2, 0x6E, 0x53, 0x00, 0x9B, 0x18, 0x5B, 0x00, ++0x99, 0x46, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x4B, 0x45, 0xA7, 0xD3, 0x12, 0x4B, 0x1B, 0x78, 0x01, 0x33, 0xDB, 0xB2, ++0x03, 0x2B, 0x00, 0xD9, 0x23, 0xE7, 0x0F, 0x4A, 0x13, 0x70, 0x3E, 0x22, 0x3D, 0xE7, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x00, 0xD1, 0x68, 0xE7, 0x00, 0x23, 0x47, 0x22, 0xA2, 0x5C, 0x00, 0x2A, 0x00, 0xD0, 0xFF, 0xE5, 0x44, 0x23, 0xE2, 0x5A, ++0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, 0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0xF6, 0x18, 0x62, 0xE7, 0xFE, 0x7F, 0x00, 0x00, ++0xF1, 0x12, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xE6, 0x10, 0x00, 0x58, 0x40, 0x34, 0x40, 0xF8, 0xD3, 0x10, 0x00, ++0x65, 0x17, 0x0D, 0x00, 0x71, 0x02, 0x00, 0x00, 0x42, 0x0E, 0x00, 0x00, 0x64, 0xE6, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x07, ++0xF8, 0xB5, 0x04, 0x1E, 0x32, 0xD0, 0xA1, 0xF7, 0x55, 0xFD, 0x05, 0x00, 0x8F, 0x23, 0xE6, 0x5C, 0x00, 0x2E, 0x17, 0xD1, ++0xE3, 0x6C, 0xA2, 0x6E, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x64, 0x7E, 0x22, 0xA3, 0x5A, 0x01, 0x33, ++0xA3, 0x52, 0xA3, 0x7D, 0x13, 0x49, 0x4F, 0x3A, 0x8A, 0x5C, 0x9B, 0x18, 0xA3, 0x75, 0x8E, 0x23, 0xE0, 0x5C, 0x00, 0x22, ++0x29, 0x00, 0xFF, 0xF7, 0x01, 0xFD, 0xF8, 0xBD, 0x67, 0x68, 0xA1, 0xF7, 0x35, 0xFD, 0x03, 0x00, 0x3A, 0x00, 0x31, 0x00, ++0x0B, 0x48, 0x7A, 0xF7, 0x03, 0xFA, 0x8F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0xDA, 0xD0, 0x09, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD3, 0xE7, 0x05, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0xE3, 0xE7, 0xC0, 0x46, 0x7C, 0x91, 0x0D, 0x00, 0x08, 0xD4, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x80, 0x46, 0x0F, 0x00, 0x16, 0x00, 0x1D, 0x00, 0x02, 0x21, 0x10, 0x20, 0x78, 0xF7, 0xAD, 0xF9, 0x04, 0x00, ++0x04, 0x23, 0x03, 0x70, 0xFB, 0x33, 0x43, 0x70, 0xF2, 0x3B, 0x83, 0x70, 0x43, 0x46, 0xC3, 0x70, 0x47, 0x60, 0x86, 0x60, ++0xC5, 0x60, 0x1F, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x1A, 0xD0, 0x01, 0x2B, 0x30, 0xD1, 0x1D, 0x4B, 0x1B, 0x68, 0x00, 0x2B, ++0x0D, 0xD0, 0x0A, 0x25, 0x1B, 0x4F, 0x80, 0x26, 0xB6, 0x02, 0xE8, 0x20, 0x7F, 0xF7, 0xA7, 0xF9, 0x3B, 0x68, 0x33, 0x42, ++0x25, 0xD1, 0x01, 0x3D, 0xED, 0xB2, 0x00, 0x2D, 0xF5, 0xD1, 0x00, 0x23, 0x15, 0x4A, 0x10, 0x21, 0x20, 0x00, 0x81, 0xF7, ++0x6D, 0xFC, 0x17, 0xE0, 0x13, 0x48, 0x14, 0x49, 0x01, 0x22, 0x43, 0x58, 0x1A, 0x42, 0xFC, 0xD1, 0x10, 0x4B, 0x12, 0x4A, ++0x9C, 0x50, 0x12, 0x4A, 0x99, 0x58, 0x10, 0x20, 0x01, 0x43, 0x99, 0x50, 0x81, 0x21, 0x49, 0x01, 0x5A, 0x58, 0x02, 0x43, ++0x5A, 0x50, 0x0B, 0x49, 0x5A, 0x58, 0x0F, 0x38, 0x02, 0x43, 0x5A, 0x50, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0A, 0x4B, ++0x80, 0x22, 0x92, 0x02, 0x1A, 0x60, 0xD8, 0xE7, 0xA8, 0xE5, 0x10, 0x00, 0x28, 0x25, 0x16, 0x00, 0x1C, 0x41, 0x04, 0x40, ++0x19, 0x74, 0x08, 0x00, 0x00, 0x00, 0x07, 0x40, 0x08, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, ++0x08, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, ++0x10, 0xB5, 0x01, 0x00, 0x13, 0x00, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x00, 0xD4, 0x72, 0xB6, 0x74, 0x46, 0x0E, 0x4A, ++0x94, 0x42, 0x0F, 0xD0, 0x22, 0x00, 0x0D, 0x48, 0x7A, 0xF7, 0x6A, 0xF9, 0x23, 0x00, 0x00, 0x22, 0x00, 0x21, 0x57, 0x20, ++0xFF, 0xF7, 0x7A, 0xFF, 0x09, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x05, 0xD0, 0x72, 0xB6, 0xFE, 0xE7, 0x07, 0x48, 0x7A, 0xF7, ++0x5B, 0xF9, 0x10, 0xBD, 0x06, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0xF4, 0xE7, 0xC0, 0x46, 0xB9, 0x25, 0x0D, 0x00, ++0x40, 0xD4, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, 0x18, 0xD4, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x82, 0xB0, ++0x04, 0x00, 0x0D, 0x00, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x00, 0xD4, 0x72, 0xB6, 0x76, 0x46, 0x00, 0x93, 0x33, 0x00, ++0x2A, 0x00, 0x21, 0x00, 0x09, 0x48, 0x7A, 0xF7, 0x39, 0xF9, 0x33, 0x00, 0x2A, 0x00, 0x21, 0x00, 0x57, 0x20, 0xFF, 0xF7, ++0x49, 0xFF, 0x06, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x01, 0xD0, 0x72, 0xB6, 0xFE, 0xE7, 0x04, 0x4B, 0x80, 0x22, 0xD2, 0x04, ++0x1A, 0x60, 0xF8, 0xE7, 0x64, 0xD4, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x65, 0x4B, 0x1E, 0x68, 0x07, 0x20, 0xA1, 0xF7, 0xA4, 0xF9, ++0x00, 0x28, 0x06, 0xD1, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x5F, 0x4A, ++0xD5, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0xDC, 0x00, 0xE4, 0x1A, 0x64, 0x00, 0x5C, 0x4B, 0xE3, 0x18, 0x1D, 0x88, 0xAD, 0xB2, ++0xA1, 0xF7, 0x62, 0xF9, 0x6B, 0x07, 0xE9, 0xD1, 0x3A, 0x23, 0xF3, 0x5C, 0x02, 0x2B, 0x52, 0xD0, 0x57, 0x4B, 0xE3, 0x18, ++0x1B, 0x88, 0x9B, 0xB2, 0x98, 0x46, 0x56, 0x4B, 0xE2, 0x18, 0x13, 0x88, 0x5B, 0x06, 0x1B, 0x0F, 0x02, 0x2B, 0x08, 0xD0, ++0x10, 0x88, 0x40, 0x06, 0x00, 0x0F, 0x52, 0x4B, 0xDF, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xB8, 0x47, 0x39, 0x23, ++0xF3, 0x5C, 0x00, 0x2B, 0x01, 0xD0, 0xEB, 0x05, 0x53, 0xD4, 0x10, 0x23, 0xFF, 0x22, 0x00, 0x21, 0x4B, 0x48, 0x77, 0xF7, ++0xD5, 0xFF, 0x07, 0x00, 0x00, 0x23, 0x83, 0x73, 0xFB, 0x1D, 0xBA, 0x1D, 0x02, 0x92, 0x05, 0xAA, 0x01, 0x92, 0x00, 0x22, ++0x00, 0x92, 0x3A, 0x00, 0x00, 0x21, 0x40, 0x46, 0xB0, 0xF7, 0x7C, 0xFC, 0x43, 0x4B, 0x19, 0x88, 0x43, 0x4B, 0x1B, 0x88, ++0x05, 0x9A, 0x92, 0x00, 0x09, 0x04, 0x0B, 0x43, 0xD3, 0x1A, 0x6A, 0xD4, 0xDB, 0x03, 0x5B, 0x0C, 0x7B, 0x81, 0x3F, 0x4B, ++0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x3B, 0x73, 0xED, 0x05, 0xED, 0x0F, 0x7D, 0x73, 0x38, 0x00, 0x77, 0xF7, 0xD8, 0xFF, ++0x3C, 0x23, 0xF3, 0x5C, 0x3B, 0x22, 0xB2, 0x5C, 0x9A, 0x42, 0x00, 0xD8, 0x96, 0xE7, 0x01, 0x33, 0x3C, 0x22, 0xB3, 0x54, ++0x92, 0xE7, 0x37, 0x33, 0xF3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x8D, 0xE7, 0xEB, 0x05, 0x00, 0xD4, 0x8A, 0xE7, 0x07, 0x20, ++0xA1, 0xF7, 0x2A, 0xF9, 0x00, 0x28, 0x00, 0xD1, 0x84, 0xE7, 0x25, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, ++0x9B, 0x1A, 0x5B, 0x00, 0x22, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0xA1, 0xF7, 0xEE, 0xF8, 0x76, 0xE7, 0x07, 0x20, ++0xA1, 0xF7, 0x16, 0xF9, 0x00, 0x28, 0xA6, 0xD0, 0x1B, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, ++0x5B, 0x00, 0x19, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x52, 0x07, 0x02, 0xD0, 0xA1, 0xF7, 0xDA, 0xF8, 0x97, 0xE7, 0x1D, 0x4A, ++0x9A, 0x18, 0x11, 0x88, 0x8A, 0xB2, 0x91, 0x46, 0x1B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0xDB, 0x08, 0x9B, 0x46, ++0xFF, 0x23, 0x5A, 0x46, 0x1A, 0x40, 0x92, 0x46, 0x13, 0x00, 0x10, 0x33, 0xFF, 0x22, 0x00, 0x21, 0x0F, 0x48, 0x77, 0xF7, ++0x5D, 0xFF, 0x07, 0x00, 0x5B, 0x46, 0x83, 0x73, 0x12, 0x49, 0x49, 0x44, 0x0F, 0x30, 0x52, 0x46, 0xCE, 0xF7, 0x4C, 0xFE, ++0xA1, 0xF7, 0xB8, 0xF8, 0x7E, 0xE7, 0x80, 0x22, 0x52, 0x05, 0x94, 0x46, 0x63, 0x44, 0x8F, 0xE7, 0x18, 0x27, 0x16, 0x00, ++0x20, 0xA3, 0x16, 0x00, 0x92, 0x69, 0x61, 0x40, 0x9C, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, ++0x01, 0x05, 0x00, 0x00, 0xFA, 0x67, 0x61, 0x40, 0xF8, 0x67, 0x61, 0x40, 0x98, 0x69, 0x61, 0x40, 0x9A, 0x69, 0x61, 0x40, ++0x96, 0x69, 0x61, 0x40, 0x00, 0x00, 0x61, 0x40, 0x70, 0xB5, 0xA1, 0xF7, 0x5F, 0xFB, 0x05, 0x00, 0x0F, 0x4B, 0x1C, 0x68, ++0x00, 0x2C, 0x06, 0xD1, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x70, 0xBD, 0xFF, 0xF7, ++0x03, 0xFF, 0x01, 0x21, 0x20, 0x00, 0xCC, 0xF7, 0x81, 0xFB, 0x3A, 0x23, 0xE3, 0x5C, 0x02, 0x2B, 0x06, 0xD0, 0x07, 0x4B, ++0x1B, 0x7D, 0xA3, 0x75, 0x65, 0x60, 0x06, 0x4B, 0x98, 0x47, 0xED, 0xE7, 0x05, 0x4B, 0x98, 0x47, 0xEA, 0xE7, 0xC0, 0x46, ++0x18, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0xE5, 0xC1, 0x0A, 0x00, 0x99, 0xC1, 0x0A, 0x00, ++0x70, 0xB5, 0x0D, 0x00, 0x14, 0x00, 0x07, 0x29, 0x06, 0xD0, 0x11, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, ++0x28, 0x00, 0xB0, 0x47, 0x01, 0x2C, 0x0E, 0xD9, 0x04, 0x2C, 0x0F, 0xD1, 0x0C, 0x4B, 0x1C, 0x68, 0x01, 0x21, 0x20, 0x00, ++0xCC, 0xF7, 0x52, 0xFB, 0x3A, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x20, 0x00, 0x08, 0x4B, 0x98, 0x47, 0x01, 0xE0, 0xFF, 0xF7, ++0xB3, 0xFF, 0x70, 0xBD, 0x03, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0x28, 0x00, 0xB0, 0x47, 0xF6, 0xE7, ++0x28, 0x19, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0xD1, 0xC2, 0x0A, 0x00, 0x10, 0xB5, 0x01, 0x28, 0x00, 0xD0, 0x10, 0xBD, ++0x00, 0x29, 0xFC, 0xD0, 0x04, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xF8, 0xD0, 0x03, 0x4A, 0xDA, 0x61, 0x03, 0x48, 0x79, 0xF7, ++0xCB, 0xFF, 0xF2, 0xE7, 0x24, 0x27, 0x16, 0x00, 0x85, 0x04, 0x10, 0x00, 0x94, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x1E, 0x4B, ++0x1E, 0x4A, 0x13, 0x60, 0x80, 0x22, 0x52, 0x00, 0x9C, 0x5C, 0x1D, 0x4B, 0xE3, 0x18, 0x1B, 0x01, 0x1A, 0x88, 0xD2, 0x08, ++0x06, 0x21, 0x11, 0x42, 0x08, 0xD1, 0x19, 0x88, 0x89, 0x06, 0x49, 0x0F, 0x18, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x20, 0x00, 0xA8, 0x47, 0x13, 0x4B, 0x1A, 0x68, 0x81, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, 0x12, 0x4B, ++0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0D, 0x4B, 0x1B, 0x68, 0x22, 0x01, 0x9B, 0x18, 0x1B, 0x7B, ++0x00, 0x2B, 0x05, 0xD1, 0x0B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x06, 0x4B, 0x1A, 0x68, ++0x23, 0x01, 0xD3, 0x18, 0x5D, 0x68, 0x00, 0x2D, 0x03, 0xD0, 0x99, 0x68, 0x18, 0x68, 0x02, 0x22, 0xA8, 0x47, 0x70, 0xBD, ++0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0x00, 0x10, 0x06, 0x04, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0xFF, 0x23, ++0x9B, 0x00, 0x98, 0x42, 0x08, 0xD9, 0x05, 0x4B, 0x59, 0x80, 0x00, 0x24, 0x21, 0x00, 0x04, 0x48, 0x79, 0xF7, 0x72, 0xFF, ++0x20, 0x00, 0x10, 0xBD, 0x11, 0x24, 0xF7, 0xE7, 0x54, 0x2A, 0x16, 0x00, 0xA0, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, ++0x0D, 0x00, 0x81, 0x88, 0x00, 0x88, 0xFF, 0xF7, 0xE5, 0xFF, 0x01, 0x1E, 0x04, 0xD0, 0x28, 0x00, 0xFC, 0xF7, 0x90, 0xFE, ++0x00, 0x20, 0x70, 0xBD, 0xE1, 0x88, 0xA0, 0x78, 0xCB, 0xF7, 0xB6, 0xFE, 0x01, 0x00, 0xF4, 0xE7, 0xF0, 0xB5, 0xCE, 0x46, ++0x47, 0x46, 0x80, 0xB5, 0x89, 0xB0, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x23, 0x00, 0x21, 0x26, 0x48, 0x77, 0xF7, 0x46, 0xFE, ++0x80, 0x46, 0x00, 0x23, 0x43, 0x80, 0xB1, 0x79, 0x23, 0x48, 0x79, 0xF7, 0x43, 0xFF, 0xB3, 0x79, 0x00, 0x2B, 0x2A, 0xD1, ++0x60, 0x24, 0x6B, 0x46, 0xDD, 0x1D, 0x16, 0x23, 0x99, 0x46, 0x1F, 0x4F, 0x07, 0xE0, 0x03, 0x23, 0x42, 0x46, 0x13, 0x70, ++0x24, 0xE0, 0x01, 0x34, 0xE4, 0xB2, 0x68, 0x2C, 0x20, 0xD0, 0x4B, 0x46, 0x2B, 0x70, 0x02, 0xAA, 0x29, 0x00, 0x20, 0x00, ++0x3B, 0x68, 0x98, 0x47, 0x00, 0x28, 0xF2, 0xD1, 0x06, 0x22, 0x02, 0xA9, 0x30, 0x00, 0xCE, 0xF7, 0xF3, 0xFC, 0x00, 0x28, ++0xEB, 0xD1, 0x12, 0x4B, 0x9B, 0x68, 0x20, 0x00, 0x98, 0x47, 0x00, 0x28, 0xE1, 0xD1, 0x43, 0x46, 0x5B, 0x88, 0x01, 0x33, ++0x42, 0x46, 0x53, 0x80, 0x04, 0xE0, 0x01, 0x2B, 0x0B, 0xD0, 0x12, 0x23, 0x42, 0x46, 0x13, 0x70, 0x40, 0x46, 0xC9, 0xF7, ++0x69, 0xFC, 0x00, 0x20, 0x09, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x43, 0x46, 0x5B, 0x88, 0x08, 0x33, ++0x42, 0x46, 0x53, 0x80, 0xF0, 0xE7, 0xC0, 0x46, 0x01, 0x11, 0x00, 0x00, 0xAC, 0xD4, 0x10, 0x00, 0x94, 0x92, 0x16, 0x00, ++0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x85, 0xB0, 0x0C, 0x00, 0x16, 0x00, 0x17, 0x0A, ++0xBA, 0x00, 0x91, 0x4B, 0xD5, 0x58, 0x50, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xD6, 0xE0, 0x4B, 0x78, 0x5B, 0x08, ++0x98, 0x46, 0x7F, 0x2B, 0x11, 0xD0, 0x01, 0x93, 0x00, 0x22, 0x19, 0x00, 0x8A, 0x48, 0x79, 0xF7, 0xDD, 0xFE, 0x43, 0x46, ++0x7E, 0x2B, 0x56, 0xD1, 0x36, 0x3B, 0xEB, 0x5C, 0x00, 0x2B, 0x43, 0xD0, 0x00, 0x23, 0x9B, 0x46, 0x7E, 0x33, 0x01, 0x93, ++0x0C, 0xE0, 0x8B, 0x78, 0x9B, 0x46, 0x1A, 0x00, 0x7F, 0x21, 0x81, 0x48, 0x79, 0xF7, 0xCA, 0xFE, 0x7F, 0x23, 0x01, 0x93, ++0x48, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x43, 0xD0, 0xFB, 0xB2, 0x99, 0x46, 0x61, 0x78, 0x4F, 0x08, 0x59, 0x29, 0x00, 0xD8, ++0xE0, 0xE0, 0x7F, 0x2F, 0x05, 0xD1, 0xA3, 0x78, 0x9A, 0x46, 0x0D, 0x2B, 0x55, 0xD8, 0x0B, 0x2B, 0x55, 0xD8, 0x07, 0x23, ++0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x9A, 0x46, 0x23, 0x78, 0x52, 0x46, 0x13, 0x70, 0x14, 0x23, 0x32, 0x00, 0x31, 0x00, ++0x70, 0x48, 0x77, 0xF7, 0xA3, 0xFD, 0x07, 0x00, 0x61, 0x1C, 0x52, 0x46, 0x82, 0xF7, 0x30, 0xF9, 0x02, 0x28, 0x75, 0xD0, ++0x00, 0x28, 0x00, 0xD1, 0xA9, 0xE0, 0x04, 0x28, 0x00, 0xD0, 0x99, 0xE0, 0xFB, 0x22, 0x43, 0x46, 0x15, 0x3B, 0x13, 0x42, ++0x00, 0xD1, 0xB1, 0xE0, 0x19, 0x24, 0x6F, 0xE0, 0x36, 0x33, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, ++0x0C, 0x22, 0x7E, 0x21, 0x9F, 0xF7, 0xC7, 0xFA, 0x00, 0x23, 0x9B, 0x46, 0x7E, 0x33, 0x01, 0x93, 0xBE, 0xE7, 0x00, 0x23, ++0x9B, 0x46, 0xB7, 0xE7, 0x59, 0x46, 0x40, 0x46, 0x82, 0xF7, 0x96, 0xF8, 0x00, 0x28, 0xB5, 0xD1, 0x43, 0x46, 0x7F, 0x2B, ++0x0A, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, 0x0C, 0x22, 0x41, 0x46, 0x9F, 0xF7, ++0xAC, 0xFA, 0x5A, 0xE0, 0x49, 0x3B, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, 0x0C, 0x22, 0x59, 0x46, ++0x9F, 0xF7, 0xB0, 0xFA, 0x4F, 0xE0, 0x15, 0x2B, 0xA9, 0xD1, 0x4B, 0x46, 0x9B, 0x00, 0x48, 0x4A, 0x9B, 0x58, 0xB2, 0x22, ++0x92, 0x00, 0x9A, 0x5C, 0x00, 0x2A, 0xA0, 0xD0, 0xCA, 0x07, 0x9E, 0xD5, 0x46, 0x4A, 0x9A, 0x5C, 0xBA, 0x42, 0x14, 0xD1, ++0x7F, 0x2F, 0x98, 0xD1, 0x44, 0x4A, 0x9B, 0x5C, 0x53, 0x45, 0x94, 0xD0, 0x4B, 0x46, 0x1B, 0x02, 0x01, 0x20, 0x18, 0x43, ++0x78, 0xF7, 0x16, 0xF9, 0x00, 0x28, 0x30, 0xD0, 0x01, 0x23, 0x2A, 0x22, 0x51, 0x46, 0x48, 0x46, 0x9F, 0xF7, 0x8A, 0xFA, ++0x29, 0xE0, 0x4B, 0x46, 0x1B, 0x02, 0x01, 0x20, 0x18, 0x43, 0x78, 0xF7, 0x07, 0xF9, 0x00, 0x28, 0x21, 0xD0, 0x7F, 0x2F, ++0xEE, 0xD0, 0x01, 0x23, 0x2A, 0x22, 0x39, 0x00, 0x48, 0x46, 0x9F, 0xF7, 0x6A, 0xFA, 0x18, 0xE0, 0x33, 0x4B, 0xDC, 0x6E, ++0x00, 0x23, 0x00, 0x22, 0x01, 0x99, 0x08, 0x00, 0xA0, 0x47, 0x1E, 0x24, 0x38, 0x00, 0x0C, 0x38, 0x77, 0xF7, 0x69, 0xFD, ++0x43, 0x46, 0x7F, 0x2B, 0x1C, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0x22, 0x00, 0x41, 0x46, ++0x48, 0x46, 0x9F, 0xF7, 0x50, 0xFA, 0x8A, 0x23, 0xFF, 0x33, 0xEB, 0x5C, 0x00, 0x2B, 0x03, 0xD0, 0x25, 0x4B, 0xEB, 0x5C, ++0x00, 0x2B, 0x18, 0xD1, 0x00, 0x20, 0x05, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, ++0x1E, 0x24, 0xDB, 0xE7, 0x49, 0x3B, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0x22, 0x00, 0x59, 0x46, 0x48, 0x46, ++0x9F, 0xF7, 0x42, 0xFA, 0xE1, 0xE7, 0x38, 0x00, 0x77, 0xF7, 0x16, 0xFD, 0xDD, 0xE7, 0xAA, 0x8D, 0xEB, 0x8D, 0xD2, 0x1A, ++0x31, 0x00, 0x16, 0x48, 0x77, 0xF7, 0x24, 0xFC, 0xAA, 0x8D, 0x31, 0x00, 0x14, 0x48, 0x77, 0xF7, 0x1F, 0xFC, 0xD9, 0xE7, ++0x38, 0x00, 0x0C, 0x38, 0x77, 0xF7, 0x29, 0xFD, 0x1A, 0x24, 0xC0, 0xE7, 0x12, 0x2F, 0x00, 0xD8, 0x23, 0xE7, 0x3A, 0x00, ++0x13, 0x3A, 0xD2, 0xB2, 0x01, 0x23, 0x93, 0x40, 0x0C, 0x4A, 0x13, 0x42, 0x00, 0xD1, 0x1A, 0xE7, 0x00, 0x23, 0x9A, 0x46, ++0x6D, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xBC, 0xD4, 0x10, 0x00, 0x01, 0x06, 0x00, 0x00, 0xC6, 0x02, 0x00, 0x00, ++0xC7, 0x02, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xAF, 0x02, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x0A, 0x06, 0x00, 0x00, ++0x31, 0x00, 0x00, 0x03, 0x30, 0xB5, 0x87, 0xB0, 0x1E, 0x4C, 0x23, 0x7B, 0x03, 0x22, 0x13, 0x43, 0x23, 0x73, 0x03, 0xAD, ++0x21, 0x00, 0x27, 0x31, 0x03, 0x22, 0x28, 0x00, 0xCE, 0xF7, 0x9E, 0xFB, 0xE3, 0x89, 0xAB, 0x80, 0x23, 0x8A, 0xEB, 0x80, ++0xA3, 0x7C, 0x2B, 0x72, 0x23, 0x7F, 0x6B, 0x72, 0x28, 0x00, 0xA2, 0xF7, 0x3F, 0xFB, 0x23, 0x00, 0x3C, 0x33, 0x00, 0x24, ++0x1A, 0x78, 0x00, 0x2A, 0x06, 0xD0, 0x01, 0x34, 0xE4, 0xB2, 0x09, 0x33, 0x07, 0x2C, 0xF7, 0xD1, 0x07, 0xB0, 0x30, 0xBD, ++0x06, 0x2C, 0xFB, 0xD8, 0x01, 0xA8, 0x0B, 0x4B, 0x1A, 0x8B, 0x02, 0x80, 0x5A, 0x8B, 0x42, 0x80, 0x5B, 0x7F, 0x03, 0x71, ++0x44, 0x71, 0x08, 0x4A, 0xD0, 0x23, 0xD3, 0x58, 0x98, 0x47, 0x00, 0x28, 0xEC, 0xD1, 0xE3, 0x00, 0x1B, 0x19, 0x03, 0x4C, ++0xE4, 0x18, 0x3C, 0x34, 0x02, 0x23, 0x23, 0x70, 0xE4, 0xE7, 0xC0, 0x46, 0x68, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x10, 0xB5, 0x07, 0x4C, 0xA0, 0x47, 0x86, 0xF7, 0x97, 0xF8, 0x00, 0x28, 0x01, 0xD1, 0x00, 0x20, 0x10, 0xBD, 0xFF, 0xF7, ++0xB1, 0xFF, 0x03, 0x48, 0x79, 0xF7, 0x66, 0xFD, 0xF7, 0xE7, 0xC0, 0x46, 0xDD, 0x90, 0x0A, 0x00, 0xCC, 0xD4, 0x10, 0x00, ++0x00, 0xB5, 0x83, 0xB0, 0x01, 0xAA, 0x01, 0x23, 0x0B, 0x40, 0x30, 0x21, 0x0B, 0x43, 0x13, 0x70, 0x11, 0x00, 0x9F, 0xF7, ++0x41, 0xF9, 0x03, 0xB0, 0x00, 0xBD, 0x00, 0x00, 0x30, 0xB5, 0x83, 0xB0, 0x04, 0x00, 0x00, 0x0A, 0x82, 0x00, 0x0E, 0x4B, ++0xD2, 0x58, 0x3C, 0x23, 0xD3, 0x5C, 0x02, 0x2B, 0x07, 0xD0, 0x96, 0x22, 0x52, 0x00, 0x21, 0x00, 0x0A, 0x48, 0x77, 0xF7, ++0x7D, 0xFB, 0x03, 0xB0, 0x30, 0xBD, 0x6B, 0x46, 0x9D, 0x1D, 0xC0, 0xB2, 0x00, 0x22, 0x29, 0x00, 0x89, 0xF7, 0xEE, 0xFA, ++0x28, 0x88, 0x79, 0xF7, 0x95, 0xFD, 0x40, 0x00, 0x02, 0x00, 0x2D, 0x32, 0xFF, 0x32, 0xEA, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0x05, 0x06, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x00, 0x0A, 0x82, 0x00, 0x07, 0x4B, 0xD2, 0x58, 0x36, 0x23, 0xD1, 0x5C, ++0xC0, 0xB2, 0xFF, 0xF7, 0xC1, 0xFF, 0x20, 0x00, 0xFF, 0xF7, 0xCC, 0xFF, 0x32, 0x21, 0x20, 0x00, 0x77, 0xF7, 0x8C, 0xFF, ++0x10, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x70, 0xB5, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x17, 0x4B, 0xD6, 0x58, ++0x20, 0x00, 0x77, 0xF7, 0xDF, 0xFF, 0x03, 0x00, 0x19, 0x28, 0x1D, 0xD8, 0x01, 0x38, 0xC0, 0xB2, 0x14, 0x28, 0x06, 0xD8, ++0x02, 0x20, 0x01, 0x2B, 0x15, 0xD1, 0x3C, 0x23, 0xF3, 0x5C, 0x02, 0x2B, 0x16, 0xD0, 0x08, 0x23, 0x14, 0x22, 0x00, 0x21, ++0x0D, 0x48, 0x77, 0xF7, 0xF5, 0xFB, 0x0C, 0x23, 0x03, 0x70, 0x80, 0x35, 0x45, 0x80, 0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, ++0xF3, 0x5C, 0x03, 0x71, 0xC9, 0xF7, 0x4A, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x02, 0x20, 0x66, 0x2B, 0xFB, 0xD1, 0xE4, 0xE7, ++0x20, 0x00, 0xFF, 0xF7, 0xB9, 0xFF, 0x00, 0x20, 0xF5, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, ++0x70, 0xB5, 0x82, 0xB0, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x24, 0x4B, 0xD6, 0x58, 0x20, 0x00, 0x77, 0xF7, 0xA6, 0xFF, ++0x01, 0x28, 0x16, 0xD0, 0x04, 0xD9, 0x16, 0x38, 0xC3, 0xB2, 0x02, 0x20, 0x03, 0x2B, 0x0E, 0xD8, 0x06, 0x23, 0x1C, 0x22, ++0x00, 0x21, 0x1D, 0x48, 0x77, 0xF7, 0xC2, 0xFB, 0x02, 0x23, 0x03, 0x70, 0x80, 0x35, 0x45, 0x80, 0x00, 0x23, 0x83, 0x80, ++0xC9, 0xF7, 0x1A, 0xFA, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x36, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x0E, 0xD1, 0x01, 0xA9, ++0x0A, 0x33, 0x0B, 0x70, 0xE8, 0xB2, 0x9F, 0xF7, 0x9D, 0xF8, 0x20, 0x00, 0xFF, 0xF7, 0x5C, 0xFF, 0x06, 0x21, 0x20, 0x00, ++0x77, 0xF7, 0x1C, 0xFF, 0x00, 0x20, 0xEA, 0xE7, 0x06, 0x23, 0x1C, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x77, 0xF7, 0x9E, 0xFB, ++0x04, 0x00, 0x00, 0x23, 0x03, 0x70, 0x2B, 0x00, 0x80, 0x33, 0x43, 0x80, 0xE8, 0xB2, 0xA8, 0xF7, 0x3D, 0xFF, 0x00, 0x04, ++0x40, 0x0C, 0xA0, 0x80, 0x20, 0x00, 0xC9, 0xF7, 0xEF, 0xF9, 0x00, 0x20, 0xD3, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x03, 0x11, 0x00, 0x00, 0x70, 0xB5, 0x14, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x14, 0x4A, 0x9D, 0x58, 0x20, 0x00, 0x77, 0xF7, ++0x55, 0xFF, 0x00, 0x28, 0x1E, 0xD0, 0x16, 0x38, 0xC3, 0xB2, 0x00, 0x20, 0x03, 0x2B, 0x13, 0xD9, 0x43, 0x23, 0x01, 0x22, ++0xEA, 0x54, 0x07, 0x3B, 0xEB, 0x5C, 0x02, 0x2B, 0x0D, 0xD0, 0x37, 0x23, 0xE9, 0x5C, 0x20, 0x00, 0x8B, 0xF7, 0x32, 0xF8, ++0x00, 0x28, 0x0D, 0xD0, 0x37, 0x23, 0xE9, 0x5C, 0x20, 0x00, 0x90, 0xF7, 0x57, 0xFF, 0x00, 0x20, 0x70, 0xBD, 0x20, 0x00, ++0x89, 0xF7, 0xFE, 0xFD, 0x02, 0x20, 0xF9, 0xE7, 0x00, 0x20, 0xF7, 0xE7, 0x02, 0x20, 0xF5, 0xE7, 0x64, 0xA2, 0x16, 0x00, ++0x10, 0xB5, 0x80, 0x00, 0x0F, 0x4B, 0xC4, 0x58, 0x8E, 0xF7, 0xD4, 0xFC, 0x03, 0x00, 0x01, 0x20, 0x0B, 0x2B, 0x13, 0xD9, ++0x11, 0x2B, 0x06, 0xD8, 0x20, 0x00, 0x54, 0x30, 0x00, 0x21, 0x9E, 0xF7, 0x53, 0xFF, 0x00, 0x28, 0x0B, 0xD1, 0x20, 0x00, ++0x54, 0x30, 0x01, 0x21, 0x9E, 0xF7, 0x4C, 0xFF, 0x43, 0x42, 0x58, 0x41, 0x40, 0x42, 0x03, 0x23, 0x98, 0x43, 0x05, 0x30, ++0x10, 0xBD, 0x03, 0x20, 0xFC, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x02, 0x00, 0x00, 0x29, 0x16, 0xD1, 0x01, 0x23, ++0x03, 0x40, 0x58, 0x42, 0x43, 0x41, 0x58, 0x42, 0x20, 0x4B, 0x18, 0x40, 0x20, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x06, 0x23, ++0x1A, 0x40, 0x04, 0x2A, 0x02, 0xD0, 0x02, 0x2A, 0x03, 0xD0, 0x70, 0x47, 0x80, 0x04, 0x80, 0x0C, 0xFB, 0xE7, 0x1B, 0x4B, ++0x18, 0x40, 0xF8, 0xE7, 0x18, 0x23, 0x19, 0x00, 0x01, 0x40, 0x03, 0x42, 0x21, 0xD0, 0x08, 0x29, 0x0E, 0xD0, 0x60, 0x23, ++0x03, 0x40, 0x40, 0x2B, 0x21, 0xD0, 0x20, 0x3B, 0x18, 0x00, 0x43, 0x1E, 0x98, 0x41, 0x40, 0x42, 0x12, 0x4B, 0x18, 0x40, ++0x12, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xE2, 0xE7, 0x48, 0x33, 0x03, 0x40, 0x60, 0x2B, 0x0E, 0xD0, 0x40, 0x2B, 0x0E, 0xD0, ++0x20, 0x3B, 0x18, 0x00, 0x43, 0x1E, 0x98, 0x41, 0x40, 0x42, 0x0C, 0x4B, 0x18, 0x40, 0x0C, 0x4B, 0x9C, 0x46, 0x60, 0x44, ++0xD1, 0xE7, 0x0B, 0x48, 0xCF, 0xE7, 0x0B, 0x48, 0xCD, 0xE7, 0x0B, 0x48, 0xCB, 0xE7, 0x0B, 0x48, 0xC9, 0xE7, 0xC0, 0x46, ++0xF0, 0x77, 0xFF, 0xFF, 0x1E, 0xFF, 0x00, 0x00, 0xFF, 0x33, 0x00, 0x00, 0x00, 0xCD, 0xFF, 0xFF, 0x08, 0x33, 0x00, 0x00, ++0x00, 0xEF, 0xFF, 0xFF, 0x0C, 0x33, 0x00, 0x00, 0x0E, 0x33, 0x00, 0x00, 0x0C, 0x22, 0x00, 0x00, 0x0C, 0x32, 0x00, 0x00, ++0x08, 0x30, 0x00, 0x00, 0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x77, 0xF7, 0xA4, 0xFE, 0x03, 0x00, 0x01, 0x28, ++0x0A, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x06, 0xD9, 0x16, 0x3B, 0xDB, 0xB2, 0x03, 0x30, 0x98, 0x42, 0x80, 0x41, 0x40, 0x42, ++0x40, 0x00, 0x70, 0xBD, 0x24, 0x0A, 0xA2, 0x00, 0x0F, 0x4B, 0xD6, 0x58, 0x3F, 0x23, 0xF1, 0x5C, 0x68, 0x78, 0xFF, 0xF7, ++0x83, 0xFF, 0x70, 0x85, 0xE4, 0xB2, 0x20, 0x00, 0xFF, 0xF7, 0x5A, 0xFF, 0x9E, 0xF7, 0x5C, 0xFF, 0x71, 0x8D, 0x01, 0x22, ++0x9E, 0xF7, 0x08, 0xFD, 0x31, 0x8C, 0x01, 0x22, 0x9E, 0xF7, 0x04, 0xFD, 0x01, 0x00, 0x33, 0x8C, 0x00, 0x20, 0x8B, 0x42, ++0xE1, 0xD0, 0x20, 0x00, 0xA8, 0xF7, 0xA2, 0xFF, 0x00, 0x20, 0xDC, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, ++0x00, 0xB5, 0x05, 0x00, 0x08, 0x00, 0x0E, 0x0A, 0xB2, 0x00, 0x29, 0x4B, 0xD4, 0x58, 0x77, 0xF7, 0x67, 0xFE, 0x00, 0x28, ++0x03, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x03, 0xD8, 0x00, 0x20, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2B, 0x78, ++0x01, 0x27, 0x3B, 0x40, 0x39, 0x22, 0xA3, 0x54, 0x54, 0x23, 0x98, 0x46, 0xA0, 0x44, 0x69, 0x1C, 0x31, 0x3A, 0x40, 0x46, ++0xCE, 0xF7, 0x72, 0xF9, 0x57, 0x22, 0xA3, 0x5C, 0x04, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x02, 0x32, 0xA3, 0x5C, 0x3E, 0x31, ++0x8B, 0x43, 0xA3, 0x54, 0x29, 0x78, 0x39, 0x40, 0xF0, 0xB2, 0x9F, 0xF7, 0x2D, 0xF9, 0x09, 0x21, 0x40, 0x46, 0x9E, 0xF7, ++0x73, 0xFE, 0x00, 0x28, 0x0D, 0xD1, 0x85, 0xF7, 0x8F, 0xFE, 0x00, 0x28, 0x02, 0xD0, 0x4F, 0x23, 0x01, 0x22, 0xE2, 0x54, ++0xBC, 0x22, 0x52, 0x00, 0xA3, 0x5C, 0x01, 0x21, 0x0B, 0x43, 0xA3, 0x54, 0xCB, 0xE7, 0x3A, 0x21, 0x40, 0x46, 0x9E, 0xF7, ++0x5F, 0xFE, 0x02, 0x00, 0x53, 0x1E, 0x9A, 0x41, 0x4F, 0x23, 0xE2, 0x54, 0x00, 0x23, 0x00, 0x28, 0x04, 0xD0, 0x05, 0x4A, ++0x05, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0xDB, 0x0F, 0x4F, 0x22, 0xA3, 0x54, 0xDD, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0x7C, 0x1E, 0x16, 0x00, 0xA2, 0x02, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x0B, 0x0A, ++0x98, 0x46, 0x9A, 0x00, 0x32, 0x4B, 0xD4, 0x58, 0x27, 0x00, 0x54, 0x37, 0x41, 0x1C, 0x08, 0x22, 0x38, 0x00, 0xCE, 0xF7, ++0x23, 0xF9, 0x57, 0x22, 0xA3, 0x5C, 0x04, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x02, 0x32, 0xA3, 0x5C, 0x3E, 0x31, 0x8B, 0x43, ++0xA3, 0x54, 0x28, 0x00, 0x77, 0xF7, 0xF4, 0xFD, 0x14, 0x28, 0x13, 0xD0, 0x07, 0xD9, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, ++0x05, 0xD8, 0x00, 0x20, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x00, 0x28, 0xF9, 0xD0, 0x28, 0x00, 0x77, 0xF7, 0xE4, 0xFD, ++0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0x7D, 0xF7, 0xB1, 0xF8, 0xF0, 0xE7, 0x29, 0x00, 0x1D, 0x48, 0x77, 0xF7, 0xBC, 0xF9, ++0x32, 0x78, 0x01, 0x23, 0x13, 0x40, 0x3A, 0x22, 0xA3, 0x54, 0x09, 0x21, 0x38, 0x00, 0x9E, 0xF7, 0x07, 0xFE, 0x00, 0x28, ++0x11, 0xD1, 0xBC, 0x22, 0x52, 0x00, 0xA3, 0x5C, 0x01, 0x21, 0x0B, 0x43, 0xA3, 0x54, 0x3F, 0x21, 0x38, 0x00, 0x9E, 0xF7, ++0xFB, 0xFD, 0x00, 0x28, 0x19, 0xD0, 0x01, 0x22, 0x41, 0x46, 0x28, 0x00, 0x91, 0xF7, 0xE6, 0xF8, 0xCF, 0xE7, 0x3A, 0x21, ++0x38, 0x00, 0x9E, 0xF7, 0xEF, 0xFD, 0x02, 0x00, 0x53, 0x1E, 0x9A, 0x41, 0x4F, 0x23, 0xE2, 0x54, 0x00, 0x23, 0x00, 0x28, ++0x04, 0xD0, 0x08, 0x4A, 0x08, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0xDB, 0x0F, 0x4F, 0x22, 0xA3, 0x54, 0xD9, 0xE7, 0x01, 0x21, ++0x28, 0x00, 0x77, 0xF7, 0x45, 0xFD, 0xB6, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x05, 0x06, 0x00, 0x00, 0x7C, 0x1E, 0x16, 0x00, ++0xA2, 0x02, 0x00, 0x00, 0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0x0E, 0x0A, ++0xB2, 0x00, 0x35, 0x4B, 0xD7, 0x58, 0x02, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xBB, 0x54, 0x36, 0x23, 0xFB, 0x5C, ++0x98, 0x46, 0x33, 0x01, 0x9B, 0x1B, 0x9B, 0x00, 0x2F, 0x4A, 0xD3, 0x18, 0x5B, 0x7B, 0x99, 0x46, 0x08, 0x00, 0x77, 0xF7, ++0x7F, 0xFD, 0x02, 0x00, 0x19, 0x28, 0x1B, 0xD8, 0x01, 0x38, 0xC0, 0xB2, 0x14, 0x28, 0x47, 0xD8, 0x02, 0x20, 0x01, 0x2A, ++0x47, 0xD1, 0x3C, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x36, 0xD1, 0x7B, 0x8C, 0x5B, 0x07, 0x33, 0xD5, 0xA3, 0x88, 0x62, 0x88, ++0x61, 0x78, 0x20, 0x89, 0x01, 0x90, 0xE0, 0x88, 0x00, 0x90, 0x21, 0x4C, 0x94, 0x20, 0x24, 0x58, 0x28, 0x00, 0xA0, 0x47, ++0x00, 0x20, 0x32, 0xE0, 0x2E, 0x28, 0x2F, 0xD1, 0x01, 0x23, 0x4A, 0x46, 0x5A, 0x40, 0x13, 0x00, 0x42, 0x46, 0x5A, 0x40, ++0x13, 0x00, 0x39, 0x22, 0xBA, 0x5C, 0xDB, 0xB2, 0x9A, 0x42, 0x0D, 0xD1, 0xA3, 0x88, 0x62, 0x88, 0x61, 0x78, 0x20, 0x89, ++0x01, 0x90, 0xE0, 0x88, 0x00, 0x90, 0x13, 0x4C, 0x94, 0x20, 0x24, 0x58, 0x28, 0x00, 0xA0, 0x47, 0x00, 0x20, 0x16, 0xE0, ++0x22, 0x78, 0x01, 0x23, 0x13, 0x40, 0xF0, 0xB2, 0x23, 0x22, 0x17, 0x21, 0x9E, 0xF7, 0xA9, 0xFE, 0x00, 0x20, 0x0C, 0xE0, ++0x22, 0x78, 0x01, 0x23, 0x13, 0x40, 0xF0, 0xB2, 0x24, 0x22, 0x17, 0x21, 0x9E, 0xF7, 0x9F, 0xFE, 0x00, 0x20, 0x02, 0xE0, ++0x00, 0x20, 0x00, 0xE0, 0x02, 0x20, 0x03, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x64, 0xA2, 0x16, 0x00, ++0xC0, 0xA0, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x04, 0x00, 0x08, 0x00, 0x0D, 0x0A, 0xAA, 0x00, 0x22, 0x4B, ++0xD6, 0x58, 0x77, 0xF7, 0x19, 0xFD, 0x00, 0x28, 0x3B, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x37, 0xD9, 0x22, 0x78, ++0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x36, 0x23, 0xF3, 0x5C, 0x01, 0x2B, 0x27, 0xD1, 0x23, 0x7A, 0x1B, 0x3A, ++0x01, 0x2B, 0x24, 0xD8, 0x27, 0x00, 0x09, 0x37, 0x38, 0x00, 0x79, 0xF7, 0x93, 0xFA, 0x01, 0x00, 0x13, 0x28, 0x16, 0xD9, ++0x8B, 0x23, 0x9B, 0x00, 0xF0, 0x18, 0x0A, 0x22, 0x39, 0x00, 0xCE, 0xF7, 0x19, 0xF8, 0x22, 0x7A, 0x53, 0x1E, 0x9A, 0x41, ++0xD2, 0xB2, 0xE8, 0xB2, 0x3B, 0x00, 0x61, 0x68, 0xA9, 0xF7, 0x2E, 0xF8, 0x23, 0x7A, 0x5A, 0x1E, 0x93, 0x41, 0x91, 0x22, ++0x92, 0x00, 0xB3, 0x54, 0x0B, 0xE0, 0x08, 0x48, 0x79, 0xF7, 0x12, 0xFA, 0x1E, 0x22, 0x00, 0xE0, 0x24, 0x22, 0x39, 0x23, ++0xF3, 0x5C, 0xE8, 0xB2, 0x3C, 0x21, 0x9E, 0xF7, 0x48, 0xFE, 0x00, 0x20, 0xF8, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, ++0xD8, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x04, 0x00, 0x08, 0x00, 0x0D, 0x0A, 0xAA, 0x00, 0x2B, 0x4B, 0xD6, 0x58, ++0x77, 0xF7, 0xCA, 0xFC, 0x00, 0x28, 0x20, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x1C, 0xD9, 0x22, 0x78, 0x01, 0x23, ++0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x16, 0xD0, 0xA3, 0x78, 0x01, 0x2B, 0x31, 0xD0, ++0x02, 0x2B, 0x39, 0xD0, 0x00, 0x20, 0x00, 0x2B, 0x22, 0xD0, 0x01, 0xA9, 0x39, 0x23, 0xF2, 0x5C, 0x3B, 0x3B, 0x13, 0x43, ++0x0B, 0x70, 0x20, 0x23, 0x4B, 0x70, 0x88, 0x70, 0xE8, 0xB2, 0x9E, 0xF7, 0xC1, 0xFD, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, ++0x85, 0xF7, 0xF8, 0xFC, 0x00, 0x28, 0x03, 0xD0, 0x4F, 0x23, 0x01, 0x22, 0xF2, 0x54, 0xE0, 0xE7, 0x4F, 0x23, 0xF3, 0x5C, ++0x00, 0x2B, 0xDC, 0xD1, 0x39, 0x23, 0xF3, 0x5C, 0xE8, 0xB2, 0x1A, 0x22, 0x1F, 0x21, 0x9E, 0xF7, 0x0D, 0xFE, 0xE8, 0xE7, ++0xE8, 0xB2, 0xF5, 0xF7, 0x59, 0xF9, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0x2A, 0x20, 0x18, 0x40, 0x15, 0x30, 0xD2, 0xE7, ++0xE8, 0xB2, 0xF5, 0xF7, 0x79, 0xF9, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0x15, 0x20, 0x18, 0x40, 0x15, 0x30, 0xC8, 0xE7, ++0xE8, 0xB2, 0x03, 0x4B, 0x1B, 0x69, 0x98, 0x47, 0x2A, 0x20, 0xC2, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x60, 0x92, 0x16, 0x00, ++0x70, 0xB5, 0x14, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x11, 0x4A, 0x9D, 0x58, 0x20, 0x00, 0x77, 0xF7, 0x69, 0xFC, 0x03, 0x00, ++0x01, 0x28, 0x0A, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x06, 0xD9, 0x16, 0x3B, 0xDB, 0xB2, 0x03, 0x30, 0x98, 0x42, 0x80, 0x41, ++0x40, 0x42, 0x40, 0x00, 0x70, 0xBD, 0x36, 0x23, 0xEB, 0x5C, 0x00, 0x20, 0x00, 0x2B, 0xF9, 0xD1, 0x91, 0x23, 0x9B, 0x00, ++0xEB, 0x5C, 0x00, 0x2B, 0xF4, 0xD0, 0x00, 0x21, 0x20, 0x00, 0x8E, 0xF7, 0xDB, 0xFC, 0x00, 0x20, 0xEE, 0xE7, 0xC0, 0x46, ++0x64, 0xA2, 0x16, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x00, 0x90, 0x0F, 0x00, 0x16, 0x00, 0x01, 0x93, 0x0B, 0x78, 0xDC, 0x00, ++0xE3, 0x18, 0x32, 0x4C, 0xE4, 0x18, 0x3C, 0x34, 0x23, 0x78, 0x01, 0x2B, 0x02, 0xD0, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, ++0x4B, 0x78, 0x00, 0x2B, 0x4B, 0xD1, 0x2C, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x4D, 0xD0, 0x2B, 0x4D, 0x2C, 0x00, 0x3F, 0x34, ++0x02, 0xE0, 0x09, 0x35, 0xA5, 0x42, 0x43, 0xD0, 0xAB, 0x79, 0x02, 0x2B, 0xF9, 0xD9, 0x3B, 0x78, 0xD9, 0x00, 0xC9, 0x18, ++0x36, 0x31, 0x23, 0x4B, 0x9C, 0x46, 0x61, 0x44, 0x06, 0x22, 0x28, 0x00, 0xCD, 0xF7, 0x18, 0xFF, 0x00, 0x28, 0xEC, 0xD1, ++0x0C, 0x23, 0x03, 0x22, 0x00, 0x21, 0x1F, 0x48, 0x77, 0xF7, 0x3C, 0xF8, 0x04, 0x00, 0x0B, 0x23, 0x03, 0x70, 0x3B, 0x78, ++0xD9, 0x00, 0xC9, 0x18, 0x36, 0x31, 0x18, 0x4D, 0x49, 0x19, 0x04, 0x30, 0x06, 0x22, 0xCD, 0xF7, 0x27, 0xFF, 0x01, 0x23, ++0x5B, 0x42, 0x63, 0x80, 0x02, 0x33, 0xA3, 0x72, 0x00, 0x26, 0xE6, 0x72, 0x20, 0x00, 0xC8, 0xF7, 0x85, 0xFE, 0x3A, 0x78, ++0xD3, 0x00, 0x9B, 0x18, 0xEB, 0x18, 0x3E, 0x33, 0x18, 0x78, 0x85, 0xF7, 0x0F, 0xFA, 0x3A, 0x78, 0xD3, 0x00, 0x9B, 0x18, ++0xEB, 0x18, 0x3C, 0x33, 0x1E, 0x70, 0x28, 0x68, 0x0C, 0x38, 0x77, 0xF7, 0x62, 0xF8, 0x2E, 0x60, 0xAD, 0xE7, 0x16, 0x2B, ++0xAB, 0xD0, 0x02, 0xE0, 0x7B, 0x78, 0x16, 0x2B, 0xA7, 0xD0, 0x01, 0x9B, 0x32, 0x00, 0x39, 0x00, 0x00, 0x98, 0x04, 0x4C, ++0xA0, 0x47, 0xA0, 0xE7, 0x68, 0x9E, 0x16, 0x00, 0x9E, 0x9E, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, 0xED, 0x33, 0x09, 0x00, ++0xF0, 0xB5, 0x87, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x02, 0x92, 0x03, 0x93, 0x0A, 0x78, 0xD3, 0x00, 0x9A, 0x18, 0x29, 0x4B, ++0x9B, 0x18, 0x3C, 0x33, 0x1B, 0x78, 0x02, 0x2B, 0x02, 0xD0, 0x00, 0x20, 0x07, 0xB0, 0xF0, 0xBD, 0x25, 0x4C, 0x27, 0x00, ++0x3F, 0x37, 0x4E, 0x1C, 0x02, 0xE0, 0x09, 0x34, 0xBC, 0x42, 0x39, 0xD0, 0xA3, 0x79, 0x02, 0x2B, 0xF9, 0xD9, 0x06, 0x22, ++0x31, 0x00, 0x20, 0x00, 0xCD, 0xF7, 0xAE, 0xFE, 0x00, 0x28, 0xF2, 0xD1, 0x1B, 0x4A, 0x29, 0x78, 0xCB, 0x00, 0x5B, 0x18, ++0xD3, 0x18, 0x3C, 0x33, 0x00, 0x21, 0x19, 0x70, 0x13, 0x7B, 0x9B, 0x07, 0xDF, 0xD5, 0x18, 0x4B, 0x00, 0x24, 0x1A, 0x78, ++0x00, 0x2A, 0x05, 0xD0, 0x01, 0x34, 0xE4, 0xB2, 0x09, 0x33, 0x07, 0x2C, 0xF7, 0xD1, 0xD4, 0xE7, 0x06, 0x2C, 0xD2, 0xD8, ++0x0F, 0x4B, 0x1A, 0x8B, 0x04, 0xA9, 0x0A, 0x80, 0x5A, 0x8B, 0x4A, 0x80, 0x5B, 0x7F, 0x0B, 0x71, 0x4C, 0x71, 0x0E, 0x4A, ++0xD0, 0x23, 0xD3, 0x58, 0x08, 0x00, 0x98, 0x47, 0x00, 0x28, 0xC2, 0xD1, 0xE3, 0x00, 0x1C, 0x19, 0x06, 0x4B, 0x1C, 0x19, ++0x3C, 0x34, 0x02, 0x22, 0x22, 0x70, 0xBA, 0xE7, 0x03, 0x9B, 0x02, 0x9A, 0x29, 0x00, 0x01, 0x98, 0x05, 0x4C, 0xA0, 0x47, ++0xB3, 0xE7, 0xC0, 0x46, 0x68, 0x9E, 0x16, 0x00, 0x9E, 0x9E, 0x16, 0x00, 0xA4, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xDD, 0x32, 0x09, 0x00, 0x00, 0x09, 0x70, 0x47, 0x00, 0x28, 0x14, 0xD0, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x03, 0xD0, ++0x0D, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x06, 0xD1, 0x0C, 0x4B, 0x0A, 0x4A, 0x99, 0x68, 0x11, 0x60, 0xDA, 0x68, 0x09, 0x4B, ++0x1A, 0x60, 0x09, 0x4B, 0x09, 0x4A, 0x9A, 0x60, 0x09, 0x4A, 0xDA, 0x60, 0x70, 0x47, 0x06, 0x4B, 0x03, 0x4A, 0x12, 0x68, ++0x9A, 0x60, 0x03, 0x4A, 0x12, 0x68, 0xDA, 0x60, 0xF6, 0xE7, 0xC0, 0x46, 0xB8, 0xE6, 0x10, 0x00, 0xD4, 0xE6, 0x10, 0x00, ++0x60, 0x92, 0x16, 0x00, 0x2D, 0x01, 0x10, 0x00, 0x81, 0x01, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x01, 0x00, 0x2F, 0x48, ++0x79, 0xF7, 0x68, 0xF8, 0x7D, 0xF7, 0xE8, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x70, 0xBD, 0xFF, 0xF7, 0xC9, 0xFF, 0x2B, 0x4A, ++0x95, 0x23, 0x9B, 0x00, 0xD2, 0x5C, 0x2A, 0x4B, 0x1A, 0x70, 0x2A, 0x4B, 0x1A, 0x68, 0x2A, 0x4B, 0x1A, 0x60, 0xE6, 0x23, ++0x5B, 0x00, 0x1B, 0x68, 0x28, 0x48, 0x98, 0x47, 0x28, 0x4B, 0x18, 0x60, 0x01, 0x2C, 0x27, 0xD0, 0x02, 0x23, 0x22, 0x00, ++0x9A, 0x43, 0x05, 0xD0, 0x25, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x1C, 0x4E, 0x95, 0x25, ++0xAD, 0x00, 0x40, 0x23, 0x73, 0x55, 0x1C, 0x4B, 0x20, 0x4A, 0x1A, 0x60, 0x8C, 0x21, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, ++0x49, 0x00, 0x1A, 0x48, 0x98, 0x47, 0x73, 0x5D, 0x1C, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x01, 0x2C, 0x1B, 0xD9, 0x02, 0x2C, ++0xC8, 0xD1, 0x1A, 0x49, 0x0A, 0x88, 0xFF, 0x20, 0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xC1, 0xE7, 0x0D, 0x4D, 0x95, 0x24, ++0xA4, 0x00, 0x30, 0x23, 0x2B, 0x55, 0x0D, 0x4B, 0x11, 0x4A, 0x1A, 0x60, 0x8C, 0x21, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, ++0x49, 0x00, 0x0B, 0x48, 0x98, 0x47, 0x2B, 0x5D, 0x0D, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x0E, 0x49, 0x0A, 0x88, 0xFF, 0x20, ++0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xA7, 0xE7, 0xE4, 0xD4, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0xF6, 0xE8, 0x10, 0x00, ++0x54, 0x07, 0x62, 0x40, 0x08, 0xE7, 0x10, 0x00, 0x58, 0x00, 0x01, 0x50, 0x18, 0xE7, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xFD, 0x20, 0x22, 0x21, 0x60, 0x92, 0x16, 0x00, 0x8E, 0x01, 0x61, 0x40, 0x0C, 0x65, 0x61, 0x40, 0x70, 0xB5, 0x04, 0x00, ++0x01, 0x00, 0x1A, 0x48, 0x78, 0xF7, 0xEE, 0xFF, 0x7D, 0xF7, 0x6E, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x70, 0xBD, 0x00, 0x20, ++0xFF, 0xF7, 0x4E, 0xFF, 0x15, 0x4E, 0x95, 0x25, 0xAD, 0x00, 0x15, 0x4B, 0x1B, 0x78, 0x73, 0x55, 0x14, 0x4B, 0x1A, 0x68, ++0x14, 0x4B, 0x1A, 0x60, 0x14, 0x4B, 0x1B, 0x68, 0x80, 0x21, 0x49, 0x00, 0x19, 0x43, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, ++0x11, 0x48, 0x98, 0x47, 0x73, 0x5D, 0x11, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x01, 0x2C, 0x08, 0xD9, 0x02, 0x2C, 0xDF, 0xD1, ++0x0E, 0x49, 0x0A, 0x88, 0xFF, 0x20, 0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xD8, 0xE7, 0x0C, 0x49, 0x0A, 0x88, 0xFF, 0x20, ++0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xD1, 0xE7, 0xF8, 0xD4, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0xF6, 0xE8, 0x10, 0x00, ++0x08, 0xE7, 0x10, 0x00, 0x54, 0x07, 0x62, 0x40, 0x18, 0xE7, 0x10, 0x00, 0x58, 0x00, 0x01, 0x50, 0x60, 0x92, 0x16, 0x00, ++0x8E, 0x01, 0x61, 0x40, 0x0C, 0x65, 0x61, 0x40, 0x10, 0xB5, 0x09, 0x28, 0x0B, 0xD9, 0xFF, 0x28, 0x0B, 0xD1, 0x0B, 0x09, ++0x1F, 0x29, 0x0D, 0xD9, 0x02, 0x3B, 0x01, 0x2B, 0x05, 0xD8, 0x01, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, 0x01, 0xE0, 0x00, 0x28, ++0x08, 0xD1, 0x10, 0xBD, 0x00, 0x20, 0xFF, 0xF7, 0x25, 0xFF, 0xFA, 0xE7, 0x00, 0x20, 0xFF, 0xF7, 0x9B, 0xFF, 0xF6, 0xE7, ++0x0B, 0x09, 0x1F, 0x29, 0xF4, 0xD9, 0x02, 0x3B, 0x01, 0x2B, 0xF0, 0xD8, 0x01, 0x20, 0xFF, 0xF7, 0x17, 0xFF, 0xEC, 0xE7, ++0xF8, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0x1F, 0x00, 0x13, 0x0A, 0x9B, 0x00, ++0x11, 0x4A, 0x9B, 0x58, 0x99, 0x46, 0x0A, 0x88, 0x10, 0x4B, 0xD3, 0x5C, 0x98, 0x46, 0x20, 0x00, 0x77, 0xF7, 0x42, 0xFA, ++0x0A, 0x28, 0x0A, 0xD0, 0x3B, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0x0B, 0x4C, 0xA0, 0x47, 0x00, 0x20, 0x0C, 0xBC, ++0x90, 0x46, 0x99, 0x46, 0xF8, 0xBD, 0x43, 0x46, 0x5B, 0x08, 0x03, 0x2B, 0xF0, 0xD1, 0x07, 0x4B, 0x4A, 0x46, 0xD1, 0x5C, ++0x06, 0x3B, 0xD0, 0x5C, 0xFF, 0xF7, 0xB0, 0xFF, 0xE8, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, ++0x05, 0x87, 0x0A, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x20, 0x4B, ++0xD6, 0x58, 0x20, 0x00, 0x77, 0xF7, 0x16, 0xFA, 0x03, 0x00, 0x01, 0x28, 0x10, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x05, 0xD9, ++0x19, 0x2B, 0x05, 0xD8, 0x15, 0x22, 0x9A, 0x42, 0x40, 0x41, 0x40, 0x00, 0x02, 0xB0, 0x70, 0xBD, 0x58, 0x3B, 0x18, 0x00, ++0x43, 0x1E, 0x98, 0x41, 0x40, 0x00, 0xF7, 0xE7, 0x4C, 0x23, 0xF3, 0x5C, 0x00, 0x20, 0x00, 0x2B, 0xF2, 0xD1, 0x4B, 0x33, ++0xF3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x4B, 0x23, 0x00, 0x22, 0xF2, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x20, 0x00, 0x2B, ++0xE6, 0xD0, 0x01, 0xA9, 0x36, 0x23, 0xF2, 0x5C, 0x38, 0x3B, 0x13, 0x43, 0x0B, 0x70, 0x1F, 0x23, 0x4B, 0x70, 0x1D, 0x3B, ++0x8B, 0x70, 0xE8, 0xB2, 0x9E, 0xF7, 0xFE, 0xFA, 0x20, 0x00, 0x8E, 0xF7, 0xF1, 0xFE, 0x58, 0x21, 0x20, 0x00, 0x77, 0xF7, ++0x7D, 0xF9, 0x00, 0x20, 0xD0, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x05, 0x4B, 0x00, 0x20, 0x1A, 0x78, 0x00, 0x2A, ++0x04, 0xD0, 0x01, 0x30, 0xC0, 0xB2, 0x09, 0x33, 0x07, 0x28, 0xF7, 0xD1, 0x70, 0x47, 0xC0, 0x46, 0xA4, 0x9E, 0x16, 0x00, ++0x70, 0xB5, 0x80, 0x00, 0x28, 0x4B, 0xC2, 0x58, 0x28, 0x49, 0xD5, 0x23, 0x5B, 0x00, 0xC9, 0x5C, 0xCB, 0x00, 0x5B, 0x1A, ++0x5B, 0x00, 0x26, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x19, 0x88, 0xC9, 0x0B, 0x0B, 0xD0, 0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, ++0x19, 0x80, 0x20, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x0B, 0x40, 0x23, 0x54, 0x9E, 0x23, ++0xD3, 0x5C, 0x5B, 0x00, 0xAE, 0x21, 0x51, 0x5C, 0x5B, 0x18, 0xDB, 0xB2, 0x99, 0x00, 0xCB, 0x18, 0x5B, 0x00, 0x19, 0x49, ++0x5C, 0x18, 0x21, 0x88, 0x89, 0xB2, 0x00, 0x29, 0x19, 0xD1, 0x9C, 0x31, 0x50, 0x5C, 0x00, 0x28, 0x01, 0xD1, 0x01, 0x31, ++0x50, 0x5C, 0x14, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x78, 0x26, 0xB1, 0x43, 0xC0, 0x00, 0x01, 0x43, 0x29, 0x80, 0x96, 0x21, ++0x51, 0x5A, 0xC9, 0x00, 0x06, 0x20, 0x01, 0x43, 0x89, 0xB2, 0x0E, 0x48, 0x18, 0x18, 0x01, 0x80, 0x94, 0x21, 0x51, 0x5A, ++0x21, 0x80, 0x0C, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x19, 0x80, 0xAE, 0x21, 0x53, 0x5C, ++0x58, 0x42, 0x43, 0x41, 0x53, 0x54, 0x70, 0xBD, 0x38, 0xE6, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, ++0xCE, 0x69, 0x61, 0x40, 0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0x70, 0xB5, 0x35, 0x4B, ++0x1C, 0x68, 0x00, 0x2C, 0x14, 0xD0, 0xE3, 0x78, 0x9B, 0x00, 0x33, 0x4A, 0x9D, 0x58, 0xA0, 0x23, 0xEB, 0x5C, 0x02, 0x2B, ++0x0E, 0xD0, 0x31, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x05, 0xD0, 0x30, 0x4A, 0x11, 0x68, 0x80, 0x23, 0xDB, 0x03, 0x0B, 0x43, ++0x13, 0x60, 0xA0, 0x23, 0x02, 0x22, 0xEA, 0x54, 0x00, 0x20, 0x70, 0xBD, 0x94, 0x23, 0xE8, 0x5A, 0x00, 0x28, 0x07, 0xD0, ++0x63, 0x78, 0x00, 0x2B, 0x42, 0xD0, 0x01, 0x2B, 0x43, 0xD0, 0x94, 0x23, 0x00, 0x22, 0xEA, 0x52, 0xE2, 0x78, 0x62, 0x23, ++0x53, 0x43, 0x24, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x40, 0x05, 0x40, 0x0F, 0x84, 0xF7, 0x51, 0xFF, 0x1D, 0x4D, ++0xE3, 0x78, 0x9B, 0x00, 0x58, 0x59, 0x76, 0xF7, 0xCF, 0xFE, 0xE3, 0x78, 0x9B, 0x00, 0x00, 0x24, 0x5C, 0x51, 0x1C, 0x48, ++0xCB, 0xF7, 0x56, 0xFD, 0x1B, 0x48, 0x78, 0xF7, 0x53, 0xFE, 0x14, 0x4D, 0x2B, 0x68, 0xD8, 0x68, 0x76, 0xF7, 0xC0, 0xFE, ++0x2B, 0x68, 0xDC, 0x60, 0x98, 0x68, 0x00, 0x28, 0x05, 0xD0, 0x76, 0xF7, 0xB9, 0xFE, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x22, ++0x9A, 0x60, 0x0C, 0x4C, 0x20, 0x68, 0x76, 0xF7, 0xB1, 0xFE, 0x00, 0x23, 0x23, 0x60, 0x0B, 0x4B, 0x1B, 0x78, 0x00, 0x2B, ++0xBC, 0xD0, 0x0E, 0x4A, 0x13, 0x68, 0x0E, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x06, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xB3, 0xE7, ++0x80, 0xF7, 0x4A, 0xFE, 0xBB, 0xE7, 0x80, 0xF7, 0xFD, 0xFD, 0xB8, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, ++0xDC, 0xE5, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, 0xFE, 0x64, 0x61, 0x40, 0xFC, 0xE6, 0x10, 0x00, 0x0C, 0xD5, 0x10, 0x00, ++0xD0, 0x04, 0x60, 0x40, 0xFF, 0x7F, 0xFF, 0xFF, 0x70, 0xB5, 0x13, 0x4B, 0x1C, 0x68, 0xA5, 0x78, 0x00, 0x2D, 0x1D, 0xD1, ++0x23, 0x78, 0x03, 0x2B, 0x1C, 0xD0, 0x63, 0x78, 0x00, 0x2B, 0x08, 0xD0, 0x01, 0x2B, 0x0F, 0xD0, 0x0D, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x04, 0xE0, 0x0E, 0x22, 0x01, 0x00, 0xE0, 0x68, 0xCD, 0xF7, 0xF2, 0xFB, ++0x01, 0x23, 0xA3, 0x70, 0x28, 0x00, 0x70, 0xBD, 0x0E, 0x22, 0x01, 0x00, 0xE0, 0x68, 0xCD, 0xF7, 0xE9, 0xFB, 0xF5, 0xE7, ++0x0C, 0x25, 0xF5, 0xE7, 0x0C, 0x25, 0xF3, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xDE, 0x46, ++0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0xB0, 0x05, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x01, 0x93, 0x00, 0x23, ++0x08, 0x93, 0x09, 0x93, 0x06, 0x93, 0x06, 0xAA, 0x93, 0x80, 0x82, 0x00, 0xBB, 0x4B, 0xD3, 0x58, 0x00, 0x2B, 0x00, 0xD1, ++0x10, 0xE1, 0xAB, 0x00, 0xB8, 0x4A, 0x9F, 0x58, 0x21, 0x00, 0xB8, 0x48, 0x78, 0xF7, 0xCE, 0xFD, 0x00, 0x2C, 0x00, 0xD1, ++0x0D, 0xE1, 0x01, 0x2C, 0x00, 0xD1, 0x6D, 0xE2, 0xB4, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x00, 0x23, 0x00, 0x93, 0x98, 0x46, 0x99, 0x46, 0x02, 0x93, 0x00, 0x21, 0x00, 0x26, 0x01, 0x9B, 0x00, 0x2B, 0x63, 0xD0, ++0x62, 0x23, 0x6B, 0x43, 0xAC, 0x4A, 0x98, 0x18, 0x02, 0x88, 0x1F, 0x24, 0xA2, 0x43, 0x32, 0x43, 0x02, 0x80, 0xAA, 0x4A, ++0x9A, 0x18, 0x10, 0x88, 0xA9, 0x4E, 0x06, 0x40, 0x80, 0x20, 0x40, 0x00, 0x30, 0x43, 0x10, 0x80, 0x10, 0x88, 0x40, 0x04, ++0x40, 0x0C, 0x10, 0x80, 0x10, 0x88, 0xA5, 0x4E, 0x30, 0x40, 0x10, 0x80, 0xA4, 0x4A, 0x94, 0x46, 0x9C, 0x44, 0x62, 0x46, ++0x16, 0x88, 0xFF, 0x20, 0x86, 0x43, 0xA2, 0x4A, 0x93, 0x46, 0x2D, 0x22, 0x5C, 0x46, 0xA2, 0x5C, 0x32, 0x43, 0x64, 0x46, ++0x22, 0x80, 0x9F, 0x4A, 0x9E, 0x18, 0x00, 0x22, 0x94, 0x46, 0x32, 0x80, 0x9D, 0x4A, 0x93, 0x46, 0x9B, 0x44, 0x5A, 0x46, ++0x12, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x5C, 0x46, 0x22, 0x80, 0x9A, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x99, 0x4A, 0x9A, 0x18, ++0x61, 0x46, 0x11, 0x80, 0x98, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x98, 0x4A, 0x99, 0x18, 0x02, 0x22, 0xFF, 0x32, 0x0A, 0x80, ++0x32, 0x88, 0x40, 0x24, 0xA2, 0x43, 0x22, 0x43, 0x32, 0x80, 0x0A, 0x88, 0x82, 0x43, 0xFE, 0x38, 0x02, 0x43, 0x0A, 0x80, ++0x9E, 0x22, 0xBA, 0x5C, 0x14, 0x21, 0x4A, 0x43, 0x8F, 0x49, 0x8C, 0x46, 0x62, 0x44, 0x92, 0xB2, 0x8E, 0x49, 0x59, 0x18, ++0x0A, 0x80, 0x8E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x3F, 0x21, 0x0A, 0x40, 0x8C, 0x49, 0x0A, 0x43, 0x1A, 0x80, ++0x08, 0xAE, 0x31, 0x00, 0x06, 0xA8, 0xAF, 0xF7, 0x9D, 0xF9, 0x06, 0xAB, 0x5A, 0x78, 0x12, 0x02, 0x1B, 0x78, 0x13, 0x43, ++0x62, 0x27, 0x6F, 0x43, 0x85, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x06, 0xAB, 0xDA, 0x78, 0x12, 0x02, 0x9B, 0x78, 0x13, 0x43, ++0x82, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x06, 0xAB, 0x5A, 0x79, 0x12, 0x02, 0x1B, 0x79, 0x13, 0x43, 0x7F, 0x4A, 0xBA, 0x18, ++0x13, 0x80, 0x72, 0x78, 0x12, 0x02, 0x33, 0x78, 0x13, 0x43, 0x7D, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0xF2, 0x78, 0x12, 0x02, ++0xB3, 0x78, 0x13, 0x43, 0x7A, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x00, 0x22, 0x06, 0x2D, 0x01, 0xD8, 0x6A, 0x1C, 0xD2, 0xB2, ++0x08, 0xAB, 0x19, 0x79, 0x03, 0x23, 0x0B, 0x40, 0x92, 0x00, 0x13, 0x43, 0x6E, 0x4A, 0x13, 0x43, 0x6C, 0x4A, 0xBA, 0x18, ++0x13, 0x80, 0x72, 0x48, 0x03, 0x68, 0x72, 0x49, 0x0B, 0x40, 0x80, 0x22, 0x52, 0x01, 0x1A, 0x43, 0x02, 0x60, 0x5A, 0x4B, ++0xFE, 0x18, 0x33, 0x88, 0x02, 0x9A, 0x14, 0x03, 0x24, 0xB2, 0x0B, 0x40, 0x23, 0x43, 0x9B, 0xB2, 0x33, 0x80, 0x4B, 0x46, ++0x00, 0x2B, 0x00, 0xD1, 0xDE, 0xE1, 0x56, 0x4B, 0xFA, 0x18, 0x13, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x80, 0x21, 0x09, 0x02, ++0x0B, 0x43, 0x13, 0x80, 0x33, 0x88, 0x64, 0x4A, 0x13, 0x40, 0x00, 0x9A, 0xD2, 0x02, 0x13, 0x43, 0x9B, 0xB2, 0x33, 0x80, ++0x61, 0x49, 0x0B, 0x68, 0x61, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, 0x13, 0x43, 0x0B, 0x60, 0x4C, 0x4B, 0xFB, 0x18, ++0x00, 0x22, 0x1A, 0x80, 0x49, 0x4B, 0xFB, 0x18, 0x1A, 0x88, 0x08, 0x21, 0x8A, 0x43, 0x1A, 0x80, 0x30, 0x88, 0x31, 0x88, ++0x33, 0x88, 0x80, 0x0B, 0x01, 0x22, 0x10, 0x40, 0x80, 0x03, 0xC9, 0x0A, 0x0A, 0x40, 0xD2, 0x02, 0x10, 0x43, 0x05, 0x43, ++0x58, 0x05, 0x40, 0x0F, 0x00, 0x02, 0x05, 0x43, 0x25, 0x43, 0xAD, 0xB2, 0x35, 0x80, 0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x32, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0xE7, 0xE6, 0xB3, 0x78, 0x99, 0x46, 0xF3, 0x78, 0x98, 0x46, 0x33, 0x79, 0x00, 0x93, 0x72, 0x79, 0x02, 0x92, 0x00, 0x2B, ++0x10, 0xD1, 0x9D, 0x23, 0x00, 0x22, 0xFA, 0x54, 0x32, 0x78, 0x01, 0x3B, 0xFA, 0x54, 0xF2, 0x88, 0x96, 0x23, 0xFA, 0x52, ++0x73, 0x78, 0x07, 0x2B, 0x00, 0xD9, 0x3D, 0xE1, 0x9B, 0x00, 0x3E, 0x49, 0xCB, 0x58, 0x9F, 0x46, 0x31, 0x78, 0x9D, 0x23, ++0xF9, 0x54, 0x3C, 0x48, 0x78, 0xF7, 0x9C, 0xFC, 0x9C, 0x23, 0x00, 0x22, 0xFA, 0x54, 0xEA, 0xE7, 0x39, 0x4B, 0x1A, 0x68, ++0x39, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x30, 0x49, 0x11, 0x40, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x1A, 0x60, ++0x35, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x76, 0xD0, 0x31, 0x49, 0x0B, 0x68, 0x2D, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, ++0x13, 0x43, 0x0B, 0x60, 0x6D, 0xE0, 0x2D, 0x4B, 0x1A, 0x68, 0x2D, 0x49, 0x11, 0x40, 0x80, 0x22, 0x92, 0x01, 0x0A, 0x43, ++0x1A, 0x60, 0x1A, 0x68, 0x22, 0x49, 0x11, 0x40, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x27, 0x4B, 0x1B, 0x78, ++0x00, 0x2B, 0x5A, 0xD0, 0x23, 0x49, 0x0B, 0x68, 0x1F, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, 0x13, 0x43, 0x0B, 0x60, ++0x51, 0xE0, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0x18, 0xD5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF8, 0x64, 0x61, 0x40, ++0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0x0C, 0x65, 0x61, 0x40, 0x60, 0x92, 0x16, 0x00, ++0x0E, 0x65, 0x61, 0x40, 0x56, 0x65, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, ++0x1E, 0x65, 0x61, 0x40, 0xC8, 0x69, 0x00, 0x00, 0x12, 0x65, 0x61, 0x40, 0x0A, 0x65, 0x61, 0x40, 0x40, 0xFF, 0x00, 0x00, ++0x00, 0x65, 0x61, 0x40, 0x02, 0x65, 0x61, 0x40, 0x04, 0x65, 0x61, 0x40, 0x06, 0x65, 0x61, 0x40, 0x08, 0x65, 0x61, 0x40, ++0x00, 0x04, 0x60, 0x40, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x28, 0x04, 0x60, 0x40, 0xFF, 0x7F, 0xFF, 0xFF, ++0x48, 0xD5, 0x10, 0x00, 0x30, 0xD5, 0x10, 0x00, 0xD0, 0x04, 0x60, 0x40, 0xFF, 0xDF, 0xFF, 0xFF, 0xDC, 0xE5, 0x10, 0x00, ++0x94, 0x23, 0xF8, 0x5A, 0x8E, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xF0, 0x21, 0x74, 0xF7, 0x96, 0xFB, 0x8C, 0x4A, 0x13, 0x68, ++0x8C, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x9E, 0x23, 0xFA, 0x5C, 0x52, 0x00, 0x10, 0x33, 0xFB, 0x5C, 0xD2, 0x18, 0xD2, 0xB2, ++0x62, 0x23, 0x6B, 0x43, 0x87, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x03, 0x93, 0x02, 0x20, 0x07, 0x23, 0x9A, 0x46, 0x04, 0x95, ++0x05, 0x96, 0x91, 0x00, 0x89, 0x18, 0x49, 0x00, 0x82, 0x4B, 0xCC, 0x18, 0x23, 0x88, 0x78, 0x25, 0xAB, 0x43, 0x70, 0x3D, ++0x2B, 0x43, 0x9B, 0xB2, 0x23, 0x80, 0x03, 0x9B, 0x1B, 0x88, 0x25, 0x88, 0xAB, 0x46, 0x1B, 0x0A, 0x55, 0x46, 0x2B, 0x40, ++0x5D, 0x46, 0x56, 0x46, 0xB5, 0x43, 0x2B, 0x43, 0x23, 0x80, 0x79, 0x4B, 0x9C, 0x46, 0x8C, 0x44, 0x63, 0x46, 0x1B, 0x88, ++0x77, 0x4C, 0x23, 0x40, 0x64, 0x46, 0x23, 0x80, 0x76, 0x4B, 0xCB, 0x18, 0x00, 0x24, 0x1C, 0x80, 0x75, 0x4B, 0x9C, 0x46, ++0x61, 0x44, 0x9E, 0x23, 0xFB, 0x5C, 0x5B, 0x00, 0x01, 0x34, 0x54, 0x40, 0xE4, 0xB2, 0xA4, 0x46, 0x63, 0x44, 0x9C, 0x00, ++0xA4, 0x46, 0x63, 0x44, 0x5B, 0x00, 0x6F, 0x4C, 0xA4, 0x46, 0x63, 0x44, 0x6E, 0x4C, 0x23, 0x43, 0x9B, 0xB2, 0x0B, 0x80, ++0x0B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x0B, 0x80, 0x53, 0x42, 0x5A, 0x41, 0xD2, 0xB2, 0x01, 0x38, 0xC0, 0xB2, 0x00, 0x28, ++0xB9, 0xD1, 0x04, 0x9D, 0x05, 0x9E, 0x31, 0x00, 0x08, 0x31, 0x06, 0x22, 0x06, 0xA8, 0xCD, 0xF7, 0xA5, 0xF9, 0x00, 0x21, ++0x02, 0x26, 0xF2, 0xE5, 0x94, 0x23, 0xF8, 0x5A, 0x56, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xAA, 0x21, 0x74, 0xF7, 0x26, 0xFB, ++0x54, 0x4A, 0x13, 0x68, 0x54, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x8E, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x4F, 0x4B, 0x9C, 0x46, ++0x60, 0x44, 0xFF, 0x21, 0x74, 0xF7, 0x18, 0xFB, 0x4D, 0x4A, 0x13, 0x68, 0x4D, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x80, 0xE7, ++0x94, 0x23, 0xF8, 0x5A, 0x48, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x74, 0xF7, 0x0A, 0xFB, 0x46, 0x4A, 0x13, 0x68, ++0x46, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x72, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x41, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x0F, 0x21, ++0x74, 0xF7, 0xFC, 0xFA, 0x3F, 0x4A, 0x13, 0x68, 0x3F, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x64, 0xE7, 0x94, 0x23, 0xF8, 0x5A, ++0x3A, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x55, 0x21, 0x74, 0xF7, 0xEE, 0xFA, 0x38, 0x4A, 0x13, 0x68, 0x38, 0x49, 0x0B, 0x40, ++0x13, 0x60, 0x56, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x33, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x74, 0xF7, 0xE0, 0xFA, ++0x31, 0x4A, 0x13, 0x68, 0x31, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x48, 0xE7, 0xB3, 0x78, 0x98, 0x46, 0xF3, 0x78, 0x00, 0x93, ++0xB4, 0x79, 0xF1, 0x1D, 0x06, 0x22, 0x06, 0xA8, 0xCD, 0xF7, 0x44, 0xF9, 0x00, 0x22, 0x33, 0x4B, 0x99, 0x46, 0xD5, 0x23, ++0x5B, 0x00, 0x9C, 0x46, 0x03, 0x26, 0x17, 0x3B, 0xFF, 0x3B, 0x9B, 0x46, 0x0A, 0xE0, 0x2F, 0x49, 0x8A, 0x46, 0x53, 0x44, ++0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x19, 0x80, 0x01, 0x32, 0xD2, 0xB2, 0x04, 0x2A, 0x11, 0xD0, 0x4B, 0x46, 0x61, 0x46, ++0x5B, 0x5C, 0xD3, 0x18, 0x33, 0x40, 0xD9, 0x00, 0xCB, 0x1A, 0x5B, 0x00, 0x26, 0x49, 0x58, 0x18, 0x01, 0x88, 0x89, 0xB2, ++0x00, 0x29, 0xE6, 0xD1, 0x59, 0x46, 0x79, 0x5A, 0x01, 0x80, 0xE2, 0xE7, 0x02, 0x94, 0x00, 0x23, 0x99, 0x46, 0x21, 0x49, ++0x03, 0x26, 0x66, 0xE5, 0x20, 0x4B, 0xFA, 0x18, 0x13, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x13, 0x80, 0x43, 0x46, 0xDB, 0x07, ++0x0F, 0xD4, 0x11, 0x88, 0x43, 0x46, 0x5B, 0x08, 0x1B, 0x02, 0x1B, 0x48, 0x01, 0x40, 0x0B, 0x43, 0x13, 0x80, 0x43, 0x46, ++0x5B, 0x08, 0x28, 0x33, 0x19, 0x00, 0x18, 0x48, 0x78, 0xF7, 0x0A, 0xFB, 0x10, 0xE6, 0x10, 0x88, 0x43, 0x46, 0x5B, 0x08, ++0x28, 0x33, 0x1B, 0x02, 0x12, 0x49, 0x01, 0x40, 0x0B, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0xEC, 0xE7, 0x00, 0x00, 0x61, 0x40, ++0xD0, 0x04, 0x60, 0x40, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0x64, 0x61, 0x40, 0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, ++0x07, 0xE0, 0xFF, 0xFF, 0xCE, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, ++0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, 0x9A, 0x69, 0x61, 0x40, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x65, 0x61, 0x40, ++0xFF, 0x80, 0xFF, 0xFF, 0x3C, 0xD5, 0x10, 0x00, 0x10, 0xB5, 0x07, 0x4B, 0x1C, 0x68, 0xA3, 0x78, 0x00, 0x2B, 0x00, 0xD1, ++0x10, 0xBD, 0x00, 0x23, 0x0A, 0x00, 0xE1, 0x68, 0xFF, 0xF7, 0xE2, 0xFC, 0x00, 0x23, 0xA3, 0x70, 0xF6, 0xE7, 0xC0, 0x46, ++0xD8, 0xE5, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x05, 0x00, 0x82, 0x00, 0x52, 0x4B, 0xD4, 0x58, 0x00, 0x2C, ++0x00, 0xD1, 0x98, 0xE0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, 0x4E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, 0xDB, 0xB2, 0xA3, 0x54, 0x09, 0x3A, 0xA2, 0x5C, 0x02, 0x3A, ++0x01, 0x2A, 0x01, 0xD8, 0x00, 0x2B, 0x14, 0xD0, 0x9F, 0xF7, 0xD2, 0xFD, 0x06, 0x00, 0x01, 0x00, 0x28, 0x00, 0xFF, 0xF7, ++0xA9, 0xFB, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x68, 0xE0, 0x3F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x01, 0x21, 0x20, 0x00, 0xCA, 0xF7, 0xEF, 0xFD, 0xA0, 0x23, ++0x02, 0x22, 0xE2, 0x54, 0xFF, 0xF7, 0xF4, 0xFB, 0x37, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, ++0x5B, 0x00, 0x35, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0xD2, 0x0B, 0xE7, 0xD0, 0x33, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, ++0xD2, 0x0A, 0xAA, 0x42, 0x07, 0xD0, 0x19, 0x88, 0xC9, 0x0A, 0x2C, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x28, 0x00, ++0xA0, 0x47, 0x2A, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x22, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x27, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x19, 0x40, 0x21, 0x54, ++0x23, 0x4B, 0x1A, 0x68, 0xCB, 0x00, 0x5B, 0x1A, 0x5B, 0x00, 0x22, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x52, 0x04, 0x52, 0x0C, ++0x93, 0x42, 0x05, 0xD0, 0x19, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x18, 0x4E, 0x00, 0x24, ++0xD5, 0x23, 0x5B, 0x00, 0x98, 0x46, 0x14, 0x4F, 0x03, 0xE0, 0x01, 0x34, 0x0E, 0x36, 0x04, 0x2C, 0xA8, 0xD0, 0x33, 0x88, ++0xDB, 0x0B, 0xF8, 0xD0, 0x10, 0x4B, 0x42, 0x46, 0x98, 0x5C, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xFD, 0x6E, 0xA8, 0x47, ++0xEF, 0xE7, 0x01, 0x21, 0x20, 0x00, 0xCA, 0xF7, 0x8F, 0xFD, 0x02, 0x36, 0x66, 0x60, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, ++0x4F, 0xFF, 0x20, 0x00, 0xF4, 0xF7, 0xA6, 0xFA, 0x8E, 0xE7, 0x04, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, ++0xA0, 0x47, 0x87, 0xE7, 0x38, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, ++0x92, 0x69, 0x61, 0x40, 0x2C, 0x04, 0x60, 0x40, 0x90, 0x69, 0x00, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, ++0x14, 0x00, 0xCF, 0xB2, 0x06, 0x2F, 0x07, 0xD9, 0xFF, 0x20, 0x08, 0x40, 0x0B, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x21, 0x00, 0xB0, 0x47, 0x00, 0x2C, 0x09, 0xD0, 0xFF, 0x20, 0x28, 0x40, 0x06, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x21, 0x00, 0xA8, 0x47, 0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x99, 0x38, 0x00, 0xFF, 0xF7, 0x28, 0xFF, 0xF8, 0xE7, 0xC0, 0x46, ++0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x96, 0xB0, 0x2F, 0x4B, 0x1B, 0x68, 0xD9, 0x68, 0xEF, 0xF3, ++0x10, 0x83, 0xDB, 0x07, 0x51, 0xD4, 0x72, 0xB6, 0x10, 0x31, 0x24, 0x22, 0x0D, 0xA8, 0xCC, 0xF7, 0xCF, 0xFF, 0x62, 0xB6, ++0x0D, 0x9C, 0x00, 0x26, 0x00, 0x2C, 0x07, 0xD0, 0x0E, 0x9B, 0xE3, 0x1A, 0x64, 0x20, 0x58, 0x43, 0x21, 0x00, 0xCC, 0xF7, ++0x75, 0xFB, 0x06, 0x00, 0x13, 0x9D, 0x00, 0x20, 0x00, 0x2D, 0x05, 0xD0, 0x21, 0x48, 0x14, 0x9B, 0x58, 0x43, 0x29, 0x00, ++0xCC, 0xF7, 0x6A, 0xFB, 0x11, 0x9A, 0x12, 0x9F, 0x15, 0x99, 0x13, 0x00, 0x3B, 0x43, 0x0B, 0x43, 0x1B, 0xD0, 0x0F, 0x9B, ++0x98, 0x46, 0x0E, 0x9B, 0x9C, 0x46, 0x00, 0x23, 0x09, 0x93, 0x08, 0x90, 0x07, 0x93, 0x06, 0x96, 0x14, 0x9B, 0x0B, 0x93, ++0x05, 0x93, 0x04, 0x95, 0x03, 0x91, 0x02, 0x97, 0x01, 0x92, 0x10, 0x9B, 0x00, 0x93, 0x43, 0x46, 0x22, 0x00, 0x61, 0x46, ++0x11, 0x48, 0x78, 0xF7, 0xA5, 0xF9, 0x16, 0xB0, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0F, 0x9B, 0x0E, 0x99, 0x00, 0x22, ++0x06, 0x92, 0x05, 0x90, 0x04, 0x92, 0x03, 0x96, 0x14, 0x9A, 0x0B, 0x92, 0x02, 0x92, 0x01, 0x95, 0x10, 0x9A, 0x00, 0x92, ++0x22, 0x00, 0x08, 0x48, 0x78, 0xF7, 0x90, 0xF9, 0xE9, 0xE7, 0x10, 0x31, 0x24, 0x22, 0x0D, 0xA8, 0xCC, 0xF7, 0x7E, 0xFF, ++0xAE, 0xE7, 0xC0, 0x46, 0xD8, 0xE5, 0x10, 0x00, 0x10, 0x27, 0x00, 0x00, 0x68, 0xD5, 0x10, 0x00, 0xC8, 0xD5, 0x10, 0x00, ++0x70, 0x47, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x05, 0x00, 0x0F, 0x00, 0x16, 0x00, 0x1C, 0x00, 0x4B, 0x4B, ++0x1B, 0x68, 0x00, 0x2B, 0x05, 0xD0, 0x4A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x21, ++0x10, 0x20, 0x76, 0xF7, 0x37, 0xF9, 0x44, 0x4B, 0x18, 0x60, 0x00, 0x28, 0x10, 0xD0, 0x42, 0x4B, 0x18, 0x68, 0x10, 0x22, ++0x00, 0x21, 0x74, 0xF7, 0xDF, 0xF8, 0x00, 0x2D, 0x0E, 0xD0, 0x01, 0x2D, 0x2C, 0xD0, 0x3E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x1B, 0xE0, 0x3A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x98, 0x47, 0xE8, 0xE7, ++0x36, 0x4C, 0x25, 0x68, 0x00, 0x21, 0x0E, 0x20, 0x76, 0xF7, 0x16, 0xF9, 0xE8, 0x60, 0x23, 0x68, 0xDB, 0x68, 0x00, 0x2B, ++0x0D, 0xD0, 0x31, 0x4C, 0x23, 0x68, 0xD8, 0x68, 0x0E, 0x22, 0x00, 0x21, 0x74, 0xF7, 0xBC, 0xF8, 0x23, 0x68, 0x00, 0x22, ++0x5A, 0x70, 0xDE, 0x70, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0xEA, 0xE7, 0x26, 0x4D, 0x2B, 0x68, 0x98, 0x46, 0x00, 0x21, 0x38, 0x20, 0x76, 0xF7, 0xF5, 0xF8, 0x43, 0x46, ++0xD8, 0x60, 0x2B, 0x68, 0xDB, 0x68, 0x00, 0x2B, 0x31, 0xD0, 0x20, 0x4D, 0x2B, 0x68, 0xD8, 0x68, 0x38, 0x22, 0x00, 0x21, ++0x74, 0xF7, 0x9A, 0xF8, 0x2B, 0x68, 0x98, 0x46, 0x00, 0x21, 0x28, 0x20, 0x76, 0xF7, 0xE2, 0xF8, 0x43, 0x46, 0x98, 0x60, ++0x2B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0x25, 0xD0, 0x16, 0x4D, 0x2B, 0x68, 0x98, 0x68, 0x28, 0x22, 0x00, 0x21, 0x74, 0xF7, ++0x87, 0xF8, 0x2B, 0x68, 0xD8, 0x68, 0x0E, 0x22, 0x39, 0x00, 0xCC, 0xF7, 0xF5, 0xFE, 0x2B, 0x68, 0x01, 0x22, 0x5A, 0x70, ++0xC8, 0x22, 0x52, 0x01, 0x5A, 0x60, 0xDE, 0x70, 0x0E, 0x48, 0x0F, 0x4A, 0x82, 0x60, 0x5B, 0x68, 0xE4, 0x18, 0x24, 0x01, ++0x24, 0x09, 0x44, 0x60, 0xCA, 0xF7, 0xA0, 0xFF, 0xB6, 0xE7, 0x08, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, ++0x98, 0x47, 0xC6, 0xE7, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD2, 0xE7, 0xC0, 0x46, ++0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xFC, 0xE6, 0x10, 0x00, 0xD5, 0x01, 0x10, 0x00, 0xF8, 0xB5, 0x04, 0x00, ++0x4E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0xF7, 0xB8, 0xFA, 0x05, 0x00, 0x28, 0x00, 0xF8, 0xBD, 0x4B, 0x48, ++0x78, 0xF7, 0xCA, 0xF8, 0x4A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x07, 0xD0, 0x49, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0xEE, 0xE7, 0x00, 0x21, 0xF8, 0x20, 0x76, 0xF7, 0x88, 0xF8, 0x42, 0x4B, 0x18, 0x60, ++0x00, 0x28, 0x75, 0xD0, 0x9F, 0xF7, 0xE0, 0xFB, 0x07, 0x00, 0x84, 0xF7, 0x81, 0xF9, 0x40, 0x4A, 0x13, 0x88, 0x40, 0x49, ++0x0B, 0x40, 0x00, 0x02, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x3A, 0x4B, 0x1E, 0x68, 0xF8, 0x22, 0x00, 0x21, 0x30, 0x00, ++0x74, 0xF7, 0x22, 0xF8, 0x00, 0x23, 0x73, 0x62, 0x39, 0x4A, 0xF2, 0x61, 0x39, 0x4A, 0x32, 0x62, 0x03, 0x22, 0x32, 0x76, ++0x38, 0x4A, 0x12, 0x78, 0xB2, 0x75, 0x38, 0x4A, 0x32, 0x61, 0x05, 0x22, 0xF2, 0x75, 0x99, 0x32, 0xB3, 0x54, 0x01, 0x32, ++0xB3, 0x54, 0x02, 0x32, 0xB3, 0x54, 0x03, 0x32, 0x28, 0x21, 0xB1, 0x52, 0x1C, 0x3A, 0xB3, 0x52, 0x80, 0xF7, 0x72, 0xF8, ++0x05, 0x1E, 0x05, 0xD1, 0x28, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x94, 0x23, 0xF5, 0x52, ++0x93, 0x3B, 0x00, 0x22, 0x21, 0x00, 0x00, 0x20, 0xFF, 0xF7, 0x8A, 0xFA, 0x28, 0x4A, 0x13, 0x88, 0x1F, 0x21, 0x0B, 0x40, ++0x13, 0x80, 0x77, 0x60, 0x00, 0x23, 0x82, 0x22, 0xB3, 0x52, 0xB3, 0x60, 0x00, 0x22, 0xA6, 0x33, 0xF2, 0x54, 0x20, 0x3B, ++0xFA, 0x22, 0xD2, 0x01, 0xF2, 0x52, 0x37, 0x67, 0x20, 0x4B, 0xB3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0xFB, 0x18, 0x1B, 0x01, ++0x1B, 0x09, 0xF3, 0x60, 0x30, 0x00, 0xCA, 0xF7, 0x15, 0xFA, 0x05, 0x1E, 0x07, 0xD0, 0x12, 0x4B, 0x9B, 0x6E, 0x00, 0x22, ++0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0x7F, 0xE7, 0xA0, 0x23, 0x00, 0x22, 0xF2, 0x54, 0x01, 0x32, 0x00, 0x21, ++0x00, 0x20, 0x9F, 0xF7, 0xF3, 0xF8, 0x3B, 0x00, 0x00, 0x22, 0x21, 0x00, 0x00, 0x20, 0xFF, 0xF7, 0xC3, 0xFE, 0x70, 0xE7, ++0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0x68, 0xE7, 0xD8, 0xE5, 0x10, 0x00, ++0x10, 0xD6, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, ++0xF1, 0x02, 0x10, 0x00, 0xD1, 0x01, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x6A, 0x04, 0x00, 0x00, 0xF8, 0x64, 0x61, 0x40, ++0x00, 0x80, 0xFF, 0xFF, 0x10, 0xB5, 0x00, 0x29, 0x12, 0xD1, 0x03, 0x78, 0xFF, 0x2B, 0x0A, 0xD1, 0x43, 0x78, 0xC1, 0x2B, ++0x2F, 0xD1, 0x83, 0x78, 0xFB, 0x2B, 0x2E, 0xD1, 0xC1, 0x78, 0xE8, 0x39, 0x4B, 0x42, 0x59, 0x41, 0x03, 0x31, 0x04, 0x39, ++0x48, 0x42, 0x48, 0x41, 0xC0, 0xB2, 0x10, 0xBD, 0x03, 0x29, 0x0C, 0xD0, 0x12, 0x4B, 0x5C, 0x5C, 0x00, 0x23, 0xD9, 0xB2, ++0xC2, 0x5C, 0xA2, 0x42, 0xF1, 0xD1, 0x01, 0x31, 0xC9, 0xB2, 0x01, 0x33, 0x04, 0x2B, 0xF6, 0xD1, 0xEB, 0xE7, 0x03, 0x78, ++0xFF, 0x2B, 0x0A, 0xD1, 0x43, 0x78, 0xC1, 0x2B, 0x09, 0xD1, 0x83, 0x78, 0xFB, 0x2B, 0x08, 0xD1, 0xC3, 0x78, 0xE8, 0x2B, ++0xDF, 0xD1, 0x04, 0x21, 0xDD, 0xE7, 0x00, 0x21, 0xDB, 0xE7, 0x01, 0x21, 0xD9, 0xE7, 0x02, 0x21, 0xD7, 0xE7, 0x01, 0x21, ++0xD5, 0xE7, 0x02, 0x21, 0xD3, 0xE7, 0xC0, 0x46, 0x1C, 0xE0, 0x10, 0x00, 0xF8, 0xB5, 0x23, 0x4B, 0x1B, 0x68, 0x00, 0x2B, ++0x3A, 0xD0, 0xDA, 0x68, 0x53, 0x78, 0x00, 0x2B, 0x10, 0xD1, 0x95, 0x88, 0x00, 0x2D, 0x0C, 0xD0, 0x1E, 0x4F, 0x1F, 0x4E, ++0xF1, 0x5C, 0xC4, 0x5C, 0x61, 0x40, 0x79, 0x5C, 0xD4, 0x6A, 0xA4, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xAB, 0x42, ++0xF4, 0xD3, 0xF8, 0xBD, 0x03, 0x2B, 0x11, 0xD0, 0x18, 0x49, 0xCD, 0x5C, 0x94, 0x88, 0x00, 0x2C, 0xF7, 0xD0, 0x00, 0x23, ++0x13, 0x4E, 0xC1, 0x5C, 0x69, 0x40, 0x71, 0x5C, 0xD7, 0x6A, 0xBC, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xA3, 0x42, ++0xF5, 0xD3, 0xEA, 0xE7, 0x95, 0x88, 0x00, 0x2D, 0xE7, 0xD0, 0x00, 0x23, 0x0B, 0x4F, 0x0E, 0x4E, 0xF1, 0x5C, 0xC4, 0x5C, ++0x61, 0x40, 0x79, 0x5C, 0xD4, 0x6A, 0xA4, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xAB, 0x42, 0xF4, 0xD3, 0xD8, 0xE7, ++0x08, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD1, 0xE7, 0xC0, 0x46, 0xD8, 0xE5, 0x10, 0x00, ++0xBC, 0xDE, 0x10, 0x00, 0xBC, 0xDA, 0x10, 0x00, 0x1C, 0xE0, 0x10, 0x00, 0xBC, 0xD6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x06, 0x00, 0x74, 0x4B, 0x1B, 0x68, 0xDD, 0x68, ++0x54, 0x1E, 0xE4, 0xB2, 0x00, 0x2A, 0x00, 0xD1, 0xDA, 0xE0, 0x71, 0x4F, 0xAB, 0xE0, 0x04, 0x21, 0x08, 0x00, 0x10, 0x40, ++0x11, 0x42, 0x2F, 0xD0, 0xE9, 0x69, 0x01, 0x31, 0xE9, 0x61, 0xDB, 0x04, 0x9B, 0x0D, 0x99, 0x46, 0xB8, 0x23, 0x13, 0x42, ++0x5B, 0xD1, 0xAB, 0x88, 0xDB, 0x00, 0xAA, 0x6A, 0x94, 0x46, 0x63, 0x44, 0xAB, 0x62, 0xD5, 0x23, 0x5B, 0x00, 0x65, 0x4A, ++0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x63, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x83, 0xB2, 0x9A, 0x46, ++0x00, 0x2B, 0x06, 0xD1, 0x60, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x4B, 0x46, ++0x00, 0x2B, 0x53, 0xD0, 0x43, 0x46, 0x59, 0x06, 0x09, 0x0F, 0x5B, 0x48, 0x50, 0x44, 0xFF, 0xF7, 0x67, 0xFF, 0x4B, 0xE0, ++0x69, 0x69, 0x01, 0x31, 0x69, 0x61, 0xDB, 0x04, 0x9B, 0x0D, 0x99, 0x46, 0xB8, 0x23, 0x13, 0x42, 0x00, 0xD0, 0x95, 0xE0, ++0x00, 0x28, 0xCC, 0xD1, 0xAB, 0x88, 0x4B, 0x45, 0x2B, 0xD0, 0x6B, 0x6A, 0x01, 0x33, 0x6B, 0x62, 0x4C, 0x4A, 0xD5, 0x23, ++0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x4A, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x83, 0xB2, ++0x98, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x47, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x4B, 0x46, ++0x00, 0x2B, 0x21, 0xD0, 0x69, 0x78, 0x43, 0x48, 0x40, 0x44, 0xFF, 0xF7, 0xF7, 0xFE, 0x00, 0x28, 0x1A, 0xD1, 0x2B, 0x6B, ++0x01, 0x33, 0x2B, 0x63, 0x16, 0xE0, 0x2B, 0x6A, 0x01, 0x33, 0x2B, 0x62, 0x00, 0x28, 0x11, 0xD1, 0xD0, 0xE7, 0xDB, 0x00, ++0xAA, 0x6A, 0x94, 0x46, 0x63, 0x44, 0xAB, 0x62, 0xD0, 0xE7, 0x35, 0x23, 0xEB, 0x5C, 0x01, 0x33, 0xDB, 0xB2, 0x64, 0x2B, ++0x54, 0xD8, 0x35, 0x22, 0xAB, 0x54, 0x34, 0x23, 0x00, 0x22, 0xEA, 0x54, 0x2F, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, ++0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x2D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x05, 0xD1, ++0x2A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x25, 0x48, 0xD5, 0x21, 0x49, 0x00, 0x42, 0x5C, ++0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x26, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, ++0x42, 0x5C, 0x01, 0x32, 0x03, 0x23, 0x13, 0x40, 0x43, 0x54, 0x01, 0x3C, 0xE4, 0xB2, 0xFF, 0x2C, 0x2C, 0xD0, 0x30, 0x00, ++0x9E, 0xF7, 0x5A, 0xFF, 0x00, 0x28, 0x27, 0xD0, 0xD5, 0x23, 0x5B, 0x00, 0xFA, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, ++0x19, 0x4A, 0x9A, 0x18, 0x10, 0x88, 0x82, 0xB2, 0x18, 0x49, 0x59, 0x18, 0x09, 0x88, 0x89, 0xB2, 0x88, 0x46, 0x17, 0x49, ++0x8C, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9B, 0xB2, 0xC1, 0x07, 0xAE, 0xD4, 0x29, 0x69, 0x01, 0x31, 0x29, 0x61, 0x91, 0x07, ++0x00, 0xD4, 0x32, 0xE7, 0xAB, 0x69, 0x01, 0x33, 0xAB, 0x61, 0xAF, 0xE7, 0x35, 0x23, 0x64, 0x22, 0xEA, 0x54, 0xA8, 0xE7, ++0x2B, 0x6A, 0x01, 0x33, 0x2B, 0x62, 0x67, 0xE7, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, ++0xD8, 0xE5, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x9A, 0x69, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, ++0x90, 0x69, 0x61, 0x40, 0x92, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, 0x96, 0x69, 0x61, 0x40, 0xF0, 0xB5, 0xD6, 0x46, ++0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x89, 0x46, 0x82, 0x00, 0x41, 0x4B, 0xD5, 0x58, 0xA6, 0x23, 0xEF, 0x5C, 0x2E, 0x6D, ++0x44, 0x3B, 0x58, 0x43, 0x3E, 0x4B, 0xC3, 0x18, 0x1B, 0x88, 0x3E, 0x4A, 0x82, 0x18, 0x14, 0x88, 0x1B, 0x04, 0x1C, 0x43, ++0xA2, 0x46, 0x3C, 0x4B, 0xC3, 0x18, 0x1B, 0x88, 0x9B, 0x05, 0x9B, 0x0D, 0x98, 0x46, 0x3A, 0x4B, 0xC3, 0x18, 0x1C, 0x88, ++0x39, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x01, 0x88, 0x24, 0x04, 0x0C, 0x19, 0x37, 0x4B, 0x9E, 0x42, 0x1C, 0xD8, 0x53, 0x46, ++0x4A, 0x46, 0x9B, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x80, 0x22, 0x12, 0x05, 0x91, 0x42, 0x40, 0xD9, 0x4B, 0x46, 0x52, 0x46, ++0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0x3D, 0xD0, 0x00, 0x2B, 0x07, 0xDB, ++0x89, 0x08, 0x00, 0x29, 0x04, 0xDD, 0x89, 0x00, 0x49, 0x44, 0x09, 0x01, 0x0B, 0x09, 0x99, 0x46, 0x53, 0x46, 0xE1, 0x1A, ++0x49, 0x44, 0x09, 0x01, 0x09, 0x09, 0xF4, 0x23, 0x5B, 0x00, 0x42, 0x46, 0x9B, 0x1A, 0x32, 0xD4, 0xA9, 0x67, 0x82, 0x22, ++0xAB, 0x52, 0x4A, 0x42, 0x03, 0x20, 0x10, 0x40, 0xA6, 0x22, 0xA8, 0x54, 0x72, 0x3A, 0x2A, 0x65, 0xAB, 0x60, 0x34, 0x2E, ++0x09, 0xD9, 0xEA, 0x7D, 0x00, 0x2A, 0x06, 0xD0, 0xC8, 0x22, 0x52, 0x00, 0x9A, 0x42, 0x92, 0x41, 0x52, 0x42, 0x05, 0x32, ++0xEA, 0x75, 0x69, 0x67, 0x84, 0x22, 0xAB, 0x52, 0xC0, 0x1B, 0x43, 0x1E, 0x98, 0x41, 0xC0, 0xB2, 0x1C, 0xBC, 0x90, 0x46, ++0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0x1B, 0x01, 0x1B, 0x09, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0xC4, 0xD0, 0xC1, 0xE7, ++0x00, 0x2B, 0xC1, 0xDA, 0x0D, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xC2, 0xE7, 0x0B, 0x4B, ++0x9B, 0x1A, 0x01, 0x31, 0x09, 0x01, 0x09, 0x09, 0xC6, 0xE7, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0x4C, 0x65, 0x61, 0x40, ++0x4A, 0x65, 0x61, 0x40, 0x4E, 0x65, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, 0xE1, 0x04, 0x00, 0x00, ++0x28, 0x19, 0x16, 0x00, 0x59, 0x04, 0x00, 0x00, 0xF8, 0xB5, 0x80, 0x00, 0x25, 0x4B, 0xC5, 0x58, 0xA6, 0x23, 0xEE, 0x5C, ++0x6C, 0x6F, 0xEB, 0x6E, 0xC8, 0x1A, 0x00, 0x01, 0x00, 0x09, 0x22, 0x49, 0x48, 0x43, 0x22, 0x49, 0xCB, 0xF7, 0x84, 0xFF, ++0x1A, 0x30, 0x40, 0x00, 0x02, 0x00, 0x34, 0x3A, 0x52, 0x08, 0x84, 0x23, 0xEB, 0x5A, 0x9B, 0x1A, 0x19, 0xB2, 0x1B, 0x04, ++0x27, 0xD5, 0x00, 0x23, 0x1B, 0x4A, 0x8A, 0x18, 0x11, 0xB2, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0x1F, 0x00, 0x01, 0x33, ++0xDB, 0xB2, 0x12, 0x04, 0xF4, 0xD4, 0xAC, 0x67, 0x82, 0x22, 0xA9, 0x52, 0x64, 0x42, 0x7F, 0x3A, 0x14, 0x40, 0xA3, 0x32, ++0xAC, 0x54, 0x28, 0x65, 0xA9, 0x60, 0x00, 0x2B, 0x0A, 0xD0, 0xEB, 0x7D, 0x00, 0x2B, 0x07, 0xD0, 0xC8, 0x23, 0x5B, 0x00, ++0x8B, 0x42, 0x9B, 0x41, 0x5B, 0x42, 0x06, 0x37, 0xDF, 0x19, 0xEF, 0x75, 0x34, 0x1B, 0x66, 0x1E, 0xB4, 0x41, 0xE0, 0xB2, ++0xF8, 0xBD, 0xAC, 0x67, 0x82, 0x23, 0xE9, 0x52, 0x64, 0x42, 0x7F, 0x3B, 0x1C, 0x40, 0xA3, 0x33, 0xEC, 0x54, 0x28, 0x65, ++0xA9, 0x60, 0xEF, 0xE7, 0x38, 0xE6, 0x10, 0x00, 0xA8, 0x61, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x71, 0x02, 0x00, 0x00, ++0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x8A, 0xB0, 0x0E, 0x00, 0x8A, 0x00, 0x52, 0x4B, 0xD5, 0x58, 0x00, 0x2D, 0x00, 0xD1, ++0x9B, 0xE0, 0xA6, 0x23, 0x98, 0x46, 0xEB, 0x5C, 0x01, 0x33, 0x03, 0x24, 0x23, 0x40, 0x1F, 0x00, 0x9F, 0xF7, 0xB0, 0xF8, ++0x00, 0x90, 0x03, 0x00, 0xA3, 0x43, 0x3B, 0x43, 0x42, 0x46, 0xAA, 0x5C, 0xD2, 0x1A, 0x14, 0x40, 0x04, 0x3B, 0xE4, 0x18, ++0x24, 0x01, 0x24, 0x09, 0x23, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x22, 0x12, 0x05, 0x93, 0x42, 0x02, 0xD9, 0x03, 0x1B, ++0x1B, 0x01, 0x59, 0xD1, 0x00, 0x23, 0x01, 0x93, 0x01, 0xA9, 0x68, 0x46, 0x9F, 0xF7, 0x9C, 0xF8, 0x01, 0x9B, 0x1A, 0x00, ++0x0F, 0x32, 0xFF, 0x32, 0x9C, 0x21, 0x89, 0x00, 0x8A, 0x42, 0x57, 0xD8, 0x01, 0x92, 0x00, 0x9A, 0x13, 0x1B, 0x1B, 0x01, ++0x1B, 0x09, 0x38, 0x49, 0x8B, 0x42, 0x05, 0xD8, 0xA2, 0x42, 0x61, 0xD1, 0xAB, 0x68, 0x01, 0x9A, 0x93, 0x42, 0x5D, 0xD9, ++0x02, 0xA8, 0x34, 0x4B, 0x02, 0x93, 0x44, 0x60, 0xAB, 0x68, 0x83, 0x60, 0x06, 0x76, 0x06, 0x61, 0x31, 0x4B, 0xC3, 0x60, ++0xAB, 0x7D, 0x03, 0x75, 0x01, 0x33, 0x43, 0x75, 0x00, 0x23, 0x83, 0x75, 0xB0, 0x22, 0xAA, 0x5C, 0xC2, 0x75, 0x83, 0x76, ++0xC3, 0x76, 0x01, 0x33, 0x43, 0x76, 0xCA, 0xF7, 0xD7, 0xFE, 0xA9, 0x22, 0xAB, 0x5C, 0x01, 0x33, 0xAB, 0x54, 0xAA, 0x23, ++0xEB, 0x5C, 0x00, 0x2B, 0x31, 0xD1, 0x9F, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x3B, 0xD1, 0xAB, 0x6F, 0x9B, 0xB2, 0x62, 0x21, ++0x4E, 0x43, 0x22, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0xAB, 0x6F, 0x1B, 0x0C, 0x20, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0x20, 0x4B, ++0x9C, 0x46, 0x66, 0x44, 0x2B, 0x6D, 0x01, 0x33, 0x5B, 0x08, 0x01, 0x33, 0x5B, 0x08, 0x1D, 0x4A, 0x13, 0x43, 0x9B, 0xB2, ++0x33, 0x80, 0x22, 0xE0, 0x04, 0x34, 0x24, 0x01, 0x24, 0x09, 0x23, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x93, 0x42, 0x9D, 0xD9, ++0x03, 0x1B, 0x1B, 0x01, 0x9A, 0xD0, 0xF3, 0xE7, 0x64, 0x3B, 0xFF, 0x3B, 0x01, 0x93, 0x00, 0x9B, 0x01, 0x33, 0x1B, 0x01, ++0x1B, 0x09, 0x00, 0x93, 0x9F, 0xE7, 0x9E, 0x23, 0xE8, 0x5C, 0xCB, 0xF7, 0x21, 0xF8, 0x0F, 0x4B, 0x01, 0x22, 0x1A, 0x60, ++0xAA, 0x23, 0x00, 0x22, 0xEA, 0x54, 0xC2, 0xE7, 0x0C, 0x48, 0x77, 0xF7, 0xF1, 0xFC, 0x0A, 0xB0, 0x04, 0xBC, 0x90, 0x46, ++0xF0, 0xBD, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, ++0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0x18, 0x00, 0x60, 0x40, ++0x28, 0xD6, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x82, 0xB0, 0x05, 0x00, 0x0E, 0x00, 0x82, 0x00, 0x9D, 0x4B, ++0xD4, 0x58, 0x00, 0x2C, 0x00, 0xD1, 0x2B, 0xE1, 0x9B, 0x4B, 0x1B, 0x68, 0xDF, 0x68, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, ++0x05, 0xD1, 0x99, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, ++0xDB, 0xB2, 0xA3, 0x54, 0x09, 0x3A, 0xA2, 0x5C, 0x02, 0x2A, 0x01, 0xD1, 0x00, 0x2B, 0x51, 0xD0, 0x9E, 0xF7, 0xDE, 0xFF, ++0x01, 0x90, 0x01, 0x22, 0x31, 0x00, 0x28, 0x00, 0xFF, 0xF7, 0x20, 0xFD, 0x62, 0x23, 0x6B, 0x43, 0x8C, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1B, 0x88, 0xDB, 0x0B, 0x00, 0xD1, 0xAC, 0xE0, 0x31, 0x00, 0x28, 0x00, 0xFF, 0xF7, 0x15, 0xFE, 0xB4, 0x23, ++0xE0, 0x54, 0xA0, 0x23, 0xE3, 0x5C, 0x02, 0x2B, 0x00, 0xD1, 0xEA, 0xE0, 0x01, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0xBA, 0xF9, ++0x82, 0x23, 0xE3, 0x5E, 0xA3, 0x60, 0x81, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x0C, 0xD0, 0x34, 0x23, 0xFB, 0x5C, 0x00, 0x2B, ++0x00, 0xD1, 0x9D, 0xE0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x93, 0xE0, 0x7A, 0x4B, 0x00, 0x22, 0x1A, 0x60, ++0x34, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x90, 0xE0, 0xB4, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xBE, 0xE0, ++0xAA, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xD6, 0xE0, 0xA6, 0x33, 0xE2, 0x5C, 0x01, 0x32, 0xA3, 0x3B, 0x13, 0x40, ++0x9E, 0x22, 0xA1, 0x5C, 0x9C, 0x3A, 0x6E, 0x48, 0xCA, 0xF7, 0x56, 0xFF, 0xAA, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xC7, 0xE0, ++0x01, 0x21, 0x20, 0x00, 0xC9, 0xF7, 0xBE, 0xFF, 0xA0, 0x23, 0x02, 0x22, 0xE2, 0x54, 0x0A, 0x33, 0xE3, 0x5C, 0x00, 0x2B, ++0x49, 0xD1, 0xFE, 0xF7, 0xBF, 0xFD, 0x65, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, ++0x62, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0xD2, 0x0B, 0x00, 0xD1, 0xAD, 0xE0, 0x60, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, ++0xD2, 0x0A, 0xAA, 0x42, 0x07, 0xD0, 0x19, 0x88, 0xC9, 0x0A, 0x56, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x28, 0x00, ++0xA0, 0x47, 0x57, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x22, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x54, 0x4A, 0x94, 0x46, ++0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x19, 0x40, 0x21, 0x54, ++0x50, 0x4B, 0x1A, 0x68, 0xCB, 0x00, 0x5B, 0x1A, 0x5B, 0x00, 0x4F, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x52, 0x04, 0x52, 0x0C, ++0x93, 0x42, 0x05, 0xD0, 0x43, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x45, 0x4E, 0x00, 0x24, ++0xD5, 0x23, 0x5B, 0x00, 0x98, 0x46, 0x3E, 0x4F, 0x0A, 0xE0, 0x28, 0x00, 0xCA, 0xF7, 0x30, 0xFF, 0xAA, 0x23, 0x00, 0x22, ++0xE2, 0x54, 0xAE, 0xE7, 0x01, 0x34, 0x0E, 0x36, 0x04, 0x2C, 0x67, 0xD0, 0x33, 0x88, 0xDB, 0x0B, 0xF8, 0xD0, 0x3A, 0x4B, ++0x42, 0x46, 0x98, 0x5C, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xFD, 0x6E, 0xA8, 0x47, 0xEF, 0xE7, 0x31, 0x00, 0x28, 0x00, ++0xFF, 0xF7, 0x04, 0xFE, 0xB4, 0x23, 0xE0, 0x54, 0x51, 0xE7, 0x29, 0x00, 0x01, 0x98, 0xFF, 0xF7, 0x53, 0xFE, 0x66, 0xE7, ++0xB4, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x2E, 0xD1, 0xAA, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x47, 0xD1, 0xA9, 0x33, 0xE3, 0x5C, ++0x00, 0x2B, 0x43, 0xD1, 0x01, 0x21, 0x20, 0x00, 0xC9, 0xF7, 0x3A, 0xFF, 0x01, 0x99, 0x61, 0x60, 0x86, 0x23, 0xFA, 0x22, ++0xD2, 0x01, 0xE2, 0x52, 0x21, 0x67, 0x20, 0x33, 0xE3, 0x5C, 0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x13, 0x40, 0x26, 0x4A, ++0x13, 0x43, 0xA3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0x9C, 0x46, 0x61, 0x44, 0x0F, 0x01, 0x3F, 0x09, 0xE7, 0x60, 0x20, 0x00, ++0xC9, 0xF7, 0x7C, 0xFD, 0x00, 0x28, 0x23, 0xD0, 0x15, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x1C, 0xE0, 0x9E, 0x23, 0xE0, 0x5C, 0xCA, 0xF7, 0xD9, 0xFE, 0x00, 0x23, 0xAA, 0x22, 0xA3, 0x54, 0x75, 0x3A, 0xBB, 0x54, ++0xC6, 0xE7, 0x9E, 0x23, 0xE0, 0x5C, 0xCA, 0xF7, 0xCF, 0xFE, 0xAA, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x01, 0x3B, 0xE1, 0x5C, ++0x12, 0x48, 0x77, 0xF7, 0xA1, 0xFB, 0x05, 0xE0, 0x06, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xA0, 0x47, ++0x02, 0xB0, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x38, 0xE6, 0x10, 0x00, 0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, ++0x4E, 0x65, 0x61, 0x40, 0xC8, 0xE6, 0x10, 0x00, 0x7D, 0x03, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, ++0x92, 0x69, 0x61, 0x40, 0x2C, 0x04, 0x60, 0x40, 0x90, 0x69, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x34, 0xD6, 0x10, 0x00, ++0x10, 0xB5, 0x82, 0x00, 0x0C, 0x4B, 0xD4, 0x58, 0x00, 0x2C, 0x0E, 0xD0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, ++0x09, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, 0xA3, 0x54, ++0x10, 0xBD, 0x04, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xA0, 0x47, 0xF7, 0xE7, 0x38, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0xCF, 0xB2, 0x06, 0x2F, ++0x08, 0xD9, 0xFF, 0x20, 0x08, 0x40, 0x10, 0x4B, 0xDB, 0x6E, 0x98, 0x46, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xC0, 0x47, ++0x00, 0x2C, 0x0A, 0xD0, 0x04, 0x2C, 0x0F, 0xD0, 0xFF, 0x20, 0x28, 0x40, 0x09, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, ++0x21, 0x00, 0xA8, 0x47, 0x03, 0xE0, 0x31, 0x00, 0x38, 0x00, 0xFF, 0xF7, 0x61, 0xFE, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, ++0x31, 0x00, 0x38, 0x00, 0xFF, 0xF7, 0xB6, 0xFF, 0xF7, 0xE7, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x05, 0x00, ++0x51, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x02, 0xD0, 0xFE, 0xF7, 0x0E, 0xFD, 0xF8, 0xBD, 0x4F, 0x48, 0x77, 0xF7, 0x22, 0xFB, ++0x4E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x07, 0xD0, 0x4D, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, ++0x12, 0x20, 0xEF, 0xE7, 0x00, 0x21, 0xF8, 0x20, 0x75, 0xF7, 0xE0, 0xFA, 0x46, 0x4B, 0x18, 0x60, 0x00, 0x28, 0x00, 0xD1, ++0x7C, 0xE0, 0x9E, 0xF7, 0x37, 0xFE, 0x06, 0x00, 0x83, 0xF7, 0xD8, 0xFB, 0x43, 0x4A, 0x13, 0x88, 0x43, 0x49, 0x0B, 0x40, ++0x00, 0x02, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x3D, 0x4B, 0x1C, 0x68, 0xF8, 0x22, 0x00, 0x21, 0x20, 0x00, 0x73, 0xF7, ++0x79, 0xFA, 0x00, 0x23, 0x63, 0x62, 0x3D, 0x4A, 0xE2, 0x61, 0x3D, 0x4A, 0x22, 0x62, 0x03, 0x22, 0x22, 0x76, 0x3C, 0x4A, ++0x12, 0x78, 0xA2, 0x75, 0x3B, 0x4A, 0x22, 0x61, 0x05, 0x22, 0xE2, 0x75, 0x99, 0x32, 0xA3, 0x54, 0x01, 0x32, 0x01, 0x21, ++0xA1, 0x54, 0x6B, 0x3A, 0x22, 0x65, 0x6D, 0x32, 0xA3, 0x54, 0x7F, 0xF7, 0xA9, 0xFA, 0x07, 0x1E, 0x3D, 0xD0, 0x3A, 0x89, ++0x94, 0x23, 0xE2, 0x52, 0x93, 0x3B, 0x01, 0x22, 0x29, 0x00, 0x00, 0x20, 0xFE, 0xF7, 0xE8, 0xFC, 0x33, 0x00, 0x00, 0x22, ++0x29, 0x00, 0x01, 0x20, 0xFF, 0xF7, 0x50, 0xF9, 0x9E, 0xF7, 0xF8, 0xFD, 0x60, 0x60, 0x00, 0x23, 0x82, 0x22, 0xA3, 0x52, ++0xA3, 0x60, 0x04, 0x32, 0xFA, 0x21, 0xC9, 0x01, 0xA1, 0x52, 0xE6, 0x66, 0x26, 0x67, 0x63, 0x67, 0xA3, 0x67, 0x00, 0x22, ++0xA6, 0x33, 0xE2, 0x54, 0x23, 0x4B, 0xA3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0x9C, 0x46, 0x66, 0x44, 0x36, 0x01, 0x36, 0x09, ++0xE6, 0x60, 0x20, 0x00, 0xC9, 0xF7, 0x6C, 0xFC, 0x00, 0x28, 0x15, 0xD1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x1C, 0x49, ++0xA1, 0x32, 0xFF, 0x32, 0x8B, 0x5A, 0x01, 0x24, 0x23, 0x43, 0x8B, 0x52, 0xA0, 0x3A, 0xFF, 0x3A, 0x18, 0x4B, 0x1A, 0x60, ++0x78, 0xE7, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xBA, 0xE7, 0x0A, 0x4B, 0x9B, 0x6E, ++0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x20, 0x69, 0xE7, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, ++0x00, 0x20, 0x98, 0x47, 0x12, 0x20, 0x61, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x4C, 0xD6, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, ++0x28, 0x19, 0x16, 0x00, 0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, 0xA1, 0x04, 0x10, 0x00, 0xD3, 0x01, 0x10, 0x00, ++0x7C, 0x91, 0x0D, 0x00, 0x6A, 0x04, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x20, 0xA3, 0x16, 0x00, 0xC8, 0xE6, 0x10, 0x00, ++0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0A, 0x48, 0x77, 0xF7, 0x68, 0xFA, 0xA1, 0x78, 0x4A, 0x10, 0x01, 0x23, 0x1A, 0x40, ++0x07, 0x48, 0x02, 0x70, 0x0B, 0x40, 0xA3, 0x70, 0x20, 0x00, 0xFF, 0xF7, 0x85, 0xF9, 0x01, 0x00, 0x28, 0x00, 0xFA, 0xF7, ++0x8B, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xC0, 0x46, 0x60, 0xD6, 0x10, 0x00, 0xDC, 0xE5, 0x10, 0x00, 0x70, 0xB5, 0x05, 0x00, ++0x0C, 0x00, 0x06, 0x48, 0x77, 0xF7, 0x4C, 0xFA, 0x28, 0x00, 0xFF, 0xF7, 0x1B, 0xFF, 0x01, 0x00, 0x20, 0x00, 0xFA, 0xF7, ++0x77, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xC0, 0x46, 0x68, 0xD6, 0x10, 0x00, 0x10, 0xB5, 0xFF, 0xF7, 0x51, 0xF8, 0x00, 0x20, ++0x10, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x17, 0xD0, 0xDC, 0x68, 0x18, 0x23, 0x0D, 0x22, ++0x00, 0x21, 0x0B, 0x48, 0x75, 0xF7, 0x2A, 0xF9, 0xFF, 0x23, 0x03, 0x70, 0xA3, 0x88, 0x43, 0x80, 0x00, 0x23, 0x03, 0x71, ++0x43, 0x71, 0x23, 0x69, 0x83, 0x60, 0x63, 0x69, 0xC3, 0x60, 0xE3, 0x69, 0x03, 0x61, 0xE3, 0x6A, 0x43, 0x61, 0xC6, 0xF7, ++0x79, 0xFF, 0x10, 0xBD, 0xD8, 0xE5, 0x10, 0x00, 0x03, 0x11, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x01, 0x78, ++0x0A, 0x48, 0x77, 0xF7, 0x11, 0xFA, 0x23, 0x78, 0x00, 0x2B, 0x07, 0xD0, 0x01, 0x2B, 0x08, 0xD0, 0x00, 0x21, 0x28, 0x00, ++0xFA, 0xF7, 0x3A, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xFE, 0xF7, 0x6E, 0xFB, 0xF6, 0xE7, 0xFF, 0xF7, 0xC7, 0xFF, 0xFE, 0xF7, ++0x69, 0xFB, 0xF1, 0xE7, 0x70, 0xD6, 0x10, 0x00, 0x45, 0x54, 0x45, 0x52, 0x52, 0x3A, 0x0A, 0x00, 0x77, 0x61, 0x6B, 0x65, ++0x75, 0x70, 0x5F, 0x68, 0x6F, 0x73, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x5F, 0x75, 0x70, ++0x5F, 0x68, 0x6F, 0x73, 0x74, 0x0A, 0x00, 0x00, 0x75, 0x61, 0x72, 0x74, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x0A, 0x00, 0x00, ++0x70, 0x5F, 0x73, 0x5F, 0x70, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x5F, 0x63, 0x68, 0x5F, 0x75, 0x70, 0x64, 0x61, ++0x74, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, ++0xE6, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xF6, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x1A, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x42, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x66, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x8E, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xBA, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xE6, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x0C, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x32, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x5C, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0x82, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA2, 0x1C, 0x10, 0x00, 0xC4, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x16, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x3E, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x62, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x8A, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0xB6, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0xE2, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x08, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x2E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x58, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x7E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0x9E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, ++0xA8, 0x1A, 0x10, 0x00, 0xC0, 0x1C, 0x10, 0x00, 0x30, 0x78, 0x34, 0x30, 0x33, 0x34, 0x33, 0x30, 0x30, 0x34, 0x3A, 0x25, ++0x78, 0x2C, 0x25, 0x78, 0x00, 0x00, 0x00, 0x00, 0x43, 0x54, 0x53, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x20, 0x0A, 0x00, ++0xE2, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, ++0x78, 0x1D, 0x10, 0x00, 0x52, 0x1E, 0x10, 0x00, 0xE4, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, ++0xE2, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x6D, 0x64, 0x6C, 0x6C, 0x5F, 0x72, 0x65, 0x63, ++0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x62, 0x64, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, 0x2C, 0x25, ++0x78, 0x0A, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x6D, 0x61, 0x63, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, 0x2C, ++0x25, 0x78, 0x0A, 0x00, 0x66, 0x6C, 0x61, 0x73, 0x68, 0x6D, 0x61, 0x63, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, ++0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x43, 0x52, 0x5F, 0x50, 0x57, 0x52, 0x5F, 0x52, 0x45, 0x51, ++0x0A, 0x00, 0x00, 0x00, 0x50, 0x57, 0x52, 0x5F, 0x43, 0x54, 0x52, 0x4C, 0x5F, 0x52, 0x45, 0x51, 0x0A, 0x00, 0x00, 0x00, ++0x72, 0x65, 0x6D, 0x6F, 0x74, 0x65, 0x5F, 0x6D, 0x61, 0x78, 0x5F, 0x70, 0x77, 0x72, 0x0A, 0x00, 0x61, 0x66, 0x68, 0x74, ++0x6F, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x74, 0x78, 0x5F, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x00, ++0x72, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x73, 0x73, 0x69, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, ++0x73, 0x6D, 0x75, 0x74, 0x65, 0x0A, 0x00, 0x00, 0x72, 0x78, 0x5F, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x25, ++0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, ++0x64, 0x75, 0x20, 0x65, 0x6E, 0x6F, 0x75, 0x67, 0x68, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x77, 0x69, 0x66, 0x69, 0x20, 0x63, ++0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x69, 0x6F, 0x6E, 0x0A, 0x00, 0x00, 0x00, 0x75, 0x6D, 0x72, 0x65, 0x0A, 0x00, 0x00, 0x00, ++0x55, 0x4E, 0x44, 0x45, 0x46, 0x20, 0x56, 0x45, 0x4E, 0x44, 0x4F, 0x52, 0x5F, 0x49, 0x4E, 0x46, 0x4F, 0x0A, 0x00, 0x00, ++0x55, 0x4E, 0x4B, 0x4E, 0x4F, 0x57, 0x20, 0x56, 0x45, 0x4E, 0x44, 0x4F, 0x52, 0x5F, 0x49, 0x4E, 0x46, 0x4F, 0x3A, 0x25, ++0x78, 0x0A, 0x00, 0x00, 0x69, 0x6E, 0x69, 0x74, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, ++0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x38, 0x5C, 0x10, 0x00, 0x70, 0x5C, 0x10, 0x00, 0x78, 0x5C, 0x10, 0x00, ++0x38, 0x5C, 0x10, 0x00, 0x70, 0x5C, 0x10, 0x00, 0x76, 0x65, 0x72, 0x3A, 0x25, 0x73, 0x0A, 0x00, 0x6C, 0x6D, 0x74, 0x3A, ++0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x72, 0x65, 0x6A, 0x65, 0x63, 0x74, 0x3A, 0x25, 0x78, 0x00, 0x00, 0x00, ++0x76, 0x73, 0x5F, 0x61, 0x70, 0x63, 0x66, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x6A, 0x65, 0x63, 0x74, 0x32, 0x3A, ++0x25, 0x78, 0x00, 0x00, 0x92, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0x86, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, ++0x92, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0x8C, 0x73, 0x10, 0x00, 0xC0, 0x72, 0x10, 0x00, ++0x6E, 0x6F, 0x61, 0x6C, 0x63, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, 0x00, 0x62, 0x62, 0x5F, 0x74, 0x78, 0x5F, 0x74, 0x6F, ++0x6E, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x6F, 0x70, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x6D, 0x73, 0x73, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x6D, 0x73, 0x73, 0x65, 0x72, 0x72, 0x0A, 0x00, 0x46, 0x4C, 0x55, 0x53, 0x48, 0x3A, 0x25, 0x78, ++0x0A, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x4B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x25, 0x78, 0x20, 0x00, 0x6F, 0x70, 0x63, 0x3A, ++0x25, 0x78, 0x0A, 0x00, 0x69, 0x20, 0x3D, 0x20, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x3A, 0x25, 0x78, ++0x0A, 0x00, 0x00, 0x00, 0x6F, 0x70, 0x6C, 0x6C, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x1E, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xBE, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, ++0xFC, 0x89, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xDA, 0x89, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0x4C, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xE8, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, ++0xF4, 0x8A, 0x10, 0x00, 0x62, 0x8A, 0x10, 0x00, 0x55, 0x50, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, ++0x25, 0x78, 0x0A, 0x00, 0x6F, 0x70, 0x6C, 0x6C, 0x63, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x63, 0x72, ++0x78, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x63, 0x74, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, ++0x61, 0x70, 0x63, 0x66, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x61, 0x74, 0x65, 0x6E, 0x63, 0x79, 0x0A, ++0x00, 0x00, 0x00, 0x00, 0x72, 0x66, 0x5F, 0x72, 0x65, 0x73, 0x65, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x45, 0x52, 0x52, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x41, 0x53, 0x53, 0x45, ++0x52, 0x54, 0x5F, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x28, 0x25, 0x73, 0x29, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x25, ++0x78, 0x20, 0x61, 0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x41, 0x53, 0x53, 0x45, ++0x52, 0x54, 0x5F, 0x45, 0x52, 0x52, 0x7A, 0x28, 0x25, 0x73, 0x29, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x61, ++0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x5F, 0x50, ++0x41, 0x52, 0x41, 0x4D, 0x7A, 0x28, 0x30, 0x78, 0x25, 0x58, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x58, 0x29, 0x2C, 0x20, 0x69, ++0x6E, 0x20, 0x25, 0x78, 0x20, 0x61, 0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, ++0x70, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0A, 0x00, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x25, ++0x78, 0x0D, 0x0A, 0x00, 0x64, 0x65, 0x6C, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x6F, 0x70, 0x3A, 0x30, 0x78, 0x25, 0x78, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, ++0x5F, 0x65, 0x6E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x65, 0x72, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, ++0x74, 0x65, 0x73, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x5F, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, ++0x74, 0x65, 0x73, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x5F, 0x65, 0x78, 0x69, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, ++0x74, 0x73, 0x74, 0x5F, 0x65, 0x6E, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x74, 0x73, ++0x74, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x64, 0x72, 0x5F, ++0x70, 0x6B, 0x74, 0x3D, 0x25, 0x78, 0x00, 0x00, 0x66, 0x72, 0x65, 0x71, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0xC0, 0xB8, 0x10, 0x00, 0xB4, 0xB9, 0x10, 0x00, 0x94, 0xBA, 0x10, 0x00, 0xF2, 0xB8, 0x10, 0x00, 0xB0, 0xBA, 0x10, 0x00, ++0xCC, 0xBA, 0x10, 0x00, 0xE8, 0xBA, 0x10, 0x00, 0x04, 0xBB, 0x10, 0x00, 0x70, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, ++0x73, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x68, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x65, 0x3A, 0x25, ++0x34, 0x64, 0x2C, 0x20, 0x6F, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x6F, 0x6C, 0x65, 0x3A, 0x25, 0x34, 0x64, ++0x2C, 0x20, 0x70, 0x6E, 0x3A, 0x25, 0x34, 0x64, 0x20, 0x62, 0x63, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x3A, ++0x25, 0x37, 0x64, 0x2C, 0x20, 0x70, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2E, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x72, 0x3A, ++0x25, 0x64, 0x2E, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x70, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x73, 0x6F, 0x3A, 0x25, ++0x34, 0x64, 0x2C, 0x20, 0x68, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, ++0x62, 0x63, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x70, 0x65, 0x72, 0x3A, ++0x25, 0x64, 0x2E, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2E, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, ++0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x62, 0x75, 0x72, 0x73, 0x74, 0x5F, 0x74, 0x78, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, ++0x0A, 0x00, 0x00, 0x00, 0x72, 0x78, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x63, 0x68, 0x5F, ++0x70, 0x72, 0x6F, 0x67, 0x5F, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, ++0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x72, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0A, 0x00, ++0x74, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x0A, 0x00, 0x72, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x0A, 0x00, 0x62, 0x62, 0x5F, 0x74, ++0x73, 0x74, 0x5F, 0x73, 0x74, 0x6F, 0x70, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x02, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC7, 0x03, 0x00, 0x00, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, ++0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, ++0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, ++0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, ++0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, ++0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, ++0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, ++0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, ++0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, ++0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, ++0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, ++0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, ++0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, ++0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, ++0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, ++0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, ++0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, ++0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, ++0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, ++0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, ++0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, ++0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, ++0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, ++0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, ++0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, ++0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, ++0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, ++0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, ++0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, ++0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, ++0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, ++0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, ++0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, ++0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, ++0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, ++0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, ++0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, ++0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, ++0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, ++0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, ++0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, ++0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, ++0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, ++0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, ++0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, ++0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, ++0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, ++0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, ++0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, ++0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, ++0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, ++0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFF, 0xC1, 0xFB, 0xE8, ++0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, ++0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, ++0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, ++0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, ++0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, ++0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, ++0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, ++0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, ++0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, ++0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, ++0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, ++0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, ++0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, ++0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, ++0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, ++0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, ++0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, ++0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, ++0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, ++0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, ++0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, ++0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, ++0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, ++0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, ++0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, ++0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, ++0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, ++0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, ++0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, ++0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, ++0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, ++0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, ++0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, ++0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, ++0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, ++0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, ++0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, ++0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, ++0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, ++0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, ++0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, ++0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, ++0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, ++0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, ++0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, ++0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, ++0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, ++0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, ++0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, ++0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, ++0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, ++0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x01, 0x02, 0x02, 0x03, ++0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, ++0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, ++0x04, 0x05, 0x05, 0x06, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, ++0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, ++0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, ++0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, ++0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, ++0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, ++0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, ++0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, ++0x05, 0x06, 0x06, 0x07, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, ++0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08, 0x00, 0x10, 0x20, 0x30, ++0x40, 0x50, 0x60, 0x70, 0x00, 0x00, 0x01, 0x50, 0x00, 0x03, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x50, ++0x00, 0x02, 0x07, 0x03, 0x0C, 0x04, 0x0D, 0x05, 0x26, 0x06, 0x37, 0x07, 0x2C, 0x08, 0x3D, 0x09, 0x00, 0x00, 0x02, 0x01, ++0x05, 0x00, 0x01, 0x07, 0x00, 0x01, 0x00, 0x00, 0x01, 0x07, 0x00, 0x01, 0x0C, 0x00, 0x03, 0x0D, 0x00, 0x03, 0x06, 0x01, ++0x01, 0x07, 0x01, 0x01, 0x0C, 0x01, 0x03, 0x0D, 0x01, 0x03, 0x00, 0x00, 0x00, 0x27, 0x35, 0x00, 0x2B, 0x00, 0x31, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x22, 0x10, 0x00, 0xFF, 0xF0, 0xAA, 0xFF, 0xFF, 0x00, 0x0F, 0x55, ++0x80, 0x01, 0x00, 0x00, 0xF6, 0xFC, 0xFE, 0x00, 0x03, 0x06, 0x09, 0x0A, 0xF9, 0xFC, 0xFF, 0x02, 0x05, 0x07, 0x09, 0x0C, ++0x0F, 0x11, 0x15, 0x17, 0x50, 0x00, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, 0x50, 0xC3, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, ++0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x24, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x25, ++0x00, 0x80, 0xDE, 0xA9, 0x91, 0x06, 0x7B, 0x00, 0x04, 0x10, 0x04, 0x00, 0x04, 0x00, 0x00, 0x26, 0x00, 0x80, 0xDE, 0xA9, ++0x65, 0x06, 0x7C, 0x00, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x48, ++0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0x7F, 0x24, 0x17, 0x42, 0x40, 0x40, 0x8D, 0x08, 0x7B, 0xB0, 0x14, 0x10, 0x04, 0x00, ++0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, 0x04, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x26, ++0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, ++0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, 0x17, 0x42, 0x40, 0x40, 0xFD, 0x08, 0x7A, 0xB0, ++0x14, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, 0x04, 0x10, 0x04, 0x00, ++0x0C, 0x21, 0x04, 0x26, 0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, ++0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, 0x17, 0x42, 0x40, 0x40, ++0xFD, 0x08, 0x7A, 0xB0, 0x14, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, ++0x04, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x26, 0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, ++0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, ++0x17, 0x42, 0x40, 0x40, 0xFD, 0x08, 0x7A, 0xB0, 0xD0, 0x9E, 0x21, 0x00, 0x1C, 0x1C, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, ++0x1C, 0x1C, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x61, ++0xD6, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x65, 0xD7, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x75, 0xD7, 0x9E, 0x21, 0x00, ++0x70, 0x70, 0xFB, 0xFD, 0xD7, 0x9E, 0x21, 0x00, 0xF0, 0xF0, 0xFB, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, ++0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, ++0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, ++0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, ++0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0B, 0x00, 0x00, 0x04, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0xFF, 0xF9, 0x01, 0x08, ++0x00, 0x00, 0x00, 0x00, 0xAC, 0x2B, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x28, 0x21, 0x16, 0x00, 0xA8, 0x61, 0x00, 0x00, ++0xB8, 0x88, 0x00, 0x00, 0x74, 0x40, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0xED, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xCD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, ++0x60, 0x07, 0x8D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x0D, 0x79, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x6B, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0xDB, 0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, ++0x60, 0xD7, 0x0C, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x58, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x55, 0x00, ++0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, ++0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0xEB, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0xED, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xCD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, ++0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x79, ++0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3E, 0x55, 0x00, ++0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0xDB, ++0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0xD7, 0x0C, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x22, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, ++0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0xDB, ++0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, ++0xEB, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, ++0x6C, 0x00, 0x00, 0x03, 0x60, 0x07, 0xAC, 0xE9, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0x00, 0x03, ++0x60, 0x07, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0x20, 0x03, 0x60, 0xD7, 0x0C, 0xE8, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0xE0, 0x03, 0x60, 0x9F, 0x0D, 0xE8, 0x80, 0x80, 0x80, 0x80, ++0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0xE7, 0x8C, 0x69, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, ++0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x2F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, ++0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, ++0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, ++0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, ++0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, ++0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, 0x03, 0xC7, 0x8E, 0x00, 0x07, 0xC7, 0x8E, 0x00, 0x0B, 0xC7, 0x8E, 0x00, ++0x0F, 0xC7, 0x8E, 0x00, 0x13, 0xC7, 0x8E, 0x00, 0x17, 0xC7, 0x8E, 0x00, 0x1B, 0xC7, 0x8E, 0x00, 0x1F, 0xC7, 0x8E, 0x00, ++0x23, 0xC7, 0x8E, 0x00, 0x27, 0xC7, 0x8E, 0x00, 0x2B, 0xC7, 0x8E, 0x00, 0x2F, 0xC7, 0x8E, 0x00, 0x33, 0xC7, 0x8E, 0x00, ++0x37, 0xC7, 0x8E, 0x00, 0x3B, 0xC7, 0x8E, 0x00, 0x3F, 0xC7, 0x8E, 0x00, 0x06, 0x81, 0x88, 0x00, 0x0A, 0x81, 0x88, 0x00, ++0x0C, 0xC1, 0x88, 0x00, 0x14, 0xC1, 0x90, 0x00, 0x14, 0x41, 0x91, 0x00, 0x15, 0xC1, 0x91, 0x00, 0x23, 0xC1, 0x91, 0x00, ++0x3F, 0xC1, 0x91, 0x00, 0x3F, 0xC1, 0x92, 0x00, 0x3F, 0x01, 0x94, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, ++0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, ++0x2D, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, 0x33, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x33, 0x38, 0x3A, ++0x33, 0x39, 0x20, 0x2D, 0x20, 0x67, 0x69, 0x74, 0x20, 0x30, 0x61, 0x61, 0x62, 0x66, 0x62, 0x66, 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, ++}; ++ ++struct firmware_info{ ++ char fw_name[30]; ++ char* fw_array; ++ int fw_size; ++}; ++ ++struct firmware_info firmware[]={ ++ {"fmacfw.bin", fmacfw, sizeof(fmacfw)}, ++ {"fw_adid_u03.bin", fw_adid_u03, sizeof(fw_adid_u03)}, ++ {"fw_patch_table_u03.bin", fw_patch_table_u03, sizeof(fw_patch_table_u03)}, ++ {"fw_patch_u03.bin", fw_patch_u03, sizeof(fw_patch_u03)} ++}; ++ ++int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf){ ++ int firmware_number = 0; ++ int index = 0; ++ int fw_size = 0; ++ ++ firmware_number = sizeof(firmware)/sizeof(struct firmware_info); ++ printk("%s search:%s \r\n", __func__ , fw_name); ++ ++ for(index = 0; index < firmware_number; index++){ ++ if(!strcmp(firmware[index].fw_name, fw_name)){ ++ fw_size = firmware[index].fw_size; ++ printk("%s find %s len:%d\r\n", __func__, fw_name, fw_size); ++ *fw_buf = (u32*)firmware[index].fw_array; ++ return fw_size; ++ } ++ } ++ ++ printk("%s %s not found \r\n", __func__, fw_name); ++ ++ return 0; ++} +\ No newline at end of file +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h +new file mode 100644 +index 000000000000..dcf38e9ba302 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h +@@ -0,0 +1,3 @@ ++int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf); ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c +new file mode 100644 +index 000000000000..9514c416b5d6 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c +@@ -0,0 +1,62 @@ ++#include ++#include "aicsdio_txrxif.h" ++#include "aic_bsp_driver.h" ++ ++struct prealloc_txq{ ++ int prealloced; ++ void *txq; ++ size_t size; ++}; ++ ++struct prealloc_txq prealloc_txq; ++#define MAX_TXQ_SIZE 100 * 1024 ++ ++void *aicwf_prealloc_txq_alloc(size_t size) ++{ ++ ++ BUG_ON(size > MAX_TXQ_SIZE); ++ ++ //check prealloc_txq.size ++ if((int)prealloc_txq.size != (int)size) ++ { ++ AICWFDBG(LOGINFO, "%s size is diff will to be kzalloc \r\n", __func__); ++ ++ if(prealloc_txq.txq != NULL) ++ { ++ AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__); ++ kfree(prealloc_txq.txq); ++ prealloc_txq.txq = NULL; ++ } ++ ++ prealloc_txq.size = size; ++ prealloc_txq.prealloced = 0; ++ } ++ ++ //check prealloc or not ++ if(!prealloc_txq.prealloced) ++ { ++ prealloc_txq.txq = kzalloc(size, GFP_KERNEL); ++ if(!prealloc_txq.txq){ ++ AICWFDBG(LOGERROR, "%s txq kzalloc fail \r\n", __func__); ++ }else{ ++ AICWFDBG(LOGINFO, "%s txq kzalloc successful \r\n", __func__); ++ prealloc_txq.prealloced = 1; ++ } ++ }else{ ++ AICWFDBG(LOGINFO, "%s txq not need to kzalloc \r\n", __func__); ++ } ++ ++ return prealloc_txq.txq; ++} ++void aicwf_prealloc_txq_free(void) ++{ ++ if(prealloc_txq.txq != NULL) ++ { ++ AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__); ++ kfree(prealloc_txq.txq); ++ prealloc_txq.txq = NULL; ++ } ++} ++ ++EXPORT_SYMBOL(aicwf_prealloc_txq_alloc); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h +new file mode 100644 +index 000000000000..ce4ee07473b3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h +@@ -0,0 +1,4 @@ ++ ++ ++void aicwf_prealloc_txq_free(void); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c +new file mode 100644 +index 000000000000..3d7b65375adb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c +@@ -0,0 +1,161 @@ ++#include ++#include "md5.h" ++ ++unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; ++ ++void MD5Init(MD5_CTX *context) ++{ ++ context->count[0] = 0; ++ context->count[1] = 0; ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xEFCDAB89; ++ context->state[2] = 0x98BADCFE; ++ context->state[3] = 0x10325476; ++} ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) ++{ ++ unsigned int i = 0,index = 0,partlen = 0; ++ index = (context->count[0] >> 3) & 0x3F; ++ partlen = 64 - index; ++ context->count[0] += inputlen << 3; ++ if(context->count[0] < (inputlen << 3)) ++ context->count[1]++; ++ context->count[1] += inputlen >> 29; ++ ++ if(inputlen >= partlen) ++ { ++ memcpy(&context->buffer[index],input,partlen); ++ MD5Transform(context->state,context->buffer); ++ for(i = partlen;i+64 <= inputlen;i+=64) ++ MD5Transform(context->state,&input[i]); ++ index = 0; ++ } ++ else ++ { ++ i = 0; ++ } ++ memcpy(&context->buffer[index],&input[i],inputlen-i); ++} ++void MD5Final(MD5_CTX *context,unsigned char digest[16]) ++{ ++ unsigned int index = 0,padlen = 0; ++ unsigned char bits[8]; ++ index = (context->count[0] >> 3) & 0x3F; ++ padlen = (index < 56)?(56-index):(120-index); ++ MD5Encode(bits,context->count,8); ++ MD5Update(context,PADDING,padlen); ++ MD5Update(context,bits,8); ++ MD5Encode(digest,context->state,16); ++} ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[j] = input[i] & 0xFF; ++ output[j+1] = (input[i] >> 8) & 0xFF; ++ output[j+2] = (input[i] >> 16) & 0xFF; ++ output[j+3] = (input[i] >> 24) & 0xFF; ++ i++; ++ j+=4; ++ } ++} ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[i] = (input[j]) | ++ (input[j+1] << 8) | ++ (input[j+2] << 16) | ++ (input[j+3] << 24); ++ i++; ++ j+=4; ++ } ++} ++void MD5Transform(unsigned int state[4],unsigned char block[64]) ++{ ++ unsigned int a = state[0]; ++ unsigned int b = state[1]; ++ unsigned int c = state[2]; ++ unsigned int d = state[3]; ++ unsigned int x[64]; ++ MD5Decode(x,block,64); ++ FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ ++ FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ ++ FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ ++ FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ ++ FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ ++ FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ ++ FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ ++ FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ ++ FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ ++ FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ ++ FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ ++ FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ ++ FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ ++ FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ ++ FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ ++ FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ ++ ++ /* Round 2 */ ++ GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ ++ GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ ++ GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ ++ GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ ++ GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ ++ GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ ++ GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ ++ GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ ++ GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ ++ GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ ++ GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ ++ GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ ++ GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ ++ GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ ++ GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ ++ GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ ++ ++ /* Round 3 */ ++ HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ ++ HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ ++ HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ ++ HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ ++ HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ ++ HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ ++ HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ ++ HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ ++ HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ ++ HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ ++ HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ ++ HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ ++ HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ ++ HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ ++ HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ ++ HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ ++ ++ /* Round 4 */ ++ II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ ++ II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ ++ II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ ++ II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ ++ II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ ++ II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ ++ II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ ++ II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ ++ II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ ++ II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ ++ II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ ++ II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ ++ II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ ++ II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ ++ II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ ++ II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h +new file mode 100644 +index 000000000000..6ed5c0f8e886 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h +@@ -0,0 +1,48 @@ ++#ifndef MD5_H ++#define MD5_H ++ ++typedef struct ++{ ++ unsigned int count[2]; ++ unsigned int state[4]; ++ unsigned char buffer[64]; ++}MD5_CTX; ++ ++ ++#define F(x,y,z) ((x & y) | (~x & z)) ++#define G(x,y,z) ((x & z) | (y & ~z)) ++#define H(x,y,z) (x^y^z) ++#define I(x,y,z) (y ^ (x | ~z)) ++#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) ++#define FF(a,b,c,d,x,s,ac) \ ++ { \ ++ a += F(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define GG(a,b,c,d,x,s,ac) \ ++ { \ ++ a += G(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define HH(a,b,c,d,x,s,ac) \ ++ { \ ++ a += H(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define II(a,b,c,d,x,s,ac) \ ++ { \ ++ a += I(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++void MD5Init(MD5_CTX *context); ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); ++void MD5Final(MD5_CTX *context,unsigned char digest[16]); ++void MD5Transform(unsigned int state[4],unsigned char block[64]); ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h +new file mode 100644 +index 000000000000..6fcb679c8934 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h +@@ -0,0 +1,4 @@ ++#define RWNX_VERS_REV "241c091M (master)" ++#define RWNX_VERS_MOD "6.4.3.0" ++#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" ++#define RELEASE_DATE "2025_0410_b99ca8b6" +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore +new file mode 100644 +index 000000000000..c3c2d151e157 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig +new file mode 100644 +index 000000000000..ff7aaa649f83 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig +@@ -0,0 +1,5 @@ ++config AIC8800_BTLPM_SUPPORT ++ tristate "AIC8800 bluetooth Support" ++ help ++ This is support for aic bluetooh driver. ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile +new file mode 100644 +index 000000000000..6d59301f9741 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile +@@ -0,0 +1,83 @@ ++CONFIG_AIC8800_BTLPM_SUPPORT = m ++ ++obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) := aic8800_btlpm.o ++ ++ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp ++ ++# Platform support list ++CONFIG_PLATFORM_ROCKCHIP ?= n ++CONFIG_PLATFORM_ROCKCHIP2 ?= n ++CONFIG_PLATFORM_ALLWINNER ?= n ++CONFIG_PLATFORM_AMLOGIC ?= n ++CONFIG_PLATFORM_UBUNTU ?= y ++ ++ ++CONFIG_SUPPORT_LPM ?= n ++CONFIG_AUTO_PM ?= n ++ ++aic8800_btlpm-y := \ ++ aic_bluetooth_main.o \ ++ rfkill.o \ ++ ++aic8800_btlpm-$(CONFIG_SUPPORT_LPM) += lpm.o ++ ++ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) ++ ++ccflags-$(CONFIG_AUTO_PM) += -DCONFIG_AUTO_PM ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ARCH = arm64 ++KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++ARCH = arm64 ++KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++KDIR ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9/ ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ccflags-$(CONFIG_PLATFORM_NANOPI) += -DCONFIG_PLATFORM_NANOPI ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++KDIR ?= /lib/modules/$(shell uname -r)/build ++PWD ?= $(shell pwd) ++KVER ?= $(shell uname -r) ++MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ++ARCH ?= x86_64 ++CROSS_COMPILE ?= ++endif ++ ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c +new file mode 100644 +index 000000000000..52d768d83da8 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c +@@ -0,0 +1,1167 @@ ++/* ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++#include ++#endif ++ ++#include "aic_bsp_export.h" ++ ++/* ++ * #define BT_SLEEP_DBG ++ */ ++#define BT_SLEEP_DBG ++#undef BT_DBG ++#undef BT_ERR ++#ifdef BT_SLEEP_DBG ++#define BT_DBG(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++#else ++#define BT_DBG(fmt, arg...) ++#endif ++#define BT_ERR(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++ ++/* ++ * Defines ++ */ ++ ++#define VERSION "1.3.3" ++#define PROC_DIR "bluetooth/sleep" ++ ++#define DEFAULT_UART_INDEX 1 ++#define BT_BLUEDROID_SUPPORT 1 ++static int bluesleep_start(void); ++static void bluesleep_stop(void); ++ ++struct bluesleep_info { ++ unsigned int wakeup_enable; ++ unsigned host_wake; ++ unsigned ext_wake; ++ unsigned host_wake_irq; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ struct wakeup_source *ws; ++#else ++ struct wake_lock wake_lock; ++#endif ++ struct uart_port *uport; ++ unsigned host_wake_assert:1; ++ unsigned ext_wake_assert:1; ++ struct platform_device *pdev; ++}; ++ ++/* work function */ ++static void bluesleep_sleep_work(struct work_struct *work); ++static void bluesleep_tx_allow_sleep(void); ++ ++/* work queue */ ++DECLARE_DELAYED_WORK(sleep_workqueue, bluesleep_sleep_work); ++ ++/* Macros for handling sleep work */ ++#define bluesleep_rx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_rx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++ ++/* 1 second timeout */ ++#define RX_TIMER_INTERVAL 1 ++ ++/* state variable names and bit positions */ ++#define BT_PROTO 0x01 ++#define BT_TXDATA 0x02 ++#define BT_ASLEEP 0x04 ++#define BT_TXIDLE 0x08 ++#define BT_PAUSE 0x09 ++#define BT_RXTIMER 0x0a ++ ++#if BT_BLUEDROID_SUPPORT ++static bool has_lpm_enabled; ++#else ++/* global pointer to a single hci device. */ ++static struct hci_dev *bluesleep_hdev; ++#endif ++ ++#if BT_BLUEDROID_SUPPORT ++static struct platform_device *bluesleep_uart_dev; ++#endif ++static struct bluesleep_info *bsi; ++ ++/* module usage */ ++static atomic_t open_count = ATOMIC_INIT(1); ++ ++/* ++ * Local function prototypes ++ */ ++ ++#if !BT_BLUEDROID_SUPPORT ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data); ++#endif ++ ++/* ++ * Global variables ++ */ ++ ++/** Global state flags */ ++static unsigned long flags; ++ ++/** Tasklet to respond to change in hostwake line */ ++static struct tasklet_struct hostwake_task; ++ ++/** Reception timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t); ++#else ++static void bluesleep_rx_timer_expire(unsigned long data); ++#endif ++static struct timer_list rx_timer; ++ ++/** Lock for state transitions */ ++static spinlock_t rw_lock; ++ ++#if !BT_BLUEDROID_SUPPORT ++/** Notifier block for HCI events */ ++struct notifier_block hci_event_nblock = { ++ .notifier_call = bluesleep_hci_event, ++}; ++#endif ++ ++struct proc_dir_entry *bluetooth_dir, *sleep_dir; ++ ++/* ++ * Local functions ++ */ ++ ++/* ++ * bt go to sleep will call this function tell uart stop data interactive ++ */ ++static void hsuart_power(int on) ++{ ++ if (bsi->uport != NULL) { ++ if (on) ++ bsi->uport->ops->set_mctrl(bsi->uport, TIOCM_RTS); ++ else ++ bsi->uport->ops->set_mctrl(bsi->uport, 0); ++ } else { ++ BT_ERR("bsi->uport = NULL, has_lpm_enabled = %d", has_lpm_enabled); ++ } ++} ++ ++/** ++ * @return 1 if the Host can go to sleep, 0 otherwise. ++ */ ++static inline int bluesleep_can_sleep(void) ++{ ++ /* check if HOST_WAKE_BT_GPIO and BT_WAKE_HOST_GPIO ++ * are both deasserted ++ */ ++ return (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) && ++ (gpio_get_value(bsi->host_wake) != bsi->host_wake_assert) && ++ (!test_bit(BT_RXTIMER, &flags)) && (bsi->uport != NULL); ++} ++ ++/** ++ * @brief@ main sleep work handling function which update the flags ++ * and activate and deactivate UART ,check FIFO. ++ */ ++static void bluesleep_sleep_work(struct work_struct *work) ++{ ++ if (!has_lpm_enabled) ++ return; ++ ++ if (bluesleep_can_sleep()) { ++ /* already asleep, this is an error case */ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("already asleep"); ++ return; ++ } ++ if (bsi->uport->ops->tx_empty(bsi->uport)) { ++ BT_DBG("going to sleep..."); ++ set_bit(BT_ASLEEP, &flags); ++ /*Deactivating UART */ ++ hsuart_power(0); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++ } else { ++ BT_DBG("This should never happen.\n"); ++ return; ++ } ++ } else if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("hold wake locks for rx_task."); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ clear_bit(BT_ASLEEP, &flags); ++ ++ /* Add a timer to make sure that UART ++ * would not be turned on&off very frequentently ++ */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ ++ set_bit(BT_RXTIMER, &flags); ++ hsuart_power(1); ++ } else { ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ set_bit(BT_RXTIMER, &flags); ++ ++ if(test_bit(BT_PAUSE, &flags)){ ++ BT_DBG("rx wake du BT_PAUSE:%lx", flags); ++ ///enable bt sleep immediately ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } else if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert ++ && !test_bit(BT_TXIDLE, &flags)) { ++ BT_DBG("force retrigger bt wake:%lx", flags); ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ msleep(20); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } ++ } ++} ++ ++/** ++ * A tasklet function that runs in tasklet context and reads the value ++ * of the HOST_WAKE GPIO pin and further defer the work. ++ * @param data Not used. ++ */ ++static void bluesleep_hostwake_task(unsigned long data) ++{ ++ BT_DBG("hostwake line change"); ++ spin_lock(&rw_lock); ++ ++ if (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert) ++ bluesleep_rx_busy(); ++ else ++ bluesleep_rx_idle(); ++ ++ spin_unlock(&rw_lock); ++} ++ ++/** ++ * Handles proper timer action when outgoing data is delivered to the ++ * HCI line discipline. Sets BT_TXDATA. ++ */ ++static void bluesleep_outgoing_data(void) ++{ ++ unsigned long irq_flags; ++ int power_on_uart = 0; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ /* if the tx side is sleeping... */ ++ if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) { ++ BT_DBG("tx was sleeping, wakeup it"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ clear_bit(BT_ASLEEP, &flags); ++ clear_bit(BT_TXIDLE, &flags); ++ power_on_uart = 1; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ if (power_on_uart == 1) ++ hsuart_power(1); ++} ++ ++#if BT_BLUEDROID_SUPPORT ++static struct uart_port *bluesleep_get_uart_port(void) ++{ ++ struct uart_port *uport = NULL; ++ ++ if (bluesleep_uart_dev) { ++ uport = platform_get_drvdata(bluesleep_uart_dev); ++ if (uport) ++ BT_DBG( ++ "%s get uart_port from blusleep_uart_dev: %s, port irq: %d", ++ __func__, bluesleep_uart_dev->name, uport->irq); ++ } ++ return uport; ++} ++ ++static int bluesleep_lpm_proc_show(struct seq_file *m, void *v) ++{ ++ seq_printf(m, "lpm enable: %d\n", has_lpm_enabled); ++ return 0; ++} ++ ++static int bluesleep_lpm_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_lpm_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_lpm(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ if (b == '0') { ++#if 1 ++ set_bit(BT_PAUSE, &flags); ++ set_bit(BT_TXIDLE, &flags); ++ clear_bit(BT_TXDATA, &flags); ++ /* deassert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++#else ++ /* HCI_DEV_UNREG */ ++ bluesleep_stop(); ++ has_lpm_enabled = false; ++ bsi->uport = NULL; ++#endif ++ } else { ++ clear_bit(BT_PAUSE, &flags); ++ /* HCI_DEV_REG */ ++ if (!has_lpm_enabled) { ++ has_lpm_enabled = true; ++ if (bluesleep_uart_dev) ++ bsi->uport = bluesleep_get_uart_port(); ++ ++ /* if bluetooth started, start bluesleep*/ ++ bluesleep_start(); ++ } ++ } ++ ++ return count; ++} ++ ++static int bluesleep_btwrite_proc_show(struct seq_file *m, void *v) ++{ ++ seq_puts(m, "it's not support\n"); ++ return 0; ++} ++ ++static int bluesleep_btwrite_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_btwrite_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_btwrite(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ /* HCI_DEV_WRITE */ ++ if (b != '0') ++ bluesleep_outgoing_data(); ++ else ++ bluesleep_tx_allow_sleep(); ++ ++ return count; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops lpm_fops = { ++ .proc_open = bluesleep_lpm_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_lpm, ++}; ++static const struct proc_ops btwrite_fops = { ++ .proc_open = bluesleep_btwrite_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_btwrite, ++}; ++ ++#else ++ ++static const struct file_operations lpm_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_lpm_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_lpm, ++}; ++static const struct file_operations btwrite_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_btwrite_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_btwrite, ++}; ++#endif ++ ++#else ++/** ++ * Handles HCI device events. ++ * @param this Not used. ++ * @param event The event that occurred. ++ * @param data The HCI device associated with the event. ++ * @return NOTIFY_DONE. ++ */ ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data) ++{ ++ struct hci_dev *hdev = (struct hci_dev *) data; ++ struct hci_uart *hu; ++ struct uart_state *state; ++ ++ if (!hdev) ++ return NOTIFY_DONE; ++ ++ switch (event) { ++ case HCI_DEV_REG: ++ if (!bluesleep_hdev) { ++ bluesleep_hdev = hdev; ++ hu = (struct hci_uart *) hdev->driver_data; ++ state = (struct uart_state *) hu->tty->driver_data; ++ bsi->uport = state->uart_port; ++ } ++ break; ++ case HCI_DEV_UNREG: ++ bluesleep_hdev = NULL; ++ bsi->uport = NULL; ++ break; ++ case HCI_DEV_WRITE: ++ bluesleep_outgoing_data(); ++ break; ++ } ++ ++ return NOTIFY_DONE; ++} ++#endif ++ ++/** ++ * Function to check wheather bluetooth can sleep when btwrite was deasserted ++ * by bluedroid. ++ */ ++static void bluesleep_tx_allow_sleep(void) ++{ ++ unsigned long irq_flags; ++ BT_DBG("Tx has been idle\n"); ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ set_bit(BT_TXIDLE, &flags); ++ clear_bit(BT_TXDATA, &flags); ++ bluesleep_tx_idle(); ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++} ++ ++ ++/* Handles reception timer expiration. ++ * Clear BT_RXTIMER. ++ * @param data Not used. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t) ++#else ++static void bluesleep_rx_timer_expire(unsigned long data) ++#endif ++{ ++ BT_DBG("bluesleep_rx_timer_expire"); ++ clear_bit(BT_RXTIMER, &flags); ++ bluesleep_rx_idle(); ++} ++ ++/** ++ * Schedules a tasklet to run when receiving an interrupt on the ++ * HOST_WAKE GPIO pin. ++ * @param irq Not used. ++ * @param dev_id Not used. ++ */ ++static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id) ++{ ++ /* schedule a tasklet to handle the change in the host wake line */ ++ tasklet_schedule(&hostwake_task); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * Starts the Sleep-Mode Protocol on the Host. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++static int bluesleep_start(void) ++{ ++ int retval; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return 0; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ ++ if (!atomic_dec_and_test(&open_count)) { ++ atomic_inc(&open_count); ++ return -EBUSY; ++ } ++ ++ /* start the timer */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL*HZ)); ++ /*deassert BT_WAKE first*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ msleep(20); ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ retval = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr, ++ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, ++ "bluetooth hostwake", &bsi->pdev->dev); ++ if (retval < 0) { ++ BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ"); ++ goto fail; ++ } ++ ++ set_bit(BT_PROTO, &flags); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ ++ return 0; ++fail: ++ del_timer(&rx_timer); ++ atomic_inc(&open_count); ++ ++ return retval; ++} ++ ++/** ++ * Stops the Sleep-Mode Protocol on the Host. ++ */ ++static void bluesleep_stop(void) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (!test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return; ++ } ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ ++ del_timer(&rx_timer); ++ clear_bit(BT_PROTO, &flags); ++ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ clear_bit(BT_ASLEEP, &flags); ++ hsuart_power(1); ++ } ++ ++ atomic_inc(&open_count); ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++} ++#if 0 ++/** ++ * Read the BT_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the ++ * pin is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_btwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "btwake:%u\n", ++ (gpio_get_value(bsi->ext_wake) == bsi->ext_wake_assert)); ++} ++ ++/** ++ * Write the BT_WAKE GPIO pin value via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluepower_write_proc_btwake(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char *buf; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ buf = kmalloc(count, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ if (copy_from_user(buf, buffer, count)) { ++ kfree(buf); ++ return -EFAULT; ++ } ++ ++ if (buf[0] == '0') { ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } else if (buf[0] == '1') { ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ } else { ++ kfree(buf); ++ return -EINVAL; ++ } ++ ++ kfree(buf); ++ return count; ++} ++ ++/** ++ * Read the BT_HOST_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the pin ++ * is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_hostwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "hostwake: %u\n", ++ (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert)); ++} ++ ++ ++/** ++ * Read the low-power status of the Host via the proc interface. ++ * When this function returns, page contains a 1 if the Host ++ * is asleep, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_asleep(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int asleep; ++ ++ asleep = test_bit(BT_ASLEEP, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "asleep: %u\n", asleep); ++} ++ ++/** ++ * Read the low-power protocol being used by the Host via the proc interface. ++ * When this function returns, page will contain a 1 if the Host ++ * is using the Sleep Mode Protocol, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_proto(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int proto; ++ ++ proto = test_bit(BT_PROTO, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "proto: %u\n", proto); ++} ++ ++/** ++ * Modify the low-power protocol used by the Host via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluesleep_write_proc_proto(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char proto; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&proto, buffer, 1)) ++ return -EFAULT; ++ ++ if (proto == '0') ++ bluesleep_stop(); ++ else ++ bluesleep_start(); ++ ++ /* claim that we wrote everything */ ++ return count; ++} ++#endif ++ ++static int assert_level = -1; ++module_param(assert_level, int, S_IRUGO); ++MODULE_PARM_DESC(assert_level, "BT_LPM hostwake/btwake assert level"); ++ ++static struct platform_device *sw_uart_get_pdev(int id) ++{ ++ struct device_node *np; ++ char match[20]; ++ sprintf(match, "uart%d", id); ++ np = of_find_node_by_type(NULL, match); ++ return of_find_device_by_node(np); ++} ++ ++static int __init bluesleep_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device *dev = &pdev->dev; ++ enum of_gpio_flags config; ++ int ret, uart_index; ++ u32 val; ++ struct aicbsp_feature_t bsp_feature_lpm; ++ ++ bsi = devm_kzalloc(&pdev->dev, sizeof(struct bluesleep_info), ++ GFP_KERNEL); ++ if (!bsi) ++ return -ENOMEM; ++ ++ bsi->host_wake = of_get_named_gpio_flags(np, "bt_hostwake", 0, &config); ++ if (!gpio_is_valid(bsi->host_wake)) { ++ BT_ERR("get gpio bt_hostwake failed\n"); ++ ret = -EINVAL; ++ goto err0; ++ } ++ ++ /* set host_wake_assert */ ++ aicbsp_get_feature(&bsp_feature_lpm); ++ if (bsp_feature_lpm.irqf == 0) ++ bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ else ++ bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 1 : 0; ++ ++ BT_DBG("bt_hostwake gpio=%d assert=%d\n", bsi->host_wake, bsi->host_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->host_wake_assert = (assert_level & 0x02) > 0; ++ BT_DBG("override host_wake assert to %d", bsi->host_wake_assert); ++ } ++ ++ ret = devm_gpio_request(dev, bsi->host_wake, "bt_hostwake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_hostwake gpio %d\n", ++ bsi->host_wake); ++ goto err0; ++ } ++ ret = gpio_direction_input(bsi->host_wake); ++ if (ret < 0) { ++ BT_ERR("can't request input direction bt_wake gpio %d\n", ++ bsi->host_wake); ++ goto err1; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (!of_property_read_bool(np, "wakeup-source")) { ++#else ++ if (!of_property_read_u32(np, "wakeup-source", &bsi->wakeup_enable) && ++ (bsi->wakeup_enable == 0)) { ++#endif ++ BT_DBG("wakeup source is disabled!\n"); ++ } else { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ ret = device_init_wakeup(dev, true); ++ if (ret < 0) { ++ BT_ERR("device init wakeup failed!\n"); ++ goto err1; ++ } ++ ret = dev_pm_set_wake_irq(dev, gpio_to_irq(bsi->host_wake)); ++ if (ret < 0) { ++ BT_ERR("can't enable wakeup src for bt_hostwake %d\n", ++ bsi->host_wake); ++ goto err2; ++ } ++ bsi->wakeup_enable = 1; ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ } ++ ++ bsi->ext_wake = of_get_named_gpio_flags(np, "bt_wake", 0, &config); ++ if (!gpio_is_valid(bsi->ext_wake)) { ++ BT_ERR("get gpio bt_wake failed\n"); ++ ret = -EINVAL; ++ goto err2; ++ } ++ ++ ret = devm_gpio_request(dev, bsi->ext_wake, "bt_wake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err2; ++ } ++ ++ /* set ext_wake_assert */ ++ bsi->ext_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ BT_DBG("bt_wake gpio=%d assert=%d\n", bsi->ext_wake, bsi->ext_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->ext_wake_assert = (assert_level & 0x01) > 0; ++ BT_DBG("override ext_wake assert to %d", bsi->ext_wake_assert); ++ } ++ ++ /* 1.set bt_wake as output and the level is assert, assert bt wake */ ++ ret = gpio_direction_output(bsi->ext_wake, bsi->ext_wake_assert); ++ if (ret < 0) { ++ BT_ERR("can't request output direction bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err3; ++ } ++ /*set ext_wake deassert as default*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ ++ /* 2.get bt_host_wake gpio irq */ ++ bsi->host_wake_irq = gpio_to_irq(bsi->host_wake); ++ if (bsi->host_wake_irq < 0) { ++ BT_ERR("map gpio [%d] to virq failed, errno = %d\n", ++ bsi->host_wake, bsi->host_wake_irq); ++ ret = -ENODEV; ++ goto err3; ++ } ++ ++ uart_index = DEFAULT_UART_INDEX; ++ if (!of_property_read_u32(np, "uart_index", &val)) { ++ switch (val) { ++ case 0: ++ case 1: ++ case 2: ++ uart_index = val; ++ break; ++ default: ++ BT_ERR("unsupported uart_index (%u)\n", val); ++ } ++ } ++ BT_DBG("uart_index (%u)\n", uart_index); ++ bluesleep_uart_dev = sw_uart_get_pdev(uart_index); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ bsi->ws = wakeup_source_register(dev, "bluesleep"); ++#else ++ wake_lock_init(&bsi->wake_lock, WAKE_LOCK_SUSPEND, "bluesleep"); ++#endif ++ bsi->pdev = pdev; ++ ++ return 0; ++ ++err3: ++ devm_gpio_free(dev, bsi->ext_wake); ++err2: ++ device_init_wakeup(dev, false); ++err1: ++ devm_gpio_free(dev, bsi->host_wake); ++err0: ++ devm_kfree(dev, bsi); ++ ++ BT_ERR("probe fail, err: %d", ret); ++ return ret; ++} ++ ++static int bluesleep_remove(struct platform_device *pdev) ++{ ++ /* assert bt wake */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ if (test_bit(BT_PROTO, &flags)) { ++ if (disable_irq_wake(bsi->host_wake_irq)) ++ BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n"); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++ del_timer(&rx_timer); ++ if (test_bit(BT_ASLEEP, &flags)) ++ hsuart_power(1); ++ } ++ gpio_free(bsi->host_wake); ++ gpio_free(bsi->ext_wake); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ wakeup_source_unregister(bsi->ws); ++#else ++ wake_lock_destroy(&bsi->wake_lock); ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ if (bsi->wakeup_enable) { ++ BT_DBG("Deinit wakeup source"); ++ device_init_wakeup(&pdev->dev, false); ++ dev_pm_clear_wake_irq(&pdev->dev); ++ } ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ return 0; ++} ++ ++#ifdef CONFIG_AUTO_PM ++static int bluesleep_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ printk("%s\n", __func__); ++ ++ bluesleep_tx_allow_sleep(); ++ return 0; ++} ++ ++static int bluesleep_resume(struct platform_device *pdev) ++{ ++ printk("%s\n", __func__); ++ ++ bluesleep_outgoing_data(); ++ return 0; ++} ++#endif ++ ++static const struct of_device_id sunxi_btlpm_ids[] = { ++ { .compatible = "allwinner,sunxi-btlpm" }, ++ { /* Sentinel */ } ++}; ++ ++static struct platform_driver bluesleep_driver = { ++ .remove = bluesleep_remove, ++#ifdef CONFIG_AUTO_PM ++ .suspend = bluesleep_suspend, ++ .resume = bluesleep_resume, ++#endif ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "sunxi-btlpm", ++ .of_match_table = sunxi_btlpm_ids, ++ }, ++}; ++ ++/** ++ * Initializes the module. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++static int __init bluesleep_init(void) ++{ ++ int retval; ++ struct proc_dir_entry *ent; ++ ++ BT_DBG("BlueSleep Mode Driver Ver %s", VERSION); ++ ++ retval = platform_driver_probe(&bluesleep_driver, bluesleep_probe); ++ if (retval) ++ return retval; ++ ++#if !BT_BLUEDROID_SUPPORT ++ bluesleep_hdev = NULL; ++#endif ++ ++ bluetooth_dir = proc_mkdir("bluetooth", NULL); ++ if (bluetooth_dir == NULL) { ++ BT_ERR("Unable to create /proc/bluetooth directory"); ++ return -ENOMEM; ++ } ++ ++ sleep_dir = proc_mkdir("sleep", bluetooth_dir); ++ if (sleep_dir == NULL) { ++ BT_ERR("Unable to create /proc/%s directory", PROC_DIR); ++ return -ENOMEM; ++ } ++#if 0 ++ /* Creating read/write "btwake" entry */ ++ ent = create_proc_entry("btwake", 0, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluepower_read_proc_btwake; ++ ent->write_proc = bluepower_write_proc_btwake; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("hostwake", 0, sleep_dir, ++ bluepower_read_proc_hostwake, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* read/write proc entries */ ++ ent = create_proc_entry("proto", 0666, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluesleep_read_proc_proto; ++ ent->write_proc = bluesleep_write_proc_proto; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("asleep", 0, ++ sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++#if BT_BLUEDROID_SUPPORT ++ /* read/write proc entries */ ++ ent = proc_create("lpm", 0660, sleep_dir, &lpm_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/lpm entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ ent = proc_create("btwrite", 0660, sleep_dir, &btwrite_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwrite entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++ ++ flags = 0; /* clear all status bits */ ++ ++ /* Initialize spinlock. */ ++ spin_lock_init(&rw_lock); ++ ++ /* Initialize timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ timer_setup(&rx_timer, bluesleep_rx_timer_expire, 0); ++#else ++ init_timer(&rx_timer); ++ rx_timer.function = bluesleep_rx_timer_expire; ++ rx_timer.data = 0; ++#endif ++ ++ /* initialize host wake tasklet */ ++ tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); ++ ++#if !BT_BLUEDROID_SUPPORT ++ hci_register_notifier(&hci_event_nblock); ++#endif ++ ++ return 0; ++ ++fail: ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++ return retval; ++} ++ ++/** ++ * Cleans up the module. ++ */ ++static void __exit bluesleep_exit(void) ++{ ++#if !BT_BLUEDROID_SUPPORT ++ hci_unregister_notifier(&hci_event_nblock); ++#endif ++ platform_driver_unregister(&bluesleep_driver); ++ ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++} ++ ++module_init(bluesleep_init); ++module_exit(bluesleep_exit); ++ ++MODULE_DESCRIPTION("Bluetooth Sleep Mode Driver ver %s " VERSION); ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c +new file mode 100644 +index 000000000000..122d867f0ed6 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c +@@ -0,0 +1,88 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "lpm.h" ++#include "rfkill.h" ++ ++#define DRV_CONFIG_FW_NAME "fw.bin" ++#define DRV_DESCRIPTION "AIC BLUETOOTH" ++#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi" ++#define DRV_AUTHOR "AICSemi" ++#define DRV_VERS_MOD "1.0" ++ ++static struct platform_device *aicbt_pdev; ++ ++static struct platform_driver aicbt_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "aic_bt", ++ }, ++ //.probe = aicbt_probe, ++ //.remove = aicbt_remove, ++}; ++ ++static int __init aic_bluetooth_mod_init(void) ++{ ++ int ret; ++ printk("%s\n", __func__); ++ ret = platform_driver_register(&aicbt_driver); ++ if (ret) { ++ pr_err("register platform driver failed: %d\n", ret); ++ return ret; ++ } ++ ++ aicbt_pdev = platform_device_alloc("aic-bt", -1); ++ ret = platform_device_add(aicbt_pdev); ++ if (ret) { ++ pr_err("register platform device failed: %d\n", ret); ++ goto err0; ++ } ++ ++ ret = rfkill_bluetooth_init(aicbt_pdev); ++ if (ret) { ++ pr_err("rfkill init fail\n"); ++ goto err1; ++ } ++#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) ++ ret = bluesleep_init(aicbt_pdev); ++ if (ret) { ++ pr_err("bluesleep init fail\n"); ++ goto err2; ++ } ++#endif ++ ++ return 0; ++ ++#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) ++err2: ++#endif ++ rfkill_bluetooth_remove(aicbt_pdev); ++err1: ++ platform_device_del(aicbt_pdev); ++err0: ++ platform_driver_unregister(&aicbt_driver); ++ return ret; ++} ++ ++static void __exit aic_bluetooth_mod_exit(void) ++{ ++ printk("%s\n", __func__); ++#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) ++ bluesleep_exit(aicbt_pdev); ++#endif ++ rfkill_bluetooth_remove(aicbt_pdev); ++ platform_device_del(aicbt_pdev); ++ platform_driver_unregister(&aicbt_driver); ++} ++ ++module_init(aic_bluetooth_mod_init); ++module_exit(aic_bluetooth_mod_exit); ++ ++MODULE_DESCRIPTION(DRV_DESCRIPTION); ++MODULE_VERSION(DRV_VERS_MOD); ++MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h +new file mode 100644 +index 000000000000..88f6b565cd5f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h +@@ -0,0 +1,19 @@ ++#ifndef __AIC_BSP_EXPORT_H ++#define __AIC_BSP_EXPORT_H ++ ++#define AIC_BLUETOOTH 0 ++#define AIC_WIFI 1 ++#define AIC_PWR_OFF 0 ++#define AIC_PWR_ON 1 ++ ++struct aicbsp_feature_t { ++ bool band_5g_support; ++ uint32_t sdio_clock; ++ uint8_t sdio_phase; ++ uint8_t irqf; ++}; ++ ++int aicbsp_set_subsys(int, int); ++int aicbsp_get_feature(struct aicbsp_feature_t *feature); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c +new file mode 100644 +index 000000000000..6e9b71564f19 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c +@@ -0,0 +1,1111 @@ ++/* ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ */ ++ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#endif ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++#include ++#endif ++ ++/* ++ * #define BT_SLEEP_DBG ++ */ ++#define BT_SLEEP_DBG ++#undef BT_DBG ++#undef BT_ERR ++#ifdef BT_SLEEP_DBG ++#define BT_DBG(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++#else ++#define BT_DBG(fmt, arg...) ++#endif ++#define BT_ERR(fmt, arg...) pr_debug("[BT_LPM] %s: " fmt "\n",\ ++ __func__, ## arg) ++ ++/* ++ * Defines ++ */ ++ ++#define VERSION "1.3.3" ++#define PROC_DIR "bluetooth/sleep" ++ ++#define DEFAULT_UART_INDEX 1 ++#define BT_BLUEDROID_SUPPORT 1 ++static int bluesleep_start(void); ++static void bluesleep_stop(void); ++ ++struct bluesleep_info { ++ unsigned int wakeup_enable; ++ unsigned host_wake; ++ unsigned ext_wake; ++ unsigned host_wake_irq; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ struct wakeup_source *ws; ++#else ++ struct wake_lock wake_lock; ++#endif ++ struct uart_port *uport; ++ unsigned host_wake_assert:1; ++ unsigned ext_wake_assert:1; ++ struct platform_device *pdev; ++}; ++ ++/* work function */ ++static void bluesleep_sleep_work(struct work_struct *work); ++static void bluesleep_tx_allow_sleep(void); ++ ++/* work queue */ ++DECLARE_DELAYED_WORK(sleep_workqueue, bluesleep_sleep_work); ++ ++/* Macros for handling sleep work */ ++#define bluesleep_rx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_busy() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_rx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++#define bluesleep_tx_idle() schedule_delayed_work(&sleep_workqueue, 0) ++ ++/* 1 second timeout */ ++#define RX_TIMER_INTERVAL 1 ++ ++/* state variable names and bit positions */ ++#define BT_PROTO 0x01 ++#define BT_TXDATA 0x02 ++#define BT_ASLEEP 0x04 ++#define BT_RXTIMER 0x20 ++#define BT_TXIDLE 0x08 ++ ++#if BT_BLUEDROID_SUPPORT ++static bool has_lpm_enabled; ++#else ++/* global pointer to a single hci device. */ ++static struct hci_dev *bluesleep_hdev; ++#endif ++ ++#if BT_BLUEDROID_SUPPORT ++static struct platform_device *bluesleep_uart_dev; ++#endif ++static struct bluesleep_info *bsi; ++ ++/* module usage */ ++static atomic_t open_count = ATOMIC_INIT(1); ++ ++/* ++ * Local function prototypes ++ */ ++ ++#if !BT_BLUEDROID_SUPPORT ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data); ++#endif ++ ++/* ++ * Global variables ++ */ ++ ++/** Global state flags */ ++static unsigned long flags; ++ ++/** Tasklet to respond to change in hostwake line */ ++static struct tasklet_struct hostwake_task; ++ ++/** Reception timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t); ++#else ++static void bluesleep_rx_timer_expire(unsigned long data); ++#endif ++static struct timer_list rx_timer; ++ ++/** Lock for state transitions */ ++static spinlock_t rw_lock; ++ ++#if !BT_BLUEDROID_SUPPORT ++/** Notifier block for HCI events */ ++struct notifier_block hci_event_nblock = { ++ .notifier_call = bluesleep_hci_event, ++}; ++#endif ++ ++struct proc_dir_entry *bluetooth_dir, *sleep_dir; ++ ++/* ++ * Local functions ++ */ ++ ++/* ++ * bt go to sleep will call this function tell uart stop data interactive ++ */ ++static void hsuart_power(int on) ++{ ++ if (bsi->uport != NULL) { ++ if (on) ++ bsi->uport->ops->set_mctrl(bsi->uport, TIOCM_RTS); ++ else ++ bsi->uport->ops->set_mctrl(bsi->uport, 0); ++ } else { ++ BT_ERR("bsi->uport = NULL, has_lpm_enabled = %d", has_lpm_enabled); ++ } ++} ++ ++/** ++ * @return 1 if the Host can go to sleep, 0 otherwise. ++ */ ++static inline int bluesleep_can_sleep(void) ++{ ++ /* check if HOST_WAKE_BT_GPIO and BT_WAKE_HOST_GPIO ++ * are both deasserted ++ */ ++ return (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) && ++ (gpio_get_value(bsi->host_wake) != bsi->host_wake_assert) && ++ (!test_bit(BT_RXTIMER, &flags)) && (bsi->uport != NULL); ++} ++ ++/** ++ * @brief@ main sleep work handling function which update the flags ++ * and activate and deactivate UART ,check FIFO. ++ */ ++static void bluesleep_sleep_work(struct work_struct *work) ++{ ++ if (!has_lpm_enabled) ++ return; ++ ++ if (bluesleep_can_sleep()) { ++ /* already asleep, this is an error case */ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("already asleep"); ++ return; ++ } ++ if (bsi->uport->ops->tx_empty(bsi->uport)) { ++ BT_DBG("going to sleep..."); ++ set_bit(BT_ASLEEP, &flags); ++ /*Deactivating UART */ ++ hsuart_power(0); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++ } else { ++ BT_DBG("This should never happen.\n"); ++ return; ++ } ++ } else if (test_bit(BT_ASLEEP, &flags)) { ++ BT_DBG("hold wake locks for rx_task."); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ clear_bit(BT_ASLEEP, &flags); ++ ++ /* Add a timer to make sure that UART ++ * would not be turned on&off very frequentently ++ */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ ++ set_bit(BT_RXTIMER, &flags); ++ hsuart_power(1); ++ } else { ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); ++ if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert ++ && !test_bit(BT_TXIDLE, &flags)) { ++ BT_DBG("force retrigger bt wake:%lx", flags); ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ msleep(20); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } ++ } ++} ++ ++/** ++ * A tasklet function that runs in tasklet context and reads the value ++ * of the HOST_WAKE GPIO pin and further defer the work. ++ * @param data Not used. ++ */ ++static void bluesleep_hostwake_task(unsigned long data) ++{ ++ BT_DBG("hostwake line change"); ++ spin_lock(&rw_lock); ++ ++ if (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert) ++ bluesleep_rx_busy(); ++ else ++ bluesleep_rx_idle(); ++ ++ spin_unlock(&rw_lock); ++} ++ ++/** ++ * Handles proper timer action when outgoing data is delivered to the ++ * HCI line discipline. Sets BT_TXDATA. ++ */ ++static void bluesleep_outgoing_data(void) ++{ ++ unsigned long irq_flags; ++ int power_on_uart = 0; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ /* if the tx side is sleeping... */ ++ if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) { ++ BT_DBG("tx was sleeping, wakeup it"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ clear_bit(BT_ASLEEP, &flags); ++ clear_bit(BT_TXIDLE, &flags); ++ power_on_uart = 1; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ if (power_on_uart == 1) ++ hsuart_power(1); ++} ++ ++#if BT_BLUEDROID_SUPPORT ++static struct uart_port *bluesleep_get_uart_port(void) ++{ ++ struct uart_port *uport = NULL; ++ ++ if (bluesleep_uart_dev) { ++ uport = platform_get_drvdata(bluesleep_uart_dev); ++ if (uport) ++ BT_DBG( ++ "%s get uart_port from blusleep_uart_dev: %s, port irq: %d", ++ __func__, bluesleep_uart_dev->name, uport->irq); ++ } ++ return uport; ++} ++ ++static int bluesleep_lpm_proc_show(struct seq_file *m, void *v) ++{ ++ seq_printf(m, "lpm enable: %d\n", has_lpm_enabled); ++ return 0; ++} ++ ++static int bluesleep_lpm_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_lpm_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_lpm(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ if (b == '0') { ++ /* HCI_DEV_UNREG */ ++ bluesleep_stop(); ++ has_lpm_enabled = false; ++ bsi->uport = NULL; ++ } else { ++ /* HCI_DEV_REG */ ++ if (!has_lpm_enabled) { ++ has_lpm_enabled = true; ++ if (bluesleep_uart_dev) ++ bsi->uport = bluesleep_get_uart_port(); ++ ++ /* if bluetooth started, start bluesleep*/ ++ bluesleep_start(); ++ } ++ } ++ ++ return count; ++} ++ ++static int bluesleep_btwrite_proc_show(struct seq_file *m, void *v) ++{ ++ seq_puts(m, "it's not support\n"); ++ return 0; ++} ++ ++static int bluesleep_btwrite_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bluesleep_btwrite_proc_show, NULL); ++} ++ ++static ssize_t bluesleep_write_proc_btwrite(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos) ++{ ++ char b; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&b, buffer, 1)) ++ return -EFAULT; ++ ++ /* HCI_DEV_WRITE */ ++ if (b != '0') ++ bluesleep_outgoing_data(); ++ else ++ bluesleep_tx_allow_sleep(); ++ ++ return count; ++} ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0) ++static const struct proc_ops lpm_fops = { ++ .proc_open = bluesleep_lpm_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_lpm, ++}; ++static const struct proc_ops btwrite_fops = { ++ .proc_open = bluesleep_btwrite_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = bluesleep_write_proc_btwrite, ++}; ++#else ++static const struct file_operations lpm_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_lpm_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_lpm, ++}; ++static const struct file_operations btwrite_fops = { ++ .owner = THIS_MODULE, ++ .open = bluesleep_btwrite_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = bluesleep_write_proc_btwrite, ++}; ++#endif ++#else ++/** ++ * Handles HCI device events. ++ * @param this Not used. ++ * @param event The event that occurred. ++ * @param data The HCI device associated with the event. ++ * @return NOTIFY_DONE. ++ */ ++static int bluesleep_hci_event(struct notifier_block *this, ++ unsigned long event, void *data) ++{ ++ struct hci_dev *hdev = (struct hci_dev *) data; ++ struct hci_uart *hu; ++ struct uart_state *state; ++ ++ if (!hdev) ++ return NOTIFY_DONE; ++ ++ switch (event) { ++ case HCI_DEV_REG: ++ if (!bluesleep_hdev) { ++ bluesleep_hdev = hdev; ++ hu = (struct hci_uart *) hdev->driver_data; ++ state = (struct uart_state *) hu->tty->driver_data; ++ bsi->uport = state->uart_port; ++ } ++ break; ++ case HCI_DEV_UNREG: ++ bluesleep_hdev = NULL; ++ bsi->uport = NULL; ++ break; ++ case HCI_DEV_WRITE: ++ bluesleep_outgoing_data(); ++ break; ++ } ++ ++ return NOTIFY_DONE; ++} ++#endif ++ ++/** ++ * Function to check wheather bluetooth can sleep when btwrite was deasserted ++ * by bluedroid. ++ */ ++static void bluesleep_tx_allow_sleep(void) ++{ ++ unsigned long irq_flags; ++ BT_DBG("Tx has been idle\n"); ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ set_bit(BT_TXIDLE, &flags); ++ bluesleep_tx_idle(); ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++} ++ ++ ++/* Handles reception timer expiration. ++ * Clear BT_RXTIMER. ++ * @param data Not used. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static void bluesleep_rx_timer_expire(struct timer_list *t) ++#else ++static void bluesleep_rx_timer_expire(unsigned long data) ++#endif ++{ ++ BT_DBG("bluesleep_rx_timer_expire"); ++ clear_bit(BT_RXTIMER, &flags); ++ bluesleep_rx_idle(); ++} ++ ++/** ++ * Schedules a tasklet to run when receiving an interrupt on the ++ * HOST_WAKE GPIO pin. ++ * @param irq Not used. ++ * @param dev_id Not used. ++ */ ++static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id) ++{ ++ /* schedule a tasklet to handle the change in the host wake line */ ++ tasklet_schedule(&hostwake_task); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * Starts the Sleep-Mode Protocol on the Host. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++static int bluesleep_start(void) ++{ ++ int retval; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return 0; ++ } ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ ++ if (!atomic_dec_and_test(&open_count)) { ++ atomic_inc(&open_count); ++ return -EBUSY; ++ } ++ ++ /* start the timer */ ++ mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL*HZ)); ++ /*deassert BT_WAKE first*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ msleep(20); ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ retval = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr, ++ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, ++ "bluetooth hostwake", &bsi->pdev->dev); ++ if (retval < 0) { ++ BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ"); ++ goto fail; ++ } ++ ++ set_bit(BT_PROTO, &flags); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_stay_awake(bsi->ws); ++#else ++ wake_lock(&bsi->wake_lock); ++#endif ++ ++ return 0; ++fail: ++ del_timer(&rx_timer); ++ atomic_inc(&open_count); ++ ++ return retval; ++} ++ ++/** ++ * Stops the Sleep-Mode Protocol on the Host. ++ */ ++static void bluesleep_stop(void) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&rw_lock, irq_flags); ++ ++ if (!test_bit(BT_PROTO, &flags)) { ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ return; ++ } ++ ++ /* assert BT_WAKE */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ ++ del_timer(&rx_timer); ++ clear_bit(BT_PROTO, &flags); ++ ++ if (test_bit(BT_ASLEEP, &flags)) { ++ clear_bit(BT_ASLEEP, &flags); ++ hsuart_power(1); ++ } ++ ++ atomic_inc(&open_count); ++ ++ spin_unlock_irqrestore(&rw_lock, irq_flags); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ __pm_wakeup_event(bsi->ws, HZ / 2); ++#else ++ wake_lock_timeout(&bsi->wake_lock, HZ / 2); ++#endif ++} ++#if 0 ++/** ++ * Read the BT_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the ++ * pin is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_btwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "btwake:%u\n", ++ (gpio_get_value(bsi->ext_wake) == bsi->ext_wake_assert)); ++} ++ ++/** ++ * Write the BT_WAKE GPIO pin value via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluepower_write_proc_btwake(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char *buf; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ buf = kmalloc(count, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ if (copy_from_user(buf, buffer, count)) { ++ kfree(buf); ++ return -EFAULT; ++ } ++ ++ if (buf[0] == '0') { ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ } else if (buf[0] == '1') { ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ } else { ++ kfree(buf); ++ return -EINVAL; ++ } ++ ++ kfree(buf); ++ return count; ++} ++ ++/** ++ * Read the BT_HOST_WAKE GPIO pin value via the proc interface. ++ * When this function returns, page will contain a 1 if the pin ++ * is high, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluepower_read_proc_hostwake(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ *eof = 1; ++ return sprintf(page, "hostwake: %u\n", ++ (gpio_get_value(bsi->host_wake) == bsi->host_wake_assert)); ++} ++ ++ ++/** ++ * Read the low-power status of the Host via the proc interface. ++ * When this function returns, page contains a 1 if the Host ++ * is asleep, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_asleep(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int asleep; ++ ++ asleep = test_bit(BT_ASLEEP, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "asleep: %u\n", asleep); ++} ++ ++/** ++ * Read the low-power protocol being used by the Host via the proc interface. ++ * When this function returns, page will contain a 1 if the Host ++ * is using the Sleep Mode Protocol, 0 otherwise. ++ * @param page Buffer for writing data. ++ * @param start Not used. ++ * @param offset Not used. ++ * @param count Not used. ++ * @param eof Whether or not there is more data to be read. ++ * @param data Not used. ++ * @return The number of bytes written. ++ */ ++static int bluesleep_read_proc_proto(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ unsigned int proto; ++ ++ proto = test_bit(BT_PROTO, &flags) ? 1 : 0; ++ *eof = 1; ++ return sprintf(page, "proto: %u\n", proto); ++} ++ ++/** ++ * Modify the low-power protocol used by the Host via the proc interface. ++ * @param file Not used. ++ * @param buffer The buffer to read from. ++ * @param count The number of bytes to be written. ++ * @param data Not used. ++ * @return On success, the number of bytes written. On error, -1, and ++ * errno is set appropriately. ++ */ ++static int bluesleep_write_proc_proto(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char proto; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&proto, buffer, 1)) ++ return -EFAULT; ++ ++ if (proto == '0') ++ bluesleep_stop(); ++ else ++ bluesleep_start(); ++ ++ /* claim that we wrote everything */ ++ return count; ++} ++#endif ++ ++static int assert_level = -1; ++module_param(assert_level, int, S_IRUGO); ++MODULE_PARM_DESC(assert_level, "BT_LPM hostwake/btwake assert level"); ++ ++#if 1 ++static struct platform_device *sw_uart_get_pdev(int id) ++{ ++ struct device_node *np; ++ char match[20]; ++ sprintf(match, "uart%d", id); ++ np = of_find_node_by_type(NULL, match); ++ return of_find_device_by_node(np); ++} ++#endif ++ ++static int bluesleep_probe(struct platform_device *pdev) ++{ ++#if 1 ++ struct device_node *np = of_find_compatible_node(NULL, NULL, "allwinner,sunxi-btlpm"); ++ struct device *dev = &pdev->dev; ++ enum of_gpio_flags config; ++ int ret, uart_index; ++ u32 val; ++ ++ bsi = devm_kzalloc(&pdev->dev, sizeof(struct bluesleep_info), ++ GFP_KERNEL); ++ if (!bsi) ++ return -ENOMEM; ++ ++ bsi->host_wake = of_get_named_gpio_flags(np, "bt_hostwake", 0, &config); ++ if (!gpio_is_valid(bsi->host_wake)) { ++ BT_ERR("get gpio bt_hostwake failed\n"); ++ ret = -EINVAL; ++ goto err0; ++ } ++ ++ /* set host_wake_assert */ ++ bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ BT_DBG("bt_hostwake gpio=%d assert=%d\n", bsi->host_wake, bsi->host_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->host_wake_assert = (assert_level & 0x02) > 0; ++ BT_DBG("override host_wake assert to %d", bsi->host_wake_assert); ++ } ++ ++ ret = devm_gpio_request(dev, bsi->host_wake, "bt_hostwake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_hostwake gpio %d\n", ++ bsi->host_wake); ++ goto err0; ++ } ++ ret = gpio_direction_input(bsi->host_wake); ++ if (ret < 0) { ++ BT_ERR("can't request input direction bt_wake gpio %d\n", ++ bsi->host_wake); ++ goto err1; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (!of_property_read_bool(np, "wakeup-source")) { ++#else ++ if (!of_property_read_u32(np, "wakeup-source", &bsi->wakeup_enable) && ++ (bsi->wakeup_enable == 0)) { ++#endif ++ BT_DBG("wakeup source is disabled!\n"); ++ } else { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ ret = device_init_wakeup(dev, true); ++ if (ret < 0) { ++ BT_ERR("device init wakeup failed!\n"); ++ goto err1; ++ } ++ ret = dev_pm_set_wake_irq(dev, gpio_to_irq(bsi->host_wake)); ++ if (ret < 0) { ++ BT_ERR("can't enable wakeup src for bt_hostwake %d\n", ++ bsi->host_wake); ++ goto err2; ++ } ++ bsi->wakeup_enable = 1; ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ } ++ ++ bsi->ext_wake = of_get_named_gpio_flags(np, "bt_wake", 0, &config); ++ if (!gpio_is_valid(bsi->ext_wake)) { ++ BT_ERR("get gpio bt_wake failed\n"); ++ ret = -EINVAL; ++ goto err2; ++ } ++ ++ ret = devm_gpio_request(dev, bsi->ext_wake, "bt_wake"); ++ if (ret < 0) { ++ BT_ERR("can't request bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err2; ++ } ++ ++ /* set ext_wake_assert */ ++ bsi->ext_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ BT_DBG("bt_wake gpio=%d assert=%d\n", bsi->ext_wake, bsi->ext_wake_assert); ++ ++ if (assert_level != -1) { ++ bsi->ext_wake_assert = (assert_level & 0x01) > 0; ++ BT_DBG("override ext_wake assert to %d", bsi->ext_wake_assert); ++ } ++ ++ /* 1.set bt_wake as output and the level is assert, assert bt wake */ ++ ret = gpio_direction_output(bsi->ext_wake, bsi->ext_wake_assert); ++ if (ret < 0) { ++ BT_ERR("can't request output direction bt_wake gpio %d\n", ++ bsi->ext_wake); ++ goto err3; ++ } ++ /*set ext_wake deassert as default*/ ++ gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); ++ ++ /* 2.get bt_host_wake gpio irq */ ++ bsi->host_wake_irq = gpio_to_irq(bsi->host_wake); ++ if (bsi->host_wake_irq < 0) { ++ BT_ERR("map gpio [%d] to virq failed, errno = %d\n", ++ bsi->host_wake, bsi->host_wake_irq); ++ ret = -ENODEV; ++ goto err3; ++ } ++ ++ uart_index = DEFAULT_UART_INDEX; ++ if (!of_property_read_u32(np, "uart_index", &val)) { ++ switch (val) { ++ case 0: ++ case 1: ++ case 2: ++ uart_index = val; ++ break; ++ default: ++ BT_ERR("unsupported uart_index (%u)\n", val); ++ } ++ } ++ BT_DBG("uart_index (%u)\n", uart_index); ++ bluesleep_uart_dev = sw_uart_get_pdev(uart_index); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ bsi->ws = wakeup_source_register(dev, "bluesleep"); ++#else ++ bsi->ws = wakeup_source_register("bluesleep"); ++#endif ++ ++#else ++ wake_lock_init(&bsi->wake_lock, WAKE_LOCK_SUSPEND, "bluesleep"); ++#endif ++ bsi->pdev = pdev; ++ ++ return 0; ++ ++err3: ++ devm_gpio_free(dev, bsi->ext_wake); ++err2: ++ device_init_wakeup(dev, false); ++err1: ++ devm_gpio_free(dev, bsi->host_wake); ++err0: ++ devm_kfree(dev, bsi); ++ ++ BT_ERR("probe fail, err: %d", ret); ++ return ret; ++#endif ++ return 0; ++} ++ ++static int bluesleep_remove(struct platform_device *pdev) ++{ ++ /* assert bt wake */ ++ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); ++ if (test_bit(BT_PROTO, &flags)) { ++ if (disable_irq_wake(bsi->host_wake_irq)) ++ BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n"); ++ free_irq(bsi->host_wake_irq, &bsi->pdev->dev); ++ del_timer(&rx_timer); ++ if (test_bit(BT_ASLEEP, &flags)) ++ hsuart_power(1); ++ } ++ gpio_free(bsi->host_wake); ++ gpio_free(bsi->ext_wake); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ wakeup_source_unregister(bsi->ws); ++#else ++ wake_lock_destroy(&bsi->wake_lock); ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ if (bsi->wakeup_enable) { ++ BT_DBG("Deinit wakeup source"); ++ device_init_wakeup(&pdev->dev, false); ++ dev_pm_clear_wake_irq(&pdev->dev); ++ } ++#else ++ BT_ERR("%s kernel unsupport this feature!\r\n", __func__); ++#endif ++ return 0; ++} ++ ++/** ++ * Initializes the module. ++ * @return On success, 0. On error, -1, and errno is set ++ * appropriately. ++ */ ++int bluesleep_init(struct platform_device *pdev) ++{ ++ int retval; ++ struct proc_dir_entry *ent; ++ ++ BT_DBG("BlueSleep Mode Driver Ver %s", VERSION); ++ ++#if 1 ++ retval = bluesleep_probe(pdev); ++ if (retval) ++ return retval; ++#endif ++ ++#if !BT_BLUEDROID_SUPPORT ++ bluesleep_hdev = NULL; ++#endif ++ ++ bluetooth_dir = proc_mkdir("bluetooth", NULL); ++ if (bluetooth_dir == NULL) { ++ BT_ERR("Unable to create /proc/bluetooth directory"); ++ return -ENOMEM; ++ } ++ ++ sleep_dir = proc_mkdir("sleep", bluetooth_dir); ++ if (sleep_dir == NULL) { ++ BT_ERR("Unable to create /proc/%s directory", PROC_DIR); ++ return -ENOMEM; ++ } ++#if 0 ++ /* Creating read/write "btwake" entry */ ++ ent = create_proc_entry("btwake", 0, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluepower_read_proc_btwake; ++ ent->write_proc = bluepower_write_proc_btwake; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("hostwake", 0, sleep_dir, ++ bluepower_read_proc_hostwake, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* read/write proc entries */ ++ ent = create_proc_entry("proto", 0666, sleep_dir); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ent->read_proc = bluesleep_read_proc_proto; ++ ent->write_proc = bluesleep_write_proc_proto; ++ ++ /* read only proc entries */ ++ if (create_proc_read_entry("asleep", 0, ++ sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) { ++ BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++#if BT_BLUEDROID_SUPPORT ++ /* read/write proc entries */ ++ ent = proc_create("lpm", 0660, sleep_dir, &lpm_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/lpm entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ ent = proc_create("btwrite", 0660, sleep_dir, &btwrite_fops); ++ if (ent == NULL) { ++ BT_ERR("Unable to create /proc/%s/btwrite entry", PROC_DIR); ++ retval = -ENOMEM; ++ goto fail; ++ } ++#endif ++ ++ flags = 0; /* clear all status bits */ ++ ++ /* Initialize spinlock. */ ++ spin_lock_init(&rw_lock); ++ ++ /* Initialize timer */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ timer_setup(&rx_timer, bluesleep_rx_timer_expire, 0); ++#else ++ init_timer(&rx_timer); ++ rx_timer.function = bluesleep_rx_timer_expire; ++ rx_timer.data = 0; ++#endif ++ ++ /* initialize host wake tasklet */ ++ tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); ++ ++#if !BT_BLUEDROID_SUPPORT ++ hci_register_notifier(&hci_event_nblock); ++#endif ++ ++ return 0; ++ ++fail: ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++ return retval; ++} ++ ++/** ++ * Cleans up the module. ++ */ ++int bluesleep_exit(struct platform_device *dev) ++{ ++#if !BT_BLUEDROID_SUPPORT ++ hci_unregister_notifier(&hci_event_nblock); ++#endif ++ ++#if BT_BLUEDROID_SUPPORT ++ remove_proc_entry("btwrite", sleep_dir); ++ remove_proc_entry("lpm", sleep_dir); ++#endif ++#if 0 ++ remove_proc_entry("asleep", sleep_dir); ++ remove_proc_entry("proto", sleep_dir); ++ remove_proc_entry("hostwake", sleep_dir); ++ remove_proc_entry("btwake", sleep_dir); ++#endif ++ remove_proc_entry("sleep", bluetooth_dir); ++ remove_proc_entry("bluetooth", 0); ++ bluesleep_remove(dev); ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h +new file mode 100644 +index 000000000000..0ff9dca14c0b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2015 Spreadtrum Communications Inc. ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __LPM_H ++#define __LPM_H ++ ++int bluesleep_init(struct platform_device *pdev); ++int bluesleep_exit(struct platform_device *dev); ++ ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c +new file mode 100644 +index 000000000000..5caf3f83a03a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c +@@ -0,0 +1,81 @@ ++/* ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aic_bsp_export.h" ++ ++static struct rfkill *bt_rfk; ++static const char bt_name[] = "bluetooth"; ++ ++static int bluetooth_set_power(void *data, bool blocked) ++{ ++ pr_info("%s: start_block=%d\n", __func__, blocked); ++ if (!blocked) { ++ aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON); ++ } else { ++ aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_OFF); ++ } ++ ++ pr_info("%s: end_block=%d\n", __func__, blocked); ++ return 0; ++} ++ ++static struct rfkill_ops rfkill_bluetooth_ops = { ++ .set_block = bluetooth_set_power, ++}; ++ ++int rfkill_bluetooth_init(struct platform_device *pdev) ++{ ++ ++ int rc = 0; ++ ++ pr_info("-->%s\n", __func__); ++ bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH, ++ &rfkill_bluetooth_ops, NULL); ++ if (!bt_rfk) { ++ rc = -ENOMEM; ++ goto err_rfkill_alloc; ++ } ++ /* userspace cannot take exclusive control */ ++ rfkill_init_sw_state(bt_rfk, true); ++ rc = rfkill_register(bt_rfk); ++ if (rc) ++ goto err_rfkill_reg; ++ ++ pr_info("<--%s\n", __func__); ++ ++ return 0; ++ ++err_rfkill_reg: ++ rfkill_destroy(bt_rfk); ++err_rfkill_alloc: ++ return rc; ++} ++ ++int rfkill_bluetooth_remove(struct platform_device *dev) ++{ ++ pr_info("-->%s\n", __func__); ++ rfkill_unregister(bt_rfk); ++ rfkill_destroy(bt_rfk); ++ pr_info("<--%s\n", __func__); ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h +new file mode 100644 +index 000000000000..ce0d5761a960 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h +@@ -0,0 +1,17 @@ ++/* ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef __RFKILL_H__ ++#define __RFKILL_H__ ++ ++int rfkill_bluetooth_init(struct platform_device *pdev); ++int rfkill_bluetooth_remove(struct platform_device *pdev); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore +new file mode 100644 +index 000000000000..c3c2d151e157 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig +new file mode 100644 +index 000000000000..c26f2b4af23c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig +@@ -0,0 +1,5 @@ ++config AIC8800_WLAN_SUPPORT ++ tristate "AIC8800 wlan Support" ++ help ++ This is support for aic wifi driver. ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile +new file mode 100644 +index 000000000000..558f3818b8e2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile +@@ -0,0 +1,424 @@ ++EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) ++EXTRA_CFLAGS += -Wno-implicit-fallthrough ++#EXTRA_CFLAGS += -Wno-unused-function ++#EXTRA_CFLAGS += -Wno-maybe-uninitialized ++#EXTRA_CFLAGS += -Wno-unused-variable ++ ++RWNX_VERS_NUM := 6.4.3.0 ++ ++CONFIG_COUNTRY_CODE = "00" ++ ++MODULE_NAME = aic8800_fdrv ++CONFIG_AIC8800_WLAN_SUPPORT = m ++ ++# Support of bootrom start ++CONFIG_START_FROM_BOOTROM = y ++ ++# Support of pmic setting, new version bootrom avaliable ++CONFIG_PMIC_SETTING ?=y ++ ++# Select 8800DC/DW DCDC_VRF mode, check your board ++CONFIG_VRF_DCDC_MODE = y ++ ++ ++# ROM patch enabled option ++CONFIG_ROM_PATCH_EN ?=y ++# Support chip with mcu ++CONFIG_MCU_INTEGRATED ?= n ++CONFIG_MCU_MESSAGE ?= n ++ifeq ($(CONFIG_MCU_INTEGRATED), y) ++CONFIG_PMIC_SETTING = n ++else ++CONFIG_MCU_MESSAGE ?= n ++endif ++ ++# ++# WAITING FOR KCONFIG { ++# ++CONFIG_RWNX_FULLMAC ?= y ++CONFIG_RWNX_FHOST ?= n ++ ++# ++# DEBUG OPTIONS ++CONFIG_RWNX_UM_HELPER_DFLT ?= "/dini/dini_bin/rwnx_umh.sh" ++ ++# ++# FW ARCH: ++CONFIG_RWNX_SDM ?= n ++CONFIG_RWNX_TL4 ?= n ++ ++# IPC version ++CONFIG_RWNX_OLD_IPC ?= n ++ ++# Support of P2P DebugFS for enabling/disabling NoA and OppPS ++CONFIG_RWNX_P2P_DEBUGFS := n ++# ++# } // WAITING FOR KCONFIG ++# ++ ++# Enable A-MSDU support (need FW support) ++## Select this if FW is compiled with AMSDU support ++CONFIG_RWNX_SPLIT_TX_BUF ?= n ++## Select this TO send AMSDU ++CONFIG_RWNX_AMSDUS_TX ?= n ++ ++# Enable BFMER support (need FW support) ++CONFIG_RWNX_BFMER ?= n ++ ++CONFIG_SDIO_SUPPORT =y ++CONFIG_USB_SUPPORT =n ++CONFIG_RX_REORDER ?=y ++CONFIG_ARP_OFFLOAD =y ++CONFIG_RADAR_OR_IR_DETECT =n ++CONFIG_DOWNLOAD_FW =n ++CONFIG_RFTEST=y ++CONFIG_USB_BT =y ++CONFIG_SDIO_BT=n ++CONFIG_USE_5G ?= y ++CONFIG_CREATE_TRACE_POINTS = n ++CONFIG_TXRX_THREAD_PRIO = y ++# CONFIG_COEX = n for BT_ONLY, CONFIG_COEX =y for combo and sw ++CONFIG_COEX = y ++CONFIG_RX_NETIF_RECV_SKB = y ++CONFIG_SET_VENDOR_EXTENSION_IE = n ++CONFIG_SUPPORT_REALTIME_CHANGE_MAC = y ++CONFIG_WPA3_FOR_OLD_KERNEL ?= n ++CONFIG_VHT_FOR_OLD_KERNEL ?= n ++CONFIG_HE_FOR_OLD_KERNEL ?= n ++CONFIG_PREALLOC_RX_SKB ?= n ++CONFIG_WIFI_SUSPEND_FOR_LINUX = n ++# Need to set fw path in BOARD_KERNEL_CMDLINE ++CONFIG_USE_FW_REQUEST ?= n ++CONFIG_USE_P2P0=n ++CONFIG_TX_NETIF_FLOWCTRL = n ++CONFIG_ONE_TXQ = n ++CONFIG_BR_SUPPORT =n ++BR_NAME = br0 ++CONFIG_FDRV_NO_REG_SDIO=n ++CONFIG_SCHED_SCAN = n ++CONFIG_OOB ?= n ++CONFIG_USE_CUSTOMER_MAC = n ++CONFIG_PREALLOC_TXQ ?= y ++CONFIG_DPD = y ++CONFIG_FORCE_DPD_CALIB = y ++CONFIG_LOFT_CALIB = n ++CONFIG_FILTER_TCP_ACK =y ++CONFIG_RESV_MEM_SUPPORT ?= y ++CONFIG_GKI = n ++CONFIG_TEMP_COMP = n ++CONFIG_TEMP_CONTROL = n ++CONFIG_EXT_FEM_8800DCDW = n ++CONFIG_SHUTDOWN_CALLBACK = y ++CONFIG_FOR_IPCAM = n ++CONFIG_SDIO_ADMA = n ++# CONFIG_MCC = n for sta and p2p concurrent in same channel. ++CONFIG_MCC = y ++CONFIG_APF = n ++CONFIG_POWER_LIMIT = n ++ ++#CONFIG FOR LOW POWER MODE ++CONFIG_SDIO_PWRCTRL ?= y ++CONFIG_GPIO_WAKEUP ?= n ++CONFIG_AUTO_POWERSAVE = n ++ ++# Enable wifi-hal Latency Mode ++CONFIG_AICWF_LATENCY_MODE = n ++ ++ifneq ($(CONFIG_WIRELESS_EXT), y) ++CONFIG_USE_WIRELESS_EXT = n ++endif ++ ++ifeq ($(CONFIG_EXT_FEM_8800DCDW), y) ++CONFIG_DPD = n ++CONFIG_FORCE_DPD_CALIB = n ++CONFIG_LOFT_CALIB = y ++endif ++ ++# Support of MU-MIMO transmission (need FW support) ++ifeq ($(CONFIG_RWNX_BFMER), y) ++CONFIG_RWNX_MUMIMO_TX ?= n ++else ++CONFIG_RWNX_MUMIMO_TX = n ++endif ++ ++# Enable handling of radar event ++CONFIG_RWNX_RADAR ?= y ++ ++# Enable HW queue for Broadcast/Multicast traffic (need FW support) ++CONFIG_RWNX_BCMC ?= y ++ ++# Enable Monitor+Data interface support (need FW support) ++CONFIG_RWNX_MON_DATA = n ++CONFIG_RWNX_MON_XMIT = n ++CONFIG_RWNX_MON_RXFILTER = n ++ ++ ++# extra DEBUG config ++CONFIG_RWNX_SW_PROFILING ?= n ++CONFIG_RWNX_DBG ?= y ++CONFIG_DEBUG_FS ?= n ++ ++obj-$(CONFIG_AIC8800_WLAN_SUPPORT) := $(MODULE_NAME).o ++$(MODULE_NAME)-y := \ ++ rwnx_msg_tx.o \ ++ rwnx_msg_rx.o \ ++ rwnx_utils.o \ ++ rwnx_cmds.o \ ++ rwnx_irqs.o \ ++ rwnx_cfgfile.o \ ++ rwnx_strs.o \ ++ rwnx_rx.o \ ++ rwnx_tx.o \ ++ rwnx_txq.o \ ++ rwnx_main.o \ ++ rwnx_mod_params.o \ ++ rwnx_mesh.o \ ++ rwnx_platform.o \ ++ rwnx_pci.o \ ++ rwnx_dini.o \ ++ rwnx_v7.o \ ++ ipc_host.o \ ++ rwnx_tdls.o \ ++ aic_vendor.o \ ++ md5.o \ ++ aicwf_compat_8800dc.o \ ++ aicwf_compat_8800d80.o \ ++ rwnx_wakelock.o \ ++ regdb.o \ ++ aic_priv_cmd.o \ ++ aicwf_rx_prealloc.o ++ ++$(MODULE_NAME)-$(CONFIG_BR_SUPPORT) += aic_br_ext.o ++$(MODULE_NAME)-$(CONFIG_RWNX_RADAR) += rwnx_radar.o ++$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_debugfs.o ++$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_fw_trace.o ++$(MODULE_NAME)-$(CONFIG_NL80211_TESTMODE) += rwnx_testmode.o ++$(MODULE_NAME)-$(CONFIG_RWNX_BFMER) += rwnx_bfmer.o ++$(MODULE_NAME)-$(CONFIG_RWNX_MUMIMO_TX) += rwnx_mu_group.o ++$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += sdio_host.o ++$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_txrxif.o ++$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_sdio.o ++$(MODULE_NAME)-$(CONFIG_FILTER_TCP_ACK) += aicwf_tcp_ack.o ++$(MODULE_NAME)-$(CONFIG_SDIO_BT) += aic_btsdio.o ++$(MODULE_NAME)-$(CONFIG_SDIO_BT) += btsdio.o ++ ++$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += usb_host.o ++$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_txrxif.o ++$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_usb.o ++$(MODULE_NAME)-$(CONFIG_GKI) += rwnx_gki.o ++ ++ ++ ++ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_DEBUGFS ++ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_UM_HELPER_DFLT=\"$(CONFIG_RWNX_UM_HELPER_DFLT)\" ++ccflags-$(CONFIG_RWNX_P2P_DEBUGFS) += -DCONFIG_RWNX_P2P_DEBUGFS ++ ++# FW VARS ++ccflags-y += -DNX_VIRT_DEV_MAX=4 ++ ++#for 8800D and DCDW u01 ++#ccflags-y += -DNX_REMOTE_STA_MAX=10 ++ ++#for 8800DCDW u02 ++ccflags-y += -DNX_REMOTE_STA_MAX_FOR_OLD_IC=10 ++ccflags-y += -DNX_REMOTE_STA_MAX=32 ++ ++ccflags-y += -DNX_MU_GROUP_MAX=62 ++ccflags-y += -DNX_TXDESC_CNT=64 ++ccflags-y += -DNX_TX_MAX_RATES=4 ++ccflags-y += -DNX_CHAN_CTXT_CNT=3 ++ ++# FW ARCH: ++ccflags-$(CONFIG_RWNX_SDM) += -DCONFIG_RWNX_SDM ++ccflags-$(CONFIG_RWNX_TL4) += -DCONFIG_RWNX_TL4 ++ccflags-$(CONFIG_RWNX_OLD_IPC) += -DCONFIG_RWNX_OLD_IPC ++ccflags-$(CONFIG_PLATFORM_NANOPI_M4) += -DCONFIG_NANOPI_M4 ++ccflags-$(CONFIG_PLATFORM_INGENIC_T20) += -DCONFIG_INGENIC_T20 ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++ccflags-$(CONFIG_START_FROM_BOOTROM) += -DCONFIG_START_FROM_BOOTROM ++ccflags-$(CONFIG_PMIC_SETTING) += -DCONFIG_PMIC_SETTING ++ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE ++ccflags-$(CONFIG_ROM_PATCH_EN) += -DCONFIG_ROM_PATCH_EN ++ccflags-$(CONFIG_HE_FOR_OLD_KERNEL) += -DCONFIG_HE_FOR_OLD_KERNEL ++ccflags-$(CONFIG_MCU_INTEGRATED) += -DCONFIG_MCU_INTEGRATED ++ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE ++ccflags-$(CONFIG_COEX) += -DCONFIG_COEX ++ ++ccflags-y += -DCONFIG_RWNX_FULLMAC ++ccflags-y += -I$(srctree) ++ccflags-y += -I$(srctree)/$(src) ++ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp ++ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\" ++ccflags-$(CONFIG_RWNX_RADAR) += -DCONFIG_RWNX_RADAR ++ccflags-$(CONFIG_RWNX_MON_DATA) += -DCONFIG_RWNX_MON_DATA ++ccflags-$(CONFIG_RWNX_MON_XMIT) += -DCONFIG_RWNX_MON_XMIT ++ccflags-$(CONFIG_RWNX_MON_RXFILTER) += -DCONFIG_RWNX_MON_RXFILTER ++ ++ccflags-$(CONFIG_RWNX_BFMER) += -DCONFIG_RWNX_BFMER ++ccflags-$(CONFIG_RWNX_SPLIT_TX_BUF) += -DCONFIG_RWNX_SPLIT_TX_BUF ++ifeq ($(CONFIG_RWNX_SPLIT_TX_BUF), y) ++ccflags-$(CONFIG_RWNX_AMSDUS_TX) += -DCONFIG_RWNX_AMSDUS_TX ++endif ++ccflags-$(CONFIG_RWNX_DBG) += -DCONFIG_RWNX_DBG ++ccflags-$(CONFIG_RWNX_SW_PROFILING) += -DCONFIG_RWNX_SW_PROFILING ++ccflags-$(CONFIG_RWNX_MUMIMO_TX) += -DCONFIG_RWNX_MUMIMO_TX ++ccflags-$(CONFIG_RFTEST) += -DCONFIG_RFTEST ++ccflags-y += -DDEFAULT_COUNTRY_CODE=""\$(CONFIG_COUNTRY_CODE)"\" ++ccflags-$(CONFIG_USE_5G) += -DUSE_5G ++ccflags-$(CONFIG_CREATE_TRACE_POINTS) += -DCREATE_TRACE_POINTS ++ccflags-$(CONFIG_TXRX_THREAD_PRIO) += -DCONFIG_TXRX_THREAD_PRIO ++ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP ++ccflags-$(CONFIG_SET_VENDOR_EXTENSION_IE) += -DCONFIG_SET_VENDOR_EXTENSION_IE ++ccflags-$(CONFIG_SUPPORT_REALTIME_CHANGE_MAC) += -DCONFIG_SUPPORT_REALTIME_CHANGE_MAC ++ccflags-$(CONFIG_WPA3_FOR_OLD_KERNEL) += -DCONFIG_WPA3_FOR_OLD_KERNEL ++ccflags-$(CONFIG_VHT_FOR_OLD_KERNEL) += -DCONFIG_VHT_FOR_OLD_KERNEL ++ccflags-$(CONFIG_PREALLOC_RX_SKB) += -DCONFIG_PREALLOC_RX_SKB ++ccflags-$(CONFIG_WIFI_SUSPEND_FOR_LINUX) += -DCONFIG_WIFI_SUSPEND_FOR_LINUX ++ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST ++ccflags-$(CONFIG_USE_P2P0) += -DCONFIG_USE_P2P0 ++ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO ++ccflags-$(CONFIG_SCHED_SCAN) += -DCONFIG_SCHED_SCAN ++ccflags-$(CONFIG_OOB) += -DCONFIG_OOB ++ccflags-$(CONFIG_AICWF_LATENCY_MODE) += -DAICWF_LATENCY_MODE ++ccflags-$(CONFIG_USE_CUSTOMER_MAC) += -DCONFIG_USE_CUSTOMER_MAC ++ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ ++ccflags-$(CONFIG_DPD) += -DCONFIG_DPD ++ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD ++ccflags-$(CONFIG_LOFT_CALIB) += -DCONFIG_LOFT_CALIB ++ccflags-$(CONFIG_FILTER_TCP_ACK) += -DCONFIG_FILTER_TCP_ACK ++ccflags-$(CONFIG_SDIO_BT) += -DCONFIG_SDIO_BT ++ccflags-$(CONFIG_RESV_MEM_SUPPORT) += -DCONFIG_RESV_MEM_SUPPORT ++ccflags-$(CONFIG_GKI) += -DCONFIG_GKI ++ccflags-$(CONFIG_TEMP_COMP) += -DCONFIG_TEMP_COMP ++ccflags-$(CONFIG_TEMP_CONTROL) += -DCONFIG_TEMP_CONTROL ++ccflags-$(CONFIG_POWER_LIMIT) += -DCONFIG_POWER_LIMIT ++ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW ++ccflags-$(CONFIG_MCC) += -DCONFIG_MCC ++ccflags-$(CONFIG_SHUTDOWN_CALLBACK) += -DCONFIG_SHUTDOWN_CALLBACK ++ccflags-$(CONFIG_FOR_IPCAM) += -DCONFIG_FOR_IPCAM ++ccflags-$(CONFIG_SDIO_ADMA) += -DCONFIG_SDIO_ADMA ++ ++ ++ifeq ($(CONFIG_SDIO_SUPPORT), y) ++ccflags-y += -DAICWF_SDIO_SUPPORT ++ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL ++endif ++ ++ifeq ($(CONFIG_USB_SUPPORT), y) ++ccflags-y += -DAICWF_USB_SUPPORT ++endif ++ ++ifeq ($(CONFIG_BR_SUPPORT), y) ++ccflags-y += -DCONFIG_BR_SUPPORT ++ccflags-y += '-DCONFIG_BR_SUPPORT_BRNAME="'$(BR_NAME)'"' ++endif ++ ++ifeq ($(CONFIG_RWNX_MUMIMO_TX), y) ++ccflags-y += -DCONFIG_USER_MAX=2 ++else ++ccflags-y += -DCONFIG_USER_MAX=1 ++endif ++ ++ifeq ($(CONFIG_RWNX_BCMC), y) ++ccflags-y += -DNX_TXQ_CNT=5 ++else ++ccflags-y += -DNX_TXQ_CNT=4 ++endif ++ ++# For old kernel (<=3.19) ++ifeq ($(shell test $(VERSION) -lt 4 -a "$(CONFIG_VENDOR_RWNX)" = y ; echo $$?),0) ++ccflags-y += -DCONFIG_VENDOR_RWNX_VHT_NO80 ++endif ++ ++ccflags-$(CONFIG_RX_REORDER) += -DAICWF_RX_REORDER ++ccflags-$(CONFIG_ARP_OFFLOAD) += -DAICWF_ARP_OFFLOAD ++ccflags-$(CONFIG_RADAR_OR_IR_DETECT) += -DCONFIG_RADAR_OR_IR_DETECT ++ccflags-$(CONFIG_DOWNLOAD_FW) += -DCONFIG_DOWNLOAD_FW ++ccflags-$(CONFIG_RX_NETIF_RECV_SKB) += -DCONFIG_RX_NETIF_RECV_SKB ++ccflags-$(CONFIG_ONE_TXQ) += -DCONFIG_ONE_TXQ ++ccflags-$(CONFIG_TX_NETIF_FLOWCTRL) += -DCONFIG_TX_NETIF_FLOWCTRL ++ccflags-$(CONFIG_APF) += -DCONFIG_APF ++ccflags-$(CONFIG_AUTO_POWERSAVE) += -DCONFIG_AUTO_POWERSAVE ++ ++ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) ++MAKEFLAGS +=-j$(shell nproc) ++ ++########## Platform support list ########## ++CONFIG_PLATFORM_ROCKCHIP ?= n ++CONFIG_PLATFORM_ROCKCHIP2 ?= n ++CONFIG_PLATFORM_ALLWINNER ?= n ++CONFIG_PLATFORM_INGENIC_T20 ?= n ++CONFIG_PLATFORM_AMLOGIC ?= n ++CONFIG_PLATFORM_UBUNTU ?= y ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ++ARCH := arm64 ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE := /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) ++ARCH := arm64 ++KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ++CROSS_COMPILE := /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ++ ++ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ ++ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ++ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER ++ccflags-y += -DANDROID_PLATFORM ++KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/ ++ARCH ?= arm64 ++CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y) ++KDIR ?= /home/yaya/E/T40/kernel ++ARCH ?= mips ++CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu- ++endif ++ ++ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) ++ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC ++ccflags-y += -DANDROID_PLATFORM ++endif ++ ++ifeq ($(CONFIG_PLATFORM_UBUNTU), y) ++ccflags-$(CONFIG_PLATFORM_UBUNTU) += -DCONFIG_PLATFORM_UBUNTU ++KDIR ?= /lib/modules/$(shell uname -r)/build ++PWD ?= $(shell pwd) ++KVER ?= $(shell uname -r) ++MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ++ARCH ?= x86_64 ++CROSS_COMPILE ?= ++ ++ifeq ($(CONFIG_AW_BSP), y) ++ccflags-y += -DCONFIG_PLATFORM_ALLWINNER ++endif ++ ++endif ++########################################### ++ ++ ++all: modules ++modules: ++ make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: ++ mkdir -p $(MODDESTDIR) ++ install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) ++ /sbin/depmod -a ${KVER} ++ ++uninstall: ++ rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko ++ /sbin/depmod -a ${KVER} ++ ++clean: ++ rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c +new file mode 100644 +index 000000000000..dd038e39f3fe +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c +@@ -0,0 +1,1569 @@ ++/****************************************************************************** ++ * ++ * Copyright(c) 2007 - 2017 Realtek Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ *****************************************************************************/ ++#define _AIC_BR_EXT_C_ ++ ++#ifdef __KERNEL__ ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include "rwnx_defs.h" ++#endif ++ ++#ifdef CL_IPV6_PASS ++ #ifdef __KERNEL__ ++ #include ++ #include ++ #include ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)) ++ #include ++ #else ++ #include ++ #endif ++ #endif ++#endif ++ ++#ifdef CONFIG_BR_SUPPORT ++ ++/* #define BR_SUPPORT_DEBUG */ ++ ++#define NAT25_IPV4 01 ++#define NAT25_IPV6 02 ++#define NAT25_IPX 03 ++#define NAT25_APPLE 04 ++#define NAT25_PPPOE 05 ++ ++#define RTL_RELAY_TAG_LEN (ETH_ALEN) ++#define TAG_HDR_LEN 4 ++ ++#define MAGIC_CODE 0x8186 ++#define MAGIC_CODE_LEN 2 ++#define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */ ++ ++/*----------------------------------------------------------------- ++ How database records network address: ++ 0 1 2 3 4 5 6 7 8 9 10 ++ |----|----|----|----|----|----|----|----|----|----|----| ++ IPv4 |type| | IP addr | ++ IPX |type| Net addr | Node addr | ++ IPX |type| Net addr |Sckt addr| ++ Apple |type| Network |node| ++ PPPoE |type| SID | AC MAC | ++-----------------------------------------------------------------*/ ++ ++ ++/* Find a tag in pppoe frame and return the pointer */ ++static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type) ++{ ++ unsigned char *cur_ptr, *start_ptr; ++ unsigned short tagLen, tagType; ++ ++ start_ptr = cur_ptr = (unsigned char *)ph->tag; ++ while ((cur_ptr - start_ptr) < ntohs(ph->length)) { ++ /* prevent un-alignment access */ ++ tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]); ++ tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]); ++ if (tagType == type) ++ return cur_ptr; ++ cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen; ++ } ++ return 0; ++} ++ ++ ++static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag) ++{ ++ struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); ++ int data_len; ++ ++ data_len = tag->tag_len + TAG_HDR_LEN; ++ if (skb_tailroom(skb) < data_len) { ++ printk("skb_tailroom() failed in add SID tag!\n"); ++ return -1; ++ } ++ ++ skb_put(skb, data_len); ++ /* have a room for new tag */ ++ memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length)); ++ ph->length = htons(ntohs(ph->length) + data_len); ++ memcpy((unsigned char *)ph->tag, tag, data_len); ++ return data_len; ++} ++ ++static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len) ++{ ++ int tail_len; ++ unsigned long end, tail; ++ ++ if ((src + len) > skb_tail_pointer(skb) || skb->len < len) ++ return -1; ++ ++ tail = (unsigned long)skb_tail_pointer(skb); ++ end = (unsigned long)src + len; ++ if (tail < end) ++ return -1; ++ ++ tail_len = (int)(tail - end); ++ if (tail_len > 0) ++ memmove(src, src + len, tail_len); ++ ++ skb_trim(skb, skb->len - len); ++ return 0; ++} ++ ++static __inline__ unsigned long __nat25_timeout(struct rwnx_vif *vif) ++{ ++ unsigned long timeout; ++ ++ timeout = jiffies - NAT25_AGEING_TIME * HZ; ++ ++ return timeout; ++} ++ ++ ++static __inline__ int __nat25_has_expired(struct rwnx_vif *vif, ++ struct nat25_network_db_entry *fdb) ++{ ++ if (time_before_eq(fdb->ageing_timer, __nat25_timeout(vif))) ++ return 1; ++ ++ return 0; ++} ++ ++ ++static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr, ++ unsigned int *ipAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPV4; ++ memcpy(networkAddr + 7, (unsigned char *)ipAddr, 4); ++} ++ ++ ++static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr, ++ unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPX; ++ memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); ++ memcpy(networkAddr + 5, ipxNodeAddr, 6); ++} ++ ++ ++static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr, ++ unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPX; ++ memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); ++ memcpy(networkAddr + 5, (unsigned char *)ipxSocketAddr, 2); ++} ++ ++ ++static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr, ++ unsigned short *network, unsigned char *node) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_APPLE; ++ memcpy(networkAddr + 1, (unsigned char *)network, 2); ++ networkAddr[3] = *node; ++} ++ ++ ++static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr, ++ unsigned char *ac_mac, unsigned short *sid) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_PPPOE; ++ memcpy(networkAddr + 1, (unsigned char *)sid, 2); ++ memcpy(networkAddr + 3, (unsigned char *)ac_mac, 6); ++} ++ ++ ++#ifdef CL_IPV6_PASS ++static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr, ++ unsigned int *ipAddr) ++{ ++ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); ++ ++ networkAddr[0] = NAT25_IPV6; ++ memcpy(networkAddr + 1, (unsigned char *)ipAddr, 16); ++} ++ ++ ++static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b) ++{ ++ while (len > 0) { ++ if (*data == tag && *(data + 1) == len8b && len >= len8b * 8) ++ return data + 2; ++ ++ len -= (*(data + 1)) * 8; ++ data += (*(data + 1)) * 8; ++ } ++ return NULL; ++} ++ ++ ++static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac) ++{ ++ struct icmp6hdr *icmphdr = (struct icmp6hdr *)data; ++ unsigned char *mac; ++ ++ if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { ++ if (len >= 8) { ++ mac = scan_tlv(&data[8], len - 8, 1, 1); ++ if (mac) { ++ printk("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) { ++ if (len >= 16) { ++ mac = scan_tlv(&data[16], len - 16, 1, 1); ++ if (mac) { ++ printk("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { ++ if (len >= 24) { ++ mac = scan_tlv(&data[24], len - 24, 1, 1); ++ if (mac) { ++ printk("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { ++ if (len >= 24) { ++ mac = scan_tlv(&data[24], len - 24, 2, 1); ++ if (mac) { ++ printk("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } else if (icmphdr->icmp6_type == NDISC_REDIRECT) { ++ if (len >= 40) { ++ mac = scan_tlv(&data[40], len - 40, 2, 1); ++ if (mac) { ++ printk("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); ++ memcpy(mac, replace_mac, 6); ++ return 1; ++ } ++ } ++ } ++ return 0; ++} ++ ++#ifdef SUPPORT_RX_UNI2MCAST ++static void convert_ipv6_mac_to_mc(struct sk_buff *skb) ++{ ++ struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); ++ unsigned char *dst_mac = skb->data; ++ ++ /* dst_mac[0] = 0xff; */ ++ /* dst_mac[1] = 0xff; */ ++ /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/ ++ dst_mac[0] = 0x33; ++ dst_mac[1] = 0x33; ++ memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4); ++#if defined(__LINUX_2_6__) ++ /*modified by qinjunjie,warning:should not remove next line*/ ++ skb->pkt_type = PACKET_MULTICAST; ++#endif ++} ++#endif /* CL_IPV6_PASS */ ++#endif /* SUPPORT_RX_UNI2MCAST */ ++ ++ ++static __inline__ int __nat25_network_hash(unsigned char *networkAddr) ++{ ++ if (networkAddr[0] == NAT25_IPV4) { ++ unsigned long x; ++ ++ x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } else if (networkAddr[0] == NAT25_IPX) { ++ unsigned long x; ++ ++ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ ++ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } else if (networkAddr[0] == NAT25_APPLE) { ++ unsigned long x; ++ ++ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } else if (networkAddr[0] == NAT25_PPPOE) { ++ unsigned long x; ++ ++ x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } ++#ifdef CL_IPV6_PASS ++ else if (networkAddr[0] == NAT25_IPV6) { ++ unsigned long x; ++ ++ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ ++ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^ ++ networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^ ++ networkAddr[16]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } ++#endif ++ else { ++ unsigned long x = 0; ++ int i; ++ ++ for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++) ++ x ^= networkAddr[i]; ++ ++ return x & (NAT25_HASH_SIZE - 1); ++ } ++} ++ ++ ++static __inline__ void __network_hash_link(struct rwnx_vif *vif, ++ struct nat25_network_db_entry *ent, int hash) ++{ ++ /* Caller must _enter_critical_bh already! */ ++ /* _irqL irqL; */ ++ /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ ++ ++ ent->next_hash = vif->nethash[hash]; ++ if (ent->next_hash != NULL) ++ ent->next_hash->pprev_hash = &ent->next_hash; ++ vif->nethash[hash] = ent; ++ ent->pprev_hash = &vif->nethash[hash]; ++ ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++} ++ ++ ++static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent) ++{ ++ /* Caller must _enter_critical_bh already! */ ++ /* _irqL irqL; */ ++ /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ ++ ++ *(ent->pprev_hash) = ent->next_hash; ++ if (ent->next_hash != NULL) ++ ent->next_hash->pprev_hash = ent->pprev_hash; ++ ent->next_hash = NULL; ++ ent->pprev_hash = NULL; ++ ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++} ++ ++ ++static int __nat25_db_network_lookup_and_replace(struct rwnx_vif *vif, ++ struct sk_buff *skb, unsigned char *networkAddr) ++{ ++ struct nat25_network_db_entry *db; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ db = vif->nethash[__nat25_network_hash(networkAddr)]; ++ while (db != NULL) { ++ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { ++ if (!__nat25_has_expired(vif, db)) { ++ /* replace the destination mac address */ ++ memcpy(skb->data, db->macAddr, ETH_ALEN); ++ atomic_inc(&db->use_count); ++ ++#ifdef CL_IPV6_PASS ++ printk("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ++ "%02x%02x%02x%02x%02x%02x\n", ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10], ++ db->networkAddr[11], ++ db->networkAddr[12], ++ db->networkAddr[13], ++ db->networkAddr[14], ++ db->networkAddr[15], ++ db->networkAddr[16]); ++#else ++ printk("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10]); ++#endif ++ } ++ spin_unlock_bh(&vif->br_ext_lock); ++ return 1; ++ } ++ ++ db = db->next_hash; ++ } ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++ return 0; ++} ++ ++ ++static void __nat25_db_network_insert(struct rwnx_vif *vif, ++ unsigned char *macAddr, unsigned char *networkAddr) ++{ ++ struct nat25_network_db_entry *db; ++ int hash; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ hash = __nat25_network_hash(networkAddr); ++ db = vif->nethash[hash]; ++ ++ while (db != NULL) { ++ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { ++ memcpy(db->macAddr, macAddr, ETH_ALEN); ++ db->ageing_timer = jiffies; ++ spin_unlock_bh(&vif->br_ext_lock); ++ return; ++ } ++ ++ db = db->next_hash; ++ } ++ ++ db = (struct nat25_network_db_entry *)kmalloc(sizeof(*db), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); ++ if (db == NULL) { ++ spin_unlock_bh(&vif->br_ext_lock); ++ return; ++ } ++ ++ memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN); ++ memcpy(db->macAddr, macAddr, ETH_ALEN); ++ atomic_set(&db->use_count, 1); ++ db->ageing_timer = jiffies; ++ ++ __network_hash_link(vif, db, hash); ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++static void __nat25_db_print(struct rwnx_vif *vif) ++{ ++ spin_lock_bh(&vif->br_ext_lock); ++ ++#ifdef BR_SUPPORT_DEBUG ++ static int counter = 0; ++ int i, j; ++ struct nat25_network_db_entry *db; ++ ++ counter++; ++ if ((counter % 16) != 0) ++ return; ++ ++ for (i = 0, j = 0; i < NAT25_HASH_SIZE; i++) { ++ db = vif->nethash[i]; ++ ++ while (db != NULL) { ++#ifdef CL_IPV6_PASS ++ printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ++ "%02x%02x%02x%02x%02x%02x\n", ++ j, ++ i, ++ atomic_read(&db->use_count), ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10], ++ db->networkAddr[11], ++ db->networkAddr[12], ++ db->networkAddr[13], ++ db->networkAddr[14], ++ db->networkAddr[15], ++ db->networkAddr[16]); ++#else ++ printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ j, ++ i, ++ atomic_read(&db->use_count), ++ db->macAddr[0], ++ db->macAddr[1], ++ db->macAddr[2], ++ db->macAddr[3], ++ db->macAddr[4], ++ db->macAddr[5], ++ db->networkAddr[0], ++ db->networkAddr[1], ++ db->networkAddr[2], ++ db->networkAddr[3], ++ db->networkAddr[4], ++ db->networkAddr[5], ++ db->networkAddr[6], ++ db->networkAddr[7], ++ db->networkAddr[8], ++ db->networkAddr[9], ++ db->networkAddr[10]); ++#endif ++ j++; ++ ++ db = db->next_hash; ++ } ++ } ++#endif ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++ ++ ++/* ++ * NAT2.5 interface ++ */ ++ ++void nat25_db_cleanup(struct rwnx_vif *vif) ++{ ++ int i; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ for (i = 0; i < NAT25_HASH_SIZE; i++) { ++ struct nat25_network_db_entry *f; ++ f = vif->nethash[i]; ++ while (f != NULL) { ++ struct nat25_network_db_entry *g; ++ ++ g = f->next_hash; ++ if (vif->scdb_entry == f) { ++ memset(vif->scdb_mac, 0, ETH_ALEN); ++ memset(vif->scdb_ip, 0, 4); ++ vif->scdb_entry = NULL; ++ } ++ __network_hash_unlink(f); ++ kfree(f); ++ ++ f = g; ++ } ++ } ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++void nat25_db_expire(struct rwnx_vif *vif) ++{ ++ int i; ++ spin_lock_bh(&vif->br_ext_lock); ++ ++ /* if(!priv->ethBrExtInfo.nat25_disable) */ ++ { ++ for (i = 0; i < NAT25_HASH_SIZE; i++) { ++ struct nat25_network_db_entry *f; ++ f = vif->nethash[i]; ++ ++ while (f != NULL) { ++ struct nat25_network_db_entry *g; ++ g = f->next_hash; ++ ++ if (__nat25_has_expired(vif, f)) { ++ if (atomic_dec_and_test(&f->use_count)) { ++#ifdef BR_SUPPORT_DEBUG ++#ifdef CL_IPV6_PASS ++ panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ++ "%02x%02x%02x%02x%02x%02x\n", ++ i, ++ f->macAddr[0], ++ f->macAddr[1], ++ f->macAddr[2], ++ f->macAddr[3], ++ f->macAddr[4], ++ f->macAddr[5], ++ f->networkAddr[0], ++ f->networkAddr[1], ++ f->networkAddr[2], ++ f->networkAddr[3], ++ f->networkAddr[4], ++ f->networkAddr[5], ++ f->networkAddr[6], ++ f->networkAddr[7], ++ f->networkAddr[8], ++ f->networkAddr[9], ++ f->networkAddr[10], ++ f->networkAddr[11], ++ f->networkAddr[12], ++ f->networkAddr[13], ++ f->networkAddr[14], ++ f->networkAddr[15], ++ f->networkAddr[16]); ++#else ++ ++ panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ i, ++ f->macAddr[0], ++ f->macAddr[1], ++ f->macAddr[2], ++ f->macAddr[3], ++ f->macAddr[4], ++ f->macAddr[5], ++ f->networkAddr[0], ++ f->networkAddr[1], ++ f->networkAddr[2], ++ f->networkAddr[3], ++ f->networkAddr[4], ++ f->networkAddr[5], ++ f->networkAddr[6], ++ f->networkAddr[7], ++ f->networkAddr[8], ++ f->networkAddr[9], ++ f->networkAddr[10]); ++#endif ++#endif ++ if (vif->scdb_entry == f) { ++ memset(vif->scdb_mac, 0, ETH_ALEN); ++ memset(vif->scdb_ip, 0, 4); ++ vif->scdb_entry = NULL; ++ } ++ __network_hash_unlink(f); ++ kfree(f); ++ } ++ } ++ ++ f = g; ++ } ++ } ++ } ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++} ++ ++ ++#ifdef SUPPORT_TX_MCAST2UNI ++static int checkIPMcAndReplace(struct rwnx_vif *vif, struct sk_buff *skb, unsigned int *dst_ip) ++{ ++ struct stat_info *pstat; ++ struct list_head *phead, *plist; ++ int i; ++ ++ phead = &vif->asoc_list; ++ plist = phead->next; ++ ++ while (plist != phead) { ++ pstat = list_entry(plist, struct stat_info, asoc_list); ++ plist = plist->next; ++ ++ if (pstat->ipmc_num == 0) ++ continue; ++ ++ for (i = 0; i < MAX_IP_MC_ENTRY; i++) { ++ if (pstat->ipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip) + 1, 3)) { ++ memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN); ++ return 1; ++ } ++ } ++ } ++ return 0; ++} ++#endif ++ ++int nat25_db_handle(struct rwnx_vif *vif, struct sk_buff *skb, int method) ++{ ++ unsigned short protocol; ++ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; ++ ++ if (skb == NULL) ++ return -1; ++ ++ if ((method <= NAT25_MIN) || (method >= NAT25_MAX)) ++ return -1; ++ ++ protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); ++ ++ /*---------------------------------------------------*/ ++ /* Handle IP frame */ ++ /*---------------------------------------------------*/ ++ if (protocol == __constant_htons(ETH_P_IP)) { ++ struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); ++ ++ if (((unsigned char *)(iph) + (iph->ihl << 2)) >= (skb->data + ETH_HLEN + skb->len)) { ++ printk("NAT25: malformed IP packet !\n"); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: { ++ /* some muticast with source IP is all zero, maybe other case is illegal */ ++ /* in class A, B, C, host address is all zero or all one is illegal */ ++ if (iph->saddr == 0) ++ return 0; ++ printk("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); ++ __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr); ++ /* record source IP address and , source mac address into db */ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); ++#ifdef SUPPORT_TX_MCAST2UNI ++ if (vif->pshare->rf_ft_var.mc2u_disable || ++ ((((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) ++ == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) && ++ !checkIPMcAndReplace(vif, skb, &iph->daddr)) || ++ (OPMODE & WIFI_ADHOC_STATE))) ++#endif ++ { ++ __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr); ++ ++ if (!__nat25_db_network_lookup_and_replace(vif, skb, networkAddr)) { ++ if (*((unsigned char *)&iph->daddr + 3) == 0xff) { ++ /* L2 is unicast but L3 is broadcast, make L2 bacome broadcast */ ++ printk("NAT25: Set DA as boardcast\n"); ++ memset(skb->data, 0xff, ETH_ALEN); ++ } else { ++ /* forward unknow IP packet to upper TCP/IP */ ++ printk("NAT25: Replace DA with BR's MAC\n"); ++ if ((*(u32 *)vif->br_mac) == 0 && (*(u16 *)(vif->br_mac + 4)) == 0) { ++ void netdev_br_init(struct net_device *netdev); ++ printk("Re-init netdev_br_init() due to br_mac==0!\n"); ++ netdev_br_init(vif->ndev); ++ } ++ memcpy(skb->data, vif->br_mac, ETH_ALEN); ++ } ++ } ++ } ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle ARP frame */ ++ /*---------------------------------------------------*/ ++ else if (protocol == __constant_htons(ETH_P_ARP)) { ++ struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); ++ unsigned char *arp_ptr = (unsigned char *)(arp + 1); ++ unsigned int *sender, *target; ++ ++ if (arp->ar_pro != __constant_htons(ETH_P_IP)) { ++ printk("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro)); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ return 0; /* skb_copy for all ARP frame */ ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0], ++ arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]); ++ ++ /* change to ARP sender mac address to wlan STA address */ ++ memcpy(arp_ptr, vif->ndev->dev_addr, ETH_ALEN); ++ ++ arp_ptr += arp->ar_hln; ++ sender = (unsigned int *)arp_ptr; ++ ++ __nat25_generate_ipv4_network_addr(networkAddr, sender); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup ARP\n"); ++ ++ arp_ptr += arp->ar_hln; ++ sender = (unsigned int *)arp_ptr; ++ arp_ptr += (arp->ar_hln + arp->ar_pln); ++ target = (unsigned int *)arp_ptr; ++ ++ __nat25_generate_ipv4_network_addr(networkAddr, target); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ /* change to ARP target mac address to Lookup result */ ++ arp_ptr = (unsigned char *)(arp + 1); ++ arp_ptr += (arp->ar_hln + arp->ar_pln); ++ memcpy(arp_ptr, skb->data, ETH_ALEN); ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle IPX and Apple Talk frame */ ++ /*---------------------------------------------------*/ ++ else if ((protocol == __constant_htons(ETH_P_IPX)) || ++ (protocol == __constant_htons(ETH_P_ATALK)) || ++ (protocol == __constant_htons(ETH_P_AARP))) { ++ unsigned char ipx_header[2] = {0xFF, 0xFF}; ++ struct ipxhdr *ipx = NULL; ++ struct elapaarp *ea = NULL; ++ struct ddpehdr *ddp = NULL; ++ unsigned char *framePtr = skb->data + ETH_HLEN; ++ ++ if (protocol == __constant_htons(ETH_P_IPX)) { ++ printk("NAT25: Protocol=IPX (Ethernet II)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else { /* if(protocol <= __constant_htons(ETH_FRAME_LEN)) */ ++ if (!memcmp(ipx_header, framePtr, 2)) { ++ printk("NAT25: Protocol=IPX (Ethernet 802.3)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else { ++ unsigned char ipx_8022_type = 0xE0; ++ unsigned char snap_8022_type = 0xAA; ++ ++ if (*framePtr == snap_8022_type) { ++ unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; /* IPX SNAP ID */ ++ unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; /* Apple Talk AARP SNAP ID */ ++ unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; /* Apple Talk DDP SNAP ID */ ++ ++ framePtr += 3; /* eliminate the 802.2 header */ ++ ++ if (!memcmp(ipx_snap_id, framePtr, 5)) { ++ framePtr += 5; /* eliminate the SNAP header */ ++ ++ printk("NAT25: Protocol=IPX (Ethernet SNAP)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else if (!memcmp(aarp_snap_id, framePtr, 5)) { ++ framePtr += 5; /* eliminate the SNAP header */ ++ ++ ea = (struct elapaarp *)framePtr; ++ } else if (!memcmp(ddp_snap_id, framePtr, 5)) { ++ framePtr += 5; /* eliminate the SNAP header */ ++ ++ ddp = (struct ddpehdr *)framePtr; ++ } else { ++ printk("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0], ++ framePtr[1], framePtr[2], framePtr[3], framePtr[4]); ++ return -1; ++ } ++ } else if (*framePtr == ipx_8022_type) { ++ framePtr += 3; /* eliminate the 802.2 header */ ++ ++ if (!memcmp(ipx_header, framePtr, 2)) { ++ printk("NAT25: Protocol=IPX (Ethernet 802.2)\n"); ++ ipx = (struct ipxhdr *)framePtr; ++ } else ++ return -1; ++ } ++ } ++ } ++ ++ /* IPX */ ++ if (ipx != NULL) { ++ switch (method) { ++ case NAT25_CHECK: ++ if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { ++ printk("NAT25: Check IPX skb_copy\n"); ++ return 0; ++ } ++ return -1; ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n", ++ ipx->ipx_dest.net, ++ ipx->ipx_dest.node[0], ++ ipx->ipx_dest.node[1], ++ ipx->ipx_dest.node[2], ++ ipx->ipx_dest.node[3], ++ ipx->ipx_dest.node[4], ++ ipx->ipx_dest.node[5], ++ ipx->ipx_dest.sock, ++ ipx->ipx_source.net, ++ ipx->ipx_source.node[0], ++ ipx->ipx_source.node[1], ++ ipx->ipx_source.node[2], ++ ipx->ipx_source.node[3], ++ ipx->ipx_source.node[4], ++ ipx->ipx_source.node[5], ++ ipx->ipx_source.sock); ++ ++ if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { ++ printk("NAT25: Use IPX Net, and Socket as network addr\n"); ++ ++ __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock); ++ ++ /* change IPX source node addr to wlan STA address */ ++ memcpy(ipx->ipx_source.node, vif->ndev->dev_addr, ETH_ALEN); ++ } else ++ __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ if (!memcmp(vif->ndev->dev_addr, ipx->ipx_dest.node, ETH_ALEN)) { ++ printk("NAT25: Lookup IPX, Modify Destination IPX Node addr\n"); ++ ++ __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ /* replace IPX destination node addr with Lookup destination MAC addr */ ++ memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN); ++ } else { ++ __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ } ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /* AARP */ ++ else if (ea != NULL) { ++ /* Sanity check fields. */ ++ if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) { ++ printk("NAT25: Appletalk AARP Sanity check fail!\n"); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ return 0; ++ ++ case NAT25_INSERT: { ++ /* change to AARP source mac address to wlan STA address */ ++ memcpy(ea->hw_src, vif->ndev->dev_addr, ETH_ALEN); ++ ++ printk("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n", ++ ea->pa_src_net, ++ ea->pa_src_node, ++ ea->pa_dst_net, ++ ea->pa_dst_node); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n", ++ ea->pa_src_net, ++ ea->pa_src_node, ++ ea->pa_dst_net, ++ ea->pa_dst_node); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ /* change to AARP destination mac address to Lookup result */ ++ memcpy(ea->hw_dst, skb->data, ETH_ALEN); ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /* DDP */ ++ else if (ddp != NULL) { ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n", ++ ddp->deh_snet, ++ ddp->deh_snode, ++ ddp->deh_dnet, ++ ddp->deh_dnode); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: { ++ printk("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n", ++ ddp->deh_snet, ++ ddp->deh_snode, ++ ddp->deh_dnet, ++ ddp->deh_dnode); ++ ++ __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ return -1; ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle PPPoE frame */ ++ /*---------------------------------------------------*/ ++ else if ((protocol == __constant_htons(ETH_P_PPP_DISC)) || ++ (protocol == __constant_htons(ETH_P_PPP_SES))) { ++ struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); ++ unsigned short *pMagic; ++ ++ switch (method) { ++ case NAT25_CHECK: ++ if (ph->sid == 0) ++ return 0; ++ return 1; ++ ++ case NAT25_INSERT: ++ if (ph->sid == 0) { /* Discovery phase according to tag */ ++ if (ph->code == PADI_CODE || ph->code == PADR_CODE) { ++ if (vif->ethBrExtInfo.addPPPoETag) { ++ struct pppoe_tag *tag, *pOldTag; ++ unsigned char tag_buf[40]; ++ int old_tag_len = 0; ++ ++ tag = (struct pppoe_tag *)tag_buf; ++ pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); ++ if (pOldTag) { /* if SID existed, copy old value and delete it */ ++ old_tag_len = ntohs(pOldTag->tag_len); ++ if (old_tag_len + TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN > sizeof(tag_buf)) { ++ printk("SID tag length too long!\n"); ++ return -1; ++ } ++ ++ memcpy(tag->tag_data + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN, ++ pOldTag->tag_data, old_tag_len); ++ ++ if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN + old_tag_len) < 0) { ++ printk("call skb_pull_and_merge() failed in PADI/R packet!\n"); ++ return -1; ++ } ++ ph->length = htons(ntohs(ph->length) - TAG_HDR_LEN - old_tag_len); ++ } ++ ++ tag->tag_type = PTT_RELAY_SID; ++ tag->tag_len = htons(MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN + old_tag_len); ++ ++ /* insert the magic_code+client mac in relay tag */ ++ pMagic = (unsigned short *)tag->tag_data; ++ *pMagic = htons(MAGIC_CODE); ++ memcpy(tag->tag_data + MAGIC_CODE_LEN, skb->data + ETH_ALEN, ETH_ALEN); ++ ++ /* Add relay tag */ ++ if (__nat25_add_pppoe_tag(skb, tag) < 0) ++ return -1; ++ ++ printk("NAT25: Insert PPPoE, forward %s packet\n", ++ (ph->code == PADI_CODE ? "PADI" : "PADR")); ++ } else { /* not add relay tag */ ++ if (vif->pppoe_connection_in_progress && ++ memcmp(skb->data + ETH_ALEN, vif->pppoe_addr, ETH_ALEN)) { ++ printk("Discard PPPoE packet due to another PPPoE connection is in progress!\n"); ++ return -2; ++ } ++ ++ if (vif->pppoe_connection_in_progress == 0) ++ memcpy(vif->pppoe_addr, skb->data + ETH_ALEN, ETH_ALEN); ++ ++ vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE; ++ } ++ } else ++ return -1; ++ } else { /* session phase */ ++ printk("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name); ++ ++ __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid)); ++ ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ ++ __nat25_db_print(vif); ++ ++ if (!vif->ethBrExtInfo.addPPPoETag && ++ vif->pppoe_connection_in_progress && ++ !memcmp(skb->data + ETH_ALEN, vif->pppoe_addr, ETH_ALEN)) ++ vif->pppoe_connection_in_progress = 0; ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: ++ if (ph->code == PADO_CODE || ph->code == PADS_CODE) { ++ if (vif->ethBrExtInfo.addPPPoETag) { ++ struct pppoe_tag *tag; ++ unsigned char *ptr; ++ unsigned short tagType, tagLen; ++ int offset = 0; ++ ++ ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); ++ if (ptr == 0) { ++ printk("Fail to find PTT_RELAY_SID in FADO!\n"); ++ return -1; ++ } ++ ++ tag = (struct pppoe_tag *)ptr; ++ tagType = (unsigned short)((ptr[0] << 8) + ptr[1]); ++ tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]); ++ ++ if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN))) { ++ printk("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen); ++ return -1; ++ } ++ ++ pMagic = (unsigned short *)tag->tag_data; ++ if (ntohs(*pMagic) != MAGIC_CODE) { ++ printk("Can't find MAGIC_CODE in %s packet!\n", ++ (ph->code == PADO_CODE ? "PADO" : "PADS")); ++ return -1; ++ } ++ ++ memcpy(skb->data, tag->tag_data + MAGIC_CODE_LEN, ETH_ALEN); ++ ++ if (tagLen > MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN) ++ offset = TAG_HDR_LEN; ++ ++ if (skb_pull_and_merge(skb, ptr + offset, TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset) < 0) { ++ printk("call skb_pull_and_merge() failed in PADO packet!\n"); ++ return -1; ++ } ++ ph->length = htons(ntohs(ph->length) - (TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset)); ++ if (offset > 0) ++ tag->tag_len = htons(tagLen - MAGIC_CODE_LEN - RTL_RELAY_TAG_LEN); ++ ++ printk("NAT25: Lookup PPPoE, forward %s Packet from %s\n", ++ (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name); ++ } else { /* not add relay tag */ ++ if (!vif->pppoe_connection_in_progress) { ++ printk("Discard PPPoE packet due to no connection in progresss!\n"); ++ return -1; ++ } ++ memcpy(skb->data, vif->pppoe_addr, ETH_ALEN); ++ vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE; ++ } ++ } else { ++ if (ph->sid != 0) { ++ printk("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name); ++ __nat25_generate_pppoe_network_addr(networkAddr, skb->data + ETH_ALEN, &(ph->sid)); ++ ++ __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); ++ ++ __nat25_db_print(vif); ++ } else ++ return -1; ++ ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle EAP frame */ ++ /*---------------------------------------------------*/ ++ else if (protocol == __constant_htons(0x888e)) { ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: ++ return 0; ++ ++ case NAT25_LOOKUP: ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle C-Media proprietary frame */ ++ /*---------------------------------------------------*/ ++ else if ((protocol == __constant_htons(0xe2ae)) || ++ (protocol == __constant_htons(0xe2af))) { ++ switch (method) { ++ case NAT25_CHECK: ++ return -1; ++ ++ case NAT25_INSERT: ++ return 0; ++ ++ case NAT25_LOOKUP: ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++ ++ /*---------------------------------------------------*/ ++ /* Handle IPV6 frame */ ++ /*---------------------------------------------------*/ ++#ifdef CL_IPV6_PASS ++ else if (protocol == __constant_htons(ETH_P_IPV6)) { ++ struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); ++ ++ if (sizeof(*iph) >= (skb->len - ETH_HLEN)) { ++ printk("NAT25: malformed IPv6 packet !\n"); ++ return -1; ++ } ++ ++ switch (method) { ++ case NAT25_CHECK: ++ if (skb->data[0] & 1) ++ return 0; ++ return -1; ++ ++ case NAT25_INSERT: { ++ printk("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," ++ " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", ++ iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], ++ iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], ++ iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], ++ iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); ++ ++ if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) { ++ __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr); ++ __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); ++ __nat25_db_print(vif); ++ ++ if (iph->nexthdr == IPPROTO_ICMPV6 && ++ skb->len > (ETH_HLEN + sizeof(*iph) + 4)) { ++ if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), ++ skb->len - ETH_HLEN - sizeof(*iph), vif->ndev->dev_addr)) { ++ struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); ++ hdr->icmp6_cksum = 0; ++ hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr, ++ iph->payload_len, ++ IPPROTO_ICMPV6, ++ csum_partial((__u8 *)hdr, iph->payload_len, 0)); ++ } ++ } ++ } ++ } ++ return 0; ++ ++ case NAT25_LOOKUP: ++ printk("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," ++ " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", ++ iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], ++ iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], ++ iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], ++ iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); ++ ++ ++ __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr); ++ if (!__nat25_db_network_lookup_and_replace(vif, skb, networkAddr)) { ++#ifdef SUPPORT_RX_UNI2MCAST ++ if (iph->daddr.s6_addr[0] == 0xff) ++ convert_ipv6_mac_to_mc(skb); ++#endif ++ } ++ return 0; ++ ++ default: ++ return -1; ++ } ++ } ++#endif /* CL_IPV6_PASS */ ++ ++ return -1; ++} ++ ++ ++int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb) ++{ ++ //printk("%s : vif_type=%d \n",__func__,RWNX_VIF_TYPE(vif)); ++#ifdef BR_SUPPORT_DEBUG ++ if ((!vif->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1))) { ++ printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n", ++ skb->data[0], ++ skb->data[1], ++ skb->data[2], ++ skb->data[3], ++ skb->data[4], ++ skb->data[5], ++ skb->data[6], ++ skb->data[7], ++ skb->data[8], ++ skb->data[9], ++ skb->data[10], ++ skb->data[11]); ++ } ++#endif ++ ++ if (!(skb->data[0] & 1)) { ++ int is_vlan_tag = 0, i, retval = 0; ++ unsigned short vlan_hdr = 0; ++ ++ if (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_8021Q)) { ++ is_vlan_tag = 1; ++ vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2)); ++ skb_pull(skb, 4); ++ } ++ ++ if (!vif->ethBrExtInfo.nat25_disable) { ++ unsigned long irqL; ++ spin_lock_bh(&vif->br_ext_lock); ++ /* ++ * This function look up the destination network address from ++ * the NAT2.5 database. Return value = -1 means that the ++ * corresponding network protocol is NOT support. ++ */ ++ if (!vif->ethBrExtInfo.nat25sc_disable && ++ (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && ++ !memcmp(vif->scdb_ip, skb->data + ETH_HLEN + 16, 4)) { ++ memcpy(skb->data, vif->scdb_mac, ETH_ALEN); ++ ++ spin_unlock_bh(&vif->br_ext_lock); ++ } else { ++ spin_unlock_bh(&vif->br_ext_lock); ++ ++ retval = nat25_db_handle(vif, skb, NAT25_LOOKUP); ++ } ++ } else { ++ if (((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && ++ !memcmp(vif->br_ip, skb->data + ETH_HLEN + 16, 4)) || ++ ((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_ARP)) && ++ !memcmp(vif->br_ip, skb->data + ETH_HLEN + 24, 4))) { ++ /* for traffic to upper TCP/IP */ ++ retval = nat25_db_handle(vif, skb, NAT25_LOOKUP); ++ } ++ } ++ ++ if (is_vlan_tag) { ++ skb_push(skb, 4); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); ++ *((unsigned short *)(skb->data + ETH_ALEN * 2)) = __constant_htons(ETH_P_8021Q); ++ *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr; ++ } ++ ++ if (retval == -1) { ++ /* DEBUG_ERR("NAT25: Lookup fail!\n"); */ ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++#if 0 ++void mac_clone(_adapter *priv, unsigned char *addr) ++{ ++ struct sockaddr sa; ++ ++ memcpy(sa.sa_data, addr, ETH_ALEN); ++ RTW_INFO("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); ++ rtl8192cd_set_hwaddr(priv->dev, &sa); ++} ++ ++ ++int mac_clone_handle_frame(_adapter *priv, struct sk_buff *skb) ++{ ++ if (priv->ethBrExtInfo.macclone_enable && !priv->macclone_completed) { ++ if (!(skb->data[ETH_ALEN] & 1)) { /* check any other particular MAC add */ ++ if (memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(priv), ETH_ALEN) && ++ ((priv->dev->br_port) && ++ memcmp(skb->data + ETH_ALEN, priv->br_mac, ETH_ALEN))) { ++ mac_clone(priv, skb->data + ETH_ALEN); ++ priv->macclone_completed = 1; ++ } ++ } ++ } ++ ++ return 0; ++} ++#endif /* 0 */ ++ ++#define SERVER_PORT 67 ++#define CLIENT_PORT 68 ++#define DHCP_MAGIC 0x63825363 ++#define BROADCAST_FLAG 0x8000 ++ ++struct dhcpMessage { ++ u_int8_t op; ++ u_int8_t htype; ++ u_int8_t hlen; ++ u_int8_t hops; ++ u_int32_t xid; ++ u_int16_t secs; ++ u_int16_t flags; ++ u_int32_t ciaddr; ++ u_int32_t yiaddr; ++ u_int32_t siaddr; ++ u_int32_t giaddr; ++ u_int8_t chaddr[16]; ++ u_int8_t sname[64]; ++ u_int8_t file[128]; ++ u_int32_t cookie; ++ u_int8_t options[308]; /* 312 - cookie */ ++}; ++ ++void dhcp_flag_bcast(struct rwnx_vif *vif, struct sk_buff *skb) ++{ ++ if (skb == NULL) ++ return; ++ //print_hex_dump(KERN_ERR, "SKB DUMP: SKB->DATA== ", DUMP_PREFIX_NONE, 32, 1, skb->data, 64,false); ++ if (!vif->ethBrExtInfo.dhcp_bcst_disable) { ++ unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); ++ printk("%s protocol: %04x\n", __func__, protocol); ++ ++ if (protocol == __constant_htons(ETH_P_IP)) { /* IP */ ++ struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); ++ ++ if (iph->protocol == IPPROTO_UDP) { /* UDP */ ++ struct udphdr *udph = (struct udphdr *)((u8 *)iph + (iph->ihl << 2)); ++ ++ if ((udph->source == __constant_htons(CLIENT_PORT)) ++ && (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */ ++ struct dhcpMessage *dhcph = ++ (struct dhcpMessage *)((u8 *)udph + sizeof(struct udphdr)); ++ ++ if (dhcph->cookie == __constant_htonl(DHCP_MAGIC)) { /* match magic word */ ++ if (!(dhcph->flags & htons(BROADCAST_FLAG))) { /* if not broadcast */ ++ register int sum = 0; ++ ++ printk("DHCP: change flag of DHCP request to broadcast.\n"); ++ ++ #if 1 ++ /* or BROADCAST flag */ ++ dhcph->flags |= htons(BROADCAST_FLAG); ++ /* recalculate checksum */ ++ sum = ~(udph->check) & 0xffff; ++ sum += dhcph->flags; ++ while (sum >> 16) ++ sum = (sum & 0xffff) + (sum >> 16); ++ udph->check = ~sum; ++ #endif ++ } ++ } ++ } ++ } ++ } ++ } ++} ++ ++ ++void *scdb_findEntry(struct rwnx_vif *vif, unsigned char *macAddr, ++ unsigned char *ipAddr) ++{ ++ printk("%s()\n",__func__); ++ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; ++ struct nat25_network_db_entry *db; ++ int hash; ++ /* _irqL irqL; */ ++ /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ ++ ++ __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr); ++ hash = __nat25_network_hash(networkAddr); ++ db = vif->nethash[hash]; ++ while (db != NULL) { ++ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++ return (void *)db; ++ } ++ ++ db = db->next_hash; ++ } ++ ++ /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ ++ return NULL; ++} ++ ++#endif /* CONFIG_BR_SUPPORT */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h +new file mode 100644 +index 000000000000..71ebeb293b8e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h +@@ -0,0 +1,73 @@ ++/****************************************************************************** ++ * ++ * Copyright(c) 2007 - 2017 Realtek Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * 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 _AIC_BR_EXT_H_ ++#define _AIC_BR_EXT_H_ ++ ++#define CL_IPV6_PASS 1 ++#define MACADDRLEN 6 ++#define WLAN_ETHHDR_LEN 14 ++ ++#define NAT25_HASH_BITS 4 ++#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS) ++#define NAT25_AGEING_TIME 300 ++ ++#define NDEV_FMT "%s" ++#define NDEV_ARG(ndev) ndev->name ++#define ADPT_FMT "%s" ++//#define ADPT_ARG(adapter) (adapter->pnetdev ? adapter->pnetdev->name : NULL) ++#define FUNC_NDEV_FMT "%s(%s)" ++#define FUNC_NDEV_ARG(ndev) __func__, ndev->name ++#define FUNC_ADPT_FMT "%s(%s)" ++//#define FUNC_ADPT_ARG(adapter) __func__, (adapter->pnetdev ? adapter->pnetdev->name : NULL) ++#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" ++#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5] ++ ++ ++#ifdef CL_IPV6_PASS ++ #define MAX_NETWORK_ADDR_LEN 17 ++#else ++ #define MAX_NETWORK_ADDR_LEN 11 ++#endif ++ ++struct nat25_network_db_entry { ++ struct nat25_network_db_entry *next_hash; ++ struct nat25_network_db_entry **pprev_hash; ++ atomic_t use_count; ++ unsigned char macAddr[6]; ++ unsigned long ageing_timer; ++ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; ++}; ++ ++enum NAT25_METHOD { ++ NAT25_MIN, ++ NAT25_CHECK, ++ NAT25_INSERT, ++ NAT25_LOOKUP, ++ NAT25_PARSE, ++ NAT25_MAX ++}; ++ ++struct br_ext_info { ++ unsigned int nat25_disable; ++ unsigned int macclone_enable; ++ unsigned int dhcp_bcst_disable; ++ int addPPPoETag; /* 1: Add PPPoE relay-SID, 0: disable */ ++ unsigned char nat25_dmzMac[MACADDRLEN]; ++ unsigned int nat25sc_disable; ++}; ++ ++void nat25_db_cleanup(struct rwnx_vif *vif); ++ ++#endif /* _AIC_BR_EXT_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h +new file mode 100644 +index 000000000000..d3d020533a84 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h +@@ -0,0 +1,64 @@ ++#ifndef __AIC_BSP_EXPORT_H ++#define __AIC_BSP_EXPORT_H ++ ++enum aicbsp_subsys { ++ AIC_BLUETOOTH, ++ AIC_WIFI, ++}; ++ ++enum aicbsp_pwr_state { ++ AIC_PWR_OFF, ++ AIC_PWR_ON, ++}; ++ ++struct aicbsp_feature_t { ++ int hwinfo; ++ uint32_t sdio_clock; ++ uint8_t sdio_phase; ++ int fwlog_en; ++ uint8_t irqf; ++}; ++ ++enum skb_buff_id { ++ AIC_RESV_MEM_TXDATA, ++}; ++ ++#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) ++typedef struct { ++ uint32_t bit_mask[3]; ++ uint32_t reserved; ++ uint32_t dpd_high[96]; ++ uint32_t dpd_11b[96]; ++ uint32_t dpd_low[96]; ++ uint32_t idac_11b[48]; ++ uint32_t idac_high[48]; ++ uint32_t idac_low[48]; ++ uint32_t loft_res[18]; ++ uint32_t rx_iqim_res[16]; ++} rf_misc_ram_t; ++ ++typedef struct { ++ uint32_t bit_mask[4]; ++ uint32_t dpd_high[96]; ++ uint32_t loft_res[18]; ++} rf_misc_ram_lite_t; ++ ++#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) ++#define DPD_RESULT_SIZE_8800DC sizeof(rf_misc_ram_lite_t) ++#endif ++ ++#ifdef CONFIG_DPD ++extern rf_misc_ram_lite_t dpd_res; ++#endif ++ ++#ifdef CONFIG_LOFT_CALIB ++extern rf_misc_ram_lite_t loft_res_local; ++#endif ++ ++int aicbsp_set_subsys(int, int); ++int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path); ++bool aicbsp_get_load_fw_in_fdrv(void); ++struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id); ++void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c +new file mode 100644 +index 000000000000..ba26a37ef6e7 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c +@@ -0,0 +1,1299 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aic_btsdio.h" ++#include "rwnx_msg_tx.h" ++ ++#if CONFIG_BLUEDROID == 1 ++static spinlock_t queue_lock; ++static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how) ++{ ++ struct sk_buff *skb; ++ ++ if ((skb = alloc_skb(len + BT_SKB_RESERVE, how))) { ++ skb_reserve(skb, BT_SKB_RESERVE); ++ bt_cb(skb)->incoming = 0; ++ } ++ return skb; ++} ++ ++static spinlock_t queue_lock; ++static spinlock_t dlfw_lock; ++static volatile uint16_t dlfw_dis_state = 0; ++ ++/* Global parameters for bt usb char driver */ ++#define BT_CHAR_DEVICE_NAME "aicbt_dev" ++struct mutex btchr_mutex; ++static struct sk_buff_head btchr_readq; ++static wait_queue_head_t btchr_read_wait; ++static wait_queue_head_t bt_dlfw_wait; ++static int bt_char_dev_registered; ++static dev_t bt_devid; /* bt char device number */ ++static struct cdev bt_char_dev; /* bt character device structure */ ++static struct class *bt_char_class; /* device class for usb char driver */ ++static int bt_reset = 0; ++//int aic_queue_cnt(void); ++/* HCI device & lock */ ++DEFINE_RWLOCK(hci_dev_lock); ++ ++struct hci_dev *ghdev = NULL; ++ ++static struct sk_buff *aic_skb_queue[QUEUE_SIZE]; ++static int aic_skb_queue_front = 0; ++static int aic_skb_queue_rear = 0; ++ ++static inline int check_set_dlfw_state_value(uint16_t change_value) ++{ ++ spin_lock(&dlfw_lock); ++ if(!dlfw_dis_state) { ++ dlfw_dis_state = change_value; ++ } ++ spin_unlock(&dlfw_lock); ++ return dlfw_dis_state; ++} ++ ++static inline void set_dlfw_state_value(uint16_t change_value) ++{ ++ spin_lock(&dlfw_lock); ++ dlfw_dis_state = change_value; ++ spin_unlock(&dlfw_lock); ++} ++ ++static void print_acl(struct sk_buff *skb, int direction) ++{ ++#if PRINT_ACL_DATA ++ //uint wlength = skb->len; ++ u16 *handle = (u16 *)(skb->data); ++ u16 len = *(handle+1); ++ //u8 *acl_data = (u8 *)(skb->data); ++ ++ AICBT_INFO("aic %s: direction %d, handle %04x, len %d", ++ __func__, direction, *handle, len); ++#endif ++} ++ ++static void print_sco(struct sk_buff *skb, int direction) ++{ ++#if PRINT_SCO_DATA ++ uint wlength = skb->len; ++ u16 *handle = (u16 *)(skb->data); ++ u8 len = *(u8 *)(handle+1); ++ //u8 *sco_data =(u8 *)(skb->data); ++ ++ AICBT_INFO("aic %s: direction %d, handle %04x, len %d,wlength %d", ++ __func__, direction, *handle, len,wlength); ++#endif ++} ++ ++int bt_bypass_event(struct sk_buff *skb) ++{ ++ int ret = 0; ++ u8 *opcode = (u8*)(skb->data); ++ //u8 len = *(opcode+1); ++ //printk("bypass_event %x,%x,%x,%x,%x\r\n",opcode[0],opcode[1],opcode[2],opcode[3],opcode[4]); ++ ++ switch(opcode[1]) { ++ case HCI_EV_LE_Meta: ++ { ++ u8 subevent_code; ++ subevent_code = opcode[3]; ++ switch(subevent_code){ ++ case HCI_BLE_ADV_PKT_RPT_EVT: ++ case HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT: ++ { ++ if(aic_queue_cnt() > (QUEUE_SIZE-490)){ ++ printk("more adv report bypass\r\n"); ++ ret = 1; ++ } ++ } ++ break; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++ ++int bt_sdio_recv(u8 *data,u32 data_len) ++{ ++ struct sk_buff *skb; ++ int type= data[0]; ++ struct hci_dev *hdev; ++ u32 len = data_len; ++ //int ret=0; ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICWFDBG(LOGERROR,"%s: Failed to get hci dev[NULL]", __func__); ++ return -ENODEV; ++ } ++ ++ skb = alloc_skb(len,GFP_ATOMIC); ++ if(!skb){ ++ AICWFDBG(LOGERROR, "alloc skb fail %s \n",__func__); ++ } ++ memcpy(skb_put(skb,len) ,data, len); ++ if(bt_bypass_event(skb)){ ++ kfree_skb(skb); ++ return 0; ++ } ++ //bt_data_dump("bt_skb", skb, skb->len); ++ ++ if(aic_enqueue(skb)<0){ ++ kfree_skb(skb); ++ }else{ ++ //printk("wake up \n"); ++ wake_up_interruptible(&btchr_read_wait); ++ } ++ return 0; ++} ++ ++ ++static int bypass_event(struct sk_buff *skb) ++{ ++ int ret = 0; ++ u8 *opcode = (u8*)(skb->data); ++ //u8 len = *(opcode+1); ++ //printk("bypass_event %x,%x,%x,%x,%x\r\n",opcode[0],opcode[1],opcode[2],opcode[3],opcode[4]); ++ ++ switch(*opcode) { ++#ifdef CONFIG_SUPPORT_VENDOR_APCF ++ case HCI_EV_CMD_COMPLETE: ++ { ++ u16 sub_opcpde; ++ sub_opcpde = ((u16)opcode[3]|(u16)(opcode[4])<<8); ++ if(sub_opcpde == 0xfd57){ ++ if(vendor_apcf_sent_done){ ++ vendor_apcf_sent_done--; ++ printk("apcf bypass\r\n"); ++ ret = 1; ++ } ++ } ++ } ++ break; ++#endif//CONFIG_SUPPORT_VENDOR_APCF ++ case HCI_EV_LE_Meta: ++ { ++ u8 subevent_code; ++ subevent_code = opcode[2]; ++ switch(subevent_code){ ++ case HCI_BLE_ADV_PKT_RPT_EVT: ++ case HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT: ++ { ++ if(aic_queue_cnt() > (QUEUE_SIZE-100)){ ++ printk("more adv report bypass\r\n"); ++ ret = 1; ++ } ++ } ++ break; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++static void print_event(struct sk_buff *skb) ++{ ++#if PRINT_CMD_EVENT ++ //uint wlength = skb->len; ++ //uint icount = 0; ++ u8 *opcode = (u8*)(skb->data); ++ //u8 len = *(opcode+1); ++ ++ printk("aic %s ", __func__); ++ switch (*opcode) { ++ case HCI_EV_INQUIRY_COMPLETE: ++ printk("HCI_EV_INQUIRY_COMPLETE"); ++ break; ++ case HCI_EV_INQUIRY_RESULT: ++ printk("HCI_EV_INQUIRY_RESULT"); ++ break; ++ case HCI_EV_CONN_COMPLETE: ++ printk("HCI_EV_CONN_COMPLETE"); ++ break; ++ case HCI_EV_CONN_REQUEST: ++ printk("HCI_EV_CONN_REQUEST"); ++ break; ++ case HCI_EV_DISCONN_COMPLETE: ++ printk("HCI_EV_DISCONN_COMPLETE"); ++ break; ++ case HCI_EV_AUTH_COMPLETE: ++ printk("HCI_EV_AUTH_COMPLETE"); ++ break; ++ case HCI_EV_REMOTE_NAME: ++ printk("HCI_EV_REMOTE_NAME"); ++ break; ++ case HCI_EV_ENCRYPT_CHANGE: ++ printk("HCI_EV_ENCRYPT_CHANGE"); ++ break; ++ case HCI_EV_CHANGE_LINK_KEY_COMPLETE: ++ printk("HCI_EV_CHANGE_LINK_KEY_COMPLETE"); ++ break; ++ case HCI_EV_REMOTE_FEATURES: ++ printk("HCI_EV_REMOTE_FEATURES"); ++ break; ++ case HCI_EV_REMOTE_VERSION: ++ printk("HCI_EV_REMOTE_VERSION"); ++ break; ++ case HCI_EV_QOS_SETUP_COMPLETE: ++ printk("HCI_EV_QOS_SETUP_COMPLETE"); ++ break; ++ case HCI_EV_CMD_COMPLETE: ++ printk("HCI_EV_CMD_COMPLETE"); ++ break; ++ case HCI_EV_CMD_STATUS: ++ printk("HCI_EV_CMD_STATUS"); ++ break; ++ case HCI_EV_ROLE_CHANGE: ++ printk("HCI_EV_ROLE_CHANGE"); ++ break; ++ case HCI_EV_NUM_COMP_PKTS: ++ printk("HCI_EV_NUM_COMP_PKTS"); ++ break; ++ case HCI_EV_MODE_CHANGE: ++ printk("HCI_EV_MODE_CHANGE"); ++ break; ++ case HCI_EV_PIN_CODE_REQ: ++ printk("HCI_EV_PIN_CODE_REQ"); ++ break; ++ case HCI_EV_LINK_KEY_REQ: ++ printk("HCI_EV_LINK_KEY_REQ"); ++ break; ++ case HCI_EV_LINK_KEY_NOTIFY: ++ printk("HCI_EV_LINK_KEY_NOTIFY"); ++ break; ++ case HCI_EV_CLOCK_OFFSET: ++ printk("HCI_EV_CLOCK_OFFSET"); ++ break; ++ case HCI_EV_PKT_TYPE_CHANGE: ++ printk("HCI_EV_PKT_TYPE_CHANGE"); ++ break; ++ case HCI_EV_PSCAN_REP_MODE: ++ printk("HCI_EV_PSCAN_REP_MODE"); ++ break; ++ case HCI_EV_INQUIRY_RESULT_WITH_RSSI: ++ printk("HCI_EV_INQUIRY_RESULT_WITH_RSSI"); ++ break; ++ case HCI_EV_REMOTE_EXT_FEATURES: ++ printk("HCI_EV_REMOTE_EXT_FEATURES"); ++ break; ++ case HCI_EV_SYNC_CONN_COMPLETE: ++ printk("HCI_EV_SYNC_CONN_COMPLETE"); ++ break; ++ case HCI_EV_SYNC_CONN_CHANGED: ++ printk("HCI_EV_SYNC_CONN_CHANGED"); ++ break; ++ case HCI_EV_SNIFF_SUBRATE: ++ printk("HCI_EV_SNIFF_SUBRATE"); ++ break; ++ case HCI_EV_EXTENDED_INQUIRY_RESULT: ++ printk("HCI_EV_EXTENDED_INQUIRY_RESULT"); ++ break; ++ case HCI_EV_IO_CAPA_REQUEST: ++ printk("HCI_EV_IO_CAPA_REQUEST"); ++ break; ++ case HCI_EV_SIMPLE_PAIR_COMPLETE: ++ printk("HCI_EV_SIMPLE_PAIR_COMPLETE"); ++ break; ++ case HCI_EV_REMOTE_HOST_FEATURES: ++ printk("HCI_EV_REMOTE_HOST_FEATURES"); ++ break; ++ default: ++ printk("unknow event"); ++ break; ++ } ++ printk("\n"); ++#if 0 ++ printk("%02x,len:%d,", *opcode,len); ++ for (icount = 2; (icount < wlength) && (icount < 24); icount++) ++ printk("%02x ", *(opcode+icount)); ++ printk("\n"); ++#endif ++#endif ++} ++ ++ ++static inline ssize_t sdio_put_user(struct sk_buff *skb, ++ char __user *buf, int count) ++{ ++ char __user *ptr = buf; ++ int len = min_t(unsigned int, skb->len, count); ++ ++ if (copy_to_user(ptr, skb->data, len)) ++ return -EFAULT; ++ ++ return len; ++} ++ ++int aic_enqueue(struct sk_buff *skb) ++{ ++ unsigned long flags = 0; ++ int ret = 0; ++ spin_lock_irqsave(&queue_lock, flags); ++ if (aic_skb_queue_front == (aic_skb_queue_rear + 1) % QUEUE_SIZE) { ++ /* ++ * If queue is full, current solution is to drop ++ * the following entries. ++ */ ++ AICBT_WARN("%s: Queue is full, entry will be dropped", __func__); ++ ret = -1; ++ } else { ++ aic_skb_queue[aic_skb_queue_rear] = skb; ++ ++ aic_skb_queue_rear++; ++ aic_skb_queue_rear %= QUEUE_SIZE; ++ ++ } ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return ret; ++} ++ ++static struct sk_buff *aic_dequeue_try(unsigned int deq_len) ++{ ++ struct sk_buff *skb; ++ struct sk_buff *skb_copy; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&queue_lock, flags); ++ if (aic_skb_queue_front == aic_skb_queue_rear) { ++ AICBT_WARN("%s: Queue is empty", __func__); ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return NULL; ++ } ++ ++ skb = aic_skb_queue[aic_skb_queue_front]; ++ if (deq_len >= skb->len) { ++ ++ aic_skb_queue_front++; ++ aic_skb_queue_front %= QUEUE_SIZE; ++ ++ /* ++ * Return skb addr to be dequeued, and the caller ++ * should free the skb eventually. ++ */ ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return skb; ++ } else { ++ skb_copy = pskb_copy(skb, GFP_ATOMIC); ++ skb_pull(skb, deq_len); ++ /* Return its copy to be freed */ ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return skb_copy; ++ } ++} ++ ++static inline int is_queue_empty(void) ++{ ++ return (aic_skb_queue_front == aic_skb_queue_rear) ? 1 : 0; ++} ++ ++void aic_clear_queue(void) ++{ ++ struct sk_buff *skb; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&queue_lock, flags); ++ while(!is_queue_empty()) { ++ skb = aic_skb_queue[aic_skb_queue_front]; ++ aic_skb_queue[aic_skb_queue_front] = NULL; ++ aic_skb_queue_front++; ++ aic_skb_queue_front %= QUEUE_SIZE; ++ if (skb) { ++ kfree_skb(skb); ++ } ++ } ++ spin_unlock_irqrestore(&queue_lock, flags); ++} ++ ++int aic_queue_cnt(void) ++{ ++ int ret_cnt = 0; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&queue_lock, flags); ++ if(is_queue_empty()) { ++ ret_cnt = 0; ++ }else{ ++ if(aic_skb_queue_rear > aic_skb_queue_front){ ++ ret_cnt = aic_skb_queue_rear-aic_skb_queue_front; ++ }else{ ++ ret_cnt = aic_skb_queue_rear+QUEUE_SIZE-aic_skb_queue_front; ++ } ++ } ++ spin_unlock_irqrestore(&queue_lock, flags); ++ return ret_cnt; ++} ++ ++/* ++ * AicSemi - Integrate from hci_core.c ++ */ ++ ++/* Get HCI device by index. ++ * Device is held on return. */ ++struct hci_dev *hci_dev_get(int index) ++{ ++ if (index != 0) ++ return NULL; ++ ++ return ghdev; ++} ++ ++/* ---- HCI ioctl helpers ---- */ ++static int hci_dev_open(__u16 dev) ++{ ++ struct hci_dev *hdev; ++ int ret = 0; ++ ++ AICBT_DBG("%s: dev %d", __func__, dev); ++ ++ hdev = hci_dev_get(dev); ++ if (!hdev) { ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ return -ENODEV; ++ } ++ ++ /*if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) { ++ ret = -ENODEV; ++ goto done; ++ } ++ ++ if (test_bit(HCI_UP, &hdev->flags)) { ++ ret = -EALREADY; ++ goto done; ++ }*/ ++ ++done: ++ return ret; ++} ++ ++static int hci_dev_do_close(struct hci_dev *hdev) ++{ ++ //if (hdev->flush) ++ // hdev->flush(hdev); ++ /* After this point our queues are empty ++ * and no tasks are scheduled. */ ++ //hdev->close(hdev); ++ /* Clear flags */ ++ hdev->flags = 0; ++ return 0; ++} ++ ++static int hci_dev_close(__u16 dev) ++{ ++ struct hci_dev *hdev; ++ int err; ++ hdev = hci_dev_get(dev); ++ if (!hdev) { ++ AICBT_ERR("%s: failed to get hci dev[Null]", __func__); ++ return -ENODEV; ++ } ++ ++ err = hci_dev_do_close(hdev); ++ ++ return err; ++} ++ ++#if CONFIG_BLUEDROID ++static struct hci_dev *hci_alloc_dev(void) ++{ ++ struct hci_dev *hdev; ++ ++ hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL); ++ if (!hdev) ++ return NULL; ++ ++ return hdev; ++} ++ ++/* Free HCI device */ ++static void hci_free_dev(struct hci_dev *hdev) ++{ ++ kfree(hdev); ++} ++ ++/* Register HCI device */ ++static int hci_register_dev(struct hci_dev *hdev) ++{ ++ int i, id; ++ ++ AICBT_DBG("%s: %p name %s bus %d", __func__, hdev, hdev->name, hdev->bus); ++ /* Do not allow HCI_AMP devices to register at index 0, ++ * so the index can be used as the AMP controller ID. ++ */ ++ id = (hdev->dev_type == HCI_BREDR) ? 0 : 1; ++ ++ write_lock(&hci_dev_lock); ++ ++ sprintf(hdev->name, "hci%d", id); ++ hdev->id = id; ++ hdev->flags = 0; ++ hdev->dev_flags = 0; ++ mutex_init(&hdev->lock); ++ ++ AICBT_DBG("%s: id %d, name %s", __func__, hdev->id, hdev->name); ++ ++ ++ for (i = 0; i < NUM_REASSEMBLY; i++) ++ hdev->reassembly[i] = NULL; ++ ++ memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); ++ atomic_set(&hdev->promisc, 0); ++ ++ if (ghdev) { ++ write_unlock(&hci_dev_lock); ++ AICBT_ERR("%s: Hci device has been registered already", __func__); ++ return -1; ++ } else ++ ghdev = hdev; ++ ++ write_unlock(&hci_dev_lock); ++ ++ return id; ++} ++ ++/* Unregister HCI device */ ++static void hci_unregister_dev(struct hci_dev *hdev) ++{ ++ int i; ++ ++ AICBT_DBG("%s: hdev %p name %s bus %d", __func__, hdev, hdev->name, hdev->bus); ++ set_bit(HCI_UNREGISTER, &hdev->dev_flags); ++ ++ write_lock(&hci_dev_lock); ++ ghdev = NULL; ++ write_unlock(&hci_dev_lock); ++ ++ hci_dev_do_close(hdev); ++ for (i = 0; i < NUM_REASSEMBLY; i++) ++ kfree_skb(hdev->reassembly[i]); ++} ++ ++static void hci_send_to_stack(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ struct sk_buff *aic_skb_copy = NULL; ++ ++ //AICBT_DBG("%s", __func__); ++ ++ if (!hdev) { ++ AICBT_ERR("%s: Frame for unknown HCI device", __func__); ++ return; ++ } ++ ++ if (!test_bit(HCI_RUNNING, &hdev->flags)) { ++ AICBT_ERR("%s: HCI not running", __func__); ++ return; ++ } ++ ++ aic_skb_copy = pskb_copy(skb, GFP_ATOMIC); ++ if (!aic_skb_copy) { ++ AICBT_ERR("%s: Copy skb error", __func__); ++ return; ++ } ++ ++ memcpy(skb_push(aic_skb_copy, 1), &bt_cb(skb)->pkt_type, 1); ++ aic_enqueue(aic_skb_copy); ++ ++ /* Make sure bt char device existing before wakeup read queue */ ++ hdev = hci_dev_get(0); ++ if (hdev) { ++ //AICBT_DBG("%s: Try to wakeup read queue", __func__); ++ AICBT_DBG("%s", __func__); ++ wake_up_interruptible(&btchr_read_wait); ++ } ++ ++ ++ return; ++} ++ ++/* Receive frame from HCI drivers */ ++static int hci_recv_frame(struct sk_buff *skb) ++{ ++ struct hci_dev *hdev = (struct hci_dev *) skb->dev; ++ ++ if (!hdev || ++ (!test_bit(HCI_UP, &hdev->flags) && !test_bit(HCI_INIT, &hdev->flags))) { ++ kfree_skb(skb); ++ return -ENXIO; ++ } ++ ++ /* Incomming skb */ ++ bt_cb(skb)->incoming = 1; ++ ++ /* Time stamp */ ++ __net_timestamp(skb); ++ ++ if (atomic_read(&hdev->promisc)) { ++#ifdef CONFIG_SCO_OVER_HCI ++ if(bt_cb(skb)->pkt_type == HCI_SCODATA_PKT){ ++ hci_send_to_alsa_ringbuffer(hdev, skb); ++ }else{ ++ if(bt_cb(skb)->pkt_type == HCI_EVENT_PKT){ ++ if(bypass_event(skb)){ ++ kfree_skb(skb); ++ return 0; ++ } ++ } ++ hci_send_to_stack(hdev, skb); ++ } ++#else ++ if(bt_cb(skb)->pkt_type == HCI_EVENT_PKT){ ++ if(bypass_event(skb)){ ++ kfree_skb(skb); ++ return 0; ++ } ++ } ++ /* Send copy to the sockets */ ++ hci_send_to_stack(hdev, skb); ++#endif ++ ++ } ++ ++ kfree_skb(skb); ++ return 0; ++} ++ ++ ++ ++static int hci_reassembly(struct hci_dev *hdev, int type, void *data, ++ int count, __u8 index) ++{ ++ int len = 0; ++ int hlen = 0; ++ int remain = count; ++ struct sk_buff *skb; ++ struct bt_skb_cb *scb; ++ ++ //AICBT_DBG("%s", __func__); ++ ++ if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) || ++ index >= NUM_REASSEMBLY) ++ return -EILSEQ; ++ ++ skb = hdev->reassembly[index]; ++ ++ if (!skb) { ++ switch (type) { ++ case HCI_ACLDATA_PKT: ++ len = HCI_MAX_FRAME_SIZE; ++ hlen = HCI_ACL_HDR_SIZE; ++ break; ++ case HCI_EVENT_PKT: ++ len = HCI_MAX_EVENT_SIZE; ++ hlen = HCI_EVENT_HDR_SIZE; ++ break; ++ case HCI_SCODATA_PKT: ++ len = HCI_MAX_SCO_SIZE; ++ hlen = HCI_SCO_HDR_SIZE; ++ break; ++ } ++ ++ skb = bt_skb_alloc(len, GFP_ATOMIC); ++ if (!skb) ++ return -ENOMEM; ++ ++ scb = (void *) skb->cb; ++ scb->expect = hlen; ++ scb->pkt_type = type; ++ ++ skb->dev = (void *) hdev; ++ hdev->reassembly[index] = skb; ++ } ++ ++ while (count) { ++ scb = (void *) skb->cb; ++ len = min_t(uint, scb->expect, count); ++ ++ memcpy(skb_put(skb, len), data, len); ++ ++ count -= len; ++ data += len; ++ scb->expect -= len; ++ remain = count; ++ ++ switch (type) { ++ case HCI_EVENT_PKT: ++ if (skb->len == HCI_EVENT_HDR_SIZE) { ++ struct hci_event_hdr *h = hci_event_hdr(skb); ++ scb->expect = h->plen; ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ hdev->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ ++ case HCI_ACLDATA_PKT: ++ if (skb->len == HCI_ACL_HDR_SIZE) { ++ struct hci_acl_hdr *h = hci_acl_hdr(skb); ++ scb->expect = __le16_to_cpu(h->dlen); ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ hdev->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ ++ case HCI_SCODATA_PKT: ++ if (skb->len == HCI_SCO_HDR_SIZE) { ++ struct hci_sco_hdr *h = hci_sco_hdr(skb); ++ scb->expect = h->dlen; ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ hdev->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ } ++ ++ if (scb->expect == 0) { ++ /* Complete frame */ ++ if(HCI_ACLDATA_PKT == type) ++ print_acl(skb,0); ++ if(HCI_SCODATA_PKT == type) ++ print_sco(skb,0); ++ if(HCI_EVENT_PKT == type) ++ print_event(skb); ++ ++ bt_cb(skb)->pkt_type = type; ++ hci_recv_frame(skb); ++ ++ hdev->reassembly[index] = NULL; ++ return remain; ++ } ++ } ++ ++ return remain; ++} ++ ++int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) ++{ ++ int rem = 0; ++ ++ if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ++ return -EILSEQ; ++ ++ while (count) { ++ rem = hci_reassembly(hdev, type, data, count, type - 1); ++ if (rem < 0) ++ return rem; ++ ++ data += (count - rem); ++ count = rem; ++ } ++ ++ return rem; ++} ++#endif //CONFIG_BLUEDROID ++ ++static int btchr_open(struct inode *inode_p, struct file *file_p) ++{ ++ struct btusb_data *data; ++ struct hci_dev *hdev; ++ ++ AICBT_DBG("%s: BT sdio char device is opening", __func__); ++ /* Not open unless wanna tracing log */ ++ /* trace_printk("%s: open....\n", __func__); */ ++ ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_DBG("%s: Failed to get hci dev[NULL]", __func__); ++ return -ENODEV; ++ } ++ data = GET_DRV_DATA(hdev); ++ ++ atomic_inc(&hdev->promisc); ++ /* ++ * As bt device is not re-opened when hotplugged out, we cannot ++ * trust on file's private data(may be null) when other file ops ++ * are invoked. ++ */ ++ file_p->private_data = data; ++ ++ mutex_lock(&btchr_mutex); ++ hci_dev_open(0); ++ mutex_unlock(&btchr_mutex); ++ ++ aic_clear_queue(); ++ return nonseekable_open(inode_p, file_p); ++} ++ ++static int btchr_close(struct inode *inode_p, struct file *file_p) ++{ ++ struct btusb_data *data; ++ struct hci_dev *hdev; ++ ++ AICBT_INFO("%s: BT sdio char device is closing", __func__); ++ /* Not open unless wanna tracing log */ ++ /* trace_printk("%s: close....\n", __func__); */ ++ ++ data = file_p->private_data; ++ file_p->private_data = NULL; ++ ++#if CONFIG_BLUEDROID ++ /* ++ * If the upper layer closes bt char interfaces, no reset ++ * action required even bt device hotplugged out. ++ */ ++ bt_reset = 0; ++#endif ++ ++ hdev = hci_dev_get(0); ++ if (hdev) { ++ atomic_set(&hdev->promisc, 0); ++ mutex_lock(&btchr_mutex); ++ hci_dev_close(0); ++ mutex_unlock(&btchr_mutex); ++ } ++ ++ return 0; ++} ++ ++void bt_data_dump(char* tag, void* data, unsigned long len){ ++ unsigned long i = 0; ++ uint8_t* data_ = (uint8_t* )data; ++ ++ printk("%s %s len:(%lu)\r\n", __func__, tag, len); ++ ++ for (i = 0; i < len; i += 16){ ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", ++ data_[0 + i], ++ data_[1 + i], ++ data_[2 + i], ++ data_[3 + i], ++ data_[4 + i], ++ data_[5 + i], ++ data_[6 + i], ++ data_[7 + i], ++ data_[8 + i], ++ data_[9 + i], ++ data_[10 + i], ++ data_[11 + i], ++ data_[12 + i], ++ data_[13 + i], ++ data_[14 + i], ++ data_[15 + i]); ++ } ++ ++} ++ ++static ssize_t btchr_read(struct file *file_p, ++ char __user *buf_p, ++ size_t count, ++ loff_t *pos_p) ++{ ++ struct hci_dev *hdev; ++ struct sk_buff *skb; ++ ssize_t ret = 0; ++ ++ while (count) { ++#if 1 ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ /* ++ * Note: Only when BT device hotplugged out, we wil get ++ * into such situation. In order to keep the upper layer ++ * stack alive (blocking the read), we should never return ++ * EFAULT or break the loop. ++ */ ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ } ++#endif ++ ret = wait_event_interruptible(btchr_read_wait, !is_queue_empty()); ++ if (ret < 0) { ++ AICBT_ERR("%s: wait event is signaled %d", __func__, (int)ret); ++ break; ++ } ++ ++ skb = aic_dequeue_try(count); ++ //bt_data_dump("btchr_read", skb->data, skb->len); ++ //printk("btchr_read \n"); ++ if (skb) { ++ ret = sdio_put_user(skb, buf_p, count); ++ if (ret < 0) ++ AICBT_ERR("%s: Failed to put data to user space", __func__); ++ kfree_skb(skb); ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++#ifdef CONFIG_SUPPORT_VENDOR_APCF ++void btchr_external_write(char* buff, int len){ ++ struct hci_dev *hdev; ++ struct sk_buff *skb; ++ int i; ++ struct btusb_data *data; ++ ++ AICBT_INFO("%s \r\n", __func__); ++ for(i=0;idev = (void *)hdev; ++ memcpy((__u8 *)skb->data,(__u8 *)buff,len); ++ skb_put(skb, len); ++ bt_cb(skb)->pkt_type = *((__u8 *)skb->data); ++ skb_pull(skb, 1); ++ data->hdev->send(skb); ++} ++ ++EXPORT_SYMBOL(btchr_external_write); ++#endif //CONFIG_SUPPORT_VENDOR_APCF ++ ++//extern struct rwnx_plat *g_rwnx_plat; ++static ssize_t btchr_write(struct file *file_p, ++ const char __user *buf_p, ++ size_t count, ++ loff_t *pos_p) ++{ ++ struct btusb_data *data = file_p->private_data; ++ struct hci_dev *hdev; ++ struct sk_buff *skb; ++ int err=0; ++ ++ AICBT_DBG("%s", __func__); ++ ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_WARN("%s: Failed to get hci dev[Null]", __func__); ++ /* ++ * Note: we bypass the data from the upper layer if bt device ++ * is hotplugged out. Fortunatelly, H4 or H5 HCI stack does ++ * NOT check btchr_write's return value. However, returning ++ * count instead of EFAULT is preferable. ++ */ ++ /* return -EFAULT; */ ++ return count; ++ } ++ ++#if 0 ++ /* Never trust on btusb_data, as bt device may be hotplugged out */ ++ data = GET_DRV_DATA(hdev); ++ if (!data) { ++ AICBT_WARN("%s: Failed to get bt usb driver data[Null]", __func__); ++ return count; ++ } ++#endif ++ ++ if (count > HCI_MAX_FRAME_SIZE) ++ return -EINVAL; ++ ++ skb = bt_skb_alloc(count, GFP_ATOMIC); ++ if (!skb) ++ return -ENOMEM; ++ skb_reserve(skb, -1); // Add this line ++ ++ if (copy_from_user(skb_put(skb, count), buf_p, count)) { ++ AICBT_ERR("%s: Failed to get data from user space", __func__); ++ kfree_skb(skb); ++ return -EFAULT; ++ } ++ ++ skb->dev = (void *)hdev; ++ bt_cb(skb)->pkt_type = *((__u8 *)skb->data); ++ //skb_pull(skb, 1); ++ //data->hdev->send(skb); ++ ++ //bt_data_dump("btwrite", skb->data, skb->len); ++ err = rwnx_sdio_bt_send_req(g_rwnx_plat->sdiodev->rwnx_hw, skb->len, skb); ++ if(err<0){ ++ printk("%s rwnx_sdio_bt_send_req error %d",__func__,err); ++ } ++ ++ kfree_skb(skb); ++ return count; ++} ++ ++static unsigned int btchr_poll(struct file *file_p, poll_table *wait) ++{ ++ struct btusb_data *data = file_p->private_data; ++ struct hci_dev *hdev; ++ ++ //AICBT_DBG("%s: BT sdio char device is polling", __func__); ++ ++ /*if(!bt_char_dev_registered) { ++ AICBT_ERR("%s: char device has not registered!", __func__); ++ return POLLERR | POLLHUP; ++ }*/ ++ //printk("poll wait\n"); ++ poll_wait(file_p, &btchr_read_wait, wait); ++ //printk("poll out\n"); ++ ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ //mdelay(URB_CANCELING_DELAY_MS); ++ return POLLERR | POLLHUP; ++ return POLLOUT | POLLWRNORM; ++ } ++ ++#if 0 ++ /* Never trust on btusb_data, as bt device may be hotplugged out */ ++ data = GET_DRV_DATA(hdev); ++ if (!data) { ++ /* ++ * When bt device is hotplugged out, btusb_data will ++ * be freed in disconnect. ++ */ ++ AICBT_ERR("%s: Failed to get bt sdio driver data[Null]", __func__); ++ mdelay(URB_CANCELING_DELAY_MS); ++ return POLLOUT | POLLWRNORM; ++ } ++#endif ++ ++ if (!is_queue_empty()) ++ return POLLIN | POLLRDNORM; ++ ++ return POLLOUT | POLLWRNORM; ++} ++static long btchr_ioctl(struct file *file_p,unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ struct hci_dev *hdev; ++ struct btusb_data *data; ++ //firmware_info *fw_info; ++ ++ /*if(!bt_char_dev_registered) { ++ return -ENODEV; ++ }*/ ++ ++ printk("%s cmd support %d \n",__func__,cmd); ++ ++#if 1 ++ if(check_set_dlfw_state_value(1) != 1) { ++ AICBT_ERR("%s bt controller is disconnecting!", __func__); ++ return 0; ++ } ++ ++ hdev = hci_dev_get(0); ++ if(!hdev) { ++ AICBT_ERR("%s device is NULL!", __func__); ++ set_dlfw_state_value(0); ++ return 0; ++ } ++ //data = GET_DRV_DATA(hdev); ++ //fw_info = data->fw_info; ++ ++ AICBT_INFO(" btchr_ioctl DOWN_FW_CFG with Cmd:%d",cmd); ++ switch (cmd) { ++ case DOWN_FW_CFG: ++ AICBT_INFO(" btchr_ioctl DOWN_FW_CFG"); ++ /*ret = usb_autopm_get_interface(data->intf); ++ if (ret < 0){ ++ goto failed; ++ }*/ ++ ++ //ret = download_patch(fw_info,1); ++ /*usb_autopm_put_interface(data->intf); ++ if(ret < 0){ ++ AICBT_ERR("%s:Failed in download_patch with ret:%d",__func__,ret); ++ goto failed; ++ } ++ ++ ret = hdev->open(hdev); ++ if(ret < 0){ ++ AICBT_ERR("%s:Failed in hdev->open(hdev):%d",__func__,ret); ++ goto failed; ++ }*/ ++ set_bit(HCI_UP, &hdev->flags); ++ set_dlfw_state_value(0); ++ wake_up_interruptible(&bt_dlfw_wait); ++ return 1; ++ case DWFW_CMPLT: ++ AICBT_INFO(" btchr_ioctl DWFW_CMPLT"); ++#if 1 ++ case SET_ISO_CFG: ++ AICBT_INFO("btchr_ioctl SET_ISO_CFG"); ++ if(copy_from_user(&(hdev->voice_setting), (__u16*)arg, sizeof(__u16))){ ++ AICBT_INFO(" voice settings err"); ++ } ++ //hdev->voice_setting = *(uint16_t*)arg; ++ AICBT_INFO(" voice settings = %d", hdev->voice_setting); ++ //return 1; ++#endif ++ case GET_USB_INFO: ++ //ret = download_patch(fw_info,1); ++ AICBT_INFO(" btchr_ioctl GET_USB_INFO"); ++ /*ret = hdev->open(hdev); ++ if(ret < 0){ ++ AICBT_ERR("%s:Failed in hdev->open(hdev):%d",__func__,ret); ++ //goto done; ++ }*/ ++ set_bit(HCI_UP, &hdev->flags); ++ set_dlfw_state_value(0); ++ wake_up_interruptible(&bt_dlfw_wait); ++ return 1; ++ case RESET_CONTROLLER: ++ AICBT_INFO(" btchr_ioctl RESET_CONTROLLER"); ++ //reset_controller(fw_info); ++ return 1; ++ default: ++ AICBT_ERR("%s:Failed with wrong Cmd:%d",__func__,cmd); ++ goto failed; ++ } ++ failed: ++ set_dlfw_state_value(0); ++ wake_up_interruptible(&bt_dlfw_wait); ++ return ret; ++#endif ++} ++ ++#ifdef CONFIG_PLATFORM_UBUNTU//AIDEN ++typedef u32 compat_uptr_t; ++static inline void __user *compat_ptr(compat_uptr_t uptr) ++{ ++ return (void __user *)(unsigned long)uptr; ++} ++#endif ++ ++#ifdef CONFIG_COMPAT ++static long compat_btchr_ioctl (struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ AICBT_DBG("%s: enter",__func__); ++ return btchr_ioctl(filp, cmd, (unsigned long) compat_ptr(arg)); ++} ++#endif ++static struct file_operations bt_chrdev_ops = { ++ open : btchr_open, ++ release : btchr_close, ++ read : btchr_read, ++ write : btchr_write, ++ poll : btchr_poll, ++ unlocked_ioctl : btchr_ioctl, ++#ifdef CONFIG_COMPAT ++ compat_ioctl : compat_btchr_ioctl, ++#endif ++}; ++ ++int btchr_init() ++{ ++ int res = 0; ++ struct device *dev; ++ ++ AICBT_INFO("Register sdio char device interface for BT driver"); ++ /* ++ * btchr mutex is used to sync between ++ * 1) downloading patch and opening bt char driver ++ * 2) the file operations of bt char driver ++ */ ++ mutex_init(&btchr_mutex); ++ ++ skb_queue_head_init(&btchr_readq); ++ init_waitqueue_head(&btchr_read_wait); ++ init_waitqueue_head(&bt_dlfw_wait); ++ ++ bt_char_class = class_create(THIS_MODULE, BT_CHAR_DEVICE_NAME); ++ if (IS_ERR(bt_char_class)) { ++ AICBT_ERR("Failed to create bt char class"); ++ return PTR_ERR(bt_char_class); ++ } ++ ++ res = alloc_chrdev_region(&bt_devid, 0, 1, BT_CHAR_DEVICE_NAME); ++ if (res < 0) { ++ AICBT_ERR("Failed to allocate bt char device"); ++ goto err_alloc; ++ } ++ ++ dev = device_create(bt_char_class, NULL, bt_devid, NULL, BT_CHAR_DEVICE_NAME); ++ if (IS_ERR(dev)) { ++ AICBT_ERR("Failed to create bt char device"); ++ res = PTR_ERR(dev); ++ goto err_create; ++ } ++ ++ cdev_init(&bt_char_dev, &bt_chrdev_ops); ++ res = cdev_add(&bt_char_dev, bt_devid, 1); ++ if (res < 0) { ++ AICBT_ERR("Failed to add bt char device"); ++ goto err_add; ++ } ++ ++ return 0; ++ ++err_add: ++ device_destroy(bt_char_class, bt_devid); ++err_create: ++ unregister_chrdev_region(bt_devid, 1); ++err_alloc: ++ class_destroy(bt_char_class); ++ return res; ++} ++ ++void btchr_exit(void) ++{ ++ AICBT_INFO("Unregister sdio char device interface for BT driver"); ++ ++ device_destroy(bt_char_class, bt_devid); ++ cdev_del(&bt_char_dev); ++ unregister_chrdev_region(bt_devid, 1); ++ class_destroy(bt_char_class); ++ ++ return; ++} ++ ++int hdev_init(void) ++{ ++ struct hci_dev *hdev; ++ int err=0; ++ hdev = hci_alloc_dev(); ++ ++ err = hci_register_dev(hdev); ++ if (err < 0) { ++ hci_free_dev(hdev); ++ hdev = NULL; ++ return err; ++ } ++ ++ spin_lock_init(&queue_lock); ++ ++ return 0; ++} ++ ++void hdev_exit(void) ++{ ++ struct hci_dev *hdev; ++ hdev = ghdev; ++ hci_unregister_dev(hdev); ++ hci_free_dev(hdev); ++} ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h +new file mode 100644 +index 000000000000..153ba49d7c55 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h +@@ -0,0 +1,554 @@ ++#ifndef _AICWF_SDIO_BT_H_ ++#define _AICWF_SDIO_BT_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++ ++#ifdef CONFIG_PLATFORM_UBUNTU ++#define CONFIG_BLUEDROID 0 /* bleuz 0, bluedroid 1 */ ++#else ++#define CONFIG_BLUEDROID 1 /* bleuz 0, bluedroid 1 */ ++#endif ++/* #define HCI_VERSION_CODE KERNEL_VERSION(3, 14, 41) */ ++#define HCI_VERSION_CODE LINUX_VERSION_CODE ++ ++ ++#define PRINT_CMD_EVENT 1 ++#define PRINT_ACL_DATA 1 ++#define PRINT_SCO_DATA 1 ++ ++#define AICBT_DBG_FLAG 1 ++ ++#if AICBT_DBG_FLAG ++#define AICBT_DBG(fmt, arg...) printk( "aic_btsdio: " fmt "\n" , ## arg) ++#else ++#define AICBT_DBG(fmt, arg...) ++#endif ++ ++#define AICBT_INFO(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) ++#define AICBT_WARN(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) ++#define AICBT_ERR(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 0) ++#define GET_DRV_DATA(x) hci_get_drvdata(x) ++#else ++#define GET_DRV_DATA(x) x->driver_data ++#endif ++ ++#if CONFIG_BLUEDROID ++struct btusb_data { ++ struct hci_dev *hdev; ++ //struct usb_device *udev; ++ //struct usb_interface *intf; ++ //struct usb_interface *isoc; ++ ++ spinlock_t lock; ++ ++ unsigned long flags; ++ ++ struct work_struct work; ++ struct work_struct waker; ++ ++ /*struct usb_anchor tx_anchor; ++ struct usb_anchor intr_anchor; ++ struct usb_anchor bulk_anchor; ++ struct usb_anchor isoc_anchor; ++ struct usb_anchor deferred;*/ ++ int tx_in_flight; ++ spinlock_t txlock; ++ ++#if (CONFIG_BLUEDROID == 0) ++#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) ++ spinlock_t rxlock; ++ struct sk_buff *evt_skb; ++ struct sk_buff *acl_skb; ++ struct sk_buff *sco_skb; ++#endif ++#endif ++ ++ /*struct usb_endpoint_descriptor *intr_ep; ++ struct usb_endpoint_descriptor *bulk_tx_ep; ++ struct usb_endpoint_descriptor *bulk_rx_ep; ++ struct usb_endpoint_descriptor *isoc_tx_ep; ++ struct usb_endpoint_descriptor *isoc_rx_ep;*/ ++ ++ __u8 cmdreq_type; ++ ++ unsigned int sco_num; ++ int isoc_altsetting; ++ int suspend_count; ++ uint16_t sco_handle; ++ ++#if (CONFIG_BLUEDROID == 0) ++#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) ++ int (*recv_bulk) (struct btusb_data * data, void *buffer, int count); ++#endif ++#endif ++ ++//#ifdef CONFIG_HAS_EARLYSUSPEND ++#if 0 ++ struct early_suspend early_suspend; ++#else ++ struct notifier_block pm_notifier; ++ struct notifier_block reboot_notifier; ++#endif ++ //firmware_info *fw_info; ++ ++#ifdef CONFIG_SCO_OVER_HCI ++ AIC_sco_card_t *pSCOSnd; ++#endif ++}; ++ ++ ++ ++#define QUEUE_SIZE 500 ++ ++/*************************************** ++** AicSemi - Integrate from bluetooth.h ** ++*****************************************/ ++/* Reserv for core and drivers use */ ++#define BT_SKB_RESERVE 8 ++ ++/* BD Address */ ++typedef struct { ++ __u8 b[6]; ++} __packed bdaddr_t; ++ ++/* Skb helpers */ ++struct bt_skb_cb { ++ __u8 pkt_type; ++ __u8 incoming; ++ __u16 expect; ++ __u16 tx_seq; ++ __u8 retries; ++ __u8 sar; ++ __u8 force_active; ++}; ++ ++#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) ++ ++ ++/*********************************** ++** AicSemi - Integrate from hci.h ** ++***********************************/ ++#define HCI_MAX_ACL_SIZE 1024 ++#define HCI_MAX_SCO_SIZE 255 ++#define HCI_MAX_EVENT_SIZE 260 ++#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) ++ ++/* 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 ++ ++/* HCI controller types */ ++#define HCI_BREDR 0x00 ++#define HCI_AMP 0x01 ++ ++/* HCI device flags */ ++enum { ++ HCI_UP, ++ HCI_INIT, ++ HCI_RUNNING, ++ ++ HCI_PSCAN, ++ HCI_ISCAN, ++ HCI_AUTH, ++ HCI_ENCRYPT, ++ HCI_INQUIRY, ++ ++ HCI_RAW, ++ ++ HCI_RESET, ++}; ++ ++/* ++ * BR/EDR and/or LE controller flags: the flags defined here should represent ++ * states from the controller. ++ */ ++enum { ++ HCI_SETUP, ++ HCI_AUTO_OFF, ++ HCI_MGMT, ++ HCI_PAIRABLE, ++ HCI_SERVICE_CACHE, ++ HCI_LINK_KEYS, ++ HCI_DEBUG_KEYS, ++ HCI_UNREGISTER, ++ ++ HCI_LE_SCAN, ++ HCI_SSP_ENABLED, ++ HCI_HS_ENABLED, ++ HCI_LE_ENABLED, ++ HCI_CONNECTABLE, ++ HCI_DISCOVERABLE, ++ HCI_LINK_SECURITY, ++ HCI_PENDING_CLASS, ++}; ++ ++/* HCI data types */ ++#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 ++ ++#define HCI_MAX_NAME_LENGTH 248 ++#define HCI_MAX_EIR_LENGTH 240 ++ ++#define HCI_OP_READ_LOCAL_VERSION 0x1001 ++struct hci_rp_read_local_version { ++ __u8 status; ++ __u8 hci_ver; ++ __le16 hci_rev; ++ __u8 lmp_ver; ++ __le16 manufacturer; ++ __le16 lmp_subver; ++} __packed; ++ ++#define HCI_EV_CMD_COMPLETE 0x0e ++struct hci_ev_cmd_complete { ++ __u8 ncmd; ++ __le16 opcode; ++} __packed; ++ ++/* ---- HCI Packet structures ---- */ ++#define HCI_COMMAND_HDR_SIZE 3 ++#define HCI_EVENT_HDR_SIZE 2 ++#define HCI_ACL_HDR_SIZE 4 ++#define HCI_SCO_HDR_SIZE 3 ++ ++struct hci_command_hdr { ++ __le16 opcode; /* OCF & OGF */ ++ __u8 plen; ++} __packed; ++ ++struct hci_event_hdr { ++ __u8 evt; ++ __u8 plen; ++} __packed; ++ ++struct hci_acl_hdr { ++ __le16 handle; /* Handle & Flags(PB, BC) */ ++ __le16 dlen; ++} __packed; ++ ++struct hci_sco_hdr { ++ __le16 handle; ++ __u8 dlen; ++} __packed; ++ ++static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb) ++{ ++ return (struct hci_event_hdr *) skb->data; ++} ++ ++static inline struct hci_acl_hdr *hci_acl_hdr(const struct sk_buff *skb) ++{ ++ return (struct hci_acl_hdr *) skb->data; ++} ++ ++static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) ++{ ++ return (struct hci_sco_hdr *) skb->data; ++} ++ ++/* ---- HCI Ioctl requests structures ---- */ ++struct hci_dev_stats { ++ __u32 err_rx; ++ __u32 err_tx; ++ __u32 cmd_tx; ++ __u32 evt_rx; ++ __u32 acl_tx; ++ __u32 acl_rx; ++ __u32 sco_tx; ++ __u32 sco_rx; ++ __u32 byte_rx; ++ __u32 byte_tx; ++}; ++/* AicSemi - Integrate from hci.h end */ ++ ++/***************************************** ++** AicSemi - Integrate from hci_core.h ** ++*****************************************/ ++struct hci_conn_hash { ++ struct list_head list; ++ unsigned int acl_num; ++ unsigned int sco_num; ++ unsigned int le_num; ++}; ++ ++#define HCI_MAX_SHORT_NAME_LENGTH 10 ++ ++#define NUM_REASSEMBLY 4 ++struct hci_dev { ++ struct mutex lock; ++ ++ char name[8]; ++ unsigned long flags; ++ __u16 id; ++ __u8 bus; ++ __u8 dev_type; ++ ++ struct sk_buff *reassembly[NUM_REASSEMBLY]; ++ ++ struct hci_conn_hash conn_hash; ++ ++ struct hci_dev_stats stat; ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) ++ atomic_t refcnt; ++ struct module *owner; ++ void *driver_data; ++#endif ++ ++ atomic_t promisc; ++ ++ struct device *parent; ++ struct device dev; ++ ++ unsigned long dev_flags; ++ ++ int (*open)(struct hci_dev *hdev); ++ int (*close)(struct hci_dev *hdev); ++ int (*flush)(struct hci_dev *hdev); ++ int (*send)(struct sk_buff *skb); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) ++ void (*destruct)(struct hci_dev *hdev); ++#endif ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 1) ++ __u16 voice_setting; ++#endif ++ void (*notify)(struct hci_dev *hdev, unsigned int evt); ++ int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); ++ u8 *align_data; ++}; ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) ++static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d) ++{ ++ atomic_inc(&d->refcnt); ++ return d; ++} ++ ++static inline void __hci_dev_put(struct hci_dev *d) ++{ ++ if (atomic_dec_and_test(&d->refcnt)) ++ d->destruct(d); ++} ++#endif ++ ++static inline void *hci_get_drvdata(struct hci_dev *hdev) ++{ ++ return dev_get_drvdata(&hdev->dev); ++} ++ ++static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) ++{ ++ dev_set_drvdata(&hdev->dev, data); ++} ++ ++#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev)) ++ ++ ++/* ---- HCI Packet structures ---- */ ++#define HCI_COMMAND_HDR_SIZE 3 ++#define HCI_EVENT_HDR_SIZE 2 ++#define HCI_ACL_HDR_SIZE 4 ++#define HCI_SCO_HDR_SIZE 3 ++ ++/* ----- HCI Commands ---- */ ++#define HCI_OP_INQUIRY 0x0401 ++#define HCI_OP_INQUIRY_CANCEL 0x0402 ++#define HCI_OP_EXIT_PERIODIC_INQ 0x0404 ++#define HCI_OP_CREATE_CONN 0x0405 ++#define HCI_OP_DISCONNECT 0x0406 ++#define HCI_OP_ADD_SCO 0x0407 ++#define HCI_OP_CREATE_CONN_CANCEL 0x0408 ++#define HCI_OP_ACCEPT_CONN_REQ 0x0409 ++#define HCI_OP_REJECT_CONN_REQ 0x040a ++#define HCI_OP_LINK_KEY_REPLY 0x040b ++#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c ++#define HCI_OP_PIN_CODE_REPLY 0x040d ++#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e ++#define HCI_OP_CHANGE_CONN_PTYPE 0x040f ++#define HCI_OP_AUTH_REQUESTED 0x0411 ++#define HCI_OP_SET_CONN_ENCRYPT 0x0413 ++#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415 ++#define HCI_OP_REMOTE_NAME_REQ 0x0419 ++#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a ++#define HCI_OP_READ_REMOTE_FEATURES 0x041b ++#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c ++#define HCI_OP_READ_REMOTE_VERSION 0x041d ++#define HCI_OP_SETUP_SYNC_CONN 0x0428 ++#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429 ++#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a ++#define HCI_OP_SNIFF_MODE 0x0803 ++#define HCI_OP_EXIT_SNIFF_MODE 0x0804 ++#define HCI_OP_ROLE_DISCOVERY 0x0809 ++#define HCI_OP_SWITCH_ROLE 0x080b ++#define HCI_OP_READ_LINK_POLICY 0x080c ++#define HCI_OP_WRITE_LINK_POLICY 0x080d ++#define HCI_OP_READ_DEF_LINK_POLICY 0x080e ++#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f ++#define HCI_OP_SNIFF_SUBRATE 0x0811 ++#define HCI_OP_Write_Link_Policy_Settings 0x080d ++#define HCI_OP_SET_EVENT_MASK 0x0c01 ++#define HCI_OP_RESET 0x0c03 ++#define HCI_OP_SET_EVENT_FLT 0x0c05 ++#define HCI_OP_Write_Extended_Inquiry_Response 0x0c52 ++#define HCI_OP_Write_Simple_Pairing_Mode 0x0c56 ++#define HCI_OP_Read_Buffer_Size 0x1005 ++#define HCI_OP_Host_Buffer_Size 0x0c33 ++#define HCI_OP_Read_Local_Version_Information 0x1001 ++#define HCI_OP_Read_BD_ADDR 0x1009 ++#define HCI_OP_Read_Local_Supported_Commands 0x1002 ++#define HCI_OP_Write_Scan_Enable 0x0c1a ++#define HCI_OP_Write_Current_IAC_LAP 0x0c3a ++#define HCI_OP_Write_Inquiry_Scan_Activity 0x0c1e ++#define HCI_OP_Write_Class_of_Device 0x0c24 ++#define HCI_OP_LE_Rand 0x2018 ++#define HCI_OP_LE_Set_Random_Address 0x2005 ++#define HCI_OP_LE_Set_Extended_Scan_Enable 0x2042 ++#define HCI_OP_LE_Set_Extended_Scan_Parameters 0x2041 ++#define HCI_OP_Set_Event_Filter 0x0c05 ++#define HCI_OP_Write_Voice_Setting 0x0c26 ++#define HCI_OP_Change_Local_Name 0x0c13 ++#define HCI_OP_Read_Local_Name 0x0c14 ++#define HCI_OP_Wirte_Page_Timeout 0x0c18 ++#define HCI_OP_LE_Clear_Resolving_List 0x0c29 ++#define HCI_OP_LE_Set_Addres_Resolution_Enable_Command 0x0c2e ++#define HCI_OP_Write_Inquiry_mode 0x0c45 ++#define HCI_OP_Write_Page_Scan_Type 0x0c47 ++#define HCI_OP_Write_Inquiry_Scan_Type 0x0c43 ++ ++#define HCI_OP_Delete_Stored_Link_Key 0x0c12 ++#define HCI_OP_LE_Read_Local_Resolvable_Address 0x202d ++#define HCI_OP_LE_Extended_Create_Connection 0x2043 ++#define HCI_OP_Read_Remote_Version_Information 0x041d ++#define HCI_OP_LE_Start_Encryption 0x2019 ++#define HCI_OP_LE_Add_Device_to_Resolving_List 0x2027 ++#define HCI_OP_LE_Set_Privacy_Mode 0x204e ++#define HCI_OP_LE_Connection_Update 0x2013 ++ ++/* ----- HCI events---- */ ++#define HCI_OP_DISCONNECT 0x0406 ++#define HCI_EV_INQUIRY_COMPLETE 0x01 ++#define HCI_EV_INQUIRY_RESULT 0x02 ++#define HCI_EV_CONN_COMPLETE 0x03 ++#define HCI_EV_CONN_REQUEST 0x04 ++#define HCI_EV_DISCONN_COMPLETE 0x05 ++#define HCI_EV_AUTH_COMPLETE 0x06 ++#define HCI_EV_REMOTE_NAME 0x07 ++#define HCI_EV_ENCRYPT_CHANGE 0x08 ++#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09 ++ ++#define HCI_EV_REMOTE_FEATURES 0x0b ++#define HCI_EV_REMOTE_VERSION 0x0c ++#define HCI_EV_QOS_SETUP_COMPLETE 0x0d ++#define HCI_EV_CMD_COMPLETE 0x0e ++#define HCI_EV_CMD_STATUS 0x0f ++ ++#define HCI_EV_ROLE_CHANGE 0x12 ++#define HCI_EV_NUM_COMP_PKTS 0x13 ++#define HCI_EV_MODE_CHANGE 0x14 ++#define HCI_EV_PIN_CODE_REQ 0x16 ++#define HCI_EV_LINK_KEY_REQ 0x17 ++#define HCI_EV_LINK_KEY_NOTIFY 0x18 ++#define HCI_EV_CLOCK_OFFSET 0x1c ++#define HCI_EV_PKT_TYPE_CHANGE 0x1d ++#define HCI_EV_PSCAN_REP_MODE 0x20 ++ ++#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22 ++#define HCI_EV_REMOTE_EXT_FEATURES 0x23 ++#define HCI_EV_SYNC_CONN_COMPLETE 0x2c ++#define HCI_EV_SYNC_CONN_CHANGED 0x2d ++#define HCI_EV_SNIFF_SUBRATE 0x2e ++#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f ++#define HCI_EV_IO_CAPA_REQUEST 0x31 ++#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36 ++#define HCI_EV_REMOTE_HOST_FEATURES 0x3d ++#define HCI_EV_LE_Meta 0x3e ++ ++/* ULP Event sub code */ ++#define HCI_BLE_CONN_COMPLETE_EVT 0x01 ++#define HCI_BLE_ADV_PKT_RPT_EVT 0x02 ++#define HCI_BLE_LL_CONN_PARAM_UPD_EVT 0x03 ++#define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT 0x04 ++#define HCI_BLE_LTK_REQ_EVT 0x05 ++#define HCI_BLE_RC_PARAM_REQ_EVT 0x06 ++#define HCI_BLE_DATA_LENGTH_CHANGE_EVT 0x07 ++#define HCI_BLE_ENHANCED_CONN_COMPLETE_EVT 0x0a ++#define HCI_BLE_DIRECT_ADV_EVT 0x0b ++#define HCI_BLE_PHY_UPDATE_COMPLETE_EVT 0x0c ++#define HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT 0x0D ++#define HCI_BLE_PERIODIC_ADV_SYNC_EST_EVT 0x0E ++#define HCI_BLE_PERIODIC_ADV_REPORT_EVT 0x0F ++#define HCI_BLE_PERIODIC_ADV_SYNC_LOST_EVT 0x10 ++#define HCI_BLE_SCAN_TIMEOUT_EVT 0x11 ++#define HCI_LE_ADVERTISING_SET_TERMINATED_EVT 0x12 ++#define HCI_BLE_SCAN_REQ_RX_EVT 0x13 ++#define HCI_BLE_CIS_EST_EVT 0x19 ++#define HCI_BLE_CIS_REQ_EVT 0x1a ++#define HCI_BLE_CREATE_BIG_CPL_EVT 0x1b ++#define HCI_BLE_TERM_BIG_CPL_EVT 0x1c ++#define HCI_BLE_BIG_SYNC_EST_EVT 0x1d ++#define HCI_BLE_BIG_SYNC_LOST_EVT 0x1e ++#define HCI_BLE_REQ_PEER_SCA_CPL_EVT 0x1f ++ ++#define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */ ++ ++#define CONFIG_MAC_OFFSET_GEN_1_2 (0x3C) //MAC's OFFSET in config/efuse for aic generation 1~2 bluetooth chip ++#define CONFIG_MAC_OFFSET_GEN_3PLUS (0x44) //MAC's OFFSET in config/efuse for aic generation 3+ bluetooth chip ++ ++//Define ioctl cmd the same as HCIDEVUP in the kernel ++#define DOWN_FW_CFG _IOW('E', 176, int) ++//#ifdef CONFIG_SCO_OVER_HCI ++//#define SET_ISO_CFG _IOW('H', 202, int) ++//#else ++#define SET_ISO_CFG _IOW('E', 177, int) ++//#endif ++#define RESET_CONTROLLER _IOW('E', 178, int) ++#define DWFW_CMPLT _IOW('E', 179, int) ++ ++#define GET_USB_INFO _IOR('E', 180, int) ++ ++void bt_data_dump(char* tag, void* data, unsigned long len); ++int aic_enqueue(struct sk_buff *skb); ++int aic_queue_cnt(void); ++int bt_sdio_recv(u8 *data,u32 data_len); ++ ++ ++int btchr_init(void); ++void btchr_exit(void); ++int hdev_init(void); ++void hdev_exit(void); ++ ++ ++struct hci_dev *hci_dev_get(int index); ++int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); ++#else ++int btsdio_init(void); ++void btsdio_remove(void); ++int bt_sdio_recv(u8 *data,u32 data_len); ++#endif ++#endif//_AICWF_SDIO_BT_H_ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.c +new file mode 100644 +index 000000000000..4f3d5867dd04 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.c +@@ -0,0 +1,2023 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file aic_priv_cmd.c ++ * ++ * @brief Entry point of the AIC driver ++ * ++ * Copyright (C) Aicsemi 2018-2024 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include "rwnx_defs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_main.h" ++#include "aicwf_sdio.h" ++#include "aic_priv_cmd.h" ++#include "rwnx_mod_params.h" ++ ++ ++extern int testmode; ++static void print_help(const char *cmd); ++struct dbg_rftest_cmd_cfm cfm = {{0,}}; ++ ++#ifdef CONFIG_RFTEST ++enum { ++ SET_TX, ++ SET_TXSTOP, ++ SET_TXTONE, ++ SET_RX, ++ GET_RX_RESULT, ++ SET_RXSTOP, ++ SET_RX_METER, ++ SET_POWER, ++ SET_XTAL_CAP, ++ SET_XTAL_CAP_FINE, ++ GET_EFUSE_BLOCK, ++ SET_FREQ_CAL, ++ SET_FREQ_CAL_FINE, ++ GET_FREQ_CAL, ++ SET_MAC_ADDR, ++ GET_MAC_ADDR, ++ SET_BT_MAC_ADDR, ++ GET_BT_MAC_ADDR, ++ SET_VENDOR_INFO, ++ GET_VENDOR_INFO, ++ RDWR_PWRMM, ++ RDWR_PWRIDX, ++ RDWR_PWRLVL = RDWR_PWRIDX, ++ RDWR_PWROFST, ++ RDWR_DRVIBIT, ++ RDWR_EFUSE_PWROFST, ++ RDWR_EFUSE_DRVIBIT, ++ SET_PAPR, ++ SET_CAL_XTAL, ++ GET_CAL_XTAL_RES, ++ SET_COB_CAL, ++ GET_COB_CAL_RES, ++ RDWR_EFUSE_USRDATA, ++ SET_NOTCH, ++ RDWR_PWROFSTFINE, ++ RDWR_EFUSE_PWROFSTFINE, ++ RDWR_EFUSE_SDIOCFG, ++ RDWR_EFUSE_USBVIDPID, ++ SET_SRRC, ++ SET_FSS, ++ RDWR_EFUSE_HE_OFF, ++ SET_USB_OFF, ++ SET_PLL_TEST, ++ SET_ANT_MODE, ++ RDWR_BT_EFUSE_PWROFST, ++}; ++ ++typedef struct { ++ u8_l chan; ++ u8_l bw; ++ u8_l mode; ++ u8_l rate; ++ u16_l length; ++ u16_l tx_intv_us; ++ s8_l max_pwr; ++} cmd_rf_settx_t; ++ ++typedef struct { ++ u8_l val; ++} cmd_rf_setfreq_t; ++ ++typedef struct { ++ u8_l chan; ++ u8_l bw; ++} cmd_rf_rx_t; ++ ++typedef struct { ++ u8_l block; ++} cmd_rf_getefuse_t; ++ ++typedef struct { ++ u8_l dutid; ++ u8_l chip_num; ++ u8_l dis_xtal; ++} cmd_rf_setcobcal_t; ++ ++typedef struct { ++ u16_l dut_rcv_golden_num; ++ u8_l golden_rcv_dut_num; ++ s8_l rssi_static; ++ s8_l snr_static; ++ s8_l dut_rssi_static; ++ u16_l reserved; ++} cob_result_ptr_t; ++#endif ++ ++typedef struct ++{ ++ u8_l func; ++ u8_l cnt; ++ u8_l reserved[2]; ++ u32_l usrdata[3]; // 3 words totally ++} cmd_ef_usrdata_t; ++ ++#define CMD_MAXARGS 10 ++#define POWER_LEVEL_INVALID_VAL (127) ++ ++extern char country_code[]; ++ ++#if 0//#include ++#define isblank(c) ((c) == ' ' || (c) == '\t') ++#define isascii(c) (((unsigned char)(c)) <= 0x7F) ++ ++static int isdigit(unsigned char c) ++{ ++ return ((c >= '0') && (c <='9')); ++} ++ ++static int isxdigit(unsigned char c) ++{ ++ if ((c >= '0') && (c <='9')) ++ return 1; ++ if ((c >= 'a') && (c <='f')) ++ return 1; ++ if ((c >= 'A') && (c <='F')) ++ return 1; ++ return 0; ++} ++ ++static int islower(unsigned char c) ++{ ++ return ((c >= 'a') && (c <='z')); ++} ++ ++static unsigned char toupper(unsigned char c) ++{ ++ if (islower(c)) ++ c -= 'a'-'A'; ++ return c; ++} ++#endif ++ ++static int parse_line (char *line, char *argv[]) ++{ ++ int nargs = 0; ++ ++ while (nargs < CMD_MAXARGS) { ++ /* skip any white space */ ++ while ((*line == ' ') || (*line == '\t')) { ++ ++line; ++ } ++ ++ if (*line == '\0') { /* end of line, no more args */ ++ argv[nargs] = 0; ++ return nargs; ++ } ++ ++ /* Argument include space should be bracketed by quotation mark */ ++ if (*line == '\"') { ++ /* Skip quotation mark */ ++ line++; ++ ++ /* Begin of argument string */ ++ argv[nargs++] = line; ++ ++ /* Until end of argument */ ++ while (*line && (*line != '\"')) { ++ ++line; ++ } ++ } else { ++ argv[nargs++] = line; /* begin of argument string */ ++ ++ /* find end of string */ ++ while (*line && (*line != ' ') && (*line != '\t')) { ++ ++line; ++ } ++ } ++ ++ if (*line == '\0') { /* end of line, no more args */ ++ argv[nargs] = 0; ++ return nargs; ++ } ++ ++ *line++ = '\0'; /* terminate current arg */ ++ } ++ ++ printk("** Too many args (max. %d) **\n", CMD_MAXARGS); ++ ++ return nargs; ++} ++ ++unsigned int command_strtoul(const char *cp, char **endp, unsigned int base) ++{ ++ unsigned int result = 0, value, is_neg = 0; ++ ++ if (*cp == '0') { ++ cp++; ++ if ((*cp == 'x') && isxdigit(cp[1])) { ++ base = 16; ++ cp++; ++ } ++ if (!base) { ++ base = 8; ++ } ++ } ++ if (!base) { ++ base = 10; ++ } ++ if (*cp == '-') { ++ is_neg = 1; ++ cp++; ++ } ++ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0' : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) { ++ result = result * base + value; ++ cp++; ++ } ++ if (is_neg) ++ result = (unsigned int)((int)result * (-1)); ++ ++ if (endp) ++ *endp = (char *)cp; ++ return result; ++} ++ ++/* ++ * aic_priv_cmd handers. ++ */ ++static int aic_priv_cmd_set_tx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_settx_t settx_param; ++ u8_l set_p = 0; ++ u8_l lvl_band, lvl_mod, lvl_idx, lvl_pwr = 0; ++ u8_l buf[10]; ++#ifdef CONFIG_POWER_LIMIT ++ int8_t max_pwr; ++ uint8_t r_idx; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++ txpwr_loss = &txpwr_loss_tmp; ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (argc < 6) ++ return -EINVAL; ++ ++ settx_param.chan = command_strtoul(argv[1], NULL, 10); ++ settx_param.bw = command_strtoul(argv[2], NULL, 10); ++ settx_param.mode = command_strtoul(argv[3], NULL, 10); ++ settx_param.rate = command_strtoul(argv[4], NULL, 10); ++ settx_param.length = command_strtoul(argv[5], NULL, 10); ++ if (argc > 6) { ++ settx_param.tx_intv_us = command_strtoul(argv[6], NULL, 10); ++ } else { ++ settx_param.tx_intv_us = 10000; // set default val 10ms ++ } ++ if (argc > 7) { ++ if (dev->chipid == PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ return -EINVAL; ++ } ++ lvl_pwr = command_strtoul(argv[7], NULL, 10); ++ AICWFDBG(LOGINFO, "lvl_pwr: %d\n", lvl_pwr); ++ ++ if (settx_param.chan >= 36) ++ lvl_band = 2; ++ else ++ lvl_band = 1; ++ if (settx_param.mode == 0) ++ lvl_mod = 0; ++ else if (settx_param.mode == 2 || settx_param.mode == 4) ++ lvl_mod = 1; ++ else if (settx_param.mode == 5) ++ lvl_mod = 2; ++ if (settx_param.mode >= 4) ++ lvl_idx = settx_param.rate & 0xF; ++ else if (settx_param.mode >= 2) ++ lvl_idx = settx_param.rate & 0x7; ++ else ++ lvl_idx = settx_param.rate; ++ ++ buf[0] = lvl_band; ++ buf[1] = lvl_mod; ++ buf[2] = lvl_idx; ++ buf[3] = lvl_pwr; ++ ++ set_p = 1; ++ } ++ settx_param.max_pwr = POWER_LEVEL_INVALID_VAL; ++ AICWFDBG(LOGINFO, "txparam:%d,%d,%d,%d,%d,%d\n", settx_param.chan, settx_param.bw, ++ settx_param.mode, settx_param.rate, settx_param.length, settx_param.tx_intv_us); ++ ++#ifdef CONFIG_POWER_LIMIT ++ r_idx = get_ccode_region(country_code); ++ txpwr_loss = &txpwr_loss_tmp; ++ get_userconfig_txpwr_loss(txpwr_loss); ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ if (txpwr_loss->loss_enable_5g == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ max_pwr = get_powerlimit_by_chnum(settx_param.chan, r_idx, settx_param.bw); ++ if (settx_param.chan >= 36) { ++ if (txpwr_loss->loss_enable_5g == 1) ++ max_pwr -= txpwr_loss->loss_value_5g; ++ } else { ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ max_pwr -= txpwr_loss->loss_value_2g4; ++ } ++ ++ if (!set_p || (lvl_pwr == 255)) { ++ settx_param.max_pwr = max_pwr; ++ AICWFDBG(LOGINFO, "max_pwr:%d\n", settx_param.max_pwr); ++ } else ++ AICWFDBG(LOGINFO, "the specified power is input without power limit\n"); ++#endif ++ ++ if (set_p && (lvl_pwr != 255)) ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, 4, buf, &cfm); ++ ++ rwnx_send_rftest_req(rwnx_hw, SET_TX, sizeof(cmd_rf_settx_t), (u8_l *)&settx_param, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_txstop (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_TXSTOP, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_rx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_rx_t setrx_param; ++ ++ if (argc < 3) { ++ return -EINVAL; ++ } ++ setrx_param.chan = command_strtoul(argv[1], NULL, 10); ++ setrx_param.bw = command_strtoul(argv[2], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_RX, sizeof(cmd_rf_rx_t), (u8_l *)&setrx_param, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_rx_result (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, GET_RX_RESULT, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ return 8; ++} ++ ++static int aic_priv_cmd_set_rxstop (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_RXSTOP, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_tx_tone (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ u8_l buf[2]; ++ s8_l freq_ = 0; ++ ++ AICWFDBG(LOGINFO, "%s argc:%d\n", argv[0], argc); ++ if ((argc == 2) || (argc == 3)) { ++ AICWFDBG(LOGINFO, "argv 1:%s\n",argv[1]); ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ if (argc == 3) { ++ AICWFDBG(LOGINFO, "argv 2:%s\n",argv[2]); ++ freq_ = (u8_l)command_strtoul(argv[2], NULL, 10); ++ } else { ++ freq_ = 0; ++ }; ++ buf[0] = func; ++ buf[1] = (u8_l)freq_; ++ rwnx_send_rftest_req(rwnx_hw, SET_TXTONE, argc - 1, buf, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_rx_meter (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ s8_l freq = 0; ++ ++ freq = (int)command_strtoul(argv[1], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_RX_METER, sizeof(freq), (u8_l *)&freq, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_set_power (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l ana_pwr; ++ u8_l dig_pwr; ++ u8_l pwr; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (dev->chipid == PRODUCT_ID_AIC8801) { ++ ana_pwr = command_strtoul(argv[1], NULL, 16); ++ dig_pwr = command_strtoul(argv[2], NULL, 16); ++ pwr = (ana_pwr << 4 | dig_pwr); ++ if (ana_pwr > 0xf || dig_pwr > 0xf) ++ return -EINVAL; ++ } else { ++ ana_pwr = command_strtoul(argv[1], NULL, 10); ++ pwr = ana_pwr; ++ if (ana_pwr > 0x1e) ++ return -EINVAL; ++ } ++ AICWFDBG(LOGINFO, "pwr =%x\r\n", pwr); ++ rwnx_send_rftest_req(rwnx_hw, SET_POWER, sizeof(pwr), (u8_l *)&pwr, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_xtal_cap (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l xtal_cap; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ xtal_cap = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "xtal_cap =%x\r\n", xtal_cap); ++ rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap), (u8_l *)&xtal_cap, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_xtal_cap_fine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l xtal_cap_fine; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ xtal_cap_fine = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "xtal_cap_fine =%x\r\n", xtal_cap_fine); ++ rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP_FINE, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_get_efuse_block (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_getefuse_t getefuse_param; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ getefuse_param.block = command_strtoul(argv[1], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, GET_EFUSE_BLOCK, sizeof(cmd_rf_getefuse_t), (u8_l *)&getefuse_param, &cfm); ++ AICWFDBG(LOGINFO, "get val=%x\r\n", cfm.rftest_result[0]); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_setfreq_t cmd_setfreq; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); ++ rwnx_send_rftest_req(rwnx_hw, SET_FREQ_CAL, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_freq_cal_fine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_setfreq_t cmd_setfreq; ++ ++ if (argc < 2) ++ return -EINVAL; ++ ++ cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); ++ rwnx_send_rftest_req(rwnx_hw, SET_FREQ_CAL_FINE, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_get_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u32_l val; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_FREQ_CAL, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ val = cfm.rftest_result[0]; ++ if (dev->chipid != PRODUCT_ID_AIC8801) { ++ AICWFDBG(LOGINFO, "cap=0x%x (remain:%x), cap_fine=%x (remain:%x)\n", ++ val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff); ++ } else { ++ AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", val & 0xff, (val >> 8) & 0xff); ++ } ++ return 4; ++} ++ ++static int aic_priv_cmd_set_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l mac_addr[6]; ++ ++ if (argc < 7) ++ return -EINVAL; ++ ++ mac_addr[5] = command_strtoul(argv[1], NULL, 16); ++ mac_addr[4] = command_strtoul(argv[2], NULL, 16); ++ mac_addr[3] = command_strtoul(argv[3], NULL, 16); ++ mac_addr[2] = command_strtoul(argv[4], NULL, 16); ++ mac_addr[1] = command_strtoul(argv[5], NULL, 16); ++ mac_addr[0] = command_strtoul(argv[6], NULL, 16); ++ AICWFDBG(LOGINFO, "set macaddr:%x,%x,%x,%x,%x,%x\n", mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); ++ rwnx_send_rftest_req(rwnx_hw, SET_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u32_l addr0, addr1; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_MAC_ADDR, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ addr0 = cfm.rftest_result[0]; ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ int rem_cnt = (cfm.rftest_result[1] >> 16) & 0x00FF; ++ addr1 = cfm.rftest_result[1] & 0x0000FFFF; ++ AICWFDBG(LOGINFO, "0x%x,0x%x (remain:%x)\n", addr0, addr1, rem_cnt); ++ } else { ++ addr1 = cfm.rftest_result[1]; ++ AICWFDBG(LOGINFO, "0x%x,0x%x\n", addr0, addr1); ++ } ++ return 8; ++} ++ ++static int aic_priv_cmd_set_bt_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l mac_addr[6]; ++ ++ if (argc < 7) ++ return -EINVAL; ++ ++ mac_addr[5] = command_strtoul(argv[1], NULL, 16); ++ mac_addr[4] = command_strtoul(argv[2], NULL, 16); ++ mac_addr[3] = command_strtoul(argv[3], NULL, 16); ++ mac_addr[2] = command_strtoul(argv[4], NULL, 16); ++ mac_addr[1] = command_strtoul(argv[5], NULL, 16); ++ mac_addr[0] = command_strtoul(argv[6], NULL, 16); ++ AICWFDBG(LOGINFO, "set bt macaddr:%x,%x,%x,%x,%x,%x\n", mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); ++ rwnx_send_rftest_req(rwnx_hw, SET_BT_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_bt_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u32_l addr0, addr1; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_BT_MAC_ADDR, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ addr0 = cfm.rftest_result[0]; ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ int rem_cnt = (cfm.rftest_result[1] >> 16) & 0x00FF; ++ addr1 = cfm.rftest_result[1] & 0x0000FFFF; ++ AICWFDBG(LOGINFO, "0x%x,0x%x (remain:%x)\n", addr0, addr1, rem_cnt); ++ } else { ++ addr1 = cfm.rftest_result[1]; ++ AICWFDBG(LOGINFO, "0x%x,0x%x\n", addr0, addr1); ++ } ++ return 8; ++} ++ ++static int aic_priv_cmd_set_vendor_info (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l vendor_info; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ vendor_info = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "set vendor info:%x\n", vendor_info); ++ rwnx_send_rftest_req(rwnx_hw, SET_VENDOR_INFO, 1, &vendor_info, &cfm); ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ memcpy(command, &cfm.rftest_result[0], 2); ++ return 2; ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 1); ++ return 1; ++ } ++ AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); ++} ++ ++static int aic_priv_cmd_get_vendor_info (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_VENDOR_INFO, 0, NULL, &cfm); ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { ++ memcpy(command, &cfm.rftest_result[0], 2); ++ return 2; ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 1); ++ return 1; ++ } ++ AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); ++} ++ ++static int aic_priv_cmd_rdwr_pwrmm (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ if (argc <= 1) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRMM, 0, NULL, &cfm); ++ } else { // write ++ u8_l pwrmm = (u8_l)command_strtoul(argv[1], NULL, 16); ++ pwrmm = (pwrmm) ? 1 : 0; ++ AICWFDBG(LOGINFO, "set pwrmm = %x\r\n", pwrmm); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRMM, sizeof(pwrmm), (u8_l *)&pwrmm, &cfm); ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_pwridx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (dev->chipid != PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ return -EINVAL; ++ } ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRIDX, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr idx ++ if (argc > 3) { ++ u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l pwridx = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, type, pwridx}; ++ AICWFDBG(LOGINFO, "set pwridx:[%x][%x]=%x\r\n", func, type, pwridx); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRIDX, sizeof(buf), buf, &cfm); ++ } else { ++ return -EINVAL; ++ } ++ } else { ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 9); ++ return 9; ++} ++ ++static int aic_priv_cmd_rdwr_pwrlvl (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (dev->chipid == PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ return -EINVAL; ++ } ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr lvl ++ if (argc > 4) { ++ u8_l grp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l idx, size; ++ u8_l buf[14] = {func, grp,}; ++ if (argc > 12) { // set all grp ++ AICWFDBG(LOGINFO, "set pwrlvl %s:\n" ++ " [%x] =", (func == 1) ? "2.4g" : "5g", grp); ++ if (grp == 1) { // TXPWR_LVL_GRP_11N_11AC ++ size = 10; ++ } else { ++ size = 12; ++ } ++ for (idx = 0; idx < size; idx++) { ++ s8_l pwrlvl = (s8_l)command_strtoul(argv[3 + idx], NULL, 10); ++ buf[2 + idx] = (u8_l)pwrlvl; ++ if (idx && !(idx & 0x3)) { ++ AICWFDBG(LOGINFO, " "); ++ } ++ AICWFDBG(LOGINFO, " %2d", pwrlvl); ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ size += 2; ++ } else { // set grp[idx] ++ u8_l idx = (u8_l)command_strtoul(argv[3], NULL, 10); ++ s8_l pwrlvl = (s8_l)command_strtoul(argv[4], NULL, 10); ++ buf[2] = idx; ++ buf[3] = (u8_l)pwrlvl; ++ size = 4; ++ AICWFDBG(LOGINFO, "set pwrlvl %s:\n" ++ " [%x][%d] = %d\n", (func == 1) ? "2.4g" : "5g", grp, idx, pwrlvl); ++ } ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, size, buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ if(dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ memcpy(command, &cfm.rftest_result[0], 6 * 12); ++ return (6 * 12); ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 3 * 12); ++ return (3 * 12); ++ } ++} ++ ++static int aic_priv_cmd_rdwr_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ int res_len = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, 0, NULL, &cfm); ++ } else if (func <= 4) { // write 2.4g/5g pwr ofst and ant0/1 ++ if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); ++ u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); ++ } else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D80) && (dev->chipid != PRODUCT_ID_AIC8800D80X2)) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); ++ } else { ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { // 3 = 3 (2.4g) ++ res_len = 3; ++ } else if (dev->chipid == PRODUCT_ID_AIC8800D80) { // 3 * 2 (2.4g) + 3 * 6 (5g) ++ res_len = 3 * 3 + 3 * 6; ++ } else if (dev->chipid == PRODUCT_ID_AIC8800D80X2) { // ant0/1 ++ res_len = ( 3 * 3 + 3 * 6 ) * 2; ++ } else { ++ res_len = 3 + 4; ++ } ++ memcpy(command, &cfm.rftest_result[0], res_len); ++ return res_len; ++} ++ ++static int aic_priv_cmd_rdwr_pwrofstfine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr ofst ++ if (argc > 3) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ ++ } ++ memcpy(command, &cfm.rftest_result[0], 7); ++ return 7; ++} ++ ++static int aic_priv_cmd_rdwr_drvibit (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_DRVIBIT, 0, NULL, &cfm); ++ } else if (func == 1) { // write 2.4g pa drv_ibit ++ if (argc > 2) { ++ u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[2] = {func, ibit}; ++ AICWFDBG(LOGINFO, "set drvibit:[%x]=%x\r\n", func, ibit); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_DRVIBIT, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 16); ++ return 16; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ int res_len = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *dev = g_rwnx_plat->usbdev; ++#endif ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, 0, NULL, &cfm); ++ } else if (func <= 4) { // write 2.4g/5g pwr ofst and ant0/1 ++ if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); ++ u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set efuse pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); ++ } else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D80) && (dev->chipid != PRODUCT_ID_AIC8800D80X2)) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set efuse pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { // 6 = 3 (2.4g) * 2 ++ res_len = 3 * 2; ++ } else if (dev->chipid == PRODUCT_ID_AIC8800D80 || dev->chipid == PRODUCT_ID_AIC8800D80X2) { // 3 * 2 (2.4g) + 3 * 6 (5g) ++ res_len = (3 * 3 + 3 * 6) * 2; ++ } else { // 7 = 3(2.4g) + 4(5g) ++ res_len = 3 + 4; ++ } ++ memcpy(command, &cfm.rftest_result[0], res_len); ++ return res_len; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_pwrofstfine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, 0, NULL, &cfm); ++ } else if (func <= 2) { // write 2.4g/5g pwr ofst ++ if (argc > 3) { ++ u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); ++ s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); ++ u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; ++ AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 7); ++ return 7; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_drvibit (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_DRVIBIT, 0, NULL, &cfm); ++ } else if (func == 1) { // write 2.4g pa drv_ibit ++ if (argc > 2) { ++ u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[2] = {func, ibit}; ++ AICWFDBG(LOGINFO, "set efuse drvibit:[%x]=%x\r\n", func, ibit); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_DRVIBIT, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_usrdata (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_ef_usrdata_t cmd_ef_usrdata; ++ ++ if (argc <= 1) { // read all ++ cmd_ef_usrdata.func = 0; ++ cmd_ef_usrdata.cnt = 3; ++ } else if (argc >= 2) { // read/write ++ cmd_ef_usrdata.func = (u8_l)command_strtoul(argv[1], NULL, 10); ++ cmd_ef_usrdata.cnt = (u8_l)command_strtoul(argv[2], NULL, 10); ++ if (cmd_ef_usrdata.func == 1) { ++ int idx; ++ for (idx = 0; idx < cmd_ef_usrdata.cnt; idx++) { ++ cmd_ef_usrdata.usrdata[idx] = (u32_l)command_strtoul(argv[3 + idx], NULL, 16); ++ } ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong argc: %x\n", argc); ++ return -EINVAL; ++ } ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USRDATA, sizeof(cmd_ef_usrdata), (u8_l *)&cmd_ef_usrdata, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 12); ++ return 12; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_sdiocfg (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_SDIOCFG, 0, NULL, &cfm); ++ } else if (func == 1) { // write sdiocfg ++ if (argc > 2) { ++ u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[2] = {func, ibit}; ++ AICWFDBG(LOGINFO, "set efuse sdiocfg:[%x]=%x\r\n", func, ibit); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_SDIOCFG, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_usbvidpid (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ AICWFDBG(LOGINFO, "read/write usb vid/pid into efuse\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USBVIDPID, 0, NULL, &cfm); ++ } else if (func == 1) { // write USB vid+pid ++ if (argc > 2) { ++ u32_l usb_id = (u32_l)command_strtoul(argv[2], NULL, 16); ++ u8_l buf[5] = {func, (u8_l)usb_id, (u8_l)(usb_id >> 8), (u8_l)(usb_id >> 16), (u8_l)(usb_id >> 24)}; ++ AICWFDBG(LOGINFO, "set efuse usb vid/pid:[%x]=%x\r\n", func, usb_id); ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USBVIDPID, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ return -EINVAL; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++} ++ ++static int aic_priv_cmd_rdwr_efuse_he_off (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set he off: %d\n", func); ++ if(func == 1 || func == 0) { ++ rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_HE_OFF, sizeof(func), (u8_l *)&func, &cfm); ++ AICWFDBG(LOGINFO, "he_off cfm: %d\n", cfm.rftest_result[0]); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ return 4; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_cal_xtal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_CAL_XTAL, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_cal_xtal_res (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, GET_CAL_XTAL_RES, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", cfm.rftest_result[0] & 0x0000ffff, (cfm.rftest_result[0] >> 16) & 0x0000ffff); ++ return 4; ++} ++ ++static int aic_priv_cmd_set_cob_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ cmd_rf_setcobcal_t setcob_cal; ++ ++ if (argc < 3) ++ return -EINVAL; ++ setcob_cal.dutid = command_strtoul(argv[1], NULL, 10); ++ setcob_cal.chip_num = command_strtoul(argv[2], NULL, 10); ++ setcob_cal.dis_xtal = command_strtoul(argv[3], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_get_cob_cal_res (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l state; ++ cob_result_ptr_t *cob_result_ptr; ++ ++ rwnx_send_rftest_req(rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); ++ state = (cfm.rftest_result[0] >> 16) & 0x000000ff; ++ if (!state){ ++ AICWFDBG(LOGINFO, "cap= 0x%x, cap_fine= 0x%x, freq_ofst= %d Hz\n", ++ cfm.rftest_result[0] & 0x000000ff, (cfm.rftest_result[0] >> 8) & 0x000000ff, cfm.rftest_result[1]); ++ cob_result_ptr = (cob_result_ptr_t *) & (cfm.rftest_result[2]); ++ AICWFDBG(LOGINFO, "golden_rcv_dut= %d , tx_rssi= %d dBm, snr = %d dB\ndut_rcv_godlden= %d , rx_rssi= %d dBm", ++ cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, ++ cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static); ++ memcpy(command, &cfm.rftest_result, 16); ++ return 16; ++ } else { ++ AICWFDBG(LOGERROR, "cob not idle\n"); ++ return -EINVAL; ++ } ++} ++ ++static int aic_priv_cmd_do_cob_test (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l state; ++ cmd_rf_setcobcal_t setcob_cal; ++ cob_result_ptr_t *cob_result_ptr; ++ ++ setcob_cal.dutid = 1; ++ setcob_cal.chip_num = 1; ++ setcob_cal.dis_xtal = 0; ++ if (argc > 1) ++ setcob_cal.dis_xtal = command_strtoul(argv[1], NULL, 10); ++ rwnx_send_rftest_req(rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); ++ msleep(2000); ++ rwnx_send_rftest_req(rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); ++ state = (cfm.rftest_result[0] >> 16) & 0x000000ff; ++ if (!state){ ++ AICWFDBG(LOGINFO, "cap= 0x%x, cap_fine= 0x%x, freq_ofst= %d Hz\n", ++ cfm.rftest_result[0] & 0x000000ff, (cfm.rftest_result[0] >> 8) & 0x000000ff, cfm.rftest_result[1]); ++ cob_result_ptr = (cob_result_ptr_t *) & (cfm.rftest_result[2]); ++ AICWFDBG(LOGINFO, "golden_rcv_dut= %d , tx_rssi= %d dBm, snr = %d dB\ndut_rcv_godlden= %d , rx_rssi= %d dBm", ++ cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, ++ cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static); ++ memcpy(command, &cfm.rftest_result, 16); ++ return 16; ++ } else { ++ AICWFDBG(LOGERROR, "cob not idle\n"); ++ return -EINVAL; ++ } ++} ++ ++static int aic_priv_cmd_set_papr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "papr %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_PAPR, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_notch (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "notch %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_NOTCH, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_srrc (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "srrc %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_SRRC, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_fss (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "fss %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_FSS, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_usb_off (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ rwnx_send_rftest_req(rwnx_hw, SET_USB_OFF, 0, NULL, NULL); ++ return 0; ++} ++ ++static int aic_priv_cmd_set_pll_test (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0, tx_pwr = 0xc; ++ s8_l freq = 0; ++ ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 16); ++ } ++ if (argc > 3) { ++ freq = (s8_l)command_strtoul(argv[2], NULL, 10); ++ tx_pwr = command_strtoul(argv[3], NULL, 16); ++ } ++ if (func <= 1) { ++ u8_l buf[3] = {func, (u8_l)freq, tx_pwr}; ++ AICWFDBG(LOGINFO, "set pll_test %d: freq=%d, tx_pwr=0x%x\n", func, freq, tx_pwr); ++ rwnx_send_rftest_req(rwnx_hw, SET_PLL_TEST, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_get_txpwr(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ s8_l power=0; ++ power = get_txpwr_max(power); ++ memcpy(command, &power, 1); ++ return 1; ++} ++ ++static int aic_priv_cmd_set_txpwr_loss(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ s8_l func; ++ if (argc > 1) { ++ func = (s8_l)command_strtoul(argv[1], NULL, 10); ++ printk("set txpwr loss: %d\n", func); ++ if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ set_txpwr_loss_ofst(func); ++ rwnx_send_txpwr_lvl_v3_req(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ set_txpwr_loss_ofst(func); ++ rwnx_send_txpwr_lvl_v4_req(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ set_txpwr_loss_ofst(func); ++ rwnx_send_txpwr_lvl_req(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else{ ++ AICWFDBG(LOGINFO,"error:don't support 8800D"); ++ } ++ } else { ++ printk("wrong args\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_set_ant_mode (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc > 1) { ++ func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "ant %d\r\n", func); ++ rwnx_send_rftest_req(rwnx_hw, SET_ANT_MODE, sizeof(func), (u8_l *)&func, NULL); ++ } else { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int aic_priv_cmd_rdwr_bt_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ u8_l func = 0; ++ if (argc == 1) { ++ func = 0; ++ } else if (argc == 2) { ++ func = 1; ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(rwnx_hw, RDWR_BT_EFUSE_PWROFST, 0, NULL, &cfm); ++ } else if (func == 1) { // write bt tx pwrofst ++ int8_t bt_txpwrofst = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set bt efuse pwrofst %d\r\n",bt_txpwrofst); ++ if (bt_txpwrofst < -7 || bt_txpwrofst > 7) { ++ AICWFDBG(LOGERROR, "wrong params %d, pwrofst limit -7 ~ 7\n", bt_txpwrofst); ++ return -EINVAL; ++ } else { ++ rwnx_send_rftest_req(rwnx_hw, RDWR_BT_EFUSE_PWROFST, sizeof(bt_txpwrofst), &bt_txpwrofst, &cfm); ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ return -EINVAL; ++ } ++ memcpy(command, &cfm.rftest_result[0], 2); ++ return 2; ++} ++ ++static int aic_priv_cmd_country_set(struct rwnx_hw *rwnx_hw, int argc, ++ char *argv[], char *command) ++{ ++ int ret = 0; ++ struct ieee80211_regdomain *regdomain; ++ ++ if (argc < 2) { ++ AICWFDBG(LOGINFO, "%s param err\n", __func__); ++ return -1; ++ } ++ ++ AICWFDBG(LOGINFO, "cmd country_set: %s\n", argv[1]); ++ ++ regdomain = getRegdomainFromRwnxDB(rwnx_hw->wiphy, argv[1]); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ ret = regulatory_set_wiphy_regd( ++ rwnx_hw->wiphy, regdomain); ++#else ++ ret = wiphy_apply_custom_regulatory( ++ rwnx_hw->wiphy, regdomain); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */ ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ rwnx_radar_set_domain(&rwnx_hw->radar, regdomain->dfs_region); ++#endif ++ ++#ifdef CONFIG_POWER_LIMIT ++ if (!testmode){ ++ rwnx_send_me_chan_config_req(rwnx_hw, argv[1]); ++ } ++#endif ++ ++ return ret; ++} ++ ++static int aic_priv_cmd_help (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) ++{ ++ print_help(argc > 0 ? argv[0] : NULL); ++ return 0; ++} ++ ++struct aic_priv_cmd { ++ const char *cmd; ++ int (*handler)(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command); ++ const char *usage; ++}; ++ ++static const struct aic_priv_cmd aic_priv_commands[] = { ++ { "set_tx", aic_priv_cmd_set_tx, ++ " " }, ++ { "set_txstop", aic_priv_cmd_set_txstop, ++ "= stop tx " }, ++ { "set_rx", aic_priv_cmd_set_rx, ++ " " }, ++ { "get_rx_result", aic_priv_cmd_get_rx_result, ++ "= display rx fcsok/total pkt num" }, ++ { "set_rxstop", aic_priv_cmd_set_rxstop, ++ "= stop rx " }, ++ { "set_txtone", aic_priv_cmd_set_tx_tone, ++ " val = 0/off" }, ++ { "set_rx_meter", aic_priv_cmd_set_rx_meter, ++ "= set rx meter " }, ++ { "set_power", aic_priv_cmd_set_set_power, ++ " " }, ++ { "set_xtal_cap", aic_priv_cmd_set_xtal_cap, ++ " [0 ~ 31]" }, ++ { "set_xtal_cap_fine", aic_priv_cmd_set_xtal_cap_fine, ++ " [0 ~ 63]" }, ++ { "get_efuse_block", aic_priv_cmd_get_efuse_block, ++ "" }, ++ { "set_freq_cal", aic_priv_cmd_set_freq_cal, ++ "" }, ++ { "set_freq_cal_fine", aic_priv_cmd_set_freq_cal_fine, ++ "" }, ++ { "get_freq_cal", aic_priv_cmd_get_freq_cal, ++ "= display cap & cap fine" }, ++ { "set_mac_addr", aic_priv_cmd_set_mac_addr, ++ "= write WiFi MAC into efuse or flash is limited to a maximum of two times" }, ++ { "get_mac_addr", aic_priv_cmd_get_mac_addr, ++ "= display WiFi MAC stored in efuse or flash" }, ++ { "set_bt_mac_addr", aic_priv_cmd_set_bt_mac_addr, ++ "= write BT MAC into efuse or flash is limited to a maximum of two times" }, ++ { "get_bt_mac_addr", aic_priv_cmd_get_bt_mac_addr, ++ "= display BT MAC stored in efuse or flash" }, ++ { "set_vendor_info", aic_priv_cmd_set_vendor_info, ++ "= write vendor info into efuse or flash is allowed only once" }, ++ { "get_vendor_info", aic_priv_cmd_get_vendor_info, ++ "= display vendor info stored in efuse or flash" }, ++ { "rdwr_pwrmm", aic_priv_cmd_rdwr_pwrmm, ++ " = 0/rdwr_pwrlvl, 1/set_power = read/write txpwr manul mode" }, ++ { "rdwr_pwridx", aic_priv_cmd_rdwr_pwridx, ++ " " }, ++ { "rdwr_pwrlvl", aic_priv_cmd_rdwr_pwrlvl, ++ " " }, ++ { "rdwr_pwrofst", aic_priv_cmd_rdwr_pwrofst, ++ " " }, ++ { "rdwr_pwrofstfine", aic_priv_cmd_rdwr_pwrofstfine, ++ " " }, ++ { "rdwr_drvibit", aic_priv_cmd_rdwr_drvibit, ++ " read/write 8800D pa drvibit" }, ++ { "set_cal_xtal", aic_priv_cmd_set_cal_xtal, ++ "= set cal xtal" }, ++ { "get_cal_xtal_res", aic_priv_cmd_get_cal_xtal_res, ++ "= get cal xtal result cap & cap_fine" }, ++ { "set_cob_cal", aic_priv_cmd_set_cob_cal, ++ " = dut cob test" }, ++ { "get_cob_cal_res", aic_priv_cmd_get_cob_cal_res, ++ "= get cob cal result" }, ++ { "do_cob_test", aic_priv_cmd_do_cob_test, ++ " = 0/xtal, 1/dis_xtal, 2/only_xtal" }, ++ { "rdwr_efuse_pwrofst", aic_priv_cmd_rdwr_efuse_pwrofst, ++ " limited to a maximum of two times" }, ++ { "rdwr_efuse_pwrofstfine", aic_priv_cmd_rdwr_efuse_pwrofstfine, ++ " limited to a maximum of two times" }, ++ { "rdwr_efuse_drvibit", aic_priv_cmd_rdwr_efuse_drvibit, ++ " = read/write 8800D efuse pa drvibitis allowed only once" }, ++ { "rdwr_efuse_usrdata", aic_priv_cmd_rdwr_efuse_usrdata, ++ " = read/write efuse usrdata" }, ++ { "rdwr_efuse_sdiocfg", aic_priv_cmd_rdwr_efuse_sdiocfg, ++ " = read/write sdiocfg_bit into efuse" }, ++ { "rdwr_efuse_usbvidpid", aic_priv_cmd_rdwr_efuse_usbvidpid, ++ " = read/write usb vid/pid into efuse" }, ++ { "rdwr_efuse_he_off", aic_priv_cmd_rdwr_efuse_he_off, ++ " = read/write he_off into efuse" }, ++ { "set_papr", aic_priv_cmd_set_papr, ++ " = configure papr filter to optimize sideband suppression" }, ++ { "set_notch", aic_priv_cmd_set_notch, ++ " = configure filter to optimize sideband suppression" }, ++ { "set_srrc", aic_priv_cmd_set_srrc, ++ " = disable/enable sideband suppression for SRRC" }, ++ { "set_fss", aic_priv_cmd_set_fss, ++ " = disable/enable treatment of spurious emissions and burrs" }, ++ { "set_usb_off", aic_priv_cmd_set_usb_off, ++ "= off usb configure before usb disconnect" }, ++ { "set_pll_test", aic_priv_cmd_set_pll_test, ++ " = use pll test to measure saturation power" }, ++ { "get_txpwr", aic_priv_cmd_get_txpwr, ++ "= get userconfig max txpwr" }, ++ { "set_txpwr_loss",aic_priv_cmd_set_txpwr_loss, ++ " = txpwr will change ,val can be negative" }, ++ { "set_ant", aic_priv_cmd_set_ant_mode, ++ " = 0/ant0, 1/ant1, 2/both" }, ++ { "rdwr_bt_efuse_pwrofst", aic_priv_cmd_rdwr_bt_efuse_pwrofst, ++ " = read/write bt tx power offset into efuse" }, ++ {"country_set", aic_priv_cmd_country_set, ""}, ++//Reserve for new aic_priv_cmd. ++ { "help", aic_priv_cmd_help, ++ "= show usage help" }, ++ { NULL, NULL, NULL } ++ ++}; ++ ++ ++/* ++ * Prints command usage, lines are padded with the specified string. ++ */ ++static void print_help(const char *cmd) ++{ ++ int n; ++ printk("commands:\n"); ++ for (n = 0; aic_priv_commands[n].cmd; n++) { ++ if (cmd != NULL) ++ printk("%s %s\n", aic_priv_commands[n].cmd, aic_priv_commands[n].usage); ++ } ++} ++ ++int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len) ++{ ++ const struct aic_priv_cmd *cmd, *match = NULL; ++ int count; ++ int bytes_written = 0; ++ char *argv[CMD_MAXARGS + 1]; ++ int argc; ++ struct rwnx_vif *vif = container_of(net->ieee80211_ptr, struct rwnx_vif, wdev); ++ struct rwnx_hw *p_rwnx_hw = vif->rwnx_hw; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#if 1 ++ if(!testmode) { ++ AICWFDBG(LOGERROR, "not in testmdoe\n"); ++ return -1; ++ } ++#endif ++ argc = parse_line(command, argv); ++ if (argc == 0) { ++ return -1; ++ } ++ ++ count = 0; ++ cmd = aic_priv_commands; ++ while (cmd->cmd) { ++ if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0 && ++ strncasecmp(cmd->cmd, argv[0], strlen(cmd->cmd)) == 0) ++ { ++ match = cmd; ++ if (strcasecmp(cmd->cmd, argv[0]) == 0) { ++ /* we have an exact match */ ++ count = 1; ++ break; ++ } ++ count++; ++ } ++ cmd++; ++ } ++ ++ if (count > 1) { ++ AICWFDBG(LOGINFO, "Ambiguous command '%s'; possible commands:", argv[0]); ++ cmd = aic_priv_commands; ++ while (cmd->cmd) { ++ if (strncasecmp(cmd->cmd, argv[0], ++ strlen(argv[0])) == 0) { ++ AICWFDBG(LOGINFO, " %s", cmd->cmd); ++ } ++ cmd++; ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ } else if (count == 0) { ++ AICWFDBG(LOGERROR, "Unknown command '%s'\n", argv[0]); ++ } else { ++ AICWFDBG(LOGINFO, "match %s", match->cmd); ++ bytes_written = match->handler(p_rwnx_hw, argc, &argv[0], command); ++ } ++ ++ if (bytes_written < 0) ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ ++ return bytes_written; ++} ++ ++#define RWNX_COUNTRY_CODE_LEN 2 ++#define CMD_SET_COUNTRY "COUNTRY" ++#define CMD_SET_VENDOR_EX_IE "SET_VENDOR_EX_IE" ++#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" ++#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" ++#define CMD_SET_MON_FREQ "SET_MON_FREQ" ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2); ++struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, int index); ++extern int reg_regdb_size; ++ ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++extern u8_l vendor_extension_data[256]; ++extern int vendor_extension_len; ++extern int testmode = 0; ++ ++void set_vendor_extension_ie(char *command){ ++ ++ char databyte[3]={0x00, 0x00, 0x00}; ++ int skip = strlen(CMD_SET_VENDOR_EX_IE) + 1; ++ int command_index = skip; ++ int data_index = 0; ++ ++ memset(vendor_extension_data, 0, 256); ++ vendor_extension_len = 0; ++ memcpy(databyte, command + command_index, 2); ++ vendor_extension_len = command_strtoul(databyte, NULL, 16); ++ printk("%s len:%d \r\n", __func__, vendor_extension_len); ++ ++ //parser command and save data in vendor_extension_data ++ for(data_index = 0;data_index < vendor_extension_len; data_index++){ ++ command_index = command_index + 3; ++ memcpy(databyte, command + command_index, 2); ++ vendor_extension_data[data_index] = command_strtoul(databyte, NULL, 16); ++ } ++ ++} ++#endif//CONFIG_SET_VENDOR_EXTENSION_IE ++int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef); ++int rwnx_atoi2(char *value, int c_len); ++void set_mon_chan(struct rwnx_vif *vif, char *parameter){ ++ struct cfg80211_chan_def *chandef = NULL; ++ int freq = 0; ++ ++ ++ chandef = (struct cfg80211_chan_def *)vmalloc(sizeof(struct cfg80211_chan_def)); ++ memset(chandef, 0, sizeof(struct cfg80211_chan_def)); ++ chandef->chan = (struct ieee80211_channel *)vmalloc(sizeof(struct ieee80211_channel)); ++ memset(chandef->chan, 0, sizeof(struct ieee80211_channel)); ++ ++ freq = rwnx_atoi2(parameter, 4); ++ ++ if(freq <= 2484){ ++ chandef->chan->band = NL80211_BAND_2GHZ; ++ }else{ ++ chandef->chan->band = NL80211_BAND_5GHZ; ++ } ++ chandef->chan->center_freq = freq; ++ chandef->width = NL80211_CHAN_WIDTH_20; ++ chandef->center_freq1 = chandef->chan->center_freq; ++ chandef->center_freq2 = 0; ++ ++ rwnx_cfg80211_set_monitor_channel_(vif->rwnx_hw->wiphy, chandef); ++ ++ vfree(chandef->chan); ++ vfree(chandef); ++ ++} ++ ++ ++int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) ++{ ++#define PRIVATE_COMMAND_MAX_LEN 8192 ++#define PRIVATE_COMMAND_DEF_LEN 4096 ++ ++ struct rwnx_vif *vif = netdev_priv(net); ++ int ret = 0; ++ char *command = NULL; ++ int bytes_written = 0; ++ android_wifi_priv_cmd priv_cmd; ++ int buf_size = 0; ++ int skip = 0; ++ char *country = NULL; ++#ifdef CONFIG_GPIO_WAKEUP ++ int setsusp_mode; ++#endif ++ struct ieee80211_regdomain *regdomain; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ///todo: add our lock ++ //net_os_wake_lock(net); ++ ++ ++/* if (!capable(CAP_NET_ADMIN)) { ++ ret = -EPERM; ++ goto exit; ++ }*/ ++ if (!ifr->ifr_data) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++#ifdef CONFIG_COMPAT ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) ++ if (in_compat_syscall()) ++#else ++ if (is_compat_task()) ++#endif ++ { ++ compat_android_wifi_priv_cmd compat_priv_cmd; ++ if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ 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 /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ } ++ if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { ++ printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); ++ command = kmalloc((buf_size + 1), GFP_KERNEL); ++ ++ if (!command) { ++ printk("%s: failed to allocate memory\n", __FUNCTION__); ++ ret = -ENOMEM; ++ goto exit; ++ } ++ if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ command[priv_cmd.total_len] = '\0'; ++ ++ /* outputs */ ++ AICWFDBG(LOGINFO, "%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); ++ AICWFDBG(LOGINFO, "cmd = %d\n", cmd); ++ AICWFDBG(LOGINFO, "buf_size=%d\n", buf_size); ++ ++#if 1//Handle Android command ++ if(!strncasecmp(command, CMD_SET_COUNTRY, strlen(CMD_SET_COUNTRY)) && ++ strncasecmp(command, "country_set", strlen("country_set"))) { ++ skip = strlen(CMD_SET_COUNTRY) + 1; ++ country = command + skip; ++ if (!country || strlen(country) < RWNX_COUNTRY_CODE_LEN) { ++ printk("%s: invalid country code\n", __func__); ++ ret = -EINVAL; ++ goto exit; ++ } ++#if 0 ++ for(index = 0; index < reg_regdb_size; index++){ ++ regdomain = getRegdomainFromRwnxDBIndex(vif->rwnx_hw->wiphy, index); ++ if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ ++ printk("regulatory_set_wiphy_regd fail \r\n"); ++ }else{ ++ printk("regulatory_set_wiphy_regd ok \r\n"); ++ } ++ } ++#endif ++ AICWFDBG(LOGINFO, "%s country code:%c%c\n", __func__, toupper(country[0]), toupper(country[1])); ++ regdomain = getRegdomainFromRwnxDB(vif->rwnx_hw->wiphy, country); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ ++ printk("regulatory_set_wiphy_regd fail \r\n"); ++ } ++#else ++ wiphy_apply_custom_regulatory(vif->rwnx_hw->wiphy, regdomain); ++#endif ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ rwnx_radar_set_domain(&vif->rwnx_hw->radar, regdomain->dfs_region); ++#endif ++ ++#ifdef CONFIG_POWER_LIMIT ++ if (!testmode) ++ rwnx_send_me_chan_config_req(vif->rwnx_hw, country); ++#endif ++ ret = 0; ++ goto exit; ++ } ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++ else if(!strncasecmp(command, CMD_SET_VENDOR_EX_IE, strlen(CMD_SET_VENDOR_EX_IE))){ ++ set_vendor_extension_ie(command); ++ ret = 0; ++ goto exit; ++ } ++#endif//CONFIG_SET_VENDOR_EXTENSION_IE ++ else if(!strncasecmp(command, CMD_SET_AP_WPS_P2P_IE, strlen(CMD_SET_AP_WPS_P2P_IE))){ ++ ret = 0; ++ goto exit; ++ } ++ else if(!strncasecmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) && testmode == 0){ ++#ifdef AICWF_SDIO_SUPPORT ++#if defined(CONFIG_GPIO_WAKEUP) && !defined(CONFIG_AUTO_POWERSAVE) ++ skip = strlen(CMD_SETSUSPENDMODE) + 1; ++ setsusp_mode = command_strtoul((command + skip), NULL, 10); ++#ifdef AICWF_LATENCY_MODE ++ if (setsusp_mode) ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, setsusp_mode, 0); ++ else ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1, 1); ++#else ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, setsusp_mode, !setsusp_mode); ++#endif ++ #if 0 ++ if (setsusp_mode == 1) { ++#if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); ++#endif ++ ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); ++ } ++ } ++ #endif ++ AICWFDBG(LOGINFO, "set suspend mode %d\n", setsusp_mode); ++#endif//CONFIG_GPIO_WAKEUP ++#endif ++ goto exit; ++ } ++#ifdef CONFIG_RWNX_MON_DATA ++ else if(!strncasecmp(command, CMD_SET_MON_FREQ, strlen(CMD_SET_MON_FREQ))){ ++ char *set_parameter; ++ skip = strlen(CMD_SET_MON_FREQ) + 1; ++ set_parameter = command + skip; ++ set_mon_chan(vif, set_parameter); ++ ret = 0; ++ goto exit; ++ } ++#endif ++ ++#endif//Handle Android command ++ ++ bytes_written = handle_private_cmd(net, command, priv_cmd.total_len); ++ if (bytes_written >= 0) { ++ if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { ++ command[0] = '\0'; ++ } ++ if (bytes_written >= priv_cmd.total_len) { ++ printk("%s: err. bytes_written:%d >= buf_size:%d \n", ++ __FUNCTION__, bytes_written, buf_size); ++ goto exit; ++ } ++ bytes_written++; ++ priv_cmd.used_len = bytes_written; ++ if (copy_to_user(priv_cmd.buf, command, bytes_written)) { ++ printk("%s: failed to copy data to user buffer\n", __FUNCTION__); ++ ret = -EFAULT; ++ } ++ } else { ++ /* Propagate the error */ ++ ret = bytes_written; ++ } ++ ++exit: ++ ///todo: add our unlock ++ //net_os_wake_unlock(net); ++ kfree(command); ++ return ret; ++} ++ ++#ifdef CONFIG_MCU_MESSAGE ++#define CMD_GET_VERSION_STR "GET_VERSION" ++#define CMD_GET_SSID_STR "GET_SSID" ++#define CMD_SET_SSID_STR "SET_SSID" ++#define CMD_GET_PASS_STR "GET_PASS" ++#define CMD_SET_PASS_STR "SET_PASS" ++#define CMD_GET_VAR_STR "GET_VAR" ++#define CMD_SET_VAR_STR "SET_VAR" ++ ++enum custmsg_cmd_tag ++{ ++ CUST_CMD_GET_VERSION = 0, ++ CUST_CMD_GET_SSID, ++ CUST_CMD_SET_SSID, ++ CUST_CMD_GET_PASS, ++ CUST_CMD_SET_PASS, ++ CUST_CMD_GET_VAR, ++ CUST_CMD_SET_VAR, ++ CUST_CMD_MAX ++}; ++ ++int handle_custom_msg(char *command, u32 cmd_len) ++{ ++ int bytes_read = 0, max_bytes_to_read = 0; ++ struct rwnx_hw *p_rwnx_hw = NULL; ++ u32 cmd, len = 0, flags = 0; ++ char *buf = NULL; ++ struct dbg_custom_msg_cfm *cust_msg_cfm; ++ printk("cmd,%s,%ld\n",command,strlen(command)); ++ if (strncasecmp(command, CMD_GET_VERSION_STR, strlen(CMD_GET_VERSION_STR)) == 0) { ++ cmd = CUST_CMD_GET_VERSION; ++ max_bytes_to_read = 32; // max str len for version ++ } else if (strncasecmp(command, CMD_GET_SSID_STR, strlen(CMD_GET_SSID_STR)) == 0) { ++ cmd = CUST_CMD_GET_SSID; ++ max_bytes_to_read = 48; // max str len for ssid ++ } else if (strncasecmp(command, CMD_SET_SSID_STR, strlen(CMD_SET_SSID_STR)) == 0) { ++ cmd = CUST_CMD_SET_SSID; ++ len = cmd_len - (strlen(CMD_SET_SSID_STR) + 1); ++ buf = command + (strlen(CMD_SET_SSID_STR) + 1); ++ max_bytes_to_read = 0; ++ } else if (strncasecmp(command, CMD_GET_PASS_STR, strlen(CMD_GET_PASS_STR)) == 0) { ++ cmd = CUST_CMD_GET_PASS; ++ max_bytes_to_read = 64; // max str len for PASS ++ } else if (strncasecmp(command, CMD_SET_PASS_STR, strlen(CMD_SET_PASS_STR)) == 0) { ++ cmd = CUST_CMD_SET_PASS; ++ len = cmd_len - (strlen(CMD_SET_PASS_STR) + 1); ++ buf = command + (strlen(CMD_SET_PASS_STR) + 1); ++ max_bytes_to_read = 0; ++ } else if (strncasecmp(command, CMD_GET_VAR_STR, strlen(CMD_GET_VAR_STR)) == 0) { ++ cmd = CUST_CMD_GET_VAR; ++ max_bytes_to_read = 64; // max str len for VAR ++ } else if (strncasecmp(command, CMD_SET_VAR_STR, strlen(CMD_SET_VAR_STR)) == 0) { ++ cmd = CUST_CMD_SET_VAR; ++ len = cmd_len - (strlen(CMD_SET_VAR_STR) + 1); ++ buf = command + (strlen(CMD_SET_VAR_STR) + 1); ++ max_bytes_to_read = 0; ++ } else { ++ printk("invalid cmd: %s\r\n", command); ++ return -1; ++ } ++ if (len < 0) { ++ printk("invalid len: %d\r\n", len); ++ return -3; ++ } ++ #ifdef AICWF_SDIO_SUPPORT ++ p_rwnx_hw = g_rwnx_plat->sdiodev->rwnx_hw; ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ p_rwnx_hw = g_rwnx_plat->usbdev->rwnx_hw; ++ #endif ++ cust_msg_cfm = (struct dbg_custom_msg_cfm *)kmalloc((offsetof(struct dbg_custom_msg_cfm, buf) + max_bytes_to_read), GFP_KERNEL); ++ if (cust_msg_cfm == NULL) { ++ printk("msg cfm alloc fail\r\n"); ++ return -2; ++ } ++ rwnx_send_dbg_custom_msg_req(p_rwnx_hw, cmd, buf, len, flags, cust_msg_cfm); ++ bytes_read = cust_msg_cfm->len; ++ printk("Custom msg cfm: cmd=%d, len=%d, status=%x\n", cust_msg_cfm->cmd, bytes_read, cust_msg_cfm->status); ++ if (bytes_read) { ++ memcpy(command, cust_msg_cfm->buf, bytes_read); ++ command[bytes_read] = '\0'; ++ } else { ++ command[0] = '\0'; ++ } ++ if (cust_msg_cfm->status) { ++ printk("cfm status: %x", cust_msg_cfm->status); ++ } ++ return bytes_read; ++} ++ ++int devipc_cust_msg(struct net_device *net, struct ifreq *ifr, int cmd) ++{ ++#ifdef PRIVATE_COMMAND_MAX_LEN ++#undef PRIVATE_COMMAND_MAX_LEN ++#undef PRIVATE_COMMAND_DEF_LEN ++#define PRIVATE_COMMAND_MAX_LEN 8192 ++#define PRIVATE_COMMAND_DEF_LEN 4096 ++#endif ++ int ret = 0; ++ char *command = NULL; ++ int bytes_written = 0; ++ android_wifi_priv_cmd priv_cmd; ++ int buf_size = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ///todo: add our lock ++ //net_os_wake_lock(net); ++ ++ ++/* if (!capable(CAP_NET_ADMIN)) { ++ ret = -EPERM; ++ goto exit; ++ }*/ ++ if (!ifr->ifr_data) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++#ifdef CONFIG_COMPAT ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) ++ if (in_compat_syscall()) ++#else ++ if (is_compat_task()) ++#endif ++ { ++ compat_android_wifi_priv_cmd compat_priv_cmd; ++ if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ 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 /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ } ++ if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { ++ printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); ++ command = kmalloc((buf_size + 1), GFP_KERNEL); ++ ++ if (!command) ++ { ++ printk("%s: failed to allocate memory\n", __FUNCTION__); ++ ret = -ENOMEM; ++ goto exit; ++ } ++ if (copy_from_user(command, priv_cmd.buf, priv_cmd.used_len)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ command[priv_cmd.used_len] = '\0'; ++ ++ /* outputs */ ++ printk("%s: Devipc custom msg \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); ++ printk("cmd = %x\n", cmd); ++ printk("buf_size=%d\n", buf_size); ++ ++ ++ bytes_written = handle_custom_msg(command, priv_cmd.used_len); ++ if (bytes_written >= 0) { ++ if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { ++ command[0] = '\0'; ++ } ++ if (bytes_written >= priv_cmd.total_len) { ++ printk("%s: err. bytes_written:%d >= buf_size:%d \n", ++ __FUNCTION__, bytes_written, buf_size); ++ goto exit; ++ } ++ bytes_written++; ++ priv_cmd.used_len = bytes_written; ++ if (copy_to_user(priv_cmd.buf, command, bytes_written)) { ++ printk("%s: failed to copy data to user buffer\n", __FUNCTION__); ++ ret = -EFAULT; ++ } ++ } ++ else { ++ /* Propagate the error */ ++ ret = bytes_written; ++ } ++ ++exit: ++ ///todo: add our unlock ++ //net_os_wake_unlock(net); ++ kfree(command); ++ Sreturn ret; ++} ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.h +new file mode 100644 +index 000000000000..265658ed1053 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_priv_cmd.h +@@ -0,0 +1,33 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file private_cmd.h ++ * ++ * Copyright (C) Aicsemi 2018-2024 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _AIC_PRIV_CMD_H_ ++#define _AIC_PRIV_CMD_H_ ++ ++#include "rwnx_defs.h" ++ ++typedef struct _android_wifi_priv_cmd { ++ char *buf; ++ int used_len; ++ int total_len; ++} android_wifi_priv_cmd; ++ ++#ifdef CONFIG_COMPAT ++typedef struct _compat_android_wifi_priv_cmd { ++ compat_caddr_t buf; ++ int used_len; ++ int total_len; ++} compat_android_wifi_priv_cmd; ++#endif /* CONFIG_COMPAT */ ++ ++int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd); ++ ++#endif /* _AIC_PRIV_CMD_H_ */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c +new file mode 100644 +index 000000000000..004a1a3cfdc9 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c +@@ -0,0 +1,1247 @@ ++#include "aic_vendor.h" ++#include "rwnx_defs.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_version_gen.h" ++#include "rwnx_msg_tx.h" ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ ++static struct wifi_ring_buffer_status ring_buffer[] = { ++ { ++ .name = "aicwf_ring_buffer0", ++ .flags = 0, ++ .ring_id = 0, ++ .verbose_level = 0, ++ .written_bytes = 0, ++ .read_bytes = 0, ++ .written_records = 0, ++ }, ++}; ++ ++static struct wlan_driver_wake_reason_cnt_t wake_reason_cnt = { ++ .total_cmd_event_wake = 10, ++}; ++ ++#endif ++ ++#ifdef CONFIG_APF ++#define AIC_APF_MEM_SIZE 2048 ++#define AIC_APF_VERSION 4 ++ ++static char apfProgram[AIC_APF_MEM_SIZE]; ++#endif ++ ++int aic_dev_start_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 mkeep_alive_id, u8 *ip_pkt, u16 ip_pkt_len, u8 *src_mac, u8 *dst_mac, u32 period_msec) ++{ ++ u8 *data, *pos; ++ ++ data = kzalloc(ip_pkt_len + 14, GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ pos = data; ++ memcpy(pos, dst_mac, 6); ++ pos += 6; ++ memcpy(pos, src_mac, 6); ++ pos += 6; ++ /* Mapping Ethernet type (ETHERTYPE_IP: 0x0800) */ ++ *(pos++) = 0x08; ++ *(pos++) = 0x00; ++ ++ /* Mapping IP pkt */ ++ memcpy(pos, ip_pkt, ip_pkt_len); ++ pos += ip_pkt_len; ++ ++ //add send 802.3 pkt(raw data) ++ kfree(data); ++ ++ return 0; ++} ++ ++int aic_dev_stop_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, u8 mkeep_alive_id) ++{ ++ int res = -1; ++ ++ /* ++ * The mkeep_alive packet is for STA interface only; if the bss is configured as AP, ++ * dongle shall reject a mkeep_alive request. ++ */ ++ if (rwnx_vif->wdev.iftype != NL80211_IFTYPE_STATION) ++ return res; ++ ++ printk("%s execution\n", __func__); ++ ++ //add send stop keep alive ++ res = 0; ++ return res; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++static int aicwf_vendor_start_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* max size of IP packet for keep alive */ ++ const int MKEEP_ALIVE_IP_PKT_MAX = 256; ++ ++ int ret = 0, rem, type; ++ u8 mkeep_alive_id = 0; ++ u8 *ip_pkt = NULL; ++ u16 ip_pkt_len = 0; ++ u8 src_mac[6]; ++ u8 dst_mac[6]; ++ u32 period_msec = 0; ++ const struct nlattr *iter; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; ++ printk("%s\n", __func__); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case MKEEP_ALIVE_ATTRIBUTE_ID: ++ mkeep_alive_id = nla_get_u8(iter); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN: ++ ip_pkt_len = nla_get_u16(iter); ++ if (ip_pkt_len > MKEEP_ALIVE_IP_PKT_MAX) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_IP_PKT: ++ if (!ip_pkt_len) { ++ ret = -EINVAL; ++ printk("ip packet length is 0\n"); ++ goto exit; ++ } ++ ip_pkt = (u8 *)kzalloc(ip_pkt_len, kflags); ++ if (ip_pkt == NULL) { ++ ret = -ENOMEM; ++ printk("Failed to allocate mem for ip packet\n"); ++ goto exit; ++ } ++ memcpy(ip_pkt, (u8 *)nla_data(iter), ip_pkt_len); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR: ++ memcpy(src_mac, nla_data(iter), 6); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR: ++ memcpy(dst_mac, nla_data(iter), 6); ++ break; ++ case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC: ++ period_msec = nla_get_u32(iter); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ ret = -EINVAL; ++ goto exit; ++ } ++ } ++ ++ if (ip_pkt == NULL) { ++ ret = -EINVAL; ++ printk("ip packet is NULL\n"); ++ goto exit; ++ } ++ ++ ret = aic_dev_start_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id, ip_pkt, ip_pkt_len, src_mac, ++ dst_mac, period_msec); ++ if (ret < 0) { ++ printk("start_mkeep_alive is failed ret: %d\n", ret); ++ } ++ ++exit: ++ if (ip_pkt) { ++ kfree(ip_pkt); ++ } ++ ++ return ret; ++} ++ ++static int aicwf_vendor_stop_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ u8 mkeep_alive_id = 0; ++ const struct nlattr *iter; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ ++ printk("%s\n", __func__); ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case MKEEP_ALIVE_ATTRIBUTE_ID: ++ mkeep_alive_id = nla_get_u8(iter); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ ++ ret = aic_dev_stop_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id); ++ if (ret < 0) { ++ printk("stop_mkeep_alive is failed ret: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++static int aicwf_vendor_get_ver(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ int payload = 0; ++ char version[128]; ++ int attr = -1; ++ struct sk_buff *reply; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_DRIVER_VER: ++ memcpy(version, RWNX_VERS_BANNER, sizeof(RWNX_VERS_BANNER)); ++ payload = strlen(version); ++ attr = LOGGER_ATTRIBUTE_DRIVER_VER; ++ break; ++ case LOGGER_ATTRIBUTE_FW_VER: ++ memcpy(version, wiphy->fw_version, sizeof(wiphy->fw_version)); ++ payload = strlen(version); ++ attr = LOGGER_ATTRIBUTE_FW_VER; ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ if (attr < 0) ++ return -EINVAL; ++ ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put(reply, attr, ++ payload, version)) { ++ wiphy_err(wiphy, "%s put version error\n", __func__); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "%s reply cmd error\n", __func__); ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_subcmd_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ struct sk_buff *reply; ++ int num_channels = 0; ++ int *channel_list = NULL; ++ int payload; ++ int i = 0; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ]; ++ ++ num_channels += rwnx_band_2GHz->n_channels; ++ num_channels += (rwnx_hw->band_5g_support) ? rwnx_band_5GHz->n_channels : 0; ++ ++ channel_list = (int *)kzalloc(sizeof(int) * num_channels, GFP_KERNEL); ++ if (!channel_list) ++ return -ENOMEM; ++ ++ for (i = 0; i < rwnx_band_2GHz->n_channels; i++) ++ channel_list[i] = rwnx_band_2GHz->channels[i].center_freq; ++ ++ for (; rwnx_hw->band_5g_support && i < num_channels; i++) ++ channel_list[i] = rwnx_band_5GHz->channels[i].center_freq; ++ ++ payload = sizeof(num_channels) + sizeof(int) * num_channels + 4; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case GSCAN_ATTRIBUTE_BAND: ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put_u32(reply, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels)) ++ goto out_put_fail; ++ ++ if (nla_put(reply, GSCAN_ATTRIBUTE_CHANNEL_LIST, sizeof(int) * num_channels, channel_list)) ++ goto out_put_fail; ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "%s reply cmd error\n", __func__); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ kfree(channel_list); ++ return ret; ++ ++out_put_fail: ++ kfree(channel_list); ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2); ++ ++static int aicwf_vendor_subcmd_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ struct ieee80211_regdomain *regdomain; ++ char *country = NULL; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case ANDR_WIFI_ATTRIBUTE_COUNTRY: ++ printk("%s(%d), ANDR_WIFI_ATTRIBUTE_COUNTRY: %s\n", __func__, __LINE__, (char *)nla_data(iter)); ++ country = (char *)nla_data(iter); ++ ++ AICWFDBG(LOGINFO, "%s country code:%c%c\n", __func__, ++ country[0], ++ country[1]); ++ ++ regdomain = getRegdomainFromRwnxDB(rwnx_hw->wiphy, country); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ if((ret = regulatory_set_wiphy_regd(rwnx_hw->wiphy, regdomain))){ ++ printk("regulatory_set_wiphy_regd fail \r\n"); ++ } ++#else ++ wiphy_apply_custom_regulatory(rwnx_hw->wiphy, regdomain); ++#endif ++ ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future! ++ */ ++ ++ return ret; ++} ++ ++static int aicwf_vendor_logger_trigger_memory_dump(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* TODO ++ * Add handle in the future! ++ */ ++ return 0; ++} ++ ++static int aicwf_vendor_subcmd_get_feature_set(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t feature = 0, payload; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ payload = sizeof(feature); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ /* TODO ++ * Add handle in the future! ++ */ ++ /*bit 1:Basic infrastructure mode*/ ++ if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) ++ feature |= WIFI_FEATURE_INFRA; ++ ++ /*bit 2:Support for 5 GHz Band*/ ++ if (rwnx_hw->band_5g_support) ++ feature |= WIFI_FEATURE_INFRA_5G; ++ ++ /*bit3:HOTSPOT is a supplicant feature, enable it by default*/ ++ feature |= WIFI_FEATURE_HOTSPOT; ++ ++ /*bit 4:P2P*/ ++ if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) && ++ (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) ++ feature |= WIFI_FEATURE_P2P; ++ ++ /*bit 5:soft AP feature supported*/ ++ if (wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) ++ feature |= WIFI_FEATURE_SOFT_AP; ++ ++ /*bit 18:WiFi Logger*/ ++ feature |= WIFI_FEATURE_LOGGER; ++ ++ /*bit 21:WiFi mkeep_alive*/ ++ feature |= WIFI_FEATURE_MKEEP_ALIVE; ++ ++#ifdef AICWF_LATENCY_MODE ++ feature |= WIFI_FEATURE_SET_LATENCY_MODE; ++#endif ++ if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) { ++ wiphy_err(wiphy, "%s put u32 error\n", __func__); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "%s reply cmd error\n", __func__); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_get_feature(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t feature = 0, payload; ++ ++ payload = sizeof(feature); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ feature |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED; ++ feature |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED; ++ ++ /*vts will test wake reason state function*/ ++ feature |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED; ++ ++ if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) { ++ wiphy_err(wiphy, "put skb u32 failed\n"); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_get_ring_status(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t payload; ++ uint32_t ring_buffer_nums = sizeof(ring_buffer) / sizeof(ring_buffer[0]); ++ ++ payload = sizeof(ring_buffer_nums) + sizeof(ring_buffer); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put_u32(reply, LOGGER_ATTRIBUTE_RING_NUM, ring_buffer_nums)) { ++ wiphy_err(wiphy, "put skb u32 failed\n"); ++ goto out_put_fail; ++ } ++ ++ if (nla_put(reply, LOGGER_ATTRIBUTE_RING_STATUS, sizeof(ring_buffer), ring_buffer)) { ++ wiphy_err(wiphy, "put skb failed\n"); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_start_logging(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type, intval, size, i; ++ const struct nlattr *iter; ++ struct wifi_ring_buffer_status rb; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_LOG_LEVEL: ++ rb.verbose_level = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_RING_FLAGS: ++ rb.flags = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_LOG_TIME_INTVAL: ++ intval = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE: ++ size = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_RING_NAME: ++ strcpy(rb.name, nla_data(iter)); ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ ret = -EINVAL; ++ for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) { ++ if (strcmp(rb.name, ring_buffer[i].name) == 0) { ++ ret = 0; ++ break; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ ++ return ret; ++} ++ ++static int aicwf_vendor_logger_get_ring_data(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type, i; ++ const struct nlattr *iter; ++ struct wifi_ring_buffer_status rb; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_RING_NAME: ++ strcpy(rb.name, nla_data(iter)); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ ret = -EINVAL; ++ for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) { ++ if (strcmp(rb.name, ring_buffer[i].name) == 0) { ++ ret = 0; ++ break; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ ++ return ret; ++} ++ ++static int aicwf_vendor_logger_get_wake_reason_stats(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t payload; ++ ++ payload = sizeof(wake_reason_cnt.total_cmd_event_wake); ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ if (nla_put_u32(reply, WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT, wake_reason_cnt.total_cmd_event_wake)) ++ goto out_put_fail; ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_logger_get_tx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++#if 0 ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ int fate_num; ++ int fate_data; ++ ++ AICWFDBG(LOGDEBUG, "%s Enter\r\n", __func__); ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_PKT_FATE_NUM: ++ fate_num = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_PKT_FATE_DATA: ++ fate_data = nla_get_u64(iter); ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++#endif ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++static int aicwf_vendor_logger_get_rx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++#if 0 ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ int fate_num; ++ int fate_data; ++ ++ AICWFDBG(LOGDEBUG, "%s Enter\r\n", __func__); ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case LOGGER_ATTRIBUTE_PKT_FATE_NUM: ++ fate_num = nla_get_u32(iter); ++ break; ++ case LOGGER_ATTRIBUTE_PKT_FATE_DATA: ++ fate_data = nla_get_u64(iter); ++ break; ++ default: ++ AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++#endif ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++ ++#ifdef AICWF_LATENCY_MODE ++static int aicwf_vendor_subcmd_set_latency_mode(struct wiphy *wiphy, ++ struct wireless_dev *wdev, const void *data, int len) ++{ ++ int err = 0, rem, type; ++ u32 latency_mode; ++ const struct nlattr *iter; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case ANDR_WIFI_ATTRIBUTE_LATENCY_MODE: ++ latency_mode = nla_get_u32(iter); ++ printk("%s,Setting latency mode %d\n", __func__, latency_mode); ++ #ifdef AICWF_SDIO_SUPPORT ++ if (latency_mode) { ++ rwnx_send_me_set_lp_level(rwnx_hw, 0, 1); ++ } else { ++ rwnx_send_me_set_lp_level(rwnx_hw, 1, 0); ++ } ++ #endif ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return err; ++ } ++ } ++ ++ return err; ++} ++#endif ++ ++static int aicwf_vendor_logger_start_pkt_fate_monitoring(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++#ifdef CONFIG_APF ++static int aicwf_vendor_apf_subcmd_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret; ++ struct sk_buff *reply; ++ uint32_t payload; ++ printk("%s\n", __func__); ++ ++ /* APF_ATTRIBUTE_VERSION + APF_ATTRIBUTE_MAX_LEN */ ++ payload = sizeof(u32) * 2; ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ ++ if (!reply) ++ return -ENOMEM; ++ ++ if (nla_put_u32(reply, APF_ATTRIBUTE_VERSION, AIC_APF_VERSION)) ++ goto out_put_fail; ++ ++ if (nla_put_u32(reply, APF_ATTRIBUTE_MAX_LEN, AIC_APF_MEM_SIZE)) ++ goto out_put_fail; ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++ ++static int aicwf_vendor_apf_set_filter(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ unsigned int mProgramLen = 0; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ printk("%s\n", __func__); ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case APF_ATTRIBUTE_PROGRAM_LEN: ++ memcpy(&mProgramLen, nla_data(iter), sizeof(unsigned int)); ++ ret = (mProgramLen > 0 && mProgramLen <= AIC_APF_MEM_SIZE) ? 0 : -EINVAL; ++ break; ++ case APF_ATTRIBUTE_PROGRAM: ++ if (mProgramLen > AIC_APF_MEM_SIZE || mProgramLen == 0) { ++ printk("%s: apf program size invalid: %d (should > 0 and <= %d)\n", ++ __func__, mProgramLen, AIC_APF_MEM_SIZE); ++ return -EINVAL; ++ } ++ ++ memcpy(apfProgram, nla_data(iter), mProgramLen); ++ ret = rwnx_send_set_apf_prog_req(rwnx_hw, apfProgram, mProgramLen); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ return ret; ++} ++ ++static int aicwf_vendor_apf_read_filter_data(struct wiphy *wiphy, ++ struct wireless_dev *wdev, const void *data, int len) ++{ ++ struct sk_buff *reply; ++ int ret, payload, apf_mem_size; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ printk("%s\n", __func__); ++ ++ apf_mem_size = AIC_APF_MEM_SIZE; ++ payload = sizeof(u32) + apf_mem_size; ++ ++ ret = rwnx_send_get_apf_prog_req(rwnx_hw, apfProgram, apf_mem_size); ++ if (ret != 0) { ++ pr_err("%s, Failed to read apf mem from firmware, ret = %d\n", __func__, ret); ++ return ret; ++ } ++ ++ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload); ++ if (!reply) ++ return -ENOMEM; ++ ++ ret = nla_put_u32(reply, APF_ATTRIBUTE_PROGRAM_LEN, apf_mem_size); ++ if (ret < 0) { ++ pr_err("%s, Failed to put APF_ATTRIBUTE_MAX_LEN, ret = %d\n", __func__, ret); ++ goto out_put_fail; ++ } ++ ++ /* copy the full apf mem */ ++ ret = nla_put(reply, APF_ATTRIBUTE_PROGRAM, apf_mem_size, &apfProgram[0]); ++ if (ret < 0) { ++ pr_err("%s, Failed to put APF_ATTRIBUTE_PROGRAM, ret = %d\n", __func__, ret); ++ goto out_put_fail; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(reply); ++ if (ret) ++ wiphy_err(wiphy, "reply cmd error\n"); ++ ++ return ret; ++ ++out_put_fail: ++ kfree_skb(reply); ++ return -EMSGSIZE; ++} ++#endif ++ ++static int aicwf_vendor_sub_cmd_set_mac(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ int ret = 0, rem, type; ++ const struct nlattr *iter; ++ u8 mac[ETH_ALEN]; ++ ++ nla_for_each_attr(iter, data, len, rem) { ++ type = nla_type(iter); ++ switch (type) { ++ case WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR: ++ memcpy(mac, nla_data(iter), ETH_ALEN); ++ printk("%s, %02X:%02X:%02X:%02X:%02X:%02X\n", __func__, ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ break; ++ default: ++ pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type); ++ return -EINVAL; ++ } ++ } ++ ++ /* TODO ++ * Add handle in the future ++ */ ++ ++ return ret; ++} ++#endif ++ ++static const struct nla_policy ++aicwf_cfg80211_mkeep_alive_policy[MKEEP_ALIVE_ATTRIBUTE_MAX+1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [MKEEP_ALIVE_ATTRIBUTE_ID] = { .type = NLA_U8 }, ++ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = { .type = NLA_MSECS }, ++ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = { .type = NLA_U16 }, ++ [MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = { .type = NLA_MSECS, ++ .len = ETH_ALEN }, ++ [MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = { .type = NLA_MSECS, ++ .len = ETH_ALEN }, ++ [MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = { .type = NLA_U32 }, ++}; ++ ++static const struct nla_policy ++aicwf_cfg80211_logger_policy[LOGGER_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [LOGGER_ATTRIBUTE_DRIVER_VER] = { .type = NLA_BINARY }, ++ [LOGGER_ATTRIBUTE_FW_VER] = { .type = NLA_BINARY }, ++ [LOGGER_ATTRIBUTE_LOG_LEVEL] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_RING_FLAGS] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_LOG_TIME_INTVAL] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE] = { .type = NLA_U32 }, ++ [LOGGER_ATTRIBUTE_RING_NAME] = { .type = NLA_STRING }, ++}; ++ ++#ifdef CONFIG_APF ++static const struct nla_policy ++aicwf_cfg80211_apf_policy[APF_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [APF_ATTRIBUTE_VERSION] = {.type = NLA_U32 }, ++ [APF_ATTRIBUTE_MAX_LEN] = {.type = NLA_U32 }, ++ [APF_ATTRIBUTE_PROGRAM] = { .type = NLA_BINARY }, ++ [APF_ATTRIBUTE_PROGRAM_LEN] = { .type = NLA_U32 }, ++}; ++#endif ++ ++static const struct nla_policy ++aicwf_cfg80211_subcmd_policy[GSCAN_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [GSCAN_ATTRIBUTE_BAND] = { .type = NLA_U32 }, ++}; ++ ++static const struct nla_policy ++aicwf_cfg80211_andr_wifi_policy[ANDR_WIFI_ATTRIBUTE_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [ANDR_WIFI_ATTRIBUTE_COUNTRY] = { .type = NLA_STRING }, ++}; ++ ++static const struct nla_policy ++aicwf_cfg80211_subcmd_set_mac_policy[WIFI_VENDOR_ATTR_DRIVER_MAX + 1] = { ++ [0] = {.type = NLA_UNSPEC }, ++ [WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR] = { .type = NLA_MSECS, .len = ETH_ALEN }, ++}; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++static int aicwf_dump_interface(struct wiphy *wiphy, ++ struct wireless_dev *wdev, struct sk_buff *skb, ++ const void *data, int data_len, ++ unsigned long *storage) ++{ ++ return 0; ++} ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++const struct wiphy_vendor_command aicwf_vendor_cmd[] = { ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_start_mkeep_alive, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_mkeep_alive_policy, ++ .maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_stop_mkeep_alive, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_mkeep_alive_policy, ++ .maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_VER ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_get_ver, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_logger_policy, ++ .maxattr = LOGGER_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_get_channel_list, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_subcmd_policy, ++ .maxattr = GSCAN_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_set_country_code, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_andr_wifi_policy, ++ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_TRIGGER_MEM_DUMP ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_trigger_memory_dump, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_GET_FEATURE_SET ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_get_feature_set, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_FEATURE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_feature, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_RING_STATUS ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_ring_status, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_START_LOGGING ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_start_logging, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_logger_policy, ++ .maxattr = LOGGER_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_RING_DATA ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_ring_data, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_logger_policy, ++ .maxattr = LOGGER_ATTRIBUTE_MAX ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_WAKE_REASON_STATS ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_wake_reason_stats, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++#ifdef CONFIG_APF ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = APF_SUBCMD_GET_CAPABILITIES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_apf_subcmd_get_capabilities, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_apf_policy, ++ .maxattr = APF_ATTRIBUTE_MAX, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = APF_SUBCMD_SET_FILTER ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_apf_set_filter, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_apf_policy, ++ .maxattr = APF_ATTRIBUTE_MAX, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = APF_SUBCMD_READ_FILTER_DATA ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_apf_read_filter_data, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) ++ .policy = aicwf_cfg80211_apf_policy, ++ .maxattr = APF_ATTRIBUTE_MAX ++#endif /* LINUX_VERSION >= 5.3 */ ++ }, ++#endif ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_START_PKT_FATE_MONITORING ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_start_pkt_fate_monitoring, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_TX_PKT_FATES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_tx_pkt_fates, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LOGGER_GET_RX_PKT_FATES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_logger_get_rx_pkt_fates, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = VENDOR_CMD_RAW_DATA, ++#endif ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = VENDOR_NL80211_SUBCMD_SET_MAC ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = aicwf_vendor_sub_cmd_set_mac, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_subcmd_set_mac_policy, ++ .maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX, ++#endif ++ }, ++ { ++ { ++ .vendor_id = BRCM_OUI, ++ .subcmd = VENDOR_NL80211_SUBCMD_SET_MAC ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = aicwf_vendor_sub_cmd_set_mac, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) ++ .dumpit = aicwf_dump_interface, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) ++ .policy = aicwf_cfg80211_subcmd_set_mac_policy, ++ .maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX, ++#endif ++ }, ++#ifdef AICWF_LATENCY_MODE ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_SET_LATENCY_MODE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = aicwf_vendor_subcmd_set_latency_mode, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) ++ .policy = aicwf_cfg80211_andr_wifi_policy, ++ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX ++#endif /* LINUX_VERSION >= 5.3 */ ++ }, ++#endif ++}; ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++static const struct nl80211_vendor_cmd_info aicwf_vendor_events[] = { ++}; ++#endif ++ ++int aicwf_vendor_init(struct wiphy *wiphy) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ wiphy->vendor_commands = aicwf_vendor_cmd; ++ wiphy->n_vendor_commands = ARRAY_SIZE(aicwf_vendor_cmd); ++ wiphy->vendor_events = aicwf_vendor_events; ++ wiphy->n_vendor_events = ARRAY_SIZE(aicwf_vendor_events); ++#endif ++ return 0; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h +new file mode 100644 +index 000000000000..996edefa812e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h +@@ -0,0 +1,363 @@ ++#ifndef _AIC_VENDOR_H ++#define _AIC_VENDOR_H ++ ++#include ++ ++#define GOOGLE_OUI 0x001A11 ++#define BRCM_OUI 0x001018 ++ ++typedef enum { ++ START_MKEEP_ALIVE, ++ STOP_MKEEP_ALIVE, ++} GetCmdType; ++ ++typedef enum { ++ /* don't use 0 as a valid subcommand */ ++ VENDOR_NL80211_SUBCMD_UNSPECIFIED, ++ ++ /* define all vendor startup commands between 0x0 and 0x0FFF */ ++ VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001, ++ VENDOR_NL80211_SUBCMD_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 NearbyDiscovery related commands between 0x1100 and 0x11FF */ ++ ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100, ++ ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x11FF, ++ ++ /* 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, ++ ++ /* define all NAN related commands between 0x1700 and 0x17FF */ ++ ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700, ++ ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF, ++ ++ /* define all Android Packet Filter related commands between 0x1800 and 0x18FF */ ++ ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800, ++ ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF, ++ ++ /* This is reserved for future usage */ ++ ++} ANDROID_VENDOR_SUB_COMMAND; ++ ++typedef enum { ++ WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, ++ WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE, ++} WIFI_OFFLOAD_SUB_COMMAND; ++ ++ ++enum mkeep_alive_attributes { ++ MKEEP_ALIVE_ATTRIBUTE_ID = 0x1, ++ MKEEP_ALIVE_ATTRIBUTE_IP_PKT, ++ MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, ++ MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, ++ MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, ++ MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, ++ MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST, ++ MKEEP_ALIVE_ATTRIBUTE_MAX = MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST - 1 ++}; ++ ++enum debug_sub_command { ++ LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, ++ LOGGER_TRIGGER_MEM_DUMP, ++ LOGGER_GET_MEM_DUMP, ++ LOGGER_GET_VER, ++ LOGGER_GET_RING_STATUS, ++ LOGGER_GET_RING_DATA, ++ LOGGER_GET_FEATURE, ++ LOGGER_RESET_LOGGING, ++ LOGGER_TRIGGER_DRIVER_MEM_DUMP, ++ LOGGER_GET_DRIVER_MEM_DUMP, ++ LOGGER_START_PKT_FATE_MONITORING, ++ LOGGER_GET_TX_PKT_FATES, ++ LOGGER_GET_RX_PKT_FATES, ++ LOGGER_GET_WAKE_REASON_STATS, ++ LOGGER_DEBUG_GET_DUMP, ++ LOGGER_FILE_DUMP_DONE_IND, ++ LOGGER_SET_HAL_START, ++ LOGGER_HAL_STOP, ++ LOGGER_SET_HAL_PID, ++}; ++ ++enum logger_attributes { ++ LOGGER_ATTRIBUTE_INVALID = 0, ++ LOGGER_ATTRIBUTE_DRIVER_VER, ++ LOGGER_ATTRIBUTE_FW_VER, ++ LOGGER_ATTRIBUTE_RING_ID, ++ LOGGER_ATTRIBUTE_RING_NAME, ++ LOGGER_ATTRIBUTE_RING_FLAGS, ++ LOGGER_ATTRIBUTE_LOG_LEVEL, ++ LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, ++ LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, ++ LOGGER_ATTRIBUTE_FW_DUMP_LEN, ++ LOGGER_ATTRIBUTE_FW_DUMP_DATA, ++ // LOGGER_ATTRIBUTE_FW_ERR_CODE, ++ LOGGER_ATTRIBUTE_RING_DATA, ++ LOGGER_ATTRIBUTE_RING_STATUS, ++ LOGGER_ATTRIBUTE_RING_NUM, ++ LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN, ++ LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA, ++ LOGGER_ATTRIBUTE_PKT_FATE_NUM, ++ LOGGER_ATTRIBUTE_PKT_FATE_DATA, ++ LOGGER_ATTRIBUTE_AFTER_LAST, ++ LOGGER_ATTRIBUTE_MAX = LOGGER_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++#ifdef CONFIG_APF ++enum wifi_apf_attr { ++ APF_ATTRIBUTE_VERSION, ++ APF_ATTRIBUTE_MAX_LEN, ++ APF_ATTRIBUTE_PROGRAM, ++ APF_ATTRIBUTE_PROGRAM_LEN, ++ APF_ATTRIBUTE_LAST, ++ APF_ATTRIBUTE_MAX = APF_ATTRIBUTE_LAST - 1, ++}; ++#endif ++ ++enum wifi_sub_command { ++ 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 */ ++ GSCAN_SUBCMD_GET_CHANNEL_LIST, /* 0x1009 */ ++ WIFI_SUBCMD_GET_FEATURE_SET, /* 0x100A */ ++ WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x100B */ ++ WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x100C */ ++ WIFI_SUBCMD_NODFS_SET, /* 0x100D */ ++ WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x100E */ ++ /* Add more sub commands here */ ++ GSCAN_SUBCMD_SET_EPNO_SSID, /* 0x100F */ ++ WIFI_SUBCMD_SET_SSID_WHITE_LIST, /* 0x1010 */ ++ WIFI_SUBCMD_SET_ROAM_PARAMS, /* 0x1011 */ ++ WIFI_SUBCMD_ENABLE_LAZY_ROAM, /* 0x1012 */ ++ WIFI_SUBCMD_SET_BSSID_PREF, /* 0x1013 */ ++ WIFI_SUBCMD_SET_BSSID_BLACKLIST, /* 0x1014 */ ++ GSCAN_SUBCMD_ANQPO_CONFIG, /* 0x1015 */ ++ WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x1016 */ ++ WIFI_SUBCMD_CONFIG_ND_OFFLOAD, /* 0x1017 */ ++ WIFI_SUBCMD_SET_LATENCY_MODE, /* 0x1018 */ ++ /* Add more sub commands here */ ++ GSCAN_SUBCMD_MAX, ++ APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START, ++ APF_SUBCMD_SET_FILTER, ++#ifdef CONFIG_APF ++ APF_SUBCMD_READ_FILTER_DATA, ++#endif ++}; ++ ++enum gscan_attributes { ++ 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_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, ++ ++ 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, ++ ++ /* remaining reserved for additional attributes */ ++ 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_NUM_CHANNELS, ++ GSCAN_ATTRIBUTE_CHANNEL_LIST, ++ GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, ++ ++ GSCAN_ATTRIBUTE_AFTER_LAST, ++ GSCAN_ATTRIBUTE_MAX = GSCAN_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++enum andr_wifi_attributes { ++ ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, ++ ANDR_WIFI_ATTRIBUTE_FEATURE_SET, ++ ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, ++ ANDR_WIFI_ATTRIBUTE_NODFS_SET, ++ ANDR_WIFI_ATTRIBUTE_COUNTRY, ++ ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE, ++ ANDR_WIFI_ATTRIBUTE_LATENCY_MODE, ++ // Add more attribute here ++ ANDR_WIFI_ATTRIBUTE_AFTER_LAST, ++ ANDR_WIFI_ATTRIBUTE_MAX = ANDR_WIFI_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++enum wifi_support_feature { ++ /* Feature enums */ ++ WIFI_FEATURE_INFRA = 0x0001, /* Basic infrastructure mode */ ++ WIFI_FEATURE_INFRA_5G = 0x0002, /* Support for 5, GHz Band */ ++ WIFI_FEATURE_HOTSPOT = 0x0004, /* Support for GAS/ANQP */ ++ WIFI_FEATURE_P2P = 0x0008, /* Wifi-Direct */ ++ WIFI_FEATURE_SOFT_AP = 0x0010, /* Soft AP */ ++ WIFI_FEATURE_GSCAN = 0x0020, /* Google-Scan APIs */ ++ WIFI_FEATURE_NAN = 0x0040, /* Neighbor Awareness Networking */ ++ WIFI_FEATURE_D2D_RTT = 0x0080, /* Device-to-device RTT */ ++ WIFI_FEATURE_D2AP_RTT = 0x0100, /* Device-to-AP RTT */ ++ WIFI_FEATURE_BATCH_SCAN = 0x0200, /* Batched Scan (legacy) */ ++ WIFI_FEATURE_PNO = 0x0400, /* Preferred network offload */ ++ WIFI_FEATURE_ADDITIONAL_STA = 0x0800, /* Support for two STAs */ ++ WIFI_FEATURE_TDLS = 0x1000, /* Tunnel directed link setup */ ++ WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000, /* Support for TDLS off channel */ ++ WIFI_FEATURE_EPR = 0x4000, /* Enhanced power reporting */ ++ WIFI_FEATURE_AP_STA = 0x8000, /* Support for AP STA Concurrency */ ++ WIFI_FEATURE_LINK_LAYER_STATS = 0x10000, /* Support for Linkstats */ ++ WIFI_FEATURE_LOGGER = 0x20000, /* WiFi Logger */ ++ WIFI_FEATURE_HAL_EPNO = 0x40000, /* WiFi PNO enhanced */ ++ WIFI_FEATURE_RSSI_MONITOR = 0x80000, /* RSSI Monitor */ ++ WIFI_FEATURE_MKEEP_ALIVE = 0x100000, /* WiFi mkeep_alive */ ++ WIFI_FEATURE_CONFIG_NDO = 0x200000, /* ND offload configure */ ++ WIFI_FEATURE_TX_TRANSMIT_POWER = 0x400000, /* Capture Tx transmit power levels */ ++ WIFI_FEATURE_CONTROL_ROAMING = 0x800000, /* Enable/Disable firmware roaming */ ++ WIFI_FEATURE_IE_WHITELIST = 0x1000000, /* Support Probe IE white listing */ ++ WIFI_FEATURE_SCAN_RAND = 0x2000000, /* Support MAC & Probe Sequence Number randomization */ ++ WIFI_FEATURE_SET_LATENCY_MODE = 0x40000000, /* Support Latency mode setting */ ++ WIFI_FEATURE_INVALID = 0xFFFFFFFF, /* Invalid Feature */ ++}; ++ ++enum wifi_logger_feature { ++ WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), // Memory dump of FW ++ WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), // PKT status ++ WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), // Connectivity event ++ WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), // POWER of Driver ++ WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), // WAKE LOCK of Driver ++ WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), // verbose log of FW ++ WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), // monitor the health of FW ++ WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), // dumps driver state ++ WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)), // tracks connection packets' fate ++}; ++ ++enum wake_stats_attributes { ++ WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT, ++ WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE, ++ WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT, ++ WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED, ++ WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW, ++ WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE, ++ WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT, ++ WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED, ++ WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE, ++ WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT, ++ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT, ++ WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA, ++ WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS, ++ WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT, ++ WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT, ++ WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT, ++ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO, ++ WAKE_STAT_ATTRIBUTE_AFTER_LAST, ++ WAKE_STAT_ATTRIBUTE_MAX = WAKE_STAT_ATTRIBUTE_AFTER_LAST - 1, ++}; ++ ++enum vendor_nl80211_subcmd { ++ /* copied from wpa_supplicant brcm definations */ ++ VENDOR_NL80211_SUBCMD_UNSPEC = 0, ++ VENDOR_NL80211_SUBCMD_SET_PMK = 4, ++ VENDOR_NL80211_SUBCMD_SET_MAC = 6, ++ VENDOR_NL80211_SCMD_ACS = 9, ++ VENDOR_NL80211_SCMD_MAX = 10, ++}; ++ ++enum nl80211_vendor_subcmd_attributes { ++ WIFI_VENDOR_ATTR_DRIVER_CMD = 0, ++ WIFI_VENDOR_ATTR_DRIVER_KEY_PMK = 1, ++ WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR = 3, ++ WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST = 5, ++ WIFI_VENDOR_ATTR_DRIVER_MAX = ++ WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST - 1, ++}; ++ ++typedef int wifi_ring_buffer_id; ++ ++struct wifi_ring_buffer_status { ++ u8 name[32]; ++ u32 flags; ++ wifi_ring_buffer_id ring_id; ++ u32 ring_buffer_byte_size; ++ u32 verbose_level; ++ u32 written_bytes; ++ u32 read_bytes; ++ u32 written_records; ++}; ++ ++struct rx_data_cnt_details_t { ++ int rx_unicast_cnt; /*Total rx unicast packet which woke up host */ ++ int rx_multicast_cnt; /*Total rx multicast packet which woke up host */ ++ int rx_broadcast_cnt; /*Total rx broadcast packet which woke up host */ ++}; ++ ++struct rx_wake_pkt_type_classification_t { ++ int icmp_pkt; /*wake icmp packet count */ ++ int icmp6_pkt; /*wake icmp6 packet count */ ++ int icmp6_ra; /*wake icmp6 RA packet count */ ++ int icmp6_na; /*wake icmp6 NA packet count */ ++ int icmp6_ns; /*wake icmp6 NS packet count */ ++ //ToDo: Any more interesting classification to add? ++}; ++ ++struct rx_multicast_cnt_t{ ++ int ipv4_rx_multicast_addr_cnt; /*Rx wake packet was ipv4 multicast */ ++ int ipv6_rx_multicast_addr_cnt; /*Rx wake packet was ipv6 multicast */ ++ int other_rx_multicast_addr_cnt;/*Rx wake packet was non-ipv4 and non-ipv6*/ ++}; ++ ++struct wlan_driver_wake_reason_cnt_t { ++ int total_cmd_event_wake; /* Total count of cmd event wakes */ ++ int *cmd_event_wake_cnt; /* Individual wake count array, each index a reason */ ++ int cmd_event_wake_cnt_sz; /* Max number of cmd event wake reasons */ ++ int cmd_event_wake_cnt_used; /* Number of cmd event wake reasons specific to the driver */ ++ ++ int total_driver_fw_local_wake; /* Total count of drive/fw wakes, for local reasons */ ++ int *driver_fw_local_wake_cnt; /* Individual wake count array, each index a reason */ ++ int driver_fw_local_wake_cnt_sz; /* Max number of local driver/fw wake reasons */ ++ int driver_fw_local_wake_cnt_used; /* Number of local driver/fw wake reasons specific to the driver */ ++ ++ int total_rx_data_wake; /* total data rx packets, that woke up host */ ++ struct rx_data_cnt_details_t rx_wake_details; ++ struct rx_wake_pkt_type_classification_t rx_wake_pkt_classification_info; ++ struct rx_multicast_cnt_t rx_multicast_wake_pkt_info; ++}; ++ ++typedef struct wl_mkeep_alive_pkt { ++ u16 version; /* Version for mkeep_alive */ ++ u16 length; /* length of fixed parameters in the structure */ ++ u32 period_msec; /* high bit on means immediate send */ ++ u16 len_bytes; ++ u8 keep_alive_id; /* 0 - 3 for N = 4 */ ++ u8 data[1]; ++} wl_mkeep_alive_pkt_t; ++ ++#endif /* _AIC_VENDOR_H */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c +new file mode 100644 +index 000000000000..8dee7597efad +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c +@@ -0,0 +1,166 @@ ++#include "rwnx_main.h" ++#include "rwnx_msg_tx.h" ++#include "reg_access.h" ++#include "aicwf_compat_8800d80.h" ++ ++#define FW_USERCONFIG_NAME_8800D80 "aic_userconfig_8800d80.txt" ++#define FW_USERCONFIG_NAME_8800D80X2 "aic_userconfig_8800d80x2.txt" ++#define FW_POWERLIMIT_NAME_8800D80 "aic_powerlimit_8800d80.txt" ++ ++ ++int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, ++ u32** buffer, const char *filename); ++void rwnx_plat_userconfig_parsing2(char *buffer, int size); ++void rwnx_plat_userconfig_parsing3(char *buffer, int size); ++void rwnx_plat_userconfig_parsing_8800d80x2(char *buffer, int size); ++ ++void rwnx_release_firmware_common(u32** buffer); ++ ++int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm) ++{ ++ int ret = 0; ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ if ((ret = rwnx_send_txpwr_lvl_v3_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst2x_req(rwnx_hw))) { ++ return -1; ++ } ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if ((ret = rwnx_send_txpwr_lvl_v4_req(rwnx_hw))) { ++ return -1; ++ } ++ if ((ret = rwnx_send_txpwr_ofst2x_v2_req(rwnx_hw))) { ++ return -1; ++ } ++ } ++ ++ if ((ret = rwnx_send_txpwr_lvl_adj_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) { ++ return -1; ++ } ++ ++ return 0 ; ++} ++ ++int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800D80; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing3((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ ++int rwnx_plat_userconfig_load_8800d80x2(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800D80X2; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing_8800d80x2((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ ++#ifdef CONFIG_POWER_LIMIT ++extern char country_code[4]; ++int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst = NULL; ++ char *filename = FW_POWERLIMIT_NAME_8800D80; ++ ++ AICWFDBG(LOGDEBUG, "powerlimit file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of cfg file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ AICWFDBG(LOGDEBUG, "### Load file done: %s, size=%d\n", filename, size); ++ ++ /* parsing the file */ ++ rwnx_plat_powerlimit_parsing((char *)dst, size, country_code); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGDEBUG, "powerlimit download complete\n\n"); ++ return 0; ++} ++ ++int rwnx_plat_powerlimit_load_8800d80x2(struct rwnx_hw *rwnx_hw) ++{ ++ int size; ++ u32 *dst = NULL; ++ char *filename = FW_POWERLIMIT_NAME_8800D80; ++ ++ AICWFDBG(LOGDEBUG, "powerlimit file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of cfg file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ AICWFDBG(LOGDEBUG, "### Load file done: %s, size=%d\n", filename, size); ++ ++ /* parsing the file */ ++ rwnx_plat_powerlimit_parsing((char *)dst, size, country_code); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGDEBUG, "powerlimit download complete\n\n"); ++ return 0; ++} ++ ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h +new file mode 100644 +index 000000000000..e76577414834 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h +@@ -0,0 +1,15 @@ ++#ifndef _AICWF_COMPAT_8800D80_H_ ++#define _AICWF_COMPAT_8800D80_H_ ++#include ++ ++int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); ++int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw); ++int rwnx_plat_userconfig_load_8800d80x2(struct rwnx_hw *rwnx_hw); ++ ++#ifdef CONFIG_POWER_LIMIT ++int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw); ++int rwnx_plat_powerlimit_load_8800d80x2(struct rwnx_hw *rwnx_hw); ++#endif ++ ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c +new file mode 100644 +index 000000000000..3e68283f6dc7 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c +@@ -0,0 +1,685 @@ ++#include "rwnx_main.h" ++#include "rwnx_msg_tx.h" ++#include "reg_access.h" ++#include "aic_bsp_export.h" ++ ++#define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc" ++#define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin" ++#define FW_USERCONFIG_NAME_8800DC "aic_userconfig_8800dc.txt" ++#define FW_USERCONFIG_NAME_8800DW "aic_userconfig_8800dw.txt" ++ ++int rwnx_plat_bin_fw_upload_2(struct rwnx_hw *rwnx_hw, u32 fw_addr, ++ char *filename); ++int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, ++ u32** buffer, const char *filename); ++void rwnx_plat_userconfig_parsing2(char *buffer, int size); ++ ++void rwnx_release_firmware_common(u32** buffer); ++ ++#if !defined(CONFIG_EXT_FEM_8800DCDW) ++u32 wifi_txgain_table_24g_8800dcdw[32] = ++{ ++ 0xA4B22189, //index 0 ++ 0x00007825, ++ 0xA4B2214B, //index 1 ++ 0x00007825, ++ 0xA4B2214F, //index 2 ++ 0x00007825, ++ 0xA4B221D5, //index 3 ++ 0x00007825, ++ 0xA4B221DC, //index 4 ++ 0x00007825, ++ 0xA4B221E5, //index 5 ++ 0x00007825, ++ 0xAC9221E5, //index 6 ++ 0x00006825, ++ 0xAC9221EF, //index 7 ++ 0x00006825, ++ 0xBC9221EE, //index 8 ++ 0x00006825, ++ 0xBC9221FF, //index 9 ++ 0x00006825, ++ 0xBC9221FF, //index 10 ++ 0x00004025, ++ 0xB792203F, //index 11 ++ 0x00004026, ++ 0xDC92203F, //index 12 ++ 0x00004025, ++ 0xE692203F, //index 13 ++ 0x00004025, ++ 0xFF92203F, //index 14 ++ 0x00004035, ++ 0xFFFE203F, //index 15 ++ 0x00004832 ++}; ++ ++u32 wifi_txgain_table_24g_1_8800dcdw[32] = ++{ ++ 0x096E2011, //index 0 ++ 0x00004001, ++ 0x096E2015, //index 1 ++ 0x00004001, ++ 0x096E201B, //index 2 ++ 0x00004001, ++ 0x116E2018, //index 3 ++ 0x00004001, ++ 0x116E201E, //index 4 ++ 0x00004001, ++ 0x116E2023, //index 5 ++ 0x00004001, ++ 0x196E2021, //index 6 ++ 0x00004001, ++ 0x196E202B, //index 7 ++ 0x00004001, ++ 0x216E202B, //index 8 ++ 0x00004001, ++ 0x236E2027, //index 9 ++ 0x00004001, ++ 0x236E2031, //index 10 ++ 0x00004001, ++ 0x246E2039, //index 11 ++ 0x00004001, ++ 0x26922039, //index 12 ++ 0x00004001, ++ 0x2E92203F, //index 13 ++ 0x00004001, ++ 0x3692203F, //index 14 ++ 0x00004001, ++ 0x3FF2203F, //index 15 ++ 0x00004001, ++}; ++ ++u32 wifi_txgain_table_24g_8800dcdw_h[32] = ++{ ++ 0xA55629C9, //index 0 ++ 0x00005825, ++ 0xAE5629C9, //index 1 ++ 0x00005825, ++ 0xAD5629CD, //index 2 ++ 0x00005825, ++ 0xAD5629D1, //index 3 ++ 0x00005825, ++ 0xAD5629D7, //index 4 ++ 0x00005825, ++ 0xAD5629DE, //index 5 ++ 0x00005825, ++ 0xAD5629E6, //index 6 ++ 0x00005825, ++ 0xBD5629E6, //index 7 ++ 0x00005825, ++ 0xBD5629F0, //index 8 ++ 0x00005825, ++ 0xCD5629F0, //index 9 ++ 0x00005825, ++ 0xE55629F0, //index 10 ++ 0x00005825, ++ 0xE55629FF, //index 11 ++ 0x00005825, ++ 0xE55629FF, //index 12 ++ 0x00002825, ++ 0xE75629FF, //index 13 ++ 0x00002825, ++ 0xFF5629FF, //index 14 ++ 0x00001825, ++ 0xFF5628FF, //index 15 ++ 0x00001025, ++}; ++ ++u32 wifi_txgain_table_24g_1_8800dcdw_h[32] = ++{ ++ 0x941A2048, //index 0 ++ 0x00001825, ++ 0x961A2048, //index 1 ++ 0x00001825, ++ 0x9D1A2048, //index 2 ++ 0x00001825, ++ 0x9A1A204F, //index 3 ++ 0x00001825, ++ 0x961A204F, //index 4 ++ 0x00001825, ++ 0x9A1A2057, //index 5 ++ 0x00001825, ++ 0x9C1A2057, //index 6 ++ 0x00001825, ++ 0xA31A205B, //index 7 ++ 0x00001825, ++ 0xAB1A205B, //index 8 ++ 0x00001825, ++ 0xAD1A205B, //index 9 ++ 0x00001825, ++ 0xA71A2064, //index 10 ++ 0x00001825, ++ 0xAD1A2070, //index 11 ++ 0x00001825, ++ 0xAD72207F, //index 12 ++ 0x00001825, ++ 0xBCAE207F, //index 13 ++ 0x00001825, ++ 0xBFB2207F, //index 14 ++ 0x00001825, ++ 0xD73A207F, //index 15 ++ 0x00001825, ++}; ++ ++#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ ++// ofdm ++uint32_t wifi_txgain_table_24g_8800dcdw_femkct[32] = { ++ 0x919221C2, //index 0 ++ 0x00007825, ++ 0x899221C3, //index 1 ++ 0x00007825, ++ 0x8B9221C3, //index 2 ++ 0x00007825, ++ 0x929221C3, //index 3 ++ 0x00007825, ++ 0x949221C4, //index 4 ++ 0x00007825, ++ 0x969221C4, //index 5 ++ 0x00007825, ++ 0x949221C6, //index 6 ++ 0x00007825, ++ 0x949221C8, //index 7 ++ 0x00007825, ++ 0x9C9221C8, //index 8 ++ 0x00007825, ++ 0x9C9221CA, //index 9 ++ 0x00007825, ++ 0x9C9221CB, //index 10 ++ 0x00007825, ++ 0x939221D5, //index 11 ++ 0x00007825, ++ 0x9B9221D7, //index 12 ++ 0x00007825, ++ 0xA49221D7, //index 13 ++ 0x00007825, ++ 0xA79221D7, //index 14 ++ 0x00007825, ++ 0xBD9221D7, //index 15 ++ 0x00007825, ++}; ++ ++// 11b ++uint32_t wifi_txgain_table_24g_1_8800dcdw_femkct[32] = { ++ 0x836E20C2, //index 0 ++ 0x00003024, ++ 0x856E20C2, //index 1 ++ 0x00003024, ++ 0x826E20C3, //index 2 ++ 0x00003024, ++ 0x836E20C3, //index 3 ++ 0x00003024, ++ 0x856E20C3, //index 4 ++ 0x00003024, ++ 0x876E20C3, //index 5 ++ 0x00003024, ++ 0x8B6E20C3, //index 6 ++ 0x00003024, ++ 0x926E20C4, //index 7 ++ 0x00003024, ++ 0x9A6E20C4, //index 8 ++ 0x00003024, ++ 0x936E20C5, //index 9 ++ 0x00003024, ++ 0x936E20C7, //index 10 ++ 0x00003024, ++ 0xA16E20C8, //index 11 ++ 0x00003024, ++ 0xA16E20CA, //index 12 ++ 0x00003024, ++ 0xA26E20CB, //index 13 ++ 0x00003024, ++ 0xAA6E20CD, //index 14 ++ 0x00003024, ++ 0xAC7220CF, //index 15 ++ 0x00003024, ++}; ++#endif ++ ++u32 wifi_rxgain_table_24g_20m_8800dcdw[64] = { ++ 0x82f282d1,//index 0 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x42f282d1,//index 1 ++ 0x95923524, ++ 0x80808419, ++ 0x000000f0, ++ 0x22f282d1,//index 2 ++ 0x9592c724, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282d1,//index 3 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x06f282d1,//index 4 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ad1,//index 5 ++ 0x9591a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ad3,//index 6 ++ 0x95923524, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ad7,//index 7 ++ 0x9595a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282d2,//index 8 ++ 0x95951124, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282f4,//index 9 ++ 0x95951124, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 10 ++ 0x9595a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 11 ++ 0x9599a324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 12 ++ 0x959da324, ++ 0x80808419, ++ 0x000000f0, ++ 0x02f282e6,//index 13 ++ 0x959f5924, ++ 0x80808419, ++ 0x000000f0, ++ 0x06f282e6,//index 14 ++ 0x959f5924, ++ 0x80808419, ++ 0x000000f0, ++ 0x0ef29ae6,//index 15 ++ 0x959f5924, //loft [35:34]=3 ++ 0x80808419, ++ 0x000000f0 ++}; ++ ++u32 wifi_rxgain_table_24g_40m_8800dcdw[64] = { ++ 0x83428151,//index 0 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x43428151,//index 1 ++ 0x96323528, ++ 0x80808419, ++ 0x000000f0, ++ 0x23428151,//index 2 ++ 0x9632c728, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428151,//index 3 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x07429951,//index 4 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d151,//index 5 ++ 0x9631a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d153,//index 6 ++ 0x96323528, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d157,//index 7 ++ 0x9635a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428152,//index 8 ++ 0x96351128, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428174,//index 9 ++ 0x96351128, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 10 ++ 0x9635a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 11 ++ 0x9639a328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 12 ++ 0x963da328, ++ 0x80808419, ++ 0x000000f0, ++ 0x03428166,//index 13 ++ 0x963f5928, ++ 0x80808419, ++ 0x000000f0, ++ 0x07429966,//index 14 ++ 0x963f5928, ++ 0x80808419, ++ 0x000000f0, ++ 0x0f42d166,//index 15 ++ 0x963f5928, ++ 0x80808419, ++ 0x000000f0 ++}; ++ ++#define RAM_LMAC_FW_ADDR 0x00150000 ++#ifdef CONFIG_DPD ++#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++extern int is_file_exist(char* name); ++#endif ++extern rf_misc_ram_lite_t dpd_res; ++ ++int aicwf_fdrv_dpd_result_apply_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", dpd_res->bit_mask[1]); ++ if (dpd_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void dpd_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == 1) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy dpd_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", dpd_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // dpd_high ++ AICWFDBG(LOGINFO, "dpd_high[0]=%x\n", dpd_res->dpd_high[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, dpd_high); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, dpd_high); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->dpd_high[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "dpd_high wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", dpd_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&dpd_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++ ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_fdrv_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res) ++{ ++ int ret = 0; ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_DPDRESULT_NAME_8800DC; ++ AICWFDBG(LOGINFO, "dpd_res file path:%s \r\n", filename); ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of dpd_res file\n"); ++ dst = NULL; ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d, dst[0]=%x\n", filename, size, dst[0]); ++ memcpy((u8 *)dpd_res, (u8 *)dst, sizeof(rf_misc_ram_lite_t)); ++ if (dst) { ++ rwnx_release_firmware_common(&dst); ++ } ++ return ret; ++} ++#endif ++#endif ++ ++#if defined(CONFIG_LOFT_CALIB) ++extern rf_misc_ram_lite_t loft_res_local; ++ ++int aicwf_fdrv_loft_result_apply_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *loft_res) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t ram_base_addr, ram_byte_cnt; ++ AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", loft_res->bit_mask[1]); ++ if (loft_res->bit_mask[1] == 0) { ++ AICWFDBG(LOGERROR, "void loft_res, bypass it.\n"); ++ return 0; ++ } ++ if (testmode == 1) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm))) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr); ++ /* Copy loft_res on the Embedded side */ ++ // bit_mask ++ AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", loft_res->bit_mask[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->bit_mask[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ // loft_res ++ AICWFDBG(LOGINFO, "loft_res[0]=%x\n", loft_res->loft_res[0]); ++ ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res); ++ ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res); ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->loft_res[0]); ++ if (ret) { ++ AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret); ++ return ret; ++ } ++ return ret; ++} ++#endif ++ ++int aicwf_fdrv_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw) ++{ ++ int ret = 0; ++ uint32_t cfg_base = 0x10164; ++ struct dbg_mem_read_cfm cfm; ++ uint32_t misc_ram_addr; ++ uint32_t misc_ram_size = 12; ++ int i; ++ ++ if (testmode == 1) { ++ cfg_base = RAM_LMAC_FW_ADDR + 0x0164; ++ } ++ // init misc ram ++ printk("%s\n", __func__); ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret); ++ return ret; ++ } ++ misc_ram_addr = cfm.memdata; ++ AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr); ++ for (i = 0; i < (misc_ram_size / 4); i++) { ++ ret = rwnx_send_dbg_mem_write_req(rwnx_hw, misc_ram_addr + i * 4, 0); ++ if (ret) { ++ AICWFDBG(LOGERROR, "rf misc ram[0x%x] wr fail: %d\n", misc_ram_addr + i * 4, ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++ ++ ++int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm){ ++ int ret = 0; ++ ++ if ((ret = rwnx_send_txpwr_lvl_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ ++ if (testmode == 0) { ++ #if !defined(CONFIG_EXT_FEM_8800DCDW) ++ if (IS_CHIP_ID_H()) { ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_h, 128))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw_h, 128))) ++ return -1; ++ } else { ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw, 128))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw, 128))) ++ return -1; ++ } ++ #else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ ++ { ++ ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_femkct, 128); ++ if (ret) { ++ return -1; ++ } ++ ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw_femkct, 128); ++ if (ret) { ++ return -1; ++ } ++ } ++ #endif ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 0, (u8_l *)wifi_rxgain_table_24g_20m_8800dcdw, 256))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_config_req(rwnx_hw, 32, 0, (u8_l *)wifi_rxgain_table_24g_40m_8800dcdw, 256))) ++ return -1; ++ ++ if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) { ++ return -1; ++ } ++ } else if (testmode == 1) { ++ if (chip_sub_id >= 1) { ++ #ifdef CONFIG_DPD ++ #ifndef CONFIG_FORCE_DPD_CALIB ++ if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 1) { ++ AICWFDBG(LOGINFO, "%s load dpd bin\n", __func__); ++ ret = aicwf_fdrv_dpd_result_load_8800dc(rwnx_hw, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "load dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ if (dpd_res.bit_mask[1]) { ++ ret = aicwf_fdrv_dpd_result_apply_8800dc(rwnx_hw, &dpd_res); ++ if (ret) { ++ AICWFDBG(LOGINFO, "apply dpd bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #elif defined(CONFIG_LOFT_CALIB) ++ if (loft_res_local.bit_mask[1]) { ++ ret = aicwf_fdrv_loft_result_apply_8800dc(rwnx_hw, &loft_res_local); ++ if (ret) { ++ AICWFDBG(LOGINFO, "apply loft res fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #else ++ { ++ ret = aicwf_fdrv_misc_ram_init_8800dc(rwnx_hw); ++ if (ret) { ++ AICWFDBG(LOGINFO, "misc ram init fail: %d\n", ret); ++ return ret; ++ } ++ } ++ #endif ++ ret = rwnx_send_rf_calib_req(rwnx_hw, cfm); ++ if (ret) { ++ AICWFDBG(LOGINFO, "rf calib req fail: %d\n", ret); ++ return ret; ++ } ++ } ++ } ++ ++ return 0 ; ++} ++ ++int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw){ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800DC; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing2((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ ++int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw){ ++ int size; ++ u32 *dst=NULL; ++ char *filename = FW_USERCONFIG_NAME_8800DC; ++ ++ AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename); ++ ++ /* load file */ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing2((char *)dst, size); ++ ++ rwnx_release_firmware_common(&dst); ++ ++ AICWFDBG(LOGINFO, "userconfig download complete\n\n"); ++ return 0; ++ ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h +new file mode 100644 +index 000000000000..249703b68389 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h +@@ -0,0 +1,15 @@ ++#include ++#include "aic_bsp_export.h" ++ ++#ifdef CONFIG_DPD ++int aicwf_fdrv_dpd_result_apply_8800dc(struct rwnx_hw * rwnx_hw, rf_misc_ram_lite_t * dpd_res); ++#ifndef CONFIG_FORCE_DPD_CALIB ++int aicwf_fdrv_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res); ++#endif ++#endif ++int aicwf_fdrv_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw); ++int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); ++int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw); ++int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw); ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h +new file mode 100644 +index 000000000000..25a5766567eb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h +@@ -0,0 +1,56 @@ ++ ++ ++#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ ++ ++ ++ ++/* message levels */ ++#define LOGERROR 0x0001 ++#define LOGINFO 0x0002 ++#define LOGTRACE 0x0004 ++#define LOGDEBUG 0x0008 ++#define LOGDATA 0x0010 ++#define LOGIRQ 0x0020 ++#define LOGSDPWRC 0x0040 ++#define LOGWAKELOCK 0x0080 ++#define LOGRXPOLL 0x0100 ++ ++extern int aicwf_dbg_level; ++void rwnx_data_dump(char* tag, void* data, unsigned long len); ++ ++#define AICWF_LOG "AICWFDBG(" ++ ++#define AICWFDBG(level, args, arg...) \ ++do { \ ++ if (aicwf_dbg_level & level) { \ ++ printk(AICWF_LOG#level")\t" args, ##arg); \ ++ } \ ++} while (0) ++ ++#define RWNX_DBG(fmt, ...) \ ++do { \ ++ if (aicwf_dbg_level & LOGTRACE) { \ ++ printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \ ++ } \ ++} while (0) ++ ++ ++ ++#if 0 ++#define RWNX_DBG(fmt, ...) \ ++ do { \ ++ if (aicwf_dbg_level & LOGTRACE) { \ ++ printk(AICWF_LOG"LOGTRACE"")\t" fmt, ##__VA_ARGS__); \ ++ } \ ++ } while (0) ++#define AICWFDBG(args, level) \ ++do { \ ++ if (aicwf_dbg_level & level) { \ ++ printk(AICWF_LOG"(%s)\t" ,#level); \ ++ printf args; \ ++ } \ ++} while (0) ++#endif ++ ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c +new file mode 100644 +index 000000000000..59502b89a318 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c +@@ -0,0 +1,97 @@ ++#include ++#include ++#include ++#include ++#include ++#include "aicwf_rx_prealloc.h" ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct aicwf_rx_buff_list aic_rx_buff_list; ++ ++int aic_rxbuff_num_max = 30; ++ ++int aic_rxbuff_size = (64 * 512); ++ ++struct rx_buff *aicwf_prealloc_rxbuff_alloc(spinlock_t *lock) ++{ ++ unsigned long flags; ++ struct rx_buff *rxbuff = NULL; ++ ++ spin_lock_irqsave(lock, flags); ++ if (list_empty(&aic_rx_buff_list.rxbuff_list)) { ++ spin_unlock_irqrestore(lock, flags); ++ printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); ++ return NULL; ++ } else { ++ rxbuff = list_first_entry(&aic_rx_buff_list.rxbuff_list, ++ struct rx_buff, queue); ++ list_del_init(&rxbuff->queue); ++ atomic_dec(&aic_rx_buff_list.rxbuff_list_len); ++ } ++ spin_unlock_irqrestore(lock, flags); ++ //printk("len:%d\n", aic_rx_buff_list.rxbuff_list_len); ++ memset(rxbuff->data, 0, aic_rxbuff_size); ++ rxbuff->len = 0; ++ rxbuff->start = NULL; ++ rxbuff->read = NULL; ++ rxbuff->end = NULL; ++ ++ return rxbuff; ++} ++ ++void aicwf_prealloc_rxbuff_free(struct rx_buff *rxbuff, spinlock_t *lock) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(lock, flags); ++ list_add_tail(&rxbuff->queue, &aic_rx_buff_list.rxbuff_list); ++ atomic_inc(&aic_rx_buff_list.rxbuff_list_len); ++ spin_unlock_irqrestore(lock, flags); ++} ++ ++int aicwf_prealloc_init() ++{ ++ struct rx_buff *rxbuff; ++ int i = 0; ++ ++ printk("%s enter\n", __func__); ++ INIT_LIST_HEAD(&aic_rx_buff_list.rxbuff_list); ++ ++ for (i = 0 ; i < aic_rxbuff_num_max ; i++) { ++ rxbuff = kzalloc(sizeof(struct rx_buff), GFP_KERNEL); ++ if (rxbuff) { ++ rxbuff->data = kzalloc(aic_rxbuff_size, GFP_KERNEL); ++ if (rxbuff->data == NULL) { ++ printk("failed to alloc rxbuff data\n"); ++ kfree(rxbuff); ++ continue; ++ } ++ rxbuff->len = 0; ++ rxbuff->start = NULL; ++ rxbuff->read = NULL; ++ rxbuff->end = NULL; ++ list_add_tail(&rxbuff->queue, &aic_rx_buff_list.rxbuff_list); ++ atomic_inc(&aic_rx_buff_list.rxbuff_list_len); ++ } ++ } ++ ++ printk("pre alloc rxbuff list len: %d\n", (int)atomic_read(&aic_rx_buff_list.rxbuff_list_len)); ++ return 0; ++} ++ ++void aicwf_prealloc_exit() ++{ ++ struct rx_buff *rxbuff; ++ struct rx_buff *pos; ++ ++ printk("%s enter\n", __func__); ++ ++ printk("free pre alloc rxbuff list %d\n", (int)atomic_read(&aic_rx_buff_list.rxbuff_list_len)); ++ list_for_each_entry_safe(rxbuff, pos, &aic_rx_buff_list.rxbuff_list, queue) { ++ list_del_init(&rxbuff->queue); ++ kfree(rxbuff->data); ++ kfree(rxbuff); ++ } ++} ++#endif ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h +new file mode 100644 +index 000000000000..64a494aeef16 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h +@@ -0,0 +1,24 @@ ++#ifndef _AICWF_RX_PREALLOC_H_ ++#define _AICWF_RX_PREALLOC_H_ ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct rx_buff { ++ struct list_head queue; ++ unsigned char *data; ++ u32 len; ++ uint8_t *start; ++ uint8_t *end; ++ uint8_t *read; ++}; ++ ++struct aicwf_rx_buff_list { ++ struct list_head rxbuff_list; ++ atomic_t rxbuff_list_len; ++}; ++ ++struct rx_buff *aicwf_prealloc_rxbuff_alloc(spinlock_t *lock); ++void aicwf_prealloc_rxbuff_free(struct rx_buff *rxbuff, spinlock_t *lock); ++int aicwf_prealloc_init(void); ++void aicwf_prealloc_exit(void); ++#endif ++#endif /* _AICWF_RX_PREALLOC_H_ */ +\ No newline at end of file +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c +new file mode 100644 +index 000000000000..0c0fa323b3de +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c +@@ -0,0 +1,3462 @@ ++/** ++ * aicwf_sdmmc.c ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aicwf_txrxif.h" ++#include "aicwf_sdio.h" ++#include "sdio_host.h" ++#include "rwnx_defs.h" ++#include "rwnx_platform.h" ++#include "aicwf_rx_prealloc.h" ++#include "rwnx_msg_tx.h" ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#else ++#include ++#endif ++#include "rwnx_wakelock.h" ++ ++#ifdef CONFIG_INGENIC_T20 ++#include "mach/jzmmc.h" ++#endif /* CONFIG_INGENIC_T20 */ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#include ++#endif ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#include ++#endif ++ ++#include "aic_bsp_export.h" ++extern uint8_t scanning; ++ ++#ifdef CONFIG_SDIO_ADMA ++unsigned char sdio_tx_buf_fill[512]; ++unsigned char sdio_tx_buf_dummy[SDIO_TX_SLIST_MAX][8]; ++#endif ++ ++#ifdef CONFIG_GPIO_WAKEUP ++extern int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter); ++ ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++#include ++void rwnx_init_wifi_suspend_node(void); ++void rwnx_deinit_wifi_suspend_node(void); ++void rwnx_set_wifi_suspend(char onoff); ++struct proc_dir_entry *wifi_suspend_node; ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ ++#endif//CONFIG_GPIO_WAKEUP ++ ++int tx_aggr_counter = 32; ++module_param_named(tx_aggr_counter, tx_aggr_counter, int, 0644); ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++int tx_fc_low_water = AICWF_SDIO_TX_LOW_WATER; ++module_param_named(tx_fc_low_water, tx_fc_low_water, int, 0644); ++ ++int tx_fc_high_water = AICWF_SDIO_TX_HIGH_WATER; ++module_param_named(tx_fc_high_water, tx_fc_high_water, int, 0644); ++#endif ++ ++#if 0 ++void rwnx_data_dump(char* tag, void* data, unsigned long len){ ++ if(dump){ ++ unsigned long i = 0; ++ uint8_t* data_ = (uint8_t* )data; ++ ++ printk("%s %s len:(%lu)\r\n", __func__, tag, len); ++ ++ for (i = 0; i < len; i += 16){ ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", ++ data_[0 + i], ++ data_[1 + i], ++ data_[2 + i], ++ data_[3 + i], ++ data_[4 + i], ++ data_[5 + i], ++ data_[6 + i], ++ data_[7 + i], ++ data_[8 + i], ++ data_[9 + i], ++ data_[10 + i], ++ data_[11 + i], ++ data_[12 + i], ++ data_[13 + i], ++ data_[14 + i], ++ data_[15 + i]); ++ } ++ } ++} ++#endif ++ ++int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ *val = sdio_readb(sdiodev->func, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func); ++ sdio_writeb(sdiodev->func, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++} ++ ++int aicwf_sdio_func2_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func2); ++ *val = sdio_readb(sdiodev->func2, regaddr, &ret); ++ sdio_release_host(sdiodev->func2); ++ return ret; ++} ++ ++int aicwf_sdio_func2_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) ++{ ++ int ret; ++ sdio_claim_host(sdiodev->func2); ++ sdio_writeb(sdiodev->func2, val, regaddr, &ret); ++ sdio_release_host(sdiodev->func2); ++ return ret; ++} ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++void aicwf_sdio_tx_netif_flowctrl(struct rwnx_hw *rwnx_hw, bool state) ++{ ++ struct rwnx_vif *rwnx_vif; ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (! rwnx_vif->up) ++ continue; ++ if (state) ++ netif_tx_stop_all_queues(rwnx_vif->ndev);//netif_stop_queue(rwnx_vif->ndev); ++ else ++ netif_tx_wake_all_queues(rwnx_vif->ndev);//netif_wake_queue(rwnx_vif->ndev); ++ } ++} ++#endif ++ ++#ifdef CONFIG_TEMP_CONTROL ++//int interval = 30; ++//module_param(interval, int, 0660); ++static int update_state(s8_l value, u8_l current_state) ++{ ++ if (value > TEMP_THD_2) ++ return 2; ++ else if (value > (TEMP_THD_2 - BUFFERING_V2) && (current_state == 2)) ++ return 2; ++ else if (value > TEMP_THD_1 && current_state != 2) ++ return 1; ++ else if (value > (TEMP_THD_1 - BUFFERING_V1) && current_state == 1) ++ return 1; ++ else if (current_state == 0) ++ return 0; ++ else ++ return 1; ++} ++ ++void aicwf_netif_ctrl(struct aic_sdio_dev *sdiodev, int val) ++{ ++ unsigned long flags; ++ struct rwnx_vif *rwnx_vif; ++ ++ if (sdiodev->net_stop) ++ return; ++ ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ list_for_each_entry(rwnx_vif, &sdiodev->rwnx_hw->vifs, list) { ++ if (!rwnx_vif || !rwnx_vif->ndev || !rwnx_vif->up) ++ continue; ++ netif_tx_stop_all_queues(rwnx_vif->ndev);//netif_stop_queue(rwnx_vif->ndev); ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++ sdiodev->net_stop = true; ++ mod_timer(&sdiodev->netif_timer, jiffies + msecs_to_jiffies(val)); ++ ++ return; ++} ++ ++void aicwf_temp_ctrl(struct aic_sdio_dev *sdiodev) ++{ ++ if (sdiodev->set_level) { ++ if (sdiodev->set_level == 1) { ++ sdiodev->get_level = 1; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t1/*TMR_INTERVAL_1*/); ++ //mdelay(1); ++ } else if (sdiodev->set_level == 2) { ++ sdiodev->get_level = 2; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t2/*TMR_INTERVAL_2*/); ++ //mdelay(2); ++ } ++ return; ++ } else { ++ if (sdiodev->cur_temp > (TEMP_THD_1 - 8)) { ++ //if ((sdiodev->cur_temp > TEMP_THD_1 && sdiodev->cur_temp <= TEMP_THD_2) || (sdiodev->cur_stat == 1)) { ++ if (update_state(sdiodev->cur_temp, sdiodev->cur_stat) == 1) { ++ sdiodev->get_level = 1; ++ sdiodev->cur_stat = 1; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t1/*TMR_INTERVAL_1*/); ++ //mdelay(1); ++ //break; ++ //} else if ((sdiodev->cur_temp > TEMP_THD_2) || (sdiodev->cur_stat == 2)) { ++ } else if (update_state(sdiodev->cur_temp, sdiodev->cur_stat) == 2) { ++ sdiodev->get_level = 2; ++ sdiodev->cur_stat = 2; ++ aicwf_netif_ctrl(sdiodev, sdiodev->interval_t2/*TMR_INTERVAL_2*/); ++ //mdelay(2); ++ //break; ++ } ++ return; ++ } ++ ++ if (sdiodev->cur_stat) { ++ AICWFDBG(LOGINFO, "reset cur_stat"); ++ sdiodev->cur_stat = 0; ++ } ++ ++ return; ++ } ++} ++ ++void aicwf_netif_worker(struct work_struct *work) ++{ ++ struct aic_sdio_dev *sdiodev = container_of(work, struct aic_sdio_dev, netif_work); ++ unsigned long flags; ++ struct rwnx_vif *rwnx_vif; ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ list_for_each_entry(rwnx_vif, &sdiodev->rwnx_hw->vifs, list) { ++ if (!rwnx_vif || !rwnx_vif->ndev || !rwnx_vif->up) ++ continue; ++ netif_tx_wake_all_queues(rwnx_vif->ndev);//netif_wake_queue(rwnx_vif->ndev); ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++ sdiodev->net_stop = false; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++static void aicwf_netif_timer(ulong data) ++#else ++static void aicwf_netif_timer(struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, netif_timer); ++#endif ++ ++ if (!work_pending(&sdiodev->netif_work)) ++ schedule_work(&sdiodev->netif_work); ++ ++ return; ++} ++ ++void aicwf_temp_ctrl_worker(struct work_struct *work) ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct mm_set_vendor_swconfig_cfm cfm; ++ struct aic_sdio_dev *sdiodev = container_of(work, struct aic_sdio_dev, tp_ctrl_work); ++ rwnx_hw = sdiodev->rwnx_hw; ++ //AICWFDBG(LOGINFO, "%s\n", __func__); ++ ++ rwnx_hw->started_jiffies = jiffies; ++ ++ rwnx_send_get_temp_req(rwnx_hw, &cfm); ++ sdiodev->cur_temp = cfm.temp_comp_get_cfm.degree; ++ ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++ ++ return; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++static void aicwf_temp_ctrl_timer(ulong data) ++#else ++static void aicwf_temp_ctrl_timer(struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, tp_ctrl_timer); ++#endif ++ ++ if (!work_pending(&sdiodev->tp_ctrl_work)) ++ schedule_work(&sdiodev->tp_ctrl_work); ++ ++ return; ++} ++#endif ++ ++int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = -1; ++ u8 fc_reg = 0; ++ u32 count = 0; ++ ++ while (true) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.flow_ctrl_reg, &fc_reg); ++ if (ret) { ++ return -1; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ fc_reg = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; ++ } ++ ++ if (fc_reg != 0) { ++ ret = fc_reg; ++ if(ret > tx_aggr_counter){ ++ ret = tx_aggr_counter; ++ } ++ return ret; ++ } else { ++ if (count >= FLOW_CTRL_RETRY_COUNT) { ++ ret = -fc_reg; ++ break; ++ } ++ count++; ++ if (count < 30) ++ udelay(200); ++ else if(count < 40) ++ msleep(2); ++ else ++ msleep(10); ++ } ++ } ++ ++ return ret; ++} ++ ++ ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = -1; ++ u8 fc_reg = 0; ++ u32 count = 0; ++ ++ while (true) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.flow_ctrl_reg, &fc_reg); ++ if (ret) { ++ return -1; ++ } ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ fc_reg = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; ++ } ++ ++ if (fc_reg > DATA_FLOW_CTRL_THRESH) { ++ ret = fc_reg; ++ if(ret > tx_aggr_counter){ ++ ret = tx_aggr_counter; ++ } ++ return ret; ++ } else { ++ if (count >= FLOW_CTRL_RETRY_COUNT) { ++ ret = -fc_reg; ++ break; ++ } ++ count++; ++ if (count < 30) ++ udelay(200); ++ else if(count < 40) ++ msleep(2); ++ else ++ msleep(10); ++ } ++ } ++ ++ return ret; ++} ++ ++ ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) ++{ ++ int ret = 0; ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, buf, count); ++ sdio_release_host(sdiodev->func); ++ ++ return ret; ++} ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct rx_buff *rxbuff, ++ u32 size) ++{ ++ int ret; ++ ++ if ((!rxbuff->data) || (!size)) { ++ return -EINVAL;; ++ } ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_readsb(sdiodev->func, rxbuff->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ rxbuff->len = size; ++ ++ return ret; ++} ++#else ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, ++ u32 size) ++{ ++ int ret; ++ ++ if ((!skbbuf) || (!size)) { ++ return -EINVAL;; ++ } ++ ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_readsb(sdiodev->func, skbbuf->data, sdiodev->sdio_reg.rd_fifo_addr, size); ++ sdio_release_host(sdiodev->func); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ skbbuf->len = size; ++ ++ return ret; ++} ++#endif ++ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++static int wakeup_enable; ++static u32 hostwake_irq_num; ++#endif//CONFIG_GPIO_WAKEUP ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)//LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++//static struct wakeup_source *ws_rx_sdio; ++//static struct wakeup_source *ws_sdio_pwrctrl; ++//static struct wakeup_source *ws_tx_sdio; ++#ifdef CONFIG_GPIO_WAKEUP ++//static struct wakeup_source *ws; ++#endif ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++#include ++static struct wake_lock irq_wakelock; ++//struct wake_lock irq_wakelock; ++#endif//CONFIG_GPIO_WAKEUP ++#endif//ANDROID_PLATFORM ++#endif ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++extern int sunxi_wlan_get_oob_irq(int *, int *); ++#else ++extern int sunxi_wlan_get_oob_irq(void); ++extern int sunxi_wlan_get_oob_irq_flags(void); ++#endif ++#endif// CONFIG_PLATFORM_ALLWINNER ++ ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++static struct wakeup_source *ws; ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++#include ++static struct wake_lock irq_wakelock; ++#endif//CONFIG_GPIO_WAKEUP ++#endif//ANDROID_PLATFORM ++#endif ++#endif ++ ++#if 0 ++void rwnx_pm_stay_awake(struct aic_sdio_dev *sdiodev){ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ spin_lock_bh(&sdiodev->wslock); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if(ws != NULL){ ++ __pm_stay_awake(ws); ++ AICWFDBG(LOGWAKELOCK, "%s active_count:%d relax_count:%d\r\n", __func__, (int)ws->active_count, (int)ws->relax_count); ++ } ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++ wake_lock(&irq_wakelock); ++#endif //CONFIG_GPIO_WAKEUP ++#endif //ANDROID_PLATFORM ++#endif ++ ++ spin_unlock_bh(&sdiodev->wslock); ++#endif ++} ++ ++void rwnx_pm_relax(struct aic_sdio_dev *sdiodev){ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ spin_lock_bh(&sdiodev->wslock); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if(ws != NULL){ ++ __pm_relax(ws); ++ AICWFDBG(LOGWAKELOCK, "%s active_count:%d relax_count:%d\r\n", __func__, (int)ws->active_count, (int)ws->relax_count); ++ } ++#else ++#ifdef ANDROID_PLATFORM ++#ifdef CONFIG_GPIO_WAKEUP ++ wake_unlock(&irq_wakelock); ++#endif //CONFIG_GPIO_WAKEUP ++#endif //ANDROID_PLATFORM ++#endif ++ spin_unlock_bh(&sdiodev->wslock); ++#endif ++ ++} ++#endif ++ ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ ++void rwnx_set_wifi_suspend(char onoff); ++ ++ ++static irqreturn_t rwnx_hostwake_irq_handler(int irq, void *para) ++{ ++ static int wake_cnt; ++ wake_cnt++; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ rwnx_wakeup_lock_timeout(g_rwnx_plat->sdiodev->rwnx_hw->ws_rx, 1000); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_timeout(&irq_wakelock, HZ); ++#endif //ANDROID_PLATFORM ++#endif ++ ++ AICWFDBG(LOGIRQ, "%s(%d): wake_irq_cnt = %d\n", __func__, __LINE__, wake_cnt); ++ ++#ifdef CONFIG_OOB ++#if 0//old oob feature ++ complete(&g_rwnx_plat->sdiodev->bus_if->busrx_trgg); ++#else//new oob feature ++ if(g_rwnx_plat->sdiodev->oob_enable){ ++ complete(&g_rwnx_plat->sdiodev->bus_if->busirq_trgg); ++ } ++#endif//old oob feature ++#endif ++ ++ return IRQ_HANDLED; ++} ++#endif//CONFIG_GPIO_WAKEUP ++ ++#ifdef CONFIG_GPIO_WAKEUP ++static int rwnx_disable_hostwake_irq(void); ++static int rwnx_enable_hostwake_irq(void); ++#endif ++ ++static int rwnx_register_hostwake_irq(struct device *dev) ++{ ++ int ret = 0;//-1; ++#ifdef CONFIG_GPIO_WAKEUP ++ unsigned long flag_edge; ++ struct aicbsp_feature_t aicwf_feature; ++ int irq_flags; ++//TODO hostwake_irq_num hostwake_irq_num and wakeup_enable ++ ++ aicbsp_get_feature(&aicwf_feature, NULL); ++ if (aicwf_feature.irqf == 0) ++ flag_edge = IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND; ++ else ++ flag_edge = IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND; ++ ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ hostwake_irq_num = sunxi_wlan_get_oob_irq(&irq_flags, &wakeup_enable); ++#else ++ hostwake_irq_num = sunxi_wlan_get_oob_irq(); ++ irq_flags = sunxi_wlan_get_oob_irq_flags(); ++ wakeup_enable = 1; ++#endif ++#endif //CONFIG_PLATFORM_ALLWINNER ++ ++//For Rockchip ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ hostwake_irq_num = rockchip_wifi_get_oob_irq(); ++ printk("%s hostwake_irq_num:%d \r\n", __func__, hostwake_irq_num); ++ irq_flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE) & IRQF_TRIGGER_MASK; ++ printk("%s irq_flags:%d \r\n", __func__, irq_flags); ++ wakeup_enable = 1; ++#endif //CONFIG_PLATFORM_ROCKCHIP ++ //For Rockchip ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ hostwake_irq_num = rockchip_wifi_get_oob_irq(); ++ printk("%s hostwake_irq_num:%d \r\n", __func__, hostwake_irq_num); ++ irq_flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE) & IRQF_TRIGGER_MASK; ++ printk("%s irq_flags:%d \r\n", __func__, irq_flags); ++ wakeup_enable = 1; ++#endif //CONFIG_PLATFORM_ROCKCHIP ++ ++ ++ ++ if (wakeup_enable) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ //ws = wakeup_source_register(dev, "wifisleep"); ++ //ws_tx_sdio = wakeup_source_register(dev, "wifi_tx_sleep"); ++ //ws_rx_sdio = wakeup_source_register(dev, "wifi_rx_sleep"); ++ //ws_sdio_pwrctrl = wakeup_source_register(dev, "sdio_pwrctrl_sleep"); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_init(&irq_wakelock, WAKE_LOCK_SUSPEND, "wifisleep"); ++#endif ++#endif ++ ret = device_init_wakeup(dev, true); ++ if (ret < 0) { ++ pr_err("%s(%d): device init wakeup failed!\n", __func__, __LINE__); ++ return ret; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ ret = dev_pm_set_wake_irq(dev, hostwake_irq_num); ++#endif ++ if (ret < 0) { ++ pr_err("%s(%d): can't enable wakeup src!\n", __func__, __LINE__); ++ goto fail1; ++ } ++ ++ ret = request_irq(hostwake_irq_num, rwnx_hostwake_irq_handler, flag_edge, "rwnx_hostwake_irq", NULL); ++ ++ if (ret < 0) { ++ pr_err("%s(%d): request_irq fail! ret = %d\n", __func__, __LINE__, ret); ++ goto fail2; ++ } ++ } ++ //disable_irq(hostwake_irq_num); ++ rwnx_disable_hostwake_irq(); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ dev_pm_clear_wake_irq(dev); ++#endif ++ rwnx_enable_hostwake_irq(); ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++ return ret; ++ ++fail2: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ dev_pm_clear_wake_irq(dev); ++#endif ++fail1: ++ device_init_wakeup(dev, false); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ //wakeup_source_unregister(ws); ++ //wakeup_source_unregister(ws_tx_sdio); ++ //wakeup_source_unregister(ws_rx_sdio); ++ //wakeup_source_unregister(ws_sdio_pwrctrl); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_destroy(&irq_wakelock); ++#endif ++#endif ++#endif//CONFIG_GPIO_WAKEUP ++ return ret; ++} ++ ++static int rwnx_unregister_hostwake_irq(struct device *dev) ++{ ++#ifdef CONFIG_GPIO_WAKEUP ++ rwnx_disable_hostwake_irq(); ++ if (wakeup_enable) { ++ device_init_wakeup(dev, false); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++ dev_pm_clear_wake_irq(dev); ++#else ++ AICWFDBG(LOGERROR, "%s kernel unsupport this feature!\r\n", __func__); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ //wakeup_source_unregister(ws); ++ //wakeup_source_unregister(ws_tx_sdio); ++ //wakeup_source_unregister(ws_rx_sdio); ++ //wakeup_source_unregister(ws_sdio_pwrctrl); ++#else ++#ifdef ANDROID_PLATFORM ++ wake_lock_destroy(&irq_wakelock); ++#endif //ANDROID_PLATFORM ++#endif ++ } ++ free_irq(hostwake_irq_num, NULL); ++#endif//CONFIG_GPIO_WAKEUP ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++ return 0; ++} ++ ++#ifdef CONFIG_GPIO_WAKEUP ++static int rwnx_enable_hostwake_irq(void) ++{ ++#ifdef CONFIG_GPIO_WAKEUP ++ enable_irq(hostwake_irq_num); ++ enable_irq_wake(hostwake_irq_num); ++#endif//CONFIG_GPIO_WAKEUP ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++ return 0; ++} ++ ++static int rwnx_disable_hostwake_irq(void) ++{ ++ AICWFDBG(LOGINFO, "%s(%d)\n", __func__, __LINE__); ++#ifdef CONFIG_GPIO_WAKEUP ++ disable_irq_nosync(hostwake_irq_num); ++ //disable_irq_wake(hostwake_irq_num); ++ //disable_irq(hostwake_irq_num); ++#endif//CONFIG_GPIO_WAKEUP ++ return 0; ++} ++#endif ++ ++static int aicwf_sdio_chipmatch(struct aic_sdio_dev *sdio_dev, u16_l vid, u16_l did){ ++ ++ if(vid == SDIO_VENDOR_ID_AIC8801 && did == SDIO_DEVICE_ID_AIC8801){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8801; ++ AICWFDBG(LOGINFO, "%s USE AIC8801\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800DC && did == SDIO_DEVICE_ID_AIC8800DC){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800DC; ++ AICWFDBG(LOGINFO, "%s USE AIC8800DC\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80 && did == SDIO_DEVICE_ID_AIC8800D80){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80\r\n", __func__); ++ return 0; ++ }else if(vid == SDIO_VENDOR_ID_AIC8800D80X2 && did == SDIO_DEVICE_ID_AIC8800D80X2){ ++ sdio_dev->chipid = PRODUCT_ID_AIC8800D80X2; ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80X2\r\n", __func__); ++ return 0; ++ }else{ ++ return -1; ++ } ++} ++ ++ ++extern int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter); ++ ++static int aicwf_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ struct mmc_host *host; ++ struct aic_sdio_dev *sdiodev; ++ struct aicwf_bus *bus_if; ++ int err = -ENODEV; ++ ++ AICWFDBG(LOGDEBUG, "%s:%d\n", __func__, func->num); ++ AICWFDBG(LOGDEBUG, "Class=%x\n", func->class); ++ AICWFDBG(LOGDEBUG, "sdio vendor ID: 0x%04x\n", func->vendor); ++ AICWFDBG(LOGDEBUG, "sdio device ID: 0x%04x\n", func->device); ++ AICWFDBG(LOGDEBUG, "Function#: %d\n", func->num); ++ ++ host = func->card->host; ++ if (func->num != 1) { ++ return err; ++ } ++ ++ bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_KERNEL); ++ if (!bus_if) { ++ sdio_err("alloc bus fail\n"); ++ return -ENOMEM; ++ } ++ ++ sdiodev = kzalloc(sizeof(struct aic_sdio_dev), GFP_KERNEL); ++ if (!sdiodev) { ++ sdio_err("alloc sdiodev fail\n"); ++ kfree(bus_if); ++ return -ENOMEM; ++ } ++ ++ ++ err = aicwf_sdio_chipmatch(sdiodev, func->vendor, func->device); ++ ++ sdiodev->func = func; ++ sdiodev->bus_if = bus_if; ++ ++#ifdef CONFIG_OOB ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ AICWFDBG(LOGERROR, "%s ERROR!!! 8801 not support OOB \r\n", __func__); ++ sdiodev->oob_enable = false; ++ }else{ ++ sdiodev->oob_enable = true; ++ } ++#else ++ sdiodev->oob_enable = false; ++#endif ++ ++ atomic_set(&sdiodev->is_bus_suspend, 0); ++ bus_if->bus_priv.sdio = sdiodev; ++ ++ dev_set_drvdata(&func->dev, bus_if); ++ sdiodev->dev = &func->dev; ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ sdiodev->func2 = func->card->sdio_func[1]; ++ } ++ ++ //sdio func init start ++ if (sdiodev->chipid != PRODUCT_ID_AIC8800D80 && sdiodev->chipid != PRODUCT_ID_AIC8800D80X2) { ++ err = aicwf_sdio_func_init(sdiodev); ++ } else { ++ err = aicwf_sdiov3_func_init(sdiodev); ++ } ++ if (err < 0) { ++ sdio_err("sdio func init fail\n"); ++ goto fail; ++ } ++ //sdio func init end ++ ++ if (aicwf_sdio_bus_init(sdiodev) == NULL) { ++ sdio_err("sdio bus init fail\n"); ++ err = -1; ++ goto fail; ++ } ++ ++ host->caps |= MMC_CAP_NONREMOVABLE; ++ aicwf_rwnx_sdio_platform_init(sdiodev); ++ aicwf_hostif_ready(); ++ err = rwnx_register_hostwake_irq(sdiodev->dev); ++ if (err != 0) ++ return err; ++ ++#ifdef CONFIG_GPIO_WAKEUP ++#ifdef CONFIG_OOB ++ if(sdiodev->oob_enable){ ++ AICWFDBG(LOGINFO, "%s SDIOWIFI_INTR_CONFIG_REG Disable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ err = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x0); ++ if (err < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_INTR_CONFIG_REG); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++#if 0 ++#if 0//old oob feature ++ sdiodev->oob_enable = true; ++#else//new oob feature ++ sdiodev->oob_enable = true; ++#endif//old oob feature ++#endif ++ } ++#endif ++ ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++ rwnx_init_wifi_suspend_node(); ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++#endif//CONFIG_GPIO_WAKEUP ++ device_disable_async_suspend(sdiodev->dev); ++ ++ return 0; ++fail: ++ aicwf_sdio_func_deinit(sdiodev); ++ dev_set_drvdata(&func->dev, NULL); ++ kfree(sdiodev); ++ kfree(bus_if); ++ aicwf_hostif_fail(); ++ return err; ++} ++ ++void aicwf_sdio_probe_(struct sdio_func *func, ++ const struct sdio_device_id *id){ ++ aicwf_sdio_probe(func, NULL); ++} ++ ++ ++static void aicwf_sdio_remove(struct sdio_func *func) ++{ ++ struct mmc_host *host; ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_sdio_dev *sdiodev = NULL; ++ ++ AICWFDBG(LOGINFO, "%s Enter\n", __func__); ++ host = func->card->host; ++ host->caps &= ~MMC_CAP_NONREMOVABLE; ++ bus_if = dev_get_drvdata(&func->dev); ++ if (!bus_if) { ++ return; ++ } ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ if (!sdiodev) { ++ return; ++ } ++ ++ sdiodev->bus_if->state = BUS_DOWN_ST; ++ aicwf_sdio_release(sdiodev); ++ aicwf_sdio_func_deinit(sdiodev); ++ rwnx_unregister_hostwake_irq(sdiodev->dev); ++ dev_set_drvdata(&sdiodev->func->dev, NULL); ++ kfree(sdiodev); ++ kfree(bus_if); ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++ rwnx_deinit_wifi_suspend_node(); ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ AICWFDBG(LOGINFO, "%s done\n", __func__); ++} ++ ++void aicwf_sdio_remove_(struct sdio_func *func){ ++ aicwf_sdio_remove(func); ++} ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_SHUTDOWN_CALLBACK ++int rwnx_close_(struct net_device *dev); ++ ++void aicwf_sdio_shutdown(struct device *dev) ++{ ++ struct rwnx_vif *rwnx_vif, *tmp; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ AICWFDBG(LOGINFO, "%s Enter", __func__); ++ list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { ++ if (rwnx_vif->ndev && test_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags)){ ++ AICWFDBG(LOGINFO, "%s rwnx_close by shutdown", __func__); ++ rwnx_close_(rwnx_vif->ndev); ++ ++ }else{ ++ if(!rwnx_vif->ndev){ ++ AICWFDBG(LOGERROR, "%s rwnx_vif->ndev is NULL \r\n", __func__); ++ } ++ if(!test_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags)){ ++ AICWFDBG(LOGERROR, "%s rwnx_vif->drv_flags close\r\n", __func__); ++ } ++ } ++ ++ } ++ AICWFDBG(LOGINFO, "%s Exit", __func__); ++ ++} ++#endif ++#endif ++ ++#if defined(CONFIG_AUTO_POWERSAVE) ++static int aicwf_wakeup_lock_status(struct rwnx_hw *rwnx_hw) ++{ ++ if(rwnx_hw->ws_tx && rwnx_hw->ws_tx->active) ++ return -1; ++ ++ if(rwnx_hw->ws_rx && rwnx_hw->ws_rx->active) ++ return -1; ++ ++ if(rwnx_hw->ws_pwrctrl && rwnx_hw->ws_pwrctrl->active) ++ return -1; ++ ++ if(rwnx_hw->ws_irqrx && rwnx_hw->ws_irqrx->active) ++ return -1; ++ ++ return 0; ++} ++#endif ++ ++static int aicwf_sdio_suspend(struct device *dev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ mmc_pm_flag_t sdio_flags; ++ struct rwnx_vif *rwnx_vif, *tmp; ++ ++ sdio_dbg("%s enter\n", __func__); ++ ++ list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { ++ if (rwnx_vif->ndev) ++ netif_device_detach(rwnx_vif->ndev); ++ } ++ ++ sdio_flags = sdio_get_host_pm_caps(sdiodev->func); ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ return -EINVAL; ++ } ++ ret = sdio_set_host_pm_flags(sdiodev->func, MMC_PM_KEEP_POWER); ++ if (ret) { ++ return ret; ++ } ++ ++#ifdef CONFIG_TEMP_CONTROL ++ del_timer_sync(&sdiodev->tp_ctrl_timer); ++ cancel_work_sync(&sdiodev->tp_ctrl_work); ++ ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++ ++ del_timer_sync(&sdiodev->netif_timer); ++ cancel_work_sync(&sdiodev->netif_work); ++#endif ++ ++#if (defined(CONFIG_AUTO_POWERSAVE) && defined(CONFIG_SDIO_PWRCTRL)) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ ++ if((sdiodev->chipid == PRODUCT_ID_AIC8800D80) || (sdiodev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ sdio_dbg("autops set\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x8); ++ if(ret) { ++ sdio_err("sdio set autops fail\n"); ++ } ++ } ++#endif ++ ++ #if (!defined(CONFIG_AUTO_POWERSAVE)) ++ while (sdiodev->state == SDIO_ACTIVE_ST) { ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) ++ continue; ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ #endif ++ up(&sdiodev->tx_priv->txctl_sema); ++ break; ++ } ++ #else ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ #endif ++ #endif ++#ifdef CONFIG_GPIO_WAKEUP ++// rwnx_enable_hostwake_irq(); ++#endif ++ ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ sdio_dbg("%s SDIOWIFI_INTR_CONFIG_REG Disable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_INTR_CONFIG_REG); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++#endif ++ atomic_set(&sdiodev->is_bus_suspend, 1); ++// smp_mb(); ++ ++#if defined(CONFIG_AUTO_POWERSAVE) ++ if(aicwf_wakeup_lock_status(sdiodev->rwnx_hw)) { ++ printk("%s ws active dont suspend", __func__); ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ ++ if((sdiodev->chipid == PRODUCT_ID_AIC8800D80) || (sdiodev->chipid == PRODUCT_ID_AIC8800D80X2)) { ++ sdio_dbg("autops clear\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x8); ++ if(ret) { ++ sdio_err("sdio clear autops fail\n"); ++ } ++ } ++ ++ return -EBUSY; ++ } ++#endif ++ ++ sdio_dbg("%s exit\n", __func__); ++ ++ return 0; ++} ++ ++static int aicwf_sdio_resume(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ struct rwnx_vif *rwnx_vif, *tmp; ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_AUTO_POWERSAVE) ++ int ret; ++#endif ++ ++ sdio_dbg("%s enter \n", __func__); ++ ++#ifdef CONFIG_TEMP_CONTROL ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++#endif ++ ++//#ifdef CONFIG_GPIO_WAKEUP ++// rwnx_disable_hostwake_irq(); ++//#endif ++ //dev_pm_clear_wake_irq(dev); ++ list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { ++ if (rwnx_vif->ndev) ++ netif_device_attach(rwnx_vif->ndev); ++ } ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ #endif ++ ++#if defined(CONFIG_AUTO_POWERSAVE) && defined(CONFIG_SDIO_PWRCTRL) ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ sdio_dbg("autops clear\n"); ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x8); ++ if(ret) { ++ sdio_err("sdio clear autops fail\n"); ++ } ++ } ++#endif ++ ++// aicwf_sdio_hal_irqhandler(sdiodev->func); ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ sdio_dbg("%s SDIOWIFI_INTR_CONFIG_REG Enable\n", __func__); ++ sdio_claim_host(sdiodev->func); ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ sdio_release_host(sdiodev->func); ++ } ++#endif ++ atomic_set(&sdiodev->is_bus_suspend, 0); ++// smp_mb(); ++ #ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++ rwnx_set_wifi_suspend('0'); ++ #endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ ++ ++ sdio_dbg("%s exit\n", __func__); ++ return 0; ++} ++ ++static const struct sdio_device_id aicwf_sdmmc_ids[] = { ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8801, SDIO_DEVICE_ID_AIC8801)}, ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8800DC, SDIO_DEVICE_ID_AIC8800DC)}, ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8800D80, SDIO_DEVICE_ID_AIC8800D80)}, ++ {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8800D80X2, SDIO_DEVICE_ID_AIC8800D80X2)}, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(sdio, aicwf_sdmmc_ids); ++ ++static const struct dev_pm_ops aicwf_sdio_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(aicwf_sdio_suspend, aicwf_sdio_resume) ++}; ++ ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++static struct sdio_driver aicwf_sdio_driver = { ++ .probe = aicwf_sdio_probe, ++ .remove = aicwf_sdio_remove, ++ .name = AICWF_SDIO_NAME, ++ .id_table = aicwf_sdmmc_ids, ++ .drv = { ++ .pm = &aicwf_sdio_pm_ops, ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_SHUTDOWN_CALLBACK ++ .shutdown = aicwf_sdio_shutdown, ++#endif ++#endif ++ }, ++}; ++#endif ++ ++#if 0 ++#ifdef CONFIG_NANOPI_M4 ++extern int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq); ++extern unsigned aic_max_freqs; ++extern struct mmc_host *aic_host_drv; ++extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); ++extern void mmc_release_host(struct mmc_host *host); ++#endif ++#endif ++ ++#ifdef CONFIG_FDRV_NO_REG_SDIO ++extern struct sdio_func *get_sdio_func(void); ++void aicwf_sdio_probe_(struct sdio_func *func, const struct sdio_device_id *id); ++void aicwf_sdio_remove_(struct sdio_func *func); ++#endif ++ ++void aicwf_sdio_register(void) ++{ ++#if 0 ++#ifdef CONFIG_PLATFORM_NANOPI ++ extern_wifi_set_enable(0); ++ mdelay(200); ++ extern_wifi_set_enable(1); ++ mdelay(200); ++ sdio_reinit(); ++#endif /*CONFIG_PLATFORM_NANOPI*/ ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ rockchip_wifi_power(0); ++ mdelay(200); ++ rockchip_wifi_power(1); ++ mdelay(200); ++ rockchip_wifi_set_carddetect(1); ++#endif /*CONFIG_PLATFORM_ROCKCHIP*/ ++ ++#ifdef CONFIG_INGENIC_T20 ++ jzmmc_manual_detect(1, 1); ++#endif /* CONFIG_INGENIC_T20 */ ++ ++ ++#ifdef CONFIG_NANOPI_M4 ++ if (aic_host_drv->card == NULL) { ++ __mmc_claim_host(aic_host_drv, NULL); ++ printk("aic: >>>mmc_rescan_try_freq\n"); ++ mmc_rescan_try_freq(aic_host_drv, aic_max_freqs); ++ mmc_release_host(aic_host_drv); ++ } ++#endif ++#endif ++ ++ ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ if (sdio_register_driver(&aicwf_sdio_driver)) { ++ ++ } else { ++ //may add mmc_rescan here ++ } ++#else ++ aicwf_sdio_probe_(get_sdio_func(), NULL); ++#endif ++} ++ ++void aicwf_sdio_exit(void) ++{ ++ if (g_rwnx_plat && g_rwnx_plat->enabled){ ++#ifdef CONFIG_TEMP_CONTROL ++ if (timer_pending(&g_rwnx_plat->sdiodev->tp_ctrl_timer)) { ++ AICWFDBG(LOGINFO, "%s del tp_ctrl_timer\n", __func__); ++ del_timer_sync(&g_rwnx_plat->sdiodev->tp_ctrl_timer); ++ } ++ cancel_work_sync(&g_rwnx_plat->sdiodev->tp_ctrl_work); ++ ++ if (timer_pending(&g_rwnx_plat->sdiodev->netif_timer)) { ++ AICWFDBG(LOGINFO, "%s del netif_timer\n", __func__); ++ del_timer_sync(&g_rwnx_plat->sdiodev->netif_timer); ++ } ++ cancel_work_sync(&g_rwnx_plat->sdiodev->netif_work); ++#endif ++ rwnx_platform_deinit(g_rwnx_plat->sdiodev->rwnx_hw); ++ }else{ ++ AICWFDBG(LOGERROR, "%s g_rwnx_plat is not ready \r\n", __func__); ++ } ++ ++ udelay(500); ++ ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ sdio_unregister_driver(&aicwf_sdio_driver); ++#else ++ aicwf_sdio_remove_(get_sdio_func()); ++#endif ++ ++#if 0 ++#ifdef CONFIG_PLATFORM_AMLOGIC ++ extern_wifi_set_enable(0); ++#endif /*CONFIG_PLATFORM_AMLOGIC*/ ++#endif ++ ++#if 0 ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ rockchip_wifi_set_carddetect(0); ++ mdelay(200); ++ rockchip_wifi_power(0); ++ mdelay(200); ++#endif /*CONFIG_PLATFORM_ROCKCHIP*/ ++#endif ++ ++ if(g_rwnx_plat){ ++ kfree(g_rwnx_plat); ++ } ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++int aicwf_sdio_wakeup(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ int read_retry; ++ int write_retry = 1; ++ int wakeup_reg_val = 0; ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ wakeup_reg_val = 1; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ wakeup_reg_val = 0x11; ++ } ++ ++ if (sdiodev->state == SDIO_SLEEP_ST) { ++ AICWFDBG(LOGSDPWRC, "%s w\n", __func__); ++ ++ //rwnx_pm_stay_awake(sdiodev); ++ ++ while (write_retry) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, wakeup_reg_val); ++ if (ret) { ++ txrx_err("sdio wakeup fail\n"); ++ ret = -1; ++ } else { ++ read_retry = 50; ++ while (read_retry) { ++ u8 val; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.wakeup_reg, &val); ++ if (ret < 0) ++ txrx_err("sdio wakeup read fail\n"); ++ else if ((val & 0x1) == 0) { ++ break; ++ } ++ read_retry--; ++ udelay(200); ++ } ++ if (read_retry != 0) ++ break; ++ } ++ sdio_dbg("write retry: %d \n", write_retry); ++ write_retry--; ++ udelay(100); ++ } ++ ++ sdiodev->state = SDIO_ACTIVE_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ return ret; ++} ++ ++int aicwf_sdio_sleep_allow(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = sdiodev->bus_if; ++ struct rwnx_hw *rwnx_hw = sdiodev->rwnx_hw; ++ u8 read_retry; ++ u8 val; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, 0x10); ++ if (ret) { ++ sdio_err("Write sleep fail!\n"); ++ } ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ return ret; ++ } ++ ++ sdio_info("sleep: %d, %d\n", sdiodev->state, scanning); ++ if (sdiodev->state == SDIO_ACTIVE_ST && !scanning && !rwnx_hw->is_p2p_alive \ ++ && !rwnx_hw->is_p2p_connected && (int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) <= 0) \ ++ && (sdiodev->tx_priv->cmd_txstate == false) && (int)(atomic_read(&sdiodev->rx_priv->rx_cnt) == 0)) { ++ AICWFDBG(LOGSDPWRC, "%s s\n", __func__); ++ if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ if (aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x02) < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ if (aicwf_sdio_func2_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x2) < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++ read_retry = 100; ++ while (read_retry) { ++ val = 0; ++ if (aicwf_sdio_func2_readb(sdiodev, sdiodev->sdio_reg.wakeup_reg, &val) < 0){ ++ sdio_err("reg %d read fail\n", sdiodev->sdio_reg.wakeup_reg); ++ }else if ((val & 0x2) == 0) { ++ break; ++ } else { ++ sdio_err("val:%d\n", val); ++ } ++ read_retry--; ++ if(read_retry < 90) ++ printk("warning: read cnt %d\n", read_retry); ++ udelay(500); ++ } ++ } ++ sdiodev->state = SDIO_SLEEP_ST; ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ //rwnx_pm_relax(sdiodev); ++ } else { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ ++ return ret; ++} ++ ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target) ++{ ++ int ret = 0; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ return -1; ++ } ++ ++ down(&sdiodev->pwrctl_wakeup_sema); ++ ++ if (sdiodev->state == target) { ++ if (target == SDIO_ACTIVE_ST) { ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ } ++ up(&sdiodev->pwrctl_wakeup_sema); ++ return ret; ++ } ++ ++ switch (target) { ++ case SDIO_ACTIVE_ST: ++ aicwf_sdio_wakeup(sdiodev); ++ break; ++ case SDIO_SLEEP_ST: ++ aicwf_sdio_sleep_allow(sdiodev); ++ break; ++ } ++ ++ up(&sdiodev->pwrctl_wakeup_sema); ++ return ret; ++} ++#endif ++ ++#if 0 ++int align_param = 16; ++module_param(align_param, int, 0660); ++#endif ++ ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++{ ++ int ret = 0; ++ u8 *frame; ++ u32 len = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++#if 0 ++ int align = 0; ++#endif ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("tx bus is down!\n"); ++ return -EINVAL; ++ } ++ ++#if 0 ++ len = pkt->len; ++ len = (len + SDIOWIFI_FUNC_BLOCKSIZE - 1) / SDIOWIFI_FUNC_BLOCKSIZE * SDIOWIFI_FUNC_BLOCKSIZE; ++ ++ frame = (u8*)kmalloc(sizeof(u8) * len + align_param, GFP_ATOMIC); ++ align = ((unsigned long)(frame)) & (align_param - 1); ++ memcpy(frame + (align_param - align), (u8 *) (pkt->data), len); ++ ++ ret = aicwf_sdio_send_pkt(sdiodev, frame + (align_param - align), len); ++ if (ret) ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", ret); ++ ++ kfree(frame); ++#endif ++#if 1 ++ frame = (u8 *) (pkt->data); ++ len = pkt->len; ++ len = (len + SDIOWIFI_FUNC_BLOCKSIZE - 1) / SDIOWIFI_FUNC_BLOCKSIZE * SDIOWIFI_FUNC_BLOCKSIZE; ++ ++ ret = aicwf_sdio_send_pkt(sdiodev, pkt->data, len); ++ if (ret) ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", ret); ++#endif ++ return ret; ++} ++ ++#ifdef CONFIG_SDIO_ADMA ++int aicwf_sdio_txscatterpkt(struct aicwf_tx_priv *tx_priv) ++{ ++ int ret = 0; ++ u8 *frame; ++ u32 len = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(tx_priv->sdiodev->dev); ++ struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; ++ int nents = tx_priv->aggr_segcnt; ++ int i=0; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("tx bus is down!\n"); ++ return -EINVAL; ++ } ++ ++ //AICWFDBG(LOGTRACE,"%s aggr_segcnt %d len %d \n",__func__,tx_priv->aggr_segcnt, tx_priv->len); ++ sdio_claim_host(sdiodev->func); ++ ret = sdio_write_sg(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, &(tx_priv->sg_list[0]), tx_priv->aggr_segcnt, tx_priv->len);//&(tx_priv->sg_list[0]) ++ //sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, tx_priv->sg_list[0].buf, tx_priv->sg_list[0].len); ++ /*for(i=0;i<1;i++){ ++ sdio_writesb(sdiodev->func, sdiodev->sdio_reg.wr_fifo_addr, tx_priv->sg_list[i].buf, tx_priv->sg_list[i].len); ++ }*/ ++ sdio_release_host(sdiodev->func); ++ ++ return ret; ++ ++} ++ ++void aicwf_adma_add(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt) ++{ ++ u8 adj_len = 0; ++ u8 *sdio_header = NULL; ++ u32 sdio_len = 0; ++ u32 curr_len = 0; ++ unsigned int align_len = 0; ++ u8 *start_ptr = NULL; ++ ++ adj_len = ALIGN4_ADJ_LEN((uint32_t)pkt->data); ++ start_ptr = skb_push(pkt,adj_len); //skb_push(pkt,adj_len) ++ //ASSERT((adj_len==0)||(adj_len==2)); // mgmt-pkt or data-pkt ++ //ASSERT((((uint32_t)start_ptr)&3) == 0); // start_ptr addr word align ++ if(!((adj_len==0)||(adj_len==2))) ++ AICWFDBG(LOGTRACE,"adj_len false %u \n",adj_len); ++ ++ if((((uint32_t)start_ptr)&3) != 0) ++ AICWFDBG(LOGTRACE,"start_ptr %x \n",(((uint32_t)start_ptr)&3)); ++ ++ //AICWFDBG(LOGTRACE,"start adj_len %d aggrcnt %d segcnt %d len %d \n",adj_len,atomic_read(&tx_priv->aggr_count),tx_priv->aggr_segcnt,tx_priv->len); ++ ++ if (adj_len==0) { ++ sdio_len = pkt->len + SDIO_MGMT_FAKE_LEN; ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ //AICWFDBG(LOGTRACE,"pkt_len %d \n",pkt->len); ++ start_ptr = skb_push(pkt, (SDIO_HEADER_LEN+SDIO_MGMT_FAKE_LEN)); ++ //AICWFDBG(LOGTRACE,"push_pkt_len %d \n",pkt->len); ++ sdio_header = start_ptr; ++ ++ sdio_header[0] =((sdio_len) & 0xff); ++ sdio_header[1] =(((sdio_len) >> 8)&0x0f); ++ sdio_header[2] = 0x01; //data ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80) ++ sdio_header[3] = crc8_ponl_107(&sdio_header[0], 3); // crc8 ++ else ++ sdio_header[3] = 0; //reserved ++ ++ // fill 4 byte 0x00, need to fasync with data-pkt. ++ sdio_header[4] = 0; ++ sdio_header[5] = 0; ++ sdio_header[6] = 0; ++ sdio_header[7] = 0; ++ ++ curr_len = sdio_len + SDIO_HEADER_LEN; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj0",pkt->data,((pkt->len>32) ? 32 : pkt->len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ tx_priv->len += curr_len; ++ }else if (adj_len==1) { ++ sdio_len = pkt->len + 3; ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][0] = ((sdio_len) & 0xff); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][1] = (((sdio_len) >> 8)&0x0f); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][2] = 0x01; // data ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][3] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][4] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][5] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][6] = 0; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_dummy[tx_priv->aggr_segcnt]; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = SDIO_HEADER_LEN + 3; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] =NULL; ++ ++ tx_priv->aggr_segcnt++; ++ ++ sdio_header = start_ptr; ++ sdio_header[0] = 0; ++ ++ curr_len = sdio_len - 3; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj1",start_ptr,((curr_len>32) ? 32 : curr_len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ ++ tx_priv->len += curr_len + SDIO_HEADER_LEN + 3; ++ ++ }else if (adj_len==2) { // adj_len==2 ++ sdio_len = pkt->len + SDIO_DATA_FAKE_LEN;//adj_len + ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][0] = ((sdio_len) & 0xff); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][1] = (((sdio_len) >> 8)&0x0f); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][2] = 0x01; // data ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][3] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][4] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][5] = 0; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_dummy[tx_priv->aggr_segcnt]; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = SDIO_HEADER_LEN + SDIO_DATA_FAKE_LEN; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] =NULL; ++ ++ tx_priv->aggr_segcnt++; ++ ++ sdio_header = start_ptr; ++ sdio_header[0] = 0; ++ sdio_header[1] = 0; ++ ++ curr_len = sdio_len - SDIO_DATA_FAKE_LEN; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj2",start_ptr,((curr_len>32) ? 32 : curr_len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ ++ tx_priv->len += curr_len + SDIO_HEADER_LEN + SDIO_DATA_FAKE_LEN; ++ }else if (adj_len==3) { ++ sdio_len = pkt->len + 1; ++ if (sdio_len & (TX_ALIGNMENT - 1)) { ++ align_len = TX_ALIGNMENT - (sdio_len & (TX_ALIGNMENT - 1)); ++ //#ifdef CONFIG_SDIO_ADMA_ADJ ++ //memset(pkt->data + sdio_len,0,align_len); ++ //#endif ++ //skb_put(pkt,align_len); ++ sdio_len += align_len; ++ } ++ ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][0] = ((sdio_len) & 0xff); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][1] = (((sdio_len) >> 8)&0x0f); ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][2] = 0x01; // data ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][3] = 0; ++ sdio_tx_buf_dummy[tx_priv->aggr_segcnt][4] = 0; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_dummy[tx_priv->aggr_segcnt]; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = SDIO_HEADER_LEN + 1; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] =NULL; ++ ++ tx_priv->aggr_segcnt++; ++ ++ sdio_header = start_ptr; ++ sdio_header[0] = 0; ++ sdio_header[1] = 0; ++ sdio_header[2] = 0; ++ ++ curr_len = sdio_len - 1; ++ ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = start_ptr; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = curr_len; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = pkt; ++ ++ //AICWFDBG(LOGTRACE,"curr_len %d \n",curr_len); ++ //rwnx_data_dump("adj3",start_ptr,((curr_len>32) ? 32 : curr_len)); ++ ++ tx_priv->aggr_segcnt++; ++ atomic_inc(&tx_priv->aggr_count); ++ ++ tx_priv->len += curr_len + SDIO_HEADER_LEN + 1; ++ } ++ ++ //AICWFDBG(LOGTRACE,"end aggrcnt %d segcnt %d len %d \n",atomic_read(&tx_priv->aggr_count),tx_priv->aggr_segcnt,tx_priv->len); ++ ++} ++ ++#endif ++ ++static int aicwf_sdio_intr_get_len_bytemode(struct aic_sdio_dev *sdiodev, u8 *byte_len) ++{ ++ int ret = 0; ++ ++ if (!byte_len) ++ return -EBADE; ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ *byte_len = 0; ++ } else { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.bytemode_len_reg, byte_len); ++ sdiodev->rx_priv->data_len = (*byte_len)*4; ++ } ++ ++ return ret; ++} ++ ++static void aicwf_sdio_bus_stop(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwrctl_timer(sdiodev, 0); ++ #endif ++ AICWFDBG(LOGINFO, "%s Enter\n", __func__); ++ ++ bus_if->state = BUS_DOWN_ST; ++ if (sdiodev->tx_priv) { ++ ret = down_interruptible(&sdiodev->tx_priv->txctl_sema); ++ if (ret) ++ AICWFDBG(LOGERROR, "down txctl_sema fail\n"); ++ } ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ #endif ++ ++ if (sdiodev->tx_priv) { ++ if (!ret) ++ up(&sdiodev->tx_priv->txctl_sema); ++ aicwf_frame_queue_flush(&sdiodev->tx_priv->txq); ++ } ++ AICWFDBG(LOGINFO, "%s Exit \n", __func__); ++} ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct rx_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ u32 size = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ struct rx_buff* rxbuff; ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("bus down\n"); ++ return NULL; ++ } ++ ++ size = sdiodev->rx_priv->data_len; ++ rxbuff = aicwf_prealloc_rxbuff_alloc(&sdiodev->rx_priv->rxbuff_lock); ++ if (rxbuff == NULL) { ++ printk("failed to alloc rxbuff\n"); ++ return NULL; ++ } ++ rxbuff->len = 0; ++ rxbuff->start = rxbuff->data; ++ rxbuff->read = rxbuff->start; ++ rxbuff->end = rxbuff->data + size; ++ ++ ret = aicwf_sdio_recv_pkt(sdiodev, rxbuff, size); ++ if (ret) { ++ printk("%s %d, sdio recv pkt fail\n", __func__, __LINE__); ++ aicwf_prealloc_rxbuff_free(rxbuff, &sdiodev->rx_priv->rxbuff_lock); ++ return NULL; ++ } ++ ++ return rxbuff; ++} ++#else ++struct sk_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev) ++{ ++ int ret = 0; ++ u32 size = 0; ++ struct sk_buff *skb = NULL; ++ struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_dbg("bus down\n"); ++ return NULL; ++ } ++ ++ size = sdiodev->rx_priv->data_len; ++ skb = __dev_alloc_skb(size, GFP_KERNEL); ++ if (!skb) { ++ return NULL; ++ } ++ ++ ret = aicwf_sdio_recv_pkt(sdiodev, skb, size); ++ if (ret) { ++ dev_kfree_skb(skb); ++ skb = NULL; ++ } ++ ++ return skb; ++} ++#endif ++ ++static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++ u16 len; ++ u8 *payload = sdiodev->tx_priv->cmd_buf; ++ u16 payload_len = sdiodev->tx_priv->cmd_len; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ int adjust_len = 0; ++ int buffer_cnt = 0; ++ u8 retry = 0; ++ ++ len = payload_len; ++ if ((len % TX_ALIGNMENT) != 0) { ++ adjust_len = roundup(len, TX_ALIGNMENT); ++ memcpy(payload+payload_len, adjust_str, (adjust_len - len)); ++ payload_len += (adjust_len - len); ++ } ++ len = payload_len; ++ ++ //link tail is necessary ++ if ((len % SDIOWIFI_FUNC_BLOCKSIZE) != 0) { ++ memset(payload+payload_len, 0, TAIL_LEN); ++ payload_len += TAIL_LEN; ++ len = (payload_len/SDIOWIFI_FUNC_BLOCKSIZE + 1) * SDIOWIFI_FUNC_BLOCKSIZE; ++ } else ++ len = payload_len; ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ buffer_cnt = aicwf_sdio_flow_ctrl_msg(sdiodev); ++ while ((buffer_cnt <= 0 || (buffer_cnt > 0 && len > (buffer_cnt * BUFFER_SIZE))) && retry < 10) { ++ retry++; ++ buffer_cnt = aicwf_sdio_flow_ctrl_msg(sdiodev); ++ printk("buffer_cnt = %d\n", buffer_cnt); ++ } ++ } ++ down(&sdiodev->tx_priv->cmd_txsema); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if (buffer_cnt > 0 && len < (buffer_cnt * BUFFER_SIZE)) { ++ err = aicwf_sdio_send_pkt(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ }else if(sdiodev->chipid == PRODUCT_ID_AIC8800DC){ ++ err = aicwf_sdio_send_pkt(sdiodev, payload, len); ++ if (err) { ++ sdio_err("aicwf_sdio_send_pkt fail%d\n", err); ++ } ++ } else { ++ sdio_err("tx msg fc retry fail:%d, %d\n", buffer_cnt, len); ++ up(&sdiodev->tx_priv->cmd_txsema); ++ return -1; ++ } ++ ++ sdiodev->tx_priv->cmd_txstate = false; ++ if (!err) ++ sdiodev->tx_priv->cmd_tx_succ = true; ++ else ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ return err; ++ ++} ++ ++static void aicwf_sdio_tx_process(struct aic_sdio_dev *sdiodev) ++{ ++ int err = 0; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ unsigned long flags; ++#endif ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("Bus is down\n"); ++ return; ++ } ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); ++ #endif ++ ++ //config ++ sdio_info("send cmd\n"); ++ if (sdiodev->tx_priv->cmd_txstate) { ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txctl down bus->txctl_sema fail\n"); ++ return; ++ } ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ txrx_err("txctl up bus->txctl_sema fail\n"); ++ return; ++ } ++ err = aicwf_sdio_tx_msg(sdiodev); ++ up(&sdiodev->tx_priv->txctl_sema); ++ if (waitqueue_active(&sdiodev->tx_priv->cmd_txdone_wait)) ++ wake_up(&sdiodev->tx_priv->cmd_txdone_wait); ++ } ++ ++ //data ++ sdio_info("send data\n"); ++ if (down_interruptible(&sdiodev->tx_priv->txctl_sema)) { ++ txrx_err("txdata down bus->txctl_sema\n"); ++ return; ++ } ++ ++ if (sdiodev->state != SDIO_ACTIVE_ST) { ++ txrx_err("sdio state err\n"); ++ up(&sdiodev->tx_priv->txctl_sema); ++ return; ++ } ++ ++ if (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)){ ++ sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ } ++ while (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) { ++ if(sdiodev->bus_if->state == BUS_DOWN_ST) { ++ break; ++ } ++#ifdef CONFIG_TEMP_CONTROL ++ if (sdiodev->on_off) ++ aicwf_temp_ctrl(sdiodev); ++#endif ++ ++ if (sdiodev->tx_priv->fw_avail_bufcnt <= DATA_FLOW_CTRL_THRESH) { ++ if (sdiodev->tx_priv->cmd_txstate) ++ break; ++ sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); ++ } else { ++ if (sdiodev->tx_priv->cmd_txstate) { ++ aicwf_sdio_send(sdiodev->tx_priv, 1); ++ break; ++ } else { ++ aicwf_sdio_send(sdiodev->tx_priv, 0); ++ } ++ } ++ } ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) < tx_fc_low_water) { ++ //printk("sdiodev->tx_priv->tx_pktcnt < tx_fc_low_water:%d %d\r\n", ++ // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_low_water); ++ if (sdiodev->flowctrl) { ++ sdiodev->flowctrl = 0; ++ aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, false); ++ } ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++#endif ++ ++ up(&sdiodev->tx_priv->txctl_sema); ++} ++ ++static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) ++{ ++ uint prio; ++ int ret = -EBADE; ++ struct rwnx_txhdr *txhdr = NULL; ++ int headroom = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ unsigned long flags; ++#endif ++ ++ if (bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus_if stopped\n"); ++ txhdr = (struct rwnx_txhdr *)pkt->data; ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ consume_skb(pkt); ++ return -1; ++ } ++ ++ prio = (pkt->priority & 0x7); ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ if (!aicwf_frame_enq(sdiodev->dev, &sdiodev->tx_priv->txq, pkt, prio)) { ++ txhdr = (struct rwnx_txhdr *)pkt->data; ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ consume_skb(pkt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return -ENOSR; ++ goto flowctrl; ++ } else { ++ ret = 0; ++ } ++ ++ atomic_inc(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ complete(&bus_if->bustx_trgg); ++ ++ flowctrl: ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) >= tx_fc_high_water) { ++ //printk("sdiodev->tx_priv->tx_pktcnt >= tx_fc_high_water:%d %d\r\n", ++ // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_high_water); ++ if (!sdiodev->flowctrl) { ++ sdiodev->flowctrl = 1; ++ aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, true); ++ } ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++#endif ++ ++ return ret; ++} ++ ++static int aicwf_sdio_bus_txmsg(struct device *dev, u8 *msg, uint msglen) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ ++ down(&sdiodev->tx_priv->cmd_txsema); ++ sdiodev->tx_priv->cmd_txstate = true; ++ sdiodev->tx_priv->cmd_tx_succ = false; ++ sdiodev->tx_priv->cmd_buf = msg; ++ sdiodev->tx_priv->cmd_len = msglen; ++ up(&sdiodev->tx_priv->cmd_txsema); ++ ++ if (bus_if->state != BUS_UP_ST) { ++ sdio_err("bus has stop\n"); ++ return -1; ++ } ++ ++ complete(&bus_if->bustx_trgg); ++#if 0 ++ if (sdiodev->tx_priv->cmd_txstate) { ++ int timeout = msecs_to_jiffies(CMD_TX_TIMEOUT); ++ ret = wait_event_interruptible_timeout(sdiodev->tx_priv->cmd_txdone_wait, \ ++ !(sdiodev->tx_priv->cmd_txstate), timeout); ++ } ++ ++ if (!sdiodev->tx_priv->cmd_txstate && sdiodev->tx_priv->cmd_tx_succ) { ++ ret = 0; ++ } else { ++ sdio_err("send faild:%d, %d,%x\n", sdiodev->tx_priv->cmd_txstate, sdiodev->tx_priv->cmd_tx_succ, ret); ++ ret = -EIO; ++ } ++#endif ++ return 0; ++} ++ ++ ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv, u8 txnow) ++{ ++ struct sk_buff *pkt; ++ struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; ++ u32 aggr_len = 0; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ unsigned long flags; ++#endif ++ ++#ifdef CONFIG_SDIO_ADMA ++ aggr_len = tx_priv->len; ++#else ++ aggr_len = (tx_priv->tail - tx_priv->head); ++#endif ++ ++ if (((atomic_read(&tx_priv->aggr_count) == 0) && (aggr_len != 0)) ++ || ((atomic_read(&tx_priv->aggr_count) != 0) && (aggr_len == 0))) { ++ if (aggr_len > 0){ ++#ifdef CONFIG_SDIO_ADMA ++ printk("len %d seg_cnt %d aggr_cnt %d avail_cnt %d \n",aggr_len,tx_priv->aggr_segcnt,atomic_read(&tx_priv->aggr_count),tx_priv->fw_avail_bufcnt ); ++#endif ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++#ifdef CONFIG_SDIO_ADMA ++ printk("set len %d seg_cnt %d aggr_cnt %d avail_cnt %d \n",aggr_len,tx_priv->aggr_segcnt,atomic_read(&tx_priv->aggr_count),tx_priv->fw_avail_bufcnt ); ++#endif ++ } ++ ++ return 0; ++ } ++ ++ if (atomic_read(&tx_priv->aggr_count) == (tx_priv->fw_avail_bufcnt - DATA_FLOW_CTRL_THRESH)) { ++ if (atomic_read(&tx_priv->aggr_count) > 0) { ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); //send and check the next pkt; ++ } ++ return 0; ++ } else { ++ spin_lock_bh(&sdiodev->tx_priv->txqlock); ++ pkt = aicwf_frame_dequeue(&sdiodev->tx_priv->txq); ++ if (pkt == NULL) { ++ sdio_err("txq no pkt\n"); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ return 0; ++ } ++ //atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ spin_unlock_bh(&sdiodev->tx_priv->txqlock); ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); ++ if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) < tx_fc_low_water) { ++ //printk("sdiodev->tx_priv->tx_pktcnt < tx_fc_low_water:%d %d\r\n", ++ // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_low_water); ++ if (sdiodev->flowctrl) { ++ sdiodev->flowctrl = 0; ++ aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, false); ++ } ++ } ++ spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); ++#endif ++ ++#ifndef CONFIG_SDIO_ADMA ++ if (tx_priv == NULL || tx_priv->tail == NULL || pkt == NULL) ++ txrx_err("null error\n"); ++#endif ++ if (aicwf_sdio_aggr(tx_priv, pkt)) { ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++ sdio_err("add aggr pkts failed!\n"); ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ return 0; ++ } ++ ++ //when aggr finish or there is cmd to send, just send this aggr pkt to fw ++ if ((int)atomic_read(&sdiodev->tx_priv->tx_pktcnt) == 1 || txnow || (atomic_read(&tx_priv->aggr_count) == (tx_priv->fw_avail_bufcnt - DATA_FLOW_CTRL_THRESH))) { ++ tx_priv->fw_avail_bufcnt -= atomic_read(&tx_priv->aggr_count); ++ aicwf_sdio_aggr_send(tx_priv); ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ return 0; ++ } else { ++ atomic_dec(&sdiodev->tx_priv->tx_pktcnt); ++ return 0; ++ } ++ } ++} ++ ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt) ++{ ++#ifdef CONFIG_SDIO_ADMA ++ u8 adj_len = 0; ++ struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; ++ u8 *sdio_header = NULL; ++ u32 sdio_len = 0; ++ u32 curr_len = 0; ++ int align_len = 0; ++ int headroom; ++ u32 pkt_len = 0; ++ struct txdesc_api tmp_txdesc; ++ struct sk_buff *tmp_skb; ++ ++ //AICWFDBG(LOGTRACE,"%s \n",__func__); ++ //pkt (txhdr + data),aggr only need txhdr->sw_hdr->desc and data ++ memcpy(&tmp_txdesc, (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ ++ if(txhdr->sw_hdr->need_cfm){ ++ tmp_skb = skb_copy(pkt,GFP_ATOMIC);//save pkt when cfm get,then release,send skb is copy ++ if(!tmp_skb){ ++ AICWFDBG(LOGERROR,"skb copy fail"); ++ return -ENOMEM; ++ } ++ //AICWFDBG(LOGTRACE,"tmp_len %d pkt_len %d \n",tmp_skb->len,pkt->len); ++ ++ skb_pull(tmp_skb, txhdr->sw_hdr->headroom); ++ ++ //AICWFDBG(LOGTRACE,"pull_tmp_len %d \n",tmp_skb->len); ++ ++ skb_push(tmp_skb,sizeof(struct txdesc_api));//skb header is enough ++ ++ //AICWFDBG(LOGTRACE,"push_tmp_len %d \n",tmp_skb->len); ++ ++ memcpy(tmp_skb->data, (u8 *)(long)&tmp_txdesc,sizeof(struct txdesc_api)); ++ AICWFDBG(LOGTRACE,"need cfm len %d \n",tmp_skb->len); ++ ++ //printk("cfm alloc %p \n",tmp_skb); ++ //printk("delay free %p \n",pkt); ++ aicwf_adma_add(tx_priv, tmp_skb); ++ tx_priv->copyd[tx_priv->aggr_segcnt -1] = true; ++ }else{ ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ ++ //AICWFDBG(LOGTRACE,"pull_pkt_len %d \n",pkt->len); ++ ++ skb_push(pkt,sizeof(struct txdesc_api));//skb header is enough ++ ++ //AICWFDBG(LOGTRACE,"push_pkt_len %d \n",pkt->len); ++ ++ memcpy(pkt->data, (u8 *)(long)&tmp_txdesc,sizeof(struct txdesc_api)); ++ ++ //rwnx_data_dump("data",pkt->data,((pkt->len>64) ? 64 : pkt->len)); ++ ++ //printk("alloc %p \n",pkt); ++ ++ aicwf_adma_add(tx_priv, pkt); ++ tx_priv->copyd[tx_priv->aggr_segcnt -1] = false; ++ } ++ ++#else ++ ++ struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; ++ u8 *start_ptr = tx_priv->tail; ++ u8 sdio_header[4]; ++ u8 adjust_str[4] = {0, 0, 0, 0}; ++ u32 curr_len = 0; ++ int allign_len = 0; ++ int headroom; ++ ++ sdio_header[0] = ((pkt->len - txhdr->sw_hdr->headroom + sizeof(struct txdesc_api)) & 0xff); ++ sdio_header[1] = (((pkt->len - txhdr->sw_hdr->headroom + sizeof(struct txdesc_api)) >> 8)&0x0f); ++ sdio_header[2] = 0x01; //data ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ sdio_header[3] = 0; //reserved ++ else if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ sdio_header[3] = crc8_ponl_107(&sdio_header[0], 3); // crc8 ++ ++ memcpy(tx_priv->tail, (u8 *)&sdio_header, sizeof(sdio_header)); ++ tx_priv->tail += sizeof(sdio_header); ++ //payload ++ memcpy(tx_priv->tail, (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ tx_priv->tail += sizeof(struct txdesc_api); //hostdesc ++ memcpy(tx_priv->tail, (u8 *)((u8 *)txhdr + txhdr->sw_hdr->headroom), pkt->len-txhdr->sw_hdr->headroom); ++ tx_priv->tail += (pkt->len - txhdr->sw_hdr->headroom); ++ ++ //word alignment ++ curr_len = tx_priv->tail - tx_priv->head; ++ if (curr_len & (TX_ALIGNMENT - 1)) { ++ allign_len = roundup(curr_len, TX_ALIGNMENT)-curr_len; ++ memcpy(tx_priv->tail, adjust_str, allign_len); ++ tx_priv->tail += allign_len; ++ } ++ ++ if (tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8801 || tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ tx_priv->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ start_ptr[0] = ((tx_priv->tail - start_ptr - 4) & 0xff); ++ start_ptr[1] = (((tx_priv->tail - start_ptr - 4)>>8) & 0x0f); ++ } ++ tx_priv->aggr_buf->dev = pkt->dev; ++ ++ if (!txhdr->sw_hdr->need_cfm) { ++ headroom = txhdr->sw_hdr->headroom; ++ kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ skb_pull(pkt, headroom); ++ consume_skb(pkt); ++ } ++ ++ atomic_inc(&tx_priv->aggr_count); ++#endif /* CONFIG_SDIO_ADMA */ ++ ++ return 0; ++} ++ ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv) ++{ ++#ifdef CONFIG_SDIO_ADMA ++ int ret = 0; ++ int i=0; ++ int nents = tx_priv->aggr_segcnt; ++ //struct sk_buff *scatter_buf; ++ ++ if(tx_priv->len & (TXPKT_BLOCKSIZE-1)) ++ { ++ uint16_t alen = TXPKT_BLOCKSIZE-(tx_priv->len & (TXPKT_BLOCKSIZE-1)); ++ ++ memset(sdio_tx_buf_fill, 0,32); ++ tx_priv->sg_list[tx_priv->aggr_segcnt].buf = sdio_tx_buf_fill; ++ tx_priv->sg_list[tx_priv->aggr_segcnt].len = alen; ++ tx_priv->free_buf[tx_priv->aggr_segcnt] = NULL; ++ tx_priv->aggr_segcnt += 1; ++ tx_priv->len += alen; ++ } ++ ++ //AICWFDBG(LOGTRACE,"nents %d \n",tx_priv->aggr_segcnt); ++ /*for(i=0;iaggr_segcnt;i++){ ++ if(tx_priv->sg_list[i].buf != NULL){ ++ rwnx_data_dump("send",tx_priv->sg_list[i].buf,((tx_priv->sg_list[i].len>64) ? 64 : tx_priv->sg_list[i].len)); ++ } ++ }*/ ++ ++ ret = aicwf_sdio_txscatterpkt(tx_priv); ++ if (ret < 0) { ++ sdio_err("fail to send scatter pkt %d !\n",ret); ++ } ++ ++#else ++ ++ struct sk_buff *tx_buf = tx_priv->aggr_buf; ++ int ret = 0; ++ int curr_len = 0; ++ ++ //link tail is necessary ++ curr_len = tx_priv->tail - tx_priv->head; ++ if ((curr_len % TXPKT_BLOCKSIZE) != 0) { ++ memset(tx_priv->tail, 0, TAIL_LEN); ++ tx_priv->tail += TAIL_LEN; ++ } ++ ++ tx_buf->len = tx_priv->tail - tx_priv->head; ++ ret = aicwf_sdio_txpkt(tx_priv->sdiodev, tx_buf); ++ if (ret < 0) { ++ sdio_err("fail to send aggr pkt!\n"); ++ } ++#endif/* CONFIG_SDIO_ADMA */ ++ ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++} ++ ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv) ++{ ++#ifdef CONFIG_SDIO_ADMA ++ struct sk_buff *scatter_buf; ++ int i = 0; ++ int nents = tx_priv->aggr_segcnt; ++ ++ for(i=0;ifree_buf[i]; ++ if(scatter_buf != NULL){ ++ //printk("free %p \n",scatter_buf); ++ if(tx_priv->copyd[i]){ ++ kfree_skb(scatter_buf); ++ tx_priv->copyd[i] = false; ++ } ++ else ++ consume_skb(scatter_buf); ++ } ++ } ++ ++ tx_priv->len = 0; ++ tx_priv->aggr_segcnt = 0; ++ atomic_set(&tx_priv->aggr_count, 0); ++ AICWFDBG(LOGTRACE,"reset len %d seg_cnt %d aggr_cnt %d \n",tx_priv->len,tx_priv->aggr_segcnt,atomic_read(&tx_priv->aggr_count)); ++#else ++ ++ struct sk_buff *aggr_buf = tx_priv->aggr_buf; ++ ++ tx_priv->tail = tx_priv->head; ++ aggr_buf->len = 0; ++ atomic_set(&tx_priv->aggr_count, 0); ++#endif/* CONFIG_SDIO_ADMA */ ++} ++ ++extern void set_irq_handler(void *fn); ++ ++static int aicwf_sdio_bus_start(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ ++ sdio_claim_host(sdiodev->func); ++#ifndef CONFIG_FDRV_NO_REG_SDIO ++ sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); ++#else ++ set_irq_handler(aicwf_sdio_hal_irqhandler); ++#endif ++ if(sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdio_f0_writeb(sdiodev->func, 0x07, 0x04, &ret); ++ if (ret) { ++ sdio_err("set func0 int en fail %d\n", ret); ++ } ++ } ++ sdio_release_host(sdiodev->func); ++ ++ ++ //enable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x07); ++ if (ret != 0) ++ sdio_err("intr register failed:%d\n", ret); ++ ++ bus_if->state = BUS_UP_ST; ++ ++ return ret; ++} ++ ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) ++#include "uapi/linux/sched/types.h" ++#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) ++#include "linux/sched/types.h" ++#else ++#include "linux/sched/rt.h" ++#endif ++ ++int bustx_thread_prio = 1; ++module_param_named(bustx_thread_prio, bustx_thread_prio, int, 0644); ++//module_param(bustx_thread_prio, int, 0); ++int busrx_thread_prio = 1; ++module_param_named(busrx_thread_prio, busrx_thread_prio, int, 0644); ++//module_param(busrx_thread_prio, int, 0); ++#endif ++ ++ ++static inline void aic_thread_wait_stop(void) ++{ ++#if 1// PLATFORM_LINUX ++ #if 0 ++ while (!kthread_should_stop()){ ++ AICWFDBG(LOGINFO, "%s waiting for thread_stop notify \r\n", __func__); ++ msleep(100); ++ } ++ #else ++ set_current_state(TASK_INTERRUPTIBLE); ++ while (!kthread_should_stop()) { ++ AICWFDBG(LOGINFO, "%s waiting for thread_stop notify \r\n", __func__); ++ schedule(); ++ set_current_state(TASK_INTERRUPTIBLE); ++ } ++ __set_current_state(TASK_RUNNING); ++ #endif ++#endif ++} ++ ++#ifdef CONFIG_OOB ++int rx_thread_wait_to = 1000; ++module_param_named(rx_thread_wait_to, rx_thread_wait_to, int, 0644); ++ ++//new oob feature ++int sdio_busirq_thread(void *data){ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++#if 0 ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ int set_cpu_ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s the cpu is:%d\n", __func__, current->cpu); ++ set_cpu_ret = set_cpus_allowed_ptr(current, cpumask_of(0)); ++ AICWFDBG(LOGINFO, "%s set_cpu_ret is:%d\n", __func__, set_cpu_ret); ++ AICWFDBG(LOGINFO, "%s change cpu to:%d\n", __func__, current->cpu); ++#endif ++#endif ++ ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (busrx_thread_prio > 0) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) ++ sched_set_fifo_low(current); ++#else ++ struct sched_param param; ++ param.sched_priority = (busrx_thread_prio - 1 < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++#endif ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++ ++ while (1) { ++#if 0 ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busirq thread stop\n"); ++ break; ++ } ++#endif ++ if(!wait_for_completion_timeout(&bus_if->busirq_trgg, msecs_to_jiffies(rx_thread_wait_to))){ ++ AICWFDBG(LOGRXPOLL, "%s wait for completion timout \r\n", __func__); ++ } ++ ++ if (bus_if->state == BUS_DOWN_ST){ ++ AICWFDBG(LOGERROR, "%s bus down thread exit \r\n", __func__); ++ break; ++ } ++ //continue; ++#if 1 ++#ifdef CONFIG_SDIO_PWRCTRL ++ while(atomic_read(&bus_if->bus_priv.sdio->is_bus_suspend) == 1){ ++ AICWFDBG(LOGDEBUG, "%s waiting for sdio bus resume \r\n", __func__); ++ msleep(100); ++ } ++ aicwf_sdio_pwr_stctl(bus_if->bus_priv.sdio, SDIO_ACTIVE_ST); ++#endif//CONFIG_SDIO_PWRCTRL ++#endif ++ aicwf_sdio_hal_irqhandler(bus_if->bus_priv.sdio->func); ++ } ++ ++ aic_thread_wait_stop(); ++ ++ return 0; ++} ++ ++#endif//CONFIG_OOB ++ ++#if 0 ++#include ++#endif ++int sdio_bustx_thread(void *data) ++{ ++ struct aicwf_bus *bus = (struct aicwf_bus *) data; ++ struct aic_sdio_dev *sdiodev = bus->bus_priv.sdio; ++#if 0 ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ int set_cpu_ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s the cpu is:%d\n", __func__, current->cpu); ++ set_cpu_ret = set_cpus_allowed_ptr(current, cpumask_of(1)); ++ AICWFDBG(LOGINFO, "%s set_cpu_ret is:%d\n", __func__, set_cpu_ret); ++ AICWFDBG(LOGINFO, "%s change cpu to:%d\n", __func__, current->cpu); ++#endif ++#endif ++ ++#if 0 ++ struct cpumask cpumask; ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(1, &cpumask); ++ cpumask_set_cpu(2, &cpumask); ++ cpumask_set_cpu(3, &cpumask); ++ sched_setaffinity(0, &cpumask);//need to add EXPORT_SYMBOL_GPL(sched_setaffinity) in kernel/sched/core.c ++#endif ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (bustx_thread_prio > 0) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) ++ sched_set_fifo_low(current); ++#else ++ struct sched_param param; ++ param.sched_priority = (bustx_thread_prio < MAX_RT_PRIO)?bustx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++#endif ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++ while (1) { ++ #if 0 ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio bustx thread stop\n"); ++ break; ++ } ++ #endif ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) ++ break; ++ //continue; ++ ++ rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_tx); ++ if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) > 0) || (sdiodev->tx_priv->cmd_txstate == true)){ ++ aicwf_sdio_tx_process(sdiodev); ++ } ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_tx); ++ } ++ } ++ ++ aic_thread_wait_stop(); ++ AICWFDBG(LOGINFO, "%s Exit\r\n", __func__); ++ return 0; ++} ++ ++#if 0//old oob feature ++int sdio_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++#if 0 ++ struct cpumask cpumask; ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(1, &cpumask); ++ cpumask_set_cpu(2, &cpumask); ++ cpumask_set_cpu(3, &cpumask); ++ sched_setaffinity(0, &cpumask); ++#endif ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (busrx_thread_prio > 0) { ++ struct sched_param param; ++ param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++while (1) { ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busrx thread stop\n"); ++ break; ++ } ++#ifndef CONFIG_OOB ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++#else ++ if(!wait_for_completion_timeout(&bus_if->busrx_trgg, msecs_to_jiffies(rx_thread_wait_to))){ ++ AICWFDBG(LOGDEBUG, "%s wait for completion timout \r\n", __func__); ++ } ++#endif ++ if (bus_if->state == BUS_DOWN_ST) ++ continue; ++#ifdef CONFIG_OOB ++#ifdef CONFIG_SDIO_PWRCTRL ++ while(atomic_read(&bus_if->bus_priv.sdio->is_bus_suspend) == 1){ ++ AICWFDBG(LOGDEBUG, "%s waiting for sdio bus resume \r\n", __func__); ++ msleep(100); ++ } ++ aicwf_sdio_pwr_stctl(bus_if->bus_priv.sdio, SDIO_ACTIVE_ST); ++#endif//CONFIG_SDIO_PWRCTRL ++ aicwf_sdio_hal_irqhandler(bus_if->bus_priv.sdio->func); ++#endif//CONFIG_OOB ++ rwnx_wakeup_lock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++ aicwf_process_rxframes(rx_priv); ++ rwnx_wakeup_unlock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++#ifndef CONFIG_OOB ++ } ++#endif ++ } ++ ++ return 0; ++ ++} ++#else//new oob feature ++int sdio_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++ ++ ++#if 0 ++ struct cpumask cpumask; ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(1, &cpumask); ++ cpumask_set_cpu(2, &cpumask); ++ cpumask_set_cpu(3, &cpumask); ++ sched_setaffinity(0, &cpumask); ++#endif ++#if 0 ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ int set_cpu_ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s the cpu is:%d\n", __func__, current->cpu); ++ set_cpu_ret = set_cpus_allowed_ptr(current, cpumask_of(2)); ++ AICWFDBG(LOGINFO, "%s set_cpu_ret is:%d\n", __func__, set_cpu_ret); ++ AICWFDBG(LOGINFO, "%s change cpu to:%d\n", __func__, current->cpu); ++#endif ++#endif ++#ifdef CONFIG_TXRX_THREAD_PRIO ++ if (busrx_thread_prio > 0) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) ++ sched_set_fifo_low(current); ++#else ++ struct sched_param param; ++ param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1); ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++#endif ++ } ++#endif ++ ++ AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy); ++ AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority); ++ AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid); ++ ++ while (1) { ++ #if 0 ++ if (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busrx thread stop\n"); ++ break; ++ } ++ #endif ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ ++ if (bus_if->state == BUS_DOWN_ST) ++ break; ++ //continue; ++ rwnx_wakeup_lock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++ aicwf_process_rxframes(rx_priv); ++ rwnx_wakeup_unlock(rx_priv->sdiodev->rwnx_hw->ws_rx); ++ } ++ } ++ aic_thread_wait_stop(); ++ AICWFDBG(LOGINFO, "%s Exit\r\n", __func__); ++ return 0; ++ ++} ++ ++#endif//old oob feature ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++static int aicwf_sdio_pwrctl_thread(void *data) ++{ ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ sdio_err("sdio pwrctl thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&sdiodev->pwrctrl_trgg)) { ++ //printk("%s working\r\n", __func__); ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) ++ continue; ++ ++ rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_pwrctrl); ++ ++ if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) <= 0) && (sdiodev->tx_priv->cmd_txstate == false) && \ ++ atomic_read(&sdiodev->rx_priv->rx_cnt) == 0) ++ aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); ++ else ++ aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); ++ ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_pwrctrl); ++ } ++ } ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++static void aicwf_sdio_bus_pwrctl(ulong data) ++#else ++static void aicwf_sdio_bus_pwrctl(struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *) data; ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ struct aic_sdio_dev *sdiodev = timer_container_of(sdiodev, t, timer); ++#else ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, timer); ++#endif ++#endif ++ ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus down\n"); ++ return; ++ } ++ ++ if (sdiodev->pwrctl_tsk) { ++ complete(&sdiodev->pwrctrl_trgg); ++ } ++} ++#endif ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++static void aicwf_sdio_enq_rxpkt(struct aic_sdio_dev *sdiodev, struct rx_buff *pkt) ++#else ++static void aicwf_sdio_enq_rxpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt) ++#endif ++{ ++ struct aicwf_rx_priv *rx_priv = sdiodev->rx_priv; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ if (!aicwf_rxbuff_enqueue(sdiodev->dev, &rx_priv->rxq, pkt)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ printk("%s %d, enqueue rxq fail\n", __func__, __LINE__); ++ aicwf_prealloc_rxbuff_free(pkt, &rx_priv->rxbuff_lock); ++ return; ++ } ++ #else ++ if (!aicwf_rxframe_enqueue(sdiodev->dev, &rx_priv->rxq, pkt)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ aicwf_dev_skb_free(pkt); ++ return; ++ } ++ #endif ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ ++ atomic_inc(&rx_priv->rx_cnt); ++} ++ ++ ++#define SDIO_OTHER_INTERRUPT (0x1ul << 7) ++ ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(&func->dev); ++ struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ u8 intstatus = 0; ++ u8 byte_len = 0; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_buff *pkt = NULL; ++ #else ++ struct sk_buff *pkt = NULL; ++ #endif ++ int ret; ++ ++ ++ if ((sdiodev->rwnx_hw) == NULL) { ++ sdio_err("waiting for rwnx_hw->irq_enable is true\r\n"); ++ return; ++ } ++ ++ //AICWFDBG(LOGDEBUG, "fdrv %s enter \r\n", __func__); ++ rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_irqrx); ++ ++ ++ if (!bus_if || bus_if->state == BUS_DOWN_ST) { ++ sdio_err("bus err\n"); ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); ++ return; ++ } ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++ if (list_empty(&aic_rx_buff_list.rxbuff_list)) { ++ printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); ++ return; ++ } ++#endif ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ while (ret || (intstatus & SDIO_OTHER_INTERRUPT)) { ++ sdio_err("ret=%d, intstatus=%x\r\n", ret, intstatus); ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); ++ if (!ret) { ++ return; ++ } ++ } ++ sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; ++ ++ if (intstatus > 0) { ++ if (intstatus < 64) { ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } else { ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ // sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ ++ if(atomic_read(&sdiodev->rx_priv->rx_cnt) == 1){ ++ complete(&bus_if->busrx_trgg); ++ } ++ ++ }else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ do { ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.misc_int_status_reg, &intstatus); ++ if (!ret) { ++ break; ++ } ++ sdio_err("ret=%d, intstatus=%x\r\n",ret, intstatus); ++ return; ++ } while (1); ++ if (intstatus & SDIO_OTHER_INTERRUPT) { ++ u8 int_pending; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ int_pending &= ~0x01; // dev to host soft irq ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.sleep_reg, int_pending); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.sleep_reg); ++ } ++ } ++ ++ if (intstatus > 0) { ++ uint8_t intmaskf2 = intstatus | (0x1UL << 3); ++ if (intmaskf2 > 120U) { // func2 ++ if (intmaskf2 == 127U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 1);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ //pkt = aicwf_sdio_readframes(sdiodev, 1); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7U) * SDIOWIFI_FUNC_BLOCKSIZE; ++ //pkt = aicwf_sdio_readframes(sdiodev, 1); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } ++ } else { // func1 ++ if (intstatus == 120U) { // byte mode ++ //aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len, 0);//byte_len must<= 128 ++ aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 ++ sdio_info("byte mode len=%d\r\n", byte_len); ++ //pkt = aicwf_sdio_readframes(sdiodev, 0); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } else { // block mode ++ sdiodev->rx_priv->data_len = (intstatus & 0x7FU) * SDIOWIFI_FUNC_BLOCKSIZE; ++ //pkt = aicwf_sdio_readframes(sdiodev, 0); ++ pkt = aicwf_sdio_readframes(sdiodev); ++ } ++ } ++ } else { ++ #ifndef CONFIG_PLATFORM_ALLWINNER ++ //sdio_err("Interrupt but no data\n"); ++ #endif ++ } ++ ++ if (pkt) ++ aicwf_sdio_enq_rxpkt(sdiodev, pkt); ++ ++ if(atomic_read(&sdiodev->rx_priv->rx_cnt) == 1){ ++ complete(&bus_if->busrx_trgg); ++ } ++ } ++ ++ rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); ++} ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration) ++{ ++ uint timeout; ++ ++ //printk("%s duration:%d\r\n", __func__, duration); ++ if (sdiodev->bus_if->state == BUS_DOWN_ST && duration) ++ return; ++ ++ spin_lock_bh(&sdiodev->pwrctl_lock); ++ if (!duration) { ++ if (timer_pending(&sdiodev->timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&sdiodev->timer); ++#else ++ del_timer_sync(&sdiodev->timer); ++#endif ++ } else { ++ sdiodev->active_duration = duration; ++ timeout = msecs_to_jiffies(sdiodev->active_duration); ++ mod_timer(&sdiodev->timer, jiffies + timeout); ++ } ++ spin_unlock_bh(&sdiodev->pwrctl_lock); ++} ++#endif ++ ++static struct aicwf_bus_ops aicwf_sdio_bus_ops = { ++ .stop = aicwf_sdio_bus_stop, ++ .start = aicwf_sdio_bus_start, ++ .txdata = aicwf_sdio_bus_txdata, ++ .txmsg = aicwf_sdio_bus_txmsg, ++}; ++ ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) ++{ ++ struct aicwf_bus *bus_if; ++ int ret = 0; ++ AICWFDBG(LOGINFO, "%s Enter\n", __func__); ++ ++ bus_if = dev_get_drvdata(sdiodev->dev); ++ bus_if->state = BUS_DOWN_ST; ++#ifdef CONFIG_OOB ++ if(sdiodev->oob_enable){ ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ } ++#else ++ sdio_claim_host(sdiodev->func); ++ //disable sdio interrupt ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); ++ } ++ sdio_release_irq(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++#endif ++ if (sdiodev->dev) ++ aicwf_bus_deinit(sdiodev->dev); ++ ++ if (sdiodev->tx_priv) ++ aicwf_tx_deinit(sdiodev->tx_priv); ++ ++ if (sdiodev->rx_priv) ++ aicwf_rx_deinit(sdiodev->rx_priv); ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ if (sdiodev->pwrctl_tsk) { ++ complete_all(&sdiodev->pwrctrl_trgg); ++ kthread_stop(sdiodev->pwrctl_tsk); ++ sdiodev->pwrctl_tsk = NULL; ++ } ++ ++ AICWFDBG(LOGINFO, "%s:pwrctl stopped\n", __func__); ++ #endif ++ ++ if (sdiodev->cmd_mgr.state == RWNX_CMD_MGR_STATE_INITED) ++ rwnx_cmd_mgr_deinit(&sdiodev->cmd_mgr); ++ AICWFDBG(LOGINFO, "%s Exit\n", __func__); ++} ++ ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev) ++{ ++ sdio_dbg("%s\n", __func__); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_CONFIG_REG; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_SLEEP_REG; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_WAKEUP_REG; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_REG; ++ sdiodev->sdio_reg.register_block = SDIOWIFI_REGISTER_BLOCK; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG; ++ sdiodev->sdio_reg.block_cnt_reg = SDIOWIFI_BLOCK_CNT_REG; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR; ++ } else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ sdiodev->sdio_reg.bytemode_len_reg = SDIOWIFI_BYTEMODE_LEN_REG_V3; ++ sdiodev->sdio_reg.intr_config_reg = SDIOWIFI_INTR_ENABLE_REG_V3; ++ sdiodev->sdio_reg.sleep_reg = SDIOWIFI_INTR_PENDING_REG_V3; ++ sdiodev->sdio_reg.wakeup_reg = SDIOWIFI_INTR_TO_DEVICE_REG_V3; ++ sdiodev->sdio_reg.flow_ctrl_reg = SDIOWIFI_FLOW_CTRL_Q1_REG_V3; ++ sdiodev->sdio_reg.bytemode_enable_reg = SDIOWIFI_BYTEMODE_ENABLE_REG_V3; ++ sdiodev->sdio_reg.misc_int_status_reg = SDIOWIFI_MISC_INT_STATUS_REG_V3; ++ sdiodev->sdio_reg.rd_fifo_addr = SDIOWIFI_RD_FIFO_ADDR_V3; ++ sdiodev->sdio_reg.wr_fifo_addr = SDIOWIFI_WR_FIFO_ADDR_V3; ++ } ++} ++ ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 block_bit0 = 0x1; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ struct aicbsp_feature_t feature; ++ //u8 val = 0; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++#if 0//SDIO PHASE SETTING ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ sdio_f0_writeb(sdiodev->func, feature.sdio_phase, 0x13, &ret); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "write func0 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#endif ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_release_host(sdiodev->func); ++ AICWFDBG(LOGERROR, "enable func fail %d.\n", ret); ++ return ret; ++ } ++ ++#if 1//SDIO CLOCK SETTING ++ if (feature.sdio_clock > 0) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ AICWFDBG(LOGINFO, "Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++ ++ sdio_release_host(sdiodev->func); ++ ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ sdio_claim_host(sdiodev->func2); ++ //set sdio blocksize ++ ret = sdio_set_block_size(sdiodev->func2, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set func2 blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func2); ++ return ret; ++ } ++ ++ //set sdio enable func ++ ret = sdio_enable_func(sdiodev->func2); ++ if (ret < 0) { ++ sdio_release_host(sdiodev->func2); ++ AICWFDBG(LOGERROR, "enable func2 fail %d.\n", ret); ++ return ret; ++ } ++ ++ sdio_release_host(sdiodev->func2); ++ ++ ret = aicwf_sdio_func2_writeb(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_func2_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ } ++ ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.register_block, block_bit0); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.register_block); ++ return ret; ++ } ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++#if 0 ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 1); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ return ret; ++ } ++ ++ mdelay(5); ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ return ret; ++ } ++ ++ if(!(val & 0x10)){ ++ AICWFDBG(LOGERROR, "wakeup fail\n"); ++ }else{ ++ AICWFDBG(LOGINFO, "sdio ready\n"); ++ } ++#else ++ mdelay(10); ++#endif ++ return ret; ++} ++ ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct mmc_host *host; ++ u8 byte_mode_disable = 0x1;//1: no byte mode ++ int ret = 0; ++ struct aicbsp_feature_t feature; ++ //u8 val = 0; ++ u8 val1 = 0; ++ ++ aicbsp_get_feature(&feature, NULL); ++ aicwf_sdio_reg_init(sdiodev); ++ ++ host = sdiodev->func->card->host; ++ ++ sdio_claim_host(sdiodev->func); ++ sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ ++ ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "set blocksize fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ ret = sdio_enable_func(sdiodev->func); ++ if (ret < 0) { ++ sdio_release_host(sdiodev->func); ++ AICWFDBG(LOGERROR, "enable func fail %d.\n", ret); ++ return ret; ++ } ++ ++ sdio_f0_writeb(sdiodev->func, 0x7F, 0xF2, &ret); ++ if (ret) { ++ sdio_err("set fn0 0xF2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++#if 0 ++ if (host->ios.timing == MMC_TIMING_UHS_DDR50) { ++ val = 0x21;//0x1D;//0x5; ++ } else { ++ val = 0x01;//0x19;//0x1; ++ } ++ val |= SDIOCLK_FREE_RUNNING_BIT; ++ sdio_f0_writeb(sdiodev->func, val, 0xF0, &ret); ++ if (ret) { ++ sdio_err("set iopad ctrl fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x0, 0xF8, &ret); ++ if (ret) { ++ sdio_err("set iopad delay2 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ sdio_f0_writeb(sdiodev->func, 0x20, 0xF1, &ret); ++ if (ret) { ++ sdio_err("set iopad delay1 fail %d\n", ret); ++ sdio_release_host(sdiodev->func); ++ return ret; ++ } ++ msleep(1); ++#if 1//SDIO CLOCK SETTING ++ if ((feature.sdio_clock > 0) && (host->ios.timing != MMC_TIMING_UHS_DDR50)) { ++ host->ios.clock = feature.sdio_clock; ++ host->ops->set_ios(host, &host->ios); ++ AICWFDBG(LOGINFO, "Set SDIO Clock %d MHz\n", host->ios.clock/1000000); ++ } ++#endif ++#endif ++ sdio_release_host(sdiodev->func); ++ ++ //1: no byte mode ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.bytemode_enable_reg, byte_mode_disable); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.bytemode_enable_reg); ++ return ret; ++ } ++ ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 0x11); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ return ret; ++ } ++ ++#if 1 ++ mdelay(5); ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val1); ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "reg:%d read failed!\n", sdiodev->sdio_reg.sleep_reg); ++ return ret; ++ } ++ ++ if(!(val1 & 0x10)){ ++ AICWFDBG(LOGERROR, "wakeup fail\n"); ++ }else{ ++ AICWFDBG(LOGINFO, "sdio ready\n"); ++ } ++#endif ++ return ret; ++} ++ ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev) ++{ ++ sdio_claim_host(sdiodev->func); ++ sdio_disable_func(sdiodev->func); ++ sdio_release_host(sdiodev->func); ++ ++ if(sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ sdio_claim_host(sdiodev->func2); ++ sdio_disable_func(sdiodev->func2); ++ sdio_release_host(sdiodev->func2); ++ } ++} ++ ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev) ++{ ++ int ret; ++ struct aicwf_bus *bus_if; ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ spin_lock_init(&sdiodev->pwrctl_lock); ++ sema_init(&sdiodev->pwrctl_wakeup_sema, 1); ++ #endif ++ ++ bus_if = sdiodev->bus_if; ++ bus_if->dev = sdiodev->dev; ++ bus_if->ops = &aicwf_sdio_bus_ops; ++ bus_if->state = BUS_DOWN_ST; ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ sdiodev->state = SDIO_SLEEP_ST; ++ sdiodev->active_duration = SDIOWIFI_PWR_CTRL_INTERVAL; ++ #else ++ sdiodev->state = SDIO_ACTIVE_ST; ++ #endif ++ ++ rx_priv = aicwf_rx_init(sdiodev); ++ if (!rx_priv) { ++ sdio_err("rx init fail\n"); ++ goto fail; ++ } ++ sdiodev->rx_priv = rx_priv; ++ ++ tx_priv = aicwf_tx_init(sdiodev); ++ if (!tx_priv) { ++ sdio_err("tx init fail\n"); ++ goto fail; ++ } ++ sdiodev->tx_priv = tx_priv; ++ aicwf_frame_queue_init(&tx_priv->txq, 8, TXQLEN); ++ spin_lock_init(&tx_priv->txqlock); ++ sema_init(&tx_priv->txctl_sema, 1); ++ sema_init(&tx_priv->cmd_txsema, 1); ++ init_waitqueue_head(&tx_priv->cmd_txdone_wait); ++ atomic_set(&tx_priv->tx_pktcnt, 0); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ init_timer(&sdiodev->timer); ++ sdiodev->timer.data = (ulong) sdiodev; ++ sdiodev->timer.function = aicwf_sdio_bus_pwrctl; ++#else ++ timer_setup(&sdiodev->timer, aicwf_sdio_bus_pwrctl, 0); ++#endif ++ init_completion(&sdiodev->pwrctrl_trgg); ++#ifdef AICWF_SDIO_SUPPORT ++ sdiodev->pwrctl_tsk = kthread_run(aicwf_sdio_pwrctl_thread, sdiodev, "aicwf_pwrctl"); ++#endif ++ if (IS_ERR(sdiodev->pwrctl_tsk)) { ++ sdiodev->pwrctl_tsk = NULL; ++ } ++#endif ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ sdiodev->flowctrl = 0; ++ spin_lock_init(&sdiodev->tx_flow_lock); ++#endif ++ ++#ifdef CONFIG_TEMP_CONTROL ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ init_timer(&sdiodev->tp_ctrl_timer); ++ sdiodev->tp_ctrl_timer.data = (ulong) sdiodev; ++ sdiodev->tp_ctrl_timer.function = aicwf_temp_ctrl_timer; ++ init_timer(&sdiodev->netif_timer); ++ sdiodev->netif_timer.data = (ulong) sdiodev; ++ sdiodev->netif_timer.function = aicwf_netif_timer; ++#else ++ timer_setup(&sdiodev->tp_ctrl_timer, aicwf_temp_ctrl_timer, 0); ++ timer_setup(&sdiodev->netif_timer, aicwf_netif_timer, 0); ++#endif ++ INIT_WORK(&sdiodev->tp_ctrl_work, aicwf_temp_ctrl_worker); ++ INIT_WORK(&sdiodev->netif_work, aicwf_netif_worker); ++ mod_timer(&sdiodev->tp_ctrl_timer, jiffies + msecs_to_jiffies(TEMP_GET_INTERVAL)); ++ sdiodev->net_stop = false;; ++ sdiodev->on_off = true; ++ sdiodev->cur_temp = 0; ++ sdiodev->get_level = 0; ++ sdiodev->set_level = 0; ++ sdiodev->interval_t1 = TMR_INTERVAL_1; ++ sdiodev->interval_t2 = TMR_INTERVAL_2; ++ sdiodev->cur_stat = 0; ++#endif ++ ++ ret = aicwf_bus_init(0, sdiodev->dev); ++ if (ret < 0) { ++ sdio_err("bus init fail\n"); ++ goto fail; ++ } ++ ++ ret = aicwf_bus_start(bus_if); ++ if (ret != 0) { ++ sdio_err("bus start fail\n"); ++ goto fail; ++ } ++ ++ return sdiodev; ++ ++fail: ++ aicwf_sdio_release(sdiodev); ++ return NULL; ++} ++ ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size) ++{ ++ uint8_t i; ++ uint8_t crc = 0; ++ if (cal_size==0) { ++ return crc; ++ } ++ while (cal_size--) { ++ for (i = 0x80; i > 0; i /= 2) { ++ if (crc & 0x80) { ++ crc *= 2; ++ crc ^= 0x07; //polynomial X8 + X2 + X + 1,(0x107) ++ } else { ++ crc *= 2; ++ } ++ if ((*p_buffer) & i) { ++ crc ^= 0x07; ++ } ++ } ++ p_buffer++; ++ } ++ ++ return crc; ++} ++ ++#ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX ++void rwnx_set_wifi_suspend(char onoff){ ++ int ret = 0; ++ if (onoff == '0') { ++ printk("%s resume \r\n", __func__); ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 0, 1); ++ }else{ ++ printk("%s suspend \r\n", __func__); ++ ret = rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1, 0); ++ if (!ret) { ++ aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); ++ ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); ++ } ++ } ++ } ++} ++ ++static ssize_t rwnx_wifi_suspend_write_proc(struct file *file, ++ const char __user *buffer, ++ size_t count, loff_t *pos){ ++ char onoff; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ if (copy_from_user(&onoff, buffer, 1)) ++ return -EFAULT; ++ ++ rwnx_set_wifi_suspend(onoff); ++ ++ return count; ++} ++ ++static const struct file_operations wifi_suspend_fops = { ++ .owner = THIS_MODULE, ++ .write = rwnx_wifi_suspend_write_proc, ++}; ++ ++void rwnx_init_wifi_suspend_node(void){ ++ struct proc_dir_entry *ent; ++ ++ wifi_suspend_node = proc_mkdir("wifi_suspend", NULL); ++ if (wifi_suspend_node == NULL) { ++ printk("Unable to create /proc/wifi_suspend directory"); ++ } ++ ++ ent = proc_create("suspend", 0660, wifi_suspend_node, &wifi_suspend_fops); ++ if (ent == NULL) { ++ printk("Unable to create /proc/wifi_suspend/suspend"); ++ } ++} ++ ++void rwnx_deinit_wifi_suspend_node(void){ ++ remove_proc_entry("suspend", wifi_suspend_node); ++ remove_proc_entry("wifi_suspend", 0); ++} ++#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h +new file mode 100644 +index 000000000000..7e3e16fd405c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h +@@ -0,0 +1,226 @@ ++/** ++ * aicwf_sdio.h ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_SDMMC_H_ ++#define _AICWF_SDMMC_H_ ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include ++#include ++#include ++#include ++#include "rwnx_cmds.h" ++#include "aicwf_rx_prealloc.h" ++#define AICWF_SDIO_NAME "aicwf_sdio" ++#define SDIOWIFI_FUNC_BLOCKSIZE 512 ++ ++#define SDIOWIFI_BYTEMODE_LEN_REG 0x02 ++#define SDIOWIFI_INTR_CONFIG_REG 0x04 ++#define SDIOWIFI_SLEEP_REG 0x05 ++#define SDIOWIFI_WAKEUP_REG 0x09 ++#define SDIOWIFI_FLOW_CTRL_REG 0x0A ++#define SDIOWIFI_REGISTER_BLOCK 0x0B ++#define SDIOWIFI_BYTEMODE_ENABLE_REG 0x11 ++#define SDIOWIFI_BLOCK_CNT_REG 0x12 ++#define SDIOWIFI_FLOWCTRL_MASK_REG 0x7F ++#define SDIOWIFI_WR_FIFO_ADDR 0x07 ++#define SDIOWIFI_RD_FIFO_ADDR 0x08 ++ ++#define SDIOWIFI_INTR_ENABLE_REG_V3 0x00 ++#define SDIOWIFI_INTR_PENDING_REG_V3 0x01 ++#define SDIOWIFI_INTR_TO_DEVICE_REG_V3 0x02 ++#define SDIOWIFI_FLOW_CTRL_Q1_REG_V3 0x03 ++#define SDIOWIFI_MISC_INT_STATUS_REG_V3 0x04 ++#define SDIOWIFI_BYTEMODE_LEN_REG_V3 0x05 ++#define SDIOWIFI_BYTEMODE_LEN_MSB_REG_V3 0x06 ++#define SDIOWIFI_BYTEMODE_ENABLE_REG_V3 0x07 ++#define SDIOWIFI_MISC_CTRL_REG_V3 0x08 ++#define SDIOWIFI_FLOW_CTRL_Q2_REG_V3 0x09 ++#define SDIOWIFI_CLK_TEST_RESULT_REG_V3 0x0A ++#define SDIOWIFI_RD_FIFO_ADDR_V3 0x0F ++#define SDIOWIFI_WR_FIFO_ADDR_V3 0x10 ++ ++#define SDIOCLK_FREE_RUNNING_BIT (1 << 6) ++ ++#define SDIOWIFI_PWR_CTRL_INTERVAL 30 ++#define FLOW_CTRL_RETRY_COUNT 50 ++#define BUFFER_SIZE 1536 ++#define TAIL_LEN 4 ++#define TXQLEN (2048*4) ++ ++#define SDIO_SLEEP_ST 0 ++#define SDIO_ACTIVE_ST 1 ++ ++#define DATA_FLOW_CTRL_THRESH 2 ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++#define AICWF_SDIO_TX_LOW_WATER 100 ++#define AICWF_SDIO_TX_HIGH_WATER 500 ++#endif ++ ++#ifdef CONFIG_TEMP_CONTROL ++#define TEMP_GET_INTERVAL (60 * 1000) ++#define TEMP_THD_1 80 //temperature 1 (℃) ++#define TEMP_THD_2 95 //temperature 2 (℃) ++#define BUFFERING_V1 8 ++#define BUFFERING_V2 13 ++#define TMR_INTERVAL_1 60 //timer_1 60ms ++#define TMR_INTERVAL_2 180 //timer_2 130ms ++#endif ++ ++typedef enum { ++ SDIO_TYPE_DATA = 0X00, ++ SDIO_TYPE_CFG = 0X10, ++ SDIO_TYPE_CFG_CMD_RSP = 0X11, ++ SDIO_TYPE_CFG_DATA_CFM = 0X12, ++ SDIO_TYPE_CFG_PRINT = 0X13 ++} sdio_type; ++ ++/* SDIO Device ID */ ++#define SDIO_VENDOR_ID_AIC8801 0x5449 ++#define SDIO_VENDOR_ID_AIC8800DC 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80 0xc8a1 ++#define SDIO_VENDOR_ID_AIC8800D80X2 0xc8a1 ++ ++#define SDIO_DEVICE_ID_AIC8801 0x0145 ++#define SDIO_DEVICE_ID_AIC8800DC 0xc08d ++#define SDIO_DEVICE_ID_AIC8800D80 0x0082 ++#define SDIO_DEVICE_ID_AIC8800D80X2 0x2082 ++ ++enum AICWF_IC{ ++ PRODUCT_ID_AIC8801 = 0, ++ PRODUCT_ID_AIC8800DC, ++ PRODUCT_ID_AIC8800DW, ++ PRODUCT_ID_AIC8800D80, ++ PRODUCT_ID_AIC8800D80X2 ++}; ++ ++ ++struct rwnx_hw; ++ ++struct aic_sdio_reg { ++ u8 bytemode_len_reg; ++ u8 intr_config_reg; ++ u8 sleep_reg; ++ u8 wakeup_reg; ++ u8 flow_ctrl_reg; ++ u8 flowctrl_mask_reg; ++ u8 register_block; ++ u8 bytemode_enable_reg; ++ u8 block_cnt_reg; ++ u8 misc_int_status_reg; ++ u8 rd_fifo_addr; ++ u8 wr_fifo_addr; ++}; ++ ++struct aic_sdio_dev { ++ struct rwnx_hw *rwnx_hw; ++ struct sdio_func *func; ++ struct sdio_func *func2; ++ struct device *dev; ++ struct aicwf_bus *bus_if; ++ struct rwnx_cmd_mgr cmd_mgr; ++ ++ struct aicwf_rx_priv *rx_priv; ++ struct aicwf_tx_priv *tx_priv; ++ u32 state; ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ u8 flowctrl; ++ spinlock_t tx_flow_lock; ++#endif ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ //for sdio pwr ctrl ++ struct timer_list timer; ++ uint active_duration; ++ struct completion pwrctrl_trgg; ++ struct task_struct *pwrctl_tsk; ++ spinlock_t pwrctl_lock; ++ struct semaphore pwrctl_wakeup_sema; ++ #endif ++ u16 chipid; ++ struct aic_sdio_reg sdio_reg; ++ ++ spinlock_t wslock;//AIDEN test ++ bool oob_enable; ++ atomic_t is_bus_suspend; ++ ++#ifdef CONFIG_TEMP_CONTROL ++ spinlock_t tx_flow_lock; ++ struct timer_list netif_timer; ++ struct timer_list tp_ctrl_timer; ++ struct work_struct tp_ctrl_work; ++ struct work_struct netif_work; ++ s8_l cur_temp; ++ bool net_stop; ++ bool on_off; //for command, 0 - off, 1 - on ++ int8_t get_level; //for command, 0 - 100%, 1 - 12%, 2 - 3% ++ int8_t set_level; //for command, 0 - driver auto, 1 - 12%, 2 - 3% ++ int interval_t1; ++ int interval_t2; ++ u8_l cur_stat; //0--normal temp, 1/2--buffering temp ++#endif ++ ++}; ++ ++#ifdef CONFIG_TEMP_CONTROL ++void aicwf_netif_worker(struct work_struct *work); ++void aicwf_temp_ctrl_worker(struct work_struct *work); ++void aicwf_temp_ctrl(struct aic_sdio_dev *sdiodev); ++void aicwf_netif_ctrl(struct aic_sdio_dev *sdiodev, int val); ++#endif ++extern struct aicwf_rx_buff_list aic_rx_buff_list; ++int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++int aicwf_sdio_func2_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val); ++int aicwf_sdio_func2_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++void aicwf_sdio_hal_irqhandler(struct sdio_func *func); ++ ++#if defined(CONFIG_SDIO_PWRCTRL) ++void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration); ++int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target); ++#endif ++void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); ++int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev); ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++void aicwf_sdio_tx_netif_flowctrl(struct rwnx_hw *rwnx_hw, bool state); ++#endif ++int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); ++int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev); ++#ifdef CONFIG_PREALLOC_RX_SKB ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct rx_buff *rxbbuf, u32 size); ++#else ++int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size); ++#endif ++int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count); ++void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_release(struct aic_sdio_dev *sdiodev); ++void aicwf_sdio_exit(void); ++void aicwf_sdio_register(void); ++int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt); ++int sdio_bustx_thread(void *data); ++int sdio_busrx_thread(void *data); ++#ifdef CONFIG_OOB ++//new oob feature ++int sdio_busirq_thread(void *data); ++#endif //CONFIG_OOB ++int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt); ++int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv, u8 txnow); ++void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv); ++void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv); ++extern void aicwf_hostif_ready(void); ++extern void aicwf_hostif_fail(void); ++#ifdef CONFIG_PLATFORM_AMLOGIC ++extern void extern_wifi_set_enable(int is_on); ++extern void sdio_reinit(void); ++#endif /*CONFIG_PLATFORM_AMLOGIC*/ ++uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size); ++ ++#endif /* AICWF_SDIO_SUPPORT */ ++ ++#endif /*_AICWF_SDMMC_H_*/ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c +new file mode 100644 +index 000000000000..d74bd8d1f420 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c +@@ -0,0 +1,646 @@ ++#include"aicwf_tcp_ack.h" ++//#include"rwnx_tx.h" ++//#include "aicwf_tcp_ack.h" ++#include"rwnx_defs.h" ++extern int intf_tx(struct rwnx_hw *priv,struct msg_buf *msg); ++struct msg_buf *intf_tcp_alloc_msg(struct msg_buf *msg) ++{ ++ //printk("%s \n",__func__); ++ int len=sizeof(struct msg_buf) ; ++ msg = kzalloc(len , /*GFP_KERNEL*/GFP_ATOMIC); ++ if(!msg) ++ printk("%s: alloc failed \n", __func__); ++ memset(msg,0,len); ++ return msg; ++} ++ ++void intf_tcp_drop_msg(struct rwnx_hw *priv, ++ struct msg_buf *msg) ++{ ++ //printk("%s \n",__func__); ++ if (msg->skb) ++ dev_kfree_skb_any(msg->skb); ++ ++ kfree(msg); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void tcp_ack_timeout(unsigned long data) ++#else ++void tcp_ack_timeout(struct timer_list *t) ++#endif ++{ ++ //printk("%s \n",__func__); ++ struct tcp_ack_info *ack_info; ++ struct msg_buf *msg; ++ struct tcp_ack_manage *ack_m = NULL; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ ack_info = (struct tcp_ack_info *)data; ++#else ++ ack_info = container_of(t,struct tcp_ack_info,timer); ++#endif ++ ++ ack_m = container_of(ack_info, struct tcp_ack_manage, ++ ack_info[ack_info->ack_info_num]); ++ ++ write_seqlock_bh(&ack_info->seqlock); ++ msg = ack_info->msgbuf; ++ if (ack_info->busy && msg && !ack_info->in_send_msg) { ++ ack_info->msgbuf = NULL; ++ ack_info->drop_cnt = 0; ++ ack_info->in_send_msg = msg; ++ write_sequnlock_bh(&ack_info->seqlock); ++ intf_tx(ack_m->priv, msg);//send skb ++ //ack_info->in_send_msg = NULL;//add by dwx ++ //write_sequnlock_bh(&ack_info->seqlock); ++ //intf_tx(ack_m->priv, msg); ++ return; ++ } ++ write_sequnlock_bh(&ack_info->seqlock); ++} ++ ++void tcp_ack_init(struct rwnx_hw *priv) ++{ ++ int i; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ ++ printk("%s \n",__func__); ++ memset(ack_m, 0, sizeof(struct tcp_ack_manage)); ++ ack_m->priv = priv; ++ spin_lock_init(&ack_m->lock); ++ atomic_set(&ack_m->max_drop_cnt, TCP_ACK_DROP_CNT); ++ ack_m->last_time = jiffies; ++ ack_m->timeout = msecs_to_jiffies(ACK_OLD_TIME); ++ ++ for (i = 0; i < TCP_ACK_NUM; i++) { ++ ack_info = &ack_m->ack_info[i]; ++ ack_info->ack_info_num = i; ++ seqlock_init(&ack_info->seqlock); ++ ack_info->last_time = jiffies; ++ ack_info->timeout = msecs_to_jiffies(ACK_OLD_TIME); ++ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ setup_timer(&ack_info->timer, tcp_ack_timeout, ++ (unsigned long)ack_info); ++ #else ++ timer_setup(&ack_info->timer,tcp_ack_timeout,0); ++ #endif ++ } ++ ++ atomic_set(&ack_m->enable, 1); ++ ack_m->ack_winsize = MIN_WIN; ++} ++ ++void tcp_ack_deinit(struct rwnx_hw *priv) ++{ ++ int i; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ struct msg_buf *drop_msg = NULL; ++ ++ printk("%s \n",__func__); ++ atomic_set(&ack_m->enable, 0); ++ ++ for (i = 0; i < TCP_ACK_NUM; i++) { ++ drop_msg = NULL; ++ ++ write_seqlock_bh(&ack_m->ack_info[i].seqlock); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_m->ack_info[i].timer); ++#else ++ del_timer(&ack_m->ack_info[i].timer); ++#endif ++ drop_msg = ack_m->ack_info[i].msgbuf; ++ ack_m->ack_info[i].msgbuf = NULL; ++ write_sequnlock_bh(&ack_m->ack_info[i].seqlock); ++ ++ if (drop_msg) ++ intf_tcp_drop_msg(priv, drop_msg);//drop skb ++ } ++} ++ ++int tcp_check_quick_ack(unsigned char *buf, ++ struct tcp_ack_msg *msg) ++{ ++ int ip_hdr_len; ++ unsigned char *temp; ++ struct ethhdr *ethhdr; ++ struct iphdr *iphdr; ++ struct tcphdr *tcphdr; ++ ++ ethhdr = (struct ethhdr *)buf; ++ if (ethhdr->h_proto != htons(ETH_P_IP)) ++ return 0; ++ iphdr = (struct iphdr *)(ethhdr + 1); ++ if (iphdr->version != 4 || iphdr->protocol != IPPROTO_TCP) ++ return 0; ++ ip_hdr_len = iphdr->ihl * 4; ++ temp = (unsigned char *)(iphdr) + ip_hdr_len; ++ tcphdr = (struct tcphdr *)temp; ++ /* TCP_FLAG_ACK */ ++ if (!(temp[13] & 0x10)) ++ return 0; ++ ++ if (temp[13] & 0x8) { ++ msg->saddr = iphdr->daddr; ++ msg->daddr = iphdr->saddr; ++ msg->source = tcphdr->dest; ++ msg->dest = tcphdr->source; ++ msg->seq = ntohl(tcphdr->seq); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int is_drop_tcp_ack(struct tcphdr *tcphdr, int tcp_tot_len, ++ unsigned short *win_scale) ++{ ++ //printk("%s \n",__func__); ++ int drop = 1; ++ int len = tcphdr->doff * 4; ++ unsigned char *ptr; ++ ++ if(tcp_tot_len > len) { ++ drop = 0; ++ } else { ++ len -= sizeof(struct tcphdr); ++ ptr = (unsigned char *)(tcphdr + 1); ++ ++ while ((len > 0) && drop) { ++ int opcode = *ptr++; ++ int opsize; ++ ++ switch (opcode) { ++ case TCPOPT_EOL: ++ break; ++ case TCPOPT_NOP: ++ len--; ++ continue; ++ default: ++ opsize = *ptr++; ++ if (opsize < 2) ++ break; ++ if (opsize > len) ++ break; ++ ++ switch (opcode) { ++ /* TODO: Add other ignore opt */ ++ case TCPOPT_TIMESTAMP: ++ break; ++ case TCPOPT_WINDOW: ++ if (*ptr < 15) ++ *win_scale = (1 << (*ptr)); ++ //printk("%d\n",*win_scale); ++ break; ++ default: ++ drop = 2; ++ } ++ ++ ptr += opsize - 2; ++ len -= opsize; ++ } ++ } ++ } ++ ++ return drop; ++} ++ ++ ++/* flag:0 for not tcp ack ++ * 1 for ack which can be drop ++ * 2 for other ack whith more info ++ */ ++ ++int tcp_check_ack(unsigned char *buf, ++ struct tcp_ack_msg *msg, ++ unsigned short *win_scale) ++{ ++ int ret; ++ int ip_hdr_len; ++ int tcp_tot_len; ++ unsigned char *temp; ++ struct ethhdr *ethhdr; ++ struct iphdr *iphdr; ++ struct tcphdr *tcphdr; ++ ++ ethhdr =(struct ethhdr *)buf; ++ if (ethhdr->h_proto != htons(ETH_P_IP)) ++ return 0; ++ ++ iphdr = (struct iphdr *)(ethhdr + 1); ++ if (iphdr->version != 4 || iphdr->protocol != IPPROTO_TCP) ++ return 0; ++ ++ ip_hdr_len = iphdr->ihl * 4; ++ temp = (unsigned char *)(iphdr) + ip_hdr_len; ++ tcphdr = (struct tcphdr *)temp; ++ /* TCP_FLAG_ACK */ ++ if (!(temp[13] & 0x10)) ++ return 0; ++ ++ tcp_tot_len = ntohs(iphdr->tot_len) - ip_hdr_len;// tcp total len ++ ret = is_drop_tcp_ack(tcphdr, tcp_tot_len, win_scale); ++ //printk("is drop:%d \n",ret); ++ ++ if (ret > 0) { ++ msg->saddr = iphdr->saddr; ++ msg->daddr = iphdr->daddr; ++ msg->source = tcphdr->source; ++ msg->dest = tcphdr->dest; ++ msg->seq = ntohl(tcphdr->ack_seq); ++ msg->win = ntohs(tcphdr->window); ++ } ++ ++ return ret; ++} ++ ++/* return val: -1 for not match, others for match */ ++int tcp_ack_match(struct tcp_ack_manage *ack_m, ++ struct tcp_ack_msg *ack_msg) ++{ ++ int i, ret = -1; ++ unsigned start; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_msg *ack; ++ ++ for (i = 0; ((ret < 0) && (i < TCP_ACK_NUM)); i++) { ++ ack_info = &ack_m->ack_info[i]; ++ do { ++ start = read_seqbegin(&ack_info->seqlock); ++ ret = -1; ++ ++ ack = &ack_info->ack_msg; ++ if (ack_info->busy && ++ ack->dest == ack_msg->dest && ++ ack->source == ack_msg->source && ++ ack->saddr == ack_msg->saddr && ++ ack->daddr == ack_msg->daddr) ++ ret = i; ++ } while(read_seqretry(&ack_info->seqlock, start)); ++ } ++ ++ return ret; ++} ++ ++ ++void tcp_ack_update(struct tcp_ack_manage *ack_m) ++{ ++ int i; ++ struct tcp_ack_info *ack_info; ++ ++ if (time_after(jiffies, ack_m->last_time + ack_m->timeout)) { ++ spin_lock_bh(&ack_m->lock); ++ ack_m->last_time = jiffies; ++ for (i = TCP_ACK_NUM - 1; i >= 0; i--) { ++ ack_info = &ack_m->ack_info[i]; ++ write_seqlock_bh(&ack_info->seqlock); ++ if (ack_info->busy && ++ time_after(jiffies, ack_info->last_time + ++ ack_info->timeout)) { ++ ack_m->free_index = i; ++ ack_m->max_num--; ++ ack_info->busy = 0; ++ } ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++ spin_unlock_bh(&ack_m->lock); ++ } ++} ++ ++/* return val: -1 for no index, others for index */ ++int tcp_ack_alloc_index(struct tcp_ack_manage *ack_m) ++{ ++ int i, ret = -1; ++ struct tcp_ack_info *ack_info; ++ unsigned start; ++ ++ spin_lock_bh(&ack_m->lock); ++ if (ack_m->max_num == TCP_ACK_NUM) { ++ spin_unlock_bh(&ack_m->lock); ++ return -1; ++ } ++ ++ if (ack_m->free_index >= 0) { ++ i = ack_m->free_index; ++ ack_m->free_index = -1; ++ ack_m->max_num++; ++ spin_unlock_bh(&ack_m->lock); ++ return i; ++ } ++ ++ for (i = 0; ((ret < 0) && (i < TCP_ACK_NUM)); i++) { ++ ack_info = &ack_m->ack_info[i]; ++ do { ++ start = read_seqbegin(&ack_info->seqlock); ++ ret = -1; ++ if (!ack_info->busy) { ++ ack_m->free_index = -1; ++ ack_m->max_num++; ++ ret = i; ++ } ++ } while(read_seqretry(&ack_info->seqlock, start)); ++ } ++ spin_unlock_bh(&ack_m->lock); ++ ++ return ret; ++} ++ ++ ++/* return val: 0 for not handle tx, 1 for handle tx */ ++int tcp_ack_handle(struct msg_buf *new_msgbuf, ++ struct tcp_ack_manage *ack_m, ++ struct tcp_ack_info *ack_info, ++ struct tcp_ack_msg *ack_msg, ++ int type) ++{ ++ int quick_ack = 0; ++ struct tcp_ack_msg *ack; ++ int ret = 0; ++ struct msg_buf *drop_msg = NULL; ++ ++ //printk("%s %d",__func__,type); ++ write_seqlock_bh(&ack_info->seqlock); ++ ++ ack_info->last_time = jiffies; ++ ack = &ack_info->ack_msg; ++ ++ if (type == 2) { ++ if (U32_BEFORE(ack->seq, ack_msg->seq)) { ++ ack->seq = ack_msg->seq; ++ if (ack_info->psh_flag && ++ !U32_BEFORE(ack_msg->seq, ++ ack_info->psh_seq)) { ++ ack_info->psh_flag = 0; ++ } ++ ++ if (ack_info->msgbuf) { ++ //printk("%lx \n",ack_info->msgbuf); ++ drop_msg = ack_info->msgbuf; ++ ack_info->msgbuf = NULL; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_info->timer); ++#else ++ del_timer(&ack_info->timer); ++#endif ++ }else{ ++ //printk("msgbuf is NULL \n"); ++ } ++ ++ ack_info->in_send_msg = NULL; ++ ack_info->drop_cnt = atomic_read(&ack_m->max_drop_cnt); ++ } else { ++ printk("%s before abnormal ack: %d, %d\n", ++ __func__, ack->seq, ack_msg->seq); ++ drop_msg = new_msgbuf; ++ ret = 1; ++ } ++ } else if (U32_BEFORE(ack->seq, ack_msg->seq)) { ++ if (ack_info->msgbuf) { ++ drop_msg = ack_info->msgbuf; ++ ack_info->msgbuf = NULL; ++ } ++ ++ if (ack_info->psh_flag && ++ !U32_BEFORE(ack_msg->seq, ack_info->psh_seq)) { ++ ack_info->psh_flag = 0; ++ quick_ack = 1; ++ } else { ++ ack_info->drop_cnt++; ++ } ++ ++ ack->seq = ack_msg->seq; ++ ++ if (quick_ack || (!ack_info->in_send_msg && ++ (ack_info->drop_cnt >= ++ atomic_read(&ack_m->max_drop_cnt)))) { ++ ack_info->drop_cnt = 0; ++ ack_info->in_send_msg = new_msgbuf; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_info->timer); ++#else ++ del_timer(&ack_info->timer); ++#endif ++ } else { ++ ret = 1; ++ ack_info->msgbuf = new_msgbuf; ++ if (!timer_pending(&ack_info->timer)) ++ mod_timer(&ack_info->timer, ++ (jiffies + msecs_to_jiffies(5))); ++ } ++ } else { ++ printk("%s before ack: %d, %d\n", ++ __func__, ack->seq, ack_msg->seq); ++ drop_msg = new_msgbuf; ++ ret = 1; ++ } ++ ++ write_sequnlock_bh(&ack_info->seqlock); ++ ++ if (drop_msg) ++ intf_tcp_drop_msg(ack_m->priv, drop_msg);// drop skb ++ ++ return ret; ++} ++ ++int tcp_ack_handle_new(struct msg_buf *new_msgbuf, ++ struct tcp_ack_manage *ack_m, ++ struct tcp_ack_info *ack_info, ++ struct tcp_ack_msg *ack_msg, ++ int type) ++{ ++ int quick_ack = 0; ++ struct tcp_ack_msg *ack; ++ int ret = 0; ++ struct msg_buf *drop_msg = NULL; ++ //struct msg_buf * send_msg = NULL; ++ //printk("",); ++ write_seqlock_bh(&ack_info->seqlock); ++ ++ ack_info->last_time = jiffies; ++ ack = &ack_info->ack_msg; ++ ++ if(U32_BEFORE(ack->seq, ack_msg->seq)){ ++ if (ack_info->msgbuf) { ++ drop_msg = ack_info->msgbuf; ++ ack_info->msgbuf = NULL; ++ //ack_info->drop_cnt++; ++ } ++ ++ if (ack_info->psh_flag && ++ !U32_BEFORE(ack_msg->seq, ack_info->psh_seq)) { ++ ack_info->psh_flag = 0; ++ quick_ack = 1; ++ } else { ++ ack_info->drop_cnt++; ++ } ++ ++ ack->seq = ack_msg->seq; ++ ++ if(quick_ack || (!ack_info->in_send_msg && ++ (ack_info->drop_cnt >= ++ atomic_read(&ack_m->max_drop_cnt)))){ ++ ack_info->drop_cnt = 0; ++ //send_msg = new_msgbuf; ++ ack_info->in_send_msg = new_msgbuf; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete(&ack_info->timer); ++#else ++ del_timer(&ack_info->timer); ++#endif ++ }else{ ++ ret = 1; ++ ack_info->msgbuf = new_msgbuf; ++ if (!timer_pending(&ack_info->timer)) ++ mod_timer(&ack_info->timer, ++ (jiffies + msecs_to_jiffies(5))); ++ } ++ ++ //ret = 1; ++ }else { ++ printk("%s before ack: %d, %d\n", ++ __func__, ack->seq, ack_msg->seq); ++ drop_msg = new_msgbuf; ++ ret = 1; ++ } ++ ++ /*if(send_msg){ ++ intf_tx(ack_m->priv,send_msg); ++ ack_info->in_send_msg=NULL; ++ }*/ ++ ++ //ack_info->in_send_msg=NULL; ++ ++ write_sequnlock_bh(&ack_info->seqlock); ++ ++ /*if(send_msg){ ++ intf_tx(ack_m->priv,send_msg); ++ //ack_info->in_send_msg=NULL; ++ }*/ ++ ++ if (drop_msg) ++ intf_tcp_drop_msg(ack_m->priv, drop_msg);// drop skb ++ ++ return ret; ++ ++} ++ ++void filter_rx_tcp_ack(struct rwnx_hw *priv, ++ unsigned char *buf, unsigned plen) ++{ ++ int index; ++ struct tcp_ack_msg ack_msg; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ ++ if (!atomic_read(&ack_m->enable)) ++ return; ++ ++ if ((plen > MAX_TCP_ACK) || ++ !tcp_check_quick_ack(buf, &ack_msg)) ++ return; ++ ++ index = tcp_ack_match(ack_m, &ack_msg); ++ if (index >= 0) { ++ ack_info = ack_m->ack_info + index; ++ write_seqlock_bh(&ack_info->seqlock); ++ ack_info->psh_flag = 1; ++ ack_info->psh_seq = ack_msg.seq; ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++} ++ ++/* return val: 0 for not filter, 1 for filter */ ++int filter_send_tcp_ack(struct rwnx_hw *priv, ++ struct msg_buf *msgbuf, ++ unsigned char *buf, unsigned int plen) ++{ ++ //printk("%s \n",__func__); ++ int ret = 0; ++ int index, drop; ++ unsigned short win_scale = 0; ++ unsigned int win = 0; ++ struct tcp_ack_msg ack_msg; ++ struct tcp_ack_msg *ack; ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ ++ tcp_ack_update(ack_m); ++ drop = tcp_check_ack(buf, &ack_msg, &win_scale); ++ //printk("drop:%d win_scale:%d",drop,win_scale); ++ if (!drop && (0 == win_scale)) ++ return 0; ++ ++ index = tcp_ack_match(ack_m, &ack_msg); ++ if (index >= 0) { ++ ack_info = ack_m->ack_info + index; ++ if ((0 != win_scale) && ++ (ack_info->win_scale != win_scale)) { ++ write_seqlock_bh(&ack_info->seqlock); ++ ack_info->win_scale = win_scale; ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++ ++ if (drop > 0 && atomic_read(&ack_m->enable)) { ++ win = ack_info->win_scale * ack_msg.win; ++ if ((win_scale!=0) && (win < (ack_m->ack_winsize * SIZE_KB))) ++ { ++ drop = 2; ++ printk("%d %d %d",win_scale,win,(ack_m->ack_winsize * SIZE_KB)); ++ } ++ ret = tcp_ack_handle_new(msgbuf, ack_m, ack_info, ++ &ack_msg, drop); ++ } ++ ++ goto out; ++ } ++ ++ index = tcp_ack_alloc_index(ack_m); ++ if (index >= 0) { ++ write_seqlock_bh(&ack_m->ack_info[index].seqlock); ++ ack_m->ack_info[index].busy = 1; ++ ack_m->ack_info[index].psh_flag = 0; ++ ack_m->ack_info[index].last_time = jiffies; ++ ack_m->ack_info[index].drop_cnt = ++ atomic_read(&ack_m->max_drop_cnt); ++ ack_m->ack_info[index].win_scale = ++ (win_scale != 0) ? win_scale : 1; ++ ++ //ack_m->ack_info[index].msgbuf = NULL; ++ //ack_m->ack_info[index].in_send_msg = NULL; ++ ack = &ack_m->ack_info[index].ack_msg; ++ ack->dest = ack_msg.dest; ++ ack->source = ack_msg.source; ++ ack->saddr = ack_msg.saddr; ++ ack->daddr = ack_msg.daddr; ++ ack->seq = ack_msg.seq; ++ write_sequnlock_bh(&ack_m->ack_info[index].seqlock); ++ } ++ ++out: ++ return ret; ++} ++ ++void move_tcpack_msg(struct rwnx_hw *priv, ++ struct msg_buf *msg) ++{ ++ struct tcp_ack_info *ack_info; ++ struct tcp_ack_manage *ack_m = &priv->ack_m; ++ int i = 0; ++ ++ if (!atomic_read(&ack_m->enable)) ++ return; ++ ++ //if (msg->len > MAX_TCP_ACK) ++ // return; ++ ++ for (i = 0; i < TCP_ACK_NUM; i++) { ++ ack_info = &ack_m->ack_info[i]; ++ write_seqlock_bh(&ack_info->seqlock); ++ if (ack_info->busy && (ack_info->in_send_msg == msg)) ++ ack_info->in_send_msg = NULL; ++ write_sequnlock_bh(&ack_info->seqlock); ++ } ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h +new file mode 100644 +index 000000000000..542023fc577c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h +@@ -0,0 +1,92 @@ ++#ifndef _AICWF_TCP_ACK_H_ ++#define _AICWF_TCP_ACK_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define TCP_ACK_NUM 32 ++#define TCP_ACK_EXIT_VAL 0x800 ++#define TCP_ACK_DROP_CNT 10 ++ ++#define ACK_OLD_TIME 4000 ++#define U32_BEFORE(a, b) ((__s32)((__u32)a - (__u32)b) <= 0) ++ ++#define MAX_TCP_ACK 200 ++/*min window size in KB, it's 256KB*/ ++#define MIN_WIN 256 ++#define SIZE_KB 1024 ++ ++ ++struct msg_buf { ++ //struct list_head list; ++ struct sk_buff *skb; ++ struct rwnx_vif *rwnx_vif; ++ /* data just tx cmd use,not include the head */ ++}; ++ ++struct tcp_ack_msg { ++ u16 source; ++ u16 dest; ++ s32 saddr; ++ s32 daddr; ++ u32 seq; ++ u16 win; ++}; ++ ++ ++struct tcp_ack_info { ++ int ack_info_num; ++ int busy; ++ int drop_cnt; ++ int psh_flag; ++ u32 psh_seq; ++ u16 win_scale; ++ /* seqlock for ack info */ ++ seqlock_t seqlock; ++ unsigned long last_time; ++ unsigned long timeout; ++ struct timer_list timer; ++ struct msg_buf *msgbuf; ++ struct msg_buf *in_send_msg; ++ struct tcp_ack_msg ack_msg; ++}; ++ ++struct tcp_ack_manage { ++ /* 1 filter */ ++ atomic_t enable; ++ int max_num; ++ int free_index; ++ unsigned long last_time; ++ unsigned long timeout; ++ atomic_t max_drop_cnt; ++ /* lock for tcp ack alloc and free */ ++ spinlock_t lock; ++ struct rwnx_hw *priv; ++ struct tcp_ack_info ack_info[TCP_ACK_NUM]; ++ /*size in KB*/ ++ unsigned int ack_winsize; ++}; ++ ++struct msg_buf *intf_tcp_alloc_msg(struct msg_buf *msg); ++ ++void tcp_ack_init(struct rwnx_hw *priv); ++ ++void tcp_ack_deinit(struct rwnx_hw *priv); ++ ++ ++int is_drop_tcp_ack(struct tcphdr *tcphdr, int tcp_tot_len, unsigned short *win_scale); ++ ++int is_tcp_ack(struct sk_buff *skb, unsigned short *win_scale); ++ ++int filter_send_tcp_ack(struct rwnx_hw *priv, struct msg_buf *msgbuf,unsigned char *buf, unsigned int plen); ++ ++void filter_rx_tcp_ack(struct rwnx_hw *priv,unsigned char *buf, unsigned plen); ++ ++void move_tcpack_msg(struct rwnx_hw *priv, struct msg_buf * msg); ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c +new file mode 100644 +index 000000000000..555a8deadf54 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c +@@ -0,0 +1,891 @@ ++/** ++ * aicwf_bus.c ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "lmac_msg.h" ++#include "aicwf_txrxif.h" ++#include "rwnx_platform.h" ++#include "rwnx_defs.h" ++#include "rwnx_msg_rx.h" ++#include "rwnx_rx.h" ++#include "aicwf_rx_prealloc.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "sdio_host.h" ++#endif ++#include "aic_bsp_export.h" ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++void aicwf_rxframe_queue_init_2(struct rx_frame_queue *pq, int max_len) ++{ ++ //int prio; ++ ++ memset(pq, 0, offsetof(struct rx_frame_queue, queuelist) + (sizeof(struct list_head))); ++ pq->qmax = (u16)max_len; ++ INIT_LIST_HEAD(&pq->queuelist); ++#if 0 ++ memset(pq, 0, offsetof(struct rx_frame_queue, queuelist) + (sizeof(struct list_head) * num_prio)); ++ pq->num_prio = (u16)num_prio; ++ pq->qmax = (u16)max_len; ++ ++ for (prio = 0; prio < num_prio; prio++) { ++ INIT_LIST_HEAD(&pq->queuelist[prio]); ++ } ++#endif ++} ++ ++//extern struct aic_sdio_dev *g_sdiodev; ++void rxbuff_queue_flush(struct aicwf_rx_priv* rx_priv) ++{ ++ ++ //int prio; ++ struct rx_frame_queue *pq = &rx_priv->rxq; ++ struct list_head *pos; ++ struct list_head *n; ++ struct list_head *head; ++ struct rx_buff *tempbuf = NULL; ++ ++ head = &pq->queuelist; ++ list_for_each_safe(pos, n, head) { ++ tempbuf = list_entry(pos, struct rx_buff, queue); ++ list_del_init(&tempbuf->queue); ++#if 0 ++ rxbuff_free(tempbuf); ++#else ++ aicwf_prealloc_rxbuff_free(tempbuf, &rx_priv->rxbuff_lock); ++#endif ++ pq->qcnt--; ++ } ++} ++#endif ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if; ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return -1; ++ } ++ bus_if = dev_get_drvdata(dev); ++ bus_if->cmd_buf = kzalloc(CMD_BUF_MAX, GFP_KERNEL); ++ if (!bus_if->cmd_buf) { ++ ret = -ENOMEM; ++ txrx_err("proto_attach failed\n"); ++ goto fail; ++ } ++ memset(bus_if->cmd_buf, '\0', CMD_BUF_MAX); ++ ++ init_completion(&bus_if->bustx_trgg); ++ init_completion(&bus_if->busrx_trgg); ++ //new oob feature ++ init_completion(&bus_if->busirq_trgg); ++#ifdef AICWF_SDIO_SUPPORT ++ spin_lock_init(&bus_if->bus_priv.sdio->wslock);//AIDEN test ++ bus_if->bustx_thread = kthread_run(sdio_bustx_thread, (void *)bus_if, "aicwf_bustx_thread"); ++ bus_if->busrx_thread = kthread_run(sdio_busrx_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busrx_thread"); ++ //new oob feature ++#ifdef CONFIG_OOB ++ if(bus_if->bus_priv.sdio->oob_enable){ ++ bus_if->busirq_thread = kthread_run(sdio_busirq_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busirq_thread"); ++ } ++#endif //CONFIG_OOB ++#endif ++#ifdef AICWF_USB_SUPPORT ++ bus_if->bustx_thread = kthread_run(usb_bustx_thread, (void *)bus_if, "aicwf_bustx_thread"); ++ bus_if->busrx_thread = kthread_run(usb_busrx_thread, (void *)bus_if->bus_priv.usb->rx_priv, "aicwf_busrx_thread"); ++#endif ++ ++ if (IS_ERR(bus_if->bustx_thread)) { ++ bus_if->bustx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ goto fail; ++ } ++ ++ if (IS_ERR(bus_if->busrx_thread)) { ++ bus_if->busrx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ goto fail; ++ } ++ ++ return ret; ++fail: ++ aicwf_bus_deinit(dev); ++ ++ return ret; ++} ++ ++void aicwf_bus_deinit(struct device *dev) ++{ ++ struct aicwf_bus *bus_if; ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usb; ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++ ++ if (!dev) { ++ txrx_err("device not found\n"); ++ return; ++ } ++ AICWFDBG(LOGINFO, "%s Enter\r\n", __func__); ++ bus_if = dev_get_drvdata(dev); ++ aicwf_bus_stop(bus_if); ++ ++#ifdef AICWF_USB_SUPPORT ++ usb = bus_if->bus_priv.usb; ++ if (g_rwnx_plat->enabled) ++ rwnx_platform_deinit(usb->rwnx_hw); ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ sdiodev = bus_if->bus_priv.sdio; ++ if (g_rwnx_plat && g_rwnx_plat->enabled) { ++ rwnx_platform_deinit(sdiodev->rwnx_hw); ++ } ++#endif ++ ++ if (bus_if->cmd_buf) { ++ kfree(bus_if->cmd_buf); ++ bus_if->cmd_buf = NULL; ++ } ++ ++ if (bus_if->bustx_thread) { ++ complete_all(&bus_if->bustx_trgg); ++ kthread_stop(bus_if->bustx_thread); ++ bus_if->bustx_thread = NULL; ++ } ++ AICWFDBG(LOGINFO, "%s Exit\r\n", __func__); ++} ++ ++void aicwf_frame_tx(void *dev, struct sk_buff *skb) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ aicwf_bus_txdata(sdiodev->bus_if, skb); ++#else ++ struct aic_usb_dev *usbdev = (struct aic_usb_dev *)dev; ++ ++ if (!usbdev->state) { ++ txrx_err("down\n"); ++ aicwf_usb_tx_flowctrl(usbdev->rwnx_hw, true); ++ dev_kfree_skb(skb); ++ return; ++ } ++ aicwf_bus_txdata(usbdev->bus_if, skb); ++#endif ++} ++ ++struct aicwf_tx_priv *aicwf_tx_init(void *arg) ++{ ++ struct aicwf_tx_priv *tx_priv; ++ ++ tx_priv = kzalloc(sizeof(struct aicwf_tx_priv), GFP_KERNEL); ++ if (!tx_priv) ++ return NULL; ++ ++#ifdef AICWF_SDIO_SUPPORT ++ tx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++#else ++ tx_priv->usbdev = (struct aic_usb_dev *)arg; ++#endif ++ ++ atomic_set(&tx_priv->aggr_count, 0); ++#ifdef CONFIG_RESV_MEM_SUPPORT ++ tx_priv->aggr_buf = aicbsp_resv_mem_alloc_skb(MAX_AGGR_TXPKT_LEN, AIC_RESV_MEM_TXDATA); ++#else ++ tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN); ++#endif ++ if (!tx_priv->aggr_buf) { ++ txrx_err("Alloc bus->txdata_buf failed!\n"); ++ kfree(tx_priv); ++ return NULL; ++ } ++ tx_priv->head = tx_priv->aggr_buf->data; ++ tx_priv->tail = tx_priv->aggr_buf->data; ++ ++#ifdef CONFIG_SDIO_ADMA ++ tx_priv->aggr_segcnt = 0; ++ tx_priv->len = 0; ++#endif ++ ++ return tx_priv; ++} ++ ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv) ++{ ++ if (tx_priv && tx_priv->aggr_buf) { ++#ifdef CONFIG_RESV_MEM_SUPPORT ++ aicbsp_resv_mem_kfree_skb(tx_priv->aggr_buf, AIC_RESV_MEM_TXDATA); ++#else ++ dev_kfree_skb(tx_priv->aggr_buf); ++#endif ++ kfree(tx_priv); ++ } ++#ifdef CONFIG_SDIO_ADMA ++ aicwf_sdio_aggrbuf_reset(tx_priv); ++#endif ++} ++ ++#ifdef AICWF_SDIO_SUPPORT ++#ifdef CONFIG_PREALLOC_RX_SKB ++static bool aicwf_another_ptk_1(struct rx_buff *buffer) ++{ ++ u8 *read = buffer->read; ++ u16 aggr_len = 0; ++ ++ BUG_ON((read - buffer->start)%4 != 0); ++ ++ if(read == NULL || read >= buffer->end) { ++ return false; ++ } ++ ++ aggr_len = (*read | (*(read + 1) << 8)); ++ if(aggr_len == 0) { ++ return false; ++ } ++ ++ return true; ++} ++#else ++static bool aicwf_another_ptk(struct sk_buff *skb) ++{ ++ u8 *data; ++ u16 aggr_len = 0; ++ ++ if (skb->data == NULL || skb->len == 0) { ++ return false; ++ } ++ data = skb->data; ++ aggr_len = (*skb->data | (*(skb->data + 1) << 8)); ++ if (aggr_len == 0) { ++ return false; ++ } ++ ++ return true; ++} ++#endif ++#endif ++ ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ int ret = 0; ++ unsigned long flags = 0; ++#ifndef CONFIG_PREALLOC_RX_SKB ++ struct sk_buff *skb = NULL; ++#endif ++ u16 pkt_len = 0; ++ struct sk_buff *skb_inblock = NULL; ++ u16 aggr_len = 0, adjust_len = 0; ++ u8 *data = NULL; ++ u8_l *msg = NULL; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_buff *buffer = NULL; ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (!rx_priv->rxq.qcnt) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ buffer = rxbuff_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (buffer == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ while (aicwf_another_ptk_1(buffer)) { ++ data = buffer->read; ++ pkt_len = (*data | (*(data + 1) << 8)); ++ ++ if ((data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL); ++ if (skb_inblock == NULL) { ++ txrx_err("no more space! skip\n"); ++ buffer->read = buffer->read + adjust_len; ++ continue; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ buffer->read = buffer->read + adjust_len; ++ } else { ++ // type : config ++ aggr_len = pkt_len; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ msg = kmalloc(aggr_len+4, GFP_KERNEL); ++ if (msg == NULL) { ++ txrx_err("no more space for msg!\n"); ++ aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock); ++ return -EBADE; ++ } ++ ++ memcpy(msg, data, aggr_len + 4); ++ if (((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) && (rx_priv->sdiodev->bus_if->state != BUS_DOWN_ST)) ++ rwnx_rx_handle_msg(rx_priv->sdiodev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) ++ aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_PRINT) ++ rwnx_rx_handle_print(rx_priv->sdiodev->rwnx_hw, msg + 4, aggr_len); ++ ++ buffer->read = buffer->read + (adjust_len + 4); ++ kfree(msg); ++ } ++ } ++ ++ aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock); ++ ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ ++ #else ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ skb = aicwf_frame_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (skb == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ while (aicwf_another_ptk(skb)) { ++ data = skb->data; ++ pkt_len = (*skb->data | (*(skb->data + 1) << 8)); ++ ++ if ((skb->data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL); ++ if (skb_inblock == NULL) { ++ txrx_err("no more space! skip\n"); ++ skb_pull(skb, adjust_len); ++ continue; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ skb_pull(skb, adjust_len); ++ } else { ++ // type : config ++ aggr_len = pkt_len; ++ ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ msg = kmalloc(aggr_len+4, GFP_KERNEL); ++ if (msg == NULL) { ++ txrx_err("no more space for msg!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ ++ memcpy(msg, data, aggr_len + 4); ++ if (((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) && (rx_priv->sdiodev->bus_if->state != BUS_DOWN_ST)) ++ rwnx_rx_handle_msg(rx_priv->sdiodev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) ++ aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == SDIO_TYPE_CFG_PRINT) ++ rwnx_rx_handle_print(rx_priv->sdiodev->rwnx_hw, msg + 4, aggr_len); ++ ++ skb_pull(skb, adjust_len+4); ++ kfree(msg); ++ } ++ } ++ ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ #endif ++ ++ #if defined(CONFIG_SDIO_PWRCTRL) ++ aicwf_sdio_pwr_stctl(rx_priv->sdiodev, SDIO_ACTIVE_ST); ++ #endif ++ ++ return ret; ++#else //AICWF_USB_SUPPORT ++ int ret = 0; ++ unsigned long flags = 0; ++ struct sk_buff *skb = NULL; /* Packet for event or data frames */ ++ u16 pkt_len = 0; ++ struct sk_buff *skb_inblock = NULL; ++ u16 aggr_len = 0, adjust_len = 0; ++ u8 *data = NULL; ++ u8_l *msg = NULL; ++ ++ while (1) { ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { ++ usb_info("no more rxdata\n"); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ break; ++ } ++ skb = aicwf_frame_dequeue(&rx_priv->rxq); ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ if (skb == NULL) { ++ txrx_err("skb_error\r\n"); ++ break; ++ } ++ data = skb->data; ++ pkt_len = (*skb->data | (*(skb->data + 1) << 8)); ++ //printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]); ++ if (pkt_len > 1600) { ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ continue; ++ } ++ ++ if ((skb->data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data ++ aggr_len = pkt_len + RX_HWHRD_LEN; ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv ++ if (skb_inblock == NULL) { ++ txrx_err("no more space! skip!\n"); ++ skb_pull(skb, adjust_len); ++ continue; ++ } ++ ++ skb_put(skb_inblock, aggr_len); ++ memcpy(skb_inblock->data, data, aggr_len); ++ rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb_inblock, (void *)rx_priv); ++ ///TODO: here need to add rx data process ++ ++ skb_pull(skb, adjust_len); ++ } else { // type : config ++ aggr_len = pkt_len; ++ if (aggr_len & (RX_ALIGNMENT - 1)) ++ adjust_len = roundup(aggr_len, RX_ALIGNMENT); ++ else ++ adjust_len = aggr_len; ++ ++ msg = kmalloc(aggr_len+4, GFP_KERNEL); ++ if (msg == NULL) { ++ txrx_err("no more space for msg!\n"); ++ aicwf_dev_skb_free(skb); ++ return -EBADE; ++ } ++ memcpy(msg, data, aggr_len + 4); ++ if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP) ++ rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4)); ++ ++ if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM) ++ aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4)); ++ skb_pull(skb, adjust_len + 4); ++ kfree(msg); ++ } ++ ++ dev_kfree_skb(skb); ++ atomic_dec(&rx_priv->rx_cnt); ++ } ++ ++ return ret; ++#endif //AICWF_SDIO_SUPPORT ++} ++ ++static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize) ++{ ++ int i; ++ struct recv_msdu *req, *reqs; ++ ++ reqs = vmalloc(qsize*sizeof(struct recv_msdu)); ++ if (reqs == NULL) ++ return NULL; ++ ++ req = reqs; ++ for (i = 0; i < qsize; i++) { ++ INIT_LIST_HEAD(&req->rxframe_list); ++ list_add(&req->rxframe_list, q); ++ req++; ++ } ++ ++ return reqs; ++} ++ ++struct aicwf_rx_priv *aicwf_rx_init(void *arg) ++{ ++ struct aicwf_rx_priv *rx_priv; ++ rx_priv = kzalloc(sizeof(struct aicwf_rx_priv), GFP_KERNEL); ++ if (!rx_priv) ++ return NULL; ++ ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv->sdiodev = (struct aic_sdio_dev *)arg; ++#else ++ rx_priv->usbdev = (struct aic_usb_dev *)arg; ++#endif ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ aicwf_rxframe_queue_init_2(&rx_priv->rxq, MAX_RXQLEN); ++ #else ++ aicwf_frame_queue_init(&rx_priv->rxq, 1, MAX_RXQLEN); ++ #endif ++ spin_lock_init(&rx_priv->rxqlock); ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ spin_lock_init(&rx_priv->rxbuff_lock); ++ aicwf_prealloc_init(); ++ #endif ++ atomic_set(&rx_priv->rx_cnt, 0); ++ ++#ifdef AICWF_RX_REORDER ++ INIT_LIST_HEAD(&rx_priv->rxframes_freequeue); ++ spin_lock_init(&rx_priv->freeq_lock); ++ rx_priv->recv_frames = aicwf_rxframe_queue_init(&rx_priv->rxframes_freequeue, MAX_REORD_RXFRAME); ++ if (!rx_priv->recv_frames) { ++ txrx_err("no enough buffer for free recv frame queue!\n"); ++ kfree(rx_priv); ++ return NULL; ++ } ++ spin_lock_init(&rx_priv->stas_reord_lock); ++ INIT_LIST_HEAD(&rx_priv->stas_reord_list); ++#endif ++ ++ return rx_priv; ++} ++ ++ ++static void aicwf_recvframe_queue_deinit(struct list_head *q) ++{ ++ struct recv_msdu *req, *next; ++ ++ list_for_each_entry_safe(req, next, q, rxframe_list) { ++ list_del_init(&req->rxframe_list); ++ } ++} ++ ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv) ++{ ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *tmp; ++ ++ AICWFDBG(LOGINFO, "%s\n", __func__); ++ ++ list_for_each_entry_safe(reord_info, tmp, ++ &rx_priv->stas_reord_list, list) { ++ reord_deinit_sta(rx_priv, reord_info); ++ } ++#endif ++ ++#ifdef AICWF_SDIO_SUPPORT ++ AICWFDBG(LOGINFO, "sdio rx thread\n"); ++ if (rx_priv->sdiodev->bus_if->busrx_thread) { ++ complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg); ++ kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread); ++ rx_priv->sdiodev->bus_if->busrx_thread = NULL; ++ } ++#ifdef CONFIG_OOB ++ if(rx_priv->sdiodev->oob_enable){ ++ //new oob feature ++ if (rx_priv->sdiodev->bus_if->busirq_thread) { ++ complete_all(&rx_priv->sdiodev->bus_if->busirq_trgg); ++ kthread_stop(rx_priv->sdiodev->bus_if->busirq_thread); ++ rx_priv->sdiodev->bus_if->busirq_thread = NULL; ++ } ++ } ++#endif //CONFIG_OOB ++#endif ++#ifdef AICWF_USB_SUPPORT ++ if (rx_priv->usbdev->bus_if->busrx_thread) { ++ complete_all(&rx_priv->usbdev->bus_if->busrx_trgg); ++ kthread_stop(rx_priv->usbdev->bus_if->busrx_thread); ++ rx_priv->usbdev->bus_if->busrx_thread = NULL; ++ } ++#endif ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ rxbuff_queue_flush(rx_priv); ++ #else ++ aicwf_frame_queue_flush(&rx_priv->rxq); ++ #endif ++ ++#ifdef AICWF_RX_REORDER ++ aicwf_recvframe_queue_deinit(&rx_priv->rxframes_freequeue); ++ if (rx_priv->recv_frames) ++ vfree(rx_priv->recv_frames); ++#endif ++ ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ aicwf_prealloc_exit(); ++ #endif ++ kfree(rx_priv); ++ ++ AICWFDBG(LOGINFO, "%s exit \n", __func__); ++} ++ ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt) ++{ ++ return aicwf_frame_enq(dev, q, pkt, 0); ++} ++ ++ ++void aicwf_dev_skb_free(struct sk_buff *skb) ++{ ++ if (!skb) ++ return; ++ ++ dev_kfree_skb_any(skb); ++} ++ ++static struct sk_buff *aicwf_frame_queue_penq(struct frame_queue *pq, int prio, struct sk_buff *p) ++{ ++ struct sk_buff_head *q; ++ ++ if (pq->queuelist[prio].qlen >= pq->qmax) ++ return NULL; ++ ++ q = &pq->queuelist[prio]; ++ __skb_queue_tail(q, p); ++ pq->qcnt++; ++ if (pq->hi_prio < prio) ++ pq->hi_prio = (u16)prio; ++ ++ return p; ++} ++ ++void aicwf_frame_queue_flush(struct frame_queue *pq) ++{ ++ int prio; ++ struct sk_buff_head *q; ++ struct sk_buff *p, *next; ++ ++ for (prio = 0; prio < pq->num_prio; prio++) { ++ q = &pq->queuelist[prio]; ++ skb_queue_walk_safe(q, p, next) { ++ skb_unlink(p, q); ++ aicwf_dev_skb_free(p); ++ pq->qcnt--; ++ } ++ } ++} ++ ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len) ++{ ++ int prio; ++ ++ memset(pq, 0, offsetof(struct frame_queue, queuelist) + (sizeof(struct sk_buff_head) * num_prio)); ++ pq->num_prio = (u16)num_prio; ++ pq->qmax = (u16)max_len; ++ ++ for (prio = 0; prio < num_prio; prio++) { ++ skb_queue_head_init(&pq->queuelist[prio]); ++ } ++} ++ ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out) ++{ ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ for (prio = 0; prio < pq->hi_prio; prio++) ++ if (!skb_queue_empty(&pq->queuelist[prio])) ++ break; ++ ++ if (prio_out) ++ *prio_out = prio; ++ ++ return skb_peek_tail(&pq->queuelist[prio]); ++} ++ ++bool aicwf_is_framequeue_empty(struct frame_queue *pq) ++{ ++ int prio, len = 0; ++ ++ for (prio = 0; prio <= pq->hi_prio; prio++) ++ len += pq->queuelist[prio].qlen; ++ ++ if (len > 0) ++ return false; ++ else ++ return true; ++} ++ ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq) ++{ ++ struct sk_buff_head *q; ++ struct sk_buff *p; ++ int prio; ++ ++ if (pq->qcnt == 0) ++ return NULL; ++ ++ while ((prio = pq->hi_prio) > 0 && skb_queue_empty(&pq->queuelist[prio])) ++ pq->hi_prio--; ++ ++ q = &pq->queuelist[prio]; ++ p = __skb_dequeue(q); ++ if (p == NULL) ++ return NULL; ++ ++ pq->qcnt--; ++ ++ return p; ++} ++#if 0 ++static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio) ++{ ++ struct sk_buff_head *q = &pq->queuelist[prio]; ++ struct sk_buff *p = skb_dequeue_tail(q); ++ ++ if (!p) ++ return NULL; ++ ++ pq->qcnt--; ++ return p; ++} ++#endif ++ ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio) ++{ ++ #if 0 ++ struct sk_buff *p = NULL; ++ int prio_modified = -1; ++ ++ if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { ++ aicwf_frame_queue_penq(q, prio, pkt); ++ return true; ++ } ++ if (q->queuelist[prio].qlen >= q->qmax) { ++ prio_modified = prio; ++ } else if (q->qcnt >= q->qmax) { ++ p = aicwf_frame_queue_peek_tail(q, &prio_modified); ++ if (prio_modified > prio) ++ return false; ++ } ++ ++ if (prio_modified >= 0) { ++ if (prio_modified == prio) ++ return false; ++ ++ p = aicwf_skb_dequeue_tail(q, prio_modified); ++ aicwf_dev_skb_free(p); ++ ++ p = aicwf_frame_queue_penq(q, prio_modified, pkt); ++ if (p == NULL) ++ txrx_err("failed\n"); ++ } ++ ++ return p != NULL; ++ #else ++ if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { ++ aicwf_frame_queue_penq(q, prio, pkt); ++ return true; ++ } else ++ return false; ++ #endif ++} ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++void rxbuff_free(struct rx_buff *rxbuff) ++{ ++ kfree(rxbuff->data); ++ kfree(rxbuff); ++} ++ ++struct rx_buff *rxbuff_queue_penq(struct rx_frame_queue *pq, struct rx_buff *p) ++{ ++ ++ struct list_head *q; ++ if (pq->qcnt >= pq->qmax) ++ return NULL; ++ ++ q = &pq->queuelist; ++ list_add_tail(&p->queue,q); ++ ++ pq->qcnt++; ++ ++ return p; ++} ++ ++struct rx_buff *rxbuff_dequeue(struct rx_frame_queue *pq) ++{ ++ struct rx_buff *p = NULL; ++ ++ if (pq->qcnt == 0) { ++ printk("%s %d, rxq is empty\n", __func__, __LINE__); ++ return NULL; ++ } ++ ++ if(list_empty(&pq->queuelist)) { ++ printk("%s %d, rxq is empty\n", __func__, __LINE__); ++ return NULL; ++ } else { ++ p = list_first_entry(&pq->queuelist, struct rx_buff, queue); ++ list_del_init(&p->queue); ++ pq->qcnt--; ++ } ++ ++ return p; ++} ++ ++bool aicwf_rxbuff_enqueue(struct device *dev, struct rx_frame_queue *rxq, struct rx_buff *pkt) ++{ ++// struct rx_buff *p = NULL; ++ ++ if ((rxq == NULL) || (pkt == NULL)) { ++ printk("%s %d, rxq or pkt is NULL\n", __func__, __LINE__); ++ return false; ++ } ++ ++ if (rxq->qcnt < rxq->qmax) { ++ if (rxbuff_queue_penq(rxq, pkt)) { ++ return true; ++ } else { ++ printk("%s %d, rxbuff enqueue fail\n", __func__, __LINE__); ++ return false; ++ } ++ } else { ++ printk("%s %d, rxq or pkt is full\n", __func__, __LINE__); ++ return false; ++ } ++} ++#endif ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h +new file mode 100644 +index 000000000000..0774c1676235 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h +@@ -0,0 +1,284 @@ ++/** ++ * aicwf_txrxif.h ++ * ++ * bus function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_TXRXIF_H_ ++#define _AICWF_TXRXIF_H_ ++ ++#include ++#include ++#include "ipc_shared.h" ++#include "aicwf_rx_prealloc.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#else ++#include "aicwf_usb.h" ++#endif ++ ++#define CMD_BUF_MAX 1536 ++#define TXPKT_BLOCKSIZE 512 ++#define MAX_AGGR_TXPKT_LEN (1536*64) ++#define CMD_TX_TIMEOUT 5000 ++#define TX_ALIGNMENT 4 ++ ++#define RX_HWHRD_LEN 60 //58->60 word allined ++#define CCMP_OR_WEP_INFO 8 ++#define MAX_RXQLEN 2000 ++#define RX_ALIGNMENT 4 ++ ++#define DEBUG_ERROR_LEVEL 0 ++#define DEBUG_DEBUG_LEVEL 1 ++#define DEBUG_INFO_LEVEL 2 ++ ++#define DBG_LEVEL DEBUG_DEBUG_LEVEL ++ ++#define txrx_err(fmt, ...) pr_err("txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define sdio_err(fmt, ...) pr_err("sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#define usb_err(fmt, ...) pr_err("usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) ++#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL ++#define txrx_dbg(fmt, ...) printk("txrx: " fmt, ##__VA_ARGS__) ++#define sdio_dbg(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__) ++#define usb_dbg(fmt, ...) printk("aicusb: " fmt, ##__VA_ARGS__) ++#else ++#define txrx_dbg(fmt, ...) ++#define sdio_dbg(fmt, ...) ++#define usb_dbg(fmt, ...) ++#endif ++#if DBG_LEVEL >= DEBUG_INFO_LEVEL ++#define txrx_info(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__) ++#define sdio_info(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__) ++#define usb_info(fmt, ...) printk("aicusb: " fmt, ##__VA_ARGS__) ++#else ++#define txrx_info(fmt, ...) ++#define sdio_info(fmt, ...) ++#define usb_info(fmt, ...) ++#endif ++ ++enum aicwf_bus_state { ++ BUS_DOWN_ST, ++ BUS_UP_ST ++}; ++ ++struct aicwf_bus_ops { ++ int (*start) (struct device *dev); ++ void (*stop) (struct device *dev); ++ int (*txdata) (struct device *dev, struct sk_buff *skb); ++ int (*txmsg) (struct device *dev, u8 *msg, uint len); ++}; ++ ++struct frame_queue { ++ u16 num_prio; ++ u16 hi_prio; ++ u16 qmax; /* max number of queued frames */ ++ u16 qcnt; ++ struct sk_buff_head queuelist[8]; ++}; ++ ++#ifdef CONFIG_PREALLOC_RX_SKB ++struct rx_frame_queue { ++ u16 qmax; /* max number of queued frames */ ++ u16 qcnt; ++ struct list_head queuelist; ++}; ++#endif ++ ++struct aicwf_bus { ++ union { ++ struct aic_sdio_dev *sdio; ++ struct aic_usb_dev *usb; ++ } bus_priv; ++ struct device *dev; ++ struct aicwf_bus_ops *ops; ++ enum aicwf_bus_state state; ++ u8 *cmd_buf; ++ struct completion bustx_trgg; ++ struct completion busrx_trgg; ++ struct completion busirq_trgg;//new oob feature ++ struct task_struct *bustx_thread; ++ struct task_struct *busrx_thread; ++ struct task_struct *busirq_thread;//new oob feature ++}; ++ ++#ifdef CONFIG_SDIO_ADMA ++#define SDIO_HEADER_LEN 4 ++#define SDIO_DATA_FAKE_LEN 2 ++#define SDIO_MGMT_FAKE_LEN 4 ++#define ALIGN4_ADJ_LEN(x) ((4-(x&3))&3) ++ ++#define SDIO_TX_SLIST_MAX 136 ++ ++/*struct tx_scatterlist { ++ const void *buf; ++ unsigned int len; ++};*/ ++#endif ++ ++struct aicwf_tx_priv { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++ int fw_avail_bufcnt; ++ //for cmd tx ++ u8 *cmd_buf; ++ uint cmd_len; ++ bool cmd_txstate; ++ bool cmd_tx_succ; ++ struct semaphore cmd_txsema; ++ wait_queue_head_t cmd_txdone_wait; ++ //for data tx ++ atomic_t tx_pktcnt; ++ ++ struct frame_queue txq; ++ spinlock_t txqlock; ++ struct semaphore txctl_sema; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ struct sk_buff *aggr_buf; ++ atomic_t aggr_count; ++ u8 *head; ++ u8 *tail; ++ ++#ifdef CONFIG_SDIO_ADMA ++ struct tx_scatterlist sg_list[SDIO_TX_SLIST_MAX]; ++ void *free_buf[SDIO_TX_SLIST_MAX]; ++ bool copyd[SDIO_TX_SLIST_MAX]; ++ u32 aggr_segcnt; ++ u32 len; ++#endif ++}; ++ ++ ++#define DEFRAG_MAX_WAIT 40 //100 ++#ifdef AICWF_RX_REORDER ++#define MAX_REORD_RXFRAME 250 ++#define REORDER_UPDATE_TIME 50 ++#define AICWF_REORDER_WINSIZE 64 ++#define SN_LESS(a, b) (((a-b)&0x800) != 0) ++#define SN_EQUAL(a, b) (a == b) ++ ++struct reord_ctrl { ++ struct aicwf_rx_priv *rx_priv; ++ u8 enable; ++ u16 ind_sn; ++ u8 wsize_b; ++ spinlock_t reord_list_lock; ++ struct list_head reord_list; ++ struct timer_list reord_timer; ++ struct work_struct reord_timer_work; ++}; ++ ++struct reord_ctrl_info { ++ u8 mac_addr[6]; ++ struct reord_ctrl preorder_ctrl[8]; ++ struct list_head list; ++}; ++ ++struct recv_msdu { ++ struct sk_buff *pkt; ++ u8 tid; ++ u16 seq_num; ++ u8 forward; ++ //uint len; ++ u32 is_amsdu; ++ u8 *rx_data; ++ //for pending rx reorder list ++ struct list_head reord_pending_list; ++ //for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue ++ struct list_head rxframe_list; ++ struct reord_ctrl *preorder_ctrl; ++}; ++#endif ++ ++struct aicwf_rx_priv { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ ++ void *rwnx_vif; ++ atomic_t rx_cnt; ++ u32 data_len; ++ spinlock_t rxqlock; ++ #ifdef CONFIG_PREALLOC_RX_SKB ++ struct rx_frame_queue rxq; ++ #else ++ struct frame_queue rxq; ++ #endif ++ ++#ifdef AICWF_RX_REORDER ++ spinlock_t freeq_lock; ++ struct list_head rxframes_freequeue; ++ struct list_head stas_reord_list; ++ spinlock_t stas_reord_lock; ++ struct recv_msdu *recv_frames; ++#endif ++#ifdef CONFIG_PREALLOC_RX_SKB ++ spinlock_t rxbuff_lock; ++#endif ++}; ++ ++static inline int aicwf_bus_start(struct aicwf_bus *bus) ++{ ++ return bus->ops->start(bus->dev); ++} ++ ++static inline void aicwf_bus_stop(struct aicwf_bus *bus) ++{ ++ bus->ops->stop(bus->dev); ++} ++ ++static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb) ++{ ++ return bus->ops->txdata(bus->dev, skb); ++} ++ ++static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len) ++{ ++ return bus->ops->txmsg(bus->dev, msg, len); ++} ++ ++static inline void aicwf_sched_timeout(u32 millisec) ++{ ++ ulong timeout = 0, expires = 0; ++ expires = jiffies + msecs_to_jiffies(millisec); ++ timeout = millisec; ++ ++ while (timeout) { ++ timeout = schedule_timeout(timeout); ++ if (time_after(jiffies, expires)) ++ break; ++ } ++} ++ ++int aicwf_bus_init(uint bus_hdrlen, struct device *dev); ++void aicwf_bus_deinit(struct device *dev); ++void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv); ++void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv); ++struct aicwf_tx_priv *aicwf_tx_init(void *arg); ++struct aicwf_rx_priv *aicwf_rx_init(void *arg); ++void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len); ++void aicwf_frame_queue_flush(struct frame_queue *pq); ++bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio); ++bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt); ++bool aicwf_is_framequeue_empty(struct frame_queue *pq); ++void aicwf_frame_tx(void *dev, struct sk_buff *skb); ++void aicwf_dev_skb_free(struct sk_buff *skb); ++struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq); ++struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out); ++#ifdef CONFIG_PREALLOC_RX_SKB ++void rxbuff_queue_flush(struct aicwf_rx_priv* rx_priv); ++void aicwf_rxframe_queue_init_2(struct rx_frame_queue *pq, int max_len); ++void rxbuff_free(struct rx_buff *rxbuff); ++struct rx_buff *rxbuff_dequeue(struct rx_frame_queue *pq); ++bool aicwf_rxbuff_enqueue(struct device *dev, struct rx_frame_queue *rxq, struct rx_buff *pkt); ++extern struct aicwf_rx_buff_list aic_rx_buff_list; ++#endif ++ ++#endif /* _AICWF_TXRXIF_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c +new file mode 100644 +index 000000000000..9344217c2256 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c +@@ -0,0 +1,957 @@ ++/** ++ * aicwf_usb.c ++ * ++ * USB function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#include ++#include ++#include "aicwf_txrxif.h" ++#include "aicwf_usb.h" ++#include "rwnx_tx.h" ++#include "rwnx_defs.h" ++#include "usb_host.h" ++#include "rwnx_platform.h" ++ ++void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state) ++{ ++ struct rwnx_vif *rwnx_vif; ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (!rwnx_vif->up) ++ continue; ++ if (!rwnx_vif->ndev) ++ continue; ++ if (state) ++ netif_stop_queue(rwnx_vif->ndev); ++ else ++ netif_wake_queue(rwnx_vif->ndev); ++ } ++} ++ ++static struct aicwf_usb_buf *aicwf_usb_tx_dequeue(struct aic_usb_dev *usb_dev, ++ struct list_head *q, int *counter, spinlock_t *qlock) ++{ ++ unsigned long flags; ++ struct aicwf_usb_buf *usb_buf; ++ ++ spin_lock_irqsave(qlock, flags); ++ if (list_empty(q)) { ++ usb_buf = NULL; ++ } else { ++ usb_buf = list_first_entry(q, struct aicwf_usb_buf, list); ++ list_del_init(&usb_buf->list); ++ if (counter) ++ (*counter)--; ++ } ++ spin_unlock_irqrestore(qlock, flags); ++ return usb_buf; ++} ++ ++static void aicwf_usb_tx_queue(struct aic_usb_dev *usb_dev, ++ struct list_head *q, struct aicwf_usb_buf *usb_buf, int *counter, ++ spinlock_t *qlock) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(qlock, flags); ++ list_add_tail(&usb_buf->list, q); ++ (*counter)++; ++ spin_unlock_irqrestore(qlock, flags); ++} ++ ++static struct aicwf_usb_buf *aicwf_usb_rx_buf_get(struct aic_usb_dev *usb_dev) ++{ ++ unsigned long flags; ++ struct aicwf_usb_buf *usb_buf; ++ ++ spin_lock_irqsave(&usb_dev->rx_free_lock, flags); ++ if (list_empty(&usb_dev->rx_free_list)) { ++ usb_buf = NULL; ++ } else { ++ usb_buf = list_first_entry(&usb_dev->rx_free_list, struct aicwf_usb_buf, list); ++ list_del_init(&usb_buf->list); ++ } ++ spin_unlock_irqrestore(&usb_dev->rx_free_lock, flags); ++ return usb_buf; ++} ++ ++static void aicwf_usb_rx_buf_put(struct aic_usb_dev *usb_dev, struct aicwf_usb_buf *usb_buf) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&usb_dev->rx_free_lock, flags); ++ list_add_tail(&usb_buf->list, &usb_dev->rx_free_list); ++ spin_unlock_irqrestore(&usb_dev->rx_free_lock, flags); ++} ++ ++static void aicwf_usb_tx_complete(struct urb *urb) ++{ ++ unsigned long flags; ++ struct aicwf_usb_buf *usb_buf = (struct aicwf_usb_buf *) urb->context; ++ struct aic_usb_dev *usb_dev = usb_buf->usbdev; ++ struct sk_buff *skb; ++ u8 *buf; ++ ++ if (usb_buf->cfm == false) { ++ skb = usb_buf->skb; ++ } else { ++ buf = (u8 *)usb_buf->skb; ++ } ++ ++ if (usb_buf->cfm == false) { ++ dev_kfree_skb_any(skb); ++ } else { ++ kfree(buf); ++ } ++ usb_buf->skb = NULL; ++ ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ ++ spin_lock_irqsave(&usb_dev->tx_flow_lock, flags); ++ if (usb_dev->tx_free_count > AICWF_USB_TX_HIGH_WATER) { ++ if (usb_dev->tbusy) { ++ usb_dev->tbusy = false; ++ aicwf_usb_tx_flowctrl(usb_dev->rwnx_hw, false); ++ } ++ } ++ spin_unlock_irqrestore(&usb_dev->tx_flow_lock, flags); ++ } ++ ++static void aicwf_usb_rx_complete(struct urb *urb) ++{ ++ struct aicwf_usb_buf *usb_buf = (struct aicwf_usb_buf *) urb->context; ++ struct aic_usb_dev *usb_dev = usb_buf->usbdev; ++ struct aicwf_rx_priv *rx_priv = usb_dev->rx_priv; ++ struct sk_buff *skb = NULL; ++ unsigned long flags = 0; ++ ++ skb = usb_buf->skb; ++ usb_buf->skb = NULL; ++ ++ if (urb->actual_length > urb->transfer_buffer_length) { ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ schedule_work(&usb_dev->rx_urb_work); ++ return; ++ } ++ ++ if (urb->status != 0 || !urb->actual_length) { ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ schedule_work(&usb_dev->rx_urb_work); ++ return; ++ } ++ ++ if (usb_dev->state == USB_UP_ST) { ++ skb_put(skb, urb->actual_length); ++ ++ spin_lock_irqsave(&rx_priv->rxqlock, flags); ++ if (!aicwf_rxframe_enqueue(usb_dev->dev, &rx_priv->rxq, skb)) { ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ usb_err("rx_priv->rxq is over flow!!!\n"); ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ return; ++ } ++ spin_unlock_irqrestore(&rx_priv->rxqlock, flags); ++ atomic_inc(&rx_priv->rx_cnt); ++ complete(&rx_priv->usbdev->bus_if->busrx_trgg); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ ++ schedule_work(&usb_dev->rx_urb_work); ++ } else { ++ aicwf_dev_skb_free(skb); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ } ++} ++ ++static int aicwf_usb_submit_rx_urb(struct aic_usb_dev *usb_dev, ++ struct aicwf_usb_buf *usb_buf) ++{ ++ struct sk_buff *skb; ++ int ret; ++ ++ if (!usb_buf || !usb_dev) ++ return -1; ++ ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("usb state is not up!\n"); ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ return -1; ++ } ++ ++ skb = __dev_alloc_skb(AICWF_USB_MAX_PKT_SIZE, GFP_KERNEL); ++ if (!skb) { ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ return -1; ++ } ++ ++ usb_buf->skb = skb; ++ ++ usb_fill_bulk_urb(usb_buf->urb, ++ usb_dev->udev, ++ usb_dev->bulk_in_pipe, ++ skb->data, skb_tailroom(skb), aicwf_usb_rx_complete, usb_buf); ++ ++ usb_buf->usbdev = usb_dev; ++ ++ usb_anchor_urb(usb_buf->urb, &usb_dev->rx_submitted); ++ ret = usb_submit_urb(usb_buf->urb, GFP_ATOMIC); ++ if (ret) { ++ usb_err("usb submit rx urb fail:%d\n", ret); ++ usb_unanchor_urb(usb_buf->urb); ++ aicwf_dev_skb_free(usb_buf->skb); ++ usb_buf->skb = NULL; ++ aicwf_usb_rx_buf_put(usb_dev, usb_buf); ++ ++ msleep(100); ++ } ++ return 0; ++} ++ ++static void aicwf_usb_rx_submit_all_urb(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf; ++ ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("bus is not up=%d\n", usb_dev->state); ++ return; ++ } ++ ++ while ((usb_buf = aicwf_usb_rx_buf_get(usb_dev)) != NULL) { ++ if (aicwf_usb_submit_rx_urb(usb_dev, usb_buf)) { ++ usb_err("usb rx refill fail\n"); ++ if (usb_dev->state != USB_UP_ST) ++ return; ++ } ++ } ++} ++ ++static void aicwf_usb_rx_prepare(struct aic_usb_dev *usb_dev) ++{ ++ aicwf_usb_rx_submit_all_urb(usb_dev); ++} ++ ++static void aicwf_usb_tx_prepare(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf; ++ ++ while (!list_empty(&usb_dev->tx_post_list)) { ++ usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_post_list, ++ &usb_dev->tx_post_count, &usb_dev->tx_post_lock); ++ if (usb_buf->skb) { ++ dev_kfree_skb(usb_buf->skb); ++ usb_buf->skb = NULL; ++ } ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ } ++} ++static void aicwf_usb_tx_process(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf; ++ int ret = 0; ++ u8 *data = NULL; ++ ++ while (!list_empty(&usb_dev->tx_post_list)) { ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("usb state is not up!\n"); ++ return; ++ } ++ ++ usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_post_list, ++ &usb_dev->tx_post_count, &usb_dev->tx_post_lock); ++ if (!usb_buf) { ++ usb_err("can not get usb_buf from tx_post_list!\n"); ++ return; ++ } ++ data = usb_buf->skb->data; ++ ++ ret = usb_submit_urb(usb_buf->urb, GFP_ATOMIC); ++ if (ret) { ++ usb_err("aicwf_usb_bus_tx usb_submit_urb FAILED\n"); ++ goto fail; ++ } ++ ++ continue; ++fail: ++ dev_kfree_skb(usb_buf->skb); ++ usb_buf->skb = NULL; ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ } ++} ++ ++int usb_bustx_thread(void *data) ++{ ++ struct aicwf_bus *bus = (struct aicwf_bus *)data; ++ struct aic_usb_dev *usbdev = bus->bus_priv.usb; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ usb_err("usb bustx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if (usbdev->bus_if->state == BUS_DOWN_ST) ++ continue; ++ if (usbdev->tx_post_count > 0) ++ aicwf_usb_tx_process(usbdev); ++ } ++ } ++ ++ return 0; ++} ++ ++int usb_busrx_thread(void *data) ++{ ++ struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; ++ struct aicwf_bus *bus_if = rx_priv->usbdev->bus_if; ++ ++ while (1) { ++ if (kthread_should_stop()) { ++ usb_err("usb busrx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ if (bus_if->state == BUS_DOWN_ST) ++ continue; ++ aicwf_process_rxframes(rx_priv); ++ } ++ } ++ ++ return 0; ++} ++ ++static void aicwf_usb_send_msg_complete(struct urb *urb) ++{ ++ struct aic_usb_dev *usb_dev = (struct aic_usb_dev *) urb->context; ++ ++ usb_dev->msg_finished = true; ++ if (waitqueue_active(&usb_dev->msg_wait)) ++ wake_up(&usb_dev->msg_wait); ++} ++ ++static int aicwf_usb_bus_txmsg(struct device *dev, u8 *buf, u32 len) ++{ ++ int ret = 0; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ ++ if (usb_dev->state != USB_UP_ST) ++ return -EIO; ++ ++ if (buf == NULL || len == 0 || usb_dev->msg_out_urb == NULL) ++ return -EINVAL; ++ ++ if (test_and_set_bit(0, &usb_dev->msg_busy)) { ++ usb_err("In a control frame option, can't tx!\n"); ++ return -EIO; ++ } ++ ++ usb_dev->msg_finished = false; ++ ++ usb_fill_bulk_urb(usb_dev->msg_out_urb, ++ usb_dev->udev, ++ usb_dev->bulk_out_pipe, ++ buf, len, (usb_complete_t) aicwf_usb_send_msg_complete, usb_dev); ++ usb_dev->msg_out_urb->transfer_flags |= URB_ZERO_PACKET; ++ ++ ret = usb_submit_urb(usb_dev->msg_out_urb, GFP_ATOMIC); ++ if (ret) { ++ usb_err("usb_submit_urb failed %d\n", ret); ++ goto exit; ++ } ++ ++ ret = wait_event_timeout(usb_dev->msg_wait, ++ usb_dev->msg_finished, msecs_to_jiffies(CMD_TX_TIMEOUT)); ++ if (!ret) { ++ if (usb_dev->msg_out_urb) ++ usb_kill_urb(usb_dev->msg_out_urb); ++ usb_err("Txmsg wait timed out\n"); ++ ret = -EIO; ++ goto exit; ++ } ++ ++ if (usb_dev->msg_finished == false) { ++ usb_err("Txmsg timed out\n"); ++ ret = -ETIMEDOUT; ++ goto exit; ++ } ++exit: ++ clear_bit(0, &usb_dev->msg_busy); ++ return ret; ++} ++ ++ ++static void aicwf_usb_free_urb(struct list_head *q, spinlock_t *qlock) ++{ ++ struct aicwf_usb_buf *usb_buf, *tmp; ++ unsigned long flags; ++ ++ spin_lock_irqsave(qlock, flags); ++ list_for_each_entry_safe(usb_buf, tmp, q, list) { ++ spin_unlock_irqrestore(qlock, flags); ++ if (!usb_buf->urb) { ++ usb_err("bad usb_buf\n"); ++ spin_lock_irqsave(qlock, flags); ++ break; ++ } ++ usb_free_urb(usb_buf->urb); ++ list_del_init(&usb_buf->list); ++ spin_lock_irqsave(qlock, flags); ++ } ++ spin_unlock_irqrestore(qlock, flags); ++} ++ ++static int aicwf_usb_alloc_rx_urb(struct aic_usb_dev *usb_dev) ++{ ++ int i; ++ ++ for (i = 0; i < AICWF_USB_RX_URBS; i++) { ++ struct aicwf_usb_buf *usb_buf = &usb_dev->usb_rx_buf[i]; ++ ++ usb_buf->usbdev = usb_dev; ++ usb_buf->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!usb_buf->urb) { ++ usb_err("could not allocate rx data urb\n"); ++ goto err; ++ } ++ list_add_tail(&usb_buf->list, &usb_dev->rx_free_list); ++ } ++ return 0; ++ ++err: ++ aicwf_usb_free_urb(&usb_dev->rx_free_list, &usb_dev->rx_free_lock); ++ return -ENOMEM; ++} ++ ++static int aicwf_usb_alloc_tx_urb(struct aic_usb_dev *usb_dev) ++{ ++ int i; ++ ++ for (i = 0; i < AICWF_USB_TX_URBS; i++) { ++ struct aicwf_usb_buf *usb_buf = &usb_dev->usb_tx_buf[i]; ++ ++ usb_buf->usbdev = usb_dev; ++ usb_buf->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!usb_buf->urb) { ++ usb_err("could not allocate tx data urb\n"); ++ goto err; ++ } ++ list_add_tail(&usb_buf->list, &usb_dev->tx_free_list); ++ (usb_dev->tx_free_count)++; ++ } ++ return 0; ++ ++err: ++ aicwf_usb_free_urb(&usb_dev->tx_free_list, &usb_dev->tx_free_lock); ++ return -ENOMEM; ++} ++ ++ ++static void aicwf_usb_state_change(struct aic_usb_dev *usb_dev, int state) ++{ ++ int old_state; ++ ++ if (usb_dev->state == state) ++ return; ++ ++ old_state = usb_dev->state; ++ usb_dev->state = state; ++ ++ if (state == USB_DOWN_ST) { ++ usb_dev->bus_if->state = BUS_DOWN_ST; ++ } ++ if (state == USB_UP_ST) { ++ usb_dev->bus_if->state = BUS_UP_ST; ++ } ++} ++ ++static int aicwf_usb_bus_txdata(struct device *dev, struct sk_buff *skb) ++{ ++ u8 *buf; ++ u16 buf_len = 0; ++ u16 adjust_len = 0; ++ struct aicwf_usb_buf *usb_buf; ++ int ret = 0; ++ unsigned long flags; ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)skb->data; ++ struct rwnx_hw *rwnx_hw = usb_dev->rwnx_hw; ++ u8 usb_header[4]; ++ u8 adj_buf[4] = {0}; ++ u16 index = 0; ++ bool need_cfm = false; ++ ++ if (usb_dev->state != USB_UP_ST) { ++ usb_err("usb state is not up!\n"); ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ dev_kfree_skb_any(skb); ++ return -EIO; ++ } ++ ++ usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_free_list, ++ &usb_dev->tx_free_count, &usb_dev->tx_free_lock); ++ if (!usb_buf) { ++ usb_err("free:%d, post:%d\n", usb_dev->tx_free_count, usb_dev->tx_post_count); ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ dev_kfree_skb_any(skb); ++ ret = -ENOMEM; ++ goto flow_ctrl; ++ } ++ ++ if (txhdr->sw_hdr->need_cfm) { ++ need_cfm = true; ++ buf = kmalloc(skb->len, GFP_KERNEL); ++ index += sizeof(usb_header); ++ memcpy(&buf[index], (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ index += sizeof(struct txdesc_api); ++ memcpy(&buf[index], &skb->data[txhdr->sw_hdr->headroom], skb->len - txhdr->sw_hdr->headroom); ++ index += skb->len - txhdr->sw_hdr->headroom; ++ buf_len = index; ++ if (buf_len & (TX_ALIGNMENT - 1)) { ++ adjust_len = roundup(buf_len, TX_ALIGNMENT)-buf_len; ++ memcpy(&buf[buf_len], adj_buf, adjust_len); ++ buf_len += adjust_len; ++ } ++ usb_header[0] = ((buf_len) & 0xff); ++ usb_header[1] = (((buf_len) >> 8)&0x0f); ++ usb_header[2] = 0x01; //data ++ usb_header[3] = 0; //reserved ++ memcpy(&buf[0], usb_header, sizeof(usb_header)); ++ usb_buf->skb = (struct sk_buff *)buf; ++ } else { ++ skb_pull(skb, txhdr->sw_hdr->headroom); ++ skb_push(skb, sizeof(struct txdesc_api)); ++ memcpy(&skb->data[0], (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); ++ ++ skb_push(skb, sizeof(usb_header)); ++ usb_header[0] = ((skb->len) & 0xff); ++ usb_header[1] = (((skb->len) >> 8)&0x0f); ++ usb_header[2] = 0x01; //data ++ usb_header[3] = 0; //reserved ++ memcpy(&skb->data[0], usb_header, sizeof(usb_header)); ++ ++ buf = skb->data; ++ buf_len = skb->len; ++ ++ usb_buf->skb = skb; ++ } ++ usb_buf->usbdev = usb_dev; ++ if (need_cfm) ++ usb_buf->cfm = true; ++ else ++ usb_buf->cfm = false; ++ usb_fill_bulk_urb(usb_buf->urb, usb_dev->udev, usb_dev->bulk_out_pipe, ++ buf, buf_len, aicwf_usb_tx_complete, usb_buf); ++ usb_buf->urb->transfer_flags |= URB_ZERO_PACKET; ++ ++ aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_post_list, usb_buf, ++ &usb_dev->tx_post_count, &usb_dev->tx_post_lock); ++ complete(&bus_if->bustx_trgg); ++ ret = 0; ++ ++ flow_ctrl: ++ spin_lock_irqsave(&usb_dev->tx_flow_lock, flags); ++ if (usb_dev->tx_free_count < AICWF_USB_TX_LOW_WATER) { ++ usb_dev->tbusy = true; ++ aicwf_usb_tx_flowctrl(usb_dev->rwnx_hw, true); ++ } ++ spin_unlock_irqrestore(&usb_dev->tx_flow_lock, flags); ++ ++ return ret; ++} ++ ++static int aicwf_usb_bus_start(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ ++ if (usb_dev->state == USB_UP_ST) ++ return 0; ++ ++ aicwf_usb_state_change(usb_dev, USB_UP_ST); ++ aicwf_usb_rx_prepare(usb_dev); ++ aicwf_usb_tx_prepare(usb_dev); ++ return 0; ++} ++ ++static void aicwf_usb_cancel_all_urbs(struct aic_usb_dev *usb_dev) ++{ ++ struct aicwf_usb_buf *usb_buf, *tmp; ++ unsigned long flags; ++ ++ if (usb_dev->msg_out_urb) ++ usb_kill_urb(usb_dev->msg_out_urb); ++ ++ spin_lock_irqsave(&usb_dev->tx_post_lock, flags); ++ list_for_each_entry_safe(usb_buf, tmp, &usb_dev->tx_post_list, list) { ++ spin_unlock_irqrestore(&usb_dev->tx_post_lock, flags); ++ if (!usb_buf->urb) { ++ usb_err("bad usb_buf\n"); ++ spin_lock_irqsave(&usb_dev->tx_post_lock, flags); ++ break; ++ } ++ usb_kill_urb(usb_buf->urb); ++ spin_lock_irqsave(&usb_dev->tx_post_lock, flags); ++ } ++ spin_unlock_irqrestore(&usb_dev->tx_post_lock, flags); ++ ++ usb_kill_anchored_urbs(&usb_dev->rx_submitted); ++} ++ ++static void aicwf_usb_bus_stop(struct device *dev) ++{ ++ struct aicwf_bus *bus_if = dev_get_drvdata(dev); ++ struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; ++ ++ usb_dbg("%s\r\n", __func__); ++ if (usb_dev == NULL) ++ return; ++ ++ if (usb_dev->state == USB_DOWN_ST) ++ return; ++ ++ aicwf_usb_state_change(usb_dev, USB_DOWN_ST); ++ aicwf_usb_cancel_all_urbs(usb_dev); ++} ++ ++static void aicwf_usb_deinit(struct aic_usb_dev *usbdev) ++{ ++ cancel_work_sync(&usbdev->rx_urb_work); ++ aicwf_usb_free_urb(&usbdev->rx_free_list, &usbdev->rx_free_lock); ++ aicwf_usb_free_urb(&usbdev->tx_free_list, &usbdev->tx_free_lock); ++ usb_free_urb(usbdev->msg_out_urb); ++} ++ ++static void aicwf_usb_rx_urb_work(struct work_struct *work) ++{ ++ struct aic_usb_dev *usb_dev = container_of(work, struct aic_usb_dev, rx_urb_work); ++ ++ aicwf_usb_rx_submit_all_urb(usb_dev); ++} ++ ++static int aicwf_usb_init(struct aic_usb_dev *usb_dev) ++{ ++ int ret = 0; ++ ++ usb_dev->tbusy = false; ++ usb_dev->state = USB_DOWN_ST; ++ ++ init_waitqueue_head(&usb_dev->msg_wait); ++ init_usb_anchor(&usb_dev->rx_submitted); ++ ++ spin_lock_init(&usb_dev->tx_free_lock); ++ spin_lock_init(&usb_dev->tx_post_lock); ++ spin_lock_init(&usb_dev->rx_free_lock); ++ spin_lock_init(&usb_dev->tx_flow_lock); ++ ++ INIT_LIST_HEAD(&usb_dev->rx_free_list); ++ INIT_LIST_HEAD(&usb_dev->tx_free_list); ++ INIT_LIST_HEAD(&usb_dev->tx_post_list); ++ ++ usb_dev->tx_free_count = 0; ++ usb_dev->tx_post_count = 0; ++ ++ ret = aicwf_usb_alloc_rx_urb(usb_dev); ++ if (ret) { ++ goto error; ++ } ++ ret = aicwf_usb_alloc_tx_urb(usb_dev); ++ if (ret) { ++ goto error; ++ } ++ ++ ++ usb_dev->msg_out_urb = usb_alloc_urb(0, GFP_ATOMIC); ++ if (!usb_dev->msg_out_urb) { ++ usb_err("usb_alloc_urb (msg out) failed\n"); ++ ret = ENOMEM; ++ goto error; ++ } ++ ++ INIT_WORK(&usb_dev->rx_urb_work, aicwf_usb_rx_urb_work); ++ ++ return ret; ++ error: ++ usb_err("failed!\n"); ++ aicwf_usb_deinit(usb_dev); ++ return ret; ++} ++ ++ ++static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *interface) ++{ ++ struct usb_interface_descriptor *interface_desc; ++ struct usb_host_interface *host_interface; ++ struct usb_endpoint_descriptor *endpoint; ++ struct usb_device *usb = usb_dev->udev; ++ int i, endpoints; ++ u8 endpoint_num; ++ int ret = 0; ++ ++ usb_dev->bulk_in_pipe = 0; ++ usb_dev->bulk_out_pipe = 0; ++ ++ host_interface = &interface->altsetting[0]; ++ interface_desc = &host_interface->desc; ++ endpoints = interface_desc->bNumEndpoints; ++ ++ /* Check device configuration */ ++ if (usb->descriptor.bNumConfigurations != 1) { ++ usb_err("Number of configurations: %d not supported\n", ++ usb->descriptor.bNumConfigurations); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ /* Check deviceclass */ ++#ifndef CONFIG_USB_BT ++ if (usb->descriptor.bDeviceClass != 0x00) { ++ usb_err("DeviceClass %d not supported\n", ++ usb->descriptor.bDeviceClass); ++ ret = -ENODEV; ++ goto exit; ++ } ++#endif ++ ++ /* Check interface number */ ++#ifdef CONFIG_USB_BT ++ if (usb->actconfig->desc.bNumInterfaces != 3) { ++#else ++ if (usb->actconfig->desc.bNumInterfaces != 1) { ++#endif ++ usb_err("Number of interfaces: %d not supported\n", ++ usb->actconfig->desc.bNumInterfaces); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ if ((interface_desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || ++ (interface_desc->bInterfaceSubClass != 0xff) || ++ (interface_desc->bInterfaceProtocol != 0xff)) { ++ usb_err("non WLAN interface %d: 0x%x:0x%x:0x%x\n", ++ interface_desc->bInterfaceNumber, interface_desc->bInterfaceClass, ++ interface_desc->bInterfaceSubClass, interface_desc->bInterfaceProtocol); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ for (i = 0; i < endpoints; i++) { ++ endpoint = &host_interface->endpoint[i].desc; ++ endpoint_num = usb_endpoint_num(endpoint); ++ ++ if (usb_endpoint_dir_in(endpoint) && ++ usb_endpoint_xfer_bulk(endpoint)) { ++ if (!usb_dev->bulk_in_pipe) { ++ usb_dev->bulk_in_pipe = usb_rcvbulkpipe(usb, endpoint_num); ++ } ++ } ++ ++ if (usb_endpoint_dir_out(endpoint) && ++ usb_endpoint_xfer_bulk(endpoint)) { ++ if (!usb_dev->bulk_out_pipe) { ++ usb_dev->bulk_out_pipe = usb_sndbulkpipe(usb, endpoint_num); ++ } ++ } ++ } ++ ++ if (usb_dev->bulk_in_pipe == 0) { ++ usb_err("No RX (in) Bulk EP found\n"); ++ ret = -ENODEV; ++ goto exit; ++ } ++ if (usb_dev->bulk_out_pipe == 0) { ++ usb_err("No TX (out) Bulk EP found\n"); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ if (usb->speed == USB_SPEED_HIGH) ++ printk("Aic high speed USB device detected\n"); ++ else ++ printk("Aic full speed USB device detected\n"); ++ ++ exit: ++ return ret; ++} ++ ++ ++ ++static struct aicwf_bus_ops aicwf_usb_bus_ops = { ++ .start = aicwf_usb_bus_start, ++ .stop = aicwf_usb_bus_stop, ++ .txdata = aicwf_usb_bus_txdata, ++ .txmsg = aicwf_usb_bus_txmsg, ++}; ++ ++static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ++{ ++ int ret = 0; ++ struct usb_device *usb = interface_to_usbdev(intf); ++ struct aicwf_bus *bus_if ; ++ struct device *dev = NULL; ++ struct aicwf_rx_priv *rx_priv = NULL; ++ struct aic_usb_dev *usb_dev = NULL; ++ ++ usb_dev = kzalloc(sizeof(struct aic_usb_dev), GFP_ATOMIC); ++ if (!usb_dev) { ++ return -ENOMEM; ++ } ++ ++ usb_dev->udev = usb; ++ usb_dev->dev = &usb->dev; ++ usb_set_intfdata(intf, usb_dev); ++ ++ ret = aicwf_parse_usb(usb_dev, intf); ++ if (ret) { ++ usb_err("aicwf_parse_usb err %d\n", ret); ++ goto out_free; ++ } ++ ++ ret = aicwf_usb_init(usb_dev); ++ if (ret) { ++ usb_err("aicwf_usb_init err %d\n", ret); ++ goto out_free; ++ } ++ ++ bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_ATOMIC); ++ if (!bus_if) { ++ ret = -ENOMEM; ++ goto out_free_usb; ++ } ++ ++ dev = usb_dev->dev; ++ bus_if->dev = dev; ++ usb_dev->bus_if = bus_if; ++ bus_if->bus_priv.usb = usb_dev; ++ dev_set_drvdata(dev, bus_if); ++ ++ bus_if->ops = &aicwf_usb_bus_ops; ++ ++ rx_priv = aicwf_rx_init(usb_dev); ++ if (!rx_priv) { ++ txrx_err("rx init failed\n"); ++ ret = -1; ++ goto out_free_bus; ++ } ++ usb_dev->rx_priv = rx_priv; ++ ++ ret = aicwf_bus_init(0, dev); ++ if (ret < 0) { ++ usb_err("aicwf_bus_init err %d\n", ret); ++ goto out_free_bus; ++ } ++ ++ ret = aicwf_bus_start(bus_if); ++ if (ret < 0) { ++ usb_err("aicwf_bus_start err %d\n", ret); ++ goto out_free_bus; ++ } ++ ++ aicwf_rwnx_usb_platform_init(usb_dev); ++ aicwf_hostif_ready(); ++ return 0; ++ ++out_free_bus: ++ aicwf_bus_deinit(dev); ++ kfree(bus_if); ++out_free_usb: ++ aicwf_usb_deinit(usb_dev); ++out_free: ++ usb_err("failed with errno %d\n", ret); ++ kfree(usb_dev); ++ usb_set_intfdata(intf, NULL); ++ return ret; ++} ++ ++static void aicwf_usb_disconnect(struct usb_interface *intf) ++{ ++ struct aic_usb_dev *usb_dev = ++ (struct aic_usb_dev *) usb_get_intfdata(intf); ++ ++ if (!usb_dev) ++ return; ++ ++ aicwf_bus_deinit(usb_dev->dev); ++ aicwf_usb_deinit(usb_dev); ++ rwnx_cmd_mgr_deinit(&usb_dev->cmd_mgr); ++ ++ if (usb_dev->rx_priv) ++ aicwf_rx_deinit(usb_dev->rx_priv); ++ kfree(usb_dev->bus_if); ++ kfree(usb_dev); ++} ++ ++static int aicwf_usb_suspend(struct usb_interface *intf, pm_message_t state) ++{ ++ struct aic_usb_dev *usb_dev = ++ (struct aic_usb_dev *) usb_get_intfdata(intf); ++ ++ aicwf_usb_state_change(usb_dev, USB_SLEEP_ST); ++ aicwf_bus_stop(usb_dev->bus_if); ++ return 0; ++} ++ ++static int aicwf_usb_resume(struct usb_interface *intf) ++{ ++ struct aic_usb_dev *usb_dev = ++ (struct aic_usb_dev *) usb_get_intfdata(intf); ++ ++ if (usb_dev->state == USB_UP_ST) ++ return 0; ++ ++ aicwf_bus_start(usb_dev->bus_if); ++ return 0; ++} ++ ++static int aicwf_usb_reset_resume(struct usb_interface *intf) ++{ ++ return aicwf_usb_resume(intf); ++} ++ ++static struct usb_device_id aicwf_usb_id_table[] = { ++#ifndef CONFIG_USB_BT ++ {USB_DEVICE(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC)}, ++#else ++ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC, 0xff, 0xff, 0xff)}, ++#endif ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(usb, aicwf_usb_id_table); ++ ++static struct usb_driver aicwf_usbdrvr = { ++ .name = KBUILD_MODNAME, ++ .probe = aicwf_usb_probe, ++ .disconnect = aicwf_usb_disconnect, ++ .id_table = aicwf_usb_id_table, ++ .suspend = aicwf_usb_suspend, ++ .resume = aicwf_usb_resume, ++ .reset_resume = aicwf_usb_reset_resume, ++ .supports_autosuspend = 1, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) ++ .disable_hub_initiated_lpm = 1, ++#endif ++}; ++ ++void aicwf_usb_register(void) ++{ ++ if (usb_register(&aicwf_usbdrvr) < 0) { ++ usb_err("usb_register failed\n"); ++ } ++} ++ ++void aicwf_usb_exit(void) ++{ ++ if (g_rwnx_plat && g_rwnx_plat->enabled) ++ rwnx_platform_deinit(g_rwnx_plat->usbdev->rwnx_hw); ++ usb_deregister(&aicwf_usbdrvr); ++ kfree(g_rwnx_plat); ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h +new file mode 100644 +index 000000000000..cc3619b2dfe0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h +@@ -0,0 +1,99 @@ ++/** ++ * aicwf_usb.h ++ * ++ * USB function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++#ifndef _AICWF_USB_H_ ++#define _AICWF_USB_H_ ++ ++#include ++#include "rwnx_cmds.h" ++ ++#ifdef AICWF_USB_SUPPORT ++ ++/* USB Device ID */ ++#define USB_VENDOR_ID_AIC 0xA69C ++ ++#ifndef CONFIG_USB_BT ++#define USB_PRODUCT_ID_AIC 0x8800 ++#else ++#define USB_PRODUCT_ID_AIC 0x8801 ++#endif ++ ++#define AICWF_USB_RX_URBS (200) ++#define AICWF_USB_TX_URBS (100) ++#define AICWF_USB_TX_LOW_WATER (AICWF_USB_TX_URBS/4) ++#define AICWF_USB_TX_HIGH_WATER (AICWF_USB_TX_LOW_WATER*3) ++#define AICWF_USB_MAX_PKT_SIZE (2048) ++ ++typedef enum { ++ USB_TYPE_DATA = 0X00, ++ USB_TYPE_CFG = 0X10, ++ USB_TYPE_CFG_CMD_RSP = 0X11, ++ USB_TYPE_CFG_DATA_CFM = 0X12 ++} usb_type; ++ ++enum aicwf_usb_state { ++ USB_DOWN_ST, ++ USB_UP_ST, ++ USB_SLEEP_ST ++}; ++ ++struct aicwf_usb_buf { ++ struct list_head list; ++ struct aic_usb_dev *usbdev; ++ struct urb *urb; ++ struct sk_buff *skb; ++ bool cfm; ++}; ++ ++struct aic_usb_dev { ++ struct rwnx_hw *rwnx_hw; ++ struct aicwf_bus *bus_if; ++ struct usb_device *udev; ++ struct device *dev; ++ struct aicwf_rx_priv *rx_priv; ++ enum aicwf_usb_state state; ++ struct rwnx_cmd_mgr cmd_mgr; ++ ++ struct usb_anchor rx_submitted; ++ struct work_struct rx_urb_work; ++ ++ spinlock_t rx_free_lock; ++ spinlock_t tx_free_lock; ++ spinlock_t tx_post_lock; ++ spinlock_t tx_flow_lock; ++ ++ struct list_head rx_free_list; ++ struct list_head tx_free_list; ++ struct list_head tx_post_list; ++ ++ uint bulk_in_pipe; ++ uint bulk_out_pipe; ++ ++ int tx_free_count; ++ int tx_post_count; ++ ++ struct aicwf_usb_buf usb_tx_buf[AICWF_USB_TX_URBS]; ++ struct aicwf_usb_buf usb_rx_buf[AICWF_USB_RX_URBS]; ++ ++ int msg_finished; ++ wait_queue_head_t msg_wait; ++ ulong msg_busy; ++ struct urb *msg_out_urb; ++ ++ bool tbusy; ++}; ++ ++extern void aicwf_usb_exit(void); ++extern void aicwf_usb_register(void); ++extern void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state); ++int usb_bustx_thread(void *data); ++int usb_busrx_thread(void *data); ++extern void aicwf_hostif_ready(void); ++ ++#endif /* AICWF_USB_SUPPORT */ ++#endif /* _AICWF_USB_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/btsdio.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/btsdio.c +new file mode 100644 +index 000000000000..81c5c1ae1e98 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/btsdio.c +@@ -0,0 +1,298 @@ ++/* ++ * ++ * Generic Bluetooth SDIO driver ++ * ++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd. ++ * Copyright (C) 2007 Marcel Holtmann ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++ ++#include "aic_btsdio.h" ++#include "rwnx_msg_tx.h" ++ ++#include ++ ++#define VERSION "0.1" ++#if CONFIG_BLUEDROID == 0 ++struct btsdio_data { ++ struct hci_dev *hdev; ++ ++ struct work_struct work; ++ ++ struct sk_buff_head txq; ++}; ++struct hci_dev *ghdev = NULL; ++ ++void bt_data_dump(char* tag, void* data, unsigned long len){ ++ unsigned long i = 0; ++ uint8_t* data_ = (uint8_t* )data; ++ ++ printk("%s %s len:(%lu)\r\n", __func__, tag, len); ++ ++ for (i = 0; i < len; i += 16){ ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", ++ data_[0 + i], ++ data_[1 + i], ++ data_[2 + i], ++ data_[3 + i], ++ data_[4 + i], ++ data_[5 + i], ++ data_[6 + i], ++ data_[7 + i], ++ data_[8 + i], ++ data_[9 + i], ++ data_[10 + i], ++ data_[11 + i], ++ data_[12 + i], ++ data_[13 + i], ++ data_[14 + i], ++ data_[15 + i]); ++ } ++ ++} ++ ++static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) ++{ ++ int err; ++ ++ AICBT_INFO("%s", data->hdev->name); ++ ++ /* Prepend Type-A header */ ++ skb_push(skb, 1); ++ skb->data[0] = hci_skb_pkt_type(skb); ++ ++ //bt_data_dump("btwrite", skb->data, skb->len); ++ err = rwnx_sdio_bt_send_req(g_rwnx_plat->sdiodev->rwnx_hw, skb->len, skb); ++ if(err<0){ ++ printk("%s rwnx_sdio_bt_send_req error %d",__func__,err); ++ return err; ++ } ++ ++ data->hdev->stat.byte_tx += skb->len; ++ ++ kfree_skb(skb); ++ ++ return 0; ++} ++ ++static void btsdio_work(struct work_struct *work) ++{ ++ struct btsdio_data *data = container_of(work, struct btsdio_data, work); ++ struct sk_buff *skb; ++ int err; ++ ++ AICBT_INFO("%s,%s", data->hdev->name,__func__); ++ ++ ++ while ((skb = skb_dequeue(&data->txq))) { ++ err = btsdio_tx_packet(data, skb); ++ if (err < 0) { ++ data->hdev->stat.err_tx++; ++ skb_queue_head(&data->txq, skb); ++ break; ++ } ++ } ++} ++ ++/* Get HCI device by index. ++ * Device is held on return. */ ++struct hci_dev *hci_dev_get(int index) ++{ ++ if (index != 0) ++ return NULL; ++ ++ return ghdev; ++} ++ ++int bt_sdio_recv(u8 *data,u32 data_len) ++{ ++ struct sk_buff *skb; ++ int type= data[0]; ++ struct hci_dev *hdev; ++ u32 len = data_len; ++ int ret=0; ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICWFDBG(LOGERROR,"%s: Failed to get hci dev[NULL]", __func__); ++ return -ENODEV; ++ } ++ ++ skb = alloc_skb(len-1,GFP_ATOMIC); ++ if(!skb){ ++ AICWFDBG(LOGERROR, "alloc skb fail %s \n",__func__); ++ } ++ memcpy(skb_put(skb,len-1) ,(data+1), len-1); ++ hdev->stat.byte_rx += len; ++ hci_skb_pkt_type(skb) = type; ++ //if(bt_bypass_event(skb)){ ++ //kfree_skb(skb); ++ ///return 0; ++ //} ++ AICBT_INFO("skb type %d",type); ++ //bt_data_dump("bt_skb", skb, skb->len); ++ ret = hci_recv_frame(hdev, skb); ++ if(ret < 0){ ++ AICWFDBG(LOGERROR, "hci_recv_frame fail %d\n",ret); ++ hdev->stat.err_rx++; ++ kfree_skb(skb); ++ } ++ return 0; ++} ++ ++static int btsdio_open(struct hci_dev *hdev) ++{ ++ //struct btsdio_data *data = hci_get_drvdata(hdev); ++ int err = 0; ++ ++ AICBT_INFO("%s", hdev->name); ++ ++ return err; ++} ++ ++static int btsdio_close(struct hci_dev *hdev) ++{ ++ //struct btsdio_data *data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("%s,%s", hdev->name,__func__); ++ ++ return 0; ++} ++ ++static int btsdio_flush(struct hci_dev *hdev) ++{ ++ struct btsdio_data *data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("%s,%s", hdev->name,__func__); ++ ++ skb_queue_purge(&data->txq); ++ ++ return 0; ++} ++ ++static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ struct btsdio_data *data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("%s,%s", hdev->name,__func__); ++ ++ switch (hci_skb_pkt_type(skb)) { ++ case HCI_COMMAND_PKT: ++ hdev->stat.cmd_tx++; ++ break; ++ ++ case HCI_ACLDATA_PKT: ++ hdev->stat.acl_tx++; ++ break; ++ ++ case HCI_SCODATA_PKT: ++ hdev->stat.sco_tx++; ++ break; ++ ++ default: ++ return -EILSEQ; ++ } ++ ++ skb_queue_tail(&data->txq, skb); ++ ++ schedule_work(&data->work); ++ ++ return 0; ++} ++ ++int btsdio_init(void) ++{ ++ struct btsdio_data *data; ++ struct hci_dev *hdev; ++ int err; ++ ++ AICBT_INFO("%s", __func__); ++ ++ ++ data = kzalloc(sizeof(struct btsdio_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ INIT_WORK(&data->work, btsdio_work); ++ ++ skb_queue_head_init(&data->txq); ++ ++ hdev = hci_alloc_dev(); ++ if (!hdev) ++ return -ENOMEM; ++ ++ hdev->bus = HCI_SDIO; ++ hci_set_drvdata(hdev, data); ++ ++ hdev->dev_type = HCI_PRIMARY; ++ ++ data->hdev = hdev; ++ ++ hdev->open = btsdio_open; ++ hdev->close = btsdio_close; ++ hdev->flush = btsdio_flush; ++ hdev->send = btsdio_send_frame; ++ ++ err = hci_register_dev(hdev); ++ if (err < 0) { ++ hci_free_dev(hdev); ++ return err; ++ } ++ ghdev = hdev; ++ ++ return 0; ++} ++ ++void btsdio_remove(void) ++{ ++ struct btsdio_data *data; ++ struct hci_dev *hdev; ++ hdev = hci_dev_get(0); ++ if (!hdev) { ++ AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); ++ return; ++ } ++ data = hci_get_drvdata(hdev); ++ ++ AICBT_INFO("btsdio_remove"); ++ ++ if (!data) ++ return; ++ ++ kfree(data); ++ ++ hci_unregister_dev(hdev); ++ ++ hci_free_dev(hdev); ++} ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h +new file mode 100644 +index 000000000000..e2429283314b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h +@@ -0,0 +1,383 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file hal_desc.h ++ * ++ * @brief File containing the definition of HW descriptors. ++ * ++ * Contains the definition and structures used by HW ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _HAL_DESC_H_ ++#define _HAL_DESC_H_ ++ ++#include "lmac_types.h" ++ ++/* Rate and policy table */ ++ ++#define N_CCK 8 ++#define N_OFDM 8 ++#define N_HT (8 * 2 * 2 * 4) ++#define N_VHT (10 * 4 * 2 * 8) ++#define N_HE_SU (12 * 4 * 3 * 8) ++#define N_HE_MU (12 * 6 * 3 * 8) ++#define N_HE_ER (3 * 3 + 3) //RU242 + RU106 ++ ++/* conversion table from NL80211 to MACHW enum */ ++extern const int chnl2bw[]; ++ ++/* conversion table from MACHW to NL80211 enum */ ++extern const int bw2chnl[]; ++ ++/* Rate cntrl info */ ++#define MCS_INDEX_TX_RCX_OFT 0 ++#define MCS_INDEX_TX_RCX_MASK (0x7F << MCS_INDEX_TX_RCX_OFT) ++#define BW_TX_RCX_OFT 7 ++#define BW_TX_RCX_MASK (0x3 << BW_TX_RCX_OFT) ++#define SHORT_GI_TX_RCX_OFT 9 ++#define SHORT_GI_TX_RCX_MASK (0x1 << SHORT_GI_TX_RCX_OFT) ++#define PRE_TYPE_TX_RCX_OFT 10 ++#define PRE_TYPE_TX_RCX_MASK (0x1 << PRE_TYPE_TX_RCX_OFT) ++#define FORMAT_MOD_TX_RCX_OFT 11 ++#define FORMAT_MOD_TX_RCX_MASK (0x7 << FORMAT_MOD_TX_RCX_OFT) ++ ++ ++/* Values for formatModTx */ ++#define FORMATMOD_NON_HT 0 ++#define FORMATMOD_NON_HT_DUP_OFDM 1 ++#define FORMATMOD_HT_MF 2 ++#define FORMATMOD_HT_GF 3 ++#define FORMATMOD_VHT 4 ++#define FORMATMOD_HE_SU 5 ++#define FORMATMOD_HE_MU 6 ++#define FORMATMOD_HE_ER 7 ++#define FORMATMOD_HE_TB 8 ++ ++/* Values for navProtFrmEx */ ++#define NAV_PROT_NO_PROT_BIT 0 ++#define NAV_PROT_SELF_CTS_BIT 1 ++#define NAV_PROT_RTS_CTS_BIT 2 ++#define NAV_PROT_RTS_CTS_WITH_QAP_BIT 3 ++#define NAV_PROT_STBC_BIT 4 ++ ++/* THD MACCTRLINFO2 fields, used in struct umacdesc umac.flags */ ++/// WhichDescriptor definition - contains aMPDU bit and position value ++/// Offset of WhichDescriptor field in the MAC CONTROL INFO 2 word ++#define WHICHDESC_OFT 19 ++/// Mask of the WhichDescriptor field ++#define WHICHDESC_MSK (0x07 << WHICHDESC_OFT) ++/// Only 1 THD possible, describing an unfragmented MSDU ++#define WHICHDESC_UNFRAGMENTED_MSDU (0x00 << WHICHDESC_OFT) ++/// THD describing the first MPDU of a fragmented MSDU ++#define WHICHDESC_FRAGMENTED_MSDU_FIRST (0x01 << WHICHDESC_OFT) ++/// THD describing intermediate MPDUs of a fragmented MSDU ++#define WHICHDESC_FRAGMENTED_MSDU_INT (0x02 << WHICHDESC_OFT) ++/// THD describing the last MPDU of a fragmented MSDU ++#define WHICHDESC_FRAGMENTED_MSDU_LAST (0x03 << WHICHDESC_OFT) ++/// THD for extra descriptor starting an AMPDU ++#define WHICHDESC_AMPDU_EXTRA (0x04 << WHICHDESC_OFT) ++/// THD describing the first MPDU of an A-MPDU ++#define WHICHDESC_AMPDU_FIRST (0x05 << WHICHDESC_OFT) ++/// THD describing intermediate MPDUs of an A-MPDU ++#define WHICHDESC_AMPDU_INT (0x06 << WHICHDESC_OFT) ++/// THD describing the last MPDU of an A-MPDU ++#define WHICHDESC_AMPDU_LAST (0x07 << WHICHDESC_OFT) ++ ++/// aMPDU bit offset ++#define AMPDU_OFT 21 ++/// aMPDU bit ++#define AMPDU_BIT CO_BIT(AMPDU_OFT) ++ ++union rwnx_mcs_index { ++ struct { ++ u32 mcs : 3; ++ u32 nss : 2; ++ } ht; ++ struct { ++ u32 mcs : 4; ++ u32 nss : 3; ++ } vht; ++ struct { ++ u32 mcs : 4; ++ u32 nss : 3; ++ } he; ++ u32 legacy : 7; ++}; ++ ++enum { ++ HW_RATE_1MBPS = 0, ++ HW_RATE_2MBPS = 1, ++ HW_RATE_5_5MBPS = 2, ++ HW_RATE_11MBPS = 3, ++ HW_RATE_6MBPS = 4, ++ HW_RATE_9MBPS = 5, ++ HW_RATE_12MBPS = 6, ++ HW_RATE_18MBPS = 7, ++ HW_RATE_24MBPS = 8, ++ HW_RATE_36MBPS = 9, ++ HW_RATE_48MBPS = 10, ++ HW_RATE_54MBPS = 11, ++ HW_RATE_MAX ++}; ++ ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_rate_ctrl_info { ++ struct { ++ u32 mcsIndexTx : 7; ++ u32 bwTx : 2; ++ u32 giAndPreTypeTx : 2; ++ u32 formatModTx : 3; ++ u32 navProtFrmEx : 3; ++ u32 mcsIndexProtTx : 7; ++ u32 bwProtTx : 2; ++ u32 formatModProtTx : 3; ++ u32 nRetry : 3; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++struct rwnx_power_ctrl_info { ++ u32 txPwrLevelPT : 8; ++ u32 txPwrLevelProtPT : 8; ++ u32 reserved :16; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_phy_ctrl_info_1 { ++ struct { ++ u32 rsvd1 : 3; ++ u32 bfFrmEx : 1; ++ u32 numExtnSS : 2; ++ u32 fecCoding : 1; ++ u32 stbc : 2; ++ u32 rsvd2 : 5; ++ u32 nTx : 3; ++ u32 nTxProt : 3; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_phy_ctrl_info_2 { ++ struct { ++ u32 antennaSet : 8; ++ u32 smmIndex : 8; ++ u32 beamFormed : 1; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_mac_ctrl_info_1 { ++ struct { ++ u32 keySRamIndex : 10; ++ u32 keySRamIndexRA : 10; ++ }; ++ u32 value; ++}; ++ ++/* c.f RW-WLAN-nX-MAC-HW-UM */ ++union rwnx_pol_mac_ctrl_info_2 { ++ struct { ++ u32 longRetryLimit : 8; ++ u32 shortRetryLimit : 8; ++ u32 rtsThreshold : 12; ++ }; ++ u32 value; ++}; ++ ++#define POLICY_TABLE_PATTERN 0xBADCAB1E ++ ++struct tx_policy_tbl { ++ /* Unique Pattern at the start of Policy Table */ ++ u32 upatterntx; ++ /* PHY Control 1 Information used by MAC HW */ ++ union rwnx_pol_phy_ctrl_info_1 phyctrlinfo_1; ++ /* PHY Control 2 Information used by MAC HW */ ++ union rwnx_pol_phy_ctrl_info_2 phyctrlinfo_2; ++ /* MAC Control 1 Information used by MAC HW */ ++ union rwnx_pol_mac_ctrl_info_1 macctrlinfo_1; ++ /* MAC Control 2 Information used by MAC HW */ ++ union rwnx_pol_mac_ctrl_info_2 macctrlinfo_2; ++ ++ union rwnx_rate_ctrl_info ratectrlinfos[NX_TX_MAX_RATES]; ++ struct rwnx_power_ctrl_info powerctrlinfos[NX_TX_MAX_RATES]; ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++/** ++ * struct rwnx_hw_txstatus - Bitfield of confirmation status ++ * ++ * @tx_done: packet has been processed by the firmware. ++ * @retry_required: packet has been transmitted but not acknoledged. ++ * Driver must repush it. ++ * @sw_retry_required: packet has not been transmitted (FW wasn't able to push ++ * it when it received it: not active channel ...). Driver must repush it. ++ * @acknowledged: packet has been acknowledged by peer ++ */ ++union rwnx_hw_txstatus { ++ struct { ++ u32 tx_done : 1; ++ u32 retry_required : 1; ++ u32 sw_retry_required : 1; ++ u32 acknowledged : 1; ++ u32 reserved :28; ++ }; ++ u32 value; ++}; ++ ++/** ++ * struct tx_cfm_tag - Structure indicating the status and other ++ * information about the transmission ++ * ++ * @pn: PN that was used for the transmission ++ * @sn: Sequence number of the packet ++ * @timestamp: Timestamp of first transmission of this MPDU ++ * @credits: Number of credits to be reallocated for the txq that push this ++ * buffer (can be 0 or 1) ++ * @ampdu_size: Size of the ampdu in which the frame has been transmitted if ++ * this was the last frame of the a-mpdu, and 0 if the frame is not the last ++ * frame on a a-mdpu. ++ * 1 means that the frame has been transmitted as a singleton. ++ * @amsdu_size: Size, in bytes, allowed to create a-msdu. ++ * @status: transmission status ++ */ ++struct tx_cfm_tag { ++/* ++ u16_l pn[4]; ++ u16_l sn; ++ u16_l timestamp; ++*/ ++ s8_l credits; ++ u8_l ampdu_size; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ u16_l amsdu_size; ++#endif ++ union rwnx_hw_txstatus status; ++ u32_l hostid; ++}; ++ ++/** ++ * struct rwnx_hw_txhdr - Hardware part of tx header ++ * ++ * @cfm: Information updated by fw/hardware after sending a frame ++ */ ++struct rwnx_hw_txhdr { ++ struct tx_cfm_tag cfm; ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/* Modem */ ++ ++#define MDM_PHY_CONFIG_TRIDENT 0 ++#define MDM_PHY_CONFIG_ELMA 1 ++#define MDM_PHY_CONFIG_KARST 2 ++ ++// MODEM features (from reg_mdm_stat.h) ++/// MUMIMOTX field bit ++#define MDM_MUMIMOTX_BIT ((u32)0x80000000) ++/// MUMIMOTX field position ++#define MDM_MUMIMOTX_POS 31 ++/// MUMIMORX field bit ++#define MDM_MUMIMORX_BIT ((u32)0x40000000) ++/// MUMIMORX field position ++#define MDM_MUMIMORX_POS 30 ++/// BFMER field bit ++#define MDM_BFMER_BIT ((u32)0x20000000) ++/// BFMER field position ++#define MDM_BFMER_POS 29 ++/// BFMEE field bit ++#define MDM_BFMEE_BIT ((u32)0x10000000) ++/// BFMEE field position ++#define MDM_BFMEE_POS 28 ++/// LDPCDEC field bit ++#define MDM_LDPCDEC_BIT ((u32)0x08000000) ++/// LDPCDEC field position ++#define MDM_LDPCDEC_POS 27 ++/// LDPCENC field bit ++#define MDM_LDPCENC_BIT ((u32)0x04000000) ++/// LDPCENC field position ++#define MDM_LDPCENC_POS 26 ++/// CHBW field mask ++#define MDM_CHBW_MASK ((u32)0x03000000) ++/// CHBW field LSB position ++#define MDM_CHBW_LSB 24 ++/// CHBW field width ++#define MDM_CHBW_WIDTH ((u32)0x00000002) ++/// DSSSCCK field bit ++#define MDM_DSSSCCK_BIT ((u32)0x00800000) ++/// DSSSCCK field position ++#define MDM_DSSSCCK_POS 23 ++/// VHT field bit ++#define MDM_VHT_BIT ((u32)0x00400000) ++/// VHT field position ++#define MDM_VHT_POS 22 ++/// HE field bit ++#define MDM_HE_BIT ((u32)0x00200000) ++/// HE field position ++#define MDM_HE_POS 21 ++/// ESS field bit ++#define MDM_ESS_BIT ((u32)0x00100000) ++/// ESS field position ++#define MDM_ESS_POS 20 ++/// RFMODE field mask ++#define MDM_RFMODE_MASK ((u32)0x000F0000) ++/// RFMODE field LSB position ++#define MDM_RFMODE_LSB 16 ++/// RFMODE field width ++#define MDM_RFMODE_WIDTH ((u32)0x00000004) ++/// NSTS field mask ++#define MDM_NSTS_MASK ((u32)0x0000F000) ++/// NSTS field LSB position ++#define MDM_NSTS_LSB 12 ++/// NSTS field width ++#define MDM_NSTS_WIDTH ((u32)0x00000004) ++/// NSS field mask ++#define MDM_NSS_MASK ((u32)0x00000F00) ++/// NSS field LSB position ++#define MDM_NSS_LSB 8 ++/// NSS field width ++#define MDM_NSS_WIDTH ((u32)0x00000004) ++/// NTX field mask ++#define MDM_NTX_MASK ((u32)0x000000F0) ++/// NTX field LSB position ++#define MDM_NTX_LSB 4 ++/// NTX field width ++#define MDM_NTX_WIDTH ((u32)0x00000004) ++/// NRX field mask ++#define MDM_NRX_MASK ((u32)0x0000000F) ++/// NRX field LSB position ++#define MDM_NRX_LSB 0 ++/// NRX field width ++#define MDM_NRX_WIDTH ((u32)0x00000004) ++ ++#define __MDM_PHYCFG_FROM_VERS(v) (((v) & MDM_RFMODE_MASK) >> MDM_RFMODE_LSB) ++ ++#define RIU_FCU_PRESENT_MASK ((u32)0xFF000000) ++#define RIU_FCU_PRESENT_LSB 24 ++ ++#define __RIU_FCU_PRESENT(v) (((v) & RIU_FCU_PRESENT_MASK) >> RIU_FCU_PRESENT_LSB == 5) ++ ++/// AGC load version field mask ++#define RIU_AGC_LOAD_MASK ((u32)0x00C00000) ++/// AGC load version field LSB position ++#define RIU_AGC_LOAD_LSB 22 ++ ++#define __RIU_AGCLOAD_FROM_VERS(v) (((v) & RIU_AGC_LOAD_MASK) >> RIU_AGC_LOAD_LSB) ++ ++#define __FPGA_TYPE(v) (((v) & 0xFFFF0000) >> 16) ++ ++#define __MDM_MAJOR_VERSION(v) (((v) & 0xFF000000) >> 24) ++#define __MDM_MINOR_VERSION(v) (((v) & 0x00FF0000) >> 16) ++#define __MDM_VERSION(v) ((__MDM_MAJOR_VERSION(v) + 2) * 10 + __MDM_MINOR_VERSION(v)) ++ ++ ++#endif // _HAL_DESC_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h +new file mode 100644 +index 000000000000..069f69ee5ee0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h +@@ -0,0 +1,25 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file ipc_compat.h ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _IPC_H_ ++#define _IPC_H_ ++ ++#define __INLINE inline ++ ++#define __ALIGN4 __aligned(4) ++ ++#define ASSERT_ERR(condition) \ ++ do { \ ++ if (unlikely(!(condition))) { \ ++ printk(KERN_ERR "%s:%d:ASSERT_ERR(" #condition ")\n", __FILE__, __LINE__); \ ++ } \ ++ } while (0) ++ ++#endif /* _IPC_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c +new file mode 100644 +index 000000000000..7746f4097976 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c +@@ -0,0 +1,52 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file ipc_host.c ++ * ++ * @brief IPC module. ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++/* ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++#ifndef __KERNEL__ ++#include ++#else ++#include ++#include "rwnx_defs.h" ++#include "rwnx_prof.h" ++#endif ++ ++#include "ipc_host.h" ++ ++/* ++ * TYPES DEFINITION ++ ****************************************************************************** ++ */ ++ ++const int nx_txdesc_cnt[] = { ++ NX_TXDESC_CNT0, ++ NX_TXDESC_CNT1, ++ NX_TXDESC_CNT2, ++ NX_TXDESC_CNT3, ++ #if NX_TXQ_CNT == 5 ++ NX_TXDESC_CNT4, ++ #endif ++}; ++ ++const int nx_txuser_cnt[] = { ++ CONFIG_USER_MAX, ++ CONFIG_USER_MAX, ++ CONFIG_USER_MAX, ++ CONFIG_USER_MAX, ++ #if NX_TXQ_CNT == 5 ++ 1, ++ #endif ++}; ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h +new file mode 100644 +index 000000000000..583b66889aa4 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h +@@ -0,0 +1,168 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file ipc_host.h ++ * ++ * @brief IPC module. ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _IPC_HOST_H_ ++#define _IPC_HOST_H_ ++ ++/* ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++#include "ipc_shared.h" ++#ifndef __KERNEL__ ++#include "arch.h" ++#else ++#include "ipc_compat.h" ++#endif ++ ++/** ++ ****************************************************************************** ++ * @brief This structure is used to initialize the MAC SW ++ * ++ * The WLAN device driver provides functions call-back with this structure ++ ****************************************************************************** ++ */ ++struct ipc_host_cb_tag { ++ /// WLAN driver call-back function: send_data_cfm ++ int (*send_data_cfm)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_data_ind ++ uint8_t (*recv_data_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_radar_ind ++ uint8_t (*recv_radar_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_unsup_rx_vec_ind ++ uint8_t (*recv_unsup_rx_vec_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_msg_ind ++ uint8_t (*recv_msg_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_msgack_ind ++ uint8_t (*recv_msgack_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: recv_dbg_ind ++ uint8_t (*recv_dbg_ind)(void *pthis, void *host_id); ++ ++ /// WLAN driver call-back function: prim_tbtt_ind ++ void (*prim_tbtt_ind)(void *pthis); ++ ++ /// WLAN driver call-back function: sec_tbtt_ind ++ void (*sec_tbtt_ind)(void *pthis); ++ ++}; ++ ++/* ++ * Struct used to store information about host buffers (DMA Address and local pointer) ++ */ ++struct ipc_hostbuf { ++ void *hostid; ///< ptr to hostbuf client (ipc_host client) structure ++ uint32_t dma_addr; ///< ptr to real hostbuf dma address ++}; ++ ++/// Definition of the IPC Host environment structure. ++struct ipc_host_env_tag { ++ /// Structure containing the callback pointers ++ struct ipc_host_cb_tag cb; ++ ++ /// Pointer to the shared environment ++ struct ipc_shared_env_tag *shared; ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ // Array used to store the descriptor addresses ++ struct ipc_hostbuf ipc_host_rxdesc_array[IPC_RXDESC_CNT]; ++ // Index of the host RX descriptor array (ipc_shared environment) ++ uint8_t ipc_host_rxdesc_idx; ++ /// Store the number of RX Descriptors ++ uint8_t rxdesc_nb; ++ #endif //(CONFIG_RWNX_FULLMAC) ++ ++ /// Fields for Data Rx handling ++ // Index used for ipc_host_rxbuf_array to point to current buffer ++ uint8_t ipc_host_rxbuf_idx; ++ // Store the number of Rx Data buffers ++ uint32_t rx_bufnb; ++ // Store the size of the Rx Data buffers ++ uint32_t rx_bufsz; ++ ++ /// Fields for Radar events handling ++ // Global array used to store the hostid and hostbuf addresses ++ struct ipc_hostbuf ipc_host_radarbuf_array[IPC_RADARBUF_CNT]; ++ // Index used for ipc_host_rxbuf_array to point to current buffer ++ uint8_t ipc_host_radarbuf_idx; ++ // Store the number of radar event buffers ++ uint32_t radar_bufnb; ++ // Store the size of the radar event buffers ++ uint32_t radar_bufsz; ++ ++ ///Fields for Unsupported frame handling ++ // Global array used to store the hostid and hostbuf addresses ++ struct ipc_hostbuf ipc_host_unsuprxvecbuf_array[IPC_UNSUPRXVECBUF_CNT]; ++ // Index used for ipc_host_unsuprxvecbuf_array to point to current buffer ++ uint8_t ipc_host_unsuprxvecbuf_idx; ++ // Store the number of unsupported rx vector buffers ++ uint32_t unsuprxvec_bufnb; ++ // Store the size of unsupported rx vector buffers ++ uint32_t unsuprxvec_bufsz; ++ ++ // Index used that points to the first free TX desc ++ uint32_t txdesc_free_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ // Index used that points to the first used TX desc ++ uint32_t txdesc_used_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ // Array storing the currently pushed host ids for the BK queue ++ void *tx_host_id0[CONFIG_USER_MAX][NX_TXDESC_CNT0]; ++ // Array storing the currently pushed host ids for the BE queue ++ void *tx_host_id1[CONFIG_USER_MAX][NX_TXDESC_CNT1]; ++ // Array storing the currently pushed host ids for the VI queue ++ void *tx_host_id2[CONFIG_USER_MAX][NX_TXDESC_CNT2]; ++ // Array storing the currently pushed host ids for the VO queue ++ void *tx_host_id3[CONFIG_USER_MAX][NX_TXDESC_CNT3]; ++ #if NX_TXQ_CNT == 5 ++ // Array storing the currently pushed host ids for the BCN queue ++ void *tx_host_id4[1][NX_TXDESC_CNT4]; ++ #endif ++ // Pointer to the different host ids arrays, per IPC queue ++ void **tx_host_id[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ // Pointer to the different TX descriptor arrays, per IPC queue ++ volatile struct txdesc_host *txdesc[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; ++ ++ /// Fields for Emb->App MSGs handling ++ // Global array used to store the hostid and hostbuf addresses for msg/ind ++ struct ipc_hostbuf ipc_host_msgbuf_array[IPC_MSGE2A_BUF_CNT]; ++ // Index of the MSG E2A buffers array to point to current buffer ++ uint8_t ipc_host_msge2a_idx; ++ // Store the number of E2A MSG buffers ++ uint32_t ipc_e2amsg_bufnb; ++ // Store the size of the E2A MSG buffers ++ uint32_t ipc_e2amsg_bufsz; ++ ++ /// E2A ACKs of A2E MSGs ++ uint8_t msga2e_cnt; ++ void *msga2e_hostid; ++ ++ /// Fields for Debug MSGs handling ++ // Global array used to store the hostid and hostbuf addresses for Debug messages ++ struct ipc_hostbuf ipc_host_dbgbuf_array[IPC_DBGBUF_CNT]; ++ // Index of the Debug messages buffers array to point to current buffer ++ uint8_t ipc_host_dbg_idx; ++ // Store the number of Debug messages buffers ++ uint32_t ipc_dbg_bufnb; ++ // Store the size of the Debug messages buffers ++ uint32_t ipc_dbg_bufsz; ++ ++ /// Pointer to the attached object (used in callbacks and register accesses) ++ void *pthis; ++}; ++ ++extern const int nx_txdesc_cnt[]; ++extern const int nx_txuser_cnt[]; ++ ++#endif // _IPC_HOST_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h +new file mode 100644 +index 000000000000..7e2fedcb1b53 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h +@@ -0,0 +1,785 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file ipc_shared.h ++ * ++ * @brief Shared data between both IPC modules. ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _IPC_SHARED_H_ ++#define _IPC_SHARED_H_ ++ ++/* ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++#include "ipc_compat.h" ++#include "lmac_mac.h" ++ ++/* ++ * DEFINES AND MACROS ++ **************************************************************************************** ++ */ ++#define CO_BIT(pos) (1U<<(pos)) ++ ++#define IPC_TXQUEUE_CNT NX_TXQ_CNT ++#define NX_TXDESC_CNT0 8 ++#define NX_TXDESC_CNT1 64 ++#define NX_TXDESC_CNT2 64 ++#define NX_TXDESC_CNT3 32 ++#if NX_TXQ_CNT == 5 ++#define NX_TXDESC_CNT4 8 ++#endif ++ ++/* ++ * Number of Host buffers available for Data Rx handling (through DMA) ++ */ ++#define IPC_RXBUF_CNT 128 ++ ++/* ++ * Number of shared descriptors available for Data RX handling ++ */ ++#define IPC_RXDESC_CNT 128 ++ ++/* ++ * Number of Host buffers available for Radar events handling (through DMA) ++ */ ++#define IPC_RADARBUF_CNT 16 ++ ++/* ++ * Number of Host buffers available for unsupported Rx vectors handling (through DMA) ++ */ ++#define IPC_UNSUPRXVECBUF_CNT 8 ++ ++/* ++ * Size of RxVector ++ */ ++#define IPC_RXVEC_SIZE 16 ++ ++/* ++ * Number of Host buffers available for Emb->App MSGs sending (through DMA) ++ */ ++#ifdef CONFIG_RWNX_FULLMAC ++#define IPC_MSGE2A_BUF_CNT 64 ++#endif ++/* ++ * Number of Host buffers available for Debug Messages sending (through DMA) ++ */ ++#define IPC_DBGBUF_CNT 32 ++ ++/* ++ * Length used in MSGs structures ++ */ ++#define IPC_A2E_MSG_BUF_SIZE 127 // size in 4-byte words ++#ifdef CONFIG_RWNX_FULLMAC ++#define IPC_E2A_MSG_SIZE_BASE 256 // size in 4-byte words ++#endif ++ ++#ifdef CONFIG_RWNX_TL4 ++#define IPC_E2A_MSG_PARAM_SIZE (IPC_E2A_MSG_SIZE_BASE + (IPC_E2A_MSG_SIZE_BASE / 2)) ++#else ++#define IPC_E2A_MSG_PARAM_SIZE IPC_E2A_MSG_SIZE_BASE ++#endif ++ ++/* ++ * Debug messages buffers size (in bytes) ++ */ ++#define IPC_DBG_PARAM_SIZE 256 ++ ++/* ++ * Define used for Rx hostbuf validity. ++ * This value should appear only when hostbuf was used for a Reception. ++ */ ++#define RX_DMA_OVER_PATTERN 0xAAAAAA00 ++ ++/* ++ * Define used for MSG buffers validity. ++ * This value will be written only when a MSG buffer is used for sending from Emb to App. ++ */ ++#define IPC_MSGE2A_VALID_PATTERN 0xADDEDE2A ++ ++/* ++ * Define used for Debug messages buffers validity. ++ * This value will be written only when a DBG buffer is used for sending from Emb to App. ++ */ ++#define IPC_DBG_VALID_PATTERN 0x000CACA0 ++ ++/* ++ * Length of the receive vectors, in bytes ++ */ ++#define DMA_HDR_PHYVECT_LEN 36 ++ ++/* ++ * Maximum number of payload addresses and lengths present in the descriptor ++ */ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++#define NX_TX_PAYLOAD_MAX 6 ++#else ++#define NX_TX_PAYLOAD_MAX 1 ++#endif ++ ++/* ++ * Message struct/ID API version ++ */ ++#define MSG_API_VER 33 ++ ++/* ++ **************************************************************************************** ++ */ ++// c.f LMAC/src/tx/tx_swdesc.h ++/// Descriptor filled by the Host ++struct hostdesc { ++ /// Pointer to packet payload ++ //u32_l packet_addr; ++ /// Size of the payload ++ u16_l packet_len; ++ u16_l flags_ext; ++ ++ u32_l hostid; ++#ifdef CONFIG_RWNX_FULLMAC ++ /// Address of the status descriptor in host memory (used for confirmation upload) ++ //u32_l status_desc_addr; ++ /// Destination Address ++ struct mac_addr eth_dest_addr; ++ /// Source Address ++ struct mac_addr eth_src_addr; ++ /// Ethernet Type ++ u16_l ethertype; ++#else /* ! CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_AGG_TX ++ ///Sequence Number for AMPDU MPDUs - for quick check if it's allowed within window ++ u16_l sn; ++#endif /* CONFIG_RWNX_AGG_TX */ ++ /// Padding between the buffer control structure and the MPDU in host memory ++ u8_l padding; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ u8_l ac; ++ /// Packet TID (0xFF if not a QoS frame) ++ u8_l tid; ++ /// Interface Id ++ u8_l vif_idx; ++ /// Station Id (0xFF if station is unknown) ++ u8_l staid; ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ /// MU-MIMO information (GroupId and User Position in the group) - The GroupId ++ /// is located on bits 0-5 and the User Position on bits 6-7. The GroupId value is set ++ /// to 63 if MU-MIMO shall not be used ++ u8_l mumimo_info; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#ifdef CONFIG_RWNX_FULLMAC ++ /// TX flags ++ u16_l flags; ++#endif /* CONFIG_RWNX_FULLMAC */ ++}; ++ ++/// Descriptor filled by the UMAC ++struct umacdesc { ++#ifdef CONFIG_RWNX_AGG_TX ++ ///First Sequence Number of the BlockAck window ++ u16_l sn_win; ++ /// Flags from UMAC (match tx_hd.macctrlinfo2 format) ++ u32_l flags; ++ /// PHY related flags field - rate, GI type, BW type - filled by driver ++ u32_l phy_flags; ++#endif //(CONFIG_RWNX_AGG_TX) ++}; ++ ++struct txdesc_api { ++ /// Information provided by Host ++ struct hostdesc host; ++}; ++ ++ ++struct txdesc_host { ++ u32_l ready; ++ ++ /// API of the embedded part ++ struct txdesc_api api; ++}; ++ ++/// Comes from ipc_dma.h ++/// Element in the pool of TX DMA bridge descriptors. ++struct dma_desc { ++ /** Application subsystem address which is used as source address for DMA payload ++ * transfer*/ ++ u32_l src; ++ /** Points to the start of the embedded data buffer associated with this descriptor. ++ * This address acts as the destination address for the DMA payload transfer*/ ++ u32_l dest; ++ /// Complete length of the buffer in memory ++ u16_l length; ++ /// Control word for the DMA engine (e.g. for interrupt generation) ++ u16_l ctrl; ++ /// Pointer to the next element of the chained list ++ u32_l next; ++}; ++ ++// Comes from la.h ++/// Length of the configuration data of a logic analyzer ++#define LA_CONF_LEN 10 ++ ++/// Structure containing the configuration data of a logic analyzer ++struct la_conf_tag { ++ u32_l conf[LA_CONF_LEN]; ++ u32_l trace_len; ++ u32_l diag_conf; ++}; ++ ++/// Size of a logic analyzer memory ++#define LA_MEM_LEN (1024 * 1024) ++ ++/// Type of errors ++enum { ++ /// Recoverable error, not requiring any action from Upper MAC ++ DBG_ERROR_RECOVERABLE = 0, ++ /// Fatal error, requiring Upper MAC to reset Lower MAC and HW and restart operation ++ DBG_ERROR_FATAL ++}; ++ ++/// Maximum length of the SW diag trace ++#define DBG_SW_DIAG_MAX_LEN 1024 ++ ++/// Maximum length of the error trace ++#define DBG_ERROR_TRACE_SIZE 256 ++ ++/// Number of MAC diagnostic port banks ++#define DBG_DIAGS_MAC_MAX 48 ++ ++/// Number of PHY diagnostic port banks ++#define DBG_DIAGS_PHY_MAX 32 ++ ++/// Maximum size of the RX header descriptor information in the debug dump ++#define DBG_RHD_MEM_LEN (5 * 1024) ++ ++/// Maximum size of the RX buffer descriptor information in the debug dump ++#define DBG_RBD_MEM_LEN (5 * 1024) ++ ++/// Maximum size of the TX header descriptor information in the debug dump ++#define DBG_THD_MEM_LEN (10 * 1024) ++ ++/// Structure containing the information about the PHY channel that is used ++struct phy_channel_info { ++ /// PHY channel information 1 ++ u32_l info1; ++ /// PHY channel information 2 ++ u32_l info2; ++}; ++ ++/// Debug information forwarded to host when an error occurs ++struct dbg_debug_info_tag { ++ /// Type of error (0: recoverable, 1: fatal) ++ u32_l error_type; ++ /// Pointer to the first RX Header Descriptor chained to the MAC HW ++ u32_l rhd; ++ /// Size of the RX header descriptor buffer ++ u32_l rhd_len; ++ /// Pointer to the first RX Buffer Descriptor chained to the MAC HW ++ u32_l rbd; ++ /// Size of the RX buffer descriptor buffer ++ u32_l rbd_len; ++ /// Pointer to the first TX Header Descriptors chained to the MAC HW ++ u32_l thd[NX_TXQ_CNT]; ++ /// Size of the TX header descriptor buffer ++ u32_l thd_len[NX_TXQ_CNT]; ++ /// MAC HW diag configuration ++ u32_l hw_diag; ++ /// Error message ++ u32_l error[DBG_ERROR_TRACE_SIZE/4]; ++ /// SW diag configuration length ++ u32_l sw_diag_len; ++ /// SW diag configuration ++ u32_l sw_diag[DBG_SW_DIAG_MAX_LEN/4]; ++ /// PHY channel information ++ struct phy_channel_info chan_info; ++ /// Embedded LA configuration ++ struct la_conf_tag la_conf; ++ /// MAC diagnostic port state ++ u16_l diags_mac[DBG_DIAGS_MAC_MAX]; ++ /// PHY diagnostic port state ++ u16_l diags_phy[DBG_DIAGS_PHY_MAX]; ++ /// MAC HW RX Header descriptor pointer ++ u32_l rhd_hw_ptr; ++ /// MAC HW RX Buffer descriptor pointer ++ u32_l rbd_hw_ptr; ++}; ++ ++/// Full debug dump that is forwarded to host in case of error ++struct dbg_debug_dump_tag { ++ /// Debug information ++ struct dbg_debug_info_tag dbg_info; ++ ++ /// RX header descriptor memory ++ u32_l rhd_mem[DBG_RHD_MEM_LEN/4]; ++ ++ /// RX buffer descriptor memory ++ u32_l rbd_mem[DBG_RBD_MEM_LEN/4]; ++ ++ /// TX header descriptor memory ++ u32_l thd_mem[NX_TXQ_CNT][DBG_THD_MEM_LEN/4]; ++ ++ /// Logic analyzer memory ++ u32_l la_mem[LA_MEM_LEN/4]; ++}; ++ ++ ++/// Number of pulses in a radar event structure ++#define RADAR_PULSE_MAX 4 ++ ++/// Definition of an array of radar pulses ++struct radar_pulse_array_desc { ++ /// Buffer containing the radar pulses ++ u32_l pulse[RADAR_PULSE_MAX]; ++ /// Index of the radar detection chain that detected those pulses ++ u32_l idx; ++ /// Number of valid pulses in the buffer ++ u32_l cnt; ++}; ++ ++/// Bit mapping inside a radar pulse element ++struct radar_pulse { ++ s32_l freq:6; /** Freq (resolution is 2Mhz range is [-Fadc/4 .. Fadc/4]) */ ++ u32_l fom:4; /** Figure of Merit */ ++ u32_l len:6; /** Length of the current radar pulse (resolution is 2us) */ ++ u32_l rep:16; /** Time interval between the previous radar event ++ and the current one (in us) */ ++}; ++ ++/// Definition of a RX vector descriptor ++struct rx_vector_desc { ++ /// PHY channel information ++ struct phy_channel_info phy_info; ++ ++ /// RX vector 1 ++ u32_l rx_vect1[IPC_RXVEC_SIZE/4]; ++ ++ /// Used to print a valid rx vector ++ u32_l pattern; ++}; ++ ++/// ++struct rxdesc_tag { ++ /// Host Buffer Address ++ u32_l host_id; ++ /// Length ++ u32_l frame_len; ++ /// Status ++ u16_l status; ++}; ++ ++/** ++ **************************************************************************************** ++ * @defgroup IPC IPC ++ * @ingroup NXMAC ++ * @brief Inter Processor Communication module. ++ * ++ * The IPC module implements the protocol to communicate between the Host CPU ++ * and the Embedded CPU. ++ * ++ * @see http://en.wikipedia.org/wiki/Circular_buffer ++ * For more information about the ring buffer typical use and difficulties. ++ **************************************************************************************** ++ */ ++ ++ ++/** ++ **************************************************************************************** ++ * @addtogroup IPC_TX IPC Tx path ++ * @ingroup IPC ++ * @brief IPC Tx path structures and functions ++ * ++ * A typical use case of the IPC Tx path API: ++ * @msc ++ * hscale = "2"; ++ * ++ * a [label=Driver], ++ * b [label="IPC host"], ++ * c [label="IPC emb"], ++ * d [label=Firmware]; ++ * ++ * --- [label="Tx descriptor queue example"]; ++ * a=>a [label="Driver receives a Tx packet from OS"]; ++ * a=>b [label="ipc_host_txdesc_get()"]; ++ * a<a [label="Driver fill the descriptor"]; ++ * a=>b [label="ipc_host_txdesc_push()"]; ++ * ... [label="(several Tx desc can be pushed)"]; ++ * b:>c [label="Tx desc queue filled IRQ"]; ++ * c=>>d [label="EDCA sub-scheduler callback"]; ++ * c<>d [label="UMAC Tx desc callback"]; ++ * ... [label="(several Tx desc can be popped)"]; ++ * d=>d [label="Packets are sent or discarded"]; ++ * --- [label="Tx confirm queue example"]; ++ * c<=d [label="ipc_emb_txcfm_push()"]; ++ * c>>d [label="Request accepted"]; ++ * ... [label="(several Tx cfm can be pushed)"]; ++ * b<:c [label="Tx cfm queue filled IRQ"]; ++ * a<<=b [label="Driver's Tx Confirm callback"]; ++ * a=>b [label="ipc_host_txcfm_pop()"]; ++ * a<c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * ... [label="(several Rx buffer are pushed)"]; ++ * a=>a [label=" Frame is received\n from the medium"]; ++ * a<a [label=" Firmware fill the buffer\n with received frame"]; ++ * a<c [label="Rx desc queue filled IRQ"]; ++ * c=>>d [label="Driver Rx packet callback"]; ++ * c<=d [label="ipc_host_rxdesc_pop()"]; ++ * d=>d [label="Rx packet is handed \nover to the OS "]; ++ * ... [label="(several Rx desc can be poped)"]; ++ * --- [label="Rx buffer request exemple"]; ++ * b:>c [label="Low Rx buffer count IRQ"]; ++ * a<>d [label="Driver Rx buffer callback"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * d=>c [label="ipc_host_rxbuf_push()"]; ++ * ... [label="(several Rx buffer are pushed)"]; ++ * @endmsc ++ * ++ * @addtogroup IPC_RX ++ * @{ ++ **************************************************************************************** ++ */ ++ ++/// @} IPC_RX ++ ++ ++ ++/** ++ **************************************************************************************** ++ * @defgroup IPC_MISC IPC Misc ++ * @ingroup IPC ++ * @brief IPC miscellaneous functions ++ **************************************************************************************** ++ */ ++/** IPC header structure. This structure is stored at the beginning of every IPC message. ++ * @warning This structure's size must NOT exceed 4 bytes in length. ++ */ ++struct ipc_header { ++ /// IPC message type. ++ u16_l type; ++ /// IPC message size in number of bytes. ++ u16_l size; ++}; ++ ++struct ipc_msg_elt { ++ /// Message header (alignment forced on word size, see allocation in shared env). ++ struct ipc_header header __ALIGN4; ++}; ++ ++/// Message structure for MSGs from Emb to App ++struct ipc_e2a_msg { ++ u16_l id; ///< Message id. ++ u16_l dummy_dest_id; ++ u16_l dummy_src_id; ++ u16_l param_len; ///< Parameter embedded struct length. ++ u32_l pattern; ///< Used to stamp a valid MSG buffer ++ u32_l param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++/// Message structure for Debug messages from Emb to App ++struct ipc_dbg_msg { ++ u32_l string[IPC_DBG_PARAM_SIZE/4]; ///< Debug string ++ u32_l pattern; ///< Used to stamp a valid buffer ++}; ++ ++/// Message structure for MSGs from App to Emb. ++/// Actually a sub-structure will be used when filling the messages. ++struct ipc_a2e_msg { ++ u32_l dummy_word; // used to cope with kernel message structure ++ u32_l msg[IPC_A2E_MSG_BUF_SIZE]; // body of the msg ++}; ++ ++struct ipc_shared_rx_buf { ++ /// < ptr to hostbuf client (ipc_host client) structure ++ u32_l hostid; ++ /// < ptr to real hostbuf dma address ++ u32_l dma_addr; ++}; ++ ++struct ipc_shared_rx_desc { ++ /// DMA Address ++ u32_l dma_addr; ++}; ++ ++/// Structure containing FW characteristics for compatibility checking ++struct compatibility_tag { ++ /// Size of IPC shared memory ++ u16_l ipc_shared_size; ++ /// Message struct/ID API version ++ u16_l msg_api; ++ /// Version of IPC shared ++ u8_l ipc_shared_version; ++ /// Number of host buffers available for Emb->App MSGs sending ++ u8_l msge2a_buf_cnt; ++ /// Number of host buffers available for Debug Messages sending ++ u8_l dbgbuf_cnt; ++ /// Number of host buffers available for Radar events handling ++ u8_l radarbuf_cnt; ++ /// Number of host buffers available for unsupported Rx vectors handling ++ u8_l unsuprxvecbuf_cnt; ++ /// Number of shared descriptors available for Data RX handling ++ u8_l rxdesc_cnt; ++ /// Number of host buffers available for Data Rx handling ++ u8_l rxbuf_cnt; ++ /// Number of descriptors in BK TX queue (power of 2, min 4, max 64) ++ u8_l bk_txq; ++ /// Number of descriptors in BE TX queue (power of 2, min 4, max 64) ++ u8_l be_txq; ++ /// Number of descriptors in VI TX queue (power of 2, min 4, max 64) ++ u8_l vi_txq; ++ /// Number of descriptors in VO TX queue (power of 2, min 4, max 64) ++ u8_l vo_txq; ++ /// Number of descriptors in BCN TX queue (power of 2, min 4, max 64) ++ u8_l bcn_txq; ++}; ++ ++/* ++ * TYPE and STRUCT DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++ ++// Indexes are defined in the MIB shared structure ++struct ipc_shared_env_tag { ++ volatile struct compatibility_tag comp_info; //FW characteristics ++ ++ volatile struct ipc_a2e_msg msg_a2e_buf; // room for MSG to be sent from App to Emb ++ ++ // Fields for MSGs sending from Emb to App ++ volatile struct ipc_e2a_msg msg_e2a_buf; // room to build the MSG to be DMA Xferred ++ volatile struct dma_desc msg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers ++ volatile u32_l msg_e2a_hostbuf_addr[IPC_MSGE2A_BUF_CNT]; // buffers @ for DMA Xfers ++ ++ // Fields for Debug MSGs sending from Emb to App ++ volatile struct ipc_dbg_msg dbg_buf; // room to build the MSG to be DMA Xferred ++ volatile struct dma_desc dbg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers ++ volatile u32_l dbg_hostbuf_addr[IPC_DBGBUF_CNT]; // buffers @ for MSGs DMA Xfers ++ volatile u32_l la_dbginfo_addr; // Host buffer address for the debug information ++ volatile u32_l pattern_addr; ++ volatile u32_l radarbuf_hostbuf[IPC_RADARBUF_CNT]; // buffers @ for Radar Events ++ volatile u32_l unsuprxvecbuf_hostbuf[IPC_UNSUPRXVECBUF_CNT]; // buffers @ for unsupported Rx vectors ++ volatile struct txdesc_host txdesc0[CONFIG_USER_MAX][NX_TXDESC_CNT0]; ++ volatile struct txdesc_host txdesc1[CONFIG_USER_MAX][NX_TXDESC_CNT1]; ++ volatile struct txdesc_host txdesc2[CONFIG_USER_MAX][NX_TXDESC_CNT2]; ++ volatile struct txdesc_host txdesc3[CONFIG_USER_MAX][NX_TXDESC_CNT3]; ++ #if NX_TXQ_CNT == 5 ++ volatile struct txdesc_host txdesc4[1][NX_TXDESC_CNT4]; ++ #endif ++ #ifdef CONFIG_RWNX_FULLMAC ++ // RX Descriptors Array ++ volatile struct ipc_shared_rx_desc host_rxdesc[IPC_RXDESC_CNT]; ++ // RX Buffers Array ++ volatile struct ipc_shared_rx_buf host_rxbuf[IPC_RXBUF_CNT]; ++ #else ++ // buffers @ for Data Rx ++ volatile u32_l host_rxbuf[IPC_RXBUF_CNT]; ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ ++ u32_l buffered[NX_REMOTE_STA_MAX][TID_MAX]; ++ ++ volatile uint16_t trace_pattern; ++ volatile uint32_t trace_start; ++ volatile uint32_t trace_end; ++ volatile uint32_t trace_size; ++ volatile uint32_t trace_offset; ++ volatile uint32_t trace_nb_compo; ++ volatile uint32_t trace_offset_compo; ++}; ++ ++extern struct ipc_shared_env_tag ipc_shared_env; ++ ++ ++/* ++ * TYPE and STRUCT DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++// IRQs from app to emb ++/// Interrupts bits used for the TX descriptors of the AC queues ++#ifdef CONFIG_RWNX_MUMIMO_TX ++#ifdef CONFIG_RWNX_OLD_IPC ++#error "MU-MIMO cannot be compiled for old IPC" ++#endif ++/// Interrupts bits used ++#if CONFIG_USER_MAX > 3 ++#define IPC_IRQ_A2E_USER_MSK 0xF ++#elif CONFIG_USER_MAX > 2 ++#define IPC_IRQ_A2E_USER_MSK 0x7 ++#else ++#define IPC_IRQ_A2E_USER_MSK 0x3 ++#endif ++ ++/// Offset of the interrupts for AC0 ++#define IPC_IRQ_A2E_AC0_OFT 8 ++/// Mask of the interrupts for AC0 ++#define IPC_IRQ_A2E_AC0_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC0_OFT) ++/// Offset of the interrupts for AC1 ++#define IPC_IRQ_A2E_AC1_OFT (IPC_IRQ_A2E_AC0_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC1 ++#define IPC_IRQ_A2E_AC1_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC1_OFT) ++/// Offset of the interrupts for AC2 ++#define IPC_IRQ_A2E_AC2_OFT (IPC_IRQ_A2E_AC1_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC2 ++#define IPC_IRQ_A2E_AC2_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC2_OFT) ++/// Offset of the interrupts for AC3 ++#define IPC_IRQ_A2E_AC3_OFT (IPC_IRQ_A2E_AC2_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC3 ++#define IPC_IRQ_A2E_AC3_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC3_OFT) ++/// Offset of the interrupts for BCN ++#define IPC_IRQ_A2E_BCN_OFT (IPC_IRQ_A2E_AC3_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for BCN ++#define IPC_IRQ_A2E_BCN_MSK CO_BIT(IPC_IRQ_A2E_BCN_OFT) ++ ++#define IPC_IRQ_A2E_AC_TXDESC (IPC_IRQ_A2E_AC0_MSK | IPC_IRQ_A2E_AC1_MSK | \ ++ IPC_IRQ_A2E_AC2_MSK | IPC_IRQ_A2E_AC3_MSK) ++ ++/// Interrupts bits used for the TX descriptors of the BCN queue ++#if NX_TXQ_CNT < 5 ++#define IPC_IRQ_A2E_BCN_TXDESC 0 ++#else ++#define IPC_IRQ_A2E_BCN_TXDESC (0x01 << IPC_IRQ_A2E_BCN_OFT) ++#endif ++ ++/// IPC TX descriptor interrupt mask ++#define IPC_IRQ_A2E_TXDESC (IPC_IRQ_A2E_AC_TXDESC | IPC_IRQ_A2E_BCN_TXDESC) ++#else ++/// IPC TX descriptor interrupt mask ++#define IPC_IRQ_A2E_TXDESC 0xFF00 ++#endif ++ ++#define IPC_IRQ_A2E_TXDESC_FIRSTBIT (8) ++#define IPC_IRQ_A2E_RXBUF_BACK CO_BIT(5) ++#define IPC_IRQ_A2E_RXDESC_BACK CO_BIT(4) ++ ++#define IPC_IRQ_A2E_MSG CO_BIT(1) ++#define IPC_IRQ_A2E_DBG CO_BIT(0) ++ ++#define IPC_IRQ_A2E_ALL (IPC_IRQ_A2E_TXDESC|IPC_IRQ_A2E_MSG|IPC_IRQ_A2E_DBG) ++ ++// IRQs from emb to app ++#define IPC_IRQ_E2A_TXCFM_POS 7 ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++#ifdef CONFIG_RWNX_OLD_IPC ++#error "MU-MIMO cannot be compiled for old IPC" ++#endif ++/// Interrupts bits used ++#if CONFIG_USER_MAX > 3 ++#define IPC_IRQ_E2A_USER_MSK 0xF ++#elif CONFIG_USER_MAX > 2 ++#define IPC_IRQ_E2A_USER_MSK 0x7 ++#else ++#define IPC_IRQ_E2A_USER_MSK 0x3 ++#endif ++ ++/// Offset of the interrupts for AC0 ++#define IPC_IRQ_E2A_AC0_OFT IPC_IRQ_E2A_TXCFM_POS ++/// Mask of the interrupts for AC0 ++#define IPC_IRQ_E2A_AC0_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC0_OFT) ++/// Offset of the interrupts for AC1 ++#define IPC_IRQ_E2A_AC1_OFT (IPC_IRQ_E2A_AC0_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC1 ++#define IPC_IRQ_E2A_AC1_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC1_OFT) ++/// Offset of the interrupts for AC2 ++#define IPC_IRQ_E2A_AC2_OFT (IPC_IRQ_E2A_AC1_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC2 ++#define IPC_IRQ_E2A_AC2_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC2_OFT) ++/// Offset of the interrupts for AC3 ++#define IPC_IRQ_E2A_AC3_OFT (IPC_IRQ_E2A_AC2_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for AC3 ++#define IPC_IRQ_E2A_AC3_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC3_OFT) ++/// Offset of the interrupts for BCN ++#define IPC_IRQ_E2A_BCN_OFT (IPC_IRQ_E2A_AC3_OFT + CONFIG_USER_MAX) ++/// Mask of the interrupts for BCN ++#define IPC_IRQ_E2A_BCN_MSK CO_BIT(IPC_IRQ_E2A_BCN_OFT) ++ ++#define IPC_IRQ_E2A_AC_TXCFM (IPC_IRQ_E2A_AC0_MSK | IPC_IRQ_E2A_AC1_MSK | \ ++ IPC_IRQ_E2A_AC2_MSK | IPC_IRQ_E2A_AC3_MSK) ++ ++/// Interrupts bits used for the TX descriptors of the BCN queue ++#if NX_TXQ_CNT < 5 ++#define IPC_IRQ_E2A_BCN_TXCFM 0 ++#else ++#define IPC_IRQ_E2A_BCN_TXCFM (0x01 << IPC_IRQ_E2A_BCN_OFT) ++#endif ++ ++/// IPC TX descriptor interrupt mask ++#define IPC_IRQ_E2A_TXCFM (IPC_IRQ_E2A_AC_TXCFM | IPC_IRQ_E2A_BCN_TXCFM) ++ ++#else ++ ++#define IPC_IRQ_E2A_TXCFM (((1 << NX_TXQ_CNT) - 1) << IPC_IRQ_E2A_TXCFM_POS) ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++#define IPC_IRQ_E2A_UNSUP_RX_VEC CO_BIT(7) ++#define IPC_IRQ_E2A_RADAR CO_BIT(6) ++#define IPC_IRQ_E2A_TBTT_SEC CO_BIT(5) ++#define IPC_IRQ_E2A_TBTT_PRIM CO_BIT(4) ++#define IPC_IRQ_E2A_RXDESC CO_BIT(3) ++#define IPC_IRQ_E2A_MSG_ACK CO_BIT(2) ++#define IPC_IRQ_E2A_MSG CO_BIT(1) ++#define IPC_IRQ_E2A_DBG CO_BIT(0) ++ ++#define IPC_IRQ_E2A_ALL (IPC_IRQ_E2A_TXCFM \ ++ | IPC_IRQ_E2A_RXDESC \ ++ | IPC_IRQ_E2A_MSG_ACK \ ++ | IPC_IRQ_E2A_MSG \ ++ | IPC_IRQ_E2A_DBG \ ++ | IPC_IRQ_E2A_TBTT_PRIM \ ++ | IPC_IRQ_E2A_TBTT_SEC \ ++ | IPC_IRQ_E2A_RADAR \ ++ | IPC_IRQ_E2A_UNSUP_RX_VEC) ++ ++// FLAGS for RX desc ++#define IPC_RX_FORWARD CO_BIT(1) ++#define IPC_RX_INTRABSS CO_BIT(0) ++ ++ ++// IPC message TYPE ++enum { ++ IPC_MSG_NONE = 0, ++ IPC_MSG_WRAP, ++ IPC_MSG_KMSG, ++ ++ IPC_DBG_STRING, ++ ++}; ++ ++#endif // _IPC_SHARED_H_ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h +new file mode 100644 +index 000000000000..2753d4d23253 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h +@@ -0,0 +1,564 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file lmac_mac_types.h ++ * ++ * @brief MAC related definitions. ++ * ++ * Adapted from mac_types.h to used lmac_types.h instead of standard types ++ * eg: perl -pi -e '$_ =~ s/uint(\d{1,2})_t/u$1_l/g; \ ++ * $_ =~ s/int(\d{1,2})_t/s$1_l/g; \ ++ * $_ =~ s/CO_BIT/BIT/g;' lmac_mac.h ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef LMAC_MAC_H_ ++#define LMAC_MAC_H_ ++ ++#include "lmac_types.h" ++ ++/// Interface types ++enum mac_vif_type { ++ /// ESS STA interface ++ VIF_STA, ++ /// IBSS STA interface ++ VIF_IBSS, ++ /// AP interface ++ VIF_AP, ++ /// Mesh Point interface ++ VIF_MESH_POINT, ++ /// Monitor interface ++ VIF_MONITOR, ++ /// Unknown type ++ VIF_UNKNOWN ++}; ++ ++/// MAC address length in bytes. ++#define MAC_ADDR_LEN 6 ++ ++/// MAC address structure. ++struct mac_addr { ++ /// Array of 16-bit words that make up the MAC address. ++ u16_l array[MAC_ADDR_LEN/2]; ++}; ++ ++/// SSID maximum length. ++#define MAC_SSID_LEN 32 ++ ++/// SSID. ++struct mac_ssid { ++ /// Actual length of the SSID. ++ u8_l length; ++ /// Array containing the SSID name. ++ u8_l array[MAC_SSID_LEN]; ++}; ++ ++/// BSS type ++enum mac_bss_type { ++ INFRASTRUCTURE_MODE = 1, ++ INDEPENDENT_BSS_MODE, ++ ANY_BSS_MODE ++}; ++ ++/// Channel Band ++enum mac_chan_band { ++ /// 2.4GHz Band ++ PHY_BAND_2G4, ++ /// 5GHz band ++ PHY_BAND_5G, ++ /// Number of bands ++ PHY_BAND_MAX, ++}; ++ ++/// Operating Channel Bandwidth ++enum mac_chan_bandwidth { ++ /// 20MHz BW ++ PHY_CHNL_BW_20, ++ /// 40MHz BW ++ PHY_CHNL_BW_40, ++ /// 80MHz BW ++ PHY_CHNL_BW_80, ++ /// 160MHz BW ++ PHY_CHNL_BW_160, ++ /// 80+80MHz BW ++ PHY_CHNL_BW_80P80, ++ /// Reserved BW ++ PHY_CHNL_BW_OTHER, ++}; ++ ++/// max number of channels in the 2.4 GHZ band ++#define MAC_DOMAINCHANNEL_24G_MAX 14 ++ ++/// max number of channels in the 5 GHZ band ++#define MAC_DOMAINCHANNEL_5G_MAX 28 ++ ++/// Channel Flag ++enum mac_chan_flags { ++ /// Cannot initiate radiation on this channel ++ CHAN_NO_IR = BIT(0), ++ /// Channel is not allowed ++ CHAN_DISABLED = BIT(1), ++ /// Radar detection required on this channel ++ CHAN_RADAR = BIT(2), ++}; ++ ++/// Primary Channel definition ++struct mac_chan_def { ++ /// Frequency of the channel (in MHz) ++ u16_l freq; ++ /// RF band (@ref mac_chan_band) ++ u8_l band; ++ /// Additional information (@ref mac_chan_flags) ++ u8_l flags; ++ /// Max transmit power allowed on this channel (dBm) ++ s8_l tx_power; ++}; ++ ++/// Operating Channel ++struct mac_chan_op { ++ /// Band (@ref mac_chan_band) ++ u8_l band; ++ /// Channel type (@ref mac_chan_bandwidth) ++ u8_l type; ++ /// Frequency for Primary 20MHz channel (in MHz) ++ u16_l prim20_freq; ++ /// Frequency center of the contiguous channel or center of Primary 80+80 (in MHz) ++ u16_l center1_freq; ++ /// Frequency center of the non-contiguous secondary 80+80 (in MHz) ++ u16_l center2_freq; ++ /// Max transmit power allowed on this channel (dBm) ++ s8_l tx_power; ++ /// Additional information (@ref mac_chan_flags) ++ u8_l flags; ++}; ++ ++/// Cipher suites (order is important as it is used by MACHW) ++enum mac_cipher_suite { ++ /// 00-0F-AC 1 ++ MAC_CIPHER_WEP40 = 0, ++ /// 00-0F-AC 2 ++ MAC_CIPHER_TKIP = 1, ++ /// 00-0F-AC 4 ++ MAC_CIPHER_CCMP = 2, ++ /// 00-0F-AC 5 ++ MAC_CIPHER_WEP104 = 3, ++ /// 00-14-72 1 ++ MAC_CIPHER_WPI_SMS4 = 4, ++ /// 00-0F-AC 6 (aka AES_CMAC) ++ MAC_CIPHER_BIP_CMAC_128 = 5, ++ ++ // following cipher are not supported by MACHW ++ /// 00-0F-AC 08 ++ MAC_CIPHER_GCMP_128, ++ /// 00-0F-AC 09 ++ MAC_CIPHER_GCMP_256, ++ /// 00-0F-AC 10 ++ MAC_CIPHER_CCMP_256, ++ /// 00-0F-AC 11 ++ MAC_CIPHER_BIP_GMAC_128, ++ /// 00-0F-AC 12 ++ MAC_CIPHER_BIP_GMAC_256, ++ /// 00-0F-AC 13 ++ MAC_CIPHER_BIP_CMAC_256, ++ ++ MAC_CIPHER_INVALID = 0xFF ++}; ++ ++/// Authentication and Key Management suite ++enum mac_akm_suite { ++ /// No security ++ MAC_AKM_NONE, ++ /// Pre RSN (WEP or WPA) ++ MAC_AKM_PRE_RSN, ++ /// 00-0F-AC 1 ++ MAC_AKM_8021X, ++ /// 00-0F-AC 2 ++ MAC_AKM_PSK, ++ /// 00-0F-AC 3 ++ MAC_AKM_FT_8021X, ++ /// 00-0F-AC 4 ++ MAC_AKM_FT_PSK, ++ /// 00-0F-AC 5 ++ MAC_AKM_8021X_SHA256, ++ /// 00-0F-AC 6 ++ MAC_AKM_PSK_SHA256, ++ /// 00-0F-AC 7 ++ MAC_AKM_TDLS, ++ /// 00-0F-AC 8 ++ MAC_AKM_SAE, ++ /// 00-0F-AC 9 ++ MAC_AKM_FT_OVER_SAE, ++ /// 00-0F-AC 11 ++ MAC_AKM_8021X_SUITE_B, ++ /// 00-0F-AC 12 ++ MAC_AKM_8021X_SUITE_B_192, ++ /// 00-0F-AC 14 ++ MAC_AKM_FILS_SHA256, ++ /// 00-0F-AC 15 ++ MAC_AKM_FILS_SHA384, ++ /// 00-0F-AC 16 ++ MAC_AKM_FT_FILS_SHA256, ++ /// 00-0F-AC 17 ++ MAC_AKM_FT_FILS_SHA384, ++ /// 00-0F-AC 18 ++ MAC_AKM_OWE, ++ ++ /// 00-14-72 1 ++ MAC_AKM_WAPI_CERT, ++ /// 00-14-72 2 ++ MAC_AKM_WAPI_PSK, ++}; ++ ++/// Scan result element, parsed from beacon or probe response frames. ++struct mac_scan_result { ++ /// Scan result is valid ++ bool valid_flag; ++ /// Network BSSID. ++ struct mac_addr bssid; ++ /// Network name. ++ struct mac_ssid ssid; ++ /// Network type (@ref mac_bss_type). ++ u16_l bsstype; ++ /// Network channel. ++ struct mac_chan_def *chan; ++ /// Network beacon period (in TU). ++ u16_l beacon_period; ++ /// Capability information ++ u16_l cap_info; ++ /// Supported AKM (bit-field of @ref mac_akm_suite) ++ u32_l akm; ++ /// Group cipher (bit-field of @ref mac_cipher_suite) ++ u16_l group_cipher; ++ /// Group cipher (bit-field of @ref mac_cipher_suite) ++ u16_l pairwise_cipher; ++ /// RSSI of the scanned BSS (in dBm) ++ s8_l rssi; ++}; ++ ++/// Legacy rate 802.11 definitions ++enum mac_legacy_rates { ++ /// DSSS/CCK 1Mbps ++ MAC_RATE_1MBPS = 2, ++ /// DSSS/CCK 2Mbps ++ MAC_RATE_2MBPS = 4, ++ /// DSSS/CCK 5.5Mbps ++ MAC_RATE_5_5MBPS = 11, ++ /// OFDM 6Mbps ++ MAC_RATE_6MBPS = 12, ++ /// OFDM 9Mbps ++ MAC_RATE_9MBPS = 18, ++ /// DSSS/CCK 11Mbps ++ MAC_RATE_11MBPS = 22, ++ /// OFDM 12Mbps ++ MAC_RATE_12MBPS = 24, ++ /// OFDM 18Mbps ++ MAC_RATE_18MBPS = 36, ++ /// OFDM 24Mbps ++ MAC_RATE_24MBPS = 48, ++ /// OFDM 36Mbps ++ MAC_RATE_36MBPS = 72, ++ /// OFDM 48Mbps ++ MAC_RATE_48MBPS = 96, ++ /// OFDM 54Mbps ++ MAC_RATE_54MBPS = 108 ++}; ++ ++/// BSS Membership Selector definitions ++enum mac_bss_membership { ++ /// HT PHY ++ MAC_BSS_MEMBERSHIP_HT_PHY = 127, ++ /// VHT PHY ++ MAC_BSS_MEMBERSHIP_VHT_PHY = 126, ++}; ++ ++/// MAC rateset maximum length ++#define MAC_RATESET_LEN 12 ++ ++/// Structure containing the legacy rateset of a station ++struct mac_rateset { ++ /// Number of legacy rates supported ++ u8_l length; ++ /// Array of legacy rates ++ u8_l array[MAC_RATESET_LEN]; ++}; ++ ++/// MAC Security Key maximum length ++#define MAC_SEC_KEY_LEN 32 // TKIP keys 256 bits (max length) with MIC keys ++ ++/// Structure defining a security key ++struct mac_sec_key { ++ /// Key material length ++ u8_l length; ++ /// Key material ++ u32_l array[MAC_SEC_KEY_LEN/4]; ++}; ++ ++/// Access Category enumeration ++enum mac_ac { ++ /// Background ++ AC_BK = 0, ++ /// Best-effort ++ AC_BE, ++ /// Video ++ AC_VI, ++ /// Voice ++ AC_VO, ++ /// Number of access categories ++ AC_MAX ++}; ++ ++/// Traffic ID enumeration ++enum mac_tid { ++ /// TID_0. Mapped to @ref AC_BE as per 802.11 standard. ++ TID_0, ++ /// TID_1. Mapped to @ref AC_BK as per 802.11 standard. ++ TID_1, ++ /// TID_2. Mapped to @ref AC_BK as per 802.11 standard. ++ TID_2, ++ /// TID_3. Mapped to @ref AC_BE as per 802.11 standard. ++ TID_3, ++ /// TID_4. Mapped to @ref AC_VI as per 802.11 standard. ++ TID_4, ++ /// TID_5. Mapped to @ref AC_VI as per 802.11 standard. ++ TID_5, ++ /// TID_6. Mapped to @ref AC_VO as per 802.11 standard. ++ TID_6, ++ /// TID_7. Mapped to @ref AC_VO as per 802.11 standard. ++ TID_7, ++ /// Non standard Management TID used internally ++ TID_MGT, ++ /// Number of TID supported ++ TID_MAX ++}; ++ ++/// MCS bitfield maximum size (in bytes) ++#define MAX_MCS_LEN 16 // 16 * 8 = 128 ++ ++/// MAC HT capability information element ++struct mac_htcapability { ++ /// HT capability information ++ u16_l ht_capa_info; ++ /// A-MPDU parameters ++ u8_l a_mpdu_param; ++ /// Supported MCS ++ u8_l mcs_rate[MAX_MCS_LEN]; ++ /// HT extended capability information ++ u16_l ht_extended_capa; ++ /// Beamforming capability information ++ u32_l tx_beamforming_capa; ++ /// Antenna selection capability information ++ u8_l asel_capa; ++}; ++ ++/// MAC VHT capability information element ++struct mac_vhtcapability { ++ /// VHT capability information ++ u32_l vht_capa_info; ++ /// RX MCS map ++ u16_l rx_mcs_map; ++ /// RX highest data rate ++ u16_l rx_highest; ++ /// TX MCS map ++ u16_l tx_mcs_map; ++ /// TX highest data rate ++ u16_l tx_highest; ++}; ++ ++/// Length (in bytes) of the MAC HE capability field ++#define MAC_HE_MAC_CAPA_LEN 6 ++/// Length (in bytes) of the PHY HE capability field ++#define MAC_HE_PHY_CAPA_LEN 11 ++/// Maximum length (in bytes) of the PPE threshold data ++#define MAC_HE_PPE_THRES_MAX_LEN 25 ++ ++/// Structure listing the per-NSS, per-BW supported MCS combinations ++struct mac_he_mcs_nss_supp { ++ /// per-NSS supported MCS in RX, for BW <= 80MHz ++ u16_l rx_mcs_80; ++ /// per-NSS supported MCS in TX, for BW <= 80MHz ++ u16_l tx_mcs_80; ++ /// per-NSS supported MCS in RX, for BW = 160MHz ++ u16_l rx_mcs_160; ++ /// per-NSS supported MCS in TX, for BW = 160MHz ++ u16_l tx_mcs_160; ++ /// per-NSS supported MCS in RX, for BW = 80+80MHz ++ u16_l rx_mcs_80p80; ++ /// per-NSS supported MCS in TX, for BW = 80+80MHz ++ u16_l tx_mcs_80p80; ++}; ++ ++/// MAC HE capability information element ++struct mac_hecapability { ++ /// MAC HE capabilities ++ u8_l mac_cap_info[MAC_HE_MAC_CAPA_LEN]; ++ /// PHY HE capabilities ++ u8_l phy_cap_info[MAC_HE_PHY_CAPA_LEN]; ++ /// Supported MCS combinations ++ struct mac_he_mcs_nss_supp mcs_supp; ++ /// PPE Thresholds data ++ u8_l ppe_thres[MAC_HE_PPE_THRES_MAX_LEN]; ++}; ++ ++/// Station flags ++enum mac_sta_flags { ++ /// Bit indicating that a STA has QoS (WMM) capability ++ STA_QOS_CAPA = BIT(0), ++ /// Bit indicating that a STA has HT capability ++ STA_HT_CAPA = BIT(1), ++ /// Bit indicating that a STA has VHT capability ++ STA_VHT_CAPA = BIT(2), ++ /// Bit indicating that a STA has MFP capability ++ STA_MFP_CAPA = BIT(3), ++ /// Bit indicating that the STA included the Operation Notification IE ++ STA_OPMOD_NOTIF = BIT(4), ++ /// Bit indicating that a STA has HE capability ++ STA_HE_CAPA = BIT(5), ++}; ++ ++/// Connection flags ++enum mac_connection_flags { ++ /// Flag indicating whether the control port is controlled by host or not ++ CONTROL_PORT_HOST = BIT(0), ++ /// Flag indicating whether the control port frame shall be sent unencrypted ++ CONTROL_PORT_NO_ENC = BIT(1), ++ /// Flag indicating whether HT and VHT shall be disabled or not ++ DISABLE_HT = BIT(2), ++ /// Flag indicating whether WPA or WPA2 authentication is in use ++ WPA_WPA2_IN_USE = BIT(3), ++ /// Flag indicating whether MFP is in use ++ MFP_IN_USE = BIT(4), ++ // Flag indicating Roam ++ REASSOCIATION = BIT(5), ++}; ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++#define IEEE80211_HE_MAC_CAP2_ALL_ACK 0x02 ++#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02 ++#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04 ++#define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD 0x20 ++#define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US 0x40 ++#define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS 0x80 ++#define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS 0x01 ++#define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US 0x02 ++#define IEEE80211_HE_PHY_CAP2_DOPPLER_RX 0x20 ++#define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ 0x08 ++#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM 0x18 ++#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 0x00 ++#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA 0x40 ++#define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE 0x01 ++#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 0x0c ++#define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK 0x40 ++#define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK 0x80 ++#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU 0x01 ++#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU 0x02 ++#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB 0x04 ++#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB 0x08 ++#define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT 0x80 ++#define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO 0x40 ++#define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI 0x04 ++#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G 0x02 ++#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB 0x10 ++#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB 0x20 ++ ++#define IEEE80211_HE_PPE_THRES_MAX_LEN 25 ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) ++#define WLAN_EID_EXTENSION 255 ++/* Element ID Extensions for Element ID 255 */ ++ ++enum ieee80211_eid_ext { ++ WLAN_EID_EXT_ASSOC_DELAY_INFO = 1, ++ WLAN_EID_EXT_FILS_REQ_PARAMS = 2, ++ WLAN_EID_EXT_FILS_KEY_CONFIRM = 3, ++ WLAN_EID_EXT_FILS_SESSION = 4, ++ WLAN_EID_EXT_FILS_HLP_CONTAINER = 5, ++ WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN = 6, ++ WLAN_EID_EXT_KEY_DELIVERY = 7, ++ WLAN_EID_EXT_FILS_WRAPPED_DATA = 8, ++ WLAN_EID_EXT_FILS_PUBLIC_KEY = 12, ++ WLAN_EID_EXT_FILS_NONCE = 13, ++ WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE = 14, ++ ++}; ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define WLAN_EID_EXT_HE_CAPABILITY 35 ++#define WLAN_EID_EXT_HE_OPERATION 36 ++#define WLAN_EID_EXT_UORA 37 ++#define WLAN_EID_EXT_HE_MU_EDCA 38 ++#define WLAN_EID_EXT_HE_SPR 39 ++#define WLAN_EID_EXT_NDP_FEEDBACK_REPORT_PARAMSET 41 ++#define WLAN_EID_EXT_BSS_COLOR_CHG_ANN 42 ++#define WLAN_EID_EXT_QUIET_TIME_PERIOD_SETUP 43 ++#define WLAN_EID_EXT_ESS_REPORT 45 ++#define WLAN_EID_EXT_OPS 46 ++#define WLAN_EID_EXT_HE_BSS_LOAD 47 ++#define WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME 52 ++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55 ++#define WLAN_EID_EXT_NON_INHERITANCE 56 ++#define WLAN_EID_EXT_KNOWN_BSSID 57 ++#define WLAN_EID_EXT_SHORT_SSID_LIST 58 ++#define WLAN_EID_EXT_HE_6GHZ_CAPA 59 ++#define WLAN_EID_EXT_UL_MU_POWER_CAPA 60 ++#define WLAN_EID_EXT_EHT_OPERATION 106 ++#define WLAN_EID_EXT_EHT_MULTI_LINK 107 ++#define WLAN_EID_EXT_EHT_CAPABILITY 108 ++#endif ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++#include ++#else ++struct ieee80211_he_cap_elem { ++ u8 mac_cap_info[6]; ++ u8 phy_cap_info[11]; ++} __packed; ++ ++struct ieee80211_he_mcs_nss_supp { ++ __le16 rx_mcs_80; ++ __le16 tx_mcs_80; ++ __le16 rx_mcs_160; ++ __le16 tx_mcs_160; ++ __le16 rx_mcs_80p80; ++ __le16 tx_mcs_80p80; ++} __packed; ++ ++struct ieee80211_sta_he_cap { ++ bool has_he; ++ struct ieee80211_he_cap_elem he_cap_elem; ++ struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; ++ u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; ++}; ++ ++struct ieee80211_sband_iftype_data { ++ u16 types_mask; ++ struct ieee80211_sta_he_cap he_cap; ++}; ++#endif ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++struct ieee80211_vht_mcs_info { ++ __le16 rx_mcs_map; ++ __le16 rx_highest; ++ __le16 tx_mcs_map; ++ __le16 tx_highest; ++} __packed; ++ ++struct ieee80211_vht_cap { ++ __le32 vht_cap_info; ++ struct ieee80211_vht_mcs_info supp_mcs; ++}; ++#define WLAN_EID_VHT_CAPABILITY 191 ++ ++struct ieee80211_sta_vht_cap { ++ bool vht_supported; ++ u32 cap; /* use IEEE80211_VHT_CAP_ */ ++ struct ieee80211_vht_mcs_info vht_mcs; ++}; ++#endif ++#endif // LMAC_MAC_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h +new file mode 100644 +index 000000000000..96f492bba754 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h +@@ -0,0 +1,3224 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file lmac_msg.h ++ * ++ * @brief Main definitions for message exchanges with LMAC ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef LMAC_MSG_H_ ++#define LMAC_MSG_H_ ++ ++/* ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++// for MAC related elements (mac_addr, mac_ssid...) ++#include "lmac_mac.h" ++ ++#define LMAC_MSG_MAX_LEN 1024 ++ ++/* ++ **************************************************************************************** ++ */ ++///////////////////////////////////////////////////////////////////////////////// ++// COMMUNICATION WITH LMAC LAYER ++///////////////////////////////////////////////////////////////////////////////// ++/* Task identifiers for communication between LMAC and DRIVER */ ++enum { ++ TASK_NONE = (u8_l) -1, ++ ++ // MAC Management task. ++ TASK_MM = 0, ++ // DEBUG task ++ TASK_DBG, ++ /// SCAN task ++ TASK_SCAN, ++ /// TDLS task ++ TASK_TDLS, ++ /// SCANU task ++ TASK_SCANU, ++ /// ME task ++ TASK_ME, ++ /// SM task ++ TASK_SM, ++ /// APM task ++ TASK_APM, ++ /// BAM task ++ TASK_BAM, ++ /// MESH task ++ TASK_MESH, ++ /// RXU task ++ TASK_RXU, ++ /// RM_task ++ TASK_RM, ++ /// TWT task ++ TASK_TWT, ++#if defined CONFIG_RWNX_FULLMAC || defined CONFIG_RWNX_FHOST ++ // This is used to define the last task that is running on the EMB processor ++ TASK_LAST_EMB = TASK_TWT, ++#else ++#error "Need to define SOFTMAC or FULLMAC" ++#endif ++ // nX API task ++ TASK_API, ++ TASK_MAX, ++}; ++ ++ ++/// For MAC HW States copied from "hal_machw.h" ++enum { ++ /// MAC HW IDLE State. ++ HW_IDLE = 0, ++ /// MAC HW RESERVED State. ++ HW_RESERVED, ++ /// MAC HW DOZE State. ++ HW_DOZE, ++ /// MAC HW ACTIVE State. ++ HW_ACTIVE ++}; ++ ++/// Power Save mode setting ++enum mm_ps_mode_state { ++ MM_PS_MODE_OFF, ++ MM_PS_MODE_ON, ++ MM_PS_MODE_ON_DYN, ++}; ++ ++/// Status/error codes used in the MAC software. ++enum { ++ CO_OK, ++ CO_FAIL, ++ CO_EMPTY, ++ CO_FULL, ++ CO_BAD_PARAM, ++ CO_NOT_FOUND, ++ CO_NO_MORE_ELT_AVAILABLE, ++ CO_NO_ELT_IN_USE, ++ CO_BUSY, ++ CO_OP_IN_PROGRESS, ++}; ++ ++/// Remain on channel operation codes ++enum mm_remain_on_channel_op { ++ MM_ROC_OP_START = 0, ++ MM_ROC_OP_CANCEL, ++}; ++ ++#define DRV_TASK_ID 100 ++ ++/// Message Identifier. The number of messages is limited to 0xFFFF. ++/// The message ID is divided in two parts: ++/// - bits[15..10] : task index (no more than 64 tasks supported). ++/// - bits[9..0] : message index (no more that 1024 messages per task). ++typedef u16 lmac_msg_id_t; ++ ++typedef u16 lmac_task_id_t; ++ ++/// Build the first message ID of a task. ++#define LMAC_FIRST_MSG(task) ((lmac_msg_id_t)((task) << 10)) ++ ++#define MSG_T(msg) ((lmac_task_id_t)((msg) >> 10)) ++#define MSG_I(msg) ((msg) & ((1<<10)-1)) ++ ++/// Message structure. ++struct lmac_msg { ++ lmac_msg_id_t id; ///< Message id. ++ lmac_task_id_t dest_id; ///< Destination kernel identifier. ++ lmac_task_id_t src_id; ///< Source kernel identifier. ++ u16 param_len; ///< Parameter embedded struct length. ++ u32 param[]; ///< Parameter embedded struct. Must be word-aligned. ++}; ++ ++/// List of messages related to the task. ++enum mm_msg_tag { ++ /// RESET Request. ++ MM_RESET_REQ = LMAC_FIRST_MSG(TASK_MM), ++ /// RESET Confirmation. ++ MM_RESET_CFM, ++ /// START Request. ++ MM_START_REQ, ++ /// START Confirmation. ++ MM_START_CFM, ++ /// Read Version Request. ++ MM_VERSION_REQ, ++ /// Read Version Confirmation. ++ MM_VERSION_CFM, ++ /// ADD INTERFACE Request. ++ MM_ADD_IF_REQ, ++ /// ADD INTERFACE Confirmation. ++ MM_ADD_IF_CFM, ++ /// REMOVE INTERFACE Request. ++ MM_REMOVE_IF_REQ, ++ /// REMOVE INTERFACE Confirmation. ++ MM_REMOVE_IF_CFM, ++ /// STA ADD Request. ++ MM_STA_ADD_REQ, ++ /// STA ADD Confirm. ++ MM_STA_ADD_CFM, ++ /// STA DEL Request. ++ MM_STA_DEL_REQ, ++ /// STA DEL Confirm. ++ MM_STA_DEL_CFM, ++ /// RX FILTER CONFIGURATION Request. ++ MM_SET_FILTER_REQ, ++ /// RX FILTER CONFIGURATION Confirmation. ++ MM_SET_FILTER_CFM, ++ /// CHANNEL CONFIGURATION Request. ++ MM_SET_CHANNEL_REQ, ++ /// CHANNEL CONFIGURATION Confirmation. ++ MM_SET_CHANNEL_CFM, ++ /// DTIM PERIOD CONFIGURATION Request. ++ MM_SET_DTIM_REQ, ++ /// DTIM PERIOD CONFIGURATION Confirmation. ++ MM_SET_DTIM_CFM, ++ /// BEACON INTERVAL CONFIGURATION Request. ++ MM_SET_BEACON_INT_REQ, ++ /// BEACON INTERVAL CONFIGURATION Confirmation. ++ MM_SET_BEACON_INT_CFM, ++ /// BASIC RATES CONFIGURATION Request. ++ MM_SET_BASIC_RATES_REQ, ++ /// BASIC RATES CONFIGURATION Confirmation. ++ MM_SET_BASIC_RATES_CFM, ++ /// BSSID CONFIGURATION Request. ++ MM_SET_BSSID_REQ, ++ /// BSSID CONFIGURATION Confirmation. ++ MM_SET_BSSID_CFM, ++ /// EDCA PARAMETERS CONFIGURATION Request. ++ MM_SET_EDCA_REQ, ++ /// EDCA PARAMETERS CONFIGURATION Confirmation. ++ MM_SET_EDCA_CFM, ++ /// ABGN MODE CONFIGURATION Request. ++ MM_SET_MODE_REQ, ++ /// ABGN MODE CONFIGURATION Confirmation. ++ MM_SET_MODE_CFM, ++ /// Request setting the VIF active state (i.e associated or AP started) ++ MM_SET_VIF_STATE_REQ, ++ /// Confirmation of the @ref MM_SET_VIF_STATE_REQ message. ++ MM_SET_VIF_STATE_CFM, ++ /// SLOT TIME PARAMETERS CONFIGURATION Request. ++ MM_SET_SLOTTIME_REQ, ++ /// SLOT TIME PARAMETERS CONFIGURATION Confirmation. ++ MM_SET_SLOTTIME_CFM, ++ /// Power Mode Change Request. ++ MM_SET_IDLE_REQ, ++ /// Power Mode Change Confirm. ++ MM_SET_IDLE_CFM, ++ /// KEY ADD Request. ++ MM_KEY_ADD_REQ, ++ /// KEY ADD Confirm. ++ MM_KEY_ADD_CFM, ++ /// KEY DEL Request. ++ MM_KEY_DEL_REQ, ++ /// KEY DEL Confirm. ++ MM_KEY_DEL_CFM, ++ /// Block Ack agreement info addition ++ MM_BA_ADD_REQ, ++ /// Block Ack agreement info addition confirmation ++ MM_BA_ADD_CFM, ++ /// Block Ack agreement info deletion ++ MM_BA_DEL_REQ, ++ /// Block Ack agreement info deletion confirmation ++ MM_BA_DEL_CFM, ++ /// Indication of the primary TBTT to the upper MAC. Upon the reception of this ++ // message the upper MAC has to push the beacon(s) to the beacon transmission queue. ++ MM_PRIMARY_TBTT_IND, ++ /// Indication of the secondary TBTT to the upper MAC. Upon the reception of this ++ // message the upper MAC has to push the beacon(s) to the beacon transmission queue. ++ MM_SECONDARY_TBTT_IND, ++ /// Request for changing the TX power ++ MM_SET_POWER_REQ, ++ /// Confirmation of the TX power change ++ MM_SET_POWER_CFM, ++ /// Request to the LMAC to trigger the embedded logic analyzer and forward the debug ++ /// dump. ++ MM_DBG_TRIGGER_REQ, ++ /// Set Power Save mode ++ MM_SET_PS_MODE_REQ, ++ /// Set Power Save mode confirmation ++ MM_SET_PS_MODE_CFM, ++ /// Request to add a channel context ++ MM_CHAN_CTXT_ADD_REQ, ++ /// Confirmation of the channel context addition ++ MM_CHAN_CTXT_ADD_CFM, ++ /// Request to delete a channel context ++ MM_CHAN_CTXT_DEL_REQ, ++ /// Confirmation of the channel context deletion ++ MM_CHAN_CTXT_DEL_CFM, ++ /// Request to link a channel context to a VIF ++ MM_CHAN_CTXT_LINK_REQ, ++ /// Confirmation of the channel context link ++ MM_CHAN_CTXT_LINK_CFM, ++ /// Request to unlink a channel context from a VIF ++ MM_CHAN_CTXT_UNLINK_REQ, ++ /// Confirmation of the channel context unlink ++ MM_CHAN_CTXT_UNLINK_CFM, ++ /// Request to update a channel context ++ MM_CHAN_CTXT_UPDATE_REQ, ++ /// Confirmation of the channel context update ++ MM_CHAN_CTXT_UPDATE_CFM, ++ /// Request to schedule a channel context ++ MM_CHAN_CTXT_SCHED_REQ, ++ /// Confirmation of the channel context scheduling ++ MM_CHAN_CTXT_SCHED_CFM, ++ /// Request to change the beacon template in LMAC ++ MM_BCN_CHANGE_REQ, ++ /// Confirmation of the beacon change ++ MM_BCN_CHANGE_CFM, ++ /// Request to update the TIM in the beacon (i.e to indicate traffic bufferized at AP) ++ MM_TIM_UPDATE_REQ, ++ /// Confirmation of the TIM update ++ MM_TIM_UPDATE_CFM, ++ /// Connection loss indication ++ MM_CONNECTION_LOSS_IND, ++ /// Channel context switch indication to the upper layers ++ MM_CHANNEL_SWITCH_IND, ++ /// Channel context pre-switch indication to the upper layers ++ MM_CHANNEL_PRE_SWITCH_IND, ++ /// Request to remain on channel or cancel remain on channel ++ MM_REMAIN_ON_CHANNEL_REQ, ++ /// Confirmation of the (cancel) remain on channel request ++ MM_REMAIN_ON_CHANNEL_CFM, ++ /// Remain on channel expired indication ++ MM_REMAIN_ON_CHANNEL_EXP_IND, ++ /// Indication of a PS state change of a peer device ++ MM_PS_CHANGE_IND, ++ /// Indication that some buffered traffic should be sent to the peer device ++ MM_TRAFFIC_REQ_IND, ++ /// Request to modify the STA Power-save mode options ++ MM_SET_PS_OPTIONS_REQ, ++ /// Confirmation of the PS options setting ++ MM_SET_PS_OPTIONS_CFM, ++ /// Indication of PS state change for a P2P VIF ++ MM_P2P_VIF_PS_CHANGE_IND, ++ /// Indication that CSA counter has been updated ++ MM_CSA_COUNTER_IND, ++ /// Channel occupation report indication ++ MM_CHANNEL_SURVEY_IND, ++ /// Message containing Beamformer Information ++ MM_BFMER_ENABLE_REQ, ++ /// Request to Start/Stop/Update NOA - GO Only ++ MM_SET_P2P_NOA_REQ, ++ /// Request to Start/Stop/Update Opportunistic PS - GO Only ++ MM_SET_P2P_OPPPS_REQ, ++ /// Start/Stop/Update NOA Confirmation ++ MM_SET_P2P_NOA_CFM, ++ /// Start/Stop/Update Opportunistic PS Confirmation ++ MM_SET_P2P_OPPPS_CFM, ++ /// P2P NoA Update Indication - GO Only ++ MM_P2P_NOA_UPD_IND, ++ /// Request to set RSSI threshold and RSSI hysteresis ++ MM_CFG_RSSI_REQ, ++ /// Indication that RSSI level is below or above the threshold ++ MM_RSSI_STATUS_IND, ++ /// Indication that CSA is done ++ MM_CSA_FINISH_IND, ++ /// Indication that CSA is in prorgess (resp. done) and traffic must be stopped (resp. restarted) ++ MM_CSA_TRAFFIC_IND, ++ /// Request to update the group information of a station ++ MM_MU_GROUP_UPDATE_REQ, ++ /// Confirmation of the @ref MM_MU_GROUP_UPDATE_REQ message ++ MM_MU_GROUP_UPDATE_CFM, ++ /// Request to initialize the antenna diversity algorithm ++ MM_ANT_DIV_INIT_REQ, ++ /// Request to stop the antenna diversity algorithm ++ MM_ANT_DIV_STOP_REQ, ++ /// Request to update the antenna switch status ++ MM_ANT_DIV_UPDATE_REQ, ++ /// Request to switch the antenna connected to path_0 ++ MM_SWITCH_ANTENNA_REQ, ++ /// Indication that a packet loss has occurred ++ MM_PKTLOSS_IND, ++ ++ MM_SET_ARPOFFLOAD_REQ, ++ MM_SET_ARPOFFLOAD_CFM, ++ MM_SET_AGG_DISABLE_REQ, ++ MM_SET_AGG_DISABLE_CFM, ++ MM_SET_COEX_REQ, ++ MM_SET_COEX_CFM, ++ MM_SET_RF_CONFIG_REQ, ++ MM_SET_RF_CONFIG_CFM, ++ MM_SET_RF_CALIB_REQ, ++ MM_SET_RF_CALIB_CFM, ++ ++ /// MU EDCA PARAMETERS Configuration Request. ++ MM_SET_MU_EDCA_REQ, ++ /// MU EDCA PARAMETERS Configuration Confirmation. ++ MM_SET_MU_EDCA_CFM, ++ /// UORA PARAMETERS Configuration Request. ++ MM_SET_UORA_REQ, ++ /// UORA PARAMETERS Configuration Confirmation. ++ MM_SET_UORA_CFM, ++ /// TXOP RTS THRESHOLD Configuration Request. ++ MM_SET_TXOP_RTS_THRES_REQ, ++ /// TXOP RTS THRESHOLD Configuration Confirmation. ++ MM_SET_TXOP_RTS_THRES_CFM, ++ /// HE BSS Color Configuration Request. ++ MM_SET_BSS_COLOR_REQ, ++ /// HE BSS Color Configuration Confirmation. ++ MM_SET_BSS_COLOR_CFM, ++ ++ MM_GET_MAC_ADDR_REQ, ++ MM_GET_MAC_ADDR_CFM, ++ ++ MM_GET_STA_INFO_REQ, ++ MM_GET_STA_INFO_CFM, ++ ++ MM_SET_TXPWR_IDX_LVL_REQ, ++ MM_SET_TXPWR_IDX_LVL_CFM, ++ ++ MM_SET_TXPWR_OFST_REQ, ++ MM_SET_TXPWR_OFST_CFM, ++ ++ MM_SET_STACK_START_REQ, ++ MM_SET_STACK_START_CFM, ++ ++ MM_APM_STALOSS_IND, ++ ++ MM_SET_VENDOR_HWCONFIG_REQ, ++ MM_SET_VENDOR_HWCONFIG_CFM, ++ ++ MM_GET_FW_VERSION_REQ, ++ MM_GET_FW_VERSION_CFM, ++ ++ MM_SET_RESUME_RESTORE_REQ, ++ MM_SET_RESUME_RESTORE_CFM, ++ ++ MM_GET_WIFI_DISABLE_REQ, ++ MM_GET_WIFI_DISABLE_CFM, ++ ++ MM_CFG_RSSI_CFM, ++ ++ MM_SET_VENDOR_SWCONFIG_REQ, ++ MM_SET_VENDOR_SWCONFIG_CFM, ++ ++ MM_SET_TXPWR_LVL_ADJ_REQ, ++ MM_SET_TXPWR_LVL_ADJ_CFM, ++ ++ MM_RADAR_DETECT_IND, ++ ++ MM_SET_APF_PROG_REQ, ++ MM_SET_APF_PROG_CFM, ++ ++ MM_GET_APF_PROG_REQ, ++ MM_GET_APF_PROG_CFM, ++ ++ /// MAX number of messages ++ MM_MAX, ++}; ++ ++/// Interface types ++enum { ++ /// ESS STA interface ++ MM_STA, ++ /// IBSS STA interface ++ MM_IBSS, ++ /// AP interface ++ MM_AP, ++ // Mesh Point interface ++ MM_MESH_POINT, ++ // Monitor interface ++ MM_MONITOR, ++}; ++ ++///BA agreement types ++enum { ++ ///BlockAck agreement for TX ++ BA_AGMT_TX, ++ ///BlockAck agreement for RX ++ BA_AGMT_RX, ++}; ++ ++///BA agreement related status ++enum { ++ ///Correct BA agreement establishment ++ BA_AGMT_ESTABLISHED, ++ ///BA agreement already exists for STA+TID requested, cannot override it (should have been deleted first) ++ BA_AGMT_ALREADY_EXISTS, ++ ///Correct BA agreement deletion ++ BA_AGMT_DELETED, ++ ///BA agreement for the (STA, TID) doesn't exist so nothing to delete ++ BA_AGMT_DOESNT_EXIST, ++}; ++ ++/// Features supported by LMAC - Positions ++enum mm_features { ++ /// Beaconing ++ MM_FEAT_BCN_BIT = 0, ++/* ++ /// Autonomous Beacon Transmission ++ MM_FEAT_AUTOBCN_BIT, ++ /// Scan in LMAC ++ MM_FEAT_HWSCAN_BIT, ++ /// Connection Monitoring ++ MM_FEAT_CMON_BIT, ++ /// Multi Role ++ MM_FEAT_MROLE_BIT, ++*/ ++ /// Radar Detection ++ MM_FEAT_RADAR_BIT, ++ /// Power Save ++ MM_FEAT_PS_BIT, ++ /// UAPSD ++ MM_FEAT_UAPSD_BIT, ++ /// DPSM ++// MM_FEAT_DPSM_BIT, ++ /// A-MPDU ++ MM_FEAT_AMPDU_BIT, ++ /// A-MSDU ++ MM_FEAT_AMSDU_BIT, ++ /// Channel Context ++// MM_FEAT_CHNL_CTXT_BIT, ++ /// Packet reordering ++// MM_FEAT_REORD_BIT, ++ /// P2P ++ MM_FEAT_P2P_BIT, ++ /// P2P Go ++ MM_FEAT_P2P_GO_BIT, ++ /// UMAC Present ++ MM_FEAT_UMAC_BIT, ++ /// VHT support ++ MM_FEAT_VHT_BIT, ++ /// Beamformee ++ MM_FEAT_BFMEE_BIT, ++ /// Beamformer ++ MM_FEAT_BFMER_BIT, ++ /// WAPI ++ MM_FEAT_WAPI_BIT, ++ /// MFP ++ MM_FEAT_MFP_BIT, ++ /// Mu-MIMO RX support ++ MM_FEAT_MU_MIMO_RX_BIT, ++ /// Mu-MIMO TX support ++ MM_FEAT_MU_MIMO_TX_BIT, ++ /// Wireless Mesh Networking ++ MM_FEAT_MESH_BIT, ++ /// TDLS support ++ MM_FEAT_TDLS_BIT, ++ /// Antenna Diversity support ++ MM_FEAT_ANT_DIV_BIT, ++ /// UF support ++ MM_FEAT_UF_BIT, ++ /// A-MSDU maximum size (bit0) ++ MM_AMSDU_MAX_SIZE_BIT0, ++ /// A-MSDU maximum size (bit1) ++ MM_AMSDU_MAX_SIZE_BIT1, ++ /// MON_DATA support ++ MM_FEAT_MON_DATA_BIT, ++ /// HE (802.11ax) support ++ MM_FEAT_HE_BIT, ++ /// TWT support ++ MM_FEAT_TWT_BIT, ++}; ++ ++/// Maximum number of words in the configuration buffer ++#define PHY_CFG_BUF_SIZE 16 ++ ++/// Structure containing the parameters of the PHY configuration ++struct phy_cfg_tag { ++ /// Buffer containing the parameters specific for the PHY used ++ u32_l parameters[PHY_CFG_BUF_SIZE]; ++}; ++ ++/// Structure containing the parameters of the Trident PHY configuration ++struct phy_trd_cfg_tag { ++ /// MDM type(nxm)(upper nibble) and MDM2RF path mapping(lower nibble) ++ u8_l path_mapping; ++ /// TX DC offset compensation ++ u32_l tx_dc_off_comp; ++}; ++ ++/// Structure containing the parameters of the Karst PHY configuration ++struct phy_karst_cfg_tag { ++ /// TX IQ mismatch compensation in 2.4GHz ++ u32_l tx_iq_comp_2_4G[2]; ++ /// RX IQ mismatch compensation in 2.4GHz ++ u32_l rx_iq_comp_2_4G[2]; ++ /// TX IQ mismatch compensation in 5GHz ++ u32_l tx_iq_comp_5G[2]; ++ /// RX IQ mismatch compensation in 5GHz ++ u32_l rx_iq_comp_5G[2]; ++ /// RF path used by default (0 or 1) ++ u8_l path_used; ++}; ++ ++/// Structure containing the parameters of the @ref MM_START_REQ message ++struct mm_start_req { ++ /// PHY configuration ++ struct phy_cfg_tag phy_cfg; ++ /// UAPSD timeout ++ u32_l uapsd_timeout; ++ /// Local LP clock accuracy (in ppm) ++ u16_l lp_clk_accuracy; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_CHANNEL_REQ message ++struct mm_set_channel_req { ++ /// Channel information ++ struct mac_chan_op chan; ++ /// Index of the RF for which the channel has to be set (0: operating (primary), 1: secondary ++ /// RF (used for additional radar detection). This parameter is reserved if no secondary RF ++ /// is available in the system ++ u8_l index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_CHANNEL_CFM message ++struct mm_set_channel_cfm { ++ /// Radio index to be used in policy table ++ u8_l radio_idx; ++ /// TX power configured (in dBm) ++ s8_l power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_DTIM_REQ message ++struct mm_set_dtim_req { ++ /// DTIM period ++ u8_l dtim_period; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_POWER_REQ message ++struct mm_set_power_req { ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++ /// TX power (in dBm) ++ s8_l power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_POWER_CFM message ++struct mm_set_power_cfm { ++ /// Radio index to be used in policy table ++ u8_l radio_idx; ++ /// TX power configured (in dBm) ++ s8_l power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BEACON_INT_REQ message ++struct mm_set_beacon_int_req { ++ /// Beacon interval ++ u16_l beacon_int; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BASIC_RATES_REQ message ++struct mm_set_basic_rates_req { ++ /// Basic rate set (as expected by bssBasicRateSet field of Rates MAC HW register) ++ u32_l rates; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++ /// Band on which the interface will operate ++ u8_l band; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BSSID_REQ message ++struct mm_set_bssid_req { ++ /// BSSID to be configured in HW ++ struct mac_addr bssid; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_FILTER_REQ message ++struct mm_set_filter_req { ++ /// RX filter to be put into rxCntrlReg HW register ++ u32_l filter; ++}; ++ ++/// Structure containing the parameters of the @ref MM_ADD_IF_REQ message. ++struct mm_add_if_req { ++ /// Type of the interface (AP, STA, ADHOC, ...) ++ u8_l type; ++ /// MAC ADDR of the interface to start ++ struct mac_addr addr; ++ /// P2P Interface ++ bool_l p2p; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_EDCA_REQ message ++struct mm_set_edca_req { ++ /// EDCA parameters of the queue (as expected by edcaACxReg HW register) ++ u32_l ac_param; ++ /// Flag indicating if UAPSD can be used on this queue ++ bool_l uapsd; ++ /// HW queue for which the parameters are configured ++ u8_l hw_queue; ++ /// Index of the interface for which the parameters are configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_MU_EDCA_REQ message ++struct mm_set_mu_edca_req { ++ /// MU EDCA parameters of the different HE queues ++ u32_l param[AC_MAX]; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_UORA_REQ message ++struct mm_set_uora_req { ++ /// Minimum exponent of OFDMA Contention Window. ++ u8_l eocw_min; ++ /// Maximum exponent of OFDMA Contention Window. ++ u8_l eocw_max; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_TXOP_RTS_THRES_REQ message ++struct mm_set_txop_rts_thres_req { ++ /// TXOP RTS threshold ++ u16_l txop_dur_rts_thres; ++ /// Index of the interface for which the parameter is configured ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_BSS_COLOR_REQ message ++struct mm_set_bss_color_req { ++ /// HE BSS color, formatted as per BSS_COLOR MAC HW register ++ u32_l bss_color; ++}; ++ ++struct mm_set_idle_req { ++ u8_l hw_idle; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_SLOTTIME_REQ message ++struct mm_set_slottime_req { ++ /// Slot time expressed in us ++ u8_l slottime; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_MODE_REQ message ++struct mm_set_mode_req { ++ /// abgnMode field of macCntrl1Reg register ++ u8_l abgnmode; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_VIF_STATE_REQ message ++struct mm_set_vif_state_req { ++ /// Association Id received from the AP (valid only if the VIF is of STA type) ++ u16_l aid; ++ /// Flag indicating if the VIF is active or not ++ bool_l active; ++ /// Interface index ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_ADD_IF_CFM message. ++struct mm_add_if_cfm { ++ /// Status of operation (different from 0 if unsuccessful) ++ u8_l status; ++ /// Interface index assigned by the LMAC ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMOVE_IF_REQ message. ++struct mm_remove_if_req { ++ /// Interface index assigned by the LMAC ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_VERSION_CFM message. ++struct mm_version_cfm { ++ /// Version of the LMAC FW ++ u32_l version_lmac; ++ /// Version1 of the MAC HW (as encoded in version1Reg MAC HW register) ++ u32_l version_machw_1; ++ /// Version2 of the MAC HW (as encoded in version2Reg MAC HW register) ++ u32_l version_machw_2; ++ /// Version1 of the PHY (depends on actual PHY) ++ u32_l version_phy_1; ++ /// Version2 of the PHY (depends on actual PHY) ++ u32_l version_phy_2; ++ /// Supported Features ++ u32_l features; ++ /// Maximum number of supported stations ++ u16_l max_sta_nb; ++ /// Maximum number of supported virtual interfaces ++ u8_l max_vif_nb; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_ADD_REQ message. ++struct mm_sta_add_req { ++ /// Bitfield showing some capabilities of the STA (@ref enum mac_sta_flags) ++ u32_l capa_flags; ++ /// Maximum A-MPDU size, in bytes, for HE frames ++ u32_l ampdu_size_max_he; ++ /// Maximum A-MPDU size, in bytes, for VHT frames ++ u32_l ampdu_size_max_vht; ++ /// PAID/GID ++ u32_l paid_gid; ++ /// Maximum A-MPDU size, in bytes, for HT frames ++ u16_l ampdu_size_max_ht; ++ /// MAC address of the station to be added ++ struct mac_addr mac_addr; ++ /// A-MPDU spacing, in us ++ u8_l ampdu_spacing_min; ++ /// Interface index ++ u8_l inst_nbr; ++ /// TDLS station ++ bool_l tdls_sta; ++ /// Indicate if the station is TDLS link initiator station ++ bool_l tdls_sta_initiator; ++ /// Indicate if the TDLS Channel Switch is allowed ++ bool_l tdls_chsw_allowed; ++ /// nonTransmitted BSSID index, set to the BSSID index in case the STA added is an AP ++ /// that is a nonTransmitted BSSID. Should be set to 0 otherwise ++ u8_l bssid_index; ++ /// Maximum BSSID indicator, valid if the STA added is an AP that is a nonTransmitted ++ /// BSSID ++ u8_l max_bssid_ind; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_ADD_CFM message. ++struct mm_sta_add_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++ /// Index assigned by the LMAC to the newly added station ++ u8_l sta_idx; ++ /// MAC HW index of the newly added station ++ u8_l hw_sta_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_DEL_REQ message. ++struct mm_sta_del_req { ++ /// Index of the station to be deleted ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_STA_DEL_CFM message. ++struct mm_sta_del_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the SET_POWER_MODE REQ message. ++struct mm_setpowermode_req { ++ u8_l mode; ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the parameters of the SET_POWER_MODE CFM message. ++struct mm_setpowermode_cfm { ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_KEY_ADD REQ message. ++struct mm_key_add_req { ++ /// Key index (valid only for default keys) ++ u8_l key_idx; ++ /// STA index (valid only for pairwise or mesh group keys) ++ u8_l sta_idx; ++ /// Key material ++ struct mac_sec_key key; ++ /// Cipher suite (WEP64, WEP128, TKIP, CCMP) ++ u8_l cipher_suite; ++ /// Index of the interface for which the key is set (valid only for default keys or mesh group keys) ++ u8_l inst_nbr; ++ /// A-MSDU SPP parameter ++ u8_l spp; ++ /// Indicate if provided key is a pairwise key or not ++ bool_l pairwise; ++}; ++ ++/// Structure containing the parameters of the @ref MM_KEY_ADD_CFM message. ++struct mm_key_add_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++ /// HW index of the key just added ++ u8_l hw_key_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_KEY_DEL_REQ message. ++struct mm_key_del_req { ++ /// HW index of the key to be deleted ++ u8_l hw_key_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_ADD_REQ message. ++struct mm_ba_add_req { ++ ///Type of agreement (0: TX, 1: RX) ++ u8_l type; ++ ///Index of peer station with which the agreement is made ++ u8_l sta_idx; ++ ///TID for which the agreement is made with peer station ++ u8_l tid; ++ ///Buffer size - number of MPDUs that can be held in its buffer per TID ++ u8_l bufsz; ++ /// Start sequence number negotiated during BA setup - the one in first aggregated MPDU counts more ++ u16_l ssn; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_ADD_CFM message. ++struct mm_ba_add_cfm { ++ ///Index of peer station for which the agreement is being confirmed ++ u8_l sta_idx; ++ ///TID for which the agreement is being confirmed ++ u8_l tid; ++ /// Status of ba establishment ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_DEL_REQ message. ++struct mm_ba_del_req { ++ ///Type of agreement (0: TX, 1: RX) ++ u8_l type; ++ ///Index of peer station for which the agreement is being deleted ++ u8_l sta_idx; ++ ///TID for which the agreement is being deleted ++ u8_l tid; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BA_DEL_CFM message. ++struct mm_ba_del_cfm { ++ ///Index of peer station for which the agreement deletion is being confirmed ++ u8_l sta_idx; ++ ///TID for which the agreement deletion is being confirmed ++ u8_l tid; ++ /// Status of ba deletion ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_ADD_REQ message ++struct mm_chan_ctxt_add_req { ++ /// Operating channel ++ struct mac_chan_op chan; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_ADD_REQ message ++struct mm_chan_ctxt_add_cfm { ++ /// Status of the addition ++ u8_l status; ++ /// Index of the new channel context ++ u8_l index; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_DEL_REQ message ++struct mm_chan_ctxt_del_req { ++ /// Index of the new channel context to be deleted ++ u8_l index; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_LINK_REQ message ++struct mm_chan_ctxt_link_req { ++ /// VIF index ++ u8_l vif_index; ++ /// Channel context index ++ u8_l chan_index; ++ /// Indicate if this is a channel switch (unlink current ctx first if true) ++ u8_l chan_switch; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_UNLINK_REQ message ++struct mm_chan_ctxt_unlink_req { ++ /// VIF index ++ u8_l vif_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_UPDATE_REQ message ++struct mm_chan_ctxt_update_req { ++ /// Channel context index ++ u8_l chan_index; ++ /// New channel information ++ struct mac_chan_op chan; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHAN_CTXT_SCHED_REQ message ++struct mm_chan_ctxt_sched_req { ++ /// VIF index ++ u8_l vif_index; ++ /// Channel context index ++ u8_l chan_index; ++ /// Type of the scheduling request (0: normal scheduling, 1: derogatory ++ /// scheduling) ++ u8_l type; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHANNEL_SWITCH_IND message ++struct mm_channel_switch_ind { ++ /// Index of the channel context we will switch to ++ u8_l chan_index; ++ /// Indicate if the switch has been triggered by a Remain on channel request ++ bool_l roc; ++ /// VIF on which remain on channel operation has been started (if roc == 1) ++ u8_l vif_index; ++ /// Indicate if the switch has been triggered by a TDLS Remain on channel request ++ bool_l roc_tdls; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHANNEL_PRE_SWITCH_IND message ++struct mm_channel_pre_switch_ind { ++ /// Index of the channel context we will switch to ++ u8_l chan_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CONNECTION_LOSS_IND message. ++struct mm_connection_loss_ind { ++ /// VIF instance number ++ u8_l inst_nbr; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_DBG_TRIGGER_REQ message. ++struct mm_dbg_trigger_req { ++ /// Error trace to be reported by the LMAC ++ char error[64]; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_PS_MODE_REQ message. ++struct mm_set_ps_mode_req { ++ /// Power Save is activated or deactivated ++ u8_l new_state; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BCN_CHANGE_REQ message. ++#define BCN_MAX_CSA_CPT 2 ++struct mm_bcn_change_req { ++ /// Pointer, in host memory, to the new beacon template ++ u32_l bcn_ptr; ++ /// Length of the beacon template ++ u16_l bcn_len; ++ /// Offset of the TIM IE in the beacon ++ u16_l tim_oft; ++ /// Length of the TIM IE ++ u8_l tim_len; ++ /// Index of the VIF for which the beacon is updated ++ u8_l inst_nbr; ++ /// Offset of CSA (channel switch announcement) counters (0 means no counter) ++ u8_l csa_oft[BCN_MAX_CSA_CPT]; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_TIM_UPDATE_REQ message. ++struct mm_tim_update_req { ++ /// Association ID of the STA the bit of which has to be updated (0 for BC/MC traffic) ++ u16_l aid; ++ /// Flag indicating the availability of data packets for the given STA ++ u8_l tx_avail; ++ /// Index of the VIF for which the TIM is updated ++ u8_l inst_nbr; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMAIN_ON_CHANNEL_REQ message. ++struct mm_remain_on_channel_req { ++ /// Operation Code ++ u8_l op_code; ++ /// VIF Index ++ u8_l vif_index; ++ /// Band (2.4GHz or 5GHz) ++ u8_l band; ++ /// Channel type: 20,40,80,160 or 80+80 MHz ++ u8_l type; ++ /// Frequency for Primary 20MHz channel (in MHz) ++ u16_l prim20_freq; ++ /// Frequency for Center of the contiguous channel or center of Primary 80+80 ++ u16_l center1_freq; ++ /// Frequency for Center of the non-contiguous secondary 80+80 ++ u16_l center2_freq; ++ /// Duration (in ms) ++ u32_l duration_ms; ++ /// TX power (in dBm) ++ s8_l tx_power; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMAIN_ON_CHANNEL_CFM message ++struct mm_remain_on_channel_cfm { ++ /// Operation Code ++ u8_l op_code; ++ /// Status of the operation ++ u8_l status; ++ /// Channel Context index ++ u8_l chan_ctxt_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_REMAIN_ON_CHANNEL_EXP_IND message ++struct mm_remain_on_channel_exp_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// Channel Context index ++ u8_l chan_ctxt_index; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_UAPSD_TMR_REQ message. ++struct mm_set_uapsd_tmr_req { ++ /// action: Start or Stop the timer ++ u8_l action; ++ /// timeout value, in milliseconds ++ u32_l timeout; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_UAPSD_TMR_CFM message. ++struct mm_set_uapsd_tmr_cfm { ++ /// Status of the operation (different from 0 if unsuccessful) ++ u8_l status; ++}; ++ ++ ++/// Structure containing the parameters of the @ref MM_PS_CHANGE_IND message ++struct mm_ps_change_ind { ++ /// Index of the peer device that is switching its PS state ++ u8_l sta_idx; ++ /// New PS state of the peer device (0: active, 1: sleeping) ++ u8_l ps_state; ++}; ++ ++/// Structure containing the parameters of the @ref MM_P2P_VIF_PS_CHANGE_IND message ++struct mm_p2p_vif_ps_change_ind { ++ /// Index of the P2P VIF that is switching its PS state ++ u8_l vif_index; ++ /// New PS state of the P2P VIF interface (0: active, 1: sleeping) ++ u8_l ps_state; ++}; ++ ++/// Structure containing the parameters of the @ref MM_TRAFFIC_REQ_IND message ++struct mm_traffic_req_ind { ++ /// Index of the peer device that needs traffic ++ u8_l sta_idx; ++ /// Number of packets that need to be sent (if 0, all buffered traffic shall be sent and ++ /// if set to @ref PS_SP_INTERRUPTED, it means that current service period has been interrupted) ++ u8_l pkt_cnt; ++ /// Flag indicating if the traffic request concerns U-APSD queues or not ++ bool_l uapsd; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_PS_OPTIONS_REQ message. ++struct mm_set_ps_options_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// Listen interval (0 if wake up shall be based on DTIM period) ++ u16_l listen_interval; ++ /// Flag indicating if we shall listen the BC/MC traffic or not ++ bool_l dont_listen_bc_mc; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CSA_COUNTER_IND message ++struct mm_csa_counter_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Updated CSA counter value ++ u8_l csa_count; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CHANNEL_SURVEY_IND message ++struct mm_channel_survey_ind { ++ /// Frequency of the channel ++ u16_l freq; ++ /// Noise in dbm ++ s8_l noise_dbm; ++ /// Amount of time spent of the channel (in ms) ++ u32_l chan_time_ms; ++ /// Amount of time the primary channel was sensed busy ++ u32_l chan_time_busy_ms; ++}; ++ ++/// Structure containing the parameters of the @ref MM_BFMER_ENABLE_REQ message. ++struct mm_bfmer_enable_req { ++ /** ++ * Address of the beamforming report space allocated in host memory ++ * (Valid only if vht_su_bfmee is true) ++ */ ++ u32_l host_bfr_addr; ++ /** ++ * Size of the beamforming report space allocated in host memory. This space should ++ * be twice the maximum size of the expected beamforming reports as the FW will ++ * divide it in two in order to be able to upload a new report while another one is ++ * used in transmission ++ */ ++ u16_l host_bfr_size; ++ /// AID ++ u16_l aid; ++ /// Station Index ++ u8_l sta_idx; ++ /// Maximum number of spatial streams the station can receive ++ u8_l rx_nss; ++ /** ++ * Indicate if peer STA is MU Beamformee (VHT) capable ++ * (Valid only if vht_su_bfmee is true) ++ */ ++ bool_l vht_mu_bfmee; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_NOA_REQ message. ++struct mm_set_p2p_noa_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// Allocated NOA Instance Number - Valid only if count = 0 ++ u8_l noa_inst_nb; ++ /// Count ++ u8_l count; ++ /// Indicate if NoA can be paused for traffic reason ++ bool_l dyn_noa; ++ /// Duration (in us) ++ u32_l duration_us; ++ /// Interval (in us) ++ u32_l interval_us; ++ /// Start Time offset from next TBTT (in us) ++ u32_l start_offset; ++}; ++ ++#ifdef AICWF_ARP_OFFLOAD ++struct mm_set_arpoffload_en_req { ++ u32_l ipaddr; ++ u8_l enable; ++ u8_l vif_idx; ++}; ++ ++struct mm_set_arpoffload_en_cfm { ++ u8_l status; ++}; ++#endif ++ ++struct mm_set_agg_disable_req { ++ u8_l disable; ++ u8_l staidx; ++ u8_l disable_rx; ++}; ++ ++struct mm_set_coex_req { ++ u8_l bt_on; ++ u8_l disable_coexnull; ++ u8_l enable_nullcts; ++ u8_l enable_periodic_timer; ++ u8_l coex_timeslot_set; ++ u32_l coex_timeslot[2]; ++}; ++#if 0 ++struct mm_set_rf_config_req { ++ u8_l def_band; ++ u8_l config_type; ++ u16_l offset; ++ u16_l len; ++ u16_l set; ++ u32_l rx_gain_24g[48][4]; ++ u32_l rx_gain_5g[32][4]; ++ u32_l tx_gain[32]; ++}; ++#endif ++struct mm_set_rf_config_req ++{ ++ u8_l table_sel; ++ u8_l table_ofst; ++ u8_l table_num; ++ u8_l deft_page; ++ u32_l data[64]; ++}; ++ ++struct mm_set_rf_calib_req { ++ u32_l cal_cfg_24g; ++ u32_l cal_cfg_5g; ++ u32_l param_alpha; ++ u32_l bt_calib_en; ++ u32_l bt_calib_param; ++ u8_l xtal_cap; ++ u8_l xtal_cap_fine; ++}; ++ ++struct mm_set_rf_calib_cfm { ++ u32_l rxgain_24g_addr; ++ u32_l rxgain_5g_addr; ++ u32_l txgain_24g_addr; ++ u32_l txgain_5g_addr; ++}; ++ ++struct mm_get_mac_addr_req { ++ u32_l get; ++}; ++ ++struct mm_get_mac_addr_cfm { ++ u8_l mac_addr[6]; ++}; ++ ++struct mm_get_sta_info_req { ++ u8_l sta_idx; ++}; ++ ++struct mm_get_sta_info_cfm { ++ u32_l rate_info; ++ u32_l txfailed; ++ u8 rssi; ++ u8 reserved[3]; ++ u32_l chan_busy_time; ++ u32_l ack_fail_stat; ++ u32_l ack_succ_stat; ++ u32_l chan_tx_busy_time; ++}; ++ ++typedef struct ++{ ++ u8_l enable; ++ u8_l dsss; ++ u8_l ofdmlowrate_2g4; ++ u8_l ofdm64qam_2g4; ++ u8_l ofdm256qam_2g4; ++ u8_l ofdm1024qam_2g4; ++ u8_l ofdmlowrate_5g; ++ u8_l ofdm64qam_5g; ++ u8_l ofdm256qam_5g; ++ u8_l ofdm1024qam_5g; ++} txpwr_lvl_conf_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_11b_11ag_2g4[12]; ++ s8_l pwrlvl_11n_11ac_2g4[10]; ++ s8_l pwrlvl_11ax_2g4[12]; ++} txpwr_lvl_conf_v2_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_11b_11ag_2g4[12]; ++ s8_l pwrlvl_11n_11ac_2g4[10]; ++ s8_l pwrlvl_11ax_2g4[12]; ++ s8_l pwrlvl_11a_5g[12]; ++ s8_l pwrlvl_11n_11ac_5g[10]; ++ s8_l pwrlvl_11ax_5g[12]; ++} txpwr_lvl_conf_v3_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_11b_11ag_2g4[12]; ++ s8_l pwrlvl_11n_11ac_2g4[10]; ++ s8_l pwrlvl_11ax_2g4[12]; ++ s8_l pwrlvl_11a_5g[8]; ++ s8_l pwrlvl_11n_11ac_5g[10]; ++ s8_l pwrlvl_11ax_5g[12]; ++ s8_l pwrlvl_11a_6g[8]; ++ s8_l pwrlvl_11n_11ac_6g[10]; ++ s8_l pwrlvl_11ax_6g[12]; ++} txpwr_lvl_conf_v4_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ s8_l pwrlvl_adj_tbl_2g4[3]; ++ s8_l pwrlvl_adj_tbl_5g[6]; ++} txpwr_lvl_adj_conf_t; ++ ++typedef struct ++{ ++ u8_l loss_enable_2g4; ++ s8_l loss_value_2g4; ++ u8_l loss_enable_5g; ++ s8_l loss_value_5g; ++} txpwr_loss_conf_t; ++ ++struct mm_set_txpwr_lvl_req ++{ ++ union { ++ txpwr_lvl_conf_t txpwr_lvl; ++ txpwr_lvl_conf_v2_t txpwr_lvl_v2; ++ txpwr_lvl_conf_v3_t txpwr_lvl_v3; ++ txpwr_lvl_conf_v4_t txpwr_lvl_v4; ++ }; ++}; ++ ++struct mm_set_txpwr_lvl_adj_req ++{ ++ txpwr_lvl_adj_conf_t txpwr_lvl_adj; ++}; ++ ++typedef struct { ++ u8_l enable; ++ u8_l dsss; ++ u8_l ofdmlowrate_2g4; ++ u8_l ofdm64qam_2g4; ++ u8_l ofdm256qam_2g4; ++ u8_l ofdm1024qam_2g4; ++ u8_l ofdmlowrate_5g; ++ u8_l ofdm64qam_5g; ++ u8_l ofdm256qam_5g; ++ u8_l ofdm1024qam_5g; ++} txpwr_idx_conf_t; ++ ++struct mm_set_txpwr_idx_req { ++ txpwr_idx_conf_t txpwr_idx; ++}; ++ ++typedef struct { ++ u8_l enable; ++ s8_l chan_1_4; ++ s8_l chan_5_9; ++ s8_l chan_10_13; ++ s8_l chan_36_64; ++ s8_l chan_100_120; ++ s8_l chan_122_140; ++ s8_l chan_142_165; ++} txpwr_ofst_conf_t; ++ ++/* ++ * pwrofst2x_tbl_2g4[3][3]: ++ * +---------------+----------+----------+----------+ ++ * | RateTyp\ChGrp | CH_1_4 | CH_5_9 | CH_10_13 | ++ * +---------------+----------+----------+----------+ ++ * | DSSS | [0][0] | [0][1] | [0][2] | ++ * +---------------+----------+----------+----------+ ++ * | OFDM_HIGHRATE | [1][0] | [1][1] | [1][2] | ++ * +---------------+----------+----------+----------+ ++ * | OFDM_LOWRATE | [2][0] | [2][1] | [2][2] | ++ * +---------------+----------+----------+----------+ ++ * pwrofst2x_tbl_5g[3][6]: ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | RateTyp\ChGrp | CH_42(36~50) | CH_58(51~64) | CH_106(98~114) | CH_122(115~130)| CH_138(131~146)| CH_155(147~166)| ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | OFDM_LOWRATE | [0][0] | [0][1] | [0][2] | [0][3] | [0][4] | [0][5] | ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | OFDM_HIGHRATE | [1][0] | [1][1] | [1][2] | [1][3] | [1][4] | [1][5] | ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ * | OFDM_MIDRATE | [2][0] | [2][1] | [2][2] | [2][3] | [2][4] | [2][5] | ++ * +---------------+--------------+--------------+----------------+----------------+----------------+----------------+ ++ */ ++ ++typedef struct ++{ ++ int8_t enable; ++ int8_t pwrofst2x_tbl_2g4[3][3]; ++ int8_t pwrofst2x_tbl_5g[3][6]; ++} txpwr_ofst2x_conf_t; ++ ++/* ++ * pwrofst2x_v2_tbl_2g4_ant0/1[3][3]: ++ * +---------------+----------+---------------+--------------+ ++ * | ChGrp\RateTyp | DSSS | OFDM_HIGHRATE | OFDM_LOWRATE | ++ * +---------------+----------+---------------+--------------+ ++ * | CH_1_4 | [0][0] | [0][1] | Reserved | ++ * +---------------+----------+---------------+--------------+ ++ * | CH_5_9 | [1][0] | [1][1] | Reserved | ++ * +---------------+----------+---------------+--------------+ ++ * | CH_10_13 | [2][0] | [2][1] | Reserved | ++ * +---------------+----------+---------------+--------------+ ++ * pwrofst2x_v2_tbl_5g_ant0/1[6][3]: ++ * +-----------------+---------------+--------------+--------------+ ++ * | ChGrp\RateTyp | OFDM_HIGHRATE | OFDM_LOWRATE | OFDM_MIDRATE | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_42(36~50) | [0][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_58(51~64) | [1][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_106(98~114) | [2][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_122(115~130) | [3][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_138(131~146) | [4][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ * | CH_155(147~166) | [5][0] | Reserved | Reserved | ++ * +-----------------+---------------+--------------+--------------+ ++ */ ++ ++typedef struct ++{ ++ u8_l enable; ++ u8_l pwrofst_flags; ++ s8_l pwrofst2x_tbl_2g4_ant0[3][3]; ++ s8_l pwrofst2x_tbl_2g4_ant1[3][3]; ++ s8_l pwrofst2x_tbl_5g_ant0[6][3]; ++ s8_l pwrofst2x_tbl_5g_ant1[6][3]; ++ s8_l pwrofst2x_tbl_6g_ant0[15]; ++ s8_l pwrofst2x_tbl_6g_ant1[15]; ++} txpwr_ofst2x_conf_v2_t; ++ ++typedef struct ++{ ++ u8_l enable; ++ u8_l xtal_cap; ++ u8_l xtal_cap_fine; ++} xtal_cap_conf_t; ++ ++ ++struct mm_set_txpwr_ofst_req { ++ union { ++ txpwr_ofst_conf_t txpwr_ofst; ++ txpwr_ofst2x_conf_t txpwr_ofst2x; ++ txpwr_ofst2x_conf_v2_t txpwr_ofst2x_v2; ++ }; ++}; ++ ++struct mm_set_stack_start_req { ++ u8_l is_stack_start; ++ u8_l efuse_valid; ++ u8_l set_vendor_info; ++ u8_l fwtrace_redir; ++}; ++ ++struct mm_set_stack_start_cfm { ++ u8_l is_5g_support; ++ u8_l vendor_info; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_OPPPS_REQ message. ++struct mm_set_p2p_oppps_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// CTWindow ++ u8_l ctwindow; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_NOA_CFM message. ++struct mm_set_p2p_noa_cfm { ++ /// Request status ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_SET_P2P_OPPPS_CFM message. ++struct mm_set_p2p_oppps_cfm { ++ /// Request status ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MM_P2P_NOA_UPD_IND message. ++struct mm_p2p_noa_upd_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// NOA Instance Number ++ u8_l noa_inst_nb; ++ /// NoA Type ++ u8_l noa_type; ++ /// Count ++ u8_l count; ++ /// Duration (in us) ++ u32_l duration_us; ++ /// Interval (in us) ++ u32_l interval_us; ++ /// Start Time ++ u32_l start_time; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CFG_RSSI_REQ message ++struct mm_cfg_rssi_req { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// RSSI threshold ++ s8_l rssi_thold; ++ /// RSSI hysteresis ++ u8_l rssi_hyst; ++}; ++ ++/// Structure containing the parameters of the @ref MM_RSSI_STATUS_IND message ++struct mm_rssi_status_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Status of the RSSI ++ bool_l rssi_status; ++ /// Current RSSI ++ s8_l rssi; ++}; ++ ++/// Structure containing the parameters of the @ref MM_PKTLOSS_IND message ++struct mm_pktloss_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Address of the STA for which there is a packet loss ++ struct mac_addr mac_addr; ++ /// Number of packets lost ++ u32 num_packets; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CSA_FINISH_IND message ++struct mm_csa_finish_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Status of the operation ++ u8_l status; ++ /// New channel ctx index ++ u8_l chan_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MM_CSA_TRAFFIC_IND message ++struct mm_csa_traffic_ind { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// Is tx traffic enable or disable ++ bool_l enable; ++}; ++ ++/// Structure containing the parameters of the @ref MM_MU_GROUP_UPDATE_REQ message. ++/// Size allocated for the structure depends of the number of group ++struct mm_mu_group_update_req { ++ /// Station index ++ u8_l sta_idx; ++ /// Number of groups the STA belongs to ++ u8_l group_cnt; ++ /// Group information ++ struct { ++ /// Group Id ++ u8_l group_id; ++ /// User position ++ u8_l user_pos; ++ } groups[0]; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For Scan messages ++/////////////////////////////////////////////////////////////////////////////// ++enum scan_msg_tag { ++ /// Scanning start Request. ++ SCAN_START_REQ = LMAC_FIRST_MSG(TASK_SCAN), ++ /// Scanning start Confirmation. ++ SCAN_START_CFM, ++ /// End of scanning indication. ++ SCAN_DONE_IND, ++ /// Cancel scan request ++ SCAN_CANCEL_REQ, ++ /// Cancel scan confirmation ++ SCAN_CANCEL_CFM, ++ ++ /// MAX number of messages ++ SCAN_MAX, ++}; ++ ++/// Maximum number of SSIDs in a scan request ++#define SCAN_SSID_MAX 3 ++ ++/// Maximum number of channels in a scan request ++#define SCAN_CHANNEL_MAX (MAC_DOMAINCHANNEL_24G_MAX + MAC_DOMAINCHANNEL_5G_MAX) ++ ++/// Maximum length of the ProbeReq IEs (SoftMAC mode) ++#define SCAN_MAX_IE_LEN 300 ++ ++/// Maximum number of PHY bands supported ++#define SCAN_BAND_MAX 2 ++ ++/// Structure containing the parameters of the @ref SCAN_START_REQ message ++struct scan_start_req { ++ /// List of channel to be scanned ++ struct mac_chan_def chan[SCAN_CHANNEL_MAX]; ++ /// List of SSIDs to be scanned ++ struct mac_ssid ssid[SCAN_SSID_MAX]; ++ /// BSSID to be scanned ++ struct mac_addr bssid; ++ /// Pointer (in host memory) to the additional IEs that need to be added to the ProbeReq ++ /// (following the SSID element) ++ u32_l add_ies; ++ /// Length of the additional IEs ++ u16_l add_ie_len; ++ /// Index of the VIF that is scanning ++ u8_l vif_idx; ++ /// Number of channels to scan ++ u8_l chan_cnt; ++ /// Number of SSIDs to scan for ++ u8_l ssid_cnt; ++ /// no CCK - For P2P frames not being sent at CCK rate in 2GHz band. ++ bool no_cck; ++ /// Scan duration, in us ++ u32_l duration; ++}; ++ ++/// Structure containing the parameters of the @ref SCAN_START_CFM message ++struct scan_start_cfm { ++ /// Status of the request ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref SCAN_CANCEL_REQ message ++struct scan_cancel_req { ++}; ++ ++/// Structure containing the parameters of the @ref SCAN_START_CFM message ++struct scan_cancel_cfm { ++ /// Status of the request ++ u8_l status; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For Scanu messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Messages that are logically related to the task. ++enum { ++ /// Scan request from host. ++ SCANU_START_REQ = LMAC_FIRST_MSG(TASK_SCANU), ++ /// Scanning start Confirmation. ++ SCANU_START_CFM, ++ /// Join request ++ SCANU_JOIN_REQ, ++ /// Join confirmation. ++ SCANU_JOIN_CFM, ++ /// Scan result indication. ++ SCANU_RESULT_IND, ++ /// Fast scan request from any other module. ++ SCANU_FAST_REQ, ++ /// Confirmation of fast scan request. ++ SCANU_FAST_CFM, ++ ++ SCANU_VENDOR_IE_REQ, ++ SCANU_VENDOR_IE_CFM, ++ SCANU_START_CFM_ADDTIONAL, ++ SCANU_CANCEL_REQ, ++ SCANU_CANCEL_CFM, ++ ++ /// MAX number of messages ++ SCANU_MAX, ++}; ++ ++/// Maximum length of the additional ProbeReq IEs (FullMAC mode) ++#define SCANU_MAX_IE_LEN 200 ++ ++/// Structure containing the parameters of the @ref SCANU_START_REQ message ++struct scanu_start_req { ++ /// List of channel to be scanned ++ struct mac_chan_def chan[SCAN_CHANNEL_MAX]; ++ /// List of SSIDs to be scanned ++ struct mac_ssid ssid[SCAN_SSID_MAX]; ++ /// BSSID to be scanned (or WILDCARD BSSID if no BSSID is searched in particular) ++ struct mac_addr bssid; ++ /// Address (in host memory) of the additional IEs that need to be added to the ProbeReq ++ /// (following the SSID element) ++ u32_l add_ies; ++ /// Length of the additional IEs ++ u16_l add_ie_len; ++ /// Index of the VIF that is scanning ++ u8_l vif_idx; ++ /// Number of channels to scan ++ u8_l chan_cnt; ++ /// Number of SSIDs to scan for ++ u8_l ssid_cnt; ++ /// no CCK - For P2P frames not being sent at CCK rate in 2GHz band. ++ bool no_cck; ++ /// Scan duration, in us ++ u32_l duration; ++}; ++ ++struct scanu_vendor_ie_req { ++ u16_l add_ie_len; ++ u8_l vif_idx; ++ u8_l ie[256]; ++}; ++ ++/// Structure containing the parameters of the @ref SCANU_START_CFM message ++struct scanu_start_cfm { ++ /// Index of the VIF that was scanning ++ u8_l vif_idx; ++ /// Status of the request ++ u8_l status; ++ /// Number of scan results available ++ u8_l result_cnt; ++}; ++ ++/// Parameters of the @SCANU_RESULT_IND message ++struct scanu_result_ind { ++ /// Length of the frame ++ u16_l length; ++ /// Frame control field of the frame. ++ u16_l framectrl; ++ /// Center frequency on which we received the packet ++ u16_l center_freq; ++ /// PHY band ++ u8_l band; ++ /// Index of the station that sent the frame. 0xFF if unknown. ++ u8_l sta_idx; ++ /// Index of the VIF that received the frame. 0xFF if unknown. ++ u8_l inst_nbr; ++ /// RSSI of the received frame. ++ s8_l rssi; ++ /// Frame payload. ++ u32_l payload[]; ++}; ++ ++/// Structure containing the parameters of the message. ++struct scanu_fast_req { ++ /// The SSID to scan in the channel. ++ struct mac_ssid ssid; ++ /// BSSID. ++ struct mac_addr bssid; ++ /// Probe delay. ++ u16_l probe_delay; ++ /// Minimum channel time. ++ u16_l minch_time; ++ /// Maximum channel time. ++ u16_l maxch_time; ++ /// The channel number to scan. ++ u16_l ch_nbr; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For ME messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Messages that are logically related to the task. ++enum { ++ /// Configuration request from host. ++ ME_CONFIG_REQ = LMAC_FIRST_MSG(TASK_ME), ++ /// Configuration confirmation. ++ ME_CONFIG_CFM, ++ /// Configuration request from host. ++ ME_CHAN_CONFIG_REQ, ++ /// Configuration confirmation. ++ ME_CHAN_CONFIG_CFM, ++ /// Set control port state for a station. ++ ME_SET_CONTROL_PORT_REQ, ++ /// Control port setting confirmation. ++ ME_SET_CONTROL_PORT_CFM, ++ /// TKIP MIC failure indication. ++ ME_TKIP_MIC_FAILURE_IND, ++ /// Add a station to the FW (AP mode) ++ ME_STA_ADD_REQ, ++ /// Confirmation of the STA addition ++ ME_STA_ADD_CFM, ++ /// Delete a station from the FW (AP mode) ++ ME_STA_DEL_REQ, ++ /// Confirmation of the STA deletion ++ ME_STA_DEL_CFM, ++ /// Indication of a TX RA/TID queue credit update ++ ME_TX_CREDITS_UPDATE_IND, ++ /// Request indicating to the FW that there is traffic buffered on host ++ ME_TRAFFIC_IND_REQ, ++ /// Confirmation that the @ref ME_TRAFFIC_IND_REQ has been executed ++ ME_TRAFFIC_IND_CFM, ++ /// Request of RC statistics to a station ++ ME_RC_STATS_REQ, ++ /// RC statistics confirmation ++ ME_RC_STATS_CFM, ++ /// RC fixed rate request ++ ME_RC_SET_RATE_REQ, ++ /// Configure monitor interface ++ ME_CONFIG_MONITOR_REQ, ++ /// Configure monitor interface response ++ ME_CONFIG_MONITOR_CFM, ++ /// Setting power Save mode request from host ++ ME_SET_PS_MODE_REQ, ++ /// Set power Save mode confirmation ++ ME_SET_PS_MODE_CFM, ++ /// Setting Low Power level request from host ++ ME_SET_LP_LEVEL_REQ, ++ /// Set Low Power level confirmation ++ ME_SET_LP_LEVEL_CFM, ++ /// MAX number of messages ++ ME_MAX, ++}; ++ ++/// Structure containing the parameters of the @ref ME_START_REQ message ++struct me_config_req { ++ /// HT Capabilities ++ struct mac_htcapability ht_cap; ++ /// VHT Capabilities ++ struct mac_vhtcapability vht_cap; ++ /// HE capabilities ++ struct mac_hecapability he_cap; ++ /// Lifetime of packets sent under a BlockAck agreement (expressed in TUs) ++ u16_l tx_lft; ++ /// Maximum supported BW ++ u8_l phy_bw_max; ++ /// Boolean indicating if HT is supported or not ++ bool_l ht_supp; ++ /// Boolean indicating if VHT is supported or not ++ bool_l vht_supp; ++ /// Boolean indicating if HE is supported or not ++ bool_l he_supp; ++ /// Boolean indicating if HE OFDMA UL is enabled or not ++ bool_l he_ul_on; ++ /// Boolean indicating if PS mode shall be enabled or not ++ bool_l ps_on; ++ /// Boolean indicating if Antenna Diversity shall be enabled or not ++ bool_l ant_div_on; ++ /// Boolean indicating if Dynamic PS mode shall be used or not ++ bool_l dpsm; ++}; ++ ++/// Structure containing the parameters of the @ref ME_CHAN_CONFIG_REQ message ++struct me_chan_config_req { ++ /// List of 2.4GHz supported channels ++ struct mac_chan_def chan2G4[MAC_DOMAINCHANNEL_24G_MAX]; ++ /// List of 5GHz supported channels ++ struct mac_chan_def chan5G[MAC_DOMAINCHANNEL_5G_MAX]; ++ /// Number of 2.4GHz channels in the list ++ u8_l chan2G4_cnt; ++ /// Number of 5GHz channels in the list ++ u8_l chan5G_cnt; ++}; ++ ++/// Structure containing the parameters of the @ref ME_SET_CONTROL_PORT_REQ message ++struct me_set_control_port_req { ++ /// Index of the station for which the control port is opened ++ u8_l sta_idx; ++ /// Control port state ++ bool_l control_port_open; ++}; ++ ++/// Structure containing the parameters of the @ref ME_TKIP_MIC_FAILURE_IND message ++struct me_tkip_mic_failure_ind { ++ /// Address of the sending STA ++ struct mac_addr addr; ++ /// TSC value ++ u64_l tsc; ++ /// Boolean indicating if the packet was a group or unicast one (true if group) ++ bool_l ga; ++ /// Key Id ++ u8_l keyid; ++ /// VIF index ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref ME_STA_ADD_REQ message ++struct me_sta_add_req { ++ /// MAC address of the station to be added ++ struct mac_addr mac_addr; ++ /// Supported legacy rates ++ struct mac_rateset rate_set; ++ /// HT Capabilities ++ struct mac_htcapability ht_cap; ++ /// VHT Capabilities ++ struct mac_vhtcapability vht_cap; ++ /// HE capabilities ++ struct mac_hecapability he_cap; ++ /// Flags giving additional information about the station (@ref mac_sta_flags) ++ u32_l flags; ++ /// Association ID of the station ++ u16_l aid; ++ /// Bit field indicating which queues have U-APSD enabled ++ u8_l uapsd_queues; ++ /// Maximum size, in frames, of a APSD service period ++ u8_l max_sp_len; ++ /// Operation mode information (valid if bit @ref STA_OPMOD_NOTIF is ++ /// set in the flags) ++ u8_l opmode; ++ /// Index of the VIF the station is attached to ++ u8_l vif_idx; ++ /// Whether the the station is TDLS station ++ bool_l tdls_sta; ++ /// Indicate if the station is TDLS link initiator station ++ bool_l tdls_sta_initiator; ++ /// Indicate if the TDLS Channel Switch is allowed ++ bool_l tdls_chsw_allowed; ++}; ++ ++/// Structure containing the parameters of the @ref ME_STA_ADD_CFM message ++struct me_sta_add_cfm { ++ /// Station index ++ u8_l sta_idx; ++ /// Status of the station addition ++ u8_l status; ++ /// PM state of the station ++ u8_l pm_state; ++}; ++ ++/// Structure containing the parameters of the @ref ME_STA_DEL_REQ message. ++struct me_sta_del_req { ++ /// Index of the station to be deleted ++ u8_l sta_idx; ++ /// Whether the the station is TDLS station ++ bool_l tdls_sta; ++}; ++ ++/// Structure containing the parameters of the @ref ME_TX_CREDITS_UPDATE_IND message. ++struct me_tx_credits_update_ind { ++ /// Index of the station for which the credits are updated ++ u8_l sta_idx; ++ /// TID for which the credits are updated ++ u8_l tid; ++ /// Offset to be applied on the credit count ++ s8_l credits; ++}; ++ ++/// Structure containing the parameters of the @ref ME_TRAFFIC_IND_REQ message. ++struct me_traffic_ind_req { ++ /// Index of the station for which UAPSD traffic is available on host ++ u8_l sta_idx; ++ /// Flag indicating the availability of UAPSD packets for the given STA ++ u8_l tx_avail; ++ /// Indicate if traffic is on uapsd-enabled queues ++ bool_l uapsd; ++}; ++ ++struct mm_apm_staloss_ind ++{ ++ u8_l sta_idx; ++ u8_l vif_idx; ++ u8_l mac_addr[6]; ++}; ++ ++#ifdef CONFIG_SDIO_BT ++struct mm_bt_recv_ind ++{ ++ u32_l data_len; ++ u8_l bt_data[1024]; ++}; ++#endif ++ ++enum vendor_hwconfig_tag{ ++ ACS_TXOP_REQ = 0, ++ CHANNEL_ACCESS_REQ, ++ MAC_TIMESCALE_REQ, ++ CCA_THRESHOLD_REQ, ++ BWMODE_REQ, ++ CHIP_TEMP_GET_REQ, ++ AP_PS_LEVEL_SET_REQ, ++ CUSTOMIZED_FREQ_REQ, ++ WAKEUP_INFO_REQ, ++ KEEPALIVE_PKT_REQ, ++}; ++ ++enum { ++ BWMODE20M = 0, ++ BWMODE10M, ++ BWMODE5M, ++}; ++ ++struct mm_set_acs_txop_req ++{ ++ u32_l hwconfig_id; ++ u16_l txop_bk; ++ u16_l txop_be; ++ u16_l txop_vi; ++ u16_l txop_vo; ++}; ++ ++struct mm_set_channel_access_req ++{ ++ u32_l hwconfig_id; ++ u32_l edca[4]; ++ u8_l vif_idx; ++ u8_l retry_cnt; ++ u8_l rts_en; ++ u8_l long_nav_en; ++ u8_l cfe_en; ++ u8_l rc_retry_cnt[3]; ++ s8_l ccademod_th; ++ u8_l remove_1m2m; ++}; ++ ++struct mm_set_mac_timescale_req ++{ ++ u32_l hwconfig_id; ++ u8_l sifsA_time; ++ u8_l sifsB_time; ++ u8_l slot_time; ++ u8_l rx_startdelay_ofdm; ++ u8_l rx_startdelay_long; ++ u8_l rx_startdelay_short; ++}; ++ ++struct mm_set_cca_threshold_req ++{ ++ u32_l hwconfig_id; ++ u8_l auto_cca_en; ++ s8_l cca20p_rise_th; ++ s8_l cca20s_rise_th; ++ s8_l cca20p_fall_th; ++ s8_l cca20s_fall_th; ++ ++}; ++ ++struct mm_set_bwmode_req ++{ ++ u32_l hwconfig_id; ++ u8_l bwmode; ++}; ++ ++struct mm_get_chip_temp_req ++{ ++ u32_l hwconfig_id; ++}; ++ ++struct mm_get_chip_temp_cfm ++{ ++ /// Temp degree val ++ s8_l degree; ++}; ++ ++struct mm_set_ap_ps_level_req ++{ ++ u32_l hwconfig_id; ++ u8 ap_ps_level; ++}; ++ ++struct mm_set_vendor_hwconfig_cfm ++{ ++ u32_l hwconfig_id; ++ union { ++ struct mm_get_chip_temp_cfm chip_temp_cfm; ++ }; ++}; ++ ++struct mm_set_customized_freq_req ++{ ++ u32_l hwconfig_id; ++ u16_l raw_freq[4]; ++ u16_l map_freq[4]; ++}; ++ ++struct mm_set_wakeup_info_req ++{ ++ u32_l hwconfig_id; ++ u16_l offset; ++ u8_l length; ++ u8_l mask_and_patten[]; ++ ++}; ++ ++struct mm_set_keepalive_req ++{ ++ u32_l hwconfig_id; ++ u16_l code; ++ u16_l length; ++ u32_l intv; ++ u8_l payload[]; ++}; ++ ++struct mm_set_txop_req ++{ ++ u16_l txop_bk; ++ u16_l txop_be; ++ u16_l txop_vi; ++ u16_l txop_vo; ++ u8_l long_nav_en; ++ u8_l cfe_en; ++}; ++ ++#ifdef CONFIG_APF ++struct mm_set_apf_prog_req { ++ u32_l program_len; ++ u32_l offset; ++ u8_l program[LMAC_MSG_MAX_LEN]; ++}; ++ ++struct mm_get_apf_prog_req { ++ u16_l offset; ++}; ++ ++struct mm_get_apf_prog_cfm { ++ u8_l program[LMAC_MSG_MAX_LEN]; ++}; ++#endif ++ ++struct mm_get_fw_version_cfm ++{ ++ u8_l fw_version_len; ++ u8_l fw_version[63]; ++}; ++ ++struct mm_get_wifi_disable_cfm ++{ ++ u8_l wifi_disable; ++}; ++ ++enum vendor_swconfig_tag ++{ ++ BCN_CFG_REQ = 0, ++ TEMP_COMP_SET_REQ, ++ TEMP_COMP_GET_REQ, ++ EXT_FLAGS_SET_REQ, ++ EXT_FLAGS_GET_REQ, ++ EXT_FLAGS_MASK_SET_REQ, ++}; ++ ++struct mm_set_bcn_cfg_req ++{ ++ /// Ignore or not bcn tim bcmc bit ++ bool_l tim_bcmc_ignored_enable; ++}; ++ ++struct mm_set_bcn_cfg_cfm ++{ ++ /// Request status ++ bool_l tim_bcmc_ignored_status; ++}; ++ ++struct mm_set_temp_comp_req ++{ ++ /// Enable or not temp comp ++ u8_l enable; ++ u8_l reserved[3]; ++ u32_l tmr_period_ms; ++}; ++ ++struct mm_set_temp_comp_cfm ++{ ++ /// Request status ++ u8_l status; ++}; ++ ++struct mm_get_temp_comp_cfm ++{ ++ /// Request status ++ u8_l status; ++ /// Temp degree val ++ s8_l degree; ++}; ++ ++struct mm_set_ext_flags_req ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_set_ext_flags_cfm ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_get_ext_flags_cfm ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_mask_set_ext_flags_req ++{ ++ u32_l user_flags_mask; ++ u32_l user_flags_val; ++}; ++ ++struct mm_mask_set_ext_flags_cfm ++{ ++ u32_l user_flags; ++}; ++ ++struct mm_set_vendor_swconfig_req ++{ ++ u32_l swconfig_id; ++ union { ++ struct mm_set_bcn_cfg_req bcn_cfg_req; ++ struct mm_set_temp_comp_req temp_comp_set_req; ++ struct mm_set_ext_flags_req ext_flags_set_req; ++ struct mm_mask_set_ext_flags_req ext_flags_mask_set_req; ++ }; ++}; ++ ++struct mm_set_vendor_swconfig_cfm ++{ ++ u32_l swconfig_id; ++ union { ++ struct mm_set_bcn_cfg_cfm bcn_cfg_cfm; ++ struct mm_set_temp_comp_cfm temp_comp_set_cfm; ++ struct mm_get_temp_comp_cfm temp_comp_get_cfm; ++ struct mm_set_ext_flags_cfm ext_flags_set_cfm; ++ struct mm_get_ext_flags_cfm ext_flags_get_cfm; ++ struct mm_mask_set_ext_flags_cfm ext_flags_mask_set_cfm; ++ }; ++}; ++ ++#ifdef CONFIG_SDIO_BT ++struct mm_bt_send_req ++{ ++ u32_l data_len; ++ u8_l bt_data[1024]; ++}; ++ ++struct mm_bt_send_cfm ++{ ++ u8_l status; ++}; ++#endif ++ ++/// Structure containing the parameters of the @ref ME_RC_STATS_REQ message. ++struct me_rc_stats_req { ++ /// Index of the station for which the RC statistics are requested ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the rate control statistics ++struct rc_rate_stats { ++ /// Number of attempts (per sampling interval) ++ u16_l attempts; ++ /// Number of success (per sampling interval) ++ u16_l success; ++ /// Estimated probability of success (EWMA) ++ u16_l probability; ++ /// Rate configuration of the sample ++ u16_l rate_config; ++ union { ++ struct { ++ /// Number of times the sample has been skipped (per sampling interval) ++ u8_l sample_skipped; ++ /// Whether the old probability is available ++ bool_l old_prob_available; ++ /// Whether the rate can be used in the retry chain ++ bool_l rate_allowed; ++ }; ++ struct { ++ /// RU size and UL length received in the latest HE trigger frame ++ u16_l ru_and_length; ++ }; ++ }; ++}; ++ ++/// Number of RC samples ++#define RC_MAX_N_SAMPLE 10 ++/// Index of the HE statistics element in the table ++#define RC_HE_STATS_IDX RC_MAX_N_SAMPLE ++ ++/// Structure containing the parameters of the @ref ME_RC_STATS_CFM message. ++struct me_rc_stats_cfm { ++ /// Index of the station for which the RC statistics are provided ++ u8_l sta_idx; ++ /// Number of samples used in the RC algorithm ++ u16_l no_samples; ++ /// Number of MPDUs transmitted (per sampling interval) ++ u16_l ampdu_len; ++ /// Number of AMPDUs transmitted (per sampling interval) ++ u16_l ampdu_packets; ++ /// Average number of MPDUs in each AMPDU frame (EWMA) ++ u32_l avg_ampdu_len; ++ // Current step 0 of the retry chain ++ u8_l sw_retry_step; ++ /// Trial transmission period ++ u8_l sample_wait; ++ /// Retry chain steps ++ u16_l retry_step_idx[4]; ++ /// RC statistics - Max number of RC samples, plus one for the HE TB statistics ++ struct rc_rate_stats rate_stats[RC_MAX_N_SAMPLE + 1]; ++ /// Throughput - Max number of RC samples, plus one for the HE TB statistics ++ u32_l tp[RC_MAX_N_SAMPLE + 1]; ++}; ++ ++/// Structure containing the parameters of the @ref ME_RC_SET_RATE_REQ message. ++struct me_rc_set_rate_req { ++ /// Index of the station for which the fixed rate is set ++ u8_l sta_idx; ++ /// Rate configuration to be set ++ u16_l fixed_rate_cfg; ++}; ++ ++/// Structure containing the parameters of the @ref ME_CONFIG_MONITOR_REQ message. ++struct me_config_monitor_req { ++ /// Channel to configure ++ struct mac_chan_op chan; ++ /// Is channel data valid ++ bool_l chan_set; ++ /// Enable report of unsupported HT frames ++ bool_l uf; ++ /// Enable auto-reply as the mac_addr matches ++ bool_l auto_reply; ++}; ++ ++/// Structure containing the parameters of the @ref ME_CONFIG_MONITOR_CFM message. ++struct me_config_monitor_cfm { ++ /// Channel context index ++ u8_l chan_index; ++ /// Channel parameters ++ struct mac_chan_op chan; ++}; ++ ++/// Structure containing the parameters of the @ref ME_SET_PS_MODE_REQ message. ++struct me_set_ps_mode_req { ++ /// Power Save is activated or deactivated ++ u8_l ps_state; ++}; ++ ++/// Structure containing the parameters of the @ref ME_SET_LP_LEVEL_REQ message. ++struct me_set_lp_level_req { ++ /// Low Power level ++ u8_l lp_level; ++ u8_l disable_filter; ++}; ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For SM messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Message API of the SM task ++enum sm_msg_tag { ++ /// Request to connect to an AP ++ SM_CONNECT_REQ = LMAC_FIRST_MSG(TASK_SM), ++ /// Confirmation of connection ++ SM_CONNECT_CFM, ++ /// Indicates that the SM associated to the AP ++ SM_CONNECT_IND, ++ /// Request to disconnect ++ SM_DISCONNECT_REQ, ++ /// Confirmation of disconnection ++ SM_DISCONNECT_CFM, ++ /// Indicates that the SM disassociated the AP ++ SM_DISCONNECT_IND, ++ /// Request to start external authentication ++ SM_EXTERNAL_AUTH_REQUIRED_IND, ++ /// Response to external authentication request ++ SM_EXTERNAL_AUTH_REQUIRED_RSP, ++ /// Request to update assoc elements after FT over the air authentication ++ SM_FT_AUTH_IND, ++ /// Response to FT authentication with updated assoc elements ++ SM_FT_AUTH_RSP, ++ ++ SM_RSP_TIMEOUT_IND, ++ ++ SM_COEX_TS_TIMEOUT_IND, ++ ++ SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM, ++ /// MAX number of messages ++ SM_MAX, ++}; ++ ++/// Structure containing the parameters of @ref SM_CONNECT_REQ message. ++struct sm_connect_req { ++ /// SSID to connect to ++ struct mac_ssid ssid; ++ /// BSSID to connect to (if not specified, set this field to WILDCARD BSSID) ++ struct mac_addr bssid; ++ /// Channel on which we have to connect (if not specified, set -1 in the chan.freq field) ++ struct mac_chan_def chan; ++ /// Connection flags (see @ref mac_connection_flags) ++ u32_l flags; ++ /// Control port Ethertype (in network endianness) ++ u16_l ctrl_port_ethertype; ++ /// Length of the association request IEs ++ u16_l ie_len; ++ /// Listen interval to be used for this connection ++ u16_l listen_interval; ++ /// Flag indicating if the we have to wait for the BC/MC traffic after beacon or not ++ bool_l dont_wait_bcmc; ++ /// Authentication type ++ u8_l auth_type; ++ /// UAPSD queues (bit0: VO, bit1: VI, bit2: BE, bit3: BK) ++ u8_l uapsd_queues; ++ /// VIF index ++ u8_l vif_idx; ++ /// Buffer containing the additional information elements to be put in the ++ /// association request ++ u32_l ie_buf[64]; ++}; ++ ++/// Structure containing the parameters of the @ref SM_CONNECT_CFM message. ++struct sm_connect_cfm { ++ /// Status. If 0, it means that the connection procedure will be performed and that ++ /// a subsequent @ref SM_CONNECT_IND message will be forwarded once the procedure is ++ /// completed ++ u8_l status; ++}; ++ ++#define SM_ASSOC_IE_LEN 800 ++/// Structure containing the parameters of the @ref SM_CONNECT_IND message. ++struct sm_connect_ind { ++ /// Status code of the connection procedure ++ u16_l status_code; ++ /// BSSID ++ struct mac_addr bssid; ++ /// Flag indicating if the indication refers to an internal roaming or from a host request ++ bool_l roamed; ++ /// Index of the VIF for which the association process is complete ++ u8_l vif_idx; ++ /// Index of the STA entry allocated for the AP ++ u8_l ap_idx; ++ /// Index of the LMAC channel context the connection is attached to ++ u8_l ch_idx; ++ /// Flag indicating if the AP is supporting QoS ++ bool_l qos; ++ /// ACM bits set in the AP WMM parameter element ++ u8_l acm; ++ /// Length of the AssocReq IEs ++ u16_l assoc_req_ie_len; ++ /// Length of the AssocRsp IEs ++ u16_l assoc_rsp_ie_len; ++ /// IE buffer ++ u32_l assoc_ie_buf[SM_ASSOC_IE_LEN/4]; ++ ++ u16_l aid; ++ u8_l band; ++ u16_l center_freq; ++ u8_l width; ++ u32_l center_freq1; ++ u32_l center_freq2; ++ ++ /// EDCA parameters ++ u32_l ac_param[AC_MAX]; ++}; ++ ++/// Structure containing the parameters of the @ref SM_DISCONNECT_REQ message. ++struct sm_disconnect_req { ++ /// Reason of the deauthentication. ++ u16_l reason_code; ++ /// Index of the VIF. ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of SM_ASSOCIATION_IND the message ++struct sm_association_ind { ++ // MAC ADDR of the STA ++ struct mac_addr me_mac_addr; ++}; ++ ++ ++/// Structure containing the parameters of the @ref SM_DISCONNECT_IND message. ++struct sm_disconnect_ind { ++ /// Reason of the disconnection. ++ u16_l reason_code; ++ /// Index of the VIF. ++ u8_l vif_idx; ++ /// FT over DS is ongoing ++ bool_l ft_over_ds; ++ u8_l reassoc; ++}; ++ ++/// Structure containing the parameters of the @ref SM_EXTERNAL_AUTH_REQUIRED_IND ++struct sm_external_auth_required_ind { ++ /// Index of the VIF. ++ u8_l vif_idx; ++ /// SSID to authenticate to ++ struct mac_ssid ssid; ++ /// BSSID to authenticate to ++ struct mac_addr bssid; ++ /// AKM suite of the respective authentication ++ u32_l akm; ++}; ++ ++/// Structure containing the parameters of the @ref SM_EXTERNAL_AUTH_REQUIRED_RSP ++struct sm_external_auth_required_rsp { ++ /// Index of the VIF. ++ u8_l vif_idx; ++ /// Authentication status ++ u16_l status; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For APM messages ++/////////////////////////////////////////////////////////////////////////////// ++/// Message API of the APM task ++enum apm_msg_tag { ++ /// Request to start the AP. ++ APM_START_REQ = LMAC_FIRST_MSG(TASK_APM), ++ /// Confirmation of the AP start. ++ APM_START_CFM, ++ /// Request to stop the AP. ++ APM_STOP_REQ, ++ /// Confirmation of the AP stop. ++ APM_STOP_CFM, ++ /// Request to start CAC ++ APM_START_CAC_REQ, ++ /// Confirmation of the CAC start ++ APM_START_CAC_CFM, ++ /// Request to stop CAC ++ APM_STOP_CAC_REQ, ++ /// Confirmation of the CAC stop ++ APM_STOP_CAC_CFM, ++ ++ APM_SET_BEACON_IE_REQ, ++ APM_SET_BEACON_IE_CFM, ++ ++ /// MAX number of messages ++ APM_MAX, ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_REQ message. ++struct apm_start_req { ++ /// Basic rate set ++ struct mac_rateset basic_rates; ++ /// Control channel on which we have to enable the AP ++ struct mac_chan_def chan; ++ /// Center frequency of the first segment ++ u32_l center_freq1; ++ /// Center frequency of the second segment (only in 80+80 configuration) ++ u32_l center_freq2; ++ /// Width of channel ++ u8_l ch_width; ++ /// Address, in host memory, to the beacon template ++ u32_l bcn_addr; ++ /// Length of the beacon template ++ u16_l bcn_len; ++ /// Offset of the TIM IE in the beacon ++ u16_l tim_oft; ++ /// Beacon interval ++ u16_l bcn_int; ++ /// Flags (@ref mac_connection_flags) ++ u32_l flags; ++ /// Control port Ethertype ++ u16_l ctrl_port_ethertype; ++ /// Length of the TIM IE ++ u8_l tim_len; ++ /// Index of the VIF for which the AP is started ++ u8_l vif_idx; ++}; ++ ++struct apm_set_bcn_ie_req { ++ u8_l vif_idx; ++ u16_l bcn_ie_len; ++ u8_l bcn_ie[512]; ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_CFM message. ++struct apm_start_cfm { ++ /// Status of the AP starting procedure ++ u8_l status; ++ /// Index of the VIF for which the AP is started ++ u8_l vif_idx; ++ /// Index of the channel context attached to the VIF ++ u8_l ch_idx; ++ /// Index of the STA used for BC/MC traffic ++ u8_l bcmc_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_STOP_REQ message. ++struct apm_stop_req { ++ /// Index of the VIF for which the AP has to be stopped ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_CAC_REQ message. ++struct apm_start_cac_req { ++ /// Control channel on which we have to start the CAC ++ struct mac_chan_op chan; ++ /// Center frequency of the first segment ++ //u32_l center_freq1; ++ /// Center frequency of the second segment (only in 80+80 configuration) ++ //u32_l center_freq2; ++ /// Width of channel ++ //u8_l ch_width; ++ /// Index of the VIF for which the CAC is started ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_START_CAC_CFM message. ++struct apm_start_cac_cfm { ++ /// Status of the CAC starting procedure ++ u8_l status; ++ /// Index of the channel context attached to the VIF for CAC ++ u8_l ch_idx; ++}; ++ ++/// Structure containing the parameters of the @ref APM_STOP_CAC_REQ message. ++struct apm_stop_cac_req { ++ /// Index of the VIF for which the CAC has to be stopped ++ u8_l vif_idx; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For MESH messages ++/////////////////////////////////////////////////////////////////////////////// ++ ++/// Maximum length of the Mesh ID ++#define MESH_MESHID_MAX_LEN (32) ++ ++/// Message API of the MESH task ++enum mesh_msg_tag ++{ ++ /// Request to start the MP ++ MESH_START_REQ = LMAC_FIRST_MSG(TASK_MESH), ++ /// Confirmation of the MP start. ++ MESH_START_CFM, ++ ++ /// Request to stop the MP. ++ MESH_STOP_REQ, ++ /// Confirmation of the MP stop. ++ MESH_STOP_CFM, ++ ++ // Request to update the MP ++ MESH_UPDATE_REQ, ++ /// Confirmation of the MP update ++ MESH_UPDATE_CFM, ++ ++ /// Request information about a given link ++ MESH_PEER_INFO_REQ, ++ /// Response to the MESH_PEER_INFO_REQ message ++ MESH_PEER_INFO_CFM, ++ ++ /// Request automatic establishment of a path with a given mesh STA ++ MESH_PATH_CREATE_REQ, ++ /// Confirmation to the MESH_PATH_CREATE_REQ message ++ MESH_PATH_CREATE_CFM, ++ ++ /// Request a path update (delete path, modify next hop mesh STA) ++ MESH_PATH_UPDATE_REQ, ++ /// Confirmation to the MESH_PATH_UPDATE_REQ message ++ MESH_PATH_UPDATE_CFM, ++ ++ /// Indication from Host that the indicated Mesh Interface is a proxy for an external STA ++ MESH_PROXY_ADD_REQ, ++ ++ /// Indicate that a connection has been established or lost ++ MESH_PEER_UPDATE_IND, ++ /// Notification that a connection has been established or lost (when MPM handled by userspace) ++ MESH_PEER_UPDATE_NTF = MESH_PEER_UPDATE_IND, ++ ++ /// Indicate that a path is now active or inactive ++ MESH_PATH_UPDATE_IND, ++ /// Indicate that proxy information have been updated ++ MESH_PROXY_UPDATE_IND, ++ ++ /// MAX number of messages ++ MESH_MAX, ++}; ++ ++ ++/// Structure containing the parameters of the @ref MESH_START_REQ message. ++struct mesh_start_req { ++ /// Basic rate set ++ struct mac_rateset basic_rates; ++ /// Control channel on which we have to enable the AP ++ struct mac_chan_def chan; ++ /// Center frequency of the first segment ++ u32_l center_freq1; ++ /// Center frequency of the second segment (only in 80+80 configuration) ++ u32_l center_freq2; ++ /// Width of channel ++ u8_l ch_width; ++ /// DTIM Period ++ u8_l dtim_period; ++ /// Beacon Interval ++ u16_l bcn_int; ++ /// Index of the VIF for which the MP is started ++ u8_l vif_index; ++ /// Length of the Mesh ID ++ u8_l mesh_id_len; ++ /// Mesh ID ++ u8_l mesh_id[MESH_MESHID_MAX_LEN]; ++ /// Address of the IEs to download ++ u32_l ie_addr; ++ /// Length of the provided IEs ++ u8_l ie_len; ++ /// Indicate if Mesh Peering Management (MPM) protocol is handled in userspace ++ bool_l user_mpm; ++ /// Indicate if Mesh Point is using authentication ++ bool_l is_auth; ++ /// Indicate which authentication method is used ++ u8_l auth_id; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_START_CFM message. ++struct mesh_start_cfm { ++ /// Status of the MP starting procedure ++ u8_l status; ++ /// Index of the VIF for which the MP is started ++ u8_l vif_idx; ++ /// Index of the channel context attached to the VIF ++ u8_l ch_idx; ++ /// Index of the STA used for BC/MC traffic ++ u8_l bcmc_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_STOP_REQ message. ++struct mesh_stop_req { ++ /// Index of the VIF for which the MP has to be stopped ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_STOP_CFM message. ++struct mesh_stop_cfm { ++ /// Index of the VIF for which the MP has to be stopped ++ u8_l vif_idx; ++ /// Status ++ u8_l status; ++}; ++ ++/// Bit fields for mesh_update_req message's flags value ++enum mesh_update_flags_bit { ++ /// Root Mode ++ MESH_UPDATE_FLAGS_ROOT_MODE_BIT = 0, ++ /// Gate Mode ++ MESH_UPDATE_FLAGS_GATE_MODE_BIT, ++ /// Mesh Forwarding ++ MESH_UPDATE_FLAGS_MESH_FWD_BIT, ++ /// Local Power Save Mode ++ MESH_UPDATE_FLAGS_LOCAL_PSM_BIT, ++}; ++ ++/// Structure containing the parameters of the @ref MESH_UPDATE_REQ message. ++struct mesh_update_req { ++ /// Flags, indicate fields which have been updated ++ u8_l flags; ++ /// VIF Index ++ u8_l vif_idx; ++ /// Root Mode ++ u8_l root_mode; ++ /// Gate Announcement ++ bool_l gate_announ; ++ /// Mesh Forwarding ++ bool_l mesh_forward; ++ /// Local PS Mode ++ u8_l local_ps_mode; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_UPDATE_CFM message. ++struct mesh_update_cfm { ++ /// Status ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_INFO_REQ message. ++struct mesh_peer_info_req { ++ ///Index of the station allocated for the peer ++ u8_l sta_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_INFO_CFM message. ++struct mesh_peer_info_cfm { ++ /// Response status ++ u8_l status; ++ /// Index of the station allocated for the peer ++ u8_l sta_idx; ++ /// Local Link ID ++ u16_l local_link_id; ++ /// Peer Link ID ++ u16_l peer_link_id; ++ /// Local PS Mode ++ u8_l local_ps_mode; ++ /// Peer PS Mode ++ u8_l peer_ps_mode; ++ /// Non-peer PS Mode ++ u8_l non_peer_ps_mode; ++ /// Link State ++ u8_l link_state; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_CREATE_REQ message. ++struct mesh_path_create_req { ++ /// Index of the interface on which path has to be created ++ u8_l vif_idx; ++ /// Indicate if originator MAC Address is provided ++ bool_l has_orig_addr; ++ /// Path Target MAC Address ++ struct mac_addr tgt_mac_addr; ++ /// Originator MAC Address ++ struct mac_addr orig_mac_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_CREATE_CFM message. ++struct mesh_path_create_cfm { ++ /// Confirmation status ++ u8_l status; ++ /// VIF Index ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_UPDATE_REQ message. ++struct mesh_path_update_req { ++ /// Indicate if path must be deleted ++ bool_l delete; ++ /// Index of the interface on which path has to be created ++ u8_l vif_idx; ++ /// Path Target MAC Address ++ struct mac_addr tgt_mac_addr; ++ /// Next Hop MAC Address ++ struct mac_addr nhop_mac_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_UPDATE_CFM message. ++struct mesh_path_update_cfm { ++ /// Confirmation status ++ u8_l status; ++ /// VIF Index ++ u8_l vif_idx; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PROXY_ADD_REQ message. ++struct mesh_proxy_add_req { ++ /// VIF Index ++ u8_l vif_idx; ++ /// MAC Address of the External STA ++ struct mac_addr ext_sta_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PROXY_UPDATE_IND ++struct mesh_proxy_update_ind { ++ /// Indicate if proxy information has been added or deleted ++ bool_l delete; ++ /// Indicate if we are a proxy for the external STA ++ bool_l local; ++ /// VIF Index ++ u8_l vif_idx; ++ /// MAC Address of the External STA ++ struct mac_addr ext_sta_addr; ++ /// MAC Address of the proxy (only valid if local is false) ++ struct mac_addr proxy_mac_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_UPDATE_IND message. ++struct mesh_peer_update_ind { ++ /// Indicate if connection has been established or lost ++ bool_l estab; ++ /// VIF Index ++ u8_l vif_idx; ++ /// STA Index ++ u8_l sta_idx; ++ /// Peer MAC Address ++ struct mac_addr peer_addr; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PEER_UPDATE_NTF message. ++struct mesh_peer_update_ntf { ++ /// VIF Index ++ u8_l vif_idx; ++ /// STA Index ++ u8_l sta_idx; ++ /// Mesh Link State ++ u8_l state; ++}; ++ ++/// Structure containing the parameters of the @ref MESH_PATH_UPDATE_IND message. ++struct mesh_path_update_ind { ++ /// Indicate if path is deleted or not ++ bool_l delete; ++ /// Indicate if path is towards an external STA (not part of MBSS) ++ bool_l ext_sta; ++ /// VIF Index ++ u8_l vif_idx; ++ /// Path Index ++ u8_l path_idx; ++ /// Target MAC Address ++ struct mac_addr tgt_mac_addr; ++ /// External STA MAC Address (only if ext_sta is true) ++ struct mac_addr ext_sta_mac_addr; ++ /// Next Hop STA Index ++ u8_l nhop_sta_idx; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For Debug messages ++/////////////////////////////////////////////////////////////////////////////// ++ ++/// Messages related to Debug Task ++enum dbg_msg_tag { ++ /// Memory read request ++ DBG_MEM_READ_REQ = LMAC_FIRST_MSG(TASK_DBG), ++ /// Memory read confirm ++ DBG_MEM_READ_CFM, ++ /// Memory write request ++ DBG_MEM_WRITE_REQ, ++ /// Memory write confirm ++ DBG_MEM_WRITE_CFM, ++ /// Module filter request ++ DBG_SET_MOD_FILTER_REQ, ++ /// Module filter confirm ++ DBG_SET_MOD_FILTER_CFM, ++ /// Severity filter request ++ DBG_SET_SEV_FILTER_REQ, ++ /// Severity filter confirm ++ DBG_SET_SEV_FILTER_CFM, ++ /// LMAC/MAC HW fatal error indication ++ DBG_ERROR_IND, ++ /// Request to get system statistics ++ DBG_GET_SYS_STAT_REQ, ++ /// COnfirmation of system statistics ++ DBG_GET_SYS_STAT_CFM, ++ /// Memory block write request ++ DBG_MEM_BLOCK_WRITE_REQ, ++ /// Memory block write confirm ++ DBG_MEM_BLOCK_WRITE_CFM, ++ /// Start app request ++ DBG_START_APP_REQ, ++ /// Start app confirm ++ DBG_START_APP_CFM, ++ /// Start npc request ++ DBG_START_NPC_REQ, ++ /// Start npc confirm ++ DBG_START_NPC_CFM, ++ /// Memory mask write request ++ DBG_MEM_MASK_WRITE_REQ, ++ /// Memory mask write confirm ++ DBG_MEM_MASK_WRITE_CFM, ++ ++ DBG_RFTEST_CMD_REQ, ++ DBG_RFTEST_CMD_CFM, ++ DBG_BINDING_REQ, ++ DBG_BINDING_CFM, ++ DBG_BINDING_IND, ++ ++ DBG_CUSTOM_MSG_REQ, ++ DBG_CUSTOM_MSG_CFM, ++ DBG_CUSTOM_MSG_IND, ++ ++ DBG_GPIO_WRITE_REQ, ++ DBG_GPIO_WRITE_CFM, ++ DBG_GPIO_READ_REQ, ++ DBG_GPIO_READ_CFM, ++ DBG_GPIO_INIT_REQ, ++ DBG_GPIO_INIT_CFM, ++ ++ /// EF usrdata read request ++ DBG_EF_USRDATA_READ_REQ, ++ /// EF usrdata read confirm ++ DBG_EF_USRDATA_READ_CFM, ++ /// Memory block read request ++ DBG_MEM_BLOCK_READ_REQ, ++ /// Memory block read confirm ++ DBG_MEM_BLOCK_READ_CFM, ++ ++ DBG_PWM_INIT_REQ, ++ DBG_PWM_INIT_CFM, ++ DBG_PWM_DEINIT_REQ, ++ DBG_PWM_DEINIT_CFM, ++ ++ /// Max number of Debug messages ++ DBG_MAX, ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_REQ message. ++struct dbg_mem_read_req { ++ u32_l memaddr; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_READ_CFM message. ++struct dbg_mem_read_cfm { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_REQ message. ++struct dbg_mem_write_req { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_WRITE_CFM message. ++struct dbg_mem_write_cfm { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_REQ message. ++struct dbg_mem_mask_write_req { ++ u32_l memaddr; ++ u32_l memmask; ++ u32_l memdata; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_CFM message. ++struct dbg_mem_mask_write_cfm { ++ u32_l memaddr; ++ u32_l memdata; ++}; ++ ++struct dbg_rftest_cmd_req { ++ u32_l cmd; ++ u32_l argc; ++ u8_l argv[10]; ++}; ++ ++struct dbg_rftest_cmd_cfm { ++ u32_l rftest_result[32]; ++}; ++ ++struct dbg_gpio_write_req { ++ uint8_t gpio_idx; ++ uint8_t gpio_val; ++}; ++ ++struct dbg_gpio_read_req { ++ uint8_t gpio_idx; ++}; ++ ++struct dbg_gpio_read_cfm { ++ uint8_t gpio_idx; ++ uint8_t gpio_val; ++}; ++ ++struct dbg_gpio_init_req { ++ uint8_t gpio_idx; ++ uint8_t gpio_dir; //1 output, 0 input; ++ uint8_t gpio_val; //for output, 1 high, 0 low; ++}; ++ ++#ifdef CONFIG_MCU_MESSAGE ++/// Structure containing the parameters of the @ref DBG_CUSTOM_MSG_REQ message. ++struct dbg_custom_msg_req ++{ ++ u32_l cmd; ++ u32_l len; ++ u32_l flags; ++ u32_l buf[1]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_CUSTOM_MSG_CFM message. ++struct dbg_custom_msg_cfm ++{ ++ u32_l cmd; ++ u32_l len; ++ u32_l status; ++ u32_l buf[1]; ++}; ++ ++typedef struct dbg_custom_msg_cfm dbg_custom_msg_ind_t; ++#endif ++ ++/// Structure containing the parameters of the @ref DBG_SET_MOD_FILTER_REQ message. ++struct dbg_set_mod_filter_req { ++ /// Bit field indicating for each module if the traces are enabled or not ++ u32_l mod_filter; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_SEV_MOD_FILTER_REQ message. ++struct dbg_set_sev_filter_req { ++ /// Bit field indicating the severity threshold for the traces ++ u32_l sev_filter; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_GET_SYS_STAT_CFM message. ++struct dbg_get_sys_stat_cfm { ++ /// Time spent in CPU sleep since last reset of the system statistics ++ u32_l cpu_sleep_time; ++ /// Time spent in DOZE since last reset of the system statistics ++ u32_l doze_time; ++ /// Total time spent since last reset of the system statistics ++ u32_l stats_time; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_REQ message. ++struct dbg_mem_block_write_req { ++ u32_l memaddr; ++ u32_l memsize; ++ u32_l memdata[1024 / sizeof(u32_l)]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_CFM message. ++struct dbg_mem_block_write_cfm { ++ u32_l wstatus; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_READ_REQ message. ++struct dbg_mem_block_read_req ++{ ++ u32_l memaddr; ++ u32_l memsize; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_READ_CFM message. ++struct dbg_mem_block_read_cfm ++{ ++ u32_l memaddr; ++ u32_l memsize; ++ u32_l memdata[1024 / sizeof(u32_l)]; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_REQ message. ++struct dbg_start_app_req { ++ u32_l bootaddr; ++ u32_l boottype; ++}; ++ ++/// Structure containing the parameters of the @ref DBG_START_APP_CFM message. ++struct dbg_start_app_cfm { ++ u32_l bootstatus; ++}; ++ ++enum { ++ HOST_START_APP_AUTO = 1, ++ HOST_START_APP_CUSTOM, ++ HOST_START_APP_FNCALL = 4, ++ HOST_START_APP_DUMMY = 5, ++}; ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// For TDLS messages ++/////////////////////////////////////////////////////////////////////////////// ++ ++/// List of messages related to the task. ++enum tdls_msg_tag { ++ /// TDLS channel Switch Request. ++ TDLS_CHAN_SWITCH_REQ = LMAC_FIRST_MSG(TASK_TDLS), ++ /// TDLS channel switch confirmation. ++ TDLS_CHAN_SWITCH_CFM, ++ /// TDLS channel switch indication. ++ TDLS_CHAN_SWITCH_IND, ++ /// TDLS channel switch to base channel indication. ++ TDLS_CHAN_SWITCH_BASE_IND, ++ /// TDLS cancel channel switch request. ++ TDLS_CANCEL_CHAN_SWITCH_REQ, ++ /// TDLS cancel channel switch confirmation. ++ TDLS_CANCEL_CHAN_SWITCH_CFM, ++ /// TDLS peer power save indication. ++ TDLS_PEER_PS_IND, ++ /// TDLS peer traffic indication request. ++ TDLS_PEER_TRAFFIC_IND_REQ, ++ /// TDLS peer traffic indication confirmation. ++ TDLS_PEER_TRAFFIC_IND_CFM, ++ ++#ifdef CONFIG_SDIO_BT ++ TDLS_SDIO_BT_SEND_REQ = LMAC_FIRST_MSG(TASK_TDLS)+16, ++ TDLS_SDIO_BT_SEND_CFM, ++ TDLS_SDIO_BT_RECV_IND, ++#endif ++ /// MAX number of messages ++ TDLS_MAX ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_REQ message ++struct tdls_chan_switch_req { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ /// MAC address of the TDLS station ++ struct mac_addr peer_mac_addr; ++ bool_l initiator; ++ /// Band (2.4GHz or 5GHz) ++ u8_l band; ++ /// Channel type: 20,40,80,160 or 80+80 MHz ++ u8_l type; ++ /// Frequency for Primary 20MHz channel (in MHz) ++ u16_l prim20_freq; ++ /// Frequency for Center of the contiguous channel or center of Primary 80+80 ++ u16_l center1_freq; ++ /// Frequency for Center of the non-contiguous secondary 80+80 ++ u16_l center2_freq; ++ /// TX power (in dBm) ++ s8_l tx_power; ++ /// Operating class ++ u8_l op_class; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CANCEL_CHAN_SWITCH_REQ message ++struct tdls_cancel_chan_switch_req { ++ /// Index of the VIF ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ /// MAC address of the TDLS station ++ struct mac_addr peer_mac_addr; ++}; ++ ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_CFM message ++struct tdls_chan_switch_cfm { ++ /// Status of the operation ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CANCEL_CHAN_SWITCH_CFM message ++struct tdls_cancel_chan_switch_cfm { ++ /// Status of the operation ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_IND message ++struct tdls_chan_switch_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// Channel Context Index ++ u8_l chan_ctxt_index; ++ /// Status of the operation ++ u8_l status; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_BASE_IND message ++struct tdls_chan_switch_base_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// Channel Context index ++ u8_l chan_ctxt_index; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_PEER_PS_IND message ++struct tdls_peer_ps_ind { ++ /// VIF Index ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ /// MAC ADDR of the TDLS STA ++ struct mac_addr peer_mac_addr; ++ /// Flag to indicate if the TDLS peer is going to sleep ++ bool ps_on; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_PEER_TRAFFIC_IND_REQ message ++struct tdls_peer_traffic_ind_req { ++ /// VIF Index ++ u8_l vif_index; ++ /// STA Index ++ u8_l sta_idx; ++ // MAC ADDR of the TDLS STA ++ struct mac_addr peer_mac_addr; ++ /// Dialog token ++ u8_l dialog_token; ++ /// TID of the latest MPDU transmitted over the TDLS direct link to the TDLS STA ++ u8_l last_tid; ++ /// Sequence number of the latest MPDU transmitted over the TDLS direct link ++ /// to the TDLS STA ++ u16_l last_sn; ++}; ++ ++/// Structure containing the parameters of the @ref TDLS_PEER_TRAFFIC_IND_CFM message ++struct tdls_peer_traffic_ind_cfm { ++ /// Status of the operation ++ u8_l status; ++}; ++ ++ ++#endif // LMAC_MSG_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h +new file mode 100644 +index 000000000000..83b112290409 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h +@@ -0,0 +1,62 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file co_types.h ++ * ++ * @brief This file replaces the need to include stdint or stdbool typical headers, ++ * which may not be available in all toolchains, and adds new types ++ * ++ * Copyright (C) RivieraWaves 2009-2019 ++ * ++ * $Rev: $ ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _LMAC_INT_H_ ++#define _LMAC_INT_H_ ++ ++ ++/** ++ **************************************************************************************** ++ * @addtogroup CO_INT ++ * @ingroup COMMON ++ * @brief Common integer standard types (removes use of stdint) ++ * ++ * @{ ++ **************************************************************************************** ++ */ ++ ++ ++/* ++ * DEFINES ++ **************************************************************************************** ++ */ ++ ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++#include ++#else ++#include ++#endif ++ ++#ifdef CONFIG_RWNX_TL4 ++typedef uint16_t u8_l; ++typedef int16_t s8_l; ++typedef uint16_t bool_l; ++#else ++typedef uint8_t u8_l; ++typedef int8_t s8_l; ++typedef bool bool_l; ++#endif ++typedef uint16_t u16_l; ++typedef int16_t s16_l; ++typedef uint32_t u32_l; ++typedef int32_t s32_l; ++typedef uint64_t u64_l; ++ ++ ++ ++/// @} CO_INT ++#endif // _LMAC_INT_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c +new file mode 100644 +index 000000000000..3d7b65375adb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c +@@ -0,0 +1,161 @@ ++#include ++#include "md5.h" ++ ++unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; ++ ++void MD5Init(MD5_CTX *context) ++{ ++ context->count[0] = 0; ++ context->count[1] = 0; ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xEFCDAB89; ++ context->state[2] = 0x98BADCFE; ++ context->state[3] = 0x10325476; ++} ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) ++{ ++ unsigned int i = 0,index = 0,partlen = 0; ++ index = (context->count[0] >> 3) & 0x3F; ++ partlen = 64 - index; ++ context->count[0] += inputlen << 3; ++ if(context->count[0] < (inputlen << 3)) ++ context->count[1]++; ++ context->count[1] += inputlen >> 29; ++ ++ if(inputlen >= partlen) ++ { ++ memcpy(&context->buffer[index],input,partlen); ++ MD5Transform(context->state,context->buffer); ++ for(i = partlen;i+64 <= inputlen;i+=64) ++ MD5Transform(context->state,&input[i]); ++ index = 0; ++ } ++ else ++ { ++ i = 0; ++ } ++ memcpy(&context->buffer[index],&input[i],inputlen-i); ++} ++void MD5Final(MD5_CTX *context,unsigned char digest[16]) ++{ ++ unsigned int index = 0,padlen = 0; ++ unsigned char bits[8]; ++ index = (context->count[0] >> 3) & 0x3F; ++ padlen = (index < 56)?(56-index):(120-index); ++ MD5Encode(bits,context->count,8); ++ MD5Update(context,PADDING,padlen); ++ MD5Update(context,bits,8); ++ MD5Encode(digest,context->state,16); ++} ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[j] = input[i] & 0xFF; ++ output[j+1] = (input[i] >> 8) & 0xFF; ++ output[j+2] = (input[i] >> 16) & 0xFF; ++ output[j+3] = (input[i] >> 24) & 0xFF; ++ i++; ++ j+=4; ++ } ++} ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) ++{ ++ unsigned int i = 0,j = 0; ++ while(j < len) ++ { ++ output[i] = (input[j]) | ++ (input[j+1] << 8) | ++ (input[j+2] << 16) | ++ (input[j+3] << 24); ++ i++; ++ j+=4; ++ } ++} ++void MD5Transform(unsigned int state[4],unsigned char block[64]) ++{ ++ unsigned int a = state[0]; ++ unsigned int b = state[1]; ++ unsigned int c = state[2]; ++ unsigned int d = state[3]; ++ unsigned int x[64]; ++ MD5Decode(x,block,64); ++ FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ ++ FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ ++ FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ ++ FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ ++ FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ ++ FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ ++ FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ ++ FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ ++ FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ ++ FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ ++ FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ ++ FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ ++ FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ ++ FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ ++ FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ ++ FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ ++ ++ /* Round 2 */ ++ GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ ++ GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ ++ GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ ++ GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ ++ GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ ++ GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ ++ GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ ++ GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ ++ GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ ++ GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ ++ GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ ++ GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ ++ GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ ++ GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ ++ GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ ++ GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ ++ ++ /* Round 3 */ ++ HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ ++ HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ ++ HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ ++ HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ ++ HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ ++ HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ ++ HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ ++ HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ ++ HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ ++ HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ ++ HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ ++ HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ ++ HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ ++ HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ ++ HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ ++ HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ ++ ++ /* Round 4 */ ++ II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ ++ II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ ++ II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ ++ II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ ++ II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ ++ II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ ++ II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ ++ II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ ++ II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ ++ II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ ++ II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ ++ II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ ++ II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ ++ II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ ++ II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ ++ II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h +new file mode 100644 +index 000000000000..6ed5c0f8e886 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h +@@ -0,0 +1,48 @@ ++#ifndef MD5_H ++#define MD5_H ++ ++typedef struct ++{ ++ unsigned int count[2]; ++ unsigned int state[4]; ++ unsigned char buffer[64]; ++}MD5_CTX; ++ ++ ++#define F(x,y,z) ((x & y) | (~x & z)) ++#define G(x,y,z) ((x & z) | (y & ~z)) ++#define H(x,y,z) (x^y^z) ++#define I(x,y,z) (y ^ (x | ~z)) ++#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) ++#define FF(a,b,c,d,x,s,ac) \ ++ { \ ++ a += F(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define GG(a,b,c,d,x,s,ac) \ ++ { \ ++ a += G(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define HH(a,b,c,d,x,s,ac) \ ++ { \ ++ a += H(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++#define II(a,b,c,d,x,s,ac) \ ++ { \ ++ a += I(b,c,d) + x + ac; \ ++ a = ROTATE_LEFT(a,s); \ ++ a += b; \ ++ } ++void MD5Init(MD5_CTX *context); ++void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); ++void MD5Final(MD5_CTX *context,unsigned char digest[16]); ++void MD5Transform(unsigned int state[4],unsigned char block[64]); ++void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); ++void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h +new file mode 100644 +index 000000000000..568146624cee +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h +@@ -0,0 +1,148 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file reg_access.h ++ * ++ * @brief Definitions and macros for MAC HW and platform register accesses ++ * ++ * Copyright (C) RivieraWaves 2011-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef REG_ACCESS_H_ ++#define REG_ACCESS_H_ ++ ++/***************************************************************************** ++ * Addresses within RWNX_ADDR_SYSTEM ++ *****************************************************************************/ ++/* Shard RAM */ ++#define SHARED_RAM_START_ADDR 0x00000000 ++ ++/* IPC registers */ ++#define IPC_REG_BASE_ADDR 0x00800000 ++ ++/* System Controller Registers */ ++#define SYSCTRL_SIGNATURE_ADDR 0x00900000 ++// old diag register name ++#define SYSCTRL_DIAG_CONF_ADDR 0x00900068 ++#define SYSCTRL_PHYDIAG_CONF_ADDR 0x00900074 ++#define SYSCTRL_RIUDIAG_CONF_ADDR 0x00900078 ++// new diag register name ++#define SYSCTRL_DIAG_CONF0 0x00900064 ++#define SYSCTRL_DIAG_CONF1 0x00900068 ++#define SYSCTRL_DIAG_CONF2 0x00900074 ++#define SYSCTRL_DIAG_CONF3 0x00900078 ++#define SYSCTRL_MISC_CNTL_ADDR 0x009000E0 ++#define BOOTROM_ENABLE BIT(4) ++#define FPGA_B_RESET BIT(1) ++#define SOFT_RESET BIT(0) ++ ++/* MAC platform */ ++#define NXMAC_VERSION_1_ADDR 0x00B00004 ++#define NXMAC_MU_MIMO_TX_BIT BIT(19) ++#define NXMAC_BFMER_BIT BIT(18) ++#define NXMAC_BFMEE_BIT BIT(17) ++#define NXMAC_MAC_80211MH_FORMAT_BIT BIT(16) ++#define NXMAC_COEX_BIT BIT(14) ++#define NXMAC_WAPI_BIT BIT(13) ++#define NXMAC_TPC_BIT BIT(12) ++#define NXMAC_VHT_BIT BIT(11) ++#define NXMAC_HT_BIT BIT(10) ++#define NXMAC_RCE_BIT BIT(8) ++#define NXMAC_CCMP_BIT BIT(7) ++#define NXMAC_TKIP_BIT BIT(6) ++#define NXMAC_WEP_BIT BIT(5) ++#define NXMAC_SECURITY_BIT BIT(4) ++#define NXMAC_SME_BIT BIT(3) ++#define NXMAC_HCCA_BIT BIT(2) ++#define NXMAC_EDCA_BIT BIT(1) ++#define NXMAC_QOS_BIT BIT(0) ++ ++#define NXMAC_RX_CNTRL_ADDR 0x00B00060 ++#define NXMAC_EN_DUPLICATE_DETECTION_BIT BIT(31) ++#define NXMAC_ACCEPT_UNKNOWN_BIT BIT(30) ++#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT BIT(29) ++#define NXMAC_ACCEPT_QO_S_NULL_BIT BIT(28) ++#define NXMAC_ACCEPT_QCFWO_DATA_BIT BIT(27) ++#define NXMAC_ACCEPT_Q_DATA_BIT BIT(26) ++#define NXMAC_ACCEPT_CFWO_DATA_BIT BIT(25) ++#define NXMAC_ACCEPT_DATA_BIT BIT(24) ++#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT BIT(23) ++#define NXMAC_ACCEPT_CF_END_BIT BIT(22) ++#define NXMAC_ACCEPT_ACK_BIT BIT(21) ++#define NXMAC_ACCEPT_CTS_BIT BIT(20) ++#define NXMAC_ACCEPT_RTS_BIT BIT(19) ++#define NXMAC_ACCEPT_PS_POLL_BIT BIT(18) ++#define NXMAC_ACCEPT_BA_BIT BIT(17) ++#define NXMAC_ACCEPT_BAR_BIT BIT(16) ++#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT BIT(15) ++#define NXMAC_ACCEPT_BFMEE_FRAMES_BIT BIT(14) ++#define NXMAC_ACCEPT_ALL_BEACON_BIT BIT(13) ++#define NXMAC_ACCEPT_NOT_EXPECTED_BA_BIT BIT(12) ++#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_BIT BIT(11) ++#define NXMAC_ACCEPT_BEACON_BIT BIT(10) ++#define NXMAC_ACCEPT_PROBE_RESP_BIT BIT(9) ++#define NXMAC_ACCEPT_PROBE_REQ_BIT BIT(8) ++#define NXMAC_ACCEPT_MY_UNICAST_BIT BIT(7) ++#define NXMAC_ACCEPT_UNICAST_BIT BIT(6) ++#define NXMAC_ACCEPT_ERROR_FRAMES_BIT BIT(5) ++#define NXMAC_ACCEPT_OTHER_BSSID_BIT BIT(4) ++#define NXMAC_ACCEPT_BROADCAST_BIT BIT(3) ++#define NXMAC_ACCEPT_MULTICAST_BIT BIT(2) ++#define NXMAC_DONT_DECRYPT_BIT BIT(1) ++#define NXMAC_EXC_UNENCRYPTED_BIT BIT(0) ++ ++#define NXMAC_DEBUG_PORT_SEL_ADDR 0x00B00510 ++#define NXMAC_SW_SET_PROFILING_ADDR 0x00B08564 ++#define NXMAC_SW_CLEAR_PROFILING_ADDR 0x00B08568 ++ ++/* Modem Status */ ++#define MDM_HDMCONFIG_ADDR 0x00C00000 ++ ++/* Clock gating configuration */ ++#define MDM_MEMCLKCTRL0_ADDR 0x00C00848 ++#define MDM_CLKGATEFCTRL0_ADDR 0x00C00874 ++#define CRM_CLKGATEFCTRL0_ADDR 0x00940010 ++ ++/* AGC (trident) */ ++#define AGC_RWNXAGCCNTL_ADDR 0x00C02060 ++ ++/* LDPC RAM*/ ++#define PHY_LDPC_RAM_ADDR 0x00C09000 ++ ++/* FCU (elma )*/ ++#define FCU_RWNXFCAGCCNTL_ADDR 0x00C09034 ++ ++/* AGC RAM */ ++#define PHY_AGC_UCODE_ADDR 0x00C0A000 ++ ++/* RIU */ ++#define RIU_RWNXVERSION_ADDR 0x00C0B000 ++#define RIU_RWNXDYNAMICCONFIG_ADDR 0x00C0B008 ++#define RIU_AGCMEMBISTSTAT_ADDR 0x00C0B238 ++#define RIU_AGCMEMSIGNATURESTAT_ADDR 0x00C0B23C ++#define RIU_RWNXAGCCNTL_ADDR 0x00C0B390 ++ ++/* FCU RAM */ ++#define PHY_FCU_UCODE_ADDR 0x00C0E000 ++ ++/* RF ITF */ ++#define FPGAB_MPIF_SEL_ADDR 0x00C10030 ++#define RF_V6_DIAGPORT_CONF1_ADDR 0x00C10010 ++#define RF_v6_PHYDIAG_CONF1_ADDR 0x00C10018 ++ ++#define RF_V7_DIAGPORT_CONF1_ADDR 0x00F10010 ++#define RF_v7_PHYDIAG_CONF1_ADDR 0x00F10018 ++ ++/***************************************************************************** ++ * Macros for generated register files ++ *****************************************************************************/ ++/* Macros for IPC registers access (used in reg_ipc_app.h) */ ++#define REG_IPC_APP_RD(env, INDEX) \ ++ (*(volatile u32 *)((u8 *)env + IPC_REG_BASE_ADDR + 4 * (INDEX))) ++ ++#define REG_IPC_APP_WR(env, INDEX, value) \ ++ (*(volatile u32 *)((u8 *)env + IPC_REG_BASE_ADDR + 4 * (INDEX)) = value) ++ ++#endif /* REG_ACCESS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c +new file mode 100644 +index 000000000000..260a9d27468e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c +@@ -0,0 +1,2914 @@ ++#include ++#include ++#include ++ ++//#include "regdb.h" ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++#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_antenna_gain = DBI_TO_MBI(gain),\ ++ .power_rule.max_eirp = DBM_TO_MBM(eirp), \ ++ .flags = reg_flags, \ ++} ++#define NL80211_RRF_AUTO_BW 0 ++#endif ++ ++static const struct ieee80211_regdomain regdom_00 = { ++ .n_reg_rules = 2, ++ .alpha2 = "00", ++ .reg_rules = { ++ // 1...14 ++ REG_RULE(2390 - 10, 2510 + 10, 40, 0, 20, 0), ++ // 36...165 ++ REG_RULE(5150 - 10, 5970 + 10, 80, 0, 20, 0), ++ } ++ ++#if 0 ++ .alpha2 = "00", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 20, 0, 0), ++ //REG_RULE_EXT(2457, 2482, 40, 0, 20, 0, ++ // NL80211_RRF_NO_IR | 0), ++ REG_RULE_EXT(2474, 2494, 20, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_NO_OFDM | 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 20, 0, ++ NL80211_RRF_NO_IR | ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, ++ NL80211_RRF_NO_IR | 0), ++ }, ++ .n_reg_rules = 6 ++#endif ++}; ++ ++static const struct ieee80211_regdomain regdom_AD = { ++ .alpha2 = "AD", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5710, 80, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AE = { ++ .alpha2 = "AE", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ //REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AF = { ++ .alpha2 = "AF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AI = { ++ .alpha2 = "AI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AL = { ++ .alpha2 = "AL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AM = { ++ .alpha2 = "AM", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 18, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 18, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_AN = { ++ .alpha2 = "AN", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AR = { ++ .alpha2 = "AR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ //REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ // NL80211_RRF_AUTO_BW | 0), ++ //REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ // NL80211_RRF_DFS | ++ // NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5270, 5330, 40, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ //REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ // NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_AS = { ++ .alpha2 = "AS", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AT = { ++ .alpha2 = "AT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AU = { ++ .alpha2 = "AU", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_AW = { ++ .alpha2 = "AW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_AZ = { ++ .alpha2 = "AZ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 18, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 18, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_BA = { ++ .alpha2 = "BA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BB = { ++ .alpha2 = "BB", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BD = { ++ .alpha2 = "BD", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_BE = { ++ .alpha2 = "BE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BF = { ++ .alpha2 = "BF", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BG = { ++ .alpha2 = "BG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BH = { ++ .alpha2 = "BH", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BL = { ++ .alpha2 = "BL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BM = { ++ .alpha2 = "BM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BN = { ++ .alpha2 = "BN", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BO = { ++ .alpha2 = "BO", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_BR = { ++ .alpha2 = "BR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BS = { ++ .alpha2 = "BS", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_BT = { ++ .alpha2 = "BT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BY = { ++ .alpha2 = "BY", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_BZ = { ++ .alpha2 = "BZ", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_CA = { ++ .alpha2 = "CA", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CF = { ++ .alpha2 = "CF", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 40, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 40, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 40, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 40, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CH = { ++ .alpha2 = "CH", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CI = { ++ .alpha2 = "CI", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CL = { ++ .alpha2 = "CL", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_CN = { ++ .alpha2 = "CN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ REG_RULE_EXT(57240, 59400, 2160, 0, 28, 0, 0), ++ REG_RULE_EXT(59400, 63720, 2160, 0, 44, 0, 0), ++ REG_RULE_EXT(63720, 65880, 2160, 0, 28, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_CO = { ++ .alpha2 = "CO", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CR = { ++ .alpha2 = "CR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CX = { ++ .alpha2 = "CX", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CY = { ++ .alpha2 = "CY", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_CZ = { ++ .alpha2 = "CZ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5470, 5725, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_DE = { ++ .alpha2 = "DE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 20, 0, NL80211_RRF_AUTO_BW| ++ NL80211_RRF_NO_OUTDOOR| ++ 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, NL80211_RRF_AUTO_BW| ++ NL80211_RRF_DFS| ++ NL80211_RRF_NO_OUTDOOR| ++ 0), ++ REG_RULE_EXT(5470, 5725, 160, 0, 20, 0, NL80211_RRF_DFS| ++ 0), ++ REG_RULE_EXT(5725, 5875, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5945, 6425, 160, 0, 20, 0, NL80211_RRF_NO_OUTDOOR| ++ 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++ ++static const struct ieee80211_regdomain regdom_DK = { ++ .alpha2 = "DK", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_DM = { ++ .alpha2 = "DM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_DO = { ++ .alpha2 = "DO", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_DZ = { ++ .alpha2 = "DZ", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5670, 160, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_EC = { ++ .alpha2 = "EC", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_EE = { ++ .alpha2 = "EE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_EG = { ++ .alpha2 = "EG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_ES = { ++ .alpha2 = "ES", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5470, 5725, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_ET = { ++ .alpha2 = "ET", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_FI = { ++ .alpha2 = "FI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_FM = { ++ .alpha2 = "FM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_FR = { ++ .alpha2 = "FR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5695, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GB = { ++ .alpha2 = "GB", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GD = { ++ .alpha2 = "GD", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GE = { ++ .alpha2 = "GE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 18, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 18, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GF = { ++ .alpha2 = "GF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GH = { ++ .alpha2 = "GH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GL = { ++ .alpha2 = "GL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5710, 80, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GP = { ++ .alpha2 = "GP", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GR = { ++ .alpha2 = "GR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GT = { ++ .alpha2 = "GT", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_GU = { ++ .alpha2 = "GU", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_GY = { ++ .alpha2 = "GY", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_HK = { ++ .alpha2 = "HK", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HN = { ++ .alpha2 = "HN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HR = { ++ .alpha2 = "HR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HT = { ++ .alpha2 = "HT", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_HU = { ++ .alpha2 = "HU", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_ID = { ++ .alpha2 = "ID", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 23, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_IE = { ++ .alpha2 = "IE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_IL = { ++ .alpha2 = "IL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_IN = { ++ .alpha2 = "IN", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_IR = { ++ .alpha2 = "IR", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_IS = { ++ .alpha2 = "IS", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_IT = { ++ .alpha2 = "IT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_JM = { ++ .alpha2 = "JM", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_JO = { ++ .alpha2 = "JO", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 23, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_JP = { ++ .alpha2 = "JP", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(2474, 2494, 20, 0, 20, 0, ++ NL80211_RRF_NO_OFDM | 0), ++ REG_RULE_EXT(4910, 4990, 40, 0, 23, 0, 0), ++ REG_RULE_EXT(5030, 5090, 40, 0, 23, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_KE = { ++ .alpha2 = "KE", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, 0), ++ REG_RULE_EXT(5490, 5570, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5775, 40, 0, 23, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_KH = { ++ .alpha2 = "KH", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_KN = { ++ .alpha2 = "KN", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KP = { ++ .alpha2 = "KP", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5630, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KR = { ++ .alpha2 = "KR", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KW = { ++ .alpha2 = "KW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_KY = { ++ .alpha2 = "KY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_KZ = { ++ .alpha2 = "KZ", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 1 ++}; ++ ++static const struct ieee80211_regdomain regdom_LB = { ++ .alpha2 = "LB", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LC = { ++ .alpha2 = "LC", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5815, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LI = { ++ .alpha2 = "LI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_LK = { ++ .alpha2 = "LK", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LS = { ++ .alpha2 = "LS", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_LT = { ++ .alpha2 = "LT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LU = { ++ .alpha2 = "LU", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_LV = { ++ .alpha2 = "LV", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MA = { ++ .alpha2 = "MA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_MC = { ++ .alpha2 = "MC", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MD = { ++ .alpha2 = "MD", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_ME = { ++ .alpha2 = "ME", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MF = { ++ .alpha2 = "MF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MH = { ++ .alpha2 = "MH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MK = { ++ .alpha2 = "MK", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MN = { ++ .alpha2 = "MN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MO = { ++ .alpha2 = "MO", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 40, 0, 23, 0, 0), ++ REG_RULE_EXT(5250, 5330, 40, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 40, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MP = { ++ .alpha2 = "MP", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MQ = { ++ .alpha2 = "MQ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MR = { ++ .alpha2 = "MR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MT = { ++ .alpha2 = "MT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MU = { ++ .alpha2 = "MU", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MW = { ++ .alpha2 = "MW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_MX = { ++ .alpha2 = "MX", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_MY = { ++ .alpha2 = "MY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_NG = { ++ .alpha2 = "NG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, NL80211_RRF_DFS| ++ 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_NI = { ++ .alpha2 = "NI", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_NL = { ++ .alpha2 = "NL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_NO = { ++ .alpha2 = "NO", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5350, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5470, 5795, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5815, 5850, 35, 0, 33, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(17100, 17300, 200, 0, 20, 0, 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_NP = { ++ .alpha2 = "NP", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_NZ = { ++ .alpha2 = "NZ", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_OM = { ++ .alpha2 = "OM", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PA = { ++ .alpha2 = "PA", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PE = { ++ .alpha2 = "PE", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PF = { ++ .alpha2 = "PF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PG = { ++ .alpha2 = "PG", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PH = { ++ .alpha2 = "PH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PK = { ++ .alpha2 = "PK", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_PL = { ++ .alpha2 = "PL", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PM = { ++ .alpha2 = "PM", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_PR = { ++ .alpha2 = "PR", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PT = { ++ .alpha2 = "PT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PW = { ++ .alpha2 = "PW", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_PY = { ++ .alpha2 = "PY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_QA = { ++ .alpha2 = "QA", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 2 ++}; ++ ++static const struct ieee80211_regdomain regdom_RE = { ++ .alpha2 = "RE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_RO = { ++ .alpha2 = "RO", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_RS = { ++ .alpha2 = "RS", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5150, 5350, 40, 0, 23, 0, ++ NL80211_RRF_NO_OUTDOOR | 0), ++ REG_RULE_EXT(5470, 5725, 20, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_RU = { ++ .alpha2 = "RU", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5650, 5730, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_RW = { ++ .alpha2 = "RW", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SA = { ++ .alpha2 = "SA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_SE = { ++ .alpha2 = "SE", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SG = { ++ .alpha2 = "SG", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SI = { ++ .alpha2 = "SI", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SK = { ++ .alpha2 = "SK", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SN = { ++ .alpha2 = "SN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_SR = { ++ .alpha2 = "SR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_SV = { ++ .alpha2 = "SV", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_SY = { ++ .alpha2 = "SY", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 1 ++}; ++ ++static const struct ieee80211_regdomain regdom_TC = { ++ .alpha2 = "TC", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TD = { ++ .alpha2 = "TD", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_TG = { ++ .alpha2 = "TG", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5250, 5330, 40, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5710, 40, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_TH = { ++ .alpha2 = "TH", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TN = { ++ .alpha2 = "TN", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_TR = { ++ .alpha2 = "TR", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TT = { ++ .alpha2 = "TT", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_TW = { ++ .alpha2 = "TW", ++ .dfs_region = NL80211_DFS_JP, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5270, 5330, 40, 0, 17, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5590, 80, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5650, 5710, 40, 0, 30, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_UA = { ++ .alpha2 = "UA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2400, 2483, 40, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | 0), ++ REG_RULE_EXT(5150, 5350, 40, 0, 20, 0, ++ NL80211_RRF_NO_OUTDOOR | 0), ++ REG_RULE_EXT(5490, 5670, 80, 0, 20, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 20, 0, 0), ++ REG_RULE_EXT(57000, 66000, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_UG = { ++ .alpha2 = "UG", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_US = { ++ .alpha2 = "US", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ // 1...13 ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ // 36 40 44 48 ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ // 52 56 60 64 ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ // 100 104 108 112 116 120 124 ++ REG_RULE_EXT(5490, 5650, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ // 128 132 136 140 ++ REG_RULE_EXT(5650, 5710, 40, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ // 149 153 157 161 165 ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ REG_RULE_EXT(57240, 63720, 2160, 0, 40, 0, 0), ++ }, ++ .n_reg_rules = 7 ++}; ++ ++static const struct ieee80211_regdomain regdom_UY = { ++ .alpha2 = "UY", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_UZ = { ++ .alpha2 = "UZ", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ }, ++ .n_reg_rules = 3 ++}; ++ ++static const struct ieee80211_regdomain regdom_VC = { ++ .alpha2 = "VC", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_VE = { ++ .alpha2 = "VE", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 23, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 23, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_VI = { ++ .alpha2 = "VI", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2472, 40, 0, 30, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 24, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_VN = { ++ .alpha2 = "VN", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5490, 5730, 80, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_VU = { ++ .alpha2 = "VU", ++ .dfs_region = NL80211_DFS_FCC, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 17, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 24, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5730, 160, 0, 24, 0, ++ NL80211_RRF_DFS | 0), ++ REG_RULE_EXT(5735, 5835, 80, 0, 30, 0, 0), ++ }, ++ .n_reg_rules = 5 ++}; ++ ++static const struct ieee80211_regdomain regdom_WF = { ++ .alpha2 = "WF", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_YE = { ++ .alpha2 = "YE", ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ }, ++ .n_reg_rules = 1 ++}; ++ ++static const struct ieee80211_regdomain regdom_YT = { ++ .alpha2 = "YT", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_ZA = { ++ .alpha2 = "ZA", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5695, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ /*REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0),*/ ++ }, ++ .n_reg_rules = 4 ++}; ++ ++static const struct ieee80211_regdomain regdom_ZW = { ++ .alpha2 = "ZW", ++ .dfs_region = NL80211_DFS_ETSI, ++ .reg_rules = { ++ REG_RULE_EXT(2402, 2482, 40, 0, 20, 0, 0), ++ REG_RULE_EXT(5170, 5250, 80, 0, 20, 0, ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5250, 5330, 80, 0, 20, 0, ++ NL80211_RRF_DFS | ++ NL80211_RRF_AUTO_BW | 0), ++ REG_RULE_EXT(5490, 5710, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 0), ++ }, ++ .n_reg_rules = 4 ++}; ++ ++const struct ieee80211_regdomain *reg_regdb[] = { ++ ®dom_00, ++ ®dom_AD, ++ ®dom_AE, ++ ®dom_AF, ++ ®dom_AI, ++ ®dom_AL, ++ ®dom_AM, ++ ®dom_AN, ++ ®dom_AR, ++ ®dom_AS, ++ ®dom_AT, ++ ®dom_AU, ++ ®dom_AW, ++ ®dom_AZ, ++ ®dom_BA, ++ ®dom_BB, ++ ®dom_BD, ++ ®dom_BE, ++ ®dom_BF, ++ ®dom_BG, ++ ®dom_BH, ++ ®dom_BL, ++ ®dom_BM, ++ ®dom_BN, ++ ®dom_BO, ++ ®dom_BR, ++ ®dom_BS, ++ ®dom_BT, ++ ®dom_BY, ++ ®dom_BZ, ++ ®dom_CA, ++ ®dom_CF, ++ ®dom_CH, ++ ®dom_CI, ++ ®dom_CL, ++ ®dom_CN, ++ ®dom_CO, ++ ®dom_CR, ++ ®dom_CX, ++ ®dom_CY, ++ ®dom_CZ, ++ ®dom_DE, ++ ®dom_DK, ++ ®dom_DM, ++ ®dom_DO, ++ ®dom_DZ, ++ ®dom_EC, ++ ®dom_EE, ++ ®dom_EG, ++ ®dom_ES, ++ ®dom_ET, ++ ®dom_FI, ++ ®dom_FM, ++ ®dom_FR, ++ ®dom_GB, ++ ®dom_GD, ++ ®dom_GE, ++ ®dom_GF, ++ ®dom_GH, ++ ®dom_GL, ++ ®dom_GP, ++ ®dom_GR, ++ ®dom_GT, ++ ®dom_GU, ++ ®dom_GY, ++ ®dom_HK, ++ ®dom_HN, ++ ®dom_HR, ++ ®dom_HT, ++ ®dom_HU, ++ ®dom_ID, ++ ®dom_IE, ++ ®dom_IL, ++ ®dom_IN, ++ ®dom_IR, ++ ®dom_IS, ++ ®dom_IT, ++ ®dom_JM, ++ ®dom_JO, ++ ®dom_JP, ++ ®dom_KE, ++ ®dom_KH, ++ ®dom_KN, ++ ®dom_KP, ++ ®dom_KR, ++ ®dom_KW, ++ ®dom_KY, ++ ®dom_KZ, ++ ®dom_LB, ++ ®dom_LC, ++ ®dom_LI, ++ ®dom_LK, ++ ®dom_LS, ++ ®dom_LT, ++ ®dom_LU, ++ ®dom_LV, ++ ®dom_MA, ++ ®dom_MC, ++ ®dom_MD, ++ ®dom_ME, ++ ®dom_MF, ++ ®dom_MH, ++ ®dom_MK, ++ ®dom_MN, ++ ®dom_MO, ++ ®dom_MP, ++ ®dom_MQ, ++ ®dom_MR, ++ ®dom_MT, ++ ®dom_MU, ++ ®dom_MW, ++ ®dom_MX, ++ ®dom_MY, ++ ®dom_NG, ++ ®dom_NI, ++ ®dom_NL, ++ ®dom_NO, ++ ®dom_NP, ++ ®dom_NZ, ++ ®dom_OM, ++ ®dom_PA, ++ ®dom_PE, ++ ®dom_PF, ++ ®dom_PG, ++ ®dom_PH, ++ ®dom_PK, ++ ®dom_PL, ++ ®dom_PM, ++ ®dom_PR, ++ ®dom_PT, ++ ®dom_PW, ++ ®dom_PY, ++ ®dom_QA, ++ ®dom_RE, ++ ®dom_RO, ++ ®dom_RS, ++ ®dom_RU, ++ ®dom_RW, ++ ®dom_SA, ++ ®dom_SE, ++ ®dom_SG, ++ ®dom_SI, ++ ®dom_SK, ++ ®dom_SN, ++ ®dom_SR, ++ ®dom_SV, ++ ®dom_SY, ++ ®dom_TC, ++ ®dom_TD, ++ ®dom_TG, ++ ®dom_TH, ++ ®dom_TN, ++ ®dom_TR, ++ ®dom_TT, ++ ®dom_TW, ++ ®dom_UA, ++ ®dom_UG, ++ ®dom_US, ++ ®dom_UY, ++ ®dom_UZ, ++ ®dom_VC, ++ ®dom_VE, ++ ®dom_VI, ++ ®dom_VN, ++ ®dom_VU, ++ ®dom_WF, ++ ®dom_YE, ++ ®dom_YT, ++ ®dom_ZA, ++ ®dom_ZW, ++ NULL, ++}; ++ ++int reg_regdb_size = ARRAY_SIZE(reg_regdb); ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c +new file mode 100644 +index 000000000000..b39cf0f205a3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c +@@ -0,0 +1,105 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_bfmer.c ++ * ++ * @brief VHT Beamformer function definitions ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++/** ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++ ++#include ++#include "rwnx_bfmer.h" ++ ++/** ++ * FUNCTION DEFINITIONS ++ ****************************************************************************** ++ */ ++ ++int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ unsigned int length) ++{ ++ gfp_t flags; ++ struct rwnx_bfmer_report *bfm_report ; ++ ++ if (in_softirq()) ++ flags = GFP_ATOMIC; ++ else ++ flags = GFP_KERNEL; ++ ++ /* Allocate a structure that will contain the beamforming report */ ++ bfm_report = kmalloc(sizeof(*bfm_report) + length, flags); ++ ++ ++ /* Check report allocation */ ++ if (!bfm_report) { ++ /* Do not use beamforming */ ++ return -1; ++ } ++ ++ /* Store report length */ ++ bfm_report->length = length; ++ ++ /* ++ * Need to provide a Virtual Address to the MAC so that it can ++ * upload the received Beamforming Report in driver memory ++ */ ++ bfm_report->dma_addr = dma_map_single(rwnx_hw->dev, &bfm_report->report[0], ++ length, DMA_FROM_DEVICE); ++ ++ /* Check DMA mapping result */ ++ if (dma_mapping_error(rwnx_hw->dev, bfm_report->dma_addr)) { ++ /* Free allocated report */ ++ kfree(bfm_report); ++ /* And leave */ ++ return -1; ++ } ++ ++ /* Store report structure */ ++ rwnx_sta->bfm_report = bfm_report; ++ ++ return 0; ++} ++ ++void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) ++{ ++ /* Verify if a report has been allocated */ ++ if (rwnx_sta->bfm_report) { ++ struct rwnx_bfmer_report *bfm_report = rwnx_sta->bfm_report; ++ ++ /* Unmap DMA region */ ++ dma_unmap_single(rwnx_hw->dev, bfm_report->dma_addr, ++ bfm_report->length, DMA_BIDIRECTIONAL); ++ ++ /* Free allocated report structure and clean the pointer */ ++ kfree(bfm_report); ++ rwnx_sta->bfm_report = NULL; ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa) ++{ ++ int i; ++ u8 rx_nss = 0; ++ u16 rx_mcs_map = le16_to_cpu(vht_capa->supp_mcs.rx_mcs_map); ++ ++ for (i = 7; i >= 0; i--) { ++ u8 mcs = (rx_mcs_map >> (2 * i)) & 3; ++ ++ if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) { ++ rx_nss = i + 1; ++ break; ++ } ++ } ++ ++ return rx_nss; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h +new file mode 100644 +index 000000000000..4ce16496ef2e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h +@@ -0,0 +1,100 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_bfmer.h ++ * ++ * @brief VHT Beamformer function declarations ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_BFMER_H_ ++#define _RWNX_BFMER_H_ ++ ++/** ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++ ++/** ++ * DEFINES ++ ****************************************************************************** ++ */ ++ ++/// Maximal supported report length (in bytes) ++#define RWNX_BFMER_REPORT_MAX_LEN 2048 ++ ++/// Size of the allocated report space (twice the maximum report length) ++#define RWNX_BFMER_REPORT_SPACE_SIZE (RWNX_BFMER_REPORT_MAX_LEN * 2) ++ ++/** ++ * TYPE DEFINITIONS ++ ****************************************************************************** ++ */ ++ ++/* ++ * Structure used to store a beamforming report. ++ */ ++struct rwnx_bfmer_report { ++ dma_addr_t dma_addr; /* Virtual address provided to MAC for ++ DMA transfer of the Beamforming Report */ ++ unsigned int length; /* Report Length */ ++ u8 report[1]; /* Report to be used for VHT TX Beamforming */ ++}; ++ ++/** ++ * FUNCTION DECLARATIONS ++ ****************************************************************************** ++ */ ++ ++/** ++ ****************************************************************************** ++ * @brief Allocate memory aiming to contains the Beamforming Report received ++ * from a Beamformee capable capable. ++ * The providing length shall be large enough to contain the VHT Compressed ++ * Beaforming Report and the MU Exclusive part. ++ * It also perform a DMA Mapping providing an address to be provided to the HW ++ * responsible for the DMA transfer of the report. ++ * If successful a struct rwnx_bfmer_report object is allocated, it's address ++ * is stored in rwnx_sta->bfm_report. ++ * ++ * @param[in] rwnx_hw PHY Information ++ * @param[in] rwnx_sta Peer STA Information ++ * @param[in] length Memory size to be allocated ++ * ++ * @return 0 if operation is successful, else -1. ++ ****************************************************************************** ++ */ ++int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ unsigned int length); ++ ++/** ++ ****************************************************************************** ++ * @brief Free a previously allocated memory intended to be used for ++ * Beamforming Reports. ++ * ++ * @param[in] rwnx_hw PHY Information ++ * @param[in] rwnx_sta Peer STA Information ++ * ++ ****************************************************************************** ++ */ ++void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/** ++ ****************************************************************************** ++ * @brief Parse a Rx VHT-MCS map in order to deduce the maximum number of ++ * Spatial Streams supported by a beamformee. ++ * ++ * @param[in] vht_capa Received VHT Capability field. ++ * ++ ****************************************************************************** ++ */ ++u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#endif /* _RWNX_BFMER_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c +new file mode 100644 +index 000000000000..39a5a251482a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c +@@ -0,0 +1,239 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_configparse.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_cfgfile.h" ++ ++/** ++ * ++ */ ++static const char *rwnx_find_tag(const u8 *file_data, unsigned int file_size, ++ const char *tag_name, unsigned int tag_len) ++{ ++ unsigned int curr, line_start = 0, line_size; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Walk through all the lines of the configuration file */ ++ while (line_start < file_size) { ++ /* Search the end of the current line (or the end of the file) */ ++ for (curr = line_start; curr < file_size; curr++) ++ if (file_data[curr] == '\n') ++ break; ++ ++ /* Compute the line size */ ++ line_size = curr - line_start; ++ ++ /* Check if this line contains the expected tag */ ++ if ((line_size == (strlen(tag_name) + tag_len)) && ++ (!strncmp(&file_data[line_start], tag_name, strlen(tag_name)))) ++ return &file_data[line_start + strlen(tag_name)]; ++ ++ /* Move to next line */ ++ line_start = curr + 1; ++ } ++ ++ /* Tag not found */ ++ return NULL; ++} ++ ++/** ++ * Parse the Config file used at init time ++ */ ++int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_conf_file *config) ++{ ++ const struct firmware *config_fw; ++ u8 dflt_mac[ETH_ALEN] = { 0, 111, 111, 111, 111, 0 }; ++ int ret; ++ const u8 *tag_ptr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ret = request_firmware(&config_fw, filename, rwnx_hw->dev); ++ if (ret) { ++ printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); ++ return ret; ++ } ++ ++ /* Get MAC Address */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "MAC_ADDR=", strlen("00:00:00:00:00:00")); ++ if (tag_ptr != NULL) { ++ u8 *addr = config->mac_addr; ++ if (sscanf(tag_ptr, ++ "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ addr + 0, addr + 1, addr + 2, ++ addr + 3, addr + 4, addr + 5) != ETH_ALEN) ++ memcpy(config->mac_addr, dflt_mac, ETH_ALEN); ++ } else ++ memcpy(config->mac_addr, dflt_mac, ETH_ALEN); ++ ++ RWNX_DBG("MAC Address is:\n%pM\n", config->mac_addr); ++ ++ /* Release the configuration file */ ++ release_firmware(config_fw); ++ ++ return 0; ++} ++ ++/** ++ * Parse the Config file used at init time ++ */ ++int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_phy_conf_file *config, int path) ++{ ++ const struct firmware *config_fw; ++ int ret; ++ const u8 *tag_ptr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ret = request_firmware(&config_fw, filename, rwnx_hw->dev); ++ if (ret) { ++ printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); ++ return ret; ++ } ++ ++ /* Get Trident path mapping */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "TRD_PATH_MAPPING=", strlen("00")); ++ if (tag_ptr != NULL) { ++ u8 val; ++ if (sscanf(tag_ptr, "%hhx", &val) == 1) ++ config->trd.path_mapping = val; ++ else ++ config->trd.path_mapping = path; ++ } else ++ config->trd.path_mapping = path; ++ ++ RWNX_DBG("Trident path mapping is: %d\n", config->trd.path_mapping); ++ ++ /* Get DC offset compensation */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "TX_DC_OFF_COMP=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->trd.tx_dc_off_comp) != 1) ++ config->trd.tx_dc_off_comp = 0; ++ } else ++ config->trd.tx_dc_off_comp = 0; ++ ++ RWNX_DBG("TX DC offset compensation is: %08X\n", config->trd.tx_dc_off_comp); ++ ++ /* Get Karst TX IQ compensation value for path0 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[0]) != 1) ++ config->karst.tx_iq_comp_2_4G[0] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_2_4G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[0]); ++ ++ /* Get Karst TX IQ compensation value for path1 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[1]) != 1) ++ config->karst.tx_iq_comp_2_4G[1] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_2_4G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[1]); ++ ++ /* Get Karst RX IQ compensation value for path0 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[0]) != 1) ++ config->karst.rx_iq_comp_2_4G[0] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_2_4G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[0]); ++ ++ /* Get Karst RX IQ compensation value for path1 on 2.4GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[1]) != 1) ++ config->karst.rx_iq_comp_2_4G[1] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_2_4G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[1]); ++ ++ /* Get Karst TX IQ compensation value for path0 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_5G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[0]) != 1) ++ config->karst.tx_iq_comp_5G[0] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_5G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[0]); ++ ++ /* Get Karst TX IQ compensation value for path1 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_TX_IQ_COMP_5G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[1]) != 1) ++ config->karst.tx_iq_comp_5G[1] = 0x01000000; ++ } else ++ config->karst.tx_iq_comp_5G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst TX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[1]); ++ ++ /* Get Karst RX IQ compensation value for path0 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_5G_PATH_0=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[0]) != 1) ++ config->karst.rx_iq_comp_5G[0] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_5G[0] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[0]); ++ ++ /* Get Karst RX IQ compensation value for path1 on 5GHz */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_RX_IQ_COMP_5G_PATH_1=", strlen("00000000")); ++ if (tag_ptr != NULL) { ++ if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[1]) != 1) ++ config->karst.rx_iq_comp_5G[1] = 0x01000000; ++ } else ++ config->karst.rx_iq_comp_5G[1] = 0x01000000; ++ ++ RWNX_DBG("Karst RX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[1]); ++ ++ /* Get Karst default path */ ++ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, ++ "KARST_DEFAULT_PATH=", strlen("00")); ++ if (tag_ptr != NULL) { ++ u8 val; ++ if (sscanf(tag_ptr, "%hhx", &val) == 1) ++ config->karst.path_used = val; ++ else ++ config->karst.path_used = path; ++ } else ++ config->karst.path_used = path; ++ ++ RWNX_DBG("Karst default path is: %d\n", config->karst.path_used); ++ ++ /* Release the configuration file */ ++ release_firmware(config_fw); ++ ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h +new file mode 100644 +index 000000000000..7dc96fe5862b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h +@@ -0,0 +1,35 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_cfgfile.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_CFGFILE_H_ ++#define _RWNX_CFGFILE_H_ ++ ++/* ++ * Structure used to retrieve information from the Config file used at Initialization time ++ */ ++struct rwnx_conf_file { ++ u8 mac_addr[ETH_ALEN]; ++}; ++ ++/* ++ * Structure used to retrieve information from the PHY Config file used at Initialization time ++ */ ++struct rwnx_phy_conf_file { ++ struct phy_trd_cfg_tag trd; ++ struct phy_karst_cfg_tag karst; ++}; ++ ++int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_conf_file *config); ++ ++int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, ++ struct rwnx_phy_conf_file *config, int path); ++ ++#endif /* _RWNX_CFGFILE_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c +new file mode 100644 +index 000000000000..cdbe42c3f14c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c +@@ -0,0 +1,586 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.c ++ * ++ * Handles queueing (push to IPC, ack/cfm from IPC) of commands issued to ++ * LMAC FW ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++ ++#include "rwnx_cmds.h" ++#include "rwnx_defs.h" ++#include "rwnx_strs.h" ++//#define CREATE_TRACE_POINTS ++#include "rwnx_events.h" ++#include "aicwf_txrxif.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#else ++#include "aicwf_usb.h" ++#endif ++/** ++ * ++ */ ++extern int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); ++ ++void rwnx_cmd_free(struct rwnx_cmd *cmd); ++ ++static void cmd_dump(const struct rwnx_cmd *cmd) ++{ ++ printk(KERN_CRIT "tkn[%d] flags:%04x result:%3d cmd:%4d-%-24s - reqcfm(%4d-%-s)\n", ++ cmd->tkn, cmd->flags, cmd->result, cmd->id, RWNX_ID2STR(cmd->id), ++ cmd->reqid, cmd->reqid != (lmac_msg_id_t)-1 ? RWNX_ID2STR(cmd->reqid) : "none"); ++} ++ ++/** ++ * ++ */ ++static void cmd_complete(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ lockdep_assert_held(&cmd_mgr->lock); ++ ++ //list_del(&cmd->list); ++ //cmd_mgr->queue_sz--; ++ ++ cmd->flags |= RWNX_CMD_FLAG_DONE; ++ if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) { ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ } else { ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) { ++ cmd->result = 0; ++ complete(&cmd->complete); ++ } ++ } ++} ++ ++int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ bool defer_push = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef CREATE_TRACE_POINTS ++ trace_msg_send(cmd->id); ++#endif ++ spin_lock_bh(&cmd_mgr->lock); ++ ++ if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { ++ printk(KERN_CRIT"cmd queue crashed\n"); ++ cmd->result = -EPIPE; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EPIPE; ++ } ++ ++ #ifndef CONFIG_RWNX_FHOST ++ if (!list_empty(&cmd_mgr->cmds)) { ++ if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) { ++ printk(KERN_CRIT"Too many cmds (%d) already queued\n", ++ cmd_mgr->max_queue_sz); ++ cmd->result = -ENOMEM; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -ENOMEM; ++ } ++ } ++ #endif ++ ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ defer_push = true; ++ ++ if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM) ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM; ++ ++ cmd->tkn = cmd_mgr->next_tkn++; ++ cmd->result = -EINTR; ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ init_completion(&cmd->complete); ++ ++ list_add_tail(&cmd->list, &cmd_mgr->cmds); ++ cmd_mgr->queue_sz++; ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ WAKE_CMD_WORK(cmd_mgr); ++ return 0; ++} ++ ++#if 1 ++static void aic8800_start_system_reset_flow(struct aic_sdio_dev *aic) ++{ ++ int ret = 0; ++ char *event_string = "DHDISDOWN=1"; ++ char *envp[] = { event_string, NULL }; ++ printk(KERN_ERR "wlan error reset flow.\n"); ++ printk(KERN_ERR "send event.\n"); ++ ret=kobject_uevent_env(&aic->dev->kobj, KOBJ_CHANGE,envp); ++ if(!ret) ++ printk(KERN_ERR "wlan error event send.\n"); ++} ++#endif ++ ++static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ int ret; ++ struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); ++#endif ++ bool defer_push = false; ++ u8_l empty = 0; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef CREATE_TRACE_POINTS ++ trace_msg_send(cmd->id); ++#endif ++ if(cmd->e2a_msg != NULL) { ++ do { ++ if(cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) ++ break; ++ spin_lock_bh(&cmd_mgr->lock); ++ empty = list_empty(&cmd_mgr->cmds); ++ if(!empty) { ++ spin_unlock_bh(&cmd_mgr->lock); ++ if(in_softirq()) { ++ printk("in_softirq:check cmdqueue empty\n"); ++ mdelay(10); ++ } else { ++ printk("check cmdqueue empty\n"); ++ msleep(50); ++ } ++ } ++ } while(!empty);//wait for cmd queue empty ++ } else { ++ spin_lock_bh(&cmd_mgr->lock); ++ } ++ ++ if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { ++ printk(KERN_CRIT"cmd queue crashed\n"); ++ cmd->result = -EPIPE; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EPIPE; ++ } ++ ++ #ifndef CONFIG_RWNX_FHOST ++ if (!list_empty(&cmd_mgr->cmds)) { ++ struct rwnx_cmd *last; ++ ++ if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) { ++ printk(KERN_CRIT"Too many cmds (%d) already queued\n", ++ cmd_mgr->max_queue_sz); ++ cmd->result = -ENOMEM; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -ENOMEM; ++ } ++ last = list_entry(cmd_mgr->cmds.prev, struct rwnx_cmd, list); ++ if (last->flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_PUSH | RWNX_CMD_FLAG_WAIT_CFM)) { ++#if 0 // queue even NONBLOCK command. ++ if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) { ++ printk(KERN_CRIT"cmd queue busy\n"); ++ cmd->result = -EBUSY; ++ spin_unlock_bh(&cmd_mgr->lock); ++ return -EBUSY; ++ } ++#endif ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ defer_push = true; ++ } ++ } ++ #endif ++ ++#if 0 ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_ACK; ++#endif ++ if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM) ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM; ++ ++ cmd->tkn = cmd_mgr->next_tkn++; ++ cmd->result = -EINTR; ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ init_completion(&cmd->complete); ++ ++ list_add_tail(&cmd->list, &cmd_mgr->cmds); ++ cmd_mgr->queue_sz++; ++ ++ if (cmd->a2e_msg->id == ME_TRAFFIC_IND_REQ ++ #ifdef AICWF_ARP_OFFLOAD ++ || cmd->a2e_msg->id == MM_SET_ARPOFFLOAD_REQ ++ #endif ++ ) { ++ defer_push = true; ++ cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH; ++ //printk("defer push: tkn=%d\r\n", cmd->tkn); ++ } ++ ++ spin_unlock_bh(&cmd_mgr->lock); ++ if (!defer_push) { ++ //printk("queue:id=%x, param_len=%u\n",cmd->a2e_msg->id, cmd->a2e_msg->param_len); ++ #ifdef AICWF_SDIO_SUPPORT ++ aicwf_set_cmd_tx((void *)(sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ #else ++ aicwf_set_cmd_tx((void *)(usbdev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++ #endif ++ //rwnx_ipc_msg_push(rwnx_hw, cmd, RWNX_CMD_A2EMSG_LEN(cmd->a2e_msg)); ++ ++ kfree(cmd->a2e_msg); ++ } else { ++ if(cmd_mgr->queue_sz <= 1){ ++ WAKE_CMD_WORK(cmd_mgr); ++ } ++ return 0; ++ } ++ ++ if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) { ++ #ifdef CONFIG_RWNX_FHOST ++ if (wait_for_completion_killable(&cmd->complete)) { ++ cmd->result = -EINTR; ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_complete(cmd_mgr, cmd); ++ spin_unlock_bh(&cmd_mgr->lock); ++ /* TODO: kill the cmd at fw level */ ++ } ++ #else ++ unsigned long tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz); ++ if (!wait_for_completion_timeout(&cmd->complete, tout)) { ++ printk(KERN_CRIT"cmd timed-out\n"); ++ #ifdef AICWF_SDIO_SUPPORT ++ ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++ #endif ++ ++ aic8800_start_system_reset_flow(sdiodev); ++ ++ cmd_dump(cmd); ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED; ++ if (!(cmd->flags & RWNX_CMD_FLAG_DONE)) { ++ cmd->result = -ETIMEDOUT; ++ cmd_complete(cmd_mgr, cmd); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ } else { ++ spin_lock_bh(&cmd_mgr->lock); ++ list_del(&cmd->list); ++ cmd_mgr->queue_sz--; ++ spin_unlock_bh(&cmd_mgr->lock); ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ if (!list_empty(&cmd_mgr->cmds)) ++ WAKE_CMD_WORK(cmd_mgr); ++ } ++ #endif ++ } else { ++ cmd->result = 0; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ++ */ ++static int cmd_mgr_llind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) ++{ ++ struct rwnx_cmd *cur, *acked = NULL, *next = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ if (!acked) { ++ if (cur->tkn == cmd->tkn) { ++ if (WARN_ON_ONCE(cur != cmd)) { ++ cmd_dump(cmd); ++ } ++ acked = cur; ++ continue; ++ } ++ } ++ if (cur->flags & RWNX_CMD_FLAG_WAIT_PUSH) { ++ next = cur; ++ break; ++ } ++ } ++ if (!acked) { ++ printk(KERN_CRIT "Error: acked cmd not found\n"); ++ } else { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) ++ cmd_complete(cmd_mgr, cmd); ++ } ++ ++ if (next) { ++ #if 0 //there is no ack ++ struct rwnx_hw *rwnx_hw = container_of(cmd_mgr, struct rwnx_hw, cmd_mgr); ++ next->flags &= ~RWNX_CMD_FLAG_WAIT_PUSH; ++ rwnx_ipc_msg_push(rwnx_hw, next, RWNX_CMD_A2EMSG_LEN(next->a2e_msg)); ++ kfree(next->a2e_msg); ++ #endif ++ } ++ spin_unlock(&cmd_mgr->lock); ++ ++ return 0; ++} ++ ++void cmd_mgr_task_process(struct work_struct *work) ++{ ++ struct rwnx_cmd_mgr *cmd_mgr = container_of(work, struct rwnx_cmd_mgr, cmdWork); ++ struct rwnx_cmd *cur, *next = NULL; ++ unsigned long tout; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ while (1) { ++ next = NULL; ++ spin_lock_bh(&cmd_mgr->lock); ++ ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ if (cur->flags & RWNX_CMD_FLAG_WAIT_PUSH) { //just judge the first ++ next = cur; ++ } ++ break; ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ if (next == NULL) ++ break; ++ ++ if (next) { ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); ++#endif ++ next->flags &= ~RWNX_CMD_FLAG_WAIT_PUSH; ++ ++ //printk("cmd_process, cmd->id=%d, tkn=%d\r\n",next->reqid, next->tkn); ++ //rwnx_ipc_msg_push(rwnx_hw, next, RWNX_CMD_A2EMSG_LEN(next->a2e_msg)); ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_set_cmd_tx((void *)(sdiodev), next->a2e_msg, sizeof(struct lmac_msg) + next->a2e_msg->param_len); ++#else ++ aicwf_set_cmd_tx((void *)(usbdev), next->a2e_msg, sizeof(struct lmac_msg) + next->a2e_msg->param_len); ++#endif ++ kfree(next->a2e_msg); ++ ++ tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz); ++ if (!wait_for_completion_timeout(&next->complete, tout)) { ++ printk(KERN_CRIT"cmd timed-out\n"); ++#ifdef AICWF_SDIO_SUPPORT ++ if (aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.wakeup_reg, 2) < 0) { ++ sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.wakeup_reg); ++ } ++#endif ++ aic8800_start_system_reset_flow(sdiodev); ++ ++ cmd_dump(next); ++ spin_lock_bh(&cmd_mgr->lock); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED; ++ if (!(next->flags & RWNX_CMD_FLAG_DONE)) { ++ next->result = -ETIMEDOUT; ++ cmd_complete(cmd_mgr, next); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ } else { ++ spin_lock_bh(&cmd_mgr->lock); ++ list_del(&next->list); ++ cmd_mgr->queue_sz--; ++ spin_unlock_bh(&cmd_mgr->lock); ++ rwnx_cmd_free(next);//kfree(next); ++ } ++ } ++ } ++ ++} ++ ++ ++static int cmd_mgr_run_callback(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd, ++ struct rwnx_cmd_e2amsg *msg, msg_cb_fct cb) ++{ ++ int res; ++ ++ if (!cb) { ++ return 0; ++ } ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ //spin_lock_bh(&rwnx_hw->cb_lock); ++ res = cb(rwnx_hw, cmd, msg); ++ //spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ return res; ++} ++ ++/** ++ * ++ ++ */ ++static int cmd_mgr_msgind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd_e2amsg *msg, ++ msg_cb_fct cb) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); ++ struct rwnx_hw *rwnx_hw = sdiodev->rwnx_hw; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); ++ struct rwnx_hw *rwnx_hw = usbdev->rwnx_hw; ++#endif ++ struct rwnx_cmd *cmd, *pos; ++ bool found = false; ++ ++ // RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef CREATE_TRACE_POINTS ++ trace_msg_recv(msg->id); ++#endif ++ //printk("cmd->id=%x\n", msg->id); ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry_safe(cmd, pos, &cmd_mgr->cmds, list) { ++ if (cmd->reqid == msg->id && ++ (cmd->flags & RWNX_CMD_FLAG_WAIT_CFM)) { ++ ++ if (!cmd_mgr_run_callback(rwnx_hw, cmd, msg, cb)) { ++ found = true; ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_CFM; ++ ++ if (WARN((msg->param_len > RWNX_CMD_E2AMSG_LEN_MAX), ++ "Unexpect E2A msg len %d > %d\n", msg->param_len, ++ RWNX_CMD_E2AMSG_LEN_MAX)) { ++ msg->param_len = RWNX_CMD_E2AMSG_LEN_MAX; ++ } ++ ++ if (cmd->e2a_msg && msg->param_len) ++ memcpy(cmd->e2a_msg, &msg->param, msg->param_len); ++ ++ if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) ++ cmd_complete(cmd_mgr, cmd); ++ ++ break; ++ } ++ } ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++ ++ if (!found) ++ cmd_mgr_run_callback(rwnx_hw, NULL, msg, cb); ++ ++ return 0; ++} ++ ++/** ++ * ++ */ ++static void cmd_mgr_print(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur; ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ RWNX_DBG("q_sz/max: %2d / %2d - next tkn: %d\n", ++ cmd_mgr->queue_sz, cmd_mgr->max_queue_sz, ++ cmd_mgr->next_tkn); ++ list_for_each_entry(cur, &cmd_mgr->cmds, list) { ++ cmd_dump(cur); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++static void cmd_mgr_drain(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ struct rwnx_cmd *cur, *nxt; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ spin_lock_bh(&cmd_mgr->lock); ++ list_for_each_entry_safe(cur, nxt, &cmd_mgr->cmds, list) { ++ list_del(&cur->list); ++ cmd_mgr->queue_sz--; ++ if (!(cur->flags & RWNX_CMD_FLAG_NONBLOCK)) ++ complete(&cur->complete); ++ } ++ spin_unlock_bh(&cmd_mgr->lock); ++} ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ INIT_LIST_HEAD(&cmd_mgr->cmds); ++ cmd_mgr->state = RWNX_CMD_MGR_STATE_INITED; ++ spin_lock_init(&cmd_mgr->lock); ++ cmd_mgr->max_queue_sz = RWNX_CMD_MAX_QUEUED; ++ cmd_mgr->queue = &cmd_mgr_queue; ++ cmd_mgr->print = &cmd_mgr_print; ++ cmd_mgr->drain = &cmd_mgr_drain; ++ cmd_mgr->llind = &cmd_mgr_llind; ++ cmd_mgr->msgind = &cmd_mgr_msgind; ++ ++ INIT_WORK(&cmd_mgr->cmdWork, cmd_mgr_task_process); ++ cmd_mgr->cmd_wq = create_singlethread_workqueue("cmd_wq"); ++ if (!cmd_mgr->cmd_wq) { ++ txrx_err("insufficient memory to create cmd workqueue.\n"); ++ return; ++ } ++} ++ ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr) ++{ ++ cmd_mgr->print(cmd_mgr); ++ cmd_mgr->drain(cmd_mgr); ++ cmd_mgr->print(cmd_mgr); ++ flush_workqueue(cmd_mgr->cmd_wq); ++ destroy_workqueue(cmd_mgr->cmd_wq); ++ memset(cmd_mgr, 0, sizeof(*cmd_mgr)); ++} ++ ++void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len) ++{ ++ u8 *buffer = NULL; ++ u16 index = 0; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; ++ struct aicwf_bus *bus = sdiodev->bus_if; ++#else ++ struct aic_usb_dev *usbdev = (struct aic_usb_dev *)dev; ++ struct aicwf_bus *bus = NULL; ++ if (!usbdev->state) { ++ printk("down msg \n"); ++ return; ++ } ++ bus = usbdev->bus_if; ++#endif ++ buffer = bus->cmd_buf; ++ ++ memset(buffer, 0, CMD_BUF_MAX); ++ buffer[0] = (len+4) & 0x00ff; ++ buffer[1] = ((len+4) >> 8) &0x0f; ++ buffer[2] = 0x11; ++ if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ buffer[3] = 0x0; ++ else if (sdiodev->chipid == PRODUCT_ID_AIC8800D80 || sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ buffer[3] = crc8_ponl_107(&buffer[0], 3); // crc8 ++ index += 4; ++ //there is a dummy word ++ index += 4; ++ ++ //make sure little endian ++ put_u16(&buffer[index], msg->id); ++ index += 2; ++ put_u16(&buffer[index], msg->dest_id); ++ index += 2; ++ put_u16(&buffer[index], msg->src_id); ++ index += 2; ++ put_u16(&buffer[index], msg->param_len); ++ index += 2; ++ memcpy(&buffer[index], (u8 *)msg->param, msg->param_len); ++ ++ aicwf_bus_txmsg(bus, buffer, len + 8); ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h +new file mode 100644 +index 000000000000..d1ba11994193 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h +@@ -0,0 +1,124 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_cmds.h ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_CMDS_H_ ++#define _RWNX_CMDS_H_ ++ ++#include ++#include ++#include ++#include "lmac_msg.h" ++ ++#ifdef CONFIG_RWNX_SDM ++#define RWNX_80211_CMD_TIMEOUT_MS (20 * 300) ++#elif defined(CONFIG_RWNX_FHOST) ++#define RWNX_80211_CMD_TIMEOUT_MS (10000) ++#else ++#ifdef AICWF_USB_SUPPORT ++#define RWNX_80211_CMD_TIMEOUT_MS 2000//300 ++#else ++#define RWNX_80211_CMD_TIMEOUT_MS 6000//500//300 ++#endif ++#endif ++ ++#define RWNX_CMD_FLAG_NONBLOCK BIT(0) ++#define RWNX_CMD_FLAG_REQ_CFM BIT(1) ++#define RWNX_CMD_FLAG_WAIT_PUSH BIT(2) ++#define RWNX_CMD_FLAG_WAIT_ACK BIT(3) ++#define RWNX_CMD_FLAG_WAIT_CFM BIT(4) ++#define RWNX_CMD_FLAG_DONE BIT(5) ++/* ATM IPC design makes it possible to get the CFM before the ACK, ++ * otherwise this could have simply been a state enum */ ++#define RWNX_CMD_WAIT_COMPLETE(flags) \ ++ (!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM))) ++ ++#define RWNX_CMD_MAX_QUEUED 16 ++ ++#ifdef CONFIG_RWNX_FHOST ++#include "ipc_fhost.h" ++#define rwnx_cmd_e2amsg ipc_fhost_msg ++#define rwnx_cmd_a2emsg ipc_fhost_msg ++#define RWNX_CMD_A2EMSG_LEN(m) (m->param_len) ++#define RWNX_CMD_E2AMSG_LEN_MAX IPC_FHOST_MSG_BUF_SIZE ++struct rwnx_term_stream; ++ ++#else /* !CONFIG_RWNX_FHOST*/ ++#include "ipc_shared.h" ++#define rwnx_cmd_e2amsg ipc_e2a_msg ++#define rwnx_cmd_a2emsg lmac_msg ++#define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len) ++#define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4) ++ ++#endif /* CONFIG_RWNX_FHOST*/ ++ ++struct rwnx_hw; ++struct rwnx_cmd; ++typedef int (*msg_cb_fct)(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd, ++ struct rwnx_cmd_e2amsg *msg); ++static inline void put_u16(u8 *buf, u16 data) ++{ ++ buf[0] = (u8)(data&0x00ff); ++ buf[1] = (u8)((data >> 8)&0x00ff); ++} ++ ++enum rwnx_cmd_mgr_state { ++ RWNX_CMD_MGR_STATE_DEINIT, ++ RWNX_CMD_MGR_STATE_INITED, ++ RWNX_CMD_MGR_STATE_CRASHED, ++}; ++ ++struct rwnx_cmd { ++ struct list_head list; ++ lmac_msg_id_t id; ++ lmac_msg_id_t reqid; ++ struct rwnx_cmd_a2emsg *a2e_msg; ++ char *e2a_msg; ++ u32 tkn; ++ u16 flags; ++ ++ struct completion complete; ++ u32 result; ++ u8 used; ++ int array_id; ++ #ifdef CONFIG_RWNX_FHOST ++ struct rwnx_term_stream *stream; ++ #endif ++}; ++ ++struct rwnx_cmd_mgr { ++ enum rwnx_cmd_mgr_state state; ++ spinlock_t lock; ++ u32 next_tkn; ++ u32 queue_sz; ++ u32 max_queue_sz; ++ ++ struct list_head cmds; ++ ++ int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *); ++ int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct); ++ void (*print)(struct rwnx_cmd_mgr *); ++ void (*drain)(struct rwnx_cmd_mgr *); ++ ++ struct work_struct cmdWork; ++ struct workqueue_struct *cmd_wq; ++}; ++ ++#define WAKE_CMD_WORK(cmd_mgr) \ ++ do { \ ++ queue_work((cmd_mgr)->cmd_wq, &cmd_mgr->cmdWork); \ ++ } while (0) ++ ++void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr); ++void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr); ++int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd); ++void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len); ++ ++#endif /* _RWNX_CMDS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h +new file mode 100644 +index 000000000000..49f5cdd032a2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h +@@ -0,0 +1,448 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_compat.h ++ * ++ * Ensure driver compilation for linux 3.16 to 3.19 ++ * ++ * To avoid too many #if LINUX_VERSION_CODE if the code, when prototype change ++ * between different kernel version: ++ * - For external function, define a macro whose name is the function name with ++ * _compat suffix and prototype (actually the number of parameter) of the ++ * latest version. Then latest version this macro simply call the function ++ * and for older kernel version it call the function adapting the api. ++ * - For internal function (e.g. cfg80211_ops) do the same but the macro name ++ * doesn't need to have the _compat suffix when the function is not used ++ * directly by the driver ++ * ++ * Copyright (C) RivieraWaves 2018 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_COMPAT_H_ ++#define _RWNX_COMPAT_H_ ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) ++#error "Minimum kernel version supported is 3.10" ++#endif ++ ++/* Generic */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) ++#define __bf_shf(x) (__builtin_ffsll(x) - 1) ++#define FIELD_PREP(_mask, _val) \ ++ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) ++#else ++#include ++#endif ++ ++/* CFG80211 */ ++ ++//because android kernel 5.15 uses kernel 6.0 or 6.1 kernel api ++#ifdef ANDROID_PLATFORM ++#define HIGH_KERNEL_VERSION KERNEL_VERSION(5, 15, 41) ++#define HIGH_KERNEL_VERSION2 KERNEL_VERSION(5, 15, 41) ++#define HIGH_KERNEL_VERSION3 KERNEL_VERSION(5, 15, 104) ++#define HIGH_KERNEL_VERSION4 KERNEL_VERSION(6, 1, 0) ++#else ++#define HIGH_KERNEL_VERSION KERNEL_VERSION(6, 0, 0) ++#define HIGH_KERNEL_VERSION2 KERNEL_VERSION(6, 1, 0) ++#define HIGH_KERNEL_VERSION3 KERNEL_VERSION(6, 3, 0) ++#define HIGH_KERNEL_VERSION4 KERNEL_VERSION(6, 3, 0) ++#endif ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 60) ++#define IEEE80211_MAX_AMPDU_BUF IEEE80211_MAX_AMPDU_BUF_HE ++#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB ++#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB ++#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU ++#endif ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) ++#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_MASK ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define IEEE80211_RADIOTAP_HE 23 ++#define IEEE80211_RADIOTAP_HE_MU 24 ++ ++struct ieee80211_radiotap_he { ++ __le16 data1, data2, data3, data4, data5, data6; ++}; ++ ++enum ieee80211_radiotap_he_bits { ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2, ++ IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3, ++ ++ IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004, ++ IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008, ++ IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010, ++ IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020, ++ IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040, ++ IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080, ++ IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100, ++ IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000, ++ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000, ++ IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001, ++ IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002, ++ IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004, ++ IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008, ++ IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010, ++ IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020, ++ IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040, ++ IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080, ++ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00, ++ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f, ++ IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040, ++ IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080, ++ IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00, ++ IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000, ++ IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000, ++ IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00, ++ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000, ++ ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10, ++ ++ IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030, ++ IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0, ++ IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1, ++ IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2, ++ ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2, ++ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3, ++ IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700, ++ IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000, ++ IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000, ++ IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f, ++ IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010, ++ IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00, ++ IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000, ++}; ++ ++struct ieee80211_radiotap_he_mu { ++ __le16 flags1, flags2; ++ u8 ru_ch1[4]; ++ u8 ru_ch2[4]; ++}; ++ ++enum ieee80211_radiotap_he_mu_bits { ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS = 0x000f, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN = 0x0010, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM = 0x0020, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN = 0x0040, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN = 0x0080, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN = 0x0100, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN = 0x0200, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN = 0x1000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU = 0x2000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN = 0x4000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN = 0x8000, ++ ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW = 0x0003, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_20MHZ = 0x0000, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_40MHZ = 0x0001, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_80MHZ = 0x0002, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_160MHZ = 0x0003, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN = 0x0004, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP = 0x0008, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS = 0x00f0, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW = 0x0300, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN = 0x0400, ++ IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800, ++}; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) ++#define rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, params) \ ++ rwnx_cfg80211_add_iface(wiphy, name, type, u32 *flags, params) ++#else ++#define rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, params) \ ++ rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, u32 *flags, params) ++#endif ++ ++#define rwnx_cfg80211_change_iface(wiphy, dev, type, params) \ ++ rwnx_cfg80211_change_iface(wiphy, dev, type, u32 *flags, params) ++ ++#define CCFS0(vht) vht->center_freq_seg1_idx ++#define CCFS1(vht) vht->center_freq_seg2_idx ++ ++#else ++#define CCFS0(vht) vht->center_freq_seg0_idx ++#define CCFS1(vht) vht->center_freq_seg1_idx ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) ++#define cfg80211_cqm_rssi_notify(dev, event, level, gfp) \ ++ cfg80211_cqm_rssi_notify(dev, event, gfp) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) ++#define ieee80211_amsdu_to_8023s(skb, list, addr, iftype, extra_headroom, check_da, check_sa) \ ++ ieee80211_amsdu_to_8023s(skb, list, addr, iftype, extra_headroom, false) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) ++#define NUM_NL80211_BANDS IEEE80211_NUM_BANDS ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++#define cfg80211_disconnected(dev, reason, ie, len, local, gfp) \ ++ cfg80211_disconnected(dev, reason, ie, len, gfp) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !(defined CONFIG_VENDOR_RWNX) ++#define ieee80211_chandef_to_operating_class(chan_def, op_class) 0 ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++#define SURVEY_INFO_TIME SURVEY_INFO_CHANNEL_TIME ++#define SURVEY_INFO_TIME_BUSY SURVEY_INFO_CHANNEL_TIME_BUSY ++#define SURVEY_INFO_TIME_EXT_BUSY SURVEY_INFO_CHANNEL_TIME_EXT_BUSY ++#define SURVEY_INFO_TIME_RX SURVEY_INFO_CHANNEL_TIME_RX ++#define SURVEY_INFO_TIME_TX SURVEY_INFO_CHANNEL_TIME_TX ++ ++#define SURVEY_TIME(s) s->channel_time ++#define SURVEY_TIME_BUSY(s) s->channel_time_busy ++#else ++#define SURVEY_TIME(s) s->time ++#define SURVEY_TIME_BUSY(s) s->time_busy ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) ++#define cfg80211_ch_switch_started_notify(dev, chandef, count) ++ ++#define WLAN_BSS_COEX_INFORMATION_REQUEST BIT(0) ++#define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2) ++#define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4) ++#define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5) ++#define WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH BIT(6) ++#define WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED BIT(7) ++#define NL80211_FEATURE_TDLS_CHANNEL_SWITCH 0 ++ ++#define STA_TDLS_INITIATOR(sta) 0 ++ ++#else ++#define STA_TDLS_INITIATOR(sta) sta->tdls_initiator ++#endif ++ ++#ifndef REGULATORY_IGNORE_STALE_KICKOFF ++#define REGULATORY_IGNORE_STALE_KICKOFF 0 ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) ++#define cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags) \ ++ cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags, GFP_ATOMIC) ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) ++#define cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags) \ ++ cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, GFP_ATOMIC) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) ++#define rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, initiator, buf, len) \ ++ rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, buf, len) ++#else ++#define rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, initiator, buf, len) \ ++ rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, buf, len) ++#endif ++#endif ++ ++#include ++ ++struct ieee80211_wmm_ac_param { ++ u8 aci_aifsn; /* AIFSN, ACM, ACI */ ++ u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ ++ __le16 txop_limit; ++} __packed; ++ ++struct ieee80211_wmm_param_ie { ++ u8 element_id; /* Element ID: 221 (0xdd); */ ++ u8 len; /* Length: 24 */ ++ /* required fields for WMM version 1 */ ++ u8 oui[3]; /* 00:50:f2 */ ++ u8 oui_type; /* 2 */ ++ u8 oui_subtype; /* 1 */ ++ u8 version; /* 1 for WMM version 1.0 */ ++ u8 qos_info; /* AP/STA specific QoS info */ ++ u8 reserved; /* 0 */ ++ /* AC_BE, AC_BK, AC_VI, AC_VO */ ++ struct ieee80211_wmm_ac_param ac[4]; ++} __packed; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++enum { ++ IEEE80211_HE_MCS_SUPPORT_0_7 = 0, ++ IEEE80211_HE_MCS_SUPPORT_0_9 = 1, ++ IEEE80211_HE_MCS_SUPPORT_0_11 = 2, ++ IEEE80211_HE_MCS_NOT_SUPPORTED = 3, ++}; ++#endif ++ ++/* MAC80211 */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) ++#define rwnx_ops_mgd_prepare_tx(hw, vif, duration) \ ++ rwnx_ops_mgd_prepare_tx(hw, vif) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) ++ ++#define RX_ENC_HT(s) (s->flag |= RX_FLAG_HT) ++#define RX_ENC_HT_GF(s) (s->flag |= (RX_FLAG_HT | RX_FLAG_HT_GF)) ++#define RX_ENC_VHT(s) (s->flag |= RX_FLAG_HT) ++#define RX_ENC_HE(s) (s->flag |= RX_FLAG_HT) ++#define RX_ENC_FLAG_SHORT_GI(s) (s->flag |= RX_FLAG_SHORT_GI) ++#define RX_ENC_FLAG_SHORT_PRE(s) (s->flag |= RX_FLAG_SHORTPRE) ++#define RX_ENC_FLAG_LDPC(s) (s->flag |= RX_FLAG_LDPC) ++#define RX_BW_40MHZ(s) (s->flag |= RX_FLAG_40MHZ) ++#define RX_BW_80MHZ(s) (s->vht_flag |= RX_VHT_FLAG_80MHZ) ++#define RX_BW_160MHZ(s) (s->vht_flag |= RX_VHT_FLAG_160MHZ) ++#define RX_NSS(s) s->vht_nss ++ ++#else ++#define RX_ENC_HT(s) (s->encoding = RX_ENC_HT) ++#define RX_ENC_HT_GF(s) { s->encoding = RX_ENC_HT; \ ++ s->enc_flags |= RX_ENC_FLAG_HT_GF; } ++#define RX_ENC_VHT(s) (s->encoding = RX_ENC_VHT) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define RX_ENC_HE(s) (s->encoding = RX_ENC_VHT) ++#else ++#define RX_ENC_HE(s) (s->encoding = RX_ENC_HE) ++#endif ++#define RX_ENC_FLAG_SHORT_GI(s) (s->enc_flags |= RX_ENC_FLAG_SHORT_GI) ++#define RX_ENC_FLAG_SHORT_PRE(s) (s->enc_flags |= RX_ENC_FLAG_SHORTPRE) ++#define RX_ENC_FLAG_LDPC(s) (s->enc_flags |= RX_ENC_FLAG_LDPC) ++#define RX_BW_40MHZ(s) (s->bw = RATE_INFO_BW_40) ++#define RX_BW_80MHZ(s) (s->bw = RATE_INFO_BW_80) ++#define RX_BW_160MHZ(s) (s->bw = RATE_INFO_BW_160) ++#define RX_NSS(s) s->nss ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) ++#define ieee80211_cqm_rssi_notify(vif, event, level, gfp) \ ++ ieee80211_cqm_rssi_notify(vif, event, gfp) ++#endif ++ ++#ifndef CONFIG_VENDOR_RWNX_AMSDUS_TX ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) ++#define rwnx_ops_ampdu_action(hw, vif, params) \ ++ rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \ ++ struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) ++#define rwnx_ops_ampdu_action(hw, vif, params) \ ++ rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \ ++ struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, \ ++ bool amsdu) ++#endif ++#endif /* CONFIG_VENDOR_RWNX_AMSDUS_TX */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++#define IEEE80211_HW_SUPPORT_FAST_XMIT 0 ++#define ieee80211_hw_check(hw, feat) (hw->flags & IEEE80211_HW_##feat) ++#define ieee80211_hw_set(hw, feat) {hw->flags |= IEEE80211_HW_##feat; } ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) ++#define rwnx_ops_sw_scan_start(hw, vif, mac_addr) \ ++ rwnx_ops_sw_scan_start(hw) ++#define rwnx_ops_sw_scan_complete(hw, vif) \ ++ rwnx_ops_sw_scan_complete(hw) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define rwnx_ops_hw_scan(hw, vif, hw_req) \ ++ rwnx_ops_hw_scan(hw, vif, struct cfg80211_scan_request *req) ++#endif ++ ++/* NET */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb) ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb, void *accel_priv, select_queue_fallback_t fallback) ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb, sb_dev, select_queue_fallback_t fallback) ++#else ++#define rwnx_select_queue(dev, skb, sb_dev) \ ++ rwnx_select_queue(dev, skb, sb_dev) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)) && !(defined CONFIG_VENDOR_RWNX) ++#define sk_pacing_shift_update(sk, shift) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define alloc_netdev_mqs(size, name, assign, setup, txqs, rxqs) \ ++ alloc_netdev_mqs(size, name, setup, txqs, rxqs) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define NET_NAME_UNKNOWN 0 ++#endif ++ ++/* TRACE */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++#define trace_print_symbols_seq ftrace_print_symbols_seq ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++#define trace_seq_buffer_ptr(p) (p->buffer + p->len) ++#endif ++ ++/* TIME */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) ++#define time64_to_tm(t, o, tm) time_to_tm((time_t)t, o, tm) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) ++#define ktime_get_real_seconds get_seconds ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++typedef __s64 time64_t; ++#endif ++ ++#endif /* _RWNX_COMPAT_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c +new file mode 100644 +index 000000000000..fdca110169b0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c +@@ -0,0 +1,2469 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_debugfs.c ++ * ++ * @brief Definition of debugfs entries ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rwnx_debugfs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_radar.h" ++#include "rwnx_tx.h" ++ ++#ifdef CONFIG_DEBUG_FS ++#ifdef CONFIG_RWNX_FULLMAC ++static ssize_t rwnx_dbgfs_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int ret; ++ int i, skipped; ++ ssize_t read; ++ int bufsz = (NX_TXQ_CNT) * 20 + (ARRAY_SIZE(priv->stats.amsdus_rx) + 1) * 40 ++ + (ARRAY_SIZE(priv->stats.ampdus_tx) * 30); ++ ++ if (*ppos) ++ return 0; ++ ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ ret = scnprintf(buf, bufsz, "TXQs CFM balances "); ++ for (i = 0; i < NX_TXQ_CNT; i++) ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%1d]:%3d", i, ++ priv->stats.cfm_balance[i]); ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, "\n"); ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "\nAMSDU[len] done failed received\n"); ++ for (i = skipped = 0; i < NX_TX_PAYLOAD_MAX; i++) { ++ if (priv->stats.amsdus[i].done) { ++ per = DIV_ROUND_UP((priv->stats.amsdus[i].failed) * ++ 100, priv->stats.amsdus[i].done); ++ } else if (priv->stats.amsdus_rx[i]) { ++ per = 0; ++ } else { ++ per = 0; ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %10d %8d(%3d%%) %10d\n", i ? i + 1 : i, ++ priv->stats.amsdus[i].done, ++ priv->stats.amsdus[i].failed, per, ++ priv->stats.amsdus_rx[i]); ++ } ++ ++ for (; i < ARRAY_SIZE(priv->stats.amsdus_rx); i++) { ++ if (!priv->stats.amsdus_rx[i]) { ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %10d\n", ++ i + 1, priv->stats.amsdus_rx[i]); ++ } ++#else ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "\nAMSDU[len] received\n"); ++ for (i = skipped = 0; i < ARRAY_SIZE(priv->stats.amsdus_rx); i++) { ++ if (!priv->stats.amsdus_rx[i]) { ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %10d\n", ++ i + 1, priv->stats.amsdus_rx[i]); ++ } ++ ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "\nAMPDU[len] done received\n"); ++ for (i = skipped = 0; i < ARRAY_SIZE(priv->stats.ampdus_tx); i++) { ++ if (!priv->stats.ampdus_tx[i] && !priv->stats.ampdus_rx[i]) { ++ skipped = 1; ++ continue; ++ } ++ if (skipped) { ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " ...\n"); ++ skipped = 0; ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ " [%2d] %9d %9d\n", i ? i + 1 : i, ++ priv->stats.ampdus_tx[i], priv->stats.ampdus_rx[i]); ++ } ++ ++ ret += scnprintf(&buf[ret], bufsz - ret, ++ "#mpdu missed %9d\n", ++ priv->stats.ampdus_rx_miss); ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ kfree(buf); ++ ++ return read; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++static ssize_t rwnx_dbgfs_stats_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ ++ /* Prevent from interrupt preemption as these statistics are updated under ++ * interrupt */ ++ spin_lock_bh(&priv->tx_lock); ++ ++ memset(&priv->stats, 0, sizeof(priv->stats)); ++ ++ spin_unlock_bh(&priv->tx_lock); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(stats); ++ ++#define TXQ_STA_PREF "tid|" ++#define TXQ_STA_PREF_FMT "%3d|" ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define TXQ_VIF_PREF "type|" ++#define TXQ_VIF_PREF_FMT "%4s|" ++#else ++#define TXQ_VIF_PREF "AC|" ++#define TXQ_VIF_PREF_FMT "%2s|" ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#define TXQ_HDR "idx| status|credit|ready|retry" ++#define TXQ_HDR_FMT "%3d|%s%s%s%s%s%s%s|%6d|%5d|%5d" ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++#ifdef CONFIG_RWNX_FULLMAC ++#define TXQ_HDR_SUFF "|amsdu" ++#define TXQ_HDR_SUFF_FMT "|%5d" ++#else ++#define TXQ_HDR_SUFF "|amsdu-ht|amdsu-vht" ++#define TXQ_HDR_SUFF_FMT "|%8d|%9d" ++#endif /* CONFIG_RWNX_FULLMAC */ ++#else ++#define TXQ_HDR_SUFF "" ++#define TXQ_HDR_SUF_FMT "" ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++#define TXQ_HDR_MAX_LEN (sizeof(TXQ_STA_PREF) + sizeof(TXQ_HDR) + sizeof(TXQ_HDR_SUFF) + 1) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define PS_HDR "Legacy PS: ready=%d, sp=%d / UAPSD: ready=%d, sp=%d" ++#define PS_HDR_LEGACY "Legacy PS: ready=%d, sp=%d" ++#define PS_HDR_UAPSD "UAPSD: ready=%d, sp=%d" ++#define PS_HDR_MAX_LEN sizeof("Legacy PS: ready=xxx, sp=xxx / UAPSD: ready=xxx, sp=xxx\n") ++#else ++#define PS_HDR "" ++#define PS_HDR_MAX_LEN 0 ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#define STA_HDR "** STA %d (%pM)\n" ++#define STA_HDR_MAX_LEN (sizeof("- STA xx (xx:xx:xx:xx:xx:xx)\n") + PS_HDR_MAX_LEN) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define VIF_HDR "* VIF [%d] %s\n" ++#define VIF_HDR_MAX_LEN (sizeof(VIF_HDR) + IFNAMSIZ) ++#else ++#define VIF_HDR "* VIF [%d]\n" ++#define VIF_HDR_MAX_LEN sizeof(VIF_HDR) ++#endif ++ ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define VIF_SEP "---------------------------------------\n" ++#else ++#define VIF_SEP "----------------------------------------------------\n" ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#else /* ! CONFIG_RWNX_AMSDUS_TX */ ++#define VIF_SEP "---------------------------------\n" ++#endif /* CONFIG_RWNX_AMSDUS_TX*/ ++ ++#define VIF_SEP_LEN sizeof(VIF_SEP) ++ ++#define CAPTION "status: L=in hwq list, F=stop full, P=stop sta PS, V=stop vif PS, C=stop channel, S=stop CSA, M=stop MU" ++#define CAPTION_LEN sizeof(CAPTION) ++ ++#define STA_TXQ 0 ++#define VIF_TXQ 1 ++ ++static int rwnx_dbgfs_txq(char *buf, size_t size, struct rwnx_txq *txq, int type, int tid, char *name) ++{ ++ int res, idx = 0; ++ ++ if (type == STA_TXQ) { ++ res = scnprintf(&buf[idx], size, TXQ_STA_PREF_FMT, tid); ++ idx += res; ++ size -= res; ++ } else { ++ res = scnprintf(&buf[idx], size, TXQ_VIF_PREF_FMT, name); ++ idx += res; ++ size -= res; ++ } ++ ++ res = scnprintf(&buf[idx], size, TXQ_HDR_FMT, txq->idx, ++ (txq->status & RWNX_TXQ_IN_HWQ_LIST) ? "L" : " ", ++ (txq->status & RWNX_TXQ_STOP_FULL) ? "F" : " ", ++ (txq->status & RWNX_TXQ_STOP_STA_PS) ? "P" : " ", ++ (txq->status & RWNX_TXQ_STOP_VIF_PS) ? "V" : " ", ++ (txq->status & RWNX_TXQ_STOP_CHAN) ? "C" : " ", ++ (txq->status & RWNX_TXQ_STOP_CSA) ? "S" : " ", ++ (txq->status & RWNX_TXQ_STOP_MU_POS) ? "M" : " ", ++ txq->credits, skb_queue_len(&txq->sk_list), ++ txq->nb_retry); ++ idx += res; ++ size -= res; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (type == STA_TXQ) { ++ res = scnprintf(&buf[idx], size, TXQ_HDR_SUFF_FMT, ++#ifdef CONFIG_RWNX_FULLMAC ++ txq->amsdu_len ++#else ++ txq->amsdu_ht_len_cap, txq->amsdu_vht_len_cap ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ); ++ idx += res; ++ size -= res; ++ } ++#endif ++ ++ res = scnprintf(&buf[idx], size, "\n"); ++ idx += res; ++ size -= res; ++ ++ return idx; ++} ++ ++static int rwnx_dbgfs_txq_sta(char *buf, size_t size, struct rwnx_sta *rwnx_sta, ++ struct rwnx_hw *rwnx_hw) ++{ ++ int tid, res, idx = 0; ++ struct rwnx_txq *txq; ++ ++ res = scnprintf(&buf[idx], size, "\n" STA_HDR, ++ rwnx_sta->sta_idx, ++#ifdef CONFIG_RWNX_FULLMAC ++ rwnx_sta->mac_addr ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ); ++ idx += res; ++ size -= res; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (rwnx_sta->ps.active) { ++ if (rwnx_sta->uapsd_tids && ++ (rwnx_sta->uapsd_tids == ((1 << NX_NB_TXQ_PER_STA) - 1))) ++ res = scnprintf(&buf[idx], size, PS_HDR_UAPSD "\n", ++ rwnx_sta->ps.pkt_ready[UAPSD_ID], ++ rwnx_sta->ps.sp_cnt[UAPSD_ID]); ++ else if (rwnx_sta->uapsd_tids) ++ res = scnprintf(&buf[idx], size, PS_HDR "\n", ++ rwnx_sta->ps.pkt_ready[LEGACY_PS_ID], ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID], ++ rwnx_sta->ps.pkt_ready[UAPSD_ID], ++ rwnx_sta->ps.sp_cnt[UAPSD_ID]); ++ else ++ res = scnprintf(&buf[idx], size, PS_HDR_LEGACY "\n", ++ rwnx_sta->ps.pkt_ready[LEGACY_PS_ID], ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID]); ++ idx += res; ++ size -= res; ++ } else { ++ res = scnprintf(&buf[idx], size, "\n"); ++ idx += res; ++ size -= res; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ ++ res = scnprintf(&buf[idx], size, TXQ_STA_PREF TXQ_HDR TXQ_HDR_SUFF "\n"); ++ idx += res; ++ size -= res; ++ ++ ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, STA_TXQ, tid, NULL); ++ idx += res; ++ size -= res; ++ } ++ ++ return idx; ++} ++ ++static int rwnx_dbgfs_txq_vif(char *buf, size_t size, struct rwnx_vif *rwnx_vif, ++ struct rwnx_hw *rwnx_hw) ++{ ++ int res, idx = 0; ++ struct rwnx_txq *txq; ++ struct rwnx_sta *rwnx_sta; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ res = scnprintf(&buf[idx], size, VIF_HDR, rwnx_vif->vif_index, rwnx_vif->ndev->name); ++ idx += res; ++ size -= res; ++ if (!rwnx_vif->up || rwnx_vif->ndev == NULL) ++ return idx; ++ ++#else ++ int ac; ++ char ac_name[2] = {'0', '\0'}; ++ ++ res = scnprintf(&buf[idx], size, VIF_HDR, rwnx_vif->vif_index); ++ idx += res; ++ size -= res; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT) { ++ res = scnprintf(&buf[idx], size, TXQ_VIF_PREF TXQ_HDR "\n"); ++ idx += res; ++ size -= res; ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, VIF_TXQ, 0, "UNK"); ++ idx += res; ++ size -= res; ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, VIF_TXQ, 0, "BCMC"); ++ idx += res; ++ size -= res; ++ rwnx_sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ if (rwnx_sta->ps.active) { ++ res = scnprintf(&buf[idx], size, PS_HDR_LEGACY "\n", ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID], ++ rwnx_sta->ps.sp_cnt[LEGACY_PS_ID]); ++ idx += res; ++ size -= res; ++ } else { ++ res = scnprintf(&buf[idx], size, "\n"); ++ idx += res; ++ size -= res; ++ } ++ ++ list_for_each_entry(rwnx_sta, &rwnx_vif->ap.sta_list, list) { ++ res = rwnx_dbgfs_txq_sta(&buf[idx], size, rwnx_sta, rwnx_hw); ++ idx += res; ++ size -= res; ++ } ++ } else if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ if (rwnx_vif->sta.ap) { ++ res = rwnx_dbgfs_txq_sta(&buf[idx], size, rwnx_vif->sta.ap, rwnx_hw); ++ idx += res; ++ size -= res; ++ } ++ } ++ ++#else ++ res = scnprintf(&buf[idx], size, TXQ_VIF_PREF TXQ_HDR "\n"); ++ idx += res; ++ size -= res; ++ ++ foreach_vif_txq(rwnx_vif, txq, ac) { ++ ac_name[0]++; ++ res = rwnx_dbgfs_txq(&buf[idx], size, txq, VIF_TXQ, 0, ac_name); ++ idx += res; ++ size -= res; ++ } ++ ++ list_for_each_entry(rwnx_sta, &rwnx_vif->stations, list) { ++ res = rwnx_dbgfs_txq_sta(&buf[idx], size, rwnx_sta, rwnx_hw); ++ idx += res; ++ size -= res; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ return idx; ++} ++ ++static ssize_t rwnx_dbgfs_txq_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rwnx_hw = file->private_data; ++ struct rwnx_vif *vif; ++ char *buf; ++ int idx, res; ++ ssize_t read; ++ size_t bufsz = ((NX_VIRT_DEV_MAX * (VIF_HDR_MAX_LEN + 2 * VIF_SEP_LEN)) + ++ (NX_REMOTE_STA_MAX * STA_HDR_MAX_LEN) + ++ ((NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX + NX_NB_TXQ) * ++ TXQ_HDR_MAX_LEN) + CAPTION_LEN); ++ ++ /* everything is read in one go */ ++ if (*ppos) ++ return 0; ++ ++ bufsz = min_t(size_t, bufsz, count); ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ bufsz--; ++ idx = 0; ++ ++ res = scnprintf(&buf[idx], bufsz, CAPTION); ++ idx += res; ++ bufsz -= res; ++ ++ //spin_lock_bh(&rwnx_hw->tx_lock); ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ res = scnprintf(&buf[idx], bufsz, "\n"VIF_SEP); ++ idx += res; ++ bufsz -= res; ++ res = rwnx_dbgfs_txq_vif(&buf[idx], bufsz, vif, rwnx_hw); ++ idx += res; ++ bufsz -= res; ++ res = scnprintf(&buf[idx], bufsz, VIF_SEP); ++ idx += res; ++ bufsz -= res; ++ } ++ //spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, idx); ++ kfree(buf); ++ ++ return read; ++} ++DEBUGFS_READ_FILE_OPS(txq); ++ ++static ssize_t rwnx_dbgfs_acsinfo_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++#ifdef CONFIG_RWNX_FULLMAC ++ struct wiphy *wiphy = priv->wiphy; ++#endif //CONFIG_RWNX_FULLMAC ++ int survey_cnt = 0; ++ int len = 0; ++ int band, chan_cnt; ++ int band_max = NL80211_BAND_5GHZ; ++ char *buf = (char *)vmalloc((SCAN_CHANNEL_MAX + 1) * 43); ++ ssize_t size; ++ ++ if (!buf) ++ return 0; ++ ++ if (priv->band_5g_support) ++ band_max = NL80211_BAND_5GHZ + 1; ++ ++ mutex_lock(&priv->dbgdump_elem.mutex); ++ ++ len += scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "FREQ TIME(ms) BUSY(ms) NOISE(dBm)\n"); ++ ++ for (band = NL80211_BAND_2GHZ; band < band_max; band++) { ++ for (chan_cnt = 0; chan_cnt < wiphy->bands[band]->n_channels; chan_cnt++) { ++ struct rwnx_survey_info *p_survey_info = &priv->survey[survey_cnt]; ++ struct ieee80211_channel *p_chan = &wiphy->bands[band]->channels[chan_cnt]; ++ ++ if (p_survey_info->filled) { ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - len - 1, count), ++ "%d %03d %03d %d\n", ++ p_chan->center_freq, ++ p_survey_info->chan_time_ms, ++ p_survey_info->chan_time_busy_ms, ++ p_survey_info->noise_dbm); ++ } else { ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) -len -1, count), ++ "%d NOT AVAILABLE\n", ++ p_chan->center_freq); ++ } ++ ++ survey_cnt++; ++ } ++ } ++ ++ mutex_unlock(&priv->dbgdump_elem.mutex); ++ ++ size = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ vfree(buf); ++ ++ return size; ++} ++ ++DEBUGFS_READ_FILE_OPS(acsinfo); ++ ++static ssize_t rwnx_dbgfs_fw_dbg_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ char help[] = "usage: [MOD:]* " ++ "[DBG:]\n"; ++ ++ return simple_read_from_buffer(user_buf, count, ppos, help, sizeof(help)); ++} ++ ++ ++static ssize_t rwnx_dbgfs_fw_dbg_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int idx = 0; ++ u32 mod = 0; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ ++#define RWNX_MOD_TOKEN(str, val) \ ++ do { \ ++ if (strncmp(&buf[idx], str, sizeof(str) - 1) == 0) { \ ++ idx += sizeof(str) - 1; \ ++ mod |= val; \ ++ continue; \ ++ } \ ++ } while (0) ++ ++#define RWNX_DBG_TOKEN(str, val) \ ++ do { \ ++ if (strncmp(&buf[idx], str, sizeof(str) - 1) == 0) { \ ++ idx += sizeof(str) - 1; \ ++ dbg = val; \ ++ goto dbg_done; \ ++ } \ ++ } while (0) ++ ++ while ((idx + 4) < len) { ++ if (strncmp(&buf[idx], "MOD:", 4) == 0) { ++ idx += 4; ++ RWNX_MOD_TOKEN("ALL", 0xffffffff); ++ RWNX_MOD_TOKEN("KE", BIT(0)); ++ RWNX_MOD_TOKEN("DBG", BIT(1)); ++ RWNX_MOD_TOKEN("IPC", BIT(2)); ++ RWNX_MOD_TOKEN("DMA", BIT(3)); ++ RWNX_MOD_TOKEN("MM", BIT(4)); ++ RWNX_MOD_TOKEN("TX", BIT(5)); ++ RWNX_MOD_TOKEN("RX", BIT(6)); ++ RWNX_MOD_TOKEN("PHY", BIT(7)); ++ idx++; ++ } else if (strncmp(&buf[idx], "DBG:", 4) == 0) { ++ u32 dbg = 0; ++ idx += 4; ++ RWNX_DBG_TOKEN("NONE", 0); ++ RWNX_DBG_TOKEN("CRT", 1); ++ RWNX_DBG_TOKEN("ERR", 2); ++ RWNX_DBG_TOKEN("WRN", 3); ++ RWNX_DBG_TOKEN("INF", 4); ++ RWNX_DBG_TOKEN("VRB", 5); ++ idx++; ++ continue; ++ dbg_done: ++ rwnx_send_dbg_set_sev_filter_req(priv, dbg); ++ } else { ++ idx++; ++ } ++ } ++ ++ if (mod) { ++ rwnx_send_dbg_set_mod_filter_req(priv, mod); ++ } ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg); ++ ++static ssize_t rwnx_dbgfs_sys_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[3*64]; ++ int len = 0; ++ ssize_t read; ++ int error = 0; ++ struct dbg_get_sys_stat_cfm cfm; ++ u32 sleep_int, sleep_frac, doze_int, doze_frac; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Get the information from the FW */ ++ error = rwnx_send_dbg_get_sys_stat_req(priv, &cfm); ++ if (error) ++ return error; ++ ++ if (cfm.stats_time == 0) ++ return 0; ++ ++ sleep_int = ((cfm.cpu_sleep_time * 100) / cfm.stats_time); ++ sleep_frac = (((cfm.cpu_sleep_time * 100) % cfm.stats_time) * 10) / cfm.stats_time; ++ doze_int = ((cfm.doze_time * 100) / cfm.stats_time); ++ doze_frac = (((cfm.doze_time * 100) % cfm.stats_time) * 10) / cfm.stats_time; ++ ++ len += scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "\nSystem statistics:\n"); ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - 1, count), ++ " CPU sleep [%%]: %d.%d\n", sleep_int, sleep_frac); ++ len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - 1, count), ++ " Doze [%%]: %d.%d\n", doze_int, doze_frac); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ return read; ++} ++ ++DEBUGFS_READ_FILE_OPS(sys_stats); ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++static ssize_t rwnx_dbgfs_mu_group_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rwnx_hw = file->private_data; ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ struct rwnx_mu_group *group; ++ size_t bufsz = NX_MU_GROUP_MAX * sizeof("xx = (xx - xx - xx - xx)\n") + 50; ++ char *buf; ++ int j, res, idx = 0; ++ ++ if (*ppos) ++ return 0; ++ ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ res = scnprintf(&buf[idx], bufsz, "MU Group list (%d groups, %d users max)\n", ++ NX_MU_GROUP_MAX, CONFIG_USER_MAX); ++ idx += res; ++ bufsz -= res; ++ ++ list_for_each_entry(group, &mu->active_groups, list) { ++ if (group->user_cnt) { ++ res = scnprintf(&buf[idx], bufsz, "%2d = (", group->group_id); ++ idx += res; ++ bufsz -= res; ++ for (j = 0; j < (CONFIG_USER_MAX - 1) ; j++) { ++ if (group->users[j]) ++ res = scnprintf(&buf[idx], bufsz, "%2d - ", ++ group->users[j]->sta_idx); ++ else ++ res = scnprintf(&buf[idx], bufsz, ".. - "); ++ ++ idx += res; ++ bufsz -= res; ++ } ++ ++ if (group->users[j]) ++ res = scnprintf(&buf[idx], bufsz, "%2d)\n", ++ group->users[j]->sta_idx); ++ else ++ res = scnprintf(&buf[idx], bufsz, "..)\n"); ++ ++ idx += res; ++ bufsz -= res; ++ } ++ } ++ ++ res = simple_read_from_buffer(user_buf, count, ppos, buf, idx); ++ kfree(buf); ++ ++ return res; ++} ++ ++DEBUGFS_READ_FILE_OPS(mu_group); ++#endif ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++static ssize_t rwnx_dbgfs_oppps_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rw_hw = file->private_data; ++ struct rwnx_vif *rw_vif; ++ char buf[32]; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ctw; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ ++ /* Read the written CT Window (provided in ms) value */ ++ if (sscanf(buf, "ctw=%d", &ctw) > 0) { ++ /* Check if at least one VIF is configured as P2P GO */ ++ list_for_each_entry(rw_vif, &rw_hw->vifs, list) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (RWNX_VIF_TYPE(rw_vif) == NL80211_IFTYPE_P2P_GO) { ++#endif /* CONFIG_RWNX_FULLMAC */ ++ struct mm_set_p2p_oppps_cfm cfm; ++ ++ /* Forward request to the embedded and wait for confirmation */ ++ rwnx_send_p2p_oppps_req(rw_hw, rw_vif, (u8)ctw, &cfm); ++ ++ break; ++ } ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(oppps); ++ ++static ssize_t rwnx_dbgfs_noa_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *rw_hw = file->private_data; ++ struct rwnx_vif *rw_vif; ++ char buf[64]; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int noa_count, interval, duration, dyn_noa; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ ++ /* Read the written NOA information */ ++ if (sscanf(buf, "count=%d interval=%d duration=%d dyn=%d", ++ &noa_count, &interval, &duration, &dyn_noa) > 0) { ++ /* Check if at least one VIF is configured as P2P GO */ ++ list_for_each_entry(rw_vif, &rw_hw->vifs, list) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (RWNX_VIF_TYPE(rw_vif) == NL80211_IFTYPE_P2P_GO) { ++#endif /* CONFIG_RWNX_FULLMAC */ ++ struct mm_set_p2p_noa_cfm cfm; ++ ++ /* Forward request to the embedded and wait for confirmation */ ++ rwnx_send_p2p_noa_req(rw_hw, rw_vif, noa_count, interval, ++ duration, (dyn_noa > 0), &cfm); ++ ++ break; ++ } ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(noa); ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++static char fw_log_buffer[FW_LOG_SIZE]; ++ ++static ssize_t rwnx_dbgfs_fw_log_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ size_t not_cpy; ++ size_t nb_cpy; ++ char *log = fw_log_buffer; ++ ++ printk("%s, %d, %p, %p\n", __func__, priv->debugfs.fw_log.buf.size, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.dataend); ++ //spin_lock_bh(&priv->debugfs.fw_log.lock); ++ ++ if ((priv->debugfs.fw_log.buf.start + priv->debugfs.fw_log.buf.size) >= priv->debugfs.fw_log.buf.dataend) { ++ memcpy(log, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.dataend - priv->debugfs.fw_log.buf.start); ++ not_cpy = copy_to_user(user_buf, log, priv->debugfs.fw_log.buf.dataend - priv->debugfs.fw_log.buf.start); ++ nb_cpy = priv->debugfs.fw_log.buf.dataend - priv->debugfs.fw_log.buf.start - not_cpy; ++ priv->debugfs.fw_log.buf.start = priv->debugfs.fw_log.buf.data; ++ } else { ++ memcpy(log, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.size); ++ not_cpy = copy_to_user(user_buf, log, priv->debugfs.fw_log.buf.size); ++ nb_cpy = priv->debugfs.fw_log.buf.size - not_cpy; ++ priv->debugfs.fw_log.buf.start = priv->debugfs.fw_log.buf.start + priv->debugfs.fw_log.buf.size - not_cpy; ++ } ++ ++ priv->debugfs.fw_log.buf.size -= nb_cpy; ++ //spin_unlock_bh(&priv->debugfs.fw_log.lock); ++ ++ printk("nb_cpy=%lu, not_cpy=%lu, start=%p, end=%p\n", (long unsigned int)nb_cpy, (long unsigned int)not_cpy, priv->debugfs.fw_log.buf.start, priv->debugfs.fw_log.buf.end); ++ return nb_cpy; ++} ++ ++static ssize_t rwnx_dbgfs_fw_log_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ //struct rwnx_hw *priv = file->private_data; ++ ++ printk("%s\n", __func__); ++ return count; ++} ++DEBUGFS_READ_WRITE_FILE_OPS(fw_log); ++ ++#ifdef CONFIG_RWNX_RADAR ++static ssize_t rwnx_dbgfs_pulses_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos, ++ int rd_idx) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int len = 0; ++ int bufsz; ++ int i; ++ int index; ++ struct rwnx_radar_pulses *p = &priv->radar.pulses[rd_idx]; ++ ssize_t read; ++ ++ if (*ppos != 0) ++ return 0; ++ ++ /* Prevent from interrupt preemption */ ++ spin_lock_bh(&priv->radar.lock); ++ bufsz = p->count * 34 + 51; ++ bufsz += rwnx_radar_dump_pattern_detector(NULL, 0, &priv->radar, rd_idx); ++ buf = kmalloc(bufsz, GFP_ATOMIC); ++ if (buf == NULL) { ++ spin_unlock_bh(&priv->radar.lock); ++ return 0; ++ } ++ ++ if (p->count) { ++ len += scnprintf(&buf[len], bufsz - len, ++ " PRI WIDTH FOM FREQ\n"); ++ index = p->index; ++ for (i = 0; i < p->count; i++) { ++ struct radar_pulse *pulse; ++ ++ if (index > 0) ++ index--; ++ else ++ index = RWNX_RADAR_PULSE_MAX - 1; ++ ++ pulse = (struct radar_pulse *) &p->buffer[index]; ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ "%05dus %03dus %2d%% %+3dMHz\n", pulse->rep, ++ 2 * pulse->len, 6 * pulse->fom, 2*pulse->freq); ++ } ++ } ++ ++ len += rwnx_radar_dump_pattern_detector(&buf[len], bufsz - len, ++ &priv->radar, rd_idx); ++ ++ spin_unlock_bh(&priv->radar.lock); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_pulses_prim_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ return rwnx_dbgfs_pulses_read(file, user_buf, count, ppos, 0); ++} ++ ++DEBUGFS_READ_FILE_OPS(pulses_prim); ++ ++static ssize_t rwnx_dbgfs_pulses_sec_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ return rwnx_dbgfs_pulses_read(file, user_buf, count, ppos, 1); ++} ++ ++DEBUGFS_READ_FILE_OPS(pulses_sec); ++ ++static ssize_t rwnx_dbgfs_detected_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int bufsz, len = 0; ++ ssize_t read; ++ ++ if (*ppos != 0) ++ return 0; ++ ++ bufsz = 5; // RIU:\n ++ bufsz += rwnx_radar_dump_radar_detected(NULL, 0, &priv->radar, ++ RWNX_RADAR_RIU); ++ ++ if (priv->phy.cnt > 1) { ++ bufsz += 5; // FCU:\n ++ bufsz += rwnx_radar_dump_radar_detected(NULL, 0, &priv->radar, ++ RWNX_RADAR_FCU); ++ } ++ ++ buf = kmalloc(bufsz, GFP_KERNEL); ++ if (buf == NULL) { ++ return 0; ++ } ++ ++ len = scnprintf(&buf[len], bufsz, "RIU:\n"); ++ len += rwnx_radar_dump_radar_detected(&buf[len], bufsz - len, &priv->radar, ++ RWNX_RADAR_RIU); ++ ++ if (priv->phy.cnt > 1) { ++ len += scnprintf(&buf[len], bufsz - len, "FCU:\n"); ++ len += rwnx_radar_dump_radar_detected(&buf[len], bufsz - len, ++ &priv->radar, RWNX_RADAR_FCU); ++ } ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ ++ return read; ++} ++ ++DEBUGFS_READ_FILE_OPS(detected); ++ ++static ssize_t rwnx_dbgfs_enable_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "RIU=%d FCU=%d\n", priv->radar.dpd[RWNX_RADAR_RIU]->enabled, ++ priv->radar.dpd[RWNX_RADAR_FCU]->enabled); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_enable_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "RIU=%d", &val) > 0) ++ rwnx_radar_detection_enable(&priv->radar, val, RWNX_RADAR_RIU); ++ ++ if (sscanf(buf, "FCU=%d", &val) > 0) ++ rwnx_radar_detection_enable(&priv->radar, val, RWNX_RADAR_FCU); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(enable); ++ ++static ssize_t rwnx_dbgfs_band_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "BAND=%d\n", priv->phy.sec_chan.band); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_band_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int band_max = NL80211_BAND_5GHZ; ++ ++ if (priv->band_5g_support) ++ band_max = NL80211_BAND_5GHZ + 1; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if ((sscanf(buf, "%d", &val) > 0) && (val >= 0) && (val < band_max)) ++ priv->phy.sec_chan.band = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(band); ++ ++static ssize_t rwnx_dbgfs_type_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "TYPE=%d\n", priv->phy.sec_chan.type); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_type_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if ((sscanf(buf, "%d", &val) > 0) && (val >= PHY_CHNL_BW_20) && ++ (val <= PHY_CHNL_BW_80P80)) ++ priv->phy.sec_chan.type = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(type); ++ ++static ssize_t rwnx_dbgfs_prim20_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "PRIM20=%dMHz\n", priv->phy.sec_chan.prim20_freq); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_prim20_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%d", &val) > 0) ++ priv->phy.sec_chan.prim20_freq = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(prim20); ++ ++static ssize_t rwnx_dbgfs_center1_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "CENTER1=%dMHz\n", priv->phy.sec_chan.center_freq1); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_center1_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%d", &val) > 0) ++ priv->phy.sec_chan.center_freq1 = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(center1); ++ ++static ssize_t rwnx_dbgfs_center2_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int ret; ++ ssize_t read; ++ ++ ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count), ++ "CENTER2=%dMHz\n", priv->phy.sec_chan.center_freq2); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++ ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_center2_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ int val; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%d", &val) > 0) ++ priv->phy.sec_chan.center_freq2 = val; ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(center2); ++ ++ ++static ssize_t rwnx_dbgfs_set_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ return 0; ++} ++ ++static ssize_t rwnx_dbgfs_set_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ ++ rwnx_send_set_channel(priv, 1, NULL); ++ rwnx_radar_detection_enable(&priv->radar, RWNX_RADAR_DETECT_ENABLE, ++ RWNX_RADAR_FCU); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(set); ++#endif /* CONFIG_RWNX_RADAR */ ++ ++static ssize_t rwnx_dbgfs_regdbg_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[32]; ++ u32 addr,val, oper; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ struct dbg_mem_read_cfm mem_read_cfm; ++ int ret; ++ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ if (sscanf(buf, "%x %x %x" , &oper, &addr, &val ) > 0) ++ printk("addr=%x, val=%x,oper=%d\n", addr, val, oper); ++ ++ if(oper== 0) { ++ ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); ++ printk("[0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); ++ } else if (oper == 1) { ++ ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); ++ printk("before write : [0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); ++ ret = rwnx_send_dbg_mem_block_write_req(priv, addr, 4, &val); ++ ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); ++ printk("after write : [0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(regdbg); ++ ++static ssize_t rwnx_dbgfs_vendor_hwconfig_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[64]; ++ int32_t addr[14]; ++ int32_t addr_out[12]; ++ u32_l hwconfig_id; ++ size_t len = min_t(size_t,count,sizeof(buf)-1); ++ int ret; ++ printk("%s\n",__func__); ++ //choose the type of write info by struct ++ //struct mm_set_vendor_trx_param_req trx_param; ++ ++ if(copy_from_user(buf,user_buf,len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", ++ &hwconfig_id, &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5], &addr[6], &addr[7], &addr[8], &addr[9], &addr[10], &addr[11], &addr[12], &addr[13]); ++ if(ret > 15) { ++ printk("param error > 15\n"); ++ } else { ++ switch(hwconfig_id) ++ { ++ case 0: ++ if(ret != 5) { ++ printk("param error != 5\n"); ++ break;} ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("ACS_TXOP_REQ bk:0x%x be:0x%x vi:0x%x vo:0x%x\n",addr[0], addr[1], addr[2], addr[3]); ++ break; ++ case 1: ++ if(ret != 15) { ++ printk("param error != 15\n"); ++ break;} ++ addr[12] = ~addr[12] + 1; ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("CHANNEL_ACCESS_REQ edca:%x,%x,%x,%x, vif:%x, retry_cnt:%x, rts:%x, long_nav:%x, cfe:%x, rc_retry_cnt:%x:%x:%x ccademod_th %x, remove_1m2m %x\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13]); ++ break; ++ case 2: ++ if(ret != 7) { ++ printk("param error != 7\n"); ++ break;} ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("MAC_TIMESCALE_REQ sifsA:%x,sifsB:%x,slot:%x,ofdm_delay:%x,long_delay:%x,short_delay:%x\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); ++ break; ++ case 3: ++ if(ret != 6) { ++ printk("param error != 6\n"); ++ break;} ++ addr[1] = ~addr[1] + 1; ++ addr[2] = ~addr[2] + 1; ++ addr[3] = ~addr[3] + 1; ++ addr[4] = ~addr[4] + 1; ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("CCA_THRESHOLD_REQ auto_cca:%d, cca20p_rise:%d cca20s_rise:%d cca20p_fail:%d cca20s_fail:%d\n", ++ addr[0], addr[1], addr[2], addr[3], addr[4]); ++ break; ++ case 4: // BWMODE_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("BWMODE_REQ md=%d\n", addr[0]); ++ } ++ break; ++ case 5: // CHIP_TEMP_GET_REQ ++ if (ret != 1) { ++ printk("param error != 1\n"); ++ } else { ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, addr_out); ++ printk("CHIP_TEMP_GET_REQ degree=%d\n", addr_out[0]); ++ } ++ break; ++ case 6://AP_PS_LEVEL_SET_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); ++ printk("AP_PS_LEVEL_SET_REQ lvl=%d\n", addr[0]); ++ } ++ break; ++ default: ++ printk("param error\n"); ++ break; ++ } ++ if(ret) { ++ printk("rwnx_send_vendor_hwconfig_req fail: %x\n", ret); ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(vendor_hwconfig); ++ ++static ssize_t rwnx_dbgfs_vendor_swconfig_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[64]; ++ int32_t addr[12]; ++ int32_t addr_out[12]; ++ u32_l swconfig_id; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ret; ++ printk("%s\n", __func__); ++ ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%x %x %x", &swconfig_id, &addr[0], &addr[1]); ++ if (ret > 3) { ++ printk("param error > 3\n"); ++ } else { ++ switch (swconfig_id) ++ { ++ case 0: // BCN_CFG_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("BCN_CFG_REQ set_en=%d, get_en=%d\n", addr[0], addr_out[0]); ++ } ++ break; ++ ++ case 1: // TEMP_COMP_SET_REQ ++ if (ret != 3) { ++ printk("param error != 3\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("TEMP_COMP_SET_REQ set_en=%d, tmr=%dms, get_st=%d\n", ++ addr[0], addr[1], addr_out[0]); ++ } ++ break; ++ ++ case 2: // TEMP_COMP_GET_REQ ++ if (ret != 1) { ++ printk("param error != 1\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("TEMP_COMP_GET_REQ get_st=%d, degree=%d\n", addr_out[0], addr_out[1]); ++ } ++ break; ++ ++ case 3: // EXT_FLAGS_SET_REQ ++ if (ret != 2) { ++ printk("param error != 2\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("EXT_FLAGS_SET_REQ set ext_flags=0x%x, get ext_flags=0x%x\n", ++ addr[0], addr_out[0]); ++ } ++ break; ++ ++ case 4: // EXT_FLAGS_GET_REQ ++ if (ret != 1) { ++ printk("param error != 1\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("EXT_FLAGS_GET_REQ get ext_flags=0x%x\n", addr_out[0]); ++ } ++ break; ++ ++ case 5: // EXT_FLAGS_MASK_SET_REQ ++ if (ret != 3) { ++ printk("param error != 3\n"); ++ } else { ++ ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); ++ printk("EXT_FLAGS_MASK_SET_REQ set ext_flags mask=0x%x, val=0x%x, get ext_flags=0x%x\n", ++ addr[0], addr[1], addr_out[0]); ++ } ++ break; ++ ++ default: ++ printk("param error\n"); ++ break; ++ } ++ ++ if (ret) { ++ printk("rwnx_send_vendor_swconfig_req fail: %x\n", ret); ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(vendor_swconfig); ++ ++static ssize_t rwnx_dbgfs_agg_disable_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ char buf[64]; ++ int agg_disable, agg_disable_rx, sta_idx; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ret; ++ printk("%s\n", __func__); ++ ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%d %d %d", &agg_disable, &agg_disable_rx, &sta_idx); ++ if ((ret > 3) || (ret < 2)) { ++ printk("param error: cnt=%d\n", ret); ++ } else { ++ if (ret < 3) { ++ sta_idx = RWNX_INVALID_STA; ++ } ++ printk("disable_agg: T=%d, R=%d, staidx=%d\n", agg_disable, agg_disable_rx, sta_idx); ++ ret = rwnx_send_disable_agg_req(priv, (u8_l)agg_disable, (u8_l)agg_disable_rx, (u8_l)sta_idx); ++ if (ret) { ++ printk("rwnx_send_disable_agg_req fail: %d\n", ret); ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(agg_disable); ++ ++static ssize_t rwnx_dbgfs_set_roc_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_hw *priv = file->private_data; ++ struct rwnx_vif *vif = NULL; ++ char buf[64]; ++ int roc_start, chan_freq, duration; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ int ret; ++ int if_type = NL80211_IFTYPE_STATION; ++ printk("%s\n", __func__); ++ ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ buf[len] = '\0'; ++ ret = sscanf(buf, "%d %d %d", &roc_start, &chan_freq, &duration); ++ ++ list_for_each_entry(vif, &priv->vifs, list) { ++ if (RWNX_VIF_TYPE(vif) == if_type) { ++ break; ++ } ++ } ++ if ((ret > 3) || (ret < 1)) { ++ printk("param error: cnt=%d\n", ret); ++ } else if (vif) { ++ struct ieee80211_channel chan_entry = {0,}; ++ struct ieee80211_channel *chan = &chan_entry; ++ struct mm_remain_on_channel_cfm roc_cfm; ++ if (ret < 3) { ++ duration = 2000; ++ if (ret < 2) { ++ chan_freq = 2412; ++ } ++ } ++ printk("set_roc: start=%d, freq=%d\n", roc_start, chan_freq); ++ if (roc_start) { ++ if (chan_freq <= 2484) { ++ chan->band = NL80211_BAND_2GHZ; ++ } else { ++ chan->band = NL80211_BAND_5GHZ; ++ } ++ chan->center_freq = chan_freq; ++ chan->max_power = 18; ++ ret = rwnx_send_roc(priv, vif, chan, duration, &roc_cfm); ++ if (ret) { ++ printk("rwnx_send_roc fail: %d\n", ret); ++ } else { ++ printk("roc_cfm: opcode=%x, st=%d, idx=%d\n", roc_cfm.op_code, roc_cfm.status, roc_cfm.chan_ctxt_index); ++ } ++ } else { ++ ret = rwnx_send_cancel_roc(priv); ++ if (ret) { ++ printk("rwnx_send_cancel_roc fail: %d\n", ret); ++ } ++ } ++ } ++ ++ return count; ++} ++ ++DEBUGFS_WRITE_FILE_OPS(set_roc); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++#define LINE_MAX_SZ 150 ++ ++struct st { ++ char line[LINE_MAX_SZ + 1]; ++ unsigned int r_idx; ++}; ++ ++static int compare_idx(const void *st1, const void *st2) ++{ ++ int index1 = ((struct st *)st1)->r_idx; ++ int index2 = ((struct st *)st2)->r_idx; ++ ++ if (index1 > index2) ++ return 1; ++ if (index1 < index2) ++ return -1; ++ ++ return 0; ++} ++ ++static const int ru_size[] = { ++ 26, ++ 52, ++ 106, ++ 242, ++ 484, ++ 996 ++}; ++ ++static int print_rate(char *buf, int size, int format, int nss, int mcs, int bw, ++ int sgi, int pre, int *r_idx) ++{ ++ int res = 0; ++ int bitrates_cck[4] = { 10, 20, 55, 110 }; ++ int bitrates_ofdm[8] = { 6, 9, 12, 18, 24, 36, 48, 54}; ++ char he_gi[3][4] = {"0.8", "1.6", "3.2"}; ++ ++ if (format < FORMATMOD_HT_MF) { ++ if (mcs < 4) { ++ if (r_idx) { ++ *r_idx = (mcs * 2) + pre; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "L-CCK/%cP %2u.%1uM ", ++ pre > 0 ? 'L' : 'S', ++ bitrates_cck[mcs] / 10, ++ bitrates_cck[mcs] % 10); ++ } else { ++ mcs -= 4; ++ if (r_idx) { ++ *r_idx = N_CCK + mcs; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "L-OFDM %2u.0M ", ++ bitrates_ofdm[mcs]); ++ } ++ } else if (format < FORMATMOD_VHT) { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + nss * 32 + mcs * 4 + bw * 2 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ mcs += nss * 8; ++ res += scnprintf(&buf[res], size - res, "HT%d/%cGI MCS%-2d ", ++ 20 * (1 << bw), sgi ? 'S' : 'L', mcs); ++ } else if (format == FORMATMOD_VHT) { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + N_HT + nss * 80 + mcs * 8 + bw * 2 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "VHT%d/%cGI%*cMCS%d/%1d ", ++ 20 * (1 << bw), sgi ? 'S' : 'L', bw > 2 ? 5 : 6, ' ', ++ mcs, nss + 1); ++ } else if (format == FORMATMOD_HE_SU) { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + N_HT + N_VHT + nss * 144 + mcs * 12 + bw * 3 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "HE%d/GI%s%*cMCS%d/%1d%*c", ++ 20 * (1 << bw), he_gi[sgi], bw > 2 ? 4 : 5, ' ', ++ mcs, nss + 1, mcs > 9 ? 1 : 2, ' '); ++ } else { ++ if (r_idx) { ++ *r_idx = N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU + nss * 216 + mcs * 18 + bw * 3 + sgi; ++ res = scnprintf(buf, size - res, "%3d ", *r_idx); ++ } ++ res += scnprintf(&buf[res], size - res, "HEMU-%d/GI%s%*cMCS%d/%1d%*c", ++ ru_size[bw], he_gi[sgi], bw > 1 ? 1 : 2, ' ', ++ mcs, nss + 1, mcs > 9 ? 1 : 2, ' '); ++ ++ } ++ ++ return res; ++} ++ ++static int print_rate_from_cfg(char *buf, int size, u32 rate_config, int *r_idx, int ru_size) ++{ ++ union rwnx_rate_ctrl_info *r_cfg = (union rwnx_rate_ctrl_info *)&rate_config; ++ union rwnx_mcs_index *mcs_index = (union rwnx_mcs_index *)&rate_config; ++ unsigned int ft, pre, gi, bw, nss, mcs, len; ++ ++ ft = r_cfg->formatModTx; ++ pre = r_cfg->giAndPreTypeTx >> 1; ++ gi = r_cfg->giAndPreTypeTx; ++ bw = r_cfg->bwTx; ++ if (ft == FORMATMOD_HE_MU) { ++ mcs = mcs_index->he.mcs; ++ nss = mcs_index->he.nss; ++ bw = ru_size; ++ } else if (ft == FORMATMOD_HE_SU) { ++ mcs = mcs_index->he.mcs; ++ nss = mcs_index->he.nss; ++ } else if (ft == FORMATMOD_VHT) { ++ mcs = mcs_index->vht.mcs; ++ nss = mcs_index->vht.nss; ++ } else if (ft >= FORMATMOD_HT_MF) { ++ mcs = mcs_index->ht.mcs; ++ nss = mcs_index->ht.nss; ++ } else { ++ mcs = mcs_index->legacy; ++ nss = 0; ++ } ++ ++ len = print_rate(buf, size, ft, nss, mcs, bw, gi, pre, r_idx); ++ return len; ++} ++ ++static void idx_to_rate_cfg(int idx, union rwnx_rate_ctrl_info *r_cfg, int *ru_size) ++{ ++ r_cfg->value = 0; ++ if (idx < N_CCK) { ++ r_cfg->formatModTx = FORMATMOD_NON_HT; ++ r_cfg->giAndPreTypeTx = (idx & 1) << 1; ++ r_cfg->mcsIndexTx = idx / 2; ++ } else if (idx < (N_CCK + N_OFDM)) { ++ r_cfg->formatModTx = FORMATMOD_NON_HT; ++ r_cfg->mcsIndexTx = idx - N_CCK + 4; ++ } else if (idx < (N_CCK + N_OFDM + N_HT)) { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ idx -= (N_CCK + N_OFDM); ++ r_cfg->formatModTx = FORMATMOD_HT_MF; ++ r->ht.nss = idx / (8*2*2); ++ r->ht.mcs = (idx % (8*2*2)) / (2*2); ++ r_cfg->bwTx = ((idx % (8*2*2)) % (2*2)) / 2; ++ r_cfg->giAndPreTypeTx = idx & 1; ++ } else if (idx < (N_CCK + N_OFDM + N_HT + N_VHT)) { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ idx -= (N_CCK + N_OFDM + N_HT); ++ r_cfg->formatModTx = FORMATMOD_VHT; ++ r->vht.nss = idx / (10*4*2); ++ r->vht.mcs = (idx % (10*4*2)) / (4*2); ++ r_cfg->bwTx = ((idx % (10*4*2)) % (4*2)) / 2; ++ r_cfg->giAndPreTypeTx = idx & 1; ++ } else if (idx < (N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU)) { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ idx -= (N_CCK + N_OFDM + N_HT + N_VHT); ++ r_cfg->formatModTx = FORMATMOD_HE_SU; ++ r->vht.nss = idx / (12*4*3); ++ r->vht.mcs = (idx % (12*4*3)) / (4*3); ++ r_cfg->bwTx = ((idx % (12*4*3)) % (4*3)) / 3; ++ r_cfg->giAndPreTypeTx = idx % 3; ++ } else { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ BUG_ON(ru_size == NULL); ++ ++ idx -= (N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU); ++ r_cfg->formatModTx = FORMATMOD_HE_MU; ++ r->vht.nss = idx / (12*6*3); ++ r->vht.mcs = (idx % (12*6*3)) / (6*3); ++ *ru_size = ((idx % (12*6*3)) % (6*3)) / 3; ++ r_cfg->giAndPreTypeTx = idx % 3; ++ r_cfg->bwTx = 0; ++ } ++} ++ ++static void idx_to_rate_cfg1(unsigned int formatmod, ++ unsigned int mcs,unsigned int nss, ++ unsigned int bwTx,unsigned int gi, ++ union rwnx_rate_ctrl_info *r_cfg, int *ru_size) ++{ ++ r_cfg->value = 0; ++ ++ switch(formatmod){ ++ case FORMATMOD_NON_HT: ++ { ++ r_cfg->formatModTx = formatmod; ++ r_cfg->giAndPreTypeTx = 1; ++ r_cfg->mcsIndexTx = mcs; ++ break; ++ } ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ { ++ r_cfg->formatModTx = formatmod; ++ r_cfg->giAndPreTypeTx = gi; ++ r_cfg->mcsIndexTx = mcs; ++ break; ++ } ++ case FORMATMOD_HT_MF: ++ { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ r_cfg->formatModTx = formatmod; ++ r->ht.nss = nss; ++ r->ht.mcs = mcs; ++ r_cfg->bwTx = bwTx; ++ r_cfg->giAndPreTypeTx = gi; ++ break; ++ } ++ case FORMATMOD_VHT: ++ case FORMATMOD_HE_SU: ++ { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ r_cfg->formatModTx = formatmod; ++ r->vht.nss = nss; ++ r->vht.mcs = mcs; ++ r_cfg->bwTx = bwTx; ++ r_cfg->giAndPreTypeTx = gi; ++ break; ++ } ++ case FORMATMOD_HE_MU: ++ { ++ union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg; ++ ++ r_cfg->formatModTx = formatmod; ++ r->he.nss = nss; ++ r->he.mcs = mcs; ++ r_cfg->bwTx = 0; ++ r_cfg->giAndPreTypeTx = gi; ++ break; ++ } ++ default: ++ printk("Don't have the formatmod"); ++ } ++} ++ ++static ssize_t rwnx_dbgfs_rc_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ char *buf; ++ int bufsz, len = 0; ++ ssize_t read; ++ int i = 0; ++ int error = 0; ++ struct me_rc_stats_cfm me_rc_stats_cfm; ++ unsigned int no_samples; ++ struct st *st; ++ u8 mac[6]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* everything should fit in one call */ ++ if (*ppos) ++ return 0; ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ //if (mac == NULL) ++ // return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_me_rc_stats(priv, sta->sta_idx, &me_rc_stats_cfm); ++ if (error) ++ return error; ++ ++ no_samples = me_rc_stats_cfm.no_samples; ++ if (no_samples == 0) ++ return 0; ++ ++ bufsz = no_samples * LINE_MAX_SZ + 500; ++ ++ buf = kmalloc(bufsz + 1, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ st = kmalloc(sizeof(struct st) * no_samples, GFP_ATOMIC); ++ if (st == NULL) { ++ kfree(buf); ++ return 0; ++ } ++ ++ for (i = 0; i < no_samples; i++) { ++ unsigned int tp, eprob; ++ len = print_rate_from_cfg(st[i].line, LINE_MAX_SZ, ++ me_rc_stats_cfm.rate_stats[i].rate_config, ++ &st[i].r_idx, 0); ++ ++ if (me_rc_stats_cfm.sw_retry_step != 0) { ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c", ++ me_rc_stats_cfm.retry_step_idx[me_rc_stats_cfm.sw_retry_step] == i ? '*' : ' '); ++ } else { ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, " "); ++ } ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c", ++ me_rc_stats_cfm.retry_step_idx[0] == i ? 'T' : ' '); ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c", ++ me_rc_stats_cfm.retry_step_idx[1] == i ? 't' : ' '); ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, "%c ", ++ me_rc_stats_cfm.retry_step_idx[2] == i ? 'P' : ' '); ++ ++ tp = me_rc_stats_cfm.tp[i] / 10; ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, " %4u.%1u", ++ tp / 10, tp % 10); ++ ++ eprob = ((me_rc_stats_cfm.rate_stats[i].probability * 1000) >> 16) + 1; ++ len += scnprintf(&st[i].line[len], LINE_MAX_SZ - len, ++ " %4u.%1u %5u(%6u) %6u", ++ eprob / 10, eprob % 10, ++ me_rc_stats_cfm.rate_stats[i].success, ++ me_rc_stats_cfm.rate_stats[i].attempts, ++ me_rc_stats_cfm.rate_stats[i].sample_skipped); ++ } ++ len = scnprintf(buf, bufsz, ++ "\nTX rate info for %02X:%02X:%02X:%02X:%02X:%02X:\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ " # type rate tpt eprob ok( tot) skipped\n"); ++ ++ // add sorted statistics to the buffer ++ sort(st, no_samples, sizeof(st[0]), compare_idx, NULL); ++ for (i = 0; i < no_samples; i++) { ++ len += scnprintf(&buf[len], bufsz - len, "%s\n", st[i].line); ++ } ++ ++ // display HE TB statistics if any ++ if (me_rc_stats_cfm.rate_stats[RC_HE_STATS_IDX].rate_config != 0) { ++ unsigned int tp, eprob; ++ struct rc_rate_stats *rate_stats = &me_rc_stats_cfm.rate_stats[RC_HE_STATS_IDX]; ++ int ru_index = rate_stats->ru_and_length & 0x07; ++ int ul_length = rate_stats->ru_and_length >> 3; ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ "\nHE TB rate info:\n"); ++ ++ len += scnprintf(&buf[len], bufsz - len, ++ " type rate tpt eprob ok( tot) ul_length\n "); ++ len += print_rate_from_cfg(&buf[len], bufsz - len, rate_stats->rate_config, ++ NULL, ru_index); ++ ++ tp = me_rc_stats_cfm.tp[RC_HE_STATS_IDX] / 10; ++ len += scnprintf(&buf[len], bufsz - len, " %4u.%1u", ++ tp / 10, tp % 10); ++ ++ eprob = ((rate_stats->probability * 1000) >> 16) + 1; ++ len += scnprintf(&buf[len], bufsz - len, ++ " %4u.%1u %5u(%6u) %6u\n", ++ eprob / 10, eprob % 10, ++ rate_stats->success, ++ rate_stats->attempts, ++ ul_length); ++ } ++ ++ len += scnprintf(&buf[len], bufsz - len, "\n MPDUs AMPDUs AvLen trialP"); ++ len += scnprintf(&buf[len], bufsz - len, "\n%6u %6u %3d.%1d %6u\n", ++ me_rc_stats_cfm.ampdu_len, ++ me_rc_stats_cfm.ampdu_packets, ++ me_rc_stats_cfm.avg_ampdu_len >> 16, ++ ((me_rc_stats_cfm.avg_ampdu_len * 10) >> 16) % 10, ++ me_rc_stats_cfm.sample_wait); ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ kfree(st); ++ ++ return read; ++} ++ ++DEBUGFS_READ_FILE_OPS(rc_stats); ++ ++static ssize_t rwnx_dbgfs_rc_fixed_rate_idx_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ u8 mac[6]; ++ char buf[20]; ++ int fixed_rate_idx = 1; ++ unsigned int formatmod, mcs, nss, bwTx, gi; ++ union rwnx_rate_ctrl_info rate_config; ++ union rwnx_rate_ctrl_info *r_cfg=&rate_config; ++ int error = 0; ++ size_t len = min_t(size_t, count, sizeof(buf) - 1); ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ //if (mac == NULL) ++ // return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ /* Get the content of the file */ ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ //sscanf(buf, "%i\n", &fixed_rate_idx); ++ sscanf(buf, "%u %u %u %u %u",&formatmod, &mcs, &nss, &bwTx, &gi); ++ printk("%u %u %u %u %u\n",formatmod, mcs, nss, bwTx, gi); ++ ++ if((formatmod > 6) || (mcs > 11) || (nss > 8) || (bwTx > 6) || (gi > 3)){ ++ printk("error parameter"); ++ return len; ++ } ++ ++ /* Convert rate index into rate configuration */ ++ if ((fixed_rate_idx < 0) || (fixed_rate_idx >= (N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU))) ++ { ++ // disable fixed rate ++ rate_config.value = (u32)-1; ++ } ++ else ++ { ++ //idx_to_rate_cfg(fixed_rate_idx, &rate_config, NULL); ++ idx_to_rate_cfg1(formatmod, mcs, nss, bwTx, gi, &rate_config, NULL); ++ } ++ ++ printk("formatModTx=%u mcsIndexTx=%u bwTx=%u giAndPreTypeTx=%u\n",r_cfg->formatModTx,r_cfg->mcsIndexTx,r_cfg->bwTx,r_cfg->giAndPreTypeTx); ++ // Forward the request to the LMAC ++ if ((error = rwnx_send_me_rc_set_rate(priv, sta->sta_idx, ++ (u16)rate_config.value)) != 0) ++ { ++ return error; ++ } ++ ++ printk("send success \n"); ++ priv->debugfs.rc_config[sta->sta_idx] = (int)rate_config.value; ++ return len; ++ ++} ++ ++DEBUGFS_WRITE_FILE_OPS(rc_fixed_rate_idx); ++ ++static ssize_t rwnx_dbgfs_last_rx_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ struct rwnx_rx_rate_stats *rate_stats; ++ char *buf; ++ int bufsz, i, len = 0; ++ ssize_t read; ++ unsigned int fmt, pre, bw, nss, mcs, gi; ++ u8 mac[6]; ++ struct rx_vector_1 *last_rx; ++ char hist[] = "##################################################"; ++ int hist_len = sizeof(hist) - 1; ++ u8 nrx; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* everything should fit in one call */ ++ if (*ppos) ++ return 0; ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++// if (mac == NULL) ++// return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ rate_stats = &sta->stats.rx_rate; ++ bufsz = (rate_stats->rate_cnt * (50 + hist_len) + 200); ++ buf = kmalloc(bufsz + 1, GFP_ATOMIC); ++ if (buf == NULL) ++ return 0; ++ ++ // Get number of RX paths ++ nrx = (priv->version_cfm.version_phy_1 & MDM_NRX_MASK) >> MDM_NRX_LSB; ++ ++ len += scnprintf(buf, bufsz, ++ "\nRX rate info for %02X:%02X:%02X:%02X:%02X:%02X:\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ ++ // Display Statistics ++ for (i = 0; i < rate_stats->size; i++) { ++ if (rate_stats->table[i]) { ++ union rwnx_rate_ctrl_info rate_config; ++ int percent = (rate_stats->table[i] * 1000) / rate_stats->cpt; ++ int p = 0; ++ int ru_size = 0; ++ ++ idx_to_rate_cfg(i, &rate_config, &ru_size); ++ len += print_rate_from_cfg(&buf[len], bufsz - len, ++ rate_config.value, NULL, ru_size); ++ p = (percent * hist_len) / 1000; ++ len += scnprintf(&buf[len], bufsz - len, ": %6d(%3d.%1d%%)%.*s\n", ++ rate_stats->table[i], ++ percent / 10, percent % 10, p, hist); ++ } ++ } ++ ++ // Display detailed info of the last received rate ++ last_rx = &sta->stats.last_rx.rx_vect1; ++ ++ len += scnprintf(&buf[len], bufsz - len, "\nLast received rate\n" ++ " type rate LDPC STBC BEAMFM DCM DOPPLER %s\n", ++ (nrx > 1) ? "rssi1(dBm) rssi2(dBm)" : "rssi(dBm)"); ++ ++ fmt = last_rx->format_mod; ++ bw = last_rx->ch_bw; ++ pre = last_rx->pre_type; ++ if (fmt >= FORMATMOD_HE_SU) { ++ mcs = last_rx->he.mcs; ++ nss = last_rx->he.nss; ++ gi = last_rx->he.gi_type; ++ if (fmt == FORMATMOD_HE_MU) ++ bw = last_rx->he.ru_size; ++ } else if (fmt == FORMATMOD_VHT) { ++ mcs = last_rx->vht.mcs; ++ nss = last_rx->vht.nss; ++ gi = last_rx->vht.short_gi; ++ } else if (fmt >= FORMATMOD_HT_MF) { ++ mcs = last_rx->ht.mcs % 8; ++ nss = last_rx->ht.mcs / 8;; ++ gi = last_rx->ht.short_gi; ++ } else { ++ BUG_ON((mcs = legrates_lut[last_rx->leg_rate].idx) == -1); ++ nss = 0; ++ gi = 0; ++ } ++ ++ len += print_rate(&buf[len], bufsz - len, fmt, nss, mcs, bw, gi, pre, NULL); ++ ++ /* flags for HT/VHT/HE */ ++ if (fmt >= FORMATMOD_HE_SU) { ++ len += scnprintf(&buf[len], bufsz - len, " %c %c %c %c %c", ++ last_rx->he.fec ? 'L' : ' ', ++ last_rx->he.stbc ? 'S' : ' ', ++ last_rx->he.beamformed ? 'B' : ' ', ++ last_rx->he.dcm ? 'D' : ' ', ++ last_rx->he.doppler ? 'D' : ' '); ++ } else if (fmt == FORMATMOD_VHT) { ++ len += scnprintf(&buf[len], bufsz - len, " %c %c %c ", ++ last_rx->vht.fec ? 'L' : ' ', ++ last_rx->vht.stbc ? 'S' : ' ', ++ last_rx->vht.beamformed ? 'B' : ' '); ++ } else if (fmt >= FORMATMOD_HT_MF) { ++ len += scnprintf(&buf[len], bufsz - len, " %c %c ", ++ last_rx->ht.fec ? 'L' : ' ', ++ last_rx->ht.stbc ? 'S' : ' '); ++ } else { ++ len += scnprintf(&buf[len], bufsz - len, " "); ++ } ++ if (nrx > 1) { ++ len += scnprintf(&buf[len], bufsz - len, " %-4d %d\n", ++ last_rx->rssi1, last_rx->rssi1); ++ } else { ++ len += scnprintf(&buf[len], bufsz - len, " %d\n", last_rx->rssi1); ++ } ++ ++ read = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ return read; ++} ++ ++static ssize_t rwnx_dbgfs_last_rx_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_hw *priv = file->private_data; ++ u8 mac[6]; ++ ++ /* Get the station index from MAC address */ ++ sscanf(file->f_path.dentry->d_parent->d_iname, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++// if (mac == NULL) ++// return 0; ++ sta = rwnx_get_sta(priv, mac); ++ if (sta == NULL) ++ return 0; ++ ++ /* Prevent from interrupt preemption as these statistics are updated under ++ * interrupt */ ++ spin_lock_bh(&priv->tx_lock); ++ memset(sta->stats.rx_rate.table, 0, ++ sta->stats.rx_rate.size * sizeof(sta->stats.rx_rate.table[0])); ++ sta->stats.rx_rate.cpt = 0; ++ sta->stats.rx_rate.rate_cnt = 0; ++ spin_unlock_bh(&priv->tx_lock); ++ ++ return count; ++} ++ ++DEBUGFS_READ_WRITE_FILE_OPS(last_rx); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static void rwnx_rc_stat_work(struct work_struct *ws) ++{ ++ struct rwnx_debugfs *rwnx_debugfs = container_of(ws, struct rwnx_debugfs, ++ rc_stat_work); ++ struct rwnx_hw *rwnx_hw = container_of(rwnx_debugfs, struct rwnx_hw, ++ debugfs); ++ struct rwnx_sta *sta; ++ uint8_t ridx, sta_idx; ++ ++ ridx = rwnx_debugfs->rc_read; ++ sta_idx = rwnx_debugfs->rc_sta[ridx]; ++ if (sta_idx > (NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX)) { ++ WARN(1, "Invalid sta index %d", sta_idx); ++ return; ++ } ++ ++ rwnx_debugfs->rc_sta[ridx] = 0xFF; ++ ridx = (ridx + 1) % ARRAY_SIZE(rwnx_debugfs->rc_sta); ++ rwnx_debugfs->rc_read = ridx; ++ sta = &rwnx_hw->sta_table[sta_idx]; ++ if (!sta) { ++ WARN(1, "Invalid sta %d", sta_idx); ++ return; ++ } ++ ++ if (rwnx_debugfs->dir_sta[sta_idx] == NULL) { ++ /* register the sta */ ++ struct dentry *dir_rc = rwnx_debugfs->dir_rc; ++ struct dentry *dir_sta; ++ struct dentry *file; ++ char sta_name[18]; ++ struct rwnx_rx_rate_stats *rate_stats = &sta->stats.rx_rate; ++ int nb_rx_rate = N_CCK + N_OFDM; ++ struct rwnx_rc_config_save *rc_cfg, *next; ++ ++ if (sta->sta_idx >= NX_REMOTE_STA_MAX) { ++ scnprintf(sta_name, sizeof(sta_name), "bc_mc"); ++ } else { ++ scnprintf(sta_name, sizeof(sta_name), "%pM", sta->mac_addr); ++ } ++ ++ dir_sta = debugfs_create_dir(sta_name, dir_rc); ++ if (!dir_sta) ++ goto error; ++ ++ rwnx_debugfs->dir_sta[sta->sta_idx] = dir_sta; ++ ++ file = debugfs_create_file("stats", S_IRUSR, dir_sta, rwnx_hw, ++ &rwnx_dbgfs_rc_stats_ops); ++ if (IS_ERR_OR_NULL(file)) ++ goto error_after_dir; ++ ++ file = debugfs_create_file("fixed_rate_idx", S_IWUSR, dir_sta, rwnx_hw, ++ &rwnx_dbgfs_rc_fixed_rate_idx_ops); ++ if (IS_ERR_OR_NULL(file)) ++ goto error_after_dir; ++ ++ file = debugfs_create_file("rx_rate", S_IRUSR | S_IWUSR, dir_sta, rwnx_hw, ++ &rwnx_dbgfs_last_rx_ops); ++ if (IS_ERR_OR_NULL(file)) ++ goto error_after_dir; ++ ++ if (rwnx_hw->mod_params->ht_on) ++ nb_rx_rate += N_HT; ++ ++ if (rwnx_hw->mod_params->vht_on) ++ nb_rx_rate += N_VHT; ++ ++ if (rwnx_hw->mod_params->he_on) ++ nb_rx_rate += N_HE_SU + N_HE_MU; ++ ++ rate_stats->table = kzalloc(nb_rx_rate * sizeof(rate_stats->table[0]), ++ GFP_KERNEL); ++ if (!rate_stats->table) ++ goto error_after_dir; ++ ++ rate_stats->size = nb_rx_rate; ++ rate_stats->cpt = 0; ++ rate_stats->rate_cnt = 0; ++ ++ /* By default enable rate contoller */ ++ rwnx_debugfs->rc_config[sta_idx] = -1; ++ ++ /* Unless we already fix the rate for this station */ ++ list_for_each_entry_safe(rc_cfg, next, &rwnx_debugfs->rc_config_save, list) { ++ if (jiffies_to_msecs(jiffies - rc_cfg->timestamp) > RC_CONFIG_DUR) { ++ list_del(&rc_cfg->list); ++ kfree(rc_cfg); ++ } else if (!memcmp(rc_cfg->mac_addr, sta->mac_addr, ETH_ALEN)) { ++ rwnx_debugfs->rc_config[sta_idx] = rc_cfg->rate; ++ list_del(&rc_cfg->list); ++ kfree(rc_cfg); ++ break; ++ } ++ } ++ ++ if ((rwnx_debugfs->rc_config[sta_idx] >= 0) && ++ rwnx_send_me_rc_set_rate(rwnx_hw, sta_idx, ++ (u16)rwnx_debugfs->rc_config[sta_idx])) ++ rwnx_debugfs->rc_config[sta_idx] = -1; ++ ++ } else { ++ /* unregister the sta */ ++ if (sta->stats.rx_rate.table) { ++ kfree(sta->stats.rx_rate.table); ++ sta->stats.rx_rate.table = NULL; ++ } ++ sta->stats.rx_rate.size = 0; ++ sta->stats.rx_rate.cpt = 0; ++ sta->stats.rx_rate.rate_cnt = 0; ++ ++ /* If fix rate was set for this station, save the configuration in case ++ we reconnect to this station within RC_CONFIG_DUR msec */ ++ if (rwnx_debugfs->rc_config[sta_idx] >= 0) { ++ struct rwnx_rc_config_save *rc_cfg; ++ rc_cfg = kmalloc(sizeof(*rc_cfg), GFP_KERNEL); ++ if (rc_cfg) { ++ rc_cfg->rate = rwnx_debugfs->rc_config[sta_idx]; ++ rc_cfg->timestamp = jiffies; ++ memcpy(rc_cfg->mac_addr, sta->mac_addr, ETH_ALEN); ++ list_add_tail(&rc_cfg->list, &rwnx_debugfs->rc_config_save); ++ } ++ } ++ ++ debugfs_remove_recursive(rwnx_debugfs->dir_sta[sta_idx]); ++ rwnx_debugfs->dir_sta[sta->sta_idx] = NULL; ++ } ++ ++ return; ++ ++error_after_dir: ++ debugfs_remove_recursive(rwnx_debugfs->dir_sta[sta_idx]); ++ rwnx_debugfs->dir_sta[sta->sta_idx] = NULL; ++error: ++ dev_err(rwnx_hw->dev, ++ "Error while (un)registering debug entry for sta %d\n", sta_idx); ++} ++ ++void _rwnx_dbgfs_rc_stat_write(struct rwnx_debugfs *rwnx_debugfs, uint8_t sta_idx) ++{ ++ uint8_t widx = rwnx_debugfs->rc_write; ++ if (rwnx_debugfs->rc_sta[widx] != 0XFF) { ++ WARN(1, "Overlap in debugfs rc_sta table\n"); ++ } ++ ++ if (rwnx_debugfs->unregistering) ++ return; ++ ++ rwnx_debugfs->rc_sta[widx] = sta_idx; ++ widx = (widx + 1) % ARRAY_SIZE(rwnx_debugfs->rc_sta); ++ rwnx_debugfs->rc_write = widx; ++ ++ schedule_work(&rwnx_debugfs->rc_stat_work); ++} ++ ++void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{ ++ _rwnx_dbgfs_rc_stat_write(&rwnx_hw->debugfs, sta->sta_idx); ++} ++ ++void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{ ++ _rwnx_dbgfs_rc_stat_write(&rwnx_hw->debugfs, sta->sta_idx); ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct dentry *phyd = rwnx_hw->wiphy->debugfsdir; ++ struct dentry *dir_rc; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ struct rwnx_debugfs *rwnx_debugfs = &rwnx_hw->debugfs; ++ struct dentry *dir_drv, *dir_diags; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ dir_drv = debugfs_create_dir(name, phyd); ++ if (!dir_drv) ++ return -ENOMEM; ++ ++ rwnx_debugfs->dir = dir_drv; ++ rwnx_debugfs->unregistering = false; ++ ++ dir_diags = debugfs_create_dir("diags", dir_drv); ++ if (!dir_diags) ++ goto err; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ dir_rc = debugfs_create_dir("rc", dir_drv); ++ if (!dir_rc) ++ goto err; ++ rwnx_debugfs->dir_rc = dir_rc; ++ INIT_WORK(&rwnx_debugfs->rc_stat_work, rwnx_rc_stat_work); ++ INIT_LIST_HEAD(&rwnx_debugfs->rc_config_save); ++ rwnx_debugfs->rc_write = rwnx_debugfs->rc_read = 0; ++ memset(rwnx_debugfs->rc_sta, 0xFF, sizeof(rwnx_debugfs->rc_sta)); ++#endif ++ ++ DEBUGFS_ADD_U32(tcp_pacing_shift, dir_drv, &rwnx_hw->tcp_pacing_shift, ++ S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(stats, dir_drv, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(sys_stats, dir_drv, S_IRUSR); ++ DEBUGFS_ADD_FILE(txq, dir_drv, S_IRUSR); ++ DEBUGFS_ADD_FILE(acsinfo, dir_drv, S_IRUSR); ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ DEBUGFS_ADD_FILE(mu_group, dir_drv, S_IRUSR); ++#endif ++ DEBUGFS_ADD_FILE(regdbg, dir_drv, S_IWUSR); ++ DEBUGFS_ADD_FILE(vendor_hwconfig, dir_drv,S_IWUSR); ++ DEBUGFS_ADD_FILE(vendor_swconfig, dir_drv,S_IWUSR); ++ DEBUGFS_ADD_FILE(agg_disable, dir_drv,S_IWUSR); ++ DEBUGFS_ADD_FILE(set_roc, dir_drv,S_IWUSR); ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++ { ++ /* Create a p2p directory */ ++ struct dentry *dir_p2p; ++ dir_p2p = debugfs_create_dir("p2p", dir_drv); ++ if (!dir_p2p) ++ goto err; ++ ++ /* Add file allowing to control Opportunistic PS */ ++ DEBUGFS_ADD_FILE(oppps, dir_p2p, S_IRUSR); ++ /* Add file allowing to control Notice of Absence */ ++ DEBUGFS_ADD_FILE(noa, dir_p2p, S_IRUSR); ++ } ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++ if (rwnx_hw->fwlog_en) { ++ rwnx_fw_log_init(&rwnx_hw->debugfs.fw_log); ++ DEBUGFS_ADD_FILE(fw_log, dir_drv, S_IWUSR | S_IRUSR); ++ } ++#ifdef CONFIG_RWNX_RADAR ++ { ++ struct dentry *dir_radar, *dir_sec; ++ dir_radar = debugfs_create_dir("radar", dir_drv); ++ if (!dir_radar) ++ goto err; ++ ++ DEBUGFS_ADD_FILE(pulses_prim, dir_radar, S_IRUSR); ++ DEBUGFS_ADD_FILE(detected, dir_radar, S_IRUSR); ++ DEBUGFS_ADD_FILE(enable, dir_radar, S_IRUSR); ++ ++ if (rwnx_hw->phy.cnt == 2) { ++ DEBUGFS_ADD_FILE(pulses_sec, dir_radar, S_IRUSR); ++ ++ dir_sec = debugfs_create_dir("sec", dir_radar); ++ if (!dir_sec) ++ goto err; ++ ++ DEBUGFS_ADD_FILE(band, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(type, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(prim20, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(center1, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(center2, dir_sec, S_IWUSR | S_IRUSR); ++ DEBUGFS_ADD_FILE(set, dir_sec, S_IWUSR | S_IRUSR); ++ } ++ } ++#endif /* CONFIG_RWNX_RADAR */ ++ return 0; ++ ++err: ++ rwnx_dbgfs_unregister(rwnx_hw); ++ return -ENOMEM; ++} ++ ++void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_debugfs *rwnx_debugfs = &rwnx_hw->debugfs; ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_rc_config_save *cfg, *next; ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ list_for_each_entry_safe(cfg, next, &rwnx_debugfs->rc_config_save, list) { ++ list_del(&cfg->list); ++ kfree(cfg); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (rwnx_hw->fwlog_en) ++ rwnx_fw_log_deinit(&rwnx_hw->debugfs.fw_log); ++ ++ if (!rwnx_hw->debugfs.dir) ++ return; ++ ++ rwnx_debugfs->unregistering = true; ++#ifdef CONFIG_RWNX_FULLMAC ++ flush_work(&rwnx_debugfs->rc_stat_work); ++#endif ++ debugfs_remove_recursive(rwnx_hw->debugfs.dir); ++ rwnx_hw->debugfs.dir = NULL; ++} ++ ++#endif /* CONFIG_DEBUG_FS */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h +new file mode 100644 +index 000000000000..7f5c7c9c575d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h +@@ -0,0 +1,202 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_debugfs.h ++ * ++ * @brief Miscellaneous utility function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++ ++#ifndef _RWNX_DEBUGFS_H_ ++#define _RWNX_DEBUGFS_H_ ++#include ++ ++#include ++#include ++#include "rwnx_fw_trace.h" ++ ++struct rwnx_hw; ++struct rwnx_sta; ++ ++/* some macros taken from iwlwifi */ ++/* TODO: replace with generic read and fill read buffer in open to avoid double ++ * reads */ ++#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ ++ if (!debugfs_create_file(#name, mode, parent, rwnx_hw, \ ++ &rwnx_dbgfs_##name##_ops)) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_X64(name, parent, ptr) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_x64(#name, S_IWUSR | S_IRUSR, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_U64(name, parent, ptr, mode) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_u64(#name, mode, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++} while (0) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) ++#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ ++ debugfs_create_u32(#name, mode, \ ++ parent, ptr); \ ++} while (0) ++#else ++#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ ++ struct dentry *__tmp; \ ++ __tmp = debugfs_create_u32(#name, mode, \ ++ parent, ptr); \ ++ if (IS_ERR(__tmp) || !__tmp) \ ++ goto err; \ ++ } while (0) ++#endif ++ ++ ++ ++/* file operation */ ++#define DEBUGFS_READ_FUNC(name) \ ++ static ssize_t rwnx_dbgfs_##name##_read(struct file *file, \ ++ char __user *user_buf, \ ++ size_t count, loff_t *ppos); ++ ++#define DEBUGFS_WRITE_FUNC(name) \ ++ static ssize_t rwnx_dbgfs_##name##_write(struct file *file, \ ++ const char __user *user_buf,\ ++ size_t count, loff_t *ppos); ++ ++#define DEBUGFS_OPEN_FUNC(name) \ ++ static int rwnx_dbgfs_##name##_open(struct inode *inode, \ ++ struct file *file); ++ ++#define DEBUGFS_RELEASE_FUNC(name) \ ++ static int rwnx_dbgfs_##name##_release(struct inode *inode, \ ++ struct file *file); ++ ++#define DEBUGFS_READ_FILE_OPS(name) \ ++ DEBUGFS_READ_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .read = rwnx_dbgfs_##name##_read, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++#define DEBUGFS_WRITE_FILE_OPS(name) \ ++ DEBUGFS_WRITE_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .write = rwnx_dbgfs_##name##_write, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ ++ DEBUGFS_READ_FUNC(name); \ ++ DEBUGFS_WRITE_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .write = rwnx_dbgfs_##name##_write, \ ++ .read = rwnx_dbgfs_##name##_read, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++#define DEBUGFS_READ_WRITE_OPEN_RELEASE_FILE_OPS(name) \ ++ DEBUGFS_READ_FUNC(name); \ ++ DEBUGFS_WRITE_FUNC(name); \ ++ DEBUGFS_OPEN_FUNC(name); \ ++ DEBUGFS_RELEASE_FUNC(name); \ ++static const struct file_operations rwnx_dbgfs_##name##_ops = { \ ++ .write = rwnx_dbgfs_##name##_write, \ ++ .read = rwnx_dbgfs_##name##_read, \ ++ .open = rwnx_dbgfs_##name##_open, \ ++ .release = rwnx_dbgfs_##name##_release, \ ++ .llseek = generic_file_llseek, \ ++}; ++ ++ ++#ifdef CONFIG_RWNX_DEBUGFS ++ ++struct rwnx_debugfs { ++ unsigned long long rateidx; ++ struct dentry *dir; ++ bool trace_prst; ++ ++ char helper_cmd[64]; ++ //struct work_struct helper_work; ++ bool helper_scheduled; ++ spinlock_t umh_lock; ++ bool unregistering; ++ ++#ifndef CONFIG_RWNX_FHOST ++ struct rwnx_fw_log fw_log; ++#endif /* CONFIG_RWNX_FHOST */ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct work_struct rc_stat_work; ++ uint8_t rc_sta[NX_REMOTE_STA_MAX]; ++ uint8_t rc_write; ++ uint8_t rc_read; ++ struct dentry *dir_rc; ++ struct dentry *dir_sta[NX_REMOTE_STA_MAX]; ++ int rc_config[NX_REMOTE_STA_MAX]; ++ struct list_head rc_config_save; ++#endif ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++// Max duration in msecs to save rate config for a sta after disconnection ++#define RC_CONFIG_DUR 600000 ++ ++struct rwnx_rc_config_save { ++ struct list_head list; ++ unsigned long timestamp; ++ int rate; ++ u8 mac_addr[ETH_ALEN]; ++}; ++#endif ++ ++int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name); ++void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw); ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); ++void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); ++#endif ++#else ++struct rwnx_debugfs { ++}; ++static inline int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name) { return 0; } ++static inline void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw) {} ++#ifdef CONFIG_RWNX_FULLMAC ++static inline void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {} ++static inline void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {} ++#endif ++#endif /* CONFIG_RWNX_DEBUGFS */ ++ ++ ++#endif /* _RWNX_DEBUGFS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h +new file mode 100644 +index 000000000000..55e532bcbf8c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h +@@ -0,0 +1,769 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_defs.h ++ * ++ * @brief Main driver structure declarations for fullmac driver ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_DEFS_H_ ++#define _RWNX_DEFS_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rwnx_mod_params.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_tx.h" ++#include "rwnx_rx.h" ++#include "rwnx_radar.h" ++#include "rwnx_utils.h" ++#include "rwnx_mu_group.h" ++#include "rwnx_platform.h" ++#include "rwnx_cmds.h" ++#ifdef CONFIG_GKI ++#include "rwnx_gki.h" ++#endif ++#include "rwnx_compat.h" ++#ifdef CONFIG_FILTER_TCP_ACK ++#include "aicwf_tcp_ack.h" ++#endif ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#include "sdio_host.h" ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++#include "usb_host.h" ++#endif ++ ++#ifdef CONFIG_BR_SUPPORT ++#include "aic_br_ext.h" ++#endif /* CONFIG_BR_SUPPORT */ ++ ++#define WPI_HDR_LEN 18 ++#define WPI_PN_LEN 16 ++#define WPI_PN_OFST 2 ++#define WPI_MIC_LEN 16 ++#define WPI_KEY_LEN 32 ++#define WPI_SUBKEY_LEN 16 // WPI key is actually two 16bytes key ++ ++#define LEGACY_PS_ID 0 ++#define UAPSD_ID 1 ++ ++#define PS_SP_INTERRUPTED 255 ++#define MAC_ADDR_LEN 6 ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++enum nl80211_ac { ++ NL80211_AC_VO, ++ NL80211_AC_VI, ++ NL80211_AC_BE, ++ NL80211_AC_BK, ++ NL80211_NUM_ACS ++}; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++struct ieee80211_vht_operation { ++ u8 vht_op_info_chwidth; ++ u8 vht_op_info_chan_center_freq_seg1_idx; ++ u8 vht_op_info_chan_center_freq_seg2_idx; ++ __le16 vht_basic_mcs_set; ++} __packed; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++#define IEEE80211_RADIOTAP_VHT 21 ++#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004 ++#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040 ++ ++#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01 ++#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04 ++ ++#define NL80211_FEATURE_CELL_BASE_REG_HINTS 1 << 3 ++#define NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL 1 << 4 ++#define NL80211_FEATURE_SAE 1 << 5 ++#define NL80211_FEATURE_LOW_PRIORITY_SCAN 1 << 6 ++#define NL80211_FEATURE_SCAN_FLUSH 1 << 7 ++#define NL80211_FEATURE_AP_SCAN 1 << 8 ++#define NL80211_FEATURE_VIF_TXPOWER 1 << 9 ++#define NL80211_FEATURE_NEED_OBSS_SCAN 1 << 10 ++#define NL80211_FEATURE_P2P_GO_CTWIN 1 << 11 ++#define NL80211_FEATURE_P2P_GO_OPPPS 1 << 12 ++ ++/* 802.11ac VHT Capabilities */ ++#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 ++#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 ++#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 ++#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 ++#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 ++#define IEEE80211_VHT_CAP_RXLDPC 0x00000010 ++#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 ++#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 ++#define IEEE80211_VHT_CAP_TXSTBC 0x00000080 ++#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 ++#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 ++#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 ++#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 ++#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 ++#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 ++#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 ++#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000 ++#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 ++#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 ++#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 ++#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 ++#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23 ++#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \ ++ (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT) ++#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 ++#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 ++#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 ++#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 ++ ++enum ieee80211_vht_mcs_support { ++ IEEE80211_VHT_MCS_SUPPORT_0_7 = 0, ++ IEEE80211_VHT_MCS_SUPPORT_0_8 = 1, ++ IEEE80211_VHT_MCS_SUPPORT_0_9 = 2, ++ IEEE80211_VHT_MCS_NOT_SUPPORTED = 3, ++}; ++ ++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, ++}; ++ ++struct cfg80211_chan_def { ++ struct ieee80211_channel *chan; ++ enum nl80211_chan_width width; ++ u32 center_freq1; ++ u32 center_freq2; ++}; ++ ++enum nl80211_mesh_power_mode { ++ NL80211_MESH_POWER_UNKNOWN, ++ NL80211_MESH_POWER_ACTIVE, ++ NL80211_MESH_POWER_LIGHT_SLEEP, ++ NL80211_MESH_POWER_DEEP_SLEEP, ++ __NL80211_MESH_POWER_AFTER_LAST, ++ NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1 ++}; ++#endif ++ ++/** ++ * struct rwnx_bcn - Information of the beacon in used (AP mode) ++ * ++ * @head: head portion of beacon (before TIM IE) ++ * @tail: tail portion of beacon (after TIM IE) ++ * @ies: extra IEs (not used ?) ++ * @head_len: length of head data ++ * @tail_len: length of tail data ++ * @ies_len: length of extra IEs data ++ * @tim_len: length of TIM IE ++ * @len: Total beacon len (head + tim + tail + extra) ++ * @dtim: dtim period ++ */ ++struct rwnx_bcn { ++ u8 *head; ++ u8 *tail; ++ u8 *ies; ++ size_t head_len; ++ size_t tail_len; ++ size_t ies_len; ++ size_t tim_len; ++ size_t len; ++ u8 dtim; ++}; ++ ++/** ++ * struct rwnx_key - Key information ++ * ++ * @hw_idx: Idx of the key from hardware point of view ++ */ ++struct rwnx_key { ++ u8 hw_idx; ++}; ++ ++/** ++ * Structure containing information about a Mesh Path ++ */ ++struct rwnx_mesh_path { ++ struct list_head list; /* For rwnx_vif.mesh_paths */ ++ u8 path_idx; /* Path Index */ ++ struct mac_addr tgt_mac_addr; /* Target MAC Address */ ++ struct rwnx_sta *p_nhop_sta; /* Pointer to the Next Hop STA */ ++}; ++ ++struct rwnx_mesh_proxy { ++ struct list_head list; /* For rwnx_vif.mesh_proxy */ ++ struct mac_addr ext_sta_addr; /* Address of the External STA */ ++ struct mac_addr proxy_addr; /* Proxy MAC Address */ ++ bool local; /* Indicate if interface is a proxy for the device */ ++}; ++ ++/** ++ * struct rwnx_csa - Information for CSA (Channel Switch Announcement) ++ * ++ * @vif: Pointer to the vif doing the CSA ++ * @bcn: Beacon to use after CSA ++ * @elem: IPC buffer to send the new beacon to the fw ++ * @chandef: defines the channel to use after the switch ++ * @count: Current csa counter ++ * @status: Status of the CSA at fw level ++ * @ch_idx: Index of the new channel context ++ * @work: work scheduled at the end of CSA ++ */ ++struct rwnx_csa { ++ struct rwnx_vif *vif; ++ struct rwnx_bcn bcn; ++ struct rwnx_ipc_elem_var elem; ++ struct cfg80211_chan_def chandef; ++ int count; ++ int status; ++ int ch_idx; ++ struct work_struct work; ++}; ++ ++struct apm_probe_sta { ++ u8 sta_mac_addr[6]; ++ u8 vif_idx; ++ u64 probe_id; ++ struct work_struct apmprobestaWork; ++ struct workqueue_struct *apmprobesta_wq; ++}; ++/// Possible States of the TDLS link. ++enum tdls_status_tag { ++ /// TDLS link is not active (no TDLS peer connected) ++ TDLS_LINK_IDLE, ++ /// TDLS Setup Request transmitted ++ TDLS_SETUP_REQ_TX, ++ /// TDLS Setup Response transmitted ++ TDLS_SETUP_RSP_TX, ++ /// TDLS link is active (TDLS peer connected) ++ TDLS_LINK_ACTIVE, ++ /// TDLS Max Number of states. ++ TDLS_STATE_MAX ++}; ++ ++/* ++ * Structure used to save information relative to the TDLS peer. ++ * This is also linked within the rwnx_hw vifs list. ++ * ++ */ ++struct rwnx_tdls { ++ bool active; /* Indicate if TDLS link is active */ ++ bool initiator; /* Indicate if TDLS peer is the TDLS initiator */ ++ bool chsw_en; /* Indicate if channel switch is enabled */ ++ u8 last_tid; /* TID of the latest MPDU transmitted over the ++ TDLS direct link to the TDLS STA */ ++ u16 last_sn; /* Sequence number of the latest MPDU transmitted ++ over the TDLS direct link to the TDLS STA */ ++ bool ps_on; /* Indicate if the power save is enabled on the ++ TDLS STA */ ++ bool chsw_allowed; /* Indicate if TDLS channel switch is allowed */ ++}; ++ ++ ++/** ++ * enum rwnx_ap_flags - AP flags ++ * ++ * @RWNX_AP_ISOLATE Isolate clients (i.e. Don't brige packets transmitted by ++ * one client for another one) ++ */ ++enum rwnx_ap_flags { ++ RWNX_AP_ISOLATE = BIT(0), ++}; ++ ++/* ++ * Structure used to save information relative to the managed interfaces. ++ * This is also linked within the rwnx_hw vifs list. ++ * ++ */ ++struct rwnx_vif { ++ struct list_head list; ++ struct rwnx_hw *rwnx_hw; ++ struct wireless_dev wdev; ++ struct net_device *ndev; ++ struct net_device_stats net_stats; ++ struct rwnx_key key[6]; ++ unsigned long drv_flags; ++ atomic_t drv_conn_state; ++ u8 drv_vif_index; /* Identifier of the VIF in driver */ ++ u8 vif_index; /* Identifier of the station in FW */ ++ u8 ch_index; /* Channel context identifier */ ++ bool up; /* Indicate if associated netdev is up ++ (i.e. Interface is created at fw level) */ ++ bool use_4addr; /* Should we use 4addresses mode */ ++ bool is_resending; /* Indicate if a frame is being resent on this interface */ ++ bool user_mpm; /* In case of Mesh Point VIF, indicate if MPM is handled by userspace */ ++ bool roc_tdls; /* Indicate if the ROC has been called by a ++ TDLS station */ ++ u8 tdls_status; /* Status of the TDLS link */ ++ bool tdls_chsw_prohibited; /* Indicate if TDLS Channel Switch is prohibited */ ++ bool wep_enabled; /* 1 if WEP is enabled */ ++ bool wep_auth_err; /* 1 if auth status code is not supported auth alg when WEP enabled */ ++ enum nl80211_auth_type last_auth_type; /* Authentication type (algorithm) sent in the last connection ++ when WEP enabled */ ++ union { ++ struct { ++ struct rwnx_sta *ap; /* Pointer to the peer STA entry allocated for ++ the AP */ ++ struct rwnx_sta *tdls_sta; /* Pointer to the TDLS station */ ++ bool external_auth; /* Indicate if external authentication is in progress */ ++ u32 group_cipher_type; ++ u32 paired_cipher_type; ++ //connected network info start ++ char ssid[33];//ssid max is 32, but this has one spare for '\0' ++ int ssid_len; ++ u8 bssid[ETH_ALEN]; ++ u32 conn_owner_nlportid; ++ bool is_roam; ++ //connected network info end ++ } sta; ++ struct { ++ u16 flags; /* see rwnx_ap_flags */ ++ struct list_head sta_list; /* List of STA connected to the AP */ ++ struct rwnx_bcn bcn; /* beacon */ ++ u8 bcmc_index; /* Index of the BCMC sta to use */ ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ u8 aic_index; ++#endif ++ struct rwnx_csa *csa; ++ ++ struct list_head mpath_list; /* List of Mesh Paths used on this interface */ ++ struct list_head proxy_list; /* List of Proxies Information used on this interface */ ++ bool create_path; /* Indicate if we are waiting for a MESH_CREATE_PATH_CFM ++ message */ ++ int generation; /* Increased each time the list of Mesh Paths is updated */ ++ enum nl80211_mesh_power_mode mesh_pm; /* mesh power save mode currently set in firmware */ ++ enum nl80211_mesh_power_mode next_mesh_pm; /* mesh power save mode for next peer */ ++ } ap; ++ struct { ++ struct rwnx_vif *master; /* pointer on master interface */ ++ struct rwnx_sta *sta_4a; ++ } ap_vlan; ++ }; ++ ++ u8_l key_has_add; ++ u8_l is_p2p_vif; ++ struct apm_probe_sta sta_probe; ++ ++ #ifdef CONFIG_BR_SUPPORT ++ spinlock_t br_ext_lock; ++ /* unsigned int macclone_completed; */ ++ struct nat25_network_db_entry *nethash[NAT25_HASH_SIZE]; ++ int pppoe_connection_in_progress; ++ unsigned char pppoe_addr[MACADDRLEN]; ++ unsigned char scdb_mac[MACADDRLEN]; ++ unsigned char scdb_ip[4]; ++ struct nat25_network_db_entry *scdb_entry; ++ unsigned char br_mac[MACADDRLEN]; ++ unsigned char br_ip[4]; ++ ++ struct br_ext_info ethBrExtInfo; ++ #endif /* CONFIG_BR_SUPPORT */ ++}; ++ ++#define RWNX_VIF_TYPE(rwnx_vif) (rwnx_vif->wdev.iftype) ++ ++/** ++ * Structure used to store information relative to PS mode. ++ * ++ * @active: True when the sta is in PS mode. ++ * If false, other values should be ignored ++ * @pkt_ready: Number of packets buffered for the sta in drv's txq ++ * (1 counter for Legacy PS and 1 for U-APSD) ++ * @sp_cnt: Number of packets that remain to be pushed in the service period. ++ * 0 means that no service period is in progress ++ * (1 counter for Legacy PS and 1 for U-APSD) ++ */ ++struct rwnx_sta_ps { ++ bool active; ++ u16 pkt_ready[2]; ++ u16 sp_cnt[2]; ++}; ++ ++/** ++ * struct rwnx_rx_rate_stats - Store statistics for RX rates ++ * ++ * @table: Table indicating how many frame has been receive which each ++ * rate index. Rate index is the same as the one used by RC algo for TX ++ * @size: Size of the table array ++ * @cpt: number of frames received ++ */ ++struct rwnx_rx_rate_stats { ++ int *table; ++ int size; ++ int cpt; ++ int rate_cnt; ++}; ++ ++/** ++ * struct rwnx_sta_stats - Structure Used to store statistics specific to a STA ++ * ++ * @last_rx: Hardware vector of the last received frame ++ * @rx_rate: Statistics of the received rates ++ */ ++struct rwnx_sta_stats { ++ struct hw_vect last_rx; ++ struct rwnx_rx_rate_stats rx_rate; ++}; ++ ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++struct aic_sta { ++ u8 sta_idx; /* Identifier of the station */ ++ bool he; /* Flag indicating if the station supports HE */ ++ bool vht; /* Flag indicating if the station supports VHT */ ++ ++ struct ieee80211_he_cap_elem he_cap_elem; ++ struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ __le32 vht_cap_info; ++ struct ieee80211_vht_mcs_info supp_mcs; ++#endif ++}; ++#endif ++ ++/* ++ * Structure used to save information relative to the managed stations. ++ */ ++struct rwnx_sta { ++ struct list_head list; ++ u16 aid; /* association ID */ ++ u8 sta_idx; /* Identifier of the station */ ++ u8 vif_idx; /* Identifier of the VIF (fw id) the station ++ belongs to */ ++ u8 vlan_idx; /* Identifier of the VLAN VIF (fw id) the station ++ belongs to (= vif_idx if no vlan in used) */ ++ enum nl80211_band band; /* Band */ ++ enum nl80211_chan_width width; /* Channel width */ ++ u16 center_freq; /* Center frequency */ ++ u32 center_freq1; /* Center frequency 1 */ ++ u32 center_freq2; /* Center frequency 2 */ ++ u8 ch_idx; /* Identifier of the channel ++ context the station belongs to */ ++ bool qos; /* Flag indicating if the station ++ supports QoS */ ++ u8 acm; /* Bitfield indicating which queues ++ have AC mandatory */ ++ u16 uapsd_tids; /* Bitfield indicating which tids are subject to ++ UAPSD */ ++ u8 mac_addr[ETH_ALEN]; /* MAC address of the station */ ++ struct rwnx_key key; ++ bool valid; /* Flag indicating if the entry is valid */ ++ struct rwnx_sta_ps ps; /* Information when STA is in PS (AP only) */ ++#ifdef CONFIG_RWNX_BFMER ++ struct rwnx_bfmer_report *bfm_report; /* Beamforming report to be used for ++ VHT TX Beamforming */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ struct rwnx_sta_group_info group_info; /* MU grouping information for the STA */ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ bool ht; /* Flag indicating if the station ++ supports HT */ ++ bool vht; /* Flag indicating if the station ++ supports VHT */ ++ u32 ac_param[AC_MAX]; /* EDCA parameters */ ++ struct rwnx_tdls tdls; /* TDLS station information */ ++ struct rwnx_sta_stats stats; ++ enum nl80211_mesh_power_mode mesh_pm; /* link-specific mesh power save mode */ ++}; ++ ++static inline const u8 *rwnx_sta_addr(struct rwnx_sta *rwnx_sta) ++{ ++ return rwnx_sta->mac_addr; ++} ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++struct rwnx_amsdu_stats { ++ int done; ++ int failed; ++}; ++#endif ++ ++struct rwnx_stats { ++ int cfm_balance[NX_TXQ_CNT]; ++ unsigned long last_rx, last_tx; /* jiffies */ ++ int ampdus_tx[IEEE80211_MAX_AMPDU_BUF]; ++ int ampdus_rx[IEEE80211_MAX_AMPDU_BUF]; ++ int ampdus_rx_map[4]; ++ int ampdus_rx_miss; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ struct rwnx_amsdu_stats amsdus[NX_TX_PAYLOAD_MAX]; ++#endif ++ int amsdus_rx[64]; ++}; ++ ++struct rwnx_sec_phy_chan { ++ u16 prim20_freq; ++ u16 center_freq1; ++ u16 center_freq2; ++ enum nl80211_band band; ++ u8 type; ++}; ++ ++/* Structure that will contains all RoC information received from cfg80211 */ ++struct rwnx_roc_elem { ++ struct wireless_dev *wdev; ++ struct ieee80211_channel *chan; ++ unsigned int duration; ++ /* Used to avoid call of CFG80211 callback upon expiration of RoC */ ++ bool mgmt_roc; ++ /* Indicate if we have switch on the RoC channel */ ++ bool on_chan; ++}; ++ ++/* Structure containing channel survey information received from MAC */ ++struct rwnx_survey_info { ++ // Filled ++ u32 filled; ++ // Amount of time in ms the radio spent on the channel ++ u32 chan_time_ms; ++ // Amount of time the primary channel was sensed busy ++ u32 chan_time_busy_ms; ++ // Noise in dbm ++ s8 noise_dbm; ++}; ++ ++#define RWNX_CH_NOT_SET 0xFF ++#define RWNX_INVALID_VIF 0xFF ++#define RWNX_INVALID_STA 0xFF ++ ++/* Structure containing channel context information */ ++struct rwnx_chanctx { ++ struct cfg80211_chan_def chan_def; /* channel description */ ++ u8 count; /* number of vif using this ctxt */ ++}; ++ ++/** ++ * rwnx_phy_info - Phy information ++ * ++ * @phy_cnt: Number of phy interface ++ * @cfg: Configuration send to firmware ++ * @sec_chan: Channel configuration of the second phy interface (if phy_cnt > 1) ++ * @limit_bw: Set to true to limit BW on requested channel. Only set to use ++ * VHT with old radio that don't support 80MHz (deprecated) ++ */ ++struct rwnx_phy_info { ++ u8 cnt; ++ struct phy_cfg_tag cfg; ++ struct rwnx_sec_phy_chan sec_chan; ++ bool limit_bw; ++}; ++ ++ ++struct defrag_ctrl_info { ++ struct list_head list; ++ u8 sta_idx; ++ u8 tid; ++ u16 sn; ++ u8 next_fn; ++ u16 frm_len; ++ struct sk_buff *skb; ++ struct timer_list defrag_timer; ++ struct rwnx_hw *rwnx_hw; ++}; ++ ++struct amsdu_subframe_hdr { ++ u8 da[6]; ++ u8 sa[6]; ++ u16 sublen; ++}; ++ ++ ++/* rwnx driver status */ ++void rwnx_set_conn_state(atomic_t *drv_conn_state, int state); ++ ++enum rwnx_drv_connect_status { ++ RWNX_DRV_STATUS_DISCONNECTED = 0, ++ RWNX_DRV_STATUS_DISCONNECTING, ++ RWNX_DRV_STATUS_CONNECTING, ++ RWNX_DRV_STATUS_CONNECTED, ++ RWNX_DRV_STATUS_ROAMING, ++}; ++ ++static const char *const s_conn_state[] = { ++ "RWNX_DRV_STATUS_DISCONNECTED", ++ "RWNX_DRV_STATUS_DISCONNECTING", ++ "RWNX_DRV_STATUS_CONNECTING", ++ "RWNX_DRV_STATUS_CONNECTED", ++ "RWNX_DRV_STATUS_ROAMING", ++}; ++ ++ ++struct rwnx_hw { ++ struct rwnx_mod_params *mod_params; ++ struct device *dev; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ struct wiphy *wiphy; ++ struct list_head vifs; ++ struct rwnx_vif *vif_table[NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX]; /* indexed with fw id */ ++ struct rwnx_sta sta_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX]; ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ struct aic_sta aic_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX]; ++#endif ++ struct rwnx_survey_info survey[SCAN_CHANNEL_MAX]; ++ struct cfg80211_scan_request *scan_request; ++#ifdef CONFIG_SCHED_SCAN ++ struct cfg80211_sched_scan_request *sched_scan_req; ++#endif ++ struct rwnx_chanctx chanctx_table[NX_CHAN_CTXT_CNT]; ++ u8 cur_chanctx; ++ ++ u8 monitor_vif; /* FW id of the monitor interface, RWNX_INVALID_VIF if no monitor vif at fw level */ ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ /* tcp ack management */ ++ struct tcp_ack_manage ack_m; ++#endif ++ ++ /* RoC Management */ ++ struct rwnx_roc_elem *roc_elem; /* Information provided by cfg80211 in its remain on channel request */ ++ u32 roc_cookie_cnt; /* Counter used to identify RoC request sent by cfg80211 */ ++ ++ struct rwnx_cmd_mgr *cmd_mgr; ++ ++ struct rwnx_plat *plat; ++ ++ spinlock_t tx_lock; ++ spinlock_t cb_lock; ++ struct mutex mutex; /* per-device perimeter lock */ ++ ++ struct tasklet_struct task; ++ struct mm_version_cfm version_cfm; /* Lower layers versions - obtained via MM_VERSION_REQ */ ++ ++ u32 tcp_pacing_shift; ++ ++ /* IPC */ ++ struct ipc_host_env_tag *ipc_env; ++#ifdef AICWF_SDIO_SUPPORT ++ struct sdio_host_env_tag sdio_env; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ struct usb_host_env_tag usb_env; ++#endif ++ ++ struct rwnx_ipc_elem_pool e2amsgs_pool; ++ struct rwnx_ipc_elem_pool dbgmsgs_pool; ++ struct rwnx_ipc_elem_pool e2aradars_pool; ++ struct rwnx_ipc_elem_var pattern_elem; ++ struct rwnx_ipc_dbgdump_elem dbgdump_elem; ++ struct rwnx_ipc_elem_pool e2arxdesc_pool; ++ struct rwnx_ipc_skb_elem *e2aunsuprxvec_elems; ++ //struct rwnx_ipc_rxbuf_elems rxbuf_elems; ++ struct rwnx_ipc_elem_var scan_ie; ++ ++ struct kmem_cache *sw_txhdr_cache; ++ ++ struct rwnx_debugfs debugfs; ++ struct rwnx_stats stats; ++ ++#ifdef CONFIG_PREALLOC_TXQ ++ struct rwnx_txq *txq; ++#else ++ struct rwnx_txq txq[NX_NB_TXQ]; ++#endif ++ ++ struct rwnx_hwq hwq[NX_TXQ_CNT]; ++ ++ u64 avail_idx_map; ++ u8 vif_started; ++ bool adding_sta; ++ struct rwnx_phy_info phy; ++ ++ struct rwnx_radar radar; ++ ++ /* extended capabilities supported */ ++ u8 ext_capa[8]; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ struct rwnx_mu_info mu; ++#endif ++ u8 is_p2p_alive; ++ u8 is_p2p_connected; ++ struct timer_list p2p_alive_timer; ++ struct rwnx_vif *p2p_dev_vif; ++ atomic_t p2p_alive_timer_count; ++ bool band_5g_support; ++ u8_l vendor_info; ++ bool fwlog_en; ++ ++ struct list_head defrag_list; ++ spinlock_t defrag_lock; ++ ++ struct work_struct apmStalossWork; ++ struct workqueue_struct *apmStaloss_wq; ++ u8 apm_vif_idx; ++ u8 sta_mac_addr[6]; ++ ++ struct wakeup_source *ws_rx; ++ struct wakeup_source *ws_irqrx; ++ struct wakeup_source *ws_tx; ++ struct wakeup_source *ws_pwrctrl; ++ ++#ifdef CONFIG_SCHED_SCAN ++ bool is_sched_scan; ++#endif//CONFIG_SCHED_SCAN ++#ifdef CONFIG_TEMP_CONTROL ++ unsigned long started_jiffies; ++ s8_l temp; ++#endif ++ ++}; ++ ++u8 *rwnx_build_bcn(struct rwnx_bcn *bcn, struct cfg80211_beacon_data *new); ++ ++void rwnx_chanctx_link(struct rwnx_vif *vif, u8 idx, ++ struct cfg80211_chan_def *chandef); ++void rwnx_chanctx_unlink(struct rwnx_vif *vif); ++int rwnx_chanctx_valid(struct rwnx_hw *rwnx_hw, u8 idx); ++ ++extern u8 chip_id; ++ ++static inline bool is_multicast_sta(int sta_idx) ++{ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)) ++ { ++ return (sta_idx >= NX_REMOTE_STA_MAX_FOR_OLD_IC); ++ }else{ ++ return (sta_idx >= NX_REMOTE_STA_MAX); ++ } ++ ++} ++struct rwnx_sta *rwnx_get_sta(struct rwnx_hw *rwnx_hw, const u8 *mac_addr); ++ ++static inline uint8_t master_vif_idx(struct rwnx_vif *vif) ++{ ++ if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) { ++ return vif->ap_vlan.master->vif_index; ++ } else { ++ return vif->vif_index; ++ } ++} ++ ++void rwnx_external_auth_enable(struct rwnx_vif *vif); ++void rwnx_external_auth_disable(struct rwnx_vif *vif); ++ ++#endif /* _RWNX_DEFS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c +new file mode 100644 +index 000000000000..17d55da1156f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c +@@ -0,0 +1,297 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_dini.c - Add support for dini platform ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_dini.h" ++#include "rwnx_defs.h" ++#include "rwnx_irqs.h" ++#include "reg_access.h" ++ ++/* Config FPGA is accessed via bar0 */ ++#define CFPGA_DMA0_CTRL_REG 0x02C ++#define CFPGA_DMA1_CTRL_REG 0x04C ++#define CFPGA_DMA2_CTRL_REG 0x06C ++#define CFPGA_UINTR_SRC_REG 0x0E8 ++#define CFPGA_UINTR_MASK_REG 0x0EC ++#define CFPGA_BAR4_HIADDR_REG 0x100 ++#define CFPGA_BAR4_LOADDR_REG 0x104 ++#define CFPGA_BAR4_LOADDR_MASK_REG 0x110 ++#define CFPGA_BAR_TOUT 0x120 ++ ++#define CFPGA_DMA_CTRL_ENABLE 0x00001400 ++#define CFPGA_DMA_CTRL_DISABLE 0x00001000 ++#define CFPGA_DMA_CTRL_CLEAR 0x00001800 ++#define CFPGA_DMA_CTRL_REREAD_TIME_MASK (BIT(10) - 1) ++ ++#define CFPGA_BAR4_LOADDR_MASK_MAX 0xFF000000 ++ ++#define CFPGA_PCIEX_IT 0x00000001 ++#define CFPGA_ALL_ITS 0x0000000F ++ ++/* Programmable BAR4 Window start address */ ++#define CPU_RAM_WINDOW_HIGH 0x00000000 ++#define CPU_RAM_WINDOW_LOW 0x00000000 ++#define AHB_BRIDGE_WINDOW_HIGH 0x00000000 ++#define AHB_BRIDGE_WINDOW_LOW 0x60000000 ++ ++struct rwnx_dini { ++ u8 *pci_bar0_vaddr; ++ u8 *pci_bar4_vaddr; ++}; ++ ++static const u32 mv_cfg_fpga_dma_ctrl_regs[] = { ++ CFPGA_DMA0_CTRL_REG, ++ CFPGA_DMA1_CTRL_REG, ++ CFPGA_DMA2_CTRL_REG ++}; ++ ++/* This also clears running transactions */ ++static void dini_dma_on(struct rwnx_dini *rwnx_dini) ++{ ++ int i; ++ u32 reread_time; ++ volatile void *reg; ++ ++ for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) { ++ reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i]; ++ reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK; ++ ++ writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg); ++ writel(CFPGA_DMA_CTRL_ENABLE | reread_time, reg); ++ } ++} ++ ++/* This also clears running transactions */ ++static void dini_dma_off(struct rwnx_dini *rwnx_dini) ++{ ++ int i; ++ u32 reread_time; ++ volatile void *reg; ++ ++ for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) { ++ reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i]; ++ reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK; ++ ++ writel(CFPGA_DMA_CTRL_DISABLE | reread_time, reg); ++ writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg); ++ } ++} ++ ++ ++/* Configure address range for BAR4. ++ * By default BAR4_LOADDR_MASK value is 0xFF000000, then there is no need to ++ * change it because the addresses we need to access are covered by this mask ++ */ ++static void dini_set_bar4_win(u32 low, u32 high, struct rwnx_dini *rwnx_dini) ++{ ++ writel(low, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_REG); ++ writel(high, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_HIADDR_REG); ++ writel(CFPGA_BAR4_LOADDR_MASK_MAX, ++ rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_MASK_REG); ++} ++ ++ ++/** ++ * Enable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10 ++ * and request the corresponding IRQ line ++ */ ++int rwnx_cfpga_irq_enable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ unsigned int cfpga_uintr_mask; ++ volatile void *reg; ++ int ret; ++ ++ /* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */ ++ ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0, "rwnx", rwnx_hw); ++ if (ret) ++ return ret; ++ ++ reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG; ++ cfpga_uintr_mask = readl(reg); ++ writel(cfpga_uintr_mask | CFPGA_PCIEX_IT, reg); ++ ++ return ret; ++} ++ ++/** ++ * Disable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10 ++ * and free the corresponding IRQ line ++ */ ++int rwnx_cfpga_irq_disable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ unsigned int cfpga_uintr_mask; ++ volatile void *reg; ++ ++ reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG; ++ cfpga_uintr_mask = readl(reg); ++ writel(cfpga_uintr_mask & ~CFPGA_PCIEX_IT, reg); ++ ++ free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw); ++ ++ return 0; ++} ++ ++static int rwnx_dini_platform_enable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++#ifdef CONFIG_RWNX_SDM ++ writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT); ++#endif ++ ++ dini_dma_on(rwnx_dini); ++ return rwnx_cfpga_irq_enable(rwnx_hw); ++} ++ ++static int rwnx_dini_platform_disable(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ int ret; ++ ++ ret = rwnx_cfpga_irq_disable(rwnx_hw); ++ dini_dma_off(rwnx_dini); ++ return ret; ++} ++ ++static void rwnx_dini_platform_deinit(struct rwnx_plat *rwnx_plat) ++{ ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++ pci_disable_device(rwnx_plat->pci_dev); ++ iounmap(rwnx_dini->pci_bar0_vaddr); ++ iounmap(rwnx_dini->pci_bar4_vaddr); ++ pci_release_regions(rwnx_plat->pci_dev); ++ ++ kfree(rwnx_plat); ++} ++ ++static u8 *rwnx_dini_get_address(struct rwnx_plat *rwnx_plat, int addr_name, ++ unsigned int offset) ++{ ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++ if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name)) ++ return NULL; ++ ++ if (addr_name == RWNX_ADDR_CPU) ++ dini_set_bar4_win(CPU_RAM_WINDOW_LOW, CPU_RAM_WINDOW_HIGH, rwnx_dini); ++ else ++ dini_set_bar4_win(AHB_BRIDGE_WINDOW_LOW, AHB_BRIDGE_WINDOW_HIGH, rwnx_dini); ++ ++ return rwnx_dini->pci_bar4_vaddr + offset; ++} ++ ++static void rwnx_dini_ack_irq(struct rwnx_plat *rwnx_plat) ++{ ++ struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; ++ ++ writel(CFPGA_ALL_ITS, rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_SRC_REG); ++} ++ ++static const u32 rwnx_dini_config_reg[] = { ++ NXMAC_DEBUG_PORT_SEL_ADDR, ++ SYSCTRL_DIAG_CONF_ADDR, ++ RF_V6_DIAGPORT_CONF1_ADDR, ++ RF_v6_PHYDIAG_CONF1_ADDR, ++}; ++ ++static int rwnx_dini_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list) ++{ ++ if (!list) ++ return 0; ++ ++ *list = rwnx_dini_config_reg; ++ return ARRAY_SIZE(rwnx_dini_config_reg); ++} ++ ++/** ++ * rwnx_dini_platform_init - Initialize the DINI platform ++ * ++ * @pci_dev PCI device ++ * @rwnx_plat Pointer on struct rwnx_stat * to be populated ++ * ++ * @return 0 on success, < 0 otherwise ++ * ++ * Allocate and initialize a rwnx_plat structure for the dini platform. ++ */ ++int rwnx_dini_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat) ++{ ++ struct rwnx_dini *rwnx_dini; ++ u16 pci_cmd; ++ int ret = 0; ++ ++ *rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_dini), ++ GFP_KERNEL); ++ if (!*rwnx_plat) ++ return -ENOMEM; ++ ++ rwnx_dini = (struct rwnx_dini *)(*rwnx_plat)->priv; ++ ++ /* Hotplug fixups */ ++ pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd); ++ pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; ++ pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd); ++ //pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2); ++ ++ ret = pci_enable_device(pci_dev); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_enable_device failed\n"); ++ goto out_enable; ++ } ++ ++ pci_set_master(pci_dev); ++#if 0 ++ ret = pci_request_regions(pci_dev, KBUILD_MODNAME); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_request_regions failed\n"); ++ goto out_request; ++ } ++#endif ++ rwnx_dini->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0); ++ if (!rwnx_dini->pci_bar0_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0); ++ ret = -ENOMEM; ++ goto out_bar0; ++ } ++ rwnx_dini->pci_bar4_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 4); ++ if (!rwnx_dini->pci_bar4_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 4); ++ ret = -ENOMEM; ++ goto out_bar4; ++ } ++ ++ (*rwnx_plat)->enable = rwnx_dini_platform_enable; ++ (*rwnx_plat)->disable = rwnx_dini_platform_disable; ++ (*rwnx_plat)->deinit = rwnx_dini_platform_deinit; ++ (*rwnx_plat)->get_address = rwnx_dini_get_address; ++ (*rwnx_plat)->ack_irq = rwnx_dini_ack_irq; ++ (*rwnx_plat)->get_config_reg = rwnx_dini_get_config_reg; ++ ++#ifdef CONFIG_RWNX_SDM ++ writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT); ++#endif ++ ++ return 0; ++ ++out_bar4: ++ iounmap(rwnx_dini->pci_bar0_vaddr); ++out_bar0: ++ pci_release_regions(pci_dev); ++//out_request: ++ pci_disable_device(pci_dev); ++out_enable: ++ kfree(*rwnx_plat); ++ return ret; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h +new file mode 100644 +index 000000000000..d9f57c10ed4f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h +@@ -0,0 +1,20 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_dini.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_DINI_H_ ++#define _RWNX_DINI_H_ ++ ++#include ++#include "rwnx_platform.h" ++ ++int rwnx_dini_platform_init(struct pci_dev *pci_dev, ++ struct rwnx_plat **rwnx_plat); ++ ++#endif /* _RWNX_DINI_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h +new file mode 100644 +index 000000000000..3bd59807f663 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h +@@ -0,0 +1,1326 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_events.h ++ * ++ * @brief Trace events definition ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM rwnx ++ ++#if !defined(_RWNX_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _RWNX_EVENTS_H ++ ++#include ++#ifndef CONFIG_RWNX_FHOST ++#include "rwnx_tx.h" ++#endif ++#include "rwnx_compat.h" ++ ++/***************************************************************************** ++ * TRACE function for MGMT TX (FULLMAC) ++ ****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++#include "linux/ieee80211.h" ++#if defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) ++#include ++ ++/* P2P Public Action Frames Definitions (see WiFi P2P Technical Specification, section 4.2.8) */ ++/* IEEE 802.11 Public Action Usage Category - Define P2P public action frames */ ++#define MGMT_ACTION_PUBLIC_CAT (0x04) ++/* Offset of OUI Subtype field in P2P Action Frame format */ ++#define MGMT_ACTION_OUI_SUBTYPE_OFFSET (6) ++/* P2P Public Action Frame Types */ ++enum p2p_action_type { ++ P2P_ACTION_GO_NEG_REQ = 0, /* GO Negociation Request */ ++ P2P_ACTION_GO_NEG_RSP, /* GO Negociation Response */ ++ P2P_ACTION_GO_NEG_CFM, /* GO Negociation Confirmation */ ++ P2P_ACTION_INVIT_REQ, /* P2P Invitation Request */ ++ P2P_ACTION_INVIT_RSP, /* P2P Invitation Response */ ++ P2P_ACTION_DEV_DISC_REQ, /* Device Discoverability Request */ ++ P2P_ACTION_DEV_DISC_RSP, /* Device Discoverability Response */ ++ P2P_ACTION_PROV_DISC_REQ, /* Provision Discovery Request */ ++ P2P_ACTION_PROV_DISC_RSP, /* Provision Discovery Response */ ++}; ++ ++const char *ftrace_print_mgmt_info(struct trace_seq *p, u16 frame_control, u8 cat, u8 type, u8 p2p) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ switch (frame_control & IEEE80211_FCTL_STYPE) { ++ case (IEEE80211_STYPE_ASSOC_REQ): ++ trace_seq_printf(p, "Association Request"); ++ break; ++ case (IEEE80211_STYPE_ASSOC_RESP): ++ trace_seq_printf(p, "Association Response"); ++ break; ++ case (IEEE80211_STYPE_REASSOC_REQ): ++ trace_seq_printf(p, "Reassociation Request"); ++ break; ++ case (IEEE80211_STYPE_REASSOC_RESP): ++ trace_seq_printf(p, "Reassociation Response"); ++ break; ++ case (IEEE80211_STYPE_PROBE_REQ): ++ trace_seq_printf(p, "Probe Request"); ++ break; ++ case (IEEE80211_STYPE_PROBE_RESP): ++ trace_seq_printf(p, "Probe Response"); ++ break; ++ case (IEEE80211_STYPE_BEACON): ++ trace_seq_printf(p, "Beacon"); ++ break; ++ case (IEEE80211_STYPE_ATIM): ++ trace_seq_printf(p, "ATIM"); ++ break; ++ case (IEEE80211_STYPE_DISASSOC): ++ trace_seq_printf(p, "Disassociation"); ++ break; ++ case (IEEE80211_STYPE_AUTH): ++ trace_seq_printf(p, "Authentication"); ++ break; ++ case (IEEE80211_STYPE_DEAUTH): ++ trace_seq_printf(p, "Deauthentication"); ++ break; ++ case (IEEE80211_STYPE_ACTION): ++ trace_seq_printf(p, "Action"); ++ if (cat == MGMT_ACTION_PUBLIC_CAT && type == 0x9) { ++ switch (p2p) { ++ case (P2P_ACTION_GO_NEG_REQ): ++ trace_seq_printf(p, ": GO Negociation Request"); ++ break; ++ case (P2P_ACTION_GO_NEG_RSP): ++ trace_seq_printf(p, ": GO Negociation Response"); ++ break; ++ case (P2P_ACTION_GO_NEG_CFM): ++ trace_seq_printf(p, ": GO Negociation Confirmation"); ++ break; ++ case (P2P_ACTION_INVIT_REQ): ++ trace_seq_printf(p, ": P2P Invitation Request"); ++ break; ++ case (P2P_ACTION_INVIT_RSP): ++ trace_seq_printf(p, ": P2P Invitation Response"); ++ break; ++ case (P2P_ACTION_DEV_DISC_REQ): ++ trace_seq_printf(p, ": Device Discoverability Request"); ++ break; ++ case (P2P_ACTION_DEV_DISC_RSP): ++ trace_seq_printf(p, ": Device Discoverability Response"); ++ break; ++ case (P2P_ACTION_PROV_DISC_REQ): ++ trace_seq_printf(p, ": Provision Discovery Request"); ++ break; ++ case (P2P_ACTION_PROV_DISC_RSP): ++ trace_seq_printf(p, ": Provision Discovery Response"); ++ break; ++ default: ++ trace_seq_printf(p, "Unknown p2p %d", p2p); ++ break; ++ } ++ } else { ++ switch (cat) { ++ case 0: ++ trace_seq_printf(p, ":Spectrum %d", type); ++ break; ++ case 1: ++ trace_seq_printf(p, ":QOS %d", type); break; ++ case 2: ++ trace_seq_printf(p, ":DLS %d", type); ++ break; ++ case 3: ++ trace_seq_printf(p, ":BA %d", type); ++ break; ++ case 4: ++ trace_seq_printf(p, ":Public %d", type); ++ break; ++ case 5: ++ trace_seq_printf(p, ":Radio Measure %d", type); ++ break; ++ case 6: ++ trace_seq_printf(p, ":Fast BSS %d", type); ++ break; ++ case 7: ++ trace_seq_printf(p, ":HT Action %d", type); ++ break; ++ case 8: ++ trace_seq_printf(p, ":SA Query %d", type); ++ break; ++ case 9: ++ trace_seq_printf(p, ":Protected Public %d", type); ++ break; ++ case 10: ++ trace_seq_printf(p, ":WNM %d", type); ++ break; ++ case 11: ++ trace_seq_printf(p, ":Unprotected WNM %d", type); ++ break; ++ case 12: ++ trace_seq_printf(p, ":TDLS %d", type); ++ break; ++ case 13: ++ trace_seq_printf(p, ":Mesh %d", type); ++ break; ++ case 14: ++ trace_seq_printf(p, ":MultiHop %d", type); ++ break; ++ case 15: ++ trace_seq_printf(p, ":Self Protected %d", type); ++ break; ++ case 126: ++ trace_seq_printf(p, ":Vendor protected"); ++ break; ++ case 127: ++ trace_seq_printf(p, ":Vendor"); ++ break; ++ default: ++ trace_seq_printf(p, ":Unknown category %d", cat); ++ break; ++ } ++ } ++ break; ++ default: ++ trace_seq_printf(p, "Unknown subtype %d", frame_control & IEEE80211_FCTL_STYPE); ++ break; ++ } ++ ++ trace_seq_putc(p, 0); ++ ++ return ret; ++} ++#endif /* defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) */ ++ ++#undef __print_mgmt_info ++#define __print_mgmt_info(frame_control, cat, type, p2p) ftrace_print_mgmt_info(p, frame_control, cat, type, p2p) ++ ++TRACE_EVENT( ++ roc, ++ TP_PROTO(u8 vif_idx, u16 freq, unsigned int duration), ++ TP_ARGS(vif_idx, freq, duration), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ __field(u16, freq) ++ __field(unsigned int, duration) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ __entry->freq = freq; ++ __entry->duration = duration; ++ ), ++ TP_printk("f=%d vif=%d dur=%d", ++ __entry->freq, __entry->vif_idx, __entry->duration) ++); ++ ++TRACE_EVENT( ++ cancel_roc, ++ TP_PROTO(u8 vif_idx), ++ TP_ARGS(vif_idx), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ ), ++ TP_printk("vif=%d", __entry->vif_idx) ++); ++ ++TRACE_EVENT( ++ roc_exp, ++ TP_PROTO(u8 vif_idx), ++ TP_ARGS(vif_idx), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ ), ++ TP_printk("vif=%d", __entry->vif_idx) ++); ++ ++TRACE_EVENT( ++ switch_roc, ++ TP_PROTO(u8 vif_idx), ++ TP_ARGS(vif_idx), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ ), ++ TP_printk("vif=%d", __entry->vif_idx) ++); ++ ++DECLARE_EVENT_CLASS( ++ mgmt_template, ++ TP_PROTO(u16 freq, u8 vif_idx, u8 sta_idx, struct ieee80211_mgmt *mgmt), ++ TP_ARGS(freq, vif_idx, sta_idx, mgmt), ++ TP_STRUCT__entry( ++ __field(u16, freq) ++ __field(u8, vif_idx) ++ __field(u8, sta_idx) ++ __field(u16, frame_control) ++ __field(u8, action_cat) ++ __field(u8, action_type) ++ __field(u8, action_p2p) ++ ), ++ TP_fast_assign( ++ __entry->freq = freq; ++ __entry->vif_idx = vif_idx; ++ __entry->sta_idx = sta_idx; ++ __entry->frame_control = mgmt->frame_control; ++ __entry->action_cat = mgmt->u.action.category; ++ __entry->action_type = mgmt->u.action.u.wme_action.action_code; ++ __entry->action_p2p = *((u8 *)&mgmt->u.action.category ++ + MGMT_ACTION_OUI_SUBTYPE_OFFSET); ++ ), ++ TP_printk("f=%d vif=%d sta=%d -> %s", ++ __entry->freq, __entry->vif_idx, __entry->sta_idx, ++ __print_mgmt_info(__entry->frame_control, __entry->action_cat, ++ __entry->action_type, __entry->action_p2p)) ++); ++ ++DEFINE_EVENT(mgmt_template, mgmt_tx, ++ TP_PROTO(u16 freq, u8 vif_idx, u8 sta_idx, struct ieee80211_mgmt *mgmt), ++ TP_ARGS(freq, vif_idx, sta_idx, mgmt)); ++ ++DEFINE_EVENT(mgmt_template, mgmt_rx, ++ TP_PROTO(u16 freq, u8 vif_idx, u8 sta_idx, struct ieee80211_mgmt *mgmt), ++ TP_ARGS(freq, vif_idx, sta_idx, mgmt)); ++ ++TRACE_EVENT( ++ mgmt_cfm, ++ TP_PROTO(u8 vif_idx, u8 sta_idx, bool acked), ++ TP_ARGS(vif_idx, sta_idx, acked), ++ TP_STRUCT__entry( ++ __field(u8, vif_idx) ++ __field(u8, sta_idx) ++ __field(bool, acked) ++ ), ++ TP_fast_assign( ++ __entry->vif_idx = vif_idx; ++ __entry->sta_idx = sta_idx; ++ __entry->acked = acked; ++ ), ++ TP_printk("vif=%d sta=%d ack=%d", ++ __entry->vif_idx, __entry->sta_idx, __entry->acked) ++); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/***************************************************************************** ++ * TRACE function for TXQ ++ ****************************************************************************/ ++#ifndef CONFIG_RWNX_FHOST ++#if defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) ++ ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#else ++#include ++#endif ++ ++const char * ++ftrace_print_txq(struct trace_seq *p, int txq_idx) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (txq_idx == TXQ_INACTIVE) { ++ trace_seq_printf(p, "[INACTIVE]"); ++ } else if (txq_idx < NX_FIRST_VIF_TXQ_IDX) { ++ trace_seq_printf(p, "[STA %d/%d]", ++ txq_idx / NX_NB_TXQ_PER_STA, ++ txq_idx % NX_NB_TXQ_PER_STA); ++#ifdef CONFIG_RWNX_FULLMAC ++ } else if (txq_idx < NX_FIRST_UNK_TXQ_IDX) { ++ trace_seq_printf(p, "[BC/MC %d]", ++ txq_idx - NX_FIRST_BCMC_TXQ_IDX); ++ } else if (txq_idx < NX_OFF_CHAN_TXQ_IDX) { ++ trace_seq_printf(p, "[UNKNOWN %d]", ++ txq_idx - NX_FIRST_UNK_TXQ_IDX); ++ } else if (txq_idx == NX_OFF_CHAN_TXQ_IDX) { ++ trace_seq_printf(p, "[OFFCHAN]"); ++#else ++ } else if (txq_idx < NX_NB_TXQ) { ++ txq_idx -= NX_FIRST_VIF_TXQ_IDX; ++ trace_seq_printf(p, "[VIF %d/%d]", ++ txq_idx / NX_NB_TXQ_PER_VIF, ++ txq_idx % NX_NB_TXQ_PER_VIF); ++#endif ++ } else { ++ trace_seq_printf(p, "[ERROR %d]", txq_idx); ++ } ++ ++ trace_seq_putc(p, 0); ++ ++ return ret; ++} ++ ++const char * ++ftrace_print_sta(struct trace_seq *p, int sta_idx) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (sta_idx < NX_REMOTE_STA_MAX) { ++ trace_seq_printf(p, "[STA %d]", sta_idx); ++ } else { ++ trace_seq_printf(p, "[BC/MC %d]", sta_idx - NX_REMOTE_STA_MAX); ++ } ++ ++ trace_seq_putc(p, 0); ++ ++ return ret; ++} ++ ++const char * ++ftrace_print_hwq(struct trace_seq *p, int hwq_idx) ++{ ++ ++ static const struct trace_print_flags symbols[] = { ++ {RWNX_HWQ_BK, "BK"}, ++ {RWNX_HWQ_BE, "BE"}, ++ {RWNX_HWQ_VI, "VI"}, ++ {RWNX_HWQ_VO, "VO"}, ++#ifdef CONFIG_RWNX_FULLMAC ++ {RWNX_HWQ_BCMC, "BCMC"}, ++#else ++ {RWNX_HWQ_BCN, "BCN"}, ++#endif ++ { -1, NULL } }; ++ return trace_print_symbols_seq(p, hwq_idx, symbols); ++} ++ ++const char * ++ftrace_print_hwq_cred(struct trace_seq *p, u8 *cred) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++#if CONFIG_USER_MAX == 1 ++ trace_seq_printf(p, "%d", cred[0]); ++#else ++ int i; ++ ++ for (i = 0; i < CONFIG_USER_MAX - 1; i++) ++ trace_seq_printf(p, "%d-", cred[i]); ++ trace_seq_printf(p, "%d", cred[i]); ++#endif ++ ++ trace_seq_putc(p, 0); ++ return ret; ++} ++ ++const char * ++ftrace_print_mu_info(struct trace_seq *p, u8 mu_info) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (mu_info) ++ trace_seq_printf(p, "MU: %d-%d", (mu_info & 0x3f), (mu_info >> 6)); ++ ++ trace_seq_putc(p, 0); ++ return ret; ++} ++ ++const char * ++ftrace_print_mu_group(struct trace_seq *p, int nb_user, u8 *users) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ int i; ++ ++ if (users[0] != 0xff) ++ trace_seq_printf(p, "(%d", users[0]); ++ else ++ trace_seq_printf(p, "(-"); ++ for (i = 1; i < CONFIG_USER_MAX ; i++) { ++ if (users[i] != 0xff) ++ trace_seq_printf(p, ",%d", users[i]); ++ else ++ trace_seq_printf(p, ",-"); ++ } ++ ++ trace_seq_printf(p, ")"); ++ trace_seq_putc(p, 0); ++ return ret; ++} ++ ++const char * ++ftrace_print_amsdu(struct trace_seq *p, u16 nb_pkt) ++{ ++ const char *ret = trace_seq_buffer_ptr(p); ++ ++ if (nb_pkt > 1) ++ trace_seq_printf(p, "(AMSDU %d)", nb_pkt); ++ ++ trace_seq_putc(p, 0); ++ return ret; ++} ++#endif /* defined(CONFIG_TRACEPOINTS) && defined(CREATE_TRACE_POINTS) */ ++ ++#undef __print_txq ++#define __print_txq(txq_idx) ftrace_print_txq(p, txq_idx) ++ ++#undef __print_sta ++#define __print_sta(sta_idx) ftrace_print_sta(p, sta_idx) ++ ++#undef __print_hwq ++#define __print_hwq(hwq) ftrace_print_hwq(p, hwq) ++ ++#undef __print_hwq_cred ++#define __print_hwq_cred(cred) ftrace_print_hwq_cred(p, cred) ++ ++#undef __print_mu_info ++#define __print_mu_info(mu_info) ftrace_print_mu_info(p, mu_info) ++ ++#undef __print_mu_group ++#define __print_mu_group(nb, users) ftrace_print_mu_group(p, nb, users) ++ ++#undef __print_amsdu ++#define __print_amsdu(nb_pkt) ftrace_print_amsdu(p, nb_pkt) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++TRACE_EVENT( ++ txq_select, ++ TP_PROTO(int txq_idx, u16 pkt_ready_up, struct sk_buff *skb), ++ TP_ARGS(txq_idx, pkt_ready_up, skb), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, pkt_ready) ++ __field(struct sk_buff *, skb) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq_idx; ++ __entry->pkt_ready = pkt_ready_up; ++ __entry->skb = skb; ++ ), ++ TP_printk("%s pkt_ready_up=%d skb=%p", __print_txq(__entry->txq_idx), ++ __entry->pkt_ready, __entry->skb) ++); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++DECLARE_EVENT_CLASS( ++ hwq_template, ++ TP_PROTO(u8 hwq_idx), ++ TP_ARGS(hwq_idx), ++ TP_STRUCT__entry( ++ __field(u8, hwq_idx) ++ ), ++ TP_fast_assign( ++ __entry->hwq_idx = hwq_idx; ++ ), ++ TP_printk("%s", __print_hwq(__entry->hwq_idx)) ++); ++ ++DEFINE_EVENT(hwq_template, hwq_flowctrl_stop, ++ TP_PROTO(u8 hwq_idx), ++ TP_ARGS(hwq_idx)); ++ ++DEFINE_EVENT(hwq_template, hwq_flowctrl_start, ++ TP_PROTO(u8 hwq_idx), ++ TP_ARGS(hwq_idx)); ++ ++ ++DECLARE_EVENT_CLASS( ++ txq_template, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ ), ++ TP_printk("%s", __print_txq(__entry->txq_idx)) ++); ++ ++DEFINE_EVENT(txq_template, txq_add_to_hw, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++DEFINE_EVENT(txq_template, txq_del_from_hw, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++DEFINE_EVENT(txq_template, txq_flowctrl_stop, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++DEFINE_EVENT(txq_template, txq_flowctrl_restart, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq)); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++TRACE_EVENT( ++ process_txq, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, len) ++ __field(u16, len_retry) ++ __field(s8, credit) ++ #ifdef CONFIG_RWNX_FULLMAC ++ __field(u16, limit) ++ #endif /* CONFIG_RWNX_FULLMAC*/ ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->len = skb_queue_len(&txq->sk_list); ++ #ifdef CONFIG_MAC80211_TXQ ++ __entry->len += txq->nb_ready_mac80211; ++ #endif ++ __entry->len_retry = txq->nb_retry; ++ __entry->credit = txq->credits; ++ #ifdef CONFIG_RWNX_FULLMAC ++ __entry->limit = txq->push_limit; ++ #endif /* CONFIG_RWNX_FULLMAC*/ ++ ), ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ TP_printk("%s txq_credits=%d, len=%d, retry_len=%d, push_limit=%d", ++ __print_txq(__entry->txq_idx), __entry->credit, ++ __entry->len, __entry->len_retry, __entry->limit) ++ #else ++ TP_printk("%s txq_credits=%d, len=%d, retry_len=%d", ++ __print_txq(__entry->txq_idx), __entry->credit, ++ __entry->len, __entry->len_retry) ++ #endif /* CONFIG_RWNX_FULLMAC*/ ++); ++ ++DECLARE_EVENT_CLASS( ++ txq_reason_template, ++ TP_PROTO(struct rwnx_txq *txq, u16 reason), ++ TP_ARGS(txq, reason), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, reason) ++ __field(u16, status) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->reason = reason; ++ __entry->status = txq->status; ++ ), ++ TP_printk("%s reason=%s status=%s", ++ __print_txq(__entry->txq_idx), ++ __print_symbolic(__entry->reason, ++ {RWNX_TXQ_STOP_FULL, "FULL"}, ++ {RWNX_TXQ_STOP_CSA, "CSA"}, ++ {RWNX_TXQ_STOP_STA_PS, "PS"}, ++ {RWNX_TXQ_STOP_VIF_PS, "VPS"}, ++ {RWNX_TXQ_STOP_CHAN, "CHAN"}, ++ {RWNX_TXQ_STOP_MU_POS, "MU"}), ++ __print_flags(__entry->status, "|", ++ {RWNX_TXQ_IN_HWQ_LIST, "IN LIST"}, ++ {RWNX_TXQ_STOP_FULL, "FULL"}, ++ {RWNX_TXQ_STOP_CSA, "CSA"}, ++ {RWNX_TXQ_STOP_STA_PS, "PS"}, ++ {RWNX_TXQ_STOP_VIF_PS, "VPS"}, ++ {RWNX_TXQ_STOP_CHAN, "CHAN"}, ++ {RWNX_TXQ_STOP_MU_POS, "MU"}, ++ {RWNX_TXQ_NDEV_FLOW_CTRL, "FLW_CTRL"})) ++); ++ ++DEFINE_EVENT(txq_reason_template, txq_start, ++ TP_PROTO(struct rwnx_txq *txq, u16 reason), ++ TP_ARGS(txq, reason)); ++ ++DEFINE_EVENT(txq_reason_template, txq_stop, ++ TP_PROTO(struct rwnx_txq *txq, u16 reason), ++ TP_ARGS(txq, reason)); ++ ++ ++TRACE_EVENT( ++ push_desc, ++ TP_PROTO(struct sk_buff *skb, struct rwnx_sw_txhdr *sw_txhdr, int push_flags), ++ ++ TP_ARGS(skb, sw_txhdr, push_flags), ++ ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(unsigned int, len) ++ __field(u16, tx_queue) ++ __field(u8, hw_queue) ++ __field(u8, push_flag) ++ __field(u32, flag) ++ __field(s8, txq_cred) ++ __field(u8, hwq_cred) ++ __field(u16, pkt_cnt) ++ __field(u8, mu_info) ++ ), ++ TP_fast_assign( ++ __entry->skb = skb; ++ __entry->tx_queue = sw_txhdr->txq->idx; ++ __entry->push_flag = push_flags; ++ __entry->hw_queue = sw_txhdr->txq->hwq->id; ++ __entry->txq_cred = sw_txhdr->txq->credits; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ __entry->pkt_cnt = sw_txhdr->desc.host.packet_cnt; ++#endif ++#ifdef CONFIG_RWNX_FULLMAC ++ __entry->flag = sw_txhdr->desc.host.flags; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->amsdu.len) ++ __entry->len = sw_txhdr->amsdu.len; ++ else ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ __entry->len = sw_txhdr->desc.host.packet_len[0]; ++#else ++ __entry->len = sw_txhdr->desc.host.packet_len; ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ ++#else /* !CONFIG_RWNX_FULLMAC */ ++ __entry->flag = sw_txhdr->desc.umac.flags; ++ __entry->len = sw_txhdr->frame_len; ++ __entry->sn = sw_txhdr->sn; ++#endif /* CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ __entry->mu_info = sw_txhdr->desc.host.mumimo_info; ++#else ++ __entry->mu_info = 0; ++#endif ++ ), ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ TP_printk("%s skb=%p (len=%d) hw_queue=%s cred_txq=%d cred_hwq=%d %s flag=%s %s%s%s", ++ __print_txq(__entry->tx_queue), __entry->skb, __entry->len, ++ __print_hwq(__entry->hw_queue), ++ __entry->txq_cred, __entry->hwq_cred, ++ __print_mu_info(__entry->mu_info), ++ __print_flags(__entry->flag, "|", ++ {TXU_CNTRL_RETRY, "RETRY"}, ++ {TXU_CNTRL_MORE_DATA, "MOREDATA"}, ++ {TXU_CNTRL_MGMT, "MGMT"}, ++ {TXU_CNTRL_MGMT_NO_CCK, "NO_CCK"}, ++ {TXU_CNTRL_MGMT_ROBUST, "ROBUST"}, ++ {TXU_CNTRL_AMSDU, "AMSDU"}, ++ {TXU_CNTRL_USE_4ADDR, "4ADDR"}, ++ {TXU_CNTRL_EOSP, "EOSP"}, ++ {TXU_CNTRL_MESH_FWD, "MESH_FWD"}, ++ {TXU_CNTRL_TDLS, "TDLS"}), ++ (__entry->push_flag & RWNX_PUSH_IMMEDIATE) ? "(IMMEDIATE)" : "", ++ (!(__entry->flag & TXU_CNTRL_RETRY) && ++ (__entry->push_flag & RWNX_PUSH_RETRY)) ? "(SW_RETRY)" : "", ++ __print_amsdu(__entry->pkt_cnt)) ++#else ++ TP_printk("%s skb=%p (len=%d) hw_queue=%s cred_txq=%d cred_hwq=%d %s flag=%x (%s) sn=%d %s", ++ __print_txq(__entry->tx_queue), __entry->skb, __entry->len, ++ __print_hwq(__entry->hw_queue), __entry->txq_cred, __entry->hwq_cred, ++ __print_mu_info(__entry->mu_info), ++ __entry->flag, ++ __print_flags(__entry->push_flag, "|", ++ {RWNX_PUSH_RETRY, "RETRY"}, ++ {RWNX_PUSH_IMMEDIATE, "IMMEDIATE"}), ++ __entry->sn, __print_amsdu(__entry->pkt_cnt)) ++#endif /* CONFIG_RWNX_FULLMAC */ ++); ++ ++ ++TRACE_EVENT( ++ txq_queue_skb, ++ TP_PROTO(struct sk_buff *skb, struct rwnx_txq *txq, bool retry), ++ TP_ARGS(skb, txq, retry), ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(s8, credit) ++ __field(u16, q_len) ++ __field(u16, q_len_retry) ++ __field(bool, retry) ++ ), ++ TP_fast_assign( ++ __entry->skb = skb; ++ __entry->txq_idx = txq->idx; ++ __entry->credit = txq->credits; ++ __entry->q_len = skb_queue_len(&txq->sk_list); ++ __entry->q_len_retry = txq->nb_retry; ++ __entry->retry = retry; ++ ), ++ ++ TP_printk("%s skb=%p retry=%d txq_credits=%d queue_len=%d (retry = %d)", ++ __print_txq(__entry->txq_idx), __entry->skb, __entry->retry, ++ __entry->credit, __entry->q_len, __entry->q_len_retry) ++); ++ ++#ifdef CONFIG_MAC80211_TXQ ++TRACE_EVENT( ++ txq_wake, ++ TP_PROTO(struct rwnx_txq *txq), ++ TP_ARGS(txq), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, q_len) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->q_len = txq->nb_ready_mac80211; ++ ), ++ ++ TP_printk("%s mac80211_queue_len=%d", __print_txq(__entry->txq_idx), __entry->q_len) ++); ++ ++TRACE_EVENT( ++ txq_drop, ++ TP_PROTO(struct rwnx_txq *txq, unsigned long nb_drop), ++ TP_ARGS(txq, nb_drop), ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u16, nb_drop) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->nb_drop = nb_drop; ++ ), ++ ++ TP_printk("%s %u pkt have been dropped by codel in mac80211 txq", ++ __print_txq(__entry->txq_idx), __entry->nb_drop) ++); ++ ++#endif ++ ++ ++DECLARE_EVENT_CLASS( ++ idx_template, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ ), ++ TP_fast_assign( ++ __entry->idx = idx; ++ ), ++ TP_printk("idx=%d", __entry->idx) ++); ++ ++ ++DEFINE_EVENT(idx_template, txq_vif_start, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++DEFINE_EVENT(idx_template, txq_vif_stop, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++TRACE_EVENT( ++ process_hw_queue, ++ TP_PROTO(struct rwnx_hwq *hwq), ++ TP_ARGS(hwq), ++ TP_STRUCT__entry( ++ __field(u16, hwq) ++ __array(u8, credits, CONFIG_USER_MAX) ++ ), ++ TP_fast_assign( ++ __entry->hwq = hwq->id; ++ ), ++ TP_printk("hw_queue=%s hw_credits=%s", ++ __print_hwq(__entry->hwq), __print_hwq_cred(__entry->credits)) ++); ++ ++DECLARE_EVENT_CLASS( ++ sta_idx_template, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ ), ++ TP_fast_assign( ++ __entry->idx = idx; ++ ), ++ TP_printk("%s", __print_sta(__entry->idx)) ++); ++ ++DEFINE_EVENT(sta_idx_template, txq_sta_start, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++DEFINE_EVENT(sta_idx_template, txq_sta_stop, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++DEFINE_EVENT(sta_idx_template, ps_disable, ++ TP_PROTO(u16 idx), ++ TP_ARGS(idx)); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++TRACE_EVENT( ++ skb_confirm, ++ TP_PROTO(struct sk_buff *skb, struct rwnx_txq *txq, struct rwnx_hwq *hwq, ++#ifdef CONFIG_RWNX_FULLMAC ++ struct tx_cfm_tag *cfm ++#else ++ u8 cfm ++#endif ++ ), ++ ++ TP_ARGS(skb, txq, hwq, cfm), ++ ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(u8, hw_queue) ++ __array(u8, hw_credit, CONFIG_USER_MAX) ++ __field(s8, sw_credit) ++ __field(s8, sw_credit_up) ++#ifdef CONFIG_RWNX_FULLMAC ++ __field(u8, ampdu_size) ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ __field(u16, amsdu) ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ __field(u16, sn) ++#endif /* CONFIG_RWNX_FULLMAC*/ ++ ), ++ ++ TP_fast_assign( ++ __entry->skb = skb; ++ __entry->txq_idx = txq->idx; ++ __entry->hw_queue = hwq->id; ++ __entry->sw_credit = txq->credits; ++#if defined CONFIG_RWNX_FULLMAC ++ __entry->sw_credit_up = cfm->credits; ++ __entry->ampdu_size = cfm->ampdu_size; ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ __entry->amsdu = cfm->amsdu_size; ++ __entry->sn = cfm->sn; ++#endif ++#else ++ __entry->sw_credit_up = cfm ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ), ++ ++ TP_printk("%s skb=%p hw_queue=%s, hw_credits=%s, txq_credits=%d (+%d)" ++#ifdef CONFIG_RWNX_FULLMAC ++ " sn=%u ampdu=%d" ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ " amsdu=%u" ++#endif ++#endif ++ , __print_txq(__entry->txq_idx), __entry->skb, ++ __print_hwq(__entry->hw_queue), ++ __print_hwq_cred(__entry->hw_credit), ++ __entry->sw_credit, __entry->sw_credit_up ++#ifdef CONFIG_RWNX_FULLMAC ++ , __entry->sn, __entry->ampdu_size ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ , __entry->amsdu ++#endif ++#endif ++ ) ++); ++ ++TRACE_EVENT( ++ credit_update, ++ TP_PROTO(struct rwnx_txq *txq, s8_l cred_up), ++ ++ TP_ARGS(txq, cred_up), ++ ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(s8, sw_credit) ++ __field(s8, sw_credit_up) ++ ), ++ ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->sw_credit = txq->credits; ++ __entry->sw_credit_up = cred_up; ++ ), ++ ++ TP_printk("%s txq_credits=%d (%+d)", __print_txq(__entry->txq_idx), ++ __entry->sw_credit, __entry->sw_credit_up) ++) ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++DECLARE_EVENT_CLASS( ++ ps_template, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ __field(u16, ready_ps) ++ __field(u16, sp_ps) ++ __field(u16, ready_uapsd) ++ __field(u16, sp_uapsd) ++ ), ++ TP_fast_assign( ++ __entry->idx = sta->sta_idx; ++ __entry->ready_ps = sta->ps.pkt_ready[LEGACY_PS_ID]; ++ __entry->sp_ps = sta->ps.sp_cnt[LEGACY_PS_ID]; ++ __entry->ready_uapsd = sta->ps.pkt_ready[UAPSD_ID]; ++ __entry->sp_uapsd = sta->ps.sp_cnt[UAPSD_ID]; ++ ), ++ ++ TP_printk("%s [PS] ready=%d sp=%d [UAPSD] ready=%d sp=%d", ++ __print_sta(__entry->idx), __entry->ready_ps, __entry->sp_ps, ++ __entry->ready_uapsd, __entry->sp_uapsd) ++); ++ ++DEFINE_EVENT(ps_template, ps_queue, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta)); ++ ++DEFINE_EVENT(ps_template, ps_push, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta)); ++ ++DEFINE_EVENT(ps_template, ps_enable, ++ TP_PROTO(struct rwnx_sta *sta), ++ TP_ARGS(sta)); ++ ++TRACE_EVENT( ++ ps_traffic_update, ++ TP_PROTO(u16 sta_idx, u8 traffic, bool uapsd), ++ ++ TP_ARGS(sta_idx, traffic, uapsd), ++ ++ TP_STRUCT__entry( ++ __field(u16, sta_idx) ++ __field(u8, traffic) ++ __field(bool, uapsd) ++ ), ++ ++ TP_fast_assign( ++ __entry->sta_idx = sta_idx; ++ __entry->traffic = traffic; ++ __entry->uapsd = uapsd; ++ ), ++ ++ TP_printk("%s %s%s traffic available ", __print_sta(__entry->sta_idx), ++ __entry->traffic ? "" : "no more ", ++ __entry->uapsd ? "U-APSD" : "legacy PS") ++); ++ ++TRACE_EVENT( ++ ps_traffic_req, ++ TP_PROTO(struct rwnx_sta *sta, u16 pkt_req, u8 ps_id), ++ TP_ARGS(sta, pkt_req, ps_id), ++ TP_STRUCT__entry( ++ __field(u16, idx) ++ __field(u16, pkt_req) ++ __field(u8, ps_id) ++ __field(u16, ready) ++ __field(u16, sp) ++ ), ++ TP_fast_assign( ++ __entry->idx = sta->sta_idx; ++ __entry->pkt_req = pkt_req; ++ __entry->ps_id = ps_id; ++ __entry->ready = sta->ps.pkt_ready[ps_id]; ++ __entry->sp = sta->ps.sp_cnt[ps_id]; ++ ), ++ ++ TP_printk("%s %s traffic request %d pkt (ready=%d, sp=%d)", ++ __print_sta(__entry->idx), ++ __entry->ps_id == UAPSD_ID ? "U-APSD" : "legacy PS", ++ __entry->pkt_req, __entry->ready, __entry->sp) ++); ++ ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++TRACE_EVENT( ++ amsdu_subframe, ++ TP_PROTO(struct rwnx_sw_txhdr *sw_txhdr), ++ TP_ARGS(sw_txhdr), ++ TP_STRUCT__entry( ++ __field(struct sk_buff *, skb) ++ __field(u16, txq_idx) ++ __field(u8, nb) ++ __field(u32, len) ++ ), ++ TP_fast_assign( ++ __entry->skb = sw_txhdr->skb; ++ __entry->nb = sw_txhdr->amsdu.nb; ++ __entry->len = sw_txhdr->amsdu.len; ++ __entry->txq_idx = sw_txhdr->txq->idx; ++ ), ++ ++ TP_printk("%s skb=%p %s nb_subframe=%d, len=%u", ++ __print_txq(__entry->txq_idx), __entry->skb, ++ (__entry->nb == 2) ? "Start new AMSDU" : "Add subframe", ++ __entry->nb, __entry->len) ++); ++#endif ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++TRACE_EVENT( ++ mu_group_update, ++ TP_PROTO(struct rwnx_mu_group *group), ++ TP_ARGS(group), ++ TP_STRUCT__entry( ++ __field(u8, nb_user) ++ __field(u8, group_id) ++ __array(u8, users, CONFIG_USER_MAX) ++ ), ++ TP_fast_assign( ++ int i; ++ __entry->nb_user = group->user_cnt; ++ for (i = 0; i < CONFIG_USER_MAX ; i++) { ++ if (group->users[i]) { ++ __entry->users[i] = group->users[i]->sta_idx; ++ } else { ++ __entry->users[i] = 0xff; ++ } ++ } ++ ++ __entry->group_id = group->group_id; ++ ), ++ ++ TP_printk("Group-id = %d, Users = %s", ++ __entry->group_id, ++ __print_mu_group(__entry->nb_user, __entry->users)) ++); ++ ++TRACE_EVENT( ++ mu_group_delete, ++ TP_PROTO(int group_id), ++ TP_ARGS(group_id), ++ TP_STRUCT__entry( ++ __field(u8, group_id) ++ ), ++ TP_fast_assign( ++ __entry->group_id = group_id; ++ ), ++ ++ TP_printk("Group-id = %d", __entry->group_id) ++); ++ ++TRACE_EVENT( ++ mu_group_selection, ++ TP_PROTO(struct rwnx_sta *sta, int group_id), ++ TP_ARGS(sta, group_id), ++ TP_STRUCT__entry( ++ __field(u8, sta_idx) ++ __field(u8, group_id) ++ ), ++ TP_fast_assign( ++ __entry->sta_idx = sta->sta_idx; ++ __entry->group_id = group_id; ++ ), ++ ++ TP_printk("[Sta %d] Group-id = %d", __entry->sta_idx, __entry->group_id) ++); ++ ++TRACE_EVENT( ++ txq_select_mu_group, ++ TP_PROTO(struct rwnx_txq *txq, int group_id, int pos), ++ ++ TP_ARGS(txq, group_id, pos), ++ ++ TP_STRUCT__entry( ++ __field(u16, txq_idx) ++ __field(u8, group_id) ++ __field(u8, pos) ++ ), ++ TP_fast_assign( ++ __entry->txq_idx = txq->idx; ++ __entry->group_id = group_id; ++ __entry->pos = pos; ++ ), ++ ++ TP_printk("%s: group=%d pos=%d", __print_txq(__entry->txq_idx), ++ __entry->group_id, __entry->pos) ++); ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* ! CONFIG_RWNX_FHOST */ ++ ++/***************************************************************************** ++ * TRACE functions for MESH ++ ****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++DECLARE_EVENT_CLASS( ++ mesh_path_template, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path), ++ TP_STRUCT__entry( ++ __field(u8, idx) ++ __field(u8, next_hop_sta) ++ __array(u8, tgt_mac, ETH_ALEN) ++ ), ++ ++ TP_fast_assign( ++ __entry->idx = mesh_path->path_idx; ++ memcpy(__entry->tgt_mac, &mesh_path->tgt_mac_addr, ETH_ALEN); ++ if (mesh_path->p_nhop_sta) ++ __entry->next_hop_sta = mesh_path->p_nhop_sta->sta_idx; ++ else ++ __entry->next_hop_sta = 0xff; ++ ), ++ ++ TP_printk("Mpath(%d): target=%pM next_hop=STA-%d", ++ __entry->idx, __entry->tgt_mac, __entry->next_hop_sta) ++); ++ ++DEFINE_EVENT(mesh_path_template, mesh_create_path, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path)); ++ ++DEFINE_EVENT(mesh_path_template, mesh_delete_path, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path)); ++ ++DEFINE_EVENT(mesh_path_template, mesh_update_path, ++ TP_PROTO(struct rwnx_mesh_path *mesh_path), ++ TP_ARGS(mesh_path)); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/***************************************************************************** ++ * TRACE functions for RADAR ++ ****************************************************************************/ ++#ifdef CONFIG_RWNX_RADAR ++TRACE_EVENT( ++ radar_pulse, ++ TP_PROTO(u8 chain, struct radar_pulse *pulse), ++ TP_ARGS(chain, pulse), ++ TP_STRUCT__entry( ++ __field(u8, chain) ++ __field(s16, freq) ++ __field(u16, pri) ++ __field(u8, len) ++ __field(u8, fom) ++ ), ++ TP_fast_assign( ++ __entry->freq = pulse->freq * 2; ++ __entry->len = pulse->len * 2; ++ __entry->fom = pulse->fom * 6; ++ __entry->pri = pulse->rep; ++ __entry->chain = chain; ++ ), ++ ++ TP_printk("%s: PRI=%.5d LEN=%.3d FOM=%.2d%% freq=%dMHz ", ++ __print_symbolic(__entry->chain, ++ {RWNX_RADAR_RIU, "RIU"}, ++ {RWNX_RADAR_FCU, "FCU"}), ++ __entry->pri, __entry->len, __entry->fom, __entry->freq) ++ ); ++ ++TRACE_EVENT( ++ radar_detected, ++ TP_PROTO(u8 chain, u8 region, s16 freq, u8 type, u16 pri), ++ TP_ARGS(chain, region, freq, type, pri), ++ TP_STRUCT__entry( ++ __field(u8, chain) ++ __field(u8, region) ++ __field(s16, freq) ++ __field(u8, type) ++ __field(u16, pri) ++ ), ++ TP_fast_assign( ++ __entry->chain = chain; ++ __entry->region = region; ++ __entry->freq = freq; ++ __entry->type = type; ++ __entry->pri = pri; ++ ), ++ TP_printk("%s: region=%s type=%d freq=%dMHz (pri=%dus)", ++ __print_symbolic(__entry->chain, ++ {RWNX_RADAR_RIU, "RIU"}, ++ {RWNX_RADAR_FCU, "FCU"}), ++ __print_symbolic(__entry->region, ++ {NL80211_DFS_UNSET, "UNSET"}, ++ {NL80211_DFS_FCC, "FCC"}, ++ {NL80211_DFS_ETSI, "ETSI"}, ++ {NL80211_DFS_JP, "JP"}), ++ __entry->type, __entry->freq, __entry->pri) ++); ++ ++TRACE_EVENT( ++ radar_set_region, ++ TP_PROTO(u8 region), ++ TP_ARGS(region), ++ TP_STRUCT__entry( ++ __field(u8, region) ++ ), ++ TP_fast_assign( ++ __entry->region = region; ++ ), ++ TP_printk("region=%s", ++ __print_symbolic(__entry->region, ++ {NL80211_DFS_UNSET, "UNSET"}, ++ {NL80211_DFS_FCC, "FCC"}, ++ {NL80211_DFS_ETSI, "ETSI"}, ++ {NL80211_DFS_JP, "JP"})) ++); ++ ++TRACE_EVENT( ++ radar_enable_detection, ++ TP_PROTO(u8 region, u8 enable, u8 chain), ++ TP_ARGS(region, enable, chain), ++ TP_STRUCT__entry( ++ __field(u8, region) ++ __field(u8, chain) ++ __field(u8, enable) ++ ), ++ TP_fast_assign( ++ __entry->chain = chain; ++ __entry->enable = enable; ++ __entry->region = region; ++ ), ++ TP_printk("%s: %s radar detection %s", ++ __print_symbolic(__entry->chain, ++ {RWNX_RADAR_RIU, "RIU"}, ++ {RWNX_RADAR_FCU, "FCU"}), ++ __print_symbolic(__entry->enable, ++ {RWNX_RADAR_DETECT_DISABLE, "Disable"}, ++ {RWNX_RADAR_DETECT_ENABLE, "Enable (no report)"}, ++ {RWNX_RADAR_DETECT_REPORT, "Enable"}), ++ __entry->enable == RWNX_RADAR_DETECT_DISABLE ? "" : ++ __print_symbolic(__entry->region, ++ {NL80211_DFS_UNSET, "UNSET"}, ++ {NL80211_DFS_FCC, "FCC"}, ++ {NL80211_DFS_ETSI, "ETSI"}, ++ {NL80211_DFS_JP, "JP"})) ++); ++#endif /* CONFIG_RWNX_RADAR */ ++ ++/***************************************************************************** ++ * TRACE functions for IPC message ++ ****************************************************************************/ ++#include "rwnx_strs.h" ++ ++DECLARE_EVENT_CLASS( ++ ipc_msg_template, ++ TP_PROTO(u16 id), ++ TP_ARGS(id), ++ TP_STRUCT__entry( ++ __field(u16, id) ++ ), ++ TP_fast_assign( ++ __entry->id = id; ++ ), ++ ++ TP_printk("%s (%d - %d)", RWNX_ID2STR(__entry->id), ++ MSG_T(__entry->id), MSG_I(__entry->id)) ++); ++ ++DEFINE_EVENT(ipc_msg_template, msg_send, ++ TP_PROTO(u16 id), ++ TP_ARGS(id)); ++ ++DEFINE_EVENT(ipc_msg_template, msg_recv, ++ TP_PROTO(u16 id), ++ TP_ARGS(id)); ++ ++ ++ ++#endif /* !defined(_RWNX_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ) */ ++ ++#undef TRACE_INCLUDE_PATH ++#undef TRACE_INCLUDE_FILE ++//#define TRACE_INCLUDE_PATH . ++#define TRACE_INCLUDE_PATH AIC_TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_FILE rwnx_events ++#include +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c +new file mode 100644 +index 000000000000..9151c8b81f59 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c +@@ -0,0 +1,48 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_fw_trace.c ++ * ++ * Copyright (C) RivieraWaves 2017-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_fw_trace.h" ++#include "aicwf_debug.h" ++ ++int rwnx_fw_log_init(struct rwnx_fw_log *fw_log) ++{ ++ u8 *buf = kmalloc(FW_LOG_SIZE, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ fw_log->buf.data = buf; ++ fw_log->buf.start = fw_log->buf.data; ++ fw_log->buf.size = 0; ++ fw_log->buf.end = fw_log->buf.data; ++ fw_log->buf.dataend = fw_log->buf.data + FW_LOG_SIZE; ++ spin_lock_init(&fw_log->lock); ++ ++ AICWFDBG(LOGINFO, "fw_log_init: %lx, %lx\n", (unsigned long)fw_log->buf.start, (unsigned long)(fw_log->buf.dataend)); ++ return 0; ++} ++ ++void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log) ++{ ++ if (!fw_log) ++ return; ++ ++ if (fw_log->buf.data) ++ kfree(fw_log->buf.data); ++ fw_log->buf.start = NULL; ++ fw_log->buf.end = NULL; ++ fw_log->buf.size = 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h +new file mode 100644 +index 000000000000..7956790957c3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h +@@ -0,0 +1,35 @@ ++/** ++ ****************************************************************************** ++ * ++ * rwnx_fw_trace.h ++ * ++ * Copyright (C) RivieraWaves 2017-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_FW_TRACE_H_ ++#define _RWNX_FW_TRACE_H_ ++ ++#include ++#include ++#include ++ ++#define FW_LOG_SIZE (10240) ++ ++struct rwnx_fw_log_buf { ++ uint8_t *data; ++ uint8_t *start; ++ uint8_t *end; ++ uint8_t *dataend; ++ uint32_t size; ++}; ++ ++struct rwnx_fw_log { ++ struct rwnx_fw_log_buf buf; ++ spinlock_t lock; ++}; ++ ++int rwnx_fw_log_init(struct rwnx_fw_log *fw_log); ++void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log); ++#endif /* _RWNX_FW_TRACE_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c +new file mode 100644 +index 000000000000..7f6333d91e59 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c +@@ -0,0 +1,408 @@ ++#include ++#ifdef ANDROID_PLATFORM ++#include "net/wireless/core.h" ++#endif ++#include ++ ++#undef NL80211_MCGRP_MLME ++#define NL80211_MCGRP_MLME 3 ++//#if IS_ENABLED(CONFIG_GKI_OPT_FEATURES) && IS_ENABLED(CONFIG_ANDROID) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++ ++static struct genl_family rwnx_nl80211_fam; ++ ++static bool __rwnx_cfg80211_unexpected_frame(struct net_device *dev, u8 cmd, ++ const u8 *addr, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid); ++ ++ if (!nlportid) ++ return false; ++ ++ msg = nlmsg_new(100, gfp); ++ if (!msg) ++ return true; ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, cmd); ++ if (!hdr) { ++ nlmsg_free(msg); ++ return true; ++ } ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || ++ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || ++ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); ++ return true; ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++ return true; ++} ++ ++bool rwnx_cfg80211_rx_spurious_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ bool ret; ++ ++ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && ++ wdev->iftype != NL80211_IFTYPE_P2P_GO)) { ++ return false; ++ } ++ ret = __rwnx_cfg80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, ++ addr, gfp); ++ return ret; ++} ++ ++bool rwnx_cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ bool ret; ++ ++ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && ++ wdev->iftype != NL80211_IFTYPE_P2P_GO && ++ wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { ++ return false; ++ } ++ ret = __rwnx_cfg80211_unexpected_frame(dev, ++ NL80211_CMD_UNEXPECTED_4ADDR_FRAME, ++ addr, gfp); ++ return ret; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) ++void rwnx_cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, ++ const u8 *ie, u8 ie_len, ++ int sig_dbm, gfp_t gfp) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ ++ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) ++ return; ++ ++ msg = nlmsg_new(100 + ie_len, gfp); ++ if (!msg) ++ return; ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, NL80211_CMD_NEW_PEER_CANDIDATE); ++ if (!hdr) { ++ nlmsg_free(msg); ++ return; ++ } ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || ++ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || ++ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || ++ (ie_len && ie && ++ nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) || ++ (sig_dbm && ++ nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm))) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++#define NL80211_MCGRP_MLME 3 ++ genlmsg_multicast_netns(&rwnx_nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, ++ NL80211_MCGRP_MLME, gfp); ++ return; ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++} ++#endif ++ ++void rwnx_cfg80211_report_obss_beacon(struct wiphy *wiphy, ++ const u8 *frame, size_t len, ++ int freq, int sig_dbm) ++{ ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ struct cfg80211_beacon_registration *reg; ++ ++ spin_lock_bh(&rdev->beacon_registrations_lock); ++ list_for_each_entry(reg, &rdev->beacon_registrations, list) { ++ msg = nlmsg_new(len + 100, GFP_ATOMIC); ++ if (!msg) { ++ spin_unlock_bh(&rdev->beacon_registrations_lock); ++ return; ++ } ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, NL80211_CMD_FRAME); ++ if (!hdr) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || ++ (freq && ++ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || ++ (sig_dbm && ++ nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || ++ nla_put(msg, NL80211_ATTR_FRAME, len, frame)) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid); ++ } ++ spin_unlock_bh(&rdev->beacon_registrations_lock); ++ return; ++ ++ nla_put_failure: ++ spin_unlock_bh(&rdev->beacon_registrations_lock); ++ nlmsg_free(msg); ++} ++ ++static int rwnx_nl80211_send_chandef(struct sk_buff *msg, ++ const struct cfg80211_chan_def *chandef) ++{ ++ if (WARN_ON(!cfg80211_chandef_valid(chandef))) ++ return -EINVAL; ++ ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, ++ chandef->chan->center_freq)) ++ return -ENOBUFS; ++ switch (chandef->width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ case NL80211_CHAN_WIDTH_40: ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ++ cfg80211_get_chandef_type(chandef))) ++ return -ENOBUFS; ++ break; ++ default: ++ break; ++ } ++ if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width)) ++ return -ENOBUFS; ++ if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1)) ++ return -ENOBUFS; ++ if (chandef->center_freq2 && ++ nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2)) ++ return -ENOBUFS; ++ return 0; ++} ++ ++void rwnx_cfg80211_ch_switch_notify(struct cfg80211_registered_device *rdev, ++ struct net_device *netdev, ++ struct cfg80211_chan_def *chandef, ++ gfp_t gfp, ++ enum nl80211_commands notif, ++ u8 count) ++{ ++ struct sk_buff *msg; ++ void *hdr; ++ ++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); ++ if (!msg) ++ return; ++ ++ hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, notif); ++ if (!hdr) { ++ nlmsg_free(msg); ++ return; ++ } ++ ++ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) ++ goto nla_put_failure; ++ ++ if (rwnx_nl80211_send_chandef(msg, chandef)) ++ goto nla_put_failure; ++ ++ if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) && ++ (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++ genlmsg_multicast_netns(&rwnx_nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, ++ NL80211_MCGRP_MLME, gfp); ++ return; ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++} ++ ++void rwnx_cfg80211_ch_switch_started_notify(struct net_device *dev, ++ struct cfg80211_chan_def *chandef, ++ u8 count ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ , bool quiet ++ #endif ++ ) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct wiphy *wiphy = wdev->wiphy; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ ++ rwnx_cfg80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL, ++ NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count); ++} ++ ++int rwnx_regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, ++ struct ieee80211_regdomain *rd) ++{ ++ wiphy_apply_custom_regulatory(wiphy, rd); ++ return 0; ++} ++ ++void rwnx_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list) ++{ ++ unsigned long flags; ++ struct sk_buff *prev = old; ++ struct sk_buff *next = prev->next; ++ spin_lock_irqsave(&list->lock, flags); ++ WRITE_ONCE(newsk->next, next); ++ WRITE_ONCE(newsk->prev, prev); ++ WRITE_ONCE(next->prev, newsk); ++ WRITE_ONCE(prev->next, newsk); ++ list->qlen++; ++ spin_unlock_irqrestore(&list->lock, flags); ++} ++ ++bool rwnx_ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, ++ u8 *op_class) ++{ ++ u8 vht_opclass; ++ u32 freq = chandef->center_freq1; ++ ++ if (freq >= 2412 && freq <= 2472) { ++ if (chandef->width > NL80211_CHAN_WIDTH_40) ++ return false; ++ ++ /* 2.407 GHz, channels 1..13 */ ++ if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 83; /* HT40+ */ ++ else ++ *op_class = 84; /* HT40- */ ++ } else { ++ *op_class = 81; ++ } ++ ++ return true; ++ } ++ ++ if (freq == 2484) { ++ /* channel 14 is only for IEEE 802.11b */ ++ if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT) ++ return false; ++ ++ *op_class = 82; /* channel 14 */ ++ return true; ++ } ++ ++ switch (chandef->width) { ++ case NL80211_CHAN_WIDTH_80: ++ vht_opclass = 128; ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ vht_opclass = 129; ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ vht_opclass = 130; ++ break; ++ case NL80211_CHAN_WIDTH_10: ++ case NL80211_CHAN_WIDTH_5: ++ return false; /* unsupported for now */ ++ default: ++ vht_opclass = 0; ++ break; ++ } ++ ++ /* 5 GHz, channels 36..48 */ ++ if (freq >= 5180 && freq <= 5240) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 116; ++ else ++ *op_class = 117; ++ } else { ++ *op_class = 115; ++ } ++ ++ return true; ++ } ++ ++ /* 5 GHz, channels 52..64 */ ++ if (freq >= 5260 && freq <= 5320) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 119; ++ else ++ *op_class = 120; ++ } else { ++ *op_class = 118; ++ } ++ ++ return true; ++ } ++ ++ /* 5 GHz, channels 100..144 */ ++ if (freq >= 5500 && freq <= 5720) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 122; ++ else ++ *op_class = 123; ++ } else { ++ *op_class = 121; ++ } ++ ++ return true; ++ } ++ ++ /* 5 GHz, channels 149..169 */ ++ if (freq >= 5745 && freq <= 5845) { ++ if (vht_opclass) { ++ *op_class = vht_opclass; ++ } else if (chandef->width == NL80211_CHAN_WIDTH_40) { ++ if (freq > chandef->chan->center_freq) ++ *op_class = 126; ++ else ++ *op_class = 127; ++ } else if (freq <= 5805) { ++ *op_class = 124; ++ } else { ++ *op_class = 125; ++ } ++ ++ return true; ++ } ++ ++ /* 56.16 GHz, channel 1..4 */ ++ if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) { ++ if (chandef->width >= NL80211_CHAN_WIDTH_40) ++ return false; ++ ++ *op_class = 180; ++ return true; ++ } ++ ++ /* not supported yet */ ++ return false; ++} ++ ++int rwnx_call_usermodehelper(const char *path, char **argv, char **envp, int wait) ++{ ++ return -1; ++} ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h +new file mode 100644 +index 000000000000..a41f57832279 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h +@@ -0,0 +1,72 @@ ++#ifndef __RWNX_GKI_H ++#define __RWNX_GKI_H ++ ++#ifdef ANDROID_PLATFORM ++#include "net/wireless/core.h" ++#endif ++ ++//#if IS_ENABLED(CONFIG_GKI_OPT_FEATURES) && IS_ENABLED(CONFIG_ANDROID) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++ ++ ++bool rwnx_cfg80211_rx_spurious_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp); ++ ++bool rwnx_cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, ++ const u8 *addr, gfp_t gfp); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) ++void rwnx_cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, ++ const u8 *ie, u8 ie_len, ++ int sig_dbm, gfp_t gfp); ++#endif ++ ++void rwnx_cfg80211_report_obss_beacon(struct wiphy *wiphy, ++ const u8 *frame, size_t len, ++ int freq, int sig_dbm); ++ ++void rwnx_cfg80211_ch_switch_notify(struct cfg80211_registered_device *rdev, ++ struct net_device *netdev, ++ struct cfg80211_chan_def *chandef, ++ gfp_t gfp, ++ enum nl80211_commands notif, ++ u8 count); ++ ++void rwnx_cfg80211_ch_switch_started_notify(struct net_device *dev, ++ struct cfg80211_chan_def *chandef, ++ u8 count ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ , bool quiet ++ #endif ++ ); ++ ++int rwnx_regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, ++ struct ieee80211_regdomain *rd); ++ ++void rwnx_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list); ++ ++bool rwnx_ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, ++ u8 *op_class); ++ ++int rwnx_call_usermodehelper(const char *path, char **argv, char **envp, int wait); ++ ++#else ++ ++#define rwnx_cfg80211_rx_spurious_frame cfg80211_rx_spurious_frame ++#define rwnx_cfg80211_rx_unexpected_4addr_frame cfg80211_rx_unexpected_4addr_frame ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) ++#define rwnx_cfg80211_notify_new_peer_candidate cfg80211_notify_new_peer_candidate ++#endif ++ ++#define rwnx_cfg80211_report_obss_beacon cfg80211_report_obss_beacon ++#define rwnx_cfg80211_ch_switch_notify cfg80211_ch_switch_notify ++#define rwnx_cfg80211_ch_switch_started_notify cfg80211_ch_switch_started_notify ++#define rwnx_regulatory_set_wiphy_regd_sync_rtnl regulatory_set_wiphy_regd_sync_rtnl ++#define rwnx_skb_append skb_append ++#define rwnx_ieee80211_chandef_to_operating_class ieee80211_chandef_to_operating_class ++#define rwnx_call_usermodehelper call_usermodehelper ++ ++#endif ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c +new file mode 100644 +index 000000000000..8ba95b703f17 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c +@@ -0,0 +1,65 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_irqs.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++ ++#include "rwnx_defs.h" ++#include "ipc_host.h" ++#include "rwnx_prof.h" ++ ++/** ++ * rwnx_irq_hdlr - IRQ handler ++ * ++ * Handler registerd by the platform driver ++ */ ++irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id) ++{ ++ struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)dev_id; ++ disable_irq_nosync(irq); ++ tasklet_schedule(&rwnx_hw->task); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * rwnx_task - Bottom half for IRQ handler ++ * ++ * Read irq status and process accordingly ++ */ ++void rwnx_task(unsigned long data) ++{ ++ struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)data; ++ ++#if 0 ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ u32 status, statuses = 0; ++ ++ /* Ack unconditionnally in case ipc_host_get_status does not see the irq */ ++ rwnx_plat->ack_irq(rwnx_plat); ++ ++ while ((status = ipc_host_get_status(rwnx_hw->ipc_env))) { ++ statuses |= status; ++ /* All kinds of IRQs will be handled in one shot (RX, MSG, DBG, ...) ++ * this will ack IPC irqs not the cfpga irqs */ ++ ipc_host_irq(rwnx_hw->ipc_env, status); ++ ++ rwnx_plat->ack_irq(rwnx_plat); ++ } ++#endif ++ //if (statuses & IPC_IRQ_E2A_RXDESC) ++ // rwnx_hw->stats.last_rx = now; ++ //if (statuses & IPC_IRQ_E2A_TXCFM) ++ // rwnx_hw->stats.last_tx = now; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ rwnx_hwq_process_all(rwnx_hw); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++#if 0 ++ enable_irq(rwnx_platform_get_irq(rwnx_plat)); ++#endif ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h +new file mode 100644 +index 000000000000..d3fb4519c615 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h +@@ -0,0 +1,20 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_irqs.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_IRQS_H_ ++#define _RWNX_IRQS_H_ ++ ++#include ++ ++/* IRQ handler to be registered by platform driver */ ++irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id); ++ ++void rwnx_task(unsigned long data); ++ ++#endif /* _RWNX_IRQS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c +new file mode 100644 +index 000000000000..4773735ffe64 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c +@@ -0,0 +1,6124 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_main.c ++ * ++ * @brief Entry point of the RWNX driver ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_defs.h" ++#include "rwnx_dini.h" ++#include "rwnx_msg_tx.h" ++#include "reg_access.h" ++#include "hal_desc.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_cfgfile.h" ++#include "rwnx_irqs.h" ++#include "rwnx_radar.h" ++#include "rwnx_version.h" ++#ifdef CONFIG_RWNX_BFMER ++#include "rwnx_bfmer.h" ++#endif //(CONFIG_RWNX_BFMER) ++#include "rwnx_tdls.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "rwnx_version.h" ++#include "rwnx_main.h" ++#include "aicwf_txrxif.h" ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#endif ++#ifdef AICWF_USB_SUPPORT ++#include "aicwf_usb.h" ++#endif ++#include "aic_bsp_export.h" ++#include "aicwf_compat_8800dc.h" ++#include "aicwf_compat_8800d80.h" ++#include "rwnx_wakelock.h" ++#ifdef CONFIG_SDIO_BT ++#include "aic_btsdio.h" ++#endif ++#include "aic_priv_cmd.h" ++ ++#define RW_DRV_DESCRIPTION "RivieraWaves 11nac driver for Linux cfg80211" ++#define RW_DRV_COPYRIGHT "Copyright(c) 2015-2017 RivieraWaves" ++#define RW_DRV_AUTHOR "RivieraWaves S.A.S" ++ ++#define RWNX_PRINT_CFM_ERR(req) \ ++ printk(KERN_CRIT "%s: Status Error(%d)\n", #req, (&req##_cfm)->status) ++ ++extern char country_code[]; ++ ++#define RWNX_HT_CAPABILITIES \ ++{ \ ++ .ht_supported = true, \ ++ .cap = 0, \ ++ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, \ ++ .mcs = { \ ++ .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \ ++ .rx_highest = cpu_to_le16(65), \ ++ .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ ++ }, \ ++} ++ ++#define RWNX_VHT_CAPABILITIES \ ++{ \ ++ .vht_supported = false, \ ++ .cap = \ ++ (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT),\ ++ .vht_mcs = { \ ++ .rx_mcs_map = cpu_to_le16( \ ++ IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 14), \ ++ .tx_mcs_map = cpu_to_le16( \ ++ IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | \ ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << 14), \ ++ } \ ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) || defined(CONFIG_HE_FOR_OLD_KERNEL) ++#define RWNX_HE_CAPABILITIES \ ++{ \ ++ .has_he = false, \ ++ .he_cap_elem = { \ ++ .mac_cap_info[0] = 0, \ ++ .mac_cap_info[1] = 0, \ ++ .mac_cap_info[2] = 0, \ ++ .mac_cap_info[3] = 0, \ ++ .mac_cap_info[4] = 0, \ ++ .mac_cap_info[5] = 0, \ ++ .phy_cap_info[0] = 0, \ ++ .phy_cap_info[1] = 0, \ ++ .phy_cap_info[2] = 0, \ ++ .phy_cap_info[3] = 0, \ ++ .phy_cap_info[4] = 0, \ ++ .phy_cap_info[5] = 0, \ ++ .phy_cap_info[6] = 0, \ ++ .phy_cap_info[7] = 0, \ ++ .phy_cap_info[8] = 0, \ ++ .phy_cap_info[9] = 0, \ ++ .phy_cap_info[10] = 0, \ ++ }, \ ++ .he_mcs_nss_supp = { \ ++ .rx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .tx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .rx_mcs_160 = cpu_to_le16(0xffff), \ ++ .tx_mcs_160 = cpu_to_le16(0xffff), \ ++ .rx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ .tx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ }, \ ++ .ppe_thres = {0x08, 0x1c, 0x07}, \ ++} ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++#define RWNX_HE_CAPABILITIES \ ++{ \ ++ .has_he = false, \ ++ .he_cap_elem = { \ ++ .mac_cap_info[0] = 0, \ ++ .mac_cap_info[1] = 0, \ ++ .mac_cap_info[2] = 0, \ ++ .mac_cap_info[3] = 0, \ ++ .mac_cap_info[4] = 0, \ ++ .phy_cap_info[0] = 0, \ ++ .phy_cap_info[1] = 0, \ ++ .phy_cap_info[2] = 0, \ ++ .phy_cap_info[3] = 0, \ ++ .phy_cap_info[4] = 0, \ ++ .phy_cap_info[5] = 0, \ ++ .phy_cap_info[6] = 0, \ ++ .phy_cap_info[7] = 0, \ ++ .phy_cap_info[8] = 0, \ ++ }, \ ++ .he_mcs_nss_supp = { \ ++ .rx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .tx_mcs_80 = cpu_to_le16(0xfffa), \ ++ .rx_mcs_160 = cpu_to_le16(0xffff), \ ++ .tx_mcs_160 = cpu_to_le16(0xffff), \ ++ .rx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ .tx_mcs_80p80 = cpu_to_le16(0xffff), \ ++ }, \ ++ .ppe_thres = {0x08, 0x1c, 0x07}, \ ++} ++#endif ++#endif ++ ++#define RATE(_bitrate, _hw_rate, _flags) { \ ++ .bitrate = (_bitrate), \ ++ .flags = (_flags), \ ++ .hw_value = (_hw_rate), \ ++} ++ ++#define CHAN(_freq) { \ ++ .center_freq = (_freq), \ ++ .max_power = 30, /* FIXME */ \ ++} ++ ++static struct ieee80211_rate rwnx_ratetable[] = { ++ RATE(10, 0x00, 0), ++ RATE(20, 0x01, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(55, 0x02, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(110, 0x03, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(60, 0x04, 0), ++ RATE(90, 0x05, 0), ++ RATE(120, 0x06, 0), ++ RATE(180, 0x07, 0), ++ RATE(240, 0x08, 0), ++ RATE(360, 0x09, 0), ++ RATE(480, 0x0A, 0), ++ RATE(540, 0x0B, 0), ++}; ++ ++/* The channels indexes here are not used anymore */ ++static struct ieee80211_channel rwnx_2ghz_channels[] = { ++ CHAN(2412), ++ CHAN(2417), ++ CHAN(2422), ++ CHAN(2427), ++ CHAN(2432), ++ CHAN(2437), ++ CHAN(2442), ++ CHAN(2447), ++ CHAN(2452), ++ CHAN(2457), ++ CHAN(2462), ++ CHAN(2467), ++ CHAN(2472), ++ CHAN(2484), ++ // Extra channels defined only to be used for PHY measures. ++ // Enabled only if custregd and custchan parameters are set ++ CHAN(2390), ++ CHAN(2400), ++ CHAN(2410), ++ CHAN(2420), ++ CHAN(2430), ++ CHAN(2440), ++ CHAN(2450), ++ CHAN(2460), ++ CHAN(2470), ++ CHAN(2480), ++ CHAN(2490), ++ CHAN(2500), ++ CHAN(2510), ++}; ++ ++static struct ieee80211_channel rwnx_5ghz_channels[] = { ++ CHAN(5180), // 36 - 20MHz ++ CHAN(5200), // 40 - 20MHz ++ CHAN(5220), // 44 - 20MHz ++ CHAN(5240), // 48 - 20MHz ++ CHAN(5260), // 52 - 20MHz ++ CHAN(5280), // 56 - 20MHz ++ CHAN(5300), // 60 - 20MHz ++ CHAN(5320), // 64 - 20MHz ++ CHAN(5500), // 100 - 20MHz ++ CHAN(5520), // 104 - 20MHz ++ CHAN(5540), // 108 - 20MHz ++ CHAN(5560), // 112 - 20MHz ++ CHAN(5580), // 116 - 20MHz ++ CHAN(5600), // 120 - 20MHz ++ CHAN(5620), // 124 - 20MHz ++ CHAN(5640), // 128 - 20MHz ++ CHAN(5660), // 132 - 20MHz ++ CHAN(5680), // 136 - 20MHz ++ CHAN(5700), // 140 - 20MHz ++ CHAN(5720), // 144 - 20MHz ++ CHAN(5745), // 149 - 20MHz ++ CHAN(5765), // 153 - 20MHz ++ CHAN(5785), // 157 - 20MHz ++ CHAN(5805), // 161 - 20MHz ++ CHAN(5825), // 165 - 20MHz ++ // Extra channels defined only to be used for PHY measures. ++ // Enabled only if custregd and custchan parameters are set ++ CHAN(5190), ++ CHAN(5210), ++ CHAN(5230), ++ CHAN(5250), ++ CHAN(5270), ++ CHAN(5290), ++ CHAN(5310), ++ CHAN(5330), ++ CHAN(5340), ++ CHAN(5350), ++ CHAN(5360), ++ CHAN(5370), ++ CHAN(5380), ++ CHAN(5390), ++ CHAN(5400), ++ CHAN(5410), ++ CHAN(5420), ++ CHAN(5430), ++ CHAN(5440), ++ CHAN(5450), ++ CHAN(5460), ++ CHAN(5470), ++ CHAN(5480), ++ CHAN(5490), ++ CHAN(5510), ++ CHAN(5530), ++ CHAN(5550), ++ CHAN(5570), ++ CHAN(5590), ++ CHAN(5610), ++ CHAN(5630), ++ CHAN(5650), ++ CHAN(5670), ++ CHAN(5690), ++ CHAN(5710), ++ CHAN(5730), ++ CHAN(5750), ++ CHAN(5760), ++ CHAN(5770), ++ CHAN(5780), ++ CHAN(5790), ++ CHAN(5800), ++ CHAN(5810), ++ CHAN(5820), ++ CHAN(5830), ++ CHAN(5840), ++ CHAN(5850), ++ CHAN(5860), ++ CHAN(5870), ++ CHAN(5880), ++ CHAN(5890), ++ CHAN(5900), ++ CHAN(5910), ++ CHAN(5920), ++ CHAN(5930), ++ CHAN(5940), ++ CHAN(5950), ++ CHAN(5960), ++ CHAN(5970), ++}; ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) || defined(CONFIG_HE_FOR_OLD_KERNEL) ++struct ieee80211_sband_iftype_data rwnx_he_capa = { ++ .types_mask = BIT(NL80211_IFTYPE_STATION)|BIT(NL80211_IFTYPE_AP), ++ .he_cap = RWNX_HE_CAPABILITIES, ++}; ++#endif ++ ++static struct ieee80211_supported_band rwnx_band_2GHz = { ++ .channels = rwnx_2ghz_channels, ++ .n_channels = ARRAY_SIZE(rwnx_2ghz_channels) - 13, // -13 to exclude extra channels ++ .bitrates = rwnx_ratetable, ++ .n_bitrates = ARRAY_SIZE(rwnx_ratetable), ++ .ht_cap = RWNX_HT_CAPABILITIES, ++ .vht_cap = RWNX_VHT_CAPABILITIES, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ .iftype_data = &rwnx_he_capa, ++ .n_iftype_data = 1, ++#endif ++}; ++ ++static struct ieee80211_supported_band rwnx_band_5GHz = { ++ .channels = rwnx_5ghz_channels, ++ .n_channels = ARRAY_SIZE(rwnx_5ghz_channels) - 59, // -59 to exclude extra channels ++ .bitrates = &rwnx_ratetable[4], ++ .n_bitrates = ARRAY_SIZE(rwnx_ratetable) - 4, ++ .ht_cap = RWNX_HT_CAPABILITIES, ++ .vht_cap = RWNX_VHT_CAPABILITIES, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ .iftype_data = &rwnx_he_capa, ++ .n_iftype_data = 1, ++#endif ++}; ++ ++static struct ieee80211_iface_limit rwnx_limits[] = { ++ { .max = 1, ++ .types = BIT(NL80211_IFTYPE_STATION)}, ++ { .max = 1, ++ .types = BIT(NL80211_IFTYPE_AP)}, ++#ifdef CONFIG_USE_P2P0 ++ { .max = 2, ++#else ++ { .max = 1, ++#endif ++ .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)}, ++#ifndef CONFIG_USE_P2P0 ++ { .max = 1, ++ .types = BIT(NL80211_IFTYPE_P2P_DEVICE), ++ } ++#endif ++}; ++ ++static struct ieee80211_iface_limit rwnx_limits_dfs[] = { ++ { .max = NX_VIRT_DEV_MAX, .types = BIT(NL80211_IFTYPE_AP)} ++}; ++ ++static const struct ieee80211_iface_combination rwnx_combinations[] = { ++ { ++ .limits = rwnx_limits, ++ .n_limits = ARRAY_SIZE(rwnx_limits), ++#ifdef CONFIG_MCC ++ .num_different_channels = NX_CHAN_CTXT_CNT, ++#else ++ .num_different_channels = 1, ++#endif ++ .max_interfaces = NX_VIRT_DEV_MAX, ++ }, ++ /* Keep this combination as the last one */ ++ { ++ .limits = rwnx_limits_dfs, ++ .n_limits = ARRAY_SIZE(rwnx_limits_dfs), ++ .num_different_channels = 1, ++ .max_interfaces = NX_VIRT_DEV_MAX, ++ .radar_detect_widths = (BIT(NL80211_CHAN_WIDTH_20_NOHT) | ++ BIT(NL80211_CHAN_WIDTH_20) | ++ BIT(NL80211_CHAN_WIDTH_40) | ++ BIT(NL80211_CHAN_WIDTH_80)), ++ } ++}; ++ ++/* There isn't a lot of sense in it, but you can transmit anything you like */ ++static struct ieee80211_txrx_stypes ++rwnx_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { ++ [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_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_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_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_DEVICE] = { ++ .tx = 0xffff, ++ .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)), ++ }, ++ [NL80211_IFTYPE_MESH_POINT] = { ++ .tx = 0xffff, ++ .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) | ++ BIT(IEEE80211_STYPE_AUTH >> 4) | ++ BIT(IEEE80211_STYPE_DEAUTH >> 4)), ++ }, ++}; ++ ++ ++static u32 cipher_suites[] = { ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++ WLAN_CIPHER_SUITE_AES_CMAC, // reserved entries to enable AES-CMAC and/or SMS4 ++ WLAN_CIPHER_SUITE_SMS4, ++ 0, ++}; ++#define NB_RESERVED_CIPHER 1; ++ ++static const int rwnx_ac2hwq[1][NL80211_NUM_ACS] = { ++ { ++ [NL80211_TXQ_Q_VO] = RWNX_HWQ_VO, ++ [NL80211_TXQ_Q_VI] = RWNX_HWQ_VI, ++ [NL80211_TXQ_Q_BE] = RWNX_HWQ_BE, ++ [NL80211_TXQ_Q_BK] = RWNX_HWQ_BK ++ } ++}; ++ ++const int rwnx_tid2hwq[IEEE80211_NUM_TIDS] = { ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BK, ++ RWNX_HWQ_BK, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_VI, ++ RWNX_HWQ_VI, ++ RWNX_HWQ_VO, ++ RWNX_HWQ_VO, ++ /* TID_8 is used for management frames */ ++ RWNX_HWQ_VO, ++ /* At the moment, all others TID are mapped to BE */ ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++ RWNX_HWQ_BE, ++}; ++ ++static const int rwnx_hwq2uapsd[NL80211_NUM_ACS] = { ++ [RWNX_HWQ_VO] = IEEE80211_WMM_IE_STA_QOSINFO_AC_VO, ++ [RWNX_HWQ_VI] = IEEE80211_WMM_IE_STA_QOSINFO_AC_VI, ++ [RWNX_HWQ_BE] = IEEE80211_WMM_IE_STA_QOSINFO_AC_BE, ++ [RWNX_HWQ_BK] = IEEE80211_WMM_IE_STA_QOSINFO_AC_BK, ++}; ++ ++#define P2P_ALIVE_TIME_MS (1*1000) ++#define P2P_ALIVE_TIME_COUNT 200 ++ ++ ++extern uint8_t scanning; ++int aicwf_dbg_level = LOGERROR; ++module_param(aicwf_dbg_level, int, 0660); ++int testmode = 0; ++char aic_fw_path[200]; ++u8 chip_sub_id = 0; ++u8 chip_mcu_id = 0; ++u8 chip_id = 0; ++ ++int rwnx_init_cmd_array(void); ++void rwnx_free_cmd_array(void); ++ ++ ++/********************************************************************* ++ * helper ++ *********************************************************************/ ++struct rwnx_sta *rwnx_get_sta(struct rwnx_hw *rwnx_hw, const u8 *mac_addr) ++{ ++ int i; ++ ++ for (i = 0; i < NX_REMOTE_STA_MAX; i++) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[i]; ++ if (sta->valid && (memcmp(mac_addr, &sta->mac_addr, 6) == 0)) ++ return sta; ++ } ++ ++ return NULL; ++} ++ ++void rwnx_enable_wapi(struct rwnx_hw *rwnx_hw) ++{ ++ //cipher_suites[rwnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_SMS4; ++ rwnx_hw->wiphy->n_cipher_suites++; ++ rwnx_hw->wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; ++} ++ ++void rwnx_enable_mfp(struct rwnx_hw *rwnx_hw) ++{ ++ cipher_suites[rwnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC; ++ rwnx_hw->wiphy->n_cipher_suites++; ++} ++ ++u8 *rwnx_build_bcn(struct rwnx_bcn *bcn, struct cfg80211_beacon_data *new) ++{ ++ u8 *buf, *pos; ++ ++ if (new->head) { ++ u8 *head = kmalloc(new->head_len, GFP_KERNEL); ++ ++ if (!head) ++ return NULL; ++ ++ if (bcn->head) ++ kfree(bcn->head); ++ ++ bcn->head = head; ++ bcn->head_len = new->head_len; ++ memcpy(bcn->head, new->head, new->head_len); ++ } ++ if (new->tail) { ++ u8 *tail = kmalloc(new->tail_len, GFP_KERNEL); ++ ++ if (!tail) ++ return NULL; ++ ++ if (bcn->tail) ++ kfree(bcn->tail); ++ ++ bcn->tail = tail; ++ bcn->tail_len = new->tail_len; ++ memcpy(bcn->tail, new->tail, new->tail_len); ++ } ++ ++ if (!bcn->head) ++ return NULL; ++ ++ bcn->tim_len = 6; ++ bcn->len = bcn->head_len + bcn->tail_len + bcn->ies_len + bcn->tim_len; ++ ++ buf = kmalloc(bcn->len, GFP_KERNEL); ++ if (!buf) ++ return NULL; ++ ++ // Build the beacon buffer ++ pos = buf; ++ memcpy(pos, bcn->head, bcn->head_len); ++ pos += bcn->head_len; ++ *pos++ = WLAN_EID_TIM; ++ *pos++ = 4; ++ *pos++ = 0; ++ *pos++ = bcn->dtim; ++ *pos++ = 0; ++ *pos++ = 0; ++ if (bcn->tail) { ++ memcpy(pos, bcn->tail, bcn->tail_len); ++ pos += bcn->tail_len; ++ } ++ if (bcn->ies) { ++ memcpy(pos, bcn->ies, bcn->ies_len); ++ } ++ ++ return buf; ++} ++ ++ ++static void rwnx_del_bcn(struct rwnx_bcn *bcn) ++{ ++ if (bcn->head) { ++ kfree(bcn->head); ++ bcn->head = NULL; ++ } ++ bcn->head_len = 0; ++ ++ if (bcn->tail) { ++ kfree(bcn->tail); ++ bcn->tail = NULL; ++ } ++ bcn->tail_len = 0; ++ ++ if (bcn->ies) { ++ kfree(bcn->ies); ++ bcn->ies = NULL; ++ } ++ bcn->ies_len = 0; ++ bcn->tim_len = 0; ++ bcn->dtim = 0; ++ bcn->len = 0; ++} ++ ++/** ++ * Link channel ctxt to a vif and thus increments count for this context. ++ */ ++void rwnx_chanctx_link(struct rwnx_vif *vif, u8 ch_idx, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_chanctx *ctxt; ++ ++ if (ch_idx >= NX_CHAN_CTXT_CNT) { ++ WARN(1, "Invalid channel ctxt id %d", ch_idx); ++ return; ++ } ++ ++ vif->ch_index = ch_idx; ++ ctxt = &vif->rwnx_hw->chanctx_table[ch_idx]; ++ ctxt->count++; ++ ++ // For now chandef is NULL for STATION interface ++ if (chandef) { ++ if (!ctxt->chan_def.chan) ++ ctxt->chan_def = *chandef; ++ else { ++ // TODO. check that chandef is the same as the one already ++ // set for this ctxt ++ } ++ } ++} ++ ++/** ++ * Unlink channel ctxt from a vif and thus decrements count for this context ++ */ ++void rwnx_chanctx_unlink(struct rwnx_vif *vif) ++{ ++ struct rwnx_chanctx *ctxt; ++ ++ if (vif->ch_index == RWNX_CH_NOT_SET) ++ return; ++ ++ ctxt = &vif->rwnx_hw->chanctx_table[vif->ch_index]; ++ ++ if (ctxt->count == 0) { ++ WARN(1, "Chan ctxt ref count is already 0"); ++ } else { ++ ctxt->count--; ++ } ++ ++ if (ctxt->count == 0) { ++ if (vif->ch_index == vif->rwnx_hw->cur_chanctx) { ++ /* If current chan ctxt is no longer linked to a vif ++ disable radar detection (no need to check if it was activated) */ ++ rwnx_radar_detection_enable(&vif->rwnx_hw->radar, ++ RWNX_RADAR_DETECT_DISABLE, ++ RWNX_RADAR_RIU); ++ } ++ /* set chan to null, so that if this ctxt is relinked to a vif that ++ don't have channel information, don't use wrong information */ ++ ctxt->chan_def.chan = NULL; ++ } ++ vif->ch_index = RWNX_CH_NOT_SET; ++} ++ ++int rwnx_chanctx_valid(struct rwnx_hw *rwnx_hw, u8 ch_idx) ++{ ++ if (ch_idx >= NX_CHAN_CTXT_CNT || ++ rwnx_hw->chanctx_table[ch_idx].chan_def.chan == NULL) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static void rwnx_del_csa(struct rwnx_vif *vif) ++{ ++ struct rwnx_csa *csa = vif->ap.csa; ++ ++ if (!csa) ++ return; ++ ++ rwnx_del_bcn(&csa->bcn); ++ kfree(csa); ++ vif->ap.csa = NULL; ++} ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++static void rwnx_csa_finish(struct work_struct *ws) ++{ ++ struct rwnx_csa *csa = container_of(ws, struct rwnx_csa, work); ++ struct rwnx_vif *vif = csa->vif; ++ struct rwnx_hw *rwnx_hw = vif->rwnx_hw; ++ int error = csa->status; ++ u8 *buf, *pos; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ buf = kmalloc(csa->bcn.len, GFP_KERNEL); ++ if (!buf) { ++ printk ("%s buf fail\n", __func__); ++ return; ++ } ++ pos = buf; ++ ++ memcpy(pos, csa->bcn.head, csa->bcn.head_len); ++ pos += csa->bcn.head_len; ++ *pos++ = WLAN_EID_TIM; ++ *pos++ = 4; ++ *pos++ = 0; ++ *pos++ = csa->bcn.dtim; ++ *pos++ = 0; ++ *pos++ = 0; ++ if (csa->bcn.tail) { ++ memcpy(pos, csa->bcn.tail, csa->bcn.tail_len); ++ pos += csa->bcn.tail_len; ++ } ++ if (csa->bcn.ies) { ++ memcpy(pos, csa->bcn.ies, csa->bcn.ies_len); ++ } ++ ++ if (!error) { ++ error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, csa->bcn.len); ++ if (error) ++ return; ++ error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, ++ csa->bcn.len, csa->bcn.head_len, ++ csa->bcn.tim_len, NULL); ++ } ++ ++ if (error) { ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) ++ cfg80211_stop_iface(rwnx_hw->wiphy, &vif->wdev, GFP_KERNEL); ++ #else ++ cfg80211_disconnected(vif->ndev, 0, NULL, 0, 0, GFP_KERNEL); ++ #endif ++ } else { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) ++ wiphy_lock(rwnx_hw->wiphy); ++#else ++ mutex_lock(&vif->wdev.mtx); ++ __acquire(&vif->wdev.mtx); ++#endif ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_unlink(vif); ++ rwnx_chanctx_link(vif, csa->ch_idx, &csa->chandef); ++ if (rwnx_hw->cur_chanctx == csa->ch_idx) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ rwnx_txq_vif_start(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } else ++ rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 9, 0)) ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0); ++#elif (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION3) ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0, 0); ++#elif (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION) ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0); ++#else ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef); ++#endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) ++ wiphy_unlock(rwnx_hw->wiphy); ++#else ++ mutex_unlock(&vif->wdev.mtx); ++ __release(&vif->wdev.mtx); ++#endif ++ } ++ rwnx_del_csa(vif); ++} ++#endif ++ ++/** ++ * rwnx_external_auth_enable - Enable external authentication on a vif ++ * ++ * @vif: VIF on which external authentication must be enabled ++ * ++ * External authentication requires to start TXQ for unknown STA in ++ * order to send auth frame pusehd by user space. ++ * Note: It is assumed that fw is on the correct channel. ++ */ ++void rwnx_external_auth_enable(struct rwnx_vif *vif) ++{ ++ vif->sta.external_auth = true; ++ rwnx_txq_unk_vif_init(vif); ++ rwnx_txq_start(rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE), 0); ++} ++ ++/** ++ * rwnx_external_auth_disable - Disable external authentication on a vif ++ * ++ * @vif: VIF on which external authentication must be disabled ++ */ ++void rwnx_external_auth_disable(struct rwnx_vif *vif) ++{ ++ if (!vif->sta.external_auth) ++ return; ++ ++ vif->sta.external_auth = false; ++ rwnx_txq_unk_vif_deinit(vif); ++} ++ ++/** ++ * rwnx_update_mesh_power_mode - ++ * ++ * @vif: mesh VIF for which power mode is updated ++ * ++ * Does nothing if vif is not a mesh point interface. ++ * Since firmware doesn't support one power save mode per link select the ++ * most "active" power mode among all mesh links. ++ * Indeed as soon as we have to be active on one link we might as well be ++ * active on all links. ++ * ++ * If there is no link then the power mode for next peer is used; ++ */ ++void rwnx_update_mesh_power_mode(struct rwnx_vif *vif) ++{ ++ enum nl80211_mesh_power_mode mesh_pm; ++ struct rwnx_sta *sta; ++ struct mesh_config mesh_conf; ++ struct mesh_update_cfm cfm; ++ u32 mask; ++ ++ if (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_MESH_POINT) ++ return; ++ ++ if (list_empty(&vif->ap.sta_list)) { ++ mesh_pm = vif->ap.next_mesh_pm; ++ } else { ++ mesh_pm = NL80211_MESH_POWER_DEEP_SLEEP; ++ list_for_each_entry(sta, &vif->ap.sta_list, list) { ++ if (sta->valid && (sta->mesh_pm < mesh_pm)) { ++ mesh_pm = sta->mesh_pm; ++ } ++ } ++ } ++ ++ if (mesh_pm == vif->ap.mesh_pm) ++ return; ++ ++ mask = BIT(NL80211_MESHCONF_POWER_MODE - 1); ++ mesh_conf.power_mode = mesh_pm; ++ if (rwnx_send_mesh_update_req(vif->rwnx_hw, vif, mask, &mesh_conf, &cfm) || ++ cfm.status) ++ return; ++ ++ vif->ap.mesh_pm = mesh_pm; ++} ++ ++#ifdef CONFIG_BR_SUPPORT ++void netdev_br_init(struct net_device *netdev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(netdev); ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++ rcu_read_lock(); ++#endif ++ ++ /* if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) */ ++ { ++ /* struct net_bridge *br = netdev->br_port->br; */ /* ->dev->dev_addr; */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ if (netdev->br_port) ++ #else ++ if (rcu_dereference(rwnx_vif->ndev->rx_handler_data)) ++ #endif ++ { ++ struct net_device *br_netdev; ++ ++ br_netdev = dev_get_by_name(&init_net, CONFIG_BR_SUPPORT_BRNAME); ++ if (br_netdev) { ++ memcpy(rwnx_vif->br_mac, br_netdev->dev_addr, ETH_ALEN); ++ dev_put(br_netdev); ++ printk(FUNC_NDEV_FMT" bind bridge dev "NDEV_FMT"("MAC_FMT")\n" ++ , FUNC_NDEV_ARG(netdev), NDEV_ARG(br_netdev), MAC_ARG(br_netdev->dev_addr)); ++ } else { ++ printk(FUNC_NDEV_FMT" can't get bridge dev by name \"%s\"\n" ++ , FUNC_NDEV_ARG(netdev), CONFIG_BR_SUPPORT_BRNAME); ++ } ++ } ++ ++ rwnx_vif->ethBrExtInfo.addPPPoETag = 1; ++ } ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++ rcu_read_unlock(); ++#endif ++} ++#endif /* CONFIG_BR_SUPPORT */ ++ ++void rwnx_set_conn_state(atomic_t *drv_conn_state, int state){ ++ ++ if((int)atomic_read(drv_conn_state) != state){ ++ AICWFDBG(LOGDEBUG, "%s drv_conn_state:%p %s --> %s \r\n", __func__, ++ drv_conn_state, ++ s_conn_state[(int)atomic_read(drv_conn_state)], ++ s_conn_state[state]); ++ ++ atomic_set(drv_conn_state, state); ++ } ++} ++ ++/********************************************************************* ++ * netdev callbacks ++ ********************************************************************/ ++/** ++ * int (*ndo_open)(struct net_device *dev); ++ * This function is called when network device transistions to the up ++ * state. ++ * ++ * - Start FW if this is the first interface opened ++ * - Add interface at fw level ++ */ ++static int rwnx_open(struct net_device *dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct mm_add_if_cfm add_if_cfm; ++ int error = 0; ++ u8 rwnx_rx_gain = 0x0E; ++ int err = 0; ++ int waiting_counter = 10; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ while(test_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags)){ ++ msleep(100); ++ AICWFDBG(LOGDEBUG, "%s waiting for rwnx_close \r\n", __func__); ++ waiting_counter--; ++ if(waiting_counter == 0){ ++ AICWFDBG(LOGERROR, "%s error waiting for close time out \r\n", __func__); ++ break; ++ } ++ } ++ ++#ifdef AICWF_LATENCY_MODE ++ if ((testmode == 0) && (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT)) { ++ rwnx_send_me_set_lp_level(rwnx_hw, 1, 1); ++ } ++#endif ++ ++#ifdef CONFIG_GPIO_WAKEUP ++//close lp mode ++// rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 0); ++#endif//CONFIG_GPIO_WAKEUP ++ ++ // Check if it is the first opened VIF ++ if (rwnx_hw->vif_started == 0) { ++ // Start the FW ++ error = rwnx_send_start(rwnx_hw); ++ if (error) ++ return error; ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ error = rwnx_send_dbg_mem_mask_write_req(rwnx_hw, 0x4033b300, 0xFF, rwnx_rx_gain); ++ if(error){ ++ return error; ++ } ++ } ++ ++#ifdef CONFIG_COEX ++ if (testmode == 0) { ++ rwnx_send_coex_req(rwnx_hw, 0, 1); ++ } ++#endif ++ ++ /* Device is now started */ ++ } ++ ++ set_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif->drv_flags:%d\r\n", __func__, (int)rwnx_vif->drv_flags); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO) { ++ if (!rwnx_hw->is_p2p_alive) { ++ if (rwnx_hw->p2p_dev_vif && !rwnx_hw->p2p_dev_vif->up) { ++ err = rwnx_send_add_if (rwnx_hw, rwnx_hw->p2p_dev_vif->wdev.address, ++ RWNX_VIF_TYPE(rwnx_hw->p2p_dev_vif), false, &add_if_cfm); ++ if (err) { ++ return -EIO; ++ } ++ ++ if (add_if_cfm.status != 0) { ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->p2p_dev_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_hw->p2p_dev_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_hw->p2p_dev_vif; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++ rwnx_hw->is_p2p_alive = 1; ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ } ++ } ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN) { ++ /* For AP_vlan use same fw and drv indexes. We ensure that this index ++ will not be used by fw for another vif by taking index >= NX_VIRT_DEV_MAX */ ++ add_if_cfm.inst_nbr = rwnx_vif->drv_vif_index; ++ netif_tx_stop_all_queues(dev); ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ AICWFDBG(LOGDEBUG, "%s ap create vif in rwnx_hw->vif_table[%d] \r\n", ++ __func__, rwnx_vif->vif_index); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } else { ++ /* Forward the information to the LMAC, ++ * p2p value not used in FMAC configuration, iftype is sufficient */ ++ error = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); ++ if (error) { ++ printk("add if fail\n"); ++ return error; ++ } ++ ++ if (add_if_cfm.status != 0) { ++ RWNX_PRINT_CFM_ERR(add_if); ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ AICWFDBG(LOGDEBUG, "%s sta create vif in rwnx_hw->vif_table[%d] \r\n", ++ __func__, rwnx_vif->vif_index); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++#ifdef CONFIG_USE_P2P0 ++ if(rwnx_vif->is_p2p_vif){ ++ rwnx_hw->p2p_dev_vif = rwnx_vif; ++ rwnx_hw->is_p2p_alive = 1; ++ } ++#endif ++ } ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MONITOR) { ++ rwnx_hw->monitor_vif = rwnx_vif->vif_index; ++ if (rwnx_vif->ch_index != RWNX_CH_NOT_SET) { ++ //Configure the monitor channel ++ error = rwnx_send_config_monitor_req(rwnx_hw, &rwnx_hw->chanctx_table[rwnx_vif->ch_index].chan_def, NULL); ++ } ++#if defined(CONFIG_RWNX_MON_XMIT) ++ rwnx_txq_unk_vif_init(rwnx_vif); ++#endif ++#if defined(CONFIG_RWNX_MON_RXFILTER) ++ rwnx_send_set_filter(rwnx_hw, (FIF_BCN_PRBRESP_PROMISC | FIF_OTHER_BSS | FIF_PSPOLL | FIF_PROBE_REQ)); ++#endif ++ } ++ ++#if defined(CONFIG_RWNX_MON_XMIT) ++ netif_carrier_on(dev); ++ AICWFDBG(LOGINFO, "monitor xmit: netif_carrier_on\n"); ++#endif ++ ++ ++ #ifdef CONFIG_BR_SUPPORT ++ netdev_br_init(dev); ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ //netif_carrier_off(dev); ++ netif_start_queue(dev); ++ ++ return error; ++} ++ ++/** ++ * int (*ndo_stop)(struct net_device *dev); ++ * This function is called when network device transistions to the down ++ * state. ++ * ++ * - Remove interface at fw level ++ * - Reset FW if this is the last interface opened ++ */ ++static int rwnx_close(struct net_device *dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ int ret; ++#if defined(AICWF_USB_SUPPORT) ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_usb_dev *usbdev = NULL; ++ bus_if = dev_get_drvdata(rwnx_hw->dev); ++ usbdev = bus_if->bus_priv.usb; ++#elif defined(AICWF_SDIO_SUPPORT) ++ struct aicwf_bus *bus_if = NULL; ++ struct aic_sdio_dev *sdiodev = NULL; ++#else ++#endif ++ int waiting_counter = 20; ++ int test_counter = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ test_counter = waiting_counter; ++ while(atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING|| ++ atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING){ ++ AICWFDBG(LOGDEBUG, "%s wifi is connecting or disconnecting, waiting 200ms for state to stable\r\n", __func__); ++ msleep(200); ++ test_counter--; ++ if(test_counter == 0){ ++ AICWFDBG(LOGERROR, "%s connecting or disconnecting, not finish\r\n", __func__); ++ WARN_ON(1); ++ break; ++ } ++ } ++ ++#if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) ++ if (scanning) { ++ scanning = false; ++ } ++#endif ++ ++ netdev_info(dev, "CLOSE"); ++ ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ ++ /* Abort scan request on the vif */ ++ if (rwnx_hw->scan_request && ++ rwnx_hw->scan_request->wdev == &rwnx_vif->wdev) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ cfg80211_scan_done(rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(rwnx_hw->scan_request, true); ++#endif ++ rwnx_hw->scan_request = NULL; ++ ++ ret = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ mdelay(35);//make sure firmware take affect ++ if (ret) { ++ printk("scanu_cancel fail\n"); ++ return ret; ++ } ++ } ++ ++ if (rwnx_hw->roc_elem && (rwnx_hw->roc_elem->wdev == &rwnx_vif->wdev)) { ++ printk(KERN_CRIT "%s clear roc\n", __func__); ++ /* Initialize RoC element pointer to NULL, indicate that RoC can be started */ ++ kfree(rwnx_hw->roc_elem); ++ rwnx_hw->roc_elem = NULL; ++ } ++ ++ rwnx_vif->up = false; ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif[%d] down \r\n", __func__, rwnx_vif->vif_index); ++ ++ if (netif_carrier_ok(dev)) { ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ cfg80211_disconnected(dev, WLAN_REASON_DEAUTH_LEAVING, ++ NULL, 0, true, GFP_ATOMIC); ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ udelay(1000); ++ } else if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN) { ++ netif_carrier_off(dev); ++ } else { ++ netdev_warn(dev, "AP not stopped when disabling interface"); ++ } ++ ++ #ifdef CONFIG_BR_SUPPORT ++ /* if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) */ ++ { ++ /* void nat25_db_cleanup(_adapter *priv); */ ++ nat25_db_cleanup(rwnx_vif); ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ } ++ ++#if defined(AICWF_USB_SUPPORT) ++ if (usbdev != NULL) { ++ if (usbdev->state != USB_DOWN_ST) ++ rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, false); ++ } ++#endif ++#if defined(AICWF_SDIO_SUPPORT) ++ bus_if = dev_get_drvdata(rwnx_hw->dev); ++ if (bus_if) { ++ sdiodev = bus_if->bus_priv.sdio; ++ } ++ if (sdiodev != NULL) { ++ if (sdiodev->bus_if->state != BUS_DOWN_ST){ ++ if(RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT){ ++ test_counter = waiting_counter; ++ if(atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTED){ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTING); ++ rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, 3); ++ while (atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING) { ++ AICWFDBG(LOGDEBUG, "%s wifi is disconnecting, waiting 100ms for state to stable\r\n", __func__); ++ msleep(100); ++ test_counter--; ++ if (test_counter ==0) ++ break; ++ } ++ } ++ } ++#ifdef CONFIG_USE_P2P0 ++ if(!rwnx_vif->is_p2p_vif || ( rwnx_vif->is_p2p_vif && rwnx_hw->is_p2p_alive)){ ++ if (rwnx_vif->is_p2p_vif) ++ rwnx_hw->is_p2p_alive = 0; ++#endif ++ rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, false); ++#ifdef CONFIG_USE_P2P0 ++ } ++#endif ++ } ++ } ++#endif ++ /* Ensure that we won't process disconnect ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ ++ rwnx_hw->vif_table[rwnx_vif->vif_index] = NULL; ++ ++ rwnx_chanctx_unlink(rwnx_vif); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MONITOR) ++ rwnx_hw->monitor_vif = RWNX_INVALID_VIF; ++ ++ rwnx_hw->vif_started--; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if (rwnx_hw->vif_started == 0) { ++ /* This also lets both ipc sides remain in sync before resetting */ ++#if 0 ++ rwnx_ipc_tx_drain(rwnx_hw); ++#else ++#ifdef AICWF_USB_SUPPORT ++ if (usbdev->bus_if->state != BUS_DOWN_ST) { ++#else ++ if (sdiodev->bus_if->state != BUS_DOWN_ST) { ++#endif ++ rwnx_send_reset(rwnx_hw); ++ // Set parameters to firmware ++ if (testmode == 0) { ++ rwnx_send_me_config_req(rwnx_hw); ++ // Set channel parameters to firmware ++ rwnx_send_me_chan_config_req(rwnx_hw, country_code); ++ } ++ } ++#endif ++ } ++ clear_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif->drv_flags:%d\r\n", __func__, (int)rwnx_vif->drv_flags); ++ ++ return 0; ++} ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) ++#ifdef CONFIG_SHUTDOWN_CALLBACK ++int rwnx_close_(struct net_device *dev){ ++ return rwnx_close(dev); ++} ++#endif ++#endif ++ ++#define IOCTL_HOSTAPD (SIOCIWFIRSTPRIV+28) ++#define IOCTL_WPAS (SIOCIWFIRSTPRIV+30) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) ++static int rwnx_do_ioctl(struct net_device *net, struct ifreq *req, int cmd) ++#else ++static int rwnx_do_ioctl(struct net_device *net, struct ifreq *req, void __user *data, int cmd) ++#endif ++{ ++ int ret = 0; ++ ///TODO: add ioctl command handler later ++ switch (cmd) { ++ case IOCTL_HOSTAPD: ++ printk("IOCTL_HOSTAPD\n"); ++ break; ++ case IOCTL_WPAS: ++ AICWFDBG(LOGINFO, "IOCTL_WPAS\n"); ++ break; ++ case SIOCDEVPRIVATE: ++ AICWFDBG(LOGINFO, "IOCTL SIOCDEVPRIVATE\n"); ++ break; ++ case (SIOCDEVPRIVATE+1): ++ AICWFDBG(LOGINFO, "IOCTL PRIVATE\n"); ++ ret = android_priv_cmd(net, req, cmd); ++ break; ++ case (SIOCDEVPRIVATE+2): ++ AICWFDBG(LOGINFO, "IOCTL PRIVATE+2\n"); ++ #ifdef CONFIG_MCU_MESSAGE ++ devipc_cust_msg(net, req, cmd); ++ #endif ++ break; ++ default: ++ ret = -EOPNOTSUPP; ++ } ++ return ret; ++} ++ ++/** ++ * struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); ++ * Called when a user wants to get the network device usage ++ * statistics. Drivers must do one of the following: ++ * 1. Define @ndo_get_stats64 to fill in a zero-initialised ++ * rtnl_link_stats64 structure passed by the caller. ++ * 2. Define @ndo_get_stats to update a net_device_stats structure ++ * (which should normally be dev->stats) and return a pointer to ++ * it. The structure may be changed asynchronously only if each ++ * field is written atomically. ++ * 3. Update dev->stats asynchronously and atomically, and define ++ * neither operation. ++ */ ++static struct net_device_stats *rwnx_get_stats(struct net_device *dev) ++{ ++ struct rwnx_vif *vif = netdev_priv(dev); ++ ++ return &vif->net_stats; ++} ++ ++/** ++ * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, ++ * struct net_device *sb_dev); ++ * Called to decide which queue to when device supports multiple ++ * transmit queues. ++ */ ++u16 rwnx_select_queue(struct net_device *dev, struct sk_buff *skb, ++ struct net_device *sb_dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ return rwnx_select_txq(rwnx_vif, skb); ++} ++ ++/** ++ * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); ++ * This function is called when the Media Access Control address ++ * needs to be changed. If this interface is not defined, the ++ * mac address can not be changed. ++ */ ++static int rwnx_set_mac_address(struct net_device *dev, void *addr) ++{ ++ struct sockaddr *sa = addr; ++ int ret = 0; ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ AICWFDBG(LOGTRACE, "%s enter \r\n", __func__); ++ ++ ret = eth_mac_addr(dev, sa); ++ AICWFDBG(LOGINFO, "%s set %02X:%02X:%02X:%02X:%02X:%02X\r\n", __func__, ++ dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2], ++ dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]); ++ memcpy(rwnx_vif->wdev.address, dev->dev_addr, 6); ++ ++ return ret; ++} ++ ++static const struct net_device_ops rwnx_netdev_ops = { ++ .ndo_open = rwnx_open, ++ .ndo_stop = rwnx_close, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) ++ .ndo_do_ioctl = rwnx_do_ioctl, ++#else ++ .ndo_siocdevprivate = rwnx_do_ioctl, ++#endif ++ .ndo_start_xmit = rwnx_start_xmit, ++ .ndo_get_stats = rwnx_get_stats, ++#ifndef CONFIG_ONE_TXQ ++ .ndo_select_queue = rwnx_select_queue, ++#endif ++#ifdef CONFIG_SUPPORT_REALTIME_CHANGE_MAC ++ .ndo_set_mac_address = rwnx_set_mac_address ++#endif ++// .ndo_set_features = rwnx_set_features, ++// .ndo_set_rx_mode = rwnx_set_multicast_list, ++}; ++ ++static const struct net_device_ops rwnx_netdev_monitor_ops = { ++ .ndo_open = rwnx_open, ++ .ndo_stop = rwnx_close, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) ++ .ndo_siocdevprivate = rwnx_do_ioctl, ++#else ++ .ndo_do_ioctl = rwnx_do_ioctl, ++#endif ++#ifdef CONFIG_RWNX_MON_XMIT ++ .ndo_start_xmit = rwnx_start_monitor_if_xmit, ++ .ndo_select_queue = rwnx_select_queue, ++#endif ++ .ndo_get_stats = rwnx_get_stats, ++ .ndo_set_mac_address = rwnx_set_mac_address, ++}; ++ ++static void rwnx_netdev_setup(struct net_device *dev) ++{ ++ ether_setup(dev); ++ dev->priv_flags &= ~IFF_TX_SKB_SHARING; ++ dev->netdev_ops = &rwnx_netdev_ops; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) ++ dev->destructor = free_netdev; ++#else ++ dev->needs_free_netdev = true; ++#endif ++ dev->watchdog_timeo = RWNX_TX_LIFETIME_MS; ++ ++ dev->needed_headroom = sizeof(struct rwnx_txhdr) + RWNX_SWTXHDR_ALIGN_SZ; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ dev->needed_headroom = max(dev->needed_headroom, ++ (unsigned short)(sizeof(struct rwnx_amsdu_txhdr) ++ + sizeof(struct ethhdr) + 4 ++ + sizeof(rfc1042_header) + 2)); ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++ dev->hw_features = 0; ++} ++ ++/********************************************************************* ++ * Cfg80211 callbacks (and helper) ++ *********************************************************************/ ++static struct rwnx_vif *rwnx_interface_add(struct rwnx_hw *rwnx_hw, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ struct net_device *ndev; ++ struct rwnx_vif *vif; ++ int min_idx, max_idx; ++ int vif_idx = -1; ++ int i; ++ int nx_nb_ndev_txq = NX_NB_NDEV_TXQ; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_nb_ndev_txq = NX_NB_NDEV_TXQ_FOR_OLD_IC; ++ } ++ ++ AICWFDBG(LOGINFO, "rwnx_interface_add: %s, %d, %d\r\n", name, type, NL80211_IFTYPE_P2P_DEVICE); ++ // Look for an available VIF ++ if (type == NL80211_IFTYPE_AP_VLAN) { ++ min_idx = NX_VIRT_DEV_MAX; ++ max_idx = NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; ++ } else { ++ min_idx = 0; ++ max_idx = NX_VIRT_DEV_MAX; ++ } ++ ++ for (i = min_idx; i < max_idx; i++) { ++ if ((rwnx_hw->avail_idx_map) & BIT(i)) { ++ vif_idx = i; ++ break; ++ } ++ } ++ if (vif_idx < 0) ++ return NULL; ++ ++ #ifndef CONFIG_RWNX_MON_DATA ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ // Check if monitor interface already exists or type is monitor ++ if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR) || ++ (type == NL80211_IFTYPE_MONITOR)) { ++ wiphy_err(rwnx_hw->wiphy, ++ "Monitor+Data interface support (MON_DATA) disabled\n"); ++ return NULL; ++ } ++ } ++ #endif ++ ++#ifndef CONFIG_ONE_TXQ ++ ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type, ++ rwnx_netdev_setup, nx_nb_ndev_txq, 1); ++#else ++ ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type, ++ rwnx_netdev_setup, 1, 1); ++#endif ++ ++ if (!ndev) ++ return NULL; ++ ++ vif = netdev_priv(ndev); ++ vif->key_has_add = 0; ++ ndev->ieee80211_ptr = &vif->wdev; ++ vif->wdev.wiphy = rwnx_hw->wiphy; ++ vif->rwnx_hw = rwnx_hw; ++ vif->ndev = ndev; ++ vif->drv_vif_index = vif_idx; ++ SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy)); ++ vif->wdev.netdev = ndev; ++ vif->wdev.iftype = type; ++ vif->up = false; ++ vif->ch_index = RWNX_CH_NOT_SET; ++ memset(&vif->net_stats, 0, sizeof(vif->net_stats)); ++ vif->is_p2p_vif = 0; ++ ++ #ifdef CONFIG_BR_SUPPORT ++ spin_lock_init(&vif->br_ext_lock); ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ ++ switch (type) { ++ case NL80211_IFTYPE_STATION: ++ vif->sta.ap = NULL; ++ vif->sta.tdls_sta = NULL; ++ vif->sta.external_auth = false; ++ break; ++ case NL80211_IFTYPE_P2P_CLIENT: ++ vif->sta.ap = NULL; ++ vif->sta.tdls_sta = NULL; ++ vif->sta.external_auth = false; ++ vif->is_p2p_vif = 1; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ INIT_LIST_HEAD(&vif->ap.mpath_list); ++ INIT_LIST_HEAD(&vif->ap.proxy_list); ++ vif->ap.create_path = false; ++ vif->ap.generation = 0; ++ vif->ap.mesh_pm = NL80211_MESH_POWER_ACTIVE; ++ vif->ap.next_mesh_pm = NL80211_MESH_POWER_ACTIVE; ++ // no break ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ INIT_LIST_HEAD(&vif->ap.sta_list); ++ memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn)); ++ break; ++ case NL80211_IFTYPE_P2P_GO: ++ INIT_LIST_HEAD(&vif->ap.sta_list); ++ memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn)); ++ vif->is_p2p_vif = 1; ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ { ++ struct rwnx_vif *master_vif; ++ bool found = false; ++ list_for_each_entry(master_vif, &rwnx_hw->vifs, list) { ++ if ((RWNX_VIF_TYPE(master_vif) == NL80211_IFTYPE_AP) && ++ !(!memcmp(master_vif->ndev->dev_addr, params->macaddr, ++ ETH_ALEN))) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ goto err; ++ ++ vif->ap_vlan.master = master_vif; ++ vif->ap_vlan.sta_4a = NULL; ++ break; ++ } ++ case NL80211_IFTYPE_MONITOR: ++ ndev->type = ARPHRD_IEEE80211_RADIOTAP; ++ ndev->netdev_ops = &rwnx_netdev_monitor_ops; ++ break; ++ default: ++ break; ++ } ++ ++ if (type == NL80211_IFTYPE_AP_VLAN) { ++ memcpy((void *)ndev->dev_addr, (const void *)params->macaddr, ETH_ALEN); ++ memcpy((void *)vif->wdev.address, (const void *)params->macaddr, ETH_ALEN); ++ } else { ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 17, 0) ++ unsigned char mac_addr[6]; ++ memcpy(mac_addr, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ mac_addr[5] ^= vif_idx; ++ //memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); ++ eth_hw_addr_set(ndev, mac_addr); ++ memcpy(vif->wdev.address, mac_addr, ETH_ALEN); ++#else ++ memcpy(ndev->dev_addr, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ ndev->dev_addr[5] ^= vif_idx; ++ memcpy(vif->wdev.address, ndev->dev_addr, ETH_ALEN); ++#endif ++ ++ } ++ ++ AICWFDBG(LOGINFO, "interface add:%x %x %x %x %x %x\n", vif->wdev.address[0], vif->wdev.address[1], \ ++ vif->wdev.address[2], vif->wdev.address[3], vif->wdev.address[4], vif->wdev.address[5]); ++ ++ if (params) { ++ vif->use_4addr = params->use_4addr; ++ ndev->ieee80211_ptr->use_4addr = params->use_4addr; ++ } else ++ vif->use_4addr = false; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) ++ if (cfg80211_register_netdevice(ndev)) ++#else ++ if (register_netdevice(ndev)) ++#endif ++ goto err; ++ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_add_tail(&vif->list, &rwnx_hw->vifs); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->avail_idx_map &= ~BIT(vif_idx); ++ ++ return vif; ++ ++err: ++ free_netdev(ndev); ++ return NULL; ++} ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++void aicwf_p2p_alive_timeout(ulong data) ++#else ++void aicwf_p2p_alive_timeout(struct timer_list *t) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct rwnx_vif *rwnx_vif; ++ struct rwnx_vif *rwnx_vif1, *tmp; ++ u8_l p2p = 0; ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ rwnx_vif = (struct rwnx_vif *)data; ++ rwnx_hw = rwnx_vif->rwnx_hw; ++ #else ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ rwnx_hw = timer_container_of(rwnx_hw, t, p2p_alive_timer); ++ #else ++ rwnx_hw = from_timer(rwnx_hw, t, p2p_alive_timer); ++ #endif ++ rwnx_vif = rwnx_hw->p2p_dev_vif; ++ #endif ++ ++ list_for_each_entry_safe(rwnx_vif1, tmp, &rwnx_hw->vifs, list) { ++ if ((rwnx_hw->avail_idx_map & BIT(rwnx_vif1->drv_vif_index)) == 0) { ++ switch (RWNX_VIF_TYPE(rwnx_vif1)) { ++ case NL80211_IFTYPE_P2P_CLIENT: ++ case NL80211_IFTYPE_P2P_GO: ++ rwnx_hw->is_p2p_alive = 1; ++ p2p = 1; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ ++ if (p2p) ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++ else ++ atomic_inc(&rwnx_hw->p2p_alive_timer_count); ++ ++ if (atomic_read(&rwnx_hw->p2p_alive_timer_count) < P2P_ALIVE_TIME_COUNT) { ++ mod_timer(&rwnx_hw->p2p_alive_timer, ++ jiffies + msecs_to_jiffies(P2P_ALIVE_TIME_MS)); ++ return; ++ } else ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++ ++ rwnx_hw->is_p2p_alive = 0; ++ if (rwnx_vif->up) { ++ rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, true); ++ ++ /* Ensure that we won't process disconnect ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ ++ rwnx_vif->up = false; ++ rwnx_hw->vif_table[rwnx_vif->vif_index] = NULL; ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif[%d] down \r\n", __func__, rwnx_vif->vif_index); ++ rwnx_hw->vif_started--; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++} ++ ++ ++/********************************************************************* ++ * Cfg80211 callbacks (and helper) ++ *********************************************************************/ ++static struct wireless_dev *rwnx_virtual_interface_add(struct rwnx_hw *rwnx_hw, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ struct wireless_dev *wdev = NULL; ++ struct rwnx_vif *vif; ++ int min_idx, max_idx; ++ int vif_idx = -1; ++ int i; ++ ++ printk("rwnx_virtual_interface_add: %d, %s\n", type, name); ++ ++ if (type == NL80211_IFTYPE_AP_VLAN) { ++ min_idx = NX_VIRT_DEV_MAX; ++ max_idx = NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; ++ } else { ++ min_idx = 0; ++ max_idx = NX_VIRT_DEV_MAX; ++ } ++ ++ for (i = min_idx; i < max_idx; i++) { ++ if ((rwnx_hw->avail_idx_map) & BIT(i)) { ++ vif_idx = i; ++ break; ++ } ++ } ++ ++ if (vif_idx < 0) { ++ printk("virtual_interface_add %s fail\n", name); ++ return NULL; ++ } ++ ++ vif = kzalloc(sizeof(struct rwnx_vif), GFP_KERNEL); ++ if (unlikely(!vif)) { ++ printk("Could not allocate wireless device\n"); ++ return NULL; ++ } ++ wdev = &vif->wdev; ++ wdev->wiphy = rwnx_hw->wiphy; ++ wdev->iftype = type; ++ ++ printk("rwnx_virtual_interface_add, ifname=%s, wdev=%p, vif_idx=%d\n", name, wdev, vif_idx); ++ ++ #ifndef CONFIG_USE_P2P0 ++ vif->is_p2p_vif = 1; ++ vif->rwnx_hw = rwnx_hw; ++ vif->vif_index = vif_idx; ++ vif->wdev.wiphy = rwnx_hw->wiphy; ++ vif->drv_vif_index = vif_idx; ++ vif->up = false; ++ vif->ch_index = RWNX_CH_NOT_SET; ++ memset(&vif->net_stats, 0, sizeof(vif->net_stats)); ++ vif->use_4addr = false; ++ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_add_tail(&vif->list, &rwnx_hw->vifs); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if (rwnx_hw->is_p2p_alive == 0) { ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ init_timer(&rwnx_hw->p2p_alive_timer); ++ rwnx_hw->p2p_alive_timer.data = (unsigned long)vif; ++ rwnx_hw->p2p_alive_timer.function = aicwf_p2p_alive_timeout; ++ #else ++ timer_setup(&rwnx_hw->p2p_alive_timer, aicwf_p2p_alive_timeout, 0); ++ #endif ++ rwnx_hw->is_p2p_alive = 0; ++ rwnx_hw->is_p2p_connected = 0; ++ rwnx_hw->p2p_dev_vif = vif; ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++ } ++ #endif ++ rwnx_hw->avail_idx_map &= ~BIT(vif_idx); ++ ++ memcpy(vif->wdev.address, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ vif->wdev.address[5] ^= vif_idx; ++ printk("p2p dev addr=%x %x %x %x %x %x\n", vif->wdev.address[0], vif->wdev.address[1], \ ++ vif->wdev.address[2], vif->wdev.address[3], vif->wdev.address[4], vif->wdev.address[5]); ++ ++ return wdev; ++} ++ ++/* ++ * @brief Retrieve the rwnx_sta object allocated for a given MAC address ++ * and a given role. ++ */ ++static struct rwnx_sta *rwnx_retrieve_sta(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, u8 *addr, ++ __le16 fc, bool ap) ++{ ++ if (ap) { ++ /* only deauth, disassoc and action are bufferable MMPDUs */ ++ bool bufferable = ieee80211_is_deauth(fc) || ++ ieee80211_is_disassoc(fc) || ++ ieee80211_is_action(fc); ++ ++ /* Check if the packet is bufferable or not */ ++ if (bufferable) { ++ /* Check if address is a broadcast or a multicast address */ ++ if (is_broadcast_ether_addr(addr) || is_multicast_ether_addr(addr)) { ++ /* Returned STA pointer */ ++ struct rwnx_sta *rwnx_sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ ++ if (rwnx_sta->valid) ++ return rwnx_sta; ++ } else { ++ /* Returned STA pointer */ ++ struct rwnx_sta *rwnx_sta; ++ ++ /* Go through list of STAs linked with the provided VIF */ ++ spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ list_for_each_entry(rwnx_sta, &rwnx_vif->ap.sta_list, list) { ++ if (rwnx_sta->valid && ++ ether_addr_equal(rwnx_sta->mac_addr, addr)) { ++ /* Return the found STA */ ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ return rwnx_sta; ++ } ++ } ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ } ++ } ++ } else { ++ return rwnx_vif->sta.ap; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * @add_virtual_intf: create a new virtual interface with the given name, ++ * must set the struct wireless_dev's iftype. Beware: You must create ++ * the new netdev in the wiphy's network namespace! Returns the struct ++ * wireless_dev, or an ERR_PTR. For P2P device wdevs, the driver must ++ * also set the address member in the wdev. ++ */ ++static struct wireless_dev *rwnx_cfg80211_add_iface(struct wiphy *wiphy, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct wireless_dev *wdev; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) ++ unsigned char name_assign_type = NET_NAME_UNKNOWN; ++#endif ++ ++ if (type != NL80211_IFTYPE_P2P_DEVICE) { ++ struct rwnx_vif *vif = rwnx_interface_add(rwnx_hw, name, name_assign_type, type, params); ++ if (!vif) ++ return ERR_PTR(-EINVAL); ++ return &vif->wdev; ++ ++ } else { ++ wdev = rwnx_virtual_interface_add(rwnx_hw, name, name_assign_type, type, params); ++ if (!wdev) ++ return ERR_PTR(-EINVAL); ++ return wdev; ++ } ++} ++ ++/** ++ * @del_virtual_intf: remove the virtual interface ++ */ ++static int rwnx_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ struct net_device *dev = wdev->netdev; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ ++ AICWFDBG(LOGINFO, "del_iface: %p, %x\n", wdev, wdev->address[5]); ++ ++ if (!dev || !rwnx_vif->ndev) { ++ cfg80211_unregister_wdev(wdev); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_del(&rwnx_vif->list); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->avail_idx_map |= BIT(rwnx_vif->drv_vif_index); ++ rwnx_vif->ndev = NULL; ++ kfree(rwnx_vif); ++ return 0; ++ } ++ ++ netdev_info(dev, "Remove Interface"); ++ ++ if (dev->reg_state == NETREG_REGISTERED) { ++ /* Will call rwnx_close if interface is UP */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) ++ cfg80211_unregister_netdevice(dev); ++#else ++ unregister_netdevice(dev); ++#endif ++ ++ } ++ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_del(&rwnx_vif->list); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->avail_idx_map |= BIT(rwnx_vif->drv_vif_index); ++ rwnx_vif->ndev = NULL; ++ ++ /* Clear the priv in adapter */ ++ dev->ieee80211_ptr = NULL; ++ ++ return 0; ++} ++ ++/** ++ * @change_virtual_intf: change type/configuration of virtual interface, ++ * keep the struct wireless_dev's iftype updated. ++ */ ++static int rwnx_cfg80211_change_iface(struct wiphy *wiphy, ++ struct net_device *dev, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++#ifndef CONFIG_RWNX_MON_DATA ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++#endif ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct mm_add_if_cfm add_if_cfm; ++ bool_l p2p = false; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("change_if: %d to %d, %d, %d", vif->wdev.iftype, type, NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_STATION); ++ ++#ifndef CONFIG_RWNX_MON_DATA ++ if ((type == NL80211_IFTYPE_MONITOR) && ++ (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_MONITOR)) { ++ struct rwnx_vif *vif_el; ++ list_for_each_entry(vif_el, &rwnx_hw->vifs, list) { ++ // Check if data interface already exists ++ if ((vif_el != vif) && ++ (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_MONITOR)) { ++ wiphy_err(rwnx_hw->wiphy, ++ "Monitor+Data interface support (MON_DATA) disabled\n"); ++ return -EIO; ++ } ++ } ++ } ++#endif ++ ++ // Reset to default case (i.e. not monitor) ++ dev->type = ARPHRD_ETHER; ++ dev->netdev_ops = &rwnx_netdev_ops; ++ ++ switch (type) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ vif->sta.ap = NULL; ++ vif->sta.tdls_sta = NULL; ++ vif->sta.external_auth = false; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ INIT_LIST_HEAD(&vif->ap.mpath_list); ++ INIT_LIST_HEAD(&vif->ap.proxy_list); ++ vif->ap.create_path = false; ++ vif->ap.generation = 0; ++ // no break ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ INIT_LIST_HEAD(&vif->ap.sta_list); ++ memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn)); ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ return -EPERM; ++ case NL80211_IFTYPE_MONITOR: ++ dev->type = ARPHRD_IEEE80211_RADIOTAP; ++ dev->netdev_ops = &rwnx_netdev_monitor_ops; ++ break; ++ default: ++ break; ++ } ++ ++ vif->wdev.iftype = type; ++ if (params->use_4addr != -1) ++ vif->use_4addr = params->use_4addr; ++ if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO) ++ p2p = true; ++ ++ if (vif->up) { ++ /* Abort scan request on the vif */ ++ if (vif->rwnx_hw->scan_request && ++ vif->rwnx_hw->scan_request->wdev == &vif->wdev) { ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ cfg80211_scan_done(vif->rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(vif->rwnx_hw->scan_request, true); ++#endif ++ ret = rwnx_send_scanu_cancel_req(vif->rwnx_hw, NULL); ++ if (ret) { ++ printk("scanu_cancel fail\n"); ++ return ret; ++ } ++ vif->rwnx_hw->scan_request = NULL; ++#else ++ if ((ret = rwnx_send_scanu_cancel_req(vif->rwnx_hw, NULL))) { ++ AICWFDBG(LOGERROR, "scanu_cancel fail\n"); ++ return ret; ++ } ++#endif ++ } ++ ret = rwnx_send_remove_if(vif->rwnx_hw, vif->vif_index, false); ++ if (ret) { ++ printk("remove_if fail\n"); ++ return ret; ++ } ++ vif->rwnx_hw->vif_table[vif->vif_index] = NULL; ++ printk("change_if from %d \n", vif->vif_index); ++ ret = rwnx_send_add_if(vif->rwnx_hw, vif->wdev.address, RWNX_VIF_TYPE(vif), p2p, &add_if_cfm); ++ if (ret) { ++ printk("add if fail\n"); ++ return ret; ++ } ++ if (add_if_cfm.status != 0) { ++ printk("add if status fail\n"); ++ return -EIO; ++ } ++ ++ printk("change_if to %d \n", add_if_cfm.inst_nbr); ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&vif->rwnx_hw->cb_lock); ++ vif->vif_index = add_if_cfm.inst_nbr; ++ vif->rwnx_hw->vif_table[add_if_cfm.inst_nbr] = vif; ++ spin_unlock_bh(&vif->rwnx_hw->cb_lock); ++ } ++ ++ if (type == NL80211_IFTYPE_MONITOR) { ++ vif->rwnx_hw->monitor_vif = vif->vif_index; ++ #if defined(CONFIG_RWNX_MON_XMIT) ++ rwnx_txq_unk_vif_init(vif); ++ #endif ++ #if defined(CONFIG_RWNX_MON_RXFILTER) ++ rwnx_send_set_filter(vif->rwnx_hw, (FIF_BCN_PRBRESP_PROMISC | FIF_OTHER_BSS | FIF_PSPOLL | FIF_PROBE_REQ)); ++ #endif ++ } else { ++ vif->rwnx_hw->monitor_vif = RWNX_INVALID_VIF; ++ } ++ ++ return 0; ++} ++ ++static int rwnx_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ int ret = 0; ++ ++ //do nothing ++ printk("P2P interface started\n"); ++ ++ return ret; ++} ++ ++static void rwnx_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ int ret = 0; ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ /* Abort scan request on the vif */ ++ if (rwnx_hw->scan_request && ++ rwnx_hw->scan_request->wdev == &rwnx_vif->wdev) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ cfg80211_scan_done(rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(rwnx_hw->scan_request, true); ++#endif ++ rwnx_hw->scan_request = NULL; ++ ret = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ if (ret) ++ printk("scanu_cancel fail\n"); ++ } ++ ++ if (rwnx_vif == rwnx_hw->p2p_dev_vif) { ++ rwnx_hw->is_p2p_alive = 0; ++ if (timer_pending(&rwnx_hw->p2p_alive_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&rwnx_hw->p2p_alive_timer); ++#else ++ del_timer_sync(&rwnx_hw->p2p_alive_timer); ++#endif ++ } ++ ++ if (rwnx_vif->up) { ++ rwnx_send_remove_if(rwnx_hw, rwnx_vif->vif_index, true); ++ /* Ensure that we won't process disconnect ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->up = false; ++ rwnx_hw->vif_table[rwnx_vif->vif_index] = NULL; ++ AICWFDBG(LOGDEBUG, "%s rwnx_vif[%d] down \r\n", __func__, rwnx_vif->vif_index); ++ rwnx_hw->vif_started--; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++ ++ } ++ ++ printk("Exit. P2P interface stopped\n"); ++ ++ return; ++} ++ ++ ++/** ++ * @scan: Request to do a scan. If returning zero, the scan request is given ++ * the driver, and will be valid until passed to cfg80211_scan_done(). ++ * For scan results, call cfg80211_inform_bss(); you can call this outside ++ * the scan/scan_done bracket too. ++ */ ++static int rwnx_cfg80211_scan(struct wiphy *wiphy, ++ struct cfg80211_scan_request *request) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(request->wdev, struct rwnx_vif, wdev); ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if(testmode){ ++ return -EBUSY; ++ } ++ ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING){ ++ AICWFDBG(LOGERROR, "%s wifi is connecting, return it\r\n", __func__); ++ return -EBUSY; ++ } ++ ++ if (scanning) { ++ AICWFDBG(LOGERROR, "%s is scanning, abort\n", __func__); ++ #if 0 ++ error = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ if (error) ++ return error; ++ msleep(150); ++ #endif ++ return -EBUSY; ++ } ++ ++ if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || ++ RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) && ++ rwnx_vif->sta.external_auth) { ++ AICWFDBG(LOGERROR, "scan about: external auth\r\n"); ++ return -EBUSY; ++ } ++ ++ rwnx_hw->scan_request = request; ++ error = rwnx_send_scanu_req(rwnx_hw, rwnx_vif, request); ++ if (error) ++ return error; ++ ++ return 0; ++} ++ ++bool key_flag = false; ++/** ++ * @add_key: add a key with the given parameters. @mac_addr will be %NULL ++ * when adding a group key. ++ */ ++ static int rwnx_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool pairwise, const u8 *mac_addr, ++ struct key_params *params) ++ ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(netdev); ++ int i, error = 0; ++ struct mm_key_add_cfm key_add_cfm; ++ u8_l cipher = 0; ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_key *rwnx_key; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (mac_addr) { ++ sta = rwnx_get_sta(rwnx_hw, mac_addr); ++ if (!sta) ++ return -EINVAL; ++ rwnx_key = &sta->key; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.paired_cipher_type = params->cipher; ++ } else { ++ rwnx_key = &vif->key[key_index]; ++ vif->key_has_add = 1; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.group_cipher_type = params->cipher; ++ } ++ ++ /* Retrieve the cipher suite selector */ ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ cipher = MAC_CIPHER_WEP40; ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ cipher = MAC_CIPHER_WEP104; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ cipher = MAC_CIPHER_TKIP; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ cipher = MAC_CIPHER_CCMP; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ cipher = MAC_CIPHER_BIP_CMAC_128; ++ break; ++ case WLAN_CIPHER_SUITE_SMS4: ++ { ++ // Need to reverse key order ++ u8 tmp, *key = (u8 *)params->key; ++ cipher = MAC_CIPHER_WPI_SMS4; ++ for (i = 0; i < WPI_SUBKEY_LEN/2; i++) { ++ tmp = key[i]; ++ key[i] = key[WPI_SUBKEY_LEN - 1 - i]; ++ key[WPI_SUBKEY_LEN - 1 - i] = tmp; ++ } ++ for (i = 0; i < WPI_SUBKEY_LEN/2; i++) { ++ tmp = key[i + WPI_SUBKEY_LEN]; ++ key[i + WPI_SUBKEY_LEN] = key[WPI_KEY_LEN - 1 - i]; ++ key[WPI_KEY_LEN - 1 - i] = tmp; ++ } ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ key_flag = false; ++ error = rwnx_send_key_add(rwnx_hw, vif->vif_index, ++ (sta ? sta->sta_idx : 0xFF), pairwise, ++ (u8 *)params->key, params->key_len, ++ key_index, cipher, &key_add_cfm); ++ if (error) ++ return error; ++ ++ if (key_add_cfm.status != 0) { ++ RWNX_PRINT_CFM_ERR(key_add); ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ rwnx_key->hw_idx = key_add_cfm.hw_key_idx; ++ ++ return 0; ++} ++ ++/** ++ * @get_key: get information about the key with the given parameters. ++ * @mac_addr will be %NULL when requesting information for a group ++ * key. All pointers given to the @callback function need not be valid ++ * after it returns. This function should return an error if it is ++ * not possible to retrieve the key, -ENOENT if it doesn't exist. ++ * ++ */ ++static int rwnx_cfg80211_get_key(struct wiphy *wiphy, struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool pairwise, const u8 *mac_addr, ++ void *cookie, ++ void (*callback)(void *cookie, struct key_params*)) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ return -1; ++} ++ ++ ++/** ++ * @del_key: remove a key given the @mac_addr (%NULL for a group key) ++ * and @key_index, return -ENOENT if the key doesn't exist. ++ */ ++static int rwnx_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool pairwise, const u8 *mac_addr) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(netdev); ++ int error; ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_key *rwnx_key; ++ if (!key_flag && vif->wdev.iftype == NL80211_IFTYPE_STATION) ++ return 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ if (mac_addr) { ++ sta = rwnx_get_sta(rwnx_hw, mac_addr); ++ if (!sta) ++ return -EINVAL; ++ rwnx_key = &sta->key; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.paired_cipher_type = 0xff; ++ } else { ++ rwnx_key = &vif->key[key_index]; ++ vif->key_has_add = 0; ++ if (vif->wdev.iftype == NL80211_IFTYPE_STATION || vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ vif->sta.group_cipher_type = 0xff; ++ } ++ ++ error = rwnx_send_key_del(rwnx_hw, rwnx_key->hw_idx); ++ ++ rwnx_key->hw_idx = 0; ++ return error; ++} ++ ++/** ++ * @set_default_key: set the default key on an interface ++ */ ++static int rwnx_cfg80211_set_default_key(struct wiphy *wiphy, ++ struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index, bool unicast, bool multicast) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ return 0; ++} ++ ++/** ++ * @set_default_mgmt_key: set the default management frame key on an interface ++ */ ++static int rwnx_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, ++ struct net_device *netdev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ int link_id, ++#endif ++ u8 key_index) ++{ ++ return 0; ++} ++ ++/** ++ * @connect: Connect to the ESS with the specified parameters. When connected, ++ * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. ++ * If the connection fails for some reason, call cfg80211_connect_result() ++ * with the status from the AP. ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_connect_params *sme) ++{ ++ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct sm_connect_cfm sm_connect_cfm; ++ int error = 0; ++ int is_wep = ((sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104)); ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#if 1 ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTED) { ++ AICWFDBG(LOGDEBUG, "%s this connection is roam \r\n", __func__); ++ rwnx_vif->sta.is_roam = true; ++ }else{ ++ rwnx_vif->sta.is_roam = false; ++ } ++ ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING|| ++ (int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING) { ++ AICWFDBG(LOGERROR, "%s driver is disconnecting or connecting ,return it \r\n", __func__); ++ return 0; ++ } ++#endif ++ ++ if(rwnx_vif->sta.is_roam){ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_ROAMING); ++ }else{ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTING); ++ } ++ ++ if (is_wep) { ++ if(sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { ++ if(rwnx_vif->wep_enabled && rwnx_vif->wep_auth_err) { ++ if(rwnx_vif->last_auth_type == NL80211_AUTHTYPE_SHARED_KEY) ++ sme->auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; ++ else ++ sme->auth_type = NL80211_AUTHTYPE_SHARED_KEY; ++ } else { ++ if((rwnx_vif->wep_enabled && !rwnx_vif->wep_auth_err)) ++ sme->auth_type = rwnx_vif->last_auth_type; ++ else ++ sme->auth_type = NL80211_AUTHTYPE_SHARED_KEY; ++ } ++ printk("auto: use sme->auth_type = %d\r\n", sme->auth_type); ++ } else { ++ if (rwnx_vif->wep_enabled && rwnx_vif->wep_auth_err && (sme->auth_type == rwnx_vif->last_auth_type)) { ++ if(sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { ++ sme->auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; ++ printk("start connect, auth_type changed, shared --> open\n"); ++ } else if(sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { ++ sme->auth_type = NL80211_AUTHTYPE_SHARED_KEY; ++ printk("start connect, auth_type changed, open --> shared\n"); ++ } ++ } ++ } ++ } ++ ++ /* For SHARED-KEY authentication, must install key first */ ++ if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY && sme->key) { ++ struct key_params key_params; ++ key_params.key = (u8*)sme->key; ++ key_params.seq = NULL; ++ key_params.key_len = sme->key_len; ++ key_params.seq_len = 0; ++ key_params.cipher = sme->crypto.cipher_group; ++ rwnx_cfg80211_add_key(wiphy, dev, ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2) ++ 0, ++#endif ++ sme->key_idx, false, NULL, &key_params); ++ } ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ else if ((sme->auth_type == NL80211_AUTHTYPE_SAE) && ++ !(sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) { ++ netdev_err(dev, "Doesn't support SAE without external authentication\n"); ++ return -EINVAL; ++ } ++#endif ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) { ++ rwnx_hw->is_p2p_connected = 1; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) { ++ rwnx_vif->sta.paired_cipher_type = 0xff; ++ rwnx_vif->sta.group_cipher_type = 0xff; ++ } ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_sm_connect_req(rwnx_hw, rwnx_vif, sme, &sm_connect_cfm); ++ if (error) ++ return error; ++ ++ // Check the status ++ switch (sm_connect_cfm.status) { ++ case CO_OK: ++ error = 0; ++ break; ++ case CO_BUSY: ++ error = -EINPROGRESS; ++ break; ++ case CO_OP_IN_PROGRESS: ++ error = -EALREADY; ++ break; ++ default: ++ error = -EIO; ++ break; ++ } ++ ++ return error; ++ ++} ++ ++/** ++ * @disconnect: Disconnect from the BSS/ESS. ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, ++ u16 reason_code) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int ret = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ AICWFDBG(LOGINFO, "%s drv_vif_index:%d disconnect reason:%d \r\n", ++ __func__, rwnx_vif->drv_vif_index, reason_code); ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTED) { ++ AICWFDBG(LOGERROR, "%s this\r\n",__func__); ++ WARN_ON(1); ++ return -EBUSY; ++ } ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTING) { ++ AICWFDBG(LOGERROR, "%s wifi is disconnecting, return it:%d \r\n", ++ __func__, reason_code); ++ return -EBUSY; ++ } ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTED|| ++ atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTING|| ++ atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_ROAMING) { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTING); ++ key_flag = true; ++ ret = rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, reason_code); ++#ifdef AICWF_SDIO_SUPPORT ++ if (rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { ++ AICWFDBG(LOGINFO, "%s bus is down %d\n", __func__, ret); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ } ++#endif ++ return ret; ++ } ++#if 0 ++ else { ++ cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, ++ reason_code?reason_code:WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ return 0; ++ } ++#endif ++ return 0; ++} ++ ++#ifdef CONFIG_SCHED_SCAN ++ ++static int rwnx_cfg80211_sched_scan_stop(struct wiphy *wiphy, ++ struct net_device *ndev ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) ++ ,u64 reqid) ++#else ++ ) ++#endif ++{ ++ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ //struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ AICWFDBG(LOGINFO, "%s enter wiphy:%p\r\n", __func__, wiphy); ++ ++ if(rwnx_hw->scan_request){ ++ AICWFDBG(LOGINFO, "%s rwnx_send_scanu_cancel_req\r\n", __func__); ++ return rwnx_send_scanu_cancel_req(rwnx_hw, NULL); ++ }else{ ++ return 0; ++ } ++} ++ ++ ++static int rwnx_cfg80211_sched_scan_start(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_sched_scan_request *request) ++ ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct cfg80211_scan_request *scan_request = NULL; ++ ++ int ret = 0; ++ int index = 0; ++ ++ AICWFDBG(LOGINFO, "%s enter wiphy:%p\r\n", __func__, wiphy); ++ ++ if(rwnx_hw->is_sched_scan || scanning){ ++ AICWFDBG(LOGERROR, "%s is_sched_scanning and scanning, busy", __func__); ++ return -EBUSY; ++ } ++ ++ scan_request = (struct cfg80211_scan_request *)kmalloc(sizeof(struct cfg80211_scan_request), GFP_KERNEL); ++ ++ scan_request->ssids = request->ssids; ++ scan_request->n_channels = request->n_channels; ++ scan_request->n_ssids = request->n_match_sets; ++ scan_request->no_cck = false; ++ scan_request->ie = request->ie; ++ scan_request->ie_len = request->ie_len; ++ scan_request->flags = request->flags; ++ ++ scan_request->wiphy = wiphy; ++ scan_request->scan_start = request->scan_start; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) ++ memcpy(scan_request->mac_addr, request->mac_addr, ETH_ALEN); ++ memcpy(scan_request->mac_addr_mask, request->mac_addr_mask, ETH_ALEN); ++#endif ++ rwnx_hw->sched_scan_req = request; ++ scan_request->wdev = &rwnx_vif->wdev; ++ AICWFDBG(LOGDEBUG, "%s scan_request->n_channels:%d \r\n", __func__, scan_request->n_channels); ++ AICWFDBG(LOGDEBUG, "%s scan_request->n_ssids:%d \r\n", __func__, scan_request->n_ssids); ++ ++ for(index = 0; index < scan_request->n_ssids; index++){ ++ memset(scan_request->ssids[index].ssid, 0, IEEE80211_MAX_SSID_LEN); ++ ++ memcpy(scan_request->ssids[index].ssid, ++ request->match_sets[index].ssid.ssid, ++ IEEE80211_MAX_SSID_LEN); ++ ++ scan_request->ssids[index].ssid_len = request->match_sets[index].ssid.ssid_len; ++ ++ AICWFDBG(LOGDEBUG, "%s request ssid:%s len:%d \r\n", __func__, ++ scan_request->ssids[index].ssid, scan_request->ssids[index].ssid_len); ++ } ++ ++ for(index = 0;index < scan_request->n_channels; index++){ ++ scan_request->channels[index] = request->channels[index]; ++ ++ AICWFDBG(LOGDEBUG, "%s scan_request->channels[%d]:%d \r\n", __func__, index, ++ scan_request->channels[index]->center_freq); ++ ++ if(scan_request->channels[index] == NULL){ ++ AICWFDBG(LOGERROR, "%s ERROR!!! channels is NULL", __func__); ++ continue; ++ } ++ } ++ ++ rwnx_hw->is_sched_scan = true; ++ ++ if(scanning){ ++ AICWFDBG(LOGERROR, "%s scanning, about it", __func__); ++ kfree(scan_request); ++ return -EBUSY; ++ }else{ ++ ret = rwnx_cfg80211_scan(wiphy, scan_request); ++ } ++ ++ return ret; ++} ++#endif //CONFIG_SCHED_SCAN ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++/** ++ * @external_auth: indicates result of offloaded authentication processing from ++ * user space ++ */ ++static int rwnx_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_external_auth_params *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ ++ if (!rwnx_vif->sta.external_auth) ++ return -EINVAL; ++ ++ rwnx_external_auth_disable(rwnx_vif); ++ return rwnx_send_sm_external_auth_required_rsp(rwnx_hw, rwnx_vif, ++ params->status); ++} ++#endif ++ ++/** ++ * @add_station: Add a new station. ++ */ ++static int rwnx_cfg80211_add_station(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac, ++#else ++ const u8 *mac, ++#endif ++ struct station_parameters *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct me_sta_add_cfm me_sta_add_cfm; ++ int error = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ WARN_ON(RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN); ++ ++ /* Do not add TDLS station */ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ++ return 0; ++ ++ /* Indicate we are in a STA addition process - This will allow handling ++ * potential PS mode change indications correctly ++ */ ++ rwnx_hw->adding_sta = true; ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_me_sta_add(rwnx_hw, params, mac, rwnx_vif->vif_index, &me_sta_add_cfm); ++ if (error) ++ return error; ++ ++ // Check the status ++ switch (me_sta_add_cfm.status) { ++ case CO_OK: ++ { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[me_sta_add_cfm.sta_idx]; ++ int tid; ++ sta->aid = params->aid; ++ ++ sta->sta_idx = me_sta_add_cfm.sta_idx; ++ sta->ch_idx = rwnx_vif->ch_index; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->vlan_idx = sta->vif_idx; ++ sta->qos = (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) != 0; ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ sta->ht = params->link_sta_params.ht_capa ? 1 : 0; ++ sta->vht = params->link_sta_params.vht_capa ? 1 : 0; ++#else ++ sta->ht = params->ht_capa ? 1 : 0; ++ sta->vht = params->vht_capa ? 1 : 0; ++#endif ++ sta->acm = 0; ++ sta->key.hw_idx = 0; ++ ++ if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) ++ sta->mesh_pm = params->local_pm; ++ else ++ sta->mesh_pm = rwnx_vif->ap.next_mesh_pm; ++ rwnx_update_mesh_power_mode(rwnx_vif); ++ ++ for (tid = 0; tid < NX_NB_TXQ_PER_STA; tid++) { ++ int uapsd_bit = rwnx_hwq2uapsd[rwnx_tid2hwq[tid]]; ++ if (params->uapsd_queues & uapsd_bit) ++ sta->uapsd_tids |= 1 << tid; ++ else ++ sta->uapsd_tids &= ~(1 << tid); ++ } ++ memcpy(sta->mac_addr, mac, ETH_ALEN); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, sta); ++#endif ++ ++ /* Ensure that we won't process PS change or channel switch ind*/ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_txq_sta_init(rwnx_hw, sta, rwnx_txq_vif_get_status(rwnx_vif)); ++ list_add_tail(&sta->list, &rwnx_vif->ap.sta_list); ++ sta->valid = true; ++ rwnx_ps_bh_enable(rwnx_hw, sta, sta->ps.active || me_sta_add_cfm.pm_state); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ error = 0; ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { ++ struct station_info sinfo; ++ memset(&sinfo, 0, sizeof(struct station_info)); ++ sinfo.assoc_req_ies = NULL; ++ sinfo.assoc_req_ies_len = 0; ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; ++ #endif ++ cfg80211_new_sta(rwnx_vif->ndev, sta->mac_addr, &sinfo, GFP_KERNEL); ++ } ++#ifdef CONFIG_RWNX_BFMER ++ if (rwnx_hw->mod_params->bfmer) ++ rwnx_send_bfmer_enable(rwnx_hw, sta, params->vht_capa); ++ ++ rwnx_mu_group_sta_init(sta, params->vht_capa); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ #define PRINT_STA_FLAG(f) \ ++ (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "") ++ ++ netdev_info(dev, "Add sta %d (%pM) flags=%s%s%s%s%s%s%s", ++ sta->sta_idx, mac, ++ PRINT_STA_FLAG(AUTHORIZED), ++ PRINT_STA_FLAG(SHORT_PREAMBLE), ++ PRINT_STA_FLAG(WME), ++ PRINT_STA_FLAG(MFP), ++ PRINT_STA_FLAG(AUTHENTICATED), ++ PRINT_STA_FLAG(TDLS_PEER), ++ PRINT_STA_FLAG(ASSOCIATED)); ++ #undef PRINT_STA_FLAG ++ break; ++ } ++ default: ++ error = -EBUSY; ++ break; ++ } ++ ++ rwnx_hw->adding_sta = false; ++ ++ return error; ++} ++ ++/** ++ * @del_station: Remove a station ++ */ ++static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)) ++ const u8 *mac ++#else ++ struct station_del_parameters *params ++#endif ++ ++) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_sta *cur, *tmp; ++ int error = 0, found = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ const u8 *mac = NULL; ++#endif ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *reord_tmp; ++ u8 *macaddr; ++ struct aicwf_rx_priv *rx_priv; ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ if (params) ++ mac = params->mac; ++#endif ++ printk("%s: %pM\n", __func__, mac); ++ ++ do { ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ if(list_empty(&rwnx_vif->ap.sta_list)) { ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ break; ++ } ++ ++ list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { ++ if ((!mac) || (!memcmp(cur->mac_addr, mac, ETH_ALEN))) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if(found) { ++ cur->ps.active = false; ++ cur->valid = false; ++ list_del(&cur->list); ++ } ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if(found) { ++ netdev_info(dev, "Del sta %d (%pM)", cur->sta_idx, cur->mac_addr); ++ if (cur->vif_idx != cur->vlan_idx) { ++ struct rwnx_vif *vlan_vif; ++ vlan_vif = rwnx_hw->vif_table[cur->vlan_idx]; ++ if (vlan_vif->up) { ++ if ((RWNX_VIF_TYPE(vlan_vif) == NL80211_IFTYPE_AP_VLAN) && ++ (vlan_vif->use_4addr)) { ++ vlan_vif->ap_vlan.sta_4a = NULL; ++ } else { ++ WARN(1, "Deleting sta belonging to VLAN other than AP_VLAN 4A"); ++ } ++ } ++ } ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { ++ cfg80211_del_sta(rwnx_vif->ndev, cur->mac_addr, GFP_KERNEL); ++ } ++ ++#ifdef AICWF_RX_REORDER ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv = rwnx_hw->sdiodev->rx_priv; ++#else ++ rx_priv = rwnx_hw->usbdev->rx_priv; ++#endif ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ BUG();//should be other function ++ } ++ else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)){ ++ macaddr = cur->mac_addr; ++ printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0],macaddr[1],macaddr[2], \ ++ macaddr[3],macaddr[4],macaddr[5]); ++ list_for_each_entry_safe(reord_info, reord_tmp, ++ &rx_priv->stas_reord_list, list) { ++ printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0],reord_info->mac_addr[1],reord_info->mac_addr[2], \ ++ reord_info->mac_addr[3],reord_info->mac_addr[4],reord_info->mac_addr[5]); ++ if (!memcmp(reord_info->mac_addr, macaddr, 6)) { ++ reord_deinit_sta(rx_priv, reord_info); ++ break; ++ } ++ } ++ } ++#endif ++ ++ rwnx_txq_sta_deinit(rwnx_hw, cur); ++ error = rwnx_send_me_sta_del(rwnx_hw, cur->sta_idx, false); ++ if ((error != 0) && (error != -EPIPE)) ++ return error; ++ ++#ifdef CONFIG_RWNX_BFMER ++ // Disable Beamformer if supported ++ rwnx_bfmer_report_del(rwnx_hw, cur); ++ rwnx_mu_group_sta_del(rwnx_hw, cur); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++#ifdef CONFIG_DEBUG_FS_AIC ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, cur); ++#endif ++ } ++ ++ if(mac) ++ break; ++ } while (1); ++ ++ rwnx_update_mesh_power_mode(rwnx_vif); ++ ++ if(!found && mac != NULL) ++ return -ENOENT; ++ else ++ return 0; ++} ++ ++ ++void apm_staloss_work_process(struct work_struct *work) ++{ ++ struct rwnx_hw *rwnx_hw = container_of(work, struct rwnx_hw, apmStalossWork); ++ struct rwnx_sta *cur, *tmp; ++ int error = 0; ++ ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *reord_tmp; ++ u8 *macaddr; ++ struct aicwf_rx_priv *rx_priv; ++#endif ++ struct rwnx_vif *rwnx_vif; ++ bool_l found = false; ++ const u8 *mac = rwnx_hw->sta_mac_addr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == rwnx_hw->apm_vif_idx) { ++ found = true; ++ break; ++ } ++ } ++ ++ printk("apm vif idx=%d, found=%d, mac addr=%pM\n", rwnx_hw->apm_vif_idx, found, mac); ++ if (!found || !rwnx_vif || (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_AP && RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_P2P_GO)) ++ { ++ return; ++ } ++ ++ found = false; ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { ++ if ((mac) && (!memcmp(cur->mac_addr, mac, ETH_ALEN))) { ++ found = true; ++ break; ++ } ++ } ++ if(found) { ++ cur->ps.active = false; ++ cur->valid = false; ++ list_del(&cur->list); ++ } ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ if(found) { ++ netdev_info(rwnx_vif->ndev, "Del sta %d (%pM)", cur->sta_idx, cur->mac_addr); ++ if (cur->vif_idx != cur->vlan_idx) { ++ struct rwnx_vif *vlan_vif; ++ vlan_vif = rwnx_hw->vif_table[cur->vlan_idx]; ++ if (vlan_vif->up) { ++ if ((RWNX_VIF_TYPE(vlan_vif) == NL80211_IFTYPE_AP_VLAN) && ++ (vlan_vif->use_4addr)) { ++ vlan_vif->ap_vlan.sta_4a = NULL; ++ } else { ++ WARN(1, "Deleting sta belonging to VLAN other than AP_VLAN 4A"); ++ } ++ } ++ } ++ ++#ifdef AICWF_RX_REORDER ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv = rwnx_hw->sdiodev->rx_priv; ++#else ++ rx_priv = rwnx_hw->usbdev->rx_priv; ++#endif ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ BUG();//should be other function ++ } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { ++ macaddr = cur->mac_addr; ++ printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0], macaddr[1], macaddr[2], \ ++ macaddr[3], macaddr[4], macaddr[5]); ++ list_for_each_entry_safe(reord_info, reord_tmp, ++ &rx_priv->stas_reord_list, list) { ++ printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0], reord_info->mac_addr[1], reord_info->mac_addr[2], \ ++ reord_info->mac_addr[3], reord_info->mac_addr[4], reord_info->mac_addr[5]); ++ if (!memcmp(reord_info->mac_addr, macaddr, 6)) { ++ reord_deinit_sta(rx_priv, reord_info); ++ break; ++ } ++ } ++ } ++#endif ++ ++ rwnx_txq_sta_deinit(rwnx_hw, cur); ++ error = rwnx_send_me_sta_del(rwnx_hw, cur->sta_idx, false); ++ if ((error != 0) && (error != -EPIPE)) ++ return; ++ ++#ifdef CONFIG_RWNX_BFMER ++ // Disable Beamformer if supported ++ rwnx_bfmer_report_del(rwnx_hw, cur); ++ rwnx_mu_group_sta_del(rwnx_hw, cur); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++#ifdef CONFIG_DEBUG_FS_AIC ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, cur); ++#endif ++ }else { ++ printk("sta not found: %pM\n", mac); ++ return; ++ } ++ ++ rwnx_update_mesh_power_mode(rwnx_vif); ++} ++ ++ ++void apm_probe_sta_work_process(struct work_struct *work) ++{ ++ struct apm_probe_sta *probe_sta = container_of(work, struct apm_probe_sta, apmprobestaWork); ++ struct rwnx_vif *rwnx_vif = container_of(probe_sta, struct rwnx_vif, sta_probe); ++ bool found = false; ++ struct rwnx_sta *cur, *tmp; ++ ++ u8 *mac = rwnx_vif->sta_probe.sta_mac_addr; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { ++ if (!memcmp(cur->mac_addr, mac, ETH_ALEN)) { ++ found = true; ++ break; ++ } ++ } ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ ++ printk("sta %pM found = %d\n", mac, found); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) ++ if(found) ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, 0, false, GFP_ATOMIC); ++ else ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 0, 0, false, GFP_ATOMIC); ++#else ++ if(found) ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, GFP_ATOMIC); ++ else ++ cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 0, GFP_ATOMIC); ++ ++#endif ++ rwnx_vif->sta_probe.probe_id ++; ++} ++/** ++ * @change_station: Modify a given station. Note that flags changes are not much ++ * validated in cfg80211, in particular the auth/assoc/authorized flags ++ * might come to the driver in invalid combinations -- make sure to check ++ * them, also against the existing state! Drivers must call ++ * cfg80211_check_station_change() to validate the information. ++ */ ++static int rwnx_cfg80211_change_station(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac, ++#else ++ const u8 *mac, ++#endif ++ struct station_parameters *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_sta *sta; ++ ++ sta = rwnx_get_sta(rwnx_hw, mac); ++ if (!sta) { ++ /* Add the TDLS station */ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct me_sta_add_cfm me_sta_add_cfm; ++ int error = 0; ++ ++ /* Indicate we are in a STA addition process - This will allow handling ++ * potential PS mode change indications correctly ++ */ ++ rwnx_hw->adding_sta = true; ++ ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_me_sta_add(rwnx_hw, params, mac, rwnx_vif->vif_index, &me_sta_add_cfm); ++ if (error) ++ return error; ++ ++ // Check the status ++ switch (me_sta_add_cfm.status) { ++ case CO_OK: ++ { ++ int tid; ++ sta = &rwnx_hw->sta_table[me_sta_add_cfm.sta_idx]; ++ sta->aid = params->aid; ++ sta->sta_idx = me_sta_add_cfm.sta_idx; ++ sta->ch_idx = rwnx_vif->ch_index; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->vlan_idx = sta->vif_idx; ++ sta->qos = (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) != 0; ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ sta->ht = params->link_sta_params.ht_capa ? 1 : 0; ++ sta->vht = params->link_sta_params.vht_capa ? 1 : 0; ++#else ++ sta->ht = params->ht_capa ? 1 : 0; ++ sta->vht = params->vht_capa ? 1 : 0; ++#endif ++ sta->acm = 0; ++ for (tid = 0; tid < NX_NB_TXQ_PER_STA; tid++) { ++ int uapsd_bit = rwnx_hwq2uapsd[rwnx_tid2hwq[tid]]; ++ if (params->uapsd_queues & uapsd_bit) ++ sta->uapsd_tids |= 1 << tid; ++ else ++ sta->uapsd_tids &= ~(1 << tid); ++ } ++ memcpy(sta->mac_addr, mac, ETH_ALEN); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, sta); ++#endif ++ /* Ensure that we won't process PS change or channel switch ind*/ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_txq_sta_init(rwnx_hw, sta, rwnx_txq_vif_get_status(rwnx_vif)); ++ if (rwnx_vif->tdls_status == TDLS_SETUP_RSP_TX) { ++ rwnx_vif->tdls_status = TDLS_LINK_ACTIVE; ++ sta->tdls.initiator = true; ++ sta->tdls.active = true; ++ } ++ /* Set TDLS channel switch capability */ ++ if ((params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) && ++ !rwnx_vif->tdls_chsw_prohibited) ++ sta->tdls.chsw_allowed = true; ++ rwnx_vif->sta.tdls_sta = sta; ++ sta->valid = true; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++#ifdef CONFIG_RWNX_BFMER ++ if (rwnx_hw->mod_params->bfmer) ++ rwnx_send_bfmer_enable(rwnx_hw, sta, params->vht_capa); ++ ++ rwnx_mu_group_sta_init(sta, NULL); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ #define PRINT_STA_FLAG(f) \ ++ (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "") ++ ++ netdev_info(dev, "Add %s TDLS sta %d (%pM) flags=%s%s%s%s%s%s%s", ++ sta->tdls.initiator ? "initiator" : "responder", ++ sta->sta_idx, mac, ++ PRINT_STA_FLAG(AUTHORIZED), ++ PRINT_STA_FLAG(SHORT_PREAMBLE), ++ PRINT_STA_FLAG(WME), ++ PRINT_STA_FLAG(MFP), ++ PRINT_STA_FLAG(AUTHENTICATED), ++ PRINT_STA_FLAG(TDLS_PEER), ++ PRINT_STA_FLAG(ASSOCIATED)); ++ #undef PRINT_STA_FLAG ++ ++ break; ++ } ++ default: ++ error = -EBUSY; ++ break; ++ } ++ ++ rwnx_hw->adding_sta = false; ++ } else { ++ return -EINVAL; ++ } ++ } ++ ++ if (params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) ++ rwnx_send_me_set_control_port_req(rwnx_hw, ++ (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) != 0, ++ sta->sta_idx); ++ ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MESH_POINT) { ++ if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) { ++ if (params->plink_state < NUM_NL80211_PLINK_STATES) { ++ rwnx_send_mesh_peer_update_ntf(rwnx_hw, vif, sta->sta_idx, params->plink_state); ++ } ++ } ++ ++ if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) { ++ sta->mesh_pm = params->local_pm; ++ rwnx_update_mesh_power_mode(vif); ++ } ++ } ++ ++ if (params->vlan) { ++ uint8_t vlan_idx; ++ ++ vif = netdev_priv(params->vlan); ++ vlan_idx = vif->vif_index; ++ ++ if (sta->vlan_idx != vlan_idx) { ++ struct rwnx_vif *old_vif; ++ old_vif = rwnx_hw->vif_table[sta->vlan_idx]; ++ rwnx_txq_sta_switch_vif(sta, old_vif, vif); ++ sta->vlan_idx = vlan_idx; ++ ++ if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP_VLAN) && ++ (vif->use_4addr)) { ++ WARN((vif->ap_vlan.sta_4a), ++ "4A AP_VLAN interface with more than one sta"); ++ vif->ap_vlan.sta_4a = sta; ++ } ++ ++ if ((RWNX_VIF_TYPE(old_vif) == NL80211_IFTYPE_AP_VLAN) && ++ (old_vif->use_4addr)) { ++ old_vif->ap_vlan.sta_4a = NULL; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * @start_ap: Start acting in AP mode defined by the parameters. ++ */ ++static int rwnx_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_ap_settings *settings) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct apm_start_cfm apm_start_cfm; ++ struct rwnx_ipc_elem_var elem; ++ struct rwnx_sta *sta; ++ int error = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ INIT_WORK(&rwnx_vif->sta_probe.apmprobestaWork, apm_probe_sta_work_process); ++ rwnx_vif->sta_probe.apmprobesta_wq = create_singlethread_workqueue("apmprobe_wq"); ++ if (!rwnx_vif->sta_probe.apmprobesta_wq) { ++ txrx_err("insufficient memory to create apmprobe_wq.\n"); ++ return -ENOBUFS; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ++ rwnx_hw->is_p2p_connected = 1; ++ /* Forward the information to the LMAC */ ++ error = rwnx_send_apm_start_req(rwnx_hw, rwnx_vif, settings, &apm_start_cfm, &elem); ++ if (error) ++ goto end; ++ ++ // Check the status ++ switch (apm_start_cfm.status) { ++ case CO_OK: ++ { ++ u8 txq_status = 0; ++ rwnx_vif->ap.bcmc_index = apm_start_cfm.bcmc_idx; ++ rwnx_vif->ap.flags = 0; ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ rwnx_vif->ap.aic_index = 0; ++#endif ++ rwnx_vif->ap.csa = NULL; ++ sta = &rwnx_hw->sta_table[apm_start_cfm.bcmc_idx]; ++ sta->valid = true; ++ sta->aid = 0; ++ sta->sta_idx = apm_start_cfm.bcmc_idx; ++ sta->ch_idx = apm_start_cfm.ch_idx; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->qos = false; ++ sta->acm = 0; ++ sta->ps.active = false; ++ rwnx_mu_group_sta_init(sta, NULL); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_link(rwnx_vif, apm_start_cfm.ch_idx, ++ &settings->chandef); ++ if (rwnx_hw->cur_chanctx != apm_start_cfm.ch_idx) { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ rwnx_txq_vif_init(rwnx_hw, rwnx_vif, txq_status); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ error = 0; ++ /* If the AP channel is already the active, we probably skip radar ++ activation on MM_CHANNEL_SWITCH_IND (unless another vif use this ++ ctxt). In anycase retest if radar detection must be activated ++ */ ++ if (txq_status == 0) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ } ++ break; ++ } ++ case CO_BUSY: ++ error = -EINPROGRESS; ++ break; ++ case CO_OP_IN_PROGRESS: ++ error = -EALREADY; ++ break; ++ default: ++ error = -EIO; ++ break; ++ } ++ ++ if (error) { ++ netdev_info(dev, "Failed to start AP (%d)", error); ++ } else { ++ netdev_info(dev, "AP started: ch=%d, bcmc_idx=%d channel=%d bw=%d", ++ rwnx_vif->ch_index, rwnx_vif->ap.bcmc_index, ++ ((settings->chandef).chan)->center_freq, ++ ((settings->chandef).width)); ++ } ++ ++end: ++ //rwnx_ipc_elem_var_deallocs(rwnx_hw, &elem); ++ ++ return error; ++} ++ ++ ++/** ++ * @change_beacon: Change the beacon parameters for an access point mode ++ * interface. This should reject the call when AP mode wasn't started. ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)) ++static int rwnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_ap_update *params) ++#else ++static int rwnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_beacon_data *info) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_bcn *bcn = &vif->ap.bcn; ++ struct rwnx_ipc_elem_var elem; ++ u8 *buf; ++ int error = 0; ++ elem.dma_addr = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Build the beacon ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)) ++ buf = rwnx_build_bcn(bcn, ¶ms->beacon); ++#else ++ buf = rwnx_build_bcn(bcn, info); ++#endif ++ if (!buf) ++ return -ENOMEM; ++ ++ rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn->len); ++ ++ // Forward the information to the LMAC ++ error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, ++ bcn->len, bcn->head_len, bcn->tim_len, NULL); ++ ++ return error; ++} ++ ++/** ++ * * @stop_ap: Stop being an AP, including stopping beaconing. ++ */ ++#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION) ++static int rwnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, unsigned int link_id) ++#else ++static int rwnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_sta *sta; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ ++ /* delete any remaining STA*/ ++ while (!list_empty(&rwnx_vif->ap.sta_list)) { ++ rwnx_cfg80211_del_station_compat(wiphy, dev, NULL); ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ++ rwnx_hw->is_p2p_connected = 0; ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ rwnx_send_apm_stop_req(rwnx_hw, rwnx_vif); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_unlink(rwnx_vif); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ /* delete BC/MC STA */ ++ sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ rwnx_txq_vif_deinit(rwnx_hw, rwnx_vif); ++ rwnx_del_bcn(&rwnx_vif->ap.bcn); ++ rwnx_del_csa(rwnx_vif); ++ ++ flush_workqueue(rwnx_vif->sta_probe.apmprobesta_wq); ++ destroy_workqueue(rwnx_vif->sta_probe.apmprobesta_wq); ++ ++ netdev_info(dev, "AP Stopped"); ++ ++ return 0; ++} ++ ++/** ++ * @set_monitor_channel: Set the monitor mode channel for the device. If other ++ * interfaces are active this callback should reject the configuration. ++ * If no interfaces are active or the device is down, the channel should ++ * be stored for when a monitor interface becomes active. ++ * ++ * Also called internaly with chandef set to NULL simply to retrieve the channel ++ * configured at firmware level. ++ */ ++static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 13, 0) ++ struct net_device *, ++#endif ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif; ++ struct me_config_monitor_cfm cfm; ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (rwnx_hw->monitor_vif == RWNX_INVALID_VIF) ++ return -EINVAL; ++ ++ rwnx_vif = rwnx_hw->vif_table[rwnx_hw->monitor_vif]; ++ ++ // Do nothing if monitor interface is already configured with the requested channel ++ if (rwnx_chanctx_valid(rwnx_hw, rwnx_vif->ch_index)) { ++ struct rwnx_chanctx *ctxt; ++ ctxt = &rwnx_vif->rwnx_hw->chanctx_table[rwnx_vif->ch_index]; ++ if (chandef && cfg80211_chandef_identical(&ctxt->chan_def, chandef)) ++ return 0; ++ } ++ ++ // Always send command to firmware. It allows to retrieve channel context index ++ // and its configuration. ++ if (rwnx_send_config_monitor_req(rwnx_hw, chandef, &cfm)) ++ return -EIO; ++ ++ // Always re-set channel context info ++ rwnx_chanctx_unlink(rwnx_vif); ++ ++ ++ ++ // If there is also a STA interface not yet connected then monitor interface ++ // will only have a channel context after the connection of the STA interface. ++ if (cfm.chan_index != RWNX_CH_NOT_SET) { ++ struct cfg80211_chan_def mon_chandef; ++ ++ if (rwnx_hw->vif_started > 1) { ++ // In this case we just want to update the channel context index not ++ // the channel configuration ++ rwnx_chanctx_link(rwnx_vif, cfm.chan_index, NULL); ++ return -EBUSY; ++ } ++ ++ mon_chandef.chan = ieee80211_get_channel(wiphy, cfm.chan.prim20_freq); ++ mon_chandef.center_freq1 = cfm.chan.center1_freq; ++ mon_chandef.center_freq2 = cfm.chan.center2_freq; ++ mon_chandef.width = chnl2bw[cfm.chan.type]; ++ rwnx_chanctx_link(rwnx_vif, cfm.chan_index, &mon_chandef); ++ } ++ ++ return 0; ++} ++ ++int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef){ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 13, 0) ++ return rwnx_cfg80211_set_monitor_channel(wiphy, NULL, chandef); ++#else ++ return rwnx_cfg80211_set_monitor_channel(wiphy, chandef); ++#endif ++} ++ ++ ++/** ++ * @probe_client: probe an associated client, must return a cookie that it ++ * later passes to cfg80211_probe_status(). ++ */ ++int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, u64 *cookie) ++{ ++// struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_sta *sta = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if((RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP) && (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_P2P_GO) && ++ (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP_VLAN)) ++ return -EINVAL; ++ spin_lock_bh(&vif->rwnx_hw->cb_lock); ++ list_for_each_entry(sta, &vif->ap.sta_list, list){ ++ if (sta->valid && ether_addr_equal(sta->mac_addr, peer)) ++ break; ++ } ++ spin_unlock_bh(&vif->rwnx_hw->cb_lock); ++ ++ if (!sta) ++ return -ENOENT; ++ ++ ++ memcpy(vif->sta_probe.sta_mac_addr, peer, 6); ++ queue_work(vif->sta_probe.apmprobesta_wq, &vif->sta_probe.apmprobestaWork); ++ ++ *cookie = vif->sta_probe.probe_id; ++ ++ return 0; ++ ++} ++ ++/** ++ * @mgmt_frame_register: Notify driver that a management frame type was ++ * registered. Note that this callback may not sleep, and cannot run ++ * concurrently with itself. ++ */ ++void rwnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ u16 frame_type, bool reg) ++{ ++} ++ ++/** ++ * @set_wiphy_params: Notify that wiphy parameters have changed; ++ * @changed bitfield (see &enum wiphy_params_flags) describes which values ++ * have changed. The actual parameter values are available in ++ * struct wiphy. If returning an error, no value should be changed. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ++#else ++static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, int radio_idx, u32 changed) ++#endif ++{ ++ return 0; ++} ++ ++ ++/** ++ * @set_tx_power: set the transmit power according to the parameters, ++ * the power passed is in mBm, to get dBm use MBM_TO_DBM(). The ++ * wdev may be %NULL if power was set for the wiphy, and will ++ * always be %NULL unless the driver supports per-vif TX power ++ * (as advertised by the nl80211 feature flag.) ++ */ ++static int rwnx_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ enum nl80211_tx_power_setting type, int mbm) ++#else ++ int radio_idx, enum nl80211_tx_power_setting type, int mbm) ++#endif ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif; ++ s8 pwr; ++ int res = 0; ++ ++ if (type == NL80211_TX_POWER_AUTOMATIC) { ++ pwr = 0x7f; ++ } else { ++ pwr = MBM_TO_DBM(mbm); ++ } ++ ++ if (wdev) { ++ vif = container_of(wdev, struct rwnx_vif, wdev); ++ res = rwnx_send_set_power(rwnx_hw, vif->vif_index, pwr, NULL); ++ } else { ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ res = rwnx_send_set_power(rwnx_hw, vif->vif_index, pwr, NULL); ++ if (res) ++ break; ++ } ++ } ++ ++ return res; ++} ++ ++static int rwnx_cfg80211_get_tx_power(struct wiphy *wiphy, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) ++ struct wireless_dev *wdev, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 14, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ unsigned int link_id, ++#else ++ int radio_idx, unsigned int link_id, ++#endif ++#endif ++#endif ++ int *mbm) ++{ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) ++ struct wireless_dev *wdev = NULL; ++ #endif ++ //struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ //struct rwnx_vif *vif; ++ s8 pwr = 0; ++ int res = 0; ++ ++ *mbm = get_txpwr_max(pwr); ++ ++ return res; ++} ++ ++/** ++ * @set_power_mgmt: set the power save to one of those two modes: ++ * Power-save off ++ * Power-save on - Dynamic mode ++ */ ++static int rwnx_cfg80211_set_power_mgmt(struct wiphy *wiphy, ++ struct net_device *dev, ++ bool enabled, int timeout) ++{ ++#if 0 ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ u8 ps_mode; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ if (timeout >= 0) ++ netdev_info(dev, "Ignore timeout value %d", timeout); ++ ++ if (!(rwnx_hw->version_cfm.features & BIT(MM_FEAT_PS_BIT))) ++ enabled = false; ++ ++ if (enabled) { ++ /* Switch to Dynamic Power Save */ ++ ps_mode = MM_PS_MODE_ON_DYN; ++ } else { ++ /* Exit Power Save */ ++ ps_mode = MM_PS_MODE_OFF; ++ } ++ ++ return rwnx_send_me_set_ps_mode(rwnx_hw, ps_mode); ++#else ++ /* TODO ++ * Add handle in the feature! ++ */ ++ return 0; ++#endif ++} ++ ++static int rwnx_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev, ++ struct ieee80211_txq_params *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ u8 hw_queue, aifs, cwmin, cwmax; ++ u32 param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ hw_queue = rwnx_ac2hwq[0][params->ac]; ++ ++ aifs = params->aifs; ++ cwmin = fls(params->cwmin); ++ cwmax = fls(params->cwmax); ++ ++ /* Store queue information in general structure */ ++ param = (u32) (aifs << 0); ++ param |= (u32) (cwmin << 4); ++ param |= (u32) (cwmax << 8); ++ param |= (u32) (params->txop) << 12; ++ ++ /* Send the MM_SET_EDCA_REQ message to the FW */ ++ return rwnx_send_set_edca(rwnx_hw, hw_queue, param, false, rwnx_vif->vif_index); ++} ++ ++ ++/** ++ * @remain_on_channel: Request the driver to remain awake on the specified ++ * channel for the specified duration to complete an off-channel ++ * operation (e.g., public action frame exchange). When the driver is ++ * ready on the requested channel, it must indicate this with an event ++ * notification by calling cfg80211_ready_on_channel(). ++ */ ++static int ++rwnx_cfg80211_remain_on_channel_(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, ++ unsigned int duration, u64 *cookie, bool mgmt_roc_flag) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ //struct rwnx_vif *rwnx_vif = netdev_priv(wdev->netdev); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ struct rwnx_roc_elem *roc_elem; ++ struct mm_add_if_cfm add_if_cfm; ++ struct mm_remain_on_channel_cfm roc_cfm; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* For debug purpose (use ftrace kernel option) */ ++#ifdef CREATE_TRACE_POINTS ++ trace_roc(rwnx_vif->vif_index, chan->center_freq, duration); ++#endif ++ /* Check that no other RoC procedure has been launched */ ++ if (rwnx_hw->roc_elem) { ++ msleep(2); ++ if (rwnx_hw->roc_elem) { ++ printk("remain_on_channel fail\n"); ++ return -EBUSY; ++ } ++ } ++ ++ printk("remain:%d,%d,%d\n", rwnx_vif->vif_index, rwnx_vif->is_p2p_vif, rwnx_hw->is_p2p_alive); ++#ifdef CONFIG_USE_P2P0 ++ if (rwnx_vif->is_p2p_vif) { ++#else ++ if (rwnx_vif == rwnx_hw->p2p_dev_vif && !rwnx_vif->up) { ++#endif ++ if (!rwnx_hw->is_p2p_alive) { ++ error = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, //wdev->netdev->dev_addr, ++ RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); ++ if (error) ++ return -EIO; ++ ++ if (add_if_cfm.status != 0) { ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_hw->is_p2p_alive = 1; ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ } else { ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ } ++ } ++ ++ /* Allocate a temporary RoC element */ ++ roc_elem = kmalloc(sizeof(struct rwnx_roc_elem), GFP_KERNEL); ++ ++ /* Verify that element has well been allocated */ ++ if (!roc_elem) { ++ return -ENOMEM; ++ } ++ ++ /* Initialize the RoC information element */ ++ roc_elem->wdev = wdev; ++ roc_elem->chan = chan; ++ roc_elem->duration = duration; ++ roc_elem->mgmt_roc = mgmt_roc_flag; ++ roc_elem->on_chan = false; ++ ++ /* Initialize the OFFCHAN TX queue to allow off-channel transmissions */ ++ rwnx_txq_offchan_init(rwnx_vif); ++ ++ /* Forward the information to the FMAC */ ++ rwnx_hw->roc_elem = roc_elem; ++ error = rwnx_send_roc(rwnx_hw, rwnx_vif, chan, duration, &roc_cfm); ++ ++ /* If no error, keep all the information for handling of end of procedure */ ++ if (error == 0) { ++ /* Set the cookie value */ ++ *cookie = (u64)(rwnx_hw->roc_cookie_cnt); ++ if (roc_cfm.status) { ++ // failed to roc ++ rwnx_hw->roc_elem = NULL; ++ kfree(roc_elem); ++ rwnx_txq_offchan_deinit(rwnx_vif); ++ return -EBUSY; ++ } ++ } else { ++ /* Free the allocated element */ ++ rwnx_hw->roc_elem = NULL; ++ kfree(roc_elem); ++ rwnx_txq_offchan_deinit(rwnx_vif); ++ } ++ ++ return error; ++} ++ ++ ++static int ++rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, ++ unsigned int duration, u64 *cookie) ++{ ++ return rwnx_cfg80211_remain_on_channel_(wiphy, wdev, chan, duration, cookie, false); ++} ++ ++/** ++ * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. ++ * This allows the operation to be terminated prior to timeout based on ++ * the duration value. ++ */ ++static int rwnx_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ u64 cookie) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++#ifdef CREATE_TRACE_POINTS ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);//netdev_priv(wdev->netdev); ++#endif ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* For debug purpose (use ftrace kernel option) */ ++#ifdef CREATE_TRACE_POINTS ++ trace_cancel_roc(rwnx_vif->vif_index); ++#endif ++ /* Check if a RoC procedure is pending */ ++ if (!rwnx_hw->roc_elem) { ++ return 0; ++ } ++ ++ /* Forward the information to the FMAC */ ++ return rwnx_send_cancel_roc(rwnx_hw); ++} ++ ++#define IS_2P4GHZ(n) (n >= 2412 && n <= 2484) ++#define IS_5GHZ(n) (n >= 4000 && n <= 5895) ++#define DEFAULT_NOISE_FLOOR_2GHZ (-89) ++#define DEFAULT_NOISE_FLOOR_5GHZ (-92) ++ ++/** ++ * @dump_survey: get site survey information. ++ */ ++static int rwnx_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *netdev, ++ int idx, struct survey_info *info) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct ieee80211_supported_band *sband; ++ struct rwnx_survey_info *rwnx_survey; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (idx >= ARRAY_SIZE(rwnx_hw->survey)) ++ return -ENOENT; ++ ++ rwnx_survey = &rwnx_hw->survey[idx]; ++ ++ // Check if provided index matches with a supported 2.4GHz channel ++ sband = wiphy->bands[NL80211_BAND_2GHZ]; ++ if (sband && idx >= sband->n_channels) { ++ idx -= sband->n_channels; ++ sband = NULL; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ if (!sband) { ++ // Check if provided index matches with a supported 5GHz channel ++ sband = wiphy->bands[NL80211_BAND_5GHZ]; ++ ++ if (!sband || idx >= sband->n_channels) ++ return -ENOENT; ++ } ++ } else { ++ if (!sband || idx >= sband->n_channels) ++ return -ENOENT; ++ } ++ ++ // Fill the survey ++ info->channel = &sband->channels[idx]; ++ info->filled = rwnx_survey->filled; ++ ++ if (rwnx_survey->filled != 0) { ++ SURVEY_TIME(info) = (u64)rwnx_survey->chan_time_ms; ++ SURVEY_TIME_BUSY(info) = (u64)rwnx_survey->chan_time_busy_ms; ++ //info->noise = rwnx_survey->noise_dbm; ++ info->noise = ((IS_2P4GHZ(info->channel->center_freq)) ? DEFAULT_NOISE_FLOOR_2GHZ : ++ (IS_5GHZ(info->channel->center_freq)) ? DEFAULT_NOISE_FLOOR_5GHZ : DEFAULT_NOISE_FLOOR_5GHZ); ++ ++ // Set the survey report as not used ++ if(info->noise == 0){ ++ rwnx_survey->filled = 0; ++ }else{ ++ rwnx_survey->filled |= SURVEY_INFO_NOISE_DBM; ++ } ++ ++ } ++ ++ return 0; ++} ++ ++/** ++ * @get_channel: Get the current operating channel for the virtual interface. ++ * For monitor interfaces, it should return %NULL unless there's a single ++ * current monitoring channel. ++ */ ++static int rwnx_cfg80211_get_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ unsigned int link_id, ++#endif ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev); ++ struct rwnx_chanctx *ctxt; ++ ++ if (!rwnx_vif->up) { ++ return -ENODATA; ++ } ++ ++ if (rwnx_vif->vif_index == rwnx_hw->monitor_vif) { ++ //retrieve channel from firmware ++#if LINUX_VERSION_CODE >= KERNEL_VERSION (6, 13, 0) ++ rwnx_cfg80211_set_monitor_channel(wiphy, NULL, NULL); ++#else ++ rwnx_cfg80211_set_monitor_channel(wiphy, NULL); ++#endif ++ } ++ ++ //Check if channel context is valid ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_vif->ch_index)) { ++ return -ENODATA; ++ } ++ ++ ctxt = &rwnx_hw->chanctx_table[rwnx_vif->ch_index]; ++ *chandef = ctxt->chan_def; ++ ++ return 0; ++} ++ ++/** ++ * @mgmt_tx: Transmit a management frame. ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct cfg80211_mgmt_tx_params *params, ++ u64 *cookie) ++#else ++static int rwnx_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, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ bool no_cck, ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) ++ bool dont_wait_for_ack, ++ #endif ++ u64 *cookie) ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);//netdev_priv(wdev->netdev); ++ struct rwnx_sta *rwnx_sta; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ struct ieee80211_channel *channel = params->chan; ++ const u8 *buf = params->buf; ++ //size_t len = params->len; ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ struct ieee80211_mgmt *mgmt = (void *)buf; ++ bool ap = false; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ bool offchan = false; ++ #endif ++ ++ /* Check if provided VIF is an AP or a STA one */ ++ switch (RWNX_VIF_TYPE(rwnx_vif)) { ++ case NL80211_IFTYPE_AP_VLAN: ++ rwnx_vif = rwnx_vif->ap_vlan.master; ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ case NL80211_IFTYPE_MESH_POINT: ++ ap = true; ++ break; ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ default: ++ break; ++ } ++ ++ /* Get STA on which management frame has to be sent */ ++ rwnx_sta = rwnx_retrieve_sta(rwnx_hw, rwnx_vif, mgmt->da, ++ mgmt->frame_control, ap); ++#ifdef CREATE_TRACE_POINTS ++ trace_mgmt_tx((channel) ? channel->center_freq : 0, ++ rwnx_vif->vif_index, (rwnx_sta) ? rwnx_sta->sta_idx : 0xFF, ++ mgmt); ++#endif ++ if (ap || rwnx_sta) ++ goto send_frame; ++ ++ /* Not an AP interface sending frame to unknown STA: ++ * This is allowed for external authetication */ ++ if (rwnx_vif->sta.external_auth && ieee80211_is_auth(mgmt->frame_control)) ++ goto send_frame; ++ ++ /* Otherwise ROC is needed */ ++ if (!channel) { ++ printk("mgmt_tx fail since channel\n"); ++ return -EINVAL; ++ } ++ ++ /* Check that a RoC is already pending */ ++ if (rwnx_hw->roc_elem) { ++ /* Get VIF used for current ROC */ ++ struct rwnx_vif *rwnx_roc_vif = container_of(rwnx_hw->roc_elem->wdev, struct rwnx_vif, wdev);//netdev_priv(rwnx_hw->roc_elem->wdev->netdev); ++ ++ /* Check if RoC channel is the same than the required one */ ++ if ((rwnx_hw->roc_elem->chan->center_freq != channel->center_freq) ++ || (rwnx_vif->vif_index != rwnx_roc_vif->vif_index)) { ++ printk("mgmt rx chan invalid: %d, %d", rwnx_hw->roc_elem->chan->center_freq, channel->center_freq); ++ return -EINVAL; ++ } ++ } else { ++ u64 cookie; ++ int error; ++ ++ printk("mgmt rx remain on chan\n"); ++ ++ /* Start a ROC procedure for 30ms */ ++ error = rwnx_cfg80211_remain_on_channel_(wiphy, wdev, channel, ++ 30, &cookie, true); ++ if (error) { ++ printk("mgmt rx chan err\n"); ++ return error; ++ } ++ /* Need to keep in mind that RoC has been launched internally in order to ++ * avoid to call the cfg80211 callback once expired */ ++ //rwnx_hw->roc_elem->mgmt_roc = true; ++ } ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ offchan = true; ++ #endif ++ ++send_frame: ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, params, offchan, cookie); ++ #else ++ return rwnx_start_mgmt_xmit(rwnx_vif, rwnx_sta, channel, offchan, wait, buf, len, no_cck, dont_wait_for_ack, cookie); ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++} ++ ++/** ++ * @start_radar_detection: Start radar detection in the driver. ++ */ ++static ++int rwnx_cfg80211_start_radar_detection(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_chan_def *chandef ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) ++ , u32 cac_time_ms ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)) ++ , int link_id ++ #endif ++ ) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct apm_start_cac_cfm cfm; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) ++ rwnx_radar_start_cac(&rwnx_hw->radar, cac_time_ms, rwnx_vif); ++ #endif ++ rwnx_send_apm_start_cac_req(rwnx_hw, rwnx_vif, chandef, &cfm); ++ ++ if (cfm.status == CO_OK) { ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_link(rwnx_vif, cfm.ch_idx, chandef); ++ if (rwnx_hw->cur_chanctx == rwnx_vif->ch_index) ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_REPORT, ++ RWNX_RADAR_RIU); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } else { ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++/** ++ * @update_ft_ies: Provide updated Fast BSS Transition information to the ++ * driver. If the SME is in the driver/firmware, this information can be ++ * used in building Authentication and Reassociation Request frames. ++ */ ++static ++int rwnx_cfg80211_update_ft_ies(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_update_ft_ies_params *ftie) ++{ ++ printk("%s\n", __func__); ++ return 0; ++} ++ ++/** ++ * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. ++ */ ++static ++int rwnx_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, ++ struct net_device *dev, ++ int32_t rssi_thold, uint32_t rssi_hyst) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ ++ return rwnx_send_cfg_rssi_req(rwnx_hw, rwnx_vif->vif_index, rssi_thold, rssi_hyst); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++/** ++ * ++ * @channel_switch: initiate channel-switch procedure (with CSA). Driver is ++ * responsible for veryfing if the switch is possible. Since this is ++ * inherently tricky driver may decide to disconnect an interface later ++ * with cfg80211_stop_iface(). This doesn't mean driver can accept ++ * everything. It should do it's best to verify requests and reject them ++ * as soon as possible. ++ */ ++int rwnx_cfg80211_channel_switch (struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_csa_settings *params) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_bcn *bcn, *bcn_after; ++ struct rwnx_csa *csa; ++ u16 csa_oft[BCN_MAX_CSA_CPT]; ++ u8 *buf; ++ int i, error = 0; ++ ++ ++ if (vif->ap.csa) ++ return -EBUSY; ++ ++ if (params->n_counter_offsets_beacon > BCN_MAX_CSA_CPT) ++ return -EINVAL; ++ ++ /* Build the new beacon with CSA IE */ ++ bcn = &vif->ap.bcn; ++ buf = rwnx_build_bcn(bcn, ¶ms->beacon_csa); ++ if (!buf) ++ return -ENOMEM; ++ ++ memset(csa_oft, 0, sizeof(csa_oft)); ++ for (i = 0; i < params->n_counter_offsets_beacon; i++) { ++ csa_oft[i] = params->counter_offsets_beacon[i] + bcn->head_len + ++ bcn->tim_len; ++ } ++ ++ /* If count is set to 0 (i.e anytime after this beacon) force it to 2 */ ++ if (params->count == 0) { ++ params->count = 2; ++ for (i = 0; i < params->n_counter_offsets_beacon; i++) { ++ buf[csa_oft[i]] = 2; ++ } ++ } ++ ++ error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn->len); ++ if (error) { ++ goto end; ++ } ++ ++ /* Build the beacon to use after CSA. It will only be sent to fw once ++ CSA is over, but do it before sending the beacon as it must be ready ++ when CSA is finished. */ ++ csa = kzalloc(sizeof(struct rwnx_csa), GFP_KERNEL); ++ if (!csa) { ++ error = -ENOMEM; ++ goto end; ++ } ++ ++ bcn_after = &csa->bcn; ++ buf = rwnx_build_bcn(bcn_after, ¶ms->beacon_after); ++ if (!buf) { ++ error = -ENOMEM; ++ rwnx_del_csa(vif); ++ goto end; ++ } ++ ++ vif->ap.csa = csa; ++ csa->vif = vif; ++ csa->chandef = params->chandef; ++ ++ /* Send new Beacon. FW will extract channel and count from the beacon */ ++ error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, ++ bcn->len, bcn->head_len, bcn->tim_len, csa_oft); ++ ++ if (error) { ++ rwnx_del_csa(vif); ++ goto end; ++ } else { ++ INIT_WORK(&csa->work, rwnx_csa_finish); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 9, 0)) ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false); ++#elif LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION4 ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false, 0); ++#elif LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2 ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count, params->block_tx); ++#else ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count); ++#endif ++ ++ } ++ ++end: ++ return error; ++} ++#endif ++ ++ ++/* ++ * @tdls_mgmt: prepare TDLS action frame packets and forward them to FW ++ */ ++static int ++rwnx_cfg80211_tdls_mgmt(struct wiphy *wiphy, ++ struct net_device *dev, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ const u8 *peer, ++#else ++ u8 *peer, ++#endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0)) ++ int link_id, ++#endif ++ u8 action_code, ++ u8 dialog_token, ++ u16 status_code, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) ++ u32 peer_capability, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) ++ bool initiator, ++#endif ++ const u8 *buf, ++ size_t len) ++ ++{ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++ u32 peer_capability = 0; ++ #endif ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ bool initiator = false; ++ #endif ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int ret = 0; ++ ++ /* make sure we support TDLS */ ++ if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return -ENOTSUPP; ++ ++ /* make sure we are in station mode (and connected) */ ++ if ((RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_STATION) || ++ (!rwnx_vif->up) || (!rwnx_vif->sta.ap)) ++ return -ENOTSUPP; ++ ++ /* only one TDLS link is supported */ ++ if ((action_code == WLAN_TDLS_SETUP_REQUEST) && ++ (rwnx_vif->sta.tdls_sta) && ++ (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE)) { ++ printk("%s: only one TDLS link is supported!\n", __func__); ++ return -ENOTSUPP; ++ } ++ ++ if ((action_code == WLAN_TDLS_DISCOVERY_REQUEST) && ++ (rwnx_hw->mod_params->ps_on)) { ++ printk("%s: discovery request is not supported when " ++ "power-save is enabled!\n", __func__); ++ return -ENOTSUPP; ++ } ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_RESPONSE: ++ /* only one TDLS link is supported */ ++ if ((status_code == 0) && ++ (rwnx_vif->sta.tdls_sta) && ++ (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE)) { ++ printk("%s: only one TDLS link is supported!\n", __func__); ++ status_code = WLAN_STATUS_REQUEST_DECLINED; ++ } ++ /* fall-through */ ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ ret = rwnx_tdls_send_mgmt_packet_data(rwnx_hw, rwnx_vif, peer, action_code, ++ dialog_token, status_code, peer_capability, initiator, buf, len, 0, NULL); ++ break; ++ ++ default: ++ printk("%s: Unknown TDLS mgmt/action frame %pM\n", ++ __func__, peer); ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ if (action_code == WLAN_TDLS_SETUP_REQUEST) { ++ rwnx_vif->tdls_status = TDLS_SETUP_REQ_TX; ++ } else if (action_code == WLAN_TDLS_SETUP_RESPONSE) { ++ rwnx_vif->tdls_status = TDLS_SETUP_RSP_TX; ++ } else if ((action_code == WLAN_TDLS_SETUP_CONFIRM) && (ret == CO_OK)) { ++ rwnx_vif->tdls_status = TDLS_LINK_ACTIVE; ++ /* Set TDLS active */ ++ rwnx_vif->sta.tdls_sta->tdls.active = true; ++ } ++ ++ return ret; ++} ++ ++/* ++ * @tdls_oper: execute TDLS operation ++ */ ++static int ++rwnx_cfg80211_tdls_oper(struct wiphy *wiphy, ++ struct net_device *dev, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ const u8 *peer, ++#else ++ u8 *peer, ++#endif ++ enum nl80211_tdls_operation oper) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int error; ++ ++ if (oper != NL80211_TDLS_DISABLE_LINK) ++ return 0; ++ ++ if (!rwnx_vif->sta.tdls_sta) { ++ printk("%s: TDLS station %pM does not exist\n", __func__, peer); ++ return -ENOLINK; ++ } ++ ++ if (memcmp(rwnx_vif->sta.tdls_sta->mac_addr, peer, ETH_ALEN) == 0) { ++ /* Disable Channel Switch */ ++ if (!rwnx_send_tdls_cancel_chan_switch_req(rwnx_hw, rwnx_vif, ++ rwnx_vif->sta.tdls_sta, ++ NULL)) ++ rwnx_vif->sta.tdls_sta->tdls.chsw_en = false; ++ ++ netdev_info(dev, "Del TDLS sta %d (%pM)", ++ rwnx_vif->sta.tdls_sta->sta_idx, ++ rwnx_vif->sta.tdls_sta->mac_addr); ++ /* Ensure that we won't process PS change ind */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->sta.tdls_sta->ps.active = false; ++ rwnx_vif->sta.tdls_sta->valid = false; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_vif->sta.tdls_sta); ++ error = rwnx_send_me_sta_del(rwnx_hw, rwnx_vif->sta.tdls_sta->sta_idx, true); ++ if ((error != 0) && (error != -EPIPE)) ++ return error; ++ ++#ifdef CONFIG_RWNX_BFMER ++ // Disable Beamformer if supported ++ rwnx_bfmer_report_del(rwnx_hw, rwnx_vif->sta.tdls_sta); ++ rwnx_mu_group_sta_del(rwnx_hw, rwnx_vif->sta.tdls_sta); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ /* Set TDLS not active */ ++ rwnx_vif->sta.tdls_sta->tdls.active = false; ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.tdls_sta); ++#endif ++ // Remove TDLS station ++ rwnx_vif->tdls_status = TDLS_LINK_IDLE; ++ rwnx_vif->sta.tdls_sta = NULL; ++ } ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++/* ++ * @tdls_channel_switch: enable TDLS channel switch ++ */ ++static int ++rwnx_cfg80211_tdls_channel_switch (struct wiphy *wiphy, ++ struct net_device *dev, ++ const u8 *addr, u8 oper_class, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_sta *rwnx_sta = rwnx_vif->sta.tdls_sta; ++ struct tdls_chan_switch_cfm cfm; ++ int error; ++ ++ if ((!rwnx_sta) || (memcmp(addr, rwnx_sta->mac_addr, ETH_ALEN))) { ++ printk("%s: TDLS station %pM doesn't exist\n", __func__, addr); ++ return -ENOLINK; ++ } ++ ++ if (!rwnx_sta->tdls.chsw_allowed) { ++ printk("%s: TDLS station %pM does not support TDLS channel switch\n", __func__, addr); ++ return -ENOTSUPP; ++ } ++ ++ error = rwnx_send_tdls_chan_switch_req(rwnx_hw, rwnx_vif, rwnx_sta, ++ rwnx_sta->tdls.initiator, ++ oper_class, chandef, &cfm); ++ if (error) ++ return error; ++ ++ if (!cfm.status) { ++ rwnx_sta->tdls.chsw_en = true; ++ return 0; ++ } else { ++ printk("%s: TDLS channel switch already enabled and only one is supported\n", __func__); ++ return -EALREADY; ++ } ++} ++ ++/* ++ * @tdls_cancel_channel_switch: disable TDLS channel switch ++ */ ++static void ++rwnx_cfg80211_tdls_cancel_channel_switch (struct wiphy *wiphy, ++ struct net_device *dev, ++ const u8 *addr) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_sta *rwnx_sta = rwnx_vif->sta.tdls_sta; ++ struct tdls_cancel_chan_switch_cfm cfm; ++ ++ if (!rwnx_sta) ++ return; ++ ++ if (!rwnx_send_tdls_cancel_chan_switch_req(rwnx_hw, rwnx_vif, ++ rwnx_sta, &cfm)) ++ rwnx_sta->tdls.chsw_en = false; ++} ++#endif /* version >= 3.19 */ ++ ++/** ++ * @change_bss: Modify parameters for a given BSS (mainly for AP mode). ++ */ ++int rwnx_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, ++ struct bss_parameters *params) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ int res = -EOPNOTSUPP; ++ ++ if (((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP) || ++ (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO)) && ++ (params->ap_isolate > -1)) { ++ ++ if (params->ap_isolate) ++ rwnx_vif->ap.flags |= RWNX_AP_ISOLATE; ++ else ++ rwnx_vif->ap.flags &= ~RWNX_AP_ISOLATE; ++ ++ res = 0; ++ } ++ ++ return res; ++} ++ ++static int rwnx_fill_station_info(struct rwnx_sta *sta, struct rwnx_vif *vif, ++ struct station_info *sinfo) ++{ ++ struct rwnx_sta_stats *stats = &sta->stats; ++ struct rx_vector_1 *rx_vect1 = &stats->last_rx.rx_vect1; ++ union rwnx_rate_ctrl_info *rate_info; ++ struct mm_get_sta_info_cfm cfm; ++ ++ rwnx_send_get_sta_info_req(vif->rwnx_hw, sta->sta_idx, &cfm); ++ sinfo->tx_failed = cfm.txfailed; ++ rate_info = (union rwnx_rate_ctrl_info *)&cfm.rate_info; ++ ++ AICWFDBG(LOGDEBUG, "%s ModTx(%d):%d TxIndex:%d ModRx(%d):%d RxHTIndex:%d RxVHTIndex:%d RxHEIndex:%d RSSI:%d \r\n", __func__, ++ rate_info->bwTx, ++ rate_info->formatModTx, ++ rate_info->mcsIndexTx, ++ rx_vect1->ch_bw, ++ rx_vect1->format_mod, ++ rx_vect1->ht.mcs, ++ rx_vect1->vht.mcs, ++ rx_vect1->he.mcs, ++ (s8)cfm.rssi); ++ ++ ++ ++ switch (rate_info->formatModTx) { ++ case FORMATMOD_NON_HT: ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ sinfo->txrate.flags = 0; ++ sinfo->txrate.legacy = tx_legrates_lut_rate[rate_info->mcsIndexTx]; ++ sinfo->txrate.nss = 1; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx & 0x7; ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 3) & 0x7) + 1; ++ if (rate_info->giAndPreTypeTx) ++ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ break; ++ case FORMATMOD_VHT: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx & 0xF; ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 4) & 0x7) + 1; ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_HE_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx & 0xF; ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 4) & 0x7) + 1; ++ break; ++#else ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ sinfo->txrate.mcs = ((rate_info->mcsIndexTx & 0xF) > 9 ? 9 : (rate_info->mcsIndexTx & 0xF)); ++ sinfo->txrate.nss = ((rate_info->mcsIndexTx >> 4) & 0x7) + 1; ++ break; ++#endif ++ default: ++ return -EINVAL; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ switch (rate_info->bwTx) { ++ case PHY_CHNL_BW_20: ++ sinfo->txrate.bw = RATE_INFO_BW_20; ++ break; ++ case PHY_CHNL_BW_40: ++ sinfo->txrate.bw = RATE_INFO_BW_40; ++ break; ++ case PHY_CHNL_BW_80: ++ sinfo->txrate.bw = RATE_INFO_BW_80; ++ break; ++ case PHY_CHNL_BW_160: ++ sinfo->txrate.bw = RATE_INFO_BW_160; ++ break; ++ default: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ sinfo->txrate.bw = RATE_INFO_BW_HE_RU; ++#else ++ sinfo->txrate.bw = RATE_INFO_BW_20; ++#endif ++ break; ++ } ++#endif ++ ++ sinfo->filled |= (BIT(NL80211_STA_INFO_TX_BITRATE) | BIT(NL80211_STA_INFO_TX_FAILED)); ++ ++ sinfo->inactive_time = jiffies_to_msecs(jiffies - vif->rwnx_hw->stats.last_tx); ++ sinfo->rx_bytes = vif->net_stats.rx_bytes; ++ sinfo->tx_bytes = vif->net_stats.tx_bytes; ++ sinfo->tx_packets = vif->net_stats.tx_packets; ++ sinfo->rx_packets = vif->net_stats.rx_packets; ++ sinfo->signal = (s8)cfm.rssi; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ switch (rx_vect1->ch_bw) { ++ case PHY_CHNL_BW_20: ++ sinfo->rxrate.bw = RATE_INFO_BW_20; ++ break; ++ case PHY_CHNL_BW_40: ++ sinfo->rxrate.bw = RATE_INFO_BW_40; ++ break; ++ case PHY_CHNL_BW_80: ++ sinfo->rxrate.bw = RATE_INFO_BW_80; ++ break; ++ case PHY_CHNL_BW_160: ++ sinfo->rxrate.bw = RATE_INFO_BW_160; ++ break; ++ default: ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ sinfo->rxrate.bw = RATE_INFO_BW_HE_RU; ++ #else ++ sinfo->rxrate.bw = RATE_INFO_BW_20; ++ #endif ++ break; ++ } ++ #endif ++ ++ switch (rx_vect1->format_mod) { ++ case FORMATMOD_NON_HT: ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ sinfo->rxrate.flags = 0; ++ sinfo->rxrate.legacy = legrates_lut[rx_vect1->leg_rate].rate; ++ sinfo->rxrate.nss = 1; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS; ++ if (rx_vect1->ht.short_gi) ++ sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ sinfo->rxrate.mcs = rx_vect1->ht.mcs; ++ sinfo->rxrate.nss = rx_vect1->ht.num_extn_ss + 1; ++ break; ++ case FORMATMOD_VHT: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ if (rx_vect1->vht.short_gi) ++ sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ sinfo->rxrate.mcs = rx_vect1->vht.mcs; ++ sinfo->rxrate.nss = rx_vect1->vht.nss + 1; ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ case FORMATMOD_HE_MU: ++ sinfo->rxrate.he_ru_alloc = rx_vect1->he.ru_size; ++ __attribute__((__fallthrough__)); ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_HE_MCS; ++ sinfo->rxrate.mcs = rx_vect1->he.mcs; ++ sinfo->rxrate.he_gi = rx_vect1->he.gi_type; ++ sinfo->rxrate.he_dcm = rx_vect1->he.dcm; ++ sinfo->rxrate.nss = rx_vect1->he.nss + 1; ++ break; ++#else ++ //kernel not support he ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ if(rx_vect1->he.mcs > 9){ ++ sinfo->rxrate.mcs = 9; ++ }else{ ++ sinfo->rxrate.mcs = rx_vect1->he.mcs; ++ } ++ sinfo->rxrate.mcs = (rx_vect1->he.mcs > 9 ? 9 : rx_vect1->he.mcs); ++ sinfo->rxrate.nss = rx_vect1->he.nss + 1; ++ break; ++#endif ++ default: ++ return -EINVAL; ++ } ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ sinfo->filled |= (STATION_INFO_INACTIVE_TIME | ++ STATION_INFO_RX_BYTES64 | ++ STATION_INFO_TX_BYTES64 | ++ STATION_INFO_RX_PACKETS | ++ STATION_INFO_TX_PACKETS | ++ STATION_INFO_SIGNAL | ++ STATION_INFO_RX_BITRATE); ++#else ++ sinfo->filled |= (BIT(NL80211_STA_INFO_INACTIVE_TIME) | ++ BIT(NL80211_STA_INFO_RX_BYTES64) | ++ BIT(NL80211_STA_INFO_TX_BYTES64) | ++ BIT(NL80211_STA_INFO_RX_PACKETS) | ++ BIT(NL80211_STA_INFO_TX_PACKETS) | ++ BIT(NL80211_STA_INFO_SIGNAL) | ++ BIT(NL80211_STA_INFO_RX_BITRATE)); ++#endif ++ ++ return 0; ++} ++ ++ ++/** ++ * @get_station: get station information for the station identified by @mac ++ */ ++static int rwnx_cfg80211_get_station(struct wiphy *wiphy, ++ struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *mac, ++#else ++ const u8 *mac, ++#endif ++ struct station_info *sinfo) ++{ ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_sta *sta = NULL; ++ ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR) ++ return -EINVAL; ++ else if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_STATION) || ++ (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_CLIENT)) { ++ if (vif->sta.ap && ether_addr_equal(vif->sta.ap->mac_addr, mac)) ++ sta = vif->sta.ap; ++ } else { ++ struct rwnx_sta *sta_iter; ++ spin_lock_bh(&vif->rwnx_hw->cb_lock); ++ list_for_each_entry(sta_iter, &vif->ap.sta_list, list) { ++ if (sta_iter->valid && ether_addr_equal(sta_iter->mac_addr, mac)) { ++ sta = sta_iter; ++ break; ++ } ++ } ++ spin_unlock_bh(&vif->rwnx_hw->cb_lock); ++ } ++ ++ if (sta) ++ return rwnx_fill_station_info(sta, vif, sinfo); ++ ++ return -ENOENT; ++} ++ ++ ++/** ++ * @dump_station: dump station callback -- resume dump at index @idx ++ */ ++static int rwnx_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, ++ int idx, u8 *mac, struct station_info *sinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ //struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_sta *sta_iter, *sta = NULL; ++ //struct mesh_peer_info_cfm peer_info_cfm; ++ int i = 0; ++ ++#if 0 ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++#endif ++ ++ list_for_each_entry(sta_iter, &rwnx_vif->ap.sta_list, list) { ++ if (i < idx) { ++ i++; ++ continue; ++ } ++ ++ sta = sta_iter; ++ break; ++ } ++ ++ if (sta == NULL) ++ return -ENOENT; ++ ++ /* Copy peer MAC address */ ++ memcpy(mac, &sta->mac_addr, ETH_ALEN); ++ ++ ++#if 0 ++ /* Forward the information to the UMAC */ ++ if (rwnx_send_mesh_peer_info_req(rwnx_hw, rwnx_vif, sta->sta_idx, ++ &peer_info_cfm)) ++ return -ENOMEM; ++ ++ /* Copy peer MAC address */ ++ memcpy(mac, &sta->mac_addr, ETH_ALEN); ++ ++ /* Fill station information */ ++ sinfo->llid = peer_info_cfm.local_link_id; ++ sinfo->plid = peer_info_cfm.peer_link_id; ++ sinfo->plink_state = peer_info_cfm.link_state; ++ sinfo->local_pm = peer_info_cfm.local_ps_mode; ++ sinfo->peer_pm = peer_info_cfm.peer_ps_mode; ++ sinfo->nonpeer_pm = peer_info_cfm.non_peer_ps_mode; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ sinfo->filled = (STATION_INFO_LLID | ++ STATION_INFO_PLID | ++ STATION_INFO_PLINK_STATE | ++ STATION_INFO_LOCAL_PM | ++ STATION_INFO_PEER_PM | ++ STATION_INFO_NONPEER_PM); ++#else ++ sinfo->filled = (BIT(NL80211_STA_INFO_LLID) | ++ BIT(NL80211_STA_INFO_PLID) | ++ BIT(NL80211_STA_INFO_PLINK_STATE) | ++ BIT(NL80211_STA_INFO_LOCAL_PM) | ++ BIT(NL80211_STA_INFO_PEER_PM) | ++ BIT(NL80211_STA_INFO_NONPEER_PM)); ++#endif ++#endif ++ ++ if (sta){ ++ rwnx_fill_station_info(sta, rwnx_vif, sinfo); ++ } ++ ++ return 0; ++} ++ ++/** ++ * @add_mpath: add a fixed mesh path ++ */ ++static int rwnx_cfg80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *dst, ++ u8 *next_hop ++#else ++ const u8 *dst, ++ const u8 *next_hop ++#endif ++) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_path_update_cfm cfm; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return rwnx_send_mesh_path_update_req(rwnx_hw, rwnx_vif, dst, next_hop, &cfm); ++} ++ ++/** ++ * @del_mpath: delete a given mesh path ++ */ ++static int rwnx_cfg80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *dst ++#else ++ const u8 *dst ++#endif ++) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_path_update_cfm cfm; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return rwnx_send_mesh_path_update_req(rwnx_hw, rwnx_vif, dst, NULL, &cfm); ++} ++ ++/** ++ * @change_mpath: change a given mesh path ++ */ ++static int rwnx_cfg80211_change_mpath(struct wiphy *wiphy, struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) ++ u8 *dst, ++ u8 *next_hop ++#else ++ const u8 *dst, ++ const u8 *next_hop ++#endif ++) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_path_update_cfm cfm; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return rwnx_send_mesh_path_update_req(rwnx_hw, rwnx_vif, dst, next_hop, &cfm); ++} ++ ++/** ++ * @get_mpath: get a mesh path for the given parameters ++ */ ++static int rwnx_cfg80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, ++ u8 *dst, u8 *next_hop, struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_path *mesh_path = NULL; ++ struct rwnx_mesh_path *cur; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.mpath_list, list) { ++ /* Compare the path target address and the provided destination address */ ++ if (memcmp(dst, &cur->tgt_mac_addr, ETH_ALEN)) { ++ continue; ++ } ++ ++ mesh_path = cur; ++ break; ++ } ++ ++ if (mesh_path == NULL) ++ return -ENOENT; ++ ++ /* Copy next HOP MAC address */ ++ if (mesh_path->p_nhop_sta) ++ memcpy(next_hop, &mesh_path->p_nhop_sta->mac_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++ ++/** ++ * @dump_mpath: dump mesh path callback -- resume dump at index @idx ++ */ ++static int rwnx_cfg80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, ++ int idx, u8 *dst, u8 *next_hop, ++ struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_path *mesh_path = NULL; ++ struct rwnx_mesh_path *cur; ++ int i = 0; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.mpath_list, list) { ++ if (i < idx) { ++ i++; ++ continue; ++ } ++ ++ mesh_path = cur; ++ break; ++ } ++ ++ if (mesh_path == NULL) ++ return -ENOENT; ++ ++ /* Copy target and next hop MAC address */ ++ memcpy(dst, &mesh_path->tgt_mac_addr, ETH_ALEN); ++ if (mesh_path->p_nhop_sta) ++ memcpy(next_hop, &mesh_path->p_nhop_sta->mac_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++/** ++ * @get_mpp: get a mesh proxy path for the given parameters ++ */ ++static int rwnx_cfg80211_get_mpp(struct wiphy *wiphy, struct net_device *dev, ++ u8 *dst, u8 *mpp, struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_proxy *mesh_proxy = NULL; ++ struct rwnx_mesh_proxy *cur; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.proxy_list, list) { ++ if (cur->local) { ++ continue; ++ } ++ ++ /* Compare the path target address and the provided destination address */ ++ if (memcmp(dst, &cur->ext_sta_addr, ETH_ALEN)) { ++ continue; ++ } ++ ++ mesh_proxy = cur; ++ break; ++ } ++ ++ if (mesh_proxy == NULL) ++ return -ENOENT; ++ ++ memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++ ++/** ++ * @dump_mpp: dump mesh proxy path callback -- resume dump at index @idx ++ */ ++static int rwnx_cfg80211_dump_mpp(struct wiphy *wiphy, struct net_device *dev, ++ int idx, u8 *dst, u8 *mpp, struct mpath_info *pinfo) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_mesh_proxy *mesh_proxy = NULL; ++ struct rwnx_mesh_proxy *cur; ++ int i = 0; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ list_for_each_entry(cur, &rwnx_vif->ap.proxy_list, list) { ++ if (cur->local) { ++ continue; ++ } ++ ++ if (i < idx) { ++ i++; ++ continue; ++ } ++ ++ mesh_proxy = cur; ++ break; ++ } ++ ++ if (mesh_proxy == NULL) ++ return -ENOENT; ++ ++ /* Copy target MAC address */ ++ memcpy(dst, &mesh_proxy->ext_sta_addr, ETH_ALEN); ++ memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN); ++ ++ /* Fill path information */ ++ pinfo->filled = 0; ++ pinfo->generation = rwnx_vif->ap.generation; ++ ++ return 0; ++} ++#endif /* version >= 3.19 */ ++ ++/** ++ * @get_mesh_config: Get the current mesh configuration ++ */ ++static int rwnx_cfg80211_get_mesh_config(struct wiphy *wiphy, struct net_device *dev, ++ struct mesh_config *conf) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ return 0; ++} ++ ++/** ++ * @update_mesh_config: Update mesh parameters on a running mesh. ++ */ ++static int rwnx_cfg80211_update_mesh_config(struct wiphy *wiphy, struct net_device *dev, ++ u32 mask, const struct mesh_config *nconf) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct mesh_update_cfm cfm; ++ int status; ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ if (mask & CO_BIT(NL80211_MESHCONF_POWER_MODE - 1)) { ++ rwnx_vif->ap.next_mesh_pm = nconf->power_mode; ++ ++ if (!list_empty(&rwnx_vif->ap.sta_list)) { ++ // If there are mesh links we don't want to update the power mode ++ // It will be updated with rwnx_update_mesh_power_mode() when the ++ // ps mode of a link is updated or when a new link is added/removed ++ mask &= ~BIT(NL80211_MESHCONF_POWER_MODE - 1); ++ ++ if (!mask) ++ return 0; ++ } ++ } ++ ++ status = rwnx_send_mesh_update_req(rwnx_hw, rwnx_vif, mask, nconf, &cfm); ++ ++ if (!status && (cfm.status != 0)) ++ status = -EINVAL; ++ ++ return status; ++} ++ ++/** ++ * @join_mesh: join the mesh network with the specified parameters ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, ++ const struct mesh_config *conf, const struct mesh_setup *setup) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct mesh_start_cfm mesh_start_cfm; ++ int error = 0; ++ u8 txq_status = 0; ++ /* STA for BC/MC traffic */ ++ struct rwnx_sta *sta; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ /* Forward the information to the UMAC */ ++ error = rwnx_send_mesh_start_req(rwnx_hw, rwnx_vif, conf, setup, &mesh_start_cfm); ++ if (error) { ++ return error; ++ } ++ ++ /* Check the status */ ++ switch (mesh_start_cfm.status) { ++ case CO_OK: ++ rwnx_vif->ap.bcmc_index = mesh_start_cfm.bcmc_idx; ++ rwnx_vif->ap.flags = 0; ++ rwnx_vif->use_4addr = true; ++ rwnx_vif->user_mpm = setup->user_mpm; ++ ++ sta = &rwnx_hw->sta_table[mesh_start_cfm.bcmc_idx]; ++ sta->valid = true; ++ sta->aid = 0; ++ sta->sta_idx = mesh_start_cfm.bcmc_idx; ++ sta->ch_idx = mesh_start_cfm.ch_idx; ++ sta->vif_idx = rwnx_vif->vif_index; ++ sta->qos = true; ++ sta->acm = 0; ++ sta->ps.active = false; ++ rwnx_mu_group_sta_init(sta, NULL); ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_link(rwnx_vif, mesh_start_cfm.ch_idx, ++ (struct cfg80211_chan_def *)(&setup->chandef)); ++ if (rwnx_hw->cur_chanctx != mesh_start_cfm.ch_idx) { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ rwnx_txq_vif_init(rwnx_hw, rwnx_vif, txq_status); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ ++ /* If the AP channel is already the active, we probably skip radar ++ activation on MM_CHANNEL_SWITCH_IND (unless another vif use this ++ ctxt). In anycase retest if radar detection must be activated ++ */ ++ if (rwnx_hw->cur_chanctx == mesh_start_cfm.ch_idx) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ } ++ break; ++ ++ case CO_BUSY: ++ error = -EINPROGRESS; ++ break; ++ ++ default: ++ error = -EIO; ++ break; ++ } ++ ++ /* Print information about the operation */ ++ if (error) { ++ netdev_info(dev, "Failed to start MP (%d)", error); ++ } else { ++ netdev_info(dev, "MP started: ch=%d, bcmc_idx=%d", ++ rwnx_vif->ch_index, rwnx_vif->ap.bcmc_index); ++ } ++ ++ return error; ++} ++ ++/** ++ * @leave_mesh: leave the current mesh network ++ * (invoked with the wireless_dev mutex held) ++ */ ++static int rwnx_cfg80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct mesh_stop_cfm mesh_stop_cfm; ++ int error = 0; ++ ++ error = rwnx_send_mesh_stop_req(rwnx_hw, rwnx_vif, &mesh_stop_cfm); ++ ++ if (error == 0) { ++ /* Check the status */ ++ switch (mesh_stop_cfm.status) { ++ case CO_OK: ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_chanctx_unlink(rwnx_vif); ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ /* delete BC/MC STA */ ++ rwnx_txq_vif_deinit(rwnx_hw, rwnx_vif); ++ rwnx_del_bcn(&rwnx_vif->ap.bcn); ++ ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ ++ break; ++ ++ default: ++ error = -EIO; ++ break; ++ } ++ } ++ ++ if (error) { ++ netdev_info(dev, "Failed to stop MP"); ++ } else { ++ netdev_info(dev, "MP Stopped"); ++ } ++ ++ return 0; ++} ++ ++static struct cfg80211_ops rwnx_cfg80211_ops = { ++ .add_virtual_intf = rwnx_cfg80211_add_iface, ++ .del_virtual_intf = rwnx_cfg80211_del_iface, ++ .change_virtual_intf = rwnx_cfg80211_change_iface, ++ .start_p2p_device = rwnx_cfgp2p_start_p2p_device, ++ .stop_p2p_device = rwnx_cfgp2p_stop_p2p_device, ++ .scan = rwnx_cfg80211_scan, ++ .connect = rwnx_cfg80211_connect, ++ .disconnect = rwnx_cfg80211_disconnect, ++ .add_key = rwnx_cfg80211_add_key, ++ .get_key = rwnx_cfg80211_get_key, ++ .del_key = rwnx_cfg80211_del_key, ++ .set_default_key = rwnx_cfg80211_set_default_key, ++ .set_default_mgmt_key = rwnx_cfg80211_set_default_mgmt_key, ++ .add_station = rwnx_cfg80211_add_station, ++ .del_station = rwnx_cfg80211_del_station_compat, ++ .change_station = rwnx_cfg80211_change_station, ++ .mgmt_tx = rwnx_cfg80211_mgmt_tx, ++ .start_ap = rwnx_cfg80211_start_ap, ++ .change_beacon = rwnx_cfg80211_change_beacon, ++ .stop_ap = rwnx_cfg80211_stop_ap, ++ .set_monitor_channel = rwnx_cfg80211_set_monitor_channel, ++ .probe_client = rwnx_cfg80211_probe_client, ++// .mgmt_frame_register = rwnx_cfg80211_mgmt_frame_register, ++ .set_wiphy_params = rwnx_cfg80211_set_wiphy_params, ++ .set_txq_params = rwnx_cfg80211_set_txq_params, ++ .set_tx_power = rwnx_cfg80211_set_tx_power, ++ .get_tx_power = rwnx_cfg80211_get_tx_power, ++ .set_power_mgmt = rwnx_cfg80211_set_power_mgmt, ++ .get_station = rwnx_cfg80211_get_station, ++ .remain_on_channel = rwnx_cfg80211_remain_on_channel, ++ .cancel_remain_on_channel = rwnx_cfg80211_cancel_remain_on_channel, ++ .dump_survey = rwnx_cfg80211_dump_survey, ++ .get_channel = rwnx_cfg80211_get_channel, ++ .start_radar_detection = rwnx_cfg80211_start_radar_detection, ++ .update_ft_ies = rwnx_cfg80211_update_ft_ies, ++ .set_cqm_rssi_config = rwnx_cfg80211_set_cqm_rssi_config, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ .channel_switch = rwnx_cfg80211_channel_switch, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ .tdls_channel_switch = rwnx_cfg80211_tdls_channel_switch, ++ .tdls_cancel_channel_switch = rwnx_cfg80211_tdls_cancel_channel_switch, ++#endif ++ .tdls_mgmt = rwnx_cfg80211_tdls_mgmt, ++ .tdls_oper = rwnx_cfg80211_tdls_oper, ++ .change_bss = rwnx_cfg80211_change_bss, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ .external_auth = rwnx_cfg80211_external_auth, ++#endif ++#ifdef CONFIG_SCHED_SCAN ++ .sched_scan_start = rwnx_cfg80211_sched_scan_start, ++ .sched_scan_stop = rwnx_cfg80211_sched_scan_stop, ++#endif ++}; ++ ++ ++/********************************************************************* ++ * Init/Exit functions ++ *********************************************************************/ ++static void rwnx_wdev_unregister(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_vif *rwnx_vif, *tmp; ++ ++ rtnl_lock(); ++ list_for_each_entry_safe(rwnx_vif, tmp, &rwnx_hw->vifs, list) { ++ rwnx_cfg80211_del_iface(rwnx_hw->wiphy, &rwnx_vif->wdev); ++ } ++ rtnl_unlock(); ++} ++ ++static void rwnx_set_vers(struct rwnx_hw *rwnx_hw) ++{ ++ u32 vers = rwnx_hw->version_cfm.version_lmac; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ snprintf(rwnx_hw->wiphy->fw_version, ++ sizeof(rwnx_hw->wiphy->fw_version), "%d.%d.%d.%d", ++ (vers & (0xff << 24)) >> 24, (vers & (0xff << 16)) >> 16, ++ (vers & (0xff << 8)) >> 8, (vers & (0xff << 0)) >> 0); ++} ++ ++static void rwnx_reg_notifier(struct wiphy *wiphy, ++ struct regulatory_request *request) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ ++ // For now trust all initiator ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ if(request->dfs_region != 0) ++ rwnx_radar_set_domain(&rwnx_hw->radar, request->dfs_region); ++#else ++ rwnx_radar_set_domain(&rwnx_hw->radar, request->dfs_region); ++#endif ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC|| ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) && testmode == 0)){ ++ rwnx_send_me_chan_config_req(rwnx_hw, &request->alpha2[0]); ++ } ++} ++ ++static void rwnx_enable_mesh(struct rwnx_hw *rwnx_hw) ++{ ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ ++ if (!rwnx_mod_params.mesh) ++ return; ++ ++ rwnx_cfg80211_ops.get_station = rwnx_cfg80211_get_station; ++ rwnx_cfg80211_ops.dump_station = rwnx_cfg80211_dump_station; ++ rwnx_cfg80211_ops.add_mpath = rwnx_cfg80211_add_mpath; ++ rwnx_cfg80211_ops.del_mpath = rwnx_cfg80211_del_mpath; ++ rwnx_cfg80211_ops.change_mpath = rwnx_cfg80211_change_mpath; ++ rwnx_cfg80211_ops.get_mpath = rwnx_cfg80211_get_mpath; ++ rwnx_cfg80211_ops.dump_mpath = rwnx_cfg80211_dump_mpath; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ rwnx_cfg80211_ops.get_mpp = rwnx_cfg80211_get_mpp; ++ rwnx_cfg80211_ops.dump_mpp = rwnx_cfg80211_dump_mpp; ++#endif ++ rwnx_cfg80211_ops.get_mesh_config = rwnx_cfg80211_get_mesh_config; ++ rwnx_cfg80211_ops.update_mesh_config = rwnx_cfg80211_update_mesh_config; ++ rwnx_cfg80211_ops.join_mesh = rwnx_cfg80211_join_mesh; ++ rwnx_cfg80211_ops.leave_mesh = rwnx_cfg80211_leave_mesh; ++ ++ wiphy->flags |= (WIPHY_FLAG_MESH_AUTH | WIPHY_FLAG_IBSS_RSN); ++ wiphy->features |= NL80211_FEATURE_USERSPACE_MPM; ++ wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT); ++ ++ rwnx_limits[0].types |= BIT(NL80211_IFTYPE_MESH_POINT); ++ rwnx_limits_dfs[0].types |= BIT(NL80211_IFTYPE_MESH_POINT); ++} ++ ++extern int rwnx_init_aic(struct rwnx_hw *rwnx_hw); ++ ++#if IS_ENABLED(CONFIG_SUNXI_ADDR_MGT) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++extern int get_custom_mac_address(int fmt, char *name, char *addr); ++#else ++extern int get_wifi_custom_mac_address(char *addr_str); ++#endif ++#endif ++#if IS_ENABLED(CONFIG_PM) ++static const struct wiphy_wowlan_support aic_wowlan_support = { ++ .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT, ++}; ++#endif ++/** ++ * ++ */ ++extern int aicwf_vendor_init(struct wiphy *wiphy); ++extern txpwr_idx_conf_t nvram_txpwr_idx; ++ ++ ++int rwnx_ic_system_init(struct rwnx_hw *rwnx_hw){ ++ u32 mem_addr; ++ struct dbg_mem_read_cfm rd_mem_addr_cfm; ++ ++ mem_addr = 0x40500000; ++ ++// if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++// rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ if (rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &rd_mem_addr_cfm)){ ++ return -1; ++ } ++ ++ chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16); ++ ++ if (rwnx_send_dbg_mem_read_req(rwnx_hw, 0x00000020, &rd_mem_addr_cfm)) { ++ AICWFDBG(LOGERROR, "[0x00000020] rd fail\n"); ++ return -1; ++ } ++ chip_sub_id = (u8)(rd_mem_addr_cfm.memdata); ++ ++ AICWFDBG(LOGINFO, "FDRV chip_id=%x, chip_sub_id=%x!!\n", chip_id, chip_sub_id); ++ ++#ifdef CONFIG_OOB ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ u32 memdata_temp = 0x00000006; ++ int ret; ++ ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, 0x40504084, 4, &memdata_temp); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x40504084] write fail: %d\n", ret); ++ return -1; ++ } ++ ++ ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40504084, &rd_mem_addr_cfm); ++ if (ret) { ++ AICWFDBG(LOGERROR, "[0x40504084] rd fail\n"); ++ return -1; ++ } ++ AICWFDBG(LOGINFO, "rd [0x40504084] = %x\n", rd_mem_addr_cfm.memdata); ++ } ++#endif ++ ++ if (rwnx_platform_on(rwnx_hw, NULL)) ++ return -1; ++#if defined(CONFIG_START_FROM_BOOTROM) ++ //if (start_from_bootrom(rwnx_hw)) ++ // return -1; ++#endif ++// } ++ return 0; ++} ++ ++int rwnx_ic_rf_init(struct rwnx_hw *rwnx_hw){ ++ struct mm_set_rf_calib_cfm cfm; ++ int ret = 0; ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ if ((ret = rwnx_send_txpwr_idx_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if (testmode == 0) { ++ if ((ret = rwnx_send_rf_calib_req(rwnx_hw, &cfm))) ++ return -1; ++ } ++ ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ ++ if ((ret = aicwf_set_rf_config_8800dc(rwnx_hw, &cfm))) ++ return -1; ++ ++ ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ if ((ret = aicwf_set_rf_config_8800d80(rwnx_hw, &cfm))) ++ return -1; ++ } ++ return 0; ++} ++ ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#ifdef CONFIG_USE_CUSTOMER_MAC ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++extern int get_custom_mac_address(int fmt, char *name, char *addr); ++#else ++extern int get_wifi_custom_mac_address(char *addr_str); ++#endif ++#endif//CONFIG_USE_CUSTOMER_MAC ++#endif//CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++#include ++#endif ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++#include ++#endif ++ ++#ifdef CONFIG_USE_CUSTOMER_MAC ++int rwnx_get_custom_mac_addr(u8_l *mac_addr_efuse){ ++ int ret = 0; ++ ++#ifdef CONFIG_PLATFORM_ALLWINNER ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ ret = get_custom_mac_address(1, "wifi", mac_addr_efuse); ++#else ++ ret = get_wifi_custom_mac_address(addr_str); ++ if (ret >= 0) { ++ sscanf(addr_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &mac_addr_efuse[0], &mac_addr_efuse[1], &mac_addr_efuse[2], ++ &mac_addr_efuse[3], &mac_addr_efuse[4], &mac_addr_efuse[5]); ++ } ++#endif ++ ++#endif//CONFIG_PLATFORM_ALLWINNER ++ ++#ifdef CONFIG_PLATFORM_ROCKCHIP ++ ret = rockchip_wifi_mac_addr(mac_addr_efuse); ++#endif//CONFIG_PLATFORM_ROCKCHIP ++#ifdef CONFIG_PLATFORM_ROCKCHIP2 ++ ret = rockchip_wifi_mac_addr(mac_addr_efuse); ++#endif//CONFIG_PLATFORM_ROCKCHIP ++ ++ if(ret == 0){ ++ AICWFDBG(LOGINFO, "%s %02x:%02x:%02x:%02x:%02x:%02x", __func__, ++ mac_addr_efuse[0], mac_addr_efuse[1], mac_addr_efuse[2], ++ mac_addr_efuse[3], mac_addr_efuse[4], mac_addr_efuse[5]); ++ } ++ ++ return ret; ++} ++#endif ++ ++#ifdef CONFIG_FOR_IPCAM ++void aic_ipc_setting(struct rwnx_vif *rwnx_vif){ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ uint32_t hw_edca = 1; ++ uint32_t hw_cca = 3; ++ int32_t param[14]; ++ int32_t cca[5]= {0x10, 0, 0, 0, 0}; ++ ++ param[0] = 0xFA522; param[1] = 0xFA522; param[2] = 0xFA522; param[3] = 0xFA522; ++ param[4] = rwnx_vif->vif_index; ++ param[5] = 0x1e; param[6] = 0; param[7] = 0; param[8] =0;param[9] = 0x2;param[10] = 0x2;param[11] = 0x7;param[12] = 0;param[13] = 1; ++ rwnx_send_vendor_hwconfig_req(rwnx_hw, hw_edca, param, NULL); ++ rwnx_send_vendor_hwconfig_req(rwnx_hw, hw_cca, cca, NULL); ++} ++#endif ++ ++extern void *aicwf_prealloc_txq_alloc(size_t size); ++#ifdef CONFIG_POWER_LIMIT ++extern char default_ccode[]; ++#endif ++int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data) ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct rwnx_conf_file init_conf; ++ int ret = 0; ++ struct wiphy *wiphy; ++ struct rwnx_vif *vif; ++ int i; ++ u8 dflt_mac[ETH_ALEN] = { 0x88, 0x00, 0x33, 0x77, 0x10, 0x99}; ++ u8 addr_str[20]; ++ //struct mm_set_rf_calib_cfm cfm; ++ struct mm_get_fw_version_cfm fw_version; ++ u8_l mac_addr_efuse[ETH_ALEN]; ++ struct aicbsp_feature_t feature; ++ struct mm_set_stack_start_cfm set_start_cfm; ++#ifdef CONFIG_TEMP_COMP ++ struct mm_set_vendor_swconfig_cfm swconfig_cfm; ++#endif ++ char fw_path[200]; ++ (void)addr_str; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ memset(fw_path, 0, 200); ++ aicbsp_get_feature(&feature, fw_path); ++ ++ get_random_bytes(&dflt_mac[4], 2); ++#ifdef CONFIG_POWER_LIMIT ++ memcpy(country_code, default_ccode, 4); ++#endif ++ ++ /* create a new wiphy for use with cfg80211 */ ++ AICWFDBG(LOGINFO, "%s sizeof(struct rwnx_hw):%d \r\n", __func__, (int)sizeof(struct rwnx_hw)); ++ wiphy = wiphy_new(&rwnx_cfg80211_ops, sizeof(struct rwnx_hw)); ++ ++ if (!wiphy) { ++ dev_err(rwnx_platform_get_dev(rwnx_plat), "Failed to create new wiphy\n"); ++ ret = -ENOMEM; ++ goto err_out; ++ } ++ ++ rwnx_hw = wiphy_priv(wiphy); ++ rwnx_hw->wiphy = wiphy; ++ rwnx_hw->plat = rwnx_plat; ++ rwnx_hw->dev = rwnx_platform_get_dev(rwnx_plat); ++#ifdef AICWF_SDIO_SUPPORT ++ rwnx_hw->sdiodev = rwnx_plat->sdiodev; ++ rwnx_plat->sdiodev->rwnx_hw = rwnx_hw; ++ rwnx_hw->cmd_mgr = &rwnx_plat->sdiodev->cmd_mgr; ++#else ++ rwnx_hw->usbdev = rwnx_plat->usbdev; ++ rwnx_plat->usbdev->rwnx_hw = rwnx_hw; ++ rwnx_hw->cmd_mgr = &rwnx_plat->usbdev->cmd_mgr; ++#endif ++ rwnx_hw->mod_params = &rwnx_mod_params; ++ rwnx_hw->tcp_pacing_shift = 7; ++ ++#ifdef CONFIG_SCHED_SCAN ++ rwnx_hw->is_sched_scan = false; ++#endif//CONFIG_SCHED_SCAN ++ ++ aicwf_wakeup_lock_init(rwnx_hw); ++ rwnx_init_aic(rwnx_hw); ++ /* set device pointer for wiphy */ ++ set_wiphy_dev(wiphy, rwnx_hw->dev); ++ ++ /* Create cache to allocate sw_txhdr */ ++ rwnx_hw->sw_txhdr_cache = KMEM_CACHE(rwnx_sw_txhdr, 0); ++ if (!rwnx_hw->sw_txhdr_cache) { ++ wiphy_err(wiphy, "Cannot allocate cache for sw TX header\n"); ++ ret = -ENOMEM; ++ goto err_cache; ++ } ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ tcp_ack_init(rwnx_hw); ++#endif ++ ++#if 0 ++ ret = rwnx_parse_configfile(rwnx_hw, RWNX_CONFIG_FW_NAME, &init_conf); ++ if (ret) { ++ wiphy_err(wiphy, "rwnx_parse_configfile failed\n"); ++ goto err_config; ++ } ++#else ++ memcpy(init_conf.mac_addr, dflt_mac, ETH_ALEN); ++#endif ++ ++ rwnx_hw->vif_started = 0; ++ rwnx_hw->monitor_vif = RWNX_INVALID_VIF; ++ rwnx_hw->adding_sta = false; ++ ++ rwnx_hw->scan_ie.addr = NULL; ++ ++ for (i = 0; i < NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; i++) ++ rwnx_hw->avail_idx_map |= BIT(i); ++ ++ rwnx_hwq_init(rwnx_hw); ++ ++#ifdef CONFIG_PREALLOC_TXQ ++ rwnx_hw->txq = (struct rwnx_txq*)aicwf_prealloc_txq_alloc(sizeof(struct rwnx_txq)*NX_NB_TXQ); ++#endif ++ ++ for (i = 0; i < NX_NB_TXQ; i++) { ++ rwnx_hw->txq[i].idx = TXQ_INACTIVE; ++ } ++ ++ rwnx_mu_group_init(rwnx_hw); ++ ++ /* Initialize RoC element pointer to NULL, indicate that RoC can be started */ ++ rwnx_hw->roc_elem = NULL; ++ /* Cookie can not be 0 */ ++ rwnx_hw->roc_cookie_cnt = 1; ++ ++ INIT_LIST_HEAD(&rwnx_hw->vifs); ++ INIT_LIST_HEAD(&rwnx_hw->defrag_list); ++ spin_lock_init(&rwnx_hw->defrag_lock); ++ mutex_init(&rwnx_hw->mutex); ++ mutex_init(&rwnx_hw->dbgdump_elem.mutex); ++ spin_lock_init(&rwnx_hw->tx_lock); ++ spin_lock_init(&rwnx_hw->cb_lock); ++ ++ INIT_WORK(&rwnx_hw->apmStalossWork, apm_staloss_work_process); ++ rwnx_hw->apmStaloss_wq = create_singlethread_workqueue("apmStaloss_wq"); ++ if (!rwnx_hw->apmStaloss_wq) { ++ txrx_err("insufficient memory to create apmStaloss workqueue.\n"); ++ goto err_cache; ++ } ++ ++ wiphy->mgmt_stypes = rwnx_default_mgmt_stypes; ++ rwnx_hw->fwlog_en = feature.fwlog_en; ++ ++ ++ //init ic system ++ if((ret = rwnx_ic_system_init(rwnx_hw))){ ++ goto err_lmac_reqs; ++ } ++ ++ //ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, feature.hwinfo < 0, feature.hwinfo, 0, &set_start_cfm); ++#ifdef USE_5G ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801) { ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, CO_BIT(5), 0, &set_start_cfm); ++ } ++#else ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801) { ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, 0, 0, &set_start_cfm); ++ } ++#endif ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, 0, 0, &set_start_cfm); ++ set_start_cfm.is_5g_support = false; ++ } else { ++ ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, 0, CO_BIT(5), 0, &set_start_cfm); ++ } ++ ++ if (ret) ++ goto err_lmac_reqs; ++ ++ AICWFDBG(LOGINFO, "is 5g support = %d, vendor_info = 0x%02X\n", set_start_cfm.is_5g_support, set_start_cfm.vendor_info); ++ rwnx_hw->band_5g_support = set_start_cfm.is_5g_support; ++ rwnx_hw->vendor_info = (feature.hwinfo < 0) ? set_start_cfm.vendor_info : feature.hwinfo; ++ ++ ret = rwnx_send_get_fw_version_req(rwnx_hw, &fw_version); ++ memcpy(wiphy->fw_version, fw_version.fw_version, fw_version.fw_version_len>32? 32 : fw_version.fw_version_len); ++ AICWFDBG(LOGINFO, "Firmware Version: %s\r\n", fw_version.fw_version); ++ ++ wiphy->bands[NL80211_BAND_2GHZ] = &rwnx_band_2GHz; ++ if (rwnx_hw->band_5g_support) ++ wiphy->bands[NL80211_BAND_5GHZ] = &rwnx_band_5GHz; ++ ++ wiphy->interface_modes = ++ BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_AP_VLAN) | ++ BIT(NL80211_IFTYPE_P2P_CLIENT) | ++ BIT(NL80211_IFTYPE_P2P_GO) | ++#ifndef CONFIG_USE_P2P0 ++ BIT(NL80211_IFTYPE_P2P_DEVICE) | ++#endif ++ BIT(NL80211_IFTYPE_MONITOR); ++ ++#if IS_ENABLED(CONFIG_PM) ++ /* Set WoWLAN flags */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) ++ wiphy->wowlan = &aic_wowlan_support; ++#else ++ wiphy->wowlan.flags = aic_wowlan_support.flags; ++#endif ++#endif ++ wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) ++ WIPHY_FLAG_HAS_CHANNEL_SWITCH | ++ #endif ++ WIPHY_FLAG_4ADDR_STATION | ++ WIPHY_FLAG_4ADDR_AP; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ wiphy->max_num_csa_counters = BCN_MAX_CSA_CPT; ++ #endif ++ ++ wiphy->max_remain_on_channel_duration = rwnx_hw->mod_params->roc_dur_max; ++ ++ wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN | ++ NL80211_FEATURE_SK_TX_STATUS | ++ NL80211_FEATURE_VIF_TXPOWER | ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) ++ NL80211_FEATURE_ACTIVE_MONITOR | ++ #endif ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | ++ #endif ++ 0; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ wiphy->features |= NL80211_FEATURE_SAE; ++#endif ++ ++ if (rwnx_mod_params.tdls) ++ /* TDLS support */ ++ wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH; ++ ++ wiphy->iface_combinations = rwnx_combinations; ++ /* -1 not to include combination with radar detection, will be re-added in ++ rwnx_handle_dynparams if supported */ ++ wiphy->n_iface_combinations = ARRAY_SIZE(rwnx_combinations) - 1; ++ wiphy->reg_notifier = rwnx_reg_notifier; ++ ++ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; ++ ++ rwnx_enable_wapi(rwnx_hw); ++ ++ wiphy->cipher_suites = cipher_suites; ++ wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites) - NB_RESERVED_CIPHER; ++ ++ rwnx_hw->ext_capa[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING; ++ rwnx_hw->ext_capa[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF; ++ ++ wiphy->extended_capabilities = rwnx_hw->ext_capa; ++ wiphy->extended_capabilities_mask = rwnx_hw->ext_capa; ++ wiphy->extended_capabilities_len = ARRAY_SIZE(rwnx_hw->ext_capa); ++ ++#ifdef CONFIG_SCHED_SCAN ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ wiphy->max_sched_scan_reqs = 1; ++#endif ++ wiphy->max_sched_scan_ssids = SCAN_SSID_MAX;//16; ++ wiphy->max_match_sets = SCAN_SSID_MAX;//16; ++ wiphy->max_sched_scan_ie_len = 2048; ++#endif//CONFIG_SCHED_SCAN ++ ++ tasklet_init(&rwnx_hw->task, rwnx_task, (unsigned long)rwnx_hw); ++ ++ //init ic rf ++ if((ret = rwnx_ic_rf_init(rwnx_hw))){ ++ goto err_lmac_reqs; ++ } ++ ++ ++#ifdef CONFIG_USE_CUSTOMER_MAC ++ ret = rwnx_get_custom_mac_addr(mac_addr_efuse); ++ if (ret){ ++ AICWFDBG(LOGERROR, "%s read mac fail use default mac\r\n", __func__); ++ memcpy(init_conf.mac_addr, dflt_mac, ETH_ALEN); ++ } ++#else ++ ret = rwnx_send_get_macaddr_req(rwnx_hw, (struct mm_get_mac_addr_cfm *)mac_addr_efuse); ++ if (ret) ++ goto err_lmac_reqs; ++#endif ++ ++ if (mac_addr_efuse[0] | mac_addr_efuse[1] | mac_addr_efuse[2] | mac_addr_efuse[3]) { ++ memcpy(init_conf.mac_addr, mac_addr_efuse, ETH_ALEN); ++ }else{ ++ memcpy(init_conf.mac_addr, dflt_mac, ETH_ALEN); ++ } ++ ++ ++ AICWFDBG(LOGINFO, "get macaddr: %02x:%02x:%02x:%02x:%02x:%02x\r\n", ++ mac_addr_efuse[0], mac_addr_efuse[1], mac_addr_efuse[2], ++ mac_addr_efuse[3], mac_addr_efuse[4], mac_addr_efuse[5]); ++ memcpy(wiphy->perm_addr, init_conf.mac_addr, ETH_ALEN); ++ ++ /* Reset FW */ ++ ret = rwnx_send_reset(rwnx_hw); ++ if (ret) ++ goto err_lmac_reqs; ++ ++#ifdef CONFIG_TEMP_COMP ++ rwnx_send_set_temp_comp_req(rwnx_hw, &swconfig_cfm); ++#endif ++ ++ ret = rwnx_send_version_req(rwnx_hw, &rwnx_hw->version_cfm); ++ if (ret) ++ goto err_lmac_reqs; ++ rwnx_set_vers(rwnx_hw); ++ ++ ret = rwnx_handle_dynparams(rwnx_hw, rwnx_hw->wiphy); ++ if (ret) ++ goto err_lmac_reqs; ++ ++ rwnx_enable_mesh(rwnx_hw); ++ rwnx_radar_detection_init(&rwnx_hw->radar); ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ rwnx_radar_set_domain(&rwnx_hw->radar, NL80211_DFS_FCC); ++#endif ++ ++ /* Set parameters to firmware */ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC|| ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) && testmode == 0)){ ++ rwnx_send_me_config_req(rwnx_hw); ++ } ++ ++ /* Only monitor mode supported when custom channels are enabled */ ++ if (rwnx_mod_params.custchan) { ++ rwnx_limits[0].types = BIT(NL80211_IFTYPE_MONITOR); ++ rwnx_limits_dfs[0].types = BIT(NL80211_IFTYPE_MONITOR); ++ } ++ ++ aicwf_vendor_init(wiphy); ++ ++ ret = wiphy_register(wiphy); ++ if (ret) { ++ wiphy_err(wiphy, "Could not register wiphy device\n"); ++ goto err_register_wiphy; ++ } ++ ++ /* Update regulatory (if needed) and set channel parameters to firmware ++ (must be done after WiPHY registration) */ ++ rwnx_custregd(rwnx_hw, wiphy); ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || ++ ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) && testmode == 0)) { ++ rwnx_send_me_chan_config_req(rwnx_hw, "00"); ++ } ++ ++ *platform_data = rwnx_hw; ++ ++#ifdef CONFIG_DEBUG_FS ++ ret = rwnx_dbgfs_register(rwnx_hw, "rwnx"); ++ if (ret) { ++ wiphy_err(wiphy, "Failed to register debugfs entries"); ++ goto err_debugfs; ++ } ++#endif ++ rtnl_lock(); ++ ++ /* Add an initial station interface */ ++ vif = rwnx_interface_add(rwnx_hw, "wlan%d", NET_NAME_UNKNOWN, ++ NL80211_IFTYPE_STATION, NULL); ++ ++#ifdef CONFIG_RWNX_MON_DATA ++ /* Add an initial station interface */ ++ vif = rwnx_interface_add(rwnx_hw, "wlan%d", 1, ++ NL80211_IFTYPE_MONITOR, NULL); ++#endif ++ ++ rtnl_unlock(); ++ ++ if (!vif) { ++ wiphy_err(wiphy, "Failed to instantiate a network device\n"); ++ ret = -ENOMEM; ++ goto err_add_interface; ++ } ++ ++ //wiphy_info(wiphy, "New interface create %s", vif->ndev->name); ++ AICWFDBG(LOGINFO, "New interface create %s \r\n", vif->ndev->name); ++ ++#ifdef CONFIG_SDIO_BT ++#if CONFIG_BLUEDROID ++ btchr_init(); ++ hdev_init(); ++#else ++ btsdio_init(); ++#endif ++#endif ++ ++#ifdef CONFIG_USE_P2P0 ++ ++ rtnl_lock(); ++ /* Add an initial p2p0 interface */ ++ vif = rwnx_interface_add(rwnx_hw, "p2p%d", NET_NAME_UNKNOWN, ++ NL80211_IFTYPE_STATION, NULL); ++ vif->is_p2p_vif = 1; ++ rtnl_unlock(); ++ ++ if (!vif) { ++ wiphy_err(wiphy, "Failed to instantiate a network device\n"); ++ ret = -ENOMEM; ++ goto err_add_interface; ++ } ++ ++ //wiphy_info(wiphy, "New interface create %s", vif->ndev->name); ++ AICWFDBG(LOGINFO, "New interface create %s \r\n", vif->ndev->name); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ init_timer(&rwnx_hw->p2p_alive_timer); ++ rwnx_hw->p2p_alive_timer.data = (unsigned long)vif; ++ rwnx_hw->p2p_alive_timer.function = aicwf_p2p_alive_timeout; ++#else ++ timer_setup(&rwnx_hw->p2p_alive_timer, aicwf_p2p_alive_timeout, 0); ++#endif ++ rwnx_hw->is_p2p_alive = 0; ++ rwnx_hw->is_p2p_connected = 0; ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ ++#ifdef CONFIG_FOR_IPCAM ++ if(!testmode && !adap_test) { ++ aic_ipc_setting(vif); ++ } ++#endif ++ ++ return 0; ++ ++err_add_interface: ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister(rwnx_hw); ++err_debugfs: ++#endif ++ wiphy_unregister(rwnx_hw->wiphy); ++err_register_wiphy: ++err_lmac_reqs: ++ printk("err_lmac_reqs\n"); ++ rwnx_platform_off(rwnx_hw, NULL); ++//err_platon: ++//err_config: ++ kmem_cache_destroy(rwnx_hw->sw_txhdr_cache); ++err_cache: ++ aicwf_wakeup_lock_deinit(rwnx_hw); ++ wiphy_free(wiphy); ++err_out: ++ return ret; ++} ++ ++/** ++ * ++ */ ++void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_stack_start_cfm set_start_cfm; ++ struct defrag_ctrl_info *defrag_ctrl = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef AICWF_USB_SUPPORT ++ if (rwnx_hw->usbdev->bus_if->state != BUS_DOWN_ST) ++#else ++ if (rwnx_hw->sdiodev->bus_if->state != BUS_DOWN_ST) ++#endif ++ rwnx_send_set_stack_start_req(rwnx_hw, 0, 0, 0, 0, &set_start_cfm); ++ ++ rwnx_hw->fwlog_en = 0; ++ spin_lock_bh(&rwnx_hw->defrag_lock); ++ if (!list_empty(&rwnx_hw->defrag_list)) { ++ list_for_each_entry(defrag_ctrl, &rwnx_hw->defrag_list, list) { ++ list_del_init(&defrag_ctrl->list); ++ if (timer_pending(&defrag_ctrl->defrag_timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ timer_delete_sync(&defrag_ctrl->defrag_timer); ++#else ++ del_timer_sync(&defrag_ctrl->defrag_timer); ++#endif ++ dev_kfree_skb(defrag_ctrl->skb); ++ kfree(defrag_ctrl); ++ } ++ } ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister(rwnx_hw); ++#endif ++ ++#ifdef CONFIG_SDIO_BT ++#if CONFIG_BLUEDROID ++ btchr_exit(); ++ hdev_exit(); ++#else ++ btsdio_remove(); ++#endif ++#endif ++ ++ flush_workqueue(rwnx_hw->apmStaloss_wq); ++ destroy_workqueue(rwnx_hw->apmStaloss_wq); ++ ++ rwnx_wdev_unregister(rwnx_hw); ++ wiphy_unregister(rwnx_hw->wiphy); ++ rwnx_radar_detection_deinit(&rwnx_hw->radar); ++ rwnx_platform_off(rwnx_hw, NULL); ++ kmem_cache_destroy(rwnx_hw->sw_txhdr_cache); ++#ifdef CONFIG_FILTER_TCP_ACK ++ tcp_ack_deinit(rwnx_hw); ++#endif ++ aicwf_wakeup_lock_deinit(rwnx_hw); ++ wiphy_free(rwnx_hw->wiphy); ++} ++ ++static void aicsmac_driver_register(void) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_register(); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ aicwf_usb_register(); ++#endif ++#ifdef AICWF_PCIE_SUPPORT ++ aicwf_pcie_register(); ++#endif ++} ++ ++//static DECLARE_WORK(aicsmac_driver_work, aicsmac_driver_register); ++ ++struct completion hostif_register_done; ++static int rwnx_driver_err = -1; ++ ++#define REGISTRATION_TIMEOUT 9000 ++ ++void aicwf_hostif_ready(void) ++{ ++ rwnx_driver_err = 0; ++ g_rwnx_plat->enabled = true; ++ complete(&hostif_register_done); ++} ++ ++void aicwf_hostif_fail(void) ++{ ++ rwnx_driver_err = 1; ++ complete(&hostif_register_done); ++} ++ ++static int __init rwnx_mod_init(void) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ rwnx_print_version(); ++ rwnx_init_cmd_array(); ++ ++//#ifndef CONFIG_PLATFORM_ROCKCHIP ++ if (aicbsp_set_subsys(AIC_WIFI, AIC_PWR_ON) < 0) { ++ AICWFDBG(LOGERROR, "%s, set power on fail!\n", __func__); ++ if(!aicbsp_get_load_fw_in_fdrv()){ ++ return -ENODEV; ++ } ++ } ++//#endif ++ ++ init_completion(&hostif_register_done); ++ aicsmac_driver_register(); ++ ++ if ((wait_for_completion_timeout(&hostif_register_done, msecs_to_jiffies(REGISTRATION_TIMEOUT)) == 0) || rwnx_driver_err) { ++ AICWFDBG(LOGERROR, "register_driver timeout or error\n"); ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_exit(); ++#endif /* AICWF_SDIO_SUPPORT */ ++#ifdef AICWF_USB_SUPPORT ++ aicwf_usb_exit(); ++#endif /*AICWF_USB_SUPPORT */ ++ aicbsp_set_subsys(AIC_WIFI, AIC_PWR_OFF); ++ return -ENODEV; ++ } ++ ++#ifdef AICWF_PCIE_SUPPORT ++ return rwnx_platform_register_drv(); ++#else ++ return 0; ++#endif ++} ++ ++/** ++ * ++ */ ++static void __exit rwnx_mod_exit(void) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef AICWF_PCIE_SUPPORT ++ rwnx_platform_unregister_drv(); ++#endif ++ ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_exit(); ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++ aicwf_usb_exit(); ++#endif ++//#ifndef CONFIG_PLATFORM_ROCKCHIP ++ aicbsp_set_subsys(AIC_WIFI, AIC_PWR_OFF); ++//#endif ++ rwnx_free_cmd_array(); ++ ++} ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) ++MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver"); ++#else ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#endif ++#endif ++ ++module_init(rwnx_mod_init); ++module_exit(rwnx_mod_exit); ++ ++MODULE_FIRMWARE(RWNX_CONFIG_FW_NAME); ++ ++MODULE_DESCRIPTION(RW_DRV_DESCRIPTION); ++MODULE_VERSION(RWNX_VERS_MOD); ++MODULE_AUTHOR(RW_DRV_COPYRIGHT " " RW_DRV_AUTHOR); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h +new file mode 100644 +index 000000000000..dfa89034706a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h +@@ -0,0 +1,26 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_main.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_MAIN_H_ ++#define _RWNX_MAIN_H_ ++ ++#include "rwnx_defs.h" ++ ++int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data); ++void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw); ++extern int testmode; ++extern u8 chip_sub_id; ++extern u8 chip_mcu_id; ++extern u8 chip_id; ++ ++#define CHIP_ID_H_MASK 0xC0 ++#define IS_CHIP_ID_H() ((chip_id & CHIP_ID_H_MASK) == CHIP_ID_H_MASK) ++ ++#endif /* _RWNX_MAIN_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c +new file mode 100644 +index 000000000000..8773db61a664 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c +@@ -0,0 +1,42 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_mesh.c ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++/** ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++ ++#include "rwnx_mesh.h" ++ ++/** ++ * FUNCTION DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local) ++{ ++ struct rwnx_mesh_proxy *p_mesh_proxy = NULL; ++ struct rwnx_mesh_proxy *p_cur_proxy; ++ ++ /* Look for proxied devices with provided address */ ++ list_for_each_entry(p_cur_proxy, &p_rwnx_vif->ap.proxy_list, list) { ++ if (p_cur_proxy->local != local) { ++ continue; ++ } ++ ++ if (!memcmp(&p_cur_proxy->ext_sta_addr, p_sta_addr, ETH_ALEN)) { ++ p_mesh_proxy = p_cur_proxy; ++ break; ++ } ++ } ++ ++ /* Return the found information */ ++ return p_mesh_proxy; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h +new file mode 100644 +index 000000000000..db8950f160de +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h +@@ -0,0 +1,45 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_mesh.h ++ * ++ * @brief VHT Beamformer function declarations ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_MESH_H_ ++#define _RWNX_MESH_H_ ++ ++/** ++ * INCLUDE FILES ++ **************************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++ ++/** ++ * DEFINES ++ **************************************************************************************** ++ */ ++ ++/** ++ * TYPE DEFINITIONS ++ **************************************************************************************** ++ */ ++ ++/** ++ * FUNCTION DECLARATIONS ++ **************************************************************************************** ++ */ ++ ++/** ++ **************************************************************************************** ++ * @brief TODO [LT] ++ **************************************************************************************** ++ */ ++struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local); ++ ++#endif /* _RWNX_MESH_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c +new file mode 100644 +index 000000000000..965454201a8a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c +@@ -0,0 +1,1798 @@ ++/** ++****************************************************************************** ++* ++* @file rwnx_mod_params.c ++* ++* @brief Set configuration according to modules parameters ++* ++* Copyright (C) RivieraWaves 2012-2019 ++* ++****************************************************************************** ++*/ ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_tx.h" ++#include "hal_desc.h" ++#include "rwnx_cfgfile.h" ++#include "rwnx_dini.h" ++#include "reg_access.h" ++#include "rwnx_compat.h" ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define COMMON_PARAM(name, default_softmac, default_fullmac) \ ++ .name = default_fullmac, ++#define SOFTMAC_PARAM(name, default) ++#define FULLMAC_PARAM(name, default) .name = default, ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++struct rwnx_mod_params rwnx_mod_params = { ++ /* common parameters */ ++ COMMON_PARAM(ht_on, true, true) ++ COMMON_PARAM(vht_on, true, true) ++ COMMON_PARAM(he_on, true, true) ++ COMMON_PARAM(mcs_map, IEEE80211_VHT_MCS_SUPPORT_0_9, IEEE80211_VHT_MCS_SUPPORT_0_9) ++ COMMON_PARAM(he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_11, IEEE80211_HE_MCS_SUPPORT_0_11) ++ COMMON_PARAM(he_ul_on, false, false) ++ COMMON_PARAM(ldpc_on, true, true) ++ COMMON_PARAM(stbc_on, true, true) ++ COMMON_PARAM(gf_rx_on, false, false) ++ COMMON_PARAM(phy_cfg, 2, 2) ++ COMMON_PARAM(uapsd_timeout, 300, 300) ++ COMMON_PARAM(ap_uapsd_on, true, true) ++ COMMON_PARAM(sgi, true, true) ++ COMMON_PARAM(sgi80, false, false) ++ COMMON_PARAM(use_2040, 1, 1) ++ COMMON_PARAM(nss, 2, 2) ++ COMMON_PARAM(amsdu_rx_max, 1, 1) ++ COMMON_PARAM(bfmee, true, true) ++ COMMON_PARAM(bfmer, false, false) ++ COMMON_PARAM(mesh, true, true) ++ COMMON_PARAM(murx, true, true) ++ COMMON_PARAM(mutx, true, true) ++ COMMON_PARAM(mutx_on, true, true) ++ COMMON_PARAM(use_80, false, false) ++ COMMON_PARAM(custregd, true, true) ++ COMMON_PARAM(custchan, false, false) ++ COMMON_PARAM(roc_dur_max, 500, 500) ++ COMMON_PARAM(listen_itv, 0, 0) ++ COMMON_PARAM(listen_bcmc, true, true) ++ COMMON_PARAM(lp_clk_ppm, 20, 20) ++ COMMON_PARAM(ps_on, true, true) ++ COMMON_PARAM(tx_lft, RWNX_TX_LIFETIME_MS, RWNX_TX_LIFETIME_MS) ++ COMMON_PARAM(amsdu_maxnb, NX_TX_PAYLOAD_MAX, NX_TX_PAYLOAD_MAX) ++ // By default, only enable UAPSD for Voice queue (see IEEE80211_DEFAULT_UAPSD_QUEUE comment) ++ COMMON_PARAM(uapsd_queues, IEEE80211_WMM_IE_STA_QOSINFO_AC_VO, IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) ++ COMMON_PARAM(tdls, false, false) ++ COMMON_PARAM(uf, false, false) ++ COMMON_PARAM(auto_reply, false, false) ++ COMMON_PARAM(ftl, "", "") ++ COMMON_PARAM(dpsm, false, false) ++ ++ /* SOFTMAC only parameters */ ++ SOFTMAC_PARAM(mfp_on, false) ++ SOFTMAC_PARAM(gf_on, false) ++ SOFTMAC_PARAM(bwsig_on, true) ++ SOFTMAC_PARAM(dynbw_on, true) ++ SOFTMAC_PARAM(agg_tx, true) ++ SOFTMAC_PARAM(amsdu_force, 2) ++ SOFTMAC_PARAM(rc_probes_on, false) ++ SOFTMAC_PARAM(cmon, true) ++ SOFTMAC_PARAM(hwscan, true) ++ SOFTMAC_PARAM(autobcn, true) ++ SOFTMAC_PARAM(dpsm, true) ++ ++ /* FULLMAC only parameters */ ++ FULLMAC_PARAM(ant_div, true) ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/* FULLMAC specific parameters*/ ++module_param_named(ant_div, rwnx_mod_params.ant_div, bool, S_IRUGO); ++MODULE_PARM_DESC(ant_div, "Enable Antenna Diversity (Default: 1)"); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++module_param_named(ht_on, rwnx_mod_params.ht_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ht_on, "Enable HT (Default: 1)"); ++ ++module_param_named(vht_on, rwnx_mod_params.vht_on, bool, S_IRUGO); ++MODULE_PARM_DESC(vht_on, "Enable VHT (Default: 1)"); ++ ++module_param_named(he_on, rwnx_mod_params.he_on, bool, S_IRUGO); ++MODULE_PARM_DESC(he_on, "Enable HE (Default: 1)"); ++ ++module_param_named(mcs_map, rwnx_mod_params.mcs_map, int, S_IRUGO); ++MODULE_PARM_DESC(mcs_map, "VHT MCS map value 0: MCS0_7, 1: MCS0_8, 2: MCS0_9" ++ " (Default: 2)"); ++ ++module_param_named(he_mcs_map, rwnx_mod_params.he_mcs_map, int, S_IRUGO); ++MODULE_PARM_DESC(he_mcs_map, "HE MCS map value 0: MCS0_7, 1: MCS0_9, 2: MCS0_11" ++ " (Default: 2)"); ++ ++module_param_named(he_ul_on, rwnx_mod_params.he_ul_on, bool, S_IRUGO); ++MODULE_PARM_DESC(he_ul_on, "Enable HE OFDMA UL (Default: 0)"); ++ ++module_param_named(amsdu_maxnb, rwnx_mod_params.amsdu_maxnb, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(amsdu_maxnb, "Maximum number of MSDUs inside an A-MSDU in TX: (Default: NX_TX_PAYLOAD_MAX)"); ++ ++module_param_named(ps_on, rwnx_mod_params.ps_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ps_on, "Enable PowerSaving (Default: 1-Enabled)"); ++ ++module_param_named(tx_lft, rwnx_mod_params.tx_lft, int, 0644); ++MODULE_PARM_DESC(tx_lft, "Tx lifetime (ms) - setting it to 0 disables retries " ++ "(Default: "__stringify(RWNX_TX_LIFETIME_MS)")"); ++ ++module_param_named(ldpc_on, rwnx_mod_params.ldpc_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ldpc_on, "Enable LDPC (Default: 1)"); ++ ++module_param_named(stbc_on, rwnx_mod_params.stbc_on, bool, S_IRUGO); ++MODULE_PARM_DESC(stbc_on, "Enable STBC in RX (Default: 1)"); ++ ++module_param_named(gf_rx_on, rwnx_mod_params.gf_rx_on, bool, S_IRUGO); ++MODULE_PARM_DESC(gf_rx_on, "Enable HT greenfield in reception (Default: 1)"); ++ ++module_param_named(phycfg, rwnx_mod_params.phy_cfg, int, S_IRUGO); ++MODULE_PARM_DESC(phycfg, ++ "0 <= phycfg <= 5 : RF Channel Conf (Default: 2(C0-A1-B2))"); ++ ++module_param_named(uapsd_timeout, rwnx_mod_params.uapsd_timeout, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(uapsd_timeout, ++ "UAPSD Timer timeout, in ms (Default: 300). If 0, UAPSD is disabled"); ++ ++module_param_named(uapsd_queues, rwnx_mod_params.uapsd_queues, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(uapsd_queues, "UAPSD Queues, integer value, must be seen as a bitfield\n" ++ " Bit 0 = VO\n" ++ " Bit 1 = VI\n" ++ " Bit 2 = BK\n" ++ " Bit 3 = BE\n" ++ " -> uapsd_queues=7 will enable uapsd for VO, VI and BK queues"); ++ ++module_param_named(ap_uapsd_on, rwnx_mod_params.ap_uapsd_on, bool, S_IRUGO); ++MODULE_PARM_DESC(ap_uapsd_on, "Enable UAPSD in AP mode (Default: 1)"); ++ ++module_param_named(sgi, rwnx_mod_params.sgi, bool, S_IRUGO); ++MODULE_PARM_DESC(sgi, "Advertise Short Guard Interval support (Default: 1)"); ++ ++module_param_named(sgi80, rwnx_mod_params.sgi80, bool, S_IRUGO); ++MODULE_PARM_DESC(sgi80, "Advertise Short Guard Interval support for 80MHz (Default: 1)"); ++ ++module_param_named(use_2040, rwnx_mod_params.use_2040, bool, S_IRUGO); ++MODULE_PARM_DESC(use_2040, "Use tweaked 20-40MHz mode (Default: 1)"); ++ ++module_param_named(use_80, rwnx_mod_params.use_80, bool, S_IRUGO); ++MODULE_PARM_DESC(use_80, "Enable 80MHz (Default: 1)"); ++ ++module_param_named(custregd, rwnx_mod_params.custregd, bool, S_IRUGO); ++MODULE_PARM_DESC(custregd, ++ "Use permissive custom regulatory rules (for testing ONLY) (Default: 0)"); ++ ++module_param_named(custchan, rwnx_mod_params.custchan, bool, S_IRUGO); ++MODULE_PARM_DESC(custchan, ++ "Extend channel set to non-standard channels (for testing ONLY) (Default: 0)"); ++ ++module_param_named(nss, rwnx_mod_params.nss, int, S_IRUGO); ++MODULE_PARM_DESC(nss, "1 <= nss <= 2 : Supported number of Spatial Streams (Default: 1)"); ++ ++module_param_named(amsdu_rx_max, rwnx_mod_params.amsdu_rx_max, int, S_IRUGO); ++MODULE_PARM_DESC(amsdu_rx_max, "0 <= amsdu_rx_max <= 2 : Maximum A-MSDU size supported in RX\n" ++ " 0: 3895 bytes\n" ++ " 1: 7991 bytes\n" ++ " 2: 11454 bytes\n" ++ " This value might be reduced according to the FW capabilities.\n" ++ " Default: 2"); ++ ++module_param_named(bfmee, rwnx_mod_params.bfmee, bool, S_IRUGO); ++MODULE_PARM_DESC(bfmee, "Enable Beamformee Capability (Default: 1-Enabled)"); ++ ++module_param_named(bfmer, rwnx_mod_params.bfmer, bool, S_IRUGO); ++MODULE_PARM_DESC(bfmer, "Enable Beamformer Capability (Default: 0-Disabled)"); ++ ++module_param_named(mesh, rwnx_mod_params.mesh, bool, S_IRUGO); ++MODULE_PARM_DESC(mesh, "Enable Meshing Capability (Default: 1-Enabled)"); ++ ++module_param_named(murx, rwnx_mod_params.murx, bool, S_IRUGO); ++MODULE_PARM_DESC(murx, "Enable MU-MIMO RX Capability (Default: 1-Enabled)"); ++ ++module_param_named(mutx, rwnx_mod_params.mutx, bool, S_IRUGO); ++MODULE_PARM_DESC(mutx, "Enable MU-MIMO TX Capability (Default: 1-Enabled)"); ++ ++module_param_named(mutx_on, rwnx_mod_params.mutx_on, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(mutx_on, "Enable MU-MIMO transmissions (Default: 1-Enabled)"); ++ ++module_param_named(roc_dur_max, rwnx_mod_params.roc_dur_max, int, S_IRUGO); ++MODULE_PARM_DESC(roc_dur_max, "Maximum Remain on Channel duration"); ++ ++module_param_named(listen_itv, rwnx_mod_params.listen_itv, int, S_IRUGO); ++MODULE_PARM_DESC(listen_itv, "Maximum listen interval"); ++ ++module_param_named(listen_bcmc, rwnx_mod_params.listen_bcmc, bool, S_IRUGO); ++MODULE_PARM_DESC(listen_bcmc, "Wait for BC/MC traffic following DTIM beacon"); ++ ++module_param_named(lp_clk_ppm, rwnx_mod_params.lp_clk_ppm, int, S_IRUGO); ++MODULE_PARM_DESC(lp_clk_ppm, "Low Power Clock accuracy of the local device"); ++ ++module_param_named(tdls, rwnx_mod_params.tdls, bool, S_IRUGO); ++MODULE_PARM_DESC(tdls, "Enable TDLS (Default: 1-Enabled)"); ++ ++module_param_named(uf, rwnx_mod_params.uf, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(uf, "Enable Unsupported HT Frame Logging (Default: 0-Disabled)"); ++ ++module_param_named(auto_reply, rwnx_mod_params.auto_reply, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(auto_reply, "Enable Monitor MacAddr Auto-Reply (Default: 0-Disabled)"); ++ ++module_param_named(ftl, rwnx_mod_params.ftl, charp, S_IRUGO); ++MODULE_PARM_DESC(ftl, "Firmware trace level (Default: \"\")"); ++ ++module_param_named(dpsm, rwnx_mod_params.dpsm, bool, S_IRUGO); ++MODULE_PARM_DESC(dpsm, "Enable Dynamic PowerSaving (Default: 1-Enabled)"); ++ ++ ++#ifdef DEFAULT_COUNTRY_CODE ++char default_ccode[4] = DEFAULT_COUNTRY_CODE; ++#else ++char default_ccode[4] = "00"; ++#endif ++ ++char country_code[4]; ++module_param_string(country_code, country_code, 4, 0600); ++ ++#if 0 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++/* Regulatory rules */ ++static struct ieee80211_regdomain rwnx_regdom = { ++ .n_reg_rules = 2, ++ .alpha2 = "99", ++ .reg_rules = { ++ REG_RULE(2390 - 10, 2510 + 10, 40, 0, 1000, 0), ++ REG_RULE(5150 - 10, 5970 + 10, 80, 0, 1000, 0), ++ } ++}; ++#endif ++#endif ++ ++static const int mcs_map_to_rate[4][3] = { ++ [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_7] = 65, ++ [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_8] = 78, ++ [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_9] = 78, ++ [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_7] = 135, ++ [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_8] = 162, ++ [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_9] = 180, ++ [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_7] = 292, ++ [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_8] = 351, ++ [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_9] = 390, ++ [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_7] = 585, ++ [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_8] = 702, ++ [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_9] = 780, ++}; ++ ++#define MAX_VHT_RATE(map, nss, bw) (mcs_map_to_rate[bw][map] * (nss)) ++ ++extern struct ieee80211_regdomain *reg_regdb[]; ++extern int reg_regdb_size; ++ ++char ccode_channels[200]; ++int index_for_channel_list = 0; ++module_param_string(ccode_channels, ccode_channels, 200, 0600); ++ ++void rwnx_get_countrycode_channels(struct wiphy *wiphy, ++ struct ieee80211_regdomain *regdomain){ ++ enum nl80211_band band; ++ struct ieee80211_supported_band *sband; ++ int channel_index; ++ int rule_index; ++ int band_num = 0; ++ int rule_num = regdomain->n_reg_rules; ++ int start_freq = 0; ++ int end_freq = 0; ++ int center_freq = 0; ++ char channel[4]; ++ ++ band_num = NUM_NL80211_BANDS; ++ ++ memset(ccode_channels, 0, 200); ++ index_for_channel_list = 0; ++ ++ for (band = 0; band < band_num; band++) { ++ sband = wiphy->bands[band];// bands: 0:2.4G 1:5G 2:60G ++ if (!sband) ++ continue; ++ ++ for (channel_index = 0; channel_index < sband->n_channels; channel_index++) { ++ for(rule_index = 0; rule_index < rule_num; rule_index++){ ++ start_freq = regdomain->reg_rules[rule_index].freq_range.start_freq_khz/1000; ++ end_freq = regdomain->reg_rules[rule_index].freq_range.end_freq_khz/1000; ++ center_freq = sband->channels[channel_index].center_freq; ++ if((center_freq - 10) >= start_freq && (center_freq + 10) <= end_freq){ ++ sprintf(channel, "%d",ieee80211_frequency_to_channel(center_freq)); ++ memcpy(ccode_channels + index_for_channel_list, channel, strlen(channel)); ++ index_for_channel_list += strlen(channel); ++ memcpy(ccode_channels + index_for_channel_list, " ", 1); ++ index_for_channel_list += 1; ++ break; ++ } ++ } ++ } ++ } ++ AICWFDBG(LOGINFO, "%s support channel:%s\r\n", __func__, ccode_channels); ++} ++ ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, ++ int index) ++{ ++ u8 idx; ++ ++ idx = index; ++ ++ memset(country_code, 0, 4); ++ country_code[0] = reg_regdb[idx]->alpha2[0]; ++ country_code[1] = reg_regdb[idx]->alpha2[1]; ++ ++ printk("%s set ccode:%s \r\n", __func__, country_code); ++ ++ rwnx_get_countrycode_channels(wiphy, reg_regdb[idx]); ++ ++ return reg_regdb[idx]; ++} ++ ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, ++ char *alpha2) ++{ ++ u8 idx; ++ ++ memset(country_code, 0, 4); ++ ++ AICWFDBG(LOGINFO, "%s set ccode:%s \r\n", __func__, alpha2); ++ idx = 0; ++ ++ while (reg_regdb[idx]){ ++ if((reg_regdb[idx]->alpha2[0] == alpha2[0]) && ++ (reg_regdb[idx]->alpha2[1] == alpha2[1])){ ++ memcpy(country_code, alpha2, 2); ++ rwnx_get_countrycode_channels(wiphy, reg_regdb[idx]); ++ return reg_regdb[idx]; ++ } ++ idx++; ++ } ++ ++ AICWFDBG(LOGERROR, "%s(): Error, wrong country = %s\n", ++ __func__, alpha2); ++ AICWFDBG(LOGINFO, "Set as default 00\n"); ++ memcpy(country_code, default_ccode, sizeof(default_ccode)); ++ rwnx_get_countrycode_channels(wiphy, reg_regdb[0]); ++ ++ return reg_regdb[0]; ++} ++ ++ ++ ++/** ++ * Do some sanity check ++ * ++ */ ++#if 0 ++static int rwnx_check_fw_hw_feature(struct rwnx_hw *rwnx_hw, ++ struct wiphy *wiphy) ++{ ++ u32_l sys_feat = rwnx_hw->version_cfm.features; ++ u32_l mac_feat = rwnx_hw->version_cfm.version_machw_1; ++ u32_l phy_feat = rwnx_hw->version_cfm.version_phy_1; ++ u32_l phy_vers = rwnx_hw->version_cfm.version_phy_2; ++ u16_l max_sta_nb = rwnx_hw->version_cfm.max_sta_nb; ++ u8_l max_vif_nb = rwnx_hw->version_cfm.max_vif_nb; ++ int bw, res = 0; ++ int amsdu_rx; ++ ++ if (!rwnx_hw->mod_params->custregd) ++ rwnx_hw->mod_params->custchan = false; ++ ++ if (rwnx_hw->mod_params->custchan) { ++ rwnx_hw->mod_params->mesh = false; ++ rwnx_hw->mod_params->tdls = false; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++ if (!(sys_feat & BIT(MM_FEAT_UMAC_BIT))) { ++ wiphy_err(wiphy, ++ "Loading softmac firmware with fullmac driver\n"); ++ res = -1; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_ANT_DIV_BIT))) { ++ rwnx_hw->mod_params->ant_div = false; ++ } ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (!(sys_feat & BIT(MM_FEAT_VHT_BIT))) { ++ rwnx_hw->mod_params->vht_on = false; ++ } ++ ++ // Check if HE is supported ++ if (!(sys_feat & BIT(MM_FEAT_HE_BIT))) { ++ rwnx_hw->mod_params->he_on = false; ++ rwnx_hw->mod_params->he_ul_on = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_PS_BIT))) { ++ rwnx_hw->mod_params->ps_on = false; ++ } ++ ++ /* AMSDU (non)support implies different shared structure definition ++ so insure that fw and drv have consistent compilation option */ ++ if (sys_feat & BIT(MM_FEAT_AMSDU_BIT)) { ++#ifndef CONFIG_RWNX_SPLIT_TX_BUF ++ wiphy_err(wiphy, ++ "AMSDU enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#else ++ if (rwnx_hw->mod_params->amsdu_maxnb > NX_TX_PAYLOAD_MAX) ++ rwnx_hw->mod_params->amsdu_maxnb = NX_TX_PAYLOAD_MAX; ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ } else { ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ wiphy_err(wiphy, ++ "AMSDU disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_SPLIT_TX_BUF */ ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_UAPSD_BIT))) { ++ rwnx_hw->mod_params->uapsd_timeout = 0; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_BFMEE_BIT))) { ++ rwnx_hw->mod_params->bfmee = false; ++ } ++ ++ if ((sys_feat & BIT(MM_FEAT_BFMER_BIT))) { ++#ifndef CONFIG_RWNX_BFMER ++ wiphy_err(wiphy, ++ "BFMER enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_BFMER */ ++ // Check PHY and MAC HW BFMER support and update parameter accordingly ++ if (!(phy_feat & MDM_BFMER_BIT) || !(mac_feat & NXMAC_BFMER_BIT)) { ++ rwnx_hw->mod_params->bfmer = false; ++ // Disable the feature in the bitfield so that it won't be displayed ++ sys_feat &= ~BIT(MM_FEAT_BFMER_BIT); ++ } ++ } else { ++#ifdef CONFIG_RWNX_BFMER ++ wiphy_err(wiphy, ++ "BFMER disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#else ++ rwnx_hw->mod_params->bfmer = false; ++#endif /* CONFIG_RWNX_BFMER */ ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_MESH_BIT))) { ++ rwnx_hw->mod_params->mesh = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_TDLS_BIT))) { ++ rwnx_hw->mod_params->tdls = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_UF_BIT))) { ++ rwnx_hw->mod_params->uf = false; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if ((sys_feat & BIT(MM_FEAT_MON_DATA_BIT))) { ++#ifndef CONFIG_RWNX_MON_DATA ++ wiphy_err(wiphy, ++ "Monitor+Data interface support (MON_DATA) is enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_MON_DATA */ ++ } else { ++#ifdef CONFIG_RWNX_MON_DATA ++ wiphy_err(wiphy, ++ "Monitor+Data interface support (MON_DATA) disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_MON_DATA */ ++ } ++#endif ++ ++ // Check supported AMSDU RX size ++ amsdu_rx = (sys_feat >> MM_AMSDU_MAX_SIZE_BIT0) & 0x03; ++ if (amsdu_rx < rwnx_hw->mod_params->amsdu_rx_max) { ++ rwnx_hw->mod_params->amsdu_rx_max = amsdu_rx; ++ } ++ ++ // Check supported BW ++ bw = (phy_feat & MDM_CHBW_MASK) >> MDM_CHBW_LSB; ++ // Check if 80MHz BW is supported ++ if (bw < 2) { ++ rwnx_hw->mod_params->use_80 = false; ++ } ++ // Check if 40MHz BW is supported ++ if (bw < 1) ++ rwnx_hw->mod_params->use_2040 = false; ++ ++ // 80MHz BW shall be disabled if 40MHz is not enabled ++ if (!rwnx_hw->mod_params->use_2040) ++ rwnx_hw->mod_params->use_80 = false; ++ ++ // Check if HT is supposed to be supported. If not, disable VHT/HE too ++ if (!rwnx_hw->mod_params->ht_on) { ++ rwnx_hw->mod_params->vht_on = false; ++ rwnx_hw->mod_params->he_on = false; ++ rwnx_hw->mod_params->he_ul_on = false; ++ rwnx_hw->mod_params->use_80 = false; ++ rwnx_hw->mod_params->use_2040 = false; ++ } ++ ++ // LDPC is mandatory for HE40 and above, so if LDPC is not supported, then disable ++ // HE to use HT/VHT only ++ if (rwnx_hw->mod_params->use_2040 && !rwnx_hw->mod_params->ldpc_on) { ++ rwnx_hw->mod_params->he_on = false; ++ rwnx_hw->mod_params->he_ul_on = false; ++ } ++ ++ // HT greenfield is not supported in modem >= 3.0 ++ if (__MDM_MAJOR_VERSION(phy_vers) > 0) { ++ rwnx_hw->mod_params->gf_rx_on = false; ++ } ++ ++ if (!(sys_feat & BIT(MM_FEAT_MU_MIMO_RX_BIT)) || ++ !rwnx_hw->mod_params->bfmee) { ++ rwnx_hw->mod_params->murx = false; ++ } ++ ++ if ((sys_feat & BIT(MM_FEAT_MU_MIMO_TX_BIT))) { ++#ifndef CONFIG_RWNX_MUMIMO_TX ++ wiphy_err(wiphy, ++ "MU-MIMO TX enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ if (!rwnx_hw->mod_params->bfmer) ++ rwnx_hw->mod_params->mutx = false; ++ // Check PHY and MAC HW MU-MIMO TX support and update parameter accordingly ++ else if (!(phy_feat & MDM_MUMIMOTX_BIT) || !(mac_feat & NXMAC_MU_MIMO_TX_BIT)) { ++ rwnx_hw->mod_params->mutx = false; ++ // Disable the feature in the bitfield so that it won't be displayed ++ sys_feat &= ~BIT(MM_FEAT_MU_MIMO_TX_BIT); ++ } ++ } else { ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ wiphy_err(wiphy, ++ "MU-MIMO TX disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#else ++ rwnx_hw->mod_params->mutx = false; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ } ++ ++ if (sys_feat & BIT(MM_FEAT_WAPI_BIT)) { ++ rwnx_enable_wapi(rwnx_hw); ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (sys_feat & BIT(MM_FEAT_MFP_BIT)) { ++ rwnx_enable_mfp(rwnx_hw); ++ } ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++#define QUEUE_NAME "Broadcast/Multicast queue " ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (sys_feat & BIT(MM_FEAT_BCN_BIT)) { ++#if NX_TXQ_CNT == 4 ++ wiphy_err(wiphy, QUEUE_NAME ++ "enabled in firmware but support not compiled in driver\n"); ++ res = -1; ++#endif /* NX_TXQ_CNT == 4 */ ++ } else { ++#if NX_TXQ_CNT == 5 ++ wiphy_err(wiphy, QUEUE_NAME ++ "disabled in firmware but support compiled in driver\n"); ++ res = -1; ++#endif /* NX_TXQ_CNT == 5 */ ++ } ++#undef QUEUE_NAME ++ ++#ifdef CONFIG_RWNX_RADAR ++ if (sys_feat & BIT(MM_FEAT_RADAR_BIT)) { ++ /* Enable combination with radar detection */ ++ wiphy->n_iface_combinations++; ++ } ++#endif /* CONFIG_RWNX_RADAR */ ++ ++#ifndef CONFIG_RWNX_SDM ++ switch (__MDM_PHYCFG_FROM_VERS(phy_feat)) { ++ case MDM_PHY_CONFIG_TRIDENT: ++ case MDM_PHY_CONFIG_ELMA: ++ rwnx_hw->mod_params->nss = 1; ++ break; ++ case MDM_PHY_CONFIG_KARST: ++ { ++ int nss_supp = (phy_feat & MDM_NSS_MASK) >> MDM_NSS_LSB; ++ if (rwnx_hw->mod_params->nss > nss_supp) ++ rwnx_hw->mod_params->nss = nss_supp; ++ } ++ break; ++ default: ++ WARN_ON(1); ++ break; ++ } ++#endif /* CONFIG_RWNX_SDM */ ++ ++ if (rwnx_hw->mod_params->nss < 1 || rwnx_hw->mod_params->nss > 2) ++ rwnx_hw->mod_params->nss = 1; ++ ++ if (rwnx_hw->mod_params->phy_cfg < 0 || rwnx_hw->mod_params->phy_cfg > 5) ++ rwnx_hw->mod_params->phy_cfg = 2; ++ ++ if (rwnx_hw->mod_params->mcs_map < 0 || rwnx_hw->mod_params->mcs_map > 2) ++ rwnx_hw->mod_params->mcs_map = 0; ++ ++ wiphy_info(wiphy, "PHY features: [NSS=%d][CHBW=%d]%s%s\n", ++ rwnx_hw->mod_params->nss, ++ 20 * (1 << ((phy_feat & MDM_CHBW_MASK) >> MDM_CHBW_LSB)), ++ rwnx_hw->mod_params->ldpc_on ? "[LDPC]" : "", ++ rwnx_hw->mod_params->he_on ? "[HE]" : ""); ++ ++#define PRINT_RWNX_FEAT(feat) \ ++ (sys_feat & BIT(MM_FEAT_##feat##_BIT) ? "["#feat"]" : "") ++ ++ wiphy_info(wiphy, "FW features: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", ++ PRINT_RWNX_FEAT(BCN), ++ PRINT_RWNX_FEAT(AUTOBCN), ++ PRINT_RWNX_FEAT(HWSCAN), ++ PRINT_RWNX_FEAT(CMON), ++ PRINT_RWNX_FEAT(MROLE), ++ PRINT_RWNX_FEAT(RADAR), ++ PRINT_RWNX_FEAT(PS), ++ PRINT_RWNX_FEAT(UAPSD), ++ PRINT_RWNX_FEAT(DPSM), ++ PRINT_RWNX_FEAT(AMPDU), ++ PRINT_RWNX_FEAT(AMSDU), ++ PRINT_RWNX_FEAT(CHNL_CTXT), ++ PRINT_RWNX_FEAT(REORD), ++ PRINT_RWNX_FEAT(P2P), ++ PRINT_RWNX_FEAT(P2P_GO), ++ PRINT_RWNX_FEAT(UMAC), ++ PRINT_RWNX_FEAT(VHT), ++ PRINT_RWNX_FEAT(HE), ++ PRINT_RWNX_FEAT(BFMEE), ++ PRINT_RWNX_FEAT(BFMER), ++ PRINT_RWNX_FEAT(WAPI), ++ PRINT_RWNX_FEAT(MFP), ++ PRINT_RWNX_FEAT(MU_MIMO_RX), ++ PRINT_RWNX_FEAT(MU_MIMO_TX), ++ PRINT_RWNX_FEAT(MESH), ++ PRINT_RWNX_FEAT(TDLS), ++ PRINT_RWNX_FEAT(ANT_DIV)); ++#undef PRINT_RWNX_FEAT ++ ++ if (max_sta_nb != NX_REMOTE_STA_MAX) { ++ wiphy_err(wiphy, "Different number of supported stations between driver and FW (%d != %d)\n", ++ NX_REMOTE_STA_MAX, max_sta_nb); ++ res = -1; ++ } ++ ++ if (max_vif_nb != NX_VIRT_DEV_MAX) { ++ wiphy_err(wiphy, "Different number of supported virtual interfaces between driver and FW (%d != %d)\n", ++ NX_VIRT_DEV_MAX, max_vif_nb); ++ res = -1; ++ } ++ ++ return res; ++} ++#endif ++ ++ ++static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#ifdef CONFIG_VHT_FOR_OLD_KERNEL ++ #ifdef USE_5G ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ #endif ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ int mcs_map; ++ int mcs_map_max; ++ int bw_max; ++ ++ if (!rwnx_hw->mod_params->vht_on) { ++ return; ++ } ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ rwnx_hw->vht_cap_2G.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_2G.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_2G.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ rwnx_hw->vht_cap_2G.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_2G.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_2G.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif//CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_2G.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ ++ rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; ++ printk("%s, vht_capa_info=0x%x\n", __func__, rwnx_hw->vht_cap_2G.cap); ++#ifdef USE_5G ++ if (rwnx_hw->band_5g_support) { ++ rwnx_hw->vht_cap_5G.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_5G.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_5G.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ rwnx_hw->vht_cap_5G.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ rwnx_hw->vht_cap_5G.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ rwnx_hw->vht_cap_5G.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif//CONFIG_VENDOR_RWNX_VHT_NO80 ++ rwnx_hw->vht_cap_5G.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ ++ rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; ++ } ++#endif//USE_5G ++ return; ++#else ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ int mcs_map; ++ int mcs_map_max; ++ int bw_max; ++#endif//CONFIG_VHT_FOR_OLD_KERNEL ++ ++ if (!rwnx_hw->mod_params->vht_on) { ++ return; ++ } ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ band_2GHz->vht_cap.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_2GHz->vht_cap.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ band_2GHz->vht_cap.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ band_2GHz->vht_cap.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_2GHz->vht_cap.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ band_2GHz->vht_cap.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_2GHz->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_2GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_2GHz->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_2GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif ++ band_2GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ band_5GHz->vht_cap.vht_supported = true; ++ if (rwnx_hw->mod_params->sgi80) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; ++ if (rwnx_hw->mod_params->stbc_on) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; ++ if (rwnx_hw->mod_params->ldpc_on) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; ++ if (rwnx_hw->mod_params->bfmee) { ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_5GHz->vht_cap.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ #else ++ band_5GHz->vht_cap.cap |= 3 << 13; ++ #endif ++ } ++ if (nss > 1) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC; ++ ++ // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap) ++ band_5GHz->vht_cap.cap |= rwnx_hw->mod_params->amsdu_rx_max; ++ ++ if (rwnx_hw->mod_params->bfmer) { ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; ++ /* Set number of sounding dimensions */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ band_5GHz->vht_cap.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ #else ++ band_5GHz->vht_cap.cap |= (nss - 1) << 16; ++ #endif ++ } ++ if (rwnx_hw->mod_params->murx) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; ++ if (rwnx_hw->mod_params->mutx) ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; ++ ++ /* ++ * MCS map: ++ * This capabilities are filled according to the mcs_map module parameter. ++ * However currently we have some limitations due to FPGA clock constraints ++ * that prevent always using the range of MCS that is defined by the ++ * parameter: ++ * - in RX, 2SS, we support up to MCS7 ++ * - in TX, 2SS, we support up to MCS8 ++ */ ++ // Get max supported BW ++ if (rwnx_hw->mod_params->use_80) ++ bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ bw_max = PHY_CHNL_BW_40; ++ else ++ bw_max = PHY_CHNL_BW_20; ++ ++ // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20, ++ // MCS9 is not supported in 1 and 2 SS ++ if (rwnx_hw->mod_params->use_2040) ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9; ++ else ++ mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8; ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_5GHz->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_5GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, mcs_map_max); ++ band_5GHz->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0); ++ for (i = 0; i < nss; i++) { ++ band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2)); ++ band_5GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max); ++ //mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ // IEEE80211_VHT_MCS_SUPPORT_0_8); ++ } ++ for (; i < 8; i++) { ++ band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16( ++ IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); ++ } ++ ++ if (!rwnx_hw->mod_params->use_80) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif ++ band_5GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; ++ } ++ } ++} ++ ++static void rwnx_set_ht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ ++ if (!rwnx_hw->mod_params->ht_on) { ++ band_2GHz->ht_cap.ht_supported = false; ++ if (rwnx_hw->band_5g_support) ++ band_5GHz->ht_cap.ht_supported = false; ++ return; ++ } ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ if (rwnx_hw->mod_params->stbc_on) ++ band_2GHz->ht_cap.cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; ++ if (rwnx_hw->mod_params->ldpc_on) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; ++ if (rwnx_hw->mod_params->use_2040) { ++ band_2GHz->ht_cap.mcs.rx_mask[4] = 0x1; /* MCS32 */ ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(135 * nss); ++ } else { ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(65 * nss); ++ } ++ if (nss > 1) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; ++ ++ // Update the AMSDU max RX size ++ if (rwnx_hw->mod_params->amsdu_rx_max) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; ++ ++ if (rwnx_hw->mod_params->sgi) { ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; ++ if (rwnx_hw->mod_params->use_2040) { ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(150 * nss); ++ } else ++ band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(72 * nss); ++ } ++ if (rwnx_hw->mod_params->gf_rx_on) ++ band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; ++ ++ for (i = 0; i < nss; i++) { ++ band_2GHz->ht_cap.mcs.rx_mask[i] = 0xFF; ++ } ++ ++ if (rwnx_hw->band_5g_support) ++ band_5GHz->ht_cap = band_2GHz->ht_cap; ++} ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++extern struct ieee80211_sband_iftype_data rwnx_he_capa; ++#endif ++static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++ struct ieee80211_sta_he_cap *he_cap; ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ int mcs_map; ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ he_cap = (struct ieee80211_sta_he_cap *) &rwnx_he_capa.he_cap; ++ he_cap->has_he = true; ++ he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK; ++ if (rwnx_hw->mod_params->use_2040) { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; ++ he_cap->ppe_thres[0] |= 0x10; ++ } ++ if (rwnx_hw->mod_params->use_80) { ++ he_cap->ppe_thres[0] |= 0x20; ++ he_cap->ppe_thres[2] |= 0xc0; ++ he_cap->ppe_thres[3] |= 0x01; ++ } ++ if (nss == 2) { ++ he_cap->ppe_thres[0] |= 0x01; ++ he_cap->ppe_thres[3] |= 0x70; ++ he_cap->ppe_thres[4] |= 0x1c; ++ he_cap->ppe_thres[5] |= 0x07; ++ } ++ //if (rwnx_hw->mod_params->use_80) ++ { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; ++ } ++ if (rwnx_hw->mod_params->ldpc_on) { ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; ++ } else { ++ // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory ++ // for MCS 10 and 11 ++ rwnx_hw->mod_params->he_mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US ++ | IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS; ++ ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS | ++ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #endif ++ if (rwnx_hw->mod_params->stbc_on) ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; ++ if (rwnx_hw->mod_params->bfmee) { ++ he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ he_cap->he_cap_elem.phy_cap_info[4] |= ++ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; ++ } ++ he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | ++ IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ //he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; ++ he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; ++ he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | ++ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9); ++ memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp)); ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ } ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, ++ // IEEE80211_HE_MCS_SUPPORT_0_7); ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ } ++ ++ return ; ++ #endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ int i; ++ int nss = rwnx_hw->mod_params->nss; ++ struct ieee80211_sta_he_cap *he_cap; ++ int mcs_map; ++ ++ if(rwnx_hw->sdiodev->chipid <= PRODUCT_ID_AIC8800D80) ++ nss = 1; ++ ++ if (!rwnx_hw->mod_params->he_on) { ++ band_2GHz->iftype_data = NULL; ++ band_2GHz->n_iftype_data = 0; ++ if (rwnx_hw->band_5g_support) { ++ band_5GHz->iftype_data = NULL; ++ band_5GHz->n_iftype_data = 0; ++ } ++ return; ++ } ++ he_cap = (struct ieee80211_sta_he_cap *) &band_2GHz->iftype_data->he_cap; ++ he_cap->has_he = true; ++ he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK; ++ if (rwnx_hw->mod_params->use_2040) { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; ++ he_cap->ppe_thres[0] |= 0x10; ++ } ++ if (rwnx_hw->mod_params->use_80) { ++ he_cap->ppe_thres[0] |= 0x20; ++ he_cap->ppe_thres[2] |= 0xc0; ++ he_cap->ppe_thres[3] |= 0x01; ++ } ++ if (nss == 2) { ++ he_cap->ppe_thres[0] |= 0x01; ++ he_cap->ppe_thres[3] |= 0x70; ++ he_cap->ppe_thres[4] |= 0x1c; ++ he_cap->ppe_thres[5] |= 0x07; ++ } ++ //if (rwnx_hw->mod_params->use_80) ++ { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; ++ } ++ if (rwnx_hw->mod_params->ldpc_on) { ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; ++ } else { ++ // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory ++ // for MCS 10 and 11 ++ rwnx_hw->mod_params->he_mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US ++ | IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS; ++ ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS | ++ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #endif ++ if (rwnx_hw->mod_params->stbc_on) ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; ++ #endif ++ ++ ++ if (rwnx_hw->mod_params->bfmee) { ++ he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ he_cap->he_cap_elem.phy_cap_info[4] |= ++ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; ++ } ++ he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | ++ IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #endif ++ ++ //he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; ++ he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | ++ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; ++ #endif ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ } ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp)); ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ } ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, ++ // IEEE80211_HE_MCS_SUPPORT_0_7); ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ he_cap = (struct ieee80211_sta_he_cap *) &band_5GHz->iftype_data->he_cap; ++ he_cap->has_he = true; ++ he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK; ++ if (rwnx_hw->mod_params->use_2040) { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; ++ he_cap->ppe_thres[0] |= 0x10; ++ } ++ if (rwnx_hw->mod_params->use_80) { ++ he_cap->ppe_thres[0] |= 0x20; ++ he_cap->ppe_thres[2] |= 0xc0; ++ he_cap->ppe_thres[3] |= 0x01; ++ } ++ if (nss == 2) { ++ he_cap->ppe_thres[0] |= 0x01; ++ he_cap->ppe_thres[3] |= 0x70; ++ he_cap->ppe_thres[4] |= 0x1c; ++ he_cap->ppe_thres[5] |= 0x07; ++ } ++ //if (rwnx_hw->mod_params->use_80) ++ { ++ he_cap->he_cap_elem.phy_cap_info[0] |= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; ++ } ++ if (rwnx_hw->mod_params->ldpc_on) { ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; ++ } else { ++ // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory ++ // for MCS 10 and 11 ++ rwnx_hw->mod_params->he_mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map, ++ IEEE80211_HE_MCS_SUPPORT_0_9); ++ } ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US | ++ IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS | ++ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | ++ IEEE80211_HE_PHY_CAP2_DOPPLER_RX; ++ #endif ++ if (rwnx_hw->mod_params->stbc_on) ++ he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | ++ IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | ++ IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; ++ #endif ++ ++ if (rwnx_hw->mod_params->bfmee) { ++ he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ he_cap->he_cap_elem.phy_cap_info[4] |= ++ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; ++ } ++ he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | ++ IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #else ++ he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | ++ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | ++ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | ++ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | ++ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; ++ #endif ++ ++ //he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; ++ he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) ++ he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | ++ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; ++ #endif ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) ++ mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9); ++ memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp)); ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7; ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss; ++ } ++ mcs_map = rwnx_hw->mod_params->he_mcs_map; ++ for (i = 0; i < nss; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, ++ // IEEE80211_HE_MCS_SUPPORT_0_7); ++ } ++ for (; i < 8; i++) { ++ __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2)); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss; ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss; ++ } ++ } ++#endif ++} ++ ++static void rwnx_set_wiphy_params(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) ++ struct ieee80211_regdomain *regdomain; ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ /* FULLMAC specific parameters */ ++ wiphy->flags |= WIPHY_FLAG_REPORTS_OBSS; ++ wiphy->max_scan_ssids = SCAN_SSID_MAX; ++ wiphy->max_scan_ie_len = SCANU_MAX_IE_LEN; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (rwnx_hw->mod_params->tdls) { ++ /* TDLS support */ ++ wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; ++#ifdef CONFIG_RWNX_FULLMAC ++ /* TDLS external setup support */ ++ wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; ++#endif ++ } ++ ++ if (rwnx_hw->mod_params->ap_uapsd_on) ++ wiphy->flags |= WIPHY_FLAG_AP_UAPSD; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (rwnx_hw->mod_params->ps_on) ++ wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; ++ else ++ wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; ++#endif ++ ++if (rwnx_hw->mod_params->custregd) { ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ // Apply custom regulatory. Note that for recent kernel versions we use instead the ++ // REGULATORY_WIPHY_SELF_MANAGED flag, along with the regulatory_set_wiphy_regd() ++ // function, that needs to be called after wiphy registration ++ memcpy(country_code, default_ccode, sizeof(default_ccode)); ++ regdomain = getRegdomainFromRwnxDB(wiphy, default_ccode); ++ printk(KERN_CRIT ++ "\n\n%s: CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES\n\n", ++ __func__); ++ wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; ++ /* From kernel 6.5.0, this bit is removed and will be reused later */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 39) || LINUX_VERSION_CODE > KERNEL_VERSION(6, 2, 0)) ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) */ ++ wiphy_apply_custom_regulatory(wiphy, regdomain); ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) ++ memcpy(country_code, default_ccode, sizeof(default_ccode)); ++ regdomain = getRegdomainFromRwnxDB(wiphy, default_ccode); ++ printk(KERN_CRIT"%s: Registering custom regulatory\n", __func__); ++ wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; ++ wiphy_apply_custom_regulatory(wiphy, regdomain); ++#endif ++ // Check if custom channel set shall be enabled. In such case only monitor mode is ++ // supported ++ if (rwnx_hw->mod_params->custchan) { ++ wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR); ++ ++ // Enable "extra" channels ++ wiphy->bands[NL80211_BAND_2GHZ]->n_channels += 13; ++ //#ifdef USE_5G ++ if(rwnx_hw->band_5g_support){ ++ wiphy->bands[NL80211_BAND_5GHZ]->n_channels += 59; ++ } ++ //#endif ++ } ++ } ++ ++#if 0 ++ if (rwnx_hw->mod_params->custregd) { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ // Apply custom regulatory. Note that for recent kernel versions we use instead the ++ // REGULATORY_WIPHY_SELF_MANAGED flag, along with the regulatory_set_wiphy_regd() ++ // function, that needs to be called after wiphy registration ++ printk(KERN_CRIT ++ "\n\n%s: CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES\n\n", ++ __func__); ++ wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; ++ /* From kernel 6.5.0, this bit is removed and will be reused later */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 39) || LINUX_VERSION_CODE > KERNEL_VERSION(6, 2, 0)) ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) */ ++ wiphy_apply_custom_regulatory(wiphy, &rwnx_regdom); ++#endif ++ // Check if custom channel set shall be enabled. In such case only monitor mode is ++ // supported ++ if (rwnx_hw->mod_params->custchan) { ++ wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR); ++ ++ // Enable "extra" channels ++ wiphy->bands[NL80211_BAND_2GHZ]->n_channels += 13; ++ if (rwnx_hw->band_5g_support) ++ wiphy->bands[NL80211_BAND_5GHZ]->n_channels += 59; ++ } ++ } ++#endif ++} ++ ++#if 0 ++static void rwnx_set_rf_params(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#ifndef CONFIG_RWNX_SDM ++ struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ]; ++ struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ]; ++ u32 mdm_phy_cfg = __MDM_PHYCFG_FROM_VERS(rwnx_hw->version_cfm.version_phy_1); ++ ++ /* ++ * Get configuration file depending on the RF ++ */ ++ if (mdm_phy_cfg == MDM_PHY_CONFIG_TRIDENT) { ++ struct rwnx_phy_conf_file phy_conf; ++ // Retrieve the Trident configuration ++ rwnx_parse_phy_configfile(rwnx_hw, RWNX_PHY_CONFIG_TRD_NAME, ++ &phy_conf, rwnx_hw->mod_params->phy_cfg); ++ memcpy(&rwnx_hw->phy.cfg, &phy_conf.trd, sizeof(phy_conf.trd)); ++ } else if (mdm_phy_cfg == MDM_PHY_CONFIG_ELMA) { ++ } else if (mdm_phy_cfg == MDM_PHY_CONFIG_KARST) { ++ struct rwnx_phy_conf_file phy_conf; ++ // We use the NSS parameter as is ++ // Retrieve the Karst configuration ++ rwnx_parse_phy_configfile(rwnx_hw, RWNX_PHY_CONFIG_KARST_NAME, ++ &phy_conf, rwnx_hw->mod_params->phy_cfg); ++ ++ memcpy(&rwnx_hw->phy.cfg, &phy_conf.karst, sizeof(phy_conf.karst)); ++ } else { ++ WARN_ON(1); ++ } ++ ++ /* ++ * adjust caps depending on the RF ++ */ ++ switch (mdm_phy_cfg) { ++ case MDM_PHY_CONFIG_TRIDENT: ++ { ++ wiphy_dbg(wiphy, "found Trident phy .. limit BW to 40MHz\n"); ++ rwnx_hw->phy.limit_bw = true; ++ if (rwnx_hw->band_5g_support) { ++#ifdef CONFIG_VENDOR_RWNX_VHT_NO80 ++ band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80; ++#endif ++ band_5GHz->vht_cap.cap &= ~(IEEE80211_VHT_CAP_SHORT_GI_80 | ++ IEEE80211_VHT_CAP_RXSTBC_MASK); ++ } ++ break; ++ } ++ case MDM_PHY_CONFIG_ELMA: ++ wiphy_dbg(wiphy, "found ELMA phy .. disabling 2.4GHz and greenfield rx\n"); ++ wiphy->bands[NL80211_BAND_2GHZ] = NULL; ++ band_2GHz->ht_cap.cap &= ~IEEE80211_HT_CAP_GRN_FLD; ++ if (rwnx_hw->band_5g_support) { ++ band_5GHz->ht_cap.cap &= ~IEEE80211_HT_CAP_GRN_FLD; ++ band_5GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_RXSTBC_MASK; ++ } ++ break; ++ case MDM_PHY_CONFIG_KARST: ++ { ++ wiphy_dbg(wiphy, "found KARST phy\n"); ++ break; ++ } ++ default: ++ WARN_ON(1); ++ break; ++ } ++#endif /* CONFIG_RWNX_SDM */ ++} ++#endif ++ ++int rwnx_handle_dynparams(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++#if 0 ++ /* Check compatibility between requested parameters and HW/SW features */ ++ int ret; ++ ++ ret = rwnx_check_fw_hw_feature(rwnx_hw, wiphy); ++ if (ret) ++ return ret; ++ ++ /* Allocate the RX buffers according to the maximum AMSDU RX size */ ++ ret = rwnx_ipc_rxbuf_init(rwnx_hw, ++ (4 * (rwnx_hw->mod_params->amsdu_rx_max + 1) + 1) * 1024); ++ if (ret) { ++ wiphy_err(wiphy, "Cannot allocate the RX buffers\n"); ++ return ret; ++ } ++#endif ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rwnx_hw->mod_params->sgi80 = true; ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80 && rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80X2 && ++ rwnx_hw->mod_params->he_mcs_map == IEEE80211_HE_MCS_SUPPORT_0_11) { ++ AICWFDBG(LOGINFO,"%s unsupport mcs11 change to mcs9", __func__); ++ rwnx_hw->mod_params->he_mcs_map = IEEE80211_HE_MCS_SUPPORT_0_9; ++ } ++ ++ /* Set wiphy parameters */ ++ rwnx_set_wiphy_params(rwnx_hw, wiphy); ++ /* Set VHT capabilities */ ++ rwnx_set_vht_capa(rwnx_hw, wiphy); ++ /* Set HE capabilities */ ++ rwnx_set_he_capa(rwnx_hw, wiphy); ++ /* Set HT capabilities */ ++ rwnx_set_ht_capa(rwnx_hw, wiphy); ++ /* Set RF specific parameters (shall be done last as it might change some ++ capabilities previously set) */ ++#if 0 ++ rwnx_set_rf_params(rwnx_hw, wiphy); ++#endif ++ return 0; ++} ++ ++void rwnx_custregd(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) ++{ ++// For older kernel version, the custom regulatory is applied before the wiphy ++// registration (in rwnx_set_wiphy_params()), so nothing has to be done here ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ if (!rwnx_hw->mod_params->custregd) ++ return; ++ ++ /* From kernel 6.5.0, this bit is removed and will be reused later */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 39) || LINUX_VERSION_CODE > KERNEL_VERSION(6, 2, 0)) ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) */ ++ wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; ++ ++ rtnl_lock(); ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) ++ if (regulatory_set_wiphy_regd_sync(wiphy, getRegdomainFromRwnxDB(wiphy, default_ccode))){ ++ wiphy_err(wiphy, "Failed to set custom regdomain\n"); ++ } ++ #else ++ if (regulatory_set_wiphy_regd_sync_rtnl(wiphy, getRegdomainFromRwnxDB(wiphy, default_ccode))){ ++ wiphy_err(wiphy, "Failed to set custom regdomain\n"); ++ } ++ #endif ++ ++ else{ ++ wiphy_err(wiphy,"\n" ++ "*******************************************************\n" ++ "** CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES **\n" ++ "*******************************************************\n"); ++ } ++ rtnl_unlock(); ++#endif ++ ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h +new file mode 100644 +index 000000000000..ef31093fcadb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h +@@ -0,0 +1,76 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_mod_params.h ++ * ++ * @brief Declaration of module parameters ++ * ++ * Copyright (C) RivieraWaves 2012-2021 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_MOD_PARAM_H_ ++#define _RWNX_MOD_PARAM_H_ ++ ++struct rwnx_mod_params { ++ bool ht_on; ++ bool vht_on; ++ bool he_on; ++ int mcs_map; ++ int he_mcs_map; ++ bool he_ul_on; ++ bool ldpc_on; ++ bool stbc_on; ++ bool gf_rx_on; ++ int phy_cfg; ++ int uapsd_timeout; ++ bool ap_uapsd_on; ++ bool sgi; ++ bool sgi80; ++ bool use_2040; ++ bool use_80; ++ bool custregd; ++ bool custchan; ++ int nss; ++ int amsdu_rx_max; ++ bool bfmee; ++ bool bfmer; ++ bool mesh; ++ bool murx; ++ bool mutx; ++ bool mutx_on; ++ unsigned int roc_dur_max; ++ int listen_itv; ++ bool listen_bcmc; ++ int lp_clk_ppm; ++ bool ps_on; ++ int tx_lft; ++ int amsdu_maxnb; ++ int uapsd_queues; ++ bool tdls; ++ bool uf; ++ bool auto_reply; ++ char *ftl; ++ bool dpsm; ++#ifdef CONFIG_RWNX_FULLMAC ++ bool ant_div; ++#endif /* CONFIG_RWNX_FULLMAC */ ++}; ++ ++extern struct rwnx_mod_params rwnx_mod_params; ++ ++struct rwnx_hw; ++struct wiphy; ++int rwnx_handle_dynparams(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy); ++void rwnx_custregd(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy); ++void rwnx_enable_wapi(struct rwnx_hw *rwnx_hw); ++void rwnx_enable_mfp(struct rwnx_hw *rwnx_hw); ++struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, ++ char *alpha2); ++ ++struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, ++ int index); ++ ++ ++#endif /* _RWNX_MOD_PARAM_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c +new file mode 100644 +index 000000000000..1799d7dde4cd +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c +@@ -0,0 +1,1557 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_msg_rx.c ++ * ++ * @brief RX function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2021 ++ * ++ **************************************************************************************** ++ */ ++#include ++#include "rwnx_defs.h" ++#include "rwnx_prof.h" ++#include "rwnx_tx.h" ++#ifdef CONFIG_RWNX_BFMER ++#include "rwnx_bfmer.h" ++#endif //(CONFIG_RWNX_BFMER) ++#ifdef CONFIG_RWNX_FULLMAC ++#include "rwnx_debugfs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_tdls.h" ++#endif /* CONFIG_RWNX_FULLMAC */ ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "aicwf_txrxif.h" ++#include "rwnx_msg_rx.h" ++#ifdef CONFIG_SDIO_BT ++#include "aic_btsdio.h" ++#endif ++void rwnx_cfg80211_unlink_bss(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif); ++ ++static int rwnx_freq_to_idx(struct rwnx_hw *rwnx_hw, int freq) ++{ ++ struct ieee80211_supported_band *sband = NULL; ++ int band, ch, idx = 0; ++ ++ for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { ++#ifdef CONFIG_RWNX_FULLMAC ++ sband = rwnx_hw->wiphy->bands[band]; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ if (!sband) { ++ continue; ++ } ++ ++ for (ch = 0; ch < sband->n_channels; ch++, idx++) { ++ if (sband->channels[ch].center_freq == freq) { ++ goto exit; ++ } ++ } ++ } ++ ++ BUG_ON(1); ++ ++exit: ++ // Channel has been found, return the index ++ return idx; ++} ++ ++/*************************************************************************** ++ * Messages from MM task ++ **************************************************************************/ ++static inline int rwnx_rx_chan_pre_switch_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ int chan_idx = ((struct mm_channel_pre_switch_ind *)msg->param)->chan_index; ++ ++ REG_SW_SET_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->up && rwnx_vif->ch_index == chan_idx) { ++ rwnx_txq_vif_stop(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ REG_SW_CLEAR_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT); ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_chan_switch_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ int chan_idx = ((struct mm_channel_switch_ind *)msg->param)->chan_index; ++ bool roc = ((struct mm_channel_switch_ind *)msg->param)->roc; ++ bool roc_tdls = ((struct mm_channel_switch_ind *)msg->param)->roc_tdls; ++ ++ REG_SW_SET_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (roc_tdls) { ++ u8 vif_index = ((struct mm_channel_switch_ind *)msg->param)->vif_index; ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == vif_index) { ++ rwnx_vif->roc_tdls = true; ++ rwnx_txq_tdls_sta_start(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ } else if (!roc) { ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->up && rwnx_vif->ch_index == chan_idx) { ++ rwnx_txq_vif_start(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ } else { ++ /* Retrieve the allocated RoC element */ ++ struct rwnx_roc_elem *roc_elem = rwnx_hw->roc_elem; ++ /* Get VIF on which RoC has been started */ ++ //rwnx_vif = netdev_priv(roc_elem->wdev->netdev); ++ ++ /* For debug purpose (use ftrace kernel option) */ ++ //trace_switch_roc(rwnx_vif->vif_index); ++ ++ if(roc_elem) { ++ /* If mgmt_roc is true, remain on channel has been started by ourself */ ++ if (!roc_elem->mgmt_roc) { ++ /* Inform the host that we have switch on the indicated off-channel */ ++ cfg80211_ready_on_channel(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), ++ roc_elem->chan, roc_elem->duration, GFP_ATOMIC); ++ } ++ ++ /* Keep in mind that we have switched on the channel */ ++ roc_elem->on_chan = true; ++ } else { ++ printk("roc_elem == null\n"); ++ } ++ // Enable traffic on OFF channel queue ++ rwnx_txq_offchan_start(rwnx_hw); ++ } ++ ++ tasklet_schedule(&rwnx_hw->task); ++ ++ rwnx_hw->cur_chanctx = chan_idx; ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ REG_SW_CLEAR_PROFILING_CHAN(rwnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT); ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_tdls_chan_switch_cfm(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ return 0; ++} ++ ++static inline int rwnx_rx_tdls_chan_switch_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ // Enable traffic on OFF channel queue ++ rwnx_txq_offchan_start(rwnx_hw); ++ ++ return 0; ++#endif ++} ++ ++static inline int rwnx_rx_tdls_chan_switch_base_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ u8 vif_index = ((struct tdls_chan_switch_base_ind *)msg->param)->vif_index; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == vif_index) { ++ rwnx_vif->roc_tdls = false; ++ rwnx_txq_tdls_sta_stop(rwnx_vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ return 0; ++#endif ++} ++ ++static inline int rwnx_rx_tdls_peer_ps_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct rwnx_vif *rwnx_vif; ++ u8 vif_index = ((struct tdls_peer_ps_ind *)msg->param)->vif_index; ++ bool ps_on = ((struct tdls_peer_ps_ind *)msg->param)->ps_on; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (rwnx_vif->vif_index == vif_index) { ++ rwnx_vif->sta.tdls_sta->tdls.ps_on = ps_on; ++ // Update PS status for the TDLS station ++ rwnx_ps_bh_enable(rwnx_hw, rwnx_vif->sta.tdls_sta, ps_on); ++ } ++ } ++ ++ return 0; ++#endif ++} ++ ++static inline int rwnx_rx_remain_on_channel_exp_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ /* Retrieve the allocated RoC element */ ++ struct rwnx_roc_elem *roc_elem = rwnx_hw->roc_elem; ++ /* Get VIF on which RoC has been started */ ++ struct rwnx_vif *rwnx_vif; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (!roc_elem) ++ return 0; ++ ++ rwnx_vif = container_of(roc_elem->wdev, struct rwnx_vif, wdev); ++ /* For debug purpose (use ftrace kernel option) */ ++#ifdef CREATE_TRACE_POINTS ++ trace_roc_exp(rwnx_vif->vif_index); ++#endif ++ /* If mgmt_roc is true, remain on channel has been started by ourself */ ++ /* If RoC has been cancelled before we switched on channel, do not call cfg80211 */ ++ if (!roc_elem->mgmt_roc && roc_elem->on_chan) { ++ /* Inform the host that off-channel period has expired */ ++ cfg80211_remain_on_channel_expired(roc_elem->wdev, (u64)(rwnx_hw->roc_cookie_cnt), ++ roc_elem->chan, GFP_ATOMIC); ++ } ++ ++ /* De-init offchannel TX queue */ ++ rwnx_txq_offchan_deinit(rwnx_vif); ++ ++ /* Increase the cookie counter cannot be zero */ ++ rwnx_hw->roc_cookie_cnt++; ++ ++ if (rwnx_hw->roc_cookie_cnt == 0) { ++ rwnx_hw->roc_cookie_cnt = 1; ++ } ++ ++ /* Free the allocated RoC element */ ++ kfree(roc_elem); ++ rwnx_hw->roc_elem = NULL; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ return 0; ++} ++ ++static inline int rwnx_rx_p2p_vif_ps_change_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ int vif_idx = ((struct mm_p2p_vif_ps_change_ind *)msg->param)->vif_index; ++ int ps_state = ((struct mm_p2p_vif_ps_change_ind *)msg->param)->ps_state; ++ struct rwnx_vif *vif_entry; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ vif_entry = rwnx_hw->vif_table[vif_idx]; ++ ++ if (vif_entry) { ++ goto found_vif; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ goto exit; ++ ++found_vif: ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (ps_state == MM_PS_MODE_OFF) { ++ // Start TX queues for provided VIF ++ rwnx_txq_vif_start(vif_entry, RWNX_TXQ_STOP_VIF_PS, rwnx_hw); ++ tasklet_schedule(&rwnx_hw->task); ++ } else { ++ // Stop TX queues for provided VIF ++ rwnx_txq_vif_stop(vif_entry, RWNX_TXQ_STOP_VIF_PS, rwnx_hw); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++exit: ++ return 0; ++} ++ ++static inline int rwnx_rx_channel_survey_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_channel_survey_ind *ind = (struct mm_channel_survey_ind *)msg->param; ++ // Get the channel index ++ int idx = rwnx_freq_to_idx(rwnx_hw, ind->freq); ++ // Get the survey ++ struct rwnx_survey_info *rwnx_survey; ++ ++ if (idx > ARRAY_SIZE(rwnx_hw->survey)) ++ return 0; ++ ++ rwnx_survey = &rwnx_hw->survey[idx]; ++ ++ // Store the received parameters ++ rwnx_survey->chan_time_ms = ind->chan_time_ms; ++ rwnx_survey->chan_time_busy_ms = ind->chan_time_busy_ms; ++ rwnx_survey->noise_dbm = ind->noise_dbm; ++ rwnx_survey->filled = (SURVEY_INFO_TIME | ++ SURVEY_INFO_TIME_BUSY); ++ ++ if (ind->noise_dbm != 0) { ++ rwnx_survey->filled |= SURVEY_INFO_NOISE_DBM; ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_p2p_noa_upd_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ return 0; ++} ++ ++static inline int rwnx_rx_rssi_status_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_rssi_status_ind *ind = (struct mm_rssi_status_ind *)msg->param; ++ int vif_idx = ind->vif_index; ++ bool rssi_status = ind->rssi_status; ++ ++ struct rwnx_vif *vif_entry; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++vif_entry = rwnx_hw->vif_table[vif_idx]; ++ if (vif_entry) { ++ cfg80211_cqm_rssi_notify(vif_entry->ndev, ++ rssi_status ? NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW : ++ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, ++ ind->rssi, GFP_ATOMIC); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_pktloss_notify_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct mm_pktloss_ind *ind = (struct mm_pktloss_ind *)msg->param; ++ struct rwnx_vif *vif_entry; ++ int vif_idx = ind->vif_index; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ vif_entry = rwnx_hw->vif_table[vif_idx]; ++ if (vif_entry) { ++ cfg80211_cqm_pktloss_notify(vif_entry->ndev, (const u8 *)ind->mac_addr.array, ++ ind->num_packets, GFP_ATOMIC); ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ return 0; ++} ++ ++static inline int rwnx_radar_detect_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct radar_pulse_array_desc *pulses = (struct radar_pulse_array_desc *)msg->param; ++ int i; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ //printk("%s\n", __func__); ++ ++ if(pulses->cnt == 0) { ++ printk("cnt error\n"); ++ return -1; ++ } ++ ++ if(rwnx_radar_detection_is_enable(&rwnx_hw->radar, pulses->idx)) { ++ for(i=0; icnt; i++) { ++ struct rwnx_radar_pulses *p = &rwnx_hw->radar.pulses[pulses->idx]; ++ ++ p->buffer[p->index] = pulses->pulse[i]; ++ p->index = (p->index + 1)%RWNX_RADAR_PULSE_MAX; ++ if(p->count < RWNX_RADAR_PULSE_MAX) ++ p->count++; ++ //printk("pulse=%x\n", pulses->pulse[i]); ++ } ++ ++ if(!work_pending(&rwnx_hw->radar.detection_work)) ++ schedule_work(&rwnx_hw->radar.detection_work); ++ } else ++ printk("not enable\n"); ++ ++ return 0; ++} ++ ++static inline int rwnx_apm_staloss_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_apm_staloss_ind *ind = (struct mm_apm_staloss_ind *)msg->param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ memcpy(rwnx_hw->sta_mac_addr, ind->mac_addr, 6); ++ rwnx_hw->apm_vif_idx = ind->vif_idx; ++ ++ queue_work(rwnx_hw->apmStaloss_wq, &rwnx_hw->apmStalossWork); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SDIO_BT ++static inline int rwnx_bt_recv_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_bt_recv_ind *ind = (struct mm_bt_recv_ind *)msg->param; ++ ++ bt_sdio_recv(ind->bt_data,ind->data_len); ++ return 0; ++} ++#endif ++ ++static inline int rwnx_rx_csa_counter_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_csa_counter_ind *ind = (struct mm_csa_counter_ind *)msg->param; ++ struct rwnx_vif *vif; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ if (vif->vif_index == ind->vif_index) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (vif->ap.csa) ++ vif->ap.csa->count = ind->csa_count; ++ else ++ netdev_err(vif->ndev, "CSA counter update but no active CSA"); ++ ++#endif ++ } ++ ++ return 0; ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline int rwnx_rx_csa_finish_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_csa_finish_ind *ind = (struct mm_csa_finish_ind *)msg->param; ++ struct rwnx_vif *vif; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ if (vif->vif_index == ind->vif_index) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) { ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP || ++ RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_GO) { ++ if (vif->ap.csa) { ++ vif->ap.csa->status = ind->status; ++ vif->ap.csa->ch_idx = ind->chan_idx; ++ schedule_work(&vif->ap.csa->work); ++ } else ++ netdev_err(vif->ndev, "CSA finish indication but no active CSA"); ++ } else { ++ if (ind->status == 0) { ++ rwnx_chanctx_unlink(vif); ++ rwnx_chanctx_link(vif, ind->chan_idx, NULL); ++ if (rwnx_hw->cur_chanctx == ind->chan_idx) { ++ rwnx_radar_detection_enable_on_cur_channel(rwnx_hw); ++ rwnx_txq_vif_start(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } else ++ rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_csa_traffic_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_csa_traffic_ind *ind = (struct mm_csa_traffic_ind *)msg->param; ++ struct rwnx_vif *vif; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ // Look for VIF entry ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ if (vif->vif_index == ind->vif_index) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) { ++ if (ind->enable) ++ rwnx_txq_vif_start(vif, RWNX_TXQ_STOP_CSA, rwnx_hw); ++ else ++ rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CSA, rwnx_hw); ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_ps_change_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_ps_change_ind *ind = (struct mm_ps_change_ind *)msg->param; ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[ind->sta_idx]; ++ ++ if (ind->sta_idx >= (NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX)) { ++ wiphy_err(rwnx_hw->wiphy, "Invalid sta index reported by fw %d\n", ++ ind->sta_idx); ++ return 1; ++ } ++ ++ netdev_dbg(rwnx_hw->vif_table[sta->vif_idx]->ndev, ++ "Sta %d, change PS mode to %s", sta->sta_idx, ++ ind->ps_state ? "ON" : "OFF"); ++ ++ if (sta->valid) { ++ rwnx_ps_bh_enable(rwnx_hw, sta, ind->ps_state); ++ } else if (rwnx_hw->adding_sta) { ++ sta->ps.active = ind->ps_state ? true : false; ++ } else { ++ if (rwnx_hw->vif_table[sta->vif_idx] && rwnx_hw->vif_table[sta->vif_idx]->ndev) ++ netdev_err(rwnx_hw->vif_table[sta->vif_idx]->ndev, ++ "Ignore PS mode change on invalid sta\n"); ++ } ++ ++ return 0; ++} ++ ++ ++static inline int rwnx_rx_traffic_req_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mm_traffic_req_ind *ind = (struct mm_traffic_req_ind *)msg->param; ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[ind->sta_idx]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ netdev_dbg(rwnx_hw->vif_table[sta->vif_idx]->ndev, ++ "Sta %d, asked for %d pkt", sta->sta_idx, ind->pkt_cnt); ++ ++ rwnx_ps_bh_traffic_req(rwnx_hw, sta, ind->pkt_cnt, ++ ind->uapsd ? UAPSD_ID : LEGACY_PS_ID); ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from SCAN task ++ **************************************************************************/ ++#if 0 ++static inline int rwnx_rx_scan_done_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = false, ++ }; ++#endif ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_ipc_elem_var_deallocs(rwnx_hw, &rwnx_hw->scan_ie); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ ieee80211_scan_completed(rwnx_hw->hw, &info); ++#else ++ ieee80211_scan_completed(rwnx_hw->hw, false); ++#endif ++ ++ return 0; ++} ++#endif ++ ++/*************************************************************************** ++ * Messages from SCANU task ++ **************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++extern uint8_t scanning; ++static inline int rwnx_rx_scanu_start_cfm(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (rwnx_hw->scan_request ++#ifdef CONFIG_SCHED_SCAN ++ && !rwnx_hw->is_sched_scan ++#endif//CONFIG_SCHED_SCAN ++ ) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ struct cfg80211_scan_info info = { ++ .aborted = false, ++ }; ++ ++ cfg80211_scan_done(rwnx_hw->scan_request, &info); ++#else ++ cfg80211_scan_done(rwnx_hw->scan_request, false); ++#endif ++ } ++ ++#ifdef CONFIG_SCHED_SCAN ++ if(rwnx_hw->is_sched_scan){ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ AICWFDBG(LOGINFO, "%s cfg80211_sched_scan_results \r\n", __func__); ++ cfg80211_sched_scan_results(rwnx_hw->scan_request->wiphy, ++ rwnx_hw->sched_scan_req->reqid); ++#else ++ cfg80211_sched_scan_results(rwnx_hw->sched_scan_req->wiphy); ++#endif ++ kfree(rwnx_hw->scan_request); ++ rwnx_hw->is_sched_scan = false; ++ } ++#endif//CONFIG_SCHED_SCAN ++ ++ rwnx_hw->scan_request = NULL; ++ scanning = 0; ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_scanu_result_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct cfg80211_bss *bss = NULL; ++ struct ieee80211_channel *chan; ++ struct scanu_result_ind *ind = (struct scanu_result_ind *)msg->param; ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)ind->payload; ++ u64 tsf; ++ u8 *ie; ++ size_t ielen; ++ u16 capability, beacon_interval; ++ u16 len = ind->length; ++ ++ chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq); ++ ++ if (chan != NULL) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ struct timespec ts; ++ get_monotonic_boottime(&ts); ++ tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000); ++ mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000) + ts.tv_nsec/1000; ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0) ++ struct timespec ts; ++ ts = ktime_to_timespec(ktime_get_boottime()); ++ tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000); ++ mgmt->u.probe_resp.timestamp = tsf; ++#else ++ struct timespec64 ts; ++ ts = ktime_to_timespec64(ktime_get_boottime()); ++ tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000); ++ mgmt->u.probe_resp.timestamp = tsf; ++#endif ++ ie = mgmt->u.probe_resp.variable; ++ ielen = len - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); ++ beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); ++ capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); ++ /* framework use system bootup time */ ++ bss = cfg80211_inform_bss(rwnx_hw->wiphy, chan, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) ++ CFG80211_BSS_FTYPE_UNKNOWN, ++#endif ++ mgmt->bssid, tsf, capability, beacon_interval, ++ ie, ielen, ind->rssi * 100, GFP_ATOMIC); ++ } ++ ++ if (bss != NULL) ++ cfg80211_put_bss(rwnx_hw->wiphy, bss); ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from ME task ++ **************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline int rwnx_rx_me_tkip_mic_failure_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct me_tkip_mic_failure_ind *ind = (struct me_tkip_mic_failure_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct net_device *dev = rwnx_vif->ndev; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ cfg80211_michael_mic_failure(dev, (u8 *)&ind->addr, (ind->ga ? NL80211_KEYTYPE_GROUP : ++ NL80211_KEYTYPE_PAIRWISE), ind->keyid, ++ (u8 *)&ind->tsc, GFP_ATOMIC); ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_me_tx_credits_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct me_tx_credits_update_ind *ind = (struct me_tx_credits_update_ind *)msg->param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_txq_credit_update(rwnx_hw, ind->sta_idx, ind->tid, ind->credits); ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from SM task ++ **************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct sm_connect_ind *ind = (struct sm_connect_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct net_device *dev = rwnx_vif->ndev; ++ const u8 *req_ie, *rsp_ie; ++ const u8 *extcap_ie; ++ const struct ieee_types_extcap *extcap; ++ struct ieee80211_channel *chan; ++ //struct cfg80211_bss *bss = NULL; ++ struct wireless_dev *wdev = NULL; ++ //int retry_counter = 10; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ wdev = dev->ieee80211_ptr; ++ ++ /* Retrieve IE addresses and lengths */ ++ req_ie = (const u8 *)ind->assoc_ie_buf; ++ rsp_ie = req_ie + ind->assoc_req_ie_len; ++ ++ // Fill-in the AP information ++ AICWFDBG(LOGINFO, "%s ind->status_code:%d \r\n", __func__, ind->status_code); ++ ++ if (ind->status_code == 0) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[ind->ap_idx]; ++ u8 txq_status; ++ struct cfg80211_chan_def chandef; ++ ++ sta->valid = true; ++ sta->sta_idx = ind->ap_idx; ++ sta->ch_idx = ind->ch_idx; ++ sta->vif_idx = ind->vif_idx; ++ sta->vlan_idx = sta->vif_idx; ++ sta->qos = ind->qos; ++ sta->acm = ind->acm; ++ sta->ps.active = false; ++ sta->aid = ind->aid; ++ sta->band = ind->band;//ind->chan.band; ++ sta->width = ind->width;//ind->chan.type; ++ sta->center_freq = ind->center_freq;//ind->chan.prim20_freq; ++ sta->center_freq1 = ind->center_freq1;//ind->chan.center1_freq; ++ sta->center_freq2 = ind->center_freq2;//ind->chan.center2_freq; ++ rwnx_vif->sta.ap = sta; ++ chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq);//ind->chan.prim20_freq); ++ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); ++ if (!rwnx_hw->mod_params->ht_on) ++ chandef.width = NL80211_CHAN_WIDTH_20_NOHT; ++ else ++ chandef.width = chnl2bw[ind->width];//[ind->chan.type]; ++ chandef.center_freq1 = ind->center_freq1;//ind->chan.center1_freq; ++ chandef.center_freq2 = ind->center_freq2;//ind->chan.center2_freq; ++ rwnx_chanctx_link(rwnx_vif, ind->ch_idx, &chandef); ++ memcpy(sta->mac_addr, ind->bssid.array, ETH_ALEN); ++ if (ind->ch_idx == rwnx_hw->cur_chanctx) { ++ txq_status = 0; ++ } else { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ memcpy(sta->ac_param, ind->ac_param, sizeof(sta->ac_param)); ++ rwnx_txq_sta_init(rwnx_hw, sta, txq_status); ++ rwnx_txq_tdls_vif_init(rwnx_vif); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, sta); ++#endif ++ rwnx_mu_group_sta_init(sta, NULL); ++ /* Look for TDLS Channel Switch Prohibited flag in the Extended Capability ++ * Information Element*/ ++ extcap_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, rsp_ie, ind->assoc_rsp_ie_len); ++ if (extcap_ie && extcap_ie[1] >= 5) { ++ extcap = (void *)(extcap_ie); ++ rwnx_vif->tdls_chsw_prohibited = extcap->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED; ++ } ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ if (chan->flags & IEEE80211_CHAN_RADAR) ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_REPORT, ++ RWNX_RADAR_RIU); ++#endif ++ ++ if (rwnx_vif->wep_enabled) ++ rwnx_vif->wep_auth_err = false; ++ ++#ifdef CONFIG_RWNX_BFMER ++ /* If Beamformer feature is activated, check if features can be used ++ * with the new peer device ++ */ ++ if (rwnx_hw->mod_params->bfmer) { ++ const u8 *vht_capa_ie; ++ const struct ieee80211_vht_cap *vht_cap; ++ ++ do { ++ /* Look for VHT Capability Information Element */ ++ vht_capa_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, rsp_ie, ++ ind->assoc_rsp_ie_len); ++ ++ /* Stop here if peer device does not support VHT */ ++ if (!vht_capa_ie) { ++ break; ++ } ++ ++ vht_cap = (const struct ieee80211_vht_cap *)(vht_capa_ie + 2); ++ ++ /* Send MM_BFMER_ENABLE_REQ message if needed */ ++ rwnx_send_bfmer_enable(rwnx_hw, sta, vht_cap); ++ } while (0); ++ } ++#endif //(CONFIG_RWNX_BFMER) ++ ++#ifdef CONFIG_RWNX_MON_DATA ++ // If there are 1 sta and 1 monitor interface active at the same time then ++ // monitor interface channel context is always the same as the STA interface. ++ // This doesn't work with 2 STA interfaces but we don't want to support it. ++ if (rwnx_hw->monitor_vif != RWNX_INVALID_VIF) { ++ struct rwnx_vif *rwnx_mon_vif = rwnx_hw->vif_table[rwnx_hw->monitor_vif]; ++ rwnx_chanctx_unlink(rwnx_mon_vif); ++ rwnx_chanctx_link(rwnx_mon_vif, ind->ch_idx, NULL); ++ } ++#endif ++ //atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ } else if (ind->status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { ++ if (rwnx_vif->wep_enabled) { ++ rwnx_vif->wep_auth_err = true; ++ AICWFDBG(LOGINFO, "con ind wep_auth_err %d\n", rwnx_vif->wep_auth_err); ++ } ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ }else{ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ } ++ ++ AICWFDBG(LOGINFO, "%s ind->roamed:%d ind->status_code:%d rwnx_vif->drv_conn_state:%d\r\n", ++ __func__, ++ ind->roamed, ++ ind->status_code, ++ (int)atomic_read(&rwnx_vif->drv_conn_state)); ++ ++ if(ind->status_code == 0 && (int)atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTING){ ++ AICWFDBG(LOGINFO, "%s the disconnection has been requested, return it\r\n", __func__); ++ goto exit; ++ } ++ ++ if (!ind->roamed){//not roaming ++ cfg80211_connect_result(dev, (const u8 *)ind->bssid.array, req_ie, ++ ind->assoc_req_ie_len, rsp_ie, ++ ind->assoc_rsp_ie_len, ind->status_code, ++ GFP_ATOMIC); ++ if (ind->status_code == 0) { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ AICWFDBG(LOGINFO, "%s cfg80211_connect_result pass, rwnx_vif->drv_conn_state:%d\r\n", ++ __func__, ++ (int)atomic_read(&rwnx_vif->drv_conn_state)); ++ } else { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ } ++ ++ }else {//roaming ++ if(ind->status_code != 0){ ++ AICWFDBG(LOGINFO, "%s roaming fail to notify disconnect \r\n", __func__); ++ cfg80211_disconnected(dev, 0, NULL, 0,1, GFP_ATOMIC); ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ }else{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ struct cfg80211_roam_info info; ++ memset(&info, 0, sizeof(info)); ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ if (rwnx_vif->ch_index < NX_CHAN_CTXT_CNT) ++ info.links[0].channel = rwnx_hw->chanctx_table[rwnx_vif->ch_index].chan_def.chan; ++ info.links[0].bssid = (const u8 *)ind->bssid.array; ++#else ++ if (rwnx_vif->ch_index < NX_CHAN_CTXT_CNT) ++ info.channel = rwnx_hw->chanctx_table[rwnx_vif->ch_index].chan_def.chan; ++ info.bssid = (const u8 *)ind->bssid.array; ++#endif ++ info.req_ie = req_ie; ++ info.req_ie_len = ind->assoc_req_ie_len; ++ info.resp_ie = rsp_ie; ++ info.resp_ie_len = ind->assoc_rsp_ie_len; ++ cfg80211_roamed(dev, &info, GFP_ATOMIC); ++#else ++ chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq); ++ cfg80211_roamed(dev ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE) ++ , chan ++#endif ++ , (const u8 *)ind->bssid.array ++ , req_ie ++ , ind->assoc_req_ie_len ++ , rsp_ie ++ , ind->assoc_rsp_ie_len ++ , GFP_ATOMIC); ++ ++#endif /*LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)*/ ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ } ++ rwnx_vif->sta.is_roam = false; ++ } ++ ++ if (ind->status_code == 0) { ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ } ++ ++exit: ++ rwnx_vif->sta.is_roam = false; ++ return 0; ++} ++ ++void rwnx_cfg80211_unlink_bss(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif){ ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ struct cfg80211_bss *bss = NULL; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/, ++ rwnx_vif->sta.bssid, rwnx_vif->sta.ssid, ++ rwnx_vif->sta.ssid_len, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) ++ IEEE80211_BSS_TYPE_ESS, ++ IEEE80211_PRIVACY(true));//temp set true ++#else ++ WLAN_CAPABILITY_ESS, ++ WLAN_CAPABILITY_ESS); ++#endif ++ ++ if (bss) { ++ cfg80211_unlink_bss(wiphy, bss); ++ AICWFDBG(LOGINFO, "%s(): cfg80211_unlink %s!!\n", __func__, rwnx_vif->sta.ssid); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) ++ cfg80211_put_bss(wiphy, bss); ++#else ++ cfg80211_put_bss(bss); ++#endif ++ }else{ ++ AICWFDBG(LOGINFO, "%s(): cfg80211_unlink error %s!!\n", __func__, rwnx_vif->sta.ssid); ++ } ++} ++ ++extern u8 dhcped; ++static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct sm_disconnect_ind *ind = (struct sm_disconnect_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct net_device *dev; ++#ifdef AICWF_RX_REORDER ++ struct reord_ctrl_info *reord_info, *tmp; ++ u8 *macaddr; ++ struct aicwf_rx_priv *rx_priv; ++#endif ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ AICWFDBG(LOGINFO, "%s reason code:%d \r\n", __func__, ind->reason_code); ++ ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTED){ ++ AICWFDBG(LOGINFO, "%s, is already disconnected, drop disconnect ind", __func__); ++ return 0; ++ } ++ ++ dhcped = 0; ++ ++ if(!rwnx_vif) ++ return 0; ++ dev = rwnx_vif->ndev; ++ ++ if (rwnx_vif->sta.is_roam == false) { ++ rwnx_cfg80211_unlink_bss(rwnx_hw, rwnx_vif); ++ } else { ++ AICWFDBG(LOGINFO, "%s roaming no rwnx_cfg80211_unlink_bss \r\n", __func__); ++ } ++ ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.ap); ++#endif ++ ++ #ifdef CONFIG_BR_SUPPORT ++ struct rwnx_vif *vif = netdev_priv(dev); ++ /* clear bridge database */ ++ nat25_db_cleanup(rwnx_vif); ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ++ rwnx_hw->is_p2p_connected = 0; ++ /* if vif is not up, rwnx_close has already been called */ ++ if (rwnx_vif->up) { ++ if (!ind->ft_over_ds && !ind->reassoc) { ++ cfg80211_disconnected(dev, ind->reason_code, NULL, 0, ++ (ind->reason_code < 1), GFP_ATOMIC); ++ } ++ netif_tx_stop_all_queues(dev); ++ netif_carrier_off(dev); ++ } ++ ++#ifdef CONFIG_RWNX_BFMER ++ /* Disable Beamformer if supported */ ++ rwnx_bfmer_report_del(rwnx_hw, rwnx_vif->sta.ap); ++#endif //(CONFIG_RWNX_BFMER) ++ ++#ifdef AICWF_RX_REORDER ++#ifdef AICWF_SDIO_SUPPORT ++ rx_priv = rwnx_hw->sdiodev->rx_priv; ++#else ++ rx_priv = rwnx_hw->usbdev->rx_priv; ++#endif ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ macaddr = (u8*)rwnx_vif->ndev->dev_addr; ++ printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0], macaddr[1], macaddr[2], \ ++ macaddr[3], macaddr[4], macaddr[5]); ++ ++ //spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry_safe(reord_info, tmp, &rx_priv->stas_reord_list, list) { ++ macaddr = (u8*)rwnx_vif->ndev->dev_addr; ++ printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0], reord_info->mac_addr[1], reord_info->mac_addr[2], \ ++ reord_info->mac_addr[3], reord_info->mac_addr[4], reord_info->mac_addr[5]); ++ if (!memcmp(reord_info->mac_addr, macaddr, 6)) { ++ reord_deinit_sta(rx_priv, reord_info); ++ break; ++ } ++ } ++ //spin_unlock_bh(&rx_priv->stas_reord_lock); ++ } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { ++ BUG();//should be not here: del_sta function ++ } ++#endif ++ ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_vif->sta.ap); ++ rwnx_txq_tdls_vif_deinit(rwnx_vif); ++ #if 0 ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.ap); ++ #endif ++ rwnx_vif->sta.ap->valid = false; ++ rwnx_vif->sta.ap = NULL; ++ rwnx_external_auth_disable(rwnx_vif); ++ rwnx_chanctx_unlink(rwnx_vif); ++ ++ //msleep(200); ++ if (rwnx_vif->sta.is_roam == false) { ++ rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_sm_external_auth_required_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct sm_external_auth_required_ind *ind = ++ (struct sm_external_auth_required_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) ++ struct net_device *dev = rwnx_vif->ndev; ++ struct cfg80211_external_auth_params params; ++ int ret = 0; ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ int retry_counter = 10; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ memset((void*)¶ms, 0, sizeof(struct cfg80211_external_auth_params)); ++ ++ params.action = NL80211_EXTERNAL_AUTH_START; ++ memcpy(params.bssid, ind->bssid.array, ETH_ALEN); ++ params.ssid.ssid_len = ind->ssid.length; ++ memcpy(params.ssid.ssid, ind->ssid.array, ++ min_t(size_t, ind->ssid.length, sizeof(params.ssid.ssid))); ++ params.key_mgmt_suite = ind->akm; ++ ++ while (wdev->conn_owner_nlportid == 0) { ++ AICWFDBG(LOGINFO, "%s WARNING conn_owner_nlportid = 0, msleep 100ms.\r\n", __func__); ++ msleep(100); ++ retry_counter--; ++ if (retry_counter == 0) { ++ break; ++ } ++ } ++ AICWFDBG(LOGINFO, "%s wdev->conn_owner_nlportid:%d \r\n", __func__, (int)wdev->conn_owner_nlportid); ++ ++ if ((ind->vif_idx > NX_VIRT_DEV_MAX) || !rwnx_vif->up || ++ (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_STATION) || ++ (ret = cfg80211_external_auth_request(dev, ¶ms, GFP_ATOMIC))) { ++ wiphy_err(rwnx_hw->wiphy, "Failed to start external auth on vif %d, rwnx_vif->up %d, iftype:%d, ret %d", ++ ind->vif_idx, rwnx_vif->up, RWNX_VIF_TYPE(rwnx_vif), ret); ++ rwnx_send_sm_external_auth_required_rsp(rwnx_hw, rwnx_vif, ++ WLAN_STATUS_UNSPECIFIED_FAILURE); ++ return 0; ++ } ++ ++ rwnx_external_auth_enable(rwnx_vif); ++#else ++ rwnx_send_sm_external_auth_required_rsp(rwnx_hw, rwnx_vif, ++ WLAN_STATUS_UNSPECIFIED_FAILURE); ++#endif ++ return 0; ++} ++ ++ ++static inline int rwnx_rx_mesh_path_create_cfm(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_path_create_cfm *cfm = (struct mesh_path_create_cfm *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[cfm->vif_idx]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Check we well have a Mesh Point Interface */ ++ if (rwnx_vif && (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT)) { ++ rwnx_vif->ap.create_path = false; ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_mesh_peer_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_peer_update_ind *ind = (struct mesh_peer_update_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct rwnx_sta *rwnx_sta = &rwnx_hw->sta_table[ind->sta_idx]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if ((ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) || ++ (rwnx_vif && (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT)) || ++ (ind->sta_idx >= NX_REMOTE_STA_MAX)) ++ return 1; ++ ++ /* Check we well have a Mesh Point Interface */ ++ if (!rwnx_vif->user_mpm) { ++ /* Check if peer link has been established or lost */ ++ if (ind->estab) { ++ if (!rwnx_sta->valid) { ++ u8 txq_status; ++ ++ rwnx_sta->valid = true; ++ rwnx_sta->sta_idx = ind->sta_idx; ++ rwnx_sta->ch_idx = rwnx_vif->ch_index; ++ rwnx_sta->vif_idx = ind->vif_idx; ++ rwnx_sta->vlan_idx = rwnx_sta->vif_idx; ++ rwnx_sta->ps.active = false; ++ rwnx_sta->qos = true; ++ rwnx_sta->aid = ind->sta_idx + 1; ++ //rwnx_sta->acm = ind->acm; ++ memcpy(rwnx_sta->mac_addr, ind->peer_addr.array, ETH_ALEN); ++ ++ rwnx_chanctx_link(rwnx_vif, rwnx_sta->ch_idx, NULL); ++ ++ /* Add the station in the list of VIF's stations */ ++ INIT_LIST_HEAD(&rwnx_sta->list); ++ list_add_tail(&rwnx_sta->list, &rwnx_vif->ap.sta_list); ++ ++ /* Initialize the TX queues */ ++ if (rwnx_sta->ch_idx == rwnx_hw->cur_chanctx) { ++ txq_status = 0; ++ } else { ++ txq_status = RWNX_TXQ_STOP_CHAN; ++ } ++ ++ rwnx_txq_sta_init(rwnx_hw, rwnx_sta, txq_status); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_register_rc_stat(rwnx_hw, rwnx_sta); ++#endif ++#ifdef CONFIG_RWNX_BFMER ++ // TODO: update indication to contains vht capabilties ++ if (rwnx_hw->mod_params->bfmer) ++ rwnx_send_bfmer_enable(rwnx_hw, rwnx_sta, NULL); ++ ++ rwnx_mu_group_sta_init(rwnx_sta, NULL); ++#endif /* CONFIG_RWNX_BFMER */ ++ ++ } else { ++ WARN_ON(0); ++ } ++ } else { ++ if (rwnx_sta->valid) { ++ rwnx_sta->ps.active = false; ++ rwnx_sta->valid = false; ++ ++ /* Remove the station from the list of VIF's station */ ++ list_del_init(&rwnx_sta->list); ++ ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_sta); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_sta); ++#endif ++ } else { ++ WARN_ON(0); ++ } ++ } ++ } else { ++ if (!ind->estab && rwnx_sta->valid) { ++ /* There is no way to inform upper layer for lost of peer, still ++ clean everything in the driver */ ++ rwnx_sta->ps.active = false; ++ rwnx_sta->valid = false; ++ ++ /* Remove the station from the list of VIF's station */ ++ list_del_init(&rwnx_sta->list); ++ ++ rwnx_txq_sta_deinit(rwnx_hw, rwnx_sta); ++#ifdef CONFIG_DEBUG_FS ++ rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_sta); ++#endif ++ } else { ++ WARN_ON(0); ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_mesh_path_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_path_update_ind *ind = (struct mesh_path_update_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct rwnx_mesh_path *mesh_path; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) ++ return 1; ++ ++ if (!rwnx_vif || (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT)) ++ return 0; ++ ++ /* Look for path with provided target address */ ++ list_for_each_entry(mesh_path, &rwnx_vif->ap.mpath_list, list) { ++ if (mesh_path->path_idx == ind->path_idx) { ++ found = true; ++ break; ++ } ++ } ++ ++ /* Check if element has been deleted */ ++ if (ind->delete) { ++ if (found) { ++#ifdef CREATE_TRACE_POINTS ++ trace_mesh_delete_path(mesh_path); ++#endif ++ /* Remove element from list */ ++ list_del_init(&mesh_path->list); ++ /* Free the element */ ++ kfree(mesh_path); ++ } ++ } else { ++ if (found) { ++ // Update the Next Hop STA ++ mesh_path->p_nhop_sta = &rwnx_hw->sta_table[ind->nhop_sta_idx]; ++#ifdef CREATE_TRACE_POINTS ++ trace_mesh_update_path(mesh_path); ++#endif ++ } else { ++ // Allocate a Mesh Path structure ++ mesh_path = (struct rwnx_mesh_path *)kmalloc(sizeof(struct rwnx_mesh_path), GFP_ATOMIC); ++ ++ if (mesh_path) { ++ INIT_LIST_HEAD(&mesh_path->list); ++ ++ mesh_path->path_idx = ind->path_idx; ++ mesh_path->p_nhop_sta = &rwnx_hw->sta_table[ind->nhop_sta_idx]; ++ memcpy(&mesh_path->tgt_mac_addr, &ind->tgt_mac_addr, MAC_ADDR_LEN); ++ ++ // Insert the path in the list of path ++ list_add_tail(&mesh_path->list, &rwnx_vif->ap.mpath_list); ++#ifdef CREATE_TRACE_POINTS ++ trace_mesh_create_path(mesh_path); ++#endif ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int rwnx_rx_mesh_proxy_update_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ struct mesh_proxy_update_ind *ind = (struct mesh_proxy_update_ind *)msg->param; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; ++ struct rwnx_mesh_proxy *mesh_proxy; ++ bool found = false; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) ++ return 1; ++ ++ if (!rwnx_vif || (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT)) ++ return 0; ++ ++ /* Look for path with provided external STA address */ ++ list_for_each_entry(mesh_proxy, &rwnx_vif->ap.proxy_list, list) { ++ if (!memcmp(&ind->ext_sta_addr, &mesh_proxy->ext_sta_addr, ETH_ALEN)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (ind->delete && found) { ++ /* Delete mesh path */ ++ list_del_init(&mesh_proxy->list); ++ kfree(mesh_proxy); ++ } else if (!ind->delete && !found) { ++ /* Allocate a Mesh Path structure */ ++ mesh_proxy = (struct rwnx_mesh_proxy *)kmalloc(sizeof(*mesh_proxy), ++ GFP_ATOMIC); ++ ++ if (mesh_proxy) { ++ INIT_LIST_HEAD(&mesh_proxy->list); ++ ++ memcpy(&mesh_proxy->ext_sta_addr, &ind->ext_sta_addr, MAC_ADDR_LEN); ++ mesh_proxy->local = ind->local; ++ ++ if (!ind->local) { ++ memcpy(&mesh_proxy->proxy_addr, &ind->proxy_mac_addr, MAC_ADDR_LEN); ++ } ++ ++ /* Insert the path in the list of path */ ++ list_add_tail(&mesh_proxy->list, &rwnx_vif->ap.proxy_list); ++ } ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/*************************************************************************** ++ * Messages from APM task ++ **************************************************************************/ ++ ++ ++/*************************************************************************** ++ * Messages from DEBUG task ++ **************************************************************************/ ++static inline int rwnx_rx_dbg_error_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_MCU_MESSAGE ++static inline int rwnx_rx_dbg_custmsg_ind(struct rwnx_hw *rwnx_hw, ++ struct rwnx_cmd *cmd, ++ struct ipc_e2a_msg *msg) ++{ ++ dbg_custom_msg_ind_t * ind; ++ char str_msg[32 + 1]; ++ int str_len; ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ ind = (dbg_custom_msg_ind_t *)msg->param; ++ str_len = (ind->len < 32) ? ind->len : 32; ++ memcpy(str_msg, (char *)ind->buf, str_len); ++ str_msg[str_len] = '\0'; ++ printk("CustMsgInd: cmd=0x%x, len=%d, str=%s\r\n", ind->cmd, ind->len, str_msg); ++ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++static msg_cb_fct mm_hdlrs[MSG_I(MM_MAX)] = { ++ [MSG_I(MM_CHANNEL_SWITCH_IND)] = rwnx_rx_chan_switch_ind, ++ [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = rwnx_rx_chan_pre_switch_ind, ++ [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = rwnx_rx_remain_on_channel_exp_ind, ++ [MSG_I(MM_PS_CHANGE_IND)] = rwnx_rx_ps_change_ind, ++ [MSG_I(MM_TRAFFIC_REQ_IND)] = rwnx_rx_traffic_req_ind, ++ [MSG_I(MM_P2P_VIF_PS_CHANGE_IND)] = rwnx_rx_p2p_vif_ps_change_ind, ++ [MSG_I(MM_CSA_COUNTER_IND)] = rwnx_rx_csa_counter_ind, ++ [MSG_I(MM_CSA_FINISH_IND)] = rwnx_rx_csa_finish_ind, ++ [MSG_I(MM_CSA_TRAFFIC_IND)] = rwnx_rx_csa_traffic_ind, ++ [MSG_I(MM_CHANNEL_SURVEY_IND)] = rwnx_rx_channel_survey_ind, ++ [MSG_I(MM_P2P_NOA_UPD_IND)] = rwnx_rx_p2p_noa_upd_ind, ++ [MSG_I(MM_RSSI_STATUS_IND)] = rwnx_rx_rssi_status_ind, ++ [MSG_I(MM_PKTLOSS_IND)] = rwnx_rx_pktloss_notify_ind, ++ [MSG_I(MM_APM_STALOSS_IND)] = rwnx_apm_staloss_ind, ++ [MSG_I(MM_RADAR_DETECT_IND)] = rwnx_radar_detect_ind, ++}; ++ ++static msg_cb_fct scan_hdlrs[MSG_I(SCANU_MAX)] = { ++ [MSG_I(SCANU_START_CFM)] = rwnx_rx_scanu_start_cfm, ++ [MSG_I(SCANU_RESULT_IND)] = rwnx_rx_scanu_result_ind, ++}; ++ ++static msg_cb_fct me_hdlrs[MSG_I(ME_MAX)] = { ++ [MSG_I(ME_TKIP_MIC_FAILURE_IND)] = rwnx_rx_me_tkip_mic_failure_ind, ++ [MSG_I(ME_TX_CREDITS_UPDATE_IND)] = rwnx_rx_me_tx_credits_update_ind, ++}; ++ ++static msg_cb_fct sm_hdlrs[MSG_I(SM_MAX)] = { ++ [MSG_I(SM_CONNECT_IND)] = rwnx_rx_sm_connect_ind, ++ [MSG_I(SM_DISCONNECT_IND)] = rwnx_rx_sm_disconnect_ind, ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_IND)] = rwnx_rx_sm_external_auth_required_ind, ++}; ++ ++static msg_cb_fct apm_hdlrs[MSG_I(APM_MAX)] = { ++}; ++ ++static msg_cb_fct mesh_hdlrs[MSG_I(MESH_MAX)] = { ++ [MSG_I(MESH_PATH_CREATE_CFM)] = rwnx_rx_mesh_path_create_cfm, ++ [MSG_I(MESH_PEER_UPDATE_IND)] = rwnx_rx_mesh_peer_update_ind, ++ [MSG_I(MESH_PATH_UPDATE_IND)] = rwnx_rx_mesh_path_update_ind, ++ [MSG_I(MESH_PROXY_UPDATE_IND)] = rwnx_rx_mesh_proxy_update_ind, ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = { ++ [MSG_I(DBG_ERROR_IND)] = rwnx_rx_dbg_error_ind, ++#ifdef CONFIG_MCU_MESSAGE ++ [MSG_I(DBG_CUSTOM_MSG_IND)] = rwnx_rx_dbg_custmsg_ind, ++#endif ++}; ++ ++static msg_cb_fct tdls_hdlrs[MSG_I(TDLS_MAX)] = { ++ [MSG_I(TDLS_CHAN_SWITCH_CFM)] = rwnx_rx_tdls_chan_switch_cfm, ++ [MSG_I(TDLS_CHAN_SWITCH_IND)] = rwnx_rx_tdls_chan_switch_ind, ++ [MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = rwnx_rx_tdls_chan_switch_base_ind, ++ [MSG_I(TDLS_PEER_PS_IND)] = rwnx_rx_tdls_peer_ps_ind, ++#ifdef CONFIG_SDIO_BT ++ [MSG_I(TDLS_SDIO_BT_RECV_IND)] = rwnx_bt_recv_ind, ++#endif ++}; ++ ++static msg_cb_fct *msg_hdlrs[] = { ++ [TASK_MM] = mm_hdlrs, ++ [TASK_DBG] = dbg_hdlrs, ++#ifdef CONFIG_RWNX_FULLMAC ++ [TASK_TDLS] = tdls_hdlrs, ++ [TASK_SCANU] = scan_hdlrs, ++ [TASK_ME] = me_hdlrs, ++ [TASK_SM] = sm_hdlrs, ++ [TASK_APM] = apm_hdlrs, ++ [TASK_MESH] = mesh_hdlrs, ++#endif /* CONFIG_RWNX_FULLMAC */ ++}; ++ ++/** ++ * ++ */ ++void rwnx_rx_handle_msg(struct rwnx_hw *rwnx_hw, struct ipc_e2a_msg *msg) ++{ ++ AICWFDBG(LOGDEBUG, "%s msg->id:0x%x \r\n", __func__, msg->id); ++ ++ rwnx_hw->cmd_mgr->msgind(rwnx_hw->cmd_mgr, msg, ++ msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]); ++} ++ ++void rwnx_rx_handle_print(struct rwnx_hw *rwnx_hw, u8 *msg, u32 len) ++{ ++ u8 *data_end = NULL; ++ (void)data_end; ++ ++ if (!rwnx_hw || !rwnx_hw->fwlog_en) { ++ pr_err("FWLOG-OVFL: %s", msg); ++ return; ++ } ++ ++ printk("FWLOG: %s", msg); ++ ++#ifdef CONFIG_RWNX_DEBUGFS ++ data_end = rwnx_hw->debugfs.fw_log.buf.dataend; ++ ++ if (!rwnx_hw->debugfs.fw_log.buf.data) ++ return ; ++ ++ //printk("end=%lx, len=%d\n", (unsigned long)rwnx_hw->debugfs.fw_log.buf.end, len); ++ ++ spin_lock_bh(&rwnx_hw->debugfs.fw_log.lock); ++ ++ if (rwnx_hw->debugfs.fw_log.buf.end + len > data_end) { ++ int rem = data_end - rwnx_hw->debugfs.fw_log.buf.end; ++ memcpy(rwnx_hw->debugfs.fw_log.buf.end, msg, rem); ++ memcpy(rwnx_hw->debugfs.fw_log.buf.data, &msg[rem], len - rem); ++ rwnx_hw->debugfs.fw_log.buf.end = rwnx_hw->debugfs.fw_log.buf.data + (len - rem); ++ } else { ++ memcpy(rwnx_hw->debugfs.fw_log.buf.end, msg, len); ++ rwnx_hw->debugfs.fw_log.buf.end += len; ++ } ++ ++ rwnx_hw->debugfs.fw_log.buf.size += len; ++ if (rwnx_hw->debugfs.fw_log.buf.size > FW_LOG_SIZE) ++ rwnx_hw->debugfs.fw_log.buf.size = FW_LOG_SIZE; ++ ++ spin_unlock_bh(&rwnx_hw->debugfs.fw_log.lock); ++#endif ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h +new file mode 100644 +index 000000000000..b5556d160ff0 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h +@@ -0,0 +1,19 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_msg_rx.h ++ * ++ * @brief RX function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_MSG_RX_H_ ++#define _RWNX_MSG_RX_H_ ++ ++void rwnx_rx_handle_msg(struct rwnx_hw *rwnx_hw, struct ipc_e2a_msg *msg); ++void rwnx_rx_handle_print(struct rwnx_hw *rwnx_hw, u8 *msg, u32 len); ++ ++#endif /* _RWNX_MSG_RX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c +new file mode 100644 +index 000000000000..849a8ea709e3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c +@@ -0,0 +1,4185 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_msg_tx.c ++ * ++ * @brief TX function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_msg_tx.h" ++#include "rwnx_mod_params.h" ++#include "reg_access.h" ++#ifdef CONFIG_RWNX_BFMER ++#include "rwnx_bfmer.h" ++#endif //(CONFIG_RWNX_BFMER) ++#include "rwnx_compat.h" ++#include "rwnx_cmds.h" ++#include "aicwf_txrxif.h" ++#include "rwnx_strs.h" ++#include "rwnx_main.h" ++#include "rwnx_wakelock.h" ++ ++const struct mac_addr mac_addr_bcst = {{0xFFFF, 0xFFFF, 0xFFFF}}; ++ ++/* Default MAC Rx filters that can be changed by mac80211 ++ * (via the configure_filter() callback) */ ++#define RWNX_MAC80211_CHANGEABLE ( \ ++ NXMAC_ACCEPT_BA_BIT | \ ++ NXMAC_ACCEPT_BAR_BIT | \ ++ NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT | \ ++ NXMAC_ACCEPT_PROBE_REQ_BIT | \ ++ NXMAC_ACCEPT_PS_POLL_BIT \ ++ ) ++ ++/* Default MAC Rx filters that cannot be changed by mac80211 */ ++#define RWNX_MAC80211_NOT_CHANGEABLE ( \ ++ NXMAC_ACCEPT_QO_S_NULL_BIT | \ ++ NXMAC_ACCEPT_Q_DATA_BIT | \ ++ NXMAC_ACCEPT_DATA_BIT | \ ++ NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT | \ ++ NXMAC_ACCEPT_MY_UNICAST_BIT | \ ++ NXMAC_ACCEPT_BROADCAST_BIT | \ ++ NXMAC_ACCEPT_BEACON_BIT | \ ++ NXMAC_ACCEPT_PROBE_RESP_BIT \ ++ ) ++ ++/* Default MAC Rx filter */ ++#define RWNX_DEFAULT_RX_FILTER (RWNX_MAC80211_CHANGEABLE | RWNX_MAC80211_NOT_CHANGEABLE) ++ ++const int bw2chnl[] = { ++ [NL80211_CHAN_WIDTH_20_NOHT] = PHY_CHNL_BW_20, ++ [NL80211_CHAN_WIDTH_20] = PHY_CHNL_BW_20, ++ [NL80211_CHAN_WIDTH_40] = PHY_CHNL_BW_40, ++ [NL80211_CHAN_WIDTH_80] = PHY_CHNL_BW_80, ++ [NL80211_CHAN_WIDTH_160] = PHY_CHNL_BW_160, ++ [NL80211_CHAN_WIDTH_80P80] = PHY_CHNL_BW_80P80, ++}; ++ ++const int chnl2bw[] = { ++ [PHY_CHNL_BW_20] = NL80211_CHAN_WIDTH_20, ++ [PHY_CHNL_BW_40] = NL80211_CHAN_WIDTH_40, ++ [PHY_CHNL_BW_80] = NL80211_CHAN_WIDTH_80, ++ [PHY_CHNL_BW_160] = NL80211_CHAN_WIDTH_160, ++ [PHY_CHNL_BW_80P80] = NL80211_CHAN_WIDTH_80P80, ++}; ++ ++#define RWNX_CMD_ARRAY_SIZE 40 ++#define RWNX_CMD_HIGH_WATER_SIZE RWNX_CMD_ARRAY_SIZE/2 ++ ++struct rwnx_cmd cmd_array[RWNX_CMD_ARRAY_SIZE]; ++static spinlock_t cmd_array_lock; ++int cmd_array_index = 0; ++ ++ ++ ++/*****************************************************************************/ ++/* ++ * Parse the ampdu density to retrieve the value in usec, according to the ++ * values defined in ieee80211.h ++ */ ++static inline u8 rwnx_ampdudensity2usec(u8 ampdudensity) ++{ ++ switch (ampdudensity) { ++ case IEEE80211_HT_MPDU_DENSITY_NONE: ++ return 0; ++ /* 1 microsecond is our granularity */ ++ case IEEE80211_HT_MPDU_DENSITY_0_25: ++ case IEEE80211_HT_MPDU_DENSITY_0_5: ++ case IEEE80211_HT_MPDU_DENSITY_1: ++ return 1; ++ case IEEE80211_HT_MPDU_DENSITY_2: ++ return 2; ++ case IEEE80211_HT_MPDU_DENSITY_4: ++ return 4; ++ case IEEE80211_HT_MPDU_DENSITY_8: ++ return 8; ++ case IEEE80211_HT_MPDU_DENSITY_16: ++ return 16; ++ default: ++ return 0; ++ } ++} ++ ++static inline bool use_pairwise_key(struct cfg80211_crypto_settings *crypto) ++{ ++ if ((crypto->cipher_group == WLAN_CIPHER_SUITE_WEP40) || ++ (crypto->cipher_group == WLAN_CIPHER_SUITE_WEP104)) ++ return false; ++ ++ return true; ++} ++ ++static inline bool is_non_blocking_msg(int id) ++{ ++ return ((id == MM_TIM_UPDATE_REQ) || (id == ME_RC_SET_RATE_REQ) || ++ (id == MM_BFMER_ENABLE_REQ) || (id == ME_TRAFFIC_IND_REQ) || ++ (id == TDLS_PEER_TRAFFIC_IND_REQ) || ++ (id == MESH_PATH_CREATE_REQ) || (id == MESH_PROXY_ADD_REQ) || ++ (id == SM_EXTERNAL_AUTH_REQUIRED_RSP)); ++} ++ ++static inline u8_l get_chan_flags(uint32_t flags) ++{ ++ u8_l chan_flags = 0; ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) ++ if (flags & IEEE80211_CHAN_PASSIVE_SCAN) ++ #else ++ if (flags & IEEE80211_CHAN_NO_IR) ++ #endif ++ chan_flags |= CHAN_NO_IR; ++ if (flags & IEEE80211_CHAN_RADAR) ++ chan_flags |= CHAN_RADAR; ++#endif ++ return chan_flags; ++} ++ ++static inline s8_l chan_to_fw_pwr(int power) ++{ ++ return power > 127 ? 127 : (s8_l)power; ++} ++ ++static inline void limit_chan_bw(u8_l *bw, u16_l primary, u16_l *center1) ++{ ++ int oft, new_oft = 10; ++ ++ if (*bw <= PHY_CHNL_BW_40) ++ return; ++ ++ oft = *center1 - primary; ++ *bw = PHY_CHNL_BW_40; ++ ++ if (oft < 0) ++ new_oft = new_oft * -1; ++ if (abs(oft) == 10 || abs(oft) == 50) ++ new_oft = new_oft * -1; ++ ++ *center1 = primary + new_oft; ++} ++ ++struct rwnx_cmd *rwnx_cmd_malloc(void){ ++ struct rwnx_cmd *cmd = NULL; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&cmd_array_lock, flags); ++ ++ for(cmd_array_index = 0; cmd_array_index < RWNX_CMD_ARRAY_SIZE; cmd_array_index++){ ++ if(cmd_array[cmd_array_index].used == 0){ ++ AICWFDBG(LOGTRACE, "%s get cmd_array[%d]:%p \r\n", __func__, cmd_array_index,&cmd_array[cmd_array_index]); ++ cmd = &cmd_array[cmd_array_index]; ++ cmd_array[cmd_array_index].used = 1; ++ break; ++ } ++ } ++ ++ if(cmd_array_index >= RWNX_CMD_HIGH_WATER_SIZE){ ++ AICWFDBG(LOGERROR, "%s cmd(%d) was pending...\r\n", __func__, cmd_array_index); ++ mdelay(100); ++ } ++ ++ if(!cmd){ ++ AICWFDBG(LOGERROR, "%s array is empty...\r\n", __func__); ++ } ++ ++ spin_unlock_irqrestore(&cmd_array_lock, flags); ++ ++ return cmd; ++} ++ ++void rwnx_cmd_free(struct rwnx_cmd *cmd){ ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&cmd_array_lock, flags); ++ cmd->used = 0; ++ AICWFDBG(LOGTRACE, "%s cmd_array[%d]:%p \r\n", __func__, cmd->array_id, cmd); ++ spin_unlock_irqrestore(&cmd_array_lock, flags); ++} ++ ++ ++int rwnx_init_cmd_array(void){ ++ ++ AICWFDBG(LOGTRACE, "%s Enter \r\n", __func__); ++ spin_lock_init(&cmd_array_lock); ++ ++ for(cmd_array_index = 0; cmd_array_index < RWNX_CMD_ARRAY_SIZE; cmd_array_index++){ ++ AICWFDBG(LOGTRACE, "%s cmd_queue[%d]:%p \r\n", __func__, cmd_array_index, &cmd_array[cmd_array_index]); ++ cmd_array[cmd_array_index].used = 0; ++ cmd_array[cmd_array_index].array_id = cmd_array_index; ++ } ++ AICWFDBG(LOGTRACE, "%s Exit \r\n", __func__); ++ ++ return 0; ++} ++ ++void rwnx_free_cmd_array(void){ ++ ++ AICWFDBG(LOGTRACE, "%s Enter \r\n", __func__); ++ ++ for(cmd_array_index = 0; cmd_array_index < RWNX_CMD_ARRAY_SIZE; cmd_array_index++){ ++ cmd_array[cmd_array_index].used = 0; ++ } ++ ++ AICWFDBG(LOGTRACE, "%s Exit \r\n", __func__); ++} ++ ++ ++/** ++ ****************************************************************************** ++ * @brief Allocate memory for a message ++ * ++ * This primitive allocates memory for a message that has to be sent. The memory ++ * is allocated dynamically on the heap and the length of the variable parameter ++ * structure has to be provided in order to allocate the correct size. ++ * ++ * Several additional parameters are provided which will be preset in the message ++ * and which may be used internally to choose the kind of memory to allocate. ++ * ++ * The memory allocated will be automatically freed by the kernel, after the ++ * pointer has been sent to ke_msg_send(). If the message is not sent, it must ++ * be freed explicitly with ke_msg_free(). ++ * ++ * Allocation failure is considered critical and should not happen. ++ * ++ * @param[in] id Message identifier ++ * @param[in] dest_id Destination Task Identifier ++ * @param[in] src_id Source Task Identifier ++ * @param[in] param_len Size of the message parameters to be allocated ++ * ++ * @return Pointer to the parameter member of the ke_msg. If the parameter ++ * structure is empty, the pointer will point to the end of the message ++ * and should not be used (except to retrieve the message pointer or to ++ * send the message) ++ ****************************************************************************** ++ */ ++static inline void *rwnx_msg_zalloc(lmac_msg_id_t const id, ++ lmac_task_id_t const dest_id, ++ lmac_task_id_t const src_id, ++ uint16_t const param_len) ++{ ++ struct lmac_msg *msg; ++ gfp_t flags; ++ ++// if (is_non_blocking_msg(id) && (in_softirq()||in_atomic())) ++ flags = GFP_ATOMIC; ++// else ++// flags = GFP_KERNEL; ++ ++ msg = (struct lmac_msg *)kzalloc(sizeof(struct lmac_msg) + param_len, ++ flags); ++ if (msg == NULL) { ++ AICWFDBG(LOGERROR, "%s: msg allocation failed\n", __func__); ++ return NULL; ++ } ++ msg->id = id; ++ msg->dest_id = dest_id; ++ msg->src_id = src_id; ++ msg->param_len = param_len; ++ //printk("rwnx_msg_zalloc size=%d id=%d\n",msg->param_len,msg->id); ++ ++ return msg->param; ++} ++ ++static void rwnx_msg_free(struct rwnx_hw *rwnx_hw, const void *msg_params) ++{ ++ struct lmac_msg *msg = container_of((void *)msg_params, ++ struct lmac_msg, param); ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Free the message */ ++ kfree(msg); ++} ++ ++//void rwnx_pm_relax(struct aic_sdio_dev *sdiodev); ++//void rwnx_pm_stay_awake(struct aic_sdio_dev *sdiodev); ++ ++static int rwnx_send_msg(struct rwnx_hw *rwnx_hw, const void *msg_params, ++ int reqcfm, lmac_msg_id_t reqid, void *cfm) ++{ ++ struct lmac_msg *msg; ++ struct rwnx_cmd *cmd; ++ bool nonblock; ++ int ret = 0; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ AICWFDBG(LOGTRACE, "%s (%d)%s reqcfm:%d in_irq:%d in_softirq:%d in_atomic:%d\r\n", ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(6, 18, 0)) ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_irq(), (int)in_softirq(), (int)in_atomic()); ++#else ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_hardirq(), (int)in_softirq(), (int)in_atomic()); ++#endif ++ ++ ++#ifdef AICWF_USB_SUPPORT ++ if (rwnx_hw->usbdev->state == USB_DOWN_ST) { ++ rwnx_msg_free(rwnx_hw, msg_params); ++ usb_err("bus is down\n"); ++ return 0; ++ } ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ rwnx_wakeup_lock(rwnx_hw->ws_tx); ++ if (rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { ++ rwnx_msg_free(rwnx_hw, msg_params); ++ sdio_err("bus is down\n"); ++ rwnx_wakeup_unlock(rwnx_hw->ws_tx); ++ return 0; ++ } ++#endif ++ ++ msg = container_of((void *)msg_params, struct lmac_msg, param); ++ ++ #if 0 ++ if (!test_bit(RWNX_DEV_STARTED, &rwnx_hw->drv_flags) && ++ reqid != DBG_MEM_READ_CFM && reqid != DBG_MEM_WRITE_CFM && ++ reqid != DBG_MEM_BLOCK_WRITE_CFM && reqid != DBG_START_APP_CFM && ++ reqid != MM_SET_RF_CALIB_CFM && reqid != MM_SET_RF_CONFIG_CFM && ++ reqid != MM_RESET_CFM && reqid != MM_VERSION_CFM && ++ reqid != MM_START_CFM && reqid != MM_SET_IDLE_CFM && ++ reqid != ME_CONFIG_CFM && reqid != MM_SET_PS_MODE_CFM && ++ reqid != ME_CHAN_CONFIG_CFM) { ++ printk(KERN_CRIT "%s: bypassing (RWNX_DEV_RESTARTING set) 0x%02x\n", ++ __func__, reqid); ++ kfree(msg); ++ return -EBUSY; ++ } ++ #endif ++#if 0 ++ else if (!rwnx_hw->ipc_env) { ++ printk(KERN_CRIT "%s: bypassing (restart must have failed)\n", __func__); ++ kfree(msg); ++ return -EBUSY; ++ } ++#endif ++ ++ //nonblock = is_non_blocking_msg(msg->id); ++ nonblock = 0; ++ cmd = rwnx_cmd_malloc();//kzalloc(sizeof(struct rwnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL); ++ cmd->result = -EINTR; ++ cmd->id = msg->id; ++ cmd->reqid = reqid; ++ cmd->a2e_msg = msg; ++ cmd->e2a_msg = cfm; ++ if (nonblock) ++ cmd->flags = RWNX_CMD_FLAG_NONBLOCK; ++ if (reqcfm) ++ cmd->flags |= RWNX_CMD_FLAG_REQ_CFM; ++ ++#if 0 ++ if (cfm != NULL) { ++ do { ++ if(rwnx_hw->cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) ++ break; ++ spin_lock_bh(&rwnx_hw->cmd_mgr->lock); ++ empty = list_empty(&rwnx_hw->cmd_mgr->cmds); ++ spin_unlock_bh(&rwnx_hw->cmd_mgr->lock); ++ if(!empty) { ++ if(in_softirq()) { ++ printk("in_softirq:check cmdqueue empty\n"); ++ mdelay(10); ++ } ++ else { ++ printk("check cmdqueue empty\n"); ++ msleep(50); ++ } ++ } ++ } while (!empty);//wait for cmd queue empty ++ } ++#endif ++ if (reqcfm) { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; // we don't need ack any more ++ ret = rwnx_hw->cmd_mgr->queue(rwnx_hw->cmd_mgr, cmd); ++ } else { ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_set_cmd_tx((void *)(rwnx_hw->sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++#else ++ aicwf_set_cmd_tx((void *)(rwnx_hw->usbdev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len); ++#endif ++ } ++ ++ if (!reqcfm || ret) ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ ++ rwnx_wakeup_unlock(rwnx_hw->ws_tx); ++ return 0; ++} ++ ++ ++static int rwnx_send_msg1(struct rwnx_hw *rwnx_hw, const void *msg_params, ++ int reqcfm, lmac_msg_id_t reqid, void *cfm, bool defer) ++{ ++ struct lmac_msg *msg; ++ struct rwnx_cmd *cmd; ++ bool nonblock; ++ int ret = 0; ++ ++// RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("%s (%d)%s reqcfm:%d in_irq:%d in_softirq:%d in_atomic:%d\r\n", ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(6, 18, 0)) ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_irq(), (int)in_softirq(), (int)in_atomic()); ++#else ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_hardirq(), (int)in_softirq(), (int)in_atomic()); ++#endif ++ ++ rwnx_wakeup_lock(rwnx_hw->ws_tx); ++ msg = container_of((void *)msg_params, struct lmac_msg, param); ++ ++ //nonblock = is_non_blocking_msg(msg->id); ++ nonblock = 0; ++ cmd = rwnx_cmd_malloc();//kzalloc(sizeof(struct rwnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL); ++ cmd->result = -EINTR; ++ cmd->id = msg->id; ++ cmd->reqid = reqid; ++ cmd->a2e_msg = msg; ++ cmd->e2a_msg = cfm; ++ if (nonblock) ++ cmd->flags = RWNX_CMD_FLAG_NONBLOCK; ++ if (reqcfm) ++ cmd->flags |= RWNX_CMD_FLAG_REQ_CFM; ++ ++ if (reqcfm) { ++ cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK; // we don't need ack any more ++ if (!defer) ++ ret = rwnx_hw->cmd_mgr->queue(rwnx_hw->cmd_mgr, cmd); ++ else ++ ret = cmd_mgr_queue_force_defer(rwnx_hw->cmd_mgr, cmd); ++ } ++ ++ if (!reqcfm || ret) ++ rwnx_cmd_free(cmd);//kfree(cmd); ++ ++ if (!ret) ++ ret = cmd->result; ++ ++ rwnx_wakeup_unlock(rwnx_hw->ws_tx); ++ //return ret; ++ return 0; ++} ++ ++/****************************************************************************** ++ * Control messages handling functions (FULLMAC) ++ *****************************************************************************/ ++int rwnx_send_reset(struct rwnx_hw *rwnx_hw) ++{ ++ void *void_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* RESET REQ has no parameter */ ++ void_param = rwnx_msg_zalloc(MM_RESET_REQ, TASK_MM, DRV_TASK_ID, 0); ++ if (!void_param) ++ return -ENOMEM; ++ ++ return rwnx_send_msg(rwnx_hw, void_param, 1, MM_RESET_CFM, NULL); ++} ++ ++int rwnx_send_start(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_start_req *start_req_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the START REQ message */ ++ start_req_param = rwnx_msg_zalloc(MM_START_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_start_req)); ++ if (!start_req_param) ++ return -ENOMEM; ++ ++ /* Set parameters for the START message */ ++ memcpy(&start_req_param->phy_cfg, &rwnx_hw->phy.cfg, sizeof(rwnx_hw->phy.cfg)); ++ start_req_param->uapsd_timeout = (u32_l)rwnx_hw->mod_params->uapsd_timeout; ++ start_req_param->lp_clk_accuracy = (u16_l)rwnx_hw->mod_params->lp_clk_ppm; ++ ++ /* Send the START REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, start_req_param, 1, MM_START_CFM, NULL); ++} ++ ++int rwnx_send_version_req(struct rwnx_hw *rwnx_hw, struct mm_version_cfm *cfm) ++{ ++ void *void_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* VERSION REQ has no parameter */ ++ void_param = rwnx_msg_zalloc(MM_VERSION_REQ, TASK_MM, DRV_TASK_ID, 0); ++ if (!void_param) ++ return -ENOMEM; ++ ++ return rwnx_send_msg(rwnx_hw, void_param, 1, MM_VERSION_CFM, cfm); ++} ++ ++int rwnx_send_add_if (struct rwnx_hw *rwnx_hw, const unsigned char *mac, ++ enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm) ++{ ++ struct mm_add_if_req *add_if_req_param; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ADD_IF_REQ message */ ++ add_if_req_param = rwnx_msg_zalloc(MM_ADD_IF_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_add_if_req)); ++ if (!add_if_req_param) ++ return -ENOMEM; ++ ++ /* Set parameters for the ADD_IF_REQ message */ ++ memcpy(&(add_if_req_param->addr.array[0]), mac, ETH_ALEN); ++ switch (iftype) { ++ #ifdef CONFIG_RWNX_FULLMAC ++ //case NL80211_IFTYPE_P2P_DEVICE: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ add_if_req_param->p2p = true; ++ // no break ++ __attribute__((__fallthrough__)); ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ case NL80211_IFTYPE_STATION: ++ add_if_req_param->type = MM_STA; ++ break; ++ ++ case NL80211_IFTYPE_ADHOC: ++ add_if_req_param->type = MM_IBSS; ++ break; ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ case NL80211_IFTYPE_P2P_GO: ++ add_if_req_param->p2p = true; ++ // no break ++ __attribute__((__fallthrough__)); ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ case NL80211_IFTYPE_AP: ++ add_if_req_param->type = MM_AP; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ add_if_req_param->type = MM_MESH_POINT; ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ return -1; ++ case NL80211_IFTYPE_MONITOR: ++ add_if_req_param->type = MM_MONITOR; ++ break; ++ default: ++ add_if_req_param->type = MM_STA; ++ break; ++ } ++ ++ ++ /* Send the ADD_IF_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, add_if_req_param, 1, MM_ADD_IF_CFM, cfm); ++} ++ ++int rwnx_send_remove_if (struct rwnx_hw *rwnx_hw, u8 vif_index, bool defer) ++{ ++ struct mm_remove_if_req *remove_if_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_REMOVE_IF_REQ message */ ++ remove_if_req = rwnx_msg_zalloc(MM_REMOVE_IF_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_remove_if_req)); ++ if (!remove_if_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_REMOVE_IF_REQ message */ ++ remove_if_req->inst_nbr = vif_index; ++ ++ /* Send the MM_REMOVE_IF_REQ message to LMAC FW */ ++ return rwnx_send_msg1(rwnx_hw, remove_if_req, 1, MM_REMOVE_IF_CFM, NULL, defer); ++} ++ ++int rwnx_send_set_channel(struct rwnx_hw *rwnx_hw, int phy_idx, ++ struct mm_set_channel_cfm *cfm) ++{ ++ struct mm_set_channel_req *req; ++ enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT; ++ u16 center_freq = 2412, center_freq1 = 2412, center_freq2 = 2412; ++ s8 tx_power = 0; ++ u8 flags = 0; ++ enum nl80211_band band = NL80211_BAND_2GHZ; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (phy_idx >= rwnx_hw->phy.cnt) ++ return -ENOTSUPP; ++ ++ req = rwnx_msg_zalloc(MM_SET_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_channel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if (phy_idx == 0) { ++#ifdef CONFIG_RWNX_FULLMAC ++ /* On FULLMAC only setting channel of secondary chain */ ++ wiphy_err(rwnx_hw->wiphy, "Trying to set channel of primary chain"); ++ return 0; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } else { ++ struct rwnx_sec_phy_chan *chan = &rwnx_hw->phy.sec_chan; ++ width = chnl2bw[chan->type]; ++ band = chan->band; ++ center_freq = chan->prim20_freq; ++ center_freq1 = chan->center_freq1; ++ center_freq2 = chan->center_freq2; ++ flags = 0; ++ } ++ ++ req->chan.band = band; ++ req->chan.type = bw2chnl[width]; ++ req->chan.prim20_freq = center_freq; ++ req->chan.center1_freq = center_freq1; ++ req->chan.center2_freq = center_freq2; ++ req->chan.tx_power = tx_power; ++ req->chan.flags = flags; ++ req->index = phy_idx; ++ ++ if (rwnx_hw->phy.limit_bw) ++ limit_chan_bw(&req->chan.type, req->chan.prim20_freq, &req->chan.center1_freq); ++ ++ RWNX_DBG("mac80211: freq=%d(c1:%d - c2:%d)/width=%d - band=%d\n" ++ " hw(%d): prim20=%d(c1:%d - c2:%d)/ type=%d - band=%d\n", ++ center_freq, center_freq1, center_freq2, width, band, ++ phy_idx, req->chan.prim20_freq, req->chan.center1_freq, ++ req->chan.center2_freq, req->chan.type, req->chan.band); ++ ++ /* Send the MM_SET_CHANNEL_REQ REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_SET_CHANNEL_CFM, cfm); ++} ++ ++int rwnx_send_key_add(struct rwnx_hw *rwnx_hw, u8 vif_idx, u8 sta_idx, bool pairwise, ++ u8 *key, u8 key_len, u8 key_idx, u8 cipher_suite, ++ struct mm_key_add_cfm *cfm) ++{ ++ struct mm_key_add_req *key_add_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_KEY_ADD_REQ message */ ++ key_add_req = rwnx_msg_zalloc(MM_KEY_ADD_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_key_add_req)); ++ if (!key_add_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_KEY_ADD_REQ message */ ++ if (sta_idx != 0xFF) { ++ /* Pairwise key */ ++ key_add_req->sta_idx = sta_idx; ++ } else { ++ /* Default key */ ++ key_add_req->sta_idx = sta_idx; ++ key_add_req->key_idx = (u8_l)key_idx; /* only useful for default keys */ ++ } ++ key_add_req->pairwise = pairwise; ++ key_add_req->inst_nbr = vif_idx; ++ key_add_req->key.length = key_len; ++ memcpy(&(key_add_req->key.array[0]), key, key_len); ++ ++ key_add_req->cipher_suite = cipher_suite; ++ ++ RWNX_DBG("%s: sta_idx:%d key_idx:%d inst_nbr:%d cipher:%d key_len:%d\n", __func__, ++ key_add_req->sta_idx, key_add_req->key_idx, key_add_req->inst_nbr, ++ key_add_req->cipher_suite, key_add_req->key.length); ++#if defined(CONFIG_RWNX_DBG) || defined(CONFIG_DYNAMIC_DEBUG) ++ print_hex_dump_bytes("key: ", DUMP_PREFIX_OFFSET, key_add_req->key.array, key_add_req->key.length); ++#endif ++ ++ /* Send the MM_KEY_ADD_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, key_add_req, 1, MM_KEY_ADD_CFM, cfm); ++} ++ ++int rwnx_send_key_del(struct rwnx_hw *rwnx_hw, uint8_t hw_key_idx) ++{ ++ struct mm_key_del_req *key_del_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_KEY_DEL_REQ message */ ++ key_del_req = rwnx_msg_zalloc(MM_KEY_DEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_key_del_req)); ++ if (!key_del_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_KEY_DEL_REQ message */ ++ key_del_req->hw_key_idx = hw_key_idx; ++ ++ /* Send the MM_KEY_DEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, key_del_req, 1, MM_KEY_DEL_CFM, NULL); ++} ++ ++int rwnx_send_bcn(struct rwnx_hw *rwnx_hw, u8 *buf, u8 vif_idx, u16 bcn_len) ++{ ++ struct apm_set_bcn_ie_req *bcn_ie_req; ++ bcn_ie_req = rwnx_msg_zalloc(APM_SET_BEACON_IE_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_set_bcn_ie_req)); ++ if (!bcn_ie_req) ++ return -ENOMEM; ++ ++ bcn_ie_req->vif_idx = vif_idx; ++ bcn_ie_req->bcn_ie_len = bcn_len; ++ memcpy(bcn_ie_req->bcn_ie, (u8 *)buf, bcn_len); ++ kfree(buf); ++ ++ return rwnx_send_msg(rwnx_hw, bcn_ie_req, 1, APM_SET_BEACON_IE_CFM, NULL); ++} ++ ++int rwnx_send_bcn_change(struct rwnx_hw *rwnx_hw, u8 vif_idx, u32 bcn_addr, ++ u16 bcn_len, u16 tim_oft, u16 tim_len, u16 *csa_oft) ++{ ++ struct mm_bcn_change_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_BCN_CHANGE_REQ message */ ++ req = rwnx_msg_zalloc(MM_BCN_CHANGE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_bcn_change_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_BCN_CHANGE_REQ message */ ++ req->bcn_ptr = bcn_addr; ++ req->bcn_len = bcn_len; ++ req->tim_oft = tim_oft; ++ req->tim_len = tim_len; ++ req->inst_nbr = vif_idx; ++ ++ if (csa_oft) { ++ int i; ++ for (i = 0; i < BCN_MAX_CSA_CPT; i++) { ++ req->csa_oft[i] = csa_oft[i]; ++ } ++ } ++ ++ /* Send the MM_BCN_CHANGE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_BCN_CHANGE_CFM, NULL); ++} ++ ++int rwnx_send_roc(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct ieee80211_channel *chan, unsigned int duration, ++ struct mm_remain_on_channel_cfm *roc_cfm) ++{ ++ struct mm_remain_on_channel_req *req; ++ struct cfg80211_chan_def chandef; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Create channel definition structure */ ++ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); ++ ++ /* Build the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req = rwnx_msg_zalloc(MM_REMAIN_ON_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_remain_on_channel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req->op_code = MM_ROC_OP_START; ++ req->vif_index = vif->vif_index; ++ req->duration_ms = duration; ++ req->band = chan->band; ++ req->type = bw2chnl[chandef.width]; ++ req->prim20_freq = chan->center_freq; ++ req->center1_freq = chandef.center_freq1; ++ req->center2_freq = chandef.center_freq2; ++ req->tx_power = chan_to_fw_pwr(chan->max_power); ++ ++ /* Send the MM_REMAIN_ON_CHANNEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_REMAIN_ON_CHANNEL_CFM, roc_cfm); ++} ++ ++int rwnx_send_cancel_roc(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_remain_on_channel_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req = rwnx_msg_zalloc(MM_REMAIN_ON_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_remain_on_channel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_REMAIN_ON_CHANNEL_REQ message */ ++ req->op_code = MM_ROC_OP_CANCEL; ++ ++ /* Send the MM_REMAIN_ON_CHANNEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_REMAIN_ON_CHANNEL_CFM, NULL); ++} ++ ++int rwnx_send_set_power(struct rwnx_hw *rwnx_hw, u8 vif_idx, s8 pwr, ++ struct mm_set_power_cfm *cfm) ++{ ++ struct mm_set_power_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_POWER_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_POWER_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_power_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_SET_POWER_REQ message */ ++ req->inst_nbr = vif_idx; ++ req->power = pwr; ++ ++ /* Send the MM_SET_POWER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_SET_POWER_CFM, cfm); ++} ++ ++int rwnx_send_set_edca(struct rwnx_hw *rwnx_hw, u8 hw_queue, u32 param, ++ bool uapsd, u8 inst_nbr) ++{ ++ struct mm_set_edca_req *set_edca_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_EDCA_REQ message */ ++ set_edca_req = rwnx_msg_zalloc(MM_SET_EDCA_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_edca_req)); ++ if (!set_edca_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_SET_EDCA_REQ message */ ++ set_edca_req->ac_param = param; ++ set_edca_req->uapsd = uapsd; ++ set_edca_req->hw_queue = hw_queue; ++ set_edca_req->inst_nbr = inst_nbr; ++ ++ /* Send the MM_SET_EDCA_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_edca_req, 1, MM_SET_EDCA_CFM, NULL); ++} ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++int rwnx_send_p2p_oppps_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 ctw, struct mm_set_p2p_oppps_cfm *cfm) ++{ ++ struct mm_set_p2p_oppps_req *p2p_oppps_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_P2P_OPPPS_REQ message */ ++ p2p_oppps_req = rwnx_msg_zalloc(MM_SET_P2P_OPPPS_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_p2p_oppps_req)); ++ ++ if (!p2p_oppps_req) { ++ return -ENOMEM; ++ } ++ ++ /* Fill the message parameters */ ++ p2p_oppps_req->vif_index = rwnx_vif->vif_index; ++ p2p_oppps_req->ctwindow = ctw; ++ ++ /* Send the MM_P2P_OPPPS_REQ message to LMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, p2p_oppps_req, 1, MM_SET_P2P_OPPPS_CFM, cfm); ++ ++ return error; ++} ++ ++int rwnx_send_p2p_noa_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ int count, int interval, int duration, bool dyn_noa, ++ struct mm_set_p2p_noa_cfm *cfm) ++{ ++ struct mm_set_p2p_noa_req *p2p_noa_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Param check */ ++ if (count > 255) ++ count = 255; ++ ++ if (duration >= interval) { ++ dev_err(rwnx_hw->dev, "Invalid p2p NOA config: interval=%d <= duration=%d\n", ++ interval, duration); ++ return -EINVAL; ++ } ++ ++ /* Build the MM_SET_P2P_NOA_REQ message */ ++ p2p_noa_req = rwnx_msg_zalloc(MM_SET_P2P_NOA_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_p2p_noa_req)); ++ ++ if (!p2p_noa_req) { ++ return -ENOMEM; ++ } ++ ++ /* Fill the message parameters */ ++ p2p_noa_req->vif_index = rwnx_vif->vif_index; ++ p2p_noa_req->noa_inst_nb = 0; ++ p2p_noa_req->count = count; ++ ++ if (count) { ++ p2p_noa_req->duration_us = duration * 1024; ++ p2p_noa_req->interval_us = interval * 1024; ++ p2p_noa_req->start_offset = (interval - duration - 10) * 1024; ++ p2p_noa_req->dyn_noa = dyn_noa; ++ } ++ ++ /* Send the MM_SET_2P_NOA_REQ message to LMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, p2p_noa_req, 1, MM_SET_P2P_NOA_CFM, cfm); ++ ++ return error; ++} ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++#ifdef AICWF_ARP_OFFLOAD ++int rwnx_send_arpoffload_en_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u32_l ipaddr, u8_l enable) ++{ ++ struct mm_set_arpoffload_en_req *arp_offload_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_P2P_NOA_REQ message */ ++ arp_offload_req = rwnx_msg_zalloc(MM_SET_ARPOFFLOAD_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_arpoffload_en_req)); ++ ++ if (!arp_offload_req) { ++ return -ENOMEM; ++ } ++ ++ /* Fill the message parameters */ ++ arp_offload_req->enable = enable; ++ arp_offload_req->vif_idx = rwnx_vif->vif_index; ++ arp_offload_req->ipaddr = ipaddr; ++ ++ /* Send the MM_ARPOFFLOAD_EN_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, arp_offload_req, 1, MM_SET_ARPOFFLOAD_CFM, NULL); ++ ++ return error; ++} ++#endif ++ ++int rwnx_send_disable_agg_req(struct rwnx_hw *rwnx_hw, u8_l agg_disable, u8_l agg_disable_rx, u8_l sta_idx) ++{ ++ struct mm_set_agg_disable_req *req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_AGG_DISABLE_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_AGG_DISABLE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_agg_disable_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->disable = agg_disable; ++ req->staidx = sta_idx; ++ req->disable_rx = agg_disable_rx; ++ ++ /* Send the MM_SET_AGG_DISABLE_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_AGG_DISABLE_CFM, NULL); ++ ++ return (error); ++}; ++ ++int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enable_nullcts) ++{ ++ struct mm_set_coex_req *coex_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_COEX_REQ message */ ++ coex_req = rwnx_msg_zalloc(MM_SET_COEX_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_coex_req)); ++ ++ if (!coex_req) { ++ return -ENOMEM; ++ } ++ ++ coex_req->bt_on = 1; ++ coex_req->disable_coexnull = disable_coexnull; ++ coex_req->enable_nullcts = enable_nullcts; ++ coex_req->enable_periodic_timer = 0; ++ coex_req->coex_timeslot_set = 0; ++ ++ /* Send the MM_SET_COEX_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, coex_req, 1, MM_SET_COEX_CFM, NULL); ++ ++ return error; ++}; ++ ++ ++int rwnx_send_rf_config_req(struct rwnx_hw *rwnx_hw, u8_l ofst, u8_l sel, u8_l *tbl, u16_l len) ++{ ++ struct mm_set_rf_config_req *rf_config_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_RF_CONFIG_REQ message */ ++ rf_config_req = rwnx_msg_zalloc(MM_SET_RF_CONFIG_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_rf_config_req)); ++ ++ if (!rf_config_req) { ++ return -ENOMEM; ++ } ++ ++ rf_config_req->table_sel = sel; ++ rf_config_req->table_ofst = ofst; ++ rf_config_req->table_num = 16; ++ rf_config_req->deft_page = 0; ++ ++ memcpy(rf_config_req->data, tbl, len); ++ ++ /* Send the MM_SET_RF_CONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, rf_config_req, 1, MM_SET_RF_CONFIG_CFM, NULL); ++ ++ return (error); ++ ++} ++ ++int rwnx_send_rf_calib_req(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm) ++{ ++ struct mm_set_rf_calib_req *rf_calib_req; ++ xtal_cap_conf_t xtal_cap = {0,}; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_P2P_NOA_REQ message */ ++ rf_calib_req = rwnx_msg_zalloc(MM_SET_RF_CALIB_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_rf_calib_req)); ++ ++ if (!rf_calib_req) { ++ return -ENOMEM; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ rf_calib_req->cal_cfg_24g = 0xbf; ++ rf_calib_req->cal_cfg_5g = 0x3f; ++ } else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW) { ++ rf_calib_req->cal_cfg_24g = 0x0f8f; ++ rf_calib_req->cal_cfg_5g = 0; ++ } else if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rf_calib_req->cal_cfg_24g = 0x0f8f; ++ rf_calib_req->cal_cfg_5g = 0x0f0f; ++ } ++ ++ rf_calib_req->param_alpha = 0x0c34c008; ++ rf_calib_req->bt_calib_en = 0; ++ rf_calib_req->bt_calib_param = 0x264203; ++ ++ get_userconfig_xtal_cap(&xtal_cap); ++ ++ if (xtal_cap.enable) { ++ printk("user xtal cap: %d, cap_fine: %d\n", xtal_cap.xtal_cap, xtal_cap.xtal_cap_fine); ++ rf_calib_req->xtal_cap = xtal_cap.xtal_cap; ++ rf_calib_req->xtal_cap_fine = xtal_cap.xtal_cap_fine; ++ } else { ++ rf_calib_req->xtal_cap = 0; ++ rf_calib_req->xtal_cap_fine = 0; ++ } ++ ++ ++ /* Send the MM_SET_RF_CALIB_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, rf_calib_req, 1, MM_SET_RF_CALIB_CFM, cfm); ++ ++ return error; ++}; ++ ++int rwnx_send_get_macaddr_req(struct rwnx_hw *rwnx_hw, struct mm_get_mac_addr_cfm *cfm) ++{ ++ struct mm_get_mac_addr_req *get_macaddr_req; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_GET_MAC_ADDR_REQ message */ ++ get_macaddr_req = rwnx_msg_zalloc(MM_GET_MAC_ADDR_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_get_mac_addr_req)); ++ ++ if (!get_macaddr_req) { ++ return -ENOMEM; ++ } ++ ++ get_macaddr_req->get = 1; ++ ++ /* Send the MM_GET_MAC_ADDR_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, get_macaddr_req, 1, MM_GET_MAC_ADDR_CFM, cfm); ++ ++ return error; ++}; ++ ++int rwnx_send_get_sta_info_req(struct rwnx_hw *rwnx_hw, u8_l sta_idx, struct mm_get_sta_info_cfm *cfm) ++{ ++ struct mm_get_sta_info_req *get_info_req; ++ int error; ++ ++ ++ /* Build the MM_GET_STA_INFO_REQ message */ ++ get_info_req = rwnx_msg_zalloc(MM_GET_STA_INFO_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_get_sta_info_req)); ++ ++ if (!get_info_req) { ++ return -ENOMEM; ++ } ++ ++ get_info_req->sta_idx = sta_idx; ++ ++ /* Send the MM_GET_STA_INFO_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, get_info_req, 1, MM_GET_STA_INFO_CFM, cfm); ++ ++ return error; ++}; ++ ++int rwnx_send_set_stack_start_req(struct rwnx_hw *rwnx_hw, u8_l on, u8_l efuse_valid, u8_l set_vendor_info, ++ u8_l fwtrace_redir_en, struct mm_set_stack_start_cfm *cfm) ++{ ++ struct mm_set_stack_start_req *req; ++ int error; ++ ++ /* Build the MM_SET_STACK_START_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_STACK_START_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_stack_start_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->is_stack_start = on; ++ req->efuse_valid = efuse_valid; ++ req->set_vendor_info = set_vendor_info; ++ req->fwtrace_redir = fwtrace_redir_en; ++ /* Send the MM_SET_STACK_START_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_STACK_START_CFM, cfm); ++ ++ return error; ++} ++ ++#ifdef CONFIG_TEMP_COMP ++ ++int rwnx_send_get_temp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the TEMP_COMP_GET_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ AICWFDBG(LOGINFO, "%s msg_alloc fail\n", __func__); ++ return -ENOMEM; ++ } ++ req->swconfig_id = TEMP_COMP_GET_REQ; ++ ++ ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); ++ if (!ret) ++ AICWFDBG(LOGINFO, "status=%d, temp=%d\n", cfm->temp_comp_get_cfm.status, cfm->temp_comp_get_cfm.degree); ++ else { ++ AICWFDBG(LOGINFO, "%s msg_fail\n", __func__); ++ return ret; ++ } ++ //rwnx_hw->started_jiffies = jiffies; ++ rwnx_hw->temp = cfm->temp_comp_get_cfm.degree; ++ ++ return ret; ++} ++ ++ ++int rwnx_send_set_temp_comp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ /* Build the TEMP_COMP_SET_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ printk("%s msg_alloc fail\n", __func__); ++ return -ENOMEM; ++ } ++ req->swconfig_id = TEMP_COMP_SET_REQ; ++ req->temp_comp_set_req.enable = 1; ++ req->temp_comp_set_req.tmr_period_ms = 15 * 1000; ++ ++ ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); ++ if (!ret) ++ printk("temp_comp status: %d\n", cfm->temp_comp_set_cfm.status); ++ else { ++ printk("%s msg_fail\n", __func__); ++ return ret; ++ } ++ return ret; ++} ++#endif ++ ++int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, int32_t *param, int32_t *param_out) ++{ ++ struct mm_set_acs_txop_req *req0; ++ struct mm_set_channel_access_req *req1; ++ struct mm_set_mac_timescale_req *req2; ++ struct mm_set_cca_threshold_req *req3; ++ struct mm_set_bwmode_req *req4; ++ struct mm_set_ap_ps_level_req *req5 = NULL; ++ struct mm_set_customized_freq_req *req6; ++ ++ int error = 0; ++ int i; ++ ++ switch (hwconfig_id) ++ { ++ case ACS_TXOP_REQ: ++ /* Build the ACS_TXOP_REQ message */ ++ req0= rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_acs_txop_req) ); ++ if (!req0) ++ return -ENOMEM; ++ req0->hwconfig_id = hwconfig_id; ++ req0->txop_be = param[0]; ++ req0->txop_bk = param[1]; ++ req0->txop_vi = param[2]; ++ req0->txop_vo = param[3]; ++ printk("set_acs_txop_req: be: %x,bk: %x,vi: %x,vo: %x\n", ++ req0->txop_be, req0->txop_bk, req0->txop_vi, req0->txop_vo); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req0, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ ++ case CHANNEL_ACCESS_REQ: ++ /* Build the CHANNEL_ACCESS_REQ message */ ++ req1 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_channel_access_req)); ++ if (!req1) ++ return -ENOMEM; ++ req1->hwconfig_id = hwconfig_id; ++ req1->edca[0] = param[0]; ++ req1->edca[1] = param[1]; ++ req1->edca[2] = param[2]; ++ req1->edca[3] = param[3]; ++ req1->vif_idx = param[4]; ++ req1->retry_cnt = param[5]; ++ req1->rts_en = param[6]; ++ req1->long_nav_en = param[7]; ++ req1->cfe_en = param[8]; ++ req1->rc_retry_cnt[0] = param[9]; ++ req1->rc_retry_cnt[1] = param[10]; ++ req1->rc_retry_cnt[2] = param[11]; ++ req1->ccademod_th = param[12]; ++ req1->remove_1m2m = param[13]; ++ printk("set_channel_access_req:edca[]= %x %x %x %x\nvif_idx: %x, retry_cnt: %x, rts_en: %x, long_nav_en: %x, cfe_en: %x, rc_retry_cnt: %x:%x:%x, ccademod_th = %d remove_1m2m = %x\n", ++ req1->edca[0], req1->edca[1], req1->edca[2], req1->edca[3], req1->vif_idx, req1->retry_cnt, req1->rts_en, req1->long_nav_en, req1->cfe_en, req1->rc_retry_cnt[0],req1->rc_retry_cnt[1], req1->rc_retry_cnt[2], req1->ccademod_th, req1->remove_1m2m); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req1, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ ++ case MAC_TIMESCALE_REQ: ++ /* Build the MAC_TIMESCALE_REQ message */ ++ req2 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_mac_timescale_req)); ++ if (!req2) ++ return -ENOMEM; ++ req2->hwconfig_id = hwconfig_id; ++ req2->sifsA_time = param[0]; ++ req2->sifsB_time = param[1]; ++ req2->slot_time = param[2]; ++ req2->rx_startdelay_ofdm = param[3]; ++ req2->rx_startdelay_long = param[4]; ++ req2->rx_startdelay_short = param[5]; ++ printk("set_mac_timescale_req:sifsA_time: %x, sifsB_time: %x, slot_time: %x, rx_startdelay ofdm:%x long %x short %x\n", ++ req2->sifsA_time, req2->sifsB_time, req2->slot_time, req2->rx_startdelay_ofdm, req2->rx_startdelay_long, req2->rx_startdelay_short); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req2, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ ++ case CCA_THRESHOLD_REQ: ++ /* Build the CCA_THRESHOLD_REQ message */ ++ req3 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_cca_threshold_req)); ++ if (!req3) ++ return -ENOMEM; ++ req3->hwconfig_id = hwconfig_id; ++ req3->auto_cca_en = param[0]; ++ req3->cca20p_rise_th = param[1]; ++ req3->cca20s_rise_th = param[2]; ++ req3->cca20p_fall_th = param[3]; ++ req3->cca20s_fall_th = param[4]; ++ printk("cca_threshold_req: auto_cca_en:%d\ncca20p_rise_th = %d\ncca20s_rise_th = %d\ncca20p_fall_th = %d\ncca20s_fall_th = %d\n", ++ req3->auto_cca_en, req3->cca20p_rise_th, req3->cca20s_rise_th, req3->cca20p_fall_th, req3->cca20s_fall_th); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req3, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ case BWMODE_REQ: ++ /* Build the SET_BWMODE_REQ message */ ++ req4 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_bwmode_req)); ++ if (!req4) ++ return -ENOMEM; ++ req4->hwconfig_id = hwconfig_id; ++ req4->bwmode = param[0]; ++ printk("bwmode :%d\n", req4->bwmode); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req4, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ break; ++ case CHIP_TEMP_GET_REQ: ++ if ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) ++ { ++ struct mm_get_chip_temp_req *req; ++ struct mm_set_vendor_hwconfig_cfm cfm = {0,}; ++ /* Build the CHIP_TEMP_GET_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_get_chip_temp_req)); ++ if (!req) ++ return -ENOMEM; ++ req->hwconfig_id = hwconfig_id; ++ /* Send the MM_SET_VENDOR_HWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_HWCONFIG_CFM, &cfm); ++ if (!error) { ++ if (param_out) { ++ param_out[0] = (int32_t)cfm.chip_temp_cfm.degree; ++ } ++ printk("get_chip_temp degree=%d\n", cfm.chip_temp_cfm.degree); ++ } else { ++ printk("get_chip_temp err=%d\n", error); ++ } ++ } ++ break; ++ case AP_PS_LEVEL_SET_REQ: ++ /* ++ AP_PS_CLK_1 = 1, // 3:7 -> active 3, doze 7 ++ AP_PS_CLK_2, // 5:5 -> active 5, doze 5 ++ AP_PS_CLK_3, // 7:3 -> active 7, doze 3 ++ AP_PS_CLK_4, // 8:2 -> active 8, doze 2 ++ AP_PS_CLK_5, // 9:1 -> active 9, doze 1 ++ */ ++ /* Build the MM_SET_VENDOR_HWCONFIG_REQ message */ ++ req5 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_ap_ps_level_req)); ++ if (!req5) { ++ return -ENOMEM; ++ } ++ req5->hwconfig_id = hwconfig_id; ++ req5->ap_ps_level = param[0]; ++ ++ /* Send the MM_GET_MAC_ADDR_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req5, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ if(!error) ++ printk("set ap_ps_level=%d \n",param[0]); ++ break; ++ ++ case CUSTOMIZED_FREQ_REQ: ++ /* Build the CUSTOMIZED_FREQ_REQ message */ ++ req6 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_customized_freq_req)); ++ if (!req6) ++ return -ENOMEM; ++ req5->hwconfig_id = hwconfig_id; ++ for (i = 0; i < 4; i++) { ++ req6->raw_freq[i] = param [i]; ++ req6->map_freq[i] = param [i + 4]; ++ } ++ printk("customized_freq_req: raw_freq[ %d %d %d %d ], map_freq[ %d %d %d %d]\n", ++ param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7]); ++ /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req5, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); ++ ++ break; ++ default: ++ return -ENOMEM; ++ } ++ return error; ++} ++ ++int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, int32_t *param_in, int32_t *param_out) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ struct mm_set_vendor_swconfig_cfm cfm = {0,}; ++ int error; ++ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ req->swconfig_id = swconfig_id; ++ ++ switch (swconfig_id) ++ { ++ case BCN_CFG_REQ: ++ /* Build the BCN_CFG_REQ message */ ++ req->bcn_cfg_req.tim_bcmc_ignored_enable = (bool_l)param_in[0]; ++ printk("bcn_cfg_req: tim_bcmc_ignd=%d\n", req->bcn_cfg_req.tim_bcmc_ignored_enable); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (int32_t)cfm.bcn_cfg_cfm.tim_bcmc_ignored_status; ++ printk("status=%d\n", cfm.bcn_cfg_cfm.tim_bcmc_ignored_status); ++ } ++ break; ++ ++ case TEMP_COMP_SET_REQ: ++ /* Build the TEMP_COMP_SET_REQ message */ ++ req->temp_comp_set_req.enable = (u8_l)param_in[0]; ++ req->temp_comp_set_req.tmr_period_ms = (u32_l)param_in[1]; ++ printk("temp_comp_set_req: en=%d, tmr=%x\n", ++ req->temp_comp_set_req.enable, req->temp_comp_set_req.tmr_period_ms); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (int32_t)cfm.temp_comp_set_cfm.status; ++ printk("status=%d\n", cfm.temp_comp_set_cfm.status); ++ } ++ break; ++ ++ case TEMP_COMP_GET_REQ: ++ printk("temp_comp_get_req\n"); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (int32_t)cfm.temp_comp_get_cfm.status; ++ param_out[1] = (int32_t)cfm.temp_comp_get_cfm.degree; ++ printk("status=%d, degree=%d\n", ++ cfm.temp_comp_get_cfm.status, cfm.temp_comp_get_cfm.degree); ++ } ++ break; ++ ++ case EXT_FLAGS_SET_REQ: ++ /* Build the EXT_FLAGS_SET_REQ message */ ++ req->ext_flags_set_req.user_flags = (u32_l)param_in[0]; ++ printk("ext_flags_set_req: flags=%x\n", ++ req->ext_flags_set_req.user_flags); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (uint32_t)cfm.ext_flags_set_cfm.user_flags; ++ printk("cfm flags=%x\n", cfm.ext_flags_set_cfm.user_flags); ++ } ++ break; ++ ++ case EXT_FLAGS_GET_REQ: ++ /* Build the EXT_FLAGS_GET_REQ message */ ++ printk("ext_flags_get_req\n"); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (uint32_t)cfm.ext_flags_get_cfm.user_flags; ++ printk("cfm flags=%x\n", cfm.ext_flags_get_cfm.user_flags); ++ } ++ break; ++ ++ case EXT_FLAGS_MASK_SET_REQ: ++ /* Build the EXT_FLAGS_MASK_SET_REQ message */ ++ req->ext_flags_mask_set_req.user_flags_mask = (u32_l)param_in[0]; ++ req->ext_flags_mask_set_req.user_flags_val = (u32_l)param_in[1]; ++ printk("ext_flags_mask_set_req: flags mask=0x%x, val=0x%x\n", ++ req->ext_flags_mask_set_req.user_flags_mask, req->ext_flags_mask_set_req.user_flags_val); ++ /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); ++ if (!error) { ++ param_out[0] = (uint32_t)cfm.ext_flags_mask_set_cfm.user_flags; ++ printk("cfm flags=%x\n", cfm.ext_flags_mask_set_cfm.user_flags); ++ } ++ break; ++ ++ default: ++ error = -ENOMEM; ++ break; ++ } ++ ++ return error; ++} ++ ++int rwnx_send_mask_set_ext_flags_req(struct rwnx_hw *rwnx_hw, uint32_t flags_mask, uint32_t flags_val, struct mm_set_vendor_swconfig_cfm *cfm) ++{ ++ struct mm_set_vendor_swconfig_req *req; ++ int ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ /* Build the REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); ++ if (!req) { ++ AICWFDBG(LOGERROR, "%s msg_alloc fail\n", __func__); ++ return -ENOMEM; ++ } ++ req->swconfig_id = EXT_FLAGS_MASK_SET_REQ; ++ req->ext_flags_mask_set_req.user_flags_mask = (u32_l)flags_mask; ++ req->ext_flags_mask_set_req.user_flags_val = (u32_l)flags_val; ++ ++ ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); ++ if (!ret) { ++ AICWFDBG(LOGINFO, "curr ext_flags=%x\n", cfm->ext_flags_mask_set_cfm.user_flags); ++ } else { ++ AICWFDBG(LOGERROR, "%s send_msg_fail\n", __func__); ++ return ret; ++ } ++ return ret; ++} ++ ++#ifdef CONFIG_SDIO_BT ++int rwnx_sdio_bt_send_req(struct rwnx_hw *rwnx_hw,uint32_t len, struct sk_buff *skb) ++{ ++ struct mm_bt_send_req *req; ++ struct mm_bt_send_cfm cfm; ++ int error; ++ ++ if(testmode) { ++ AICWFDBG(LOGERROR, "%s testmode can not send\n", __func__); ++ return 0; ++ } ++ cfm.status = 0; ++ req = rwnx_msg_zalloc(TDLS_SDIO_BT_SEND_REQ, TASK_TDLS, DRV_TASK_ID, sizeof(struct mm_bt_send_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->data_len = len; ++ memcpy(req->bt_data,skb->data,len); ++ ++ error = rwnx_send_msg(rwnx_hw, req, 1, TDLS_SDIO_BT_SEND_CFM, &cfm); ++ if(!cfm.status){ ++ printk("bt send no cfm"); ++ } ++ ++ return error; ++} ++#endif ++ ++int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_version_cfm *cfm) ++{ ++ void *req; ++ int error; ++ ++ /* Build the MM_GET_FW_VERSION_REQ message */ ++ req = rwnx_msg_zalloc(MM_GET_FW_VERSION_REQ, TASK_MM, DRV_TASK_ID, sizeof(u8)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ /* Send the MM_GET_FW_VERSION_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_GET_FW_VERSION_CFM, cfm); ++ ++ return error; ++} ++ ++int rwnx_send_txpwr_lvl_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_req *txpwr_lvl_req; ++ txpwr_lvl_conf_v2_t txpwr_lvl_v2_tmp; ++ txpwr_lvl_conf_v2_t *txpwr_lvl_v2; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_req)); ++ ++ if (!txpwr_lvl_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_v2 = &txpwr_lvl_v2_tmp; ++ ++ get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_v2); ++ ++ if (txpwr_lvl_v2->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v2->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[11]); ++ ++ if ((testmode == 0) && (chip_sub_id == 0)) { ++ txpwr_lvl_req->txpwr_lvl.enable = txpwr_lvl_v2->enable; ++ txpwr_lvl_req->txpwr_lvl.dsss = txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]; // 11M ++ txpwr_lvl_req->txpwr_lvl.ofdmlowrate_2g4= txpwr_lvl_v2->pwrlvl_11ax_2g4[4]; // MCS4 ++ txpwr_lvl_req->txpwr_lvl.ofdm64qam_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[7]; // MCS7 ++ txpwr_lvl_req->txpwr_lvl.ofdm256qam_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[9]; // MCS9 ++ txpwr_lvl_req->txpwr_lvl.ofdm1024qam_2g4= txpwr_lvl_v2->pwrlvl_11ax_2g4[11]; // MCS11 ++ txpwr_lvl_req->txpwr_lvl.ofdmlowrate_5g = 13; // unused ++ txpwr_lvl_req->txpwr_lvl.ofdm64qam_5g = 13; // unused ++ txpwr_lvl_req->txpwr_lvl.ofdm256qam_5g = 13; // unused ++ txpwr_lvl_req->txpwr_lvl.ofdm1024qam_5g = 13; // unused ++ } else { ++ txpwr_lvl_req->txpwr_lvl_v2 = *txpwr_lvl_v2; ++ } ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_req *txpwr_lvl_req; ++ txpwr_lvl_conf_v3_t txpwr_lvl_v3_tmp; ++ txpwr_lvl_conf_v3_t *txpwr_lvl_v3; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++ int error; ++ int i; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_req)); ++ ++ if (!txpwr_lvl_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_v3 = &txpwr_lvl_v3_tmp; ++ txpwr_loss = &txpwr_loss_tmp; ++ txpwr_loss->loss_enable_2g4 = 0; ++ txpwr_loss->loss_enable_5g = 0; ++ ++ get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_v3); ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable_2g4 == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11ax_2g4[i] -= txpwr_loss->loss_value_2g4; ++ } ++ ++ if (txpwr_loss->loss_enable_5g == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11a_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v3->pwrlvl_11n_11ac_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11ax_5g[i] -= txpwr_loss->loss_value_5g; ++ } ++ ++ if (txpwr_lvl_v3->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v3->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_1m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_2m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_5m5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_11m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[11]); ++ ++ txpwr_lvl_req->txpwr_lvl_v3 = *txpwr_lvl_v3; ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_lvl_v4_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_req *txpwr_lvl_req; ++ txpwr_lvl_conf_v4_t txpwr_lvl_v4_tmp; ++ txpwr_lvl_conf_v4_t *txpwr_lvl_v4; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++ int error; ++ int i; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_req)); ++ ++ if (!txpwr_lvl_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_v4 = &txpwr_lvl_v4_tmp; ++ txpwr_loss = &txpwr_loss_tmp; ++ txpwr_loss->loss_enable_2g4 = 0; ++ txpwr_loss->loss_enable_5g = 0; ++ ++ get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_v4); ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable_2g4 == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[i] -= txpwr_loss->loss_value_2g4; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v4->pwrlvl_11ax_2g4[i] -= txpwr_loss->loss_value_2g4; ++ } ++ ++ if (txpwr_loss->loss_enable_5g == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ ++ for (i = 0; i <= 7; i++) ++ txpwr_lvl_v4->pwrlvl_11a_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v4->pwrlvl_11n_11ac_5g[i] -= txpwr_loss->loss_value_5g; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v4->pwrlvl_11ax_5g[i] -= txpwr_loss->loss_value_5g; ++ } ++ ++ ++ if (txpwr_lvl_v4->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v4->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[11]); ++ ++ txpwr_lvl_req->txpwr_lvl_v4 = *txpwr_lvl_v4; ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_lvl_adj_req *txpwr_lvl_adj_req; ++ txpwr_lvl_adj_conf_t txpwr_lvl_adj_tmp; ++ txpwr_lvl_adj_conf_t *txpwr_lvl_adj; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_LVL_REQ message */ ++ txpwr_lvl_adj_req = rwnx_msg_zalloc(MM_SET_TXPWR_LVL_ADJ_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_lvl_adj_req)); ++ ++ if (!txpwr_lvl_adj_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_lvl_adj = &txpwr_lvl_adj_tmp; ++ ++ get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj); ++ ++ if (txpwr_lvl_adj->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_lvl_adj_req); ++ return 0; ++ } else { ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_adj->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_1_4:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_5_9:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_10_13:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[2]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_42:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_58:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_106:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_122:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_138:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_155:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[5]); ++ ++ txpwr_lvl_adj_req->txpwr_lvl_adj = *txpwr_lvl_adj; ++ ++ /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_lvl_adj_req, 1, MM_SET_TXPWR_LVL_ADJ_CFM, NULL); ++ ++ return (error); ++ } ++} ++ ++int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_idx_req *txpwr_idx_req; ++ txpwr_idx_conf_t *txpwr_idx; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_IDX_LVL_REQ message */ ++ txpwr_idx_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_idx_req)); ++ ++ if (!txpwr_idx_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_idx = &txpwr_idx_req->txpwr_idx; ++ txpwr_idx->enable = 1; ++ txpwr_idx->dsss = 9; ++ txpwr_idx->ofdmlowrate_2g4 = 8; ++ txpwr_idx->ofdm64qam_2g4 = 8; ++ txpwr_idx->ofdm256qam_2g4 = 8; ++ txpwr_idx->ofdm1024qam_2g4 = 8; ++ txpwr_idx->ofdmlowrate_5g = 11; ++ txpwr_idx->ofdm64qam_5g = 10; ++ txpwr_idx->ofdm256qam_5g = 9; ++ txpwr_idx->ofdm1024qam_5g = 9; ++ ++ get_userconfig_txpwr_idx(txpwr_idx); ++ ++ if (txpwr_idx->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_idx_req); ++ return 0; ++ } else { ++ /* Send the MM_SET_TXPWR_IDX_LVL_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_idx_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); ++ ++ return error; ++ } ++}; ++ ++int rwnx_send_txpwr_ofst_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_ofst_req *txpwr_ofst_req; ++ txpwr_ofst_conf_t *txpwr_ofst; ++ int error; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_OFST_REQ message */ ++ txpwr_ofst_req = rwnx_msg_zalloc(MM_SET_TXPWR_OFST_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_ofst_req)); ++ ++ if (!txpwr_ofst_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_ofst = &txpwr_ofst_req->txpwr_ofst; ++ txpwr_ofst->enable = 1; ++ txpwr_ofst->chan_1_4 = 0; ++ txpwr_ofst->chan_5_9 = 0; ++ txpwr_ofst->chan_10_13 = 0; ++ txpwr_ofst->chan_36_64 = 0; ++ txpwr_ofst->chan_100_120 = 0; ++ txpwr_ofst->chan_122_140 = 0; ++ txpwr_ofst->chan_142_165 = 0; ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ get_userconfig_txpwr_ofst(txpwr_ofst); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst); ++ } ++ ++ if (txpwr_ofst->enable == 0) { ++ rwnx_msg_free(rwnx_hw, txpwr_ofst_req); ++ return 0; ++ } else { ++ /* Send the MM_SET_TXPWR_OFST_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_ofst_req, 1, MM_SET_TXPWR_OFST_CFM, NULL); ++ ++ return error; ++ } ++}; ++ ++int rwnx_send_txpwr_ofst2x_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_ofst_req *txpwr_ofst_req; ++ txpwr_ofst2x_conf_t *txpwr_ofst2x; ++ int error = 0; ++ int type, ch_grp; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_OFST_REQ message */ ++ txpwr_ofst_req = rwnx_msg_zalloc(MM_SET_TXPWR_OFST_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_ofst_req)); ++ ++ if (!txpwr_ofst_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_ofst2x = &txpwr_ofst_req->txpwr_ofst2x; ++ txpwr_ofst2x->enable = 0; ++ for (type = 0; type < 3; type++) { ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ if (ch_grp < 3) { ++ txpwr_ofst2x->pwrofst2x_tbl_2g4[type][ch_grp] = 0; ++ } ++ txpwr_ofst2x->pwrofst2x_tbl_5g[type][ch_grp] = 0; ++ } ++ } ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x); ++ } ++ if (txpwr_ofst2x->enable){ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_ofst2x->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g: [0]:11b, [1]:ofdm_highrate, [2]:ofdm_lowrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_2g4[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g: [0]:ofdm_lowrate, [1]:ofdm_highrate, [2]:ofdm_midrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_5g[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ ++ /* Send the MM_SET_TXPWR_OFST_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_ofst_req, 1, MM_SET_TXPWR_OFST_CFM, NULL); ++ }else{ ++ AICWFDBG(LOGINFO, "%s:Do not use txpwr_ofst2x\r\n", __func__); ++ rwnx_msg_free(rwnx_hw, txpwr_ofst_req); ++ } ++ ++ return (error); ++} ++ ++int rwnx_send_txpwr_ofst2x_v2_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct mm_set_txpwr_ofst_req *txpwr_ofst_req; ++ txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2; ++ int error = 0; ++ int type, ch_grp; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_TXPWR_OFST_REQ message */ ++ txpwr_ofst_req = rwnx_msg_zalloc(MM_SET_TXPWR_OFST_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_txpwr_ofst_req)); ++ ++ if (!txpwr_ofst_req) { ++ return -ENOMEM; ++ } ++ ++ txpwr_ofst2x_v2 = &txpwr_ofst_req->txpwr_ofst2x_v2; ++ txpwr_ofst2x_v2->enable = 0; ++ ++ get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_v2); ++ ++ if (txpwr_ofst2x_v2->enable){ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_ofst2x_v2->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g(ant0/ant1): [0]:11b, [1]:ofdm_highrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 2; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g(ant0/ant1): [0]:ofdm_highrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 1; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++ ++ /* Send the MM_SET_TXPWR_OFST_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, txpwr_ofst_req, 1, MM_SET_TXPWR_OFST_CFM, NULL); ++ }else{ ++ AICWFDBG(LOGINFO, "%s:Do not use txpwr_ofst2x_v2\r\n", __func__); ++ rwnx_msg_free(rwnx_hw, txpwr_ofst_req); ++ } ++ ++ return (error); ++} ++ ++#ifdef CONFIG_APF ++int rwnx_send_set_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len) ++{ ++ struct mm_set_apf_prog_req *req; ++ int error = 0; ++ int buffer_len, buffer_start = 0, buffer_end, page; ++ ++ /* current only 8800d80 support apf */ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80) { ++ return 0; ++ } ++ ++ if (!program) ++ return -ENOMEM; ++ ++ for (page = 0; buffer_start < program_len; page++) { ++ buffer_end = buffer_start + LMAC_MSG_MAX_LEN; ++ if (buffer_end > program_len) ++ buffer_end = program_len; ++ buffer_len = buffer_end - buffer_start; ++ ++ /* Build the MM_SET_TXOP_REQ message */ ++ req = rwnx_msg_zalloc(MM_SET_APF_PROG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_apf_prog_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ req->program_len = buffer_len; ++ req->offset = page; ++ memcpy(req->program, program + buffer_start, buffer_len); ++ buffer_start = buffer_end; ++ ++ /* Send the MM_SET_TXOP_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_APF_PROG_CFM, NULL); ++ if (error) ++ break; ++ } ++ return error; ++} ++ ++int rwnx_send_get_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len) ++{ ++ struct mm_get_apf_prog_req *req; ++ int error = 0; ++ struct mm_get_apf_prog_cfm cfm; ++ int buffer_len, buffer_start = 0, buffer_end, page; ++ ++ /* current only 8800d80 support apf */ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80) { ++ return 0; ++ } ++ ++ if (!program) ++ return -ENOMEM; ++ ++ for (page = 0; buffer_start < program_len; page++) { ++ buffer_end = buffer_start + LMAC_MSG_MAX_LEN; ++ if (buffer_end > program_len) ++ buffer_end = program_len; ++ buffer_len = buffer_end - buffer_start; ++ ++ /* Build the MM_SET_TXOP_REQ message */ ++ req = rwnx_msg_zalloc(MM_GET_APF_PROG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_get_apf_prog_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ req->offset = page; ++ /* Send the MM_GET_APF_PROG_REQ message to UMAC FW */ ++ error = rwnx_send_msg(rwnx_hw, req, 1, MM_GET_APF_PROG_CFM, &cfm); ++ if (error) ++ break; ++ ++ memcpy(program + buffer_start, cfm.program, buffer_len); ++ buffer_start = buffer_end; ++ } ++ ++ return error; ++} ++#endif ++ ++int rwnx_send_set_filter(struct rwnx_hw *rwnx_hw, uint32_t filter) ++{ ++ struct mm_set_filter_req *set_filter_req_param; ++ uint32_t rx_filter = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_SET_FILTER_REQ message */ ++ set_filter_req_param = ++ rwnx_msg_zalloc(MM_SET_FILTER_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_set_filter_req)); ++ if (!set_filter_req_param) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_SET_FILTER_REQ message */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ++ if (filter & FIF_PROMISC_IN_BSS) ++ rx_filter |= NXMAC_ACCEPT_UNICAST_BIT; ++#endif ++ if (filter & FIF_ALLMULTI) ++ rx_filter |= NXMAC_ACCEPT_MULTICAST_BIT; ++ ++ if (filter & (FIF_FCSFAIL | FIF_PLCPFAIL)) ++ rx_filter |= NXMAC_ACCEPT_ERROR_FRAMES_BIT; ++ ++ if (filter & FIF_BCN_PRBRESP_PROMISC) ++ rx_filter |= NXMAC_ACCEPT_OTHER_BSSID_BIT; ++ ++ if (filter & FIF_CONTROL) ++ rx_filter |= NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT | ++ NXMAC_ACCEPT_CF_END_BIT | ++ NXMAC_ACCEPT_ACK_BIT | ++ NXMAC_ACCEPT_CTS_BIT | ++ NXMAC_ACCEPT_RTS_BIT | ++ NXMAC_ACCEPT_BA_BIT | NXMAC_ACCEPT_BAR_BIT; ++ ++ if (filter & FIF_OTHER_BSS) ++ rx_filter |= NXMAC_ACCEPT_OTHER_BSSID_BIT; ++ ++ if (filter & FIF_PSPOLL) { ++ /* TODO: check if the MAC filters apply to our BSSID or is general */ ++ rx_filter |= NXMAC_ACCEPT_PS_POLL_BIT; ++ } ++ ++ if (filter & FIF_PROBE_REQ) { ++ rx_filter |= NXMAC_ACCEPT_PROBE_REQ_BIT; ++ rx_filter |= NXMAC_ACCEPT_ALL_BEACON_BIT; ++ } ++ ++ /* Add the filter flags that are set by default and cannot be changed here */ ++ rx_filter |= RWNX_MAC80211_NOT_CHANGEABLE; ++ ++ /* XXX */ ++ //if (ieee80211_hw_check(rwnx_hw->hw, AMPDU_AGGREGATION)) ++ rx_filter |= NXMAC_ACCEPT_BA_BIT; ++ ++ /* Now copy all the flags into the message parameter */ ++ set_filter_req_param->filter = rx_filter; ++ ++ RWNX_DBG("new total_flags = 0x%08x rx filter set to 0x%08x\r\n", ++ filter, rx_filter); ++ ++ /* Send the MM_SET_FILTER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_filter_req_param, 1, MM_SET_FILTER_CFM, NULL); ++} ++ ++ ++/****************************************************************************** ++ * Control messages handling functions (FULLMAC only) ++ *****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++extern struct ieee80211_sband_iftype_data rwnx_he_capa; ++#endif ++#ifdef CONFIG_VHT_FOR_OLD_KERNEL ++static struct ieee80211_sta_vht_cap* rwnx_vht_capa; ++#endif ++int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw) ++{ ++ struct me_config_req *req; ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ ++ struct ieee80211_sta_ht_cap *ht_cap; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ struct ieee80211_sta_vht_cap *vht_cap; ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ struct ieee80211_sta_he_cap const *he_cap = NULL; ++#else ++ #ifdef CONFIG_HE_FOR_OLD_KERNEL ++ struct ieee80211_sta_he_cap const *he_cap; ++ #endif ++#endif ++ uint8_t *ht_mcs; ++ int i; ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2) { ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->band_5g_support) { ++ ht_cap = &wiphy->bands[NL80211_BAND_5GHZ]->ht_cap; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ vht_cap = &wiphy->bands[NL80211_BAND_5GHZ]->vht_cap; ++ #endif ++ } else { ++ ht_cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ vht_cap = &wiphy->bands[NL80211_BAND_2GHZ]->vht_cap; ++ #endif ++ } ++ #ifdef CONFIG_VHT_FOR_OLD_KERNEL ++ rwnx_vht_capa = vht_cap; ++ #endif ++ ++ ht_mcs = (uint8_t *)&ht_cap->mcs; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_CONFIG_REQ message */ ++ req = rwnx_msg_zalloc(ME_CONFIG_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_config_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_CONFIG_REQ message */ ++ req->ht_supp = ht_cap->ht_supported; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ req->vht_supp = vht_cap->vht_supported; ++ #endif ++ req->ht_cap.ht_capa_info = cpu_to_le16(ht_cap->cap | IEEE80211_HT_CAP_LDPC_CODING); ++ req->ht_cap.a_mpdu_param = ht_cap->ampdu_factor | ++ (ht_cap->ampdu_density << ++ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); ++ for (i = 0; i < sizeof(ht_cap->mcs); i++) ++ req->ht_cap.mcs_rate[i] = ht_mcs[i]; ++ req->ht_cap.ht_extended_capa = 0; ++ req->ht_cap.tx_beamforming_capa = 0; ++ req->ht_cap.asel_capa = 0; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ if (req->vht_supp) { ++ req->vht_cap.vht_capa_info = cpu_to_le32(vht_cap->cap); ++ req->vht_cap.rx_highest = cpu_to_le16(vht_cap->vht_mcs.rx_highest); ++ req->vht_cap.rx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.rx_mcs_map); ++ req->vht_cap.tx_highest = cpu_to_le16(vht_cap->vht_mcs.tx_highest); ++ req->vht_cap.tx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.tx_mcs_map); ++ } ++ #endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) || defined(CONFIG_HE_FOR_OLD_KERNEL) ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (wiphy->bands[NL80211_BAND_2GHZ]->iftype_data != NULL) { ++ he_cap = &wiphy->bands[NL80211_BAND_2GHZ]->iftype_data->he_cap; ++ //} ++ #endif ++ #if defined(CONFIG_HE_FOR_OLD_KERNEL) ++ if (1) { ++ he_cap = &rwnx_he_capa.he_cap; ++ #endif ++ req->he_supp = he_cap->has_he; ++ for (i = 0; i < ARRAY_SIZE(he_cap->he_cap_elem.mac_cap_info); i++) { ++ req->he_cap.mac_cap_info[i] = he_cap->he_cap_elem.mac_cap_info[i]; ++ } ++ for (i = 0; i < ARRAY_SIZE(he_cap->he_cap_elem.phy_cap_info); i++) { ++ req->he_cap.phy_cap_info[i] = he_cap->he_cap_elem.phy_cap_info[i]; ++ } ++ req->he_cap.mcs_supp.rx_mcs_80 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_80); ++ req->he_cap.mcs_supp.tx_mcs_80 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_80); ++ req->he_cap.mcs_supp.rx_mcs_160 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_160); ++ req->he_cap.mcs_supp.tx_mcs_160 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_160); ++ req->he_cap.mcs_supp.rx_mcs_80p80 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_80p80); ++ req->he_cap.mcs_supp.tx_mcs_80p80 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_80p80); ++ for (i = 0; i < MAC_HE_PPE_THRES_MAX_LEN; i++) { ++ req->he_cap.ppe_thres[i] = he_cap->ppe_thres[i]; ++ } ++ req->he_ul_on = rwnx_hw->mod_params->he_ul_on; ++ } ++#else ++ req->he_supp = false; ++ req->he_ul_on = false; ++#endif ++ req->ps_on = rwnx_hw->mod_params->ps_on; ++ req->dpsm = rwnx_hw->mod_params->dpsm; ++ req->tx_lft = rwnx_hw->mod_params->tx_lft; ++ req->ant_div_on = rwnx_hw->mod_params->ant_div; ++ if (rwnx_hw->mod_params->use_80) ++ req->phy_bw_max = PHY_CHNL_BW_80; ++ else if (rwnx_hw->mod_params->use_2040) ++ req->phy_bw_max = PHY_CHNL_BW_40; ++ else ++ req->phy_bw_max = PHY_CHNL_BW_20; ++ ++ wiphy_info(wiphy, "HT supp %d, VHT supp %d, HE supp %d\n", req->ht_supp, ++ req->vht_supp, ++ req->he_supp); ++ /* Send the ME_CONFIG_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_CONFIG_CFM, NULL); ++} ++ ++int rwnx_send_me_chan_config_req(struct rwnx_hw *rwnx_hw, char *ccode) ++{ ++ struct me_chan_config_req *req; ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ int i; ++#ifdef CONFIG_POWER_LIMIT ++ int8_t max_pwr; ++ uint8_t r_idx; ++ txpwr_loss_conf_t txpwr_loss_tmp; ++ txpwr_loss_conf_t *txpwr_loss; ++#endif ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_CHAN_CONFIG_REQ message */ ++ req = rwnx_msg_zalloc(ME_CHAN_CONFIG_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_chan_config_req)); ++ if (!req) ++ return -ENOMEM; ++ ++#ifdef CONFIG_POWER_LIMIT ++ txpwr_loss = &txpwr_loss_tmp; ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__, ++ txpwr_loss->loss_value_2g4); ++ if (txpwr_loss->loss_enable_5g == 1) ++ AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__, ++ txpwr_loss->loss_value_5g); ++ r_idx = get_ccode_region(ccode); ++#endif ++ ++ req->chan2G4_cnt = 0; ++ if (wiphy->bands[NL80211_BAND_2GHZ] != NULL) { ++ struct ieee80211_supported_band *b = wiphy->bands[NL80211_BAND_2GHZ]; ++ for (i = 0; i < b->n_channels; i++) { ++ req->chan2G4[req->chan2G4_cnt].flags = 0; ++ if (b->channels[i].flags & IEEE80211_CHAN_DISABLED) ++ req->chan2G4[req->chan2G4_cnt].flags |= CHAN_DISABLED; ++ req->chan2G4[req->chan2G4_cnt].flags |= get_chan_flags(b->channels[i].flags); ++ req->chan2G4[req->chan2G4_cnt].band = NL80211_BAND_2GHZ; ++ req->chan2G4[req->chan2G4_cnt].freq = b->channels[i].center_freq; ++ req->chan2G4[req->chan2G4_cnt].tx_power = chan_to_fw_pwr(b->channels[i].max_power); ++#ifdef CONFIG_POWER_LIMIT ++ { ++ max_pwr = get_powerlimit_by_freq(PHY_BAND_2G4, req->chan2G4[req->chan2G4_cnt].freq, r_idx); ++ if (txpwr_loss->loss_enable_2g4 == 1) ++ max_pwr -= txpwr_loss->loss_value_2g4; ++ if (req->chan2G4[req->chan2G4_cnt].tx_power > max_pwr) ++ req->chan2G4[req->chan2G4_cnt].tx_power = max_pwr; ++ } ++#endif ++ req->chan2G4_cnt++; ++ if (req->chan2G4_cnt == MAC_DOMAINCHANNEL_24G_MAX) ++ break; ++ } ++ } ++ ++ req->chan5G_cnt = 0; ++ if (wiphy->bands[NL80211_BAND_5GHZ] != NULL) { ++ struct ieee80211_supported_band *b = wiphy->bands[NL80211_BAND_5GHZ]; ++ for (i = 0; i < b->n_channels; i++) { ++ req->chan5G[req->chan5G_cnt].flags = 0; ++ if (b->channels[i].flags & IEEE80211_CHAN_DISABLED) ++ req->chan5G[req->chan5G_cnt].flags |= CHAN_DISABLED; ++ req->chan5G[req->chan5G_cnt].flags |= get_chan_flags(b->channels[i].flags); ++ req->chan5G[req->chan5G_cnt].band = NL80211_BAND_5GHZ; ++ req->chan5G[req->chan5G_cnt].freq = b->channels[i].center_freq; ++ req->chan5G[req->chan5G_cnt].tx_power = chan_to_fw_pwr(b->channels[i].max_power); ++#ifdef CONFIG_POWER_LIMIT ++ { ++ max_pwr = get_powerlimit_by_freq( PHY_BAND_5G, req->chan5G[req->chan5G_cnt].freq, r_idx); ++ if (txpwr_loss->loss_enable_5g == 1) ++ max_pwr -= txpwr_loss->loss_value_5g; ++ if (req->chan5G[req->chan5G_cnt].tx_power > max_pwr) ++ req->chan5G[req->chan5G_cnt].tx_power = max_pwr; ++ } ++#endif ++ req->chan5G_cnt++; ++ if (req->chan5G_cnt == MAC_DOMAINCHANNEL_5G_MAX) ++ break; ++ } ++ } ++ ++ /* Send the ME_CHAN_CONFIG_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_CHAN_CONFIG_CFM, NULL); ++} ++ ++int rwnx_send_me_set_control_port_req(struct rwnx_hw *rwnx_hw, bool opened, u8 sta_idx) ++{ ++ struct me_set_control_port_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_SET_CONTROL_PORT_REQ message */ ++ req = rwnx_msg_zalloc(ME_SET_CONTROL_PORT_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_set_control_port_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_SET_CONTROL_PORT_REQ message */ ++ req->sta_idx = sta_idx; ++ req->control_port_open = opened; ++ ++ /* Send the ME_SET_CONTROL_PORT_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_CONTROL_PORT_CFM, NULL); ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)) ++struct ieee80211_he_cap_elem_4_19 { ++ u8 mac_cap_info[6]; ++ u8 phy_cap_info[11]; ++} __packed; ++#endif ++ ++int rwnx_send_me_sta_add(struct rwnx_hw *rwnx_hw, struct station_parameters *params, ++ const u8 *mac, u8 inst_nbr, struct me_sta_add_cfm *cfm) ++{ ++ struct me_sta_add_req *req; ++ ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ struct link_station_parameters *link_sta_params = ¶ms->link_sta_params; ++#else ++ struct station_parameters *link_sta_params = params; ++#endif ++ u8 *ht_mcs = (u8 *)&link_sta_params->ht_capa->mcs; ++ ++ int i; ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[inst_nbr]; ++ #if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ struct aic_sta *sta = &rwnx_hw->aic_table[rwnx_vif->ap.aic_index]; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("assoc_req idx %d, he: %d, vht: %d\n ", rwnx_vif->ap.aic_index, sta->he, sta->vht); ++ if (rwnx_vif->ap.aic_index < NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX) ++ rwnx_vif->ap.aic_index++; ++ else ++ rwnx_vif->ap.aic_index = 0; ++ #endif ++ ++ /* Build the MM_STA_ADD_REQ message */ ++ req = rwnx_msg_zalloc(ME_STA_ADD_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_sta_add_req)); ++ if (!req){ ++ return -ENOMEM; ++ } ++ ++ /* Set parameters for the MM_STA_ADD_REQ message */ ++ memcpy(&(req->mac_addr.array[0]), mac, ETH_ALEN); ++ ++ req->rate_set.length = link_sta_params->supported_rates_len; ++ for (i = 0; i < link_sta_params->supported_rates_len; i++) ++ req->rate_set.array[i] = link_sta_params->supported_rates[i]; ++ ++ req->flags = 0; ++ if (link_sta_params->ht_capa) { ++ const struct ieee80211_ht_cap *ht_capa = link_sta_params->ht_capa; ++ ++ req->flags |= STA_HT_CAPA; ++ req->ht_cap.ht_capa_info = cpu_to_le16(ht_capa->cap_info); ++ req->ht_cap.a_mpdu_param = ht_capa->ampdu_params_info; ++ for (i = 0; i < sizeof(ht_capa->mcs); i++) ++ req->ht_cap.mcs_rate[i] = ht_mcs[i]; ++ req->ht_cap.ht_extended_capa = cpu_to_le16(ht_capa->extended_ht_cap_info); ++ req->ht_cap.tx_beamforming_capa = cpu_to_le32(ht_capa->tx_BF_cap_info); ++ req->ht_cap.asel_capa = ht_capa->antenna_selection_info; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) ++ if (link_sta_params->vht_capa) { ++ const struct ieee80211_vht_cap *vht_capa = link_sta_params->vht_capa; ++ ++ req->flags |= STA_VHT_CAPA; ++ req->vht_cap.vht_capa_info = cpu_to_le32(vht_capa->vht_cap_info); ++ req->vht_cap.rx_highest = cpu_to_le16(vht_capa->supp_mcs.rx_highest); ++ req->vht_cap.rx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.rx_mcs_map); ++ req->vht_cap.tx_highest = cpu_to_le16(vht_capa->supp_mcs.tx_highest); ++ req->vht_cap.tx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.tx_mcs_map); ++ } ++#elif defined(CONFIG_VHT_FOR_OLD_KERNEL) ++ if (sta->vht) { ++ //const struct ieee80211_vht_cap *vht_capa = rwnx_vht_capa; ++ ++ req->flags |= STA_VHT_CAPA; ++ req->vht_cap.vht_capa_info = cpu_to_le32(rwnx_vht_capa->cap); ++ req->vht_cap.rx_highest = sta->supp_mcs.rx_highest;//cpu_to_le16(rwnx_vht_capa->vht_mcs.rx_highest); ++ req->vht_cap.rx_mcs_map = sta->supp_mcs.rx_mcs_map;//cpu_to_le16(rwnx_vht_capa->vht_mcs.rx_mcs_map); ++ req->vht_cap.tx_highest = sta->supp_mcs.tx_highest;//cpu_to_le16(rwnx_vht_capa->vht_mcs.tx_highest); ++ req->vht_cap.tx_mcs_map = sta->supp_mcs.tx_mcs_map;//cpu_to_le16(rwnx_vht_capa->vht_mcs.tx_mcs_map); ++ } ++#endif ++ ++ AICWFDBG(LOGDEBUG,"rx map %x rx high %x tx map %x tx high %x \n",req->vht_cap.rx_mcs_map,req->vht_cap.rx_highest,req->vht_cap.tx_mcs_map,req->vht_cap.tx_highest); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (link_sta_params->he_capa) { ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) ++ const struct ieee80211_he_cap_elem_4_19 *he_capa = (const struct ieee80211_he_cap_elem_4_19 *) link_sta_params->he_capa; ++ #else ++ const struct ieee80211_he_cap_elem *he_capa = link_sta_params->he_capa; ++ #endif ++ struct ieee80211_he_mcs_nss_supp *mcs_nss_supp = ++ (struct ieee80211_he_mcs_nss_supp *)(he_capa + 1); ++ ++ req->flags |= STA_HE_CAPA; ++ for (i = 0; i < ARRAY_SIZE(he_capa->mac_cap_info); i++) { ++ req->he_cap.mac_cap_info[i] = he_capa->mac_cap_info[i]; ++ } ++ for (i = 0; i < ARRAY_SIZE(he_capa->phy_cap_info); i++) { ++ req->he_cap.phy_cap_info[i] = he_capa->phy_cap_info[i]; ++ } ++ req->he_cap.mcs_supp.rx_mcs_80 = mcs_nss_supp->rx_mcs_80; ++ req->he_cap.mcs_supp.tx_mcs_80 = mcs_nss_supp->tx_mcs_80; ++ req->he_cap.mcs_supp.rx_mcs_160 = mcs_nss_supp->rx_mcs_160; ++ req->he_cap.mcs_supp.tx_mcs_160 = mcs_nss_supp->tx_mcs_160; ++ req->he_cap.mcs_supp.rx_mcs_80p80 = mcs_nss_supp->rx_mcs_80p80; ++ req->he_cap.mcs_supp.tx_mcs_80p80 = mcs_nss_supp->tx_mcs_80p80; ++ } ++#else ++ #ifdef CONFIG_HE_FOR_OLD_KERNEL ++ if (sta->he) { ++ const struct ieee80211_he_cap_elem *he_capa = &rwnx_he_capa.he_cap.he_cap_elem; ++ struct ieee80211_he_mcs_nss_supp *mcs_nss_supp = ++ (struct ieee80211_he_mcs_nss_supp *)(he_capa + 1); ++ req->flags |= STA_HE_CAPA; ++ for (i = 0; i < ARRAY_SIZE(he_capa->mac_cap_info); i++) { ++ req->he_cap.mac_cap_info[i] = sta->he_cap_elem.mac_cap_info[i];//he_capa->mac_cap_info[i]; ++ } ++ for (i = 0; i < ARRAY_SIZE(he_capa->phy_cap_info); i++) { ++ req->he_cap.phy_cap_info[i] = sta->he_cap_elem.phy_cap_info[i];//he_capa->phy_cap_info[i]; ++ } ++ req->he_cap.mcs_supp.rx_mcs_80 = sta->he_mcs_nss_supp.rx_mcs_80;//mcs_nss_supp->rx_mcs_80; ++ req->he_cap.mcs_supp.tx_mcs_80 = sta->he_mcs_nss_supp.tx_mcs_80;//mcs_nss_supp->tx_mcs_80; ++ req->he_cap.mcs_supp.rx_mcs_160 = mcs_nss_supp->rx_mcs_160; ++ req->he_cap.mcs_supp.tx_mcs_160 = mcs_nss_supp->tx_mcs_160; ++ req->he_cap.mcs_supp.rx_mcs_80p80 = mcs_nss_supp->rx_mcs_80p80; ++ req->he_cap.mcs_supp.tx_mcs_80p80 = mcs_nss_supp->tx_mcs_80p80; ++ } ++ #endif ++#endif ++ ++ AICWFDBG(LOGDEBUG,"rwnx sta add he mcs/nss rx mcs 80 0x%04x \n",le16_to_cpu(req->he_cap.mcs_supp.rx_mcs_80)); ++ AICWFDBG(LOGDEBUG,"rwnx sta add he mcs/nss tx mcs 80 0x%04x \n",le16_to_cpu(req->he_cap.mcs_supp.tx_mcs_80)); ++ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) ++ req->flags |= STA_QOS_CAPA; ++ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_MFP)) ++ req->flags |= STA_MFP_CAPA; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ if (link_sta_params->opmode_notif_used) { ++ req->flags |= STA_OPMOD_NOTIF; ++ req->opmode = link_sta_params->opmode_notif_used; ++ } ++ #endif ++ ++ req->aid = cpu_to_le16(params->aid); ++ req->uapsd_queues = params->uapsd_queues; ++ req->max_sp_len = params->max_sp * 2; ++ req->vif_idx = inst_nbr; ++ ++ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { ++ //struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[inst_nbr]; ++ req->tdls_sta = true; ++ if ((params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) && ++ !rwnx_vif->tdls_chsw_prohibited) ++ req->tdls_chsw_allowed = true; ++ if (rwnx_vif->tdls_status == TDLS_SETUP_RSP_TX) ++ req->tdls_sta_initiator = true; ++ } ++ ++ /* Send the ME_STA_ADD_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_STA_ADD_CFM, cfm); ++} ++ ++int rwnx_send_me_sta_del(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool tdls_sta) ++{ ++ struct me_sta_del_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_STA_DEL_REQ message */ ++ req = rwnx_msg_zalloc(ME_STA_DEL_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_sta_del_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_STA_DEL_REQ message */ ++ req->sta_idx = sta_idx; ++ req->tdls_sta = tdls_sta; ++ ++ /* Send the ME_STA_DEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_STA_DEL_CFM, NULL); ++} ++ ++int rwnx_send_me_traffic_ind(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool uapsd, u8 tx_status) ++{ ++ struct me_traffic_ind_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_UTRAFFIC_IND_REQ message */ ++ req = rwnx_msg_zalloc(ME_TRAFFIC_IND_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_traffic_ind_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_TRAFFIC_IND_REQ message */ ++ req->sta_idx = sta_idx; ++ req->tx_avail = tx_status; ++ req->uapsd = uapsd; ++ ++ /* Send the ME_TRAFFIC_IND_REQ to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_TRAFFIC_IND_CFM, NULL); ++} ++ ++int rwnx_send_me_rc_stats(struct rwnx_hw *rwnx_hw, ++ u8 sta_idx, ++ struct me_rc_stats_cfm *cfm) ++{ ++ struct me_rc_stats_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_RC_STATS_REQ message */ ++ req = rwnx_msg_zalloc(ME_RC_STATS_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_rc_stats_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_RC_STATS_REQ message */ ++ req->sta_idx = sta_idx; ++ ++ /* Send the ME_RC_STATS_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_RC_STATS_CFM, cfm); ++} ++ ++int rwnx_send_me_rc_set_rate(struct rwnx_hw *rwnx_hw, ++ u8 sta_idx, ++ u16 rate_cfg) ++{ ++ struct me_rc_set_rate_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_RC_SET_RATE_REQ message */ ++ req = rwnx_msg_zalloc(ME_RC_SET_RATE_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_rc_set_rate_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_RC_SET_RATE_REQ message */ ++ req->sta_idx = sta_idx; ++ req->fixed_rate_cfg = rate_cfg; ++ ++ /* Send the ME_RC_SET_RATE_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 0, 0, NULL); ++} ++ ++int rwnx_send_me_set_ps_mode(struct rwnx_hw *rwnx_hw, u8 ps_mode) ++{ ++ struct me_set_ps_mode_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_SET_PS_MODE_REQ message */ ++ req = rwnx_msg_zalloc(ME_SET_PS_MODE_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_set_ps_mode_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_SET_PS_MODE_REQ message */ ++ req->ps_state = ps_mode; ++ ++ /* Send the ME_SET_PS_MODE_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_PS_MODE_CFM, NULL); ++} ++ ++int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter) ++{ ++ struct me_set_lp_level_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ printk("%s %d %d \n", __func__, lp_level, disable_filter); ++ /* Build the ME_SET_LP_LEVEL_REQ message */ ++ req = rwnx_msg_zalloc(ME_SET_LP_LEVEL_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_set_lp_level_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the ME_SET_LP_LEVEL_REQ message */ ++ req->lp_level = lp_level; ++ req->disable_filter = disable_filter; ++ /* Send the ME_SET_LP_LEVEL_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_LP_LEVEL_CFM, NULL); ++} ++ ++int rwnx_send_sm_connect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct cfg80211_connect_params *sme, ++ struct sm_connect_cfm *cfm) ++{ ++ struct sm_connect_req *req; ++ int i; ++ u32_l flags = 0; ++ bool gval = false; ++ bool pval = false; ++ rwnx_vif->wep_enabled = false; ++ rwnx_vif->wep_auth_err = false; ++ rwnx_vif->last_auth_type = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SM_CONNECT_REQ message */ ++ req = rwnx_msg_zalloc(SM_CONNECT_REQ, TASK_SM, DRV_TASK_ID, ++ sizeof(struct sm_connect_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if ((sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)) { ++ gval = true; ++ } ++ ++ if (sme->crypto.n_ciphers_pairwise && ++ ((sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104))) { ++ pval = true; ++ } ++ ++ /* Set parameters for the SM_CONNECT_REQ message */ ++ if (sme->crypto.n_ciphers_pairwise && ++ ((sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_TKIP) || ++ (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104))) ++ flags |= DISABLE_HT; ++ ++ if (sme->crypto.control_port) ++ flags |= CONTROL_PORT_HOST; ++ ++ if (sme->crypto.control_port_no_encrypt) ++ flags |= CONTROL_PORT_NO_ENC; ++ ++ if (use_pairwise_key(&sme->crypto)) ++ flags |= WPA_WPA2_IN_USE; ++ ++ if (sme->mfp == NL80211_MFP_REQUIRED) ++ flags |= MFP_IN_USE; ++ ++ if (rwnx_vif->sta.ap) ++ flags |= REASSOCIATION; ++ ++ req->ctrl_port_ethertype = sme->crypto.control_port_ethertype; ++ ++ if (sme->bssid) ++ memcpy(&req->bssid, sme->bssid, ETH_ALEN); ++ else ++ req->bssid = mac_addr_bcst; ++ req->vif_idx = rwnx_vif->vif_index; ++ if (sme->channel) { ++ req->chan.band = sme->channel->band; ++ req->chan.freq = sme->channel->center_freq; ++ req->chan.flags = get_chan_flags(sme->channel->flags); ++ } else { ++ req->chan.freq = (u16_l)-1; ++ } ++ for (i = 0; i < sme->ssid_len; i++) ++ req->ssid.array[i] = sme->ssid[i]; ++ req->ssid.length = sme->ssid_len; ++ req->flags = flags; ++ if (WARN_ON(sme->ie_len > sizeof(req->ie_buf))) ++ goto invalid_param; ++ if (sme->ie_len) ++ memcpy(req->ie_buf, sme->ie, sme->ie_len); ++ req->ie_len = sme->ie_len; ++ req->listen_interval = rwnx_mod_params.listen_itv; ++ req->dont_wait_bcmc = !rwnx_mod_params.listen_bcmc; ++ ++ /* Set auth_type */ ++ if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) ++ req->auth_type = WLAN_AUTH_OPEN; ++ else if (sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ++ req->auth_type = WLAN_AUTH_OPEN; ++ else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ++ req->auth_type = WLAN_AUTH_SHARED_KEY; ++ else if (sme->auth_type == NL80211_AUTHTYPE_FT) { ++ req->auth_type = WLAN_AUTH_FT; ++ } else if (sme->auth_type == NL80211_AUTHTYPE_SAE) ++ req->auth_type = WLAN_AUTH_SAE; ++ else ++ goto invalid_param; ++ ++ /* Set UAPSD queues */ ++ req->uapsd_queues = rwnx_mod_params.uapsd_queues; ++ ++ rwnx_vif->wep_enabled = pval & gval; ++ ++ if (rwnx_vif->wep_enabled) { ++ rwnx_vif->last_auth_type = sme->auth_type; ++ } ++ ++ rwnx_vif->sta.ssid_len = (int)sme->ssid_len; ++ memset(rwnx_vif->sta.ssid, 0, rwnx_vif->sta.ssid_len + 1); ++ memcpy(rwnx_vif->sta.ssid, sme->ssid, rwnx_vif->sta.ssid_len); ++ if (sme->bssid) ++ memcpy(rwnx_vif->sta.bssid, sme->bssid, ETH_ALEN); ++ ++ printk("%s drv_vif_index:%d connect to %s(%d) channel:%d auth_type:%d\r\n", ++ __func__, ++ rwnx_vif->drv_vif_index, ++ rwnx_vif->sta.ssid, ++ rwnx_vif->sta.ssid_len, ++ req->chan.freq, ++ req->auth_type); ++ ++ /* Send the SM_CONNECT_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SM_CONNECT_CFM, cfm); ++ ++invalid_param: ++ rwnx_msg_free(rwnx_hw, req); ++ return -EINVAL; ++} ++ ++int rwnx_send_sm_disconnect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 reason) ++{ ++ struct sm_disconnect_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SM_DISCONNECT_REQ message */ ++ req = rwnx_msg_zalloc(SM_DISCONNECT_REQ, TASK_SM, DRV_TASK_ID, ++ sizeof(struct sm_disconnect_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the SM_DISCONNECT_REQ message */ ++ req->reason_code = reason; ++ req->vif_idx = rwnx_vif->vif_index; ++ ++ /* Send the SM_DISCONNECT_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SM_DISCONNECT_CFM, NULL); ++} ++ ++int rwnx_send_sm_external_auth_required_rsp(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 status) ++{ ++ struct sm_external_auth_required_rsp *rsp; ++ ++ /* Build the SM_EXTERNAL_AUTH_CFM message */ ++ rsp = rwnx_msg_zalloc(SM_EXTERNAL_AUTH_REQUIRED_RSP, TASK_SM, DRV_TASK_ID, ++ sizeof(struct sm_external_auth_required_rsp)); ++ if (!rsp) ++ return -ENOMEM; ++ ++ rsp->status = status; ++ rsp->vif_idx = rwnx_vif->vif_index; ++ ++ /* send the SM_EXTERNAL_AUTH_REQUIRED_RSP message UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, rsp, 1, SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM, NULL); ++} ++ ++int rwnx_send_apm_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_ap_settings *settings, ++ struct apm_start_cfm *cfm, ++ struct rwnx_ipc_elem_var *elem) ++{ ++ struct apm_start_req *req; ++ struct rwnx_bcn *bcn = &vif->ap.bcn; ++ u8 *buf; ++ u32 flags = 0; ++ const u8 *rate_ie; ++ u8 rate_len = 0; ++ int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); ++ const u8 *var_pos; ++ int len, i; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_START_REQ message */ ++ req = rwnx_msg_zalloc(APM_START_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_start_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ // Build the beacon ++ bcn->dtim = (u8)settings->dtim_period; ++ buf = rwnx_build_bcn(bcn, &settings->beacon); ++ if (!buf) { ++ rwnx_msg_free(rwnx_hw, req); ++ return -ENOMEM; ++ } ++ ++ // Retrieve the basic rate set from the beacon buffer ++ len = bcn->len - var_offset; ++ var_pos = buf + var_offset; ++ ++// Assume that rate higher that 54 Mbps are BSS membership ++#define IS_BASIC_RATE(r) ((r & 0x80) && ((r & ~0x80) <= (54 * 2))) ++ ++ rate_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); ++ if (rate_ie) { ++ const u8 *rates = rate_ie + 2; ++ for (i = 0; (i < rate_ie[1]) && (rate_len < MAC_RATESET_LEN); i++) { ++ if (IS_BASIC_RATE(rates[i])) ++ req->basic_rates.array[rate_len++] = rates[i]; ++ } ++ } ++ rate_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, var_pos, len); ++ if (rate_ie) { ++ const u8 *rates = rate_ie + 2; ++ for (i = 0; (i < rate_ie[1]) && (rate_len < MAC_RATESET_LEN); i++) { ++ if (IS_BASIC_RATE(rates[i])) ++ req->basic_rates.array[rate_len++] = rates[i]; ++ } ++ } ++ req->basic_rates.length = rate_len; ++#undef IS_BASIC_RATE ++ ++#if 0 ++ // Sync buffer for FW ++ error = rwnx_ipc_elem_var_allocs(rwnx_hw, elem, bcn->len, DMA_TO_DEVICE, buf, NULL, NULL); ++ if (error) { ++ return error; ++ } ++#else ++ rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn->len); ++#endif ++ ++ /* Set parameters for the APM_START_REQ message */ ++ req->vif_idx = vif->vif_index; ++ req->bcn_addr = elem->dma_addr; ++ req->bcn_len = bcn->len; ++ req->tim_oft = bcn->head_len; ++ req->tim_len = bcn->tim_len; ++ req->chan.band = settings->chandef.chan->band; ++ req->chan.freq = settings->chandef.chan->center_freq; ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ req->chan.flags = get_chan_flags(settings->chandef.chan->flags); ++#else ++ req->chan.flags = 0; ++#endif ++ printk("chan.flags %u \n",req->chan.flags); ++ req->chan.tx_power = chan_to_fw_pwr(settings->chandef.chan->max_power); ++ req->center_freq1 = settings->chandef.center_freq1; ++ req->center_freq2 = settings->chandef.center_freq2; ++ req->ch_width = bw2chnl[settings->chandef.width]; ++ req->bcn_int = settings->beacon_interval; ++ if (settings->crypto.control_port) ++ flags |= CONTROL_PORT_HOST; ++ ++ if (settings->crypto.control_port_no_encrypt) ++ flags |= CONTROL_PORT_NO_ENC; ++ ++ if (use_pairwise_key(&settings->crypto)) ++ flags |= WPA_WPA2_IN_USE; ++ ++ if (settings->crypto.control_port_ethertype) ++ req->ctrl_port_ethertype = settings->crypto.control_port_ethertype; ++ else ++ req->ctrl_port_ethertype = ETH_P_PAE; ++ req->flags = flags; ++ ++ /* Send the APM_START_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_START_CFM, cfm); ++} ++ ++int rwnx_send_apm_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif) ++{ ++ struct apm_stop_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_STOP_REQ message */ ++ req = rwnx_msg_zalloc(APM_STOP_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_stop_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the APM_STOP_REQ message */ ++ req->vif_idx = vif->vif_index; ++ ++ /* Send the APM_STOP_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_STOP_CFM, NULL); ++} ++ ++uint8_t scanning;// = 0; ++ ++#define P2P_WILDCARD_SSID "DIRECT-" ++#define P2P_WILDCARD_SSID_LEN (sizeof(P2P_WILDCARD_SSID) - 1) ++ ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++u8_l vendor_extension_data[256]; ++u8_l vendor_extension_len = 0; ++#if 0 ++u8_l vendor_extension_data[]={ ++ 0x10,0x49,0x00,0x17,0x00,0x01,0x37,0x10, ++ 0x06,0x00,0x10,0xc5,0xc9,0x91,0xeb,0x1f, ++ 0xce,0x4d,0x00,0xa1,0x2a,0xdf,0xa1,0xe9, ++ 0xc3,0x44,0xe6,0x10,0x49,0x00,0x21,0x00, ++ 0x01,0x37,0x20,0x01,0x00,0x01,0x05,0x20, ++ 0x02,0x00,0x04,0x43,0x56,0x54,0x45,0x20, ++ 0x05,0x00,0x0d,0x31,0x39,0x32,0x2e,0x31, ++ 0x36,0x38,0x2e,0x31,0x35,0x34,0x2e,0x31}; ++#endif ++ ++void rwnx_insert_vendor_extension_data(struct scanu_vendor_ie_req *ie_req){ ++ u8_l temp_ie[256]; ++ u8_l vendor_extension_subelement[3] = {0x00,0x37,0x2A}; ++ u8_l vendor_extension_id[2] = {0x10,0x49}; ++ int index = 0; ++ int vendor_extension_subelement_len = 0; ++ ++ memset(temp_ie, 0, 256); ++ ++ //find vendor_extension_subelement ++ for(index = 0; index < ie_req->add_ie_len; index++){ ++ if(ie_req->ie[index] == vendor_extension_id[0]){ ++ index++; ++ if(index == ie_req->add_ie_len){ ++ return; ++ } ++ if(ie_req->ie[index] == vendor_extension_id[1] && ++ ie_req->ie[index + 3] == vendor_extension_subelement[0]&& ++ ie_req->ie[index + 4] == vendor_extension_subelement[1]&& ++ ie_req->ie[index + 5] == vendor_extension_subelement[2]){ ++ index = index + 2; ++ vendor_extension_subelement_len = ie_req->ie[index]; ++ printk("%s find vendor_extension_subelement,index:%d len:%d\r\n", __func__, index, ie_req->ie[index]); ++ break; ++ } ++ } ++ } ++ index = index + vendor_extension_subelement_len; ++ ++ //insert vendor extension ++ memcpy(&temp_ie[0], ie_req->ie, index + 1); ++ memcpy(&temp_ie[index + 1], vendor_extension_data, vendor_extension_len/*sizeof(vendor_extension_data)*/);//insert vendor extension data ++ memcpy(&temp_ie[index + 1 + vendor_extension_len/*sizeof(vendor_extension_data)*/], &ie_req->ie[index + 1], ie_req->add_ie_len - index); ++ ++ memcpy(ie_req->ie, temp_ie, ie_req->add_ie_len + vendor_extension_len/*sizeof(vendor_extension_data)*/); ++ ie_req->add_ie_len = ie_req->add_ie_len + vendor_extension_len/*sizeof(vendor_extension_data)*/; ++ ie_req->ie[1] = ie_req->ie[1] + vendor_extension_len/*sizeof(vendor_extension_data)*/; ++ ++ //rwnx_data_dump((char*)__func__, (void*)ie_req->ie, ie_req->add_ie_len); ++} ++#endif//CONFIG_SET_VENDOR_EXTENSION_IE ++ ++ ++int rwnx_send_scanu_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct cfg80211_scan_request *param) ++{ ++ struct scanu_start_req *req = NULL; ++ struct scanu_vendor_ie_req *ie_req = NULL; ++ struct mm_add_if_cfm add_if_cfm; ++ int i; ++ uint8_t chan_flags = 0; ++ int err; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SCANU_START_REQ message */ ++ req = rwnx_msg_zalloc(SCANU_START_REQ, TASK_SCANU, DRV_TASK_ID, ++ sizeof(struct scanu_start_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ scanning = 1; ++ /* Set parameters */ ++ req->vif_idx = rwnx_vif->vif_index; ++ req->chan_cnt = (u8)min_t(int, SCAN_CHANNEL_MAX, param->n_channels); ++ req->ssid_cnt = (u8)min_t(int, SCAN_SSID_MAX, param->n_ssids); ++ req->bssid = mac_addr_bcst; ++ req->no_cck = param->no_cck; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) ++ if (param->duration_mandatory) ++ //req->duration = ieee80211_tu_to_usec(param->duration); ++ req->duration = 0; ++#endif ++ ++#ifdef CONFIG_RADAR_OR_IR_DETECT ++ if (req->ssid_cnt == 0) ++ chan_flags |= CHAN_NO_IR; ++#endif ++ for (i = 0; i < req->ssid_cnt; i++) { ++ int j; ++ for (j = 0; j < param->ssids[i].ssid_len; j++) ++ req->ssid[i].array[j] = param->ssids[i].ssid[j]; ++ req->ssid[i].length = param->ssids[i].ssid_len; ++ ++ if (!memcmp(P2P_WILDCARD_SSID, param->ssids[i].ssid, ++ P2P_WILDCARD_SSID_LEN)) { ++ AICWFDBG(LOGINFO, "p2p scanu:%d,%d,%d\n", rwnx_vif->vif_index, rwnx_vif->is_p2p_vif, rwnx_hw->is_p2p_alive); ++#ifdef CONFIG_USE_P2P0 ++ if (rwnx_vif->is_p2p_vif && !rwnx_hw->is_p2p_alive) { ++#else ++ if (rwnx_vif == rwnx_hw->p2p_dev_vif && !rwnx_vif->up) { ++#endif ++ err = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, ++ RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); ++ if (err) ++ goto error; ++ ++ if (add_if_cfm.status != 0) { ++ return -EIO; ++ } ++ ++ /* Save the index retrieved from LMAC */ ++ spin_lock_bh(&rwnx_hw->cb_lock); ++ rwnx_vif->vif_index = add_if_cfm.inst_nbr; ++ rwnx_vif->up = true; ++ rwnx_hw->vif_started++; ++ rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; ++ spin_unlock_bh(&rwnx_hw->cb_lock); ++ } ++ rwnx_hw->is_p2p_alive = 1; ++#ifndef CONFIG_USE_P2P0 ++ mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); ++ atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); ++#endif ++ AICWFDBG(LOGINFO, "p2p scan start\n"); ++ } ++ } ++ ++#if 1 ++ if (param->ie) { ++ #if 0 ++ if (rwnx_ipc_elem_var_allocs(rwnx_hw, &rwnx_hw->scan_ie, ++ param->ie_len, DMA_TO_DEVICE, ++ NULL, param->ie, NULL)) ++ goto error; ++ ++ req->add_ie_len = param->ie_len; ++ req->add_ies = rwnx_hw->scan_ie.dma_addr; ++ #else ++ ie_req = rwnx_msg_zalloc(SCANU_VENDOR_IE_REQ, TASK_SCANU, DRV_TASK_ID, ++ sizeof(struct scanu_vendor_ie_req)); ++ if (!ie_req) ++ return -ENOMEM; ++ ++ ie_req->add_ie_len = param->ie_len; ++ ie_req->vif_idx = rwnx_vif->vif_index; ++ memcpy(ie_req->ie, param->ie, param->ie_len); ++#ifdef CONFIG_SET_VENDOR_EXTENSION_IE ++ rwnx_insert_vendor_extension_data(ie_req); ++#endif //CONFIG_SET_VENDOR_EXTENSION_IE ++ req->add_ie_len = 0; ++ req->add_ies = 0; ++ ++ err = rwnx_send_msg(rwnx_hw, ie_req, 1, SCANU_VENDOR_IE_CFM, NULL); ++ if (err) ++ goto error; ++ #endif ++ } ++ else { ++ req->add_ie_len = 0; ++ req->add_ies = 0; ++ } ++#else ++ req->add_ie_len = 0; ++ req->add_ies = 0; ++#endif ++ ++ for (i = 0; i < req->chan_cnt; i++) { ++ struct ieee80211_channel *chan = param->channels[i]; ++ AICWFDBG(LOGDEBUG, "scan channel:%d(%d) \r\n", ieee80211_frequency_to_channel(chan->center_freq), chan->center_freq); ++ req->chan[i].band = chan->band; ++ req->chan[i].freq = chan->center_freq; ++ req->chan[i].flags = chan_flags | get_chan_flags(chan->flags); ++ req->chan[i].tx_power = chan_to_fw_pwr(chan->max_reg_power); ++ } ++ ++ /* Send the SCANU_START_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SCANU_START_CFM_ADDTIONAL, NULL); ++error: ++ if (req != NULL) ++ rwnx_msg_free(rwnx_hw, req); ++ if (ie_req != NULL) ++ rwnx_msg_free(rwnx_hw, ie_req); ++ return -ENOMEM; ++} ++ ++int rwnx_send_scanu_cancel_req(struct rwnx_hw *rwnx_hw, struct scan_cancel_cfm *cfm) ++{ ++ struct scan_cancel_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the SCAN_CANCEL_REQ message */ ++ req = rwnx_msg_zalloc(SCANU_CANCEL_REQ, TASK_SCANU, DRV_TASK_ID, ++ sizeof(struct scan_cancel_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Send the SCAN_CANCEL_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, SCANU_CANCEL_CFM, cfm); ++} ++ ++int rwnx_send_apm_start_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_chan_def *chandef, ++ struct apm_start_cac_cfm *cfm) ++{ ++ struct apm_start_cac_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_START_CAC_REQ message */ ++ req = rwnx_msg_zalloc(APM_START_CAC_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_start_cac_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the APM_START_CAC_REQ message */ ++ req->vif_idx = vif->vif_index; ++ req->chan.band = chandef->chan->band; ++ req->chan.type = bw2chnl[chandef->width]; ++ req->chan.prim20_freq = chandef->chan->center_freq; ++ req->chan.center1_freq = chandef->center_freq1; ++ req->chan.center2_freq = chandef->center_freq2; ++ req->chan.tx_power = 20; ++ req->chan.flags = get_chan_flags(chandef->chan->flags); ++ ++ /* Send the APM_START_CAC_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_START_CAC_CFM, cfm); ++} ++ ++int rwnx_send_apm_stop_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif) ++{ ++ struct apm_stop_cac_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the APM_STOP_CAC_REQ message */ ++ req = rwnx_msg_zalloc(APM_STOP_CAC_REQ, TASK_APM, DRV_TASK_ID, ++ sizeof(struct apm_stop_cac_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the APM_STOP_CAC_REQ message */ ++ req->vif_idx = vif->vif_index; ++ ++ /* Send the APM_STOP_CAC_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, APM_STOP_CAC_CFM, NULL); ++} ++ ++int rwnx_send_mesh_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ const struct mesh_config *conf, const struct mesh_setup *setup, ++ struct mesh_start_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_start_req *req; ++ // Supported basic rates ++ struct ieee80211_supported_band *band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ /* Counter */ ++ int i; ++ /* Return status */ ++ int status; ++ /* DMA Address to be unmapped after confirmation reception */ ++ u32 dma_addr = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_START_REQ message */ ++ req = rwnx_msg_zalloc(MESH_START_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_start_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->vif_index = vif->vif_index; ++ req->bcn_int = setup->beacon_interval; ++ req->dtim_period = setup->dtim_period; ++ req->mesh_id_len = setup->mesh_id_len; ++ ++ for (i = 0; i < setup->mesh_id_len; i++) { ++ req->mesh_id[i] = *(setup->mesh_id + i); ++ } ++ ++ req->user_mpm = setup->user_mpm; ++ req->is_auth = setup->is_authenticated; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) ++ req->auth_id = setup->auth_id; ++ #endif ++ req->ie_len = setup->ie_len; ++ ++ if (setup->ie_len) { ++ /* ++ * Need to provide a Virtual Address to the MAC so that it can download the ++ * additional information elements. ++ */ ++ req->ie_addr = dma_map_single(rwnx_hw->dev, (void *)setup->ie, ++ setup->ie_len, DMA_FROM_DEVICE); ++ ++ /* Check DMA mapping result */ ++ if (dma_mapping_error(rwnx_hw->dev, req->ie_addr)) { ++ printk(KERN_CRIT "%s - DMA Mapping error on additional IEs\n", __func__); ++ ++ /* Consider there is no Additional IEs */ ++ req->ie_len = 0; ++ } else { ++ /* Store DMA Address so that we can unmap the memory section once MESH_START_CFM is received */ ++ dma_addr = req->ie_addr; ++ } ++ } ++ ++ /* Provide rate information */ ++ req->basic_rates.length = 0; ++ for (i = 0; i < band_2GHz->n_bitrates; i++) { ++ u16 rate = band_2GHz->bitrates[i].bitrate; ++ ++ /* Read value is in in units of 100 Kbps, provided value is in units ++ * of 1Mbps, and multiplied by 2 so that 5.5 becomes 11 */ ++ rate = (rate << 1) / 10; ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) // TODO: check basic rates ++ if (setup->basic_rates & CO_BIT(i)) { ++ rate |= 0x80; ++ } ++ #endif ++ ++ req->basic_rates.array[i] = (u8)rate; ++ req->basic_rates.length++; ++ } ++ ++ /* Provide channel information */ ++ req->chan.band = setup->chandef.chan->band; ++ req->chan.freq = setup->chandef.chan->center_freq; ++ req->chan.flags = 0; ++ req->chan.tx_power = chan_to_fw_pwr(setup->chandef.chan->max_power); ++ req->center_freq1 = setup->chandef.center_freq1; ++ req->center_freq2 = setup->chandef.center_freq2; ++ req->ch_width = bw2chnl[setup->chandef.width]; ++ ++ /* Send the MESH_START_REQ message to UMAC FW */ ++ status = rwnx_send_msg(rwnx_hw, req, 1, MESH_START_CFM, cfm); ++ ++ /* Unmap DMA area */ ++ if (setup->ie_len) { ++ dma_unmap_single(rwnx_hw->dev, dma_addr, setup->ie_len, DMA_TO_DEVICE); ++ } ++ ++ /* Return the status */ ++ return status; ++} ++ ++int rwnx_send_mesh_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct mesh_stop_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_stop_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_STOP_REQ message */ ++ req = rwnx_msg_zalloc(MESH_STOP_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_stop_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->vif_idx = vif->vif_index; ++ ++ /* Send the MESH_STOP_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_STOP_CFM, cfm); ++} ++ ++int rwnx_send_mesh_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u32 mask, const struct mesh_config *p_mconf, struct mesh_update_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_update_req *req; ++ // Keep only bit for fields which can be updated ++ u32 supp_mask = (mask << 1) & (CO_BIT(NL80211_MESHCONF_GATE_ANNOUNCEMENTS) ++ | CO_BIT(NL80211_MESHCONF_HWMP_ROOTMODE) ++ | CO_BIT(NL80211_MESHCONF_FORWARDING) ++ | CO_BIT(NL80211_MESHCONF_POWER_MODE)); ++ ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (!supp_mask) { ++ return -ENOENT; ++ } ++ ++ /* Build the MESH_UPDATE_REQ message */ ++ req = rwnx_msg_zalloc(MESH_UPDATE_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_update_req)); ++ ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->vif_idx = vif->vif_index; ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_GATE_ANNOUNCEMENTS)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_GATE_MODE_BIT); ++ req->gate_announ = p_mconf->dot11MeshGateAnnouncementProtocol; ++ } ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_HWMP_ROOTMODE)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_ROOT_MODE_BIT); ++ req->root_mode = p_mconf->dot11MeshHWMPRootMode; ++ } ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_FORWARDING)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_MESH_FWD_BIT); ++ req->mesh_forward = p_mconf->dot11MeshForwarding; ++ } ++ ++ if (supp_mask & CO_BIT(NL80211_MESHCONF_POWER_MODE)) { ++ req->flags |= CO_BIT(MESH_UPDATE_FLAGS_LOCAL_PSM_BIT); ++ req->local_ps_mode = p_mconf->power_mode; ++ } ++ ++ /* Send the MESH_UPDATE_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_UPDATE_CFM, cfm); ++} ++ ++int rwnx_send_mesh_peer_info_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, struct mesh_peer_info_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_peer_info_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PEER_INFO_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PEER_INFO_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_peer_info_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->sta_idx = sta_idx; ++ ++ /* Send the MESH_PEER_INFO_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_PEER_INFO_CFM, cfm); ++} ++ ++void rwnx_send_mesh_peer_update_ntf(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, u8 mlink_state) ++{ ++ // Message to send ++ struct mesh_peer_update_ntf *ntf; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PEER_UPDATE_NTF message */ ++ ntf = rwnx_msg_zalloc(MESH_PEER_UPDATE_NTF, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_peer_update_ntf)); ++ ++ if (ntf) { ++ ntf->vif_idx = vif->vif_index; ++ ntf->sta_idx = sta_idx; ++ ntf->state = mlink_state; ++ ++ /* Send the MESH_PEER_INFO_REQ message to UMAC FW */ ++ rwnx_send_msg(rwnx_hw, ntf, 0, 0, NULL); ++ } ++} ++ ++void rwnx_send_mesh_path_create_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *tgt_addr) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Check if we are already waiting for a confirmation */ ++ if (!vif->ap.create_path) { ++ // Message to send ++ struct mesh_path_create_req *req; ++ ++ /* Build the MESH_PATH_CREATE_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PATH_CREATE_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_path_create_req)); ++ ++ if (req) { ++ req->vif_idx = vif->vif_index; ++ memcpy(&req->tgt_mac_addr, tgt_addr, ETH_ALEN); ++ ++ vif->ap.create_path = true; ++ ++ /* Send the MESH_PATH_CREATE_REQ message to UMAC FW */ ++ rwnx_send_msg(rwnx_hw, req, 0, 0, NULL); ++ } ++ } ++} ++ ++int rwnx_send_mesh_path_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, const u8 *tgt_addr, ++ const u8 *p_nhop_addr, struct mesh_path_update_cfm *cfm) ++{ ++ // Message to send ++ struct mesh_path_update_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PATH_UPDATE_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PATH_UPDATE_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_path_update_req)); ++ if (!req) { ++ return -ENOMEM; ++ } ++ ++ req->delete = (p_nhop_addr == NULL); ++ req->vif_idx = vif->vif_index; ++ memcpy(&req->tgt_mac_addr, tgt_addr, ETH_ALEN); ++ ++ if (p_nhop_addr) { ++ memcpy(&req->nhop_mac_addr, p_nhop_addr, ETH_ALEN); ++ } ++ ++ /* Send the MESH_PATH_UPDATE_REQ message to UMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MESH_PATH_UPDATE_CFM, cfm); ++} ++ ++void rwnx_send_mesh_proxy_add_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *ext_addr) ++{ ++ // Message to send ++ struct mesh_proxy_add_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MESH_PROXY_ADD_REQ message */ ++ req = rwnx_msg_zalloc(MESH_PROXY_ADD_REQ, TASK_MESH, DRV_TASK_ID, ++ sizeof(struct mesh_proxy_add_req)); ++ ++ if (req) { ++ req->vif_idx = vif->vif_index; ++ memcpy(&req->ext_sta_addr, ext_addr, ETH_ALEN); ++ ++ /* Send the MESH_PROXY_ADD_REQ message to UMAC FW */ ++ rwnx_send_msg(rwnx_hw, req, 0, 0, NULL); ++ } ++} ++ ++int rwnx_send_tdls_peer_traffic_ind_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif) ++{ ++ struct tdls_peer_traffic_ind_req *tdls_peer_traffic_ind_req; ++ ++ if (!rwnx_vif->sta.tdls_sta) ++ return -ENOLINK; ++ ++ /* Build the TDLS_PEER_TRAFFIC_IND_REQ message */ ++ tdls_peer_traffic_ind_req = rwnx_msg_zalloc(TDLS_PEER_TRAFFIC_IND_REQ, TASK_TDLS, DRV_TASK_ID, ++ sizeof(struct tdls_peer_traffic_ind_req)); ++ ++ if (!tdls_peer_traffic_ind_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the TDLS_PEER_TRAFFIC_IND_REQ message */ ++ tdls_peer_traffic_ind_req->vif_index = rwnx_vif->vif_index; ++ tdls_peer_traffic_ind_req->sta_idx = rwnx_vif->sta.tdls_sta->sta_idx; ++ memcpy(&(tdls_peer_traffic_ind_req->peer_mac_addr.array[0]), ++ rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN); ++ tdls_peer_traffic_ind_req->dialog_token = 0; // check dialog token value ++ tdls_peer_traffic_ind_req->last_tid = rwnx_vif->sta.tdls_sta->tdls.last_tid; ++ tdls_peer_traffic_ind_req->last_sn = rwnx_vif->sta.tdls_sta->tdls.last_sn; ++ ++ /* Send the TDLS_PEER_TRAFFIC_IND_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, tdls_peer_traffic_ind_req, 0, 0, NULL); ++} ++ ++int rwnx_send_config_monitor_req(struct rwnx_hw *rwnx_hw, ++ struct cfg80211_chan_def *chandef, ++ struct me_config_monitor_cfm *cfm) ++{ ++ struct me_config_monitor_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the ME_CONFIG_MONITOR_REQ message */ ++ req = rwnx_msg_zalloc(ME_CONFIG_MONITOR_REQ, TASK_ME, DRV_TASK_ID, ++ sizeof(struct me_config_monitor_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if (chandef) { ++ req->chan_set = true; ++ ++ req->chan.band = chandef->chan->band; ++ req->chan.type = bw2chnl[chandef->width]; ++ req->chan.prim20_freq = chandef->chan->center_freq; ++ req->chan.center1_freq = chandef->center_freq1; ++ req->chan.center2_freq = chandef->center_freq2; ++ req->chan.tx_power = chan_to_fw_pwr(chandef->chan->max_power); ++ ++ if (rwnx_hw->phy.limit_bw) ++ limit_chan_bw(&req->chan.type, req->chan.prim20_freq, &req->chan.center1_freq); ++ } else { ++ req->chan_set = false; ++ } ++ ++ req->uf = rwnx_hw->mod_params->uf; ++ req->auto_reply = rwnx_hw->mod_params->auto_reply; ++ ++ /* Send the ME_CONFIG_MONITOR_REQ message to FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, ME_CONFIG_MONITOR_CFM, cfm); ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++int rwnx_send_tdls_chan_switch_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, bool sta_initiator, ++ u8 oper_class, struct cfg80211_chan_def *chandef, ++ struct tdls_chan_switch_cfm *cfm) ++{ ++ struct tdls_chan_switch_req *tdls_chan_switch_req; ++ ++ ++ /* Build the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_chan_switch_req = rwnx_msg_zalloc(TDLS_CHAN_SWITCH_REQ, TASK_TDLS, DRV_TASK_ID, ++ sizeof(struct tdls_chan_switch_req)); ++ ++ if (!tdls_chan_switch_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_chan_switch_req->vif_index = rwnx_vif->vif_index; ++ tdls_chan_switch_req->sta_idx = rwnx_sta->sta_idx; ++ memcpy(&(tdls_chan_switch_req->peer_mac_addr.array[0]), ++ rwnx_sta_addr(rwnx_sta), ETH_ALEN); ++ tdls_chan_switch_req->initiator = sta_initiator; ++ tdls_chan_switch_req->band = chandef->chan->band; ++ tdls_chan_switch_req->type = bw2chnl[chandef->width]; ++ tdls_chan_switch_req->prim20_freq = chandef->chan->center_freq; ++ tdls_chan_switch_req->center1_freq = chandef->center_freq1; ++ tdls_chan_switch_req->center2_freq = chandef->center_freq2; ++ tdls_chan_switch_req->tx_power = chan_to_fw_pwr(chandef->chan->max_power); ++ tdls_chan_switch_req->op_class = oper_class; ++ ++ /* Send the TDLS_CHAN_SWITCH_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, tdls_chan_switch_req, 1, TDLS_CHAN_SWITCH_CFM, cfm); ++} ++ ++int rwnx_send_tdls_cancel_chan_switch_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, ++ struct tdls_cancel_chan_switch_cfm *cfm) ++{ ++ struct tdls_cancel_chan_switch_req *tdls_cancel_chan_switch_req; ++ ++ /* Build the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_cancel_chan_switch_req = rwnx_msg_zalloc(TDLS_CANCEL_CHAN_SWITCH_REQ, TASK_TDLS, DRV_TASK_ID, ++ sizeof(struct tdls_cancel_chan_switch_req)); ++ if (!tdls_cancel_chan_switch_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the TDLS_CHAN_SWITCH_REQ message */ ++ tdls_cancel_chan_switch_req->vif_index = rwnx_vif->vif_index; ++ tdls_cancel_chan_switch_req->sta_idx = rwnx_sta->sta_idx; ++ memcpy(&(tdls_cancel_chan_switch_req->peer_mac_addr.array[0]), ++ rwnx_sta_addr(rwnx_sta), ETH_ALEN); ++ ++ /* Send the TDLS_CHAN_SWITCH_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, tdls_cancel_chan_switch_req, 1, TDLS_CANCEL_CHAN_SWITCH_CFM, cfm); ++} ++ ++#ifdef CONFIG_RWNX_BFMER ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_send_bfmer_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ const struct ieee80211_vht_cap *vht_cap) ++#endif /* CONFIG_RWNX_FULLMAC*/ ++{ ++ struct mm_bfmer_enable_req *bfmer_en_req; ++#ifdef CONFIG_RWNX_FULLMAC ++ __le32 vht_capability; ++ u8 rx_nss = 0; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (!vht_cap) { ++#endif /* CONFIG_RWNX_FULLMAC */ ++ goto end; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ vht_capability = vht_cap->vht_cap_info; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (!(vht_capability & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) { ++ goto end; ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ rx_nss = rwnx_bfmer_get_rx_nss(vht_cap); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ /* Allocate a structure that will contain the beamforming report */ ++ if (rwnx_bfmer_report_add(rwnx_hw, rwnx_sta, RWNX_BFMER_REPORT_SPACE_SIZE)) { ++ goto end; ++ } ++ ++ /* Build the MM_BFMER_ENABLE_REQ message */ ++ bfmer_en_req = rwnx_msg_zalloc(MM_BFMER_ENABLE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_bfmer_enable_req)); ++ ++ /* Check message allocation */ ++ if (!bfmer_en_req) { ++ /* Free memory allocated for the report */ ++ rwnx_bfmer_report_del(rwnx_hw, rwnx_sta); ++ ++ /* Do not use beamforming */ ++ goto end; ++ } ++ ++ /* Provide DMA address to the MAC */ ++ bfmer_en_req->host_bfr_addr = rwnx_sta->bfm_report->dma_addr; ++ bfmer_en_req->host_bfr_size = RWNX_BFMER_REPORT_SPACE_SIZE; ++ bfmer_en_req->sta_idx = rwnx_sta->sta_idx; ++#ifdef CONFIG_RWNX_FULLMAC ++ bfmer_en_req->aid = rwnx_sta->aid; ++ bfmer_en_req->rx_nss = rx_nss; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (vht_capability & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) { ++ bfmer_en_req->vht_mu_bfmee = true; ++ } else { ++ bfmer_en_req->vht_mu_bfmee = false; ++ } ++ ++ /* Send the MM_BFMER_EN_REQ message to LMAC FW */ ++ rwnx_send_msg(rwnx_hw, bfmer_en_req, 0, 0, NULL); ++ ++end: ++ return; ++} ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++int rwnx_send_mu_group_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) ++{ ++ struct mm_mu_group_update_req *req; ++ int group_id, i = 0; ++ u64 map; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_MU_GROUP_UPDATE_REQ message */ ++ req = rwnx_msg_zalloc(MM_MU_GROUP_UPDATE_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_mu_group_update_req) + ++ rwnx_sta->group_info.cnt * sizeof(req->groups[0])); ++ ++ /* Check message allocation */ ++ if (!req) ++ return -ENOMEM; ++ ++ /* Go through the groups the STA belongs to */ ++ group_sta_for_each(rwnx_sta, group_id, map) { ++ int user_pos = rwnx_mu_group_sta_get_pos(rwnx_hw, rwnx_sta, group_id); ++ ++ if (WARN((i >= rwnx_sta->group_info.cnt), ++ "STA%d: Too much group (%d)\n", ++ rwnx_sta->sta_idx, i + 1)) ++ break; ++ ++ req->groups[i].group_id = group_id; ++ req->groups[i].user_pos = user_pos; ++ ++ i++; ++ } ++ ++ req->group_cnt = rwnx_sta->group_info.cnt; ++ req->sta_idx = rwnx_sta->sta_idx; ++ ++ /* Send the MM_MU_GROUP_UPDATE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_MU_GROUP_UPDATE_CFM, NULL); ++} ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* CONFIG_RWNX_BFMER */ ++ ++/********************************************************************** ++ * Debug Messages ++ *********************************************************************/ ++int rwnx_send_dbg_trigger_req(struct rwnx_hw *rwnx_hw, char *msg) ++{ ++ struct mm_dbg_trigger_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_DBG_TRIGGER_REQ message */ ++ req = rwnx_msg_zalloc(MM_DBG_TRIGGER_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_dbg_trigger_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Set parameters for the MM_DBG_TRIGGER_REQ message */ ++ strncpy(req->error, msg, sizeof(req->error)); ++ ++ /* Send the MM_DBG_TRIGGER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 0, -1, NULL); ++} ++ ++int rwnx_send_dbg_mem_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm) ++{ ++ struct dbg_mem_read_req *mem_read_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_READ_REQ message */ ++ mem_read_req = rwnx_msg_zalloc(DBG_MEM_READ_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_read_req)); ++ if (!mem_read_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_READ_REQ message */ ++ mem_read_req->memaddr = mem_addr; ++ ++ /* Send the DBG_MEM_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_read_req, 1, DBG_MEM_READ_CFM, cfm); ++} ++ ++int rwnx_send_dbg_mem_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_data) ++{ ++ struct dbg_mem_write_req *mem_write_req; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_WRITE_REQ message */ ++ mem_write_req = rwnx_msg_zalloc(DBG_MEM_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_write_req)); ++ if (!mem_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_WRITE_REQ message */ ++ mem_write_req->memaddr = mem_addr; ++ mem_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_write_req, 1, DBG_MEM_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_mask_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_mask, u32 mem_data) ++{ ++ struct dbg_mem_mask_write_req *mem_mask_write_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req = rwnx_msg_zalloc(DBG_MEM_MASK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_mask_write_req)); ++ if (!mem_mask_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_mask_write_req->memaddr = mem_addr; ++ mem_mask_write_req->memmask = mem_mask; ++ mem_mask_write_req->memdata = mem_data; ++ ++ /* Send the DBG_MEM_MASK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_mask_write_req, 1, DBG_MEM_MASK_WRITE_CFM, NULL); ++} ++ ++#ifdef CONFIG_RFTEST ++int rwnx_send_rftest_req(struct rwnx_hw *rwnx_hw, u32_l cmd, u32_l argc, u8_l *argv, struct dbg_rftest_cmd_cfm *cfm) ++{ ++ struct dbg_rftest_cmd_req *mem_rftest_cmd_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_RFTEST_CMD_REQ message */ ++ mem_rftest_cmd_req = rwnx_msg_zalloc(DBG_RFTEST_CMD_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_rftest_cmd_req)); ++ if (!mem_rftest_cmd_req) ++ return -ENOMEM; ++ ++ if (argc > 10) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_MASK_WRITE_REQ message */ ++ mem_rftest_cmd_req->cmd = cmd; ++ mem_rftest_cmd_req->argc = argc; ++ if (argc != 0) ++ memcpy(mem_rftest_cmd_req->argv, argv, argc); ++ ++ /* Send the DBG_RFTEST_CMD_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_rftest_cmd_req, 1, DBG_RFTEST_CMD_CFM, cfm); ++} ++#endif ++ ++#ifdef CONFIG_MCU_MESSAGE ++int rwnx_send_dbg_custom_msg_req(struct rwnx_hw *rwnx_hw, ++ u32 cmd, void *buf, u32 len, u32 action, ++ struct dbg_custom_msg_cfm *cfm) ++{ ++ struct dbg_custom_msg_req *cust_msg_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_CUSTOM_MSG_REQ message */ ++ cust_msg_req = ++ rwnx_msg_zalloc(DBG_CUSTOM_MSG_REQ, TASK_DBG, DRV_TASK_ID, ++ offsetof(struct dbg_custom_msg_req, buf) + len); ++ if (!cust_msg_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_CUSTOM_MSG_REQ message */ ++ cust_msg_req->cmd = cmd; ++ cust_msg_req->len = len; ++ cust_msg_req->flags = action; ++ if (buf) { ++ memcpy(cust_msg_req->buf, buf, len); ++ } ++ ++ /* Send the DBG_CUSTOM_MSG_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, cust_msg_req, 1, DBG_CUSTOM_MSG_CFM, cfm); ++} ++#endif ++ ++int rwnx_send_dbg_set_mod_filter_req(struct rwnx_hw *rwnx_hw, u32 filter) ++{ ++ struct dbg_set_mod_filter_req *set_mod_filter_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_SET_MOD_FILTER_REQ message */ ++ set_mod_filter_req = ++ rwnx_msg_zalloc(DBG_SET_MOD_FILTER_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_set_mod_filter_req)); ++ if (!set_mod_filter_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_SET_MOD_FILTER_REQ message */ ++ set_mod_filter_req->mod_filter = filter; ++ ++ /* Send the DBG_SET_MOD_FILTER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_mod_filter_req, 1, DBG_SET_MOD_FILTER_CFM, NULL); ++} ++ ++int rwnx_send_dbg_set_sev_filter_req(struct rwnx_hw *rwnx_hw, u32 filter) ++{ ++ struct dbg_set_sev_filter_req *set_sev_filter_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_SET_SEV_FILTER_REQ message */ ++ set_sev_filter_req = ++ rwnx_msg_zalloc(DBG_SET_SEV_FILTER_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_set_sev_filter_req)); ++ if (!set_sev_filter_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_SET_SEV_FILTER_REQ message */ ++ set_sev_filter_req->sev_filter = filter; ++ ++ /* Send the DBG_SET_SEV_FILTER_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, set_sev_filter_req, 1, DBG_SET_SEV_FILTER_CFM, NULL); ++} ++ ++int rwnx_send_dbg_get_sys_stat_req(struct rwnx_hw *rwnx_hw, ++ struct dbg_get_sys_stat_cfm *cfm) ++{ ++ void *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Allocate the message */ ++ req = rwnx_msg_zalloc(DBG_GET_SYS_STAT_REQ, TASK_DBG, DRV_TASK_ID, 0); ++ if (!req) ++ return -ENOMEM; ++ ++ /* Send the DBG_MEM_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, DBG_GET_SYS_STAT_CFM, cfm); ++} ++ ++int rwnx_send_dbg_mem_block_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, u32 *mem_data) ++{ ++ struct dbg_mem_block_write_req *mem_blk_write_req; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req = rwnx_msg_zalloc(DBG_MEM_BLOCK_WRITE_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_block_write_req)); ++ if (!mem_blk_write_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_BLOCK_WRITE_REQ message */ ++ mem_blk_write_req->memaddr = mem_addr; ++ mem_blk_write_req->memsize = mem_size; ++ memcpy(mem_blk_write_req->memdata, mem_data, mem_size); ++ ++ /* Send the DBG_MEM_BLOCK_WRITE_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_blk_write_req, 1, DBG_MEM_BLOCK_WRITE_CFM, NULL); ++} ++ ++int rwnx_send_dbg_mem_block_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, struct dbg_mem_block_read_cfm *cfm) ++{ ++ struct dbg_mem_block_read_req *mem_blk_read_req; ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_MEM_BLOCK_READ_REQ message */ ++ mem_blk_read_req = rwnx_msg_zalloc(DBG_MEM_BLOCK_READ_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_mem_block_read_req)); ++ if (!mem_blk_read_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_MEM_BLOCK_READ_REQ message */ ++ mem_blk_read_req->memaddr = mem_addr; ++ mem_blk_read_req->memsize = mem_size; ++ ++ /* Send the DBG_MEM_BLOCK_READ_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, mem_blk_read_req, 1, DBG_MEM_BLOCK_READ_CFM, cfm); ++} ++ ++int rwnx_send_dbg_start_app_req(struct rwnx_hw *rwnx_hw, u32 boot_addr, ++ u32 boot_type) ++{ ++ struct dbg_start_app_req *start_app_req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the DBG_START_APP_REQ message */ ++ start_app_req = rwnx_msg_zalloc(DBG_START_APP_REQ, TASK_DBG, DRV_TASK_ID, ++ sizeof(struct dbg_start_app_req)); ++ if (!start_app_req) ++ return -ENOMEM; ++ ++ /* Set parameters for the DBG_START_APP_REQ message */ ++ start_app_req->bootaddr = boot_addr; ++ start_app_req->boottype = boot_type; ++ ++ /* Send the DBG_START_APP_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, start_app_req, 1, DBG_START_APP_CFM, NULL); ++} ++ ++int rwnx_send_cfg_rssi_req(struct rwnx_hw *rwnx_hw, u8 vif_index, int rssi_thold, u32 rssi_hyst) ++{ ++ struct mm_cfg_rssi_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* Build the MM_CFG_RSSI_REQ message */ ++ req = rwnx_msg_zalloc(MM_CFG_RSSI_REQ, TASK_MM, DRV_TASK_ID, ++ sizeof(struct mm_cfg_rssi_req)); ++ if (!req) ++ return -ENOMEM; ++ ++ if (rwnx_hw->vif_table[vif_index] == NULL) ++ return 0; ++ ++ /* Set parameters for the MM_CFG_RSSI_REQ message */ ++ req->vif_index = vif_index; ++ req->rssi_thold = (s8)rssi_thold; ++ req->rssi_hyst = (u8)rssi_hyst; ++ ++ /* Send the MM_CFG_RSSI_REQ message to LMAC FW */ ++ return rwnx_send_msg(rwnx_hw, req, 1, MM_CFG_RSSI_CFM, NULL); ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h +new file mode 100644 +index 000000000000..d44c66c4645a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h +@@ -0,0 +1,196 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_msg_tx.h ++ * ++ * @brief TX function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_MSG_TX_H_ ++#define _RWNX_MSG_TX_H_ ++ ++#include "rwnx_defs.h" ++ ++int rwnx_send_reset(struct rwnx_hw *rwnx_hw); ++int rwnx_send_start(struct rwnx_hw *rwnx_hw); ++int rwnx_send_version_req(struct rwnx_hw *rwnx_hw, struct mm_version_cfm *cfm); ++int rwnx_send_add_if (struct rwnx_hw *rwnx_hw, const unsigned char *mac, ++ enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm); ++int rwnx_send_remove_if (struct rwnx_hw *rwnx_hw, u8 vif_index, bool defer); ++int rwnx_send_set_channel(struct rwnx_hw *rwnx_hw, int phy_idx, ++ struct mm_set_channel_cfm *cfm); ++int rwnx_send_key_add(struct rwnx_hw *rwnx_hw, u8 vif_idx, u8 sta_idx, bool pairwise, ++ u8 *key, u8 key_len, u8 key_idx, u8 cipher_suite, ++ struct mm_key_add_cfm *cfm); ++int rwnx_send_key_del(struct rwnx_hw *rwnx_hw, uint8_t hw_key_idx); ++int rwnx_send_bcn(struct rwnx_hw *rwnx_hw, u8 *buf, u8 vif_idx, u16 bcn_len); ++ ++int rwnx_send_bcn_change(struct rwnx_hw *rwnx_hw, u8 vif_idx, u32 bcn_addr, ++ u16 bcn_len, u16 tim_oft, u16 tim_len, u16 *csa_oft); ++int rwnx_send_tim_update(struct rwnx_hw *rwnx_hw, u8 vif_idx, u16 aid, ++ u8 tx_status); ++int rwnx_send_roc(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct ieee80211_channel *chan, unsigned int duration, struct mm_remain_on_channel_cfm *roc_cfm); ++int rwnx_send_cancel_roc(struct rwnx_hw *rwnx_hw); ++int rwnx_send_set_power(struct rwnx_hw *rwnx_hw, u8 vif_idx, s8 pwr, ++ struct mm_set_power_cfm *cfm); ++int rwnx_send_set_edca(struct rwnx_hw *rwnx_hw, u8 hw_queue, u32 param, ++ bool uapsd, u8 inst_nbr); ++int rwnx_send_tdls_chan_switch_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, bool sta_initiator, ++ u8 oper_class, struct cfg80211_chan_def *chandef, ++ struct tdls_chan_switch_cfm *cfm); ++int rwnx_send_tdls_cancel_chan_switch_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct rwnx_sta *rwnx_sta, ++ struct tdls_cancel_chan_switch_cfm *cfm); ++ ++#ifdef CONFIG_RWNX_P2P_DEBUGFS ++int rwnx_send_p2p_oppps_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 ctw, struct mm_set_p2p_oppps_cfm *cfm); ++int rwnx_send_p2p_noa_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ int count, int interval, int duration, ++ bool dyn_noa, struct mm_set_p2p_noa_cfm *cfm); ++#endif /* CONFIG_RWNX_P2P_DEBUGFS */ ++ ++#ifdef AICWF_ARP_OFFLOAD ++int rwnx_send_arpoffload_en_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u32_l ipaddr, u8_l enable); ++#endif ++int rwnx_send_rf_config_req(struct rwnx_hw *rwnx_hw, u8_l ofst, u8_l sel, u8_l *tbl, u16_l len); ++int rwnx_send_rf_calib_req(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); ++int rwnx_send_get_macaddr_req(struct rwnx_hw *rwnx_hw, struct mm_get_mac_addr_cfm *cfm); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_me_chan_config_req(struct rwnx_hw *rwnx_hw, char *ccode); ++int rwnx_send_me_set_control_port_req(struct rwnx_hw *rwnx_hw, bool opened, ++ u8 sta_idx); ++int rwnx_send_me_sta_add(struct rwnx_hw *rwnx_hw, struct station_parameters *params, ++ const u8 *mac, u8 inst_nbr, struct me_sta_add_cfm *cfm); ++int rwnx_send_me_sta_del(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool tdls_sta); ++int rwnx_send_me_traffic_ind(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool uapsd, u8 tx_status); ++int rwnx_send_me_rc_stats(struct rwnx_hw *rwnx_hw, u8 sta_idx, ++ struct me_rc_stats_cfm *cfm); ++int rwnx_send_me_rc_set_rate(struct rwnx_hw *rwnx_hw, ++ u8 sta_idx, ++ u16 rate_idx); ++int rwnx_send_me_set_ps_mode(struct rwnx_hw *rwnx_hw, u8 ps_mode); ++int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level, u8 disable_filter); ++int rwnx_send_sm_connect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ struct cfg80211_connect_params *sme, ++ struct sm_connect_cfm *cfm); ++int rwnx_send_sm_disconnect_req(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 reason); ++int rwnx_send_sm_external_auth_required_rsp(struct rwnx_hw *rwnx_hw, ++ struct rwnx_vif *rwnx_vif, ++ u16 status); ++int rwnx_send_apm_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_ap_settings *settings, ++ struct apm_start_cfm *cfm, ++ struct rwnx_ipc_elem_var *elem); ++int rwnx_send_apm_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); ++int rwnx_send_scanu_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct cfg80211_scan_request *param); ++int rwnx_send_scanu_cancel_req(struct rwnx_hw *rwnx_hw, ++ struct scan_cancel_cfm *cfm); ++ ++int rwnx_send_apm_start_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct cfg80211_chan_def *chandef, ++ struct apm_start_cac_cfm *cfm); ++int rwnx_send_apm_stop_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); ++int rwnx_send_tdls_peer_traffic_ind_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif); ++int rwnx_send_config_monitor_req(struct rwnx_hw *rwnx_hw, ++ struct cfg80211_chan_def *chandef, ++ struct me_config_monitor_cfm *cfm); ++int rwnx_send_mesh_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ const struct mesh_config *conf, const struct mesh_setup *setup, ++ struct mesh_start_cfm *cfm); ++int rwnx_send_mesh_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ struct mesh_stop_cfm *cfm); ++int rwnx_send_mesh_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u32 mask, const struct mesh_config *p_mconf, struct mesh_update_cfm *cfm); ++int rwnx_send_mesh_peer_info_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, struct mesh_peer_info_cfm *cfm); ++void rwnx_send_mesh_peer_update_ntf(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 sta_idx, u8 mlink_state); ++void rwnx_send_mesh_path_create_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *tgt_addr); ++int rwnx_send_mesh_path_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, const u8 *tgt_addr, ++ const u8 *p_nhop_addr, struct mesh_path_update_cfm *cfm); ++void rwnx_send_mesh_proxy_add_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *ext_addr); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_BFMER ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_send_bfmer_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ const struct ieee80211_vht_cap *vht_cap); ++#endif /* CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++int rwnx_send_mu_group_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++#endif /* CONFIG_RWNX_BFMER */ ++ ++/* Debug messages */ ++int rwnx_send_dbg_trigger_req(struct rwnx_hw *rwnx_hw, char *msg); ++int rwnx_send_dbg_mem_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ struct dbg_mem_read_cfm *cfm); ++int rwnx_send_dbg_mem_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_data); ++int rwnx_send_dbg_mem_mask_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_mask, u32 mem_data); ++int rwnx_send_dbg_set_mod_filter_req(struct rwnx_hw *rwnx_hw, u32 filter); ++#ifdef CONFIG_RFTEST ++int rwnx_send_rftest_req(struct rwnx_hw *rwnx_hw, u32_l cmd, u32_l argc, u8_l *argv, struct dbg_rftest_cmd_cfm *cfm); ++#endif ++#ifdef CONFIG_MCU_MESSAGE ++int rwnx_send_dbg_custom_msg_req(struct rwnx_hw *rwnx_hw, ++ u32 cmd, void *buf, u32 len, u32 action, ++ struct dbg_custom_msg_cfm *cfm); ++#endif ++int rwnx_send_dbg_set_sev_filter_req(struct rwnx_hw *rwnx_hw, u32 filter); ++int rwnx_send_dbg_get_sys_stat_req(struct rwnx_hw *rwnx_hw, ++ struct dbg_get_sys_stat_cfm *cfm); ++int rwnx_send_dbg_mem_block_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, u32 *mem_data); ++int rwnx_send_dbg_mem_block_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, ++ u32 mem_size, struct dbg_mem_block_read_cfm *cfm); ++int rwnx_send_dbg_start_app_req(struct rwnx_hw *rwnx_hw, u32 boot_addr, ++ u32 boot_type); ++int rwnx_send_cfg_rssi_req(struct rwnx_hw *rwnx_hw, u8 vif_index, int rssi_thold, u32 rssi_hyst); ++int rwnx_send_disable_agg_req(struct rwnx_hw *rwnx_hw, u8_l agg_disable, u8_l agg_disable_rx, u8_l sta_idx); ++int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enable_nullcts); ++int rwnx_send_get_sta_info_req(struct rwnx_hw *rwnx_hw, u8_l sta_idx, struct mm_get_sta_info_cfm *cfm); ++int rwnx_send_set_stack_start_req(struct rwnx_hw *rwnx_hw, u8_l on, u8_l efuse_valid, u8_l set_vendor_info, ++ u8_l fwtrace_redir_en, struct mm_set_stack_start_cfm *cfm); ++int rwnx_send_txop_req(struct rwnx_hw *rwnx_hw, uint16_t *txop, u8_l long_nav_en, u8_l cfe_en); ++int rwnx_send_get_temp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm); ++int rwnx_send_set_temp_comp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm); ++int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, int32_t *param, int32_t *param_out); ++int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, int32_t *param_in, int32_t *param_out); ++int rwnx_send_mask_set_ext_flags_req(struct rwnx_hw *rwnx_hw, uint32_t flags_mask, uint32_t flags_val, struct mm_set_vendor_swconfig_cfm *cfm); ++int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_version_cfm *cfm); ++int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_ofst_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_ofst2x_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_ofst2x_v2_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_set_filter(struct rwnx_hw *rwnx_hw, uint32_t filter); ++int rwnx_send_txpwr_lvl_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_v4_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw); ++#ifdef CONFIG_APF ++int rwnx_send_set_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len); ++int rwnx_send_get_apf_prog_req(struct rwnx_hw *rwnx_hw, u8_l *program, u32_l program_len); ++#endif ++ ++#ifdef CONFIG_SDIO_BT ++int rwnx_sdio_bt_send_req(struct rwnx_hw *rwnx_hw,uint32_t len, struct sk_buff *skb); ++#endif ++ ++#endif /* _RWNX_MSG_TX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c +new file mode 100644 +index 000000000000..538f14306afb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c +@@ -0,0 +1,659 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_mu_group.c ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_events.h" ++ ++ ++/** ++ * rwnx_mu_group_sta_init - Initialize group information for a STA ++ * ++ * @sta: Sta to initialize ++ */ ++void rwnx_mu_group_sta_init(struct rwnx_sta *sta, ++ const struct ieee80211_vht_cap *vht_cap) ++{ ++ sta->group_info.map = 0; ++ sta->group_info.cnt = 0; ++ sta->group_info.active.next = LIST_POISON1; ++ sta->group_info.update.next = LIST_POISON1; ++ sta->group_info.last_update = 0; ++ sta->group_info.traffic = 0; ++ sta->group_info.group = 0; ++ ++ if (!vht_cap || ++ !(vht_cap->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { ++ sta->group_info.map = RWNX_SU_GROUP; ++ } ++} ++ ++/** ++ * rwnx_mu_group_sta_del - Remove a sta from all MU group ++ * ++ * @rwnx_hw: main driver data ++ * @sta: STA to remove ++ * ++ * Remove one sta from all the MU groups it belongs to. ++ */ ++void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ int i, j, group_id; ++ bool lock_taken; ++ u64 map; ++ ++ lock_taken = (down_interruptible(&mu->lock) == 0); ++ ++ group_sta_for_each(sta, group_id, map) { ++ struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id); ++ ++ for (i = 0; i < CONFIG_USER_MAX; i++) { ++ if (group->users[i] == sta) { ++ group->users[i] = NULL; ++ group->user_cnt--; ++ /* Don't keep group with only one user */ ++ if (group->user_cnt == 1) { ++ for (j = 0; j < CONFIG_USER_MAX; j++) { ++ if (group->users[j]) { ++ group->users[j]->group_info.cnt--; ++ group->users[j]->group_info.map &= ~BIT_ULL(group->group_id); ++ if (group->users[j]->group_info.group == group_id) ++ group->users[j]->group_info.group = 0; ++ group->user_cnt--; ++ break; ++ } ++ } ++ mu->group_cnt--; ++ trace_mu_group_delete(group->group_id); ++ } else { ++ trace_mu_group_update(group); ++ } ++ break; ++ } ++ } ++ ++ WARN((i == CONFIG_USER_MAX), "sta %d doesn't belongs to group %d", ++ sta->sta_idx, group_id); ++ } ++ ++ sta->group_info.map = 0; ++ sta->group_info.cnt = 0; ++ sta->group_info.traffic = 0; ++ ++ if (sta->group_info.active.next != LIST_POISON1) ++ list_del(&sta->group_info.active); ++ ++ if (sta->group_info.update.next != LIST_POISON1) ++ list_del(&sta->group_info.update); ++ ++ if (lock_taken) ++ up(&mu->lock); ++} ++ ++/** ++ * rwnx_mu_group_sta_get_map - Get the list of group a STA belongs to ++ * ++ * @sta: pointer to the sta ++ * ++ * @return the list of group a STA belongs to as a bitfield ++ */ ++u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta) ++{ ++ if (sta) ++ return sta->group_info.map; ++ return 0; ++} ++ ++/** ++ * rwnx_mu_group_sta_get_pos - Get sta position in a group ++ * ++ * @rwnx_hw: main driver data ++ * @sta: pointer to the sta ++ * @group_id: Group id ++ * ++ * @return the positon of @sta in group @group_id or -1 if the sta ++ * doesn't belongs to the group (or group id is invalid) ++ */ ++int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int group_id) ++{ ++ struct rwnx_mu_group *group; ++ int i; ++ ++ group = rwnx_mu_group_from_id(&rwnx_hw->mu, group_id); ++ if (!group) ++ return -1; ++ ++ for (i = 0; i < CONFIG_USER_MAX; i++) { ++ if (group->users[i] == sta) ++ return i; ++ } ++ ++ WARN(1, "sta %d doesn't belongs to group %d", ++ sta->sta_idx, group_id); ++ return -1; ++} ++ ++/** ++ * rwnx_mu_group_move_head - Move (or add) one element at the top of a list ++ * ++ * @list: list pointer ++ * @elem: element to move (or add) at the top of @list ++ * ++ */ ++static inline ++void rwnx_mu_group_move_head(struct list_head *list, struct list_head *elem) ++{ ++ if (elem->next != LIST_POISON1) { ++ __list_del_entry(elem); ++ } ++ list_add(elem, list); ++} ++ ++/** ++ * rwnx_mu_group_remove_users - Remove all the users of a group ++ * ++ * @mu: pointer on MU info ++ * @group: pointer on group to remove users from ++ * ++ * Loop over all users one one group and remove this group from their ++ * map (and count). ++ * Each users is also added to the update_sta list, so that group info ++ * will be resent to fw for this user. ++ */ ++static inline ++void rwnx_mu_group_remove_users(struct rwnx_mu_info *mu, ++ struct rwnx_mu_group *group) ++{ ++ struct rwnx_sta *sta; ++ int i, group_id = group->group_id; ++ ++ for (i = 0; i < CONFIG_USER_MAX; i++) { ++ if (group->users[i]) { ++ sta = group->users[i]; ++ group->users[i] = NULL; ++ sta->group_info.cnt--; ++ sta->group_info.map &= ~BIT_ULL(group_id); ++ rwnx_mu_group_move_head(&mu->update_sta, ++ &sta->group_info.update); ++ } ++ } ++ ++ if (group->user_cnt) ++ mu->group_cnt--; ++ group->user_cnt = 0; ++ trace_mu_group_delete(group_id); ++} ++ ++/** ++ * rwnx_mu_group_add_users - Add users to a group ++ * ++ * @mu: pointer on MU info ++ * @group: pointer on group to add users in ++ * @nb_user: number of users to ad ++ * @users: table of user to add ++ * ++ * Add @nb_users to @group (which may already have users) ++ * Each new users is added to the first free position. ++ * It is assume that @group has at least @nb_user free position. If it is not ++ * case it only add the number of users needed to complete the group. ++ * Each users (effectively added to @group) is also added to the update_sta ++ * list, so that group info will be resent to fw for this user. ++ */ ++static inline ++void rwnx_mu_group_add_users(struct rwnx_mu_info *mu, ++ struct rwnx_mu_group *group, ++ int nb_user, struct rwnx_sta **users) ++{ ++ int i, j, group_id = group->group_id; ++ ++ if (!group->user_cnt) ++ mu->group_cnt++; ++ ++ j = 0; ++ for (i = 0; i < nb_user ; i++) { ++ for (; j < CONFIG_USER_MAX ; j++) { ++ if (group->users[j] == NULL) { ++ group->users[j] = users[i]; ++ users[i]->group_info.cnt++; ++ users[i]->group_info.map |= BIT_ULL(group_id); ++ ++ rwnx_mu_group_move_head(&(mu->update_sta), ++ &(users[i]->group_info.update)); ++ group->user_cnt++; ++ j++; ++ break; ++ } ++ ++ WARN(j == (CONFIG_USER_MAX - 1), ++ "Too many user for group %d (nb_user=%d)", ++ group_id, group->user_cnt + nb_user - i); ++ } ++ } ++ ++ trace_mu_group_update(group); ++} ++ ++ ++/** ++ * rwnx_mu_group_create_one - create on group with a specific group of user ++ * ++ * @mu: pointer on MU info ++ * @nb_user: number of user to include in the group (<= CONFIG_USER_MAX) ++ * @users: table of users ++ * ++ * Try to create a new group with a specific group of users. ++ * 1- First it checks if a group containing all this users already exists. ++ * ++ * 2- Then it checks if it is possible to complete a group which already ++ * contains at least one user. ++ * ++ * 3- Finally it create a new group. To do so, it take take the last group of ++ * the active_groups list, remove all its current users and add the new ones ++ * ++ * In all cases, the group selected is moved at the top of the active_groups ++ * list ++ * ++ * @return 1 if a new group has been created and 0 otherwise ++ */ ++static ++int rwnx_mu_group_create_one(struct rwnx_mu_info *mu, int nb_user, ++ struct rwnx_sta **users, int *nb_group_left) ++{ ++ int i, group_id; ++ struct rwnx_mu_group *group; ++ u64 group_match; ++ u64 group_avail; ++ ++ group_match = users[0]->group_info.map; ++ group_avail = users[0]->group_info.map; ++ for (i = 1; i < nb_user ; i++) { ++ group_match &= users[i]->group_info.map; ++ group_avail |= users[i]->group_info.map; ++ ++ } ++ ++ if (group_match) { ++ /* a group (or more) with all the users already exist */ ++ group_id = RWNX_GET_FIRST_GROUP_ID(group_match); ++ group = rwnx_mu_group_from_id(mu, group_id); ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++ return 0; ++ } ++ ++#if CONFIG_USER_MAX > 2 ++ if (group_avail) { ++ /* check if we can complete a group */ ++ struct rwnx_sta *users2[CONFIG_USER_MAX]; ++ int nb_user2; ++ ++ group_for_each(group_id, group_avail) { ++ group = rwnx_mu_group_from_id(mu, group_id); ++ if (group->user_cnt == CONFIG_USER_MAX) ++ continue; ++ ++ nb_user2 = 0; ++ for (i = 0; i < nb_user ; i++) { ++ if (!(users[i]->group_info.map & BIT_ULL(group_id))) { ++ users2[nb_user2] = users[i]; ++ nb_user2++; ++ } ++ } ++ ++ if ((group->user_cnt + nb_user2) <= CONFIG_USER_MAX) { ++ rwnx_mu_group_add_users(mu, group, nb_user2, users2); ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++ return 0; ++ } ++ } ++ } ++#endif /* CONFIG_USER_MAX > 2*/ ++ ++ /* create a new group */ ++ group = list_last_entry(&mu->active_groups, struct rwnx_mu_group, list); ++ rwnx_mu_group_remove_users(mu, group); ++ rwnx_mu_group_add_users(mu, group, nb_user, users); ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++ (*nb_group_left)--; ++ ++ return 1; ++} ++ ++/** ++ * rwnx_mu_group_create - Create new groups containing one specific sta ++ * ++ * @mu: pointer on MU info ++ * @sta: sta to add in each group ++ * @nb_group_left: maximum number to new group allowed. (updated on exit) ++ * ++ * This will try to create "all the possible" group with a specific sta being ++ * a member of all these group. ++ * The function simply loops over the @active_sta list (starting from @sta). ++ * When it has (CONFIG_USER_MAX - 1) users it try to create a new group with ++ * these users (plus @sta). ++ * Loops end when there is no more users, or no more new group is allowed ++ * ++ */ ++static ++void rwnx_mu_group_create(struct rwnx_mu_info *mu, struct rwnx_sta *sta, ++ int *nb_group_left) ++{ ++ struct rwnx_sta *user_sta = sta; ++ struct rwnx_sta *users[CONFIG_USER_MAX]; ++ int nb_user = 1; ++ ++ users[0] = sta; ++ while (*nb_group_left) { ++ ++ list_for_each_entry_continue(user_sta, &mu->active_sta, group_info.active) { ++ users[nb_user] = user_sta; ++ if (++nb_user == CONFIG_USER_MAX) { ++ break; ++ } ++ } ++ ++ if (nb_user > 1) { ++ if (rwnx_mu_group_create_one(mu, nb_user, users, nb_group_left)) ++ (*nb_group_left)--; ++ ++ if (nb_user < CONFIG_USER_MAX) ++ break; ++ else ++ nb_user = 1; ++ } else ++ break; ++ } ++} ++ ++/** ++ * rwnx_mu_group_work - process function of the "group_work" ++ * ++ * The work is scheduled when several sta (MU beamformee capable) are active. ++ * When called, the @active_sta contains the list of the active sta (starting ++ * from the most recent one), and @active_groups is the list of all possible ++ * groups ordered so that the first one is the most recently used. ++ * ++ * This function will create new groups, starting from group containing the ++ * most "active" sta. ++ * For example if the list of sta is : ++ * sta8 -> sta3 -> sta4 -> sta7 -> sta1 ++ * and the number of user per group is 3, it will create grooups : ++ * - sta8 / sta3 / sta4 ++ * - sta8 / sta7 / sta1 ++ * - sta3 / sta4 / sta7 ++ * - sta3 / sta1 ++ * - sta4 / sta7 / sta1 ++ * - sta7 / sta1 ++ * ++ * To create new group, the least used group are first selected. ++ * It is only allowed to create NX_MU_GROUP_MAX per iteration. ++ * ++ * Once groups have been updated, mu group information is update to the fw. ++ * To do so it use the @update_sta list to know which sta has been affected. ++ * As it is necessary to wait for fw confirmation before using this new group ++ * MU is temporarily disabled during group update ++ * ++ * Work is then rescheduled. ++ * ++ * At the end of the function, both @active_sta and @update_sta list are empty. ++ * ++ * Note: ++ * - This is still a WIP, and will require more tuning ++ * - not all combinations are created, to avoid to much processing. ++ * - reschedule delay should be adaptative ++ */ ++void rwnx_mu_group_work(struct work_struct *ws) ++{ ++ struct delayed_work *dw = container_of(ws, struct delayed_work, work); ++ struct rwnx_mu_info *mu = container_of(dw, struct rwnx_mu_info, group_work); ++ struct rwnx_hw *rwnx_hw = container_of(mu, struct rwnx_hw, mu); ++ struct rwnx_sta *sta, *next; ++ int nb_group_left = NX_MU_GROUP_MAX; ++ ++ if (WARN(!rwnx_hw->mod_params->mutx, ++ "In group formation work, but mutx disabled")) ++ return; ++ ++ if (down_interruptible(&mu->lock) != 0) ++ return; ++ ++ mu->update_count++; ++ if (!mu->update_count) ++ mu->update_count++; ++ ++ list_for_each_entry_safe(sta, next, &mu->active_sta, group_info.active) { ++ if (nb_group_left) ++ rwnx_mu_group_create(mu, sta, &nb_group_left); ++ ++ sta->group_info.last_update = mu->update_count; ++ list_del(&sta->group_info.active); ++ } ++ ++ if (!list_empty(&mu->update_sta)) { ++ list_for_each_entry_safe(sta, next, &mu->update_sta, group_info.update) { ++ rwnx_send_mu_group_update_req(rwnx_hw, sta); ++ list_del(&sta->group_info.update); ++ } ++ } ++ ++ mu->next_group_select = jiffies; ++ rwnx_mu_group_sta_select(rwnx_hw); ++ up(&mu->lock); ++ ++ return; ++} ++ ++/** ++ * rwnx_mu_group_init - Initialize MU groups ++ * ++ * @rwnx_hw: main driver data ++ * ++ * Initialize all MU group ++ */ ++void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ int i; ++ ++ INIT_LIST_HEAD(&mu->active_groups); ++ INIT_LIST_HEAD(&mu->active_sta); ++ INIT_LIST_HEAD(&mu->update_sta); ++ ++ for (i = 0; i < NX_MU_GROUP_MAX; i++) { ++ int j; ++ mu->groups[i].user_cnt = 0; ++ mu->groups[i].group_id = i + 1; ++ for (j = 0; j < CONFIG_USER_MAX; j++) { ++ mu->groups[i].users[j] = NULL; ++ } ++ list_add(&mu->groups[i].list, &mu->active_groups); ++ } ++ ++ mu->update_count = 1; ++ mu->group_cnt = 0; ++ mu->next_group_select = jiffies; ++ INIT_DELAYED_WORK(&mu->group_work, rwnx_mu_group_work); ++ sema_init(&mu->lock, 1); ++} ++ ++/** ++ * rwnx_mu_set_active_sta - mark a STA as active ++ * ++ * @rwnx_hw: main driver data ++ * @sta: pointer to the sta ++ * @traffic: Number of buffers to add in the sta's traffic counter ++ * ++ * If @sta is MU beamformee capable (and MU-MIMO tx is enabled) move the ++ * sta at the top of the @active_sta list. ++ * It also schedule the group_work if not already scheduled and the list ++ * contains more than one sta. ++ * ++ * If a STA was already in the list during the last group update ++ * (i.e. sta->group_info.last_update == mu->update_count) it is not added ++ * back to the list until a sta that wasn't active during the last update is ++ * added. This is to avoid scheduling group update with a list of sta that ++ * were all already in the list during previous update. ++ * ++ * It is called with mu->lock taken. ++ */ ++void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int traffic) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ ++ if (!sta || (sta->group_info.map & RWNX_SU_GROUP)) ++ return; ++ ++ sta->group_info.traffic += traffic; ++ ++ if ((sta->group_info.last_update != mu->update_count) || ++ !list_empty(&mu->active_sta)) { ++ ++ rwnx_mu_group_move_head(&mu->active_sta, &sta->group_info.active); ++ ++ if (!delayed_work_pending(&mu->group_work) && ++ !list_is_singular(&mu->active_sta)) { ++ schedule_delayed_work(&mu->group_work, ++ msecs_to_jiffies(RWNX_MU_GROUP_INTERVAL)); ++ } ++ } ++} ++ ++/** ++ * rwnx_mu_set_active_group - mark a MU group as active ++ * ++ * @rwnx_hw: main driver data ++ * @group_id: Group id ++ * ++ * move a group at the top of the @active_groups list ++ */ ++void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id); ++ ++ rwnx_mu_group_move_head(&mu->active_groups, &group->list); ++} ++ ++ ++/** ++ * rwnx_mu_group_sta_select - Select the best group for MU stas ++ * ++ * @rwnx_hw: main driver data ++ * ++ * For each MU capable client of AP interfaces this function tries to select ++ * the best group to use. ++ * ++ * In first pass, gather information from all stations to form statistics ++ * for each group for the previous @RWNX_MU_GROUP_SELECT_INTERVAL interval: ++ * - number of buffers transmitted ++ * - number of user ++ * ++ * Then groups with more than 2 active users, are assigned after being ordered ++ * by traffic : ++ * - group with highest traffic is selected: set this group for all its users ++ * - update nb_users for all others group (as one sta may be in several groups) ++ * - select the next group that have still mor than 2 users and assign it. ++ * - continue until all group are processed ++ * ++ */ ++void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_mu_info *mu = &rwnx_hw->mu; ++ int nb_users[NX_MU_GROUP_MAX + 1]; ++ int traffic[NX_MU_GROUP_MAX + 1]; ++ int order[NX_MU_GROUP_MAX + 1]; ++ struct rwnx_sta *sta; ++ struct rwnx_vif *vif; ++ struct list_head *head; ++ u64 map; ++ int i, j, update, group_id, tmp, cnt = 0; ++ ++ if (!mu->group_cnt || time_before(jiffies, mu->next_group_select)) ++ return; ++ ++ list_for_each_entry(vif, &rwnx_hw->vifs, list) { ++ ++ if (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP) ++ continue; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ head = &vif->ap.sta_list; ++#else ++ head = &vif->stations; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ memset(nb_users, 0, sizeof(nb_users)); ++ memset(traffic, 0, sizeof(traffic)); ++ list_for_each_entry(sta, head, list) { ++ int sta_traffic = sta->group_info.traffic; ++ ++ /* reset statistics for next selection */ ++ sta->group_info.traffic = 0; ++ if (sta->group_info.group) ++ trace_mu_group_selection(sta, 0); ++ sta->group_info.group = 0; ++ ++ if (sta->group_info.cnt == 0 || ++ sta_traffic < RWNX_MU_GROUP_MIN_TRAFFIC) ++ continue; ++ ++ group_sta_for_each(sta, group_id, map) { ++ nb_users[group_id]++; ++ traffic[group_id] += sta_traffic; ++ ++ /* list group with 2 users or more */ ++ if (nb_users[group_id] == 2) ++ order[cnt++] = group_id; ++ } ++ } ++ ++ /* reorder list of group with more that 2 users */ ++ update = 1; ++ while (update) { ++ update = 0; ++ for (i = 0; i < cnt - 1; i++) { ++ if (traffic[order[i]] < traffic[order[i + 1]]) { ++ tmp = order[i]; ++ order[i] = order[i + 1]; ++ order[i + 1] = tmp; ++ update = 1; ++ } ++ } ++ } ++ ++ /* now assign group in traffic order */ ++ for (i = 0; i < cnt; i++) { ++ struct rwnx_mu_group *group; ++ group_id = order[i]; ++ ++ if (nb_users[group_id] < 2) ++ continue; ++ ++ group = rwnx_mu_group_from_id(mu, group_id); ++ for (j = 0; j < CONFIG_USER_MAX; j++) { ++ if (group->users[j]) { ++ trace_mu_group_selection(group->users[j], group_id); ++ group->users[j]->group_info.group = group_id; ++ ++ group_sta_for_each(group->users[j], tmp, map) { ++ if (group_id != tmp) ++ nb_users[tmp]--; ++ } ++ } ++ } ++ } ++ } ++ ++ mu->next_group_select = jiffies + ++ msecs_to_jiffies(RWNX_MU_GROUP_SELECT_INTERVAL); ++ mu->next_group_select |= 1; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h +new file mode 100644 +index 000000000000..c24bb0396e9f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h +@@ -0,0 +1,181 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_mu_group.h ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_MU_GROUP_H_ ++#define _RWNX_MU_GROUP_H_ ++ ++#include ++#include ++ ++struct rwnx_hw; ++struct rwnx_sta; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ ++/** ++ * struct rwnx_sta_group_info - Group Information for a STA ++ * ++ * @active: node for @mu->active_sta list ++ * @update: node for @mu->update_sta list ++ * @cnt: Number of groups the STA belongs to ++ * @map: Bitfield of groups the sta belongs to ++ * @traffic: Number of buffers sent since previous group selection ++ * @group: Id of the group selected by previous group selection ++ * (cf @rwnx_mu_group_sta_select) ++ */ ++struct rwnx_sta_group_info { ++ struct list_head active; ++ struct list_head update; ++ u16 last_update; ++ int cnt; ++ u64 map; ++ int traffic; ++ u8 group; ++}; ++ ++/** ++ * struct mu_group_info - Information about the users of a group ++ * ++ * @list: node for mu->active_groups ++ * @group_id: Group identifier ++ * @user_cnt: Number of the users in the group ++ * @users: Pointer to the sta, ordered by user position ++ */ ++struct rwnx_mu_group { ++ struct list_head list; ++ int group_id; ++ int user_cnt; ++ struct rwnx_sta *users[CONFIG_USER_MAX]; ++}; ++ ++/** ++ * struct rwnx_mu_info - Information about all MU group ++ * ++ * @active_groups: List of all possible groups. Ordered from the most recently ++ * used one to the least one (and possibly never used) ++ * @active_sta: List of MU beamformee sta that have been active (since previous ++ * group update). Ordered from the most recently active. ++ * @update_sta: List of sta whose group information has changed and need to be ++ * updated at fw level ++ * @groups: Table of all groups ++ * @group_work: Work item used to schedule group update ++ * @update_count: Counter used to identify the last group formation update. ++ * (cf rwnx_sta_group_info.last_update) ++ * @lock: Lock taken during group update. If tx happens lock is taken, then tx ++ * will not used MU. ++ * @next_group_assign: Next time the group selection should be run ++ * (ref @rwnx_mu_group_sta_select) ++ * @group_cnt: Number of group created ++ */ ++struct rwnx_mu_info { ++ struct list_head active_groups; ++ struct list_head active_sta; ++ struct list_head update_sta; ++ struct rwnx_mu_group groups[NX_MU_GROUP_MAX]; ++ struct delayed_work group_work; ++ u16 update_count; ++ struct semaphore lock; ++ unsigned long next_group_select; ++ u8 group_cnt; ++}; ++ ++#define RWNX_SU_GROUP BIT_ULL(0) ++#define RWNX_MU_GROUP_MASK 0x7ffffffffffffffeULL ++#define RWNX_MU_GROUP_INTERVAL 200 /* in ms */ ++#define RWNX_MU_GROUP_SELECT_INTERVAL 100 /* in ms */ ++// minimum traffic in a RWNX_MU_GROUP_SELECT_INTERVAL to consider the sta ++#define RWNX_MU_GROUP_MIN_TRAFFIC 50 /* in number of packet */ ++ ++ ++#define RWNX_GET_FIRST_GROUP_ID(map) (fls64(map) - 1) ++ ++#define group_sta_for_each(sta, id, map) \ ++ do { \ ++ map = sta->group_info.map & RWNX_MU_GROUP_MASK; \ ++ for (id = (fls64(map) - 1) ; id > 0 ; \ ++ map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1)) \ ++ } while (0) ++ ++#define group_for_each(id, map) \ ++ for (id = (fls64(map) - 1) ; id > 0 ; \ ++ map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1)) ++ ++#define RWNX_MUMIMO_INFO_POS_ID(info) (((info) >> 6) & 0x3) ++#define RWNX_MUMIMO_INFO_GROUP_ID(info) ((info) & 0x3f) ++ ++static inline ++struct rwnx_mu_group *rwnx_mu_group_from_id(struct rwnx_mu_info *mu, int id) ++{ ++ if (id > NX_MU_GROUP_MAX) ++ return NULL; ++ ++ return &mu->groups[id - 1]; ++} ++ ++ ++void rwnx_mu_group_sta_init(struct rwnx_sta *sta, ++ const struct ieee80211_vht_cap *vht_cap); ++void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); ++u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta); ++int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int group_id); ++ ++void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw); ++ ++void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int traffic); ++void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id); ++void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw); ++ ++ ++#else /* ! CONFIG_RWNX_MUMIMO_TX */ ++ ++static inline ++void rwnx_mu_group_sta_init(struct rwnx_sta *sta, ++ const struct ieee80211_vht_cap *vht_cap) ++{} ++ ++static inline ++void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) ++{} ++ ++static inline ++u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta) ++{ ++ return 0; ++} ++ ++static inline ++int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int group_id) ++{ ++ return 0; ++} ++ ++static inline ++void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw) ++{} ++ ++static inline ++void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ int traffic) ++{} ++ ++static inline ++void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id) ++{} ++ ++static inline ++void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw) ++{} ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++#endif /* _RWNX_MU_GROUP_H_ */ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c +new file mode 100644 +index 000000000000..40dac946536d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c +@@ -0,0 +1,94 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_pci.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_dini.h" ++#include "rwnx_v7.h" ++ ++#define PCI_VENDOR_ID_DINIGROUP 0x17DF ++#define PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE 0x1907 ++ ++#define PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7 0x7011 ++ ++static const struct pci_device_id rwnx_pci_ids[] = { ++ {PCI_DEVICE(PCI_VENDOR_ID_DINIGROUP, PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7)}, ++ {0,} ++}; ++ ++ ++/* Uncomment this for depmod to create module alias */ ++/* We don't want this on development platform */ ++//MODULE_DEVICE_TABLE(pci, rwnx_pci_ids); ++ ++static int rwnx_pci_probe(struct pci_dev *pci_dev, ++ const struct pci_device_id *pci_id) ++{ ++ struct rwnx_plat *rwnx_plat = NULL; ++ void *drvdata; ++ int ret = -ENODEV; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (pci_id->vendor == PCI_VENDOR_ID_DINIGROUP) { ++ ret = rwnx_dini_platform_init(pci_dev, &rwnx_plat); ++ } else if (pci_id->vendor == PCI_VENDOR_ID_XILINX) { ++ ret = rwnx_v7_platform_init(pci_dev, &rwnx_plat); ++ } ++ ++ if (ret) ++ return ret; ++ ++ rwnx_plat->pci_dev = pci_dev; ++ ++ ret = rwnx_platform_init(rwnx_plat, &drvdata); ++ pci_set_drvdata(pci_dev, drvdata); ++ ++ if (ret) ++ rwnx_plat->deinit(rwnx_plat); ++ ++ return ret; ++} ++ ++static void rwnx_pci_remove(struct pci_dev *pci_dev) ++{ ++ struct rwnx_hw *rwnx_hw; ++ struct rwnx_plat *rwnx_plat; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_hw = pci_get_drvdata(pci_dev); ++ rwnx_plat = rwnx_hw->plat; ++ ++ rwnx_platform_deinit(rwnx_hw); ++ rwnx_plat->deinit(rwnx_plat); ++ ++ pci_set_drvdata(pci_dev, NULL); ++} ++ ++static struct pci_driver rwnx_pci_drv = { ++ .name = KBUILD_MODNAME, ++ .id_table = rwnx_pci_ids, ++ .probe = rwnx_pci_probe, ++ .remove = rwnx_pci_remove ++}; ++ ++int rwnx_pci_register_drv(void) ++{ ++ return pci_register_driver(&rwnx_pci_drv); ++} ++ ++void rwnx_pci_unregister_drv(void) ++{ ++ pci_unregister_driver(&rwnx_pci_drv); ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h +new file mode 100644 +index 000000000000..d81578cbef48 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h +@@ -0,0 +1,17 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_pci.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_PCI_H_ ++#define _RWNX_PCI_H_ ++ ++int rwnx_pci_register_drv(void); ++void rwnx_pci_unregister_drv(void); ++ ++#endif /* _RWNX_PCI_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c +new file mode 100644 +index 000000000000..33bc63bd4057 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c +@@ -0,0 +1,3417 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_platform.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "rwnx_platform.h" ++#include "reg_access.h" ++#include "hal_desc.h" ++#include "rwnx_main.h" ++#include "rwnx_pci.h" ++#ifndef CONFIG_RWNX_FHOST ++#include "ipc_host.h" ++#endif /* !CONFIG_RWNX_FHOST */ ++#include "rwnx_msg_tx.h" ++ ++#ifdef AICWF_SDIO_SUPPORT ++#include "aicwf_sdio.h" ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++#include "aicwf_usb.h" ++#endif ++#include "md5.h" ++#include "aicwf_compat_8800dc.h" ++#include "aicwf_compat_8800d80.h" ++ ++#ifdef CONFIG_USE_FW_REQUEST ++#include ++#endif ++ ++#define FW_PATH_MAX_LEN 200 ++extern char aic_fw_path[FW_PATH_MAX_LEN]; ++ ++//Parser state ++#define INIT 0 ++#define CMD 1 ++#define PRINT 2 ++#define GET_VALUE 3 ++ ++ ++struct rwnx_plat *g_rwnx_plat; ++ ++typedef struct ++{ ++ txpwr_lvl_conf_t txpwr_lvl; ++ txpwr_lvl_conf_v2_t txpwr_lvl_v2; ++ txpwr_lvl_conf_v3_t txpwr_lvl_v3; ++ txpwr_lvl_conf_v4_t txpwr_lvl_v4; ++ txpwr_lvl_adj_conf_t txpwr_lvl_adj; ++ txpwr_loss_conf_t txpwr_loss; ++ txpwr_ofst_conf_t txpwr_ofst; ++ txpwr_ofst2x_conf_t txpwr_ofst2x; ++ txpwr_ofst2x_conf_v2_t txpwr_ofst2x_v2; ++ xtal_cap_conf_t xtal_cap; ++} userconfig_info_t; ++ ++userconfig_info_t userconfig_info = { ++ .txpwr_lvl = { ++ .enable = 1, ++ .dsss = 9, ++ .ofdmlowrate_2g4 = 8, ++ .ofdm64qam_2g4 = 8, ++ .ofdm256qam_2g4 = 8, ++ .ofdm1024qam_2g4 = 8, ++ .ofdmlowrate_5g = 11, ++ .ofdm64qam_5g = 10, ++ .ofdm256qam_5g = 9, ++ .ofdm1024qam_5g = 9 ++ }, ++ .txpwr_lvl_v2 = { ++ .enable = 1, ++ .pwrlvl_11b_11ag_2g4 = ++ //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, ++ .pwrlvl_11ax_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, ++ }, ++ .txpwr_lvl_v3 = { ++ .enable = 1, ++ .pwrlvl_11b_11ag_2g4 = ++ //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, ++ .pwrlvl_11ax_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, ++ .pwrlvl_11a_5g = ++ //NA, NA, NA, NA, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 0x80, 0x80, 0x80, 0x80, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15}, ++ .pwrlvl_11ax_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15, 14, 14}, ++ }, ++ .txpwr_lvl_v4 = { ++ .enable = 1, ++ .pwrlvl_11b_11ag_2g4 = ++ //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, ++ .pwrlvl_11ax_2g4 = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, ++ .pwrlvl_11a_5g = ++ //6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M ++ { 20, 20, 20, 20, 18, 18, 16, 16}, ++ .pwrlvl_11n_11ac_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15}, ++ .pwrlvl_11ax_5g = ++ //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 ++ { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15, 14, 14}, ++ }, ++ .txpwr_loss = { ++ .loss_enable_2g4 = 0, ++ .loss_value_2g4 = 0, ++ .loss_enable_5g = 0, ++ .loss_value_5g = 0, ++ }, ++ .txpwr_ofst = { ++ .enable = 1, ++ .chan_1_4 = 0, ++ .chan_5_9 = 0, ++ .chan_10_13 = 0, ++ .chan_36_64 = 0, ++ .chan_100_120 = 0, ++ .chan_122_140 = 0, ++ .chan_142_165 = 0, ++ }, ++ .txpwr_ofst2x = { ++ .enable = 0, ++ .pwrofst2x_tbl_2g4 = ++ { // ch1-4, ch5-9, ch10-13 ++ { 0, 0, 0 }, // 11b ++ { 0, 0, 0 }, // ofdm_highrate ++ { 0, 0, 0 }, // ofdm_lowrate ++ }, ++ .pwrofst2x_tbl_5g = ++ { // ch42, ch58, ch106,ch122,ch138,ch155 ++ { 0, 0, 0, 0, 0, 0 }, // ofdm_lowrate ++ { 0, 0, 0, 0, 0, 0 }, // ofdm_highrate ++ { 0, 0, 0, 0, 0, 0 }, // ofdm_midrate ++ }, ++ }, ++ .txpwr_ofst2x_v2 = { ++ .enable = 0, ++ .pwrofst_flags = 0, ++ .pwrofst2x_tbl_2g4_ant0 = ++ { // 11b, ofdm_highrate, ofdm_lowrate ++ { 0, 0, 0 }, // ch1-4 ++ { 0, 0, 0 }, // ch5-9 ++ { 0, 0, 0 }, // ch10-13 ++ }, ++ .pwrofst2x_tbl_2g4_ant1 = ++ { // 11b, ofdm_highrate, ofdm_lowrate ++ { 0, 0, 0 }, // ch1-4 ++ { 0, 0, 0 }, // ch5-9 ++ { 0, 0, 0 }, // ch10-13 ++ }, ++ .pwrofst2x_tbl_5g_ant0 = ++ { // ofdm_highrate, ofdm_lowrate, ofdm_midrate ++ { 0, 0, 0 }, // ch42 ++ { 0, 0, 0 }, // ch58 ++ { 0, 0, 0 }, // ch106 ++ { 0, 0, 0 }, // ch122 ++ { 0, 0, 0 }, // ch138 ++ { 0, 0, 0 }, // ch155 ++ }, ++ .pwrofst2x_tbl_5g_ant1 = ++ { // ofdm_highrate, ofdm_lowrate, ofdm_midrate ++ { 0, 0, 0 }, // ch42 ++ { 0, 0, 0 }, // ch58 ++ { 0, 0, 0 }, // ch106 ++ { 0, 0, 0 }, // ch122 ++ { 0, 0, 0 }, // ch138 ++ { 0, 0, 0 }, // ch155 ++ }, ++ .pwrofst2x_tbl_6g_ant0 = { 0, }, // ofdm_highrate: 6e_ch7 ~ 6e_ch229 ++ .pwrofst2x_tbl_6g_ant1 = { 0, }, // ofdm_highrate: 6e_ch7 ~ 6e_ch229 ++ }, ++ .xtal_cap = { ++ .enable = 0, ++ .xtal_cap = 24, ++ .xtal_cap_fine = 31, ++ }, ++}; ++ ++typedef struct { ++ char ccode[3]; ++ Regions_code region; ++} reg_table; ++ ++/* If the region conflicts with the kernel, the actual authentication standard prevails */ ++reg_table reg_tables[] = { ++ {.ccode = "CN", .region = REGIONS_SRRC}, ++ {.ccode = "US", .region = REGIONS_FCC}, ++ {.ccode = "DE", .region = REGIONS_ETSI}, ++ {.ccode = "00", .region = REGIONS_DEFAULT}, ++ {.ccode = "WW", .region = REGIONS_DEFAULT}, ++ {.ccode = "XX", .region = REGIONS_DEFAULT}, ++ {.ccode = "JP", .region = REGIONS_JP}, ++ {.ccode = "AD", .region = REGIONS_ETSI}, ++ {.ccode = "AE", .region = REGIONS_ETSI}, ++ {.ccode = "AF", .region = REGIONS_ETSI}, ++ {.ccode = "AI", .region = REGIONS_ETSI}, ++ {.ccode = "AL", .region = REGIONS_ETSI}, ++ {.ccode = "AM", .region = REGIONS_ETSI}, ++ {.ccode = "AN", .region = REGIONS_ETSI}, ++ {.ccode = "AR", .region = REGIONS_FCC}, ++ {.ccode = "AS", .region = REGIONS_FCC}, ++ {.ccode = "AT", .region = REGIONS_ETSI}, ++ {.ccode = "AU", .region = REGIONS_ETSI}, ++ {.ccode = "AW", .region = REGIONS_ETSI}, ++ {.ccode = "AZ", .region = REGIONS_ETSI}, ++ {.ccode = "BA", .region = REGIONS_ETSI}, ++ {.ccode = "BB", .region = REGIONS_FCC}, ++ {.ccode = "BD", .region = REGIONS_JP}, ++ {.ccode = "BE", .region = REGIONS_ETSI}, ++ {.ccode = "BF", .region = REGIONS_FCC}, ++ {.ccode = "BG", .region = REGIONS_ETSI}, ++ {.ccode = "BH", .region = REGIONS_ETSI}, ++ {.ccode = "BL", .region = REGIONS_ETSI}, ++ {.ccode = "BM", .region = REGIONS_FCC}, ++ {.ccode = "BN", .region = REGIONS_JP}, ++ {.ccode = "BO", .region = REGIONS_JP}, ++ {.ccode = "BR", .region = REGIONS_FCC}, ++ {.ccode = "BS", .region = REGIONS_FCC}, ++ {.ccode = "BT", .region = REGIONS_ETSI}, ++ {.ccode = "BW", .region = REGIONS_ETSI}, ++ {.ccode = "BY", .region = REGIONS_ETSI}, ++ {.ccode = "BZ", .region = REGIONS_JP}, ++ {.ccode = "CA", .region = REGIONS_FCC}, ++ {.ccode = "CF", .region = REGIONS_FCC}, ++ {.ccode = "CH", .region = REGIONS_ETSI}, ++ {.ccode = "CI", .region = REGIONS_FCC}, ++ {.ccode = "CL", .region = REGIONS_ETSI}, ++ {.ccode = "CO", .region = REGIONS_FCC}, ++ {.ccode = "CR", .region = REGIONS_FCC}, ++ {.ccode = "CX", .region = REGIONS_FCC}, ++ {.ccode = "CY", .region = REGIONS_ETSI}, ++ {.ccode = "CZ", .region = REGIONS_ETSI}, ++ {.ccode = "DK", .region = REGIONS_ETSI}, ++ {.ccode = "DM", .region = REGIONS_FCC}, ++ {.ccode = "DO", .region = REGIONS_FCC}, ++ {.ccode = "DZ", .region = REGIONS_JP}, ++ {.ccode = "EC", .region = REGIONS_FCC}, ++ {.ccode = "EE", .region = REGIONS_ETSI}, ++ {.ccode = "EG", .region = REGIONS_ETSI}, ++ {.ccode = "ES", .region = REGIONS_ETSI}, ++ {.ccode = "ET", .region = REGIONS_ETSI}, ++ {.ccode = "FI", .region = REGIONS_ETSI}, ++ {.ccode = "FM", .region = REGIONS_FCC}, ++ {.ccode = "FR", .region = REGIONS_ETSI}, ++ {.ccode = "GB", .region = REGIONS_ETSI}, ++ {.ccode = "GD", .region = REGIONS_FCC}, ++ {.ccode = "GE", .region = REGIONS_ETSI}, ++ {.ccode = "GF", .region = REGIONS_ETSI}, ++ {.ccode = "GH", .region = REGIONS_FCC}, ++ {.ccode = "GI", .region = REGIONS_ETSI}, ++ {.ccode = "GL", .region = REGIONS_ETSI}, ++ {.ccode = "GP", .region = REGIONS_ETSI}, ++ {.ccode = "GR", .region = REGIONS_ETSI}, ++ {.ccode = "GT", .region = REGIONS_FCC}, ++ {.ccode = "GU", .region = REGIONS_FCC}, ++ {.ccode = "GY", .region = REGIONS_DEFAULT}, ++ {.ccode = "HK", .region = REGIONS_ETSI}, ++ {.ccode = "HN", .region = REGIONS_FCC}, ++ {.ccode = "HR", .region = REGIONS_ETSI}, ++ {.ccode = "HT", .region = REGIONS_FCC}, ++ {.ccode = "HU", .region = REGIONS_ETSI}, ++ {.ccode = "ID", .region = REGIONS_ETSI}, ++ {.ccode = "IE", .region = REGIONS_ETSI}, ++ {.ccode = "IL", .region = REGIONS_ETSI}, ++ {.ccode = "IN", .region = REGIONS_ETSI}, ++ {.ccode = "IQ", .region = REGIONS_ETSI}, ++ {.ccode = "IR", .region = REGIONS_JP}, ++ {.ccode = "IS", .region = REGIONS_ETSI}, ++ {.ccode = "IT", .region = REGIONS_ETSI}, ++ {.ccode = "JM", .region = REGIONS_FCC}, ++ {.ccode = "JO", .region = REGIONS_ETSI}, ++ {.ccode = "KE", .region = REGIONS_ETSI}, ++ {.ccode = "KG", .region = REGIONS_ETSI}, ++ {.ccode = "KH", .region = REGIONS_ETSI}, ++ {.ccode = "KN", .region = REGIONS_ETSI}, ++ {.ccode = "KP", .region = REGIONS_JP}, ++ {.ccode = "KR", .region = REGIONS_ETSI}, ++ {.ccode = "KW", .region = REGIONS_ETSI}, ++ {.ccode = "KY", .region = REGIONS_FCC}, ++ {.ccode = "KZ", .region = REGIONS_DEFAULT}, ++ {.ccode = "LB", .region = REGIONS_ETSI}, ++ {.ccode = "LC", .region = REGIONS_ETSI}, ++ {.ccode = "LI", .region = REGIONS_ETSI}, ++ {.ccode = "LK", .region = REGIONS_FCC}, ++ {.ccode = "LS", .region = REGIONS_ETSI}, ++ {.ccode = "LT", .region = REGIONS_ETSI}, ++ {.ccode = "LU", .region = REGIONS_ETSI}, ++ {.ccode = "LV", .region = REGIONS_ETSI}, ++ {.ccode = "LY", .region = REGIONS_ETSI}, ++ {.ccode = "MA", .region = REGIONS_ETSI}, ++ {.ccode = "MC", .region = REGIONS_ETSI}, ++ {.ccode = "MD", .region = REGIONS_ETSI}, ++ {.ccode = "ME", .region = REGIONS_ETSI}, ++ {.ccode = "MF", .region = REGIONS_ETSI}, ++ {.ccode = "MH", .region = REGIONS_FCC}, ++ {.ccode = "MK", .region = REGIONS_ETSI}, ++ {.ccode = "MN", .region = REGIONS_ETSI}, ++ {.ccode = "MO", .region = REGIONS_ETSI}, ++ {.ccode = "MP", .region = REGIONS_FCC}, ++ {.ccode = "MQ", .region = REGIONS_ETSI}, ++ {.ccode = "MR", .region = REGIONS_ETSI}, ++ {.ccode = "MT", .region = REGIONS_ETSI}, ++ {.ccode = "MU", .region = REGIONS_FCC}, ++ {.ccode = "MV", .region = REGIONS_ETSI}, ++ {.ccode = "MW", .region = REGIONS_ETSI}, ++ {.ccode = "MX", .region = REGIONS_FCC}, ++ {.ccode = "MY", .region = REGIONS_FCC}, ++ {.ccode = "NA", .region = REGIONS_ETSI}, ++ {.ccode = "NG", .region = REGIONS_ETSI}, ++ {.ccode = "NI", .region = REGIONS_FCC}, ++ {.ccode = "NL", .region = REGIONS_ETSI}, ++ {.ccode = "NO", .region = REGIONS_ETSI}, ++ {.ccode = "NP", .region = REGIONS_JP}, ++ {.ccode = "NZ", .region = REGIONS_ETSI}, ++ {.ccode = "OM", .region = REGIONS_ETSI}, ++ {.ccode = "PA", .region = REGIONS_FCC}, ++ {.ccode = "PE", .region = REGIONS_FCC}, ++ {.ccode = "PF", .region = REGIONS_ETSI}, ++ {.ccode = "PG", .region = REGIONS_FCC}, ++ {.ccode = "PH", .region = REGIONS_FCC}, ++ {.ccode = "PK", .region = REGIONS_ETSI}, ++ {.ccode = "PL", .region = REGIONS_ETSI}, ++ {.ccode = "PM", .region = REGIONS_ETSI}, ++ {.ccode = "PR", .region = REGIONS_FCC}, ++ {.ccode = "PT", .region = REGIONS_ETSI}, ++ {.ccode = "PW", .region = REGIONS_FCC}, ++ {.ccode = "PY", .region = REGIONS_FCC}, ++ {.ccode = "QA", .region = REGIONS_ETSI}, ++ {.ccode = "RE", .region = REGIONS_ETSI}, ++ {.ccode = "RO", .region = REGIONS_ETSI}, ++ {.ccode = "RS", .region = REGIONS_ETSI}, ++ {.ccode = "RU", .region = REGIONS_ETSI}, ++ {.ccode = "RW", .region = REGIONS_FCC}, ++ {.ccode = "SA", .region = REGIONS_ETSI}, ++ {.ccode = "SE", .region = REGIONS_ETSI}, ++ {.ccode = "SG", .region = REGIONS_ETSI}, ++ {.ccode = "SI", .region = REGIONS_ETSI}, ++ {.ccode = "SK", .region = REGIONS_ETSI}, ++ {.ccode = "SM", .region = REGIONS_ETSI}, ++ {.ccode = "SN", .region = REGIONS_FCC}, ++ {.ccode = "SR", .region = REGIONS_ETSI}, ++ {.ccode = "SV", .region = REGIONS_FCC}, ++ {.ccode = "SY", .region = REGIONS_DEFAULT}, ++ {.ccode = "TC", .region = REGIONS_FCC}, ++ {.ccode = "TD", .region = REGIONS_ETSI}, ++ {.ccode = "TG", .region = REGIONS_ETSI}, ++ {.ccode = "TH", .region = REGIONS_FCC}, ++ {.ccode = "TJ", .region = REGIONS_ETSI}, ++ {.ccode = "TM", .region = REGIONS_ETSI}, ++ {.ccode = "TN", .region = REGIONS_ETSI}, ++ {.ccode = "TR", .region = REGIONS_ETSI}, ++ {.ccode = "TT", .region = REGIONS_FCC}, ++ {.ccode = "TW", .region = REGIONS_FCC}, ++ {.ccode = "UA", .region = REGIONS_ETSI}, ++ {.ccode = "UG", .region = REGIONS_FCC}, ++ {.ccode = "UY", .region = REGIONS_FCC}, ++ {.ccode = "UZ", .region = REGIONS_ETSI}, ++ {.ccode = "VC", .region = REGIONS_ETSI}, ++ {.ccode = "VE", .region = REGIONS_FCC}, ++ {.ccode = "VI", .region = REGIONS_FCC}, ++ {.ccode = "VN", .region = REGIONS_JP}, ++ {.ccode = "VU", .region = REGIONS_FCC}, ++ {.ccode = "WF", .region = REGIONS_ETSI}, ++ {.ccode = "YE", .region = REGIONS_DEFAULT}, ++ {.ccode = "YT", .region = REGIONS_ETSI}, ++ {.ccode = "ZA", .region = REGIONS_ETSI}, ++ {.ccode = "ZM", .region = REGIONS_ETSI}, ++ {.ccode = "ZW", .region = REGIONS_ETSI}, ++}; ++ ++uint8_t get_ccode_region(char * ccode) ++{ ++ int i, cnt; ++ AICWFDBG(LOGDEBUG, "%s ccode:%s\r\n", __func__, ccode); ++ ++ cnt = sizeof(reg_tables) / sizeof(reg_tables[0]); ++ ++ for (i = 0; i < cnt; i++) { ++ if (reg_tables[i].ccode[0] == ccode[0] && ++ reg_tables[i].ccode[1] == ccode[1]) { ++ AICWFDBG(LOGDEBUG, "region: %d\r\n", reg_tables[i].region); ++ return reg_tables[i].region; ++ } ++ } ++ AICWFDBG(LOGDEBUG, "use default region\r\n"); ++ return REGIONS_DEFAULT; ++} ++ ++u8 get_region_index(char * name) ++{ ++ if (strncmp(name, "SRRC", 4) == 0) ++ return REGIONS_SRRC; ++ else if (strncmp(name, "FCC", 3) == 0) ++ return REGIONS_FCC; ++ else if (strncmp(name, "ETSI", 4) == 0) ++ return REGIONS_ETSI; ++ else if (strncmp(name, "JP", 2) == 0) ++ return REGIONS_JP; ++ else if (strncmp(name, "UNSET", 5) == 0) ++ return REGIONS_DEFAULT; ++ ++ return REGIONS_DEFAULT; ++} ++ ++ ++#ifdef CONFIG_POWER_LIMIT ++#define POWER_LIMIT_INVALID_VAL POWER_LEVEL_INVALID_VAL ++ ++#define POWER_LIMIT_CC_MATCHED_BIT (0x1U << 0) ++ ++#define MAX_2_4G_BW_NUM 2 ++#define MAX_5G_BW_NUM 3 ++#define MAX_REGION_NUM 5 ++ ++typedef struct ++{ ++ u8_l ch_cnt_2g4[MAX_2_4G_BW_NUM]; ++ u8_l ch_cnt_5g[MAX_5G_BW_NUM]; ++ u8_l ch_num_2g4[MAX_2_4G_BW_NUM][MAC_DOMAINCHANNEL_24G_MAX]; ++ u8_l ch_num_5g[MAX_5G_BW_NUM][MAC_DOMAINCHANNEL_5G_MAX]; ++ s8_l max_pwr_2g4[MAX_2_4G_BW_NUM][MAC_DOMAINCHANNEL_24G_MAX]; ++ s8_l max_pwr_5g[MAX_5G_BW_NUM][MAC_DOMAINCHANNEL_5G_MAX]; ++} txpwr_lmt_info_t; ++ ++typedef struct ++{ ++ u32_l flags; ++ txpwr_lmt_info_t txpwr_lmt[MAX_REGION_NUM]; ++} powerlimit_info_t; ++ ++powerlimit_info_t powerlimit_info = {0,}; ++#endif ++ ++#ifdef CONFIG_RWNX_TL4 ++/** ++ * rwnx_plat_tl4_fw_upload() - Load the requested FW into embedded side. ++ * ++ * @rwnx_plat: pointer to platform structure ++ * @fw_addr: Virtual address where the fw must be loaded ++ * @filename: Name of the fw. ++ * ++ * Load a fw, stored as a hex file, into the specified address ++ */ ++static int rwnx_plat_tl4_fw_upload(struct rwnx_plat *rwnx_plat, u8 *fw_addr, ++ char *filename) ++{ ++ struct device *dev = rwnx_platform_get_dev(rwnx_plat); ++ const struct firmware *fw; ++ int err = 0; ++ u32 *dst; ++ u8 const *file_data; ++ char typ0, typ1; ++ u32 addr0, addr1; ++ u32 dat0, dat1; ++ int remain; ++ ++ err = request_firmware(&fw, filename, dev); ++ if (err) { ++ return err; ++ } ++ file_data = fw->data; ++ remain = fw->size; ++ ++ /* Copy the file on the Embedded side */ ++ dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr); ++ ++ /* Walk through all the lines of the configuration file */ ++ while (remain >= 16) { ++ u32 data, offset; ++ ++ if (sscanf(file_data, "%c:%08X %04X", &typ0, &addr0, &dat0) != 3) ++ break; ++ if ((addr0 & 0x01) != 0) { ++ addr0 = addr0 - 1; ++ dat0 = 0; ++ } else { ++ file_data += 16; ++ remain -= 16; ++ } ++ if ((remain < 16) || ++ (sscanf(file_data, "%c:%08X %04X", &typ1, &addr1, &dat1) != 3) || ++ (typ1 != typ0) || (addr1 != (addr0 + 1))) { ++ typ1 = typ0; ++ addr1 = addr0 + 1; ++ dat1 = 0; ++ } else { ++ file_data += 16; ++ remain -= 16; ++ } ++ ++ if (typ0 == 'C') { ++ offset = 0x00200000; ++ if ((addr1 % 4) == 3) ++ offset += 2*(addr1 - 3); ++ else ++ offset += 2*(addr1 + 1); ++ ++ data = dat1 | (dat0 << 16); ++ } else { ++ offset = 2*(addr1 - 1); ++ data = dat0 | (dat1 << 16); ++ } ++ dst = (u32 *)(fw_addr + offset); ++ *dst = data; ++ } ++ ++ release_firmware(fw); ++ ++ return err; ++} ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) ++MODULE_IMPORT_NS("VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver"); ++#else ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#endif ++#endif ++ ++#if 0 ++/** ++ * rwnx_plat_bin_fw_upload() - Load the requested binary FW into embedded side. ++ * ++ * @rwnx_plat: pointer to platform structure ++ * @fw_addr: Virtual address where the fw must be loaded ++ * @filename: Name of the fw. ++ * ++ * Load a fw, stored as a binary file, into the specified address ++ */ ++static int rwnx_plat_bin_fw_upload(struct rwnx_plat *rwnx_plat, u8 *fw_addr, ++ char *filename) ++{ ++ const struct firmware *fw; ++ struct device *dev = rwnx_platform_get_dev(rwnx_plat); ++ int err = 0; ++ unsigned int i, size; ++ u32 *src, *dst; ++ ++ err = request_firmware(&fw, filename, dev); ++ if (err) { ++ return err; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr); ++ ++ src = (u32 *)fw->data; ++ dst = (u32 *)fw_addr; ++ size = (unsigned int)fw->size; ++ ++ /* check potential platform bug on multiple stores vs memcpy */ ++ for (i = 0; i < size; i += 4) { ++ *dst++ = *src++; ++ } ++ ++ release_firmware(fw); ++ ++ return err; ++} ++#endif ++ ++#define MD5(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] ++#define MD5PINRT "file md5:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\r\n" ++ ++static int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device) ++{ ++#ifdef CONFIG_USE_FW_REQUEST ++ const struct firmware *fw = NULL; ++ u32 *dst = NULL; ++ void *buffer=NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ int size = 0; ++ int ret = 0; ++ ++ printk("%s: request firmware = %s \n", __func__ ,name); ++ ++ ret = request_firmware(&fw, name, NULL); ++ ++ if (ret < 0) { ++ printk("Load %s fail\n", name); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ size = fw->size; ++ dst = (u32 *)fw->data; ++ ++ if (size <= 0) { ++ printk("wrong size of firmware file\n"); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ memcpy(buffer, dst, size); ++ ++ *fw_buf = buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ printk(MD5PINRT, MD5(decrypt)); ++ ++ release_firmware(fw); ++ ++ return size; ++#else ++ void *buffer = NULL; ++ char *path = NULL; ++ struct file *fp = NULL; ++ int size = 0, len = 0;// i = 0; ++ ssize_t rdlen = 0; ++ //u32 *src = NULL, *dst = NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ ++ /* get the firmware path */ ++ path = __getname(); ++ if (!path) { ++ *fw_buf = NULL; ++ return -1; ++ } ++ ++ len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", aic_fw_path, name); ++ ++ //len = snprintf(path, FW_PATH_MAX_LEN, "%s", name); ++ if (len >= FW_PATH_MAX_LEN) { ++ AICWFDBG(LOGERROR, "%s: %s file's path too long\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ return -1; ++ } ++ ++ AICWFDBG(LOGINFO, "%s :firmware path = %s \n", __func__, path); ++ ++ /* open the firmware file */ ++ fp = filp_open(path, O_RDONLY, 0); ++ if (IS_ERR_OR_NULL(fp)) { ++ AICWFDBG(LOGERROR, "%s: %s file failed to open\n", __func__, name); ++ *fw_buf = NULL; ++ __putname(path); ++ fp = NULL; ++ return -1; ++ } ++ ++ size = i_size_read(file_inode(fp)); ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "%s: %s file size invalid %d\n", __func__, name, size); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ } ++ ++ /* start to read from firmware file */ ++ buffer = kzalloc(size, GFP_KERNEL); ++ if (!buffer) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ return -1; ++ } ++ ++ #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) ++ rdlen = kernel_read(fp, buffer, size, &fp->f_pos); ++ #else ++ rdlen = kernel_read(fp, fp->f_pos, buffer, size); ++ #endif ++ ++ if (size != rdlen) { ++ AICWFDBG(LOGERROR, "%s: %s file rdlen invalid %d\n", __func__, name, (int)rdlen); ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ kfree(buffer); ++ buffer = NULL; ++ return -1; ++ } ++ if (rdlen > 0) { ++ fp->f_pos += rdlen; ++ } ++ ++#if 0 ++ /*start to transform the data format*/ ++ src = (u32 *)buffer; ++ dst = (u32 *)kzalloc(size, GFP_KERNEL); ++ ++ if (!dst) { ++ *fw_buf = NULL; ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ kfree(buffer); ++ buffer = NULL; ++ return -1; ++ } ++ ++ for (i = 0; i < (size/4); i++) { ++ dst[i] = src[i]; ++ } ++#endif ++ ++ __putname(path); ++ filp_close(fp, NULL); ++ fp = NULL; ++ //kfree(buffer); ++ //buffer = NULL; ++ *fw_buf = (u32*)buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ ++ AICWFDBG(LOGINFO, MD5PINRT, MD5(decrypt)); ++ ++ return size; ++#endif ++} ++ ++ ++ ++/* buffer is allocated by kzalloc */ ++int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, u32** buffer, const char *filename) ++{ ++ int size; ++ ++ AICWFDBG(LOGINFO, "### Load file %s\n", filename); ++ ++ size = rwnx_load_firmware(buffer, filename, NULL); ++ ++ return size; ++} ++ ++static void rwnx_restore_firmware(u32 **fw_buf) ++{ ++#ifdef CONFIG_USE_FW_REQUEST ++ vfree(*fw_buf); ++#else ++ kfree(*fw_buf); ++#endif ++ *fw_buf = NULL; ++} ++ ++ ++void rwnx_release_firmware_common(u32** buffer) ++{ ++ rwnx_restore_firmware(buffer); ++} ++ ++ ++/** ++ * rwnx_plat_bin_fw_upload_2() - Load the requested binary FW into embedded side. ++ * ++ * @rwnx_hw: Main driver data ++ * @fw_addr: Address where the fw must be loaded ++ * @filename: Name of the fw. ++ * ++ * Load a fw, stored as a binary file, into the specified address ++ */ ++int rwnx_plat_bin_fw_upload_2(struct rwnx_hw *rwnx_hw, u32 fw_addr, ++ char *filename) ++{ ++ int err = 0; ++ unsigned int i = 0, size; ++// u32 *src; ++ u32 *dst=NULL; ++ ++ /* Copy the file on the Embedded side */ ++ AICWFDBG(LOGINFO, "### Upload %s firmware, @ = %x\n", filename, fw_addr); ++ ++ size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); ++ if (!dst) { ++ AICWFDBG(LOGERROR, "No such file or directory\n"); ++ return -1; ++ } ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ dst = NULL; ++ err = -1; ++ } ++ ++ AICWFDBG(LOGINFO, "size=%d, dst[0]=%x\n", size, dst[0]); ++ if (size > 512) { ++ for (; i < (size - 512); i += 512) { ++ //printk("wr blk 0: %p -> %x\r\n", dst + i / 4, fw_addr + i); ++ err = rwnx_send_dbg_mem_block_write_req(rwnx_hw, fw_addr + i, 512, dst + i / 4); ++ if (err) { ++ AICWFDBG(LOGERROR, "bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ break; ++ } ++ } ++ } ++ if (!err && (i < size)) { ++ //printk("wr blk 1: %p -> %x\r\n", dst + i / 4, fw_addr + i); ++ err = rwnx_send_dbg_mem_block_write_req(rwnx_hw, fw_addr + i, size - i, dst + i / 4); ++ if (err) { ++ AICWFDBG(LOGERROR, "bin upload fail: %x, err:%d\r\n", fw_addr + i, err); ++ } ++ } ++ ++ if (dst) { ++ rwnx_release_firmware_common(&dst); ++ } ++ ++ return err; ++} ++ ++ ++ ++typedef struct { ++ txpwr_idx_conf_t txpwr_idx; ++ txpwr_ofst_conf_t txpwr_ofst; ++ xtal_cap_conf_t xtal_cap; ++} nvram_info_t; ++ ++nvram_info_t nvram_info = { ++ .txpwr_idx = { ++ .enable = 1, ++ .dsss = 9, ++ .ofdmlowrate_2g4 = 8, ++ .ofdm64qam_2g4 = 8, ++ .ofdm256qam_2g4 = 8, ++ .ofdm1024qam_2g4 = 8, ++ .ofdmlowrate_5g = 11, ++ .ofdm64qam_5g = 10, ++ .ofdm256qam_5g = 9, ++ .ofdm1024qam_5g = 9 ++ }, ++ .txpwr_ofst = { ++ .enable = 1, ++ .chan_1_4 = 0, ++ .chan_5_9 = 0, ++ .chan_10_13 = 0, ++ .chan_36_64 = 0, ++ .chan_100_120 = 0, ++ .chan_122_140 = 0, ++ .chan_142_165 = 0, ++ }, ++ .xtal_cap = { ++ .enable = 0, ++ .xtal_cap = 24, ++ .xtal_cap_fine = 31, ++ }, ++}; ++ ++void get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst_conf_t *txpwr_ofst) ++{ ++ txpwr_ofst->enable = userconfig_info.txpwr_ofst.enable; ++ txpwr_ofst->chan_1_4 = userconfig_info.txpwr_ofst.chan_1_4; ++ txpwr_ofst->chan_5_9 = userconfig_info.txpwr_ofst.chan_5_9; ++ txpwr_ofst->chan_10_13 = userconfig_info.txpwr_ofst.chan_10_13; ++ txpwr_ofst->chan_36_64 = userconfig_info.txpwr_ofst.chan_36_64; ++ txpwr_ofst->chan_100_120 = userconfig_info.txpwr_ofst.chan_100_120; ++ txpwr_ofst->chan_122_140 = userconfig_info.txpwr_ofst.chan_122_140; ++ txpwr_ofst->chan_142_165 = userconfig_info.txpwr_ofst.chan_142_165; ++ ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst->enable); ++ AICWFDBG(LOGINFO, "%s:chan_1_4 :%d\r\n", __func__, txpwr_ofst->chan_1_4); ++ AICWFDBG(LOGINFO, "%s:chan_5_9 :%d\r\n", __func__, txpwr_ofst->chan_5_9); ++ AICWFDBG(LOGINFO, "%s:chan_10_13 :%d\r\n", __func__, txpwr_ofst->chan_10_13); ++ AICWFDBG(LOGINFO, "%s:chan_36_64 :%d\r\n", __func__, txpwr_ofst->chan_36_64); ++ AICWFDBG(LOGINFO, "%s:chan_100_120:%d\r\n", __func__, txpwr_ofst->chan_100_120); ++ AICWFDBG(LOGINFO, "%s:chan_122_140:%d\r\n", __func__, txpwr_ofst->chan_122_140); ++ AICWFDBG(LOGINFO, "%s:chan_142_165:%d\r\n", __func__, txpwr_ofst->chan_142_165); ++} ++ ++void get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x_conf_t *txpwr_ofst2x) ++{ ++ int type, ch_grp; ++ *txpwr_ofst2x = userconfig_info.txpwr_ofst2x; ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst2x->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g: [0]:11b, [1]:ofdm_highrate, [2]:ofdm_lowrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_2g4[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g: [0]:ofdm_lowrate, [1]:ofdm_highrate, [2]:ofdm_midrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 3; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d", txpwr_ofst2x->pwrofst2x_tbl_5g[type][ch_grp]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++} ++ ++void get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2) ++{ ++ int type, ch_grp; ++ *txpwr_ofst2x_v2 = userconfig_info.txpwr_ofst2x_v2; ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst2x_v2->enable); ++ AICWFDBG(LOGINFO, "pwrofst2x 2.4g(ant0/ant1): [0]:11b, [1]:ofdm_highrate\n" ++ " chan=" "\t1-4" "\t5-9" "\t10-13"); ++ for (type = 0; type < 2; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 3; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_2g4_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\npwrofst2x 5g: [0]:ofdm_highrate\n" ++ " chan=" "\t36-50" "\t51-64" "\t98-114" "\t115-130" "\t131-146" "\t147-166"); ++ for (type = 0; type < 1; type++) { ++ AICWFDBG(LOGINFO, "\n [%d] =", type); ++ for (ch_grp = 0; ch_grp < 6; ch_grp++) { ++ AICWFDBG(LOGINFO, "\t%d/%d", txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant0[ch_grp][type], txpwr_ofst2x_v2->pwrofst2x_tbl_5g_ant1[ch_grp][type]); ++ } ++ } ++ AICWFDBG(LOGINFO, "\n"); ++} ++ ++void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx) ++{ ++ memcpy(txpwr_idx, &(nvram_info.txpwr_idx), sizeof(txpwr_idx_conf_t)); ++} ++ ++void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst) ++{ ++ memcpy(txpwr_ofst, &(nvram_info.txpwr_ofst), sizeof(txpwr_ofst_conf_t)); ++} ++ ++void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap) ++{ ++ if(nvram_info.xtal_cap.enable){ ++ *xtal_cap = nvram_info.xtal_cap; ++ } ++ ++ if(userconfig_info.xtal_cap.enable){ ++ *xtal_cap = userconfig_info.xtal_cap; ++ } ++ ++ AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, xtal_cap->enable); ++ AICWFDBG(LOGINFO, "%s:xtal_cap :%d\r\n", __func__, xtal_cap->xtal_cap); ++ AICWFDBG(LOGINFO, "%s:xtal_cap_fine:%d\r\n", __func__, xtal_cap->xtal_cap_fine); ++} ++ ++s8_l get_txpwr_max(s8_l power) ++{ ++ int i=0; ++ ++ if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80 || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i]; ++ } ++ for (i = 0; i <= 9; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i]; ++ } ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i]; ++ } ++ for (i = 4; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i]; ++ } ++ for (i = 0; i <= 9; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i]; ++ } ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i]) ++ power = userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i]; ++ } ++ ++ if ((userconfig_info.txpwr_loss.loss_enable_2g4 == 1) || ++ (userconfig_info.txpwr_loss.loss_enable_5g == 1)) { ++ if (userconfig_info.txpwr_loss.loss_value_2g4 < ++ userconfig_info.txpwr_loss.loss_value_5g) ++ power += userconfig_info.txpwr_loss.loss_value_5g; ++ else ++ power += userconfig_info.txpwr_loss.loss_value_2g4; ++ } ++ ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[i]; ++ } ++ for (i = 0; i <= 9; i++){ ++ if(power < userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[i]; ++ } ++ for (i = 0; i <= 11; i++){ ++ if(power < userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[i]) ++ power = userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[i]; ++ } ++ } ++ ++ printk("%s:txpwr_max:%d \r\n",__func__,power); ++ return power; ++} ++ ++ ++void set_txpwr_loss_ofst(s8_l value) ++{ ++ int i=0; ++ if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i] += value; ++ } ++ for (i = 4; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i] += value; ++ } ++ }else if( g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[i] += value; ++ } ++ for (i = 0; i <= 7; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[i] += value; ++ } ++ }else if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[i] += value; ++ } ++ for (i = 0; i <= 9; i++){ ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[i] += value; ++ } ++ for (i = 0; i <= 11; i++){ ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[i] += value; ++ } ++ } ++ printk("%s:value:%d\r\n", __func__, value); ++} ++ ++ ++#define MATCH_NODE(type, node, cfg_key) {cfg_key, offsetof(type, node)} ++ ++struct parse_match_t { ++ char keyname[64]; ++ int offset; ++}; ++ ++static const char *parse_key_prefix[] = { ++ [0x01] = "module0_", ++ [0x21] = "module1_", ++}; ++ ++static const struct parse_match_t parse_match_tab[] = { ++ MATCH_NODE(nvram_info_t, txpwr_idx.enable, "enable"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.dsss, "dsss"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdmlowrate_2g4, "ofdmlowrate_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm64qam_2g4, "ofdm64qam_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm256qam_2g4, "ofdm256qam_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm1024qam_2g4, "ofdm1024qam_2g4"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdmlowrate_5g, "ofdmlowrate_5g"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm64qam_5g, "ofdm64qam_5g"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm256qam_5g, "ofdm256qam_5g"), ++ MATCH_NODE(nvram_info_t, txpwr_idx.ofdm1024qam_5g, "ofdm1024qam_5g"), ++ ++ MATCH_NODE(nvram_info_t, txpwr_ofst.enable, "ofst_enable"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_1_4, "ofst_chan_1_4"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_5_9, "ofst_chan_5_9"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_10_13, "ofst_chan_10_13"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_36_64, "ofst_chan_36_64"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_100_120, "ofst_chan_100_120"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_122_140, "ofst_chan_122_140"), ++ MATCH_NODE(nvram_info_t, txpwr_ofst.chan_142_165, "ofst_chan_142_165"), ++ ++ MATCH_NODE(nvram_info_t, xtal_cap.enable, "xtal_enable"), ++ MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap, "xtal_cap"), ++ MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap_fine, "xtal_cap_fine"), ++}; ++ ++static int parse_key_val(const char *str, const char *key, char *val) ++{ ++ const char *p = NULL; ++ const char *dst = NULL; ++ int keysize = 0; ++ int bufsize = 0; ++ ++ if (str == NULL || key == NULL || val == NULL) ++ return -1; ++ ++ keysize = strlen(key); ++ bufsize = strlen(str); ++ if (bufsize <= keysize) ++ return -1; ++ ++ p = str; ++ while (*p != 0 && *p == ' ') ++ p++; ++ ++ if (*p == '#') ++ return -1; ++ ++ if (str + bufsize - p <= keysize) ++ return -1; ++ ++ if (strncmp(p, key, keysize) != 0) ++ return -1; ++ ++ p += keysize; ++ ++ while (*p != 0 && *p == ' ') ++ p++; ++ ++ if (*p != '=') ++ return -1; ++ ++ p++; ++ while (*p != 0 && *p == ' ') ++ p++; ++ ++ if (*p == '"') ++ p++; ++ ++ dst = p; ++ while (*p != 0) ++ p++; ++ ++ p--; ++ while (*p == ' ') ++ p--; ++ ++ if (*p == '"') ++ p--; ++ ++ while (*p == '\r' || *p == '\n') ++ p--; ++ ++ p++; ++ strncpy(val, dst, p -dst); ++ val[p - dst] = 0; ++ return 0; ++} ++ ++int rwnx_atoi2(char *value, int c_len) ++{ ++ int len = 0; ++ int i = 0; ++ int result = 0; ++ int flag = 1; ++ ++ if (value[0] == '-') { ++ flag = -1; ++ value++; ++ } ++ len = c_len; ++ ++ for (i = 0;i < len ;i++) { ++ result = result * 10; ++ if (value[i] >= 48 && value[i] <= 57) { ++ result += value[i] - 48; ++ } else { ++ result = 0; ++ break; ++ } ++ } ++ ++ return result * flag; ++} ++ ++ ++int rwnx_atoi(char *value) ++{ ++ int len = 0; ++ int i = 0; ++ int result = 0; ++ int flag = 1; ++ ++ if (value[0] == '-') { ++ flag = -1; ++ value++; ++ } ++ len = strlen(value); ++ ++ for (i = 0;i < len ;i++) { ++ result = result * 10; ++ if (value[i] >= 48 && value[i] <= 57) { ++ result += value[i] - 48; ++ } else { ++ result = 0; ++ break; ++ } ++ } ++ ++ return result * flag; ++} ++ ++ ++void rwnx_plat_nvram_set_value(char *command, char *value) ++{ ++ //TODO send command ++ AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); ++ if (!strcmp(command, "enable")) { ++ userconfig_info.txpwr_lvl.enable = rwnx_atoi(value); ++ userconfig_info.txpwr_lvl_v2.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "dsss")) { ++ userconfig_info.txpwr_lvl.dsss = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_2g4")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_5g")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { ++ userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_enable")) { ++ userconfig_info.txpwr_ofst.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_1_4")) { ++ userconfig_info.txpwr_ofst.chan_1_4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_5_9")) { ++ userconfig_info.txpwr_ofst.chan_5_9 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_10_13")) { ++ userconfig_info.txpwr_ofst.chan_10_13 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_36_64")) { ++ userconfig_info.txpwr_ofst.chan_36_64 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_100_120")) { ++ userconfig_info.txpwr_ofst.chan_100_120 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_122_140")) { ++ userconfig_info.txpwr_ofst.chan_122_140 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_142_165")) { ++ userconfig_info.txpwr_ofst.chan_142_165 = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_enable")) { ++ userconfig_info.xtal_cap.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap")) { ++ userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap_fine")) { ++ userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); ++ } else { ++ AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); ++ } ++} ++ ++void rwnx_plat_nvram_set_value_v3(char *command, char *value) ++{ ++ //TODO send command ++ AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); ++ if (!strcmp(command, "enable")) { ++ userconfig_info.txpwr_lvl.enable = rwnx_atoi(value); ++ userconfig_info.txpwr_lvl_v3.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "dsss")) { ++ userconfig_info.txpwr_lvl.dsss = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_2g4")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_2g4")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdmlowrate_5g")) { ++ userconfig_info.txpwr_lvl.ofdmlowrate_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm64qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm64qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm256qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm256qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofdm1024qam_5g")) { ++ userconfig_info.txpwr_lvl.ofdm1024qam_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_1m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_2m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_5m5_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_11m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_6m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_9m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_12m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_18m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_24m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_36m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_48m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_54m_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_5g")) { ++ userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_enable")) { ++ userconfig_info.txpwr_lvl_adj.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_1_4")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_5_9")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_10_13")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_42")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_58")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_106")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_122")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_138")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_155")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_2g4")) { ++ userconfig_info.txpwr_loss.loss_enable_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_2g4")) { ++ userconfig_info.txpwr_loss.loss_value_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_5g")) { ++ userconfig_info.txpwr_loss.loss_enable_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_5g")) { ++ userconfig_info.txpwr_loss.loss_value_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_enable")) { ++ userconfig_info.txpwr_ofst.enable = rwnx_atoi(value); ++ userconfig_info.txpwr_ofst2x.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_1_4")) { ++ userconfig_info.txpwr_ofst.chan_1_4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_5_9")) { ++ userconfig_info.txpwr_ofst.chan_5_9 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_10_13")) { ++ userconfig_info.txpwr_ofst.chan_10_13 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_36_64")) { ++ userconfig_info.txpwr_ofst.chan_36_64 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_100_120")) { ++ userconfig_info.txpwr_ofst.chan_100_120 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_122_140")) { ++ userconfig_info.txpwr_ofst.chan_122_140 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_chan_142_165")) { ++ userconfig_info.txpwr_ofst.chan_142_165 = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_11b_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_11b_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_11b_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[0][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_highrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_highrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_highrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[1][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_lowrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_lowrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ofdm_lowrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_2g4[2][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_lowrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[0][5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[1][5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_midrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x.pwrofst2x_tbl_5g[2][5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_enable")) { ++ userconfig_info.xtal_cap.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap")) { ++ userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap_fine")) { ++ userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); ++ } else { ++ AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); ++ } ++} ++ ++void rwnx_plat_userconfig_parsing2(char *buffer, int size) ++{ ++ int i = 0; ++ int parse_state = 0; ++ char command[30]; ++ char value[100]; ++ int char_counter = 0; ++ ++ memset(command, 0, 30); ++ memset(value, 0, 100); ++ ++ for (i = 0; i < size; i++) { ++ //Send command or print nvram log when char is \r or \n ++ if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ if (command[0] != 0 && value[0] != 0) { ++ if (parse_state == PRINT) { ++ AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); ++ } else if (parse_state == GET_VALUE) { ++ rwnx_plat_nvram_set_value(command, value); ++ } ++ } ++ //Reset command value and char_counter ++ memset(command, 0, 30); ++ memset(value, 0, 100); ++ char_counter = 0; ++ parse_state = INIT; ++ continue; ++ } ++ ++ //Switch parser state ++ if (parse_state == INIT) { ++ if (buffer[i] == '#') { ++ parse_state = PRINT; ++ continue; ++ } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ parse_state = INIT; ++ continue; ++ } else { ++ parse_state = CMD; ++ } ++ } ++ ++ //Fill data to command and value ++ if (parse_state == PRINT) { ++ command[0] = 0x01; ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == CMD) { ++ if (command[0] != 0 && buffer[i] == '=') { ++ parse_state = GET_VALUE; ++ char_counter = 0; ++ continue; ++ } ++ command[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == GET_VALUE) { ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } ++ } ++} ++ ++void rwnx_plat_userconfig_parsing3(char *buffer, int size) ++{ ++ int i = 0; ++ int parse_state = 0; ++ char command[64]; ++ char value[100]; ++ int char_counter = 0; ++ ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ ++ for (i = 0; i < size; i++) { ++ //Send command or print nvram log when char is \r or \n ++ if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ if (command[0] != 0 && value[0] != 0) { ++ if (parse_state == PRINT) { ++ AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); ++ } else if (parse_state == GET_VALUE) { ++ rwnx_plat_nvram_set_value_v3(command, value); ++ } ++ } ++ //Reset command value and char_counter ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ char_counter = 0; ++ parse_state = INIT; ++ continue; ++ } ++ ++ //Switch parser state ++ if (parse_state == INIT) { ++ if (buffer[i] == '#') { ++ parse_state = PRINT; ++ continue; ++ } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ parse_state = INIT; ++ continue; ++ } else { ++ parse_state = CMD; ++ } ++ } ++ ++ //Fill data to command and value ++ if (parse_state == PRINT) { ++ command[0] = 0x01; ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == CMD) { ++ if (command[0] != 0 && buffer[i] == '=') { ++ parse_state = GET_VALUE; ++ char_counter = 0; ++ continue; ++ } ++ command[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == GET_VALUE) { ++ if(buffer[i] != 0x2D && (buffer[i] < 0x30 || buffer[i] > 0x39)) { ++ continue; ++ } ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } ++ } ++} ++ ++void rwnx_plat_userconfig_parsing(struct rwnx_hw *rwnx_hw, char *buffer, int size) ++{ ++ char conf[100], keyname[64]; ++ char *line; ++ char *data; ++ int i = 0, err, len = 0; ++ long val; ++ ++ if (size <= 0) { ++ pr_err("Config buffer size %d error\n", size); ++ return; ++ } ++ ++ printk("%s rwnx_hw->vendor_info:0x%02X \r\n", __func__, rwnx_hw->vendor_info); ++ if (rwnx_hw->vendor_info == 0x00 || ++ (rwnx_hw->vendor_info > (sizeof(parse_key_prefix) / sizeof(parse_key_prefix[0]) - 1))) { ++ printk("Unsuppor vendor info config\n"); ++ printk("Using module0 config\n"); ++ rwnx_hw->vendor_info = 0x01; ++ //return; ++ } ++ ++ data = vmalloc(size + 1); ++ if (!data) { ++ pr_err("vmalloc fail\n"); ++ return; ++ } ++ ++ memcpy(data, buffer, size); ++ buffer = data; ++ ++ while (1) { ++ line = buffer; ++ if (*line == 0) ++ break; ++ ++ while (*buffer != '\r' && *buffer != '\n' && *buffer != 0 && len++ < size) ++ buffer++; ++ ++ while ((*buffer == '\r' || *buffer == '\n') && len++ < size) ++ *buffer++ = 0; ++ ++ if (len >= size) ++ *buffer = 0; ++ ++ // store value to data struct ++ for (i = 0; i < sizeof(parse_match_tab) / sizeof(parse_match_tab[0]); i++) { ++ sprintf(&keyname[0], "%s%s", parse_key_prefix[rwnx_hw->vendor_info], parse_match_tab[i].keyname); ++ if (parse_key_val(line, keyname, conf) == 0) { ++ err = kstrtol(conf, 0, &val); ++ *(unsigned long *)((unsigned long)&nvram_info + parse_match_tab[i].offset) = val; ++ printk("%s, %s = %ld\n", __func__, parse_match_tab[i].keyname, val); ++ break; ++ } ++ } ++ ++ } ++ vfree(data); ++} ++ ++void rwnx_plat_nvram_set_value_8800d80x2(char *command, char *value) ++{ ++ //TODO send command ++ AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); ++ if (!strcmp(command, "enable")) { ++ userconfig_info.txpwr_lvl_v4.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_6m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_9m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_12m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_18m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_24m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_36m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_48m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11a_54m_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11n_11ac_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11n_11ac_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs0_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs1_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs2_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs3_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs4_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs5_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs6_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[6] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs7_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[7] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs8_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[8] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs9_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[9] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs10_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[10] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_11ax_mcs11_5g")) { ++ userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_5g[11] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_enable")) { ++ userconfig_info.txpwr_lvl_adj.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_1_4")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_5_9")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_2g4_chan_10_13")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_42")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_58")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_106")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_122")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_138")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "lvl_adj_5g_chan_155")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_2g4")) { ++ userconfig_info.txpwr_loss.loss_enable_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_2g4")) { ++ userconfig_info.txpwr_loss.loss_value_2g4 = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable_5g")) { ++ userconfig_info.txpwr_loss.loss_enable_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value_5g")) { ++ userconfig_info.txpwr_loss.loss_value_5g = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_enable")) { ++ userconfig_info.txpwr_ofst2x_v2.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_11b_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_11b_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_11b_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_ofdm_highrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_ofdm_highrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant0_ofdm_highrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant0[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_11b_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_11b_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_11b_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_ofdm_highrate_chan_1_4")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[0][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_ofdm_highrate_chan_5_9")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[1][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_2g4_ant1_ofdm_highrate_chan_10_13")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_2g4_ant1[2][1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[3][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[4][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant0_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant0[5][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[0][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[1][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[2][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[3][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[4][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ant1_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_ofst2x_v2.pwrofst2x_tbl_5g_ant1[5][0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_enable")) { ++ userconfig_info.xtal_cap.enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap")) { ++ userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); ++ } else if (!strcmp(command, "xtal_cap_fine")) { ++ userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); ++ } else { ++ AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); ++ } ++} ++ ++void rwnx_plat_userconfig_parsing_8800d80x2(char *buffer, int size) ++{ ++ int i = 0; ++ int parse_state = 0; ++ char command[100]; ++ char value[100]; ++ int char_counter = 0; ++ ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ ++ for (i = 0; i < size; i++) { ++ //Send command or print nvram log when char is \r or \n ++ if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ if (command[0] != 0 && value[0] != 0) { ++ if (parse_state == PRINT) { ++ AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); ++ } else if (parse_state == GET_VALUE) { ++ rwnx_plat_nvram_set_value_8800d80x2(command, value); ++ } ++ } ++ //Reset command value and char_counter ++ memset(command, 0, 64); ++ memset(value, 0, 100); ++ char_counter = 0; ++ parse_state = INIT; ++ continue; ++ } ++ ++ //Switch parser state ++ if (parse_state == INIT) { ++ if (buffer[i] == '#') { ++ parse_state = PRINT; ++ continue; ++ } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { ++ parse_state = INIT; ++ continue; ++ } else { ++ parse_state = CMD; ++ } ++ } ++ ++ //Fill data to command and value ++ if (parse_state == PRINT) { ++ command[0] = 0x01; ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == CMD) { ++ if (command[0] != 0 && buffer[i] == '=') { ++ parse_state = GET_VALUE; ++ char_counter = 0; ++ continue; ++ } ++ command[char_counter] = buffer[i]; ++ char_counter++; ++ } else if (parse_state == GET_VALUE) { ++ if(buffer[i] != 0x2D && (buffer[i] < 0x30 || buffer[i] > 0x39)) { ++ continue; ++ } ++ value[char_counter] = buffer[i]; ++ char_counter++; ++ } ++ } ++} ++ ++static int aic_load_firmware(u32 ** fw_buf, char *fw_path,const char *name, struct device *device) ++{ ++#ifdef CONFIG_USE_FW_REQUEST ++ const struct firmware *fw = NULL; ++ u32 *dst = NULL; ++ void *buffer=NULL; ++ MD5_CTX md5; ++ unsigned char decrypt[16]; ++ int size = 0; ++ int ret = 0; ++ ++ AICWFDBG(LOGINFO, "%s: request firmware = %s \n", __func__ ,name); ++ ++ ret = request_firmware(&fw, name, NULL); ++ ++ if (ret < 0) { ++ AICWFDBG(LOGERROR, "Load %s fail\n", name); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ size = fw->size; ++ dst = (u32 *)fw->data; ++ ++ if (size <= 0) { ++ AICWFDBG(LOGERROR, "wrong size of firmware file\n"); ++ release_firmware(fw); ++ return -1; ++ } ++ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ memcpy(buffer, dst, size); ++ ++ *fw_buf = buffer; ++ ++ MD5Init(&md5); ++ MD5Update(&md5, (unsigned char *)buffer, size); ++ MD5Final(&md5, decrypt); ++ AICWFDBG(LOGINFO, MD5PINRT, MD5(decrypt)); ++ ++ release_firmware(fw); ++ ++ return size; ++#else ++ void *buffer=NULL; ++ char *path=NULL; ++ struct file *fp=NULL; ++ int size = 0, len=0;//, i=0; ++ ssize_t rdlen=0; ++ //u32 *src=NULL, *dst = NULL; ++ ++ /* get the firmware path */ ++ path = __getname(); ++ if (!path){ ++ *fw_buf=NULL; ++ return -1; ++ } ++ ++ len = sprintf(path, "%s/%s",fw_path, name); ++ ++ AICWFDBG(LOGINFO, "%s :firmware path = %s \n", __func__ ,path); ++ ++ ++ /* open the firmware file */ ++ fp=filp_open(path, O_RDONLY, 0); ++ if(IS_ERR(fp) || (!fp)){ ++ printk("%s: %s file failed to open\n", __func__, name); ++ if(IS_ERR(fp)){ ++ printk("is_Err\n"); ++ } ++ if((!fp)){ ++ printk("null\n"); ++ } ++ *fw_buf=NULL; ++ __putname(path); ++ fp=NULL; ++ return -1; ++ } ++ ++ size = i_size_read(file_inode(fp)); ++ if(size<=0){ ++ printk("%s: %s file size invalid %d\n", __func__, name, size); ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ return -1; ++ } ++ ++ /* start to read from firmware file */ ++ buffer = vmalloc(size); ++ memset(buffer, 0, size); ++ if(!buffer){ ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ return -1; ++ } ++ ++ ++ #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) ++ rdlen = kernel_read(fp, buffer, size, &fp->f_pos); ++ #else ++ rdlen = kernel_read(fp, fp->f_pos, buffer, size); ++ #endif ++ ++ if(size != rdlen){ ++ printk("%s: %s file rdlen invalid %d %d\n", __func__, name, (int)rdlen, size); ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ vfree(buffer); ++ buffer=NULL; ++ return -1; ++ } ++ if(rdlen > 0){ ++ fp->f_pos += rdlen; ++ //printk("f_pos=%d\n", (int)fp->f_pos); ++ } ++ ++#if 0 ++ /*start to transform the data format*/ ++ src = (u32*)buffer; ++ //printk("malloc dst\n"); ++ dst = (u32*)vmalloc(size); ++ memset(dst, 0, size); ++ ++ if(!dst){ ++ *fw_buf=NULL; ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ vfree(buffer); ++ buffer=NULL; ++ return -1; ++ } ++ ++ for(i=0;i<(size/4);i++){ ++ dst[i] = src[i]; ++ } ++#endif ++ ++ __putname(path); ++ filp_close(fp,NULL); ++ fp=NULL; ++ //vfree(buffer); ++ //buffer=NULL; ++ *fw_buf = (u32 *)buffer; ++ ++ return size; ++#endif ++} ++ ++ ++ ++#define FW_USERCONFIG_NAME "aic_userconfig.txt" ++ ++int rwnx_plat_userconfig_upload_android(struct rwnx_hw *rwnx_hw, char *fw_path, char *filename) ++{ ++ int size; ++ u32 *dst=NULL; ++ ++ printk("userconfig file path:%s \r\n", filename); ++ ++ /* load aic firmware */ ++ size = aic_load_firmware(&dst, fw_path ,filename, NULL); ++ if(size <= 0){ ++ printk("wrong size of firmware file\n"); ++ vfree(dst); ++ dst = NULL; ++ return 0; ++ } ++ ++ /* Copy the file on the Embedded side */ ++ printk("### Upload %s userconfig, size=%d\n", filename, size); ++ ++ rwnx_plat_userconfig_parsing(rwnx_hw, (char *)dst, size); ++ ++ if (dst) { ++ vfree(dst); ++ dst = NULL; ++ } ++ ++ printk("userconfig download complete\n\n"); ++ ++ return 0; ++ ++} ++ ++/** ++ * rwnx_plat_fmac_load() - Load FW code ++ * ++ * @rwnx_hw: Main driver data ++ */ ++ #if 0 ++static int rwnx_plat_fmac_load(struct rwnx_hw *rwnx_hw, char *fw_path) ++{ ++ int ret = 0; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ret = rwnx_plat_userconfig_upload_android(rwnx_hw, fw_path, FW_USERCONFIG_NAME); ++ return ret; ++} ++ #endif ++ ++/** ++ * rwnx_platform_reset() - Reset the platform ++ * ++ * @rwnx_plat: platform data ++ */ ++static int rwnx_platform_reset(struct rwnx_plat *rwnx_plat) ++{ ++ u32 regval; ++ ++#if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) ++ return 0; ++#endif ++ ++ /* the doc states that SOFT implies FPGA_B_RESET ++ * adding FPGA_B_RESET is clearer */ ++ RWNX_REG_WRITE(SOFT_RESET | FPGA_B_RESET, rwnx_plat, ++ RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); ++ msleep(100); ++ ++ regval = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); ++ ++ if (regval & SOFT_RESET) { ++ dev_err(rwnx_platform_get_dev(rwnx_plat), "reset: failed\n"); ++ return -EIO; ++ } ++ ++ RWNX_REG_WRITE(regval & ~FPGA_B_RESET, rwnx_plat, ++ RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); ++ msleep(100); ++ return 0; ++} ++ ++/** ++ * rwmx_platform_save_config() - Save hardware config before reload ++ * ++ * @rwnx_plat: Pointer to platform data ++ * ++ * Return configuration registers values. ++ */ ++static void *rwnx_term_save_config(struct rwnx_plat *rwnx_plat) ++{ ++ const u32 *reg_list; ++ u32 *reg_value, *res; ++ int i, size = 0; ++ ++ if (rwnx_plat->get_config_reg) { ++ size = rwnx_plat->get_config_reg(rwnx_plat, ®_list); ++ } ++ ++ if (size <= 0) ++ return NULL; ++ ++ res = kmalloc(sizeof(u32) * size, GFP_KERNEL); ++ if (!res) ++ return NULL; ++ ++ reg_value = res; ++ for (i = 0; i < size; i++) { ++ *reg_value++ = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, ++ *reg_list++); ++ } ++ ++ return res; ++} ++ ++#if 0 ++/** ++ * rwmx_platform_restore_config() - Restore hardware config after reload ++ * ++ * @rwnx_plat: Pointer to platform data ++ * @reg_value: Pointer of value to restore ++ * (obtained with rwmx_platform_save_config()) ++ * ++ * Restore configuration registers value. ++ */ ++static void rwnx_term_restore_config(struct rwnx_plat *rwnx_plat, ++ u32 *reg_value) ++{ ++ const u32 *reg_list; ++ int i, size = 0; ++ ++ if (!reg_value || !rwnx_plat->get_config_reg) ++ return; ++ ++ size = rwnx_plat->get_config_reg(rwnx_plat, ®_list); ++ ++ for (i = 0; i < size; i++) { ++ RWNX_REG_WRITE(*reg_value++, rwnx_plat, RWNX_ADDR_SYSTEM, ++ *reg_list++); ++ } ++} ++#endif ++ ++#ifndef CONFIG_RWNX_FHOST ++#if 0 ++static int rwnx_check_fw_compatibility(struct rwnx_hw *rwnx_hw) ++{ ++ struct ipc_shared_env_tag *shared = rwnx_hw->ipc_env->shared; ++ #ifdef CONFIG_RWNX_FULLMAC ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ #endif //CONFIG_RWNX_FULLMAC ++ #ifdef CONFIG_RWNX_OLD_IPC ++ int ipc_shared_version = 10; ++ #else //CONFIG_RWNX_OLD_IPC ++ int ipc_shared_version = 11; ++ #endif //CONFIG_RWNX_OLD_IPC ++ int res = 0; ++ ++ if (shared->comp_info.ipc_shared_version != ipc_shared_version) { ++ wiphy_err(wiphy, "Different versions of IPC shared version between driver and FW (%d != %d)\n ", ++ ipc_shared_version, shared->comp_info.ipc_shared_version); ++ res = -1; ++ } ++ ++ if (shared->comp_info.radarbuf_cnt != IPC_RADARBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for Radar events handling "\ ++ "between driver and FW (%d != %d)\n", IPC_RADARBUF_CNT, ++ shared->comp_info.radarbuf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.unsuprxvecbuf_cnt != IPC_UNSUPRXVECBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for unsupported Rx vectors "\ ++ "handling between driver and FW (%d != %d)\n", IPC_UNSUPRXVECBUF_CNT, ++ shared->comp_info.unsuprxvecbuf_cnt); ++ res = -1; ++ } ++ ++ #ifdef CONFIG_RWNX_FULLMAC ++ if (shared->comp_info.rxdesc_cnt != IPC_RXDESC_CNT) { ++ wiphy_err(wiphy, "Different number of shared descriptors available for Data RX handling "\ ++ "between driver and FW (%d != %d)\n", IPC_RXDESC_CNT, ++ shared->comp_info.rxdesc_cnt); ++ res = -1; ++ } ++ #endif /* CONFIG_RWNX_FULLMAC */ ++ ++ if (shared->comp_info.rxbuf_cnt != IPC_RXBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for Data Rx handling "\ ++ "between driver and FW (%d != %d)\n", IPC_RXBUF_CNT, ++ shared->comp_info.rxbuf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.msge2a_buf_cnt != IPC_MSGE2A_BUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for Emb->App MSGs "\ ++ "sending between driver and FW (%d != %d)\n", IPC_MSGE2A_BUF_CNT, ++ shared->comp_info.msge2a_buf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.dbgbuf_cnt != IPC_DBGBUF_CNT) { ++ wiphy_err(wiphy, "Different number of host buffers available for debug messages "\ ++ "sending between driver and FW (%d != %d)\n", IPC_DBGBUF_CNT, ++ shared->comp_info.dbgbuf_cnt); ++ res = -1; ++ } ++ ++ if (shared->comp_info.bk_txq != NX_TXDESC_CNT0) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of BK TX queue (%d != %d)\n", ++ NX_TXDESC_CNT0, shared->comp_info.bk_txq); ++ res = -1; ++ } ++ ++ if (shared->comp_info.be_txq != NX_TXDESC_CNT1) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of BE TX queue (%d != %d)\n", ++ NX_TXDESC_CNT1, shared->comp_info.be_txq); ++ res = -1; ++ } ++ ++ if (shared->comp_info.vi_txq != NX_TXDESC_CNT2) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of VI TX queue (%d != %d)\n", ++ NX_TXDESC_CNT2, shared->comp_info.vi_txq); ++ res = -1; ++ } ++ ++ if (shared->comp_info.vo_txq != NX_TXDESC_CNT3) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of VO TX queue (%d != %d)\n", ++ NX_TXDESC_CNT3, shared->comp_info.vo_txq); ++ res = -1; ++ } ++ ++ #if NX_TXQ_CNT == 5 ++ if (shared->comp_info.bcn_txq != NX_TXDESC_CNT4) { ++ wiphy_err(wiphy, "Driver and FW have different sizes of BCN TX queue (%d != %d)\n", ++ NX_TXDESC_CNT4, shared->comp_info.bcn_txq); ++ res = -1; ++ } ++ #else ++ if (shared->comp_info.bcn_txq > 0) { ++ wiphy_err(wiphy, "BCMC enabled in firmware but disabled in driver\n"); ++ res = -1; ++ } ++ #endif /* NX_TXQ_CNT == 5 */ ++ ++ if (shared->comp_info.ipc_shared_size != sizeof(ipc_shared_env)) { ++ wiphy_err(wiphy, "Different sizes of IPC shared between driver and FW (%zd != %d)\n", ++ sizeof(ipc_shared_env), shared->comp_info.ipc_shared_size); ++ res = -1; ++ } ++ ++ if (shared->comp_info.msg_api != MSG_API_VER) { ++ wiphy_warn(wiphy, "WARNING: Different supported message API versions between "\ ++ "driver and FW (%d != %d)\n", MSG_API_VER, shared->comp_info.msg_api); ++ } ++ ++ return res; ++} ++#endif ++#endif /* !CONFIG_RWNX_FHOST */ ++ ++ ++void get_userconfig_txpwr_lvl_in_fdrv(txpwr_lvl_conf_t *txpwr_lvl) ++{ ++ txpwr_lvl->enable = userconfig_info.txpwr_lvl.enable; ++ txpwr_lvl->dsss = userconfig_info.txpwr_lvl.dsss; ++ txpwr_lvl->ofdmlowrate_2g4 = userconfig_info.txpwr_lvl.ofdmlowrate_2g4; ++ txpwr_lvl->ofdm64qam_2g4 = userconfig_info.txpwr_lvl.ofdm64qam_2g4; ++ txpwr_lvl->ofdm256qam_2g4 = userconfig_info.txpwr_lvl.ofdm256qam_2g4; ++ txpwr_lvl->ofdm1024qam_2g4 = userconfig_info.txpwr_lvl.ofdm1024qam_2g4; ++ txpwr_lvl->ofdmlowrate_5g = userconfig_info.txpwr_lvl.ofdmlowrate_5g; ++ txpwr_lvl->ofdm64qam_5g = userconfig_info.txpwr_lvl.ofdm64qam_5g; ++ txpwr_lvl->ofdm256qam_5g = userconfig_info.txpwr_lvl.ofdm256qam_5g; ++ txpwr_lvl->ofdm1024qam_5g = userconfig_info.txpwr_lvl.ofdm1024qam_5g; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl->enable); ++ AICWFDBG(LOGINFO, "%s:dsss:%d\r\n", __func__, txpwr_lvl->dsss); ++ AICWFDBG(LOGINFO, "%s:ofdmlowrate_2g4:%d\r\n", __func__, txpwr_lvl->ofdmlowrate_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdm64qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm64qam_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdm256qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm256qam_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdm1024qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm1024qam_2g4); ++ AICWFDBG(LOGINFO, "%s:ofdmlowrate_5g:%d\r\n", __func__, txpwr_lvl->ofdmlowrate_5g); ++ AICWFDBG(LOGINFO, "%s:ofdm64qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm64qam_5g); ++ AICWFDBG(LOGINFO, "%s:ofdm256qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm256qam_5g); ++ AICWFDBG(LOGINFO, "%s:ofdm1024qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm1024qam_5g); ++} ++ ++void get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_conf_v2_t *txpwr_lvl_v2) ++{ ++ *txpwr_lvl_v2 = userconfig_info.txpwr_lvl_v2; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v2->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[11]); ++} ++ ++void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3) ++{ ++ *txpwr_lvl_v3 = userconfig_info.txpwr_lvl_v3; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v3->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_1m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_2m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_5m5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_11m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[11]); ++} ++ ++void get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_conf_v4_t *txpwr_lvl_v4) ++{ ++ *txpwr_lvl_v4 = userconfig_info.txpwr_lvl_v4; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v4->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11b_11ag_2g4[11]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v4->pwrlvl_11n_11ac_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_2g4[11]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11a_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11n_11ac_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[5]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[6]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[7]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[8]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[9]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[10]); ++ AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v4->pwrlvl_11ax_5g[11]); ++} ++ ++void get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj) ++{ ++ *txpwr_lvl_adj = userconfig_info.txpwr_lvl_adj; ++ ++ AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_adj->enable); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_1_4:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_5_9:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_10_13:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[2]); ++ ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_42:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[0]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_58:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[1]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_106:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[2]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_122:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[3]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_138:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[4]); ++ AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_155:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[5]); ++} ++ ++#ifdef CONFIG_POWER_LIMIT ++#define GetLineFromBuffer(buffer) strsep(&buffer, "\n") ++ ++int isAllSpaceOrTab(uint8_t *data, uint8_t size) ++{ ++ uint8_t cnt = 0, NumOfSpaceAndTab = 0; ++ while (size > cnt) { ++ if (data[cnt] == ' ' || data[cnt] == '\t' || data[cnt] == '\0') ++ ++NumOfSpaceAndTab; ++ ++cnt; ++ } ++ return size == NumOfSpaceAndTab; ++} ++ ++int IsCommentString(char *szStr) ++{ ++ if (*szStr == '#' && *(szStr + 1) == ' ') ++ return 1; ++ else ++ return 0; ++} ++ ++int ParseQualifiedString(char *In, u32 *Start, char *Out, char LeftQualifier, char RightQualifier) ++{ ++ u32 i = 0, j = 0; ++ char c = In[(*Start)++]; ++ if (c != LeftQualifier) ++ return 0; ++ i = (*Start); ++ c = In[(*Start)++]; ++ while (c != RightQualifier && c != '\0') ++ c = In[(*Start)++]; ++ if (c == '\0') ++ return 0; ++ j = (*Start) - 2; ++ strncpy((char *)Out, (const char *)(In + i), j - i + 1); ++ return 1; ++} ++ ++int GetU1ByteIntegerFromStringInDecimal(char *Str, u8 *pInt) ++{ ++ u16 i = 0; ++ *pInt = 0; ++ while (Str[i] != '\0') { ++ if (Str[i] >= '0' && Str[i] <= '9') { ++ *pInt *= 10; ++ *pInt += (Str[i] - '0'); ++ } else ++ return 0; ++ ++i; ++ } ++ return 1; ++} ++int GetS1ByteIntegerFromStringInDecimal(char *str, s8 *val) ++{ ++ u8 negative = 0; ++ u16 i = 0; ++ *val = 0; ++ while (str[i] != '\0') { ++ if (i == 0 && (str[i] == '+' || str[i] == '-')) { ++ if (str[i] == '-') ++ negative = 1; ++ } else if (str[i] >= '0' && str[i] <= '9') { ++ *val *= 10; ++ *val += (str[i] - '0'); ++ } else ++ return 0; ++ ++i; ++ } ++ if (negative) ++ *val = -*val; ++ return 1; ++} ++ ++int8_t rwnx_plat_powerlimit_save(u8_l band, char *channel, u8_l bw, char *limit, char *name) ++{ ++ u8 channel_num, powerLimit_val, reg_idx; ++ ++ if (GetU1ByteIntegerFromStringInDecimal((char *)channel, &channel_num) == 0 ++ || GetS1ByteIntegerFromStringInDecimal((char *)limit, &powerLimit_val) == 0) { ++ AICWFDBG(LOGERROR, "Illegal index of power limit table [ch %s][val %s]\n", channel, limit); ++ return -1; ++ } ++ ++ reg_idx = get_region_index(name); ++ ++ if (band == PHY_BAND_2G4) { ++ uint8_t cur_idx = powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_2g4[bw]; ++ AICWFDBG(LOGINFO, "reg_idx=%d, band=%d, bw=%d, cur_idx=%d, ch=%s, pwr=%s\n", ++ reg_idx, band, bw, cur_idx, channel, limit); ++ if (cur_idx < MAC_DOMAINCHANNEL_24G_MAX) { ++ powerlimit_info.txpwr_lmt[reg_idx].ch_num_2g4[bw][cur_idx] = channel_num; ++ powerlimit_info.txpwr_lmt[reg_idx].max_pwr_2g4[bw][cur_idx] = powerLimit_val; ++ powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_2g4[bw]++; ++ } else { ++ AICWFDBG(LOGERROR, "band %d chan_cnt reached %d\n", band, MAC_DOMAINCHANNEL_24G_MAX); ++ AICWFDBG(LOGERROR, "channel=%s(%d) powerLimit=%s(%d)\n", channel, channel_num, limit, powerLimit_val); ++ } ++ } else if (band == PHY_BAND_5G) { ++ uint8_t cur_idx = powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_5g[bw]; ++ AICWFDBG(LOGINFO, "reg_idx=%d, band=%d, bw=%d, cur_idx=%d, ch=%s, pwr=%s\n", ++ reg_idx, band, bw, cur_idx, channel, limit); ++ if (cur_idx < MAC_DOMAINCHANNEL_5G_MAX) { ++ powerlimit_info.txpwr_lmt[reg_idx].ch_num_5g[bw][cur_idx] = channel_num; ++ powerlimit_info.txpwr_lmt[reg_idx].max_pwr_5g[bw][cur_idx] = powerLimit_val; ++ powerlimit_info.txpwr_lmt[reg_idx].ch_cnt_5g[bw]++; ++ } else { ++ AICWFDBG(LOGERROR, "band %d chan_cnt reached %d\n", band, MAC_DOMAINCHANNEL_5G_MAX); ++ AICWFDBG(LOGERROR, "channel=%s(%d) powerLimit=%s(%d)\n", channel, channel_num, limit, powerLimit_val); ++ } ++ } ++ ++ return 0; ++} ++ ++ ++void rwnx_plat_powerlimit_parsing(char *buffer, int size, char *cc) ++{ ++#define LD_STAGE_EXC_MAPPING 0 ++#define LD_STAGE_TAB_DEFINE 1 ++#define LD_STAGE_TAB_START 2 ++#define LD_STAGE_COLUMN_DEFINE 3 ++#define LD_STAGE_CH_ROW 4 ++ ++ uint8_t loadingStage = LD_STAGE_EXC_MAPPING; ++ uint32_t i = 0, forCnt = 0; ++ uint32_t i_cc; ++ char *szLine, *ptmp; ++ char band[10], colNumBuf[10], bandwidth[10]; ++ uint8_t colNum = 0, band_cc = 0, bw_cc = 0; ++ char **reg_name = NULL; ++ // clear powerlimit info at first ++ memset((void *)&powerlimit_info, 0, sizeof(powerlimit_info_t)); ++ ptmp = buffer; ++ for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { ++ if (isAllSpaceOrTab(szLine, sizeof(*szLine))) ++ continue; ++ if (IsCommentString(szLine)) ++ continue; ++ ++ if (loadingStage == LD_STAGE_EXC_MAPPING) { ++ if (szLine[0] == '#' || szLine[1] == '#') { ++ loadingStage = LD_STAGE_TAB_DEFINE; ++ } else { ++ continue; ++ } ++ } ++ ++ if (loadingStage == LD_STAGE_TAB_DEFINE) { ++ /* read "## 2.4G" */ ++ if (szLine[0] != '#' || szLine[1] != '#') ++ continue; ++ ++ /* skip the space */ ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ szLine[--i] = ' '; /* return the space in front of the regulation info */ ++ ++ /* Parse the label of the table */ ++ memset((void *)band, 0, 10); ++ memset((void *)bandwidth, 0, 10); ++ memset((void *)colNumBuf, 0, 10); ++ ++ if (!ParseQualifiedString(szLine, &i, band, ' ', ',')) { ++ AICWFDBG(LOGERROR, "Fail to parse band!\n"); ++ goto exit; ++ } ++ if (strncmp(band, "2.4G", 4) == 0) { ++ band_cc = PHY_BAND_2G4; ++ } else if (strncmp(band, "5G", 2) == 0) { ++ band_cc = PHY_BAND_5G; ++ } ++ ++ if (!ParseQualifiedString(szLine, &i, bandwidth, ' ', ',')) { ++ AICWFDBG(LOGERROR, "Fail to parse bandwidth!\n"); ++ goto exit; ++ } ++ if (strncmp(bandwidth, "20M", 3) == 0) ++ bw_cc = PHY_CHNL_BW_20; ++ else if (strncmp(bandwidth, "40M", 3) == 0) ++ bw_cc = PHY_CHNL_BW_40; ++ else if (strncmp(bandwidth, "80M", 3) == 0) ++ bw_cc = PHY_CHNL_BW_80; ++ ++ if (!ParseQualifiedString(szLine, &i, colNumBuf, '#', '#')) { ++ AICWFDBG(LOGERROR, "Fail to parse column number!\n"); ++ goto exit; ++ } ++ if (!GetU1ByteIntegerFromStringInDecimal(colNumBuf, &colNum)) { ++ AICWFDBG(LOGERROR, "Column number \"%s\" is not unsigned decimal\n", colNumBuf); ++ goto exit; ++ } ++ if (colNum == 0) { ++ AICWFDBG(LOGERROR, "Column number is 0\n"); ++ goto exit; ++ } ++ ++ AICWFDBG(LOGINFO, "band=%s, bandwidth=%s, colnum=%d\n", band, bandwidth, colNum); ++ loadingStage = LD_STAGE_TAB_START; ++ } else if (loadingStage == LD_STAGE_TAB_START) { ++ /* read "## START" */ ++ if (szLine[0] != '#' || szLine[1] != '#') ++ continue; ++ ++ /* skip the space */ ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ if (strncmp((u8 *)(szLine + i), "START", 5)) { ++ AICWFDBG(LOGERROR, "Missing \"## START\" label\n"); ++ goto exit; ++ } ++ ++ loadingStage = LD_STAGE_COLUMN_DEFINE; ++ } else if (loadingStage == LD_STAGE_COLUMN_DEFINE) { ++ /* read "## FCC ETSI" */ ++ if (szLine[0] != '#' || szLine[1] != '#') ++ continue; ++ ++ /* skip the space */ ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ reg_name = (char **)kmalloc(sizeof(char *) * colNum, GFP_KERNEL); ++ if (!reg_name) { ++ AICWFDBG(LOGERROR, "reg_name alloc fail\n"); ++ goto exit; ++ } ++ ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ /* skip the space */ ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ i++; ++ i_cc = i; ++ ++ while (szLine[i] != ' ' && szLine[i] != '\t' && szLine[i] != '\0') ++ i++; ++ ++ reg_name[forCnt] = (char *)kmalloc(i - i_cc + 1, GFP_KERNEL); ++ if (!reg_name[forCnt]) { ++ AICWFDBG(LOGERROR, "reg_name element alloc fail\n"); ++ goto exit; ++ } ++ ++ strncpy(reg_name[forCnt], szLine + i_cc, i - i_cc); ++ reg_name[forCnt][i - i_cc] = '\0'; ++ AICWFDBG(LOGINFO, "reg_name: %s\n", reg_name[forCnt]); ++ ++ } ++ ++ loadingStage = LD_STAGE_CH_ROW; ++ } else if (loadingStage == LD_STAGE_CH_ROW) { ++ char channel[10] = {0}, powerLimit[10] = {0}; ++ u8 cnt = 0; ++ ++ /* the table ends */ ++ if (szLine[0] == '#' && szLine[1] == '#') { ++ i = 2; ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ if (strncmp((u8 *)(szLine + i), "END", 3) == 0) { ++ loadingStage = LD_STAGE_TAB_DEFINE; ++ if (reg_name) { ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ if (reg_name[forCnt]) { ++ kfree(reg_name[forCnt]); ++ reg_name[forCnt] = NULL; ++ } ++ } ++ kfree(reg_name); ++ reg_name = NULL; ++ } ++ colNum = 0; ++ continue; ++ } else { ++ AICWFDBG(LOGERROR, "Missing \"## END\" label\n"); ++ goto exit; ++ } ++ } ++ ++ if ((szLine[0] != 'c' && szLine[0] != 'C') || ++ (szLine[1] != 'h' && szLine[1] != 'H')) { ++ AICWFDBG(LOGERROR, "Wrong channel prefix: '%c','%c'(%d,%d)\n", szLine[0], szLine[1], szLine[0], szLine[1]); ++ continue; ++ } ++ i = 2;/* move to the location behind 'h' */ ++ ++ /* load the channel number */ ++ cnt = 0; ++ while (szLine[i] >= '0' && szLine[i] <= '9') { ++ channel[cnt] = szLine[i]; ++ ++cnt; ++ ++i; ++ } ++ ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ /* skip the space between channel number and the power limit value */ ++ while (szLine[i] == ' ' || szLine[i] == '\t') ++ ++i; ++ ++ /* load the power limit value */ ++ memset((void *)powerLimit, 0, 10); ++ ++ if (szLine[i] == 'N' && szLine[i + 1] == 'A') { ++ /* ++ * means channel not available ++ */ ++ sprintf(powerLimit, "%d", POWER_LIMIT_INVALID_VAL); ++ i += 2; ++ } else if ((szLine[i] >= '0' && szLine[i] <= '9') ++ || szLine[i] == '+' || szLine[i] == '-') { ++ /* case of dBm value */ ++ cnt = 0; ++ while ((szLine[i] >= '0' && szLine[i] <= '9') ++ || szLine[i] == '+' || szLine[i] == '-' ++ ) { ++ powerLimit[cnt] = szLine[i]; ++ ++cnt; ++ ++i; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "Wrong limit expression \"%c%c\"(%d, %d)\n", ++ szLine[i], szLine[i + 1], szLine[i], szLine[i + 1]); ++ goto exit; ++ } ++ ++ if (rwnx_plat_powerlimit_save(band_cc, channel, bw_cc, powerLimit, reg_name[forCnt]) < 0) ++ goto exit; ++ } ++ } ++ } ++ ++ powerlimit_info.flags |= POWER_LIMIT_CC_MATCHED_BIT; ++exit: ++ if (reg_name) { ++ for (forCnt = 0; forCnt < colNum; ++forCnt) { ++ if (reg_name[forCnt]) { ++ kfree(reg_name[forCnt]); ++ reg_name[forCnt] = NULL; ++ } ++ } ++ kfree(reg_name); ++ reg_name = NULL; ++ } ++ ++ return; ++} ++ ++ ++/// 5G lower bound freq ++#define PHY_FREQ_5G 5000 ++ ++uint16_t phy_channel_to_freq(uint8_t band, int channel) ++{ ++ if ((band == PHY_BAND_2G4) && (channel >= 1) && (channel <= 14)) { ++ if (channel == 14) ++ return 2484; ++ else ++ return 2407 + channel * 5; ++ } else if ((band == PHY_BAND_5G) && (channel >= 1) && (channel <= 165)) { ++ return PHY_FREQ_5G + channel * 5; ++ } ++ return 0; ++} ++ ++int8_t get_powerlimit_by_freq(uint8_t band, uint16_t freq, uint8_t r_idx) ++{ ++ int8_t ret = POWER_LIMIT_INVALID_VAL; ++ uint8_t idx; ++ if (!(powerlimit_info.flags & POWER_LIMIT_CC_MATCHED_BIT)) { ++ AICWFDBG(LOGERROR, "powerlimit flag not set\n"); ++ return ret; ++ } ++ ++ if (band == PHY_BAND_2G4) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_2g4[0]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ int ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_2g4[0][idx]; ++ uint16_t freq_tmp = phy_channel_to_freq(PHY_BAND_2G4, ch_num); ++ if (freq == freq_tmp) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_2g4[0][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d(freq=%d), pwr=%d\n", idx, ch_num, freq, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "powerlimit search failed: band=%d freq=%d\n", band, freq); ++ } else if (band == PHY_BAND_5G) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_5g[0]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ int ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_5g[0][idx]; ++ uint16_t freq_tmp = phy_channel_to_freq(PHY_BAND_5G, ch_num); ++ if (freq == freq_tmp) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_5g[0][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d(freq=%d), pwr=%d\n", idx, ch_num, freq, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "powerlimit search failed: band=%d freq=%d\n", band, freq); ++ } ++ return ret; ++} ++ ++int8_t get_powerlimit_by_chnum(uint8_t chnum, uint8_t r_idx, uint8_t bw) ++{ ++ int8_t ret = POWER_LIMIT_INVALID_VAL; ++ uint8_t idx; ++ if (!(powerlimit_info.flags & POWER_LIMIT_CC_MATCHED_BIT)) { ++ AICWFDBG(LOGERROR, "powerlimit flag not set\n"); ++ return ret; ++ } ++ ++ if (chnum <= 14) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_2g4[bw]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ uint8_t ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_2g4[bw][idx]; ++ if (chnum == ch_num) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_2g4[bw][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d, pwr=%d\n", idx, ch_num, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "%s powerlimit search failed: chnum=%d, please confirm the center frequency\n", ++ __func__, chnum); ++ } else if (chnum <= 165) { ++ uint8_t idx_cnt = powerlimit_info.txpwr_lmt[r_idx].ch_cnt_5g[bw]; ++ for (idx = 0; idx < idx_cnt; idx++) { ++ uint8_t ch_num = powerlimit_info.txpwr_lmt[r_idx].ch_num_5g[bw][idx]; ++ if (chnum == ch_num) { ++ ret = powerlimit_info.txpwr_lmt[r_idx].max_pwr_5g[bw][idx]; ++ AICWFDBG(LOGINFO, "[%d]: ch=%d, pwr=%d\n", idx, ch_num, ret); ++ break; ++ } ++ } ++ if (idx == idx_cnt) ++ AICWFDBG(LOGERROR, "%s powerlimit search failed: chnum=%d, please confirm the center frequency\n", ++ __func__, chnum); ++ } ++ ++ return ret; ++} ++#endif ++ ++/** ++ * rwnx_plat_userconfig_load ---Load aic_userconfig.txt ++ *@filename name of config ++*/ ++static int rwnx_plat_userconfig_load(struct rwnx_hw *rwnx_hw) { ++ ++ if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ ++ ++ rwnx_plat_userconfig_upload_android(rwnx_hw, aic_fw_path, FW_USERCONFIG_NAME); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC){ ++ rwnx_plat_userconfig_load_8800dc(rwnx_hw); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ ++ rwnx_plat_userconfig_load_8800dw(rwnx_hw); ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ rwnx_plat_userconfig_load_8800d80(rwnx_hw); ++#ifdef CONFIG_POWER_LIMIT ++ rwnx_plat_powerlimit_load_8800d80(rwnx_hw); ++#endif ++ }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80X2){ ++ rwnx_plat_userconfig_load_8800d80x2(rwnx_hw); ++#ifdef CONFIG_POWER_LIMIT ++ rwnx_plat_powerlimit_load_8800d80x2(rwnx_hw); ++#endif ++ } ++ return 0; ++} ++ ++void get_userconfig_txpwr_loss(txpwr_loss_conf_t *txpwr_loss) ++{ ++ txpwr_loss->loss_enable_2g4 = userconfig_info.txpwr_loss.loss_enable_2g4; ++ txpwr_loss->loss_value_2g4 = userconfig_info.txpwr_loss.loss_value_2g4; ++ txpwr_loss->loss_enable_5g = userconfig_info.txpwr_loss.loss_enable_5g; ++ txpwr_loss->loss_value_5g = userconfig_info.txpwr_loss.loss_value_5g; ++ ++ AICWFDBG(LOGDEBUG, "%s:loss_enable_2g4: %d, val_2g4: %d, loss_enable_5g: %d, val_5g: %d\r\n", __func__, ++ txpwr_loss->loss_enable_2g4, txpwr_loss->loss_value_2g4, ++ txpwr_loss->loss_enable_5g, txpwr_loss->loss_value_5g); ++ ++} ++ ++/** ++ * rwnx_platform_on() - Start the platform ++ * ++ * @rwnx_hw: Main driver data ++ * @config: Config to restore (NULL if nothing to restore) ++ * ++ * It starts the platform : ++ * - load fw and ucodes ++ * - initialize IPC ++ * - boot the fw ++ * - enable link communication/IRQ ++ * ++ * Called by 802.11 part ++ */ ++int rwnx_platform_on(struct rwnx_hw *rwnx_hw, void *config) ++{ ++ int ret; ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ (void)ret; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (rwnx_plat->enabled) ++ return 0; ++ ++ #ifndef CONFIG_ROM_PATCH_EN ++ #ifdef CONFIG_DOWNLOAD_FW ++ ret = rwnx_plat_fmac_load(rwnx_hw, (char*)config); ++ if (ret) ++ return ret; ++ #endif /* !CONFIG_ROM_PATCH_EN */ ++ #endif ++ ++#if 0 ++ ret = rwnx_plat_patch_load(rwnx_hw); ++ if (ret) { ++ return ret; ++ } ++#endif ++ ++ ++ rwnx_plat_userconfig_load(rwnx_hw); ++ ++ //rwnx_plat->enabled = true; ++ ++ return 0; ++} ++ ++/** ++ * rwnx_platform_off() - Stop the platform ++ * ++ * @rwnx_hw: Main driver data ++ * @config: Updated with pointer to config, to be able to restore it with ++ * rwnx_platform_on(). It's up to the caller to free the config. Set to NULL ++ * if configuration is not needed. ++ * ++ * Called by 802.11 part ++ */ ++void rwnx_platform_off(struct rwnx_hw *rwnx_hw, void **config) ++{ ++#if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) ++ tasklet_kill(&rwnx_hw->task); ++ rwnx_hw->plat->enabled = false; ++ return ; ++#endif ++ ++ if (!rwnx_hw->plat->enabled) { ++ if (config) ++ *config = NULL; ++ return; ++ } ++ ++ if (config) ++ *config = rwnx_term_save_config(rwnx_hw->plat); ++ ++ rwnx_hw->plat->disable(rwnx_hw); ++ ++ tasklet_kill(&rwnx_hw->task); ++ rwnx_platform_reset(rwnx_hw->plat); ++ ++ rwnx_hw->plat->enabled = false; ++} ++ ++/** ++ * rwnx_platform_init() - Initialize the platform ++ * ++ * @rwnx_plat: platform data (already updated by platform driver) ++ * @platform_data: Pointer to store the main driver data pointer (aka rwnx_hw) ++ * That will be set as driver data for the platform driver ++ * Return: 0 on success, < 0 otherwise ++ * ++ * Called by the platform driver after it has been probed ++ */ ++int rwnx_platform_init(struct rwnx_plat *rwnx_plat, void **platform_data) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ rwnx_plat->enabled = false; ++ g_rwnx_plat = rwnx_plat; ++ ++#if defined CONFIG_RWNX_FULLMAC ++ return rwnx_cfg80211_init(rwnx_plat, platform_data); ++#elif defined CONFIG_RWNX_FHOST ++ return rwnx_fhost_init(rwnx_plat, platform_data); ++#endif ++} ++ ++/** ++ * rwnx_platform_deinit() - Deinitialize the platform ++ * ++ * @rwnx_hw: main driver data ++ * ++ * Called by the platform driver after it is removed ++ */ ++void rwnx_platform_deinit(struct rwnx_hw *rwnx_hw) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++#if defined CONFIG_RWNX_FULLMAC ++ rwnx_cfg80211_deinit(rwnx_hw); ++#elif defined CONFIG_RWNX_FHOST ++ rwnx_fhost_deinit(rwnx_hw); ++#endif ++} ++ ++/** ++ * rwnx_platform_register_drv() - Register all possible platform drivers ++ */ ++int rwnx_platform_register_drv(void) ++{ ++ return rwnx_pci_register_drv(); ++} ++ ++ ++/** ++ * rwnx_platform_unregister_drv() - Unegister all platform drivers ++ */ ++void rwnx_platform_unregister_drv(void) ++{ ++ return rwnx_pci_unregister_drv(); ++} ++ ++struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat) ++{ ++#ifdef AICWF_SDIO_SUPPORT ++ return rwnx_plat->sdiodev->dev; ++#endif ++#ifdef AICWF_USB_SUPPORT ++ return rwnx_plat->usbdev->dev; ++#endif ++ return &(rwnx_plat->pci_dev->dev); ++} ++ ++ ++#ifndef CONFIG_RWNX_SDM ++MODULE_FIRMWARE(RWNX_AGC_FW_NAME); ++MODULE_FIRMWARE(RWNX_FCU_FW_NAME); ++MODULE_FIRMWARE(RWNX_LDPC_RAM_NAME); ++#endif ++MODULE_FIRMWARE(RWNX_MAC_FW_NAME); ++#ifndef CONFIG_RWNX_TL4 ++MODULE_FIRMWARE(RWNX_MAC_FW_NAME2); ++#endif ++ ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h +new file mode 100644 +index 000000000000..1ce300dbfed5 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h +@@ -0,0 +1,159 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_platorm.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_PLATFORM_H_ ++#define _RWNX_PLATFORM_H_ ++ ++#include ++#include "lmac_msg.h" ++ ++#define RWNX_CONFIG_FW_NAME "rwnx_settings.ini" ++#define RWNX_PHY_CONFIG_TRD_NAME "rwnx_trident.ini" ++#define RWNX_PHY_CONFIG_KARST_NAME "rwnx_karst.ini" ++#define RWNX_AGC_FW_NAME "agcram.bin" ++#define RWNX_LDPC_RAM_NAME "ldpcram.bin" ++#ifdef CONFIG_RWNX_FULLMAC ++#define RWNX_MAC_FW_BASE_NAME "fmacfw" ++#elif defined CONFIG_RWNX_FHOST ++#define RWNX_MAC_FW_BASE_NAME "fhostfw" ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#ifdef CONFIG_RWNX_TL4 ++#define RWNX_MAC_FW_NAME RWNX_MAC_FW_BASE_NAME".hex" ++#else ++#define RWNX_MAC_FW_NAME RWNX_MAC_FW_BASE_NAME".ihex" ++#define RWNX_MAC_FW_NAME2 RWNX_MAC_FW_BASE_NAME".bin" ++#endif ++ ++#define RWNX_FCU_FW_NAME "fcuram.bin" ++#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB)) ++#define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_lite_8800dc.bin" ++#endif ++ ++/** ++ * Type of memory to access (cf rwnx_plat.get_address) ++ * ++ * @RWNX_ADDR_CPU To access memory of the embedded CPU ++ * @RWNX_ADDR_SYSTEM To access memory/registers of one subsystem of the ++ * embedded system ++ * ++ */ ++enum rwnx_platform_addr { ++ RWNX_ADDR_CPU, ++ RWNX_ADDR_SYSTEM, ++ RWNX_ADDR_MAX, ++}; ++ ++#define POWER_LEVEL_INVALID_VAL (127) ++ ++typedef enum { ++ REGIONS_SRRC, ++ REGIONS_FCC, ++ REGIONS_ETSI, ++ REGIONS_JP, ++ REGIONS_DEFAULT, ++} Regions_code; ++ ++struct rwnx_hw; ++ ++/** ++ * struct rwnx_plat - Operation pointers for RWNX PCI platform ++ * ++ * @pci_dev: pointer to pci dev ++ * @enabled: Set if embedded platform has been enabled (i.e. fw loaded and ++ * ipc started) ++ * @enable: Configure communication with the fw (i.e. configure the transfers ++ * enable and register interrupt) ++ * @disable: Stop communication with the fw ++ * @deinit: Free all ressources allocated for the embedded platform ++ * @get_address: Return the virtual address to access the requested address on ++ * the platform. ++ * @ack_irq: Acknowledge the irq at link level. ++ * @get_config_reg: Return the list (size + pointer) of registers to restore in ++ * order to reload the platform while keeping the current configuration. ++ * ++ * @priv Private data for the link driver ++ */ ++struct rwnx_plat { ++ struct pci_dev *pci_dev; ++ ++#ifdef AICWF_SDIO_SUPPORT ++ struct aic_sdio_dev *sdiodev; ++#endif ++ ++#ifdef AICWF_USB_SUPPORT ++ struct aic_usb_dev *usbdev; ++#endif ++ bool enabled; ++ ++ int (*enable)(struct rwnx_hw *rwnx_hw); ++ int (*disable)(struct rwnx_hw *rwnx_hw); ++ void (*deinit)(struct rwnx_plat *rwnx_plat); ++ u8* (*get_address)(struct rwnx_plat *rwnx_plat, int addr_name, ++ unsigned int offset); ++ void (*ack_irq)(struct rwnx_plat *rwnx_plat); ++ int (*get_config_reg)(struct rwnx_plat *rwnx_plat, const u32 **list); ++ ++ u8 priv[0] __aligned(sizeof(void *)); ++}; ++ ++#define RWNX_ADDR(plat, base, offset) \ ++ plat->get_address(plat, base, offset) ++ ++#define RWNX_REG_READ(plat, base, offset) \ ++ readl(plat->get_address(plat, base, offset)) ++ ++#define RWNX_REG_WRITE(val, plat, base, offset) \ ++ writel(val, plat->get_address(plat, base, offset)) ++ ++extern struct rwnx_plat *g_rwnx_plat; ++ ++int rwnx_platform_init(struct rwnx_plat *rwnx_plat, void **platform_data); ++void rwnx_platform_deinit(struct rwnx_hw *rwnx_hw); ++ ++int rwnx_platform_on(struct rwnx_hw *rwnx_hw, void *config); ++void rwnx_platform_off(struct rwnx_hw *rwnx_hw, void **config); ++ ++int rwnx_platform_register_drv(void); ++void rwnx_platform_unregister_drv(void); ++ ++void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx); ++void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst); ++void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap); ++s8_l get_txpwr_max(s8_l power); ++void set_txpwr_loss_ofst(s8_l value); ++ ++void get_userconfig_txpwr_lvl_in_fdrv(txpwr_lvl_conf_t *txpwr_lvl); ++void get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_conf_v2_t *txpwr_lvl_v2); ++void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3); ++void get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_conf_v4_t *txpwr_lvl_v4); ++void get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj); ++uint8_t get_ccode_region(char * ccode); ++u8 get_region_index(char * name); ++ ++#ifdef CONFIG_POWER_LIMIT ++int8_t rwnx_plat_powerlimit_save(u8_l band, char *channel, u8_l bw, char *limit, char *name); ++void rwnx_plat_powerlimit_parsing(char *buffer, int size, char *cc); ++int8_t get_powerlimit_by_freq(uint8_t band, uint16_t freq, uint8_t r_idx); ++int8_t get_powerlimit_by_chnum(uint8_t chnum, uint8_t r_idx, uint8_t bw); ++#endif ++ ++void get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst_conf_t *txpwr_ofst); ++void get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x_conf_t *txpwr_ofst2x); ++void get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2); ++void get_userconfig_txpwr_loss(txpwr_loss_conf_t *txpwr_loss); ++extern struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat); ++ ++static inline unsigned int rwnx_platform_get_irq(struct rwnx_plat *rwnx_plat) ++{ ++ return rwnx_plat->pci_dev->irq; ++} ++ ++#endif /* _RWNX_PLATFORM_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h +new file mode 100644 +index 000000000000..5442f588212f +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h +@@ -0,0 +1,133 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_prof.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_PROF_H_ ++#define _RWNX_PROF_H_ ++ ++#include "reg_access.h" ++#include "rwnx_platform.h" ++ ++static inline void rwnx_prof_set(struct rwnx_hw *rwnx_hw, int val) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_SET_PROFILING_ADDR); ++} ++ ++static inline void rwnx_prof_clear(struct rwnx_hw *rwnx_hw, int val) ++{ ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_CLEAR_PROFILING_ADDR); ++} ++ ++#if 0 ++/* Defines for SW Profiling registers values */ ++enum { ++ TX_IPC_IRQ, ++ TX_IPC_EVT, ++ TX_PREP_EVT, ++ TX_DMA_IRQ, ++ TX_MAC_IRQ, ++ TX_PAYL_HDL, ++ TX_CFM_EVT, ++ TX_IPC_CFM, ++ RX_MAC_IRQ, // 8 ++ RX_TRIGGER_EVT, ++ RX_DMA_IRQ, ++ RX_DMA_EVT, ++ RX_IPC_IND, ++ RX_MPDU_XFER, ++ DBG_PROF_MAX ++}; ++#endif ++ ++enum { ++ SW_PROF_HOSTBUF_IDX = 12, ++ /****** IPC IRQs related signals ******/ ++ /* E2A direction */ ++ SW_PROF_IRQ_E2A_RXDESC = 16, // to make sure we let 16 bits available for LMAC FW ++ SW_PROF_IRQ_E2A_TXCFM, ++ SW_PROF_IRQ_E2A_DBG, ++ SW_PROF_IRQ_E2A_MSG, ++ SW_PROF_IPC_MSGPUSH, ++ SW_PROF_MSGALLOC, ++ SW_PROF_MSGIND, ++ SW_PROF_DBGIND, ++ ++ /* A2E direction */ ++ SW_PROF_IRQ_A2E_TXCFM_BACK, ++ ++ /****** Driver functions related signals ******/ ++ SW_PROF_WAIT_QUEUE_STOP, ++ SW_PROF_WAIT_QUEUE_WAKEUP, ++ SW_PROF_RWNXDATAIND, ++ SW_PROF_RWNX_IPC_IRQ_HDLR, ++ SW_PROF_RWNX_IPC_THR_IRQ_HDLR, ++ SW_PROF_IEEE80211RX, ++ SW_PROF_RWNX_PATTERN, ++ SW_PROF_MAX ++}; ++ ++// [LT]For debug purpose only ++#if (0) ++#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (21) ++#define SW_PROF_CHAN_CTXT_CFM_BIT (22) ++#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (23) ++#define SW_PROF_CHAN_CTXT_PUSH_BIT (24) ++#define SW_PROF_CHAN_CTXT_QUEUE_BIT (25) ++#define SW_PROF_CHAN_CTXT_TX_BIT (26) ++#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (27) ++#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (28) ++#define SW_PROF_CHAN_CTXT_SWTCH_BIT (29) ++ ++// TO DO: update this ++ ++#define REG_SW_SET_PROFILING_CHAN(env, bit) \ ++ rwnx_prof_set((struct rwnx_hw *)env, BIT(bit)) ++ ++#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) \ ++ rwnx_prof_clear((struct rwnx_hw *)env, BIT(bit)) ++ ++#else ++#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (0) ++#define SW_PROF_CHAN_CTXT_CFM_BIT (0) ++#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (0) ++#define SW_PROF_CHAN_CTXT_PUSH_BIT (0) ++#define SW_PROF_CHAN_CTXT_QUEUE_BIT (0) ++#define SW_PROF_CHAN_CTXT_TX_BIT (0) ++#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (0) ++#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (0) ++#define SW_PROF_CHAN_CTXT_SWTCH_BIT (0) ++ ++#define REG_SW_SET_PROFILING_CHAN(env, bit) do {} while (0) ++#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) do {} while (0) ++#endif ++ ++#ifdef CONFIG_RWNX_SW_PROFILING ++/* Macros for SW PRofiling registers access */ ++#define REG_SW_SET_PROFILING(env, bit) \ ++ rwnx_prof_set((struct rwnx_hw *)env, BIT(bit)) ++ ++#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) \ ++ rwnx_prof_set((struct rwnx_hw *)env, val << (SW_PROF_HOSTBUF_IDX)) ++ ++#define REG_SW_CLEAR_PROFILING(env, bit) \ ++ rwnx_prof_clear((struct rwnx_hw *)env, BIT(bit)) ++ ++#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) \ ++ rwnx_prof_clear((struct rwnx_hw *)env, 0x0F << (SW_PROF_HOSTBUF_IDX)) ++ ++#else ++#define REG_SW_SET_PROFILING(env, value) do {} while (0) ++#define REG_SW_CLEAR_PROFILING(env, value) do {} while (0) ++#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) do {} while (0) ++#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) do {} while (0) ++#endif ++ ++#endif /* _RWNX_PROF_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c +new file mode 100644 +index 000000000000..5017fd36f3bf +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c +@@ -0,0 +1,1657 @@ ++/** ++****************************************************************************** ++ * ++ * @file rwnx_radar.c ++ * ++ * @brief Functions to handle radar detection ++ * Radar detection is copied (and adapted) from ath driver source code. ++ * ++ * Copyright (c) 2012 Neratec Solutions AG ++ * Copyright (C) RivieraWaves 2015-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++#include ++ ++#include "rwnx_radar.h" ++#include "rwnx_defs.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++ ++/* ++ * tolerated deviation of radar time stamp in usecs on both sides ++ * TODO: this might need to be HW-dependent ++ */ ++#define PRI_TOLERANCE 16 ++ ++/** ++ * struct radar_types - contains array of patterns defined for one DFS domain ++ * @domain: DFS regulatory domain ++ * @num_radar_types: number of radar types to follow ++ * @radar_types: radar types array ++ */ ++struct radar_types { ++ enum nl80211_dfs_regions region; ++ u32 num_radar_types; ++ const struct radar_detector_specs *spec_riu; ++ const struct radar_detector_specs *spec_fcu; ++}; ++ ++/** ++ * Type of radar waveform: ++ * RADAR_WAVEFORM_SHORT : waveform defined by ++ * - pulse width ++ * - pulse interval in a burst (pri) ++ * - number of pulses in a burst (ppb) ++ * ++ * RADAR_WAVEFORM_WEATHER : ++ * same than SHORT except that ppb is dependent of pri ++ * ++ * RADAR_WAVEFORM_INTERLEAVED : ++ * same than SHORT except there are several value of pri (interleaved) ++ * ++ * RADAR_WAVEFORM_LONG : ++ * ++ */ ++enum radar_waveform_type { ++ RADAR_WAVEFORM_SHORT, ++ RADAR_WAVEFORM_WEATHER, ++ RADAR_WAVEFORM_INTERLEAVED, ++ RADAR_WAVEFORM_LONG ++}; ++ ++/** ++ * struct radar_detector_specs - detector specs for a radar pattern type ++ * @type_id: pattern type, as defined by regulatory ++ * @width_min: minimum radar pulse width in [us] ++ * @width_max: maximum radar pulse width in [us] ++ * @pri_min: minimum pulse repetition interval in [us] (including tolerance) ++ * @pri_max: minimum pri in [us] (including tolerance) ++ * @num_pri: maximum number of different pri for this type ++ * @ppb: pulses per bursts for this type ++ * @ppb_thresh: number of pulses required to trigger detection ++ * @max_pri_tolerance: pulse time stamp tolerance on both sides [us] ++ * @type: Type of radar waveform ++ */ ++struct radar_detector_specs { ++ u8 type_id; ++ u8 width_min; ++ u8 width_max; ++ u16 pri_min; ++ u16 pri_max; ++ u8 num_pri; ++ u8 ppb; ++ u8 ppb_thresh; ++ u8 max_pri_tolerance; ++ enum radar_waveform_type type; ++}; ++ ++ ++/* percentage on ppb threshold to trigger detection */ ++#define MIN_PPB_THRESH 50 ++#define PPB_THRESH(PPB) ((PPB * MIN_PPB_THRESH + 50) / 100) ++#define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF) ++ ++/* width tolerance */ ++#define WIDTH_TOLERANCE 2 ++#define WIDTH_LOWER(X) (X) ++#define WIDTH_UPPER(X) (X) ++ ++#define ETSI_PATTERN_SHORT(ID, WMIN, WMAX, PMIN, PMAX, PPB) \ ++ { \ ++ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ ++ (PRF2PRI(PMAX) - PRI_TOLERANCE), \ ++ (PRF2PRI(PMIN) + PRI_TOLERANCE), 1, PPB, \ ++ PPB_THRESH(PPB), PRI_TOLERANCE, RADAR_WAVEFORM_SHORT \ ++ } ++ ++#define ETSI_PATTERN_INTERLEAVED(ID, WMIN, WMAX, PMIN, PMAX, PRFMIN, PRFMAX, PPB) \ ++ { \ ++ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ ++ (PRF2PRI(PMAX) * PRFMIN- PRI_TOLERANCE), \ ++ (PRF2PRI(PMIN) * PRFMAX + PRI_TOLERANCE), \ ++ PRFMAX, PPB * PRFMAX, \ ++ PPB_THRESH(PPB), PRI_TOLERANCE, RADAR_WAVEFORM_INTERLEAVED \ ++ } ++ ++/* radar types as defined by ETSI EN-301-893 v1.7.1 */ ++static const struct radar_detector_specs etsi_radar_ref_types_v17_riu[] = { ++ ETSI_PATTERN_SHORT(0, 0, 8, 700, 700, 18), ++ ETSI_PATTERN_SHORT(1, 0, 10, 200, 1000, 10), ++ ETSI_PATTERN_SHORT(2, 0, 22, 200, 1600, 15), ++ ETSI_PATTERN_SHORT(3, 0, 22, 2300, 4000, 25), ++ ETSI_PATTERN_SHORT(4, 20, 38, 2000, 4000, 20), ++ ETSI_PATTERN_INTERLEAVED(5, 0, 8, 300, 400, 2, 3, 10), ++ ETSI_PATTERN_INTERLEAVED(6, 0, 8, 400, 1200, 2, 3, 15), ++}; ++ ++static const struct radar_detector_specs etsi_radar_ref_types_v17_fcu[] = { ++ ETSI_PATTERN_SHORT(0, 0, 8, 700, 700, 18), ++ ETSI_PATTERN_SHORT(1, 0, 8, 200, 1000, 10), ++ ETSI_PATTERN_SHORT(2, 0, 16, 200, 1600, 15), ++ ETSI_PATTERN_SHORT(3, 0, 16, 2300, 4000, 25), ++ ETSI_PATTERN_SHORT(4, 20, 34, 2000, 4000, 20), ++ ETSI_PATTERN_INTERLEAVED(5, 0, 8, 300, 400, 2, 3, 10), ++ ETSI_PATTERN_INTERLEAVED(6, 0, 8, 400, 1200, 2, 3, 15), ++}; ++ ++static const struct radar_types etsi_radar_types_v17 = { ++ .region = NL80211_DFS_ETSI, ++ .num_radar_types = ARRAY_SIZE(etsi_radar_ref_types_v17_riu), ++ .spec_riu = etsi_radar_ref_types_v17_riu, ++ .spec_fcu = etsi_radar_ref_types_v17_fcu, ++}; ++ ++#define FCC_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB, TYPE) \ ++ { \ ++ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ ++ PMIN - PRI_TOLERANCE, \ ++ PMAX * PRF + PRI_TOLERANCE, PRF, PPB * PRF, \ ++ PPB_THRESH(PPB), PRI_TOLERANCE, TYPE \ ++ } ++ ++static const struct radar_detector_specs fcc_radar_ref_types_riu[] = { ++ FCC_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(1, 0, 8, 518, 3066, 1, 102, RADAR_WAVEFORM_WEATHER), ++ FCC_PATTERN(2, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(3, 6, 20, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(4, 10, 28, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(5, 50, 110, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ FCC_PATTERN(6, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_detector_specs fcc_radar_ref_types_fcu[] = { ++ FCC_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(1, 0, 8, 518, 3066, 1, 102, RADAR_WAVEFORM_WEATHER), ++ FCC_PATTERN(2, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(3, 6, 12, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(4, 10, 22, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ FCC_PATTERN(5, 50, 104, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ FCC_PATTERN(6, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_types fcc_radar_types = { ++ .region = NL80211_DFS_FCC, ++ .num_radar_types = ARRAY_SIZE(fcc_radar_ref_types_riu), ++ .spec_riu = fcc_radar_ref_types_riu, ++ .spec_fcu = fcc_radar_ref_types_fcu, ++}; ++ ++#define JP_PATTERN FCC_PATTERN ++static const struct radar_detector_specs jp_radar_ref_types_riu[] = { ++ JP_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(1, 2, 8, 3846, 3846, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(2, 0, 8, 1388, 1388, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(3, 0, 8, 4000, 4000, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(4, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(5, 6, 20, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(6, 10, 28, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(7, 50, 110, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ JP_PATTERN(8, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_detector_specs jp_radar_ref_types_fcu[] = { ++ JP_PATTERN(0, 0, 8, 1428, 1428, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(1, 2, 6, 3846, 3846, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(2, 0, 8, 1388, 1388, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(3, 2, 2, 4000, 4000, 1, 18, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(4, 0, 8, 150, 230, 1, 23, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(5, 6, 12, 200, 500, 1, 16, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(6, 10, 22, 200, 500, 1, 12, RADAR_WAVEFORM_SHORT), ++ JP_PATTERN(7, 50, 104, 1000, 2000, 1, 8, RADAR_WAVEFORM_LONG), ++ JP_PATTERN(8, 0, 8, 333, 333, 1, 9, RADAR_WAVEFORM_SHORT), ++}; ++ ++static const struct radar_types jp_radar_types = { ++ .region = NL80211_DFS_JP, ++ .num_radar_types = ARRAY_SIZE(jp_radar_ref_types_riu), ++ .spec_riu = jp_radar_ref_types_riu, ++ .spec_fcu = jp_radar_ref_types_fcu, ++}; ++ ++static const struct radar_types *dfs_domains[] = { ++ &etsi_radar_types_v17, ++ &fcc_radar_types, ++ &jp_radar_types, ++}; ++ ++ ++/** ++ * struct pri_sequence - sequence of pulses matching one PRI ++ * @head: list_head ++ * @pri: pulse repetition interval (PRI) in usecs ++ * @dur: duration of sequence in usecs ++ * @count: number of pulses in this sequence ++ * @count_falses: number of not matching pulses in this sequence ++ * @first_ts: time stamp of first pulse in usecs ++ * @last_ts: time stamp of last pulse in usecs ++ * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur) ++ * @ppb_thresh: Number of pulses to validate detection ++ * (need for weather radar whose value depends of pri) ++ */ ++struct pri_sequence { ++ struct list_head head; ++ u32 pri; ++ u32 dur; ++ u32 count; ++ u32 count_falses; ++ u64 first_ts; ++ u64 last_ts; ++ u64 deadline_ts; ++ u8 ppb_thresh; ++}; ++ ++ ++/** ++ * struct pulse_elem - elements in pulse queue ++ * @ts: time stamp in usecs ++ */ ++struct pulse_elem { ++ struct list_head head; ++ u64 ts; ++}; ++ ++/** ++ * struct pri_detector - PRI detector element for a dedicated radar type ++ * @head: ++ * @rs: detector specs for this detector element ++ * @last_ts: last pulse time stamp considered for this element in usecs ++ * @sequences: list_head holding potential pulse sequences ++ * @pulses: list connecting pulse_elem objects ++ * @count: number of pulses in queue ++ * @max_count: maximum number of pulses to be queued ++ * @window_size: window size back from newest pulse time stamp in usecs ++ * @freq: ++ */ ++struct pri_detector { ++ struct list_head head; ++ const struct radar_detector_specs *rs; ++ u64 last_ts; ++ struct list_head sequences; ++ struct list_head pulses; ++ u32 count; ++ u32 max_count; ++ u32 window_size; ++ struct pri_detector_ops *ops; ++ u16 freq; ++}; ++ ++/** ++ * struct pri_detector_ops - PRI detector ops (dependent of waveform type) ++ * @init : Initialize pri_detector structure ++ * @add_pulse : Add a pulse to the pri-detector ++ * @reset_on_pri_overflow : Should the pri_detector be resetted when pri overflow ++ */ ++struct pri_detector_ops { ++ void (*init)(struct pri_detector *pde); ++ struct pri_sequence * (*add_pulse)(struct pri_detector *pde, u16 len, u64 ts, u16 pri); ++ int reset_on_pri_overflow; ++}; ++ ++ ++/****************************************************************************** ++ * PRI (pulse repetition interval) sequence detection ++ *****************************************************************************/ ++/** ++ * Singleton Pulse and Sequence Pools ++ * ++ * Instances of pri_sequence and pulse_elem are kept in singleton pools to ++ * reduce the number of dynamic allocations. They are shared between all ++ * instances and grow up to the peak number of simultaneously used objects. ++ * ++ * Memory is freed after all references to the pools are released. ++ */ ++static u32 singleton_pool_references; ++static LIST_HEAD(pulse_pool); ++static LIST_HEAD(pseq_pool); ++static DEFINE_SPINLOCK(pool_lock); ++ ++static void pool_register_ref(void) ++{ ++ spin_lock_bh(&pool_lock); ++ singleton_pool_references++; ++ spin_unlock_bh(&pool_lock); ++} ++ ++static void pool_deregister_ref(void) ++{ ++ spin_lock_bh(&pool_lock); ++ singleton_pool_references--; ++ if (singleton_pool_references == 0) { ++ /* free singleton pools with no references left */ ++ struct pri_sequence *ps, *ps0; ++ struct pulse_elem *p, *p0; ++ ++ list_for_each_entry_safe(p, p0, &pulse_pool, head) { ++ list_del(&p->head); ++ kfree(p); ++ } ++ list_for_each_entry_safe(ps, ps0, &pseq_pool, head) { ++ list_del(&ps->head); ++ kfree(ps); ++ } ++ } ++ spin_unlock_bh(&pool_lock); ++} ++ ++static void pool_put_pulse_elem(struct pulse_elem *pe) ++{ ++ spin_lock_bh(&pool_lock); ++ list_add(&pe->head, &pulse_pool); ++ spin_unlock_bh(&pool_lock); ++} ++ ++static void pool_put_pseq_elem(struct pri_sequence *pse) ++{ ++ spin_lock_bh(&pool_lock); ++ list_add(&pse->head, &pseq_pool); ++ spin_unlock_bh(&pool_lock); ++} ++ ++static struct pri_sequence *pool_get_pseq_elem(void) ++{ ++ struct pri_sequence *pse = NULL; ++ spin_lock_bh(&pool_lock); ++ if (!list_empty(&pseq_pool)) { ++ pse = list_first_entry(&pseq_pool, struct pri_sequence, head); ++ list_del(&pse->head); ++ } ++ spin_unlock_bh(&pool_lock); ++ ++ if (pse == NULL) { ++ pse = kmalloc(sizeof(*pse), GFP_ATOMIC); ++ } ++ ++ return pse; ++} ++ ++static struct pulse_elem *pool_get_pulse_elem(void) ++{ ++ struct pulse_elem *pe = NULL; ++ spin_lock_bh(&pool_lock); ++ if (!list_empty(&pulse_pool)) { ++ pe = list_first_entry(&pulse_pool, struct pulse_elem, head); ++ list_del(&pe->head); ++ } ++ spin_unlock_bh(&pool_lock); ++ return pe; ++} ++ ++static struct pulse_elem *pulse_queue_get_tail(struct pri_detector *pde) ++{ ++ struct list_head *l = &pde->pulses; ++ if (list_empty(l)) ++ return NULL; ++ return list_entry(l->prev, struct pulse_elem, head); ++} ++ ++static bool pulse_queue_dequeue(struct pri_detector *pde) ++{ ++ struct pulse_elem *p = pulse_queue_get_tail(pde); ++ if (p != NULL) { ++ list_del_init(&p->head); ++ pde->count--; ++ /* give it back to pool */ ++ pool_put_pulse_elem(p); ++ } ++ return (pde->count > 0); ++} ++ ++/** ++ * pulse_queue_check_window - remove pulses older than window ++ * @pde: pointer on pri_detector ++ * ++ * dequeue pulse that are too old. ++ */ ++static ++void pulse_queue_check_window(struct pri_detector *pde) ++{ ++ u64 min_valid_ts; ++ struct pulse_elem *p; ++ ++ /* there is no delta time with less than 2 pulses */ ++ if (pde->count < 2) ++ return; ++ ++ if (pde->last_ts <= pde->window_size) ++ return; ++ ++ min_valid_ts = pde->last_ts - pde->window_size; ++ while ((p = pulse_queue_get_tail(pde)) != NULL) { ++ if (p->ts >= min_valid_ts) ++ return; ++ pulse_queue_dequeue(pde); ++ } ++} ++ ++/** ++ * pulse_queue_enqueue - Queue one pulse ++ * @pde: pointer on pri_detector ++ * ++ * Add one pulse to the list. If the maximum number of pulses ++ * if reached, remove oldest one. ++ */ ++static ++bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts) ++{ ++ struct pulse_elem *p = pool_get_pulse_elem(); ++ if (p == NULL) { ++ p = kmalloc(sizeof(*p), GFP_ATOMIC); ++ if (p == NULL) { ++ return false; ++ } ++ } ++ INIT_LIST_HEAD(&p->head); ++ p->ts = ts; ++ list_add(&p->head, &pde->pulses); ++ pde->count++; ++ pde->last_ts = ts; ++ pulse_queue_check_window(pde); ++ if (pde->count >= pde->max_count) ++ pulse_queue_dequeue(pde); ++ ++ return true; ++} ++ ++ ++/*************************************************************************** ++ * Short waveform ++ **************************************************************************/ ++/** ++ * pde_get_multiple() - get number of multiples considering a given tolerance ++ * @return factor if abs(val - factor*fraction) <= tolerance, 0 otherwise ++ */ ++static ++u32 pde_get_multiple(u32 val, u32 fraction, u32 tolerance) ++{ ++ u32 remainder; ++ u32 factor; ++ u32 delta; ++ ++ if (fraction == 0) ++ return 0; ++ ++ delta = (val < fraction) ? (fraction - val) : (val - fraction); ++ ++ if (delta <= tolerance) ++ /* val and fraction are within tolerance */ ++ return 1; ++ ++ factor = val / fraction; ++ remainder = val % fraction; ++ if (remainder > tolerance) { ++ /* no exact match */ ++ if ((fraction - remainder) <= tolerance) ++ /* remainder is within tolerance */ ++ factor++; ++ else ++ factor = 0; ++ } ++ return factor; ++} ++ ++/** ++ * pde_short_create_sequences - create_sequences function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * @ts: timestamp of the pulse ++ * @min_count: Minimum number of pulse to be present in the sequence. ++ * (With this pulse there is already a sequence with @min_count ++ * pulse, so if we can't create a sequence with more pulse don't ++ * create it) ++ * @return: false if an error occured (memory allocation) true otherwise ++ * ++ * For each pulses queued check if we can create a sequence with ++ * pri = (ts - pulse_queued.ts) which contains more than @min_count pulses. ++ * ++ */ ++static ++bool pde_short_create_sequences(struct pri_detector *pde, ++ u64 ts, u32 min_count) ++{ ++ struct pulse_elem *p; ++ u16 pulse_idx = 0; ++ ++ list_for_each_entry(p, &pde->pulses, head) { ++ struct pri_sequence ps, *new_ps; ++ struct pulse_elem *p2; ++ u32 tmp_false_count; ++ u64 min_valid_ts; ++ u32 delta_ts = ts - p->ts; ++ pulse_idx++; ++ ++ if (delta_ts < pde->rs->pri_min) ++ /* ignore too small pri */ ++ continue; ++ ++ if (delta_ts > pde->rs->pri_max) ++ /* stop on too large pri (sorted list) */ ++ break; ++ ++ /* build a new sequence with new potential pri */ ++ ps.count = 2; ++ ps.count_falses = pulse_idx - 1; ++ ps.first_ts = p->ts; ++ ps.last_ts = ts; ++ ps.pri = ts - p->ts; ++ ps.dur = ps.pri * (pde->rs->ppb - 1) ++ + 2 * pde->rs->max_pri_tolerance; ++ ++ p2 = p; ++ tmp_false_count = 0; ++ if (ps.dur > ts) ++ min_valid_ts = 0; ++ else ++ min_valid_ts = ts - ps.dur; ++ /* check which past pulses are candidates for new sequence */ ++ list_for_each_entry_continue(p2, &pde->pulses, head) { ++ u32 factor; ++ if (p2->ts < min_valid_ts) ++ /* stop on crossing window border */ ++ break; ++ /* check if pulse match (multi)PRI */ ++ factor = pde_get_multiple(ps.last_ts - p2->ts, ps.pri, ++ pde->rs->max_pri_tolerance); ++ if (factor > 0) { ++ ps.count++; ++ ps.first_ts = p2->ts; ++ /* ++ * on match, add the intermediate falses ++ * and reset counter ++ */ ++ ps.count_falses += tmp_false_count; ++ tmp_false_count = 0; ++ } else { ++ /* this is a potential false one */ ++ tmp_false_count++; ++ } ++ } ++ if (ps.count <= min_count) { ++ /* did not reach minimum count, drop sequence */ ++ continue; ++ } ++ /* this is a valid one, add it */ ++ ps.deadline_ts = ps.first_ts + ps.dur; ++ if (pde->rs->type == RADAR_WAVEFORM_WEATHER) { ++ ps.ppb_thresh = 19000000 / (360 * ps.pri); ++ ps.ppb_thresh = PPB_THRESH(ps.ppb_thresh); ++ } else { ++ ps.ppb_thresh = pde->rs->ppb_thresh; ++ } ++ ++ new_ps = pool_get_pseq_elem(); ++ if (new_ps == NULL) { ++ return false; ++ } ++ memcpy(new_ps, &ps, sizeof(ps)); ++ INIT_LIST_HEAD(&new_ps->head); ++ list_add(&new_ps->head, &pde->sequences); ++ } ++ return true; ++} ++ ++/** ++ * pde_short_add_to_existing_seqs - add_to_existing_seqs function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * @ts: timestamp of the pulse ++ * ++ * Check all sequemces created for this pde. ++ * - If the sequence is too old delete it. ++ * - Else if the delta with the previous pulse match the pri of the sequence ++ * add the pulse to this sequence. If the pulse cannot be added it is added ++ * to the false pulses for this sequence ++ * ++ * @return the length of the longest sequence in which the pulse has been added ++ */ ++static ++u32 pde_short_add_to_existing_seqs(struct pri_detector *pde, u64 ts) ++{ ++ u32 max_count = 0; ++ struct pri_sequence *ps, *ps2; ++ list_for_each_entry_safe(ps, ps2, &pde->sequences, head) { ++ u32 delta_ts; ++ u32 factor; ++ ++ /* first ensure that sequence is within window */ ++ if (ts > ps->deadline_ts) { ++ list_del_init(&ps->head); ++ pool_put_pseq_elem(ps); ++ continue; ++ } ++ ++ delta_ts = ts - ps->last_ts; ++ factor = pde_get_multiple(delta_ts, ps->pri, ++ pde->rs->max_pri_tolerance); ++ ++ if (factor > 0) { ++ ps->last_ts = ts; ++ ps->count++; ++ ++ if (max_count < ps->count) ++ max_count = ps->count; ++ } else { ++ ps->count_falses++; ++ } ++ } ++ return max_count; ++} ++ ++ ++/** ++ * pde_short_check_detection - check_detection function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * ++ * Check all sequemces created for this pde. ++ * - If a sequence contains more pulses than the threshold and more matching ++ * that false pulses. ++ * ++ * @return The first complete sequence, and NULL if no sequence is complete. ++ */ ++static ++struct pri_sequence *pde_short_check_detection(struct pri_detector *pde) ++{ ++ struct pri_sequence *ps; ++ ++ if (list_empty(&pde->sequences)) ++ return NULL; ++ ++ list_for_each_entry(ps, &pde->sequences, head) { ++ /* ++ * we assume to have enough matching confidence if we ++ * 1) have enough pulses ++ * 2) have more matching than false pulses ++ */ ++ if ((ps->count >= ps->ppb_thresh) && ++ (ps->count * pde->rs->num_pri > ps->count_falses)) { ++ return ps; ++ } ++ } ++ return NULL; ++} ++ ++/** ++ * pde_short_init - init function for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * @pde: pointer on pri_detector ++ * ++ * Initialize pri_detector window size to the maximun size of one burst ++ * for the radar specification associated. ++ */ ++static ++void pde_short_init(struct pri_detector *pde) ++{ ++ pde->window_size = pde->rs->pri_max * pde->rs->ppb * pde->rs->num_pri; ++ pde->max_count = pde->rs->ppb * 2; ++} ++ ++static void pri_detector_reset(struct pri_detector *pde, u64 ts); ++/** ++ * pde_short_add_pulse - Add pulse to a pri_detector for ++ * SHORT/WEATHER/INTERLEAVED radar waveform ++ * ++ * @pde : pointer on pri_detector ++ * @len : width of the pulse ++ * @ts : timestamp of the pulse received ++ * @pri : Delta in us with the previous pulse. ++ * (0 means that delta in bigger than 65535 us) ++ * ++ * Process on pulse within this pri_detector ++ * - First try to add it to existing sequence ++ * - Then try to create a new and longest sequence ++ * - Check if this pulse complete a sequence ++ * - If not save this pulse in the list ++ */ ++static ++struct pri_sequence *pde_short_add_pulse(struct pri_detector *pde, ++ u16 len, u64 ts, u16 pri) ++{ ++ u32 max_updated_seq; ++ struct pri_sequence *ps; ++ const struct radar_detector_specs *rs = pde->rs; ++ ++ if (pde->count == 0) { ++ /* This is the first pulse after reset, no need to check sequences */ ++ pulse_queue_enqueue(pde, ts); ++ return NULL; ++ } ++ ++ if ((ts - pde->last_ts) < rs->max_pri_tolerance) { ++ /* if delta to last pulse is too short, don't use this pulse */ ++ return NULL; ++ } ++ ++ max_updated_seq = pde_short_add_to_existing_seqs(pde, ts); ++ ++ if (!pde_short_create_sequences(pde, ts, max_updated_seq)) { ++ pri_detector_reset(pde, ts); ++ return NULL; ++ } ++ ++ ps = pde_short_check_detection(pde); ++ ++ if (ps == NULL) ++ pulse_queue_enqueue(pde, ts); ++ ++ return ps; ++} ++ ++ ++ ++/** ++ * pri detector ops to detect short radar waveform ++ * A Short waveform is defined by : ++ * The width of pulses. ++ * The interval between two pulses inside a burst (called pri) ++ * (some waveform may have or 2/3 interleaved pri) ++ * The number of pulses per burst (ppb) ++ */ ++static struct pri_detector_ops pri_detector_short = { ++ .init = pde_short_init, ++ .add_pulse = pde_short_add_pulse, ++ .reset_on_pri_overflow = 1, ++}; ++ ++ ++/*************************************************************************** ++ * Long waveform ++ **************************************************************************/ ++#define LONG_RADAR_DURATION 12000000 ++#define LONG_RADAR_BURST_MIN_DURATION (12000000 / 20) ++#define LONG_RADAR_MAX_BURST 20 ++ ++/** ++ * pde_long_init - init function for LONG radar waveform ++ * @pde: pointer on pri_detector ++ * ++ * Initialize pri_detector window size to the long waveform radar ++ * waveform (ie. 12s) and max_count ++ */ ++static ++void pde_long_init(struct pri_detector *pde) ++{ ++ pde->window_size = LONG_RADAR_DURATION; ++ pde->max_count = LONG_RADAR_MAX_BURST; /* only count burst not pulses */ ++} ++ ++ ++/** ++ * pde_long_add_pulse - Add pulse to a pri_detector for ++ * LONG radar waveform ++ * ++ * @pde : pointer on pri_detector ++ * @len : width of the pulse ++ * @ts : timestamp of the pulse received ++ * @pri : Delta in us with the previous pulse. ++ * ++ * ++ * For long pulse we only handle one sequence. Since each burst ++ * have a different set of parameters (number of pulse, pri) than ++ * the previous one we only use pulse width to add the pulse in the ++ * sequence. ++ * We only queue one pulse per burst and valid the radar when enough burst ++ * has been detected. ++ */ ++static ++struct pri_sequence *pde_long_add_pulse(struct pri_detector *pde, ++ u16 len, u64 ts, u16 pri) ++{ ++ struct pri_sequence *ps; ++ const struct radar_detector_specs *rs = pde->rs; ++ ++ if (list_empty(&pde->sequences)) { ++ /* First pulse, create a new sequence */ ++ ps = pool_get_pseq_elem(); ++ if (ps == NULL) { ++ return NULL; ++ } ++ ++ /*For long waveform, "count" represents the number of burst detected */ ++ ps->count = 1; ++ /*"count_false" represents the number of pulse in the current burst */ ++ ps->count_falses = 1; ++ ps->first_ts = ts; ++ ps->last_ts = ts; ++ ps->deadline_ts = ts + pde->window_size; ++ ps->pri = 0; ++ INIT_LIST_HEAD(&ps->head); ++ list_add(&ps->head, &pde->sequences); ++ pulse_queue_enqueue(pde, ts); ++ } else { ++ u32 delta_ts; ++ ++ ps = (struct pri_sequence *)pde->sequences.next; ++ ++ delta_ts = ts - ps->last_ts; ++ ps->last_ts = ts; ++ ++ if (delta_ts < rs->pri_max) { ++ /* ignore pulse too close from previous one */ ++ } else if ((delta_ts >= rs->pri_min) && ++ (delta_ts <= rs->pri_max)) { ++ /* this is a new pulse in the current burst, ignore it ++ (i.e don't queue it) */ ++ ps->count_falses++; ++ } else if ((ps->count > 2) && ++ (ps->dur + delta_ts) < LONG_RADAR_BURST_MIN_DURATION) { ++ /* not enough time between burst, ignore pulse */ ++ } else { ++ /* a new burst */ ++ ps->count++; ++ ps->count_falses = 1; ++ ++ /* reset the start of the sequence if deadline reached */ ++ if (ts > ps->deadline_ts) { ++ struct pulse_elem *p; ++ u64 min_valid_ts; ++ ++ min_valid_ts = ts - pde->window_size; ++ while ((p = pulse_queue_get_tail(pde)) != NULL) { ++ if (p->ts >= min_valid_ts) { ++ ps->first_ts = p->ts; ++ ps->deadline_ts = p->ts + pde->window_size; ++ break; ++ } ++ pulse_queue_dequeue(pde); ++ ps->count--; ++ } ++ } ++ ++ /* valid radar if enough burst detected and delta with first burst ++ is at least duration/2 */ ++ if (ps->count > pde->rs->ppb_thresh && ++ (ts - ps->first_ts) > (pde->window_size / 2)) { ++ return ps; ++ } else { ++ pulse_queue_enqueue(pde, ts); ++ ps->dur = delta_ts; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++/** ++ * pri detector ops to detect long radar waveform ++ */ ++static struct pri_detector_ops pri_detector_long = { ++ .init = pde_long_init, ++ .add_pulse = pde_long_add_pulse, ++ .reset_on_pri_overflow = 0, ++}; ++ ++ ++/*************************************************************************** ++ * PRI detector init/reset/exit/get ++ **************************************************************************/ ++/** ++ * pri_detector_init- Create a new pri_detector ++ * ++ * @dpd: dfs_pattern_detector instance pointer ++ * @radar_type: index of radar pattern ++ * @freq: Frequency of the pri detector ++ */ ++struct pri_detector *pri_detector_init(struct dfs_pattern_detector *dpd, ++ u16 radar_type, u16 freq) ++{ ++ struct pri_detector *pde; ++ ++ pde = kzalloc(sizeof(*pde), GFP_ATOMIC); ++ if (pde == NULL) ++ return NULL; ++ ++ INIT_LIST_HEAD(&pde->sequences); ++ INIT_LIST_HEAD(&pde->pulses); ++ INIT_LIST_HEAD(&pde->head); ++ list_add(&pde->head, &dpd->detectors[radar_type]); ++ ++ pde->rs = &dpd->radar_spec[radar_type]; ++ pde->freq = freq; ++ ++ if (pde->rs->type == RADAR_WAVEFORM_LONG) { ++ /* for LONG WAVEFORM */ ++ pde->ops = &pri_detector_long; ++ } else { ++ /* for SHORT, WEATHER and INTERLEAVED */ ++ pde->ops = &pri_detector_short; ++ } ++ ++ /* Init dependent of specs */ ++ pde->ops->init(pde); ++ ++ pool_register_ref(); ++ return pde; ++} ++ ++/** ++ * pri_detector_reset - Reset pri_detector ++ * ++ * @pde: pointer on pri_detector ++ * @ts: New ts reference for the pri_detector ++ * ++ * free pulse queue and sequences list and give objects back to pools ++ */ ++static ++void pri_detector_reset(struct pri_detector *pde, u64 ts) ++{ ++ struct pri_sequence *ps, *ps0; ++ struct pulse_elem *p, *p0; ++ list_for_each_entry_safe(ps, ps0, &pde->sequences, head) { ++ list_del_init(&ps->head); ++ pool_put_pseq_elem(ps); ++ } ++ list_for_each_entry_safe(p, p0, &pde->pulses, head) { ++ list_del_init(&p->head); ++ pool_put_pulse_elem(p); ++ } ++ pde->count = 0; ++ pde->last_ts = ts; ++} ++ ++/** ++ * pri_detector_exit - Delete pri_detector ++ * ++ * @pde: pointer on pri_detector ++ */ ++static ++void pri_detector_exit(struct pri_detector *pde) ++{ ++ pri_detector_reset(pde, 0); ++ pool_deregister_ref(); ++ list_del(&pde->head); ++ kfree(pde); ++} ++ ++/** ++ * pri_detector_get() - get pri detector for a given frequency and type ++ * @dpd: dfs_pattern_detector instance pointer ++ * @freq: frequency in MHz ++ * @radar_type: index of radar pattern ++ * @return pointer to pri detector on success, NULL otherwise ++ * ++ * Return existing pri detector for the given frequency or return a ++ * newly create one. ++ * Pri detector are "merged" by frequency so that if a pri detector for a freq ++ * of +/- 2Mhz already exists don't create a new one. ++ * ++ * Maybe will need to adapt frequency merge for pattern with chirp. ++ */ ++static struct pri_detector * ++pri_detector_get(struct dfs_pattern_detector *dpd, u16 freq, u16 radar_type) ++{ ++ struct pri_detector *pde, *cur = NULL; ++ list_for_each_entry(pde, &dpd->detectors[radar_type], head) { ++ if (pde->freq == freq) { ++ if (pde->count) ++ return pde; ++ else ++ cur = pde; ++ } else if (pde->freq - 2 == freq && pde->count) { ++ return pde; ++ } else if (pde->freq + 2 == freq && pde->count) { ++ return pde; ++ } ++ } ++ ++ if (cur) ++ return cur; ++ else ++ return pri_detector_init(dpd, radar_type, freq); ++} ++ ++ ++/****************************************************************************** ++ * DFS Pattern Detector ++ *****************************************************************************/ ++/** ++ * dfs_pattern_detector_reset() - reset all channel detectors ++ * ++ * @dpd: dfs_pattern_detector ++ */ ++static void dfs_pattern_detector_reset(struct dfs_pattern_detector *dpd) ++{ ++ struct pri_detector *pde; ++ int i; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry(pde, &dpd->detectors[i], head) ++ pri_detector_reset(pde, dpd->last_pulse_ts); ++ } ++ ++ dpd->last_pulse_ts = 0; ++ dpd->prev_jiffies = jiffies; ++} ++ ++/** ++ * dfs_pattern_detector_reset() - delete all channel detectors ++ * ++ * @dpd: dfs_pattern_detector ++ */ ++static void dfs_pattern_detector_exit(struct dfs_pattern_detector *dpd) ++{ ++ struct pri_detector *pde, *pde0; ++ int i; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry_safe(pde, pde0, &dpd->detectors[i], head) ++ pri_detector_exit(pde); ++ } ++ ++ kfree(dpd); ++} ++ ++/** ++ * dfs_pattern_detector_pri_overflow - reset all channel detectors on pri ++ * overflow ++ * @dpd: dfs_pattern_detector ++ */ ++static void dfs_pattern_detector_pri_overflow(struct dfs_pattern_detector *dpd) ++{ ++ struct pri_detector *pde; ++ int i; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry(pde, &dpd->detectors[i], head) ++ if (pde->ops->reset_on_pri_overflow) ++ pri_detector_reset(pde, dpd->last_pulse_ts); ++ } ++} ++ ++/** ++ * dfs_pattern_detector_add_pulse - Process one pulse ++ * ++ * @dpd: dfs_pattern_detector ++ * @chain: Chain that correspond to this pattern_detector (only for debug) ++ * @freq: frequency of the pulse ++ * @pri: Delta with previous pulse. (0 if delta is too big for u16) ++ * @len: width of the pulse ++ * @now: jiffies value when pulse was received ++ * ++ * Get (or create) the channel_detector for this frequency. Then add the pulse ++ * in each pri_detector created in this channel_detector. ++ * ++ * ++ * @return True is the pulse complete a radar pattern, false otherwise ++ */ ++static bool dfs_pattern_detector_add_pulse(struct dfs_pattern_detector *dpd, ++ enum rwnx_radar_chain chain, ++ u16 freq, u16 pri, u16 len, u32 now) ++{ ++ u32 i; ++ ++ /* ++ * pulses received for a non-supported or un-initialized ++ * domain are treated as detected radars for fail-safety ++ */ ++ if (dpd->region == NL80211_DFS_UNSET) ++ return true; ++ ++ /* Compute pulse time stamp */ ++ if (pri == 0) { ++ u32 delta_jiffie; ++ if (unlikely(now < dpd->prev_jiffies)) { ++ delta_jiffie = 0xffffffff - dpd->prev_jiffies + now; ++ } else { ++ delta_jiffie = now - dpd->prev_jiffies; ++ } ++ dpd->last_pulse_ts += jiffies_to_usecs(delta_jiffie); ++ dpd->prev_jiffies = now; ++ dfs_pattern_detector_pri_overflow(dpd); ++ } else { ++ dpd->last_pulse_ts += pri; ++ } ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ struct pri_sequence *ps; ++ struct pri_detector *pde; ++ const struct radar_detector_specs *rs = &dpd->radar_spec[i]; ++ ++ /* no need to look up for pde if len is not within range */ ++ if ((rs->width_min > len) || ++ (rs->width_max < len)) { ++ continue; ++ } ++ ++ pde = pri_detector_get(dpd, freq, i); ++ ps = pde->ops->add_pulse(pde, len, dpd->last_pulse_ts, pri); ++ ++ if (ps != NULL) { ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_detected(chain, dpd->region, pde->freq, i, ps->pri); ++#endif ++ // reset everything instead of just the channel detector ++ dfs_pattern_detector_reset(dpd); ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++/** ++ * get_dfs_domain_radar_types() - get radar types for a given DFS domain ++ * @param domain DFS domain ++ * @return radar_types ptr on success, NULL if DFS domain is not supported ++ */ ++static const struct radar_types * ++get_dfs_domain_radar_types(enum nl80211_dfs_regions region) ++{ ++ u32 i; ++ for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) { ++ if (dfs_domains[i]->region == region) ++ return dfs_domains[i]; ++ } ++ return NULL; ++} ++ ++/** ++ * get_dfs_max_radar_types() - get maximum radar types for all supported domain ++ * @return the maximum number of radar pattern supported by on region ++ */ ++static u16 get_dfs_max_radar_types(void) ++{ ++ u32 i; ++ u16 max = 0; ++ for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) { ++ if (dfs_domains[i]->num_radar_types > max) ++ max = dfs_domains[i]->num_radar_types; ++ } ++ return max; ++} ++ ++/** ++ * dfs_pattern_detector_set_domain - set DFS domain ++ * ++ * @dpd: dfs_pattern_detector ++ * @region: DFS region ++ * ++ * set DFS domain, resets detector lines upon domain changes ++ */ ++static ++bool dfs_pattern_detector_set_domain(struct dfs_pattern_detector *dpd, ++ enum nl80211_dfs_regions region, u8 chain) ++{ ++ const struct radar_types *rt; ++ struct pri_detector *pde, *pde0; ++ int i; ++ ++ if (dpd->region == region) ++ return true; ++ ++ dpd->region = NL80211_DFS_UNSET; ++ ++ rt = get_dfs_domain_radar_types(region); ++ if (rt == NULL) ++ return false; ++ ++ /* delete all pri detectors for previous DFS domain */ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ if (!list_empty(&dpd->detectors[i])) ++ list_for_each_entry_safe(pde, pde0, &dpd->detectors[i], head) ++ pri_detector_exit(pde); ++ } ++ ++ if (chain == RWNX_RADAR_RIU) ++ dpd->radar_spec = rt->spec_riu; ++ else ++ dpd->radar_spec = rt->spec_fcu; ++ dpd->num_radar_types = rt->num_radar_types; ++ ++ dpd->region = region; ++ ++ AICWFDBG(LOGINFO,"set_region %d \n",region); ++ return true; ++} ++ ++/** ++ * dfs_pattern_detector_init - Initialize dfs_pattern_detector ++ * ++ * @region: DFS region ++ * @return: pointer on dfs_pattern_detector ++ * ++ */ ++static struct dfs_pattern_detector * ++dfs_pattern_detector_init(enum nl80211_dfs_regions region, u8 chain) ++{ ++ struct dfs_pattern_detector *dpd; ++ u16 i, max_radar_type = get_dfs_max_radar_types(); ++ ++ dpd = kmalloc(sizeof(*dpd) + max_radar_type * sizeof(dpd->detectors[0]), ++ GFP_KERNEL); ++ if (dpd == NULL) ++ return NULL; ++ ++ dpd->region = NL80211_DFS_UNSET; ++ dpd->enabled = RWNX_RADAR_DETECT_DISABLE; ++ dpd->last_pulse_ts = 0; ++ dpd->prev_jiffies = jiffies; ++ dpd->num_radar_types = 0; ++ for (i = 0; i < max_radar_type; i++) ++ INIT_LIST_HEAD(&dpd->detectors[i]); ++ ++ if (dfs_pattern_detector_set_domain(dpd, region, chain)) ++ return dpd; ++ ++ kfree(dpd); ++ return NULL; ++} ++ ++ ++/****************************************************************************** ++ * driver interface ++ *****************************************************************************/ ++static u16 rwnx_radar_get_center_freq(struct rwnx_hw *rwnx_hw, u8 chain) ++{ ++ if (chain == RWNX_RADAR_FCU) ++ return rwnx_hw->phy.sec_chan.center_freq1; ++ ++ if (chain == RWNX_RADAR_RIU) { ++#ifdef CONFIG_RWNX_FULLMAC ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) { ++ WARN(1, "Radar pulse without channel information"); ++ } else ++ return rwnx_hw->chanctx_table[rwnx_hw->cur_chanctx].chan_def.center_freq1; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } ++ ++ return 0; ++} ++ ++static void rwnx_radar_detected(struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct cfg80211_chan_def chan_def; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) { ++ WARN(1, "Radar detected without channel information"); ++ return; ++ } ++ ++ /* ++ recopy chan_def in local variable because rwnx_radar_cancel_cac may ++ clean the variable (if in CAC and it's the only vif using this context) ++ and CAC should be aborted before reporting the radar. ++ */ ++ chan_def = rwnx_hw->chanctx_table[rwnx_hw->cur_chanctx].chan_def; ++ ++ rwnx_radar_cancel_cac(&rwnx_hw->radar); ++ cfg80211_radar_event(rwnx_hw->wiphy, &chan_def, GFP_KERNEL); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++static void rwnx_radar_process_pulse(struct work_struct *ws) ++{ ++ struct rwnx_radar *radar = container_of(ws, struct rwnx_radar, ++ detection_work); ++ struct rwnx_hw *rwnx_hw = container_of(radar, struct rwnx_hw, radar); ++ int chain; ++ u32 pulses[RWNX_RADAR_LAST][RWNX_RADAR_PULSE_MAX]; ++ u16 pulses_count[RWNX_RADAR_LAST]; ++ u32 now = jiffies; /* would be better to store jiffies value in IT handler */ ++ ++ /* recopy pulses locally to avoid too long spin_lock */ ++ spin_lock_bh(&radar->lock); ++ for (chain = RWNX_RADAR_RIU; chain < RWNX_RADAR_LAST; chain++) { ++ int start, count; ++ ++ count = radar->pulses[chain].count; ++ start = radar->pulses[chain].index - count; ++ if (start < 0) ++ start += RWNX_RADAR_PULSE_MAX; ++ ++ pulses_count[chain] = count; ++ if (count == 0) ++ continue; ++ ++ if ((start + count) > RWNX_RADAR_PULSE_MAX) { ++ u16 count1 = (RWNX_RADAR_PULSE_MAX - start); ++ memcpy(&(pulses[chain][0]), ++ &(radar->pulses[chain].buffer[start]), ++ count1 * sizeof(struct radar_pulse)); ++ memcpy(&(pulses[chain][count1]), ++ &(radar->pulses[chain].buffer[0]), ++ (count - count1) * sizeof(struct radar_pulse)); ++ } else { ++ memcpy(&(pulses[chain][0]), ++ &(radar->pulses[chain].buffer[start]), ++ count * sizeof(struct radar_pulse)); ++ } ++ radar->pulses[chain].count = 0; ++ } ++ spin_unlock_bh(&radar->lock); ++ ++ ++ /* now process pulses */ ++ for (chain = RWNX_RADAR_RIU; chain < RWNX_RADAR_LAST; chain++) { ++ int i; ++ u16 freq; ++ ++ if (pulses_count[chain] == 0) ++ continue; ++ ++ freq = rwnx_radar_get_center_freq(rwnx_hw, chain); ++ ++ for (i = 0; i < pulses_count[chain] ; i++) { ++ struct radar_pulse *p = (struct radar_pulse *)&pulses[chain][i]; ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_pulse(chain, p); ++#endif ++ if (dfs_pattern_detector_add_pulse(radar->dpd[chain], chain, ++ (s16)freq + (2 * p->freq), ++ p->rep, (p->len * 2), now)) { ++ ++ u16 idx = radar->detected[chain].index; ++ ++ if (chain == RWNX_RADAR_RIU) { ++ /* operating chain, inform upper layer to change channel */ ++ if (radar->dpd[chain]->enabled == RWNX_RADAR_DETECT_REPORT) { ++ rwnx_radar_detected(rwnx_hw); ++ /* no need to report new radar until upper layer set a ++ new channel. This prevent warning if a new radar is ++ detected while mac80211 is changing channel */ ++ rwnx_radar_detection_enable(radar, ++ RWNX_RADAR_DETECT_DISABLE, ++ chain); ++ /* purge any event received since the beginning of the ++ function (we are sure not to interfer with tasklet ++ as we disable detection just before) */ ++ radar->pulses[chain].count = 0; ++ } ++ } else { ++ /* secondary radar detection chain, simply report info in ++ debugfs for now */ ++ } ++ ++ radar->detected[chain].freq[idx] = (s16)freq + (2 * p->freq); ++ radar->detected[chain].time[idx] = ktime_get_real_seconds(); ++ radar->detected[chain].index = ((idx + 1) % ++ NX_NB_RADAR_DETECTED); ++ radar->detected[chain].count++; ++ /* no need to process next pulses for this chain */ ++ break; ++ } ++ } ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static void rwnx_radar_cac_work(struct work_struct *ws) ++{ ++ struct delayed_work *dw = container_of(ws, struct delayed_work, work); ++ struct rwnx_radar *radar = container_of(dw, struct rwnx_radar, cac_work); ++ struct rwnx_hw *rwnx_hw = container_of(radar, struct rwnx_hw, radar); ++ struct rwnx_chanctx *ctxt; ++ ++ if (radar->cac_vif == NULL) { ++ WARN(1, "CAC finished but no vif set"); ++ return; ++ } ++ ++ ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index]; ++ cfg80211_cac_event(radar->cac_vif->ndev, ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ &ctxt->chan_def, ++ #endif ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) ++ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0); ++ #else ++ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); ++ #endif ++ rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif); ++ rwnx_chanctx_unlink(radar->cac_vif); ++ ++ radar->cac_vif = NULL; ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++bool rwnx_radar_detection_init(struct rwnx_radar *radar) ++{ ++ spin_lock_init(&radar->lock); ++ ++ radar->dpd[RWNX_RADAR_RIU] = dfs_pattern_detector_init(NL80211_DFS_UNSET, ++ RWNX_RADAR_RIU); ++ if (radar->dpd[RWNX_RADAR_RIU] == NULL) ++ return false; ++ ++ radar->dpd[RWNX_RADAR_FCU] = dfs_pattern_detector_init(NL80211_DFS_UNSET, ++ RWNX_RADAR_FCU); ++ if (radar->dpd[RWNX_RADAR_FCU] == NULL) { ++ rwnx_radar_detection_deinit(radar); ++ return false; ++ } ++ ++ INIT_WORK(&radar->detection_work, rwnx_radar_process_pulse); ++#ifdef CONFIG_RWNX_FULLMAC ++ INIT_DELAYED_WORK(&radar->cac_work, rwnx_radar_cac_work); ++ radar->cac_vif = NULL; ++#endif /* CONFIG_RWNX_FULLMAC */ ++ return true; ++} ++ ++void rwnx_radar_detection_deinit(struct rwnx_radar *radar) ++{ ++ if (radar->dpd[RWNX_RADAR_RIU]) { ++ dfs_pattern_detector_exit(radar->dpd[RWNX_RADAR_RIU]); ++ radar->dpd[RWNX_RADAR_RIU] = NULL; ++ } ++ if (radar->dpd[RWNX_RADAR_FCU]) { ++ dfs_pattern_detector_exit(radar->dpd[RWNX_RADAR_FCU]); ++ radar->dpd[RWNX_RADAR_FCU] = NULL; ++ } ++} ++ ++bool rwnx_radar_set_domain(struct rwnx_radar *radar, ++ enum nl80211_dfs_regions region) ++{ ++ if (radar->dpd[0] == NULL) ++ return false; ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_set_region(region); ++#endif ++ return (dfs_pattern_detector_set_domain(radar->dpd[RWNX_RADAR_RIU], ++ region, RWNX_RADAR_RIU) && ++ dfs_pattern_detector_set_domain(radar->dpd[RWNX_RADAR_FCU], ++ region, RWNX_RADAR_FCU)); ++} ++ ++void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain) ++{ ++ if (chain < RWNX_RADAR_LAST) { ++#ifdef CREATE_TRACE_POINTS ++ trace_radar_enable_detection(radar->dpd[chain]->region, enable, chain); ++#endif ++ spin_lock_bh(&radar->lock); ++ radar->dpd[chain]->enabled = enable; ++ spin_unlock_bh(&radar->lock); ++ } ++} ++ ++bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, u8 chain) ++{ ++ return radar->dpd[chain]->enabled != RWNX_RADAR_DETECT_DISABLE; ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_radar_start_cac(struct rwnx_radar *radar, u32 cac_time_ms, ++ struct rwnx_vif *vif) ++{ ++ WARN(radar->cac_vif != NULL, "CAC already in progress"); ++ radar->cac_vif = vif; ++ schedule_delayed_work(&radar->cac_work, msecs_to_jiffies(cac_time_ms)); ++} ++ ++void rwnx_radar_cancel_cac(struct rwnx_radar *radar) ++{ ++ struct rwnx_hw *rwnx_hw = container_of(radar, struct rwnx_hw, radar); ++ ++ if (radar->cac_vif == NULL) { ++ return; ++ } ++ ++ if (cancel_delayed_work(&radar->cac_work)) { ++ struct rwnx_chanctx *ctxt; ++ ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index]; ++ rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif); ++ cfg80211_cac_event(radar->cac_vif->ndev, ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++ &ctxt->chan_def, ++ #endif ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) ++ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0); ++ #else ++ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); ++ #endif ++ rwnx_chanctx_unlink(radar->cac_vif); ++ } ++ ++ radar->cac_vif = NULL; ++} ++ ++void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_chanctx *ctxt; ++ ++ /* If no information on current channel do nothing */ ++ if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) ++ return; ++ ++ ctxt = &rwnx_hw->chanctx_table[rwnx_hw->cur_chanctx]; ++ if (ctxt->chan_def.chan->flags & IEEE80211_CHAN_RADAR) { ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_REPORT, ++ RWNX_RADAR_RIU); ++ } else { ++ rwnx_radar_detection_enable(&rwnx_hw->radar, ++ RWNX_RADAR_DETECT_DISABLE, ++ RWNX_RADAR_RIU); ++ } ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/***************************************************************************** ++ * Debug functions ++ *****************************************************************************/ ++static ++int rwnx_radar_dump_pri_detector(char *buf, size_t len, ++ struct pri_detector *pde) ++{ ++ char freq_info[] = "Freq = %3.dMhz\n"; ++ char seq_info[] = " pri | count | false \n"; ++ struct pri_sequence *seq; ++ int res, write = 0; ++ ++ if (list_empty(&pde->sequences)) { ++ return 0; ++ } ++ ++ if (buf == NULL) { ++ int nb_seq = 1; ++ list_for_each_entry(seq, &pde->sequences, head) { ++ nb_seq++; ++ } ++ ++ return (sizeof(freq_info) + nb_seq * sizeof(seq_info)); ++ } ++ ++ res = scnprintf(buf, len, freq_info, pde->freq); ++ write += res; ++ len -= res; ++ ++ res = scnprintf(&buf[write], len, "%s", seq_info); ++ write += res; ++ len -= res; ++ ++ list_for_each_entry(seq, &pde->sequences, head) { ++ res = scnprintf(&buf[write], len, " %6.d | %2.d | %.2d \n", ++ seq->pri, seq->count, seq->count_falses); ++ write += res; ++ len -= res; ++ } ++ ++ return write; ++} ++ ++int rwnx_radar_dump_pattern_detector(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain) ++{ ++ struct dfs_pattern_detector *dpd = radar->dpd[chain]; ++ char info[] = "Type = %3.d\n"; ++ struct pri_detector *pde; ++ int i, res, write = 0; ++ ++ /* if buf is NULL return size needed for dump */ ++ if (buf == NULL) { ++ int size_needed = 0; ++ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ list_for_each_entry(pde, &dpd->detectors[i], head) { ++ size_needed += rwnx_radar_dump_pri_detector(NULL, 0, pde); ++ } ++ size_needed += sizeof(info); ++ ++ return size_needed; ++ } ++ } ++ ++ /* */ ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ res = scnprintf(&buf[write], len, info, i); ++ ++ write += res; ++ len -= res; ++ list_for_each_entry(pde, &dpd->detectors[i], head) { ++ res = rwnx_radar_dump_pri_detector(&buf[write], len, pde); ++ write += res; ++ len -= res; ++ } ++ } ++ ++ return write; ++} ++ ++ ++int rwnx_radar_dump_radar_detected(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain) ++{ ++ struct rwnx_radar_detected *detect = &(radar->detected[chain]); ++ char info[] = "2001/02/02 - 02:20 5126MHz\n"; ++ int idx, i, res, write = 0; ++ int count = detect->count; ++ ++ if (count > NX_NB_RADAR_DETECTED) ++ count = NX_NB_RADAR_DETECTED; ++ ++ if (buf == NULL) { ++ return (count * sizeof(info)) + 1; ++ } ++ ++ idx = (detect->index - detect->count) % NX_NB_RADAR_DETECTED; ++ ++ for (i = 0; i < count; i++) { ++ struct tm tm; ++ time64_to_tm(detect->time[idx], 0, &tm); ++ ++ res = scnprintf(&buf[write], len, ++ "%.4d/%.2d/%.2d - %.2d:%.2d %4.4dMHz\n", ++ (int)tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, ++ tm.tm_hour, tm.tm_min, detect->freq[idx]); ++ write += res; ++ len -= res; ++ ++ idx = (idx + 1) % NX_NB_RADAR_DETECTED; ++ } ++ ++ return write; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h +new file mode 100644 +index 000000000000..8bc36f527f62 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h +@@ -0,0 +1,160 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_radar.h ++ * ++ * @brief Functions to handle radar detection ++ * ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_RADAR_H_ ++#define _RWNX_RADAR_H_ ++ ++#include ++ ++struct rwnx_vif; ++struct rwnx_hw; ++ ++enum rwnx_radar_chain { ++ RWNX_RADAR_RIU = 0, ++ RWNX_RADAR_FCU, ++ RWNX_RADAR_LAST ++}; ++ ++enum rwnx_radar_detector { ++ RWNX_RADAR_DETECT_DISABLE = 0, /* Ignore radar pulses */ ++ RWNX_RADAR_DETECT_ENABLE = 1, /* Process pattern detection but do not ++ report radar to upper layer (for test) */ ++ RWNX_RADAR_DETECT_REPORT = 2 /* Process pattern detection and report ++ radar to upper layer. */ ++}; ++ ++#ifdef CONFIG_RWNX_RADAR ++#include ++#include ++ ++#define RWNX_RADAR_PULSE_MAX 32 ++ ++/** ++ * struct rwnx_radar_pulses - List of pulses reported by HW ++ * @index: write index ++ * @count: number of valid pulses ++ * @buffer: buffer of pulses ++ */ ++struct rwnx_radar_pulses { ++ /* Last radar pulses received */ ++ int index; ++ int count; ++ u32 buffer[RWNX_RADAR_PULSE_MAX]; ++}; ++ ++/** ++ * struct dfs_pattern_detector - DFS pattern detector ++ * @region: active DFS region, NL80211_DFS_UNSET until set ++ * @num_radar_types: number of different radar types ++ * @last_pulse_ts: time stamp of last valid pulse in usecs ++ * @prev_jiffies: ++ * @radar_detector_specs: array of radar detection specs ++ * @channel_detectors: list connecting channel_detector elements ++ */ ++struct dfs_pattern_detector { ++ u8 enabled; ++ enum nl80211_dfs_regions region; ++ u8 num_radar_types; ++ u64 last_pulse_ts; ++ u32 prev_jiffies; ++ const struct radar_detector_specs *radar_spec; ++ struct list_head detectors[]; ++}; ++ ++#define NX_NB_RADAR_DETECTED 4 ++ ++/** ++ * struct rwnx_radar_detected - List of radar detected ++ */ ++struct rwnx_radar_detected { ++ u16 index; ++ u16 count; ++ s64 time[NX_NB_RADAR_DETECTED]; ++ s16 freq[NX_NB_RADAR_DETECTED]; ++}; ++ ++ ++struct rwnx_radar { ++ struct rwnx_radar_pulses pulses[RWNX_RADAR_LAST]; ++ struct dfs_pattern_detector *dpd[RWNX_RADAR_LAST]; ++ struct rwnx_radar_detected detected[RWNX_RADAR_LAST]; ++ struct work_struct detection_work; /* Work used to process radar pulses */ ++ spinlock_t lock; /* lock for pulses processing */ ++ ++ /* In softmac cac is handled by mac80211 */ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct delayed_work cac_work; /* Work used to handle CAC */ ++ struct rwnx_vif *cac_vif; /* vif on which we started CAC */ ++#endif ++}; ++ ++bool rwnx_radar_detection_init(struct rwnx_radar *radar); ++void rwnx_radar_detection_deinit(struct rwnx_radar *radar); ++bool rwnx_radar_set_domain(struct rwnx_radar *radar, ++ enum nl80211_dfs_regions region); ++void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain); ++bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, u8 chain); ++void rwnx_radar_start_cac(struct rwnx_radar *radar, u32 cac_time_ms, ++ struct rwnx_vif *vif); ++void rwnx_radar_cancel_cac(struct rwnx_radar *radar); ++void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw); ++int rwnx_radar_dump_pattern_detector(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain); ++int rwnx_radar_dump_radar_detected(char *buf, size_t len, ++ struct rwnx_radar *radar, u8 chain); ++ ++#else ++ ++struct rwnx_radar { ++}; ++ ++static inline bool rwnx_radar_detection_init(struct rwnx_radar *radar) ++{return true; } ++ ++static inline void rwnx_radar_detection_deinit(struct rwnx_radar *radar) ++{} ++ ++static inline bool rwnx_radar_set_domain(struct rwnx_radar *radar, ++ enum nl80211_dfs_regions region) ++{return true; } ++ ++static inline void rwnx_radar_detection_enable(struct rwnx_radar *radar, ++ u8 enable, u8 chain) ++{} ++ ++static inline bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, ++ u8 chain) ++{return false; } ++ ++static inline void rwnx_radar_start_cac(struct rwnx_radar *radar, ++ u32 cac_time_ms, struct rwnx_vif *vif) ++{} ++ ++static inline void rwnx_radar_cancel_cac(struct rwnx_radar *radar) ++{} ++ ++static inline void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw) ++{} ++ ++static inline int rwnx_radar_dump_pattern_detector(char *buf, size_t len, ++ struct rwnx_radar *radar, ++ u8 chain) ++{return 0; } ++ ++static inline int rwnx_radar_dump_radar_detected(char *buf, size_t len, ++ struct rwnx_radar *radar, ++ u8 chain) ++{return 0; } ++ ++#endif /* CONFIG_RWNX_RADAR */ ++ ++#endif // _RWNX_RADAR_H_ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c +new file mode 100644 +index 000000000000..148dca51c1df +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c +@@ -0,0 +1,2531 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_rx.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_rx.h" ++#include "rwnx_tx.h" ++#include "rwnx_prof.h" ++#include "ipc_host.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "aicwf_txrxif.h" ++#ifdef AICWF_ARP_OFFLOAD ++#include ++#include ++#include "rwnx_msg_tx.h" ++#endif ++ ++#ifndef IEEE80211_MAX_CHAINS ++#define IEEE80211_MAX_CHAINS 4 ++#endif ++ ++u8 dhcped; // = 0; ++ ++u16 tx_legrates_lut_rate[] = { ++ 10, ++ 20, ++ 55, ++ 110, ++ 60, ++ 90, ++ 120, ++ 180, ++ 240, ++ 360, ++ 480, ++ 540 ++}; ++ ++struct rwnx_legrate legrates_lut[] = { ++ [0] = { .idx = 0, .rate = 10}, ++ [1] = { .idx = 1, .rate = 20}, ++ [2] = { .idx = 2, .rate = 55}, ++ [3] = { .idx = 3, .rate = 110}, ++ [4] = { .idx = -1, .rate = 0}, ++ [5] = { .idx = -1, .rate = 0}, ++ [6] = { .idx = -1, .rate = 0}, ++ [7] = { .idx = -1, .rate = 0}, ++ [8] = { .idx = 10, .rate = 480}, ++ [9] = { .idx = 8, .rate = 240}, ++ [10] = { .idx = 6, .rate = 120}, ++ [11] = { .idx = 4, .rate = 60}, ++ [12] = { .idx = 11, .rate = 540}, ++ [13] = { .idx = 9, .rate = 360}, ++ [14] = { .idx = 7, .rate = 180}, ++ [15] = { .idx = 5, .rate = 90}, ++}; ++ ++struct vendor_radiotap_hdr { ++ u8 oui[3]; ++ u8 subns; ++ u16 len; ++ u8 data[]; ++}; ++ ++/** ++ * rwnx_rx_get_vif - Return pointer to the destination vif ++ * ++ * @rwnx_hw: main driver data ++ * @vif_idx: vif index present in rx descriptor ++ * ++ * Select the vif that should receive this frame. Returns NULL if the destination ++ * vif is not active or vif is not specified in the descriptor. ++ */ ++static inline ++struct rwnx_vif *rwnx_rx_get_vif(struct rwnx_hw *rwnx_hw, int vif_idx) ++{ ++ struct rwnx_vif *rwnx_vif = NULL; ++ ++ if (vif_idx < NX_VIRT_DEV_MAX) { ++ rwnx_vif = rwnx_hw->vif_table[vif_idx]; ++ ++ if(!rwnx_vif){ ++ AICWFDBG(LOGERROR, "%s rwnx_hw->vif_table[%d] NULL\r\n", __func__, vif_idx); ++ return NULL; ++ }else if(!rwnx_vif->up){ ++ AICWFDBG(LOGERROR, "%s rwnx_hw->vif_table[%d] is down\r\n", __func__, vif_idx); ++ return NULL; ++ } ++ } ++ ++ return rwnx_vif; ++} ++ ++/** ++ * rwnx_rx_vector_convert - Convert a legacy RX vector into a new RX vector format ++ * ++ * @rwnx_hw: main driver data. ++ * @rx_vect1: Rx vector 1 descriptor of the received frame. ++ * @rx_vect2: Rx vector 2 descriptor of the received frame. ++ */ ++static void rwnx_rx_vector_convert(struct rwnx_hw *rwnx_hw, ++ struct rx_vector_1 *rx_vect1, ++ struct rx_vector_2 *rx_vect2) ++{ ++ struct rx_vector_1_old rx_vect1_leg; ++ struct rx_vector_2_old rx_vect2_leg; ++ u32_l phy_vers = rwnx_hw->version_cfm.version_phy_2; ++ ++ // Check if we need to do the conversion. Only if old modem is used ++ if (__MDM_MAJOR_VERSION(phy_vers) > 0) { ++ rx_vect1->rssi1 = rx_vect1->rssi_leg; ++ return; ++ } ++ ++ // Copy the received vector locally ++ memcpy(&rx_vect1_leg, rx_vect1, sizeof(struct rx_vector_1_old)); ++ ++ // Reset it ++ memset(rx_vect1, 0, sizeof(struct rx_vector_1)); ++ ++ // Perform the conversion ++ rx_vect1->format_mod = rx_vect1_leg.format_mod; ++ rx_vect1->ch_bw = rx_vect1_leg.ch_bw; ++ rx_vect1->antenna_set = rx_vect1_leg.antenna_set; ++ rx_vect1->leg_length = rx_vect1_leg.leg_length; ++ rx_vect1->leg_rate = rx_vect1_leg.leg_rate; ++ rx_vect1->rssi1 = rx_vect1_leg.rssi1; ++ ++ switch (rx_vect1->format_mod) { ++ case FORMATMOD_NON_HT: ++ case FORMATMOD_NON_HT_DUP_OFDM: ++ rx_vect1->leg.lsig_valid = rx_vect1_leg.lsig_valid; ++ rx_vect1->leg.chn_bw_in_non_ht = rx_vect1_leg.num_extn_ss; ++ rx_vect1->leg.dyn_bw_in_non_ht = rx_vect1_leg.dyn_bw; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ rx_vect1->ht.aggregation = rx_vect1_leg.aggregation; ++ rx_vect1->ht.fec = rx_vect1_leg.fec_coding; ++ rx_vect1->ht.lsig_valid = rx_vect1_leg.lsig_valid; ++ rx_vect1->ht.length = rx_vect1_leg.ht_length; ++ rx_vect1->ht.mcs = rx_vect1_leg.mcs; ++ rx_vect1->ht.num_extn_ss = rx_vect1_leg.num_extn_ss; ++ rx_vect1->ht.short_gi = rx_vect1_leg.short_gi; ++ rx_vect1->ht.smoothing = rx_vect1_leg.smoothing; ++ rx_vect1->ht.sounding = rx_vect1_leg.sounding; ++ rx_vect1->ht.stbc = rx_vect1_leg.stbc; ++ break; ++ case FORMATMOD_VHT: ++ rx_vect1->vht.beamformed = !rx_vect1_leg.smoothing; ++ rx_vect1->vht.fec = rx_vect1_leg.fec_coding; ++ rx_vect1->vht.length = rx_vect1_leg.ht_length | rx_vect1_leg._ht_length << 8; ++ rx_vect1->vht.mcs = rx_vect1_leg.mcs & 0x0F; ++ rx_vect1->vht.nss = rx_vect1_leg.stbc ? rx_vect1_leg.n_sts/2 : rx_vect1_leg.n_sts; ++ rx_vect1->vht.doze_not_allowed = rx_vect1_leg.doze_not_allowed; ++ rx_vect1->vht.short_gi = rx_vect1_leg.short_gi; ++ rx_vect1->vht.sounding = rx_vect1_leg.sounding; ++ rx_vect1->vht.stbc = rx_vect1_leg.stbc; ++ rx_vect1->vht.group_id = rx_vect1_leg.group_id; ++ rx_vect1->vht.partial_aid = rx_vect1_leg.partial_aid; ++ rx_vect1->vht.first_user = rx_vect1_leg.first_user; ++ break; ++ } ++ ++ if (!rx_vect2) ++ return; ++ ++ // Copy the received vector 2 locally ++ memcpy(&rx_vect2_leg, rx_vect2, sizeof(struct rx_vector_2_old)); ++ ++ // Reset it ++ memset(rx_vect2, 0, sizeof(struct rx_vector_2)); ++ ++ rx_vect2->rcpi1 = rx_vect2_leg.rcpi; ++ rx_vect2->rcpi2 = rx_vect2_leg.rcpi; ++ rx_vect2->rcpi3 = rx_vect2_leg.rcpi; ++ rx_vect2->rcpi4 = rx_vect2_leg.rcpi; ++ ++ rx_vect2->evm1 = rx_vect2_leg.evm1; ++ rx_vect2->evm2 = rx_vect2_leg.evm2; ++ rx_vect2->evm3 = rx_vect2_leg.evm3; ++ rx_vect2->evm4 = rx_vect2_leg.evm4; ++} ++ ++/** ++ * rwnx_rx_statistic - save some statistics about received frames ++ * ++ * @rwnx_hw: main driver data. ++ * @hw_rxhdr: Rx Hardware descriptor of the received frame. ++ * @sta: STA that sent the frame. ++ */ ++static void rwnx_rx_statistic(struct rwnx_hw *rwnx_hw, struct hw_rxhdr *hw_rxhdr, ++ struct rwnx_sta *sta) ++{ ++#if 1//def CONFIG_RWNX_DEBUGFS ++ struct rwnx_stats *stats = &rwnx_hw->stats; ++ struct rwnx_rx_rate_stats *rate_stats = &sta->stats.rx_rate; ++ struct rx_vector_1 *rxvect = &hw_rxhdr->hwvect.rx_vect1; ++ int mpdu, ampdu, mpdu_prev, rate_idx; ++ ++ /* save complete hwvect */ ++ sta->stats.last_rx = hw_rxhdr->hwvect; ++ ++ /* update ampdu rx stats */ ++ mpdu = hw_rxhdr->hwvect.mpdu_cnt; ++ ampdu = hw_rxhdr->hwvect.ampdu_cnt; ++ mpdu_prev = stats->ampdus_rx_map[ampdu]; ++ ++ if (mpdu_prev < mpdu) { ++ stats->ampdus_rx_miss += mpdu - mpdu_prev - 1; ++ } else { ++ stats->ampdus_rx[mpdu_prev]++; ++ } ++ stats->ampdus_rx_map[ampdu] = mpdu; ++ ++ /* update rx rate statistic */ ++ if (!rate_stats->size) ++ return; ++ ++ if (rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) { ++ int mcs; ++ int bw = rxvect->ch_bw; ++ int sgi; ++ int nss; ++ switch (rxvect->format_mod) { ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ mcs = rxvect->ht.mcs % 8; ++ nss = rxvect->ht.mcs / 8; ++ sgi = rxvect->ht.short_gi; ++ rate_idx = N_CCK + N_OFDM + nss * 32 + mcs * 4 + bw * 2 + sgi; ++ break; ++ case FORMATMOD_VHT: ++ mcs = rxvect->vht.mcs; ++ nss = rxvect->vht.nss; ++ sgi = rxvect->vht.short_gi; ++ rate_idx = N_CCK + N_OFDM + N_HT + nss * 80 + mcs * 8 + bw * 2 + sgi; ++ break; ++ case FORMATMOD_HE_SU: ++ mcs = rxvect->he.mcs; ++ nss = rxvect->he.nss; ++ sgi = rxvect->he.gi_type; ++ rate_idx = N_CCK + N_OFDM + N_HT + N_VHT + nss * 144 + mcs * 12 + bw * 3 + sgi; ++ break; ++ default: ++ mcs = rxvect->he.mcs; ++ nss = rxvect->he.nss; ++ sgi = rxvect->he.gi_type; ++ rate_idx = N_CCK + N_OFDM + N_HT + N_VHT + N_HE_SU ++ + nss * 216 + mcs * 18 + rxvect->he.ru_size * 3 + sgi; ++ break; ++ } ++ } else { ++ int idx = legrates_lut[rxvect->leg_rate].idx; ++ if (idx < 4) { ++ rate_idx = idx * 2 + rxvect->pre_type; ++ } else { ++ rate_idx = N_CCK + idx - 4; ++ } ++ } ++ if (rate_idx < rate_stats->size) { ++ if (!rate_stats->table[rate_idx]) ++ rate_stats->rate_cnt++; ++ rate_stats->table[rate_idx]++; ++ rate_stats->cpt++; ++ } else { ++ wiphy_err(rwnx_hw->wiphy, "RX: Invalid index conversion => %d/%d\n", ++ rate_idx, rate_stats->size); ++ } ++#endif ++} ++ ++/** ++ * rwnx_rx_data_skb - Process one data frame ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: vif that received the buffer ++ * @skb: skb received ++ * @rxhdr: HW rx descriptor ++ * @return: true if buffer has been forwarded to upper layer ++ * ++ * If buffer is amsdu , it is first split into a list of skb. ++ * Then each skb may be: ++ * - forwarded to upper layer ++ * - resent on wireless interface ++ * ++ * When vif is a STA interface, every skb is only forwarded to upper layer. ++ * When vif is an AP interface, multicast skb are forwarded and resent, whereas ++ * skb for other BSS's STA are only resent. ++ */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#define RAISE_RX_SOFTIRQ() \ ++ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) ++#endif /* LINUX_VERSION_CODE */ ++ ++void rwnx_rx_data_skb_resend(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *rxhdr) ++{ ++ struct sk_buff *rx_skb = skb; ++ const struct ethhdr *eth; ++ struct sk_buff *skb_copy; ++ ++ rx_skb->dev = rwnx_vif->ndev; ++ skb_reset_mac_header(rx_skb); ++ eth = eth_hdr(rx_skb); ++ ++ //printk("resend\n"); ++ /* resend pkt on wireless interface */ ++ /* always need to copy buffer when forward=0 to get enough headrom for tsdesc */ ++ skb_copy = skb_copy_expand(rx_skb, sizeof(struct rwnx_txhdr) + ++ RWNX_SWTXHDR_ALIGN_SZ + 3 + 24 + 8, 0, GFP_ATOMIC); ++ ++ if (skb_copy) { ++ int res; ++ skb_copy->protocol = htons(ETH_P_802_3); ++ skb_reset_network_header(skb_copy); ++ skb_reset_mac_header(skb_copy); ++ ++ rwnx_vif->is_resending = true; ++ res = dev_queue_xmit(skb_copy); ++ rwnx_vif->is_resending = false; ++ /* note: buffer is always consummed by dev_queue_xmit */ ++ if (res == NET_XMIT_DROP) { ++ rwnx_vif->net_stats.rx_dropped++; ++ rwnx_vif->net_stats.tx_dropped++; ++ } else if (res != NET_XMIT_SUCCESS) { ++ netdev_err(rwnx_vif->ndev, ++ "Failed to re-send buffer to driver (res=%d)", ++ res); ++ rwnx_vif->net_stats.tx_errors++; ++ } ++ } else { ++ netdev_err(rwnx_vif->ndev, "Failed to copy skb"); ++ } ++} ++ ++static void rwnx_rx_data_skb_forward(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *rxhdr) ++{ ++ struct sk_buff *rx_skb; ++ ++ rx_skb = skb; ++ rx_skb->dev = rwnx_vif->ndev; ++ skb_reset_mac_header(rx_skb); ++ ++ #ifdef CONFIG_BR_SUPPORT ++ void *br_port = NULL; ++ ++ if (1) {//(check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ /* Insert NAT2.5 RX here! */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb); ++ ++ if (nat25_handle_frame(rwnx_vif, rx_skb) == -1) { ++ /* priv->ext_stats.rx_data_drops++; */ ++ /* DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); */ ++ /* return FAIL; */ ++ ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ /* Update statistics */ ++ rwnx_vif->net_stats.rx_packets++; ++ rwnx_vif->net_stats.rx_bytes += rx_skb->len; ++ ++ //printk("forward\n"); ++ ++ rx_skb->protocol = eth_type_trans(rx_skb, rwnx_vif->ndev); ++ memset(rx_skb->cb, 0, sizeof(rx_skb->cb)); ++ REG_SW_SET_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++ #ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_hw,rx_skb->data, cpu_to_le16(rx_skb->len)); ++ #endif ++ ++ #ifdef CONFIG_RX_NETIF_RECV_SKB //modify by aic ++ local_bh_disable(); ++ netif_receive_skb(rx_skb); ++ local_bh_enable(); ++ #else ++ if (in_interrupt()) { ++ netif_rx(rx_skb); ++ } else { ++ /* ++ * If the receive is not processed inside an ISR, the softirqd must be woken explicitly to service the NET_RX_SOFTIRQ. ++ * * In 2.6 kernels, this is handledby netif_rx_ni(), but in earlier kernels, we need to do it manually. ++ */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(rx_skb); ++ #else ++ ulong flags; ++ netif_rx(rx_skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++ #endif ++ } ++ #endif ++ REG_SW_CLEAR_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++ rwnx_hw->stats.last_rx = jiffies; ++} ++ ++ ++static bool rwnx_rx_data_skb(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *rxhdr) ++{ ++ struct sk_buff_head list; ++ struct sk_buff *rx_skb; ++ bool amsdu = rxhdr->flags_is_amsdu; ++ u8 flags_dst_idx = rxhdr->flags_dst_idx; ++ bool resend = false, forward = true; ++ ++ skb->dev = rwnx_vif->ndev; ++ ++ __skb_queue_head_init(&list); ++ ++ if (amsdu) { ++ #if 1 ++ rwnx_rxdata_process_amsdu(rwnx_hw, skb, rxhdr->flags_vif_idx, &list); //rxhdr not used below since skb free! ++ #else ++ int count; ++ ieee80211_amsdu_to_8023s(skb, &list, rwnx_vif->ndev->dev_addr, ++ RWNX_VIF_TYPE(rwnx_vif), 0, NULL, NULL); ++ ++ count = skb_queue_len(&list); ++ if (count > ARRAY_SIZE(rwnx_hw->stats.amsdus_rx)) ++ count = ARRAY_SIZE(rwnx_hw->stats.amsdus_rx); ++ rwnx_hw->stats.amsdus_rx[count - 1]++; ++ #endif ++ } else { ++ rwnx_hw->stats.amsdus_rx[0]++; ++ __skb_queue_head(&list, skb); ++ } ++ ++ if (((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP) || ++ (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP_VLAN) || ++ (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO)) && ++ !(rwnx_vif->ap.flags & RWNX_AP_ISOLATE)) { ++ const struct ethhdr *eth; ++ rx_skb = skb_peek(&list); ++ skb_reset_mac_header(rx_skb); ++ eth = eth_hdr(rx_skb); ++ ++ if (unlikely(is_multicast_ether_addr(eth->h_dest))) { ++ /* broadcast pkt need to be forwared to upper layer and resent ++ on wireless interface */ ++ resend = true; ++ } else { ++ /* unicast pkt for STA inside the BSS, no need to forward to upper ++ layer simply resend on wireless interface */ ++ if (flags_dst_idx != RWNX_INVALID_STA) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[flags_dst_idx]; ++ if (sta->valid && (sta->vlan_idx == rwnx_vif->vif_index)) { ++ forward = false; ++ resend = true; ++ } ++ } ++ } ++ } else if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT) { ++ const struct ethhdr *eth; ++ rx_skb = skb_peek(&list); ++ skb_reset_mac_header(rx_skb); ++ eth = eth_hdr(rx_skb); ++ ++ if (!is_multicast_ether_addr(eth->h_dest)) { ++ /* unicast pkt for STA inside the BSS, no need to forward to upper ++ layer simply resend on wireless interface */ ++ if (flags_dst_idx != RWNX_INVALID_STA) { ++ forward = false; ++ resend = true; ++ } ++ } ++ } ++ ++ while (!skb_queue_empty(&list)) { ++ rx_skb = __skb_dequeue(&list); ++ ++ /* resend pkt on wireless interface */ ++ if (resend) { ++ struct sk_buff *skb_copy; ++ /* always need to copy buffer when forward=0 to get enough headrom for tsdesc */ ++ skb_copy = skb_copy_expand(rx_skb, sizeof(struct rwnx_txhdr) + ++ RWNX_SWTXHDR_ALIGN_SZ + 3 + 24 + 8, 0, GFP_ATOMIC); ++ ++ if (skb_copy) { ++ int res; ++ skb_copy->protocol = htons(ETH_P_802_3); ++ skb_reset_network_header(skb_copy); ++ skb_reset_mac_header(skb_copy); ++ ++ rwnx_vif->is_resending = true; ++ res = dev_queue_xmit(skb_copy); ++ rwnx_vif->is_resending = false; ++ /* note: buffer is always consummed by dev_queue_xmit */ ++ if (res == NET_XMIT_DROP) { ++ rwnx_vif->net_stats.rx_dropped++; ++ rwnx_vif->net_stats.tx_dropped++; ++ } else if (res != NET_XMIT_SUCCESS) { ++ netdev_err(rwnx_vif->ndev, ++ "Failed to re-send buffer to driver (res=%d)", ++ res); ++ rwnx_vif->net_stats.tx_errors++; ++ } ++ } else { ++ netdev_err(rwnx_vif->ndev, "Failed to copy skb"); ++ } ++ } ++ ++ /* forward pkt to upper layer */ ++ if (forward) { ++ #ifdef CONFIG_BR_SUPPORT ++ void *br_port = NULL; ++ ++ if (1) {//(check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ /* Insert NAT2.5 RX here! */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb); ++ ++ if (nat25_handle_frame(rwnx_vif, rx_skb) == -1) { ++ /* priv->ext_stats.rx_data_drops++; */ ++ /* DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); */ ++ /* return FAIL; */ ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ /* Update statistics */ ++ rwnx_vif->net_stats.rx_packets++; ++ rwnx_vif->net_stats.rx_bytes += rx_skb->len; ++ ++ rx_skb->protocol = eth_type_trans(rx_skb, rwnx_vif->ndev); ++#ifdef AICWF_ARP_OFFLOAD ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) ++ arpoffload_proc(rx_skb, rwnx_vif); ++#endif ++ memset(rx_skb->cb, 0, sizeof(rx_skb->cb)); ++ REG_SW_SET_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_hw,rx_skb->data, cpu_to_le16(rx_skb->len)); ++#endif ++ ++ #ifdef CONFIG_RX_NETIF_RECV_SKB //modify by aic ++ local_bh_disable(); ++ netif_receive_skb(rx_skb); ++ local_bh_enable(); ++ #else ++ if (in_interrupt()) { ++ netif_rx(rx_skb); ++ } else { ++ /* ++ * If the receive is not processed inside an ISR, the softirqd must be woken explicitly to service the NET_RX_SOFTIRQ. ++ * * In 2.6 kernels, this is handledby netif_rx_ni(), but in earlier kernels, we need to do it manually. ++ */ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(rx_skb); ++ #else ++ ulong flags; ++ netif_rx(rx_skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++ #endif ++ } ++ #endif ++ REG_SW_CLEAR_PROFILING(rwnx_hw, SW_PROF_IEEE80211RX); ++ ++ rwnx_hw->stats.last_rx = jiffies; ++ } ++ } ++ ++ return forward; ++} ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) ++const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len, ++ const u8 *match, int match_len, ++ int match_offset) ++{ ++ const struct element *elem; ++ ++ /* 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; ++ ++ for_each_element_id(elem, eid, ies, len) { ++ if (elem->datalen >= match_offset - 2 + match_len && ++ !memcmp(elem->data + match_offset - 2, match, match_len)) ++ return (void *)elem; ++ } ++ ++ return NULL; ++} ++#endif ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) ++static inline const u8 *cfg80211_find_ext_ie(u8 ext_eid, const u8* ies, int len) ++{ ++ return cfg80211_find_ie_match(WLAN_EID_EXTENSION, ies, len, ++ &ext_eid, 1, 2); ++} ++#endif ++#endif ++ ++ ++/** ++ * rwnx_rx_mgmt - Process one 802.11 management frame ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: vif to upload the buffer to ++ * @skb: skb received ++ * @rxhdr: HW rx descriptor ++ * ++ * Forward the management frame to a given interface. ++ */ ++static void rwnx_rx_mgmt(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *hw_rxhdr) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; ++ struct rx_vector_1 *rxvect = &hw_rxhdr->hwvect.rx_vect1; ++ ++ //printk("rwnx_rx_mgmt\n"); ++ ++#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) ++ struct aic_sta *sta = &rwnx_hw->aic_table[rwnx_vif->ap.aic_index]; ++ const u8* ie; ++ u32 len; ++ ++ if(skb->data[0]!=0x80) ++ AICWFDBG(LOGDEBUG,"rxmgmt:%x,%x\n", skb->data[0], skb->data[1]); ++ ++ if (ieee80211_is_assoc_req(mgmt->frame_control) && rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) { ++ printk("ASSOC_REQ: sta_idx %d MAC %pM\n", rwnx_vif->ap.aic_index, mgmt->sa); ++ sta->sta_idx = rwnx_vif->ap.aic_index; ++ len = skb->len - (mgmt->u.assoc_req.variable - skb->data); ++ ++ #ifdef CONFIG_HE_FOR_OLD_KERNEL ++ struct ieee80211_he_cap_elem *he; ++ struct ieee80211_he_mcs_nss_supp *he_mcs; ++ ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, mgmt->u.assoc_req.variable, len); ++ if (ie && ie[1] >= sizeof(*he) + 1) { ++ printk("assoc_req: find he\n"); ++ he = (struct ieee80211_he_cap_elem *)(ie+3); ++ he_mcs = (struct ieee80211_he_mcs_nss_supp *)((u8 *)he + sizeof(*he)); ++ memcpy(&sta->he_cap_elem,ie+3,sizeof(struct ieee80211_he_cap_elem)); ++ ++ sta->he_mcs_nss_supp.rx_mcs_80 = he_mcs->rx_mcs_80; ++ sta->he_mcs_nss_supp.tx_mcs_80 = he_mcs->tx_mcs_80; ++ sta->he = true; ++ } ++ else { ++ printk("assoc_req: no find he\n"); ++ sta->he = false; ++ } ++ #endif ++ ++ #ifdef CONFIG_VHT_FOR_OLD_KERNEL ++ struct ieee80211_vht_cap *vht; ++ ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.assoc_req.variable, len); ++ if (ie && ie[1] >= sizeof(*vht)) { ++ printk("assoc_req: find vht\n"); ++ memcpy(&sta->vht_cap_info,ie+2,4); ++ memcpy(&sta->supp_mcs,ie+2+4,sizeof(struct ieee80211_vht_mcs_info)); ++ sta->vht = true; ++ } else { ++ printk("assoc_req: no find vht\n"); ++ sta->vht = false; ++ } ++ #endif ++ } ++#endif ++ ++ /*if (ieee80211_is_mgmt(mgmt->frame_control) && ++ (skb->len <= 24 || skb->len > 768)) { ++ printk("mgmt err\n"); ++ return; ++ }*/ ++ if (ieee80211_is_beacon(mgmt->frame_control)) { ++ if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MESH_POINT) && ++ hw_rxhdr->flags_new_peer) { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ GFP_ATOMIC); ++#else ++ cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ GFP_ATOMIC); ++#endif ++#else ++ ++#ifdef CONFIG_GKI ++ /* TODO: the value of parameter sig_dbm need to be confirmed */ ++ rwnx_cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ rxvect->rssi1, GFP_ATOMIC); ++#else ++ /* TODO: the value of parameter sig_dbm need to be confirmed */ ++ cfg80211_notify_new_peer_candidate(rwnx_vif->ndev, mgmt->sa, ++ mgmt->u.beacon.variable, ++ skb->len - offsetof(struct ieee80211_mgmt, ++ u.beacon.variable), ++ rxvect->rssi1, GFP_ATOMIC); ++#endif ++ ++#endif ++ } else { ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_report_obss_beacon(rwnx_hw->wiphy, skb->data, skb->len, ++ hw_rxhdr->phy_info.phy_prim20_freq, ++ rxvect->rssi1); ++#else ++ cfg80211_report_obss_beacon(rwnx_hw->wiphy, skb->data, skb->len, ++ hw_rxhdr->phy_info.phy_prim20_freq, ++ rxvect->rssi1); ++#endif ++ } ++ } else if ((ieee80211_is_deauth(mgmt->frame_control) || ++ ieee80211_is_disassoc(mgmt->frame_control)) && ++ (mgmt->u.deauth.reason_code == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA || ++ mgmt->u.deauth.reason_code == WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)) { ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) // TODO: process unprot mgmt ++ cfg80211_rx_unprot_mlme_mgmt(rwnx_vif->ndev, skb->data, skb->len); ++ #endif ++ } else if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION) && ++ (ieee80211_is_action(mgmt->frame_control) && ++ (mgmt->u.action.category == 6))) { ++ struct cfg80211_ft_event_params ft_event; ++ ft_event.target_ap = (uint8_t *)&mgmt->u.action + ETH_ALEN + 2; ++ ft_event.ies = (uint8_t *)&mgmt->u.action + ETH_ALEN * 2 + 2; ++ ft_event.ies_len = skb->len - (ft_event.ies - (uint8_t *)mgmt); ++ ft_event.ric_ies = NULL; ++ ft_event.ric_ies_len = 0; ++ cfg80211_ft_event(rwnx_vif->ndev, &ft_event); ++ } else { ++ cfg80211_rx_mgmt(&rwnx_vif->wdev, hw_rxhdr->phy_info.phy_prim20_freq, ++ rxvect->rssi1, skb->data, skb->len, 0); ++ } ++} ++ ++/** ++ * rwnx_rx_mgmt_any - Process one 802.11 management frame ++ * ++ * @rwnx_hw: main driver data ++ * @skb: skb received ++ * @rxhdr: HW rx descriptor ++ * ++ * Process the management frame and free the corresponding skb. ++ * If vif is not specified in the rx descriptor, the the frame is uploaded ++ * on all active vifs. ++ */ ++static void rwnx_rx_mgmt_any(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, ++ struct hw_rxhdr *hw_rxhdr) ++{ ++ struct rwnx_vif *rwnx_vif; ++ int vif_idx = hw_rxhdr->flags_vif_idx; ++#ifdef CREATE_TRACE_POINTS ++ trace_mgmt_rx(hw_rxhdr->phy_info.phy_prim20_freq, vif_idx, ++ hw_rxhdr->flags_sta_idx, (struct ieee80211_mgmt *)skb->data); ++#endif ++ if (vif_idx == RWNX_INVALID_VIF) { ++ list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { ++ if (!rwnx_vif->up) ++ continue; ++ rwnx_rx_mgmt(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } ++ } else { ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, vif_idx); ++ if (rwnx_vif) ++ rwnx_rx_mgmt(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } ++ ++ dev_kfree_skb(skb); ++} ++ ++/** ++ * rwnx_rx_rtap_hdrlen - Return radiotap header length ++ * ++ * @rxvect: Rx vector used to fill the radiotap header ++ * @has_vend_rtap: boolean indicating if vendor specific data is present ++ * ++ * Compute the length of the radiotap header based on @rxvect and vendor ++ * specific data (if any). ++ */ ++static u8 rwnx_rx_rtap_hdrlen(struct rx_vector_1 *rxvect, ++ bool has_vend_rtap) ++{ ++ u8 rtap_len; ++ ++ /* Compute radiotap header length */ ++ rtap_len = sizeof(struct ieee80211_radiotap_header) + 8; ++ ++ // Check for multiple antennas ++ if (hweight32(rxvect->antenna_set) > 1) ++ // antenna and antenna signal fields ++ rtap_len += 4 * hweight8(rxvect->antenna_set); ++ ++ // TSFT ++ if (!has_vend_rtap) { ++ rtap_len = ALIGN(rtap_len, 8); ++ rtap_len += 8; ++ } ++ ++ // IEEE80211_HW_SIGNAL_DBM ++ rtap_len++; ++ ++ // Check if single antenna ++ if (hweight32(rxvect->antenna_set) == 1) ++ rtap_len++; //Single antenna ++ ++ // padding for RX FLAGS ++ rtap_len = ALIGN(rtap_len, 2); ++ ++ // Check for HT frames ++ if ((rxvect->format_mod == FORMATMOD_HT_MF) || ++ (rxvect->format_mod == FORMATMOD_HT_GF)) ++ rtap_len += 3; ++ ++ // Check for AMPDU ++ if (!(has_vend_rtap) && ((rxvect->format_mod >= FORMATMOD_VHT) || ++ ((rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) && ++ (rxvect->ht.aggregation)))) { ++ rtap_len = ALIGN(rtap_len, 4); ++ rtap_len += 8; ++ } ++ ++ // Check for VHT frames ++ if (rxvect->format_mod == FORMATMOD_VHT) { ++ rtap_len = ALIGN(rtap_len, 2); ++ rtap_len += 12; ++ } ++ ++ // Check for HE frames ++ if (rxvect->format_mod == FORMATMOD_HE_SU) { ++ rtap_len = ALIGN(rtap_len, 2); ++ rtap_len += sizeof(struct ieee80211_radiotap_he); ++ } ++ ++ // Check for multiple antennas ++ if (hweight32(rxvect->antenna_set) > 1) { ++ // antenna and antenna signal fields ++ rtap_len += 2 * hweight8(rxvect->antenna_set); ++ } ++ ++ // Check for vendor specific data ++ if (has_vend_rtap) { ++ /* vendor presence bitmap */ ++ rtap_len += 4; ++ /* alignment for fixed 6-byte vendor data header */ ++ rtap_len = ALIGN(rtap_len, 2); ++ } ++ ++ return rtap_len; ++} ++ ++/** ++ * rwnx_rx_add_rtap_hdr - Add radiotap header to sk_buff ++ * ++ * @rwnx_hw: main driver data ++ * @skb: skb received (will include the radiotap header) ++ * @rxvect: Rx vector ++ * @phy_info: Information regarding the phy ++ * @hwvect: HW Info (NULL if vendor specific data is available) ++ * @rtap_len: Length of the radiotap header ++ * @vend_rtap_len: radiotap vendor length (0 if not present) ++ * @vend_it_present: radiotap vendor present ++ * ++ * Builds a radiotap header and add it to @skb. ++ */ ++static void rwnx_rx_add_rtap_hdr(struct rwnx_hw *rwnx_hw, ++ struct sk_buff *skb, ++ struct rx_vector_1 *rxvect, ++ struct phy_channel_info_desc *phy_info, ++ struct hw_vect *hwvect, ++ int rtap_len, ++ u8 vend_rtap_len, ++ u32 vend_it_present) ++{ ++ struct ieee80211_radiotap_header *rtap; ++ u8 *pos, rate_idx; ++ __le32 *it_present; ++ u32 it_present_val = 0; ++ bool fec_coding = false; ++ bool short_gi = false; ++ bool stbc = false; ++ bool aggregation = false; ++ ++ rtap = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); ++ memset((u8 *) rtap, 0, rtap_len); ++ ++ rtap->it_version = 0; ++ rtap->it_pad = 0; ++ rtap->it_len = cpu_to_le16(rtap_len + vend_rtap_len); ++ ++ it_present = &rtap->it_present; ++ ++ // Check for multiple antennas ++ if (hweight32(rxvect->antenna_set) > 1) { ++ int chain; ++ unsigned long chains = rxvect->antenna_set; ++ ++ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { ++ it_present_val |= ++ BIT(IEEE80211_RADIOTAP_EXT) | ++ BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE); ++ put_unaligned_le32(it_present_val, it_present); ++ it_present++; ++ it_present_val = BIT(IEEE80211_RADIOTAP_ANTENNA) | ++ BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); ++ } ++ } ++ ++ // Check if vendor specific data is present ++ if (vend_rtap_len) { ++ it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | ++ BIT(IEEE80211_RADIOTAP_EXT); ++ put_unaligned_le32(it_present_val, it_present); ++ it_present++; ++ it_present_val = vend_it_present; ++ } ++ ++ put_unaligned_le32(it_present_val, it_present); ++ pos = (void *)(it_present + 1); ++ ++ // IEEE80211_RADIOTAP_TSFT ++ if (hwvect) { ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); ++ // padding ++ while ((pos - (u8 *)rtap) & 7) ++ *pos++ = 0; ++ put_unaligned_le64((((u64)le32_to_cpu(hwvect->tsf_hi) << 32) + ++ (u64)le32_to_cpu(hwvect->tsf_lo)), pos); ++ pos += 8; ++ } ++ ++ // IEEE80211_RADIOTAP_FLAGS ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_FLAGS); ++ if (hwvect && (!hwvect->frm_successful_rx)) ++ *pos |= IEEE80211_RADIOTAP_F_BADFCS; ++ if (!rxvect->pre_type ++ && (rxvect->format_mod <= FORMATMOD_NON_HT_DUP_OFDM)) ++ *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; ++ pos++; ++ ++ // IEEE80211_RADIOTAP_RATE ++ // check for HT, VHT or HE frames ++ if (rxvect->format_mod >= FORMATMOD_HE_SU) { ++ rate_idx = rxvect->he.mcs; ++ fec_coding = rxvect->he.fec; ++ stbc = rxvect->he.stbc; ++ aggregation = true; ++ *pos = 0; ++ } else if (rxvect->format_mod == FORMATMOD_VHT) { ++ rate_idx = rxvect->vht.mcs; ++ fec_coding = rxvect->vht.fec; ++ short_gi = rxvect->vht.short_gi; ++ stbc = rxvect->vht.stbc; ++ aggregation = true; ++ *pos = 0; ++ } else if (rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) { ++ rate_idx = rxvect->ht.mcs; ++ fec_coding = rxvect->ht.fec; ++ short_gi = rxvect->ht.short_gi; ++ stbc = rxvect->ht.stbc; ++ aggregation = rxvect->ht.aggregation; ++ *pos = 0; ++ } else { ++ struct ieee80211_supported_band *band = ++ rwnx_hw->wiphy->bands[phy_info->phy_band]; ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); ++ BUG_ON((rate_idx = legrates_lut[rxvect->leg_rate].idx) == -1); ++ if (phy_info->phy_band == NL80211_BAND_5GHZ) ++ rate_idx -= 4; /* rwnx_ratetable_5ghz[0].hw_value == 4 */ ++ *pos = DIV_ROUND_UP(band->bitrates[rate_idx].bitrate, 5); ++ } ++ pos++; ++ ++ // IEEE80211_RADIOTAP_CHANNEL ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CHANNEL); ++ put_unaligned_le16(phy_info->phy_prim20_freq, pos); ++ pos += 2; ++ ++ if (phy_info->phy_band == NL80211_BAND_5GHZ) ++ put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, pos); ++ else if (rxvect->format_mod > FORMATMOD_NON_HT_DUP_OFDM) ++ put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, pos); ++ else ++ put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, pos); ++ pos += 2; ++ ++ if (hweight32(rxvect->antenna_set) == 1) { ++ // IEEE80211_RADIOTAP_DBM_ANTSIGNAL ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); ++ *pos++ = rxvect->rssi1; ++ ++ // IEEE80211_RADIOTAP_ANTENNA ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_ANTENNA); ++ *pos++ = rxvect->antenna_set; ++ } ++ ++ // IEEE80211_RADIOTAP_LOCK_QUALITY is missing ++ // IEEE80211_RADIOTAP_DB_ANTNOISE is missing ++ ++ // IEEE80211_RADIOTAP_RX_FLAGS ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RX_FLAGS); ++ // 2 byte alignment ++ if ((pos - (u8 *)rtap) & 1) ++ *pos++ = 0; ++ put_unaligned_le16(0, pos); ++ //Right now, we only support fcs error (no RX_FLAG_FAILED_PLCP_CRC) ++ pos += 2; ++ ++ // Check if HT ++ if ((rxvect->format_mod == FORMATMOD_HT_MF) ++ || (rxvect->format_mod == FORMATMOD_HT_GF)) { ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); ++ *pos++ = IEEE80211_RADIOTAP_MCS_HAVE_MCS | ++ IEEE80211_RADIOTAP_MCS_HAVE_GI | ++ IEEE80211_RADIOTAP_MCS_HAVE_BW; ++ *pos = 0; ++ if (short_gi) ++ *pos |= IEEE80211_RADIOTAP_MCS_SGI; ++ if (rxvect->ch_bw == PHY_CHNL_BW_40) ++ *pos |= IEEE80211_RADIOTAP_MCS_BW_40; ++ if (rxvect->format_mod == FORMATMOD_HT_GF) ++ *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; ++ if (fec_coding) ++ *pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC; ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ *pos++ |= stbc << 5; ++ #else ++ *pos++ |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; ++ #endif ++ *pos++ = rate_idx; ++ } ++ ++ // check for HT or VHT frames ++ if (aggregation && hwvect) { ++ // 4 byte alignment ++ while ((pos - (u8 *)rtap) & 3) ++ pos++; ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); ++ put_unaligned_le32(hwvect->ampdu_cnt, pos); ++ pos += 4; ++ put_unaligned_le32(0, pos); ++ pos += 4; ++ } ++ ++ // Check for VHT frames ++ if (rxvect->format_mod == FORMATMOD_VHT) { ++ u16 vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | ++ IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; ++ u8 vht_nss = rxvect->vht.nss + 1; ++ ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); ++ ++ if ((rxvect->ch_bw == PHY_CHNL_BW_160) ++ && phy_info->phy_center2_freq) ++ vht_details &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; ++ put_unaligned_le16(vht_details, pos); ++ pos += 2; ++ ++ // flags ++ if (short_gi) ++ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; ++ if (stbc) ++ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; ++ pos++; ++ ++ // bandwidth ++ if (rxvect->ch_bw == PHY_CHNL_BW_40) ++ *pos++ = 1; ++ if (rxvect->ch_bw == PHY_CHNL_BW_80) ++ *pos++ = 4; ++ else if ((rxvect->ch_bw == PHY_CHNL_BW_160) ++ && phy_info->phy_center2_freq) ++ *pos++ = 0; //80P80 ++ else if (rxvect->ch_bw == PHY_CHNL_BW_160) ++ *pos++ = 11; ++ else // 20 MHz ++ *pos++ = 0; ++ ++ // MCS/NSS ++ *pos = (rate_idx << 4) | vht_nss; ++ pos += 4; ++ if (fec_coding) ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++ *pos |= 0x01; ++ #else ++ *pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0; ++ #endif ++ pos++; ++ // group ID ++ pos++; ++ // partial_aid ++ pos += 2; ++ } ++ ++ // Check for HE frames ++ if (rxvect->format_mod == FORMATMOD_HE_SU) { ++ struct ieee80211_radiotap_he he; ++ #define HE_PREP(f, val) cpu_to_le16(FIELD_PREP(IEEE80211_RADIOTAP_HE_##f, val)) ++ #define D1_KNOWN(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_##f##_KNOWN) ++ #define D2_KNOWN(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_##f##_KNOWN) ++ ++ he.data1 = D1_KNOWN(DATA_MCS) | D1_KNOWN(BSS_COLOR) | D1_KNOWN(BEAM_CHANGE) | ++ D1_KNOWN(UL_DL) | D1_KNOWN(CODING) | D1_KNOWN(STBC) | ++ D1_KNOWN(BW_RU_ALLOC) | D1_KNOWN(DOPPLER) | D1_KNOWN(DATA_DCM); ++ he.data2 = D2_KNOWN(GI) | D2_KNOWN(TXBF); ++ ++ if (stbc) { ++ he.data6 |= HE_PREP(DATA6_NSTS, 2); ++ he.data3 |= HE_PREP(DATA3_STBC, 1); ++ } else { ++ he.data6 |= HE_PREP(DATA6_NSTS, rxvect->he.nss); ++ } ++ ++ he.data3 |= HE_PREP(DATA3_BSS_COLOR, rxvect->he.bss_color); ++ he.data3 |= HE_PREP(DATA3_BEAM_CHANGE, rxvect->he.beam_change); ++ he.data3 |= HE_PREP(DATA3_UL_DL, rxvect->he.uplink_flag); ++ he.data3 |= HE_PREP(DATA3_BSS_COLOR, rxvect->he.bss_color); ++ he.data3 |= HE_PREP(DATA3_DATA_MCS, rxvect->he.mcs); ++ he.data3 |= HE_PREP(DATA3_DATA_DCM, rxvect->he.dcm); ++ he.data3 |= HE_PREP(DATA3_CODING, rxvect->he.fec); ++ ++ he.data5 |= HE_PREP(DATA5_GI, rxvect->he.gi_type); ++ he.data5 |= HE_PREP(DATA5_TXBF, rxvect->he.beamformed); ++ he.data5 |= HE_PREP(DATA5_LTF_SIZE, rxvect->he.he_ltf_type + 1); ++ ++ switch (rxvect->ch_bw) { ++ case PHY_CHNL_BW_20: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ); ++ break; ++ case PHY_CHNL_BW_40: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ); ++ break; ++ case PHY_CHNL_BW_80: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ); ++ break; ++ case PHY_CHNL_BW_160: ++ he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, ++ IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ); ++ break; ++ default: ++ WARN_ONCE(1, "Invalid SU BW %d\n", rxvect->ch_bw); ++ } ++ ++ he.data6 |= HE_PREP(DATA6_DOPPLER, rxvect->he.doppler); ++ ++ /* ensure 2 byte alignment */ ++ while ((pos - (u8 *)rtap) & 1) ++ pos++; ++ rtap->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE); ++ memcpy(pos, &he, sizeof(he)); ++ pos += sizeof(he); ++ } ++ ++ // Rx Chains ++ if (hweight32(rxvect->antenna_set) > 1) { ++ int chain; ++ unsigned long chains = rxvect->antenna_set; ++ u8 rssis[4] = {rxvect->rssi1, rxvect->rssi1, rxvect->rssi1, rxvect->rssi1}; ++ ++ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { ++ *pos++ = rssis[chain]; ++ *pos++ = chain; ++ } ++ } ++} ++ ++/** ++ * rwnx_rx_monitor - Build radiotap header for skb an send it to netdev ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: vif that received the buffer ++ * @skb: sk_buff received ++ * @hw_rxhdr_ptr: Pointer to HW RX header ++ * @rtap_len: Radiotap Header length ++ * ++ * Add radiotap header to the receved skb and send it to netdev ++ */ ++static int rwnx_rx_monitor(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, struct hw_rxhdr *hw_rxhdr_ptr, ++ u8 rtap_len) ++{ ++ skb->dev = rwnx_vif->ndev; ++ ++ if (rwnx_vif->wdev.iftype != NL80211_IFTYPE_MONITOR) { ++ netdev_err(rwnx_vif->ndev, "not a monitor vif\n"); ++ return -1; ++ } ++ ++ /* Add RadioTap Header */ ++ rwnx_rx_add_rtap_hdr(rwnx_hw, skb, &hw_rxhdr_ptr->hwvect.rx_vect1, ++ &hw_rxhdr_ptr->phy_info, &hw_rxhdr_ptr->hwvect, ++ rtap_len, 0, 0); ++ ++ skb_reset_mac_header(skb); ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ skb->pkt_type = PACKET_OTHERHOST; ++ skb->protocol = htons(ETH_P_802_2); ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_hw,skb->data, cpu_to_le16(skb->len)); ++#endif ++ ++ local_bh_disable(); ++ netif_receive_skb(skb); ++ local_bh_enable(); ++ ++ return 0; ++} ++ ++#ifdef AICWF_ARP_OFFLOAD ++void arpoffload_proc(struct sk_buff *skb, struct rwnx_vif *rwnx_vif) ++{ ++ struct iphdr *iphead = (struct iphdr *)(skb->data); ++ struct udphdr *udph; ++ struct DHCPInfo *dhcph; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { // IP ++ if (iphead->protocol == IPPROTO_UDP) { // UDP ++ udph = (struct udphdr *)((u8 *)iphead + (iphead->ihl << 2)); ++ if ((udph->source == __constant_htons(SERVER_PORT)) ++ && (udph->dest == __constant_htons(CLIENT_PORT))) { // DHCP offset/ack ++ dhcph = (struct DHCPInfo *)((u8 *)udph + sizeof(struct udphdr)); ++ if (dhcph->cookie == htonl(DHCP_MAGIC) && dhcph->op == 2 && ++ !memcmp(dhcph->chaddr, rwnx_vif->ndev->dev_addr, 6)) { // match magic word ++ u32 length = ntohs(udph->len) - sizeof(struct udphdr) - offsetof(struct DHCPInfo, options); ++ u16 offset = 0; ++ u8 *option = dhcph->options; ++ while (option[offset] != DHCP_OPTION_END && offset < length) { ++ if (option[offset] == DHCP_OPTION_MESSAGE_TYPE) { ++ if (option[offset+2] == DHCP_ACK) { ++ dhcped = 1; ++ AICWFDBG(LOGINFO, "paired=%x, should=%x\n", rwnx_vif->sta.paired_cipher_type, WLAN_CIPHER_SUITE_CCMP); ++ if (rwnx_vif->sta.paired_cipher_type == WLAN_CIPHER_SUITE_CCMP || \ ++ rwnx_vif->sta.paired_cipher_type == WLAN_CIPHER_SUITE_AES_CMAC || \ ++ ((rwnx_vif->sta.group_cipher_type == 0xff) && \ ++ (rwnx_vif->sta.paired_cipher_type == 0xff))) ++ rwnx_send_arpoffload_en_req(rwnx_vif->rwnx_hw, rwnx_vif, dhcph->yiaddr, 1); ++ else ++ rwnx_send_arpoffload_en_req(rwnx_vif->rwnx_hw, rwnx_vif, dhcph->yiaddr, 0); ++ } ++ } ++ offset += 2 + option[offset+1]; ++ } ++ } ++ } ++ } ++ } ++} ++#endif ++ ++#ifdef AICWF_RX_REORDER ++void reord_rxframe_free(spinlock_t *lock, struct list_head *q, struct list_head *list) ++{ ++ spin_lock_bh(lock); ++ list_add(list, q); ++ spin_unlock_bh(lock); ++} ++ ++struct recv_msdu *reord_rxframe_alloc(spinlock_t *lock, struct list_head *q) ++{ ++ struct recv_msdu *rxframe; ++ ++ spin_lock_bh(lock); ++ if (list_empty(q)) { ++ spin_unlock_bh(lock); ++ return NULL; ++ } ++ rxframe = list_entry(q->next, struct recv_msdu, rxframe_list); ++ list_del_init(q->next); ++ spin_unlock_bh(lock); ++ return rxframe; ++} ++ ++struct reord_ctrl_info *reord_init_sta(struct aicwf_rx_priv *rx_priv, const u8 *mac_addr) ++{ ++ u8 i = 0; ++ struct reord_ctrl *preorder_ctrl = NULL; ++ struct reord_ctrl_info *reord_info; ++#ifdef AICWF_SDIO_SUPPORT ++ struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; ++#else ++ struct aicwf_bus *bus_if = rx_priv->usbdev->bus_if; ++#endif ++ ++ if (bus_if->state == BUS_DOWN_ST || rx_priv == NULL) { ++ AICWFDBG(LOGERROR, "bad stat!\n"); ++ return NULL; ++ } ++ ++ AICWFDBG(LOGINFO, "reord_init_sta:%pM\n", mac_addr); ++ reord_info = kmalloc(sizeof(struct reord_ctrl_info), GFP_ATOMIC); ++ if (!reord_info) ++ return NULL; ++ ++ memcpy(reord_info->mac_addr, mac_addr, ETH_ALEN); ++ for (i = 0; i < 8; i++) { ++ preorder_ctrl = &reord_info->preorder_ctrl[i]; ++ preorder_ctrl->enable = true; ++ preorder_ctrl->ind_sn = 0xffff; ++ preorder_ctrl->wsize_b = AICWF_REORDER_WINSIZE; ++ preorder_ctrl->rx_priv = rx_priv; ++ INIT_LIST_HEAD(&preorder_ctrl->reord_list); ++ spin_lock_init(&preorder_ctrl->reord_list_lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ init_timer(&preorder_ctrl->reord_timer); ++ preorder_ctrl->reord_timer.data = (ulong) preorder_ctrl; ++ preorder_ctrl->reord_timer.function = reord_timeout_handler; ++#else ++ timer_setup(&preorder_ctrl->reord_timer, reord_timeout_handler, 0); ++#endif ++ INIT_WORK(&preorder_ctrl->reord_timer_work, reord_timeout_worker); ++ } ++ ++ return reord_info; ++} ++ ++int reord_flush_tid(struct aicwf_rx_priv *rx_priv, struct sk_buff *skb, u8 tid) ++{ ++ struct reord_ctrl_info *reord_info; ++ struct reord_ctrl *preorder_ctrl; ++ struct rwnx_vif *rwnx_vif = (struct rwnx_vif *)rx_priv->rwnx_vif; ++ struct ethhdr *eh = (struct ethhdr *)(skb->data); ++ u8 *mac; ++ unsigned long flags; ++ u8 found = 0; ++ struct list_head *phead, *plist; ++ struct recv_msdu *prframe; ++ int ret; ++ ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) ++ mac = eh->h_dest; ++ else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) ++ mac = eh->h_source; ++ else { ++ AICWFDBG(LOGERROR, "error mode:%d!\n", rwnx_vif->wdev.iftype); ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry(reord_info, &rx_priv->stas_reord_list, list) { ++ if (!memcmp(mac, reord_info->mac_addr, ETH_ALEN)) { ++ found = 1; ++ preorder_ctrl = &reord_info->preorder_ctrl[tid]; ++ break; ++ } ++ } ++ if (!found) { ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ return 0; ++ } ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ ++ if (preorder_ctrl->enable == false) ++ return 0; ++ spin_lock_irqsave(&preorder_ctrl->reord_list_lock, flags); ++ phead = &preorder_ctrl->reord_list; ++ while (1) { ++ if (list_empty(phead)) { ++ break; ++ } ++ plist = phead->next; ++ prframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ reord_single_frame_ind(rx_priv, prframe); ++ list_del_init(&(prframe->reord_pending_list)); ++ } ++ ++ AICWFDBG(LOGINFO, "flush:tid=%d", tid); ++ preorder_ctrl->enable = false; ++ spin_unlock_irqrestore(&preorder_ctrl->reord_list_lock, flags); ++ if (timer_pending(&preorder_ctrl->reord_timer)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete_sync(&preorder_ctrl->reord_timer); ++#else ++ ret = del_timer_sync(&preorder_ctrl->reord_timer); ++#endif ++ cancel_work_sync(&preorder_ctrl->reord_timer_work); ++ ++ return 0; ++} ++ ++ ++void reord_deinit_sta(struct aicwf_rx_priv *rx_priv, struct reord_ctrl_info *reord_info) ++{ ++ u8 i = 0; ++ unsigned long flags; ++ struct reord_ctrl *preorder_ctrl = NULL; ++ int ret; ++ ++ if (rx_priv == NULL) { ++ txrx_err("bad rx_priv!\n"); ++ return; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ struct recv_msdu *req, *next; ++ preorder_ctrl = &reord_info->preorder_ctrl[i]; ++ if(preorder_ctrl->enable){ ++ preorder_ctrl->enable = false; ++ if (timer_pending(&preorder_ctrl->reord_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete_sync(&preorder_ctrl->reord_timer); ++#else ++ ret = del_timer_sync(&preorder_ctrl->reord_timer); ++#endif ++ } ++ cancel_work_sync(&preorder_ctrl->reord_timer_work); ++ } ++ spin_lock_irqsave(&preorder_ctrl->reord_list_lock, flags); ++ list_for_each_entry_safe(req, next, &preorder_ctrl->reord_list, reord_pending_list) { ++ list_del_init(&req->reord_pending_list); ++ if (req->pkt != NULL) ++ dev_kfree_skb(req->pkt); ++ req->pkt = NULL; ++ reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &req->rxframe_list); ++ } ++ spin_unlock_irqrestore(&preorder_ctrl->reord_list_lock, flags); ++ ++ } ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_del(&reord_info->list); ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ kfree(reord_info); ++} ++ ++int reord_single_frame_ind(struct aicwf_rx_priv *rx_priv, struct recv_msdu *prframe) ++{ ++ struct list_head *rxframes_freequeue = NULL; ++ struct sk_buff *skb = NULL; ++ struct rwnx_vif *rwnx_vif = (struct rwnx_vif *)rx_priv->rwnx_vif; ++ struct sk_buff_head list; ++ struct sk_buff *rx_skb; ++ ++ rxframes_freequeue = &rx_priv->rxframes_freequeue; ++ skb = prframe->pkt; ++ ++ #ifdef CONFIG_BR_SUPPORT ++ void *br_port = NULL; ++ ++ if (1) {//(check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ /* Insert NAT2.5 RX here! */ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb); ++ ++ if (nat25_handle_frame(rwnx_vif, skb) == -1) { ++ /* priv->ext_stats.rx_data_drops++; */ ++ /* DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); */ ++ /* return FAIL; */ ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ if (skb == NULL) { ++ txrx_err("skb is NULL\n"); ++ return -1; ++ } ++ ++ if(!prframe->forward) { ++ //printk("single: %d not forward: drop\n", prframe->seq_num); ++ dev_kfree_skb(skb); ++ prframe->pkt = NULL; ++ reord_rxframe_free(&rx_priv->freeq_lock, rxframes_freequeue, &prframe->rxframe_list); ++ return 0; ++ } ++ ++ //skb->data = prframe->rx_data; ++ //skb_set_tail_pointer(skb, prframe->len); ++ //skb->len = prframe->len; ++ __skb_queue_head_init(&list); ++ //printk("sg:%d\n", prframe->is_amsdu); ++ if(prframe->is_amsdu) { ++ rwnx_rxdata_process_amsdu(rwnx_vif->rwnx_hw, skb, rwnx_vif->vif_index, &list); //rxhdr not used below since skb free! ++ } else { ++ __skb_queue_head(&list, skb); ++ } ++ ++ ++ while (!skb_queue_empty(&list)) { ++ rx_skb = __skb_dequeue(&list); ++ ++ rwnx_vif->net_stats.rx_packets++; ++ rwnx_vif->net_stats.rx_bytes += rx_skb->len; ++ //printk("netif sn=%d, len=%d\n", precv_frame->attrib.seq_num, skb->len); ++ ++ rx_skb->dev = rwnx_vif->ndev; ++ rx_skb->protocol = eth_type_trans(rx_skb, rwnx_vif->ndev); ++ ++#ifdef AICWF_ARP_OFFLOAD ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ arpoffload_proc(rx_skb, rwnx_vif); ++ } ++#endif ++ memset(rx_skb->cb, 0, sizeof(rx_skb->cb)); ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ filter_rx_tcp_ack(rwnx_vif->rwnx_hw,rx_skb->data, cpu_to_le16(rx_skb->len)); ++#endif ++ ++#ifdef CONFIG_RX_NETIF_RECV_SKB//AIDEN test ++ local_bh_disable(); ++ netif_receive_skb(rx_skb); ++ local_bh_enable(); ++#else ++ if (in_interrupt()) { ++ netif_rx(rx_skb); ++ } else { ++ /* ++ * If the receive is not processed inside an ISR, the softirqd must be woken explicitly to service the NET_RX_SOFTIRQ. ++ * * In 2.6 kernels, this is handledby netif_rx_ni(), but in earlier kernels, we need to do it manually. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(rx_skb); ++#else ++ ulong flags; ++ netif_rx(rx_skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++#endif ++ } ++#endif /* CONFIG_RX_NETIF_RECV_SKB */ ++ } ++ ++ prframe->pkt = NULL; ++ reord_rxframe_free(&rx_priv->freeq_lock, rxframes_freequeue, &prframe->rxframe_list); ++ ++ return 0; ++} ++ ++bool reord_rxframes_process(struct aicwf_rx_priv *rx_priv, struct reord_ctrl *preorder_ctrl, int bforced) ++{ ++ struct list_head *phead, *plist; ++ struct recv_msdu *prframe; ++ bool bPktInBuf = false; ++ ++ if (bforced == true) { ++ phead = &preorder_ctrl->reord_list; ++ if (list_empty(phead)) { ++ return false; ++ } ++ ++ plist = phead->next; ++ prframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ preorder_ctrl->ind_sn = prframe->seq_num; ++ } ++ ++ phead = &preorder_ctrl->reord_list; ++ if (list_empty(phead)) { ++ return bPktInBuf; ++ } ++ ++ list_for_each_entry(prframe, phead, reord_pending_list) { ++ if (!SN_LESS(preorder_ctrl->ind_sn, prframe->seq_num)) { ++ if (SN_EQUAL(preorder_ctrl->ind_sn, prframe->seq_num)) { ++ preorder_ctrl->ind_sn = (preorder_ctrl->ind_sn + 1) & 0xFFF; ++ } ++ } else { ++ bPktInBuf = true; ++ break; ++ } ++ } ++ ++ return bPktInBuf; ++} ++ ++void reord_rxframes_ind(struct aicwf_rx_priv *rx_priv, ++ struct reord_ctrl *preorder_ctrl) ++{ ++ struct list_head *phead, *plist; ++ struct recv_msdu *prframe; ++ ++ phead = &preorder_ctrl->reord_list; ++ while (1) { ++ //spin_lock_bh(&preorder_ctrl->reord_list_lock); ++ if (list_empty(phead)) { ++ // spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ break; ++ } ++ ++ plist = phead->next; ++ prframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ ++ if (!SN_LESS(preorder_ctrl->ind_sn, prframe->seq_num)) { ++ list_del_init(&(prframe->reord_pending_list)); ++ // spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ reord_single_frame_ind(rx_priv, prframe); ++ } else { ++ // spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ break; ++ } ++ } ++} ++ ++int reorder_timeout = REORDER_UPDATE_TIME; ++module_param(reorder_timeout, int, 0660); ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void reord_timeout_handler (ulong data) ++#else ++void reord_timeout_handler (struct timer_list *t) ++#endif ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ struct reord_ctrl *preorder_ctrl = (struct reord_ctrl *)data; ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ struct reord_ctrl *preorder_ctrl = timer_container_of(preorder_ctrl, t, reord_timer); ++#else ++ struct reord_ctrl *preorder_ctrl = from_timer(preorder_ctrl, t, reord_timer); ++#endif ++#endif ++ ++#if 0 //AIDEN ++ struct aicwf_rx_priv *rx_priv = preorder_ctrl->rx_priv; ++ ++ if (reord_rxframes_process(rx_priv, preorder_ctrl, true) == true) { ++ mod_timer(&preorder_ctrl->reord_timer, jiffies + msecs_to_jiffies(REORDER_UPDATE_TIME)); ++ } ++#endif ++ ++ if (!work_pending(&preorder_ctrl->reord_timer_work)) ++ schedule_work(&preorder_ctrl->reord_timer_work); ++} ++ ++void reord_timeout_worker(struct work_struct *work) ++{ ++ struct reord_ctrl *preorder_ctrl = container_of(work, struct reord_ctrl, reord_timer_work); ++ struct aicwf_rx_priv *rx_priv = preorder_ctrl->rx_priv; ++ ++ spin_lock_bh(&preorder_ctrl->reord_list_lock); ++#if 1//AIDEN ++ if (reord_rxframes_process(rx_priv, preorder_ctrl, true)==true) { ++ mod_timer(&preorder_ctrl->reord_timer, jiffies + msecs_to_jiffies(reorder_timeout/*REORDER_UPDATE_TIME*/)); ++ } ++#endif ++ ++ reord_rxframes_ind(rx_priv, preorder_ctrl); ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ ++ return ; ++} ++ ++int reord_process_unit(struct aicwf_rx_priv *rx_priv, struct sk_buff *skb, u16 seq_num, u8 tid, u8 forward, u8 is_amsdu) ++{ ++ int ret = 0; ++ u8 *mac; ++ struct recv_msdu *pframe; ++ struct reord_ctrl *preorder_ctrl; ++ struct reord_ctrl_info *reord_info; ++ struct rwnx_vif *rwnx_vif = (struct rwnx_vif *)rx_priv->rwnx_vif; ++ struct ethhdr *eh = (struct ethhdr *)(skb->data); ++ u8 *da = eh->h_dest; ++ u8 is_mcast = ((*da) & 0x01) ? 1 : 0; ++ ++ if (rwnx_vif == NULL || skb->len <= 14) { ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ pframe = reord_rxframe_alloc(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue); ++ if (!pframe) { ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ INIT_LIST_HEAD(&pframe->reord_pending_list); ++ pframe->seq_num = seq_num; ++ pframe->tid = tid; ++ pframe->rx_data = skb->data; ++ //pframe->len = skb->len; ++ pframe->pkt = skb; ++ pframe->forward = forward; ++ preorder_ctrl = pframe->preorder_ctrl; ++ pframe->is_amsdu = is_amsdu; ++ ++ if ((ntohs(eh->h_proto) == ETH_P_PAE) || is_mcast) ++ return reord_single_frame_ind(rx_priv, pframe); ++ ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) ++ mac = eh->h_dest; ++ else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) ++ mac = eh->h_source; ++ else { ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry(reord_info, &rx_priv->stas_reord_list, list) { ++ if (!memcmp(mac, reord_info->mac_addr, ETH_ALEN)) { ++ preorder_ctrl = &reord_info->preorder_ctrl[pframe->tid]; ++ break; ++ } ++ } ++ ++ if (&reord_info->list == &rx_priv->stas_reord_list) { ++ reord_info = reord_init_sta(rx_priv, mac); ++ if (!reord_info) { ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ dev_kfree_skb(skb); ++ return -1; ++ } ++ list_add_tail(&reord_info->list, &rx_priv->stas_reord_list); ++ preorder_ctrl = &reord_info->preorder_ctrl[pframe->tid]; ++ } else { ++ if (preorder_ctrl->enable == false) { ++ preorder_ctrl->enable = true; ++ preorder_ctrl->ind_sn = 0xffff; ++ preorder_ctrl->wsize_b = AICWF_REORDER_WINSIZE; ++ preorder_ctrl->rx_priv = rx_priv; ++ } ++ } ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ ++ if (preorder_ctrl->enable == false) { ++ spin_lock_bh(&preorder_ctrl->reord_list_lock); ++ preorder_ctrl->ind_sn = pframe->seq_num; ++ reord_single_frame_ind(rx_priv, pframe); ++ preorder_ctrl->ind_sn = (preorder_ctrl->ind_sn + 1)%4096; ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ return 0; ++ } ++ ++ spin_lock_bh(&preorder_ctrl->reord_list_lock); ++ if (reord_need_check(preorder_ctrl, pframe->seq_num)) { ++#if 1 ++ if(pframe->rx_data[42] == 0x80){//this is rtp package ++ if(pframe->seq_num == preorder_ctrl->ind_sn){ ++ printk("%s pframe->seq_num1:%d \r\n", __func__, pframe->seq_num); ++ reord_single_frame_ind(rx_priv, pframe);//not need to reorder ++ }else{ ++ printk("%s free pframe->seq_num:%d \r\n", __func__, pframe->seq_num); ++ if (pframe->pkt){ ++ dev_kfree_skb(pframe->pkt); ++ pframe->pkt = NULL; ++ } ++ reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &pframe->rxframe_list); ++ } ++ }else{ ++ //printk("%s pframe->seq_num2:%d \r\n", __func__, pframe->seq_num); ++ reord_single_frame_ind(rx_priv, pframe);//not need to reorder ++ } ++#else ++ reord_single_frame_ind(rx_priv, pframe);//not need to reor ++#endif ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ return 0; ++ } ++ ++ if (reord_rxframe_enqueue(preorder_ctrl, pframe)) { ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ goto fail; ++ } ++ ++ if (reord_rxframes_process(rx_priv, preorder_ctrl, false) == true) { ++ if (!timer_pending(&preorder_ctrl->reord_timer)) { ++ ret = mod_timer(&preorder_ctrl->reord_timer, jiffies + msecs_to_jiffies(reorder_timeout/*REORDER_UPDATE_TIME*/)); ++ } ++ } else { ++ if (timer_pending(&preorder_ctrl->reord_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete(&preorder_ctrl->reord_timer); ++#else ++ ret = del_timer(&preorder_ctrl->reord_timer); ++#endif ++ } ++ } ++ ++ reord_rxframes_ind(rx_priv, preorder_ctrl); ++ spin_unlock_bh(&preorder_ctrl->reord_list_lock); ++ ++ return 0; ++ ++fail: ++ if (pframe->pkt) { ++ dev_kfree_skb(pframe->pkt); ++ pframe->pkt = NULL; ++ } ++ reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &pframe->rxframe_list); ++ return ret; ++} ++ ++int reord_need_check(struct reord_ctrl *preorder_ctrl, u16 seq_num) ++{ ++ u8 wsize = preorder_ctrl->wsize_b; ++ u16 wend = (preorder_ctrl->ind_sn + wsize -1) & 0xFFF; ++ ++ if (preorder_ctrl->ind_sn == 0xFFFF) { ++ preorder_ctrl->ind_sn = seq_num; ++ } ++ ++ if (SN_LESS(seq_num, preorder_ctrl->ind_sn)) { ++ return -1; ++ } ++ ++ if (SN_EQUAL(seq_num, preorder_ctrl->ind_sn)) { ++ preorder_ctrl->ind_sn = (preorder_ctrl->ind_sn + 1) & 0xFFF; ++ } else if (SN_LESS(wend, seq_num)) { ++ if (seq_num >= (wsize-1)) ++ preorder_ctrl->ind_sn = seq_num-(wsize-1); ++ else ++ preorder_ctrl->ind_sn = 0xFFF - (wsize - (seq_num + 1)) + 1; ++ } ++ ++ return 0; ++} ++ ++int reord_rxframe_enqueue(struct reord_ctrl *preorder_ctrl, struct recv_msdu *prframe) ++{ ++ struct list_head *preord_list = &preorder_ctrl->reord_list; ++ struct list_head *phead, *plist; ++ struct recv_msdu *pnextrframe; ++ ++ phead = preord_list; ++ plist = phead->next; ++ ++ while (phead != plist) { ++ pnextrframe = list_entry(plist, struct recv_msdu, reord_pending_list); ++ if (SN_LESS(pnextrframe->seq_num, prframe->seq_num)) { ++ plist = plist->next; ++ continue; ++ } else if (SN_EQUAL(pnextrframe->seq_num, prframe->seq_num)) { ++ return -1; ++ } else { ++ break; ++ } ++ } ++ list_add_tail(&(prframe->reord_pending_list), plist); ++ ++ return 0; ++} ++#endif /* AICWF_RX_REORDER */ ++ ++void remove_sec_hdr_mgmt_frame(struct hw_rxhdr *hw_rxhdr, struct sk_buff *skb) ++{ ++ u8 hdr_len = 24; ++ u8 mgmt_header[24] = {0}; ++ ++ if (!hw_rxhdr->hwvect.ga_frame) { ++ if (((skb->data[0] & 0x0C) == 0) && (skb->data[1] & 0x40) == 0x40) { //protect management frame ++ printk("frame type %x\n", skb->data[0]); ++ if (hw_rxhdr->hwvect.decr_status == RWNX_RX_HD_DECR_CCMP128) { ++ memcpy(mgmt_header, skb->data, hdr_len); ++ skb_pull(skb, 8); ++ memcpy(skb->data, mgmt_header, hdr_len); ++ hw_rxhdr->hwvect.len -= 8; ++ } else { ++ printk("unsupport decr_status:%d\n", hw_rxhdr->hwvect.decr_status); ++ } ++ } ++ } ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++void defrag_timeout_cb(ulong data) ++#else ++void defrag_timeout_cb(struct timer_list *t) ++#endif ++{ ++ struct defrag_ctrl_info *defrag_ctrl = NULL; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ defrag_ctrl = (struct defrag_ctrl_info *)data; ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0) ++ defrag_ctrl = timer_container_of(defrag_ctrl, t, defrag_timer); ++#else ++ defrag_ctrl = from_timer(defrag_ctrl, t, defrag_timer); ++#endif ++#endif ++ ++ printk("%s:%p\r\n", __func__, defrag_ctrl); ++ spin_lock_bh(&defrag_ctrl->rwnx_hw->defrag_lock); ++ list_del_init(&defrag_ctrl->list); ++ dev_kfree_skb(defrag_ctrl->skb); ++ kfree(defrag_ctrl); ++ spin_unlock_bh(&defrag_ctrl->rwnx_hw->defrag_lock); ++} ++ ++void rwnx_rxdata_process_amsdu(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, u8 vif_idx, ++ struct sk_buff_head *list) ++{ ++ u16 len_alligned = 0; ++ u16 sublen = 0; ++ struct sk_buff *sub_skb = NULL; ++ struct rwnx_vif *rwnx_vif; ++ ++ //if (is_amsdu) ++ { ++ //skb_pull(skb, pull_len-8); ++ /* |amsdu sub1 | amsdu sub2 | ... */ ++ len_alligned = 0; ++ sublen = 0; ++ sub_skb = NULL; ++ while (skb->len > 16) { ++ sublen = (skb->data[12]<<8)|(skb->data[13]); ++ if (skb->len > (sublen+14)) ++ len_alligned = roundup(sublen + 14, 4); ++ else if (skb->len == (sublen+14)) ++ len_alligned = sublen+14; ++ else { ++ printk("accroding to amsdu: this will not happen\n"); ++ break; ++ } ++ //printk("sublen = %d, %x, %x, %x, %x\r\n", sublen,skb->data[0], skb->data[1], skb->data[12], skb->data[13]); ++#if 1 ++ sub_skb = __dev_alloc_skb(sublen - 6 + 12, GFP_ATOMIC); ++ if(!sub_skb){ ++ printk("sub_skb alloc fail:%d\n", sublen); ++ break; ++ } ++ skb_put(sub_skb, sublen - 6 + 12); ++ memcpy(sub_skb->data, skb->data, MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[6], &skb->data[6], MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[12], &skb->data[14 + 6], sublen - 6); ++ ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, vif_idx); ++ if (!rwnx_vif) { ++ printk("Frame received but no active vif (%d)", vif_idx); ++ //dev_kfree_skb(sub_skb); ++ break; ++ } ++ ++ __skb_queue_tail(list, sub_skb); ++ ++ //printk("a:%p\n", sub_skb); ++ //if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, sub_skb, hw_rxhdr)) ++ // dev_kfree_skb(sub_skb); ++#endif ++ skb_pull(skb, len_alligned); ++ } ++ //printk("af:%p\n", skb); ++ ++ dev_kfree_skb(skb); ++ //return 0; ++ } ++} ++ ++u8 rwnx_rxdataind_aicwf(struct rwnx_hw *rwnx_hw, void *hostid, void *rx_priv) ++{ ++ struct hw_rxhdr *hw_rxhdr; ++ struct rxdesc_tag *rxdesc = NULL; ++ struct rwnx_vif *rwnx_vif; ++ struct sk_buff *skb = hostid; ++ int msdu_offset = sizeof(struct hw_rxhdr) + 2; ++ u16_l status = 0; ++ struct aicwf_rx_priv *rx_priv_tmp; ++ u8 hdr_len = 24; ++ u8 ra[MAC_ADDR_LEN] = {0}; ++ u8 ta[MAC_ADDR_LEN] = {0}; ++ u8 ether_type[2] = {0}; ++ u8 pull_len = 0; ++ u16 seq_num = 0; ++ u8_l frag_num = 0; ++ u8 tid = 0; ++ u8 is_qos = 0; ++ u8 is_frag = 0; ++ struct defrag_ctrl_info *defrag_info = NULL; ++ struct defrag_ctrl_info *defrag_info_tmp = NULL; ++ struct sk_buff *skb_tmp = NULL; ++ int ret; ++ u8 sta_idx = 0; ++ u16_l frame_ctrl; ++ u8 is_amsdu = 0; ++ bool resend = false, forward = true; ++ const struct ethhdr *eth; ++ ++ hw_rxhdr = (struct hw_rxhdr *)skb->data; ++ ++#ifdef AICWF_RX_REORDER ++ if (hw_rxhdr->is_monitor_vif) { ++ status = RX_STAT_MONITOR; ++ //printk("monitor rx\n"); ++ } ++#endif ++ ++ if (hw_rxhdr->flags_upload) ++ status |= RX_STAT_FORWARD; ++ ++ /* Check if we need to delete the buffer */ ++ if (status & RX_STAT_DELETE) { ++ /* Remove the SK buffer from the rxbuf_elems table */ ++ #if 0 ++ rwnx_ipc_rxbuf_elem_pull(rwnx_hw, skb); ++ #endif ++ /* Free the buffer */ ++ dev_kfree_skb(skb); ++ goto end; ++ } ++ ++ /* Check if we need to forward the buffer coming from a monitor interface */ ++ if (status & RX_STAT_MONITOR) { ++ struct sk_buff *skb_monitor = NULL; ++ struct hw_rxhdr hw_rxhdr_copy; ++ u8 rtap_len; ++ u16 frm_len = 0; ++ ++ //Check if monitor interface exists and is open ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, rwnx_hw->monitor_vif); ++ if (!rwnx_vif) { ++ dev_err(rwnx_hw->dev, "Received monitor frame but there is no monitor interface open\n"); ++ goto check_len_update; ++ } ++ ++ rwnx_rx_vector_convert(rwnx_hw, ++ &hw_rxhdr->hwvect.rx_vect1, ++ &hw_rxhdr->hwvect.rx_vect2); ++ rtap_len = rwnx_rx_rtap_hdrlen(&hw_rxhdr->hwvect.rx_vect1, false); ++ ++ if (status == RX_STAT_MONITOR) ++ { ++ /* Remove the SK buffer from the rxbuf_elems table. It will also ++ unmap the buffer and then sync the buffer for the cpu */ ++ //rwnx_ipc_rxbuf_elem_pull(rwnx_hw, skb); ++ skb->data += (msdu_offset + 2); //sdio/usb word allign ++ ++ //Save frame length ++ frm_len = le32_to_cpu(hw_rxhdr->hwvect.len); ++ ++ // Reserve space for frame ++ skb->len = frm_len; ++ ++ //Check if there is enough space to add the radiotap header ++ if (skb_headroom(skb) > rtap_len) { ++ ++ skb_monitor = skb; ++ ++ //Duplicate the HW Rx Header to override with the radiotap header ++ memcpy(&hw_rxhdr_copy, hw_rxhdr, sizeof(hw_rxhdr_copy)); ++ ++ hw_rxhdr = &hw_rxhdr_copy; ++ } else { ++ //Duplicate the skb and extend the headroom ++ skb_monitor = skb_copy_expand(skb, rtap_len, 0, GFP_ATOMIC); ++ ++ //Reset original skb->data pointer ++ skb->data = (void*) hw_rxhdr; ++ } ++ } else { ++ #ifdef CONFIG_RWNX_MON_DATA ++ skb_monitor = skb_copy_expand(skb, rtap_len, 0, GFP_ATOMIC); ++ skb_monitor->data += (msdu_offset + 2); //sdio/usb word allign ++ ++ //Save frame length ++ frm_len = le32_to_cpu(hw_rxhdr->hwvect.len); ++ #endif ++ } ++ ++ skb_reset_tail_pointer(skb_monitor); ++ skb_monitor->len = 0; ++ skb_put(skb_monitor, frm_len); ++ ++ if (rwnx_rx_monitor(rwnx_hw, rwnx_vif, skb_monitor, hw_rxhdr, rtap_len)) ++ dev_kfree_skb(skb_monitor); ++ ++ if (status == RX_STAT_MONITOR) { ++ if (skb_monitor != skb) { ++ dev_kfree_skb(skb); ++ } ++ } ++ } ++ ++ ++check_len_update: ++ /* Check if we need to update the length */ ++ if (status & RX_STAT_LEN_UPDATE) { ++ if (rxdesc) ++ hw_rxhdr->hwvect.len = rxdesc->frame_len; ++ ++ if (status & RX_STAT_ETH_LEN_UPDATE) { ++ /* Update Length Field inside the Ethernet Header */ ++ struct ethhdr *hdr = (struct ethhdr *)((u8 *)hw_rxhdr + msdu_offset); ++ ++ if (rxdesc) ++ hdr->h_proto = htons(rxdesc->frame_len - sizeof(struct ethhdr)); ++ } ++ ++ goto end; ++ } ++ ++ /* Check if it must be discarded after informing upper layer */ ++ if (status & RX_STAT_SPURIOUS) { ++ struct ieee80211_hdr *hdr; ++ ++ hdr = (struct ieee80211_hdr *)(skb->data + msdu_offset); ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ if (rwnx_vif) { ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, GFP_ATOMIC); ++#else ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, GFP_ATOMIC); ++#else ++ cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, -1, GFP_ATOMIC); ++#endif ++#endif ++ } ++ goto end; ++ } ++ ++ /* Check if we need to forward the buffer */ ++ if (status & RX_STAT_FORWARD) { ++ rwnx_rx_vector_convert(rwnx_hw, ++ &hw_rxhdr->hwvect.rx_vect1, ++ &hw_rxhdr->hwvect.rx_vect2); ++ skb_pull(skb, msdu_offset + 2); //+2 since sdio allign 58->60 ++ ++#define MAC_FCTRL_MOREFRAG 0x0400 ++ frame_ctrl = (skb->data[1] << 8) | skb->data[0]; ++ seq_num = ((skb->data[22] & 0xf0) >> 4) | (skb->data[23] << 4); ++ frag_num = (skb->data[22] & 0x0f); ++ is_amsdu = 0; ++ ++ if ((skb->data[0] & 0x0f) == 0x08) { ++ if ((skb->data[0] & 0x80) == 0x80) {//qos data ++ hdr_len = 26; ++ tid = skb->data[24] & 0x0F; ++ is_qos = 1; ++ if (skb->data[24] & 0x80) ++ is_amsdu = 1; ++ } ++ ++ if(skb->data[1] & 0x80)// htc ++ hdr_len += 4; ++ ++ if ((skb->data[1] & 0x3) == 0x1) {// to ds ++ memcpy(ra, &skb->data[16], MAC_ADDR_LEN); ++ memcpy(ta, &skb->data[10], MAC_ADDR_LEN); ++ } else if ((skb->data[1] & 0x3) == 0x2) { //from ds ++ memcpy(ta, &skb->data[16], MAC_ADDR_LEN); ++ memcpy(ra, &skb->data[4], MAC_ADDR_LEN); ++ } ++ ++ pull_len += (hdr_len + 8); ++ ++ switch (hw_rxhdr->hwvect.decr_status) { ++ case RWNX_RX_HD_DECR_CCMP128: ++ pull_len += 8;//ccmp_header ++ //skb_pull(&skb->data[skb->len-8], 8); //ccmp_mic_len ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 8], 2); ++ break; ++ case RWNX_RX_HD_DECR_TKIP: ++ pull_len += 8;//tkip_header ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 8], 2); ++ break; ++ case RWNX_RX_HD_DECR_WEP: ++ pull_len += 4;//wep_header ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 4], 2); ++ break; ++ case RWNX_RX_HD_DECR_WAPI: ++ pull_len += 18;//wapi_header ++ memcpy(ether_type, &skb->data[hdr_len + 6 + 18], 2); ++ break; ++ ++ default: ++ memcpy(ether_type, &skb->data[hdr_len + 6], 2); ++ break; ++ } ++ if(is_amsdu) ++ hw_rxhdr->flags_is_amsdu = 1; ++ else ++ hw_rxhdr->flags_is_amsdu = 0; ++ ++ if (is_amsdu) { ++ #if 1 ++ skb_pull(skb, pull_len-8); ++ #else ++ skb_pull(skb, pull_len-8); ++ /* |amsdu sub1 | amsdu sub2 | ... */ ++ len_alligned = 0; ++ sublen = 0; ++ sub_skb = NULL; ++ //printk("is_len:%d, pull:%d\n", skb->len, pull_len); ++ while (skb->len > 16) { ++ sublen = (skb->data[12]<<8)|(skb->data[13]); ++ if (skb->len > (sublen+14)) ++ len_alligned = roundup(sublen + 14, 4); ++ else if (skb->len == (sublen+14)) ++ len_alligned = sublen+14; ++ else { ++ printk("accroding to amsdu: this will not happen\n"); ++ break; ++ } ++ //printk("sublen = %d, %x, %x, %x, %x\r\n", sublen,skb->data[0], skb->data[1], skb->data[12], skb->data[13]); ++#if 1 ++ sub_skb = __dev_alloc_skb(sublen - 6 + 12, GFP_KERNEL); ++ skb_put(sub_skb, sublen - 6 + 12); ++ memcpy(sub_skb->data, skb->data, MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[6], &skb->data[6], MAC_ADDR_LEN); ++ memcpy(&sub_skb->data[12], &skb->data[14 + 6], sublen - 6); ++ ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ if (!rwnx_vif) { ++ printk("Frame received but no active vif (%d)", hw_rxhdr->flags_vif_idx); ++ dev_kfree_skb(sub_skb); ++ break; ++ } ++ ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, sub_skb, hw_rxhdr)) ++ dev_kfree_skb(sub_skb); ++#endif ++ skb_pull(skb, len_alligned); ++ } ++ dev_kfree_skb(skb); ++ return 0; ++ #endif ++ } ++ ++ if (hw_rxhdr->flags_dst_idx != RWNX_INVALID_STA) ++ sta_idx = hw_rxhdr->flags_dst_idx; ++ ++ if (!hw_rxhdr->flags_need_reord && ((frame_ctrl & MAC_FCTRL_MOREFRAG) || frag_num)) { ++ printk("rxfrag:%d,%d,%d,sn=%d,%d\r\n", (frame_ctrl & MAC_FCTRL_MOREFRAG), frag_num, skb->len, seq_num,pull_len); ++ if (frame_ctrl & MAC_FCTRL_MOREFRAG) { ++ spin_lock_bh(&rwnx_hw->defrag_lock); ++ if (!list_empty(&rwnx_hw->defrag_list)) { ++ list_for_each_entry(defrag_info_tmp, &rwnx_hw->defrag_list, list) { ++ if ((defrag_info_tmp->sn == seq_num) && (defrag_info_tmp->tid == tid) && \ ++ defrag_info_tmp->sta_idx == sta_idx) { ++ defrag_info = defrag_info_tmp; ++ break; ++ } ++ } ++ } ++ ++ //printk("rx frag: sn=%d, fn=%d, skb->len=%d\r\n", seq_num, frag_num, skb->len); ++ if (defrag_info) { ++ is_frag = 1; ++ if (defrag_info->next_fn != frag_num) { ++ printk("discard:%d:%d\n", defrag_info->next_fn, frag_num); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ ++ skb_put(defrag_info->skb, skb->len-(pull_len-8)); ++ memcpy(&defrag_info->skb->data[defrag_info->frm_len], \ ++ &skb->data[pull_len-8], skb->len - (pull_len-8)); ++ //printk("middle:%d,%d\n", skb->len-(pull_len-8), skb->len); ++ defrag_info->frm_len += (skb->len - (pull_len - 8)); ++ defrag_info->next_fn++; ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } else { ++ defrag_info = kzalloc(sizeof(struct defrag_ctrl_info), GFP_KERNEL); ++ if (defrag_info == NULL) { ++ printk("no defrag_ctrl_info\r\n"); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ defrag_info->skb = __dev_alloc_skb(2000, GFP_KERNEL); ++ if (defrag_info->skb == NULL) { ++ printk("no fragment skb\r\n"); ++ dev_kfree_skb(skb); ++ kfree(defrag_info); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ is_frag = 1; ++ skb_pull(skb, pull_len); ++ skb_push(skb, 14); ++ memcpy(skb->data, ra, MAC_ADDR_LEN); ++ memcpy(&skb->data[6], ta, MAC_ADDR_LEN); ++ memcpy(&skb->data[12], ether_type, 2); ++ defrag_info->sn = seq_num; ++ defrag_info->next_fn = 1; ++ defrag_info->tid = tid; ++ defrag_info->sta_idx = sta_idx; ++ ++ skb_put(defrag_info->skb, skb->len); ++ memcpy(defrag_info->skb->data, skb->data, skb->len); ++ defrag_info->frm_len = skb->len; ++ defrag_info->rwnx_hw = rwnx_hw; ++ //printk("first:%p,%p,%p,%p,%p, %d,%d\r\n", defrag_info, defrag_info->skb, defrag_info->skb->head, defrag_info->skb->tail, defrag_info->skb->end, defrag_info->frm_len, skb->len); ++ list_add_tail(&defrag_info->list, &rwnx_hw->defrag_list); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ init_timer(&defrag_info->defrag_timer); ++ defrag_info->defrag_timer.data = (unsigned long)defrag_info; ++ defrag_info->defrag_timer.function = defrag_timeout_cb; ++#else ++ timer_setup(&defrag_info->defrag_timer, defrag_timeout_cb, 0); ++#endif ++ ret = mod_timer(&defrag_info->defrag_timer, jiffies + msecs_to_jiffies(DEFRAG_MAX_WAIT)); ++ dev_kfree_skb(skb); ++ return 0; ++ } ++ } else { ++ //check whether the last fragment ++ if (!list_empty(&rwnx_hw->defrag_list)) { ++ spin_lock_bh(&rwnx_hw->defrag_lock); ++ list_for_each_entry(defrag_info_tmp, &rwnx_hw->defrag_list, list) { ++ if (((defrag_info_tmp->sn == seq_num) && (defrag_info_tmp->tid == tid) && \ ++ defrag_info_tmp->sta_idx == sta_idx)) { ++ defrag_info = defrag_info_tmp; ++ break; ++ } ++ } ++ ++ if (!defrag_info) ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ else { ++ if (defrag_info->next_fn != frag_num) { ++ printk("discard:%d:%d\n", defrag_info->next_fn, frag_num); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ ++ skb_put(defrag_info->skb, skb->len - (pull_len-8)); ++ memcpy(&defrag_info->skb->data[defrag_info->frm_len], \ ++ &skb->data[pull_len-8], skb->len - (pull_len-8)); ++ defrag_info->frm_len += (skb->len - (pull_len-8)); ++ is_frag = 1; ++ //printk("last: sn=%d, fn=%d, %d, %d\r\n", seq_num, frag_num, defrag_info->frm_len, skb->len); ++ ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ if (!rwnx_vif) { ++ printk("Frame received but no active vif (%d)", hw_rxhdr->flags_vif_idx); ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ return 0; ++ } ++ dev_kfree_skb(skb); ++ ++ skb_tmp = defrag_info->skb; ++ list_del_init(&defrag_info->list); ++ if (timer_pending(&defrag_info->defrag_timer)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) ++ ret = timer_delete(&defrag_info->defrag_timer); ++#else ++ ret = del_timer(&defrag_info->defrag_timer); ++#endif ++ } ++ kfree(defrag_info); ++ spin_unlock_bh(&rwnx_hw->defrag_lock); ++ ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb_tmp, hw_rxhdr)) ++ dev_kfree_skb(skb_tmp); ++ ++ return 0; ++ } ++ } ++ } ++ } ++ ++ if (!is_frag && !is_amsdu) { ++ skb_pull(skb, pull_len); ++ skb_push(skb, 14); ++ memcpy(skb->data, ra, MAC_ADDR_LEN); ++ memcpy(&skb->data[6], ta, MAC_ADDR_LEN); ++ memcpy(&skb->data[12], ether_type, 2); ++ } ++ } ++ ++ if (hw_rxhdr->flags_is_80211_mpdu) { ++ remove_sec_hdr_mgmt_frame(hw_rxhdr, skb); ++ rwnx_rx_mgmt_any(rwnx_hw, skb, hw_rxhdr); ++ } else { ++ rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx); ++ ++ if (!rwnx_vif) { ++ dev_err(rwnx_hw->dev, "Frame received but no active vif(%d)", ++ hw_rxhdr->flags_vif_idx); ++ dev_kfree_skb(skb); ++ goto end; ++ } ++ ++ if (hw_rxhdr->flags_sta_idx != RWNX_INVALID_STA) { ++ struct rwnx_sta *sta; ++ ++ sta = &rwnx_hw->sta_table[hw_rxhdr->flags_sta_idx]; ++ rwnx_rx_statistic(rwnx_hw, hw_rxhdr, sta); ++ ++ if (sta->vlan_idx != rwnx_vif->vif_index) { ++ rwnx_vif = rwnx_hw->vif_table[sta->vlan_idx]; ++ if (!rwnx_vif) { ++ dev_kfree_skb(skb); ++ goto end; ++ } ++ } ++ ++ if (hw_rxhdr->flags_is_4addr && !rwnx_vif->use_4addr) { ++#ifdef CONFIG_GKI ++ rwnx_cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev, ++ sta->mac_addr, GFP_ATOMIC); ++#else ++ cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) ++ sta->mac_addr, GFP_ATOMIC); ++#else ++ sta->mac_addr, -1, GFP_ATOMIC); ++#endif ++#endif ++ } ++ } ++ ++ skb->priority = 256 + tid;//hw_rxhdr->flags_user_prio; ++ ++#ifdef AICWF_RX_REORDER ++ rx_priv_tmp = rx_priv; ++ rx_priv_tmp->rwnx_vif = (void *)rwnx_vif; ++ ++ if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) { ++ if (is_qos && hw_rxhdr->flags_need_reord) ++ reord_process_unit((struct aicwf_rx_priv *)rx_priv, skb, seq_num, tid, 1, hw_rxhdr->flags_is_amsdu); ++ else if (is_qos && !hw_rxhdr->flags_need_reord) { ++ reord_flush_tid((struct aicwf_rx_priv *)rx_priv, skb, tid); ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr) && !hw_rxhdr->flags_is_amsdu) ++ dev_kfree_skb(skb); ++ } else { ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr) && !hw_rxhdr->flags_is_amsdu) ++ dev_kfree_skb(skb); ++ } ++ } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { ++#if 1 ++ skb_reset_mac_header(skb); ++ eth = eth_hdr(skb); ++ //printk("da:%pM, %x,%x, len=%d\n", eth->h_dest, skb->data[12], skb->data[13], skb->len); ++ ++ if (unlikely(is_multicast_ether_addr(eth->h_dest))) { ++ /* broadcast pkt need to be forwared to upper layer and resent ++ on wireless interface */ ++ resend = true; ++ } else { ++ /* unicast pkt for STA inside the BSS, no need to forward to upper ++ layer simply resend on wireless interface */ ++ if (hw_rxhdr->flags_dst_idx != RWNX_INVALID_STA) { ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[hw_rxhdr->flags_dst_idx]; ++ if (sta->valid && (sta->vlan_idx == rwnx_vif->vif_index)) { ++ resend = true; ++ forward = false; ++ } ++ } ++ } ++ ++ if (resend) ++ rwnx_rx_data_skb_resend(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ ++ if (forward) { ++ if (is_qos && hw_rxhdr->flags_need_reord) ++ reord_process_unit((struct aicwf_rx_priv *)rx_priv, skb, seq_num, tid, 1, hw_rxhdr->flags_is_amsdu); ++ else if (is_qos && !hw_rxhdr->flags_need_reord) { ++ reord_flush_tid((struct aicwf_rx_priv *)rx_priv, skb, tid); ++ rwnx_rx_data_skb_forward(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } else ++ rwnx_rx_data_skb_forward(rwnx_hw, rwnx_vif, skb, hw_rxhdr); ++ } else if(resend) { ++ if (is_qos && hw_rxhdr->flags_need_reord) ++ reord_process_unit((struct aicwf_rx_priv *)rx_priv, skb, seq_num, tid, 0, hw_rxhdr->flags_is_amsdu); ++ else if (is_qos && !hw_rxhdr->flags_need_reord) { ++ reord_flush_tid((struct aicwf_rx_priv *)rx_priv, skb, tid); ++ dev_kfree_skb(skb); ++ } ++ }else ++ dev_kfree_skb(skb); ++#else ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr)) ++ dev_kfree_skb(skb); ++#endif ++ } ++#else ++ if (!rwnx_rx_data_skb(rwnx_hw, rwnx_vif, skb, hw_rxhdr)) ++ dev_kfree_skb(skb); ++#endif ++ } ++ } ++ ++end: ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h +new file mode 100644 +index 000000000000..b831bc8e4012 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h +@@ -0,0 +1,396 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_rx.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_RX_H_ ++#define _RWNX_RX_H_ ++ ++#include "aicwf_txrxif.h" ++ ++#define SERVER_PORT 67 ++#define CLIENT_PORT 68 ++#define DHCP_MAGIC 0x63825363 ++#define DHCP_ACK 5 ++#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ ++#define DHCP_OPTION_END 255 ++ ++enum rx_status_bits { ++ /// The buffer can be forwarded to the networking stack ++ RX_STAT_FORWARD = 1 << 0, ++ /// A new buffer has to be allocated ++ RX_STAT_ALLOC = 1 << 1, ++ /// The buffer has to be deleted ++ RX_STAT_DELETE = 1 << 2, ++ /// The length of the buffer has to be updated ++ RX_STAT_LEN_UPDATE = 1 << 3, ++ /// The length in the Ethernet header has to be updated ++ RX_STAT_ETH_LEN_UPDATE = 1 << 4, ++ /// Simple copy ++ RX_STAT_COPY = 1 << 5, ++ /// Spurious frame (inform upper layer and discard) ++ RX_STAT_SPURIOUS = 1 << 6, ++ /// packet for monitor interface ++ RX_STAT_MONITOR = 1 << 7, ++}; ++ ++ ++/* ++ * Decryption status subfields. ++ * { ++ */ ++#define RWNX_RX_HD_DECR_UNENC 0 // ENCRYPTION TYPE NONE ++#define RWNX_RX_HD_DECR_WEP 1 // ENCRYPTION TYPE WEP ++#define RWNX_RX_HD_DECR_TKIP 2 // ENCRYPTION TYPE TKIP ++#define RWNX_RX_HD_DECR_CCMP128 3 // ENCRYPTION TYPE CCMP128 ++#define RWNX_RX_HD_DECR_CCMP256 4 // ENCRYPTION TYPE CCMP256 ++#define RWNX_RX_HD_DECR_GCMP128 5 // ENCRYPTION TYPE GCMP128 ++#define RWNX_RX_HD_DECR_GCMP256 6 // ENCRYPTION TYPE GCMP256 ++#define RWNX_RX_HD_DECR_WAPI 7 // ENCRYPTION TYPE WAPI ++// @} ++ ++//#ifdef CONFIG_RWNX_MON_DATA ++#if 0 ++#define RX_MACHDR_BACKUP_LEN 64 ++#endif ++ ++struct rx_vector_1_old { ++ /** Receive Vector 1a */ ++ u32 leg_length :12; ++ u32 leg_rate : 4; ++ u32 ht_length :16; ++ ++ /** Receive Vector 1b */ ++ u32 _ht_length : 4; // FIXME ++ u32 short_gi : 1; ++ u32 stbc : 2; ++ u32 smoothing : 1; ++ u32 mcs : 7; ++ u32 pre_type : 1; ++ u32 format_mod : 3; ++ u32 ch_bw : 2; ++ u32 n_sts : 3; ++ u32 lsig_valid : 1; ++ u32 sounding : 1; ++ u32 num_extn_ss : 2; ++ u32 aggregation : 1; ++ u32 fec_coding : 1; ++ u32 dyn_bw : 1; ++ u32 doze_not_allowed : 1; ++ ++ /** Receive Vector 1c */ ++ u32 antenna_set : 8; ++ u32 partial_aid : 9; ++ u32 group_id : 6; ++ u32 first_user : 1; ++ s32 rssi1 : 8; ++ ++ /** Receive Vector 1d */ ++ s32 rssi2 : 8; ++ s32 rssi3 : 8; ++ s32 rssi4 : 8; ++ u32 reserved_1d : 8; ++}; ++ ++struct rx_leg_vect { ++ u8 dyn_bw_in_non_ht : 1; ++ u8 chn_bw_in_non_ht : 2; ++ u8 rsvd_nht : 4; ++ u8 lsig_valid : 1; ++} __packed; ++ ++struct rx_ht_vect { ++ u16 sounding : 1; ++ u16 smoothing : 1; ++ u16 short_gi : 1; ++ u16 aggregation : 1; ++ u16 stbc : 1; ++ u16 num_extn_ss : 2; ++ u16 lsig_valid : 1; ++ u16 mcs : 7; ++ u16 fec : 1; ++ u16 length :16; ++} __packed; ++ ++struct rx_vht_vect { ++ u8 sounding : 1; ++ u8 beamformed : 1; ++ u8 short_gi : 1; ++ u8 rsvd_vht1 : 1; ++ u8 stbc : 1; ++ u8 doze_not_allowed : 1; ++ u8 first_user : 1; ++ u8 rsvd_vht2 : 1; ++ u16 partial_aid : 9; ++ u16 group_id : 6; ++ u16 rsvd_vht3 : 1; ++ u32 mcs : 4; ++ u32 nss : 3; ++ u32 fec : 1; ++ u32 length :20; ++ u32 rsvd_vht4 : 4; ++} __packed; ++ ++struct rx_he_vect { ++ u8 sounding : 1; ++ u8 beamformed : 1; ++ u8 gi_type : 2; ++ u8 stbc : 1; ++ u8 rsvd_he1 : 3; ++ ++ u8 uplink_flag : 1; ++ u8 beam_change : 1; ++ u8 dcm : 1; ++ u8 he_ltf_type : 2; ++ u8 doppler : 1; ++ u8 rsvd_he2 : 2; ++ ++ u8 bss_color : 6; ++ u8 rsvd_he3 : 2; ++ ++ u8 txop_duration : 7; ++ u8 rsvd_he4 : 1; ++ ++ u8 pe_duration : 4; ++ u8 spatial_reuse : 4; ++ ++ u8 sig_b_comp_mode : 1; ++ u8 dcm_sig_b : 1; ++ u8 mcs_sig_b : 3; ++ u8 ru_size : 3; ++ ++ u32 mcs : 4; ++ u32 nss : 3; ++ u32 fec : 1; ++ u32 length :20; ++ u32 rsvd_he6 : 4; ++} __packed; ++ ++struct rx_vector_1 { ++ u8 format_mod : 4; ++ u8 ch_bw : 3; ++ u8 pre_type : 1; ++ u8 antenna_set : 8; ++ s32 rssi_leg : 8; ++ u32 leg_length :12; ++ u32 leg_rate : 4; ++ s32 rssi1 : 8; ++ ++ union { ++ struct rx_leg_vect leg; ++ struct rx_ht_vect ht; ++ struct rx_vht_vect vht; ++ struct rx_he_vect he; ++ }; ++} __packed; ++ ++struct rx_vector_2_old { ++ /** Receive Vector 2a */ ++ u32 rcpi : 8; ++ u32 evm1 : 8; ++ u32 evm2 : 8; ++ u32 evm3 : 8; ++ ++ /** Receive Vector 2b */ ++ u32 evm4 : 8; ++ u32 reserved2b_1 : 8; ++ u32 reserved2b_2 : 8; ++ u32 reserved2b_3 : 8; ++ ++}; ++ ++struct rx_vector_2 { ++ /** Receive Vector 2a */ ++ u32 rcpi1 : 8; ++ u32 rcpi2 : 8; ++ u32 rcpi3 : 8; ++ u32 rcpi4 : 8; ++ ++ /** Receive Vector 2b */ ++ u32 evm1 : 8; ++ u32 evm2 : 8; ++ u32 evm3 : 8; ++ u32 evm4 : 8; ++}; ++ ++struct phy_channel_info_desc { ++ /** PHY channel information 1 */ ++ u32 phy_band : 8; ++ u32 phy_channel_type : 8; ++ u32 phy_prim20_freq : 16; ++ /** PHY channel information 2 */ ++ u32 phy_center1_freq : 16; ++ u32 phy_center2_freq : 16; ++}; ++ ++struct hw_vect { ++ /** Total length for the MPDU transfer */ ++ u32 len :16; ++ ++ u32 reserved : 8;//data type is included ++ /** AMPDU Status Information */ ++ u32 mpdu_cnt : 6; ++ u32 ampdu_cnt : 2; ++ ++ /** TSF Low */ ++ __le32 tsf_lo; ++ /** TSF High */ ++ __le32 tsf_hi; ++ ++ /** Receive Vector 1 */ ++ struct rx_vector_1 rx_vect1; ++ /** Receive Vector 2 */ ++ struct rx_vector_2 rx_vect2; ++ ++ /** Status **/ ++ u32 rx_vect2_valid : 1; ++ u32 resp_frame : 1; ++ /** Decryption Status */ ++ u32 decr_status : 3; ++ u32 rx_fifo_oflow : 1; ++ ++ /** Frame Unsuccessful */ ++ u32 undef_err : 1; ++ u32 phy_err : 1; ++ u32 fcs_err : 1; ++ u32 addr_mismatch : 1; ++ u32 ga_frame : 1; ++ u32 current_ac : 2; ++ ++ u32 frm_successful_rx : 1; ++ /** Descriptor Done */ ++ u32 desc_done_rx : 1; ++ /** Key Storage RAM Index */ ++ u32 key_sram_index : 10; ++ /** Key Storage RAM Index Valid */ ++ u32 key_sram_v : 1; ++ u32 type : 2; ++ u32 subtype : 4; ++}; ++ ++//#ifdef CONFIG_RWNX_MON_DATA ++#if 0 ++/// MAC header backup descriptor ++struct mon_machdrdesc { ++ /// Length of the buffer ++ u32 buf_len; ++ /// Buffer containing mac header, LLC and SNAP ++ u8 buffer[RX_MACHDR_BACKUP_LEN]; ++}; ++#endif ++ ++struct hw_rxhdr { ++ /** RX vector */ ++ struct hw_vect hwvect; ++ ++ /** PHY channel information */ ++ struct phy_channel_info_desc phy_info; ++ ++ /** RX flags */ ++ u32 flags_is_amsdu : 1; ++ u32 flags_is_80211_mpdu: 1; ++ u32 flags_is_4addr : 1; ++ u32 flags_new_peer : 1; ++#if defined(AICWF_SDIO_SUPPORT) || defined(AICWF_USB_SUPPORT) ++ u32 flags_user_prio : 1; // aic: fw not fill any more ++ u32 flags_need_reord : 1; ++ u32 flags_upload : 1; ++#else ++ u32 flags_user_prio : 3; ++#endif ++#ifndef AICWF_RX_REORDER ++ u32 flags_rsvd0 : 1; ++#else ++ u32 is_monitor_vif : 1; ++#endif ++ u32 flags_vif_idx : 8; // 0xFF if invalid VIF index ++ u32 flags_sta_idx : 8; // 0xFF if invalid STA index ++ u32 flags_dst_idx : 8; // 0xFF if unknown destination STA ++//#ifdef CONFIG_RWNX_MON_DATA ++#if 0 ++ /// MAC header backup descriptor (used only for MSDU when there is a monitor and a data interface) ++ struct mon_machdrdesc mac_hdr_backup; ++#endif ++ /** Pattern indicating if the buffer is available for the driver */ ++ u32 pattern; ++}; ++ ++struct rwnx_legrate { ++ int idx; ++ int rate; ++}; ++ ++extern struct rwnx_legrate legrates_lut[]; ++extern u16 tx_legrates_lut_rate[]; ++ ++struct DHCPInfo { ++ u8 op; ++ u8 htype; ++ u8 hlen; ++ u8 hops; ++ u32 xid; ++ u16 secs; ++ u16 flags; ++ u32 ciaddr; ++ u32 yiaddr; ++ u32 siaddr; ++ u32 giaddr; ++ u8 chaddr[16]; ++ u8 sname[64]; ++ u8 file[128]; ++ u32 cookie; ++ u8 options[308]; /* 312 - cookie */ ++}; ++ ++u8 rwnx_rxdataind_aicwf(struct rwnx_hw *rwnx_hw, void *hostid, void *rx_priv); ++int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv); ++ ++#ifdef AICWF_ARP_OFFLOAD ++void arpoffload_proc(struct sk_buff *skb, struct rwnx_vif *rwnx_vif); ++#endif ++#ifdef AICWF_RX_REORDER ++struct recv_msdu *reord_rxframe_alloc(spinlock_t *lock, struct list_head *q); ++void reord_rxframe_free(spinlock_t *lock, struct list_head *q, struct list_head *list); ++struct reord_ctrl_info *reord_init_sta(struct aicwf_rx_priv *rx_priv, const u8 *mac_addr); ++void reord_deinit_sta(struct aicwf_rx_priv *rx_priv, struct reord_ctrl_info *reord_info); ++int reord_need_check(struct reord_ctrl *preorder_ctrl, u16 seq_num); ++int reord_rxframe_enqueue(struct reord_ctrl *preorder_ctrl, struct recv_msdu *prframe); ++void reord_timeout_worker(struct work_struct *work); ++int reord_single_frame_ind(struct aicwf_rx_priv *rx_priv, struct recv_msdu *prframe); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++void reord_timeout_handler (ulong data); ++#else ++void reord_timeout_handler (struct timer_list *t); ++#endif ++ ++#endif ++void rwnx_rxdata_process_amsdu(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, u8 vif_idx, ++ struct sk_buff_head *list); ++ ++#ifdef CONFIG_HE_FOR_OLD_KERNEL ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 197) ++struct element { ++ u8 id; ++ u8 datalen; ++ u8 data[]; ++}; ++/* element iteration helpers */ ++#define for_each_element(_elem, _data, _datalen) \ ++ for (_elem = (const struct element *)(_data); \ ++ (const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \ ++ (int)sizeof(*_elem) && \ ++ (const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \ ++ (int)sizeof(*_elem) + _elem->datalen; \ ++ _elem = (const struct element *)(_elem->data + _elem->datalen)) ++ ++#define for_each_element_id(element, _id, data, datalen) \ ++ for_each_element(element, data, datalen) \ ++ if (element->id == (_id)) ++#endif ++#endif ++ ++#endif /* _RWNX_RX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c +new file mode 100644 +index 000000000000..52ffbf64c6fb +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c +@@ -0,0 +1,266 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_strs.c ++ * ++ * @brief Miscellaneous debug strings ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "lmac_msg.h" ++static const char *const rwnx_mmid2str[MSG_I(MM_MAX)] = { ++ [MSG_I(MM_RESET_REQ)] = "MM_RESET_REQ", ++ [MSG_I(MM_RESET_CFM)] = "MM_RESET_CFM", ++ [MSG_I(MM_START_REQ)] = "MM_START_REQ", ++ [MSG_I(MM_START_CFM)] = "MM_START_CFM", ++ [MSG_I(MM_VERSION_REQ)] = "MM_VERSION_REQ", ++ [MSG_I(MM_VERSION_CFM)] = "MM_VERSION_CFM", ++ [MSG_I(MM_ADD_IF_REQ)] = "MM_ADD_IF_REQ", ++ [MSG_I(MM_ADD_IF_CFM)] = "MM_ADD_IF_CFM", ++ [MSG_I(MM_REMOVE_IF_REQ)] = "MM_REMOVE_IF_REQ", ++ [MSG_I(MM_REMOVE_IF_CFM)] = "MM_REMOVE_IF_CFM", ++ [MSG_I(MM_STA_ADD_REQ)] = "MM_STA_ADD_REQ", ++ [MSG_I(MM_STA_ADD_CFM)] = "MM_STA_ADD_CFM", ++ [MSG_I(MM_STA_DEL_REQ)] = "MM_STA_DEL_REQ", ++ [MSG_I(MM_STA_DEL_CFM)] = "MM_STA_DEL_CFM", ++ [MSG_I(MM_SET_FILTER_REQ)] = "MM_SET_FILTER_REQ", ++ [MSG_I(MM_SET_FILTER_CFM)] = "MM_SET_FILTER_CFM", ++ [MSG_I(MM_SET_CHANNEL_REQ)] = "MM_SET_CHANNEL_REQ", ++ [MSG_I(MM_SET_CHANNEL_CFM)] = "MM_SET_CHANNEL_CFM", ++ [MSG_I(MM_SET_DTIM_REQ)] = "MM_SET_DTIM_REQ", ++ [MSG_I(MM_SET_DTIM_CFM)] = "MM_SET_DTIM_CFM", ++ [MSG_I(MM_SET_BEACON_INT_REQ)] = "MM_SET_BEACON_INT_REQ", ++ [MSG_I(MM_SET_BEACON_INT_CFM)] = "MM_SET_BEACON_INT_CFM", ++ [MSG_I(MM_SET_BASIC_RATES_REQ)] = "MM_SET_BASIC_RATES_REQ", ++ [MSG_I(MM_SET_BASIC_RATES_CFM)] = "MM_SET_BASIC_RATES_CFM", ++ [MSG_I(MM_SET_BSSID_REQ)] = "MM_SET_BSSID_REQ", ++ [MSG_I(MM_SET_BSSID_CFM)] = "MM_SET_BSSID_CFM", ++ [MSG_I(MM_SET_EDCA_REQ)] = "MM_SET_EDCA_REQ", ++ [MSG_I(MM_SET_EDCA_CFM)] = "MM_SET_EDCA_CFM", ++ [MSG_I(MM_SET_MODE_REQ)] = "MM_SET_MODE_REQ", ++ [MSG_I(MM_SET_MODE_CFM)] = "MM_SET_MODE_CFM", ++ [MSG_I(MM_SET_VIF_STATE_REQ)] = "MM_SET_VIF_STATE_REQ", ++ [MSG_I(MM_SET_VIF_STATE_CFM)] = "MM_SET_VIF_STATE_CFM", ++ [MSG_I(MM_SET_SLOTTIME_REQ)] = "MM_SET_SLOTTIME_REQ", ++ [MSG_I(MM_SET_SLOTTIME_CFM)] = "MM_SET_SLOTTIME_CFM", ++ [MSG_I(MM_SET_IDLE_REQ)] = "MM_SET_IDLE_REQ", ++ [MSG_I(MM_SET_IDLE_CFM)] = "MM_SET_IDLE_CFM", ++ [MSG_I(MM_KEY_ADD_REQ)] = "MM_KEY_ADD_REQ", ++ [MSG_I(MM_KEY_ADD_CFM)] = "MM_KEY_ADD_CFM", ++ [MSG_I(MM_KEY_DEL_REQ)] = "MM_KEY_DEL_REQ", ++ [MSG_I(MM_KEY_DEL_CFM)] = "MM_KEY_DEL_CFM", ++ [MSG_I(MM_BA_ADD_REQ)] = "MM_BA_ADD_REQ", ++ [MSG_I(MM_BA_ADD_CFM)] = "MM_BA_ADD_CFM", ++ [MSG_I(MM_BA_DEL_REQ)] = "MM_BA_DEL_REQ", ++ [MSG_I(MM_BA_DEL_CFM)] = "MM_BA_DEL_CFM", ++ [MSG_I(MM_PRIMARY_TBTT_IND)] = "MM_PRIMARY_TBTT_IND", ++ [MSG_I(MM_SECONDARY_TBTT_IND)] = "MM_SECONDARY_TBTT_IND", ++ [MSG_I(MM_SET_POWER_REQ)] = "MM_SET_POWER_REQ", ++ [MSG_I(MM_SET_POWER_CFM)] = "MM_SET_POWER_CFM", ++ [MSG_I(MM_DBG_TRIGGER_REQ)] = "MM_DBG_TRIGGER_REQ", ++ [MSG_I(MM_SET_PS_MODE_REQ)] = "MM_SET_PS_MODE_REQ", ++ [MSG_I(MM_SET_PS_MODE_CFM)] = "MM_SET_PS_MODE_CFM", ++ [MSG_I(MM_CHAN_CTXT_ADD_REQ)] = "MM_CHAN_CTXT_ADD_REQ", ++ [MSG_I(MM_CHAN_CTXT_ADD_CFM)] = "MM_CHAN_CTXT_ADD_CFM", ++ [MSG_I(MM_CHAN_CTXT_DEL_REQ)] = "MM_CHAN_CTXT_DEL_REQ", ++ [MSG_I(MM_CHAN_CTXT_DEL_CFM)] = "MM_CHAN_CTXT_DEL_CFM", ++ [MSG_I(MM_CHAN_CTXT_LINK_REQ)] = "MM_CHAN_CTXT_LINK_REQ", ++ [MSG_I(MM_CHAN_CTXT_LINK_CFM)] = "MM_CHAN_CTXT_LINK_CFM", ++ [MSG_I(MM_CHAN_CTXT_UNLINK_REQ)] = "MM_CHAN_CTXT_UNLINK_REQ", ++ [MSG_I(MM_CHAN_CTXT_UNLINK_CFM)] = "MM_CHAN_CTXT_UNLINK_CFM", ++ [MSG_I(MM_CHAN_CTXT_UPDATE_REQ)] = "MM_CHAN_CTXT_UPDATE_REQ", ++ [MSG_I(MM_CHAN_CTXT_UPDATE_CFM)] = "MM_CHAN_CTXT_UPDATE_CFM", ++ [MSG_I(MM_CHAN_CTXT_SCHED_REQ)] = "MM_CHAN_CTXT_SCHED_REQ", ++ [MSG_I(MM_CHAN_CTXT_SCHED_CFM)] = "MM_CHAN_CTXT_SCHED_CFM", ++ [MSG_I(MM_BCN_CHANGE_REQ)] = "MM_BCN_CHANGE_REQ", ++ [MSG_I(MM_BCN_CHANGE_CFM)] = "MM_BCN_CHANGE_CFM", ++ [MSG_I(MM_TIM_UPDATE_REQ)] = "MM_TIM_UPDATE_REQ", ++ [MSG_I(MM_TIM_UPDATE_CFM)] = "MM_TIM_UPDATE_CFM", ++ [MSG_I(MM_CONNECTION_LOSS_IND)] = "MM_CONNECTION_LOSS_IND", ++ [MSG_I(MM_CHANNEL_SWITCH_IND)] = "MM_CHANNEL_SWITCH_IND", ++ [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = "MM_CHANNEL_PRE_SWITCH_IND", ++ [MSG_I(MM_REMAIN_ON_CHANNEL_REQ)] = "MM_REMAIN_ON_CHANNEL_REQ", ++ [MSG_I(MM_REMAIN_ON_CHANNEL_CFM)] = "MM_REMAIN_ON_CHANNEL_CFM", ++ [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = "MM_REMAIN_ON_CHANNEL_EXP_IND", ++ [MSG_I(MM_PS_CHANGE_IND)] = "MM_PS_CHANGE_IND", ++ [MSG_I(MM_TRAFFIC_REQ_IND)] = "MM_TRAFFIC_REQ_IND", ++ [MSG_I(MM_SET_PS_OPTIONS_REQ)] = "MM_SET_PS_OPTIONS_REQ", ++ [MSG_I(MM_SET_PS_OPTIONS_CFM)] = "MM_SET_PS_OPTIONS_CFM", ++ [MSG_I(MM_P2P_VIF_PS_CHANGE_IND)] = "MM_P2P_VIF_PS_CHANGE_IND", ++ [MSG_I(MM_CSA_COUNTER_IND)] = "MM_CSA_COUNTER_IND", ++ [MSG_I(MM_CHANNEL_SURVEY_IND)] = "MM_CHANNEL_SURVEY_IND", ++ [MSG_I(MM_SET_P2P_NOA_REQ)] = "MM_SET_P2P_NOA_REQ", ++ [MSG_I(MM_SET_P2P_OPPPS_REQ)] = "MM_SET_P2P_OPPPS_REQ", ++ [MSG_I(MM_SET_P2P_NOA_CFM)] = "MM_SET_P2P_NOA_CFM", ++ [MSG_I(MM_SET_P2P_OPPPS_CFM)] = "MM_SET_P2P_OPPPS_CFM", ++ [MSG_I(MM_CFG_RSSI_REQ)] = "MM_CFG_RSSI_REQ", ++ [MSG_I(MM_RSSI_STATUS_IND)] = "MM_RSSI_STATUS_IND", ++ [MSG_I(MM_CSA_FINISH_IND)] = "MM_CSA_FINISH_IND", ++ [MSG_I(MM_CSA_TRAFFIC_IND)] = "MM_CSA_TRAFFIC_IND", ++ [MSG_I(MM_MU_GROUP_UPDATE_REQ)] = "MM_MU_GROUP_UPDATE_REQ", ++ [MSG_I(MM_MU_GROUP_UPDATE_CFM)] = "MM_MU_GROUP_UPDATE_CFM", ++ ++ [MSG_I(MM_SET_ARPOFFLOAD_REQ)] = "MM_SET_ARPOFFLOAD_REQ", ++ [MSG_I(MM_SET_ARPOFFLOAD_CFM)] = "MM_SET_ARPOFFLOAD_CFM", ++ [MSG_I(MM_SET_AGG_DISABLE_REQ)] = "MM_SET_AGG_DISABLE_REQ", ++ [MSG_I(MM_SET_AGG_DISABLE_CFM)] = "MM_SET_AGG_DISABLE_CFM", ++ [MSG_I(MM_SET_COEX_REQ)] = "MM_SET_COEX_REQ", ++ [MSG_I(MM_SET_COEX_CFM)] = "MM_SET_COEX_CFM", ++ [MSG_I(MM_SET_RF_CONFIG_REQ)] = "MM_SET_RF_CONFIG_REQ", ++ [MSG_I(MM_SET_RF_CONFIG_CFM)] = "MM_SET_RF_CONFIG_CFM", ++ [MSG_I(MM_SET_RF_CALIB_REQ)] = "MM_SET_RF_CALIB_REQ", ++ [MSG_I(MM_SET_RF_CALIB_CFM)] = "MM_SET_RF_CALIB_CFM", ++ ++ [MSG_I(MM_GET_MAC_ADDR_REQ)] = "MM_GET_MAC_ADDR_REQ", ++ [MSG_I(MM_GET_MAC_ADDR_CFM)] = "MM_GET_MAC_ADDR_CFM", ++ [MSG_I(MM_GET_STA_INFO_REQ)] = "MM_GET_STA_INFO_REQ", ++ [MSG_I(MM_GET_STA_INFO_CFM)] = "MM_GET_STA_INFO_CFM", ++ [MSG_I(MM_SET_TXPWR_IDX_LVL_REQ)] = "MM_SET_TXPWR_IDX_LVL_REQ", ++ [MSG_I(MM_SET_TXPWR_IDX_LVL_CFM)] = "MM_SET_TXPWR_IDX_LVL_CFM", ++ [MSG_I(MM_SET_TXPWR_OFST_REQ)] = "MM_SET_TXPWR_OFST_REQ", ++ [MSG_I(MM_SET_TXPWR_OFST_CFM)] = "MM_SET_TXPWR_OFST_CFM", ++ [MSG_I(MM_SET_STACK_START_REQ)] = "MM_SET_STACK_START_REQ", ++ [MSG_I(MM_SET_STACK_START_CFM)] = "MM_SET_STACK_START_CFM", ++ [MSG_I(MM_APM_STALOSS_IND)] = "MM_APM_STALOSS_IND", ++ [MSG_I(MM_SET_VENDOR_HWCONFIG_REQ)] = "MM_SET_VENDOR_HWCONFIG_REQ", ++ [MSG_I(MM_SET_VENDOR_HWCONFIG_CFM)] = "MM_SET_VENDOR_HWCONFIG_CFM", ++ [MSG_I(MM_GET_FW_VERSION_REQ)] = "MM_GET_FW_VERSION_REQ", ++ [MSG_I(MM_GET_FW_VERSION_CFM)] = "MM_GET_FW_VERSION_CFM", ++ [MSG_I(MM_SET_RESUME_RESTORE_REQ)] = "MM_SET_RESUME_RESTORE_REQ", ++ [MSG_I(MM_SET_RESUME_RESTORE_CFM)] = "MM_SET_RESUME_RESTORE_CFM", ++ [MSG_I(MM_GET_WIFI_DISABLE_REQ)] = "MM_GET_WIFI_DISABLE_REQ", ++ [MSG_I(MM_GET_WIFI_DISABLE_CFM)] = "MM_GET_WIFI_DISABLE_CFM", ++ [MSG_I(MM_CFG_RSSI_CFM)] = "MM_CFG_RSSI_CFM", ++}; ++ ++static const char *const rwnx_dbgid2str[MSG_I(DBG_MAX)] = { ++ [MSG_I(DBG_MEM_READ_REQ)] = "DBG_MEM_READ_REQ", ++ [MSG_I(DBG_MEM_READ_CFM)] = "DBG_MEM_READ_CFM", ++ [MSG_I(DBG_MEM_WRITE_REQ)] = "DBG_MEM_WRITE_REQ", ++ [MSG_I(DBG_MEM_WRITE_CFM)] = "DBG_MEM_WRITE_CFM", ++ [MSG_I(DBG_SET_MOD_FILTER_REQ)] = "DBG_SET_MOD_FILTER_REQ", ++ [MSG_I(DBG_SET_MOD_FILTER_CFM)] = "DBG_SET_MOD_FILTER_CFM", ++ [MSG_I(DBG_SET_SEV_FILTER_REQ)] = "DBG_SET_SEV_FILTER_REQ", ++ [MSG_I(DBG_SET_SEV_FILTER_CFM)] = "DBG_SET_SEV_FILTER_CFM", ++ [MSG_I(DBG_ERROR_IND)] = "DBG_ERROR_IND", ++ [MSG_I(DBG_GET_SYS_STAT_REQ)] = "DBG_GET_SYS_STAT_REQ", ++ [MSG_I(DBG_GET_SYS_STAT_CFM)] = "DBG_GET_SYS_STAT_CFM", ++}; ++ ++static const char *const rwnx_scanid2str[MSG_I(SCAN_MAX)] = { ++ [MSG_I(SCAN_START_REQ)] = "SCAN_START_REQ", ++ [MSG_I(SCAN_START_CFM)] = "SCAN_START_CFM", ++ [MSG_I(SCAN_DONE_IND)] = "SCAN_DONE_IND", ++}; ++ ++static const char *const rwnx_tdlsid2str[MSG_I(TDLS_MAX)] = { ++ [MSG_I(TDLS_CHAN_SWITCH_CFM)] = "TDLS_CHAN_SWITCH_CFM", ++ [MSG_I(TDLS_CHAN_SWITCH_REQ)] = "TDLS_CHAN_SWITCH_REQ", ++ [MSG_I(TDLS_CHAN_SWITCH_IND)] = "TDLS_CHAN_SWITCH_IND", ++ [MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = "TDLS_CHAN_SWITCH_BASE_IND", ++ [MSG_I(TDLS_CANCEL_CHAN_SWITCH_REQ)] = "TDLS_CANCEL_CHAN_SWITCH_REQ", ++ [MSG_I(TDLS_CANCEL_CHAN_SWITCH_CFM)] = "TDLS_CANCEL_CHAN_SWITCH_CFM", ++ [MSG_I(TDLS_PEER_PS_IND)] = "TDLS_PEER_PS_IND", ++ [MSG_I(TDLS_PEER_TRAFFIC_IND_REQ)] = "TDLS_PEER_TRAFFIC_IND_REQ", ++ [MSG_I(TDLS_PEER_TRAFFIC_IND_CFM)] = "TDLS_PEER_TRAFFIC_IND_CFM", ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++static const char *const rwnx_scanuid2str[MSG_I(SCANU_MAX)] = { ++ [MSG_I(SCANU_START_REQ)] = "SCANU_START_REQ", ++ [MSG_I(SCANU_START_CFM)] = "SCANU_START_CFM", ++ [MSG_I(SCANU_JOIN_REQ)] = "SCANU_JOIN_REQ", ++ [MSG_I(SCANU_JOIN_CFM)] = "SCANU_JOIN_CFM", ++ [MSG_I(SCANU_RESULT_IND)] = "SCANU_RESULT_IND", ++ [MSG_I(SCANU_FAST_REQ)] = "SCANU_FAST_REQ", ++ [MSG_I(SCANU_FAST_CFM)] = "SCANU_FAST_CFM", ++ [MSG_I(SCANU_VENDOR_IE_REQ)] = "SCANU_VENDOR_IE_REQ", ++ [MSG_I(SCANU_VENDOR_IE_CFM)] = "SCANU_VENDOR_IE_CFM", ++ [MSG_I(SCANU_START_CFM_ADDTIONAL)] = "SCANU_START_CFM_ADDTIONAL", ++ [MSG_I(SCANU_CANCEL_REQ)] = "SCANU_CANCEL_REQ", ++ [MSG_I(SCANU_CANCEL_CFM)] = "SCANU_CANCEL_CFM", ++}; ++ ++static const char *const rwnx_meid2str[MSG_I(ME_MAX)] = { ++ [MSG_I(ME_CONFIG_REQ)] = "ME_CONFIG_REQ", ++ [MSG_I(ME_CONFIG_CFM)] = "ME_CONFIG_CFM", ++ [MSG_I(ME_CHAN_CONFIG_REQ)] = "ME_CHAN_CONFIG_REQ", ++ [MSG_I(ME_CHAN_CONFIG_CFM)] = "ME_CHAN_CONFIG_CFM", ++ [MSG_I(ME_SET_CONTROL_PORT_REQ)] = "ME_SET_CONTROL_PORT_REQ", ++ [MSG_I(ME_SET_CONTROL_PORT_CFM)] = "ME_SET_CONTROL_PORT_CFM", ++ [MSG_I(ME_TKIP_MIC_FAILURE_IND)] = "ME_TKIP_MIC_FAILURE_IND", ++ [MSG_I(ME_STA_ADD_REQ)] = "ME_STA_ADD_REQ", ++ [MSG_I(ME_STA_ADD_CFM)] = "ME_STA_ADD_CFM", ++ [MSG_I(ME_STA_DEL_REQ)] = "ME_STA_DEL_REQ", ++ [MSG_I(ME_STA_DEL_CFM)] = "ME_STA_DEL_CFM", ++ [MSG_I(ME_TX_CREDITS_UPDATE_IND)]= "ME_TX_CREDITS_UPDATE_IND", ++ [MSG_I(ME_RC_STATS_REQ)] = "ME_RC_STATS_REQ", ++ [MSG_I(ME_RC_STATS_CFM)] = "ME_RC_STATS_CFM", ++ [MSG_I(ME_RC_SET_RATE_REQ)] = "ME_RC_SET_RATE_REQ", ++ [MSG_I(ME_TRAFFIC_IND_REQ)] = "ME_TRAFFIC_IND_REQ", ++ [MSG_I(ME_TRAFFIC_IND_CFM)] = "ME_TRAFFIC_IND_CFM", ++ [MSG_I(ME_SET_PS_MODE_REQ)] = "ME_SET_PS_MODE_REQ", ++ [MSG_I(ME_SET_PS_MODE_CFM)] = "ME_SET_PS_MODE_CFM", ++}; ++ ++static const char *const rwnx_smid2str[MSG_I(SM_MAX)] = { ++ [MSG_I(SM_CONNECT_REQ)] = "SM_CONNECT_REQ", ++ [MSG_I(SM_CONNECT_CFM)] = "SM_CONNECT_CFM", ++ [MSG_I(SM_CONNECT_IND)] = "SM_CONNECT_IND", ++ [MSG_I(SM_DISCONNECT_REQ)] = "SM_DISCONNECT_REQ", ++ [MSG_I(SM_DISCONNECT_CFM)] = "SM_DISCONNECT_CFM", ++ [MSG_I(SM_DISCONNECT_IND)] = "SM_DISCONNECT_IND", ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_IND)] = "SM_EXTERNAL_AUTH_REQUIRED_IND", ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP", ++ [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM", ++}; ++ ++static const char *const rwnx_apmid2str[MSG_I(APM_MAX)] = { ++ [MSG_I(APM_START_REQ)] = "APM_START_REQ", ++ [MSG_I(APM_START_CFM)] = "APM_START_CFM", ++ [MSG_I(APM_STOP_REQ)] = "APM_STOP_REQ", ++ [MSG_I(APM_STOP_CFM)] = "APM_STOP_CFM", ++ [MSG_I(APM_START_CAC_REQ)] = "APM_START_CAC_REQ", ++ [MSG_I(APM_START_CAC_CFM)] = "APM_START_CAC_CFM", ++ [MSG_I(APM_STOP_CAC_REQ)] = "APM_STOP_CAC_REQ", ++ [MSG_I(APM_STOP_CAC_CFM)] = "APM_STOP_CAC_CFM", ++ [MSG_I(APM_SET_BEACON_IE_REQ)] = "APM_SET_BEACON_IE_REQ", ++ [MSG_I(APM_SET_BEACON_IE_CFM)] = "APM_SET_BEACON_IE_CFM", ++}; ++ ++static const char *const rwnx_meshid2str[MSG_I(MESH_MAX)] = { ++ [MSG_I(MESH_START_REQ)] = "MESH_START_REQ", ++ [MSG_I(MESH_START_CFM)] = "MESH_START_CFM", ++ [MSG_I(MESH_STOP_REQ)] = "MESH_STOP_REQ", ++ [MSG_I(MESH_STOP_CFM)] = "MESH_STOP_CFM", ++ [MSG_I(MESH_UPDATE_REQ)] = "MESH_UPDATE_REQ", ++ [MSG_I(MESH_UPDATE_CFM)] = "MESH_UPDATE_CFM", ++ [MSG_I(MESH_PATH_CREATE_REQ)] = "MESH_PATH_CREATE_REQ", ++ [MSG_I(MESH_PATH_CREATE_CFM)] = "MESH_PATH_CREATE_CFM", ++ [MSG_I(MESH_PATH_UPDATE_REQ)] = "MESH_PATH_UPDATE_REQ", ++ [MSG_I(MESH_PATH_UPDATE_CFM)] = "MESH_PATH_UPDATE_CFM", ++ [MSG_I(MESH_PROXY_ADD_REQ)] = "MESH_PROXY_ADD_REQ", ++ [MSG_I(MESH_PEER_UPDATE_IND)] = "MESH_PEER_UPDATE_IND", ++ [MSG_I(MESH_PATH_UPDATE_IND)] = "MESH_PATH_UPDATE_IND", ++ [MSG_I(MESH_PROXY_UPDATE_IND)] = "MESH_PROXY_UPDATE_IND", ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++const char *const *rwnx_id2str[TASK_LAST_EMB + 1] = { ++ [TASK_MM] = rwnx_mmid2str, ++ [TASK_DBG] = rwnx_dbgid2str, ++ [TASK_SCAN] = rwnx_scanid2str, ++ [TASK_TDLS] = rwnx_tdlsid2str, ++#ifdef CONFIG_RWNX_FULLMAC ++ [TASK_SCANU] = rwnx_scanuid2str, ++ [TASK_ME] = rwnx_meid2str, ++ [TASK_SM] = rwnx_smid2str, ++ [TASK_APM] = rwnx_apmid2str, ++ [TASK_MESH] = rwnx_meshid2str, ++#endif ++}; +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h +new file mode 100644 +index 000000000000..7dc83aba8bea +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h +@@ -0,0 +1,31 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_strs.h ++ * ++ * @brief Miscellaneous debug strings ++ * ++ * Copyright (C) RivieraWaves 2014-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef _RWNX_STRS_H_ ++#define _RWNX_STRS_H_ ++ ++#ifdef CONFIG_RWNX_FHOST ++ ++#define RWNX_ID2STR(tag) "Cmd" ++ ++#else ++#include "lmac_msg.h" ++ ++#define RWNX_ID2STR(tag) (((MSG_T(tag) < ARRAY_SIZE(rwnx_id2str)) && \ ++ (rwnx_id2str[MSG_T(tag)]) && \ ++ ((rwnx_id2str[MSG_T(tag)])[MSG_I(tag)])) ? \ ++ (rwnx_id2str[MSG_T(tag)])[MSG_I(tag)] : "unknown") ++ ++extern const char *const *rwnx_id2str[TASK_LAST_EMB + 1]; ++#endif /* CONFIG_RWNX_FHOST */ ++ ++#endif /* _RWNX_STRS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c +new file mode 100644 +index 000000000000..7d9afb935ac7 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c +@@ -0,0 +1,786 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tx.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++/** ++ * INCLUDE FILES ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_tdls.h" ++#include "rwnx_compat.h" ++ ++/** ++ * FUNCTION DEFINITIONS ++ ****************************************************************************** ++ */ ++ ++static u16 ++rwnx_get_tdls_sta_capab(struct rwnx_vif *rwnx_vif, u16 status_code) ++{ ++ u16 capab = 0; ++ ++ /* The capability will be 0 when sending a failure code */ ++ if (status_code != 0) ++ return capab; ++ ++ if (rwnx_vif->sta.ap->band != NL80211_BAND_2GHZ) ++ return capab; ++ ++ capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; ++ capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; ++ ++ return capab; ++} ++ ++static int ++rwnx_tdls_prepare_encap_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, struct sk_buff *skb) ++{ ++ struct ieee80211_tdls_data *tf; ++ tf = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_data) - sizeof(tf->u)); ++ ++ // set eth header ++ memcpy(tf->da, peer, ETH_ALEN); ++ memcpy(tf->sa, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ tf->ether_type = cpu_to_be16(ETH_P_TDLS); ++ ++ // set common TDLS info ++ tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; ++ tf->category = WLAN_CATEGORY_TDLS; ++ tf->action_code = action_code; ++ ++ // set action specific TDLS info ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ skb_put(skb, sizeof(tf->u.setup_req)); ++ tf->u.setup_req.dialog_token = dialog_token; ++ tf->u.setup_req.capability = ++ cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code)); ++ break; ++ ++ case WLAN_TDLS_SETUP_RESPONSE: ++ skb_put(skb, sizeof(tf->u.setup_resp)); ++ tf->u.setup_resp.status_code = cpu_to_le16(status_code); ++ tf->u.setup_resp.dialog_token = dialog_token; ++ tf->u.setup_resp.capability = ++ cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code)); ++ break; ++ ++ case WLAN_TDLS_SETUP_CONFIRM: ++ skb_put(skb, sizeof(tf->u.setup_cfm)); ++ tf->u.setup_cfm.status_code = cpu_to_le16(status_code); ++ tf->u.setup_cfm.dialog_token = dialog_token; ++ break; ++ ++ case WLAN_TDLS_TEARDOWN: ++ skb_put(skb, sizeof(tf->u.teardown)); ++ tf->u.teardown.reason_code = cpu_to_le16(status_code); ++ break; ++ ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ skb_put(skb, sizeof(tf->u.discover_req)); ++ tf->u.discover_req.dialog_token = dialog_token; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++rwnx_prep_tdls_direct(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt; ++ ++ mgmt = (void *)skb_put(skb, 24); ++ memset(mgmt, 0, 24); ++ memcpy(mgmt->da, peer, ETH_ALEN); ++ memcpy(mgmt->sa, rwnx_hw->wiphy->perm_addr, ETH_ALEN); ++ memcpy(mgmt->bssid, rwnx_vif->sta.ap->mac_addr, ETH_ALEN); ++ ++ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | ++ IEEE80211_STYPE_ACTION); ++ ++ switch (action_code) { ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); ++ mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; ++ mgmt->u.action.u.tdls_discover_resp.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES; ++ mgmt->u.action.u.tdls_discover_resp.dialog_token = dialog_token; ++ mgmt->u.action.u.tdls_discover_resp.capability = ++ cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++rwnx_add_srates_ie(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ u8 i, rates, *pos; ++ int rate; ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ rates = 8; ++ ++ if (skb_tailroom(skb) < rates + 2) ++ return -ENOMEM; ++ ++ pos = skb_put(skb, rates + 2); ++ *pos++ = WLAN_EID_SUPP_RATES; ++ *pos++ = rates; ++ for (i = 0; i < rates; i++) { ++ rate = rwnx_band_2GHz->bitrates[i].bitrate; ++ rate = DIV_ROUND_UP(rate, 5); ++ *pos++ = (u8)rate; ++ } ++ ++ return 0; ++} ++ ++static int ++rwnx_add_ext_srates_ie(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ u8 i, exrates, *pos; ++ int rate; ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ ++ exrates = rwnx_band_2GHz->n_bitrates - 8; ++ ++ if (skb_tailroom(skb) < exrates + 2) ++ return -ENOMEM; ++ ++ pos = skb_put(skb, exrates + 2); ++ *pos++ = WLAN_EID_EXT_SUPP_RATES; ++ *pos++ = exrates; ++ for (i = 8; i < (8+exrates); i++) { ++ rate = rwnx_band_2GHz->bitrates[i].bitrate; ++ rate = DIV_ROUND_UP(rate, 5); ++ *pos++ = (u8)rate; ++ } ++ ++ return 0; ++} ++ ++static void ++rwnx_tdls_add_supp_channels(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ /* ++ * Add possible channels for TDLS. These are channels that are allowed ++ * to be active. ++ */ ++ u8 subband_cnt = 0; ++ u8 *pos_subband; ++ u8 *pos = skb_put(skb, 2); ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ]; ++ ++ *pos++ = WLAN_EID_SUPPORTED_CHANNELS; ++ ++ /* ++ * 5GHz and 2GHz channels numbers can overlap. Ignore this for now, as ++ * this doesn't happen in real world scenarios. ++ */ ++ ++ /* 2GHz, with 5MHz spacing */ ++ pos_subband = skb_put(skb, 2); ++ if (rwnx_band_2GHz->n_channels > 0) { ++ *pos_subband++ = ieee80211_frequency_to_channel(rwnx_band_2GHz->channels[0].center_freq); ++ *pos_subband++ = rwnx_band_2GHz->n_channels; ++ subband_cnt++; ++ } ++ ++ /* 5GHz, with 20MHz spacing */ ++ pos_subband = skb_put(skb, 2); ++ if (rwnx_hw->band_5g_support) { ++ if (rwnx_band_5GHz->n_channels > 0) { ++ *pos_subband++ = ieee80211_frequency_to_channel(rwnx_band_5GHz->channels[0].center_freq); ++ *pos_subband++ = rwnx_band_5GHz->n_channels; ++ subband_cnt++; ++ } ++ } ++ /* length */ ++ *pos = 2 * subband_cnt; ++} ++ ++static void ++rwnx_tdls_add_ext_capab(struct rwnx_hw *rwnx_hw, struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 7); ++ bool chan_switch = rwnx_hw->wiphy->features & ++ NL80211_FEATURE_TDLS_CHANNEL_SWITCH; ++ ++ *pos++ = WLAN_EID_EXT_CAPABILITY; ++ *pos++ = 5; /* len */ ++ *pos++ = 0x0; ++ *pos++ = 0x0; ++ *pos++ = 0x0; ++ *pos++ = WLAN_EXT_CAPA4_TDLS_BUFFER_STA | ++ (chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0); ++ *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; ++} ++ ++static void ++rwnx_add_wmm_info_ie(struct sk_buff *skb, u8 qosinfo) ++{ ++ u8 *pos = (void *)skb_put(skb, 9); ++ ++ *pos++ = WLAN_EID_VENDOR_SPECIFIC; ++ *pos++ = 7; /* len */ ++ *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ ++ *pos++ = 0x50; ++ *pos++ = 0xf2; ++ *pos++ = 2; /* WME */ ++ *pos++ = 0; /* WME info */ ++ *pos++ = 1; /* WME ver */ ++ *pos++ = qosinfo; /* U-APSD no in use */ ++} ++ ++/* translate numbering in the WMM parameter IE to the mac80211 notation */ ++static u8 rwnx_ac_from_wmm(int ac) ++{ ++ switch (ac) { ++ default: ++ WARN_ON_ONCE(1); ++ __attribute__((__fallthrough__)); ++ case 0: ++ return AC_BE; ++ case 1: ++ return AC_BK; ++ case 2: ++ return AC_VI; ++ case 3: ++ return AC_VO; ++ } ++} ++ ++static void ++rwnx_add_wmm_param_ie(struct sk_buff *skb, u8 acm_bits, u32 *ac_params) ++{ ++ struct ieee80211_wmm_param_ie *wmm; ++ int i, j; ++ u8 cw_min, cw_max; ++ bool acm; ++ ++ wmm = (void *)skb_put(skb, sizeof(struct ieee80211_wmm_param_ie)); ++ memset(wmm, 0, sizeof(*wmm)); ++ ++ wmm->element_id = WLAN_EID_VENDOR_SPECIFIC; ++ wmm->len = sizeof(*wmm) - 2; ++ ++ wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */ ++ wmm->oui[1] = 0x50; ++ wmm->oui[2] = 0xf2; ++ wmm->oui_type = 2; /* WME */ ++ wmm->oui_subtype = 1; /* WME param */ ++ wmm->version = 1; /* WME ver */ ++ wmm->qos_info = 0; /* U-APSD not in use */ ++ ++ /* ++ * Use the EDCA parameters defined for the BSS, or default if the AP ++ * doesn't support it, as mandated by 802.11-2012 section 10.22.4 ++ */ ++ for (i = 0; i < AC_MAX; i++) { ++ j = rwnx_ac_from_wmm(i); ++ cw_min = (ac_params[j] & 0xF0) >> 4; ++ cw_max = (ac_params[j] & 0xF00) >> 8; ++ acm = (acm_bits & (1 << j)) != 0; ++ ++ wmm->ac[i].aci_aifsn = (i << 5) | (acm << 4) | (ac_params[j] & 0xF); ++ wmm->ac[i].cw = (cw_max << 4) | cw_min; ++ wmm->ac[i].txop_limit = (ac_params[j] & 0x0FFFF000) >> 12; ++ } ++} ++ ++static void ++rwnx_tdls_add_oper_classes(struct rwnx_vif *rwnx_vif, struct sk_buff *skb) ++{ ++ u8 *pos; ++ u8 op_class; ++ struct cfg80211_chan_def chan_def; ++ struct ieee80211_channel chan; ++ ++ chan.band = rwnx_vif->sta.ap->band; ++ chan.center_freq = rwnx_vif->sta.ap->center_freq; ++ chan_def.chan = &chan; ++ chan_def.width = rwnx_vif->sta.ap->width; ++ chan_def.center_freq1 = rwnx_vif->sta.ap->center_freq1; ++ chan_def.center_freq2 = rwnx_vif->sta.ap->center_freq2; ++#ifdef CONFIG_GKI ++ if (!rwnx_ieee80211_chandef_to_operating_class(&chan_def, &op_class)) ++#else ++ if (!ieee80211_chandef_to_operating_class(&chan_def, &op_class)) ++#endif ++ return; ++ ++ pos = skb_put(skb, 4); ++ *pos++ = WLAN_EID_SUPPORTED_REGULATORY_CLASSES; ++ *pos++ = 2; /* len */ ++ ++ // current op class ++ *pos++ = op_class; ++ *pos++ = op_class; /* give current operating class as alternate too */ ++ ++ // need to add 5GHz classes? ++} ++ ++static void ++rwnx_ie_build_ht_cap(struct sk_buff *skb, struct ieee80211_sta_ht_cap *ht_cap, ++ u16 cap) ++{ ++ u8 *pos; ++ __le16 tmp; ++ ++ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); ++ *pos++ = WLAN_EID_HT_CAPABILITY; ++ *pos++ = sizeof(struct ieee80211_ht_cap); ++ memset(pos, 0, sizeof(struct ieee80211_ht_cap)); ++ ++ /* capability flags */ ++ tmp = cpu_to_le16(cap); ++ memcpy(pos, &tmp, sizeof(u16)); ++ pos += sizeof(u16); ++ ++ /* AMPDU parameters */ ++ *pos++ = ht_cap->ampdu_factor | ++ (ht_cap->ampdu_density << ++ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); ++ ++ /* MCS set */ ++ memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs)); ++ pos += sizeof(ht_cap->mcs); ++ ++ /* extended capabilities */ ++ pos += sizeof(__le16); ++ ++ /* BF capabilities */ ++ pos += sizeof(__le32); ++ ++ /* antenna selection */ ++ pos += sizeof(u8); ++} ++ ++static void ++rwnx_ie_build_vht_cap(struct sk_buff *skb, struct ieee80211_sta_vht_cap *vht_cap, ++ u32 cap) ++{ ++ u8 *pos; ++ __le32 tmp; ++ ++ pos = skb_put(skb, 14); ++ ++ *pos++ = WLAN_EID_VHT_CAPABILITY; ++ *pos++ = sizeof(struct ieee80211_vht_cap); ++ memset(pos, 0, sizeof(struct ieee80211_vht_cap)); ++ ++ /* capability flags */ ++ tmp = cpu_to_le32(cap); ++ memcpy(pos, &tmp, sizeof(u32)); ++ pos += sizeof(u32); ++ ++ /* VHT MCS set */ ++ memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs)); ++ pos += sizeof(vht_cap->vht_mcs); ++} ++ ++static void ++rwnx_tdls_add_bss_coex_ie(struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 3); ++ ++ *pos++ = WLAN_EID_BSS_COEX_2040; ++ *pos++ = 1; /* len */ ++ ++ *pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST; ++} ++ ++static void ++rwnx_tdls_add_link_ie(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, ++ bool initiator) ++{ ++ struct ieee80211_tdls_lnkie *lnkid; ++ const u8 *init_addr, *rsp_addr; ++ ++ if (initiator) { ++ init_addr = rwnx_hw->wiphy->perm_addr; ++ rsp_addr = peer; ++ } else { ++ init_addr = peer; ++ rsp_addr = rwnx_hw->wiphy->perm_addr; ++ } ++ ++ lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); ++ ++ lnkid->ie_type = WLAN_EID_LINK_ID; ++ lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; ++ ++ memcpy(lnkid->bssid, rwnx_vif->sta.ap->mac_addr, ETH_ALEN); ++ memcpy(lnkid->init_sta, init_addr, ETH_ALEN); ++ memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN); ++} ++ ++static void ++rwnx_tdls_add_aid_ie(struct rwnx_vif *rwnx_vif, struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 4); ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) ++ *pos++ = WLAN_EID_AID; ++ #else ++ *pos++ = 197; ++ #endif ++ *pos++ = 2; /* len */ ++ *pos++ = rwnx_vif->sta.ap->aid; ++} ++ ++static u8 * ++rwnx_ie_build_ht_oper(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, ++ u16 prot_mode) ++{ ++ struct ieee80211_ht_operation *ht_oper; ++ /* Build HT Information */ ++ *pos++ = WLAN_EID_HT_OPERATION; ++ *pos++ = sizeof(struct ieee80211_ht_operation); ++ ht_oper = (struct ieee80211_ht_operation *)pos; ++ ht_oper->primary_chan = ieee80211_frequency_to_channel( ++ rwnx_vif->sta.ap->center_freq); ++ switch (rwnx_vif->sta.ap->width) { ++ case NL80211_CHAN_WIDTH_160: ++ case NL80211_CHAN_WIDTH_80P80: ++ case NL80211_CHAN_WIDTH_80: ++ case NL80211_CHAN_WIDTH_40: ++ if (rwnx_vif->sta.ap->center_freq1 > rwnx_vif->sta.ap->center_freq) ++ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; ++ else ++ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; ++ break; ++ default: ++ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; ++ break; ++ } ++ if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && ++ rwnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20_NOHT && ++ rwnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20) ++ ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; ++ ++ ht_oper->operation_mode = cpu_to_le16(prot_mode); ++ ht_oper->stbc_param = 0x0000; ++ ++ /* It seems that Basic MCS set and Supported MCS set ++ are identical for the first 10 bytes */ ++ memset(&ht_oper->basic_set, 0, 16); ++ memcpy(&ht_oper->basic_set, &ht_cap->mcs, 10); ++ ++ return pos + sizeof(struct ieee80211_ht_operation); ++} ++ ++static u8 * ++rwnx_ie_build_vht_oper(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, ++ u16 prot_mode) ++{ ++ struct ieee80211_vht_operation *vht_oper; ++ /* Build HT Information */ ++ *pos++ = WLAN_EID_VHT_OPERATION; ++ *pos++ = sizeof(struct ieee80211_vht_operation); ++ vht_oper = (struct ieee80211_vht_operation *)pos; ++ ++ switch (rwnx_vif->sta.ap->width) { ++ case NL80211_CHAN_WIDTH_80: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; // Channel Width ++ CCFS0(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0 ++ CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.) ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ; // Channel Width ++ CCFS0(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0 ++ CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.) ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ; // Channel Width ++ CCFS0(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq1); // Channel Center Frequency Segment 0 ++ CCFS1(vht_oper) = ++ ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq2); // Channel Center Frequency Segment 1 ++ break; ++ default: ++ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT; ++ CCFS0(vht_oper) = 0; ++ CCFS1(vht_oper) = 0; ++ break; ++ } ++ ++ vht_oper->basic_mcs_set = cpu_to_le16(rwnx_hw->mod_params->mcs_map); ++ ++ return pos + sizeof(struct ieee80211_vht_operation); ++ ++} ++ ++static void ++rwnx_tdls_add_setup_start_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, ++ u8 action_code, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len) ++{ ++ enum nl80211_band band = rwnx_vif->sta.ap->band; ++ struct ieee80211_supported_band *sband; ++ struct ieee80211_sta_ht_cap ht_cap; ++ struct ieee80211_sta_vht_cap vht_cap; ++ size_t offset = 0, noffset; ++ u8 *pos; ++ ++ rcu_read_lock(); ++ ++ rwnx_add_srates_ie(rwnx_hw, skb); ++ rwnx_add_ext_srates_ie(rwnx_hw, skb); ++ rwnx_tdls_add_supp_channels(rwnx_hw, skb); ++ rwnx_tdls_add_ext_capab(rwnx_hw, skb); ++ ++ /* add the QoS element if we support it */ ++ if (/*local->hw.queues >= IEEE80211_NUM_ACS &&*/ ++ action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES) ++ rwnx_add_wmm_info_ie(skb, 0); /* no U-APSD */ ++ ++ rwnx_tdls_add_oper_classes(rwnx_vif, skb); ++ ++ /* ++ * with TDLS we can switch channels, and HT-caps are not necessarily ++ * the same on all bands. The specification limits the setup to a ++ * single HT-cap, so use the current band for now. ++ */ ++ sband = rwnx_hw->wiphy->bands[band]; ++ memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); ++ if (((action_code == WLAN_TDLS_SETUP_REQUEST) || ++ (action_code == WLAN_TDLS_SETUP_RESPONSE) || ++ (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES)) && ++ ht_cap.ht_supported /* (!sta || sta->sta.ht_cap.ht_supported)*/) { ++ rwnx_ie_build_ht_cap(skb, &ht_cap, ht_cap.cap); ++ } ++ ++ if (ht_cap.ht_supported && ++ (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) ++ rwnx_tdls_add_bss_coex_ie(skb); ++ ++ rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator); ++ ++ memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); ++ if (vht_cap.vht_supported) { ++ rwnx_tdls_add_aid_ie(rwnx_vif, skb); ++ rwnx_ie_build_vht_cap(skb, &vht_cap, vht_cap.cap); ++ // Operating mode Notification (optional) ++ } ++ ++ /* add any remaining IEs */ ++ if (extra_ies_len) { ++ noffset = extra_ies_len; ++ pos = skb_put(skb, noffset - offset); ++ memcpy(pos, extra_ies + offset, noffset - offset); ++ } ++ ++ rcu_read_unlock(); ++} ++ ++ ++static void ++rwnx_tdls_add_setup_cfm_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len) ++{ ++ struct ieee80211_supported_band *sband; ++ enum nl80211_band band = rwnx_vif->sta.ap->band; ++ struct ieee80211_sta_ht_cap ht_cap; ++ struct ieee80211_sta_vht_cap vht_cap; ++ ++ size_t offset = 0, noffset; ++ struct rwnx_sta *sta, *ap_sta; ++ u8 *pos; ++ ++ rcu_read_lock(); ++ ++ sta = rwnx_get_sta(rwnx_hw, peer); ++ ap_sta = rwnx_vif->sta.ap; ++ if (WARN_ON_ONCE(!sta || !ap_sta)) { ++ rcu_read_unlock(); ++ return; ++ } ++ ++ /* add the QoS param IE if both the peer and we support it */ ++ if (sta->qos) ++ rwnx_add_wmm_param_ie(skb, ap_sta->acm, ap_sta->ac_param); ++ ++ /* if HT support is only added in TDLS, we need an HT-operation IE */ ++ sband = rwnx_hw->wiphy->bands[band]; ++ memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); ++ if (ht_cap.ht_supported && !ap_sta->ht && sta->ht) { ++ pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); ++ /* send an empty HT operation IE */ ++ rwnx_ie_build_ht_oper(rwnx_hw, rwnx_vif, pos, &ht_cap, 0); ++ } ++ ++ rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator); ++ ++ memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); ++ if (vht_cap.vht_supported && !ap_sta->vht && sta->vht) { ++ pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_operation)); ++ rwnx_ie_build_vht_oper(rwnx_hw, rwnx_vif, pos, &ht_cap, 0); ++ // Operating mode Notification (optional) ++ } ++ ++ /* add any remaining IEs */ ++ if (extra_ies_len) { ++ noffset = extra_ies_len; ++ pos = skb_put(skb, noffset - offset); ++ memcpy(pos, extra_ies + offset, noffset - offset); ++ } ++ ++ rcu_read_unlock(); ++} ++ ++static void ++rwnx_tdls_add_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, const u8 *peer, ++ u8 action_code, u16 status_code, ++ bool initiator, const u8 *extra_ies, ++ size_t extra_ies_len, u8 oper_class, ++ struct cfg80211_chan_def *chandef) ++{ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ if (status_code == 0) ++ rwnx_tdls_add_setup_start_ies(rwnx_hw, rwnx_vif, skb, peer, action_code, ++ initiator, extra_ies, extra_ies_len); ++ break; ++ case WLAN_TDLS_SETUP_CONFIRM: ++ if (status_code == 0) ++ rwnx_tdls_add_setup_cfm_ies(rwnx_hw, rwnx_vif, skb, peer, initiator, ++ extra_ies, extra_ies_len); ++ break; ++ ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ if (extra_ies_len) ++ memcpy(skb_put(skb, extra_ies_len), extra_ies, ++ extra_ies_len); ++ if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN) ++ rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator); ++ break; ++ } ++} ++ ++int ++rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len, u8 oper_class, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct sk_buff *skb; ++ int ret = 0; ++ struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ]; ++ int channels = rwnx_band_2GHz->n_channels; ++ ++ if (rwnx_hw->band_5g_support) ++ channels += rwnx_band_5GHz->n_channels; ++ ++ skb = netdev_alloc_skb(rwnx_vif->ndev, ++ sizeof(struct ieee80211_tdls_data) + // ethhdr + TDLS info ++ 10 + /* supported rates */ ++ 6 + /* extended supported rates */ ++ (2 + channels) + /* supported channels */ ++ sizeof(struct ieee_types_extcap) + ++ sizeof(struct ieee80211_wmm_param_ie) + ++ 4 + /* oper classes */ ++ 28 + //sizeof(struct ieee80211_ht_cap) + ++ sizeof(struct ieee_types_bss_co_2040) + ++ sizeof(struct ieee80211_tdls_lnkie) + ++ (2 + sizeof(struct ieee80211_vht_cap)) + ++ 4 + /*AID*/ ++ (2 + sizeof(struct ieee80211_ht_operation)) + ++ extra_ies_len); ++ ++ if (!skb) ++ return 0; ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ ret = rwnx_tdls_prepare_encap_data(rwnx_hw, rwnx_vif, peer, action_code, ++ dialog_token, status_code, skb); ++ break; ++ ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ ret = rwnx_prep_tdls_direct(rwnx_hw, rwnx_vif, peer, action_code, ++ dialog_token, status_code, skb); ++ break; ++ ++ default: ++ ret = -ENOTSUPP; ++ break; ++ } ++ ++ if (ret < 0) ++ goto fail; ++ ++ rwnx_tdls_add_ies(rwnx_hw, rwnx_vif, skb, peer, action_code, status_code, ++ initiator, extra_ies, extra_ies_len, oper_class, chandef); ++ ++ if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) { ++ u64 cookie; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ struct cfg80211_mgmt_tx_params params; ++ ++ params.len = skb->len; ++ params.buf = skb->data; ++ ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, ¶ms, false, &cookie); ++ #else ++ ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, NULL, false, 0, skb->data, skb->len, false, false, &cookie); ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ ++ return ret; ++ } ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ skb->priority = 2; ++ break; ++ default: ++ skb->priority = 5; ++ break; ++ } ++ ++ ret = rwnx_select_txq(rwnx_vif, skb); ++ ret = rwnx_start_xmit(skb, rwnx_vif->ndev); ++ ++ return ret; ++ ++fail: ++ dev_kfree_skb(skb); ++ return ret; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h +new file mode 100644 +index 000000000000..590b420f6ec6 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h +@@ -0,0 +1,54 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tdls.h ++ * ++ * @brief TDLS function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef RWNX_TDLS_H_ ++#define RWNX_TDLS_H_ ++ ++#include "rwnx_defs.h" ++ ++struct ieee_types_header { ++ u8 element_id; ++ u8 len; ++} __packed; ++ ++struct ieee_types_bss_co_2040 { ++ struct ieee_types_header ieee_hdr; ++ u8 bss_2040co; ++} __packed; ++ ++struct ieee_types_extcap { ++ struct ieee_types_header ieee_hdr; ++ u8 ext_capab[8]; ++} __packed; ++ ++struct ieee_types_vht_cap { ++ struct ieee_types_header ieee_hdr; ++ struct ieee80211_vht_cap vhtcap; ++} __packed; ++ ++struct ieee_types_vht_oper { ++ struct ieee_types_header ieee_hdr; ++ struct ieee80211_vht_operation vhtoper; ++} __packed; ++ ++struct ieee_types_aid { ++ struct ieee_types_header ieee_hdr; ++ u16 aid; ++} __packed; ++ ++int rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, bool initiator, ++ const u8 *extra_ies, size_t extra_ies_len, u8 oper_class, ++ struct cfg80211_chan_def *chandef); ++ ++#endif /* RWNX_TDLS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c +new file mode 100644 +index 000000000000..ef97354d08df +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c +@@ -0,0 +1,230 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_testmode.c ++ * ++ * @brief Test mode function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#include ++#include ++ ++#include "rwnx_testmode.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_dini.h" ++#include "reg_access.h" ++ ++/* ++ * This function handles the user application commands for register access. ++ * ++ * It retrieves command ID carried with RWNX_TM_ATTR_COMMAND and calls to the ++ * handlers respectively. ++ * ++ * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the ++ * mandatory fields(RWNX_TM_ATTR_REG_OFFSET,RWNX_TM_ATTR_REG_VALUE32) ++ * are missing; Otherwise 0 is replied indicating the success of the command execution. ++ * ++ * If RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_READ, the register read ++ * value is returned with RWNX_TM_ATTR_REG_VALUE32. ++ * ++ * @hw: ieee80211_hw object that represents the device ++ * @tb: general message fields from the user space ++ */ ++int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) ++{ ++ struct rwnx_hw *rwnx_hw = hw->priv; ++ u32 mem_addr, val32; ++ struct sk_buff *skb; ++ int status = 0; ++ ++ /* First check if register address is there */ ++ if (!tb[RWNX_TM_ATTR_REG_OFFSET]) { ++ printk("Error finding register offset\n"); ++ return -ENOMSG; ++ } ++ ++ mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]); ++ ++ switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { ++ case RWNX_TM_CMD_APP2DEV_REG_READ: ++ { ++ struct dbg_mem_read_cfm mem_read_cfm; ++ ++ /*** Send the command to the LMAC ***/ ++ status = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &mem_read_cfm); ++ if (status) ++ return status; ++ ++ /* Allocate the answer message */ ++ skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); ++ if (!skb) { ++ printk("Error allocating memory\n"); ++ return -ENOMEM; ++ } ++ ++ val32 = mem_read_cfm.memdata; ++ if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, val32)) ++ goto nla_put_failure; ++ ++ /* Send the answer to upper layer */ ++ status = cfg80211_testmode_reply(skb); ++ if (status < 0) ++ printk("Error sending msg : %d\n", status); ++ } ++ break; ++ ++ case RWNX_TM_CMD_APP2DEV_REG_WRITE: ++ { ++ if (!tb[RWNX_TM_ATTR_REG_VALUE32]) { ++ printk("Error finding value to write\n"); ++ return -ENOMSG; ++ } else { ++ val32 = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]); ++ /* Send the command to the LMAC */ ++ status = rwnx_send_dbg_mem_write_req(rwnx_hw, mem_addr, val32); ++ if (status) ++ return status; ++ } ++ } ++ break; ++ ++ default: ++ printk("Unknown testmode register command ID\n"); ++ return -ENOSYS; ++ } ++ ++ return status; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -EMSGSIZE; ++} ++ ++/* ++ * This function handles the user application commands for Debug filter settings. ++ * ++ * @hw: ieee80211_hw object that represents the device ++ * @tb: general message fields from the user space ++ */ ++int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb) ++{ ++ struct rwnx_hw *rwnx_hw = hw->priv; ++ u32 filter; ++ int status = 0; ++ ++ /* First check if the filter is there */ ++ if (!tb[RWNX_TM_ATTR_REG_FILTER]) { ++ printk("Error finding filter value\n"); ++ return -ENOMSG; ++ } ++ ++ filter = nla_get_u32(tb[RWNX_TM_ATTR_REG_FILTER]); ++ RWNX_DBG("testmode debug filter, setting: 0x%x\n", filter); ++ ++ switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { ++ case RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER: ++ { ++ /* Send the command to the LMAC */ ++ status = rwnx_send_dbg_set_mod_filter_req(rwnx_hw, filter); ++ if (status) ++ return status; ++ } ++ break; ++ case RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER: ++ { ++ /* Send the command to the LMAC */ ++ status = rwnx_send_dbg_set_sev_filter_req(rwnx_hw, filter); ++ if (status) ++ return status; ++ } ++ break; ++ ++ default: ++ printk("Unknown testmode register command ID\n"); ++ return -ENOSYS; ++ } ++ ++ return status; ++} ++ ++/* ++ * This function handles the user application commands for register access without using ++ * the normal LMAC messaging way. ++ * This time register access will be done through direct PCI BAR windows. This can be used ++ * to access registers even when the :AMC FW is stuck. ++ * ++ * @hw: ieee80211_hw object that represents the device ++ * @tb: general message fields from the user space ++ */ ++int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb) ++{ ++ struct rwnx_hw *rwnx_hw = hw->priv; ++ struct rwnx_plat *rwnx_plat = rwnx_hw->plat; ++ u32 mem_addr; ++ struct sk_buff *skb; ++ int status = 0; ++ volatile unsigned int reg_value = 0; ++ unsigned int offset; ++ ++ /* First check if register address is there */ ++ if (!tb[RWNX_TM_ATTR_REG_OFFSET]) { ++ printk("Error finding register offset\n"); ++ return -ENOMSG; ++ } ++ ++ mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]); ++ offset = mem_addr & 0x00FFFFFF; ++ ++ switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { ++ case RWNX_TM_CMD_APP2DEV_REG_READ_DBG: ++ { ++ /*** Send the command to the LMAC ***/ ++ reg_value = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, offset); ++ ++ /* Allocate the answer message */ ++ skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); ++ if (!skb) { ++ printk("Error allocating memory\n"); ++ return -ENOMEM; ++ } ++ ++ if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, reg_value)) ++ goto nla_put_failure; ++ ++ /* Send the answer to upper layer */ ++ status = cfg80211_testmode_reply(skb); ++ if (status < 0) ++ printk("Error sending msg : %d\n", status); ++ } ++ break; ++ ++ case RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG: ++ { ++ if (!tb[RWNX_TM_ATTR_REG_VALUE32]) { ++ printk("Error finding value to write\n"); ++ return -ENOMSG; ++ } else { ++ reg_value = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]); ++ ++ /* Send the command to the LMAC */ ++ RWNX_REG_WRITE(reg_value, rwnx_plat, RWNX_ADDR_SYSTEM, ++ offset); ++ } ++ } ++ break; ++ ++ default: ++ printk("Unknown testmode register command ID\n"); ++ return -ENOSYS; ++ } ++ ++ return status; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -EMSGSIZE; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h +new file mode 100644 +index 000000000000..9d1bca47eb50 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h +@@ -0,0 +1,64 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_testmode.h ++ * ++ * @brief Test mode function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++ ++#ifndef RWNX_TESTMODE_H_ ++#define RWNX_TESTMODE_H_ ++ ++#include ++#include ++ ++/* Commands from user space to kernel space(RWNX_TM_CMD_APP2DEV_XX) and ++ * from and kernel space to user space(RWNX_TM_CMD_DEV2APP_XX). ++ * The command ID is carried with RWNX_TM_ATTR_COMMAND. ++ */ ++enum rwnx_tm_cmd_t { ++ /* commands from user application to access register */ ++ RWNX_TM_CMD_APP2DEV_REG_READ = 1, ++ RWNX_TM_CMD_APP2DEV_REG_WRITE, ++ ++ /* commands from user application to select the Debug levels */ ++ RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER, ++ RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER, ++ ++ /* commands to access registers without sending messages to LMAC layer, ++ * this must be used when LMAC FW is stuck. */ ++ RWNX_TM_CMD_APP2DEV_REG_READ_DBG, ++ RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG, ++ ++ RWNX_TM_CMD_MAX, ++}; ++ ++enum rwnx_tm_attr_t { ++ RWNX_TM_ATTR_NOT_APPLICABLE = 0, ++ ++ RWNX_TM_ATTR_COMMAND, ++ ++ /* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_XXX, ++ * The mandatory fields are: ++ * RWNX_TM_ATTR_REG_OFFSET for the offset of the target register; ++ * RWNX_TM_ATTR_REG_VALUE32 for value */ ++ RWNX_TM_ATTR_REG_OFFSET, ++ RWNX_TM_ATTR_REG_VALUE32, ++ ++ /* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_SET_DBGXXXFILTER, ++ * The mandatory field is RWNX_TM_ATTR_REG_FILTER. */ ++ RWNX_TM_ATTR_REG_FILTER, ++ ++ RWNX_TM_ATTR_MAX, ++}; ++ ++/***********************************************************************/ ++int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb); ++int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb); ++int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb); ++ ++#endif /* RWNX_TESTMODE_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c +new file mode 100644 +index 000000000000..5a57acc20c71 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c +@@ -0,0 +1,2344 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tx.c ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#include ++#include ++#include ++ ++#include "rwnx_defs.h" ++#include "rwnx_tx.h" ++#include "rwnx_msg_tx.h" ++#include "rwnx_mesh.h" ++#include "rwnx_events.h" ++#include "rwnx_compat.h" ++#include "aicwf_txrxif.h" ++#ifdef CONFIG_RWNX_MON_XMIT ++#include ++#endif ++ ++/****************************************************************************** ++ * Power Save functions ++ *****************************************************************************/ ++/** ++ * rwnx_set_traffic_status - Inform FW if traffic is available for STA in PS ++ * ++ * @rwnx_hw: Driver main data ++ * @sta: Sta in PS mode ++ * @available: whether traffic is buffered for the STA ++ * @ps_id: type of PS data requested (@LEGACY_PS_ID or @UAPSD_ID) ++ */ ++void rwnx_set_traffic_status(struct rwnx_hw *rwnx_hw, ++ struct rwnx_sta *sta, ++ bool available, ++ u8 ps_id) ++{ ++ if (sta->tdls.active) { ++ rwnx_send_tdls_peer_traffic_ind_req(rwnx_hw, ++ rwnx_hw->vif_table[sta->vif_idx]); ++ } else { ++ bool uapsd = (ps_id != LEGACY_PS_ID); ++ rwnx_send_me_traffic_ind(rwnx_hw, sta->sta_idx, uapsd, available); ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_traffic_update(sta->sta_idx, available, uapsd); ++#endif ++ } ++} ++ ++/** ++ * rwnx_ps_bh_enable - Enable/disable PS mode for one STA ++ * ++ * @rwnx_hw: Driver main data ++ * @sta: Sta which enters/leaves PS mode ++ * @enable: PS mode status ++ * ++ * This function will enable/disable PS mode for one STA. ++ * When enabling PS mode: ++ * - Stop all STA's txq for RWNX_TXQ_STOP_STA_PS reason ++ * - Count how many buffers are already ready for this STA ++ * - For BC/MC sta, update all queued SKB to use hw_queue BCMC ++ * - Update TIM if some packet are ready ++ * ++ * When disabling PS mode: ++ * - Start all STA's txq for RWNX_TXQ_STOP_STA_PS reason ++ * - For BC/MC sta, update all queued SKB to use hw_queue AC_BE ++ * - Update TIM if some packet are ready (otherwise fw will not update TIM ++ * in beacon for this STA) ++ * ++ * All counter/skb updates are protected from TX path by taking tx_lock ++ * ++ * NOTE: _bh_ in function name indicates that this function is called ++ * from a bottom_half tasklet. ++ */ ++void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ bool enable) ++{ ++ struct rwnx_txq *txq; ++ ++ if (enable) { ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_enable(sta); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ sta->ps.active = true; ++ sta->ps.sp_cnt[LEGACY_PS_ID] = 0; ++ sta->ps.sp_cnt[UAPSD_ID] = 0; ++ rwnx_txq_sta_stop(sta, RWNX_TXQ_STOP_STA_PS, rwnx_hw); ++ ++ if (is_multicast_sta(sta->sta_idx)) { ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ sta->ps.pkt_ready[LEGACY_PS_ID] = skb_queue_len(&txq->sk_list); ++ sta->ps.pkt_ready[UAPSD_ID] = 0; ++ //txq->hwq = &rwnx_hw->hwq[RWNX_HWQ_BCMC]; ++ } else { ++ int i; ++ sta->ps.pkt_ready[LEGACY_PS_ID] = 0; ++ sta->ps.pkt_ready[UAPSD_ID] = 0; ++ foreach_sta_txq(sta, txq, i, rwnx_hw) { ++ sta->ps.pkt_ready[txq->ps_id] += skb_queue_len(&txq->sk_list); ++ } ++ } ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ //if (sta->ps.pkt_ready[LEGACY_PS_ID]) ++ //srwnx_set_traffic_status(rwnx_hw, sta, true, LEGACY_PS_ID); ++ ++ //if (sta->ps.pkt_ready[UAPSD_ID]) ++ // rwnx_set_traffic_status(rwnx_hw, sta, true, UAPSD_ID); ++ } else { ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_disable(sta->sta_idx); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ sta->ps.active = false; ++ ++ if (is_multicast_sta(sta->sta_idx)) { ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ txq->hwq = &rwnx_hw->hwq[RWNX_HWQ_BE]; ++ txq->push_limit = 0; ++ } else { ++ int i; ++ foreach_sta_txq(sta, txq, i, rwnx_hw) { ++ txq->push_limit = 0; ++ } ++ } ++ ++ rwnx_txq_sta_start(sta, RWNX_TXQ_STOP_STA_PS, rwnx_hw); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ if (sta->ps.pkt_ready[LEGACY_PS_ID]) ++ rwnx_set_traffic_status(rwnx_hw, sta, false, LEGACY_PS_ID); ++ ++ //if (sta->ps.pkt_ready[UAPSD_ID]) ++ // rwnx_set_traffic_status(rwnx_hw, sta, false, UAPSD_ID); ++ ++ tasklet_schedule(&rwnx_hw->task); ++ } ++} ++ ++/** ++ * rwnx_ps_bh_traffic_req - Handle traffic request for STA in PS mode ++ * ++ * @rwnx_hw: Driver main data ++ * @sta: Sta which enters/leaves PS mode ++ * @pkt_req: number of pkt to push ++ * @ps_id: type of PS data requested (@LEGACY_PS_ID or @UAPSD_ID) ++ * ++ * This function will make sure that @pkt_req are pushed to fw ++ * whereas the STA is in PS mode. ++ * If request is 0, send all traffic ++ * If request is greater than available pkt, reduce request ++ * Note: request will also be reduce if txq credits are not available ++ * ++ * All counter updates are protected from TX path by taking tx_lock ++ * ++ * NOTE: _bh_ in function name indicates that this function is called ++ * from the bottom_half tasklet. ++ */ ++void rwnx_ps_bh_traffic_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ u16 pkt_req, u8 ps_id) ++{ ++ int pkt_ready_all; ++ struct rwnx_txq *txq; ++ int schedule = 0; ++ ++ //if (WARN(!sta->ps.active, "sta %pM is not in Power Save mode", ++ // sta->mac_addr)) ++ // return; ++ if (!sta->ps.active) { ++ AICWFDBG(LOGTRACE,"sta %pM is not in Power Save mode", sta->mac_addr); ++ return; ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_traffic_req(sta, pkt_req, ps_id); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ /* Fw may ask to stop a service period with PS_SP_INTERRUPTED. This only ++ happens for p2p-go interface if NOA starts during a service period */ ++ if ((pkt_req == PS_SP_INTERRUPTED) && (ps_id == UAPSD_ID)) { ++ int tid; ++ sta->ps.sp_cnt[ps_id] = 0; ++ foreach_sta_txq(sta, txq, tid, rwnx_hw) { ++ txq->push_limit = 0; ++ } ++ goto done; ++ } ++ ++ pkt_ready_all = (sta->ps.pkt_ready[ps_id] - sta->ps.sp_cnt[ps_id]); ++ ++ /* Don't start SP until previous one is finished or we don't have ++ packet ready (which must not happen for U-APSD) */ ++ if (sta->ps.sp_cnt[ps_id] || pkt_ready_all <= 0) { ++ goto done; ++ } ++ ++ /* Adapt request to what is available. */ ++ if (pkt_req == 0 || pkt_req > pkt_ready_all) { ++ pkt_req = pkt_ready_all; ++ } ++ ++ /* Reset the SP counter */ ++ sta->ps.sp_cnt[ps_id] = 0; ++ schedule = 1; ++ ++ /* "dispatch" the request between txq */ ++ if (is_multicast_sta(sta->sta_idx)) { ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ //if (txq->credits <= 0) ++ // goto done; ++ if (pkt_req > txq->credits) ++ pkt_req = txq->credits; ++ txq->push_limit = pkt_req; ++ sta->ps.sp_cnt[ps_id] = pkt_req; ++ rwnx_txq_add_to_hw_list(txq); ++ } else { ++ int i, tid; ++ ++ //foreach_sta_txq_prio(sta, txq, tid, i, rwnx_hw) { ++ for (i = 0; i < NX_NB_TID_PER_STA; i++) { ++ u16 txq_len; ++ tid = nx_tid_prio[i]; ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ txq_len = skb_queue_len(&txq->sk_list); ++ ++ if (txq->ps_id != ps_id) ++ continue; ++ ++ if (txq_len > txq->credits) ++ txq_len = txq->credits; ++ ++ if (txq_len == 0) ++ continue; ++ ++ if (txq_len < pkt_req) { ++ /* Not enough pkt queued in this txq, add this ++ txq to hwq list and process next txq */ ++ pkt_req -= txq_len; ++ txq->push_limit = txq_len; ++ sta->ps.sp_cnt[ps_id] += txq_len; ++ rwnx_txq_add_to_hw_list(txq); ++ } else { ++ /* Enough pkt in this txq to comlete the request ++ add this txq to hwq list and stop processing txq */ ++ txq->push_limit = pkt_req; ++ sta->ps.sp_cnt[ps_id] += pkt_req; ++ rwnx_txq_add_to_hw_list(txq); ++ break; ++ } ++ } ++ } ++ ++done: ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ if (schedule) ++ tasklet_schedule(&rwnx_hw->task); ++} ++ ++/****************************************************************************** ++ * TX functions ++ *****************************************************************************/ ++#define PRIO_STA_NULL 0xAA ++ ++static const int rwnx_down_hwq2tid[3] = { ++ [RWNX_HWQ_BK] = 2, ++ [RWNX_HWQ_BE] = 3, ++ [RWNX_HWQ_VI] = 5, ++}; ++ ++static void rwnx_downgrade_ac(struct rwnx_sta *sta, struct sk_buff *skb) ++{ ++ int8_t ac = rwnx_tid2hwq[skb->priority]; ++ ++ if (WARN((ac > RWNX_HWQ_VO), ++ "Unexepcted ac %d for skb before downgrade", ac)) ++ ac = RWNX_HWQ_VO; ++ ++ while (sta->acm & BIT(ac)) { ++ if (ac == RWNX_HWQ_BK) { ++ skb->priority = 1; ++ return; ++ } ++ ac--; ++ skb->priority = rwnx_down_hwq2tid[ac]; ++ } ++} ++ ++u16 rwnx_select_txq(struct rwnx_vif *rwnx_vif, struct sk_buff *skb) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct wireless_dev *wdev = &rwnx_vif->wdev; ++ struct rwnx_sta *sta = NULL; ++ struct rwnx_txq *txq; ++ u16 netdev_queue; ++ bool tdls_mgmgt_frame = false; ++ int nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC; ++ } ++ ++ switch (wdev->iftype) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ { ++ struct ethhdr *eth; ++ eth = (struct ethhdr *)skb->data; ++ if (eth->h_proto == cpu_to_be16(ETH_P_TDLS)) { ++ tdls_mgmgt_frame = true; ++ } ++ if ((rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) && ++ (rwnx_vif->sta.tdls_sta != NULL) && ++ (memcmp(eth->h_dest, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) ++ sta = rwnx_vif->sta.tdls_sta; ++ else ++ sta = rwnx_vif->sta.ap; ++ break; ++ } ++ case NL80211_IFTYPE_AP_VLAN: ++ if (rwnx_vif->ap_vlan.sta_4a) { ++ sta = rwnx_vif->ap_vlan.sta_4a; ++ break; ++ } ++ ++ /* AP_VLAN interface is not used for a 4A STA, ++ fallback searching sta amongs all AP's clients */ ++ rwnx_vif = rwnx_vif->ap_vlan.master; ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ { ++ struct rwnx_sta *cur; ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ ++ if (is_multicast_ether_addr(eth->h_dest)) { ++ sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ } else { ++ spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ list_for_each_entry(cur, &rwnx_vif->ap.sta_list, list) { ++ if (!memcmp(cur->mac_addr, eth->h_dest, ETH_ALEN)) { ++ sta = cur; ++ break; ++ } ++ } ++ spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock); ++ } ++ ++ break; ++ } ++ case NL80211_IFTYPE_MESH_POINT: ++ { ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ ++ if (!rwnx_vif->is_resending) { ++ /* ++ * If ethernet source address is not the address of a mesh wireless interface, we are proxy for ++ * this address and have to inform the HW ++ */ ++ if (memcmp(ð->h_source[0], &rwnx_vif->ndev->perm_addr[0], ETH_ALEN)) { ++ /* Check if LMAC is already informed */ ++ if (!rwnx_get_mesh_proxy_info(rwnx_vif, (u8 *)ð->h_source, true)) { ++ rwnx_send_mesh_proxy_add_req(rwnx_hw, rwnx_vif, (u8 *)ð->h_source); ++ } ++ } ++ } ++ ++ if (is_multicast_ether_addr(eth->h_dest)) { ++ sta = &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index]; ++ } else { ++ /* Path to be used */ ++ struct rwnx_mesh_path *p_mesh_path = NULL; ++ struct rwnx_mesh_path *p_cur_path; ++ /* Check if destination is proxied by a peer Mesh STA */ ++ struct rwnx_mesh_proxy *p_mesh_proxy = rwnx_get_mesh_proxy_info(rwnx_vif, (u8 *)ð->h_dest, false); ++ /* Mesh Target address */ ++ struct mac_addr *p_tgt_mac_addr; ++ ++ if (p_mesh_proxy) { ++ p_tgt_mac_addr = &p_mesh_proxy->proxy_addr; ++ } else { ++ p_tgt_mac_addr = (struct mac_addr *)ð->h_dest; ++ } ++ ++ /* Look for path with provided target address */ ++ list_for_each_entry(p_cur_path, &rwnx_vif->ap.mpath_list, list) { ++ if (!memcmp(&p_cur_path->tgt_mac_addr, p_tgt_mac_addr, ETH_ALEN)) { ++ p_mesh_path = p_cur_path; ++ break; ++ } ++ } ++ ++ if (p_mesh_path) { ++ sta = p_mesh_path->p_nhop_sta; ++ } else { ++ rwnx_send_mesh_path_create_req(rwnx_hw, rwnx_vif, (u8 *)p_tgt_mac_addr); ++ } ++ } ++ ++ break; ++ } ++ default: ++ break; ++ } ++ ++ if (sta && sta->qos) { ++ if (tdls_mgmgt_frame) { ++ skb_set_queue_mapping(skb, NX_STA_NDEV_IDX(skb->priority, sta->sta_idx)); ++ } else { ++ /* use the data classifier to determine what 802.1d tag the ++ * data frame has */ ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) ++ skb->priority = cfg80211_classify8021d(skb) & IEEE80211_QOS_CTL_TAG1D_MASK; ++ #else ++ skb->priority = cfg80211_classify8021d(skb, NULL) & IEEE80211_QOS_CTL_TAG1D_MASK; ++ #endif ++ } ++ if (sta->acm) ++ rwnx_downgrade_ac(sta, skb); ++ ++ txq = rwnx_txq_sta_get(sta, skb->priority, rwnx_hw); ++ netdev_queue = txq->ndev_idx; ++ } else if (sta) { ++ skb->priority = 0xFF; ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ netdev_queue = txq->ndev_idx; ++ } else { ++ /* This packet will be dropped in xmit function, still need to select ++ an active queue for xmit to be called. As it most likely to happen ++ for AP interface, select BCMC queue ++ (TODO: select another queue if BCMC queue is stopped) */ ++ skb->priority = PRIO_STA_NULL; ++ netdev_queue = nx_bcmc_txq_ndev_idx; ++ } ++ ++#ifndef CONFIG_ONE_TXQ ++ BUG_ON(netdev_queue >= NX_NB_NDEV_TXQ); ++#endif ++ ++ return netdev_queue; ++} ++ ++/** ++ * rwnx_set_more_data_flag - Update MORE_DATA flag in tx sw desc ++ * ++ * @rwnx_hw: Driver main data ++ * @sw_txhdr: Header for pkt to be pushed ++ * ++ * If STA is in PS mode ++ * - Set EOSP in case the packet is the last of the UAPSD service period ++ * - Set MORE_DATA flag if more pkt are ready for this sta ++ * - Update TIM if this is the last pkt buffered for this sta ++ * ++ * note: tx_lock already taken. ++ */ ++static inline void rwnx_set_more_data_flag(struct rwnx_hw *rwnx_hw, ++ struct rwnx_sw_txhdr *sw_txhdr) ++{ ++ struct rwnx_sta *sta = sw_txhdr->rwnx_sta; ++ struct rwnx_vif *vif = sw_txhdr->rwnx_vif; ++ struct rwnx_txq *txq = sw_txhdr->txq; ++ ++ if (unlikely(sta->ps.active)) { ++ sta->ps.pkt_ready[txq->ps_id]--; ++ sta->ps.sp_cnt[txq->ps_id]--; ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_push(sta); ++#endif ++ if (((txq->ps_id == UAPSD_ID) || (vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) || (sta->tdls.active)) ++ && !sta->ps.sp_cnt[txq->ps_id]) { ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_EOSP; ++ } ++ ++ if (sta->ps.pkt_ready[txq->ps_id]) { ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_MORE_DATA; ++ } else { ++ rwnx_set_traffic_status(rwnx_hw, sta, false, txq->ps_id); ++ } ++ } ++} ++ ++/** ++ * rwnx_get_tx_priv - Get STA and tid for one skb ++ * ++ * @rwnx_vif: vif ptr ++ * @skb: skb ++ * @tid: pointer updated with the tid to use for this skb ++ * ++ * @return: pointer on the destination STA (may be NULL) ++ * ++ * skb has already been parsed in rwnx_select_queue function ++ * simply re-read information form skb. ++ */ ++static struct rwnx_sta *rwnx_get_tx_priv(struct rwnx_vif *rwnx_vif, ++ struct sk_buff *skb, ++ u8 *tid) ++{ ++ static struct rwnx_hw *rwnx_hw; ++ struct rwnx_sta *sta; ++ int sta_idx; ++ int nx_remote_sta_max = NX_REMOTE_STA_MAX; ++ int nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX; ++ ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_remote_sta_max = NX_REMOTE_STA_MAX_FOR_OLD_IC; ++ nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC; ++ } ++ ++ ++ rwnx_hw = rwnx_vif->rwnx_hw; ++ *tid = skb->priority; ++ if (unlikely(skb->priority == PRIO_STA_NULL)) { ++ return NULL; ++ } else { ++ int ndev_idx = skb_get_queue_mapping(skb); ++ ++ if (ndev_idx == nx_bcmc_txq_ndev_idx) ++ sta_idx = nx_remote_sta_max + master_vif_idx(rwnx_vif); ++ else ++ sta_idx = ndev_idx / NX_NB_TID_PER_STA; ++ ++ sta = &rwnx_hw->sta_table[sta_idx]; ++ } ++ ++ return sta; ++} ++ ++/** ++ * rwnx_prep_tx - Prepare buffer for DMA transmission ++ * ++ * @rwnx_hw: Driver main data ++ * @txhdr: Tx descriptor ++ * ++ * Maps hw_txhdr and buffer data for transmission via DMA. ++ * - Data buffer with be downloaded by embebded side. ++ * - hw_txhdr will be uploaded by embedded side when buffer has been ++ * transmitted over the air. ++ */ ++static int rwnx_prep_tx(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr) ++{ ++#if 0 ++ struct rwnx_sw_txhdr *sw_txhdr = txhdr->sw_hdr; ++ struct rwnx_hw_txhdr *hw_txhdr = &txhdr->hw_hdr; ++ dma_addr_t dma_addr; ++ ++ /* MAP (and sync) memory for DMA */ ++ dma_addr = dma_map_single(rwnx_hw->dev, hw_txhdr, ++ sw_txhdr->map_len, DMA_BIDIRECTIONAL); ++ if (WARN_ON(dma_mapping_error(rwnx_hw->dev, dma_addr))) ++ return -1; ++ ++ sw_txhdr->dma_addr = dma_addr; ++#endif ++ return 0; ++} ++ ++/** ++ * rwnx_tx_push - Push one packet to fw ++ * ++ * @rwnx_hw: Driver main data ++ * @txhdr: tx desc of the buffer to push ++ * @flags: push flags (see @rwnx_push_flags) ++ * ++ * Push one packet to fw. Sw desc of the packet has already been updated. ++ * Only MORE_DATA flag will be set if needed. ++ */ ++void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags) ++{ ++ struct rwnx_sw_txhdr *sw_txhdr = txhdr->sw_hdr; ++ struct sk_buff *skb = sw_txhdr->skb; ++ struct rwnx_txq *txq = sw_txhdr->txq; ++ u16 hw_queue = txq->hwq->id; ++ int user = 0; ++ ++ lockdep_assert_held(&rwnx_hw->tx_lock); ++ ++ //printk("rwnx_tx_push\n"); ++ /* RETRY flag is not always set so retest here */ ++ if (txq->nb_retry) { ++ flags |= RWNX_PUSH_RETRY; ++ txq->nb_retry--; ++ if (txq->nb_retry == 0) { ++ WARN(skb != txq->last_retry_skb, ++ "last retry buffer is not the expected one"); ++ txq->last_retry_skb = NULL; ++ } ++ } else if (!(flags & RWNX_PUSH_RETRY)) { ++ txq->pkt_sent++; ++ } ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (txq->amsdu == sw_txhdr) { ++ WARN((flags & RWNX_PUSH_RETRY), "End A-MSDU on a retry"); ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].done++; ++ txq->amsdu = NULL; ++ } else if (!(flags & RWNX_PUSH_RETRY) && ++ !(sw_txhdr->desc.host.flags & TXU_CNTRL_AMSDU)) { ++ rwnx_hw->stats.amsdus[0].done++; ++ } ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++ /* Wait here to update hw_queue, as for multicast STA hwq may change ++ between queue and push (because of PS) */ ++ sw_txhdr->hw_queue = hw_queue; ++ ++ //sw_txhdr->desc.host.packet_addr = hw_queue; //use packet_addr field for hw_txq ++ sw_txhdr->desc.host.ac = hw_queue; //use ac field for hw_txq ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ /* MU group is only selected during hwq processing */ ++ sw_txhdr->desc.host.mumimo_info = txq->mumimo_info; ++ user = RWNX_TXQ_POS_ID(txq); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++ if (sw_txhdr->rwnx_sta) { ++ /* only for AP mode */ ++ rwnx_set_more_data_flag(rwnx_hw, sw_txhdr); ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_push_desc(skb, sw_txhdr, flags); ++#endif ++ #if 0 ++ txq->credits--; ++ #endif ++ txq->pkt_pushed[user]++; ++ //printk("txq->credits=%d\n",txq->credits); ++ #if 0 ++ if (txq->credits <= 0) ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); ++ #endif ++ ++ if (txq->push_limit) ++ txq->push_limit--; ++#if 0 ++ rwnx_ipc_txdesc_push(rwnx_hw, &sw_txhdr->desc, skb, hw_queue, user); ++#else ++#ifdef AICWF_SDIO_SUPPORT ++ if (((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT) && \ ++ ((*(skb->data+sw_txhdr->headroom) == 0xd0) || (*(skb->data+sw_txhdr->headroom) == 0x10) || (*(skb->data+sw_txhdr->headroom) == 0x30))) || \ ++ (sw_txhdr->desc.host.ethertype == 0x8e88) || (sw_txhdr->desc.host.ethertype == 0xb488)) { ++ sw_txhdr->need_cfm = 1; ++ sw_txhdr->desc.host.hostid = ((1<<31) | rwnx_hw->sdio_env.txdesc_free_idx[0]); ++ aicwf_sdio_host_txdesc_push(&(rwnx_hw->sdio_env), 0, (long)skb); ++ if((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT)) ++ AICWFDBG(LOGINFO, "need cfm mgmt:%x,user_idx=%d, skb=%p\n", *(skb->data+sw_txhdr->headroom), rwnx_hw->sdio_env.txdesc_free_idx[0], skb); ++ else ++ AICWFDBG(LOGINFO, "need cfm ethertype:%8x,user_idx=%d, skb=%p\n", sw_txhdr->desc.host.ethertype, rwnx_hw->sdio_env.txdesc_free_idx[0], skb); ++ } else { ++ sw_txhdr->need_cfm = 0; ++ sw_txhdr->desc.host.hostid = 0; ++ if (sw_txhdr->raw_frame) { ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_MGMT; ++ AICWFDBG(LOGDEBUG, "%s TXU_CNTRL_MGMT sw_txhdr->desc.host.flags:%x\r\n", __func__, ++ sw_txhdr->desc.host.flags); ++ } ++ if (sw_txhdr->fixed_rate) { ++ sw_txhdr->desc.host.hostid = (0x01UL << 30) | sw_txhdr->rate_config; ++ AICWFDBG(LOGDEBUG, "%s TXU_CNTRL_MGMT hostid:%x\r\n", __func__, ++ sw_txhdr->desc.host.hostid); ++ } else { ++ sw_txhdr->desc.host.hostid = 0; ++ } ++ ++ sw_txhdr->rwnx_vif->net_stats.tx_packets++; ++ sw_txhdr->rwnx_vif->net_stats.tx_bytes += sw_txhdr->frame_len; ++ rwnx_hw->stats.last_tx = jiffies; ++ } ++ aicwf_frame_tx((void *)(rwnx_hw->sdiodev), skb); ++#endif ++#ifdef AICWF_USB_SUPPORT ++ if (((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT) && \ ++ ((*(skb->data+sw_txhdr->headroom) == 0xd0) || (*(skb->data+sw_txhdr->headroom) == 0x10) || (*(skb->data+sw_txhdr->headroom) == 0x30))) || \ ++ (sw_txhdr->desc.host.ethertype == 0x8e88)) { ++ printk("push need cfm flags 0x%x\n", sw_txhdr->desc.host.flags); ++ sw_txhdr->need_cfm = 1; ++ sw_txhdr->desc.host.hostid = ((1<<31) | rwnx_hw->usb_env.txdesc_free_idx[0]); ++ aicwf_usb_host_txdesc_push(&(rwnx_hw->usb_env), 0, (long)(skb)); ++ } else { ++ sw_txhdr->need_cfm = 0; ++ sw_txhdr->desc.host.hostid = 0; ++ ++ sw_txhdr->rwnx_vif->net_stats.tx_packets++; ++ sw_txhdr->rwnx_vif->net_stats.tx_bytes += sw_txhdr->frame_len; ++ rwnx_hw->stats.last_tx = jiffies; ++ } ++ aicwf_frame_tx((void *)(rwnx_hw->usbdev), skb); ++#endif ++#endif ++#if 0 ++ txq->hwq->credits[user]--; ++#endif ++ rwnx_hw->stats.cfm_balance[hw_queue]++; ++} ++ ++ ++ ++/** ++ * rwnx_tx_retry - Push an AMPDU pkt that need to be retried ++ * ++ * @rwnx_hw: Driver main data ++ * @skb: pkt to re-push ++ * @txhdr: tx desc of the pkt to re-push ++ * @sw_retry: Indicates if fw decide to retry this buffer ++ * (i.e. it has never been transmitted over the air) ++ * ++ * Called when a packet needs to be repushed to the firmware. ++ * First update sw descriptor and then queue it in the retry list. ++ */ ++static void rwnx_tx_retry(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, ++ struct rwnx_txhdr *txhdr, bool sw_retry) ++{ ++ struct rwnx_sw_txhdr *sw_txhdr = txhdr->sw_hdr; ++ struct tx_cfm_tag *cfm = &txhdr->hw_hdr.cfm; ++ struct rwnx_txq *txq = sw_txhdr->txq; ++ int peek_off = offsetof(struct rwnx_hw_txhdr, cfm); ++ int peek_len = sizeof(((struct rwnx_hw_txhdr *)0)->cfm); ++ ++ if (!sw_retry) { ++ /* update sw desc */ ++ #if 0 ++ sw_txhdr->desc.host.sn = cfm->sn; ++ sw_txhdr->desc.host.pn[0] = cfm->pn[0]; ++ sw_txhdr->desc.host.pn[1] = cfm->pn[1]; ++ sw_txhdr->desc.host.pn[2] = cfm->pn[2]; ++ sw_txhdr->desc.host.pn[3] = cfm->pn[3]; ++ sw_txhdr->desc.host.timestamp = cfm->timestamp; ++ #endif ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_RETRY; ++ ++ #ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->desc.host.flags & TXU_CNTRL_AMSDU) ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].failed++; ++ #endif ++ } ++ ++ /* MORE_DATA will be re-set if needed when pkt will be repushed */ ++ sw_txhdr->desc.host.flags &= ~TXU_CNTRL_MORE_DATA; ++ ++ cfm->status.value = 0; ++ dma_sync_single_for_device(rwnx_hw->dev, sw_txhdr->dma_addr + peek_off, ++ peek_len, DMA_BIDIRECTIONAL); ++ ++ txq->credits++; ++ if (txq->credits > 0) ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_FULL); ++ ++ /* Queue the buffer */ ++ rwnx_txq_queue_skb(skb, txq, rwnx_hw, true); ++} ++ ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++/* return size of subframe (including header) */ ++static inline int rwnx_amsdu_subframe_length(struct ethhdr *eth, int eth_len) ++{ ++ /* ethernet header is replaced with amdsu header that have the same size ++ Only need to check if LLC/SNAP header will be added */ ++ int len = eth_len; ++ ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ len += sizeof(rfc1042_header) + 2; ++ } ++ ++ return len; ++} ++ ++static inline bool rwnx_amsdu_is_aggregable(struct sk_buff *skb) ++{ ++ /* need to add some check on buffer to see if it can be aggregated ? */ ++ return true; ++} ++ ++ ++/** ++ * rwnx_amsdu_del_subframe_header - remove AMSDU header ++ * ++ * amsdu_txhdr: amsdu tx descriptor ++ * ++ * Move back the ethernet header at the "beginning" of the data buffer. ++ * (which has been moved in @rwnx_amsdu_add_subframe_header) ++ */ ++static void rwnx_amsdu_del_subframe_header(struct rwnx_amsdu_txhdr *amsdu_txhdr) ++{ ++ struct sk_buff *skb = amsdu_txhdr->skb; ++ struct ethhdr *eth; ++ u8 *pos; ++ ++ pos = skb->data; ++ pos += sizeof(struct rwnx_amsdu_txhdr); ++ eth = (struct ethhdr *)pos; ++ pos += amsdu_txhdr->pad + sizeof(struct ethhdr); ++ ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ pos += sizeof(rfc1042_header) + 2; ++ } ++ ++ memmove(pos, eth, sizeof(*eth)); ++ skb_pull(skb, (pos - skb->data)); ++} ++ ++/** ++ * rwnx_amsdu_add_subframe_header - Add AMSDU header and link subframe ++ * ++ * @rwnx_hw Driver main data ++ * @skb Buffer to aggregate ++ * @sw_txhdr Tx descriptor for the first A-MSDU subframe ++ * ++ * return 0 on sucess, -1 otherwise ++ * ++ * This functions Add A-MSDU header and LLC/SNAP header in the buffer ++ * and update sw_txhdr of the first subframe to link this buffer. ++ * If an error happens, the buffer will be queued as a normal buffer. ++ * ++ * ++ * Before After ++ * +-------------+ +-------------+ ++ * | HEADROOM | | HEADROOM | ++ * | | +-------------+ <- data ++ * | | | amsdu_txhdr | ++ * | | | * pad size | ++ * | | +-------------+ ++ * | | | ETH hdr | keep original eth hdr ++ * | | | | to restore it once transmitted ++ * | | +-------------+ <- packet_addr[x] ++ * | | | Pad | ++ * | | +-------------+ ++ * data -> +-------------+ | AMSDU HDR | ++ * | ETH hdr | +-------------+ ++ * | | | LLC/SNAP | ++ * +-------------+ +-------------+ ++ * | DATA | | DATA | ++ * | | | | ++ * +-------------+ +-------------+ ++ * ++ * Called with tx_lock hold ++ */ ++static int rwnx_amsdu_add_subframe_header(struct rwnx_hw *rwnx_hw, ++ struct sk_buff *skb, ++ struct rwnx_sw_txhdr *sw_txhdr) ++{ ++ struct rwnx_amsdu *amsdu = &sw_txhdr->amsdu; ++ struct rwnx_amsdu_txhdr *amsdu_txhdr; ++ struct ethhdr *amsdu_hdr, *eth = (struct ethhdr *)skb->data; ++ int headroom_need, map_len, msdu_len; ++ dma_addr_t dma_addr; ++ u8 *pos, *map_start; ++ ++ msdu_len = skb->len - sizeof(*eth); ++ headroom_need = sizeof(*amsdu_txhdr) + amsdu->pad + ++ sizeof(*amsdu_hdr); ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ headroom_need += sizeof(rfc1042_header) + 2; ++ msdu_len += sizeof(rfc1042_header) + 2; ++ } ++ ++ /* we should have enough headroom (checked in xmit) */ ++ if (WARN_ON(skb_headroom(skb) < headroom_need)) { ++ return -1; ++ } ++ ++ /* allocate headroom */ ++ pos = skb_push(skb, headroom_need); ++ amsdu_txhdr = (struct rwnx_amsdu_txhdr *)pos; ++ pos += sizeof(*amsdu_txhdr); ++ ++ /* move eth header */ ++ memmove(pos, eth, sizeof(*eth)); ++ eth = (struct ethhdr *)pos; ++ pos += sizeof(*eth); ++ ++ /* Add padding from previous subframe */ ++ map_start = pos; ++ memset(pos, 0, amsdu->pad); ++ pos += amsdu->pad; ++ ++ /* Add AMSDU hdr */ ++ amsdu_hdr = (struct ethhdr *)pos; ++ memcpy(amsdu_hdr->h_dest, eth->h_dest, ETH_ALEN); ++ memcpy(amsdu_hdr->h_source, eth->h_source, ETH_ALEN); ++ amsdu_hdr->h_proto = htons(msdu_len); ++ pos += sizeof(*amsdu_hdr); ++ ++ if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { ++ memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); ++ pos += sizeof(rfc1042_header); ++ } ++ ++ /* MAP (and sync) memory for DMA */ ++ map_len = msdu_len + amsdu->pad + sizeof(*amsdu_hdr); ++ dma_addr = dma_map_single(rwnx_hw->dev, map_start, map_len, ++ DMA_BIDIRECTIONAL); ++ if (WARN_ON(dma_mapping_error(rwnx_hw->dev, dma_addr))) { ++ pos -= sizeof(*eth); ++ memmove(pos, eth, sizeof(*eth)); ++ skb_pull(skb, headroom_need); ++ return -1; ++ } ++ ++ /* update amdsu_txhdr */ ++ amsdu_txhdr->map_len = map_len; ++ amsdu_txhdr->dma_addr = dma_addr; ++ amsdu_txhdr->skb = skb; ++ amsdu_txhdr->pad = amsdu->pad; ++ amsdu_txhdr->msdu_len = msdu_len; ++ ++ /* update rwnx_sw_txhdr (of the first subframe) */ ++ BUG_ON(amsdu->nb != sw_txhdr->desc.host.packet_cnt); ++ sw_txhdr->desc.host.packet_addr[amsdu->nb] = dma_addr; ++ sw_txhdr->desc.host.packet_len[amsdu->nb] = map_len; ++ sw_txhdr->desc.host.packet_cnt++; ++ amsdu->nb++; ++ ++ amsdu->pad = AMSDU_PADDING(map_len - amsdu->pad); ++ list_add_tail(&amsdu_txhdr->list, &amsdu->hdrs); ++ amsdu->len += map_len; ++ ++ trace_amsdu_subframe(sw_txhdr); ++ return 0; ++} ++ ++/** ++ * rwnx_amsdu_add_subframe - Add this buffer as an A-MSDU subframe if possible ++ * ++ * @rwnx_hw Driver main data ++ * @skb Buffer to aggregate if possible ++ * @sta Destination STA ++ * @txq sta's txq used for this buffer ++ * ++ * Tyr to aggregate the buffer in an A-MSDU. If it succeed then the ++ * buffer is added as a new A-MSDU subframe with AMSDU and LLC/SNAP ++ * headers added (so FW won't have to modify this subframe). ++ * ++ * To be added as subframe : ++ * - sta must allow amsdu ++ * - buffer must be aggregable (to be defined) ++ * - at least one other aggregable buffer is pending in the queue ++ * or an a-msdu (with enough free space) is currently in progress ++ * ++ * returns true if buffer has been added as A-MDSP subframe, false otherwise ++ * ++ */ ++static bool rwnx_amsdu_add_subframe(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, ++ struct rwnx_sta *sta, struct rwnx_txq *txq) ++{ ++ bool res = false; ++ struct ethhdr *eth; ++ ++ /* immediately return if amsdu are not allowed for this sta */ ++ if (!txq->amsdu_len || rwnx_hw->mod_params->amsdu_maxnb < 2 || ++ !rwnx_amsdu_is_aggregable(skb) ++ ) ++ return false; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (txq->amsdu) { ++ /* aggreagation already in progress, add this buffer if enough space ++ available, otherwise end the current amsdu */ ++ struct rwnx_sw_txhdr *sw_txhdr = txq->amsdu; ++ eth = (struct ethhdr *)(skb->data); ++ ++ if (((sw_txhdr->amsdu.len + sw_txhdr->amsdu.pad + ++ rwnx_amsdu_subframe_length(eth, skb->len)) > txq->amsdu_len) || ++ rwnx_amsdu_add_subframe_header(rwnx_hw, skb, sw_txhdr)) { ++ txq->amsdu = NULL; ++ goto end; ++ } ++ ++ if (sw_txhdr->amsdu.nb >= rwnx_hw->mod_params->amsdu_maxnb) { ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].done++; ++ /* max number of subframes reached */ ++ txq->amsdu = NULL; ++ } ++ } else { ++ /* Check if a new amsdu can be started with the previous buffer ++ (if any) and this one */ ++ struct sk_buff *skb_prev = skb_peek_tail(&txq->sk_list); ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ int len1, len2; ++ ++ if (!skb_prev || !rwnx_amsdu_is_aggregable(skb_prev)) ++ goto end; ++ ++ txhdr = (struct rwnx_txhdr *)skb_prev->data; ++ sw_txhdr = txhdr->sw_hdr; ++ if ((sw_txhdr->amsdu.len) || ++ (sw_txhdr->desc.host.flags & TXU_CNTRL_RETRY)) ++ /* previous buffer is already a complete amsdu or a retry */ ++ goto end; ++ ++ eth = (struct ethhdr *)(skb_prev->data + sw_txhdr->headroom); ++ len1 = rwnx_amsdu_subframe_length(eth, (sw_txhdr->frame_len + ++ sizeof(struct ethhdr))); ++ ++ eth = (struct ethhdr *)(skb->data); ++ len2 = rwnx_amsdu_subframe_length(eth, skb->len); ++ ++ if (len1 + AMSDU_PADDING(len1) + len2 > txq->amsdu_len) ++ /* not enough space to aggregate those two buffers */ ++ goto end; ++ ++ /* Add subframe header. ++ Note: Fw will take care of adding AMDSU header for the first ++ subframe while generating 802.11 MAC header */ ++ INIT_LIST_HEAD(&sw_txhdr->amsdu.hdrs); ++ sw_txhdr->amsdu.len = len1; ++ sw_txhdr->amsdu.nb = 1; ++ sw_txhdr->amsdu.pad = AMSDU_PADDING(len1); ++ if (rwnx_amsdu_add_subframe_header(rwnx_hw, skb, sw_txhdr)) ++ goto end; ++ ++ sw_txhdr->desc.host.flags |= TXU_CNTRL_AMSDU; ++ ++ if (sw_txhdr->amsdu.nb < rwnx_hw->mod_params->amsdu_maxnb) ++ txq->amsdu = sw_txhdr; ++ else ++ rwnx_hw->stats.amsdus[sw_txhdr->amsdu.nb - 1].done++; ++ } ++ ++ res = true; ++ ++end: ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ return res; ++} ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++#ifdef CONFIG_BR_SUPPORT ++int aic_br_client_tx(struct rwnx_vif *vif, struct sk_buff **pskb) ++{ ++ struct sk_buff *skb = *pskb; ++ ++ /* if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) */ ++ { ++ void dhcp_flag_bcast(struct rwnx_vif *vif, struct sk_buff *skb); ++ int res, is_vlan_tag = 0, i, do_nat25 = 1; ++ unsigned short vlan_hdr = 0; ++ void *br_port = NULL; ++ ++ /* mac_clone_handle_frame(priv, skb); */ ++ ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = vif->ndev->br_port; ++#else /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) */ ++ rcu_read_lock(); ++ br_port = rcu_dereference(vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) */ ++#ifdef BR_SUPPORT_DEBUG ++ printk("SA=%pM, br_mac=%pM, type=0x%x, da[0]=%x, scdb=%pM, vif_type=%d\n", skb->data + MACADDRLEN, vif->br_mac, *((unsigned short *)(skb->data + MACADDRLEN * 2)), ++ skb->data[0], vif->scdb_mac,RWNX_VIF_TYPE(vif)); ++#endif ++ spin_lock_bh(&vif->br_ext_lock); ++ if (!(skb->data[0] & 1) && ++ br_port && ++ memcmp(skb->data + MACADDRLEN, vif->br_mac, MACADDRLEN) && ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) != __constant_htons(ETH_P_8021Q) && ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP) && ++ !memcmp(vif->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN) && vif->scdb_entry) { ++ memcpy(skb->data + MACADDRLEN, vif->ndev->dev_addr, MACADDRLEN); ++ vif->scdb_entry->ageing_timer = jiffies; ++ spin_unlock_bh(&vif->br_ext_lock); ++ } else ++ /* if (!priv->pmib->ethBrExtInfo.nat25_disable) */ ++ { ++ /* if (priv->dev->br_port && ++ * !memcmp(skb->data+MACADDRLEN, priv->br_mac, MACADDRLEN)) { */ ++#if 1 ++ if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_8021Q)) { ++ is_vlan_tag = 1; ++ vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2)); ++ skb_pull(skb, 4); ++ } ++ /* if SA == br_mac && skb== IP => copy SIP to br_ip ?? why */ ++ if (!memcmp(skb->data + MACADDRLEN, vif->br_mac, MACADDRLEN) && ++ (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP))) ++ memcpy(vif->br_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4); ++ ++ if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP)) { ++ if (memcmp(vif->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN)) { ++ #if 1 ++ void *scdb_findEntry(struct rwnx_vif *vif, unsigned char *macAddr, unsigned char *ipAddr); ++ ++ vif->scdb_entry = (struct nat25_network_db_entry *)scdb_findEntry(vif, ++ skb->data + MACADDRLEN, skb->data + WLAN_ETHHDR_LEN + 12); ++ if (vif->scdb_entry != NULL) { ++ memcpy(vif->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN); ++ memcpy(vif->scdb_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4); ++ vif->scdb_entry->ageing_timer = jiffies; ++ do_nat25 = 0; ++ } ++ #endif ++ } else { ++ if (vif->scdb_entry) { ++ vif->scdb_entry->ageing_timer = jiffies; ++ do_nat25 = 0; ++ } else { ++ memset(vif->scdb_mac, 0, MACADDRLEN); ++ memset(vif->scdb_ip, 0, 4); ++ } ++ } ++ } ++ spin_unlock_bh(&vif->br_ext_lock); ++#endif /* 1 */ ++ if (do_nat25) { ++ #if 1 ++ int nat25_db_handle(struct rwnx_vif *vif, struct sk_buff *skb, int method); ++ if (nat25_db_handle(vif, skb, NAT25_CHECK) == 0) { ++ struct sk_buff *newskb; ++ ++ if (is_vlan_tag) { ++ skb_push(skb, 4); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr; ++ } ++ ++ newskb = skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); ++ if (newskb == NULL) { ++ /* priv->ext_stats.tx_drops++; */ ++ printk("TX DROP: skb_copy fail!\n"); ++ /* goto stop_proc; */ ++ return -1; ++ } ++ dev_kfree_skb_any(skb); ++ ++ *pskb = skb = newskb; ++ if (is_vlan_tag) { ++ vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2)); ++ skb_pull(skb, 4); ++ } ++ } ++ ++ if (skb_is_nonlinear(skb)) ++ printk("%s(): skb_is_nonlinear!!\n", __FUNCTION__); ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) ++ res = skb_linearize(skb, GFP_ATOMIC); ++#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) */ ++ res = skb_linearize(skb); ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) */ ++ if (res < 0) { ++ printk("TX DROP: skb_linearize fail!\n"); ++ /* goto free_and_stop; */ ++ return -1; ++ } ++ ++ res = nat25_db_handle(vif, skb, NAT25_INSERT); ++ if (res < 0) { ++ if (res == -2) { ++ /* priv->ext_stats.tx_drops++; */ ++ printk("TX DROP: nat25_db_handle fail!\n"); ++ /* goto free_and_stop; */ ++ return -1; ++ ++ } ++ /* we just print warning message and let it go */ ++ /* DEBUG_WARN("%s()-%d: nat25_db_handle INSERT Warning!\n", __FUNCTION__, __LINE__); */ ++ /* return -1; */ /* return -1 will cause system crash on 2011/08/30! */ ++ return 0; ++ } ++ #endif ++ } ++ ++ memcpy(skb->data + MACADDRLEN, vif->ndev->dev_addr, MACADDRLEN); ++ ++ dhcp_flag_bcast(vif, skb); ++ ++ if (is_vlan_tag) { ++ skb_push(skb, 4); ++ for (i = 0; i < 6; i++) ++ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q); ++ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr; ++ } ++ } ++#if 0 ++ else { ++ if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_8021Q)) ++ is_vlan_tag = 1; ++ ++ if (is_vlan_tag) { ++ if (ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A_VALN(skb->data)) ++ memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN); ++ } else { ++ if (ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A(skb->data)) ++ memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN); ++ } ++ } ++#endif /* 0 */ ++ ++ /* check if SA is equal to our MAC */ ++ if (memcmp(skb->data + MACADDRLEN, vif->ndev->dev_addr, MACADDRLEN)) { ++ /* priv->ext_stats.tx_drops++; */ ++ printk("TX DROP: untransformed frame SA:%02X%02X%02X%02X%02X%02X!\n", ++ skb->data[6], skb->data[7], skb->data[8], skb->data[9], skb->data[10], skb->data[11]); ++ /* goto free_and_stop; */ ++ return -1; ++ } ++ } ++ printk("%s:exit\n",__func__); ++ return 0; ++} ++#endif /* CONFIG_BR_SUPPORT */ ++ ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++/* return: ++ * 0, msg buf freed by the real driver ++ * others, skb need free by the caller,remember not use msg->skb! ++ */ ++ ++int intf_tx(struct rwnx_hw *priv,struct msg_buf *msg) ++{ ++ struct rwnx_vif *rwnx_vif = msg->rwnx_vif; ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct rwnx_sta *sta; ++ struct rwnx_txq *txq; ++ int headroom; ++ //int max_headroom; ++ int hdr_pads; ++ ++ u16 frame_len; ++ u16 frame_oft; ++ u8 tid; ++ struct sk_buff *skb=msg->skb; ++ struct ethhdr eth_t; ++ ++ move_tcpack_msg(rwnx_hw,msg); ++ kfree(msg); ++ ++ memcpy(ð_t, skb->data, sizeof(struct ethhdr)); ++ ++ /* Get the STA id and TID information */ ++ sta = rwnx_get_tx_priv(rwnx_vif, skb, &tid); ++ if (!sta) ++ goto free; ++ ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ if (txq->idx == TXQ_INACTIVE) ++ goto free; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (rwnx_amsdu_add_subframe(rwnx_hw, skb, sta, txq)) ++ return NETDEV_TX_OK; ++#endif ++ ++#ifdef CONFIG_BR_SUPPORT ++ if (1) {//(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ void *br_port = NULL; ++ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ s32 res = aic_br_client_tx(rwnx_vif, &skb); ++ if (res == -1) { ++ goto free; ++ } ++ } ++ } ++#endif /* CONFIG_BR_SUPPORT */ ++ ++ ++ /* Retrieve the pointer to the Ethernet data */ ++ // eth = (struct ethhdr *)skb->data; ++ ++ skb_pull(skb, 14); ++ //hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)eth); ++ hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)skb->data); ++ headroom = sizeof(struct rwnx_txhdr) + hdr_pads; ++ ++ skb_push(skb, headroom); ++ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) ++ goto free; ++ txhdr->sw_hdr = sw_txhdr; ++ desc = &sw_txhdr->desc; ++ ++ frame_len = (u16)skb->len - headroom;// - sizeof(*eth); ++ ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = rwnx_vif; ++ sw_txhdr->skb = skb; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ sw_txhdr->amsdu.len = 0; ++ sw_txhdr->amsdu.nb = 0; ++#endif ++ sw_txhdr->raw_frame = 0; ++ sw_txhdr->fixed_rate = 0; ++ ++ // Fill-in the descriptor ++ memcpy(&desc->host.eth_dest_addr, eth_t.h_dest, ETH_ALEN); ++ memcpy(&desc->host.eth_src_addr, eth_t.h_source, ETH_ALEN); ++ desc->host.ethertype = eth_t.h_proto; ++ desc->host.staid = sta->sta_idx; ++ desc->host.tid = tid; ++ if (unlikely(rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) ++ desc->host.vif_idx = rwnx_vif->ap_vlan.master->vif_index; ++ else ++ desc->host.vif_idx = rwnx_vif->vif_index; ++ ++ if (rwnx_vif->use_4addr && (sta->sta_idx < NX_REMOTE_STA_MAX)) ++ desc->host.flags = TXU_CNTRL_USE_4ADDR; ++ else ++ desc->host.flags = 0; ++ ++ if ((rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) && ++ rwnx_vif->sta.tdls_sta && ++ (memcmp(desc->host.eth_dest_addr.array, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) { ++ desc->host.flags |= TXU_CNTRL_TDLS; ++ rwnx_vif->sta.tdls_sta->tdls.last_tid = desc->host.tid; ++ //rwnx_vif->sta.tdls_sta->tdls.last_sn = desc->host.sn; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) { ++ if (rwnx_vif->is_resending) { ++ desc->host.flags |= TXU_CNTRL_MESH_FWD; ++ } ++ } ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_len[0] = frame_len; ++#else ++ desc->host.packet_len = frame_len; ++#endif ++ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ if (unlikely(rwnx_prep_tx(rwnx_hw, txhdr))) { ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_BUSY; ++ } ++ ++ /* Fill-in TX descriptor */ ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr) ++ + hdr_pads;// + sizeof(*eth); ++#if 0 ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_cnt = 1; ++#else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++#endif ++#endif ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ return 0;//NETDEV_TX_OK ++ ++free: ++ dev_kfree_skb_any(skb); ++ ++ return 0;//NETDEV_TX_OK ++} ++#endif ++ ++/** ++ * netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, ++ * struct net_device *dev); ++ * Called when a packet needs to be transmitted. ++ * Must return NETDEV_TX_OK , NETDEV_TX_BUSY. ++ * (can also return NETDEV_TX_LOCKED if NETIF_F_LLTX) ++ * ++ * - Initialize the desciptor for this pkt (stored in skb before data) ++ * - Push the pkt in the corresponding Txq ++ * - If possible (i.e. credit available and not in PS) the pkt is pushed ++ * to fw ++ */ ++netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct rwnx_sta *sta; ++ struct rwnx_txq *txq; ++ int headroom; ++ int max_headroom; ++ int hdr_pads; ++ ++ u16 frame_len; ++ u16 frame_oft; ++ u8 tid; ++ ++ struct ethhdr eth_t; ++#ifdef CONFIG_FILTER_TCP_ACK ++ struct msg_buf *msgbuf = NULL; ++#endif ++ ++#ifdef CONFIG_ONE_TXQ ++ skb->queue_mapping = rwnx_select_txq(rwnx_vif, skb); ++#endif ++ ++ sk_pacing_shift_update(skb->sk, rwnx_hw->tcp_pacing_shift); ++ max_headroom = sizeof(struct rwnx_txhdr); ++ ++ /* check whether the current skb can be used */ ++ if (skb_shared(skb) || (skb_headroom(skb) < max_headroom) || ++ (skb_cloned(skb) && (dev->priv_flags & IFF_BRIDGE_PORT))) { ++ struct sk_buff *newskb = skb_copy_expand(skb, max_headroom, 0, ++ GFP_ATOMIC); ++ if (unlikely(newskb == NULL)) ++ goto free; ++ ++ dev_kfree_skb_any(skb); ++ ++ skb = newskb; ++ } ++ ++ if(skb->priority < 3) ++ skb->priority = 0; ++ ++#ifdef CONFIG_FILTER_TCP_ACK ++ if(cpu_to_le16(skb->len) <= MAX_TCP_ACK){ ++ msgbuf=intf_tcp_alloc_msg(msgbuf); ++ msgbuf->rwnx_vif=rwnx_vif; ++ msgbuf->skb=skb; ++ if(filter_send_tcp_ack(rwnx_hw,msgbuf,skb->data,cpu_to_le16(skb->len))){ ++ return NETDEV_TX_OK; ++ }else{ ++ move_tcpack_msg(rwnx_hw,msgbuf); ++ kfree(msgbuf); ++ } ++ } ++#endif ++ ++ memcpy(ð_t, skb->data, sizeof(struct ethhdr)); ++ ++ /* Get the STA id and TID information */ ++ sta = rwnx_get_tx_priv(rwnx_vif, skb, &tid); ++ if (!sta) ++ goto free; ++ ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ if (txq->idx == TXQ_INACTIVE) ++ goto free; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (rwnx_amsdu_add_subframe(rwnx_hw, skb, sta, txq)) ++ return NETDEV_TX_OK; ++#endif ++ ++ #ifdef CONFIG_BR_SUPPORT ++ if (1) {//(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) { ++ void *br_port = NULL; ++ ++ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) ++ br_port = rwnx_vif->ndev->br_port; ++ #else ++ rcu_read_lock(); ++ br_port = rcu_dereference(rwnx_vif->ndev->rx_handler_data); ++ rcu_read_unlock(); ++ #endif ++ ++ if (br_port) { ++ s32 res = aic_br_client_tx(rwnx_vif, &skb); ++ if (res == -1) { ++ goto free; ++ } ++ } ++ } ++ #endif /* CONFIG_BR_SUPPORT */ ++ ++ ++ /* Retrieve the pointer to the Ethernet data */ ++ // eth = (struct ethhdr *)skb->data; ++ ++ skb_pull(skb, 14); ++ //hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)eth); ++ hdr_pads = RWNX_SWTXHDR_ALIGN_PADS((long)skb->data); ++ headroom = sizeof(struct rwnx_txhdr) + hdr_pads; ++ ++ skb_push(skb, headroom); ++ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) ++ goto free; ++ txhdr->sw_hdr = sw_txhdr; ++ desc = &sw_txhdr->desc; ++ ++ frame_len = (u16)skb->len - headroom;// - sizeof(*eth); ++ ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = rwnx_vif; ++ sw_txhdr->skb = skb; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ sw_txhdr->amsdu.len = 0; ++ sw_txhdr->amsdu.nb = 0; ++#endif ++ sw_txhdr->raw_frame = 0; ++ sw_txhdr->fixed_rate = 0; ++ ++ // Fill-in the descriptor ++ memcpy(&desc->host.eth_dest_addr, eth_t.h_dest, ETH_ALEN); ++ memcpy(&desc->host.eth_src_addr, eth_t.h_source, ETH_ALEN); ++ desc->host.ethertype = eth_t.h_proto; ++ desc->host.staid = sta->sta_idx; ++ desc->host.tid = tid; ++ if (unlikely(rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) ++ desc->host.vif_idx = rwnx_vif->ap_vlan.master->vif_index; ++ else ++ desc->host.vif_idx = rwnx_vif->vif_index; ++ ++ if (rwnx_vif->use_4addr && (sta->sta_idx < NX_REMOTE_STA_MAX)) ++ desc->host.flags = TXU_CNTRL_USE_4ADDR; ++ else ++ desc->host.flags = 0; ++ ++ if ((rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) && ++ rwnx_vif->sta.tdls_sta && ++ (memcmp(desc->host.eth_dest_addr.array, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) { ++ desc->host.flags |= TXU_CNTRL_TDLS; ++ rwnx_vif->sta.tdls_sta->tdls.last_tid = desc->host.tid; ++ //rwnx_vif->sta.tdls_sta->tdls.last_sn = desc->host.sn; ++ } ++ ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) { ++ if (rwnx_vif->is_resending) { ++ desc->host.flags |= TXU_CNTRL_MESH_FWD; ++ } ++ } ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_len[0] = frame_len; ++#else ++ desc->host.packet_len = frame_len; ++#endif ++ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ if (unlikely(rwnx_prep_tx(rwnx_hw, txhdr))) { ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_BUSY; ++ } ++ ++ /* Fill-in TX descriptor */ ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr) ++ + hdr_pads;// + sizeof(*eth); ++#if 0 ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_cnt = 1; ++#else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++#endif ++#endif ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ return NETDEV_TX_OK; ++ ++free: ++ dev_kfree_skb_any(skb); ++ ++ return NETDEV_TX_OK; ++} ++ ++#ifdef CONFIG_RWNX_MON_XMIT ++/** ++ * netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, ++ * struct net_device *dev); ++ * Called when a packet needs to be transmitted. ++ * Must return NETDEV_TX_OK , NETDEV_TX_BUSY. ++ * (can also return NETDEV_TX_LOCKED if NETIF_F_LLTX) ++ * ++ * - Initialize the desciptor for this pkt (stored in skb before data) ++ * - Push the pkt in the corresponding Txq ++ * - If possible (i.e. credit available and not in PS) the pkt is pushed ++ * to fw ++ */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)) ++#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20 ++#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 ++#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 ++#endif ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)) ++#define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01 ++#endif ++ ++char bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; ++netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ int rtap_len, ret, idx; ++ struct ieee80211_radiotap_header *rtap_hdr; // net/ieee80211_radiotap.h ++ struct ieee80211_radiotap_iterator iterator; // net/cfg80211.h ++ u8_l *rtap_buf = (u8_l *)skb->data; ++ u8_l rate; ++ ++ struct rwnx_vif *vif = netdev_priv(dev); ++ struct rwnx_hw *rwnx_hw = vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct rwnx_sta *sta; ++ struct rwnx_txq *txq; ++ u16_l frame_len, headroom, frame_oft; ++ u8_l tid, rate_fmt = FORMATMOD_NON_HT, rate_idx = 0, txsig_bw = PHY_CHNL_BW_20; ++ u8_l *pframe, *data; ++ bool robust; ++ struct sk_buff *skb_mgmt; ++ bool offchan = false; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ rtap_hdr = (struct ieee80211_radiotap_header*)(rtap_buf); ++ rtap_len = ieee80211_get_radiotap_len(rtap_buf);//max_length ++ frame_len = skb->len; ++ ++ AICWFDBG(LOGINFO, "rwnx_start_monitor_if_xmit, skb_len=%d, rtap_len=%d\n", skb->len, rtap_len); ++//rwnx_data_dump((char*)__func__, skb->data, skb->len); ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ if (unlikely(rtap_hdr->it_version)){ ++ AICWFDBG(LOGERROR, "%s itv \r\n", __func__); ++ goto free_tag; ++ } ++ ++ if (unlikely(skb->len < rtap_len)){ ++ AICWFDBG(LOGERROR, "%s skb->len < rtap_len \r\n", __func__); ++ goto free_tag; ++ } ++ ++ if (unlikely(rtap_len < sizeof(struct ieee80211_radiotap_header))){ ++ AICWFDBG(LOGERROR, "%s rtap_len < sizeof(struct ieee80211_radiotap_header) \r\n", __func__); ++ goto free_tag; ++ } ++ ++ frame_len -= rtap_len; ++ pframe = rtap_buf + rtap_len; ++ ++ // Parse radiotap for injection items and overwrite attribs as needed ++ ret = ieee80211_radiotap_iterator_init(&iterator, rtap_hdr, rtap_len, NULL); ++ while (!ret) { ++ ret = ieee80211_radiotap_iterator_next(&iterator); ++ if (ret) { ++ continue; ++ } ++ AICWFDBG(LOGDEBUG, "%s iterator.this_arg_index:%d iterator.this_arg:%x\r\n", __func__, ++ iterator.this_arg_index, *iterator.this_arg); ++ switch (iterator.this_arg_index) { ++ case IEEE80211_RADIOTAP_RATE: ++ // This is basic 802.11b/g rate; use MCS/VHT for higher rates ++ rate = *iterator.this_arg; ++ AICWFDBG(LOGDEBUG, "rate=0x%x\n", rate); ++ for (idx = 0; idx < HW_RATE_MAX; idx++) { ++ if ((rate * 5) == tx_legrates_lut_rate[idx]) { ++ AICWFDBG(LOGDEBUG, "%s datarate:%d \r\n", __func__, tx_legrates_lut_rate[idx]); ++ break; ++ } ++ } ++ ++ if (idx < HW_RATE_MAX) { ++ rate_idx = idx; ++ AICWFDBG(LOGDEBUG, "rate_idx = %d \r\n", rate_idx); ++ } else { ++ AICWFDBG(LOGERROR, "invalid radiotap rate: %d\n", rate); ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_TX_FLAGS: { ++ u16_l txflags = get_unaligned_le16(iterator.this_arg); ++ AICWFDBG(LOGDEBUG, "txflags=0x%x\n", txflags); ++ if ((txflags & IEEE80211_RADIOTAP_F_TX_NOACK) == 0) { ++ AICWFDBG(LOGDEBUG, " TX_NOACK\n"); ++ } ++ if (txflags & 0x0010) { // Use preconfigured seq num ++ // NOTE: this is currently ignored due to qos_en=_FALSE and HW seq num override ++ AICWFDBG(LOGDEBUG, " GetSequence\n"); ++ } ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_MCS: { ++ u8_l mcs_have = iterator.this_arg[0]; ++ AICWFDBG(LOGDEBUG, "mcs_have=0x%x\n", mcs_have); ++ rate_fmt = FORMATMOD_HT_MF; ++ if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_BW) { ++ u8_l bw = (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_BW_MASK); ++ u8_l ch_offset = 0; ++ if (bw == IEEE80211_RADIOTAP_MCS_BW_40) { ++ txsig_bw = PHY_CHNL_BW_40; ++ } else if (bw == IEEE80211_RADIOTAP_MCS_BW_20L) { ++ bw = IEEE80211_RADIOTAP_MCS_BW_20; ++ ch_offset = 1; // CHNL_OFFSET_LOWER; ++ } else if (bw == IEEE80211_RADIOTAP_MCS_BW_20U) { ++ bw = IEEE80211_RADIOTAP_MCS_BW_20; ++ ch_offset = 2; // CHNL_OFFSET_UPPER; ++ } ++ AICWFDBG(LOGDEBUG, " bw=%d, ch_offset=%d\n", bw, ch_offset); ++ } ++ if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_MCS) { ++ u8_l fixed_rate = iterator.this_arg[2] & 0x7f; ++ if (fixed_rate > 31) { ++ fixed_rate = 0; ++ } ++ rate_idx = fixed_rate; ++ AICWFDBG(LOGDEBUG, " fixed_rate=0x%x\n", fixed_rate); ++ } ++ if ((mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_GI) && (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_SGI)) { ++ AICWFDBG(LOGDEBUG, " sgi\n"); ++ } ++ if ((mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_FEC) && (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_FEC_LDPC)) { ++ AICWFDBG(LOGDEBUG, " ldpc\n"); ++ } ++ if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_STBC) { ++ u8 stbc = (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT; ++ AICWFDBG(LOGDEBUG, " stbc=0x%x\n", stbc); ++ } ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_VHT: { ++ unsigned int mcs, nss; ++ u8 known = iterator.this_arg[0]; ++ u8 flags = iterator.this_arg[2]; ++ rate_fmt = FORMATMOD_VHT; ++ AICWFDBG(LOGDEBUG, "known=0x%x, flags=0x%x\n", known, flags); ++ // NOTE: this code currently only supports 1SS for radiotap defined rates ++ if ((known & IEEE80211_RADIOTAP_VHT_KNOWN_STBC) && (flags & IEEE80211_RADIOTAP_VHT_FLAG_STBC)) { ++ AICWFDBG(LOGDEBUG, " stbc\n"); ++ } ++ if ((known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) && (flags & IEEE80211_RADIOTAP_VHT_FLAG_SGI)) { ++ AICWFDBG(LOGDEBUG, " sgi\n"); ++ } ++ if (known & IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) { ++ u8_l bw = iterator.this_arg[3] & 0x1F; ++ AICWFDBG(LOGDEBUG, " bw=0x%x\n",bw); ++ // NOTE: there are various L and U, but we just use straight 20/40/80 ++ // since it's not clear how to set CHNL_OFFSET_LOWER/_UPPER with different ++ // sideband sizes/configurations. TODO. ++ // Also, any 160 is treated as 80 due to lack of WIDTH_160. ++ txsig_bw = PHY_CHNL_BW_40; ++ if (bw == 0) { ++ txsig_bw = PHY_CHNL_BW_20; ++ AICWFDBG(LOGDEBUG, " 20M\n"); ++ } else if (bw >=1 && bw <= 3) { ++ AICWFDBG(LOGDEBUG, " 40M\n"); ++ } else if (bw >=4 && bw <= 10) { ++ AICWFDBG(LOGDEBUG, " 80M\n"); ++ } else if (bw >= 11 && bw <= 25) { ++ AICWFDBG(LOGDEBUG, " 160M\n"); ++ } ++ } ++ // User 0 ++ nss = iterator.this_arg[4] & 0x0F; // Number of spatial streams ++ AICWFDBG(LOGDEBUG, " nss=0x%x\n", nss); ++ if (nss > 0) { ++ if (nss > 4) nss = 4; ++ mcs = (iterator.this_arg[4]>>4) & 0x0F; // MCS rate index ++ if (mcs > 8) mcs = 9; ++ rate_idx = mcs; ++ AICWFDBG(LOGDEBUG, " mcs=0x%x\n", mcs); ++ if (iterator.this_arg[8] & IEEE80211_RADIOTAP_CODING_LDPC_USER0) { ++ AICWFDBG(LOGDEBUG, " ldpc\n"); ++ } ++ } ++ } ++ break; ++ ++ case IEEE80211_RADIOTAP_HE: { ++ u16 data1 = ((u16)iterator.this_arg[1] << 8) | iterator.this_arg[0]; ++ u16 data2 = ((u16)iterator.this_arg[3] << 8) | iterator.this_arg[2]; ++ u16 data3 = ((u16)iterator.this_arg[5] << 8) | iterator.this_arg[4]; ++ u16 data5 = ((u16)iterator.this_arg[9] << 8) | iterator.this_arg[8]; ++ u8 fmt_he = data1 & IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK; ++ if (fmt_he == IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU) { ++ rate_fmt = FORMATMOD_HE_MU; ++ } else if (fmt_he == IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU) { ++ rate_fmt = FORMATMOD_HE_ER; ++ } else { ++ rate_fmt = FORMATMOD_HE_SU; ++ } ++ if (data1 & IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN) { ++ u8 mcs = (data3 & IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS) >> 8; ++ if (mcs > 11) mcs = 11; ++ rate_idx = mcs; ++ } ++ if (data1 & IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN) { ++ u8 bw = data5 & IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC; ++ txsig_bw = (bw == IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ) ? PHY_CHNL_BW_20 : PHY_CHNL_BW_40; ++ } ++ if (data2 & IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN) { ++ u8 gi = (data5 & IEEE80211_RADIOTAP_HE_DATA5_GI) >> 4; ++ AICWFDBG(LOGDEBUG, " gi: %d\n", gi); ++ } ++ } ++ break; ++ ++ default: ++ AICWFDBG(LOGERROR, "unparsed arg: 0x%x\n",iterator.this_arg_index); ++ break; ++ } ++ } ++ ++ #if 0 ++ // dump buffer ++ tmp_len = 128; ++ if (skb->len < 128) { ++ tmp_len = skb->len; ++ } ++ for (idx = 0; idx < tmp_len; idx+=16) { ++ printk("[%04X] %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", idx, ++ rtap_buf[idx+0],rtap_buf[idx+1],rtap_buf[idx+2],rtap_buf[idx+3], ++ rtap_buf[idx+4],rtap_buf[idx+5],rtap_buf[idx+6],rtap_buf[idx+7], ++ rtap_buf[idx+8],rtap_buf[idx+9],rtap_buf[idx+10],rtap_buf[idx+11], ++ rtap_buf[idx+12],rtap_buf[idx+13],rtap_buf[idx+14],rtap_buf[idx+15]); ++ } ++ #endif ++ //rwnx_data_dump((char*)__func__, pframe, frame_len); ++ ++ /* Get the STA id and TID information */ ++ sta = rwnx_get_tx_priv(vif, skb, &tid); ++ //if (!sta) { ++ // printk("sta=null, tid=0x%x\n", tid); ++ //} ++ /* Set TID and Queues indexes */ ++ if (sta) { ++ txq = rwnx_txq_sta_get(sta, 8, rwnx_hw); ++ } else { ++ if (offchan) ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ else ++ txq = rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE); ++ } ++ if (txq->idx == TXQ_INACTIVE) { ++ AICWFDBG(LOGERROR, "TXQ_INACTIVE\n"); ++ goto free_tag; ++ } ++ // prepare to xmit ++ headroom = sizeof(struct rwnx_txhdr); ++ skb_mgmt = dev_alloc_skb(headroom + frame_len); ++ if (!skb_mgmt) { ++ AICWFDBG(LOGERROR, "skb_mgmt alloc fail\n"); ++ goto free_tag; ++ } ++ skb_reserve(skb_mgmt, headroom); ++ data = skb_put(skb_mgmt, frame_len); ++ /* Copy the provided data */ ++ memcpy(data, pframe, frame_len); ++ robust = ieee80211_is_robust_mgmt_frame( ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)) ++ (void*)skb_mgmt ++#else ++ skb_mgmt ++#endif ++ ); ++ skb_push(skb_mgmt, headroom); ++ /* Fill the TX Header */ ++ txhdr = (struct rwnx_txhdr *)skb_mgmt->data; ++ txhdr->hw_hdr.cfm.status.value = 0; ++ /* Fill the SW TX Header */ ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) { ++ dev_kfree_skb(skb_mgmt); ++ AICWFDBG(LOGERROR, "sw_txhdr alloc fail\n"); ++ goto free_tag; ++ } ++ txhdr->sw_hdr = sw_txhdr; ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = vif; ++ sw_txhdr->skb = skb_mgmt; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb_mgmt->len - offsetof(struct rwnx_txhdr, hw_hdr); ++ sw_txhdr->raw_frame = 1; ++ sw_txhdr->fixed_rate = 1; ++ sw_txhdr->rate_config = ((rate_fmt << FORMAT_MOD_TX_RCX_OFT) & FORMAT_MOD_TX_RCX_MASK) | ++ ((txsig_bw << BW_TX_RCX_OFT) & BW_TX_RCX_MASK) | ++ ((rate_idx << MCS_INDEX_TX_RCX_OFT) & MCS_INDEX_TX_RCX_MASK); // from radiotap ++ /* Fill the Descriptor to be provided to the MAC SW */ ++ desc = &sw_txhdr->desc; ++ desc->host.staid = (sta) ? sta->sta_idx : 0xFF; ++ desc->host.vif_idx = vif->vif_index; ++ desc->host.tid = 0xFF; ++ desc->host.flags = TXU_CNTRL_MGMT; ++ if (robust) { ++ desc->host.flags |= TXU_CNTRL_MGMT_ROBUST; ++ } ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr); ++ #if 0 ++ #ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_len[0] = frame_len; ++ desc->host.packet_cnt = 1; ++ #else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_len = frame_len; ++ #endif ++ #else ++ desc->host.packet_len = frame_len; ++ #endif ++ ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ memcpy(desc->host.eth_dest_addr.array, bcast, ETH_ALEN); ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ AICWFDBG(LOGTRACE, "%s send data\r\n", __func__); ++ if (rwnx_txq_queue_skb(skb_mgmt, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++free_tag: ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++} ++#endif ++ ++ ++/** ++ * rwnx_start_mgmt_xmit - Transmit a management frame ++ * ++ * @vif: Vif that send the frame ++ * @sta: Destination of the frame. May be NULL if the destiantion is unknown ++ * to the AP. ++ * @params: Mgmt frame parameters ++ * @offchan: Indicate whether the frame must be send via the offchan TXQ. ++ * (is is redundant with params->offchan ?) ++ * @cookie: updated with a unique value to identify the frame with upper layer ++ * ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct cfg80211_mgmt_tx_params *params, bool offchan, ++ u64 *cookie) ++#else ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct ieee80211_channel *channel, bool offchan, ++ unsigned int wait, const u8 *buf, size_t len, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ bool no_cck, ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) ++ bool dont_wait_for_ack, ++ #endif ++ u64 *cookie) ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++{ ++ struct rwnx_hw *rwnx_hw = vif->rwnx_hw; ++ struct rwnx_txhdr *txhdr; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct txdesc_api *desc; ++ struct sk_buff *skb; ++ u16 frame_len, headroom, frame_oft; ++ u8 *data; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ struct rwnx_txq *txq; ++ bool robust; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++ const u8 *buf = params->buf; ++ size_t len = params->len; ++ bool no_cck = params->no_cck; ++ #endif ++ ++ AICWFDBG(LOGDEBUG,"mgmt xmit %x %x ",buf[0],buf[1]); ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ headroom = sizeof(struct rwnx_txhdr); ++ frame_len = len; ++ ++ //---------------------------------------------------------------------- ++ ++ /* Set TID and Queues indexes */ ++ if (sta) { ++ txq = rwnx_txq_sta_get(sta, 8, rwnx_hw); ++ } else { ++ if (offchan) ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ else ++ txq = rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE); ++ } ++ ++ /* Ensure that TXQ is active */ ++ if (txq->idx == TXQ_INACTIVE) { ++ netdev_dbg(vif->ndev, "TXQ inactive\n"); ++ return -EBUSY; ++ } ++ ++ /* ++ * Create a SK Buff object that will contain the provided data ++ */ ++ skb = dev_alloc_skb(headroom + frame_len); ++ ++ if (!skb) { ++ return -ENOMEM; ++ } ++ ++ *cookie = (unsigned long)skb; ++ ++ /* ++ * Move skb->data pointer in order to reserve room for rwnx_txhdr ++ * headroom value will be equal to sizeof(struct rwnx_txhdr) ++ */ ++ skb_reserve(skb, headroom); ++ ++ /* ++ * Extend the buffer data area in order to contain the provided packet ++ * len value (for skb) will be equal to param->len ++ */ ++ data = skb_put(skb, frame_len); ++ /* Copy the provided data */ ++ memcpy(data, buf, frame_len); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) ++ robust = ieee80211_is_robust_mgmt_frame(skb); ++#else ++ if (skb->len < 25){ ++ robust = false; ++ } ++ robust = ieee80211_is_robust_mgmt_frame((void *)skb->data); ++#endif ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) ++ /* Update CSA counter if present */ ++ if (unlikely(params->n_csa_offsets) && ++ vif->wdev.iftype == NL80211_IFTYPE_AP && ++ vif->ap.csa) { ++ int i; ++ ++ data = skb->data; ++ for (i = 0; i < params->n_csa_offsets ; i++) { ++ data[params->csa_offsets[i]] = vif->ap.csa->count; ++ } ++ } ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ ++ /* ++ * Go back to the beginning of the allocated data area ++ * skb->data pointer will move backward ++ */ ++ skb_push(skb, headroom); ++ ++ //---------------------------------------------------------------------- ++ ++ /* Fill the TX Header */ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ //---------------------------------------------------------------------- ++ ++ /* Fill the SW TX Header */ ++ sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC); ++ if (unlikely(sw_txhdr == NULL)) { ++ dev_kfree_skb(skb); ++ return -ENOMEM; ++ } ++ txhdr->sw_hdr = sw_txhdr; ++ ++ sw_txhdr->txq = txq; ++ sw_txhdr->frame_len = frame_len; ++ sw_txhdr->rwnx_sta = sta; ++ sw_txhdr->rwnx_vif = vif; ++ sw_txhdr->skb = skb; ++ sw_txhdr->headroom = headroom; ++ sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr); ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ sw_txhdr->amsdu.len = 0; ++ sw_txhdr->amsdu.nb = 0; ++#endif ++ sw_txhdr->raw_frame = 0; ++ sw_txhdr->fixed_rate = 0; ++ ++ //---------------------------------------------------------------------- ++ ++ /* Fill the Descriptor to be provided to the MAC SW */ ++ desc = &sw_txhdr->desc; ++ ++ desc->host.ethertype = 0; ++ desc->host.staid = (sta) ? sta->sta_idx : 0xFF; ++ desc->host.vif_idx = vif->vif_index; ++ desc->host.tid = 0xFF; ++ desc->host.flags = TXU_CNTRL_MGMT; ++ if (robust) ++ desc->host.flags |= TXU_CNTRL_MGMT_ROBUST; ++ ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_len[0] = frame_len; ++#else ++ desc->host.packet_len = frame_len; ++#endif ++ ++ if (no_cck) { ++ desc->host.flags |= TXU_CNTRL_MGMT_NO_CCK; ++ } ++ ++ /* Get DMA Address */ ++ if (unlikely(rwnx_prep_tx(rwnx_hw, txhdr))) { ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ dev_kfree_skb(skb); ++ return -EBUSY; ++ } ++ ++ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr); ++#if 0 ++#ifdef CONFIG_RWNX_SPLIT_TX_BUF ++ desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; ++ desc->host.packet_cnt = 1; ++#else ++ desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; ++#endif ++#endif ++ desc->host.hostid = sw_txhdr->dma_addr; ++ ++ //---------------------------------------------------------------------- ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false)) ++ rwnx_hwq_process(rwnx_hw, txq->hwq); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ return 0; ++} ++ ++/** ++ * rwnx_txdatacfm - FW callback for TX confirmation ++ * ++ * called with tx_lock hold ++ */ ++int rwnx_txdatacfm(void *pthis, void *host_id) ++{ ++ struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)pthis; ++ struct sk_buff *skb = host_id; ++ struct rwnx_txhdr *txhdr; ++ union rwnx_hw_txstatus rwnx_txst; ++ struct rwnx_sw_txhdr *sw_txhdr; ++ struct rwnx_hwq *hwq; ++ struct rwnx_txq *txq; ++ int headroom; ++ //int peek_off = offsetof(struct rwnx_hw_txhdr, cfm); ++ //int peek_len = sizeof(((struct rwnx_hw_txhdr *)0)->cfm); ++ ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ sw_txhdr = txhdr->sw_hdr; ++ ++ /* Read status in the TX control header */ ++ rwnx_txst = txhdr->hw_hdr.cfm.status; ++ ++ /* Check status in the header. If status is null, it means that the buffer ++ * was not transmitted and we have to return immediately */ ++ if (rwnx_txst.value == 0) { ++ return -1; ++ } ++ ++#ifdef AICWF_USB_SUPPORT ++ if (rwnx_hw->usbdev->state == USB_DOWN_ST) { ++ headroom = sw_txhdr->headroom; ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ consume_skb(skb); ++ return 0; ++ } ++#endif ++#ifdef AICWF_SDIO_SUPPORT ++ if(rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { ++ headroom = sw_txhdr->headroom; ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ consume_skb(skb); ++ return 0; ++ } ++#endif ++ ++ txq = sw_txhdr->txq; ++ /* don't use txq->hwq as it may have changed between push and confirm */ ++ hwq = &rwnx_hw->hwq[sw_txhdr->hw_queue]; ++ rwnx_txq_confirm_any(rwnx_hw, txq, hwq, sw_txhdr); ++ ++ /* Update txq and HW queue credits */ ++ if (sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT) { ++ printk("done=%d retry_required=%d sw_retry_required=%d acknowledged=%d\n", ++ rwnx_txst.tx_done, rwnx_txst.retry_required, ++ rwnx_txst.sw_retry_required, rwnx_txst.acknowledged); ++#ifdef CREATE_TRACE_POINTS ++ trace_mgmt_cfm(sw_txhdr->rwnx_vif->vif_index, ++ (sw_txhdr->rwnx_sta) ? sw_txhdr->rwnx_sta->sta_idx : 0xFF, ++ rwnx_txst.acknowledged); ++#endif ++ /* Confirm transmission to CFG80211 */ ++ cfg80211_mgmt_tx_status(&sw_txhdr->rwnx_vif->wdev, ++ (unsigned long)skb, ++ (skb->data + sw_txhdr->headroom), ++ sw_txhdr->frame_len, ++ rwnx_txst.acknowledged, ++ GFP_ATOMIC); ++ } else if ((txq->idx != TXQ_INACTIVE) && ++ (rwnx_txst.retry_required || rwnx_txst.sw_retry_required)) { ++ bool sw_retry = (rwnx_txst.sw_retry_required) ? true : false; ++ ++ /* Reset the status */ ++ txhdr->hw_hdr.cfm.status.value = 0; ++ ++ /* The confirmed packet was part of an AMPDU and not acked ++ * correctly, so reinject it in the TX path to be retried */ ++ rwnx_tx_retry(rwnx_hw, skb, txhdr, sw_retry); ++ return 0; ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_skb_confirm(skb, txq, hwq, &txhdr->hw_hdr.cfm); ++#endif ++ /* STA may have disconnect (and txq stopped) when buffers were stored ++ in fw. In this case do nothing when they're returned */ ++ if (txq->idx != TXQ_INACTIVE) { ++ #if 0 ++ if (txhdr->hw_hdr.cfm.credits) { ++ txq->credits += txhdr->hw_hdr.cfm.credits; ++ if (txq->credits <= 0) ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); ++ else if (txq->credits > 0) ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_FULL); ++ } ++ #endif ++ ++ /* continue service period */ ++ if (unlikely(txq->push_limit && !rwnx_txq_is_full(txq))) { ++ rwnx_txq_add_to_hw_list(txq); ++ } ++ } ++ ++ if (txhdr->hw_hdr.cfm.ampdu_size && ++ txhdr->hw_hdr.cfm.ampdu_size < IEEE80211_MAX_AMPDU_BUF) ++ rwnx_hw->stats.ampdus_tx[txhdr->hw_hdr.cfm.ampdu_size - 1]++; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ txq->amsdu_len = txhdr->hw_hdr.cfm.amsdu_size; ++#endif ++ ++ /* Update statistics */ ++ sw_txhdr->rwnx_vif->net_stats.tx_packets++; ++ sw_txhdr->rwnx_vif->net_stats.tx_bytes += sw_txhdr->frame_len; ++ ++ /* Release SKBs */ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->desc.host.flags & TXU_CNTRL_AMSDU) { ++ struct rwnx_amsdu_txhdr *amsdu_txhdr; ++ list_for_each_entry(amsdu_txhdr, &sw_txhdr->amsdu.hdrs, list) { ++ rwnx_amsdu_del_subframe_header(amsdu_txhdr); ++ consume_skb(amsdu_txhdr->skb); ++ } ++ } ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++ ++ headroom = sw_txhdr->headroom; ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ skb_pull(skb, headroom); ++ consume_skb(skb); ++ ++ return 0; ++} ++ ++/** ++ * rwnx_txq_credit_update - Update credit for one txq ++ * ++ * @rwnx_hw: Driver main data ++ * @sta_idx: STA idx ++ * @tid: TID ++ * @update: offset to apply in txq credits ++ * ++ * Called when fw send ME_TX_CREDITS_UPDATE_IND message. ++ * Apply @update to txq credits, and stop/start the txq if needed ++ */ ++void rwnx_txq_credit_update(struct rwnx_hw *rwnx_hw, int sta_idx, u8 tid, ++ s8 update) ++{ ++ struct rwnx_sta *sta = &rwnx_hw->sta_table[sta_idx]; ++ struct rwnx_txq *txq; ++ ++ txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ if (txq->idx != TXQ_INACTIVE) { ++ //txq->credits += update; ++#ifdef CREATE_TRACE_POINTS ++ trace_credit_update(txq, update); ++#endif ++ if (txq->credits <= 0) ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); ++ else ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_FULL); ++ } ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h +new file mode 100644 +index 000000000000..b7c863ff3284 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h +@@ -0,0 +1,196 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_tx.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++#ifndef _RWNX_TX_H_ ++#define _RWNX_TX_H_ ++ ++#include ++#include ++#include ++#include "lmac_types.h" ++#include "ipc_shared.h" ++#include "rwnx_txq.h" ++#include "hal_desc.h" ++ ++#define RWNX_HWQ_BK 0 ++#define RWNX_HWQ_BE 1 ++#define RWNX_HWQ_VI 2 ++#define RWNX_HWQ_VO 3 ++#define RWNX_HWQ_BCMC 4 ++#define RWNX_HWQ_NB NX_TXQ_CNT ++#define RWNX_HWQ_ALL_ACS (RWNX_HWQ_BK | RWNX_HWQ_BE | RWNX_HWQ_VI | RWNX_HWQ_VO) ++#define RWNX_HWQ_ALL_ACS_BIT (BIT(RWNX_HWQ_BK) | BIT(RWNX_HWQ_BE) | \ ++ BIT(RWNX_HWQ_VI) | BIT(RWNX_HWQ_VO)) ++ ++#define RWNX_TX_LIFETIME_MS 1000 ++#define RWNX_TX_MAX_RATES NX_TX_MAX_RATES ++ ++#define RWNX_SWTXHDR_ALIGN_SZ 4 ++#define RWNX_SWTXHDR_ALIGN_MSK (RWNX_SWTXHDR_ALIGN_SZ - 1) ++#define RWNX_SWTXHDR_ALIGN_PADS(x) \ ++ ((RWNX_SWTXHDR_ALIGN_SZ - ((x) & RWNX_SWTXHDR_ALIGN_MSK)) \ ++ & RWNX_SWTXHDR_ALIGN_MSK) ++#if RWNX_SWTXHDR_ALIGN_SZ & RWNX_SWTXHDR_ALIGN_MSK ++#error bad RWNX_SWTXHDR_ALIGN_SZ ++#endif ++ ++#define AMSDU_PADDING(x) ((4 - ((x) & 0x3)) & 0x3) ++ ++#define TXU_CNTRL_RETRY BIT(0) ++#define TXU_CNTRL_MORE_DATA BIT(2) ++#define TXU_CNTRL_MGMT BIT(3) ++#define TXU_CNTRL_MGMT_NO_CCK BIT(4) ++#define TXU_CNTRL_AMSDU BIT(6) ++#define TXU_CNTRL_MGMT_ROBUST BIT(7) ++#define TXU_CNTRL_USE_4ADDR BIT(8) ++#define TXU_CNTRL_EOSP BIT(9) ++#define TXU_CNTRL_MESH_FWD BIT(10) ++#define TXU_CNTRL_TDLS BIT(11) ++ ++extern const int rwnx_tid2hwq[IEEE80211_NUM_TIDS]; ++ ++/** ++ * struct rwnx_amsdu_txhdr - Structure added in skb headroom (instead of ++ * rwnx_txhdr) for amsdu subframe buffer (except for the first subframe ++ * that has a normal rwnx_txhdr) ++ * ++ * @list List of other amsdu subframe (rwnx_sw_txhdr.amsdu.hdrs) ++ * @map_len Length to be downloaded for this subframe ++ * @dma_addr Buffer address form embedded point of view ++ * @skb skb ++ * @pad padding added before this subframe ++ * (only use when amsdu must be dismantled) ++ * @msdu_len Size, in bytes, of the MSDU (without padding nor amsdu header) ++ */ ++struct rwnx_amsdu_txhdr { ++ struct list_head list; ++ size_t map_len; ++ dma_addr_t dma_addr; ++ struct sk_buff *skb; ++ u16 pad; ++ u16 msdu_len; ++}; ++ ++/** ++ * struct rwnx_amsdu - Structure to manage creation of an A-MSDU, updated ++ * only In the first subframe of an A-MSDU ++ * ++ * @hdrs List of subframe of rwnx_amsdu_txhdr ++ * @len Current size for this A-MDSU (doesn't take padding into account) ++ * 0 means that no amsdu is in progress ++ * @nb Number of subframe in the amsdu ++ * @pad Padding to add before adding a new subframe ++ */ ++struct rwnx_amsdu { ++ struct list_head hdrs; ++ u16 len; ++ u8 nb; ++ u8 pad; ++}; ++ ++/** ++ * struct rwnx_sw_txhdr - Software part of tx header ++ * ++ * @rwnx_sta sta to which this buffer is addressed ++ * @rwnx_vif vif that send the buffer ++ * @txq pointer to TXQ used to send the buffer ++ * @hw_queue Index of the HWQ used to push the buffer. ++ * May be different than txq->hwq->id on confirmation. ++ * @frame_len Size of the frame (doesn't not include mac header) ++ * (Only used to update stat, can't we use skb->len instead ?) ++ * @headroom Headroom added in skb to add rwnx_txhdr ++ * (Only used to remove it before freeing skb, is it needed ?) ++ * @amsdu Description of amsdu whose first subframe is this buffer ++ * (amsdu.nb = 0 means this buffer is not part of amsdu) ++ * @skb skb received from transmission ++ * @map_len Length mapped for DMA (only rwnx_hw_txhdr and data are mapped) ++ * @dma_addr DMA address after mapping ++ * @desc Buffer description that will be copied in shared mem for FW ++ */ ++struct rwnx_sw_txhdr { ++ struct rwnx_sta *rwnx_sta; ++ struct rwnx_vif *rwnx_vif; ++ struct rwnx_txq *txq; ++ u8 hw_queue; ++ u16 frame_len; ++ u16 headroom; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ struct rwnx_amsdu amsdu; ++#endif ++ u32 need_cfm; ++ struct sk_buff *skb; ++ ++ size_t map_len; ++ dma_addr_t dma_addr; ++ struct txdesc_api desc; ++ ++ u8 raw_frame; ++ u8 fixed_rate; ++ u16 rate_config; ++}; ++ ++/** ++ * struct rwnx_txhdr - Stucture to control transimission of packet ++ * (Added in skb headroom) ++ * ++ * @sw_hdr: Information from driver ++ * @cache_guard: ++ * @hw_hdr: Information for/from hardware ++ */ ++struct rwnx_txhdr { ++ struct rwnx_sw_txhdr *sw_hdr; ++ char cache_guard[L1_CACHE_BYTES]; ++ struct rwnx_hw_txhdr hw_hdr; ++}; ++ ++u16 rwnx_select_txq(struct rwnx_vif *rwnx_vif, struct sk_buff *skb); ++netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct cfg80211_mgmt_tx_params *params, bool offchan, ++ u64 *cookie); ++#else ++int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, ++ struct ieee80211_channel *channel, bool offchan, ++ unsigned int wait, const u8 *buf, size_t len, ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ bool no_cck, ++ #endif ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) ++ bool dont_wait_for_ack, ++ #endif ++ u64 *cookie); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ ++ ++#ifdef CONFIG_RWNX_MON_XMIT ++int rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *dev); ++#endif ++int rwnx_txdatacfm(void *pthis, void *host_id); ++ ++struct rwnx_hw; ++struct rwnx_sta; ++void rwnx_set_traffic_status(struct rwnx_hw *rwnx_hw, ++ struct rwnx_sta *sta, ++ bool available, ++ u8 ps_id); ++void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ bool enable); ++void rwnx_ps_bh_traffic_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, ++ u16 pkt_req, u8 ps_id); ++ ++void rwnx_switch_vif_sta_txq(struct rwnx_sta *sta, struct rwnx_vif *old_vif, ++ struct rwnx_vif *new_vif); ++ ++int rwnx_dbgfs_print_sta(char *buf, size_t size, struct rwnx_sta *sta, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_credit_update(struct rwnx_hw *rwnx_hw, int sta_idx, u8 tid, ++ s8 update); ++void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags); ++ ++#endif /* _RWNX_TX_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c +new file mode 100644 +index 000000000000..9bdc07268407 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c +@@ -0,0 +1,1371 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_txq.c ++ * ++ * Copyright (C) RivieraWaves 2016-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_defs.h" ++#include "rwnx_tx.h" ++#include "ipc_host.h" ++#include "rwnx_events.h" ++ ++/****************************************************************************** ++ * Utils functions ++ *****************************************************************************/ ++#ifdef CONFIG_RWNX_FULLMAC ++const int nx_tid_prio[NX_NB_TID_PER_STA] = {7, 6, 5, 4, 3, 0, 2, 1}; ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++extern int tx_fc_low_water; ++extern int tx_fc_high_water; ++#endif ++ ++static inline int rwnx_txq_sta_idx(struct rwnx_sta *sta, u8 tid) ++{ ++ if (is_multicast_sta(sta->sta_idx)){ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ return NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + sta->vif_idx; ++ }else{ ++ return NX_FIRST_VIF_TXQ_IDX + sta->vif_idx; ++ } ++ }else{ ++ return (sta->sta_idx * NX_NB_TXQ_PER_STA) + tid; ++ } ++} ++ ++static inline int rwnx_txq_vif_idx(struct rwnx_vif *vif, u8 type) ++{ ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ return NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + master_vif_idx(vif) + (type * NX_VIRT_DEV_MAX); ++ }else{ ++ return NX_FIRST_VIF_TXQ_IDX + master_vif_idx(vif) + (type * NX_VIRT_DEV_MAX); ++ } ++ ++} ++ ++struct rwnx_txq *rwnx_txq_sta_get(struct rwnx_sta *sta, u8 tid, ++ struct rwnx_hw *rwnx_hw) ++{ ++ if (tid >= NX_NB_TXQ_PER_STA) ++ tid = 0; ++ ++ return &rwnx_hw->txq[rwnx_txq_sta_idx(sta, tid)]; ++} ++ ++struct rwnx_txq *rwnx_txq_vif_get(struct rwnx_vif *vif, u8 type) ++{ ++ if (type > NX_UNK_TXQ_TYPE) ++ type = NX_BCMC_TXQ_TYPE; ++ ++ return &vif->rwnx_hw->txq[rwnx_txq_vif_idx(vif, type)]; ++} ++ ++static inline struct rwnx_sta *rwnx_txq_2_sta(struct rwnx_txq *txq) ++{ ++ return txq->sta; ++} ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ ++/****************************************************************************** ++ * Init/Deinit functions ++ *****************************************************************************/ ++/** ++ * rwnx_txq_init - Initialize a TX queue ++ * ++ * @txq: TX queue to be initialized ++ * @idx: TX queue index ++ * @status: TX queue initial status ++ * @hwq: Associated HW queue ++ * @ndev: Net device this queue belongs to ++ * (may be null for non netdev txq) ++ * ++ * Each queue is initialized with the credit of @NX_TXQ_INITIAL_CREDITS. ++ */ ++static void rwnx_txq_init(struct rwnx_txq *txq, int idx, u8 status, ++ struct rwnx_hwq *hwq, int tid, ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_sta *sta, struct net_device *ndev ++#endif ++ ) ++{ ++ int i; ++ int nx_first_unk_txq_idx = NX_FIRST_UNK_TXQ_IDX; ++ int nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX; ++ int nx_first_vif_txq_idx = NX_FIRST_VIF_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_first_unk_txq_idx = NX_FIRST_UNK_TXQ_IDX_FOR_OLD_IC; ++ nx_bcmc_txq_ndev_idx = NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC; ++ nx_first_vif_txq_idx = NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ ++ txq->idx = idx; ++ txq->status = status; ++ txq->credits = NX_TXQ_INITIAL_CREDITS; ++ txq->pkt_sent = 0; ++ skb_queue_head_init(&txq->sk_list); ++ txq->last_retry_skb = NULL; ++ txq->nb_retry = 0; ++ txq->hwq = hwq; ++ txq->sta = sta; ++ for (i = 0; i < CONFIG_USER_MAX ; i++) ++ txq->pkt_pushed[i] = 0; ++ txq->push_limit = 0; ++ txq->tid = tid; ++#ifdef CONFIG_MAC80211_TXQ ++ txq->nb_ready_mac80211 = 0; ++#endif ++#ifdef CONFIG_RWNX_FULLMAC ++ txq->ps_id = LEGACY_PS_ID; ++ if (idx < nx_first_vif_txq_idx) { ++ int sta_idx = sta->sta_idx; ++ int tid = idx - (sta_idx * NX_NB_TXQ_PER_STA); ++ if (tid < NX_NB_TID_PER_STA) ++ txq->ndev_idx = NX_STA_NDEV_IDX(tid, sta_idx); ++ else ++ txq->ndev_idx = NDEV_NO_TXQ; ++ } else if (idx < nx_first_unk_txq_idx) { ++ txq->ndev_idx = nx_bcmc_txq_ndev_idx; ++ } else { ++ txq->ndev_idx = NDEV_NO_TXQ; ++ } ++ txq->ndev = ndev; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ txq->amsdu = NULL; ++ txq->amsdu_len = 0; ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++/** ++ * rwnx_txq_flush - Flush all buffers queued for a TXQ ++ * ++ * @rwnx_hw: main driver data ++ * @txq: txq to flush ++ */ ++void rwnx_txq_flush(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq) ++{ ++ struct sk_buff *skb; ++ ++ ++ while ((skb = skb_dequeue(&txq->sk_list)) != NULL) { ++ struct rwnx_sw_txhdr *sw_txhdr = ((struct rwnx_txhdr *)skb->data)->sw_hdr; ++ ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ if (sw_txhdr->desc.host.packet_cnt > 1) { ++ struct rwnx_amsdu_txhdr *amsdu_txhdr; ++ list_for_each_entry(amsdu_txhdr, &sw_txhdr->amsdu.hdrs, list) { ++ //dma_unmap_single(rwnx_hw->dev, amsdu_txhdr->dma_addr, ++ // amsdu_txhdr->map_len, DMA_TO_DEVICE); ++ dev_kfree_skb_any(amsdu_txhdr->skb); ++ } ++ } ++#endif ++ kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); ++ //dma_unmap_single(rwnx_hw->dev, sw_txhdr->dma_addr, sw_txhdr->map_len, ++ // DMA_TO_DEVICE); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ dev_kfree_skb_any(skb); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } ++} ++ ++/** ++ * rwnx_txq_deinit - De-initialize a TX queue ++ * ++ * @rwnx_hw: Driver main data ++ * @txq: TX queue to be de-initialized ++ * Any buffer stuck in a queue will be freed. ++ */ ++static void rwnx_txq_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq) ++{ ++ if (txq->idx == TXQ_INACTIVE) ++ return; ++ ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ rwnx_txq_del_from_hw_list(txq); ++ txq->idx = TXQ_INACTIVE; ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++ ++ rwnx_txq_flush(rwnx_hw, txq); ++} ++ ++/** ++ * rwnx_txq_vif_init - Initialize all TXQ linked to a vif ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: Pointer on VIF ++ * @status: Intial txq status ++ * ++ * Softmac : 1 VIF TXQ per HWQ ++ * ++ * Fullmac : 1 VIF TXQ for BC/MC ++ * 1 VIF TXQ for MGMT to unknown STA ++ */ ++void rwnx_txq_vif_init(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ u8 status) ++{ ++ struct rwnx_txq *txq; ++ int idx; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ idx = rwnx_txq_vif_idx(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_init(txq, idx, status, &rwnx_hw->hwq[RWNX_HWQ_BE], 0, ++ &rwnx_hw->sta_table[rwnx_vif->ap.bcmc_index], rwnx_vif->ndev); ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ idx = rwnx_txq_vif_idx(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_init(txq, idx, status, &rwnx_hw->hwq[RWNX_HWQ_VO], TID_MGT, ++ NULL, rwnx_vif->ndev); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++/** ++ * rwnx_txq_vif_deinit - Deinitialize all TXQ linked to a vif ++ * ++ * @rwnx_hw: main driver data ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_vif_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_deinit(rwnx_hw, txq); ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_deinit(rwnx_hw, txq); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++} ++ ++ ++/** ++ * rwnx_txq_sta_init - Initialize TX queues for a STA ++ * ++ * @rwnx_hw: Main driver data ++ * @rwnx_sta: STA for which tx queues need to be initialized ++ * @status: Intial txq status ++ * ++ * This function initialize all the TXQ associated to a STA. ++ * Softmac : 1 TXQ per TID ++ * ++ * Fullmac : 1 TXQ per TID (limited to 8) ++ * 1 TXQ for MGMT ++ */ ++void rwnx_txq_sta_init(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ u8 status) ++{ ++ struct rwnx_txq *txq; ++ int tid, idx; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[rwnx_sta->vif_idx]; ++ idx = rwnx_txq_sta_idx(rwnx_sta, 0); ++ ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_init(txq, idx, status, &rwnx_hw->hwq[rwnx_tid2hwq[tid]], tid, ++ rwnx_sta, rwnx_vif->ndev); ++ txq->ps_id = rwnx_sta->uapsd_tids & (1 << tid) ? UAPSD_ID : LEGACY_PS_ID; ++ idx++; ++ } ++ ++#endif /* CONFIG_RWNX_FULLMAC*/ ++} ++ ++/** ++ * rwnx_txq_sta_deinit - Deinitialize TX queues for a STA ++ * ++ * @rwnx_hw: Main driver data ++ * @rwnx_sta: STA for which tx queues need to be deinitialized ++ */ ++void rwnx_txq_sta_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) ++{ ++ struct rwnx_txq *txq; ++ int tid; ++ ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_deinit(rwnx_hw, txq); ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/** ++ * rwnx_txq_unk_vif_init - Initialize TXQ for unknown STA linked to a vif ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_unk_vif_init(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txq *txq; ++ int idx; ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ idx = rwnx_txq_vif_idx(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_init(txq, idx, 0, &rwnx_hw->hwq[RWNX_HWQ_VO], TID_MGT, NULL, rwnx_vif->ndev); ++} ++ ++/** ++ * rwnx_txq_tdls_vif_deinit - Deinitialize TXQ for unknown STA linked to a vif ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_unk_vif_deinit(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq; ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_deinit(rwnx_vif->rwnx_hw, txq); ++} ++ ++/** ++ * rwnx_init_unk_txq - Initialize TX queue for the transmission on a offchannel ++ * ++ * @vif: Interface for which the queue has to be initialized ++ * ++ * NOTE: Offchannel txq is only active for the duration of the ROC ++ */ ++void rwnx_txq_offchan_init(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ struct rwnx_txq *txq; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ rwnx_txq_init(txq, nx_off_chan_txq_idx, RWNX_TXQ_STOP_CHAN, ++ &rwnx_hw->hwq[RWNX_HWQ_VO], TID_MGT, NULL, rwnx_vif->ndev); ++} ++ ++/** ++ * rwnx_deinit_offchan_txq - Deinitialize TX queue for offchannel ++ * ++ * @vif: Interface that manages the STA ++ * ++ * This function deintialize txq for one STA. ++ * Any buffer stuck in a queue will be freed. ++ */ ++void rwnx_txq_offchan_deinit(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq; ++ ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ txq = &rwnx_vif->rwnx_hw->txq[nx_off_chan_txq_idx]; ++ rwnx_txq_deinit(rwnx_vif->rwnx_hw, txq); ++} ++ ++ ++/** ++ * rwnx_txq_tdls_vif_init - Initialize TXQ vif for TDLS ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_tdls_vif_init(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ ++ if (!(rwnx_hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return; ++ ++ rwnx_txq_unk_vif_init(rwnx_vif); ++} ++ ++/** ++ * rwnx_txq_tdls_vif_deinit - Deinitialize TXQ vif for TDLS ++ * ++ * @rwnx_vif: Pointer on VIF ++ */ ++void rwnx_txq_tdls_vif_deinit(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw; ++ ++ if (!(rwnx_hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return; ++ ++ rwnx_txq_unk_vif_deinit(rwnx_vif); ++} ++#endif ++ ++/****************************************************************************** ++ * Start/Stop functions ++ *****************************************************************************/ ++/** ++ * rwnx_txq_add_to_hw_list - Add TX queue to a HW queue schedule list. ++ * ++ * @txq: TX queue to add ++ * ++ * Add the TX queue if not already present in the HW queue list. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq) ++{ ++ if (!(txq->status & RWNX_TXQ_IN_HWQ_LIST)) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_add_to_hw(txq); ++#endif ++ txq->status |= RWNX_TXQ_IN_HWQ_LIST; ++ list_add_tail(&txq->sched_list, &txq->hwq->list); ++ txq->hwq->need_processing = true; ++ } ++} ++ ++/** ++ * rwnx_txq_del_from_hw_list - Delete TX queue from a HW queue schedule list. ++ * ++ * @txq: TX queue to delete ++ * ++ * Remove the TX queue from the HW queue list if present. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_del_from_hw_list(struct rwnx_txq *txq) ++{ ++ if (txq->status & RWNX_TXQ_IN_HWQ_LIST) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_del_from_hw(txq); ++#endif ++ txq->status &= ~RWNX_TXQ_IN_HWQ_LIST; ++ list_del(&txq->sched_list); ++ } ++} ++ ++/** ++ * rwnx_txq_skb_ready - Check if skb are available for the txq ++ * ++ * @txq: Pointer on txq ++ * @return True if there are buffer ready to be pushed on this txq, ++ * false otherwise ++ */ ++static inline bool rwnx_txq_skb_ready(struct rwnx_txq *txq) ++{ ++#ifdef CONFIG_MAC80211_TXQ ++ if (txq->nb_ready_mac80211 != NOT_MAC80211_TXQ) ++ return ((txq->nb_ready_mac80211 > 0) || !skb_queue_empty(&txq->sk_list)); ++ else ++#endif ++ return !skb_queue_empty(&txq->sk_list); ++} ++ ++/** ++ * rwnx_txq_start - Try to Start one TX queue ++ * ++ * @txq: TX queue to start ++ * @reason: reason why the TX queue is started (among RWNX_TXQ_STOP_xxx) ++ * ++ * Re-start the TX queue for one reason. ++ * If after this the txq is no longer stopped and some buffers are ready, ++ * the TX queue is also added to HW queue list. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_start(struct rwnx_txq *txq, u16 reason) ++{ ++ BUG_ON(txq == NULL); ++ if (txq->idx != TXQ_INACTIVE && (txq->status & reason)) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_start(txq, reason); ++#endif ++ txq->status &= ~reason; ++ if (!rwnx_txq_is_stopped(txq) && rwnx_txq_skb_ready(txq)) ++ rwnx_txq_add_to_hw_list(txq); ++ } ++} ++ ++/** ++ * rwnx_txq_stop - Stop one TX queue ++ * ++ * @txq: TX queue to stop ++ * @reason: reason why the TX queue is stopped (among RWNX_TXQ_STOP_xxx) ++ * ++ * Stop the TX queue. It will remove the TX queue from HW queue list ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_stop(struct rwnx_txq *txq, u16 reason) ++{ ++ BUG_ON(txq == NULL); ++ if (txq->idx != TXQ_INACTIVE) { ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_stop(txq, reason); ++#endif ++ txq->status |= reason; ++ rwnx_txq_del_from_hw_list(txq); ++ } ++} ++ ++ ++/** ++ * rwnx_txq_sta_start - Start all the TX queue linked to a STA ++ * ++ * @sta: STA whose TX queues must be re-started ++ * @reason: Reason why the TX queue are restarted (among RWNX_TXQ_STOP_xxx) ++ * @rwnx_hw: Driver main data ++ * ++ * This function will re-start all the TX queues of the STA for the reason ++ * specified. It can be : ++ * - RWNX_TXQ_STOP_STA_PS: the STA is no longer in power save mode ++ * - RWNX_TXQ_STOP_VIF_PS: the VIF is in power save mode (p2p absence) ++ * - RWNX_TXQ_STOP_CHAN: the STA's VIF is now on the current active channel ++ * ++ * Any TX queue with buffer ready and not Stopped for other reasons, will be ++ * added to the HW queue list ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_sta_start(struct rwnx_sta *rwnx_sta, u16 reason ++#ifdef CONFIG_RWNX_FULLMAC ++ , struct rwnx_hw *rwnx_hw ++#endif ++ ) ++{ ++ struct rwnx_txq *txq; ++ int tid; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_sta_start(rwnx_sta->sta_idx); ++#endif ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_start(txq, reason); ++ } ++} ++ ++ ++/** ++ * rwnx_stop_sta_txq - Stop all the TX queue linked to a STA ++ * ++ * @sta: STA whose TX queues must be stopped ++ * @reason: Reason why the TX queue are stopped (among RWNX_TX_STOP_xxx) ++ * @rwnx_hw: Driver main data ++ * ++ * This function will stop all the TX queues of the STA for the reason ++ * specified. It can be : ++ * - RWNX_TXQ_STOP_STA_PS: the STA is in power save mode ++ * - RWNX_TXQ_STOP_VIF_PS: the VIF is in power save mode (p2p absence) ++ * - RWNX_TXQ_STOP_CHAN: the STA's VIF is not on the current active channel ++ * ++ * Any TX queue present in a HW queue list will be removed from this list. ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_sta_stop(struct rwnx_sta *rwnx_sta, u16 reason ++#ifdef CONFIG_RWNX_FULLMAC ++ , struct rwnx_hw *rwnx_hw ++#endif ++ ) ++{ ++ struct rwnx_txq *txq; ++ int tid; ++ ++ if (!rwnx_sta) ++ return; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_sta_stop(rwnx_sta->sta_idx); ++#endif ++ foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { ++ rwnx_txq_stop(txq, reason); ++ } ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_start(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ if (rwnx_vif->sta.tdls_sta) ++ rwnx_txq_sta_start(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_tdls_sta_stop(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_stop(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++ if (rwnx_vif->sta.tdls_sta) ++ rwnx_txq_sta_stop(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++static inline void rwnx_txq_vif_for_each_sta(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, ++ void (*f)(struct rwnx_sta *, u16, struct rwnx_hw *), u16 reason) { ++ ++ switch (RWNX_VIF_TYPE(rwnx_vif)) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ { ++ if (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE) ++ f(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ if (!WARN_ON(rwnx_vif->sta.ap == NULL)) ++ f(rwnx_vif->sta.ap, reason, rwnx_hw); ++ break; ++ } ++ case NL80211_IFTYPE_AP_VLAN: ++ rwnx_vif = rwnx_vif->ap_vlan.master; ++ __attribute__((__fallthrough__)); ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_MESH_POINT: ++ case NL80211_IFTYPE_P2P_GO: ++ { ++ struct rwnx_sta *sta; ++ list_for_each_entry(sta, &rwnx_vif->ap.sta_list, list) { ++ f(sta, reason, rwnx_hw); ++ } ++ break; ++ } ++ default: ++ BUG(); ++ break; ++ } ++} ++#endif ++ ++/** ++ * rwnx_txq_vif_start - START TX queues of all STA associated to the vif ++ * and vif's TXQ ++ * ++ * @vif: Interface to start ++ * @reason: Start reason (RWNX_TXQ_STOP_CHAN or RWNX_TXQ_STOP_VIF_PS) ++ * @rwnx_hw: Driver main data ++ * ++ * Iterate over all the STA associated to the vif and re-start them for the ++ * reason @reason ++ * Take tx_lock ++ */ ++void rwnx_txq_vif_start(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_txq *txq; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_start(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ //Reject if monitor interface ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MONITOR) ++ goto end; ++ ++ if (rwnx_vif->roc_tdls && rwnx_vif->sta.tdls_sta && rwnx_vif->sta.tdls_sta->tdls.chsw_en) { ++ rwnx_txq_sta_start(rwnx_vif->sta.tdls_sta, reason, rwnx_hw); ++ } ++ if (!rwnx_vif->roc_tdls) { ++ rwnx_txq_vif_for_each_sta(rwnx_hw, rwnx_vif, rwnx_txq_sta_start, reason); ++ } ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_start(txq, reason); ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_start(txq, reason); ++ ++end: ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++ ++ ++/** ++ * rwnx_txq_vif_stop - STOP TX queues of all STA associated to the vif ++ * ++ * @vif: Interface to stop ++ * @arg: Stop reason (RWNX_TXQ_STOP_CHAN or RWNX_TXQ_STOP_VIF_PS) ++ * @rwnx_hw: Driver main data ++ * ++ * Iterate over all the STA associated to the vif and stop them for the ++ * reason RWNX_TXQ_STOP_CHAN or RWNX_TXQ_STOP_VIF_PS ++ * Take tx_lock ++ */ ++void rwnx_txq_vif_stop(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_txq *txq; ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_vif_stop(rwnx_vif->vif_index); ++#endif ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ //Reject if monitor interface ++ if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MONITOR) ++ goto end; ++ ++ rwnx_txq_vif_for_each_sta(rwnx_hw, rwnx_vif, rwnx_txq_sta_stop, reason); ++ ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_BCMC_TXQ_TYPE); ++ rwnx_txq_stop(txq, reason); ++ txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE); ++ rwnx_txq_stop(txq, reason); ++ ++end: ++#endif /* CONFIG_RWNX_FULLMAC*/ ++ ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++/** ++ * rwnx_start_offchan_txq - START TX queue for offchannel frame ++ * ++ * @rwnx_hw: Driver main data ++ */ ++void rwnx_txq_offchan_start(struct rwnx_hw *rwnx_hw) ++{ ++ struct rwnx_txq *txq; ++ int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX; ++ ++ if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ++ ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || ++ g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ ++ nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC; ++ } ++ ++ ++ txq = &rwnx_hw->txq[nx_off_chan_txq_idx]; ++ spin_lock_bh(&rwnx_hw->tx_lock); ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_CHAN); ++ spin_unlock_bh(&rwnx_hw->tx_lock); ++} ++ ++/** ++ * rwnx_switch_vif_sta_txq - Associate TXQ linked to a STA to a new vif ++ * ++ * @sta: STA whose txq must be switched ++ * @old_vif: Vif currently associated to the STA (may no longer be active) ++ * @new_vif: vif which should be associated to the STA for now on ++ * ++ * This function will switch the vif (i.e. the netdev) associated to all STA's ++ * TXQ. This is used when AP_VLAN interface are created. ++ * If one STA is associated to an AP_vlan vif, it will be moved from the master ++ * AP vif to the AP_vlan vif. ++ * If an AP_vlan vif is removed, then STA will be moved back to mastert AP vif. ++ * ++ */ ++void rwnx_txq_sta_switch_vif(struct rwnx_sta *sta, struct rwnx_vif *old_vif, ++ struct rwnx_vif *new_vif) ++{ ++ struct rwnx_hw *rwnx_hw = new_vif->rwnx_hw; ++ struct rwnx_txq *txq; ++ int i; ++ ++ /* start TXQ on the new interface, and update ndev field in txq */ ++ if (!netif_carrier_ok(new_vif->ndev)) ++ netif_carrier_on(new_vif->ndev); ++ txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); ++ for (i = 0; i < NX_NB_TID_PER_STA; i++, txq++) { ++ txq->ndev = new_vif->ndev; ++ netif_wake_subqueue(txq->ndev, txq->ndev_idx); ++ } ++} ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/****************************************************************************** ++ * TXQ queue/schedule functions ++ *****************************************************************************/ ++/** ++ * rwnx_txq_queue_skb - Queue a buffer in a TX queue ++ * ++ * @skb: Buffer to queue ++ * @txq: TX Queue in which the buffer must be added ++ * @rwnx_hw: Driver main data ++ * @retry: Should it be queued in the retry list ++ * ++ * @return: Retrun 1 if txq has been added to hwq list, 0 otherwise ++ * ++ * Add a buffer in the buffer list of the TX queue ++ * and add this TX queue in the HW queue list if the txq is not stopped. ++ * If this is a retry packet it is added after the last retry packet or at the ++ * beginning if there is no retry packet queued. ++ * ++ * If the STA is in PS mode and this is the first packet queued for this txq ++ * update TIM. ++ * ++ * To be called with tx_lock hold ++ */ ++int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, ++ struct rwnx_hw *rwnx_hw, bool retry) ++{ ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ if (unlikely(txq->sta && txq->sta->ps.active)) { ++ txq->sta->ps.pkt_ready[txq->ps_id]++; ++#ifdef CREATE_TRACE_POINTS ++ trace_ps_queue(txq->sta); ++#endif ++ if (txq->sta->ps.pkt_ready[txq->ps_id] == 1) { ++ rwnx_set_traffic_status(rwnx_hw, txq->sta, true, txq->ps_id); ++ } ++ } ++#endif ++ ++ if (!retry) { ++ /* add buffer in the sk_list */ ++ skb_queue_tail(&txq->sk_list, skb); ++ } else { ++ if (txq->last_retry_skb) ++#ifdef CONFIG_GKI ++ rwnx_skb_append(txq->last_retry_skb, skb, &txq->sk_list); ++#else ++ skb_append(txq->last_retry_skb, skb, &txq->sk_list); ++#endif ++ else ++ skb_queue_head(&txq->sk_list, skb); ++ ++ txq->last_retry_skb = skb; ++ txq->nb_retry++; ++ } ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_queue_skb(skb, txq, retry); ++#endif ++ /* Flowctrl corresponding netdev queue if needed */ ++#ifdef CONFIG_RWNX_FULLMAC ++#ifndef CONFIG_ONE_TXQ ++ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ if ((txq->ndev_idx != NDEV_NO_TXQ) && ((skb_queue_len(&txq->sk_list) > RWNX_NDEV_FLOW_CTRL_STOP) && ++ !rwnx_hw->sdiodev->flowctrl)) { ++// (atomic_read(&rwnx_hw->sdiodev->tx_priv->tx_pktcnt) >= tx_fc_high_water))) { ++#else ++ /* If too many buffer are queued for this TXQ stop netdev queue */ ++ if ((txq->ndev_idx != NDEV_NO_TXQ) && ++ (skb_queue_len(&txq->sk_list) > RWNX_NDEV_FLOW_CTRL_STOP)) { ++#endif ++ ++ txq->status |= RWNX_TXQ_NDEV_FLOW_CTRL; ++ netif_stop_subqueue(txq->ndev, txq->ndev_idx); ++#ifdef CREATE_TRACE_POINT ++ trace_txq_flowctrl_stop(txq); ++#endif ++ } ++#endif /* CONFIG_ONE_TXQ */ ++#else /* ! CONFIG_RWNX_FULLMAC */ ++ ++ if (!retry && ++txq->hwq->len == txq->hwq->len_stop) { ++ trace_hwq_flowctrl_stop(txq->hwq->id); ++ ieee80211_stop_queue(rwnx_hw->hw, txq->hwq->id); ++ rwnx_hw->stats.queues_stops++; ++ } ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++ /* add it in the hwq list if not stopped and not yet present */ ++ if (!rwnx_txq_is_stopped(txq)) { ++ rwnx_txq_add_to_hw_list(txq); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * rwnx_txq_confirm_any - Process buffer confirmed by fw ++ * ++ * @rwnx_hw: Driver main data ++ * @txq: TX Queue ++ * @hwq: HW Queue ++ * @sw_txhdr: software descriptor of the confirmed packet ++ * ++ * Process a buffer returned by the fw. It doesn't check buffer status ++ * and only does systematic counter update: ++ * - hw credit ++ * - buffer pushed to fw ++ * ++ * To be called with tx_lock hold ++ */ ++void rwnx_txq_confirm_any(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, ++ struct rwnx_hwq *hwq, struct rwnx_sw_txhdr *sw_txhdr) ++{ ++ int user = 0; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ int group_id; ++ ++ user = RWNX_MUMIMO_INFO_POS_ID(sw_txhdr->desc.host.mumimo_info); ++ group_id = RWNX_MUMIMO_INFO_GROUP_ID(sw_txhdr->desc.host.mumimo_info); ++ ++ if ((txq->idx != TXQ_INACTIVE) && ++ (txq->pkt_pushed[user] == 1) && ++ (txq->status & RWNX_TXQ_STOP_MU_POS)) ++ rwnx_txq_start(txq, RWNX_TXQ_STOP_MU_POS); ++ ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++ if (txq->pkt_pushed[user]) ++ txq->pkt_pushed[user]--; ++ ++ hwq->need_processing = true; ++ rwnx_hw->stats.cfm_balance[hwq->id]--; ++} ++ ++/****************************************************************************** ++ * HWQ processing ++ *****************************************************************************/ ++static inline ++bool rwnx_txq_take_mu_lock(struct rwnx_hw *rwnx_hw) ++{ ++ bool res = false; ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ if (rwnx_hw->mod_params->mutx) ++ res = (down_trylock(&rwnx_hw->mu.lock) == 0); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ return res; ++} ++ ++static inline ++void rwnx_txq_release_mu_lock(struct rwnx_hw *rwnx_hw) ++{ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ up(&rwnx_hw->mu.lock); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++} ++ ++static inline ++void rwnx_txq_set_mu_info(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, ++ int group_id, int pos) ++{ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ trace_txq_select_mu_group(txq, group_id, pos); ++ if (group_id) { ++ txq->mumimo_info = group_id | (pos << 6); ++ rwnx_mu_set_active_group(rwnx_hw, group_id); ++ } else ++ txq->mumimo_info = 0; ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++} ++ ++static inline ++s8 rwnx_txq_get_credits(struct rwnx_txq *txq) ++{ ++ s8 cred = txq->credits; ++ /* if destination is in PS mode, push_limit indicates the maximum ++ number of packet that can be pushed on this txq. */ ++ if (txq->push_limit && (cred > txq->push_limit)) { ++ cred = txq->push_limit; ++ } ++ return cred; ++} ++ ++/** ++ * skb_queue_extract - Extract buffer from skb list ++ * ++ * @list: List of skb to extract from ++ * @head: List of skb to append to ++ * @nb_elt: Number of skb to extract ++ * ++ * extract the first @nb_elt of @list and append them to @head ++ * It is assume that: ++ * - @list contains more that @nb_elt ++ * - There is no need to take @list nor @head lock to modify them ++ */ ++static inline void skb_queue_extract(struct sk_buff_head *list, ++ struct sk_buff_head *head, int nb_elt) ++{ ++ int i; ++ struct sk_buff *first, *last, *ptr; ++ ++ first = ptr = list->next; ++ for (i = 0; i < nb_elt; i++) { ++ ptr = ptr->next; ++ } ++ last = ptr->prev; ++ ++ /* unlink nb_elt in list */ ++ list->qlen -= nb_elt; ++ list->next = ptr; ++ ptr->prev = (struct sk_buff *)list; ++ ++ /* append nb_elt at end of head */ ++ head->qlen += nb_elt; ++ last->next = (struct sk_buff *)head; ++ head->prev->next = first; ++ first->prev = head->prev; ++ head->prev = last; ++} ++ ++ ++#ifdef CONFIG_MAC80211_TXQ ++/** ++ * rwnx_txq_mac80211_dequeue - Dequeue buffer from mac80211 txq and ++ * add them to push list ++ * ++ * @rwnx_hw: Main driver data ++ * @sk_list: List of buffer to push (initialized without lock) ++ * @txq: TXQ to dequeue buffers from ++ * @max: Max number of buffer to dequeue ++ * ++ * Dequeue buffer from mac80211 txq, prepare them for transmission and chain them ++ * to the list of buffer to push. ++ * ++ * @return true if no more buffer are queued in mac80211 txq and false otherwise. ++ */ ++static bool rwnx_txq_mac80211_dequeue(struct rwnx_hw *rwnx_hw, ++ struct sk_buff_head *sk_list, ++ struct rwnx_txq *txq, int max) ++{ ++ struct ieee80211_txq *mac_txq; ++ struct sk_buff *skb; ++ unsigned long mac_txq_len; ++ ++ if (txq->nb_ready_mac80211 == NOT_MAC80211_TXQ) ++ return true; ++ ++ mac_txq = container_of((void *)txq, struct ieee80211_txq, drv_priv); ++ ++ for (; max > 0; max--) { ++ skb = rwnx_tx_dequeue_prep(rwnx_hw, mac_txq); ++ if (skb == NULL) ++ return true; ++ ++ __skb_queue_tail(sk_list, skb); ++ } ++ ++ /* re-read mac80211 txq current length. ++ It is mainly for debug purpose to trace dropped packet. There is no ++ problems to have nb_ready_mac80211 != actual mac80211 txq length */ ++ ieee80211_txq_get_depth(mac_txq, &mac_txq_len, NULL); ++ if (txq->nb_ready_mac80211 > mac_txq_len) ++ trace_txq_drop(txq, txq->nb_ready_mac80211 - mac_txq_len); ++ txq->nb_ready_mac80211 = mac_txq_len; ++ ++ return (txq->nb_ready_mac80211 == 0); ++} ++#endif ++ ++/** ++ * rwnx_txq_get_skb_to_push - Get list of buffer to push for one txq ++ * ++ * @rwnx_hw: main driver data ++ * @hwq: HWQ on wich buffers will be pushed ++ * @txq: TXQ to get buffers from ++ * @user: user postion to use ++ * @sk_list_push: list to update ++ * ++ * ++ * This function will returned a list of buffer to push for one txq. ++ * It will take into account the number of credit of the HWQ for this user ++ * position and TXQ (and push_limit). ++ * This allow to get a list that can be pushed without having to test for ++ * hwq/txq status after each push ++ * ++ * If a MU group has been selected for this txq, it will also update the ++ * counter for the group ++ * ++ * @return true if txq no longer have buffer ready after the ones returned. ++ * false otherwise ++ */ ++static ++bool rwnx_txq_get_skb_to_push(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq, ++ struct rwnx_txq *txq, int user, ++ struct sk_buff_head *sk_list_push) ++{ ++ int nb_ready = skb_queue_len(&txq->sk_list); ++ int credits = rwnx_txq_get_credits(txq); ++ bool res = false; ++ ++ __skb_queue_head_init(sk_list_push); ++ ++ if (credits >= nb_ready) { ++ skb_queue_splice_init(&txq->sk_list, sk_list_push); ++#ifdef CONFIG_MAC80211_TXQ ++ res = rwnx_txq_mac80211_dequeue(rwnx_hw, sk_list_push, txq, credits - nb_ready); ++ credits = skb_queue_len(sk_list_push); ++#else ++ res = true; ++ credits = nb_ready; ++#endif ++ } else { ++ skb_queue_extract(&txq->sk_list, sk_list_push, credits); ++ ++ /* When processing PS service period (i.e. push_limit != 0), no longer ++ process this txq if the buffers extracted will complete the SP for ++ this txq */ ++ if (txq->push_limit && (credits == txq->push_limit)) ++ res = true; ++ } ++ ++ rwnx_mu_set_active_sta(rwnx_hw, rwnx_txq_2_sta(txq), credits); ++ ++ return res; ++} ++ ++/** ++ * rwnx_txq_select_user - Select User queue for a txq ++ * ++ * @rwnx_hw: main driver data ++ * @mu_lock: true is MU lock is taken ++ * @txq: TXQ to select MU group for ++ * @hwq: HWQ for the TXQ ++ * @user: Updated with user position selected ++ * ++ * @return false if it is no possible to process this txq. ++ * true otherwise ++ * ++ * This function selects the MU group to use for a TXQ. ++ * The selection is done as follow: ++ * ++ * - return immediately for STA that don't belongs to any group and select ++ * group 0 / user 0 ++ * ++ * - If MU tx is disabled (by user mutx_on, or because mu group are being ++ * updated !mu_lock), select group 0 / user 0 ++ * ++ * - Use the best group selected by @rwnx_mu_group_sta_select. ++ * ++ * Each time a group is selected (except for the first case where sta ++ * doesn't belongs to a MU group), the function checks that no buffer is ++ * pending for this txq on another user position. If this is the case stop ++ * the txq (RWNX_TXQ_STOP_MU_POS) and return false. ++ * ++ */ ++static ++bool rwnx_txq_select_user(struct rwnx_hw *rwnx_hw, bool mu_lock, ++ struct rwnx_txq *txq, struct rwnx_hwq *hwq, int *user) ++{ ++ int pos = 0; ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ int id, group_id = 0; ++ struct rwnx_sta *sta = rwnx_txq_2_sta(txq); ++ ++ /* for sta that belong to no group return immediately */ ++ if (!sta || !sta->group_info.cnt) ++ goto end; ++ ++ /* If MU is disabled, need to check user */ ++ if (!rwnx_hw->mod_params->mutx_on || !mu_lock) ++ goto check_user; ++ ++ /* Use the "best" group selected */ ++ group_id = sta->group_info.group; ++ ++ if (group_id > 0) ++ pos = rwnx_mu_group_sta_get_pos(rwnx_hw, sta, group_id); ++ ++check_user: ++ /* check that we can push on this user position */ ++#if CONFIG_USER_MAX == 2 ++ id = (pos + 1) & 0x1; ++ if (txq->pkt_pushed[id]) { ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_MU_POS); ++ return false; ++ } ++ ++#else ++ for (id = 0 ; id < CONFIG_USER_MAX ; id++) { ++ if (id != pos && txq->pkt_pushed[id]) { ++ rwnx_txq_stop(txq, RWNX_TXQ_STOP_MU_POS); ++ return false; ++ } ++ } ++#endif ++ ++end: ++ rwnx_txq_set_mu_info(rwnx_hw, txq, group_id, pos); ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++ *user = pos; ++ return true; ++} ++ ++ ++/** ++ * rwnx_hwq_process - Process one HW queue list ++ * ++ * @rwnx_hw: Driver main data ++ * @hw_queue: HW queue index to process ++ * ++ * The function will iterate over all the TX queues linked in this HW queue ++ * list. For each TX queue, push as many buffers as possible in the HW queue. ++ * (NB: TX queue have at least 1 buffer, otherwise it wouldn't be in the list) ++ * - If TX queue no longer have buffer, remove it from the list and check next ++ * TX queue ++ * - If TX queue no longer have credits or has a push_limit (PS mode) and it ++ * is reached , remove it from the list and check next TX queue ++ * - If HW queue is full, update list head to start with the next TX queue on ++ * next call if current TX queue already pushed "too many" pkt in a row, and ++ * return ++ * ++ * To be called when HW queue list is modified: ++ * - when a buffer is pushed on a TX queue ++ * - when new credits are received ++ * - when a STA returns from Power Save mode or receives traffic request. ++ * - when Channel context change ++ * ++ * To be called with tx_lock hold ++ */ ++#define ALL_HWQ_MASK ((1 << CONFIG_USER_MAX) - 1) ++ ++void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq) ++{ ++ struct rwnx_txq *txq, *next; ++ int user, credit_map = 0; ++ bool mu_enable; ++#ifdef CREATE_TRACE_POINTS ++ trace_process_hw_queue(hwq); ++#endif ++ hwq->need_processing = false; ++ ++ mu_enable = rwnx_txq_take_mu_lock(rwnx_hw); ++ if (!mu_enable) ++ credit_map = ALL_HWQ_MASK - 1; ++ ++ list_for_each_entry_safe(txq, next, &hwq->list, sched_list) { ++ struct rwnx_txhdr *txhdr = NULL; ++ struct sk_buff_head sk_list_push; ++ struct sk_buff *skb; ++ bool txq_empty; ++#ifdef CREATE_TRACE_POINTS ++ trace_process_txq(txq); ++#endif ++ /* sanity check for debug */ ++ BUG_ON(!(txq->status & RWNX_TXQ_IN_HWQ_LIST)); ++ if(txq->idx == TXQ_INACTIVE){ ++ printk("%s txq->idx == TXQ_INACTIVE \r\n", __func__); ++ rwnx_txq_del_from_hw_list(txq); ++ rwnx_txq_flush(rwnx_hw, txq); ++ continue; ++ } ++ BUG_ON(txq->idx == TXQ_INACTIVE); ++ BUG_ON(txq->credits <= 0); ++ BUG_ON(!rwnx_txq_skb_ready(txq)); ++ ++ if (!rwnx_txq_select_user(rwnx_hw, mu_enable, txq, hwq, &user)) { ++ printk("select user:%d\n", user); ++ continue; ++ } ++ ++ txq_empty = rwnx_txq_get_skb_to_push(rwnx_hw, hwq, txq, user, ++ &sk_list_push); ++ while ((skb = __skb_dequeue(&sk_list_push)) != NULL) { ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ rwnx_tx_push(rwnx_hw, txhdr, 0); ++ } ++ ++ if (txq_empty) { ++ rwnx_txq_del_from_hw_list(txq); ++ txq->pkt_sent = 0; ++ } else if (rwnx_txq_is_scheduled(txq)) { ++ /* txq not empty, ++ - To avoid starving need to process other txq in the list ++ - For better aggregation, need to send "as many consecutive ++ pkt as possible" for he same txq ++ ==> Add counter to trigger txq switch ++ */ ++ if (txq->pkt_sent > hwq->size) { ++ txq->pkt_sent = 0; ++ list_rotate_left(&hwq->list); ++ } ++ } ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ /* Unable to complete PS traffic request because of hwq credit */ ++ if (txq->push_limit && txq->sta) { ++ if (txq->ps_id == LEGACY_PS_ID) { ++ /* for legacy PS abort SP and wait next ps-poll */ ++ txq->sta->ps.sp_cnt[txq->ps_id] -= txq->push_limit; ++ txq->push_limit = 0; ++ } ++ /* for u-apsd need to complete the SP to send EOSP frame */ ++ } ++#ifndef CONFIG_ONE_TXQ ++ /* restart netdev queue if number of queued buffer is below threshold */ ++#ifdef CONFIG_TX_NETIF_FLOWCTRL ++ if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && ++ (skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART)) { ++#else ++ if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && ++ skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART) { ++#endif ++ ++ txq->status &= ~RWNX_TXQ_NDEV_FLOW_CTRL; ++ netif_wake_subqueue(txq->ndev, txq->ndev_idx); ++#ifdef CREATE_TRACE_POINTS ++ trace_txq_flowctrl_restart(txq); ++#endif ++ } ++#endif /* CONFIG_ONE_TXQ */ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ } ++ ++ ++ if (mu_enable) ++ rwnx_txq_release_mu_lock(rwnx_hw); ++} ++ ++/** ++ * rwnx_hwq_process_all - Process all HW queue list ++ * ++ * @rwnx_hw: Driver main data ++ * ++ * Loop over all HWQ, and process them if needed ++ * To be called with tx_lock hold ++ */ ++void rwnx_hwq_process_all(struct rwnx_hw *rwnx_hw) ++{ ++ int id; ++ ++ rwnx_mu_group_sta_select(rwnx_hw); ++ ++ for (id = ARRAY_SIZE(rwnx_hw->hwq) - 1; id >= 0 ; id--) { ++ if (rwnx_hw->hwq[id].need_processing) { ++ rwnx_hwq_process(rwnx_hw, &rwnx_hw->hwq[id]); ++ } ++ } ++} ++ ++/** ++ * rwnx_hwq_init - Initialize all hwq structures ++ * ++ * @rwnx_hw: Driver main data ++ * ++ */ ++void rwnx_hwq_init(struct rwnx_hw *rwnx_hw) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(rwnx_hw->hwq); i++) { ++ struct rwnx_hwq *hwq = &rwnx_hw->hwq[i]; ++ ++ hwq->id = i; ++ hwq->size = nx_txdesc_cnt[i]; ++ INIT_LIST_HEAD(&hwq->list); ++ ++ } ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h +new file mode 100644 +index 000000000000..9653d014bf70 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h +@@ -0,0 +1,404 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_txq.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++#ifndef _RWNX_TXQ_H_ ++#define _RWNX_TXQ_H_ ++ ++#include ++#include ++#include ++ ++#include ++ ++#ifdef CONFIG_RWNX_FULLMAC ++/** ++ * Fullmac TXQ configuration: ++ * - STA: 1 TXQ per TID (limited to 8) ++ * 1 TXQ for bufferable MGT frames ++ * - VIF: 1 TXQ for Multi/Broadcast + ++ * 1 TXQ for MGT for unknown STAs or non-bufferable MGT frames ++ * - 1 TXQ for offchannel transmissions ++ * ++ * ++ * Txq mapping looks like ++ * for NX_REMOTE_STA_MAX=10 and NX_VIRT_DEV_MAX=4 ++ * ++ * | TXQ | NDEV_ID | VIF | STA | TID | HWQ | ++ * |-----+---------+-----+-------+------+-----|- ++ * | 0 | 0 | | 0 | 0 | 1 | 9 TXQ per STA ++ * | 1 | 1 | | 0 | 1 | 0 | (8 data + 1 mgmt) ++ * | 2 | 2 | | 0 | 2 | 0 | ++ * | 3 | 3 | | 0 | 3 | 1 | ++ * | 4 | 4 | | 0 | 4 | 2 | ++ * | 5 | 5 | | 0 | 5 | 2 | ++ * | 6 | 6 | | 0 | 6 | 3 | ++ * | 7 | 7 | | 0 | 7 | 3 | ++ * | 8 | N/A | | 0 | MGMT | 3 | ++ * |-----+---------+-----+-------+------+-----|- ++ * | ... | | | | | | Same for all STAs ++ * |-----+---------+-----+-------+------+-----|- ++ * | 90 | 80 | 0 | BC/MC | 0 | 1/4 | 1 TXQ for BC/MC per VIF ++ * | ... | | | | | | ++ * | 93 | 80 | 3 | BC/MC | 0 | 1/4 | ++ * |-----+---------+-----+-------+------+-----|- ++ * | 94 | N/A | 0 | N/A | MGMT | 3 | 1 TXQ for unknown STA per VIF ++ * | ... | | | | | | ++ * | 97 | N/A | 3 | N/A | MGMT | 3 | ++ * |-----+---------+-----+-------+------+-----|- ++ * | 98 | N/A | | N/A | MGMT | 3 | 1 TXQ for offchannel frame ++ */ ++#define NX_NB_TID_PER_STA 8 ++#define NX_NB_TXQ_PER_STA (NX_NB_TID_PER_STA + 1) ++#define NX_NB_TXQ_PER_VIF 2 ++#define NX_NB_TXQ ((NX_NB_TXQ_PER_STA * NX_REMOTE_STA_MAX) + \ ++ (NX_NB_TXQ_PER_VIF * NX_VIRT_DEV_MAX) + 1) ++ ++#define NX_FIRST_VIF_TXQ_IDX (NX_REMOTE_STA_MAX * NX_NB_TXQ_PER_STA) ++#define NX_FIRST_BCMC_TXQ_IDX NX_FIRST_VIF_TXQ_IDX ++#define NX_FIRST_UNK_TXQ_IDX (NX_FIRST_BCMC_TXQ_IDX + NX_VIRT_DEV_MAX) ++ ++#define NX_OFF_CHAN_TXQ_IDX (NX_FIRST_VIF_TXQ_IDX + \ ++ (NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF)) ++ ++#define NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC (NX_REMOTE_STA_MAX_FOR_OLD_IC * NX_NB_TXQ_PER_STA) ++#define NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC ++#define NX_FIRST_UNK_TXQ_IDX_FOR_OLD_IC (NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC + NX_VIRT_DEV_MAX) ++ ++#define NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC (NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + \ ++ (NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF)) ++ ++ ++#define NX_BCMC_TXQ_TYPE 0 ++#define NX_UNK_TXQ_TYPE 1 ++ ++/** ++ * Each data TXQ is a netdev queue. TXQ to send MGT are not data TXQ as ++ * they did not recieved buffer from netdev interface. ++ * Need to allocate the maximum case. ++ * AP : all STAs + 1 BC/MC ++ */ ++#define NX_NB_NDEV_TXQ ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX) + 1) ++#define NX_NB_NDEV_TXQ_FOR_OLD_IC ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC) + 1) ++ ++#define NX_BCMC_TXQ_NDEV_IDX (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX) ++#define NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC) ++#define NX_STA_NDEV_IDX(tid, sta_idx) ((tid) + (sta_idx) * NX_NB_TID_PER_STA) ++#define NDEV_NO_TXQ 0xffff ++#if (NX_NB_NDEV_TXQ >= NDEV_NO_TXQ) ++#error("Need to increase struct rwnx_txq->ndev_idx size") ++#endif ++ ++/* stop netdev queue when number of queued buffers if greater than this */ ++#define RWNX_NDEV_FLOW_CTRL_STOP 64 ++/* restart netdev queue when number of queued buffers is lower than this */ ++#define RWNX_NDEV_FLOW_CTRL_RESTART 64 ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++#define TXQ_INACTIVE 0xffff ++#if (NX_NB_TXQ >= TXQ_INACTIVE) ++#error("Need to increase struct rwnx_txq->idx size") ++#endif ++ ++#define NX_TXQ_INITIAL_CREDITS 64 ++ ++/** ++ * TXQ tid sorted by decreasing priority ++ */ ++extern const int nx_tid_prio[NX_NB_TID_PER_STA]; ++ ++/** ++ * struct rwnx_hwq - Structure used to save information relative to ++ * an AC TX queue (aka HW queue) ++ * @list: List of TXQ, that have buffers ready for this HWQ ++ * @credits: available credit for the queue (i.e. nb of buffers that ++ * can be pushed to FW ) ++ * @id Id of the HWQ among RWNX_HWQ_.... ++ * @size size of the queue ++ * @need_processing Indicate if hwq should be processed ++ * @len number of packet ready to be pushed to fw for this HW queue ++ * @len_stop threshold to stop mac80211(i.e. netdev) queues. Stop queue when ++ * driver has more than @len_stop packets ready. ++ * @len_start threshold to wake mac8011 queues. Wake queue when driver has ++ * less than @len_start packets ready. ++ */ ++struct rwnx_hwq { ++ struct list_head list; ++ u8 size; ++ u8 id; ++ bool need_processing; ++}; ++ ++/** ++ * enum rwnx_push_flags - Flags of pushed buffer ++ * ++ * @RWNX_PUSH_RETRY Pushing a buffer for retry ++ * @RWNX_PUSH_IMMEDIATE Pushing a buffer without queuing it first ++ */ ++enum rwnx_push_flags { ++ RWNX_PUSH_RETRY = BIT(0), ++ RWNX_PUSH_IMMEDIATE = BIT(1), ++}; ++ ++/** ++ * enum rwnx_txq_flags - TXQ status flag ++ * ++ * @RWNX_TXQ_IN_HWQ_LIST: The queue is scheduled for transmission ++ * @RWNX_TXQ_STOP_FULL: No more credits for the queue ++ * @RWNX_TXQ_STOP_CSA: CSA is in progress ++ * @RWNX_TXQ_STOP_STA_PS: Destiniation sta is currently in power save mode ++ * @RWNX_TXQ_STOP_VIF_PS: Vif owning this queue is currently in power save mode ++ * @RWNX_TXQ_STOP_CHAN: Channel of this queue is not the current active channel ++ * @RWNX_TXQ_STOP_MU_POS: TXQ is stopped waiting for all the buffers pushed to ++ * fw to be confirmed ++ * @RWNX_TXQ_STOP: All possible reason to have a txq stopped ++ * @RWNX_TXQ_NDEV_FLOW_CTRL: associated netdev queue is currently stopped. ++ * Note: when a TXQ is flowctrl it is NOT stopped ++ */ ++enum rwnx_txq_flags { ++ RWNX_TXQ_IN_HWQ_LIST = BIT(0), ++ RWNX_TXQ_STOP_FULL = BIT(1), ++ RWNX_TXQ_STOP_CSA = BIT(2), ++ RWNX_TXQ_STOP_STA_PS = BIT(3), ++ RWNX_TXQ_STOP_VIF_PS = BIT(4), ++ RWNX_TXQ_STOP_CHAN = BIT(5), ++ RWNX_TXQ_STOP_MU_POS = BIT(6), ++ RWNX_TXQ_STOP = (RWNX_TXQ_STOP_FULL | RWNX_TXQ_STOP_CSA | ++ RWNX_TXQ_STOP_STA_PS | RWNX_TXQ_STOP_VIF_PS | ++ RWNX_TXQ_STOP_CHAN), ++ RWNX_TXQ_NDEV_FLOW_CTRL = BIT(7), ++}; ++ ++ ++/** ++ * struct rwnx_txq - Structure used to save information relative to ++ * a RA/TID TX queue ++ * ++ * @idx: Unique txq idx. Set to TXQ_INACTIVE if txq is not used. ++ * @status: bitfield of @rwnx_txq_flags. ++ * @credits: available credit for the queue (i.e. nb of buffers that ++ * can be pushed to FW). ++ * @pkt_sent: number of consecutive pkt sent without leaving HW queue list ++ * @pkt_pushed: number of pkt currently pending for transmission confirmation ++ * @sched_list: list node for HW queue schedule list (rwnx_hwq.list) ++ * @sk_list: list of buffers to push to fw ++ * @last_retry_skb: pointer on the last skb in @sk_list that is a retry. ++ * (retry skb are stored at the beginning of the list) ++ * NULL if no retry skb is queued in @sk_list ++ * @nb_retry: Number of retry packet queued. ++ * @hwq: Pointer on the associated HW queue. ++ * @push_limit: number of packet to push before removing the txq from hwq list. ++ * (we always have push_limit < skb_queue_len(sk_list)) ++ * @tid: TID ++ * ++ * SOFTMAC specific: ++ * @baw: Block Ack window information ++ * @amsdu_anchor: pointer to rwnx_sw_txhdr of the first subframe of the A-MSDU. ++ * NULL if no A-MSDU frame is in construction ++ * @amsdu_ht_len_cap: ++ * @amsdu_vht_len_cap: ++ * @nb_ready_mac80211: Number of buffer ready in mac80211 txq ++ * ++ * FULLMAC specific ++ * @ps_id: Index to use for Power save mode (LEGACY or UAPSD) ++ * @ndev_idx: txq idx from netdev point of view (0xFF for non netdev queue) ++ * @ndev: pointer to ndev of the corresponding vif ++ * @amsdu: pointer to rwnx_sw_txhdr of the first subframe of the A-MSDU. ++ * NULL if no A-MSDU frame is in construction ++ * @amsdu_len: Maximum size allowed for an A-MSDU. 0 means A-MSDU not allowed ++ */ ++struct rwnx_txq { ++ u16 idx; ++ u8 status; ++ s8 credits; ++ u8 pkt_sent; ++ u8 pkt_pushed[CONFIG_USER_MAX]; ++ struct list_head sched_list; ++ struct sk_buff_head sk_list; ++ struct sk_buff *last_retry_skb; ++ struct rwnx_hwq *hwq; ++ int nb_retry; ++ u8 push_limit; ++ u8 tid; ++#ifdef CONFIG_MAC80211_TXQ ++ unsigned long nb_ready_mac80211; ++#endif ++#ifdef CONFIG_RWNX_FULLMAC ++ struct rwnx_sta *sta; ++ u8 ps_id; ++ u16 ndev_idx; ++ struct net_device *ndev; ++#ifdef CONFIG_RWNX_AMSDUS_TX ++ struct rwnx_sw_txhdr *amsdu; ++ u16 amsdu_len; ++#endif /* CONFIG_RWNX_AMSDUS_TX */ ++#endif /* CONFIG_RWNX_FULLMAC */ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++ u8 mumimo_info; ++#endif ++}; ++ ++struct rwnx_sta; ++struct rwnx_vif; ++struct rwnx_hw; ++struct rwnx_sw_txhdr; ++ ++#ifdef CONFIG_RWNX_MUMIMO_TX ++#define RWNX_TXQ_GROUP_ID(txq) ((txq)->mumimo_info & 0x3f) ++#define RWNX_TXQ_POS_ID(txq) (((txq)->mumimo_info >> 6) & 0x3) ++#else ++#define RWNX_TXQ_GROUP_ID(txq) 0 ++#define RWNX_TXQ_POS_ID(txq) 0 ++#endif /* CONFIG_RWNX_MUMIMO_TX */ ++ ++static inline bool rwnx_txq_is_stopped(struct rwnx_txq *txq) ++{ ++ return (txq->status & RWNX_TXQ_STOP); ++} ++ ++static inline bool rwnx_txq_is_full(struct rwnx_txq *txq) ++{ ++ return (txq->status & RWNX_TXQ_STOP_FULL); ++} ++ ++static inline bool rwnx_txq_is_scheduled(struct rwnx_txq *txq) ++{ ++ return (txq->status & RWNX_TXQ_IN_HWQ_LIST); ++} ++ ++/** ++ * foreach_sta_txq - Macro to iterate over all TXQ of a STA in increasing ++ * TID order ++ * ++ * @sta: pointer to rwnx_sta ++ * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration ++ * @tid: int updated with the TXQ tid at each iteration ++ * @rwnx_hw: main driver data ++ */ ++#ifdef CONFIG_MAC80211_TXQ ++#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \ ++ for (tid = 0, txq = rwnx_txq_sta_get(sta, 0); \ ++ tid < NX_NB_TXQ_PER_STA; \ ++ tid++, txq = rwnx_txq_sta_get(sta, tid)) ++ ++#elif defined(CONFIG_RWNX_FULLMAC) /* CONFIG_RWNX_FULLMAC */ ++#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \ ++ for (tid = 0, txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); \ ++ tid < (is_multicast_sta(sta->sta_idx) ? 1 : NX_NB_TXQ_PER_STA); \ ++ tid++, txq++) ++ ++#endif ++ ++/** ++ * foreach_sta_txq_prio - Macro to iterate over all TXQ of a STA in ++ * decreasing priority order ++ * ++ * @sta: pointer to rwnx_sta ++ * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration ++ * @tid: int updated with the TXQ tid at each iteration ++ * @i: int updated with ieration count ++ * @rwnx_hw: main driver data ++ * ++ * Note: For fullmac txq for mgmt frame is skipped ++ */ ++#ifdef CONFIG_RWNX_FULLMAC ++#define foreach_sta_txq_prio(sta, txq, tid, i, rwnx_hw) \ ++ for (i = 0, tid = nx_tid_prio[0], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); \ ++ i < NX_NB_TID_PER_STA; \ ++ i++, tid = nx_tid_prio[i], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw)) ++#endif ++ ++/** ++ * foreach_vif_txq - Macro to iterate over all TXQ of a VIF (in AC order) ++ * ++ * @vif: pointer to rwnx_vif ++ * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration ++ * @ac: int updated with the TXQ ac at each iteration ++ */ ++#ifdef CONFIG_MAC80211_TXQ ++#define foreach_vif_txq(vif, txq, ac) \ ++ for (ac = RWNX_HWQ_BK, txq = rwnx_txq_vif_get(vif, ac); \ ++ ac < NX_NB_TXQ_PER_VIF; \ ++ ac++, txq = rwnx_txq_vif_get(vif, ac)) ++ ++#else ++#define foreach_vif_txq(vif, txq, ac) \ ++ for (ac = RWNX_HWQ_BK, txq = &vif->txqs[0]; \ ++ ac < NX_NB_TXQ_PER_VIF; \ ++ ac++, txq++) ++#endif ++ ++#ifdef CONFIG_RWNX_FULLMAC ++struct rwnx_txq *rwnx_txq_sta_get(struct rwnx_sta *sta, u8 tid, ++ struct rwnx_hw *rwnx_hw); ++struct rwnx_txq *rwnx_txq_vif_get(struct rwnx_vif *vif, u8 type); ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++/** ++ * rwnx_txq_vif_get_status - return status bits related to the vif ++ * ++ * @rwnx_vif: Pointer to vif structure ++ */ ++static inline u8 rwnx_txq_vif_get_status(struct rwnx_vif *rwnx_vif) ++{ ++ struct rwnx_txq *txq = rwnx_txq_vif_get(rwnx_vif, 0); ++ return (txq->status & (RWNX_TXQ_STOP_CHAN | RWNX_TXQ_STOP_VIF_PS)); ++} ++ ++void rwnx_txq_vif_init(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, ++ u8 status); ++void rwnx_txq_vif_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); ++void rwnx_txq_sta_init(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, ++ u8 status); ++void rwnx_txq_sta_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_unk_vif_init(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_unk_vif_deinit(struct rwnx_vif *vif); ++void rwnx_txq_offchan_init(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_offchan_deinit(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_tdls_vif_init(struct rwnx_vif *rwnx_vif); ++void rwnx_txq_tdls_vif_deinit(struct rwnx_vif *vif); ++void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_tdls_sta_stop(struct rwnx_vif *rwnx_vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++#endif ++ ++ ++void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq); ++void rwnx_txq_del_from_hw_list(struct rwnx_txq *txq); ++void rwnx_txq_stop(struct rwnx_txq *txq, u16 reason); ++void rwnx_txq_start(struct rwnx_txq *txq, u16 reason); ++void rwnx_txq_vif_start(struct rwnx_vif *vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_vif_stop(struct rwnx_vif *vif, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++ ++#ifdef CONFIG_RWNX_FULLMAC ++void rwnx_txq_sta_start(struct rwnx_sta *sta, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_sta_stop(struct rwnx_sta *sta, u16 reason, ++ struct rwnx_hw *rwnx_hw); ++void rwnx_txq_offchan_start(struct rwnx_hw *rwnx_hw); ++void rwnx_txq_sta_switch_vif(struct rwnx_sta *sta, struct rwnx_vif *old_vif, ++ struct rwnx_vif *new_vif); ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++ ++int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, ++ struct rwnx_hw *rwnx_hw, bool retry); ++void rwnx_txq_confirm_any(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, ++ struct rwnx_hwq *hwq, struct rwnx_sw_txhdr *sw_txhdr); ++ ++ ++void rwnx_hwq_init(struct rwnx_hw *rwnx_hw); ++void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq); ++void rwnx_hwq_process_all(struct rwnx_hw *rwnx_hw); ++ ++#endif /* _RWNX_TXQ_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c +new file mode 100644 +index 000000000000..6b3c6f29bf10 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c +@@ -0,0 +1,39 @@ ++/** ++ * rwnx_utils.c ++ * ++ * IPC utility function definitions ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ */ ++#include "rwnx_utils.h" ++#include "rwnx_defs.h" ++#include "rwnx_rx.h" ++#include "rwnx_tx.h" ++#include "rwnx_msg_rx.h" ++#include "rwnx_debugfs.h" ++#include "rwnx_prof.h" ++#include "ipc_host.h" ++ ++extern int get_testmode(void); ++extern void get_fw_path(char* fw_path); ++extern int testmode; ++extern char aic_fw_path[200]; ++ ++ ++int rwnx_init_aic(struct rwnx_hw *rwnx_hw) ++{ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++#ifdef AICWF_SDIO_SUPPORT ++ aicwf_sdio_host_init(&(rwnx_hw->sdio_env), NULL, NULL, rwnx_hw); ++#else ++ aicwf_usb_host_init(&(rwnx_hw->usb_env), NULL, NULL, rwnx_hw); ++#endif ++ rwnx_cmd_mgr_init(rwnx_hw->cmd_mgr); ++ ++ testmode = get_testmode(); ++ memset(aic_fw_path, 0, 200); ++ get_fw_path(aic_fw_path); ++ ++ return 0; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h +new file mode 100644 +index 000000000000..f71a601c2af3 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h +@@ -0,0 +1,133 @@ ++/** ++ * rwnx_ipc_utils.h ++ * ++ * IPC utility function declarations ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ */ ++#ifndef _RWNX_IPC_UTILS_H_ ++#define _RWNX_IPC_UTILS_H_ ++ ++#include ++#include ++#include ++#include "aicwf_debug.h" ++ ++ ++#include "lmac_msg.h" ++#if 0 ++#ifdef CONFIG_RWNX_DBG ++/* #define RWNX_DBG(format, arg...) pr_warn(format, ## arg) */ ++#define RWNX_DBG printk ++#else ++#define RWNX_DBG(a...) do {} while (0) ++#endif ++ ++#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ ++#endif ++enum rwnx_dev_flag { ++ RWNX_DEV_RESTARTING, ++ RWNX_DEV_STACK_RESTARTING, ++ RWNX_DEV_STARTED, ++}; ++ ++struct rwnx_hw; ++struct rwnx_sta; ++ ++/** ++ * struct rwnx_ipc_elem - Generic IPC buffer of fixed size ++ * ++ * @addr: Host address of the buffer. ++ * @dma_addr: DMA address of the buffer. ++ */ ++struct rwnx_ipc_elem { ++ void *addr; ++ dma_addr_t dma_addr; ++}; ++ ++/** ++ * struct rwnx_ipc_elem_pool - Generic pool of IPC buffers of fixed size ++ * ++ * @nb: Number of buffers currenlty allocated in the pool ++ * @buf: Array of buffers (size of array is @nb) ++ * @pool: DMA pool in which buffers have been allocated ++ */ ++struct rwnx_ipc_elem_pool { ++ int nb; ++ struct rwnx_ipc_elem *buf; ++ struct dma_pool *pool; ++}; ++ ++/** ++ * struct rwnx_ipc_elem - Generic IPC buffer of variable size ++ * ++ * @addr: Host address of the buffer. ++ * @dma_addr: DMA address of the buffer. ++ * @size: Size, in bytes, of the buffer ++ */ ++struct rwnx_ipc_elem_var { ++ void *addr; ++ dma_addr_t dma_addr; ++ size_t size; ++}; ++ ++/** ++ * struct rwnx_ipc_dbgdump_elem - IPC buffer for debug dump ++ * ++ * @mutex: Mutex to protect access to debug dump ++ * @buf: IPC buffer ++ */ ++struct rwnx_ipc_dbgdump_elem { ++ struct mutex mutex; ++ struct rwnx_ipc_elem_var buf; ++}; ++ ++static const u32 rwnx_rxbuff_pattern = 0xCAFEFADE; ++ ++/* ++ * Maximum Length of Radiotap header vendor specific data(in bytes) ++ */ ++#define RADIOTAP_HDR_VEND_MAX_LEN 16 ++ ++/* ++ * Maximum Radiotap Header Length without vendor specific data (in bytes) ++ */ ++#define RADIOTAP_HDR_MAX_LEN 80 ++ ++/* ++ * Unsupported HT Frame data length (in bytes) ++ */ ++#define UNSUP_RX_VEC_DATA_LEN 2 ++ ++/** ++ * struct rwnx_ipc_skb_elem - IPC buffer for SKB element ++ * ++ * @skb: Pointer to the skb buffer allocated ++ * @dma_addr: DMA address of the data buffer fo skb ++ * ++ */ ++struct rwnx_ipc_skb_elem { ++ struct sk_buff *skb; ++ dma_addr_t dma_addr; ++}; ++ ++#ifdef CONFIG_RWNX_FULLMAC ++ ++/* Maximum number of rx buffer the fw may use at the same time */ ++#define RWNX_RXBUFF_MAX (64 * NX_REMOTE_STA_MAX) ++ ++/** ++ * struct rwnx_ipc_rxbuf_elems - IPC buffers for RX ++ * ++ * @skb: Array of buffer push to FW. ++ * @idx: Index of the last pushed skb.(Use to find the next free entry quicker) ++ * ++ * Note: contrary to softmac version, dma_addr are stored inside skb->cb. ++ */ ++struct rwnx_ipc_rxbuf_elems { ++ struct sk_buff *skb[RWNX_RXBUFF_MAX]; ++ int idx; ++}; ++ ++#endif /* CONFIG_RWNX_FULLMAC */ ++#endif /* _RWNX_IPC_UTILS_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c +new file mode 100644 +index 000000000000..72e3c850b48e +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c +@@ -0,0 +1,195 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_v7.c - Support for v7 platform ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#include "rwnx_v7.h" ++#include "rwnx_defs.h" ++#include "rwnx_irqs.h" ++#include "reg_access.h" ++#include "hal_desc.h" ++ ++struct rwnx_v7 { ++ u8 *pci_bar0_vaddr; ++ u8 *pci_bar1_vaddr; ++}; ++ ++static int rwnx_v7_platform_enable(struct rwnx_hw *rwnx_hw) ++{ ++ int ret; ++ ++ /* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */ ++ ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0, ++ "rwnx", rwnx_hw); ++ return ret; ++} ++ ++static int rwnx_v7_platform_disable(struct rwnx_hw *rwnx_hw) ++{ ++ free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw); ++ return 0; ++} ++ ++static void rwnx_v7_platform_deinit(struct rwnx_plat *rwnx_plat) ++{ ++ #ifdef CONFIG_PCI ++ struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; ++ ++ pci_disable_device(rwnx_plat->pci_dev); ++ iounmap(rwnx_v7->pci_bar0_vaddr); ++ iounmap(rwnx_v7->pci_bar1_vaddr); ++ pci_release_regions(rwnx_plat->pci_dev); ++ pci_clear_master(rwnx_plat->pci_dev); ++ pci_disable_msi(rwnx_plat->pci_dev); ++ #endif ++ kfree(rwnx_plat); ++} ++ ++static u8 *rwnx_v7_get_address(struct rwnx_plat *rwnx_plat, int addr_name, ++ unsigned int offset) ++{ ++ struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; ++ ++ if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name)) ++ return NULL; ++ ++ if (addr_name == RWNX_ADDR_CPU) ++ return rwnx_v7->pci_bar0_vaddr + offset; ++ else ++ return rwnx_v7->pci_bar1_vaddr + offset; ++} ++ ++static void rwnx_v7_ack_irq(struct rwnx_plat *rwnx_plat) ++{ ++ ++} ++ ++static const u32 rwnx_v7_config_reg[] = { ++ NXMAC_DEBUG_PORT_SEL_ADDR, ++ SYSCTRL_DIAG_CONF_ADDR, ++ SYSCTRL_PHYDIAG_CONF_ADDR, ++ SYSCTRL_RIUDIAG_CONF_ADDR, ++ RF_V7_DIAGPORT_CONF1_ADDR, ++}; ++ ++static const u32 rwnx_v7_he_config_reg[] = { ++ SYSCTRL_DIAG_CONF0, ++ SYSCTRL_DIAG_CONF1, ++ SYSCTRL_DIAG_CONF2, ++ SYSCTRL_DIAG_CONF3, ++}; ++ ++static int rwnx_v7_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list) ++{ ++ u32 fpga_sign; ++ ++ if (!list) ++ return 0; ++ ++ fpga_sign = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_SIGNATURE_ADDR); ++ if (__FPGA_TYPE(fpga_sign) == 0xc0ca) { ++ *list = rwnx_v7_he_config_reg; ++ return ARRAY_SIZE(rwnx_v7_he_config_reg); ++ } else { ++ *list = rwnx_v7_config_reg; ++ return ARRAY_SIZE(rwnx_v7_config_reg); ++ } ++} ++ ++ ++/** ++ * rwnx_v7_platform_init - Initialize the DINI platform ++ * ++ * @pci_dev PCI device ++ * @rwnx_plat Pointer on struct rwnx_stat * to be populated ++ * ++ * @return 0 on success, < 0 otherwise ++ * ++ * Allocate and initialize a rwnx_plat structure for the dini platform. ++ */ ++int rwnx_v7_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat) ++{ ++ struct rwnx_v7 *rwnx_v7; ++ u16 pci_cmd; ++ int ret = 0; ++ ++ *rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_v7), ++ GFP_KERNEL); ++ if (!*rwnx_plat) ++ return -ENOMEM; ++ ++ rwnx_v7 = (struct rwnx_v7 *)(*rwnx_plat)->priv; ++ ++ /* Hotplug fixups */ ++ pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd); ++ pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; ++ pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd); ++ //pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2); ++ ++ ret = pci_enable_device(pci_dev); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_enable_device failed\n"); ++ goto out_enable; ++ } ++ ++ pci_set_master(pci_dev); ++ ++#if 0 ++ ret = pci_request_regions(pci_dev, KBUILD_MODNAME); ++ if (ret) { ++ dev_err(&(pci_dev->dev), "pci_request_regions failed\n"); ++ goto out_request; ++ } ++#endif ++ #ifdef CONFIG_PCI ++ if (pci_enable_msi(pci_dev)) { ++ dev_err(&(pci_dev->dev), "pci_enable_msi failed\n"); ++ goto out_msi; ++ ++ } ++ #endif ++ ++ rwnx_v7->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0); ++ if (!rwnx_v7->pci_bar0_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0); ++ ret = -ENOMEM; ++ goto out_bar0; ++ } ++ rwnx_v7->pci_bar1_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 1); ++ if (!rwnx_v7->pci_bar1_vaddr) { ++ dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 1); ++ ret = -ENOMEM; ++ goto out_bar1; ++ } ++ ++ (*rwnx_plat)->enable = rwnx_v7_platform_enable; ++ (*rwnx_plat)->disable = rwnx_v7_platform_disable; ++ (*rwnx_plat)->deinit = rwnx_v7_platform_deinit; ++ (*rwnx_plat)->get_address = rwnx_v7_get_address; ++ (*rwnx_plat)->ack_irq = rwnx_v7_ack_irq; ++ (*rwnx_plat)->get_config_reg = rwnx_v7_get_config_reg; ++ ++ return 0; ++ ++out_bar1: ++ iounmap(rwnx_v7->pci_bar0_vaddr); ++out_bar0: ++#ifdef CONFIG_PCI ++ pci_disable_msi(pci_dev); ++out_msi: ++#endif ++ pci_release_regions(pci_dev); ++//out_request: ++#ifdef CONFIG_PCI ++ pci_clear_master(pci_dev); ++#endif ++ pci_disable_device(pci_dev); ++out_enable: ++ kfree(*rwnx_plat); ++ return ret; ++} +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h +new file mode 100644 +index 000000000000..c2e39765ae1c +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h +@@ -0,0 +1,20 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_v7.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_V7_H_ ++#define _RWNX_V7_H_ ++ ++#include ++#include "rwnx_platform.h" ++ ++int rwnx_v7_platform_init(struct pci_dev *pci_dev, ++ struct rwnx_plat **rwnx_plat); ++ ++#endif /* _RWNX_V7_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h +new file mode 100644 +index 000000000000..46ecb5de1ca5 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h +@@ -0,0 +1,12 @@ ++#ifndef _RWNX_VERSION_H_ ++#define _RWNX_VERSION_H_ ++ ++#include "rwnx_version_gen.h" ++ ++static inline void rwnx_print_version(void) ++{ ++ AICWFDBG(LOGINFO, RWNX_VERS_BANNER"\n"); ++ AICWFDBG(LOGINFO, "RELEASE_DATE:%s \r\n", RELEASE_DATE); ++} ++ ++#endif /* _RWNX_VERSION_H_ */ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h +new file mode 100644 +index 000000000000..6fcb679c8934 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h +@@ -0,0 +1,4 @@ ++#define RWNX_VERS_REV "241c091M (master)" ++#define RWNX_VERS_MOD "6.4.3.0" ++#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" ++#define RELEASE_DATE "2025_0410_b99ca8b6" +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c +new file mode 100644 +index 000000000000..7c785e952c3d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c +@@ -0,0 +1,96 @@ ++#include ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) ++#include ++#else ++#include ++#endif ++#include "rwnx_defs.h" ++#include "rwnx_wakelock.h" ++ ++struct wakeup_source *rwnx_wakeup_init(const char *name) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0) ++ struct wakeup_source *ws; ++ ws = wakeup_source_create(name); ++ wakeup_source_add(ws); ++ return ws; ++#else ++ return NULL; ++#endif ++} ++ ++void rwnx_wakeup_deinit(struct wakeup_source *ws) ++{ ++ if (ws && ws->active) ++ __pm_relax(ws); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0) ++ wakeup_source_remove(ws); ++ wakeup_source_destroy(ws); ++#endif ++} ++ ++struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name) ++{ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++ return wakeup_source_register(dev, name); ++#else ++ ++#if defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_PLATFORM_ROCKCHIP) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) ++ return wakeup_source_register(dev, name); ++#else ++ return wakeup_source_register(name); ++#endif ++ ++#else ++ return wakeup_source_register(name); ++#endif//#if defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_PLATFORM_ROCKCHIP) ++ ++#endif//LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++} ++ ++void rwnx_wakeup_unregister(struct wakeup_source *ws) ++{ ++ if (ws && ws->active) ++ __pm_relax(ws); ++ wakeup_source_unregister(ws); ++} ++ ++void rwnx_wakeup_lock(struct wakeup_source *ws) ++{ ++ __pm_stay_awake(ws); ++} ++ ++void rwnx_wakeup_unlock(struct wakeup_source *ws) ++{ ++ __pm_relax(ws); ++} ++ ++void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec) ++{ ++ __pm_wakeup_event(ws, msec); ++} ++ ++void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw) ++{ ++ rwnx_hw->ws_tx = rwnx_wakeup_init("rwnx_tx_wakelock"); ++ rwnx_hw->ws_rx = rwnx_wakeup_init("rwnx_rx_wakelock"); ++ rwnx_hw->ws_irqrx = rwnx_wakeup_init("rwnx_irqrx_wakelock"); ++ rwnx_hw->ws_pwrctrl = rwnx_wakeup_init("rwnx_pwrcrl_wakelock"); ++} ++ ++void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw) ++{ ++ rwnx_wakeup_deinit(rwnx_hw->ws_tx); ++ rwnx_wakeup_deinit(rwnx_hw->ws_rx); ++ rwnx_wakeup_deinit(rwnx_hw->ws_irqrx); ++ rwnx_wakeup_deinit(rwnx_hw->ws_pwrctrl); ++ rwnx_hw->ws_tx = NULL; ++ rwnx_hw->ws_rx = NULL; ++ rwnx_hw->ws_irqrx = NULL; ++ rwnx_hw->ws_pwrctrl = NULL; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h +new file mode 100644 +index 000000000000..9c9655a46be2 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h +@@ -0,0 +1,21 @@ ++#ifndef __RWNX_WAKELOCK_H ++#define __RWNX_WAKELOCK_H ++ ++#include ++#include ++#include ++ ++struct wakeup_source *rwnx_wakeup_init(const char *name); ++void rwnx_wakeup_deinit(struct wakeup_source *ws); ++ ++struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name); ++void rwnx_wakeup_unregister(struct wakeup_source *ws); ++ ++void rwnx_wakeup_lock(struct wakeup_source *ws); ++void rwnx_wakeup_unlock(struct wakeup_source *ws); ++void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec); ++ ++void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw); ++void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c +new file mode 100644 +index 000000000000..f59409946e39 +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c +@@ -0,0 +1,137 @@ ++/** ++ * sdio_host.c ++ * ++ * SDIO host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#include "sdio_host.h" ++//#include "ipc_compat.h" ++#include "rwnx_tx.h" ++#include "rwnx_platform.h" ++#include "aicwf_debug.h" ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_sdio_host_init(struct sdio_host_env_tag *env, ++ void *cb, ++ void *shared_env_ptr, ++ void *pthis) ++{ ++ // Reset the environments ++ ++ // Reset the Host environment ++ memset(env, 0, sizeof(struct sdio_host_env_tag)); ++ // Save the pointer to the register base ++ env->pthis = pthis; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++volatile struct txdesc_host *aicwf_sdio_host_txdesc_get(struct sdio_host_env_tag *env, const int queue_idx) ++{ ++ // struct ipc_shared_env_tag *shared_env_ptr = env->shared; ++ volatile struct txdesc_host *txdesc_free = NULL; ++ uint32_t used_idx = env->txdesc_used_idx[queue_idx]; ++ uint32_t free_idx = env->txdesc_free_idx[queue_idx]; ++ ++ // ASSERT_ERR(queue_idx < SDIO_TXQUEUE_CNT); ++ // ASSERT_ERR((free_idx - used_idx) <= SDIO_TXDESC_CNT); ++ ++ // Check if a free descriptor is available ++ if (free_idx != (used_idx + SDIO_TXDESC_CNT)) { ++ // Get the pointer to the first free descriptor ++ // txdesc_free = shared_env_ptr->txdesc[queue_idx] + (free_idx % IPC_TXDESC_CNT); ++ } else { ++ txdesc_free = NULL; ++ } ++ ++ return txdesc_free; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_sdio_host_txdesc_push(struct sdio_host_env_tag *env, const int queue_idx, const uint64_t host_id) ++{ ++ //printk("push, %d, %d, 0x%llx \r\n", queue_idx, env->txdesc_free_idx[queue_idx], host_id); ++ // Save the host id in the environment ++ env->tx_host_id[queue_idx][env->txdesc_free_idx[queue_idx] % SDIO_TXDESC_CNT] = host_id; ++ ++ // Increment the index ++ env->txdesc_free_idx[queue_idx]++; ++ if (env->txdesc_free_idx[queue_idx] == 0x80000000) ++ env->txdesc_free_idx[queue_idx] = 0; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_sdio_host_tx_cfm_handler(struct sdio_host_env_tag *env, u32 *data) ++{ ++ u32 queue_idx = 0;// data[0]; ++ //struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)env->pthis; ++ struct sk_buff *skb = NULL; ++ struct rwnx_txhdr *txhdr; ++ ++ // TX confirmation descriptors have been received ++ // REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM); ++ //while (1) ++ { ++ // Get the used index and increase it. We do the increase before knowing if the ++ // current buffer is confirmed because the callback function may call the ++ // ipc_host_txdesc_get() in case flow control was enabled and the index has to be ++ // already at the good value to ensure that the test of FIFO full is correct ++ //uint32_t used_idx = env->txdesc_used_idx[queue_idx]++; ++ uint32_t used_idx = data[1]; ++ unsigned long host_id = env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT]; ++ ++ // Reset the host id in the array ++ env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = 0; ++ ++ // call the external function to indicate that a TX packet is freed ++ if (host_id == 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ AICWFDBG(LOGERROR, "ERROR:No more confirmations\r\n"); ++ //break; ++ } ++ // set the cfm status ++ skb = (struct sk_buff *)host_id; ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ txhdr->hw_hdr.cfm.status = (union rwnx_hw_txstatus)data[0]; ++ AICWFDBG(LOGINFO, "sdio_host_tx_cfm_handler:used_idx=%d, 0x%p, status=%x\r\n", used_idx, env->pthis, txhdr->hw_hdr.cfm.status.value); ++ //if (env->cb.send_data_cfm(env->pthis, host_id) != 0) ++ if (rwnx_txdatacfm(env->pthis, (void *)host_id) != 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = host_id; ++ // and exit the loop ++ AICWFDBG(LOGERROR, "ERROR:rwnx_txdatacfm,\r\n"); ++ // break; ++ } ++ } ++} ++ ++int aicwf_rwnx_sdio_platform_init(struct aic_sdio_dev *sdiodev) ++{ ++ struct rwnx_plat *rwnx_plat = NULL; ++ void *drvdata; ++ int ret = -ENODEV; ++ ++ rwnx_plat = kzalloc(sizeof(struct rwnx_plat), GFP_KERNEL); ++ ++ if (!rwnx_plat) { ++ return -ENOMEM; ++ } ++ ++ rwnx_plat->sdiodev = sdiodev; ++ ret = rwnx_platform_init(rwnx_plat, &drvdata); ++ ++ return ret; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h +new file mode 100644 +index 000000000000..670e9e08663d +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h +@@ -0,0 +1,41 @@ ++/** ++ * sdio_host.h ++ * ++ * SDIO host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#ifndef _SDIO_HOST_H_ ++#define _SDIO_HOST_H_ ++ ++#include "lmac_types.h" ++#include "aicwf_sdio.h" ++ ++#define SDIO_TXQUEUE_CNT NX_TXQ_CNT ++#define SDIO_TXDESC_CNT NX_TXDESC_CNT ++ ++ ++/// Definition of the IPC Host environment structure. ++struct sdio_host_env_tag { ++ // Index used that points to the first free TX desc ++ uint32_t txdesc_free_idx[SDIO_TXQUEUE_CNT]; ++ // Index used that points to the first used TX desc ++ uint32_t txdesc_used_idx[SDIO_TXQUEUE_CNT]; ++ // Array storing the currently pushed host ids, per IPC queue ++ uint64_t tx_host_id[SDIO_TXQUEUE_CNT][SDIO_TXDESC_CNT]; ++ ++ /// Pointer to the attached object (used in callbacks and register accesses) ++ void *pthis; ++}; ++ ++extern void aicwf_sdio_host_init(struct sdio_host_env_tag *env, ++ void *cb, void *shared_env_ptr, void *pthis); ++ ++extern void aicwf_sdio_host_txdesc_push(struct sdio_host_env_tag *env, const int queue_idx, const uint64_t host_id); ++ ++extern void aicwf_sdio_host_tx_cfm_handler(struct sdio_host_env_tag *env, u32 *data); ++extern int aicwf_rwnx_sdio_platform_init(struct aic_sdio_dev *sdiodev); ++ ++#endif +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c +new file mode 100644 +index 000000000000..c5c86d0de27b +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c +@@ -0,0 +1,146 @@ ++/** ++ * usb_host.c ++ * ++ * USB host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#include "usb_host.h" ++//#include "ipc_compat.h" ++#include "rwnx_tx.h" ++#include "rwnx_platform.h" ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_usb_host_init(struct usb_host_env_tag *env, ++ void *cb, ++ void *shared_env_ptr, ++ void *pthis) ++{ ++ // Reset the environments ++ ++ // Reset the Host environment ++ memset(env, 0, sizeof(struct usb_host_env_tag)); ++ //printk("[Gaofx]rwnx_init_aic pthis %p !\n", pthis); ++ // Save the pointer to the register base ++ env->pthis = pthis; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++volatile struct txdesc_host *aicwf_usb_host_txdesc_get(struct usb_host_env_tag *env, const int queue_idx) ++{ ++ // struct ipc_shared_env_tag *shared_env_ptr = env->shared; ++ volatile struct txdesc_host *txdesc_free = NULL; ++ uint32_t used_idx = env->txdesc_used_idx[queue_idx]; ++ uint32_t free_idx = env->txdesc_free_idx[queue_idx]; ++ ++ // ASSERT_ERR(queue_idx < SDIO_TXQUEUE_CNT); ++ // ASSERT_ERR((free_idx - used_idx) <= USB_TXDESC_CNT); ++ ++ // Check if a free descriptor is available ++ if (free_idx != (used_idx + USB_TXDESC_CNT)) { ++ // Get the pointer to the first free descriptor ++ // txdesc_free = shared_env_ptr->txdesc[queue_idx] + (free_idx % IPC_TXDESC_CNT); ++ } else { ++ txdesc_free = NULL; ++ } ++ ++ return txdesc_free; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_usb_host_txdesc_push(struct usb_host_env_tag *env, const int queue_idx, const uint64_t host_id) ++{ ++ //printk("push, %d, %d, 0x%llx \r\n", queue_idx, env->txdesc_free_idx[queue_idx], host_id); ++ // Save the host id in the environment ++ env->tx_host_id[queue_idx][env->txdesc_free_idx[queue_idx] % USB_TXDESC_CNT] = host_id; ++ ++ // Increment the index ++ env->txdesc_free_idx[queue_idx]++; ++ if (env->txdesc_free_idx[queue_idx] == 0x80000000) ++ env->txdesc_free_idx[queue_idx] = 0; ++} ++ ++/** ++ **************************************************************************************** ++ */ ++void aicwf_usb_host_tx_cfm_handler(struct usb_host_env_tag *env, u32 *data) ++{ ++ u32 queue_idx = 0;//data[0]; ++ //struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)env->pthis; ++ struct sk_buff *skb = NULL; ++ struct rwnx_txhdr *txhdr; ++ printk("%s enter \n", __func__); ++ //printk("sdio_host_tx_cfm_handler, %d, 0x%08x\r\n", queue_idx, data[1]); ++ // TX confirmation descriptors have been received ++ // REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM); ++ //while (1) ++ { ++ // Get the used index and increase it. We do the increase before knowing if the ++ // current buffer is confirmed because the callback function may call the ++ // ipc_host_txdesc_get() in case flow control was enabled and the index has to be ++ // already at the good value to ensure that the test of FIFO full is correct ++ //uint32_t used_idx = env->txdesc_used_idx[queue_idx]++; ++ uint32_t used_idx = data[1]; ++ uint64_t host_id = env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT]; ++ ++ // Reset the host id in the array ++ env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT] = 0; ++ ++ // call the external function to indicate that a TX packet is freed ++ if (host_id == 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ printk("ERROR:No more confirmations\r\n"); ++ return; ++ //break; ++ } ++ // set the cfm status ++ skb = (struct sk_buff *)(uint64_t)host_id; ++ txhdr = (struct rwnx_txhdr *)skb->data; ++ txhdr->hw_hdr.cfm.status = (union rwnx_hw_txstatus)data[0]; ++ //txhdr->hw_hdr.status = data[1]; ++ //printk("sdio_host_tx_cfm_handler, 0x%p\r\n", env->pthis); ++ //if (env->cb.send_data_cfm(env->pthis, host_id) != 0) ++ if (rwnx_txdatacfm(env->pthis, (void *)host_id) != 0) { ++ // No more confirmations, so put back the used index at its initial value ++ env->txdesc_used_idx[queue_idx] = used_idx; ++ env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT] = host_id; ++ // and exit the loop ++ printk("ERROR:rwnx_txdatacfm,\r\n"); ++ // break; ++ } ++ } ++} ++ ++int aicwf_rwnx_usb_platform_init(struct aic_usb_dev *usbdev) ++{ ++ struct rwnx_plat *rwnx_plat = NULL; ++ void *drvdata; ++ int ret = -ENODEV; ++ ++ rwnx_plat = kzalloc(sizeof(struct rwnx_plat), GFP_KERNEL); ++ ++ if (!rwnx_plat) ++ return -ENOMEM; ++ ++// rwnx_plat->pci_dev = pci_dev; ++ rwnx_plat->usbdev = usbdev; ++ ++ ret = rwnx_platform_init(rwnx_plat, &drvdata); ++#if 0 ++ pci_set_drvdata(pci_dev, drvdata); ++ ++ if (ret) ++ rwnx_plat->deinit(rwnx_plat); ++#endif ++ return ret; ++} ++ +diff --git a/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h +new file mode 100644 +index 000000000000..012b90c9770a +--- /dev/null ++++ b/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h +@@ -0,0 +1,41 @@ ++/** ++ * usb_host.h ++ * ++ * USB host function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++ ++ ++#ifndef _USB_HOST_H_ ++#define _USB_HOST_H_ ++ ++#include "lmac_types.h" ++#include "aicwf_usb.h" ++ ++#define USB_TXQUEUE_CNT NX_TXQ_CNT ++#define USB_TXDESC_CNT NX_TXDESC_CNT ++ ++ ++/// Definition of the IPC Host environment structure. ++struct usb_host_env_tag { ++ // Index used that points to the first free TX desc ++ uint32_t txdesc_free_idx[USB_TXQUEUE_CNT]; ++ // Index used that points to the first used TX desc ++ uint32_t txdesc_used_idx[USB_TXQUEUE_CNT]; ++ // Array storing the currently pushed host ids, per IPC queue ++ uint64_t tx_host_id[USB_TXQUEUE_CNT][USB_TXDESC_CNT]; ++ ++ /// Pointer to the attached object (used in callbacks and register accesses) ++ void *pthis; ++}; ++ ++extern void aicwf_usb_host_init(struct usb_host_env_tag *env, ++ void *cb, void *shared_env_ptr, void *pthis); ++ ++extern void aicwf_usb_host_txdesc_push(struct usb_host_env_tag *env, const int queue_idx, const uint64_t host_id); ++ ++extern void aicwf_usb_host_tx_cfm_handler(struct usb_host_env_tag *env, u32 *data); ++extern int aicwf_rwnx_usb_platform_init(struct aic_usb_dev *usbdev); ++ ++#endif From 76246b5fa70ccdf2f29d75cba02682b7ff94de90 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 22 Jul 2024 22:41:12 +0200 Subject: [PATCH 21/43] meson64: remove U-Boot boot order patch since it sometimes results in a boot loop, when aiming to boot from eMMC or SD card: https://github.com/MichaIng/DietPi/issues/7168, https://forum.armbian.com/topic/36141-usb-errors/ The attempt to boot from USB might be too fast, when trying it first, where some USB drives are not ready yet, resulting in an error. Signed-off-by: MichaIng --- .../meson64-boot-usb-nvme-scsi-first.patch | 26 -------------- .../meson64-boot-usb-nvme-scsi-first.patch | 33 ------------------ .../meson64-boot-usb-nvme-scsi-first.patch | 34 ------------------- .../meson64-boot-usb-nvme-scsi-first.patch | 34 ------------------- .../meson64-boot-usb-nvme-scsi-first.patch | 26 -------------- 5 files changed, 153 deletions(-) delete mode 100644 patch/u-boot/v2022.01/meson64-boot-usb-nvme-scsi-first.patch delete mode 100644 patch/u-boot/v2022.10/meson64-boot-usb-nvme-scsi-first.patch delete mode 100644 patch/u-boot/v2023.01/meson64-boot-usb-nvme-scsi-first.patch delete mode 100644 patch/u-boot/v2023.10/board_odroidn2l/meson64-boot-usb-nvme-scsi-first.patch delete mode 100644 patch/u-boot/v2026.04/board_odroidn2/meson64-boot-usb-nvme-scsi-first.patch diff --git a/patch/u-boot/v2022.01/meson64-boot-usb-nvme-scsi-first.patch b/patch/u-boot/v2022.01/meson64-boot-usb-nvme-scsi-first.patch deleted file mode 100644 index cec174d228df..000000000000 --- a/patch/u-boot/v2022.01/meson64-boot-usb-nvme-scsi-first.patch +++ /dev/null @@ -1,26 +0,0 @@ -Subject: [PATCH] meson64 boot stuff first ---- -Index: include/configs/meson64.h -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== -diff --git a/include/configs/meson64.h b/include/configs/meson64.h ---- a/include/configs/meson64.h (revision d637294e264adfeb29f390dfc393106fd4d41b17) -+++ b/include/configs/meson64.h (revision 53886e58a1b76a466bf6c8cb75e70dfefe97cd02) -@@ -71,12 +71,12 @@ - #ifndef BOOT_TARGET_DEVICES - #define BOOT_TARGET_DEVICES(func) \ - func(ROMUSB, romusb, na) \ -- func(MMC, mmc, 0) \ -- func(MMC, mmc, 1) \ -- func(MMC, mmc, 2) \ - BOOT_TARGET_DEVICES_USB(func) \ - BOOT_TARGET_NVME(func) \ - BOOT_TARGET_SCSI(func) \ -+ func(MMC, mmc, 0) \ -+ func(MMC, mmc, 1) \ -+ func(MMC, mmc, 2) \ - func(PXE, pxe, na) \ - func(DHCP, dhcp, na) - #endif diff --git a/patch/u-boot/v2022.10/meson64-boot-usb-nvme-scsi-first.patch b/patch/u-boot/v2022.10/meson64-boot-usb-nvme-scsi-first.patch deleted file mode 100644 index d7f8141477ff..000000000000 --- a/patch/u-boot/v2022.10/meson64-boot-usb-nvme-scsi-first.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ricardo Pardini -Date: Mon, 14 Nov 2022 14:59:45 +0100 -Subject: meson64 u-boot v2022.10: change `BOOT_TARGET_DEVICES to try to boot - USB, NVME and SCSI before SD, MMC, PXE, DHCP - ---- - include/configs/meson64.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/include/configs/meson64.h b/include/configs/meson64.h -index 40803ee9da1..af7b764da6a 100644 ---- a/include/configs/meson64.h -+++ b/include/configs/meson64.h -@@ -64,12 +64,12 @@ - #ifndef BOOT_TARGET_DEVICES - #define BOOT_TARGET_DEVICES(func) \ - func(ROMUSB, romusb, na) \ -- func(MMC, mmc, 0) \ -- func(MMC, mmc, 1) \ -- func(MMC, mmc, 2) \ - BOOT_TARGET_DEVICES_USB(func) \ - BOOT_TARGET_NVME(func) \ - BOOT_TARGET_SCSI(func) \ -+ func(MMC, mmc, 0) \ -+ func(MMC, mmc, 1) \ -+ func(MMC, mmc, 2) \ - func(PXE, pxe, na) \ - func(DHCP, dhcp, na) - #endif --- -Armbian - diff --git a/patch/u-boot/v2023.01/meson64-boot-usb-nvme-scsi-first.patch b/patch/u-boot/v2023.01/meson64-boot-usb-nvme-scsi-first.patch deleted file mode 100644 index 3ab90ba2cbfb..000000000000 --- a/patch/u-boot/v2023.01/meson64-boot-usb-nvme-scsi-first.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ricardo Pardini -Date: Mon, 14 Nov 2022 14:59:45 +0100 -Subject: meson64: change `BOOT_TARGET_DEVICES` to try to boot USB, NVME and - SCSI before SD, MMC, PXE, DHCP - -meson64: change `BOOT_TARGET_DEVICES` to try to boot USB, NVME and SCSI before SD, MMC, PXE, DHCP ---- - include/configs/meson64.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/include/configs/meson64.h b/include/configs/meson64.h -index 726f33c26c2a..d21899c335fb 100644 ---- a/include/configs/meson64.h -+++ b/include/configs/meson64.h -@@ -71,12 +71,12 @@ - #ifndef BOOT_TARGET_DEVICES - #define BOOT_TARGET_DEVICES(func) \ - func(ROMUSB, romusb, na) \ -- func(MMC, mmc, 0) \ -- func(MMC, mmc, 1) \ -- func(MMC, mmc, 2) \ - BOOT_TARGET_DEVICES_USB(func) \ - BOOT_TARGET_NVME(func) \ - BOOT_TARGET_SCSI(func) \ -+ func(MMC, mmc, 0) \ -+ func(MMC, mmc, 1) \ -+ func(MMC, mmc, 2) \ - func(PXE, pxe, na) \ - func(DHCP, dhcp, na) - #endif --- -Armbian - diff --git a/patch/u-boot/v2023.10/board_odroidn2l/meson64-boot-usb-nvme-scsi-first.patch b/patch/u-boot/v2023.10/board_odroidn2l/meson64-boot-usb-nvme-scsi-first.patch deleted file mode 100644 index 4676681e3201..000000000000 --- a/patch/u-boot/v2023.10/board_odroidn2l/meson64-boot-usb-nvme-scsi-first.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ricardo Pardini -Date: Mon, 14 Nov 2022 14:59:45 +0100 -Subject: meson64: change `BOOT_TARGET_DEVICES` to try to boot USB, NVME and - SCSI before SD, MMC, PXE, DHCP - -meson64: change `BOOT_TARGET_DEVICES` to try to boot USB, NVME and SCSI before SD, MMC, PXE, DHCP ---- - include/configs/meson64.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/include/configs/meson64.h b/include/configs/meson64.h -index 801cdae4708..927919ef17a 100644 ---- a/include/configs/meson64.h -+++ b/include/configs/meson64.h -@@ -74,12 +74,12 @@ - #ifndef BOOT_TARGET_DEVICES - #define BOOT_TARGET_DEVICES(func) \ - func(ROMUSB, romusb, na) \ -- func(MMC, mmc, 0) \ -- func(MMC, mmc, 1) \ -- func(MMC, mmc, 2) \ - BOOT_TARGET_DEVICES_USB(func) \ - BOOT_TARGET_NVME(func) \ - BOOT_TARGET_SCSI(func) \ -+ func(MMC, mmc, 0) \ -+ func(MMC, mmc, 1) \ -+ func(MMC, mmc, 2) \ - func(PXE, pxe, na) \ - func(DHCP, dhcp, na) - #endif --- -Armbian - diff --git a/patch/u-boot/v2026.04/board_odroidn2/meson64-boot-usb-nvme-scsi-first.patch b/patch/u-boot/v2026.04/board_odroidn2/meson64-boot-usb-nvme-scsi-first.patch deleted file mode 100644 index 29d315f7ab03..000000000000 --- a/patch/u-boot/v2026.04/board_odroidn2/meson64-boot-usb-nvme-scsi-first.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ricardo Pardini -Date: Mon, 14 Nov 2022 14:59:45 +0100 -Subject: meson64 u-boot v2022.10: change `BOOT_TARGET_DEVICES to try to boot - USB, NVME and SCSI before SD, MMC, PXE, DHCP - ---- - include/configs/meson64.h | 2 +- - 1 file changed, 1 insertions(+), 1 deletions(-) - -diff --git a/include/configs/meson64.h b/include/configs/meson64.h -index f3275b37a51..db27b6a6909 100644 ---- a/include/configs/meson64.h -+++ b/include/configs/meson64.h -@@ -119,10 +119,10 @@ - #define BOOT_TARGET_DEVICES(func) \ - func(ROMUSB, romusb, na) \ - func(USB_DFU, usbdfu, na) \ -- BOOT_TARGET_MMC(func) \ - BOOT_TARGET_DEVICES_USB(func) \ - BOOT_TARGET_NVME(func) \ - BOOT_TARGET_SCSI(func) \ -+ BOOT_TARGET_MMC(func) \ - BOOT_TARGET_PXE(func) \ - BOOT_TARGET_DHCP(func) - #endif From 9b7039ed7b12174c812030213ea58a0955269011 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 7 Jun 2025 17:49:59 +0200 Subject: [PATCH 22/43] nanopi-r6s: apply static MAC addresses for all 3 Ethernet adapters U-Boot assigns the variables eth(0)addr, eth1addr, eth2addr etc as MAC addresses to device tree aliases ethernet0, ethernet1, ethernet2 etc. For Rockchip SBCs, it generates only ethaddr and eth1addr so far. To support 3 static MAC addresses for the NanoPi R6S, it needs to generate eth2addr. This is archived with a U-Boot patch, to derive eth2addr the same way like eth1addr, but inverting the 2nd last bit instead. With a kernel patch, PCIe child nodes with the needed "local-mac-address" attributes are added to respective PCIe bridge nodes, and added as ethernet1 and ethernet2 aliases respectively. In sum: U-Boot additionally generates a valid eth2addr, and additionally assigns eth1addr and eth2addr to the now existing ethernet1 and ethernet2 aliases, pointing to the 2.5 Gbit Ethernet device nodes. Due to shared includes, this applies static MAC addresses for both NanoPi R6C adapters as well. This commit additionally fixes the default Ethernet LED triggers for NanoPi R6C and applies them for later Linux versions. Signed-off-by: MichaIng --- .../rockchip64-6.12/dt/rk3588s-nanopi-r6c.dts | 14 +- .../rockchip64-6.12/dt/rk3588s-nanopi-r6s.dts | 211 +++++++++--------- .../board-nanopi-r6-static-eth-mac.patch | 88 ++++++++ .../board-nanopi-r6-static-eth-mac.patch | 88 ++++++++ .../board-nanopi-r6s-static-lan2-mac.patch | 25 +++ .../board_nanopi-r6s/mac-ethernet2.patch | 15 ++ 6 files changed, 339 insertions(+), 102 deletions(-) create mode 100644 patch/kernel/archive/rockchip64-6.18/board-nanopi-r6-static-eth-mac.patch create mode 100644 patch/kernel/archive/rockchip64-7.0/board-nanopi-r6-static-eth-mac.patch create mode 100644 patch/kernel/rk35xx-vendor-6.1/board-nanopi-r6s-static-lan2-mac.patch create mode 100644 patch/u-boot/v2025.10/board_nanopi-r6s/mac-ethernet2.patch diff --git a/patch/kernel/archive/rockchip64-6.12/dt/rk3588s-nanopi-r6c.dts b/patch/kernel/archive/rockchip64-6.12/dt/rk3588s-nanopi-r6c.dts index 5c8b850efe75..8ab6afa49d9b 100644 --- a/patch/kernel/archive/rockchip64-6.12/dt/rk3588s-nanopi-r6c.dts +++ b/patch/kernel/archive/rockchip64-6.12/dt/rk3588s-nanopi-r6c.dts @@ -6,7 +6,19 @@ / { model = "FriendlyElec NanoPi R6C"; - compatible = "friendlyelec,nanopi-r6c", "rockchip,rk3588s"; + compatible = "friendlyarm,nanopi-r6c", "rockchip,rk3588s"; + + aliases { + /delete-property/ ethernet2; + }; +}; + +&wan_led { + linux,default-trigger = "stmmac-0:01:link"; +}; + +&lan1_led { + linux,default-trigger = "r8169-3-3100:00:link"; }; &lan2_led { diff --git a/patch/kernel/archive/rockchip64-6.12/dt/rk3588s-nanopi-r6s.dts b/patch/kernel/archive/rockchip64-6.12/dt/rk3588s-nanopi-r6s.dts index b39a3fc976b5..390e5c185b15 100644 --- a/patch/kernel/archive/rockchip64-6.12/dt/rk3588s-nanopi-r6s.dts +++ b/patch/kernel/archive/rockchip64-6.12/dt/rk3588s-nanopi-r6s.dts @@ -10,18 +10,58 @@ / { model = "FriendlyElec NanoPi R6S"; - compatible = "friendlyelec,nanopi-r6s", "rockchip,rk3588s"; + compatible = "friendlyarm,nanopi-r6s", "rockchip,rk3588s"; aliases { + ethernet0 = &gmac1; + ethernet1 = &r8125_u25; + ethernet2 = &r8125_u40; mmc0 = &sdmmc; mmc1 = &sdhci; - serial2 = &uart2; }; chosen { stdout-path = "serial2:1500000n8"; }; + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 0>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + button-maskrom { + label = "Maskrom"; + linux,code = ; + press-threshold-microvolt = <1800>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&key1_pin>; + + button-user { + label = "User"; + linux,code = ; + gpios = <&gpio1 RK_PC0 GPIO_ACTIVE_LOW>; + debounce-interval = <50>; + }; + }; + + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi0_out_con>; + }; + }; + }; + leds { compatible = "gpio-leds"; @@ -58,34 +98,6 @@ }; }; - adc-keys { - compatible = "adc-keys"; - io-channels = <&saradc 0>; - io-channel-names = "buttons"; - keyup-threshold-microvolt = <1800000>; - poll-interval = <100>; - - button-maskrom { - label = "Maskrom"; - linux,code = ; - press-threshold-microvolt = <1800>; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-names = "default"; - pinctrl-0 = <&key1_pin>; - - button-user { - label = "User"; - linux,code = ; - gpios = <&gpio1 RK_PC0 GPIO_ACTIVE_LOW>; - debounce-interval = <50>; - wakeup-source; - }; - }; - vcc5v0_sys: vcc5v0-sys-regulator { compatible = "regulator-fixed"; regulator-name = "vcc5v0_sys"; @@ -105,14 +117,24 @@ vin-supply = <&vcc5v0_sys>; }; + vcc_3v3_s0: vcc-3v3-s0-regulator { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_3v3_s0"; + vin-supply = <&vcc_3v3_s3>; + }; + vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { compatible = "regulator-fixed"; - regulator-name = "vcc_3v3_sd_s0"; enable-active-high; - regulator-boot-on; - gpio = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; + gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&sd_s0_pwr>; + regulator-name = "vcc_3v3_sd_s0"; + regulator-boot-on; regulator-max-microvolt = <3000000>; regulator-min-microvolt = <3000000>; vin-supply = <&vcc_3v3_s3>; @@ -140,11 +162,11 @@ vcc5v0_usb_otg0: vcc5v0-usb-otg0-regulator { compatible = "regulator-fixed"; - regulator-name = "vcc5v0_usb_otg0"; enable-active-high; - gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&typec5v_pwren>; + regulator-name = "vcc5v0_usb_otg0"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; vin-supply = <&vcc5v0_usb>; @@ -152,11 +174,11 @@ vcc5v0_host_20: vcc5v0-host-20-regulator { compatible = "regulator-fixed"; - regulator-name = "vcc5v0_host_20"; enable-active-high; - gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; + gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&vcc5v0_host20_en>; + regulator-name = "vcc5v0_host_20"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; vin-supply = <&vcc5v0_usb>; @@ -171,58 +193,50 @@ status = "okay"; }; -&gmac1 { - clock_in_out = "output"; - phy-handle = <&rgmii_phy1>; - phy-mode = "rgmii-rxid"; - pinctrl-0 = <&gmac1_miim - &gmac1_tx_bus2 - &gmac1_rx_bus2 - &gmac1_rgmii_clk - &gmac1_rgmii_bus>; - pinctrl-names = "default"; - tx_delay = <0x42>; - status = "okay"; -}; - &cpu_b0 { cpu-supply = <&vdd_cpu_big0_s0>; - mem-supply = <&vdd_cpu_big0_mem_s0>; }; &cpu_b1 { cpu-supply = <&vdd_cpu_big0_s0>; - mem-supply = <&vdd_cpu_big0_mem_s0>; }; &cpu_b2 { cpu-supply = <&vdd_cpu_big1_s0>; - mem-supply = <&vdd_cpu_big1_mem_s0>; }; &cpu_b3 { cpu-supply = <&vdd_cpu_big1_s0>; - mem-supply = <&vdd_cpu_big1_mem_s0>; }; &cpu_l0 { cpu-supply = <&vdd_cpu_lit_s0>; - mem-supply = <&vdd_cpu_lit_mem_s0>; }; &cpu_l1 { cpu-supply = <&vdd_cpu_lit_s0>; - mem-supply = <&vdd_cpu_lit_mem_s0>; }; &cpu_l2 { cpu-supply = <&vdd_cpu_lit_s0>; - mem-supply = <&vdd_cpu_lit_mem_s0>; }; &cpu_l3 { cpu-supply = <&vdd_cpu_lit_s0>; - mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&gmac1 { + clock_in_out = "output"; + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii-rxid"; + pinctrl-0 = <&gmac1_miim + &gmac1_tx_bus2 + &gmac1_rx_bus2 + &gmac1_rgmii_clk + &gmac1_rgmii_bus>; + pinctrl-names = "default"; + tx_delay = <0x42>; + status = "okay"; }; &gpu { @@ -230,12 +244,32 @@ status = "okay"; }; +&hdmi0 { + status = "okay"; +}; + +&hdmi0_in { + hdmi0_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi0>; + }; +}; + +&hdmi0_out { + hdmi0_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&hdptxphy_hdmi0 { + status = "okay"; +}; + &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c0m2_xfer>; status = "okay"; - vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: regulator@42 { + vdd_cpu_big0_s0: regulator@42 { compatible = "rockchip,rk8602"; reg = <0x42>; fcs,suspend-voltage-selector = <1>; @@ -252,7 +286,7 @@ }; }; - vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: regulator@43 { + vdd_cpu_big1_s0: regulator@43 { compatible = "rockchip,rk8603", "rockchip,rk8602"; reg = <0x43>; fcs,suspend-voltage-selector = <1>; @@ -273,11 +307,10 @@ &i2c2 { status = "okay"; - vdd_npu_s0: vdd_npu_mem_s0: rk8602@42 { + vdd_npu_s0: regulator@42 { compatible = "rockchip,rk8602"; reg = <0x42>; fcs,suspend-voltage-selector = <1>; - regulator-compatible = "rk860x-reg"; regulator-name = "vdd_npu_s0"; regulator-min-microvolt = <550000>; regulator-max-microvolt = <950000>; @@ -416,11 +449,6 @@ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; }; - /omit-if-no-ref/ - usbc0_int: usbc0-int { - rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; - }; - vcc5v0_host20_en: vcc5v0-host20-en { rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; }; @@ -443,9 +471,7 @@ no-sdio; no-sd; non-removable; - /* HS400 doesn't work properly -> https://github.com/torvalds/linux/commit/cee572756aa2cb46e959e9797ad4b730b78a050b */ mmc-hs200-1_8v; - max-frequency = <200000000>; status = "okay"; }; @@ -504,13 +530,13 @@ #gpio-cells = <2>; rk806_dvs1_null: dvs1-null-pins { - pins = "gpio_pwrctrl2"; + pins = "gpio_pwrctrl1"; function = "pin_fun0"; }; rk806_dvs2_null: dvs2-null-pins { pins = "gpio_pwrctrl2"; - function = "pin_fudr_moden0"; + function = "pin_fun0"; }; rk806_dvs3_null: dvs3-null-pins { @@ -564,7 +590,6 @@ regulator-boot-on; regulator-min-microvolt = <550000>; regulator-max-microvolt = <950000>; - regulator-init-microvolt = <750000>; regulator-ramp-delay = <12500>; regulator-name = "vdd_vdenc_s0"; @@ -685,13 +710,13 @@ }; }; - vcc_3v3_s0: pldo-reg4 { + avcc_3v3_s0: pldo-reg4 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-ramp-delay = <12500>; - regulator-name = "vcc_3v3_s0"; + regulator-name = "avcc_3v3_s0"; regulator-state-mem { regulator-off-in-suspend; @@ -737,12 +762,12 @@ }; }; - vdd_ddr_pll_s0: nldo-reg2 { + avdd_ddr_pll_s0: nldo-reg2 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <850000>; regulator-max-microvolt = <850000>; - regulator-name = "vdd_ddr_pll_s0"; + regulator-name = "avdd_ddr_pll_s0"; regulator-state-mem { regulator-off-in-suspend; @@ -762,12 +787,12 @@ }; }; - vdd_0v85_s0: nldo-reg4 { + avdd_0v85_s0: nldo-reg4 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <850000>; regulator-max-microvolt = <850000>; - regulator-name = "vdd_0v85_s0"; + regulator-name = "avdd_0v85_s0"; regulator-state-mem { regulator-off-in-suspend; @@ -789,11 +814,6 @@ }; }; -&uart2 { - pinctrl-0 = <&uart2m0_xfer>; - status = "okay"; -}; - &tsadc { status = "okay"; }; @@ -816,6 +836,11 @@ status = "okay"; }; +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + &usb_host0_ehci { status = "okay"; }; @@ -826,7 +851,6 @@ &usb_host0_xhci { dr_mode = "host"; - extcon = <&u2phy0>; status = "okay"; }; @@ -834,12 +858,7 @@ status = "okay"; }; -&hdmi0 { - status = "okay"; -}; - - -&hdptxphy_hdmi0 { +&vop { status = "okay"; }; @@ -847,16 +866,6 @@ status = "okay"; }; -&hdmi0_in { - hdmi0_in_vp0: endpoint { - remote-endpoint = <&vp0_out_hdmi0>; - }; -}; - -&vop { - status = "okay"; -}; - &vp0 { vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { reg = ; diff --git a/patch/kernel/archive/rockchip64-6.18/board-nanopi-r6-static-eth-mac.patch b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r6-static-eth-mac.patch new file mode 100644 index 000000000000..a53e0d1475e7 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/board-nanopi-r6-static-eth-mac.patch @@ -0,0 +1,88 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi +index fbf062ec3bf17..aea04d9abbce6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi +@@ -11,6 +11,7 @@ + / { + aliases { + ethernet0 = &gmac1; ++ ethernet1 = &r8125_u25; + mmc0 = &sdmmc; + mmc1 = &sdhci; + }; +@@ -351,6 +352,17 @@ &pcie2x1l1 { + reset-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie20>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0x00300000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ r8125_u25: pcie@30,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie2x1l2 { +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts +index ccc5e46275176..d461430f824dd 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts +@@ -9,6 +9,14 @@ / { + compatible = "friendlyarm,nanopi-r6c", "rockchip,rk3588s"; + }; + ++&wan_led { ++ linux,default-trigger = "stmmac-0:01:link"; ++}; ++ ++&lan1_led { ++ linux,default-trigger = "r8169-3-3100:00:link"; ++}; ++ + &lan2_led { + label = "user_led"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts +index 9c3e0b0daaacb..5ed1303549035 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts +@@ -7,8 +7,34 @@ + / { + model = "FriendlyElec NanoPi R6S"; + compatible = "friendlyarm,nanopi-r6s", "rockchip,rk3588s"; ++ ++ aliases { ++ ethernet2 = &r8125_u40; ++ }; ++}; ++ ++&wan_led { ++ linux,default-trigger = "r8169-3-3100:00:link"; ++}; ++ ++&lan1_led { ++ linux,default-trigger = "r8169-4-4100:00:link"; + }; + + &lan2_led { + label = "lan2_led"; ++ linux,default-trigger = "stmmac-0:01:link"; ++}; ++ ++&pcie2x1l2 { ++ pcie@0,0 { ++ reg = <0x00400000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ r8125_u40: pcie@40,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; diff --git a/patch/kernel/archive/rockchip64-7.0/board-nanopi-r6-static-eth-mac.patch b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r6-static-eth-mac.patch new file mode 100644 index 000000000000..a53e0d1475e7 --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/board-nanopi-r6-static-eth-mac.patch @@ -0,0 +1,88 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi +index fbf062ec3bf17..aea04d9abbce6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi +@@ -11,6 +11,7 @@ + / { + aliases { + ethernet0 = &gmac1; ++ ethernet1 = &r8125_u25; + mmc0 = &sdmmc; + mmc1 = &sdhci; + }; +@@ -351,6 +352,17 @@ &pcie2x1l1 { + reset-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie20>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0x00300000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ r8125_u25: pcie@30,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; + + &pcie2x1l2 { +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts +index ccc5e46275176..d461430f824dd 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts +@@ -9,6 +9,14 @@ / { + compatible = "friendlyarm,nanopi-r6c", "rockchip,rk3588s"; + }; + ++&wan_led { ++ linux,default-trigger = "stmmac-0:01:link"; ++}; ++ ++&lan1_led { ++ linux,default-trigger = "r8169-3-3100:00:link"; ++}; ++ + &lan2_led { + label = "user_led"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts +index 9c3e0b0daaacb..5ed1303549035 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts +@@ -7,8 +7,34 @@ + / { + model = "FriendlyElec NanoPi R6S"; + compatible = "friendlyarm,nanopi-r6s", "rockchip,rk3588s"; ++ ++ aliases { ++ ethernet2 = &r8125_u40; ++ }; ++}; ++ ++&wan_led { ++ linux,default-trigger = "r8169-3-3100:00:link"; ++}; ++ ++&lan1_led { ++ linux,default-trigger = "r8169-4-4100:00:link"; + }; + + &lan2_led { + label = "lan2_led"; ++ linux,default-trigger = "stmmac-0:01:link"; ++}; ++ ++&pcie2x1l2 { ++ pcie@0,0 { ++ reg = <0x00400000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ r8125_u40: pcie@40,0 { ++ reg = <0 0 0 0 0>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; + }; diff --git a/patch/kernel/rk35xx-vendor-6.1/board-nanopi-r6s-static-lan2-mac.patch b/patch/kernel/rk35xx-vendor-6.1/board-nanopi-r6s-static-lan2-mac.patch new file mode 100644 index 000000000000..cc09fd7722a0 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/board-nanopi-r6s-static-lan2-mac.patch @@ -0,0 +1,25 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts +index 269d33d359470..2ced053899e42 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts +@@ -15,7 +15,7 @@ / { + compatible = "friendlyelec,nanopi-r6c", "rockchip,rk3588"; + + aliases { +- ethernet0 = &r8125_u25; ++ /delete-property/ ethernet2; + }; + }; + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts +index 8b35c0b09d73d..376e60f8895e6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts +@@ -16,6 +16,7 @@ / { + + aliases { + ethernet0 = &r8125_u25; ++ ethernet2 = &r8125_u40; + }; + + gpio_keys: gpio-keys { diff --git a/patch/u-boot/v2025.10/board_nanopi-r6s/mac-ethernet2.patch b/patch/u-boot/v2025.10/board_nanopi-r6s/mac-ethernet2.patch new file mode 100644 index 000000000000..83e598d8f57d --- /dev/null +++ b/patch/u-boot/v2025.10/board_nanopi-r6s/mac-ethernet2.patch @@ -0,0 +1,15 @@ +diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c +index 7d03f0c2b67..4bb00d9a73a 100644 +--- a/arch/arm/mach-rockchip/board.c ++++ b/arch/arm/mach-rockchip/board.c +@@ -357,6 +357,10 @@ int rockchip_setup_macaddr(void) + /* Make a valid MAC address for ethernet1 */ + mac_addr[5] ^= 0x01; + eth_env_set_enetaddr("eth1addr", mac_addr); ++ ++ /* Make a valid MAC address for ethernet2 */ ++ mac_addr[5] ^= 0x03; ++ eth_env_set_enetaddr("eth2addr", mac_addr); + #endif + return 0; + } From 1036425152986748e12aa5a628dc97b87a466485 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 28 Apr 2025 20:10:28 +0200 Subject: [PATCH 23/43] orangepi3b: add support for PWM fan Signed-off-by: MichaIng --- .../board-orangepi3b-pwm-fan.patch | 36 +++++++++++++++++++ .../board-orangepi3b-pwm-fan.patch | 36 +++++++++++++++++++ .../board-orangepi3b-pwm-fan.patch | 36 +++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.12/board-orangepi3b-pwm-fan.patch create mode 100644 patch/kernel/archive/rockchip64-6.18/board-orangepi3b-pwm-fan.patch create mode 100644 patch/kernel/archive/rockchip64-7.0/board-orangepi3b-pwm-fan.patch diff --git a/patch/kernel/archive/rockchip64-6.12/board-orangepi3b-pwm-fan.patch b/patch/kernel/archive/rockchip64-6.12/board-orangepi3b-pwm-fan.patch new file mode 100644 index 000000000000..583c7c88d21c --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/board-orangepi3b-pwm-fan.patch @@ -0,0 +1,36 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi +index d539570f531e1..889cd57488bc4 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi +@@ -21,6 +21,20 @@ chosen { + stdout-path = "serial2:1500000n8"; + }; + ++ fan: pwm-fan { ++ compatible = "pwm-fan"; ++ #cooling-cells = <2>; ++ pwms = <&pwm7 0 50000 0>; ++ cooling-levels = <0 50 100 150 200 255>; ++ rockchip,temp-trips = < ++ 50000 1 ++ 55000 2 ++ 60000 3 ++ 65000 4 ++ 70000 5 ++ >; ++ }; ++ + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; +@@ -530,6 +544,10 @@ &pmu_io_domains { + status = "okay"; + }; + ++&pwm7 { ++ status = "okay"; ++}; ++ + &saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; diff --git a/patch/kernel/archive/rockchip64-6.18/board-orangepi3b-pwm-fan.patch b/patch/kernel/archive/rockchip64-6.18/board-orangepi3b-pwm-fan.patch new file mode 100644 index 000000000000..583c7c88d21c --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/board-orangepi3b-pwm-fan.patch @@ -0,0 +1,36 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi +index d539570f531e1..889cd57488bc4 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi +@@ -21,6 +21,20 @@ chosen { + stdout-path = "serial2:1500000n8"; + }; + ++ fan: pwm-fan { ++ compatible = "pwm-fan"; ++ #cooling-cells = <2>; ++ pwms = <&pwm7 0 50000 0>; ++ cooling-levels = <0 50 100 150 200 255>; ++ rockchip,temp-trips = < ++ 50000 1 ++ 55000 2 ++ 60000 3 ++ 65000 4 ++ 70000 5 ++ >; ++ }; ++ + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; +@@ -530,6 +544,10 @@ &pmu_io_domains { + status = "okay"; + }; + ++&pwm7 { ++ status = "okay"; ++}; ++ + &saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; diff --git a/patch/kernel/archive/rockchip64-7.0/board-orangepi3b-pwm-fan.patch b/patch/kernel/archive/rockchip64-7.0/board-orangepi3b-pwm-fan.patch new file mode 100644 index 000000000000..583c7c88d21c --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/board-orangepi3b-pwm-fan.patch @@ -0,0 +1,36 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi +index d539570f531e1..889cd57488bc4 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi +@@ -21,6 +21,20 @@ chosen { + stdout-path = "serial2:1500000n8"; + }; + ++ fan: pwm-fan { ++ compatible = "pwm-fan"; ++ #cooling-cells = <2>; ++ pwms = <&pwm7 0 50000 0>; ++ cooling-levels = <0 50 100 150 200 255>; ++ rockchip,temp-trips = < ++ 50000 1 ++ 55000 2 ++ 60000 3 ++ 65000 4 ++ 70000 5 ++ >; ++ }; ++ + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; +@@ -530,6 +544,10 @@ &pmu_io_domains { + status = "okay"; + }; + ++&pwm7 { ++ status = "okay"; ++}; ++ + &saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; From 9a8876b15a7972eb6c5ff7a91d44da4eadb68042 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 2 Nov 2025 16:48:13 +0100 Subject: [PATCH 24/43] rk3328: add overlays to toggle USB-C mode Signed-off-by: MichaIng --- patch/kernel/archive/rockchip64-6.12/overlay/Makefile | 3 +++ .../overlay/rockchip-rk3328-usb-c-host.dtso | 10 ++++++++++ .../overlay/rockchip-rk3328-usb-c-otg.dtso | 10 ++++++++++ .../overlay/rockchip-rk3328-usb-c-peripheral.dtso | 10 ++++++++++ patch/kernel/archive/rockchip64-6.18/overlay/Makefile | 3 +++ .../overlay/rockchip-rk3328-usb-c-host.dtso | 10 ++++++++++ .../overlay/rockchip-rk3328-usb-c-otg.dtso | 10 ++++++++++ .../overlay/rockchip-rk3328-usb-c-peripheral.dtso | 10 ++++++++++ patch/kernel/archive/rockchip64-7.0/overlay/Makefile | 3 +++ .../overlay/rockchip-rk3328-usb-c-host.dtso | 10 ++++++++++ .../overlay/rockchip-rk3328-usb-c-otg.dtso | 10 ++++++++++ .../overlay/rockchip-rk3328-usb-c-peripheral.dtso | 10 ++++++++++ 12 files changed, 99 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-host.dtso create mode 100644 patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-otg.dtso create mode 100644 patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-peripheral.dtso create mode 100644 patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-host.dtso create mode 100644 patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-otg.dtso create mode 100644 patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-peripheral.dtso create mode 100644 patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-host.dtso create mode 100644 patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-otg.dtso create mode 100644 patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-peripheral.dtso diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/Makefile b/patch/kernel/archive/rockchip64-6.12/overlay/Makefile index a0f92f182209..9c5f0c4f8da6 100644 --- a/patch/kernel/archive/rockchip64-6.12/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-6.12/overlay/Makefile @@ -33,6 +33,9 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ rockchip-rk3328-opp-1.5ghz.dtbo \ rockchip-rk3328-spi-spidev.dtbo \ rockchip-rk3328-uart1.dtbo \ + rockchip-rk3328-usb-c-host.dtbo \ + rockchip-rk3328-usb-c-otg.dtbo \ + rockchip-rk3328-usb-c-peripheral.dtbo \ rockchip-rk3399-dwc3-0-host.dtbo \ rockchip-rk3399-i2c7.dtbo \ rockchip-rk3399-i2c8.dtbo \ diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-host.dtso b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-host.dtso new file mode 100644 index 000000000000..b483737af69b --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-host.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "host"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-otg.dtso b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-otg.dtso new file mode 100644 index 000000000000..a8a264a53c46 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-otg.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "otg"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-peripheral.dtso b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-peripheral.dtso new file mode 100644 index 000000000000..8544110ac803 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3328-usb-c-peripheral.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "peripheral"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/Makefile b/patch/kernel/archive/rockchip64-6.18/overlay/Makefile index b6e1105266d0..6d21eb429f6f 100644 --- a/patch/kernel/archive/rockchip64-6.18/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-6.18/overlay/Makefile @@ -34,6 +34,9 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ rockchip-rk3328-opp-1.5ghz.dtbo \ rockchip-rk3328-spi-spidev.dtbo \ rockchip-rk3328-uart1.dtbo \ + rockchip-rk3328-usb-c-host.dtbo \ + rockchip-rk3328-usb-c-otg.dtbo \ + rockchip-rk3328-usb-c-peripheral.dtbo \ rockchip-rk3399-dwc3-0-host.dtbo \ rockchip-rk3399-i2c7.dtbo \ rockchip-rk3399-i2c8.dtbo \ diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-host.dtso b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-host.dtso new file mode 100644 index 000000000000..b483737af69b --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-host.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "host"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-otg.dtso b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-otg.dtso new file mode 100644 index 000000000000..a8a264a53c46 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-otg.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "otg"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-peripheral.dtso b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-peripheral.dtso new file mode 100644 index 000000000000..8544110ac803 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3328-usb-c-peripheral.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "peripheral"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/Makefile b/patch/kernel/archive/rockchip64-7.0/overlay/Makefile index b6e1105266d0..6d21eb429f6f 100644 --- a/patch/kernel/archive/rockchip64-7.0/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-7.0/overlay/Makefile @@ -34,6 +34,9 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ rockchip-rk3328-opp-1.5ghz.dtbo \ rockchip-rk3328-spi-spidev.dtbo \ rockchip-rk3328-uart1.dtbo \ + rockchip-rk3328-usb-c-host.dtbo \ + rockchip-rk3328-usb-c-otg.dtbo \ + rockchip-rk3328-usb-c-peripheral.dtbo \ rockchip-rk3399-dwc3-0-host.dtbo \ rockchip-rk3399-i2c7.dtbo \ rockchip-rk3399-i2c8.dtbo \ diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-host.dtso b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-host.dtso new file mode 100644 index 000000000000..b483737af69b --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-host.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "host"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-otg.dtso b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-otg.dtso new file mode 100644 index 000000000000..a8a264a53c46 --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-otg.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "otg"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-peripheral.dtso b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-peripheral.dtso new file mode 100644 index 000000000000..8544110ac803 --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3328-usb-c-peripheral.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "peripheral"; + }; + }; +}; From 2a1074bc186574cbe288897665e1aab134c025b4 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 28 May 2025 19:19:11 +0200 Subject: [PATCH 25/43] rk3399: revert raised CPU temperature trip points MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seriously, while the chip might live long enough at 85 °C - 100 °C, it is also about the temperature sourrounding components, peripherals and in case passive cooling cases get. I do not want to fry eggs on my NanoPi R4S case, which is directly connected to the SoC as passive cooler. Revert to upstream Linux values, which can always be overridden via board device tree or overlay. Signed-off-by: MichaIng --- .../rk3399-unlock-temperature.patch | 127 ------------------ .../rk3399-unlock-temperature.patch | 127 ------------------ .../rk3399-unlock-temperature.patch | 127 ------------------ 3 files changed, 381 deletions(-) delete mode 100644 patch/kernel/archive/rockchip64-6.12/rk3399-unlock-temperature.patch delete mode 100644 patch/kernel/archive/rockchip64-6.18/rk3399-unlock-temperature.patch delete mode 100644 patch/kernel/archive/rockchip64-7.0/rk3399-unlock-temperature.patch diff --git a/patch/kernel/archive/rockchip64-6.12/rk3399-unlock-temperature.patch b/patch/kernel/archive/rockchip64-6.12/rk3399-unlock-temperature.patch deleted file mode 100644 index 989d2b7cffe3..000000000000 --- a/patch/kernel/archive/rockchip64-6.12/rk3399-unlock-temperature.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ThomasKaiser -Date: Sat, 13 Oct 2018 16:35:07 +0200 -Subject: [ARCHEOLOGY] Increase performance with rk3399-dev - -> X-Git-Archeology: - Revision b28fa47aa8b9864ccae8b90ebb3d46ae55103d6e: https://github.com/armbian/build/commit/b28fa47aa8b9864ccae8b90ebb3d46ae55103d6e -> X-Git-Archeology: Date: Sat, 13 Oct 2018 16:35:07 +0200 -> X-Git-Archeology: From: ThomasKaiser -> X-Git-Archeology: Subject: Increase performance with rk3399-dev -> X-Git-Archeology: -> X-Git-Archeology: - Revision f18360d1ef5d6487392ff4079301bca97945e704: https://github.com/armbian/build/commit/f18360d1ef5d6487392ff4079301bca97945e704 -> X-Git-Archeology: Date: Wed, 24 Oct 2018 17:03:35 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: [rk3399-dev] Merging rk3399-DEV with rockchip64-DEV on sources, patches and config level. Leave family intact, add 1.5 OPP for RK3328, add upstream patch for rk3399-default -> X-Git-Archeology: -> X-Git-Archeology: - Revision 150ac0c2afa147d9e3b036c8ecd8238fe5648cf3: https://github.com/armbian/build/commit/150ac0c2afa147d9e3b036c8ecd8238fe5648cf3 -> X-Git-Archeology: Date: Tue, 19 Nov 2019 23:25:39 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Remove K<4, change branches, new features (#1586) -> X-Git-Archeology: -> X-Git-Archeology: - Revision dfd5cf9692e97774f7f0bfd72227144e36f58070: https://github.com/armbian/build/commit/dfd5cf9692e97774f7f0bfd72227144e36f58070 -> X-Git-Archeology: Date: Sun, 13 Dec 2020 22:13:03 -0500 -> X-Git-Archeology: From: tonymac32 -> X-Git-Archeology: Subject: [ rockchip64 ] Clean up patchset -> X-Git-Archeology: -> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 -> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) -> X-Git-Archeology: -> X-Git-Archeology: - Revision e7377248b3cae186e24e2be781cd3365b43246f0: https://github.com/armbian/build/commit/e7377248b3cae186e24e2be781cd3365b43246f0 -> X-Git-Archeology: Date: Thu, 22 Jul 2021 00:15:54 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Second part of EDGE bumping to 5.13.y (#3045) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 744ea89a589d62cb6f409baab60fc6664520bc39: https://github.com/armbian/build/commit/744ea89a589d62cb6f409baab60fc6664520bc39 -> X-Git-Archeology: Date: Wed, 08 Sep 2021 17:51:34 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bumping EDGE kernel to 5.14.y (#3125) -> X-Git-Archeology: -> X-Git-Archeology: - Revision dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e: https://github.com/armbian/build/commit/dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e -> X-Git-Archeology: Date: Tue, 09 Nov 2021 18:06:34 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump imx6, xu4, rockchip64 and jetson-nano to 5.15 (#3238) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 6b490e16944b30ff69bf9c13678905187df0d9d4: https://github.com/armbian/build/commit/6b490e16944b30ff69bf9c13678905187df0d9d4 -> X-Git-Archeology: Date: Tue, 11 Jan 2022 15:26:11 +0100 -> X-Git-Archeology: From: Oleg -> X-Git-Archeology: Subject: move kernel edge to 5.16 (#3387) -> X-Git-Archeology: -> X-Git-Archeology: - Revision ac8fc4385594d59257ee9dffd9efa85e3497fa7d: https://github.com/armbian/build/commit/ac8fc4385594d59257ee9dffd9efa85e3497fa7d -> X-Git-Archeology: Date: Sat, 26 Feb 2022 07:46:44 +0100 -> X-Git-Archeology: From: Piotr Szczepanik -> X-Git-Archeology: Subject: Switch rockchip64 current to linux 5.15.y (#3489) -> X-Git-Archeology: -> X-Git-Archeology: - Revision f52a4193d02ef88333ba117c68d49486dfd7ff41: https://github.com/armbian/build/commit/f52a4193d02ef88333ba117c68d49486dfd7ff41 -> X-Git-Archeology: Date: Sun, 20 Mar 2022 22:58:21 +0100 -> X-Git-Archeology: From: Oleg -> X-Git-Archeology: Subject: Adding Pine64 Quartz64a as WIP target (#3539) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 0afe24c95729044910e0b3f84dc5500bcdc6524c: https://github.com/armbian/build/commit/0afe24c95729044910e0b3f84dc5500bcdc6524c -> X-Git-Archeology: Date: Sun, 24 Apr 2022 22:33:47 +0200 -> X-Git-Archeology: From: Oleg -> X-Git-Archeology: Subject: move kernel media edge to 5.17 (#3704) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 897674aa74bce0326ed7fe06f5336bf4709a8a1f: https://github.com/armbian/build/commit/897674aa74bce0326ed7fe06f5336bf4709a8a1f -> X-Git-Archeology: Date: Tue, 03 May 2022 08:27:32 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump and freeze kernel at last known working versions (#3736) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 597d2dac11f00d9070a4e49d6bad1b2244e36cb3: https://github.com/armbian/build/commit/597d2dac11f00d9070a4e49d6bad1b2244e36cb3 -> X-Git-Archeology: Date: Sat, 28 May 2022 07:56:22 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64-edge to 5.18 (#3814) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 8c6641e7b79f0d50acdc306d140e586a4e923cf0: https://github.com/armbian/build/commit/8c6641e7b79f0d50acdc306d140e586a4e923cf0 -> X-Git-Archeology: Date: Wed, 03 Aug 2022 22:22:55 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64 edge to 5.19 (#4039) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 6765f734cc4a22aeaa9f99a3ad28c8c322de26f6: https://github.com/armbian/build/commit/6765f734cc4a22aeaa9f99a3ad28c8c322de26f6 -> X-Git-Archeology: Date: Tue, 25 Oct 2022 11:26:51 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump rockchip64 edge to 6.0.y (#4337) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 92f1a22d76b987afa7ba555d5b509adc51d689e7: https://github.com/armbian/build/commit/92f1a22d76b987afa7ba555d5b509adc51d689e7 -> X-Git-Archeology: Date: Fri, 16 Dec 2022 13:38:13 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Re-add rockchip64 6.0 patches (#4575) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 34ae84fac5d0b66a1ab2d1e51534b7beb13ef245: https://github.com/armbian/build/commit/34ae84fac5d0b66a1ab2d1e51534b7beb13ef245 -> X-Git-Archeology: Date: Fri, 05 May 2023 14:22:00 +0200 -> X-Git-Archeology: From: amazingfate -> X-Git-Archeology: Subject: bump rockchip64 edge to v6.3 -> X-Git-Archeology: ---- - arch/arm64/boot/dts/rockchip/rk3399-base.dtsi | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi -index 111111111111..222222222222 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi -@@ -928,17 +928,17 @@ cpu_thermal: cpu-thermal { - - trips { - cpu_alert0: cpu_alert0 { -- temperature = <70000>; -+ temperature = <85000>; - hysteresis = <2000>; - type = "passive"; - }; - cpu_alert1: cpu_alert1 { -- temperature = <75000>; -+ temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - cpu_crit: cpu_crit { -- temperature = <95000>; -+ temperature = <100000>; - hysteresis = <2000>; - type = "critical"; - }; --- -Armbian - diff --git a/patch/kernel/archive/rockchip64-6.18/rk3399-unlock-temperature.patch b/patch/kernel/archive/rockchip64-6.18/rk3399-unlock-temperature.patch deleted file mode 100644 index 989d2b7cffe3..000000000000 --- a/patch/kernel/archive/rockchip64-6.18/rk3399-unlock-temperature.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ThomasKaiser -Date: Sat, 13 Oct 2018 16:35:07 +0200 -Subject: [ARCHEOLOGY] Increase performance with rk3399-dev - -> X-Git-Archeology: - Revision b28fa47aa8b9864ccae8b90ebb3d46ae55103d6e: https://github.com/armbian/build/commit/b28fa47aa8b9864ccae8b90ebb3d46ae55103d6e -> X-Git-Archeology: Date: Sat, 13 Oct 2018 16:35:07 +0200 -> X-Git-Archeology: From: ThomasKaiser -> X-Git-Archeology: Subject: Increase performance with rk3399-dev -> X-Git-Archeology: -> X-Git-Archeology: - Revision f18360d1ef5d6487392ff4079301bca97945e704: https://github.com/armbian/build/commit/f18360d1ef5d6487392ff4079301bca97945e704 -> X-Git-Archeology: Date: Wed, 24 Oct 2018 17:03:35 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: [rk3399-dev] Merging rk3399-DEV with rockchip64-DEV on sources, patches and config level. Leave family intact, add 1.5 OPP for RK3328, add upstream patch for rk3399-default -> X-Git-Archeology: -> X-Git-Archeology: - Revision 150ac0c2afa147d9e3b036c8ecd8238fe5648cf3: https://github.com/armbian/build/commit/150ac0c2afa147d9e3b036c8ecd8238fe5648cf3 -> X-Git-Archeology: Date: Tue, 19 Nov 2019 23:25:39 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Remove K<4, change branches, new features (#1586) -> X-Git-Archeology: -> X-Git-Archeology: - Revision dfd5cf9692e97774f7f0bfd72227144e36f58070: https://github.com/armbian/build/commit/dfd5cf9692e97774f7f0bfd72227144e36f58070 -> X-Git-Archeology: Date: Sun, 13 Dec 2020 22:13:03 -0500 -> X-Git-Archeology: From: tonymac32 -> X-Git-Archeology: Subject: [ rockchip64 ] Clean up patchset -> X-Git-Archeology: -> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 -> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) -> X-Git-Archeology: -> X-Git-Archeology: - Revision e7377248b3cae186e24e2be781cd3365b43246f0: https://github.com/armbian/build/commit/e7377248b3cae186e24e2be781cd3365b43246f0 -> X-Git-Archeology: Date: Thu, 22 Jul 2021 00:15:54 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Second part of EDGE bumping to 5.13.y (#3045) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 744ea89a589d62cb6f409baab60fc6664520bc39: https://github.com/armbian/build/commit/744ea89a589d62cb6f409baab60fc6664520bc39 -> X-Git-Archeology: Date: Wed, 08 Sep 2021 17:51:34 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bumping EDGE kernel to 5.14.y (#3125) -> X-Git-Archeology: -> X-Git-Archeology: - Revision dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e: https://github.com/armbian/build/commit/dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e -> X-Git-Archeology: Date: Tue, 09 Nov 2021 18:06:34 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump imx6, xu4, rockchip64 and jetson-nano to 5.15 (#3238) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 6b490e16944b30ff69bf9c13678905187df0d9d4: https://github.com/armbian/build/commit/6b490e16944b30ff69bf9c13678905187df0d9d4 -> X-Git-Archeology: Date: Tue, 11 Jan 2022 15:26:11 +0100 -> X-Git-Archeology: From: Oleg -> X-Git-Archeology: Subject: move kernel edge to 5.16 (#3387) -> X-Git-Archeology: -> X-Git-Archeology: - Revision ac8fc4385594d59257ee9dffd9efa85e3497fa7d: https://github.com/armbian/build/commit/ac8fc4385594d59257ee9dffd9efa85e3497fa7d -> X-Git-Archeology: Date: Sat, 26 Feb 2022 07:46:44 +0100 -> X-Git-Archeology: From: Piotr Szczepanik -> X-Git-Archeology: Subject: Switch rockchip64 current to linux 5.15.y (#3489) -> X-Git-Archeology: -> X-Git-Archeology: - Revision f52a4193d02ef88333ba117c68d49486dfd7ff41: https://github.com/armbian/build/commit/f52a4193d02ef88333ba117c68d49486dfd7ff41 -> X-Git-Archeology: Date: Sun, 20 Mar 2022 22:58:21 +0100 -> X-Git-Archeology: From: Oleg -> X-Git-Archeology: Subject: Adding Pine64 Quartz64a as WIP target (#3539) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 0afe24c95729044910e0b3f84dc5500bcdc6524c: https://github.com/armbian/build/commit/0afe24c95729044910e0b3f84dc5500bcdc6524c -> X-Git-Archeology: Date: Sun, 24 Apr 2022 22:33:47 +0200 -> X-Git-Archeology: From: Oleg -> X-Git-Archeology: Subject: move kernel media edge to 5.17 (#3704) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 897674aa74bce0326ed7fe06f5336bf4709a8a1f: https://github.com/armbian/build/commit/897674aa74bce0326ed7fe06f5336bf4709a8a1f -> X-Git-Archeology: Date: Tue, 03 May 2022 08:27:32 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump and freeze kernel at last known working versions (#3736) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 597d2dac11f00d9070a4e49d6bad1b2244e36cb3: https://github.com/armbian/build/commit/597d2dac11f00d9070a4e49d6bad1b2244e36cb3 -> X-Git-Archeology: Date: Sat, 28 May 2022 07:56:22 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64-edge to 5.18 (#3814) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 8c6641e7b79f0d50acdc306d140e586a4e923cf0: https://github.com/armbian/build/commit/8c6641e7b79f0d50acdc306d140e586a4e923cf0 -> X-Git-Archeology: Date: Wed, 03 Aug 2022 22:22:55 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64 edge to 5.19 (#4039) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 6765f734cc4a22aeaa9f99a3ad28c8c322de26f6: https://github.com/armbian/build/commit/6765f734cc4a22aeaa9f99a3ad28c8c322de26f6 -> X-Git-Archeology: Date: Tue, 25 Oct 2022 11:26:51 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump rockchip64 edge to 6.0.y (#4337) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 92f1a22d76b987afa7ba555d5b509adc51d689e7: https://github.com/armbian/build/commit/92f1a22d76b987afa7ba555d5b509adc51d689e7 -> X-Git-Archeology: Date: Fri, 16 Dec 2022 13:38:13 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Re-add rockchip64 6.0 patches (#4575) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 34ae84fac5d0b66a1ab2d1e51534b7beb13ef245: https://github.com/armbian/build/commit/34ae84fac5d0b66a1ab2d1e51534b7beb13ef245 -> X-Git-Archeology: Date: Fri, 05 May 2023 14:22:00 +0200 -> X-Git-Archeology: From: amazingfate -> X-Git-Archeology: Subject: bump rockchip64 edge to v6.3 -> X-Git-Archeology: ---- - arch/arm64/boot/dts/rockchip/rk3399-base.dtsi | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi -index 111111111111..222222222222 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi -@@ -928,17 +928,17 @@ cpu_thermal: cpu-thermal { - - trips { - cpu_alert0: cpu_alert0 { -- temperature = <70000>; -+ temperature = <85000>; - hysteresis = <2000>; - type = "passive"; - }; - cpu_alert1: cpu_alert1 { -- temperature = <75000>; -+ temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - cpu_crit: cpu_crit { -- temperature = <95000>; -+ temperature = <100000>; - hysteresis = <2000>; - type = "critical"; - }; --- -Armbian - diff --git a/patch/kernel/archive/rockchip64-7.0/rk3399-unlock-temperature.patch b/patch/kernel/archive/rockchip64-7.0/rk3399-unlock-temperature.patch deleted file mode 100644 index 989d2b7cffe3..000000000000 --- a/patch/kernel/archive/rockchip64-7.0/rk3399-unlock-temperature.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ThomasKaiser -Date: Sat, 13 Oct 2018 16:35:07 +0200 -Subject: [ARCHEOLOGY] Increase performance with rk3399-dev - -> X-Git-Archeology: - Revision b28fa47aa8b9864ccae8b90ebb3d46ae55103d6e: https://github.com/armbian/build/commit/b28fa47aa8b9864ccae8b90ebb3d46ae55103d6e -> X-Git-Archeology: Date: Sat, 13 Oct 2018 16:35:07 +0200 -> X-Git-Archeology: From: ThomasKaiser -> X-Git-Archeology: Subject: Increase performance with rk3399-dev -> X-Git-Archeology: -> X-Git-Archeology: - Revision f18360d1ef5d6487392ff4079301bca97945e704: https://github.com/armbian/build/commit/f18360d1ef5d6487392ff4079301bca97945e704 -> X-Git-Archeology: Date: Wed, 24 Oct 2018 17:03:35 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: [rk3399-dev] Merging rk3399-DEV with rockchip64-DEV on sources, patches and config level. Leave family intact, add 1.5 OPP for RK3328, add upstream patch for rk3399-default -> X-Git-Archeology: -> X-Git-Archeology: - Revision 150ac0c2afa147d9e3b036c8ecd8238fe5648cf3: https://github.com/armbian/build/commit/150ac0c2afa147d9e3b036c8ecd8238fe5648cf3 -> X-Git-Archeology: Date: Tue, 19 Nov 2019 23:25:39 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Remove K<4, change branches, new features (#1586) -> X-Git-Archeology: -> X-Git-Archeology: - Revision dfd5cf9692e97774f7f0bfd72227144e36f58070: https://github.com/armbian/build/commit/dfd5cf9692e97774f7f0bfd72227144e36f58070 -> X-Git-Archeology: Date: Sun, 13 Dec 2020 22:13:03 -0500 -> X-Git-Archeology: From: tonymac32 -> X-Git-Archeology: Subject: [ rockchip64 ] Clean up patchset -> X-Git-Archeology: -> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 -> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) -> X-Git-Archeology: -> X-Git-Archeology: - Revision e7377248b3cae186e24e2be781cd3365b43246f0: https://github.com/armbian/build/commit/e7377248b3cae186e24e2be781cd3365b43246f0 -> X-Git-Archeology: Date: Thu, 22 Jul 2021 00:15:54 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Second part of EDGE bumping to 5.13.y (#3045) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 744ea89a589d62cb6f409baab60fc6664520bc39: https://github.com/armbian/build/commit/744ea89a589d62cb6f409baab60fc6664520bc39 -> X-Git-Archeology: Date: Wed, 08 Sep 2021 17:51:34 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bumping EDGE kernel to 5.14.y (#3125) -> X-Git-Archeology: -> X-Git-Archeology: - Revision dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e: https://github.com/armbian/build/commit/dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e -> X-Git-Archeology: Date: Tue, 09 Nov 2021 18:06:34 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump imx6, xu4, rockchip64 and jetson-nano to 5.15 (#3238) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 6b490e16944b30ff69bf9c13678905187df0d9d4: https://github.com/armbian/build/commit/6b490e16944b30ff69bf9c13678905187df0d9d4 -> X-Git-Archeology: Date: Tue, 11 Jan 2022 15:26:11 +0100 -> X-Git-Archeology: From: Oleg -> X-Git-Archeology: Subject: move kernel edge to 5.16 (#3387) -> X-Git-Archeology: -> X-Git-Archeology: - Revision ac8fc4385594d59257ee9dffd9efa85e3497fa7d: https://github.com/armbian/build/commit/ac8fc4385594d59257ee9dffd9efa85e3497fa7d -> X-Git-Archeology: Date: Sat, 26 Feb 2022 07:46:44 +0100 -> X-Git-Archeology: From: Piotr Szczepanik -> X-Git-Archeology: Subject: Switch rockchip64 current to linux 5.15.y (#3489) -> X-Git-Archeology: -> X-Git-Archeology: - Revision f52a4193d02ef88333ba117c68d49486dfd7ff41: https://github.com/armbian/build/commit/f52a4193d02ef88333ba117c68d49486dfd7ff41 -> X-Git-Archeology: Date: Sun, 20 Mar 2022 22:58:21 +0100 -> X-Git-Archeology: From: Oleg -> X-Git-Archeology: Subject: Adding Pine64 Quartz64a as WIP target (#3539) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 0afe24c95729044910e0b3f84dc5500bcdc6524c: https://github.com/armbian/build/commit/0afe24c95729044910e0b3f84dc5500bcdc6524c -> X-Git-Archeology: Date: Sun, 24 Apr 2022 22:33:47 +0200 -> X-Git-Archeology: From: Oleg -> X-Git-Archeology: Subject: move kernel media edge to 5.17 (#3704) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 897674aa74bce0326ed7fe06f5336bf4709a8a1f: https://github.com/armbian/build/commit/897674aa74bce0326ed7fe06f5336bf4709a8a1f -> X-Git-Archeology: Date: Tue, 03 May 2022 08:27:32 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump and freeze kernel at last known working versions (#3736) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 597d2dac11f00d9070a4e49d6bad1b2244e36cb3: https://github.com/armbian/build/commit/597d2dac11f00d9070a4e49d6bad1b2244e36cb3 -> X-Git-Archeology: Date: Sat, 28 May 2022 07:56:22 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64-edge to 5.18 (#3814) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 8c6641e7b79f0d50acdc306d140e586a4e923cf0: https://github.com/armbian/build/commit/8c6641e7b79f0d50acdc306d140e586a4e923cf0 -> X-Git-Archeology: Date: Wed, 03 Aug 2022 22:22:55 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64 edge to 5.19 (#4039) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 6765f734cc4a22aeaa9f99a3ad28c8c322de26f6: https://github.com/armbian/build/commit/6765f734cc4a22aeaa9f99a3ad28c8c322de26f6 -> X-Git-Archeology: Date: Tue, 25 Oct 2022 11:26:51 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump rockchip64 edge to 6.0.y (#4337) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 92f1a22d76b987afa7ba555d5b509adc51d689e7: https://github.com/armbian/build/commit/92f1a22d76b987afa7ba555d5b509adc51d689e7 -> X-Git-Archeology: Date: Fri, 16 Dec 2022 13:38:13 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Re-add rockchip64 6.0 patches (#4575) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 34ae84fac5d0b66a1ab2d1e51534b7beb13ef245: https://github.com/armbian/build/commit/34ae84fac5d0b66a1ab2d1e51534b7beb13ef245 -> X-Git-Archeology: Date: Fri, 05 May 2023 14:22:00 +0200 -> X-Git-Archeology: From: amazingfate -> X-Git-Archeology: Subject: bump rockchip64 edge to v6.3 -> X-Git-Archeology: ---- - arch/arm64/boot/dts/rockchip/rk3399-base.dtsi | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi -index 111111111111..222222222222 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi -@@ -928,17 +928,17 @@ cpu_thermal: cpu-thermal { - - trips { - cpu_alert0: cpu_alert0 { -- temperature = <70000>; -+ temperature = <85000>; - hysteresis = <2000>; - type = "passive"; - }; - cpu_alert1: cpu_alert1 { -- temperature = <75000>; -+ temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - cpu_crit: cpu_crit { -- temperature = <95000>; -+ temperature = <100000>; - hysteresis = <2000>; - type = "critical"; - }; --- -Armbian - From dd18bd2ec7f8314c4e5a48922cc7b0edabb2310e Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 16 Aug 2025 00:11:19 +0200 Subject: [PATCH 26/43] rk3588: add overlays to toggle USB-C mode On mainline Linux for RK3588 `&usb_host0_xhci` is usually the USB-C port, if there is one, sometimes used as debug serial port, like on NanoPi R6C. Depending on SBC, it is pre-configured differently. Add overlays to swap it freely. Signed-off-by: MichaIng --- patch/kernel/archive/rockchip64-6.12/overlay/Makefile | 3 +++ .../overlay/rockchip-rk3588-usb-c-host.dtso | 10 ++++++++++ .../overlay/rockchip-rk3588-usb-c-otg.dtso | 10 ++++++++++ .../overlay/rockchip-rk3588-usb-c-peripheral.dtso | 10 ++++++++++ patch/kernel/archive/rockchip64-6.18/overlay/Makefile | 3 +++ .../overlay/rockchip-rk3588-usb-c-host.dtso | 10 ++++++++++ .../overlay/rockchip-rk3588-usb-c-otg.dtso | 10 ++++++++++ .../overlay/rockchip-rk3588-usb-c-peripheral.dtso | 10 ++++++++++ patch/kernel/archive/rockchip64-7.0/overlay/Makefile | 3 +++ .../overlay/rockchip-rk3588-usb-c-host.dtso | 10 ++++++++++ .../overlay/rockchip-rk3588-usb-c-otg.dtso | 10 ++++++++++ .../overlay/rockchip-rk3588-usb-c-peripheral.dtso | 10 ++++++++++ 12 files changed, 99 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-host.dtso create mode 100644 patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-otg.dtso create mode 100644 patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-peripheral.dtso create mode 100644 patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-host.dtso create mode 100644 patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-otg.dtso create mode 100644 patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-peripheral.dtso create mode 100644 patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-host.dtso create mode 100644 patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-otg.dtso create mode 100644 patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-peripheral.dtso diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/Makefile b/patch/kernel/archive/rockchip64-6.12/overlay/Makefile index 9c5f0c4f8da6..dc711248f609 100644 --- a/patch/kernel/archive/rockchip64-6.12/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-6.12/overlay/Makefile @@ -100,6 +100,9 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ rockchip-rk3588-uart6-m1.dtbo \ rockchip-rk3588-uart7-m2.dtbo \ rockchip-rk3588-uart8-m1.dtbo \ + rockchip-rk3588-usb-c-host.dtbo \ + rockchip-rk3588-usb-c-otg.dtbo \ + rockchip-rk3588-usb-c-peripheral.dtbo \ rockchip-rk3588-rkvenc-overlay.dtbo \ rockchip-rk3588-nanopi-m6-spi-nor-flash.dtbo \ rockchip-rk3588-nanopc-t6-mmc-frequency.dtbo diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-host.dtso b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-host.dtso new file mode 100644 index 000000000000..5d885765bfc2 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-host.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb_host0_xhci>; + __overlay__ { + dr_mode = "host"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-otg.dtso b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-otg.dtso new file mode 100644 index 000000000000..23aab9b1566d --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-otg.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb_host0_xhci>; + __overlay__ { + dr_mode = "otg"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-peripheral.dtso b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-peripheral.dtso new file mode 100644 index 000000000000..d6a0b03de946 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/overlay/rockchip-rk3588-usb-c-peripheral.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb_host0_xhci>; + __overlay__ { + dr_mode = "peripheral"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/Makefile b/patch/kernel/archive/rockchip64-6.18/overlay/Makefile index 6d21eb429f6f..92c22820c46d 100644 --- a/patch/kernel/archive/rockchip64-6.18/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-6.18/overlay/Makefile @@ -111,6 +111,9 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ rockchip-rk3588-uart6-m1.dtbo \ rockchip-rk3588-uart7-m2.dtbo \ rockchip-rk3588-uart8-m1.dtbo \ + rockchip-rk3588-usb-c-host.dtbo \ + rockchip-rk3588-usb-c-otg.dtbo \ + rockchip-rk3588-usb-c-peripheral.dtbo \ rockchip-rk3588-rkvenc-overlay.dtbo \ rockchip-rk3588-nanopi-m6-spi-nor-flash.dtbo \ rockchip-rk3588-nanopi-m6-display-dsi1-yx35.dtbo \ diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-host.dtso b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-host.dtso new file mode 100644 index 000000000000..5d885765bfc2 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-host.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb_host0_xhci>; + __overlay__ { + dr_mode = "host"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-otg.dtso b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-otg.dtso new file mode 100644 index 000000000000..23aab9b1566d --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-otg.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb_host0_xhci>; + __overlay__ { + dr_mode = "otg"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-peripheral.dtso b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-peripheral.dtso new file mode 100644 index 000000000000..d6a0b03de946 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/overlay/rockchip-rk3588-usb-c-peripheral.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb_host0_xhci>; + __overlay__ { + dr_mode = "peripheral"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/Makefile b/patch/kernel/archive/rockchip64-7.0/overlay/Makefile index 6d21eb429f6f..92c22820c46d 100644 --- a/patch/kernel/archive/rockchip64-7.0/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-7.0/overlay/Makefile @@ -111,6 +111,9 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ rockchip-rk3588-uart6-m1.dtbo \ rockchip-rk3588-uart7-m2.dtbo \ rockchip-rk3588-uart8-m1.dtbo \ + rockchip-rk3588-usb-c-host.dtbo \ + rockchip-rk3588-usb-c-otg.dtbo \ + rockchip-rk3588-usb-c-peripheral.dtbo \ rockchip-rk3588-rkvenc-overlay.dtbo \ rockchip-rk3588-nanopi-m6-spi-nor-flash.dtbo \ rockchip-rk3588-nanopi-m6-display-dsi1-yx35.dtbo \ diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-host.dtso b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-host.dtso new file mode 100644 index 000000000000..5d885765bfc2 --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-host.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb_host0_xhci>; + __overlay__ { + dr_mode = "host"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-otg.dtso b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-otg.dtso new file mode 100644 index 000000000000..23aab9b1566d --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-otg.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb_host0_xhci>; + __overlay__ { + dr_mode = "otg"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-peripheral.dtso b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-peripheral.dtso new file mode 100644 index 000000000000..d6a0b03de946 --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/overlay/rockchip-rk3588-usb-c-peripheral.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb_host0_xhci>; + __overlay__ { + dr_mode = "peripheral"; + }; + }; +}; From d069b47e28b4d3db7730718e65d5ffa025d844ca Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 28 May 2025 18:36:42 +0200 Subject: [PATCH 27/43] rockchip64: remove obsolete patch The additional HDMI timings have been added upstream: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit?h=linux-6.12.y&id=d1ea423 Signed-off-by: MichaIng --- .../general-add-pll-hdmi-timings.patch | 155 ------------------ .../general-add-pll-hdmi-timings.patch | 155 ------------------ .../general-add-pll-hdmi-timings.patch | 155 ------------------ 3 files changed, 465 deletions(-) delete mode 100644 patch/kernel/archive/rockchip64-6.12/general-add-pll-hdmi-timings.patch delete mode 100644 patch/kernel/archive/rockchip64-6.18/general-add-pll-hdmi-timings.patch delete mode 100644 patch/kernel/archive/rockchip64-7.0/general-add-pll-hdmi-timings.patch diff --git a/patch/kernel/archive/rockchip64-6.12/general-add-pll-hdmi-timings.patch b/patch/kernel/archive/rockchip64-6.12/general-add-pll-hdmi-timings.patch deleted file mode 100644 index e1cdb34aa0e0..000000000000 --- a/patch/kernel/archive/rockchip64-6.12/general-add-pll-hdmi-timings.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: paolo -Date: Sun, 17 Jan 2021 10:20:21 +0000 -Subject: [ARCHEOLOGY] Adding pll hdmi timing to rockchip64-dev too - -> X-Git-Archeology: > recovered message: > Fixed rk3328 mali node, shortening memory range to 0x30000 as per-stated in official documentation -> X-Git-Archeology: - Revision 3a037e899b06452043e23cd2a17f40fe1a932c5f: https://github.com/armbian/build/commit/3a037e899b06452043e23cd2a17f40fe1a932c5f -> X-Git-Archeology: Date: Sun, 17 Jan 2021 10:20:21 +0000 -> X-Git-Archeology: From: paolo -> X-Git-Archeology: Subject: Adding pll hdmi timing to rockchip64-dev too -> X-Git-Archeology: -> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 -> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) -> X-Git-Archeology: -> X-Git-Archeology: - Revision e7377248b3cae186e24e2be781cd3365b43246f0: https://github.com/armbian/build/commit/e7377248b3cae186e24e2be781cd3365b43246f0 -> X-Git-Archeology: Date: Thu, 22 Jul 2021 00:15:54 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Second part of EDGE bumping to 5.13.y (#3045) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 744ea89a589d62cb6f409baab60fc6664520bc39: https://github.com/armbian/build/commit/744ea89a589d62cb6f409baab60fc6664520bc39 -> X-Git-Archeology: Date: Wed, 08 Sep 2021 17:51:34 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bumping EDGE kernel to 5.14.y (#3125) -> X-Git-Archeology: -> X-Git-Archeology: - Revision dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e: https://github.com/armbian/build/commit/dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e -> X-Git-Archeology: Date: Tue, 09 Nov 2021 18:06:34 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump imx6, xu4, rockchip64 and jetson-nano to 5.15 (#3238) -> X-Git-Archeology: -> X-Git-Archeology: - Revision ac8fc4385594d59257ee9dffd9efa85e3497fa7d: https://github.com/armbian/build/commit/ac8fc4385594d59257ee9dffd9efa85e3497fa7d -> X-Git-Archeology: Date: Sat, 26 Feb 2022 07:46:44 +0100 -> X-Git-Archeology: From: Piotr Szczepanik -> X-Git-Archeology: Subject: Switch rockchip64 current to linux 5.15.y (#3489) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 897674aa74bce0326ed7fe06f5336bf4709a8a1f: https://github.com/armbian/build/commit/897674aa74bce0326ed7fe06f5336bf4709a8a1f -> X-Git-Archeology: Date: Tue, 03 May 2022 08:27:32 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump and freeze kernel at last known working versions (#3736) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 597d2dac11f00d9070a4e49d6bad1b2244e36cb3: https://github.com/armbian/build/commit/597d2dac11f00d9070a4e49d6bad1b2244e36cb3 -> X-Git-Archeology: Date: Sat, 28 May 2022 07:56:22 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64-edge to 5.18 (#3814) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 8c6641e7b79f0d50acdc306d140e586a4e923cf0: https://github.com/armbian/build/commit/8c6641e7b79f0d50acdc306d140e586a4e923cf0 -> X-Git-Archeology: Date: Wed, 03 Aug 2022 22:22:55 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64 edge to 5.19 (#4039) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 6765f734cc4a22aeaa9f99a3ad28c8c322de26f6: https://github.com/armbian/build/commit/6765f734cc4a22aeaa9f99a3ad28c8c322de26f6 -> X-Git-Archeology: Date: Tue, 25 Oct 2022 11:26:51 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump rockchip64 edge to 6.0.y (#4337) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 92f1a22d76b987afa7ba555d5b509adc51d689e7: https://github.com/armbian/build/commit/92f1a22d76b987afa7ba555d5b509adc51d689e7 -> X-Git-Archeology: Date: Fri, 16 Dec 2022 13:38:13 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Re-add rockchip64 6.0 patches (#4575) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 34ae84fac5d0b66a1ab2d1e51534b7beb13ef245: https://github.com/armbian/build/commit/34ae84fac5d0b66a1ab2d1e51534b7beb13ef245 -> X-Git-Archeology: Date: Fri, 05 May 2023 14:22:00 +0200 -> X-Git-Archeology: From: amazingfate -> X-Git-Archeology: Subject: bump rockchip64 edge to v6.3 -> X-Git-Archeology: ---- - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 71 ++++++++++ - 1 file changed, 71 insertions(+) - -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index 111111111111..222222222222 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -465,6 +465,77 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { - {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 1, 1, 0, 0x0}, - {594000000, 371250000, 4, 495, 0, 3, 1, 1, 3, 0, 0, 1, 0x0}, - {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0x0}, -+ { 25175000, 25175000, 30, 1007, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 31500000, 31500000, 1, 21, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 33750000, 33750000, 1, 45, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 35500000, 35500000, 3, 71, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 36000000, 36000000, 1, 12, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 49500000, 49500000, 1, 33, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 50000000, 50000000, 3, 50, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 56250000, 56250000, 1, 75, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 65000000, 65000000, 3, 65, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 68250000, 68250000, 1, 91, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 71000000, 71000000, 3, 71, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 72000000, 72000000, 1, 24, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 73250000, 73250000, 3, 293, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 75000000, 75000000, 1, 25, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 78750000, 78750000, 1, 105, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 79500000, 79500000, 1, 53, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 83500000, 83500000, 3, 167, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 85500000, 85500000, 1, 57, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 88750000, 88750000, 3, 355, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 94500000, 94500000, 1, 63, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {101000000, 101000000, 3, 101, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {102250000, 102250000, 3, 409, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {106500000, 106500000, 1, 71, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {108000000, 108000000, 1, 36, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {115500000, 115500000, 1, 77, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {117500000, 117500000, 3, 235, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {119000000, 119000000, 3, 119, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {121750000, 121750000, 3, 487, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {122500000, 122500000, 3, 245, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {135000000, 135000000, 1, 45, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {136750000, 136750000, 3, 547, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {140250000, 140250000, 1, 187, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {146250000, 146250000, 1, 195, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {148250000, 148250000, 3, 593, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {154000000, 154000000, 3, 154, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {156000000, 156000000, 1, 52, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {156750000, 156750000, 1, 209, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {157000000, 157000000, 3, 157, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {157500000, 157500000, 1, 105, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {162000000, 162000000, 1, 54, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {175500000, 175500000, 1, 117, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {179500000, 179500000, 3, 359, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {182750000, 182750000, 3, 731, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {187000000, 187000000, 3, 187, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {187250000, 187250000, 3, 749, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {189000000, 189000000, 1, 63, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {193250000, 193250000, 3, 773, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {202500000, 202500000, 1, 135, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {204750000, 204750000, 1, 273, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {208000000, 208000000, 3, 208, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {214750000, 214750000, 3, 859, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {218250000, 218250000, 1, 291, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {229500000, 229500000, 1, 153, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {234000000, 234000000, 1, 78, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {241500000, 241500000, 1, 161, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {245250000, 245250000, 1, 327, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {245500000, 245500000, 3, 491, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {261000000, 261000000, 1, 87, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {268250000, 268250000, 3, 1073, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {268500000, 268500000, 1, 179, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {281250000, 281250000, 1, 375, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {288000000, 288000000, 1, 96, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {312250000, 312250000, 3, 1249, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {317000000, 317000000, 3, 317, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {333250000, 333250000, 3, 1333, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {348500000, 348500000, 3, 697, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {356500000, 356500000, 3, 713, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {380500000, 380500000, 3, 761, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {443250000, 443250000, 1, 591, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {505250000, 505250000, 3, 2021, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {552750000, 552750000, 1, 737, 1, 2, 2, 1, 2, 3, 4, 0, 0}, - { /* sentinel */ } - }; - --- -Armbian - diff --git a/patch/kernel/archive/rockchip64-6.18/general-add-pll-hdmi-timings.patch b/patch/kernel/archive/rockchip64-6.18/general-add-pll-hdmi-timings.patch deleted file mode 100644 index e1cdb34aa0e0..000000000000 --- a/patch/kernel/archive/rockchip64-6.18/general-add-pll-hdmi-timings.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: paolo -Date: Sun, 17 Jan 2021 10:20:21 +0000 -Subject: [ARCHEOLOGY] Adding pll hdmi timing to rockchip64-dev too - -> X-Git-Archeology: > recovered message: > Fixed rk3328 mali node, shortening memory range to 0x30000 as per-stated in official documentation -> X-Git-Archeology: - Revision 3a037e899b06452043e23cd2a17f40fe1a932c5f: https://github.com/armbian/build/commit/3a037e899b06452043e23cd2a17f40fe1a932c5f -> X-Git-Archeology: Date: Sun, 17 Jan 2021 10:20:21 +0000 -> X-Git-Archeology: From: paolo -> X-Git-Archeology: Subject: Adding pll hdmi timing to rockchip64-dev too -> X-Git-Archeology: -> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 -> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) -> X-Git-Archeology: -> X-Git-Archeology: - Revision e7377248b3cae186e24e2be781cd3365b43246f0: https://github.com/armbian/build/commit/e7377248b3cae186e24e2be781cd3365b43246f0 -> X-Git-Archeology: Date: Thu, 22 Jul 2021 00:15:54 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Second part of EDGE bumping to 5.13.y (#3045) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 744ea89a589d62cb6f409baab60fc6664520bc39: https://github.com/armbian/build/commit/744ea89a589d62cb6f409baab60fc6664520bc39 -> X-Git-Archeology: Date: Wed, 08 Sep 2021 17:51:34 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bumping EDGE kernel to 5.14.y (#3125) -> X-Git-Archeology: -> X-Git-Archeology: - Revision dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e: https://github.com/armbian/build/commit/dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e -> X-Git-Archeology: Date: Tue, 09 Nov 2021 18:06:34 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump imx6, xu4, rockchip64 and jetson-nano to 5.15 (#3238) -> X-Git-Archeology: -> X-Git-Archeology: - Revision ac8fc4385594d59257ee9dffd9efa85e3497fa7d: https://github.com/armbian/build/commit/ac8fc4385594d59257ee9dffd9efa85e3497fa7d -> X-Git-Archeology: Date: Sat, 26 Feb 2022 07:46:44 +0100 -> X-Git-Archeology: From: Piotr Szczepanik -> X-Git-Archeology: Subject: Switch rockchip64 current to linux 5.15.y (#3489) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 897674aa74bce0326ed7fe06f5336bf4709a8a1f: https://github.com/armbian/build/commit/897674aa74bce0326ed7fe06f5336bf4709a8a1f -> X-Git-Archeology: Date: Tue, 03 May 2022 08:27:32 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump and freeze kernel at last known working versions (#3736) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 597d2dac11f00d9070a4e49d6bad1b2244e36cb3: https://github.com/armbian/build/commit/597d2dac11f00d9070a4e49d6bad1b2244e36cb3 -> X-Git-Archeology: Date: Sat, 28 May 2022 07:56:22 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64-edge to 5.18 (#3814) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 8c6641e7b79f0d50acdc306d140e586a4e923cf0: https://github.com/armbian/build/commit/8c6641e7b79f0d50acdc306d140e586a4e923cf0 -> X-Git-Archeology: Date: Wed, 03 Aug 2022 22:22:55 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64 edge to 5.19 (#4039) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 6765f734cc4a22aeaa9f99a3ad28c8c322de26f6: https://github.com/armbian/build/commit/6765f734cc4a22aeaa9f99a3ad28c8c322de26f6 -> X-Git-Archeology: Date: Tue, 25 Oct 2022 11:26:51 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump rockchip64 edge to 6.0.y (#4337) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 92f1a22d76b987afa7ba555d5b509adc51d689e7: https://github.com/armbian/build/commit/92f1a22d76b987afa7ba555d5b509adc51d689e7 -> X-Git-Archeology: Date: Fri, 16 Dec 2022 13:38:13 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Re-add rockchip64 6.0 patches (#4575) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 34ae84fac5d0b66a1ab2d1e51534b7beb13ef245: https://github.com/armbian/build/commit/34ae84fac5d0b66a1ab2d1e51534b7beb13ef245 -> X-Git-Archeology: Date: Fri, 05 May 2023 14:22:00 +0200 -> X-Git-Archeology: From: amazingfate -> X-Git-Archeology: Subject: bump rockchip64 edge to v6.3 -> X-Git-Archeology: ---- - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 71 ++++++++++ - 1 file changed, 71 insertions(+) - -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index 111111111111..222222222222 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -465,6 +465,77 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { - {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 1, 1, 0, 0x0}, - {594000000, 371250000, 4, 495, 0, 3, 1, 1, 3, 0, 0, 1, 0x0}, - {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0x0}, -+ { 25175000, 25175000, 30, 1007, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 31500000, 31500000, 1, 21, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 33750000, 33750000, 1, 45, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 35500000, 35500000, 3, 71, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 36000000, 36000000, 1, 12, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 49500000, 49500000, 1, 33, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 50000000, 50000000, 3, 50, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 56250000, 56250000, 1, 75, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 65000000, 65000000, 3, 65, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 68250000, 68250000, 1, 91, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 71000000, 71000000, 3, 71, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 72000000, 72000000, 1, 24, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 73250000, 73250000, 3, 293, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 75000000, 75000000, 1, 25, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 78750000, 78750000, 1, 105, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 79500000, 79500000, 1, 53, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 83500000, 83500000, 3, 167, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 85500000, 85500000, 1, 57, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 88750000, 88750000, 3, 355, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 94500000, 94500000, 1, 63, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {101000000, 101000000, 3, 101, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {102250000, 102250000, 3, 409, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {106500000, 106500000, 1, 71, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {108000000, 108000000, 1, 36, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {115500000, 115500000, 1, 77, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {117500000, 117500000, 3, 235, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {119000000, 119000000, 3, 119, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {121750000, 121750000, 3, 487, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {122500000, 122500000, 3, 245, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {135000000, 135000000, 1, 45, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {136750000, 136750000, 3, 547, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {140250000, 140250000, 1, 187, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {146250000, 146250000, 1, 195, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {148250000, 148250000, 3, 593, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {154000000, 154000000, 3, 154, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {156000000, 156000000, 1, 52, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {156750000, 156750000, 1, 209, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {157000000, 157000000, 3, 157, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {157500000, 157500000, 1, 105, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {162000000, 162000000, 1, 54, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {175500000, 175500000, 1, 117, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {179500000, 179500000, 3, 359, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {182750000, 182750000, 3, 731, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {187000000, 187000000, 3, 187, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {187250000, 187250000, 3, 749, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {189000000, 189000000, 1, 63, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {193250000, 193250000, 3, 773, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {202500000, 202500000, 1, 135, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {204750000, 204750000, 1, 273, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {208000000, 208000000, 3, 208, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {214750000, 214750000, 3, 859, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {218250000, 218250000, 1, 291, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {229500000, 229500000, 1, 153, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {234000000, 234000000, 1, 78, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {241500000, 241500000, 1, 161, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {245250000, 245250000, 1, 327, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {245500000, 245500000, 3, 491, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {261000000, 261000000, 1, 87, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {268250000, 268250000, 3, 1073, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {268500000, 268500000, 1, 179, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {281250000, 281250000, 1, 375, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {288000000, 288000000, 1, 96, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {312250000, 312250000, 3, 1249, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {317000000, 317000000, 3, 317, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {333250000, 333250000, 3, 1333, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {348500000, 348500000, 3, 697, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {356500000, 356500000, 3, 713, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {380500000, 380500000, 3, 761, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {443250000, 443250000, 1, 591, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {505250000, 505250000, 3, 2021, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {552750000, 552750000, 1, 737, 1, 2, 2, 1, 2, 3, 4, 0, 0}, - { /* sentinel */ } - }; - --- -Armbian - diff --git a/patch/kernel/archive/rockchip64-7.0/general-add-pll-hdmi-timings.patch b/patch/kernel/archive/rockchip64-7.0/general-add-pll-hdmi-timings.patch deleted file mode 100644 index e1cdb34aa0e0..000000000000 --- a/patch/kernel/archive/rockchip64-7.0/general-add-pll-hdmi-timings.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: paolo -Date: Sun, 17 Jan 2021 10:20:21 +0000 -Subject: [ARCHEOLOGY] Adding pll hdmi timing to rockchip64-dev too - -> X-Git-Archeology: > recovered message: > Fixed rk3328 mali node, shortening memory range to 0x30000 as per-stated in official documentation -> X-Git-Archeology: - Revision 3a037e899b06452043e23cd2a17f40fe1a932c5f: https://github.com/armbian/build/commit/3a037e899b06452043e23cd2a17f40fe1a932c5f -> X-Git-Archeology: Date: Sun, 17 Jan 2021 10:20:21 +0000 -> X-Git-Archeology: From: paolo -> X-Git-Archeology: Subject: Adding pll hdmi timing to rockchip64-dev too -> X-Git-Archeology: -> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 -> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) -> X-Git-Archeology: -> X-Git-Archeology: - Revision e7377248b3cae186e24e2be781cd3365b43246f0: https://github.com/armbian/build/commit/e7377248b3cae186e24e2be781cd3365b43246f0 -> X-Git-Archeology: Date: Thu, 22 Jul 2021 00:15:54 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Second part of EDGE bumping to 5.13.y (#3045) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 744ea89a589d62cb6f409baab60fc6664520bc39: https://github.com/armbian/build/commit/744ea89a589d62cb6f409baab60fc6664520bc39 -> X-Git-Archeology: Date: Wed, 08 Sep 2021 17:51:34 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bumping EDGE kernel to 5.14.y (#3125) -> X-Git-Archeology: -> X-Git-Archeology: - Revision dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e: https://github.com/armbian/build/commit/dd51f9f2afcbc83a3e10b32eb6a5061d91d1558e -> X-Git-Archeology: Date: Tue, 09 Nov 2021 18:06:34 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump imx6, xu4, rockchip64 and jetson-nano to 5.15 (#3238) -> X-Git-Archeology: -> X-Git-Archeology: - Revision ac8fc4385594d59257ee9dffd9efa85e3497fa7d: https://github.com/armbian/build/commit/ac8fc4385594d59257ee9dffd9efa85e3497fa7d -> X-Git-Archeology: Date: Sat, 26 Feb 2022 07:46:44 +0100 -> X-Git-Archeology: From: Piotr Szczepanik -> X-Git-Archeology: Subject: Switch rockchip64 current to linux 5.15.y (#3489) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 897674aa74bce0326ed7fe06f5336bf4709a8a1f: https://github.com/armbian/build/commit/897674aa74bce0326ed7fe06f5336bf4709a8a1f -> X-Git-Archeology: Date: Tue, 03 May 2022 08:27:32 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump and freeze kernel at last known working versions (#3736) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 597d2dac11f00d9070a4e49d6bad1b2244e36cb3: https://github.com/armbian/build/commit/597d2dac11f00d9070a4e49d6bad1b2244e36cb3 -> X-Git-Archeology: Date: Sat, 28 May 2022 07:56:22 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64-edge to 5.18 (#3814) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 8c6641e7b79f0d50acdc306d140e586a4e923cf0: https://github.com/armbian/build/commit/8c6641e7b79f0d50acdc306d140e586a4e923cf0 -> X-Git-Archeology: Date: Wed, 03 Aug 2022 22:22:55 +0200 -> X-Git-Archeology: From: Jianfeng Liu -> X-Git-Archeology: Subject: update rockchip64 edge to 5.19 (#4039) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 6765f734cc4a22aeaa9f99a3ad28c8c322de26f6: https://github.com/armbian/build/commit/6765f734cc4a22aeaa9f99a3ad28c8c322de26f6 -> X-Git-Archeology: Date: Tue, 25 Oct 2022 11:26:51 +0200 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Bump rockchip64 edge to 6.0.y (#4337) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 92f1a22d76b987afa7ba555d5b509adc51d689e7: https://github.com/armbian/build/commit/92f1a22d76b987afa7ba555d5b509adc51d689e7 -> X-Git-Archeology: Date: Fri, 16 Dec 2022 13:38:13 +0100 -> X-Git-Archeology: From: Igor Pecovnik -> X-Git-Archeology: Subject: Re-add rockchip64 6.0 patches (#4575) -> X-Git-Archeology: -> X-Git-Archeology: - Revision 34ae84fac5d0b66a1ab2d1e51534b7beb13ef245: https://github.com/armbian/build/commit/34ae84fac5d0b66a1ab2d1e51534b7beb13ef245 -> X-Git-Archeology: Date: Fri, 05 May 2023 14:22:00 +0200 -> X-Git-Archeology: From: amazingfate -> X-Git-Archeology: Subject: bump rockchip64 edge to v6.3 -> X-Git-Archeology: ---- - drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 71 ++++++++++ - 1 file changed, 71 insertions(+) - -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -index 111111111111..222222222222 100644 ---- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c -@@ -465,6 +465,77 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { - {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 1, 1, 0, 0x0}, - {594000000, 371250000, 4, 495, 0, 3, 1, 1, 3, 0, 0, 1, 0x0}, - {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0x0}, -+ { 25175000, 25175000, 30, 1007, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 31500000, 31500000, 1, 21, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 33750000, 33750000, 1, 45, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 35500000, 35500000, 3, 71, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 36000000, 36000000, 1, 12, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 49500000, 49500000, 1, 33, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 50000000, 50000000, 3, 50, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 56250000, 56250000, 1, 75, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 65000000, 65000000, 3, 65, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 68250000, 68250000, 1, 91, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 71000000, 71000000, 3, 71, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 72000000, 72000000, 1, 24, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 73250000, 73250000, 3, 293, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 75000000, 75000000, 1, 25, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ { 78750000, 78750000, 1, 105, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 79500000, 79500000, 1, 53, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 83500000, 83500000, 3, 167, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 85500000, 85500000, 1, 57, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ { 88750000, 88750000, 3, 355, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ { 94500000, 94500000, 1, 63, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {101000000, 101000000, 3, 101, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {102250000, 102250000, 3, 409, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {106500000, 106500000, 1, 71, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {108000000, 108000000, 1, 36, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {115500000, 115500000, 1, 77, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {117500000, 117500000, 3, 235, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {119000000, 119000000, 3, 119, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {121750000, 121750000, 3, 487, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {122500000, 122500000, 3, 245, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {135000000, 135000000, 1, 45, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {136750000, 136750000, 3, 547, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {140250000, 140250000, 1, 187, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {146250000, 146250000, 1, 195, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {148250000, 148250000, 3, 593, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {154000000, 154000000, 3, 154, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {156000000, 156000000, 1, 52, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {156750000, 156750000, 1, 209, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {157000000, 157000000, 3, 157, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {157500000, 157500000, 1, 105, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {162000000, 162000000, 1, 54, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {175500000, 175500000, 1, 117, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {179500000, 179500000, 3, 359, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {182750000, 182750000, 3, 731, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {187000000, 187000000, 3, 187, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {187250000, 187250000, 3, 749, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {189000000, 189000000, 1, 63, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {193250000, 193250000, 3, 773, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {202500000, 202500000, 1, 135, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {204750000, 204750000, 1, 273, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {208000000, 208000000, 3, 208, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {214750000, 214750000, 3, 859, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {218250000, 218250000, 1, 291, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {229500000, 229500000, 1, 153, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {234000000, 234000000, 1, 78, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {241500000, 241500000, 1, 161, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {245250000, 245250000, 1, 327, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {245500000, 245500000, 3, 491, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {261000000, 261000000, 1, 87, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {268250000, 268250000, 3, 1073, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {268500000, 268500000, 1, 179, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {281250000, 281250000, 1, 375, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {288000000, 288000000, 1, 96, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {312250000, 312250000, 3, 1249, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {317000000, 317000000, 3, 317, 0, 1, 1, 1, 0, 2, 2, 0, 0}, -+ {333250000, 333250000, 3, 1333, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {348500000, 348500000, 3, 697, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {356500000, 356500000, 3, 713, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {380500000, 380500000, 3, 761, 1, 1, 1, 1, 2, 2, 2, 0, 0}, -+ {443250000, 443250000, 1, 591, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {505250000, 505250000, 3, 2021, 1, 2, 2, 1, 2, 3, 4, 0, 0}, -+ {552750000, 552750000, 1, 737, 1, 2, 2, 1, 2, 3, 4, 0, 0}, - { /* sentinel */ } - }; - --- -Armbian - From 479aa7a3b7779398444fd2c3e8545ddf8f0fd15b Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 6 May 2025 18:55:02 +0200 Subject: [PATCH 28/43] tinkerboard-2: add ethernet0 alias for fixed MAC address Linux removed it from base dtsi to be added to individual dts for boards which actually have onboard Ethernet: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit?id=5d90cb1 Signed-off-by: MichaIng --- patch/kernel/archive/rockchip64-6.12/dt/rk3399-tinker-2.dts | 4 ++++ patch/kernel/archive/rockchip64-6.18/dt/rk3399-tinker-2.dts | 4 ++++ patch/kernel/archive/rockchip64-7.0/dt/rk3399-tinker-2.dts | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/patch/kernel/archive/rockchip64-6.12/dt/rk3399-tinker-2.dts b/patch/kernel/archive/rockchip64-6.12/dt/rk3399-tinker-2.dts index 8cbe3850558e..996a70db7773 100644 --- a/patch/kernel/archive/rockchip64-6.12/dt/rk3399-tinker-2.dts +++ b/patch/kernel/archive/rockchip64-6.12/dt/rk3399-tinker-2.dts @@ -14,6 +14,10 @@ model = "Asus Tinker Board 2/2S"; compatible = "rockchip,rk3399-evb", "rockchip,rk3399"; + aliases { + ethernet0 = &gmac; + }; + chosen { stdout-path = "serial2:1500000n8"; }; diff --git a/patch/kernel/archive/rockchip64-6.18/dt/rk3399-tinker-2.dts b/patch/kernel/archive/rockchip64-6.18/dt/rk3399-tinker-2.dts index 996ef1ad1606..c454a8f20765 100644 --- a/patch/kernel/archive/rockchip64-6.18/dt/rk3399-tinker-2.dts +++ b/patch/kernel/archive/rockchip64-6.18/dt/rk3399-tinker-2.dts @@ -16,6 +16,10 @@ model = "Asus Tinker Board 2/2S"; compatible = "rockchip,rk3399-evb", "rockchip,rk3399"; + aliases { + ethernet0 = &gmac; + }; + chosen { stdout-path = "serial2:1500000n8"; }; diff --git a/patch/kernel/archive/rockchip64-7.0/dt/rk3399-tinker-2.dts b/patch/kernel/archive/rockchip64-7.0/dt/rk3399-tinker-2.dts index 996ef1ad1606..c454a8f20765 100644 --- a/patch/kernel/archive/rockchip64-7.0/dt/rk3399-tinker-2.dts +++ b/patch/kernel/archive/rockchip64-7.0/dt/rk3399-tinker-2.dts @@ -16,6 +16,10 @@ model = "Asus Tinker Board 2/2S"; compatible = "rockchip,rk3399-evb", "rockchip,rk3399"; + aliases { + ethernet0 = &gmac; + }; + chosen { stdout-path = "serial2:1500000n8"; }; From ed29a8c35380d99809a29087464aef068f1610df Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 22 May 2024 17:42:43 +0200 Subject: [PATCH 29/43] odroidc2: fix reboot All credits go to @gitmeister: https://github.com/MichaIng/DietPi/issues/5414#issuecomment-1462629461 Signed-off-by: MichaIng --- .../meson64-6.12/board-odroidc2-fix-reboot.patch | 13 +++++++++++++ .../meson64-6.18/board-odroidc2-fix-reboot.patch | 13 +++++++++++++ .../meson64-7.0/board-odroidc2-fix-reboot.patch | 13 +++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 patch/kernel/archive/meson64-6.12/board-odroidc2-fix-reboot.patch create mode 100644 patch/kernel/archive/meson64-6.18/board-odroidc2-fix-reboot.patch create mode 100644 patch/kernel/archive/meson64-7.0/board-odroidc2-fix-reboot.patch diff --git a/patch/kernel/archive/meson64-6.12/board-odroidc2-fix-reboot.patch b/patch/kernel/archive/meson64-6.12/board-odroidc2-fix-reboot.patch new file mode 100644 index 000000000000..ac6cf9f26d4b --- /dev/null +++ b/patch/kernel/archive/meson64-6.12/board-odroidc2-fix-reboot.patch @@ -0,0 +1,13 @@ +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts +index e6d2de7..662b4be 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts +@@ -102,7 +102,7 @@ + /* + * signal name from schematics: TF_3V3N_1V8_EN + */ +- gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ gpios = <&gpio_ao GPIOAO_3 GPIO_OPEN_DRAIN>; + gpios-states = <0>; + + states = <3300000 0>, diff --git a/patch/kernel/archive/meson64-6.18/board-odroidc2-fix-reboot.patch b/patch/kernel/archive/meson64-6.18/board-odroidc2-fix-reboot.patch new file mode 100644 index 000000000000..ac6cf9f26d4b --- /dev/null +++ b/patch/kernel/archive/meson64-6.18/board-odroidc2-fix-reboot.patch @@ -0,0 +1,13 @@ +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts +index e6d2de7..662b4be 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts +@@ -102,7 +102,7 @@ + /* + * signal name from schematics: TF_3V3N_1V8_EN + */ +- gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ gpios = <&gpio_ao GPIOAO_3 GPIO_OPEN_DRAIN>; + gpios-states = <0>; + + states = <3300000 0>, diff --git a/patch/kernel/archive/meson64-7.0/board-odroidc2-fix-reboot.patch b/patch/kernel/archive/meson64-7.0/board-odroidc2-fix-reboot.patch new file mode 100644 index 000000000000..ac6cf9f26d4b --- /dev/null +++ b/patch/kernel/archive/meson64-7.0/board-odroidc2-fix-reboot.patch @@ -0,0 +1,13 @@ +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts +index e6d2de7..662b4be 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts +@@ -102,7 +102,7 @@ + /* + * signal name from schematics: TF_3V3N_1V8_EN + */ +- gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ gpios = <&gpio_ao GPIOAO_3 GPIO_OPEN_DRAIN>; + gpios-states = <0>; + + states = <3300000 0>, From b853045502a792ba2107cfcd6521daf189b69abe Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 25 Jan 2026 20:12:56 +0100 Subject: [PATCH 30/43] rk3328: remove experimental Rockchip Innosilicon USB3 PHY driver It breaks the respective USB port on all RK3328 boards we support, and the internally attached Ethernet on NanoPi R2S. Signed-off-by: MichaIng --- .../rk3328-inno-usb3phy-driver.patch | 1155 ----------------- .../rk3328-inno-usb3phy-driver.patch | 1155 ----------------- 2 files changed, 2310 deletions(-) delete mode 100644 patch/kernel/archive/rockchip64-6.18/rk3328-inno-usb3phy-driver.patch delete mode 100644 patch/kernel/archive/rockchip64-7.0/rk3328-inno-usb3phy-driver.patch diff --git a/patch/kernel/archive/rockchip64-6.18/rk3328-inno-usb3phy-driver.patch b/patch/kernel/archive/rockchip64-6.18/rk3328-inno-usb3phy-driver.patch deleted file mode 100644 index d7f0dac1eb72..000000000000 --- a/patch/kernel/archive/rockchip64-6.18/rk3328-inno-usb3phy-driver.patch +++ /dev/null @@ -1,1155 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paolo Sabatino -Date: Tue, 12 Aug 2025 20:08:01 +0200 -Subject: Add rockchip Innosilicon USB3 phy driver - -source: https://patchwork.kernel.org/project/linux-rockchip/cover/20250115012628.1035928-1-pgwipeout@gmail.com/ ---- - Documentation/devicetree/bindings/phy/rockchip,inno-usb3phy.yaml | 166 ++ - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 39 + - drivers/phy/rockchip/Kconfig | 10 + - drivers/phy/rockchip/Makefile | 1 + - drivers/phy/rockchip/phy-rockchip-inno-usb3.c | 870 ++++++++++ - 5 files changed, 1086 insertions(+) - -diff --git a/Documentation/devicetree/bindings/phy/rockchip,inno-usb3phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,inno-usb3phy.yaml -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/Documentation/devicetree/bindings/phy/rockchip,inno-usb3phy.yaml -@@ -0,0 +1,166 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/phy/rockchip,inno-usb3phy.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Rockchip USB 3.0 phy with Innosilicon IP block -+ -+maintainers: -+ - Heiko Stuebner -+ -+properties: -+ compatible: -+ enum: -+ - rockchip,rk3328-usb3phy -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ minItems: 3 -+ maxItems: 3 -+ -+ clock-names: -+ items: -+ - const: refclk-usb3otg -+ - const: usb3phy-otg -+ - const: usb3phy-pipe -+ -+ interrupts: -+ minItems: 4 -+ -+ interrupt-names: -+ items: -+ - const: bvalid -+ - const: id -+ - const: linestate -+ - const: rxdet -+ -+ resets: -+ minItems: 6 -+ -+ reset-names: -+ items: -+ - const: usb3phy-u2-por -+ - const: usb3phy-u3-por -+ - const: usb3phy-pipe-mac -+ - const: usb3phy-utmi-mac -+ - const: usb3phy-utmi-apb -+ - const: usb3phy-pipe-apb -+ -+ "#address-cells": -+ const: 2 -+ -+ "#size-cells": -+ const: 2 -+ -+ ranges: true -+ -+patternProperties: -+ -+ utmi-port@[0-9a-f]+$: -+ type: object -+ additionalProperties: false -+ -+ properties: -+ compatible: -+ enum: -+ - rockchip,rk3328-usb3phy-utmi -+ -+ reg: -+ maxItems: 1 -+ -+ "#phy-cells": -+ const: 0 -+ -+ phy-supply: -+ description: -+ Phandle to a regulator that provides power to VBUS. -+ See ./phy-bindings.txt for details. -+ -+ required: -+ - compatible -+ - reg -+ - "#phy-cells" -+ -+ pipe-port@[0-9a-f]+$: -+ type: object -+ additionalProperties: false -+ -+ properties: -+ compatible: -+ enum: -+ - rockchip,rk3328-usb3phy-pipe -+ -+ reg: -+ maxItems: 1 -+ -+ "#phy-cells": -+ const: 0 -+ -+ phy-supply: -+ description: -+ Phandle to a regulator that provides power to VBUS. -+ See ./phy-bindings.txt for details. -+ -+ required: -+ - compatible -+ - reg -+ - "#phy-cells" -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ - interrupts -+ - interrupt-names -+ - resets -+ - reset-names -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ soc { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ usb3phy: usb3-phy@ff460000 { -+ compatible = "rockchip,rk3328-usb3phy"; -+ reg = <0x0 0xff460000 0x0 0x10000>; -+ clocks = <&cru SCLK_REF_USB3OTG>, <&cru PCLK_USB3PHY_OTG>, <&cru PCLK_USB3PHY_PIPE>; -+ clock-names = "refclk-usb3otg", "usb3phy-otg", "usb3phy-pipe"; -+ interrupts = , , -+ , ; -+ interrupt-names = "bvalid", "id", "linestate", "rxdet"; -+ resets = <&cru SRST_USB3PHY_U2>, -+ <&cru SRST_USB3PHY_U3>, -+ <&cru SRST_USB3PHY_PIPE>, -+ <&cru SRST_USB3OTG_UTMI>, -+ <&cru SRST_USB3PHY_OTG_P>, -+ <&cru SRST_USB3PHY_PIPE_P>; -+ reset-names = "usb3phy-u2-por", "usb3phy-u3-por", -+ "usb3phy-pipe-mac", "usb3phy-utmi-mac", -+ "usb3phy-utmi-apb", "usb3phy-pipe-apb"; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ usb3phy_utmi: utmi-port@ff470000 { -+ compatible = "rockchip,rk3328-usb3phy-utmi"; -+ reg = <0x0 0xff470000 0x0 0x8000>; -+ #phy-cells = <0>; -+ }; -+ -+ usb3phy_pipe: pipe-port@ff478000 { -+ compatible = "rockchip,rk3328-usb3phy-pipe"; -+ reg = <0x0 0xff478000 0x0 0x8000>; -+ #phy-cells = <0>; -+ }; -+ }; -+ }; -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index 111111111111..222222222222 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -1055,6 +1055,43 @@ u2phy_host: host-port { - }; - }; - -+ usb3phy: usb3-phy@ff460000 { -+ compatible = "rockchip,rk3328-usb3phy"; -+ reg = <0x0 0xff460000 0x0 0x10000>; -+ clocks = <&cru SCLK_REF_USB3OTG>, <&cru PCLK_USB3PHY_OTG>, <&cru PCLK_USB3PHY_PIPE>; -+ clock-names = "refclk-usb3otg", "usb3phy-otg", "usb3phy-pipe"; -+ interrupts = , , -+ , ; -+ interrupt-names = "bvalid", "id", "linestate", "rxdet"; -+ resets = <&cru SRST_USB3PHY_U2>, -+ <&cru SRST_USB3PHY_U3>, -+ <&cru SRST_USB3PHY_PIPE>, -+ <&cru SRST_USB3OTG_UTMI>, -+ <&cru SRST_USB3PHY_OTG_P>, -+ <&cru SRST_USB3PHY_PIPE_P>; -+ reset-names = "usb3phy-u2-por", "usb3phy-u3-por", -+ "usb3phy-pipe-mac", "usb3phy-utmi-mac", -+ "usb3phy-utmi-apb", "usb3phy-pipe-apb"; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ status = "okay"; -+ -+ usb3phy_utmi: utmi-port@ff470000 { -+ compatible = "rockchip,rk3328-usb3phy-utmi"; -+ reg = <0x0 0xff470000 0x0 0x8000>; -+ #phy-cells = <0>; -+ status = "okay"; -+ }; -+ -+ usb3phy_pipe: pipe-port@ff478000 { -+ compatible = "rockchip,rk3328-usb3phy-pipe"; -+ reg = <0x0 0xff478000 0x0 0x8000>; -+ #phy-cells = <0>; -+ status = "okay"; -+ }; -+ }; -+ - sdmmc: mmc@ff500000 { - compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xff500000 0x0 0x4000>; -@@ -1221,6 +1258,8 @@ usbdrd3: usb@ff600000 { - resets = <&cru SRST_USB3OTG>; - reset-names = "usb3-otg"; - dr_mode = "otg"; -+ phys = <&usb3phy_utmi>, <&usb3phy_pipe>; -+ phy-names = "usb2-phy", "usb3-phy"; - phy_type = "utmi_wide"; - snps,dis-del-phy-power-chg-quirk; - snps,dis_enblslpm_quirk; -diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig -index 111111111111..222222222222 100644 ---- a/drivers/phy/rockchip/Kconfig -+++ b/drivers/phy/rockchip/Kconfig -@@ -48,6 +48,16 @@ config PHY_ROCKCHIP_INNO_USB2 - help - Support for Rockchip USB2.0 PHY with Innosilicon IP block. - -+config PHY_ROCKCHIP_INNO_USB3 -+ tristate "Rockchip INNO USB3PHY Driver" -+ depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF -+ depends on COMMON_CLK -+ depends on USB_SUPPORT -+ select GENERIC_PHY -+ select USB_COMMON -+ help -+ Support for Rockchip USB3.0 PHY with Innosilicon IP block. -+ - config PHY_ROCKCHIP_INNO_CSIDPHY - tristate "Rockchip Innosilicon MIPI CSI PHY driver" - depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF -diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile -index 111111111111..222222222222 100644 ---- a/drivers/phy/rockchip/Makefile -+++ b/drivers/phy/rockchip/Makefile -@@ -6,6 +6,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY) += phy-rockchip-inno-csidphy.o - obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o - obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o - obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o -+obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB3) += phy-rockchip-inno-usb3.o - obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o - obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o - obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_DCPHY) += phy-rockchip-samsung-dcphy.o -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb3.c b/drivers/phy/rockchip/phy-rockchip-inno-usb3.c -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb3.c -@@ -0,0 +1,870 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+ -+/* -+ * phy-rockchip-inno-usb3.c - USB3 PHY based on Innosilicon IP as -+ * implemented on Rockchip rk3328. Tuning data magic bits are taken as is -+ * from the downstream driver. Downstream driver is located at: -+ * https://github.com/rockchip-linux/kernel/blob/240a5660d7c23841ccf7b7cc489078bf521b9802/drivers/phy/rockchip/phy-rockchip-inno-usb3.c -+ * -+ * Author: Peter Geis -+ * TODO: -+ * - Find the rest of the register names / definitions. -+ * - Implement pm functions. -+ * - Implement board specific tuning from dts. -+ * - Implement regulator control. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define REG_WRITE_MASK GENMASK(31, 16) -+#define REG_WRITE_SHIFT 16 -+#define DISABLE_BITS 0x0 -+ -+/* USB3PHY GRF Registers */ -+#define USB3PHY_WAKEUP_CON_REG 0x40 -+#define USB3PHY_WAKEUP_STAT_REG 0x44 -+#define USB3_LINESTATE_IRQ_EN BIT(0) -+#define USB3_RXDET_IRQ_EN BIT(1) -+#define USB3_BVALID_RISE_IRQ_EN BIT(2) -+#define USB3_BVALID_FALL_IRQ_EN BIT(3) -+#define USB3_BVALID_CLEAR_MASK GENMASK(3, 2) -+#define USB3_ID_RISE_IRQ_EN BIT(4) -+#define USB3_ID_FALL_IRQ_EN BIT(5) -+#define USB3_ID_CLEAR_MASK GENMASK(5, 4) -+#define USB3_RXDET_EN BIT(6) -+ -+/* PIPE registers */ -+/* 0x08 for SSC, default 0x0e */ -+#define UNKNOWN_PIPE_REG_000 0x000 -+#define UNKNOWN_SSC_000_MASK GENMASK(2, 1) -+#define UNKNOWN_SSC_000_ENABLE (0x00 << 1) -+ -+/* 0x83 for 24m, 0x01 for 25m, default 0x86 */ -+#define PIPE_REG_020 0x020 -+/* RX CDR multiplier high bits [7:6], as P, default 0x2, RX data rate = (2*refclk*P)/Q */ -+#define PIPE_RX_CDR_MULT_HIGH_MASK GENMASK(7, 6) -+/* TX PLL divider bits [4:0], as N, default 0x6, TX data rate = (2*refclk*M)/N */ -+#define PIPE_TX_PLL_DIV_MASK GENMASK(4, 0) -+ -+/* 0x71 for 24m, 0x64 for 25m, default 0x71 */ -+#define PIPE_REG_028 0x028 -+/* RX CDR multiplier low bits [7:0], as P, default 0x71, RX data rate = (2*refclk*P)/Q */ -+#define PIPE_RX_CDR_MULT_LOW_MASK GENMASK(7, 0) -+ -+/* 0x26 for 24m?, 0x21 for 25m, default 0x26 */ -+#define PIPE_REG_030 0x030 -+/* RX CDR divider bits [4:0], as Q, default 0x6, RX data rate = (2*refclk*P)/Q */ -+#define PIPE_RX_CDR_DIV_MASK GENMASK(4, 0) -+ -+/* 1'b1 Disable bandgap power, default 0x00 */ -+#define PIPE_REG_044 0x044 -+#define BANDGAP_POWER_DISABLE BIT(4) -+ -+/* 0xe0 for rx tune?, default 0xe1 */ -+#define PIPE_REG_060 0x060 -+#define PIPE_TX_DETECT_BYPASS_DEBUG BIT(4) /* enable to always force detection */ -+/* RX CTLE frequency bandwidth response tuning bits [1:0], default 0x1 */ -+#define PIPE_RX_CTLE_FREQ_BW_MASK GENMASK(1, 0) -+#define PIPE_RX_CTLE_FREQ_BW_TUNE 0x0 -+ -+/* default 0x49 */ -+#define PIPE_REG_064 0x064 -+/* RX equalizer tail current control bits [6:4], default 0x4 */ -+#define PIPE_RX_EQ_TAIL_CURR_MASK GENMASK(6, 4) -+ -+/* 0x08 for rx tune?, default 0x07 */ -+#define PIPE_REG_068 0x068 -+/* RX equalizer low frequency gain control bits [7:4], default 0x0 */ -+#define PIPE_RX_EQ_LOW_GAIN_MASK GENMASK(7, 4) -+#define PIPE_RX_EQ_LOW_GAIN_TUNE (0x1 << 4) -+/* RX CTLE gain tuning bits [3:0], higher = more gain default 0x7 */ -+#define PIPE_RX_CTLE_GAIN_MASK GENMASK(3, 0) -+#define PIPE_RX_CTLE_GAIN_TUNE 0x7 /* 0x5 lowest functional value, 0xf highest */ -+ -+/* RX ODT manual resistance config, higher = less resistance, depends on REG_1C4 BIT(5) set */ -+#define PIPE_REG_06C 0x06c -+/* RX ODT manual resistance high bits [3:0], default 0x0 */ -+#define PIPE_RX_ODT_RES_HIGH_MASK GENMASK(3, 0) -+#define PIPE_RX_ODT_RES_HIGH_TUNE 0xf -+ -+#define PIPE_REG_070 0x070 -+/* RX ODT manual resistance mid bits [7:0], default 0x03 */ -+#define PIPE_RX_ODT_RES_MID_MASK GENMASK(7, 0) -+#define PIPE_RX_ODT_RES_MID_TUNE 0xff -+ -+#define PIPE_REG_074 0x074 -+/* RX ODT manual resistance low bits [7:0], default 0xff */ -+#define PIPE_RX_ODT_RES_LOW_MASK GENMASK(7, 0) -+#define PIPE_RX_ODT_RES_LOW_TUNE 0xff -+ -+/* default 0x08 */ -+#define PIPE_REG_080 0x080 -+#define PIPE_TX_COMMON_MODE_DIS BIT(2) /* 1'b1 disable TX common type */ -+ -+/* default 0x33 */ -+#define PIPE_REG_088 0x088 -+#define PIPE_TX_DRIVER_PREEMP_EN BIT(4) /* 1'b1 enable pre-emphasis */ -+ -+/* default 0x18 */ -+#define PIPE_REG_0C0 0x0c0 -+#define PIPE_RX_CM_EN BIT(3) /* 1'b1 enable RX CM */ -+#define PIPE_TX_OBS_EN BIT(4) /* 1'b1 enable TX OBS */ -+ -+/* 0x12 for rx tune?, default 0x14 */ -+#define PIPE_REG_0C8 0x0c8 -+/* RX CDR charge pump current bits [3:1], default 0x2 */ -+#define PIPE_RX_CDR_CHG_PUMP_MASK GENMASK(3, 1) -+#define PIPE_RX_CDR_CHG_PUMP_TUNE (0x2 << 1) -+ -+/* 0x02 for 24m, 0x06 for 25m, default 0x06 */ -+#define UNKNOWN_PIPE_REG_108 0x108 -+#define UNKNOWN_REFCLK_108_24M 0x02 -+ -+/* 0x80 for 24m, default 0x00 */ -+#define UNKNOWN_PIPE_REG_10C 0x10c -+#define UNKNOWN_REFCLK_10C_24M BIT(7) -+ -+/* 0x01 for 24m, 0x00 for 25m, default 0x02 */ -+#define PIPE_REG_118 0x118 -+/* TX PLL multiplier high bits [3:0], as M, default 0x2, TX data rate = (2*refclk*M)/N */ -+#define PIPE_TX_PLL_MUL_HIGH_MASK GENMASK(3, 0) -+ -+/* 0x38 for 24m, 0x64 for 25m, default 0x71 */ -+#define PIPE_REG_11C 0x11c -+/* TX PLL multiplier low bits [7:0], as M, default 0x71, TX data rate = (2*refclk*M)/N */ -+#define PIPE_TX_PLL_MUL_LOW_MASK GENMASK(7, 0) -+ -+/* 0x0c for SSC, default 0x1c */ -+#define UNKNOWN_PIPE_REG_120 0x120 -+#define UNKNOWN_SSC_120_MASK BIT(4) -+#define UNKNOWN_SSC_120_ENABLE (0x0 << 4) -+ -+/* default 0x40 */ -+#define PIPE_REG_12C 0x12c -+#define PIPE_TX_PLL_ALWAYS_ON BIT(0) /* disable for PLL control by pipe_pd */ -+ -+/* 0x05 for rx tune, default 0x01 */ -+#define PIPE_REG_148 0x148 -+#define PIPE_RX_CHG_PUMP_DIV_2 BIT(2) /* RX CDR charge pump div/2, default 0 */ -+ -+/* 0x70 for rx tune, default 0x72 */ -+#define PIPE_REG_150 0x150 -+#define PIPE_TX_BIAS_EN BIT(6) /* 1'b1 Enable TX Bias */ -+/* RX CDR phase tracking speed bits [3:0], default 0x2 */ -+#define PIPE_RX_CDR_SPEED_MASK GENMASK(3, 0) -+#define PIPE_RX_CDR_SPEED_TUNE 0x00 -+ -+/* default 0xd4 */ -+#define PIPE_REG_160 -+/* RX common mode voltage strength bits [5:4], default 0x1 */ -+#define PIPE_RX_CDR_COM_VOLT_MASK GENMASK(5, 4) -+#define PIPE_RX_CDR_COM_VOLT_TUNE (0x1 << 4) -+ -+/* default 0x00 */ -+#define PIPE_REG_180 0x180 -+/* TX driver bias reference voltage bits [3:2], in mv */ -+#define PIPE_TX_BIAS_REF_VOLT_MASK GENMASK(3, 2) -+#define PIPE_TX_BIAS_REF_VOLT_200 (0x0 << 2) -+#define PIPE_TX_BIAS_REF_VOLT_175 (0x1 << 2) -+#define PIPE_TX_BIAS_REF_VOLT_225 (0x2 << 2) /* downstream 5.10 driver setting */ -+#define PIPE_TX_BIAS_REF_VOLT_250 (0x3 << 2) -+ -+/* default 0x01 */ -+#define PIPE_REG_1A8 0x1a8 -+#define PIPE_LDO_POWER_DIS BIT(4) /* 1'b1 Disable LDO Power */ -+ -+/* default 0x07 */ -+#define PIPE_REG_1AC 0x1ac -+/* TX driver output common voltage bits [5:4], in mv */ -+#define PIPE_TX_COMMON_VOLT_MASK GENMASK(5, 4) -+#define PIPE_TX_COMMON_VOLT_800 (0x0 << 4) -+#define PIPE_TX_COMMON_VOLT_750 (0x1 << 4) -+#define PIPE_TX_COMMON_VOLT_950 (0x2 << 4) -+#define PIPE_TX_COMMON_VOLT_1100 (0x3 << 4) -+ -+/* default 0xfb */ -+#define PIPE_REG_1B8 0x1b8 -+/* TX driver swing strength bits [7:4], range 0x0 to 0xf */ -+#define PIPE_TX_DRIVER_SWING_MASK GENMASK(7, 4) /* 0x2 lowest functional value */ -+/* TX driver pre-emphasis strength bits [1:0], default 0x3, enabled by REG 088 */ -+#define PIPE_TX_DRIVER_PREEMP_STR_MASK GENMASK(1, 0) -+ -+/* set to 0xf0 for rx tune?, default 0xd0 */ -+#define PIPE_REG_1C4 0x1c4 -+#define PIPE_RX_ODT_AUTO_DIS BIT(5) /* Disable RX ODT auto compensation */ -+#define PIPE_TX_ODT_AUTO_DIS BIT(3) /* Disable TX ODT auto compensation */ -+ -+/* UTMI registers */ -+/* 0x0f for utmi tune, default 0x09*/ -+#define UTMI_REG_030 0x030 -+/* {bits[2:0]=111}: always enable pre-emphasis */ -+#define UTMI_ENABLE_PRE_EMPH_MASK GENMASK(2, 0) -+#define UTMI_ENABLE_PRE_EMPH 0x07 -+ -+/* 0x41 for utmi tune, default 0x49 */ -+#define UTMI_REG_040 0x040 -+/* TX HS pre-emphasis strength bits [5:3], default 0x1*/ -+#define UTMI_TX_PRE_EMPH_STR_MASK GENMASK(5, 3) -+#define UTMI_TX_PRE_EMPH_WEAKEST (0x0 << 3) -+ -+/* set to 0xb5 for utmi tune, default 0xb5 */ -+#define UTMI_REG_11C 0x11c -+/* {bits[4:0]=10101}: odt 45ohm tuning */ -+#define UTMI_ODT_45_OHM_MASK GENMASK(4, 0) -+#define UTMI_ODT_45_OHM_TUNE 0x15 -+ -+enum rockchip_usb3phy_type { -+ USB3PHY_TYPE_USB2, -+ USB3PHY_TYPE_USB3, -+ USB3PHY_TYPE_MAX, -+}; -+ -+/** -+ * struct rockchip_usb3phy_port - usb-phy port data. -+ * @phy: port usb phy struct. -+ * @regmap: port regmap. -+ * @type: port usb phy type. -+ */ -+struct rockchip_usb3phy_port { -+ struct phy *phy; -+ struct regmap *regmap; -+ enum rockchip_usb3phy_type type; -+}; -+ -+struct rockchip_usb3phy { -+ struct device *dev; -+ struct regmap *regmap; -+ struct clk *clk_pipe; -+ struct clk *clk_otg; -+ struct clk *clk_ref; -+ struct reset_control *u3por_rst; -+ struct reset_control *u2por_rst; -+ struct reset_control *pipe_rst; -+ struct reset_control *utmi_rst; -+ struct reset_control *pipe_apb_rst; -+ struct reset_control *utmi_apb_rst; -+ struct rockchip_usb3phy_port ports[USB3PHY_TYPE_MAX]; -+ int bvalid_irq; -+ int id_irq; -+ int ls_irq; -+ int rxdet_irq; -+}; -+ -+struct usb3phy_config { -+ unsigned int reg; -+ unsigned int mask; -+ u8 def; -+}; -+ -+static const struct usb3phy_config rk3328_rx_config[] = { -+ { PIPE_REG_150, PIPE_RX_CDR_SPEED_MASK, PIPE_RX_CDR_SPEED_TUNE }, -+ { PIPE_REG_0C8, PIPE_RX_CDR_CHG_PUMP_MASK, PIPE_RX_CDR_CHG_PUMP_TUNE }, -+ { PIPE_REG_148, PIPE_RX_CHG_PUMP_DIV_2, PIPE_RX_CHG_PUMP_DIV_2 }, -+ { PIPE_REG_068, PIPE_RX_CTLE_GAIN_MASK, PIPE_RX_CTLE_GAIN_TUNE }, -+// { PIPE_REG_1C4, PIPE_RX_ODT_AUTO_DIS, PIPE_RX_ODT_AUTO_DIS }, -+ { PIPE_REG_070, PIPE_RX_ODT_RES_MID_MASK, PIPE_RX_ODT_RES_MID_TUNE }, -+ { PIPE_REG_06C, PIPE_RX_ODT_RES_HIGH_MASK, PIPE_RX_ODT_RES_HIGH_TUNE }, -+ { PIPE_REG_060, PIPE_RX_CTLE_FREQ_BW_MASK, PIPE_RX_CTLE_FREQ_BW_TUNE }, -+ { UNKNOWN_PIPE_REG_10C, UNKNOWN_REFCLK_10C_24M, UNKNOWN_REFCLK_10C_24M }, -+ { PIPE_REG_060, PIPE_RX_CTLE_FREQ_BW_MASK, PIPE_RX_CTLE_FREQ_BW_TUNE }, -+ { PIPE_REG_068, PIPE_RX_EQ_LOW_GAIN_MASK, PIPE_RX_EQ_LOW_GAIN_TUNE }, -+}; -+ -+static const struct usb3phy_config rk3328_tx_config[] = { -+ { PIPE_REG_180, PIPE_TX_BIAS_REF_VOLT_MASK, PIPE_TX_BIAS_REF_VOLT_250 }, -+}; -+ -+static const struct usb3phy_config rk3328_ssc_config[] = { -+ { UNKNOWN_PIPE_REG_000, UNKNOWN_SSC_000_MASK, UNKNOWN_SSC_000_ENABLE }, -+ { UNKNOWN_PIPE_REG_120, UNKNOWN_SSC_120_MASK, UNKNOWN_SSC_120_ENABLE }, -+}; -+ -+static const struct usb3phy_config rk3328_utmi_config[] = { -+ { UTMI_REG_030, UTMI_ENABLE_PRE_EMPH_MASK, UTMI_ENABLE_PRE_EMPH }, -+ { UTMI_REG_040, UTMI_TX_PRE_EMPH_STR_MASK, UTMI_TX_PRE_EMPH_WEAKEST }, -+ { UTMI_REG_11C, UTMI_ODT_45_OHM_MASK, UTMI_ODT_45_OHM_TUNE }, -+}; -+ -+static const struct usb3phy_config rk3328_pipe_pwr_en_config[] = { -+ { PIPE_REG_1A8, PIPE_LDO_POWER_DIS, DISABLE_BITS }, -+ { PIPE_REG_044, BANDGAP_POWER_DISABLE, DISABLE_BITS }, -+ { PIPE_REG_150, PIPE_TX_BIAS_EN, PIPE_TX_BIAS_EN }, -+ { PIPE_REG_080, PIPE_TX_COMMON_MODE_DIS, DISABLE_BITS }, -+ { PIPE_REG_0C0, PIPE_TX_OBS_EN, PIPE_TX_OBS_EN }, -+ { PIPE_REG_0C0, PIPE_RX_CM_EN, PIPE_RX_CM_EN }, -+}; -+ -+static int rockchip_usb3phy_reset(struct rockchip_usb3phy *usb3phy, -+ bool reset, enum rockchip_usb3phy_type type) -+{ -+ if (reset) { -+ if (type == USB3PHY_TYPE_USB2) { -+ clk_disable_unprepare(usb3phy->clk_otg); -+ reset_control_assert(usb3phy->utmi_rst); -+ reset_control_assert(usb3phy->u2por_rst); -+ } -+ if (type == USB3PHY_TYPE_USB3) { -+ clk_disable_unprepare(usb3phy->clk_pipe); -+ reset_control_assert(usb3phy->pipe_rst); -+ reset_control_assert(usb3phy->u3por_rst); -+ } -+ } else { -+ if (type == USB3PHY_TYPE_USB2) { -+ reset_control_deassert(usb3phy->u2por_rst); -+ fsleep(1000); -+ clk_prepare_enable(usb3phy->clk_otg); -+ fsleep(500); -+ reset_control_deassert(usb3phy->utmi_rst); -+ fsleep(100); -+ } -+ if (type == USB3PHY_TYPE_USB3) { -+ reset_control_deassert(usb3phy->u3por_rst); -+ fsleep(500); -+ clk_prepare_enable(usb3phy->clk_pipe); -+ fsleep(1000); -+ reset_control_deassert(usb3phy->pipe_rst); -+ fsleep(100); -+ } -+ } -+ return 0; -+} -+ -+static irqreturn_t rockchip_usb3phy_linestate_irq(int irq, void *data) -+{ -+ struct rockchip_usb3phy *usb3phy = data; -+ int tmp; -+ -+ /* check if the interrupt is enabled */ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, &tmp); -+ if (!(tmp & USB3_LINESTATE_IRQ_EN)) { -+ dev_warn(usb3phy->dev, "invalid linestate irq received\n"); -+ return IRQ_NONE; -+ } -+ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, &tmp); -+ if (tmp & USB3_LINESTATE_IRQ_EN) -+ dev_dbg_ratelimited(usb3phy->dev, "linestate irq received\n"); -+ -+ /* clear the interrupt */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, USB3_LINESTATE_IRQ_EN); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t rockchip_usb3phy_bvalid_irq(int irq, void *data) -+{ -+ struct rockchip_usb3phy *usb3phy = data; -+ int tmp; -+ -+ /* check if the interrupt is enabled */ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, &tmp); -+ if (!((tmp & USB3_BVALID_FALL_IRQ_EN) | (tmp & USB3_BVALID_RISE_IRQ_EN))) { -+ dev_warn_ratelimited(usb3phy->dev, "invalid bvalid irq received\n"); -+ return IRQ_NONE; -+ } -+ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, &tmp); -+ if (tmp & USB3_BVALID_FALL_IRQ_EN) -+ dev_dbg(usb3phy->dev, "bvalid falling irq received\n"); -+ if (tmp & USB3_BVALID_RISE_IRQ_EN) -+ dev_dbg(usb3phy->dev, "bvalid rising irq received\n"); -+ -+ /* clear the interrupt */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, USB3_BVALID_CLEAR_MASK); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t rockchip_usb3phy_id_irq(int irq, void *data) -+{ -+ struct rockchip_usb3phy *usb3phy = data; -+ int tmp; -+ -+ /* check if the interrupt is enabled */ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, &tmp); -+ if (!((tmp & USB3_ID_FALL_IRQ_EN) | (tmp & USB3_ID_RISE_IRQ_EN))) { -+ dev_warn(usb3phy->dev, "invalid id irq received\n"); -+ return IRQ_NONE; -+ } -+ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, &tmp); -+ if (tmp & USB3_ID_FALL_IRQ_EN) -+ dev_dbg(usb3phy->dev, "id falling irq received\n"); -+ if (tmp & USB3_ID_RISE_IRQ_EN) -+ dev_dbg(usb3phy->dev, "id rising irq received\n"); -+ -+ /* clear the interrupt */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, USB3_ID_CLEAR_MASK); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t rockchip_usb3phy_rxdet_irq(int irq, void *data) -+{ -+ struct rockchip_usb3phy *usb3phy = data; -+ int tmp; -+ -+ /* check if the interrupt is enabled */ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, &tmp); -+ if (!(tmp & USB3_RXDET_IRQ_EN)) { -+ dev_warn(usb3phy->dev, "invalid rxdet irq received\n"); -+ return IRQ_NONE; -+ } -+ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, &tmp); -+ if (tmp & USB3_RXDET_IRQ_EN) -+ dev_dbg_ratelimited(usb3phy->dev, "rxdet irq received\n"); -+ -+ /* clear the interrupt */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, USB3_RXDET_IRQ_EN); -+ -+ return IRQ_HANDLED; -+} -+ -+static int rockchip_usb3phy_bulk_update(struct rockchip_usb3phy *usb3phy, struct regmap *regmap, -+ const struct usb3phy_config *config, unsigned int size) -+{ -+ unsigned int i, val, tmp; -+ int ret = 0; -+ -+ for (i = 0; i < size; i++) { -+ ret = regmap_read(regmap, config[i].reg, &val); -+ if (ret < 0) { -+ dev_err(usb3phy->dev, "failed to read addr: 0x%02x\n", config[i].reg); -+ return ret; -+ } -+ tmp = val & ~config[i].mask; -+ tmp |= config[i].def; -+ dev_dbg(usb3phy->dev, "write: 0x%03x old: 0x%02x new: 0x%02x\n", -+ config[i].reg, val, tmp); -+ ret = regmap_write(regmap, config[i].reg, tmp); -+ if (ret < 0) { -+ dev_err(usb3phy->dev, "failed to write addr: 0x%02x\n", config[i].reg); -+ return ret; -+ } -+ } -+ -+ return ret; -+} -+ -+static int rockchip_usb3phy_calc_rate(struct rockchip_usb3phy *usb3phy, struct regmap *regmap) -+{ -+ long rate; -+ unsigned int mul, div, target = (5000000000 / 100000); -+ -+ rate = clk_get_rate(usb3phy->clk_ref) / 100000; -+ if (rate < 0) { -+ dev_err(usb3phy->dev, "failed to get refclk, %ld\n", rate); -+ return rate; -+ /* lowest possible supported clock is 4.8MHZ, highest rk3328 can do is 1.6GHZ */ -+ } else if ((rate < 48) | (rate > 16000)) { -+ goto error; -+ } -+ -+ for (div = 1; div < 32; div++) { -+ for (mul = 1; mul < 1024; mul++) { -+ if (((2 * rate * mul) / div) == target) -+ goto done; -+ if (((2 * rate * mul) / div) > target) -+ break; -+ } -+ } -+ -+error: -+ dev_err(usb3phy->dev, "invalid refclock rate, %ld\n", rate * 100000); -+ return -EINVAL; -+ -+done: -+ dev_dbg(usb3phy->dev, "refclk rate mul: %x div: %x rate: %ld\n", mul, div, (rate * 100000)); -+ -+ regmap_write(regmap, PIPE_REG_020, (mul >> 2) & PIPE_RX_CDR_MULT_HIGH_MASK); -+ regmap_write(regmap, PIPE_REG_020, div & PIPE_TX_PLL_DIV_MASK); -+ regmap_write(regmap, PIPE_REG_028, mul & PIPE_RX_CDR_MULT_LOW_MASK); -+ regmap_write(regmap, PIPE_REG_030, div & PIPE_RX_CDR_DIV_MASK); -+ regmap_write(regmap, PIPE_REG_118, (mul >> 8) & PIPE_TX_PLL_MUL_HIGH_MASK); -+ regmap_write(regmap, PIPE_REG_11C, mul & PIPE_TX_PLL_MUL_LOW_MASK); -+ -+ return 0; -+} -+ -+static int rockchip_usb3phy_init(struct phy *phy) -+{ -+ struct rockchip_usb3phy_port *port = phy_get_drvdata(phy); -+ struct rockchip_usb3phy *usb3phy = dev_get_drvdata(phy->dev.parent); -+ int tmp, ret; -+ -+ dev_warn(usb3phy->dev, "usb3phy_init %s\n", dev_name(&phy->dev)); -+ clk_prepare_enable(usb3phy->clk_ref); -+ rockchip_usb3phy_reset(usb3phy, false, port->type); -+ -+ if (port->type == USB3PHY_TYPE_USB2) { -+ /* -+ * "For RK3328 SoC, pre-emphasis and pre-emphasis strength must be -+ * written as one fixed value. The ODT 45ohm value should be tuned -+ * for different boards to adjust HS eye height." -+ */ -+ dev_dbg(usb3phy->dev, "tuning UTMI\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, rk3328_utmi_config, -+ ARRAY_SIZE(rk3328_utmi_config)); -+ } -+ -+ if (port->type == USB3PHY_TYPE_USB3) { -+ /* Enable interrupts */ -+ tmp = (USB3_LINESTATE_IRQ_EN | USB3_ID_FALL_IRQ_EN | USB3_ID_RISE_IRQ_EN | -+ USB3_RXDET_IRQ_EN | USB3_BVALID_RISE_IRQ_EN | USB3_BVALID_FALL_IRQ_EN); -+ tmp |= (tmp << REG_WRITE_SHIFT); -+ -+ ret = regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, tmp); -+ if (ret < 0) { -+ /* interrupt write determines if we have write access */ -+ dev_err(usb3phy->dev, "failed to write interrupts\n"); -+ return ret; -+ } -+ -+ /* Configure for 24M ref clk */ -+ dev_dbg(usb3phy->dev, "setting pipe for 24M refclk\n"); -+ if (rockchip_usb3phy_calc_rate(usb3phy, usb3phy->regmap)) -+ return -EINVAL; -+ -+ /* Enable SSC */ -+ udelay(3); -+ dev_dbg(usb3phy->dev, "setting pipe for SSC\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, rk3328_ssc_config, -+ ARRAY_SIZE(rk3328_ssc_config)); -+ -+ /* "Tuning RX for compliance RJTL test" */ -+ dev_dbg(usb3phy->dev, "setting pipe for RX tuning\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, rk3328_rx_config, -+ ARRAY_SIZE(rk3328_rx_config)); -+ if (ret) -+ return ret; -+ -+ /* -+ * "Tuning TX to increase the bias current used in TX driver and RX EQ, -+ * it can also increase the voltage of LFPS." -+ */ -+ dev_dbg(usb3phy->dev, "setting pipe for TX tuning\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, -+ rk3328_tx_config, ARRAY_SIZE(rk3328_tx_config)); -+ -+ /* Power up the pipe */ -+ dev_dbg(usb3phy->dev, "setting pipe power on\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, rk3328_pipe_pwr_en_config, -+ ARRAY_SIZE(rk3328_pipe_pwr_en_config)); -+ } -+ -+ return 0; -+} -+ -+static int rockchip_usb3phy_parse_dt(struct rockchip_usb3phy *usb3phy, struct device *dev) -+{ -+ int ret; -+ -+ usb3phy->clk_pipe = devm_clk_get(dev, "usb3phy-pipe"); -+ if (IS_ERR(usb3phy->clk_pipe)) { -+ dev_err(dev, "could not get usb3phy pipe clock\n"); -+ return PTR_ERR(usb3phy->clk_pipe); -+ } -+ -+ usb3phy->clk_otg = devm_clk_get(dev, "usb3phy-otg"); -+ if (IS_ERR(usb3phy->clk_otg)) { -+ dev_err(dev, "could not get usb3phy otg clock\n"); -+ return PTR_ERR(usb3phy->clk_otg); -+ } -+ -+ usb3phy->clk_ref = devm_clk_get(dev, "refclk-usb3otg"); -+ if (IS_ERR(usb3phy->clk_ref)) { -+ dev_err(dev, "could not get usb3phy ref clock\n"); -+ return PTR_ERR(usb3phy->clk_ref); -+ } -+ -+ usb3phy->u2por_rst = devm_reset_control_get(dev, "usb3phy-u2-por"); -+ if (IS_ERR(usb3phy->u2por_rst)) { -+ dev_err(dev, "no usb3phy-u2-por reset control found\n"); -+ return PTR_ERR(usb3phy->u2por_rst); -+ } -+ -+ usb3phy->u3por_rst = devm_reset_control_get(dev, "usb3phy-u3-por"); -+ if (IS_ERR(usb3phy->u3por_rst)) { -+ dev_err(dev, "no usb3phy-u3-por reset control found\n"); -+ return PTR_ERR(usb3phy->u3por_rst); -+ } -+ -+ usb3phy->pipe_rst = devm_reset_control_get(dev, "usb3phy-pipe-mac"); -+ if (IS_ERR(usb3phy->pipe_rst)) { -+ dev_err(dev, "no usb3phy_pipe_mac reset control found\n"); -+ return PTR_ERR(usb3phy->pipe_rst); -+ } -+ -+ usb3phy->utmi_rst = devm_reset_control_get(dev, "usb3phy-utmi-mac"); -+ if (IS_ERR(usb3phy->utmi_rst)) { -+ dev_err(dev, "no usb3phy-utmi-mac reset control found\n"); -+ return PTR_ERR(usb3phy->utmi_rst); -+ } -+ -+ usb3phy->pipe_apb_rst = devm_reset_control_get(dev, "usb3phy-pipe-apb"); -+ if (IS_ERR(usb3phy->pipe_apb_rst)) { -+ dev_err(dev, "no usb3phy-pipe-apb reset control found\n"); -+ return PTR_ERR(usb3phy->pipe_apb_rst); -+ } -+ -+ usb3phy->utmi_apb_rst = devm_reset_control_get(dev, "usb3phy-utmi-apb"); -+ if (IS_ERR(usb3phy->utmi_apb_rst)) { -+ dev_err(dev, "no usb3phy-utmi-apb reset control found\n"); -+ return PTR_ERR(usb3phy->utmi_apb_rst); -+ } -+ -+ usb3phy->ls_irq = of_irq_get_byname(dev->of_node, "linestate"); -+ if (usb3phy->ls_irq < 0) { -+ dev_err(dev, "no linestate irq provided\n"); -+ return usb3phy->ls_irq; -+ } -+ -+ ret = devm_request_threaded_irq(dev, usb3phy->ls_irq, NULL, rockchip_usb3phy_linestate_irq, -+ IRQF_ONESHOT, "rockchip_usb3phy_ls", usb3phy); -+ if (ret) { -+ dev_err(dev, "failed to request linestate irq handle\n"); -+ return ret; -+ } -+ -+ usb3phy->bvalid_irq = of_irq_get_byname(dev->of_node, "bvalid"); -+ if (usb3phy->bvalid_irq < 0) { -+ dev_err(dev, "no bvalid irq provided\n"); -+ return usb3phy->bvalid_irq; -+ } -+ -+ ret = devm_request_threaded_irq(dev, usb3phy->bvalid_irq, NULL, rockchip_usb3phy_bvalid_irq, -+ IRQF_ONESHOT, "rockchip_usb3phy_bvalid", usb3phy); -+ if (ret) { -+ dev_err(dev, "failed to request bvalid irq handle\n"); -+ return ret; -+ } -+ -+ usb3phy->id_irq = of_irq_get_byname(dev->of_node, "id"); -+ if (usb3phy->id_irq < 0) { -+ dev_err(dev, "no id irq provided\n"); -+ return usb3phy->id_irq; -+ } -+ -+ ret = devm_request_threaded_irq(dev, usb3phy->id_irq, NULL, rockchip_usb3phy_id_irq, -+ IRQF_ONESHOT, "rockchip_usb3phy-id", usb3phy); -+ if (ret) { -+ dev_err(dev, "failed to request id irq handle\n"); -+ return ret; -+ } -+ -+ usb3phy->rxdet_irq = of_irq_get_byname(dev->of_node, "rxdet"); -+ if (usb3phy->rxdet_irq < 0) { -+ dev_err(dev, "no rxdet irq provided\n"); -+ return usb3phy->rxdet_irq; -+ } -+ -+ ret = devm_request_threaded_irq(dev, usb3phy->rxdet_irq, NULL, rockchip_usb3phy_rxdet_irq, -+ IRQF_ONESHOT, "rockchip_usb3phy-rxdet", usb3phy); -+ if (ret) { -+ dev_err(dev, "failed to request rxdet irq handle\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int rockchip_usb3phy_exit(struct phy *phy) -+{ -+ struct rockchip_usb3phy_port *port = phy_get_drvdata(phy); -+ struct rockchip_usb3phy *usb3phy = dev_get_drvdata(phy->dev.parent); -+ -+ dev_dbg(usb3phy->dev, "usb3phy_shutdown\n"); -+ rockchip_usb3phy_reset(usb3phy, true, port->type); -+ -+ return 0; -+} -+ -+static const struct phy_ops rockchip_usb3phy_ops = { -+ .init = rockchip_usb3phy_init, -+ .exit = rockchip_usb3phy_exit, -+ .owner = THIS_MODULE, -+}; -+ -+static const struct regmap_config rockchip_usb3phy_utmi_port_regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ .max_register = 0x400, -+ .cache_type = REGCACHE_NONE, -+ .fast_io = true, -+ .name = "utmi-port", -+}; -+ -+static const struct regmap_config rockchip_usb3phy_pipe_port_regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ .max_register = 0x400, -+ .cache_type = REGCACHE_NONE, -+ .fast_io = true, -+ .name = "pipe-port", -+}; -+ -+static const struct regmap_config rockchip_usb3phy_regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ .max_register = 0x400, -+ .write_flag_mask = REG_WRITE_MASK, -+ .cache_type = REGCACHE_NONE, -+ .fast_io = true, -+}; -+ -+static int rockchip_usb3phy_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct device_node *child_np; -+ struct phy_provider *provider; -+ struct rockchip_usb3phy *usb3phy; -+ const struct regmap_config regmap_config = rockchip_usb3phy_regmap_config; -+ void __iomem *base; -+ int i, ret; -+ -+ dev_dbg(dev, "Probe usb3phy main block\n"); -+ usb3phy = devm_kzalloc(dev, sizeof(*usb3phy), GFP_KERNEL); -+ if (!usb3phy) -+ return -ENOMEM; -+ -+ ret = rockchip_usb3phy_parse_dt(usb3phy, dev); -+ if (ret) { -+ dev_err(dev, "parse dt failed %i\n", ret); -+ return ret; -+ } -+ -+ base = devm_of_iomap(dev, np, 0, NULL); -+ if (IS_ERR(base)) { -+ dev_err(dev, "failed port ioremap\n"); -+ return PTR_ERR(base); -+ } -+ -+ usb3phy->regmap = devm_regmap_init_mmio(dev, base, ®map_config); -+ if (IS_ERR(usb3phy->regmap)) { -+ dev_err(dev, "regmap init failed\n"); -+ return PTR_ERR(usb3phy->regmap); -+ } -+ -+ usb3phy->dev = dev; -+ platform_set_drvdata(pdev, usb3phy); -+ -+ /* place block in reset */ -+ reset_control_assert(usb3phy->pipe_rst); -+ reset_control_assert(usb3phy->utmi_rst); -+ reset_control_assert(usb3phy->u3por_rst); -+ reset_control_assert(usb3phy->u2por_rst); -+ reset_control_assert(usb3phy->pipe_apb_rst); -+ reset_control_assert(usb3phy->utmi_apb_rst); -+ -+ fsleep(20); -+ -+ /* take apb interface out of reset */ -+ reset_control_deassert(usb3phy->utmi_apb_rst); -+ reset_control_deassert(usb3phy->pipe_apb_rst); -+ -+ /* enable usb3phy rx detection to fix disconnection issues */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, -+ (USB3_RXDET_EN | (USB3_RXDET_EN << REG_WRITE_SHIFT))); -+ -+ dev_dbg(dev, "Completed usb3phy core probe\n"); -+ -+ /* probe the actual ports */ -+ i = 0; -+ for_each_available_child_of_node(np, child_np) { -+ const struct regmap_config *regmap_port_config; -+ struct rockchip_usb3phy_port *port = &usb3phy->ports[i]; -+ struct phy *phy; -+ -+ if (of_node_name_eq(child_np, "utmi-port")) { -+ port->type = USB3PHY_TYPE_USB2; -+ regmap_port_config = &rockchip_usb3phy_utmi_port_regmap_config; -+ } else if (of_node_name_eq(child_np, "pipe-port")) { -+ port->type = USB3PHY_TYPE_USB3; -+ regmap_port_config = &rockchip_usb3phy_pipe_port_regmap_config; -+ } else { -+ dev_err(dev, "unknown child node port type %s\n", child_np->name); -+ goto err_port; -+ } -+ -+ base = devm_of_iomap(dev, child_np, 0, NULL); -+ if (IS_ERR(base)) { -+ dev_err(dev, "failed port ioremap\n"); -+ ret = PTR_ERR(base); -+ goto err_port; -+ } -+ -+ port->regmap = devm_regmap_init_mmio(dev, base, regmap_port_config); -+ if (IS_ERR(port->regmap)) { -+ dev_err(dev, "regmap init failed\n"); -+ ret = PTR_ERR(port->regmap); -+ goto err_port; -+ } -+ -+ phy = devm_phy_create(dev, child_np, &rockchip_usb3phy_ops); -+ if (IS_ERR(phy)) { -+ dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n"); -+ ret = PTR_ERR(phy); -+ goto err_port; -+ } -+ -+ port->phy = phy; -+ phy_set_drvdata(port->phy, port); -+ -+ /* to prevent out of boundary */ -+ if (++i >= USB3PHY_TYPE_MAX) { -+ of_node_put(child_np); -+ break; -+ } -+ -+ dev_info(dev, "Completed usb3phy %s port init\n", child_np->name); -+ } -+ -+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); -+ return PTR_ERR_OR_ZERO(provider); -+ -+err_port: -+ of_node_put(child_np); -+ return ret; -+} -+ -+static const struct of_device_id rockchip_usb3phy_dt_ids[] = { -+ { .compatible = "rockchip,rk3328-usb3phy", }, -+ { /* sentinel */ } -+}; -+ -+MODULE_DEVICE_TABLE(of, rockchip_usb3phy_dt_ids); -+ -+static struct platform_driver rockchip_usb3phy_driver = { -+ .probe = rockchip_usb3phy_probe, -+ .driver = { -+ .name = "rockchip-usb3-phy", -+ .of_match_table = rockchip_usb3phy_dt_ids, -+ }, -+}; -+ -+module_platform_driver(rockchip_usb3phy_driver); -+ -+MODULE_AUTHOR("Peter Geis "); -+MODULE_DESCRIPTION("Rockchip Innosilicon USB3PHY driver"); -+MODULE_LICENSE("GPL"); --- -Armbian - diff --git a/patch/kernel/archive/rockchip64-7.0/rk3328-inno-usb3phy-driver.patch b/patch/kernel/archive/rockchip64-7.0/rk3328-inno-usb3phy-driver.patch deleted file mode 100644 index d7f0dac1eb72..000000000000 --- a/patch/kernel/archive/rockchip64-7.0/rk3328-inno-usb3phy-driver.patch +++ /dev/null @@ -1,1155 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paolo Sabatino -Date: Tue, 12 Aug 2025 20:08:01 +0200 -Subject: Add rockchip Innosilicon USB3 phy driver - -source: https://patchwork.kernel.org/project/linux-rockchip/cover/20250115012628.1035928-1-pgwipeout@gmail.com/ ---- - Documentation/devicetree/bindings/phy/rockchip,inno-usb3phy.yaml | 166 ++ - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 39 + - drivers/phy/rockchip/Kconfig | 10 + - drivers/phy/rockchip/Makefile | 1 + - drivers/phy/rockchip/phy-rockchip-inno-usb3.c | 870 ++++++++++ - 5 files changed, 1086 insertions(+) - -diff --git a/Documentation/devicetree/bindings/phy/rockchip,inno-usb3phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,inno-usb3phy.yaml -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/Documentation/devicetree/bindings/phy/rockchip,inno-usb3phy.yaml -@@ -0,0 +1,166 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/phy/rockchip,inno-usb3phy.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Rockchip USB 3.0 phy with Innosilicon IP block -+ -+maintainers: -+ - Heiko Stuebner -+ -+properties: -+ compatible: -+ enum: -+ - rockchip,rk3328-usb3phy -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ minItems: 3 -+ maxItems: 3 -+ -+ clock-names: -+ items: -+ - const: refclk-usb3otg -+ - const: usb3phy-otg -+ - const: usb3phy-pipe -+ -+ interrupts: -+ minItems: 4 -+ -+ interrupt-names: -+ items: -+ - const: bvalid -+ - const: id -+ - const: linestate -+ - const: rxdet -+ -+ resets: -+ minItems: 6 -+ -+ reset-names: -+ items: -+ - const: usb3phy-u2-por -+ - const: usb3phy-u3-por -+ - const: usb3phy-pipe-mac -+ - const: usb3phy-utmi-mac -+ - const: usb3phy-utmi-apb -+ - const: usb3phy-pipe-apb -+ -+ "#address-cells": -+ const: 2 -+ -+ "#size-cells": -+ const: 2 -+ -+ ranges: true -+ -+patternProperties: -+ -+ utmi-port@[0-9a-f]+$: -+ type: object -+ additionalProperties: false -+ -+ properties: -+ compatible: -+ enum: -+ - rockchip,rk3328-usb3phy-utmi -+ -+ reg: -+ maxItems: 1 -+ -+ "#phy-cells": -+ const: 0 -+ -+ phy-supply: -+ description: -+ Phandle to a regulator that provides power to VBUS. -+ See ./phy-bindings.txt for details. -+ -+ required: -+ - compatible -+ - reg -+ - "#phy-cells" -+ -+ pipe-port@[0-9a-f]+$: -+ type: object -+ additionalProperties: false -+ -+ properties: -+ compatible: -+ enum: -+ - rockchip,rk3328-usb3phy-pipe -+ -+ reg: -+ maxItems: 1 -+ -+ "#phy-cells": -+ const: 0 -+ -+ phy-supply: -+ description: -+ Phandle to a regulator that provides power to VBUS. -+ See ./phy-bindings.txt for details. -+ -+ required: -+ - compatible -+ - reg -+ - "#phy-cells" -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ - interrupts -+ - interrupt-names -+ - resets -+ - reset-names -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ soc { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ usb3phy: usb3-phy@ff460000 { -+ compatible = "rockchip,rk3328-usb3phy"; -+ reg = <0x0 0xff460000 0x0 0x10000>; -+ clocks = <&cru SCLK_REF_USB3OTG>, <&cru PCLK_USB3PHY_OTG>, <&cru PCLK_USB3PHY_PIPE>; -+ clock-names = "refclk-usb3otg", "usb3phy-otg", "usb3phy-pipe"; -+ interrupts = , , -+ , ; -+ interrupt-names = "bvalid", "id", "linestate", "rxdet"; -+ resets = <&cru SRST_USB3PHY_U2>, -+ <&cru SRST_USB3PHY_U3>, -+ <&cru SRST_USB3PHY_PIPE>, -+ <&cru SRST_USB3OTG_UTMI>, -+ <&cru SRST_USB3PHY_OTG_P>, -+ <&cru SRST_USB3PHY_PIPE_P>; -+ reset-names = "usb3phy-u2-por", "usb3phy-u3-por", -+ "usb3phy-pipe-mac", "usb3phy-utmi-mac", -+ "usb3phy-utmi-apb", "usb3phy-pipe-apb"; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ usb3phy_utmi: utmi-port@ff470000 { -+ compatible = "rockchip,rk3328-usb3phy-utmi"; -+ reg = <0x0 0xff470000 0x0 0x8000>; -+ #phy-cells = <0>; -+ }; -+ -+ usb3phy_pipe: pipe-port@ff478000 { -+ compatible = "rockchip,rk3328-usb3phy-pipe"; -+ reg = <0x0 0xff478000 0x0 0x8000>; -+ #phy-cells = <0>; -+ }; -+ }; -+ }; -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index 111111111111..222222222222 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -1055,6 +1055,43 @@ u2phy_host: host-port { - }; - }; - -+ usb3phy: usb3-phy@ff460000 { -+ compatible = "rockchip,rk3328-usb3phy"; -+ reg = <0x0 0xff460000 0x0 0x10000>; -+ clocks = <&cru SCLK_REF_USB3OTG>, <&cru PCLK_USB3PHY_OTG>, <&cru PCLK_USB3PHY_PIPE>; -+ clock-names = "refclk-usb3otg", "usb3phy-otg", "usb3phy-pipe"; -+ interrupts = , , -+ , ; -+ interrupt-names = "bvalid", "id", "linestate", "rxdet"; -+ resets = <&cru SRST_USB3PHY_U2>, -+ <&cru SRST_USB3PHY_U3>, -+ <&cru SRST_USB3PHY_PIPE>, -+ <&cru SRST_USB3OTG_UTMI>, -+ <&cru SRST_USB3PHY_OTG_P>, -+ <&cru SRST_USB3PHY_PIPE_P>; -+ reset-names = "usb3phy-u2-por", "usb3phy-u3-por", -+ "usb3phy-pipe-mac", "usb3phy-utmi-mac", -+ "usb3phy-utmi-apb", "usb3phy-pipe-apb"; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ status = "okay"; -+ -+ usb3phy_utmi: utmi-port@ff470000 { -+ compatible = "rockchip,rk3328-usb3phy-utmi"; -+ reg = <0x0 0xff470000 0x0 0x8000>; -+ #phy-cells = <0>; -+ status = "okay"; -+ }; -+ -+ usb3phy_pipe: pipe-port@ff478000 { -+ compatible = "rockchip,rk3328-usb3phy-pipe"; -+ reg = <0x0 0xff478000 0x0 0x8000>; -+ #phy-cells = <0>; -+ status = "okay"; -+ }; -+ }; -+ - sdmmc: mmc@ff500000 { - compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xff500000 0x0 0x4000>; -@@ -1221,6 +1258,8 @@ usbdrd3: usb@ff600000 { - resets = <&cru SRST_USB3OTG>; - reset-names = "usb3-otg"; - dr_mode = "otg"; -+ phys = <&usb3phy_utmi>, <&usb3phy_pipe>; -+ phy-names = "usb2-phy", "usb3-phy"; - phy_type = "utmi_wide"; - snps,dis-del-phy-power-chg-quirk; - snps,dis_enblslpm_quirk; -diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig -index 111111111111..222222222222 100644 ---- a/drivers/phy/rockchip/Kconfig -+++ b/drivers/phy/rockchip/Kconfig -@@ -48,6 +48,16 @@ config PHY_ROCKCHIP_INNO_USB2 - help - Support for Rockchip USB2.0 PHY with Innosilicon IP block. - -+config PHY_ROCKCHIP_INNO_USB3 -+ tristate "Rockchip INNO USB3PHY Driver" -+ depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF -+ depends on COMMON_CLK -+ depends on USB_SUPPORT -+ select GENERIC_PHY -+ select USB_COMMON -+ help -+ Support for Rockchip USB3.0 PHY with Innosilicon IP block. -+ - config PHY_ROCKCHIP_INNO_CSIDPHY - tristate "Rockchip Innosilicon MIPI CSI PHY driver" - depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF -diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile -index 111111111111..222222222222 100644 ---- a/drivers/phy/rockchip/Makefile -+++ b/drivers/phy/rockchip/Makefile -@@ -6,6 +6,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY) += phy-rockchip-inno-csidphy.o - obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o - obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o - obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o -+obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB3) += phy-rockchip-inno-usb3.o - obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o - obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o - obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_DCPHY) += phy-rockchip-samsung-dcphy.o -diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb3.c b/drivers/phy/rockchip/phy-rockchip-inno-usb3.c -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb3.c -@@ -0,0 +1,870 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+ -+/* -+ * phy-rockchip-inno-usb3.c - USB3 PHY based on Innosilicon IP as -+ * implemented on Rockchip rk3328. Tuning data magic bits are taken as is -+ * from the downstream driver. Downstream driver is located at: -+ * https://github.com/rockchip-linux/kernel/blob/240a5660d7c23841ccf7b7cc489078bf521b9802/drivers/phy/rockchip/phy-rockchip-inno-usb3.c -+ * -+ * Author: Peter Geis -+ * TODO: -+ * - Find the rest of the register names / definitions. -+ * - Implement pm functions. -+ * - Implement board specific tuning from dts. -+ * - Implement regulator control. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define REG_WRITE_MASK GENMASK(31, 16) -+#define REG_WRITE_SHIFT 16 -+#define DISABLE_BITS 0x0 -+ -+/* USB3PHY GRF Registers */ -+#define USB3PHY_WAKEUP_CON_REG 0x40 -+#define USB3PHY_WAKEUP_STAT_REG 0x44 -+#define USB3_LINESTATE_IRQ_EN BIT(0) -+#define USB3_RXDET_IRQ_EN BIT(1) -+#define USB3_BVALID_RISE_IRQ_EN BIT(2) -+#define USB3_BVALID_FALL_IRQ_EN BIT(3) -+#define USB3_BVALID_CLEAR_MASK GENMASK(3, 2) -+#define USB3_ID_RISE_IRQ_EN BIT(4) -+#define USB3_ID_FALL_IRQ_EN BIT(5) -+#define USB3_ID_CLEAR_MASK GENMASK(5, 4) -+#define USB3_RXDET_EN BIT(6) -+ -+/* PIPE registers */ -+/* 0x08 for SSC, default 0x0e */ -+#define UNKNOWN_PIPE_REG_000 0x000 -+#define UNKNOWN_SSC_000_MASK GENMASK(2, 1) -+#define UNKNOWN_SSC_000_ENABLE (0x00 << 1) -+ -+/* 0x83 for 24m, 0x01 for 25m, default 0x86 */ -+#define PIPE_REG_020 0x020 -+/* RX CDR multiplier high bits [7:6], as P, default 0x2, RX data rate = (2*refclk*P)/Q */ -+#define PIPE_RX_CDR_MULT_HIGH_MASK GENMASK(7, 6) -+/* TX PLL divider bits [4:0], as N, default 0x6, TX data rate = (2*refclk*M)/N */ -+#define PIPE_TX_PLL_DIV_MASK GENMASK(4, 0) -+ -+/* 0x71 for 24m, 0x64 for 25m, default 0x71 */ -+#define PIPE_REG_028 0x028 -+/* RX CDR multiplier low bits [7:0], as P, default 0x71, RX data rate = (2*refclk*P)/Q */ -+#define PIPE_RX_CDR_MULT_LOW_MASK GENMASK(7, 0) -+ -+/* 0x26 for 24m?, 0x21 for 25m, default 0x26 */ -+#define PIPE_REG_030 0x030 -+/* RX CDR divider bits [4:0], as Q, default 0x6, RX data rate = (2*refclk*P)/Q */ -+#define PIPE_RX_CDR_DIV_MASK GENMASK(4, 0) -+ -+/* 1'b1 Disable bandgap power, default 0x00 */ -+#define PIPE_REG_044 0x044 -+#define BANDGAP_POWER_DISABLE BIT(4) -+ -+/* 0xe0 for rx tune?, default 0xe1 */ -+#define PIPE_REG_060 0x060 -+#define PIPE_TX_DETECT_BYPASS_DEBUG BIT(4) /* enable to always force detection */ -+/* RX CTLE frequency bandwidth response tuning bits [1:0], default 0x1 */ -+#define PIPE_RX_CTLE_FREQ_BW_MASK GENMASK(1, 0) -+#define PIPE_RX_CTLE_FREQ_BW_TUNE 0x0 -+ -+/* default 0x49 */ -+#define PIPE_REG_064 0x064 -+/* RX equalizer tail current control bits [6:4], default 0x4 */ -+#define PIPE_RX_EQ_TAIL_CURR_MASK GENMASK(6, 4) -+ -+/* 0x08 for rx tune?, default 0x07 */ -+#define PIPE_REG_068 0x068 -+/* RX equalizer low frequency gain control bits [7:4], default 0x0 */ -+#define PIPE_RX_EQ_LOW_GAIN_MASK GENMASK(7, 4) -+#define PIPE_RX_EQ_LOW_GAIN_TUNE (0x1 << 4) -+/* RX CTLE gain tuning bits [3:0], higher = more gain default 0x7 */ -+#define PIPE_RX_CTLE_GAIN_MASK GENMASK(3, 0) -+#define PIPE_RX_CTLE_GAIN_TUNE 0x7 /* 0x5 lowest functional value, 0xf highest */ -+ -+/* RX ODT manual resistance config, higher = less resistance, depends on REG_1C4 BIT(5) set */ -+#define PIPE_REG_06C 0x06c -+/* RX ODT manual resistance high bits [3:0], default 0x0 */ -+#define PIPE_RX_ODT_RES_HIGH_MASK GENMASK(3, 0) -+#define PIPE_RX_ODT_RES_HIGH_TUNE 0xf -+ -+#define PIPE_REG_070 0x070 -+/* RX ODT manual resistance mid bits [7:0], default 0x03 */ -+#define PIPE_RX_ODT_RES_MID_MASK GENMASK(7, 0) -+#define PIPE_RX_ODT_RES_MID_TUNE 0xff -+ -+#define PIPE_REG_074 0x074 -+/* RX ODT manual resistance low bits [7:0], default 0xff */ -+#define PIPE_RX_ODT_RES_LOW_MASK GENMASK(7, 0) -+#define PIPE_RX_ODT_RES_LOW_TUNE 0xff -+ -+/* default 0x08 */ -+#define PIPE_REG_080 0x080 -+#define PIPE_TX_COMMON_MODE_DIS BIT(2) /* 1'b1 disable TX common type */ -+ -+/* default 0x33 */ -+#define PIPE_REG_088 0x088 -+#define PIPE_TX_DRIVER_PREEMP_EN BIT(4) /* 1'b1 enable pre-emphasis */ -+ -+/* default 0x18 */ -+#define PIPE_REG_0C0 0x0c0 -+#define PIPE_RX_CM_EN BIT(3) /* 1'b1 enable RX CM */ -+#define PIPE_TX_OBS_EN BIT(4) /* 1'b1 enable TX OBS */ -+ -+/* 0x12 for rx tune?, default 0x14 */ -+#define PIPE_REG_0C8 0x0c8 -+/* RX CDR charge pump current bits [3:1], default 0x2 */ -+#define PIPE_RX_CDR_CHG_PUMP_MASK GENMASK(3, 1) -+#define PIPE_RX_CDR_CHG_PUMP_TUNE (0x2 << 1) -+ -+/* 0x02 for 24m, 0x06 for 25m, default 0x06 */ -+#define UNKNOWN_PIPE_REG_108 0x108 -+#define UNKNOWN_REFCLK_108_24M 0x02 -+ -+/* 0x80 for 24m, default 0x00 */ -+#define UNKNOWN_PIPE_REG_10C 0x10c -+#define UNKNOWN_REFCLK_10C_24M BIT(7) -+ -+/* 0x01 for 24m, 0x00 for 25m, default 0x02 */ -+#define PIPE_REG_118 0x118 -+/* TX PLL multiplier high bits [3:0], as M, default 0x2, TX data rate = (2*refclk*M)/N */ -+#define PIPE_TX_PLL_MUL_HIGH_MASK GENMASK(3, 0) -+ -+/* 0x38 for 24m, 0x64 for 25m, default 0x71 */ -+#define PIPE_REG_11C 0x11c -+/* TX PLL multiplier low bits [7:0], as M, default 0x71, TX data rate = (2*refclk*M)/N */ -+#define PIPE_TX_PLL_MUL_LOW_MASK GENMASK(7, 0) -+ -+/* 0x0c for SSC, default 0x1c */ -+#define UNKNOWN_PIPE_REG_120 0x120 -+#define UNKNOWN_SSC_120_MASK BIT(4) -+#define UNKNOWN_SSC_120_ENABLE (0x0 << 4) -+ -+/* default 0x40 */ -+#define PIPE_REG_12C 0x12c -+#define PIPE_TX_PLL_ALWAYS_ON BIT(0) /* disable for PLL control by pipe_pd */ -+ -+/* 0x05 for rx tune, default 0x01 */ -+#define PIPE_REG_148 0x148 -+#define PIPE_RX_CHG_PUMP_DIV_2 BIT(2) /* RX CDR charge pump div/2, default 0 */ -+ -+/* 0x70 for rx tune, default 0x72 */ -+#define PIPE_REG_150 0x150 -+#define PIPE_TX_BIAS_EN BIT(6) /* 1'b1 Enable TX Bias */ -+/* RX CDR phase tracking speed bits [3:0], default 0x2 */ -+#define PIPE_RX_CDR_SPEED_MASK GENMASK(3, 0) -+#define PIPE_RX_CDR_SPEED_TUNE 0x00 -+ -+/* default 0xd4 */ -+#define PIPE_REG_160 -+/* RX common mode voltage strength bits [5:4], default 0x1 */ -+#define PIPE_RX_CDR_COM_VOLT_MASK GENMASK(5, 4) -+#define PIPE_RX_CDR_COM_VOLT_TUNE (0x1 << 4) -+ -+/* default 0x00 */ -+#define PIPE_REG_180 0x180 -+/* TX driver bias reference voltage bits [3:2], in mv */ -+#define PIPE_TX_BIAS_REF_VOLT_MASK GENMASK(3, 2) -+#define PIPE_TX_BIAS_REF_VOLT_200 (0x0 << 2) -+#define PIPE_TX_BIAS_REF_VOLT_175 (0x1 << 2) -+#define PIPE_TX_BIAS_REF_VOLT_225 (0x2 << 2) /* downstream 5.10 driver setting */ -+#define PIPE_TX_BIAS_REF_VOLT_250 (0x3 << 2) -+ -+/* default 0x01 */ -+#define PIPE_REG_1A8 0x1a8 -+#define PIPE_LDO_POWER_DIS BIT(4) /* 1'b1 Disable LDO Power */ -+ -+/* default 0x07 */ -+#define PIPE_REG_1AC 0x1ac -+/* TX driver output common voltage bits [5:4], in mv */ -+#define PIPE_TX_COMMON_VOLT_MASK GENMASK(5, 4) -+#define PIPE_TX_COMMON_VOLT_800 (0x0 << 4) -+#define PIPE_TX_COMMON_VOLT_750 (0x1 << 4) -+#define PIPE_TX_COMMON_VOLT_950 (0x2 << 4) -+#define PIPE_TX_COMMON_VOLT_1100 (0x3 << 4) -+ -+/* default 0xfb */ -+#define PIPE_REG_1B8 0x1b8 -+/* TX driver swing strength bits [7:4], range 0x0 to 0xf */ -+#define PIPE_TX_DRIVER_SWING_MASK GENMASK(7, 4) /* 0x2 lowest functional value */ -+/* TX driver pre-emphasis strength bits [1:0], default 0x3, enabled by REG 088 */ -+#define PIPE_TX_DRIVER_PREEMP_STR_MASK GENMASK(1, 0) -+ -+/* set to 0xf0 for rx tune?, default 0xd0 */ -+#define PIPE_REG_1C4 0x1c4 -+#define PIPE_RX_ODT_AUTO_DIS BIT(5) /* Disable RX ODT auto compensation */ -+#define PIPE_TX_ODT_AUTO_DIS BIT(3) /* Disable TX ODT auto compensation */ -+ -+/* UTMI registers */ -+/* 0x0f for utmi tune, default 0x09*/ -+#define UTMI_REG_030 0x030 -+/* {bits[2:0]=111}: always enable pre-emphasis */ -+#define UTMI_ENABLE_PRE_EMPH_MASK GENMASK(2, 0) -+#define UTMI_ENABLE_PRE_EMPH 0x07 -+ -+/* 0x41 for utmi tune, default 0x49 */ -+#define UTMI_REG_040 0x040 -+/* TX HS pre-emphasis strength bits [5:3], default 0x1*/ -+#define UTMI_TX_PRE_EMPH_STR_MASK GENMASK(5, 3) -+#define UTMI_TX_PRE_EMPH_WEAKEST (0x0 << 3) -+ -+/* set to 0xb5 for utmi tune, default 0xb5 */ -+#define UTMI_REG_11C 0x11c -+/* {bits[4:0]=10101}: odt 45ohm tuning */ -+#define UTMI_ODT_45_OHM_MASK GENMASK(4, 0) -+#define UTMI_ODT_45_OHM_TUNE 0x15 -+ -+enum rockchip_usb3phy_type { -+ USB3PHY_TYPE_USB2, -+ USB3PHY_TYPE_USB3, -+ USB3PHY_TYPE_MAX, -+}; -+ -+/** -+ * struct rockchip_usb3phy_port - usb-phy port data. -+ * @phy: port usb phy struct. -+ * @regmap: port regmap. -+ * @type: port usb phy type. -+ */ -+struct rockchip_usb3phy_port { -+ struct phy *phy; -+ struct regmap *regmap; -+ enum rockchip_usb3phy_type type; -+}; -+ -+struct rockchip_usb3phy { -+ struct device *dev; -+ struct regmap *regmap; -+ struct clk *clk_pipe; -+ struct clk *clk_otg; -+ struct clk *clk_ref; -+ struct reset_control *u3por_rst; -+ struct reset_control *u2por_rst; -+ struct reset_control *pipe_rst; -+ struct reset_control *utmi_rst; -+ struct reset_control *pipe_apb_rst; -+ struct reset_control *utmi_apb_rst; -+ struct rockchip_usb3phy_port ports[USB3PHY_TYPE_MAX]; -+ int bvalid_irq; -+ int id_irq; -+ int ls_irq; -+ int rxdet_irq; -+}; -+ -+struct usb3phy_config { -+ unsigned int reg; -+ unsigned int mask; -+ u8 def; -+}; -+ -+static const struct usb3phy_config rk3328_rx_config[] = { -+ { PIPE_REG_150, PIPE_RX_CDR_SPEED_MASK, PIPE_RX_CDR_SPEED_TUNE }, -+ { PIPE_REG_0C8, PIPE_RX_CDR_CHG_PUMP_MASK, PIPE_RX_CDR_CHG_PUMP_TUNE }, -+ { PIPE_REG_148, PIPE_RX_CHG_PUMP_DIV_2, PIPE_RX_CHG_PUMP_DIV_2 }, -+ { PIPE_REG_068, PIPE_RX_CTLE_GAIN_MASK, PIPE_RX_CTLE_GAIN_TUNE }, -+// { PIPE_REG_1C4, PIPE_RX_ODT_AUTO_DIS, PIPE_RX_ODT_AUTO_DIS }, -+ { PIPE_REG_070, PIPE_RX_ODT_RES_MID_MASK, PIPE_RX_ODT_RES_MID_TUNE }, -+ { PIPE_REG_06C, PIPE_RX_ODT_RES_HIGH_MASK, PIPE_RX_ODT_RES_HIGH_TUNE }, -+ { PIPE_REG_060, PIPE_RX_CTLE_FREQ_BW_MASK, PIPE_RX_CTLE_FREQ_BW_TUNE }, -+ { UNKNOWN_PIPE_REG_10C, UNKNOWN_REFCLK_10C_24M, UNKNOWN_REFCLK_10C_24M }, -+ { PIPE_REG_060, PIPE_RX_CTLE_FREQ_BW_MASK, PIPE_RX_CTLE_FREQ_BW_TUNE }, -+ { PIPE_REG_068, PIPE_RX_EQ_LOW_GAIN_MASK, PIPE_RX_EQ_LOW_GAIN_TUNE }, -+}; -+ -+static const struct usb3phy_config rk3328_tx_config[] = { -+ { PIPE_REG_180, PIPE_TX_BIAS_REF_VOLT_MASK, PIPE_TX_BIAS_REF_VOLT_250 }, -+}; -+ -+static const struct usb3phy_config rk3328_ssc_config[] = { -+ { UNKNOWN_PIPE_REG_000, UNKNOWN_SSC_000_MASK, UNKNOWN_SSC_000_ENABLE }, -+ { UNKNOWN_PIPE_REG_120, UNKNOWN_SSC_120_MASK, UNKNOWN_SSC_120_ENABLE }, -+}; -+ -+static const struct usb3phy_config rk3328_utmi_config[] = { -+ { UTMI_REG_030, UTMI_ENABLE_PRE_EMPH_MASK, UTMI_ENABLE_PRE_EMPH }, -+ { UTMI_REG_040, UTMI_TX_PRE_EMPH_STR_MASK, UTMI_TX_PRE_EMPH_WEAKEST }, -+ { UTMI_REG_11C, UTMI_ODT_45_OHM_MASK, UTMI_ODT_45_OHM_TUNE }, -+}; -+ -+static const struct usb3phy_config rk3328_pipe_pwr_en_config[] = { -+ { PIPE_REG_1A8, PIPE_LDO_POWER_DIS, DISABLE_BITS }, -+ { PIPE_REG_044, BANDGAP_POWER_DISABLE, DISABLE_BITS }, -+ { PIPE_REG_150, PIPE_TX_BIAS_EN, PIPE_TX_BIAS_EN }, -+ { PIPE_REG_080, PIPE_TX_COMMON_MODE_DIS, DISABLE_BITS }, -+ { PIPE_REG_0C0, PIPE_TX_OBS_EN, PIPE_TX_OBS_EN }, -+ { PIPE_REG_0C0, PIPE_RX_CM_EN, PIPE_RX_CM_EN }, -+}; -+ -+static int rockchip_usb3phy_reset(struct rockchip_usb3phy *usb3phy, -+ bool reset, enum rockchip_usb3phy_type type) -+{ -+ if (reset) { -+ if (type == USB3PHY_TYPE_USB2) { -+ clk_disable_unprepare(usb3phy->clk_otg); -+ reset_control_assert(usb3phy->utmi_rst); -+ reset_control_assert(usb3phy->u2por_rst); -+ } -+ if (type == USB3PHY_TYPE_USB3) { -+ clk_disable_unprepare(usb3phy->clk_pipe); -+ reset_control_assert(usb3phy->pipe_rst); -+ reset_control_assert(usb3phy->u3por_rst); -+ } -+ } else { -+ if (type == USB3PHY_TYPE_USB2) { -+ reset_control_deassert(usb3phy->u2por_rst); -+ fsleep(1000); -+ clk_prepare_enable(usb3phy->clk_otg); -+ fsleep(500); -+ reset_control_deassert(usb3phy->utmi_rst); -+ fsleep(100); -+ } -+ if (type == USB3PHY_TYPE_USB3) { -+ reset_control_deassert(usb3phy->u3por_rst); -+ fsleep(500); -+ clk_prepare_enable(usb3phy->clk_pipe); -+ fsleep(1000); -+ reset_control_deassert(usb3phy->pipe_rst); -+ fsleep(100); -+ } -+ } -+ return 0; -+} -+ -+static irqreturn_t rockchip_usb3phy_linestate_irq(int irq, void *data) -+{ -+ struct rockchip_usb3phy *usb3phy = data; -+ int tmp; -+ -+ /* check if the interrupt is enabled */ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, &tmp); -+ if (!(tmp & USB3_LINESTATE_IRQ_EN)) { -+ dev_warn(usb3phy->dev, "invalid linestate irq received\n"); -+ return IRQ_NONE; -+ } -+ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, &tmp); -+ if (tmp & USB3_LINESTATE_IRQ_EN) -+ dev_dbg_ratelimited(usb3phy->dev, "linestate irq received\n"); -+ -+ /* clear the interrupt */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, USB3_LINESTATE_IRQ_EN); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t rockchip_usb3phy_bvalid_irq(int irq, void *data) -+{ -+ struct rockchip_usb3phy *usb3phy = data; -+ int tmp; -+ -+ /* check if the interrupt is enabled */ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, &tmp); -+ if (!((tmp & USB3_BVALID_FALL_IRQ_EN) | (tmp & USB3_BVALID_RISE_IRQ_EN))) { -+ dev_warn_ratelimited(usb3phy->dev, "invalid bvalid irq received\n"); -+ return IRQ_NONE; -+ } -+ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, &tmp); -+ if (tmp & USB3_BVALID_FALL_IRQ_EN) -+ dev_dbg(usb3phy->dev, "bvalid falling irq received\n"); -+ if (tmp & USB3_BVALID_RISE_IRQ_EN) -+ dev_dbg(usb3phy->dev, "bvalid rising irq received\n"); -+ -+ /* clear the interrupt */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, USB3_BVALID_CLEAR_MASK); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t rockchip_usb3phy_id_irq(int irq, void *data) -+{ -+ struct rockchip_usb3phy *usb3phy = data; -+ int tmp; -+ -+ /* check if the interrupt is enabled */ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, &tmp); -+ if (!((tmp & USB3_ID_FALL_IRQ_EN) | (tmp & USB3_ID_RISE_IRQ_EN))) { -+ dev_warn(usb3phy->dev, "invalid id irq received\n"); -+ return IRQ_NONE; -+ } -+ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, &tmp); -+ if (tmp & USB3_ID_FALL_IRQ_EN) -+ dev_dbg(usb3phy->dev, "id falling irq received\n"); -+ if (tmp & USB3_ID_RISE_IRQ_EN) -+ dev_dbg(usb3phy->dev, "id rising irq received\n"); -+ -+ /* clear the interrupt */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, USB3_ID_CLEAR_MASK); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t rockchip_usb3phy_rxdet_irq(int irq, void *data) -+{ -+ struct rockchip_usb3phy *usb3phy = data; -+ int tmp; -+ -+ /* check if the interrupt is enabled */ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, &tmp); -+ if (!(tmp & USB3_RXDET_IRQ_EN)) { -+ dev_warn(usb3phy->dev, "invalid rxdet irq received\n"); -+ return IRQ_NONE; -+ } -+ -+ regmap_read(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, &tmp); -+ if (tmp & USB3_RXDET_IRQ_EN) -+ dev_dbg_ratelimited(usb3phy->dev, "rxdet irq received\n"); -+ -+ /* clear the interrupt */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_STAT_REG, USB3_RXDET_IRQ_EN); -+ -+ return IRQ_HANDLED; -+} -+ -+static int rockchip_usb3phy_bulk_update(struct rockchip_usb3phy *usb3phy, struct regmap *regmap, -+ const struct usb3phy_config *config, unsigned int size) -+{ -+ unsigned int i, val, tmp; -+ int ret = 0; -+ -+ for (i = 0; i < size; i++) { -+ ret = regmap_read(regmap, config[i].reg, &val); -+ if (ret < 0) { -+ dev_err(usb3phy->dev, "failed to read addr: 0x%02x\n", config[i].reg); -+ return ret; -+ } -+ tmp = val & ~config[i].mask; -+ tmp |= config[i].def; -+ dev_dbg(usb3phy->dev, "write: 0x%03x old: 0x%02x new: 0x%02x\n", -+ config[i].reg, val, tmp); -+ ret = regmap_write(regmap, config[i].reg, tmp); -+ if (ret < 0) { -+ dev_err(usb3phy->dev, "failed to write addr: 0x%02x\n", config[i].reg); -+ return ret; -+ } -+ } -+ -+ return ret; -+} -+ -+static int rockchip_usb3phy_calc_rate(struct rockchip_usb3phy *usb3phy, struct regmap *regmap) -+{ -+ long rate; -+ unsigned int mul, div, target = (5000000000 / 100000); -+ -+ rate = clk_get_rate(usb3phy->clk_ref) / 100000; -+ if (rate < 0) { -+ dev_err(usb3phy->dev, "failed to get refclk, %ld\n", rate); -+ return rate; -+ /* lowest possible supported clock is 4.8MHZ, highest rk3328 can do is 1.6GHZ */ -+ } else if ((rate < 48) | (rate > 16000)) { -+ goto error; -+ } -+ -+ for (div = 1; div < 32; div++) { -+ for (mul = 1; mul < 1024; mul++) { -+ if (((2 * rate * mul) / div) == target) -+ goto done; -+ if (((2 * rate * mul) / div) > target) -+ break; -+ } -+ } -+ -+error: -+ dev_err(usb3phy->dev, "invalid refclock rate, %ld\n", rate * 100000); -+ return -EINVAL; -+ -+done: -+ dev_dbg(usb3phy->dev, "refclk rate mul: %x div: %x rate: %ld\n", mul, div, (rate * 100000)); -+ -+ regmap_write(regmap, PIPE_REG_020, (mul >> 2) & PIPE_RX_CDR_MULT_HIGH_MASK); -+ regmap_write(regmap, PIPE_REG_020, div & PIPE_TX_PLL_DIV_MASK); -+ regmap_write(regmap, PIPE_REG_028, mul & PIPE_RX_CDR_MULT_LOW_MASK); -+ regmap_write(regmap, PIPE_REG_030, div & PIPE_RX_CDR_DIV_MASK); -+ regmap_write(regmap, PIPE_REG_118, (mul >> 8) & PIPE_TX_PLL_MUL_HIGH_MASK); -+ regmap_write(regmap, PIPE_REG_11C, mul & PIPE_TX_PLL_MUL_LOW_MASK); -+ -+ return 0; -+} -+ -+static int rockchip_usb3phy_init(struct phy *phy) -+{ -+ struct rockchip_usb3phy_port *port = phy_get_drvdata(phy); -+ struct rockchip_usb3phy *usb3phy = dev_get_drvdata(phy->dev.parent); -+ int tmp, ret; -+ -+ dev_warn(usb3phy->dev, "usb3phy_init %s\n", dev_name(&phy->dev)); -+ clk_prepare_enable(usb3phy->clk_ref); -+ rockchip_usb3phy_reset(usb3phy, false, port->type); -+ -+ if (port->type == USB3PHY_TYPE_USB2) { -+ /* -+ * "For RK3328 SoC, pre-emphasis and pre-emphasis strength must be -+ * written as one fixed value. The ODT 45ohm value should be tuned -+ * for different boards to adjust HS eye height." -+ */ -+ dev_dbg(usb3phy->dev, "tuning UTMI\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, rk3328_utmi_config, -+ ARRAY_SIZE(rk3328_utmi_config)); -+ } -+ -+ if (port->type == USB3PHY_TYPE_USB3) { -+ /* Enable interrupts */ -+ tmp = (USB3_LINESTATE_IRQ_EN | USB3_ID_FALL_IRQ_EN | USB3_ID_RISE_IRQ_EN | -+ USB3_RXDET_IRQ_EN | USB3_BVALID_RISE_IRQ_EN | USB3_BVALID_FALL_IRQ_EN); -+ tmp |= (tmp << REG_WRITE_SHIFT); -+ -+ ret = regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, tmp); -+ if (ret < 0) { -+ /* interrupt write determines if we have write access */ -+ dev_err(usb3phy->dev, "failed to write interrupts\n"); -+ return ret; -+ } -+ -+ /* Configure for 24M ref clk */ -+ dev_dbg(usb3phy->dev, "setting pipe for 24M refclk\n"); -+ if (rockchip_usb3phy_calc_rate(usb3phy, usb3phy->regmap)) -+ return -EINVAL; -+ -+ /* Enable SSC */ -+ udelay(3); -+ dev_dbg(usb3phy->dev, "setting pipe for SSC\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, rk3328_ssc_config, -+ ARRAY_SIZE(rk3328_ssc_config)); -+ -+ /* "Tuning RX for compliance RJTL test" */ -+ dev_dbg(usb3phy->dev, "setting pipe for RX tuning\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, rk3328_rx_config, -+ ARRAY_SIZE(rk3328_rx_config)); -+ if (ret) -+ return ret; -+ -+ /* -+ * "Tuning TX to increase the bias current used in TX driver and RX EQ, -+ * it can also increase the voltage of LFPS." -+ */ -+ dev_dbg(usb3phy->dev, "setting pipe for TX tuning\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, -+ rk3328_tx_config, ARRAY_SIZE(rk3328_tx_config)); -+ -+ /* Power up the pipe */ -+ dev_dbg(usb3phy->dev, "setting pipe power on\n"); -+ ret = rockchip_usb3phy_bulk_update(usb3phy, port->regmap, rk3328_pipe_pwr_en_config, -+ ARRAY_SIZE(rk3328_pipe_pwr_en_config)); -+ } -+ -+ return 0; -+} -+ -+static int rockchip_usb3phy_parse_dt(struct rockchip_usb3phy *usb3phy, struct device *dev) -+{ -+ int ret; -+ -+ usb3phy->clk_pipe = devm_clk_get(dev, "usb3phy-pipe"); -+ if (IS_ERR(usb3phy->clk_pipe)) { -+ dev_err(dev, "could not get usb3phy pipe clock\n"); -+ return PTR_ERR(usb3phy->clk_pipe); -+ } -+ -+ usb3phy->clk_otg = devm_clk_get(dev, "usb3phy-otg"); -+ if (IS_ERR(usb3phy->clk_otg)) { -+ dev_err(dev, "could not get usb3phy otg clock\n"); -+ return PTR_ERR(usb3phy->clk_otg); -+ } -+ -+ usb3phy->clk_ref = devm_clk_get(dev, "refclk-usb3otg"); -+ if (IS_ERR(usb3phy->clk_ref)) { -+ dev_err(dev, "could not get usb3phy ref clock\n"); -+ return PTR_ERR(usb3phy->clk_ref); -+ } -+ -+ usb3phy->u2por_rst = devm_reset_control_get(dev, "usb3phy-u2-por"); -+ if (IS_ERR(usb3phy->u2por_rst)) { -+ dev_err(dev, "no usb3phy-u2-por reset control found\n"); -+ return PTR_ERR(usb3phy->u2por_rst); -+ } -+ -+ usb3phy->u3por_rst = devm_reset_control_get(dev, "usb3phy-u3-por"); -+ if (IS_ERR(usb3phy->u3por_rst)) { -+ dev_err(dev, "no usb3phy-u3-por reset control found\n"); -+ return PTR_ERR(usb3phy->u3por_rst); -+ } -+ -+ usb3phy->pipe_rst = devm_reset_control_get(dev, "usb3phy-pipe-mac"); -+ if (IS_ERR(usb3phy->pipe_rst)) { -+ dev_err(dev, "no usb3phy_pipe_mac reset control found\n"); -+ return PTR_ERR(usb3phy->pipe_rst); -+ } -+ -+ usb3phy->utmi_rst = devm_reset_control_get(dev, "usb3phy-utmi-mac"); -+ if (IS_ERR(usb3phy->utmi_rst)) { -+ dev_err(dev, "no usb3phy-utmi-mac reset control found\n"); -+ return PTR_ERR(usb3phy->utmi_rst); -+ } -+ -+ usb3phy->pipe_apb_rst = devm_reset_control_get(dev, "usb3phy-pipe-apb"); -+ if (IS_ERR(usb3phy->pipe_apb_rst)) { -+ dev_err(dev, "no usb3phy-pipe-apb reset control found\n"); -+ return PTR_ERR(usb3phy->pipe_apb_rst); -+ } -+ -+ usb3phy->utmi_apb_rst = devm_reset_control_get(dev, "usb3phy-utmi-apb"); -+ if (IS_ERR(usb3phy->utmi_apb_rst)) { -+ dev_err(dev, "no usb3phy-utmi-apb reset control found\n"); -+ return PTR_ERR(usb3phy->utmi_apb_rst); -+ } -+ -+ usb3phy->ls_irq = of_irq_get_byname(dev->of_node, "linestate"); -+ if (usb3phy->ls_irq < 0) { -+ dev_err(dev, "no linestate irq provided\n"); -+ return usb3phy->ls_irq; -+ } -+ -+ ret = devm_request_threaded_irq(dev, usb3phy->ls_irq, NULL, rockchip_usb3phy_linestate_irq, -+ IRQF_ONESHOT, "rockchip_usb3phy_ls", usb3phy); -+ if (ret) { -+ dev_err(dev, "failed to request linestate irq handle\n"); -+ return ret; -+ } -+ -+ usb3phy->bvalid_irq = of_irq_get_byname(dev->of_node, "bvalid"); -+ if (usb3phy->bvalid_irq < 0) { -+ dev_err(dev, "no bvalid irq provided\n"); -+ return usb3phy->bvalid_irq; -+ } -+ -+ ret = devm_request_threaded_irq(dev, usb3phy->bvalid_irq, NULL, rockchip_usb3phy_bvalid_irq, -+ IRQF_ONESHOT, "rockchip_usb3phy_bvalid", usb3phy); -+ if (ret) { -+ dev_err(dev, "failed to request bvalid irq handle\n"); -+ return ret; -+ } -+ -+ usb3phy->id_irq = of_irq_get_byname(dev->of_node, "id"); -+ if (usb3phy->id_irq < 0) { -+ dev_err(dev, "no id irq provided\n"); -+ return usb3phy->id_irq; -+ } -+ -+ ret = devm_request_threaded_irq(dev, usb3phy->id_irq, NULL, rockchip_usb3phy_id_irq, -+ IRQF_ONESHOT, "rockchip_usb3phy-id", usb3phy); -+ if (ret) { -+ dev_err(dev, "failed to request id irq handle\n"); -+ return ret; -+ } -+ -+ usb3phy->rxdet_irq = of_irq_get_byname(dev->of_node, "rxdet"); -+ if (usb3phy->rxdet_irq < 0) { -+ dev_err(dev, "no rxdet irq provided\n"); -+ return usb3phy->rxdet_irq; -+ } -+ -+ ret = devm_request_threaded_irq(dev, usb3phy->rxdet_irq, NULL, rockchip_usb3phy_rxdet_irq, -+ IRQF_ONESHOT, "rockchip_usb3phy-rxdet", usb3phy); -+ if (ret) { -+ dev_err(dev, "failed to request rxdet irq handle\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int rockchip_usb3phy_exit(struct phy *phy) -+{ -+ struct rockchip_usb3phy_port *port = phy_get_drvdata(phy); -+ struct rockchip_usb3phy *usb3phy = dev_get_drvdata(phy->dev.parent); -+ -+ dev_dbg(usb3phy->dev, "usb3phy_shutdown\n"); -+ rockchip_usb3phy_reset(usb3phy, true, port->type); -+ -+ return 0; -+} -+ -+static const struct phy_ops rockchip_usb3phy_ops = { -+ .init = rockchip_usb3phy_init, -+ .exit = rockchip_usb3phy_exit, -+ .owner = THIS_MODULE, -+}; -+ -+static const struct regmap_config rockchip_usb3phy_utmi_port_regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ .max_register = 0x400, -+ .cache_type = REGCACHE_NONE, -+ .fast_io = true, -+ .name = "utmi-port", -+}; -+ -+static const struct regmap_config rockchip_usb3phy_pipe_port_regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ .max_register = 0x400, -+ .cache_type = REGCACHE_NONE, -+ .fast_io = true, -+ .name = "pipe-port", -+}; -+ -+static const struct regmap_config rockchip_usb3phy_regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ .max_register = 0x400, -+ .write_flag_mask = REG_WRITE_MASK, -+ .cache_type = REGCACHE_NONE, -+ .fast_io = true, -+}; -+ -+static int rockchip_usb3phy_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct device_node *child_np; -+ struct phy_provider *provider; -+ struct rockchip_usb3phy *usb3phy; -+ const struct regmap_config regmap_config = rockchip_usb3phy_regmap_config; -+ void __iomem *base; -+ int i, ret; -+ -+ dev_dbg(dev, "Probe usb3phy main block\n"); -+ usb3phy = devm_kzalloc(dev, sizeof(*usb3phy), GFP_KERNEL); -+ if (!usb3phy) -+ return -ENOMEM; -+ -+ ret = rockchip_usb3phy_parse_dt(usb3phy, dev); -+ if (ret) { -+ dev_err(dev, "parse dt failed %i\n", ret); -+ return ret; -+ } -+ -+ base = devm_of_iomap(dev, np, 0, NULL); -+ if (IS_ERR(base)) { -+ dev_err(dev, "failed port ioremap\n"); -+ return PTR_ERR(base); -+ } -+ -+ usb3phy->regmap = devm_regmap_init_mmio(dev, base, ®map_config); -+ if (IS_ERR(usb3phy->regmap)) { -+ dev_err(dev, "regmap init failed\n"); -+ return PTR_ERR(usb3phy->regmap); -+ } -+ -+ usb3phy->dev = dev; -+ platform_set_drvdata(pdev, usb3phy); -+ -+ /* place block in reset */ -+ reset_control_assert(usb3phy->pipe_rst); -+ reset_control_assert(usb3phy->utmi_rst); -+ reset_control_assert(usb3phy->u3por_rst); -+ reset_control_assert(usb3phy->u2por_rst); -+ reset_control_assert(usb3phy->pipe_apb_rst); -+ reset_control_assert(usb3phy->utmi_apb_rst); -+ -+ fsleep(20); -+ -+ /* take apb interface out of reset */ -+ reset_control_deassert(usb3phy->utmi_apb_rst); -+ reset_control_deassert(usb3phy->pipe_apb_rst); -+ -+ /* enable usb3phy rx detection to fix disconnection issues */ -+ regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG, -+ (USB3_RXDET_EN | (USB3_RXDET_EN << REG_WRITE_SHIFT))); -+ -+ dev_dbg(dev, "Completed usb3phy core probe\n"); -+ -+ /* probe the actual ports */ -+ i = 0; -+ for_each_available_child_of_node(np, child_np) { -+ const struct regmap_config *regmap_port_config; -+ struct rockchip_usb3phy_port *port = &usb3phy->ports[i]; -+ struct phy *phy; -+ -+ if (of_node_name_eq(child_np, "utmi-port")) { -+ port->type = USB3PHY_TYPE_USB2; -+ regmap_port_config = &rockchip_usb3phy_utmi_port_regmap_config; -+ } else if (of_node_name_eq(child_np, "pipe-port")) { -+ port->type = USB3PHY_TYPE_USB3; -+ regmap_port_config = &rockchip_usb3phy_pipe_port_regmap_config; -+ } else { -+ dev_err(dev, "unknown child node port type %s\n", child_np->name); -+ goto err_port; -+ } -+ -+ base = devm_of_iomap(dev, child_np, 0, NULL); -+ if (IS_ERR(base)) { -+ dev_err(dev, "failed port ioremap\n"); -+ ret = PTR_ERR(base); -+ goto err_port; -+ } -+ -+ port->regmap = devm_regmap_init_mmio(dev, base, regmap_port_config); -+ if (IS_ERR(port->regmap)) { -+ dev_err(dev, "regmap init failed\n"); -+ ret = PTR_ERR(port->regmap); -+ goto err_port; -+ } -+ -+ phy = devm_phy_create(dev, child_np, &rockchip_usb3phy_ops); -+ if (IS_ERR(phy)) { -+ dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n"); -+ ret = PTR_ERR(phy); -+ goto err_port; -+ } -+ -+ port->phy = phy; -+ phy_set_drvdata(port->phy, port); -+ -+ /* to prevent out of boundary */ -+ if (++i >= USB3PHY_TYPE_MAX) { -+ of_node_put(child_np); -+ break; -+ } -+ -+ dev_info(dev, "Completed usb3phy %s port init\n", child_np->name); -+ } -+ -+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); -+ return PTR_ERR_OR_ZERO(provider); -+ -+err_port: -+ of_node_put(child_np); -+ return ret; -+} -+ -+static const struct of_device_id rockchip_usb3phy_dt_ids[] = { -+ { .compatible = "rockchip,rk3328-usb3phy", }, -+ { /* sentinel */ } -+}; -+ -+MODULE_DEVICE_TABLE(of, rockchip_usb3phy_dt_ids); -+ -+static struct platform_driver rockchip_usb3phy_driver = { -+ .probe = rockchip_usb3phy_probe, -+ .driver = { -+ .name = "rockchip-usb3-phy", -+ .of_match_table = rockchip_usb3phy_dt_ids, -+ }, -+}; -+ -+module_platform_driver(rockchip_usb3phy_driver); -+ -+MODULE_AUTHOR("Peter Geis "); -+MODULE_DESCRIPTION("Rockchip Innosilicon USB3PHY driver"); -+MODULE_LICENSE("GPL"); --- -Armbian - From 338770b1cc8a3c2f8215509e3cf0057483a84a04 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Thu, 5 Feb 2026 18:19:26 +0100 Subject: [PATCH 31/43] rockchip64: enable SCTP module Signed-off-by: MichaIng --- config/kernel/linux-rockchip64-current.config | 1 + config/kernel/linux-rockchip64-edge.config | 1 + 2 files changed, 2 insertions(+) diff --git a/config/kernel/linux-rockchip64-current.config b/config/kernel/linux-rockchip64-current.config index db8e62a7040a..5e1eb26d285b 100644 --- a/config/kernel/linux-rockchip64-current.config +++ b/config/kernel/linux-rockchip64-current.config @@ -298,6 +298,7 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m CONFIG_NETFILTER_XT_MATCH_TCPMSS=m CONFIG_NETFILTER_XT_MATCH_TIME=m CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SCTP=m CONFIG_IP_SET=m CONFIG_IP_SET_BITMAP_IP=m CONFIG_IP_SET_BITMAP_IPMAC=m diff --git a/config/kernel/linux-rockchip64-edge.config b/config/kernel/linux-rockchip64-edge.config index 5987cfa7ad0d..1cae7af329bf 100644 --- a/config/kernel/linux-rockchip64-edge.config +++ b/config/kernel/linux-rockchip64-edge.config @@ -297,6 +297,7 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m CONFIG_NETFILTER_XT_MATCH_TCPMSS=m CONFIG_NETFILTER_XT_MATCH_TIME=m CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SCTP=m CONFIG_IP_SET=m CONFIG_IP_SET_BITMAP_IP=m CONFIG_IP_SET_BITMAP_IPMAC=m From 981b29d1cc9969dd0233402af6e5a8dfb446e563 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 17 Feb 2026 14:13:43 +0100 Subject: [PATCH 32/43] rock5b: raise eMMC compatibility as done for ROCK 5A https://github.com/armbian/linux-rockchip/commit/7628960 Everything is wired the same way, and mainline defines the same pinctl, only on vendor it is missing: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi#n368 Signed-off-by: MichaIng --- .../board-rock5b-fix-emmc.patch | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 patch/kernel/rk35xx-vendor-6.1/board-rock5b-fix-emmc.patch diff --git a/patch/kernel/rk35xx-vendor-6.1/board-rock5b-fix-emmc.patch b/patch/kernel/rk35xx-vendor-6.1/board-rock5b-fix-emmc.patch new file mode 100644 index 000000000000..70bf47d18641 --- /dev/null +++ b/patch/kernel/rk35xx-vendor-6.1/board-rock5b-fix-emmc.patch @@ -0,0 +1,24 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +index 6dcfc6d46b9d5..659d372a5d703 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -324,6 +324,10 @@ &dfi { + status = "okay"; + }; + ++&emmc_data_strobe { ++ rockchip,pins = <2 RK_PA2 1 &pcfg_pull_down>; ++}; ++ + &i2c1 { + status = "okay"; + pinctrl-names = "default"; +@@ -485,6 +489,8 @@ &sdhci { + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + mmc-hs200-1_8v; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_rstnout &emmc_bus8 &emmc_clk &emmc_cmd &emmc_data_strobe>; + status = "okay"; + }; + From 71bc0fa8010c41d0d58a75ed76b33e1042ae0bf2 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 17 Feb 2026 18:05:36 +0100 Subject: [PATCH 33/43] driver: rk805-pinctl: define modalias That way, it can be autoloaded. Otherwise, e.g. LEDs on ROCK64 do not work unless manually loading that driver. Signed-off-by: MichaIng --- .../archive/rockchip64-6.18/drv-rk805-add-modalias.patch | 9 +++++++++ .../archive/rockchip64-7.0/drv-rk805-add-modalias.patch | 9 +++++++++ 2 files changed, 18 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.18/drv-rk805-add-modalias.patch create mode 100644 patch/kernel/archive/rockchip64-7.0/drv-rk805-add-modalias.patch diff --git a/patch/kernel/archive/rockchip64-6.18/drv-rk805-add-modalias.patch b/patch/kernel/archive/rockchip64-6.18/drv-rk805-add-modalias.patch new file mode 100644 index 000000000000..d38ed70cb342 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/drv-rk805-add-modalias.patch @@ -0,0 +1,9 @@ +diff --git a/drivers/pinctrl/pinctrl-rk805.c b/drivers/pinctrl/pinctrl-rk805.c +index 22f576337faa9..694a47d95e171 100644 +--- a/drivers/pinctrl/pinctrl-rk805.c ++++ b/drivers/pinctrl/pinctrl-rk805.c +@@ -700,3 +700,4 @@ MODULE_DESCRIPTION("RK805 pin control and GPIO driver"); + MODULE_AUTHOR("Xu Shengfei "); + MODULE_AUTHOR("Joseph Chen "); + MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:rk805-pinctrl"); diff --git a/patch/kernel/archive/rockchip64-7.0/drv-rk805-add-modalias.patch b/patch/kernel/archive/rockchip64-7.0/drv-rk805-add-modalias.patch new file mode 100644 index 000000000000..d38ed70cb342 --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/drv-rk805-add-modalias.patch @@ -0,0 +1,9 @@ +diff --git a/drivers/pinctrl/pinctrl-rk805.c b/drivers/pinctrl/pinctrl-rk805.c +index 22f576337faa9..694a47d95e171 100644 +--- a/drivers/pinctrl/pinctrl-rk805.c ++++ b/drivers/pinctrl/pinctrl-rk805.c +@@ -700,3 +700,4 @@ MODULE_DESCRIPTION("RK805 pin control and GPIO driver"); + MODULE_AUTHOR("Xu Shengfei "); + MODULE_AUTHOR("Joseph Chen "); + MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:rk805-pinctrl"); From fd90e1062a5101314bdee070c7e76018334303e0 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 22 Feb 2026 18:40:09 +0100 Subject: [PATCH 34/43] deb: remove ancient /boot/.next flag Not needed anymore for any device or kernel version we support. Signed-off-by: MichaIng --- lib/functions/compilation/kernel-debs.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/functions/compilation/kernel-debs.sh b/lib/functions/compilation/kernel-debs.sh index 74b43ef8dcbd..ea840ddd62a7 100644 --- a/lib/functions/compilation/kernel-debs.sh +++ b/lib/functions/compilation/kernel-debs.sh @@ -300,7 +300,6 @@ function kernel_package_callback_linux_image() { # @TODO: only if u-boot, only for postinst. Gotta find a hook scheme for these... if [[ "${script}" == "postinst" ]]; then cat <<- HOOK_FOR_LINK_TO_LAST_INSTALLED_KERNEL # image_name="${NAME_KERNEL}", above - touch /boot/.next if is_boot_dev_vfat; then echo "Armbian: FAT32 /boot: move last-installed kernel to '$image_name'..." mv -v /${installed_image_path} /boot/${image_name} From 3bed86b7729773155ce929aa454a21d6d4dfe789 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 22 Feb 2026 16:52:35 +0100 Subject: [PATCH 35/43] config: enforce xz-compressed kernel modules Signed-off-by: MichaIng --- lib/functions/compilation/armbian-kernel.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/functions/compilation/armbian-kernel.sh b/lib/functions/compilation/armbian-kernel.sh index 8f21009d28df..29086f3dc034 100644 --- a/lib/functions/compilation/armbian-kernel.sh +++ b/lib/functions/compilation/armbian-kernel.sh @@ -597,6 +597,23 @@ function armbian_kernel_config__enable_ntsync() { fi } +# Enforce xz-compressed kernel modules +function armbian_kernel_config__enforce_modules_xz_compression() { + opts_n+=('MODULE_COMPRESS_NONE') # main switch for Linux >=6.0 and <6.12 + opts_y+=('MODULE_COMPRESS') # main switch for Linux <6.0 and >=6.12 + opts_n+=('MODULE_COMPRESS_GZIP') + opts_n+=('MODULE_COMPRESS_ZSTD') + opts_y+=('MODULE_COMPRESS_XZ') + opts_y+=('MODULE_COMPRESS_ALL') # for Linux >=6.12 to compress at "make modules_install" + # in-kernel decompression to not rely on userland doing this + # Fails on Rockchip vendor kernel with error 6/ENXIO, despite CONFIG_XZ_DEC CONFIG_XZ_DEC_* CONFIG_DECOMPRESS_XZ all on + if [[ ${BRANCH} == 'vendor' ]]; then + opts_n+=('MODULE_DECOMPRESS') + else + opts_y+=('MODULE_DECOMPRESS') + fi +} + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Kernel Configuration Helpers # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ From 1323cd0a321475f49d96e2088a8697106ef7a36a Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 31 Dec 2024 16:49:52 +0700 Subject: [PATCH 36/43] rk35xx-vendor: enable bcmdhd SDIO support for Orange Pi 5 Max and Ultra WiFi support Signed-off-by: MichaIng --- config/kernel/linux-rk35xx-vendor.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/kernel/linux-rk35xx-vendor.config b/config/kernel/linux-rk35xx-vendor.config index ceb964f1ee7a..2b6b5c771655 100644 --- a/config/kernel/linux-rk35xx-vendor.config +++ b/config/kernel/linux-rk35xx-vendor.config @@ -889,7 +889,7 @@ CONFIG_RTL8852BS=m CONFIG_WL_ROCKCHIP=y CONFIG_WIFI_BUILD_MODULE=y CONFIG_AP6XXX=m -CONFIG_BCMDHD_PCIE=y +CONFIG_BCMDHD_SDIO=y CONFIG_BCMDHD_FW_PATH="/lib/firmware/ap6275p/fw_bcmdhd.bin" CONFIG_BCMDHD_NVRAM_PATH="/lib/firmware/ap6275p/nvram.txt" CONFIG_RTL8723DS=m From 9f08ba591d8d3bade06d446781ac72e0c6e9e8e3 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 12 Jan 2025 05:40:53 +0100 Subject: [PATCH 37/43] ethernet: move reset delays from PHY to MAC for some boards In case of Orange Pi 3B v1.1: All other differences between the (functional) vendor kernel device tree and mainline kernel have been tested, as well as defining a more precise "compatible" entry for the PHY. Also raising the reset delays to match the vendor kernel values did not work. Only reverting to old way of defining reset delays in MAC instead of PHY solved the RTL8211F Ethernet of this board. Same change helped for ROCK 3B and Orange Pi 3 LTS, which use the same RTL8211F chip, or the pin-compatible YT8531. `https://dietpi.com/forum/t/22129` `https://github.com/MichaIng/DietPi/issues/7327` `https://github.com/MichaIng/DietPi/issues/7490` `https://github.com/MichaIng/DietPi/issues/7905` Signed-off-by: MichaIng --- .../board-orangepi3b-v1.1-fix-ethernet.patch | 47 +++++++++++++++++++ .../board-orangepi3b-v1.1-fix-ethernet.patch | 47 +++++++++++++++++++ .../board-orangepi3b-v1.1-fix-ethernet.patch | 47 +++++++++++++++++++ .../dt/sun50i-h6-orangepi-3-lts.dts | 13 +++-- .../001-Add-board-OrangePi-3-LTS.patch | 15 +++--- 5 files changed, 154 insertions(+), 15 deletions(-) create mode 100644 patch/kernel/archive/rockchip64-6.12/board-orangepi3b-v1.1-fix-ethernet.patch create mode 100644 patch/kernel/archive/rockchip64-6.18/board-orangepi3b-v1.1-fix-ethernet.patch create mode 100644 patch/kernel/archive/rockchip64-7.0/board-orangepi3b-v1.1-fix-ethernet.patch diff --git a/patch/kernel/archive/rockchip64-6.12/board-orangepi3b-v1.1-fix-ethernet.patch b/patch/kernel/archive/rockchip64-6.12/board-orangepi3b-v1.1-fix-ethernet.patch new file mode 100644 index 000000000000..a8e092dd092c --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/board-orangepi3b-v1.1-fix-ethernet.patch @@ -0,0 +1,47 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts +index 074e93bd4b85b..f28c40f003be0 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts +@@ -15,6 +15,9 @@ &pmu_io_domains { + + &gmac1 { + phy-handle = <&rgmii_phy1>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 50000 200000>; ++ snps,reset-gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + +@@ -22,8 +25,5 @@ &mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; +- reset-assert-us = <20000>; +- reset-deassert-us = <50000>; +- reset-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts b/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts +index 3d0c1ccfaa796..0c80a36977b78 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts +@@ -211,6 +211,9 @@ &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus + &gmac1m1_clkinout>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 50000 150000>; ++ snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + +@@ -526,9 +529,6 @@ &mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; +- reset-assert-us = <20000>; +- reset-deassert-us = <50000>; +- reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + }; + }; + diff --git a/patch/kernel/archive/rockchip64-6.18/board-orangepi3b-v1.1-fix-ethernet.patch b/patch/kernel/archive/rockchip64-6.18/board-orangepi3b-v1.1-fix-ethernet.patch new file mode 100644 index 000000000000..a8e092dd092c --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/board-orangepi3b-v1.1-fix-ethernet.patch @@ -0,0 +1,47 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts +index 074e93bd4b85b..f28c40f003be0 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts +@@ -15,6 +15,9 @@ &pmu_io_domains { + + &gmac1 { + phy-handle = <&rgmii_phy1>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 50000 200000>; ++ snps,reset-gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + +@@ -22,8 +25,5 @@ &mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; +- reset-assert-us = <20000>; +- reset-deassert-us = <50000>; +- reset-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts b/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts +index 3d0c1ccfaa796..0c80a36977b78 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts +@@ -211,6 +211,9 @@ &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus + &gmac1m1_clkinout>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 50000 150000>; ++ snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + +@@ -526,9 +529,6 @@ &mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; +- reset-assert-us = <20000>; +- reset-deassert-us = <50000>; +- reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + }; + }; + diff --git a/patch/kernel/archive/rockchip64-7.0/board-orangepi3b-v1.1-fix-ethernet.patch b/patch/kernel/archive/rockchip64-7.0/board-orangepi3b-v1.1-fix-ethernet.patch new file mode 100644 index 000000000000..a8e092dd092c --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/board-orangepi3b-v1.1-fix-ethernet.patch @@ -0,0 +1,47 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts +index 074e93bd4b85b..f28c40f003be0 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts +@@ -15,6 +15,9 @@ &pmu_io_domains { + + &gmac1 { + phy-handle = <&rgmii_phy1>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 50000 200000>; ++ snps,reset-gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + +@@ -22,8 +25,5 @@ &mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; +- reset-assert-us = <20000>; +- reset-deassert-us = <50000>; +- reset-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; + }; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts b/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts +index 3d0c1ccfaa796..0c80a36977b78 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts +@@ -211,6 +211,9 @@ &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus + &gmac1m1_clkinout>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 50000 150000>; ++ snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + +@@ -526,9 +529,6 @@ &mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; +- reset-assert-us = <20000>; +- reset-deassert-us = <50000>; +- reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + }; + }; + diff --git a/patch/kernel/archive/sunxi-6.12/dt/sun50i-h6-orangepi-3-lts.dts b/patch/kernel/archive/sunxi-6.12/dt/sun50i-h6-orangepi-3-lts.dts index ba678a2223b4..5549c3d02780 100644 --- a/patch/kernel/archive/sunxi-6.12/dt/sun50i-h6-orangepi-3-lts.dts +++ b/patch/kernel/archive/sunxi-6.12/dt/sun50i-h6-orangepi-3-lts.dts @@ -157,10 +157,13 @@ status = "okay"; pinctrl-0 = <&ext_rgmii_pins>; pinctrl-names = "default"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <&ext_rgmii_phy>; - allwinner,tx-delay-ps = <700>; - allwinner,rx-delay-ps = <1700>; + allwinner,tx-delay-ps = <300>; + allwinner,rx-delay-ps = <200>; + snps,reset-active-low; + snps,reset-delays-us = <10000 100000>; + snps,reset-gpio = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */ }; &gpu { @@ -194,10 +197,6 @@ ext_rgmii_phy: ethernet-phy@1 { compatible = "ethernet-phy-ieee802.3-c22"; reg = <1>; - - reset-gpios = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */ - reset-assert-us = <15000>; - reset-deassert-us = <40000>; }; }; diff --git a/patch/u-boot/v2026.01/board_orangepi3-lts/001-Add-board-OrangePi-3-LTS.patch b/patch/u-boot/v2026.01/board_orangepi3-lts/001-Add-board-OrangePi-3-LTS.patch index 49bd6d05cec9..17295efeaa15 100644 --- a/patch/u-boot/v2026.01/board_orangepi3-lts/001-Add-board-OrangePi-3-LTS.patch +++ b/patch/u-boot/v2026.01/board_orangepi3-lts/001-Add-board-OrangePi-3-LTS.patch @@ -27,7 +27,7 @@ new file mode 100644 index 00000000000..5291792b3f2 --- /dev/null +++ b/arch/arm/dts/sun50i-h6-orangepi-3-lts.dts -@@ -0,0 +1,392 @@ +@@ -0,0 +1,391 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2019 OndÅ™ej Jirman +// Copyright (C) 2023 Jernej Skrabec @@ -172,10 +172,13 @@ index 00000000000..5291792b3f2 + status = "okay"; + pinctrl-0 = <&ext_rgmii_pins>; + pinctrl-names = "default"; -+ phy-mode = "rgmii"; ++ phy-mode = "rgmii-id"; + phy-handle = <&ext_rgmii_phy>; -+ allwinner,tx-delay-ps = <700>; -+ allwinner,rx-delay-ps = <1700>; ++ allwinner,tx-delay-ps = <300>; ++ allwinner,rx-delay-ps = <200>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <10000 100000>; ++ snps,reset-gpio = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */ +}; + +&gpu { @@ -197,10 +200,6 @@ index 00000000000..5291792b3f2 + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; -+ -+ reset-gpios = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */ -+ reset-assert-us = <15000>; -+ reset-deassert-us = <40000>; + }; +}; + From 887a10c24e123f3598fffb2d6dc2f6938ad90625 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 16 Sep 2025 02:19:51 +0200 Subject: [PATCH 38/43] u-boot: add global support for Btrfs and setexpr including the btrsubvol for manging Btrfs subvolumes, and "setexpr fmt" sub-command. Signed-off-by: MichaIng --- lib/functions/compilation/uboot.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/functions/compilation/uboot.sh b/lib/functions/compilation/uboot.sh index ee7fc0247fc3..adfeccb3b31a 100644 --- a/lib/functions/compilation/uboot.sh +++ b/lib/functions/compilation/uboot.sh @@ -134,6 +134,14 @@ function compile_uboot_target() { # armbian specifics u-boot settings; configure the version so UART boot logs show exactly what's in there [[ -f .config ]] && sed -i "s/CONFIG_LOCALVERSION=\"\"/CONFIG_LOCALVERSION=\"_armbian-${artifact_version}\"/g" .config [[ -f .config ]] && sed -i 's/CONFIG_LOCALVERSION_AUTO=.*/# CONFIG_LOCALVERSION_AUTO is not set/g' .config + + display_alert "Adding Btrfs support to U-Boot incl. btrsubvol command" "CONFIG_CMD_BTRFS=y for ${target}" 'info' + grep -q 'CONFIG_CMD_BTRFS=' .config && run_host_command_logged sed -i '/CONFIG_CMD_BTRFS=/c\CONFIG_CMD_BTRFS=y' .config || run_host_command_logged echo 'CONFIG_CMD_BTRFS=y' '>> .config' + + display_alert "Adding setexpr command support to U-Boot incl. fmt sub-command" "CONFIG_CMD_SETEXPR_FMT=y for ${target}" 'info' + grep -q 'CONFIG_REGEX=' .config && run_host_command_logged sed -i '/CONFIG_REGEX=/c\CONFIG_REGEX=y' .config || run_host_command_logged echo 'CONFIG_REGEX=y' '>> .config' + grep -q 'CONFIG_CMD_SETEXPR=' .config && run_host_command_logged sed -i '/CONFIG_CMD_SETEXPR=/c\CONFIG_CMD_SETEXPR=y' .config || run_host_command_logged echo 'CONFIG_CMD_SETEXPR=y' '>> .config' + grep -q 'CONFIG_CMD_SETEXPR_FMT=' .config && run_host_command_logged sed -i '/CONFIG_CMD_SETEXPR_FMT=/c\CONFIG_CMD_SETEXPR_FMT=y' .config || run_host_command_logged echo 'CONFIG_CMD_SETEXPR_FMT=y' '>> .config' else display_alert "scripts/config found" "u-boot ${version} $BOOTCONFIG ${target_make}" "debug" @@ -152,6 +160,14 @@ function compile_uboot_target() { # Include Armbian version so UART bootlogs are drastically more useful run_host_command_logged ./scripts/config --disable "LOCALVERSION_AUTO" run_host_command_logged ./scripts/config --set-str "LOCALVERSION" "_armbian-${artifact_version}" # crazy quotes! + + display_alert "Adding U-Boot Btrfs support incl. btrsubvol command" "CONFIG_CMD_BTRFS=y for ${target}" 'info' + run_host_command_logged scripts/config --enable CONFIG_CMD_BTRFS + + display_alert "Adding setexpr command support to U-Boot incl. fmt sub-command" "CONFIG_CMD_SETEXPR_FMT=y for ${target}" 'info' + run_host_command_logged scripts/config --enable CONFIG_REGEX + run_host_command_logged scripts/config --enable CONFIG_CMD_SETEXPR + run_host_command_logged scripts/config --enable CONFIG_CMD_SETEXPR_FMT fi if [[ "${UBOOT_DEBUGGING}" == "yes" ]]; then From c3362026a4118eeefc4dc21340e0f5dae8a39cf8 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 22 Feb 2026 16:01:21 +0100 Subject: [PATCH 39/43] firmware: remove AYN Odin 2 firmware It has a size of >40 MiB for a device we do not support. Signed-off-by: MichaIng --- lib/functions/compilation/packages/firmware-deb.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/functions/compilation/packages/firmware-deb.sh b/lib/functions/compilation/packages/firmware-deb.sh index 8dd8886b51bb..37d8eeb92453 100644 --- a/lib/functions/compilation/packages/firmware-deb.sh +++ b/lib/functions/compilation/packages/firmware-deb.sh @@ -50,6 +50,9 @@ function compile_firmware() { # Armbian firmware; this overwrites anything in the mainline firmware repo (if that was included, in the full version only) run_host_command_logged git -C "${SRC}/cache/sources/armbian-firmware-git" archive --format=tar "${armbian_firmware_git_sha1}" "|" tar -C "${fw_temp_dir}/${fw_dir}/lib/firmware/" -xf - + # Remove huge AYN Odin 2 firmware, 170 MiB for a handheld device we do not support + run_host_command_logged rm -R "${fw_temp_dir}/${fw_dir}"/lib/firmware/qcom/sm8550 + # Show the size of the firmware directory in a tree if debugging if [[ "${SHOW_DEBUG}" == "yes" ]]; then run_host_command_logged tree -C --du -h -L 1 "${fw_temp_dir}/${fw_dir}"/lib/firmware "|| true" # do not fail From 51d798ee0694961cf579531fc7f22499863b60e3 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 19 Jul 2025 01:06:18 +0200 Subject: [PATCH 40/43] rk3308: add overlays to toggle USB-C mode It is in peripheral mode by default. Signed-off-by: MichaIng --- patch/kernel/archive/rockchip64-6.12/overlay/Makefile | 3 ++- .../{rk3308-otg-host.dtso => rk3308-usb-c-host.dtso} | 3 --- .../rockchip64-6.12/overlay/rk3308-usb-c-otg.dtso | 10 ++++++++++ patch/kernel/archive/rockchip64-6.18/overlay/Makefile | 3 ++- .../{rk3308-otg-host.dtso => rk3308-usb-c-host.dtso} | 3 --- .../rockchip64-6.18/overlay/rk3308-usb-c-otg.dtso | 10 ++++++++++ patch/kernel/archive/rockchip64-7.0/overlay/Makefile | 3 ++- .../{rk3308-otg-host.dtso => rk3308-usb-c-host.dtso} | 3 --- .../rockchip64-7.0/overlay/rk3308-usb-c-otg.dtso | 10 ++++++++++ 9 files changed, 36 insertions(+), 12 deletions(-) rename patch/kernel/archive/rockchip64-6.12/overlay/{rk3308-otg-host.dtso => rk3308-usb-c-host.dtso} (71%) create mode 100644 patch/kernel/archive/rockchip64-6.12/overlay/rk3308-usb-c-otg.dtso rename patch/kernel/archive/rockchip64-6.18/overlay/{rk3308-otg-host.dtso => rk3308-usb-c-host.dtso} (71%) create mode 100644 patch/kernel/archive/rockchip64-6.18/overlay/rk3308-usb-c-otg.dtso rename patch/kernel/archive/rockchip64-7.0/overlay/{rk3308-otg-host.dtso => rk3308-usb-c-host.dtso} (71%) create mode 100644 patch/kernel/archive/rockchip64-7.0/overlay/rk3308-usb-c-otg.dtso diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/Makefile b/patch/kernel/archive/rockchip64-6.12/overlay/Makefile index dc711248f609..4d71fffdaa3e 100644 --- a/patch/kernel/archive/rockchip64-6.12/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-6.12/overlay/Makefile @@ -3,7 +3,8 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ hinlink-h88k-240x135-lcd.dtbo \ rk35xx-radxa-zero-3w-ext-ant.dtbo \ rk3308-uart1.dtbo rk3308-uart2.dtbo rk3308-uart3.dtbo \ - rk3308-otg-host.dtbo \ + rk3308-usb-c-host.dtbo \ + rk3308-usb-c-otg.dtbo \ rk3308-s0-ext-antenna.dtbo \ rk3308-b@1.3ghz.dtbo \ rk3308-bs.dtbo rk3308-bs@1.3ghz.dtbo \ diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/rk3308-otg-host.dtso b/patch/kernel/archive/rockchip64-6.12/overlay/rk3308-usb-c-host.dtso similarity index 71% rename from patch/kernel/archive/rockchip64-6.12/overlay/rk3308-otg-host.dtso rename to patch/kernel/archive/rockchip64-6.12/overlay/rk3308-usb-c-host.dtso index c5ae9ab3cfd1..b483737af69b 100644 --- a/patch/kernel/archive/rockchip64-6.12/overlay/rk3308-otg-host.dtso +++ b/patch/kernel/archive/rockchip64-6.12/overlay/rk3308-usb-c-host.dtso @@ -1,8 +1,5 @@ -//Configure the OTG USB port as a USB host - /dts-v1/; /plugin/; - / { fragment@0 { target = <&usb20_otg>; diff --git a/patch/kernel/archive/rockchip64-6.12/overlay/rk3308-usb-c-otg.dtso b/patch/kernel/archive/rockchip64-6.12/overlay/rk3308-usb-c-otg.dtso new file mode 100644 index 000000000000..a8a264a53c46 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.12/overlay/rk3308-usb-c-otg.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "otg"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/Makefile b/patch/kernel/archive/rockchip64-6.18/overlay/Makefile index 92c22820c46d..75faa8296514 100644 --- a/patch/kernel/archive/rockchip64-6.18/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-6.18/overlay/Makefile @@ -3,7 +3,8 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ hinlink-h88k-240x135-lcd.dtbo \ rk35xx-radxa-zero-3w-ext-ant.dtbo \ rk3308-uart1.dtbo rk3308-uart2.dtbo rk3308-uart3.dtbo \ - rk3308-otg-host.dtbo \ + rk3308-usb-c-host.dtbo \ + rk3308-usb-c-otg.dtbo \ rk3308-s0-ext-antenna.dtbo \ rk3308-b@1.3ghz.dtbo \ rk3308-bs.dtbo rk3308-bs@1.3ghz.dtbo \ diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/rk3308-otg-host.dtso b/patch/kernel/archive/rockchip64-6.18/overlay/rk3308-usb-c-host.dtso similarity index 71% rename from patch/kernel/archive/rockchip64-6.18/overlay/rk3308-otg-host.dtso rename to patch/kernel/archive/rockchip64-6.18/overlay/rk3308-usb-c-host.dtso index c5ae9ab3cfd1..b483737af69b 100644 --- a/patch/kernel/archive/rockchip64-6.18/overlay/rk3308-otg-host.dtso +++ b/patch/kernel/archive/rockchip64-6.18/overlay/rk3308-usb-c-host.dtso @@ -1,8 +1,5 @@ -//Configure the OTG USB port as a USB host - /dts-v1/; /plugin/; - / { fragment@0 { target = <&usb20_otg>; diff --git a/patch/kernel/archive/rockchip64-6.18/overlay/rk3308-usb-c-otg.dtso b/patch/kernel/archive/rockchip64-6.18/overlay/rk3308-usb-c-otg.dtso new file mode 100644 index 000000000000..a8a264a53c46 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.18/overlay/rk3308-usb-c-otg.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "otg"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/Makefile b/patch/kernel/archive/rockchip64-7.0/overlay/Makefile index 92c22820c46d..75faa8296514 100644 --- a/patch/kernel/archive/rockchip64-7.0/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-7.0/overlay/Makefile @@ -3,7 +3,8 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ hinlink-h88k-240x135-lcd.dtbo \ rk35xx-radxa-zero-3w-ext-ant.dtbo \ rk3308-uart1.dtbo rk3308-uart2.dtbo rk3308-uart3.dtbo \ - rk3308-otg-host.dtbo \ + rk3308-usb-c-host.dtbo \ + rk3308-usb-c-otg.dtbo \ rk3308-s0-ext-antenna.dtbo \ rk3308-b@1.3ghz.dtbo \ rk3308-bs.dtbo rk3308-bs@1.3ghz.dtbo \ diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/rk3308-otg-host.dtso b/patch/kernel/archive/rockchip64-7.0/overlay/rk3308-usb-c-host.dtso similarity index 71% rename from patch/kernel/archive/rockchip64-7.0/overlay/rk3308-otg-host.dtso rename to patch/kernel/archive/rockchip64-7.0/overlay/rk3308-usb-c-host.dtso index c5ae9ab3cfd1..b483737af69b 100644 --- a/patch/kernel/archive/rockchip64-7.0/overlay/rk3308-otg-host.dtso +++ b/patch/kernel/archive/rockchip64-7.0/overlay/rk3308-usb-c-host.dtso @@ -1,8 +1,5 @@ -//Configure the OTG USB port as a USB host - /dts-v1/; /plugin/; - / { fragment@0 { target = <&usb20_otg>; diff --git a/patch/kernel/archive/rockchip64-7.0/overlay/rk3308-usb-c-otg.dtso b/patch/kernel/archive/rockchip64-7.0/overlay/rk3308-usb-c-otg.dtso new file mode 100644 index 000000000000..a8a264a53c46 --- /dev/null +++ b/patch/kernel/archive/rockchip64-7.0/overlay/rk3308-usb-c-otg.dtso @@ -0,0 +1,10 @@ +/dts-v1/; +/plugin/; +/ { + fragment@0 { + target = <&usb20_otg>; + __overlay__ { + dr_mode = "otg"; + }; + }; +}; From 02fee1eb7536e0ae5d6c280f0849d8744bb5f184 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 17:39:29 +0100 Subject: [PATCH 41/43] dt: rk3588s-nanopi-m6: add explicit rx_delay=0 for rgmii-rxid gmac1 (#10) It causes a kernel error if missing, despite being ignored with rgmii-rxid mode: - https://github.com/torvalds/linux/blob/b10d56b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c#L1276-L1285 - https://github.com/torvalds/linux/blob/b10d56b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c#L1433-L1438 Signed-off-by: MichaIng --- patch/kernel/archive/rockchip64-6.18/dt/rk3588s-nanopi-m6.dts | 1 + patch/kernel/archive/rockchip64-7.0/dt/rk3588s-nanopi-m6.dts | 1 + 2 files changed, 2 insertions(+) diff --git a/patch/kernel/archive/rockchip64-6.18/dt/rk3588s-nanopi-m6.dts b/patch/kernel/archive/rockchip64-6.18/dt/rk3588s-nanopi-m6.dts index 30c10ce8d955..9ae646a0707a 100644 --- a/patch/kernel/archive/rockchip64-6.18/dt/rk3588s-nanopi-m6.dts +++ b/patch/kernel/archive/rockchip64-6.18/dt/rk3588s-nanopi-m6.dts @@ -257,6 +257,7 @@ &gmac1_rgmii_clk &gmac1_rgmii_bus>; pinctrl-names = "default"; + rx_delay = <0x00>; tx_delay = <0x42>; status = "okay"; }; diff --git a/patch/kernel/archive/rockchip64-7.0/dt/rk3588s-nanopi-m6.dts b/patch/kernel/archive/rockchip64-7.0/dt/rk3588s-nanopi-m6.dts index 30c10ce8d955..9ae646a0707a 100644 --- a/patch/kernel/archive/rockchip64-7.0/dt/rk3588s-nanopi-m6.dts +++ b/patch/kernel/archive/rockchip64-7.0/dt/rk3588s-nanopi-m6.dts @@ -257,6 +257,7 @@ &gmac1_rgmii_clk &gmac1_rgmii_bus>; pinctrl-names = "default"; + rx_delay = <0x00>; tx_delay = <0x42>; status = "okay"; }; From 23688afa4dc37ab6167afa62d82dbb1771b49f9e Mon Sep 17 00:00:00 2001 From: MichaIng Date: Thu, 2 Jan 2025 17:15:40 +0700 Subject: [PATCH 42/43] nanopineo: remove LED patch conflicting with upstream Upstream kernel defines the exact same LEDs already. having both defined leads to unusable LED sysfs nodes: https://github.com/MichaIng/DietPi/issues/5401 Signed-off-by: MichaIng --- ...3-nanopi-neo-Add-regulator-leds-mmc2.patch | 22 +------------------ ...3-nanopi-neo-Add-regulator-leds-mmc2.patch | 22 +------------------ ...3-nanopi-neo-Add-regulator-leds-mmc2.patch | 22 +------------------ 3 files changed, 3 insertions(+), 63 deletions(-) diff --git a/patch/kernel/archive/sunxi-6.12/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch b/patch/kernel/archive/sunxi-6.12/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch index 628fa13bfd79..705931ce7c5a 100644 --- a/patch/kernel/archive/sunxi-6.12/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch +++ b/patch/kernel/archive/sunxi-6.12/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch @@ -11,31 +11,11 @@ diff --git a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts b/arch/arm/boot index 111111111111..222222222222 100644 --- a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts +++ b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts -@@ -49,6 +49,63 @@ / { +@@ -49,6 +49,43 @@ / { aliases { ethernet0 = &emac; }; + -+ /* Warning: sunxi-5.18: -+ * The leds node is present in the sun8i-h3-nanopi.dtsi file -+ * You will have to fix this situation yourself -+ */ -+ leds { -+ compatible = "gpio-leds"; -+ -+ pwr { -+ label = "nanopi:red:pwr"; -+ gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */ -+ linux,default-trigger = "default-on"; -+ }; -+ -+ status { -+ label = "nanopi:green:status"; -+ gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; /* PA10 */ -+ linux,default-trigger = "heartbeat"; -+ }; -+ }; -+ + vdd_cpux: gpio-regulator { + compatible = "regulator-gpio"; + pinctrl-names = "default"; diff --git a/patch/kernel/archive/sunxi-6.18/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch b/patch/kernel/archive/sunxi-6.18/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch index 628fa13bfd79..705931ce7c5a 100644 --- a/patch/kernel/archive/sunxi-6.18/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch +++ b/patch/kernel/archive/sunxi-6.18/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch @@ -11,31 +11,11 @@ diff --git a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts b/arch/arm/boot index 111111111111..222222222222 100644 --- a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts +++ b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts -@@ -49,6 +49,63 @@ / { +@@ -49,6 +49,43 @@ / { aliases { ethernet0 = &emac; }; + -+ /* Warning: sunxi-5.18: -+ * The leds node is present in the sun8i-h3-nanopi.dtsi file -+ * You will have to fix this situation yourself -+ */ -+ leds { -+ compatible = "gpio-leds"; -+ -+ pwr { -+ label = "nanopi:red:pwr"; -+ gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */ -+ linux,default-trigger = "default-on"; -+ }; -+ -+ status { -+ label = "nanopi:green:status"; -+ gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; /* PA10 */ -+ linux,default-trigger = "heartbeat"; -+ }; -+ }; -+ + vdd_cpux: gpio-regulator { + compatible = "regulator-gpio"; + pinctrl-names = "default"; diff --git a/patch/kernel/archive/sunxi-7.0/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch b/patch/kernel/archive/sunxi-7.0/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch index 628fa13bfd79..705931ce7c5a 100644 --- a/patch/kernel/archive/sunxi-7.0/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch +++ b/patch/kernel/archive/sunxi-7.0/patches.armbian/arm-dts-h3-nanopi-neo-Add-regulator-leds-mmc2.patch @@ -11,31 +11,11 @@ diff --git a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts b/arch/arm/boot index 111111111111..222222222222 100644 --- a/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts +++ b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts -@@ -49,6 +49,63 @@ / { +@@ -49,6 +49,43 @@ / { aliases { ethernet0 = &emac; }; + -+ /* Warning: sunxi-5.18: -+ * The leds node is present in the sun8i-h3-nanopi.dtsi file -+ * You will have to fix this situation yourself -+ */ -+ leds { -+ compatible = "gpio-leds"; -+ -+ pwr { -+ label = "nanopi:red:pwr"; -+ gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */ -+ linux,default-trigger = "default-on"; -+ }; -+ -+ status { -+ label = "nanopi:green:status"; -+ gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; /* PA10 */ -+ linux,default-trigger = "heartbeat"; -+ }; -+ }; -+ + vdd_cpux: gpio-regulator { + compatible = "regulator-gpio"; + pinctrl-names = "default"; From 0913afac735c2f4797ff0685e0ead940caaef6e4 Mon Sep 17 00:00:00 2001 From: ImgBotApp Date: Fri, 17 Apr 2026 13:45:41 +0000 Subject: [PATCH 43/43] [ImgBot] Optimize images *Total -- 5,229.38kb -> 4,931.20kb (5.7%) /.github/logo.png -- 60.69kb -> 35.55kb (41.43%) /packages/blobs/desktop/desktop-wallpapers/armbian-1080p-evolution.jpg -- 91.42kb -> 69.89kb (23.55%) /packages/plymouth-theme-armbian/watermark.png -- 8.65kb -> 6.61kb (23.52%) /packages/bsp/common/usr/share/pixmaps/armbian-logo-text-dark.png -- 8.77kb -> 6.76kb (22.91%) /packages/bsp/common/usr/share/pixmaps/armbian-logo-text.png -- 8.78kb -> 6.82kb (22.29%) /packages/bsp/common/usr/share/pixmaps/armbian-logo-text-dark.svg -- 5.67kb -> 4.52kb (20.33%) /packages/plymouth-theme-armbian/spinner.gif -- 18.27kb -> 15.46kb (15.35%) /packages/blobs/splash/spinner.gif -- 18.27kb -> 15.46kb (15.35%) /packages/blobs/desktop/desktop-wallpapers/armbian-1080p-love.jpg -- 145.79kb -> 126.55kb (13.19%) /packages/bsp/common/usr/share/pixmaps/armbian-logo-text.svg -- 9.71kb -> 8.44kb (13.13%) /packages/blobs/desktop/sddm/themes/plasma-chili/Preview.png -- 314.62kb -> 279.21kb (11.26%) /packages/blobs/desktop/desktop-wallpapers/armbian-4k-neon-gray-penguin.jpg -- 2,383.64kb -> 2,264.65kb (4.99%) /packages/blobs/desktop/desktop-wallpapers/armbian-4k-purple-penguin.jpg -- 1,513.64kb -> 1,460.21kb (3.53%) /.github/README.gif -- 176.24kb -> 171.58kb (2.65%) /packages/blobs/desktop/desktop-icons/scrcpy.svg -- 63.50kb -> 62.08kb (2.23%) /packages/blobs/desktop/lightdm-wallpapers/armbian-4k-green-penguin-gauss.jpg -- 131.66kb -> 129.87kb (1.36%) /packages/blobs/desktop/lightdm-wallpapers/armbian-4k-blue-monday-gauss.jpg -- 169.39kb -> 167.40kb (1.17%) /.github/armbian-logo.png -- 34.06kb -> 33.74kb (0.95%) /packages/blobs/splash/grub.png -- 66.61kb -> 66.40kb (0.32%) Signed-off-by: ImgBotApp --- .github/README.gif | Bin 180474 -> 175699 bytes .github/armbian-logo.png | Bin 34882 -> 34551 bytes .github/logo.png | Bin 62150 -> 36399 bytes .../blobs/desktop/desktop-icons/scrcpy.svg | 886 +----------------- .../armbian-1080p-evolution.jpg | Bin 93613 -> 71564 bytes .../desktop-wallpapers/armbian-1080p-love.jpg | Bin 149284 -> 129588 bytes .../armbian-4k-neon-gray-penguin.jpg | Bin 2440848 -> 2319004 bytes .../armbian-4k-purple-penguin.jpg | Bin 1549964 -> 1495258 bytes .../armbian-4k-blue-monday-gauss.jpg | Bin 173453 -> 171419 bytes .../armbian-4k-green-penguin-gauss.jpg | Bin 134823 -> 132987 bytes .../sddm/themes/plasma-chili/Preview.png | Bin 322176 -> 285907 bytes packages/blobs/splash/grub.png | Bin 68211 -> 67993 bytes packages/blobs/splash/spinner.gif | Bin 18707 -> 15836 bytes .../share/pixmaps/armbian-logo-text-dark.png | Bin 8978 -> 6921 bytes .../share/pixmaps/armbian-logo-text-dark.svg | 59 +- .../usr/share/pixmaps/armbian-logo-text.png | Bin 8990 -> 6986 bytes .../usr/share/pixmaps/armbian-logo-text.svg | 75 +- packages/plymouth-theme-armbian/spinner.gif | Bin 18707 -> 15836 bytes packages/plymouth-theme-armbian/watermark.png | Bin 8853 -> 6771 bytes 19 files changed, 3 insertions(+), 1017 deletions(-) diff --git a/.github/README.gif b/.github/README.gif index d428f4d9850f009007e38843364dec0fa10a94c8..fd2b71b988d7173a882033de3a64faee05f7bfdd 100644 GIT binary patch delta 84309 zcmWJrcRUo18@}yuIQz`(c{q|ChqFg#glv&bLK1T4oDmXHsl+AO+ZknaIGjC`$|h74 z-(-~X`~CO+`@Em$^E}VzdEehjtTPKNY-SdwTG~FXkO|-s6QJ2Qpao<_e>Wi$_2RsS zj)}Hbb25Igrm<>fLS0MeLTIzIsZLPz&D%Fii>4=7WesVr&j(VFr!1lTB?Zbl;?m+wtbbKVCT*}UxFK*GfHj=RVto1S!TMbFXp zMsHdoFH*Fiy{@M;hxv3@SKV+kwF+lld#r)$oqP#R%^tB!UP+F+qf=zl(YpI7gPW^m z^va7XRODSx;=Ca_Z9wfjkB6uFFLR2iidOOK4)3wmuI7;C@ve?rrKVo1XGLT2ln<-x zGm-3{9YNblC=IVz!P+Q#|(*v$-J6X zlV4!>%_BMO#_F5)ppddFA*Jz3b!Zl`JgzW^C zTH3MP6f4fsDFQE;TzKe`;|qbeo-=EVzBZ{~Y1gp+kl@1gIwuY?iJCQTmOsG*MWE@| z;`r!XtkIV~_7^;g7?9s8T*NQTfQNGT>Bl!tJ*a70g0z-8DrPy!K6i|hm{6gpI= zM;I2*DBZRN@grMkSnTSNFNjC&G0jk9@>-4pye5#(8z*o%rzq9uELalwfGY)C!ghDE zDw>1v^+OP&~jTl^JiZUdyN~b6C;Y-UCix5ikKiL8be8E-eB@FmcHl*RZ(-)_1 zmai=3srw2!J^bpJp!;rRkCjS_Ze&yjlW}T>6|*np&&HOIh__*u?&1 z$@oUEv^4W?KyyFa*9OaLUKxh=Ty3BB& zRbU|_uX)re>s)v^E`tYN9SxGhgYE+56e2F%RRD!&iGCKGgq)tm()wO|X!tF6@It)^ zE0^vs_*datELV+&m2XK!XT_x?wT=auHn>aj-F$&%DXc_AJ<}M{7`j(0{h~3}lCef) z1wEb}eR^Y|4jycvb!;dRmsonGq?L5oVj^-Y&WllI=VE$|)TjjA=O zkB>75Zy3(Fmvo277%z!U*x$VJr=x<2(6AYYyC?6xyA0ZwzuodqrEr*u@8AfS@Yt6p z{;SjL->UU7HFnuSQuM-h;*Se2eJ_9SH0@z=-6J7@8BE?jeDww4_@*3_l9K2=_Ny>e zChrt9Wt~TS|DG7fv-|e=SYqilqH>$X>Qg>xp8jK{R7iw)`WeewFG)@|MN!zEuxRc4 zBu&IFRX)1ETr@48_qGYIbN(`rXaZ0UHU&-x5fv=o>y@|+gPPzrc6zbJSyCoI*VjHC z-T_#>7kIupB0CgTlJT$5(h|D=Ni;dVpe@h@!-hrRsazE}78!-K1RtZF{`{z*aS&Ue zNg#Z$i%XOUl0ALQa-~3P2|%#JsYjPo@_{t4RV5GP9eqLM0B%rWI)`&EP07AV8fsofOJUd7ASeq}kM#3}`|nI3y84lF6jGdh-^x9 zE;YhvRx%5Fh>O=!BQrs{DP2Soy+TSXTLip#k<<4K=uBI?3;rNP;9f7oA_Na8@Xt@L z9LAO>-S!UXi4^*Nxc%f8UXB;YRcurjAZ=i2uGa$W>C<9}%>XwYu;`K%smj;SE2y`V zx#h$s48>zAO)-u*bH%>PlgS0rA^1#BxEzGFPk6`z@&)OmZ}}u@(pJn|I-T`yup@~K zOE2sz!1nf9v_B{GU4%E#?jQbi7<2coX&n^-@u*w$Aew3*S5iJj_GUObI%4?S1Br!$ z5=rhHrPa}%ojlVs<8e z)9*l@W@x3BlXZ?>Pkv^1Zrx_7lThYmGPjm`vfVh;nSZ}K_@TFBM(d}Ihk!rdQ22(t zh5Wj7$4m+H{O=z+UH`igk?5Y{=Jt`=^Ls!}0#K5Y?TGB_lu!TRG3polX|~)JR~9I= zfnE34S(hjHSNyaCxP3NVx#|?6#F!a%RZpW;f^t#wJS?jSp)W7ZfNNulR zij7KP3VZzKNv+)d5X8gOW=3cjyj<>{V+d6-tYtOWH*Guq}B}3f>?M{S2IhRz_jPSW$)sZ&7 zWq%4OIILJ1BbR;Dpvt}VT|?LD745E&D%aW52EwUKi=R=)>1WK5`HzC;yx9R>Hw&mB z9*wG~(GM_P2e79!P1G_O_ps(f+XpS*?pEknVU2T z7jc@2g@Zx!{>6DCq9N6^5wB@`1Lw-gDoV9sX#faD5zJLbVFtgiS7F!g8kxYTs zBXtbBKOdEwm!;ucN26KjgLvi!Gl`~isXd{-PW-V@wAiuWZ#!hwGGz8Le4&4iM-lar{Djcz4S$bRPx>Zt3r9H zci=IBY}41JO|TtY*~v4OhGnil;TK%(;v^XX$AR}hsY@Z~+R;67j`R9X1y^mZ>4eSr z(AMusM+JtEjiBX0#qX2R?ZUWysp|tdcGEu5$LCw8EIsMoi-A0K7~FNK>`4jKF=rgi zFE?llMM_C8b=I%<=UXJC1}dH1Hu&wAwk_os;cs!cq0O`>C{*#0H zT+(pB+-M~+$nvf}D&5mz)9R{6m z)`}Xkj3He}zb8mRKNP^*Fcjx26n|>uH9r7)({*`1Tqf^J%3kxTxe`%*8&G`1n40Hn zBZn!tpy(W%89r7GP7w93+J#`lhyv%-iXChl;OTbPKcC6?R~BKPp5uT;n{oFdfL;fJkLHI!l#Bf%_f=nCb`Tq zX+>Em1`O$F3XHo2{l7C#Ucj7%@M?zeYj^PLDoVm8n=^+2M!Hm-8`U(PYW|FB*+E4B zfYyJgc%c@1-4@3Xs;yg#%O~oUju!V%EuMc`yoFk?>bCm1wYtZ*_&;k6?r07D)M}pD z8tz7oU~P@cY`KXNYBP&(3#x954Qach*mlk86-l?99M4Y3yL3Si{LrmEFZ2S2@Rbv| zGRd|<>7WU9_Ud-h-8u*2I~mV9hdVk)KXt;@U=T5I2=R5EF7PT5G712WcXTa$>RS5K zwQ?rZy{6l}(eVa}W$ULvAQVV%4j6%feU2C61hCO*2vaLIWyP-jj<=_u-v0aZ79dOm z>Cr5HLtHVgLjd5UA{dguPT#I`ue z*1yM=Zpf1$rr~)qzHL_3rnMXyFF1Su}K86DVNokS>drrZyVFP8dq3 zK%jVlC1v1}ZvWRm^pJ&tKtw+R%jRQ^6l+2p>mn5=K_<`G97p?|M+Pj;C{PH76~EJ$ zBRup#Zz$h=NZ*~!2MshGu>!q7*gj+P#3P4t=p3MUb@N7enfWwJ;2)`OC zC!nXCutS|>wS%n;S-B0D6w)W-CBZ&Dvy&(Wo-MI4?xMq{&UV4V_T=iFmmL%{Bb<2<(I+jco-3JHIk!?bf@p!uAGB03>Ij)N;U|7Z|Gz)VJ8?pQFP*M3f?6s-HN8 zz_8CFhlc>{>)2@|e)^IaYIqdzWr5+1gnqXM_+ZAG&j3@KXfXF;uTIyD-r|h@-x=?3 zAOL38xOU9+&MYvLjg$*xh<72eu$n^Hhlb&&dVOA4fE8^Jf`7*y@or>~Fk3TpK{+*Zj_hg6AKec6}&(j?!$HZMgvsdk)hQLoSa_e{~1j zP0p1sPBSRr4-xNb7P<+xnP5LPS6Bmty5HZL1A!t3!k?qK$Hu~Isr0{Nq}-4ES*So8 z03(O~5zy1=PW7Wq8;5*?-TMf^gLNpV;d|=|0^q_3 zg&>njFQ9Hj)aO0cN-S&jbCi+|tHtOi@aj-&S9h;BD>R&y@Z+M8FIJ}6o7Iwnf>PdM zxfiJ7Gl-mpPqkp*$&}P*tfXA}2S8u*6ez<7F#7!Cx94jL-D~KjHGumF1j{<3NX@;& zPDQe3_`JVd%jVn#amX1m68e;5L%lLO986h9de2)cZg4FuU0+1qWZO6=GVE20(i82O z(VJJdrREcAVaAz5{z_E6aKL3{l$QRga?xgR_h#tQX59$DkH%=r0ZSv;9;z;Ik={7j4A`EgvAwsE8J=XD&H*P9*kRMy2`FZU)I$p|`u3*#Tj$cZfa&QP zJtUd!?N-F*T|>4pG?Hs{G{1Dm0u9TuMpCf@3}vJ-d4{S7o6>*25Gd4;FuZ{TCQGgx z|A9c05b3JGP4rG>=kUt+Z+oIY{?q@lH$FYxz^Xjb-JmaYP6=iKV2!Dvy9)0i8VFn8 z6Ill^>*o<{twacjx3YaW^c&293~GqIz{Q%#nk+ z`cOK4^3nozedUMkSlpKHm&JE*6GZ4U4sLh*MaFokK?Bv>-Yof z6ZH?#sVC&whEIJG@%ohx0h}CmfnwJPdw&7`l8I z{SH{jXtp2b7EuTujiVSotRTCabbD#!CbKu$;qp@FHdVc#eO_U4R=)}yA;fM3M{ z!q`(IR;06ep`^>?g_WLU1dp=g_FWt*l~dZb)McvViH7Cym5uo+$sA5^DN{Ia`ZKe9 zc}bQPioc(nB3jM}>++b01o7p$>ixgyx?Ejsib|$nj9wRo;-gzoz|Z3B`jS}hFAofz z;YDBJueOmTCUC#Y->-R_)_8Vbn`lM2$6kj39T#jNqd788j9lqUW$qvTyEgjd!u8FC z4?njmV&uzQs7zSit2*pWc2^&*wwgqkQux|({LYxQly_W$dRCBt6`Dtcxx*phRs=w~ zBEdJJzrTndP=oR{*U{X~E)girG5#zCo{!k^4nX!;1kFUpo-c6frDlGq6DKbxxiT4N z`8qt<=}Tq5>*~l*gqpUB&!BMiHI8FvBcIvKuz zd*_7V<()qd%_q{Bc;0~6Vbugos&I-JPqr3IvfC?F&=IO9BakcldfyjO@UFR3o@1ni z%(LkKEaYD1|0m}VgJ0`Tw@*)IH^9mRiBb&JZI#s0oMf`{TSt;<7)wpbBe8$*4V>&# zt)B%l|G6i>)cK48PU!Xc(DFnQ0HqvS+umoU;__?Q87uy|4Rb1wbp^qwba&jEd$i6x zKRZ(luzGbuG4T|fvrvFf*H!LX5FbrBebew#<5orAeFw1Ji+Zh!J@94ziV*g01Eh$L z9qjjMGc!J8%1|ia={Bw=T~MTlL-{u=#RU1p7yIm7f)=Oy7r@E-eLG$jXpS#-$fls~ zYc$WK%pCF26*c~*LubPNN?2Ww@ikw6OA@Qbu{W99Db^=dNWaR4KLI|iAy$Enz?qn@ z3@|kC-rL4pn6MdLnErXysJ{4C+JBa3aX~5nS>4SS!GHMan?rDfUSel*Z>m02Ss~HYwzD+wz<`V!1FBD$!>m`tnC`L| zS+PCQHmZ?+(jrNi3YxdmzEddQ?o@_O%f8#kw8TqVJh)-&>;WqJ^@tJM^;hG0OsFG4 zKP31fs4ctyAZ(qS|GfC5Zrv^6+fnOG+rPgT-hkfYV9{3MgF=swP!8-6Q3*ho{H1=P zY;ND~4@iq0L)M+5khJibz_IPlbn*Di5SfZ6OG>@4>0Bc~E*R4M8Jy#ofsIC&#-x-X z&H;_%TilNh{KP|j(~Vgq+QVvdQk0Rfg9qGdUGt$#j4M|;HIKU(zYtFu-;ap>h&!O;L$YZGtxJ;NC_ih*~%lXRsJkSh-D z-5Z%eUxIL|z&UynUp_uJ)6Y**s0nRh~Az7~-xd>G4c z@~`!^;MtI$kH~Dtao)?_2r&42a)}6|MoF`N_$9|cCR2UPey^4A^Ba}u+mf#-2o$yP zt@TCW#6SivE5C%la=NGX6m{gUn2p(wUo~ySDeVQCNH91fOrpgn-5Ijm6ouV8Rw-rIB&FfC~v0kUjf#&ioj@53TgPps6U#{{q z4qLXziCl$2B>bo1+^s*PrE6vX08;qQd6-w`Jba)ir|=4D@ew3TbRxXMscXCx1rGz~ z(IvAQA1wqW76o1ILR!uwWqv-zVM&CV0Zy4@mZ?qMw8y5Y=6vpELb(elyfm8Sa*KsY zW_n?q-LxsL>D)(_^@X5T&V_3)KY>E7-}&RV0=rd>tpHV!kZB?-Xop{_&gbkism42| zwz8}2QJD|Pw(=lA42@UJx+y1jtqO8$)jSrcx^!|9et+SvOH}cnX2ypZrVfId1AY9n zduhr@;>9d?uXx|GnFUSenw0yu-a6zi>;i0F>kM_{FMtRF-1h?VE5q3BR(^ckaV5e< zmgF`_-JSaGPhpaHPsmigD-QO#B?nF4UZjkTe4AW^Z9;E5{b|h{JDAS z?ccxGiA?S*VA65yDce#yTQAtRP{Y9asM76VMEsIWF#Q*=kv3KZL?w(WC8J@cA2vz z!0XSat;D0QvpaifUZ?A_gp)Bs;z7CB-){kgKZ|FH$Aez~ewGvd?h**6TW4a*lZ3Os zX9U2G_F9KN$UPmXP6JqDp*z~3KrB-N7M_J=F2u6bU|Bn{h*1KTZ2`-^gXK8IA`yn1 z!iHREL+(%-)Y|Z`t|4EjA%B7)D$7uy&`_|(kev$W9W^{`HWW>uImV`lq7B8+hAx3v zB@9u_+DO{n2uU{-N$CCQYb0O|4V?nXA7B+WNRDELE|banaFRf~k*aW?VziMQkHNqA zUYI)383Q1kv7n5k)dAYVJ&rVz4Jt)h%$ONX1c?##Luon-5W77PS4|%fnWE>|tDByL zLJ@%&l8U#H;|kb{L9&@7+wPG-lVEcO#Ot_EdZ8DNgPNm2UMR!!dd7R7fO0sfCJJIC zMm98uc;by53n1d#P#vnV-mEbkm!gj(5o7@USRQC828VO(b!<;YGeBl!oJ=UhY=I11 zfk;w-AnyU-F&T&Gb;hQMG5X;N$)=|eBSep*qsh$;eMcnOCBe)XkSaBrY&lPsoHsGt z84!f@vyOsMD1eZdsjl^ahaT?EPLE?niffK(prcV-0#5mu7b68AERgX8xba!q>0mq= z8@EBuT)^s+Y0>Ux4|sIoli*v{WNcuvAqrw#(Jxv$XmgC?tm#9GnRDZMS$Iqk2WG@* z8c5DGd1VlW7-Gc@Bo|_f{CX&U4D*d119hTkJGoejC=rcKK@2mg0~BkpC0W?#r8K1o zS_T!!j7xDnwqzyD4m16~dq}V<4ly$_Cxc?4TInYLPdXQoB>!2mC*BHPO84)?;kPX_ z3L#bpBT7fFVgcD|o^0(xR)&uZC6Ix% zKF3(d`m70P-pabc2D<@%Po+=qKwT*GDfHOPPM;%cd`*2!3fb=%NJa&kBT7dt9c`3X z`X;SMO^%I!Bv@ZsFk0NOF{38w%Gn0{U7Cy@vtfWfNcGzslLgG77AT?w4GJp2i8Baf z(}nRbxKUH}F^oIzUo_5Pa$t~WvafWauJHd1gS5=u!lH)}(e`qSWbtFDP_3<47egt?Wu-@$}` z!a#Ct@)~ZM$p&gZ53x4~x#W;hNC(541Hl^*j|B6jPP0p0?@Y*}gpdTR9?g-VN1~|D zYO*nS!|eQCX`?)n;5HTpLur=+a}y1`0v*e>WIWlmy+Qw`H-U>rVDl7B6j7W8Ew#S%upb(x zM=*JD2T%P4l@fM2i-%ZOmonlmj7&+x!%wd?@Xk6UKv#I}Uv{?poI&261_?{w zy2#4ctU7Hj<7P>w?H-$py<5DOQt1P%J8u6!Cc6+*Kr0IlrHro!Ht$*%nXdJTqQ*|b zXw|}AwMuaIR~F6}-#L1`b6f$=?Rsd_32u~GQh!#`hsEAB^3oJ^r95kS&3g7X8%_@m z2ui@yFS~O&Y3CP?yic(cMJ~X0<{EjgBufEAb5`7A!DV4IZsJ^{60vENmbPFHck~b_ zn{`j0v}hos>wXboA+=u^P{T|c%JKA=2c!dNg4I$nJc5ul~ZZwoNPhq9umhX`q8Tb z_(fHjHQ2)PcnZxig8b{$H?s7dzWXZq-6{sX(!99B1nG6Fq4(4{PSjeSizcJDFKha* z!Y{7ix{d$uAF`sWTy>ub50az{iljzg>_A(0wm*F+s09!=@;`hTePIh`fn z5Z(Is9IGo#`Z`N4Pgsu>4X|;6RHEPCcG^l1UPsf`sVQ5L?Bm6RU+YD)=0j3uzWTsm z5w|mw?sbXorLXFqa6j{8?|~-?i@NNebfuxBm5p5yz*7i)D`6|7JFuAQ%>?;qm<{y( z{s~Cg)}7sqDZA$OJt#+a6^Av_pjqjRgR5F*P>-&KE8DJzZR+O_iCo-*zna^-XylCF zDwVlP7@h7%Z;ujc0&D*bUc$`hFS=VDq)0|%m9(~op|~22fhc_NI2%Ks$M4+YfPTgJ z#@~rzh>><-5@_4Q+%q6d=4y9Y2naK3*6;MI1zRUVr^^tlH@}_Kx?}X2wiY%`|C!xO z#E$h3NYt21ihcWJayeca(0uU=v2Fo0Nt(a2W`DR=f+Kh_z52hrg;wP|r14#SwHb6) z{BQSOl>5WbWS3HtmHzpFTBk2rOQmJ2+0X@{qH&rMsbm+dJZ}-SFd)WwuTS|?-@v$Wp3<+ z?`{QM`xu(If29t-k{$U#7kDed?C}Ov|MZ>aO*#Ru70~-=HKyC~-%cbpe?UO935WNi zOk6@OTnl&SHay?f{OHh#o=;7gvmW)V_^}%OD{<4fLv(Q%Jth+oC9AyVCT#QW0P-|! z?P~WnYYaZI3m-d3|CB|$!E}Y~^RDq*{8vKlrtLQ9!oSF3o)oEh+|!g-i=mQmra?_u@aml- z+*$qc7L3Mrns={hCT@*n(ol(8gv9OpiC>Bnzt$&yt7pEx4bzC~zL5^&n@{}ALD+Xr zgr}3j8Li(g5gtc9Q56FSP!u;q&aQ}+t-XZFcmO9A^n)5wqyTWGHgcsm0b_{Z@<*aD zq1$`n^mHy+`z$fjOrs1z&B&eY8*Ar5)VYLERKF9K6qxl<=$HSb>CA7rl>N-ZU`d6F zuC(Y_q$D}YD2+=g_&{#D)bg=f*w+L3*$Vq|``X}N3Uf8CZIQcQe<{v4TpfI{tHWj| zZj_4h@YPBsA|71avQJPXND6xtXtHi^JUNnn0!sL!MkzBXU3e=kduA>kL7i6 z5?+0hl&e&Xka0h0_ALBAoeoA-jn)S_BnOqg{l2g>-xM%Y7xqWv`@)-BnHL-?@Fn(H zEYK)cP1Wt97+Kk6c=!T0NcY+GENn8ZMtG^TQ7m9GGwIq=rNe9t;o_B16(~LL`o#Wj z;Qh_UkS+bCi-~C;x{=Pecin>QuyaZ8)ilHgTh>ltkO#~-ex2hn{s zJdrDFUdYpVNfYiJ0?IA}Y(!tbr~R9{o^mDlwe(|;xD)9DABB{&N7|g&11F#*k_b9~ zbk8B{X&bQ-Z*CrWoB~`{mrv!=lAqc%9Z|)Y0%7XSlaNU%Ln4>;HVqlvKOb2Dv?TUm zdFXQD^Tq3iIol=o^gkj46k>S#l`|z&5t;}aaZ@f(k}AQo%u?9D@>cF=>bKlCEXR}8 zt>G`os;juYO!ND&N3zD#={~HsFh&rvSZfhfQQxV&UR{Z}*H>P1;hLZ#@V)XE`~`Zc zdZwypplX&o<Mk=R-g1hS84qayw;=ZKGq<@P3mV zPu>e;Z)vE*&{Foz6>|t{L*og316LbT0>Q zz`aQ0|7d2^P`o^%7pGfK%rwNlMYz0#(gYXTStp*}ixR2t%lWAT%yXDAS%frv_s}T& zbC2*_ixmHM>5kYZSn`Eh6~r(QZfdz}V(~R*Yn23#|}g<0!&lmm5k_a0-wt2)j(&iQQAq5h~z#aRZh0 zA~4!w!`yqgAH;9j=fe1Cgfce=bl;O>vZ0S?m3T{C(_<3eD4=Q4RAEX5!Js!e?3#>5 z^hI%2fnmXyMKTz=L=!*|{Uw#fJJw7v8zE$BX)4sOsuqD81b}rOMbnTeJgxQD2_JF? zl%P;pU-W_lwb8OC?H!EF()S-+Y7h{ z5(9&pJAGx>U7FK)!lBNg>6%;wfxfACn0qhCe!`Ch%#5C} zr2Us{`V03`w(BtDGdFuqe)vw~4f71ZCAYzxILo^dj7W($xMAc9TiO6T_}OUZ}O zq$0seVlRdDY{2ZtDfg5&c0ATYZ@HEh7s&}p zc)<4_?d#3}AJ$UXYVD;7B#R0)2uS=d`tnPnUY{VK@qAz7;sbo%)7zrF^H2g>h z8}WiFs6TBa^+rRU=WD(u=AsBkZM>eqSqQ<;s|RP*7d;{p&DQ1#gZK9)Uc<)y65_O% zSa;d&U{+chS&=>%yQ@9-m@jxmg!U1ME5N1ZL`@6$S-&&C+Gl9n8st+9`t|mv5aQ0Y z5HV4o*LjG>YdqeBTuZ-{9t^ENNEt!Q+Rx{GEt;BtCx8f%Zn#vi*1*;!P=tvIzVj{1r8ShGBKXsIcr<7u*BEcM^!1XY z{iOyzn5?*RwV-m|6SLL-gsSfyCY_v-NN)2IeL1~(m5*KDr^5RuHM)b#%*uV!7XZ-8 zStu$A?H9THk?$9`w0wLBrwirg?Xj1P^Kjb-zWY`T%Z3z8_!zk|k|W~ZD@-84hnSdh zA0QsiAe<1`Zn$9#!~Wb*e!|)kdQ>F<`V)NqZFEk=7};s)tFl|AOXL^T5`c8A2E2$E z_cMN6YdttzgZ5eJ%d7KUUu+3Fml^7EV2Wn-t-m{vEGpvX=v98T90}E9e@VaP(zk!Q zR&SoWmYrcnZ(+&~&A#68jlI4@NAH!%-GN7t2yp#P!nnqflY!MGMU9P#2)jP5rQVv5 zHEGP4BnDrdUrj$b(HY5UZf3VRRf*oEi3B}c7+bD1coVjz)%gM}=7n0K zn6&ya6I3ME_&g0?_dY3>EL=c+Y8D^ma3?fnJ`Olv`S&});B;Muz>n?vcPMLlL60tO zjOrD3FjM)gD$EsVubS_mEjE%{;N(xAM9oVQO0+o&2sxcu}t!C{$9}$5jLMpMe7JyKep55bS-tQm$`@@tmrT2Slvb6=Nii z0^LBNDQ4M$K1lL>%_cri7svqbmV&l;=;!$?tNorY=b!7nGQMt|bb=(}iM)hez`Mhp zv2{7hpQn z@Rw{W9;tKD{yLWCUUN}Rly*sdvTYf$?M>MdFVha=v( zJyFCAj_eX)U4*A&Xc?**7((D2(^KD0j}5JPey-A|s$xtRkYFx2{Y5CfUFvgjtd%M* zi&^K>gup`_K3O^N3^=uC?p?unCY)-i?*CcQWn-8HOr=Eyx=t`ux(Y2(OKy|L*`BJzuAL(kV_ADV}oI3oPze*kEERtReA#~vWx^zQy%3%oVmLsmp#0kF(7yUu;Ttdxtx#19%UH@ zEXM4mf!Q*Z51h^hA|aJ|`ttdvmHBVBA2?N-S<652uY43P|2U@daiV-dYGpyT{F6tO zPm1K9mQ_BjlYiD)`K(*MaGkl7<@4|%%u;31clqMO%Hn?nc?ztG!mjXwuj+-U zLWxXOiL$~=jjEUW3ZQ@7H>K<&b~(&AigYfTWj67ZsnbUx}9<5-MPBmCFSp%b>F`$ z|2VAs@lSaVR=>xtvd>q)FRJq2KqXL0<)=pdPkogGf@%GMt;#Q_`d^+ZhyL}4;VMTl z^+$;+$Eo$l*(xWG>Q9PPewWq%u2cEbTK}h8<#eF_bX?`{T>alAm4BP{|Gul79oCK<5VHozB@EQL0qTW;1vJ2}W0-C=FcC2Dvdz!!1@-07;HdHVA$R_uq|WQw;I@gU^tE%ILVU03D5wciXPvH}2r*v2y$Mqph9 zSJ)_6uPW5mDD+lUc(74;3$rxdD6*_7xJ^W|O3Wnv_|S)Fm}(=O$?{HJN}Wnd@q@x0+-LYI12!a`)BbA2-Ptt0|N>Db%Ye zwlyifRYMOpp(oUo-d3YBZzydwDL<<+-cdVtYE)rr#&DchAZ?kvd4LiKVtyDpBe$pn(qOQaX;%E&wtv)X?p$C&OD!7OJm7tUM_21 z<^kwcpZ#2F|EU{w{-W3UKh_}-eDg)7FETE+N25`;rKB1K=Db3X(1IEhm1dy(MS~wJ zYHh?9L6SKD*&+Z41d(kI%Hh`|a||NX*czXs0Ri(#=W4tY3wzm-DaHosIk0HaP<8cN z2Qs12X5WC)p}lf@X4R%N-UT(l4vl@GH^aJz2LJ>_5Cv(}`+Qi1P$LDsUI3y;;ut7R zry)1~Kbt6M^#YKFDh+tQD+51_@^YxaFvu#1RVO6dO^bfTXmJWDtikp+=nMFGxR!S;#%H`GjO`9%Ge{n*ju9VOeoB@r79Rd_&;{EzgABD}RV6Y!Y|=S&yJKk=ZXs9cL)J zLxZ2n;=wd`T^tJ$B-~Eq5boRJ)iPRS06{E|B#5E_-_MgRfuJ&LyED|rB$-FA)|Lr82dJHAJgk|Z2>;x|iIpKrxr zvD$?|e?>!^otTHuY>JB2`74Nzjd?WGXxyRfg&Z^?EiF))wtVz2?LZL1J68FCy-fmwna{RR~OcNi)vk zkDoY7sP8RPxyf2MqMlD=UFfaQ<$;X$5*Ne^xrtTDX9v%|0i{Ao^0YT9dp**jAo-e& zRI74T9!N=WvP44?(X8(du?>TT^c1&<>;Q#{F@oF2_gGWp0RZNRWFBe~fprpuE4Tn~ z>=AV_WOnHhMJA`he!UljLfl_lI0IQHUEWwt(jW=OQW;u&M}UnauUqOsc#OGFE4~!O zfuMQ4)vfy}UdGdhICwMD=cPe35~dugMrZMy9y5z+1*+2Cfr(tPOjaEI*~I`)cRgnJ zKQDE$OY-Uf$2Yi&&T)bswls6rpr<(WYAMLheR%7Inz2BxZj#CD=nmk(q%)K}fE z-Kd5`uzku02((_;##^tVozSiRXrnq>&eM*6 z(Be9<@#ksk1yuZctTu)|0EPgP0C*hyrZp27wuRD&K1N=}-Q|{dqQ-Li{*SA>4vH## z`+&bi*V5e~vB1(H=(2QoNl2-rbP2e?(k0z0N=TQ0h~%<#mxOeel%SyKzWkne-+7<^ z&Y3f3=A1L z0W*BevR4L6PTM5<6-M@qym0Efq`n{{!eFo)XBSToIG#=Dw`1m)y+3$zUd)Ag$9j(; zAB2c3z|?yICMz6ZAT&+l&*KHd=#l(7(y}bLdta`3w3UE4>i;D5$v$MCe4cUDeOs#j zDWIddYP;`a*KoG36=&49*5HYkf0={4HhSafWnQubUu5B#?P2pie)c(-QTo~Pl2yk4 z`?t@5zy7g?2Azu+XtToE!d_e*Eq)5bvAqnvfsOo7c*u@=`S;JwuU|O!?vr|EuLdBB zQ~|04CbFJv1F(idF@(H@sTksBM`$l8ePe1bx#DfAG8n;MH)d{V^&7 zWX&{?R);oCs?geGPN}hm(M)SF?}S4%g*#}B6>SibhI(U{;vXqB_I-8qB^0mp9vIqW z&8aQ^rkUN=@yPlrZThYSF){+1CHpHz4}-K8!W~Y=~w*bY;sltR>J64gLYp3;w9YgpkE8UTFF^^ z`S&mVdN>|i?s}wt)BM$X6s>LUMhxpqhRrzMH@TY$!kr9TNfDA`k~WI}WKC05+48p2 zbssS9WSZK_J+bEY&)dlzn$6us<$H88?iKp4=Iy-+`^UIn6wQ|ZpT%OPgOV)U{DZRB zFPRR@OW))lR@QVf9aT54<{#B|{9`(x)}1#6CvD$5 znNQoVRtru$|Ndh>>&9a*Jj0MZWI4yuuH|j@v!Ylo26^8WUJNtKbYF~0DXta%7+1ux zTu!R8zrLK-eaLz>Yx?;0)mIx7>(7NJu`E9pJ-S$bE&H#%{9%ynE7B(to2%}xpI;i2;h-o zcoz=-U_s$`p?=2t!uu9K& zEH%D6kRw8Gk5>cg1Z1gakNMq4qwGZBTn01)rm92n0oPZUIM$c4Oi8?$OE!J)in~vq zpJqYx3J)m2`PeeL|6Qyy8-x*Xra1pKn#Q}l+roZm&;<4GiPVCL#c%ZjXO!d%I)`+p zY?s|UXAxTEoNJbv;$dKsF0-HsRdccB*;bah{A5-@uBkN{gtAuw#rsaTQ$&Q2WPLV}nj^eBCybK>0d8hBw+|9l zu|ojyIPBI*?rDseML=)bgg+B_71;r5I_e|TsLJQQzQwy)|A5CPX6NAqwkYxh;6ZX+ zz+2hho{~w+m@^Eb4^APg)ES%6T;rXy-9BJzda1{%?A z*|0jfm_(vdbx7|koqa@q)WN&1R9spy2l_i=bL#r5WvcF`RDELxt0wyQa@MN!0O&n2 zhXgP;GXRDxHxw8X{_zeJs%@*rz^$ax*RuEVKTnvwXhKOiRao8U?%?{Jw|Toq;lH(p zc(cd;{kU2-n@t1`Y0_Y^%mH=YG&_zWnp<59%``iMSW5!?3tz}UQ#&#z0plUC>=rM zH2}(I0uX%#0f}#_<;m;kXdh!E6oJ*;^yNbbv*+1|1{`3ctqf&@ZNR)RwRB1diJFCJ zYKY4ZJSmoN73U`r49-P)ph9|pNH^=}IX-bfcsTwW0$k~XC%k!7i_`c`3u#MU`xfNu zC~`dhW_{D$d$P-#3(;_p5cwdQc!XxmiRt^VeSPNCHR1QTlxVzfSc;xs%0LHP z^f)4j0Ga$ITptktaj@*S>v1Z6|K&5hXJ0Cs-^fwD`ZxS)_K^1zh+D_Oh+l5vh;Oqf zHf=BM8F=cFud6y-MVQOP#;W}KkRHmE>{4OZQ_-=FfMs9 z(|w<|gfiL31c4jvmgHv0a})+Vv09vwP2`OQH$#5Y9^#aeM_u{ z5y!!{_T!C;l)7b6U#dL9N1PlMknN8#Qq%M1om=y2xQ_1k+lA&ngg><&{r>r>TNp*1 z!~RUI#vlle@oXZUIDiUoE-XNLW&yHC>M(Woj%l&bA17#%=+jl8c{xH%`nM@_Q>f6@D#3r-<7))n~QhirSSnxd9ifB-ckzme4|+<_9^d zHV|;^*t^_L6X??U?h7fMaLD}9J5m%lwU=P99wM=rs`Bm^(nw3hCz~W9n|Duo`iWse z^~l|cgwV2L95c~-I=&4tagZz!pmiA@+LDAN`yAosJqKkV+jS?K^f(XY7vx(B?;%xk z^hzP=pob-Nkr|e&+NEx2EPe`-`by7D^pk7*Q54Q>UNX_CyYMlWW4c1{EQ&lUz2fqO?i3-g?kR^oN(kE5%K!RBBmo1$I7>AG3splJV`#%XUjPp+iwd zT+n7Ikg%eVswpvEmeWaQ_NbWBLe$L~0FVm)>(j;3TVEfg>GF~&HR5dZezIXDQwAkf z?z(LLOU?v=H6FcE$<8O!;!m37;nB1}XGA0xhp)Aff~HFyX{bw>LFtn<1f?3O)=G)> zEdudJw{(TgVPcbG=C(nOd5x*1jG-0pbH*>rGSs5gemQ0mVNA#@DTt8c4(}y8x&`h^ge&5$gT#dX zsF6-Km8;(sLk?~`ethny4+$Kw`M|hrV#yj4zPzrKo}}bMw)9cV`r)$?daMA*Jc>V? zo4)bLN$I|z*P$B7^OfA>W6?}JPXq3YnS$^GnFq>h zpKT;R+$(dHS*)~hwEFM|hXZKP+FY>P28g9g1Co@D?4$fm8@c0+75d&OQv^8-?1n_N z=&tT?FG>YG?{TFpzvsTeGVqR-c|n#a_J~ds77H(x} z=;%)+Ei`I22aQs^2!}!J+}?TcZ&9w}u~|={WETLX&y>SWq)5B%;~ce(7XT0hrzt}S z83zkkEn=6z_<=eJm0be*D*9Q(2Q(`cLxvK_Fq4_- zJ^$D<=w07AZKF!prcY3u(0GjF`ITclu9yxlTvcrffYQnlL|`~!xlh;k;&?&vlK0{= zWI{)HpqhqvtGw>DrO!kq6{53g$bxK`#U58pbJdCS0fQ1-a}(v#)Sb_tSaP}my*xbl z>E_;1R%Ow32I$I|T9Bwl)N?X-e?rajSVW&I5T^n?Vv|@R1h@hLmrVwDb0fI39lVs1 z2x@7M%3;G(x0T(BY$ziii?TarFr!KXdQ!$Hm?1A|0@k*iZGM8Xq3np2(2P^7|{{Auzt4ZfBeappo*`QwVG*~Ml+z-NBWrGVcKQv8j+{@g4H&9rGs zfU%%3yz5u+W{1IR2Np5YTpyMYTn3Qd%Rm_A;^&PC5^h$HpA%cTOdj#4yTYnQ*sGa; zjX?!LpV08q|Bx~5m3{q7l72EWh$fXN3y40C5s}j+k}@syizV2Qh0Qs!7$lzi7^WC= z_BHTvZ|R0(pS*R3zHN?@R?%nll1VYxas0j^NTavxRK42s%kM_T=5f1-Lg*ihZQb&ZOnN zP#BYAU?$9T4oFK-7UAKM+v`<#oX^v{;Y^)}=Fl5T2L5?4=jx68@Hsm@SnF@P3$E z@gmg6=8v(Q?r@+_FC!nWR2a3~$T=7(D8A44>;r@8Gf_ep&t`j1y7Cl47kT&%h!L(d z;PXn7A(QY?2vc}z1DJz{qYO<6o@`J*M3mBDBl74g@ZXg{E@YNAa`;Y22ZGx7@9Atg>MW<=QwRp6^+%SQX+oigHzw5pn0%)L??a_>{eX7J8fVHaC zx>K%-@6s>?$`x_W*La-$mDKXbj}!0JCX24d;OKg0MCB~A@9 z%89HOW>ewMAg?!Z$i)KwDjNC_=Y*yQu!4^W=B7IwV`syK3jI;y+iO~HmRc3Y-*}W+ z2{|nqP4ZvR@%XIX%JC-ujbn_|LAO#K=UB&qmJ_Uq)3M$BX8F!Z$Hk1-WRnc_N zeqw_2*ZyhaYp7|w|E0<5OH0U?)`Bl>U%psQ7qAWlAgmjFNbS(TI3Ij{>Wmmhit*T??8`tg##RPrrPb zWA0jo8~=}mF;dlelh}z@_=V7`E0U^%c)6SWwwos{QTK+vs-TUI1x6d%LzdRVl;c4R zV#?5#W*rRugr8ou~DD;_F_nF;NihA`ua_<8-^nKUX zW-M^FRp@uJ?ti*Wg-IoMZSQwq?tgyU@5M6UTG;PnJrEE&5L7tuqJ1EAdEn*kKsd`_ zq{3j7^&nbjAf|9I0oOj5v^c{|e0GKx_c#afT{ z!}ymBi1Q|i3vLG+;DjOJ#ABoVxz+sx|D{_jwT~??kFDO0VM7T;>%ni~W67a}59(3i z9J}#@a57amRMLRZjdc9ddg5p3#C74s@Aip47E;%<@rS8+QK{scI^)OfgRw6q zr{SzK;)*kpIGdSgq$H>9;E+_Jf+7@t5MuIRbdpzhaL-`!NM|Twlt^@P`m6hl-rrdR z);S}^Ip#2OZ}_-Cx~JpauY|pW(Aml7t#SGaxc+9_$%=<4$?F|2g@Bp6TbZ$5FacX~n4dlVu9H}sAK{tWf86OIMHh)l0 zWNQcU@qj#remzKCupPrI>F(DWn>|3xm4z*pzh0{BSZX|;6!pUMgpFrnfN%iVGPS=N zjz_BvVTvF#Hh`+6_Meb0yB3mJ-9@v0g7lyZo}uJR2KezHaF5ME>?BCii-_Fg+o=2U zz9du=$1(OWQ9&&tVV*qD5fORHD%EWgjnc{FHU#6EM^IS}qhU4<{%wAVzx;9C(q3u7f4( z2}-=?|9TAMr4p4I5S#0Q(-A8N)H`|Lr{EZl&wm+ad?IC+;Y zWbtg=JhgwBby@2#=rMH3t$M4jrr*p1IFmf^hYTEqn05^%6hnZYK*4%mvpyobW`98( zxYyr&SNmfD;6v2%j|z{LX{I)w>erXkGZ$bDdRuG7?L2lGE>N ztk2gK>xoG9_WZoSis8f)HmmXmcRyx-&lw+W6&TUI=gLB8Rs_x%TYJPdunB|87abnd zAN{=mAtuMWbmx;qrVs26nY;+b^%}cs`*TjF-?E)-K0uvp+n&5Ro|NaJary4k z`;(jVA{*)kc#y|<)*PfhFVE)m#xVdArU-&@ku$ulqMndLGXv&jC(PFKfZk z6Ejmut6eoGZVC&uYis1=YnEP{DeMb>YQPm;L{XDJ8z25@di=*&cMEdYI;8u%tafj@ zwjr)|w@ny&S_onCCQO(D@4)t~dNzGvq?;@&ydn$QVMKdS!uKM3ke*EpZu08=+8)Xx z?7QW^Ki~Av_rsP&i-6NBLoI9nPH_Lu-cIb*6PcZjtA!tNvi|IROWpv0x+Yx9UX+>2 zM>Sm2Oc|cp$y>N4VZ*&4WCBqKO?Zv(xBAiq--@U33{4G?u&Py>a4lY>zGCH?(ha6G zE*_$P*cwU|<3XGxB;uA3bp`5YjbcXC6iQ-trU&h8LnTAGbyiHPEt{Y3EX^I6*W34{ z@LGL6wrp~lt9|nA>vyYG@15~dtN9a~_Ta0Nop1A}kGmuA9BKKgckFv(X+@tdFNk5V zaqRjr3Jd?AeDQ4Zo$4z-o25&a*_@furz=ZWZVL@hCdzES{ls}Je@6MA?yh|M<+xh5`PzGXC`XNeW{#2>{2iuk3{>O_$0sBQOe*(`o`d;08ym}jaXT9Osnrk?3}!i zJvrq5Wqq%&ywXN8#f=2&1M&o3sG~xzy*!aYh8N|f#^ly?u6FelSQ1ZeWUxsFqE{ZE zQoMz35)grD%Bb0hhdk5yJ|W-rQQb4dXwqL5IK?4{^TkJQV`jln&Lj<=20aG|^+P&J z?76P&R_2U?XWKP^Sazuh6E9&U|AAQ`HA)Bq6G+5Hi8TMlHKMS-q?~@bx1>PMsRp{} zS+U+IpkMR@3b!BA0}pmQ^^CNouI}mv-oRw+_(3L*?pwr#vO3A@q%=)UD#H|*+u!>7 zv`ChNQ8mg^omrrL7F^7}X@kOmR!lcz-f!IdrphqE`1C;r+*OuK&JIrOyh+woywST+w{(vgL+o z%k>k-ex&s*vrLe|0t+HFDCcRE+M=NgV`i#Kt|f*6h0Al0;`;c>sf;r6r>V`u?)OA= zF@y5Oh9+w7V`xmgEE&>l_;1|p(>2lVc@yJ=negqDd|rJ8XG}E3D8AKl(xhpqcR%yJ z#B8R~>iJ}f_h;NmgCBpt;PD(p024+;B}rM8EK-5Q(o5l+R4=c*ild}1Q*C(q)x22) z7O$>(P!4QZXXON%$@09U`=WIlv1S%>4kot&QxK=GXw!aodmu zh0D)1lu)xWM4p-qBCvA(-uJidDaPiI%!Q;vdvVymgi++05ufsLIGXPp4ZJR{Qw*l5?TDxPM#S0#9cGeT zAVcTmG(SeiekFX`V?EZ#33I$NhJDO-D&~o8F*MeBy?xgPIbXJSlE-^Kk>?%@Ztq7D zBPof^>OnM8>ljEL1EU<1MBcC;kRCN^A8Ugd>_$uH2npWh4H70aloeEQ;} zS(v=~1!)AW(Niq^wJ}iPl%L39x4W=VO9zjQhrh}D7DsxtjnQ<6G5;X=s9LEi~Jx6(GQz;6F zXijSv?wWi!*HrIPuqzV_7{yz#+N_3B&Bg>55&LWHIIxte3^Pm@C%VpReL0Ux$vP8T zwr1lmp9IpE6ycv8gU$P$P43&`Rgn22&AK(|DDEaM&lrXteeMO-bY2QbtmJU2aKtzN zt_H(64%G_w84P)q3Dw~)0x0y3>F3~X9G+0e@cX7uMrG3?7H?f?=zLp^Cu7W-_Ivo) z`g76hC1%aw`>sWYzoS_AkDNoId})Jacy_h|4n~QaWNWFB)zc4k zq^OtF@9f;;#KMKODgUX9>SOY zLX@ZBG-HrKyw~{~8mY=*^7xuE#{1*14bFdNtT`(QQAhDv4~;H`7|Uq5c2Y?N7|1wj zSkE;!hs^Cw{3&(%hV4-t%M6B}-{ULcrrwaT9N9yEUDaic)jj5=oFVyR22o}6+JxRd zfyXXNS8K2#N6$65%8H0z`!vANEb%l!8#<<=5il$9cuL-ASnyZ6H&vmuT!PKTfqFo4 z>Y3PAl;xG?Q*7o+w*yH?Y8uxV`tsKr!8~`Ur->zy-Ai1d)3;hV?={hRNj5Qn8Q)(HT$7b7ek8eg25%nePmJEnmnEeqw{n z^HW@Yk(0Z~!W>Z;P6(sLeNta&1&*Yrh(Ok#Z9-<`$aK1MXlBR7;KP4itS#^+4-2v5f3d5~4Pc@B=3ET??zq2ts7$E~^RQ4JLx8gyp-;4jq7hjwNG%#95AMjtl zePFXzK$z~>#P~+}@KpUz-|E(dHYDsn@^v(#>|DV14kc`3X370DCWdNfIVHbtiH(Yfz8q3FR!I5C zp0pw;TCDO0Ey@E%TDS4ZFDZ!}W9lq~D9!-LM;Usk^>jzWj2&ufZUH2)sRp;j*rnZo z{Nal+3Q>|$NEa0A{hO*Rsia)+URjh>MahH!VOYC7#j3%{K=wyTP_s=@z7cR+x(G%H z--#Go%KhQW8WAf0uFF38CTXdNKODt`FsT?X_f$OsdOV_5hG*-$Vt0Bv{U))=4$8Oi zo-mXp=_B`e44l-1km}i@szHnNO*m$7fNHtr=TspU07aDcQ(pOGNc&8&uQ9C5<&O(mOD{T%^P?rV3T$^`VdD zH_|ZVX8=K!IA>@SA3qDf_@E^GOM85hrG;io1%u83eo$rvXAwxVE#cP|Q?=|MTSTPN zI?F@&m(UH3Do)0{(YT!Bu7XfZe_Tw7CXl(P!!>xQ#~auioRmWonX5D8qmiHBj?$Rt zim&4tu9YLuw$KcAihps;h>UD+j-c-h8A7>eY2S)AM6_~j-Y=&CAk-HO z4S#R!!$Fu(xIM*oGL!*wt!UINLeW+-%3QM$IsgS(28N2DA3}L?baou?(<1l{-jb(s zeD4{i0D*%KB-vzJM>r{)U{newiknKTf*b<9`%z0e@7BeV9wq3>0-_|lIs026QwL}O6UUyUh5*Op_hsaOf)Oz!lUcS*m*ZoYAuTrpfuOUX ztbFM`6IwfC($(R9Z$dCDsw(?lzUnk%X$X~Qq+9E~+);^0E*#IJ65i5KD;lZYPY?n!Eos((PR_6Z@7>T0soCA!F z|6**csG?mC#ha!}3!w?GeB{sz z-zm~a1*Y~G-RF+?r3vy@VC9f3il9#(besfrkj!X9V1m5KkE%+I^ofY^sff>qPbp72Fp1@P@V%D$ z99s=c%1X^&xo0Y{@F=P*R_a4^Wdv;Ujp``Z3h_c1DB5)s)$kx3U^P@ugUEyQ1ZpegGUm?3k5ZE>xCq@Me z8LdkATX(KyRYCX?B#nD3;EhOp0acL)iF%OH=|e%)mP%xbRf&m(yzh*G_hTo< znCac)Kl*$|Jse(6g$Za4$NlsHE%L&0YqA00>ixqdoKcvtVEf8UP2)6k>Vz<})Fl0) zKhRIAdVW~&UVTm193QpvOo@@;G~Q~_BCUT_1UEx5Lu+eaC0*SGdkAxEn(3Gr06rI zq5d-ozw56b;G!FkYVfi@IJdGSe3K>oQpt5Ib9}?UC0zQZmBn>LeICyw=cD2wQ|*dw zY*aH3;e$3Y;#t4A*~`$#^RYOTBaHfIeN$KxIXRfF9$3;UNE>d4mRgon6@5W$Wt-e{Jp*#%;dnbT_n@Mb1%StC#~!=H z#RC$9fvwfz=GjBR`z8!gn~n5*OU2Yy+P;ImvQ_X^u{XT&FPkj{2*;n_W$0`3)PFV? zmR7EY4Qi6xrtDaT3zyYuH0G)DFHzFz^L9W{y73wZS(x>YIYDqnv#5`WN1$MjS9g!gNMR%b4xmyE*C}b*=ju#ndrM z9nLRo-zfc!4Bk{vJ+FbbYCm#grx4oHfHpb7cHgqbr;#^0TsB)wxBKf!J@tN1(Yi0J zmI2T2GxS2h?bG9I4XD%yMD(d@HbR2+xxT4ec7qW)x- zq*lq|jsaYAMHoW4?B1h}P8lL)PR_F>`_CpgkSV9x`7B35bsRkolW(R2wa}p>wB^36$_x#8%&mIloCxO)QBO8AT+dQV36Z`= zgWr6SQJjnU;y;Iia#WRnlv68^)Lx11 z_eVA0=%p2pm<8k2j}Sj&luVztzQ5_-ri6{ZIqHgB&foIw)q40;ndchUGg4h)d-_jU;kdKD=1GBCIVguxf|4eJlJzT-PlM26=C3G%)7bB( zGC}F6pqPijS&xIWJ%e*lH_0-=xo?B>>w*jFf_-&w3f68?aDX?sn-~h^RD$2t!`JV+ zf_B$~-amek^zcO)3iX2K8jy#2QCasQH}FN(#EY7`plbG;TF>7#6o2aHgBwIcDsjJa zaCcFKkgR7R`2-YhszIOMhP2g%e2JxDZx88M3+WVXF&YYdNfFw!hwx_)?R^+Z3=70Q z4()%4=<^I6e06(iMLkp(Iua;9+!Z>uc3Yb0KaLBX#5Dql!cfzqf2R&ZW@D8M^uxZ= zryfg$4S9wwPNdV9hkfe`Tb>A8SqsCho`$V;h5fq@+hBjWDf;qT7jR4e<<8@myPp5P z#RB*KSH5`qHtcxfpLJx|O#RE#Uw_weFVERg7ow;i4^fx;sEhfRKRr>7TQ8>!P^T2A zn>yU?Jb?1g1nTb^>K{QIJ&1q`#t&!Bn9O8CIjZ_|si(tSE_jAB1wKf4P_>6jq0ioQjoUAg)dH_y7mC_HJq?)DBtRn8*II49#@RSq%4`o*;>Mtb z{c?P?<^khCV#c9thRC<4L+{nOqo;mJ9?n*pe^e{@^zB#8HO=Eubyr={vs4jm-DxTrk6m zS-kn?iKt12EitL8ybrhH$9?Ixh%S@hCg(#FV)DO=W0nv8vriUeWJ2-q{43Y7 zmAWLZdt8^qDu9Z;=CGDuK&YxXcz3U3w=ppCxjn^CTsrfyr`|8-ALQOB)6#!nAYoS= z?3fgqJnX!GS|#=8{u$oS2e+=G+whp?p?Q!d`EowU6k1tg6oW5o@V>tN{jE3pYN0ND z*pvFjsU{^|u6KQVmBmG5&w|kCSs_IT9@Z*0R5%_kh>rr}Xvunoo7Tu5G^85SM7$*1 zP@!V-A=kSGsF4u$J1BgFl9TDG5;iQ&JCvmU?cgAZH;i+rod%oKkKH3T(Ws5H>xuGu z@0~6?fIqdJq2?W_Cc2G;QAIXIEYxz=pG81uG2KPo9C1WIUHo(WEWl=M#Eo)X!b=7k zKEdr+I4Ttlm;419f8Fc*rhx+(4C#%6)<=L;HmLBfvA?fUIqNytSho1pQy_II0qr9! zKgzS2;XRL9!tbKUa?#9QBUYl5k^I=c&ZD9CWM1LQTpW&y{x?AKM`yisgn5Gx5uAj8 zVl>~A9())FlC~@kLpErtWuWpd>)|9JnIxnE#ZB`b=WBjT%3eKL?sxVMeN+7U^(-83 zm~e|FvrXB7{2j(lc7u9v9ULE-7M04nLDimAM!xMu?s2w3_ys$=I%^QEb6KwOmhwXk zn{S^(z(>Og$q&+4%{VHX=$8}AG;HJcI@)ud`3tg<67O#6t@@2~`kL4cn0$#xSse&+ zP(ewQNeC{FSu%Vz*~nx)N<(hM6VK4{$h1_3%x3S8#J-3@PQs-znb3ikaT`07)kXN* z7Bs~N;eBd}0KrI=dt#yRNZLunOoru2BW>atA!YI zk3)Ws7X#~lY%P2CsM*-j0Tyi8!5)#r#q^%R-5 zYKTQ1hes((K66nnLq95$PHcQqVD8FHGv0x;_&{hU{WOZ9jTU0g`Y4NBVWF?pKaaROXZ>}^z^P%OC!|TDoN1^*V-a6wASRtAta)4xtt^N2=-xWHVL%5$3WOnwu_dlQs;+s(m0fymwgtpIbIA#%sK(sMR$??6 zDZrK7?vT!+Pp^!K_of?`BX|tP+}<10ALkJuvRu4AeA+^uv1`R& z7U4&?@u>ha_ev3VWQlv$+tPWZ;auYuJ(xwGx?uE9=eUNM!^m0~a2yLDarAR}zc`K` zMLzyaL%%H2!4srfEh_#PMacC-OcZVh6UT9$7&(Ec%U|HV?fjc6DJu`RXC5;Ia$1#m!hOVYl-*wohmZBSB?X~g>d@RL17aY|Jxot)}4)jK$A zSUZ0QyOmA?$e2jmP~S+nZhbEaX;eIwj@{z%|E-bmU=G4m)iGiFU@0td zi$q`#?Z>Bn&s?HWT!=;VpFcg@??P8_)^l0}@@K@wpK{5Ae;G6-pVw?Hn$%4*%ZL@k z%QE4=+p?RZijS5L{l@abcwF<%h3NxKAj2SEd`=+c#yCEGlagLkWSj4`O%(i6A(h3W zA=hnnwo(o6rg#4AQ{?OM8KiLtw|dzK!COjy|i@4c7Fyd^u8|r;}?srg%sg;`W zMZwK@KkAfP5@E?CBe*X?qL&zUA_)0x1b=xV9}mXCqA0QFwGxXNQ(+>1;SR@l*5Chf<4fILCMoCcl($m4pFjzW`1;ABGz3;Kk7 z{kJ+CcDxaE<*Gs91Qw-{!_g5JDNXGFylV()(Lgpp+q4Nm0@2!rJt^AnHq4C4wRGi%2!gRpKZ@`Lq59xe%~irb|g$a#j$?8-A4W<{&cr z;1MZaNRUgpT}8ovBNu||f8u9-jn;B21>UyN=Kni5y{tf8<|Hl;M6n5y@f_M+Voho8 z1!BX=X(EbIUtMa}`Hd_NjjqE>m=ZpmA9Ax^hZ$%+D&%9tJTC2RaOmC z7WE%mw+p`AWPCGqXj#vrir7|DVPZLOeY{+$4iHi%6sl!AIvK2NT!J+IzsSXNY@^vx zrq2Hw7fj{NFRQfu+|nl_#o~mT-k|Obt6r5!q!S(Xdz;TNqR?_VI9P-QY+Z;Jx{MUj!Aj3YeyLQG9iRr1tmpQ|T z> zTKZ(pB1JA?!Z2mwb)x}-L|8(D`O z>03fd(DaH!Jti(xWbHh{4bZ~X-#v=JGS`@yN>v$B@Wf%I&{?FY#&Lxys^K+kkuPW<&tPX*xcjIc7FQWHO`mln}k=DxV zd{~)FP%l-jN|LZf9C+_()Po3>)mr!M-4k1d+O5MA+bFQuB}fE{9;PBdF#+j|BH^>C zPlh&~#R%_SA3L5bxd56eL(9;BMJ|z}n~RfApUa1%2e?#Fa&Yv>QluC|l`M-0(hq&} zGg4FmeMp5K*+ky9)ZJ_%#U#<<>ye`lo??ZbzqwSzCr_K9;9jmMNuFYMn>yuck?RD{ z$)~4313Z!SN8+t8ET4*a`{~*6X*VCmI3E_aefpR0&WJm0zK)bIz{-}KAicnSZ%*JW z)ki64anu5`?*;k>a||f<5}Q07*?dmCg)!%5fO0kj|befYdgqI^#PA|D2 zGMABU0ci1A%s&zEUMKwIP>lWAIlFcZ$E&kl6jJOEbU_7Hp81Md6Ym|-YP|mUeMA~8 z7Va&7Eyf|!%XRN=N0RSM6zF>&l*jmdBxHLj?qk0TMv+z>NnLt!IM&E<)QBE?is^{T zhL_IbH?+M!nw1y7>&-gSyATm=xYfc=YBeIyj)tH1vRP?kpQFj2or^n3aK-v8J%@E+ zP%u#$n%5r15PwRNUoZnrzej|qXh!4ze zSirlqECNf-A|)Ol5Bpg5S;Pi+ce7xN+M3OclyBe@}3f0`s^u&{?%sd`_BCdoG&_4;3GuZgdeTc0ESltqs*M)OFCNsPsSq-2uv z)eAqQ`LVi$u)LF`vX|79ZL`LJKeD>X@RKBR9j>G8I}sz<>k3wu!1ldpMk$F(KlbZJ zP+!)F{nU$V7J&|IN8%gvL5#e|pA_M=o>AQGAyBKv?7n)4l(qxAo{EVV_DXPLMNzOP zZ>3#FK%%)P)IusQBR=BjD>imz-4DuAXU7vKNS9)1X@eh}U!KcdR@ImJsWt^%8+o`h ze{y~0*CmaeJj6&23O)WLiXuJo7G7vN+V$a7hU|-AsWW=)fIdKrIqapdw(m84$$dn*3Vdd07gkeNSgh^3XG{`*?eQ3ZXD$}Kgj*XnVi z<079HjGiX(#XeMumiAE37t?TfB@Mq72ct@PaIg~}ut=*=f>ok9sxk-(Xm$J0e0UMb zgT6X^6C|qPc$)Cxxxiy>25LDluGK#$5ZU@X{RgbzUU30V=FfvDNI|Rr)+Mq% z0IBmFJx~)(-==&g5VtbPs~^i5RUJFMP}LFRq?R6d+RLo#AW8Q@d5ufi+zR~x_4`U( zN-|2A6z}Q-`b9FkNKC=CT#y{{^4in!W2#WEh~MuDEAY&)Tn0Bb*gUG7q^;(y{7m{U zx!+m#j9o65cGv>#29NuQN3Um$aXzrDE`&~q0HF9j2z?pMZsUurv%Q@F3Id|dPY zkagE@QHA}#=%*QA7=~^bIs^%kMu+b19wbBor5h(mB^(+-a6ly#6cD6g=#VaHNks+0 zKvB@yJkLJgeXf1ZKd{yhYu(qi)_uP}ueS?WX}`%%2SUDdT70R$q4`vMmHH#$LYw!b zRQYYrPJi87Ifvo?(`>{34AYchUjBrKI=dI6j&Fi}s27rdMV%s5qy=7V(uLoCewjd3 zQAt$(IeHjm^IB*4_bcj?PzT+mVafc(7Izumh_PZZGv`9p} z3slpncf{>azE)PO>p0&@jFi>2eH-qc(lK;3@v3^FvdWQaf83Bl4S8Fs-yvQ*H>zv) zwA1DDf)_-aN7Y)Or677e&bwD^pYZLT|%7(Ip`?3b_R7V|Nw#c?F_9^s#kFmL4 zzrMA^@Zm^tt`S!k(HicVKWz|Tk_IlC4B|fhv3lX(Zr|^m*x=#Ge>&3f#P*u4l*Y5t zK6;iv@jRW1PZa8@t(mya^2qom1*+ajy=L*@s4vrs5hu=1IQNUB(T^gT@K-gNs2ztTZ+Z_Q+B7<_*^fOqZ`O+87xMV%pHH%#GO@y^?u@zqy9`tt@44uA8q)T8Rmp|3`&jz{()%R=YH~&QnH5#a@};BB zEuZ)GWs2_X@)g^h-@PVEnldkIs5VMnBnrONPj3tI!}cW5awx@d245RU<5G?|;|%d0 z$&vK8jpPdT9WPdm{CUO|<~RM=s6Z*6yQyvTxl?n*UtG~w72m$7c?C`@7xaZIVP_lP zB!ylJsdZ7@12dguce~Q#^&DStUUYZP@cB_uv!IyqzGc(eye4MQUpDslOjlThjK`$V ztywiw|H-h8nE4FDTb!=92l9`(Ve8_Q8TphVmxt;@Y(6nohZ?;vij5zK6cO&LC7OP^ z@Yvh;c}5}5*Sbwi^E(O@ton22H~r&KezkNS_noxVV)q!e4{ZK*v~{(dn)i~a-G@8v zmW8=@v<>yZOv^7NS9(uV3wODtuXDMWru*gZj26%EJ_eaoTwO`-kt+#`nI33S7}sDK zSDZgLF3vM1=f=hE!<-2Uo?a7fZf;I&A+jF4z^XpBoo0_MYQP_Cd*lm-;Fy`f^?R zT)*NnIXYwVpi3eDK`ykbOA6Lw3^M+UTqwKW77?A{@h>&X_2_H(*hKvga-kv@`yb>& znd|=`7nj!^>r*xVaqj$I$i;)*e78GX@2zRl9=!km8W%dHPXF7uC{}eZ!u6AacK?H1d=KL}v_1GAr7r9uwecq?^ zU*ux_=1~0G^pl-DkJ9M)OSk#|>^*&Sh5B>5r-J` ze$0E|zJFg+&iH$>`>6Zy*Fm=c_3ZfFBkI4ul`Km4Pu~G(9Wh{j6oJ;3T$1`4Lvvn! z!<4%Lk;FxH!Swf`Y;zkh)kQ7FJC+F?iHBWWK zwcqcE{by-RAwc*jBz|l^#B~&EE+hiuuY! zBJ6mBRuAFPWs#2`Y>i!*83-~U=(8$?(A+bIYCuVm;&+1Q4UKeY*P~Jz=8_qT%$k__j z`H$w&pNt;SQ}<&Da*lp)2-giAnq3)gx+ut=L~p?BDQJZ8v(AS@Ei@R_NMQ7w6eh z`-UjpgPTq(&TsDpK6sgT5OBlAWomHYb?ba>weHH)n*NLC9=FZg22!ru&q$4TG`@s< zC~#F#;As2o9}rf3>X_GwR^U6rgtvZn{Log{j@#Vz7PT{JcqV4w@zHLFIk4LOmvgZB z2R^6h_+Rd)+VWiooriZa3Z4J``<3)gh8Isu?a-mJbN0*(_z}5GudXO@_CAXZN|bbM zqjliyD-r&Zth%~c2Ak>=WdE9ayduZ^h;u*^=4)fOdX1xdF6uzag8=1xUp69;Ghk+Hh^S`TmBDPfv>L(()zH@$Gy?&MYfT#fbL8f){ zYuQrrb5QzG&b8*ZQPkphkNtD0ynj3#FD!k=>+fW+vBD&-g)$JGe;@7tDy1Q=mjA0ngM(LjomwygB zDex>$6oofd%SdF|^Q_c_DCWP)Ft@vX+P^lz*)mdcDcGxK^`rf-w!CD&h;E+sulc_^ zKH}VNvl{fT|6cgjWz@udhsv|@^~x{GFG#N_Gw-I^JZVEfyigizj{)fqBPsZ`N9y|h~kavn4)2r00D70VVxS3Xb;Exu|}r2IDeT1RW> zBbN6SS2<$z_f^9lO)i=O9sZnm6NOe><@Eeic#H&Yq2R9r}mzUNfn!EYF1Q(pHesqs)e@EpzjDCB%{(C*Lo62`Y;5gf$^*Cwm z#wR8_oNWaTeVY|2{hC#9wj=2g{l)elSk~zJN{p-1|3pi-KXnR{;!IQz@yu;vD*TqpZyMZ4x-=1+MQs3 zw^RZVSk&Kb4;+5v{*|xAFHgVRzIrm>eC6jz_tk@hcfV7A5g7X?<9>7td`)H5Z+O$a z^1YAxbG-7(m+srAJR9A=toL>nM7VBZ?>b^|5O&Y#PxrmQFaqKaVZIcEt|yx}5OHq< zW(#DpEn~Vxp&?>eZF`vc<$k@t&N@S;b;Z+=@hIwy2v;KZt_B*yY8lNL)J05%d_RQx zV!;l#*|>XX6iMKCEbJ48&DE1Gf!=|aDG9S zw2_CfG0gdGQFZ4QsvJ@=hz+m_!^pAy+n^7;4Va~2b)`T9FpT`3tjin7Ga;e(M~q-F z>e4k7Q#p$o8bYU)rFi%+Yy+B!MZMnmYfGT91F}{z(nt`%^L0!L)68iAKnWU!38oz} z;L+b?9_?Y!z(Ot(P_sQeILj$yG=<)>%mU*{OTw~ulG%hneCC#LM>I4S%ZL)<1ORE( z@azO(Au%9RlN_IZ88blg`-BAz^%iAI8iM9I>mqgdyr*wRt7Kosl7Z^4*vc<4<$l)V8mf#!Qb zpo27kLjY{4Pgqcv^y8jvWmpv5bjC&5-w_)OhJt)V5%v=-^V$*5d8K3j6q~IUi;X9n zwIK2zBQ*?zG&koYYcXKH@;%lJt!Z7>LLwFDL{8 z14^mm$ZWGcEQlc30+xk;6Lk^D_Xop8^j3g%@Nd}sw>l@}@pqKfd)C=5eP@O`P5 zsaPx$7R1s4_(Qd}X7gkI+Is{~vOHe51RIiIQ&?^$ZJrZstiB-PCK^gXvzSk?ssW&X zNOE*_kR!5`KLzGG&83A$jrAZKzp=c>9dVaZzzrL!_S0~oEz~;&(FuZrKL$qGkU#eO zb}tns0u+=Zuzs~*vt{OWvxch!nWXCY@{ZuFRy^)nu^naf))YD^1!2E3@D&U)S%`;O z5PCp@TB0?;)=>Pmgb4=OrbVYlR=T_;0ac)LK^qnwaY47a%V*F8n{SCWIC|F$c~-@q7nhnWU_?t7L;B=bV>`=m_}2C=309t zMODW@F9NmHD4IiM^lD@p>n#aQJWU;$HjI_NW@AT;0A;q)_=~60pupD2MSB)s{48jA zS(IT~+CBG~FEhczDL57xpqSnftPu~A5tN&@pn14~+>qyk=f-vrH0-A64XyPxv6`2) z_0`F6B82xQKx4K?$}NlCkqr5QVN<8TQZEVjYQgEUO)qbu%m5efdb7`vEma%XqtbRdZKE`Kl=@oFR(zmFq~pN z7pAS50Gr5RPklQqOZp6S>Xnom_JSKwzwbLr6ANP%lx8EKMm;ZI#WDniGf zA8#-{JdZw5z%iG2zR!H)J%Z~iAjPb}K>#M}9va{#w1E}w0f5L@*)$&_D$2w?HcV!( zvjaA*apQuF*DTvLDDa6gU4|(E9TtlWTZ{Y0Xwh#1*9mlv7<4nU;MSZ#28I)(b^iVv z%CSz$O#=O2y64Hl*&2}&o@|PnjLAB19-z;VCG$HA8uCl`U2z_aAi@=|>=c9n5a>!t z&}0CeRGE}hmZs|LrAe*p2bQp83Vo*cMSmOy`WP=#{Y2q2GXvxR?V?7l=7%Mq2}5GD9CGUaX5eTPWe zkLpRdY0#QS8C1*lv!vK8LuWg19$t;}QyDVmYAN z8*wYmF_H`ME6VX}9Nt@R&qGUhF3{3_jXY0<72r||&{U4dO$U5z0X~xB&fi~gY%O@6 zbCi~om{LFxZiy6EiA)L+lypp3`-P`pBqsgx%KxzA#}Q~4b<5Oo;+^HmJ#0ae%VLtp zNmKww^7X=G|Hb6noGCUs$)SZQv5P6V#rqMQsVRl2X`Ep`kxoeEUOJj@UDp#HapLYh zcDz?vc<=e*y_cM6uN>2wRqkahrgd|s_c^8y6{f#gOrPY;n03r}TbQx3nDLG?bK5cV zLt*CU#mqy_``;b!|0=wHx_F<;Njjetr+Gl4Um`JbWwAJAaXiT4S;`XNnrd;(7Jra^ zVJTadE9a6^j&gKtQ)cj0u3R0bT!RO>q9#kZ7F>BYPI(Rw@?4hknkU6Pobs=$=9%Q@ z-{va#z7U|NiUt%MMS!^eJ0 zPk<7J7BvwRSsFmgCk|1;+hf51w_3V2Zig@0Ajbn^oXBTPc|rjmD0{}8rG6mSQNolOM~GlA(FlYN&{qo z&XOQ&ABJTO#*Bh68QCJFp0q4uf-;S!9vtePTc19fzqLz6< To^=Lorl%`?+I!52 z#4g^D-yg<Bc_l>-j;%keykK$ zWQr&oo_ZGW-Vgs<1nr8@OpU<#0S>Lv-|0+b6Z5;To)2RefsDChhX zz`cP%wArq8a@}sBov=_j8y@78OV;saJJN=4H@LV~rU-g35{Knkw=hZ)axy-U2eg!0 zl;nl!wiRnuLSdB%WCDhkGzf2tvG3!QwRLEI@XVAYhynV0qHQC7F#u?o zq%>R3UawS*QPORng6tSueoK8ZI=ayYdJ-+)I(u&b1rBnGCEcUdD|XOXA~siGIMj3B zYbA40$beH?w+BzB`Op{(`oM621MgR<;@8ZSvx(=@FzS()PEjVV_QOUZ$E}miRPh%l zTj>JkKp?Cz@*BN;6wM*Xv6shBhq;gaQ9k(c#`AuZAcp1RA!cd{vilESgXtjt>)mEF zLIZ)zuT`dVm~!c50SX?rU$npd;RgV5^_cwk=gh>#FFEv(hWEbD$-mo)`QAD@yzT-X z@8`PZfMz`&{mZz{9|N7FtXEvgl!6Ccw@9E#nm>YFDFnusA8Vg}o*MCTatE9^v_0_4 z^yH4=a2h+8{nq*c-`Wg!CT7{oRgx;yn=0{jl&(UynzxXtLP z0{JaG?%m8dgcy(xI(00cxxfkQmrLCs`w^ zdU8>-V887>=?&FUun1Y(Nyb})zGV@90b1OB;|Z`Wb_mFOL`dQ#8&SO;dxDbnlMAnB z$XDSZDko~_Dp7#F5D6S*N9HgjgQowipp|WVIRM5tXBtu;vXhzU{65|{`#!5*no|JL z0H~yB;6|`$1;AC{Gr_>QNu#dU%p|RB#oP;CPk(Hq6qH0j0;%>9W5No*J&hvjLN~^c zHmXL@4fm80iwWz3F;k~NG;1n_tH4gdNDm8aW#-Xw2Pm}cgrqZL&3;hci?hvHDcw1z z$ULvJoAokSru_EJuTaF>ssTU{6yE5T0(Ag)whsgSa>|!@Cy&?QpGoTuc`}MmP`{vW z06-K{K+H#vnLl}>ERr5anic8NlRH!m z&OewkPr0@NU|hBHtJwQ*xKnY)36CYXkE;yLKAFRJhJh6~bxgfeuK;)Pl4S>JCLkPf z$5es@a~DtXlV>zD@3SQ>O$&yoeN@k8k^6eg>=)tXp~L^7Ir|{_1w|1qdtKCl=={;& zS1ny{Zj`vEarZi=+Qq3cagks1V*tGthps7H!jav(Lh|Dl&0Y$=mmTkLO2Ae}>7ggx z6VVLmjQ#<(z-LM%G1kW6@Uu&b4LGXnlgz_Za$tB13hda_G;Ctes6H&X`4?)r_gGYi z_`&u`XF>t9LI04^mTp&wqHLpu|taxI|_!Qp6ZiYwB=vRK|F4^1(8 zHa%Nn&U*DkWOCPr35cX?VWWY|_X(ys^E8-BIH0?jvZQs>&y7+fro*@zfXMAc?W{kM z!GDs~-J@f=@j3GaAjjbA$K(r(UOx>_34v#E4l`$6t=){;KQ#dFWKc;hPSLyMh>A3hk>T&-Ss=YWEM$fSi+{6WaZowgaXxCc|sK z@lv+DI_u|6L9Sn{l_J^8QozoXmp<^y_VL!edi0V%L)}92#Id-LKGZTEUS$tf-pWuA zs=pK>6Pb3Ld4JhKez@!!VaWG)pqiFcw||Z-FrMePW;Npi_G|XDEx!>Q_TK7 z5~FO&l@Q~7=o{1SVpjv5ZX=3L(I5Q;z%zjKH40!X^m&VS+z+4};u@Qdwv}Qy#?!Tcfdgm8F5JXHIy?j2DXZo&J`A{k6j8t+dS}?N1j`1b< zEJWa2}?$b+~@#D-&fCpo{|k+XTqtC?>bJ&804fy->hNMQI@|BQ}}z znNS*HG%mCCLE0@msgW9I3x6lX>ZB-1en1`RdMT451zP}+2Bs(dnxWx*aU25LhCqd<3g2wG_Aj}%voMc- z52f9~p>c_Tcjpt==ZAyle&|zqfpAuR#wZ-BOn2(ng`_5wGRa_TTU*Wdu2og&tX))s zmePlw)bmbexm|IEc}oF+MLSS%VA{}e27QN_L&ydwfW6wvp5CjH-tU+`7?tj6Zvrm2 z;Rv=v)?fa-jS|e(c@V|V`_;raix+@l2jFpDw2A<*9EN#Xqxtm%g1 zur#vMRr)bvOg_{-CazuWI(=z>CO*n5RNM^eyq79al)3!ZEyi*=kmC6d7Ym0n%ea{L zDKJLf{tB!x&$%_vwk$&_-0N7`)ep=&mcofVk+Ih`EY3EAG~EqllZna_TV&?z0!i0` z?t`*SqJaD&v(l0?a!!jEM=uMQG~C6Fm#2&o`BSYNE2B`%Xtnpu9FB_03ct&NMory@<1BzhxuC z`BXRT(sf?yv^w)8uHX^XEl#FF5G!#uvLss)OyZ;U7FH``LkUa2nw2iL=E&K6;6W5S zX+WQX{G%m{!Uf5)N0tkB(-F&LHg-S>R#6j<7WEIUV8I-7(wCQKZwIK- zaX+!g+s>35w>>dkeq#RTi6!^bdi#WNV$p*hEeUR>;%&|V31&_GRBrnxO;$YEvmZLR+Ua&uFCvVMdGf` zR;$i+uFj9CE-b1pYO8*@TwVI-yuj~SPEw>A?mSr5Rx`F-Q(sikMpqjxRU2$y)g z)IW`K-TLLhyYhl*seY9^b4#t^NDUz6-yrG#5`YF=yzo+5{nck`k@~fwS3oC~g-e$vkZ#@w8^Ex8}OE=Et@c7Pl7Bx6an(1Yc(7f4)caseS?R9 zf#6b7+cr=4H}&oxF5M%~8SaoE7z)@8ON;RA`p84M-`)il1Rtig{Vb-?bx;ti6r*`$ zH69{OV#aJhsIgt3hdpVrh*u;!SuEw~GetNd0$75VIN@qkS5~ zx^CkQSo#HIcF=$kzMn%7X*JgGk0@zTgnQ&i(V@-ad&Ap|%2g*2LQ4GiiT&3-ukAHOfX1Ao+VP=`{$ z!z(eca|y0u14%prDU)d`NpN}~`~VFigWe4R zZr5nt!q7j(&^OA_eBhT%SSwP`b%N z+6of2HrD(ZIf|aU=GKSPK*QoY=H)CGzR1yNV0*5*Ehfh=rZNZ*9!=kGN4;-HMb#pH z$F+Z61wTVgBCM9$$YVhuh$EJ^O4-v!LdPl4%s23+J&1!r@y9Z>7@YskPZ^?+SSkXGr1PtQm2YbZG~ zWdC5@<-E%4!kBUZqM-(IkOBQ71N%az)h>bbX1t9?47cu|Z%8jA?`*hiKxaBPdDl1j z`B`7`g74!Pm;eEYIJyFohzaytU0yUty^uK!TA8-iw-iAppr zP-g3G;FdxV{JZJYPWq(W(fDU+@Xz!~4f3QH7DxL}dMu;v{L#atYv^n>m`2Y)W|njm z3hFAAzxDcG5T5VtX9U>o=tJsQix~1_C7CY2ZdyYQhRcLgjz-r5_q0mh8^nKjYDr&2 z0V~vfAOgS|8_-G&{j-gaZtkC7-}!t+W)Q;ElK2-Xd~xn_{F{T7ZHJ>~whlAw)>^zY zZXYT=o%5VFoF4LRVfoki-fPp*$P3_)8uMfO$Oo%k0@Bk6ca+W=@-B8fH|GsteuY7 zbnANt$Z0Xe(UOkEZQuE^KhVJW8VWy1$e5k&P}p^1MI750DxjKlE`w3?Kb4?*3u=?uR+`ho!)=_0?lr zk7Ik>vE!rTZ+Fh4sK@TqW30eWmy18VW!pEUfBHT8Ig^3N45IU){tOcMRmww;3&7HX zR*|C{@CW3daqoVO%D3k{M@C|S>_I^7BQEZ`aIKffSS(N+dxDYuRr;Auh%^ISMLxFt zeW&~P!$Z#5I)?jo5E)Cb1%Ni|5V?=1OTf_Tp&^xzT3<{7jgY5T>V6>wK_>Ea`f{g0 z4Z2Gt+6VN1Oh_Po63q*BhEW{q&jk|bDfLfj@t^1K{!GaJE-?9hOPZ29xmMEsca{>UsnK9WtW6K#(FT zDA#;e=Re*(Q$9uNVS#dfwBFZ^a#Em|Z|xWcEh~oDCwlKY&g>ZFN-|irF@H7KeN*s4 z5fI~0fJdEMv(6ffxKIBv`jAacZ z>DdY^Zr~GRih<;}ZwuzMyUBDB`C<#O?L;4*;)nZ---dD-okj;%T?^pu2Z;Q+3YIG@6z)s3`yLk#!XF@YrRSIXzt&uwtxHY ze&&AN-Hs9+h6+R*@>_IuRJMO%H+QYN*!8|jLPp^v=pFJwiNrlWL8zDp*M63Sv|kVW zSKJ#5)#9zw2_hRt?ukg)R8Ws1AyKubYiW!GK)5K~r$aICr9C9Jb<>K)+JW z1l}!Qh4rwrCo=2p@Rs52f2r|NLLqu+=89X7rZWRX0z>FS4MNGYDayXw$^dV(TgT?c; zzD$ubwP3;C`Ps{aV{LI<6>bW;gyuG;1k-g`SU*aFli(; z+}775WEaGAXW|-^gj>scitrcB)+XQ1=Tt>$Oq|qzy8EZ4aZdm9>(g5u-xp$Ucb&fe zWcx#;Rg%kE@#L#5Lng9ypqTDz918<7cqkuz2miEEANxnQwj+Rr&SQa%aO`A zEGirFy@~E#!$T!wQvOQ#+j z>EDfTu*u2JrI-&Tz9A^_-5}2}ykid;pt)xl5t-OZVW^`FxnG=PQNF>tULpDRqU8AP z1jr4^<{o!qz@UvfCedIl1@mK4{#arRXWTp*&8e3)|+gX^N@WLAlz;E*eInY)qCOf^DD_K3cQSekS&dOjvRq?43rdD53XEcZ~yj&`;-(Sn><7I8mS8HRv8OO8&m5>orkTg$!xhes+nYC%KtD z`pRlS;0J{WlTV~1E=Qv95T=AiBP(-p$s{sTdW$J?(OBtgg-&i`se0x#yBD<$%&mp) z@r0M-M$JO35%MC}RmY>v!zye_oE{{<$j?u_5tl%>P(J~!L+QR+^)CHUgJhr6GRSP) zO%LcvbPmZLC`z4S`PPVxl1PM>xqcOUIoumJx-$rqB1Wo~X(JRGkQvFuva?2U^C`z{ zgVq_o2d+7}MWMhb1%)S2t{XZQK^7*?f)#$a;tx>X7`}&HAQd_~kp7Bbnvf&fTqDpg ze4oo~V&gfjVHzmjdWv{H+Y!$ltVd5I5d;W~9F$Efl*$I}o#-E7j5RkjIcBpQUxPi2 z3+?UL!icYoX{#^DY4b1iTc()9%Rh?*crwH~_KPjtZkx^2aGRpF)K#K3Jf&3L4A90U z31I9S$P#*jK0_=E^-1A0oklzy_ngL!^Bcsu)-e*wV1uw;ra(>~{kH?thnIsQg$DM0 zh0}})iR_}*qQlBH*o48oOt7W2qoLI{GTK+E>ERj&TL`_|+@Ji0m$hIC-?ZsfE1@iP zIbHQ~b+=D94?@9T^_gOSXdD-NP_NPU2 zQ;wD(x0e|5=K9Ep10_kGgvr&qYx4V7$Ff~OisqRoD#fwiiYZ0LIphl9=1w+>w$I+E z-1YV?Zx(R;T^B7#l$=r2T}2IOe7q$NjWkWn^e<{H%)eR&WD z<3+prM&iR0Z|5LK&uD+2_nFF3%nlpT==P{rLR*OZM%zMk%P@#KI=%HK!*RCweORTY z*n%y9mVxVc;g_wdqQhHR%^pr{q9Yt&!djy9n3Scu@#*v9QHE~o`UQ%7~PxdmHW8_G#LByqHsp4Vixx}du^g`MZKWz63fE?|z z31rs-_Z9U*E`Q6APTlxmbu@as;GRLgUHCcU095n5I8OE|vg1#o9q~ z%bR^!4A%s^lUVgjU2&OM<1Ayuii^$BtYJvnFL)rR4J6PPZwYCR}wCpyxw_5;{N z;6WG+$`vDcMv=>6mU04BJ=eO?!?NK=kdOf5sDKcZye+uVKSvgm`IH$hRSn#u043@Q zBsY6lqO_#5#OetJl12%lDnRZ;;$| zKp;h85?896w~j>5RXbNb`vAQH;k%bPpl62K!Oh0f{|JJ^K*uCUO&%xJP6?~-) zLN$iGZ1ux*Y5h(fTmg{skMyG-8pPBX#KsNO(}DEjh$5~AxHAJh0v`X#Kulg~m^7N2G~p124FM+2 z4~Lr4OH7-(BH!9US+-Z3Gf=qbFWy*r~fPTur34)pam71Rxe>zam! zjkWe8h94Sr^N#k_3=@K+?tC(xJTsj_m>rTCr=`ti5#x{4%;q)5(T-+s5oWB0l!Z96 zW!>?)^XiEo)su5(s}QsOJ)GG_m>G2jVV=!xzNKNlqhYqKJF#nOKHHC64>R9IOzZ}j zZ#}ucH)ghvF#G((d~<(dS;XupcVdFq;+vxRzT)J^ICFXm0MUY6wVj;lpI8x@T+=mY zTOK=VwD<=Z|K&aLFW3AC0Azw&p5|I)e;a!jX9l@!N%ME?Pn;!fCvK9qcItQI6eMZt zpx<(S-+b@P0$E~?(3pVjjzOPJFl$cG5-cVV6SP(q`x|%=gH?>N6?2mn`@z^5Yw9OM zQ-Qx$Xa;LRK5O3^)0c|YLT08S^Lq8eZz`rHMKY`?i;1{+NV zTP;3YZ5dk~OY~5|M=S)cG?(^+nTM}R#Eg<>gG(sZOr-X ztYzlOQ!}eoNERJ15Oijw(BsPCM6eJGV7Eocn>DN9TO#nVlz}{WTeT zFHL)IGkYI5d*6e3hj{ytd-F~u_GJO~{&ox4PW!+$`&$S0xBo6&OR^6RFZ)ck59Kos zGIMYlw+|0=h>UlLg1!wdabPRIAKLl$VY-7)6G0pcMpNt}F59CwfTETOxOs;}Jx8J) zSj5s^kObk!0UY>9i5vhTH6b1tGw%2pW4B7OkNfM0XSHWHbaZJVT;7Aaw1DuJ4SX`d zk&dvuaXYS)gd0-nJolkal?;n+ z;RI#JBtz7q+h0O;ZK7v5A%`JZBo&CgY`~cccEvqN_OgU3Of9+ctrX}vyBq*#_ngA# zf#>^7&W4b*zjmTkD}A=mtA2|dc%X6}q`1kxrzz1EZC}7Z)68ct9+mnS>L88I_B>ju z>~tNIG2X}8Dvi5NY7Tll1)3j0Yh~=4YVD>El4g$Q8L@;HouE25hkCx|IaH#@?$Tg9 z4#=m%FqTl3ho`F}lr`C*QEna>Xh{EEgBOjeE6ruYFeCb_p`W>u#M+oPHksM{cgW zOS+cCF(w*?Jv)AMMucIa$RbGD5aJTJ{u%1&*7=UM%Z^JW%Z0SD!a%vO;pv$K9I;AX zJ@)XAca5A%bUvOt4BXPXvHUIL8ZwSRcLcP;!hHQ;R)vWi!$A8zsN7E|PVP&RLn@GG z7^r`;MRnguvYT?|BomaeP^CDlJ<+i-oHqM8@>jK2CrQ~KxKbPJ)c@)9p_Iu`_{*qo#eC%M$gZKfpwb;vsrDlj8}tF%gz)A`a{ zz`Esa?m|JI?XJ1IVR2rmi!M#>8FI-SErg4OJ1v)YolBgIm3;E%2_vB?>kO{ab%_Kf z8s|dr>yl(AREmAYrgPFtM4g*!Cs4C6%l@?;A12YO5az7n&#I!DkF5$|Mi2X2|U$;+DR0wC50rrRIc zW!*|5UCFYodgm~~8-e%aOm(wZ_gQP=$hO>CbGsoT@rk(M^I8U8YcSOcL7` zz=I^n9}^;=`cVnWScpQM-!%&OoaR$q@RN`OCEtNc?D?as@Hxj&2W+0yUV_?{rT%}Q zG>u}^L@ zH-aX(5G+lWrhjk8>6dr|PIF@c=um&t9lCsfDp@ymiPI1y8pP(+av*{MadP?xVjxDt zU_&&R(=zaCkmu|aWW^q|u18$a2ca=rUf4kC;RJ!qz@3X*&b0t867OCHcAkIpS}5-J z2osGFiTK!R>xy&W0XtZ0%4yGhtMQIMB668yGzb})!a@4%TL|HqTAFiPqiFis0K;$wDw?$0dao7Apa11Og-E`sern2P*;v&aK zm8&-+{gME8fEQjKmqdK$Ob#un#pansJiLy0(S8ZaC$e%AHK_` z9G=*{{jceial@1QWQ)sSO&g7E9yoas5sp?K5~cb02kERe8Bv7X{TR5oW9RDq=fr=k$rXO_2q%IM4GjT zy8-s5wmtMBSFuB{FG(K{H_phe*WWt$^Iy1c_C?^S(wEh?$nRecPL+=~dQ(_rZ=I=p z+ZipmboW{sd`|W_)bgqc~Nqh&OmxMlXz=Q;SvcuhYmcd&?VF|0s8Q`|>iut|8 zR!dCN?p#PPI4+sf(fy%~(Bt8XLL2b6UNW;#>;WVqE5^LDR2WCXtkjz+-u9BL+ridEEOgdd>9yd|M`WMFw?;qYZX_Zte$G-d5vKDwpZ(gJ`j$8_!zBiUZqzi#-e; zRTVD@|KzK~dR`5deko_FYL@Zqaqky&TiDC9 z($5-)cXaNR?3E*54S%9xWW#W=vFGnJkd>;9=Reif8)rXO_X(btvag@u&O^k6shdcx zu1!H-vQ2-JX}Ej*<4IZ$@a~J}h*9Im$W&ML!(?kt1rv)Q!*Akt_{}FdB}^t7@&jxx zaq@#WF8>bsq4tm7I$d(ZC>@0IUZa%Vy)LxQC0L6& zd*v#3az<>-Haq>^$T$iWMab{j{+Kc_&x*9JMwqwYd1T8 zS7CI`V!br>C)AI6bVd@m(t8y!*=OL1p}vv#)QiUj2K#g1h?fx9}eI3iamjjMNAoU?GRFX z45NKer$P6;A_yu8Mq9V|aQBV? zR;yP1Y-rC+I6_#;rh3#)e?Qs#tW@QEqDZ_Zn98WW2j-u_5=>^SQh7YLSdllnA~vqk zir4j=XtWZ=7t7$>s0#hLU>e>zK~x-^2um*PjEDn49%=}vEpHG^`|l_DoCcW2A+ETkbcG06UT+dmW}p%ijw*-P=jx%1?~>8~2>01O-c^l$ zZ)p`T%pgwDVglS?@`MP|YW{|?-2wbBn%*m_skZIfPA4Rk1VT?Bgcf?}RZK!hr1u(n zN1A|G5<(BffPjFgp$aHfK(Nw5L_|bTM5T$SfQX9aR{43}@qasOXKk)A&g)w9ob#BY z;X8vIp<)XQg~^-AG$#1`l$DuQ?QB*cgHP-Go8$3%g~#K_ln2@M@!{T(Ih#dLAnT)8{OeKV2wiFwXDM6(0OMO|45SPu9y-Vhf zJs{WUyGV=g3~+9Iceb=H7N6rKHeri%smNpw%-3Z^Nc1Na z0Io>UJbiY2HW4BXjh|{Zn$Un+W5B#B9q?m%oax}*xofhjK&R*Qr`Za<85n%uL(CC| zb+At&RJDRB{;D%?+;15q+{b`zuJSzqxpfd#R{RYvF$JP$$nU~Uxh=fVZ|0XlIwTOz z!-~bb6pYK9X*JTm^a4WyqD`GnATQpc)4YTH_@XkDA+=)ExxeX%T-Zh26*7^o}3r4 zbxfh#2WDGvO_ctR2Y$TIO@C(bGV*ad_EgV=n%6S)zcJTV0A=)k+*7=WjS%OghU16oNQE8Rka%F+Ig*-kX{uuU{Ot^kjDtgL-l5=kh=@vuL$FgHi#&K%`NW%s@vs%Rvn?1GK~5Kj6|c+6nwDlV zWF#h0d79B*$ghda3XMHpPV#463wuw{ius>|HQpFCmEFtF3LIKXlKp&REjAr>5>(3^Y2_sMSb6(r3`H!rL;q zfVe^RnK+<^ndt=A&~>iE1&l|102e~MojH~N#&<-}RAl7?E2lf&{DCthiCc*nq@?7X z%XlY(ws@vRMeqWC-!*GqW3q08yGh*&D_dmwNQwQJE$Pd(e}ai&gp*0<5*f{ig}tfs8jB2WBMpj|H09Xed;P|Q>cdsmovJ}9wW8E>`INFq@1o(%z8g%4yU5hH$ z{Zq5}ie-$L*k}wt{f+m3U4-88Ba6S@a;E|fIqBT^GNY}b?NeSx5s(h)721XA)5#1ue&gm5xtGgL4@?636X!nfuO7qpsFe4gij zF?L*&{xOX1d!ik0t)w8LIUR5yl*U5>pHEnUwBzWQ|HZ#kH4u0MPw-N$lC9~RJ=y?NyB`uOdg&r`w;+-?JOHR++J_8W3U((XQ`Z>6|AwCu;@%Yl@_*^0<(H|u2twF~gjZq}#e*X|f(U+P1kBs%B|-AxD>9R)`+ZD>D@>1q6gZY<74S6c;UQ!P*|c zPh#`_1cL0IBw*hk)Jqn@ECc-x%0R1rvAjar1tPzMmfdxw#Q)GD0wI2tjO2$7_VbNP zK8%>!+4S6DZYEe~O2TK;t~H!F!x>dA0Ls3Yyk%=)BMRde9a3x>LgAJ~J*Y`^!jM(& zm4C~{lm-jIGN+gx#(v0%fZqb212%=g(I*c12>2I#lY7+vei~zXsqo3SFO_-@>AVBj zXul<+kPAk({(_{5DAw>#$aCQhKiG>(eKvL9U@q!op#mS#B6B#sH>6-mA$`?%r-o7c z%fmikCFc#r{vl34)m>u1SN=Brt$D#v*5!?iY`F1BihYM*K3{;qa(&Sb@%(-h*GgzC ztU0z%K*xAkC(cw$8?5VcFrvvGoYLlXnl&dZ*}6n?WAcug+-r@z7H=Kg|2E_V&>{%{rO!(M(8E_afmta)NY+QjFzwGcMcM7{o zo4>4X+q5WElBhnMf9b=x8;q)4OJ( zJ^3o^_RWh;;tZrFIPSNp|F<9fPh{`sd4;EFro zBLPJ^fKnuoLI+5l1lH>SA0Ve|rSb7xU4E>9JPm z+{a@$xRGci>P*n#v%GNkkBb0zG#!7~eafx!^0=l3o@?)bHX`_WN&{ZnA7bss=C znk&pp&DC@AkN878xNrEX!u@lF23JL0bl)R)GY1h#?|tnJFc_zvVFLR#^Q?w%jj>Vr=6S+%R}f_QzS7NBCJ;!S*k{9XVXZKdHry-9CWt7X0>fk zum69K%Wbi*>{Ea(%R^!i zAOZpujOKW-zM|W29@bziiNa4XD{@^k5RGPbF9@zg_dWoUL_gRw&*Yw{@U#Ev>}m#G z=^J*6;|?TQ=K~(2NNP9yd_ZcP786fgZj02NA#RMfa5tdr@t3j?Pm8z%PaWUn&LV2% zheZTtt7*bVS6wQ6bgko5ko{7U1)=tHzpmcbB=Z}K_4B|RAJX}c>=#=nM-~h*y&#J4 zr`kpK96HDsP7!;NF5I!%@+%Hg({t+T zt;KF{qxz30+)&8I3g_QlGk`?GEg6%8L6vW>j=js|kzG1gkc&)%6y3#pe@kiGobLNr zXsZ<AN<@+h;s7p!ZlzEJ=o#iG(IvpfKEU+*5OZ z^DP;>C%twT-zjNb);CIp6`0!q{H$WX{X72Jtz==okj(UVMExQE{C(j6A^`GvRFYuu zO{z|>)biA5L9y1Zpa#4l6p*eu#^9OJ@e6{R+*&JAN!s*$=PCxHg@<`^Jgf)EADgpz zmGpz|(ES7$D_gv#s&|J#)Yb43Z2#X`jqsJz`~IAJA(tY|^4fcY#6-UrT~28AdsBF6 z!EdBb`mhkev@*2A+>E9=1=@bdd;+|j$w@f84I<$u0y3B!9{-#+E$%?dU%cGxH{)rh-@aCor zFEwRWk`2IwU?s&x1+pudN~_JM>Oa5Sf5xnQ>Q(clXR9?I5ovVba(Db2?&pA5V*u3` zX{NdCa56FGI+;tO82g(cHHDVE0$^qZ2He~H)$;U~|64@;V!H9N`Gi~eP7Esen|Hku zJsH<;!Dg~nf47}Cet79&tVyT#Vbc$%!XA)s-^26`8@X6luGYn{^cL#6#)W~6!p_4C^K^W zTW^q4%&(BEg@D+Hy#?30gx13?{sfiK9|LUqusUk8x+c;>nFB^A0bcrlscv;e!><0_| zTvYd{cX-yNR~l2l6;6v&^;;X|ydlEHArJH79Y&?hn%@abUTf+$eUb5Z;a~|z*Oswt zE>>P&Tlo-^?GMrS0P;7v7%gk4G;NFxW8|aB3LM~7&!anARK#3R^n>5&%T!^XS-i>mht+7qkoW=?H7hm{6^`*-z)CkvVV8?18}6-xqL}T8@6tK(YZzCc$ChVlcHA@ zV?ck-ZU!kD2x*xG-{9PFgZt~#6>~dRD~hB{dy{^3ac&=xqxD4nXvsy6bZM$MF=a45=6W=v);ty0uk1Id2b6iNSIMZ_WFz<%J#M)`n|Ml-H2g|9) z^mJ%^3Nd0s(J3bvesSICc{btr@=z{~etC1@{>`%zDY38bocgi~X-OZRHM`$BhdZ6T{a}G5F~0RuCw8hTK$*BRiTtkNw;PUe!d49 zYrJd)YH~dEa~`@l2WULw!gmKd`+!L&sz$VY`^3*5nlUMRE7iW}Z`|N0-^Xfd@i5HN!>D8-Kz7{jJMdW4p z5R5(0zXm})l0_@o+TjOF**kwoBkDghV=f;t&eg0x^hk1Gs!rNpyY<%A!N*dtzAKNd zpF~>|kI4TI+;_`J=()@Pf%|;VKEH*eT`rsVifR3RJ-K!zTYT?|Mx$KJAMz?xx)f#F z!!EDP@R0i!7flz_Nlm5XwYrG)9+4XZY#Uqml8M~veR5GnqD7*uuTJ>G^*o(ko|4TH zj3g1xKcFh*ln|NWKrS5ybEAN0XSKp@h5fX9P>gq=F*(U`20`3bbqtWU)Wfci#C5B?9_clpPgvq!(xy`kJEaBV#s|lN zUvIyrOa1#9Afu2ke1-%5b)t*?D$UzrfKCwGGrjT){{P5*%OJ5A|hwB!X6@=#ts>uJqeWfcr5gw)zZ~h1FTj4vEN)91^ zU{Wxvs62h8V0_@|cUBNm+W)|PXqExSl8{Okd#RG)fd)CD>GyOIn31CVFHz$}Gse-E z6ZJtNC?<6Hg+=@G3COmVpHVdBnvWU!ylyvH^4I222;Piqdx%H)gG`1hqC-&^PNUR! zGFLorq}Cl&05ecIMY?Q`@11ap$W|ktwg(wH5|qQvm4!H^*YT>rAM5V*KoloJam5~> zLH199W07}!wXQGSA# zUe1N??Z2=*(L$n-^cSLw;(7jwI_2h>xy#&}kwHgixo{F6%9F{~Bft35cJx`^o5>dx z=MoalBOZ$@WU^GM8Bne}hg~(5x|*{)ssKX4yH`ILMcCK{8s#;15Ri8BZ*Dz-R4 zO8%O5ir5jvc7!SXU_88GE6*u@CqdTXY7$ zOb5{x#;QDS)kB1KLSfk{0;?gTjU7PWcblQsw)>b)sU*ulF^Rt9`a1FH84Jq%An!xr zV9}C35Pu0N`)L!E*LoQk_VPU+^*;G*4kkxR5(1Gc)s=0=M;Z=0Tw|;BTy7f}5UHJE z;?{vgV<2$-1qIHJg^R_ZL}Bzzp{3(D3WDVmxfJWKE3Uy1xG6HZicy65=#9w8$J&fyHy7+25?w38QekY!QKKzS^;~kgYjpkrC~%{@cnF zMSUqFdP=dQ4(nt`@7hP`lDHogN#_V<8q_3gE|8!vt3(&$c~*NyG3`WC#r??9o`hLp zLdBB2YWm=UYC^={K3Sl9cagPxs3wKjJ|q-CKb zktBYN6J2pS!&4bDh`E?c*>oL|kwz*vinl z*0Yn4TcdC~=5G1??w*|EWhEak64=@yQMG2Le?-x)>i9scMhJveZs@d0^%$%<)k(?K7Kyj=ze(h*sA{P)KDL=J*?cJFfxPkfrV5e&Gp z^P);5^S|cRAAE{zS7lCAKnJMo4fiV@f%_s z`YVV|*WP1FcV}#;Yi3*MR{b#T9rm78IJ?t^`*Xf`qp;ZS5RLT&cRL`md+M$5lfc?T zqBwQ4{QT|QV`zY!?hDGhE*e)8bMIVp5a$tyrs`rPqtUzh^MJZ4)Wr#M;y{&VaJDC? zimXjjxgQEvlC;* z4psvo=UWD`Gir+z;h{0E^-s#Rp9L1}c^BBc=2qCLbg_k%jf)C#iVppZy<;41#T zK+y0?Js>tZs`VU4kW3MBEjCS3zUWj0`=BiQaf0g)N6?{$HxT{O;++cZJW7A&KQ+K7 zTCM7$+$eq+WCy4~b#SL}Yt^zvxod8dGHx%)BM%(og`7Jv^Gd2|5s`DuGR+Y#3*Ml` z8SE1@4&5XXsv=q;{jXH|NG|;b9-Fc4vWDN8-kux3A`tv=DV^`YVFw%5vVKif^xa3Z z6T-hHFSoqkC24#i#^nRHf~iA74h(4_K1Vo3!-@hi8!fS+37=CEJlQ#j8U_<12Es`y zw#RkT995mv2EMgGS&z3u2hDW@4qs{LbI|iZj3JO1#Sfl4`~Z1$Iq%iBMt*s!>h64? zhy$L_XI15=qO3{;X(CW$E9O_+Afn0X-p+vftfPv(mD|`}9{yO@P@C}t^;IxKMi_)9 zQw5dq?8bltKUy7goLhJZwYXwZ#lajfRwTa)NZ+MNi&M`DgWm=QzI`JzL~Gpn&kL&8D`J z)W$)%uPqj|ZRL;_yh9$+Srz^hB4+i>Pu@~E&N``@q-`Rtz&+f$88PRxD#5}(`dzQ# z$JChGBpNa(2pL;9wqfgl+SIJ^6Tu_EYl~e0-$SFj=;bRE#5!3U2wR-y*Hbc?153}h z{nG~R?0z+ws{`2*G>U8B$qe4#c+;OFLUyv|O^gLm=LV0D$FK>?jf3Eb8K5QJ?1kCY zeFn{`9zFmGsi*!DHU;;t5)V`c;M8CcxOw zX_xzU{JUMC#LfWd+d7iX!Lw?3;Tw}qj0<)$&=(vYSilqgX}NB~5wNQR*K^ml$KoRa ziX%0+HGAw`D4fCYU8<4%&p~EjQ*?t)>u$+X(T?iYkK&QFlBgK%(H1;sF?DN>rrp#5 zccTUHz_7pYfy}YcMrjN0RiUcv00tqH#d%jd5K0QFjOEDT>m-7jBWjm5)o#j7Qo@8A zrLnL;HGDW{IrN}30L{ch(=384WOCm;7>1w*m8=zkH zMb1-PU`@Ce!{6bgZe{@VcB9-7a99)(g=&P&C|5Q*^m_rozvX1l%E#{HI!Flz%FG*1 zs^@0fFyNmOSX@DQxq)9Naj27v^{V^X@ktzzyl%2&gRCwuCD405#9uf?MK?ICJT%Hp z_kIm;)pXi?O=A~VC|#Hyp5Ydrh!E>q)+r8)>R{w$mq%QhkGQIvO$a|tghyVVk8Br? zy6F~mt32w?eAENs=wY|$@$%?L^M?hg2J97a`A4DeEX5pv8;!?9UzNxDgTxTMu@R=$ z0)u{~;SmQYqp;fwwJBU~tbBYfKMb%8l` z4~V}WEb-z<$S9Ch@UQ|du|R4$tFmxxnU%0@~a_0Doq?Z%VvJPY2|=m3tmH zIFg3g71k}!gV0x#FZl$(N)xENOtYE~pvDhLqkEug-lVVY^dBkImg6Tyewb8~(;_mY zpg*gMSYjvC);5U02-m1qHeoa_CBH$_5Ct*6735q`>?{oS1G%8d;04w2x{*)qPigK6crCFB}0L;hekR zk#|+*aq=_4U;XQsx5BceuYa3RzYyYe5trJVl6006GX7TiB*ESVNquC6u>JaT%>F!LLug#}!8V!vE zb?0VrRSo37Rv=Awe@=+Hm8P6_r1&xM*vewf-Ly|;j8B0j#lgA^C5wPZZO4K_Yo8y? zUFTi2d0Sd3XB1stfFH>?rdRIoJ<9kcDrgvgUS~O& zmOuyzfcyhoy;#(iY@HZ4dnLTg*D~a)O7uwmbGTWS!WoAzpoY8U%Mh0qS`DS2aGQn= zlJHW3p5f5SAj4_bVHE&n-5O}AMxozN?@K4{n%Raj<&m@9_+TJ}EqdWO3cP!fp6Ert zcJjATm9+6;Iau6Q_vX&l?_ma4u?dZVYz$}$5^G+_xOz*0>qLHY_;*Ol)}$Byk^D}u z*)7UowE2zPsVSbvY_mSXu9knT>Q)vO-iouzoACmbC8RER$tv4r@_H$Cyh)omu#M4B zA%k1+=G_B@@$J2H6$_2hV&7W-yI)He)hT@DHSnyQalt3Rrf^Tps94Q|m+d_SJar); zUDa}hlZGnN=6K$kFl+Z7dE#=K+XF(}@am9Tv&+x#r$YEA0ovu6H?EGL$#vKr9_t(} z#<%xY+hm$m>H0dyILhm<832;(b^DspiB~m?<>|P&{4M!UqK9|STX4BlGC$oeokasI z`H{Isj#K#R?>u;w7+XUq1)%NHg;9eK;`-6eRTsauYDlxY2q)6d7Pb~?UE!MTehZRm zsBf_e5OrALOQxlGvlWU`Kkf_|fzPxuXK+Q2=L|CfZRGTjAlyD4JjW3{5U%+_1H1bM?|g}baJcBns* zKl6p`%9O^=$6#jE>N2-lruxU9-u>35e13qx)!tL%e{|=yWT&v7l>+mZwP58{Dm!cN zeHqxtgdN)9l)&D7#hbjwJDF@S@LF1#`}2T#HdrIDAc;9s+(=McwB>WU6|s zi%w_V;%kfc(^PB&>4h2dGI%cb&H??ehC)Vq zeu`jwi7y>Kf~G_BT(~NsB`{+aodiS7WPOMHLFUu6G>gF=9kWLsDu;o&q>qm@F}(7! z?dtV#t1waW&X1xYm~OjpOA`0jpNCLT*(Op^(ArxOcVVjnx?j;(!JH*&q3B9A{t|2l z_uUzdGyhZpSo!}U#}E}ojmTzBs_9cXt3jiCz8^1&E+MH)_MrRUcO?DeU#HhdZVRBn zPM;AT`O4hQ^VZL#BQV#FG0}hex(HYM2|@Z#2mC9ZJ*c(PcrAZ0W(BG3dbXmClz5{S z+4JmpvkIb$9&2*$fw9B)+Ssw@QSt@xn&r*)=@A9ih4T{qS6p=Eo8!fO30Qjo*HS2E z@r~92mglqT?f_dN;~%i+?@OaE80UB)N`OQ&=bl;0FYWk`rw@{@zroEc;W{X18~II6 z9Euk4@O|*T?c#%xH&;ltzw+P(othnZ#hKR+Klj_}(B&PBRd>IN>^->S)B0lox(F@e zIyKzNNwrtv5q~Azq5s9!Y4v+wAN8KgbiiD*=P-~U4%6E~+(zm>;@nBD(AQRa5qrV( zB*)Md@|~Db<%}>AmbH}2v&_1x?;{@JP!2yr6k4PXc7+)ExE)xnC%jiOojRFmoH?Yp zdY%%XOuq{d@``hJOp37`&p7lx?OAFX>3RHXoM8W( z{{Z?FMs4Z7@W-~G7QVr%)~a#IC&QOa zWwR(e-x5*`eIgfdW&&C6sIz|km=XS9^n#DfFTzYolnlx1{P#?DktB>OJ|k{RvckxtB7MlMP7dYc7ggnQ~Pmn?0xRA>V#?Q zYc#@KUf7kiorhspV~d8Tv=-uqZM9wy>9Txc>Mk8kg3nYEN0B8UV5Z$WMpNlj-IM3rM5feMh9c3vj@`pvgk#dQI zM9V9a0>(v%Ln(uBudUx%g_<>*a5?j-nQdoW!hhR`Vf%MQCq*)&W(@N=cShjv%Pzld& zygB9Q(PFiyGuB*5o%e@4T&w7k2B#D5^{a|O_@XNYVFFN%lOVx6!h;Qz*T3?T7bDvr z>(YoFF_c#cPmZU&K2te-Tr11u!toLW?;4kYvGy0Pq(%ZTQy^`ki5pdwfXKK8RTb3d zxAAFWi8HDx#p3dJUaXDJ^vjF_ew|nlNr4zZBNvdi5PyO`N+BKe8oK3{@HE zc;lN`O;W3X1+tXX7(vHp@H={>|D9x`mcP`%MXV^8NkD!?9|-L4K}DWnbBVR?B5@-W z9$wHrIn;^Mn-oEt#V;&kH!bZsl1nZ#mr0CSe{z#xFq%@cTBssmF^uZbZ~t{bWAVVtSC;K4#(vTTO7`ej1*Zrss0Iq z?gp9w#;i%*o4CM}WQSETT$g;jQC+P4-XLeo5$D?oG;NB%P`y>JaFlz}ft65NuhO7s zZy*{M8~{n0sa4jFlP(zCEAcL^Xm`kaQvD z-yoEg&a9>P1Xax4Xw+%XdmJ5^cxh?moi25AD$c7DcP-pm?@8WtQcL3Ht>|k;Z@HhO zP9`3L0InVRocH9+$Hc3DwyqsL;GVf_tHpt+Hc|LlGnq=5ib+w()Cl*}T$@r#Cu2nJ zQE{%PN>UwmyUFq>Yuef_sb2Q-rZVeb7aV-r+SkS&nhO98nr_t3}`E_#AgG5*GuEI=D)=0&q!NJRJX9>03`VRuUKu^zJq>O z5C#dcIR1n+-`#SuHGKs!f*=&u_6=Wqyi{w}U2D$%2?)j~nt8~ukdVM0{H!%a3{U~Y z(9xFIK93=8*eAX`*Xte~*mbLl)pU{P#kl+l0B-8x{0u9(yMFsZ$o1645=|mb|M>^* zwBOIvyUY$@omvQdUr$l>|es%h+3{q{t|5$QV`kRd;;zGJz?i)j_JBQ5U zA=`4j-jwN7ntW$zyDi1}6z@S~@R&IL7(H_tqfnRpGXQzlnkf;Sgw&Bu=c;yYj`Uug zmo#7N*@43l_t{X))^aw$rsZHJ>Gn(y2Wl|^P9oIa73@>LFyPBKXG~iv^rS$OrUE{D zaThz9)tsxpfYzMGkGwI^H}{_~)sP&iT^F?`3k&lZG~)9_4%`TWEUUt-oAqG&He4tS zPDMrTX5_?nz^`jjZEdphzxHrowg7*M-)i>f$WxDe<~0qPo)$#;)QL~w+l{j0vqYQ3 zV0D_lO|cwt%YIWq4K{{fwx{L4HeH^X!t0Jc@gQ{gARo09lw?%{w09g0`?^@hN5SS( zx~0J-&cO$NgVz!FZFxa0;4uLfbtz+HD zpzu39J8}6&jaw7mx_>U}#dNQ^80$Z7rg2`podW5ovnfQ6sB4*sA>nD=Z{=6r>M6;D_bGR{m0Y_89ODub( z%dZi?uE<0R=?{@SS{%3tcYX?FOal{zp?^eTIvAq+QKc&{0?TpeY$zu#BFh$Bby>pM z$S@eZW+!w0;FAL#(mr1J{YKPl&ig~{dj!oFk_mQrN&brLb6}g@TZW$~IKIBICEnd# z`^M&P%CXtO_mbQno;*w#S7XjVZIydIn&bxu*M+i6!sl^9?n$ns`x;8suBO^zF7>R$ysnLmI2&-#;_xYxAouUGwvQDnQ$ZB%BIS{X|f&c}V3`QO?{Rf9X{ zA)n8dPdZk)X3CRHR!Dm_R%K;(RzLgga;bT*(`WMjq%dXp{T**IY2joHRKbBt8BqDW z!1pLHr2fYNJq@jiczA&h2M6t&i8KaW>D}00Hr^Ovo9GNh?bb&)GRjGrr5nDo< zc-WN1ZGz6Yn44GGcg*((PjDcLosb+MqG-wHVG+U(@q#3_ghij?>uZ@Z=-kR5a<|Gc zqV(N^Fi{3ZBquAeB6T=NgUG-bYXntq&=G?|tke)yRO-=Mp}V4KpEc7ka8Gl0i1`KA zn`Fyn8uZa~vQBSSPOgCZm*DO3EKM}w?wFvw0`^k}S9DF@XZZOq6V~tMdDi8um;i|8 zE?3KLEMta`H4A9~@N`OpZw6#OTTW)tzq5=4q>L!=>|7O=9L@-ZwM&(xFS1| zs8rcYf^*rl{-7Lq&=h=*AnGO%F|xKTs-S zDmD=mPmHtJ7c!Bas5cG}9e`>?9O(TDqHs+4ewWnXkk%L|P4(9)*kE~Vgbu!s>p4|r zY&FL*0*V`U&sa9(l&dMyMW^%rSLw zEks^c*%R)|PdybjNukpVWw3aC4UT@gEcceVzcmBeKq^0f;e14MIUdAy&nd7WArPm1 z#MzbSX(CV+1@)#G4G{5XxzUt45RrU@FcM5$2KNYN!|Ta(WVh6LhXb%8=LmnYVT1$3 zSr}@SBPhl&N~#dfjB^pDTW z45k>oY&`q%8XeIT;mn8a^lafYrn8#zTAK1Fn+iWRokuhmD>YxRX)cRwzKF<(&uFg9 z%QcKJAmSeNz(8u(+%d|{ZE#Uwx%Bq)laU*kEreDfawk^~2mZa;}qg z!1*cWj^9kU=TiJe_^x_F?z1d65`!&hj%YCXSy0RHm!rVB+JtW26mrtgV2sR5w0?q1 zDV?ihK`W$nt$w=1_oB92e1zK*ujU;FZ`xS&`)KHry#m$7l^`Rd)*aYvghE|$kOR}_&4V*(b^5xTjvPJ@do9K4{ z&6A{vvayPt0nAXBvL`8PQSMX7fukwN3_5klRqw}P8N>60##U$sm z7SZ|v8bd7NQ5Tc|uxQN&3NR9|dvA~;n{9{SBY2^PI@)HQO20=FkXqP{6(1K`-~o|)cr<-hsoT2aYdDEtSpQc*f0?pIOqD}+>1R^ zrP+Y<%T$Y9&tN9vgLNIhT%ZUWXhNpI(B^MK%{xWZOd4HwYvfc{j=ZTTQ3qAi0o91g z_>;!y@AAVE_MgF5!!GICnK=4@U=ePa}Edf`H%YtZdY#Lcgfp0vc` zWGmqh2^hehj(5F}~^&c8yRekJhpk@NzE;Pl(|Sa5Vjhw;5;=+Q6HMh>ua(#_}c z;|rl&FXz#VeFT2niL5`OtEgV1z_Z)Qh&-}CF#&nE26CT*%w-(i%NGAd)WKeFwXr() zTPM!2ChAdo1S>g<@SKlK|1I>8GlsbsL7Rw>SU8C9p&4FU_8ibmyfXvB*rXBqVh9oD z0>kG-ej>x!QfBF=d&FQz2NFe=VZy-}M_oO%6MMvG{78jH0xu{SxldtE-9{?lVaA>J^DB7n{zMP_ zF?e-G&hAmz&0FAJ_x_(fg;z8Tp5v&a4JMO^zq z2#shp8n-b{V^V{D%czU_CHlGhJ&{kSUeRL*Y~xMw+cXwHodw!=u4LfulEc@`Cpep7;R88Bl-5SexeQ zr}c?v#z^NZ()6K|er&!N8u%uOr)SwYDXw4PZx>=PsP8+SV=AzSd^-7c<&hDU$y3h7 z{gjWGYgtb_<5BpkA16Y4#pClBEO{3-zW^Rb%^S^%8^?jYQHq)zcF3d3AFh0-7BZt= z%||z%oBlM+lY_Z(E$g~3N+>XE-@W_fe-=tZa}*AwM1ML%6cW9e9RrYcwk;jea1-r_ zyge4>Ae}(})EPA zo_F=yD~T(wXv)2abe0e!xuGP~lJg|~mQ14+!EgdxvbNMNnk#w@6N@T#hzGjQVvW*M ztHkKX3I!F}`6Blg7S0q@x?>2cZTXEtTMl{4&tA}Z2*@U0`AevUx2c8BJNF+s@(I<@ z#cE*Lw-@So(cF?+X8F^EnKXsT<<*a9?ewCk*!C2XFxKw9Tj7M1o&3B4`2Gr436s!@ z2a`w-AJiaBp=?kDPczY=dJp6W5U>4mf~N);aiwUg*ki!7Q31{SScg~h%m3KM+5u7l0PU+}SeMCq6LnHkY+D7)vyM+!OA?%AM;v&@ zAK3Ld)jL6h#}E`gPy9ywrMUu(w076lIZuc?R!bjj_rgHl1^u>nm-I>X?Mb_x-Mi0m z0mG4Xn3NJ!P z-N}mOf>-cuFml|!O?aJb_mv%nVeK;`XCY$>>FW0gBY1o9f0cm;5l8f%fd~%9M^!fr zlJ*wvTs7|nx$GNVX}+gJs!;{gT@S%p77p8huDg?_lEp&Y)Nhd70j1wsAh)#kx})h! z;OVtivM@t4TRp0xWV$K`3RXQqt84Gc?Kh*B+&}x>Kl}F|6zj1| z8_MF9vZ(g>5;#_fJDQF4+zXy8Q}rLK_WT+;efbC-hWlNw`?TTsRg24B-y`Q+eII1w zy!WFQdt%;>#asxEeRJ>Z0Zh_I|I_Q?LMh8DKEDz+9$!A1BkB7)>7zA$)N{bW_rK(w z*Z1gLQht9@_uf6eYI)V~Z`#5B_Ui{ZQvUzW{QkcEcKoXU!MT5b{~mCW$UrXH4l?+b z(Fz$V65KKPO^rBB;Z~^cpd!^rNT$4cODr|MqYw=26tI2T+P(9xf)p7Wux3aqIpd9 z)_T`5^#>3wTa9tqo3>g{%(RZ{oa%}{uJ<-m%g*3^{Y^Wg&m&s)M}Dl|v_EYE6rhgUcMm$B#X}9q%DV0ub~Q_PG4z#L z?;LFd7;<)!~>|FPyD#tEuX|E=6b#-7ea3Nro7G4^E)LXFbE<%s?zg6`{Ug$ zfBFGbpO(%g-$%=M{d9xA%O6ZdJo@Gn3!|8xh0r@Ox9D%Pjbi)XH{OZ8 z^LfnZ#JwLIcTPMwfEmXPaw*)6I~eA-G>#t?3A-CVE|p`P@KE8}-GoQ#W9Cd zx^`YcGJ7r~?7s2()tqxbT`$qE-8WgiK5k<8;bL{Dc+!z6$@d>leDm`OXNmTL?T6?u zVB&~?tc$Knz||~2{SQzfyv@f^5trBksMMjMP&|B4;O$2XRQYK7_fC6n?E!!F-{Y)< zdtmyv)Bftr_$-OTvslDq5L)73644VR+Jn!68ln(fp^soun@|mcV-}q{636%B>!?mN zIrFD0DD9}RACz;AM7VNHRJCt_2YUcy*}WJjzm#;p> z3{E?NtB4ClkvTaf+Rs1=hr#n`nm|h5Duf3MH`<9yrz?v7BT2KkaVv`9S;CKref!bAXvrnv~M*Tl176Y8P>48MppT1 zqI0yv0C^tT&%iZtIVzd&z}Adf*_)_wf=Wk*aZ?~h)e2|VYZ zl}b7&^T*w5EX&nk-Y=KHU;Z=?GHiCsbn!&W2~zegxEZ#J80c}ejHL~!fraRs|58!{ znVOl23qNnr{?B7taBCTrW<2QQNQEMkYEGwhGcYhs7Lw#3*GY`xt#@G6x!J&oCoPrR zP~gi2U&@@aR@8R>Kd$b>pY1R3AAObxB8^d78+!$@6;+ZTHDlBsv3HB2sx*S6)TkPz z{m`OTQAMrRXzbM9)M!zwsH!fVxxU}uecXE=_fI&F$2sr!d7Se)ucrgI<#D2b^{71Z z7Hbk&+6RkjMFs~MB_hr>8L-Qp9F(aSPbb3E*!`YTjDTD=`aR5^lS6z86i&&+)B+wr z?izCxzCiP}fu$~l!c-4P6iM}aHg`l*_TR%|)Dt|_LAP(K1Rb(ZaeVyZL%+0r z58wRh8%$T+IvLgUMREex!}78o8BG$0$&jlIdGDc?T83utoWwezfN+F@V=)^?ssjOk!PpKma|^R? zBo!8sB<%AK&6p)u8J*Zc?5l7C#k2mf&XAsl}$ z!@H`dp9LF&R9~e9259$Xk-Q{n!Ze;gtGt6qS}A9@3->W!cZfzROTa4ZQUd7oJ;%XF zH6oO7trQ_+c*tH{%x)*(C7MQVqa%ih?1#;7Y)mJ5Rkp%-)FTr4x%XKV#3>Nr;euP8 zF-DfOyRZW#nBZOQ)u&Ic1B1L!Y=2oQ)u_XPXx5YGer?~hihizM5pi-<44|<7kwu0j zQyhD^v8wKOZ@K1<&;N&2F8=t#?f9qHO+tdl#XeQ{gz~OvijCd8zs) zT!RhCjfl)4EE`=aWavtiM&ACq{Gsi`x9M{IZzD}wp1jUfC6z-^-ou~YePzYbF;IzPq7&LkBd zj25UIrZw2}=j{e()4zcT+QON1Lp;vX>-Y=oY5u#V| z90uowaqh$3tVdZlV1Q{-$o@``scN zhL+vkXCOT&-kz18-D3FE<6r|;yB;Z@9@dZ^ndF{HGwjE-9(i<^99$pW)T3x;An~Su^?P~qs=(7&m_5zklS~$tj`qH)MwV$XFk(svC(Jwwa*IDPvq^l zmh87t@3+MpS;O-`MT3O?M-bg_<-7(G1d~aF|2H67$e1vqQF+yZa$z{Jo;xVqZIO$O zWf!wWH46V15Y1Qgmt7{D0HXh?d+zd9mGq4LFCZ#kkB72q|Nj8d*&4^^N-U^Jqht`F zS(?fPq=0VotAg4v7%YGV|DHP?uv+Vw3T%7ZOlC6_Pw2VXLfPIIUeJ$)gTvYw6_WR(3PtcxdCKRKq0R=p3sPQ2G z4n({Sersv(#L``wZ=^s`r_C-vziSfDT`x zEvu)Gs|jo8#3SPnU{!V|CJxd^Ho@oxa^sLa5D8sgRI=1bXJ^&}s@YHD3ggpTUlZb} zZ0cY_p!B6F4(kUq)@+IXA0ocen=!N5~XEyiXEMCe5M3WI31`k5k19=nb zHeL)Nf$;D{Q5JeHzcv!vcekhj62izu7zE%=FnESMjVZDHv-mB^!qC!D7zgvCu@wOWt6u2#A>Q;lT^Rrv+zmrR)>;a3blZ-GM_b+NC&H!6wq_56xtP zt)?YFGvOt>q75}Qn%)#)sTEoM5^8WLYsHCS8aUlXz3?SB!_ChLdMYl*OD^B4>YGH~a3o z$kUT($s!W!_Ue-D2=B#&cHA;Ta_i*EcRaHNj9T&<6I4V^uszoI`C|O;5(EtAQTRR2 zV7uSkdQT3oP;`Nl}FI)NFZyo~StBEWcA1@!{!x!(o1N3&SMd>7x{y)b2?=hbewZ0d!H>mO_-UM~VnCv+&ww?zlo z>EBVRC5LhfW^EicS&;8l^BL@;X#PX{sk$M;2csG|w2&eEB&;H#`lr57q|z`hyTDr@uod zfH#5CX>f``NmouOBC=SFV?PxO>3{IkC&6<+Ck4#@?c6g`sEZQD2bzPE&{8qa;`cTq zn;dIZrPz@?%Y9e_`*3-u6&J(Nhnsz6d#RNuXQU_waJe&)y-p7sQqQcN>I zQ2?vFtn;a2DFO7Xw?1cH_oy)`Y~;QnG1f$SAK-N+8$)WCyBL)Sz|wo|J!_y2y~G-lV5i-rvWMR%&m9QPcoje2G( zuHU8KtJZlzi_8HEPHkXWRU7p+Z5j-DRv(R`rU)N z7h+Ts1%nz(0YRa)SPwkoiV$Gz_;vs)#%pk(ke?*eh$Bl8^2lslrDxd_zA0|~{lww+ zwZ0Qnb*(B7tcF}Wmk>G3a#7HI&)7ciZmsLJ4AYv|^;XLDikGy(L=w9<;-vmT#ORl-Dv!6O z2VK!M_`cVGv=&*Csq$r5Iha-52w$#A0vWt#FS_vnoD0wsg#m!}fCN3Qjd93vsNv0= z>L_337S^NU*&R?pEc=1=cw&TMg+}$VDWqJGa>cOT-&`Jn0>@g*;EFZ5PEBUsP(=fC z-gp9!FdLBd6>g~SZaZqXqUxRo@xJF#F(r&MY&gfA{Dj5E4rawKbLc$??GV1JaRK7d zYf}T3{CeTi%Qr)ch}O12i-Y!&mtq9C5xv)o0DZ<0MqOH)3dO2vKa4?DygARo8Kdm0|BhNuN|s{nE{(SaidlxF zkgj$QihC|5jb=qjqv+dxW0=EM zxw?(F`?K$O0g%Ruk8Hg!oC4kBiz(x2g!~KUeCjGmH-8_#7~6- z0*;Y6Gx6ZNX!sJCMZH z_q=|P@6PvGl)V^O)~873ziJj##dXEe@*fpBriSmbmO}XxXjju0A7A;;F-Xv!TfFl2 zyGei`$+Kq`*=h$IArPeMQvl+$oX?RjK8tb?Q>~KE!Ab+dzGfi>?{c5Js{wMkWTc9< zy~BC;%=UAo$StIBV;J{mXQByDInc_jSMlgH{&}8(xw@E>X1FW4(#Q=2KD}zb%RGuj zadGwaIMcj*YJG3>+>^FAIZQFqme1#H=i_qR;O}b|;^I_`I+rt!Mh}3V9ZlkuD!2TF3$}fF#zVs z`HiYTv34Bx3EvLc5y`Wl!MK;BFfBFs1$jOa<%G5Q0uFpGYwd2W{7Q>!Z8`@I)Jqan zd&93r{waG9nOt@MLG|l1|HN>D6-Ec&%-?3qZ>#}cNol>w)=K<_x3m@c-g4jZvBHZd zTK`P=MegZUik}U(byo1!v`f0ibBJlp7B7=jcsZ%}kB=LlM7{yG7Cw9|Dz=eGW!h*a zgx_IPLp9UX!VJ$1`0&ihah>N8;pEZWyQnd2qqdN*blE#dk*L^4Df>H2qY~`1)VTH3KNcl=rb` zOp@}K-XJ#$k6{#<;${OHU;{u53|4dGw`?A%Ck9Jh)oSc^`4WSyk|=f7 z1gyqPj2G4BX5$4sZw{#8mW-N4S~M#`>s4;?NL*IC;lqZLdhJ|_RiPJn|89ElzksM$ zNWMhEx`c@*VcJV1?+F+Gw=2#iIjo;6?yzxPC{~jA#zVehdN;W2Y|M5igroSkI#U;{MhaQuC|2UZ|!~ zr>4odrX`k}^P~?&MFr%{BRDVcO`VJU;_Qo<>M9}i)*5#Ui!F-uG=B***0*agRv*DnAI_|)Dhl{m=Nxq((Rlv>l{|N zzDVp`Z0}s==zO#Ezmn+mUPu1fRL~jn76+m|jC};v_3!tq)f&$Ev{w*UIy8rvUbT%JM5Md;u`*%?=B|7+&UMHLhhnNGveCWaPLzvVugnWq1Mi1oe zBPHPw`~-v_-pNZAVNs%=jEiGMxEIU?E<$#W)k9rLJvR?o@T)9}a0G?Uf(L*fq6fze zdTz5sAK2!g?| zM7VY`_Cb-QLz5f>n)GPTV$R)FD2o`&-z9iyh&JdmD6bx|eh6hToER(|frdlmJAitm zp^<&iPVJb0;^^PsaOOVfh8oK&rootI{Iqt_w23UI5(%7O(78*etB_!iS0~Z6h~z^u zNb``jLOn+-ij7u}FysW|IyvrOAj)C0SN^~s03hs~ zoudHoc@l@~>U0fYey$!-8OH7^I;w(VUnMclkznnI?6A(sWI8g@ZO(tCbDYlMiy93R z8Qe2iP)-<_Is^$74djqGCjWrQ#8J8?YN3WS7g0Q25x-bfw0Pf(!+-=1Fz-}Y?n(Z* z_!AC3)rt6r9^I;)D*m%DZT`leI3brYHWAE-S?;Vk1ci1YMgb5kiSr^SYy|*0Pa0Z9 zc1{5xd5Vbb{kcWvQ`qXnNS_sq@8B3#R7V`36(0fG~2E|fc z^zK*ZyFVF%qaUX~#4!|?;jpK$Dbm~p&bj1OQ25FsTjmUW3~rG=VX(@QlhrwenmTc3 zLuxydJC`BNk2pL6kDThJ+lH)fB4>wE?cvp}t26QOUvKP{|zW8@F88F{cJUhX$Hrt8dg^w%O z14(rF^!Xw8LzaL87XOL0+23n5`zz-GD-TyVam1Ae32*QTTP$xklu)d1ezW6?Ct3A} zJXTr!|FQTpCy+}w-j3;Yj{XH@W9DyXbsAh|a9ZwAGq*_O`i;W3A08fjSVc|hW%W({ zersC?Yqwao_|vx)vIOUPJ2f&ey*eXQvSLS8$<& zdKk8#(Yd^=U7m){68E>$!n?|cV704s&9qLC-w-=j^;c#2sxiqwbv z9Q&Ng#2l!5e9;^q~llu0~fCF5|L0kh49c08$bEGh!UmgyzZ5%fst$%`t$BTBY zqb6@iu#B$kO`2^-D zoJz5AIsT<3kqfiP4{RoE3E|5=?lP`Rl(+$m~C$+&`TXBM{pu z2)SFY`wnV29S&_rbxk8-rX;ZKAuHr9SfKV>MF+bFX%0_^xF@jB>}?fy{4^zg^f%aD z79LWIk zS+{|oEK?3&3&^v-?+NI?JCFYDzWS$g(eNz1%A^z!E7 z?4CotXMd)Y%N*L~l>K;}@6y~ym$vZDv2vIB1GkRr-wrrmW`6RZQ&>((yDo&y1f*LU z`YbPe_Ga9bvZ`=>bL2a6U*k$$+`&u^^W|&w{nqhm+q996Oo@)f`hmu?sCZtACmj{yhp4Igo2ws8;j)M z-b_-HbY(4Mi2UhRIeXgXR)aY{VN%5kyFo-OX748x#xm8j#iFuZZPXM5<)=!NHG(6C zhh{$57_09Mhg)baMLvJ^dFX0Np>e?%PtG*HU&d)?4NAY<=B=YoYq(93ELmlVPRv`} zGgGDt5S-BPlr`DJA|>}8U!7wqi{PJnzmf}4ZPSub0_8JF$Q~DyJO$@tI_m`;XOn#6 zx+-xhvKVPp5-#Mlp2S-$p#DO~5SjbFFhX3V|w8jU^8u8U{m7de26Uym?F1<7PjNcrpG*|d5>GQI5dw* z$$QmWX<>rm$YdGR#m7`xy@;$-@xj;NWTnG`Hm_*YP(+&k)=pxcli=%Kh>k$GAm7C( z>-)a>f|UFBPWcpgXS%#!je4JX!4K-3;`6p`Gyin8Z>Fx~camZBgkc$r>=vB~zN1UZ z`~*htB#^z?xQSz6i7S{jK0o)@kx?T>g?BL&AMHw-Xk7JGnFv z49Q-r65o$fw-npqtIwGgi%Pcy2L3k=_PjzRh<$24RV@1gh8!Re7W+q`*UKoj^JvdG zmur8cYNtHyXeN3uN0Tq`n#$lV&2w>^jb8QezeeWiNh_xclk8yxiR+KhW>Tr{x9;%{ z>6)Yo7QApfj?|O;*MKgvGm!-OCY%$+6Ocwd$(PMM;nXr|;Js7cX^*n)PET$1ABebi z51yxZik1mbWCuKHXL&CQLms>X;PR1QpIk|3n|7m#Zwl-bF@)zYru>Q4V4lH=q#BsM z%pm`z<)?mnVo9Y_-2T@F{Vo~tH1V_v!xMV?ut!j*)`%nWan^a2ZqHCg38HASSB=2Q zA{%GUaC(M z4YE$ys~;$keSZNEWSG#Dl^^I>e1Ymn?iKP@MZaxWN>oW0r!uK@d5(h)TFjvLLDt?^+F>0usVKxnOoc*v##`RDP zXm}h)L$Za8_&G3U4y%9WI6+N!t@y%jX2wEDKC4%1w~uNvU%rb;Cx*3$8dA^JKT{#g zd0Ws<+OC9yDs~Q8Qg(g?#miG9E6vM-*S{`V%3CfgANFLJwhXK&puq`1kB^2wm=j00;%HQu*@?l;RFK{5=V|N_jO6Y4i zk_5{C84^IA<}<^ZR%m~X$Y;K~SD)Nb~{kT+q*Ytj$mr}v3*@sYr zdW%eRzenrmJ*y?{O5KdeNXho!O7_?)m_K;gM%T9b0&I z4e(AD5@7p+d5)>Hk=X8qEKU%6&hO-G9q}h6yLFyYeW!gREaJR)PgU6I>IJGsws!f8|)+>b#SrnLAkW*=YEE&R>p$38>)f z0_Mh`>jwVugkFAPqoHV|=g{6x$sNJ9_2Ho(5{nC{wOblX}HXBWk574T{&@s&9@Dj_jE$Mx?dvgpUr}h>9-{otNNRc zXLX~{Y8s9^8YeW{-iIhydUCq`Q)gtAE3Sg?mRGdSw{JimS1}GgiXRT7^^_#4^kCz- zxdD$>@Rg{3lPNYhpI8nvFi|*#Gi@o+F9wGzD0|E#VwvRAGdsaoR$gn4(|S5OCllp% zcpzQ@r+NQOV8WYRhzmwhgMX)jvTnIdTONPj%aDJLl5c*k^!U5y&-}bJ zbMtuc)$ft~|FuE?YwjY1%LCs8&5h_>rP6BDI)_4p0?^b4`57@*8Dz^DU^YQvlV z!J9yObs~HC>+vdj{rty$7)iWCoRQ;3MiZm^LZrr`Y!62kKw}x?D*#oB=_4zmXx_3( zQXRnaSyU^M5it@gq&;9|&|?Gd5j0359rpXi^@zftz6%4MeOPb2v9D_n{{-HqERg`C zk-}Kaj*T$2M%VtlTs+2~T>u9a(}EMAs#$pcHlVg6!~}_RZ!$*X!Cpv)Bs|f5$0)kP zSQ^hrbY-AAC_0YG{$$>sz&HYvrru*M(i5_5?5hpcqGNBVGrS53wu~M@n6a-T^fLS+ zCf%qY{o?(?^rje-)|5eU05x{`VgSiRfw*?O>QRUc=Vsc+V>m?TI5Wnvn6(vXEW zl{67A9B`L37Lzm?g;-dWjRbTMn#{4NHVQ$cM=)go5k|3E23YXwnYi{}+J}jWblfSR zSk;n8B-01PeTdxF(=77-V zl`3FSAq)NwUaEi+A_?_6WQ6vypsL6e9T?5s5$cctxmXCiie`a!65|Vj3RzV5Fscoa zz+X%;lBJUBCyXZsg^Lq;%ZXlLRB|CuBPCg|$SND%lNmBGot#KmB|4mxEitH$$3{X` zNv@984guEj>WRD`se*2UDD$bGxm4o?vw#_}ZPyrquo8+gLlF`Q$VtJ_$;^Z)sUmBWHY*ecBxM8@;v6LD zjmlq|GMKfITn5Vd5Dj3{b(2sZJKgivVR3_<7Ax;$H+M1aPD|aJn=2OM-emhF_Ln{!nOuJE)Gvr@g-(8F#r$PD63P`+ zR0i!O`}8|+PB_PannsD}lS8=TM4YVc^gdXgWacqr@6ZO;j&TW2?rZ5xz9VUzcgY0O z0MRnA^6UV&vY1J1;G5irKB65wixce#P!klv6E&{1lPE(6y%IGR(uVkAXu6EV{YY@y z=@q3aFtpiO6767%G4?@0eu~gk1D2zk$s>X>Ao*3|NoBqafyhi$hoT-YMT%k-CX5|+ zl9U)`N|=F(PzZVg>@~3uxI8Og3pb&((|Z?p^ap^DKGg>B(2X zang~VG*XnbmFGU`>){oaTz68z*x7$#>(rlKGE4z>tGQ+y^`KBRpRlAfb4z~Nc^@RC zaCFrQZk$wTk*p5AIqHzeiA~~P!(*>NM5=SMml8)2l>JW%LgT-^fEaK8a!CxEZtB-4GU;A_I9P{BFd6 z3b!H@g(7_9T*-nP`!Hu^D%5eXEwTg~Xz9o`1{W zdroJhP3-m^zNup)Mm!AzjCn+{c~1!z11yNko2|dF!?~3DekfVhv48z*3V#-ZkYyv6 zv8K6|sFu0Ls_7BXPe?_x$cfr|+#4s+VNpfyHHxN-qU*0t_wXt~yl zud&>{R>z3Y--bq=By5sjbWI%Ojyn>;J`8Ho-#1q1`6AJt`vd;L=4;8u*wAL5giJS! zNOw;LC<(FUDmt5H1a&1Q@@58nDB3Z3YZc$Ji$}_lI1jCC)~heXJX5j|Xvdt>@O6 zZ{hdNFf=o5M<4p6P`vk5=-9GS|D5^`Cye|-^3Sp@0xN*>*%)}|@etU%yXoa&!DLXU{<`9!d3{)}Pw3_qy@c=hXI^j!(bU$gVivS=smCmSw2z z_kJa5AAH%!>c7wY)fs{lpg23A>;kw*Bw0S*W$k0)r>8@Xj6@kiqO5c>;h#~wk}p~M zO0rVc+n2t>vUfo8gF)ufSPPmhll_&ORAi7Zk)`7WcxKK!Skq?g5>58e(TwG5vrc=_ zx%J8xNDc+87qc$jdS)L zE{qIR0DL_tB8px%rn@xZgU^NWhZE~#)*p8=8~gSU&mjZndGmWa#bqQ$JuqK%8=dfuu= z&=e`ct@z8jgGXi2K>5lyk2@I2>GSc?K(tbiB*RISYWLgS$ra;ezYLHjE4|N}osVv{ zw%H_J-SP?iIPy-Cu`uh!)OcnJ<)mG2iBx?`WxeG&XN293B3?KCpl$@c1b7=a_9gL| zgRV@9TG5YC_=2grtN*2d7^BY>UzcJvsO1%3weHPT;TP4LjRj?}etz#CDqgG6h}6g! z79%>PH-AyxiGE^LKHj$^G0^)&}P;fQD1|Glb1V_mk-l_KmIqE zGBW)kbjpM8ING7-+~|B{avWCF+JrH2ar~-);-nxonVM`PS8n~E2Kff=^z5?>H_VPf zFI#WmR(=jU{Ql`V zV^&l3nJ7F{0+J$V;N{m=AU45*O%~?99CH^bhU7O8w~Pz;yxz~x<)+=268_la7KYt9 zePQx_e}=rZvt-I4OFC82$sYasF3gN7D{Lxqj7;H9R&vuxzMsX?US^uF8oK*cZl=nn z(&lNx)sZ%U=F|kIOilwChxv~ ztg^w#ma+Y}_g!^su=~^o#?%c=dDn3W0B6a&XK_!MTC&QJwnT=;zaQd3yS2wKu8B<6^L_B#uB&0uNBvqEK z>14sHL!$Q_EgMDYE5p32~)3x0YE{o%CDyQXssYSMV!J9ro*oC;VtF#E- zYPE}}JT>_7=7zG`l&}&A+=5(h{Y>qStlKw%s({)b_r3p=3gvk+d@Tf32&yZMKF@kT z7-7syIP)+V75p8+JNMO*mxVzNZ%wr()m;f52OyqngBlj78vcC=TU;&rIFvDBgVR!!63$%rr7ZHVgYv5f-z8hY zcYiCN`;V;u>w|FX7mb&$IT_~`V!nL2$31)ViIH-02{WUFi@IozH}1L130RBms!rut zV99SdKS<>Gc@{|`fvuwY!VVf??GM)4adKXwW3ov`W0&$Twb8?@OqbUYn{B@gAz~PV zGkMOAJ!MEGF(Y7~PDMAF<#8Jc?2frBUG3eIA1^PaAhC`cGs60DnkB%(u|IaFbTbo% zqVsMr{y7HV_)(vdR114n-CMFs+YAu+t7~TNBm<;Ao?^HG!-wtECIf)!yX_KZzEqhs zugY4zk!4i}Tt@_jc#AUF#h+s|*jzeFOdZ(g+eGH!{9oyOx@1UlV=}4Kws4)Vb+z~J zY9oHB9P0Eqodckds$p&ukyE+QFOw$89+jZVWTh?i_d1rdvAsPyS$Px@n=kAFgl?e+ z3kf3beo_QYB_-FZ(2=tGv_KG-9ZkSU;v)5d1HOzcb=61wW(fk@Mu$e!_e%_=_J%8R zCzDNQIRHTNuyx#J(d4YvvzB+qVg{)HY1WI1-J2awS;c6yBj-7|oysnfo)hkDu)xYw zYdr*}S@1iX%1J*}`5hIxvJaDF;ei)3#W;NTR?B35W=%+x-+uhAkiX<05S;$t>K)Ba zIm@d;dHRcTA~QR3V!s84qN>2Q4nlr#oi=(&#gtGYImKTqq4@O+{5KX;w?PH_2V&43 zmIQ1)RLpNN!`>!O;xNTWg?DVGcW?XkM0RFH2=Ck@dC=v#yArOaDtaCnz!a?!-+X^14Qul(sCLV%+xF(7 zUG1dF`T4-^r(qup5VLIvxzMk%Rd;FEc)1oYJiW&em@yn2CBMAJtrf4WGpNyW7ZHLS zxr5CxB)mUT2{oUp4x5B}{P!7KkG;eed+ClfBtrGl6T?K%<(rTn;ylRIN_~3PjLgLEQ7LbfMjX_$23dxHb-pMdWlf= zSP~+#gnHl4@`kfFo;I8TR1CmwBmH#A2Twyj`%fxkx^)w(z7B09E`4T+op9I2^_MDs z47B}k(V|PUWjay9?X=C1wX|YQ8MD30S$P(^R&n{i`xLaFoi|MH&sNB3#MU9!|4O7msU#VpH31XFa{PQlq$Q zdur9(4~{`WcO)t@b9)=XvHzec+vA(k)Si){9286m~qBCM#xM>7P8 z2j`WTV`0Xwv&o(K#&VkWDh*38WUf7E_g&y%KujFx%i@4sNXq@S{}60LCFU$_FAVk+ z%_5)n0;R1}B1u>gL!)z!Lu6~AJOk3-Zx6_)b3XMKIAz#IsdulYFB8yxe&u|^8Ober z4>@2%jVSw|V^fnE5B90zOKi+XZ2$5#4R}EP^t=?@_^gpj=&;eo*<3vceCLj4NbcW+ z)t`AKf)B-nDoTVRQdrAQf*@klHbPOyS=aQWhbgWo0V|$@hwMQQ#mJv2_szS{noo88 zJj)d~f5!+v8$)?lJ0=9DeEnlc)dQbJcHakJ<%`_hQ>P_zUvnUVJQ#7e4uLn4sWF>~ z>B)Y{`*X;u2d>(^;O;-cfaDCVOt~>vI+Fg}y(&@K3@3D*3ogOoY$JF>W}ZoPbSyv|iGq zl>C5WC(mH6-v;FqgxR(yThqBuMDQmuR>oZa|(&aWvQns4qw)#?b#^rXF zQkU$@FS$#_!OHC~OF5Ww*x!_LJmc$-Ddlue%8VxETv2ZJK+2`1+{LEMd7#|2XU%1< z+%0p{b*tRnYl-akz1*X2!yQ^d+M4m;tML5yo+Mr2RXy&hS>gR)&C9sLXKuvXzQWgj z$;Yq454!0aUE%Nd+KV2jYz9+~{k|1?ARPwvk3W_U@2Utpvu%fzj6j%#YgPs-$&e$Bx36oGB;W(Z*(J zIf-J1eXmT2mQLWS3PH#w+E-ANb^@fUk~F20jH@o`%Tl>3lidSs?5k+@GPLSP5z(^t zAyp~PvMFRg7vW6V+b5;ubpfuqJI&o?X;bWJV^zKbvN_$KgDTIhsyj5vJJ3MS zf3kOl%CgRUaO0B;k7rh8tFmP4e{j)!lItg&Yai%jDR=K}Ro-Pe2fruzL2~)D5BQsM z_ub12PRbT?pFF6OBbW;R*CkgtRqik#S2Xve=&jsC^461w2Xc?TKY8@;gIVd5;t1Jd zzUnZze5p=l$wSs0ufS4$`BbIdm_pey`|5J{AUD(Mikr}i=%B#M)e&^r`?2y*xMi!P zSbeI~b>DZL_T}rN%by|kTp%?KyOIsk zdk!KB&#TF0&orwW-Ho1GDm2^gr8aps#ZsFuE3`%jyODxh25z-x)*N%yRMBeMvTI&O z%e-uk>l>bKp{SpE=`~OIwhh^A$h!uv#p`OJ91NEujhP+L2TC}K4DJ%s6WNTAXyub zr&PH38@SG@aLX_oxRq6Sv_9{)tO0Zzcyo+-P5eMsDt!J8d{;g%K9uG64-5SDiT{p@ zQ;Lez-% zQS7X$xJ;wCvZ{nuqr?SONs~rND^)3nMkxU7kwD+6Ds49^eNt8a(WuN+6>A4zPN}KzKUXGwZ3dh(hDwkm1#Qr|D9@fR{~H-$X-mCp-(kfv5C$a2hdY9YV|HRkLQy_)?$DR;fmJdeO>}+ z7|L6{a-9y4LKf~!9Dq$g%r&bQ%WueaOc&a>R3uUm^-W$5K8j^0a&H2{z)+lSq^^!V ztgHnUdUd=gzQ)xCG-!{GaTBy z2~Oyt27}NiaD78* zn}BXbw+w$=Ni29k2q*%2b2wptgBE8~{_a-QVE5vnChlLAFL7-z5vyOuqc)%A#(K@7gjn4%-G{O}W zfesXbgad*#WP)H5N|_r%IE?xfSi@YHLw2_`6wiMEudhRBvjZu~MKo;q?pn@}`xgpGYt)IGt zf6j@sJto*fC}6@V%y|mX!QZ!nANWFCM70NG!G%l0bxXLIyLZ!@4-fpoE)c?2xc>mg zdvq|E!jfM)=mUYYw>4MDLFoJhw{CX$T(<|XI}|fPI#2>U1G~-BdYhAZtgnOXOLu=0 ztiv}{fpp722;Teadq5LdLoN7$iBx`ZNyO%BbR7i4GW0V-Xnj(Y^f9o}VnoCYOrYa_6O*|6^ub)?>M{rKo)>ZGyp^z4=rT)S$B|K zLWK(%Hgxz9Vnm4(DOR+25o1P;8##Y=^!O2ENRcB+mNa=1WlEJRS+;cfa-|CwFBZyl zp-d)BojZB<1j+2+I&DFT3N3o{s5WgGm-=-26lzqdQ>j+9dKGI{ty{Tv_4*b6Y*?{l z$(A*H7HwL!YuUDS`xb6oxpV2(wR;zDUcEhmG_?752F|~K_ZBvM7;$37iy416cAS?O zF=gu>SGIf^b7sw(Id}H_8FXmTqe+i+Q5tn>)vH;zcKsT5Y}t7!&$fLVcW&LgdH44H z8+dTx!-*F+ejIsn<;$5jcmAArZRpdfSGRs0dv@*Hxp(*e9eiV?*;Kz5Ei)FcE)}lFTyAJQK|{ z)m)R!Hr;#^&N$_qlTNs#s}s*W_1u%sKK=X?&_D$pbfP;6JrvPI6NcwRb7?UR$YA+)>vhomDXBqy%pD7b={TM zUVZ%)*kFYnme^vAJr;l2WR+c(*=C)67TRc~otD~at-Ti8Y_;8%+it!67Tj>f9hcm4 z%{>?0bk$v#-FDr57v6Z~otNHv?Y$S@eD&Rz-+ul57vO*e=5DZp4L%q#;e-`lnBj&U vei-72C7zh#iY>kvK?TslQkP-^MMrI&7`K|mToM5JUFSVAO4LRyfJ?nV}*yBldiX+%Uo z_Wtkp@t$+%ZRVUgGY{XHGv}LcrdLR>LdnS0HPob}pEN?ofqwviG*(v-PuKTp8 zkS3d9N!wa(1@Gop^3Nlc^2^LQ#op3!Op+mFqj?38{3CGHaC%yKs**{v9_MaBGwP;; z-H8INTwQBB!@?>MpN`91z`%EE*L#HX*GO0E^>n_>fAAXbh}dlmS&XDquEXoFKLwmQ z+1S^=L#xw&e^Z{no0zT4z^iZRMufbe^6n;g#%m&2^WM8VKJmtfbv!^UW7r~jH>0_9 zAuI;%v}{RsBBA|B4^FlnYa9k!gB9fo>T3{yr9KL7(()XLr-h5FON{KE z>F4ern)wkQ9!?a|iy=y0!KMFBWO7)gx_m64Ou1Xs{rV!cg4J*6*tim4ksf8#(sG~# zYI=)m$v@J~1NNq;fOV`8r4e0>TEp+Z$uRkWKRDO6?>j9m$Ig55f1gmH z_w-dOZr-!vz#4na@L+?($lBnvl`^C|NVVH2xrY&)chf=dU(uivH&t z3B|iexdzmGs-1;U(pjdJus$f^74|U$f|*6rt9Z^210vPEFCNwYJ%$(PL;u@+8)h5z z`2+N$vk3x%axrv>?{LuwOy zvx9x9>#8|KX0J2(W4CCsX}4`az_EorkvgXjW8RqIcM5h((#$!r}t9wq^i-D#7Sudl{xX1>SL{(ka14Z7^ zKwWxqOG{bc>#xe@&D~PUtsj<#=J28TJ%H;u%WV4|9xP_(hMFA8Ji5#&aZy!<1L=)K zRB6b>@@O;I0lyv+tHUoKQ7j|ozZB9t84ThC|A4lX7A~45;b&fE+O~-d0gAkLF|JrC zlA(v#t&~44-j-z!E1Vz1IrGrmQE)5kEQ?8OmGF=vc}oKE=w)A!swxljNQ~f}4+9a^ z2ehB<%yruLV)k7klC|DLo3Z&_CEHZ;_^B8>D{<~YLA`j(Ks8mFe9_0A32Z?MS zRpp4Q0kPji4F|04N<_E;ps6}UCI0!#Y>VDmpY9mry*mAyay@dO#e^0sM)lQQf#_R` zGXv21FMcy~GW|1>5hIDu$@q;7_k7rN3nK+m+*cJS@lbAEYPaCGFDHca9UDbTL;A+s zVUWAgOqAIV+A?Ik{w0$Rv+z0Fd!`BVKScE!7mi8+FAJ7*jgT)}f7O@hc-m&UsjZ3m zv3*W=6C|JJeoW}|ekZAuf^mp^|GrB_AkOY_LUtj7XD5_OC-QG)-UJUBTpJ|t-7FRx;ZIf3u3k|oBC#$DdCcXVo;i9@)ZKv9e zrW6DU4s%d##S#F}32V&KPpT(X#`T}BU5^s)4^2jDlls+cCrsooXPizNiU?aLxu?Ud zNas&`=r2WrxeFa9^UXiAp@%Z9gd6_!c}{Cvz++KyLvyiJrXUF{nh{@5}I?Wo3d&g=1TmA90UzOWtRhv>`6{3&Hn@@qjZHKA0&Y#mP z(HAkNGKR@WJ@C_^k2Y$KPO4z)8vHs^x_^t=fy>`fQFMshE&PTID?(8L&tUdySa)&#n;kauSSUH7$vxPu5;GbP1MEIF7_QD?*URXM3C_>I8H zL;8pab?M5)GF}9Yep;<%yGTvu-;Tc-y)le4E{$}VZv7dUvms`O4~mzi6SWP^fmrD( zrri3}qlN3U^zmT(@(!5`tPomu=Zuq+Z!3oiDp1orA6WbA96onqe{c%BsZY)fjrKSL|k+BcyjeP3O9r%*CqCX8C*- zZ4iEF82gWaF*u;;XUswK)trdmoz7KcdG=_(jGgph7desw0gUBSd+%Kg0x#H*F zcPhn`g#5?;I(%D|d_kk^m!BMWfU_Y@w7pv8uER}HfYn08hsUAeJ*-|LcKB_#mTswK zYPl!M^ex6*fpkF^;Wi5XGF>(9^*AYs{D^L#cGFk$EutWI2VQSO8fjVqN)E<5oGb~- zxTSaUm|B9U4dkWtv-)88b0(tsX9Q|T+Ii$G*m0!sO-YwTi>X9`3#)~&A6*It^^3El z`He-ClF9ui4kd2?Qn1;3k}l2SFSh+W(;XRzQSOls&Wfed!vb$i!>Ikjh`JKLB8bJ0yZSUZIRFrgqVR|dJO3q&Kgw}1MBZ|`M@kZew& z4*)OjrYAkuGzBz;(=qH|Z59%48J@mUi`M)dU+O2`c*%3G0B}{yqxn(jZr**?GbzvS zKBP6IkyAX-4IS?@@oNrgT^PFuhg=Tm;d6V$r~JfCF-|WA0~ubC=oi2ZXA#!?#M?U0 zAdC<50|JTf&YAVg0)B9pYYLs!7ie^c0iVJLCSiw%cV4{91k+@1+Q|M^E~{}9oYAiY zawfe>AxdN&t>rF7Ig!(es6=Dqo>LRQNxJ`m-_MC|!0?^0nEpJ25>Yk(DF?5Z5wC2L zDfGF&`#fTMlA6s}2&th=zm?o{{|OY&Lxy?dPeREnWUA4%>1fkW^H+rS2uL}~p$3`+ zkmM)YhTo5Q!l%0-lG?@G6zP39mB_on;V|=#aG6ofm}$F5TY2)zk@DUh;Rls}DVqlo z%Vrt1Kd9bBqSUz%4TEW2AF_s8vPR4~E+vGFfo~9}bO|I>*NSYalPVxeXT`-Vw&$4e zBb-b;f&Ifb^PKMiIeUL;?|LWsQJD%G7*c#>$S|iW1=2R~nofPlnd$R`)#nI{nq4vG zfn@R^GG4;wdBhocq^)`Ir96tOJOtB6Dw&To79Z&X|I7Ty)cTQS=_BjaM>eK>4w-x| zi~Re6`MeqV4_ov3m+}R#@{vphA~Ki)F^d9;zyhg^0-4qVxupVys{$0$CncFrDi)vA z0zV-wqS39Npc^^bSD*BUs0>95jV%gI0}IVE3N2a-t(FRHt_tm#itJ^I94(5R0*hQS ziriX@95kgpu8O>WN9K2K#XyefV-RFWd|IVt9|P2lH@m|{zf&##yY(=LD@8H`MsbXxhyQu!F^ z$Kfk(C=y)CRDobJgBk!V^~L7gXjk3n*IMZ}G&x|%O3@*}UPk55*2;sW%A>2w6Q(LS z0C;9mbrD!~nNf8$RC(T7bt_XvV5$bmRzobSVL{cznbo9i)u81n_;odcxrR!%=ICcN zO|`#=5VRz4p}Yha1H0%8nQMj?#$YUZMFQ%wSw2RNai{b**Y=HItfBh zom6I>Ok16tdo}NJ9g4YLNw!|avR*By9-UdQ*;cQ;T(5Cmr_0=6DBECc*+2=PSVd8o zv^7{QH`rV^*fH1WGdDU~HaZ10f@EP3Hn2Okkst%K$6_EOY_-oUoBV>B{M)J=GMj>z zn?jcB5GeBAJP0HY(wzu~=QVm49lC|8D<6fv2Fyl$dKfgz~Y{ft&fHQeI5rB=4B-m)&!vaLC@EjI}Ko|$}gg1q;H{EZf% z-n$h;&}>4Nk&D>@%9mRoV%uApJEmki0?Vjof;tx5n+^+$QWsMO8cYqIb8yrc| zn+QRBli8uZ7_q@L^PoTXtBt(BSO7ZhCaS0bp+&}<3Px|d9$n6Pv{lUQle2D}0Y=}`jKu;f# z0H;_-kVg*#lG;Hl015{rIEcThlZ@h99vQ^0FD4Tl7TmposOrqCNDS@?E^p++5A~vk zcixiAWx>~x6rFG&9&-cve9*P$Hoyai8B`BI5U|3a?sB;Sk&~fUR-k%ITP@g~{)et&uz%k2sRpyxb2z)cI^3du( z7g(~={yPS2VF%bLZ?4jY1@gBa%Y3~E9 zU<2<7<+zc7Jn$mhxO#B&c?|fWp&qOn;+xsom zpPVdZxI;XzL8k)>$*%PF9Pt?)=(n2je?5n>(^=@2U-?VAu=jAGCwpa`rMJhu{aeZED!1@oAH1HM z>u5a>oMIubZhqb4mRKnYpV)I-g(23aZ)Qs?R$w9PeWQSZ*XwY>en-3RrbKWj89Amq zb3W+qFfR*q?JjJf9mEf4R~iLO*}*n8f7T=Dj%OM7l?O@iGnd%-8rmNM3AMIM%U~ktAQ6#$!`mW870OxEu0CvGowmx@2 zpZu$oZSSST_kj%Be`tsdO3n`<7T{Dh*^FDW z-m@Jk1q%B_NHw7AhuatK*q`vcjf4=gKD&0aI7p^v`_a$lM!RkcyXJ=&)c2{13e0U~ z>9fw7{eDXne2))46I=P$vKw8EKhT2bmw)-C`Ezghr%iT0AL1b6+u_UL9}hMTHx-T~ zWMS2w``bB3A1IEvKOP<39&rXuo+uoXj~#I-9$)4h!}e#dz8!~q9&>ISgC3ngY)@bm zCmc^sNIOs9YbR?IfS(UB(^QX6sq`o*FsBT;r%cB!B)X@pwx`rx-CG@}T()QT$Jg%? zP9J)mqObdY%aH3#ki!T;q}ar59?UPP++RZ3XAh50`GsmIu`r+NQC{zAYW?aQ6i7m^ z`Y{TmoL#$&JYQ-j6_6$8#>4#Vp#AHelzGHlh!#GwTFQxYyFAP$)AHjm?r@68GBKLxw5Iea2J~P%&q!x3^GMPFx5m~ zPx_ql{`|h`!$jeM5nfdw{Pq6Qd9+Y<%v!C}1Wa?{??W;Or~bu06YwK~SSz=-bM3mH zh13)eqJ4X{LRkAJRdH2THCmBSm5T)RP5d`>Z_Wa*gYH#P+EulA{nLj7XA>$}4@q7k zZ-ACJ$D{}Z8j8K_pHq{%jkK3k`-VQ{R26mPof&WOxMNu(PX7ZpL@Nz z+My5{u8g+!MpFwbtrQ5B1Uq>5_U6z7${9pmUREr|7=9K(vqzCihS_f{D2}j&C6}4~ zXnu;UfSA&UcPS;dEA!2VIW0+TGq4-qlkml$XAIeq5rq7^nO$<{?auualc}eyzb8R) zECuCce1RMGzl41#u`{2C0i$<_HuxRB6)g6H!yd2SRNBX~bZsc_7D+$zP0{F!xrnW% ziu>cd8@@rbv$jUS0KhcfC=i+02?|0@<6V;f&PV@qF-Nc)w~?PdsG)l^@9Q0XO#p`N z%`akmv~<{~#Bd0Oyz!=-r*~O?D%&lwiY!lt)M@&CA1md2rX2=gKTFpWeDd93z^6M> zdv--VQu+rI5wzTfvBK1)fbhJ&taId>&`Rpqw`_n7`+mN?Yj9#iI^HmzTy_Q6GsCo` z_mS>Z$=3u?ut6wLbThB}j+ixDc@<{j7UhHEX51s3_TNW6P$Tlpa?MYUqPkFNr zY6Rdj&(>>Q<703QCTs0t_x`H)*qF)Jk^J#;pm6Yw6_7)!&vV$ zHcyI=f-}l2{(vtJWF593xMC{atvFSyI8H-9)Khi8PzFUESYy)H&{!Jg61#WuQ;$D| ztHlOD99nyH+xVF7?@1Xd_hOD5qS>T4DTwU85Zu>%5L8PA#59UxBGRP;0d`42sTUsg z)22b5jmv)5p3u+SdrR&Ov#H$kn*&2~FhO}><^#~3r$i3wTt8wZ^nuPX&-*^6k$7sa zvk^s9nsVB`QRwDfPptaI@Z1=1&p9SFrADjNVe=%^Ck#OdV!;!o*C0PoN?v|;sK7VZd+^4!CL?_ES# zq!7nVHr01rqG!(rgf4daA>1eC?uvZ?D|_zWGun4Je`wgyX_jA+QTBJ~3Rhy12rr+y z@H1M+a0`cUs@e-#D&S=3-S%io!YehgB7-=0M+fF)T0Bsp1cRjt8+>`ujW9-igzK+! z(p*6LsN+2nUgJPgyv<*SJd-%tl2{oZ4MfUaJWs#`n-wkSLu1}(-@$Ef<zCq0(3kGPDYvYI0qJXG4&GsHuaHD_I2vtoXsDJQL9Ep zO6SnhI2Vc>$Ol6R$4U5^`7u`xgCaxD8;uM0ch+m*LPeSAY`VP{?EA^lB}=Y}CUo1> zzWPQ3Lk4Ob3Sw!qvaD_j(p)n9MG<&@^foAwlGwi*1GRhNNcGAjKb{UpbIP3WEz_Wr z_1(BwcE?rk&Ww&1D>RGRP(wlqQY8a`6AKcXD)~gQ|3JQEX#}GL=FAgC7~MG^>l^Z_ zTJ(_cH+*LPVAy5akM)Uu`RLx$#{(jLp(&*%?3A;_9X64O58OjeLs@I~Zf~?l4Mg)8 zsAhZ1F}*w5;Y615f ztY&y4MvoY;c;LvqRk3n(@x(Ex=+1>BhgYE{rs>N~JXvRkD)m# z7zgNFAzOdTq-M0$))v)O=*v{X=S_;GTE{lAzk{;^9I2JvuxZ3r2`LF97)D>{iI0)9 zP~g98m)UGWu`w%;i6mTCgRf96KCT*5PN2?N`{SzHTUYbR6xvegjp9 zv}Di%^f5YyP6@mY4XSoi9GY~LB}ik&%);VwIQcZG%FJd8?!Wx3BQG#BR?({*aN1~g z)(b48y8mPPb2&8!B3zCOglIN?=n+S4RlGf4eBZAo?)8B~omoSL4QZ{$a_J)$u#V#k zzlMs}o*vH3yh9WZ>qzoEb4*X6x);h~_}9;Ti!E386+FXD4?X?*Ex-LLdew1=5fFG5 zME&j0_g9_&{&``EthoQiZxOygL%eZ3RvToU5?w?t-jV87o7Bbry>&mlTNPI}nRosB zzi}`A0|^MGH|vc*FAL*`>d?ukb`R2Lbf$2E?|Pt@JseF-_OR z6jlBMyWEF@i>>+*3MVE!w}&BrzHcqF`j4yM9tcL~?TyFNj7_g9;_h_(u*7%;F4*$@ zt|{(Vv9-N!UQ_thYAbitMX3Bc@ax+jr+c9W=>K*b(#~HV#d5=)-+m`Uko$b0dcTV? zuMZ^2K-6}xb{;SP{O)Xfv&Dn?+i?_}rrgOnC5gFSCEWf9%AHNqBe~wdU~YChch4}= zmzMUJe`F{i3o2pj(eEu{02c-YwL-yeq|bvSuVg!6St!zSe4r?vI94IG4n=W*x+5o1 z`=W_X79WSk-;qp&CN$!^`@wF@Qk0=SOC<*p-V;*qH@UlF7aMK;X zrzD^q@fi7)Onyp2Wt(4=}h2sPr^VGVDtdQ z)?ZazuBR9UMKgeG5#8D|Epl0$Y3Pq0<;2F`;fib!B?g?zI#g68LIV+I!=`GaqH1DA zYP<(#cLBM?s#=w+@;CQdZFd_thw~4BY$0mW9uQm13J$mq;miYq00Y2FT*ylIV^jp2 zU4OBEIKk!yVgc#)`qbjdpC^BS#-X5!Z0gBk5WBr@xe}a?6zJ9a-spBE7ydjsY$&ig zG)SyB*jGIyw$Gvj8qS3lwHmbD2BDs)fJz2+h$GZkG&6lQip?~1?KJ1?d%dYNQm)Z$ z7!r+gE@I+|@ORocluNiG14J3sFJLvOoW&%HI*vT744aK`A3uB!ytdC6dOj}&P7!o5r&PHF6 zJ!o4Ntd7)J>L)D{4d^NhR(k?xRjtZ_?9&EBaGAx(r9-p_K)MqUeHYDDIo;#)Q8@%i zdmYDsQnS!jS>GN__a!x3=(XY3wUq(^|l3o8biUBg7h*2z3U4F_%8U zLmiZ^qwTF{whjIz)^~IOHDl{LJQzFn=rvv#zdax0O6)Us!7(6)r0vJ-Y4il`dJo`Z zs{X2E^19A)Dt|xe+17{3?&;yU3=YJ`bp}AcKlSNc;uz6T4F)U+9{S&bl6?SYlQjW_ zj@g`#sja9o{Z=*d9>8qPOs+W^3}yX?HpuCS-mI98rj>-23X1hWlbB6|poE5i(9nCt zS|EIQFaH>W6iC2(1Sqb$t%AhT{I#4eW{WHAk;#w(?NrN(x>Z*A zt;$RfE>yvKh!G3zeLn-l8Y`%xw;Z(!&s9U=5&Kp#-H>8c&lw$tFx&KL*r8ETkMZ__ zwo;)1GxR25aX zEHjkUyv}8WF@u^m1D5l0(86qP#}{&HO#6s9Ofb4P?l4>vsc*sGV^OkTdjkUf>wUBy z9)AduuU_C-53}H%;#7?Q$y+>f8Fw8`{STFV7^y{l{lz=0{TybHkKz-80K?_rB^|uk z=hc3LlkiNFIj%UIj`z}qhkEb9nC@P4BJOvXs`!)*!m^ed>m-o(QU|Sb z34R24UnM_ZLB3c+YZ^zs6#qNy-A;J2&SEahR4%_hm4F4Os)ahz&Jw&PwG9bx?}B0qaW&lL?K@$Ws=Z<2 zE#ZX)GgdY*J2NSGzr<>I?|FnV63_-Q^9<%|Vy5?pA7>ha=6s8VK>n=`&%sDeDb#Dr9pLd636#icrmU zTs97B#tS&@=={0p6V<8|O)Zaa*@jCK1= z*hXyVjl4>J`}(=O{nwril4reg>lMhPru+kryxq;mOBo7GrHed0XrQ5nS02t>{qJIMc0&LDl#skRL%JL{UYACB^$b?p0j(@$H4w2mON z&6(`=BDC^L{=U`sre{w_iqKH?fw0$wJ2JXc_j5vDeNyFp<|uwEC4ssBkY0Pb(s5xf zc3L7koL}EbmK7k^XD8pcX?x-jp6cw|p*yC%PWW$*s)X2T6*+K3kAZe@yB-s2bHiHS z_PFA|PK>VUjX|^~AgLF+F))*tAx0KDy+KC~470ct8&{50gb_;^Y!>phd?(e$RmTk1 zBe$5H>YA>-!*BM~7USrepK9pzd$l!K^LOt+lmhVW%kPCwj_OD2Fi*Q;hLuRMKG4z5 zjcUYet_WkuF2$E`K`Q!$8A#%-TidpM5u1B?yal70OQ3>kM&Fv%z%Gb?`kCxB)wy#y zZc8OvSputL{q4#7Y!i7pk5f;(w{#AvJ=1A0n~)ihlrQwd9L7PrQbX(RSW*0#^Mza6 z4dm0)SkC{b-MY-h&Y_nqI~G>()6xw4QA< zcW9KIkA4nuZaZBu=K?6w9PZ9-95(cVXZNa(fSEM=MF87KU*$rvu=xwy7rl#K@tgZ` zL&f|6f#x+eUCb_LqE;E)fU^*2HgU8`=TK(4opJvletEY{+pL#P<0tK~1Y7?Lx%G;; zg|{a95p$jju;q<^TTt$A9Hu8dpb89RBw4boqKj!_sGm#dt`LKYH6ak|JMh0C#? z*yEQ@&sfo(Y$iVU3D3 z4)pOBhMHF+Sxn2ut~cbVi7h-L?YmD`ktvhOOEWRFzC?t9u`wED!p!TC!MbcE75YsT zy}jaMbMaF>-mx{_9G4|GBTj$81K$6ffB40L zmJ(f8{TN^%WJB6n6;S>vBGj2QZ&&wT zgXO<0oXxp`Fwc#>@AY!lH3jX9;7>1X<}vl+K1?#zOG zs(>o&jpO`CxzMjaTX$RVD2>2%2!@rtAE%~4q&LXL#Rc{G6t9Mr-JnUQ#%(W$@nWe7 zuf|>LZ~izHd6&yg77$s~_|JZ&tm9jd%(}wsnc1q_-KdawA*qBa;>2+k8UW@IKgJn3 z3Ym|@TsIMXj`XhdCa;NzK_DUuN4pcYZX7ASh{xUudrveKk72pXDMw!{lcdkV-YMrm zB0Ug*LZ5LBy?;nj>oNF_QzJ>ld8*v?*ZnaZ!iw%cKAC4CPbrE@!0p_*v_LbB?)TvN zXDzV7N5iLX>nYP8&C7gfGk)s`U6P@_i&j^2O1?U(vmZd|AUtxOuJG zP{HH6XNOnf2Me{%)0KBy>wh$sh?X`UUNHawj)l84K~71N$vC)v0j3uVjTa9U>p>Ri<3xIzEg<6zs616Y50fnyN)cCm97vJT z0HR3oK|e_${*pVL)_j-n#Boul?@7Ar&{H+`2rffX&Irg?dw-j`+07(}P|-1Jh}8pA zh!_H?Mez+Cp7q*>p<3I=!IjfRgjDB56&TwJ`}Uq%UdH8PlmwFnM#2_h_d{{(045#v0 zS)-aKQligIYPmvZM@0mF(`hnL>q0u=17~q`%v^B{jU^ao{MU;&ABBNUz8>O=!;a)a z;H`Fndp)p47TXnoj4`>e2Al9(VH+1=?NIstj@q>d_b1-{@Eb!Exnpr{Z!bk?Q^XRQ z_=V%Rh_db<6xCi~(}vzXuF+w4KFUbNKV9V_QdIxQhc`8MSH+fJQy+P6qI2ng!=cSK zae=0rqj*dkvChN^++#eu9c4)3`07{5{hn$nk_+p)?a=-!p{tyo{f#elhZzbt^eIXM zS)`%r*b4}60pYQ@P4#=Y^p%(}OwQefIAF%~9Z)c_t6OdcwRp>bgfeY=8S|H^(Kn(J zlS0e6OF8pOe$MfV_}|eQpHRAmqhw!DLa=be1jh9JN6z;FC(nqxfaLQpgn^S`Qggg` zQo+0Z@7jkO$YMyijB_<~N58m!!*dM27-C zIAF!=@hwp+cjy)!rlcUMiBA&4-&{=_(4Q5nY{F}z1IXBcfl3df=Y+&d|7KoLGV@H0#c0{WGgV9cdr}3=MP~18cxn+9P?BI z#36|X#{H~7CNv?{#PWeKacnsNH&lp8vO!}79I2V)^0O6jYGctWywCX2MPm5-jRLrh zv`bO@03YnwuUJmfTcf@lyka~_ESSY%qC4e&9@(Sk;Ve(v(iajHC2p)eK;IxdWO+4t z&r0k*P``HiR=v^b$YsnD09Mb1Cze+KC4n2T-RA&5jI+iMuuCEfG))$YncicRQGDx> zl8v7ukSc6>EpkN*W0zmqWK^syn~O2Tc=+?XCYi^M0O@>`3hw9)i`Z(I&@dXX^d!-< zk6@=L7Ne*O9L>+>#W^eg40s#l$C)dps%UXa4|4~Y7(BtM0TY41VqKaf@;DnMbaPk$ zYY#K`)BA{z=K49c^&g!)T`&WcDn{T1n&SEw5A~*h49#-DQd$glRM<`w=B6&#D3KBD zjsXZ;8ocVee`@0Tk(DMb_6(1-Bk8%35rPvS7m6Qb;-u9PVk$4_dKl<|Z=_bN5U5bk zyKHX_*;$FLW~}yN0Iz6W5Q7Q{?Dj?iG!gCyAqt0@>Jx$65-pU=Z_JL+NLZ0#`eT4^ z(uDn{n;=uDzp$$AfzqTn_82s~`VaZGb}>DaZfw7k`+b4x)&uWd1|P5hTLH_84wyiJ zjEWO>r90P6ZDj3FjL#`305_P|i5@QiEW7oX?*l1-wyx1J`_D5u-Qctw>Kf)YKr zp5S2*q6lsPhntLw#*i;>-F3jrZ$>W0>*Mebd@LVvxA4BTbrO|xwFu|sl28&yC)k&f zk~h$@IbC@Y(=N9=6}yb{#N4$9I-;v{ZV}y+FW=;Bk@Q?V#5kI)nh;YQE!CF%Tz9CL zJ4Qsc-;*}da8y&-k`XdhgV>5CEv=3h1=UK}8J)yD7i0&sb-0UO$n?eEo-2hAVq&X5 zBjxM!>a|iQx_m>HeJo0V&rvKo^piA{0=7Dgk0iAhssKj7a>ADeF{lY~jp=5r`C%0y85%6!n zuSoDRhT}D4<&j(hZ=M?ci+mU5@hCTMovslbH2m-YJ zc9I4So<5@1}Iq~CQhS3mu9O9w99QD9+Y{m zt7ozJuicDoJ)+Be&@P92B=@uNo%2I-fo(``RMwNtS zi0v>Ar-P3LRFW$)zQ0~fNy=72(>*nzeKm z_D?6b&hC#Zrz{OkYcwV&P07mR|Ejby;P|^Y(9WMlqE9?5?i&47KT{Y#J2E*0i|Oh>GQUb$8YZ@b^oUHr)5`F!K)a2NEyV? zGslyrJ(!d752r}Ctjf+#9?gzzuuJ)zMHUlNC}lTT6GO{nAN*vIGM{aC=N|VMjx2Am zA`kaZ6>@8m-(d`{A%4rw5GH+MTkxChkUdm~Hry^Hd?AZ0dnc`FVF`)aAYYi`vbU33 z$)_uMe8LEzUZ-Y2M5$M-zw);Xi8I9@nTC+8DrF?fwmW#`L}0=Uz*Yk+eMl{d*JX&)CnUdTM}MHijR4xMTS2jUQG5@TVxHH^99r;lu! z`3#&o6)20l?yF+$>|433oDidY&87Q27%^l0vN zrEsEHRp>l{VxVm@!Ek}iO~rLis{fk!tK0Y&XP{Xi;Roicqy@iWQ(Y?HiGPZ=%GYq@ z(D2|;@#Qcd(uA-n#UPa)U>L%(_Ig!HSzj7}dC75PalpYzR(dsRMO4o2jD~a%&0)Io zETxKFx5Hup^R`Zx&E_4=(KHqkl_3EYjK}1yiUDs0^U@-rAV7mm@ARqMVi+(sHS9%n<)X^|E$R|(aJR35h*kOaVW7< z#B5r|IckkKG94hBISE#k(%%3~X_7?NyZJ5P{udJ`<#Tl{UnhDl1gH3h;^jvM4b>uT zlq(fV=prJxQJ?7PIO&AbL^aMnW#no6(EYy&TtJ>SN+-+vdmpm6ElPKks|&-zNb*0R zGZ~bSxXtSdY{(DH=s*iatuXWV9xf#nd=d2B013F_?v`*zOpS`=5OH{X*LMe}^~h&T zROoDBe-d#7m}-D%5Y@9b!PCzG`C6|lTDcssUPzix$c^6%ql>=dOT2+Y!V|dA@lKB; z6^Y(-#{ykKsffeZK8$p6MX&Gu_YkolfHz8tNictjNan>npc7~JHNQ9RkwNGGStM5d z#nM*%+=rAU4We(cOaUdY7k<2z7*l)z*&i55vdJrZ?=rOQs&W&j=RNXMjC>8zuh+|z z;u6~HskjlXTYKR0TMmxPa$T8#gHhr1(XsI02baIKfzes(QXi9th~#t>h4W%R)4iP# zc!GoRsZQi#o~^TZ?PXPe8^+^$K_8|*@+OO2-U;I_(-te!*5+z(+IL5kSu&JWvXwPP z@{KBf=n~Irc7iqLl(qW7nnI!taRaS=Ww}Wulb;Ah$Zc%H(7ttW?3asu`+9dxsS;&W zNhe)-7b}1F{cmW1Wcf6+oP|~V~j*# z>VCzPV1*Z=Vo(G!BvLV>D==&7X)Sd)M#0x_Au#V(F&`q}VC50+B=FHwU?E3fsi#Pu9^$da)VoF@xOu;F^QZd; zUGIjV;I>-jcH`46s@^SK!S7C$-)l{GD0+9E5d`-lEBD4UcLRG@;{|^fRsQr*{{idW ztrR@yt30Sx+XwaTj|m=quROXfTS(??{Lsctm_IcyTMp^URAtR}I`1xTRCMVnu=_ksxsO7vd8Os%r3K zOf^)`6GVo)wLucSLar$xuhA#rhSfxA)g)COFlsz37fIIS-CuO_pS&18e$v%_0-8or z>>|6DP9}d=-yu|Yo_VV^3nA!hD4oj?!-Qi>Az^AB7pg}d)ao@f{cF@-2Q;?AbknA^ zRfcr0YUqo{>D&+L6NDL)1&NE_5#Pb^lcWhVH=TOmYJRuYu#DIE;Dt}7gjsiMJQhv? z`!)9nH7+No5U>b4y^j;|88LG$htSy*wpu1p5ia$!*_>1N!qdUZ8ZPJB`^hkFvJ7rz zf%{&yya_%momIzuLNv*>53A08*n3PadETk3mg{O$|tmJn!OD&7sbe}EX z)+u6yA1$9L3i;CU_(mbcROVk`WM1vdr1_}W`clgJRt$)$y{ZShiz)o4w-!aBU!0?J zegCD3{U=%_DHGG`6eDUA(;oK)4~yxn`4X1I{<}Bb{1nq8i2c11)4%ikk8XY2)gd`` zgP~}ZzEFb^wU^PO2IJjl#(E7VU!R%SHkc+nGxchC?EdUArol}8nOQ=EIfnC@d2WNn zv8P2}hwW@yWc$lY5Q!1=R*b z2ZjtNxKN{Gork?%`c^=U8>Q(U{iT=8v z@mCK5Bww#ddMrqW9RG2{){~t`Vl$shMR`BJ`O(-f}WY>#Tj zJ@$X1-yGpAmG_|8tGG52bIJNbDu7-rI_~uZ}|`vk(T>6wYVk2Ncz85-S?f+Sv)OS;{i$YE!o#n zIlF)3j-_+^n{x?&V~ASw(xg7pUq#)M$#-tf7YdA!Y%Nfi`lKEht|wD?ues1x2J75f zbSzo?>gqK{rewUSBq1;;t@U%}E0}U)T(L}UL2KCy$?|>~zj2ugqb5wnnv8Fn7{H1n zXumaQx_LL}O%*|=`cF%B=24B%bs$j-kF#{$t5!AjppSa84TP2k+n^lhw#M-Qlx>St zazIm?OjANzMp|1-rgUrZby}5dTU9`98{w#}zqM^V=>2?K2cPtp-L|A-*-k=pCqXuz zs2x8n)kQD&_MTjKW;3Q+NG@8k{j0lFk9vEAo?Ne1bFXcCxO00Sr&Rx|U@S&%;8)W? zf?P;i`{13f~A8K(~0>bo+w3-F-rJeB9en$5ts!801(cukt!DO4yBpG zXI^`AN#&&dLDY4wK7g91J5@H|Y(<6bPApJ4YKga6qr^b|y+qvA6t&w-meFU^LdFfv z!Mn20bh1UD1Y!V%TY0K@5S^z*gS%%WO8}MNP>I~)Ttg7O*SFRee~b7N-Hb}r!IAuD z$`ASyt-$}o)?G$L^#yFhpM;@@?(QBs#TmLwItK&=q#KE0D2J4kkQf@ILsF2I66tOc z0TBWH3n#m)me8o9(SPa)_4S)0wbA2ytkw+nK-?R_ zgJcQwIiB^jIfgmL)G98Ob$?-y!)S!7j)T7k_z4S~m_-MH0?=D=P^&ptV3%Cy(qsWuAe%Xdi|=WP!aWbH;dDD-kq}GEY99j6PfE zC`DeDTZf2%OMV2}kiZEe(~u3|)KkoJLSqVKwI?NM35X;`0We17$7htcxTE;`F_-&W!EZTcES4Y@rY~TcZJTx z*T%D^6q#ku`5JHppa*sgoGEebSXCy^!gMfz(56dr#cdMDz2eJo?IOiK51_5@%Q}IRseAz&PG&d(10r{S1Dol9| zo8&W_UT*8e2n#8I#AES=QZtwbTy}&lGTO`uz~pgyvP`-p5P>?J$o8P&z{MbCVLG5wpf>x)jr22J}4C z34RhOrSvoUW1nQrw|-0&2J-q=7Zbm= zg>h_{lAzEDxc>Tz~f;56xHZMPmtn#3rZ*y5q)qv4j4vb&o$-1 zw|jidc$`{P8j$?ogIe*+o4r^c&ZATS74u6z!hQ0hxGke zD3$GS^Odo%u-I(u>-jf z-2h%(7d#7em**y2zjL!-^(VlxXHsV6>%%A|9;+KfWx9!WLm37#NUY$G0g!=MV_Ykd zF-^3D6^3Pr#V`cYKv~V0I5d-vbkB$FqA69@6NvO%W1W7S@tFB;kDXV^0?t!`!yev~2pT2! z%)huiuGBCWx{D7y$u0cl%4_5$WdFj(yv|`sM(dNYY0LW3qJ9p*v{KNjbl<$Kn6|+J zGw1QFHOr#YhM?X#RmeL0(xP{pwu#RANy&PFbZz-dr;k=7*YHaTZKbqd-E?f%aiPmRb~0Z*tT${{wrOAI+nzpg zx3%5aeo@_0`QFoS!*=H{UDx@7=$}w#JIqHm`tAwQC0`)k=93D2&s>gou{zbuo39pb z3rlCg-5d7ph}^mr+NMw~gv0mZEBzz$rci}uhpT@2{x6Z{5y!SWB1`mdZ)7H5XLXKu zf9VH+bm!4TcXnv-%Q!HP{CN!HCRznM@%E3#itPxq1EC|s@Et3VXp)(p=rO}c8z$ce zr(?H&W1u6;E_;z=z3KeBhhgkmuqo-G-NT#p&_0^}#sF3&Z0xl>4*ByeJ(j_Y%V^|{ zvdU#<{-z7RkJ}sFsLSkHJJ$og?k7@1kh#aEWndTCUH;ay6QL)_b8Iex- zQ6XsWuII?KkiYz+YDxGQ7+$bY`shiyEtkiG5~ihEi~n9(Z+Te0Wm<0ON7ROJJ+a+k zTIpW?uQ6=v$(`ff)1`JXndU@$&xh>HYZDefTk{*-o!Tna=3e}4ueJAj;>f(wgNgd7 z+q&iDgJIs>qr2*w*qZRFuGl=bxawKk@(y{+yzp65?#;2iPxub=&dsu%>!&^+%pLPC zkp6lgMAQcaXW1jNydGlQKDWNw*rUw79uai#OJd&KXI!}+Q`q+Nf4KRPlm2F0$HCt= zcJn~c@@CR{+n>68^OHpG&9uA2cMP%G=ApvM%}kiLf8G_#5sLoTEc9c4nVxS-xBWATZ-ctVVIV)`pi%x5WP9`H`vE4*#rA`X9{bZp| z+oM4SMwXiPiMHwwCCFG}R^9fRxdd7eVAUF-3M7=xqC)FRXhHzSgpEiz{t19s8%zoi zKKEEIXK8R2EeI4`|Mz=QMKH(>Y<99gY_C+DJ+^+sYm0!TN4w1fBY+rT%_p?jn3!;S zy<+|D)=yJ;3XKBr0pxz_GiskR&(cS3?+bz1bY0y5K&1+hH^J587lQz9M%Ep}84)E61byJl%Z8q4aNMW6!(*rON#yUQe` zOgOv?qhi-wFdwVzo(9MEB3h5p-_khomdMf=OL+M>9Sx|_&cFZx+9p_H1n*LUOlfYh zX~-WQm!||NZf4KY6QLC;#+rhkvdzRodBQ+90~yH#e&;;e7-BI7=6GE}!CB8<`wA0R z8?HD?b1yE)L!7f<{=Tn>4Na^Xv#-Sgl6jo>BbgISb87_NX-$A z%oJ~j3IoV6*|Ij4?!=3#5CR%w0O+F6H>S~kkT9cmL@^vd_+QYNF&?1ZoMSohDDg0k z9B5Yh(x z;u8nj-BK;eGp3RewP4tC|=TmbxGQh$~#mecrS z(w<6%u%&?1CZOIPwV~SI!~_@sRchdA>R}>)#KQYCyL2#+P0|W4F~^P>Ie8gg#aFm_Lwrn2gOSf zBJh^7a(zc%NA7PuoKM!3W@g?K0r=N?C-&NiW z18WWfrd@zAEm1TH2jP>-T3(3sF8dNE#GpER++Oy);F0bDs8VpYjwPCf_%yNLF2f9# z@sSDObYRM|OQ$^x!3HiJLoYmyCHvy;DD~WN5Qn5S#T|lZF5U|>NGWEc1Y%0h`hE;$ ziH$}R>`EUv@e+7*Pm>h#nK)kPaWozvMTfhE4Gr;Denh;M90=x-Yr7z@r(;hgcS*@UaK?$<9RLEh!^nO~b&=UQ~iYwN6)Jg2| zA^5eH;6WVkpOn>TC`S4ed$_O=92`>|Upg zgV#ub^5`|{BEd%39z(Q^4U^NIO_r-sT!zDeW@|9HOFjgMIeSFjxpY|ggunGS#Zn4b zOychgse3ks$aO_78Vic9US&=qxmC z70ZkM#T(SW!MPJjf!z7E)xzn=Bo-ZNmY!Wk2cl9-3A5|%SvlA1Sj+L@VwPOmJW5H8 zr5qpv?BWSAG-l3sUgKn9Z}5ZDqwZv(Yx&ypvQ&J#1Sc-qRBGBbAEzgJ$ONl3&`3u$ z)Rn$DD}92I?Z;G4j~AAlq-oV8azEf`RsBULENEQULUXL+P_+iRbIADN>CF`S@B>lA zyLG_0klJ&m@8j|(La=+3cdt7yfL(lx%qtZH$ORN8`X^rs{JUG@gTth|@U<8qG#A zCE>^OW)+F}0|vNt374AfKY}1*gd6}s$ZB(f7kC_?n)ITu`#Z@CQhHwRAH$vg0YRDb zuBw<^5`Ml1vIXtA+|O`XV(L^pKuL~HoOePmMJXjEB~>o`1!H*S3$8?u18&|J*J%Zh zkc><&0NJ9?0>9ISTWicW!G!QMrY`h<RI;*>rV{fA|7H5Tu?wVY;;&)@uJT5A*C>)x3r>7q^TZf4qf zxyPFt` zu0xG-iw|6}-!?oxpLQ!;TfY0sQ=K@qM&oxPqqN*s%a$#2PgALr7yYAOg!R3MM3V(b zaHq-Fb4Ty7tVUX3U8;tPJDK*ti1h=%#Yy6OgaQw_YeFNgyNi4F8d;k?$bWJ zGnY{-q~e@e;{E3$&}wqT`q>*-MX+|BYTnt+Nv9tDyP^k(J?htGl5o{5M_3qn7~eWvxP#R|`t?8LS#pn7#8 z5N$zk%yT`a#E3TZf&yzQn7m?qh|Vn(-s#C}nX^ho^9(0V{$N7yvES#VY{~Pl%yEYu z=qt!6yIR<^9qDV7(b26wM(~TCcE;HS0Uvz_G@2MGV6_gUl|GERfiRr9bZ+r6E)t>u zK%bi#F+wbh{$2$yrazQZ!0l1VYO=f=x?nYQo92OrB$IO%keoKp?0_Bp?UKh@jVGcuvds;OPkM7mM%? zX_g$2QO2F7STiL!0F$G~Z{Gp40Dn_fyz{sd$Bc^3W^sgIH`a*h}m%0-n- zv~*iuI2_Oh05Q&2`A1zQGycfXas=#0po>mCd{8#xGI%WjwO_6nRIN-_^_aRQ#X&lk zNd9U3T>{+t8lw?VE=6#z-0yOqJXwY)G_Qy737R)#a@ritygnhO=?x4a8;it5D`3iEDu?nC$K}HXN zeipMjxa{9*$9hgMt-N$LLpbfBXuVk&0oI-nSWYoagE=)5eU3u6RF+xjhON9(8h7t*fzH?By|{ z?>B+yREPztWu749#L=;3$Dw5bl;A$BhzXcZ^Z^r~$J3HYUqVKKK~f~{dtgwF4SPK2 z{9PgqMpyl%z%%i2)v^|_^f}hhi9XN;T!vI&VUx`wFe&EO<}@&?VUh|@>$db!X*Hr+sSB+w_vIus@F-!bK6 zXN{Co`5#H{PrNT2fTxR|ho51k9h2!6TUNZigtDZZ&Rp9?k64CzuCecQl%J2WrB+C5)0^P$<(d)ID z%}Mwxbq4;gEfj348ru86w$Sg+Xy&eaJY8|NT?ye`xbUv0FT3J;yHb94r89S9zI0^@ zcOwEjb8Wi|db>09x(k1IzV*6$+{LQOyxv`Djz^UHx-fpialuYh4KFoc~db~^F zeS{f(>l=OBzx#IYnEUsY`VVaT55xP9UiP2#_MdL_pZ)GXXMTIB^!A7C+n?cYuV23X z)%*5#Jk@SD6~sd75j}Z79U7NTUWB=wD6I!e113#bNNehO zrJG?LZ>Fa=r*lQ7W?0_OE5FxDAv)59^q)?YoR9m6Ob#fIHo!@W3a1zCW)34}B2TG~ z-prhC&hV0w)Vu+QrxU%z6NK(gmFrIjMUcO>o7A@(E<6VvoX$Y(X9-e=XCr2b`(~RW z$o+OF{+Vz=`eyI^{Q>7iz#2sG3N1ePx%f4K|QY@XLV zhjNN8(!GaP><$9&&5~{{IlP}G`m^MGZ#lwqTHF@{<=mVI9|9r(VC&tXdIa>D76g|< z_P`jfzB^Q%vcghGX4~um-h(Kz4t>Uxxx)Do=_|YuFi|8p7d`ErIv!;&1kQk@vaB3E zCAd|_fcKWgPFLijpT%qq7Q(@ZX4t0w@~gh}HkRf3KkLnrW6ir@1P7tJ=xlg1kt<*h zGlV2e_(_mIKv>5|_<46j5wIDt3uZ!ZZlzeY8$C!W#vA!%i9fIF#_u5$VU14X1h2se(Q;0wYu%53I2cny+4O-=BT< z2p9r6$tX4(4>(}Got5feniSbHbNJ*jy-T(|Na6j-Zu^tWE%7(9p_gRS%^2goX7qZ8 z{Z{`L_$6W!VMr)93$8)0ey;|bBVl4Jq&EJciU3G$5jhqORUBAs_uAv$oB-XGg58VB zpE|&8K#*hficr+vdLg-MBQRw4=;-7#i^wO3zsLCPQIfOW6PA;zs1pItX~o?=EtSbi z(nG~)Lf5|_cZW^!fkPWi>(P_#ad9swI0M=M_#o~Ju`oWhFos$iZ>yYxEzl5<*AbV< zq~h)uCFJ&t#!W3_=$Hf4j)PRJ_*AR${gCmY?Do+})akn!D68jtyVR3^wve*&iH*a_ zxx=>_!_PY+a}t2*Cd5(b>>es|pLKgktawFIgmiFshsAJzXclvhDJIWqSWPGU+Svy# zZHB6Fe9lOl+&vo{;yA9~9(;xey8Jy2-?}iU--|y#|G9lBb~kuAGiZDF_fndDLof;w zZcLO9hb^Y=$)pi>7=lBZi6{)dph`9z&~6>?iQJH|ovjI3?=RxBKPsDv!r}9Ae^v~Q zi9R|UC6mn!kz-Cf8o>reA5us!LRc?ZrWaNmHbxCLtarC8nikp`zu zA(wi46@9n##Q?4t{od2)>`LUg@ZLd*=n4ossS`cU?FhdIm=x=${>VC9l(M?nw*ZPH z`V5CTo$W&;w%JR5W;Y(-*pEZ(e=U<=VE%xZ(pN>;uQ45tpCa$BI^X_=Mv}ioLu))C zA;s@`eLk|VkaVAd`L_nS?dPX_jy=$jsz`|2!2a>0al4J&PyPR#4AUweOAU;1L%>|`m#dbB8_)#AR? z=(@4|)wav;(@dr9innSj=)>7)=*l<80W1be!DqL6?lj_g&sbzC*T;E0gV(6aZtY*- zFyH>rKyL2)WA(pppZ}RdYF|638*0LT5~mRK&X8#elk_`oUe%EKiNQS5_4&zX>msoE z`$4aC7`%`k{wfIw5vRGpnd5A}!qCiGvtODyL=O}m<^);T^p>?5a&VsTKo$Bi-w9B3 zq30ml7!{c#OCA^a3oGmlBQGhBDH4^aJ44CS4nH$?o0`=f08gPa&e6DggsK+S;x^Xf z>$Aw~pM^RFHG@#LMPp06^}3ttHk5ae9tC~IV1ajhsa={Fs3$WbMaSnKVoTfS7fa~1 zAVCP{iD9+Eo4}{72zYrU5E#<1cjjPzm*XufywM+;nk>$c!3JDD5pR zp9B5TYwJ9h`8I3XyxTpin4R= zl;&>+)vhsbIKfbX89pDrK!_8HKw#AkoTOK{G@MGcJp1t6h>q#gH_QOxO8L2A3~f1? zpeZsIEs0a^O<=dd=HLU8xNUuhpt=xJ#4Vl+$`4VkrYIP-Dkno|>%8;gTGLj;QHtgN z`N}mXRz~YYj$!^WN)MWQiO>yI<6Hk|7z^cIw2!ot*hPa$$KEa3;wbv@%20tHNTpxc zRl_-O*BX95mS+KD&3b&&^q7uj#o!A6$FSW8oJcX*&`ZE};N|n~Se-E8T>fvE(GwCE zG??`W-bgh5g#4z2?DTbowm_4@(e-?%72h4SMMgOG%&&w~7ccr?@t>QNWtL5xlP-#N zHy3}9jcmM#W5(~ZaGMozycvaiMI6V!=OkqG|E!{vf~3Nb7fg`<*6QT>DH{8;c4HVa zUt{qe<;+i0diivGbV<-e^G4?#nK`~&@YR_ft?kP!p{3%(xX;g=e&ni-p$KRZ14<82Bc3IoV8k~>|zNY@Wjg8G59Hfy150_D3fU(mFB%OTOd4rF!jjc@@0Xv z265<`CQ1VG=qDwCsFiWN-*QGy!|pDkMOu$XNFoQ*!onk(->n_TXI3ij;o{3il<_zW zpeaY1N@9977-~u*%~lhWo}CC6vtHn|V!7KT|QpbEvxY%cAR~s&pVsK;87Xk@;|!GW^q%*PcgX*aLIQ zh^;5Qlh}9d4oMZ@scx$+UsCND;KGGvUb$#vok88MkwpFrF~s0jHv?R#wH}7s za&eboN9N4wKeyy!TQGlC?^+3c{f92I`lf^HUO{`xeIwxGO{;#>1DjoF|ofUY8r zI|C%X$``KyuR!t5v0)2|>v-<;-|45_T6LVImx~FH^O)iX3VsaQzo(S&B5dvXISocRP@WJb@Y6Z-CU;*`T4j;j_jGVojK!#6Ao|NeLZFCr!N;INS-PD7mEUd@fh4`pe zm^pEmezos(Q>!!R>qGt z!2PF8KSEm_@kx|DJNZsv%)}2~VHOV;+K}V7VbYOw!F4Mv_O6kMt1(%%T|@EBLUq)C)gL2{ zY#o1Ze2%($8}sLVxZ^G6f6So_(BHie8ov%7|1*a^Xpd=E7&1`Y*=Cj&%9N|f%owS6v2cBq1RN+9GMq`Uy61=|_ST=Kx`wL__%ua5-fuIs-%0jjWXynYMnLgFuxX z4S2Q@vsR>MAt;M%VVwFfJeZj4M>B1q>dF&TDlCz2PGnTDIH#HJ=a3MK%RN3nDvr2B z?MtN^WHl9J&=^I0M?ykmWuqEztR}%(UV>K>njW5N8%h}%;gW)g9d zH@K}|IH@NuFmVFIG3kld(j33jlrEfr)a;BhPlJ3ZAIP z2{cgK<(in`q}^5T6>21X9PU4-fip3y)|VyaLyAiC<0x^S4DlNo3cMUu{|Z??0Dyr? zIGkUsCnrP7T;8wAT)x@-D4l1oKGKtL;rs^}a{QW2G0M0G4`3nsWegCX>PH93z?Kr{ z^KEEmzht321yFDd2I2@%ZlG6At*OZh6)lVrI$%$pT;t<}jSMU&KIY+M!sdhg@HI^+ zHU{O!d>_|+=bEUMnNJ_ff=iX^k9QG@#}TCH0GY3QP1odW{jjf`aH-TWMT{W6-hhxS9|G#3{J;r*ThQcW)&?FuJt!Q1q_V_6bY=1dw;g>^9&z*M?N zUAUG@Gd@7XdtS%RmqiPCtE`=sD!G2kTA*iB9l#q|q90KRL!#6CW z?qZA*)oXrWI7g`xi2Xw6Wq?)DvINyB5R=QfTKt!jK`xs4!U-GND)bCSk)f{iErWp( z2a<=yl5>plaD`64Fpb(X2Gc`KAOg&&)ep^hUpMaE|p_|D~j2(Vjj$!$s;H z^UQ*Ki8Tk90yg`tzWY~c%x_BhlNPpxMNPp0Lm@O4NUKL~FVWf#6UmNY9@?*noK{EAtcIWN`h7z43knWSV65q# z^+zt+L;}fZDFLrmw$a#e?h5{KAgd&Vr;R~wbyklu?%igQm;!~VL^-Bh2`2m}<`AaD z7ev8E3!!PQQr$(?xOC`vF7H`-N=g)dPcV^}^FqMyDp;~HV~5?P+)W5ajb z&hrEdEp!IdKgfYxVxCsnfuQto{ww8$2E~}o>=-(2!pD=m_Ln?tu4*x>LbTCuV&UQd zJz-1vN=#W!s(ea%;+b*t~5mzl1< zsrco*Y9v(0ZUEaUuq+C-a+|MA92GD*0r|K>eP3Zktct`j2Q0TI%b8G1F}LOiTZUT9 zu#Ra^VZ%HHeC1JMyeK2kxy%$>S!wghyb9WX{UzmQ;mwclxa>)wMwg97jR<`o`)kVH zu+my58?o2wIQjbQS|M!NylkzhW@U_J*M@lcl0Yq0-78Rif-iH!M=>5Hq5KoTuFZPD zIfN6zcxQ_lkz{JXo{KUF)*W5u4*aJp!+|U$&KCbDn6oYr@l>_pmuP>{t3_;6^<-^< z_Fx=*Yvhk8DQ5=_x9wnM{y1$z(oi*pB&fV+^Fvq3Fq5stka&OUpb*0TE;*44S6j;W zy@9){lz~I8QHVCrBM(0(Zmn!*jC!VwT&n7G(741b!AG@<8<76GoXl3>kCN+~pQf+_ z;>$xIfU`_~7XfGU`rv+@{jvfb4KGRi_|=}>Un<&2+UYOb;Y&_vBa#cGZp!XK zKKgC}q6@jNbv&j?9*e*_FcIT!-1E3?rUxxcuLxM!iVo!97Uwa#i?r1Eiek4(~ zWB|i}$ie@THC{S`v;#YSv<*zf^}4>yv`1z}ULs^-B3Dbbl)*#ws!qF0LY&%E`!=z4 z_ZmG#d87x?_M;BM-W*?{iMoH%R40MP@R*$majHFz8%c>)SIA>~$-Bk+JnMU~6pfaW ztwKL_T;ckwWG+PPz-o*(BI7hcEYCScP#l9rD*1uz1rHt;{SilLR)+_T)jL}~(-1L& z7%h2yOnS|Y`pcc$u!Hh+ik(fgTToPPw3K9lfrhh-lB`L84VCcXO6*?=Eia>j*EHD< zXhN+YGCg#Eu}odS*Eg7wF*_Ns zi80vT-H?sX$rnnqE8Ra+8sEkJXOI=+C+A1~5;Qa$9d0O@R}tQJ$`}9n;v{C=`xw|* zxOY(U&m7~6t&c~<+sEp)Uwql}E3~rxLZSWIw)}Las#3XT>h9S~56&77iRg~4i<6T< zxl5+6N!vM`h|EFJ+>gqcELoVun19ooVOfd=f^l#CnA7Hxzi0JCCpfpvRLK~=3@7Wv;Y1)dJJ$|Q ztOC21pU0km^H%dcwqDP50p`rDN6^%Sr$f)bV(RM!!A9m8_e1Sah}$Xx|jGvfO) z+c%B$+&&{;hibf(SqVE=nCLB>nbKWk2aEin`%2lQ_0Dt zx2U$a;9&tpw0|c{Z{cpbXKwQh8HDeI6^o z0BzAZ@BeO1=~E(*h0#+_RQa4WaukpdO`|t=zXATklB!SJI#Ai?$H{zvRuhGKNT6<0 zU{~}HP4Pgzoj}7Y68&$1#uPy&Z+}#$+SCROm>30_I|emh2U=i)teyvz`UY7y1=+q0 z%EAZP?F2b|`!CLlGzJm0UU%P7Jow>Nkp2B&SI1y;qu@uFU^h%t;N$1P9!)>d#lcTL z1bclm_S^~f5r3=Gl;hi!;(Z^-K=V`4T{+M(B-ke;1ap-d6Y{{3G^{Bk{Mps(zN?(F zkjQT#n18i$6ro`sLa^eYvG+sce6B|2ui|{JZ+-)wJrBJLcL`0rB8_UwN`7vWDG(By zca?N^{dGJv-6xa=a}9`L56d zUi=SzG;qNva>+4rxnzA}C#CuMdds)asjHvMZ~v&=!Zvpz@3y~1?%YN0Qbg@({kQTg z@^$Xh4#M>Hou7Mhn8+EQsH1lgWVoo4rl>D(qu`={b8900MM>L`e>SgR-**0RpT}_d zlCt`OzO&z*tY9y%fb700SC28j-VV9tMocIFxq11gfe;r6BBT;=`+t!`nla+C|Cb!% z(n_ef$l#jD7P4&hJigHF!2~?8aiDzRl{{6b7?Kd@$4|%i;<4w9UF}Ex9#4%hNw1S^ z!ITu!YSRXf|Adz7Z8|-^&SLQ^|3eP(Ce8`3w0o?ydVTqMve3m7;5N5d!>z#@5J$9V zF_}!k?oaqVE{y!ME<-}@-C3ajvuuRd%SpI*Pr13GSBm4nZl+*51%`noLx`-8O0eU- z@f;i^+9i3Kjj&>$AG{Df+w2MXe)g5_E3$Pc{$(F*Q||I$GPgJ0L-OoPx)eOICp?^s zRGC0RGdiBJpvGCaQTzxIOP5{GmCPF7M3 zKbzhki}3E@C(Jh##2)#sp_<_9{{0yl{y2)Km9Ykq>LWCSq+cWpgCf1eHfluZ46MeMZD~IiMO{$XgRKnuK4-jKD`70nD^4bDZNBFA> z(*y#Hys`h+rm|bV*yEa}%t`x&?lT=qx;)g^raG(3q4pZbm!i)%i3uQ%&)P*25nudl z*~!9b%{ItOXw=y+2>migP@jGG)gqu!DQZ)wAAQSZv)Zk*ShCXDX{Q*VI5h>L# zFjQCl2JF{*_nPN(MTwYp{YYZkj}(#?2HYq{Ua~88V2E&!d;F&+D3*|1T~IWO0);jy zIigJqpPOh2!m+QfNsD^vq+^aMODsag4jaW zSPF|~Q^o7^7!e+E-}|P+G!a}W0fEQl5(<#NF?(@Fg|QT$h%~9TgW~kmFS8ZXhZWif zpK&84@AP#ZsL@JZutRvEx$E5%To^e8J>i_p-1Pxo&gnMl{Tx%xP26{j=9aWZUMSa?Y>y)3xF>=&z14)hTuCW?Iu`QyCa0+JY*#vZn4xtAdDoSa?0)Hqy z@fui)#|nNhkRNBAar;brPheXUt=d{tkFaB1!`^a@>kahl5hn785Hr_F4I+biJi_D4 z3@Q6OM__!aZ4}DAQv9sV&*Kf0n7^NYCw@;n)<~=lJB??nx6P8OEaJb|^>MLw*4xX0SqmHjXeETGmR-Rp>bmW7te1)evM7XvmmUre+Gw9OH_raa?I5 z8aS^X5k{3v?~gKmr9**bj?Xai!palgBsmd8xdc(xkoS`?j4|t>cm?-+j$g~2V2vE@ z1D*zVe%T!QbdHQH2js5#R&;Wc$DqaAHgm!iUFyat8IC|-CDBO<+Pxu40XA03&ru(; zMZ3By5o+u3pW;=M^ z2Ra$P3qXj;#S72>j_{{x18DJD%Jx$5->>?oMs{vpOpcBp-CoQB$QVd(NUlj^xiLRT z*PGF$|N4*Bmb=yr9onB-x_nOc?D?#MA*uWlevEVZh54*$#1b8Lv8W=-oBZG$byWXU zu~9Z`iB+MT7g7$S%oslwZ$>1zY6Yn>%@ZQi9m0*3?*DdsMr(AxA#8M1cbRRTSi@K1 z_u>_}x7Vrzdy+*S$iW~}hhSZBKs!FkT9jp8I4DHNn}a|8VLC6P17GHqrDt5aWGpal9fNh6lCBG*W|tg@Z( zw70mv>u1m+1~Q&ZSx5}+!L*aS<=YWF)9Mu2SR8j)<|AKq!hR!N7BfV|-7Z_`AoLQG zrI)|k8?obxe?RUCf=e10xxI@x9aze<_|L7BzM1SXjjGFP7Ss8liSb0{@wOIED!m!D zUBlGQy_BHw1BdSexk_-tAd)L5lfDMa1lOhW1j$uWKR2LrG#_O4G@Wuy;8rlwp)94n zexSHGHom&>4{>)~)8cr=$zIPc_`(^Zmc2t+w4+v0BG|zda2-vIHatvEihfOgk}^YI zt9tioUu@m^%$Nb2KSVo`ArhxodqaLckQ0o9GaPDtZg|JHr~VzTehDEaYW=kZiO)x$W}I#QNPc*b)gCs9lew5pqYgQZdJ6tF$x&y?ySo>p6oqb-)~3r2x-7jy!R(v_|QeT%=u$YnObw1Awi|L z=LnfJmiq@t{KpWD7leEfD}dQd;^P_8KVpwH*wVt8GtDLmsDGjjvu_w3d@?(F{4e4U z&*Tr%TT3S}Jo<<8r*^9w&_eVTQ&Q2>BtzOXa2SOg(+gR*bP%wj>&@WE8{TVU9S6xZ z5*E}zyQ(05N}u>q@5s<}mw}7)p($WmVcZ3CK((d)h-G!`&G_B(VGJzc-z(}`3AeRS zee4YaU?G1i;Jmd)S^|7qE@Y{TDf8*6>L(03E`ytHv0LXU=$>SkWkOfkX$}Md*&FP; z8qz6T+(Wzf-6GKb_GE+=pLV4h-$;xLP5i=j?%Pv?sq^HqalIKV#P)^WFeJvfqxw25 znlM_UaxGU|AR~Mm^Vlb1lEfIGJur}x4l6rQCus+0#TA&))R5!jbg%i7aOy!t6Ivn@ zF$r-6JOrsD@ukXcMIsYdUq_BxMq&@uaY-X7+7pK7IwigYdlE;Q(-X(EiKUPl-Ch1v z4<;jvB%@;IsHK0JiAHImLtsix2&6WK375epn8{b0DRzf(x6`)JIHV5!QIkEkl4>&< z={lZfSo^|ILpP5gD>IIQ<~TP^F#knuezChDl092?EsAFRMZdd|xqJM9fEs|eaNAvt z!7ZPs7V}e(?DkkkA7a$bmpK+qP6I40bB`l-&wWZ*793aX4I$GwN*d5aD+}cfC15mP z+07zLWEnBnd$l#XX@!b2InKH-(q6q%OvnJmsazO(OOl*S7LSThQhBc>RyXIX`@O+i~jKN|38G?WmHtr`#1b)h8}t- z8M;$Chc1DU?hr(fZX_JKL`0->Koq1zN(98AK}6|}Aw{G_2|?iI_q*@szn=TWv!0jd z)n4nIz1KPC+SmSk)4_OePwNP<=r-uvc(=qPNCYd{BMI;A(Gv2`Rlhx1gWrM4oAylR z3r!zsbtDMs%s!az-R_pz_cV6u_ZI1+*@HcZ!SzF-%OssHCtq%??a~3o4P*aAi z=j(En;9-oY#-13$OJ35;CopzFd2cNH=ZuKAjc2XJmuj_1!SyYdS>vytNcQDighuaa z%35MQwfsI;ud{>>^6$wa)I|v(@$%iU%nB-Bpa8rF&}YVTJ{6lDD2Jr z#n)sJ?`^#X%evK|Gr_l;YHps)+mxPF60C+yjgRPA_w9NS@g^aW*|-1dL`7)TZ}Wjg zdOc6+!53|B(Ol|R86@JU8njN2kRH`3hsMwBgTJ8K)0nqs6ulor)Q2T@(Olq5j)Ti9 zkFCXB^p}|HBcD5?-RBu8qO!5-sXaUN5E-=R4n+^Xdta6>R#>A(rsiOn!MeqwL)nch4_+b#aWRNYf5|-~it%%o&oQT`uYP-dnV}wh^oWAcxWJ3{VMqF`AS34w~ezO|pj6alxzye_3<5m>=}eop^A zl55C6^LJ_+d)%Lnq}Dwys~XXk5`YkYRtCtw?6=HplJA+Q2J6Jtn#9#SnB+0)!kFK^ zRYE=ujQmkreP)CPc8lP1zt7ZhQYGL;8;hR*>Ztx+88FOLBm%JgDLA^ILYa;7~Rq>wwzLDFn- zBD^=zodI_yo3f7U@AmBf6$nzp@1q0NMR&VRXVh+wc3Xd!luV61$#2ro-qjTqmXB*v zO+Oxe+^qNg82zQmWTpxIN6hfS?QgFoyC14+GWYi8AFCS$7u{%KSJ?gfd;Irv%B+80 zcZZqQ8INwDBQob9(8AmkdHKQ3lqUREt%wU)y0-^EXc0OD?HG%z zwg!u+-?k<_68{r;vv9wj?~1erdph?>D@g2St9NcayrUB5Rd6u5a}x0FMDP1gRd}t) zot{qWmVeW}sF@g}9;}Gi?FO|ZZ&i%AT$C7jc!02Mj~Jo{(thIY92?U3M>Qg#*R?qy zEd*y6Es>YkASZi1GW`^Gz*N zKB*}pp_>AUl8#HGv=}k~!h4_RqGsP8EK**b`i#VQ{0z-?hV>ed`gx?r^D^jX|8=OS zOM|}$IH2Spbw=%ZwWPf1DbnFgU8sTQ=UM7AJs$05RTmNC{(4owhv1yIUZkO;Lh2@; zPV-l!pO^SNeJdjPB85@m5rp?|Nc$-ozn^(fQ}m6am^1VrPcO9RECd{+N;pBA*2ND9 zC#keWeEzN$B8xqblr2B7C{+*oeDcbX%ap7i=ak+83vxNO_o+J(mdI?Ds*$e_5H(X* zpFKA+ZVaowK3h$ZO)UZEllDI6Je9fqL1H(iYNAa_NVvr20~&v--XZ^zQlVDVE1b7i zw!C3{NjPu)JY8GvuD*H!XIuj%r0~60q0ep)eXOxzeIs@zY_?8#w;25Xw`33Xb-R>f zk7IbV8edq;_YbO$?VSw0M$TuiI3*JwNLRr+#)w1CV?s#mx;iNkCVw8~Ux%>3R~CNv{9HZ0`eQX=F5C!{3c0u4V=cZsP~Vb^!WRf$n=u0c*$elS^Ly{o0pM{=n+FU^S=yHbqR7HY8ieTp++mI z7TN6{hviAwIViIM?jWIlbYOA3xXR0py40_AMrJHBB>o+XF9+Ms$ z+H))|d!7-9o9Q^|4A1Jh6b^}KuxMuZS)28%p3(@bZuGtC=H=0^_eY9BW0>>04UK7L zydBrR5YuPzm*9LmlvzW1<6+5nfx(GCLj?_#HjFZ}D{8?Ao{KAY4B3u%X!(L7r4Xq^ucUhw(!n$BP4 z?c2{~*wKk*i-%YfEw!ZMeBt@3+J6G-XCN{0#Tse&-hhda_@LhgGsCG6nsY9}2!?3id2ym5(U@FFzz2dU|qMCWZBy z>q%yidCc<2f3tW%bHhx36YUjUb2j=bcDN#XHf8&)VX;}x_2b}$#I%LuhkLD|OHwCe z1r62{zWM73PZZysvb~ks+kB$j#8K6k^8hx#Rp+#y@AfiHnM0c^x`W>}&pu)78F$W? z(k=QwU;X+-KwyZla%=ZPE!ERMWkMBLm%`Y(yuv!h8}isy=o>z8aZT@9J6CHxfdNLe z_Bto|>!Us=K*$^V_K|{lFb2Fl-(YS zF7M^`TYbNVNvS^o?nZhSWhU)B8?DJqDMQ`Hl$+B*{EfFw?-ylFTYE(sV4_Kuj$72R z`hTV!<5{z3?|FS3pLJoDFnMk7DbADY@%0Y9ltqeF74on5Q9{1;P3FO(Zy&2nv+cxc zmW4wkID0X8DUxB?@%d8=bKit6>~BulnVnZ=VFCV7l_x2A=JY<7O33TgI94f!CA+D; zr*`q&#kp%K!gW&xChz|A=RZ*VC|lwA8k)C}VbEf5*N$2Gj}yW2_UT6M{o=f>e6LQ% z?}aP(LpPVK(=5N^;&0_|mpxTxa)0q?pYeURojv(h`K#jmovPYSrk^$1Hu+fh`9hfW z&-%Vw1-lI+%I%hQ?N{fUnPZQc_ggoM3-;R{I0HB9K3;wBYQMZ}SQY91U`RGx2&oXCHC&MQWw+_t)DMbY`AF2<;fDZWcxR(VM)k;{GscAqS>D?2l`+KERdD} zAm$UidY2j)DM$b@&Z3F-e?%$kqqc5Ys*>6xVpoP)*ZyfU0bCJr?6gi;0B3Fig|}BE zr|Bw*l};zM^wYx~gZShE+`0FxI@^_RupCQKn;ww{=Pjz_Seko8hJ5*y zJX9%nGs~v4XM0B#{ZgzZ*XU!-`;f*y3AVKB$f3$6@|}?soVYFH+^m+2@s}qGH7m?N zEVUI91k*H339Nr-wN)Ns1)g;Ztg#VW>8Nw?rYGGSVWOPV(N-RpO1}O_=V5#Z)Ul_2 zk@qi^Yo=M-;4yV(+6GszBBP#3@lo2#jST8eaIsER@hH34**;_5@>g~oYPLrf_@SQ@yzkyjh^NXy_MIu*%*5SJy7$Qb z^>Dvb_tcM!GsuCFcE7YoLLIE9$ibUE&GclUc6J8Fp$Y|mY(`$k2W}b0&(FjCGvC~4 z<+orQ#WG=u#>vw+RYgg${c@Mo4eiuIDc_6>?;iYr7 zW8O;g1C@o5uUPs&UqDJX1-zQkL~}{~V^1~8i{q9j*-c-mmE83ws>gGt1KTA&x*Hud zjfn+{YN^=mlm%gL@}fKGs?3%if)lJ0BkC%u-C1v&&oIrTwguHa+B3a&gauBr?H$*1 zw|LxRyQun2%-!a3RI(wBv5Gci76p@@a8M=kdrsWgt#ZAT|VBZ#VA~dy)LU?6-7Rc$jaZ zdi~sONuJ^zm4L(xx&sd+|;H?PyY_|L``@Q0nXyT(c z_mu;TjApmwd|L6bLx-h1EZgbk!Mc$mQ#iKBwS)Z+HA5+Z}H*R+st**M#w<>z;S0t z>gm#fHE;MLxFiVAa79Sej`&3PDKvue)`rJR9(tx})hG|>MRutGex%ZF|4wOa!W*pl*%i^iK|l6v4(x06${B(;F*PcB-Y8He1quvbm|oe zTjh$3WE7BW(C6wm<);@p@t;oS4yvzu9Iht6U5Sxj>*!vee7gwkA&Q8)ider!)L(tp zLDn079L0*3qYj-qeXd%K?7RWs@NZ#!Vn!LIFt=E!h9lM5Fi3R=e0_NU^>&1PLDQP6 z(&KS(Z!{f3m5yl@7J-6msL~0QLOBm2wb;q?@z78J3ET-1A0@4bf*2z@&C_2d9Llu$ zzycBH=A~2-D58*2B3B%RX&2pVJW2A~$gkK^numBWS)z0r%4js2&XS!PhanNH2Miwo zz8ykMS8qn8a{(giaTIQ16#l++fK}LIF}kZL%1Cv{5D~2{9_opvyyZkYPoTivLve_+ zD*mET0@Es#g4J*cQ!&c>x($!jiR=k*m=h@iL)U4#CO$!< zVt|Nr9QgHJ1=u}myBh-niaMV192p1|M*K~?dPNIGUEn$~)pbw*< z<_(aqQS6l{8Gis>eL0QcA;pL)W2qwo{qDo|-It-xM9WdMYU1=~XnMw9Y|bbmz!;q= zJA;W6oiRIwA_5$QrT`ftajN8x#UtX_nINigWk(pSl+LXbhQ&Biq=8s(tx~Bu(GKFk z8ffaT>|EN8h~)-w?#@Kd^rboqeKOjY2~I_1zIX~|nEDMz?FfPCXFswtYX=>csw4rUA> zlVB&@DFxq*Poo+O(Fag&H^4k`j0;o{co)kqN>n8p^mdh45k)$#&iK?3r86cTu*Txr z2y+3D+1_rGcv0qtriOrM5~#ptKz?8b|EGEyL^O=~i0m1Gwt1DVVSu>}1+8)9QHi0K zCxAByd=2bW>FLx~04P9`%M7jXr2(>mV=l+yz?C$-U#Mjk>!DQ|>wqHqM+zom zjcx=Ar3uATN+r!wsz;o#YY%ZE%`WQm=VT-GP%KUgyiXhIA36#|!~viQQ9?v(9J&&` zqpApbJUA3bJo--cM+4aOW+s(`nF3kbaNsZ$@0TN;cR1oETGAR6fhQVzM;v{LjUrLR z!{f;AjAQ&_XblMB z?_B7|38p~}bf&L(=K?8-vakqH8VxAx-@j2ZHv|IbNOr%JtP_E;$h2ffz>E)Bnw$_d zctA6+f;$c5x)Y7$DHWwOp#rQ@3`XmjInsO{hf-vU*r7%3*!6&!v`UUJTA&zRG~%|0&zZSxN<<` z@!VqSfb6xCpaTjs_kbS2Zeesp{B#nWN?=K8g7|=CrKax4N!b}lPzJ7ZK8Pl%N|XL$ zjN&<#PDLZps^mJQdXr79BrT=4w(h68GJ zZXX24=KM;?31#y+?Ij6)cKSOt=aKNYMQY`ku6yv=O9!>o>zWuSSeMYliqePrV0Oq_Ub0-blvP-;*SFQFmlVUndsDiWW5 zmPGq?vF`mNqOV~^mgOxWLAjOzuX1N=kdSw0>jbPoQv8#Y5259_vnPGXr6$=FW`Wd^ z*};y`liA#*(bm+}T=Qw!-i6DDm8Ds-#@}4u# zJ!fOg;Izu%&C3v+%Mg`IWMF(DllMYl?u80trn*(8c3!5E)eC*bEEB6Ni@YqGxhx09 zY|g*fOy|68kGX6g#+(4FoDjyW2YESI#@tw|+{C=xCv&;KW=Wn|<>ln%70l(8Fy^z) z9ETz%_THuJ9>m|m;qy>iZf?J@t_ z$2$E1Q$Fcx-v1pa^ihrd|1#6>o+<1Zwlt$lrUAjw63biud1G}ddpPZ z$ONQ)V_e-nU!8aE_Q|?tpbbiu^9Bt1A4u{2&@UhojMb=&sxR$Hgga|k!rzr?MvK!* zbo|#-M2WhVBOA(xUht_u#?_0z8qR@68?eJQxYiY$t?++5#g{rS1neFn z)S|#>qJBqT$1cMPaG6@_7*0Ty4gyMoqDoieD(*w20ghSx2320q)lh(`Jv_pR6^SKd zH-Ed7ZrM!Yf6U(J&DMxRVr~`86Ra8aYO$)m_bPV;ke%ls6A>ik000d4hoH)wZ8@4K(AKmX zLM0-NLmSeekWbiyPuNrG=#WtkUxrE_%tByUA8+GLdNF{0ANJ$ATShw{#i$MBcuVLaeV-FA;lpFFB9$y(@0P} zI?M9U9FZOHAD#YssOT=yw&%CDxfL|6uR>I))rb~45X8;P7D;S;ybmOvFHd|%!2Kv3oJyelPk0fW0qB)ht(BfhKvvVOh)IcYp680AE< za((f(&=ZU$zgzK~r0JlGh)~V`>5o}zb)B`sImn5%6IWb&vi9_Oj}b8fIFr0C?ER4D zk6?6%vG%SfpjpmbKKEU}$i;3GgC-CNOHF$ou`4XbH^42h=Q&LJdl7934>@7JZs_1i4ecLaVGFwAG5@1X^ers?51XUFrMOJTrva@cGz#b4SZ^n=Ve;ES-wjU`}N6pU`xlc0Y{ z0PbjrlSvIK8ITwxppsuke%MZ85zEo@e&tKazmYf(0y>G8qwfz5Ccyy1_TEi}XHA6} z8Ncf^(w+ioEYTnxUV1?hy%^h4>@diMxbjUCk;P@E>nuIyMt$Azr|F=enxl?IQR{`9 zMe~SfX?*Lf$EPyAc*z~0i=17Is&0Oley>b&u$$?mKIUJ#{p9)plU}{GyU8=~8Atw< zCnQD`(2bys$@y)@Z@Uzjbf1-3vH9pl^ib0>^(r*Kg_c)Xde(Evk};bWd)=ZLej#KO zUe=)hrhG~Xbvf;Wo>igGtIWi4XF5A4%{@(}mlS^Z)0EQx18H=|Ll${1AOg@0+D%kd z)|d_nnOs8rz=$%Jk#Py4tU6r!By#O)tz?2b$@uF_DCRaPRe!V6-_8E004AMdxz|$A z{Vc8V^2eQtdCP3^jbdsy?DX)7#v->k3RprzOy6@<6y7NzM64qyd*M=*P~*=5wE1HA zt*T?4TvkR@pKO0a-+5;9SEpc)p2Kz0?5&Hlf&3r4g4zYkF&OhVI%Ec9hUKPhwL8Jn z1^ChW2f7LW_}?2d)*5S0*uZTB3R>O>w;j1TyeB5j{WSK# zcI)#=qkY4VLVdL%qV-cv82{n>^H|4~lX@(1%4EMHJw1>RKL#5u1$3{wQT&Ao2|v_n z+t<9mww5Z&ogrlD>B88gl^%rFo#`RlKt@s{D-1neTB|j(wb2>lPu^I)X64vuQM+NT za9#ijmd1gvEkfUwu%cR{l@>Wj3+YFb%Ri1nURu< z`rJf++G^()5(&YgGKSv)O+--(eipa~j~LWGFz=e5u#9OE31#*RtYie zJ_U53p<JVTxUn@4(X3H=sC@Bh`oaA zA@}iTW{%+uVTb1qrBHaaZG}4`86jFhq7-oAlsu5PHHyvnH`?Cv_Ii;&$|;uCL~w__ zh8c*DDiR$LAQ^1CxSQPw;&TL0I;!lhnMIK)NW1t`n~wxDe5NsMGzNxiSoc{luZ>ya zRDJ1k!a^BD$Ou@yKC$yg!OLb;#HzN?s6LUU^si%tk4qS|!jmH=P=7LV-PniZCS}7k zawGEw zSbCt8OqgYEymb-8n`cIi7qwctnF($Nww#zC5V&=>#} z28AwDharGpG^AMi6Q5{W2$%pLw<4n~@58jQiT@_Ne^Eb>x%N%ej$^sEDmVH^4)`i~ z)HTUHRF4WL85^QY1>iFA18|3g6EYq(!cx3|k%kR`2sb*tSiJ^%U$TjicZp*3fr8zJxjArK2-!zU)sJgwW-HRVkcmEtm@Wv~r#4wI#-&*f!{ zLfcqo@I1<(Sam|a)1PtmG0bMZ=)Z+6htvAFs6A=5-oAcq3nx+}d&jPu!6fyPS?uU0 z0~R1rroQVZqWnf`HYtS`b?anCG}Y2eSIv_Dgc~}`2mj>?=@XyzLxTwXf_+IdiJn9j zs3B()Ag?m7shRLQ^qh0JXaDWc(CGVjbGXd3qutD!bmTABxY~Z{X=)*~UDL3}1Gicy zsQY-7-G;meTzx}lo>^rpVj0mkT*~Qx=!j#}1S})rV6O9HjW$)YhjB@H@A;uk3Ktd# zvyEr|Wlwa~#1=DTmzpxU^7ySEQSF^(P=NqbFX%nX6)WY$k!#sArwL`1w^`Mned>QC zlaMjWSY&DGO9kOWHQ8ys_Q}WcGaYpcVqeHS=j1iI{>zp6UBWyrCEr!lItwwAAvTdE z^TY-DM}vXqC1@r_=x+w9O-Hm@n-2~2C2}f3(nvQyXW`HgEuKbD`zj(#7@uUy?tJ&P zei6#?LeWLeZ7`XA?YV5sZ)x~#sZmwBL6FoeKi&5Sk3Vf?Y)?lvZMyu#Lak^0EEIE5 z#tDj>j8Xlthr;3yzxWAD-)6C&67+r{#Jw)enjG?#SN18Nn3s48qOmMLIhfBlR5OD~ z&xHPhgZ?VJ1o=za2w0~1C(rhGsb6WTz06CxyJ3y3QR>~IU<89;FctYD7JS(&TfOMt zFt;kc9lwX-Lk1o5`2G)hjm-<)Ai1X9^%Bp|q6L932*gzOz-T zU2jy(W7ASUy^R>(8 zwMp|d^zfXrN1z9)1o^7Ns)pvChS-e;>p{e_bfctAqx7``y-Y!)e0!tff3-tNK@}-M zHMC8WR(O-@lP10PraKEwh8InkC%JdC!5})DpN$%VO->4pE;cQ01uYLRnl##*yoQ@^ z5}MpETKqkf9WHW$!ka=DngczW!VBK-I%Uc)yw_F$#F4hjgtw}Y0zgr%njWob!;M&l zM!s-HF`EzY@DI5P3i<6X{A7i&?d=^4?VT6xc;=37g^nBS@S`A?G7K`P|E`$n-2xHg zFf;Ag1=Yj?qZsC6L%_#5LBy;AV(CI){~GcCj~(tQke~ezcF2MUDgFmLgei8OhvP{) z@Mi^hvfH+Jihp=&A^aM?lS;8`o0JCG(e?j@9SSXWv(0GZo0)`l0}LDeBWzKXFdX~h#F8M!1P%<2h!m>c(C3f(a0{v zw?fEx4bfBt+2bfkKn=tj)wzZuUM_@qr(;Qf3Q{DeL&iM6Zr60K`I0>Lg(_mc>EVc0 z6~6k{K<FdJc$V$x!cy9zo{)N_VEUsgizG#f; zX^-PSkga29s4c=C_o>Gh3iX5NvrzEZ@f+6n4m*x7UVxtOQmkI1VPgxBsff-!G#2L9 z4VH-P+N>TI7v}OKP^{r6Abya8U5ebAp|$F9KMop$sIS_Q{D!zsqP5a_QWH`|R?;Yh z?8mVi+|W36%q4Q#O{x1888`~lxfeAc5e2V6!yegwi8%zx;D{>H;iCBIJrq2khNucZ zi@?yJ^2AuK713j+ntVqQ8n^CVvQ0G+{`Z(4+zB1Esi5wOYudD0uo!`RQ;b zFBSg0w!@3H6R)d24i2}jw@BrMG&rcbdMOaw+kK1V^suhW;bFG1>J+1-B3(nZi)+J+G{vh-SDhXo=Qo}Vgt07r9-XOHA`e*tSE1KdJ?52gq-I4{ zmX5^0TN8Ouu(;TA7FL*;WCZL)1|EOfIe{A|HSFxi59CNd)}9QBVTOkZ6VEshI?Cj4 z>Y+}%Bg%D4k>p_UTb;x8k+Pkuj<>e1pDYevQr~;L<(Agz=(&vA`&=(ZKDM+f_;{`A zaH@K5RtY^NuZ-YaT7rIr8rMUkL|{AB#AvYro9lGQH0#PS)?njvH6%)8+lBxmUYu<9 zBvY=1M5jSx47U>~z`E#7u<|I$(u_TTjPnXq+WEtV0Cm6GsbB7NdA#a+>t_qamI5pI ztzzc@%i1(~|4QvAH6@4|`Euap=DryDFo7s<5ze}|vsy6mePPOCkHX_>ecNVtV_}Sq zd@_L?BH@cAUaj6eRwAdmv$sXjFF{xxsv}PZ?C0S3-YXycG3;!#A8fWiIQL$xMR6IR zW-3s`HH$xeyvgz+;AyNg;k9ca!r+*Z8O71*S}|BQZq{H4{#qD(Fa2{BU~HRt*#JX= z2drc*ZLfRGi;Y5A4u0)B9`a*JsvL=5Uyp#D@z`HU05XM3kP_2b-`^Kkf1Dm4>_@F)9F9NKe1-UZd``Az-!WYyG`VcEC;G7iJvyGD zh#-6Zo!B1n!ERd&MT5owXP)eRUszcuJsA`P_Z5B%R6;zr9bYaOD)QQfuCDK;!ySZq zv5~a{n5QRRKF8??i^fLB&sT<)>kjsCB&J`%YM23^y)EHS+tXwtbG9Qr==0M;d=+AV zbm`lg5V6JKwljK&?d^JE@fS-BNpUUVr$Ofc;6ewmV;8k-TL+^w*dg76+6z&b)O8Fg z!umSSmxV^^R7U^Q?0k0kJ6|&W;=1HOdExr*>45tCr>otStNrV% ze+5_k!0SH_*C*KPUD0d4=<6HYaR2|p4PUhPv0%%)Na^97j{iXnbHyDB%dIB13<~9f z_Ba0Dh~eFGIZ<1bTh|Yh%DbhXUGgUXFT}7fjoV}Vrv1VFrE!tfe-J~ag}xiaaNn-u z(eeILXfVziZ#Z{km-J{N zdTE{Hzp)yVrCX%DhEM8#>Oro57Vc>+c`q%T`VhL}Z{JX{jn<~- z5+5R7aj3m^2%K6q*050Kp=o*=zRt(F5|oxNzRdocn?H4|etK|2qBjkjtJ3vyh^{RX?GyU}h z+`|yv&6QPy*>r7)N>;y2$!+yXjR>l;U_&7tO>Ek@;%&~WEqR@;=E-hC<)TN>-q{#R_dp^alPex72C3eZ9E&Y$Ws&7LA4d{XE+4l+Wj3gkDn9Dz9)wh6G|JLKB#9%5 z6dQr_!CBc<(oMum`{_wnWCv-#=d&Kf6G_#35#^CRabt(_C{k4xYM0gHpq!qYCT1SP zm*xx3!j?dYI;|QJIYWJrb}mg=lVq8tL}1+vX1VYElm$^r7S6O09&>MAEBRi0M1?vm zjYFieD@o~KqzszEAb*=t5YYR>K>wbvh@Fa3gv7?p2H$51>pvnw^TLrYzFHcg!9P2LseqbqZ>*5P2d zI`0)vmo!9o69UjeZUqVwqxaG!t!EclgT>}rQzUjryJX+h?;u@n{u}tsu}2CT z^(?=QBhs?T6@mlRCGk*R#iSm(wT`1<)@V(f#cU;KhO|h!nq)BT2RvNy9RD)aqU%jP ziQ+C_H+b-Zmc?gUJgbBJn{$a$sdow=^<4qWT&;YX41nuIbeMJ*Tslrv{kPXVM(HW4 z_x-F-3}674B2UO!DVqNY=Q>@&eppvm;Ojvh0uq(vj7a}JDe2nUNcqj}L(GT-dz~{R zWjRHMK_|6WnjGY9G$S&Lr*Rv?-)JY$1FT|Vt=-Kc>?71& zM2+<^fHrmd`>l5I<*0NYq3Eb+d=KM^X%F)WyN|r74P9-hrqFbp*UK>Mf;u&Wur5-F zv3wL?OkEL8Ln5a8p5rB>Olh=wYY)BZS=TYic$$%KlqF(lox7#6-UrhKYje|PhIXgP z^pD+-luYX4GmV)$PJ0CFffB7_9dcfU-NG}hIEd-C0p2L^%X zRK%__+RWFp;+pS)ixh|(OsA|gw;YeY*^JROp>0S_B->JhaUsTc9iL6S;n|3b2DvOh zPc@Q%$ML|&6Wt>$8tZW0_wkBaOg_O0r-Z*zW$ zxOCI8K~MQ$o59GWU34#Q48(v+KuN^A8EA%0$KC-O`)dGgKLw?h!06sE4{Ahtnj{K+ z!C#9L$-y|32+4uA$6>iH%XoRFyYE3Ks8~&;p?g58q}?>@C>%uW);rVEHdPOP<>lq| zq%THo8%LQ3t257ybB7oUFyKL2#2mJ7993DhG_gAQfhjx;?`Vw!k0Jif>zQ=4Iqdu& zrvw{N1@uj*$|RFG9#ZN-A7YZRy0az!tIoNR zi=uxn0-GnY?N8x6iF7&)fgoC&W&dqNb3f=BJ!}ipos#$E zzPAn^RAPWpwu~mtP2FxtVQAgBG)HIZrn&b!8Og`C*pbcU7EMqO^Y0L@u#}yL#60VoqFA|gfU1^2A(ww_% zV(`UHSONPKB=05VpF2A{Bw?tZ!jg0ih3*>dCXo7s{+i9upUxLUcA&d3?jvbWb8Nue z6ox0{!^j>pe|W-Y1XZH2xB3_A9+EHn>HPT>obF6iE;QfblZqB>D{vHKBW~w$*Sf?U zy2qFq)-OCeXngeN6meU^uPfs&qc%j|Jl?Sz4oXXo)Q|u3^;-P0Iv30T|B%Imsva z41%Z}@y~u`sI_&;^PxYMD#W6ith#fRkgUXkXpOcgc$}K@oWLJB+_fMeA-Iwc!~|jG zR}Qhk=|siS17a+Gyg=d6vcBjzUnuEd6fYkueOn8VB~E7$q@vG4dWhQ)?~0Fx3812r zp7%(=F)fH#ev{R8bhv@6*SX6!V+6S-% zS?|$=io-um$ByKt3o<|^+;%ngnQk;6CUz$v(HE12g6EyD#-e0PhDeC?Lg~re=;jeb zMalj4c|w%!05UO$mWGzn1l4za5yvcmWLjAUy;TK4)4L+@uTndUe9}^IXnm>r;e)J`v?ksqKpMsM= zU}!(pB=u*uJr(<+z*K`LOYZyE?(?X%HxsLr=tiXZ{7x~*pq<5FT*x2}KMWrmzIXzI z)x?eiKSY;(DTqp->`vz!6`S~Cu(UWbLiqIcQ04tygX_ium~ANin~0bsGQPQ{WDCB+ z@1r0cg29hM!yPV?$;_1IYQw!n!~I>ugI&@UNeV(a3G&SFx1!OXJ4VO5DouxMOnp z1#&Wlcw>dV31I_bC8e}iI`qmxCg{xxji<&^c9Tj{liFSrr(qN5zKl#f0818Ss?uky zsx+aKH7Oi4ei&y=Z2%Vtnlyq=++j5_H82xWrAHuu7Wd5vkV&=LDXWpG^+Qv;y(#m( zDWl6N1v^u3DsxAJNkuy|$9ROQ*|eb4H19_^r`zrleSsY zExM+6y}q^ZPfd^+vDjJcV@-`~eJyt4Ea(}>=kFQk@>v9rSVT5+JX*3y)1eR8ETfA| zT069eRkDl|em@JhjAgP+l$ZI$h1mD5c6%!@cZ(kj2!s=$t!G?&8Iz-kRMQ*dd8!;;VAd{bDLtQcP< zWzku`va^28nw(pk@o@rFHd3>l)3OghA`NJ?poZ*7f8z?^tabgcshhj#hY) zK1rW%q)TpyTzGp7Z!NNEtF>wWXwxw@-?I0$DaiQstWEx)O_$liQ>1N=l5MZSVjFbv za(Cg0m{q?NaUax%ITQ<$2E;tsgV#erw=f_n{NfP#QtzIv6gsA!4x~!}c1!_vLxCuO zUH8+)vpdOUtVYFl@RqEl?q+Lxgk5%h^tIGB)TTA&%VtvjQ*ekSY%QLc@hsMT6f%3f zG;(aWL6^9BY|V?$G_3@*XGI@i;(tE1TQV~mu(K&)br`9|S~G;knkB{6J+;p{1D@1E zYJ#E(g{!h`;r%Qv=4!iilC1eY{ z`W4Xd5Q;tDv5=zL(Hq&L1n$Q`!g0K#rTwia z;IBUTfq}i0Z>)tAAscaj<~}i4+9{6^Eu8M0mt>EWb-9IK%c)$}z<};i5lJ|b-jYoZ z)`{bq1dUW`*r$f{l3jy-@1nQ6u=6*ck|)PBp2yJs zOVQRwbF=`grlBt7JoLdBSES`y z!Rv0Pv$?2!j|{PApa}A!cm_8f_+8+-edP*gy)JWBm8tA zF7)IE1fYFCND1-OG%A`)2jucF(b4|C&}@t_CT0k*#Zb8{hmRSJzJKHy=MGP7o(2v& z`BV)qUvrKnXjm>IbwJ!vEY5C6Txbw-(8mi6(H#Wqpuk9gzY5y*&KQKp0wkyv!=nvC zA-+2!{INoVv7X8|i7Bqxl>o-1my-7PQ3soYG=F5NiFDIrXdXVSAn})B0INnhNU(he zeP6iSY^R(J53)aw3k5=a5_Ic?ej@NJS5gtSB$Ud&YjEiM9>5q=%9aTIiUB-b0n9 zCJ;hEP(XS!^p128(G+?S0qKH$?$h*00mqq^+-(mhs-2U8@v|qN7)PhWsO)hYT57Bm%Y#4 zKjS`Y2gphQ9y*(u3^>#j;eZFt-CNzbxZ^#v$)II!oZrp}K_yPMq+1{TQQpL(u$>WD z{$uX`k2YlTq4m#cU4Aq4K)LLCeAIeDaF$9^;9(VrQNL)9A@$Q8o|u;KTik=*PucEY zWsUbeBzO|;TuNFp+}lpfa+zBdcl&w$Qj}5IduG;KSEV<1leV*se_P);mu3(BrxoOy znWB(Q`~0St3e04D4v8wc`=VI6>GGvN?lgdKAtg1P+s^W^fYAJ z>Mv#dEH07P@&cryVv9Nl98(G*?qu7X^dZe|?FX`c`x`;H#~>a&8INa^`-6FJ)TPWJ zw*6U<=e3_Sj&Zw#e|8;ycjdZraL^Df0&((*Xln0y$(B= zFLn6;OAL!OLU$EL|F6VwS8=RDH~2y)6q*QP9g1LbGyyM0d)DWAWYtB8!(0*TQpb@p;soZ1wS0whUIzH1j+-l*+ zjK#HZ<(6R+zn?Ckgo>)ar*b%nahc__@eZng_IB5&?w;8{`me!UXLs|Z$nSINTjhrs z5UFGgQ=*%Yp>nE12O=@1?@x9P-!r#8BD(%)fi>sa>0V>O1gm-IZj-N z!iDj(H&TwtIxMB|E~KcpbbstozblQ{D4=l`z*PIg-%~W&N0c^z63_8pH#=Su!082# z-Cnz7Rj2M@c64QZrzMLviM0!lIP?55pv)7cVLj@1T-YvL?XW^4%Cg6 zCUw6()hFaGZRzI_Plav*2QrT{;{#bv??(MJJ ztsG(6v&p+BJkJ}9h2j?(R#2nylCLW`s$sLB?iB@9`0ZGZEv;o zb{Z(ff9&6XKTY-v5uv>p3jx3AG=|xGWt4-12fUBDz~(t|Cq@>PDpK^>7EcMg{XAA? zgJwc}TtG+1jm7bR((_erYGoInWn1aG4)44lJgkQh0 z|C1Qj51+Ykgma=Tv#DQk5SDo&)fajC@MUGkwp^D-ICRGxM_wgJ^3y~e>(RKSlx|yo zkl8!QypaCt>641i7Vuc^(ZDq>c*YTHcjs@y=RK7?J(#c2nAt=r<`R!IIFClM8b2;b$z{CdfGLcP(6Nu+BwS5Ve>NQFemO1}S2%rcsI z^!pIfe2itb)oRIKNHET5*T2H0iIy2zo4+WVbW%V#ubV3_!w$=Y%U*J0LOiJHW->|& zq7ahRG$T{2pXVy+KeDtN&&z0%AFpaMu=ME4lwv0vXf)1L^wQ;%w+E|^s{naNr*7xG zU^Of6yJz9dxROcKcnC!$%|w{ zlFI0mx>qOrVMDatrX-Q;$E)1R&|dCgD$muzrN%X^rek0-(^yn0oC($FDNalUf}=F~ zOcuBdTbb+E`2T`o$$7$Eqhj)#Y%nxgZEo%3?sdoCx21(f7e5%Lw`L|-8x3R91`_*k z?m57)HdIG<@Nx@=R=aWN(I@2mUYWv2$jITzXrPQJ@s@-T8C8tAa>jlchPB(0>wk?3 zo&Nb)J`|>8gqpe7`LjkP1_IrnQY&ot6sG3DFz~w~Xn4A8jB~gJdjcv9&gxMLYS@qa zD>79y_N`w(azn3)lOOC>-&2)M6cmlin+@5MxIh4+qF6NW5z3%J$7sGn@eWY23wy0L zR*Xc&2kbS;vlV~rK=r)}D5P45sePK36mVIa-7RX)DE%_C)0$4;}>W5rg*mj<+-(;DkzZkxNipW@WSX_6$@2+lQTRw?wN3DEartJ zVy;j~*W}gz$Y_20Oad5)BqdsDKx1HtXIIqd=cU;7>C;D_l%;HHViX0<%ey zF29PRL;)L8|7D6LvNMTX&Ss_506hKp;%;*_ujOeV-yr77{;2q4cxCy;Y|kf=0`aw2 zxk0w*935s>f;9>~eeU&JIhsttgT+;qV*+!Q++B@o?veyHODvu4dO_rL_RoJOpG0A9~I86E1Es7p_7#1i=uC~~boNIO{QxD*A>;}=gY3!ZzV3Tyl`EHAY zGyfl;lowrs1R6e1Dm_ckoHo~J;2=Zh?uJ&h3cc1+aAgO8GZketlR~tS@TVnRd?W^m@p({|x5I z6q%$_Uh&ph8P-c8#cF6QtF=gioZR=^nJYMEt|`!`GuO+P%rIq@KZaYt48c3Rj1};HR74i*#e^NBCLkmz|*U(9o^r4MNzqno@oOHVshzr`rPj zkD%EE+W#^l2 zjJKd&EFu@Ik*WGt1N!!xU|YYx%evD=l{|juqh+KF``rxy#`X-m{MV3XI)q17$q>9e z;$?wiDMQE9>IlilYN6M^p zhs}lHrHAIE@IheO#Q@g~sd3eM>(zI9v>?8--fVl{E2uh*;X*^i(rFZhqn}*wVF;it zS6iWpB5uBt!X8Y>yThV@lYhLtq-L}3NvcM(kD?oV4H42G`*U+hd9p!_Lra>4^*KIE2)4T zZQdO6{wF6ke0>PQ5HvDZHtLn#ctIjBFe>&>sH|6Xk;;aQ-G$T} z{n${eBUn$1&Ij>Th?3`t_TK6H2Cnvsfm zNiJ?M;sem+6GgOd@;^t7pqj(>41^iAK5;Q-pv<)2Ph^q5J~vJKtlJ46Kd5buQ6W<^ zMZCVO->2XOs?^eHmmj4@+apr9|?VY zcwaI$ff0cc@5>Aj4!AY=p09BiM$ihP=)WIS60vaT)AIry*0<23T394od*s{agjwMz z_GjX)EcRZM#@m>;77F0gZ%l`z(r5iGXLt+QUUt6xd-RVS;tX+4gbO$%3iwc?uH?lN zdY(a~amA4(91PeTjlX%g-QuXOM%qO6^XKf>I{hXZ%vTE>;prPzPV)yIQ27ckR77}{ zd*q?6JJ)MU;G15D8aPWUV#}&mWvP*-C4I8VuO@?*s&c`}^Y!F8bHu?G+&6&C;vGMy z$~U{3Yc&Tfp3_0glZ>ZN9i(${!-w!8cg~sicyU@Q!b((2TBgO4(I?wXpEP`fPIr^e z4qPww^$a5j7HE7CrZg@05Ag*U2nBr6J*DrImT%CfCt*Pj>AUoWM^Gl$uc`MtkRhDU zq224dOtKfQwhdwyqmqfy)j{W5`%d1YUtQzSGC+#)?obj#Y8a}&D7kU;%Bj*mc{WX3 zBwZ}HhA6b*AxdEQ1(ZbO;O4{9TQ7Q?m|iy_nG0cFr-r?f2XlD6c=#kZ)xPPv8s;c3 z`qfh6GSx%WjZpoH!40&reLv50#rN-hHeYIG#3GkfkdALA%*^NUCAA8H<;cyRyt4#R z*8Yy7A6q=SRFE|@##KMX7)J z{9L}l@UHX_4Eo3aG(&@uy(!Iq3aRU0s_!QE`nbavcQWY;0}xC3_Jx{5>a1x>({XF; zPjB72X5A@3UR0`8q;74ISE!Bs zuEOtNW^-i!t#-|+bUTuh1y6wL!$Ijcx_DTJ+4K6pN8GOdYSNI;#wkAvY{7k zy9FX&k9HVb+BAH$gKA4t3)wZG#SyS~^{=!)VRRT@(=)lD_peY_c9vvtThDB$!|dh$ z*YmAk^`A|fPIVmptat3^SDLDo9`Rm>)m+=Lr)k~?tin!R|9DW*YW%Prb zU5}eIj9C9J&-?9UT<2MJgvIlUd}q+J#?dn}gPiVC%MC;FD($DXo> zb;}N7t|O8U8foY|#9JPHM5h@Z5x97xv+>>U{94sS6pMhu6Pp1ak{&!bHk7DN?5KS3 zvhm+*1E)0epi$Y6bKwj6vjkXgFB671ywFIq1_Joen*QKUS%1Di_@825+q1H{Tslz! z!z0|BX$MM7B1Mg;wx6^B9W}NhQBOtopYZq@FAU^O=fa=(Sp)F76ycv3zn{+%C zx@g^)x=f2TG90BA06i&ly>R_M))0=M=vPA;u$COMA|K|QtaIeyr??*Z$q3gYGx=$H z5@;Q~g<&UX-7QF9m|pYgEPFL67Rq<1IKKtgRj*Rr;z9DmSP%7&9x{1UujePc7odQ& z(0tTu+@r`sQg^&(bhxV>VfC{HA0}f+qYrwj)<~NCwKo-UXy9AH;C=887GOrSn4oFt zlRN!2$CwJE=CBLYv-yc8ECzo%#%#3Cin5@`Cw(@GbQlca&HiT~0`R7b z{__qzQL*~+X1Is294!{t(%1U3l7_b{_5*=vl%}2}0JsOQ(b%n*jH)FjB&8BQrstkS zDReIuO^y#^OwHwNWfg)gDduU1oJGy%ww;U6NB{8X?On{x5K-2cencN&sf$J}^1l9n z46>_5yKqG-cSN#|^S-*L1Nfveic$Ych;(hS<887MD*jlQvmfr(=08$auG9<^q20c( z)LVP*Kjir@;?dNuv!Bt1sS+`M19@V3(zCX&iJ@c7-BaJpVFR9o0IL36ZijNw9iL&; z#nzezO^tskl|lKiOA4ML{`0s-R@-D@3)^V*g+!rv$16(h#dCK|%oSCnL}z;W#}3sH zobURK)~E~7kcsM({i{|Aycv+nWm?nadQ(|a`1*E14emz}L|8QEMK0p9->WU`#6(RZ zg~%{2pWyLKP_D#R> z8i2z)o0x?0aWxG-%|(uIQb2>lesiMX2aM=ox=isf?xLCSh(c*V9zN|CEoJg9yFq4* zsd(p+@H35jqM=p!PO_4$R>+K=Vr*Pc`g#0QHnY%XXgZAEK$;Bk{nm9P-DIX#f1co>nMF1y?o54t!hjwL z!^)lGV=B8kCZCbDG-8g^h(+u+X4WZ07_16Mp+jmU?+D+NwKd!TUsT}Zb9vQ~XpJpM zpTUw;+oMNTj*)yYlxq1+9S1tk}-=M zC|u%^(OUZpBohHuK4Gl5Zoq#mzu zCgWp(O5A0B_~@{b7M-Jt2@#hcH3To18g1JE`?o1tHOCQa8?J>Y#AS3XceI8aK{$oda<0lg#TdWBnx; z_GS$C?7<2vEPE!TSlmj@}XPyZQs4HAICi!5t)OOcGb8?Wrs%*NzfyHwx;@e%g z#J*?QzqtmNhDfWkwuL^l?#@26_E=M@s@LofzwO7IJ3E_kkNRut&8qwOnY1n1?4&m@z=*)`bLdj)4NxeT_%jDlL%$@U$Y&ag1B^4A7t~9q+ z4+&C^gZdz`Zbd-E59#krGU51q8K{01)uL;HX6^l(}u1;DHi z?FSLfp)w&kj8kD@B6^ae`s(J1AyM`kM?dsVK@TRXR1#rfAxPbzvrKgAzPHsm6yKd2 zI()RI2RyK|;|;yf%?q?wYb6>@hVO<)l=&T*k{xl2Z%?YdS6#Fwjp0@43rzj5Q$NEP z7jsV31@$xXLO0};{YT>c7U2Z61h)9`=i$(O<4bv+3lX)}Tkpb=VP<_8P6#=0vB+$8 zo~v!e8V>YY?=k)0_0-A=A$irc{cl6vI?0^&x@!rG;Fnks6CWmsZL;PR%a`<~s!G*e z?2q~>8xYzg`ejM2;gH0B!UtC{Z~o|=i)Je~ZGp1eJfK@FmM^ShN+)r1vF{CKefl4)H}coU~&{ zQozjLb&P>_dC+1Q_NwZ>;|ZDzbJbx1`_+pO;MY2FOY5&;-To>b>Bwy7g7!C$#f%+Gh(Q53&$d!Y)6UJ;)?yLPFA&U=A`2!_N zAk>!eBf`Ov-r6E>V)?fu=c_PNRCvvCe7ljl0%Z4Lm;;b7Uy00R2_G!HA49vfi4DzA zU%*N#XnzXHxJTRRb8NH(ck&!bQQ!muTUf6;KElV8T6=PYDG0!lGMDe9sS1+zbXXL4n37KcH)@&huy&=s;U#Zav zjiOI7E7^PTEx(N3Lo!*it8Mb}^@oW5sDV8@zCk{xQtozs!wU1WNnDZ6U#qcL`4>w{}!pt`{c$7Og9N+sZ4^- zhzH%^l*8}~b0?JE+8=-Q)O1{*dB}wcV=bycE0E8LDDLDd3U4m%0)kHM>N@nv7II$U zW0nJGI~bcdl_;Q+;d9d`jj{oN+El_$7gMzLtLD^KjXOJhKh=JIv|XL<=<4UlR1gIa z=91eXhWY;d4RnR?!bV2WJb@`p$~yEuh8N$su@g-JPRiC{;U2c(J@xP>gE$i9uT;BE z<)H3F2hQxvrqN|}H3vRj!A$#plNNc?eLRgdYSd|PW(tGLSCp$mgk2V$s5@%w=Mf*G zu1%1(>^d7T8mS5tKLz*B< z*vi#YwnbpgaNz1>ujY``gP!G|Oor~x)QO#b%nu8>TAb0ZSiLgX+34V;MeH$ODvdDP zK=I17Y;RM*LRNN%?nvy4fEsiWy>3m`%4lcdAwLgprYMP;hrSLDA~qF{ke%Cb^Q7Id zuPzOR8nN*-%-tLhE^po$^h~gbA>A%F10>}u>y&O`vMhurAe=a(UYFG+v{e5#>J0da z+haUX=9sRci0V4y1z+)hC5M%20Kl*dyt?rI(=kdLUTOZGw<2zBe1N)x~y@Z zzYJ8!%Unc_r{CwDc0ib~09j0+RyO(uuMI$AyTm8s-Dx?cH*{s)C!N7`;stHpj}5=-tVF0(x&Is+1Jj`D{WoKxV%D|QXzav&biHh0Ej*Eq_{B}>RsOShiErg2H7#;ZpJLJNFJ;zY_}Cx( zXg%F2R4`&BH5cPAf;-9*KBG@JZS4i-v(K?_U0jMQLdKB1Z|)=Dg}%SN>!vCTP-bi^nXg|ZiwU2}U@Mq9&0ywzL% zCH|myT&f=s($BHWxpetH51dXdX4RbliP{UTNW8}wB2@`KT84fFj84v_^lfMH`tNlo z5Ts0+NgfrlpTb*i%e<0lUDG?VXjno+u84gcDd%He$;F`SG1dKbu2DSL4e0SJ%~$JK z$%<&~C>EE(>qob)&?3~ZFr_8FLQD)~Of|bMbdxl^#m+Y~u+HJN^}rDoD_GNh+7dc1 z`NkmeiUr5gn8m1R3T*rdj^RU9Ugu=Mn!x1LkEf74n)a-k; zR#-1sqIja@$X)x0m&^!x_s-6X6sU{N+@yw)dkn!?OaE-JQ&x%PaV6Tf8=cQDyQ*nS z6NN5_Tn;`Pq1@e}Hm{*oSypdXl4KnF#CO!ZOKXNPe^AnT$z9{0xYr%T|Ez^H4n(q@ z;JLrGVr>4S@@{3vx4I)S-5T+d|I-$JTIno7xb<~cmbz;$KdU~_7QUXZxeKnDhjhNF zy!vVW>SxK$g|D7d?tMG+*Y*#zg$vdZ?svN?H6FRMy5W*7%g6uNNZKvp98VQ7>0Igd{xx4uGro0P$^_d_LbXzwi0d^tnzN8+1K)UR9rgH-pF@q^7){G+GYH@~imy5*G&EI+OXTFZ2f+r-ulDXI2&XfmA!n1r{9VVX)+-!=N- zyOGB_vo#|Vg+*{u%meZSEBf?0caH#Wm>s=pswgk)IQ~(=+>@p}`ukwnFJ12}*+1!J zl5|TJk1%jMcjNpfs?tEcD(GnZcE zmMItBax(gbVj>dyZ3hz)Ra8ZPiU39Sy6XOG{cyEFjns&GsU-?bD)XSHHoiEO>!f1H zJxu0o>gs0;tkIwe4G4)CY_1a@==XR1jBVD5n(04m4K9$XFYiaJu*uwimp45Raoriysbl_GF=X;z=XwwJ#5Sl6`EQ}@%*U{dvv z;HSZ5Ajt6HLifR@Gb8?>xlhf1U7~Z(?MC9Fvkfp%YOrQ>L;>%|o)StE6zN#>S_Ti^ z{o}#?qtUA;VGv{bU}Yuw-^b50a24$L&v93#?W@vcaILa*4WJNnxcN2wl~w3)7DB2} zSxyc}3%%o}K>*!ir*^V9m;ByzY``!3Vmph~nI&MmR)~ExZ*2Z_B^nFAq|WUMk7(^& z;+V$cP45tRL&cGce8M6De@9i*CW8}BKLET6hTnM|wdyMW=*77mcI`?Ra^uXb3`Yof zLk1q5oQC05d)AgdiwsfqA0Z;YCBOdrap5h^98BPD5pT%K`Ag0bt@dXoWD9)J`6mPo zpzvgZ;ECENR02XL4NPHUF6dUG zAWPW)V%RZ>7kW(v@x~PFjft;%WwNVWi0H#@KyMA30p^!7%f{FCW(Y_lJE;sze~zfS zODaRBo}9&pjr{}HZ5S?6I9^3F%hA0)T8bPpcxE`RXv?^>PiODwN6(i^cr|v1TfHAB z3a#?npc~wI#V>IYs`l8pb*Wn1%KZW+l3~ZO=a?F4O7#QCL0qLXuIU1eKPv0=yIA=)Ua=s+y#~5;|l@- zNWB@OK#>zbNf1cjZMWV`$N`_(tSfzAH@zojsK< zy3HE!r!NhxAx*)+vtB;n+Uql3XB71-U^Ve8@Iyqxmqoves!=josf;ne^cHB zhmKy%ss&>r8JM=pcfk(G#RAXZS>eMVz1fyiObnG`GKk zzC*XXq7$)poknbk-%-t;@yUz4zYun%)>QNYf6;!1c-8dQ{r6Y%qI#rrDRnu(dvW|I zU7pZb-$!(?Ebl9D^tbna%vs`#g{6W$^(sR?Tnr5?VbA3p5aU?W)o8n=fg4L8# zp%>6@Mwj?erC8R&3)hKI46UZ8C2a2mww;r+ zHNN_s8i;yO{bFY9(}0py>Dt(_c%TiJQNHrY#Sxu!t0!0cMe@73ME>muD^a8uz5*2_MpzndA2r{%d`0Ml&2wth*Rr z5bAkzid+w}tT!bthe(Mjtm4i0J{3)(GX#9MT%%6(wTH%VL5q)+)22sTN@gcsoz|S zfcP=^DGIS7RbFI#K({nsOg2fMcYT`&@WDLF zZE?Zs9nzcWbhT`w0TIh}%q3p}<0FQ&KlkXJNc2H}?{G00MY(>s>#=%F_;D(6Gkd6y z5h{2x9A;W#D0k$@mUjc2E|Kb3U}}Hd-?-z{)gKBLp5SHJWnzVSw#$>}+1na2(%CXP zbO;mvu3#j3h_!g*kxc>3sHh3?sfaIPN!2cgv2<|51t;Pfyg}Pw?Q#DZN4ViOu z1SS0$0)ynJKZ3D@4q~30M)SBw$@>z?LQj9y7E`SI2;!;2m@_@^WI*2ngx>PLOqRZ=x*(YR}WG**l%zT}5Tr%66%Ly7%DC47%qK#NIhGMxvk%u_GxL5o;&1ZMW+ z8*yY;DCrq$Tu71}T+&hkApL6}qh{9A3p~kAlg*``2;KgFnc0q^O=5F0A@{QNmz|6@ zfkuet^Z zb|eA1+_mFEX$mDMW%UCt(|poPFX z+>?~Hw96}41iFZB72UKh@E&Mz{^nPgDu!AsmR~bk*iEAlaJ$`w zFDAkw?2Ocu?^dL15k&n=g(O&}l_L;QSZRuh11fcO!q3s3QIB2YU)oSw1*){JA5mVh z$lo~Cv$)mLJ;u4XAB6fQIlnVc$Xtdg?67!gJJwc3JYdBQtX&n4xwDrzK1oCVv6+2u zvQsVe`;Vj~>4OBWEE*uwv~0YUJs?@u$`myN2Y z_$fYoA#M2?dbN;9ry%mVS8O*&4ZF4Q&M@sq=;ZgzZi_RxldEaEiH&741#D|1NX*9#*`Cn4w&SoEjcnUDFS z>UHBl>D&97G9_$%zPiFut8?xn^fIh}&-#+n?O!zqw0?R^-qL1N(yPvv?`d5T!YkRL z-ngZE&Z)B3(jqK%rg-kRigk)%e z_5cw%)Ak~Gt@q+~{Oxl~n`CjLc0ACeqF+o(LXfx-`8n=R+TE_u2T%7evSKd32F{=7 zGy@8D($!O!`K`!k+t#f@qa=*xvj^P=>I-GfE6XyUjgV;@cNijGGwVOPMot#&mWaei zpL0ntJ>eTs`s~pRP&tVsc=T)ar_^;b+UM?!|izxY=0QZlc5(uRWIxs^kgqB2y;QkHw8DmL9T zVOI&PNQ+@krE0Mm($1p5RU}(?OkvqtyI*-V#Nxw}5KN94=*WvexiLe-v4q_i<{h6wJ)MJe4juAYBNGzvnZ`5Dr54Q4kU0V78+EEiuvC} zx60oqIVn>qXBIJqUwEWM`U@tuWh5Q{_m)_b~<-CS5eI4BgS zbmp@zpM!lMUzyTyG_*p=&)+TRbRlej3UQqxGaQt|vJFmQc$p!LBpsV8^lV;^t!jx( zFbYhx2OXm)W;%j}f@lX?s0);t1N;_Dz@Y?4)Wc1=rpjr>Q_0D}X}9O%DboV8(ff#3 zT&-=qfT<8jhX1HS{VcMpu#H1o+pLXdtS-< ztT`4LX0;t4JkGEw7=Q3YhD3*IC>eFb36f0DSXV&ZWgqVEITRU( z+O)`t^N)cqU)sh?DDd##wTE7(=L!hvjAb9MXa$;%7bLPE*D=VqR7jBlyl4l)7f(?i zch?GpevCgt;bF8l6>rYuikhckI5hRp_)V0LUK?`xI%13KU}kSAw}u1yk~^rDCdE46 zuY+i1EIwi_XaGldFG}U60V`{fNhrgHRsdQ=vqu*Z$qd7{(?L4>hG#ofOJWb*VpA(n z28E>3&p$&Vck~7OO6@~XTolyxom~7kt?tXY{6$Ay_2`B>{E<|E9|{5OB76@*^-=-$ z_61-agoG6}cLI4k05qwG=(>-jb24eVBbB_f#Yev7_KD}!@W!tb5HB&vWtPD5&dK@K zJZ-9pjF_l}18RRo{Ld~Lq$dRoks4XY%XIP+$06_M6#LE9pIewe=v2g@6bEmjG6E%x z;{jb*RZN4NwK-~tCjeru{9zSEuagM;0=i|--&P1!+0p&mbo3iXWdzTsN25yjsv0VR zrP5I;kO{;U(V(iBV~~F5242?wk4p5H;zL500abBZ{*$}_C!=VbPWjnT zOI-aUuWAm<|Cbji_vGcYxPZ|({$B^Pmit;dB2=vo=+ zm=POMAHD)f?Fhyx{&Uo9f!YSBHDz+Dke{gY@V|Y%5NeH}n_*o$=n4_ZV5fv#P2ETqIa)!ozKitJfBAJ z-Ar~?jXrVc{sH_0OB;u|vui#q7>saSqB7j74xU@Ivog;$+O*%HJrVAl%b7L!<+d{o zr5Dl?P?4(utz?QO3lOyCIfda5bUt7wVMH3$J)FTSfxj3GajV}spLP6zI%!)LuKInr z>ie^pjp#gq(Js&zA05o;5hY&Bjs0}%gUcs4$f#-mcijjIJ(WD{kdhp1*qAav@E0Ek zIJhRknYCQQ&PykORBoAphv( zTMiIy>$vX-Hf2GI@yQ?AurDsx#A-7?p?Giig7d|Kl?lNq48Ag>T$Ko_Lo`s5CuH)g zZ(UR9NUw_8;L}hui=Wa7m`}-Jsj+|!Z+OSOf^OmS=PTxCasd-lyH758aJ;rqVX*2+Mmg_U!TIv!~UV?#;o60%HRaV?+64 zFznb$apTD5*h_)uWsk<*?G8?iJsl>TU(URVb$IqWUBD?H6O}bM)7&^^OEZ3D`(jcN z(KROk7!!V0SeqP{n}1Mu{lQzpROsmnD%MyyML>Rd=D{HsaBDoKbfWJ=bMyN@7TCP; zzfQP&D)uwu&!K>ql0^J#$HJgbczCvO3mz0tN{2<;gQW{4 zD{~$@aU;ba!Z#j(UENV@t#GvcFNR#$l~1zfmn(% z%r01W$~Xq^-RK{viNk#5<)Xql!_*{|Q|cy~__k zQUsWmJ4)CMku*P7egK7I2kApNo3a8IJW*FCRGoVGHOJ2!Tb{OhSk7l&4*xI@=$U{1 zXvt6%30h0TkN~$j z!B1xBMWD+2{Vcgt1}75%7cMpdkq-wP+#>#lT%v}M39#ZEzSzeDA+A~Cg@B_x!T7Xd z90Lh8btr6-{Q;T;0|I#Yb3&Y+(CnXZt=u~Q5(;Pu)fj-j+6>Y?A_T_Tp@H!6&XiOzZ9OY|3&`&O8(__ zvF?@S>0yr>`LYYOP2z=@T*XdslVS4sg6sjduPUXpp`bCqb8D~QMjEfUJxJ^(BDm-^gz*l$C!=#isuo>@ z#uuaA_r;~UL4hcE45GM#`*Fpy7~;@c{BIRMx4QA?(_sZwDiWn!r1uDQ9_k(aY8`8iC5@*+UQG|kqGUlDnsdW%)$T`6F6RM%Tq-S&9d9*25` zuBw|+K5>5BI_&z)sX3XpGZ&sWJf%Ym6a>`qORuG&$50jGTxjeMu?U^TC&YKq33`qB zH6CH-Y?q}Hht4YrN>@|`aC9bAs2X;@63Rg@9NBD_*zB*~H5XmDmTEFCb-gJLOmifP z3HqRHznKKQc{SgDL}T2>OK1j!4ervpy{gqRY>c|r3c$UqdtrSXjj9pHD<4ug@(ByA zZQEaIDiUzMt+e`8=xv_eP@vSdyENj|&Sr4y<_`Rx5JG%M?0)NQb-f^=w~OJi?_N8} zbd5t@-v1xM&MT~`F8b3+NJ3~a^p2tTUZrU09YSxRcSS^+s6c259qB~@0Ra&KK@b4} zL+`yvmrkf6BBFu}-+!KYX71+hT%D_P_TFpl-+EuK_bhev!i$YG;F&rpi9;=H^i|o_ z{0X6OAbMy}qWN?3HwAgY1u$nljUIgqlE*fHz;w46#4SGWD~invh32YerX(MXGAAl_ z8hkr7UOH-^d*w=l!eyy|RCh_5bb7v%+n{9y$3a&%dlYMh%pd7TL#*a>Q!7L(9Ma$! zQWWP89|x{Z_dH;H;)uxcE_{VupXM|}v{lMha^as(!tGlor_}yrI))01KR<9(FIuJy zxJRjcoN*^jyl?z>k25!*W1}})SlkWZpL124)uB(uemjQAWL+bHZU|Qg9CmI%IxIEQ zeD5p%$Yr>c267hQ{4c#4MwuruUk)#%Y5dz=yryo-ZQf${Mao?B(I&P6mIs}vNR1tj z5-|Bv4i<@Tj2iZv9x!2r%h9ISr}GG!#2#olr%KHhw5ae@@HOB%4K*8m*?VV5s{7+< z8AOg%zH{32l+gzqWiq88VhuDFi+#W*?9boOWtr#&bjA)=WC=IEx|Mn0HCbl(@_OFo z=iS+A`_FiGyEC7KvPK=-JFZz9XxrW|%AyNbOtCK1B2~CYzcXTm| zW`KSCu0Jt@itA~A79F`8Kk7H1lu&%!I9XTB$8Ecg#3H6d0ks?0U>8r?8?8cvUhi#`Q z(F75VxYcvxE8;Fz6Uvl{Jf*XcqSkKZ(*yQ0@i^&-bGnB9=rqxPE>q8LAX7^tp!Ot? zH~ON{+cg%iKy!~J8}mnJCW}s0g7eBs!cV>0yOc~#q=<)yyo&y&9zK(jnCtP}|7?yk z!`tT;Fu@dgSDPBa;@w9uR6vXr1WLuEiPUxn>f}1T(8OcO8T}u^^5w(`>zqM2&0ccG z!L}j(fO-YXk_U^l+SN2>T!}oqT<-^=?3_YPBAPA!ec2Q~bAAK0=bKHg&+b5PZ6+)P zk{V@PK9_Eq)nRCM&vE>BZXAafB;uGt1GwHC(*2}@GPUMvWiUAb;AXL0m(@|+DB1dD zmN_D~v@_Pec{Tp_xiwd`Sh~ww$lF6}HB|12lEjj4LI}$-x|FxxnT6GFtG-9bBZj_qn;;K4A z414|G`2Zc>{;;f}JWUX2Ktc>^HPj@SVi@8GF!u`?8j-4y^MhIW<}rNRwz=hZHnP5 zM{^;0DCzyxH5q&2wBxS1NeAdo1}0T3l@8CKuOIb-u;X3`RJo{CnB5K+>t(ats#fIPcOV zDj{BweoEHK(^t*|?`_FmjBpNTeg=C;OuZg3JS)$5N#`Mz)okGL+&gE)oc7iNwg{-A zoFThr4TkPP41I&AUi1}n`6hT9oN)elv7_OsIMZw-Wk|w&KbPm>b$?03I-}rM_s%sv zz$lYFz&&`-69rL3Uq!tSUXk(cTbIDEw4+!9xpA~7Lyb{(vpqL zid#yGrs>(!rTm)SdWOFzT=1FL5+R(ofxDvF^I4h9g(e<-`CZf5+Trp$kh^G{qIn6q z`RnzK-MgW-=H+rTZ;Www&F=(HXYg9cu4Ue}{Lo@i6Fl>_5m@o!JdgElIrOcg<~`e) z7R$!+%*u@)p2l4ZmMyb0HII6PWxkTXeqX3{jdnyiK$NUI8D?ua7lrvZu$9xz9J6)L za6WFlpPtue`&3@V2X9nE*@-AYSS2CtfSaSuYbgcpB$1ao~X?SH!S$?@OW zuezT>HJD2!ClF&uEub*tp3prfsC;gzLXd>Io( zFTM1vT0W+UQKgBtc^geJV5gk_1-#Z&*&7XK2`%OesQZc+;%wTD8rv-O__ico6GcVR za9jMkgJ9I+S5obe=ck7$f_okWAES`&Z!LcDR!i%;&=8G}p$}6YExB{m5`MiG@q3no znMT~Zh85b z!|xUU@~-jNx8a_J9{}}b?4H%LKa;XY0acIM_UV2-nG=Nv*X6LUxye6W_?~>WRfIWw za7Siw?e?RGLj^~V-Zd_NZ-3;mU+@ik_2Dbc_*}M`1w!&D~=kBXV`%zR`l`wmwy8d zAH$B4lb$aB3h!(E6?SYx8M?-Jr@LD|{6sP-bW8qa$MB=@(@To5T`R}->5t)OoQF@^ zD;@rRWt2SYxD&pY@bY5ExaRlO#OLs@l`k*9S&2Sq819OMqq)jz9#m2Ew%vChbQ%#U{%5DPeZ74o;`K zTS=gnQMLa|SX@B0?&BB&I~aXb9}(WsV%q8GYG4M6@sp}2yO8+3j>37>Ti^4LB9bf` zH8lBhT;`oOH&uD_X-gieaU0xW?Up2`P~xXl<1=6u?d}xI?Bp(06UBC^mhP*uU#JRX z(u#?w^IlYY*w8*5ROSh6lszbwzP{H(t1B+4ZbYdsj8h2GaL#9Rc}#VQh5}iOBGsI( zv2-{+KolbpVnl?PAK&DBPNC<^f{*ro+>y)N)L*zB- z&?PQLNFc`R8t`aF8l%B8Gy$p*G)lQ_Hfq`S{#~~NAr#|e?v!0d zLImOb4892PcVeeQKhTnh(}@5giP{F;y?XsX-B6r%DYi>270d%uow*xpEdXh(1<>TC z`hG7Fa4LpI<+u@W;?_}WcZ>YJNilIqE~&`5hotUtF}z;Dl%zCQnVy)`{u%BDX0YPw zH3=*=yGT$y{OSPWfS|Li(sCyBT2=HqjrYmQuslTLM2QkpdI^3-F(THHVkkUhfiF%c zR&EYUbscM8RscTHC10CJMgo9W=g@Z-iS4yO9)BEdu5NHsbY)%9VaI@eqfbCJquoQXuS1Q(8i7;!d-uWSI^ zJSI_&YHbsdV*X2Iq6v-aoWUV!hLL$3bdu)7EiyMH3t&x%lHQSeU$`M4BN}YNWTkfPyF^=UTvB zJxaatewGU0IXGsjf#U9OHcA_yb0EyyD^lJ$@s*o{JT#2^(Sxoo2t zEaHEMk~u2?EpCxs%jYv9;=G6yZ0Av`$x-5n@farDWYRUBuI7UnEnD+`vDQew+8BQm$Q=M^x@1s9Argw6qz*jR3w%gQc?;8%#dNbmWl0Mb7DP=L4Qez1~$? zH%3f(bh_d8dLo&?7rEESP8=pi2TTQ`B4%lXnd>0ZbtJ%cmyu=)(4gOJtYzfN^uVkT zZHgkGHX4FPVIlee+G}94RKypfifI3iDf$SI1qz}*mrtRPZ%R~ee=&`Dk#T+te7b&Ft2M9&{jy2X&VDZ$nJnhj@H#rhlX)d|-4Q%-9PL-*$)Q^_zZD`K zAqk5IiAxgk5Bw}XdqpzjvOWUDN)&N@Mu6@NMq~Q1bDtNjG2A!B?K_1mG#tIU^-XL_ zz+Yt9EQFUtgXfCNmw}=>oI(91byeJ=0ua`)czf$Fpog(m5hSMF5dy0>9?juJT#6IJ zU~W3m^cAm^$C+Qm%=%Hbc$`wDWzBzu=^!J3X@+)#7Iq8%vlIOb=6~9&+hoT^)Rj*$ z>H6=m6Ip$~KPeB4=nfh#585w#U3LPKmJC}Jr++4oR%70U0oO#kmt@7J+T@wcR~-8F zH!eRfhw1EOt(Zoyl;o}KmpRNGD$l#OZTGAkPOVIAtbF7BYV&rb;!5P}DZR+1#nxM6&$7M-CVc(<;j6Dd`s0+qr3K$NL#iv;Dy%nP^(m{Qw-8`!$D=Gmo4Lb)ge2hcL4kAFo{Av0)nw zi&?*!vMxL-B{=HLv+W}KZyi=%!VKTw{^#_aSznanwN$yYTzG~Io>soSiZuJyEz1q6 z#to&}4VCSU+bd3V{jRs+Zgp&KcRbecFI?%%*S~Do%PKj|12S8$=$wL|IK~yn>G4qz z1y+kT90wNMq$UX8+rFBlRHA*|OtrRZuu@w@!>zxUo5i+UWB0dgv{Wly-EDifoP-rk zwhOIBw;XS0SZg^t@oiHrZkdT~yJZVHuV}glZ@b_2u$S5VTvVb~xP7m8+eeQ1-t4w- zyR)x{%L4{aNlRBh4$u2?I{}tELE9TM?mLh0J0aOSkIQ$SH10g@-3guD3ESQg4#w_; zLx~X##7I73lpHZyix_jgOIQ*-+=#JwVq7*czMPoQNKEV{2A?e@Z4*<@h|i$AsSLYm zeBRgwgChLFVDG{3?7;|pcWC=y40<@ua2R=ZFd=uSG^KSoeY8Dk zc{m$<_yvETv3+^I{O}rLya-uYoIPCLK3q9F{0conJ6e}J+R!@Mv^?7KINFA1 zpsQKH;C{f>M_TXeWEghte>~t+(jqZBbtNb!a?!g>|9QZZnPfxRbgw<&Y0`93$^-Aq zhB8=$TJv@5%SWPlr4+0m*S{WniTXbta8gk)fKcxg1A_Ysv5#kRCBa~H2#g6b!V191 z;$qEW=@bL7O$$x}AVp2e3})cU6ZBCXwEBmGmso`ld)KX@U)lK`MX0EfFo>{&Pb12S z(eF~K(4hJK*0l%x(<)1Z&_Flz)(rvuscSJE3pV7ZNa_!(NoZfx{pG9=+anNirc}1N z4%cVzAG;pkM`%IU#Z+lyDE^+El%+Q_FdedSQ9yxkJLO1ZLBoIL5~;!)s2RdF2wOC00<$8?lb zzzGDUhpjocuC#&ds_FxpZWn#F)sP&kTYvhHF>FVVJT-5C=d$DAR6^q~x!WSjwV1N} zoJmw)3C8jpCS%>D&sg#|JJ zfD}~7B0CZ&u{YJUId}$TU6Uq=c-jGt0ECL=j}yFGRQC~eQ==c#O~DeGo&dV42o6vH z9Ne8e;=cM8xXkR=aiclRqK1ME@WRd#ab^nuK}8T16cVQ_s1IOozqj?!{>`Y4Wl|AjwGfCu>y-D~ELe~29@vjD z`+eH0LjcDNKK>Oa1ld}BuLePS+jso20LSqQwpE31TN! zuRF4tp!Q*xdq=Imj-Kj1h7;5x-0Q}V2|%HUFOPGd1~JtUleK;l2FYXCe+sR{6&{U| z?am)I>q@k>Lgz&#+ptaRil`=H!Mn@H6qG5#KYnm%{Jh}l1dyCM&Ihep?J{#b@p=6b zo?qn_S~vL^zVUo2zt8Pl>BjQ8l~mypF_ghHtw4+?wJu*r9gsUin!LpXbABBT;WTJP z5J4O413>0`D?gs^6jJ$>3p2H@kT8}>zVmzclvp=Jeidk~`VgCTphvgnq+ykt+`opZivE+ZVZ=homa_n72_NE)@s_RD}2SYbl+2U8fqmWTk^>J!$^A@>SMy+CXhI`N<~oX0SJwf?muY4zwu2D{g5_`5j9j=u z5dt=3wQz}8U3vv0&(4#Gse?@|lzN;GvItQCFd%W@M2Wg~_7uoEf%@ioDaU`Z`6o*O z$};Jq44Q!^4>bhGCIP|9Q$XF3SW{kru?oM%)f;DQP&w!o7%<+BD~$}*7YEnb0sdt2 za}>B+<es5=kVqYi8mNTkL&uBzVxDJoDTA!_J?N!?_zI9G?HjVvIOja7w%KY;BH!NKr!8N|M^F1?1Sn_eG%3Da8tLO zdcR@ZGr_yAjDz%*5gvskyIZQqTxiBCtc@&6;9w##SZ40;^r3GZ?hQr1E-O!Xdi9Gi z>LY@z%AwA8&TTUk=@N5)umdPh!|Q<~Qo9j$yyN!hZoye0=I z2CwBi`u$!csgMBnN}~!XYq>+Hkt8q{>hP?+`4J-72S~?|?{mR+%zP%N;K>m-*A*9URC7=GI`elxbP*jrMs zXf08Es0ncQEittSh@e4MlK_zfasXg|VXnmvE@?Egp7lzGe@>|lH-`-bE%W|vaT;YZ zx3Xd>_k6qeh7;aG;j*Flk@CE8q*JeiOZdGqc_vEGXv(r-uSJAbmRE8p1Jw%DeY@}W zoJa7_ct1y&JU5q2s+fR(u%Jun@5A!pC$2v&b#xzqa^DNXi%#Bb_*;D8{iUqPQQs>+ z`mj5-s!=R-4?`Zv@Ld$UIEKE$+|63vp$|9t+d*UvRPV1}Xqxy{xn)X>p&VIX1wR@x zaOp2z+j0$l$3oJ#k%pJ^xN{(YY#qx!9OSH8JCSPRaV;jN99-hZC05+G@SrNo8uFL|2MliosLHUfm3lr)+Q`G+95W2A;>h^rN|$GJ`F7{fb!q}cGEl+2>I+fk-x}RfbSKo58yeS1MfG+pS7PFyYO&& z_k{5Bz#QOaQ8*a3P? z9XEg~$?O}$ghES<%WM`xEBKLYR!Ak+lU56wFq0=Dje&<*s z{9ZW{0zivijR;obBHpj(vLFG7)JqA+ZdlR9*?VM#1xR9jf4iyk$9in@Vl96mw@3rn z#@QzV*;wLSMpR|RT_2F57-Kt(-kpg%#NMCjQ#N^MKr4sHW?;7a;$tsggW9iTv7Ih9J2B||Gyoprrlby(K-oxmYB0aHlZV(4OWn!+e6?a( zVI@H32()`JpfdORK1T1Rmj>B!f<%svRPW>0aR|0lOE&kL6j|1<>#Y+Z5&_l-tv~?Y zov~pWsQu%C3q9@ePdB>Wd}wrkGt$sA#5gU$#p_q;?Hm%1K573joNi26%oR9hU3PsKG-1lOr(; z7_6z6%4<+5OLFNYc<;oUG%_qI;8q}slUFgYM&|KyllAa9*AIq7RTsvs3Z+vWUZ3|C z0PL$oSy}0>Za?{}UUPsaLUj^=$OF=*>L<|CQpX$d9w#wxs*~$H{1Ti@QJZ{Y)|CwH z6lwA7%z3HPkS!ysw!$FW(oF3)<3hOj(^fcEBIc$ zTk6ge$OA*N=U8gh*a=Og=`7HiMl|d(aR#v-tDkf$A_mU^N)`HO0k~zFLQF&cQOCM2 z@M1_MaXa6=qOTsym<1@)2d1z{%Cp)q$xQQDbMh!hY0b~85VX8t<2fiZ-WwVP5`3Xn zzh43>ANJ7|(4}VVm)~ttrN_`BznRb{XRtn(##l(-?CZ>l*UW>;iX!xGvGp?Kamxn# z3panH*Z#p#%_;GNIx~2Z<9UEVp*8ll{hFm%k(A&9U0`E8PmsZ?ofWol z1wPYZ9r$fodS#hM6M*AgEe4b+uxxfiizN1-9vyVR^rLDXdd z3Vqi2q2Ka^s9UMh2shlV7D@My>2Lb`3mEpoYX+Z!^O&+UvVi~N0k5*6d(OqA=&ZLl z$?LBgz*;Oe_Jx+4S*Un|9h-Pcvh4hn_hD6!qLx!1O)x**3QP3|H)~wv<7D%iuM0It ze`@d*>P`NoTEJ>x1syGnE@>UH?uo{dzq^z6ptD7Zn~Ud^ycYJNmi$v~c3t^Kd@+aB zONI_+RTjFx2?&3Bt~YYEloWzS@*aO)St_^z=w|Eqp1v1&@qVfg#LSD15&HXHg0)^s z>3^HXpVlk>#Qj@R9`dhQ&ZAnQ_A0_ zRMzHnrRGe#W@2$u_TtCfry4I_G$$(Q6tcFID7BQ@wUj??sd&*+snlF_uci7^OD*fC z;=e8L|28$)eQFwN`S{{f&SG=x|6>&IWo=^jOndaHb@&rw@M0_AZ|k^H+q7NV?9;Zn z7i|ll+Lo}3Z7YA__QRuRM|x=?K0YRcUjm~O4mZk_yYz1IJ$7&le!fn9W&Un|D* zdu&^KFiSlS7d=jFy)MeVZU^0#m|m~^-n*^6wv_Nse&oZ1?gc`Z52i0T^tvtDXBOJ~ zWT`LwqA%it@O%|?i-09JpoBj|fqkw}eUVH3DHr{zl>MP>1J?|g?1Sz`1kB_Zq#*&# zuZ2hFlhhKrmy5s>$U!|y_^Vo|kKaJe#b7PvPzKvj17@hPwc~B=fHEhf$e{mKYxg=D zD!vMSnBTpMhH4-oNufi-OT(j~J@psElgc9>mMGO%L54^yS%n07WD%?_X^?EVe~7Jf ztd^pOZB#XMSd1{ls60A-F?!54hF}{x!Hk`S_U$2IVgwR=C?T2>Yycoh2pt_ehP_w< zV^QPK#Za5e0UT7+gib zFeorqLSka)fbzLAnC40a`q^g!5C&x(AYe=r;1vE%C!@!hae}>+2pY4hZmHO4ne|_5T%is%C?2b{F$oDgG2lr4gaVHY26UDPtkT?K#J(=4XM&5G?@~?%zMJ-0uQhY>`;jy*wCMuGa zHi~Bw;L)pP!q_q8a{w4?NEiW-s5ntz(2H*)R%UDA*HZcE`_qz0^3|fTTTZY~$K<_K z^D(QS#pUI%BZM&mg}dMMme1%u;j8%S$mB8T+2u%v6NOgTQj_80pEmN9%cZ*IHIAAd z4#YZ_FQMjgjW2wi*M|aybs||wA`~kRUW}|iq#}uFg9nFAI~>l_hpp<2ta|#5rio5F z84~^sk5aXgi=$We$0<=r@GM{{Vw?&!PQpqBhlpH1tgau=Y!_@L0N`pygx{^B@O(I_ z?-IVXgI#~hL5w;g7&t6Cw~f8J zTB7W&hE1+6HzqG%6|4yVBYr*vsSqeTe3nqFkc{z;$<-<7L-5h?SG^jd5qxV(0{nt% znV*W}#nNh-^6IZq;ffHe)ox8?8&|M8A@DDbmoBGV8(Ni;)-hNDZ^P3aukn7F~!^HuX;}Fa9^5iKT9y>zv*@y6;hDdc)xS`H5 z+;uP`v(n)dJ}s+EHDXUDbEl8iU@!IliWm~SfF3=p0V_ML?z8oo)-3J~lVl*Tvqqi6rDL_gKheuE11y9#-H>H?+64<|qJR}y69VyFA) zK|=Vd8K5unaO7=-;Iqlqtbd?XEJeEUZ*t{rIVV^yb{V|1Qbu#qU9%KVSn3re&AJVa zANvyz*bH#InErRRkNDO5`QlqrKco)Wif#QRxjJ%R6!E2McpvcvTnFsFq8vmO@dZ$U z--gc~nSZ?@0*`H@F(qv3I1(<7zJcn1Wn5RH?c|QADM!F+YQY&8h>+B%=C&Sp>aY-_ z6QV0gE>aMaa4{FE@aCjsM1>G+NhLQr*+_1r@Yqal>ShXB)VTd`^SJwHX--lkhzzSc z8BH2ZfrInfntK_S>Sl?#FHHZZ9WNU-m*3ORfN}eZS-}>5UG$HZw6JzTvIe@2EU%Mq z6cR{Mgv(*GNRQ457u@4717DCq%GAy@IZ|Yi8PT~xvwVI!WNWr>q*NoFGppWcCTY~t zGP(Fm&xW|Byp#EbxiJ|en0;e3gfc(t;1bCDeOgkGmRjQWKn9LNP8D9@#Bf*|X62t( z^fD4}<58(K_;DxOix0cN8x(bP?p^UJo8{B9G5V`!-e`TU*VMLQ)+BvF?Gx*y-y7Sx zaKi0kI_&n7MHZw2im$+ClIqAIo**gCDe!wQ@3jP8+tiL5_sFH}NZ$pB>J~KjQL5Tl z)Of9t+`QX#VFiHB6VYeQ3s& z(>Fu%SD~i?l?yX(Z8~pL^pM#y#_%I`U*QD&KQLNH_YRQ6h^?-L|F$FDxQoNx9xkS+ zvW^vFN+YEmkEF)ZHjL@aoe^M0snl%6J)~|DSFyKz#Na1?9RZ~MlnYtikyjZ=2$^Z( zt)-4|j?^!T;8sh99Ac{ZMq)qTulUX zYSt_M1Pbuf!jMeS>OMQYyfhMFiEeJ(>^7-CRV%}Ub^Dgwj^i-#gJ3LDM-g0J6;zSr z7`C~osO%l}ySoG;uR}E$bJmo-De57JAr&%*%Nm$OhQf%<__? zl#)1odP_>Ph>&zowxDD|Hd3;uQjv;=N>pRktRQutlH8i&{^M1Wn!}hj z!oooLirhzzI1xPuTL~41caW!aUaEhv^D&d#jV(Cd2aiYImUn60Es^CU<#OR`WQ|d4 zKj{HK^muC_+Wn~gL=)m+Q8fP{4OEk`b@=|khEN==<|9Pt4p&!YYo%{OR%QaZB|75d zT4yUro5jtNVUDDCa*=NA68dMcjy3p*rpLLF-C%7}g9ffH^4ZRS`%L!N10UU3gj{?K z@7tl)v&yZ^Ozy!13(uui;g>*j1(6gf+`gGtD+*{>5Oci*X~ zg@XgOfl!1+1i-woYQ+p#l`hTLoxwFX??qZN9Kg{%GR_MWYW1PPW#u^vsn^N%OOmVa zI75EWCCl|MY$x?X8?hb>79-dL5`%_Fh=1O$VhnIj<&MqtE54u4N-io(`rTNXPfC}W zw3nT5EfJZ34wlV|LH>g%(@Gsx2dngL75rJY+S|g4>%&>8v-})cSU!d=c!!F$JEQHa zR$x*!!Bxp@ejwYiw1?Tc`8_J{`iqp)S|kfXt`oA;fx=0L5Zjs<2JC#$g5saYjjf}s zo_neL1SYF{zB#t5B>W*)kBmgi1@|*(6k*&PHLF0-AL9_DL6^=}e*DsiDy3Um(~a$M zQibCi?3rGXWQdCIp=VQIdtz6w#ia4Gdu#{|s6|VBi`b3O+8f^IpvgaPqQ&|{**ShH zaI+QeJm!$Cx>R<(xqw}blwDuiK*pN&Xe(&w`0R0*Qw&4AP-FR> zg2MU1Td=k9ADPx9+aix1^9z2Dymo?e?0Y$x{{n$%Yt;( z)TIr`C1SFqG3s(Y>R0k2@iGP<rarW`*D8XK~ZmBg!YqR?XV^7idyYFf_6BiP9z()KS(An7~Giy(22t6;C=dcBy_9; z`!divu~j;WlsZ?~B(j87os@%q)8T#&4b5k4y6G1hsRlY}BDz_a0c~a7oH?EBB;C9! z^&B6v+cJD*O~nx2|z|16h-5mb#8Pmfm{^uQn1u(m#xh? zc%or=w+MK(asl3*Gr;8nWnlPuun}-R(g_VEb{m#1jjUXZ?1n@#It?-xMd`rsPJR&m zqLB%VA&1~lrh@)SL;R=XNR=Y!-6p6PGP*l3k~Jb)(=Vnx={g&%CxgUa=BHqhM94gy z@pfhk;HNRDY)sJ_ypDlwYK(*E6NWLcofso`1*kk~kmS;M8G|;{8Dy?CbhpM6hsVnd z#@Hpt9+?}`ZIK}bKxjW>W*l@uCJJMX*Qy;Y(HM15z=P@a1`dpGQl+xYf!!-0?8)Oe z0aKR>+;0qwr3vhEj>chOrZ9`iXH4V_O_BU@hP#<5JiO$5)i_S3G%hNr8ElHPIP%J{ zY2?~L`^=T9q+yi7kea?ghoO2ZA02ttjaNmI2-K2DISo?@n7Zqj6(g@Lw4+J6smxx( zJ#N#*D5Lq|5uB5`ZqM|An>kWql=O0P7ZAmYGAPakZX85ByUvdsP{Na7Bje^UUHf6v zHVT^p_y$h`8MDQ{n<++M=ATIHO?t!u24)ciWH_Gg4~!(Uj~jH0H2q-cT5J9aJ!Q&1 z!>=-`Wv{PgKg7}$L^~02?tTy*o#Dfz7*hf3tGI$O=30;q z5n?5P0|o(EtYb`J_}Kd~zgvMqhfEvI*QmmsFsmA=kl4>+F#j(|(+_ z&W-CgVvsgg67#=hKxv1NY${_M%r-C!rQ3ah0$E=FK_P&OsjnMJh-F@6Ss?qIlwBlHF}G3J|62w%I}8U`%uuI>~7>CfZHXE5(Athp`l zb%xfA#IYI+hp#a};RvI;tWnA~L;yYuGolEJVMawom8~pN&f;KEwLcedh_Bx* zR-$-E_bnWV=8HT!kYCA5(2hu~oa|gw(B%4ov5*DqQUxj-fpLkOCF{VDaC~)jT+*DDbiFXk2h<=f; z&9Vdrsu8uO3_|a)e+`6yYGqe8Mx5%ZA+xIv8>04qXPk%^X!R}UZS1n)H=L0T63n#n zmDG1qfVd2wSe~9Y^J?Dnoy17*Kxgy?}-xW2MH;F-(61ME{c*X7}*cP zDMgSdIE;1$Zs<3SFKIX*hcfE>MfG$ey4{D>EPV_V*b(LjSi#4 zLO>$tu1lqn>S(AdwkcX9!csnW)#NBjQNUU#8~$Aux2yqGQ~2U6K%#BwNLv`mUlf(l zgOdpdMIIWv0-6=&zT#@5b^>v?i6DiosAak>EdoddiKi&HbtkwgNK9@ujOdMmL?WV< zipDAp@m@8yHV&}vEKBpF=%zy)MdOU!zeywdNewX%#yPAz_fL0Otu3WEJ4?LtGj=zH z+8C+vEnPln7}SH-W5Yh%bXNnEo(xeQ-@Llzx9!cb70d_KK3=C_X+;p6j^6C`pbuR=VY2N}s&#IYRDxm+v2mpn{H(Tf`Ril4(bwagvdoly>PlxK#i zKlcC~chP0j_Y3d&-k*XoI0agGqqV%4&b+Z&KMgJ~XG@%>3mCv_7uLn7HRz!a2Cz%{ zotU<2KPN{A`hYM30nq)c-HK`7=9T8eGP{?qd}`FF|5hHuX}xQ2uD}H=>6OF(VC`Ml0%$J z2*xFK)4^%Qxa?kA@I6Ny`nx9nqb#|)EG|Ult5fcJdG*4{zx~sYy}X+BC{4UIZ08Le zzg4(;!m-x_z01tuxLuG!6=yi0Vsyj7C@bvcn!{0XBUL(jPL&6WdZ#G{H z$-6ZHONX**+=3BezP(eK-9HBw-TPh*SCNAuX~=mdMH8v(-G zbVT)X8=m9yO>9o^8TbzADL~hg{hu|@b$2oy68L{v2$rAZ$xTz= zaU>4^w0r>Oxs%Ej+wcA|UiZ-Iu9tt+&p8+Vvrk2Lg=3F%8w1LI8a9cM*xi8Nzd8tH zPauIj`d()9O5&m1*aKcC?1l;d1A)}*oyP3Gr>SyyRO0L&bIy!&)~UV(ULWb?7H5-_ zwg0Q#!sV-h8Sa?M`uo)?r8^uK*%f>eDtE*jaSF;Y5P`W{`H@WBM_>LtIFNBCzYO-D zaloO?1{$K8Q+~cYJS+eAV5}Vd(qV|KnL>)6oV(rD=jB~n?Ze6ftYPi#gU_4Op5mz< zv8CLOe=>4`qH)Ib5m72}6RKXe3LM*F08hSToJdF%Pf?Is(ZMN`-}K5KEn<{+$f38dXy{+Av6@Ps+Qh`A7 zh9iN@$m;F(?oX-{?1NrEbo;nFp5%BdIR0hIoJgp0f7GoA5>LygtvOr5JLinGQGLHW z@LS$%%1*&}SFyg6E51XJP)PKs7F3_;seoPtG#_y&kg5{LwJ`Fj|E8M?S=3?Ted2oOQ*wXXU>>V_!RB(+T&P3rzGa_G>ip z(4#SknC}f}oHYi6{4mm$yDOnfujGO$jY&#P9!{;) zE3;LO@9-PI=GSTRci9@ps*2<$q0KVnPtAQ6DHxMpai_g8l?q0tJCJfW-hU%vNrz++ zY^*MGD<3QsyJm!0h)5jjW+`Unwdju{I}7c!gx*5H+Jf1X11yGRRosKGIt=nc6={SP zK2QnQaQK_gzi+G?tlB^PD}TJ&8A~hfd!cZ0P34u&xrqdkVqcrR^9^ezz45s|;M>u% zk{jbxy`%Vpf69MO_rBCW_=f4BM;BF?bjc+qnXv>#&;-or3{d?QoqoydeynMW$bGD# z$wM))PRwMIPC{w^-03fEguD67d-hRSW%2kNGJ$y4|}xtXf4@lucEr; zk5E+|e$RwbwgvU7S`1Kk&p5Gtwey`6P_j$cp88&Tb)wjxiFbj8=G^aE6kp7~zu7T< z@Umk?v5PY3G!4RF?!&XGJ0eH1RjV?BKCHfZ->*iyb5QBNnfSS$_@}KFfVy!HNdH{} zaOcHr9icN7`_^nt^Ip1vI6{@ba}4_8NE=0Y4a54}PI#v+(*H-YpEFTeYM?F6Q>aq# zX;Eb$f6m2~)Uf1G5{DiINvQPbt^Isys#wa9H16Z0gQ{_L)-ajLYw7susI=0h%(O|y z!HJ^K>tX*ubNx2iFZS4_X@Wtbid-8o-78gCGp$VyyLkW8rQD*!kc#|r5Wn_^nF<%G zg4y7|m-4H_#pb=Kfp{wU^>|^i;E6; zpXC`_PbRRe?~+f)O+M!DdMCF{M3&#+U>NPxC`qPPGMW_TP0T72C> z)tT_PDu5%PsIP;1)R29vNK5VsZOT2={|e6-Fz3TJ-8f7Fm4DNXKji=x(s|)W_9sIc z+E8XQd_fI?qmEUqfquU^U=U?i4G_Tq20EP13=!DF8*uERl)@1tI8Y%-=wOkO#{tJFhAA>PqQaNG$>a;9 z030MfQaZ{+&mN5l9bP)qIDeETaIRS#aSQ|u&x|EH(|<`EFy^h5cUzx2Tz{Y{D6QSxg5S z2ZzAwqcZ|J1c!2g2ve{jI0C^1CBUEwY$&BO9ub&^jsX?Vl&J;B@C)M{Fbu!3Mj2ut zi6QZkqkl_82@Iy7jRV4f2}77)H-`hznNGnFy@_dHno!W*0Mw~2V8Tm%GmSvZ6s*_t zABeQ7Q5P69eu4jC!Wnj2oNj<14N1&ctfdE&zuEQ1&CBh2^Du;s> z3k=$bpG9o|R>Bq*uO^+uP2U<~b&XSfr^wh;QvSAKvc;lW7lollq zXp$F%K^r)fNgtab6OPRY2#$T@!Z_KRjUoq!HOegzU|@rNHOr@-JP9Y8QP&(QVja%7 zibpOfoK?8Mr@IX5P;Wmk7BT|F9)-ZYQ=H-!x8MU?Ie!{pjv6PATlS4^n+#DXGkMCV*u|CEDhhRA zIR}Q=MKQOi3FW@|5lVQ09E$S_7)Zeyn%ICG$eBPS7u7cub;dxXu!}|8*NKK0MUj(8 zoL9)C35lR`B7UI`wAernws?dKZ1CPm4!I;T#NrD8f#y+IbsdCI?jKG8>QwuN(tkGK zG9ma_XPLaWIJ=PK3ltoKNkE#dN9ILI6rIOk_}K+SsPmokOimX#G!c^UgD8CL^7!SmhrrcO9em~VaaxYk+rjXIF1 zz&*#Hy2Jfr)lJhhnnKT*)$L{DAs;@HINLi^A~K9 zyD!-6(7OxRk_56hU+xV#Y1^Aki&&fo53&vS%yg{h+&AO|g34JAUm2ORfPd3=EODd( zIYn?ihQHCTch{lzd-MHr@z&eC`Bv|~6Mi}8xW+cpfsI_+*xxb8wr{AZjU`XKH`=&) zGtSHL|As4}=IW3H1z`Z9%3IxuTs{uwVITx+@IllwsWFOT0NXhc0J^{=Qxvpp@|nLo$}R{FtEIU z*>%WW)LTbO4&-=qxufI-LO>3s!T$WYZ@rE!-|N8MpY^=oeIWc_hc>JN1pz_rr9;{M z2JbDHN&HpeHDKNR-KoHsambhhR$y;QYMS)Ol5(yUCAst|EP}BU8-f$oiAQh0@;U3qipcaat!GXglZ~+k1$RdSd zuesU_^nm&y++H0<4}UIU5;mcp(cwCjA^oib_1&MtQCkw?p*h7@cL_(<>0uvw1QC1z z6F?3ic;Wr^hTI8OAtvD&SRf~E4FqydT6j(;j$&}EQIBb02J)O1HD3t+AMP8&S{(nZ}S)xpU!6}RaX8ED{C7ef)q)F-)@)4vG^nflh87e%3ZWSDujburV zpK<7x3$WxQ%wj3MkW7}u6f{#a+?gUU!ycUkPQKa;j6o=k0x1;-*NGUS^;}MV*iLR8 zmaSV!TGcyp;c&b{jZDG0QQ4-!fSZlNBh<*KIiL4coPSiF8IaN4tHr>jftrTpy;I$^6@AX+?KA*^K8oM;XP9Y+{)JWBZmmikxGL=SKh^qAg4eD3CaSh(e|uBY&X;V*(;ynip+p!?a0DdD13|c91Hq z(#pi<^UP+7+S>`;W^arG3#nru^i>nYrF)X)Gw?wLO~D^5Suy%XH4uU437||g|CATl zlvu675De5GB*%{ufdv6Vn0*gjdEO&Xki#%RlLklpIgtN^9$ZyZa4cC6y}}U4;cqxY zj(@(ujsl!aJ(XFFrSuhtE${&o7^qA2#xsx=wH0O~J!s|GLLfw1y`I zH1Git*uahgR+oYZn4+l@0_jMN8e1x+E4r1#xD=*-!3+!m6O4fZ#TVLTrq&&jl74BJ zaupx+lcgF_{7{gpvTBU}YN)&>E4gS0!G9>Qa-!E&N3x0vRieT!q@fGcoYyR?vK9xm za*Z}5>$M&$w|>!zu95^62L*O3xo*v44#BnT%Nv#}ySD4!2rK%8qWZWiy~_WM?D-%N zwBRIcYrXcXzsd@{wy3<)+rJj9!5%EaZcxC6>pB^0!agj-My$k+&cYJw7)>n3W`C^4 zZtU)S>-jM3aEvR*jx5QRtjW4Z#SX0Coh-|?tjoUab);-lh$76^tj*pm&XUh|uqen1 zhsfqE&<3s0(yPp(1kDaD(k89avTMAB}$A7%8E!@Vf+zL-+65FSgb2KtlkE$ z;0~_S)a~06F5)Jx;+Blz671qWF62gTu=4E(`RzMNF6L&g=9)+2uI%Q1|1Ri;u4qwi z7+LPvp!bHa`JQh_ zj<2|uFZ#Bx`!=BZHthS(Fa3^U{Dv(1*028VuR7hY&*m@x2Cx8ok^ctA&kisGCouaI zFmN2O0zWVWBM$@bYy?-Z1%Hpv1f$FaZ!iZ-FzL3F>2_}ik1z@2P6nF{0GF@|udv;m zu+FkD4976$xUd7uunpfZ<9;w`g)sTzun+&R)X;DW12GX7v8M>J5hwq#62}S>FR>Fp z@e%9ri}CRKLa`NJv3fKy7H=^ZAFla)EEUUd7mqO+FE7e~YZ&8i8Go-a8~^XlqOr=h zZX3_>8f!5f-!T{4F&^(R6zee`|8WxgF(41}4+}COAF>P^G9oXs3M(=rKQae9G9*uO z1WPg{Uorw)GA3{G{%SHOfAaf!GANI-`HC_rpK|t^GAggK^Qtl{zq0YVGAz&X?#ePP z-!kmlGA{4(>PoS^#eeba^0F|;vM&Q3Fz4RoF z-)uhbvp>6RKmW5pmux@}v_WfZK_9e2M{Ghbv_l_kLqD`c_kU|dPqaldtvbUdI~VUo zcl60tv`2?@ih{IAmvs7O^ssKU8JjdqODsvZG)z0-OUE=#^W99>G)~jlP3JUElh#i6 zG*I_1O2=zBJ8n=Pb&UQrQZF?bDK%3+^$0mNR8RE+54FG+wdYc`R>QAV_pAXA@m7a* zEJ?Lkm$hegwSP5#wOOw<*P^vbM=x8)HD{5vT-SB%(6wFXb?M->UiUTV@U>qDcI5!J zU>9}^yERtJv0*QE_z*T@KXwo!w$X|+WLNfCzcCoU_4QgdXA}RAV|O-ai_B+-Hfb}l zWIHWom$qud+i6>EYOgkIht6onHf?XpY}Yn!XK`zL?SE_Mwr_VVX7{aTi|}t3x8K~h zaVK|Hf3a{Ub}%b9bbI1%n{97Lw{_=ma98ed_waRhx6B~7cZW9xpK)e8H!_Pidb{Ry zyRA{Dw|l<|c)#~`$G3b(H+|Q)a^E+88@GP%_iy*Nf9E!U2Y77{IDyBufgkv4C%A%_ zHiI{KXn#LAgm<=tPq<}QxP?PDhG#fqZ#ah=wugVXV28Mf`!$J|xL%()irck{uee;d zxQnwjjK{cH&p3^XwT<8SR_C~mQ#FtGI8^^QkTbQA4>?j7|GAL|HIgTJPcJ!>=d_bQ zc}+*Tl*crcS9wbdad%)jgljo>aCw8fFqm_=n17GCg_pURclmm!IhUh3n;*EFzj=Vi zxt#Aeo!5DN-#MPYx1R5LdiS}Xi#MPLx_1vcq0jf4AG(ekx}rljqc?hTKRTorx1>+H zZ&$jd<2I&eI&E({r^B|Vf4XXix~P*jsh2uvpE{~@wyLjsWw*MkKQ^q#`eM&Itrxbf z-+y{w=en-65N4vC7HMLj!Q(rr_ zFSWLB`%!nhx8wA8WOwOqceo?CcaS>>oBO#Jc%rvEqO1S=4zoMFgZjJIyQAMbzDK&g z?>nXUyT4yLzz4jh4?Mwly1~D4TP!?S5Pt)6@aw@(O~TJH(W5QKaU)Ily#$&t7KF=RzY_()5z2Gc~WI_Lr%TtN%?Kz|qT zWP5l+3lzNwAiXjx{rob`%o{;gEId~zLsoD_&kzG?Z2iNk11+?`2Yf)$GXbZlgEKe- zDSQA5sC_cC{rffr&jSp`ON22r0u~&CG8ls(R6Q}U|Hc;d0y0c}&TP!fbE`1;y$moy zD6~Q!NS`eQ{niD?FsXwocmN7;LVq?hzWX-C6i7mu(8~-E185KfE+kfl5Cc${f?VK2 z;pB`L$kb#PtU9~`E09ATd;kd~Xm60i*B3z%_`n*-RV`3~4*0$I`%*2WK@oU>4nRR7 z^hPu^LKTGl_y5N1ivT$4f|Cw2?zb<)0K}L{+O%nMaS&lbg$ar6$VH6ML4O*Dlocbk zNm;Bz#D;NM_z|QF8;aI}8}$VU!gVWIwsiRtW=xqgY1XuP6K77HJ9)BXwoV+RHXqJ- zTjIeB%yDfzG;PX6o4QO+o2KxhZ5=vFEu6LhA!q+xIHp~1{9>u9#fVNU(d7YwMH1GY zbLrN#dlzqBy?gog_4^m_%73OUsTMX&HKdEciy1d|{1|d%$$JknVPkgXvqvctee}4V@ z?GI*o7(m2A;*Y=r4LlIRz+#wfC2(xv1Be%3TL=hckWeNWK@OV1v|&@QyR}#iJLuSIN|2PvAnN9}nV(}mZMcRT+yOzGu;)5{= zTFQedR#Hb54@BVPrGIo{Y=K4_UHlTvFvT46KMx2CFu=sfT$9Z<-Rvm`QPxpslqe)D z@gobBK}JItN+Sj}j9f`Y#6I!-=*}syT<4WH9d&FRGd%bLGnRT(?TYe}x4;`2erb~WCZ zW8IEjCs}0&?0=Z#l1+9A1|rVz@)=3WwN{xLQc=bf7dF6QW>bhsWtmT0*rJzQaN*3{ z7raR1rAdycJEo6AK5SXO1s|Nvgr*p1rGHh-bwQaK&>$w6MzGkZwGT~E z;s(mySlope*3#yglQ<)MV{2mczyvm|LCXX0Y-y#DNwmHJ6=!-hL{w5uy?wjxFtH^R zOinp61v-9j#SdRt!qI~)mXky)<7y&IKuXO+r}MEOFE#4K0vQ7k~bzDSv$+1y|?-C#Dm&v8}{|X(+-6 zbZ~_+tmHlZYJm^3fVGuGLq;u-fgg(4MmO%qgeUYs3g1{qJH7;nAc^6fT)@W|<`GYK ze3Ujqh&PJqq-|`&i6I5qNJsu9jwk=5<0C0aLO?F$k9oReAS+2dMs^aEq2x;>vo}dm zo_|tsn@mV1F{#Q4p%Rv{lw})9`8QL}5|0K5 zNvA$%rY}UwVCFQbSxxUDGg->C<~F(6O>ce^oPNP3nzR{CbDk5O=~U-3$C;*)trMQ{ zl;=F@>Be@73?%i`=RWz_Pk*xOo`8GjKYs~YP=g*6p}h&HVal0Mhdvad5tV3}&Lqb< z4s@a!)#ye!I?sh_52GCw=}1Xh(qVp7K>0N3N?F=cm(~%bC=6*uEm~8X-V~=f)#*-o z+EbtY6sSQJ>QISVRHGghsYzAp|5BSmE2cgbs!^5dRH<53s|J;(lALLouG&?vet#9L zVHN9G$y!#ko)xWWRqI;W+E%wZC99>}>PzWbSG(S|X*O*rUisQrzy38$dYvm^30qjh z9(Ff^RViW_+gQgwRxgVE2xKW+S<7D5C6W~;W;xqg&-zuf3i<44Nn2WyhL(t?Rqbk7 zYf#jxq_we??QGTg+Jn#*x4G5rG=FUi#JBzyxWN_faEV)7;~p2e$yM%hmmAE3Fc-Sf zmF{$@TV3m37rWWju5q2~g6)16yx|q^c*$E{^PU&IO6_iX+1ptoH@*fC=7QU;`f*!3lP+fECkB8*ezqH`eivdE8?kFBru? z7V?mZTx267H^)a-@{*a{WG5dr$xoK@l&M_hDo5GMS=REFxjbVmcNxrK7W0@R{ADtq z8O>={b9~LbW;eeX&T*D*n@8nbXFJ~+&t|1_p84EoKmXajK?d}o30-JI=d`Px)GbU~XtCm6DDDoyt+*8{?p7qYJEg_lHCS<4+={yu2@>4h9g5p`_`NgV z+&lCBdtnmDImt<$Eo-m6_LDGWMd|m*M96S(aPMVhB)-7Gy;1;f;fQa6BcUYNe}M-+ zU~zF}u&F5=99^7moRCcSC*oeiiEs*BOvX^&uf>XZ5|YGq$dbhvRzVshpIILLY2M3* zN93*QIGmbR?XRwvmIRcLA%6SL%g0aOBop>5kIZZ$$a~!1>>bnW{#}`s6N()524a`~ zOG0n>t7h+rCL&@k`WwW7VUBGodZd*z*BCg%6BEIq=f&(iX{a_TVrWmzFq`fA`}IAA zh1C`%Vq-~dYGK-soO}K~F?yPU-!}9dv{%zGIWr-&(HIdy+#2(#xC&7o;k>`C__t69 zW7J1;E^bB)KtU>xlL;K^R;Bgzb*EQY~E2j(Qh*R zh%@nmZ6aIkq}ETH%B~eS=#`aI#T@V|oVML1rrR1#pfR4IJF}KsdNN;L!J7I5<}} zIJkWyI5_@PI5>QVj3yO9;KW-Kd1(o_=a=7~twjmI5hMp0ZD%+*7Rr~~D~|#ZH{jqq z7g+_#cl+>|@0p2pmg1rSZ+CmCX}Nqcb|-UivNs3Yn31`7I+&6D=YHO(0#)5;Vsg}n z9UMOYvl>1{bkLV$zaIps7xQy6=~`k-iBRoWZAWmU6v<0{ZzEILNw zFahazs;4>}`c0&tv+(=h!Sg0c3!Td-_#I9DHQt?`8-FUcH?H~8cJC9fs7k^OD8vMe z8ijt;V>H}2VR004v-}nZvoN`a+~tgawXyc=O(RF@OoCfM%5UfVyA#lfamo~|VuP1M z*L4_H8}n|BQG}plLsoE3nXLtBma9M_aMXWTnUA7C-!8d#2~Nh2Iio zBN9{EJ|;hf?4+b)0@Z{$Bw2(AE=?6T3X?==dQ2wl`yaOR_23 z$KmNYW5vuJ29G4&jcc(xWo_RghjcVddsZeol_SSB$UiE&H_zFdhCFV!A)bg}wIZ`W zzRJiW-T$k^tO9sAz(w+ZbEkugDI78wxJM@Y?+3(<%*hMl0P%sovVnl#|Nn=BgWZ&k zgOdk1V9d$E$@X&N`1ueviq1r?4i)+|2045f*jX3F=`MAd}1N3EoNLt7kPG4~3{E!Z`E zVt2NdHCT57{;?6% z4?(gd`xBb+PP1v64Dn5>!UkeQ$N-{Le()y(xC*XYa20HigLBH76fnf!LpZv(n_$$5 z*kG*X*T!gkdPeqWS2xRSxSX#VmGYR6Rj6a8_ns=h5@g5KOa@3~G7Lno)t0W&*q=1Y zj;y9|>l1ILCDmc#IR`JKa!T1FeG0|IQ{!GkK#1OCHx&@n+pqj|t+z#Bl$i*YpMv{- z$)0S<9C?NMs?j)UD6gQAsmvD1jf*3|{ztev%ETk$F4NnkaArnx2{!(gdn_Ce(^AP2 zT2GF*C%FDLJC;8T)bSR~Bx>~L$oLCzFyPtK%Zy8qGzI#lbfbQKp$p2*t}PU1!we%C zWAwtf9{&@@frAhfovwv7zNW20YbhCsD(@PC-<bdh5ga8zn} zm<~d>V{K_R9aw#Y!~IZlP&qSd_|j0(xhvd-Ed&*Sdu{q z*^=NK(Dfl;to|hmXS?qG2hrbTZCLJCm&^D3pc%bpBXvo9B8cQo>e3W(8m;6%9J%kw zyMY5TySs>k)yw`-o68GN0UbknPRiSV>DHiRQs!f|O+KUP%0}6~=5vu>xJC1HelYo! z2hKo>-eb#i{CQ24fczuIh6y2}NJ~Xk^HPyylV(fd*C3_l;^C{7QhCdWgmGVS*Ch4WH7vPNANcQE8G}Nu~KPx(r2H9fi z$yiCOd|;|&n04$+i&u5vR3l%OtDY7JKgWy>trX% za(PD_;4>TvE=L)5+B~mbnMvurvEyu*8u7k3|Me)u+gLT?oYO5^b@*%dkI`@EA$I|| z>h4wMzg$RF{3<0hOXrUYGXitL+M3X-iN6p3K%)t_uYL=zo*lY9hq^O<^iFBXI$yr@ zd(*lxJkxO1$hqTMcH=}N_3ry0tc$wx*79mrr=y8vzB=pvyJx*}{n5E1V;8txc6Jfy zF5FlN!#%@{uytBOvs?c2=r+W9v=2DyYw|5?{MFAL^((V-Ul>P``_btAb6`1%Zz^Ac zb$wgL58$LlnCG~4`t#3dFr6R%aN~o$_R||eL>CvYDe4J0IDHyf2~jnV`J+q=4;=Lm z!8}0*f6RyeEvbo}#0CbUg~L=Z1r${HWmM_Eh^bZv;2_u(gCr+o3<_iw#NIRi!xAI= zT7xutP1(#&#hHF6CNp;3@4L2@RKw{!lIE@G8-x6P-;s7=?X+s)=m{;PyMLmVkdW}3 zTl10#Bj-?!wYmA-?2(&a^V0E&EWh+sYx3amu$rf1h46pR7;5&0{{4G;dFs^$JRY^H zzxRxbtJKLOpIqAJ zviAkrg>!hcP|rw{B{;X1H&+v*l*YR^o$dF;cQ8LyLJlm&HmKFZC0$b!@D`IZ&J)=`;m{lEL`qZ1zA{n|}J z)gt}*X7`iTi6W)?&k71tc&CxUJv}{c2Qy{qe6E8yK6e8}-tqDAMEHq3(UGXno10&+ zx^6Gt??4}&lnyuPZ;sPXH1r!Ba(*}KaUKF>?;C9H-`YI$VjORe7Z!;Li-rfnG)TR(tT z7CluvO+7GbmItmhIv4pjySUq}lzTkhxq>J96gG-JLo$d2JO`sl1l%I!6cx>vlES*z zPMbZ}OpdSt>ua<5bq3E4sInadprd8;yZ)9GHS+|bGF-kJ>@+G^+z0na7-e*ZE27`!Bg(x`GlO_5e z5@-|!UH8^|8RWpv^HrvQBSuAH7&^)Mu8C~wa&{Oi3VZr{MJoPv>;3E2chgwPYR})JhuqweE*a+Zth0!-s3k!eeF%xKy6p-=BOt?(w{v{PpLg z^#To8L#8SXw`k9V(x2{qL(Nejsm+q8gsxhz%ei8reF)=aZ`w|_xT-I666&eN| z7o$QUNkb{myX8+z_qRJ+j|P51&7U(oKYSz#HVz2U6LR`ziC^FXxVP+G%Pk(!;HQVTeM5h+k<7 zT-X-7b6?~e0L#rbVOfHX=L6g93Y}YxGoMtt`bm9jm-O|sFV{i@#BF|D>rbe!&?!8-r`NPsrTV-+ob0m)A1s-IM&h{M6IQedBjI&0TE#9~_{73& zZw#2`Q+{C~(I$+=@Q;mG>=fi=>km8uI{=>wa@~l|?KdXYl~c*AnNa#X(Km1PRDDE6 zZj63Wcch*eypcre4ngaFDHnsSKLIQsU#|SQ`aogAH;GsgPU?4K9JF|Ob-W}{ZE(bY zTW*FeQENLzgwLv1TI5oZ&SOh7l*U{+fG8|T1uyV?XI-k-l%Jn(E}F}=!bKe|o#%CV zb`RmY*n(vWcyn(zmM?Yaruu-j69||1T|2jiQmp?9?_>#8XrPq54%;}9?@wdiT`0L$ zaCdE;DXA#fvLo9Z$-{3FK`&VDTj&nXG>Rnia=NrYL$Tq+z}6pe#HRC4nQnhPC?ZbrNMO@j6!=^dG~*498^Ohi zcK`mW&_cZeNia|Dep6DFqa1FcN2yK{AmMtD8fd$67M&^`+C=IAf{sb+=z zbs`Wn`ko8&yLq~w(=hmZUCkziZLXNzrXmYL*@mtVe8gg4R9Nm>E#tW>pxYXit}$m$ z@*cPG4}E%E?s+lvknBak9_M=Z>wt@;lAg0-{XClF$A^nird#zyS=oYn_eGCAepbVp=QJ$u@Swt z$m*S9JTI%y^n09Qq++8pOmi?tx%+pRv|e7`es#_WmNSDDn9@puqY3%;ix>NK);(%% zm);gBX2zG*02N#BONEB*+zx7d>5Wm}XF6Hu`NY`*&xuBzXDX;kp?rU|Ho7iEArG>; z*yubSqXx0lfye_<@~7m(Rb@Us8`Isj_XHyt&EtYu68w$VbbGDxX9yz{Paz$b460!2 zjPAWjf_JI`X@6v3h4v)S3IO3WF91GXoMTiIh4^}3D$@VdETDsyXYzYfLunUkd%*}` zpu}#)-_;#>P(y)qNRi`!Yzknm5|W56aEWiG_cz$02GQjibGvD?shv4u9EB6N#k!A(WTPzrOx zdp|d$=N~EvGBpO6GMs&xpqWyGR%KC$622H@4H@PGjRM&V+knl@%zpJn5+^Bt2QB<9 zcyyimEr}p=p$AYgblDo-+;R)^-*z-BU+oqf$PJoYerdoO^J!#v;&V|%6RwW3s)r;e z!=gib#`B~Fh6?57!il*({(9Dsf6{=wRJ4^9KlDU-9^=IZ59%{ltCf$ zOVwsN3mRoO1-IKD>{mC#u$2adHd-1DS&|ZHtT{|!f!FBN)LWw!&O0N$K34-p?|#FF z(8*mS;TsGq|2?3oN}#FG^b)>g;^;&OozihB^YDb%Qyw6lCikn(cQ7ZqpN*y}n+t zN6@vc=J=&q!kzr>`q5riRyNMFqTYIEguM*HrJ1!-8(6V>xzcW22a zucx^kj?pZk50oj#hiRP9>^&HD1Xr5bMRB*Pk~oXsNTv`zr_b(KjU3DdK;$cc@NgK; z=jZ=DX}i6O0qP^YobzD*fUL!6mMx1W4P{7stAITfZ917)CELyMg1sNZ4T%VTW?~|a z=Pj&&2mtPs_=JQxe}B;PLBXB_?*pr0o8HFXI7-$B;6r6c5j?rwbv!+e7pT&LqO88q zLAb)CLYbBSUn*&a;oO6NZnJSm)T>9Yh@Tf!)4H=B$x@a6jfYP2PyMZ`oEyWf6 zNj*&?TYi$OtAs-8m@i!-&km{+zPCSJ8e~4s9`1=_Q#Y_&0nnF^L^RpuvY`Fx-vy~6 z>f+rvCv_T^MAcvbcrbLyD9q05z-ri_uuust^;S9J7^%w- ze+#3+BEPiE7?r%gJeZWMX>l!<1yOw93eK( z)Jy26n}aX+8MjA8%qHMp2o7gvvr$L7{o0Xn_t|*q+tK_e5dbn7vyrNag zuzA#y;bdf#uXF4U)(YDIpNEiznxx_U)}SViXnVSg=@*0WB-mHyNkz8EE;#|$EvW-) zhJoi^!N1zt+Cgdqh-SGS(#e^gJA|DUF?SY&059(Shqcq3?uuj&aF(FwIk-UP6X2Q{ zIY`w0O#hF^dqdVUn4rh0(eo!P8c~d1!E)_pulI+uZN5ffDcd>XA*0EN-v^!u%fdb=g$*d%jv^TPcZL%&Sjb~h3Sb55%0kR*J;?zCX!D6&wj z@%7;?YNc4-kLKcVL^Jl^ZyIh4s$sQ&DxpfF&?f1~27LPJ?jf!yD}PGq=oT7AXk;X6 zJK;njWhh4k8Dg#xc>c)knLeRN`P9gtEVN68lao`m&T*p;$<=x?FbSWmnwTp38hOyc zpG>anYivClwl-SEoIg;r*Jj7_M(IYfiV6#@+HVdod|6vhDIgLOxd3*>02L?yH6`Gr zAVMnb@rG}2Ko?!6>~Si)Ps5xyNA)Yh^$SM@OXU;8fDF4)sO6_$98RCD&7X=DF z7W^53Y|SR=nl}~sn%RpRdYPf8vC1}D?QNE{{={e@R^3hS6KIq&a73(n{wCx}N1unX z=Sh)}@>`w~{^t+@W$936j8+5hqq|gNxxMOkQSgHzhGKpBkT zokFF|tC_&Fjpr;jw?$zkLgBBwp8t8SRhY8}FLcKHvW>%dkvB$<`>D0+ewmc#+ez*0 zuVxJvLw24=J1=VYovfG>SQVvK0-=A3p`pPb ze1Q&tAs5w3w!}Fgh<4VPQFAHt=#1WpV)Tg5c`L#ICy)U#B#M&;@@;?IUQoZZo*BqO zJa@v9$qyp~GC*bw&7RgDJ{ZB8BTw4}bv=p3UvF*A?Pzh%zN^7ey2$%p9V&-_g`^m7OMwyPo-TCAsh?gVz@G+HQ!;^eGz?{DbjFuTz#olNcrgXQ9EqwE zL}awi;LC%MiDhR1ppa)pF=1@6cN6yl0MOo86DjQ(uVH z8vxZp*OSe)l-agN(rS8DLyqPfonhsf0<^%}=9>M0wYVN6+jTzN3S?VOy#=bW_(f{r z$B9~55H1lAR&A9+Ko!pw6(1GCBMI0Z9|sBxr||Q?8j*6n#+RNaq{y$rHP$LNbTg}<&Yq$Tx z2$@jE&n4qPlOzMkk4JqDj=T=SDr)od|{6qx` zMgC`a&o>r-$ONfyTD`A&*1ALP8}y4j*Sdo47&S|^*j!FAB7N>{(FuS2czmb);5+12Gp)S*u_a8WLI13d-oXMy3e@vkci=_GmYx4k&j3LtXabIAy3JYJZ9oAcD;gw? z^9%H%83F2?cL!vuT_NM*7T*wh`*2ZF{md+Q5|dq-^q<4a$2TPbjm;QHo_9MwPrWl) zo`)9|Z5f;vo#$plh1tB0x%wI!$<-hwYMMXa_6KM&@o-S(zmGF&C8YgVGpZUgIdxmk z2~0tv>mDw9vq(i)*b59tLf5zd5|pmr>e|NgW^rT!DAnSSN5my1CMKrTJLWK9Qsmz> z4ImWG7641@YjP8SZmk%R>6J!73=k3=F$kQRbPVy{{4a57Kp#L}?(#q&aTf(lLYU%0 zqQ4f^FZL$jRIlEGxJW76uAJ`0mF<4dPftLZOl`b5ki5WSJeWi;xh0NwaCJw5&Q@bG6dutBpI*Y4xlMob6-0;M3; zB;)VEz%My3nUAs%K*iYQFWz#lWod)~Xh5OvQZZGeLQb_Muw~~Jbdei277!bvhJgoJ z@fZM$^ymMkO7-u@gCS(1P%+Qrg^C0v7LL-A z`n8BK(Gg(vchiI#i2qj*2q*r%Wn}%%l{TL580fU=2KO6K#--aQ0deyEd&-ycc%$@M z=zG7I&5vC`simT!5ze853e?+c>b2R-4I*4@+j?01+f~hzjuaH|+N6u|xQO~TFxd-a z5fu}k7f{LUy!R`|DW$S}0hLiT+wW@b&(Xr4_5^?xs^%}yp_2+f@V`Jwd?lqNz^A&w zCwu@LAshlV`afii1v+vd^rc|Lw=(%aQ{-c}+yVyrH+HYV>>ett(NOWFNHtS!6jqe2%<|6x$`W+*=9M=XE4 z%qEYmD*Wt|AN6;wp5WWjA#*?=XV!9*9(!Qjv8^C9z>OS-|6$zvAA^do)KLA(TOrg3 zRMF^A2_HQlR_zx~)c#A=#CXeN&>{D$`ZpE-DcM*$3KV$7Hn zI!P6O^;l(fj8pjjRq+HOR(7e-UJs@C3quB4AmL$D;rfaGbU*ORFeH$S{X^dh#-tEn zC%;SVca35lv3fk^Hw{!qy`~MHJ1-|kM8uRp9Puu!zK{7Yxq21<2Mj|^FwGmtep2`6 zGWV~VO@|WFa9!=nQ!12+HR%MQ)*;L4i2P%E3r5bxE#rOb{5k0?vxxF&q(yVZat#A*CaF6*Ni`97xFQh*t zd*&}Wt0bO+tVR9HafnCmoq!X+E~T?gh#1H|Ds;r4Db-7hiFKib%SUr?a;iHzI`S&dZ9{$h>#r&m49429RHmvAP|m!@-0Co_)9 zAwJxHxV{h(=bOxzk{Zx08bCorL6&;{W)EBeTgYt=(6-tAmRp#C5W#e7ZmoTxC)#Ph zfqsAk33sjh#O8Ra>*G365Qsa=eid4FG|ByFo?isbU? zm}`D4G>&?W8C{2#Ii6tbE7g z^JTq9Wg!w(@7p4RBa1f&V0?yH*r$O!Ou`qsc-le%3G*~H;)~Zu>HaY1VcxGjM_1PXlrY~pg_M5$olF@xYa9f##(5+ z*@87@7wDuIKyk~ z*b;##6#fX96i06v&enaDW9n?Dko#juPV#H77q0`-NU7lY@PlEEI{=aUY;2%*VEQ1I zPQ@5){V3m)TKJ`wS~u%i$+c!Pd_tGE24NgCPDVy%_ZLB>>0RyK^PDAr{A)>SQr&Xv zS>)UL7CLeX43%C5OOWPR#Jph4*y|@nr$1TnJMHM_EscJxC-z=<-jSBQ*}>J-2OyOA z!Y|r*>V(L-fvfLO)ipC*m6=wroo7@mKo(?S=Z zWwG{g6hfcL$oZ=XeyjrGH9>)Ba_jc6Dqc*Fr&*ouXE@oM+c-6P*lp>l ztbNWz#I+?(^@JO>GsR9UkUGf!J8Cpj?4YHI%Kg$9M7Va=Y7IGOy$EHbXuEPb zq^5s871O^Q$iyng?40GuMq%st=}q0NCtqA2TdFk_oOPN-u>x1V8Pvj55lmUS^pt@O zKXzIUR%sC^BNb&_$2AjISoy^LWDdH9&S#w0;C|u$VRF@s!4!^&D*@W%`&Um;$@KFz za0!`;!vG5{=Nxa8A0uaDSEUG~=?tb7oC1}gDDU+Ic3 zj)3{z1MMWejyLzBpG)Bn6D+ftAE*v6+)8V;%95Jr`{cfNA+80duT8~%YB?b6^+2jX zKLyuapBjqKx^bge=<1pMgG-)PfU{;x&xM|ABjCS>Q$npYKoA+3az zXnS(x>Kh3O(k#c@1MLDML38If$ue_EN)!uNOzxP!XdVHLlhUuz$_4?iXAw}1_1jpvEyyH#T zmhwAg%Sd5g{Xcnx>z8!_k!hkp6ewV!jB7|BDq$aiNk4)NaW|oqFYDqEN0@}}Jz2Et z2@zng*A~QP?R+~T!o_>17N}jD%W2&SPD5B_(SvPDFiNO&-J2`?Srqh`ULYckj%GWEW2&+4Cn2=LjRrrCCz>uH%gaK5M}KyQx(!%Nd_EswXN-VvJ>2urHSOf79P1RuQ%oYAI7Omi;6N z+Vrd+B@e?gPoKQS+uj+80nGS1$fgm!mcT)L<6z16m-=imYlM}*@}X&F`IsFbi07$a z;C*Z^mHf=vGWK{|D)M||ssRi|+5wJ$79#F?v8`|c3>BEOfMKACpwI59b#H6K(iF4j z1lD&(BEzrzjGrL_g#3)Ll$wm6k56DuzWV);I=gq>HE#~WXY&{-?{&4UaD_QFq*80R zXv47#EM7Y(9?*W+qSepqTKqo9COa1g6=C}o_bb_tB?Uw{9$v(YGGh5Ch*cO-LS*RT z=q93n%MUA+uC6gVpa-l)lg4FG2buse_JYGAF zP~><1v}YiD;P7CK9y@^Tia~s_Tj&CDX3J^L~j2uXq@g`dQq5; z4=dML%k4vNO@#}!Yf8_cGtR2|65Vhicj0VmrsnuZE8F<93~X~{Bcr*5dm=x$m#=Up ztnTmIKMt}r0DGnGUyo&Jp4z_?m?7A_>^cr5Ji!I_~y;FV06hpq1 zPi*el0O9Co)}IA!@|yEU$Z&k%ra|kRDy+y{+)+*%y-~{JmZf?B&DK8U@(%HNfK9y@ z?O^c*&)FvW9mwr`hW$OF`b~MNWlYCDTb1&LMA9x# z4adaD$`6Re>Zv9$vRSBrW)%KudJZu$GK|<{oYH@%Qqqunr`th(BS2oqkZSj#O2P1L z`aiR{pBMcA(j6Bs?Hp*Ak?J^qu8Owbo|oeDzsmCFxTTcw=r3(n(jweHlp`u)3{rZj zyzDtNqm+6Wm@J4Rubf}0!(%QHVn4xB29Ceb%h^TesKW z%cy7+nrStdydjr82)WP^`3$n|@-Km^utW#2iC^_Igfay{w>#52}xjzi9W2>6= zK)6z^rj0_{A{Xr3nriCiLXbZBW{o}}^7)-)Or!e|4Vpx1hkT4g5@+@r=F;esE%R$D zx3ROc^ckC1U>wZ^?R;STflFNqN_?iRm}FRV6J9|o6H&CP>5rY5Wazcq(=RH$(?vyy z?o6Zl@C_*zUF;#H4VCD0khVcbg7J>+6>rHU6tk%NHfOGgF>1h^Im?8(mMK-_+F?u z-Wux{=I9!*whVVp&{xe8w!vJ+>1i5-LyzyXk@{LFihB>SdxwytiKIS{8oav9+@V%I ziW3;wKqK*2$4`>^1GW4UnXCryMoMqi=OmC=Ice%)s5lal90#%MHhg@O3;;?S6}6!j zrq+4v85eQizu1BGBkGE zER??gV(V8U3}AlywYX-h4k&X#%WQhT9afI z=KHn!67`$E`BL$H=s-sUkZPb5Kc~rRdaxRpMe0xi!B478Zy}YHe@h^%icuE2 z`NCE^_3MyD-X%)wXT96$gm5h1e)#a-Y&Dipq@_q>&9>$vx9BZTmKijB=^_S*?$n*r z`Wgfa%@PM?P2>}ZD@_WDZFH)qO08Yllf>kkPf~ zYww58a4htZ-b>@f7(k{hHNhG-h^0}SM-~}en)PKCZ#BOBC`B*Ef$a_C{M=_FP<2$mCo% z;YT@6V5?iKjTVveE3_R6*{d&=U970}{4t9+!ax0Oz7>Miw7_)e%L<>z0Qy-z^clX; zS`DB;(!coy{N8D!BK*P7m;OG?uAza7*E+1ce6)=mZ;q5yXkExNo!`0sJ-m2-t29fp z)+9qaLcl89XKCc~P6~eylv4z%H{pK?_C}fe=q*vB^FyQuHWv^KwDz@n*ZlIWPyJLm?O=GMf*D6g;wbN z>;ZD;V^+FZ1yThGYY{4cWPHCB_e*1~b{f5+vM+<(pkN1L`=yygHN(1e(=7#)R)@VO zw;w8KT8#E`Ei>hII50qJv8%ptanJi~ryyJDRwhjn@lPMLEFfN9}sgzemr>Gg0 zy$g6kc66m#l>#BU+y_H=cO+HeSUOIThk-wVj35nmvgUE0qYVIC$F}IvV@ezZ;aZ@ zamuZI9CY)#EF;i9lN%g!69)_-*F2U_n-mv6kgo!e#2M`4@6bC@s`4FFmK!J~7^2*H z&u{5kUiYY*;wLs(t^$~B#a7-qP%`9e)H&)6pv!o%6^bb>%Z%vTO5=|96QKq{lP+8V_ETg(9VRGg#t?AZjQ)J}=J})G7^hd;-F#3yp3=nKcki!~ zDq_A_{W@u%YTcrc0WztguZ$*f59mZ0k)VkwhK%t$Gx<+tVj>ab7V$-u-nBaoapvKD z?|jp~i`kMSN+2C+ql_>_+BPNcf!yuV89!&a8bcfMlSow`peW#F$LI?FNd}vV6nd9y zB@AjNv|=ho`x%=P`AE!+4|}M}vD>ik$cW4mzJ6o;yMrkwuNema;EY;7;#iD%s&qw^ zBGKX|S1(N!pO%CyfoF&&p9dm;H3z5u#^3N#nBj*Wj|zGNV}SQWY^NtG_A#@Mz~ud4 z=E?r32k84bs{dyw^#cWJedm zhJH~_2F{wg%PCJ!du$mcUi*HfjNp;#zm4d@VS(*o!;&gfd;wBglLOPu-f1CjAK z{$0?fBvM6npU=|4qG>^mLXxr5M5}uIw$dwHL6-V=d?I^7HE8wciy;6Z1EiF7j5snm zk6_M?P{lT;FI>U|=GGo|3>rctGp@(b&Kuz zPHDA=7ObVW1DMt4pH{E6GodKAgGF!+M&@nLjkK)VnES3xQnJ@YN2y$Wq_{ zzHg_2keH$`vaehMP?)!uIJpW*RN!d3*Wj$HpVCgx8fLOrc?z(HnBFP1E@cT=pia;p zFfQ&O2ufF}Gs*8NEe5&@jGZi#bZHn9>q1bgs#tzn&WM3Qw+CjZ2Shet0lB7Cz{PAV zbthaMf-oi8hL{hYDX!EtB&tJL-bmi|GkBR|0vos|aTfeG|AsH3xFWFM!}s(FhJ*@A zoD=U~5D(|#qC|Xx036%EJaRQ7&ii8_=$$t?)IJi|QCbC(1YEcr??hUvP8!?1{QO%S z`#`j{d3MopOnIrc+nl0`ET=mOPG-$`9EU5L|Bh4F{`(~DI|&$5)0hJ=Xde6@Vd~%B z1UoPYZP1|Rg%^#-?bJx$k@N1!_@LJxfGP}|@d$vKF((U4 zxl&6}Pye+}yWNsBH5Wz|&}Ao@o&{BLMDNS3Rrj&d;^k9nx}>#iN_eUav7%mSyhxf@ zuHP(oP}elD^7%STlajV^%UIvynq<4F$Z?8iw$>K1n*Q@JtO43I!_^3N2)6}EDeWnN z#q@eCfU^P{R`W~1Hn&SQ@fj%+-G#)1b*@;#VHXy)4J-;nC0LxRw zI8AAbJRI+kq*u^Pyxk$hj^^7?FZ9%Y_p1O9d?Q-q?XalKn+H~X!AlaNo}T=cD| zZCE^|usL~~T%TUBSNkh%YD-cfH0{c>FA$qUmtZ2Z+3{*$-ZW7%q(~cuh<}3$*bZ+# zjx1H%MWI8Ej3wrYX^J}-0&JZ0S=DwjNF4i7x0>6h={9;zQir}x$e6=2xnH;7-%HUghTiRB=mdU)Pk<}<%XV)xqS&iK7S8D2mrYE z8w0lE_$oXl9+&5BObQRorI(Swc$`w* zyo+{%p0P9FoIadH^!aM;;{Cx4I_noOu#x6Buyt(SaZX8O^!6;I!1Q8Htc(R+pXtR%kfhX71=tnHLj3K4)Dbd z`%kepxJkD<W~3qA7dbx z?woP7@Ew^7+OGvs@L*Xnwkh|j`m2T67ecTlgF)@G&cs`OIjV_%@=IOIs5H=l$5o1b zFm7v2itnyoZlbOu6N$}hs~WBhO|U!HIV76bXV-yL`#*bVFd4S>44%b2at|7b_Mj%v zJU6b5964ob*O(kixWCfW{4f{?B2@*?OCXK1o6j+a@^A^KT29kReZQ81lv+x%(yX?r zesY#?%BJqvc>g|w6Ne0%B|-!!^(s-6i^oFO5t&%&SN5}-29g+6oyr;-kb{3_m^7gu z6{xK=gy--86a_j-SkvCk;AglLYu&O`yD`te47^^%lR>Q*EXemQQJ`upF$x5cEL<`lXmINBm=o`UFq} z%V69K8z8Sl0iS?3IGMuFpNUik^!#>d>gYhf_Zy)+b_b;{H%9}(2^z)Hyx zZyw2knOK=e8vA<2w2}sdw(cpMT?$A|{E^6;=bs?SbP z!%b$@eNq6nu8dV{bJkk!^Feb>Vnx+ZK-%^IT}5A~^Yb3fGHt^K1)hd@FMYH}kZ@pfK~*O(H-l%bTf?UWdy%I$B963dyuTQ?|`9z_qzy3HX+nkn8>= zHn8VOXrt8#YTxdwz8JAkg7kXi?-90UN#(TiO&Hk>cLSh$vsi8_sRLcE775U`oyYY{ zLgML+wLf{zg$4I(Lt5z8u=DQPvcw>qmFGo$gBU0`LK?N}BoS!z$QCFAvNgYBTctSV zjVX#r`fPak<$?a)z>`_?5##vHOR@Mjpwh1aHD zHn1-?I0if`+2oZ{gwE!$QVM)?)j0^6Au#>1W7cdA)pbC1JCJA0y0HYN8I{U4J8dyR zpsna;kBkB^HZ{PKqPORg0Xaa}qV3}-eyRxGK=`Oal9@Z!V=)<&Oti;Fb<3w_r`#oP zm_Jl(Z7`pob+za_a=67`e317DFv~1cR{AIb0g7T!pIq(r!wMM`L$t?7wZKO|4pj8{ zn^TrLGu|mo6Cb`5l`e)U3b}rYVeyOuq(?i=)SPrITA)4FX|*ild@CLg0G{OlJ8z!D z^i_b&#QI)HZ)y9o$CfE@yMG7?9)Y=BU zU3&r)2nc^O@t3cEe&D5mN)Rcg6UQihWFZDjtb}&sL&5&??iwxbQ2tYYu9anHP06}& ztiH5bKFqp$pytN3)oLDqnrpUwyjMwsK}(t5$7LYRMn3Z{Rj}J8Q$ul*$OmxU2QU$^ z8~=Mb$m%@En-BxcOm2kFa5 zrP42pyHP4bH7Z9i^jhe0$~#O0wPVt)vNK4Cfzip$q?-0sijy=n6= zh0a;8c=9%j{@z3S>y|`wS{|4lw(^LtyecItvO zV!$qKpS5}@8()&RuJ@5W7dh74uSBhR&sjyrsiqnIfuzbE(^D1kxK1UWfEo65(dqJt zWp9*04ISE{C0&!ix6*Q^e3FxXCTO=zpd~9QT-LCH4eZX(Br$Ii*aQ_G9zUSZo`aPY|s%njntb9Ehi3gK{`JwfN7T1OhU zcX-AL__X>P9lkcAaP`Q*QW!( zCIxKr-$IXueZQhTV1XXXbAtVvWPYPRB95`&du){#A;&Gi^+utE20S1klL@_b8hgSE zy69#cH>JD!G_)d z3^iH{e4Q}g_Qpm72jQ)$+J;&$7Zz5L9I(wqNFq z5Oh?q)NwfvJpOcnweXs0X8SAx6DZ-7J*1Z_8ndzM__r3Fy(kWfdLp^h18R{EBi$7p zh&NONjnlyM0t*J^E;Q%_HUe#TfZ@wg)0&9whN+Y*`pGw*sS|V|?&U6IsgtHXL-(h%A`t zE*^|NCkGSrS7E$-(CP@iwYlsmgI@!aM!2OxU5B8wG4V!;R3LC#jjagdrLD%VYZsSV z^XCGmK#B>~woQCvphHXK(E|QA8oNo_6pONvsiyJ?ilQrOmu3j=jnRKXaJmL|95 zH3)-++h-OlZwJZk@IIY|9gSq2K!cYM_u;K!(-?*LgNG&o62;@k39IhxtQ~ z6UuO_xBIBIS3Z=ckw1Lwx_XsrMM`DO5#NCT{2=c8^`RxXqG*u>#-(q4L@e%8nOnJo z91){pu)(P}arL<4V-3uinOcd0+aVt9gB<#pF1e~(xiBW}sbO5Y*A7xWUrf)CjmtGDZ^+=~YeEYgG6dy_%$V5d_5ab9@;NX3zRcy=rxNm=!QsL;~#e z$wm{eU$e~fTCq>%NRA362%XoltPJR&ml6L=LT%lC3Ay5cBYw?p6eb&vS%l~txFfYu zQk$;DNtaSd9JB4F-y;0$bt`cNrh4FyQs|BiYO9wy^Zd7)V_lXYofF^}`7C0{2Mt1d z5TteTJ9A?mcytefou`|Y?Y_l=L8^_a zcQU;lz}W{H(vqfxM?c$_LvSsQ5Smn_C-+ILliw3oqnM8OvUJQyI_T%3$awEn%qc+4 z1d<|^39MZ{Hu=HyfwT}~t!zLWxrVrRvFrUq;Hmp0Xwtj+WKF+CJAC6XRweR~!^PfD zJA8}7N{j4}oGzs**>vz7lBNfGIq^X==dCV?Ef9`37nO(1^DY?P!>YrG-6&4mzija6 zmRElCJbb8yPmiXN!5s}gcC8U`+qkKy8k1SZz(MLO-J~~$jes)9&Rw`{Ftd}GW2KOe z)~Q`5VP-(CThfD|Sm`%}xFN?VV<5{ZgKg$Bc{<}4EdP;qGsX!C|1HqQ<>sN zL`I<+s}FEVgSWAagI42?&=X0#9R)MBtMcy<>t;hpN=$nF|bv zj$g#I9~v}7)Ua7nj^ZDJr9Oy{m;%NmQRZ8Rp5q~rB$BBD_AHvm!gOC%R(#Cl6F@vU zaw-UwAq?rnAf*=I=rxI!Y_0bA0eMDA0J2$Z%(>e2O#LX1?;W0xTrn-JLIZA)A_;ivY7l zFxL5>(Bs*WB3yDmn2jO#Pu%gJnB9L6DLL#gh>8emJNwO8YgmfEw_i=a(YgQ2t@x5eMLkxS@J_{abGEezdpy}f4B3C^BJ#Q%ADNs)#>(#V0M?O z$W$J4QR91Rl_PRi_$^o@`A$^|kJ!mCV_(H+NolFq!0M_Bz!^diw7or15^e)(4+Iw1 zed7HS+#c7yi4idz(0NKmEh5sK^vaU2r3Z*y#A!uwq{7IQ`^)zfuyA8_m<3l9NJ#vo z#RO5@kN$+~Hea93sQda|l=AHX)?ir-m@i&%M=2-LLB<2oh)7|i7mrwgShnPQjSY5y zB$@F666!T>H?Gl1uL)8lA#PW;6#%E-{#K@vgqoY0UXb(IFIExsB@OA6TMk>u6EdGA zgAi~x6{1W4hw0~U3Pn1$A1p~X9{vKXs0d7|AlU0{$72Ij#zdCLc_Y!kMH|yt{*Ted zf5jZ%pyk%t?oP)_GQe1b4*;oHFQpLlEY@wW8(d5;(yY;*i#k%L6gDrPkF3T688+N%l$q7U?nJquRIRz`C#1$DZqvUq%B8bK3 zbnHeXh0nlO3IOqpdY8Sd#@abR3%#u{?b)I(OsG}?&ufNW0o2-?9Uh}#sz0I8^ro$t z4>6>%5te+pV4jH8Q2c;ofc_}|Jn6cLM#>l zW)#zH9zKT~_op3G$AHsQ)2nhEKL;zfn}yo*PD+yV`ClfKj?T*WaGGCQL8!T{F_Nst ziRWn*zLGxA+1z=Q0x_?M?fh&Vnd{yxKNG+j@@0r>y1Kervr@9!{7B z0VL?r2+vCZS%mPxj2vd5_5Ti`Z|~|le>LkR!tBamjZYXwjq;!|Q0%2Cz9c^=qB}jD z;2-FZQs!^WVTvvU|4RtyAvf-piswS#6)bB50s<_Mn#b>h6hP3UHqPo*O$P5Ag%vKyPj4}|_?0gRTCtF=A=@!db3!*RYiSZc1M0lA9% z7U}rE2i(VS9p6L)V4;-X{a|q$_T=P3xPpa4hRVy!XXQZ&lcwrjwnLUAf--i1#zJI9 zX=BRrGvSQwcfl}XWZ57ahVgyzMsDDx+=eB11dp8lQPgg}94P$&fdmT7;GwWJM#8Qa zlKz|@A88SnX8S9{FbLcOo?aXP`0yZ5mmAZxcXXU;L^yJpjhH^%l>*Iu){9aCP7tsG zl&@MbVbE6q@<>0b_)E?OFajYWKXT| z4q=R;m~t!T9~2az4YC!~xXXV-C^>Z=qj_+W3$%sa-SfHa>8T|} zr7JTRJ#7p|2i-FWmfqHShCIEiq0wqDY z`ar9)h>pCOo&wKl>xu5ufjQ`P@{VbnydGlL8Rg4~v=wav#46 zJrnFhn2-TO;`isnUJ=%chV%gfQ6cq3L$u?`_lS?OV^wr0ele}O#O*JnRAB8VBpCM_ z%^$F542rJ=DB>)(5ogfAlIy5?u9W{(+57wRrv+1sF80 zLwW7yO=n9+!IL%{OyeIt`W>6iN-pfUDv9M`3^Sc7=)e7oy0uisCS=t)sUV{CI{ZDH z&6*}BG|s}$|B>;iW7pyD^$xBpf(=;C5dSZz)qmro|01Jfa!JVj0Noe|!$BWbY&3#6 zL>}8;2d)6b2ITKTIgGQWmwJ&XQT%4S%zLK#`;+^KPXO9n`u>^P0T5n#DCprxF558R z8g#Ca3 z&*2L&NqU`GtA!@z3C|ha<>!jtVOv+J5CPInS`@Y2u>gSRFms1K{*Sl6M-V>A2_)g4 zzDz0sYaE6b;4UO3c=Vau6Bq#gy6Tcj0UANMF!u>9pdJNAlE6)BL_Q1|Wb$tuv$_Hy zq_31@&6yy11Sm>E6^(+?o)z5;E5I^vNO2svvC{e*%@VTBl2Q8rzzltqfFJ-VQbz;Be zdT)|+N&S(7P!G6YFh|hlw8`CE&BCow%}k%rLt_zKsJRk)dL+s9o|oHn6%@_a*mw;w z?x`5ILC;7p8d&#$=7~);nC7vgQpHB~1xS-}s(-0@z%JOWUvXeCICTRC4}mC zP+<0~oE$drIv*?+c12NaCnqLqoT)rKj+Gsi1fa{-V7edy5vxw+GSKV7ro;sRA%LAx z&{Jtf#J@X+{cvG+Opt$CPF~cgY_!z9#FCysG&^6~5bfVkiKsuSpHbJ4S2LuoEZ}Cg ztZ-K=zu|f2XRe-buug)enz+~7zRR63Quk#War`{XQxT*oxm#ta@x#{M6X6AeR}hic ziA*N1+g@UY#h?`7DU(NN%({2Qc4#Q`#=Ew^1mXf}sF*56*x(TZO^)8YVnPi`o^%ClfTeAny=(LHCm7Yhz)*cj zM2Wk8mLfN#4Um3>XVw-~sE+}X*E@-hq1vDM^OI4BGfbqza1eH9EBYi^pbJta^hTpN zFS+E67C}eS7+pvKxb@+?xjCy-hNXfhA8KG4ATs3)4=beH)yGOyRL?wtPzYn9w53su zV|uX)-e+I2Ff&~1s=8vYy)93Lx_W~qq_3K&!411VPv4AdFn#z&&Fdmu6t?WNo|jjF z$qTpuAn4Yrsw5N&=FZ}mN-er&wQ1@*BhImjiFqPGD8&l&Hh1sI!F2d)yEz`y>uMW+ zwAWqLyZ%6(Y_t3NhYWdi2ogrwySe&9$IZLxW)tOw`KAvf*|OCmyk9k`VDtJ%y=h=b z%!oykdR$IEEjon>M26B>llB1hd{d@=yuQdBVLc5NBVl0k)ku@%y0!XD*V-?+6xY!l zZJttq$)W3v;&Q}#rrxHzf0I)&AUI$hFKmG1=clfUp*fY_nOG3GG?da`o^ThqH?%NQ z>99io(OE(Y)93o@Y#+0O&>Qu_C?(Omi}%)dOt*&{NG@Bw2CP}eG)3A?o{82JKq%s8 z+EB{{SkoNqkB*0>h@SUxJ3=+@ueL25sq}&HS-v^*+pEJaK{xA}4Awb--!_MZM#R~C zcQ8lG*qlYQy1!ZAs8-1BaL}ecG+I#(U<>_@Nm`qj!UAx$Xy`nZm=Y zYYeNqqe=f_3FK2Mds$cm{|WeN80fCFH+SWJwj&H{X5NF;Jz<9?UHVh?X4`Ca93*2t zt=}6rt^cT5HP$)#ER+e~H?5m&S3mM{-QV*85<`<%K$7Sjh~6lK&8R<-O2HCOilX3L z%b5bV2eLum8FR@v-;6m_%u^f2W~ESX&hk(FrU$(5-IJ#xzQ)7Fsur|BE>h!B*6s1` zbhUc?dW^4sOiBtvgQn{ymb_^E2Rak3C4Ul5p6=W_fP=kRy168qm96k;;r)V=<^z zR@yYEv7Q!61g6RaqHivJiDl*NxFDQgyvVnF#9BF@WdbNBJ^vhhq6U<^Rw zf~_rBl3XWC^h<%5&e|XGs|AB5yZXXyVM7mYg)cAbUANG4m%g#nNK?dq$ZJ3RBdR9i zU0M)Y285N?VUl4YgM*j6GMs&pT#~uYKt@7f zQ!!;@Fg-jm$$W>!ZA1tr4fYUc_i62i^+jL!*p!qvF-hxK6$v@~VBHxh$Jz%Ldc1_x z1NgZ&mzEPuH6x7xay8>u@d2_}#%?2eXU9XLefoCy&9`NHIWSfoN$$MfV};HxcWNx1 z%jf!ZvUH8tCT&Og6IZF;7ltHP@Zn9fGMsD1@-PJtZu8ZGY};Iqt$6G7TeG#^Cx|k5 zV8Uv4gywfCKKXwrjP(!6t#$v=I*Bf?d0D4b*$;ky3#cW>JszNHzJFJ(*UjB&`6B|_ zJCeqG-p8!&Ct;e~qf6X)DkWN)Gu5(?3dF+(Oj7C-*7G9Cy2_A`g|78<<}Dc>_dOEecnA|}0wITe<^u%quI-8$jq)s4(XHQp&whqi zBp1Dlw|*W5k4z^tTwi4!Pdfj@=-|Cr*vQRh7nP{}obEfQ;!Feowj_A7p)NaBcw-v?T1OqrmT`uVKFexIvIznjXB;{xSXFWpVX(nzu)B3HBqWB zedbx5Qq$UjMzrO{puosV4OXKRKn_l}LOaGXA<2BsQ>()BRJ_g^XtBMyKKZa~D*C>t zC&HrMxdSLl7WU=NHCbs69mM>6YqlJ}Ui=`(L$l;1FcNLlyQ;>ohZwg-_w{I)@;h6e z;}52ZjLJPS>WcHMvZAq5W7QNHy1WSoJ2(j*qpo01QLPkS%6$2hu@NToc}kv}+9~W9 zyaF{NEzq|zcBf&hAE}PSv7Ms1~W)~s^zvoWbYXE&w z>*jQ_FCpV_D}hm6FN@Gof0RJVM#p*wF1PZyC9NiAz^jxH3AfMW=9hzVSRzm)J+iY3 z&}?G$0Y*=tatDlh-+-a#qvIwl*r&v%aN=BlNIkK%>8AX(2Sj;yuENcI;OltnY7dqC zdmNyFwg^`IxA-|E`h{;?{-|oT)>m0=^k#av=#vV+UNxJnSo0nP8j&?mpFTx%gyP}i z8d%SMdc*|Rd0he;Z3LCzUPwc|i04?ri%D+Bd^}=8nxLliypzMU+od85paQ6AL6VIM zkowyAB5aHuAE31>nq@5UjqcccsOKYdfqoNG6oue~`ldk=la7!fOlz}@juSRDd0(Gl zJc1I^gg0M#LSOg?S(1*^1_SAxKdW}f{dwUIXF$?goo~sPQfC=wUyn!u#Z>_D?<+s_ zc3nUDxIX0Kg#-d|_T(pvz(i84Rn#raI78P}CUw(4T@gdRM%1V!ys_m7SM@;m z(ry3zYMTUvlAe!e{_dtf*&QbX6ndBo=(1j3RnV!eW@niE)ZDNMiy_Ey3{dZ!ZSvBj z0HKf9K;^Bpj?eYvcZI8$6x3}Kkl6VGU@zZx0k+_Eqn*IC7N3z}FgS3^Kq2B>tF*@@ z9YyZJEW*;f5xL!KQUFndNnJ$(uYH2x9N4)U2!fEUQkV+XUK9#{g8Nq+@wY#`&poeB zHq8;&lsr8>FSDhiT?OL~ljn3C+HVR@x9=luPtuQ$$kKXc)@j^}i z*|%ypz}DflI!LBje++bJoZOnm#>U>)wgr1_3}nJy7HS zLJeB^bwz-vtr9IQ?X24XETaux=e8bhP*#IRE!Dh|b1?T+gWLgi&>)ZFQ<)#Jleo)x z8E%>xK(P4!qRb?HztrtexU`Oh1Eygib|e4!<-Y_a{);>pO#SBL^M6XT%2ND&7X-5hFslyOo&PN=_3uegdJ+C<`1$Wiu;WpI+3Fv5(f@uIdOUEe zf8_&a?)tY6Ql~^asC#Z(}OgyYaf7v9qs`H1H6JS zR)KJUbA0d`2aY^&p#1s61p5T=ufJcVWfhdEIat`)SlBthHEbMg0&E-tY+Tgfgq=fx zi}T-d_X}M2ckW;}`8#*$;2i!RxqyA+4${A!6a3>GRtmTWf0Ys!cI`jTohiT@;ODR0 z-T%5@gkZ}_$x49_f@Ku^x}SkaKv0m7kdY8kkdcv5QBfYE<71$sp`nxD;$h)akWx`n zkdl*A)3Q9Je#}HePEODJjERk%i;IiuDZeluhY$-V7YFPnaHy!L=xFG~7#PGHkH{Z! z{9pgvw?c4GK#qRF!###Pz=4CufxB;qP=S0R!u|RAt0=I7!XqFeA)}x^L<0$`uwgX? z{{R6V5fK3ayz33#halh};yz**L&8%rMt^s4$;R9OE*N%Ru4+)8g zNl2g2J*9ufz{SnO3%+?s;)SG?w2Z8rs+zinrk1vjiK&^ng(dWjle3Gfo4bdne?VYR za7bua+=uvt#H8epDOuS$xq0~oU%r-CR902j)YjGiXlw82?CS369T^=PpP2kLHNCXF zvbwgu@q2UY@aXvD^z8iN@(NZiIPg&a{`sq9|D{|wpj;0S5a1DzVda8*;07x=4g%sM zb|hRe6=Y)vyvH2ADEQ*BpUb|Z(r~^yAb9OK{E(2AYw5`$tZ08q_Ma8Z@BdfH{#mep zm1`P;4i5(&9y|_26mot=|0xYUBOaoG6=}!9B!pM2KP@+`Cjq7DdVKl{89|eE*)XD+ z;-?)(?zf~@AKjg-rP@VOqg77^9GYn_W=u-l?Nmmxhf5xN)sj;0GQ`vo4?tY0kWZWB zH4iApJ3qTU>Hn$MLn`~M&jzIkPWY0puEp=}*~DoJ?wfCKJmb$*h=qQZSBqCK@|`T6 zl<2mK;_berSSn0su;H;vN^y&q0ezRDFzQ`G^uc!LH+LGXhUSbx`P>XFdIr8%n2SzB zBfjb9K|-pQ9Lk1hr2$dg~w?lMg-~_~?&wvm$KO5S>@( zE7%E!WSGxBKlETMyt7GD zsSea`kHHcll3lDgZ=dfB!A2(LTRUXmQ~8;?ot%0i?2sRwOAbMU9=QkSQPjgCj}6?@ zcXARLgFgl^EV9iz@}GUeyk6!FJuT*3?u<1vD;Pp7VeS);473@PFm>xL^dSe7oTN9Z z^MLsBPuUI5OBPKB{p6uiRRfFVeKN6SLvrm4KSusXQM2OcFBdT>RX0nQ3 z1fi#}X*IIoNqmPbYM+_*d;Zf_g0(yDiv*kH7L;F>Wzf;*XQgB$6yGtb9-dI?ct^L- z=!yn$xXWygat+zh8o0;U^s)1I8Jxgv86s8LNN63r9Npq|oO_uRP1?gqXw#s!A{ts^ zvbX?>Y|$~@RFYjVX~W^oVU_3=lq?{F4^ao9 z^cqjwK%p0#-W{ue7N1c2z8#1B8NxT~=7YE^v3)Jeb zq>#rj->`;cJe%Yi3fCZX^^8B5E}goE*cS%~rmlDIXL>Gi?UQ~tIphHtLs}%-5L5GW z<62|{6JfzoA>9@Fx3ViCLShs-F(Myo!tU#6-j)ECfuQa zI}s_CZ_YIhe#)7OHMxtj7<2S@nHwuZwTtj2VIq~pHsuMEpe>qE8XQ3zk$|tU2F8cM zo%0ljyg}B*T;8&_`B4Wl-H%;<>^Nk8ly;m;Rf%{XPq;?U^QEvJ72*(oF{mx97s5cHN7kAD67aoU1KRj7|E9XR2#wXAU z)B|FZP5Jup#-369#uIi7YyH`1wX}ez*JG2tB@c#&rZK7Qz(LMqILQZWLSl<8!P8MS z4sJ!lMQ%qiW*FXUxDF8svx1r_Z=l(QJ7bGw!Z0KX%4yIgZGc^BG~Z379lG2J+bnB{w8mKuom0;$kl{lAZ_&? z;_92>B8jiemK8=1`A?2gn*&k*cT{iQVSQ_yFt5_RB#8LDe^Zg(j+JEJMO=zos(Fz4 zJ>gI^$oka3n9Ru$^{9EM!In6xAvpJeu*DA%V&Hl4a&TCx@!g|jizD8f zKydCM+oeK>`S0IKED1B94H(=phCE4o@%4jX%#7?H$_Y}#KAFLdN^nO~XtuQ1ZEEb9 zlO1k(LRSeE|A5DS1j~(=L!NjugZ!{L9g?WX6P0xvVK#vkF7##4I*{;HBq9IFLGb&I z?810C-RpVPSmmuEij4(A7S~>mQS482*HXSx@q^v-_FvA7rawQZ2v{Qbu!|Sf_6(v@ z)_syLc*}hN=9j01b8}l)5t=yiScxHV4U4PfN5TbpZ`tb)cRP#Sh18N>_lpZvIN+8J zW&9%9Orgh7?P$RlQu++oABFORUm4R#5BO8~$=qA{yO$gHyD~&3-)d&hOl{S3Xtfcv zCYa*XuT_8R8t4-DVK~LYy|Em<;a?_edQ=(yaem5=%TH2S5pMAv_l79WyQk9^3li0% zi=*aMmbNcC=AXB|FRER+-9qvx##ed%BaHsjga71clK#{}yNY9_)E%rCOFF7$~)SWG61 zcXP*n`f`$4n55aG!c(vt*c}onA0W<$T4&(Z1PKm1qUTaOix^DoNtaBYwBWmQF0I|Q zfX=qXHoednlz?#%@gb@~cDZq8nK!7BAnUj5=!KO^)cWq8xJ;qzlSe#dgUE`{*L^cA z{-;ipO|mIzyNO1o)o^LG{*1AK{G`Zg{7hxNYH+6k@pO8=FJ+qdoLEgo(%L?d;EOHz z4#;v-){4Q6QoXYdvkChzgVWVr8Z;O?Ca6wN`%Ckc=s@$cbPNPlj|e+F&;3u80?+OU z%fk(;d{4PGj;D&#Lj|MwVda!C_`bN0@>Xc9ky8M)WfAq>Iu zsc#h(WNwR>{X%gbr6fQ*J_kJ@&s*lS1Aia>!s@#x^KJh;X>-{6+R6;wOxZKFp-)0i zVe~km%cXul-9NM^rPOab>XId*50lx$#+6!6&9s~67kU{;!!}ij<0%IN_SC`^J1ntah28G!SSGYe=oxSVjc){w3e!GD@L=m3+9ujGxtJCK~ z*PSGib3*X>Hq`f6|8Y&8=+$Y5?$j3%kE+#r@2;O_+jtC&zl>LCYiyX`+1$M#O%I#u zE+!GtJwYxjG&J%(=}4p>N?C-9Q$*$a!u>s5M%pm-N-ehA_@_kaJZjg5mX}Uc#1n5j zlMyW@ZXwslsbOo%&6CyPcI~-b8idvB!auZ+culqkg&D>NQ{Tj7!>x6aIo0v=b;*4% z-ZhRsbCwX+vN$Sc_+g*+IOo)MgATLl;R)kd0&y-%A)`mr{MG3m6XCSY>dTl?#)TN^ zCN+6oc{)*>*F%{J$oXILeg}jv3oGA4YI>7+sF>)#w&d9mz&(U=&S zI_avVe;HOhc7UPwEodG}wTo-5PI59}SaA=D!M}$bu&!w<>-IR&M?LAeMO5cms8rOL z++%C+#J(yFd_uS4rR%m~Gw>u;W^V10Iby|Q=wkizI1}!qbs64TStpjst9!_6BaCyI z;?1y3E&UX0#*h4kG~5M7I#eR`UO7N%Z@GMuyPbd0jcUA5 zU9XRlU3BWn6Tf=Z{fIr0zbknTwGf+K0rG9TtR>wjx{=|FxVqk0&Q2;v=VY#bB*wrBR!BruyJ@ z$b4_=b6TndP52nAoFgUG1FSZbMvO1|h8XJml#^+D{?#89|oA5RBYsR4#I{!tGRF$ajpw8CF~p9@ZyJ^Y{xm&d()A|}anYi%+2l->=3B#uivch2@=%H@=JmsPO-bZN8OscyU%Dh%u5;3x? z7(Bs7Gsi_}iF=#8U!PiejURCy9-}1LGv>+&N2S-6B<;hJ_~>(^_Yj9{Sq|?bk`{&z zb!aYHA1Ap+RDuur!=Eqh16C=2+3$5L}E6k+Vzo><~#U(4{`Pp2v@83TON55r94=KN)?FZV(YAeoFX*f zzxI7QZGtTzfdN{asH{^CLlBkx#b>)_L$z5qnRux5nPQm(0jB zc#dz~-%m>FH|r~>^@oU9zMw1~GAPiER5xs$JsS2|xrf|Ad~zke+(WwMdbrcTQbYf0|eEnuyT$I?X0A7Ppe49=An7hRFY`gGU(%!v+0 zlHG}o`ZW5)6vS=KT6WI%3JnBDP&QeP*cLBWx#z~vaN-T+AvzA?o;eNQNLPtB5rnlh zyW|QAYeda>CZE=Q;f>8{!#c#yJ|e(v%hTmeu|?1IK$|F-pXXkk`DHBqP#DpyKp)B$?^QW3?4Np%l7ZyF{ z_uB6(+(-%Us*8sE+HIXOCA1XN)*gnkw0LY9A96j@_|dCsh*;{Kx;*WPP01G;XWypvBV=f=AQzjk@Rledc}~=- zjiyg(I9lKZtOP5^x%w#%S*+VwWo}VlWv*!@6c_4?IiSCO22Wrs1-?-bgKt>2kYr>0 zkt)SAvAm)xof9#Gz@<6q<+lO^m7XYLq7@Jkr34!?77iyrwT!w_;Zn(ijSf3pcQ3K3 zk)6tGZJSRBG>wX~Jx>ex_VuMBJeArQ7pU~Md99YeyPb(4z2)9 zpL}avI5)lJiYznVSN^JB`AqObu zrTiCxha8ig^~_ZPq^i?gyboUQQd_?-VsE{NylE2cpnP;;Y_p7(%zZ8Ytct7kW2O>R z_fsnq{zimm>RagvA-ICyuEXw%BNJrfbr_5irp9!_#hr2y$5Heo>tHcbnQJYB8Y5y6pvi*JIV0?ae}8$4Q{;}OGG>QhGL@ODzm7F|U?zkm{3T?9W zio5y~w}jh<9tw|#AbW!OprcR2^C1DSmm!Aj9siROHKv^8R#fKFFjI~&b?M#;Q3PMvwZ)#kop}dqM+UeZ?m88%a|4b zM3C`qB2As@T!Ma%?`vOa2Y=bLZlKfWz2&@z1l+tiH|fZHb4?X{T`Fp^(7joc@iEJn zKuGscu!EE+w3KUx3Ilcbvk}e5<%GuX@10^h83%7XR_44qJcXMw3bU9a*!55~#K^-F zr`xD_DNt_;H@A*_q8Eo@R@xFJ-K77770xZpaxK-8*rie( zH^0sqBu#uHU2smI*!**>QlC{zQeR%NssZi%?S=o!X39#V-QogpgFTf1U9$d3ySQ_CXS6LS29aiW>u(o-YUAuEzqsk#EUi#R zh?OlXrR9xaXB)=W6orY*+-aR5+QZ;DV!sM_GF(*36T~6htfo?#gR@B1R>pJ<1&-k= z#On0Go)8i^%vOpyXbVcCaQ4V&Ne2FJvfd!Buq0=Buzn*VnZa4lh0lk{R@WS*74 z-50`qV>>r;*WT`mPU2^CW9CWUQ+Pgl9OkQzmRK{dl}G7*O57)=|EwE<^#*b@%{Y2T zYdLM3erWjeTSZw-O=YZ2O&htfO2s2&npyRQC>_FtEcwrotcsv8MRyjlpfFRQFg^m1 zBLT+gyJr_(Qllc|P@+Tu{oJblIB`m?tcU&RrfISJs!$Q~Ve<<#o-cGsmXphau0(W? z)*q03bD9i$uo0|caCl(RCO}!X*btsBFI&-&W*~q{7s3g_;p@3dS!>1snJQbsP+WLb zR?`q9C}k>}jgEgA#sPQ61-Fi`nQxgQk}BF29?7Ch=JrjuA%JjznEgG$H}=s8HA9@r zbV0?7QmBcU8DdkmcP3k>uku>m%KUqw>98}ZC;`k5S#8-AtP0f?93R~-aRTNdYX?QD zwk8aa4hnzGG`M>yFui^yTVtRo5|22Pe8ak=uhfxJ=_=sNBt|ok>|g%m)a1^|Q0I5O zLUmx)G}JXb#3mc3^h?((@1FI%veBZ-24g#8C}I&!mbkCtFCRjofSQ{8O3J00dL3qE10w$7tbVjQeqDa|Mhr&uK99G#gk5J60@G?dpQTCV9c}3^Dgx{6Q$f$>SOG7tLLOZ|8WLdqLXhXZQ${{lJyDxj*4yWehXPyX>a|cU-Q;g-bv>6AGa2Ix!_O(bmrH{r z+MBt`53$ZNW0>2;J|DT+{_3dZCmwv`6OxHJ6g8u0To5i=7K+Sn2Q1sQU2`Q{VUSfJ zlSQ*b!+>2br5ZBVYRf6}qjQTl39A+h6X|A)u@(n&H&4z+W_DKtW-q;eeMql6KP{;a zgRC_oE*>uyKhS5J_bzJO=Vq~q2>bOP-iD)Ge=cp8+&Ur z2p@V)F$WxH&(LYnY0J%_u+Wg7MfAvbwCUgvg#Q6VAENf$IVfNC@*238m!pYB7 zQ0^xP-pBht-`9ki!rtcOq>|jv{6BJ}YG>~3X6$GN`FDSK8)qdmNJR#_3Dm?yz{Jkp z!x3s>=?qbJd2J0fp?+a!V+^&ej%C*c$sYfm%+$=u#1U%m47IcU>vpeQpw`aJP+MxJ zSJL7yEyVCZYJ$I0+Zfxrm>ZioyEvLT{z?8aBc>N5!2D+dJ5w`j2<%c_BUuUX4n$T` L@kNQak>CFZV{Y8i literal 34882 zcmeFZbyQqUw>}8LHMj(q;O_437F>cf(6}`2?(PJ4Cj|Ed2<{#g7^**0s;a>Rz^Y%0s>MI{ECE!1-FC~VGcq- zkTQ8{XoJ*@-AEmr?9G8T08)^L1Ar9Z4m5{=a9^7Hq~&VX>LmHXiiiTah71Q;pK6}B zVNF6g;#xUZed8;k$vR}V(MdU#PYQEN{T7cp>oCn=aakhh*jVsCkO=<#snu`s{;X|bE>@(PLRQ7G}a z>f~mDw3{h;bNBA_s-D2eKK-h6-}@=<@PR{U;rVEH1-_q2pIH)D8F8q)_RP8T@=kcY zuxsb`DC0C|i1vxqS4sHD{@W9y|9bZWqwn+b;B=fri?Ug_p^9JB%)&+fYTeVBvRoLkFZi`<}Di?1K2p?qi22nrqT2zH~Pwqu`Td^q^I7Y1fS$7j%J7Y z$(Nc;CN8(4sPmZ5(#f{ zGiD)6fHV@P%ZFVzu^~enQ1Ydsh)eEF2vE_F_@pW|+?7b^AL4b9gR^FB8j)KXfQzB3 zrWi9D%^|Bf{$A_8T3u`=MZ<}+GY@A=VtS`;++HY)L zd)RaCOYpDTlp?adWbMyd0qqPmQq|@P7*8bv=ryZ#nvI=Rh3IR)99UJ>*6qad+me1g zYFj?``t8w^pR6RbJv*Z$yfrFcy$ZTuY+iGHAae7a(7m-o>c69W2!a;X+Sem`EtUF?-*x@Xv9ccxoVhntMs*|fq|KLXm$3s%p(cMq3PUv!^2wM0IOJPF}3M}qa zqb=k>ql#{y1*CVZ{_#{d%gC-_Uz{p}-KJQYlVvoGb#PC}YJBiNHu-e=PMG*MU<{B_ zmDh}RgF>(L@RpYt7b7y-wG}VE&NK%Ttt$9$ z=K(i~U;U?2JjZsj>{ZQ0Y6XJmiersdD}wsQ1m_nPC(4*?f#^3Ox2Bbu(osdz*%=90 zE?>sjS~x1)_%F9uULUM(M2w{i9Y-5e3C&W z2=cq|u}}EaBqX#n^4I~5 zakWyvXNc0skLF2jZgq6cW2UxJZYj$s9yQs94~@`K+Hrjj3G63t>n|Gm>CLTfML!57 zaW~1|A`uzdvwhy0Z3`G7K!@VQlwatl>#P>|8UgZZrDVY!fm0#F3CM&WyEq_1F4LhN zTb7~B>vXcHSV>L|CUq0gI4ht3G=|Q9~6|7;P;9>r3YCXCBd;$suUd~u!!~A zL7r+zYC^#?wBcb*w9gZI-Q{dkhiPx_?Y6vEzcxf--GtLekr)N*=$x&hPftROC5}U3 z!nk{6mO(4FR+;i@s9zs`A5NoTt$ZPTIR1|Qm}Jzb3w*XR7a^EMGW(njuujhM7)xjp%)5&w)hX-`@1$nu7=P_`Ns^n)-I?8%{mUle14@kDjHx z8dEUQL#-Aiig_diFOa_PAkI%5+|%f{Fj58;_G41UeeSM7qpdUwH;}$|)BHbBF}8Xw z;4LF6j8uF2GVTW<6yMzC``KyCvZpXLD8RWnkK)Qm#Yn^x8lIMpyTf3y=y`ci%LH%> zng@l4xVE`_o#vAEsB5{w8BE6eSdxdJehl8EgDNYJp4;ew*;^cOvgY}h$SnSMD-FO*poM8!1OMWY)yw~v!NJ%*fJcL z^UADeEYe)n^}Ftuz2|!v%fN7n#dlDAG+JNa6)cI2t5n>-8XGirnA$jVluKxk90;nr z2pI{?amqn|K5r=IKtDUYS=ckItk8?U=-x#I-jW-9A0rlksgM%Nd}LnKxjfk zcg6^b<&k7jeUoZS>-0x2myG;9O+(aID2%=nLNduPjhp1xf~x@ib)`q@ZGhA#-dbXu z6=tpg;g5uo(1hDAGm}(TZuYvn)bMh ziqzXU=qwm5AAR(aHp6xMO<4pB1k;(U!7+{q{!tLUxRznw8xGOwFr}PHX!ScxYzgu= zNi2$Ye1m70BOW|Qhi*mRhxpzrB?Mi(vDi^&DNzd*I!BW1 zn1zTr3yx)2;G6SB9mY0K&pU=ja`?HRv?n>Ush;`<_=}#LVp~sqDweSrnb*E zuXwewGs!5QkZ~@7jL!?(DV0nR%hfCDj!0HKCmMD}Bwsg$aq-P~fK*z@8M|+e~ zlW%ulfR|ETRMiMcun@`kIB4{9vB5i-u!J8;7TN;jjy1d04aD657y975y{ zXByF;E5jD*V?tRxPiXjHG<&TDeK}(4bWj*=z}rjEvVejbuxhR0=L7)#yeP!@2=6UJ zCGEQv(>6AK0&GH+gUna>8p>g~%}?+zzol(}cww z>D~UUBFYvIE$4^-qHg*2*0R9+PHZOFXpb{5q5_<2$#8A%hKzx;5c zYt`x#I$@uK#JEizFtTi-jlvFF64pFSHbm7tiaDUUR|elgLbqI=8Kt!W37ysIBhd?%a{(R&a~~;WijcnXr6$@tF@!1wuOI!+WT@!06~x6SR;x?76Vt zL-=o1Jh7k7%v-YaB{jwwmBOROd7Bz-$oTMoVh`6@r*sWr6T+mU_JEEfE&}&j7@eGr zvV5RSow(qpRG!n7Rw(MkNUUf+u1k;qVz=M zVMZY|3uYwoO_1)Os<7OV;@8ZT(T=2e4l7#R!rfIJB4E|wsKxK!^E@{!VAQg1LQ@ZU zLZ(BGdu7tKs_tI;&6`M2A0Q}q0-pwF-5P#=^s2sGsSmQ@9ez*9c%ga8VD$OZ2l)n$ zdXG`%2JfZT6sd2KB7v}io|{{fIrvf;JdeQ}P(y5Xx#n~CZ(Tx+*31G~*%?~GD|>MU zlPn<>NM@FzHvOy}c>4J_ai)-V?Sx%S%!vR}Zi%W@!mD_iSHD^$V#Ff}*Ceyi zsBO76{3CG=$RO}&LA8xC%uGK_bQkl`=En4F@&NA=-povrs5(nx=10nOYb4;H*Es!% zAN%PpCe{_=Y#~;0*2ENw{3e@NYXN7~J<*f}|816aDFW|ijNO~rldtJ+gg$*WW&*+V zY+`p+#+0$zsxcZgCMj)w=!$s|_{9-8{+nn9LK^_v5jD>hj%IOk1GJfZ&vI=6uSqFP zX#Yl0#Kh3P6#wxC%i@_kbV#vY_P#*|vQ?!MO^&V^In(%Op#V|a4Twd0t`SltX@T6B zrHFLmzDWpe(LmN;Q~{i9)NTGrl!dR%B^*y zFkrR5$dwaH-d4L?Ejtt|z%hUBLr5s!0HkhKO>#k_pRh42g4hx@p&XuNj|{#pvlR*adr|g{L^ljRX!jhgTf6pMYWzlVHM)gN}2y&kHz4KP{D-9 zP-x*=KoKdYslX{SosPuc_u*s3e4{G2WAf#bot}wT5*8xz{B^`41-jN`B)zU({1Jn^ zSTV=!)ag<|?`?q-gt3KgL3&Y`q1{bK*52omrhDXvZpin&-5BND>PR<9=L}Pd}s2atj zx9rH`KPyQ?b73|}PKg>`7+GjS)s^^@|F#ooMDVf2ox2aEG165Z$VTlOmKkqtot_h; zAChM*jrLsL9?dGNqE;x$bWb>!0F3jX!bJ&29Hr4UpQ)I_!nZ~mGaF>0!IJO{qSPR1`gS@Fna$0l8lci>ftWR?sFX3dl5#^GSFhj@oI!9Q$7{URzUpXv)wWKn10w% zW{KEj{(C_a)xSNDh1iHw*A147!4(wPWP zu${GXE-uuQ5PNpzDz-`#0!7&89I{O#XNS+)Vn;pgrGsCPWm)XfU|KHeg9=yC$z$eG zDday`^D49l!j0c*Oe`JC%jdI{%O7=PP9rYqn_cNHu`)pE_yY!_MBiPI=2!Ykkp4n( zwYhJR)Y6lIrpp+`aWx2SrD;BxIvSv!ZN?e{D z3xvZOCw`+Q!!uY01LtHK!qb}#6F93HTUAUnjEwx1_|2ehv@##}n_XFH$S--Ur&tlQ ztg3Zs8FY^&j{D6iVBtB-sbF+AAOK#GMRQ@S>za& zV{6a1axp<#Qyg()e8(<9WVg7J*l;w3VI8XrK{2UYrk+62=1$NVM47Q<)O%ix2tz6f z7>$IxHSSqv^O;FLiHUdB%a3Pfb)R84wsK)R8ol$W@ki- zsH?kF#hXEdSm)@M{UuRspNVuKLtj8r2v@@@5Oky8ozn0InhVsPuOo+Z1>3syr%U}i zT)za)k8^3_yTYc_={2}PSUF46&S-bFHB%(Pw{!q`<>|v%)({%_Btkp$vT4oxx>O?hGyc?j$RxTe^bSJpGEVq!s@3cwpnD-Ubgy@If-Z!xRDx__# zbjg-+Cioax#zJI4YKjtFY2n|&oC$-73)?WE#)u)i3B!8s>i4U8E*^B`YQ{@hfkq2y z`Mp^41`fyjlSp!TD&hwj(J*N=oJPaiv68QY)eN?J9~$90}U^o)RLHqXMU5;Ev3_qD+) z1n(VR`2|;ijp2AJv>5Ni!EEXZ+by8?JB8S`5!BR00PqlhVt#&p{)y*tF z9MTX2@6oM1)>?tDHK{>agn|B`h&MYNa)OKy7CAw_)Oo}O#$onGj~Ldnj3kt7wp5sI zj<#82YHoT{1|$vX#rZU)%KHUDgJpqY20?NI-O2bf{0C@OLQUPMVSYNIx>H*y%lpIo z$KNk`5GoEX0XM;0R(HMDX>iJz4e{qwSNH2!&0$3qw|wzop0edo=<&tbgoN$g1Q|b=`VzS%s7z|OoIZq$XxgLTn2ZwM;kj4 zA~KlPF80O3HK=5yA56viLbigF@vy=jt&Z^ROA91mQffczi7?^16I$!yFod+wg5WkG z${W)b3XFaqA3X~&E|b+qx|Wkza5ze}lvfH0noKmF;mrH4Kjojvr{}lYFAMXn?=(JO z3bhNv0Zrt0+dpx69L7D7K+O97c!|(eauBwKAXD!9Ccpfa(Z*%GVWL%)2zT{HijqOS zTg9T)&GZ=>ihO7Sc0_n(U@EuWL+{jPiokacPb$ z=v3ZnZezWg+!oj#ICYl2E6tWBtxAfopWHjw7eFiW)5ALgo!v7@?j=)>@##tW^V%Ax zk~RnFxK&C|S7lH|kV3uLorM9XRo8-zhVbbRW_V1|E>f|r5+nH}4cJ%j1iy(ow9lV3 z@aDnBaQI^513oG!L3qtHFqww2%IDd8qVTG&;q0=GMoAMj7sm`HX|O2x%~ftG`dV9P z4OHTp|5!7u&Es2-h{`fp_~9xQL6QjTA0}ntop#oBok}5HrR=PsZsX=c3h|5qc^IW>ZC?Av znWTYJ8d+#JPHj$?TO&(qjwOpHlxbT4RX!I;dCATpG)CqxLtMyBMeOIocgo8W%H7 zc=Z$Vt%v0=dFfBhmExrb3IlS90`I>-Pr_PV^}BtB%Of+?5NN{_ML4XE?^?Yb!$&v) zq7%WIXC|FXXv<)0MbcJjE_C|j3k%C|fs9Pp)-l`c-w z5C@4FJ!edQJ@Q z%D%V$toLC{T1Ej%Bm2N#2ITPB)Ut3s+$Ar3n$0;qvF*}A

J#(<@XPfruL!*})l! zh*(;Gp(yBchx~G0xWh35I*#WMX#VZD=&1QK*p>i&)?)VX4kc8$Z8^9twdwK~*Y46` z!wQAZdI|bpqkG?+b^LG+<7Ya0!YB_#M{DZ5Co)h&E?O0_`BrDH4LTszMrGl`p2SQi z8evRHw7xBUQ}9U>&AK!Yz8u4{^H2qsF4rBZ`)wzh@*Jp!z%7skxrVKfZ*o??I2lrw zPg+{6DbBBfH>%D2V4Dr0H8YD%!nSBu)!dLepr3!V<-VuezRWBV6%{&e^r`~wBLOao z-`?J2$yV8MLCDVsRFhW!xhfs{LH~wW`>W@M9XsXkWOQU$4mSlbiKs-XG<@cAlC=*4 z-WZKy@!=WG?)3tYQ(x~2*qsnyM00_w#P8X@8S*P<+Non)^J8F4NDs)&HBr`A2$F>A zG?eHzbWsqzRi(~0uxQi8IJrJPauHDWxeD&&JJ?&1Nk(4sx6RFv?X~W*+tPw8=ICxX zPO!je{8lWxyNnE7m>+a49Y%K35|94V_g7aOTVW8~?Rb%TKb)Sl6PjN5G8Wm_70^99 zV)MM%en2sFV!x4+tmw#rzs-D!X)-P^AI+&!KW2Ur#0;Xw#fV%|jCo{GIb`dSOvint zxD8fkui!UDMmH5-qKouarwZj-$d&zUOCwrwF~#-?c{q`epLB=$Wv0%a3TL|Uf8%M5 zO2OHosX0-yoHn}|x+uYG&afGN9b)N(j9|9iIADg!C=h>k94qS1&p-H-I$kaSf`&z6 zCZZyz0aB|zyqWCT)!?16(G}s%Z5wm?aqFCo#&n|LAIq!@1xUs{#arp)`EXuJlyD#M z+u9w1B&dm&)$>DCSCQ_(NWB?6_x>Wbx!b4vg@aOMg$g~rU0qPzQskmSW;A(Y9XT_} zq61XO z4!cLjA`E${I?02>cbepVv39gP*{l?8&?z_gUD)dr2+~mB>0u=&I;P|fpYppv7<=Ky z?XgjP`+}0Z;Kho2?Ai~0fB^8HJ~;q%0GYl%IUpD*kLoW1FMgBNLowPAle>l1AHt8j zCd}5i2y1!&`Ovo~HBobmX>Za}?&Xaqhr`Go^fFwYcn%B=^qi0wII2+q6(?Fy%T_xgNcKQg;CNS=*mVegh(pjWMRboQ_V8M`yuIa9ns{DmO_ za5i-U(+9M-BYnj*HnDdB36hh8`$_)+{z|T-JGk*51H4}Ufp-R(G0TE4IKcM<7GP#$ zVc}t9VPjseume&2eNYD*7w5l^>EaA{ZTd5B8#8le@TC5X{C6E`Sw)q9>Acct z0kn1aqwy;JcS$qTf5|zxINAJ>F*9Wb*Z^$76LAJ3v;GHpu>QXk{?ps}1OA67J_&nM zmsb>72|@DL3GkWOn*z=F{(R&#=HOyA;bCDkGdDA1<8&EIGB3S|a{Vqs%9Fgw^;{OJJCnNQpa zU<|T%(y+I;5hQ<|6X~n!A73C9_=lDADcGADzk0(TVSw4Iqx{2F#EdPN|6B?%|5w8Q z4FC^n8&}mOf8M= zECApz`41oYXFKpeF;`vy2RFdXgoBZV#e|)agPVtwk(Y;;g^|_RjDv-jn~Rm*%=AB^ zJKLLs+>D(7q84B$0B5~ zpMRL!|KJE<=>Hw$zs2wW()GV|{kItSZwddeb^R}0|1AdoTf+ZqUH`w)h4}BSF~AO7 z=(&M6zQItQ;o$E91OvszRb<7*|M}=Y1O!cjPlBLKuL$9HqnSu@Y;^i?9*Mf&HcnbwTG|IL^NsF+4<`M^CbYdbf^0Ja! zC_Scw3?JTCKgwdeiL$w`xcsw2nb25L=e-a$G5daCU!1;{fbW*RgU-(kboT5_>R7a> z5H8K7bZo^K_eh=!E521rNWOSS% zAebm#Uy$y_!mi*(IFPKOB;2nz(3r?<i?n_76Zr)hmU&3hb>wU|~ zo~HeS3$TitCnZ(+Xh`YQB=?ClB9m2M_zfccK`J6x@QU$NoCx{BYu5h39O>&FX@UZ= ztBTh$El_KI0<|h^dgd0n+4mU=V&MvL{Io+u8JL)uxw5IkVJ1g&FXfa_$}lj zos>RO8Jw?L`)HO-{QBBRx7*>f41SJfzdl{S2qy#eE@@6-ZLQUrI*F6$*=8rJg}aE| ztJ-SKoK+9iW;|`qW^E}IvL3+9yMNr6$q09FCA1~Ot1^;9vHdmwQFY`SyDXbuF7$-9 zM-?-1$j_A@_1|}&?hiLV8~1)^t~X~Cc01OeY7kib#BJY2==@7&)xJMYn8SN;^3d=3 zZns4qml<}%^c~J3(k^p{)81r$DALZD5gr#P9S@&t^DzJl?%jwOfJQm|{BnN=P@(iAoC$^$3=f?L;z(*wd)?Mgl5eP`kl$jeQz@>wKR@1S zsg39ndfn8l5=q72dAMALC+xZ&ul%@LtTUb47W}2KO}uJiVq#TmP;WjOzR~;rX5FWI zYqne+pg!`+EaOD0*6@ng`5v@Cgh_q$)o1(;F#d(zVmz7cK5yf>)}Z~M^D4L6C-g0W zFW_=e)#P^4c)`tPeQjgDT5qB>wHBAz5cwNBa*_wdOjN7$4ui1Yv3|mAFlF4+3K&p~ zS~0yrI_IR{UOr8+)nP*{zon%mEqeO<(7ET``L_Sn;rv@MK95|jCYvAAxHoo}3T7VT zp4X#4Hp2iJ*?a&io^y+p#kz+$VnJQTMhn{7E6F>BH9X<#L%d&a$6IZen{pOv3@+H@ zqB>$aaSmIZ2V#|Y*7p)9CZtGsCgB$%-x3t>OPE30ujeTlByf|e{JMIJ7JwssX4flq zCLP;1tFR3-c6G$PF41Y&kPd%-p*6kpc9>r1{$~)D$LP2x^FhePZj|qIQ#OrG$89Gl zPctU-4fCfd-i2xu5|xu|K5|NXp#-fG$$Lb=aOAN;`}<+sjv_-oT4^_(J=7E$&BwL7 z^O1)qtI52w+uPf;7(*L)wKa7$AxpIJ68Hu5hSYe-4)@u$DTjg46Wa;a@@U1%A#F$Z&Dpyqd-mh2_UM%U(J+!FDL zOe(w+jaBpModx5?iAym|#()~uF1(~6?mMNHf`WYm`No~&w(UszT; z(FHtrK(x-6sa>r#Zf1?Gc_}j(bhvk^-svMdUpYC&|aiH_doseDCqFLMBCu4$9SiX|C54UUlB-1#I`r5&@2K?G5 z#DxU~nGM!6Tug(Te(Q~}gIidLs0kRKuxip=ccSsttC&HC1RI+ty`jjRG=OT_g2C|c zo%cpwM*-H7Z8(abhH!VZVX~KiIm$~-o$f|m!?`?43**`LgYP11zxi<08a8HrcK2LO zYaTpwTl17B6!LBf(B#uOWY((zWxyRztuJeNeCu5Z^{Y++ySnpt{swF22}i%@pA(Qm zIIQNEdxBq@?y@wOD8k}8K5#aCIc;p$d`u=e89uMecNz;MQ#u-$5091`u)l0;Xwx5Ma$0xM>s2(I$1bJ?fGs@2RPr9fo^pTMhEM{=FZqo2;peWk?GfkQt}B^gRkEW*8Um_Up(| z%7DQj)v0HvU2uf(Qv*Vy_yb6^BDxK90Fu3dA>wx>j8{x)7tR+#@xR~Yl3=TuD4&i7prqR6fe}1gH z%JqY_EKX8PO)Mhvti?qn90@vKI zRyWY6)utQXUt#n-KYht@?mIl0Gs z8=Y2@_m11c*nXX$r~6C6&5UJ5_00TjdiV}J-F>Oh5Zf6~9n!J>D}r!}u(#diDRw7o zok7+M6~%W2w2kFT*`VUP!(w{0a?amRmZtlDl38`5 z$~qs;&y(>@Cv%Q1YUqAwo3_#D4iKM~s60rIiOo&RHQTRuxdP+O?TCQB)y!j4)+j~z zIguQ-g25b|g}k!BWA?9j;fI+*YBx!KJuKY*)snY71;iWBy>wf&!#RLKlAB%Es z4;IQPn(SAvL;A0@l9`VObvdo}qPUj@Omf;L4UGmXYkJ5Df)7|g|b(tbvCE-4*9RjRE}>wFi0hqDNuLO!s1vo zj2WaV-#d7nwSHzS=h`pNS3jY@Raeebe8+`>j*iaQINo{?CmgyQ=2kD&W_5k+MN6%e z1wSX}wt0J20T$|rv8YLrc3Jn8w%ncomp$TMt|z`?%9-$UO{NdmLT`&wZUlGJepI3f zsVZmohN1GmuWhcFXWyTxUvPbpQIcy-y5Y6B{tZ*!y+xg3EuvxpZ76lRIUC3!d^QdK zzMe1aMm;Ja&uJHfjPT|05Bhv?nNwi=bU!Sgh*L4RM2VQEN!Ak;wN#?X2c6A$JzV(~ zOJ5I7SLx7uKCfPPSK{jjc&)=M>|fou^JP~$k};ow`MNi>6A^)xX{aw+l525>#G;70 z3zfl&NVIv`sJjfB3fz8(BOuQOL{_WfZ=64MQWgfaR8)O`sff?XMg45Pg+EAv3}&8b z*L**!H>8#cL?4qo(M_;_53sF|^ubT`8xXV{x?W>X=&3GHzjk2MU5IohH`D)+Z4qG+ z?Y$r$g;%S)+vhBXV#w_0Kr+l;Cm&^+pIWZvOR6Z4q>^o+)^JMSwq4WELEQOxck)9+ zLl;l+9fyW4SEuJC)_OESx4dTXS{ftUO{rR@Ui0IH&Zjs%S{O_t9q%y+wmD?oxBX2( zbFS>8Ud~U)#^b=`Yezl{DgDDUXq!#uro(gRisay_NTv_bZJ}2b<9eT;bcUqd{2j zxDbx5%}qnYW;+Azbs?W|+(8nChI?~(GD^-W(T1tc;ODIv0xo2w`5$yUbtyY3BWV|? z_>XhMhg9a*M18?%CO8dhs)rIJubJy1ZVIb+KrXY{ZgrR{q;=UBid_s|mf0hf{)29n zPN!$EO@;7-wmjwqs>KVN7pGJOt%8`0RKT}_rN%WZ0xp|Jj3@?TJ>cSVR;sRBx5zbzx)6us@9-$XQtUL*V-l(Q!MMl zvc{Wf?^97RZ*Om|w6vWNBwR#Jzgk-9Q3Nt2sA&eHw&=xfdp~(_R|19f+Ef&@1Uy-s zTqd{<#sa&T-O2g%O1qo=KnE5TS>Mo8W?6^rkB-**5qanJE}vYr%wRMNY4IMyv(rZF z2Nm#D;*uxGNLZDHN4v_PzJ$407M?7biY)lGOAH*sgVE%YrYXUfuZ`1190=gwl)>?( z8kq^`=(aS9V&U{M&Ia!8&B!U{Vq!f=V7~WO3$2?eP!8wXkKh}vJ3T(VjX~Q~sDcct z&?+}sGDbO=@0@8dE-V@+;wR1phq#l4TBC_V+Og#1WQFdR=ZC(;??#wiIXS~iiovnm zA(^4C`WT!_1k4$b&ljK(is4j-_v94hde(C6tgL4l8{%OG7K937@T~-fHBKRsn_mN< zNWguxw6uqN3560u<~U@*MNEptCA>B~L2#I2GP*?(Lf`~FkK)@Yqgt#ON19_tO(_U=OdW$2)uCnlB%VE%sUU=m8aMUn1eMU*5!T_8U zykir~1q?JD6z>PZQ*FyT!~$Rv6}VW&79Q5TeZe1}Q2_7eonC7cxVqn~?ahq4Kn$@g zL1oN@Wvv=**2{yr$}V#Q*Vm2T;-a>jjqEtKD41TLq>4RLA!RUHjUe^w5}=9ED88B{ zp6tw3^Qj;j_7xd;r5u|$kYK_-u3tnG!OJNrjbn9DdGCED6Q_8%K6WlL%IzxITW>ze zKQ?G1-W8_^=HXY7c2F^#y5EXpzBySw$Eh`&@bvs^}N-e=M-+3Q} zt6Zzom^t1%uc0JBbOB)m zDbTV;m^xVCNF;MxE)6{)A)y+%kg!fT5lsy5T`Zc|v{vR9kDL!&6SZt|=-?F*&D2is z0*s`t+0VO+-vPp!+Et80F~#%&SgYtig^|fqnAJ5UB&C`rvz;hE?M>LNJ-X#G5%It0 z04~aK*iBAyT&?+ry^TWKyi9O@tkS7&1BP){tc!Fkv_$MpK4Y@l4$pRPZEYEGWv#@1 z?1PU19j~-*?vCepty0$7>USG+z$JlwF=xe))X%rheWNG0C{3a5H~1Ude&3ml+Oo9d z)Aglf;Ww6?U)SI-2YB_0a}9ZRa`HegXml}svCPAs-gW>exsU-&xsUy9c)|-ZF~{Ee zHz?R+Hu(v=Rb_Rsip9i)L~`ME^|C&mfI}W_8p^%X*P2>b)Foavo4%&vs5AwImXuTB zLZ1mZ&MGbCTX%OvVP<* zRtqJH!}cSoik;s3P9H0hmhD&DuBJD7!>kAT`Z|mgGp#ji?_w{&aRSWjvs^%+$+yQl z_M$YabeA6qz0zv}&i9vxab}W}&rc7_s$gzPYvG4UqJ1X3oQ`}Po{WJEIkPWL6 zfNg#gaatdjculak7#|lm&GsZmFxPgy$!G7{c3Gj`;ai}?tBeg0XE4o3A&bShP$$fG zx$VQo;70G9ddkl0S&?Ek8-Tv)tXi`*vh1Di4~`Ui&COSL@G#!^;w*qoiRJVu7LH# zpXq}mJA6KP6@Q`2*T)@(g>Jdx2BR$`n4kO==bibR>`xk;?jp%BeINIC5rm&_FIIDb zyOp9r+<#Vee5&C#D!$`R;-<#nMvhsLd$*3nFNedpXZCd$+XI`F-djUIR>;cAx$b+& z_#QP|i`XsftKm0q%V0FE^p#lIgIM>`uK?9vPO4xFSN*>*O?Af9LQm^a=M+YtvVXG-==5G zSSaN1_6mGyYD;=50Nd;MOv7!&&%BP!DBmZyPuJ<7b!K)8#YgA43P-hc0GqdymzkNF z{2#+jTIQ}YS`Qha0cTC?iN8|kKl7>Ui$BakEP3&d0B}BS3Fq(yOj!g31cw=ki3QAK z;Der>2k^m~c(_yW5j|0UUhu2p?}($jH*X{Z9>1Y_AY(3%q|z}8oh%5m-iv@JIvaO& zx`-cKpndT%#Ytd=IK;v$2WM2{i~;dqqScs((cid6zvE4WksxC$s3_4U7GO9Q*OkSQ;*~ZUgAx*U$#|1k0_#=tPM6{%YSkQdxN4 zAw|&}TxTfozNQ=QF+SwAhXSLQLgDAr-t|u}YmXjsa&kM!22!nlFVEND;Ma$(2^~^v zu$=UV^Vg}r)+~P!FCaDj`$DEDBP%QGZmH4Qu&%D|*!)MAkC)$HVTAm&pM+k^dpmrf z=taPOts{f+18}Xwkz(Qg>hK=r>7a7%gxi)%$h$iPxMqFMMDmWTuT?#k;aM&7TY=+K zD5^)5Wc|)&J!)=_UWda}i+mc>_JRRA2VnZwm?RQ5&e}2YFb28w1~~k*^yn-4*&Brk z!oJm{(=wEhl4zPwHU}R|&x6Zuv&Q)zWa^p^w^J)>L%S!;=f>Y*FG9>%;8AdOyWSKM zCJe|YKi}@-k|I9bMR5CceqSK|@f~jMc(|MYF!Rl9uD25Mq9_ofG-~>-k^76twgse4 zAp@XJM%FX@yN4lGnzI=?wUasaQ8C9;mV*x(=Pv^Z42Ie<^(_o;?8Wgl+k*^hMWjjZ zBY4>&^yqFMzUfbdb9;A?051r4JqHHlCAK{^TVd&?orEZs_{uB&1v33fT-M8jCLK-= zm3RYrD9FjzNLX!dzZ;8(Mv@u%03!1fyE?ttXCiu?#Ext$s|=_X2d6bN(X`$h85M`# zl$jC#!X?#g>msJ!Pt_|g~LXVDU!*dieG98gdfR~kOC@oxGuW#J+rE{rFK z{t#+fAu($#LvlZCyMAlQSuTmE^nyqc6xBRkn~_H`Hq1mh=B$>9N4i;G$U&>P+2A|2 zi4(<>OA%GVakFzTe3tq6@>QB@3}R|_S-j6uR{hy0H`(38Xq+eiRh&{Kh=FEgA|p$O zv$&P>#<@p*{+SpcYz-+aTt{|uk?8|Q_Dq2iP2M?LZYDB+%{(-U=PWI7(2=IRxvlnX z3H3$5>Zby(R_S@Cq`A9-p&x7!W9PaRgC(sbxfvsJ?A}L9c5k=p`Q483Xe9x-Owj>o`J_NU%W(Pv{q9ZBJcQ zV_aM?oYnhg^OX?6p14>p2mwdSrV?HcWXWi0_jMG3J!N5UiE38cwg(Wtd0fz5WDy4F z-6m42W{O(HV9JC4O~N@vAgUHrYX=X>ylJD=ELs>UaYb$OwZOyIZ{O$@rcBtD5(UYASm7c2$ZfC?HamCK9@|fYPPcfbI$+hf;XkUZ4>%>sst ztPv^Y$?Kf7-asBM7heWuoFS!hE(Fm`L#AqbT8*nBtI#44q}47{dx+vF^NLk|OstOV zwAejx+I^!~*CJ$z->qT z;}(^VTqCIiQZlWp(I{C9!_*^@VW}*8Zu~%C=0C%#+Y@oCrW4)x(9MQ4Sq(pKt34!C zHX~&}Y~{CQT2P3#0h7lE)Ft`Kp0iczROE`hpTlOhG8t^er6I7WPA{^*{U~i$9b!yF zz>H5r|4^Yq<4LA9M>(K=OoTBXLTfBI!{_^G847Z5+X(-&9<1m?b@Y3i>BuKD!rH^; z89_FLlbk{9&=1 z!lc_Snscbf_@w*3vNoFFGPaj@C&TC{P_F!C&rd;p3|Rv zbUZcAsk^nD8EIl{f`FcNmc*U);bm5g&FcdajssE$epD~Vz6%PLg{DF*u3C2Gf={SK zd{hbx&R_8M;Xk=s-kB7N1?l)go%xpa&*V3IRu3!BJGKT6Li*fZ5%aI7b_zSt&+vu# zd^&IX`{VV#lhaU)9aDuxz)d7f$I^m7hrSPk-pW+eG6vyKF4A*fh)UXH;x)A^qOJ3Bm^K$Hm-q{z8B8e3lSg;RM?Gh?}YjsmvOZ8zo@4$yeOr;?mWmj(y_l?PQ2UqKK z4?n;f+>5Wpg(hgra3A%xqY{~LaNNno(Hmzr$23me#@Z`GCa2tWz7|J$i-l}BZ^R`$ z_oq$1v~gpL>!{7zNQHhu(F@PDS5mWF%Fo};^hg7fJ?B4qB_{UN+68JN9(tABWswHn zF}A)INKj8X;nAB@-@Sfo|_gkYn|8JQfa~ zq|32>!;$?H1ckZxMPTX*-Pa9%q zfwf6~E@-ZBQ|uupAaqx^+xEMcja&`wQwWmL)^8y5?>qlc;{tCoSh7n|9r$GPrJh$p z=_vF{p697xOK|W@xbLr|0J{^rKmo>Y&-^O9a3?RZq0d+}!oAC16;Sc7yP9*E z+B(cFH;7NE{AWkT(a6EUVfXzI_UHQq@1IlmtF{Yfi2(N&q%p44sbMiTC!Z$6myN!R zh;y=trsyDGPt<+^o`d2^XTPYR zmZ*&oO=3rK|P^Gu`q3& zV&X`@(vGvJ2m_n&#QZihUp&mmD*raI>JnC%XUU-&3=@jZT~qs3;Z3v_Ot^e?FTFD7 zoOpMJhepPRLeN+lKD#WeNK5IkH%?BF!+we?SQc3bGUC4?4~Yz1s(rM|vqN;Tep558 z=v!Rv^NE}+`txKVdA?2qBi|CvLVNe1#AK}#95oE`S+1|pMh5v~M$4~sFXXD{mWOUZ z+8fxMN#p8@y45frOH%?A^TA6tc?EaF_FdZ*?{dTIPZl+as*$c7k7y*L~XGwXqG38j?-#iC`t`ptrN zI*5`2-jtZ1#=%+So`atfri-&Z@jM%$qYxwdq^)$0*+K1v4311r72I@xneUWGcQXu6 zLh_(}W%#~a94-{l8(|g+qEHg7MAp=HwWnVu+41fffjM+6UCO0N;;wZ0m%O|oPjb`x z16mz^S9B`_J|lTqewmO@LyB7PV~R^&{6W#_O~uPM>d6zlKJ#H8M8i~$U*?^E7F}bI zlRh};TN#}K5qL`~IQ@#OeaVD|=@*tjgdghdk5C&b+DVvy4|aIea|=L@YZI=n)|!mb&rlM)h{RQzJpe)gl56;k()*ajm`7wcT;DEs^ZY-sX3)LI1N<1u+E$Gme)_m_sui_Sscz|ydLJM>xZ<`~YJB+xCH zJep7}ZBb2lfBIcZf0svh)hc64EGf1hgxEoK7`@s;+=GR{a`*PU6CINlQrBuz z>v&|+Pv4v}uUn#UOt1I@C6C_~VC{nMGqNPNCO%9FhOZ;)7+zAbQSo<>|vCJ zVZrT=-a#e3YQd7lo~Cp|68DmjCuVOGQkkSXXl^h0x9u){*{22B@B8hhPW&zRAV2oe z(EgS$9PmVY`sxYZ$Qid5}>>ex5=Tjs&s-I!vbjHW=>+R*eudpyJ2FLFf#6kK7uc+>-{|JDG}n9qHSbm5MHT>*Sesw#q|RFu$}RZV^z=eV!)N$UpZ2(?!&v zeLJ#&Zn64`^}VOKe~T0giK8U?NvR4|x1z3O*U+92UCAI)|Fl)4D4(?>MjJv^?o);R z&3v;PrQr!J^!f*SX+Gxt(r)+Zz#YDfUy3aBT-dC(;MJ(zHp{sd z~&thm$>e!`Nc_<0MCG?cds2MwOJ&G!Yaju;KQSbf$u14w1qb27;nn zTn~~$c39Y#te(&jEemzNgePf8Om1oRV`Nc;MhJJgVwVwdNO9RWr)PYAk_sghO9ZgoDqRzM-qPqKGN2iAy ztruBtOA}R>jt5DFg@vnNM2r#K^lEZysq(o4SGhkE2s510WXniIQ_fvq*sQEp7fpbv z4{{T9)#Qt43T%%>l&guDmS-)sW`AO3tZ^5RUr;n41oP!V2 z(C7~Ek^1fEv|9QQzNo|3Ob(SxQnh!;!?2Y(U|JO@jjw_Y)6pKHV%@T_<$kIxFLHGA z$#>;~nCfC3o>6}qy58Nt>qYxtvW(>u&&J_>;hUZNh563}dS|s0S+f(Pic5?dK1Y9y z8=X6n1bS_o|GxaFdV7amUJdGl)$$plgXZ5kORiWaJk6~3(-=**&F5Zx0=oOmAu6L9 zUg9Cid!pe8pM44To&{|MGI@H$uYdpdxxFr2%h(JeH6x?~&uEW9?y=tYgfH3b6bN&} zODgtVTU=&+rwUKfVVDz?fB~K_i6b$OZ-mo#!$3UZEv-R zGeLv|^z*GgcX z5Sz@mh9~DB)xFn$J8otg3X0oMu&z@a6V&l7f^k2!q50T0qwyKE63E>PYQhto;ICm^ zXPK90f6{sTiI7lj^Iu7HKhO(>wU1s$c%2K4pRkz%@muU8!+Q#GubfHLBb(#t*rjvX zHd~F7dPRqAwwh^I*jo;}UMnMF+Pix~sw*R1J&2%ButjNL*79diqvGsjOjljUYfTAb z;UkZQlk`+1mz|oh3SSueve)acUD7s#>$6Sp7~++ohQ}aa861@i`jGcfXi{o<1Jfmm zmg{6)OwSZv{b6To4!W4oymazg?21vVrM@(a)Owuc7Wu%N3n(`;+M-7P6?EM8Y#Y+@qYf2~?7TnIJ4 zJ86_-mCGO~CDqS@C~bLCLY}TIE+ELrRy=F-rTsO9*;s>8sdE0WDSQ;HC}`PRZNvz^ zrc}D@7~Jk=MsD#|fn6=I3sbL@sr;fP%mLNsd%K^-5pEWc^B3YSX;#rX9!p_$uhU!h zQpVwikxo?J-HiI!Br_wfuO^rD!>*dpQ5{ZnTr!rM02(RIiGGWtcNR&q9U=P!+F6xi zCP%mksVb-4QL}I1RnstxX0*9)Gh{-1rMHA)`ZPhW3z=ghDSgOya02%%fDqDA@G$iau zOcnX()elk?4yefz^=qNid+|4OAL<(fgL1T#DoFe>%0oXUsUXj(qMtjTFcc- z@x7z@;4^VCG$+22pzEHDNoo&a%`X@6Zf_;<<`j%>x)5?F+`07M`{gWNdL-Ma9eup^X|NIJ{ne55b-cl?drXz|o>Eiw_`zMD01I8Xqq|J?Lw8|< zJ3e6)XWUS(>wg?g9dj|Y?Fb!b>0&P3yc$u5m-w>0jQ-6TmaM}`SNgogb6okJ++!`M zP@lGc*sU66t5mQctc{0FY%Co)a?zX%ndsS0!U`DwxU*jj7B+$ZdE%EQ5suG0u94?D zYVWHw$kM~V`zR0HqkQ`^p@(iE0yCau&+U4?k}jsijLHQCu@BHYv1u4 zwX%5Ur_hYCQRupi7X4PRdcB*>XHkEgu5_>&yP;ne?EpjT0$~Gn75v8pFj{nI*!o99 zk;iCIIkNDipXw=kcSYS*p5y8C5;sJJV0zwS?3ixhwB`Y?04#84?LF9VU1cO0+uRb8 zRGT;q$$rmhlwUfb{88Iy%Q3{n%JPguA3ol><&NmfI5M)g0UBib+Pm96T?;n}5-nTZ ze|EdNw>TBagzT>kKQExr?7eAFWwcjU$I)2e7i{L3-4xhVK8um2ur?>2&Vrr}TgxtV z{nm#Elszs*8;oC#mrKwv+-KW0QD0{=fR{Q~V57mb#VKI7iVd8Vo0(npc2sgv`XqU* z-OgDRs|D=m3*$2l^*K6Kk7OZ|wPIt5EnfU)Ljt(5S4dY?bT~|hk_vbBC~>O~Gq2#q zf96Y@4C3bCG4~|3R2vChXP2^J9llGHo=1b?UrwJ}q&@DK@^F;ZCsvenpNlPNRc))t zFj?-AgoHnCNih%5MFMX=+_nlNmNPp=scaF(Llf$s(WR}=G42G=Z;w={bbD)*Bn9Gw zGOK&$f9}8zzf1D>zsv@|BXD|(4q2|_xA|&+e+GPX_{!Gpse{6V+|*6ZuyK}2hE6dG zm7+=~YFTep2Zg6(*6>+2PBz5JZN!PS3ROf+TE&X}vrJvmK5gTk(_RLWLujWO1+xet z?cL4IU>X~l&yJJA^QN7lr7uWsRA9`)VF{5$k49B?X0gHzH^o zh!m$5KinT+>3_!{D$nnrl=pM=R6G}B5Xzk^jCCBw#!1oQAybaJ(K;F}awswp=5W(Z z0iN5R-Z3H5v9Fmr4#z6QOCx~kl*MwPG7EZJN7M*W(43yKtd~#$XPrr!Kn9|`s()xz zBEB$tG@PlEJ8>l!e!Ne>18t=RdYl6=*Emc!v}wMGAUkD5jLL0bH*Oa z1|LratWfUuxqmq62(ux*Eo<{&3?vr(cA2RKYLGtREOVRw=yo&BC|6h#$iyPut58g< z?@x047z>*E*)z1)-@miMqJ6{LsRP$+*!kw?W&j5|^IIR%EzY#v?@89KqR^ruqA8fO z|M+P8$J<%C8_Bavqg)ET4$N=zzjfW$K{HZ3ZA<;o^2Ln|oMmx@A4{dWtjtV|Dgv{5 z#?8^Vy3(`5tw<3IBl5szqlbWw795Az+F4J-zV21RD9pW$8e$3AUVB-B%H8HJ=)b(QsF75vIknr@WsBVK<>H>{<~s|v_DZn6XT#P~zbfp|hPRRCu-BN7b$#PB zUi^H+T-joXDP9s8jG`J9%E(LYoL5a8 zNvSlXzH>MTT5X#C`D$R9rY&@X7na?O>?b9j{LHw*2~b&kitU%fBM@K6Z>Ynk zEypE;M(^wpcoxPW{Cp`1yzUy>xjZ+A=4;g^g+-JnF(@c#!Ob;Ps7@l%EgjW~H-ncl zEIy6jTR0z+a(jjitkL3^&5ny-r7EOuG92Hi{sU2HR0CODsIb!Qoz4u!=33u#EjsI0 ztGMYzL>c=GwnaV&?@+Q;w=U0*CO8WyP-?f}*y$iTn0%zzEk`y`E>_=YD)_{LTFN26 zbE9KrS{$R$%xkqbw*BkGqWIBm=+~dW9D!|$i(_quzqD?%P4l0K)peOy%pl4m9~vFn zLaAkUH~0z$gq}Ec{bUgty-cBK`jH<=V2V)UP!rI$*B#Y9WNE*;+ujBijydvbfGPg{ z{yGs@ocDXA{*Ix`VK7>$)fQdaFP!`#>;pgBzBQ_H#Np`>*`!QHS12Mxj$;aPcVnm{ zelUu}#G{xWM|bWy_A_kU3(IC$a`vWzyn2pOucwaRcDi%mV=M8S5ZT9U`s%#=D|XsM zv*w3&QmENKw~lT~5hdZpE{|DG8*{bU`|Pij;RXT>)rL#ic_Z;2>XReVu|fyj9o7g! zOc!R6F#E1Dn%-tm&-^AO5jq@*} zONHL=kf4opLCX~Ir)5sM^qxc9eRXeRbhAhYPlv-Qv0NgpPNkcDViJJoqWsoS_-;2 z#jrj={Jx%&nRT*?3^YY@f8@u28dW*`Rb3UUXOAre`k z18%C+R5V^b{G>De^-rZt6ybx>`8vBW%^tB>p`$%^*4kNTx$JaHTe7kRyU*NaUFHgP z&wH%vD8q<-Dc?FL1nmCVU{N$VD|_{bzIyPs0@EZD`NI6L7A$RvsO+NBS9`k}a`SE4 zNoY3BHv3lf{l(Y2Pq%J-w9UEjP#dRot3~fFFpc+vB;FD~ta~x8QLlNC85w;sxihrd zBC~tf6@e2}Rrg75uZ>}Lz;lV)2qJ2*%^MN?39x5h5!soxM7yXE97V!J z+L!%|>AONzv|E($m#OzChIh<{xTj|m(uPP@JL(xn%`O-jH9GF6(a0cvf%UM$pz?Vi z<_8s9vVJP+&sFlcwcG2#*~g4qM!zSqehY1FIwK*Gog%=5nZ>4X*V?dZ@8}Conz&@>NHxtiEjRca8j>s* z0c()V4|^f^zWS$)Fzat|sL^`j*XReLc_F{FwslEI%^d?8LC|bnyPu|fGpr2!nn~!_ zAF74O_hkYrp%=Fve*#(PRW6w%ZrizY>%RBDGMQK}xCEbl!L*1n>)W1q?M#2`>6j?; zi#@5MGb>?Xe^0JQ{ph#;O|jR@vzAf-uddtdRL%Mao4L87{=PHFeu(wLCG9=({O{b| zGMnFTU1vib#74QpILSLrCcfN%GC3bs4LJ=2_2+t(mS{PwO!X4T{!1=+7IwQl(tyS& zu}Wfv6G+H66XCH#|3P$C`ctW4eX!>cqReNzR3@hE;gU=*GdgAc6eo2M3J4svMgSS> z-x`_ULnB4bl5UF%5qcbrmTiHP58Ax9!|!cAKYtwwa2x0UHfJmwu|aZ5^LJPiIWlG} znqJ-%{9Bys-Jx!4-ta7NHu37RrH<-Qv;UY{_Ux#!;5rYSX4`q*`R52FF_A+hM?&CD zAxH9Gw80th+r(J#L`2k4&mT@@F0RbM94XU9dyRqV7N6~%X1k*uCR^iL-`?u$aNi`R zi%E8*Nb>?snW*}WQQWsibqnd36Ny0up15}a^m;MsK#7kXqb+TNZC8CvR-#VAx-Ml% zmEmP%F=hqpOQ&V~q4c=b|DY@#NR5h=PlUfAmbCqDsMx2ti~Jw|V-j_&kK2#Mc@-^TTst9(<_9S7&$c_eD)N)ZL5eOb`U%gX~EwnG-g zQ0Y6<<`i;0KNdFE*|}5siuoa~*nv!)gUwNWaoJh-<%fRmSfTi0QzqLNtX=HHp(tFF z#IoQq`I{AnF&CD@-RTJfL%6D{YUa__Bz_NAKX;?yf=f}x!nSZ*>p#)XPKy91BCe%7 z8(-@)lym#>9^HAP=iaAkpRGT8CoBEw1j7FF`0@W0gv|PX2}1rS(7t>p6$>9LKeH|Y z3wBC@K-hQyx`wve9>BE<5fI^v)!fzV$h)1En4EpnaDmbV()++c_kP&fcu%hB)k*OI zz+PmTC&nL)=FSA4YOE7`ZSuTHew<0s*Sif|O8Csq_QJCFdn+KW|0={?!XdML0FIQj ze9e-s{XniM4)a4@k5hMC;I*;=@fHh^Cner`ZT~`!M35E2PO?Wq%nAZtQ>B_V-rj)6LC|pWpPG(@uTq z$R)$^%6o!OVW5~D%-0b`X#u(Dx`-I#mzAc$j~&Nt2-=Qu3k#uPPe59q>DmA!gbAQV zGKD?=E5v&rLQJI^uLGgg4WLi${ zmU?Qglr(X21QHParJ;4kaq#EZf&6z6OXalXoU%c z?7~51Acl&AdkqLjO9BazO2xZ0G}25t*BR4)t3rTWA~u>z+I`dp$erfvG~c~$#Ugj6 z@IY2tf#Sz^O1bD7U%yzO!A!Rj4Gd!T|B9@G3c0dYjji$LlBYN6N~3|G^-7MWid>u>)%`ku@^yjJxsqT46}&kRUCBs! z`txL`gpzFt$W*=xoNRBW`**Thv^Iy}VWtD3vv@FH@RJvu)%Me6uzd_IR&xBxL(ux) zYeD}mmA$jtc@R50yHv^-o)3q+^YaNjA4piMYT|@|oMDbxfF=nm5OVz=T@WYKCNq9_&n3o+Wz&Cc z0Tx`X4bJ`+li*8sxjEk4zsHrr!T-%|DKe`FoRX3v%x{dcwzZE?`%bH!fI=}Q-2Wa0 z;6Fr<`Q z2vA5HveAMR`_r{H^M>~-E6!^ZTcT>WBa8#3P#J&2Dbnd=4b8CcyKBaXFyp}mG{hfF z9u1C2x*z`o0^H9oY}Y@rFAY2yiO&?V!U|mvYu#0-$+<#k;K|Pn?E=xhz6H8EfJyi5 zZJG}`+sUD=8Eai`eC;#%a2+xq6@$}+B+Ce>)VquvegJCbg+tFc zP#)f8iu?7sPrARWqGsBeW7f=(H2(6Y^>pzX5s%4E=y=Zze3LV0cB++lg<^Bl6Kk_< z@JH~EOWlcvBc=g4*FE`=s2)qQe@IRa&xh9^v^;u5yGDrQ%inxp4}rc)$}Z$7aPEEA zNKrLddxQ*lKHbfl02lyb=-Y7nO&QYwn15>_NzL(BEr6iXJA$72`^Q{UTqPwXSfE@? zR9PG_3EBTcC>?CXzO6=WP$=G|#{PH`{=z)%*!V@^duS9j-}y(*O9x8r;=}2;8-=~5 z0Nhx+sYZoFZ%$ONHv8_q?O7iw?tk$;^5D_;7a0m9Zh#OT*kE|O^I5D;D_7in@Mb!! z?b`JL7%x_te+u>8zb?;;Y1%^9=l$OoKG5~QL+UkJ!r4b8Z-G)6tsa+Scg!RUu#f)G zNeufEkcqErP;PwpX{Tsyvh@s}z$iV7z8;4gl91T;2Z*%-8ov8STXR-O<8-fGj7Z=D zt!0&ofXiigo!ua+iVF>dbFHTUKycHLlt$-!%bPpNYytq((xne-l8Ni5SSfM;srE}d z;TJ$1e1tg4k=%K;=n$D!-SHo);@M3J7PK~-l28sXTnZK8z^XCR4*eNfq40IFkDtxI zMZN~O#*0s0YzXd0__qXbCQq}mv6*frej}s029}l)r;Jz{>x< z0cxx?Nq8=GU#iG<4Fe_!;Nn>UGMXon?2;P`Wc24E@!)GYjzsXe@4*_u@UAl8G5P*< zx7zIMTk)*pYrJZNtT$b2;Ip9B7Xl_nN=C+u%i)XyWVJ=>M%LeyX|}^%7i9puGkc@> z``f>NOxIW!KpLX#{XF7M#^+R zGYWjPGka!C0UYi2grrG(3ugEe+kUmPaT-9Vs8IhbRYu{}XW+a-Rh$tP{H)&B_L1~- z>?FX5jt1i)2>*d7WfHeEaDOT<*Wu3O^xO)<4?qO326Mgip25izDR4c>m1f7QXt+x> z6^Evts~;2udfL|XdhXm3f1CJgj3$ZSe%MRtwnf;7h_3ol-E_Nffe~}~0^ly7hJ&4+ z21>OaQvj1Hvd#OcyCUy+-&$FD$cSP97SZ3kckyRkAB-E#7X%#eF1ToA=X?O*ck20o zQafVB264r8^{O$0U8|5<(3y8pwCJEivV^=^c+6-a%B<+?yU?a1)gwe%Be(>)cGdozunmq^8i#kSlICQ0as|5$8&^&FiWyrN2?nkcQY$$%HDTRs1n?a3S=z#IeKy-$`+0uvc*nsOP{0p%=izVv$_ z_c)pTJXAIphfpt24gRM+Ccs<@78LMYI*m8G)(rUpQWvU!UL7|m9dp7dghkYS3jk3@ ze!xT(Ejg2<5kC<5KT+lyPzFJG=*B+A#s>HSG86Thfl^>nAjEeEsr8x~3QuY;=P=uR zYFO!c>=Rh36Y#=>4)NoP-n@FayOYz|VHMmbT;L(@pIeF$_6H>_Cu)mtwib()l|``~ zWu)0b_ch3dO4A4PDvAx}gg2z)b7Hhlz6QN34V|y^l24Yaj;29pacJbca9fI5;^?#6 z=WGTV>21RY85tW?A?Hx}SX(reASKfXkpRYGA7%)v(Ja+fc->rNAluPS8-k3s6+f2% zb!wo0U2U#lVH&A*5b;S*KH!YVwoGFgqD(1{|nzKahz zTF&xXU;;dJW$Y1v1meuC^7Yf>yW@W44Mq)~>klhENwGt@mIV&_2!l#k!-s~utV3PEF1#3vWzy66Cy)~Ri5-;-A{0C zaGTe7>@$F=gTks&24@~7j@r5)O_NfX_sMSiRo=m{B79=G+tgyyAXV_pGnSU`RIEOb z2+i;~M>U1`-p>u0D~3|9!S#_Mbf?&M?wuTEU?REebQ$15o^6Mz)7+kdtEaf-URT&< zq_IV%g-Kj&9!u%(`0j$m+ftIJfA z+k4x%aNT0LFao@T8r7}z{G758IsX>GYXy%LWr-+)%uxeMFWy3!_jH3Z^HRavD~+To z^G(r-xV~@aHNQ5cQj}`9*1e(*c1Mohr-6a%+p4X8O}!NvOwFhBWrf0X#)IVGR?3Mn zDgX^$0rLigWcXWK7-IyNqV$5B_h1SOdYTxsKcPNRtu@c4gpu^aS+hGsBb@nHFZ3b~*>n9uUbs}RQWaqX{t!TxGx!Sr++_~1)NE8M zCr-LN1)ww9XQSftfQIWwT%q6fG8FjmZ)W|K5yq1$aGv0+pl^ry@oZiIDjPu>fyBI< z{f0z_f~`hO;dJj|m^jf?>~I0x=CBc=ZijdRVMSyr@@$vXQ2u|ScKL5z4ED!J-n&+b z1l77BN^(Z%6FPzqpq7u|kZcJbltGUO>SclQhPnr?OZ5>YS`{$aBn(NfFC>8xPC#V` z8Xv$ZpI+N{dK|}6izKTHFlLuopFxF zcB3g+A(gs}Hn7d)2n^fv_YEA=)$Kf@q&89t4moP|J+tTb?ST~@KeKFmybuj8H!LlC zRKw=aS>Y+-?yp;MT^R>E7}8Y5~xz*eWp zE=u1NPY_)@T=<5~?Jr=(18(npLnXDt)!~o=fJW;T`l)YbE=bQijv5)lTLbnb3)xL2 zQ@$bRX}S{`tG`gySQ*4D{)`CH<9C$SI^HYh1Lk}1n-YMC&pRhbQnMUvJmM+TY90E| zv)_aN71zs~frd2s*BXOa_~`Lo77Y6#FuDP{_iDP{f$y0)imn2-vkD!dS>TEFnDNof ztOAH-E<4TKXH``69QBhe5bEJcV)F(-9F~NXJsFc`U}nDhl<@HM%P$haKRHwp?%4hH z*n=JIaqqh(iraP`nvQfL#*T9Z>E3;Xy(58J)%urW9o-+2Ud!>D9Abdj0b5R?^Cb)8 zrG>s|-9&|jloGJP=;`SU_H!Px3rb@SIsUSPzainXwH4!=HRpXo(0Ofr+nR4|4@&^^ zQ1hIZVa0fQJaHx*4!eF{VtD|Qx>|W;8#k_%PlE#I`^n%2LDMpjw9L8q*hdE`zjAF1cR zU<=ZBes_i;O@sd>KPVp-b&e3S`3X$_8rCADQ!H1?fLUKYO0QwPOt0c;8lSP~*qTZ4 zmE=X^tCN-zBGZw-h|7|nQ6*o-$JIGV?Ph_&%QayepgBpVA?~&q{_dW}_$?tmvzpgT z@WwCRs})C@jH4Z=8m#U?NRBpHhfikp(R(C zzb^!p6Hu_v`Lp#p7WJ{TqzY5!d$ zfPmr8D*5GhAB-nh2|DyyOm{2Poui*zx~Fuj4rbh7G?$7TI~$By<>_CE1r7juvU&v- zji3Cora7}8T0wzZ8r-`&I|e-R@n!6OsAye^yx6E|~}a z)9z&rr?9>CKbD98_3D3=GZ}aOuVep9L<1c52K4_ljQ_7c4*&n(8{xunS0s-Zrc~T= SIsobH4OK-=g(|t%AN~&#&7O_` diff --git a/.github/logo.png b/.github/logo.png index e96ae1b46a83178dd30a431163a4f2ba5119d931..06046f5552644c9be65eb6688363e14dad25263c 100644 GIT binary patch literal 36399 zcma%icRbbY8^08?H&Jqqkr1*Yd*s-gtYjrr%FH-UvPU^~c64l#y(uLt>ttj^WgbE} zMn~uP-Jj?C`~ClWUOlfTp3mpLulu^**ZUgx^@%ev(xIo}rXeFEqt``fnURq(;>gIz zUC*BdzcG1DegpjHoV&WAIvH7Q674@H3h*<`1z~1LMizX9jOe)IOng4Y% zvW>fBWQwoI$T%P8wwWq{|8dX6z(V`<^c4K{|NoyOCbIwkKVVt#FxW!)Rb@5!f!EK> z$ec{=J&ft@yX&u?Jx2feF=q1knTZfoi>I?&d2u~+ay43= z`b~nB9@uM!BtqAz`9g`|9EQj-$JfjC;|uFIz8jz5YCeq`s`opYu^GEh4ccXc_0CNU z&o;mM6T`!sKNf_@o7p)qMg6NF?i|iAPl{~3%Zl-1;{M3`akp&5RfvuyOhG575*_?` z=>suaG*}(=?Qmyi6L<8R{V2?~?+U-~>c=^+n+>tKjdo=@p8w7gQEOpzwZ&7%Uo_`r z^;~YCL!LU(C^-+M9ItfO%TzZ!=e~wZ^y)Id1fBLAH$IKQm20}@E*gF zdqr5*7-q?c{y1YsoX(ihi;n&iIFV!a(#w;1S&~)UR``rp^@z7{41Or>n6b|z0iM#j zu>q5FBh!(Ny>w%T9#@||zIYBtb(TcB;eY$g3}c%mXLs=>tb|9_8ZrhvE#fIEZ*zfF zIu^6WgiU&_K1_r2evY5xtR%Q}*`4GFHsN=f$GZAbVvnZp zNVvc5p~C6k{}#Dz$gcMQw|Hc^){>@4u%z36Z0{25`c`pvfW59|_&XyXmlR_0&YQdb z&rHMdABYxlV(lSKZ8yYM&|#e`HyO4x35j=ucH7c;w0w##U}G4E5=5`VkYX=l%*hw; zzv3A0HXc(Wgx~MxZyK-{c2zEx{^(4V45P-3_K#gVixU#I>Rlbrh!cCEl)s^r>4WGd zEI4#8Ispj`8#8mcetXUp4yy4}Vs@&k?`6Dic#fC#SD@OK_Rjv6|ElL@+fyJ1iSLoe zo!J=tu&kaDZHA(1Y{xt0v$%_u(_ffgCemSQ?B`nv~e->8E#Czq`I&)><5; zzV(@r&qF2}k8CvG`sZ?%9&0`I_#4%^uT61c#FMZMdms%;z5cflUGf)Mg}_h=@u$+4 z3z zw+u~qq7kdvPw-)ETV5}jsMFO5FSFBp$)l;UREPD&xA1+;;^?sZ4vD!e*uW{65^c-C zcNRV_IYfb}laV^1+-Z^YIpYx0g33lNWD_T+(~e%I0edem31zDL=bAsU8?kE=Ts`sf z>V#JFZwu{L#L(Zc-QI5!_RSb@&EMG_APD)(>Wz|dC>qCNHkq)2<~4bAxm<9>qS4a8 z)0mBZz4*lE6xgFlH{-kRKN}pb4?|*u2{|z2^08k-qTtw&OJTwhkU{jpDsSKgzAUdn z4Gz26w@d@{&gibxfQUABEbuAwZ=;#toW~+*FpQh5D;JiQHdb5;e#%54^w8+8HaJ7U+V$r$ z1;+U8EfgyzscXsV;#8*YgYp2x=C5wBx2JgPXJ9aWkA~Qww*mEHMk$4A1da{m4Ad$s zIJA(#gVz1%>*07`k9tAufW7pJ###OqJ%T+a1McR1uexJK$h6D?r#=n0orgY6TXH%9 zqN4C$fE@GZYbN`|8)fr@RJc^^SD;S*n^T;16mQqjlY%`!_xjn(mo)`^=^Hrz#^3rp zn1QEy$)QQun5CD~SB;>+Q6+~lcAGitpQ@;n<4RMlXjL)Zp4@M&X@P9!6iJ^FLM)nuRGPRaOMlJ? z&!9u_3VfpBvcjiX)coZ9$Se1EdC-lsoGcu_WGeuCknrjjIZv#;r+&&@Bn)YDaK}pp zl2?X4+j_tJCnNF1S<$PP3cw_j0cZ@VmTDtHCd!?vGI<{1Xl2(d%PSg*|LF1N+fi|} zDt^aB60Oo+2vA)q&(sCGlUaB9Hcc{G#Xn1`2)GMlS^WY-#wF4_m$#TaTgPh{UfUSR zTY^g!o3F0<3-5?s3h;y>hy5NtuGfHECf-U|w}6B^jD-^$xNib|9jF`xn2u0vPhmzi zP_Iv0s#KTW*Uz4uA>F>V_L&|9ayyi7U+mOAvXGqAEjKs6c5^Vl6!!f`(gcQ%MIJUnMaTrJYMY#sIUt7M#UJjn3Jh#CZ5v zIu|Ka+l)`{U9JeL}xAo(gE5SI9kMZ-q-Um=P&Bpko*xqe+sYPvtF zN_1;+bzMV&94q9=Kj(fwS=+{u1+~7Ic{M{gpYR-Sem@Ds$%T?}srRFFxk1S(Z(R_M z`kiaG#vybVV;fZ=T)op<*g&%l9QltKtAp~|OZ2{z=_5o8w-vzDV5&E5|C6+}s)l*7 z=vXs4p;e8LHR%$2{91voOW<;w&jH-LdA&ghn+&>sGD4cWld#p;^K$d3L7|ta~#hHgo)b z$Cz{+jQGPdOiP;s=)k)?Z=>xDPRJ}lzXpaBQW*94Je7|Rg41C+#}|SM-TUaUNpB5Z zUQZgPgNLuq%sIgR6Jb$KfNJSS$=IMC)BDD zUaMe|^2Y}hTMD&Mp{--V=W(gEl8@*lf(;GrtRr`0L=|$<2S3N^lVcb+Gzo<=wtaHi zM6xJ7N@gsl396R{j?{W}^VeuN*TStH2>?fEJ<`~MQp3#Pp%C)U*%=zz^Me$))Zr3AWc+2Z2J`K>D7>T&f;S3* zdg>rTj$`DBh;(c+oS{6?&bQ#j8W&o{95n960NBU;PvxhU-n=s%;_T1x^{VITaPrpA zCRQWo)Ct0VpZW8dh$pXTFa?(nnr-Nrv8X$Cr|-M2$Dcu{{^fTt?$-rTZ0iybYakdO+;JNPj$eM|H{haE-w-@q)|o}Bkm0`9MZdti$-?s709 z(c#``gB&<;Cgl?OC)vKQ8t5=jgK)gvCW~`i-!_bR4fh~|yh(}lIE+d^9RGC_{gnw$ zboZxWp2k;2!H8acu%DUB4-$Da6Yp3@*x9dua}l*^-CX8Z$gqJ{1z4tmu>48H?X$@k zVLG$mZl!lwj5vOi#Y+GljwXBVj&Nd?qMM8s;#6TPB2uhD#+}Aj_Q-rE}J~^&=LJ+%WWXk*h9(+ZON#bZ}pu)rL?39gk+=RJ?>=EXcD+ilHkN>#djT=g!2=O z5vu$WkKehf5!PP~0yCC2FmillJNSqW>*1osHGe&fXV(CaB}J&ZmxLG^?y?FaR3oRd zz)2X%pBV<$Tv%U`c>qk~BYZG!6$tUSiK;9v6+e|W%x;Yi3$WbY4#(?;aFl9tPyKp; zvkw4OlJ4x`>vtN6f?t-N*iuw?(Sw&EAo>Ix#DP@<8kT4%+o(o`6E(!yWb-*v&P+$()rs@%&oQ0p zt`p}dac?SyN6=kuglBMN$*Ly^RhtA#%%a{&Y~@WT6L1^BYq^ya zg`df=zXMz^4j=OpKxuQ6<;j!(S;#jvtc~?Ct%nrN8StoBxCY@@yuyo{lyVHXwF+G| z!jFQ1Un3^`rj{tbU$N9C0ugxTEE$YQOnVL}a#^nSQRDN~~lmK9t;+(YjXR^HDt;NF;21U>3yM3o`g(!MWE z01?dB=pcKQsXSKO;aV`k6s(xR5#3RT)>TYcomva#N5ntwKiG^FW@JBV5Y}^=r~wj= z7G8De_*GKy69pXl(P6YNk~0IKkegc(C|Up~p_$pgrU?guD1<}52f)=bfAxXk7D2%? z6|J(~_sOZnG*0=gCzbUjUm?QLenvkGX(3x3ffsg_WvS8E<|h`qp#SLKqnuPi@HV~( z)d7y$ji!^Ri^iK;nn&XO8yPQ;Re6m+y*Dq3ICcwq_@-v-S|~cqXi{;{El!oQB#hdy zb@dF!Sdk2ObCX3Wf0XV?!{AC3(AQ99Qdh%&5yG-q<+|~|pC5+F>pB)_pg_*L03&0m75;ZyaHCIEiXxba5VM6O4$dsB`}I3nYO1uCp|> zxHmfu)Q@7(T_;n^$Rca8%Q#1gn;^VhE0g?)H3AXF*p?QT$~yejRq;1kr6PM)olvC6 zG72h220E6nRKMHJAz5uK3k!SYQNIRXCQ?WNxA{(t#B0l9V%N@| z3=zBvWg4elk|Z>Rs`#8&70BlznhNQelTP$QesN)&Cm~*^^~iDaaNmuR5X} zz@xjqKM2NrI300)H9{JGGnRA(q5AO7#daHZM@KEHML6US!^Q~S+{gYmZaG+Ug0mYG z)Gi7^Fl1#qY#RBQBls+CD&-Kb2X z)sOVJH>YJ0cug+@j!}D=i;d5NTmgr1ZPbfxK|q*z2lC~U<;Dj8oroy>ILa>?uj|Vf z_kHsa?`rAJ5&LZzR(c@2PW z;PQXuENnG@4YEdu$hX?d?{88z5g$zsguMgdD}I{lX0DHC0<)V%tIBuasCyuvbd zvIKu=&M|*1q&Jba{a_<~x|lrB*B+4hp5zv*B2;CN68?0n=F4Zc{B*2JJ`?+DoQCQF6Sn)z-=n^dQImW(a9_Jo zsYYj_xv@2OQ*=%e+vaiBMOp?564>S4Z|^X?)lO%zjtFx-A;_(}ZNB>@2FNv9cwXdB zDngxRkUxqPCc|0R^{4t<@f_S>#dHrol}l$AlfqHuOrlll3rnD|vvW2N*8*ofZz~Dx zJD_m}XI;gW`*7~;klR_UxD2y=!_JJ~W=;cU=2e%q5U9f8V~kNhAINab+7#&`QA$`L z$zaP;rX@Pu^ns4`Hwn4ZI2N&DrJUdu|MD@*FGEno+_5N_poTb&w*=Xv%8he;9Ff`h zqV^*N?(B(i`E7GXQ@&zhui%iC?X362K`P)?9n#_Yn~`a|Fk&BT>_V57$*ONm>rQOn z4Ko3tTE6X9fr|xKKQ!GQyMVmKiOs}HRpFn^x8DPn1HSJ>0b~@7exW5#IYIvDdkT2I-c>{flmS&wwo!hA!$W z>)%SdD!er_A=>=q^OgT1#L&%*rB6msHmz!x>Md@HDP4)>K})FaS2j@_tdKyny*Iy^Ars?TaAiXl*N*bP9K{d_$o$mxgb#E6syjx z7m96zV_D#WDmlR~CVtT4to^Q03WqzEh~r$M&|!r;>o(scOed1k^k3vY2rZG}SWD!@ zbU%)Es;9TTzsD-5k@F{Ov;=I5Ke+%M&-KcD+N>twOP$m;zW@Uf8ny#XOT!USw$Lna zyprlSanc-$WyWbH{myusmNE+s0{TwFWZtfO#*Ax&+dClvTq?J6x%q2m0L(=SW!KqN zem%c5!hcxrv6h;qW8uYf91P@L4}mI+oC8{W3+4noZV?qf!FTXpgFr8%pk-3%Qlk}T z^v%uK`)jv2dmcVU46w=qx~Dj>XE|g69p*Dtut;M6J;F~oiYV1bhq1c&UES0qT$oN@ zNj!fY>jo7LH5+uewQT^NgwlpP52f}cDq;iLpX}``8LzW>hQf(*vzt5N8Gnnk;^Gyt zbH72jTijH*4*a>&Lh5c*>j@wOn!iz#8&W4ZI{d_N5)p*=Mm;q`b*L%nLnkQk^>Cvl zcM|45oz;@+L96s~2NpxSdEJ+4JAXgGSiglcfl-w0hRt()4m$^dO}gN!=}eJ8tKn&z zMfCnfNYkM<{I_0pL{s6W2RvT9?ESLkL9GMQt(XOdXnb68g@smH?A3+Aw3M@O;`I3v zkY)^JHuO<;Z=`)Y4=394PTk{t_-Nm{BQ%~w+@Ws@CyErN}daMUV+w&j08>x%HSQdI+#%OCK_MtmgHm&vVH_TqP_ z3{zpm!<0^r&QJ1!dTesSx}K-w{VW-35Z{Dq%o`Ap6cS!g665c5uQJ#KR3fVD{Tc*v zMXG$f7WJ7cB^@>TZf(^+zW`9Gv~L99c!92@g-Z0-QAg|Bj?IJB43#lIQ`~;^Jq{>H z#Vh0xBK9~A%)bw{K$-i5G#O};%~*w~`_3M{Ng;I*lgQdWU9v*(vV~X)j{Ig4-0GdN zD1z~>wQvZ5k~*?4;KCE8U}ZBMqJm+ildkH%_O0+fcC7nKI6fkwzI>4c1)<7o<+O*36uKAe`meIRvFE|L)8i490^tNJtvu z+{>yQX8$F>4ofI`>?{=U(h0RT-!eVN~5e0aqLYt}Egjn*JYQBZvd`AU=a zDK_QvuLm2f+%TfR+3yh6LxMHF0O#4=tRDY2q`NJp6xj(_O)9-l9~s17K( z4cnQ%IuQ-Ri-y#PiDAci zoqsR|)hN~DpW=uDfgK8Uf|iAeTd0GGhYa0KO5sk&y>Iu2>5+&6n?vUh7Kde|H(r|m zgl;mHU;EjAzvppK0s*aZhTYN*p_(90XBN=Ce9sINTi!x5C(kc;z7tZxm9`C)C8)fT zZt`_%Ipz^St3*|m=^eLO%rYe9tLtrN>d;Ai#y`W`gy?M~7Alp(O;5v)V{BkZ;c}kJ zeAUUglxRRFn-?&rmO_-m&5j%M2En+b?oF7#rDs!-3Z^?$oNv}*e;t{|)x@xm-|6Eu z1WiuofEEV1sFY-qP5=Fo?$Ty=;fXItZ5F@mE>6*z-RriP(cm>kX&xMw)qiu}1hgDp zo;6v;W~gC9IBGxEq{e*&eP5G-T*L4G>YWV~VW~U*<)1J+zGqZ1j_TaQSs#zu)tS%AVa1V?7S?7Yr5{fBj z97taU79Bui0yV7TT}B0(K`qDpef5`gZm~oUb?#E*SoM7m7DvXUhb}O+wlL6{*>)>k z4gErj>%5X4^EveZgnJM7pQxk7*B?3k^q4XoqQk+Zfgi)6Wn9WV?2VkZOrqQ0d}o9q zfpM{p4%e;^pj2uu#y(MC#s$X|1aOnA(Ii@K7W=87f$M0r%87oUGq>sU@ZlG*WM7Jz zJDG!qgezi$=&&ckN^*qxWb5Rc1HS+5y5>|qTCg%Ra{T$d0^NnTQJC4Iqz@&gSFoA= z_wp;>#LMgnhB$~Q;6k9wk<5%w!`*ye9ZDcs;FQl)Z+LiOD&y3q!#ht@lw13Zt>pRJ>xx_vGG)}-2fNeDMREN=FATtjC@o*&M?^_?7JRAZvIHT?=*}gi0B@?7uzBA z0*D$GQ{kWyKmf_%wi2z(nG<}_x6&WyWzUg1XJU|gq6KQ*p72mPFJOIeCcXUZVZ zKZ}wHD>NB_|ET-($J(FSB(~Pr3ddq*42nNU5@GspZ~aH42r|?I;*3(2&%x+KJU=B) z@awTU;Vw6Z*N}w{DMyXhs?k>`EJk;@pux<-kJ|Y7AI2Hbx$>@b9{fm_k-vyb`iaH( zR)B(CShM4`IYu?r-7vlXqT?vH_FnapNCGh0cOFFd>%+@NWmrUZaTy~{e&TBLB_$2@ z8HB3+DGA(Bs1wj(lQnv2*CgWJJf_N#RUO?lLz5iat|Ns1`N%xcNH)S=gY4EgkyWX# zh-Ks`X_uT{S0@B#!;nRvNIAyx|4fn-%CH^c6u65P5^&;Ot-!B3Y^^Cux)4p6Jm)M_ zCp24VX*@iepZel5W>gA{H>CDFS}~0BNe+1`Q7P~oe>xtg9>0@$kyFT`wnqTUHV*$S z>nK0=)>pwY`Zu}fJ^TYhJ_qv-f^mCe4`Gw69B7pY2Hf=cR3Ejar-1@gqh@UIS5Z*w zo|dQ>GP-SkkHOnS!-)4&ZtMlwm0G*+JV$p`T0l9FCcL*=XHk3M(l9h=(L5p0%%L>) zBRv_vWWV&pNIn3qGBie;T|mbwDEx74>Xrm^mF^y7@Us)YFJQ*PT77*q(w`WI=b^(0 zL4PAIx8(Ej;}!#2ukQ0=`^1KO9+L{-dKnp?L=T!DF~`|!r7!ynBNk!a;dp)A`f{X5 z`iLeaKv-={)`hebd<1@H?f=PoJ7t}`vy;kViLb)zC2%+*um3$X-^t3|l}HiJbT_EF zoOvFB=QT+r5q*1-BmO%eBBf>f-p;)?g*%y`Abe>KZrVfY&$HTyNJBk=P*PUhBO@&1 z_+I_UjmKz}@Z%1ej#kaIYoc+|k0WeodmOqiU>Pln)-Pb*g(+nJjql%GfvZDivqE=O z8y$YgtPSMFT2Dx7_%R8_MXcq&U5~isih1flgOz{JjZkG8{_d}$wR})}4noM~qloRr z-C;dK1QD0-JNP65A1;efMGK5{F4kW#;7*o&%W@ujnj}tVX3{<1qEJYKx&j?a_lY}$ zx)rt=mGX4>-G|4&6^Laj*`+a#=7J+73xOG40x~e9S5gF?V)Cy-VLbci9f;#R&Fm<) z8UHq5ycfC)>Vc3#yeM4?!f|YhwxE;Ck#et(b0s%c=t($!sN%?1BVAr+2`U&LHd@-9 z+aC4XPw5IgB`M&_)CptU7-Pz>*G++kZp>Eq&|>AUQy^67^yd@4w1+#z;HB>~*_{PB zlXkLf1m(x_s}nkcdRWt*PHi)QdKL)vsy1(c0w0G3`T1$Ei_$FuSh@J9uK)13F5Y$J zO;zU!y6bhD32*w<0jvJDZG*F6?eXG>Q(cDuIrMeDNdp6kyS@qUbEHKGy27M*4@O1+bm8DxAm_ zvh*bc!P}fzzs2@wU+yrw;>oX0Ux!1AMXMNm=6IHR{7UAVQr1BxlgA)+=6aS@{>T$6 zUmd@^1$>3VKlyKoV8C{4%8H*1J$HISSx-0Q&veQdRmaq=Jz?jl4}>-Rev+*F$WEua^|7V1jN>|H#N@7#{Ku&UiMEs>M4Vb{VxO-cJnu4Y-jvGe?1PMt4!dbF@5$ z78^5N5oTT_V12mv?Zkj}_Y6+nY7|D1#c1aulomcV1~H9SdAJk?b#&*)O9e*UQbtk* zE1_iW@yp9WhUu_KokdaBnME2BL;xv9bY^tjN{TlD2&18*HtP+VWRO=)E*=Q#C*yWt9}vw*YmVKchNqG1p66oFEHXldbbq*f+njo zx5g(*)4CRckrI{AHuII~z#S{xweiDvIb{@Hvl5xGxo`kyRP|^2rM(Y^l^4+-T--W8NBG zlLDvjadA79MQ{l5Yoae#oGICGdJKw8l$JCI)%Qm^lZ=7m7yiA6l=jLe z%`~gQ>n410E^=k|$R(`*KK*de2E55@6c%*i=DrgtWp$w$$lKdR=SR&GUSuDi)zZb?X-NUZC3ay z@_&mo8_}gyI_5k7W;X&YW=5PQfs*@^C_k&_IouKwgxytRWTev- z+tv@8`CCl+o?ZA!`TWSm`u}wP9M4~s!C`qF@Xy_JUmBb|3k*e!$@20hdWnUerbUzX}Qd#6scF ziy7l+@tkIAo=-h+4X0D8P%?L1>%UM&}Wv17Mg;*)Mz!#~5W=*BA`)ICq-tC6L49(qMS z^S1xy_Q7SW_2{d0;1-P&n^D@W&Hk||bSD`rgDN7Nru1kPkpKx{a5vb_e(l-NZKn<> zlWd(=V8_;2@mzZo#~h9?9~8IBg6Xla)yYwuChHAZeu8K=1YSC%jJOrn%CHtG#kkcA z6^@V(`URPI>YyPRt?V9$02xJIxW046nXhyXNZt*gz%5o%LWp84X9VwgxkLN$0(bY{ zjG)j0gvq!rfl$!W{l`#TWYQsM1tT)i3ShclH|^${^wE5T3XCt-2vr}LaUv!3Y>R?U z+NaXzb>H)-P+kJ|S1r^C2^*KjsNJfr+e7{eu1r^u8YQR#NT4y41BG!Zi{NhNP#sCU z{^G?QC<%N0ni_Xb9lL1a6i~JKQnmsmy6f>(-6Eub<# zjpYb)qr*09|N2!x3nHzH9(@`d+1I$oHQvsMqxA?hrH_AjTPLZp#532hlda%_$T-V3 z5bw11{GuC=0B84npPxovn(S?GD&uW(-1L|_yah6<|HO+5NmCgoxL(nYeTHgZ6?RkV z_w!TvAtXfgyxcZZb^)-9LVYAJC)G8~!oOY6s`JP0uF##{6P*NN6EflxER`N)c1D zYEiAF)JIDs**Gg1gd@3MTUx~O&&;_NqcWGMLXfv3OF&&L?U8*UT#A|DP z?@R$bXIAy}qfA#q&GSwu$LbR78oGhF95$nKNCT3rNhl(csctW85LUX}zLJoTYtj(p ziyPcd#Y|a3s;lb5Me8}Iq6WbnRD>ZfVo|!e(qb^Bwg&;lDHoot?>yM)s-!Vs6R!rb za-Cl)b;VS+=CU+4=_1Nf!^m1Fp>|)-eT=^LZ|}kkwSU!hGsq%`7RO`o zj?ZH6*|0)s;qybnliP~Gq8kWIdHq!KwXEtHU(7$CV>KSc>4>&$6YIupr`M3D*8cl? z2XRUvyLk%Ph7+NCE8^+Z&Wk!}S_|z}ng7baq#urg+x=;aT5x5aK_%+^&R~`ax}RM; z(Il`>mZ4C;hBOJ)i9sTTrR#CuG0n ziaojx>DR8@q5tST6POyIGYu7chX2~OvT)_2c)r(p& z%ueRqxhvry1+EpCUJOP>(PB|H^xV&`bSYvMjlR#66=On2=}lQODJ!O)x~9~sL7rJJ zTg)wh?EbxUv+yN*G;|*}lb;i(jwXrP{wsee2GkpN^9yg@^Fs0oCc!7H>1{{Yq;vFO z6tQqf2C-Kt;UiVQN6RDSouVxahSk8_xvxK>yG7hp-cepBNhf)c;^U;(mEE3yUg<;r zaVhVjss;lkhcIWKK)9e4xZbW6A+VF#M+f296vFXdX4VsWTz5&-$&qpV;*Zy?+t=;$ zoJj-ME4P|=hy>Q}@xZ=$;#mW;R1W3?LDzmCgH?`?I5 z(_tm5v`>x%Lyo$Y)nU6|@3#CJ+9R~=DoL6}+>cG!Q}hb`GFzQ1b@S9Ip5SbvOyW|% zS&zZxx}ztEW|(gd#63#D0ZDI+MzFkBRW%7U8+AiDbN`sES-RD?HSgd3(T2dPu4(Sp*2FV)Si3C9q^`cQjygW^N5xRVvd z7s~zTdKDr;|NHmo@TD^dN8vizo$rp|UVq-F`A&^--;$Gb^s99LJ$7ILt)A*If1Opn zimNsHy2+#|dGCtZL8qz9WLEB`PP9bcOh7!S@<+THDo^eAmqwQqa)`Mps>!0!=!d zf-bFMyWQr_1CQRnm`wr0M%l`8=rEhOT*IyUVhUuWfc_=EQLB8LO)C||soYj7S41K^ zC3Kv>c^4y!x8l& zxo@ASqpHTbfhtGuRJ@{B*Td8dJI7q>I-clPBV6sXkHqtbjSQQeTCe3dxjeh3&%-w? z{zJ9&lEB^SI93`PF#87@6?)H)c9rE~iV-M5;_tvo5^^{!nl}dnM+y{X6J^n1pERa? zjwFWC$S4urB#Yl2;y)I_3eK(nt$+k86m(cfqWY{7@Y91su9n?nzt864!}u{tB{C!1 zT_y3kh7NxW-SRHZob3=VW=!^ySo>|pz|#1E1Jd3h#C80-UB!g4!MEB3MPpy3;&|nc z*_|gBKM3+*jcY2_?!$;FEVxH1t0zN4R}MUM9sO3qnrv$g6%gbb`wE3duHWoHce>re z^lrCRBEDE+r9Hpm;jt%aOAM2QubZsse2NZxf6gsOO8$>=|0P&mv(zXJR2nuwL7b z>C0f|#Urf?@D&s{tXs=tKQ+446^PKmm0-Ync*G$Oir zSfg*Fwmh<0wsxP^@K-vMqv7PH} z&%*2V$#XoIB)TFNtaW;Ssr^6M72PYL^NyK5;fR`Iw|TI++QYwrEB;ku?ErShx$pml za9ljidUN*glwQ78$kAw#z9Oc;=EQaTQD;d!TOFYa)uHWK&|n|>&SxBeR*$!jC{n{7 z42e!Jpm&c^MM?}o_?0;m5MG~^>8k}skc};2L^Cs-$DJ;3bN8CrfBwQ3W9J3Cp7CN) z>|9vLWVZi%yA65r!{JFhW>L2$C9}-x*b`hNzA3T&WeYmCY2rc8R~P4nSXEbR^#7_Y zPXWCnf!>Q%ssZwU{(u?@hu);5%hzN@Q@X~ME=|f)X-h}G_zhgPbkZ%3QVF5@O=G60 zs@k{mw`<-5F7@TvA^rBWh>2V6pCIIp0OXSP>H{YHwsiul1auw$Ma_!e7vGzE&Ya4vz+}fIYa!S31&-6*VlgyK<<6-XT%ApEa-$OCO(o(FLq zZqw(nI^*i#o1;ddg>5%M9$(eJ_v{0hg6irfrK;n=DAX8wfjWx(6V%;sG;2?I>#q7> zrVb+!)@>NBZ6+i7w2Sf_?#&-s8H}UGo3>2L%n_r;-A%JFCY=A7(<^H*v2vA8R+>hQ zIjF+d-*~bR`7}#Y(@5&`VvbfmqZVeEk?tvewa&$_XiWabNE-vm@~T#5O;LhYNm&mb#?oWm@aC z>0&y#&zisJqRI+v#W!4x_h+R&bSs=FcGb9SKR?nqwd=SzRQhJPMXN78j$b`5aHfuB zQP#2;-T0ILsr$W`Ofx}$Ju`jK87YHZqtORHj1BW|oySRB@i@(|H5W7>IR7N_^6-5& zujvBD)0GuBpNhe+>94%o%dh!UQLafSF8#GIXchBtP+iZ8cfKBW^+Avtf$&=5d#dcx zmli3U=wjmaK$HnEfA1{{1h4SyIgEr=znP?TUA?yt68cDO)aq^UOz|a*n*cUrw#@@+ z7^y~h7WP#_!VoBKROJoIF)Np3_# zj3Qaz<)g&P1Ha(?jF}xIy8He{N z^T-9{ol0RC9B z+F}SpsOpv8JMk{{WlqO!nl&-CHtkIm0`B!#Jcw>A2!$*Gj@0U=of%0$H}^TQI^1m&`gdT&AhU8e&yEs|xzLRpC5|IZ ztrx4W`4{-0rQSvKxBDnswd_i3AXIf{_fo+3JsYVc#cxN}-&=1yy#{hW0?$FaZ3ZK5 zRMfRRwAJXB?|JRirA@Obh(J*Qz#^Wmzfd*OrsTNFdtw~)x9v_Xme)JJ`>gdgR&)e? zlst#v%^FcesB+E5Pdtp=Uf!gazV016AEK}U*w^xFBx{9jp(8kfqxt2KI%%Q0Gq_5} z!N6%Zox08womAkqIw*mX^o)xL)YNKAyme)6uhP1~g^$z4U*K4;-XJ`J4I@FcaWyL5 zy#2p*Ot0)Jyiod2WH6CkZew znG|cAkM4R#*0?zHeoX(!pfPXT8XJ~#k9-)+Jn|lEJiOES6igyGhDmS# zULM*Ps-wmY0ox5Bse$cM$Nx*V!3C{qm(JV0Nh7lY?f%2>;ER$o$rnXcw?N9~^x{Tg z3w!Xm2*xo~Vq}vt{V(fG6ux;wv-a?K!uN0&j>MF{{Y^uLn?otq=A=gvn*aCuJxU-ncI zwNSneh8rlg0`9E55nq8tCC=pwItNVA;$rxb@*@&b$qx~zQWeFTgPo!6-@MgR5(r)* z?LorZ8FUx&Lka82b$890m{&ALy}}Iz8iYFglGR8(tNT#<#(ni4-<+8orl#Bet+K-Y z;bs6hL7D!5o*?G5%!0$DwacI|)%`4H(OD#)??f1L>V0sdu#4RmlE1i3?~+1y|JyW1 z+|c5K{a-dT-xr9T)Bov^iypIcr)45U4fkXH5FPfReBJ*Hs=ycB^YeE;mvW9GjHrg` zRu1985cCCueG@^+qM{eW8P@S&hxGYNF&t^(Hp+@kO8!WlQ7x4BjJsN@{yOkp(M8D> zSUQ$V$nTv-Db$eB`pxq;U&L%ciVumj$e}|8yEg&mD!X?;jzt+r8S2Lua~Hn+Fd!_S z09Am_Sb$#|+4GDy3ZvM$p(E7qvwrmntKHesB8VRFbBrGDY#weGeE-h@>_fq*uE5uV zs;8xOV+s!|!9cV+W}4!kCSVX}!+?Rgm8dD}H&7VJXcDT)ui(~iV#n1?_AR%PkTW;h zH}h_RMD)BXqWhn1#iI`ohe9>rlU#21lVLvIE2YhgUukg(Q*Riqu{p)EV@Kov_Np|4 z*OwV>4elkjHV?JKkoYt(*jUUxBXPx#Kj-VFSs`ri!AfaPZiI|uNLN$>I{~^~PHHmC z8SSf0KhRuGDEhx>gvK`ORe*0vbTcuN*DOM(WAtze*FUsC@kTW1Xd`Py#p=E}@b;Z=CJwxs6MODwljI?f zlz;FrY_~Jv!{<3S@MUHE{_nDjxFG@WI&JP^>#5K?nemj#UZSczO~O5{OU9^ zfhA6xswZ$y&zlWOs3d(yIN~&ta-O=BUJMH9>!8KzjN;gOnZU2F%uILQzEf5|wB}#_ z_`ihA4VYBJ!1t$+T%_64{}xK8Z#p17eb*hbBh0?3Sj$h$3w8OdEBo=}NbyltpgLiF z#=o7`Irbh#A~oi`V@VahEzQtW^|IEXRrD;-Fxi3Uir30b&;gP-cf9$vb}>@x-^uum z3%E^?Cun}ndEC7)E4A|+Z#w*s5-b0ibEV@Ut7o9IP2 z>q7T)jNBra)1+Iue<-&)$w4t$eP}Tlg@)q-_m+HR*1x0fHiIPh=aCwm*e>YeGkYYu z3og65ecGR$MxQlBcU|s@Uz8D&p-_SbJJLjEo;V{2J;(nt6^YcrQo{hB7O74!VtZwp zR8Y=gj;>y^8<^Ba#O8LS3_A>}OQ~kVRl3uw-uYe!ak_YFe06?YwlUO*^RH27g4Y80 zLL+i_?@kc1G5%#0!=+1cxmz2}vY?6TLn ztR&&=GQ-&`d*79kB;>N!B^gIX9C6&;?{%N=?+>)U^<1y#^YMHW@;d^Py>|(=GX#;s1`lKlhW6_wM8TCv3_rg~b2}KCjZTU&Nv(IWF1F(I?!%UmFsI#;zMehzl zb1?hZ%9JT_C753AWBA3?`cMRFSnMl9z2JT<8b78{Kz5?-D5VjQVp7LaT84gs#+QAva!hgS~^Fo>S?v z`q!pbteKB@y?5x9hP^PF|ABSBfzR({YJ@rg8u*^pVfI5Efg*3>7CVwqj4&aafghqm zgCom#4YM!tZpUaQ$l*4|Tw8^XHks(6@yiNMJ{T$t{9*7l;chFvVACr0{fGJH3OYmg zxbMp|#C{?wyk2!cko>x~ju#HfP~NX@FbNY4PFW4=odd0LTJc{NzM6$Ypl|{2Jmaqy z#wk~U`&E8j@1$_PG||6&^k;J@j~D0Me~3O{wl&YRy z?V7UT4OY2dxGTs)U5kQ&03n$8vfaceFEIk?OLshb$)wnTa3`*2RJh0D>-29GyATiq z+H7!O*rC#|@{HFDUZz@{O<21;SmhZa<-}c=yKl4s zB!_GVf*4;u*rx90?^sjIig}8xo0RU!E+9wFwVS2GfKtnvOm@W)WYjYtC9e%3e_lOG z!$^B^LeTr>b9QgmT>=sTR(aup4POzZGOeY@=TzCj>FC8<-7&&80S2v#lL5QCRWCrx7F z#@*jIJiB3Hs1krOcau)c2rBOz;HAB6*F(!LAK(MSdp9QbkS!J{uCF z9ae5}32QiTA3p|^J4+M9M zlSe6I8>ZW#cl5Avx6gHBE zW;%2dZUKdI68bn$(rnbqL^2HJ^>f>QhGXQpE|1%O+Iz#yo{}9(sn?$m=jTU6>SWw% zgx*Y@*C2>={iUvV%$qCG%)|#K-%m>RcQbt{xhUJtqUN#+(kpBjav78Gs|J(e?gj>2 z{G{=b`j_)av;vE;zPXQp6BVYs&Q9tm3g3gm4EU|@0H;^qee7>^T0|CC|Fk#MbY?M) zl2!T`6PeBDnyas5|FsRWNKL7l|68JqQ$lWQRVfa>@i)D2XFjppRPFcQb>vy3#KE>w zzOm>Zi&{|isk_;CFV{ecC3UxP_#yZpds@VxyDzt3F%m7y{eX7!9X|wHud_Z-p$ifh zdAGl@UnYUh#wX+Gi+8AT{x`9MBL39pzz4}a_Y-+0c)pcrX5a(0d!+K^VD00lF@-%u z=O=puECcQy7_d_vX!8jbJZLDq4J0JEyCQL;+os=+ z8vwi>tp|!iX>i+5daW%(esdP}wP=d!Uc$&K{%(CI6Ghn_1)Cp$X{21_+d|OHjZMVB z!c0Cre~%**;oynyBaF(g*uByKrOL-Zs2SHZ2ymaevblb;5muVtUh zflGJ(Q6+&nSmDJOdI=xyfJrAkV;RmK+ehXo3LzpNaP4~OWxXv(coAy23TZe4T0Nxs zKrF68NKV z5k)b3d5e^?eMGXVPvRg`dtw|1jnw zB5qF4M1F>h`}~XMxgm-JVz;dEdm?`NVtog2UI^6E@7W{m zglj|V?{R(bUdXcV%XQDsOs|FT+6K;CW5Ene1bKgtqsZ~7a)iyr$(+ZJ}07C^(4 z-yErQ9%?6W;5OPf=?$o|6#TCCD^>{9 z+HNS}T~iWs!z+yn>K=N@he+G+_`03p`vk?UYs}n82H{VDhy{OXt*u>M>KagaXp1W& zIE7l&UucdOISO19u9eMwdM%M}`VPnS;>&$P_tlzv5GBJa9FN)}u9@p*3w;2s?TYF+ zBQEvN7myP3F|s1Vu_fLaH3PCMz6&=zV}wBvd&egRq=?V@UWYCxYpN2SHoG?!ai`#2 zvHOml>P_@lMG>fGf$didQ`!k^xQ%C%Um^x}Ed0}z*>?sRFsbsKiZgwb;QzKqOZ;U7 zz9XZaSr0T-qO4MPCDaHXF4#N;w%@6x|30#eUxL=1AcPVfr_S=~!-B7mAlm$0O1Gv?be~?)#vLQF83J zII0~vLa=rliUAm>k%3@P>mRcZP}b*h>-0*Hg^-Wrg+sS>!!SHgdv`2vP|_Ij-^&(J z_7KdfNbc_BUy5*T7LRplCoqR{9o>=^*!St2(ptdj!pEOpHt|IW<=u`-*dOYEpjTb^8@Ak=~-4;W;TcF=O`*ZG^ zq^`=b;bA)+C-~BuA6ntZ4I8N{Bd_Fbbpv*>jC4XPg7lK^aGAQYpZ5BXFIZ+uC&_%^ zBcJi2g1PKngQw0^7`L7}o8xErW&b4q8eHSYY+hpauO;<@n!6C-NIsPJ=uy%d3m$VF zJa6!AZH?*5|P;?^i zoC8eH7rjFk9-5+@e*>GaUmBb+b{-dBsc5vgGT7%|rApA({hRiqhH}uNdLo{a6sQO+ z5GSC1;}&i;|JstcA7D2jFneL+@g=X;uK1!TZkgOTEbvVv=I*ap_m}7H0R2SOnllsI zk@bNq!o7wP0KCb`c5|DK69PS{*36SLrD=!@i{>N#8F)3vYasW~z{ov zmM0hACNI%A{VAChf>jO6cDY}m0y7}(`)-~YX0J`Fz3+DhN0vI<@eJxrIctmk8Z;vE z3a#r=l&%V{G-7rNxG2uYo1PsA5(~43#P;=Jb_xguYSK@2av`SqQI2Kuo`9 zB>K-Ea2p(%?9m$o2OxWYbbB@r1OU~#t1z&Ciap1Nh}Cd zK7&)dr+PYSs;E$~IfWY>TFh^T;a3G{`xv~e{7F(>0#$1wAFS~zR!w0kcDyw3zSc)z zd8Cs3xMUl2;n|x{W`!ca){oubVM3DM#U>jvbiHNK7X4#>;|zwZHurTh1QEMC@Xqi? zkW!^~0X5FfT`uk6t$VqRf!%?NKpum?TlzfubE`x%8XxD8uv)?LsN4c{@3NNv5?|`m z(2EJ^rEOYf;7}9+B!FRk4(&gYgK0LQ2SPCTE!xf4_6fTqp0$ z$d%eHsif>@d@%2DJ#7MK-V-KwE>n}kF~9^#J>RT+4=3E2;i~~Q=oz?fCwtyZl#D0S#S4%R>|#CD^hUyv<87p z&m#WQR~ne`cH>v8U#t0uSJq3nhhG>G!gQXC;_ib_h@{!&$YhydxFv+v{Q2_zYlRRb z=NUgyXs()R=bHd_#qjSQ_Dq!2#$p774A?mNYf1jRz$yAF;&@@4>r1tNzPKXS{NzGvO zh7H}>RS$%69wW{!G{7Hpc-ko4Nh7gh;F{{N4CkGz*R`KqDCERg6=sA&$QdG&A1|QI zjzQ9ZXBZ&rCO>iLfZqTMf|q9~eEnCwh6!`f`x&l5V3_BTr*?OFBre?W%YKiM0avX@ zKoJ9wg%4c+Bmj4*>j%4wK>f?R8jV$N`9%rHEHC{!Ln@_lPhnZ{wsWVnS9p5d+k%K^ zRJd^}{bG}ZQ(~)m`&oHyUFU9Nky=f3oSyHSUkVTl3^dUGJ$i?iHtttw9IJTEgciUE zny{CzxVKRS;6WW`1UqP;)A-mFwh6^ zODT%a7YnD%YFwnz1c1MDocr4LlQ;iqZ-&cm$_yoxP0M+06gJkB6dpfhN(-Vm9QIbn zy~~(jLy2OeZ1j%zdn7Mx&^qBBM6XaGfu(AGVDf+ikhVyNs`-8nk9`iB9-1CtZ%q=d zAY|X0`!wb4aUOk?Rcb z#g|FDb6}HC;m{RCz`OyuZuq*u$0&jh$;yg|teb8W`rofe)JS3Z*@0?0MJ(2GaubY z*0<`eu{{O?%!qUQKv%RducEMexj$0Rk|>EQ*M{_$92U?vLFVdB+hQduSoHcLjp=)EEEF z+X0$l{okz!^?bGO0$K;PcDv)Jw2q6RnvMcO%~~340gw$jwqBM@qBelGuro`W3Mc%{ z{S&n=uK6(0u$^#ah;}@vVTKYTdD3c0I9_g@o@_QE(e>Dk;LW$c>!&}s5IK>`rgPpVG9{mQKnD^$s z*=_(5OZBpzqSJzaf@nB|FYpVlg+(u`-wYm!U_9 z6TZGFVzd1%=&LR3J|A)RO@`f($VF4%mDr$^WYjuk2{MhK_Ug#~xBTEvTI4JJBO&ky z?3uspvVa8GKK)_V;*(i}btLLgj9mFQk7gh|$kn8jAb5jc?}%fr*rX*T5<>yTIeUJl zMN$quh>WV&dF3AR!um(M#2N?#B0a>Ng(}a(ps#?&L*#3vW|5l0jQrxdo2YQaKLU?w z%$$(rdEBZL&syz!%gr^=x&W47HU4wsBZ4&XeWgak#`omlD+dK~jxCX^zfgG*v$h&* znUcKlE7k-2fbJYG43I_>k8kR#ygzQDh+lbX^NHgZOR$6 z7K--rZqnyJ*_Sc*Pj{^U3aI7E13?H~(GN55YJ{Bwh8oo;IC#VT8M|pcV!>Wtrpg7@ zC@Sn|H+SJI4yzLQ1Nt5sgb+_Qe2iaPGm50cv>3qC*>F&qTEQ^lnn1UlfFQB<=w&O# zh}-CLCr9Cl%I`NzT?+Lk*!$(YD6PtHHz|t)y2C^U%nXLsYC9ST@#0%8_z#7xTZv;C zN?w7J&yh&q$eY;bKq6dAJCdkz$KF5YBz3)B5`2AYMqU~e3XM={5G3zB7*U%EQCM7W zGafPsJJO8#Du&$tE;DoC8@LHD-`vnYqC_CsnMgV)FELjjP-Hh*%r9GSqTh~uiLx92 z^#8)leyGjlC=?Brl<4XyVwGoetqpJdi~PMCCj-I8VHL*X_{4Dfs3TaeZO_Un zu&u4!7jeh*3l3ybzLwxd(`tc!$)+m=8(uveiU>lHH+nvnl%NkM7zn@RGh3~4pripR#habcbWA9Kw1c!$1-Q&FvWKXbcuZ^+{AseOX;e+W)_x<~u9s}=P{S|%*Z>e3Dy&DLedA;bUVi7N_E%H@Y z;un>H@;06Y>>i*w1xD4mf9L~gPgvo7|2f^d3vYC>d!{JL zp3>{8ya7-X*mERX$aO#Ux4t>WUy!u7^(E>!|I zrz#wWY~u%4&^D?DipD)0a6In*`zkHaRw}|P@`hETa!xi|{UDZ_4%hGR6t6Zz_2qIb z4;Sn`?ec=ToeWDnzHn5))_VOnTP$d84Z4YaN3oy}2bArn!?g#BJ*&(`=VF$f7nds0 z1PLSkdKE-u);DcWMDl6izJ!eZf9P!&?`u&~+p7T+cZ(C}!VvlR9`R*GCJ@5B3n&a$ z2qVP_PMTMq*)5S6U$bmf)>)Icn`+@D^74#$A)cQytT1FlqdqGZTNf)R&$$Wx+5<5^{T7QVDI7jV0b7n5?YaE=}~dp2?5>N_LYce1Y{ zC1Y9YEXj#K=9)1ZKO7rBuwjA+rbutvyI2c#Uxq2DSMHa%e2@-&;S>lxlZj8KG&aZI3Ql0e2)$&fQ`YuV@5uTwbG+4YCS->>~_|BfYMsmVex8E zI#chWDNjEw6%QBjvTKs<7&CBY{6DmDoN5Hobp4|ViVdi4!T*+jqdlOoyfb9ax1U^2 zlF)1F3!Gkx2T;MW5s+4oQk&6oiVJ?4lY7pyEgm_Yna5hCObB2mXd_5^+jS|eb!UK8 zeAs=k)pGMDPTxCdSn1SJqHW}H&@fu}1h@$mJ7so;#ETfoG?uSQ3JQa?!5)jPlqR(8 z7B14HZO8bLCIaOcR?i^?f>iPx$E^jyPN}4{Qt)Fv!w8HZMhzuNC_bgIRnz%!8+oF{<3-r03~v$ zg#L|ql9U!VVP4z%aMNoxDrR1mKOGyCVCPf zs!%j%l2Hmk7Qx;Q92NyLF?e#uL6Q>gaLFd+&LFivcJm z+x~d~E~D&>Dm*pg=5?ID4YWx1vFl5M3hNE43WJK$paMRkx`KoMV=i||(S448{kMk< zq8XheoaqoK--e*6zk$dKonWlpas>@oiefa$A!SiOfEf5G(4;hNU+|ZJ-8#4~tE3yW z@gTi5h0Q|)@Po&Xvvw>7DJX_E2ws_a*fG&$L@n@$*`53hTztvqoMKyn3$xk-{GL@~ zSJ+}8sd^LT%;ZwDTobxYB@M!8(}P+yh35giJ5+}mvrUa)%d!S)$sxddWC$`~j8 z?^Hg(MS6zGK^O7M<6g#7vE zrTO8@Uk>o%5~8|8f~rko5Q6sW-ukqND@Q zD~iqlPnA7urQad0M$igu*Pc|+Yt9^IM8$$13!6JbG3*`v4ms>ze8laR^pDv|-vLPr zAFL~y)U(|0g{*I(bv!Uko9H)F=}yf3aI5h)=ve-dyTiUSauq554j5G}cOP5a{6L#3 z#eO6{fv;ce(KSh#D~+%#(xn8w*s_Eln}$74Gsd81rI@l_i4l~q{Xm%64*I^w508XM zO$d62+8b|ov;u776s?_#f-Q!2U!i%!?ksY<%lKu)T?knxVKb~SbLA4{{2Km*WIjLm zY|g=G;CZ;fhOoccT6#Xt-Y;U&kSI720+qd(eEwA<``%Zn#xB3h8 zi##P6c&hpzRh0Y?wt?xcN7#>|O}8j~W^n9*>3^>aE>*Ru(K;CyJ>SJ}CwN?;B0?Dw=+ zQieE#R?Z&J{k1hR|LWSHi$6#yF!w;J+?UxflLivQPJ63sJ?GU4du*H|sF6_xy$RY! z0rN>ik1}i87Wc9xM@+B10JiQY-60P*@+OK!COn|Io270{y`6$afEV^9%>1Zalm(ZK zkD40_%9+;FA>;@%40h9@&`H@&M|WP@V#8~_^efye@ZNs*_xVTgD#8a12>N-Mr*-Xh zP21WT>@lMxxKBqDr!zs#8*L@eq*PE}ccWT6P7k1S;4qT$rq=qOb5B)!)5rv-)4BR_b{!%B*ms3RqkAZ5qd z0p@|Y2@tpbM7;CIC#Q7+qxGI4ljM>M5-S{Vt*!aQz~Tt8OSpbY*t!^Var`q;|FW<> z*BC!|S7tM7twD=oDm_l6XrSQ=rKIUj{)-!MxSI$qINBu*0RqiFH1wP3> zHry|G>ux*{mj3Wl-8hB)!!tDeyWJ7@HKc!*?!F`la6a=E0roqL+K-~omTe%vkQ3hR zN2yc2fxu<+H8No0D<-D?2IHM?4~(}{A}^R?*l(Ge`)C6atox+TG02u}lTlhL-x9f^ z1qT)jeNZWQJ@ieZWcxJEGcqgv=Uf!t3_&7{#fSPGxo`_g15y9jDLo=j^2MDTnAO6I zWh6y?AsU47X0-O0b4-BVQfxJpEvUD!Dk{(Z&-fp(QQMOO>n3KoBd2jHo7a=fsuF*V z0aC_vQV{HqbNabcO_=mxxf;9JbjSXwl zo1naJNp9|)_pUTAY@kw59u%o6B+(ArDKw+;x+`lxxdk_VHihyz*&l|ikLb3#Rr%8* zp(gPmk>n}fO%{+S@PD-;^kGj}`oDP4&pR|W3SUwi)ARdV6ken6B&??(xqt5w3qGi9 zLxYjU4KP(Wdj)pAhdbQuAzJ?}#Gfv^f~-$HPt*MjzRB&{lK*5{N5@lPQBOQVbZbS^hCEV$ua_PcalUJ8OP z>kP5$_B_66(eq_b=mpFA{9VaM4KPm8dmf!*-(87pI>kt00V6Uc8t26$xDTSA;no>_ zY!{WN4ceS2TuI5wn@x0QaUqp6S;TF|>TNOX-S)6TmokEN(c@XuM9(Q+SWn(Mzk)X} z%%!vzmSJvZR_-E-jRvv51^I=&VD(Bh=&Ba6x-ESL>3v7oerI&F)373V$+qY06oM4v ztzWD>{w#zK)-zqIkP4XWkumTL^QJSkEZ2_L7h3EEH`+Skn)PWGe?=Yw+EK!TEb@Ea z{B-$6k9}7@;S>8KxYzYq9wgMFTn?lRb?m6a$8FByN`AUSfwh_0;AXpBU&yBCtI|C} z?Z!F@$ZA@}r^TS2t6sFi_QY-k3#yu^BSRrlV`RAw_pm<^kpUg)Opoz%{Kyn1_luVV zTPDoK?C(h|I?`D*E+9Q2H6d^?_)V$*szxY@7!&YyHI`0E!FHauFZnI#yPf00z}x?7 z;AckrHaZZf8IdO$`F9b@cQDGT8RoWTeFSdy=~?@gkoD|;<6w6(f4%-y|5;JpqUK~$S?Hw#nV84>-?mN@_^b=dD z-y=we8Of!Ukb)e)GHm}+QljEI0HG7$LPTnDsV|o!A~R@(?g1{h-zCnmH!7E?o!UCZ zn!9>51vdtn;Q|!8wn%MzTR()%Rgh>Br-;aa6)nIn-<~!+4eBU^o`3ghXiU!lCjQww zL#hN@H#7DPC)>9bWEsI63r;nNic4CF6l5b0#1LZY{^?F@mK=bk@wt#mlL8pi@h>Kz z9)u&Q>BD@*$l;u-!0x9FRP~X98%zA;>;G}Z@#`Aq(H(9B2`gurfCmIz6~27^XZ?)u zVWE#@$i&_1q8NN&^C}>L|6&ASfsG75-Rs>u_B;wTfCn|=p779&#b-||T<{mg=EpP- zt;bf&O6D1F8=^oRt1a^;;r$oafs|7?Q9;fUJkZ9}M8Xx5#@4pxufxrSF_YDOu_>2*>5x3EtOB>XzXrh(?B6mcc!rdb%e6tsEl?- z&5}g8e(O66kY%@9hr5J=ORf>!ef^7RQw|P^GJBCP7h}UFYb`q5=`f7X#J$V!fuTOb zD?+D%CC3FYFbhfpWmBIh=JEv&q+7*)e5hT+Kexlf!sSSz2bv)FiTMWe5*`m#EbaqAhx!<#!4{SY(RB$M zj8(T&@fpx#Y?7Px98e2l;0|>AU54xaR2UsLg$|lfV79${!~dSu9~ZGHWFvC=u}(>b z1+nGhvo{<;@;wHKHm8a%2Ib*x%S;IP{7!K8F#}#c<oGS_~tFI zIK;I@@ey5J;i6csn6dKUUIlPqTd~pStmZ^{iOf`Xqa>nh!DK96+LYmF;}EEGQ7s%{ zWoOnmTvlK^Wt|C0Vt-_ly= zcWphZrV4^eUKK@{kPQ;ieAz7-P*At{>KI6^>!nlTDLqHt^YtNc{luSXcmj$VDTiF- z(W{tj6VSn*Qh644J&;TNT&SS)CB@t@cUPBEQE(eCZ&~6o2mRC#cqmuiCV54z^Jgr4 z&HJ42<%qk*w=t@OhwMY8$~TelYM~9T{M!bmfQq50rah_Ua?O&#&zBEEno#F%;OHzH zUqX2qaI)t`SLqIYxj-%b(17Qx++x)aea)|wLT9PKy3c+WU}epJtAnVc>uY3NUzDU$5@QKiUg zKqUP46^w67{N1p+({1zsn=x@?9qoN2j1OznryQ1GDFN|#{J;l-zPYYQdC^HzcQaCA zB6W6VPv4?Zx$T4nSc^tR5g;CV9O^LwmOm7wdHzU{46XN={^(dxxTYmKQ*L_rutQYV znB_tYfSbmxU-@!Lw5HOd+HQ|V=PS^tZcl+G|jA1jpJ!A&wk|#*4Dt@ zOhMhWrLgkX@LUM3@PC!CC|L+ z(qUicfVmqr?mkp|Aj7pR~C*B9q_}spIlS zIN(M8&1;*#Tn>sRACCNahEL6lIVT8fsB!2eu2?mq?vfd!>-AZ`0XqJ&hUH*UEImc= z$m4%>bkNUD9EJ>_Lk&xtq)TwJ`Tq9l6L*lq zH#;VO*C}{~h%^g4tqYH5Q7#=J8Qusyk(ib*>6k8WlT0t$xKnXX!p3B9HI3DmrlU(3q6YkPjnCtR|u=uGOU z#KZZB@q+|LcxU9QyeuzFpo4x!OX?HGv&uH5O;6{?H@ykFIPzN{e!*wykyvZDrqZAL zY8+2`h4(*WX{iczC0xN2iO_sar5e+#S1^UCDk@|09S!-y2<6@T+l}cc>%@QBeWMH0 z*?3l#EI+OR!29SOEk+fdx8vSJey|<;vR>=*%s>>LCDbmze-ii&8@Tg5FxOO|0(MX1 zR(DwytD?|V{bO$i96J4w4#eWlpX_e|DszYT<_ks%f zMdy@cJ^7+v0~;Y-`%yJdWIZ^hFE!chw}a>unUWI|c@JYH>i=ilYqJQXdQ8Iy!~C1> z9|JCGzFd$)Htdn`1L69~GnPnx9heObgr~v=;m->S%GXs@u2RBDt{{)rgN?JeO`Tda zul0b)oo@)#ivuCg-kCL{HE_?JC#EEmjQ&WRpLk41*_(0XODbUq4@j&kzr_mPCLMWJ z%}kFq71S$%Fra#$QK$!J<6;nxABZ2MSYcF|?3Q80p{ZsRuzTnNO<%s7`B*T@4x>NY$e^0T`n&A0kbxmtyPJi8R{)NRq$lnYuy`9#$}s5RFKp zL8gEUsMTnF%M5tDp{bHn%ekv7ZQpQ{=e%X3UYMnvB5=JHt%e~4(6 zTNEQWZN9$H!K;plhK&Cw#QVIFQBvR;ZgWW%=jU;sszWf9%I`+aU4JbaECb?wQR2 z1S;*K_)q9;2Hw?wA!Ws|;!0UlTOjCn8n)cU7*aO<{C7rOf(Oi9(ZuuE#SxQT<1$oO zhCpS69hE-xZX#5JqI+!@OC5E2JAiH>!?2G(TvtXYN8?jd#VsVn7_Qbh+LbogN{FR*mEv-PrNZ9Ep_XAcBDgSPpQMw``N0Hk(t zv-9uhXv#SpR}SU--j%JQ^rgd9|B0MXRUw}i0CSz0duJBZ#tBd`uH^SZ3jv_H9oh4; zPHE+NE6c*+T16d8-MLC{ZjkDfUt6Jd;J+%19I=0fAFZavoYB9}i?IUXn10u6SFVT+ z+SsQ@!=G}6*cX7ECQHR252%-I!e97`tivyp&PG=*bPoYK{B7ZI(haoa(;xIEzF9@{!jv|}d-XrfI0viG(fWo3m`~FNM;FOch!>%% zRi7<|HsdHqaWTLexhx4#iY+DHpEftM^d@{S3uayOhd`N1Vttpx!zjX=PuQ(uiOeDq zqmzW2C@6WVv4kAkH&aUL5PCJhiVjvOB%Ue+L#um1ImLALH1 z?P{FtRT~}}68?#DcNX-X6joSHS^e)`BVN1@_<^T`Dvr{f7T@O zmN#2hjod|C^~1ub0d&y4{lV~y1jiwTG%%f6Z~rf@oPxAmsBIe_GAPb9ak%Wp=ox1> z8lx+?unwF?_B?1wZGNk!$p`DO+^UWG*kd|CK$4C@daFr+kq>6Vl?Q&c>}&qV^XL)P^u_fGs=y?~gHgKHey$1X1dq`LMY*}b%o+&+5xVT_yf6y{b5A*; zQZ466FAaWpmR67_CL*GV6AWsNlP9MEa{vswb-b1*uL;g2fR7I3NP>2`I)Or@?S^k;huq?N62P8ucSN>RBj8~zc4%i&z^!+S&v)& zNW2E(&l%d!Lp zMC|=Y^aHJ5e}#dfR6+NsbvK`j6{eB42~KkWC(xB~K%neOp$ye63-Q!LE3RrGV0cQl z$G6`d=}elpe4bhO@;fr@4h8)6dsWo3k$Yh^3SU|pe41zNfe>CS%kC-a3 zzO5v%2t45v?;LS~(~v@SOB_g+Ji&#=p2g9OZvjqK53>(jsg=QGcb`VWQMC6|iZ{SV z4|<4(axp|u&CvmGUhG*}VCT|0mwfF!ZA1uIoztQm)rts6} zF$syoV8M;+JL8YqXfWkI3eJd6;E!4(OOESxbcVn$@qLM>K&V;=$zvbscg`e;_2Z{; z(fHBH#KW0FXS^`1LF$p4M&a?~-!bS=BdfoHQNGHm@^QTw0mEh z+sK?(Yn}iPM}9)nt?H!MU_BG7f=uD}k35B8SIm7JOgjz-VZml3dLd4o=9mmB59N*l zh)-$zF{^8llq^Z43RGevoH7RxYM=f%C!!(${M~I%-M8fck-WzTOY9CGW@|PU+~A^0 zI0~!qw@JX;oX|hV(V)jXyc_0rPaFzs@{RxAOrv271lbDOg}*!T++Jz-I!RA50!jca z{T`U;EEps+j(5o1P9*s5;Le1tz2Zi0H#FSUBa}{D^_~qcC;w|>A*~$l?fZy@zU=_> zrT=(nDZ`IH1r6%CBS&SIqVX2e1p(_^TgdwTW5zn=e?|Zv5PpGK5dY;eJ3leCg&Z0f z^A_siP}tMPHP;5%;6u#eo+O^MYc9;)ON%3=Yeilip-x|55tbfUCK{a1QbeV|mppt6 zp;bcBuH^WaJqAk4J+2Z)PN4TB)8(8antD*nm3Q#;E#t5_LxeE=EFABm$ zTZCyLDj71Kb3H$EL^8)O=GTuBPsDnNzdXh~R?T=iQgqHwB-aqBQB7=dB{6$bB*G9a zwu^MSg}Quki~b1&oq*p8IW$YLcfu+(lp=l0RseWjCHc9dPsvCgK65xrK8A$NtTC!X zqsi|`-FyKQsPus34N8SW99228DnEs5S?u%(J|070 zsOIIHTqBI?gmn2CTHMG|C0WYQ?2|D$Dt${GInukWYDPXR#S9@=-lD@+=jMAx-M&s4(ZzgTYgg*Ks|ghvi!; zSEpqfHm$jdV~6>=5UgX*lLapWf;#To0(LF(7)?GNKjwK+M4Imkzk?j%4Cg-B19POB z=edJUYab+q>OvXzx9z9+h?Z&L?Te%Qp+7!lEx`0!TDTxsyX>BT^`-li&e8bu(%=8_ zD0h*m#KzFa1c$2_VY3ch;j8Ft-p-C@DolA=fo{MwWADdTmu)$u*$TDh!9Ggy5$#{Y zP0`Um-r!w_%NQhcS|Y>T$n34Aj8yZAM-~wHRKpt9@-*k&6Vo#0V16N&yY#IfRVMqx zuo+HXFnRnMY>~3Vcq7XNOz?P!%qdl8Otww>lb|9^txBP%zFg{Y_{A2x@g(NRo6K@& zeWmoM%D=a+!g{z7kss;##{&qcTh$IugUTHZ9Cb(p%1xTQX0j?R1j{`5#O)?roLF_W;EzJ`+m2N38JGRig&-LTqT&Tw>u588gY>!>Lck0#v^0;?6WPHpao3BOB z>om+5VC&x&73S%2qLB4ZW%e8Ut}TDFEsG%!EB=v&6fO{t$KL4@jL;eFZvr%)C$gh5 z*wqL!cFR?j`$`FcC7%wW={pr4Rm1!t*s9mtGNUkE=$XU{XOpiYme0SR#}(`}NRFxy zP2VC_-YE%e#PJKxgi{P@TCZ>bg3M??eOWarxn7kZ)R`xIAJ!pl!FP4a_`93)!SeZr z>oC7en&$btc>Snc-Hs~FX}T2VD}+-To%hT)Qw%hb_Q&D9?+`k#+_@KV0y? z!#W{BnS3ETfvc*VEsV2KZcus$;2AN>Hy}{Uk1KK=*;4kp=)Y#SmzeBmP(Gtd)T4QL z`I2o`A1JXAH-tR9AHhE1i~R^c&boxe+U8c5`Jk@2<31fUes-SXjKiO`+%3N(pL`S7 zrj#4D=&Hohvb~62U2|OG8H`Ewm-f#3H>j`Aipb0HQVqYyVcrDDhuiLTR z*lHgs62$qgDc@rAS&ELF{@sILJhjsGsQy?(O18UWp974&_-J7!D>ERLHI?jEbGs(! zc)9E}NLyuNY01sWw*C78L>bQEr8hlxW`X^W`f3ybj#-C5BZu~C_h#E2T=o^}!3*c) zeEaB+l?9Col-l>{FD9E@ywl_+0aLncTg|h zZ_9e$4Q#KyVt(v)E#>vYg1Nr|_r@41;^Fg=F>eb4hlI3=RXVu8EtVo}x0s0b#S$e; zh);$#6P4^_s3?jN*_Z!$ru+T<@9TB%>-%Nq`8>}#=lwqKbDr~Y+Gg7(Iq7-Q2qC#G zn=Sr9Nd7xQVtZ#u!cV-yf8k%uWN&s3KuB*s{+ASd$Lt6~f1xcF>+OP*f3!9Ssy61{ zZ(lv!(D&{%GNE$Th`poEibr2(l&g~}sVmiwzo90^6F+9SsIRZ2s;xd@EWbGSW8p6` zX5H8E7w@uLd!whwL><(Crqv6WoZ_L#5s@>$odYS&ab6*3HtPHzO)LvHcd}V{$qNMRK3uo zd3Q?danINM@t9!y*5`X$hQlHp)k*BXxkr_T1XX9lbch9`*UA-ICxQY=wEeyoKI!ul z|1~UTOLX=aXiwRzllZo*@Sf?h(VXc?Q|(XTT@j_Z-{g{CSvt*6yk)5Emo^_=|A*yf zQSNGyabPRs@j~Adr8BC#iP5!V0bMz{)e$dWYE1>XkN1VOnHArcy?>aRvNgDH;o2gy z%nG$#0j{mjZ|`EUyh^2L0SWDEKC87xj#8P&Cbo4faZ~vqmEzg(Z>JJvdu}zq&N>^R zO#``Jzxqn}(|c=rviy}h&M{$=XRtl@OpL2q-BJ?s?;-AJUf+08_bkMiYd%H<2oK?I_Gm*G?5L&pyb&WI`;kmV}7cK2c_+ zSzh6fuZ(^dlmuEK6u*eB-;op4EwnJAwuh-B+b3sY#`(pE`{hxhVGP8?D1U=(3yMb@-FNM@DYlR86804JhEpZUe_BIldknX4G<}__>zxmn* z17`jWKgMQh8a*pXk0A?W(iv(6`Pf{SMCQ7MPsbyVyjuJ zm0Uu^9AA1)&v?lLfYP4PtZu|S)YOewpYIwY#Ch*r;lb6P{e*7(o`Y@TNFiTS zPhNuKOuH>_(j?q)6vE!eCtCG1LV}PI!-8o&dLMn@#S2GHPES;`8)6KXS>1Sf56SxQI1A6qJ3Re{H zrt+kb0>8$>C9;UQ18>P|F4a0v92LJ?s@IbL2dVIV4DJDUuxTq}QWkOO4KF+fdP)rj!dRcYSbK;$f<}k-7aoYkET|aD zDp(g=F*A^52$ahfA8%jhixL+AX7(_AFW9L`2+SN~SpTjO=%^+2dH=>7VSsd-y&;!{{&5 zr;nCuPq~W@&D0bmIZ*xGVdL9Z`TTmCiI+ScsFvakku2qX8KD}QNzTvoHBRCQd%@}u zE%`$d#7At++u)`ZA~%hk>4^zekQ^eFc+p!dWRdL$dnq{Cd*GbQeFimecO&$f#l9Nw zw2B|wJp)1|uwbzm=k$u(@}ah@-VWh;nXc@&{B-yg8ljNKQQHx32I4$WrX)1lK}ed^ zET!Z>p1R0Am}x79;x1~1RXxb0AkO?I77MZzI_J4rb3`NdRPs(+FflqeI7&=CG@ii} zFN7ExxzKLIZSKY&Z!Gt?_RE#^>FIg}blr_*=+AJPS>@R!&_gVinTail_=fF%py762 zW-rr!$WRWVc6~jy{~SicwWQm}C7NZ86v#v(rah#SeI^Ee+04HG&E8)g5f>pT=vFP= z#g`-|iXX|#bCv*%Lt`uErHvFxA;K`6gn9kt&! zwD{=(M|E-bMvSshKZZpoj$J{Vp?`t@58m;cpLk@H>;`eMJ5&9G1R4=yq+jl%4 zc9HZfAMxKW(*CiY#C!s~i=Y+9(HNxp9!F%QFPsm&Gb6}omVUMvhMq;puE zI{k_t#67ylT$g5ht=b5sd3JiLMZE{+q2X2b^60fCh2%01D&p5?ZuLjX^8uM%P2EVj z#SWs8P|29zagX5>^Am{KP)cyW&LeXs=NL8`v00@~3NbXs)m36M!=w=3$w=*;9J=KJ z7HVaueJm^_OD2i-52WE-(awr&GZ^@kL!-^l3cE|PSx9e=X~1zBm+TRSI0^LI)rn6a zLfG0EE#VSGBA~_8^TPQ@{Xw%4XJMhp)8@b;E6}EQN7qXePv!FWwP5nKdUcOCX6-M7 zh`qAa+tRx!BjulpRwI^=I&~O0M|fN->@V%`whRbRPW3LYPD|{!IgK03llV`TC?*yL zipVaTAv%>sX2<8kFZO}5h!BVU2rO#Zm>;_$&VDC`OhuiClV)N` z7^@fJ$|;KPGk>>jE955so|q9wmMLSGCKB{SnV$t(70w-sB-4UILcSwqviaCLS$$iG zN#XJ$ekjO5gysu9oTkHAc`28U&+HC8LSi4_9#x^{*TQ4ykI%+{<*J5{A&x%Yk=(MA zu}GIlYH$4u{R?bhVX+c^s-DiisRN;WU~cq{TR~C3kDqq7v;dqFKSa2r|2C$0U$hPc zC8I1$_5f&)#OFcGRS7%_3g)1{l|MvBsz$ArT}MAM6)%Q}1XJ0b(%cn_iRVG`z|m>j zxnQunfDz^k2mgW_{7x@~#^r0?Lzo9>mF7HPS>0Hq26m}!~X#MXzX93#+F6_`9aqgpt-W& zc_%zO^(f|QGzoA0Arcbo0NiKsLxr+(aSb46AtBS`c~MDN2@o56JF+#7CICZ#h}q^F z+}R(0a!LR2T+W>W_0HQ!-~-D&c0TNJ0FZ%D;(1>+!mauS1rptu zK{&zc)Pw43(%>LHZHHQ_P&}mX3vxQ|7aTDIc>y*Q4+JkMgh143a#<{nI6BRnAmud{ zzLr+z+FKlkaJ8xzhBn(nSPP3Fky3oq&0$CPGbtReeVEv+An_bbRYP67H)~!=e*iy* z^okJkrr-Py&>kRyQyW;Fn3^utg2Rl(AZl7zojdcdkWj!SZV^MxO58SJj}w(6;k>Cl z3_e%Mgk9|`I34PqOsdY!w}E_8op&b2h&#$WsY}!Tne8Tl&RyX;Qu_hYh;y*XqWq+} zIf=vd7t(C8+J`lg-y71g+d8Yyo9bS&+;F$5%>&dR7v$YVZV=_U*hc1DD*j;23KQND z9M%)>qRq|wGR?)1t&!S^60nHUJ~)VgKSVh%F8B!cE|b+?3oIXeLscI{sbI0&rt&rV z^EuQ8)?M>a6r5qGT?ghuCQX4B#p;sH2;F@XB74{G8W(Sbkz-VM8!;A|k7b)!t8H5v zy=155smKk$d-3x5&TIE}TKdam`l}MK^gB?KXxZ#RHrm(7( z#9q+c{+Atcx@d3FBHuTUB)E@*Quf}3tn@X4&2`+T>G6;yxXza4zO0hKq*XS1KWEQE zCAZ}IRwLBOG|O1uq%4QxJ_-39Cv-b+KY)ZMmK0L}-(rU2cm&w9_bQfvZB`mm`(xKT zUw@T(aswJ^VHef(Kzc;+ECp&`2H-~_JC^6sMN@)u;y&aPv5@h0#4rTg%;I(C`UXm= zHP*?5fNdT$w{Kil-AX(ao$4ifr?Vpv8u31}gYC4>R$UAU)#3cfoUM?GatMcSWOcl)@+)5C6O#B}S0Yp$n*QWN+L z@z&p{17IBD{Y(QUWN7tGlAInx8gK+o2!lmBqm&YW7m^#!CJe%v4AWyqme8*)l1=6r zYd1l3y?Nq4;tDD7kdJo9^QQTTCMKE4E&3yIZT2N`MUf6tp)>0=4@vMFm#S?9FLWIN zZlDjO8H*=At2gyVSG-1kMBqcMJ8i92r=br>=Xk#1$Hp`$c@e9@yU50;@7+A)R(9T$ zpL)r}SvsN~oIN4pF&{8-V^7O0*Ui*`nPlGhbKl9V6< zR6azjsBQ~zaSS538P}N5fbsOB4?IW9*&BLd_JMmCNruI3AaZxlmHbWO&{aPjEnFG1 za6j-3Q(OZwzp)tSI}rOoot+fHg~&!Io7o%_?9J0t3WSVq?Xl5BjC)DlXfdP#M9ct7KZI@U$J?m2lUjE{q?mxEaAMARBF#%e0d+6h z1&{+rlGleJ!IvoBtIX|>EY?VY9V{$<&~q{YIL5FCSu!#eeJgn(%^wV`PmmTAM|o|pFKMU z`E4FV*g|?z_bjG^gGZtQb6Zo469glosbGiL0`p&QXbK5KBdt*Ky}g5k^C3#Z{W^rS z8C&zDWjf)Lh6fD>VE2ia|0Hao0Z+~ohz7D%vi!+0r3!UK$jVmF0a{Z&31&sg7yb)) zKfDwGSa~J}FwHcJo&yxax|5@#$t;XY(kaALvZ(Sb3lWbR4$hEDYG>Lb0n@uw6}3TM zg0+C2#7O=qZjlk4IuqQ#3)(()FPsIN9XtvYm~WbdZeWUpMo1dJHzL8)sIC}L5gW^I z%tgXYAvsG>XslLPqEf83a8vjq_* z8a4))=LZl9XUm~kv`|q&L_M@b4!J|wG2n4wR!LPgz$31HDMeo&;#fadnwJ8V*~aoh zoJkuSz3#3Bb#%*v{XA> z#gIV7<#iiFIsKLY7g;`&|B4b7(*T=(MPDltZ2gbiP2e;pPijfDL!x9OG(QMC+4PRp z=?Mwc-Kb^hdn^xVA=iEb8*GZ=EdZTJ+YPNSLC+Ak(E&J&0xs={lJnh$qWhZV%pfxn z1rW(@2j)hZkzQn+jR}O6P)`0C-u03&IL|OJ2JO(YzCMy5$&X&6tAtyI7V_3ial2 zA^~9vhO)XD>1&wUby1-Z8vkI2)Y?mdGBPZ#M(FyB%p2NBV9T3j54v071LldC%=sNR z0K>*`fTrXxGq=~kPZ8R_+eS0^^x5WLs9TP_Lj((_l}1-dDD^-GyJv}z(flVfQk(bU z;&`1L?0pCCZXP57D}K|=Q84#v$=}Bl3f}T7yJv9j%#*y)i?QWYY#*#AflLprS2S_O z`gMMO{!2L~7d&{_dBLf!{aBlEbm;fxi%;Q)A8vOrKD0mIV-_^t3r%6CpMX$IL~nY`$Dp{yhm!bQ}GEw3zb>+eha@4F)9*YxhrL847;VENa{^a1?6sc#WW4S-Zc=$ir@$ zmipY5NO|ccMSMT(AG{6d>Cw(e@?FHFMg@sQooNr=brBSAP?z>R&Qbbp`I_B3$nnr! zgD`U2t3Z{H@;$EO5^X(#HW{^~9LD(@ZD;>fv_Vd%lGxb`)N1OowLp~uQU5$hPSl6z zQ@KayMz@m%!F6s0WJG-N73H!-HSkLOz6QGw7|sN}rE!5A%BhDGEBiE>OC?c_F=w-2vn@A^;X&1@6} zGtm#cG*ek|MP7vp%@G0}7!!{2<9GIJNx>tB_Bt<)QYGKjVwWS{hD>qZL1-aXE;MBu zhnFD1{-L3K5+8@8$hcK_4}6|#(*EN*g&I*?Nx@Oz1BwX=F*OPy3IzoQ1533r5AS)K zy-^mKd`fCxJ(t4;dYx~i>-GcC+&Kh=lR8*Ut>R=?h~TubY79!rjE%9!oTT>rg*6M& z*68&eulcVxsBrjTgenmV6>5LZ<{4e@?J%G>JvzgSl_lpBd!X0-ZmMD+1jI|Gx(k)-AeFWDZ#QPs|En?e0QjB_# zaF1(n1c+3VXL%rQY7EtA`}O}y-j4ZCA@G_A^ZJl7Ut|J6BmZ#2t+6F^{q*^8M-gfJ zh7`V-9z^vQ#gxur-1;njWzAsDuG*i(b%ck}cI5LUvXIrkT4Bl$JRa?a56a{WNq|9E zUEu}G$$}Mm+@sL?feu-Ky$I?$M|@w+K#Q<~k-&{HW?Anp3o^|W4pQ9Ijhya_WE3Oq zj~2M}frYyx#OAgS>6! zQaCrVSUc58Rxg&S^^$~<{1(e{QQl5I{fvxg)<(6YY-acr5{!a;wE@9c15xP@wJWn7 zvlkM414;TA^h?}X-dbcj&(HT8&esAy>=Ft3qsT`fsIr-7RXHSqrJ+dm30J}?_C{5l z4g+_zn9}tjuS2`JD1QkG7K;u+p&u>F(;#i5DxV}Su84*E{Q9F@(uDytkbZ8yh6HUn zED)-@jbMy8LoGh)9IeVce(yV&3EE_O+7B_qUys4tC-Lr>)Ma0H!=9uI7l~?;U^RfY zsax-J#!9~i__}kUhU8nMvF8%@^Sa9(XP@9|gR?<3=_ZLe8;aH|Y-m{hrA;x5#XCgo+1C=32?eOwA=$6HpjVs^OW;P$NM8H(EzyU0!3EhA z1N$VjT$<_Ek> z4p9?~Fv`VgVm`DsL23{Quml5dAP8>hAeeM=-da^p05|YlG-!Kx>lggl{>Q5JFhtYf zeO&|cMUZ3yTj+;-hfjSDoPMY)Dj)-C4^^lT!>;mX>40pL+?3JdI>BpwCdi4m^eCz( zum}B2?VC^spzwMS7HzrG(BLOl{3klh02RL>ng#fl29CTJdNp7`tG~MrA7c9bA3@O$ zMa4m36-6$9jxcfVXt*TjbJHKH-V`-><6ZWJ`VO)cuc|WyvU+Zh2Te|}qOP4S&)gW5 zTP@0L{5*}!#+XlH~0yTF4i||Q6CRlL1|!F;t~i#Fu;~f9(=jxFl89s^(*jf z#|nfwAOIgmlUI}O-jC&V!YzYf{||NOW$+fRsmoy=%cE3EaV|BSdgh1jz$(Z2#c?sv z*%0bNi2yxxXek`<7AOYata|;0__(*zI@l2oSe>geG!2D$E%>s!4(mrNS1-(B*>>QF zsG27pO@BQ3r8kYt+2R~|>GkoMDt@{LyupslUm`nRY(I1jh)(De675DNUbnDt?>*aM z+EpEGrTc_7D|sRPoVWbglD;yH0s5yq_(j1UO!e{Sn)GD%BG)EY#T-8xb;JZT;%uAjh7p!R=X9_h%7C^-{T*j=?4IyRStiLML$hwlMo7k}#0R>dea%LyUy1 zmc&6}W<*f%wvoZ=Xi`MazrwJh7>HVQ4+9FPb^2k)7U)&x#`BDY=Z3Px*bAZt+l!C1 ziyuq8l$1Rpk3uWh=c{@0Q@NUx)71V7V!A@u#WM?;OHJ}xAa-u}7~}Oc^x$YJ&F#!m zm_FcSeJcx*MuKHgx#wV5VmgX6RarfiQEe-ED<8VZoTsXvxP9qsIJfpgU5=7JETR{c z^g$`kSqR$_g~lehDnpE?FJ&hp3|>W0H4i>5oI##o>-t)(tdJv~0NeF(ye=)i1TemjRMnbK$Za-0u(#7mS#oHsx0F@x+4Jlp~4b1>)blZ5Vb; zv_MLvzvjC#wrF&+E_2W7>!EeIeR99NI-`$I%B!;Ud2hKwJ5YBy?-hej*sJ-Wr)h5y zL)ov?7Xp&AdUUV#uXdi9YMpjg2Ro*9jWIeq|?8M-u63e z+D2WB<~41vj%0RUnAM33VKkBgn;Z&@Xd4cLAhT~9hUu8;jpeEHJF=+#0lr#RFCeeb zRyViT9pJ3^R_5UfZGSoM3qd^Ny)QiEejTLt_jRmf&fpQAoI5y zDwArX$mYejAc^}qodmQ@X;XU6Ne*$-bNi+d+W<5g+kjFe$*I{195QVWR@?4 zamvu6X@wv(yiyhrBa%uHy}7lY4- z!`dj`@ewn7&RW&jWADX0%g>fgXKQJomHyMlDAwLVrfTU5~a0iUcrG?Ad7zV^pBa z+|v5Sqf7d-I%pZw-u@Jm7ov^hRzq^_A06X#9{Qnnn?$1=j0+x*n4oczYyVU2wGa_) z!;`H#`L2`C7&EuwRJtfV;FTtODR2D-UtbAC_{;IefG!i*w8fwE`mbpsH`a)2w}Y=! z3f9butV_7fOQ=CzQUje*&TI%pL?p_p?n{apDW&%3$BbpuQE;=H=`qBU$VJ5*tuV%Mj|^f!rgue-nYgOm1dX}@NlAk2>6GMql|M>F-+$W}j?N^Cx?+<&k zxr;9lB#!NwmL@9krlG0G`3Gb$mZAkMr$O$w{C;HQU+D6wQj zRg@;7lnfXc3~O_@#LU?SK5)VS*`Lmyw^|tL8mv!({uMas1<+Mr#S-0S9Jp4m*|WaF z{fF{7QEdG%#8oF}2{6w~&%cyL>^?7o=XHtfmM=G%Stz05VdkSD7X0u}v$y6V*NFNk zvlrT)Nq_urQ9kXEpY0^t^9ua@rQW>b$fjG5o_UaD0>dDTiykX5BI4dGEnWvakmo`F zX>BpFM0?7$m2CD7vec#e)j#BeGuk=Vaq4EajFpte#*|u=N2Kj^QX7v(P%;PlEA1tv z4m?FD(1F^|l$RksLu7r%aMJlq?(r+b)?!cN*Dbggsbu*$YIUr?d|C`6T`><~uXsgYl zJhd#!<;8yAOE6nhFS=5Dv7COeYz>SwZ30o_tNgKRLJ!IYCS2Sg<`dl7$^BD4#$5v| z#Dl$+Mbj5dJ%CnBOl-`Em+#C_dq5U{LjqT+mP#<>QsqUAFsS_T9$^XYifd)>`w3!L zIn%q3kFK|bGb}VX2O(zlSB8$Zf#Um|7kFzCBKilzrc3(9T_Ljt%7n5~@dOIz^-j^n ze4K+)bTu^0Q(j#+^*Z7Vf>?psAT@FU%kh|0J`aT^X@v!^jy*-}8Nrick4yUcv^%zY z*e?J47-S2}qi4Y(K>)9-3|~7l-^g|cY)ok-3Dy`47)+Fihx>G04@Jt6e?;_B5r3nX-< zq)BM(nQN+#n6eJk_s)G{BM?Es+(i`mdFb4GoM!nu+J^f&*yFWk-dmxX&3AVPfaSoj z4_rwopVccq2Pe4NF03xK3!;ViDUmr@%AfB1gpB$f0~{t?8cv1jin{RnpZA&ymK@ne zAtT0FQ844MbIe~?a9WO$;>&V5c`CA!Z>SBOON0VMR2q@q%dCU(7oy&ISTbezHBmt{ ziwaFdT))y5LHux|^v9v-WB%jNE&&DRmfv9zI_@x`RSW@;c-fHd+Z`P_FMR4C&Mlpg zTY$u$7M^T86k~=$Sp{G2!r0g%T&$q*;U+_qw zqWiMMv!dJlbzDfch)Fs^?N9BV!TO#C|8L{{)4W0>!Zt&cj^Rq@nv4#jKm|*eb^ise zd}2Z7wRw_=eJrdk2!P>I1io>AkagIEx>ilJ9K>xA{Jde0pVULKuKlrnGd*0OKz3^)|boi~B|MWi472>*Sq@m#qr1K8)msbt^2kBb3 z4a0@M3v@(jdobr5g|vf&Qc0p4m!)8_d(f2TI2S-7LQc{r$L2J_*K+>ICPrp^S12Bz z$+m&74s@Uh5VqkuejvcmTjwrAA3Ju2TlZ~$-YN3gR&{oLc6&2ed8WUIPoacoe z#ws8bG!RqqA%ydFCxvL$Riya+*SHiuK429eW-2%VkdDsLS~lkb7FhfLv>k{KKqH1~ ziRDK#S`N!4zcZFSOMLNUseW1yEV-?1SRN{eKrC>M>c}LYsa8VDS@oTJId_07&wbu% z!u}hF2r(PrXj$Hd2PSn!$oB@DJpQ7&{@(;tD9mR<^WUClQw5xxnE5mN1qH>`Tx+W( zW&^WnzJe?B0=+8K>FY~hi`H=gy1B+D8jI3^C9_}{94I{J&k1+_Z$p>zz}K7&I7mbE zI>?-UxOO@@sVl0$G;xqx;$akY{smVC$*O(}0#|DLET1EWJ_71|8}?Ox z$HFfs=o+`qzyk)Y4YVQDna|a3N)Wf8Jex%=6^*u80c>?Q!hcX`Jrt(k1zYe!TaZGu zZ3wCo^=F;ZM46$ho5K1D9(6k9#|WOITq+7$ou}y(W?`tK6mx%6cROPtzOd;hemQtgJxZV_X40#5d;%ONT#;Dz44QWZ*rL) zC7L9b{9!5OWNA?c1+vY5v(yt2L%lE@ZHIB(Wu$`HXc_4S>G8t9Hj1&f zzVn&cZF53mp|Z^ht%XkOPHg>q*09vgd(OI{^XY4=UU#kV&iVd$f5&pgWdmyG*g=Bt zF5d8VgmkXCTPH{`AT`d~LyKP6hMjGuk7<@pRA}$AHqLf@}Xqj5?VIrb-vZH<#s*Lp0zb${IRRoRc42ih7lN z%^bWuF2oxQSbP6``FT1EW&JXxSG#y8)UM~0zTpS8A5}oihj(K}plC+Sy-rZDU6$x6wqD}nLNhAY!M)R83XqE67L3U&IuOGvZJ z_~5^1yE1co>Y89SWn+0;km@;!f^SlDVIJ{Yb+1wFYNw2vZbUp!{HVlqvIS@$Hy;RN zL?icP^J9v_&c;mFx~vK7zTRHfiMQEERgVlFm{~H;-$de9o;Y7Z_Eg$rX zUlYT4SoNG;vZ=hNuIXOF#JQc`X2*Ed)6x|idh^f3Nv7*a#uo;SUaZJbE{iTw(DTn^V;;>Iz8=6itx^~Zk~`B&l=Wjo>=AlZy?xQ@Y-~6y*tXe zyG3*AfUP>`#zb7qwUt|kH%{hE(FH*iU4*1_>mJVU2neKHdHE%rS?zG+xcD2-&PB34 zB*0%?Q$Ea!R6YMuj1x*xT{ZEM7^yYOZ@oUPpP9Rz+V81UYM2w`$61B=Z|?C!9o5AI zt5$yJ=|ceixUZGe=rYV2yY}s@S(5AI7{BRsf*g!0CDH6+f3CrfO1{KjDLd=T;Jmh% z-D(K=)ZzkyLwaC7ke<{q+1e1usP6JJJ%^a4(0;BRA4RM!mrN%bEnC8$n_HCE*EM~8 z7_m9^+x`!xK|5dsaq-9K17T@Z&pVV~NZ2(r%oFpxi<{RztyO(+yT#v)T<;wPC<2l7 zuKHP3S^(|eXTJGCDb?hbXA+#z)zwyQ?ZgiVpNM8VDdyskWwRBhtzP8U5oBcJ2Yadj zy@(i2njxQQ*&!nM9qGoBjrdEimpq&X{^ciNv3!$k>XnAM4ZYuBUR?~g6KM)D7Ti249-wgs3s4wwW z8y+0Q=aPK%kV4q#jUO3*_PuM=eR!14l}idHF;n!GUq_u5mrPrlM0?hsy>TMwhOn|E zLNDh!)L1qL(lpk~nGhT!DKJPrBQsZ%+Mfe#u*!a zN$}OcmEUugV=6j)DRzs{m^->eJ3bv=hs+LY1CmmeG)CDgVYEWlD`q@@#Wu=|$I@%z zD$)zO@`v&zlrJv|qd2f0ejbXQH|3c|5z2shbN)xR2~>aEYbPxkz!&e-Bae}bomeRw z%cC)05btCUBj$=@d-%?Ql&D{K4nESacPWwv82ZAM1q!}wFUqzBv9Nw4Sjb%EuE>Am ziqy9B0NQQ30)fyQR|hF3)uf(0fApQ|+2dZ{0t+8t9`{@c(_Ycvv~^!~RD(fEA1#P2 zQu{3tfrwCbuTDEKa}bz$^JLlg9q@32-8=lstv>Fo__-dN1HPbJ<_~smvyvp2<@lC4 z150a-LlQ;Ti9*=P)BTxe4Znn+iAk;1QodM}k7yBH-0y4DmCwLlYw=#;6R!5r1w7Bi za}MQWF6WrnxxmhW6B0{-X|It4N}D|PEiiG`l$^MMcZ|@Ft!*28_bn`)*SqUR?$CU{ zzP7Ty_z+)c^X5m4Y?In}b4%*UOI*-Kw;7UqR32_t?r)1MgVUNDcS~s?^zkX+PrJcM zF0RvrUY%x6z-x@w_gmre3$cTJGQI@a2694VkLo9C`C#tb>A!zHg(hu1rgl?=4*HAb zvp2$S&G1^eR-e37)#jl2SC5em*rnDD$`I5ht>=J{g)U*XU;VMip6cJ4x6S+KPK(e? z2&HXfWoC%^$)P=5hBgCM{dekX2nNQkc$WonG5a!Iqc>;;t?8B0gq;@PoiY}njZe-z zigwxX!0pnw%{ACl;<--?BvF9Z1KCp5u$i@X>KqT>KYLY68Rd}nedv0(c=oTN_pzs_ z1FtsArS3<_ax7b)oEw}8Y6T4kr*ge&wU{fzW(n=^dI$|YICw2wl$|xhX6^9y#V%W| z{NZV45z1EXquW-`wfXy!Y4k?(Wu@~<{?J2QOcJF2?_p+$1e0Ajr#0MoEwOMU7IKH^ z;tT{JW^G2m{!>>0AG&KLP`271@G^EmR4Gr&1lhyM`FA!e->`W#i93sk(f}*5`feK| zg6wc(k;L?J`u6!9=7B&%%pvAs~>;|fAwnn$4n}qP=_DBABsB9(SNypY33*z za%c2joUZr}{w!PNlS@YTfzQ&a5Lz>2N_YLIL-2d78K0cfo(#B9e2C@6vIo?Gq6fx= ztw<_t1yZuE^mtVt1$bc9^%ydZf_Ud8`6IgSOh%x*u%Vq!{ zbp0icu2*3TR1dl_52xECbZ~xa5t?bhGPDJO>M0!nD^zUPX7CIYfKAEZ&%qox*?+FM zp9%)7^iSs62F?&<@B84@Ken;(64=V~h-Fz!OkI;bMwz|YEV!SY2F1%9!g(V21n83m z=P_i;&PyZII}DXb4jXfen+F)O9VpvvUwrJdhI69L_f)m|lZLRF38iJFNonNbGC(p9 zk{z7Y=IY?l%zSWU%05^x-JD2)*{S=GQxWeNE()2BV@LMqt_TmT$^TIO9tZBV!AK6w zlug_!twBGM7lkQiy3bpS1x)8Iz(YZth&w)9NSJ{*laQ99y$&M^Z|SbxpE-jr%_4%7 zwXT`B9qbAFg_(CwJO7AknD@_37MQuSb;ZRwo`oypq#C5G$8=l4d_1o21zJa`Ok{wD z0pTaYjoN+4=!vVONJMh--n+4X>$wkySt{*np;~^E4tlp>c#!S0i+1LLCa8pmlrs*9r3!+h-jHGr%OvQ74mMv zOg^p8(&VyM7Q9!64L917VD;8P#1C1p;W{uL=Ncp4bMOL*Tywkn;OZ{ipN$vFqpRz{a;d9@3*C4UdWXyon z2$_PA7k!F3f29N0%O3a|4tPPtwy;Ch5)BgI(#zUfr8})I2$i-@gzR3UH&y{v($ICy zFJwXs4n^ec?c8q>dcO*WymT?v4P}ERm=0sC*Y=p2bM!B}%nmyEw0ej8oEb>BW~uhW z!6wvv7yS9%)^{7$qYD*h&fj&SGdw-U2E=zm7KS;zm9!HwQzQsrn1pvr*DTwP6{xCZ*$1jyqg})B*`@m;K?_?s~;SnNEfFec& z#>jJFir9e9?EMFfjZ?V#hrgLR3xaafe)D5e(-h_ z5U*u_x6ii449)U{!eZ3vSJ+&1<&OR<<0Y^kIOrNf;2Ni{$p9*H%8PJ{o9S~BHhjzd zZq4~O*bpJY2VgGa?@6F`8lH)u*nIE!!jX4I7kSA(Wr}vtbn}9h8%LlPMJXauY8mt$ z*xK2kwfgrYq@1dxlbEDF2wMHgP;(o%k-HD~60%AQ#y{d=Ievo#@*Xx`G3#6MPH ziA!a(?pd2s-wn z$W|2q#W~VPKOSY3fVu=TsGYiHbI((9j5IDvDvi$2zi|*5SHW3~=ZcSLfK8Atq|89k z9Sm)X$9moD`Bw*>Pw`D+n`N#G(}6cM)XUe2xj}6P6)g(I@5`MWdDoLmdu+|Hg&(Pm zF$XVoDDx|Estwk*9-HV5aMys8o(lpKs@LpLQ!%2Q@!BfPnTQ4QUs5bSP;_$1?2Q&r z>Pjrjhk*xrZXT3^yN6Ab?~{Nz=0CAayZ=ucYXDgM_~#FitUkTozi9cq@W6daH`*%vNYxbiza1Z29^vaT#j=4NI8#E5E>w@cyGE-f$w=Oo-8J}?%acqo4^ zQIxdcm32eys@Od=eIv;tF`5EiuPelTUf^a3HLt)KQMtIn_))9*Y&%u(8U(gD6phMN zT8cAog4?`y$p{?5y)1KB|iC^6No)PC9LAgO%aGVmy$2ku=D|+p9 z&dW^PU_n90peSW-a`3pnfc!1G>kl&aE9CbX3e_MVAb}Pxb1=CiKQLZ*xvnWt`AzlY zr(u#G0{>Aaoe72gAH4F$?igSCKGJHZe*NMGt#gd;sytX54Sfw`rPxOc1lCl4kmrbV z^t-ikSH+6N8<5@uB~kFHqWqSx?~=|#(8>DZK4e4D0DrJo+ywMnKpv&$&1kwgl%ykT z1s4&KxBbV9W3N-8%yOJ z#;IBZSI_5lqYJ+dA0N-y&?kn}(w5Ni#MO&CTT-3h{MS!lfEYgx0z~;Lo?}MY2cZ$Q z=y{2?e~3SXO$t9-$4zuc({j(O>we9zqNEZv={}N)2tHN{|m~5`1u>E=dpFH$N1ZDowfyX$*m=mO8=iWB2T}wI5KiY?N+;>1nkMC~I}u}-4)?n=bwmbMeUGarNMEx1paOV@B>~3P z;fq{7+9Pk4OqAcEYE1hoI7K5ACbGK9asfJKQ0f>C`vgu^tK7uD@Xhxy2Tf%5^@M-f{X&!f+u1$$LGdwXKr1>t^t_NMXh zSs3^>9^kEs$q!BvFsT@*lAo}oJs0=Sh_yKOK734A=YJ0O8b@%w_uUspr06wtk{Sa% zvw;Qe$@`FSb}R@z0gNE372m<)Ft}3o?_oFG)mnGsj{%16W{=K69IrS0C74CBXBa&@ zErX&yMDIMH+^%OBZhE#&N26n4E(~LgY{F!Lx`6@p@E$I9)Ym{WOS#F}>^u-rpihe! zCt)-ZS5CC;liA~8IE#1Qk(XHmQgrt&s17(G$&u|>CTio6X$)FflJ3$iNeCAZO5%AHztAlvCzc;mOD^wdr zT7&yc%n!bsz6A~HLp3hr4#0%r30yD#ok5ZAtsrC4&G~WTZ%n@2*IytGuMp3uZenvF zVxRCsRjI(1%ICD(D>1D!rMYhgLr9E`FGE6O&0Tvt9*iygJSe|hCQ8yiD^?z%= z!;S6m`sf=efYQzLqTE;*o&Cj>dsLD7hY;kSt)DIiQwQRy zhw%FR)ge>udce%woCUGb$-~v|h!gR&TPE&!Bor*K^gwLg20bGNNINeogOrZq+E20b zgU7tcY_XW5X>|HF4`P z*(LOPNOwRVi)Z`2oFghYp5S7Xqw>#Y3C>TKNST8ZwR7?#3_&Nk;p_^6$3IX}@n?wl zPn_u|(u^W9prTm7i*$Pcb%eGlbV>IqT@^y_N-f&U-wA4_xC0P9h#TRcciiyqpSi=|^Ky>Wh(pf7G@ zYL`7#gsGtc80e#re#9>di@L-wt7@{b;l|w#F28t-o(Eqs|gWI z{5?C9_{rKG=iVj02ruA?fo(=R^laUG%a=iGLc1db0G5XvhqB)_uhMK)c-$>z1Q5JgS}BH# z20lgJ<<(9%t}#M+Z?CW7NW9|1-y(p)B>KwRkK9FA=iz)d*5m@UaBKa4i>XFt8FkIl5!9 zS_<^E(;)!})2Dn6<8H2V=Mzsz#W(!k^0xWBmO#D!YWe1=90_;^ZOn5`^Z9~U?e<;~ z{4XpA?`}VY>slZY#9ZXie*M=hYya_T=h|1~Cj zC1Mw4b5_Y~zI6-5WH5R2<M#2OM3__B|K)+I@hejIemmYlni#vC}Lf`#{p)6WgufGib9K*}(iQ_Jc zTJT!)N$aQQyb@Y}jaTjoH6vYv@8s>yfreXPnb8WZ9hwPl2}G*{71#Y) zbm_+&%JVr_v!GMw#(GE}FxH-$Q5_uznGd1TZk}E}ZX0%qGV<2C|8=H(Tg~o~P;bE3 zqomI5mrQTHgMRd!nZxUDoY!IG-=H9YANQ!sH4>t{+rmm)qHo7au`D0QB=Hf4($mp9 ztJ}(?HugWwJpzq?6rMxj#T7I|GiII0hf8JuAt8-C>9b?BkgJ1B>Q(3YsDHuqM8-u| zut?>e1WnFq6uJ1WVU)DqcC+9VT%Tk|Kz%}oxmU=zvTsM@yfAt9G82~sjedfTA;teM zoSmw>Rw7~I=a>;t+`({76Gv3)1npSRqA!2gq_ga>9^$Oo|Dh`v-!CLSfOb4+n;uBg zGH`VSSK9PHW7*L{lUIpA&JUp_LSz{Ps7tE)8x5}?zHK%?9GL!H{8-m2M3`66Z6g-) z|6LUJ_iyV>eV{-VS(dFmkU0tMK@IpTAEH}eGF$)?KXBEW_~?%&fGINFWF=gQ{y(C= zJP^wEd;gI_$P%F%DV0=WiYyToZLg%#LY77g2_f0iFfHh9)AokQ(k7v%#g=U>QJGL8 zWv9qa$j*B}p6 zcKX#tQ)^O4uFb2J*fl7O*G{FY-|3HoJK-SIIFj|OCAf*RWu#uGYN_|Exv7**=OMeS zc(I)J{+1_kn!q;c{ll^5=pB?k2E-R^<=0z{;(j0hb(y^6PqDU_A z>gGh+46NNddAU#plaX8RxLUT$)xFFXset?-<%w7KxmNpvpo4siN}FA`y$1=JPxyO| znH?=Xn0{Qbv3uO$z@?YSQotbT&gq+xdH6U94)tQ#SJ8H|%LGXO2^bdUZ=CN>gtyJ- zlsSBg{j@RlWMPf;^!B05mX$m!;MXDR#zbn(mM9EMixbN!BAVHeH=ay~#7yTz=Mn$y zq)MzzX-`EIQAdGynYyLXSX60fNe1(HqBY)>b>Ijp+1j95LbFbJE_I(R@T!m9H!(be z(}l9Ln(Z~MJ}+8INeC&Z#eO2kbl0MUhdbUL`kRz;=5LSZr~49WOXY1LDJGw7X_ft? znY7eAG|EkP(TM4O$Mzkg0<6UMuzjC9Vd1s6CKoDBELWV645UA&{n^g!&-&3gpEUT0 z;L)98EN-hk^ zrI-vywwvE6xxI~|-?5prLNwii%5U77{4<16^tLa4P9=948)c+->pV{SeLsn)cI5?5 zsT(Mqnp{i=;@!RS-OY4Vlr=7V;r)viX3=aEk5Dk@C|bd=%|n}ZRNcA4%@CTq_v_Pe zzjugeXSk=!=JuAHQlGdLwlC}}njH$V=l-e-YWPp3uB69rIww>$*L6`B*e30hOitOC zHkzpOtW(NVa;vXV!sxyCf(W0v?B&g^!C5v5TRIQej3`@{5JFyC>LCJ{FoVg9a%j3ovfJdFCwR*uK3_GIapPC zQapR~b9e#Mx-6VyWT(BadI!JV{wwY%+xXjMIlsE2GY2^-#CbMUBHOV*dyr{7HeR#dDFSfkx{0>>k)y^+R|pV;g{i4_yB6uEAXETBSQOFc@< zyRm>OxnDqQ3)U@c^iQh5^wqkFI@<$?fDRr)6A9wKYCb<=oYDU(jZFCV>7iOj*1mMV)=9Rwz223o_4V{6EzG4;=yLd26HxqB0%=uV8*>+s zl&E&69r4Umhnb6tJ71u4DtIYfPbtaR#3UC<$xNSLuO>YzL*l+XoDBd9xS{gi#1Z@o z7??M%?`E-f4qt85$JrdSFpwH0IB(cWP`TguzCQPZ!74KsCDBbc^+!)is@A!sn3nSm zEk~lT1(O1_iLIyq6Ph`PY6nZasEhq;O6#7ub40d<4L@Bowa4X7|JNn54++w# z1Xsy*vx`JK6IFR1kCJIZHrY`boIY`oa5h<8IwC=x)zZDE#_xT7q&ZEbKgl2Qo#R+@ z-b;omAnuhtv5FqH@>Rvt#^1B0=Dh&;bo~jrm(du?|Cn0{3|F^XkncEZMTJMUYd#eC{gVlV)e)OCtb z2zy#g?HP&k9}xKMFe}BRQJN?XwE>SB$7=edQOo`HFsXUNa_atTp**#;s(k~`8%%7E zt_}tiWr%_T%3L#5uWYN`YyWBdNRx`cYP{u_p59_BjL^%IMX`;U${zvGZs+wM5wmf0 zmLhd(ZRKwDvVyp^?IkF#Ar14nc)sr*V$xn)%%EfM$P6oaDOUAhtAgUaB+prrC`!2Q*lX+hvlh`&TY)i} zm0ThE-!zIbH_JPDD#NvSNg7IFtk~8Mek6ovV85v21HLMgJMZ$_)IS+?oiYtXt|LwZ z@q(PPfej7B7rPKcR`Z#`q1T$C>18;8Cb-A%nb^ ziz)u1znVBUK$za8#TI(akNvy&=`6_ONa>Y7(qWcl2y?+KwmqypY$C@G#ELBrvv)E9 zIl3Sb2_%-UL`bq2nXfUQ)Xy5+Z;w}n&d+i;lRJ_Bdpy(Mg_!!?B$6}}woBtZQ$POt z2V+NPVg7iZY66BPEB0G%CIouVwnE!=(zjq6s!L~{P}rC|dlz<##9k^nPJ98e@q4F{ zsNZijdn^!B zxNbL`6zy}53`0kw>rt$u@tuC&a?27to&l{KsX4GWVs%xDQ`#uHa+1;S&IejIUv327<-4-d$0cK@xm@5$*DZL8 z6tk@U2{aPB7DZ^mHyz}W7;{I`J5leJ*$gpL%$G|@n(OPGoEBrUZNv;V^MIuz3eBM6 zyX~uO5(HSb$XhRzZp&ek!x{EJuB4}UbP$z{qlrur<0YZ7JdT%T7_&9X`YX1@9G{U9 zv0;Jf$wmwwp?i(jmt9-tNrcX#9g5rL+h^}}tJ+;G13NT|09$h1>NEc>4HPvTmB&H+qL0L-CXpd~KLQS)LropUlOS0tV>?_+UpiAY4|Zz- zdq4$cu`Hu9Ac{FO+cn5(R>%aEk6o@h>+$qFNMlzE7N z*awvK{_xxxA|FmtO$esBFN~X8l>2*fY{0Y0lJ&l=*g)71qZZ)+^!*Jesh7R`8W4}o zdd)LknCZE`m4xjMOz+rT)nKX$9#>uT)it7kja`Skk1k%zNQxi0$Kzw9|;ZDPxUejKN~P| ztO{lHXZ>rPqNg&HMrQLAF`(2Lx~JUhTHqAAmDMwgDAC7*M#GowuKppZ7;!Mj)nUU* zip6j*33z7J{T*+m61P=Pp_(6Lf7wnR8F>i6MK701E~7 zIf#z0>YUMGOOC#|R-lDyG1>SX3kBtNlhkBlFV9n{9i)=s6|248%H2d z#KL$E`j!*XZ`|K@WjC@C?nW~94s5?nYgFJ|^o0q}!94T-Y8S;67ck+Yoc6hNjAC;e z?#ijmpg*luIMTY<9i5X!SzO^tRP3B?8o#Wzho$}|p>Z>kUf_rNmE&PQAaIc(VsNgB z!RN94#1nXVS5;m9v3=-Vj&DF&sHuiemmHFYtVJ?|(=wJFRiDXQ!FA z6hlkZNe{IBtP1i?H~qHz5NG-)>0vBUZSv$u>wV7DeM59hc zf2{-cy2!>wydnZ~FQFX#wtypVX1Fc{G{c2VY8i5O?6(4`etbP1P}f z01}5#Ak@o&6fl?YE8a@yj`_UBmel+__fIT{{#?XTYOuYo)jlRRa2TvL(J(F5Xze@3 zynoG3pi3P~;RUQCAovf(xdt4PY{vFg70hctEqt@^YxaG5#Ba5cg4-s}!ZO=tNMgp> zNcb63ihJvn(BK~#8Y7msnyRAz3CLL<(0~54m`{yvQ82vCj)D^U>R|aw#Zx7hmLtaT-Hl zzhjglkwAMty5G~q_Y5M3FTXw&GNq@B6VlQm)iq8YX}B~*t_!q<>PBT;>oH)QPkYPe zh8G>#0>38+*`Cy!0e!59_2K46*etz$c98|noswNA;%q$SMy|CHMHo)>7qHXbH_(}9 zL(F86dTg5n9UgNQfTD;6|_0{D?*&ol5Mt(nd6i}1)tn*CMUh+3gXi4pvR?xG8xks% z>^%@R+`6N#29mq1`Rx!CHjR7>l5y9@D{*tT@-TJ1Tee19UiFx*#IlUb*t-V`N7J<5 zkY(lh6YUp1V$|bLA{YF3x70@iq@lFMTHG2G)=tjA9vWjj-oRkCYyQ*I;1`H)j;vOj18|mqPJn4y_oeZ~HG&zOJqjvWShhL~Tlb(~L3Ap*Z>ZeVy3R>*Mu!I6{DVqp zR}akTpAmkj4&wMOt9<8kOFF7fDhFN9jDdO>#^aDU4n7>iK0P!pZ2E<87mV{c6>?+#GLl+;b*Usx-$091Lr%Cqzv`+ev#09G3%qo zN59rxXUP-cB>#eA360dTXy)6GsI#h6m^gm0*T&RiSDIuU(F{+e)_nL+?=TYcIQUOH zTc&c}13sC<^3cf|a@6k*z7gX{K|8rvdOFYVoKW5OOS(l9emA{BTuIIFoc?Oncz({O zqzX-2^ZBc571o_A#KGCfBh%`mF_)%+7b6f`mW`PC^hD~l|i^Tgp@kH<4cS9 z=*z)MyZP$3`9`J_Wo5*5fEUuocKgA!VZWnnF zXq(mIkjT6w^r4vh@pE_M6mdMx-Qn@~1z7PmL?BVeaLiM%{<$$Hp8fCHHClIHE6Sov=4<@S^Rv!(Zi1a`wNp)O z@J4LB$2`U(+Nk<^^kf;x4(SVWDha5%GkV*|$mm&=Ut)2Nigy$rkvzn*FPt6L5guI7 zupa*9Dwc_qMmXAk3L&wiUm{say#!UVLx|s;1+YM&q@`_6Bdn^g5VBVv|L?qYDj*yY zTXEDTt`q4bb^F;DaZ`e;q8gm88xYtnQpk(dtQN;aj1J<#OR1#YsZmPINW{DIoBrt< zRNwZd;Tg{@{3R0lzC|n`ruT3?BMq6h4#BT{2+Vk}#b?1AlC_Os6sFu|jOEZqinKI?}U>s(hj^)QpOr zp?mUM>#?-@rM31%vr6e5=+0gvGOo!jQD}SIvky!9gdh#Fq$CIXpUa~l<{-s8*XIGx zQ6y#=md{;hfaHMT+jRFBH|i|-ysl@F=ZUXQ8W z7^<=T${uddCoBI)BXHsyN52mv%L_Aq(>blItZhD}g3`)#uY2B=IGign-YJB5PK(Jb zK1Lvqv&iIe7K*BC&vCLr+b{il+}+5D=r$>vLPY{DD>h~~CRYkBgouw5;|Qx6*w#iH zOzd|jHHDAI_anQNKu8wF9M}>t*n)fv$>LlerNPm!;VoT1k)fgR2gVM}56E{AB& zySL@-eSi$Gie(YV(D2$ERHaoEpXSZiDF76wCXB3a{sSVtuz&p&a@vm`@O6fAx%r>_ z`jlEli6*HBy&|!*K2p>4`LC`ibQkzBNjDkPVPA68nH}BPuB95S?odVkDXyb5!}^K} z-qO7>|4yNXz_h*N7F`%Ja2w5_?*FRg=O9LS%xIsY?48U?xT1tsk)(Nqe4rorzjLhxfvHP z7&Ioc1n>7<73FUmz)Tu3v2U(H*T&EGkWlo^#9I>`Q$A3D_RwSw_g;gP033kb#?1d> ziEz4p0G9bP)7I~5uIo~lY zvvI|>wPj^xCef@X7sFGsx+8Qx9o_WU|D$sC+%U=KkV(pwI5;|^D{K}(g1yF;Ukfju zcS;cVB-T*-s)D4k)Mz=W3qC`mv72<|Ew96&*?SP(zLmJgxxcEYknDv3^^&KfH=5Z* z2BGaCeu?`HxzS5c1%bFQ$gt}Z9Z6=1w{={4IYG|c2 zu09_!HM03tlIJdDb(MGPG+HKCi(Wirg#%5)DMg{@oCj@ye|l_ViT!ZxV2m;#=E=>y zrH}o0Mew89P2BL^@Ji#W-v8pP<7iza^W?85^W#APTRq8s$6e*oheeFG@>IN znCFWLuZ9eO;#62~$`5IiV8>jlK-ityaYu>iXMFvd!p=p9!!=&^?4Ho%hGp`1%*wtf?C7u(o zLDTj727c-?+L@A*Jj?fw&Xb&!m+XF`o+C#1(2|g__8lS76`vh{>6WPpOui^8VOBBNAas`Ot+0!H8CDxu0l8C-d#=4U zgEj1sc-JU@qnl_m3d4ShVmbFnv85o+PMh_k)$sF-gSHx*WBlHqg^S)dv91pupd*(& zlU4<^)7P6`FgA&{Xk1wF<~bvZSZzpqo~AycL3E~L;@$2>!IX-MhT+RK=^f#7An_60 zEZIw#0pAq7QpeX*#d`-{cfh{}#%!L-IJ3(A;svM-8HR;CQo?inP5qDiE#KtH%8$+7 zxFPwexF1|k9G*heUrVZ}ML)Dgvtjk`0vpC`)h1ghjoo3%YZqs@7!4l@H;|g(IA>#I zIW=}4SlG*n5;J<%>EQQ$b63QQ7Ym6cxqaNPi_6hCzi}&%`Su*|?K}#!QqyF_DD?Zg z;H5KP81w$@2~_8!sKYuWChm7cVYFMa*8u+RD3{dX8NMS_j)$A5Sk+D^|9^&F{fH9u z&;J22!jQW`N<}dO5L>pTcSqAXgG1ipx*xke{87Q6@5LunhVAiIV(7^-8#Gh`mB#tM z?AN_?p$zcmj^YB{GLZmcbOi)cs+7Cj`4wC7?F-M89gQ+XWR2_hr36;y{KDlK+Uy4v zI4H|!lrSyt$NbarEr>g2B|jyZnBN+HifwLI_f(Yg0;WfI9JGDBEd7U{mZ?YU_*4c; z#J+kOZFRDn&zOvtTdXjKtAO*iGr4|^NeEIoNMLWmUlX1aJ@Xch&Nchf5$%JswSF8h z%6D_#5V~USA=|VuKQrg?Pj@yeydCY+%;ktz2c1$aYCO0M5ExDh(<0;;3Ns+Bt0j7d?Bx#e|PfH zf=NfC)0Zwx&XvR+oFDEB$`9q3DVdw9# ztpfbGfP#2-`yw6Pa>pcSnE&{Zu6|!NgFP**8S)$RO|tu@7?wToucS@wmD{+%^Qo+` z$+ea^)wSpOIR?iP?;_yscZ{#oX!1Xv2o(_q=6Q`}E~wKK^o}HU(4v|rvHn=*1D`|k zk$sh!YGFDg|7YbSSURG0ieg(QCZTBtem0?I4pkhP+Va6nKBa<4|0?hL-F93*?Y@sx zq=N;^KT&MmmD>7Llphjcf~E*II{~z58}ofaDG|<@qvX79olHSXq{rmol5v0kmy^3) zU4i+(v`KJ|A88(}_y!$M{2CEKvR_}ncW=*@80#yZnNv4=3=0yjdogHK!v2j8Rr!?c zHfdnCeai((ucB+8kF^NsUc%Z~#NDGH*J`tLVH&9Z52(CIc!L`Za-1bDxW0#UA=9pM z#}anD6{u*?6*j+`l9<#c+VSPtmEYMOGyPriCkL{dm@}Fi^tT-gICnj4AM@P#ynmkH z6HN5<#Py$uH{JD|E%dsbJ4QtBlz_*#{kkPwC_ShQD}@)wXU{M=QI`^$n`IS{o}%{w z6AiXyDlmGB!FL(aWLsD!W1seqCIr5JtkJ5VI@feaa^r?&+Xy12rRP&B7fceVzT{$V zH}sL27%VcmI|#lAXE#cF!D)H1im#cYu8)vDsjWsN`aFkEX8qmsg>qD}4Tjq}cB)3m z_Glmt*d4*gl7G(ykJ;xvl$D}#@%lDqbZJZ5e0H2a@~4Rb=N&fr!+7%Vr{aOB(AUyw z-YDcadWE%)%ZY6>_&K}-jMN}fsgj)9wK(}$gg`8^EvX&ebo50MZ?m>N`x-Ayn|z~UbJJul;N?&#N7IAejQI;mIo~3d1zh@pX&H<#OO2}`rOw)yBp|GnhHM9T9vi@ zYEDK?+Q~vu64x$@-~>2T?NOL7P=EKP&QR6uHxmZ2-?V8$ye0GUTX}gNV+&T58#&G5 zR@-29H_|0hdsMv@)w4I}`{+gRexU#8BbPu zRxKBCC!rZ_1Z#SVR8B**fks}_h1nQjeJUNQcMUp-=y+JQCXS-pX<7jdl#dS4+UOr zjM-Ut(A2K;0HiTmA-z3srusK;x_)hT81iLk$S)VsDMRMrT~}_Q z?VY__u%3|sW|c0I!VBrXUY{lhEM4-fr7Hi6_da@W3Zr18AnOu(oTAblxf=|=yq;cX zsrLcEFwA!*6|_(t5v__npY=TB-=KNwhNfXF;9w5zL9%JK=&9?W&|NiRJU2i{Bss&7QCFd9Z2|Un!GU8*YB+^2DcVvUBTLX3S*5r0I-tb{PKo zx4{(v8mqX6vicJr&}G{p;fYNbJvWC>>>tR0HZi>za_@ALb~kUkIl*@{5ji5sJ3QmJ zycM-Z$C7Ev#h_Mm95q@zcMJh5G-(eRCnv;`e=QzT%*RsrnRL@MczkfbBNPXYhLc+- zLqwu_3RNu~_Z_=Q^?eSKPJ{*d${b#~JZ!ie9R@v5lRR&P9f&`Nh9=;GcBWYbzh*D| zMEs9P?nkUDL(S?*BRT0qnfls|q;uKro7x!CpGW$Yaw2+<4s7!|aF?GE^wcVspGsb! zZUDap?WX&GVfH)~6-ERW!rVy-*lpUzpthI6hG6O6S)I{8*e%jm)gv|W$`Eea$LJ|pD+!yojRP#sa zeu*Ayi4=)%m z;_4M~Wh5sh#Z5*JTx`nGCxE&q7-5+=ZKuOxLw>|?%gxv|!fTgMf=ktryQux~aRhXZ z-Buc()_&z;H`qY`i*)YZ>@j_0UCKDcFs~*YSERa^ANsqTPAKMMZ&X+-g+a(S!lF)< zO;lYNLZ`=4&@8TAw?C{qg=zIjsebF*k)YedPn^&TK$UfnxLphyS$_FD`xD} zo&GwBh4d|FO(Ie%Y=}UT@jL7Aqpdw0ck94r3C8TMJWm?B41mY%wuhy?=YGM!x)|H2 zAEa}$e!XL-isE+EPRUG^q3eDI)%Az~sYw9!e0U({V}cW7$B2}uaRZdb1KMU>B<>;; zK}GM8tgs9I;pO|T&*dm|wBfimwIvA~PCK(Wb=6yp1KVm>d$iI%=WpD(Ak?x&uS-?k z1#=Xnv`Y?3k(If%MkHx(LEjhsqvHQKd^+&7$ouH-^9J{~yxk%#{1p@av34(ihww0` zoF!>|dAdfBBT_xky^3Nj82`prkX(WrKP&t5SCKS@_FA9*BxIuP^FUga>m( zNKXq@8OR-r3^OC$Q2xOe+S|7EOp#T+HRTpaD25Q0tdiB|rb)8Kb$7Fd3UpT8*SQ$9 zY5WVkCE8tNA8RSi0}u2Y7RZjlni=+xKs@ePwcAe*{hyUY&Qxvin*Lagp;ZP9x6k!ESq!OaP*Js+tq zjD=IW@~W=1B^E7*Mf-C4R}k1whO~j?!$XoP;2X8K;e#G&Ey_ZQ(Xn*qstE4b zoaD0Svke`Qj+7q&0fFq-XXMQzBwVZ+8Qn>H(T8>oOBZ?Gj#Vh`H3dwBWGTPke0kaovKP zMf9`juCt{uK_J_q!e2ph@Qqvj$}WGt4vXx3e@t2UYG!$8%Xn?-OBKzAyHo2q0}p4l z#N2-G{d7OU%C6=bt!i6bj85;Pof}3lFh~D^lNLjrcTR7O%uJ4?MjP%4)6W+9g`wik zIMTdEal2xpq4Uh4n1yqrsNdVKgcMfu2A>e4oJC4O`PFNZ^8m|RZ|7G+n9sorsfoq> z{u|6hIg!W-6dTbaMNl-Q_OUy->U@#eY%H76Sf@VM^#A*wAj6vz8~O$EFCo7pv#^ru zm2iA67a>*$VVGYOG6caNt3Io+hWCTS#f)q2SVWk8uj{+dqcr!vM_N~=uzkB^dZm-E zy`0MPHiQMy>$f$K*+;*FFM@juT90FcNg>iWHP2jfUiJQKGBkHO`WtJjq(wR`pILYd zPHX>bb`s0$-|^e2m{}6PM_jr4(?=L32+ULFrod)U+Ln+>Z^#4 z0o#JoLs9Hje;uoaZqbncX#pm_ue^9(h1bTQ^NTTqa@~P|1a-gmw#?^wF^lL+yc!x8 z%8H?=*aE`jO`U+!q^;>gZ z+cvsjJp7n(xnNAC1ou$asy^^pPGnp~Ohj@;ErgVec_V3kK5{4CdmrZkaC783MQpqk z4$%uEvfL+}MrKi*#+uFfVM-d&`w6fEPeCE*X@&LHJL2FnM8k$xlZFou4;i66iqErk z6~^$mq4$&#KEgaP*Y)dp+@w44sP112UcULp@cu-5+kBOqO5-^Lfq6}^3n0l$WojXJ zIB%2)#X(iho-x9yPB5&Q^0=ju26uP38TXkXFU-+RPMgWFM_iNx7eje+GEZo_+4iYW z+2uhK8P9k;Tx~be`ZWEY6O=?Y?M9dkwt2k%Ls^E*Na?jb9%A*;%%0P@o8<)4dn`L> zz0>DaED=T#jygn$h1PRt7H=T_s+hQW;J^02EZ>*?mivN0fVYY#Xw8X~DP&AYPq!fM zAP>#*Sc`VQwlW_+yNCW-HG5kqu}{p$=lCcm69vD1O?2McH!$wv&&=oZ@9-8jK5zcO z?-^zwhNn6uW&$>II;;ZkENvQoDBg80@#6!7WF*&t(OcdgJc8>PhEO7kvFcx-1y&?) zH0y&X<0)1F&9n~QYLIDymwf5kdTY++#MLMYSbidm3dv|P)tKf|DrB@y3@xC+mKxh` za8v(M(1Ks|8}U3&S|vzneEq=I!?O6}wHr5xomnsKbc}R1vl3H_iSUr6&}u>>&0>N- zDkK)7*8Uc5dRWsb;z3}b9IG=8>T`)|dXKZ6hR<*1&ZqT5ac03~$U$MkMbs+85)=*Ad)@AD3_USbAlo1GPcc3SPRO z4isINxjvL8G|2s$@8$h6f}P5Tr8YNA zL9^;x{bQwqn?A(`#$ys+Ps{-pcBfFI&8&Wlp(tlBA~O9vwyonGuAIk?Di`bV4H;(o zcS6BbS&AUFTmEb>UVMk6^DOZhfjxvatGxez`&@64WdsB;mGcOfFJOYEJ9WuZ;g}7G z_lG;9rl8ByCOYZ&n$sb_G;RyHNsL6dlDSPf&WU%CPckAgb+h`4t)6V=KG{e_{7|f! z+*!p1g7-ld`!S>nlaZ>4wip{l47B*OBolKrXEMB0*Dm3MEMgP$H+Qxcr^qUBnuT5$ zkGJIW{hp;0PMjyBqPVFcQsMIVX9AMF7-uI~=HC!Z;M2wPG)0^OUf&~YNm;bG=(8{F zpVe5_LpOMpVp91WFaUKqpEi4wc#k5yhA3%;8vR`I%qioD)L%M`YnEM?B5bT8S8~Ok z7HNEQ!kfG~If%bks2c?RYw3it0k}6Ltihk6#Z@-_1x0M_z?~RCY8lXX>^G#(9Ceg4 zY}d;Kr(<|LCJb?|IcWZ{n!++D_x1hEmiw?1)Liycv0QJQvInM3+AFT+j6tXR7GVQg zX^NBKP%3!)C~VaH)?Xr}zI0%u+(M39&~=w|A$|sTXo!N-x&XiK>U7a?a|Z^0{pOL` zzo7^wuw-yUBqD}6Z`qZOV4B%>;+A>G3pxvKumF>BePsQ2r0E>R>YxR;fb%}Ko3}J@ z@6@b0o|uU!Lcc+Z7&O2qp{}|UZ%JnHLs?Wwu%2AGMhH2EVR!BgXUzv&{Uw;6DmTLB z=}1*{7g+Lg)UUeW|x?xqHW2&5R1~(+j2M0Lp9XhM^ zQ5*bN4E%W+gu_hD`d$sZ!{g5-Pn}*Lkt$3~A`;#}R~Z=#O61X2e?S8tVcB2W-kCeR zEwLgXu6Px9$zJ;D?dSAeB~G~~Iy7+Hb+j<@|2a29wEJ{NaoqZT$`ndWjzresW}=be zWd-CjIb#FqEPJ32b7hke{-06>q%7|H2abhK=U-lV%lHFD4IpHqn8GN@2%b{n*7=D} zaU}LOG%ihdC#{TKBkOJgJBa2m4KG}<@yd!X&e;KClhg`AvunGXuZohwKp_cQ64KK# z!7+S?@?rHtrZQG}wf@mkL9w0L9Ve~t^2@zvk_?M}-me$`^W2*?=%1oftED3w_0i*H z$hk~>0?prr&-(^xTSaM&NRCwKa}tYOtD?$T{@-oZgs;&u5@p4Ffg;jF@ zOad05fav;#tH#dw-S+2MUqG!arCB;!UwrWp<%AS3tZl|wS+u>MQ(Q3iub)HtMnTPo zB(UqINV?fo(l`d~vXL-&%C1%aa{@&LR-_mvLJ6R4kMFeO^+i{MGw=`!ea`db#AT|C zM-sG3+5B^J;xtLUus+_^IDUB+Nq;g{^Jwufp9-}_{5^#gy``5$dMx(^(s22$ve|HRLUf>D-Q1nt7x8dW z9t!5}9MTn~*v?q9EzrFN$7HH6b7MM|~dPCpmy9X?PLkbWaaI zQ9PYfu*!W_VE7aa*D^3|=`Ecv6uff`zfshwh4Kjxw{SL8Z_dvi{5OTtJM-Zpr<;&g z6q!!BG^6jiHCdGAdunfAKQ7LZcsiQ7p`O&$L|ecG6Z11%6HNApDv8gm9NQOo&%x<|t{jmS9-vpOUH2#q;bKZbV~@t&nC+nkZG@3W!i;qbyh- z0Pydv7GUThTa4o-lNfct@ucnYk-O?FLtX;VwJ_I0$!UA$9TV$UJdT13>;D>YjAA!YZJ z`LnDKx&%sy+-J+FLzMTwMc(Ffrjib0`+HiH4JuBe7ti;cCV}Y{GAm5b9|Q#x*6KQo z;RW}=%6#3)k1aFLg3(@b+a*s$SCYfQ{w^39Q)ij-;kHTI<|&+)11-TXy;Gxv=#Fp& zgv+$W8>F8W1dUE}V4K&KPs-LqJ+cvacxQqH`A80C22g6%Z{>IkuhC!to{ zh$%DFju?bjN#dOHtnE&9oeeR|vok|{C5_IPSE!@W2cx>`OUNVszBqPh=+CZwc?XG%^+La95S%0Kehfitsa&L4)4P@}KJx$q!r}ocMUg zM7~NNssW6XAZ_Q6jn%u%l_{TY>%)sE$^*n$qFbkFYqXH@PG=Wb4UV4WcxuNs>hyCl z`gT0cZ`N%~O8x%U>>V!sx~K#oblZ-C_9oItj9f|sqg6tRZ`8!j$>WImd`=%m^;!HB ziyxH16ZJpa`I`)YwncS=vGvs2(L(@P?tcs0LnAL@Fa(Xtez-Ne0!}lJs3t%42lc6u zRf_|PWV`;gml7_;EyJI%XARnhLdzn495#}16G3SdSyV7DC^cL;qp$ZE`%&dj}fxLI1f>Ip+i zmh|G}R&UJrKir(Aw2~EL75G}2x++wom=K$8kNoZ}Rc}iz;4q;CR$(|a^ z(ohbD7=9}n1rxqJX4VvYVJ z7&`EJ{rJ5=N!mriA+*scC(}url(?w{ZVu)%xdr6IdvsAoqGu4am;PzLulyZV?=>PX z7~&(d%fU~Jq6WyziHeYG5k$pDLzD6-QGw9$7*iyW^X}Y6)(4zPc-~;_7pAm)68VT| zbVToT3xA(ydzh%*n~giD=4L{;ggyr#MNf)E*9dbR!=T!$MMt!jkI@cDdE1IY&tmt^ z{}JZ^GnLsmjE1|QAZ~8cpQn@;+25#6iBzPV@ZB6R+=mMaIl&-}I6d0|4mwJSZzpHv zOxpBw5587oVi*aimrl+`HzlUhZoE0+M?lhL{3dOFnV!$pvWh#-#uyB0wK>0vYc=@D zgc4gi5`5JLh&(CU9-LcoVS!Opl}JvR@>7{a2ylb09vC+L5cfj9bR6{Eg=6 zCeiAtEQ3c~@64=qmjul0%Iu?o-ykHLimCq+?d4bbXcAa;a+s{EP70A(^P;Wy#GCl2 z$Mz61xnBk{Y2pSzbi#`lfW7j?OoH_-X8;tF~DI!De z$b(9n(q*idG4=S;J;}G4ywbZmAIeinJ=Qz*&~&!ho&Lc?v&3&^)vr8&%qBwQrC#9? zh4=gvTl`KR-;f#8auBVKJzA=vfE5@d<=DAMQ56*);zP9$XHM@zJtFTfSYuoLr7}4$ z96r^F%d)+feaP9-t>hGb$o-EXg))CNdcj*ka`F+@qYy$m?ZfAFQZ++mDb@^~cmY;6 z@8}Hnx^{~{CY^7jR!phX`tVW=l@O(I`SzQcR}t-DbD?LloQt~^OGxd3Qu$=9r_mCH z@ofgrrr`P^VqNLth7r&KRkuJQmzebX^%{PTW`DPO(yYj~0-a@CqO)3Xmq&n7Y^!l= z+gSn+rs&?=>OYA1B3JNWi_lBb4s-45sOvn6FbPrE&5J(> z55pv|J}A?FfXde5zmA@smGx%y#Tr4{{A>VT{35Up8TrIBBWglb-5`MPlU@k{%|%~= zIu8Id-NqTb+P~F?K#ia)Yv}4sN5r!do?b|_TRUUP6!v1~%pqtAwC8^rpQ*_ES)^VZ zde_KW1BMMC4+dff$bkC#BN`wKV9oQz0kN;!WsjWs^Ol$N6L@cl(@Mex?&ttX#^QHX zC8K)cqOTBo_dH1E7Ued+pROLCIP_V&gTIEcW5#7=y-lPyrJVs9} zStVoA783aGmMf{@W^c;Jq0y%HjjzL`@W^%|(~o^5digjYWDHyc%fF)iyG&&-Dd$r( zfh!~AhLyT2Mc$#`r7gOZ-MxdBv45}?#F8sh z^&grXP4S#9sj1_BR6l#MbkgGj>xb4#ZlB4H!^jUzdGW@p(OP)qmm( zWCeMBZdC?!qHEYQvuuQ&ch zkiV*qitcbrrh#ksnAh!%r^&I^AxoOwjk&;<1$h4x0@^eh{@kdWagvP0E=0~H3b@hZ&A6^pF+k7$0Q7n`KVT(5UNNY zYX}?GaSCnnsU5HdKCg169h0D()*G0E?cw7et@ICu*;?{O`Z1wV-N*}UZdG&r1{=#$ ztb!I>sMPII_~&_9No8+|eOmuIwBLp41dM8M1YkSsqe^*=bsb3?4Rs!YnnAmj;6$)YzN zkxd!m1Be~B-}OzS)Iho!)<{G)9jnWO3Qb!mS%}|t2Px>e5%^F&FzV|&&}O+kMknaU z>(j7;?$(zo?;3Ufrd_mzm-M4T-cw9Qs^C94^nWg%my~>#^#j?OdGA;Dq4u?yn%ySg zOi#W~|0o67;QbyaVU7&6r>P8~@KlkI>3ESBwGS{2xxjjk=E_-q$^LsS?xpLWKX~Bx zumz6^p@QPnvb4o7>7Utr^pk&#epowXHhG~J4GzRydzj`suwsz8pkkU;q$BYv<`G^> zf&A>n@OJcTMSgPP*u;KvGb1lWdu;q7EUxX`=#7M`CnZ7hU)%5gve}ni+hYGh?r)|^ zd&C{1)mrl&rDIa!bnwYo&%U}}j>@iVm3F2-gGa-RPFTq_m`ll1Z2o=8PJBJP#&`6h z>>WKUqY3AE#>VHpRoUEA}W{<%U%Q{GRQii(FK1n90O~$}P`AX36f!&Bl9mr>h#TVO<{G4T2zG(i6Cvyg16l=pNjJ1*+k*Nt z@wiZjn^3MZf95GYA%z42MW`U?mjX|z_UPW}kBT|qZ9pWP&E|_PW4kT}bsEs`wChMu zAAML&fRZE0e?T=i=Jnw-pR}r>N*T?1#odKi{JfYk7jWEMb^{UM&nUG9z*cIXb*H`XMqTPqX$Ma9`<>dQ0w4!x41KTv zkTegM2)qC`W~(rJ=5adu`N}lwh?#SONgR0`qka`Zr0>-Bj+Px>2>+i@3RRy*xx3Ai z@z2d6P=o)|jzWwirGgP24aT$mam9k$&b!m*VX1Asq{Kr!oV6Hcn^EvVkI8!0t^3-ZRDDP_3f(G5RM8}7=AL25SRf8vn9mH*(5ikKabF$XstuFgI! z>50K^#4mRbnZQ?9`2=25x*lOfW4R;V)N7&}EoPr!+TlEvARWH!+kRgK)h%w`#|58s zqoDDam;p_;kYX{33Jn8zG49^@#c@J(h>UTbtl@}T1*j`Ww!Eqf8n%+3N+AJt`RpYw zC-xcoLOEVl4JcfXcK}IgjHLj+#yej{P>6oMsWx;vhp#=ncx~`YkZ!%xZRR&s4dz0#0oGp zN7mL8mgpGV{yqK7Zx0ML0az<%ycP2|s134bMEJl}dEWyR&s*cnD`c))fhSh_`_v*QK?NVO zm|{L(SB0j}3qg#UgGO+Y7O1ECvwd7}SZ=`_)f4h=s5G~Xl&3(#-nepHw2cTgk4Q*R zFK>j!_c-wjZoWAo1s;2IKB;~GK)%9okFBzxi6Dq zY%k6opQDW`LKFmMCZZO9v0kD1#@V-BUUk=zFMSOm0m51|=6vQ!n|L;%ojymCD!JWy zW5Fe_DnU0)x!OJ;a29l-$|sy7NJ+YLd9G&D)Aa`eHqn}!3>D_Bycka2n-;LZo8oRe zAnGa;=~B|`archO}us2A}R!gJw+R4PjT(!lZJ(z|pI z$3;woUS17K;YGL$m&jC<2Uqrt>l(iZy*?_}5%s3_ttQky=EYuQJk1zwVpC2I+!^k@ zSw_3udvdUs{=wxWewUUpD%W%7mCG%R3(H}vj#h|LVpeL!~_Y?6eavu z)iMCT)Kg8QXBBB-5tKC_R35JXvQBAP&70_KW9HV|zN_>|dkRhz7Yq`qxMTX-L=QkZ{OAxfVHp{kwD)IW}>rXMR?j;vQPGut; z`tvRntp2^!?@~`&_!aY8X|#+jaw~hT@x7NH?3_*YwBK@-)%^M&k~T>9(Ucw7>;bt5 zRPS-Oao4O(f8ZG{)P0{WuCbg_P|=-*=|{vPTaw!N`jKD2q2&u~Z~|b*Enrh9mcgg) z%7~yNa-^s~Y2fSSMce%1!St#_&T4I9wCSAdtg%JZ)u~thW0lXOy_$OW7GvFXr3E=> zXNu0xxiM2^{(4C-U)j28joj9*yyN%$)-LSx;eK-}a0>KJ4BvC1U({<-s`K8+#uK6= ztLy}|&o0oVF7J9cO|L~TUWbXo9LF?Hs`Dq^|=A6~O5>)=EIPN*~shYU<6%S9`QG9;} zwcoylksP?|{b+{-)gPC+F5^QnpRTuWHyYGGcHYEvZK!!vj zPeOxvswBx&Nf|O_ij$$t^C_WHNaAFcDJ0{ej0crO$CP89>6qs!<8R%k-kw|dc4E1V&NAqS%HY2$GE4=NQK0BrQ5`}v{ zN-nFrKBeJ87rdZ}k(ThK&7eK09nM_8-d>f#6}Q91d*UQhJO9z>AY8shG1#p1d=)xuxjJxd&u9_C4wZ2%=Aoa4FMhdfaYsmCEir9KQXzaN}aO z%ihhzaFx6}mb>XN^K4eTM>k)22Q_M;~7^rZ*eYJvs*6?XLB=`Pw zNIlq1$-*zr2jm&S9=;KG#gCE&M(3m~=o1ae*+RP!!K_~Tiam{c#2LXm+QN9SA4TAa zwJc4ZV?!8MW~*`6Z|HMi@XLB-8DHX%%?n=JYdBa)P9_FwQx?vI@v7+?w(AHoaxxWK z#bE>VUWj#4!P#Kbu9i1E0e=NS1m7{$a2Gh`ax~g)u$>olVK18JW|TdNKdz6OLR^d_?cK<(KP#eg^u3<# zp8kkwi*2@>*#mZGIEygL1pD{n9U8c^G|NMu27!zI_y7pViYL`RU5f=@ii^5Ig7w9v zz!q6eDtFJ(A*CGEw+^IDUT)okAVSXUMGQ`|Ciyf-J!z(Bt-MxphD|T)?DxmYo(6Uk zVLU^$B8N?RVZLJ*4SQT-;%GYJ1h>+_V);eG&6}do=c43uA4+TI#Zq_SVCgAvp|5503Vz-oARcnnyqj?nDd&>p1Tg`Osmm64qE0GH%Df zDI~pV=G$6NZdQUpDEQw1JVjy^gt#WF?IgfoI$J+Lce5?cm*Ie?^b0e*{EI|$6C@XZi~hl7Gh0$8=-+yQE5@_!Q`{m%b63Rl zbJuJIx^bgP5`Ci0U^@D1C0)Nx%Y9*Z2`k$b23d`9@~N-zEE{>`1cCY7xay^D=2a9y z^dG(wuckS<;boxrO8jn;zk)Pw64<&1N%r8VbV%@x=Vx~#r3TjY*#5OUnDR#S8lX)) zlTV;YxLKVW4(qM#ijP{Y_#@20UCMz}pfQYdz z=l-|=u6hO*=`_Eh6*&&(b*H|b0K9kmeC5bEzsxQl4|}F!^)%x;#Uow0L8*}Y8N~(68X>YRYZ{ba>K9$y-Jh;(CP2>g>?VrmW*_$g#_Xr;gf5pTEz)1WtXwD^;+7i02N1Gl z!$d7w9yXpqlC?n9i0!Mw<{kVR@u=@w+Pdi}T96av0HB|7RB!kcxs`VPQiWTnzLr||FOx|lTaVrL{im8fnmm&=&eJ*+bBwi>c zUUZ^C{N71aWfwS!8&*c%=(7gCsDvk#&b5TequUQH)tILC#4BkklD1T@2bdYV*Lyha z*c-z|T<5qwk9b>k)S@=!>Ud~9G?6jbzC{d$91p;^cURVOQ1iC@&MZ!~Ct%7v4(RT< zt)^o_K8)pNcWe)GAHyR_{lGJ!o1g)Kh?8ku%sIS3fs^<#n(9To84$HyvW@P2q(LDzsnCvD}K04Xl$dBc`XaGsKiSUa@i` z18Tbhn%eCaJ1!HlDDKRN(tXd$90(blO+83wf)w4t@Khh=(;}xa!Ominn-UwJ$m3V3 zk#tEweK}4{W%8-I8**gTK*?WJZVsJ|D#D|7@a-M9CM`FQ%hAt~*}7ABIeR+d;Q=JD zC7(<37G%>F`-2RAwW|yp?zbuHLU6`E?x_XHBKYw{{X*C}f4n-kpJ% zSKm7GA=a9lc(O4mZzbnL0gbqgc9y2@qJ0-Ovm2lTAPiEG_xQdiPWv=S{NOjVB4Q04 zf&7D^@ax3&MZaxdfEyQc={7h3WX0|545tBpfJwP4?lPsf3u{7oRUiITIMgkag-11o zM-_Xd?i!#&2cJV{>t^ffM+_J7H3iGKFmtRRl!Z+PY05H~l*R5P%6?R!tq3R-uS za=U)jioXe(<+{a{kTA;uOaLD&>AV}+{vivTWm!jfR2JOEs3aun(R;_eEMT_4Z;%FU z;ZdKmbIK+Hs*jY`!=YO?()IS&S>>YCq?KB*NR5^nTbwz-ae!| z6R#LZ)(^1;oO@!jh!i^`*J(UjYZJ%f#&-Bf{Jq_&*P6L_E)sn>hLNL`u7`J)8jrtpf}opm!}D# zzYO4b8-R6zGaIo0nM#b)zAru4q*%lU({>aG6oKdIKUse{*J}+no!Wc-PgtD)4B)Kn z84G&T8%Mh4c2$6#wcx&eBo3vf??y^~d2*l14P?;2`+6H<1?5Mb4(#DAyC$%ihw_U> zM>+!LL(Sp1;ZOJ2-%yzv##_szq>Ib5K|jiWsb!~9L2S$E)E^M*ff3nMHAC$biZ2@& zC!MNWkBIZH)3c@@BcRX-%Yc~jPU}ya17rUBE*kvjHii7bWbJM68U5A%C&kKee;yU} zPD+ATEy~ag1a-ZwncW*Q+WwEXrUEsy<>w~4WG@?nYaqXqBJx9?im^U;#ZBisq6pMV zx=$+ql)pr=)Dx=BOFczNOq&w@r>BO?mf5Jz7u#klU-BjrsYE`gDZy0(@$_pvA0(Fr zjf>dx?i2%$4d;1x03v9KD@k+@6~V-|ruN{lbY$LNcGvrvIf|*XUpaeO6f6$eI{9zz zewV-KKjdC}m2S{mhiIkuYR+%GvIBhgY>l+|TwHd)(d>FxR$;)QnW|itauuYZiW2)F z`PF#s+dX0RL!z6rfX4YgkcLb?x$|OOzonH=Q4ket|3Uc}ckR4rtQyjBquU$BelH3j zFXco$9Np@wcFr^v9bJv_A}KZ|E-(_1Wsg`rW;L1-O30c z1GcxMfXIA4DqdNE77jcLPS+d*VSKI;zXH~K$V^a+-z4rYyQo90|I-24$Rw=W8T>>wF7-V1S>n^dEkbqnOf8$5YjUUke*q=M)@9VQHPaAu+ zH2C2wa4@|ECypXHvHDh99UoWM;eM_Sph?go_Z}a@`Tz)KQmbvyr` z#n=Y;*`TR?Jd5Qu6|rvc2Dqz-LmV*p^^AyoB7BEipnK;F=A8K^V^N4xS%tqh`S_0< z8=C!WW9op?yz4zGX6!%(WO4;C54`(l-uFIge(_E5qhTX#c@C+BxslcJVSz(S=+i9s z&XHX?%iPbO&=&xlUfa}r4wlx~MUoCOTbcitsrdlfg9w2x|4SzZr28KG`#a}{@ta1_ zKcstA*g;*`ybNwb;+$bQ&Ekf#k$bbAiUPHXO2yfI^=9t_L~8(2ZJN@fzL3h z4*zf*;?dH_Q<;uC0X`hhsR{QBu!YIpT)0AyEUC{Yb;*QeJOxhTrz^6=vawx^)EP^8ttkA5ZrHFEys-y^)RP0PdIVUUKK8~Lgs9z_rFOB+k90C7g;i{2Eipn2Uy|o?_$qQ#~Xib(oJhK z#1d67WH9RaWlnKXx{h}B=UOk6c{LpI1_oJBH)`ha1tbV zFpjU(acAW_FwiH*^_?EJ28ubJpPmU`Ri7GGo>Za6cHXN$BU-~RCLOIWIUdB%hmvxU zD%;`5(=WX5*iD$bK9#X$Z$9*^vo_$eG*YCCfkfX45`BzFYFQni!EH$NaJ1b|pw{+I zV$|f#4g0IYP{ugGx^q}eU6%N;^+HKbU=&sQwW}Vytn84`5XmHt`gzz+>8E7zjv*ZC zY>i&Rh!t518cA3iKB`q3tr`FIhIC*grVh`a)ROzfD8QAdJ}G|cHKg`pHB=oJv)X-O z4@;8D;Yl)6tE<9MsS%SmegMCG5tX(Hmt4UXxMd8QdcqKdyZ5e|qo|Y$43z^G+bOqr zvh8y3hF;g>J?i-#wO#x7Aiv);QEkb{(Kj?tMK2AfCJ|`uiX^P)^}^fI`hu9^%DE0Q zgxaH9p$P5y`iHkIu^XngnveBxuzli-``D|nJ^*m2}M8PLg4dAo^op)%rzE&8O< zCOjPeG>R&ekWg9=$1Y4t%@_D&c5OkVSXXc{2(($6&R{Ye_=GOWv`9}JwP{+{`D9Qg zOznSnq~xp-iViY3t$kRTw81}+S?MtF@3DhqhFr=9G7|Zi3cTxm?#ga#`SQI?wOK zD&ntlZF7pb-J-%}8%(9gs#bIZPFsrLx%B-@Cf z_vMa8u)M;wT}a2beXO?!569HV1xK+DMSVVvjHzTVS41qx@PiUlt=3C2m<8Pc5z!YO zU69(DjCtz56Swonr|g#(b~w+SR=Nc2xaq|=dsqfW7arCfAvsz@FFiYvH*x_6ljg!R z?+c;;y-Mu3c41`pyu0H?FZ@ z%YUY+RhA!J843fQE(o$t@y@Els35=ZPhxczx>#fIlG0f@TBA~CO}M=@(Jp(7gE+}u zd+qAy9K3HGGc{oe|59k;Y5nQ<-8AP*7FSr1&lCd&AQ%hZxbitr+%#Dz;dYE?0?%Ew zuDGc5YyGBf07Oyv^(ks`ZM%#yUA^CQUK_k18QzQI!NPMAze}G*{k)>l@6T`cycGRp zvfYov$o*`R?4>V%^P^9u&_dDmc?2{A)m1zx(;k`}=BgK29i68yR_wZ5wA>~>a|gD4 zuXRBD9cy~M_b9_z?4&a#b%{qO6gZuqwQ5c=x$42i$_q*ryk5aTQ5BHxU>8^Haa+Th zZ;-uFVk#CT>NhNQ>n`9j;8mIOv}h zzP9C85piIBr}^z+v_=>WlIy9g~m8zm=F@1VY^ZTG2@B8!>C z=^*ael2zToRewtCc3y&J;;4;CKLYChH{8S<9-y!53jYAfi{H4+rqop+$i0@pY0=zT zx(ISV5XHz?W0!t(h6jqsx!?oir|+AW9AtQnA75huRO^GR57`37_hfN*?b)JrW~A(! zONZwfRa>Y;BRfkLPY*lt&rIb7L*}wm*!3$0$k7k`E^)dA4&Sd8AA4-5O!-7>3h1U% zHUziaZKUPunJIB_v(Hv%_F`+}&0a_dPRr3kK%R!g70tg(ikO)maMyZB&r;7_wVSL1 z((GSqW8e?ZJ5Q z`*vW7%wKyblb{fe?-WGPER(_(l+qw%7k(%yGU&Wy)y0hggfQHbQvPQ<$xb zsJ8aizR#hote-6i;Is1hK?aTUrIUA$iEKz0C^>5VuNT0fTpbbjnx0xZEl0nU0>sPl zK`@FKYwEDm+ugu>9rBguK*mB!+}MossdFn`+&$_Z#0D^3N6Kzw@A4&nA+PlBhip2k ztJI5=ApBu?w0!UV;SAD*QQsvHk--wy9DvtsGLrAFK@N2FZs=Q106q0cK;O? zyxUPS^-rfBGvxBM`ovay2ErMLYo_Z4!;cxiZk5<53xg544;mi;_a}Zw6|-|z^aD9C z!$@S5E1zaAr)%SBBWm`jz^0YjTlaa-md~8BktA#>v}Om5a4gw0FcU&iG2eY2ht?%l z+YCUKLN&=&0zAgHckoU%tSs3LF$PWXGFqG|TDghg0s8`B_j~pQE5b80G^KWv604S& zlAZ~+PJ=5HD9@$$Xj+@FXGbw0Y)Ne=#a^2eMqD~mc%xN2VXh|j7i+X58=pUUjg~CD zP*_B{v!Pc7rOwp%=0+gO-fF~4w&AyX$Y_txfw-iV}7>8uEj9A?je9ENIFOgM5;~>OWiE*wcFRl@eT#6_T+j zP?M_rTLyp0@;F9}R>_h)(56`IBmkp|DdMwlBDFMM<^%;44l>9Aew@}2k;fYX3}Fm0v-wU<0)9bZ3f1-J2+O;Vda zu+4@Wj=vMBbbgt?-Uc5tx*;&tE-OcPEFbjlg0^?ggWV`3T7g`O?UZG)WbMqp6COj*4snG}|H1!4fM!TwT3M~KGC-J<;xv8h(8Vl|ps=j* zEPP*pXI+FsK-Ftl%gSZ$_}AD2_uQ1B#x>Rg_FaCDUx5ifyS+C1wSs8i08a74f$g5W zkm@6~@l5av#*UxpPocq>5Ztf$5*REU`6R;pj^ueDdPq9H*^v)1wt-11x!B3Ub`fUx zq9f?5e$jW`T{5C&R(p%f-%i^i_h^=w9cutn?i2>qB@cJ$0~@4CONl`(#PU)ZsJ2nC zUBzhC;nPpzX{Yw*Pqs4fA!gKvHd<3y2z=Q!f1W@_ubc_>JfJq0yuoHF-67$%1SJ;1 zg{4bwvJD*UVKQS+Ff4yl0UvBNGf5E$r@rXN`hXjwcziz4b!Ql4Kk-Ao=O`5ZxDouT4um_=i#;`B75w(7dNvS1u;%kcqR~sr!yKhBwFEwmQ}TsDZQsZ#*3*v* z1f^I0N$=2pP}3O)b*SBq;>hN;EG8uj^3izyA+!XF5Wb-PUf(qH_zuWb>b9O|TOutw z9X;Fwd6yd9c!CB>q3@$~?`nYlr#dt+K_e|%2_32Ou(}nqernTAp%8$8e$c6k4~Q5% z*-=#Pic)`1D6pY1F~G&06*pZH$Alv1d>+#tL9Yza(fVBn*2`DU2??U?oBa8On^J)y1cA-)85fD=RsPM{tF~>kS7GdJ zv?WhErKo&G2Xe5lqowXr_3SvW&Xuq1p)_D zNE1ys^%BW*zR+Dc5c;v#np*37ued8Z&3pFMuJy`mpFqKw+Q)sFOLEGXaihf5j}Duf z1xBC8&L}aCdWI}NvB0V6_|MFC8`Q+|ydz(`m?9`X+gh8mKOGpAmL@?9}N;2WdjTZZNxlc{X^juF!M%7_BxsK-P zVNf*ZVFiLp$j~eS*Qf6I*$xwj?~9ua>QxAW>q=Wi75c5nrfeuV!9}?~8wMTNYI63U z>Szd=zx-@`ix9iV+Y|oB5ajz%{4Ph^Np~AIe>)q+_|HWG^`yDp-a<3_hTvI6W-}BC z4&*Thd+6ipB*%*xNhmxYXZgVh6$3cS^PSi%tWy1FVXKz!PVut|kjC*OzJtBe@p5E# z#5cw6UNyJ;X=NDcu1dDeHZe4>*9U;R5#waxGb=ONf>6KTJZMMn9MXn7<%Yyh3=|W14 zT7>@_tdfQa=7`kVqI>*BO)%eq&?C0lGd74&Yjh2|Q>l3pI^s^i&lvFwMqvEXnXteG zxu|fV)3htHM5+3&#$Vmy{}3UTXsc8Cq%NSF^A=aY(%Z#{34iTL$u6;pLdp{~1n39e ze5?+uF?SDndNRr##`Pu3oU=jFt>>9aAI{#_hX5S+r=&}dU&PuEibQo`!6+(6M?1r?XMjPPT$|8& zkty*iM|o?cNwoW#AQ;oOO>fa(MO0^HKQ?N+fhjW?b zH(BxzH^91|=bqq$*aMiKrb@?a6ScK>)r;s*YQw7ZJq~(L4JM15LJ4MTeLyZtUqnR< zH?$m#S!zd9P5!~hD1Ezkb^8?{UwSKNKdQVj!bw+d70d{P29Si?av@T})lq%t#(+$D z_m@blA+eAdW9=cRUXggh`N!n5k=+FNTWrL}7Y>FP4Aj^S<|*L^Z%cN*ee!4-kQj`Cs0OlZQu~{*KvRYtY+_ zXk|$}GJ>4VaOUkP+;M%#V zKv64)<`}3VsG1sQNuM_?IR}?z);nhgurb2m#OIm74Z5_zAF?;)l*J~Rl4V+#S7?@qzS4(#KXg^WZ)>_{Cupe zd4PR)Qnr$zh8HY}+6~EW2$1j2$xl8%C}gKC1{nx4c=_iHzoL-p+x#5X`64Dzb&!G8 z_!>6M(MB-1UXWPB9MBTgnfFSbAyI>LBG;g+!T)4OzsKLAds-TkOgY$5(7CsQTXT+$ zGhjm+&oi8MmbfbnqqJV(l%b&DL?!)^udHXp{W47uq{?6u29vtDt}TUPJZW{;Z@3eA zGvj2V#`!?frsV~;(lrCL$D-;S+IiN!)7liso_hz@)5;7jGzw10ii}%c7W}6MutQPh zH9ub^==&7#JIyNf{7F4Y6v2sq<>SCo6PgRp)Y|NkSC!O-_*9Nd@##VEa)u`>M0#d z4KoKXti^-)z~H_ofyI~-TNWifc#x2HM#hDCkthqIu*r(T#X7i8Gd4z`O&LxC<3l?6A!e$NZ4qoQJi^?EV`$jPAKhWL+Ml{81Ff9GDCINGnfTjkDjEE;W;7M@Jvq|2E z^&d{q#EmJxFQx*JxK@!fsPJEydMkS=XZP=mYspX_$p`8)V6aW0S!;DZhv0`GqQRpA za`aOt%P9rKIDS4q%coKGDe6lpSHANCHsS(;B_F}$QC8b2%P7`F)o~pPhWwP$iinUS z7pns%Tk7xBXJq(EGon=b1_kZfuzgYMy#1iYZ|JR{5((0324oOw`Yu8`1TKwnGF7&Se&pk%@M|C&Fg0z+!+)b%j=#@=E|7|bGD5tyzB?8BCX39gmC1Vla+Het6yn`0W z4{@cWybt7kR{Yuj5JX=o;iK^W1zU(zXeSW2&_igq5raYqP&)IDEA?h~@Xw|Y$8*zD zcacN23m+rSSU_@r#JBasjwHYDGaKz?-{()E5p)($f=4$XMr8LES)a$=2itVUfRMlo zT3D*cO)utP%o;}hkBH-)e-s0kj~W^zzEs^;F)b`C1yiUR?gm>Vgck7^09)WOql5F84=*&azlQHhv zdo<2tX7Y~)8`+$*KCyMpO-wyU`j23P@0j3tD8XJqxaeu7WSr=kTP-{&Q11+^oe9qU&EY z&Yu|@i(0cb-*zcIzYC1ez5-r-MeF$cuuVN*XY98`&ACu|xoC1^nR_O6Q5MCz!MK3^ zU@=gIcK>WmV|2x)CG?L{t`poRJ_Q<-<0WYPsp&t&JXoe_MUPFkZ3Jxx3YZ?!yfls$ z*=F!K#z#!H!*Ht2j-SexT6deYe(O(T${S?!jk7!Dr1dnCr!JQvG7HQD=uxlr&Y7;U`)E zu_zJvV)+gz_DA@kF{qxk2P%C5r$Lftt`fNu)L##sYuU>mBNl}Dx8vgi^w&X)h8)`x z9-cZ3>%}_H!Md|hnvV7%_H7S@uBH7s0%6DkAUa>6o=T$%&2yIVBs5~%!-W!lmO;{w z0iZc2h?4Mdyy1!)lnf`~kvHSfGsZI=v7_Ixl`Bg7ebb=YbVI~8bRPb-AlPYs|7o@EgOE&Ih&kQ?dI9s~6XZJC2) zS!lmK)J18OEm$K;nuAfI4PRq4I%sQ(%HA1;EIf|B;0PGFEVxg8^G6@>P!ZR9?StXa#@v;~8}SmQ!b_kh;L zi=yZ_i5GZrv7|4{ph5R?c3*Su=mY}&r7Y3{a{e*20NUxON=K2(0yk3ju>JN4HwJp7b?T+H9*0d$Cz61e_PBh2gWRE@%EW@vqL zJo>ka@K_O~xoQBMnm^1)QPT{IAGD(MJLUgXF=7)Y$fuz)&E29|rlC073DAuYXelU2~Nz(cOp2zsAx|Qgyh;^m^@Sol`mA^ z1)7F9qqW^bSiu%qjhYennZJPz9Y-}4jG>TJ=mHJsD38X0FEKZh!#~7GT7VkXZgxnc z5!GEibuf^spt-FQcllpMMv;4iOev24#^5vDn)_FNhJv9tFjsvzaq!^@;JVOyrCBrO zGRM~Hc7zDmmcrdq)|^X^jzGv7i}o_(ZUqHEy>akt6%|xns374&g<)*pF9W#19cU!0 z(7l$>sGqL6C+S#2U@p0Iu#6vhH0%;b_Yu2k-4N-wu91Hzseza9=zpm20 zRfs>j9)Ac1X?U{e7FUf7S|Dh??Z2>WJAAgP>T~PQB)uEdh}?Vp$K=Y<@`k4CXeXmX z^`lq4U>eS7TIL(=xl83@hy`dE_u+%#45SN(EXWht73gVnq@kw$>8B4s8|bOl9)TMe zL4SVk?((JG^7tfb$7_%)LukVa!W%howmyRAv89|Xh%TGQmE;y0O)DUHiCkt0sD{Ok z{`5U>t@LZsof8MC9c}GCbyEl`+XPhiVZGRk=UWmTE>Mfx*kR{TvNwsLoRnB>hl*7$ zK0ipVdI`cP;XXxX2{p)G{co=}e{){UQqZxTKMio}st~Z@T6YgtIZN1)-&uCM(dKcA zwdTr0Kg82D=ubo2ZH9&*9zjW9x`+B#AOtF*Dao7s@I<@a zwF5|QDgGKCaRcd} z6a@oy)HOoh>AD+xN~3)I&A4aCZl=1}1{8=2qfj8i6&DFiqAh-oY+{C3I2u}LX#&Yj zt_BRr0#DSy)%kU3%BbNc{RLR^9}N8sO*`)APDc@;_99+N^OkkeEuggsQtlD*w6e|i zG<6eDGFjt3b%N+jmzR!oDqq@XfyqUR(x1Cqr`%7=j{@NZAZxcC;s2(=1D8idEGY7e zhRj`vzAQ?tM88Bk5Ha#8CZy6AU6x1J)!y8u`64fOh+i*R4sYdzK#@o9|fpjR5$Mvm(9F7DJ zZA2-{1n&;Gh}V+M3AP;t+Rva6W2SERagL!GNd^%i5 zkaRftV=9?Of|hY3o8V+IbAv{qhMp>ly&oH@N!q!?ru-`GCTKk7vaNd^4l&52x^h4k zSM}HGDawuA-~J19Om9emCw0Acn3`h#XZ3f0AcVywdxVTzn8^S?xF*^)0EVv$x3vYm zmUf4Rv)zrp@`-2Yba3a>uUv^l1)T?fCr>zopT1HF9lS+-0c14aL~zk$l%l(QXQs{# zE;>31J?&eb!2LV<^oqa=znp_|X<-tT;~DTUQwZirQ>km{8X4ODYc4>CE?b`Px#E`e zbSNmg?uJ!_o)v-GPe9kqAMRp%4~>(Qas?ML07=Qf_g&il9RFv%v~Cm~S^O{yWWD9H zyT&LdO#llM4~P40>*#T)qNKWDK8eYZ8d+%y>_l_sO`bwECH{~6LsJAl!Fr%Q*nW=v zek)EV_J`N^D>0A01G@o43N8wXT9n|fG2+sLoMWjj@G61}0#aBHw^%2tPy5uMK5Yl* ze$aCsJjdK{+qqrR?BQ_2lDQ#V1d+x zS7G+P3o*5D?X2OQZ%7gB{;Od)u)s$8< zm>94c>wMA?_^+%W3Qme^JUb?<2lbIrc*L4znVctGENF1{f^v1Ew}D+IHB&~{>O9av ztKomu;K(eJY@jfXyHWdZc!k0Aa1f1)>@sO_G@9#E(9{8^C?hQt1UAQ9svDmuxa+DwWPcU5^`et%AQa^ltO;71<~~tp4gpSCK@&f)X~Uo)&RQq) z6RhZTV!uGL3MVe|_tN5mCHJn0pvHctFz}f{!Wvnja1aUm0js8ALWOW&`PZUu8qeH< zmeHXZC}^!fPeA2j+Wn`k5{vR5Bz4UK)gbG;Ogv}!d;FhLRKFY}jB|v84{Jx!0lB;X zFGpuaJ5$@iljjt`*ryr%MjWdX=#WxY_p{vbUnH&Lg+(aG%qEE>H4++XK|-Hktq z>!SNNTt?~NB;@1CjV@q0{}ALr(rzWYOu3gH*ECzhr3G$>i5Twh#+vKXEqOG&rJl?x7iIIhxLuOhvibRR zpl(0>N#$WAYB-32Ik6T^fl9^4_H4sLdN4~!f}gr~_vz9!ye%!B8YUg(@^lqYi@X7f`!&;U-Fx5x)t@cy3{gO0{Vl zj4=7@P!~muYy)_3<^#2mezpc81Oa@Nc~QY%_JoUZt<==!_3ADL&%d;rZCr-mK3|z2 zi8_B!B>@89NSkLNzf650s*eAJSWzHJ$vm-_b|t~N%urx0$QnENWgeRPLdLXf;1XEQ zSQo&fx$EwZmLx8d_-X~`b#c^=KlUh7VQVn{Z$M#AbdaMoOt3!i{d7X4;blgvkt=P2rrY7b9^jr>i1q^L5d&oVN&j^OX?;l1c$6VB>Dc_#Eh@~* zB0Gi#Gef`@WiA!KfDUn_FinhxDD$MiF_0FUd~bOiQn9giq9*i23YDHM53@(}D`VsR zyw!MqzVdqk)yiyj`jQX@1(Tq1N|dI64^&;kF3|`eI-_m}5yCn7OJDkJvoY$5Sh|wu zQGzEs0_gOY?n^f%EV|$`h97N=-?js!I-@)h)!-u)XM{od(A1GFjpL**Bq%xhvkHAHXVeLpI@7SSlmx6 z9T-JZc8*;suQO;lvR_=Uu5yfD^;*e$`$kz>EcF8v%n96h98otfqcE|kwzED{jWShh7A%79#i3KU%icx|)I@BJEd2fsHC&lj*gf@s9` z>mo?{A~!44U+uDLs72yd>82)hy1(o-f<{yO)wN^Zp)IMTIVcaB9)a!$^u!+F4u13; zw4Nu5!MH&|hOSbD^crK(XjG~4%k$kJiOD!~NWb}CGR3y!OhsVD zKPuSR%WiH~gzj@0!%L5;-%eh+Pdb4b?CW+oxKq}JyQkjYb@MlxA=9DORU^)?1!s&A zp}9Mlwzb`a6nw!B&(t9jE?O_z?=>H2IM|CEx zLH`3~WUt=P8yGV*s(!*+^?OyBLcnGE-T4V1VT6o3FTpvHB&?ra9jz!5OysEBXT#B4Gm* zMJ5-yowxPSgza9ppwG|Lsp^B;R*;vOmsMQ<1ETm@^LIi)1KtdTUwf0@f1BUz4db^W z9^HeKH0^ShS%r%qXNCEF8Q_*eCFqhnAEnrC(AN7l71bHr`?Og(Fjcq?>NlPgbZEH zm%#eUoMtIgGk+9Dr)+rCqUtE)&3w}^y5bS4X)5=l9>|g1EClK&bQ_AX7MEJrFHrxN zrImf?!ui`vHSEpjgtUM6$?dcXeWM{5h~r}qNxNSAp%J&VdI{+`xW^05`uAI=MJM)V z%C^L^%=v6-5a@PoW-dw>So~f;uD@!NFE^pNCC;Vmf*ZN-%q$r%A=o`}*BKJDrHYQP zW85E#y`;u##ST=?q-2Ju24T~SoOILw{JH#0^P*Korq=5+t~mdf#oXZh_LG=cmSkvp z5qrn?!owg0z_)TtTCfjp1<5QB$nkR8o*xrOxQ33_6*Tj8oM=~L3mnKj?n^TD{OqJ# zuS@%giunwa<)i*owFEmCS-5xBD09MmNpqfN)wabUds@h2x$rvft+pCSTj8Wzd$NJ*Wc$wVS=D64N(cDYAEK$k2`9ELVtjNqe`?1p8DdJ+`V>9( z{~nTWJ*dr8cRzVlO0l$1?R!z~z{n%EWN;OuE%BwTF$nkt0=%$ws&f}!DI#3#NsbX~6L2C7rb!($?1by=_k9PmqB-5NC-Jr@=4 z)4g1mZ+hsA=p_v|Qz1*5587GKX*VWUMQnin_&V9U_h_El_gnb`BUF*-eBDHbjz**x zOa*x6KBFwaF?|bL4H~3FQb?`uW*aPb7MS)??BUZXQ5!9Zjikvai!G1IV}8n=vYg8v z*xT9o-ex{iI#H%bT2erTu>FSFYu~iT5!NTaS6OWwWLggs==_{1_Lg(`z|XY%rx~?; zTj9Z??Xi7`<83hwU0Q;U2b)fOrv|TQ(r)B_neR6|M;r}eszQ8SroNDqX>h`Rm%Del z+Qjq#$A`*Ejhcrcs`QT}@*0+QzSa@noIO$W`m)avQ*^Hh^J557yj+p73J%rR7`=2T zaq+B>t_w(%6S&A>>hL`)Q(lg;NsE|q1*r!;n5?^#>;jYW|j`Oo#G=h$`L|qRm?50E2A3?U* zp8k_u0mz3ul@Azq*`0QSZeAYhnL&Ab&RwQy>%PD1#vojTj-07WP}?4R`A1dP<+Stx z!W5nqUwh;~CD(Y1VktA~VsNKs;v0#ROK!zmpEMqu6mak$@l7oRHB+Nyb;8Qo>AHe| z3OMY_c&=hrwr>L-Y|djFWo3%DzTXLU$H@3xfGhV&Y(Y0)}% zqM%s@IviR(!dc#OF1lq+T%$Qk_;D&+o{Q%(-ev#B6w;%t>ywe`uQBWH$QxvOnc(HPTYT5pm9K6TNT84rzJYFZ_mZATV?p`y9p%|G*7p= z(TK%L6Rc;#xkS|=NPpV-Akx8Yt=1>xp|9(ui~ogV5&tzfhI~k!6qwDlHA~>Znq1ed z7sxrQpgy1)Zzezthd*SUEYp$jHR==yU_*DG)wnY*_2?t}lQ6T!S*gLijZjigAG zP~VTuT)(61rKb3TSlzl|_}W)PYba|{Lnr9qAobk)nfq)d0g((dB2 z)A_oTf;gc|KMNL{p@^_kNaB_}-IB27$}6=%mAjldAzoM7QA3Nw6ZO;1wo0jOxAoVt zYK#Fzp8Vg}E&hQ)1VmT>Uw!g`cQn69{-^PYFhF~E2wD-&pX?wm+6ro#nfmb}m0 z`ZVHPwEcjbz;d?t*Vh%VO)fQA8h?VH~ zPq(Hkp9(K~VdYbi4?bX!mD#A)7Yb0Mp#Cl_Sa&_*5)~ift=eDHQ~&Fln}RG0lFRz> z>>+l)@6PJP`o1!^rkDlopfs9+y!Un;#!+wM7fW?r&dKgYx-&9EB)lKg8b)2reWbO1 zR2?2a`=DR?vvDUH;y|!~*f$k3?4*Wfm>7@?a`Pi(K&znQ?rmc{X$6h?yyJ9I)+iy_ zvCoF+W4b~-+uP$dkb3~}{g@f4wsN=Q1TuF!>g}$9Ui+m5etiqUw{&KwU}h@aCf?>dHcbnHDm7d zgLs>kZ}#Z2#KHx7I=>d_upY~~!clL@7J-cHiJJ#dm#EWc3 z8`fMtBu7nH`P{Iyxf3?dz38Hg?@Mt@ZCm?Zru2)m!L{djolclv0`!P zZSvgDe(nBi>$khER>{iNpIciXB&uWU+(`DED^did4Y!yli%xMPg??{|Oazf7a_9B% zDTP$aiBtM80C% z8=eMXK0B@NDTQE{UE@d8!-Kb%kJpg}OwRRDIhvqIx8?PF)JkcqFjFyvnFa|>QfgHc zR0GCgvYKbKBI6MBcH*O%k@t_A#Sdj=cN1hch+TF{by<({)4<)#yKwg?A~yJZ2Z}G+8t)*jYf7hVPq~UfIR=x+J~drK8)*lz-LTN5E5ZJa7*B`?v#6hiN_*O ze2dD5wnsl7>aaK^G%8`<`M-R~I=SDsw`)6YRzmn$|D@&vuTu|nf-tA32&Boz>eikN z<*}b8b-x@UH1MBFPcnQp2Yecc-+L=IwDIi - - - - - - - image/svg+xml - - - - - - - - - + \ No newline at end of file diff --git a/packages/blobs/desktop/desktop-wallpapers/armbian-1080p-evolution.jpg b/packages/blobs/desktop/desktop-wallpapers/armbian-1080p-evolution.jpg index f615d82bfbf14daddd4c826b78c41dd50c6510e8..f38b236eb593b84e9d05ac0816c52c339cfd149b 100644 GIT binary patch literal 71564 zcmeFZ1#nzV@+a70W@d|7vY1h=5L`yT+Rw78Tw01ONaAo=kEysrR608kK+kdP2i zA0JRqP|z@lurMD51pxsL5e)?$9SsEy4Fj7H2Llry3k?mI6c?X}h=ha$1BZ-)jF^Iu zn1uMRM!-I*!a&0y!@?pHW1?Xa|J&ug8-NB2$qnNR0Y(M@M+1XE1AFfU5CXseU{D|0 z{*M9;1_=cN3l8zYCHP=~L;O!%NGLD}Xc+MKWdI_?2NM+n6#xL6`5(3abM+qt{)52( z*AW1_>G!rgX0Xb7ngxL8V`crnq3``>_^^Yz8x%?Iw*J*Y_?wBpD=&aJ?{aC(M^PU$ zLj*{njsWEUf2wD9{)!5Y;r^OTLNE2Uhb2@s?%cz>#}$jV8icTSK*VD3%>3Xx09$%y z+qLVqeVipcKa%Z|zJ>$G)xE$#1A(L*D6yV4TR_Q}e}gD1uY#32G391YR*BtO_Z%gB zTREG-d@L4FPiud@z_cinM}If4(G~q<86RfE2n2Zsui776J-@zDsJH2wZuKQT9LGg^ zT-KwS{$1<9;$r&qIdm%5t6Pv9Ow5daZaeo%I|eM}FyB8+Zv>?1ZaV%ZPW7!D)*CFl zy{M^rT(hS4m*bjW7dM)pJhyZtey|RqX~-Y7G?O~&GPLxw_9HJm~LzJRxABdsl?e+#2(+@5(^vkwBRd6%wUG1DlnA{$duhk z1A5@Zs0CoJek_T9ueje|86H$lKI*N!-j1Yb=xQpu^V7u_itRe!VLC`i9Bj~(`QuR) z_)kQY^%F7woZ7i?8!RIZLuBSZ7NGn!QtSn@4V&1VH{14bt3M*o#Bk1Yt`xYqv8d-( zpsItOFz1qC;Gix)*dgeRon|!s#zm2R(@JPyid3^R^FwrHOKg_T9Das(x=zbp(8s^= zIrs1!?~*%E*77N{mCPRY1OMb66RPX!j^GUfsRMh32=mED11W;&{)QNdJeH&JW?p8` zKYtGa0DwMGy7VcGJ~IQF=p{CWxqUFUlwgFr0kv5*9VdQ}!hVQ|Bv(JDMtv@d4*lSm z`IpR}8#kKpW^(LfY$k4o-`ymi3(pz!9l4ECTq}Wvj&Xb|^y?n8n+Z5~IO~=P3BCCs zodO^M)31@dtn_hX<7zlBK@U^-$SfHb=PBFV6BHW`>7z2ZE!S`*p8B)sGJe z9>1hHhM&4WL^wE?!hr_1eDrjG$LFz^<_v_}#@nXAJ0`*kXEFrQvk6yql z#ww<_4aqe%>(KggX3zE7AF^8=1<&0DlWj_6#`dzS!+4@LQdh;Ne>h@a%ehCSkeVAR zpSr10la=S2%9w0S1!;PBtCe4Oq~ifhb`{)s)#{JZdmG1RMa(+>@$96>n)hp99kd)ate^vQgbKneU2qP9n zM?j`6_kF|6wbl$22y}e`X0oq4==@%|k6$yIUuQPFBzqHsZ;Dgo`la>oxONdeP(h(Q zZe`G(?W9^)&hT(kLhqO}Y#$tzqoakuB>Q*G|F8OBH$Zb_z*YJGBaQu&Mu=M@`l9BZ zMdxN$-J|POeZgO<%Eo&mzC8_Q{S)cGO`^+}@}A!>%Z?8_e}OBcxBueU!FbiBiLL!Q zm0~xe{0}qfXvSVfMdsk?h5mMb|DypfloXv?((p+Bd@})s+l#|=F`~7Ar|tb4%%aO& zS0DBmc=xNnq|52FZMCcm+`IxDMQ%n>_wiMI|3@Q#;|e^VZn3|~Y5wajj^t4ejDoHZ z7Gk3C=H2&_0)&JX2$7WL_$-*p!hSm^Xr+Og46jX;LK>-@d|J(qKH>eFto^M*R0YZ4 ziQPJK-9A<4oBc)p{WtXaM^&u5AEWa3iV%w((!Z6zjb9}>xDc2hjrvx|Fi-Vk>qz^4 z;~|S695MGW0=qp-=b75IKmi6pWb*#Rb&%t{?JCf)QWOHf6u&_fjaVMdDu%QA2q1WC zS-b-(JHNuuUOjnsLP>k^+r%P$+8`eP9(u=F&+~fT`S;YOS15L!+~Da_Pyt|KJw6u@ zz5~i#3&Msxt`Dw`6g7P{S32vYW}D#|uP^~z;@k77p8-&GwEOc6;n%@RW(MR6-qPTC zNvnJ)+xGyi)vr5NP6_NZ0QY6y>ufnWh^H67uT6=#-udA&zO>i(Wn(e~PcOcIOJgir z&~2s~9*R>Dc>I-xj;lQ)XMBG?9)b_w%ViDi0pRO`_H8>m&j*lVR*W+B(ti8%+zV*9 zSWTb9m%~o`a{KRQu8{g26~>it=_h$ta-&oLB+TwN)9RX!fO2y-PVw3$-cN-cd`_X( zLmiWKEk*h2BJ4BQGqe+~?l)O~OLZ_!Z2|)CzI-8Yf7;Z&ZjP-wtbDnirpK9_iSJ<7 z_r5$^T*pH~0LbTD9+EPdXcitTmSH^-Zvf!-ckk@MVnXg>fJdPlpN)P4X2qAlN?K=E z4m3(JdIgDvRAmWosQsO9fps6`}vz3WFU5;_!5{4;hAj%pCM} z*=?*wmeRib9#!m!FsBy)hz*Hr8?$2+)kHC&%d?=^S+58H&vGqnlg+3+lAiSBvvVbj zv&IP`woC60l?d@y0GJAtOHlO@KLse?0h9Ksb3cN-&QA{j@I@FOv^p>~}oCgV#%1On6d{FF-XT;r?T-M&D69E+!SR^=p5(EN z07Ro~oq;ntPwGGi#X`QDNC|>3tzw~5gT__Jw}GT+Q`$Hc8PVg%$y zVnqnRcTP`hPs%Rz*wPtR}DgxU| zFe#s2!O-~)Ai}6}Gc58}gE#<>&(3mA*qX@#u;M=dEM;9THOu_|jgslg0jlDBT8zsj zXM?gnwNEqttD5^kdVy`|bQZDOb`A$#p83aQ3gv1N*TVZe2O5OL$avaL9>snKEI8!q zh|=$rL%3MK3N{L%CRdJz4%g}S_GlfSmF{WRKBp#{$>fj=#sCOYOT3|J3;1@y zZ&h$_h`aC}7XSc4sb29ygL-S$x4`c+DX6+0OU+qV04gH30Udn#Qt2pQU=)wjtXb{o zkDW+T<7mhfV;{M;hPJc=zZ>1&U(oUfOLmS0RJx=O7d_ zi_)G-0Z;D&|M``kZ%I*f|Az4ZD0h+!HdEE-9+S^S!xM?TmGUX3Yc$TfK1$a9jb-JZ z_sviY`mXkv3BUo0nurB#E^$lXN$L(~^Ycqi88Q>OaKq0XqM-m3T?Z=HJces1vnZD6 zU0QalgF~tFM<_b&K6nPKt}qNMUjvdDd8%TIW7DPzf6VUiXxkTFS`H z|0EtR>yFbLB4GXvX>8@E!fybSh;=WQJ`0T@b6tVi3JG&LvPtksx&6h$Gb=~4{tZA>5~zq^Aks6E zyi{#QoV$h^-EJV;4w3acdMasg<8TSb6Bd@7O@U|Hk%SSlXDG}K8je0+iBI2_t7d12 zj6re-%F~)Zt&fDj6zgv#6k-k7c_wzlKO8JApLJ7!zn{tJQa$Wj<}b*?s|$L-*ZOA6 zV%lD_GhW4po7RrGi^7owfa@i3C9s?ZYMCK{qJfM2$l5Eu`{}MM!I%KzdMn3*C=&M< z6iqFH^3e^sE*BF-prKNV=6u~COeHWf$@j#ZCww?bWjC?pTW|YqzAMk^whqQAIoMz< z9DA&d#md-kAc-9SnvL?B#}KUTMr!AOADa&!=WV;_yuxSUCuJN8`mhyHai{jA>#NOE z(hE}^cq_N_h9$TcYUzV*ycFIHtD)ZR{B}m+yor%lKSGvdG@8nkFnEsIAA=~n+smUV zhkxa_-3Du>l_ljxK8A?(o%q8P*^v+WyqhN0*RBj@JcSstpl+1`x!Zx2t@~@=E7XY- zhvmBiBX9#1O7Gisp&=jSNwY1@y*ae|-~kU2{O%r3oe--EzQ@^FFT5K{$o1 z;tj9AT-dO_yzzmz0+79&6-*PM2~t(w>a@6oV$smKVH#V39%2QB8YWUb67Z zp9mIy|F6fTXPO7v9Kfn$pw%!h%*G}KuR-E^)eeGu+Dwx$iBE_^#{jD{%EsXhk08Rl zX6H-;h8f;`;?ups=8$^Zc0m|diLvg_{q_J(vh_c^O_0}LQqR@JU8+ktMH_gfoyF&a z2}cLjF^3Fo$HNj0Y6eD9xC%dKm}{amj4aJB5dxKG-Q_<-#`z_At{?RZmt z8xx_#?AcGPKAYfh&T{UFNX>4jwO(+Z6+O%ztu6@e$xVgKcQ_tbQrV%i=#kxNK@n{8 zjK#Aq`rdZ1Lw`Ls<&w zDMd&BPmF)@qZ~^4UvU2ki^)33GT%+1c-+3<^IX;^BXS=Vg4*GGCs_0oF35<&S-UCN z_!5k?FF`hlpNT2lqUj3QUX3uigll4NIz;{)qqed|Jm8D>4rs#rxDkQ(3_%QWnob_o z(97DP1naQi1uC=j8ni^vP8ACnygfO6~yqwU6~pD^}+3XI+6 z6_5Qjwb|^<6A6}H$5J@?n5XVA7yp#>^`EHyFG(Ip-s(q=2{pJcelxsmo}F?m>FY7z zrl#A7;0-^+#{g&5xLyy;#(D$O>WO=4_EGeFh@Gf*qY!t)xa&^WYB!{ z(CsGEB*7kq{MI9r1*b{xK2yr#ijSVR^s&urH1{1__PlhsB?H(3S4e^^h{zThf{ViOo!Ozwr8N7zc zPgeV*f{I_l?+R8v*P7^`)WJ>Rr@D&_1v*o1qC{A~3W2p4t2V!+9%-9UBw2fV9y!pL zb49TcQ3l0bZ`L^}EDs(=`Wy&0jkFljb28fGx_#Ky>eSh7>ZX+wKG$CUD^5;tdUg6= zqV`Xi|0f`)R-0x$8=alNeJXm%>C1;?)d5S7{3f!qUScC{qT(Rk**W9(?U~f@QAaiD zYsI>@!N!BYVtM$++d$p z`CoWLIkKC}c8Okdo^T@%;bhep`PkBeRS!LZTTD)zkCV{M1#ZCwNLu0Dn<3&ad)`Sr zwmD4;IT1cc$s+Q;AHVnP{s~t9iUhHs>`>O(7->x;>(s#X;ZA3l^5)rsi;$hO@C4tH zEdW)EW9prvb$w1s)oMyDA2Kr+ad=v)OiF!ZF_4IB)S(A0?CX($VBiv!Jo&yJ!8;(8 zv%VOe=4^o+gTLT&VxO~4cEhVDjn$dU@YZ01@>N~kV2`VK1-Y-2EBEeD**;nzaKC zxzuh1II72YKzzvc65&i;gy59+F$h83Mh)Pk#&(+iZ)Zu_78wf+{yY+Z8$vGQw`O*8 zI%yAjl~+?yb-O_T%35$3Xc1eIa1jyP8MLH6W1uf%)N*8Bj%{+G?P11F zHV7M39h&d9hHIxzu(ui_d9Y&8aF*dsaA7-jGIVTYEYj!!KE!Q7y#@{Ns~bAzk$Dj} z(EBbom*vluO}5^e8hy`y2k;M-1ND6T?$b0Mm|1XQzd&4FbI?ZAbjMm5B_gU)3ix3Z zWpqX2`EZYP6WG#+0;G*J-*ysv&rL*8$VnFW%F8|Do*TI)V|zZ@`o_pw=GhkIX-dgh zt+pd=8Wo$;Y>u!Pphb|{6Wb_0GVlAZV(Opppj@!qlA_-M4LwKlpqFl9D{abg_Q&tn z4_94oCSaM*i(cVWoeS6C)h7kGx74AgvZKgq7{F)nPr&L&W#z@saN%|XISr4m>;(pjHU%+dq^~7fnP-Tqj}5;>YE-gtkgD$jW?$ymjnZ(E(80Oux`-8 z&tL&f6KLhZp|#}K>g-8NA9m11whPFBz$;l4(&=zZg>{ zuwM11bnaGv`X>??apJs{V`T@_dJgFvbKTsjgdz0sn-j^7N>)a)bO$e$b+CI zvYXMlkxU?K8pmV4wK%L_L&8RFZEL0dlyx8RkwRrl&=WMS96wvVChc5JmPMLtO7C9v z4724@?RTB$9UNL4IFpTPfzR|PqZ~3!t$NB}tSHj^Q^DBzuMqerJebN)D7r%MMF8*; zC^M|Aa_|!PNvteY|2p_0dZ7|u0N@{QD6@}?4=J$Y!M{X`{vu;#mH2;LepG^(qxmm3 zUDiM8;XkDRAn+dq{)51O5cm%Q|G!7zuS2;!r~oiXZ~!C(G&DFk7$gJ$00{;T0R@0Y zMMM9D!NviDNy@@%hebwC@tGa_J0+(OmGDR>{?ImM-#3usC9h@;)(nj&>Ujw;x?Q-X6ajFLz8W$ZJ@3;;6!U zbQwd=deK!T91=05lt>6tmxk=C1(s;eB7UV^{**qs$7AW1PTDK=UWDeAi-{m$i*=EM zp!hddaF+52Em20gf>G5HPvbqW@kQyHQgE)Xi0M$jpD4qYlSZ10U@*}OC=dsA#A zP)RzXnX*ts01cSA?a|1GqISvzUjD>W+DPFj2cR!jE5s%B-}11098-)<%O5`Hqc+uA zzv~?!P8(p1wNu^;mYAaAaN~B~M}G;wuEB8{T*By1+mW?*s32wi6GWdL$W=m3O>O+` z&B~Fdu_l)PgCTAdp-v&Ckr1)-q28E^n8)f{XZo-e*U+X~mm3uUZ`+ITRn54(+@|_@ zr0iLO>{;P9Fnb|Q=89`#c!LiIC0X~yqEwlOU-D`!GtswQrd{lD6a=&fS0}4@PA}}lDc+i80}fO z`7vh)di1Kqh0^dD?mO5?=lZ=2-175 z@(pckca#TxNOkcizEZli!VpcD3HOgmE+$W}9@3b<>OVZE4kZ`H?S!`;hL(;kM6%RkKjg*UxtTJ`l0&qFjPMlT zr+=-S2()krOEJ!I3_kVH-rJUqXW1P-QBmpDl{rV>LSqsb-tA33*ua<7$SCf^iG8>- zji3Tb2!>HQD)qa91&n<2Pry;(6hzV09z-Wz}>(Z5SSJKjGM-zH3qT-ztPM zGw6Tg!W>c~zUT8-Aft|AlA_P-ift?29?IZPYs{M_`!Q`;;F0fFkRm( z0nM%e@mz@681pQ_iCQWyKPe6g=7 zj|sHu9Ew$?DDG?Kn1Id>DFK?HwCZrPjQoUG%8AO5-9FDRMuzw4_m6pvlA!NdcOGA8 z+XNp_=Sb+O%XtZvmGzpC8Cp{W9eQq$b_?af05+mldv2FymxI$|6}=ie?=( zcYs;wTZ`sKWpQU(irTry^>O0Ob2a+HvE(h5C$dntS^$a8aUFgm-K0C2Z^+b-b)oa@ zqVi+&>UfIxbgi`GWRboWcho(Bov3Meio9^o1{Up_jT^XxJiB=zxF|a{KAfdP=0BR; zsFo}WlkeW*)IQC_RLqCZm4IpLR%>wTS;j4}wTOa|LezRxcpAGL&K()&*f#_e_cb~9 z>WxC#o3sjWx*Go|L)2yUf+>{hu(dpv<+)jI%oXnkm2W8{k|FrcVmw1b))15;eFhOF z{_*|%&4h~+R4#=?idnptTB?la%<1vM@{5S9okFwUkMr(+TgC=N{}Qx*^#{NONGiWL zWk-koKC8iIgAA7QNasv^Wbn;sjeG+9ex}K_QoO7o6@%4jTpX-hY1Pk;q z;IxLE!2T|WlUL%X?zDp7!7KabIRgb@KUKRRw9#h5Ou#3YQ=)le&1ePnL!TRD<_fb+4bj==&y+q~gdu*5U_Na|)I!0=P z7uIcSvul|K^%m;IQFS4$hz0kW6ZbGsh{1$W-aq1Vnr|!90u5=3K zD+O~^pIt09807j3`%87W?^G;5!Nzn!di7($MqBSkx^-AUhL}(_x`dKgykOX|AT(?v z+NQ{927TI;KR2V`$Z~z=r^VDAfx|`}bZCuS)(PlTIjLBLXfB{@x0>$xRjMp1e>%Ld z8la-0J0{<dK<<+6tnbQpeZX>6kJtdOybn7urOc!7+E={81A6fl1GU3Xpc>Vx|9%VG?1`7xIkr{#h zx@~Gs+ZVuqo9Oghmo}%vNQz$+VNn9yTc0KVQ9@1-&FF4i7v|^+#|>87vXGg8n$yr6 zRxUpu@+<5kH5MNOCu;X+E%z&yO2gVj{%FOWEX zFk@SkvhGFY>8}=vW3?`2f6P>4VF9}WHTA>9iXR+UismnQDU&RhmySbD7jVl8&sXs_ z*Il3a0@q1Qt|4+7#dfL|3D8488X_sDy)Hj1tcedFOyOByhlfAHOec~2dCqCn$-xIo z_JAWCMatmh&JRW^`EpEpXNW4}$9K8;MU9`EMQX+M<`?qxA+c@b-{_W7w1vxI`i&otoLT6)ny-kuH)SQ8%xUrUT`(o4@l^XvN z6aF+~cjrlvj674t+jN)Ew^&GoJ+{-g(i$*T_6`V^ZZ`E>YJxa-E{?EhS{}2c7hXEq z0ro`ICQXr_EYBYFE?DQ*;3TrI9<_}o{1(v>sYa(bX)E*O6N^>PTq{?SGLrj24n@Lr z=EgIhlPdqg%=*IFoU0Zty2X&ncYu3-0o~ZGN)H%}_vYLKMqbR& zMn!ahimUD9?d*Ml<@izIi353RlS+|^zjk)Cy;3rlZS98g>3a4htxtg7DSYd|$?}no zA;bo9hq(4MnxIL6L!ianUV5M~9;zmy3S~v5*|Ct7ukYm@{183jX(hU$B$vwP@2~0M ztMaey3fR}}g|h}%Eu7A~3UAkyGh+slhN284T~#0=r5ECfv3(rp#dL zSL;R=V!V$v*rTp^4QT?7!V)8J2Pj}rNcjevSfE+>5Wm(wIjv0Tp}uPgqBr7~U-Jhg z2p!J65g0N|iH{X@F)%!PWgu2C-L7%qGw5IuO+4A8Rn%D$-UdKWI=hs(ArmNDB61+I2rJH^SK(R!^cf+Bp zd#G{6OcQv&N}fB^S>zPjEQp*}j}hb~Hi*H^XxMEisEaSi-Y=IWx7lmdc2~U-$tx!$ z;y~1i>)I`sE;?JhJe!pfY5xcimwate5$xzz4rG;IhBq%aE{8^iURf{8TQImNe$Kq< zDI3+v0%arqnlJoVM`87l@)Xo}U~E{7Z2QK08Js)Yxh--Aa3G-On(h3_@Z!hZATah!@=GGYA%^B zIg$h9aSbj75^N1ikAq9K&blfbz|{@9`gZoMv1te_v_J<4#4uAmD&}n!16l0J?m|Kq%%5b62H@ z7l!a~w5^z$fjIFc!)3bZs`W9h1zlOixQ3fIY!YVYH==NqUV4*=DVg3Mdi>poaV_+8 z;Lt!;mMHV)IdcT_B3|6IwDh-AB?B?1Tk-xMY1*?6HtdQuSeseI14w;}SPV3!BPLxH za(XLSYEFGU%V6V1_>+S=-PAn-+4AKu&8?; zdyDvoO5D^1N}3`{7b|g(bnPg$4)(9p_^s({sLRr|i>_pja^DI*`E9ycBH7JtW4Kyw zRefpn5KH%ze{#oQz)sXd20dQLuAfYsv!f#zM;M&EQJAQ#YzO=RViSDDsz|%60pUdgAyC$vc zrB0h2Qd25R75%ZR)FWKiPka5ZDlB;%k9KFFbGnvm1@Hl@AG?9qR*q;49&D%uF(e|Y zT)wf|&335;+qKf;3g%BC(F0MA>T6MEYP;O%OX=Da!Uzewb)Vpqd(l=(on=Jyi&3|a z`tCo!1A^Rg16!;!w;X>Kldy{A_ea=5&BM>9vliOGb96MP}(7oKp`99Sy1L&4~s~M;j)meKX`t=Rg)P}TeET(E? zes8vF=6yD;Ed(KLo)RRsx`43G=6~MPm9>HV>ntHmIlb{4$}TpBFB$mQ?{X_0T**o6 zl1;1nUk;5gEm^N;_+HaHGmy14Bh;rUvl^T^Te(F~OnDt&GwoL?B-ZbaInIFnoS^Wb zJR`+Z0*K*Mc2WW&TNE>Ka;UQfDy%v4RjUltl(c$EO}oWAn(iJ2hS6-0W>d-CSHxar zLwLuscCu%eY|nDDN`By7IR0kcYb8e6V>643rY*|DnPjE^#RQh zaue=IcJv3;!PcpF0Q9PC?UIWHv$&pdZ#$A>V(|~NydQITPN7HRN0$`r&EE|x;l>Y5 z20g}Wj%vlWM!5Cp z@Ha>2z9UL8xKvT`S)+5u?#HwcOI)G(1MD%VW+uKDaL6uN-rALf=G7x?r}c}Y=~amh z{MkMaG8k`g*zb|U>ebrhe_d_&zKzh0U)Z}ma$KgM-@Y>!f{$N3FL)jI>i9l>@QK

u(4!<@BrJb@{Rl#iQ0hgleF8$770KkRqeDIUr2&k$0qtLlP3bq6nj~+w_ zO_)AaqI;e)c;GN%(=(`2(}@JmJ5pBQO4&7B9E_jJKnh_;T%kOD{B2Iw@ouvi*b4gI z4^qa#O&~2stxePqF{m|t?`4CCmZ*lnL|pb;p$N54a6X@Q>YnwciL zI2$@X3RwL`>@=B??bg58I8DodE=+36{srA@rWWnE61WB^Yfi|qlu?`N^RH$i7pqhl zj@Xagk+&2Dr~+A5-;+1^)f_!4#U9?9_ose`Wep#NlB8fUbCykTYjNqPC4z&7o7F;B zFf!D6O7iTAw$l82$7|c~ZHX)M&qa&FU)bnDZU6!>?Rrr~l;daQx4A31KhBHPaku(( zK0;qB0Msrql%E@o7Y3>4PiEzn!^&$6I*i4=s6~@_Hwc$hc;gA8v(uw9PS-}edzxE0 z$1VHGu#?ogX#I&VW31PW8+y7&2#>JtF^{Fn#PJm&!L2klPVw2^tlZzd*G)XX zq%!;xhmJHp9mYJ^V6h%n*ki5t`oik-@#(u$JfQDqp}k=`k2|(zM+wuQ2^H?vQ23P% z#PZ3qsz(Pb#6|{6BB}A91tT!p)azoH`RAl!5~}bK;~rz?F=2+KnH}@|)>I<2EjTl= zVU|y~411Mn=&SOwM>e`}WGidcEv(Vx?=cTP%iZk}3|&7*z$m<|m)%IsMGLgKpzwvMBY z-L&9~fkm{$T?E#f&-5TE?JwNW?yu`toRm#r}lTgp+B` zHx3Wq*&cMj-EMi@Jz(>?#7AC>%%oXSY@WgA@DU;QU*8M#eSFb7a-3xMfx65XK8lB1 zMuk`u`WF_D9$5PP5i}N?JV*E-0#}2L^UOwGU%fE=_;xrw0lo+pr1wJjc1uDwg`gZ0 ztCh`T>5G#YUgv;J`$(6-IS3=Au63j8E{R6_e30x1xmD8+QfzDR8Er$W536R0%}uQ$ zR_gD~)%lJU&Wen-Lj~fWzRekww^*wQTcbA}5L6cy{%IZUrtu`pM473+*~G;UJb7l% zbXP#DY^izBFkXh0Z+EE@6qDIydBst~LBwq)gD3oQ=n~`F;1wCA1>xpfdz00I zH;RyO)kB~b!BDKUkM)u>zA?7CkfGu&(YZ;z2Pvswklip{Vu;6`jQu?yz2RP=Yj>H0e_9vSiZl zePNZDVVG(J_Lqpn@#|HYBK_8jb+4p;U&6gYNwQ5)ij1o;b@IE?=%}WD*yj&1QMFPL zXd(T%l3PSpRoP{x?zGwnYo%(g5Z8-^Y5U(P_p&84E#D(u&m6)$xzSr19l=is4Iv-D z&rTQFC0tt*`= zN-R#o&5BiH2@fr}kJ6>3?)EWJ8e7|HJrY&bYQ8`IQNqS_@5U+hr3MfZzfnYb@U!XY zoeMyo6t#FAdddC+kOsg8%2~?~is~K_vA%SVlpk z_m91ahF6<5ObVoNF6&?u>%DS*e79uOeWUYCN>~vZ)yZr0Z9xFN^{Y!tRzXjJ`KIV^Nzd* zJV+IQ^3#wUpqDw){siIhJK|i)wLg}_p|Zd+i0C-WG~I$f`zALCYgG4$c+*I{v31K1 z>bk|f8UpFi(G@a_Iql3S{MF;nqnFCbF6N<@$0$$M&nRKU{Q-fMG}%i!x4$#ZlP&@( z$09(%ZviYJav{3%dac|W=1B7f{mv6)SOO^SPl=V<+?kfY$rcF#>dVP`N* z3;&ykZY&Jh`wQ~_3;K|Gcy(SernKJf`1V?($Tu-3*y_|R9{L=1fiu+Y7^oawjFEKw zCUjTXMQPR%xkRf|ZM_h!G@Su+eGcp(+UIAnj8ra)kHW-{XHb6=ii{P{+LNqSM>e=TpN~!Pnpt6qTs7jDCXo-@o7{-ntXTXvCkb)}ztZTC#yioQ2Qr2zdTDAQh7 zhA95S*|o|q?>J994)EoP2$EPLguIJ*aQ;|}5mIz7Ku=WX_y$TF%1M`WSuTrsggvP2 z`F%-Z1EL?d<9&2MXEXBP(CmvUP0>q5E>8K63c(j-{xyF%hVS!G%yNIuexGmf?osf) zn37jza+_N)atQ1n>GGM(vY$fnn9&LG<#Oo@ke|f;ln8pcb+_-pLKEWslNP=A)7){U z{;Ypzygx$RNJ5X=#Kl1Mhe7EB`0q9DV_nYj;F?-yV)I+w-qt6sp!-#)0r6`U zru6~!G7t;kfTJ@C9?I^&CDW71{B!JUwHJCT3yej*5ju5fz8*llflWqfN9`rEd#mLL zLtaAZ5$2B{-ymz4aHkNM?%s<70Z-HzOS|u^Z=!>Xu!KYGu|%;YTj4wG&plibAmzZb zC7(uJK)4KY%a3HQ$>0wj^ezFhH+_i;n~t2OQ~Ruf8s}eXmaSff?`gGEoyG9bSsgu2 zjNAQcGolSD0hrq{6Ga0BCAGk~CtL2<4*mXqMzc-B;85_eaKD%=*_Vvgc3RnQ>r4k! z|5}!uy}{rn`s)L567EqWABwYfJLpY$gLeCwT{#dzl!EKt0>jOH=i|*EuVmWtKd_T~ zssW{ifM^mFqZ#lilq3bgH}P^j&%j5)S25qZ`hAU@rH^bvBMnFAYxW~`1e#PT-CBEO z`c5?GfNy0=c5sw{W!@}rxVU+Rn3VO$K-xFM|7IYr?|tw-l2TJJ*>{F=ZF}>Szj_~^;6y-wXo2n$L zflrm1pYg5Uvye-H>Jl{dQrvz$sjyW?YL?>wEf90lS?Xh#NlLleZ-8vKWgMvNQ2R0{J$@O6C9csp?ZT2Yh0xuuFHct)s) znPQZ#REEPK^-d^KD#1wQN?Xq5lPR5mP^@DbU>vsmBH;-eZr=9gKl^{#FFYJ5U{1EqB?b}CRlq;hFQwmMdXSI+_@k5t?{9sr$~!LdvYZ10y!q;-szRm)K}Hv zMiT+OMpc0QA|6(NsWhy&gD_OsOIr2tG7V)D_zwSx3 z`XeQhZY;S(i?F0e!qRP_ z3g+fQ^h55*PQE`w{~m7szk@N@ z{{+UE|1U76;r|(ok^8@ZF@gVpG4B5X#uP$8bA1r9EaXR+_UJw{aPd8Wix2x}AyuGC zj-7$_#CI4o0b3m2vs~u{u4(TMy%8vb2HuB``*pytPk;Ffs>b(xVubGB1HSD6UVqe* z_Qvk_bX77n#WDG48G9r+N`QW6p{67F>9v^kmc|ZRJ!TXM5A7DKl7NdEJc?PD1e&WnhcI0r zOF1GK*{T1Rs{coO?-|u(*LI5r zQ4j?qO*&CQQ4kPmQUfX=AYucgMnt8Aq9PI?BnZ-*h@c`66cLpYkzPZOh!A?{5PBz} z1_<#ipZDAQ{oXV7Iph31V{dxi4}Sb+B7Y6MGW zXZD)`W3T=Bg{QkkguorEF81!`s!HL`iZYegHW_@pjoALw^WUkJIW=czXRM~qti{t! zCrr>a9?UBEW+*t`bmRBAbT&|ZJI$^rwf8RD4yRev`c5y((_#j!2*sfdC+;uL&A9JzY1p0J`Yhh5*4X9DiZZUQB)#57ik1W{@DhP^ec$mC-YR!sSPhP3fTktk8Bx0y$ufKf>| z^SralM#II%90k&c1VEMDwp$D$cwQshv+T?${;f_K6cH8>Jj$Uf|xXy`hf{% zY~(@ZG?N3o?}YX;6Et7xryZ(e9?&4`{A;Lmlvf;snh-~37BcrDs&zqdAQE8-f`bOW zGqClp-;f!$Dr0IaBih$s7kd#H6mWTL)}m}tzJoR?^CwDp97`mUXtVJ9BhO>Uc*j^X zO-q`mw~l+Pp?^b4JNZZGpDgX^*B_lZr|Dj##+kYI(L5qa0LE7(A@$a!N~x#bsNuqH zPMITM%gx%cWLUSMg{UjzwZ3BA6=ewvY(vMxpRIHXO2s^XWC;j(jr$(Z{rugRe(_L7 z;s^7Z@XzIQm+-kC%PLZh!za{yB;9@y2g!p3>eZ1go^|={8SI*bjwo)?nnoIf2UVSJ zPN#cV9XVp?p84}|*8T7LkM(@y8A_Xt*lpq8kQGaKEuJ|5ezBH=&j$dTNveMp#yL}uu?XFm{p2|pnqF}Kg3Mujski{W;C2w;nPova&lX`#@iqwQvi}jN0w!jry6Xks=Cx>s7mhFzcP(}sm~IGj zW_4nx9yO|UZm*}&z#-jMp{z;#z{w74cuZ3Ajf4~LqZ<#QG(NM!HvVH(1^54-$g7gy zjeC+6jTjG!_i(+X>C!2>efkD+5jp@?R5Dn-b6;R*YII;pUfcFNQrITeZ{QNRv40(Y zVc)$OFJz$GoA7N&8Z=1zoJ-k9I3HS{=vX`ZLF=<@ROICjhE!1b_qOt+3c#FBT30Ix(efU#8f7<8KfZ<6UH{6GHh z6l)vUSl<&?t^z2}mtkkjs3!i4U^@d_%}YumF-0l81=QN*qvgwun|f*djBQnD@E& zD%ECS?s3IqiNm^w{DGdM$H2i+)$ppL^F7+fsjvI)y*$;g5%$3U<8(^(>THxlr7NZp z9R9&J9zu0dkBzvof7$)^esdvJ$eS7xYpP5WQ=HkS-t#WQz<$i_kjShA#Q%%r(P9R> zDCR+B`Y8M2;Sv4{??)86lHfwl`$A{NZ-`Q&BzNN=kRMqg(N9}2Feo^)bP%hIk3lYY z{O1LyKP6qP1iC!!CRl?DS3l1zPYwKpq;`{P8*~N#Lhj zUyW(LU3gJ~xaW=y6z#o<4|0{u%&Q9A=>BQCH&W77cU@sWJR zT~gY&@w_yaM`lcTUA{lIQK}Iku#WukN#4=pbjUubrE!+fDJ~z-o5V^zxbcRJ5p$+F z`Bs8vZ%y>k8=Af3ovdWm^^;X^0L+lk;O)fNjpp*V1+(F-3;6+vwIBFa7cf%DI*bI} zjfT)ml-0J?xLx!p{P;bg&CwMk*fj!4vEwp(3Xat*U`CmEBlA-~w|%ulXa= zUJVxBJ%ID9>FeAJ#&z1>YjYNHABI)<9q+KS79p4A`!txB`9pX8aJxWf5dQBYCn#sK znX`)ig)wW{1-#K3_ujt2Tq4iDUcmcH681a^4_`z z+4306Toj@?UZ#iVI`?~oF-ea5+Hc=Id~AP-=pKFKTLAJ@I&cXtBACWfbPIl37SjkH zMwq99RIQB{#21rJvnIk0SD2&?pzszuPp%>AL7R70P&uA;xN3_Iwq?l!qbO3UwZWD&K2 zyWeEmMwp*k`Tf6RVdWlUZ|*^ZV>8*% z3FJDQlF||yi{a>f9wp>2IvsluOKeMSE3GD8;#8E8i6ti zBS<^Fd`As^ky@1V*{*L^{>$tIgV&3PzdsX>Pkn4KYxjtn%uSQJxc5$E9_|OZ3v+h& z8(^fMh;2DU(+ z@j?vAta1Ad`7pmSS5-+**)gYEfD$|phP*Q+=kCGCcNh0GOXz*$DQT*63U~<7G zEGY(G*aKfPLl=Ynca@xz!?4bsdCimUA?*|Aety`nk$uwY5tD4kg9w$O#8do{i>xL) zQtzr{-xax$hFfJONSvrxb1Erpl>EfFRMveo-uGN;RoV`>4h(QrAXt@`VZ)a6_}U-w zw*B?(O-RO#iD`+EXLcq#TFe%0RS)soF2m;lr}UHg)95DIrKfrC1_JeEK2cQ{KlSt= zp^<21tzTg(q2KQ}`=!)-T2&q2Eqd~_bI?hgx9i3->~y))hT{nGL4dmHfWG`*lriN} zQIYS-Shmckwdc)b+wb+G&YUL+wV+vTJsMzP;>YRXW2coCjM3;}RZEEn1~(J#pFg@Cv28j^TC^X7?VoLP76&aP4;uOVzrPoM%C6hQngMyh zkllS#C5fQ7wxL4xUmJ8TPFqSQ-N^iPz%#f;>(L1RI)3rkn3f`CvwCOV>#f9_0squi z6_2XkS-b05m;pOc6*(mWhs(TI?2FcRK2nv4@(Q^T9)USYf1ev|V3SPbMC&?>z~tmJ z@m+1~eXwsVveY6<>`e_`dcH+7?B5QREqS36RA~57Jc91EE1R(2tV&4!=Jzy8{suNY zGzYcWI3n0bUmfF`4nN~2RT${S;_xQ0PH0WiJBhMb8~R{{cILL~t@B zXeRg|O&|L)k!I&y`y$tZN8BYVP@(ZcKis0ojv?K1%p>4Fb?Gf-*Zilqm&Z9ux=bA_ z0Ycvl0^g@3@^` zP*r3Eo%@rW;pa1C74u=+g(%EKfFm10VZNJr1bwfHYEc)>aFeoed&wajjRWd>NBjV|o2Jmf6&_Dw#|ud9YqFP*_2 zDX`($eFpFdsT%ap9`iGaCnmp=%EQ0VK7;v%;5nmd?;{_&_EtGdCMz^Sd{0`VV0_4+ z!Ih0%nbFY35q`#*k~pPC>lSTu&W(80AJE4dYl{d&XIv3EL@$ZUpjN%v#$ozwfv)Fb zVhiNS$ah?|6GMoSRmyP7=(QUeKJOLd6ts1e(;?2zfOhjbbrHlM-_KTwM-e`7WkM_x~L_g9= z&ojODl})WaS~IN6%LBmIzxw_+#3mL@)Yokw53;C6!G$3XEuj@N>3-$~srUL%q@+uq z-?)pMG=j*qF+`}=WAMm=TRlp!LpFAnmmhx5It3`UrW4jZs^$B!b?`$~;sYp;>(r$j zAI&p{FWI6_k79kEr9saHZMf12lFtyeuN8tASDK$~32z{t!M?la-yic6!#0x7o+!); zztI7&XjOOrvG5SJB=Z?wL=Ge}eu87n?k4m%M8Jjw&aiHdiEN02bi3QhQ4iK%$6{Xr z!RO@xjYeVbkSfkOb>r53!|{DX9>3W z{+$hfnn5`F4$ztL%5ss_M2hw}2UN#A=Y2LfE!FXHHwLo@RbH#DB(6xi#cqPKclrRh zb~Vag>KoX%ZFj@=F#Da|GS6tsQMOdlHc0wo^f*QuHPEqP`A=DK~aCNLie8rqs@Au@)0&^d2jb;H}?`k{6~ z#g$-*Tufm%U0~x2{WT^3RArKwo8)7PJLX#HTEEO|`X(*iie9Pm`XoN1uNUhmlYMvS z&C*cRG~5WX(!YCyZt%GmH9eY|TGYw9uOYNg=+(5K?I(f^vZrbBjt?gCwSK(>J3A>3aMS62;Nx=UROJz02XMIm^xPrsf7Svp?f(NHBwu8_*AiW`$v zvDMy&S8_h*fgjiN$KBs?L)~1Mkz+{Yyv6 zP1368*;87=`NTaV+ZxN+~mMXqu~SPF^|?A6n$dH+6s&I;HN*(cOTJ!ZnDzPT#!IZ^8vBFfy(xcgV zL_)mER?2TkMLikM@TTvM;Ucbo!l}!pWa#%Dp{Z_@o&q*a(BUn!@EbyxG6<7Jr+9#7 z0z)#g{`tz5WU@sgf90s@k$KEPni$CM4HZ^)NhLq=TFRW)f!$^H;vhiSS)Q9XHo|d1 zF5_@mMu82RD~~r6@k#f+|!P;zk=0^0oMyP5nuOCMqZ0IVn_p`Y7QS=vD##AXKm7ynlMu&828>`5wf@fJ0^;mNZkBN^g~X!{G(0aYwpKoj32lFO zno;*oSK+TKEKscuFtF8=St=PLNFan5&Apo z6oS(^71r&VEB@q#@x%64wW&B6ULA4D&K?j8`X6Nn8lxjy+W5m*GKFbqIg;oZ=2(0)yeBTLVX9U%v5${o^(&LWbh^L+;IC z@%4D8O_AGe>{=j@b%eaI%&>p&^x{X3XJ(y*QQ8XYIP3@0Y$e(iMXdMDj9^^!%0;Sj zX${r!7&5s*WI-s~_n(4=g(?_BfrgJgmgI48CfdkG}gLT6LL7ukvcn~Rm_!~mI#WG3Y z!rt=`nzJe_B!*{%ntY4V>D2d$3z%jt^nW&9X>pP6K#iIFXwRRByK5hD4s&0T%g^?m9!z{#yi~(HwpBKl2=$-4YMM49vj)PI1UKsPXf)%;yerLeH+2xt+9LC8D~T?% zfux61mP0Vg@%2_qao%6XSVaw4Y`#c}jVOpG^fS9)1zN8gY}rVcfYjrzc00_!cIceg z!XXP0& zbu1{cZT}&3wr(}Y*t9QmY@y?MeC=vA$4=`%P8l`?TS$6dApQHAE27cRp*-AU6hwPL4Q#{t-%4kLoF;yTXZRnZnS!_+aW{wzBIx**Q;dr~p5yz`23ak# zlhtLGQ+FS?gtYGSHynrc6Kc!Ib9K6(7T7e&Y8liS!33_cB}u^DbR z5F}VZ>cVrBz<9L_dL|OfaQ*RPb_q1&F+O!>oZ};;2Y-@v!keg<9BSjm$~CBiR-tvn za-D_m!cv`b9`Kwysd`vT5fD`43V%cXiLg|fuKX#5yUp;}{am3iJ`z&Q6!=D+!XqDf zLKDCLYJbHp{>ucN@~@`N|65M~|EM-xZyZ;ZhzmxJZFb_wQ)z6^xs~4#Q(7*!{%z<@ z#7+9+DK6HU!~4nH12yG)0@U36Mu{N>BTyT=oW<2aJ@MrVmFX2cv@LtAs%O#l(*y42 zQ|2;c{&sr)7%bc?viUi)?d5Ryo6ix70Tx>GthG7C^-pDiuw5|34;IDbp*vir`uF4@ zy?n{sI`^(E?Qd1I<3*S<^eTp^8(WG!e{y-stNS2+D`;`*7iw6y$2 zVN6{v&L?}WeYS{O=w#eCE%s9Ur|}BVaJla$d=*M$s@d7^Xx8w!YzMD?KEu{Pa{mqK z2~cIIQl*ItbK6UqGMDQ#?rc3;Y;{@6p~~p^JrI77;Vs%b`coG%X-N>)^#3}mdU)3N zQtgqrgNCPeniphV(y=r}y8?1rq(xW%SgZMf#1+iwdJE(+Mv+>TNwK}2?X`FGHzex? zG=cazTY57#s*Dt}zI@wvapa?*MMTtQGaC3Khav2>z0GZPd{)7fHa+~^sa`p zxqDeVEf)^NJ0FY+iwBxcHpMkLa$E+D*9tq>Lm&wDogqSkFR@`+)RyjP6ftt8znC}W zeJu3=#2Cai?Szr$N34QZOk!XCsE(bqQygDrb4fkir5Ra$;u&cv^ZH6LUAUV{s3-7Q zBF{E?e=+u9EwPBXS-p1yZ%>aD!-p}r)TD)?tjF$Z&#tE(VyCdz`Li}8v5w4n3pk&; z3keSpGkJ(Oyk>37+Mp_YKmG@`k*#C;WF>Y3Q@Vndk#=NS!KRSS+OmYV<9iTS#w@nwTq)6DY#IEEG49?U?8&i&AF({)iIa(YtZNXQx)?(^qC(j zL&v+x??y9irl%3R`>(M9-9#RggEiGH2JhpAF6OPPtUZ4KT8K)_+G926ZQlO!#_1Hk z)Dlh|{3mTe+XcGMr<1`Ye{=iCpAY_ zcu&durUrjCYE_4pe05P#%bt(liDmY?Q)$q*g8V0LA2!%4-j(oWtXa)f(*WyswvOX% z-ojOb)$E$42FO#yA*T3T>e;7>r;qfsi*PCCdM@nq9l});IL{oATR%Ac8m6ER!Af`0 zpHiL0_vK&Pvk)rhZ~6rfn7@p^SXQFR>%Hi?nIPo;`H5M{zU^Fg2|K)NW8Gkc=hWE{cq4-#q zVbpX@aRUa%1-{t}j+%|+s=c@0G_@BxOW6P5jqYRQ*;(NZqwnV676(3UoGgd4pl!Mv zGxx<5-9Y->J{qSlWVpVb2Gyo{2d^VI5xcK%KF`IB$Ch;)=yfc6MH|V&O@lL1Zw9lb zZE6Qr1=Cxc-LmL%Q{FnA*79$;my;$5j(+=(6_t12j}nS>i>?$P%{{)0> zSEh4V)9tfqex4>Y)#`E<7gE~XO^#cRu5`EI!MoqJ&oVCcxE02KbQX|ziaX_)puNg_ zm99)?!O$IXaPUl0C7NJM~UHHJRm5Q$fac#wl9Ri)c?jjK|eHJ!_)V1 zJ4zMjVt$k;WLrY~vWfSnks}aw!@?!q60t2PD!=Do@_{WfQT$vt+E%uF?k@Mn!&(L5 z@mzJ#l-fe}qz+J8GsafjHEWP}Gug~-mNxk7EV{*c6S)r79AO$o#|>6CeSPWo4WMN=QUy)*aJl>O>)yy%;sT^=_hzcf2S?s6X= zkLk-bzSZSXXk1j*C3mkhrK~(TUWfk_;2MzeuE8AXVwioEO~i={Fs+OXeg-i%vZc3G zM+-BGVn=^0Jq=EEt;m_5-M+Th%Cs5}&G{N_e53p&`tjYP@+;X;5i}1{!%~i+g<1`( z(Y{iVk5O(#ZH^(rmI`;m3g)+5-9}%02qVb`MI|j^xaiCs>lj;AbL=@(fQ-~8kua$v zejhMa~lF8iMRd8KYyLA_iNi@o*D8)<2U5+T;6Oy+IrHnX(7F<#}@DuP4B&y zvA%lhoC?3;Vg#fYF;*vQ$9`!Yz>KCk$qdFud? z-b_1a(YdY*5XCmQ_s|M{n4}5)nWrtxFzJz9|B>U>a=FFvbe*xnKha7H1ns!p09bZv&X0%9Y_=i+-b*09_*Z!ppjVt<3Yl2w^l6w#f%l3O!$iCTm zK?-hp#UD0zUF4(S+{*9VoMzSan)@YbI}45yF}KdJmfWv)_1Ql&;}e=e{w{ z|AUSlCH>1>l7P8qZw;QvCe-F;thTu|aS#8Q#-8B-Y+qj~=;y$tE2 ztgwIQyuD!bBeED)dIJ|IZjKvu8e}Q$Emu)fn+o7HrSnq?ixEY00(cc|2N4M2XDL1s z#;K`6@!+WX@@ddcbN={ep0g5cc^C<_5sj~Gw;}bN?}quta^V$6&JnAzbq{`2q+VxtplCx!>DK;4X}IGL22@#txMLH3*I0716W6xEu3GhzdhaIi^ftWn4) zYmaIi5!+ZPGb%=oA62p$-&|(QN40+<5|LY;Jr1DdwT-n(fdN#ZPNX;ZWDME@y3@Tz z)iH$=-OKO-Em8_)hRt&abkNj%W*yRmQQy_67e7DN?VgL*t9yT!zgmcq)wGD#@&f&k zwoqgJxZpbdj~mx6H{sK&#D^BB`^u)7mcpyC!DUr(>GWpnN}%W&oN95KQOiyfH<;ED zdm2iWxo9oPBzL)gEG4!~yvW+Rg*is&|M*T{{ba@?(b0PxKki_qr>ah)O}b7Hj7<;C zU6An-a=xo3xr=ldeH~Nic4N$6-mC=q+HCk`v5j9Fdo*C)tY}xZESR6!FyUqp9W2-9 zMha{WM?a`t=ktkAXV)%il==CuI*=|5CyHH<=AYA5_Hk3;O<4c&J2LIi>JfGsZFkk)nP?8-2VXozQ=;m* zw-2mf#pvu-)cB>c>snvVTaJrjBnsV7j$QB3A3*2$mOoA#tAx$%*B zcPH*<&Ygb6vOEl>Yf;>+>k@r~ySrCf&bi;oRbXV@W^ht5hvdDue?wSd6g#2&;~xB$ zRvCr4gLHQKt4g7>b9^RIIpJs8rOZoCzimQH$Jon`w(QVT>l{!?`R@E1@P;cD&B+%Y>^n*P<#0z}>jvX6w=3P(;x~e18cXLT@4dbofrJqUcIg2Er*+++NHjo!R?uUIa zU5`Ke13~-hTO3iLmt`elVr)@b8j$?z>A3O|mNiifUZd~>0+kSWupHC^Q8WhjJXyqg zy$dh-t~5LVcKyv**d$x`08Z&lK{(pc>j5EmJcvK2I&0DJ}PGOYoc<>OKz zO3MdOUz8SQC!K_c?rGaMHAyjKlBh$ktYXTY9W>4nm7d+k+gP~mTri$Sjj6O^+Ye(t zf!av6q7mL+)sKKp8Zo9?i|3+aYX#JEqFd%odECK?ss$D8FG~xY|3%$5=E$_PXi@s7 zlkoJk3VPjeL}~&VtQaIs3$N?jteE#(zV^a*-6*sw>`)9RumR z`yl4@Ci!<`mpnG0tGVLk%c3*=Az5E@8a||d8Wb&30LWt;w<0rWu}tOxNX>^Ld9>PB z%K@!=+R!$VvSZGSi++5MI~NZpPj^uc;^ z7`Je(Ndw8_N-Pc5qBi>20a$BQz>Xv1`q$Fmkk@ET!s?m<56BxkS$sQ4qJP>m&AdGp z0HZ#b{z+v-CSw3%747_JCm5t7gT>!~3RMCrA-!yxPFl@XZ6r;hA}Cd_Sfm1QjuCDm z?OB}|1zVpg{(G$$FXr8ftXk8_`HhyD?jf{M*(zGw0$xw}b&cI&^dL#TMuj8w1^KxP zQ9Y+`J%z;7M0Qsk^O>aEwJUZ=ulQe@zE-0By?8b4U={B-W;=P&?d{{>8mv7+M>}ud ztD>Sazag5q43Yrb7UO;t=`4tmCBL2TS=_^?~526$G}-TH9xva^;Ct(zYi1g5%@&t9b)) zZ&&o$(v>HU0AbwBCoC=Kt0jIofx#csQckd71M2XSvHX$#W^PFGmu=ykaf?;Wiw{SP zV*hI*yI4Tt{75ciWUuW>Ur_3Lp+dS6F(y0mj$+xVWeIB z;1GwbRN5E2kX`+LO|L8Wq6ObI(fFd7L^@gMbMnX_%+h*`Y)Jj-A!QBHprGVP zK1Okibbn+o_~dG|<`{Eu+lcVX!jWcBPp3s_D{btFrhMNnJG>PV z^UdPqw#%pLk2iJ7v0)>(yX8fCtz61(+Fkg3GTJ+frOWpg>|n-O=kIyra(a-vXp8t3 znrjYj6!wdJ!j>4dCT4u2Cuy#ad;C7@iM;vS1Zp@EvDygVp`T)9s{|+(c!w6?0X`jU z(oXg>%I{`g5i&CDg?{DbhsX}Js!wq(Ef+h91CESzcdM6m{ya#sDw?@8e(=OT^uO;h zZ8pQ&ugy7JhH|PWtz@O7cgEZK)6^+TXoROka!Q(oF|~2}XM2h#!(fXn@@J;?z)VB( z{}Tf1@{!&ck3hM2wdPFbbD1BSl1w{->u|JP5bel(3$M12vc81+M`opK+C9*-9v%)>S zD;Gq|wGY|)*g-F~!qFqGrMBl>(RSspweG_^@Mz_-l?oNGx;k|~bI{h7urW^k4x7~x z^Jr|wY3Mz7q!U;1;`qz-bkAw$I8Go~idRj8VyI@lrT|lb5&J=f!SxX99L$v9wThQE z=dWon8Y?ww$?wqe;P$vY#rK9t(PS3~zj8zmIOerLoSa6u&;$2hU$0!5kkGb@8mHx^ z*HrNa)%li>)cAH}>EE=s!$m(HR;Ss$ck~j=c^-JyLaw)I`xbK#O>6Nt?=c?nNk{Y1M&PwDpVP9VjA5%d5g7w$V6yn<8B1jPJb= zCpU@#tll?*NXv{mw!_=oYglC<=y-F}iIud@af#e%R4LTNzX(6zHByAKm6gP%j%+$g z#V^~5*}bMVn0$(tB-JFW5UyNfm!Yv<74{C#H51^zJkU9!g|(W_YQvn?k-HPP<#SKN zw4-7h5bJ#cd41gVXm|II3Oc?lT@mv+4B50g_QW=y(4FO;fb+|tDxIXU=F=Z;n6nR0 zw^@8**b&%k&mD73d;yWpDcIHycSS$jS9Yi*mz8KIsoq^%$8x-18@C8Duj|kdG6oSy z0c!>O8eW)o(VfOM@B0(k&fxaSuj4+64c)eQHy>wm68~iE^!{_=Pm>_6{{|ivYeX%M zxFv)dGWcR+kxiHO6bQ)~mlBBw>I_Nr_r<7?^~(Fo?`*H;QKGHJZ$r*$ z`5uP*T+yblTWP{Yo;$&?FWIsjMRQ=Q91GCGkGYM!9c|7a-JY+R??HQePoeHUA(`P% z{ug5YpyvO~7sLyHA!$`z;v{x5QHF%{$8+SJj@wkw5tQAG?fLXg!^7UgfS+UjYQW-K zk+wGW_am2!lRT{z6Ar!kk!`KDr}cEA;Ypu8$%|UjIjw24E=DSX^8By*GiZXVy`Yui z8`%rB_=Ft3f3Ugmmbu3>{H3!b_QwPHbPM@2u`=#)k-URl{a&3`HXH))M`K+e3x!x7 zt>^QCLBBW^Q+mG^G38%6cN}vLB*HNH?hlG9qkP_+p8;g<-Lh_oUv{^jNUo(FimiV= zu;y$Qb5KquFh|z<8uG>Qn=7pG%a#Ry{B)Me(b9?(-2r&rP5KyC{kG4nrTUp+lP1^k z2uvwF<+$kdo&d%8<=7lw_5p(sZC;_}h^ zq2Vo9k_ZdDs`sueKK+DVrxIxVHACe&G6Jo4f7;YGA)%&l&Ng8Va=B^`^L zSWj`jkZCKJ&nW1S06twH$Qne>91Fiyf7Nh3=OEV=5wGwcoav&QX$QzwOJ6jzK~F{; z3zPpmzrJ7iv|5q{b~6TPWQv{*Ue~wU13~k@Lt`;tv`(TzIyJ`=E*3 z{)qv~n)k5;;}ur_4N-rtM_!KC%3m(I{lZ*tGjjnYojsdONqgW1oKe`e5O8+$kUW$&m-MLr+Sjr`xGU<B}q)C@<(c#NJtfHIzLPhzj zs-x?ziVYAiVXvtn4xWqP)~TMi7%&V^j}yD#i{k0q+aVv1^wtRpNr*np-aSXlkvhZC zKd21x>c@uS@;;vNSUuX0t(aZgegU zceu@=wDgdL>xDm|iVjfyv;%e`(F3=ltIuCG%nfa{*jXbk4 z4M|%)HlYpJ>%~=)Nq65&uuYZB%^YEBl>5KDGjS)#EWIe-kToj#2_WGGlv9FAm-NRu zl73O6+hSH0f;N+JJ^AZgrib6$)r^bLIMC9Wo76M@i#@3B8XGR^<2e`m*iFK(9a#W_Qk!_rB&M&FAduSEDa+{=J-==X?cs`bsbE}3wGF{7c&#WpzW`!gW4g?1L z5p>hQ?l(&8zt*U#(4-uhi!6&A`58B;c{w_OZ!E1t8G2m)L=4+wF5^f18TBCsf(~6l zJpt#YE6S4ZBEw<3Q=et57ZUAqKp4^7f6PF%!J&1;Q-}L_;+^!DS7q9A@Vr+$_;t7L zUKuMf(S#Ph*W#NhD2yE27`{{XM;%hf z0u*ElskQ)Me64Vl$(<&*2P*;-_a*{RSr?chw*yZ?#DXDudg1l%!Kz@+8xgrn0X}R`)e8}on zDspikRa*TNB<-Oma0?`iCZEPP82pzgLt0#0obCfHLm*!9KZHT{1nT}cpZ3x>xdSjS zX!tpZ#GEd;#$qHCdO;5e!)3f#m+ZK%2RX075>S6Y=dv2x%LvE~!#Tr`AVJ7NH2T-C z0S6vF6%zzh_4_1KGnHOl*Ezr;cIdP>VKZ7K0%HEa{bQ2RsWf)>NA1z#AeDgvZ-lJ= zH!Tv@pl^bldiw^Wjwtp2>sbHiXb)a2HN8(9E*t*)eyu0b`TIA@$|I4GqiHLv`tY{=Ez$GZoGpk`sRh>CdyBl1%;cOf0$*?;G~U zcTIsoVUfrgIz!Cj{jZ1lpAYaq9^~)Oe^2V)vG_X{e=+bE1Aj5_7XyDW@D~Gr zG4K}ye=+bE1Aj5_7XyDW@D~GrG4K}ye=+bE1Aj5_7XyDW@D~GrG4K}ye=+bE1Aj5_ d7XyDW@D~GrG4K}ye=+bE1OGq90QPs^{{`r~iUH0Yj6nege15IhruN{gS&);;O@bL4ia==a0_ljaCi5>Ai#wR7f#U-X8CZ(XDqM~|CL`zRg zNl#8mMftN5Bt%hE6jW?9G;B(ITzty^ntpr+;G*3ZL=8Yjq6OT;MMB0!`q2d-2Ot6N zAtTTNexU~_NXYl^p`syD$q@XXslTKF0Lb@|?jdCOF$cgzMkGE$egps@ef#n+IsSAI z8Guav`^;u^m~R8wFe|y+2SK`Hi*34snf@nr7)^4p1z4J1rHunm&ip!=^C6t|y|ayg z+*QvBGNw5)wHHju75xvY`+Wny;u#EQ3<)8+07OEM*yUc zayoxd|9@mXMT-4>9%N)eW6VHQtq5KNwE7X9x$2kN;tW1p4o3c;NG-)(G63hBA+4>1 z^s&p2ro1v+1OBu;Xl+J-vhGLo1`| zF!OY+aCyXlP^*7yw;b&4DCl@fSgPEo+do7`AUxlL`pkZJ?;9+%Jj{h zsRtYLI$l7!4B8#G?g>X-rcX%*4Ztc*u`DQxTTTFMAO@52V&P9Qi!2Gx;%4;6HAP`kN zV@-U?$fdG;o1#rCr0jJ*JA~+YgVCXhrDO)5I4xK2dwU32hKI6tt~*-{*+&o`f+ z7p!oAEt9d@?@zVpj95yVWYv@KyM}C6p7RxZHM;PZSafzYbETfI$%|(>BbvJ>&sV+* z{f)YQh2q~uey3(cp9TPo0Tk|y8t0&cVE3=n``@y274%l+HS=lt-*pU*^s?Ir>hnZ- zP3h&*nDH30ezUgR1G`GGgWcrS>Ry&+zfm+`IyP9UTp0?1Haj;9*TlcEH!2jmHug_g z#5cl*pUsfnHb#I-$sJ+;4%L6)|JGCx8~-%4?XG4Zzhvg{yS+=_tj5J`QvTJ@ol-SJ zd(Po#!eyKkF+G96Y%SY;-Qw{VNsluZ$EWI|=KesgaR@)!1?R7|g^IR)FWomp9WN8tv zd3)|McbcB(lb^1oS2MeU;zss#dR$0I4~z;-2}^FhU;Dqq|Kn6-K;J(SkOC2(#sI)m zfxXuv$Vd9hUACul>gFmf<0S9m6UcmAeU=PEaNP7(!}xahdbm;;RZDx8$z(}pE}8S^ zwrdXx7Ner7wIH9m1Q?5Uy+$%cUfP_mFFI((6=Fy3g9WropVY3=itqxnQ$`#@w^rX) zc@6{XTAJ9d>}v-dn(funsy`R^olh0g)G&PlHvoUX`Rn#*4n)F7yjl*CISBuB8_0nmp#~>HFZCAHX!!F(D$Di`F=I*#6w?)%$ zvs_Bed@s+Go=;BJ@mYD}%@!aHoIMD0H4ipkh=LzBPg@ zNMAHRelEs!iqtCc-w63XdH?0@VVVgdQwv)P-8|X9nXdK7!PytLK52rK3eLZm!HCHN znN6>|o7FDP9!~DdxVlSy+1_7IIM1cDHEeF=f{>}KW}Q`?E-p47)kQ^ijE3YYIO?5x zAM+j+8?K99?ka>IL-T-Mo?#;SnVft_jkkmjW9Qge8b;4kf=&jveL_~cmnz!Gx%eGm zy{AuF`lH)iX2Z{!tAVN%TDsQtZ+I`q`SkFW1R9$sotF3a(p{L(6mGMo#qrp`w*UVS z+rdbzYTuu(sgTag`*u$WWkk5;B^AU6`m>m=E&8TyJakZ78dw34YtUFwUK)6p1 z_Uzj-t}Vp%$WeB#r;tS}Br9}m$W$ZdX$G^5c)@JR<<`eeNvoecM&=o|M~{C1gs!#f z7+QVKO7&x6?(Sv78>hbCs9r?{qd~|7M%zFI1SSDZ>Pt`OD!>_4+u~a_V?@0(`wjD3 z=uBQa*7ZlzjI@`};20hvkTzwQ{32C&^bbJ%UyvQKY@q(1Vn}ZTsR7>b47O3>rbSAu zMxF7z5$&=QNafrT-G+N@#3JW{nx^!U+eRzg@p;qc_Yrr3T)S#-Mt5V7nudT zC$?MPEI;7AqZH38BN{N$yA(4@w7WiVK8E=YT&QRF`ZIe^R|2Wor%ZRErjIk{#)O_=GhQicYl3dQ?yr$PUnJa7T?lHSs@&<%<=Ucezgm0<+mh( zQ3fOCgYX@vxjjft)7|&mn{9WKm0OwNu3qI9ZnbM7ty%GBFB2BnCV1|IOKpl>MMplj zcpWx592>TYE_gZl5jL2tS9okY5;aNfw6YJLmy_|c`g(+IQj!@BGT)*3_sf*unYMoa zZgQ@YFb%OkXP!3Yj4=>y^~$)TZP4BbqQT_WU+CVs+@xPAqko=mGz3aSx78KiT;-5*W}7Yah13zkd$xdQ5>KRY2tnYHr>(D2Dsz(Uf$;XTasr^o&(*pxLgE>citu&Q%2Db z-9ak-!Kr^ivR{fI6T=W6SNa>F>jO8x;g{Z}%aa5`BdAaADJ0n47FRf_jTwwcN1d9{ z*>i1A>7oEc;n3Y)Y%co1go3&TkTtsx-(1_MxSwH4^xcK`m^P!g(B7q}?6>%Lem?*& zuJB!(M;atTP^`l>uh+3{a6dqZ=LJjt_njVc1Z9Sl9bSqt~ z4qDVx1QL%6U?L>)* z=s>!9eZ(7 z<|`OpT$iq|J1UyHj7e|OqTW#r%KA$VhJUDrQnyEfCyelP>C(1oHh-&2pQ52rsY*q0S2U2j;)q75jp)wJLxLAvU-ia}MgeGmlvrfx=IW=#owt_sqlDMw$-m*%z zZeNArJ|9*sF%L6IlP;Z9wC7)t@s}dRJ&s8GO@S5Mt{~5)p%4w3#Om42-LBcO$@_OC zqpen*_7Z^JWWR4Gkq3L5>F*YxPHEz?CYij-i|)SDQt4H;W!;5}+1q;lRYFF?zUhTm z%Y#)X?8_Q~2{xQDMPAX$){OChV>as4WT!$nc(uVomSd~%@hd9@(-L{zew{R z1E_Jan5*x*q72m(nmh|~U7}jJJg1oND!FGHCbM4p*JUfUo6)@#oKv3&H)K`LDr(Zf z=X|;{4V)5?S~yLSqe@a31l?6bUb`_6FqOFar-r6e(TYF$jzzx{1=ci~aOltq7 z;h_&#^e)ppzlgqz&&7JvwnGKqlgqrcwptY~3Nkjw=4&&$iWIGVvCTC+kidzlb>v`juA)ek;q9Cg=>}KX!Sl|C)D@r9Gux= zxd>G}hH?|yuzpdyUI!kAU#{6m{9gnF;0XQn>ma=B7NRE0$ANXWWW4tAOGCJH7yL+ru7d^=iHpp8wD<=}2H%t?~9nOrq z#A1`uWg)!CaAQ8uI+!|66j`94Xn<$M#K)8_7ONUg(@^cPUX-T=<$)~Cc?-iz)ckZx z1tA_WaNHUJ&lqA@t#UcZhr`a3ZM<>Jm7mD|GX3wcTw86%r7m}(GH>n;W5g(7%Y&2#O3mNGsz^T9S=v%orQeStmF}gr z0sDl+w`eUZEPk3|vNqJJOn9XZJT`o+`Ija7Tftw%LN(%4_iM@Uf!0y;H|#gP+kmJ* zzfLkQw$zK1x_i|)4=Wf=4f`c;rHw}$deB(}Dlqj6V)i1+5dj=6_J z2BRtA(fY~4TSJzlhXnSy+keqT^ouIE;x_kDNZPqgetJofvZ5Vy=9`u(d~}n{M3#pO zODzrKVvgW?b&81@C%|U=w#mZCuvc1dl%S_C!rk4lb0pGn(-GU`K1_QP9rS=0HEs>$d?7C9nhIF`4acG%P<@ ziFY^6v+Xsq81^CZ&TA5ca|}1T4dBk~*Io#=p6^aGvM#w@&v6>G-k2Pi3Df88oDS%3 zGfdUdt+i2pZ-5r-M(*rnfo#@lpI#p46k zK^?E=`_H|heY$o|`%sJuw`C!Cn#bb#)Uhw4$Fx zTk1i$xM7L`zh(cKIHe!LxA7Dy19OF>M=4MaJ_?55*}E@Rfu3CUPWso(_Vf9BdhP{@ zj0^5oYaMi4%FdO2E%uu}7A$yq=?(u>2{#gb2VT5ErGnKvrSoC;cc|AQ6LAgKoP$Jo z8J0-~Gb}*Hzr%sh6TnjZ=Qh%RPh1(q2yZ`%Zo8P*Y~;2$M1KJ4td?L4=^oawh33{_3#7$#6+)u$Nv)yGr^xuA%Ok#XcWXc=(-DXKqx>W_Vw%* zR`}FGc zWW}vtdhuktLS*{4O(Q(c0054P(9g#HOF|4vgmVkUu_L3!0dCR-EyZOd#ZuI>o;XgtK zyrx+|IAq**m{yn%Ff_y-MG;^tai4yf>$JtscS5)om1;Uz0uU2x=_$x+hkxDWEW2B~ zZ9304vxegM>voYMEq^jFSG@mwn@ZgK3DGUjgE2`gI?>M$w~qTQj7fSvQGfRv1*f`H z>}CsH+kHFZm_Qb=iP|R!B#^MY7pC7ZZn~^42>*V@MGXL~9`WaUW(773Z%3rXK)N;` zyGZ;*^H2J__5eRmlbpd5*#67GgTk|cnQDnbOwt8)v1$Bv3HoA5%|iGrZKA4oe2_-j zKc-;fFvS={vpu!;h0>}?1)h$FiE`5hP626)fgMk{s4LB==}{YpJ;Pr5-Li z+HF_mG}vTkrs&dJOnE8AfB(A;GekdeJl21`)}_$hxpQp7Vi^M)_Mu#gK@d{@mO*{l zBH=5)JML~YyTu0H*dNIJHx@B5w|9@@PcuK9^14tPj}Wr|#Qtr?Hb1EphT(k?R|6J- zE4;}j3d0HhPmez@=Sr20pfs-l01q=o_NktZcE|V&8qUx(18~HfA$j1yHg0S1Lg{0z zpn0(0GABOcHlo*C{_=u;1p+BONZ1DK++UbIVpQPQ&AqQzrLE}EXmJM>0i%H1coZ+1hsR4YqRSkHY-Y<9!I=ECZOu%=g^5DXk$^sORPGpN80C2lL zW3Tj@Ucg{TVKyGhGf=tP3apx_M02g%upZqi)yanNX<|f{%xlswh#EB6{hwZOw0>tX z;6#o&2tZn2f_l=gZStq<-@kj~X(|ePZgi^3X=wSs=nf!UyPRZm2;N~9aKHAO@$Sy5 zdNVvQ&*DBH9^Qn+KsI&?TH+YqH(+&_uVY-0bQpzHtyDNdp8BffOuIy0io1BM9jve3 zQ5FlKicFp)%V(A+yc|0{8qcZ=Y3(`RS-E4$7DE=BI^loFw-u#cTeP?9#i3aW&Hk9b z2x-lBrme6lU4ld0fs@H01%*zoaCcG8(n-Semt$R8pK6P*avVbcp{aj)B1Qo+QUWrH ziVlnz@r_*?YWw1EeRg;FVuqQo+5Q}s9qw*PG@!!W5-=w1v`>=SpkY6?vpXIg1x+V( ztkgbaDh#fXK-3p}bv(64x|JT4_RYVK)%E3*mb7_kh0Y=SXKA%rU{3CS#U=?O_#<+) zQIQv9pZ|UTJKEQ1biRwh^1y||eb{RvhQ!cHhSMNssjPOzb34~8mPAI3+T9|8Hy8z4 zlbV}8R+(uR?xGZX*v=SXXDk;^Svs6I!=zx_;js!Q`))(&k>LaA80XXFh)=rvghC1Kz{P~@-J;t&^1B$+ zy>qFSS7#>#rR+BTR(fmyqP>3v;rsnN08C<-7^Y<(Ph7SjiebUJe>(I8y2Jt%CK~d( z1fhj@_omCY32a^`>XUtedN@zERV2>=RD zAoV{m{pxw#pjv*L?Vz$!FR8n6Vj$Sabj?&UoK^J&jyF}(k{gqke|qkG-Yim)&_t$R z0xhXyotLynKwJfVRsW)I^byfPFTT5ZtR1he-qC`eAsO#^&R&bHC8;zG&KHh5gwd#F zgC`HXvfftet&ONwXxL7+}?>U z#yr?NmqzIJ>-kUJ8vlFUa%Iy^XG=fDTpx`@Ud}ui@*`}rgk;sHT1@R~b38n>27d*v zza3VoA1`vNadG?F0rH<$Y0%$(4rGDe&djh&)Q^7(wd|=0_^A{$7L|!Jlheo<){}$H zz0GKwmd~jc?`|0>?;b7IJs+7kaLIMOl(v5IRzMW+6!9JW141$_&u#FB%fV&F0vTQO_64W^ zzSu|F-bQSHjfV^fZLa0cWj85%EycVMu(-=jEs^VSpsW|#;ZJ*i`vuVc7pA5ElmIce z6$7Af|8!14BG*wXL}q90%M6@M-!!EZUNmgLheP4BT~c)Ln`KN2!D4UwLEucG&fbZR zv|R60)1+t4BHLI{%d4aK{W*4<%XNkyfMp!_<`tX2HGrg1=;xl7xBg){FJ(6$yq*to zvbpURANe3OLt?%E7%uTIr#k+L=+B2l1HS$!xcXj?heqPKpqHD<5<(4fR7je~$JGgMgW6VF@gw2%+ofG*>|HH*2% zL*@&lTh3A`fSBQ4d>hq)*|>|gk4zWjZK%Ki#(%Ut{L^@eVVKAWz|Lx(j{qr;a3n9ZCk#+z-SC8gBNGTp~$cO!t#w{byuGlcK1c$u^roLczJU>DXO>g1e_Wz*s1#5cX0i3`cQ|o8VCKO?e4*AxcNur1pb38jPV>btBn}C%`8AE058S)1Q>|5suLcOTwm$ zsG56pE7?xp+_1+jT9S?&)?qwFX8ug6O!MRc@s*fA58C~PC?!zm{TVKn!>Fvjwe1d6 zon+@K%Vcw`-xzg2_?&$)zTtQCy^w?6FU0rw`p9 z-b&m~DSN_^&#qine*o04p3RShep}23jh{arChYJPr#SOIocVZhhu7y@oq7p+(I6MU zBlOWfo5NS_2jJ!1eSasY>(T%r=MqlzlD!+xc9wV`eATz$Zl=_Cyqc}b_3mA`wmpAL zc$x#R(HGRM{R)+dn7FBD5*#q(_y^}YBkB0X&Q59zu=7wiL4p};rtjJxCp#D@B4-`i z*sqi3R&DAr%2<{Hx7%J^EswISz0xT{G!q^7KH95_9-!ebaPcP6XHJ-?*s5t(~VvrP&PEL?iz1 zeXiQZ#Hsx*H{0xQVTdCNThkSB*%Br5dk^&Xe*h?{a%@zIT(*qlt}Z8VMzSrxEzgX^ z?Cx(+>0ePz;bh!7Y`)PJe{=CHrk|qDXoSj%sg5e$kL^nAb2f;!H35EHM1^tPHsD|A zTY8v{ag&2uVNtCuMC5S8AnD(SF17{2%c#1l%_1#MpxV`?wlO#Kl6-=k23R^5Z64@d#a2vDWPvY zwSYL+p7+W>(1>EqI{@*y*DdMdKUlK~cG0FUY4F^=Ad(wn3uRT3f3)xwAXmmh_w& zCfyemVapgY{pA{+`x%acH0RFV;yEX_hiG!rm)XWw8)cr?M*W8qogsT~*qVqQer5|e zd3(VjNdD+@Bu#fnR+C;i8@E-C?05(q{$4TC@kXZm`1QzUvUix>)m?d!pN(N4wI znYM9b-@R9J#?qBaEzVt`vq3UZ&JVBXE&b*_>A~_W4 zux@r5F}_pFG+p8Sdf^n|_oCf#j^*)t{Y`hp*diU;!L|`L+=6#yCXw`XbtmMCu(Yl9 zZ!v_VH93Y*jqOks%H{|$Q@bdLrUgv-!_^wtA>xSjLeRgOR*kOy+@w_gQL^yD>;tD_ zWwPdzm6OTLCv#`b5>H@4`kx8I?Xy~~W*L@bow_b!p|a@Jr2P-(w9C&Tml_CR8Ygz^r~7bfX8EQf;ky<<~gQW#XJ~RdE;3W;!KZl2}!2~ z8ayuhr@yRg)ZchE_XkX;YtM) znMq|jn`LU7=j9=mA%;#hA{;g83m>YZlb#Yi^qYSK+KSs6Ym=BmEPC#XcIqNqwfhns z8=;ks2I4oi3;N_igL#2#0e{rBl7H=a`irp`o!?mi;&$N%@7jb`8^Xzg-Hy=>z{e$j zFSYOffs)rK{Cy2DBwdJP2MBvnzIwVrZxWJKd&I@?#$yll%j@m{R~A5{+Oc3@g%PwC z8R4fz5EaG^xU1xhl{Q8HzFng7d3{ip1mX(B@1_cWSL>ht?Rc92NvM-+Ji@=3>(yx) zx+fgr0RFNE)2H5M8%Hk%j5kD%Zd^4q7zU0As89-QlXdRzWQ$%)&M9J?OAP-2Ag1#Y z-41315`SxvitL7Qz;-F;Aw?`M-dAUhFKo^Me|*pFPXk0`Bp!+79`V3@?{emM@9mk` z#u;HZ71pxRu9Ax8^j+XO;8yG+0NxHH!R)Hb>*#OLd{|3?T^LoLMG9WZm3+HerrDjUGhsN|A zt~bFo9e=MG#sBf8!+Xu$=j(z6Qz(4xN-su+5Zhxtj=#5!zlZX_a?D8DVcZtV!fLF3 z9s^QKT_zT3Pk<=Qd!7zClh-Jn;7-f{By@oX4~m#(iRUN+=EN&XZXtW>QZ+{9_lHaB z%*O&OemWKa0MyUoCkQL55<}80Uc}Y?n1ReJ7EkN{hbnsztIb)am)>d{z;Z$smI5Em zS=zFjFS||wfcv-)N^ZSgmXld8pTYT{(fP)@VA+O_){lRKL~{F0W4Ct&Jc&Znpr9`? zM~#>hAg*x=BQ7B#Bi}VT--d41hh|iQRyUJ z857bo@bd{gCwlSZr6l5(CmQ1RC(?s^mknwOixd%hGGs3r&`SGQHn3RP)#~&JV_8k7 zy32vnOpsZl+~}`k;RW0W$@9`?a^P8~giAY-T6xSb(AWAY)<7p#Ypt=eAbm)=sy4fA za_s<%)aS^YE8+Q`qxZqn8YFf0S~tR(*_hCT zNq5$h24r*`-QypYyf@U-x`->>V2g-=z3nN7ZMr*tlqR9`sx5F!llhucEhS8bBTeG8 zUN`?jc&VT?dIJAyq`7g9+b$sPI`moz{`9#mCF&QtVN--)i* zR8SD^pbz52FMbqDi(GDz@&3LPlGSP-sa7`rf@Xu2A-+t^hYin)KAkCxu{8U_c-x(E z6^}9&=Ul%>3VOQ*7s3t%i@Aa3K@MB5bmu#t8uLh=(jqZqR7W%*?wqCZT<0OvT)bKmGs}LsQl3Fh z#znA8Gt&Y^#$|whqpT`h37iycL`U^8ym%U0mAh!%+3Y3=NtKL-{u4Vtna$c(-^ErR zX=CsfT|MSom}`=*48_6>7HIRnM;%)=O}-~#0!zAW;-Y<&URwT>_=c#5k#E6EM5J0L z`ehR@Ug{Wq=}6u%yF{a!+p7-^`1+-u9&)Oj9j`Jp65bn~D!w95MQ{wn>Iz`57Ku%e zw3|xA5>9AL@2vg0ZQVy>gmX{Zlvphn+=vy=R4zvt*Z{(|Pu=79lz(F*LZC|OcSb+` zu(pktI_b(m5lW$Fg2;nFmaAWPuk_wO3_-_JmWAz5Hy3APtf&DQlIT*ok(L7O`Op3|O z`JN zTqBqh5T*%3@`)Z)7XG9c$3%*&RMX_vZBLp)m8x91?lzm0OX5a*R0WbB1@%HRzpru<4+l z-3sPFR>>N$>0=GVvE=Cev*fGrVLOdc=K6910dgdl3OCwO;W;9$iFpMzGZXCwr_tzu z95yu;j?m8VXb3b&18s=12>mLC|6R0rZn&IcAV}5SmCi3NkCq#i{2_YvyZCiJCXl+S zI30gh63xcN7Ob73ahttI*Ei{N0TB{iF_t@Yw^ofZa@u*C9i^d=_sRRzonhtz*2HyM zTa-nLfh6nuv~^-FeQFY6U_e-&d<;o%RD_Rd-aUR1450%h6H_cQ1sUQ=%@8%{)`tf+ z&7CyW$OYxb2@a@i*K4&San5ytNQW)CKqx06L6=s4GEhBV65m@elYh0+v`B6&2(HS{ z(v0juRKbr!4+hVYK_SjgeRiTdfKaR_sbzz@!%Wfq1kf=@Zw3*+PglL${$h0?Vp$uDr*m2r+1zb6mznPH_t0HOq#P6PQS9& zL{k~g2`6st=dYp9)uz<_{1K1abdr6*Viq^g7ks^FB-z9HM=_k-=h4?4qO<=}1 zlI~%b1>B!RnN`cm>jxviZe-q%a_A0EmtV~vgQN6lqdUS~#G{WD$ z494>EM2OWOZrJ%qGRR*=L(BL(SVP$B?NXTu%iaq5Pv?7R5{eYd)2G?9*w;M_BD3~! z360*IzW++gbkj{bg^{EhOzc!^atg|HdXi{_B77gA^vjWlG4OAb6;L#y!?BIJ%xHn ziB<`XsgX$#H_8h|C3O0yA+n!~!s|P7HhI2;ma4ANehf#O9DBh#Ov99~C=6UF_^EjX)j- zN>vR#-c(lpXP*lw8mL~+D^`7kDzbovHl=H1JQv*w;@&Z9GgD6M&S_`y%2uGGt6nL{ zZiage?d418z8-L@l{AsiUy9Hzkfh=7Lz6>)cGisvMEqaLK)ijvl%{O-IAS)U_!hb) z1bbs)9f#|#AMfY#Do2d1ig046e~dmUNHIGJ{ed_m2ZiWK>#45MlRTMbX{PbnS&nUz zeBB|I#F^aaMLGtT`}@qg@`_pmOJCH;Y$`W_bmJN7=ww3c+>VW->Zcz}=$DjirXSjW znGYZ5+SUPj^*Mfo9Qs;Dg_KK9gfbc2jz2$kJwS^^_VF3FPD7 z+viU|t$tJ-lj&tG`{9~W&A6^MN6S4O>$^nZdI~jdPYm^2%`0szLHLh#%;j8qH2vqLHb> z=z9<0T~vq+V{v(hHC8c5@Gkc3LvxUpTu&NW6%}EO4HQFLnO0UAD40*>Z1$3cyW7TA zTgRe**F@(u`CFCGOA)WQZ|*doLpr}?(XKvP5~Uqe_vLc{mFL+)1xVR;_n_Z>q%_ z;zYYdEFxx|;v0dH&S;M)+D*aNiRum5FJ>;t0_!btQo;)Gtt90o=MJ4mghF!V_$N~C z$JQALcfuX&u!&3AM&6>$0R?hYq(8P?zv^|_jwLApNGqf z4cEt$0i~p_%dc`Q6BA296EaczY?$#BQ%o`1FHUQxu0nTK~W%`|bZ zFP{ewC{$DzF-v0R(Iy)5qtjOx3JozCB_CAH+(o|{2;E*psgZI)9}i_*0p3KuQ> zvap4pveNGTLIAyRF@>Ep@5A1h@ESq&x{wW=d71^^l0n!Yeqy?Nor}~w)q}B&e>EIi zm`+((vX);!Oq_tn)f20CRII#?aCUrB#D-(fINx#rBawNW*;$F|Y za0SXGGV^w&NK*cl1>mdTa>276O<+}@SF!G}ve(X0=H#lohSgC)6&FUB(JSjv2U!Nm zFckfsIaGb^hxnAQdB@ozOJjU6TiB|B^!Q2M?5Y8DFtYHYATyW{uIsGc+4SOCSN_ z^)^0vb7)*&N(jg*^+9nq=Z}-#6wGGT zM=cZ*SM-teJZKYFWQy#x(O4z*1374$*T3pWRqCi`d9To^!MO;`sh4sO7GxJ*W32rw zRLqV299d75?pO|RFWiV#seHh%X-)Jf25 zTV*A>r_>r`ZD>tSl~y1;WRWji-ilFA&l`=3Ra4fJM6Ffe!4P)epha1Gp++w=?VukS zDfuvXwR%IRtj!TRUI*pBf0>nksFT3AH5}0uoYeH)IwHbhG*&peGc0+@shD!A+n&7C z6NkO4Gi>E62&_AkI7;S<@+AANQB^!xJy-A{)@qba^m^hW13E&4?Z9g-3QYo8*HKvm zUX+jDusV8$F7%|PQ((@ExGXlj50|BG&K=M|$DkOTc%{?vwBN|_9(&e|i?T*fUY^oN z^;O0sE{d%QG|_69%QL84~OzsU*@k$J6>X*T50a|plVATy*uWMv87|=z^9)X z-^s@kEWu9RbM)Yjtgi`DjL%EVdM2ffU#_Jssm3Cm)z?ce@%epn+*TBSCR9M|v!tC& zYXtVQ1;hfA%-giJoV8Q+NG**Yt0B;x%Yq?GeoL0sq1R2_XC?Ntbt5Xaw4S! zO^!a3+6%fknbbo)V`af6H{RJof1v6@)V<)qGtB}0GCGTr1pxwSVg_Vm3T|R2i(V^T z8#9{&D_S`sbeY=3?5Ei;HAx32Qx z)x)aib>@Rn1gYwD+(gX1>|Im$=;jo%(q)3=Y7}eG8g?ja>E&tF3iHSkCmeC|-Vcky?J$Md2a6vJxXwl0 zC+f-2r_o&Vls4`90pKcLtyW&^WKMLK!@PM{f`OOj5AM-mI$exje{43Ocg-A0miMA- zEn4O2Y-2eiM;$wns}F{0b$zsFAbp8^B5i>r3U9G$_7iNjxHvgXGH2I3>6VhvY1(Is zo;@G0!Mwt#MI-q43YEI;adC0Q6L-ys4PBQ+9+X{VK;-FSn-+Kp)I#j!TVB|iS$7@~ zax9M7dcT#YG*gsQwfnA3JJLRE^{RxRJq>JH#YFj9hyKGQ+byYL18YMm$CBpm@F{c7 z0*HvEY;XUNpp|m1rU%GK_uT$cY2CilVXg=>Z=_ytq=1~pylI&VOVyjG0S%H*YwIy8 zuPG@RuhPIU={9fD4bsq?5LogBq9<<=T+wf!xlV7rujMkCapu=}5-h549C*a?NLV+B z#w!7+W$Ev_(Zq)UQWT&&<+2hdmL1?SRSOp4R|khb>^eC+UXeIXn9XMR^=Bn%7?yfa*4(l z(4Y(52dT6WZlBqC5FPF8C^uGwVtABcVU)rm%}tL{Uk2l&besmp-1`%$eEnDT#S&`- zmZbH%oYy3pZD3so(6q2p_6vr?)@YItD|qEFqb z(uTKtrg`f`9L&$&FaD}o{t=64u2B5-({6kHqP6!)_!Lt4c^U?fcP#3(+}F(1*t5R$`|-HP`In6)Kv{rG6zDj=v!Y(}ekqE~Y!iQ7hd(;7^mGM=c7% zE?2@M!%5H>A3kzQHj=AM78VTya(H-nke)4-YTS#b__#Ywz0~frT=jiCxg1Rxn5b+@-3;@PLh~N8 z`~8eG>-sxkFINj%j?82h{~u9r85LI#whL1z?pBJoXmKg7#Ri8WgS!=*fx(@Y7PsP7 z+y{4u7MJ2KgA8tiyY%CEzxSN;Yp<-GWF=R2vUA&Y7oID$@(#9135zGcMBj+M#VEVJglEdMJ<73|5)}eS?lGH zCvs#G2$>FF%PBOlWCJNW8e7kh@S8fM`-OCBm2*aXsGlnN+#YH8sq7~PwCF>;23vho z($86{+{!6!UO-wB0V#MC&faLnRENNTu@I6Lv2eqPIY`CPJ_hwcH6%Hntp&^V?R(zB z6kvR7+<%HJUJu16=+KMot6N!4i;zVz36HA=;W5@4Y|nNx``Akdt8FK`m`z(?WoW#~ z#QptA_Hn^%#;3ktKGS_}0qj=m*EaeojZBzM>eyLOUkh7n6F?(0Qs7M4Un*e_v~a5(G_WB_dXPA8Tk`za=4sDu&+I4WzTH zwF9w33lmE~7KzDoEbj-TEY?WlTa}L{k0!5!g)A1-;x(xn06SF7+6aFBF>MogR?k7Qs7-|gdt{qK?KCBHl z+W>hfL#9z2pHY%}=ULL6Pj5o`-UlqnhN+y5AnH5-06xGZ2UX{$=9oKZyuo^z zZqA7k>7DJe&Y%$~l4H2Aa+3M*(XMgQusu(>@P+XTzmlWC#I)r%{ywf@k(F(dd3b%a zAj@gYG9qJ)j&()=!0uaGY!d;mzp!p+J!*a3^cAj%z6T@lsALH@xXJ5HjnP?Q-^+hT z?LG^LHgsOOrSnV9#?70Z67MsZf`>B7Gfu<5&CboKxnBKkaPp(3GHxfz z>yS^1F2bz&^FB(J<8qrOBx?11b##m#%g&ko>q7%TU>Qnxp|72qLrh!>|7envYvQ?` zSY*R)(Z|T4iBDl7mJ*I7A~TcmL)CB&zKz<187sl#B~DVZ539O)gt`23`CmCv3oB|d ze%rM;--UAR%5#D>YMc#@7|Kou>yvL~3^_K8^RR%&r#zLk56jCr3p;I>A(UI%X|^M^ z4`Olb5tsS`*BMa(vcW~lSlHBkdiZ8}3KZJfGcIs`Nv|P?L{JvN4c3F#)U@LHo&cyx&#% z#aD1vk~{R}9}+X)fk-{HtdcMEsr+tgb5JSfgY1oKo-7}6VYD#EE(rsgWP^wU?mp(( z(xa<=$_~DhWu*+@yLT;BHP0%?fEkJC0h`(4N0y;{HL+=)nDt?u{c-xw0d7sbq;Gz^ z(Mgpho}pF!TJX>{xTy3S^O%sLpz^31BUcIsrHqcIKB(%YaaK;B}mK1U{XZ`G6s=&A`t}IkfCsNp5UbhkR)7rdBHwy z4tp6WdiAq891ABcaggBat!rpz z$q9Yk@4cBL!@Bz@;;0Di^0%8$-~Z4R%*)Grh#Ee24u9>Yw*BMaK*#{N0K<<~j9*5+ zn!G9m0)gcR)A|J}4iq?{bK<#Q^O!6JtO^Rec%oNj>cJKt_}`1(>$@%Sp8w2GyaF0&##ffEme)m`RxFli7$t5gTY2!MFMi zhyzFsgw`qXaMh&f+Bboq(@rWV#y3=fbDO2rlRVq`4RFB7tCVG&q7PKE9v0D@FE$IE zbCC-%G_TbrN#gP-vfu;9*>(((k6F6VMIP)~!jOy$N@Dm>MyepIu3OlIJ>(UMb;bR3tV-QAb@=?71wP^o>eWT#QckgY=Q$bbBip^e5PH7 zb{={K|M?NXqXYSVQ@4-9#4$l$rgCZtn4DZA9am@vQHmLAB~qCrLEYbC>Kg2vA8J55 z;^sS@8qMB<{{F9}&Q#5`Q^RmNj~@6VUUN`3rK+AHF(;Fz=W$Pk0MY=&DJuraZ zFy9J81nWd8`4@@3ZMz0p!EE+}#I=w(x(=3QP?4B8t@zh^r667!U8NrwCFCS!R(SR` zq(#cA-&%pK42dm^WACOb^1~EV6Xz1=Va_Ut$g_z}VZ7;zBHq8Pn+ho}NAN^tK$;pG zHyFzs1Ih7=zBVl@N`C}<(eMDRQgNjc!%ZTu?W8Ykrb9j`l-5{rSNImC7Yc5?`B-Zd z4vy)b3DnH=wO;|hn~rIB5(b$YRbkP<8(GWT6OAzmLbi0~SyC9}nZXwr!Uy&%15!-K zUUvNxheMhMI^!_HvpLj`JLCmy^Lz-0P6kW(Y_vQMG1J6$iMCX=DAaX4ljvw8R|Up2oCW<@+2ebYHZi(?Pk6FeV4W0*3c1Kw5cbp z5+02|Sk+YBF+@=HlPEnPB7Q`h)ZaS+hX#Lu0XY-^7St;(->1S?dWg|M5XtR4Lw z;)P7A#4}=nXu^&!sMNL&x}Z5zPl`vLlU_osotq2qK!+WJD{iBFtYEjL1YVKdnk9M# zt3^map4X^D@|CyZb>l;%LkuqyQVzb#Knvj(Mdi2c+M0y@dMuaDV3{krqqDBw4pS+hf+>9 zMh`3CP1jK4f+Q@?+YXvYr}KgiG`=D41u3icdk?#LP}A82eJoT&J<#J~6q*bvd0juF zs}=^tZH}e(K(|{!G(GZ;kfra%Y!gcDw=3Q$y0r3dHPGQO6q;CH7&;@;F0(+?HZp!q zx_c?fg3-dO#OT{5+pe9=r?O{JBMMk0d{y;{OpE|zJB~`N29T%MByW`psKya27j`}G zyO+8%qMH9=S1nK(dWF_UN~WBkfUc7*d}lr&$HBnM`8_Ac-HAb9zFWRLi$~w?6_6+KxtKIvLkeP|LRsx!^DJu{?0o8?n!pqY}U zK`RC=C96JApgjqeXFioGd z=iFF0EFCALZ!E>D9T`z`(^8R1oOb#5bGH^l&&Va!<>D2~I72WZeaS-)HWqIl_ycgs z*_mYM@6+0{Rv>9oS$3g?9V*{_(3PUNNjcea&u@1zJ9s0mQaS(1MUY{H)b4^dX-%t$ zE7$E3I=fq1mPR6B(;?ba{Pf}B}FS9V8l*pt>^sCsViEauL9UI~Lb{qR=<7bQ>rhR_Y8d>v#N@eX2 zK`Ew66`dVMy1aa$hqKdjMIE2cVeR!`WBtD`-~2h%%}Y@LPNL#-83 zj&^VD*y3lg-W5(ymFZ^sG2GAm?;zi4=H-?hOn=l%vGP)!qp@lt`uz82P;rM3`Y1L6 z>H?=ulB}B>-}5(okV`srou=g%-ZHt02&)0BY%pLYI<1>!M2Ol>yA;sVxzaEmb7{K+ zZ4UQ=P4lH)kpI97=nyJ7;wp? z-QH^HVR_p{HbfNw@@BH*CX)XrW- zYHms>`byz*|0b?wwpM5A?R4oKKcOoPA|lQ=g6mX>B@O7zG4;Xk?+w5E<-zjdOjq+1 zZI!O1N%|Gah{tKcS@hn@6Gi=9_xp{z z=Ot*(x}xsrxvt`S#du?aQb|cew8`bgYPee0`AnenrF1!y>&p)A`d#r4$x~~9h?U-N zAffwkf3|MEG!Rmt{vVS32l&bV7fJgwF1F_i8Qc>u#y_Jcz~bH)ER#=KO7}w#{-^2w z{%rBzP9lGM+K(og%hS&|ENhO@OSE>pKwe^X268+(Zy*8Cb&{DX!grX)%hX*r=`L@Z z-oa5@FFPmmRTHKEcRTka7&WQ(d<%u9AS*A(0&WYAH@CW}I{nbsaA{P~Jb2E4&O0qd z-Kgwr>`&2fKg)&S3qG73pDz;EIBoON^s3o6>cDEyyj76f6_`x#i5()3rB{V++fU1_ z-;}*=6pKtup{9}jx?^BV-#7%uE-uu`COu6!obX=0M094Knj@6C9YeYu1U?L6oQP80 zGhk)#oy3V*RNcHB?c=b<48yqzjb~0jn_Df0qu0UN#l)x*}J4X_aJkakK6QfiqN6-(viIagkZt zH2a`XpT}nUVI~|DB(fo7U|5aoid=+8TcSCQp->N?OR#n-DG&>9hNL&F%cqj^b3gH> zx#JLW8Y)SiYMjYx>TT2{x2KPX#iOx*N9Xqg>gAtLD~D33XKk-R_8MAh)%U_ahit#j zCsk0XQ74R(zp`EV6s>lLJ#hQ38LmP8CL^NhO&ByOsSx<$!^y^`1Z|~**ES^0vl*sn zIQO@lXtu&H5eCCk(8`j{a9Jw@FzbqeHRQkQo*ZDKKvb-zkK>71^c#6X8PMx-KNh9P zTqfDJu=aY1&l0=y?jyOuOE-I~j>h(`7(FL+3EE{z5fPOn@&Y5$Xts|pZoVD9$7*Mf!hkD-h52*nj&*8%jBhQjJJ0Bn6&|!5IwRSPkd5Ev-vr4) zeftXUD$1TZ+B&rZ1?7r8*)E$hyGTng!={IbB*N7^TaJHwCds~bQ7B^jhcwrLrtpg6 z$}5;8nL*pWQtj9g9WrVs$|1QfApn0Yvj}t^NXc91O1W1q2#!QbQh=^yjk}1o=^+Zw zt~X*e%U5%zBfsr6i#Hz-Q{|Kv|BZ9RX|`)7YfaM=Cg!Q0^7Miyun+*}Ic(L9~7fW&8uy=Y4 zM#X!GF}5aZu|}Aw5&!Xs#GCasuEI^gGUJLyhAz$2j=qP`NkDw1p|7~)x_IB0t9wAk z<#Wlc8^tktxau({b_jpc-t!qvpU2OE%WXul0VlWqvyb>eSh$Y4DojvXmBS*#E$v3& z@_AReD&ZfJ$@y$T2O{~gXB#dWId`CrU-UY7+S@k{G+D56)I>Vqp0@vdh98cIql0ly zZJt)l{X=qY>3{a=wjOTCE8xr9OZDBNv(|G;oaOpfskRm~SvVQUn|Th5M2Kkhle6@1 z9$66WkWI%31?Go2Cs$BV_jihnJ{>$ge>Vd6aGX9#M?4NmPU_NV503Z56+{x3FI3bh zIUa6Tj2P|tQM-6&jOJOFu6=ELl6XVTY+3b9L76mtlK0?f6|aT62PCvPdCR#DIzvrb z7X2wCvHiX*7E>V@E%y|*s`YV0Dd+gI8;LQ9+E(F zW}jjoFl3SGQC5XzWG){{eiv`Bo;EBvVz*S(v(eUG^rbrqbx)f4W6ZkD*V7_6oRYW^ zQhPe{kRg~w*=$Juo%F8OczwBq*W#0pL9@Z8c&HbrGD!AIy;A4mmH~CkLc#KJGMKvA zXz67PDz)LRo6Q94;yNaj*{(KMJ+8;m|2ug+ZJM{OLvd~!qESqe9?|)9U&m#?Z`VSh z<;cy~k?R4zHo{9r^PK;X4qtv;S&JPySAQiWO#jvg_W27PKCQ{W5w4xh`65m%w${GZ zHDQ0SUD_sFhMRl{dK8Qbr>r?k0Y3uFbU0Ha?@xjQ7p$xCpWi{EmjVY!r`k>_UUpJf z=y>EA9(}&^<~)F-b&ioA#6v(H3`rB=Pi6T1~1v>Dtdk3J1P>8UIKK++4g^Xfsv(;>_4j z-7krES`hFqk}V{UpElB|$v1Ldjl>%4C)4LA2Z{FlWf!pC=J^;(qNjGgectV1@hFYw z@XK5HmhcwOFMRY=%q+r4+_zP{mnz`*$H0D%zS`5OCsG9xOGru7;jltG7^@r|?2sO9YA zD~hLwGMZn`JCf57BOaZO^pwPQkk`(>^FzAHWl3>;Yek^lKxaoLkKMgvrIR?7ZtV9x z@&VZ{-J6V?dtAuc{mDjl=&SVTwtMKEuIOm@*4+Q%t^V{6DY9$fDEsRE1?zT>7ZV#* z{cg-{qp4$;xQHw#>NB)c7h^2J86NYp#FnHQhF>TM1c~HA!{viFlDeXr+n!=WyC%v` z$N!uds`r?-wFVBY1Rhr6AmAqNniiRr;Scp6gZom1e{#^y>JG27aH+JyB)9${;r~Ng z5c>ZcSFD}WhK-BO{P5m2-t207RDOuh4$$^x5a@bEVaM-beYqkl*Q`pXTbU4&WQr34HTo}7Yhg{~`6xcNTpUz4f&J`ZVl>y$oxFIFSX`?Ei+Wx;!pd1fFwI zG^(Ca#|XcW6%hQa+DM;i94$2npd|8mSO(0(uh}TSdVRpSO*lgh9G|CpCEVj-sGU(C z^E%4;giQTT;uR0g`%RspPWqYw$vp*yiWNzsW$~l?70;W%@Ic6|!%gm&43}m-PER|s z>|Uq44lfhYDXy;Y*KF=7&y?TzzEkgO-X8x}qzwmU-C~EYy*wVMW2{%a2!uU`ALaic z{aB~H=H&T@Wc@T*KQx;v0Zxl?r7gMJvPTdO(z+IOH5ZGLQTRkE6l*qh!A!bBSX}%6=olcWlo2n%fWGB>g(pl#rG-Ai>vd!DW;KQ zO=o^Cp}i?=D#LJxOSZ^IbI(W*&mWwV6}%jRvrQ&sk?a)}tG-Pv_W(E^6~+l93XOs# zv-YH)tRLK`;|mMnuW#<0rQ#xEAyZ6#=8E}zo3~+~{szHmmJ1WA$?EH#Z%!WZhqyoE z&MkLeEH=WLgABD!Xj|pg)63VKCg2+lMrDdEy(&z#aYVBCEmNj$5yr&*-KK)7r98y3 zuih}=u+tX3h@jbfex5ZmCTJ~^t00fPZHnDRU*HbAjoIm=?K$f_D&ydm-VH3*L$JPn z`Om3BvbP;5gqF0W5m!B&f@e{b-RY~Q%s(VToeWnzd4)!Acc&0c_y68Hy)5Q$4MR|E zhQe6+*pO`)n@t4RSTB}F4od47$JoY(Qt-BqRSHmB-Q9_AEDb9{OQsF*aKa(0YUyR#E> z)RVslIi&hotnm(^calwK|3msXk$8IKTR6^o`+ULu52+itRfirL3DS>s;HNVRN68-&kfQ!C81E;DaRzm4&T-f`Q#UhmcnY zo(mIoPRJ{;=qr$C_B$)tV8&9xZ5WrK&(F~=C`t4abR^$iVSDRmY#2VI=D!9Xrc7gX zzL3?;-rmU8Rx%sw3gW}aFAoGXCFS}c)V^~|lv#VN%wyQ~eV(|gMnlCZfX6wp>#Pj* zC5X`bh4o6aC*cp-l>4nk%f-r_rmF>SKn)P~zWU^)rZ*HvYFbCcGWmtiycBS?e@N$A zy1c1eXKh`5($rIL)bCh&!i97>p2CMiSbK-c(iGBk;MEvheNjI%H8c2KS$W_vo%m(t z&BBt#jLx#)XHG1*QFwd&udkafe@wpA2aUUm4me-U4BA+0jLWr2@2EVS<)D{C1=Ra)T~?vOv8n;lS2nKU=XmuIBwF|I9sw z3W1|X$^B8y+j-TKXUig`$LtOv{b zT!J7r;ZV0g8Z)7R=fyA7)k!wBcG17lufAP~-Qf!D3v0&m(_d&xZqInKRBN~>p136R zE0u*;*9&^!RGzyv)m4}HjZ4S?&eGeh6o!5lc(Nt8{A~XnlYu$4vWo!S9iXqet&$2i zfF8i%wn}}5%Iq_>FuGqR_fF&H>KR3g*DmOOzBU1rms`BbF8dw-kp8+2pFSOm&y;0) zashNn%FEF$Vgk<{wu9Cw73l)w)l8*wk4-@#sOJ?x~d~eE#;NamPw$_ z|CT2rN)1!wjOKJPph+!mz_BoBBDAb%yS##h3sLTqIDjr}u2_2Z>r}J9-38tR;|DrUk6XUjTFDtlUO9#v6951?r|DR1$w2y>;Jp zGH*}3ESh`~rj5AZ))PL#jmf=@FNAhf2hu~0mpr#(RBq(zQ)!u8767`u3HiQh`2bGM zZ-|{dleV~ls^yaF{b^AZT@mxe@Xud6Ev%s(MscXu!t;26Sav>qt8ceR zxAeH(|9uhNrHMFJon@W-U)r1U@p&lJfm(@0IucT}~R$9$8}L^Ueds z^`ECJcW60d?&@hNEkMB&!(h+LUwWly;1qv#(8BqYmzxp3UwQ*pltfcc>eLN~_|9Y( zf4fJ|p5^=#GvNmK346U$V!39E=6uh<-(}nId3w)C3iaM|Jm17N^UQ~1v(mbr| z&vp8Gql%s-rIjHa1+_r7*D2Rsc2uZ^dNEt^Q84ec>sO~hugT&ixJ=EPKP1h&N;$@yW+##EyrOPfkiqX{#hGH#JINneO(nxN(>h(Ez@m_Uhzj+Ew zVh4wB$IN%&gr6J)(~Kv}n3b)tz)5NzAA#K=={|LnCS{6vY993KMadlWv;()-Drz|R zBD5BmJplBpKxbe1TdCtR+Yr~ON6zE>9g>;x;9II}^AvBS*2Olg=kxp*RW8dJPfYhH zNkYxM74z=$I&sg)#jMuR4YJVp?Pu*V-;Bv&$!*~TA#(@k*a~olJf(a`;CyPUpIeW- zf8ZUKfgdhD+NL`rP7-r|-V$#uoXK`(CuI8j-)sx=Q{(~c`t#?_YN$`#JHlb`bb|5b zf?r^gmdY*d7taK9jaSb*>hZ}rZSNX`?I0U97+@I#Z&m}3sgF_8xsDBe3$=E_*+)f7 ze2HH|`l$Fw)rOLv5}qi3>ksLti{1==xigE=nJ6@PcO+5@e0QP>|1w} zYDc?PH%X<`yoCd-ws6}YKwEjKeF0_%q5*B%MDjp9GRjz3muYKhp&wVbZ?{~M#8|S; z8J_B~TI$xE6>>>w05+~t&)4Pjf%}+WLCC0PI z)HnExLcjQuY}PwA+pGDPUUkzcqG8Ql`-lh~l|v=on$vzSUM?a=UOvyxH+V=-x^b6V zRGa1PW0ghBQ2IQUYKF$!UVuWRug2gWEW880Na~2kGcukXpA=1PO|9$|a|Eni*-+#7 zjie(-grOG^Ax$dS?j8Z6;Z!)UdRy= zcak$`&Us?IyC+>rJ80AHMpDkx>Pq)7aGtcXsLSN{it|HMe%IV@6^GUI4{~4A)qN@w zkg(6Tk}ydi_Fy7*d7Ke{^@W}BKA&3>n^)KtD6YjgNHxbK{K!I?PNM2y+B2ACm(VcI z!6D31D%VG4!)DmFMevo`%?;tv@`05Su)>X>E~;eOt6Le#Wh^#*Ky%d8M#gY-$Hw*n zY7<%lCoz=PlqcrLb-fc7X!UHu2G|#U5nA%_>o2V!R-jNl$=$uUKW7=^9tg4wBvm!$ z@j#N&RM}Cmh9d>Eyl<)-4S!IIF%741%Mf}-$FJgNiOTjY_Ox;}MiB*=uDL2u&A5|a zCY`il{T8Mpu=^nU!(4Mpz|QSLYhp5?XHfDmK0T>s_4nG@lJ+?_SjrpS+X*Q_K{CK{DAYM9ZbkDkMa>Z~zS!a<$3O z$SYrRvicKu>9mpV4*=baF%z5)?;+rVGjI?J(PRqu*2r`iZ-0rOfoE*Yk$7kAgJ3bqG%O~8?8Hk8~Hsl4c8Un#qe z>HP!7_ysK%V{8sm_pimF_ zt_yjlMKq%HiCHFd;mR432}HnOK%eGFUla)mL2Bg4KP0TE#f3!N0s88Lk1D=)XTu*| zyUd_$89cqG1@TIbE5GIA7hOWK=&5ZkD1r^itqRWBh$Txv@PZOI!RW;o-bmELxYXw8 z55vn>Nqj3Z*6c@wqTkXqCzetz_mPD?uDzMGFij(5%=oB+B9bwD2KaTghjjw45xv^+ zBRNBYp(q`z_Ij0^#F#H>Uy4bc{X0@vI!S=4dfx1fij^DLsImx>g;-IRCF(vLT7!Q` ztl#m=1<5A2et?s1g_G1}2dTR|B7L>JGAEt*b_DdXKRxlu*ld!umgc(QYyey&u$0(e zzd;4RUvFZHf-U)?&oc_*vAUS%Ony%3d)s$4s>r8zHr=*;H6&>Jc0d*znx69aFahQx z7@{_%-91is^SQlcPK1pv`*_)7#GJEZR&5fl_`^LgaY~dhCmFzM8wK8{eYIXv>_k0A zA$oWRd=Qe;^d%)_s4-CZDrvw`urnhUqHy=*AISPey!sN&%IJ>OVU!?k6I-3LkHawQ zh>%$Wuf0;;SFwkdYtd)M;@GS;nOB|0pX3Uh@;_GSfT z?bitX*jX3Q80rP@K7AckeqR(B#4mzatl$;tQ&;>rV0Z~gD|l6$4u1PfKa7RyjzMtd zov|N>deCWzVtQHhL}b0S1Cv&$*4wQ~jaNu+#p>k=Mai|APCJ2{>tb4ayKY{3+|?e3 zyStBGMW^ea^rEtKnduMw^ZP}qZgxQ2DC{oDD*V%8*T`1m`QliC?f*Wa_`({Z`Dh@J z4I389_g7_PKa4{^reqh|lNi{YCYm>ygQYJ{6&gXtFDV>Qqus2_ZsN zqg?~;rKOoXr=RrIIgLp$K|zqlU56t%wcTGqu{PFIEQ#Dr@kqFWz$t;k92&)AvslbQ zCZHUZj93Cx=$pcbabN!+>>Mvychqrr_3T{JBt3OEFDT&W4h`4Ej$|v;wk+gmY&aq} zwb{jbA#k|cyr-8U>Ty>2gjoS5c3LY^mbw9tsk{8t7?0M_l90|gMcG^|n|>oOzm=OW zG?JMRP)|J@^O63$Jm11HrE`-Udwa-!kHJpJ^=tPPPyQzD3H~vpBr26ysCXKaqX&9= zMTNU|s*_DgE@+9uMHWYb2)CO!)m_`c0Ho}izu6Li7M!`;G|KPARWh%zPWZ3 z=TAd_f2{+XE89!$8G_%uoi+k2xJr=2ubz0fXz#yzCCa%%KiO?-$Vo$M2rc7d z@W5(_`j2aQ+aIa0@Ljdtg;EGRI{!i>WNd=vRm`b5JS70t#(iq=;qMyCsmI#OE{OW> zRpoihz-~d47Thypmkdp;k9^E?wB3cN?Tb830y6KQRMX^kJK5g)v8l5Hm4HZNa(y<} z!D69kZBM#wi*AUko=lo^ddWurVJ6AhS5A_64^QJdO1+$&IOv;>dEy3vm4r2VT_R0R zWRT1NAFNCiHO;J4U|LPf8eXvMc6_kY%GZ zzw>75{Zxzd{!K&PwnXmuDTc%%QfcdAvC*aUk~)t9ofC)OH0_Tw^ikEfmbKH#J8PZbx#lbJkO-tVH(7s+>#k6il3WpUW^DqVbA*<_#NAy@hrZ&rKSd5mc<1h9b)A1taj#Z(3Tim@2ng)LltKKQjn#qvfs9i?e%@kdk(4uH<+pJlR!C|yz$T&4wlf-x*D`t5a}y> zL5&o`NxM|PH-HgvM6}ykgf#C);s<|eXq%jm@KY&QW(i_7jPu1rHO8MClBJ%~&$&hNVrCHtG} z+;Kx>HI)oo1-%#H-^}Bdo&vFd_y$@VGhdz=n_@O=^zTz;DCsSCF=BN8MqZ*hUUW4m z5^u-Nt87~lXW2co!YV$GTEB* z!Y5AcJduH|pCcO*nI!It7GcoBu-lrRG_~WV(Yw%>9`!;-EL6Qywsd4kIO`DKN9bPv zUZGoj)3G@lH^#4Ui)FYqrh(?eomzxFlQ}c6N$`8wfug4h#9@v0bq*m- zuW6wUBNwcy>_6nwi+hM`2%rv}qR2s7AG(nvkXB$&N9&>LdNvjd;%=}T5VCNSC%EoD z-HMNoS%tI$ZS4`R^J&YcCPCY0#8HC?CrN40+r0HI*Y86u50DA%)Ei!(#T zJLt*nP-mIugK{<|psnB!&9fjZPZ7~*!_~p%uwo&8@xJBUV$NAfJ9(usQlUF2baCr% z3s$LcNm2CJ{=mIe$dFZZA34XVOx^MzU~8SE1{1&9w!yxM?cJsst@wUxlnWGuT#ALqWf5fNm>N;jPeCHCn}1&)m}d ztXsN%2r0w2uz2`4#{fp4l9k7Sw~$N2P|>EJ=DBFueqafytPt*UvG>B7`B%X_lB(YA zJf@-k-GHHtaQu|&A!UuaWov!a9*9G|maK&b@#<%SH*46gy;;t6enq3#0xIKH3zXxF zmLovR*OPE8FCIbsyvEKAf;_Idil;*+OR!D1~y?qJW``334NO;5bsMf3~SuDF< zffKtPH&NIb9D={sdefjK?xRhA!6#qL2dBEn0;ZS48-es}rSK-ju9Tzn4`qxS?Tes} zY*Z?C!srKq*m-6`7$`Gwn4Qyn@Y$F;9le0Rc3MNQvYZA++X7&3-{$9H1zXUgpQue?UKSC>^-i|DC_P-b5sM=e_@Q@> zltDde!>i`=#EcpjC8n0v$gBG3+69~0a+5^&w;6TNUn^3{}xm z8%}KAAZ*5=2?Eunw$S%vz8El4zNrkJCXK04w(6QD&7*_V;MJZx(YGc}o$pY%mRq$# z`0<)nHqDQZ_HR$oeNliP>Sncgrn6B8pXI9$%!1^}6IT&R{C>%ZM_$BSbl2Yl?BVByNW87n7yR^^k zK6%HHP-`lEBh-3h66b%h)rh_lROZ35>ZhBxG}!U(VgKoM6BwHRxs2BKw8Ygly%>~zN0v`={CmG;ud#A2^P(ln z{i{jz2z#uzZ)L~(hy8Pt82{;=GTZ~&9U$#0`A!GjL-wfLJhtQ0pFw-*KcxMEAxHJj z8Xt|*g|98O6`t5%vKeb6?)&xuQ6^E-f+$5I6%`G|eh5oyGqQY_5&Bh=!xvy~b$&mD z0clBB9VS6mCO`czpA~adVyOZ|3j(}99AFFqjDU59GVs@b>>;fIRSWWLa1SO@^+v9Q z1c5}ga}8C>74D>Z2a95)<|0*wG1t}7@XZV_Xh=LyfZR*W?5pE5LwQT>`<^IJGn?h4 zPXf1SxvR;~r^`DodHDy)bm;BL1#6f|ZkEFoSIgrJ-8mme-3{4$XgTepZ+mh#?TJAL zv)x8@MO>X#X{u06m`S|O*GaXt^aabOmqkIz>D&AJb-E=p7{n2+b@;k}IjB*btn?#F z>j3{g*_wp1*;601cvE!Lhod}l3coXZaEVO+TB@&=MSK$?X#5~qqICt_EFwM+&v)y| zzt)Q`FD-O)L7po66L*A}H>OQ@-ZEUEXL!y^vHxMKzt{i6TNfMq46q^X#}thQ>ovjsD(c9`sR3tucrw}7S&JCA*qZ(*fW zoE{FaWFPuGN1@nUK_)Zh6}I0G^=E{D-%?uLv>pcdlLRt0lg4)ylQG)0(Q0u zzL|TB&Xq~)+>sOw7MBn>BX9fCMn`-FT&gc^tytNBIMtc&qdFp@Dl9KpW4Pzyg`um6 zdZSXxAkmUmsG>Jhdp*=H$x$k{d8g4A19e!=i0dtD&PH6t>8f1pVl=7YnS!)~b0n(a zEH$jq`T`jGDeDj$jC{xH^XZRgDeRC4jbB2F(1G|8h(e-NCft7~vSu}xLirjs$dYFk zTsh(Ckx^14RH*Jgc7OqfBpC}{b}ybCTxmc2RkyI~T`n_alpGMg_M&QX$JV>A#w$HM)u+V&ZKDZ_Vj@+~3u|mjntLos?i6Q!!=RhOsJ0#Mo@Bth|2Kf@t@mcu|d`bH-W5l`WwWr?6&&7fp7qJzR zOqtFow^{ug!)xDj4xnRwr(HfasO29L&Pg`3YNDxuD&!-i>x=u?eQbzt3%(I+sKLk1 zFngfgUcFO(0J(HU%yyxu>i7Zm#s0OSD4dq#3NV?4kebJ;z7(8_^?;ffJ$N{w^=}X` z*s|P%6G}VtQx+XxT$(zoA370Q?z7pwYPfoRqFw4&7%a;ltW}su$Fcq$MvJ1X^fiF}b zDlRB~#YF)lHc_z7@`o{mrY-P`sXMc=@{GhNSwEJlr}Eq?qUM1kqpWH448P$&K3KvR z0$60!S7<0`XvqK3!6LmvMnWNcP4Hp~lOldc$NSNYTf-ccMEW!2lwR{&Zp~!e1}THg zpR@n5fFb{90lQH&W2)f~FHx1YC$3lj<$C_@&oXR&jVUCTxIvO-DLaw>n7?V*qsRgG z?`a$=2(2FtJ=T53Ulb#6`maqKj1`}IN@mJ~I-G-j7Anr-c_%)s8yHzMOV1& zQ71*amow{rhTG>*x_?902SgmU#BARs*%NQ*17f~irBi2{QzY43jJN%N0OUX$zpq%- zsHoz0L*+Ei&ALiyqw4@9-1iR~N;HKe2r_gGH=cptk8uH|x9gbRQo`I{iOdyrou{a8 zD%DVIu#=tVXhax=FjZ1*-(?IeeZ^f3t|F7tX*P%;s^VT=El@e1c=-uY!^Rexrm;Ig z7$b8HALTJIjoKPxav;R7;@jM$+CC*m5Y=|;1X_$D-q)5hd3m{-8Z~7c!(4o!xtlDx z>kiz_#^O>$Qcun>)5(-7XgW{00x{rcV>=U5cb|0~C*6oM?w?qgbzSpo^n~VA7}Uo| zQWPCxkCZ0D0duru5TIeE(BOVXE*`S^S_Q-oq9(7!?b-&*v}z=@`>_oj89C1K@HD)< zysFB(nO3bp*BnYs+9t2v<5eOTX|8G$QH)6u8$p1;;SX`~Bg&hZNH|{?w<%Q6WlFl5 z^S3<=O4_zFv*{U1n;ziFomZI0wSA>}O>YkpojoH=BG=kqEkjnGv7J|#&eqarF&|90 zv`VW@Z97_zln=!eRXbOL?wm>I{RE(_;782WJCv4mp?zI;EbF|bYTKaYoDeCbw zQSyzp@z7T~OmJJzzt{K7sNIcVc^|*;8oe;v8;EgK$61EbYIcO&z{+`+SPe4;L{U3& z&_$^2un{SQ%H@uf=i3yR4W@uZwT+<*3;;J+SHu+UJ0w-ILbfwZ0@)p-zseT0R@-hc+tX>;Rd%r(!9|o<2$ZT3;@T}08^OG=h^y4f zl^IUbom%g}gIgWjX;%^zG|}Vd{?E1yN`*{jm&nU+13K|LLV18oWl&rZk^z0@tH-Dm zT$o!~*H`)o_<~49N-biwiZ4x&Huj4~?Ny!&m-)f8t_3%T=+acK*}u^=a|E z6$<&biS?Ug&KH<9XxDG|7Un4J1QQogR4{WOH+AH)q+VaPw3VO?T z45+$VRN^ygwWCwiz?gLF`oUCFM=QHG_7b>Ovo9z1KY!K?2&GJR+aAC7@`-FcA#-|X z`+T?Keus~r)?!f#_{96K-L9nn0Mu2~f~P|bGB%5asQd^{=G)pPryIBH8n#V=U#De2yG10LP4^p%vTs08~Cn!RzWdkw!^Z5;mq zG;B3WH2f`fl&aO?3^=N)+E`u;RmTx=2v@PahxU~}fWxypeP%Zub<#YepQ-3SeI^F0 zwKi(LQOEsC14`OH8&>3PDdClQl+$17?SUAP16~-v2M{i^v)cJBRlKN&Uc;HFEmQTH z5{9Mg)AauU_9bep%FnpB@A}MhSqElzC--@VMMdpftfj86=wS+idCkC%^=lmq&-jmq zr?T^J?qFR+DgOY7sc2tJ6tx?lY(D!(eGyvXCdSz>!KnQ*skB0)fi+6_e%$zD>+M@# zBbW~QM6Q6SQ!y?70IjF`N*6(CW~*1|AR5ku*bYz2{^7(^7NtjsgHI7rFSKwMZnJK& zb#NdyB@aH=!q`;aVzBzEZ4}r+Y?r-xcv?7>9F2r$EzEYbrFHX0#dap_yGnwgA9*Kx z{{U%;rKnvw=@PeSH69FVI>wnnG^U!I%4blpHc`p_^_5FivQrjODNL0MQks^gI?8;tGXNr(OYg_}ory>6&t3ljuUSOt@R?n8QL*MzV6^F2ZEgPm zSy1mRX0o*Qt1$u5L4}G+p5M@d3%eP^sVAZHn+|bWiSoYOiOC2 zOgos=>Z$O=r0wb%VeMK(4a|C%*kolsAjlc2UpkfgEF_+C6(69N$=jfVX!u%eNsdJi z0`oA*_@UYcD0MF~q77QtgDH60!z~vV5RIj^QVcl}&FsUh0F2w|?NKd};sb6XoA+%i zn+)kESOuk}W?Dk+$LW9m#9UbG8x>A{^hLwHQ>gWn>1mD3^8z5hWfi+Kf1Fj-y31JH zKtpq}iBPRxAYRX7#J9>Fp=dpWUa|8rRz@cLRBNT@kLD{9F%W(JSNeSZkw!Hs`9A=X-sxoj$sxT%DqhsC{!)X1KRhS zWFO}&3}9AV%|>c6rlZ6Zj70-s0JJQkSeChl6u&SDYeGJ8xPnpfjZm$|n2mjmVHpEN zusJkl0H35N)tcvtPMwC(r_0+y34W5&rrW@B7QLlT&~XVrIJdk4*=iA1(3?v}n1j+$ z7N#Xb3BK?*Lmg~j-X{^bgely??a*bf0fb%=Y`ZR|R5o0VeJ4%lXwy-YY1$UF`o!W@ ze;$!B9U^%|tT&f{-Y*b|^_Sb*;sZICw=%0Or)XkS)*xG(nD5PmT10b|Ba?BfL;a2cpqs@`=CSfmW*<2=+Q6F5CuWB z#Eomb(cE3)-uru|`%Bz!4o%Kf@ZDQ1MPW=vcBo}MAt%Kb4vW%M!VCCiOgkp=TGEqP z`>>k`l$qjFRO2eRkh=*_4%NJM3>a!-r0iB2Y&dE6%NrfzlHAy4H>S z+1JDpbgaYD)NXjm>)h!`iKb$GBis>M(H{GIrjlQL@fEcAM5Rd7fCUze8n4hqrVvD#cYwfMQi(<3z!9lMA|zRI*g-FLe6`JV$)0a0kj4qKyU79OJSZR>@>;?sr&e} z1ulD_+EZw)?o?ezGHfnmHlwOxIVUsRbq%qMrA?1?8%1l2%5CmGVv7v%FZe_=3btG3 zdxm3_>Ic0|w3x9Qq5QuQRjDn+!d7~$b!T3$WSXWI5Nh840GCo;xw{1yFx;D&Ynw`* z3VT7Y?-_}wtu5cA*AtJ)4QgYP7OFP~BT+{tY8Jd&sN5JTDK-W*YHP7DFm1$YsJxi2 zt;EIpMtz^jhP^Otcn#%RVxrj0H8iG32InJMnB>K(jls#CSCbjlMahd=n{a<70`Ls$ zzNWTVae9*xz#jmKh)oY}>vJd_{{SS#(|2DCU$g%Jn9B4G1GK}wx?q`$T{SkEUlFqK zC*AZ>DrFMdth|``77KgI688f!bl;T`)|=4K++mF|XreF%&x!FwS0>C-PcroobpE46waS zsk^B724blOTlZg?N_6~UXhSilliQ@`6jK_9${n)8`C|IVBk&%WVPh&_`iOAuCW1MFi&Q&8ihuza zcmzY!@-MUpj2TB1ngz_n)$L8k69wr^cdIG+M62X81M0@&VSQnhFIr;#BRoXVW8TNlBW58 zSo+@2PDuObN6T4d*ip!T6+QNLg+C&MX@$x9d%xGe;vZ1W4`%={)c7s#7Z%9polb0~`@c$fS$4NvhIif$HB zU*W^Cm+LUTOwYo^HJ2)f!Uj~myUS)xw}$M|Mv-Y)>Uaf(rXX48Nrv)feikV4m0oR? zE4P`=NVMyM2)Hh;fA!Qj;*~U%gF=iau^D#X` z-mGnJ*E~;~xV(FD`ILo_WZXfS@V-svFiL0mgEJI=5cjL_KV0!#k8pBe78c64kji50 zGp;Q0P1G3vV+5z_49x!k6-QUSgx6`9q<3d08S790RsU92LcNP1_B8L0|5X500I#M5E3CV1QQ@4 zK~Z5caTFskLQ-&YfsvuH1v5Zm!8A}{bAr*5vK1slV|0_E;qX(!!|^qMgOvZ;00;pA z00ut-{{Z&`c!u|{ybJF>OLnz5>w@jm{{RxkyM6_I@juYJUoDOcFt~hIXW&BKrbUAF zBKlmM*$c$KQ&Z4?A9}k{g{Ri#?pruCuEAY`yCq~+ODl3&F3QP6DmkOQ0{0UOS6QO9 zK1YHzG&A1Ant~(N%w#y8N*USM>^tD1e!PC3=)fAhrjs zO>?;RR5b34tbny(?pX~Irt6PzU$Z;j@UEI+zk!2`R=-Ac)8aWVHun&sF!i5+U6Qf7 zK5AT69(M0_z3LhytNKfzatl{Mf#;A{uWFb*5V3p6>U@<;*Z|+3k?F~JPK`ZU71M*4 z<@K5zaBgcMZ$X-pO|wwBp!Q&5R=%@Z2+ODa)~=Q2vzHRQYq9h~>A-TccAJm6ebbip zHxG8u12Ua@FGtSCH>x0Q$SYr?VE!$XY1YB{LO5>v%77%R)r7m1kz_SFq{mefu7M>N z=^L|<;=D4vH+OgPg}B(J+=nFUZKCVP3+sC8J)*a(4{%Z{R41cW^DDc(>-Kkl%v*+| zKdMo`c6s(nE#+;>ZIZQ*-l_Cjmi8EaCdX9Z*7+OFD_Kq%SbWi?R7FsU&Azg4yR`3> zm|9%7ikEH$Egj^h>s=H}_u*uTA9aIO+3!cPIbCY;m0T3X^ZBt*z`Sin z4q>Y8HLD0MWBU!wPmq3@rZQ>9>qfpp53E>0qqWA|c&)<$ zUVbh-7P_`A>&DCO_XWIguu*JPE(3_ zk7WVzT$&WUkYMZ&CO<70?42 z$ax$#;NsM7UBr6BG_ty3Nwcc&Fo}4FILf>ubzV5R+!Qq2Y9X(XGjT#i#24=RWRnQ*H5`(2>ccpw}|zI&~b6W z-`z(Qy@5~)qfBH>m4bZZg_7bNiL!0Ec6<0KFr;N~V6Ms9!D`(CRNs-&Z#BTIDiQ8c z4kcnE)`iFL?35iC@v=f=f$WS_jw&2NH!@95rU$=c1SS6FsnxgMqjGvEyrq|4+)xFN z3mI>E$Kn?0S#0jSsHnhul#z9AzE@-(<+<}kt`JA8`;Xv>;IVK-ty{(%3Ij7X7P};R z?Dj&7#x^rpx8Sh1vbzf2$a_4Qz%#NXJC_j6myHrorVT#sLp5-J#wB0d^7pbzT_OV;^+|F%s!M-oeaPvBM zC^lz4u`gDT-UFJ3wgs8_J?6R=G4N8#@!qqYoE}1p)830-a4Q3dUwJ+2d9&QH-91+a zD0j_XpzG1gHFmK6t|4Dxk?92$Gv=fyIF98vl*B8w++9zf5P=n2k5w%oj*1^ehun^> z&u7hHqz~|{HD}(T^s7%21`7{YF4Z<}iCWP?*KEcu$8;&rYUywXuH4?XX@v*Mg9{f0 zEhKj>?brHAz@7?PAx3t6>>f%SYJcmALmexUJnHr^SBI)Ac~-N+pp>2c@DctLAL3TZgA=)7Zn z?NSIMZzU_nJ>9{0x4>6fy*VqcqW=JJS6;_7^$Qk}-mZ)zGJ$!$(RLKBD-k_b4{%d> z71>b=^_bgovu_Ruio4Q$gDHANGgE!eIgeKwl6P-PCAf>o?p~(s!o1TXk>O+k3wLy@ zl`>K`uAB{*hU>Y7ye|%6OsqCxPZhigl{!7i9M$SNB?q^d5>YyKvU-K%9^p%uG#b$W zZDO!cva$%lT`CX8&EX+mW8vtr`Rv0Q=N^FrSc+}s#Yk+t{7TkcZ$ZgP^>GgEC?+vm zuY#`BY{DVH!n=Gpa4ISZXQjy(2WuLyaM_0_sf&0z*~s%)?95n1O1}3;K#l6J4CuE5 z-`>1k3G+E-wWY_R-e{&jGQC~*&wK-n~3HH#`C7gC1noj#>$P6r|rUIsZv%V{?^BTSHEl9HWTuZv)8 z^(rjIVPrT+S27$WVRQUTS6r~Sgk~3xm-Q-WwSqHm6k*i};4%m@M0YEc;rc;E^&NS~ z)x^_#ntBx)O$v3oQB$+Lrb>j$0CU zLWYYmH;+V3%d86$eam&MVhwH6if{VGZC4h8gY;b@kf`p{U4dKd6U-*Ius zj>B|{w{>~6O7LnA-*;*`E&l+T⋙StSjCf3j4*rzOY8b(0Zt}7iB%w~JrpCt+!Cf_)eUt>=THy8v zI}jE)M+JAX{zlDXjheA!yX3KJedTz%VD|-egI3;_?$ZOjq61nwtZM}flHPHWIz2|d zt>M5#_bb;8Dxa9j-3@&83<6dQDNC_cN~DJ@G0XyXd~C*0;-Wj2U@vE4mawxu(RN*Zk@hd{bP{{YSl(e7K@ z&E_`54l3(gc=s*vSimnEGL@P4sGMwVT5Opc%J{P%ASjOVrZ5@VB@^e5s=n+gPsM6< zU@t^qrx!U2XUA1OV-}{w6bX_H)olX*+dc1OguMiy04o#-|RAY%D2U2#9>E!5B zT8DNCWOWnf`rQOg&fj>cB!E5fwFc8FdNL<((hGNsi5)zfAQ z@i_GLVXLToRZJZyIiGg?x^!48%*&F&s}|eHC`Ot0A{&e9Vf`z4q&J$HRT}m8Ze53b z72g<9*87ow1n0Ci3x+Ls9!pb5-Wiu$eb`bTG&EfmxaES@X;nSJ3K|_TNryO49Mh&h zj$|O`yE2(hn<3-QLUg)yDf%W>uCqgdTFo9yeu@?kByuH1N=|QbyTASvT}qqdh6uA% z@P9jYpf4F-jRE=Gf!9&1Rk+?RQXeC^ZZrYiXNGB*Fk}{{jugfLtyk(d6})GlQSu87 z-&P{7H>pOoyvL+~&8`=id5a`uY?KMKRU8v5Q{nPhwWWT{3j3F^bG%k>{{R<~2646# z9aF0xat-ETYAJUp-QGC43%N=)cP}&-W6c=fs_au;U7k7pff*=dG%MnytMso{ZyIkO zLbX*Un~#|M5wA-YapR>sOyJ;c*zjb2-(KWa0^zS(z^H6i-7a?XD`mwy;<*Rp@*y(3Q$sa@*@7RZ8kDz`^OGkKD zn&)hD?pWcqD(vCQVVL1ip-RzBs8e^nT&CGP6+If@eO8HkxZdQN&D~t@NYA3)YkmmQ z(CIP9nOdzfn`t=Y;BZ@lo6c>#FhoXhEfiz*MhxHj_<%G)YB?cEzAZ# zioH$d=bAbo9>8G+zJR3eXzCsu)A3LQtIko!)stW8WIt7j??$6W3K}H~-Kc~C%-Tmq zKN}{QyVHW+4fk1>k%S7HX#z2m7^}@TzNz3L7jeCc4)dB54DZ&dKI9ZPH%y}EW>a0r z%5JYnVd*H`Yh>nmsBi>z3iK8pifA-cZ?vWKYA}v4x7{YqNOMbKF$f(Q=9NRl6e#_p zQMH}vF<+xlI3mUwtMpzOrIO)0tXjS1HajhHbAxY4;(F$ZJr&^CJr~gdQn`EhKv~Cf zH#6o`l7&jSa`j)iO~F@Hv2>lEcZ^ zEDx5>Y?5Fr&AlTJcEmf1d)#`3Q@vBZKmnz=^Rcg{9Ow{XU2uZDU@eU0OGyKPO{6!^ zCoFSUsvmNS6e()|05OCE;&|OMgPBNA9o3CCd=QFM-Tf;HZEtW}q2jNyrkzJL^e6}3 zdc!8*5p&EfTRRhq4CBVaE~tfe^@6Qj`FgLY%dOVLu#qb5XSl(LP-Z*ShT^9sm9+i) zIDk~OfO$}^hTyf2I44qh?R=CsB+?z@4{E~*QhZ~QE%S0u9Exx}(?ACEaB_*0(MZwh zUglc0!iEuz*Gh*4;Xu3@$r`m{7W21OPcPp7L2C-W-4)sR)rTMYO9 z3@pYA4#4cFvH+5=SH$vHsIuy8)87X*p71MNA?-PYABinmwmgQrFr^BEdWr20NW?mk z!tXGhr09B1srkB-)gWSH7($ruO%(CGa!k?MVDTJ+yL))6#b2x0Qrc~3=B`m5^gB+H zwQPrJ4j7Ta6ApWcK-YU(IR$lrpr{iz;IBDhZXTC-HwQbKaHi|boC?;Afmy4= zg1jwnzwlr>eaKOw><4N-n;QC$9WhZ&rRU_JIsMI7s(n`k>Yg-X&^ifNPuy96Bj7 zXEL{79wl9%+LfRALW_cry?y@x{cHB9{-U9}U(If5RNdaZc81!coieUgnhxbqLcAY& zy%oj`Jy%Jj_U28@`UU=>c#$tI63M1a3XNMa{;O>FrTs|8UW#^0(Xw7Rog7LJk z4&~zXcjJ%f-72J$z$>?@Qtv8XUt7>Cv}rsq6QY-U)V$HAJ}Mbm zj{cRr8vg*2-=%lCc)Fr_E48V$9bi^v&mdw6Ujv?ZX@Kk^olI`taR4@0D*qlQhk+tX+^`j7OnMfvzm}( zCe&_dA62!hdR{HRs-H=9%}wMFMCcNZ87=G(yYKS2TMM(A-ZD^xX`U&~yT-SqW;|?&5LLl=h?v4RIkzO{lh~;1hE-R6Y6u%l^tz8h% z0>s`>WBf}4@N$OU0T#<#7U-6h916L?$LH#>F}al1H}2VkdiA#W%Z-s_99Qe)@Us9` z_5or^Tcc&v+RV-fF{$+1nHVPCnd+rA)p+F2B?@pF8^A0VX#7_3lxsU8C)}Jc{HQo! zT2nNJjoO3eg)-=zlk_s{&!?4_xS|Qf98j&J*1mk;Q+4DCFov+;c`aZB1CRl7Zo#Tm z(TOWP;xI%o-g4i6y4)N{`?sF0G3u-_f=NZKH=pM_^a^btXPRs0 zG;bd7D+{8W&ykqM%heqV#plST=tYT%c5?PLwG%1I37h`U{|TT+@h;MdL9lXqByNamd6kgIy*>e zhBUcvXUfL%LaXv_D&rl(6u8N<8q!wt96QC577Zb5>eaXcjUTb;4^?8P`&yZPQMB8~ zhA0M%1o=3#86`mSahv%o&oWTcYs&*fwVYhE{W;%wDeg}MNhQuXlCFUzUeYoAs8yp( zHt%XVS}Wd+ViS6{%gxL!djuXTr6O?c57ihvR<64*x0=>cGSg+s(&jB?6N>SyD^$`N z&Vt5-(fLt;qpa8h7h6moV>RQR9@xqjM0C8cH5>0&Y41H3IF-8ZRa@V7++441XWGF# z^5NwJM{A#w$w@E*I<4AG&D_y(;)P8pJhixh-fLGkCjonk(ghyH`~qul1`aMc1a8zH zQc!a-1wP|Loye_oXujuljc!+4iqX%VD8ii9t=*R^&C7zpOe>@d(QMOr?kj!=L1bUvla1P|A0G=(y&6R$b?b+PE?1gQioYMm|tDW)@=i5w{#|W{kt0YgEiH zVXz3zU7q_ZHl(}%08PDB-5_e*eC`VfFF6F=BCy??-RO@v=eLF1BjHz|%bUE>k98E{PcsRc^IWVz1F@J$>W<)j!Y9whYI zb!WTcw{JhWMyNNbIVV-B@Ht9s5L*~Uu%Vf(RujRpD*Y@wmLf+x0U|;dPkbxzZk*P!kYrgQUb-53ZA(laRk6on z>$3bId$J20xC9+o-5iy{MX}tlqQq%2p`1i0G|BE*Xw?t77g4 zxbJd@0X&MmKpy1;AqP7RHr|gKPRMQD{`4FPCD}u> zQZqS~yx)THj5qi^X1A}@?<;nNKY|lQxN^a2skAaNoaJ440lb3M)4*{&_8Q}mK%9B2 zt{sxKybfw0IlPMTc^@@NXe#q^vO>F8d8n2VD|BPd&JJ?BQk#H9&2y)aD;jl4>bDtp z)rHq*XJq%;fmr0Q^1u@c2Fb0PTv2UC98YL0E4JCXVP50SHv6V9?oqO3?JwZeYCrz~ zt-Gf-Ao;*{yR5xSbn-#L@cv5eNo%+efiXN)=57@bJLPXx6Wp^dAx{JwNv=3&3wT?J zvgtdF^3*Zdc1JJtjrA%fq)DFYpl*JAENf^7;E$T_(i%p`h4 zD=wY(aw{5d1vZ?ab1>`EtZ~(E6aVQrp(svDA3A z>!IF>*ttN0?kAF&B%hiuse|9cm7CO*^Tf77T&RtH*u(_8?;9Oz${dJ;>liL+BNn%-NNf zT078d86@Nzo0hjsGJMtpfI^KHwA46vE7csekpm%UYep*Ta%%%)2J~5JJF!? zh{*a|06t*xSP(%(0jqZ-lGLAez{3m5sT`Hoj5wZ4RZD%!UVDPR@LJv-RB*CKt9y^n z>t<2hyK)vGZsM^PaYGuD+_%|T>&58B5u@n0z3OYZv*@&CuwM57IFhbV-ETf6UcOg7 zfEv@^!3Km~=N>A2=XO)8Ky_2uo*h;9x=NlF0nGq2waoK|Z7BXyo1{|BxS;-ahw)b& zcUHBMN^AZoIAm>O_z??M{{Xyb_^71E3TGTF@r)(@mTG*#*dDF#0xXcas5y<83$nWf za0_~*cLWW>?`WuNLq{QLCD0q1`{t@`rBD`ryBL%MX*(Vzcr_Q^#xDfgZS1r_u)XNG z&p@wMgHk5%B{y!KVK7i=y50)xW0Gqf>1Km#&?<*<5Uhe2h>9p>W4C^$SR0$azTmg0-4Zq*s9j|3FQNrsdw z(cU0`h#=Q6ws_c2QDr(K0eVRpr!lT^Xy$!fWsc5Rtz$jmNb(dZ;|{51)^?XO#G^K0 zuo z`d;v_d{84J#?HxE6_Us*P2o+G+^)B@S2M=k6mi&X3O#^+B?dDfufN)VGdmK=FejwNna}q09ZQ8I36RKy73gx{VGPzlcaNX(7LEq zDph2b<+b3{PVwy@(Mj!`)VmUL3iHqXlnl@WZ)Q-TPbpNXH-wd+3u1U$=<|dq^XQo! z$&cpQOn;h0ZC$J{4t!PS83@&9-VdFZ>ADIIsM6DuqawA9`>KNuhRVMWSX%0B4X886 zw7efkm>2`-sRl*0Dsl>#;&+XK25=iC-g&{HYwG55l>-;@SDs|pG>7JUAw9t37$;Tb zf&-IN-N;(pIBW~ulY@|NqG1ygbjr_a^)uc%uSNWmjBdLTYqUDQ(w$A&gyv4^H@#s7 z!k*1e1!~+d^h(@2+*)(8l>z?I>O6;pX&-jqyQlrur$v`LDOalQPc+t3-g~ohq8<*d z+uiWBZ0*0~6*?gU8I<=7vQ8W=eeZV24#>9Y{R+PLhX_7FuWn&S{snd8xbv`7VZs_hDrEf_~~-MD?0N~X$fj`l^Ffr2y} z+Ht(?hKmCtaK&!DxA-fhY`$~2w|fr6S#;!2&1&n-7mP2Az2QwF%FX7|oixr15fXG8>C3wJ>c_Npt@ z00p=}HVT}wMeZ`u&3kSZ5``|L4*7HVr9-l}tNFuJ$a4cP%*nNcns#uT=bXP*^yJ4mbd zbcN{VSA^9K4tdFNDyf|A;HOuA+cLLU(cCQFASW`3 zmz*b-)++0BOk=V@a#P6cv98GAg(A?`GX|j1_tg78m?>@?LTmGDv*=dtV|k@tXokOd zc^j_YXC;3}cw@OE`g*||51&M;b+m`wz~RK>!GEh$8YM0cc$bt+YwFJRO1UZRJD$Y7 z!L!X=pns`vzIHHM+1Z7Vu9KR3Mr2!p@pVJ$496tN1*8--s(p%|CvsQs-s6JSI|{sc z6zV4o8X-j`wm>;jDi*S#gJZiR7_1;!y_$4-$(xA-3S|SRYv=E5UWP;n+0k??0a< zdZVvx&l^Qro3y^DQ>5FiQcMMQksx!o6^0hi9xIc%r!esKpbpMC8x2RCk!?2Io<2*O zZjq(IIkudAR6qbJD+~phD9dDn*(G7xb^^%tp>Nh7i*>#x(CfMP%^FZpnt`YZWT>=u+d|%oGNf6b(QFc=K1ZR~ny}iY>ZiVG&_-yI)j7f}y4kVPoq{5`ik~3=W<^Q>4uJ z@CmOYSz0l1{Wc4ZL3FbKu@X_f(i*Q*Y+-HdjlIqm{U8sd+zK^V`}Btsot%w^yE5~- zdfUIH&qe~ZY!_P@TL{#7fEF9H_%%ygf`@4rdz!9|CH?V|F{VA8;YA;{T10V`zoXL9 z8aYSkuIZm=)u1`8+To{@@Ka$kcx4c$MyIH$o+1H7j}StFiykj9=A;|U^oOm0)-=Z# za0osxym2-QA-oZ7Hs5z1iv4Fw*3@h_%^cJV9871i4gij+&8MP(;gj2fof}AddJ?YI z5!I@1sKAb@{`RudPNQ!$@L!bW>stQ+VxKd|xdt#pMgrUxD6>Y9Il9eb$BS>w>>Kq1 z>hPxA*0!-aE``Cg%o?8b7{D6QfC9q?=r|Q7-bH#raw_o3($@)ZqNmM1wFP}Fbrk;q zx`CF(52 z6KwHB9Jqzda6YuWBB=3g$a+U;=+s2i=gPpw=2gj)#MoZ*4GF@XH)@9f6DwD2@eKa^ zA)pXjpIy7dV)E6KfkmzmeP{}7%g%Qon@zbiK-qm`+K6v@E^(4`O{Uz*SZ_blHcGu+ z&SPhFfd;fd3i;u(3tB_xd#{j|<*|agts;UX9_OUs=KKZ;D})*QV84?#-hBv&7(d4Y20{j}hfea<(||^^pw{PD!+edARdCPOq76UFf;yTuvs) zLAFQgjn$e zd1D=umABd0KQCCUrs5-)G#b$WZ91nO9qSTHjwZm3cMKbYd-k6GB*&2>uOBQ&5s0?q zy9IL`5AgS3si;wC+J=czTl_j7aECt=J9h!yXV+nj;}_+P%dYP9MX5FiRVW>bY$b=Ny#U!NI%7-DNsno78Lu@)6`*!{-P^ zkIZ>MY@Q<9xZ*L7;o=ca+PLfyH-ablY65FV97&C<&M+0@hf8Htsr@!+^v4Z~e$et_ zxXUBt&vK4d6l|#JAmBfNuw9kGa9ho{vR7sm(zik{aac60p{i^Wz)jP4hjIW;jp;m6ksfZi+t4r0>IgLak0pw zQNq|E7Mn2wMUGgYS{EhT3v|kd1sp7b1{NBQ;<0dBrc@P%NBAkU*fA-znUMMI6UZXt znb~W31Oly4@STC|pC~kjXOp~gT3;3xnC>cQ7>pH2tu0J~i>~bmAUE;BIfP#TQ*y}ZHSd<{CK>q**9U$iX z2Xe<}s?~#s71Lp(nX-8*&grpG@sB82?1+TwZ_IfTg@ptN#xX^+0qr3{{t0h#8v&M! z0I{|UTWhS2Rsw;w$fs>Ly3=E<3BAaF1zj7=^hy;;8BN>RqpfHneA0{CR6x#nEy~P3 z^(O#>#`N$--1cdY%q*&ZDOC^V*r@LBDhmgUZb-EG0)>SX$jT8OiNRsSPw*@?Z(_SE zvJ?b1#>0EiLe|>r9cxjs$fITpdllJTkf2&@b%8gz58$TUZQ?PAK-bap^oAi5qY(CT zIjglPy`(J4xvg<;DcTC3eUDx4I}Y}|vucKJdB?~UEH*R_NwvA)snx>`-lzBw1OQ!D z1{ZBKlr|k`*a#tOZFP>dsMzFDKp+C@urRx6q}ptCfj7Ai;Fx9rX5zdhuVe1^xL~i- zGAzg^O$LkHMrvq2?im#>remhaOtZbgQ`nwv^2M$a4rt-I=AE*IkM6O!%5S1vp3gWs z@csm4hoylxxebTfHXGi87Pi+SonS!$W06G-fSQGd$5<14kp2m$PmX0htpt@B(>a75 z(;($!TiFeFq!xbl!Azi;WiF(uUE2-sK3uWlL073uoAgjd$+o>dBQEP1+^JI;i6vp0 zkALtREIn)%4Tsv@hWDU_t+b+@V6r(_fdoH-FH241I4QUD z@Lmm9v-H_>L5mHP`|J(m)YkGF4`;vdTkHjE8H-8yTK?+~=D;j0X~;rx>ZM2UCCZBe zu`1&-O~n{C7ZutFk;d8NyFmgCfp&rf8vsCF2*I)mg0L$fxCMqKORbVuXd`9EtO~@d zjLA0?KsFZ=yFnWoqVQ4LO00XtSfH5R&#f_{7LbY{H91Wx*5wIy7QOg>eEIgb)2x+`v zQhgJ;PhE&|ygN+AG>ag1&7~CHiKKc+jh6lp zf+Q4OK+i&+! zoIeeu-5`tnEFDo3p26?+ax7yAkWMH8lEY-V*#!f!z$j>vuR9n07OZCE8aS=rGRd;H zbgAUkJ2zvm;cC|rd7}wM&dlO$$C?bBhQalA{H8fs17}t;ZI_7OHan2P7xF}NP>q!b zI%PZA+Gi}k3*fjHzaHyb3Fob+)!-$t=V!G%cquun+#8LKeV4r>V}P`$`zUOKJbw!8 zWvvj~XT0n?yVcaDv(hl2aN4>uZGt%BY`Z<9V+2MPG5+m`cWnd71JCf4-ea{G2%CSW zVcxFWJTclYD7%^fd+h^|OmACp=Y@d;?{?dJzXs=W5}xu&E_BJZn@8`~R->W4^xh?= zMl1FQ{6g1hS}UnCVo4vz(6Ch>#AUSB*!M;@y$+VMy&GNKwib%&L9W(3waq+ytE0_y zY}S7FW+l8WXzIERf#3V)o{dP+xlBNoEg$U~cQy4I$&rRD!Ss_(*h+v!8iCXGml&J81PCd)^>ObKrnmhM^tQdOYv{9l^ zZ6Nl#^l`IZ+mvXWoc{njxoh2WwH_{Ko8FtF=+ws$C6Qf`Bar&y1ok&m=%sJIE z_j5+O4Lu=^#n&?)@80Ct#)!ah*>jYX){TQ1N5OG?u& z%Zs&b_hb5n;d4^;>ASCO-sqL0X=Rsc&BO4UXnQRBtqb{!N4_Le(eL~5RcKPuYSE`g z14A7gGgWJ8d(~-zZ*^}K{U7{`O#3RXEpWUCLxKGf&|}8ybzb>}p?#A}ASCw;0;b=y zSUfJP1I8oH7@jHG zWm;fYq6?&RZhs{p!3$2;*Qr)Daec(cX+PRF)~w+sl|9~)tG$|CYC@et)-|qx04qlO zLaRo&U3B;0R)Ki{eEia(KwS zq-hycEk$23;>bbX_jAU}xs8o&bpebazltR;Kwk&sp7HBHfL_&bbAg@i$WH*A%HI}& zIuL92f$PLUUZJ%+9G*(lCj3>@UM@%j1m{EEF3WRxtt)z?cc=b&lLFji9IM9xwi5m7 zU|{zfeo*3tBfV5*>cft8j*A)TAmlUZ2Ai=IT#2==*^~$TXt#OaBx@5x5KD>jJW0O> zl$Kn%N>d)XiC_<`{v6So_+by$v(9&&l}=VqX5!vF&D_uK@g<=aWECOz;b|XwxgYyf z-1mmb5e~HhjfZfuk~aM@)DL+t5_1OkI=<3N^5qAFAGz}nQPLk^&(pLz5{IJZn+5{! zR|jToD!j>R`?HllB-)b?{M%f68FkId-ZQn(we_-M4(cCZ&S`#J>sZ0QT~Bae)2=?2$8WnE z%xakqnL=21dP05?3t;^RaGn1>RrU3eb#3Go^bcUZ_JPw=spbveAy}7OwOX_`npF4) z2zk@YJjck_HEL7|_@MAm&Q&C%y48rbf{uBAXx19N=>%-rV8Ck+R62d6R*~m!b4iwM zqk(Iva&J`u<4*Sy-RY`tisJUY1k9XkWMV<^h+{l?Yeej2vM+L0*cadP&xy{Bzj)WZ z|COjLXq~Q(51BMUQMiwoW#)Wx?@se8_y@T82iV9vCkD=#^k|d>@c#p7$gWyFrA2IA zUZ)I{9y=5n#C~w2&}h2vWX}>Bzq%ugfkZ4BfNtF>i$A5ARIjH^LEwm^-7Lcq} z_a*ikWM+Jtc`kS@{clv@nf;|_X0oU1=V}ZM%_5qbvvz(4pS9W_f+*9e_p&z$i7@1FxQml|c~>FicEVEVQa7QJX3 z@E8OetF4naBs}6FiX5!-Uy^)njmNoBNi!>+KURP1YgtcNF5QJr${1h4*@J>Y8v%O! zzcy8U2rta2M>jin70|Ok<|!p+?=);VbT1}~lIGCln#epFzjhw)fi;iZr3H6~*7HAP z8s}#3Y5@%|a+Q;9cPI%zbY$PD15(HGCS2zQN1kLajj;jlTby9neT$pyW@P7hybjCc z9+r8(Q>pvUV3oWmtNC#uw_+Y(kQ({w!-qylwtfY}7tH3G`r;ZiP6u-?YQQOwAcr|7Xm> zJ(h*<3Geag!&3ozpgYMJJ zr6~WcO{3Q350tJTg0;%X$DN>uot8c6gVl9&E*eS6;%Dcud$n&P2ELoY|K~qt*gwm* zD`qQ(|L`|1!)dH>ma~KR6eXly)7O}OIxbMkx~Bx}$v)|4zP2!Pb_S&Q-$9S33a?9D z_YZ$dCPoLy&^Pz=SY8&M*Pbv+0ey@L=W6!LKNbo#s%fX=#^PXV+i6nq?e0zt`NES0 z1oIa5IXf_sK$ezRhchpk>l|1Yt%^*sH+ulJz{U_~tyItTypR9;g9f9TWkagrI{K$h zsy8yNeqm-ktG%X0xM5yods2s*B9*Lj!ePg0W?}4^)om-hB~KpikZq(7>j|5KqRR-w zcJ?H297CkDg(T&@H^V=GrErt`3WYKft>Ov(aihmd%c> z7|aHK_^DF&+sm7pD8$GLU&D!(`}Zb4eNjPUU*K8mCD~bK@d-DtO}O;&UO@ZbXoqeH zOIJ>RdG(9%K}Uv|TRB(XWmA@Byvf-kX;c$9uQ6{IZFIw~s1-Ef4kTPD73By4DndO^ z6q>{t(`Z0WrJo}x`iGB-g7V#ivLJTH?aNsMJW-qs zO`2273oO`MnT9bn3npnPGq>rhLyLN2ab6Efa@I%oe~krM1V>(IZ3N;J*Gv+9ypo>_ zir%UV17_0n3W3< zJ>>{6l(QTJ2x9Azg^t32ev&Ph)CGqXV z0U9-MsTD<-cm=L^^)l0j|6D6sREP;FNxAhS(CB7}$exNN|KLY&GJeHiLZbqjRvrT- zLm05|8z&yBJ}h7D%rnDixZIU_NQqNGQ?-|?Wz(h}9UGbnYDnl5)>moeJ>Ti&{635L zaucW2C8Ylp?e1h$5G=){g=M`H?TD|4IfAtBNo5{YK1vHdI1URRKa4r>SfQwN1hA}1 z9Cs;hCfh)`(hZ75tmo(AmgC9u76oM>nO~m0 z_4FU$!!zc=D)iWKV}};2v?#mw==(`-kqt8j;D6r2cCz5B%KisX{UTKkyam?6#l6gC zP0=j>@=6MjVoE*{rYnl{0@2yBzh$=O z|9`((^WmJ5**xUSf8*NnB;;c-goXEAeXo?ku`xjRzvur`j*N5hl{31GalRWcfU7O& z5yxweSD0gTw3jPqZiykU_k-uwY)#7gqWyCG@*+%N?*(e4OufSTtbHJ8c-$Y8xH|3v z(jgUiIesI`U70;4oD_09@4aEZQ~roJ?AiFHTwW?*Fsy{QFiV2|`3rQVKo{e*%>XgM z2~G%!|CbGA3(GD0&$zn4Z1)g~i?9$W5znYslLg=Soqd&lIlgZg*2@NeB zcT#uF1+Nw5ulsDI;;O;3z}nJV-2waIUH17Q$GNj1~C5{k_I zBFo-?Uo0y3TVLI&OwQ!teab5kyJh%KEImFkge+a*zWj$~-;3fW4CWAA=>&5V8khqZ zJB$`I6FCEO@Zyzx{?i-r-U*jYB`t3^-95cbPVOlq8p;n0x%wUUs$Yedn!3g!DiE%} zq})GLc8RKQN#g#(a_4*220;)44VvkwJ-oi8LMdAP*rBQzyp<_xq!21?DXJ>JkXe5C z@{qsvr$4a6o2LWTO~II4mV4c_4C3|Wq5SBV+K4Re1IPdy(a@ej1Y#QCTCEma;JscN zOghz4*|AZ}@dZTJ`H~J+%U(39I6{6g_1$NC%HPQZD$p9*JJJ5!jrjOj#a1(h4a}U- z`(5bpjmNAb!OEcwF()B0!M9zrds|;(1zk05>XY%gTC0kWolQADu?ZCLu>k;@no;&N zmJp>YFG;S%o5MjVBy%5mylLALx0EYI*LD(Edbdf>%B?^8e4wOark@Od`Kz_-=SPh1 zWcUgc5g7ZBtqp*Mqy( zQeK*Kmgx?#gc3c411m|3Y%`9{sM2@9JqJF$F8p8<@XgXN)P$`UX4XZ8`0lS!4Zms- z#wgQt09=W$QT|=vp_|75H$zz3eXI9hxYs)^P9Xd;sZrx(R1k z`hMMfq@YDK_OW0%k5b?LefH*~gqeWD-4FYcv$K}&0m5k!@zFax=>qf{@Z9|0l;gg% z7VGC$9?n(b5Ba%O&nWV*^LCepUawYv++O|>pu*oZ&w$E;hTj+UjU%J{6+Gqf*-ZBl zyLOl_+og(`cR&P#QmpCWfB>q9&mQHzf=tH=yTBNbXY+T@%AXmcY^%NrjM@U;c!Kfs zEc-y2(F@Tq2rrA1MT4JynEV>CaM{RjV<;|cY7DCHHbtP1Hu~d#-R(MgPxqf7o?PkO zKz*X6s=r(d@OowT9X6=q@DRImW^xkq&}ADRmhyc~h89F6QC|I$`O5P1X1J)kC+NfQ zfC=-%-~bBdq}Sf=&>BcQ&=Zd4a(jFS6r z+3YA>cSuHbBv+T=o4x#ScY8_Mat@JVtVdZ4Zx&nYRTC#C;=NP_W;5Sb6DpCSFN#^< zdIy14AmBp;8hAGIR(28V@^KHtZJ{J#T?7Kg%^XT(d>K^HI&dN>le2kSI*Z!Sktw|P zix2gTS*Q$Bqd0q9m|wj}_l|RLUx2aq0VsdxOckor6>lyc^Iyb8GRoKkKoet*TU^Xs z0;;?h6u7WkZe{W;1t&4Fb+v>8s+jwVl8v6;7O5TRGR)mSl*83}hH3GI4osR3obR+` zb5w)CO;za_JS9Py0S~^nv7Y%MegYvk?(&3=G=flK7G8sAeV<1f2j6wCDcP?{`@~Zi zj{^DJgvt2bLuF0IO)QKHca|*|x;P1uA1-9FOQw3K^eH<#g`AR2tMh0y^M@GLI@S3K z2Q{}D0Ak`VY1Bo^e|#+|S-qHUw?TV+)X(Jo{^3~ZRpwc?=YqpfA=G-^!%m>Nm-Lkl z+e^0OFUQ{S?GV8I{UFrERkkcQh&|Fym^8?5(=?1Ph#d1~HVLrR&Y186^pp@T!*?2+DRA z*!>o1XwX6uTXq{P;db0gw`^%@IYt1Q2};vDlP6Wrq`dz;);hm=CV23ifREFcc9LJ? z%69R=+A89C4OX?hOQ@XeU`d7<#b686<1Y6m{3a;w&dqZ@c}Y6Q=@zvLXU!A~OQKN7 zVQW=CfSNPR1tDj6scrn0PRc``_BbARMx1o!O@r)67;D41?mwsZ?DC8w7)j#$@(*Bd z0@X`Gw3lH~&Gje4<9O=)y{O=G#+p!o3p5O4Fu`j2K2!4nmNT3GXjsrlrmTC|gH?!1 z+nab14iUB&IzIs*{|Fe&3(kVl3J1&=5*0HsWzw})UYvh%f0B#Ay%@F@LM$n~#EVE2 zeqC2cRkh=WX(K%#og0XKxO|2siInYDk)@J<94YGLAPG(^z9Q1VcRNt;U|)X#EV-sV z%vqRlm1V8`0g}#XG!t59B)`ceDZqpzc!67aJf;)Zy&XJ)09;T+dc>w%?emdoYG_Ys zxFjm*4GsN{n=%6#wH_3Ra@2`V%fWIQ(fT8m3;gMMkTFDyk=h+M7H@`O9!fA z4F`ui+k^!R6GTl>=h!Cbp>@rc>~J?u8Z~EEw|l8U^G?d|()#)GOpmeEYdlnvEYJ;D zir!X61gN^IbsF z+*JvMQHuO5QK!!fx*?+vl~fV!!z;bAdqA{lQ27DJ7At3-74-HITmpkR-i(7^^tsyzh-_h8oS1U4@?tOp> z!?9B(S9s~o2FeEgGdj?czu~J$Nqap`Q6vtVY}$z9Zd>!jh21Wf z`t_Knj!4k_;o6yu8oJOi$3?7n9My-D*LL*HS4bWSWYDg^qf(4Itt0O2izPH4vR=UM zt0QJ7cPm_AtUI-UutMbrM@*p?e-r8%OnGFAXTv_0AyrZur5eKOnb3Kj?bUAqqX0<& zPutxdFjaTI?W--Sc{kJUYTU-bkJaOUxzI7Mj{Jkr%JSn`yfRtE(G|gaBXBl)xg!$V zKAt@PA%d6w)GsONAf}jZLbzZfTly(wNJzFu)(tDoe%F}@+aMIC3X_=G6`w8PY+Oo@ zoL_RJ!6p=U=@+sEBZs!zx*F^afNG0vh!81;m*%(sACjeIQx%;@BuQS=FFxZBze;~} z(0NkSwPYK44e45=5k{E`Df*Gl;wfB6Jbp^0bK-&+N`+)_RO{E7NRyhL)2wfb-PSl{ zjUO1~bdQE7oU^J#9{Y6djVycuVT7bLO8dXirjksJ6~lPlvq@)$w&M14=CfpFES2qG zUeE2mi7mIAI3?DnbZ&YCS_ilQP9I=3*z8U9dOt93-W>De(5gDepI&-(csh;}Fj>gU z5L}L0GAwXcQ-_-;g38a2nZH^~RcxVTa6d34SOAuUgC^@iUN*RM%qvQc>=L-IhP+b5 z{0ggD(X^WJ9Uwn~b?=CLn+!4qwhyuhQ@cDsuaZU!%UOD!i6BevXDMV{kP)*a-GAlvZL@0s>2RhNJ}i}dx2 zw@b_jCKpaFE`ye|mc}=1&2RZYCUtKM?#5V5u6&6etQ&$MMHn*%miWOs`g31JHK=Nt zaWjxw>j0Yw+TrOO;0Xs2SNX%Pjr5!&_B#yOl*oJ=pULf8yKXlccZu00ptG6C!!wSl zqmHl=joyJm;r7$JQd~T!DCnq_u4o0ewN1V+uh7FOa>-foN|??yk@B3x%yi9G z@=L-h9l?CuH24PKm>U?ekPE+^4{KCSrGQnjT37!P29WF>#x^YuSenqO7UDGsT3` zo;>{e*Flbwfp9=)i=CjC$=|<@VkQ~)MK1aD#33nd!VQozOT|z7Q-6e|d<22%nsUZs z&kg`2z8%X%Yl^qtyNbYcF1R^9@2*L3>|aJ6m`(S;A5>J0wjZD^dU5q$wUA%i9LCK2gVUo%;-YzL;+5u^eV(4JDU(#mf`#;#>Y?^Dpx0dV3!8QXDzJ=OP z-Q(BekxY_b(Z_IoDBw#Wj)yT)vjK24C2j5dop=XF9=8-Y+9y&|jvsy$2jqw=&vpQn z%%X;)A4}}kwlpP+2UIo9_)%tGJF}b=_MewRbyIEqsJgIaa(&uv7fh)hJdVFfIkU$7 z{UJvrOkY9^H=0Vn92A!7sJe#np`zEsN_wKGX6j9m-|+~;u+DLAD(XIyl8us_w35;Q zDP7*-(iQ|b3SKbed!vZB>hO-2x#lY?N_Nb+GA2X3OT0M3ABvv#w44i@HouGH%P|Mc zdIX~olNP+`=|mra83Py7ABQXXus>I8BFPF?SfA`g4(u~nP)f@BeRl3o3MbiE&Oj-3 z)9UPNQ(lCdoK&?e(JcLRP~2piK#into8m6WYQ45<8|U1*F)?D~?J2p9&0WG9|M(;M zkV3WU%tk@Ef{QW3)YfLt=zXD!GZ#5zZj|Q+&9v7h;U%g;M{{}h5!m-)OwGl@UmI=> zGd7zV%IhKEFQWV%?jL9F?N-@(=d=Z=$1CP1P7GCW*OdH2x3JEwKfOCdP*YRw#6V>}u5&K%B3ah5J9eO|f2YIIVo2`M7i(bfyCf zOBkGlJQRdLu*BSXDB%38*%pJ_Oe|4mtE&Y${mhCFQ^omv`3QZhtEV-~NbkNEqrYdL z40(J|V4+{BIFzjl!6n=ojzZFgsR#O+lMp{l3*7U`pQH6Xm?V!f$OjGZPTZ@n2Yw#t z#kI88nX80VkqpGq<)P5aUl$rTVvNWnRFeo6N)oU`Fkz~{Re1#3!vTh^o7U1y@mAg# zPN=*sqRu*Lz=h^UQpFths3MT%^w-9eNHU-Uk`ltO*@}r-Lz1;a>-*Js9TfAQ@XG1l zbgU%LQdihr*R0ta76U%xDPlV|O18SY9&ego(sR=Y@V2&b;#sm!Sr{4|2Tx1gm^+fc zEInpKLn}9F$$8hu1L@vSABGJ*HkTQ7W#f?TG5zdSn^-FV%P7>6Vu##_MU@IyBR4R1 zUIGtt4E9W?M8xCVH;r@{OB|3Y15EB_Xg|dJn6dQ(?5Wd>G@@rN(<$NDg(wF~<@L#x z1N!!J79>J(C-lN$I}|G{96R|*z?a6%U_59&ZAPM2K~JO1JhmyW_xy*4KWY2-QN^kj zFJ|DjaT2Trvvw0z50^a}x)W0x!NP@KM>tzePixjHb8~^pFlGJ5mJ2U0lGmu!MXN4H zFn}70a?=f?N|<%Ts#~Hi!rTnWZIM||LJv91L35g@P@ElPH`I)z&1}9Di z%#tPJ%R@a<>!3COVjEoRm#D%|3&bQvH(NAYlw3atB71MpKVfq~#}hoCGHXsj-HB;x z>58Tbq4J)Aq^4QwQHYMr9s)Ipzz7+C{6l(5Gvm4{X2l6guxuK{0BY!VCfMB(GRF1J zCfq-5nb4frv2_b#u7RfdTKBncOhj;JZnCS;KfBaDMSz=^EQ`d7^VWh>7ir6^8X1s6 zEK~t>lIghfo{ppFyFVw@4}ICZGG+iy*0V)K$@{>P=t@L-HP_ZeOUoe}Ke} zm{r$I*RQN_NT|ykt99&tB<6^P*__d@|}RTh@u6mPm5*V z6_(Do2rR-ka0Sbg0xKau8a@a-5AQQ^3y&mx8k&Vu(?2;Nu69Rd^dZ8I` z8qy5OHQ>uoNNDMa1_-Iu-Iu;NHzM+x5Q!Cr+_wqE;KIgZYAYc*YZFV$nlf_4xA8}y zxWA%r!jyw$U3K7A-i#7a%r6WIqhSy{Bk61my0)#ur5rEOCw>|xvTFPNK`EElbg7yR zPZ5-w#kbd`wfC}sCv<65gd-NilciYN3uoK2*wf~{mrCEc)mI+Mv8$ZA!UXHale=Sh zTv{J7%22v=mb}ZaU2*7L>;xiS4@}ww&_#GIFy<*q+DfkUUv8BlNIqW!kzRh&^bIL;{a~T3s-WE( zy`E0N4&9?%f>-m0yi=4EF=x0R%_5z7S>DPMcGaC{mNzD`ys_7JLba|j-HS3d0$L4v z6ISAqrWfpeMZ&E^CXN}3@H2ZT-XhSm0JTv}jwwNkPQP-OvXJvr#mSH>2<*R%t&Re< zy9Eu}e=atuV|>aYiVR&C$LzK5j<|ARyZf|p{0yKUgN_zR9&P3Q0D39Kkw?1+^$u64 z2Y}IkZYF@_C6K2NxJ!S;UtO=)W#`%g&B_m8zVEU@P5%%hhgtweLHW$91|#yp;Em{C z!KU)~4jAgPvNY0`)W69H4o$esYI$ieLw%|s8bJEf^N!UU93zWVHWlJH$S+5ztvfdw z(bmIoqqHWpuA?EQ-CMiX$!VS)53INImyg!9V1M)i(-VQ zt+KFmZrwBg2hiFH-t@AIrh+S$ zt>q>FRk~U?@KF5hzz|2?)Z(I_Zg4ormJLPQ?ok{;tgDb*>>0_#f^C2D+fNNHN9F71 zmM@}|WS?5Tbf^CVP&9tuu@^IH)uz60KD|q4K`e(vg{Tl{dl~;4jZf$ludzopJLmlV zl2ux_pd5YW!fIzhhL6;%MBDdS=L-Im`$g_OEU0$!J<-9ohO?SLJWcF5R0X+iLW2O# zPz@K(lN?=Z&X24ZdS$tvzG5N@dKpXz&u()*Xl-4VQ_z|Txd4+3<*vLy`zlB{u?3kw zS(ZW(L*!X3kQuB&ggJf2|L9a{ln!hw;lu zO&KtN_QXl4qvkc19nUUgXD!L~^~$u1E%wP-X%Bpafh|DfI4$l^wH6%Ig4k8U+7YuK z47!vq8PA-)U?Jn~5SDUhikm1_JK*C+c50+!R=rgEpNfGK5i~p-Tn!EWpQ{<{O|157?K)2(wd7}9@fV$ zqgxKCT~k2VLR<~S&q>z+l!1u(b2wp|ZwMU7MM)}nicV-Q+~sEc<#FB>C+xbM=pQ7xlE*!gF=@VexhRjMTOook)rN+h-)s$mkT)=tE7 zgIz!*<$%$R znp8+6F^v95+M!7#m&NlXhKL;7R5K@qq^Bi{slNa1{GtnH@Y4H275BUgzc2`Vf{#TQ zmy<%dbU|zxW*+`4+l_T0JbxpIaHhftl;WXL1uIu|uihzEVy#!j-R7|P6y*Z5#E;<> zJV=gqazLv?BFGVVwAB1%ijh{(^N~f*GwgDXc)3a=FCuMxrS;t&83tIsz!g4v0b|XfEk0v8MQjq0L)wz`Bn5C zlhfPNQzVSJUFa669g%jx>IO*~lQI>v<~6Qw)7)i`8pU=5iY=Z+j4nLBdJtXA{t~og zZ2^fyzEOSCS~BU*$WGyC3rl2qQk&1UaH}Cw8c%g-l>b&#>Brt`ZgtzL1@`lFt>Psc}>Xw8q%a zf3rpFuP3&cG1V&Gk$&i^lfR#1c$E6oqt1;lW(NlFx@4%^6X0!ltGQ^4bOF8Js(Q~b zSw2rC&8>X<6aRk1ySUd z85R1mpu&j+EHqwy!-2@81MZ`OPNG3QD;q~~H;IuXwt`o(I01_0*9mbw>T{{QzEon& zssdWn#bPwtDzWsWcF#yGi{j}(xkn=LvXqJ4A1X1iE^F)}xj~9NZ3Ds|JgB~ zT+N0L_mp=W<7PMw|1>*Fvmh-dlj_Co)S_JLZ+h9xyjlD$IQiaDH=T^&zaMvU(8Ab! z;fGP?WZ?^b3|x}zv7)l~tt#~(Q;dxa;qE^@;>&u7u6Hm;BK0!pq!gDFfZw~c4n@CW zPUs>b*1fjjNHLyi&4qCjU4+y{XvlAn&apIH@2k&Qj3Ne zilRLB6H~N!$REW&X}1`@yKAOe3eUKo%H_RN;<|A3Iif8)5mgwL!!Bmbep{2o73U$g zRtezGF=73AD-O`fv!>LU4J^oB5)h&sHsj?}@I55VI6U-P+DT{c5gZI|@?*|<&RYb4J0)AU?(%wWywp8PYq{_`>C{d zc-=x`{dyQImT~Z0XbWPc!Cu7UsW&jb6$L4-mhmw<^=0Mpg4|<+?Qe}bN))Nu?uKj2 z;F4tPacB6Z9QhXUXUZTGvjv?1YDx18o__Ao4iz7Qlcc8t}O*bCo|xBFV5xN#FL@Ck9;W9U5yh)c2h~(ki_~KGsK*Rc?O* zd5w)GCv{wWd&<)lqjnSIHe+D423vKzV9f0|DT?4!R~j8l1KUOFCW7jDGT0{HVXQmZ z)e8c2{D<5HhNonLUL5Zg9Tn%-tVg4(8{Oe`)XZF-NrEiIqko+>vFc8)q`TvTqwU+% ztCk!J!m;X%WKc<`15uRR*ozm9n5bv%>&Q8Dtw{DWt(ZrI>G&KhE2Xmx^~naXwZutb zlu|ZL43)+46#oIRLOLW#(vygQy46P8Dph}hcyqq!lMK&JqBM@)#X2ttF$x#`ZVh&B>)}oH0ltXr-NF9L~^g3{p9FnBCZ7s+Uo}t z&fPihk#qTXvW;UoiiH=}ucaD0AJr_Xo2VB)XjbnYGyS-mnpIraA$a+Y)gJM!eT2rA zptjT8XSjQ@+L5z!`ak0yZGB#WfJ%VaYft6pPMiJBD1T^A@6??c+*%oE=}MN^>PyRZ zcbUJJwsNpTFOtjO6~oUE&qWe0@EMPOO6HF`ygy^eZpZ1OxLv5@RZGXCWXqw>+FZS; z{sTljv(7y}P_X?wXYURSi9~+?%A;ijP3dqQQseZJ!vy zzZtPB+Eq}q_8;{#HUx%mA(QQ#9mOSOrv*@!ML-Caw$QDYgIzzLbdL;~bo^c;w;8M; zx6jWtZrWlc+_Z$gJ!Tl;pfzRM$iGa|dujsP7-! znj8Szzi`amcl^}b`^b?qHu10Mdr-nosRO6OfXXFdQMGLby6ZR$e53v~e+JwDREM71 zIik_45_gPqCq_=)b>K@*zSlJA7p1d28v~>&1i6KlKe4u>p25#DmPz{PvyQP-#S(du zM_EBXdJP1uQ`xOQO-s;zG9sRx?KyM2sbZ~eNzHuGM@%i6>GYVtD5InPP}3@?3zJOc z4L%;dhWk@8j<7o}LN*BYm@D%>&0HHftXDgw6=AsJQ*KmVs6u+>jfK~khu2g<(c*b zc4|_A;bsV4J0+HEXp3M_J_BzR)rrk7wnlZ7FixUqFNXaoPLV4W`CL*R|0TV@PgFE% zGuZ8W%y*)#&=tLc@Qf^;K0r<&anEk zf^Nh3ePAp~z;n`ULtSYWFcT}$rX_BV_o8uU=QJ%pa56@U1R3bWJcYkZgd4m<0AN#> ztJWXHJ4F-EAvOJN^sVfaFpFlIq{s;8yF~z7{`l75zPsI4Y)d!of0oy96a=f}aKpki zZ&4B2=mw)rCZz8J$?LZ@-(1;D9}Ie&92GrIi(wsv>Y*2N5&2YJ*(w-soxQ>yo|seS z79`U)A?AtA`TElK{(QgZ!wC+c;`~T@jMJT$YtikJ?<*`v59T$EC?WvP+ns*tprd4}y9! z?Um^mYzb&x4Wz4{0)3UM_CxKXV(SLnMt!1rxUz?ux5Bd(*Vs|ebctomHBt=%T(R1} zOw#r;*OsM1pzTQGXHD^iaZ%eWm16a-RL`ULLpcRyRRftVLneFANth_~NzO66T&6-u z2hUMxb+Kv^dJK(!djl;AQgx}QH_TtTPy5V`U>;~|l+5fEMrw%erZNSn*Njy%(6T#l zTJF?6jtiO4gFQlWIs=)b+M}$ey5HH#!iTTEg?MNlqWihyc?HvwuJxZXcMezB5~Q5U zkY^cY(1hasNBQK?a|VfNWPrDC;4$Db8-uhQDA95DnsxMj0)_loSZrp-%s^7?5bF~_ zwq9sKtp>$K0G|8`0ZI92G?{-L2aBnqyMJLWt|3R0fQ-b>>+aKGsj$ZC z2N@}BE0b7upgh@8u)p%PeqH)l|G9MDjB6d^C^8boNqjvcgtfX%NFf1LD%(-}q8ule zy0SuDehgq)IrE}b@WRuyvH{Q3MU|db@dk~2bF!Td{1Jm*V)qlna-OB}=QPurpu2Yd ztnM^B_~@_LsIIfu`;IeZ-aP;ZmvCcfrz3&c1^MV2hl~W#GLAsxZx%JQLz)xg_q_Ys zvsJxkG@q;q%wYjE@~)!I_kuNP^dgr@PKoDES^fG4!MZO<9mT9-@4CHoH+50YdJXRu zme^`!E}3uU@J7lL7}**xp~K$Q*)UW^bL7NS7UwDzF|x1vQZF`Q_MzS~If+a$Vk12m zFS7RmS}L%HNVW;oO*6!#lAz3E6N!`Hc?++Q@tR?bVu){rpCLJPAX?;+S4Oj-03JP& zO-&r{8JJp@3*bF!=6Sko3uW>Lt5EM#NAy-$*nwv}6dV9lwKrS-x) z>pvB9M1e*n*X$fHA-=S*2`=2OHN|Bw&Apm8>ICr>1jlFP-?zS$V*0W=>pIoqLVZ1h znuAdf$-`=iZ>zifbQkc8S#rgc&7#)&fSh+VQioaVfKW`<$U#zSz zt5WCHBM<-;h)NpBy_+2!Pr^JcK-4LmQf`ueG}%`%#RgyWm|3zgxbgVXZ@+*H6JNe1 zHg|VN?VmFKP4KRU&EN93(e8nbVq1|a*%{gDRgc_9-7fF0EU49z8 zz=urOjF+dQ<_v5?viZ)FR+5?^gXfV|tD8NyaasimL9gp&{!qIab4NTs+&}!uAKnL#TbOh4+|HT{O|dVdkxr*mLPnS)p&&af zjgB!XQUuI-N=CYX`b%#A@ItjQE=~R;MD^;_xqPSRkNV`(ywzQmasifvg~@2&IrNh; z7j7ra>pyODsZe#>70L3mKx2Y^PF)`rpf2S8jiPdB%68<71e?hc*F8AUD{yn2%bKXF{vB4TaIdmi>wCek99uGdU=T z-%_e>-r7@J)6*QN@@ZxPJfDahtOihnZYmXph@NaOiJC^<2`ww588a6BA%q+N*wEcP@w<=+xbQhYxQ zFrd65{(B!?U3W4?EShxK^{h-kTRUs($(z|4s7O{;v1krL9#ay~+j+{!}lae}v?bLQsW*A`0_%_1zcbmzSu z6`32V+kMYGX{;%eA}Eux33$zZhSBV+B(xq(QRWiX>|)c(ICZNy#nrRi)nH}*K6cP< zoRvQNffRxJjC@Oy)gzs+D<)v1DAjmd_uWRu5jdjIdTMaYE<3rH@a~Dz4f|x6uX&bE zK6nxH4=~ZC9At>3%m57QHbVl?-Tp7u-U2L+C2Ra1oZucLcyM=jcXxM(1ZQw}2*Dw^ zTYvz;9YTV;1`qBGI!L~`YyaKN-S6G^-glmU=ks?6;=l2`#Q|r!I-7=&CQ=1s-Z zaM)ixrm_O*rK}rM5lp9Or%CN84UD!-oGMa=M)=^ysrHIAYrXsSMX!hpHB_`NsFr;q zmoz$%hOO?d*;1pd5PX~*K1P)@+c|=8Yp7Fbb0t20ZlGOQqa~1~+Bzd-O(u^`{s{;J z=H|ExSVt{$y`~7A+-MCFO&_FMSrEswb2xLk#!aX9*6+#I-09FRs{vj!n;Rv+V7tP^K;`QCfEk2n(isq%pW^5`k#Y|a>SO%V-859b6XT9RT+;sqUy|XJE zx{I%3_D2v0ltKH+bjD`b*$%po`FBFE#ENLh$B9HoH(+&3u<(m`ABze_Y16w)VDC0v)29m` zsqK4-xF`VIP1#*!tKN}U}EIfUQ zu@ySYGm47FjQ95t-bYqud?9}38VZC36UOOv@rp&t>cX{(Hik|L_d&9oPR ze2r6JQat*D`xFdqX;C1v>&2R$NG#KrCorX+OVQHkPy9HZ$5HB+_e^le{H_wg1xy`S zQEYiU3{{GX7|0%>e?>|cA``Ec9h_RV}d(ZvBh*7}f z{>?O_@~Xt9O7e`jpWQ96Oj^MC35AmQ<649;=e-bv&8wc~jSM!~7lbd077kT%W_H~t zlAqU}9QlP*l%zm7XS3ftmMuHjRoATB2e`a%<9%c$AR- zO`|t5Enpz4|CXRdT`LPa{c<-D8~Eq^IWI2CRu7x@z8*3R(V`V?t0dzXE&AB_q+8j_ zaQc@85+JMFU4xVN-0yQZAf4A1A)DevjW;(C=dCwnI(V3;I;`>Q+YM7n8sGRPg0)Yu zJ_%%-f9G?hfi0z~&I!=5KjyN( zByeJ|u#AM+n&yK%UuWQ#JmD8>as368x?ZVhYw_1K;|Cyq8_1N_8=!Gmpm@Tr9#?pQ zo;9KbLZ-W=cYDrGK+eaQb7CFPmCYJoi~C~V=B?p43YZo--%EqBdQv+b0E5%ri>A11H!lgUZ7;9{_mGSm`q14l zMRLXJ0Fy!cTh>sU_DkqyC&WJSn24X<_sN6yUu)h{Nt#m8<%*olh{!S7RLLRs<`=2~ zLxMnFF_P9#-uZiKi-;Y{)Ff%guWu-EKuxM{P{Q2?pEo`Zyfx!4k2W%qp53cM1~cQZUe%p9rKxN^G2$c~Q_6`q8@J z6W10R7H+GMdE8#HjeaM5Mb(zy!JdygPgYj~h!B?lJApYVEgP^#4#e-5nHb^s6L2#j zaXr8w988?Cv^2M^iSm&E=QFyTXxr?AhjJ*r@nQ<$kh$XPlW9Mo@cW+t#PhlZf~=ji z!~D6!)S81gZI={5-_&T=iIIyHa_VU};Oy8)7Gt!VA&uw@?b$5WDtME)Jl>98T}5#- zy4+w^ezWpUBe_nPB6_y2h?8lJD2-$zfe!=B(15Hfbxu=Vg7@m?Aq98apAYQ|tnQMu z9D$lO+HuUi>Dx3Dj9g&@a9orTnqsb_64-C9%DsXbF{@D%yB}-{j{MQp%=uoc5`Ae@ z{Q>_liz5Wb_Nw&*lKpYA2Cg5{S7OB|rEL2$faGMG9%s-ykqT7fyC~ z$D(&>f5FVVEuy%%dW$z5)o7y@+tz_F3uT8N8PZa1icgi+xSLkZBCFI)+KcAg&f6m& zm1BA3>6J4~;l?XJ9I;JTwO`(&zF$Q=L-^8`| zd>@h#8^xJeZY}^9E{ECyvl@Q_qDH}sst^+|pZj2XYHbu9(gR?j-&w5`>M2r(;oSV=P3Deb0Xs=X>$xL~QtY-kX)Y0n;{ZSp;(3t>tV}A#HeR=#yf^qQ0ON*I4sMQ=a7CSAUjK>ub453Nu+C(u@SJG{s ze7B;)rRtOm%-Og6{GtHNrKd_E6^%pA_A4>(-T?qT9BkEMc_(_R_%fL(S9HES;WJ{< zDG8;6mFfm@Ek~8&u^p@mDND3Hb!uSB(|;G2Lr4W7h=1fPKs zoNf9Pe!B$-I_B!O#PS5iGnJhyLE>t1`y1qU?%p6G{k=5aOG*iRxMomuOEh*c@U3@5~5d>FKJ^Nab&wC}T5)E~bDuBk|y1`9Js*Zl<4oh#3}@Za_E#n!f+dI+%G%LWO zuj8%C-$krDN(uL4yY)N|?lqA5U7wnBeq+_j*5tJ2Xid!64_b8Y{=S5WNhneu+F* zO6S~1_|@$MNyx(P%;?mI{?m5MR&t**^Ij0HXhaENqE3uZblE#XpYkgU@~qe>B)A1! z>z4;ERcMO2!gW&R+h{N`1Drk6*vrUf-AJY0eQXxFqCDc-o$zinV1zZA;72SHC5wNjQS`d3O;8W68^^YLaz$(lwjac6?>p=rO?v?@USUcfp6j=h#NY3BW$(JceIAR{=Q23o}Tf~;Vs z2QeBh-$pI{&%>sJ-zyU7`_CqmS4hmBok3JE2<*a*<|mJ>V1+HhB3jqC7IzdTKw_%k zWG{Vr?-%+#gCbsQ`gRpLNKI9l`Z-Hg-V2>Fg-%lS<^r~n_O?-{jEpcUGFA`K2JabY z*^A1j=Tb(_t#uNki0r|EFC>UzgkRO*a~hVPPpd~_^! zlFKRn%^0)lopy(x)Qa7wA6?sST+eZEF`3@3BWmBy6TJkvo%6gBw;(o&>30LEDVh& zu6(K4G?R#U!-Zh1UrIyI~k#P<44Y0INv|W2 ze?~8z*0XitD6!ZbvQvA@Ugx(SDmi{J5}mi@tHKj7eOTp-~;;@1bO$Ggy+BH1reC` zseP+sQ@q4}mB#Pv$L3jnt1|t)cir5#p+faIjGS-F6eP|o*oYH_gy^jFU&XOP$)QsY zKJ<#kLy_#8wXuEm^5AR7KS9 zLZ%{n8}ttBHv~%@=Od%<(A+MF+klTIe0Rness^40f@F1@Ns71olox(if*hwD+5n$Q zFdI+hbNrMp7>p*cmFmj(%8&B#TFpl*4r=f4<B?w<8d0J2IWf&_Md)BMlJpS=}Jj8hy&U+-+=%t%bnExw!6Z=a*tgp@=Dw(H!; zg+*~=RS}7~kM?%@?)~u1&4x)HYvx8fM5Q13tA>j7-Q8nmXv@g_PFKl#99I0d*!tR)vykXW<}I0@*LD66s5Ho}_TKM(b8bL07?phed~274gd?Ov8j{MNt*L0MDn}q&4Zo-qS3rC(!Yzm1jg*vH z8d;Ft%1e2z18{bq( z)m5fw@s>2;U>sxj?6#zD$87j=eni1nb&9VgjI4kV3^}b*%E-IYWRdY)-OoSDNj$YP9~3n_8L%b zwy*hh>SUX)>H7T1SDhAp-`A1bM>|#aWenhlW9q{PyiX6aKkgWI4bbt7o2;-h!JW9xN{PbukY>@BL3XP%Z8U|0>z5_CBD4hq*A-{qRqR2?FYs|PeJ2Fe zmN=k0X5ZY}j@nhgMpP7tZCtkqCF;#@){f)-27R94iK4s3iMD-F&b+3KRfed%gv~F_ z=smlgug~t(qcyBqgox{?w+3v}guiYZS%-OuK>p|_6LmH7CL3vbpE*3^EMxWNk*?zD z^k@^7Cf!@vXAR~2TI72xA)TJ^?heH8`KU%>NB8%P1Zyv}dl<&_ckFtPjnMIfK8n8Z zV-CK&(%0{E*l`LP@QYm)vAsg_=fwEyLrBoI2`W$5G$_Pz*V3#!CBo4<5(l@SaFin(ScsY!cc!T#zA>>x z!&h2j;-Q9L3FSwFBhuAsR~QHAE=0``D<9$ z!1mcE<6@iHlV4|G&sUa27`R|>D}7##nu1M)dEzykRu1yh8}Q&x`pEZav-G|Q6;Mc- z)rJT;k!MD54(aEe&80$qk2&4thIJcs$mI$ zs#H_jlXX>(gzIUS^*kf|xY9f$#$wHgyb|VZN}nTxf0M?-L*@;m`{8?+z*|)kLUztB zMQjO-?3oOmQ1O@vySEi-RwGgmQvE}D$1N6q6AHD^M!+i8O4fCaW!MiqX6#?uC=_Ph z&aMv5diXm_RXT-x;hLF%KLJbTAXkJSuBcCAk?~S%OkYU=BixY~vzs07QnaaX6IMwW zX_@oRL!VY&KPcd1Q_Yj^=S_*o-lL0>mE58iH+G8K!uGAW$PZc=y_>ehJWOjGoY5&Y zXJ}jOAcD+~SE9r0THwC(;2xT1_zJzZNiVT$RJ&373**|F%JiwjADOc zRNo+{?%>UeuJMzi`1^gYf>wr|Vbk=UhYs`MM- zuv3}mMYTDVt~PmUQyu3dFUkE9Npe|ZT3MB_aM|+0UX8>22gfEW6_)?{ZU9F{a0h9x zun*&RmJV;ybA@!9HJEi)1Pw%1CDgEs=1IB=r3Io#6}r4CKAF*|TOADg&yRt)3-OWF{b6W=+bepIyjH2re^{cbSXn(K(N2~*rG7AosE1u6j%dE^a zz?@(li!3`Zxj+W#lY!;*j|*B)Wvc?HXboSyDxRtQ%M_uUYn}?#rXB<8qGnL!gWEYE zUF7HdNFpBM!@#H@yc!JR<|ulyE`>8LVPt`Up8)KRb&Ik#$a_Pew)?1rmF_c^h`KvaJ9*%kh+g~g5ZK5*TfWHxU(T||54Kw|5o*)J z$u|j9fMRawo!)&pnP^s2)OInW9Dv|9XXt-+MD%`EYmF*?yO+>|j`LnUjN-NL3IgUHNYe)h?ZkA|_viKcz_9_O$QmJDGqK;=2sY-$F*Tn=V* z&y3T;MhpF$fl~4B0|@Msj}T?OSg%-Jn~XG+di9x|w|b|ARrWg!T)y%8C0^`;xKmT! zR8)jhZmi9eZ#jW9 zz`Pq4b!yOz?;%}F?IU>wQ)t6gthseO*l^dKcR$h7U8ZS<<+U=C2us!8(+t~rX(<^_ z{=x?l)uH#sV_e`5Bnj)M^H(VvlS5@L_@PQkxOMnaX}cHE9Tue*QL(5}z!%9HPy_Vp zS1?kqj%K`MV~T*T>F=376}xk*EJE*)ZS z?xC{r&_xsUsx_H;!jY88wHC;Up};wZ@oH+qh?M;)hg4$LFRNR) zd&?gA0b%xgpfi+>b7ru$08qP57vYQ}(wPm;6Znnk>v$6zTqzub5%3kU{u>R~uA$<2 z0p*G2yTmB8E)O9U6_*v6$vS?F1d`lkBQq{K>&`$ilqw$rStHYftB)<#)f40{YR5r$ zKLJ?pn;QxRz#mCJC#s_)O(O}36wTQ9+08U}i{yKJ{IaT$r(qew)b|LMk%9sbJt|`F zbACjdx~h6=4jWdIwQWIHGSYN^jWcWGGWn&jlqCa4KL=xT*3)-Hp!?{6TO@qQ)i!kHA`zkZC>uCZ;^HGP>kb&ob9zFjr<<}M7759bT?PRpx(4vZO5 z#yag}Ar*oA_qP3tz1}R(kQGrMv=E=rToF0md5+9;A^cz~u}@?Uu7jFDBD!QaZ+|YxRH%eH-N|8gb^U=4+Ij`VG#&~J z#E>2U24X-D<2NgM|Lc$7`L97>SpgQXC>sg*rc&#HsJ9cOzpDHflHVf(04w7nX(S{) zojhNp8$c6+{{`n)6~T>PWytWLB`DrELsSs|2Y(cu{|g$pCp?q zFp*kx{G#&T2n2s2~3zs!xb1OUvm zg#Vj3{-X2mk;Xa`1`T&GaU#B#L(i-qA_JgAAu9e7>c0{EJK1-lqolAe79j;4xi$u4 z^|KBc0Ftl&$md_l2py1IcA;h51L9lRR<&{X+T{@YN2tGr`B$=wAZS9McN2#GNzPiF z4qowx-VO=lA4LBPSztnFq~aN)09sL~5q8-5i6OsZd+DIA=MS;}sf0mwfhKYW8H7I% zOyk!}WQr^95R>yQ1OdG6{v;XWOb~RY>DT{cvdsO4BSNb*9?^0mZe&MY@DJwaf5eAq zf^CKkjK4Yb;7s3WhN2|TQNl@ul(Ly9!~PGQ|INk!OAUjG7o7-Etee*gx>4Y{A2hWr zEQIb!>4-jIvi}?4KXm_@%#%Ssq&v!3Q5}2>GjF)8cmfC`W;{Q-Unm&6xL#vAtoS6X;vO&$P;($48Uq|G5@>PA3CE7mesRxjVqu= zyWF;XmAHOTGiU%@mlVd=kwpL7Hm}!mI09Vfk*$2-LW=1xKJYQge~OGQ*lH#RS^oCFAuEF` zXKKm0`TCXqM#cagvw8jF=RbvpG$?!5_82UExpX_tyxg0!5U29}i@V=3oJra!-~Smj z6gs4|FkkV@B3cW#U?7dkgdpgvHrf@MgjPQ( z3ot~1p{tsrN6^{!&yk@}J|C$Fg8H)QLk+U|7j|37XJ5U3aM6Cykl6ThWJo9cFG-z= z0(f~eyt`?b8Hu9U)B9fHb)6&GpG5;$APGW`GKrtaX6Lj5II8!Z<;;RmMOpte8PEYC zvvKtRZ>jf4Bot*(coE5h{+;@V>T6hG(1b8JN{VZp%S6VwSK#jI-?4xEer2NL6L;ZZ zYCvMv+r1-D8riQXoL@!%jReve1&ujBsrZ$>>}ImZ=KY;8IQhRL{GUY%6CD>5&n?E~ zKnbk?o?KGzUxVPB_xvjSpCv>S!WZMksVhFH&!`)GOv@xuzl6a7_5C9IF9a}UG`txBTon(#r*_4WXZe<@2q?yCdmsf|My@J^uP3u z|NZ;_a8ESB4?GgS1E1cV`CkY1!r}zd{(Cw3jSTAf58?l_cx8gob)u`QK^R=?-xv}M zi=lll4omhg`hOw!zhVvg7wP|aWAGL2Y`yE)hu3`qgM_klJNRmiUD{|otcMrYj%GV=a?@~@EJmB5Gspw94`noJ~UTS*K8+FgE2 zjoWp%Zzh+2mfQn?aS^0Y1>nQGLJf4aPW+YZG`8jnfcjH$mVl6lJBH9i{Ttry1qk1t z{grHwi%t!I`-Kei*K+tD{{Cw{tI-3{=h^HvnyX+x+fA<6-@2%@9m>~Tw8Pv2 zqc{cf_)y4#Fnu_6-+14^)582S8TPj-clZn)5rBy3)f+k>4DJ$wkQ>(J-Nxww=)a^h zx?pdFU_&&{%qVL}%&YBhf&e5|v#*>Nk+l5)UWtDu%lt-$VquGdwTnaQrI_ymuREDNov8d>@{By^R?q8gL|#^9&Z0=p-d;}C9?q>WUUf0X?SCTw_EST)7`adu1NZX>u(8T z-wlA(1_0#o3ZEa!e;X z-+G`_e#smE9PGci_6=$V*hfQZV|<){#936MPxQ}|m(Ml<=n?<`-a94Xhuzg(Sc}*U_2G~4Rz$b$Xd)%y_O%3bOmy9wZoWovK&Z>6Pw^t zzIJ~(gjcRmZg|hnwuFO!2T^P1^Z#tFH0B?Y1 z`RliV@{Ij;xaU-tr68SEeaV$6u5)`3)tbu!hsGPC2*WSRn^o|_DwJVAo~r99Mn-*Y z+PDfn^wcd1U3+O&WA$R8*t^&n8em7$=Ah*2J8MpsJYd6TylYYam~&vFSH-rg)dDi% z&3R(_1 z%uuC3wD8;IG*KjNY>pO-5Z8_KQk{w;U^Jav%HnrD)M%=B_#!I?S&km){z)G9k55x@ zhm!ZNGef9SViUrU6QB8D z?Oy8T-O7R{Bv{@nuNNI4LV#gQ)`W*y+5Kw}6ABqv1QH|`(ii%f^X?T{WnG+azha2bkC#zQgL*gMbJHq>|1g9Qn5ZFGk=)Y;3SLxC}uF+0cP z*oWUL2F1Vfmk{{83(L@zG`WGMzIxxY-TE3E3&2)AD}jnVkL>%Xf!(1WXBAtO0H|{z zl2T%kPR0RlP0||T6*=1zsY)5b8LWlQSHra~^x9UZmM4}x$`wP5IM9SWMTssW%lenu!O9B4SXPMr%s=MaHCd;y`R;!bVH?jhppX`{FVNHgBnL(wcU7D-36-fjtU-M+U5>jeD z4^hq-o1GU55S&tPAKy>g$SCp~SU5LPd)mrvC;-VuUfz40z5RGqf@Vi~y$Q#-J+oXF zE=6s+ey^6qtmf6dLVR1y7&qPE2$DphHA1jd(F-(@=)MBw}YGbWJ7IE#4*-#eCdyWUf67cAT%w`-AZ?}d8F;0p@uXwY&}Y`*ENIw4mcP?JFT z=_g>h2PeUn6IK2tczyn=HEPmA!EqO0yB}O&MpRAmVNBXcaxXZM(sVvZl<55$myJD= zMGx&jqDLOqvwM~65r~W7tJ#2C&3?hR7^lD!Azqw$Nm_i|X{Ayo>=2h2Q4Gd}M045~ zb_I6rAs+}jY4DfIj3Fjh`Y>U13tp5e518fnlqY{ONV7NKD`#1pRT|IbY>Q6csyPn+ z_AR!4v$Rn+1gintCyreLldqVKHu@z60<2_$lXp!{Rs{Adb3c0tz)Dqprxenw z-u~l@1358o3&{uT_;=7hC;;Dl(qF9O^rds^dhN`J+r9aevjDrQpC-%dGSXdk#3C;A zqWYr;tuj*cwVGd;AMFqhx(9l_4pRSgel=F96I&CX?R?OS7#8_WjhD3UOh|)uz1?tF zO>tT6*o~`E18N)t5gUOT3-Wcd74cBM2MgY@g9dcLa5E@8uQ??mjuq0O3OJ~5Idv(R z_hq9VV&-T#S)p_(xHA`w+YS_I0t%**zwxWH8;_h$7u&EP_$FtTrH@(OELTInNuNXd zB)W)7_|j?*z9~u~6zcT!XlWd?Zq>gN`MHkzm}!-fRqb;Li?yceAgsoyrT`oWG@TMG z-0eqKu_gR;Ym>KBE`Ro|=w0>KtHRIeE?J&r71uW~>s=vx+}AYbxz)9G8nX?6Xq24- zBB`6~sSU%pN)K+OzH4)63`Ec=3_y(Qp`NbH!FD`ZSWh4Syx?pt*kk^)TPSEgveDZPZ<0lp154#*V z`m|(n9jtI;M4FXOtI~OOJa==2qTWIq&9rK#**XlV-~+%U_zx8_`8c|7_NVLBGs_rJ zEA6nR;W43uYCpkyPx^hc*T-+PahOghaqiN8qC>_&+QVU30zB*m~^O15;V^bhcz6MZC42vOg_^l<5QIc#a^g|jAT^IX0OfA z9*;o-6vIdYsR%{65NYBj^t)ACi6S(_5;i&%I$e9+EG@aS&y4)i&x)Vx*mQ>Uwn>G{ zIG`~0M;3>Ww5 zsZKXGn5Si+porC7gvuv5h@!XYHoHfn3L1wGIcI?@Ciz=%tTM9%S{(HWzRMd$=~QH9 z6y*L1G}>4wH0Hu*hwL0XdeQnwV{&SeKVVc-|kC0XIsVw`uQF9-WA z{0-kKu>mThb;Ql_aJo*UOoNJJ+mv7LT9p^$#<$0~w&Dq`TdZ8i4iIINt{vEw(K+*9 zutd;?Y}X3Wu>#2BG>2_YjmDixn#|5a-tdklJKXjzWm1 z&tgKWqX!c!>6vI0=DfM=_u(+1CDiIpQJk5OC68ySxzDDH<%ho7dl|%pEBbIU5`Z;S zPbB#D-KW!_u~FB6%1RUzw3z#0AQ-H*MWP1Tedx8f7UnJ>+`J=t-nL#gyVL1foCY3! zp9M=ul^30ke`aN;&*$~*R;x1i_1kNb_ztV8M;g0C7r@B~+AkW;%c6!t^)UE4dd_7>DP5W+?J&Bv)?x$LZKyMFCj z_dSt_wzz(KD^1kiju5jAR6jw&hT=_o8eGsVb^m^8``Xnycap*0q|Z=Q6PL`RAXzof z??NlVt7Rx2_^4-%Np7I!;+qT~)-`lhmlJmb+B}b^9NYNaQhp!c)w@b2L zKgOZgn9+{kux(wajVE^EgeJM>TyugE&D#LPSopY? zd`r^_h(V-057wn8r&JtfMxxQt=Z3|_2^}c=QLHLKB!;P2AqvC6W}hWdG(-|BhldI; zauXKA!U##g+$3>~mUr7=Db{pzM0qENtr;Ca(2MHV@mGZ3X{$ykbq`t_iYKS__@Orz zsqeCP$v6uyshGdKhjkn`x5FcbHs?fFZfh-4^Ao0xq+*|(8JTY4wc683ZLx?7`4|LJ z#&}eJzpA&M&~Qdz8>>hwHN*VFgoc;q+Hke};Y^CHX2Gj+eMG#Z7Pm%O@$5j^7d!ig zp$Svm77?bA&OBG?oGai=?K}L6hdpH`hu_LcIR(uW$?{}4kDX|r4t&z8`o0ILyyiZv zyR^m9mU{_#gc;}2Ox9p9*$n)u+*yy-F0tMg8`{DFE*md1qio5yhch{i25|&HE*#=C zhL@O_ZH9rZ>+JyX)e;u&HxAq7`B)R6B$@d<-_FX|lS0vERQ5d$>&*AB9FJTF zHA)(x!lc+^bc?0XnocdTyvwP5FvDwuyr1!g=rRtemR>CrW>kdK&s-bdm2l1@Vbf3V@n^V*QFQL#Yh(HEVPvSfz!^;50uHm6rgNM2->;Hu0N;+)lJ6*HFF_qAuekKER z?{+*j!mF4N0}1m72~cPv)mYz#5@xo4wMs^r_-U11nEX6|UmII+YLZI?z|CX7v~JwJ zu5Za9OKxo|Xq`$4ZsCKIixS|(At=P{s`n_Wahsp`&6y^b4Mn~g4MQKit@wRGJnR;Uu&R8gEk7<#KweC0YF zLNdqMOoa=rok|C|G@ioT&cftlufPZ?rBUMT3T61klx5n&VIh9PXSZ@QAj!+;fa^K$WnD5DA)uNq6v;LtBcNwkl8US=H@D zCC#u2VcY3D;xE4QrA*S8j#P(s3I)ybA@4&!)05YMb~A0kKLL9X^N*=xzJYX3Uo3Lv zb#i3FJ1b%f5=~6#wa2Jj$`5VoMr@YjV&QUzGmFJK<(ihb2TE7z`TcAoSf3oVsOY-v z$Lq%wCw)MRLYZI;=~#;~IwrNP?yA#Sc*Zj!h8MEZOuhED=e;vJ-P5_(F)->Y1(Iw{ za^%r8#=Jv*GZxtfYZ-+}#*OxzonrksQRn+k$Dg-r$aQQ#~`Eh=*BDY#7!NC-A^(!?%S1glshv*#y#waO#ujUqBUREH@#%kjURw~bqx(uz_5pY6W*u^Hx0Yc8gkIMX8tNNrbTwbYD zqOyge`1yIOQ`NjoUY}@IS@@A%-!c4QBNAer^@3KNJpaWa<7$i`e?ce6-#Udu)BwJI zOp@uyVw{woqhRd;m=@B37IdBE3cbqq%9K{@U6pNGv7w+o1|AGw=Q2W|CcQo$QT|1F zk*Cmjy<0yMR1VdmNWi7G$-a6>nhMXQWdUmD_vB&o?{J*qrcK{!lpLRcluN~B`UK^e z(}jwmY{C~aUuxd^gM3_+v7n1JfJzxe#0lo$K?Ec^*hyHnAyNU=Y2W7$0YA3!Ff?6|2kRMuU!VCkD-N32v_~LD#dq*F1JBh|as` z=`2gOoM)kBZu`q@iAW>rd5VnyA%U&dJ0~evYz-XPOc(W%Y9+UZP|vzz4%p7;K`I0& zi)x$VK??ojft7aq&Yu8jv$Lk>-H@sq1Y?As02+I@A<$NV1qaQGj4c*Nj?kMTq0Fpd zwYW)UdJd?3H*5y%nopf?rGRc*VW!vUF{oG$)bBTr6LS&NZQDsPw-wKq+PvC4hU9fA zhz{)q61jjxL?wQXqx+}NQ%M>+Id=vWxa|b}z<_OTFL0$Im zh|1oK1=fFi!6oG9Z`(93Oep)5Nu;raY{3Mu)4VdRn4FcXK&UUoay%7Ak(Xy0gKs92ASN%aY{*3s1{cj; zwrQ)ac>}xFliJ5q31&I*wB7nIo`F*3?ir=t^r%5+IrKZ; z7>TybkJS&;slL>t1EBES#C{xhm92OE2D)p-Jkv6FqSZK-Nz;Xhs{+uBSN4yb^>9n2 z6ciGSUYfBZSj)wX?!~r?PHH_acoisyDHl!2!^!AODj5d~3E0vlC|S-R_yZWRhpyaEfLK}==dG&qucdkM<Y2O*_wh@*!(Uyv&>`*dH#gbFAdI0VClULMR1`gMQAP?4b`s8 zTUAP4z)Hp@aq`b9*0(+2!hML4v^D+iHSa|($fW8?V18;Bh^UxeWQ;rh6L4V$BP~%M zS$_3AjfX<~E;P?x%NT74^*+pCL5NOHs5ypPP~%0wR*3W`@5ykHK8k@J9hH|%M5Yw; zwY0TH3ex!exIai52e`yD;<4v*qzBE*L;@Hly5b4$1!|S0CGFxIMCh-d<9+6%>REAT z21mrdA~sdgNQn?%muhGo8OL-~Jii`B+bU)uNxUp`qRAUnEFSNSu%8*~1UNkt$GqI7 z#|kUUe-L_ZSc$9?MPR%OJW*um>+;}&%Z6+w2pc4jh($h9&YW^kv~L^*5a`Tz6n1K{ zn-ngj0Otc@Kr}Tz*vs`gD_b2a`!fwA2Wmu>d(*;d#_dzJ!c&0O(2y+3!uee5%pe&0 zg*1lIuBN@Urv0knye-2bCSJ#4X+m{=`qO%`VcAW3QNl}-6A7;XU(&p1*nG~fydHt6 zuWGdjk#*{gVOYGTqcbu>&0k+%WGz{TNT&t%Nv zdF-M3=fj_H=lkaqBedzG&|4}5*5yr6P2?rS<=f8HHT=#w=`vcc>_H<38s?YYDUtC> zd}|?rMm_qpl=}t5do}nZ#*NJGwe*3Jlu|ixZ1nk?cJT++PjL|*Rmd9dPs>87JSvao zO#;^Rq$s(K#afzI6@USft2npa$>z{UI-c1n2I1Qikh)|P3LGgp#+r?N`>bL^r({MN z|11iU`TGM3g5|i^Q5GfoD3~0QInY}TH->}8XnSaFEMBz$tpOWdg4Ix#V*5*l5XsQ@^(7>IHIdI6}73^Q^-7QUULcZmnkv#`%l0nO{RH1YK5x1PH#yG!ou|oF*rA# zX;W!Q7B|kLjNB(c=y2;5$<+@5L6OGSTtW^U3(H}py^uX-Wu__tdETXAEA@LzTPzED z1B8k*SzJl^r6H*xPU=>ZPCB(CS&QPFAftnWW%Mz;+;u7;y9%D7C30>N!yWiw2?JF& z8XGy06oW)7*aaksk%l4RT1&I$M2RLcTPc>nZ%SWPGJJ1>X1tbD1P05sDL+XK00UZ) zP9%s=RLrWK8@Gvkt0-#rZ^U_pZ4GS|+B~!Qr-SzPE+d>+(55gBpRsbgkJ5az4vgo0 z?Y+2)IAOLQmS8rnYH$Q1n-|LV9-hU>pH&|`E71I7U~(5&(ig738oNk?0=^c{>poK}*=AN{H-SOR{vokB4phJte*CGCz^!-?g-=0wXyA4a{W!xtYv&P&=m zkzQyEf7AerPz1>WD=z?;Lt=Ld;F4ln@Ee-bkXZFTiGL18=UN z-?esc`t41v=&jvD%v!WwoN9nC!pdU2g#6oIed$clNIw_lA(CDgMy$6f<-71cc~G&_D*JNOA;NJr=%6iVhWeR|_PTXS%FL$pRGBlReG zo0}S1FMDwIcw&Eg_86ITredMz_1OKl1vzLaXjnK{$XeT9mL#D7n2-fI49JQcnQ3tS zc~U{|6szjy-xlPce_N0PF+p~M*<%WAbYJAi&E|M>h=Jd~-v@v36wJ$AW9a78LA~Rr z)E8?&JUWf4pcZ%&$*fxNN^$^0fwbb`Hf$MW%w0rlW3Hr_ZYm z7Q8bic}Bd#31+}}3!L|ey<5%K>KIIUk-gbe`ZoRd6?LM$Xv&?`kW&=5e z`yfr(gj*nG66r%y7L|aQE~2##D1nsHT2`!~DPGWmg>@o@mOWj&A$rJGPgKdi}Dq{?Y_f-gu7 zT=w;Vk^cZxn!|kPKn`x6Sg#1LFlVlh?qE)L{llIgN9h&h=P4z@lG|b_tO8uDymNJq z3YXA_yD z$2I9W@-Zohi=?{ChB#K|<&XETu0ylP)3 zMa3gYuF1^Nm}ZPrv1n{=W1jC*U8B}1=LIdOy40i^M(8tvFB2=P!wX;7cl~=A^1{Mu z-^9=urj0=%0ixqcXxaiP*QS$mQZl^Nr%5dzYaS>%N zmeUc{@}LHf#bq^euSYa!9X_!gg;h1Wx*I=JpEMDr%^Z4YdWz)Tuo4H6GQRjuUy5Ou zgQx3XcrjKRRz9+}l8#XOaVt9u_7`7YNmR0-SW~`@H4aBVL7KWQHDE9uFZY-LR5T4b z_0Px4D3h+yDoF{qF3P5BAOywnHb+7v!eKYU&<5Rk#!zg(_woM#X1XD|&@Pe5_ax1$f z4ubB>-YPA6XH%sZK4v`*Jg^I-4PlOHuJFBJEDc-(9xWeC&k~_*ktx<+w;<|&kXf>y zu%Y#1`pRvaACkRlW_LQ?y=6v&WvUG?X1yw7vpau`pf%C|0KYVqO26hm=SZE)2{n@T#qQh1e9)QqvVC!X{PZ9XY$(16li)>oa&|Zn<^_ zt6ti!46*dsR`cdOxdqUAv8g3!KVJ>=0zj-Sr`bWDTi3iA7jw~nsX(xg+9}?ad-C^)h-wW7 z=j!|<2{$!r^Lf0sI_AcJJG}YU{nyfKOL`wZ?7af|K7M1^`+t)qzhBwUuuRsT#}K(fgV~ZI8={X=3vYenN*e_MCz6jU^7t*LH3FAqcKq2nr^T1IZY))(>!DNDp~g zVLCvh$)mTVSAd5b3q1m$O+3llPidooqxp8g%yUTxphqm~ddFHUT!1$>9(gTSQG|?NXfzl)M!P)HLEC zEm$yy2)NN^2r1bDUFW0?s%l$cGKWT}G$Mqc)GUNj@YCz_Sm-p=bL{N>o#7o*@AKtB zT+{RA%s1jcJ`#Xx!hN5#WaUluK78jhEm;7n=Ftb0t7(=jokYvTz&dqj#!i$lDxZ5{s165~l$g8B*P0U_qt9SYnhMN{>jT8PE{NZK^a3Ou{2SENH+Tc{NmJSySTi@WS{{{Ui%Wg0ub zt>OXR^?yeSe$)+GqAW|$X)zY@D9JQL!KRbPbuKKFVVM?0)5@ptn#Gu1fCn{~nv55CZQvA3rh3CdByJi_#0Qm^{2DOVhKQ&-k=et5 z+7)J!<5|sq(ze_*;rZza7?EO>cZD#+yc_Tq&FU*ExuOmR=8%I?X1ua^Sh#4K%WDVc zK=p7=i0&V}Ln+<>YQ;Ky_mt)LoV`RGFa%1dM=o)JcA86$NR&H#%yv1V%$j&(RaJJ! zw62!aAxv%N4VUHtEa6=k8&H$>Gt1d|IZtWPs}qXoT8@OoOj@-B$CLn`NU~%>rogK+l;OpqCXLCp5Q7 zu4}dT)EslAfaqjr%769R3rn1w`3Y(aqf~%Wn1(>`QygoFPAyD6z0{TFrjsqwM zaxyDy3Ovg3*k+Mw6}Q7u0<=fR(Ti9meah%e-#sA3Q7WO^ zFidlcwLbF!60Y8RN*1>Bi7Dm4Q%Pg22vanS*ERDI;$@3z#SZHh#+>DCfR^X&f64VQ z@apVJYmURmRHt7so+YS+0l)&f5f?~QSXEXZxhjB?_xY$zVDCGXA;Ae*CioK|ptjihR zQB8$@A)xUKBDmDalmPhD_O}m2Ssg?n_0?5_q z;^G~lh|xR*vL+CSr49c8NWwCrP*KI{=zH+ba*Mo94~u$V?9}iOQj}5#Pw2o6))HP` zkjk*f)=<>Y%sfOAxkIccKt@@TJnLY0j&hB2V~4rdjNyFc;KKno5a)sh>j^I}NM%@K z>nLC}g<%edNT*GV)+727FyTRayg?oImaOnO?ML00gQtjD71t+#*MY7!c7H~JD2-59 z6jG*_c6)FJPq3B`SZ$Esaym^e{5UGumIDO?XM@)^0*KWGfki55cbdMEq0pLrb4SzK@-+$Z)$YaL~4oQ@rp#o%TL!6S*V8Xf}5EvKhaV;Rm+ktVGs$S z-JZ-f*(cghVVcw2M@gmMhcj9(8mpfNu4^4NfQr@;0Gb`7ZMix;eNKyf%ZN4KRFN#Txj1fwcR$fhI1yw&udY)6k= z(e?iT+((1KUBgV}M*I@{43Z5!ye|=N_zM2SFM0 z68%yjHtH)Dt_X`qal9iMU{MKFGaJ$yr9_#L%78$`Y>JlR*TXpVV;MRK&zP2~w-ghk ztXc%sSD*dIhgP8Ai$WqUHh56oCYZE#{LK2V-vqznvJ8kgg_!w>h+9RM%d17oqm&}c zgI7{IEl4D4M->N1tvS41e~DcpQ!61Avs2~TF*Ct3aTnD~6e+ z>)hWk!53D$O&4>(|g{cmnMC2Hy7Fb>H5IQ`cgkC!#&CmfLa6OGf#Q!gu; zxDUPU#`u++{v8hdO`k4nz+1@UW9bErUL?zTYCDr(4Gz!ptMzd{TAUmloO`hfUCY6a zXw7^DzTcCMui{u8c#N->jv>PB!olSTC^~p7w zgV=lV0J+a^`^0bfr-8)Rmh99`UjG2D3W?SqsCZpJNvDQSqW3uFuCMVdaT-1^|HJ?+ z5CH%J0s#X90|WyB0RaF20096IAu&NwVQ~;3fsvuHFmS=qKv3}E@nHYj00;pA00BP` z{f&Kx`#L2hB_LP%1>Plfxzq~h*rvh-bLgS89igoI0lW-EtsDK0eTVyZQsupU9v+~s zh$})m+k61OX<>5EL(5r;O96TQFZh5>#MO0254=z$3@RU{zG?)am1T#7qxP7PTL3;$ za>;w){Q6SJc4Z5%yf6fI>Y%lm!v6qLLy}^3iH^4Wc?KS3^f)ij19MS0#T5< zEncpfnnZ>H$wmAa%Z=wZ{b9^pA*x{NI!_;|U$M`y-}`+%#Q&WyS06_ z=nE2KZ%9BCr8v6PK_^v}ygB~>*fd1dt_7hp2dCX%MSXfh9}T?LjKpDzI2$hu=DftJ zRRloZHxp`%01mHc{pQzhv~v_oHUV7MM^vxHzi~3@kmXQ)KZwyr7kB(Sn};&0{D`BF3C3IMY9VKfSna`FLXcFf;QPw8vh1(# z6?U(dW!rMYA}ZBqNauc@CV2wT!qS+fV2Uhp(>`EvMGXTLq^&@+S5~iAYN@Bm(?`ms zs4GNpfxZ^;%)$QvMWlJzGvZTgK}p+uoM`hK7WILvvC%RC7PP5!zsE@R_)si2t#UsM zQY6xE25|1b5Y0j_{@Q2uS@s|7utClu#lLe?AP!b4E88$i7p)fj5gj~@tF{Hg;uk1N5byfWN(E*WvRJ@cRpC!#8U7-)S;AWC>N@DgXL9ere}_KQ zuh|FKf3RVD{*!6&~DYis6}Yi zz%-=~lF#QMo1qcq1|xV~+&(hV=q-M^P8RGZctnA*!COk{&*E6r)w6Yr&mH)H!ki3v zd;Vf0PT*Tm1sRA~>-!-45B2N%0Fb%`%NbiRQS~wOxX>3|AHX06QL@UV4V0$^cGq^I z=2%irwF_r`I}E>8zL6tc4%PrP5$0Q7JNcN&IZML|jlM1yITNFxtiO%SnaO)}UazUS za+2baWxy9TM-J`YscV>NqObG{D^awc)MBMOYUr=|I%)wtHFMKgcU1w)Mzph}*jFW8451XoLa=1FeD@e@G!W3=zz>)&3JG&-xU zH52G>01II$aQ&ez<@+N05A}-|-iN-0YQY>?zWlvkv;q(e07irqa}00biiKzf{{W!x zGXksvx%nE4Qp?Rqj1Glr?Fz)mHOXkGN@0ENn0+*A28IgPY0e45fXv?mV0b^NAZJpjjh!N2+$b4 ziyGdreF%=>bz)Q2EZ%{93vcf&P(2PE`GhGF@~h#@Olh`|nH&WM73WhGRMNBfi#cYB z?!=7Nu~?RKr)#V43aL>?$XJzh^8G#8JXCeK0haf9V*Ob`{{V9nQZ!Pz^rE3ytcOp> z-YTl?{R@K4BZi_Es6pcNKRfKr=|e*eUVeMPLu{bl+wu6DCQsP+*lYb&kzeR+a|o`r z9}O(aM+2cR&x538qxU^xFm%hV?`TR@zm~oM#l8pu=1nuJyN-mxKEteUqM=)-&Cg z+(TMdA@2l9F5vnPx&;Lc60X!rSK@$QOLG!*3ajb;z-V!Mvg_yjg)M4_qibJzaRuCX z?wD;H13=OG6@!qVJR41{I~@pvK-M*j`Sb{Y(-JS^h0&g#etN+GZP`E>c5KqPM6s9- zlc4nN_>XqKW1nIErQJvL1RDT#SU4(Yyv(nS9wMr#ZCEUL16??-OuHZ>7v=p#qr9#T zpTb2(qQ6~uOM(Oe(l@D0tkrcW1I-Zf`GYM}nBc%lKTZ4=h!KA&Pp2{{RHe3TnbHuMujy z*g*5v1^U3->hJm#?lE*_{7kOL(vf&Lc3aP|Q38pPBN%CJ#|q&%{vf4JDY)$GoSn7I zVO@yZ-94T^W1sblA8l!PIc6B+w#vSN{Qf;C%jb8{Ic7DVV0EY3?lM(ftOx?Gf?Vqv z2VeS?3Ygt^qsANV#e}sSjFR*5{$~K z&BJ%U@}fN98|u9Iq?QmGWh)=dr)A64`26t;7OL7utKMVn(5l6+Uhz*}MXYfW>WD(m z`;S68E%Rl+@}i`GzOS^WodK%lEx>84WjJpxtGz*OEd-~_3OY*y3cEgW9G_4$>o0sw zzx-Vv+AN^Ihyb|7fc>JxFriBEFBpP|Oo?X};u zXIMw{Y&!CE=dt~ceNXhuU#5VRjfup(yb}wg^M^fS_i|Cw-Vs=Cm}X3AW-8$_DbF~+ zKwp+8S_P7<3cz}W+#am}FLNiRjEBpbj)YaT#-?`iG;^l}2kO?MsV zCQQTVHbkRMBfmtc4#Wvc+MXqG3cn9^>1}w8xLK8OzMM+X+C3Lconm8GiCOEalsrRh zH>Ea95S|FT-MF2%K(A4(e#}0m{{Ygge^SJv^&Q`u{T%g%^dnnuA>IH|R-8n;!eM|! zhjMHanQO&QEikA8p{X@oc28cvc;=|tgZrtcDr;- zum#oknMawVg1!hr2g!pTfc=2VSZdTv(mG}PjDT74Yvvb$tp3t$GS=cX6zXLFIXW&0 zV3s;yqhm?Tqc@Ok^e~`5l&`eQQNhwaVVO?F(vrpApcn56Un(H$twqd4aGryY*>}|6 z`bGV8BXB-={MIqL@fKX**>W-UxoMqcoXm<`<%rp2cU}(!E6=uyQ%p*Tegx>>Uzuc8 zi~R0BuBf^o?GhG6l*TAJ2!16wZYu~PCX);(c-h1?fBrED3<*e}4OrG7ZxLFTSquqP zNyHN@6{%G&TIW_mG%y${W}z2ONGjM2?SB!H66&3z!9}69FKi550j>gu>mbvUhT&EA zj7yxT;4rc6eqvpEL_cNUQ-A2+*3v|RD{Gus>36@km>{+JDLhuDxUC@lU_$=@aem7( z0+wl0t^E(;JBEq&!UFXANsv)!02*(++#ZZVgnDQW&;(U5j{^hO8Cr7^CL0j*%2T-FwCbuJNWMh z5@bhX398jn?p+H92~hSg0PXE@bqfrRTe~~{XDn5$v*jv?=VAge7!d4SRa>4&sG~IU zaE~YKv+94LT8n?HY{1YTQPBfmdx`Sx`#?km2Mi;h;7SM)z-~K)<;Cq3gIE%3Yvk@y z7Icoop%4*~q$%X$CMYdzARo+Pl4{hA1w4~+7d8R;iYy6MS!>I*xq&7VJqUH17z}*J zvgo!PeOy|;&|_1m0D{ZB2pl=@1{I07Y`4TBl{rKI0I7bcJ7zrw1xub0PO5Vna+$&M zXY_lA-+Yq}@E4Gg?JeWO~<{`{X3?7IjAe|CoOep< zU5|t#5=OK>z%;Smc5hTl0XbdQwY)^<7Mb->?x0MdVu*H(1uS6vrCU+Fhr|8E&I2X` z^9ASh=R1y|a-3;JJ^1q;OM+>9Z0?70}}NfZYY$IdUu$ zemgywfC!vCLGM}xtj;l(+IWv)Wnv4*f4p#0n6})xYez7f3wpVi7G#Mjixcv31VAD= z5wVIDZF_UUIj$u&V-dJ)7BSH;nmclM<}5}6CZZD(_o;b)uuhfszL7 zr`02%=|b7uQsVcfun~}tc1HMP_C@tS&A7huSebnAqrv={w?kC}$oMk{{{T->#}?*i zkyq;}0WxZ@CcH+&h<(cjn`Y|D0=3ejk zsGOxcyguRghwrVo{{YAfN2T=iF2E;KJ*9($;fpqol;!|3$tAJZvlAEqR&RS<$_A=Y z6IJmQgE?Bb(E%r@J*m30Gl5+ee7J(q*w}xUw4)YmG3Dgc#+KxkH+AERfw03ZK=mU) zu=1-Gl;;f|P5i`L7AZ&usAYk-WfYE5rLfO(7i@S8kmFk(nD~MWfYNGJw5!2VqTZ3J z#G%k!Zi#NsJz-P^kOZNoxy(K5Jxz(o*J58#FSI6I7#4`%>~rdWn7^e#4|FyZ_jEu( zR0kRtUorlKA75uqu?hzvTt8WDDxHE@{6+zBlnc7)9CHzCF1VNH+;j4|A>%e5YPF0p zsGa76)pPkJq)~3>v*gqBIWB6Vcjxg45beJeyMn?md4!A${!^)c zrty(rX&GIbj-C^|ya*ZTOT+&Fbd=z*Yh8y?-8Pbe*BD~fJQ@dZ$ibHtq1xr+>V#|% zzdhoI;qwBWg)T>G=fqT|LBqd@fPxkyVtX>W4V){e@XU`Gt6e%Tcv4u17X^h6fu z;ws;Js|86;kmRdx(Pd32p9FSjy8i%X{;HKf7XBn%zbshn0b!FDT;+lU2yDZA-g1sy zvn%-00kC;%i;Mdn`kMa$C1UpdEbDqu2fb<~guYEDk{OHORNHP5>Q0KFT~Rz@VZzpK zj+fK4VX;8OYR(?~$1*2XOnVd-ntXrf(r!vF*ItX-ZJCdkPS?}>h1{r_v&q^Bgluvr zt4U5sJOxNto+36~&fU|m;SR7YPG)K!M*3f;Td`b4Dhs@a#ILk+yI@;zMRibO3Cxuw zt<^vEL_iA|h_UnH2vACMlA^R>fYePEa4kPEKA>q$rMyO_&0Gtxbb6Bpl}I4Dt|)UT znK`VnaFYzl8EFI@ zAEaveSZ&$-A*(H=&p;5q_tsy|02Ru>vg5CqPOiqNP}Zy$P8yhk;Sq-**jC=ZeM@W^DSw$`WCBhIC-3I$a+_Ik1>mR-SVjwhqMj~}>=dwV!*B~JAo=lEMndV5OFB5 z3rA7O0s!NpdAOw58@YXR6|RM#vl@P3wM)J?VThGto*448)l)51xahj9Y02u%+_ZA` zajRSwS6NA9HvzumG-z_$7I0gU)m_EEREJa#yU_iPeNXY&@7zX;ps``z5~~JrGd<+e z0<;RngHZJNW>*WNW!^)zRWs&C3>{X*xAtNJ7Ed-$T%to@P`cwzAx;t#EZ6 zJWIBvR9P&%^DX^a= zTi}VXg>AZxuGo7)l1U4p!E)N+-WiRXHgNt#v*@r^cX@~uI8uZ@G{YW7Pyq`Z9Z&7_ zh!I!VxRDKueqPeRCfFW={2yy``yBrOmiw+WMQW`dfItLO(Uiu>S&3m^WCKX&tX4oe zx(R}f8DUoERp{+y9EHl&P@#Y7h#1P3$mv~YJj$@E=?J~jy7TJGm%WZYof&!22HL+D z!P5Rx;70gYB5=wujJkhI4S@~?4*vjunTZ-~9^K*U4U7d*T+gj)j_##_yGA}(Yjpw# zXle}#UTQugI?BO=)uA0Pr)b^KHgZ`VS0q`nG>0P_&oGVV1oY6h2DTc6QWSVI0uEdj z^jXAs7e@wpIEq(?mA85yc)&xKJnL(zEf<+;7rU6^0hmuEyuWFvo|qJldzODV`LV*!vc`CjoXO-qA!JQ4TECP!K^Nu3~7E(%1&;*LmSzR!0 zUr;UPShX#GF$%isQ+9308aDk!JZxa@1s!hES%Y5-^rTg?2ABT;sToR(0Y}S3FMLwP z!<;^Ewpgmx8RT$@@N~HighBIT>7dKrW%E!ugY^^(8_}u4&nSO$EXW zD;q9{SL|~#r=X(7tm?S`0Ou{ZSTv*7w-m6N%8SLke{6Gb4eO~feil(&0~2rifqJ|51qFdhKfT`i7|-Mhr; zU2F|@Z8i0LO5=1Pel9mSYjS%NCwNxup|AeO&O)VbEI920x=}_QZ;y$#5MZ&YII+el zBl>fIXte^gYxX(xKgoT-F|~8TyCsa=6GtqZgoyWeU;#r7huTm9DGM~=Ke$z5@_JF2 zvY!#ptw5U7i<{(XgdPL=o8o#wWF1ul%nuB#r*#-+8*;CN%w$oA7=DUnLhrJ#$5_`e z8t;LaB>_0IsoI)la4n0ieHfK1;xTMJIh0rCRS@qG+8Z5W3z7!gKRx|EAwig0H6GkP zrTrkx2KYRAf~d>K;w8r-;dDW6R#ueNc+4d)tyNCXu>BB0^%eoQ2SdK!yw4R?bl+D2 z9-9;3_oxoHRo)cuVb56k7<9CnEfm$c&cMELa&C+#Q^$FOlN)E^syvs_Zgl<NQNi-T3=Boeu-7IsikkzX9UvG=`t>sDc@ZupQC)0cSlL-U2NSZ!;EjtKHpPIW zhPkh#4DVZ8)}i6gND9qYy*kmEpAZxW=Gur3r&l7ti^u-}D8UfoiP$POK%x`_6za9{ z9TdOGPQ)P!c4_q|0zm8$EV2Ird;tiUtN*jwhJXHoqMFZwE1U9PrQ?#NSz&gmm z9F~tTrw4;p{WBIVm5mf()`#DiAui=@O_$H$fp%%qD^$By`{t`K%uZ-nuJzH5oL=Jk zL^iu?-R18LAQhN?<`ry!1)P+&q%bpe9@xK`lHJaM0OD*AfON;}tRaAMrC~(}bC?7(iK&5X z3&&#eTu3RP8n(J{f9zJtO%ZwrZv4kKt7(|$7KN2yF6Uh`%`^}tE~sxe%HMrL=@5($ zn>E{WOsr_|y}uPMP_7|5y`yBck{{SJ5{lqBXBvX<^uZrj&>Q0sk9FD`( z;w4*NkIY0deH^_PFC~V`=3e@+>1DtG00ydN4?xVN2~2o@iK$sj=x3E)&z`V=;1^@` zH5a>%!mr5)(AEMMr7XpI5c>Kuh|%SLF$M)S$F&4R!!<^>zY@I|rf~lN9*oDlDLRno zY=XKDqEWbEI~wRl>JprlPH5lZdKe6c;yr5|yEYNfKv&Nzh%IqJIuJ)0wEL%Bzg+gmSE z*sgRIIC0j@n2BR&OIbTT{Qw!q0Vy$y5eH`v#63HwhAT>HIYO;5k~nmfmm|8Cg@WS< z>ndO|v9cZzfpWFu^E0rb2V@S0yvG%KB8^qA8eX_H2;v@9v8M}+8Mi!CP7AR>8=~w5 zx071LD6U#<+_`c5G(knFdT!S_PN{{WD;`X>qJ!3Hgn9cD5UDB}hx7Gjv0AM)u#kv;=3DB%g@ab9E zvh4i6vh72KrSE1RnB9YAOgq-*^XlJa%lf)LSQI>&E9cyxG?xA$)RAuozoP}Zg-&!d zX12R#I5dIZ0|(5`Rz}2fGJtCBt@-=PwE@!>*YWca zj&#xrvBUoWsaM!8bghee=aQqtj>vo>9XB4+QP2UM@@B}5VLbvljI3^=(-na7rv=-@ zsK-?PrEXs}5YjLQwktH*#0b*jz}cQMyxOw}lz~h;IjLnDIr&qUD|cNbg{2hXRdGlo zSZVI@^8rz@lye8_cH!guij)?$YhSU?p}+C;{U!-c5Vv+)2P<_c{c9}~htDpJgZPQT z&61P5aR^y0+S8vBxh+Im@qgVT=r4d5s$w0;WbE*s81zlVVMf|o{vQ)i-EZMPpFr;4 z9sLQG%l04u0YSm9cmag^M{bW!`Hnq+lWjv0Gc4%`KnQwv`H3K&&M?HwK8~RRC5E~~ z-4gMeFWD8~r)LXM__%pEC21%hq%)M8L|dI*XU|xbg-@bnK9NdhHOhtdjMngCh=CER zL|{#_2szty3ilo$CUX9E8)4`axr5R8N(O)cP^(N^MX=4j@HE|>plQlsVqiM*?FVOqUED7B zZMitj*h~7ETMn%j^D!tg@JI{I(EU)%8wgTG{88}_3^I%!q_)Zy8boyWl$t1jvhth| zi%+$)=Gkh*;>w)S5osalO2AM}ImNy+UH<@MpF{le7s&8FRR_xw$hRp@7ZrWl+(D{V zlo$?!#9((|lm}no0EUeQf)F=68a%(aKU@Gkf&%46&pLlFEuuLrVfVVgrSiDCBfMdq z>X~0%edQ>9LG)BOzR>+60~N~vGFs(dGh8+kU;uex@{$~(R=e4?tW|V|r8Uq%Fmqd| zD`kySiF>4u)mKT-8~SyOQDvt{D{a?%j;BKhm-0?D8|A9bx}W`pK&(vJAZsX7rIf!| zw4#<9@d6d7Caa?P$qs&&I!=q!iHm`jxedTN-9v0B*_!JSh3J>{Xzv0fR)7a6la9;) zjhukdeqi9CNEQBkO3O!g{Vx)>2B`z&#$c}Sx=*150-IRhG|lYQJ!1Z7Z}jj=r^=}- z$$G7@iU*_$urCj{W(@$A+G|)KDMkY9zz*DZTYqTBJ7SLjdRZH+Ke9Rxc&r}2y{*wdncah#>Q_Ic3oka9VJ4CP z0I6xIKw6pySZJjbm|CtCt|(mheDs!Q%PjaSRS}S`@jFZ=WxawME6RQ*F|*=Z`;EF~ z1yuxo#95Gxa+XS^Y7pEbhZv^BHtdbvL-?R+(&BDZJ6;&l>0AY)#;MAZSwvE3HcAIzzF3W|y-EIoB@Cz{f7cR}HTem>BF6?BpImZ#% zL34py>=5wVtFrd<5@8}1uQ_KT$!;&St1*vO(}70a9L`iY$H&KBxp*VsaOTeQ z{{Sr7Vp%6eDxpb0ShwE1N>m2SQXj-(mi$J}CFm~E7#t7wO9(6-1&Y$8tIVvF232SX z?P?6YU)pE%2I!4ufqKnus_F=>P^CCt@XmW3O0;zeV`L5HT@Ape>v1i^$0ueHb$T+@ zt3#oy?FP&CqhR#@f>X0(015(w)l^GS&GGRZ!eUf+2F={4DzVHVjAP8d!kR#7cW$A) z1uoCcOBfgl1Ht)a0s@Oc=)8G^*j64}P3$w#BAtL-(R|nDTeB^b1P{@stG3f<`Xx#M zDQvjq^9P+!Egcb>Dp(8Rroj3Z&W??2mi;P+AahClz!w!XD8g1c4lFBwEPdkNOHGD9 z`i1~iG~MihI|~FwIQkaLV&uU1^2Pkpc%2iDy=F2}XlS(V`xgUP%48Pa0}Ar1x~jIA zHV1PD@wOWawme7u#dABeE9HXdI0WB&kR6KAlt*cj-np(MVHu$8!N0aRhb^pGnt=de-J1Q+!PL9U|kq40CDCTs*TuOMGjjIn19%pphrwr zgWv)f*+R10JA4VT>+vs4t{?)^K0z!u(TK1*Ws50%L+ql(p!%G}PKq}cqTN$)3Zjh4 zD#G~c@#X=rfv^mMWDPFwzGJIkZ&-J6(-OAG>RJlM{KREC4tOXph}gpchV4wYi+`6@ zO7X*`A1WPYK5#^`x0n9_vrTIY2g<(C2daxmFk0gK45gk%g)gHPs5fjr$f8M_TF&{z z8wAMy(&_pI;-NL}9+^?`Gb>Fst~<=VQEzhGELV~Rbr!p(?&Ay0y$KqgrlOP)mx^>B z?jlMJ1f_IHq;MJaPwE>4sp$2!f&o;f-+SgH(|4JD;EtPv3&AU!aO@s9jW&#(iKEB< z#ulpg90+Zw_=qd=>v)|!%80od*Fe5vWhi#8-DPn8OslI0ja)BCDOrd!&6SMW!WKij zQ1kkfv#8;3L_(tlSYYdQbqIk}qiJCE9-K zo8{?${X3GCUEs_H^mjYB_UcVY{{Vf8YtPo<8u1y?r_9Q6bT&9C*exLz-L^2fZP3nn z)SwE|idKX?zA@G<8kZjrVBn1BqYOQgZNn=-syT7!f-E?*IvO_#~X!4f&(tYwF~NWx`# znbtsTSMwWrBsy}jd^SD4P#1IPe06vPj+0t z*%-hon!XQ`UxR(zt3|=|%QCdF>q|k*w&WOB9QWvY&z+FRTn099puf@}7GRM>w@hZ{*;uBX z8}lp2Ft`J5dj8V8_tv08gS*f+!lOaKUB^|f&`BA2)A=w2RW};f1-#X8QT{ z0)QQ(O>PpJrc19rn`H&ZA)ZBrW#g``8?TzE35=~PRrFK=3s7bGi(dFz@K+A(brp6k z-1A>Ui2Abl{C9xZPM4P;pbFUY8Cwb9Y2P(|2>2z7nos0m^9_VT4JMzY3mM0tGCvjc zV>CO46|hc?MIWXuAO*ZCe3FnAN+T-(WSZ;_gU$GM zxqqT695CySDh0AUq)QBAPyqJE?TV_sf6O(DST_o01tDrtLukqy%gm>kCBTYFBI2qz1LZ`iT~ed!R23{r)E4AxyyLIXvSR zTU5(?&+S+QCfQ-=;88h#PpPArsAPfN=3EY0m4;evRuc`uxsl}f%(3P16^A}^1z_e7 z!Rnka551smy(S={@mpnAU$@)Lev+pH!2l=$+aBklZdhgkS14w#1xkl%_V~}{Ai9th zS*OQ%AI8Cxj)0}`NObf9k=MGT+)5x{C?5s%fT2(t zI&_w(9Qp+%NJGq}>x$c@@3ZL;(SS_ii(%P4mC+sH>|VHxIdI6p`3D((kyAw+)lC4{ z6nmN?+^Bjp)TD5De}Nfp-hc13xvEl*%^sHyTwt0VK)AL$pbG61>=r0_S8-}ZFDo-} z>kG-xI3uALJi(qC`o|U|MC7$CUaWQ5?nb{4{FOrKCj^oCF)V{BYX_dtUrt=;DIVle z>8E0j`$sh!oL!0WE*_I#J|6IGmR7;OkKFzxsH9AZxKKlEu=$Ly#i2&}_5T2~3*~5* zVl>nsuXk!~?=BUc=50)t&e@bQz_yoeb;jlLDk)h%`)s>I$#Hc1A9xF)VON#bsOQ9B zX*8FL z_U0#G=Uz&Wp3rAB9*aZ4D=>5GbCx_2 zr2^fQ?#5{ART7OY&~;@B(9YQ1{bE(M29lHUY!cQ4?Hy=Ap3pvww*@ivG2RLTAnLhZ zF1#`91c2mm^wi3bZi_6GCo2_KpUJ-rKoC;WZUCf)k3jgxuWtVU+_9)yp|*;3P)!p2 zIzo*m#9GBclpd?lcbB;!aO3{~v5M@%jNL4EWXkPmc4B=ZfK{h!1BF_8JKUsPe1>P4 ziN`me^-HM>U$okLK~OTprBqs}L4oXB^1gxWezyR$WsvUzhT{06bX3j?VOH}zEPE(p zQG2K&uArDLdX!)X0|%H6^B=nwlHp1PhY8%QomEs^P1L3vcXzh{jk^bEJi*=F-JRgU z-5U$;?(XhQaF-BVgX=f^Yu3!&+|9WBuHrSXiG`~4 zdm(4^PH;_FWi{(MT9>_+;&)ZUDDG{j9%N5(xUzLlj~t#EuH`b^nkdfv8rNteB8y>N zzY3m(M$V&Hv{YSKdTT@8VPZv+(5GGh_EnpR{R39suZQjn8)$*=E4g*nxYK6|{Hra{ zVtQw33lOU2r70q|;V*(#os?bSH-hSE5m2dv$0`F$_3_Pms!_P$CcN*Wkzm+SHEhGV z!LT!?dBx^wxMxHZrL^#Jet^0v_7&B5=CRzo97z=h_FM{E^luE&Bxg_EVq!N@yGnpgE?`pC+Ln7XO|(;! zA7n$uPm@~f*0Dim(B(c;hg!@VgF<>tm}e>VZgH@Dt3znbPQ?O<($#M1pD>|FTwfG$ zcPDmvD^9|DYBo#Ubi;Gxc40YnFla;^`SZeOE6l%=7REEbE+{VT3kpuy-TFg1i|R!V z^={!hf4kT^Qlm~*`i{7OY|s?Sxab!opaP(IMWz~pTV781=^E{MIW!2tGvs_3EQHzw zjczGB`-xiOOzg26A;GgKARxTA%g!MDIJA#q?@dH61{n9R4VoGsc&4GdZMR@o4^e2Q zqL3$fJ8ag4&ef9y!}E~6ub+t87`zfA4LQS_yGqt1sKhiU5RgevYoW?=(W#Yvt6~#a z905;$C2o%aAy_j|{B~?G;!qIb5F?tLiXtarSXURAGcuE(5Blp&wjV~h-m>c9H#XdS z!5TB{;0nb4n>K}y=4Iw4G!$7@xE7@7Cou&{H;^ZxEThyc(;x~`?9{zVcTS558z<9l z@KCU7uJ>XTYall^&X@2vu7n1oiA_}k;J1^o()z(pr9~}&xZ#&#bsruxa|5vpXW?^P zMTuXAA+CTI6cd+!CwFN{DANd(|15=NSuDc}HdiHlE5wn%=Dv*C8c1Is_;3NYixK(p zAQ$iq&9u^NcCCQ2C0w$1LW655v}L>Q!4U!CwNGuD{H?r}l)6jcYq?5=otT9{S#hIk zfe_;nn%%UiMwQgu-4%K3bw77+{URf8A1pFWCuzWMj#>ZkJ#5x1;qHFgiiIfYt$mm@ z1cQN#ibM2{4rejmW*1TxHK!7VoncMGo;}@D0*vZa{?C8{NoZ?yd8M6eaKqZ67>x~c z44iW(isJVJkWtA;wy&(~7zKwUVeA|Y3}|Vhr=vnP-$wE~x=Z{EvMei-=6Cg`UA{pb zLMio3wm4Duw#M*k#LHMEL0bleEfEtcw(o15=T#0E4G<~IqB8y3W9D72$44;CqM0>1KdsNZ}q0X zJUN_2K1PY2V(hQG{0CBRNeb_?qak82Qa_!U@G3uk3qF2$ zM_8U)WlAPA5Cr^3rpWd;2W*>6&EyxJ=g)TF?N@_yX6qZ4isVZYP1eJL!x43?Yp!~0 z-_6xYy24mN^+-!^_z&Pn1%ri~bTY~ii>XiK7hEAPH3a=(x)xV~k&gPc3hP=<40ZC< z(O+A=z01-oBg13)RI{Fa75>X_lT1qijlJYEjNereUp%J%DHR(rqih=h=X+(NJO?v>pVXQy z^E*%~@x4Juxsy$Yujdt#4*a4vJWsHsQ=yvglpkwpVXry|XnAqOH-^Ua=@qf$iSou8 zJ=*tPL~;}uY@f`F3U_PMTuQI<3SL??P%@W%iMzKOCPbue?5x?@Hil*LKD-J1!PdKJo#)ixcx&U50$b|DWbLdv<1 z#Rcg^g^y`G7#D^Y5a!t`KoKpfSNhjoWpr?^8JfyLwHjtC0Otx`2tCxuu)%Xm_gRqh zlyhqg!yJ>Abom?Em-8@_r>(t>)N~IZ*wyvVAI?e2xP@_HR2kM>{hYjMPwAzNVyU1P zNzKUw12#=ItXwqywyF*V-^su5cncTUw$N@waCSBV?8JVzqEQ|%p++)DfKY?fTg}XWB)}Xs{uo34b6+{qE^eKg zeupmD#@bREhwdGfVI8ycvSB-IOoO7iwFFpoQi-4LkD?rM;y}j;wGM&>sT!};sLQz8 zs?Z0lugDMOoxU4D=wNAu{ztF79JQo1rZL06E6VNVhZwpGHDW#o18K;#9B&P9<8;6} zHpe{e{O(;a7Z19%mof>yea?~$rF4HCX!exb`Y$`%bR!jkWLc%L=xJIEIw8X^wZ46H z;qMqIN27%}Te(AoY^-x*WFJ7{}R5t$@< z$pz(pmh1flzDBsG5wL2m&=21tB#2dOVYO4jL@8x0YH7mBxM2_dk!u8-Qmgda{z=aK z&e?2#CBkXwAn_+N6JR5EyTKXehDpXR6M28bIIN!D6Tx8_@t79QkEY{~Ud6s|B4&9D z^naCmbcC1q5ziI>Iq`f%{e@4eFf`vNxMh@>5jo(+Iz&t7_ZQgRWc-uO{`fOyqzJVk z)FE*_KHaAa!)`Bi9mDSzxp56eyFVXms_c2c*x`?)Y{r3NKY5$oRbtJgBk;$l591$n zBtIx!;Fe>nDWwtOpA<_s=aY7Yrd_|8L2Af~j(D!ozlU_8`S9o;OTwju2kd0~}1*ZA~&ovqG%u zL9L*n6+aTv6fm_s?3{5Y-G@aXVrTs&NWDAx(aW3viXebtIc8i~;5oC?->I3jRA479 z%7ez*ip866__Q^6iM5c6EdMg_I;~9n8bR^HG~u6+hP%Le}I_WM)x&RPfwnR8&2$Q!X3Wnw9&7q7~l#;E^#*MU3GQh z-g*4vPPPHAnaN7U)Xf7kY{f{ATR>SOOHoZ_9`?9z`X_Wico)R=1GYp9a?6xXhAU<3 zc525a@q&0IP~7Z~oFxYq>kA_!iqE(@o6Q5NN`XUNK ztli0ww7{6grE_+%k}Z6XP|oD0l^YrZtK4LfPl##rPUNNtj8&3YSWH{7%4j;hcGE&0 zcZ^u1RQfA)o>FwTzQ#Y$1nd#7Z_4xw#`3Gt>}i^!vk z^uNGGslzXii-*!v8x=tjF|opSlbQsnRQy7%x?INACgJ_rV~0!3A8);#y~Y*&59)fK zU{oPqSN*i4k4)5NMYMLp^TB8{_F>eD?>8rA=`OlN;YsHArgHGE8dko1b3 zKgOXl6~&he!*Fe~)j`6EvzY1H+jiOcRW{+0`gAQyhs!Gn)*iZdh{?Go&>JZmnmNuQ zJ`l-?G1}Q(;m45SGIz_rf%f3Uc!$c~#y=$E+=qFQZQQ=NlZF4oSRAy!6@OK|`33`xIH|5s6V~wSi8JgM` zr~d%W#eYjBHp@6TmS-?hL&Wr?9U$s`JdE(T70m6-oCQt>Qc@ZwBv?}YM}$M@!!`W} z`@BJn4nxex0mhWpmX*&UZohs7!|z=OvROyBd%Ao0HNktr1G;XWy(3EiZH+%*sY-uu zS5qhqx5SOKE48%HR_vPRsnuE^ zp~MazWks5yW&TZjeu+8>7UBb?3*ILxd5OVJ?tUXZC(6+1-%>&jw zyuMYQ%vteypefy4xH)B=bvm_X=;mFr3(jXOhQc^ zg?8gd6HV^@Yjc5S3~w?s=pIzN={Ms?@X)eWU}aM_e#HuIu?H;tQ14YC9csc%-{^n1 z6Mhz@4dhU%KK#Xhr(xLe%J^v>&;nP#(OWy=onIx*cHW~PVqwb)a9}(M{0?@Mj!5fZ z(&OXZ^(fvWm#OZ9+TOW%E-Hj%JTF#=I`1B+J$ z4K@D**z*1dK-_HkG?A$u+(Nd9(t!)txEjpuJC}~FDhN;oj$}#tfIXVKr|!an33TJd zQVU=${8@e}Bdzto49|0g<24<6*|BqU!W1k;OT{YzcB$aL01XYWE8#iB2Di|B+EE-A1$jl;wV~R+ z)%|gn5Tn)f2(yg&)P`pwY1@%}CYXbmgX-dBkr{HTH+z=L%Wne(Dt*RqWLrGxv8?TdcFXxoKt?& z@}f^JeCm0w$VX;vZ}S%R8lePz5Zi{YP7;NtN_EnnO$rWrcit{ASv9yMbO78!ABZe! zbSNt}eo+O!y$$N6D@HbmU8zmtYu7e%XpNd=g- zD#HFlvVM8FW47RZ)Ns{Ll4T5?KUn8mzTV(d?8F7XKcAF8T&yVeQfI-=#w|)|%Vys# zBL=aD{QF+2>fuQDGt==71xb*8hViNyNGAo2tvWECw>-b4;5}1YDD+7P+VsMecFc2#ed9Y-dLl zH3D>F`&;)RlO=R{;6L{p03^L$P$p$*V9kf!e|0Szr|S)PM_^;&G)$qUvUu@{c%cEp z$+p(|drpYg9K;8|$pVt;9FBh6MG}*oUzT>uW3I2rKtV151kTgxdSX61Y-HV|u&4Oi zjM^L4DUNah7~ML!cK!}4(+y}E?M%bowf<0Aq+_%%)~zo_q(QLG=FXw=<~Cz@Xk>J6l$KNGi@!W`!Z#3pgQENyW z7m_4`oJsW_*wie{A8dbnJclNQ*$YhOz4EpLeZ3}Xfwnk}h;4pV+S6p2Kx;N%JCn=?`v*{Na1`s-b$fWZxt zt^)KV$cxms(o#qL#z7_{>?qw-Z-hO8-M&$S;zB+B3Nj`xqgnge5N)YW#OeS#V5ASNpRrCOK38Ijl7yle_6HpVt<-go%np^dgUKw{5+0ye**8cD;YmMvU)}4{0^xsNeq_-vi{6&x*^% zq1>(MlPZ0P`_`MIm=;-S12WNu3u;scb^c`{S`)2^gpV^Jf!^LG!OK1CdIiSk#KH*y zbKZH)Al>43s9URV<7zems>7P)hYez8Lr?_@Yy5u0a!_~%r}1xT*tq6`Lb{?@Xu-o1 zIe^i>wBze*LZgFe6BM2V^IiHc9bquEDr*Y?Jj_QU*Oi!TjcvzF95WaahhT%yb-T*_ zEmBO@>3XVzQ)Jq|US`LiKtMH!T$l-bYWpiFu2!94Y3`nQ0itAT3T5yu7ICVU5tCG( zP=BLsU%RUsz$A|3!T#g|kI?`tx9iqa+~IoueJjwu*-#}ai$!|G{ezC~dVx9JX-OX6 z0ccr=cHleNBcT4fx2Q(#&{zhVm!4o5P6o+7Jc2_{N4C>`?I6&uinAbc_gxn6WLkM7 z#?G+t8HiWZy)s}nRei{#rV;c+VsXHU*mmtzUKz@|p#@K&6A{GItUGx4DxOZ3wYBtf zEnI?n0Aku$yF2BRX1~kdo-aN6CcbjQPnfT+9K)(7@&UDAxr}e%Ix%>+`rkE2HI~qCOHu}MYm4}f)l~{X6B7V({t(Qa2n^Hs@-U~DI zKyE=bo;~`EAtzo@@6;A)rpWQhl0@PUxoa85VKjawcX%CRd+<`$lXyF|v`)Jm1yk>1Nvp4r^vZ_?9lG zO4@{}ytD^^pE1B{86FRuij7Y=(Db}I}j902jel;@%P5%;e_q$=x9wv$ll_gwtCsG z7~yElYN$`>J3PFTU3WWNwsK8Sa6OB?1>P|9M}h6L=ztBc#!2te>FfbARR~>O1s>a! za%JVu_t=%?BQ&*@diUV{b~rqkaaw;_0y@=xq4`m5lO7WS#=oBmCj&cKLWz8{X8(6( zpvs6?)1*qMQwVhaTg&cje1J&=2mzNkT2JHtBRI+=#;i~+k`$Jh>?@+~qlf2oXOT{7 zRq4R^p9?1SqaBaix=cUAOS3aW8emjhXksU6He1->F>eQI=84CBc3p3yW8AuD(0CAz zQ>BOAT?{61sDzO>_xa2aI`O|_GOx;8v_$p_&rxB?DghDN(c=;?iR*s>iTwsZrDXhg zUu%KW+uK)D@Vhuk$$tPg6^&>P?0Yam#kLxPveWMsN#uOH?#!v~sOV9MmqxG635*|# zx;5|3`WFCRzi;VA1GypPNmo&!4wQ$L;f5wV2^20&et`DY-|6qF1+?h48e^_6)EzFr zl_k(Dwsg;c0=7*mi@O;Z2!)wNDVX}GgVx_xIp8ar-`t?9rH6|%34H8aMDh?>LYgVb^i+qzP;fLTEDapN&N9DBa zJd>^VWazbOXh1w_M&~lj>omg84U?;WL!~Z`J;_@{>RVHzF`%CDF%&|-#Zbs)!UMGq zB>OVfq!ya)qi;!73ei+f+zR`?!TeNDS$e0g>+VZ_{SSa8GzqD4|Db=y}S$;2i0HsMb0$0|be=#Tms%wsh=uL>+$1(y&Qc>lk)2c!du^$!4F{^_!uub*)7muO0-|p1kGYM}u!8y{7YcT6fI+bfrT|=A2?G7r!S#Lv&U`{! zw}TnxiSfo6;qQr*YI@icUG^$f)_3)wmIxG zCrb(9ykYxsxq%7tK&%X$1Sf5AC{48Us7Z=3ALXNZvUp)QAGuDL1u0Y(G7u`}5ZwNQDkt#YB*eFl&kN z;4PkvWcQRP#Lzo5Ejrt_E<#4eC%TaFuNJfW23|Q!c`JTUXqx0@dz5n@I~oX0<|4y- zGY&+g6(l$+rJIfFRPD0VBX$4<5`?O7@v$z@?_aZ>a!l791qst=-`woY%s8sX_MvoorZ&j<>{SaNhfS+5v>o6)weV+QvRvCwuaf$$6 zTz1`w402Y#d4YM64oD!bZ*qRIyqU)?a95b&8<14Ej=aULTB2f}^8(CRKK1T87`AP8 zU)2IAi4e<%n41&5ho!FgZn=L~b;B;*QX#!CAr!JkY;2~c2;W0b^iYL+fB)KAxc|{- z8-z8}uY4d;jEn3gf$`)&s=18qlTU=>z_M;y;29 zZp*^>yBYom@qYlDwt|!gv7HkQej}>)u?;~x%Cm#HWllX1k%3V&(+OI&kUmB;%AV`{oV}G*7m%`Zx`O$?!s|ZkdJO?xPY}WUL$1L zzYx-@#$RXbjdezzz#wP}!Z)6(A=vwQiVG`!B@|A%^D5kfA83wqceM()v7p)zV4(7J zTVpl$-FAKbufH{7b$5>@K__q(J~j}uY*o01vBVwylu=i!dmQe@{xTYz(K3ZWg18&E znf3SWh3V_zCf+g(7H_FYVx;e7)epflNCz4cBEsawF`XYGfxUs`mwvw)Z?c3n^2?khkFuHv#o%5TXm0L z!tN4=VNzlx#6f_0T$IS)WRW;FNyj3-5&|+gDl1k00eXutOm7>ATvROP0H?Jy4*6KD z9bGjy)p9N&otieVYUp@OMF-Qf)L~5ynOj~QO=H8)-&1dk`9?dR=;zQ| z(zm~Nr2sMU)mQ)Ux~I)|AVlo?BGp~*+&vYu|9phQiL)cMFta!K|k#CCT%hv`=ZaFnT-xCA-X4ebaAd9 zFxK^s*R;g$0^Ub4DV`DIo+4)Ryf@x%1a;OolNlOnWh`arY8~po z9|H0WoAlbV?OW7$1yBM2$S?^qaW_N*f3u~K%O6b^m<%k)(T4T21S4SoC^sV%NvJ7S z8k0SHC;VP=(Y^Pu>fed97C(TzeHedvB7HDUBZ0~I7zp+t%_qIfJEh#3h!GGZ`^Gh; zxyRcj=<3d4B&<;S^>Kc9kj@+FRTG-Bq7pN#!u4ROk`eXCk>JN9K=0(n_ft!hsG(_aZNi)(9kvzwSP97K1) zM9hZ=@ZWnB>hSnx8@OEh?J{dH&+7fuI{wN*lr={d%ibVB>LZ94q-9Nc?R=f|nP(I7 zA0V%--RXhnU2%>)dVhlzM#;UbE2_J9$U=N*OPeRz;cQ%_hwgTA1CF7z#l9Rub( z2y$C$wEH*Xryo^*bN3TC+m9Xu_^aKu0D^sV@jm07mfjNJ!a+m3Bt^pOl z8l9_sGgS~hfbeLiQ=x$q-XgTSd;++3&96x9qLJTxOxoCm6e;0}l+Y~BZ1RNoJu=Cs zm++N1Iuca)t8E9o_XrChi^6g^NB=?3Q+x*tFKNrno7d0ZwA5mJ z;MC}om#gPjzxz+7nJM@qvupO;SC^GO#>?vh=F?mW#nsea$^wFW8xX}rHbS+kvGjLo z$h!A*{n>QhpHBIhL$f9V-Ds>3Q4h*=MFzd63PgPHwNu>r9h%McSgTJbleQTlAX8ob zmld%`x%)qE2vMD3pJ5XJVy{6&0oa# zC2VS(h%}vSqDrn);`SLajGeCy-l-(}WSbP6^Io=(1rTKP zVF|w~wCOtM4#STHa}y$|sxTWPLJ=cZpahnahENLDPnbRq`h?#gYQ*cr1wcbSOb9lE zZk*fDEdzZ-F}fP(`O?o%0Tu9Jc}944?zHc-(myFyH7+SFBVUv;dtrF$5=F1|&|?7X z@Cnvo))>rYy0PcXC(?Eu*fD7tmH&o}t<{%*tt;!YazWSLFZRu~n++J}5FtYrhuvP% z$93x`!=iRn#9+QqSoiGYfX%tSu_>U$>;kioDz0AcrAg-dEN zjOVg`eNpaHjVk!2e;)@a zp;4p9Wgr3Bbe$FcjHJMDsl1Qpfpe5Q?V`oJFncY!HqD#hL)844e&C~ag``1NpeXhL zJWEBF5r`4b%Z)3)@gKJ*@w2anA5Z=HF|NPX9omqj3-&U5nbjX9f^i%vpmOYs{{ROE4|ncr0OB1f+T^)^iO?&O074(aUWA+ZBaM8uMRu+D(9qnmJrvD3 zOU$r0uk6xMJv9^vef)|{bql8@WVXJWLi8puE<1Q*zMY^Y9iva~9YS#z6cC4Cz+B&i zF{CsMA8v>}N^pXNVyaY32Fw$qSLvk1Y3$87?JH|G99G>K{0DfJp1$Hx zJiZWyjN&g;n9+W2d_;Bn-uzB?V@?TUmaI#IT5f<#nYPR&&7nq^=`0;LsNoozW-Z!M zoowBW8d}7LUcJ4oTu>2_ql67yv3>NPaK17a+jqno;dj;alNEilmZQ6L6~?HhRzYxE zv2n=@EZIF5GtH6gpR0eY@u*1+r_IRWvQ0hN`Hx|P#<%7&1Uc>}z z;@4p@e>?JE2TZEYB`j?4)2H{ea-X**HH5X8?xL7-s;7sj?rG5B7ZmAGV|%Y#K?+2B ztO)y(Pb@}-f{q%RZfxH8M&ucBKm#IH>V%{qq(xYM>9pvvVoF?f%b2N{0ij;#7dww{ z7q9-2yazMwj_;;@pFd?Al>yB-z}(q@nD`5oXZfz(p)4KrAK*Ghq$p3SPq$yOpPBkF zZt!ixR~EU=$;cFo8?IWIHp?B~sXGAw+OS8~Om5~rHPvFfFfTtuLiJ5@gvc=<=HY>` zu->OykVuoc)r%7ZdP)310?}tX7V4T(O0*%8dwS-~<;zwOmG)^8QU+>`3J$&_< z;NTO)ZsKG6Wz*uXZOD@wwOJ#P0r-neGk@%FRiyjX<yfB4v< zWiYOfo}wAI!&eGs0UTiC;YqY8?_N#$-x$%kh_N_F^?Rg{V3|OK$6p} zHM58j1paJ{v?~{l^&|XqLf!Txs+^9idM^7@Oume6EQNjOsuh>yR&`CzLD`DdSFgMq zCdHnr20BFn<@O=Rhd%P^y~=N+aj#fxiBYOie}a&n%czr&o)>n59T8jY{I+zxvDtBgf99=%k0Uw7+kt ztf2V|_MIGL%RbYf8a6A`X}h_HRC#e>S!RAg*KX%Xp9c}n!MeWW!&PD$)vppR1P;6Q zJHzymy%OA;A6 zshbz`)@p3_j(mYGJGEy%PijB=XZ%8*7b9{Z@*m)s<%qA4 zNMg#h8mAjOuY|vl+ScptmEi%^>*QlXWbI=!gWxMw%4Uz;ij&L=*LG5D_EuRc79Gto zF75&aX^IdI?$KZf{}VL0p&et=Edw?&k`*d!(az#Jz^4b?rN93oEvfsWDDA=7idSq$e}V zdUfAs)ApgVJBr6FHE}}Kkj}>OWQ<<}xJ!56#=|rY{Ua9i1yj#7 z?qMpVcta#1%-&gLF&WE^czIs>^x`shm?j?CEimIaDA{e5GPPvJJ)c< zw8HNdYO>u6AlkQV!@>l$uOWooOhz6GcAT^zNn=`(VXHqAq#8ocd7l70@LJy#c`1JDYhSp@bv!BPVB`8W6r*{}$IKNvV`6}h` zNq#)9A*ZX8S)*So+kE-o-2lR;)a`rZ2D|&hnd{ng@}zdTaOoV`iEn*FFfvGj151Be%S#~p-uKo z_5uRgp+%xM&Ou*c#?CtTZj_SF5IH?vy?eF$QG&li#ZfO{u~NG()L%i>17Rv}aFJJ4 zi9?1faw^F@jE2a#FmdY(M&~XWpyW^hp3eJRrO?EVOu<<}^<}hvJCBiAXD2b!Ov30D z-JKwMF=dPMJN!RhQJ=@#PAVQ)4+~oPKu>v@M%12nku5aulCDkwNI;J z=?oUOL_%@1%;%$pl!lv+%K~BHePw~{$6HmM{<%Yx7R5AsaRw#5{jq6(D-BWaU9fOv z6%zBq!VL=OE8+D_$2`!cis2nY4(0^uu(B(pe@)AWdhtCeUH{Llr#HaYMjx4ism=N9 z9{&wjtH^QLe>|VYczGi{U20+rdv{j3itC6}Ze+MWBv?w|!$OQ?U}ADi_K(snr+38y zh_|cf?RD$3%iw2mK1qICSF z4?hP7Tp`Yh)sbuMn(|?Xj9n9f-(E;R=vUdxig?N7xqS&;Kcxz-3kynSbp}}X?0$Uh z`VA1bpXof7i?d{Mvv*qMAX~m+x1D=GA)5HfpX}30`{RH?YGdl+)@T%5!IiIzH zBm>!=g-?r_5X*AQ2ohwKIFe3nLZqgP6OtXiiwS_fHp3Yrk=b5oxO(&ZpI=36AHFDl z3j^;%czv@JV*wh7Eq4H4J`qM1HDY0o>X_+t57zUMm%$T&Llw3y?D$RYNOsYx7$Z}< zJu^0xN{uVs(AQv`uf_XKspBW6^<(?c)?)NJ3s84yN-*`VNeQ3zoDDHF=QgG|Ct3M` z-+8|f+eft3YqN8Wk441aIF^fiV}*E5Z&KI7A($!Sk4g1VSzBJg8JDD;{E{HxILAdB z!JxrV4ivp;zFSy5TQXa1Fl@HcGf|~lE(3T4rBTroxDU?!00A_P<{C>k5y(Q}Gd#l8{U(^mZAjDsU`b3W0ThASM79gj*@7MJ^oH z^m<41hI91BcNxqcD-#F!+fC+od&~`sLO-`{kl#9&X$v%lC^B-(3WJ=$7o-x|(g2T~ zLnq3xciOqnajLfjX8LtYBp90pGzgJs*K>&0=0%+d^e4j;)4A`Nbjql{ec1|UA=J0^a2TTY3E#jNO$ zp=^yaPd-{d;B&?%f3QnKI2Lq|y+=XynVhd^`L^vJ86D)08BEId#lgq*c104 zyjR4XwZa9fNMmfL(Gur4>%wf-YjK#fPpYK^E=(>6?j{%8DGMW2686hm_x!aO{+=al zd)HA+Rv3}WKBgHTmDFL!7?z76$HLs?(!cd>)Hn?jV)!Z09qtgy-93{mHLDGzM=cNL zwh9y7$*0ubqZ$y?a;xLOm4RK+uD|+{dEC70AA>dTY~eendgwm>HS&Zwe_-cC zw|&Y6t{Uch3@wTwY)v0D%XIBR)M+EF{?v|co7&9Y{=}yvzyq2m6+YPWT5G|aQ42jo zuam~ONSV!u%RrmEcQF82&A(w#fihkpupbuj??lAc{@qdsvr6T4q1X{+fN-2_jD~Wp zOTiu}9{9@g2z>0`6d3jt zf6)iH0F0ya_0LtTm;49DjY9HlLhqa)gOkm)nZGucp6N?_IwmORaHqMVk0;VWS*Ebc zD9`Qnds*$Ti=M#_Q|2HzI2@+k(|V?xPaP#zp$d2VSvbr>8cF3FPRpySt?!BA=PHhaY?KBamNcF^si?~F+E5(1cN_k-PPyZc0r z9&*b%rUJTsqse9Fe*nzIH)_cRg2nKln^g3inz)hcm8hWC;S7_1=@4YoKcu-fLvf#z z*3C>k*Yzee_o=szMLPY)+ULlw5)sBEPCs%FBw#DV2vsQkTXE1kgsP^v`}K2!BRT?e zut<&rN0T(?B%@}6YxXa?vpNGZ@N|#sUbk+L&(i1Cw=Tn0`)kE;EOh0vq1KpR(JX@T z4=U$6$B+JWmh(|>5dMztvD_kwV0}14YJ>OJoqb0J&iZ@Z=*Tdww1ggNhfoUA(Io7# zsE{-$y_3Z|%gLEvv~VmGh_TX^Dv|&bP$2nwAt7lK_*0ScZO6n7bzXa8_MI?lME77e z9{f43)au=fqbLnvXFZCZU9kLrem;^0&KEYyD%!6WpUtT;8dV{>YWs&(^pU`D%9-sy zU4C2=(Z=^y#d9R-U%$7iy!l$UeENV4!+|UY$VxQuHyGbuNEP@y=gp2IcPSIJ2RIx0 zFmtpSdi6Q3C*wnUYNqhe%qIY77>hefs0EPrkFcs`g0h+=}POLtFxWf;ch7E;H*D?wZuyg&KJFk<#RcF2_|IWR6&12PCj z+jQRuszkVF~lb&@9n(Jb#d6{DkKHZ zMVuxtmoRBfts~WkNuy-MN$E11OK*SVsegrT=7t(G@PGe_qTSuM8RCl@Q;hv$KzShk zr3CBuOW?~V-%_~tU7^R183&%sZ>ph)pTJ8=A9GU^OQYr9@)2*s-%lKVaM|~-%=^L; zv(ev{xI8S^9(LVU4}axNB)JGEw!EPe=m>5L4mKa-b#`y`^m$+3AYtO3Y{6NUHZHC8Ss~P)8 zPF8ThGUMtf64f;kSk91)H;MIePF`u(6$f`!;Szj;g*2b?sE)WV<7KDRUzy$Yb{uXv zbfgH9FHm`;g^`k>=S-|GPjw{W@Aw~7GnsR5ESks~KDK}WM`CCyyJ*dT5mfNR^Mm`jTGX)5b-8Rh;L zvQ}lQZh7@JmDakj8r)%_dIV}Ju8j9rw=*x*P* z#<PP)>dPHb7z=0tHH&rmMAtl!XxgN0Kr8}MNO4_`Lv*9; zJT|%&Ce-=seqC?v9Q7Rb3d>_^ZPwa-oWa->UY!6AJa3V)rX3KWxD@G6$^U$v^wH|0 zCfv;|(x;}-z-!@gtR|WbROXvB@}}^(FmGn$93}J|^OolKvl39?xqo0!>A-&LJ$i40 zZ8%NAg0h;A%z8|o@>67h)jrs;&(DWu4QU!GHpP;rTUmdqyy_lGoWOE~&+hl}_@4yz zd65~|BB*Nhz969}n_8_X<_5+)fSX5w2K3yjp~by|Aw_JPDoPgax&N$H;E0{nbz_Cy zs^{fIfW^+JgQfux%25alL)auu3h=3jQA2hMUOnxjHr1}NZzb)}n-|+5=YS2SUB^ja zcmA$wr(ut)U^#1Lom>P9dkYmh;od-+Nlzybwua~lr;G=vVd{hnMI}8-v~b7WBJ|~N zhcTr~Hn)2N%V|k1ALrc&_E>N0*5;D`2LKdO^Sf5FM46Ll#Y&*JFH!mJ)@c~}V*{-GP2N~Z>>-%OJQ0aJxmdUyK7^8PlqjmHMbwI%?Z?FiXOs?% zYfBFF=H$-*I5c0Z4@g4=E=M1(!u|t19$;y#*Z-g5@DHJxxoGqa;_wSbOO|Tx`OkbC z`b&km5N_wZF?KDE;Sz{=Kv)E4w^fH{aCu93{G=1sSds}>=>~wlN8k;^l94N$p&VGm zD+(GGq&U&^U-#p_Ul+Rf{F--r!kjgtdc5)U69Naduo1`{0W}5NjPi3vbmOeNX8vzA z2$53D(Q#LNI@h}UrKP`L2`zBTA8iIXWXh&|8!H#cWz`+iRA-Y}lSr^_Q@o`paZI62 z%yx445vamUX3w6m_0UCESW>f)qjP(F%C6xUREp+wQc7OkzVQ9|QS{>J`i?1jm4N=- zpVmm`J)h(5d!NZS6dhK43ZqwHoO8%)T~X18)Ay>Oo9qlIyEMNq>RXrH0{3~DIcCXg z?LwTK7zG!{cwy#V%XyMvCs=y03~1FWr9pM!{Uli2v15m}G-$9L;-2x-F{-k0aLk73 zQL#iLW&~lT&THoo(JR{j060~fMN{;p8Gk6>Gwm1vbUJHbbp2EQUPZAKFMDM3L(vp> z7F>q(?5eTsDD;7LNva@JH1aDxYjPW_VkIdp(?3(w>T~6b7+K;(2(0CM(CSS@5~}d6HtG80*s;W29y?t2BKj?=(DF zDQ{szV7q6omm%mmWL&#?mhD-&eXPlQbzT(?j8KjC}cH+>c38zkzq?u zJ(OwN3mCqa<3=~^X~o-+@-_S&nDkZCnqiA-G*&M^hLGd^ZXDpur?F2 z{h1ND;y(|Yx?%-26Q{-QD49lyNdd=)b?b##h}5*zdmDju+ro@1nj7!TKkFJ#{ta`o zUFAi^;T7nT(jCq&r`SxNU?kDxL+`z+MV&)>YJCk{8D88`@3r5$Wp8IY=5ZxdWQ2z( zpejwm)W>RM{nOdq#k61SY8eO&f7Wvw&=lC)DlwFrp3Ub`nJc0lqw@DNIf%n`N03#v zy|VEL$g+zdBq?rHSK zoN168LKN##KG8`1?ocyJ0btbk_M#w5!Pn9(XKfc`lE*drF*}&Hhl3_S`db97$c+%H z6&K&EL9?N5)JU+$>pmfWsOHMLOtEV^TjRi_*J62d(6;KIjw7iy`b;L3;;OU%*e}`F z-sIyx(^JeYq9<(ScL&`TEkgK7OF4rpyiydt3iik{NUTa6E%V0O@(yMD?GPhO5DV{QP0tkh3U$`mTcV zS)DQ*=HPVO`F)$rr$01hO>-Lb1+(9NT^Feu_FP~xP*VB^C_`YYWGnrav)9-9x$ibk z63O(>xYSnbe4xkdbP~K8R3heJT{)%~>lHJVNnhqq6XGOHJS{o3r`l*qPRLU38Uu3q z0az~PM?owzj=iFi?i_R9_$BO(O-Z1Db&^Py^>8}?eYN?F$6d^e=N&2?aQU;$Z-hq? zKViy}KH%k*j%tMnoBAP?n`^aI5l+PRfsFRJS!hm{w!@=v5)!~V8NGf4X*jENt1}aq zC?D%a{qG5r?8@!A_u*{`zcn2MMJ%XiB*)D}3r!Jt^7m|k+4%VDRIwk5Nx^q~4IX^` z+m#Himd_G=)Ud38(V)?(cXI?eymI8>GnmR#w&{Ji3}zG_v<0h2L4v4XQ0gC)+gKIC z0_ZfF)FV+CqqjY<3~#ygaN7D-&mOAK7Ep;(-I1Uug_KMW>k*fvCpLg@8dH_!VJ2T? zQPH#`b&oupQd~0Id16K5)1Z(^pLtL5zd0&i(S6x@wo884Kp@wV^k#kY^Spi-?afx) zWCOdL_Sq)>IwkjoI2!tt$?2SKJzcIkz_u0i?Y5_N zm7zeWC_SBai_A+>h@q=h;peATmBmjLOm-gYAXHEvhz>!k*gfTI8v#dQjwD& z?_=l#82neJmViQXTh9I`1of+#&rO~NwVu^=^yYj6kgJU&=qpA})i^zUlrwuGej?Fw z1Prw+sIc9O-baqVnWE(tS8F`aXvk#bSy!Hymx!6=*|{!6S!;-3A=|Yy@v9qO+3u!x zEfEfHHNEY1p^>8}UfC6TM2E-T;-ED=Z*B@8i@I+)y>YU)$j$#y>2P}^aa@EK zBpDRjF|ZFQ+SQig=Rka2Pj>ql3q#|Hzr(Gj69ICTCT3P$0iTix7WJU{poSaZ!BD5m zbMdhD^K=0P%gA9i;3y@?*hVqH#J2?LS5*K@r8gbrL+2`euI( z1KHz@5cg{lT=*vJel{Wn!$j7vNT(Iwa|{{zJ6h)|)dkk|_e2m+i>X~%) z`CwBGJ|OGj8(~nl!7T-b$&Gy59O{%vR7|)MU~WiUVUn`%==YKyP5Y%&AP>_b!BM#o zqYHr_6nfK|_dn@`ar4f)R7x~v31|-`AA_Sg7vjx+0gs?T%+3s7pXWOrFo~C$UVh}+ zseXilZLTjIQ79!Gp-17*r1Q9&bJ9!4;0k&sR9M>E4O14nUIWjdFPp@vlgWpiiD^^% zrg3e>yGVgCxqk6hNrKyPV1UMshGAOQ=82dDm|wrI=%%Aq6B-Ga&-%T7c-IGFg-@M? z>uy@(r=>emiUUfRS*4aao!_RB>Wa3*3HoKbd%uG5F8nD)ciDT&xuKFe7lgCZoVU8B zXX!mIGQQNL&mP?50hoB6x*Hgy;kI24(#G5+SwEgzWKNm>+1S5v&2ifN*%jg6iS7GB z(<|={YDK_KYqq79<{lVD2Pwp#oJH3#;srO-PV25P9SG8PuwwEZoJPDy`n3R~10CXx zQ&N-4&NW($tX65|crQ~D*D6Y+wi2;d63tj$L3~aW2J}N~!z@xcx!N24B^gqiY-oht zvFJ~oZ@i)^j30%66$16&v%XK8O`bvJe&?jy_D7E?BMm@<`tCZ>@u0!@CC(>y!=4-8 zSYk$E^aEsmLiQjByAfU8JP572T1ct%atrRm3XFEl|fkV zMqfLM(wemuUg(Ue{ohzE>fNiSeptR&O~lk0fjY-|ydiw~K zc$^!MTcUeF>%+5ElWc6LR}&4|zGEi5_2b<4{KO+hB4M-3$pKWuf!wr4C)r9Mi`C+s zz0tBW<-zb>gX^i;VM}ET6k9Ew_3u#6Kyhhphf5>>|41~x4DPvI=qBZW7CgS3qKN(= zaIZ}w0`iJqjHW9G7ZBofi_!~$aN`+1Q#czdo^aUCDF++t4)4X;gD;WH=>tmyzA9iT zx8seB+UD{t+!}L$WNBm)6lE0{v>a=h^bGQry}!b6iYa0U3MX{o!t0o)snrF2^1b0(cEGSt6M67Y z#UD#2Z}=1^I`}<9F7n=ppodovv}S6=W~!lA(ueKcD$V=Ydm-PcE=&CuL>#ypQs;oQ z5mOtTQmu>SP#)VKvBe%9Gv@0ACSws8qw3f%&Fg7K^jc$s0=)i(P3FArSB`@iITnS+ z7*d`sedX23@7^uQQNdGu=6C8|SdmkW!n-@^dUo@&uRh+|RSs6nhMXn@Zx)_S14MVl zwAh8;Fg7fvHjFc1xG3%Gdz#(f0VI9$nfgxS5Mc~$c zu9%y=>M%5A)p7Na5C7ziXl?(OSCAz)tds!MKL^7A@Z*k8kF>`Hj2G5z3e4lF=x9fo z=D7RJtDM$dcovN2U+5ZP{%(brbNfD=yscD8+-y9$$YPJD`rK~-k#qR&v||4HPWPwL zxfcip@p+xwn1B7M|r%UG)uuP6z#1NlG&8)bQWck1}1N=VM~U1`YlJN+&;x?gVgkC1i2a zbsi9v7bll5Hk0=mB%Dw)!MS>gYvuOc@R`u;Z;yKEL;8~EyDXp1QmE_%;u2kxAW~dOmnFo`>6qWjEm7{y6in0=M!8s#S`m!^$a>BXqZ@bxfMo-;} zWT_IHkJKY1#4nZ@y_}=XRn(}MEe5m34ReTKzRC&*#K(@P*>ejx`f0!@W7!k}2&YFj zU%t3ciTdo(mKmiAYu|nHY! zj<$9saOpJJIoLo_%;5>nAg+JprMWW7CieR>Z0sv1e^k@Xv;cIDCRhSQb9IRra2rJq zBeTkt9|55o;L&(=rKK#9g@px3$C&P=bmM)74<7|y!dof~O0s}qz!u7BD^RHK@u581 zvPjVzK9L4K7QpB95;)JMJjGVRcAM?`^;c*Xq8d)S78gxv#Dy3@aVKAc-g-rqv4Jn9 zi5rJnbbwx`Go(;wpWT||24XRV$b#icx}Y{Woqnqa)J2^~W5AEyEASPEQbTj& zPr6Zuo8E|q&9yC}VD|yryD-e*SpJ*&BcyvC0yr+Rr{zgw%^D_s34MtY&5VgXm(n+C z1VFHh?ad`W=lG^Q1O+&%X>U>GQ+5J7BWds+N`zKdn=<9d<#IJ9QXhr>D{Ub4hQ2Cu zOl|Hm&(0~1eZZad`FF+ed5$puL!;Z+qR<~%hvNEdmSXQX*Jan%env6}Q?y?Vh)~@8 z)|1#`=BbT)^;o_6ypf)^ii6LQ&d9io7ZO7x7X|b;JeRiVn?;*XmZ2l29)F~QINR(G zH3<`cTe`s&W1V$$jV%?`4;PVzhe1jrL#HPKmVrMOg-j58JYU3Zv8PRQy-O5JgJ+o} z=I&G=ZFlyr$gg^`j=zqO9szO9;ar1KOHYaq{VsXN{H7^*E%`F)yx|6DhJUObzUS9u zCJR>z5LP!4PyyJot$%0kgR2s{+H?5?bbRR7oJuhGuy!T=I4#G{xP;t6^5N5aW=gbV zTWdqt*OQ0tHTLB!yBS!OEJiUhxup~bRxDtm%g!c4BEUMJ*SxPw+txPglkbJl80Yt@ z%)!FNow+^g>W)!xi+74A>GBzS7@kYDU(P_>?3;|L*z--5(G=}pNcVsf`90hA_SXhE z7L!pyt7~@B>1bR!Qx$}+q9ZU0Z_KPMtA4>dM((dOc+4stG7>3`$f7_|TZ literal 149284 zcmeFZ1yEewwl3OOAh-vI1ozlP!?vUUvjk`l|cW5sE+2`!D z>)v{=-n(bN^Qvy`Sv7ji>Rvr-jWO36bBymBbG^*JtOGD*rDUW4Ft3dXh6w<8fdT|1 zlqJPf6_xoZ%#4{W?M%!lT-aDXQqVa&TG*IT$jAaIWWPuPDO`9z(lb%mJAbpXaB`;* zqTuC1epv!Y01)8d;o;#BUOx~J5Z)l7A|bvu3>1{Ns8|@-*jN}?SUC73?{IL5@UXB5 z-V+d!l9H2?d=f05AxDsR{!F`1b|_3kUytl}K-qQC?4|#{|H_z`?=3UjM5CuV;I| z{tkf0Lco5{CiVtL=^Nq)dt7$ExEv%(@#^1r%9CeQ9EJ}5Z;|oe5fBnl)6mkKuJyzvnh3dREs5A3$V{-4>d8Z53HDU#+2C8%LDPqwUq7Ackvtb>FL*s<~B?xZMAU@Sd zSDqsO3XOG{ry1zsa!+o3ig=SL#p-@3U?U2$4%HJOQ60`%gbCwXlKd7K6f8A95%l|+ zLC=k)FmBkM{gM0H!pEAxN&TorI61u4Ijq3SYsqQ=@GOTq!^b(THl%wZay?Ey8>Ec^ zB@Dbc`otr*L)SU@V_I$er_A$pLGpyCow%`2syHWT<gKs|DeWxN*JN!ikX zT)^uoc?xWq0jFNMaQw*)pWenS&CLGtMgTG?T8<0JCnWED}Qes-p> zX6pUEotb}|pPLA4LGn;N8L*!^`BO&6mmo%AMv8sN?ZBJSu!~fb-OtEH7jyn1t*DYs zbH)W&k^NdIiuNgx9#&d*1I;e6os6aeC#h@ctb$mb}u$C z4*zU_U52%6frcYTR$G`P$uyq`3pni8w#DOW19K30vH50};o-NXgGVmU3-w*YLZ*rA zAT}?6rfw)KX!2W{Yu`Z?3IfNztj}cSxXPyn#ClG;7P1F95g* z=uorB#qbM&lyiY|IFXS1sC$8N(r2!yzA?2%x`+zT5DBh9df_N%+?aU-;)c65;fornS>N4wpq>|oLB1F?|!$?E$_Y;jy4yqN>_YJYe4>vZBz4}CIvPB{=6m#uuT?i=Sgiu@xb!C;Jam|D)cZmO;W zyu>{L&>!&SJkm>znmc;SkxF@;C$ye=d%HGQfj8vI^=cB7&%92Knk}r1zwOdaHNOCa zK*3GHI_{rUq$XR^@xBGT&KK`b{v{ZE1mSxaH0uqtSqB95%Pb z0MAY2%fv42Zsz<&yx-DlbE9%peK4BGmlDFV-YmArUz;Btw=0N6e%}|>>YKm%k@D?- z^ssbFl6VvDIj?^C_4)pn{G$!Tasx!){`G}uZsLE3W$fr+-1_sGMwEwLc@Us%HiRDsFJM!TCJo6{eHgkG$=Zd*ym= zt5cRxt5)G0uC3KlroppTO${2e$W$p-5|X5pLHfTN=u4D zBPEAK7xxV>0D+8jFt(Q%cDeo1et1MylJ!pvc$m3rzO8m{+tAeE-Wo=<52)PhgP?c} zaGUhrzOFN#h;mNn2d)=@7Ke_`A@<`~gGguxeH1rJG4e(*(F%r2=2oNFb@6x)2A(xT z%K4|}fw$HK{Xg$LG?*ntN+zI^w}fDuU6;mL+82PI$R&RiZ9mafz9DgZ zW}INbQ9QQ^w5ewN_ScFO^ZJ=Rs&Tu6U57AqG{lLt@6q_XQv^YCP9UNY9wJ&ZcSEqz%ba)0TdX zUQJ&eC{{S&wFh{0ry63rLAXkyuaED)WIj)%qie zVmmeUYt)?h?`~95n0GtLzn_>-2sUzdB_`PU?Ua3EVtVu&*cZSWFlLwwyM*9mESx}g z<^>RfKSIRV5b*mVHdnna)aa)L@dNU7?U_v$RhMT83WL#m4a0PGjvguGqiefmk%%67 zas1YMusWj`??fb9l;OUpJ8p!t&G5?j{k~=g&#Xw@H95_y_-w3+k;s}z&kG>N*7C5; z*`7K$bR4^ZrP}8E`ls)M{ms4ZVS;lkL@ebi7G5!)B4wzpD5zB!4Hw{%7r^@IElXhR zds={<#YwmcR)37+((*LfH>DsdkIhVClRTW;9RXlXwBoM)y@qqfc&u_%xuSi^GBL){ zyzz%Y12^S2avqP~2xij_4VNprO!yORkmjyj)CB$3^|gRpIeYLXC^;D0FA(dg>cBzK z7F_Yo01x<{xbut5ioEo>V-XUFh^C-4W(_$`)LU@!t7^0i0&iFMH zzn$Icw)jdXrzj_rQiQzMB*CK&kLfW68+@Mia$N6xyTp=}qty*&@XF;ynh!)r;X|a| zPu+4R4_ z?aW6=+u4?iwxF7e*^Ak@um|)M2`F}aR1lb>ckt&6 zulj6S6Qw!i;J;#f$!``|hRjw)eKK@&kM$aEm5lsH{$_Khqn{$zgf;v)Y_>5O1MfMf zVQufdu^`pD(V9b(y2T+XY#NFa&$hpIuaU0aA6$Q!LAH)3uwg^SF%ffCDJVrKd(61z zyas){zivNSK>kf1I(94X^(Ey}3~Ik{FQn*N+cNp&nqwnjGiSoaWR|`adAYP!@Ad+S z6y$KuF{ra94wbpr3L%#`eLB>p8_f^s$t19F325<@UP}^LC3pc)c{o)8Ax4kMk^hirRqGfs_`NFc<--z2v)L|9Z!z5qB~6;&I7zOiDz z4@C)iD;xXCuv#W6=i@q-v*P*`gktXIgy3m7QsBvE4yDRX$c(*`Ihd*fD*w!=gDy^} zJ{A*ycU0S@80ztuzExhgRvGswQzJeZ^B7~(4Sn^mwdwzIu>Y3}%YTQ1g`a?tR?Nw# ziO=wTosO@sw=)GYT?z9>>ZX%F(yEs3hLV&FXBvs&_E95cWo?%}ddEy#Ye}cQm1rDE z@z*UEq(1Mm!ZQQkoW{4Vctzx|P9v?}DduJ<#L7;7S^E8vJ>1CHQVuYTtb>{7zQ6p^&8!Ub1=(Hin=YOc#JRgYO`hqjDYh9NN3@(Qn+PmKg}FcaxnP zgSq21cvY3+`xjdhWXyf+^|^|)E>{LS^`s|JTCxQb{B%5QQp_AF5>(<37T>V#BHVMd69V(E_iPy*7P->J0(yhDNT5CFw0U{Df2z=??E%`O)*o1%x*4@j=|G8Qng{aVl8F0 z@RqcR@r3$N9%9^}n8hg6zW~&TouU*qtXzdV#WWwxq3o9rACi-gG_Is zXl*e4l^%2WWPz&p2OX9%MYe|zCm!>Q^`(${s*MnBJz95ns^qW->Xj>Y?D5Y(f!5kv zUcYrr%F&)gw@|xzPw&lX2jk6!ZUaCRC>I%wlzzDY<{hH0eD@2 zWq)RpS4$~5R`j&C_QU;r8e^P|Ea_co?d-e|R<1xb(ez|+YESoClz#z)4VFPs2KMf0 z{WOl9^z`>7boLvS;U+?(8FQ;+#3w6LrMZ|Dv>LwFssCw4{JDxQT(>l8_Brka0I}j4 zZX^j1IwyR>{py1&hsFIo@B+|JMNd`?DI(r1qk5!uevO?a6))JvgPotY9vQZv_oXS? z3MH0lCr*#WDKohg>glPK;n@KjkAX&Ok75_X>8kdJ!St>Rqs0qG=_pkn$*nL&DpXCh zPCBdFf2eow#OWUcFRY>H>F+kbP3i>&Xx;fy>r9$cOCpZZ-?(c&tK!)x+Uu@Xm|C&! z)?07nIz*D%iIIxE01oXnkV}>AJ=5LFnqnZ0NN zrA!$D20D^>59HCCS7sg1pE9afBi)S%1fDkUgROg!r? zu&UkO@O=7g@;0+Q#*BX8oG<+a;8Hvy0YCq`Q)&&U>x_Zhkf z9Hb3>qg$bej34>RAWE1eL1l(mvL1n{Jm2{EaS#!qBOv?faMW?sEJZ2(>w)TBLCHdo zTPcfO*OxnsGLMeJtl$duOa0nL=jA9m79mv!u-KP_YAPN`KLL!|JgSHBY^NXPf~RAN z2$r@^El$=ZB>>Fd)9y&!&33qUs3$8w1Im@YJWvi2Y{3StCT1;{cXAHAI<@5s|9|IK z(3nv)S|B#F=2Tys?^CLu7#o6=uPWO&k~M87PBIsampVzMZ*QNTpH?gOUFZ0nA8K2FMuCw0sWpxLs6QSkmU2l@%vopNQzIZ2y6ZmR>_@bKfi8^PkoKR zXr_wz7Ao-^S({TO;-*HR$=TIK7Io@`Nm3Jl#f=jF3@qDM-5g`EP`n>Qnpuy0!Ozs) zL|J9CBH-x(4s`z0W?eL#Z#jX)rI{E^EkzLNaylox+2LODwQ#46zp@&3p1C2h_>QS{+6t&EbKHc-$Z8v&Ew|0`>(cFqRC4Z8j&M}mlyhXgm>mDSg zZMv@VNYb1RPt*??+SRi5LNh}y+ncQ1zc!efHo;ZW&a@B@r>hJY{YPl&U;Tdv^8XIt zD?#EDo&Hx^@4rsu4P*l{=@ZNU6RB4Q=?FeoQne;D!H{={ws|bVN za4!X=hNYqM&*iN2V;MAOdeQ ztcw?bh<^VriA2Uwc_vZ7q|M{K2mUomRkg+C3eSotfPBqp54p3} zzMCt#bL>vV2q|9$xxuo1fhh7V&p+Id%TClcu7%iN+>q6WoJ*}Q-H9JsWg2`R$~tv~ zw4tgQl*=ncTno=J4)5=9>a%}om6JPdxcy^Klw4nQ2*#=yD{-p+bEf!{=j=$|{l@f_ z@{rpUZgkx2#QMGQjJ`o#9T?ET@z~&H+${7F5w>mXb4}AUtNP-CYxDM{FJgtqm|xMn z`Aw!;9lUh+Z9I9~-G0K|?99GO_U2ZZ?4VB(zN8{v=2%(jJ^heIVtp(0;Nqzh4*dJe zf}2#|=IX2r%TAMWP4m42J39Z>x{r89siho0Zu~6%m|aEuM{m&gx!2XJI**ENm?^I~ zjOX}amO5jsNU*~`Sko0-Caz|sy1$*kDz$<3w&n?3fpvAaN;%}<&cuc1Qs=S{wSD+j z?DnB+b7QZuIeDVi1}V>>YKm5*!c5l<**dVh6w!WyA5-XYP6?rR9d4xC`yF0I5hr^7 zvMk(f;`FIj>_|A>s!j9sweVI6gw^JCv&t74l{pU_G*`e+`|J5U|3re9QubQ_~oH$EWYaDC0f; z6axU2RjSJnK4MXds-ME6K}`|*I<9o~v6O&w12QvV0T=u(5y0OP#c8teuw9X9EOF>T3^)&FDV}@O!bEtowQZI04O0lMXYUG?8 z-OWJn96rZsRM^6ZIe?AW$e@gjai)#y%vK@5c=7lu#fI;r*ahuGqq6Y#%8M;+e}X_4 zyWn5Jw&Z@NsgHdF+atk9fp38k!d zl#Gg#j67NLdVFuws0}_n(ObIEsTDVW0n`Xm;3qR#U|*s%Yy| zOz%urt(vWq!A6H8ifJVli}mp&pQ?PG!%?VEQ%L!ZFw~*vV{7pJHG!|*{d@Ms0$LJA zbVHGQ0R*}{_UV88DRXsBr~`7J25i+v#@$AX-k`1~ZLcykO`UKJuE{m%c&fd}(#Yv2 zd;-N_LSxGy0}lx-Hr3-I@88{~YNW6xa?0Pj=&(m+jLasKPY6)L zVj$xE@j$OOs}N*Q3uAH)6`5IPN^{Lz_=B-EH$RuAvJtltD?^O;ZDKa*?7XyXES-kk zO@on|ZdgY0n0jxaGG4o=`l>UyO#&m#$N&SRt}Ib3mBu5iDJ%N8e*5HoIMVUKjeASH zE#CYqxshNjy36I<{!@t{@fKB!rd2(?{@YEFre-Oa*ej9;Z!o#`)w75SQ6eR9HW@JX zBlz~0f`-Y-wO-rgg902*@Ti^7P~X7OIu`PMSHcp{)|bKvW?0l=Jkhc?+DRfK7YnXZE@*XT{3N2Q#i=4Ll^dI1o#J zdy3sIE1|q0RWm)9;~D>Sxadd0#*%a!S57yGD5kz9BqjZ6+d*+E`$3sF#EfaXnwBax zY#}3pk18`CLdW!565xUQ&zo@{*}Md&-%8_U53*D~4hW zgFt_`j+tqzF5;L+(t!_fWdLn=yom>QDS6w)3s4y<*JO*>BNB@pw~~5~I<22MwKsC! zXfL(5khlk%=zZA^>1BR*Fvg*FjxfB+GoR1am0i3g(EbAGDoND&%5o}`dZL)|!AA7T z4C-Hb=ih~f(W4R9Mjb~`Uuv}TzFAo@dq2i<1VWLZKC|T)5qsRCaf0hy*)p@IwW=tw zmBeZ!EWhW;dI@b;X#E8xOVerNUwvH>x8uWTpXzN5ZY4c3l1h)2RT=1DR6W%36Jwan zOFPu+zA{h{z@x9p)|a@Y$V?uu%01rQQiwE5{CG?1dtLPoFEl-?wxIceMkz_D>&wF| zgACByqvHjz9g)d6$J{1VK)e)*Z`43{Io!Yze$I;PmZy47-SwJIQ;2eRrPB$G&;HoV z@OT0AYELEwSW{84!FAECdwR>OB-2?JvVH0jZF@)FV?QQTtLMgqokLvjPR^WVcFn;M zjhj)zETmAov63%ayNuC+q}W~Iq|wMuoK@YA8YF8f6C!z2ZVNMPOZMZvg?M%1$>2@J z4;w>MDz@J@IZ74kwRRCM7tL3R_D*(M%yd$@5h(du2n8 ziNxIuz0Gdy*Pn0`s2a|?H0%ZKt&eMe+}tdiKBZ-M>^!7KQCZrJWk05BIwM(|XsL^i z1+pLO&5I2E92^|nO~jBDsV#Xf^uT3<xoaHhR|0W7-RB-|_aZnj!s zy#SDo3orK>jV>xpC`<{r$OioThld!bZOAjt%vVAF9qm#-S%alZVV{P z0(#!7*8G`et0ukWxy-f2KB#0PsqX4ri2_v0JW1p+1yh3YMYp4~GTv^I5^i5WpzIEa zUdE4e-_NSs@6l7z`m|+hY-fle2CK45C(o`;-YMxBue``7Rg zb_=YMZJF5XA~m)zVmlOVGD?%EC*KM7eTit-69TWNGBXvGM}vtnySh%G1}w8U?@#)J z$W?T0Z*J<1%vqe7=_y0GCoal-j|bu4VudchSQ_98N^lj|ObL%05pHpx9n;PmCp?3I z!KGLJ207b`p&ylWXN;ejt2RCGn@zI+s23_?fjT7Ezls6gh0)Oq@F@mmr};PLQNP`?2LulJP;m{FuZ z?za5ABE@rAPP?kUn2&o}zFe zOEOVJPLQj^T|xa*iW+(Ebwk&rOseiHH~<^Y@wYN8JdjLHiqZ^oIfWiXk)bb-mn3UP ztz=@DibbE+*bq4$9UbFMp@zLzYXTQ7eqQrY7D1b>A(W)%cvravOc}_!osH?HbP(?7Uu}0FrBpm;4JqJ$YZJp{shS9gMFeaW%~fBIx>X3G z9|hbdD?5Li=#c60nvGs(2LX?Ll+OyX{Cr-oQ^TiM-Hc9TJL zCY>v>lMHz9OP@cWzXbFj1F5xM|`-3H=*D1 z+l(`?6hYhpNXj_bWg@Gzr^ z#zZaHwp=OfIRsf`;#}b_MH8xwL$-eC} z_O*)b(6H(btOfc(gi-`@Xg1SKOs6llQgU%A!MP&a_Y?fx_Y8ky-jf>{#6vbG0UEFl18>g=Cc)o zqu4yI6gE$YN_za8W}`Kie?Y-KGu<>BwX`wgsY3f$ktCP&eM09F+8n`a<(#q}NICE^ zJ&?4flPxU@yUENzvbx2~YRyvngdi?3$4n8!j9~$v&Y(HlRXf{vq0yT>H)-8sdjf(n z;8w2|Htr;FLK{JiB3GVeEWP(Ez49~3>c2A(B$MA zW4Q{WVB`8Wv&kVU1d9vVT9#SiugXZ< zSaI`n2rTKbn~E&E%g2i@bhiCmQ%dskc?^k0Dq55=dQ{8l+RJrgJ?osGjHBBwwQliK zxVOWy;|1+6nLTh7Cb^9S+{f`s3JJJ?{N78FIPzVsv_m=#-U2FaVG-AD&;KYPnGlq9>8s<`hgzWr^QI1lKxD2d7K98^AN6Y&$7oJCWC@@R=+8rYI{X;Wm+j)*qSvOj3;24U*MJOF6V~mt9%N3jpmH{OPEz z?%4X?->>;szeKO_NF7do9N&60npRslB@?7I&~N&qiwM2VR?Ik8n0@im{N8A53`6sx zBG(=yv19Ohz6CeWRYT6%1Jg@%I(eUyg zovDi_rD=n@kGA0l(i2AT0x+>Y^*b#Gi;|@Z4Vo8tKb!bS`Fd^d<}?G8fBMsYW7?-@ zxQ7qwm(UF(D9a;dvD?$E=kugWPF=eag6pc4z>l*YKrYryI2<)OTzuleT-iVWq#y|ER7*x(QC5`cyWUK6Q`^5rGn5bcTo8K>_*pUEBud1z@4VP``KF=HMt# zHF1doBA^=a&X2F&Z%EA#yq^Vu+%l5+8XC7jN*$E-iJ0A7QAe6aO~=Szq65i-+uRA0 z0_Z8C1MNWKXyPYaaHFdoF{2KKAgLA&bu;~USagjg2mG$lSD=Lkg-h+~ZO&iTvg?^+q?rWRp)f$SF@qe70Jj{Vay`k9^Xp+_LL$&6&B+{mJ(uc%16%EFz& zC>F&8OsS`yagMwVLzZWPo7XC3|DaCQ&?q*-q0^`4MuMs)pkisKiHCE8Ns6JpLyZeuq;9-qdHn?l~wo54PSx!csSgPW%&0V?4)g3}E&& zv>qq>@LekN)kpn`{4~MoU#K6^?FSGM(=rRj&?#fWxVThq~z$Q%FjYnXR5D*(VHK zwRRo3PKd4k)R%_%w_nzSl^F^=-WFEI#Fi*HkE6^8Zjd|BvI9yaJ(}dHY1s6+B7bKvX>>955GE(^t3!)OaqV z<`X6QmKk)-GDq>PbZQaAjAe&OjkW$V1vcTi?HCewuJB?eGiDr}D!5<UP~W*a9>y(HI6f_j^!PHMWgjz0a;Dc`8kZD??VD239h&d$$Gk0h?mc1(JVYX%cvI8LXXQ|pue_piIu|P$)hDh=`EHiGv}6`* zSQ%E64pmg_l+Ev~T(DIc27ziTgyCbQzw8Jc%H3?0khYiM1V3Z#}i*#QL<5N)yVD-@^wP zR7mDGN)18x57ByC!iepED#>JrfW)t{;ER(j4QwiMY0Qn{?YLjR#v%8a1#N2wM)0cp<~ z5l?K?$aUk{=a7){_pyRM3GLjL?H@F)u zSJ6B}m^(G%)@Iivaa9Z(%fwT9I{jHcPejQyJFAN0$1Q__Lw zCeN>2pI~(EXgDmxi`3IXeXEGY^rWdW-t7RVWhir1ly$! zN|KBO6CR&l-B!BFozIqidtW!R!C|%D!1m$Uljz`>D-F$I`rd>__gn1QaF&vSg`~FZ zs(D){S6+lyY*N9(Nmh}8fJjpTDtm z(G7&7lYL}oJB+!Ut$*Sw1zTv}$4gPBR8CIBXb(0^I!dk(G1M{4J`~cVs;squTEKZv ziW+w&TU2Kv-7B)Q3vDa<7w1tw*F#f=zZlzEoxvP<*XrwSvEm%?JJIZ0EANwiehmo{ z(ziWd0Q?iK6l8s+V}b)eq{pQAD!rJIaSQkg%2(F5J2vy;Aq5Jx-H!=bi}gnj77H%d zbQT>_Rpc2)tV|Ar^vHv+l?gg6uEEy?C-~|=zV-_wHCK_%o^YYDYQ`>&o%1E!VNhLF z=}eg1`5EPQ-SRtUmQb>6Ryfy~z`G9gd50Y8M@c_&rstPGX5j!yWh*R{GwAh+>nb~T zT#GyL+t^#i1C3Luw75_x$oL3?m;z4eX(NqjGdDZDI_jEgnm+1%njGN!eIkJA8U9cv z({3%*@4TC4Z+x5-zq<3re&WF&%^loR^`@X{g|z5N4mPWHMLaO=gMwG18ho9e-TVOU zr5lNC9<8h*u<@Qu1b4d(4=*yO{k8CrXKwfAaQXaz!E;H=nwIVJJ0S_iH|k{B(MZL4 zNV>L6?*x+wxlU-k6-U!`^)k22OQ@qTVH5Iyz)`@m^*6l$c#HSL%KlF8{^QPtfA#-! zC(C~n8UI(&NzPP&GiR#ozh#bp5sCo13S0C$PxZOQ9j7uC0iFI`-sLxl)3HK|>mXUy z5GY#$P)}Rv&GE68YsnWBJm{HXdrVhd5K)3gqz=oML}hF9o2O2Rl-xwPbeQy+keW>H zx3tNTQlcyzS2x0aHP+0%1hP6G>T!3~)!+NUy9kvS0bP+o$NICC;>~Hg=|P?fXAL>_ z^?OUUgxe<~+`>td`lL zf75P39ljQTE4oqea0_?M_2GxIFnly4}kpO&ov=12EpnZZ%JHr#WJ)Y_@) z+dI_0Ohvhcb;HWr1nthO{l;+>bv=EDdC5;?%c-E%aauI`{zkmah^Fmy^lNK;PC_`^ z=}Ya`JrH6A!`X6SZ1SBJG$(?#u~()=NLhruC2dPK{h*zw|#;>`hB3*;|t#)uZ8EXz`iaRXsLic(I5Ycn>jqjQMel)bga(YcRu z3SW3kQ?P6%;2q#Zh&)zNk5JH?bGaqcf^y0a-_Hs@#00Yb#&Ngw*c+k)v*`(jR|b)) zC0?VlquJ}zo=rweWhn+82_7S!WNz)R))p7tIDafH6$u_6C@QfKCUv%8y6%k%5uheS z{3BXv<2K7D%M?aIO6Wo46?#5k6enAACPqq+`Zby{Tt!h%D^p&oAUEm<9`1375Zye8 z16`dvoiId7&=YbbT!%EcFWEmdtlpBDXOl+Jo=SbC-fJ;`*Q#F|Gptihw~{{8I(Rd9 ztSKg&=~hs_Ba6L4|pfu7J;obE^k8^v>**?Pgv;kn9ngdd1b zN)J6Oa9 zFp62Fv)$8HU*&D>daj(IqAZhIa=aryuM%l&c8eKtr9T3R(;LN_$m~rUHtk5Vgv_m9 zF5b2=a6SrwIVP;V$LKcPtWU5Zn~Wy4xgT&I1x8%V=f(&+%@JPgx6 z|MBKwj?Xb)4t3l84 zh0*c%F?1nDSvwiem{Y;FVM6utX|^l1xy9&sg9roKI~#rebk}w5LwnNwi-;gyIl@~~ zXyR}M_Y2_jlDC;i24KgALP$8TUdA14QqB-j_sF~sK=Ea-fSw&cGs^wKsyWcWl;Kt~ z68X@u?U>oT{|ZwV(K|@p+!IU{p_+c+EE0C6H6OL0y1h*?$m|?u2_6r0o-A47BnrY@Ca!1q{i z&v>dE7s6SEmL+j;Fq4deab#b+TO%*`@YpH5xpY@4%@U|$6OTY()t~$%@^C#tYAb(1 zWKhRC{3Ox?8ZT&#pkAU%$VBv*o;PNOx4&0hMs|-*4kaQzx)hN^_ zo0s=i%K9j+amDqHP@kz23hBgQlEAxOS*pR3R&pdi0l$2_aFo^#AB1Z9$zt*)cm~6aJCwH@c`4rfdL79_ zL$$cC9FGU3YIxVnl$KCAn8vL!G}6Rd+0}Ni*X6Q4Cj00~CVQouq}uYv&scAWOf)bi zr$WH}LsO`nEt8|vvQ1O~{gdSD<}_D(PdghHV|HmNj!1w2fFI^qv1ZyCh2%N>|vBquEeLogxT*4Z+`kKjz zy|sZDL1~KBkoA$2(5w&qk&$L;Q!y$#vajW+66qIvUo^0Z$~3Nn@^1P19R8WD$3Esc zxg|&OWAtSNv@LE&t>^3rQco1;BkxmV>`@hXa+Qd+y06_m1j8BxSB z{>dc#X89vXNAnyQS|8e$A*bEm9Km<7sEnC)3&e}j55iMoUA5izg0i@|D?Vp%kqa1{ zy|Qxke6auZs^EW2egDtt|Hn&^5OBZzZ@wlfa!Mw@=qrgl_rFy|{SCJM^2&sg&7Fb8 zs@v}z?QT6IT^n~;T)el45Z?QQ>^_aUf^h_OivKJ!skoU~@3kiEjf6^T_TRdb^Hf(+ z-$`r^);&s1n*P9^I{x6$DrP$H`&I}+f3`A^U52{Zo#Igx8H1dWn$>MRMP5aO`Or*Wej{mynA!_(8SVzuWcuqi=Ie13nwBITd^e)+E zJK=uLtmHRKhAW>Ae(RLYPe_l5-{rK2$CQ&dxm^6S&9N!Fl&~$$=dwOe^0Bsu?|ce{ zG5VdmZnvH!N3*Fxk(P6*p7&P5Dokbs57Ak&GiO(GF1=i|Q~mS)?D*kqS-0&97#>F# zcB<=T&hWi;j_M)2X1L*IleeI8f|S z9@>w(u`m?tj>oh0PJ@Nb_3t=>lvqdN{BGY(WbW2-WnpNqV&6Pk@0kwr-YZt&B@|im zJmBrkU*o#^W(q(VJj1){krT<=8y#ygzVisEnVE?479SUd@8YE*qDS&_QA?%@1yM79 zH--dLl4R1;71+!V)f~ia z&XPw>LV8Yl_Q2LQ=yk+QeruF0_`J>c>OR%#V{!a6HHb{w5{N?^mvqVRL2nlor=3Ki zQ0$8rUI6_g2B09thj}Ry45!mOHK{V4aHWRB2WaQUn1AGh8nL|WEXbZ=q+F=wnQe|U z-jXevQdzOxDnGTEt%%+#;%Y7q)8sphma@UfG7GLZLv3sGFq>@!$)8nT^;>SLHb0RF z+Qrh*Vq-k%J3-Q!OnM8)TJw$d$Wb}ThW4~krh&WPlyBc!KMkrYe%9R%=_Hx?NWg>+K8=rV8(iT7{UZ=!>Fy3)fS% zhaXPw4;;zp?&Q89bY-yL^%DT_MEHd7X)7Gwk)t~ocF4)$KB^2H#1-puVDlTDRmq-< zL>zJQsI`W>e+~?qZzgdb)j6Asw&CJkRK)O(qV+vhOUFC_N|8TXo}Ih3eX`{1)n+{b zPHxpOr8>Bo<`IqOy6hLVHfF?sKDUTgpmyzN+$TFoBo*IZgN+5o@3mh5{b4EDybi za}J5>$2Ir2$^? zOpC$L(gGrH+qSmk)zjO$qZF062_Lfk*?1t=Qx?cBfbHi!oa;k$(u9s1O1H2&LZ*(( z^HQ|fnElmp_zWV+bR6Hdzoh$Rg;HySPXaK+VOfYvA%kGSRl{Sctka0u3nTY!s(jHd zNp3p8TaxbyC!e4zJ4sr^)17Lz@Mg@x!mEGGm1um4xV#p<%F_NZE`m0&B0MP>FY)s6 z_eFznUe(qYeG5nY5skTzUfI?J6fjeOIoT9;*7i55v74&O7+#LRx(MwI%p3*!O391K z=R<>@%i(dfH5p2|o2DHHk0y#Zt&2a}`6kuYP4oxle7AV}mpVFanxV1Xv&F<(pF6a3 zjE)#3m1Xn<((%|)(Oh=Q4XW;!FD9*~I^*Nm?B~%Xojec%{|9?#8Prz%uX$QpD3n5J zp~ayE3dP-}EyasF!5xCT(?W6gqJbj8La^ZOP6-~|H9&Ch=KtTlckk@%+@1SkcXoH~ zi@Z9MIg^|@zjJ=i_jx|gja(#5&>8>CzU#QW9&tdQP4nDQQIOZbN7-3@Wn5J)$)YxeZ%ele}kf^I26QU&%CS13P<3glw$`(S19MOG6TaWH=V%s$Hb6V-bh zyq_pd-sjqG&p*^=Qc!7xYKZ-=%2S&i(vLpXgIWBtmvj?A`tkn72=sFQnDB0NV>R@f zlWzJ_vQxprwd(44h^iz7$6pMxF{mP!fHwz3+xdn}}Ur2YhS) zkEUM6zVBL?njZA>d|NmtsXlhrSPkjFzKw(?&5Ux4&B2%|VTo0VF?Cw-3;4{Op?)kE zkp?=M*aYXrVS%dIhX09)`iIg2Hi)n;&07Jg6ielSRdnU0KvL+rgbLcyu2WIj(v~q$ zSySJbcw5n{_mGq!s~^MZ>@Ifz(e-}|2kD`nrX&T=AYTPrNG@pjWcuJ9if|r>0-8Oy zrVC<~>O^Xcg9fF+6a;+*9&e*pj)HGI(w>&e`UqTWx$ovAfMQ=g4+%22xM4Qb*OLYDy>IIOB7rXnXiN;v;r!ugl~;$Ng3T*e&N{{cMrzl8DSqd7%qgti-&Ayx9nj%? z?-3*EYElM%_oD-=sqKZ$Zn3V{TRbs%8#BRCOt;U>6TxDnrH`dE(W^l%=%Q$t*zd-Q z`qVF4J5qfvYkx65*0@k4gw5rXbN`9YCb&K;mzVcxt0_S&v8ds{6kb)T5M^qf@zC<| zpKv_2Tfw$n%VQLFQX-7hU@9&Ek`*;DXNl+@78?uJO(I1)sF%%2j6^+Gro!%&zm?XxC%DKS}$-T2wt zONgeBwNKS8`UOvMXaC>`N%z9`vU1^z)8;@Ee(T8c&T^Kp+9O)dJr%EMpC9r`;v&)_ z_LzS$zEDRyjtdoEC&ll9u^N?L*ldsTy?qs)Yh3$&9UHyNoxUqA4B^zcq%S~6*f`(( z)ZI+(PIc6amYOWG6*jB5=nE*Ylkjk0OxovHYG(0J3LyJ}oRAE)^;wcg zo${$qKkMPz3EOKLikKdyBGG8on7wsHQ2!)g7$zd=7Ly(E5V{0YeAcm{Mn>mqH77xf z#}ywZ4KFDCn(L<-<=H{{V5wKjR%d=*ZE=PQKZ^tgiGnh zq|4F`syBmzzlMW`KsDhV;)aI3zavL5ZFB4?`y@2MiJ6$nQ$21%AA1qulGtKtzsn{W zix0{U9n4RVzpcqzg|$@juY{z8&v70{ZQI%>~BoEx|4tXZwsSG$%$RlmmMDL_&6J!ryn_gn-sS4gGky*kYwYGc;`}y?5n{y zBYfr&m;>3KLV0Ui-h791&d&v+N*3>R?7OvWVH^#~TfPPz(lV|c^@8YLYsQ+qtxJFn z^3rwB?J}Dc)ODd+umtfUPP3bTXQ8SWWr|4=-{XYn>$YPTs0uu}PjeROs(Gv=ksY9T zp13YGlLL!(GbMkXLgHRjEXI84%dPVfh&0<`AJ)fe~Qkh0&Oi+-v z@$thbZpLB@)FG=4LhxE}&E||VJ}*QrJ-K{=o!-yEE^8_a;@7{9ij6ozzX(_JJSFTE zqyliN%x7coDvk4kh}yz!d61fWjNkIPX(Z{O4A_)7z2aoC%4l#FgnjF^^}|=A!;~#m9_lLR|5MMFBCzy<~m9UNuHVaPFqv? z&B+kg%LxEgkza|-?W8hi+6Ch_Y4P{j9ze($lyg8BR5DaiqatbcNkx~60&dT{Xg?zh zGfLE}RHv84_^u>?{O$$5%9Bq0JPn@skp3~9#TS(s(m!HR(lL3VbqVqDvU8y>Q@dE| zeK?0YutG1>f*>}#Wf#l*gG!27B?UF_)CZUx1&Md5NUne-HbSDK)g^)xEXH-#aU4`; z^?ES`i&Wbn`|~W_vt2+M;z$vBO+lJs9NO7=USM{1?w9J4kmAY4nr0Tk(N5KszQO+5 ztt+epAxL3T%S(#OpA_}1k723kyGy2j^6nH=D|K$nb##GJ+$=-?TPK)OpeW0!ACgni z#Qv*I&z1MZVWxX^&nX)h2N0_vCDaB&KDT4MtlQ;db1{Rf%h&7ZMYUEh>LOh~@qs)n z;Vr|E(_L&XRFYAea*sSi+x|Dl!k4OEFQ(2cveAqak+N;Ng0zX&34r+cwZC-AWNqDR zT|L&G<`6+OVQu$P?}zM0_gdSauvK3k2WCg28<1(d=KJGO2-jhFS(*<={S)fJ7BSEI z#TL?QS4V;RnPed+dq;Qootg7IR^P9FVt+9@gfzjfs1H@ zo<^LPIuJA?K2N~rYzylo#Q;)$!;#s!Z3RlJW6wOB^WaAH5#$>%-YxxlH_R91Nym^EQF^Ki^2YtQdtCDSs zry|*+{;*!p)HPbeF@czEwlK!5OumSZ8#ngt(arSdbkZd}j(rJ+GR@B)R&E;V&)X|EQuyX14b zEb%B2bL&-69===_58eDQGGUpjob6UGL>hMD02BwM73miHa$)e&^z2KMdop6ss>>uN?fACvtN4^>Ul zf6L~ff4XYKbYxd!SzI4edx4pL7Z=`-BMlO{0Ne%$6ERR&Ez&=^ z6n9ZClv5B}VrF${{L>f4WWhdHpzu5nn4|hd*B2b!Cn?ehs+nEV`G45V?+L*FG+1ONj@uh)g*B#b~#kxQ!4h z82f3@8ilZr^)p)gJfwdeA)WKY^1KYNU&KbI^kL3!J(`axDEoRqbO8E^N?=8m{4f{62>FHEd1*>YB|wf|q33(AZ1J5jXEuPL zoq5BIPmn<*qNj&(&-s?*mY*R%b;DTY$F97jiKQ7wlrv+0dxzkI1{Y25*6yz63VhQV zl5Le{w`C;Z4fXZ8)sQ+eSr5)q3Z}%5UjynSziS?T^%SFDQKLfWR^8%)KI`0%H%L0G z&JjP~k{orjeOj8@N;bi!@l9sBM~a)YpLT)j;e5&qF@>xq0WgZK^dx192yJR8nAe|d>S!*Z0ctQ7*&@{|!56RstE%w~~ zR5F)qhcvtJO`O}-{oON&ouNkXL2heR>Tou~k)N;zX{7kgLOt9!Cs?ox<=(W3WV>KZAp%#~ss4reE=4?}BdbNCg3{xr<}^;4Uf)9&&WmYYw5!kD#Ows`%%-r$%n=34=w%mx@-| zND8cTDv(@dW~Qo}Nu9;<7EqntfZ0d-xaIuDtC|q_)?|H4{If0<-k(b}oTgp1bQqX< zx(9?&GDp6Rab2e47XyFnPqw<%lUgKH`!)gL*?GcO8H`zc=wApCej?@ZPUAC6_X>va z#P@+wN9Lhc`YWU^|M;25V8#12<7H62XbUhRh8pp3l806U{IJ9+Lk27EPRChO1L)km zFQaQHX&uvDoZiIG%kLs0LvM!4&Chw?5rz>mfD}e^Nzjg6IGt+Y zpV(1}5yyT24WH7|flpFzxekYDOiFOtvFlcmfGL}gve~UJX(~fWOrs)j5BWy$^10C=4IVHh9?`!&UK`_|yG2!w>JKvEuTtFDi%i0h=_G zWlnwA$55eYd7%=#6oJQe=K;_4c9%#LOitV)N27RDOzFd&>n~PbpOrIBn#Lr8=^Oov z>055RFHgleMmdSO)6bbs5Gap2nS$~bQ6B_i_NH-fd-bS?)VTS$Ev%-9_xVo=Cu>(t z98AI?I|gjls2`cH(@$f=+Fq2q_5{?;w$m~H;Q1s5mwv)=c?kvaqy;BWdT`I@kJDnA z3E)Xr(yX79gJe-#4ZjEby1aw$lenc!v!~Y_YCd(jI}+DFE^Ic}0PDE$B&fDz)cH-O z8_3;{9wdgNw7sddx)Eisi1J9N&Wq*wTe?Qf9=$Ea6`s>iEbN_3||yMJcBTczJ`K}$aI3Jc5sLKt#6u*$^= zQFv2W?!#LHkD*~1UA5DHF^*#wqyq{^+hIw&*+P_%JBHe4G!L+o+4MHmUMXv|nTQuQ zyH;T^G;zWgZ{K&6*9y^CkZ zfdEghG?WwYxJ2BM!v4DWy6`Cw(NZXGZE@F%<3R6^k4mAw%mtf(_l0viES+K#bf z&Z6{zS^b~L==7X7{Ji`4n3KFJ4WY|Omv7c!(Xl?PPG8c~!Q7Y8uTJmjA>>h|)S`9|O zsP?>R%oNU+AK}}TlIVKJ*tbJKJgYDL1XZI%VkSatoW98`j@?DelcMJJ6;$6vqXqv0 z`6xV~b1CF>EoK)Qc>~kZBsdsy+c|8*YQZaoXc^XG^guM@z58}2oEaI zP;a|(y>6Mw8U_*VqxRWyS?+40d}BsVU1n&UwB_V71Ev4WIH1GO`tf}?W_NDa(!9lX zEBa)r3DpZFF-3H%ZAFmv@H|C602LK`NOh*Ur9m4z_rBYWyT}@I+A3WS_q%hoAo<3_ z<8|(ZIB&dG9H>#<@o4Z9oVORYuUIVK6)2B@T$Z5R+OwUb3N6hNfl@@8O4Q`Hm3-ii zs~CW0d6F+0LeCe!+B@yx7TO;toXK<`IHEIg_PiKISCztdDtjF-{v9)_@&IkrGpNXZ zSJBV_^b_rwENV&%#cfm5Q;HFBolR7No8fiaC9D!)PO@J;Xtc0M+CWn{E4SCVSfH5l z``S^`JZj_gD8TQj#p{E{bp9pwi97NiRP)ukOzM~N4zyOrFxgmRR z_0ZlT!8%_!3r*CfR#nmsPfLsBq)RvV=HVF6bB8&&`(gnz)Q6euhMpex*rx8?w*F2` zmqSyv25@18vx|FL@pE&ZPL$gzyFs?ZwaTYF5eVbXEuV>;1*xMjEPl zYIXV(U-7R7Afr9|K9ra)#m7CjKj^zAm|#dBN_S&8C@LK~HfYXJ^^ z_mT8)IJ-*$_w%So+9?0`AkY6kKJWi)=lIv`6k0|24+N(^=U}DFsdD~nhXyXj_@A0< z*z-yCSXZk-c!E>#h{v16AvUlZZt}}7#Gf#)NJsUl{E~)TMQLm zS21*)@d8vMM_@)Cudt+v?Gal`n;w8MiagS5z=z0ovbhd{n@p{`15?JGv7F4w-PWS@ zR99QawgR~_3ZtMg2y5r+Ukr$}0e9rjOrC9NiqmeioKk~PW>2xN;Yrqq(F|cfixIfJZ&L% zC7Fde=`MMaN0?m&;1z<1;C{QjdeSnVc~FfaZVDpLCNN->SqfNMO8#rBCaJUmp?(56 zC$<{P+rzdf2Ht~Q&?O6|BvK_&v?_q~v9Y^R?`n@qfOM#Aebl@mDYEDCfTN zZ^@>^G{H_3diuI3t(Yx9o4MHKXB$K~P;alYdnhjC{zEjYwt%9pNS9ZH;{kIveyJjh z0ZA+8f0VXobj?)MCy8EAws-7ymPn(O^_G7(gP)p+zTV#h8Xrt=8hlh^^bYFV+_5ol z4m4l1<8hAJ1n?9yW9@@&<9}K9hi_BVhgh_OG8#BWk=lyrP)#Gwt-)p38Tc_ddW7;_%YS$>6ZD`Z;CC22?WOm^c2-51xxa zd9T3X{IWko9hy|=Qi*kaR>-7>GS2&c(k^B^uI!b`4D5`p7?STKH$UK2t`k$ZUVday zP}{jnTuq|#ANCYk6En@#)ROv(%W^pLWHwPc)(i5eAPuOUadRDqVn))5=;w1{tawZM zD0X}Jb$sZsWh;THB8QXvj))kUw$};72u+f+!l8I2K`|j%`i7IGD%r7{aK5gEZwtH5 z57IA600El9$V-Q zE$99qdL=ij(bur6ZyD;#K=J23Plc=8|G+f1dwMH+bzVWVd(`(jHCGh-kLHx`xy_~B z*PG#{cgmM2+@redI0Qh#+CC1DBQujjEI>6`!mZfcSUuso>j0&DPGm~=5OiLSGqrJQ zIo=?Zz*RW538@L5Z5R7HP5ETY`I zNQ3oN+P9%1)K3~S!%4M2+k$>oUWc7C#2X0b%>(B5B6&~0jspmU2QB8elWCvfqu{?zeMQtn^%P+7SN-^;Q4g3j_aGw$0@6|HHTn(KkVXrZ0}x}RVQ14 zw3+AZf}fs-ma6?pz*Ky+2|F7boSAV+Hg-{iloyEz`04-dDz+14ebe0N7hDnbJ}qxy zjWZAn`;Uue3Onu{JKbWWgL-o|2H8+%{)0|YD&l1(zIvYo;GomyS& zV?S?DTCESCj76`9?a{jX9nT?M0p`Rbon`T#yx73yfSh~a7;i=_p{ICvkGab8_7yM5 zt~`%{z9LA#l}v2$S>MO@485OqUFnzO#4`Rf_bzR=WR3nct7?b}41L68eo+jd1c z3-7aLp7ltrVh^aiA<$iZ+oPrS?4cndm+Y5_Mv}=4liYI51z>S+sZR8$qg8bL?o+Y- z(STtMUfK6KRy9N8P3X^3Y-i`Q5O*xob$jczTjf%69sEO!k@)dX(YW& z)Nk$-kEfHd<^ku;$!NanM@Mn0H+$E0v#sYbl*Wx z$`WnJosmTf2@<(VN)i_zC|X){>z{1aiNlUuGvS8iKQ8+m0G8*Hyw9@<&ah%-#1!97 z-&2W(Rjz63&9vzF?fT171owsds<;wcPSY|uYvV-9YwZV;0|SH($9?HT{lEsz{Wbq}Wv5GUi4< zY^}c6iwbQ-z?)I$by0WjjnK$9h+%|z&3eis9C6po_=!_-IV3Bu-}_aq14LG4ZtIRt zQsR|G^MT^~f{zSOCXTMX>>30p=vnkAS-wpKj!V}Ch#mp`!9Q(4IClW+l)4baxm3X9 zP|!6WQ$cJO0jXYM76;(F<2QK8UyPgmMRW{>*h-g3@|^r?-N>oZ%fv6(%Okv%%U}@s z=7&`Z>O^F2lKb|hP{7STlpwNi#^6A!RHS(#^hD%si)Lx;rJ6#Uq{V~7=SGi?tWVI4 z5}S+K@gFIKf!+QLkL&Juk7K(Ki&qu!HkjK-qVns|0g?l+`Pe?Oh4g^Vu_vB0Ytd&O zjraGH-l}muPL(9?{gf@Gd(r%zjhfM`t9jb8tY!30w4Gm?P%$lSxNxea{Fa;Ah($=N z{=K_l>WIYa)HRD;^BTX!EZN)X!@TDwbzApS)k@&lJp?rH0msUsPbLI$q-Pr&cX%?e z@*{Cz#VkAPFGiEWYd5DgXgC!OKmQE>s}S@9>_ExiPt?biD*5O^;0h-nNS3fqKB$-wXd)->3{u*2`aFT7|xT6t?FQw znsN5_-DJ4dznpQI=`v3${;ZteU=2vuYaD1h5{1rOYl2=+UMWT}Lbb2{lPB~)q5b`n zCzPY|Dd*{bjJEUwg9omPlCk~=+u@%H9r*E5rC;v8W_mV=mhR#tRL|o;{gyBexF|-q zXzl<0m_>{ij$CW7%DWXAm&>TlqmuA=K_2({QZ(B4Oh6DSeZ{agp6?lS%dMIvUIimq zT%gNy#_AiqLXHjk#lpUpXN@0i)Yq5W(rX=#9s5yVXGZbM!LgoSxKq3dr9Fedrr2p= zJzdXBT>=@Roa+yyuclLb37$!>+Bpk1VX=b^s(*Ftzb?Mc6aN+{8VhsQtaH|tG2rfc zQQq>)TXT|=tAG_5uy5Z6N}KSmmrE#6nS<_c*@Wt>FGW#Mt>u;E{`{&x7ii*g+7pu` z>%x5Z2apgNr_(;-u2GZ?4cJ!;eRU0CYnv`ePMdI)qNT;&RiUz}%wBzD&8jG>QDuF+ zC`q&Kd>SL^)UePYYpWnh9H1~!&|q|c=XAaxt^0x&o8Qb*G;>Dv%ed57)#n6Z3&`S8 zjd^Vy>{h+J!TqG`JAsin#1+*;@s9SZhFYAXPcGm5Id{IdHwla;fi zmB{@4r)&EN=UrPc-H(Tfb&zDaA~nI@yZA%MX5d0Am1-J7)KRc336OZ;vR*NUzmBWb zio7{!Mf#ij2`dBn#2a;pGPC7C?J+=``R-tu?yB$NfyxvC%M$1~WasGqmbG^@uhLq;*+*8geKqZt7$b3#iE*$6MzuVSXlhZttA8i-0$A#gEc;Wq*m9E8q0hpk__0O)0`%!bepP3{UQg)>d zl*J3xG)PN7Jg%(XH<5;nITc{(`@0s7M>o?+rf-=CvfmP_cS~Tc zf5BH&V6YGWi=la)*%F;}`FTTow(I3^^!)C5sY-VTxpRz?!=^rd-iItxG}548*glW# zL(00qlKXM}MOpof&r{01`_hyaf?pv3T)yZdwif8@Fi;K4BGZ0B)`0tmzCu=N@S!gy z&pL4FYeqN&FdU~>EOT1p5B{bSlK?UNj_=BgA)I~s=HS;^JqW)!Br|puyJ9!-+C^uk zTPjmm5MsG_&Mija%iW9;Ju%cHpp}uum#5&l+IxGS-P6W&XySM5OpA*F z<&~EMU6(RSs!*@Vtc!3+kWvaAs(okRTfzj_sPyss(v6Sow2$~`;RcAXmnlI25SEG+m3)EBcWkM=W7 zmzwSYvMA~>m}dT7nK!>P2RqNe4#Y`E%(^TS$b_E@Ar1 zSoWRNsG-2^g46E2D6p{BR8W!U<9xP0`*HaR(5$)jbQ_hX$)%He;j0DfmfiO``Eub4 z2QH;V3$tl#(-*Hk@RHU2G*KWUMb->xBYouQJC+xOv$ff&(oCd3Cmyxo`qN$U_X^oT zgGH2pSfJt(0-8ZSOB%eq%O@v7D~{68(db+oF?{7L6(Kq7j~3)GLIJzuGI;SK*!q=V}voCDjzBKj z+onKPj^Pk#R=#*NZG-j+SwutT7I;S+QBAQ6B&$!gviV)cR-?4W z0$x4f0nvT}hlDjN+NLVj+l-&rQ>ZbCyD(^hKeea)T5NE6j*hQR;hwGuSCF;%FByYS zV4MtXoz1zO;ZobjI+v7B?_@ziZ?3JF(~&B*?6Hi$L#zHzEacrl{T z2k<;Xo={aF!Vg}Pa5AoQEezf-Mxpz^#I44NbYSHmpZuLdjKKsn)G;6bXR=x!)zlew zaI>Xdk+tK3HNO~TBUiCq+#*RGCuyH> zC~SyWus*$3)bT0(*b5vT7BI-7$1&bWqAG@%pzBh}kT*Kn%_p{R`0*=A2sc?w-X@>(GsBO|8Y_R}MmvBjfZ zLrz`KA^ku0<0~!cp1+K9Q#6^RKCfpBY2{i|lhqUtN)}u5^BsCxh6h16JIbG?t{o%# zmJAFx+qRsIOeNU6oeL+EVE}J{rf|2Wt}k~5Q0HN^>tpL;?`LYctwSC(dZ})3?q__5 ze%Eyb68b>r`Q>32&}2xw#39)l0I|}wxISNu_bja9uFf5+B))^HZW8QIYL zEG>q}UMw)T>C`yVDZJPFRX*vX1d*}CcD_ZQ>+F{kz}PaY$E zbADMH^{Mo*>Ojk=k}mGGkvK-S6uJT7yfhyL4mX`P|7Zy$;>djC!1&k?_Vc_rJev*L(oq#GhaIds1_Eu@lLf9a1XxS)Jt$WgPL5i9;XX8 zIb6v#TT;)tT9N8u+v~aYF0Yx+`hO_*#l5mNegV4s;Lo}IB9qotIhp*|`aAX4m;L9r zd5IbiEWV#7eT}^v*tIjVxT7$$T^3^v{gcP#mQAOhMHUD z0frkz$`2E*%&!^9a1KE&Dv!8ex0cbtZTzf4$#d;AY?=zkk%p`~Y~%7KbWV>y>@aZB{@NnV3$ zdXa5rrXir)pDx1?Q)!}X_ER}PM~swKId1>4Elqu&Dh0eMPQM<)VVy0V-Vfo^S;iO z%+Buo*RmKqf-adt-f8e42 zkSLi&{w?-kTuE?gG@{+x%%T9r~QbgYz}EMe<-QC!b1^AbT{IG?A#pr{L9uWy^M zg+aIj4nMQKyc<8;^jQ~`Uf);GLDlA0mJHb0F=IS(i36Mnl&3#Yz}I=Cc7X#Bo)K>l zM-m*~KDewI(YN)Jl!Ycn)vxH-+oh+>NT#Ty4nYbdVz7B zmn7AK6}Hf;YJ_!#qb_jzjKF!DI=DPe%3z_TX|W2 z*a~WkOX)(V#r$kIL%ASbLyD zpLcXiHV8i<^yzn(>_K!di=8U8W>b03*8&?`gk@i@sS5o2+#5RL_aObw?)l_nIZuX3KiLgXXR{Y|+|De`#!D}(GKCNO$`qCE zz8jhM0lE?OZmRj_tf@+3Tb^EwlNT9t!ro^AGirui4>S$cY3tAJp>7=7Zn8u7cMGWK-Lp zHtcn{t?yg0vRIQD&A1`QUGCubdK7QYNZPTQnU$$%P;HS6GK)|*`2;wh_TyPn8cPf# zyhpPpjb5&RXn8rn3%C8l9fa(3dZ|o^XEeou6CR;8V2;-M`u~ z%L8yvQGW_ldJFg#3fzxM>gK8^6bF}=TG84k&ads7%4!YfFUadfFFMF?eb|woZ6zyG zMAplQ-FQ-0e~{dSFh1K8sW-BBrvyJrzm)@KnJiE*?aoyE&J36kB*OQLk#sa9LTk81 zB5#Wo@~`-1Dw>k@e(;pLn>N`Qbf0aS~;-vnCwb4)1LMviOQQ2D1@KNYn)8ERUUXt zht(*!Pt`!aj(`^xfBBGaoGb(_VC_#7jme=1Vhx`rOi$Z+$Oj1Z-<_t=c-bmp$LhsM z6CY)Bz*$8!RttfQHT%0-uK?s>UA+eciws5B@$voQa>sKb%mr5y@+mKb_1oZ3WPlrA zmWK;n$~dt|NrL~5C}*aR7W|LnP(|f-LN=A+NS(drOp_P8n~PtXj?^B!sgA$6^QuS{ zG;KBM2zCX(X;`YD%1^GbS)TE41>1XsBvYst!lGabcJ@Je=|+!f`5C@5 zBgDw=OdF3!v!2E@dp{>~GKVo9AvJ zAL7k_t#7Jii#l@mc+Dk~aTjJ;EwZ)5(jt@!#if2-7SQjc5A7x%|8iIVG9w3rN;pUD6$7 zr~k!}2RP)xZzy5~yT))Ui8fsqYyEtYcCgxuT|a`Pt>k>$#IG*>K_P3cwGH?2Wzokz zO0Ss^RK+|jqhdc_iV98EE?4m-lc%xy>dr3UPr`vI&s6_oLg?9R1>v`PGG%XjvTzihIN3 zymqLmNz-t;?0OX5FMB!+q4@lr!5&=%z5NY^pGP|%U^!bpi-X%ukZ#aU@OffiUnxX{ zc|Dd|=^~3?630rG@o-IG+|SudTu-wbM4;92KwC2@Vp?Qfg(yj*4H-r0-%WNP2AxLn zrEO4~JOvEYe!aKAy7N5`lgdfc;F4q3QCZP5&R~GpPWPmNVczoFo@FUPru;clJU?C`F`G zjzzLeZ!0z@+jd$kJteR072C`9aaQt80QSIS(tB?h9a!>G2Ra^g;NH1WqI8rsfE^z- z8Uu)vTT}xA-TlUd-^SOQS6+-Eq*N5@n+%k+h^EJD!(mW&Z-Q6!|DrzW%gL&+>DL-JZ>Fx^22``&3J)Pp#IdJQ)=^<{Fng zHJ#@jS=#gP03>=OzVZAjK<5KGE@DNNv(a;QJ@0Q{t>5t*bLcH-oj7EHNcQx0q&%+# zFr;5En0sk-^D-~nc^GKwvhS-QInoR;u`N|)2axj{5omZY#-knPU#Px_-+v(bCXcpz zF|gYTs5nsih4Gl(&w0R`gBLde(Vnppu=!}so$5+Vx^=p>MhKCY8K9D2JICi+mN zy#Cl@0*kVvI+Fa0fxYSOe6d758Ixh>OH6D(H9+KJirek(&AhGfc)85)6nL1&a5r&den(|$|qDo4X@6v%Rb!ba(F(thp&uB zc<7?vQm-A@8)R$6Q6lt6gIAxzK!)9RlW(SYupb}OFQE4~gt2b8ZjZ%)SdK|$>iqQV z&B=`d`=_4^c#AbAJl{4_(Ain}-+%xMYmOd{4?5&7!KC!_b?7LutCj8|a*y&;?NT(Y z4F1#^@x&rVYP#+7tlZhtWgDlvJ&jB5ypN-bs*$o*(0g=vk|@V)MZFmF71s-!L`y&d zAim~>2s+S4oX)4LR7|0MV?L;_Lsx=Zacw3sMd3K;A5s|pn7s{RVZgcsDjM*!wzzau z{H{c#5UNE{1_NaIJn(*GHhn1EB zv)8XAB^XcBgY;xDpe^d*ORBv;is6h1C5b_U-r}`WhRW&w8^lf;50J->9RJx}@tHEt zyc)G)Lwe_fpfb|TsVUYUIF*xZ5lk+u!fSGVDUi@a{g{B4a=a?W7wps1koR~ws8Jo~RPSD%(vX_Au2ymkm%EG< z`+1+nBSYWZHnojsAOPo~Y_LuIixCqsd6jGnpObh0#6?~Ox4e?D#JsjBdl*fJ#H5+U zFK$j-KEf?rZ;^78&cPN>g}6QlkAG_=Y-w)%W!{lM*Gp1Cx3Nui4UG-fx%baY)go%1 zxx-u@uqk8XR8OcAXKOinkm&87%;peWxZF#+XFowv#lG!%!3+Hm@oc3wW!^XI zjarn;#3b645KAhjo*NcLJOx_GkUz3?7fQ16v*$5(O>EOo<+^qe&x$QX4v~9azLGH< zY_7gYM``qh+!1a7#0J==rQ<@nY(EL?F2r#o4ZuWU{beM?B3cO#Qx7j%P}D(oM`yG4 z_GBcwf~r*R#a&o^g;F?o`#S>UFXURq@bk7dBAr_65@MUK=C@5xMMCGwdOs&Uu`Bxmuat&n{mDz~RAnWgFkqqcco>WqlTUHa z43s}!Tu8;^efFV7W|Z#LN2%RRyvq%(Y6IOi>!zjK>+EKZb0@c!K&{M1f4gh8vfHs0 z^abR30qk_|Qb4^(8cuuh@)x$^Hlw3ff{o#8gI&0u`~|a*DP1?u>2C}(nhi@zf7tbA zNwiWI0t&LGLv>|#G44p`iv4bhU8U|Jc(up>=H}Z|_ALty4!u{7Ewkdv80VwRTTGkv zQB-7;doF7FJ9GE7MXz7hctwt zmmt%H34(a_h5J9h;@4^PDTwe9)Fuow+#ItxV+3Q{3~SKQx-Xo@>h_~TBWgg;wRxut z-i-7!nOEn?`2#avi!DI zQ2|GG%Ox3mI8+~BmzQpW<5BhnMT<6vFYYIXxSHyhXDf&NTbeXYF{0F~HoVDhCVDiN z-b^0SHde!pUcdZSHocdVc<-P5^X5ZrpxK0Nl3d zSD|)K8TdfyJ2mnFyHpN2zP_l@;2g2&7d>ScA>5>|zT(W+IT#k0dGZ^eQp4`-C|XHc z6Xhn&jSM^s7$ebpjgB+SC#MFht4MMskXq~z-1WAA+LyQSCH9)YR#Ou|fo+y3QVCXP z&=B%e4_%=v()+WxnLL%wU}l>CYn*NC$`m}$8%b@xv<++S!2xq`)!k!C~Xld1{pJkpTm z&b{WCCF*JO+i{!r+LM&cm(-=Endg+~w%)!nLk)Or20Cl0SrsrrDrb3egL{J~SwU=4 zanfukD-2sUNL^&rfS5U%a7jz4BtM(ut)9BRF?54Z!(yxa`Fsr~M2NvdmZm~VB^(I8 z)#fT`4DY%Co8y06u{Wu`-rrH6$jyW`zC=Grwo7x$y5N3dVn1@!`Ki}TV2!>~FBMb7 z^O=U`4wi!h?F2xBSpLS$G}W7l)z^Z->YuHAe_>#fVwl(8i$;50PkR<9OhmvKbp{y9 z@*ha*w$3N4z;^m0lbRm_RP!^fB|oYM*cc9xL(0(y$`3aXOFz@If81wpt@V!6GT9-^ zb(}@z+4!j;zC9?dj+=m=9~$aoW{~nMBm^QEVW#inX~qQGnXhN2s2HbhYebpkBL`A= zab*WO`V^n~X06*fJA}3JD2NU7&%%}A9HjjQ7*vZb10!D7R7@>;qH@2$w?$C*!2z-H z6ZwEt0QY#W2;XbAq&ulWRE;h38 zHKgBph>IaUB%r8Xa^_rr%(pu@r7#O_Ahu@`aREHV`xDY-hbbl|8#=s^-1!#PDI#yC z5gmEOhYc4p*QSYD;bt#i50G3#ay=h~cNN-fG6g;t$0zwvS9jePEDwwR1p`Rm=^h$qh=JzoJ>gunb6;;IfNM|tf&1Slnl_Wsu4e%CuC zu0V0dGO`PU%GG~3b~a+!e@-}aus%E@XyWi z8L~tu={j(@ollE7LK_V?1W*!HbbO^ReQ|kyaX4{1I>G}^sMuzb5LkP{%rlYRI$$hp z8U6lW9L4`7`w{&;ium(?44Dj*;VXNF8Z+hp=l1Nh1F!F!w`aMYSbOUM@L5W~0-S)E zdsmc_XHX)-g>NE2q{+a9+~&OQh{{fe;c>I^egddU4<;47*GOq;QJvhssaz4?g!&)5 zog=`|xRDrAA#7(daqU-vAD<0u%bUie()=7oFl~r-V{YsNkp7}H{r8nLEcs1>A5EX5 zVFdYB?O7>BFyrFYl!wihdTvs07`wW;)!CgIEM!vIO)riiHTcxW%BF&ygOe<)-> z(s1iA-Vu37k#VOJ9UOHp6MyQs0&VPLxCF+>^XgfO{d%XZ;TEe*wthHVVyvJiyF@p0 z@b2h#SgsYbJU_`FjTy^U00)FVq1E4zpyKJ?+&`{XA&?>5pUsmSRugV z4Arih!T#KbbKkUUmoHCcA=(v8dT&Nt3X^{^4hd4$Tl4la4*2~ikSTxSnT$?T&W5Sc z%Wl_JF=n4Ezn6o%Q*l4xQ%$IM{;o*+htkkm^n`E1hkxhT;z5*ubkfwxYn=my@&A4G z!umWFz~CxAUwtEUzCM|nsk=aK$2e_FFQ901Fi0c5sX8nX56CsKg14KaB=2|*eT|EJ-4}|7z07^uJSVsc zHx*CxXV|Z;V18^d4b0M<-n8Z&zM}p!nthr((6RC@!73R-i}cj1ASI8-;y~p2{eJhuj*tO~Lv*F6#X_n1bN zh%Ja?{D~rnVaDRuy*-siu}P~sC^$v+B*kv*uZdRRvon#t537u43B|5*9E->5rcKx( zI0tP>{$X>iIGToa({$$n)2wk_x_1N6fRZzbUg5b^cxdUou`*%FFpn~6we07!wWE8h z_U0{LgHiW1K6nMM3wsHh@2StVy7%N&C*P9}%pHDlLJ>*Co$0*nS8}+vV|SZ&^Lggo zXk1UG<_cuAPT4MgsU=ZUIu+~2tI zS06|AqmzfP7r58**?IJsSMuQCZmtM`Di{IKZJ6EREEdo=j41S%PD+vWvq;pgS#3WM zTsG4Gd7yJsSTrqr&lkM2a9A2=zBJ^PtwT8QEPDEdgR}-70e)2ionVo1gbYGQYqyQH^KDz@xc5L z!_M0ZS6~o579)3`aZl{MF#dbi&mY%CYUt)`CKGm(Yj9%Jo8sc1XwQ0H7(v`7dir{J zB{%juWkswlPj+&lH`UgPSk*G7XQ7;hzs0%zhst%!!lj!`pq2k4^P;1Hj?Waf(>xg~ zS<2ho-3Cl@z$gk?YwikH4$OpaT6R2E4l!bWyQCWDJC>*~?G#H)eVK#1&VN@W?P+xf z06HoAyo^}?Yu@XvQ?nng=u|w9IO)p6-$6Z@(5q^@Sg2 zTL}@9o+HN7qazp!Z5x+A69|Dq@Fl_46?~;BZCPnTxPRQVtn(mJ`isurdE0rkZP}nK zS-0tA`tkw41N|??say6&}krffzvOHqiBPIk-FTj9Lg8Xdi>Hj;}wa9yNfj zj%09S8X{oX-ut>6Mgf|Ron8hU?5E&`l{6u9mzsV6uolFk&$b|A+j{a4P<0~Fx5^eL zuZdG8mtG1-X|cqwc5a?{W=mIJ7PxfXGLyZ&^RA-MRLjz65g_0{pVvmeeBMg+!Uz9~ zkSMdvqG61mY3m`-e)gxWT5Jo-QHyQttkJG5_o{y1aV;->t6fEr4WOBLv|?al)Wd(g zRG1W&*WDhxk>0CHKD_VfULsXtP>HuX`jxdZKJbWqlQPF1pfu&7Ou0Pd2wGZ{Z6hJJ z__6lG&^uO~hFShvpVfAm_ij^sHetor{WEDbh{7<9eHNkZ2vKT4{y4nhJLePUxh>L} z$)WD3uM0)P4^Nc-L~aqE^!g|;!BzatS$`2cL7#<%QE#LHSCA5Ujou8hAr)_gKkDgHKp1{k$6g_H zhbnk;b{$RROIp2_z@Q82o`ql_MJ8OH$bCr@X6n)fG#La{QS?0yx z1qe2rK{Hp@aR4LHa<7vu zT$B4>QBAcoYI-t|y4N;LnruI^x8&+@;0cW!&hOmmj1(TVig+k}c{nkef%+TBm{J(4 zWJ#SGmKIeQ8VwrwQ(vq3X$$Eq;O=5dD1I9}HvTKjjQQ8R&aVmLCHzJBs@l1~gH#wP zDFYN_A3dR=*?$Tq-G|327&zGJJ^+;R_bgvEwNQj=qlltY+Nrb)%<@KROxfO*2nX^;?f5)K2HUK7O*U%<*Ub0K&T9gE$}V=KtKAXni)7=ZOCG zmKe=VK@d%2%v^Q>pH6b?KJ!vE`QiX~dE9&pRfsf=<^Ml368wJ~r~Lod&sv)4y8pE_ z1XWp^zW<+{eL_?}0K;s$e#OZsxHm11GM%uM6(H~|Rdh;{3|AUb?(Wi;_BB?&aq-tqKcAjk+DLNcqOs8q1(~IL~?u@ zWxns?8VifoWHC$dJ!R8DWon6D%TUeBw^nLccVb zyy)3#VNFRho=we_Q#ednI9As~?3c}B2f6&o1CMAuI zP^4AtQNs6ilxP$R`K~G|gPv777i&^D-NVBMg3<1|YY|pRO@wd_@XO>$gAC<{$2UQ; zj??ty8PC5qK3V#zST^uQ;!e1;H<{%xcY?RFa_zqAwAm>NVhRWLxCp#kFQ2L|5DJZHMCkZ*>_n%z5i+nNRfGY;C?5GfMZKmHs`?Q_{Z-i|%$`RTCv z5`Isl+eM~XV18K+#gS8wrNN6lc0771EJKj)e&AD0%2R@QGO#mVK43{aJo!YU5X?0E z53QRD&LYC!Izy<%xcvHuJNllgGuU!vVR8A-)Z*(jmjO3%ar2qPcFEm|*kd-NCVc5t zFx;^OJVV?g(pR56jgcsHuVdMeY7Jg{Io&1^pzrlK!&TW#ydFVQhS_Pir>*ZD9J;B> zR>Ii-`usG=zw&N%k#Dj(YsGN%)*tTMCQ{YAJ-;~kN3mIu!@T6{tTneK5G>lfPB427>BH3T$$i7wVpXgTcpBR z=e+IshXy3&KKlVO5=Wle8II~5Jtrmdg8!V^K8Ug@OnOqEF04q1fZts;<}~sm$u_ba zY5H4oj@14vI`&E*oy2lx2ytyzB;Vo39`U_GHq(5VV)?$_ps?Zp#20rqw`H_X^nvs{ zS)k6Ul|hrzbM3kisgpMRJT<%C#nsf8Ao>hfp9Yv~wy$P+{O==KpO4qn9r`WR2yL-i zJJ;IuAw7Y^HS11I&^wI|hIb6K%Y`X^9*VHw-5S3y3T8IjUy_NxrABH2KjY{Cm8NML z>}@U|WI~@V%?RHFV{0FNF-W7-O8$MAw2t_S(5WoEbyl!nQ66TzGuIxwGpGe#^nI~f zP8Bq2oFt#fk>gX$S#q{qK7+(&21i{!`XAkM)2fs|C6imE0>-8GTxWC|Ly@xgA94sw z=FUS>$lcyky2xEs6ZHzWEp{}!R(!4Ou*FIpAl}1VMdx6W(+HN|zDI-%-d< zQ{S>anZ0Qwo@}HEX@8gk9ceUZ{qu>+9Q{9o$^Jax6$1J&_Vb-!_5x_1{izHuF6y!m$)) zH_WtS-*xXkb3c&NpY1Q@_;7kAV}H1GAx=XZ&WT?cmlY7ZZ{qD(*x}vYVmBFvpcxSG zJ6>-1@YSqNmRV8Ye$)?t2{s3eSbaX%W?A0jY>5S~Mk+CW^dR|!(xpqGEUHvdexL-X zE4F%@mz~Rb=m>s%XznVgajyNa--=+DhAoxGI^ACrm8!J1$HjZerTR&fDViycj{-52;T9!xC9P`UFTEK);hK;>`+~_ z2ak}P9*2*z8s>NtxaJf$Zg5X{?%-+24U%QgA-+oQ|A*E#*Ku)i>wFFEi25%2sqj`r zQQaxIkI`^Mq!TT-iQ(?13PO0hGc{>E{keXIFAF9pVV$t>-utcz{Z5<09gf-K{xI_B z3)N`<6iV?k@Fm)~-7eH5A@jLjmLr)$TZ9~%;}=7JQ56gE?q;tt zFwipg`@tg^YsAH`uC0?}Hy$AM?zUv}0zx-gzxPL^$(HLj1ruzqn1Ji-xpK#Gh_D{r zba$|#w_j2gacFEDvc0u)(|N)~q->#{;~J9$zDuqgd@aolcMajc87^ECb7Mz#7=N0t!wx@XGC;(8pLRmtu)+3>#zfcc*Vz$*aa_+j$ zY%@Pq0;v!_wfe(8fsjG(1Pvb9*Z>cc1oPEB(zkIS`}mi66}=V`=R=Wm$OJcW6DSD9 zdO*8jQo=l&&S@tz$pxNpETSxSrDe*Izo+-S<+eEwxb6%e1QchXXOBOdn!h919sME` z!q9IMnM<};aw~}zuE4@m*Yp@v+??{`1=S)tXV&3q?))K*i-x_sqxG$p+7c(1)v-ZS z$lt-icaU@LQKpSeLg8b@B@?-ufnekdiXd>AG$~)|&sWLj_Waz+<^Y`1L%+0iIK!kT z%Y{F&TMTUl;h50jTI`9`Ach-`SGQqZDhZ2%-s1yrK&fzvf;Lo{H8o{%+@6YlQid?3 z`@h=Z|L0xr|IJ!qIQ?97*R=g_z3^ZE5fw?n5y3mpCm`i1`h9M7ZU_EFw!b?rDNu+` zZo@zVugcLxH4QOoypd-m{}4veekjqS{twOCheL19FyTh}L44jXtt)Bsaq@ny@q2;4 z*vG-$ohHY1Kiu!_*yXZ<;ak;J<0xp?O)7m6gvEJU9x{A5l!C&?>nDUer<88X8ABJl zAE-ZCaE((pt@tsqA5oc(mVJr2qS`{?3rj@P>_0ZS@%&-9gmCbUw3jk0d#T#z1^(Re zIIGQJp6uky&D9S!E>X7odxCM@D5PVa;R`IpQ-b(;M})V`?F_7g=!|u_Kwa!DC&85 zI@W=!5oNl!FDTWh8%`)%uu-#zcRQygEMCAeScwaZKPL{o^PBy}E-u;l2GJxa0z=C@ z0kT*Rt6$ff@U(~+kd64ye@#1)$HacsrMV}gsFfA6@*V#!`H67E=7xKqth-^}WtZUD zU_VP0c)Iy`qVo8gtD0p97{jQHXsTS2c<5)p9N3uT)aZR$_?+LoKC1c7ga(YO(#tJ$;C{H{-h=eyd%Vd z?9KOcWFs`$bu~!a)0b>|<%nAtiMBvxd{~e%-?=cZ3Fmy=x)(*XT6ObAUAumiQK`&kIc|(ZZ>)I>W=irv zaZw&)n4BqM$oid3QmY)s7SQ}uPo>b0=BO4sQdjT6;WJ==%Xh6`4Cf7f^IK<5?miA7 z3=b;Rr*_{^NTH}gi8R=j+xDW4Szcb7M}@MI(r083&Vz z zFX`J*g2ld~ad6gb>YVTkv~Q`Ox(vo!PO`4{0(_HTB)y1QBo_uiSuKF`=N!aEe`;>vXCxWQLP@d@)>ny!9NB% z>+hLWywik7Rbc}CZi}x23JE^W)U(^BFH*RGI%mP{VjOek*?1|x1@W$AAyky52jNR;b z*D(c1G9QF^s9K4Z-#yO%btKlb;{zLP* zW)OQ3(7ACM6T~vb5o_m{uv6fis$iD;d6YjM``z&!tY(jB(K#NBudQ*iX!t>HYasM4 zcD35(x29&f3gT+|-e5`TMqKk*s#*_Rv+rTjh`$pl;K(lW2c!|F+Kku%`SPZ;Ino%! zJKAWSiMhwaTd7F)g(VW&1c~Jj-N}{Nvb$W|WF^J(@4c!u;eC${aT|;t28>hq?%}VB zp3xYqh=ZuW-vY=HqTiiw<($cnUHWH-_WVItgcpL*a0bE*Mb(_4&IfPH8%HOYc&rce z6{^=^H+f@8B4VKGYJ1VJYPXxy=O0*VEWBjAY@qxdT>BZXRARiu57Yy;@Y$7aJ9Ca< zxTyXh!9BeFbUQ%8&};}Sqi=)srt#R`BPYiqXk&E}U=a5w>e92Fa{f5Tf?ZOLPUBCm zu71F66r9Jn!8%;qY+FtNY=*osVYuTt;=v{u__np4QU(oAyU_;)i?!p-BU#)DJIXD+ zpZEDXyU`fkk;#)kVR+x`h-Cvy43!-H-}Nh8j{ife@{hd+#(2MNU0CahG0S`_I`c76 z$OM9899Xp^Q?}s1z$zq50lWneVq4FBtWehHflZ<^-w11Vw->4qS~G`ibhl!8+cn?o zx^G#S$%NveWr(rS@T-0TE^m1 zT^JCun|Zf0(odAG8HaVLN*5Y0A@b8hLVw}M0OhBST7DwoURYWWRde#WATb3?ny_}= za^>d~meb`5kk~z-D70{2O$&j04w$(WPDT7Kk=0^e=^GOBPE0cb1goZqVHwXHIRr3W zI|?62aBgR4l3<23U8B?LICqUl3gq&4zFVg0Dg89$5V00EG_+Tg>wj52zG2<9fRr5x ztiJoLTe&-IjNNpcr>bdO172OSZE-yti2C>%_s!R{YJuxTE+kC}v28_?OMJ6!4?J(L zb?6Bb_-g|}5?;2>`Ly-1ecw~@eyJ`HnP}c;%sqt^d2`F~r<}Y_oF)y<`dn7{Ip%O~ zr;3<8jnZ^sjV#SgBZ2wfU%-sV_K+i{&UqbSoYDLE31V8$XWOZD1C6l7Ce?RHfIU{2 z^Txbsnl>$22EfJSD{lC#S&1g$h%^qaqWXfExO3|R5@>=M-fb~ssZ$giZlI=wx~;s0 zJcBJoY^v7^?Hj~tm6>*?JO)8-#bJC?J&kKS`zFG-!(xC3W4SpeN7^QaM?(P?MyccY z&HLHE?)~D7u%rY{z2-D-uI=*0urtCC8X45RT@c&^s`m0d6R zwJ$wP8O82~jz4c*d*(xYpqLq1{P9P)L_PDZw>(ifdgG>X zPuZcDzFbtajt|IYxVPB7DX~-PkwxDN9G&ptDEA-Qc2KT!4Pw3tkSae}oZI>j%_Qy< zf+M=V^NlW+h#>qOJ6b%)aM2otD%6eCI0Nwx?zkSNI9<&UmHoE$llt^2C5yrOTF<^X zjZaN!2M2u?c@`S0?DZc8h6!BN4HK(9FJYpH`jTl6pX2q&Pm!OZ)HvPj73Xi5fjHlF z;yv6RiS9f)8ZD+kjB_5G<^C;-&aHc$8<#EZt5L%Z|IlhX3z`xMj?s(W7&YI<9SBxf);#~AQSD{A3#I^?JOxGMu~1+xQaF?fnEU>B z`bf596!6Y(UsAS$H7YH@BjtXQBjevZZPq|%degv${QuV&au}# zaEm7<_~XUWH$~vR_=ewd?=7KtmBX?b6$T}G{eE!FkJX!TU@0uNXcI!EYsbGT16lkQ zUrk)Qi+1(UjM@b;Pld&AkFZ6c)Q`5qt}R9!ooOh@Gd|qwhdm{6r*PnP1uPBo6P@P} zMZ?K;b!kT0jgWDj;eWLLYi+%Nm490PI-VBqWVQMpT~r}o!texn=z zd?iqDm#;``U!j8iL4b<=@XCbO7n+a2cVsazHXa#%Yzd?_{3g*5s5MC82-OiD$Tc>)%gh zj(GzhcyEF8C&^P3rN&dujpzD#wKaK%(%Plpk@I~!{@peL2X$tf+))Bh{@MRlPW?Zi zrT*8s|Eu-lyef?SzcbRA=Q1o^%MRY^E>`cCx>ShZx$j|WDo;C{K(Y25sy1vv8Q%*z zH0&oX|B{Y;Ni;CGO~uHe_Kud7WI8Ret_j!<;BJxEM2iG<0gzU|Z&sT=S`>RePqI)@<@U z26fTY+V+!@Elk{@zze??iDsIct2l^7<*n6koNWMd&kO_@J~ z0wSr2%xc3Yvs)>!Q6-ueC;VUyk zp~u>dD$Ne9rp;tl=AZKPqu2*Z!bc8tQj5sym;sqqBPs5S zrD4i#xsu6JG+dXO#$m;%O~9Y3s*Zpz*XEAB`!@?}@4rc+FU1ZG-Y*MaHe6Q(WFpj-eUBzqZd=mMLOQ#lU@SAQF~2|8M$;>dTfmV}eYxb% z0Lb+6nQ`Oi8bjWD@}1<^R$>RarjM9#hLj+N(6g=DN}?FZ*h z608o2k6Qy%)et-KYu!Z{k1qnQX)rZT?9G`;N{MhH!rWDuXmd{eZFD;Pl|Qifw;LAS zb@KAtxzq0c9ykNK8#V%w=AP9(FEf94IlpKgk;C;$yAea&;m+>CGUXzXSk|uPK9w3# zdI-W%gJ-5B8yZ{>W#cQ?=JB{be|;>nFcP+Rt>6GLS3@6tJI$SxS%>?8MAGJ{IkQD$ z;K<0i!+3kHfmtbE;K1!e5aneYef=i&i6v#OZRKdiNTixv0il6*POZTn>mUNd7-GD>nLrY1KU4R=1=flBBdJ z;sI$`2hSzp1$4w&$KhOV%YIKHo>Ht1h1SOlYZFh(g2mDVQj@<5k@+OJo^~RF2X?Wl z2Suy($k;MKQgp;M6t!#Kw#yd$^%YxE0CLz|E=pwg*9Kbv@ zmarA;Pp#|o9V9tHKlm6C9E zH0UV1nxA~Dv4!nCU8Wc8+WC>dxhAiclr##6XJyIuKeQLROSe!ncG?;QMZJh4l$bE) zG6`1-$%V=o4-f(kR2(2s`g~$a7afMBCd__GnhAJ0^ly*kZ{G7?YTM@QUSS8Aiqn&( z3e*OzSU)Ji_Kc|nQs>-wAPEz&;Wxo=n{rvJN~sc$^iP@e-f+X()co}*kP!nyLV z-d`pTgq{%l;z@_~UsKn$wm79szQW?nLl$FKrOrjA>T==^hUrgDQ2U7GT3n;hf#2Uw zSOz??G+?#Tyu}LSSr#<8$Rw7zdc61h`UiYf5vF-3ZQKHwd;Tz{&2eny7egI2K(_2A z^i!Zo+3BHi?i;79Yxl|Y%;`wS@0$5{+1^Hu`zv07>^A$T2Eaz^8B%yW%CpFq>Fcr- z{e)(=2Sxk+13>)@*4?1*1a?|Hn)q`5m1czV4;2bNPo(Mq1NsE_wRA>#azOVRS(`M# z_-6Q_D{IOLh6p5o~!9 zvA}LFrR5VKy$!vytaY~hJIS|Zf7lMb1jZl@Hh^zzCW37g!Pp0~gOU=A>zBt%gnd3m z{l=t|M=uM=HRQ0%I~X^jYfu)R0ScCo+ehr1v>Jw}B40LY{1%6F5pRNC_Y=thsOc>g zJT2X^pd$=^NEWjhPN-4dcIMhhj-R;t3w(C1|c<^UN-9 z&I~5%OkWM-yWaOmZ527S&t~WaQkeMEsaXMhz|V&Bhj-)6N%o(V-PAwQH?+BWZalP` zDImohSw9?&>PnF8CW^Ug@rsH6L(|HD|E^D4uSheC>ki>o5PRY0lkxDk5wsq#W2rYn z@K`+4Lf_E%rIW)L;zsTI=TMP|9I8+*d2gk0_&oS-7lyff`PZU-`DB@Y`Ci8`rBzi4 z-`M`m9c}yR2om`9j9hI$({Qov50NKpSoM1s37)*E8c(bQxnAL6{ec#R9n%V)Y5ID0 zV(E<~i?v$LPVe&Wc=y|_xtl-A!mGiAa+M}dHpfFh(9nNO;FYTG8#>jOZ>%x&(XTA zVYtnarGNmd&s`$d;XgE3^}uxk;tHIb*uYPOJzB%+SZ|usBND6<*aZ1;Vx76;oeP(y zt#%vrhe70C{U)~2uwMsHJqj%0#eCq7kc>HDGvGDuCX*cCku%dRR!Cp zq<6Hr74MFG{v6wnK9xssV*0wzMt@P&ty{$2m);>1O2m*k?8#Oss;5#)Z8%Hky<-(3 zHHaw=ZO-?p)SIG}!dXs{6y%ck#`d=^k@EcJZznNTYObBa48n%v{aoB&lkPTPkMQm`Sv5?$K70grP~-!B|`4Y185Sp=gNo>zG7;+ zXg9kIM7BHMFL_xZIcGXX%9V>6(`)3pYJz`7QXD!PO?;YdQ#86fTp*+%R&u27=SeJ1 z9vU~ct1`x^nf81S<8xGZ*o;rpQhS>`{}`MqFksBw9;IZ16nwkz3|dVyVk!Tyx{1t$ zSH`N98{kFF@hn{Gmp-ZnzxXkvlcNtz$x<$H)L%It07F-NkE(qf->VzPoNxS3G|qn@ za{lZ1KTtvc$Lk=qFM~4`LL$TN(?_TF--ih7Oe_UwAL1x$sv(QDErAtxH_m%ug^#-H zLErt~i^FAgv6s45LL_=uc=k0p$v!jw zLC?RutjtVZS~C_K32ANmLV+(QLnWnM^Vi>liCMko-jY>}Rg6zDy}SPEq4=ozM9rt3FkQJUGFnHJ&|N0CWwE(5&bdH*0y>{tx?nu@NWL1f%P`HhbU!UpRTtm zIvMgSmRplmZ@g3ePRF>Nm#wl3r{0n}!2%6`oS1}fexS@~$)-txll^`FW+LF;qZ)Uk z_x^Zj{KLAe#Hy3(`SUhbUW;v}kybJ609(yU72cM9k<+zvjs?6n`AR;DMpUaN3bEUNi`)k9r=-yPUb%YfhuOl2~Q?OsKezDgwVj zZ>ImSKC~&3EU{>*ajxw^3lx*HbQgwV+~$1E)yeJ@)_bFWQpCJ( zH@B!W-~fAByRp>S^kC)^lj-JZ$zJ2;yisTWL&-ty>e` zHfIQ@hzpi7CIcV97XMzXtf`z2?xLVSc~d1Q0lzq;;;*-elP#I|^h6N)bLbPXv5(1D z#1~;;EW9muZr(R(z!{jSK74|jRVA(#)@7d@1*zujdb)pAt<~5r&CO}oJ6J;#Cpuiz zDWXca>dovX(kX&YxuV}0|2&8jVRR>tLX;Bhu!XK zRYSCwVwIC^EQq46mZw_YE*`!5(VA`;4HnH?_a76u%lEMF_H!*V>G4RZm$73F_CfpP z4nYTD)082*l=IaAs?4QhRrI)de2f|?uB{!d`;RsXpW0_mw=?xDnwpZ*QxwSSxWtCU z?1&vfncI#95nCCF6Vc7IsA#Po@Jq+w-iEnyPn_%*HDaS<9|V8g{z{QtcTc=J1PB8| zkffGMfwE`{7#&}Jj7s(&;b!atrA>sQ`~8{RK8udmichJ3F9ioVcdvmof1P>v5GQ{) z>@{g~pPD6$Ky~VGPXAN{lOhRAmwc=!G-alX8tvt%*S~c7@juawn*+z%?G+fb>tav( zzSby)&W5f(=jOH->8mwavLS+)+f)12j_}H$##Afv|%xW&fW}L8k zi%aww*!<^WW|qD@6skt6XU1cvYVw$>?mE=N6ln6G5QA|{DmNqS;SBnRrr*%P2B#u0 zNQnq|aFO;hD-OF&WC5QUr#o+)zFyKldi$6=BZ^EL2_MNDYc@%Y(2&6Ux*aq%Rhvrj zs{6;S1#D!x`f!uHMWi@zM>9H?K&vgaLyjz29ei}{{o2*x{Rqh*W+&8Le+R@X;Pxud zX_=8`u}shIMpl(CIw^D<>UW5}P1X)Hr|4~RwmSohmp{oB-d4=p`Dxf+yAYR1iq0~e zG7^7$i0z&TP^Ih0D%;l>MyZ`!6I35qMf)fpeE*?^Os;q0t7Jw`pEQWI!*JTp$jF1t zfquh?hGhDLN~}ulZ&(47Kc*>W9(hp7w<^S*u{~uHi8+~pQ~%I7hIehgl)c3QDMam$YMYb9I#f?4xj=y<`S+-0?`dlMlo{vZw5OL#Y?>dFKgT>M-5x;WhN z6Q@%8E`lN`vRPg$gyd&J53~HC(Xfh|M%rnx$>F`+IDGrf(^$R7Pk469K3i@s3eY5$ zBI1k@AlW+g=l2{&y4P2J?0Qhd9dDHNYxeTg#KEha1J)NmjjRnX>0QI7 z`f!}(@;RV<8*d{fLzj;>Vq88HwxodRz~&J6)<q$5Spyp(L1Hm3L!`}HQ$P{M#_;JWdnE|87dpk zI-rf4yG+P%MV=kLY)I+{boB2ys8tc8h*oq`Jz@iaBw|{_rSyv@j5{_^@38R zy{~>giAZO33^$9`_%b;vQ5atR$LX4yF=m)*4>JWc&PjNW4AJp5f?*|4j5K z>;19p$1B{{nma9S5d|6rnh#z=W_~}6zod&+U(?_gy%ORJvINl)eJi;QT;n-PU7bPb}r?1KDi+|M4mfG*xLyiUD%Z0xT{4*v|e8e4Bj5ZeV&y8I5$ z#5V1J%JG9ab$&PsNK#2~-`Px}GittvC1~Qsf&`AP19O1>to>>}!RE2vDUJ^?`#`oO zWwz4x5%1vFNG_&P&4Uk*V{|xqqgnvJ^vHnMp!VvFxVWkCmpU&(B}QQPbM$oxjq{y_ zjhbnVCBOC7p{9Rm*?_#2WhGB{y58d!1zcU23^|)!++!g?si2yMFm1xFnldw0rXiC< zLSP9INCEcNX`ACHZf?m0U@vHSvo#b=Lq#6NV(ObLFe|7sRM+iF2=@j1Dh;H&D)l`p zgzLP2cz5RQZ_f`F#;Gr6ndBCY30a$GKQ)rW{(IzE{tL7ev@KZC zt<&g!i@<`cz*o3lBByTXAMqXr1bq_)TQA^j7~mp@11zYn71QzhDQ_5pw{m0;dCe$u zq2#{D&0No@qRkv&z%jE|E?MTt{;i25p*9dtKerJQy>nw;b4eU;T|bpIeSs#i-c){$=w1vM6_z~5}(x`)KeRYo!$2t|waq4p@@qDJb zQd)`)q{e2X{0Tjh(W7)F7-60&0p}A9;Pw2N%g%h;SjB6G5*fPT zvUMk+eQm6FGgI2akOHp4miQK1Ysb;&q4T6>e?(?x%<9}6Rzz5+x!&Nm&CDfUr*kd; z@fso-PT^55Ozj8Jp5%fG_w@T3%ANR!h?~_P2BR?iL;Qe#(~wUofJlop5>g?pE$(c5 zqrAvACB9K5oFhlkg+D$6qjKf%S7VPJ+A75pJj!7@=|RA!*RxXuFL)dLtYXg*#1G>7 z!M>M6&uCGyvKB4HI0umy$ zFp|XE^1yV>*<0}HgwRlhCIDUqQu%B<%b}4-V0T8JiuRh z=@L??{`2z0t#y||@qEycVL=?p2%%_7utpFxW&_7Wbq4A0U3t(rAz49Dz}=+g<|2I0 zCXJ}xT0Tqzlh+K{{eFfYzeVXQMEMVGxK$_%U_Amy9QZh>h~pkV)SM^6&O16q$O(|6 zy3=Lo&tpfCvj;sS@Wuchdw19JK3)~kUekxHJ@rkV6=sU*dAjO75z9M0m;ZVZdwTTK=OBVlx4preoHdf$Nuts0!jq;mMrR zO57J16gQuZ(*F)0+Po_gfn5=fzbq;^-eiP0> z&v9!18s)X|qdR{+B`Aa(ro3Si@8?t^Y~Yjla=Lm;P~Z&@dd=xU{u9k=8^&%46KzP9 z0-7nhp>}PXn4Y4t-F^12084#bg!PQEAR;F{vg&95~06nSt$ta z{C3F)s23VEIGy#QS@L4|aTU{X9$Cq-z7|z2s#HmKtZkL0T89;xL{R&ConBRq>)xy* zyrwZanV1P%zWEO^5)DF7UliI-sy~F|dRA+vslznklq`tFFf(5-62+^wY<%9^-dyovet_gKtpX!DUNR zuTAkBg=kax z-A$lwg!jmV_Qz_w|2pA6v{0H!QRR(slKm6?r}_03a@$9(MlhQ@Zs7^=>}xVjbv z1ePqL^sz=8?v6aqf}i#Ky>xI1UYEXt2>h^3Px-tH$p?c;cMf}6vfa~Pu71WSW|xv4 z{D$lkoJ}REsDGk^K$0WPKR3{`gC$~d50M>Kr9X(juMO^cIB17?Vu~^6MUy)&YEcY; zJvwL`rC5b$e{13lV)1ZD4ipR&TvhXEWt6r!{n8AL&6Xi%j)ii3_k+y(l?Jkr@8t3@ z0@;C9?b!Z(AGV!7-O&OtIFIc9KGnBGq;z>Y6@HnMjX$RNa3MORAnkkW=wLN(@5Z%m@)3hizPAx4Vf$_b{ntkWfE2Vk% z&X9FjPDU?{r4;YJ`exi;563VnP7?CDfI_)X+R>O`=Ua|m%$}Pe!U+XOOA=4d<@W;S zN5RrMmw@F9>llwK*A@d*D4S8B@ULV4S5MRf`^pav!7FxGBdE~9TkGD2&ksrq=q+2k z)}gt*fQ;Ls?#$dUp4Wx8--dc)Mer`>S_lalFQit;RQN3MY!%AoMuJYrM9`E-l13R)+0-&-}y|LF_MWekc+WDL815G}OeSFTi zU4bOaBa|@oY}c?m9o257!|=?_uPxTB@v?X-LYU|976{gguH7nC0^62yRTk~};CSi5 zy64NLv-CKbLpkB4!TIE0IF*Ud29M+jMLVXk-XzbdH?BO|_)Y(;A#oI*^iHME%^RLA z0i~Pe^YQTh6dt$V$nr@Nn^)-{b@k-VY9^d zc?yUo%m}qp9@;5dJLHJWXwnB#L$LU?O?Pt!E98K!==slV~{$s|QJaAY`Gcw7Es zlI*K>ptOc9Y1_SLR~nt{GKyRM@m{N?wCH7#8w|^yus+f4$$(s7-5-|oN)ZS2yIi~U zZ1{(li_@yB)Af~xH&gMy8xX~*btL7?Ggl%d2Z`PAsDESX&rSR?9Bqj2GJNdz ze+aZ4sF{vTZy#BnNR*2|k^6Wb25|Hgf-|_+p)c{Kr%|JQryd&(6wzX_7a98fW#L|D zn4@4{aHe?ddyjhLR+YtZ5+bo5`a$~523d*_&Gb|=30v>0-V|cLtFmLK?eE$y3tgwm zrH#S`@vc+yhp*|gW14dPbS!f#F^=$SbQe>ebhjAarpRe(+sE>3>BQD7Zwt@m=qz3EntOU;kb0_z zHZ+X|zi9!{h_O^>-zAR=p4ZqE#!iI%r&ly{iaP$sRH1(;lI8+r_S1ktXn+`L_wr|c zSK#px=Zh~>Jf5POOl6tOfqh;KDfXJ(fCN-ptuu2Xe+LmQ&~CWjr+Tf+i@%hMN53Xj zSiT1<&)E+?pp+(j$~fCUXlL7q36~ssRfRO8Oql#7LrQFaxg7;Wv0F z3}_m7gU9Os?9>>4ljGe1CH2hfq||VVn$O`Ifl=i*U`RaaGA!t0ptz9g!m*@eQR$H- z@Dj<47nW(^7ZsbUr^Q(xGT2N(oRt4W!ngm;hW2Of5fUcxm&HnVHf>|2$X`MLwiWmE z_SVunsAk2UhfEh2FD1Jb@3TLkbiv1@XD*F?n1XV8hz6UIv#<4Bl^!}PiS{f+@ICZE z_6@_FW%Em{XIP(!(siza&xi_QoHsad3~FrZmAJCE-Vg3VFk?}b0j8~ARAk9i6`N_z zr?&Zcc{E(iV7vXjQh3ISXe$=8Q(m2pEto)GLVDN8q&xE|gEKKu*jGWVFaPs_m>hap zrH(iTB4P<0FY=0s$mv{zVBW+K*Z$xi8uo$>>8Oi7nKDYpOsJ6I4ul_u9vTfqBR_3) zzOmt4mf`)O?D8yPvw8fNe{RMi%Xq&wC?YmTsqEO3(mr@=Qi8v4i z$WcI6(Je*knMb<*$JSN^PWF>=L1|zf-h1U6I;vjZ^?29J>DF63#0zTMLTF9XGpu8! zBw|Fi>1LkYjlY=A|Ha-}1-12m{TfPJTA)y%&_b~mC=y(XLurc_cQ3`ExO;)(5K3?h z5*&gDm!iR4gS$)60D<4h`_7zmX5RD8nK|=6m;Z}>6J~Pp4YT*!Ypu`o?788BpPDCq z^8(T6{#~^f!$h}NV94ixUw^z2+JXq)1Ge_Ikq*ma7u-T-xd|GshC~tW!=_G*`HLiy zqTe((+*k)>R3uNd9~b>4!1{D>V62XoIh_qgTfcl5t4wrw`9oxm3xvJv!_|LcARc!b z)#=W5;^&SxmSekZ$Z>pkGnOVgV=8!?3r@S7|@00f{)jDl5S=p>mqS8wV$x|&yyGVwaEe`d8*R+n{gv# zpZ4V{SWuZ8N0wbpl@ojmRzH1Vy5#N)@8XEQ5k?Bq&tl3(8Uf5cE-mo_BNTnw^|L|z z8-5i^3v| z?&d&&o5<+6xabGiA?^8q9I;t1xsnjVJMLKcf$W8k>;S;EJPQ0lhf0dId>|tW;8!ty zQGdf5HTFJB5v)vT6PNX2RbW2ltgN9QXVL9ZBcOp^QCeRijJT;$^4;S{lE-5Awlnt7 zckMFu%^|`1!)IKpK|CmaJQA3dr%*8 zhG9z*ysm_2UzI^|j2kCr`>Y^MF!qKXCJ|-l!uqrFcDWf>q*MDhH`%-&qqZX&*UTc8 zO&4OA8I*QdJP4s*{tyd6)2fS_3)k)o$Av<5+hY8!G3&dAl44~sulmLt2L4F1{yyUa zCA)yU({A6YjJq28GlG3|3K)nR%q$OL|H0C!;6xS%6;yG$S>bmJ$4w$H_zxxuO3H2Y zD&V&dWnL}g-9}vFR{=8x0vLg5krgXt=N582$CvE8_k(n+Z5R0cc#H9Oy2ePxlpq2g z;#sPV>UU!{W>vdlf17WA3c|2@WS=!NI(pK$ zXC#dB+B|6+XCAuRE?eG-=2Lr=)e-`IZx#hY&aU~|9(YJI;pAhPO6Cjkh=!Q z*!*U_142dhZ5d{qJ1r;}DhP-g4h)GiSgj@8je{TB^Q_g0@v#E;ZO20;W71?DC3qQV&I*IL&I32qH!iN=l#9wEwixs?tq*u#qQl#CbcL)TC8 zkL@kQc~s%0?khdY_pWOU8g7Oo^-&Kp)L;+r=n^4>8)bezd-Imm=-$DY~(?U%z7s7H|!`GC)Yx3)dqMDJyZpT z%FJE*J97)pa(ZQEN9Vg5TcKjx^lF*9VN|C+0OKGx94S%?5foHnmsV^Ro4&2sGqgIf zZKuy|72I8ZJW~MLpIP79a!Cqhaj(BW>&oh^-j*P`=)dYOu&Ehn2}vB8y!~ah+0P zBwHJv#28lBNcgK>kcmMnqaV$ED2v?AR0_Z3ntSVWDZYyHC_7`TQbc3tmt0AivmAeh z>VoFHP6wv_H!l7O(~-gY_w_HFff$BSMuAzF#KQPOvDAuLI|Au|zuoh4|4;{n!8$P6 zm^#fA$8v9p`k5xdNSDCi<(38#LYc?f>T5@ivgC-XZ*t=dOcfZhNu=h_!%`YXttJO2%df!XAr3HCi4VB@W#u?;qMN5DFcw={@ zl$Y<5W6C`B`#5uu+n`&PdmwKonsTCY$~@>3qovhd^mb#|zZE#8OB0VN;QjXQrg0K*AaZbDy*$vxWC6I5=~l%%T5_O zx++u>!>T@Yd3uvvtMzkAcKj2zwDoknQw3t7PfOo+S`uyX=xG2YJ6bC5TZjLYDMP^E zS9;o5c{^$04-S`Uiu3)HQyPwnkN4W1LlXT|1B+SSGCAf(W9oVS4nRkbFmMW63fZu_ zsivM`_tPR>FB9-RH!qaJLNEqjTPhc&cD&ZL%o55yMcZN}T#1sOi*TNd8M32Uew)6# zmZlXggk@&{@&io$g#Lil$$o$H^$nS_{Fv*#(9oZrCgl?e20wsycDaEfvt~^G*quQZ zdlDi0R6Q?6tRC}+$WvBk7QMGL>v-}2oNh4tgexHB$lfr&!Hvx{>Tz$jn}eiEynWw5 z+xx_4F4G`|X3>T9lQ0f8eqH|GON{wbshsz4iOv8HmMj8M^8%C&#SuR~i!4}id!3C0 zf`uhh=nr%0_W#g^ydX~_3@cQo0&eU7wtOpVV8_^u4GQ3Z4PvzN!p9*_?+xbr`B-uA z!!>HnXl{;BvlU@3(SAqcH%j7pyA~uv&b3>F)v#&A?AA*CqK{%bP?S;RJ-l2$)ESGg ztR>3;2*`Q-@)=!lAAPGY6s`m)Kedc?b09jZ|C4@z4UeOD&N{AlD3ssVbep<7TNYF= z?vIX)^fUDn(_FY~+gM?Bt7*0Z8CMU{yW^FsgfLumRPfcKV7Ywn3MV-?;+Zx-mvJwE zFfcgz(|{gNSj^LfZ_R1zU7zc;F|W@gdqU9r}-dI)4m^CQD0wu#6X`a13Rwev#$(Zb+X zQ3O8KjT{(v%%UZ|mzMIVu<2tPW#zdVH_V=CAe;8ELLI}W&3FETRz-gE=v+%1ko`;7 zX>#-CHa_D4wqfCRunkhR1x5S6xx7qHM@zh35BT|gF;i|Z&2VC2=RszY(`v@v#0=pV z(0Za+uFw%cE6Q7DSB2CJyApY3ogiirqj}<KDE@w8qduBslySg>%hA~-aM;AN zrgs_pG^Eb$g^o>fk8@oT2X(9yNKo=vd5p3*=~1hUIjPqMi4|08+v#}Mt`%q7CNA!dkz^EQGu2!lPfmnV)NIKdZRPts%p@B_+b0p zm27&?|HaIuj$-$CL8=ABMcLimx3!OE8C53sLyTsAxID$I8NbVL;Nwl$ed1xekuuEh z1uJWYW+F)3k}M|CtD(?;TTJ1x`7PB;>+;{u!kSPXPHy0Y0M6J9$X#1#chWg6qQ*Y| zhl-LT%SHBgENhBH?@F@2mzE2X%suaHC)#Lj6^iyG%;F-zLysB$!6FHG{*V>o zx>~r_DVAq!<8h}a)?M*U0PAr`v2r|Q+WXSD@QLv z2wK7GlJ^^y@<@+PTt<9lNh04|*OO-3j}?$o;TyH8gvxXz4&00D6TjTeg7W7|{}JkQ z8V`i;9OzExmLtg6R!Eib@brBjjKY#^Tn>cIiXDn0j>=z!MS8A;(NkqO{)4r{k3a>e z#A;3Cq)A7QNa}u$W}&-v-*{Tj$SrCix(&&Ie3 z2`G!ck~qTKZrSyjde|uOYox%ewKV5NA1k0nUHdP-9+`kd^uw9kz%)(U64l zTbF?Gu@JERLbCjMA~Dk%Idj1pUXINwvJt2EvP?%cyds$oKv>%j>`&_*-CpFeM*@b6XA!Xeb2l0f$aMy9>UO7SeQ-La{JQNb=jM^ zW2R?~Y`v8|O5E4v&@_{Td>ZRRok=^xp{ql}-HE>oXF>No|hefF482f@sy-R9M zn@@A|xMCde_D);LX!6L_FxlO6xiH(+h_|Bd;wxs+2hGN{7!ErlB(!YG zD?B}={*#EmWhA^Vym{mCZQ3>M?}s;8-zHvM-0=g0Ab;Y@g)*cdx z&kR6jbB#Db@X3pcEPmOeoR&m(bDqy-pQ}y`1PQ*D6b>Da`cQ}crYpqf2w@qOOe1mc;-KOX#Xk7 z!%!CfycO1Jb+XE3=>Wgv66#{U;?F&?^GRhdYK_JT#_HHVNrB=mA!>YIcwa0jo0~J`bbhDQTjtj+hK{!446<_a&fEruUs1tZ@ z>OyUGC0gHR_{#*bPE8u=cfa|{ft=zXZfn@JfrdgK$1!JK$&GC~`W;Aq2>Hvx`cesZ zNQl2WnxR&pV6_d`;h-vxHsW23#N?4>UHo11^T+NTn5C^w<${}m^ej_?6FB~%AM0_c zDNT;W%mk=$OUF&!K&dd#&>F*Xu|3rs#&_uVrS93a4x(jDwPj8 zv<5m0696-9GIt`Os@O1PzRgE(S)KL;%YBq5p%w8jSJ+%O?lmH2!SL4C2>#1#wsEf_ ziAZsot(ofWcGxTf7$Q^ZY=M>b`Y;sg=FJRWFJkP#ZLRb`$ss&$H8Ii_R5E3MA! zet8qB;)N_5dg=x#(*yrtrT)CvR)%l-uv0&kgSUDvLy+3KV0!AzOc=!M;XFz3sAE-I zs0`KKtv6(B*)qjo)z35-ZHFs(0E9$t07)GD2oIItnoq@FX{VoQ83Wq`cbCOcVT9>T zU0*;f$Guu|$i(oA&MWp?yfYRK4tslyKbHpoLnzfB z^Q=u38P!pt3hh(NU$vt|4ULH*mnYVS($hOAZOm&Ef^UP?9dBo(g~qPiEm6J{l%=o> zI@7Padl18Gf9?x#%HBISwt2p_yo^O)=0bw=SA3^p%W(83jpRP_!KZRmkCe{+Yn-6` zz^>j9&QOWTfRCz;PeB1m9%YjA*j-e7q%7#|i6RCN0SK-=k5;L9-&ImfJn@ zWeR$Hte-R+4!Z(hJyTCIX9#*rW%uB#EwDc9YQxdwpV2GEfknb+gtO6jb%7Cu7!$$0 z%+80mlbV}Dpql}*3vd7UIRzgX1t4*{mhpgcnd=}iX{j}~Jglb==NLqM)*y?<4tVLc zgTT%WEp?h1Plt((YKMmEZ*YA(ukm2OR=a}XrDgoy?k7tz6q%bg&;~91x%bh{aIH6? zjrpVr&QrO!$XA=`mi_9TBQI5}QYV@m@I31biM~v^O4osGspU0%@*=mgE%C}89UHlW z=IPtGHPm{S^xr+dV&Z2GBA(zwmkN!mYsIxND{)-&L`&FM+=-QZp%B7*&e|3XZYW-# zRF$>P-|NT!J33RV`8k>y%SUsGUb=B+$5!8SI)R{Xw6kb5;1p^~7@R5Wy1pY&-%oL? zlywjBwBu`5^>BQu|JY7)f5;ODz21Dl4v;y`jJ*Okx{!Xu9fV_74di0%64wu!*-ztE zmskP%fDcL5O7uZXyzGO(ygST5#cbYF{@S4JVFvj-h9SMi!IUbiIYf+5_-b!&*tLlH zre+(k%@0^IPNLDT2}34FU(&wpo2hzQU%7Plx1|QyGa67RKRSly#cWb=!Kw59^sq>@ zCfFGe=2=3$6Cav$_nK-cKSo(wix-OA1iX*=b615^e=W18*E9ny+|{DBojR5W&WmJ@ zh!Az{sWUI#4UOWA23OMDu?4Txbkzx z@UNg`-L9v|$%E)}1;;Y}KxP;3G~8(%O#8PR_ZO1-u6PEUiU+k~6@ibU>V{`0AM#@V4$Y*xR%dq@~vLJZ$9 zluAzdxnE$M8R9+>fWhbCK$7&PNF^iZfPAP!yUSqP8&sV}CZD0a`I$2LSq+xP#WR<= ztBZ=S)0;XQfo22tDbFlNU-n5qJ-O09&T#oXWicnpsK=gQ zkNB0qyOum2NE8VT1=Pa%DtqZIn8dw_W9BZY53DD*V`~C9)%zia>S^5_hIWigVw3^1 zmW^}W%Vs85iDFZi>Wlub+VwidDz@vUKa8Dhvx~A4s8w$qJr4}U>@gD(RTyRO_=P#C ze};gzFld0{o*2xXL0@v2Q>Sh3==>P#D!<^m@X@o{j(_lp! z@`lvBm$4hsBob7vrHGkUOUPmu^}cMC0z9K7MEtiK+6K+Du%desD!U!3NiVpV=M%YB zEKNo|6Ma~)ud14`;fd*1kMeWAS!m7+eZH;vmoeNpxt(m$y6%eiQ?k2qish#Pm$+af z+jRv)KI363;1dVy!HN+Utpqu! z&kb>n-!>IX@!QQNZ(UPY)`bd*PRIDpsFa~@QV3HEX{29J?L19tb)TH374VoEoi1ye zHWh1d4*CjcaHF|gOLl+#n)1N<)cnwS!&XH)c)$fUsh{r1tycH9u)zoKwFm6 zx>7#8t!`8Mo<$ka3_o0>>GcPSaZdgvMLQ@YfZgA^U?DNWPi{|Vy7bwAf;siWLFSw< z!@hdHU}@v>ieGzq-+mhj%0kRkgJ*exug-nL1-&5Y|M&JDFn{T%t~6Hr4_2+Q{JTKu zDNPEdc^U6@6QoS2FExZCIbW!)Q8J0nx9t8}0HvLQffCjumS!^pnEx^j#&|PdT;I-) zj)Z(OH?p=SJ*3-RwJNGF+1uH4SixpK1?REOzYFk-Z~fJXDr=A{Zt@M@y4+6(zZ>_FHxL0MdP1MAupZy;UhK zZ^|~X3>GlE8JYBX<)CtGvN>RPaRSsUWAjw3`@Auh(T5Q&;}__w_HF zfpmUB{4f^dtN$%Z|6l1R1vx1ImS&VfXyCodC7Ds=m*@<`@g`t-V8SL%!hU~s)5k;S z=CMnPdnpG=8_PO{@cd}VsnCviVwv0AMbRh%DnR!ocqWULEiUorMv+*@<*S;`G43aU z^iW-WU50wn&t-cnID-6Tq~2uAB8VO+t_~BqK-ss0YpQ>+2Bk2g*BOsU%HLA2Z&QRB!T%-;YKNOO&>5QM^PaaAi<7Te?^`gx9+I{9uhP`%?kLf9TcU& zsz?h>#zWkCQ#{KJK0EpLjkMtb>DTqH^}&98YJayr#KeVJyeVMm!im1qb}B`{w&JDU zvbL+}xLsY9>t5K&1#C^njztdeD!X*_m`^hgE-ERE1?Itc%+<`46+2?j$ebi9TZ#sU zi&BM_bNT*WbPQ_?YvppiNNBmUD3i*z;o#|~@*i4!NJum6&!^mLUoxJSKt0`#cUpaG zmt|iy!)fUMqbHFpHb=$VpMQMsLGV;5Nx*vfP39Zt=NKifFh~~T%pOD2B>!ALP~kr8 zBBt^h*fcw{o#b-}Yaxh1MpWGf%w!o7+LDllL~+C8(Jx8nC7dr z`n+IW)<0MXUyXXuQ+T&|OLY3ErhQG|G>aA~QonPLfwAD7pG0~e)rWJs-WhVLM*1+Q z4V63-HyM!|&3=GEIs9$u`+K%)PcO`coz?u}_2N(`>+I9}Vxd7s6H^%!9o^NjlK0~m z+l|z`O1}6Nb$#U`CZ3=zFI`xXw!dUdD zOhfROX!G=2jmSskufF5ynN`Ez41rirhYOtA+yl*l>De>8VArUF{YBa8xs39Dn5;ur(bQNcVT@#Y+dE? zZQ|sT1p=Hv$Y}p)vsT|K7Y5l*xhj5S2Pj5Pyv$GVJ&AU(--aR9;$`8i9jkB2iOYJ8=zvbKGyD5?TAmhi_fvyG_gAp)Y}`bkPT;sqZmgt^zZmkp zr;qIUXAuK~rwWd^*j3jNSHrfphUt5`K4~ylnQy$a>EuPV-$0boO+-PmLuG-;f zCy&^g+6vLt{-JIT%b}K_?3aYOl<0)B%!4W8M0(Az!lyPoeu7u@#$XNHMMkLJ4WlR| zZD%rQ?~2%pJT6K>%5IE_Kn^~9^7p{V;YG`YA$zX$x1n{e%t6aH=mW|~1n>0V_DZ|b zEha^e)oc%Sb9=@3mq+lEa$|+*>2{O@WKQO>O~EH|cev0=EYyoUu&~AxJTbCiJ?~s{ zr%$(f9*oj%BuzuQJcn5o=3F-t&@${W&o3|gTY=u4?aXA#(JsA$oqUH3h6SBTaE!7x zHO6=eT&3OB-V+Q1v?`}*)`tXN6N9Q3`ny8Jkc$|?aKc`}Nf*t#WYf)sZyKD}@uJ0O zfXBLF^KKjSWQ&YNrx11J9McJ>v)D61{?v`f5pH`Hfn9LtQbCi+Z3;mNJvi~lvL?v* zK+$Bv!X1yke?Zo%`!e8#SDv0{tgOinVqN2VJMX*wwiXP{FMHf!Qhj2z^;5Qd%P(i_ zW5B2{&N}VkL14l1$Di8{3H9$kO5CxW7(PvWjKGaj{B6FVG$kPVJma@X|E=kbT0&#% z<+)Imj?A+rl4SuWzl~{c=tw1S{SOtT3l#x4A?&f4OONa4T>ryZg7pVhy-zb-M$r-D zS70SPutcV*Cy^1Tb63|usnkjmQ6~5ptb~c)gqU~*WRq1#4ro~Ry5jY?Cz3%$<=!_<^Xv12bX80`GyfI{zHd-`twG6A zVdvZZTf6%gVTpI-fiKI(n|Cp6Zd`HQPp9K)nQ0!T2T_AEP3b)^tn(4IZKF+p zqcf;B9wm^Zld(*7O(fA&kF(Rd`jBD%tl#5A`V^=^SSAw0t2Rq}ia1fxCxzG~RZEJc zt$isc970~+0s$2j(ow#3mP6BphuiB?{Zw?6UEUnINk0%oOZR^#o|2 z0%Kv90G9mL(P2jo+2H$eL}`n#-EtPGjrZ3k*GO`1Vc~4kG1BI8Kg{!X`%;A1=HVw0 ziKyr14Q!G;#HPFVR(%>j7KuJrR7OVykoZcutW%pQx04eG)j91P7dXn%zh*`yY?*_3wm0ht=l@37tz0Dr z`9ePE+?lqop-Z(DTSIT>EyC}3z$Jbx(#nKsR>&=)9K2#uV4djo-T3^EmOXzi=tfj<58|zEF156uG+V_ z6gb-IY+^HvRyT~nQ3ky4aVjd8qvA4B5^K`R(!6utbziG;vsNp{^Xb>shj?@LKxTgs zy#KVrUTZI2NHuk}*k79#e#tMR(h3q%n;8mr-l2F{z2q^jw3 zGvJ4ZlL+84NIe%(&Sr?dcQRVD`|(GXT9X${`v=u_%)ODo6>O}rzDVSucI7tO3Lq|X6bz4juhgpfZE(z&&bSS z$geKARmO!l!6}-2oB3x@qgtB_$q3Ig2GYNxNchu|U0R|R_T0t%>DH)41Nx_O_Gaf4 zvd1FY+8UQo`B~YCayP&{8D0J7qxk4s>|kC5!FuJZ1AcRQ zSIfgPRUQbOm+LnYau&lqFXzN0R(hb(V1~As;pv&pIzsN>qa5Nb=X(anv1B{lL{ti8 z`%W0_Q4-)ff8@ z0e=#o=6Kl^&JFu{F-I9OI*@(Py%Edf=IlH)G;KhHRVus z)fPMZ2lg4QnDFT^64|FN7sfjm3^lyA3cmt`vpZT|jwff*jkc@sh z)trW^!SQ`Ef<@<|_Dd*>hqb;3cYH@T+c~0`t2&sZ|`H z{x1oHARH#Ju8+@2u%NS$8JDbqzh5Fqn_VIB+K_d5M5OhesA_Go4JA>gVL#q%)Mljb zd+gPk2X$~E*wx{)FXNsKHafv~2%&v!uj1(AWJE-a-K$aOiA6*b#PgA_QLh_*=JJjv$Y4vOyR=NBo;!pV>2(pIP}@A`NBWWHRM2#;ibfNbtJiJjKBM?4Gtj>8Z& zYfAL(L33WN{w?o7@Mba}?dSz2>P1944Rxdbcyw5?4x-RFD-({s#BI2Kb&s!+t~C9# zJQ~EObrw3Ovx?L8-48JCCd9Wwq1P5y^m9`5i)~_zx!{xLBZ=-pYGEL3+q*8)C*N4k zv`D{}v`|y**`eey5tK!WU3E{orX&M%lSfR|h^G^_LXH|i&!Td%WE;XSRe|^LhVlS; zRHBKC&x_WjjHG_LF1d!6F>`)IP^r_XZgIaFD-ShNK6+n*BT)a6*Tn^OX&fphCx*0} z^U5>YJsD>x3^(w8RgBA4dZ{rEu9RVr$x`uUVU*hT52{4X0jHlwn2c0|@L@TqzbP-s_-OgnG7Vyr{^N%IgdG}hG57gT&_X~IPso*t#_;XxL%qOC$DwzpW*0&|J5-2KXFQG*fM(a zH32-2g^q%CV5Rw47Y-0gr^Vea3GbfGC(8U&2-zTnShS8ERodp6iy>iR{h`%B!zdHD zpvgq!r_URHujaHTT{NFQRB~SI)h;BpPxPvn{c)#XKqK`v*_^S24m2jfI}o+Bv{|>B zLkoQytx2797@I2hHfwaXpOoGFUh->|9#KZh=by~tJs#6s2KtyfS^M&fy}WVx^)=2E zKqn?GOm$7Yzw)ca_-TB}J?QF5tYYTKw7q{{_j&YrjYRUQOMH58EijtQ#(#znshlXr zIXR2Iv$|@91yt{xe>TaYmv|2fV0CSx$^FHvFZP;o5a_Lt#94dNi_B zQF?gauSL*4UT^4}bZud4A>{+xrX99T7fM@2Tk2&-drqG*)SIc5Y~$WS=JVR3fYykJ z-09L*>p)l}>4I8*veHq#EO?KhP9 zl;@RqTD)R4c~MXLQ0jZ&}sL(e|YA!na5sq}kIzg?AyV$T;| zoDj_YqEG7!K^5X-xhKWmkuj%Uvyu(5U7 zgv_vD%?KYU(DRyxZx(v-g8GfFB#VkNjcX=;mK1e6%cDRjv$2akED_0Nhb+peV(GY+H{CRi|I zcL*N)J;C@q!}-&XY;MXcEGz~|!u0`fn6fKW6+eFj?sN&0bZhJsUF_{(_T6s3xE&eY z=}nonwI#GfD@~6MVhH+fGT&JfRQu_lM1FKarNBaFKt4|Lx zIS}#2vWm#rKkcDMzd2u(ir#3e5lK$b_Expn6&s-9yPd3rZAl-=RhmNDk=&O!XdBM( zCcp9+(>!Z(pnPw&{LTK5?Aus-IB-hIBTB)<*^drfw)qTvM(+4v3J&NHCaEh896oZTG#yhf|MxX7dOhaj8dB7 zX)DWT9#q_FXRDsvoe+OO_m#wRR2tmi9PxpeN18@<@vJZ-xv4L@m-7MU zHkr&Iq$vA0jRVPpp zbH0!l6RRe4ZySVaN+!R}j5%Pom80i2bJNBZy_c4t*N%wg|^iZ>SZ%=XpK$L2VMNJOAA4HK|@@Uo5Ulwkkk5Z{bmLQLknJy zXLQeJ?|;MwoCFA8aGhVfi7W8@?akCabZtAheQ2gG1p0E?t>fb+2`0KR&t8)fzS+pl zQbm{c!|b%Rl1TFpSS>(viC-Ms+kW3ZJ%}}pGdeQyvJJ3G)>6+ql~{5WqE$9E2YCTR#D{`t~~dk-)BUZ(0?< z@by;jwc3+#8WK;ag)E1p*1OQ{Aj!Gg;J(pTPdI(__v>MU@k^1T_csoFccDSwxnwuF zF6d6BEGhJ*-L)X27PVFv3Jo;Mc)GR-zYfOkk)(pl59as&w_i;N|!*JFQC5-|WLyp39s zNySfoihfV;x5HNT1@Lq8uUisq+yf=OQi!nj??#LI1vHQ)h42#Lsd6L!cxubcmn^Yy z!*L$?!tpn{@v3}g*)WTU-`wDd%-PgsU#I(#F087ae^T@;lDWKQ;NPRce_=HEUq-9M z#kJc7lbXWUe znoAUUuRWDCV$=8ZdiK2=yqu?`?_a6v(e$%%!aBrw^}SDiZ6GMIuLorrE(Tzg!Vl=#o+KJC-;o%3F3xH6kkO#*yqGeZE}e{ z6YDYYl{pm)3#aF$)3=j+O+148;$iSM)<3tUPok8oRoU z?QQv~NN8OPF0A>&)orH4=Oi~0jIyXVQhR9StiHAZ;CHsMj-%y>Kk~k6P$5V!7+5l`X*8*(k7pUMe0)8GV+o%59OdTC9@p*6!3st^)D#)<*O3*2)aOJ zrCO*vz555tdgNp)P}i88y4;R0^AT_8)QP5U)0##!@{<0ne1cC0q7#3djVE|0Sf0jj z_$sdn>?`4yGGfTmBeTP9yb8GnO~HHd8%F#H0?Z-y`6>X)w6SW zqJfKFrL;FeDAC)Q6=I=>LJy}ldquDXU}0F*RVV}FL8vLsvS(P<0e@~66FobaCy zpIOD7@i9y5lkW3Mv95`qo@iJx#1E52d3cDiI;zC{(dI?ccOx-*WalM7#e&8CQkf+M z`%?G?&aJlM-^~od?FPov{GEsv^5+A!CvYpIw@9tWj4@+q-f5H} z_Mz2>IIVim<=kdYJ~FT3M8B@|L`YHo_C&44wsan$s~;Ud=8iMwqv?)Cu-zQ{*4l`6 zj1Qn7CYH4Suy!ryh;ER&pzVAv>OE~7CjQ3Gwx>x{;IxnLF6Np7KkmJ>qfF%@my42` z>ia|?O>4%|lLONtl;+wyJ3FHAimr%l^(&poRaV*!p<^E(Kid+df3_=TSYQaJ(-m#4 z5-?6V<(7dH5yRK+iTMr)pqIPvbg;uAy+mVY+l!<%xoE1KsOS$T4+?7a9rqF=Q}&lKLR=LI*}(ipCJD*gX@{r@h-VtJrqZt6AJQxX za8`_47CzmbM97any|0Gph3HFNekpGm`5^Ib->#4wEq>h}KPC>vr8~lM^tmWxNF-aT z%x4n)xp^hOl8h#GSVfD#dL=*t9@$K-ug1ngDYiQ%i)jEjeGoFGi|0F1&cKNiJnrXIseM}L+U!YOO?vw zeEHMt3+Uq%(`|b3>0bi$7-RH}|^s+2l zY!SfIre%`9jAoi^Hi``^6WKN;1$$h@i2LQV&wO3X3tkM+yCQn(Su)wJwaFUg(|vdP zdUU-lw}s7R0&1-n-DH&S5MbXehZBlLWl!C4#qSg!F{~HO%IO;+MS zb!rrvRmlr2x#Zs2ttD3WN#;{H9}CxJYFZt`D4=_@!dm$*1xp+sLh7=d<{s$Nf;C$k z)t$_$>*ovN?D1$YUeVFj0QpP&1s~(^Wg6h^oL`n+?PsvApsui)PxOUYM8|=VF0_M< z_wxriVsv&iwWH>rL;%Y4Mk`JsWh*1SU~(KH9?1+Zo6v5zW|TqgpHl|J#Q(RBunDqX;;j-g@Q zvT=@1qsH==w9gG9T&FdyGYVfYgq_gZoOMiT7oa$ASAqmVX-QQV5OMW+BA`3vI8A&Dz7a2!Essf<9d0-fHcCd?Djp=;XWOR3Sk9biJTn zW?|wtKytjO;`KO~+j><$N}2eDu=Vi~2cc1yT3vL?Twqo@ty8=5!PJ~*mfGp%fHnAI z^m_sF+YEU<7Qb|Aq8s{F4+=4C{--(S)sf_>r-@a2{r{j3d{tS|3% z7`B44*eYgqU6EYmL=Et#6I;yE+26w6kp=lJ((kQiM` z(R<*sv#afxF8|_zHeE(Fc-NX5#GOj5;$4O14};Ui z+8&h2nid?PtU$0F~m{l zSyTw5JEN8}xOf~G-0Pn>9sAOgoV=&1GBxxydD2rgG4XX8VQp+=jZtNL?d0LbflLI? z$S8a8-=U{muPP~wf4V`fC5520muI4A_xJgtqMIdOHevr@O|*X*DooPN8cLFO-vims zJzyVboiB-Jz3;7;vwt7^%w>y17N@e`f(gT~<~54AlL-3<>-Tgj6OjMq$4mQiG2D${ z!%MX-@h>=P3NKp*1K!p)I*2;(6%O8swdN{{gwkW7OTzARWoTC9SNX-%j?XrRn!yTT z)bnj8l~)x?sFe~O>zPR_t?1nSZ6_y}`uJEav1)I^&K6(!mz&NuIkavRKS~~M9qa;d zWbU-p^~q~OueJeNcgTom>PH%y)RkOLvNY1)1Ac=O-K3wqI18Z^pRXIn>~SL^CN8tz zdPbTfc3b=Qj5^-hOZ_x;#3kDhC#=5n2#4kf%@z7=+(FQhS7sRP=$Lj`iavsA>K=!_ zsmpoc>ry+mZLe>DoBIP>tA4g)Y~8zP6OkXSxZQ1RVN%n%HJ-jx+@XJhgYv)<^8HB1 zQ;e4yI)+$T$iL++&Ldy4W3GE*%BSu=aW8kQ$aJ|1TeO<>1~N55lx zOGL;;G45*imI_<8pTIDJXGMU;$bEm0$fCtYW5v!$=2D?g7toUzHkkS64_kzEKSMpZ zzo0Yv#y-UVr#Ep2n#kraedLkiX74HYwh1gow?GuM9Nm@=(_tC_{h4wAmNt3=DMT+#bEw z2`9u=A@VNPzR=I18ngunM#^a>{`sXQiCK;$8bj*2^P+sz{#f7MDnN`oMJwt)W5>*q zK2(dt!H|iZez?BDGT)kNUYg?de7jMWnCOUm-9v7%;xLbG|9vqz3oB_ zJmY8hglr;sj*B}K4o-bDkmV1<>?tiVOwlQLZko5&iyRpXG7!4s%7!{O@k&4aLS|fCG3t5-!Tfd_%>j-!YI2zU8>!gW(Ur6b6S64 zIJI~C)naV}&MS*O7mTF1#Y5KM8EX|BNDCO3_xmn~M`#um4`?39ALOZNA0`3yj*v9? zr#oHhE4#DmMm7joMXJ~TVDGKN;%c+(Q3wzS5C{bK;2PXL1Wj=F;1;xScZb3Wu0`Pl zcMI+T3U_yR{ch#!p6QUt)Q^l$C?sxCC*ItYImTB>0xgA@d zzuQ=?({v`vDTI+SURJvi&@kk9#87!dIh_=>-ukI`y01I6)OlP-Pij-r_DvK9c3p9# zQwQ9(Kx$j|raE&?33G(x6!XPTH!j^^R|59*w>ESK<@Z;O^{ZC=9zIrQahY^l?egp4Csxb@`Rz?OWY@wu)hOecDT_*=HiBm64CO_i3*7fX*p}jT&=H73&SThRzUhq3fB20 z#II9XSe8wCX~?x#hb;ZxhsIkAyLpt)syn0>XUo-y_ne?;KSK0&j$r9_R5am?_wlP{ z+9x%ZnY2@;Zm-xl+uoVdOx+o2=O-PmcR$EXsM3nI>*8*h-4b%^Q9`IBtc9hb=SgO? zYCGzHBssi*do}FdcEgk3VBP{l$LU7BNAh~H(5*YzV}ZR*NZzEbGV=iLYl~K!v=dW{ zv1bAMd$pzVECWlJ+R9pASih|wCBS|)>rU$@Z!RQv} z30X)_#wECj)mkk?eR%d*Xw=dU+hmhDbkIokr(^`oM}a`|u$$8v!D;q((1Dli4W=Gm zX>s(|!9`(3xy=k8gk2G|6*N{~$Y+;X>EbMNsl{f@0wPzHD~@yPsORTYO(?eMg`mHO zUZbumjd_-=JVPR~=hX`R!(9E^C*ebD99idG>r@wwGRVdGCZ;@CexmiAj=+bHuvKg< z?la%SIj=?o%#0jV4JBP9m%7Y|NbSdVbZ>%fD3Yc8v4sU_G0uKI0JYBT6>XQj#>zT7 zmGkg=%;Q$PoXj#@Pd-f110#wSb_+BVb<&q5ge+8ruq-`>d)T4We$$?jUi9b z@a5Z~fGWxlN;|wd(Mv*>197Z~ZSwdra_R$)EHQ^D^YMw({d_ex!!1j=oc-@UlYfJxQy&F}C9Us}r39*+5xF&qM8?5wmq^u%W(OPR{Cwdhhdx=^Ef z@X&;6*^?P{nh6y1!Acwp)3VGhJ@bGk4|UDev0Koi52|}YXmP)h8IZBGJiCPMa&K(9 zaqpx6($Y$8rD1){*d=CL>0G@QtvGhZ1qhfCaKZaoxm00(s`XKH+Ht~rI3&0+puBT` z*Fj`oR47r&CQTlERg^*7g@ONJ`C{QpuWrg~p}OR3CE}5P9dG03SAl_Ti&xPnHjtv&ex z37O{$v-YiP13!CNxwV;s7T0nU$XB2H+lcCekN2&ll>ySQu9Y|S?@&c<=<(Dfswzk- zT;q6LG#7CY1A;kAKs^rCc?*r2M#ARxiM*qeqfp^$^hl$K2a6Nyyz`?9MH_M*Bf=00 z;kl7Y)`wJ7fSMVJ?ry%q z7uX|;TB8XxXOyFSJWZFvLENMgNxBgzBHLpp& z=A&1AHmWc-N2+!wm}%*(r7CgtCC>(;J#;)W`?`NrvVb8q7d*>UerR6(GK-tM-O1@z zZ{CfPSx}z3nHk|=y4~2CP%~DjUnP+3{H6RJ@M5B2kU_IYS~K0Tn9re!FUqB>{$6h{ z{8bsZXS{?1>w-{X3JrCT1!T{sV906cQj1OPy8uQz+ylU;mlEpdU<;e8J8=bQ; zd+iF7JWFH!TlZ%Ml-j$)YHY5u znKV|kGAPGsm?45N=S9DZSV|g&{kCH4D^LC`mC$nz#gRfykBb#;b@v-kZ zB7JZb=xjVCH;A2emkB1noMtAieRgq)dBsd4C$U-C;ZfRa4ANM|E8cYl4SdXR|)qRsq%hF5p)~bLz@T}}Clc!MF{27Hzn*5^seBNh z!?RctA@gw(S;L+6u6154ibQ}h`i@QI>Qpg0Db$pNmiYP|p^tvVg?kW|>Jz$bvMK~~ z0#|Ct=k00UzK5E`WV%Jqpxgk)+^|>>S&VCsutIayHhho+c#}dhL4IeBW1lu?I(xTN3pl2{j{BLTqnw zLxMq@g##I-@5GP1!=6EA3GTlmQnL>0u6NUP7SV{0lg`h>GOQK&S;F;wfO`m&o%DavtL&0d=t%X4X<)N)F3vgmLtMfJ1tPEzc19i4^yXS;%jAoZ9l#OyNh zkK#XQ75HK03Sy);&-Qd2;^UizCeedH!TwPk;`R(d3~%l#Z<>+8I9YECT?V}KGYe|I zBWO-?3?0erih}250d)9t1eo>*(lY%tL8>4(hLlgZiMUC+-}wN#X8tGMLp-&a%3&%; zi~Iq7d+Ie=a4R<9C+aUoxQRp-`=P_;K{TP4ym@ijt$d77#Ws4ct&McFjqsf!rMEYP ze5bdnvb;35%*+>u)~?ZmRx4;L^BoH&NiUJS?l;c%ZfC|$GWrAodQWQ$*AU14ay*#F z5V&memWA%N*U6u?hkA{eQ=B3+Vlan880FWNo9!@V(CDliPu;HQi)(Z>S5mKaV~6MY zL~)1N4hBs?O=!CnJJ|j0uDCIlBe+idzOO$MND&I+(;mmgA5<;(?;+T0Jo-$~G z7;T&T&5xhmIA`Vwce88UnxG<*h1YUEh`3qwLr`W z&g9#iPJNIQ%kA}wvfr08t}Mp#fX(L0gf3d4jpMAXBkA5!)o04*-(YU3y(eGMN54Lo zWA^%bbW;O;O2yQ5dzua$(8Fi;=w>PDVf`CS5-zbG`z|0(u$VurCe8Y@e#A}_D*Rxq ze?`lE?2X&NV~K}Y{EwtP4jd8+1|vtrd5$Bsxt4mkr<#XyewOV|jhODH#Q`jEV(QhP``PGb%D zW~kmG@ugfZalYuj8w^G!ohMyUME_U_=S%A4GlUkUO;d^nwyUEC52w--A1}wn!%h1( z5?g6c=JSW&U{((uE|s^UrA%B4qVi(#O7c*#DGJFhIR^Ix(lq{B=#%brh>`8pyVwo; z@z_v`Gps>c_@iR##-_|Ih0kl(W{Bp9S;{MCh32_&(qDO{2bR7=ZT>?4`UL-c{12#x z{teYtq!Ert<)ZxS0$&;0+;9Iz++KIwjO#v9ju0jz|H(3umXau%?(1M=x^b!?^7=l% zhe@W+5hK<{oyU}~=$lA!H2P85zL7f}Es(a6brKt!UU<%iR zYHEKgM)R0GNX6EbS{U|g%AVl*nzqn%Z<_P)8^y|<2gt5 z;CX)^M%|<;v@v$95gAu5!x+A-zsNqa6; zM38K{i|Ae#J3y50T z2MZDXOf+o>d62t+<})bg0ndYuq|vf2B;kB$FvJK>lO2OvBMTSonI=e{7|j<8k1MNg z?IGS6yUteD??IHwE=cVysytC?cQcYs_PMTRpEF<6PaxsTC#Z4kcbg$JWsPQ^Wrg94 zvKtxDS_Q*PlV@ES{e%Mh^cQypNnc-4I>V*o^p|_e(I?@bE2?{q6i$?d0y*70S}Cd? z+6$!JTsVh8n>O-z#0aK~digGua|qvt=rM`a=`#bLRn1{u!gPR$%!o&2U6ZE|FKqxx zZTK(LEh?y`HYscDSe3MATrSJBBTQ;){g@&Sqnu4fx9@jW?p0=7lBPTEs(d@l%(tS< z=J)-NHiJ#1{FIb4H`3qg&U)&~xHvDKUwn;tP^6D*+B&LVv?qOAc9dIFn@Aqco1YN; zPQ(<(tjw;^`Ma%H>UG8^`5MTVb6YY^TwZ))^uh{?nVRc~E9ugddN<=Q8-*0)tujt| z%0_EeU-k{+wij}u){#1rctg%2NqrN5PBKeJFZpmx(U7=p6=iyO>O63P_S|zC#pb9pLFxgrp|LLB?g2WM1#KS9F&_ zl}5@KqfaO@Mn~ru<&{%SuvGEu?f$!((|%QEysJLCAl00)P7}oNhN+ z zQL|&5@NPjUtF&ZOc=D;RdVyxC`fn`NNJxHyAtyWHQZw}IL-i(# zi>cpkgyu_E^W6B!z0`-;3O~LZQ-%r)Y^;Rh+%rz>HCdMRoZ?xqA%C2My36@J2_7V! zne`AJsr7!6xe<{kmzv}2;$`xz z{`kC+197tcq}BAG2X>x8!?nDpy(TV3&NJQ|#1$|C=_$sCU+gqqI3CDU0n(cHm-AyI znWu~PnNqN!%0^VG4stNqnHa~^%>G!J4M!ijn|Ujl8qUk+^wKMv9ktr(XyxIbIZb&~ zC1t>hjx52LvJbruT9x=@m*v2&YnCpg1Ycu=0m0Vd7#K%zUK3Fsw$N0N#CE9%z5^(* zxLAgp8x%{fJ8H*3a(=c&X)_;C`%%v#L!Fr-?uFj~&3Cxzwvb!SQ7eu%w3kv>>-B~qzWP+22%ce=WuX-H*o)w0;q$kY48+JXJUwWOza zOST}MvQo0&t8yBtt!?*2BZr zT-beu6(9Mfbm^xht?e~U3Tk)(Pw@8Rz8_;BWt^9E-pl$Z4xn5TS~^ZsWhfr)V$VV| zNkN>c`I^fIG5WZC_l|uc^^@;1d5h=1Wo{3ueK=!d2To_|Z>m7Wn+nhVDh&L6zLb9n8-Mrv zp@Uj>yjar*A2Q8hA%B=}|7Vx;FI`S})3k6WESNz$so%*}%22Wu-LLJ;mjQel1@%s} zCOU7afEu|Ts6$hb&!?Z`CG2(`=yMN`twTz8Axe^>8z>k=>&GlypY~>NiXQ2_C%Uac z4!V41549kh@%?$x2#TAC#LiuxC#Qi0ev76;3#`XT)xKRT&0R?B9>lx1#!AxEMYUwD z5OYUC3I)Mbn66Jaq}600D2XZ-P1Tp|L8YWnEWf{=+2MPW=fS@H-eZXgu2tp|-_O7V zQ01OC)7#dDx`KUR(?B0`g&VrcSa$cdv6P+m%a7A#$wKO?L z7?pf_9DBMmCtq%b=tRQr>0RjpUmm=FIBmX$y5#9ir~6FQRmI^F2^l5}!S=Qsg`b!7 zvAhXU)^u$fsVC!^d=wKogps1YZjwYTbZLyNgP!-DB&8X!%*$d;7Vh)uXoz*b1y^M! zJch4KBt9W2d*yNWMZE5;09Hx!kkoH5+C<;dRm@A6^sgF+T-n!1{T~^;tP1C~7t=RcN4N4k7@CN7CSQxCUo>)Y&5dPnyzbRV(S z<1C5~qec~oQzktC7+LOm)ZV}+Z}<3w>Sj;GzH<`e?!^Elq}$lq5V&Q%f3klprlyM4 z*qpLD_{L<&_W73QPSTlkW7|%3PslrX4$UA86cwJov;|74ze938=uvHJ4TlsOCE0X+ zFSS~dbDIrxmKr;q!ZCGb9F`UwsEATgeFQFjpQRh5SFQ1iXv)mJF&Yw4!gv&1I8ZUq zH&rENeNiVf*njm7X)-D)REsXhZ%+4?8Rya4G!csm`pMa73A<;`!eC)mjMzjC(vdc7L}hq0kX9YDJ+_`5HEr z^+Iw0ZlX>oA(`N+Er12*`uZj{cv_7uPHpNQJsHoG*u!t4$%41&y|}aIsDb=zdZu;a zWbbyWsXMQGBCpL70sk*t&5;9soi>|Z?oR*(<$M4|bsbxGyf31#=tP=cv6|%0gy-m* zIF>Ty|1^$a<&^(RJp|^gKQ|Se>IC!8NcxvZ`p0X*ag`6okp0z)_&uop8lH*yg@h35 z5kT5TSn3i(qs9hTmW-Y`R^D`|`EWbSFWE?GdcQ<^SCZr(c|h%@I$u`$;TFfiQW1=CZg>jc+W16XFk51+z$}<(E%Jj-LXW5KEUv z@oB8Jg-a{DzufY&GSi+p)>EsmOz%Miyv1JhL6@1#O67{5UB*^fZ7msh)UL9{oHw6W zDKY~M2oCoPd)RGSd;0ljI}*EJj2N)v@ES@Bj!;YU(omkuVvo?cIPA+xKNJsrSBZ&) zR%WFV4KMNoE%wsFiMwDNOKP>{Kg7iOgifVy7M-y#brlqq1YxPo1bQ-+L1Fn2*$Kv_ zWhEca{$-UfPNrYb5J@LM)Jw5thla(~Y`HInyAc%Fq%U8zdaTiOLU|=`bbQQRlNh3e zKLOz-eM#1;&=yG|A~&D04@qAOVcr5d53GF{;S{Emh^rO{UC0|dsW~W6cF}dzbD`!U z-SH=Sy@ZVJG8Kz%Q`PY0MJJ2V%ScQ)QcT(5ND2s28zRNo_P&T~np)eXOa%}0FSh^` zMO%{DHzj;qJF|!9a9hs`LsMP{p(#VGcXPq+@dFhG&E`P9bl!})_aNt)WC_C@9vIkN zhS)P$j3ureSVUpgJ>A#CXWH5W_WXg-oQ%UB$mi`C2TJ?(l;<%ooC|z1+}xtM@XR&$ zm-}znMv2SP$L6}0{FilGlASfCYJ=ttYQDzbWKHgA#LF^{wQ1rnEJB zjLO52)Sf3=sdkU)dIF~$9!r?|S)PybthX3+AAf`Ss9K_i!>%W##_G$<=&mkml)KRF zD~+Ej28r$4(n~z;>Yz}M6ZNoW#K~a`!8>>qn*qyQvfO>#qTJ`F*krfGD3rhi`$ag+ zNgo|pKQSAP)&NnTz&9)l0|3^IEvSqgzk0T-*y>hWyA{!Wf}*5#MwKxJwWzRjYsH7t zy4c($s$QsAAzSxbKgf-t`_5%qjkx%HIF=a?9QKjY(5`ZQlQ$rI9d!todVkuzdH&wB znUwc-XO(k1#dyXWr!iSU#hKZ11C!o);pt*VP%y~#Vs4oVk~Cr^oJDwNOPb`u0JWIe zN3Zpo@1j7=DSVw6+w`DVUH>3)v}~Ku9ASh{gHJ)&>ausA*mRIAEY4zwV5QR-lej7FpZ zi)Q6i2sUbBx@d}`;RVCL0c5(*WG{-k6fDu%DMGf0zSXnLD;lB9Xo+ntcpwlj+g26g8XERH5&6x`0qXX)uB?i zWb4HrL(0Bd?0$6X`MfpsHt)6kyu8w&Z#L~NEhTK~{3$rtNgvY^Lwi$$-=ATPD0F+GsRUH<+1H zZ@`Gftz$q@cUk(|`PO?pcSmpR3czrMn(Eueg$bpr(kOKeoO1!S2hEMGfnDf4c==9d zya)a>b-Tn1c>d5aLD83uuWgm8$1ewJ3HQ`^40X=kOb_!Q@jZZc3?T~5J%aS4RIjGx zCF2xzZ%m5lz-Vy#s&mD=sjKEATLtYU%PlZH404{OFF(Sr;6Z=SwgT9-OU>gOW0NY= zNUoVl*=_NSz8ULD?WB|Z=I_)(ea2T!*2SJSvet-OttJ$4I52vPL-Sx&zQF34lD;pB^j^SV`qgeUIxMlL zCZ*5*p5kdUeeR)Oo>qTQ*`?*lm3r(LzSI3;i8Nqy!8qWGNgFD6T78{o?^$=|n)K8G z=a|a^Z|MeeF(4EGQI|B|<`1-kr3d)4F-!^J4RFkREuPTkC%uuSv%U_A6ah~@`8XLZ%b?i z$OUs~EU;kv@JtMD!*9O7B7>1Wqzj{Tu$kR|&?vFy?If0*2CWu3Hr-`10(3s;U1b&P zZ@RKfw_A9j^~dj5Us?x&J4I7Ly#~b)y%n_7gTX~P z;Vx3Fme=cVaAtIZ=K+23ZVyR_`>w)%<-@4C{q1ZlgWoqX_R-z%cGh+Kx^zX~Gu50R zcM?PNDY=tE`js5mWGYbk&c*GTg!0yf(Ux94vajYriYsNXmjoWSeij5S+SC}28CqDfv>!4 z^-m|Pm$FqI6u~|Ua^6ZW-PHrF2%NU# z3x^E6P{afz5#;S>fkt|<1+HBx)nPe4?_I|}#+Zm+^#L@5I6S-z7grJ*yriY@MYs~j zJ_t5eP#2JANTjOy_+6)PRN|Q(T8^a>GneRdPtMqi`M1=EZ&P3mHKOkwGbE={Ri;`I z_9v~6TDKXdNA07DZlnWc4$&v7Ynj*xJCjT$NS#6~C(`d6&AcsqT|+M>Kc%?rH-VRg z*@ryEa^yknDMbFqBW+vVmLHx7AIgq2uJ*p>jucGRGT7T&aB=r)1PS=#VT?*JgrB`n zq)zjc5`W;>Y(Yz*RTqR6>=VtFk7bEC@XEZN+T=ee-ll~T9^=BoZ-<`XW!L@uTa>^noe zEqY`7DPyvYcf!qIj*DY;{CT_mogI&r9xelwXUeZvny_C;jRsf$2BSHUe@)MyvlFh0 z&q>jj)Gwes^&y&pfjF5c03Hy2nFaGGFe4!TH90!BOP&gOh=*)6gqQXHl<#s=UHlZh z#-IPwDwEL<`3O@KTt~>eYjU*f{Op~0#F{Hf&__To;Y*)eh@9;RgXZ5%x7v7BbVKY& zMXz;5Hu=?>V*!bg@rwr2swk0pUN#B1@mL<9W}e$h8K)+);Qqa&iPhdcShzha`9P(4 z`X(e-NOw$!Li|Kb#<6vt7nZHvUZ^pC=0>59x}sz*iLkMc%qwW$cP z-(;O#P4Rh=_~8yZi-d$+_hq$Jt>I)-)Fu$-9LCe{qLyAABNFp(s>dUrp4|n4Xyno+ z8xKtGJdLoGa%aAOLCYwqyH#9^FR|QEZVhnGGIxM0P_p1>78DtkU(@h@b9%HBdZkk1 z%i+8auovQq@+lI8sqma+EUQ@(LP4Q@Y<7KX`5tfuZTpTGB(D)`0*0VMW>Zn!547if zF1I*X2nxk8FkfKjlft9j4E=FaEiidvOfsTjNVeM|J_6B3s?33-?DI_#Sz*fmtkX6R#QvBjm1z8VotLqpV;JbO%Ar&VRQJ;-d}_Re}lO?UTn76Q`fDUBp!I6+hqRF3drA>Rnl!64?N4p&I$PgDNq3vexiGSOA)JO1HQtZqJ9K&I zfuXmA{J4Cu_-MsF=w1F)Ms<9p+rH|pEp!}(74AWxwI}5HA137-3g%F>`oBDQ4O=!H zm)JD%uYnk@a|CNN;S}(DME^IG6)0%)zy6qGvM7H$@CDQ;?^nqFH^3jZ<%lpan!YNs zj^P7F9SbY4>=Q?RdEZQtC(7x&X(#M6oHAHG>%48GMSFX)U9TxQ^v3mu3OHA7g)`G; zoHXOeN}HG48#Zc47el1G{HgbSveosImj~8DQ(U6fm_2xXUs&&M%1fC@%!aS|_r#9a z`t)S66!pRi6~*~D->-=bQ2SDU_m#IR?1M@Daoc`IJ=v91b!+r7@KfOt?3O`7AO_^V z-cDFpX7bFm3^AyM%Bxh0OXtp%LEL8}(GSIM7hTw|BBk6cb$?qsEk#Rn%i)~g$y89* zEhU(BLT{9?x*jf26?8;X_1J%Zv6!BkC12Cf-WEJK1vkbXC?dyZDN8D!r8>oQdEk(% zxrqbhqQy$S)M%%g~ToU{e=#XLIvNu3(V_i(d zHpW(W9Sm<@v`$Z=!IGKx_)JV&!B57<4Tipq0dR;jLQe;2_@Cx~Ch%u8I@9dW z7CUKI$)C zbjS^~gZqpQZfAIs#&s5<`a!bq`*(VK4Kjc~No{>BFD0Uk@xCDSA_*SEoCzh7Q>`N! zY(YJpWe#%G53@+Kwq*4&u$`v7eSEgx5UYl>xI=FFppab{4MH4}^(JlS>pv#)T|4 zQov&iB@$b@9sS}%!vAq){(ekA%kdBKQ>LM$;w6i}gxNe0mcpN6CWE@7v0P49vz{#)x5@Tm1(%eZ(P6@k``A7p_FRhyIKuAZ{ZLs3&yCyDJshXAf7#Tu;4hu}UhmpG9ZkeyHU6?aT>5NIq2T+!x zE6K_4TY8bnT!%I=_I&rf8I!r=o1#*a%Wuk(mS8PNq`l;?2x=p3ovIBeT+ru?R6}dt z5`f{(V?LdC7HBcUx}2+*w#-k2Gh0> zgy3tAsT(t3M8%OM|JOhoIH5$ucg_Qjo-io1W%=}<>iXg@K&*i|*=}Hcu;~~_Ewzr%uQnJk4jMt$gGj`R3 ztLpUd6?tLo`3_v=p0?A=^eU#n7hfW%I~&M;1nkng4;*_wNdu&RQH9@NZ;=uTuo}Gf znm4e4#_=PR|=49pqMCC~Bc}Gjwq@rr5 z*f)_~5i(NPq`G2ObPttxFv6jLPrQl-Zq=_sF+4qkE74!~5Y%)DMzwYF=r~x{xt+%0 zRQl$s-21wBeKJJ_iw4&3Kvz}L33*ZEXC*zJgQQl2Z1;Xncp|iavq@i2i8%yrIvOAX zLdOOzX4LMONG{>1l4IyIVOPWVBa?QoKtpNpX7kL{q*z)S3mWqP&l6Bjh zFTZl%cOWtY_4UW5n{6@n`U8$I$dDI#j$_}S@wo*nl zPN%5kz&~!D2%cM_jbgenMwqN`13sw)3w{`ev!%sX72eNk%92YVeX{H(W|#heP2@bWcrEY9Y-|NZdw z{{$rd|H?Tnz{+&l&`Zm4)i7&ysq`8Qc4U zNz3i0sNAM;ANr`i-Bg&|;%196R$Jb%p5XXO+Tc3~bPd=R5)0LCYUxmG$M^*CQn#ht zTEN@6QpjPDiIU?JKIO_&KFnnKFL^+@Z4rR}U%w@` zeS;auSr2B(zI1M(xFQCW(jjQaKDMRvWuIZZ?X86|XKxujhTmql^lH3+A5^oJI`}Z! zQzgNoZcGGvStx$|enYH#zqdg5%1Ik?c63cPF5p-kPLIv{0=S#8)@-BJ4jDJo*3PqK zC8dCkTP^|Gi=pV;X;x`$Zf83&j9E_47??ZZE)n##yhIj!m^SVPf?Ro9kz{}Z^^%a& zB(7E>!#tVk%)LA3i+9jZ+(e&&W>Eh+NC&fD9;9K6;m-i4FrkGs{JrgxD8`jc?Fs%R z{2L^}(BjB+y2u!Bv@=9BRQjaY>CyhzJaH z2EL7|5?OrWJvR|gpLgF``6H()Kwvx2{+p8;gY}c}Dp621XTk|qKM=LcI47B`+~?cV zYvY4?yUM0vcFODXt=w3T$Q$C&W8vN=-dxRiEA*VpVo`F5xWT=Sy7;&)2gS-x(w)>R zI@RjNyJ=yVV&!Yw=OwQ!v(4XNUO%iP=ayRHR9HBiwy}W=cfI;5i?4R6Q=5e7^Qq+I zFqfdU-e=!G7MA~=aN!?|NfLkzvh4mmd42LYv8Ox~a7MGUW|i_BD1b zvfhN&Ve~L3|HJU|N2zh6C~OQ7Rj4C~Bi24`#plD{SD?mteypN|W~ky7N20pU3~m=6 z)o5#_N!(93WNwL=bmoJxHD$U&@j>l(z3*kkZAMA2Q_ff?5y1Y8*Bom5_1vZC!;@Uj zMVB2rBu0|qnvYTRY`p9=#9s?Su(@P zp@K4q-+sRjvnLcqNHET_q?#++g7?>vWQGrm7(dn8@xl?q_P7m|Z}quf`v5OwiCfdz zwNsc(hD2$3&OxNEB)o&MP~iY|CU^V7bgF93u9-}NQp-u_1l@79aL> zqPq7yv$3*rpchS0kYv`q^NkWbCX274l!->i@cj;&QtH?bWW(nslLW{8CEt0CMF8_3 z;$8nqQ~Y1JSy1xk->mm?eeI>iVeK6NGDrpEBIvm(a<8G~8?`vo|K5NT=?W4+HsOFK zpUN;GMG<_kN*xUASS`my<;IINSs3L66W^->sFG)O*Yz{SSyWPn3!@bZk6CD=dJ61a zA{yTYO+Cy_vGl+kE)ws6IJ8bf>7ZUYd}f@&D)E(#qR(c5>95O`2MR=H9PAs7p~Na@i&hr3t+k0WL>B#>bwMYJ*pXR1&OU#Q+P|c z{=|`KE98i=Y?M0FF`9k1$Mi$o)*bC)Ur$gS)GT&}!laR;@UnEvOo@ z(JYZqN0j@Bho&kGfsJiZ*S9I9)bL#_#YjcHoSk2L9Wn4n!@T?(>gjb#HzK3#UZ@|H zdzn2c5>uWm`T2$I301lzlws^7((yP@zMLy}c*YvHUHk}L+(o?qvba%6NzG-~Nm0iP zNXB`{r9Qz(tSu~%Wm@eBzcIf_eV<2_cqqYZ)VsD2o7sA>Upd`Exc>NJMJ<(_7!lItVXQGU+0>`QnoYigqCx%ogkQPU!1?*0sfQ62&#;o zD#n@qHAkMpB|0pxOvn&#L)WVnQ}Ec*-#EN>U+H?1u6<4UinUGXRgc?UG<^Y1mH_rx z@tQ#Lt8~Lml9ol?@-l0W^l9KK@1k33pdS``Q|+LY+W5RBK)YM|BM*Ls!?$%Bp{aEe za^7hh`3I-2gbgdh;sJ=e#=Q{t+9R60e;yHsldal~JN~7jxJTc%=&#yWjq&R-v+0|K zj}yF?#aDa6$cJk<%#JGfC`LTx0?rKkHM*a4ZW?TI(I(V z$hh=b_E&f|M^V?uQYxqvjaqeGH6#(Mt#jfjJR)xnUf>(vB}^CIxDEx;ZiZ*bVA`-v z>TS_O69B;4i~r<${oj5a-qM=4sOBdEmXeJMY@{EQA(*i*na8Ql+T;s+t!TZ*9~*;2GfE zlS1J16&Lihssd%93SQVEFtD>Qd|nLIDDp?u)vt$$wWpGH^WjNEUnVunb^K`|Y&}!n zh6|(JI$PZEEy{3p)~p^syY|X?RW4VTsc~fQybqcz*q0V3aXGWqv6k+WcjdDPa#EF$ zv%_}00d#SQ{7Xusp8DwgQ}5w(&D2`Il}`69>5oN!AEIZcJym^`YM{d8`>)i!L!qhc zu`z5s!hW5Pbke%8=LYaZB(8jO-Pn zJvOzHja@0>9Yz~U`Y7Y~!spHm(6shU@+fRc2b!0OK-1el8zAJzBu33TAxk|L!dgfo zauT=Xno}gY^99IfTWii`s&6oH);w7%erIHhr~K$RFE8J5rqh<6<@Dsrd7vls9oL;F zMFs!M*P>(5eTG3!*3gcd3ZqxbnY4H5C+GvOKIK8iz*ekfqw%N*-APAVJaCa*GFihI zcgmL2DfpSrHQgYZs5nsqsQ%?r^zFf|dUh5=<5?B3CL#ooO#B*aj|K0D7qN}?bNR*& z!FO=FlA`#F-xG^p1WmE&q?oIJD6Yf&*Y^ZZ`<6%?4o3Mev;?xv?-JBTfWfsMl?k;b zq(}Bztgg741{X*(XXTn3cBjq>k-y1h3D0CKvsg&&X0gwu%(bd(1SVTRX}r1_8`FqwS4>?mUr z{?XJkhgZi6yuK|p3k4y#NmI0=CvMndDuQHW@7a;Vn@cr>(%h%3SWNXA@}OSZPWT_R zevF(%)3=uL@}A@*LrNZ8LKJK)=7-cB60xWBT-lDtKF6J}ngQ&Vj!VdpKD34 zqZ$JHZYXbxf}v7v;0(e7rNER(_u|$r2U}xTfLvWvAQHP|?|fPok!OWoObN6E%PyxB z7DaVUdRC=2w&8{VKC1|V=rOH+Zqk+sYJY%0#kJyLQJ&WNO9z*+DHH+XOC+WgDB7>N zi(r{&Xve-aFqzYn6Z7@%lJh&AQey)f7v z{M1^*OTdslB|ud&n-kMbDf+Z5`-LshuoQ`+kkhe5xwrxmkc^+a{+)fZTiM>*T;`HF z2$MKoGRys9{z1_B%WB|@jBNA!=4>&s%#0~P2qa!ytO&r2R& zD~}%1&wCZDCT zOETMF7y>_oqaBSpU5}0`@mr`rHU zGfI*XtAk>m>_9uki||T-6{R}xYj$%{A9f|!RZ^oxWF3Pb>%`7Nr9v*<4b1Rvt*XV8 zJ`XIB7Oy==^n^Vt>{~06qW-~)U1Po?q*j*4CUY_Ic&HycL%@b4ug0|8Y5mrP{fAg) z?JKI~UU8`GmSp(0T;wO-MbulYj;wEcx zd_nm#_t>b!m|ew03qWf~cLV`~Vh4C!T=PJyQ#3a=RFzQ<2A|rOVV}Eh-YaiOcQ~fI z#m2c~V3++wpZ8Jf46Ern`$nl)GM&7)@gYy(>fk^xEo{PxR3y3P%MAfjvtN?i01k0(n5vgN-%rRIm#K#^|6Fac!f zz8`|RJ=MZ8twTM9tCjVV@%B<35E?ft zaOFA}?R<|+YhdvGN>L_$nxJmHNus@g{yOy_`q2IOWNLTB zj$rR8jFRsxv?jm3$oj(9;*wy#V>C{veg6uM^!vK2jS>j?{u)Wr!9viI~J5`qE z8x-}toy=01vu|@O3l=(H?T39JCLp)(FBEfiexI0XS8k_e82SYOt{r|^f2Y6H7bvSM zsO9G_wGt_3I&(Up!~C~eG}#E6m@vx|R?%{wNI+p}%BLu0_Bjk) zQgE~Ev}iUp#s9?Sc8BEW^s+wPPIixyTh_{fyMLLpgLL3u zPp*;WRTbU{^{7v5JCx_0j{DRh%i9G^=o`=?8M z;{(P|VM&AAEZ#}k6%tlU_Vx&$SM=%&MMYOsrf%82CCI)FPONb14Zf|^x0!bNhOC^j zKR|0&lUO0mQFb0smk=9@GRD(VOk+e6AcMhH9EugRN-19ovohhTWZuTgiJ{&Va(cwP z!UayP(pgA4cT#=jDM83C3d64+!&||`_}NTuyLWQ)-Z{s7U2voJdQju`fP-aaeeLxo z1`v1FMI|3nRc!%vqdIsVg&{lk`}0TaftV3$vECkPS*>8-ZMAg;Ea;Vu{pU}%T5E8yOUHYjt^=!=`)j)|y;R)h|Dsfx4XGiL5 zCf}^MG#i5aQFv!J-nL+810%FSdfchRw6Vte?aRJ)iii_=QHEn=s?uv{cGg0s?b&lz z9(}T#H8PpBi)*35uh2uJpxtt)HGs#ss*m)!J9P(_ z9_0DN%F%f=0qDdfg!tH7F;R$;#jxk5MYwI**xH;6ica^t>56>S43upfG@@D5ao{gq zq$-rKP#@sCSH4UJz3`SR_Iy)rZ0G#Ca9(WP_W@>fBb&4}vC(Gzk zmG${eW8uDQD&C}Q;Ji2pZ54duEO`n@NBel;o~KmH(-O*cIfMIln~{p$gLOuTPT$K; zK2~tDmcIaK#ZpNiL_A(uV&Ie%q-O}aS9uD}56-q&$^^hs}nl2j7LL;WrZ z!=`g<7`B{2m)oJmNcOohyMBRpm=fXn**#tPyZUvtkU=L*4p{;OE7I0A-89`v%gF_Q zQ7g9LPGkjZs9~yBwz6LXEMsdw$r?@4&y{kA0##`sv{;W7__i)$S) zX3YTlG_+Zh?|ptmoFR49k)@BBtF1=Tx!u9Yx+upolF+A0BnN%XRZGCsuwrM{vTTNa zULks>)NqBWeu|4d{p}oO7@a5aCZPgd7`OaDz>wW&R?;vo))9iTuTG2OvfR~^JD+Dm}p>-rMr zZ0{(zoqEchTfDyI<1Z<$tpXlC<*V$^q1dhq>+ z=3m{=WZK#Kp4?;gjrnK&8Z%-T=&n#SB89?Tfmffqcu7nePI#!dJ3Y)y_O_)n(p#zxW%G{(XdKBKq6f+^9e9wH0Tw3ebL&STKXC_B9z~wN!on^aBk4NT$R@ zoZ6)eyI*TK*o+6xuVq6CS|U6?a5($2dKN8;#pvK5(EtMe@uIN=52-lqH0^> z!f#v2sZFiX3s|Zvu7bqGEV5}vIeSq@(+1N&ek79ADeT22D-vaNAHy`qP`G(>UAQAB znay^NY>yPfovXuxcEDXlnQEUZHLbQtRB?I8$~H;_+xtDeImZ1<)1oV9sPh*`Mj_fz7vxB3ZOpVif?V(OOJ2}@#i3xy^$G<3$LV~{0x zpywa&K#Rm1eA|n}Eo)DxuU8ton&#tgCVeYTVjkat);u_lvVS0Ly6PnsV0th{q|F`Z z#pvz6Z>P7<;q`FO&6D<+OCsppz{zk#>L;JrY1%jDZukaE;2dN)W6BC9CQ=ss6_(R) z^TXSkE>O91x^AVycPxHp#`k#%3?t2MB*5-zwLf4u@nTEjcL~DeS8~>-MawZ~_AUKo z#z>2M0C?~g{Mz7vq@wKv^7+qozc>?@@EGix?^vJJDZ+&30{^kCphdY-k^GwNZ4hH} z(Ok{-8*S{0+%#MM&D&J$YqB3l)~ILbj5snv>`{SM^>gVXFV57BtU7JIP-9G z%fTFz1MC%X*346H%xi6gkXbXgc>bxtv%zkfVz`CRq&UY};q6hL=Jz|0UW>Yk^SMM? z7J_!Jk+-wb&J|h@ezxL-3X)ios`lps9;qSpLdM+x^&RLlBMM8meYs^Zx$uVaYs1m$ z9q88;m8S7<8x)DEy~18Dsz<8cfvCNxB~3I_??CmhQC9C;*1V)AZ(pBA97DsOmADjN z8kWaKC+-|LM+OviG-_R+?E>A)wv7~_sfk{UqtvE8j^+d_DNiA%z>+7bkk(<#@Vf!I&fLSt)q`}IPxikyaOF$a=L%y_fS35l#jfrCp=mIYA$ zMz_RgDK*zQ!yUD>w{q^{(0H-?rz=x`m`S|J%ZXBnMZN=pMZ`A8bzY-@HtijB$q%@^5bgFH34GDOu>-X1`ILt!fV!$jmZVoZ>KsrbOwT=%kshH;5|P z;dy5EHPy838A??#-ugtiSQF=y*QW z^p{N-vaz~T4$7OlnNl(Q^u)Jel zdZVdZBAoj!(x#FOD5~{WguMKw$+Dm0r|Gk^z~tB|B|5O%_+-^ssjbgpMXUbj+j)l^ zLC^(@-xCu_Xq)Bt?dHe9x~cNgjm(TQI?Fg;zhc_GIr7=0t@58-wsxX}?~`?nEDV!} z6LN3_?l<22K07^4)%moljPbDQ5Fd2RF_6rKp31)^ZyFqIXu6}K`@yoLQcRIo%Y5I* zKN>8HtSeu6HCgg4iQ#jCozMMxX3_ijxIw3|mt&2Z%Qq@*N^{B@_zd(59A7+n&2PRz zug+EiIgl@k4HlFoLf0d%25@_EN}rnE4rd2=!vrQP#hm2o?E;ik8mp4Tvqp}@n^??s z38WPofCBfFlGidqVx~@VcOcN!rV0WtxFEgSpfh1G&4KXU3_zcaX6P-2Y@|#HjyS$G ze~0d`k?h5FRM8_6urpJINdA~r>Bm3GZdvUyJK7i$wyRZkMmWVBKdjKi-a>sWw%9E$ zSUz5|()96BZsIwe?R*d*k>m*@n)E38dRFb2rg%~W zPk&oCgrX;Nhp{+b>@cs5smqwThY0hr(G-x<1t}LgxSW4E8F$X}#d#DnJgy;y_Cd9z7-7pY=aez;Y%o7$c1OFmdb4dZ{byx!vAm?(sCeriw68F=~7 z<^@W=^+x^&^!|77H(Tzs<%2e0d18|2`np<&6NukDE9Csqdrwa%?3Z`7H%}nfhOxY_ zIbfSOR+UscUD}TttD0+`9-y4Uyj z(C>x78R6?hxn=#4p5KS2BAAMYAOAD+_V@W}APZ6+`BgqzNpNI`zZ(!VeJ16j5l|n~ zJ=N^jSe-PrqU1ADlui6bE;qmdB8fOrsM9a;ux3r%n|7#8#2kpp5b&cmF&N5uBCXt+ z7egMaSS_My+wp_sjpw!+#YQtV_pe4i6AwR_)3Joba^pH6Av$yi@}Z>Ox`n290BCeb zJQDaWZ-_Cz-x^2mzjqGHRaLXqyB*G?m3VO&@pOG0IXW0JMjsH zB*bVmr@Cr*8pYYaUC-wdD?wNWj#+9c8-XUzrx2Y(<@f? z9V<}>OfnsAt=JHTw~_#^X$B7zjf;b!J=`yDM_@cKX<%jXfD~W;Gfw;$bogrW&&Yhsw!lTn7^fcX38Q|d$Y@LQZF%y?)|TMROJ!%ymF z^b`h0W&-#A1t8P!|J|j3p4{!(vDJPc%^j#G1u!jfU zw;xtHE+0>xnq+MzY_&{rOlaDSLW@lbVAX!qLnFx8{bmy23$wLce=lohfc8AOeE_y< zr#?mpmTq?)fsWzJ`_R@9e{u4gOW(}VnHE$$a3jnuA7w9-huv4&zpiv2885au2aY@2 z?eLgfC}c)CtD>T}d|P@m!i7561ERd4AMrds#sA6u4x{{f|Kxt*&^55j?U@gSXwzk; z*9xHQVfC$XaZNoJjq!e5Zk6!`7pw^T%5$$YPyp*hL9T9}>WOhZZowVsjSjR!pWi!B z=By0v%5p{XVRSwmhiRF+0e&;T~jsd61iuM3yWA}w)F-0qWi1+^iiMhIE-<4@J8CPN#o2>xokK%h(Y zGtA&8o9DPVy2QBbKj{M)N&R?C`&vGifcI z!2e3vaRvVZ&-d2^KFl6!a6)$23tiAHJb}CbhT;a~7< zZ;xl%o`(N*8I*PhYHEqSvI6jUPc#+mL{y>!dQ4V#2MVm%mF_V4`*aUrlJUepqR4?M z>Q{8jco{bfeCz=95c@)m_Er+uESwGKh8p~j?*(;8;D}po|9*<{j*0F0GqykbQy=Q4 z!gKxq?L1KFcB|QH5E%^c!G%}Pfdy$&{C~Sn=AV!Z2z7~`=Bc5Si+P7Rs;5-qHUlOs7HfsQ=eL*OZQW1W8e zpGy1UF1#F(SA|`kHCd#^CgD%Vdzb9y{N&f-UO&f9=_L>K^?V_c50r*+P^LG=PDX9G^*71^v& zC%u_i4cwsQ^n2U%$tWdb>6Q2n{#1n>>1aON=(-uWN<=Q}Brtnfm0-(h!+1NMTn^gTP=84+f|5D1zol$W923=RfM&~cOXEv#wKut_ygMV|J4=G)>+j6^Cp|;> z{8YF|7L-s6uE!UMr+H2d>%VT%Gg`Odf@CO9N@cE|UkLe_7N+nr;y*y*A@^b0WV)D1Zc`U4}#p&U~t@vm| zmta%xbv;+2zFkS&0;(lPb28gJ8}d0T=JT8+=`itHdQtOa)zNwVMn=f2xABKpUXe>w znF~TFTxZ5Cn2MIoXrw8w-&JO&T9+ADm90)`iJ!iwPCe@OI-_Kn`9m{RC77m1ou4q9 zgtlh6(+x1-eV&B>XfD09dTgOgcINXCh~90Eba(}vceJuUvIn<~Dr35oy|)T1mSmga ze8zKwSvJDrCdRu*- zen4Ns=YDxD6$%D0Uf65H81*D%uhMZ?b(E(y@bGMFK2_$8Re1q^0K&xuS^AzuI6=WZ zou*O>;+pnt3AyO%?xSBO)MeZ={VmOe$!AVXAJ<)tg6NSzGQA}5~M=1EsRSh!t@@EMY zD{{9QN!_VWT(^|C0BaT7HcKz)9~q~Q;Ww3m`UF~)=g*tu`j~XwfiCgzFYG2ULD-Rrz z>6smHR?A?aZ7t^$sNrpj4gTe;a46%JkC@jYHs&ECUn~3@ib*p(vnoK=@eVXY7bwtL z*6g9Qc}cks{~Omz{K2(1ev$3&Dq=F;`5%`O`91}$Hw(BN!(-d`nFp!eRsw`X#YpKV zZ)J@gyoEatt7^5_)m01%x383MP9u`e4_tj?TVWbUPGRwKRSS%RBFEihP4@ki*hHzS zzpXlsVsKY@SnXL<*fc*iIKkqCAKVvww?(8I?=L+OI8*#(V%>bDVUc84-NwM}UF*Oq zHV;HXw1jsUoK``RdVI`EyWz2ZEZ*J`xkHdk(Hsx=@nQcM-LUwfWw*2id#Pw7@Ck$X z2yz!vYQO&>7U7Tk^rW620LTl!-Ru|vZd61UfM4m|*Beb^OK&l$e%Q5pltme=L2Dqo z_!7R>*Cs^f*Qxk}x3VqmNsm_KPj1>FjlQ}cz0D5y3?`mfp?N+$huOcEWChctg_0J# zA^8lr526oo${uH!XhfYw!Y;CV8ljImVe)zu0?*+hkj|B1Jn0hY&vOirD5DSJpb4Bg zi$opKGfKPh){O+Q_nL{R;&S1F0^B~4n_+pIqz!qE*IzOS#xvEXOkd`F=id-d+$SiI zpTvC0rB^Q-Z@Ii6wD!PJyI<(gfK064cslpjt+9stq{{wyY?&$EA5(`+km?KmjMUq@7)@lV zXAY-)o6v`0hX;T!GvQyCOIFl}PHTbbt+q3i5}6y`Vc{5jMVS}7!j&i$EI2!KvAFM= zjJhr6y9D~cWLcu_MdpT*9l*8&IJpr#e;RX%0i>+pTo7^#9v`eT7sz%VZoNO+D7rU= z)M?njjY!+%p&4~n_df$;lrA-b?ZX|Y8axR8n^^V#PbXF}bGb7Xm=i!}+cJ;F{^2~w zoL?e%ng`^U5o0N;TTE~G0A()gZ}-!()5dL9gQV|~oac?ofQZ>D{nkjgg!m{S)vE05 z-i-0mmg7+~)Bc=Cqll-?Fy{~3Qy;{BJ#h8?VLl(zLw3cX@UGt(ds$nkbro&4@o=d# zsN%?Xp41^nz%}LGN1TG~su&G9QJ|iu{(*9GLS}Lvc(i?7J>rDyX5EA86s)R{9hBa{*LQJpx8}MsDLk4Rel~&h_=TgVp zu>P`A_=Ulm=A^lOMOC#|F-+k(=uB!1>Pvhce99NJ>V!S({eJKZlVOMEx{y82YUH(U zhPRu+q`#Pd2HE6j(zG~%{06r#!Olazjq!vdjdQmt4y)F4lNsUhDopnfa zF|lZNg?g*nBG}xdo5tR98Ofd8OG1llF;TqADA+NOO)2Q=^|2&sI3n3^r=W9a@bf(KL}%&pE()Rw~2UIjY#C_FtUPdoz6gQOy-Q43D0S%HYwh z zt*a5IF3PfzW-;kKE1MC8>X)~yYo#mJ3>I{V5un4daK)jbpZKb`cBs~!RSC>~uUE_s zjwore<%oTIDx&PBTN*+oFtjumKfZXSLqs`iC2NU}ReRG3AIo_ct+Q)t_Hn5}f zd}+Qrv&07uz*ZKeX{!hs=Xqzl*ppl!r3v)a29PPx$Gt>r;H2cX8~C;U=#jRTM%}s4 z1*PaJIxFke@$V_GJ?<(LP0-o2z+)ncI6In5iWqW7S(X49->Ns8n8XvvG-8ji4ynq- z2?NhlvEggkPLQS>3GMGX>hL`BCVnB)L~7ICUoa7#*D9||Rj<2(MLV&1OSR4!8vXed z3$(R~&c(0!5NOv*n3|7-pK9nd_3U(|Q>O>u_;hVjO!~U=&|+x57bZJj`>ITPQm>(& znvghVRih7?F`SioG~b0?Kxrq?#XSev0@~ncIY~ie$2u8rg=~y6FQQoHRlWuBES+5z z{R)-qRoBv-6xj<*{)iyoCGj!Mm0qx&yYwaaEcyJ5coD@vQF$#Q8{so0q~DOb#PlHe zv$Ne)=W-H5d_JT33b*Krk1Us2VW&a~D{9z3V&kDMS6`%96t|L{0^Vi>gLn=$;!%L& z)w~&b;WI=Ln#mL z<9jp~K^^0skEY=%sztV%h5AnPZvu8=>C)m9E=sm6xKvY%OMPaN!#x<4$6LqNPM~X_ zQk(PL3Kw`U@KjXMM6q*ah!4A19?F8HPsq-8bPIO0yy6#r!jzHDKlN=G^w(cm39Z3X zv|6k)-$;T(C_#MvQEiRd5>|dx!+4uqy$Gnj^M;MSox`xp?buKMZ}pM!-3G@Jq=v<0 zYjY&rbv-oYug1}0!7)gJoFsjEq1b+E-}Tn@Os%hRi3fh7a$S!^+gUVo`^M|N$nfxF ze5v1y8a@tTg)Q1ZhzETZ*gVaS5)f)@DNAcU8;lGce!lpV?$#GQj&D+=*oonfF|I_4B{xW(Ty5W4 zX|FmFe?`sA5Wb-HX|gLnDp{zv*7>y|^8!;7!l(J@Yg7;*hv9y&sJU5F#ob&Hua}xD z3DL!fA6*#LA(!5(51yf&MA`nd6{d@A=jP!M9P}Z-Uo5$U$D&nV_fl$@0pBF`J0l~I zk0TNI5FExgy6(asfOF7j_rpIAk4# z&huCF^Mm14mMKP>TZ&Tapk2X}wenUxBfG}xq$i%FM%1(}ix(-){JzStBD7Kx?qbyl z1D7j1Rh|8{()=%peEfT?+rRgo?6z_~AOAb5CZ;Uke^ij&+kTy&kH9 z1@ zjW$FRd5?%4KPv53QmeKFb@^OP;gG+sbGic=yC>~d6OnYIMVy<3|6;ch;#OqJF$2+k z2CceP1oqOoiO?^7uSv1_w?vDb^ehhp__;Eq_9=LrVx?7r;uR}7YnAm(_ z$0AqE_i*k#cq}VPxotNo?mP^4SkIJh2(l3Q%@g-bi0TWB66RRa%1KWG`i}+81jJZq95EwqhRKg zB%^~lL6CaJos8g6oj|ztGmm{exxwc{e%3Jg2*>`hC)%SHP0fh*P9oPY;vEsX@jKA{ zRT8Q%`=>ArxWzLlp{2Xtyg~uZyLJ{I^`1irkkj-($*?nOFi5oAytUHdyFEw+TC`pO zgXK(B5L|>bE_fvIguddYe}cBWArtvH4PBH9Ew$1SJ#rD- ziEw*I`EE~{zg*n=-y5_4{9eSt?4t%7wo)^F(^$p&pG(0e5-7zZHh5^M@Tg2jp((OODc?ffL6^CcO*$!c-(W`GbTT9&`lQ~XSb<2azolF z#B6AG5%!3^I0Wq(L2r$dnkSVV@6EWu?bB#|KGN5+d@~MUuE2I13cnNG1JsKGw%n@D zxXSAlokWTdOY=FZ%qZ)^KIcZ=v#fqmZ5F=Sw77bc!s*2wmuaK}N8St4CF6(|e*NTk zVs?EEC&mJwzSozHx<`p`NR8214cu#1b8EeN=L_dCSotBu_iSXN_h>X%Me|b&57gCD z#z9*^ufOL3&aHO)LbWB|Zxiu3=4aQ_`$pp5zp|$XY%fEKyG0BbA}ZBoJTv)$?Ia)% zB>C+DFL3f-(Z}_7O~n5xN34lion3{O_>cs(CZO%~PwQ!_jBunHnw){6%gWb3Ix~6q zPl*!p;y$B`)Bj%feG9k{_mD{qVE)WmNbJwY6ru}XRf)i?@?C6Q;Oxdd$lJo$AYdl^ z>}&D932Ti4o;o|5@XPi*^TT=BuVr$K#`BFzpOG{f~Xa8O&p>3N-zG z`R4+04Afi?N?eInjD+s1S?%jQ?+LEpK;ZYs0;E?dYdg-5@lC_*?eclE`ijw8OtzzI zquL2VCGuX;UK%xXd$*cAd?efuBCvd2$9m>xv*Ow!h)MZtAJVJ8KDnUi$l>l&H$}(` zE|k%imsRW24wYPrK%^TJifQZ!b`e{eM$I)`UBF}!)wR6oqU~t-)haoR*N;YOkh;nE zfZ1?ws&-`F_ZqqE_ESbI#iE)0)+|NqizG9|*v6B!_ix^$Xa+Q+^|VXA)ltYpaGvV$R!>n$GIPRI~|2c8Y2?xAi= z%48R<_7F#!xn04tlNxm5jzx`*MW?NmD*k9B8gcuyJRXxrPBFbBC;| z(CaKOmA&Ocs0R>Lm9fF0wVs!9<_)JX>!a(H75U3{1}H$Z!%K@xesc%RWS9%65~yUV znCu?&7XVTH_50k)H_2EXt2lT8EG+JFcs%2xBRChkq@9Ba0-()-NUp2Z)YPAin8Nek zW()Bm+9|RDQI1niZktwA`n*86p!sV|{~6c+!3&=mdAO{dG41`mS3Z@k4Dy^hKp1=@ zC%qq|h)7~3jwszg3mM`L5G&eES&3MA_&kFzj+rPs+x?Ai#IXd4KLayGjRDc&b5ilw zVVhU?g{L%v{V=+_H7y2TfGZD$OjLX|Z4X*(*fUEPXOwFO-Y<_Qhw?gQV@yu*_H7jjE`>+?@QzZ^uJ~Z=0R_qeU{+( zKYrTHVC}gW_Xi#`OiT7W*TpQzQreEK596B*S;*k`T&xI(L@EO4I*>n#aFLTmK(%Z}MEgq@L*;CQOkDh|56v#b2-ceEf;^V}F@qLN`rO=G%4dKfNY1mho(v>w8 zWBY7u=3MO*Z&;FW-Qo$x~x z5ew56XbF3#|3z^Q>xSKY*ud85Nch`a+0h||AHM1RLR^Jy(K%FA<~9L>B;{FhAg^K{ zlQ^!3b8^9=377W~k5VFYWjTqZ-m#D|6^fqEd6~)(qu3GCk3rk3K)I*FKL%VlvlSNDTfU<3z#Xaaw)Gts z0guzmA~&&x0|TIB4jbug)$uj~G)qSDH5u*AELBkr3%{l99@DQoXQNFuJ?ff$^>Eq4 z&|;+rHz(uMA_68%lxx6KaAoV~QO4Oelt>I$OpTNP0<0 zCHju337>t#S4S#dP|xVP$V<4>u9_^=KZVm<}(1f-#K5F9hP5qh`3??9q@v#No?4>k)acVqe322PBPl|7uV zH&SL5$Vuiq*3$5OBjJ4lUT&ua-AT-zVmz&CjS#YT&7&JU!b|4s!=z`T8s5h%g8o9h z4h--wAumNv;;%FVsZ&(Lo(w*Z;d<}K<_2t>I9}HmdosUZeqfsJhbbh{PrNf^OQO9| z?C(H^S8YAMHFurTw*u_2oKK>eyArzV3D@6Yx0=ICd>E(sx#_fIWJvDUiYX7Ie%OzE zD~;N10;~~FfDISCcPP*twF`ULU=@-fBK2q@`cFjOl=??Re(~3;_kSbu|Kh5UV{2fu zHUen85&d(Dkm-By*gFy*A)x%|9kUc7aNsRH)ta$_u7dgKfA`sCciHd%h>P7h_nN{sn zNm%d+bp0xn2co(PWQzCkAJ21wR`M`o|a`Jtyy|60m?2;=4l{>!v(r2euqMxrD(q&ffPD`;C09I}H!X@vCnC^>3K9(%; zDFLuteCkmERJtB%lmcg`b^|4K2aT*nSMANRIQ-OrevF5R92Ljx8+Hye%)f!Q7R~Oz zG_-z4au4$u<^;aQ9L$gvGNELgp#gG2O;0$#Ia_~!C%hQuRU_9?ZJl#z)YVG83}DBz zqA9zcTS_xAGt$=)(PQXp3zr*B&J#Td#9{{!T)(aSPg6)ou-TK&B>uq1s@Uk!hI5Hxp9 zEBg2kTFnu&vBCXIcKCl6rGPtcJ#PbG~|NmnEd0??&ZmdMP&7)1%CPCxAf#T=)P{-X}V}C9uD(Y zintnWC!Vj*KW59D$(vut7RX%P3(_H&c&;V{nAh^2YRFXuu#8;F*ElDvSG>-B{$6rd zL6XDydqjTmVrQPs*l)$+UzpfU3i|+aQJ9dR89!Yhr5P9LWtD-v18H14{+vQIo7G%` z=7Jkq#1jWk=1LSic#MqtotH2Y`#%d?q_!+ai5n~FhhmLz7veLh-jg%9)ECk&3@pCE zNHY!jmMot=CQ6&%o^P#2Cla3cs{HAWUd*<^DTP%~(6qXVrV4f%k*@R-Sli?6CfiKE zzhdJtFK@NJXH&F+Vp?R*6rhdxfiJAz?G?&RU#`s)H@NBWJ33hHQBuR`=V?<{q;ayLwS6NJLqy z`5tlIFqc(u(kDBT1P!b2nn+_6$jFr;JQ#Kq2G0bc5uP8v_aP}nlETAEF(gZ=ngmv) z3~Rz3z3ve1%cH4{q+Ioe$Tdkn3YL}?dn-PA!a2btNd z01R+fAl}p4g<3SnvDh`L7C!)CL53mc`Y7}h(MU6(Px$NUA0=qm%fGN`jj6L~U4$co z)ACn0Z7k#j=e@Q07x!4SKy$vOr+vlOCW1iY&PiVBApfM#3K0d+kj!G?lky(2Z3ZaC zi;nz>J^#Zi=ylC-k{1r)p35ERJ}=&^Q2@|$58Uz_IteDLb9P(+x<4AiTs>JE8B_Xu z$jnMWnF_hW_3%FG$GWQ2%Lmu+-xuS2RZ*RN57=;&pW{taGcm@`Rhod5pr8l{D1sm@*r-B4MWjYSq!Wrr z3xpz|^dcxlf)qh1k=}dnozP3@J)s6j;@h5k&Ku|5pYOi=-utoH0|q06o$p)UT63;7 zXNVr5IV#{`)Lb3JcyTN5GHFGiOF#w6JDdRf4~t^?v+|F-@At|-j-?_r}gaC?mn z;R06&w~y+0o4!^gyDwXqc#Yfm$Fe-6aJKK;npWaDha&WW8u0xdlP$Xqwnf+f0VuJ@ zZHHgltt*`oO|X`VL>&skfK~tkl2F}*A83Yrnxh*sG{VDz3rlNglU}oH-g030BP_}J zc|B(zU8y2UG{M6|AyzPE;**j3CQ{8WlL?tVVVVpkF(<$P>b?M>58;J3S=wu5`JBcL zWhSJV-N}EpBB@$YxOb3D z{u@z9BXgAVoJj_F<>wUYvoil=!LulyndBrXsFPMHGxN?kEOZ`d@(D_iIewm6Ocrqa zXvIcW|hNXbUWSA|K*Mq}6g`<7ye#ntg@*WqbeVn7k6_WtU#OTq$2Ywz6e z+q#}8=Z8g?wjLnG{(}51>G%9DPq#|!N!FIEU4Aj=?YI>{_7(pabuZ2!lGZ4SPIlXv zIW^flfhk#qlzD4n6KZ_0Kc#C>RV_3*;6k4Uo;>=xZk`e5kl)3wWMkHN{e}CD`hXfc zgq@*MO8b-O&v3a6p*`MmzF$kZL@`XuL@ZI~;(PV|p>IwOj`EwzIu@|b0~l1MVM{>m z-4b7XpCbbDinmqob5e`{(>FeU)=*C3D;p|y8>i%)d5f#txM$He(>P@=t8Zr6V>4_KJZ+{0T`#U1}A)I;8=N-Yt#}l7n3NW^cn><7mwJ3$wqm!YMiHL z@KwqKnvD1K#{=%AANbFVKXhI=A0IEID1qm;Sy05$6<9JwZV}asi0lUO##KH3bH=w} zdKZQNf~5NEqH66Ip8xg?!Cr3qP_mH5Ou<7=*v_aUmXKx<1L9W-%%OD+!axx5_zzDn zn(s2~?>})%9#n{w+s`?E$u89}ae1MSGNnHy-w?l6oc5p-?Syk5#nfLZuCBZvJGi_w z82enPzxUd9(i*bVy4BZyu?bf&9?O~Cy~$NPJu|JFb^3|(HsG*vac9fCgclwOqju7B z_IYdA(@@bB+Kq$v`VBH|P(hkLd39ho53K{=-u0Av_@$;3rc-hKyK^t1tm|5(?F*+` zZ12{yu;%B<#+&v)_B!sh_+Lsl|8+OmcEZ-!XMZksEWAQ@{F(yj1m?4k0-0BQUCUB8}4HY_{pvVOTSw*kXzAKhEe2pequ$6qe1NN-8}K*)}x<99Sx zXETi)hrYE#L2)@^icafy2RL#17QL^IL~hh$Nk8Up`f+T=mlvrdxLjGCdS${Sv=GF) zY-Q%kgpgNw?PAXScE0=+Y~6y_W}Mpn3sTKfc+BLMXRKP|dT^6BMBV(zIN$aqcJ485YR5OQ#7j~m9N=gOF2OF>?T^;q8hz0eFH~rs(myYtijildNsM0A@VB=D= zmZ#t9XJ2_SDpdRr_!(`*2MFnWvJ~u=_LZ0I!e}q4J0=!|oa$oL8#wz6GecoD>Yb~@ z^`fUH`@rv4{Ewp)hz;5QFB~AiAwso-jz;dko}&k#F*6ZBqYTqpc8uw0IK2(0L1GHy z|AI2?vBseDN5`{+r8;+y{cr|zDVet8hHUdD7q3^8Ys@y4#>8m(Lxp7VzJ93)gVB1< z4b%nV9jUgwS5EIkFZVbUn`qt>Iahogz}CsmKnLW7YPQ0@>R})RRaS~z?-r^^YPchE=>S`vL z;tYZxEnC_XH>Oa>$R`2x0WqyeP4IS6W=S@iZ+CN0b=`-Jqy4%Y_MOSVC;TVoFKE!Xz5xF& z)T$8Kq>501V~sLLhzb>*5z>sGtS%rIZZ(Bghk@`&T5<=NO}36rLi^=tX(Xj)jDpcj zNo_X^^tRX{v|N+FQOPg?@s^;z1PN9sz2|qc_|x>v+IGcw;oAxn|HC3s2>+PBGCsrHR9n5(!Ltscs`s@pGvC7QZG(T? z3*4G?|Gn`?=VrASl}!0SLi}VHqF^f#KwiI3FGvZ_l-;zxFt*%~qLSRw4~0pIwHXs#O9j zp7k#%ht&v-gVuc*f#ISf$ef!yt0txoG5W1g3C6DFe!4%TdF-mc%009ZJiuHibm0}D z$|rB*p11asRdrj@_#H{cxo05CoztibYd`v&G4*U?1@%{Z7U1H3zmtCrH(T=lJU|o? z*kJ~Kb7y5a!G8P%p+%LL^VcE5X$E}Y8`S$h21?l0Hos6DpqkJh{q7P9@^q{gedL4d z%9+NFM!r-8DO261PE<~KpnT?Lp0fm>*uts>|LFO(p%4;}r3+^0vb8f4d9AR`czX@7 zZD~vspReckv}~KZLW(Hef`*LigD=}1v(7)pz8Xxda<`ORyXtZ47N~2?B%{Uv$H9ElM3rAr#M1-^Xb0!!5`K z+beJ)hxpFren7KoSl4Z?JRrw0_T@+;d`;ZX-o zU0Lu*W7fB^r1>|z6N$>+j1;>REq;R#nj=`ySyZ%TuKnfY(&T(sCFHx$U!9sWsexB3 zTx&!Y0e5ERH5U%C4JMoB?@Xeqt)cAO6;ZvJw`MJiGUatm4T;eR1diq;LUAYIrJh7co_#eW1O{bvlG(@#5Ux7l zQ>gtM6qBJOD!(RF2XaONYw0cOlBalMa!1%M5tcpsD0`Y`in}0-Ns!w4qCCI-YWGGN zGPc{AA4t4&rG}$PX37d z)7_A$qS{hkB(t%2ztn zS#L#1WF+mrwHbf-s^ZIGf|!vG*mU)3&hJw?=)T{yhwz;FUg_?1 zZK^eu{8oS}n02<GAGr?;wJihEu)8xV^32mN+G;v%wteN@~)$S&COxN|Fh!~2~?1>-4PJXlisI8SOQ z5~QBx*M?$sDs``}#}Jis=Bk}8M+?U}KxRD*1i>dBENOSUoQx;SkKZ(LTK9 zM0l$<&#{q87kPG@r2dcsTSv8I*go*t5XmFk)5F4Lf5r65haB0u$b#(Y4o3a9s|MXv zWuF-mZ!v2sSE4;gIo8owk!|>5!zYD;Qqg=>2}wk&>6@%;q7To+*?7U*=xh)|8Ky>{ zI#wk_Vqq)~^6d=IV4>s@?l@kPx*e5aX@=j0>_U8O8oLzO+P!1gpdenZV~=h_PG5Ks z=w2w*Jw~|Kq;w$vqy=FAf-e0*y(&My zgjbIIe-+T~7gz_zLW1grJbjMc2bCCbA(+mw#V7{*$=5Yea~eymB~RD4 zyQxYmyPl(xinb~CF>TOEZLCzF5=5oWUIm5a<$Wt{8qSaPjB!Uw_|Ih44{Izhfs*kk zT7tDHKJ@b~qT*toiZ)3Lf80X<`aO?ud~+@+4ho__M;|}K?d?!4!Z^$U9Xqz*m99wYBaTfaN>{kUVG5jclV)h$v;FNHX$cz%d@Woir{Hk`Skrq0g zk7D~KRsZ{jiIk4J#=^- z-G`+EHBr6PZd{(iXiSb~#5~k^{xNa3!P~G>J%Y_JUD$n!34}0MNHOu*<5~Y;=yK6< zSC-c^`_WKrmYzD6$!Bk8eu0I~lfeX+FK}tF;PBg?M4`aqn|CU2UaDs8iu?q+a9SEp zZwdfF)Sm)0IntO!P0FpOoJYJJJyfiLvQFDlJq@v$v;xTAzU>?##ygP>1t32cFNn` z9*Ze?1FX}VOD}3|#w^NhY8!6-=<4BH^Vl#4AWs_lKRSl`1gq>C4(&cI?CdvpioWVK zAX}j(NS(_9dky<8BAHZUWK%8k@s!JOCCJn=(DDg&!T_F+Y9jTy-(7Ma>XHi2`d;A- zDcpD{Q>ee@&n=yLPujbi=OPxnTvU{kC&?xu6APP@pvpECK?C^{!vR9hNy!{bJ z;LXRjd|Ew$d0qW1@>Dex01{s@pl}58^la2Bg=|Jkf4re?gYWuyF;U`RO@N z5B;jga}JKX%WM^3ckT9E=$QWr+JF>VEBj{A2OZ{Jd;9b5`+|o$(zNi}Yact?+{i;0 zQNV8mMHhd5WI@o8vAOtLmQ__m%2C`MXMSKI>r8O0_NyqJQe3%?%rL~Q-6uj%FUCTgx_ zLkY&XN76d%#TpSjJi7F;o!9)8xt1E5_E-^uW2Mtf-uul*?%Y>wL`o!|i%nQ5e&LJw z^%oRCKSW5viL|0v>UlN<&ON87d zWR%RCt#Bh9@92(MXqz|PcFLj&D!3SCqAIa{*(dTg_@20slkS3H0!?i#0M)p`IKg2M zc2_q%SKBGD$HzJV5e8LG8M7-lRYZ(Dy$RPx?`++f9B5(?`y41&No{?Ab|KXeDHir9 z?EN@{ny+xy$Mdh0wanbQ)zK@~$??7QunWzA<0u}$gH_YK%#GfT?R=k|D7nk?1@H#b zL=S?e!WSe?+I66hYD)3^vp}}!aaR9NVmG zS&73JYToibMP>VHpX(9e*s;A}CCDNy=<@Ky1}^XV*5rJLt*}c*Mhjbs!XHzo{t=>( z$^uXU+LBUgk+=>G#}8ZE-u+=8FBWbyu*1_RV!0{P)8rVVl7z0+b~Kq^#?)G4wE@u8 zUiYisXkiL#>o;zyygN!_0bL>iuyjcANvO*0SDr{14&83ADa&-jGr?iGt|4q^(p0*K zLAvJ7Gx{YDU6=7npL-Zq~0O}BZrm@si)?;9~?TkJL=u~eDlto3Dd3Sbc8#c^C9r%kv&=d zm*RBQ!C^fdjvU2z)WGi1Uue|@*&_sOs8;5~z{SW`IL$iyR=L{-`C3W&qwCGD_SoAq z^Sm5XtiaoGzD0cq63oP}8N#V#`wO9)(o}t1mus)!xbvl?U8?Ykb>J(UYkq4?mJ^M) zHQm-CkV3TwST3TX1tf^3_i86H^n)X`!X*b4DH=dPBsfU^hxhtQqyCq*#3`^z zS{=z+|7WL=_hClx#{VD_f$8qlSy8~VkE(zpZ`>cyan=Glk|<2fc^^^_vo`$$>rn9%`ixS`mDhBz4xr=; z-A0xk^(a!FQx6AAL@c-i{SJ6eeNGP0@7timg5u7aZneqLu}qe4EAsc#kFo%J!=_4r zdA#rg%e%L|BY<6}G{(VB zAKWpgwZ6Bxf2`6Xn3egUf2!Pk&>?$NHr)PI{Xu2dp?()6!AFEYgwAfUo+~?yl=0}M z+`#@vq1|*~*O~QwSo!kBw(7|GYZ}H~Jl8~n{6i-uH!|GX=9#X-()8SS{h8f!r4)|4 z+lmi%UD~{*C(~|usE5yU$d!Bx`qUd)3Yly7ImhVW8lRBL?)#!L0CI@!uhkIM4K_PMY9h1Zw73gh0hwGO34+%a8Z$~RPI7Q0&H8T{Kin|PyE8_sJR z@xZE*$?3ux4JPO`!2Ad%;rZ-zN7At{)1uh8KThY!=BL74PnQ-H;v<+~$VScE_PF^D*d8AM&^_v7?@dKw5L#81D$$iru& zyjJT!km|nw1y$4v=c8&&7!sK_5pA7Bf8y49bP%o*WCmJ)e9^7D?cLq!T)f#sO-s`}>7YBB74F9B#o z^=96s*o{GPsgr1G@F+&v%UJJ-#4{Tds;tmc3O~^jar|e>)%=fz^8)W!=1P2RF85F3 z+W9JeNlfK=`?j3Gj1Q*0xqg6@_l%36{C;>kNo%%QKghD@KIEPvK9+!K=R7!#B-NaP z;W1@LvYU;g#}}{08Cf`o+?*UxiXB`!$Ys$=>+CF=Db|RM7S3}b3u>G`=z#V7D7;>^ zIY!Vr)VrB=JAFvQhUyzWh024Hsxu;fJX+d;emFdPr50&k_DugaYHJ-19HFP z)3@5IyVE6bv&kiaQi^GW4xtCng4K<8%=T-d4Nkg(OxCwU5 z20mjjoG?V~Bg>J;B485t(Z1n!K=!;Hs#HCgCZRSiTsx$?(u#+*^;2t!K#M&18J+i8 zRpA1_Nd*Sv->$SS#pT4`rrRw##UU3YbMWab@euolQ~AFj9wcT4d3HnLjC}z`%sg*v zINAa-L$TAntD06NU&>iByOlZjcf7 zh@H~p`92ZX3rvR14ARX{bwt%ZS!kGmwWNvQR;G+M|7=wI0=oa&l5KOJob%~XUo2z1 z&lWI!DBKu~54r9X3KVTG8;DMInD%22g$5#fiI&29DObmQi5m%)G@mqfL2dz)ULu2( zK8Cc)6xd+8kh75s~ zp^4X$SB_J>ke5SchGjoS;d7m{L?y%AA_Ts-d2#J{`~``Cm!!_lqXCkpLsh^8E>nKc zp~P1ET&-#8y#>!JzQ7CX571~oZoesyd&chNC_GimvrV?gDX?cFSq6zunHe5VJnN`p zrYl4EJ^}d!duq2L0VdAY$G(qwtwr0upyOgpc3br$&+x%6j-mKUO0@?nNzcT)AXWpk zW(Z|caT%O$wrB0$cPrPTz6h@(>2`d*B3ndORL8X{@WkDgsku!2mM+Gjz?$4M{JPR- z%Rfs^t{I2xL^4R@52m?}R)oN##TfZ=Uya^WLzD*|fPf-;hS-+t(d} zVcqGJ^??3WpdBFAIlshmh6BDCii8Op0>w2>C#90TV@|Bd7L?{Fd0*eH>%|vZNXQX! zooWpd2HAi9Pa^b9$^eP)=%@kEl~-4b1a@3G z=&5WFr0QDBMg*L5zM7r$8#d>P8=upBHaerDD7LJIvX1q*vn}1NlEr*91Xvq9SXL(x zf9GF}Rx5vbte6Gq3r2tqAf^) zO4|8^7A!g%p^0Vq;qhzU$V9od`Fg}1#utd+AikUH;;Zw4D0(F*9^T58EEkgXr@}`O zUOM1{*p11Z;gDQbQ~WGK#TN|MIx{(D$MvlRsoX|9#+7HfTf2MxG--h=l}GilI`70} zCulY;#oPxTJ@lV*z;(Gc$T1I)1Pu+Cw*aRH83@vW;p8Sm$hm~)NgMc7v|bdbfBV+R zQQk)b6Ib?!F~=dLAsWb8bnA$tt!V0UXt7ORkm2f>C2fbd3Ydu$=AdzCWio zDqvII(dD>?k(aWACR5XxNvfdD{{TZjsSb|j}!PxLZ}0r0R4I9@ivg&RxEOnLY9Fi zoj6L-ifqzGE?eLXN#172b(b+D;YI~9Y7WSP|2RO-ZjVJ1MB&5;bAU5NYokfb3cxC% z9tU1yx^4cL2{=8}u7EZGzNdl9_737TAqRKx^83|zqjAZcV#aC2xRI5S9(d1DO!e^P zVJ`V1x!YU}2W|f@*E&^RkvVJQt_cWhH12##!0S0|eH0di`iRV?H$Gnn3l!vP|P<52y*_4WLV zQ08Xd2~x%args!%INCr1vEQ+5PG*V@MOgo+ud}uZXEek?i#M*BgRI_^KcoY#K>6al z(22R}EQ81kL_-2Q{@f6GVauG8b<9~$&l>*VNuk_S7E}vceneONly?D@Y-$co*1lT1NK+A^|Sgo&#~$(uU0?? zhe9VO=E1fz?Qf$O+Li~XN1n{S_o`KKiY$*M) zBZejW0%J{7OBry3WymdHM43apJ#5G z4J%#$w%{zSxnS6bq^hSS^k9$bf4MEzM2hv#>v#?umGM|b3VSeq_@OZ`Oc6iA`*plN zp7b$)8cKMB7id}y`A|N3{bSd~>wNjtPR~?@`QE;z2N7KB|AK(O8wDhBmxda)-v<2! zX%^Zq(4YSWk?DaHLimx|Ur<`JT+{9V?kqUu zhK#|WUnB4Xm&=f2W&m;?6i1PYfOxv1WC^HuEc^ux+vHMp<^r8hqKE&hedQ4@TDDpL zIramD>70L^fJX;pwOQ6zkaB>jE> z`sy6XtXD|Sj!9d`G6xwqiq7z!7Y5Cc!e!>1fH{Sf< znm8N?JyV}}U*si*{_ZMAwf;T${TOO-EcU(P-CL2uk(b`xa`i(cia)H6W}u&?FgKJyk_7pD@x-Gly<*l3IkS^#ZC z&|9g!skgRV6~h8xwZ=&fF2I@%K2SlB>Zu~_n{{=cZ_BANdN3!EE}%12I9ra9!DJ5q z`|-^sD3l2^omg%AJsd4zb~Wu<}TLkds~B8pOdeaM`LEG<^Setd*Cj!l;$1xDWa zDt$pKgaK7b68BefoA%mS$|2AYDWLaXtN6d}hMcxC`b69MkKkm-Ytrh~6$FbK;{$$U zQAe`MM)5bVwc0MHJRE5O3r4Mby8~X3pnyZHBC(5DNI77I~odmAsr$8vB&i+Ff)?R*NcIqYWMec%fq z8KUPs^dC4g!+&*H{y%)D`qy#!?*fup2U1RG%K*JdkP<9oX6p(c4Y@})Pc)6%Ra;HJ z)6g_dz4t;FUxZ~Z(x&0E=iPP`Yl;c(#;5m=*LSW(OsB{fL?_ERSpeP2%WkR3(*zUT zQcHyZx4=z&M9229Xq^1h_M5}EU8*KtA4GwKBHRb~q*@OaVFaxUIM zi(JI(Fx(dtyAhX%sHT_Lt8wvgA}T%YCw@clJbMtJM84ooWF{>I@el z(XtZu&|))ntugL`orvg_B#t|8tzI)@%sTj3Lxk$phtTJ*5bX9%*t@uc7jV{K?7~KQ znvH{{fFEgMC)IkY-iTnb@Jh)H%ezvWrtK)*)!=D)zN@LIuh}n8CxRNU<39xdYnnI* zkpT0N{S)6}hrNx+)5#j;Iv+hc3j8^Ct_JVX){}4NT#yj?o4fSkNd*qv}+EG z<+RSUAj;a+8fdt{MHQxTArsrVC7o)Tf-D5w)bi%Ul8{i^=^2I#;7y~q2hJbbp)NjY z56_)YDOpVUrGzOrqU?cR1#v~BT@Yma)hJKR+K*7EQ(P2j>0$cN47)@~Tr4>J6z-sU zt~A@=mDCVSCxi*=><|P$wu6=BG|w|{06NL?1UKdKq7PM;5|MSOPikaBZoESXxU>U8 z4tTIXid%ws7e9A^RgbvAbY4<+ISs?A@Dfz|RK!d@?b|Nfdhpjuv!zTLd;;ZBX7OEeBMj1d zbVPG*q{$Piuq>SG_?eD3x&6ftD=u7CrM7FhO&!pkwpwSnh-u%u;E6mo!uWB|o7n9X z%(r;)Nk5_Fruc@avRH^lCf35ReyBIugad<-!%mvIRO#HX+pWR897n=wSs3^tn9=jy z!9rqAq1nb~$vh4ZTE!soz-;xNM){=;RsKAp3(kcU16h2|;AnY{+-{b-+X*cJ>}NdY z=4*J7lUp!3Lv%%O?QInx!)R8ODJ4(tKl07#L#z!}x$GOw7+$z0k1&N65yfd0O(2#<$rwbY*Uz+j!lP57epZlz@sT_P&&^w8@ z!KzTqUnPu`46*eha}$tcRxs=O@Rk7B$XNSBg|kT6oa-iMz2P%W`RmS_%WG64K;2^x z30C19aatvK;8w9r#w(iFw;i`L-fh3NNlLsCLVFJXT!gWQv34ogN1b2v`N2ZA4GJdD2pJc$y&IJet4v!RI(EN$GTr?y_o8OENL56*N5ca`2-W@KO#U{>>#Jz&+ATKkOGi* zbOgj8ZPi_74Tb=SYl21Ex$`4&%`B~Jy12ftcd$xL- z^ynjxgDBQkxR=Y3HPI<5Unq|HWhAlKi~Tb9b?FY4X_QSNBY}kIGSZM^ws(3O^|KBDfiRp;ibEx5WAc zxciDxzD>4$1a>Y$CAg(pkNo-x#aT9=oTVCvq!i4wW%dc+Ijr7VrUeTtIdtBlrWfH>(@(|=?20w^6trII?9#7* zsQhc)S5dgkrk*A6CFQc-J@^}kG^?JUa+h=|3%%I~RQw0&Mg?R^*(x-Ij+V3V&A%WP z^mUBWt+#=^;dR%BKSVwJc$MwztiQ$@C|Zk9UANUbW!+>(KMXh$Es{s0=w9?<*#5-Z zPRC{C-tXWu3>>5|6KR27*+Q|@TED@fS$d1+CW}t_-rbLhka1G{#piv(EqG;h%cHTL zw+avYv@k4@#VSsD@Ko)wepEpeNtJ3e40KM*GBvV5&QGkK|6I=pllxQ<NiXq)b0KdnC8}v`6xUZ8CoV{LjYL4I=xvCNGs+%$*UCvts<1si*Zq zVX%UYcj>3I0FX@ltadG%{4KqYP;(b^AG}W^D?w|OcSq7oQYPi+RB)#R`;ww2{{tSu zbMVs`mh4jSRNf+2kdinj`XhqEFZt_arcoj

L; zldlHCnYn2KXcOSk#%w@Va+LBCD?7WBU@8PyK^m<$vWwsu`nI03T1N^6?fMYsdOUYp z{kbJ{S^w69OXFwL$d-=XG+o*_LH2ZrW=ZKXLn$0!I1X+D)Ml9X4sfw3Ra0&X-!$Hz zGTnOq@Jmk9oZ^G?bJ(6WYfjFc8VqfoDzbl|37-^fQ35!(2*F;WR++IKcavj@s7S#= zIk`QVJb%iLE|$0zR(Un#6fC+fZ{POuE@qLWiLG-xoKAGLQ9@fAn0mDlY-3(P?%8gWuOLbQv;ye%`fH zLLPlYw{@|`auA5}Y35>D+U{<#sp{s9x!bqsXKj>WsW<0U_0mJ1jg+%`e>`YjEK$`4 z1WccLBbxB@i`1f?E!91iQ%392%lNi}ro|ypboW^!7_NJLzP+lQcU6j`#aqKeQXrQB z6b5F0IYfeQCa^UYGL&qr%W{d4U#aL0@;xXXa>CPoN?USH#GoY~W^Z*)ty+gv>SIPK z@I#iueOPC~Kw>mmPbYbDnX8NcvS7D#B#4PSMTPDS7|+E~cY;Aml`-+6HuPr77qixi zM{D8nezaZvRho`69=sn&W%jd-L#;gS(&U!q>GUTGg#X@}==667dbL``8{*eFx3BMj zR*3KF^4>!hJMm{R4`CzpcL=1INc}K|E*8P0&!16IjI_qs0?li{l|6FE)U9`AhlmeJ zUOwY1BDp(O)ZaRqF=if2dvKX7wlj%*7aG%0g4(Z$Vy8S+A7w* z1Km3kT&D9ehy1Kv)JP6(^VlpbVmiVTdnI0bAbhV>JGn@AfS<1= zkJusU+FU9~KR-HoCo0tQ_8lN`zUBpUW&(0LDkf-9abR}T!?hkYC9i*Km#~qnj$_+T z^=113RWPP@cDF<7LP#@Y=Hh5|`-{clq4&>KJ6t(4wLsR1N+g0gFT_a;!8PHaUrwS^ z|5@yoP3aJqZSZ5gPpYA--t3Z;zGlO^bApPkTYdIBAl&D+R^n_$oS{MUNd)AEJDyGnwhEn$tY&MNN%Kv^d!=f=AecCegR;f(1M`!7bA3!^++5Gf z7xal7v%J6uO8b0L71QulL+yJpDN`~j31b45a>w{F)k=6I_txf8npChwBE`NQeg%L1 z;Izc{gt2lD?Sb!|2{KZM*>TkvDLo3tblza*K?t8?L)mv)vxae?P-A~*OX5w6Fq|6` z<;IvUxhbAjZ~J4#YGD!kMj8& z=2m4h;paA!d6}s8B7k(t!s)H#;oZ?f4`0mnKYGZW5tr9E!J3QpcXmE_7SP)?J#w1# zMl<{_Gd8J!w4_g)tO31UJN#f{-`FYd%+BHAFy zWh-ZMVcX`4>YVi82}nX7PoAi1YF(4Bbj)|8p!#27LKIShvj>q_hZ+zxu*Cfiz(F`3 zcLBRE%(R3xUk?#2NKV02ti95&@6XKA)xZ=b0(V$^>;6pxTO)Cg;j@QP#% zm$2*|au>C|rFgloQ_GWnX0jj-{=_~)wa#dyf?tOe6#goXKAO9rp)7ybUwVS|kuieF zdKS4Yp>9f8iBp^v{H}2ubHMr-56rK6f~L-T=5sx?!BGV)`oyhns@(k5hR*Eh!ONH$ z1ix$wdyDBJ)X$ILs&dp@uO1lSWlX%%+uXJp&b#_Noqu4tEGSg7^Skyc_J z~5&6_Elq{UOCXg=wrAtG-iLk^0Hp%*g>05k*`+D^;U&pH}hoDeXf^wZx zEDt-05X#%_DauT(-VKsyy@*fa*EoG(s+@p@hxF6K^zz4F4iNaVeOGff>9AZFNYcLZ zlpfMLMIBFa_-T^S%*{F6M2Z`_qV9?>t~OHq1T|WdpZk$*DQQy;T`;T<9eByurvUMG zrYZ=HK}>pOKg}^0pT7CsLH%O}RXWl_$ue+9scqeORcrVMV%gUnFVH^^Q(eoCiEG>4 znLe^PI(*M{#vbV@J(y>A{-&Xh-uh2qf{Vi_s;jREH3jCMsu!1|awav46`MFTJc@b` zZMptCM#9x^?||BKrMoD9AG3Vr66gF#fpL$v^ml-a>uo!xx1av&$^WI|*?%9;0H6Cx zGw<}2cR&^a`Bq)!YC$9&QrM+ZTfUc9nM3vMgwt$bLtZ(9pi{vz;{Av>Z`zfZTN?+F z*ar*?C3}SjIJ%{NJ`OXJY(h6AX5Ju~BM+Y}FF)I^xk&w+gr{BKn%Sp>o&(&BpC?x? zb#23ujvJMh;?HjfesC%S@+>*p*73+7^h)&_w^UNJg{cGL#DBPNKj*JWa;BptrO7%Y zblDZnFlDEVE^0CTzL33&Rv+ zyaClnEijk($4BNzMDggKk7O8ihtU!6?J2kO6Y-Sqmxm6#Go>gUT^-u)<})>_f0qv7 zbFjW#FHIrsHcq1J1V&!Qf=VdpDvbydYdve9NpGaH$QyivX5^L ziIsM$QdL$HD%4z;Up|s((mwGIn*Nbmu2piZ+0#S63>Q=1A(34B&B}dh*ghVcv?o`7 zsn|u%YM-R&cmi+bXP|X{VU~&C0dVrwB60Ta9U$}!CFZH3i`R%KWFQ-zXbK8dv7uU} z-t0l6>4j)^s)|@9L7wgmL+38+p{?(RjMQ254h#EYO+8;vdeqax61=F4IXSU-Cw$Ub zwA=?@7W@!ktTWPGu_@)EqLsTAbWp#tOZExw0;PSazp7$WxHdvZ@68Gur}LW|3O74ey`P}cM;UGXPK11WJqNvoWr zn8Q(|1!b!GBv)g>(t~Esxk{^#xUcpERWmHUa!elMRz>tqaINK)*%2dqkaE)w&xV<*`cL=8!zPyO7Dk@|(q8unS49;gWc5 zMPVIPjTx7jJA*5SrRxqqgqBX-l9>5-$Uz=g521niSO4e@y3N&eWWwC{gPr#F>K{p~!8H71fidtZH>R%S&p{YjYK;O5* zktAne=$wZ9AhyH0o7OSINr+N9v>!#=0@>m zObkUzWRN{)HsVukLxFY>_1LFb#hWBpMF8@*4J_1GO2vl4Zq;!yp-~LlV+k6Wm|V>4q*w(* z<2~fh{o#VS|xS)$8q|#e(oU|ZM1KIkXkw^%9yK`2zo78(Ta;&vN}ls`t1SxH>R=@7-OYp3OQvF6Ko#J$xF1(Z3CcA(HtE@26Jm zfNU9s@Ol-xEt#;kVA-;Smjr#P5dM0@O5J)itE1zjG+9NocxjYDguEYaPm4 zvZHe{Kg|A(yaV0cI*#(pg}eu|NZoN~c}+6T^A4yP?^v2L--wFZE}`# ztX;;mwA#J7@C=;Xc;;zcHr^52x*mLMA{w=I$;86Kj#BT zTajOU93GnccDnH_z2E>_d17qY1gUn%D)>40ZG<*`kS~8vecdayDfkX<;j%VG;!D~RjIMEux85m`Z@;lU ziioK^ps97dm#U6wrad7VwShpc*@p5fnt;aSuf(7y8piOZfV;@(TkZQW+GZ;ASp(SI zx64s--R~v&CU^hP9ARi2TJ9!pgf7L^EEkJHj{kqK^_Nj`HBHzsO7P$W4H_W0>)-^} z8Qk3mcP9|s2X}|y?jC}>ySuwf2sv{<@3-D_&RX9e*lSkz?(W*v)!kKBT@4kL4ee4g zhO^owjTKmeS?iI;pV#{`7QEf9F9+=~^8v zqZ>a2Z*3JZlboBvC~>MlXoyY3gdC$~Y}Nlf`Ejc`8_#^d_0uhpagl4z2@gMQ|4Hs2 zy-E*?%B6HHuM&Z@Eu&;;G&cHmv&*R-k#dTGhs|(=nl@iYr##^w%*^hm+qi?nwxw4J zfy9q@(sv3TyxacA9j76_yart$B9P;7Hmh0I%2oPDG8(K)Gu%tZ>zEC8elKSU*K2NCh`wH6)9r43XCZc}6n?45?lt`B)@$gD_w5-tgA$WOlx_?Z%gM8%h->}kZ3Ov$$?u}iHFu97tM|=UYs@w>$?bi^cs{8;&ZH%w=^n6tD)#^50QkThRHVsu( zBP7*&G3#kpIbxSU=l2pFzS2dP1jS(c6PM(g!3wQd57pKI+ON*sW3%J_U$x%La$k)7 z5BwJsTtF$7^1M=)3LaCGi6x}7=hjUTRP8Bz!YGR_XHtdG%J(hQ{+i3ezFz-et_7hM zh{gXI`Y#G<2?i#i7*%#`C`R=IECMV7Jd{87KiDoT%m+Al1Vn7CPZaE2IGj`*qDD@X zUzG!J@xO@W{r(>|6-qQK0^PR^>7sUxVeSuijBD5WxY@invt&L@Nq-;txkc z)(jFKWIVr&YwOEpafzUig8L3BDhJOlMo|@$@b*QYBK`w@!EKyUyn- z)tEv{j9HaVGn$0}CQNi}UcIeb2~@?)7$yiN1svC0xh*JMjE@TfW&NZ!@HwWNFEO&S zb1nav!gKo%J$!7h&s3U^c_b^(fpSpp+d~@Cwo?d_bRRh299b;1PKc~`eJF>}o-nNZ zG&G!(VJTr)DnQy^fav7cAoF1P2Ac7ikiYD1*GHHK*^*H;Ah8VlElCXLtgvC0Dos>u z-h?C}PN#SLtQ%~V=nLH2M{|6YpCQ9vt5qTMzCTC%S>a=e|Kew|^L(K>Z(_XAPye<( z3lK58Q!OMGky0$P;k>t0uM+hZHa;EW`({1S>h2bpm@jwX4<2E|hUsd6$4kq=moZ7@HX#(aP zhXbov*Tv$;uz=6x<0l1x^D&@HL|P&HY7D_z5%lS+**@s9mbIxzyBqC&xz9M% z_@Vf`q(v_F#P#!Qr~=dIR;^+18PZPVJVIBCJ(0t(Tj`qtk;B0IV)4@erkmz6d2iP~ z`GM6GwzcMFpW~dvAHxf4%je$4p-vmsKVk*pMLZuaPa$MoN{7PLMH90jFS_OViGe!; zQe&!bfpx-KOsSE+Y<@h^MbE!R~tx8oA>$pY{X4z>T+dgC>_?rFnqoci}xE6;Zq zo!otdh}#~sH`Se>I|Pe2&Oau>G0aBp?|5(U?+r=%+KT}EdE%wa_WvV)jn%ZuqYOQ+ zIlrC7!W&Pknbm^%&2Raa6@Mseninx|8~^ytq!dJV4_jKOv8!tHY&4tOkGnFKq3_eu z>gfNXXrG_BmRv-!h+K1c&_>BU=)K9GTU>v1lOjCj)FeAoZ8;{;@@K=B9uOv^+1&o0 z08BYQsr(fh@ULGyI6u9#kXHdrYYYDjSxZfxuV!%=TT!3K)(kc^KCgH0UEjb|x+BvvIO);)739lAtmaXG1&xPznF;<%fI*sN`aWj)kY#A29X1pX zYh3&ndTyg|2xiz=u_Nb-?ZZoo3>UuWXdgZ-Xv3ssRh!)XQ(siZC!ON1!Of*0^0B>~ zFE!FR#lE95$Aq}{_M)NEEv`yH#$S@9FjUFW=`!2o5<#|0+}uG)(gZd(wZs1ox;#NG z7VG~k791QLECRy+VZ;89`WhY^i-Qwtu@ESYaB!(a#gyZ|7(4#RtNow7g8e`C3NqL# zFf?&a!2Op`&D~$}gk&A2ba>a%Ps-frRw+H~ZoUNCRnHHc<_*E5w(Uiiy&+4?y9)~<|#xbCpFP|wS84LM7LQd_~x22HP07-9q^(QGR zzk2?`v?l<1eaaI*6L08#j%5Jcca$Mh=dPxtQ5(ldRNMSy>A^5|?c8QE= z@Qy~i@xmkG{h};)j*Zr7nz^txbDr2Ba{iE2`V_%gY%gh+N;xg?cmiOa9ykpWq68Hl+Oy_9WHo+t~4iiRvCfnDr1N~;9W>L>lyiK2;$ zO2V-B|6r)K_87Xq%x+<;^GOfVI4FdOJ7o(W2*p;NoBVI&>b#-<>!E>2c&V+VY-edR zf=9eERX)(TE(8Z{>YI_Vcj$DfJ;R!Jq0-p>R+9Zt2xoN8?SG^9j0}piatJTaD%`_a z{Pgs;v@F8FP!;X(_Q*2n90oa+1NlVN=S2^0CKiP&bS2>_fF@lt^5ZwO)pyv@sCI}j zgl-G0Y#i0@-wWFV49ywLk^Bk@BkH2jnV={DQS})CzF8eUK5KKh*QAB^G@=CrONsNc zG=s^wOvwqp$rLIMz)!l9HVDSljiX3nZ`kXg$RrhXuRR5w4ieBL6F4a6JUsG$X(sf0gRl!++UTCv0cA?fny3 zG`OuuEn2=9CAeT;Gx{3R?}0FQ=T0qJ{78J_M3)&zKss6}SY7(7B`W5=dYcYcd7b)` zLs8#Bs%!O$SXJv~&h#ZJWJh8PIODW2%yObX8#3g0g_(lq9wk{YW99S@hSCFJ$njET z&$D%FyFq`UV0JgwOjvUlpjJ)%qiV?2Jlc-)o`>|y z2d8t!b{2q12Xg0^NTIkFL-JW{sn>M}0Ol?1-m=CyAPVv<`o9XfGOZim8d^8)N%PkU zNMGS$sc}48FHO3MtLfH#KHPR=$~Wk&6R`*sHUfeH_4>1o>h3K@_S>x+!5d=r3?%{; zPOXn{2j4YX&NATh!X*sLtG7k1E52)#&ZunvC|}SxA6>j)8LwnoM@Feqw=Y%W-%3{_ z`qHG{np`fBUZw8sTRXg!uC9NusSZ%W+f<`@g+509wVyqoyb!x$ zx!vuiu3E_~MY&>Og#KaBbpBC&+pG8wrXr)Kj0@;HzU{$&*NI(f5b{S2ZVX#$<&V(v z&JyO-2cxEU0?L@0M=K0kj_KOb-nqRl8DpRK(PA`Vo5;~!{*W_cAHOZW@*}<*Qc*g2 zoIdkn=`{8D*21U3!&TdS@&)AlXzs$^+mS+>z)u6uihLNke9g6jkizn1UADTvq!ZrK z=jXhN_1F-NlvbKSp@M>tLeUPqG?FvbcWGj#tCEDh23cr?ON`FXI@}Vv2GtL)b32ao zC4}DyC6DZIo@|(xXmqfwOB2gyDP_!^eLePK;6j8%Lcnx&*Ib%u>Ugfwx#OcBRGI_P zsCEql@tCpNMTEA`1SiQ+Z0uZZvq?g@4qA^~Kh6mCS$-bP?k*Z#-1YEqyGZT4yc(}V zLoYiF3Lj$S(9o2{jhRfxJFZ4Oa+LmR#x3%U z=?30p%RIEkwwa} z`+rXZtef$*NwMrf5;@!w!sWBxPrKY>aoiJ_PI|Ps4-Pd;RqqgKV*C+T%#<^SbojPY632QslazPL^U^eZC+1YMJR5S$ z&>+V+V`2*KDL$Xe@pe~?i`AOIG+J5T(x&mZTjGig#GNSOoqTDUA~hjht;){giC)Z{ z8SIJUcD5m;Lp=W@#CZFYJ+PV&rmlm}FkMK1?sf5SfY|zoruByffA*sBY+E%!s~2AX zlfd}ZXa3el?i`IKzIX*>51`m(>cB{!H}90A#Xe!rH$>gVAN*I+aMGTKQM#AYlutx$ zgC#DglwQIzc2p~X0lxg@O*i+e0%E%Mc!$*1&Eu^|Ix{B0<5o)+GR8%* zq3?5rW}uj(jLO@#dmw~o*U2Cr3^RUp()DzXXfU(s%A-}+Y9^~kQKiN??Zu=re3bjC zu8%6i7v>DzPK`3y5IwBC=+8@V31mmPUz% z$(B~Z-=A5$00-wGO3&vVHCRJuSr4)Fn&*T-ZLJG1VbXe9SZxRkuOi8@Rwc;0NZ@0s zCB`;{Czbd1V{^os_LPC{dDyDc`Pce8tLpQ544?|{ozte7y*n=wwN9Xyo3)$Pk@S@w zT1i_PN|28!PUy^OiT+Hqcd><1?aBnn&8y)_O0)TSVipRwb{KeZL=LHBqO#PU9}0b7<~BSx(tPRv!6!GR6X*dDPd(^93ZU70^N^2nOch3 zIB~9zW8BUuQo5GlM}&6t$7G*TXoqV1=foF`vh3P%|A^PK&@CVO6JB2a;=DkiB|(_J zb=>#|vu{TgrLmO2HuQ`pQgzupy#8Z*%Pxmgqrp%l8PY81*g(;x(v0@T8zcA>6q=97 z`+8{RQJQU65BvQP(o;#)IwOXWU+BE>V%c~<3#1x$F!m7-Ki9(vP4~E{Nm~NhOz&KiiH*)}k z?L(MXv+Z2eu0+Lnzj!-iY-a~GVl-wj83Dd5p^KuLorcu4i~V!rYNF5+pj5RvX-_Dq zvfi>``ZAO2cOYMWLnF6iD>-F@o@4Fb#GirqbwfG`4J#&t!o!(`ub`)rp-s~F(a|BW z!H*mhg|K^Tzej+#pco=$WRZedC83;OJ)e@@FdD3k~Z?08FQGuHej&xg+iz^P`VZiMhSgrkek9d zRoVhj`S65f{N=jFnCqt*NViz^XJjFDk5!UC$1Zc6XQf)-mn+nt_XS)d=B}!@RVcPG zGrb)RqF3B}5Zo`1Y@iFm{T1SI`#$hfDDj$!k9*8hJA(F4bg?nZG@*svqMglg?PTDQ z&?pQLi&+}l zNrG#bCefwz1C0jHlQ#<;q2HJQ6;7~Hc|Ci-u zBE&aPKa{Bj5Nt1KJ9e?mVd(2HfM69d4-92*-%-@zqMwnY+wn~)i8K+U6Se3yKQfR( z6%Qx@_L-$}OaPkeB6$?AR=n|w<@mZrFZaL|h2wfeGb*mSUiC?lttB%@X5$$E+Qjq? zoaHQ=&lQ0P{U5_T8SqZr-Q$LAK=L>ip2A?B8Hxm)rG!;)HPhe8G1-G=8*d=HFGM*N z2sun}b$-52Cgh(i=URdEY?n#L7Iq{eu}}@FauXuxrdU{e&e}$bEX(2lF8eF;97KAV zIqrk`k;@V2-^ti*;m`E6#)ydn6pN^rI=7_#@_6j=ogaT;;_8E|6JU+&7TD0j=eRGZ zTAaL`bFqTd*M-(ax+1CQ>+d>xzwT-&jY2E6)9Yeo5O;IB`+hcE;6dC}d_Lp4LD5Iq zB|M~`2#G@48RfPDg^I>2LZq&jXx*6`*k;>{MTwn>cPC9T_}xhm^A_Tv#cWcYz0!_&aCp0Yaqovt?jVXXy!vbi_HOBll?LbDy=&&hpB{ z_v}?{rRbaHxUP@+T#mZB;x__NZ==**u3XBa@^@plXZzY-#D$WtL`P_@f8|_f6Z9?? z)vjfG)jjmlsxYi1uXjytPN&q&;$R*#aE;Rog>B6CG;&ThvBVg5WAcWVjPaNYGNz>o zSb9~bRcnJzfwvo(&nHdBSTTB;xIlEcx-_!vsPo`MuB{9r>-pn#IvuNJZ@xvQmR$It z6zKwA7I^&Z$3`D7Lro&oL(4vO@#Urslz_ilfc&Y2IZs||{D~L2amZZ(RqP6bE?%YW zSYtV>&u=iuM+Ci-YRFp`$N}!Hg64QsR$6NEX5Uu9|2a_MX&d^@#MB`F4~B@M*?yor z);R9LxtHlT?TAHku`p1wLvKry=z`;N_c5Hb{Ub+fYPMzW`l zR?-Dx%$h8Sba(YS&(EJ$`6C(Xp(>2B`48rMdI<1vT%etg13aO#)72Cf>Ul4u9BK6x zp-rj7hbol4OpK8D8~2UM-0FyS<~925&&D;nW%+WL!!G?C_C3isILES}y&lyBO#6IE z)Sc)+aT~u6RDI&E2u{4YoNsQ_b$t;l=zCvp5r1Sc)wUo}%Gu@2FaG$8uAzy~YbM6Q zr9p7)?ar$YMUL%s#S1Hu-Nmi2m&L$TSw=~DNoAW8+`@#>ryZh0 z4+&d5r)e4~pCe8;IX8j2>yqV-4Zh}=oIyav;-D1}72>f}KzLTb`8YzCmW4hsCA9338E-92YXiYQ>hY`vt zs~;V#ZB%8EF?sDz-3932JOcj7P5K-Wi8G&<6W^F4T1=BQ_;uTok0)L^2FJko zc3zF$p~%3}J`Dl(4)SuFS%{~A!V}2X1=ZsB|1exLBu8e*v`vQmOWT6OpFKHU%?0Nib z_BOsI|KO8T41i7MUfu?g-sEVf{meCHVuj;To65uUhK|a^y@?@J8r|ox<2)dv zjfXH3)RHQ56Pu_UorUd+Liha$8gTNVJlQ`Aqt+j+^^uAsEIU7PO$d@!{c3O_Th;6B zB%f{X(~iIe;ocQ^(Ik*qA^UCNXSTVke}?JG~M{C4Q0royA5PdJ^~kG3e}VUn2=f(lG~U36j#UR-6y^n^E4Lu}eU zAE;;VeSh3nb>%CTLGsk}oA!gvK6-OHULB&n-*6#eKvw$qF@QM&X5G!J6Dt3)%SySvUG7j>~pXoZk7b#OG>c#t!{ zAgc9R$PZvx4 z&<;%z`Xi!4x;;~-T%Y8G2jH9Zs4PKMPVq?a@-#$04=ABQ8$9Q3yE}j$Ohtgt z)^*)dG-kRVUq?FvfMF{k=*g=D)-i=-a~m~ZpKq=kq!?w-eCMYf*i;v47lyeDemJ)d zKN*AP3lSh<6eL3eU0)!8%)R=ibr9c+LqA0vHt@xar7xuHigWmx2vqzeYO$AQv)$dV zaD)*)QfJ$A8f5S{DI2Afn>59n-Zt9BEWS6#aIn`$i#e)9jj~~oh!tOEOA{x1#*Rc5 zAcGh^=0ePA)6s+U`^Lan7A;6A8)pESaWi6wr$&ae0iCg&LwX&Y*G?Rnqe!HW8`cg) zL2Tg;`vw3nCir4C>uO22E=UGssgmhqXPD*!he>ag;eC^CaV}KdVO`rT-?-GzJk9+v zLsLOW9lyo|O#!&WRAk_sh=UdGFjTSeVoCZ{$;tL$e=9A0oya)83VGxrdfi-#nX2*> z@oYVhj3>aNYr#*tW~A}+8X(0 zq}jOpv04V{q(B`QRG{RpYPgW}%-k>?dYh}0qF>P1ED=f(eyNi8{8ITSWo`tb$% zxEr?099?RTA2v{AvKWtU1E)Ze=xO|&2v;A(%-I{OsbsrgL!K7F(LWh zl4(r|t=4#?*gpJ?ED?JvRFTI8Pmn#Pi-nOA6H;b@0kdqX37F4?xn)*6#L=&T!Lja# z+JrtEmqP&qzcfL9)cghbQ9d^Mgh5(#2vfGe{>MXXc%|nn?egzAy$&rm{qCVY2t44a zwBzWVLB3ADk{(*G(9mPXtKd~vHOkV9FNE#EN7|MH(|r7&GedUY&@Grti|%&Ld|k$Q zb-Kx-o=V>j{9Z8MlE1TX?jK0;&60mz(POJ6g2~73B;twEt(_v)D<4;Wp{KFSpJ1|+ zj(LdXA-hxZwI^(A;{WK%_`faXdPwz|x_rZS;wExC&qexmH4on}lV{53IPi%R#9ed1 zKdjOGhE^bC+f{;8?Dr)IAiQMe@p&P9h|AtIOn-PM#iCj2pubBm#v{IUHE$;g?M>M% zhM6i}OvXTGJJ|iX;s!y<6vJb=qod%1VU_&DzW9? z*}y%m-2MksjHgJ=c$VntaSLC)*Dbl>aommm52k>{MTS*y{yA-DUzJy^NJ&CJAp*$;+>;r}m}V3IDT1VWl&EH@OKz zXqnQtA0H#Q-F7{jP$A=|&y-_=CSSbnB(J!gmg*l=ySm+y>&~8r-UIxEG_d(lmvqQ3 z#vO+b$q_`Yoo%Wx`*qt$E*?Q(p*bTDwrPS z-a{8d{Xxvw{H#$4oFYb7pKt@mp4CTBgTx^8sJY>%4t;{m{xR6!1OCB`sum}ZA)dLI z#SCFK&VLR4=8J8GylRWKcQ_sGTwB){-&IMvc(_lt)hsVNf7LCFCE!shj z0$sp0HnJ;Y*0lpqss!v`_+vnHaJQ?&X=~-!HAxpRH)`MmGn_QVib=z;PRGPw0%F34 z0dvc@RP>nKTg5OqttAxV{$?*!k}~G(*qi>=Z8wc&>4sn0Rzr|CRxs570e2?nb)mef zqw|i+w>_0P`92*6Ia{wirYhX{VLIq01}`h!;EH{j4{|w5Tio zR@yv<@mnUtyC54e6A99$K-;3anPMoQ*U0I+@p3O#>yFRv@G6`m|q4Cf;MQyGX)0-@tk)eA$#Yd)e zg&a@Ud4J6$ujD!x+F_@yC$-{7HA)ayBR4 z7Cj37A3`M$sMBs0^|#_QjciVQSkq6QGdzSur%M@TS6~jI)~wxZQiF5B-y>G6Z)y#k z?Yp&E1rDBhOXnsI{ZZO=$=xVPs|pB8gC3iy!sme&J&H; z>Yax+MN3Ps+ZmHDTwG4Pr_FkHWqDtztbcr9l(gmxfm*pRG6w~-EK(xqWqIagToip= z&(ba$m)@@9{kP!NTdB$0-NRENE*+@L0k0*r)mKgb>kgy!jHYz%3bA+yDeWUDrfr88 z7K5SZ|`{69fs+)tl?CPs1!AbC>m z1HGEC)u#2>i?#o_$CJ{OUQmP5D)O$qokD%niu5KK9mR{aV(A9b{LkBsfSU{wBgSun z%N4`PUxZ*Ist*1qg?}*1&^r+izcct(mUz(#&KqjIpY#(sQf>h=a#dKoSZLE#yh^+b zrt%dZGXMW;rr%dcFFC%hSCQ*jW{G$2C zSRNoC%@@D=iNdDmqOM3%t>DixEMe_K*N-hI;#kukstIzQdRBV9=EY-~8Fab}9J*!# zyvx=)m*A$j-mmWBVM2p;=!9>-PO1Yo>(XO!w`79*h=H<#b89*zyjnP&P^IF!;x>P4 z5;+w3vq3zb>_RM^izisa%{wuDw=+(gDJW&Zw=kCA)Z9PR^%g!ON}3*xZrP5Tqj{0n z&~`4kbXol|aZQh{MUX-k&+{jtSjzB|lSY+6s;T{KK}ggbv$&<`w*l%@d=kBR6U(|a zAib+62xNh~WBFrz^dQ8x3Oj9+kF*Efb0sm*H$^LY+^bqIv83^xs?8Nx-!l~Sr*unD z3ZH99*xHhmXzcJu)(eGAJ(^S!GcacZ1CevZgNqVEn8`RrkzqMq@;WiQLUzfpP%(RM zx2mR8=WSkUdrU|8vwpWPDkECqQNXGQ%gzNcn4Y#?y4g0gktAhx&fM4b^gp8mew`D% zgnohARVtg-2s|-|mFqA-ChYg(`E^XnfO2Hf-Dsjq9P{8|#EK_rn)X=%D0EjvJ78Z4%6&`_2W$`sN8XmrS_~{o~Cj9_AdP{ow1?rr+f{=L19A z1_dKDtdZdp0u|G)>!o6h@;u`tFE#3BsRS|jvo7Dbz|&M{wK8|tGs3fjDM7=sW2 zTD|uA+`{o5rS+dtDkcSsDFuMBC5iM3W8?_8FI~1(48%wfvYmmXTDq@UQ!it9J;N_R zV)5mBVY%5=Md@j>)Cx_NApZDkYgj$s=E}A^0m3`O=ma<1VzFWKxu%?{8(eWkCbz^XNV{1zTJI`?1M{25}LfzxqO4>5f;|a@Rh=b(IJf{H~d++ z_=OU&uI~v7hUnOK5G1x7hy9QO6@znix)sR`qjRomO>d?;!7Pb+3PA-IozG$1B$IgP z+=}(}Q;d2$av8os1A1tuS#J*gur?UMC2~t5Sa=;a5f43TR7PctOT#wXU3w6t0i(oo z5Ah>+>={Ry*XME(_TfrrzJ+U0OmZGDW)-h7X0j&Itj6UAD{E$WgX!TC%v#E;yWk}A zT5u+C29o5Vowv;3sGF*Z*_Cd4xYmCmC`*dv4*eGF6q(TF8~O`%UdCp(bvTBj9%=WO zWk8SVw87^z+G#OIAdQO5+31ow%3Nv<{ypy68NUd{u@W?gVtAEhL~Y=xxM)PXXZ-#?=}<07UJm!_0oyk6_#;J`MR`` zMAKEJE;lL{l_3k|D+4;l)mD}KpRyTAUSs1-GPr2Hdl&CN=0Hyaz^#iivS4K*O_d)h z3JUxSj-$Oh#Xdp!0f@4oDK>rt z5%Ou;bJi@TghL-mHP{fc|Cz^5a4weT5T}SrSl%3`b}nNX%C>r#O@~)tKbys`ayXZ0 z9bp?1)MFAqFyttZzQ8MWI~X)VcrXqD%Z-<3MvC3+=I}>tzS}@6Kj*FNS734k*haIE z(RtDS)#O*<+;3JEK0IM-EUbMXw(DQ0qXoaQp!MInvrPU(67U zi<3@#&E19nnc5`~soaIi53!|ysc~5Fqp~c{D$u1s1h_RGHk*E!dvJ^P7XX+LIq7)8 zc^WlAeNnyx0o!t9H?69GmTF%~9y-orv&ZkG-SXTNZ`DBbKWPo$GW$jZCUE<=xD^rf z6O&P#0kL1N1WL11Wk9X8FB?xFVLCm*#2@o*8q(AET772;vEBjPC5g(6A0M4T#~y^z zUwx+)@1RB3x43+(|I{2P+<|UikRIE9S#4_iGdO8wG?JJ1OX-I2Ts2Js+kVMzf`>B| zEv~oVol!+!i%q0nvjS&-*#yJXa>{3AK$CaIIt3FuFRjTuRJo(Av9&S_ru`~#LS?*Y zy*Bsf?LV%NYD8UT`6{*2w%&?Xa!Cj-a5@KA_LmdkBa&RwmSc9{#6T~~t}j$aa{ZDW zzW~m_3IDI1U6Q5MtM)%Mg}0a&j#}!n&sFmPCH;)5 zdG&7Yl)oAtN(_~Yave$P9gL-AZh+(RdUZ9xVR;!ek!I2GKQKBL6m9zf3Py)!&p=_f zP(1nv7;FkGcF`}&#!m71jsbPoY&}LZH{W)Y{=Y!m4X6t5-PHBE?H}HmA zt-{&1C|IM`xxA|_>oMoOd#QTI%B?MWNUymq=jz8DLSayxs zTR+rVcOY9D%FjpjF<4WVy4(8g6MdtnIoE^2<*Jk zcXov3OvDhzJiV1%M0=~QIkd>REmg0UqJ<@^!Wwz~F8sp=5BZ~rGnz)`#=0SQ;$x5Y zl>2rpE9YlUXWtk=V>#&c$}jD=Mua8==?JMV2mYqz|v1nbzlg ziaty`@Z4{_!`mIVaA&qN6?Q9}0EZp&*B2-pgT-{$<)$S%5_*C+u(`GvftQ6o_k*Yc zXliNa1{eY7wEd9F%ncD%(ayCwkD`qw2g$Yt>Mh-Sc7EciC;+$U8Q9_in3_iSrWjDQ zehTe@<#C5%jIdu#L`gs7)nVr46@9l4xS8q!mBEqP(08S7dDj@IAXj%FnHgn$=_asD7tQ?opO?;Z$0xngJC4 zDg=lpPR-uI*&E{$6oj5@2BB`U;&_VNaY#8HDI^Ng!RWW6W3nNtc+S?)v?UADD^r1O z^}xl{!#p`$#Z`?16q#(M3O5wLKY9|TEMI-9aw&(uB6VWj5mL=#-o@4VApj`+X}-S& z$Jnn_E^UC39@Tl1r(*QeCa2eP8u!r;dQF|}H|xs}n#zBqxY73{jbSdc&gaO2?}{BJ zgFp0Z#tWV(Co~nR3zn*C$Lmx_4NKex+=i)i!K}zOw6aWXdTw6ptcuv*-xkm&AtmuA zpGGc-oza=w5wy7Wk8tYec^RbXsy0W6U$K|4H!+?$hsm0v zp_SXR#pDNZpO9$%bRsg$!_DWdJZn>iYsX4K9|V4@nKaXdbcn} zBR2L8#Yc2RC>a=<-9L7FPP?E$Oy#-8>eZY+@tUL(8ajUHpg8nx(_gRer7iLq4Ew1$ z#rE4Y1bZ1Y;-n`2L0v#_h`h|gU=5z->$2LU^S$8%Yr-1x5-E)+v7IUJ>tyfPr&ikq z2!akLf|G#Z5zp-PWC-{Qwgcs1=;W_IHVG=9I}N=9WgZL^DS~TzydGr|Bt)fD-~Unk zXEV0x4r#y|` z-HUj>|C3~yUm91AH9zgg8hnXl64Z;P#&da+u8%g9Jn<=ht2z)8mGkxu!F3+X$P{NP zgj>wkm}fm%!`+j-CmPpiz&%*d2(hwDA9B1fRZ4C6An8UDx%EwthC)c6CQ62{Lrw|K zDET8ixt3*BhHdNz+*oqC)F0P&B<$c0|+4sIGl) zmvvWdGGc*MohHSlbM^|tZOXXvm($wy4K;p&W+7*{YvgT0DECa>j#sk3i4Q)$fx-Q( zU;n{;J^9?-iG9LYA#3RAR>w+HF%HPo7Tp!8ZBq}!6lL7>`Qx6Z!4@WUzigcgDXLsl z4eDI~o#)||9`j*i9xqSJ3f01y@dRZDTk5@W8LW(#N*EMmSEeqB z(;5>2+e~lJ`*o}FXBF;2otE+YfSl`GHn96|aFx>TP_kkxF1eNZC!>A&diP&`NeQQE zl2`dN6XM6kn(l0F^7=B))+x5~k6|(w5~j}gx#Yh;-a0JB@Xn+^hV+T9-Mancx+naI zQn(ZA{txCyivO_+oYHbOO^F~z{M}v{h&Ebku%4DHoV54a3TQkOrNQ%bb(bU~g zBnji*U8KeN#WY$7fHy^8f;Au>uMN5b_+1&_~U-+xm^Cc$-xxy(c! zl`UR#IzruB3+xp2nO(113XRyW7T(#w80zQ`jk6su5hn--L!WE%(P|VgS@br~Yr$cH!B`7`HKutdy(c z%tXJx-t!lqqIGy>F_NK-bqJG}gOsjb!6=|hivpER4k?g8exM zuTKF{wUA#Zu>^0#zsaO*7y1C!(u6GPm-9St>)1c2*L=Eql2_HV*=bJOqh;_nh*0zX zBD=Exad0{m=~XjuXnEHX8?R`f@YO;7hmWE~f!4swx)8Q)@`xuyviZ>U{a zE91q}m;aqyuP3YXeP({}5Vj6VV@KEV>vx!&A_=J2+xA<1tt%dw*+>GIimHNHGEIr` zp$_-g4X0Q@18VaJB`$Ng9aKD(@-P`)r5eC1#p3^my|;{tYw6ZT8+T}&;O^28EYP@H zfZ#!b1cDRX-5r9vyE`E`jk`O+f&_ObU+?!jKh7EB-0|Ig_qjjrxG!V<=w5U^Yt~b< zs@AGC>zPy;v7?m%yYX**csv!)gR`0G`dek?D!1nu1NDp;wa4@4Pb>Q03ZL*hZHC zu1d3J^n3N^2OcYp2^vgEM<0l{tDLo4+rLGH+{oUbCBF=vdv8CdkKFm8R&72%NW2GY zXr@3Hhh%@M*Zi0sJx;0Xi?tCU>3WiHJtm6BPzL%=vPf%0){}gVPM?D>)5rVSSgO{( zEyRmG!Eqco*9+Hhve=AGuSta7vH3gBG|=HgO^HS$^A#1ipaX{01vY=9#+mgj%!w}S z1oX}36`NT)LO(8~EbiTBvI1@!IOn80dN-=z^1xUfk6YyInI@w%6>yv=hQpeaRCvRf zsOC?1@O|pW7t#V?L>mo%gOHS1#M&PKGFV+JRZ4!|(nTtRzSZdPQahjnX;IqEV%NE<7}b5!S%o$_^6T75i;S)Q${yOeU?02=F+{G`o}niwU|% zH)UN5${?WneNLCAo_%zK~AYad}V$dA~3J@~pd zK9XGcJgINlo{c||^< z{KpAqvbx|hDO84a+s@tLz$Hd8BkBSd40?-##^F|16H}A=JGWB)?v+8|aqY_fz-$Lm z=zG$_(e2JG%cRntj!cR;9w#m(>Ge|n*RBFtke}tg2|5Y zo+$QpTZSlQ(?0;zXQ-66e!Fibv0Wa9{{`9`d&Z>su~jXRElv}r3#6jpBzE#TI~tjL z1U}r^;yl>mb%>4F+tm;uJ?fi4K^|)o#OoWf^F>g~h{dU^^! zy!lCViP-C=ck+vH@%_Dvc?y}fS#iEw*14;$52h$7mhHW%1Nt7u?U5-FZDwTVd~=q)I! z8d~?aiJ-*iA|qCb%A+Z`3HGFXz-dhE6cf;$VHWhkp?L0lX^;c&Sb%pV)WH&Ap5o(8o%w zuu1=T*hl=aruF0*o;G6lZR!~lStK3*s+82kQ2)&l9U_(?vuU%c6Ff%1=i2!-?|fWz z^AUBHz?34o<^bd<-UTC=<^T^4@I!RbQ*+Ez>d4d2?Mcz_Pwo&t!~FSZL7bPwRz|eu zh)&c!y{w|1 z8B^MYF7WVu2!1xEkTF_E`oM@!Yj%@kw*hHK zjWCXYxv}?1=!5)JTOdi{lSF7ZnwqVfz!yHjkmNG`6ft&*@9{|+QTmv&Qny&{BeqAy zC<>}4;Dpg!2NMQ^S&Jh;h=-ZpE9PPwhfaYiEVn|&h17>x?>1WVDEts}x_d0Z_DQHs ztZii9KX$Cd@5;-SAs&a)q1PF>}Dvl(Eyp4QQnzXpt%oj@0o#{@TDk`DL_ zQ6|H#CSOW@zxO9Thk@t)_}%Djixmz@vqu$%cuJ#4WuND5proF158|+_WC82GLq1-d`DGsr-JF zx=3Qed+U0C0ETB6Gzat^lO&CMLdGKwsh_Ga#|SY{Y70`nze@yzZu|fsX_g*Ge(v7- z^sB5lEv^(~v=bj;I5_V@(+1r@cE3}zaHf}Jl#^cbO7>Fpd58~vi3MDo$!tY$+s(^< za2?y?3xB$JMsTsgDs+kU9VWo-HZy^#EWyQaGFjnhANP^jSJAK}y!|~nlo2b-6fL@K z4-2&64@xTYU6*;cA%M_+zay=JGZk7AX0<1EHCBUj?aUk(JxU1FGaZP$4Itvx3fHxF zfZ)5&t8<4AdP9SWczuKY@YQWr_=Ib&RP?roYGgx^E^QB;w?*Cogc`?m-0YUHb4B~I&- z6;7eFXp1m1hEa$I2ZQmZF~oo^1kxcl9)D^&v`pR7B=wT<#5pCS`R$bfn6vV_P2Dm7 zTd?ZD7RGl_m)N@wqZrM5+3CEQfZ)?o2oK{5L$bq=X(3-z0M)oZuanv#svv1g8wxN^F1CT27|>1 z?gXmH?(3wrus03JX=1+Y5k`Qf75C~7+K2#*a@2&SONcTPNq_4kAMT!85(BPnCa3kK27r$a)b{>O`v#Q-C|-ifdG2G-Oi2Wo$4&t^Av*w$*|y`lIab z8_^6mq+ubWIS%u?+0_A*g); zo^38zaA){zkSC?ra|vB?1jkt~!9Re{!Y~2%xhdO`3%Kg%B+TFSgshgNb8%`0nO;t|q}ep~?qt@pQW-(k4ZSbx7>g)mf=G)%S6*llYO4mAJ( zgFt|;*vlWl?>4fQ*kL3y26?+=Uq9*jFKzGaQgw8Sg=f}xp?48)43Hh~a!khHTf1e( z@c5PYn2dYTv*<5y#(e!>PyYb+2@qVS&ak@nWp(pOfYu zLy3P!hBA@6V;Qn)hp&GdYFP2=+(s?Y#l)L`E%ygN!u}JPh#|M;iW!N_-{A*tkKb{! z48*eD%sUZv8#_2Dkvp=@h<$!6^HDUV*p(Iua()}@n(=+Q#s0h--r7XLzrb)DVs7gu zgBvtrsik3hJI1QQ>k{%xm3Le$7q8LvSzxgypOaZ$E+t7d)|Q?aQ39(ZbqcmraxT0W zHCMa(yj`BC5qRJc7sJ3>{PlQP=L9y$TK7U3>=MAh;j2o?X4LM~v=D^3Z{EKJeV&4R ztX&UR;y+-#qb|NE#5X~x%>6Jo!MSk4xtZu&mxr*rHp*p>pr8~`nW<;Gd|3D9&`#W* zF>#LBIG9;4LRuhBZ4qk|&9?$N$q=U{uS%G)z>c)hYmQ{LQR5`=!KmLZg-nwUDd5&m zmkKJb4fQM?G{Q$fJJsQ5l+)%#->p`B!lmf+m)INfAMGLsNuwTNGowR5OOB@Li#&Gs zD@*Sub!k>h^2k#MxNoSok}Jr|1`DyDA4QpK8rgW4JMA%LM@3oa@XW3zH)5ZZo}UXX zGn%A4NK`doCuun+_A7-?*D{gjwg+_J0!4wpI=B6MPqzmC1P<-s~EDniQvp za(}Q6bl~n;+hrHOu86K8t*5sKU)G72|LSG##P|j(V%t@i#@ww5{$XYtfB|bXJy5DO zJepCaGPFC~9C8ShDL`d!V4Ew+)aox(zmqqaKtgM&6(rrhm$pE%= z4nR4XdFLtyjV>~YKwTr&I{gqMsLMf%sx6VHBv@4bF9aXLnU zZJ?hvN71}{{6(=CS+cnZV0mmAJHbFHJszS{t@dOyHPzk zv~DsSyVx1a2CHqdfM2YwGsgHc%f?_$9J8kYw%>zB&%N{!!MqiCoM$oaM zDMyZSg(;S#AsBrHMJ&o+!wI%pfh4UAKkK%kyF*trF9mqk58QDnv6F}yY-#LP)D1${ zngxxTz0>mn9~*HxGug&q<5%$y;_MuTjcewN8k?&^ni&b|+i#4po@RbZhosP~&@J7P zxmYA1e?IXDSfO`XPZ}%8{YV_D-?>K6@TAfjlww~ZYMyBrv~D|{pW+PXq6)J|g_BhM zA0;(5`V4SZ@1)ZfG~~RV^uuMK;RQ|TaWvfz#{>8f%21{6rEL$!G4_ z{s0zB4&4^IY&O1r-hfQt@gcrxHGabsnr5t#DJG9vH;&A8OZi@--tA;saTu@+A`^Vu zC&`FwfKS0(uOII24Ri9{-|ER1#ScbnGWDI3R8~t&9h**2XMB)dE#!rRc>a(v#fl!3 zL(EjkD{io|zD<`bgf6~&+DCmFp$4i%&@`sog7je`g&q+0E6-mDf4UMzq!K#+iA_Uh z8t@4T_DlQZgYkuAUm9e5W8qDEuidzlPgmtb&fH6=H}a6F-Foavt_UYG16DB&!Dp7W z*_p!d)Ek9e-4t885!eR>h=6l)r=uEe`#yZnvp8#_9l37Crk}LoomrQ;ah&Dh4poxb zMOJ$9Ix5vCPUbtl9cfDIm(*A{gC2sGVj_0`DzNUyV`tIraOzmA2a{S1WjFbEJQoNy zp;xTJh03yw;Vs{>r$@11%M3T=fZ>+OD8Zqx9TY%X!_h^FGLH_%nhwR#XpEuB65k@lrOY^qXXmDn)Naa-%mmeOJmw z=Y;9Shfr3f-0~X}vr~9K%!;Oa` z@C9-ffN&~uG1Ey$KQy74aK%)Bk@EH~e2HvWSmHv&^{4X8!3-RfjzaoYKqDy zw~2j$oA>5^w@GzN+1pwX-L^O(t802MB0%hb?)@Or%5~wlD~8g}UzIoLs*f2Rg=sEI zPCX~rT)*_b!2JP4q$L_Ejtm4{1S zkJ{L3A$L^N4(pW}R9fc@BQst4KkrHKMVbj3Gi(!>JCZlYLL+CAZ(c=EG#;OV^=|{VI$$s}5#+p{rdI zuK9uq&D~GRGZ$6=Dxb9v@!@`%bbpFDzW7Y6YQ7Q|B*6eWC*SS8 z^@3y4ID~osf-xU^BfkD6!161%uAo@_2QY)*XXa;^HfRBtMJ~Vij85UD`e#OY^Vm0(zZNUy~!pHHne(By^myOdTH)0w0 z+JUT}AZb%$69kn!m<_McZJ)DFKaeq421Al<&-*m`3N5;6S2160xlD4g+N?QDt&PJ; z7H9tFbWZb`h~tbG$G-BnXllqa#0?Y8UUgmRXpDPAVzI#KI3hU1*Fk?Yb7-hNYQ=1k zW(8&15KJ#K*Wo0f4sv144a#KO8Wzf}sHn3Cs(m8#;XF#9V+;|RmV^{0-h{`-K&=RR>7$6pm{4`0kb(~XKWQ<3uadvSIgBM(zi z=cGze`8_!OUtXfW{a2oxYf{-mgfWkQN$n=Z(W}J@lm}#B| zTEn|;1pLc^-(LBhMCD{BQ&m~bBG4^ab}u{nJ9BTQ(SN3>C$WQ%1y!_$LCL$tw=>d-3%Coi$i)qD>*~o8^SpPAuFv=uZW*=pF z|C^Vi`x>^9p#D4uV~32KH{-X9i;0@eh_Hg?Hgj}(l>YZNiuLA9vDFCjN4je`8CLsH zDIiI*XhwTk3d&tEqBPVgsZQr=D4d|X2>5oN_86YPoMFdBsGV!3tNH`3Y>c6qz48@3 zAHVJoZK!@aHwMRw@**u!VGXJ#315%!m2d&SM%1_u=XbYYWw)%~%^p@jdnJ2}*OQBz^V(c{>_|EnKuF-V_ zjADsee(T$CrwYJR|2tFW@*W|9r^9w!Mtg*OV`PC3mYh^Nc2hL&S}h>){u+3vE2Gzo zVw6Y7Tg77qjs8n)q5Kr0*soyyx*@Aj4cf(rc)Cmaj!XaluOc_5yty=Kz0GQgqjMR&K%ztPcQvP=45d}K}PqALz%+Oo;9>tXJe?!)L^xUDb_GkQa)(IK-u1Nzg79@t7nX8fQ(1_?XyLKQuerd$NcDc0Ir27lR*-7Gjdx$zoX)o3UN_vW&w>$QYy8w~2sJ%;lJl z?Y|1(D5$?`Fa4>z3Ul3QOlY9f6=ML^w$-XtMBi z+<#9{_2U(1ww!8goL@^GyA`fNRIw5t?YrpHM^NdkLwvPfg#V3U*{L73|A&J#ynFXn};? z=fjT|I4^|~PToaEze*?^Ekxa7&>YpQ8(2qbSG?1&ZF2d{9FE5FtTuEEbW4ayHnfvE z_qavF8#>IatC+hsUebO zqzDi!+(GDb^)*x^%|vj_HTC&;ntj&oG&($Ov;bW|D$*Ut+S^bmw6ICgA}V6Fn1C(TO+%EeAZ5=S zfrN(ZVB9pm{ib8Hpx*jEdFqU*B|Jh|+qGctE?RHEgu3~#-3Cq98&7xT9YN|gHsN8r zmoA0qiAH&Oo6Rel=b?3rg6GZZ&-{%GEd|d}*Q1v9mM;B{N1L;%QRlxtt3=x@K$VC3 z?c8l&T<((Zrevf#2<~QnLDx=S*(spn%jnRUSXclYR97B&H3|Or@oxtH&A|Uh7!d56 z1n>O(f1}UVV@-mkbN;80-|cvJ^i5v;0erfLE_K4PSU)RwaqmpNyCQr2$4oPy*3pgr zayIWK=3@&e4g3SJ@I?OunA7i(O8LjwLYLYda6b{SM)VHwjZru6h${F;=K1m8|8ry% zjgl8MWrCgYl)xEGJqXT^PHV6P_mx0OMnsEn7x;Hw_) z006p?ANP46SoA&r49Y)6&YJ)^^x$1W4Tj*^D}%X)+w&$Ep(JldqyIm*851-+33BX1 zzZxaI!eFEtpyH`vfxF@VMY12Q+8C7lzeo7_Fy77ts^cj4)dcVo8LaAu zw}}P58VA?Og3qJ*KcL`UO>p-HjBNFdwgmha9d^HLR=muX! z69s$*Z^45v(7_Fpq~d>z4Y|zxC}`^wkwBT8WF_utzv`wG4Tjp!4TlMBO;RH`@D3dK zQXFp+6@Ke)A)}NQ$O^-ZL#5vN9Y-kJ*ZHr;fKxJ1-y_N&0$+uIw^PHH?3z6yXB^8=rYg1-L(*CDiD%E7})fG-gL z2J*Qm?KT$tP#+#}6gVT>=okjLgm44L!G4mYszYFEM1YPd_;M6;whx_#16&{YH<0t? z7)4{zVY-3wk=#3&L6;-BGoc{Wfp&)gplU3*E*jLM48DM^R_*6L=Kx<~{SD;HK5#Bl zX2K{sXCJ!5BDzt)j6B$HnA=E_^u7u#_IHr~Pu+?X)W>Q+ z3FaIGHz=c1{w?2_7JLQov}67~ zp27M3+zHBzAH;}^Bmp17h%P5Vm*GV91GKZs=$qsGP&TLokmHB>dxQVB%~R3bMw7sq z0NT1x@a!-$Xq5jlf_5haFeO107|j265*|C8TLK0dC+u(AtP%_z>xlYBNhyQ)9fwId zp*#mNV#_dI_A++M@KY)Ca|MHqP`Ddn{?Za z^M6I8yi!K~+6~@T!0W~O+crbnLSRDqT{{q+cK__u^ zXm9|C@n-Gw^Q){>{L@8TkJL15jxUdhCBmWBip?7MhgqufM;fF*sH2fnr8^ z@pXp&J(T|`ohC z>I%lsQ$*-t3wBHUZ9S@_^d!YZF~Fz=|_ktv0-qzMmj z&zD8X$?=es8v>8B>t13B(+a&*z4}f*&7%4-I;gWe_v=ju&k=>28qb_LE<77fxsf~= zyWp*CAw2NGMS!}-iMCx?<#o~whc^ix zW!+%51#y5H5jdViF)37f6j<^zyJZK~r{{*8wStIjI8?y$knA<5I(9pq6bhAHIF()R zDa+{4A4^7dsFiBV8FUkSOu@<>jo>#?RUNJee@E46ap?4PweW1@(2w;YETW^FSw&?={HsVn>c4& zF5Ao)MeLa)iHLXj8AWy9r+)HXl5CprC-r!Jiu#O@)x1q*JYLRPbT-KK4@@HeDT=>SX3Hae*3Q^gVAV1)eL)CD8PZnQ^fzo%bi4*3o_Vq2fW4Jk)#! z^En9=IRHC@gF4w|54#TLEPWp>ZDNz=MV8$rCdjCsMH}nAymb45$gL) zfB8OC7X}^{fb=id|KGk3gr-ua1gYkU)){^EkBk3L*-4@9|Go*m!KU+8ftg#5YH~7H zW4_0ebXrs0A}6~HSXxX;)S%4G;46XzoGoS%ouK-?jcvt=WxSLE+=)F zQ*G0;HT6-9X2GDU$NX6|s{v`O)?u2FpR1sb3{H+kOD?h0$B+!!Q`^(%3p#|vkS9I$ zArC^bTV-D}#@U(qu?y5`O#o66{xX$QjpIa(q6p-{2`zk5IX6cQJ4vJ=K(=))83Vxc ztvc`vcnN?wV+>#@q zvw0*E;pzENv)IJ}sInBo)z*Cg%;gOmFM968f)hjB+wwtv;1w^WM)mg$3y&LVe1Y&W z2lk+v)AwP+7k{BRB>xr0pQZTl*(vF38c|S75=Oen%E-%?cG*WoU*W}0@~zH$&(4=D zv(ElkS(kbPO07E8dW<{SpLw^bt`hKuKfljVMEg`6AKk`^-S3y)kVTDkY}Ob)%imwDv5$~#;nL($4KrSSsI_?gYYzG)g~+7H0G-)+cCi_DurbF za@J8HkuhUJ&sTrHPB)w>S%~WYH0C7Os~%o)&D+fD8XqE_PRv={*E-d^eLd zq%PAsf^E=oTA2JZWwq89Pi?;1yMbj-M}`7d!_lh zXo=>c{s8Jyt)-|Fc~nyqgfeK|NW2dK;JZ*s1rC#D+0RUEhLzIvExL7=^k5nZCeUZJ zMZg#!k9*eRe;!|M6i^m-YL9ejysMKP*@ zg?1`!*xN=u@J_{+{-FWY#D0M``fmfdM7_%(9B3;lY?=Z5fX_sDFe|EV5L+kbq%TE> zKzUeV8HDTCNtm{rtvitg`&~HbBcQD|P@~ zK7&7m2}}I5#)8nB6d47|#>O&~d{Zq4;pzhu55#EPa;5GtLmifaU^jm#4 z$9Nhb4YjF7dk-htpvd%Vx{6+s zSe>y|QgE>chKAcK2Vx?(aem{fooMZR*l~ND-Eqmr!Qp6erG$>+Gm-OA-kzQ}ptQ)O zBEM}IrIb@i$y7F;2|TBoTivYyZws7Ygj1hiIW6Hf{dHq;F<#W{uW29Oo-r(W zV@%b@znTA}kM;JqjBLSR)tjwCd2rjy@=eLyZxLc*#XB9vEZ4d6$~LDT7o6-@5@V0J zzXyF>r_gd6&e@P=w0Ij|XD@E>rjL4x$G> zv-sX`>Gm%GsN6Xg!hHwMEsN86d)~4Kkl)yT6rbJ zz1{ELK!1dCy}$bV9l>@l<5~AX=M=|POx{aw4<^breb%O`A>qXf_b(VR z=imLNq6P$k^&yMEp%R_cq%2GC!Y8b}T?}Xk{4y64n``bVAr2F(O z0yUW#EFq5U9`PJCbtN41=y-CSH?C{6&p7s3RIHVS5Qhp|s&r2K7#EKBKuMWA zcKGnND{^?iNBzx8fIjnzv%D_D9xD6vVwUh-Ub_d|Uwq0;{Z+Xf{iC}t3pr|~^S2@K zAE0$RK(;`ss&uHFx|$NseDa1r%8u;DII8i1znJk(d?G^{M=9Hx{#T9MP<_=nBG^)L z^lM4_WGg1pUp+{($h{Fm(_AA2g#GWs%$2Keo*Isn%jVFREO_=xvP;o0--j4=rjvUh zP3PDZ$&ERg);oX3JY4$r7c|Dh77y4%grQ{Rm4o<+aK^PZS)AakfIwP>%xsK_6X9X@ z%xS^ti98yME98WXLbL@UA?x7ck-?9@1-1WO#}-0a*?v(u{umzKoNYkZcYn9Ty!}EF z;VG3n4^)oqfHn^pQGzx_d4m*eZKoU~;X&oPDP3s%?wskvUu;c@`&Eadc@1cnpoObn z)_1`HlndB-@^g$1m2IYGIxs}I`c$XG=d^nY3AeqGt@?x$+b^%{T*V2gtB}nE&P6$Q z{ozJQb7A#A^2s)@&f;6)GxCy^bb8=uECrgzw_;PT@U-f}AmT+~CpYSGKgnacN?85O z)BLM_ACQy{MIvXLCxG{9@rL2XAO%1=HxVLeJg9@=z2Tcgo~WtX3tf>-t*XD#Z7E2*iU@Gt&xsMaY6B+@?(OJ z;C=qe>WQ4YvhpieD(vGg%NqblC#<_5?PF-?cN11U2?GeJ%X7FJdab|O(4 zJaoQD9;CN!#U0G(#0;+x7`kc`s?wXuUV|^M5Y3QLvL0yQHxZnNYmgIZ9cE34pyRq< za!9-=r2_tXn%PquZLCQH9jh8$>&%H1oNu~iZHO1#U`tju*k0xWEN$&#S3hE)8va!$87%o1>3v?<|il2 zg*_|#z^|1voIT+McDqf%lnNSwPbb{(a*afMB}m3GV8^8OUuZ#L`Mf0({StKtpet%4 z>s2Wmp5M$Cm>@ecY*Nn3j)Mu7*AH)DmunHbhU2gc#AX18U5#Dt!aMXeyRaW38TSAq zXR1QfD?z!W=trnedZM~>%+P(Jk`_%7>a}k*$DD&oi<^@URHZNP)hGFQnqiwdcn%~G zFRZpIL0lmr?Rqp}h!0tl_rp5d)SuS4&_y-x(!N_|M=i4Q2fI<1h!0FGr+39#!sen@ z!H||2jeb^W*fW=}a%i8^l008CZk6JGs*{gVjkpV&$iFx!2_q}u1Ad%G_g1oHspHbs zDMKWgg%mjVvL*kdVt(QN)Jz}wso|?7WnQ;98ci(t+x8DTJbt3=y?1FdiqF3N?>Q@n zgUmdBzqhHl4d9ALP>YH(!ADy=o#d2oL)B{REb@r8$b$LU&lW0jF*|q>rkgm)l>sjw z%QDyqxz+0&&PyzXOrdn>Iwd)Lp9-GdqdQo@`TcEKp<*zXGd2}ZxVWZS3)xPq$`m;mF{s1I43ud0f^bO}H108nOCk_RUABZVq|LtJEIZlMgGSc7FimAb1i(t*RuG zZy|)aS4wvX{yd-Io50I~4^vz(J7UyN&!FPf<*ls{==EG3P38kn9+oL8Co! zi%!(}kD(J)?IH;W-j>lq84FpeAAobB$``)bBG%K5?c_N!rdS`d?3z{{X@y zki|sh4dP6G1Pnny)@TBb_>mz+#IYB$2D>$W?A;FCw293?N>RfCS!SDNM2}B0N~TQ# zODj9GF6N_l*+C3$b8yKF3v?rice_qA-4ZS|_0WG=o4L6@g?m-pOA$Yip?kKWno2MSCDj(_!=*zk^5sg^-zw~%KrfHB8`&Pt*&Wva}j$W z1(w%df`eK=oD>|t3r00EtbaEcnA7rM^snp(dk;LLqG8!kN`h`HB25?MF~}+XmaqBQ zaa(DvJr2J(@0D>|=xdiBbF2_CFd;kY{%m|Pnvit{Blz;*7-(5z!4-Cg!{c^_V1O#7 zE|!zBY6@?`J&`WUTF!(Bl>#J8ohke^_#e=BYAdzQ}pL zsM`$NvW2>`&!`$b9$ z_Kz{{*A?=?QkCmkwSqU!&0~s8B7@I@?-T4;bn;fb)=}Sp6Sd}}MP{}d!9@L|1-K{ZjT=qShGScr z!>@9c1I|YFSS$m9P2N&1;Wv?C2D`dSn$es;m^Pl`YGkV-Mu$^vqJbxT*y`;czoH|NYWM{YS*RqW;=FpIK9tTI?^v>Bh9f?!d zHuqeLD9Ex#L+v9vajxW9GJsi7s5r}RHi3@8u(gfoyPw^@&cn^jE_xH5k0KkPci#G} zBy$0eA;A*bokytNy)A3)$nq&ImF|RO2|I;Vn4EgL!K{>?drFAl9ICSMO-Poe?uc4O zZk@&^`IU046j(+DfT4X*LwzeVRmjeZ>=I(cGR$!RVnyte=ML#W6X?VK60jMqN8vWd z>|L}K`K%J5$XhPtgNg67IP1)^EkbdaX+O3ip(4nAv7FeCrJ)G#v8eo->K71+@#glL z524RiT2-z=3#tvVDJq@NL7*tj=*3QYZB$zybiws&58T-?U+L)TEXSp2BZGvCP0L?{ z^B}AGt5~F!Z{bOrAg3L+V51t|=9$h!N2v|p-70mnvTWh$!akt%J>T@TS(hfD5wT*030otX*qhZ!B*HJ_E@Ehf05P^+9;X7Q?clqXlvTG3j=Bu&{&wfD z_D8+6;$;%bh*)s7@W%mDPl32v%+Cz0ks(t7sp+|(8noJ%I7Cv>T()S`}IvEhepY%8I4CxBEtL^ z^VHw0eD-TbMDPYZk@(T)3D#|?2ggHzCT&Y~Zc~R5fjV`;fnv6PYb}T;rd4~@AAr5x ztD~m{J}@6{H$-ULdxxH((K(u(=UmTFtELZN%07ab)1zU$toRvUOZ9GsRoJDa`?G3d_m7kR51Fai+{V%ZD!u_C?`kY&AHi zLEXmWDDV{5mGvGH`^E@jePI?k56t(QHUn24uVcsPKKK``+qyvtV_ zg;52#o|)7n=nDF(Yw&r%35TvBCWLr=vvLaaJRYdon!*$@#q*<`7>SoM_bKgK^D<5O zoNjxe0v^UUnXqil<&2TUQao!9r*>_R3XJlBRG@c5H>4+ZiQ3{f9EL7eJJxr_LLqdG zfVhpJtgF0Xg9i3ccRy#=CA$6o#YQPB5;6lR$iz@-uYMR(`a=?nAR@k@fWhTdovbDb z7HS?lkz_STGNRKH>?25QG)h;h59IbDv)}4uiAfrg{;WJ z;N=A~{!>5`Devbk&F?qN+qziI^z%E8U!*Q#R@uCaO`GT?M7*1BB#3{3{Tuf1Wk(+Ot zhGw^kjSE!};{;R|2(-4tKyviI>zrcq0G5q1q$?>7NSmauNEN7{3Vx47&Q!$kGTL;srf=1S~92k*(P8Pm^oE z&3j;&L%RvUehfjti0CdJ2U(&502)fXK^l}k@)H)}m;?)nzO5Gvsp96e&b#DD7C!54 zVsV9I?2IFN3-mg&5{)uh>}qyTOS&o}$$58ZFm|1x?V7tprK zHcIM|w$)IF?%PkWjLtRSPiX@D;9lNM@tX#am~`E+&5K1&j9g)VIV!s1BL318_Xl9f z)$W08TIJd6hgcs<_lP1Ra&Ej{f=!*noz$gZ0m(CDEv=fVj<4@HR_7&eCioS)F(zCuujhFC_f;fZ0CBvSa z{e_WKlwVEjB$djrgg}o(NJi%ke_M?zycU6y3F4P*|Es%g7@QHlpja7MHl0vlC&|ww z&o$=AkJO)|E%gN98^7vRgsW-Co~3TYuV)lAd$WEe4E2Cuut-cDqNs+ggI@QbQS^wV ze&I#LhQX24om3?KA~cPtW$s(~iBOAX6+nPIRZ+z=<;J>b$1-?nT-SQURXh7-X^L#JRVx*D zW9SN>C>s#yV~g+=;C(3I+js+0n?kWw&y@y>dutCO%atGo-`do)ro!5M)wq`b0C0c@ z#0^|EKr+0o+wU#=ua}r_wE(}EzLHG0lKw9V2@@qv7$$Lv^}B7LJicE6p)E@*+G(hwFuWS2b3dFmm$^w!4kB<0;bTqjsb)pQ%CtF>2!{1YFGWne`X)?g{w7t`*J zPpOeJYjP=S7fdU81O32&&>uc23ehYi@}^x4SfXt3`3K5xm4$=@&;M6rZxt2S6MYFc z-Z%tz3+^7=C0KCx;2u1<1nA)K!zIu-G%k$>cN&)f!3plcHPbWywZ3m2=jA?Com;C; z-KskG?6ddu%B2tfPy9gf%zpqs;(e_Kj-YW*wV$&=p&tb$Cn&QTi&u zJP1jurHVd;A8ncyg$NPkj9u>N?oRb3w;1tt^31nNAH(Gl=Q8tY!x$lS2Zq9>zQ5vV z^Uc8Wp#)T%DZjA*EK3YQ_**VR^I0xV3$bbD9Xjq=q7GC(r-MAfx&Hv`huaRZFh6(^ zuMaXIr!2%!^9m<`Qy#Ms2t78{YDzU+pTs`WdWWQA+H}jFpJdiI4#u_L2jfUk?0zh= zW`rp5prmk_@&@Y2A%)ZE<7L$_CRj9n^QxA=LjG>GVOH!j=;%bB8E0)`?>?)T6$h+Y z3~&-Gjp~#Q)Wt97{gP-GA(@Ji@GK3L#onIZasF&%)m-Yw24wW-Tl@zg&~V{8!lcbF zHDRhZ>2USs=#k38NSpdC!zbKIAY_*M%Aj;B{DlExHA$g7RquY%g+E_p%~dLC*#+oy z8Wl(RnP!BH^o3PdCnl~a5k3(u!)fmhQYeD;VS*J=xvFHgpJz;d}HE6ER z<+0enWETK`H?>ApNn6Tgq-GqOB%XOl)zEMr8b_B38~*3jlK5qHiJ^K#TG|?d z#Lt0kIdrV2+3~T=Jc+d{BQNAJUA0n`&eHz?9xDVcGw)XKia&JvCq|rk*BhfWv}d$u z@!mSWZS@Tjsa*bD;F~l4PyUzf*Sy5>baE)MGlNF$?+F}5#oP29J+`BLaj1_VVNda# zahF0>V~ub=$9@3`YwU7G24eaaT})OY*+0Od!VQ4<_qIgjIl8Vh@vfuEbQ;ZNL?Lk- za96OJeiN=gfH@2_R+K}a9+dO@2zf41O+lEkB~t=b3TQswI>St9=@Pl|x{kysc6{4T zAYF{?3fcPtgU?0RCBKd&vvd7~AMwtL5i1|V@U<}zB5DE+IpGoGnBDx@cPpF<(_WnQwrt&k$hZX!4u)b8`+?78^Fy$g8QZ zF{-W-RH86hmvI?44n6A%&}tv-swVs?+=$*3K5F30VDB(}7Di$DQZi^3Uxy6lDQ&fd zISd6vWf0=<1B3gjtlhJmk*!S3#*y@ZABN4l?OM0RLNMDERD5z< zm)*98uuxBkqK~l|Gv4c8A44(dS+2<$$9Apn`BbV$|77491n9a>2<}Ze_X%cnE~wH~ zbkAz!P2k7Xihh6&9E$c=XC`6ZDj0=a{R$f<>la6pchrQFW7jamqR|$6f33n(#ll;IL6&f6ORO;tYX3YAcFtxQdV~?+s9$4C-G3&F zzoCAZ{;5JO7u;-PDS{KlG8WP!FlC z_VnDZXhx^$ZJSRme(Hbe3BqVSqL zN@tmXB@wH}kZLt3VGv=0ikao-rfkWf&{n7i#nG)9AIy<#&uq2RvgWT!AG3PhPcEQLq7H}zXdP@gXAQXtY9ZKNX-DmBuz zhWovQJFsHBEF-RBLcugrRqypFM-cX;a#gT=8$98JdN4^&vI-FI=OFV2(gBQ7YN$gB z^Fm^gG~^4B#4-siN3!M?YUeUuo^-o{@fErkF_;`Q=jsLr{R)vkV6#zebx<8U+*FHl zN^2=l!fYo=J8^yVnLTy(4PdDG3#L7T&M279Tzcj5JNoQ}Dz4vyzwi1M?^Hprh^^x8>CFJ4OCq!&%F_m0C6)#C~YeC#=g>+XHF3j zP?+5T-2Wdk%MX_~eA)_3{0Pn4evb@Beo)cvTmFCTQ5lZKUk^6LjP z<;)Cs0n*pp-DdjXd2|Nf>b3Zfu@y*NtW(O9f_h6j06@Rc?}==SL0ZbBu3nB)*_I+y zh>0rGJu95XO?_r}u<^@o#-as&N;omt*nP;_>_mvjTc6SSHN(ub(Fo?FQ-XL>R4)RYVzrNBUoa3merzNc~#L{aHXPIx+2jaefOz5@KKBHo_4P{5d3reW#Mw z4u;t@!#}J8tGafwnfm_#*|I`iz3VE&s-w?nYnTBIkl1KE>$4WS9h=`e5>?pxRI4p` z{kU)zG?gq(3>+YpApLp!XYo+bUaS9h-2B+*lS(b>DlB8a@n#y2s6m;op5}x0A%#{2 zU?<<+A-i0mdN6y|`eUqCypjn;#&~Txx#NT3PYt`m(V(*E#sycT1`m2+rc9l3XQgvq zO!iM8-0yX-aK3Z^mz$32dpQ>`fQ8bwv*KmTJ}^J#qbrO`E?6+OY62QZG^HlzTaPfr zV!abq8;+d<@X;KxP+sjHmR|0fNAbUrA#S$K$PLqELeX@+FNw2h`P#-HF9Cgv$KJ=2 z(e^W@4_a6}Dm#x(COEBPO1bu21J_byfBwWXC797lEV|T~Ugac?O0}(gT8(X+r;tWK z-5cBoHp9}bA(6Rd5lkKO?tYwO)n7fYi?$TPXxI=KJ}WZ*z*$WXz<1kDPE5YVbo>Tt z(GT0-A!6y1>gV|NIx}Nyjya8Q+iVs{NUNk9I04}xDkZUgZ_9Ghhav4(V?^WVQ`tp;&(*U(Uf+bYWN0{QBb@`V|E2Pq%}Olj0+; zC9Rj*_-H3CvIsF6rg-Jk+gZ8a)LTu|%l~CC9UpDL#?UeUV{TjDM_DTg;{h`|z!rN` z({@KK3PlDH@4%J8rA!p4o2*y`NE9-^MzMd$w+L&lSZ1!yPnU4%kr7i3J&@Vk z*`_Z(renEY;#;+oTa`B+#^TrPJ?wDxqNNtM<5)E_Pl;te!d7qxi+0d+BHJy`zFYsr z(GMXKI_8XpRUx=ukv=$7LS;M6RIA~ayf2nA%GBcHK2?MN0Q_Ur1D-1tJNDkPhZUtW z#F$`nAsP1#(I?kem9EJw)vFRAZ|l}AUHb3@f+z!t!t;!_eUw!b>GV8_J)!wdi)>A_ zGzFEFe&4)KQ%wz)G23YpoI{KRU0wulX2l<$L7htwA`=s%&&uZ*gC+JE_eq(df2{@X ztO^XeXp%etP;*b}VK;GJ&C;rtIQUepvsCa6%WI4RSgHn%n*`4g!W@pv{sCSxIoYR^ za@x{AeZA%}CMJnL;~j;Lc$<2vTJEB9;Mr6S)^ZV+((sVwroko5b=uRiX4P$wDk8q ztpU#!>fG6;$jHp_Hg!MRQT8vab6q(Fime@ZM41)5UeOYQDCq8Je}tAXvsu!u_>*wl ztMberU8Yrc@&j2}b>kC+Y)@q?K~;3-F>ZgL0En#)-X}rza#(NOAs_Ld#2STTHiw@zWE zlWI(=Hwd1|SonLnH;7deG>F(7o$@n~cQoU->UuEAMm0=BD=oOE?GLtdkR3G?6(vr~ z$sBVsbUm*xVnIMzto8=b?-iTrfr->DkVSYJ$>6(e;J7`PALKd@nodh!QKbJQQ~Ryr zjK`+R>U5-4Tgq*(-LuPj&%E|twh5`N+Dmt2t@(N9Lft|Od}LfLK@nm1^n;6xYDO8O z$P0&DWv8X@ZAja*;kin44g)FYZ7(CmAN@09V{z=_Z}&AlCi$=Ayl2pLTs-}QOsPE* z07hrEcT@5&2x zo?uD8>W)QGM^fKR#rR4v$33kSA_ar;msPYK#!*t=mH?rbya_A@>zDL1?J9^1HLYpw zV4Z#8GWT=BctoMd^q+~DB6$X({7i(C>t8e~oTNQ)Al0IGow1O@!d%)zmqWP{!x-5y({qCNfb+}W$rmF$5|c`2 zETOKj&0k7iU-0JN&RpclsH88iNvR6$1#ANQ)QPfH8vM?X`uoYb-NIwhvLhh8_0d@$ z_H{orGX7wc3{=~kB*F`~#L6R7+Gp@Kr@{8t%MM0fXmMF{;>hV7k4T3MG9<5*T{|Dj z67Q|}Sj(juAcq)EBK15a2TM%f#Imh42bpSGvS{}pFmu+tC$0<2d^N)Pux~@`*G8Mw zZN_jQL>t*u$*m<~^vI*CX~}@(cgyk;Zg<__?tpb4*VBm=sHVBu&YyV&5tz<4>HFPw zH&XNiKZ&I>ffu~P*gW~%VE@JMKB`=DODVAWA&HyFT4JSHa2oX8fNShkl1&8ETS ztLm#Ql{l7dUozM%o?M|tb5kknby;zYr5OK4weXH94kNZ9Htu~NW?*_?V_(0{^Xy$3 zU(}$0Z5SzfF=|8PKqN<1)e1kVg11wdQ@gb#eK>wO4EUy4F3L6qqJoMLE#`0^bp&ouVZAw}b~w+*T|qE*U#^ zj|FEe73yv4{5ffY(Y5c1#Zn{aQ!-)L{gAc-8$~&{%Ec4UYag!9Alf5TXe7~rA?@c> zYSgjE)KDI`yjMhgo-Ud{nk-*y@jn#FCy!PwhGIrB?{V^qc%n_hS|Fd1W=vmw z$qAI@Xq1fROaPX*Vk&n-!iI!Bh5Fxf3w z;g1tnh6urz*mJLAt*1x>?*x`n)b%G#hl$Xr>g=uBoXS`JeyE>*JK|34VJLR zzawtseR>r*jhZ|HlWzSR+Ws92k%km~DN6~~>~Px|!cfSuy58WiO5N8W<|Uvbhx^SA zoIq4o%tXb7d>AhV>HlW#Xrgs5;xhr0Jq{z1!|S0DWcsI(iLHwuy#ms|e1cl0&#pkisAQI*8Bu77gdq}Y00&~d)*hrf-j3~TdtCB2p87P({fo5F8dZx?vk!t zqo`&1XOy8 z!00>l)0RIUj~!p9>LBM008K1rPAURQ=1_C=)*6$|wbO`i%P6}BvKC#IgmhGvG?6Q; zqnwYiyS*b|`QZ715)Z8#@kCgOlC1J5XORyEgzWddg?ezoK5fEs+ElcaUKvtX%NSXw z!@KUnIETW209wcfoY7hfJ2U1HLr@~=5s#bPO7j5u-3i^y+!ccS=3@b|Xl=K!c@Y_; z@Oj}wxZ>X7xmugW{t4?r_C$*s)ydnV0t;&P^rMvH8;m4w;%$00w0@r))23%KMvv8{ zL@!x`@*&MI$iq*iS&nD#jNN*`m{Nr<5AxV_n>XE@wD31Fn65r;ynxdx;}z{9PJ-JP z9ibIrz3!v`Gg5@0iOs>EXzW7DYDyax$oU)!zVe(*D6#vp<>7DrAFpgNgMwovC3V$=5Fiy+r{OskswXyD&$yY1uiUn-rCt{;Gmm`pmyR?8(@51?2^ zCbEPh@886^b~yp1A%!S=gUpc#Cc55CYomg8Wx%m>-zr)RV;~cMIs|D*#i_#agT{AE zaxMF;*NAUun{(^bfbkBzreqLWynWtmIiT}D0PHo3LIF~HnZ)}M!{MM-O)w%6CmJlDa0{YQ2>5WQDT z7J_QNh{#Gz$J}LY6SMj5O;p6c~R9MG{qpw_7@`7(SPXvwuOz#NBF?hJk({(*iE+qK<#ds zYJgny@d}^u>>%W-t_8|hC+6+qCc{dQ^WHVq`S-1Z4Lov^cbdm(yy=O| z(5u)kY$y4gw17NtlERENgvLH-uar)oKpPBA2WR0_b7Q*_PiwuHhR^y zssDv&BL1%Z1sJ!)DlH63Z7oLm7+1`?q1(=YIVDK{&3xls^Q8e8pN9{r!jCm)`#~q& z;jZBM;i3rZ40@Ng9ejYE8zQ-l>6h;MK>y<-fllV-;35>u*847`a7_kNg!MPRZlk)M zXyTvgKROVV=m3+Px$6HJ&|&I015;^`HNLcK>$3AlOPOLMh;d3fn&o6v0T&})|DFOo z62|Z?V_70Flsz(1GS(LM#^j1Ow7sStG$Gp(9nh{cer$rmb(O+;j9|~oub)_-HAo|g zB@;M}q9^^*_2Y11A2m5Nv2g<;sK3lxo3_Rfu`2u;H2+H^cz4ah3rdikEFm%cR*jPU( z<-b(mXlkvVbK(7QgsYT!ETF3lk?d1c5o!|oM_y^47!$oy?)70W6gSeD6ec2OY(EUK zI=si@ZnNz*I~0djfQqzL`ql&q zS0LYQcj|&1nN6Z&<-)o*`g6w1`#*Z~V$vG(*~-)KW7A8$U1pZ`<0-!j!r1VeUT|JS zKrV3>8z@;VOK>Jgonx9*>iurO70iz2v7pVp%!tdscD5nXhm)2Y05bE+;1r3h!ji}= zEObGAC{g%T^Jaki=l!_3cR|?!J_5I6r3SMA0S;)a@RC)NJWQ)z>)j)MKTIi`kXn}? zIO|yBJcIs@1kn4u5Zql-6j6;`#)QNxd(Mf!gaHD{mICx#yuIt5$mO(T*Jslf?5h@IWES z2QLFj5z9XD#IselyTt7wmy_O}&{d@Sx8dQb3aMBctLNvuA->x4pE2Bum!EwI=(~L< z%R=~D2BV*M4LxJhOUmML@U+Hlu$=Dj>0&Ts+WVCm{e~tnr6(8`GGed1Y4UJ1T04HQ z1<*S0qma!*e0;at%`3QQzr*-Tzs-ETs#Sm zYvS0GIhEwaRazP?ZC?xQcU)l*$7`#|9Zh0;kNqI4Lcro?s0?2bt@?hVe^t%aW`i`l z`qmWlp~wyXV&P_BQ#H`SdGL{BpUVlXonuz2)SY7}w)DEoqb-m^JwpL7*f)^_wvZZh zcn{TLi1){gPar94OPSD~br3&qPmn#6CzvBO1^5>DJ&dd1;aRTkyAI7r64U1r<;OR% zqKwC5n7)P{2t;A%I>P0;Jc(bE(G#g~}f z68B9nnue7*;iWfGPenA8o~8>;QV``iZo4Cf>rwk<(~%VaS^34|&FeYrxnQL1_@HcC zX+U5TY^GXqIFtcfp!SYb-;R>!>3(N_X#!!@@foF?BG2o^76sRb{ZDD{{-Yen zt9PkWE>t;3^9_#KlPsS>d9DqnB5hn=mpM=t*dW!F!`x;H$&C5b{bIiwf>QuJkQ})B zC4Bk-Drg5LffxatxP3_(cJD{DnRwm~4n=Os9s3%ER95-Ujm8QKSPjMuORJQ2ME_&+ z)s$44`6Q2K>wIh#R=Dw3ir}J$?5+S_b{fKeCWQuH4Y!|XhJ#18-Vg}|(6%Ept#D-6 zs6VM8y9*U)(lOHY#8lHLh;ZfWEmb_^RUBjb`t=FE|B#=h4Sw{A<%u`vdPPG>>#BIk zvJ-5jO*hy%=_2uu(lXQXsX69CA0$qxaB8~1{lBJET19azFtRMgyT3&(U+V_>jKQ=;k?P6{t*<)i|4vcpOvz$&U;rl;Ngs_dxT(*1R8-aSJh|_ z7JdPewR2t=>t#8(R0@krvWmE-6(gNOwuz>92ZnO8De_%irZOOAJ8Me|3?w7i$9$q) zuNBFkpw5o7_wq3gGgSB@+kBC~yg#d$Kp<#qpH=CQwsSgFF5TlZUDON5Pyas*hCgN} z+39kjj6?;y)EMJFMm>Sn3@iTs|8NGJK~;@$SNCKB{o#$x>>Ip;@9Ffmc9PA zw}{!DtwdI?OG`w=vAB(V4;m#acCe<@N!E_^?=#oo%79)vsM@ym{>05-CXPw_{TS{_ zK2CqBEor6g+(?798v%wjo{n9htEwBxd>)G5K73E!CCC~z7wM=U@pF6rvoeVs1IOc6 zPb`{%Ge(D~}L_#Uc6l2H28jf$}5`^{p%#yEql zvL*`+>3Sy5L>&PA2?gORE_(jN<*A?Oa4(yQ)P)J1`6k+bO!sY+sb>NQ`elCA%*Z1> z{ZU&HOW)T!$ZQhBb|v|+4C1~ zylTVRPu^9~>_45R4!=v~&@fyNeLTxAk)D^dEp4wv7*JOA+zE?`d{8Df{i1N*6i^iA zmV?S4j&J1z%l=+t3g{!8&r%ps*u4((d~org0uA@qI_cl#j7@|o{)oDYeHBmr!6tFJ zoZb50I!ac9T^{?FkD5%Nna-YfWp7=ycbm!tCHt6nopNUFu{C_W$!hdaeN>65^io5S zy0k!LGdy>%*_WF3x?E|4tkPwF0VmQ7l#xrGVS1w4y_6MR1KTYzl0(f8hAp|1pn_DadBqK~8#%Y*0VYdnUP-%ny0I!@De#2s42gpFs zJBWS91CPXets=ttzSYq-A+1WNoSw+yeE-Yi$q2vyz^iTMl`k*-SIxA(8152aaQ&+ z66!`sTZbD-L@*o{|3>D;gJD@~e&r}2JMfw%yMpi_quGmGrpI4_f<;Cc&hMkrtqZ+2_zv!aEN3KwdrSi(w5|h&o<9T&8h|fL02~MhZw9 zN1ue{UQylB(^Wh~-D}_i$S?j%Oq=%BLx_V$)wG0;N`~cBY5Q)M{sSOj zqH#zSBdb~ioG9GIf!Q&7vlafze`Rvv`Ls5?6x?1_5|F^P$CyB&$0T(y%C{Pem>r|T zS=Wg1<1G@0sc+qaUi?2UCd6Gry;=*Fvqk>_#`xcoYeZf~Z7Y=x@Ng?MPoW`J8HHPX z1>79L-gOmXL)2CYUtx_~RkYD<`}^9*bL^iYEW{O}yi+igepp^K`n3tCFAE0`AKcaQ zM3Da=;<+5kt-)g_L`-nDNKCsbX@^*@SBwn*5>#$lePXZrC6-ii`$tv4X+#cMOKqf1zs$IVoTj%jqIXYYxZZ#*sc`JKsP~Hl*I*GYgO#}2F;Ib zuOO)RmaxrZ#AQaO0c?YCs`hfEvOrMpaPEn@8l^J`6#u~Hag7pQ5P!rert8&=wS;(< z6Ic4@Q1x95AW}~vgKi+4(>@vrn>J6hUl&Dp;%f%)C}a$;6}oFm3z*y!$;gX;9Y&=Z zxAhn?`7Y=MF=w*={cxn^{%WV$73y-zn@#e7S-x+!(xY=)?ifGTQJdgAET{;1`eFPQ zY~T!$T3a+weMtPT^;#H*Mu$V+BEx?_Grq%#RrOlot?(#}KP$J` zAN7uW3rcU!3~sXjv-p^V2Ey)LO|P}S&n_pk4s^wJsEJs;gmu>K`i%6DE?pmu#Z`rxfH}m$m&>gXmQ1;mn$Nyso_e)uDCk?%-N8nuT^e6tjAx!1L!A= zNUU)pbo0t4Jntj*zUH6YADXH6L}297B2P&*!VUe;)B7dFF-yu`g?-_=Jgm4Zj0-L4bK><-$!p!(v-rxh%rZT_Wy z0N9IFrM-pn20T-^eB8IYw!U#N0xK)qZwfOVsB><2UQJz2PYP zB6LlCSKP*SM?N*yrmDA6x4Roy;C6@w#u}bXi~d9ITdCgnTKK%dbHMF0X%C7@AP}x^ zN$+B*HxvElwx-umYhqH$4Ysx|K_dbZ$Tz&up7rUQxH5`<$2E#WfdzJ~Zoq4YoLXvV&(# z>R*5%Op~LVYo9fak{P7gR4(1j{10Hqs_NV>@AlI1L`@p{9$gVJ3!i+_j-qHJrk3d8 zRmosJwN2Fy?yIbF2V2y+dH#ma_pAyVxo1?iQ(J5AzNqdAY(r+EomT5yNY=Jl*@w-4 z6&!%KqY=2mbYQ>)yQZckac?0iU`E(}zoflRgx+QlikYc#J5~pigh5!!V#p50C5S>4 z4D#uzlX-%0+DeIIfCXn15z?JVsLbT&^cqh!qB&XIC>#mssAAuZ{?NM-OMqKDKz4bU z0y;D(^$T+c{Jbh-G2X)>Ns0FHdlfa>Xtc#yrO6JlAxJC?MJTFuO>DSh5^^GyCo=f% zi@yG?nUdK-6}4I2t`ar&2!Vol<1LOtpRw#5jdrIwm0!_9>fp^&(K(fkV<)=6B zO*5H@gtU3Ipv}bEnXHD(=}0kn{>*X!w?9*cFj_fl1N-M#mBc0Px@xx3$h$4YXFasUhr41faq z2XJ=_5SP)EeW9(UDMoMgj@$Nwg%!O!AI~#-Ha8cW_g3_ZO7iqd>az0m?jq0Fx#*qT z%%^VdLOEz(KzVA3b`AM?^?WOhiaTMDm21 zjD(aDNJK>bl$?@=hK`Pogp7fSftHDymX7w%O)$`3#lglQc<_LLmXwH;_P_ac*9jnc za9;!`5EFv|aE}NBlL+Ik2S5h^U|^w1{X^})UKsZ<@1vjc!9(0f=nvFA2HeBI#Jq=o zel!8-Py3K{PO2^f>WTj$`1xKGH)DJYp) zSlQS)1cij3i-?NJypolZS5Q>a($>)h>**Vqzq7EkvbM2xadmU|@bvNy`4}1&9uXOp zkeHO5lKSOqT3&uZVNvn7lG5)rwRQCkjZMv6-95d1{R4wTlT*_(v(UNuh1Iq7jm@p? zo!ve7$>|y5`~rD-^@lDD0Omi*`gh9yE4ql#blpRX@zdTT@W0{;u#dS`v)tScvHt>ekJ+N1q&S413Akr&% zvzC{sr;Vf;f$LGr5fz#cJfAUAV#}))efjS~WS3_8eNU|pz)ZTOYuZ}iCo3FOJG&}N zs!pF5#Rm90{=dnClJcLXHfkak0wXfAES2Tj%!ACF_TDKWt0TlG^Q^D%`zu^i(quy` zCBBiwX&8BQ?HBQV(T@bcO@d4bzYJA~jix7B-^Q-mdUEOB%VNnS@2#sy)k=rYKg|Cg z6cjtNes~c#+vc+N$Xwa%&_r&<^Tuv@AoYl@AxC$b{n1*k0J}x2qN@u|YQGc-*IwUSugDTbxySBJS8?GK za#Um-$@{X3{jx5P^kDVbPPWTNFN_E{hlK2ezqch|A9zB%0vcD8;Bi#(Hw`R&dK;c; ziRm9RCw4qzl2)x(S0f6sC`=Z}wKZh@_>eFSSyI5?@jsIXQX(6l*90x4x`GN8zf;KC z>hFjp4-83n?{T2~31;bT_1}OcsR%i@SwjEJt$f0jwYkLI}V9{@E_Ah(GkXjUsIy75&d@zOBMP@+kz4n;?~S>an8rHS}C$ zn0Pc_adc1XChbp^!NfDZv^J0hyZ2~0Azry^$l5y5WOs}5d20#ny=+Zgt-b?9w)g}0 zWeR;QJu4zXIT8}zwv!+%qiSoM<|+)Wnaybk(@44#LI{VBB|RHcR##hj;>|DA9iT^d z**f)el5SggxSMz{KIwhTJd#5ry^rndU-FtCwlbIXJbZRmo<1UV zG!c0{UZ@3*K&)9VhXk<+tDj8UH(FL-I(V?4erl&iu~Ga}$U$5I`M{uC&&r=&D9MRqln4)NMqOvTkL+{S+z{L`zdm9?#?qo_xnL zqjslN9kMvjKMq&d=2@AzHX@gr=^xzvmd+pcB zFUlXq0c}q*B8U7qvr-fzzd^VO)hO1UXoV$)iVrQtAN&rP!j6wOEDbRcvRi92d4gxj zZ(hCDatFZiOm?&GasI8uNv*48icjk|F`wvEX_~I1&FDFJkgX+SIL=i^t|zEOM@qARBE@@qbWX0yWm)BXW8B74$PEZCNx-K>sQUxQB{-s;50^{-utF7s*p-Mtl3RI zb!Lg-(EcbzUS&8-R!cA$F&ULm1H#QWaOL3myhJ;(I#Fyo&jjxbjNdg>#8Z&c)$%yV|ZNxZo?0^N-f=KNP~mzoZCxj%fh?PZ8#3x4Ac!aPDLFH_cb z6{4LnD)W0O1J1Lm?H*F-h{rfO)=eG+x@*e6@J# zyxx;@iA@!EkzyaRHnUaF*KuK*R2YHPSKKGtWR2h-*sk!dOA?O59VS%_7MN^hc*4p5 zOd##&3w0`5cY$Wwo6OXnWZ)zX5)(s3v~M+Sg%M97#@#k4np9%tC- z9kl4#P`rM8H+F_qODdpxkfk;H35zy$hKKFIb;cclz4)tKrdY>)_UnP<`sPa&CGPpKD;tM=WHaM+YD>-3G zws_gwYx~=X)!vm(W$yclVafz~9MYvny5ZV&#C={zoJy@L%j%i+)>l0+p%r z^i028NUerpL%_Fg4hibwlc)T(Om8U>DC=sF@;TKY3CxrKaJJO*Q_pPkOE1N+56=LQ z_eEx=Kvlt#_ZJ|^E?B*B;+pNcQ;NFU((9e4!EB$ooJxZZHNnYh>m#xS%nZg&>uGba zu^5xR)i;^=8K zSD;mpvHg1*O!fhW{MHxDHMvKepYTmwIoM^hWzsCp1gN=6bigXKSRADB@y#Jo4mQY? zrvwlVw$2et@DAzb7?5ZC+tijE1W+{ z4la#N&Tw)GqZPC{8Xfw|LtAg7Mfa(Ji&*K}>-)5NFL7why+3@wa$85Hyk&^vz_&vN z^wxVPMl5awcy|>UM}G9$BpL65t7=7*9kAb@c8u2oZOyGX?_wr%}B>jTV3L)KJ$yqUQ!a(C8z&AWtRu^-mj%6ePhx>P75Dt$vuYSRzA{h5_hc|U?(p46fwiz8)_3 z8q0^8@_$KI=8{%t&~$>QXEi_gLbTxJ_rLX%;OLt?2g{f2EI*#IpV0rTuv}o-{J_Cs z)wsH+R4Q3%N;62X@rd;^MnjfeDpbOa`t`(o<(l|8BvQNDv#G8Olv@}x_+3K6;^>D^ zo?+%Jsr$V^ZP)_{O$*$=LR8#z_=*xj7Kw26>)U9kb1x5W0XxeFfrwA$h9*9y9rBtA2K5#oq-#-)GH$JJdz$3(N{V7LVPvD*seRWVH*tz{B zz(#pFPJ4_AUK~!4%AWSvH_r#mZL+eK{;GMh5HII*F>tLx;}T3r%NJs*lVr{uQE2l% zt{1uev^aU4bf@g4pE$pe$Qy-GeDAoRwMoPyES7nRUTV0Bp)s_pM9=8w*L6vb8c$KP zUx_tx5|1LaPZcIJw6vzQy_tklU~x-5Wk@hD{0UBDebj^gpWFAEuZle^YnJ4>0*PpR zV<|goN=v1}kGv{Ps?qnzD=#b__yH>pttfw^ZzVmMFJ*19`c}@wOED`%7SM8h6q1WRzJ0!U(n@F?T(X<0l3xmA);ui;0~a-qNM^E zpFmY}&+mX95#VJ&^S~J>?(1Wd7*oRZJ3yPl?Wf;XcYp_HQBzFnHAW3OGiJ`9i1k{JGYcAmLw+f%0{4`5yjm4 zCp$gw$=6y!CR-tE+J%rVZ*XLirVby+4dH~yIvJO+mR9_H8-Z998>9i0NpQLvI;fw< zpeo5ZX*VcEJs1PFw43c$LbmQvH>O-?kNeX>-JHJ^Ptrrc;!+%`zC0I;jQxUR)hS_0^$cm2~K@0m&&Xqod7kAAVQB4ZOYP@7o}|74$ASpDm)jE=zio!s?D(s#2?I5MCd;0G{&W#O+t$(* zE+zpwf=2v-!1>CjoT~}Pm%4+!alB4WZng_M?9Y6_g`XpnY_{MJG{T*O^ z={9*Si(PbP^D1q9fb5vbCyS-yT*>a|P@$$y2tm$PLey0aT=LVDZNv9Ydau|Yb2^ml z(yTcwMSRijy252974Dge!l<6S;;_*@Q^W^xf8evpI+DprwV}iktQHP(rBiS;)g?c- zlotMhCc%iwO74*5)YH!yo3ftYcT;!v3}&SAXG4X(`{JJAg*o?T~0E5o(#Nc-;YL$Ic+ca8^{P#T~$N)>rCgml4u~ zgqSH_eyyALeP(akh!E<7n!=`TUveWLc6{LO*Qkq+#x>qj#bvnpmBxOFsws{yz@aW# zQi<HjP~aFhvP zX(V{#?zam3-aQT;aTS*H(L_m&_a2Td6dC1ZN$yXt#V|-m05rzIV_RR#@@|s3uWAsq zc)y1{7wjmaO^#((M!qzAgb5D60=y)T(=c$FTcGdi41tv{ELYnVO25nOlnnilmL11q z{KcShVo_*)qWdj8>!hRPVh**!JdjW(>9Wb6;ExO%JEBJr&m87t#Je*dM4cXctjc!NdmULfF^m@aE{#|HlM>!SLn zOg#mNUUTH|t@Kntv)yoa0Hsv%+}0=(7jg|bkuXt1#2^G0T(kG7_H62|C_%}aE#h~8 z&Wwv#pJ)AkF zYA`z)8KRZ_JjsU%Ef4Sh?x;Uz2a3YD1JEa5fj{&9N5ivb^$)|dOcgNDXA-X9O?d)} zhz_Wyu!9oHn8?COZe>(VbY*X0H-xotn!03&whQ{6enCj~Nna^+JT!iVdyX*$4rk979I3VSlfLCCTVB)!;V41z>U4qKJ*k;}^Bf30((@q{XR^)L6$roFtAFZE z*XHTSa?%j6W%)chU<03bvem#8Eo7mCW#JFa;&BG>uLSQLOCZYhrcJ3OCnhX|5)MKe z3^%I?hyyGe6|{NTm35Vjf+}abJ!#a*Ux)V z$O97_Ln0|XamI^ZaUtJPl~E}q9x4_2q_^T?H5=|YvbEBaC2)rK04?fT7_tPh|f z>q0@SF+%QdWxfHmPcn>kex4!tdg1MgA*nTSZSRL=X7MY^+#(5AHTxndLuGL#vApp7 z`DPz|J0(kuLJ$&;ardR-eb1<2V}eQvU>H6k-MWyJ2#>51?NyY)f0Aafq*v#MHZtG+ zID1;<(Jq6&+O=HU_dCF?BomsAo*|j4rWY~ZMj*JtC5U9@h~4|^3=}1ZhU_OlyU&#! ztHr2~hWjSV=C_9er=uiyfcQ2#t(j2g4kANJjVrJ=XCg8lJ$Y)*ATh&tfMv5i|BIf= zd1FVJ!7-*ZB{oP0=*!E0vnE&ncJgcSW>y}Go~*GpzGJT-Qpk$iQc#6AzSl*sBSPcG zZi_$r;#+o=QwJ)t%$wE&?IHfk9{n4j{ErFJaK0mPXWqaNH5fnRId9)kE+^N^jqGqf z?|MUszdLsa$kyvP!vH&;o-6X*ETAqP|JomH-$n?7v1E7(@+Ub@B*Ocy5?5?vTLxt% zIkU?Q>H}(v$1X;6Ag$d~+PiX`)u^eoHLIvT?J|wMMcjFqucgX+YInxVSs}Lo0&YqN zt)GjX#~RUTp%0(W?XDh(_gHGbX~~~uB$uU~`Lr$&Luq=U@}3|$blvxP8$ai-3tKROl$7x+e${qaTvI_XXxnihK9 z`=fe{k-qbjskBm5=>%611h>ne4Th&l_%SV76<45ZRp=~cY{16jJAjPI zbCbdK?92P0acB&*7+p}rxXPwmGet$S|5v8re7S#H`@hLFka~{AbZm$+o9Q0^^9WvA z1%=SbT-HdSr}>|Fqa106eqb#mxI8v_lMY`V^?DEj{$m=({+I@}aNBt$gcUpd@w$r8 z#>k&az4;n1DkR2B+;1HLv0}Ufct}0!LC1->cH`)7kha9r^(v$t!J*90Uhi+aMuc70 z!g{X{L?oh)%hp_?GLWh7!_U<2nPuYT;g^|eB_QKIFia_JS9rbHNHp&6S%jT_`ru+D zP9{5w>t#r(`W%S=H zSZ$-2An6kbNp&zY8lo?(c8#qo)z;)u!DEx{Af7vbS6s>U7)iiDX+!SDG}@ImxCa8cg!X8t$TJ#IJF&KXb|w{OaqgiaK^x(SK718k@m zj-NKO<+X3ze)wBP`_C_<{o$!(%a0?v?iBJv2XZuiWo?yO)+`XfL0_TiCl1`)%J>t3 ze8!>ve$hp{Z<(@Pu0B2O=_X5=$S}z$@yGe(IjrVGWAM5JcU!bv>;m6MrgkQmogeQC zigqFi%>~}6gr1G~(GrU0A0&J`n7EYl>lC>IR4Nq_vAMOFj4W=vBz{zL}yga1fKLH+3}1q-ESHWV-VXWJ4x%Npcm zqF|>`+egzkblrNU&(aTKPRF6~zOT>@(-gQeE37qcjUoFm%=YAj_ac19FFRuI(f}dP zi#95AbitYO-L<2TmN{@GTAv2sn=knrw5hv7V#b(#UtC{=yIwjcUDvzZiqgSZKVMVA zOV1st@pdNt@I6Pon+RcaC2$iKUZi^Q4v@L(=MHG$+n%8*@-psb?}8a!x8sfR&YD=| zi(%m{wEIW0DSb8Q&xMWR1r<6fcuTXdJbha-oLuD!O+dv_{42w>BjKFx7A{rPbanlc zvF*VX-H85~kqhPE9Y8>wH!S2vBHJ6mXJQ8HlURCk0Z{{b%o#KMLer&4dW?j?U-~pY*)B!Z znXA<&9PK`haaP=d=y?Wcw!R_8R`-+jru*p2`6MmRE~wemd%w?8unOkAl=b9A*OyIDVq(##5S^MmW1}b$Ldj0I|0w%+KmzE>R7dS z0RL$@4F734Ojzw(j)_Rw77ngzZUxKgn9Ez46;NrO?l9OGpgVro8t2$Ew}Pc=V#(~?&@K96@}*VUN!npMrR__q zd#f^u&^ua2G(u@}4x@rnj#fzJFKbvGGgRpgfH zFMubWT;Q29_Uw8%wt9^{Y1KuIk9QW162@Bq1#6+V&P5=7g68;e6-ioCfhWt*{o&!&jr6fjWs`0wnL+lRgvBJbo2*rUH=jn?9`$f{BNWm z*d-(d)QStro%Jl+?I?6TQ}%});;)Y6gS$5$$C@fG>$Y&)(!sY`(K%6h6Eye>Rtzqv zs+;H0+(?Z~eP4l|o7T{h?&IYIDe)d;hnbRzrGCTk4<4&%v0yYSR3{;(MpZQ7e1-SI`_N z23$X2V%_mP)OS?t7D0lz6$THY!wZ*xgcl>Lf9oIr>Gh94AscpaxSNe@*-Y}o1+|}? zvu7&q!x};Q7U~<$4dMc(HoVCN+y|hUanR&DS%bHLkD@p~`aqD3sE$j`+8sn{sdY z2nl(MqRy38-9&1D-6+FM(R8aU=_%i0%O)^f;#75WGd|-w&7NOS^Wo#waHaFAuf`G* zlm>$ckmP9N7)jb&`i0HnCz&maO~<+k{pZ$$PE)hFGb!R_56uV)zQ@nDdbP@w0&#h8 zgB0l^gkIU-6vkCUxZmk$HzmcNyTDnoM0{A4bZwV#o7-9pR)$H~0ncd>n#JwSDMyaN zS}ET+ci*H%Y5qb506Cm1Sd~{DWu|YbUOk-(X#x-}H?P#bxC2OPokEC13_F5IL=%-_Fc7puL6`wM^zZ8RnnXVkzi03`*^~ zNppEO9GVf&0!=|@t|%|9UTdkAl4k%T{y@GU6HD{pEN-^qcX8iWc^JAkoJ%wds0+@k z58Hil;)FnAr-YFjSZ&1j9yls(_tlkPX4lrq_X%Av|Z}&wpwpcxK!XnpZMmyn8r$zm1VQ6 zv(JL0XU0vm+&??sX_kt;vm5_l(avQSrA@r8kj&`DYO`b4yCp*%L*=FwV(_Ta_Jz{d zVfF(%F?pVY!|9B)!{I8eF4^9e{B2}S#IwsK1)XBDC$%0_y0za7e30>eE;_b`Hd)IW zTvm8u;9S992J*vZn-6rNi@)1$H`-ux`aHjaAkv^RbasBLHq@HO zOJy6u7wTB1-2uzo3pgDC9haU4RP!lYA+rtd07Qf=X%~F?t1=cl{G$zt~8lrE9Q@ z(FAIA+NYhDJqdfHu+GociGbjJZ%&ysa_?O+B35~ zJvFBJCENGq_4fT8F$ZN=&60!4cePE5Ya$jxSir;Dv>K4;$4ylw4R>oq2d-z{?D-Ny zW|soCXk{*wJcT@-WQ^|}fHaOIEG8;`$Ii09mol^Tkk}D(8an#+gvZ83Gk_7{o7xkq znpPMav#=Lu!$hE1N|{n&Wlkbd!y~<$cCy=QQK}H?Oa?DkUc7E;;FkEgJYR18j>PdI zPG-Ax!ds0I6LJ)a{z1A3w7V>i?40>-p0dyE8V}_3z79 z{_a_G@BcMkaQHm3;dQJySOpA9lo9*s{SFWV1V^3GMVdbFHUCY;>2vtL|A_}Kt{SaU zun(KZ@SA_ahP4 z&vy-GlG?eE4iX;3!(R*QA}=_%6XY*}C#o&^duhzu^FqoL6)Y4OOh&{QId}`~sy6>z z(3MZBdlBBsy5{(JsCuWF`EWI$SyO`jiX`Z292=kgzB|Nfs>3oa>cV}PD-Cn;h~m*x zikpY!AQE3ZWNyxY?tT~4S$08TC?0hxO=}aft7w?E9onjxyM7IpZL3`u&k~6H>7-W? zjSF!2-%aTMKcoj&QDnQ2?V@P1q~9b7WB(3NbKK`=x7rbTzro`)^8p z{V=V+qV$10B8LF7&ijLq3?Bd^3BFvUmHa2Ai8Cbk;W{R6e31SMuCI{Qs@gpp1EF$-Po%gHHK2?_vksy- zlFj3Q{M_7ix$A)n1Vu4Mkis-Zs?u+KO0$2y;>{WwoA&MT38WZe#$ z+=fcd3o2*5ZzFiGvIIu_qc=zwFa|bok=wVpWNT#}wUZJ;_e-txUndrU!g1)nQu)7Gj;sFgx8}#U(zuGO0D^*XOzX-;Ii%M5p~)aGSF5NutYgVCGW@J` z;kY}1+Bzrw7~fVYzl^!2iY|f_V^Bj=<^H&WdD`=+7c<5Rj4;8U)N6snQChvs|5($A zPDlPd{x8D=t%V=lJ;Qj9TPH;^fO3i~f%JK8F5Mk94ZV_%uT|vm@wxMyk_}Tidc1#Q z>RR2T`E$JjZ9GKR%^ME_&J6(YQqDZMX^5}Ns(2z!gsV@5=!rH386a(Yv2q* z02xJDfFcFQV$$#PeuInS`HS-yXzN1>O5qm9J%guDNkuPz(_EfGvaNFnr|2j>Nmh^h z>98LyTGk2tl5eMKd`2tW@9PFKxTNaO#zq`}ycL_=Sak8SwA2C~C}zg|q9({fY?~5F zF?x1)UQ8Gv1N0h0fgwUo4g;O;KX#_qki9uUarMB z_9h6ZE+2lw*YNT~z&tQdOvg@u#ISFil#i5F-{i}ouJ<^=CV^O7YnL+csmy6cEGXIc z`E`Kj%iG1CdMOs1k@`kjFkN?`ieFpF&+{v{-Y%>aYWwb~pyduBkPTf_I|Fe%7oXE8E{GdWX&i#9ww zRv#itoAyyp#k^Kejq}Fu`5k9Z}7tbSJn~F9sX@iken`=d#R%C7dK6BfpadM+qiH5 zZapck0pK*77WEYN{8Md7`LV0GUY2avF!6m3KTk*qT9XE+Wq0E%C_YX*R{ES-Q$_7f zztFif0@>!!(>Z9RXd=?&fC?HmjACr1WYVEu$WTGA_emm*Eh zejK%a2QVYV=+F0jfGl!`IF$k>sQsqtovy%B?9=c#GwFxK1=b~$Sn47g<5~kEqAZ~% z9<;Sbd4VFP(X{s_e4T!e$S6&7lMcZ6VrA*XGTenO?bb3G_FqCP&&mcCL>)HR!^lMr zO{?%kM0d~7@P9uR?$K-&#Q@K&wK=D%-fS*ix7j!XeIdm-Ibvs@8xj7;!b;jo?Kd7} zVzRXt3x#bJ-?wZmbY6RJl|UQ)`$2@;@bF$L6*=v`>_SlHQ^rmA{$HS=5dgZG0@k9| zHYI^spl_?`m8!8=c|NK*rdl`6EsJ|!N85-aCdV5?3m0I=M@@jBQgXWRYo0FW=Zr+Q z@6a3}%LJs7{`e9WA7o#o^2k(@D+!9#6aFQjJtkH58S@7c}-8-Br>*Y`U3g*>6o|cHW&-_ zC))M)Z+Il*wu#quqcsPu2n2~)YfJ~S&(S9R*`Fo{yXwFjy$r?|MvRh%(JV((bG3NL zAIS^t#D0+UPu}XFyM5aIn+|h%rPuAf5O-rRi^S;)=^D{$5Kz+j`;FEvfX2oez$ipT=$(*=IT)o)I>Xe`-uBR1WqF^AYxz6Vq||8xLLRmcOc>E z{K-bhA}Pit3tu*R-4I03bZ+wMXlrd<9lBoIz)#0QM8w@7@h$|6=$LDw{MnwkW}%<# zzY$N;cxz6I0WSp3pp;;=ZRj*|kMmC2O;fDJCN*ZgECM+EScLI}6tM6g7T?qIH6%v+ z*BzrnX2=W`$Px`{iO^oMe=ZO14D(mI5FdOlf@;rfMOKBejZ8ls|(x)QOTo z8fiCjlY-ZNoNB>clcZ7PjCwOVPMzdAcq04~Fd~WiD#1uvk+)a?*QPW2wX&t*&7MiKMa*Q4 z4Cs$6(wjD2pjo=Q@##Nj~c z<7kpaL5%cku&*2R$X8Pkglh{nFnZFm)`Sb-@qQC5)e0Rx9buYMu z67SA_@uda-Yb%37by3zr0JGYCO%;ZIJO{=G+;9B0T;?IO?UOg3+8_L&DKHU*18bdI z_tW(aplIRm3*Ug&7wj zn-+fGK#w0nTDfy$$$M-l`%1b>qX8Vo`I2myr#O8pHOD=7fQR1__FrAw`*={;|7y;; z7yxdjeo%1~kZ~gE<;dV~{vBdko%kw2ZeXWUJd6T(>UgLI!%>5WeSIF$Do&|yJ6oOV z*#+l__4Xde*}ee^O_LZJ4LUlJ$a1~bnFzy;pQa4^yKTdNm_7fcz5eg$LsJ*{rKwXP zJi4vX5!^S*lCtJO)Jsl{)=g}f;Lc^zS(GVcap#IABbAIqn7{0E{xo#Q@dsU?6bVc! z-p>Jy2RG>DA^n)sn z(vKL@zu&kPhl+@b3SO~c0Jc)l;2t5J{m`a>Qo;Sv{MZ^pO|=fI%d4u@qW&1mS=_Qn zaQ3O3=T-vd>Ge4j#(W0|_m!comTGVdz*?k+m~f= zMXRQdW}aafNvK~vuGJ}b6zFVwo1F9 zyUFm!vjGwKK6iAI;2W!Wom=!ZOo>=r6I1Kl4QXxxTklL+aCud9Yq8?SBWfv;-7U0- zLEsHn!twV+6mtUrZ&RY=`b2l7Df}7XPhwUVu{&lVtKaKQ@Dl1L^smTbQH&5ErD}({ zyWYD8o7k;nx45{_Pq4M_gM(p=jLW$re!eScm-|)dO*QuN)gG}o`IbfhhBYRFbM1L= z_I)I6_t-4L`pHWvJ>U;>B)D^>wxc&fiq*65eK~j5BQ`0$VUkp81Wuus#nR#7B6f3Y zVcBwfx3AxL@+!gUy7muWDkQr-dPXT4co~TE$0N>=p!Ksu z@cXHCnUb{-YddTjFbTEvqSdA;VIUGy{j;8|nZZa6IHB7mO_ z^8hrLy?WRXE=6s)-=G`SoRuRnvf;9s1-^uimlm^T%&5?IExw-mU0o9`f1l`MjC3F1 z5DX^I0pMv)$O4{@*^WUE^4lklDp*2UVio2{oqnv<+9cjHe?zEljd}8XO}0iKxvpPt z-NVewghA??^KSjD(ldLsjq^OCJ{Gzj5b-7gkf$R;yNBUxp;T z4m5;~_=kF4XiQ2y@Wn}3_=UggxcMsb2hXo3bT3_`=~!;(uZqJe+nFmfR|hJ3+!b`K zJ_1_eVDMjWpdm9AO6Tk9?OEqXGR(a_VT$PT3JFPqZ3X&~R9{)W`BvUPjyHbq&Ez-4 zu7R!?OSRvJlyh(6jY-iitk5QqN%DRG;T^y-F5;HC_0zTdYd?mW+qb9j36je)l-4yksFp5dLaL#0H{0zEEKGPBd;cSN@o7r>W4@}Qq25D%25P|UBWVPe( zuHd?U`egmyf5}VyC}DLPyHDzvrVI-BmjIq+s}0ZQu*Ff8nWdKCqe^Y4Y!gR)z&}^& zp#63$7!4=}Z=w1n&AkK8B(xY3u0WhOk{miejMma3?giq|U`gQN{WEW<;yApVl;u|{y2KE=5g(j~-;>o9D5ZSU zhH|N}Rw=L%V=0zQirp+kdy+s7pExH|2~V~2KxF3XSi*`)${NqUFnM;*7UXu0mOrky zgY0Oewn%}C)Q}w~j6N}Y02+OiLs%k6xX9Xjo?xyu!F4qC{`o@!m$S|aLUMoT)V@DS z)6_xjrx>YQ9Sp12PFK)DFVqfo8eqrQbe)$NS?`)^I#bDuXO2sb%7^XhFYu%WRM@6m zS*F`U$posjUr{h+@!O3Vci+A*ppJj#9HwEV#ylr;fSdUNP9Y8*8Vd|!D z3DxV#8*#MJ3dhd%cq+cx96u&GOrn38L-+=Y?omZ|fj4(O*ns}zyJ9j2WpVyQy@1$> zAtst;5S(T60vW?k-$(_XmA6hbt_41qU|frF=~@V0u}(|wEr?pIrvAuD=eA>apcV+K z&5Bu5dFJV}W;6?5#$zy2YSQm7u7*SatGqE^*pK5Z1yBZ9;^XwCqvU^cMsQW~Xe-1+ zu1fqf!)M#2k&&>|UMb93?9??HkzRIjjdkV(ncKn65pSFyjtf+MQukB(UpF_CHIu$# z?D?Jg>P%|~#~wV_a1J8quqMQ2%F|;_CKXgImss@ZM+aiX4EH}*zF7P*@MElq0~f&? z1HwjuVb_K&#B;{RHc`C^hwAlYm3pxm9zt7qUyie#qzUT66gTzEVhZ9%f%2MmXOGUA zkQP3_j~}X(@27Ne?w>DFR&A;W1qN_jHk|Xo{NvZ+qN<$55bbV)1M|&&>ncs_&v(904DeI8a2jH?U%jjIcvr4lHo$9(8E-? z9+J0(XsL+8?k?L0xo=@_n+DRpM^I5Ny zO+lJRmfX+S-Y-`P&bDIzNVMtfPYEKhzF^%?>|+mZOFw^&bZ(bI#$mJvtteM9=*O-k z$C+iTe{hnfQ}FLY@3&WuqWbLtZ*OxTnts1_n$LR&;9BpK6Bu7>x4J2k;;^M7@^x@E zYxF$x0iRT?-d}qiKy-141W%gQd-P(#)I#6FK;cY!m5{e=t0K>G))~jo)|cCfd4Beu zDANY?1yYT#71hVk8ber9+8f7&C@3g2omKgML7|}PhE6+UlO0b*C{tKfsN-=GJwG$S`@whfzdTN&@w z{c0xLnuq#kM`yUpR~4Q{o9U1OK)4xle8Gx2cohQD?_ljz=-PS+@p$Q0rBAuY1fG8d5gd$yvA|Rm(DouKC2}PB(xuf6tKd+#yM?YY?dTrfhoVkF-?-#MQ)Gr~CXAE$-`d1RJ` z{g7CB|DF!2-!3zeLXOj?Myb*1ZImFtqWQPEE-OU3ld+oAC*s@loMPsyc2CztegdX0 zmV+RHeq>A*I)oL4v~ZGtMHSpqPOibW-5;i$NQ?|&RQ|FO7-Ht>#`CRb&FoonM^X>@g86{sdHQ3U^S+1*qJ={(vEtvD<_5y!ut zzk*NZ$@G`ihZ+-SHwqj60@=h9S)(-qCX1fcMX&J{)bTge0Nx}SZ zc`x_0$bs)C{ltbsML2#Zuz7AN z+2{y>A|c_eA$;@+sWXzl9jTHeBR>$=$_L#g*bxDcw(SN>jz6dQ-(`OuN-+&W)(oZr2t_ zznP%E;l|JY7bu*g{P8?A+h6Mak2Cg~V`-Lu{deMcRq_qw%`$VVR z<)X^IGxJfaSL%(Lw?`w-Q7Lyt_V2nq-o}_k`^f1qeg5XMiH!OSROkODM6#F|X%$uX zTI1KX7_!W9Oqk;7l683nK?px>PejrE(sS|PZHrCPJ@*7CG`X>3I#<1i4ej;sU&Q+` zRF*2a{PACgz7bV)U9mV|vO;Cvo5)V5=AB{Z$rH!^Q$!hSrem}j)qL7 z+J<__Khmd`+P1y+8Z!=2Dg%r5!Ll6ZxhABw2CsisY~&uGm|m0V9bs7r80lv{U)%lj zt>$6>m5qI^)LOX7c~kWkZhPk5ezs7zWhd_HCYxP{H2gk+8E4b;+jQOd*{vUmZCRYL zUAA$v{!1!6dKwB`zQwQn@+knWq_{M}Ar%P&wJZ(aIkcFnlKP-5d24baLUw}TV~48Z zjS?ql4Z5?wz2j;2Bk{9T`M*G1CBbIY7wjQ|m?H#jUM%T$xCUCnBCv?(v8c^j7H(mt zVTA?V%gC%>g~tNN+SiOs3^5NzIU7q3D!wigh_dc(8r#z^ zfq}M2td6YKf;duQ;Y>e&ibe6QP!j`-BdQLwR%mHo@#a*PYjadIP5KqGad1h9{RMf5 zQkIqTMt@dfwQZ8v-Jd9&cWRyoLiZxTLFtPMIlXb&!Qaohwj&wa;Z(a3a8Bdq%CPs} zI2U|%Pe1j$sOk$flcZ#~18p1Dgv%imzjJH`z}lM4q7NDlq#v|bDbSai{t`Rkvtc~N(dtdwVDDZ~Xs ziw^F~Ns*1&G9`E#_DQP}#E0eo0qQa}zbwdo5OF)>Xd zTH{}!c70F?<;63CSvJ~QB9vixU|gz+<1V;2i4mFsg<%!*U@etr9W&F>OEu!}PY(&^ z>t&;VJC^?bp_s~)gw3Hn!T*q)DqQgrKJq`&!&kVkjF5HNdrMrl>!L6&k`Yakfh)Nj zdbJov&Wko-ZIHFUt%XY)8m``%+p{NCCZ{4xKyXy=P@up}2}|ly6>Qdgtjbr|T&7P^ zcRMup02c2hISc|)%JM<+(d$wv*Apk?Ki>%7zpQH@)CB1GK=|yF8e(qI=lFwu($#1u zlZDXXN|(2ib7Uibfj+fsJ-;)QP%O4s&IJJF{$d)QoLYD7w0}NJZld66H46`UMSM>X zUeUhYKDulrY6f~chD{1ZtDYHAZ@3Dgp5Zoj*Kh*e$+aWEu;kd?W!qj+gKwI$c`i_MXD!Fq&;k_Y5_>qgoprk;{VMKi3vhJQK2X zH{mz&Zadv@sfk*;I=Wl6y|xVGxn@Uw-u=K?_;(*j$)B1f;W-5q7!UrOtaHQ(6CNQ_ zw_J)V9@l=mRc)WZknnRAuG#*)CR#81UDdLwLvr`0@QEy<2Ju74Rn`bN>sFADXW^U< zbL&3!{HxG|>N`()(sHf{9gP-qjeiOgVq-X}o#Nvf1wSPhkFO~E1#`YW;u7r2(rX}Q zGQniY8Vi>S5a?+a=V6^Xcu~_Pd!slZ7HdHEd%Vs+3tsZ9Y_?=FYR>FR;;4yOpsbK&I3 znRZJ&?&7ZMa;R%v2c@BF$=nY~>DnSD@na)u>Yu=XL?6Z8FSlonzPL*eK*TBEHx6cU zz1bTl@>SVvBkGjvic3W!@h$0w#Vh~z@sIl3TpBHYm_WXp?U@s{qX;1HA-qP?g)}F4CMjSwLNsPmCp=;8!qasS zrkw^@e}%{4+}wcGd*qh+gL5OWvx^{qQ&ZABzbJnKiwZk`)*Ff=6pWarctaqbB)U~L zz(IHQmo2>$Bl9Hw;sGLGZFaWMhWsl)Is`o45Qnxi>b2ZnRaOE zJ*O9Iivt9{#FL#NvINg8F?mMper_ z5XE{*CRK#^KfveztT6xW)j&1(w;&C=q0I#^*>g$~!YReX)Q(=BJn9xa99QykB!@C? za`boj)HmPH3=9>2#YBI130}+q3c#8sp0(Q70 zJ*rs=8+)nRN^@OlXN>$q?;k;pQGu&d{oUHvB{d9(NQ0Pgv zk82&B@EaZU(~Yjhpy$_S(hRUM|;nQ zK}E9J2Q0yu_b|91rgZf9VvlE0EZ7|AEz3b~8JFcMzx{_8rUV@%_V<0!_3!Hfpu7Kd zb^PD@-OIiJJu&@k5f$AoiA(!Z9aS**EhUG)I_jo-5mTfJS9HLjESkJMi}()sy3AY6 zd2x)1uLL5sO@{7Y#J84~xqI#%SdDa|eks)sYhLz7r}RmEe!KO8V^x^J%aC`GD7^EA z&e8RreFV*vY!RoCU?<2YpB_qwm+2;Peu3sZe|FJiZej z3bJ>};z_MC*Re0(8nv7qD880V#)323v%gSQT?#f=G+Cl^xPGex;T);pJ;%`LZR1x@ z4eP}H$P}qrYT1*xlKTqBqUk|H6$ZU&pu(G!Hgn{jly_NrBu4p`OQ~&lb%c6#{6|DE7xh%nYV{ z1MP0I-|98o7LPoSw6O&(H7+@l!vwE!fD(U94Jw)?gs2h=00;`jKDhMZrCd>lGVE1I zVOv4J!2*o1Lu@*tYZG0eXs+ySg~huY$XYeBosUw_kgns~uot~9kQ4Vkf4J5n0!YG8CUnT`$*ku4SIK! zdPlE633M)hMHKT2)3lt&(5*c0@jzocNZK7&=V%p4}zz5mGi z#f2FG=>K0cc9$Ah-Kx$#mneyU38+M@H*OoqF6P)ColmF2Ck&Tv;T_6E<5%NU6Jk}t z-dsKahWXx?HzV-YOnKXPSL;Y=mWKz4JCHeng!3ns&yA?-;CT0Hd^4+98mN zgu;~UQ*YR$LBWKl^K|(15|{UM%({H<FRIrBK~IeGgJ}sFcs-Q*5;FFjr_H0Ju%^Y#R!L0j7&Y0(K;kyj z0ThjM5+he^RR>m$s7hEkQi;105n4{ z%fX9x8t5C_S}8*_L~>5 zE#r)*>gLi|?45u+9-S9F{q3KLDasOfwDD9`2vex@%!lS`jUFy3@eOw6wleUpqV1w5 z+Vapwne@Bad_tK?`rFWe>n%yK-A;z|eGXDb(dL!Ptp0+_g&j1OE7E`R_9}4h-C5I- z_SlXX=~(yuT=%1JItSw?@sMF(!P1YO)ny+a-tzv@8AP_#FMEPYg+7PI9O9>!pR)!(nQ<~m)yq3@5GEwT zQ~C?pdbRTf+1R#Jm{&eRAwj-3i8C;e;K#-h_C5{ax8JDtgM*AH&?R0rEQ%~2@c%EG(-bRfCcUY!kA${ojv#wJV=6)ag3Sq| zZJ~y{R{yBkOMUMr1x!`y6(dQ*NOc=0#DFx1j>bWJOTJZ_l(;&eKn-s3&&cMV769uCt*GKlmd7EjG|!R`oA&YVcH){ArQl*HX;VUaf1rqBN znM(08%RYu5XN#{mKayHv&F>;_z0sljUtDI!D@MNt(bquVge&mAi;$}U7iJvpF;eSI zsrVdh+_78wk$Yr^{blQy@hiP>zJ_QCj}pr{q=+<#ps!qhkYoK@ zyCYygmHMdqQ_qPHUe7sS=5?hT4N2(ARTW6qj6r6(^R$lB$6xxsk{;z8t63LF0Ne+) zGsQ#L0&*ms4{tLw_^Fjr;}jW!y{#{RT7)<5@uaCuyp93M!*{vNbPN2VK%l=#DkQHD z&)jjjmaf5va%6T6dA{OUK?g13CtQ2^Epb>F%cOnU5z$>Mo5Oh`bDZ>f7~F;CxbjOQjc}!pN`{ z3a=l`4|z~~!=`gNrgvAg8Zn|bb*P@yhB}2XBJp~)!<|egQH$|JJB-w@Na*!}!P1$A zb9vt=L^A+G{kf@qJ2AfXF&{&d@uRoFkv7$=BnoU4Nq;`_#cjk^t}yfA;zo~N{sR)z zXIm}kJrMlKm`xE$nfSh)%Oyy^H^}r2Rce4y>{^ug4_Q>C^6da&V=N?2#E1Lkymoa# za{YZ(9ll-Fv>SoC+zyE{nSQ>qf5t)+E6W^U36_B-ufv~X}cDCFm=CD(g^0O`7i}{74M+>z>dWQhXwxC$Pg48wF;7h4R+dtNU)GD9`=kBJ8V|rM zUP?m+<}}>x>4HaKKtfV&C{RZx-X9F8We6d0t>!c+ zgeO;RKS8fPJtc`?hwEB~m77ZM25iXCN&-#7cLdgGv$k9+^ybRmqrr0iZs^_n+7GYh znDtd{**t*%ItKk1ebN##Z?lm!VB?M?CbA7>0UW^) za5GHgsPHXj6m0G#f4F0MEY{$7iY|EmHKyF~c;`3i10M0c^` ztx@@=Dpx#6Jq0wvlYX*5xVqDoX$retvYfq{CEc9rS}t&KTg*$juw4V|@cMwDkJ`%8 zFEEukyc?+ARP0!NPw;oI2pt$1k@~jX{|>NHIH-tNU%SIX1E;A^EF*trR>)}u&Fx#{aQXL)wlG= zrKIKiiS4iLI;4~p@l=OPfc}}TO@3PuHneV`bIs#PiXVx~h?>sD{odr9U&fds#$f5D z#>EgipXKy)cMyx|St<=jH29VoMQ%wAWI|G`k*T~iofW@*3x~vsdn6mz~ zaLU%ILCnW>CBpL<^&|k}IOHX=>f5EoC3cX7w_h=Q-KvGQ=D~nJ`M!4)HSkRKc8InCQIx#@U-~^@Y?ksRv78$9JA8yjQ%JV+=wGK6G1IqZ^qVE(ccbE@Su$v?#F0v}{A;GB%5U^El6FY)#fv z^d7qsDgDGM25lJap9MX6i!;b$j+(Pid13ZL-d_65FQDu4VDZTJgi-1$(gcE;7mr*S z3$#=H^3^nc?mR*Z(cPMmbEwN8KL3{Z&k~;Rtrw|6*8q@WKLPO_DpEeP7s-69Z?dJY zK*d{XxHFZQYze@pf=?DeBtCx zCKtnVSs*0vkcKNtE+&fKZB-~K$;f>F&gV$V+eED z($fI(vK^={XC%k=U&^OaaP8Oh^3;9~N=NgJe@0!x?_FqaBIrZRSz}7aMSMA<5)`+{ zK>11xPs4YfNI_<%m(q`P-AkIr-#6ZTa93+p5WK1B7C@0O9Sxt!^h02a50JSD{YLr1 z&o?N{7;)YwwZL5%X&xXm(%zWPu8gT@_%6Fh_=!p+Xe=)=7~M#H#JFK_>cdR81=H|YevI5 z)F0{d@5P5DGk(Nxh#M-`$;TST;~%NyQ(f`S`U9B}UhGfAiK?W$h_aiqRdX$UG=gc1 zf7iLf2N?fia1Bv)2%4Q!4w0Hy*g3V{=jCMRvPuc@sSXY3tGs9+jT;WJ#77P$-P7%* z(otJX20okV4F~s)|0b^b*CqI01XusN{+6z3DAmXv1rnrA^2`D@V*+FmRfq{rf(X%n zt^QGXIk=RIYysS6PRxTd>_C|aI_~SghOZ|wEhzPnf9gcgoGAVgK0|&=;jhkUF-WyRRe;KU)CFbN;zM53K80Pbl zeC!`9dTHyw)RcqN9M0;e6Rdw#BDOz*#Os)3!)1e@+xJEHTO!chPmynCF2RyV}zu!QrJ1s z$ywSyhv$y!gZsb(a3@TNv-DbRq6*|bX(33w4R6qZovlr^u+$phW|gx)GuxPi*AlF; ze*%h@_P-Rq>uEiyE(4MkcWlx~yyF66buDcY+X6`zfmsrjVjhfCVUlGfH&gy)pMWsk zm_RDped&pD^QUgBE&9u)CEM=SF|tI^aQEq*}70 zs(VsCrH>ma`9jC_w1e#4v4||juTL)KN@d8fJ@Muh*wo>z<`sCEUM80y z{y6SA?SZHXF|seYjHAYip37~){qo+8svQI(L1@89b`o0qCoU$rI9uh&cUlYt(BEh)< zfVxY$6@0Qe)?a{y?c;7r=s0egfj>TVI6}es9awrpJjSA1uxN`f{hn?Zd*Y}*2yO%! z@GCBNNL)%UNcL-Hu2j0L@o!}E@8`$~|EL~cq~osl(~zVrEK%ho8Jhj1wsC;x$>y2z z&}9(3Ex^=Jp{Jf15kyHcDHG1X8wbtA^iG_*-u#i5N9 zl8!*9D0*TA{OTM*YxHi(*h;MP$ydAko@1BJkZacKf$T~`C0Z~Lwqj?G^#p-u=PsG- zg}OhzA0aFG&@6|c{rK!)ndoASV`%fPbRO5aH~F3Q*5INax-L{2Xww*Cp1kR877zS= zbQ+iKj*S_Cd~{i3x0*}bwE%+!fVqk4pIfuZb|GKglZvr6eZfrpm3NP+uKy{u8}cY7 zO1K<-o7YHTNoJD}`}TQX7&rA}*+Q?ZI$z;dRAfaE6JU26+0Dc`i$d@kQs4K!IG@n) zC3{b*EFya#A3(unfY3uZXMB_Fve@w^R6gZx88B*J?F(XfzpTWtp*87h-&p^F_N)9x z72GT2F%}&UrwMtIajL<3{dz8ZPuct1K*w)4bO%J2DD^YnEQ>U1b9ooeAHck$o1$oa zGqWzu*Nkg1G{}fbYqtfbxw0G+{$fI!jW7CS%I4-1)3sR8#&I=z*(S^f!V>@wg}~|) zr!;QdqB|@&9uCR8;Mzf9XP57nFQQoceYV`#Dn;*`Saof%Z;MeYAD_T0sHEUPvhKt7p^~hz`-kmqI z*I$lTvF>88oSB0JHo!RalC|E$e|mKTj8qlrji^om-@v6E9%&pG2SXf9#=2XeqTq<} z+4L9u?1>pJGg=V>jeRk(=LVbSyE`?=L}@UtKh=M88OqrC9TsnlF6X~3~w1ME62YGj*YoH%bBsy^As{pRAhJArbS)s zJwthshILIXsq8P}Z?3}0!|pt?(o9@rWZOPV%RGEfegUU&|vo1AHOAgFT!x? zc+0|Up~j)xB2f{BUTR!4GGMp*%7}u22qRm^AEzhtn4!<_`TYQ*=O1CG%3W{ghP9gR zziwBO5MFE9ak_ipQ2WmA>2t@0Uuka<=^!5nunTLo$PsaT1WiUwxeAk1{W^}jpl?xw z9j^yFfbOIvVtp%6sZsj8tEA@g{Rw6UUTbPNCCCZ}OJtbrdX?p=q~u7ZapTASow_|@ zRf<%mnYdcKgx+ViY6naF`$hfBGTZG!m_4$sbpuxD2hcP4IOZLk!9|qR$#UkJMI<8@ zw@VV_C*jw(gRC=`6)x-UFM^USepClta1ekEARf?1^Z%})|5;1_7r%ltsUtju>+zzC zZ$=>a{SozgwK0WA1%$68(bG}|)qq&cv%Zuxt~wE7@69v&=Hr!K!&7QrMh!+aG8n5<^%1elAh3jP#iW~o3 z1?z@XF0J0aGSkD6dI)((6a<$z&`Nm6>u+l=dMRmyD6Jr8In7;7ml^3c>vx`4#cpJ% zad*%&Suu7p&b)bo6HVMB$St>61lYIT;QheANs8eG34(XIzZrO|`^as@$1_*4IS$+j zV%pj<<~mh0qD~`CjBTe9Sf{RPB@B8n8H`Q41rmi1!8~nI@LuPPjMFJeb1SWO_Lb*w z1*T!RCwu}yebCMwQ0S_LVNKO&^#bf}Okbcr7v6oKfb{>;{Lp3XlIZdM8(okqQor5U z&G~f5e}FCqx6YOun@zSE+b-LvK%YrnR^ztNs-3X4-BQ$Dih;|UrU1b=h-V|$=kRZq zCn0@cjQFRxQ!W5yPfTg` zX{W^(xrw}F`sK`N`|it1`RrK=Wx%p8scs8G0r>P|&^#jJ_BCId;(HCg>ICp9ToW3h zo>&fpKH4iya%6t`!=#gM%a~kPv}X$ZaBS}`MWRrIIH!WIEKAY!7lEntFi&4Do}=uE zBRO=5UBLL0#xccvW!o8JcQG@am`~@+tqqI*=)|kbWLcQg@0eq4%YyKquKZlwtrz~q z`(Y>J5uW+CBtv7 zl(Jxz>q@P*`G?L8EXoFu=-4VcVJkEzi+wL1g_|y^ z{+LD^erx~Ruhl5#Mopvbx0=NC?F8H zi0ovX3R7O*ZsK-Ms&i||GWngoarMDiPH=+BsHT`aM*J+08^G|P%f4Y4(hZj>(6eV9 z>1JDv%T1q-@@5PTQXk^c)qOXYO5T42WNPoGv;U*<{CBa;XI268V<|!K52V4FT3Bh9 z)s?>6z|Jt1s3h-*PZGjY;XIRvnY%ZNU1n^$$B7m0_u6V}6yIvx+~dFcVL{zSBSLMJ z9@m*qkxA*L1;YZn%n8QP-&c^at(U5Q*OIN7eLj@^@#ML~4q<1edR_ZQV6m@Jy!m@1 z$gJ}exR9=NxcD?;&t66guf5ILpkucJ3Oq0_pPql_PvG!xaE|}2t64Ujl24lzrWkzk z2_NdPf{f0r9H88bXSYS1grSChO+T;V@vcqIBEG^G__H9xj)Tj8(qMi!IBeOZWXAZ; z4au{!0r5FE|2f5ybuJ=w585dS>MeNRmG4&0RPHr0`}Bz1>EXwgECf9)f#jH!KBj*vopWHaMEjZ73kFO*#FvBx-`y z<5pj5`CYey^wCwWb0f-p)h#`JL;F7Yuq#PI2{C0|=M!m()AM19tS4o7Sw%$Q?W&?= zca+m&>*E_U&rkT_=BNlolQMkuh;g3wlrOh|+`YlX#gwJb&|b40m+%M!DlO%@Kcagz zSU2Gc&b(OpJD)5q3S53p0%$HV$cVa6fYN(3%T@UJ7_2Q2@oU!RFMTOJH zZcoKk!f(WDd+N48{ZMy6KtRF`nPv@7M~aXOeR%jecO$3a@EX~1UXLNzu^ogR;eB{0Y6-1X%ce=kb@DI; z(OqFH#1bt`^N`D!|_%E&c8OpG#%?9A+`lHkAa1ZmjO*IC_x z>^Y(C^U3HDX9Fk)2*091eD8~7B^XZ-bXH`dr!_P7N}_4lGT*w%nl9R7Q6;TH*x4>P zXPntX>`C6$Pb))zGy$U38pIoBpd_x>zwitbb|ZRbo}XNh56LZ76c6u04}iE5%r4`y zm#q`ABR$Yrjv-@RuDv8d^j$=HNb(9~ma*>?(+cOo>>d3iBhJ>W4V+Ri0bIwtg_b2( zyo>E0ixe@<0Mv+;z)2%M-FXS6JRFK#a!);@UC2He#l6n>cnjN~lVVSFnBnBZ&Z|Q>=gE(yJ}9~d#QhWZVNX~bU3@m`NM_*$X5NDSWey7 zggB)*G)phR6<_ozGh6 zM|9@Zp%ZRT993}uVukV5B%Q+g!)wexU()3owuMv%;RdP@l$SXBImF`hptFm2s0E02 zfIg$IC5~6C^DGU5DYhd&9QYKZ`o8wN*?YB)w3e79)1Tm|5uT4>%9O;`x+*(J{FXgc zLEzSE$bPlTh5pcCP+-b+lJ6U9~_Fa#mPk9Zpbne)Z&+D z?+V{UC{O+|OH^hLnC)gBl5V5gXDhfkrHv{8D$^GguDI08=|HH=weEm^1T6%#==0Bq z_}{haf7Y)5Rqw%>Nrt*a24bwDd5JTC2;7s>vq?EHNYIjBIbd2iMvai6rDsEK;}e$| zV_*bWF4F7!CC`m6f`mvQ0T5DFxTNzwe}0~o?wu4g&514TpK(VLZoEKk{oxBtj=bY= z`#zd?+OCq3_c7T-OhHMpRObNBwD8<8M)a5_GbCf`K#aP5EQ`>H2Udyo+AxKvDi>5N zXiv?KB)jMEyUZeCM6;HL_~lE_noLsI&0KD9T?ys@qG0;*ETvC36PFKYoT{#>_*-?+ ztUTMsAAzNSv=#jqiW$?MmJfE3oYAJn5#kTijpUe`UhI0ttB4PS;1wZYoCF@VH&7GdAKt!)-ID}Er>KQ+) z{N3x`%HqlFCyaTaK8iuBMxCb}5l{wTOJa08UH#~8Twr~4uJM!>n*U-N&Y)W4 zbn&YTy`&ugfvMQy4|}hZ*svuhbv_<%H7!uaN$F?4%X!zf;rH=g@zT@nNIdRJZ$m zP4w?Omux0zZQ-c|SrP^iTJdSgmqXp|4{luDNpdMxx+81%B#zJcPhk`!N}GxbF!svk zC0dIcf(c3!$LpZ)*B*XxD0t-|{HMcaVqZG(<$+1FUtsmiKnu@7cK#LYmW?~2OYL~e zRgtlDGw#Nd)--JuCBM(8*EK%^@5r#P$4ey#l2xT5)bVOa)_2vuo5P zHE@9}LBf6V$O4q7H8FcBcX=h1l^x)#B7GO$mo|eFzTnSi_qV-<77S{8-3gklbziZ{U%Z39eb#bb`xC&&a;E2BJ_ifPJ$!`O zFK$58Y2))DeEMd(B?ET^;a5IrmJehz~qGhu&U zF2j8~TZ}C{3I6RAezyZ}Veh}(l+eHc^|Pp+!{zm`?DXVUB5AfNit#Rn<3$>e+{r&u zf9`YHpc^Px7v44_pZd1E!PR#ax+-Y{tViP{JS5%2XIJh}sg3D)nBK^1E^64wBJvOm z6t&yg@cPxxFHQ#P_twG!rO&Js-ro+qwD#@`LEnh}Kf0#6k{M}IiOUOih3ebdnMu2y z2pH(R=j0OpWkbVwz`>&^YuOr>GT#-sE=3Zx^a&=h2!z8ljzqMx#&p{-)P~-;Nwf7T z*PrdXeX3O{z+-;JUfPut7&SxZ)n)E6c{=$9E~02G1HA?R?C;08zfi6_=%}?xV2o^M zbq*?)tTdy#t^M_Yx-z0y;G0)7~}k(isLx1oAj#nVY}=x%R#})%w>3 z%U1K`Mt?Tv2NA{DnZ#2sKMmgS^XXV{j9lMcD>H1enHU>IbN{RBInHFrGC3}L);9Wem-7-aTP-tOMGl}EuI1*TKC6hbw3 zr(?|?;SA0404k+wo0XZJ?)Siz)G>7~+O>ZR2ukg;O$+1r6CY@5HNWhPGs-!)3zH@= zErsg!Ti>o3^|A1pmZ1;{iaM1(DeZFqWvqc+O?I{xO}S@!EVjeO_C$IL{taeG8t-a%_5ky6C&MU^?P%r9tTBpBF*n#RpQh@bZEal=X8u+Z+cZtQcr9%jkL((w zO%-*HJ#YAMU@00J-z?M9K|iN2jp5ccnRTa;yHy5GBYq-@IOWn~`xauV*xjTn@a9Y` ze}N{1NVm@&q&M%XIwjFP&YKnOn zPinw?Q~}+sHeDM&2FPsgi#^(BJo z1~Rk-)RHPCXr!GyK#xW|vovp+e3b<{)pdtGRqR*MXzTl8=ELhxt@0$8h@D=3)5yFw z8y(WTveJ>WKj;a>rY}b-voBoiznyxx1vwl zg1xa{DYKoxCiP42yf3e3>^d?SwPV_>`JPVC-}fe(BYZCB`8n+ndc#Vqdx2SJ z$&h<1Xr}CWwC^G7q=Y1)47`b?CH2FOyP`vbd+%c(e4~Hc#lvs&DkuINv6R;>N*TcU zFn(4aQ?>q1bVPA1`lWIQY?mNicDrh6=bo8F7Xu>MdhZ6>auCu+y1)dv9BMJo1~sqhTOa({D+n?kZeNQVaXNm$||# z<1s`fU`qv(n#rWd%B(8D$eHF|CM(TtJ`oqHw)TTe;tL;6+H#cqpCk+DfBWm>!+4X^ zEh~o}WDMyp?j(N-&W4%aTj2}NOK06SWIxGgv?0b25T6{afer1ipHpWWPCTg*5ctk} z3|@eiz$1ky;l^EC)=U>t1lk%bW!U8Lz;YvwVnssMh(i6Mux%FnR+is`5~O56J+z?v zIItSJjE-mRnkS!9RN*#tv3Thi2?QmDzZG6{kIbv9F7z#MS{Ycpk7;M#QhvlHkbr!) zAVqdE$c{GbuQ_g$UwAz3cGu0GxkvE@JKOUs!J&eG`?jOl7=rzXF)r(IA28!MOcbcxYVhN% zIAm@JVPAH&?}i<5Oug|rITgPGH|6sT zep;Lf2;Z2K`Gb0cSj@Mk%ovA##w8Z>?H)$5bkPlZ4?x2pRUsFPkl1-qtks;cW7hDH zQE!iLi`<`gL3Y{TV|$~T`qny^;Ig6&na7oX7vHmEAWe~>5i9Zq8Y`u8xH&C?kyv@B zBL|IvU5GB4^(sJP=gI1(mdFHXnU^F}5|g~G7?FySFP4F2#S4zG*N(WkUZWJblRo}^ z>Q$c)-tn&fP!45?Gm!V@azCn!zJgJLn)HX+(^3xXClv0j{U!DB6QPML zEGBRhFer!?^p5ME!%lMohe5h;*_^EQ-m-{}A{T9Q=h3$C8ge#rxfOOhf<%k?2z6~Y z-jK+Bqy$X|g=FK<{iv0ZShMqa_GcoGZ`qHjO7GfW4fRDh7h=!*R*SL~9waj;WIVHx z$TctwI*bmIUqogc#tV_K=5nV`KNbF$TW-|qI*6|xRN!$Ca<>kNw>($Y!a>$+ zeZa?5ig#A&uNunE{&2Lk_3XQ`^Va)u*xC1!vk44(>49mt3dcG^*e#GZ(kAbA`v+o2 zt1+<@M?Rv`kn`@j9zrxfi7US62JK*t4F!tf%Kk@p&zf0)$ddUXs;51LE>$W_U7JFg2YCsnG@Vo>p; z{g@1QVN(z&V@!RnHwOPfYsaRtU3BSg&1{SUNZ$rd7`)L=g8Gs#!80*Qdguai`F z-hnlKBHz)&&1mGn@S=g8?@vBMFORnLV2FK-i)eK7#Mp*Mo$m^9+$!MFnHeh%P11?3 zM{G_01v&ym{b>>dhq{=7*$;zv4ZR;>F#pDktd}m>17MJ=AbtyFR77x6D+f`(YFU#%6P7nCoun-Y@dOaB5* znx|DwrM&yc_A;m}HL^saxa+5(Dkco72lV?LbXKVm5mY zhl6|+81JZ}3x+}7P`cJTBzo-24@(R6*)>jA)cNQgz+7gg@6dRR+X%OEZBec~rjcRb zhoq*4=C8pO-eWXOOsAhgDEziol~jWzPulnYmM>BoGU0ff2A|K60rn<2x>qr` z?T>}^7V!@(!cB0HJr|s~^6j0e+)G$X=55{TOOBc${nUKmS(Zh(6z(t3n^xOZe583( zb8LM`;f5_#-3ro)h{uH7n{t@A`k-!7ahG0uRyQ~@QiU6ky8Z=vp2y?jLHFV1`mA)2)N?lF_aXTVIVsdnHo`aL zxNg6e(mwN6o3#jO+OaroHME&~IkDQ6n|@G%l03fzh`s*z`ToE2=akb*jH#A6eY&qj z0%5EpKP+Dyv3awV_#AvK+7y1=5~hRS52U@tQJsYy4&ooA{xX%|4f|^Q8pC$%+LX;n z+KSjk?&85-WyGdPp;xGlO-maGqMTa4mo3?W*U?{qJ4!%+!1wT-!hA234dfJN(kzzU z5;1Eep#X;IyD*aH_g?`RO_-ujxw8WIXE--!apdL)ar|G9L!&t*^7uOH2HEFqK`Rep# z&qrjzvaOe#$UF{V+ohz6piynu7w@EirHLAtfA#!s`~6IissG~}fXgsw7as=Y-Sdss zl|2r9!{gwD$~djmBsRY&O5r;aA>rpR(Yj*GU#FIX$tvUesm$tr&lUpt4sCc4K5s=| z*Ue1xcsHISb7q%(oStw{v61ciqrs4&9ib_zJOYp@bQO>WmSjSNstAvDe8^8mUY-8= zuY0(k(6gSw*}`O|sgzJ2g4`KCq3A1Gf;4N2^PI7^<4mZsL$rZdb+~C-3d2rqRwmciG|?=)oWP8EFonRr zb)Xpti(1~3-GT3`kSeBMpcRQuMrRSlx4UGQHnZ9Og2Z9@ACRDgq?#P&o2CTuzo0-9 zLJ9gVeL$0%EkVKKyg80zuzx;@Fb_l~x7n?-#JW5o(N?M?dKM~Mw_vF*ayyoBfkA0n z^hw<<+?%l+j@(fAFQ_|S0FW@9BRiT6NkEr(Ov^fTOlC1QE?$wDsZ$n-|Hdnr04?l?Zs;F*p8#-R*U(G-OU}QT=Dc(i-F9oGJuPj0}jK_ zp=~`fVkr3>wu9mY#{K(M&IiTn)PA9hrmzLBHy_JkJBY% zK)ss7!m!qE>FN>qR6Syl==H}nEak%k%UP@4CDntib(Ko>U?AxWx&|0N9 z#MGavH#jC&3D-~RYbFeH*z#aPsMc&j=H1^HoY$_LID7fA_)#1MGG~;y2N1X7%suS0 zu3Vi=45-kJ0CHEHCtXl3WTD9(xnhM*p{_%uFet?C6!P516F$1-|IAc^r$MUM2hsAL zcHje-KNtSth}bbYpatsS5bl-H7k>Q{1Tp9hz+VA2^V003Ps|@T=C>hq=i**ttCTcs z%XbvN|3048%g*rIphH{F-ncortz)|R=w0*vt15S?!2*Uu4|1|Y7L1Znx@u$W+%rx{ zTaNMFExo>10zRXj)~5ODZSPu*MJPG|@I?BDCd%+LDPRR4lwN=t0k%PUsX^>QS`n6| zzv8xKmK%k=Q$6Wg0~M!|yE9TE*V#cB13gHoD-(;(4R{iT@TD}CH1B}-e|;?5pmTrq)B41X#Didt zRE(H38YNsz z9!JZ<&xuY=DgTO$m>O%see*@@QZ)PKP}wJju8vQ99@~E_@D$MR)xz5_0F)EK{}^U6 zk7Fi=ejAzbsf`eQx>gMaGOL^&YhKu<+R4Po_HFOta?wome$D9^!Jo#%`I^zG0<40t z%)2&2qH~S@DWaF0AHFD#8y7is+&E+)@zPY{hIFSN;Fuly?AVklP)T-6z@I^Z{iL4e zoH6GxuaVU66P?HQWk%9j59He$3+CXg50LdZ#cn$%z6X|ki&(}+HDpZlsNc$*{4tAFX#*3bnAf2&k`+=JHmX?fHp_Zza&zF;(SRM36HgbFtS4G~YKialT#tpkP;1rE zyY;iO@Sv2~jdpJZzW^7hV^2yr;22_KrQ~B%Auf@55iO*}vsp@^B5ydAKx~ekwoRFiApT(=Uf3 z6~2lYGuTHDRfu>)_>ct4(<`J0W=Khha#gjCmK94ay~BkurUl9_kMlvqtqQ)_$qy3H zvJ`V2SH}hPYII;qjC=)~*~W9fTnOWpZekp)!NxXf_181be%|W|+PEKnS=@GYqaUON zOkhUHYWM;q#vFi=aJdy#i6)BTAYH5j#cV&5_F)U2M=o`tv|_oC$B9`v)AF!vtrqWgr2l*EAwNMoJLt42kst4Q$S1BB^_ z_`sqeG@cDa)1$q4f?vl+5Kkb8?iD7+2Qsq1ZuluVRkb+!BY<%#iR)yLG`=7Z+L~s} zY`pqaxu(g=9PN%CnUc){aytY9PY)VNR>W@S$Y`Br?VE>v!1GcK!BO?>U)F3+pPia~ z!#EvB%^Afd<&{i(pG@12kCg;AE2*RYu>6q0TbZW!{>7HuARO6v=5Qhy+XSa#6|?eJ zGt_Q!8KqOs9X$aC9IaSU^d-+&r3sqXyj7#(B|xDe{rmz1qdUW&hwJjX6%U)=3TA3(4(*({q#VZD#uY4oxZ z3QJH0z`;8K#;MCm@uw=0wx`%juBkSAHqADeZ0+H0(lT@}PN2+5DjCG*-WmJdw@?A^ zj&6tdphvKR6|fkbTOKm-0{l4VX7YsvF@dGXEtneN*obN!b&%+;aT|N+83XAprjKQQ z9comabj)xE_)bcq&y+f$N2hT7U6XjBB>%|Hk6{P#ip0FRsM?MD1-&{BXQ9WcTGo^v zvhqB~OXOLJipY)aldntWWlS-rwX?@?%n#j&1Rxcxv6=P)%{O5$MU^@#H*MKG{U}ez zDgVPnN>o9DOSHS=eG*{SGMofq$GIXRpc8 zXat=osy?hOP8uQ<7@x;l`ATtaw!SC_}5v`uq^e}YgY7Ba7L4+2JN>8uaq zZl`JpUbT7o!%rXg4gV0DyglViMDny>xp;6Wx2aV_UjZb^Y?Pn6l+ML+s_YlDJY=%v zuzajN;-lS3NGmWtTRXbSSUBUY-*XQsbSK7vl%DnFTE0ZTq6;;^u_g5%dBDFPDQu!V zF9WvN+s`XAu!r{RWCT%JB5@hig^PrG!iXMs$pL*IkmgwP!C>B}L)4w{35WsgHhuUY z)e9ir?G@z*C4?2d*3nnTb>Ac@_ez6O?Ilz4Q^v-UOk7jF@|Q{^|9$HE?>;-Zy+7FH zE8}Ev-o*7@XX}@;WkY?lG(AY}U(mPY4reU_nlJMD(1Ka0PuIyCYQB46T&MQt`8GAb z{M={lspeFF5ygTRk==#?8dybbk$FyNo2}c=v2NkqO2%Y^HCQ3^l&-iZp1WSwx5O*$ zgZc?%*CN1#0<32iVQn45&{>^PXr=AL2L4oE`&ZH9)f;Q$K1v%-zd~hq;qy!D8?*Qq zRW|UiPL_ph3>Ge8N=k%tKt>2Q`%1qrN@>ns5ei;@`7a5yz1&YQHE=us37Z$7nH+t~U(YQ=7Zb$*4gA_y zu8(GqPi9~1@w1Z`4hB8eVP*oMq6{A)3tNfUXw~sVe)~%Jvrd8N8=K0_N5Zx`AnDS) zSwdt5Mu?I$Z9FJ970__A9TUa6fVEI|YIzsnLOwo&EM02FpGCL&y8GNHIvv&Nw9cNE zDFAs&y+T?So%7F&*fQOW!X`! z@gld*CU&(@iY)b~yWiUZ)gre$eE4;kjNQqQ(Qe2&jGMf88$Z88RaEH>Y^dxxwkv;} zlU-OSqu;>^P)@MrIUoff5nxXx+730UP?f$`DObfm=~C+bUCNjIClf?bz6*qoNPCUm z8h_8xoAR|ak2FOA+`_VXM(Z^`wcaoF+Wy_6jL^UE60AmKHSHE20>p>gUB zlIqmkFkfzVN1m}`bj4xOyyYomWQ$;aExMu5$)VQx&O>CUJ#(sn%VL?E) zGRY%G8|FTex%uArNmNkk4|az2kT?)EC1AYD8-b33z-Jd*}kPFPwnx; z@@v|SlN&R|f=_c+zH`W{c7gX2BjK78k1H`YTHgh)io-3=oH8R?3w*C!Z ze`7Gfknrh?Udu(6LIqYv#^o!7*-MI=(vAtcd^=#@C0Ow^4@xADveuH}z+4J=YvN@^ zKN(p7m#l(3JzH?ls>t7%;xF|cE;fx&JcucrZNIF&`45Gmba@}h8mK6E4qa1_yqmE~ z;4^Iy-$x9Jji42mE2{)#Qe$I=joU%!Hz;VuGboeS+09eP4RJe`A?c4OqcW@w>BiUl zo?xs_R<7$%++?Mpv8}|c6@qcaQe28T)s}Iay`5;0my3)(YQ0^NNu0fiD*kjkrFy5Y zSy^NxNA!QZCeRWrc6PIyQ}E z;z9A<8!zo!eFaW^7GN+Uk!|_UfA5$M0a39O{LG|TbGGWxleGq2IQ;%&0PTGIT>PTN z<&Y<(a-(aIHhfIBAesJJ0bBYzzed31+HA%$d=YYn-o7o=Fa;s=sBpD~`-hhW33I(- zAphPkfpB`KE!XZP6(Ph4lEo_*Z_mtdr%>Yd@%-qYkkeEsQ_rA~Bjuj$g9m++5C>B1 z98xls)ha*btF6s%fU@F2v70ld+Rd2DI>)xEw%4kJ1wGKTr5BxW_BuG*d*#~=eQMDX z{x`(7u90H0uNC&^UiC}y?B^aJ^ohnepDbfZ;|~4LjN3MI6`#LRQs!h41=qZlnMB8v zWZ&Sb@m`i=scUVu6-)8jl78s13+|2=t@vJa9X?Cf*o4np@*pv`q^Zve?~7Ls&IWU< z4SxFwb%`N;4C~CzcWeGQ!_$75ziLOc;s|^!Mm;}3)tV`?JmYP9xv#`UVMkmc==_2! zsU7_+DH?wb>JCfH2G^6guz9P*;f9ZSK8^N{F{du819{oY39bSgO-Hw!PTUWznXIa? z8m#D%x_t|9q8R*xX%G$@rnPS$w1(tsCM9BY3c7EeGgWF{`XKsx z&!bh5cmysp{KtCDbjR39XUN#z_%A3R)syj0ibVRa_hYdG`=@V+Sbh*GT7mqwu^PtC zxvihau77V4ocB6>%rL%-v%gJyPnQ{gJC|V*z4`}j)wf{Gx>a^>u?`^ivT4hb)~B41 zLCcf0??U-fI$FR`dR6up8TSf5lk4y~rbW;tEnDH?bn?MnyWw}cOL62rB4$>QdW$sV zg@C4gc6d1cb@|x_p#g;Uuy$ri)RrniS~}GX?!DJs9J~whd3clg;H3XuITmja;t7_E zsuVo0$Tvno544#0HJ#PI|5%x_<231ugupUd0hO5QZ-c7erDtrfKjOD~Y^S@+a3oL4 zn~@6F=JP-(4b0RIr$Vzg?=Xe08iq_*x4rm$1{C=kbPxQa2EbI+`>Fo3S-@zZF4`!C zAzf1Jo9N8wU41EmCJ~+G6Cb~S0t^!F^yWPU5+J$LUuH+1z^mXr@$n(pHauT%gomJN z@pFgk$UX#tx{s@cdc&O`?96225qZpBnUj$+$!}x60){87LwT?LZb#^|eA0adY8}in zwbb#F1{GzBzt}6{_lfsE2R-Qj67jM8M(QSS@|H>*?=jFzmf$%S&5}W$-v|dT1E;7( zxe|i&jco0b_?A8{Lp8HftZ2Ym+-j+N5_@pw13uSV>yu$Q;1q!OmeZ(N_pQ8)6qWGD zc0t)G%ui2%u*iwBcF8-opp;VxbDKq|RAqgiX%GE6+3hn|bnERh{$s#w$ft6-OL;x| zk|etN4#08FIhE01|Fxm6%>9|x=aR7w*2EW``D%7w{2pyG>?&1JtoOC1un(*Mg76+x z=@Vxq-+a}05P-FT`D2)Hs&|F2Z;~#wtg4 zEF;^{x)t`+enFwLe{Ki4u3|bGYkn1%6wBq7e~&sJalXQu8FZq44M-;p_n7|+0y#K4 zwve10#G;YExg*p&kLDUwZ|HY*Q9p;3B%oSV=OGnak&4=Gq|E(k(+bC|<40y}2Tfv? zPzINNqzkjR#)&J4d)1qO&w!?rfqea-zP2yNC(~Nv{43aNU;`_=DZo~1vmVw^wxOkv6oDP|z+$$hO?lqZy)pcuAW!ISk=SD})YlICrm7 zsmI$It8II#wm|Y-K@R`|)GVpzsl2i}L0-`l6MY4I5t%gfp;O{$@8f`;2v^KJjL*}X z-+0uw3!<4&T_3=~dKyG@ir@?SY2@S5FO`j5(X@H%)pwRSjtwAkfZM z$zi;3aU%n-H0Mph2d^+u$O>MD^{VM|Tsu5ottuIodZJZm_%?RPj$sZ4LH=xuuW}@F z?g2#UCym2Ut7;Zir&2r0-TWW6FbDLwyaBj<)O_WfRcb{5G#u z)$)!_P#3@7ke^cxg0zVHl5pMKNiAuG4j>wrFW~f)^D12KkC6c|?2mflB1+3c^R0cl zz2?OZ@Iut7NL)Ad=vJ8SD~6-1WR?!hi9PcR%d5D2Aa+@#CQRuf9;)r8@Y;XQai#oj zg6&0vKZ=#lY}KjE&jzyJE`~8{)1H0>TEOAxv`Og5BO-_V1E+@+79S>J%m zJwsl}PX{PM(&0W}B4IY+WqGQ(HiFhth#kahOLqccJENF$P&l#z!MtTi3d-{L+4-DU z>Ly#|H8cNicOUmkE@e;0ed-)mG0^YJW~hCb)ZQ15oI-usX6=9*LG_Q$S$<%-5C*lS zvmw1(TQFSZ?-g1k7}r;~uOyv&v9MUDmnSi=Qv{eF&n|5s=B7E8%e*px<$nn*ugd2TIsoGM)g@x0=uxkoKZBNw(Nvmk3PIzKb`UK=E^;~?e~ z3idwyGQK}lAxlr0O)aFQU&MjOjr7OTa-1@bFnh}c|2!*o*CHF1fss1h$lb)O{A3gwCHdb&+q*luF2&`{&64_KaXRlM1)9a7m2*Cs2dO}rq&&NoI@~wqlv+s20gp_axXh)j zZ`Br|z6E>#l0Jgr&5PwOMTiXDt4i0PDmjE0ZA6ioe`Blej!i8M?_(r$z?IqvV04LW z9NXBV2@-dZgg4}fpSwCme|+OH-%fsgS~Yc|o{Lq&!D1$V z6>nNCM7e&Yy$y)aEoV5I3_fWWwC&g<@WjvH{IXF4V2opl?zs$WmWtJ8azA_Er%b$| zYj*&8QVMOwS9-)f+87jZY^}8G>+e-K=SV+fPadh0RUC&JswM9CoS3mp;$yyzE%jua zHxD)(R*}D94z>H9-n*zAounUWKfD5kG)fqdmD}eXV{V%3+)-P1p=sdMa+q8yRd^CFm8lgo}@g&S*qHvrimqa$nI^j!!bagoi4C14BKXV zvB3yxN^u#PdRFviqa^pKI}n~K4MgFx(Nrixv%t8KgLg_Oh5#e;a2@gCVWV$%ChdiU$1 zXPn$iUSvq-kdk|^IU^^Chl3KJ4 z{?q4ufd8G>kwJvC$2*H`euT?k7qAr>vsx0+onX|1JVp*q&u+Z>35`RPze=^PR{c@B zL>Q^TD9&8(&q{;OrpA=sQ9iVjKX#)kj%Z_MiyV9SZaKb}Q$FORx;BCj*I?PBLEA*< zp9p_$`}>cRV!pDRv|?GsL{$JNpXQx9g~(5yK}t%09;EO{Rh=uHVt?Zi?iQ^tqyD2z zg=cn?_-`x(^Q$fckLo!~)vJa#T-i?!su_0v15%ui z<1oRqvnN3};M-`FE~_Wwn}ecwh3eKA#6+&N2j~f3ZQ3G=x6ri)yIsVpW6Xy7XPOpH z-U~SmZ^a{~qXmPqf)Vprj&>h8g>8lF5~rPZs$DBt)?gaQETa)^r6S7@t7WPcJ>_p@ z>{!IZnvSeLA+umZ<-28#qpGs;cRS9o)VL>r4@}xY52{KeHNFzF^q4etozb~j7V)$P zG($C()#UX*Z2Ba}R{tB9i@ZUEkp^xHco+@K0E?UwIeCxvCh%x9X~TDL&@^$A^{^CC{Mi1LQAjvle-QoI{VDR_r9sJ{RRau3BJ1Ht;eW2_cT1sWM2u zk6AWx&Nb&BO(YyW!D)~^HnJ|PaWsndcV{Bi!Q%I^Bp_c%JvU5uiPX38ezxevKw!_A zIbiAV7`=tQER9>+Z=^V#zsNt7?`z;ae`L1=bj|y|N%%)^9{yUaAXUcA1>HLH)Px}v zNE=F?Gk-VZwFp_;WVfw<_cCKN;iiY`VU-~$5W}x+$P%x6eoa)Y(z$HP ziT`H8naj-PkN+X`1WhwiE&qvQh|Sb(Kxb_rmY88yI`G)sFsM-lo)|FuN>{MDu4<@z zRMfgn*heDi4N!IHa>LNddXrDy;V0yKT043D!%PS(_9|A4&0R;kMN^Pr-*S2PQQNZj zA8M*zYCmcu6!z~HuSzqH(JxW`N3}zJb9z1z$GHnEQp>M{r>-0w3mz>s0Sew$AsiFn zrC)65rhQqa%ZGA<$w=(d1}tmW>K}92Y|Z|93|RpIYbA4gewATm+fXp7I$U!xG5q)B z^LFL$oirMmx+(+o`a7-kD}yL7Nzr1of?1xaB6~|g@lC46vIdTQ7=t+9c>P!Xh1I;M zl%;b%A=|PGCV>cBN7%Qn&r=PJN`F+=ZMJ)5UV}mrh+|Lh&V|0&g245&R!T><&w=+H zaq$dA=j}1KAGD=W1Gw)$llRB0&qA8NZSC=k0l1$Rt@2IiG_x9XZ5b1VLI65|bSR>L z&@(d@u<;n$lI45seRk*q55;=ELW=A9%u5|4AGxeB$v?dbngsmkvis>|9c&!lt;E2w z47?97hz)}xMOwA(mWmk4xu+W6l5y=AX7E^&V$6~AP=?^E4`zwaA8Cbe$}YNCp6q7? z2G0LZH2NR)xuI&`h=Q5zdm*Y^`-^HMdW@Xs$f?v=qDnKieZmdkDQT z<@N&1ecdKGU>;xt_&<$k{yTkL`0(D*(J#*&7N4z+ICW79fEfIX_s%R zxSWZK-eipGtM1D#%3XX}hM=Hy{240pz*-!cON|a>Sro;a(k_jtvX5gTGBlrGy(LNX z${M+cz8AEI`wC>35ll1@#(Bv-2)$5nQl|6|TuLGW8*ss)|{+a<0|C)Jcl`fY;8Ro z8#o6B!&b^_TI$JsC;M5h8fr>U+24}xud8Fa190>8o%hp79&@$@@clR1QlE++y4`$P zHlbt0%doU-I~|9ToU>%V`4t&ySpVy7FHc{>C*P0oGhuA9uvQnrQL5SF5h8QS)6X~Y zPvz(3j7I97VZx?)-4oPF?SmfQ^B4gkc(-RMp<|j;+jVA~w}H%@CYjIGY;aiz!|l}g z_WrZaQw8Z*xcqQ;3@fi$P1dsXi3+}DqHi-K_Fy2ErzMya*>A>kiGC*#4MN@0_zQ{) zvJQXuavBH#wl{Pdc{1K0ZiBUGe9<1jh)49nS;c+O_&UkKl7%CH%F#fk=KTs zl2Z%WSc5pv{J%`n>bBUaV&sF^Cod|T#jmH&4O+kQ149d38Yz6_D?fVSb;;nHFI%D} z%aEXlfVNrrKT77ETity667N7-fcD#YKb{mkcLVoG0fD;o>BU_)7vsCkq7$~@cpwY` z#|GF;JdZJG`1Lx=TYG@dR=2I61^Tb<(sA&~IL+ZmOXLdhmpKy;}PPZAGl$wfrDAP*%@&shj%c5Usa`;0{j4`j&}WlgFhGzwKbYjA9}BRO=`Wn-k*tvCJkgxz>=kJwgSt@0;2 z=ap-T;J&(*rK?1=KT?_n)pyB)5b-H+?GlYcpDuPTa5rQ(6vHsz`&zg7 zQPLG;E*#VNR2R3qtQezK03feFJKzj%dw+5C8hHwre>eKRH;vz^OCnN%CYb( zV?=I)$v@At6oiyy-uKCuR4Ubh<{P1&FA`C7E>|1X^YF^y(3FL>&;>{9Ekj0JAcLiW zvd^72gjs9C_C5ns_rD-s|&VtOL` zy487iYE-Z-lu=jOxlIDbHr1Z;&P?bM{Wim5x!oso693#2we3E|m<8jxTk94#KvdZt zg`8C4qS@1oM=4)#h&~q<1jWT2o6SJhcSy(W(`@o6gQDi3gKyXE<2pgT6GwJk(`TM! zIkOW&8dDw!I66!S%yT^U57!gk`)AAMn*h2ZsWzRUF`r_zwJ=Xt+ z_jdyRUvv-f?H>d>^xj`kX*_jp?`j)lTVD~neg?BE2%=UDLl>k1|AL&ce?iw&`%!=? zXKKm^%qYMf6L+G2{tG&gZ_GFZ5{UlsRHGTRLs<4ic+Bp= z>q?+MV=W)soM;rp(_ZV!>2o7hK9ve!PNmo#0=YeeY-wL+s&WlkkeHR{=C*jKU*^aT zQ2Ll=e8;8qhXcn$uR8XZsw{i>VZ9XCK1eZ&VKhM$LWj#~GUU1H#WFJ2Yk$|v>P$l$ zuIrQFS?B5X22vBsf)bt1e?3vHQ|=%vP{yQ*+8)|>Y>1S)PKhOD@6Qm}O+>1QC8gIA zn;7aMx8k-T6e)#RZ*AF*&NymB|9U1 zCLG85#2h<$Q6GMjjMg#_ui-5*-bLz*lyk)d|Ja*q-OVpnn=MrjqyE*AK`b%NI{1aW z>A#>+Zfa&Nj3PZvMSEhl{({y&*5D{oRn%7ihIupxO|t{UwoF2QLCHN}+FuauRX